diff --git a/Projects/Server.Tests/AssertExtensions.cs b/Projects/Server.Tests/AssertExtensions.cs index 81f76645c..42e86b7b3 100644 --- a/Projects/Server.Tests/AssertExtensions.cs +++ b/Projects/Server.Tests/AssertExtensions.cs @@ -1,24 +1,24 @@ -using System; -using System.Text; - -namespace Server.Tests -{ - public static partial class AssertThat - { - public static string SpanToString(ReadOnlySpan bytes) - { - StringBuilder builder = new StringBuilder(); - builder.Append("["); - builder.AppendJoin(", ", bytes.ToArray()); - builder.Append("]"); - - return builder.ToString(); - } - - public static void Equal(ReadOnlySpan actual, ReadOnlySpan expected) => - Xunit.Assert.True( - expected.SequenceEqual(actual), - $"Expected does not match actual.\nExpected:\t{SpanToString(expected)}\nActual:\t\t{SpanToString(actual)}" - ); - } -} +using System; +using System.Text; + +namespace Server.Tests +{ + public static class AssertThat + { + public static string SpanToString(ReadOnlySpan bytes) + { + var builder = new StringBuilder(); + builder.Append("["); + builder.AppendJoin(", ", bytes.ToArray()); + builder.Append("]"); + + return builder.ToString(); + } + + public static void Equal(ReadOnlySpan actual, ReadOnlySpan expected) => + Xunit.Assert.True( + expected.SequenceEqual(actual), + $"Expected does not match actual.\nExpected:\t{SpanToString(expected)}\nActual:\t\t{SpanToString(actual)}" + ); + } +} diff --git a/Projects/Server.Tests/Network/Packets/AttributeNormalizerUtilities.cs b/Projects/Server.Tests/Network/Packets/AttributeNormalizerUtilities.cs index 4cb7fd077..f0b3f3fba 100644 --- a/Projects/Server.Tests/Network/Packets/AttributeNormalizerUtilities.cs +++ b/Projects/Server.Tests/Network/Packets/AttributeNormalizerUtilities.cs @@ -1,39 +1,39 @@ -using System; -using System.Buffers; -using Server.Network; - -namespace Server.Tests.Network.Packets -{ - public static class AttributeNormalizerUtilities - { - public static void WriteAttribute(this Span data, ref int pos, int cur, int max, bool normalize) - { - if (normalize && AttributeNormalizer.Enabled && max != 0) - { - int maximum = AttributeNormalizer.Maximum; - - data.Write(ref pos, (ushort)maximum); - data.Write(ref pos, (ushort)(cur * maximum / max)); - return; - } - - data.Write(ref pos, (ushort)max); - data.Write(ref pos, (ushort)cur); - } - - public static void WriteReverseAttribute(this Span data, ref int pos, int cur, int max, bool normalize) - { - if (normalize && AttributeNormalizer.Enabled && max != 0) - { - int maximum = AttributeNormalizer.Maximum; - - data.Write(ref pos, (ushort)(cur * maximum / max)); - data.Write(ref pos, (ushort)maximum); - return; - } - - data.Write(ref pos, (ushort)cur); - data.Write(ref pos, (ushort)max); - } - } -} +using System; +using System.Buffers; +using Server.Network; + +namespace Server.Tests.Network.Packets +{ + public static class AttributeNormalizerUtilities + { + public static void WriteAttribute(this Span data, ref int pos, int cur, int max, bool normalize) + { + if (normalize && AttributeNormalizer.Enabled && max != 0) + { + var maximum = AttributeNormalizer.Maximum; + + data.Write(ref pos, (ushort)maximum); + data.Write(ref pos, (ushort)(cur * maximum / max)); + return; + } + + data.Write(ref pos, (ushort)max); + data.Write(ref pos, (ushort)cur); + } + + public static void WriteReverseAttribute(this Span data, ref int pos, int cur, int max, bool normalize) + { + if (normalize && AttributeNormalizer.Enabled && max != 0) + { + var maximum = AttributeNormalizer.Maximum; + + data.Write(ref pos, (ushort)(cur * maximum / max)); + data.Write(ref pos, (ushort)maximum); + return; + } + + data.Write(ref pos, (ushort)cur); + data.Write(ref pos, (ushort)max); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/GumpUtilities.cs b/Projects/Server.Tests/Network/Packets/GumpUtilities.cs index 07ab2e959..0448c5f75 100644 --- a/Projects/Server.Tests/Network/Packets/GumpUtilities.cs +++ b/Projects/Server.Tests/Network/Packets/GumpUtilities.cs @@ -1,44 +1,43 @@ -using System; -using System.Buffers; -using System.IO.Compression; -using System.Text; - -namespace Server.Tests.Network.Packets -{ - public static class GumpUtilities - { - public static readonly byte[] NoMoveBuffer = Encoding.ASCII.GetBytes("{ nomove }"); - public static readonly byte[] NoCloseBuffer = Encoding.ASCII.GetBytes("{ noclose }"); - public static readonly byte[] NoDisposeBuffer = Encoding.ASCII.GetBytes("{ nodispose }"); - public static readonly byte[] NoResizeBuffer = Encoding.ASCII.GetBytes("{ noresize }"); - - public const string NoMove = "{ nomove }"; - public const string NoClose = "{ noclose }"; - public const string NoDispose = "{ nodispose }"; - public const string NoResize = "{ noresize }"; - - public static void WritePacked(this Span dest, ref int pos, ReadOnlySpan source) - { - int length = source.Length; - - if (length == 0) - { -#if NO_LOCAL_INIT - dest.Write(ref pos, 0); -#else - pos += 4; -#endif - return; - } - - ulong packLength = (ulong)dest.Length - 8; - - ZlibError ce = Zlib.Pack(dest.Slice(pos + 8), ref packLength, source, ZlibQuality.Default); - if (ce != ZlibError.Okay) Console.WriteLine("ZLib error: {0} (#{1})", ce, (int)ce); - - dest.Write(ref pos, (int)(4 + packLength)); - dest.Write(ref pos, length); - pos += (int)packLength; - } - } -} +using System; +using System.Buffers; +using System.IO.Compression; +using System.Text; + +namespace Server.Tests.Network.Packets +{ + public static class GumpUtilities + { + public const string NoMove = "{ nomove }"; + public const string NoClose = "{ noclose }"; + public const string NoDispose = "{ nodispose }"; + public const string NoResize = "{ noresize }"; + public static readonly byte[] NoMoveBuffer = Encoding.ASCII.GetBytes("{ nomove }"); + public static readonly byte[] NoCloseBuffer = Encoding.ASCII.GetBytes("{ noclose }"); + public static readonly byte[] NoDisposeBuffer = Encoding.ASCII.GetBytes("{ nodispose }"); + public static readonly byte[] NoResizeBuffer = Encoding.ASCII.GetBytes("{ noresize }"); + + public static void WritePacked(this Span dest, ref int pos, ReadOnlySpan source) + { + var length = source.Length; + + if (length == 0) + { +#if NO_LOCAL_INIT + dest.Write(ref pos, 0); +#else + pos += 4; +#endif + return; + } + + var packLength = (ulong)dest.Length - 8; + + ZlibError ce = Zlib.Pack(dest.Slice(pos + 8), ref packLength, source, ZlibQuality.Default); + if (ce != ZlibError.Okay) Console.WriteLine("ZLib error: {0} (#{1})", ce, (int)ce); + + dest.Write(ref pos, (int)(4 + packLength)); + dest.Write(ref pos, length); + pos += (int)packLength; + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/AccountPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/AccountPacketTests.cs index 9148ceb0d..e7804e786 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/AccountPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/AccountPacketTests.cs @@ -1,625 +1,627 @@ -using System; -using System.Buffers; -using System.Collections.Generic; -using System.IO.Pipelines; -using System.Linq; -using System.Net; -using Microsoft.AspNetCore.Connections; -using Microsoft.AspNetCore.Http.Features; -using Server.Accounting; -using Server.Network; -using Xunit; - -namespace Server.Tests.Network.Packets -{ - public class AccountPacketTests : IClassFixture - { - internal class TestAccount : IAccount, IComparable - { - public int TotalGold { get; private set; } - public int TotalPlat { get; private set; } - - public bool DepositGold(int amount) - { - TotalGold += amount; - return true; - } - - public bool DepositPlat(int amount) - { - TotalPlat += amount; - return true; - } - - public bool WithdrawGold(int amount) - { - if (TotalGold - amount < 0) return false; - - TotalGold -= amount; - return true; - } - - public bool WithdrawPlat(int amount) - { - if (TotalPlat - amount < 0) return false; - - TotalPlat -= amount; - return true; - } - - public long GetTotalGold() => TotalGold + TotalPlat * 100; - - public int CompareTo(TestAccount other) => other == null ? 1 : Username.CompareTo(other.Username); - - public int CompareTo(IAccount other) => other == null ? 1 : Username.CompareTo(other.Username); - - public string Username { get; set; } - public string Email { get; set; } - public AccessLevel AccessLevel { get; set; } - public int Length { get; } - public int Limit { get; } - public int Count { get; } - - private Mobile[] m_Mobiles; - private string m_Password; - - public Mobile this[int index] - { - get => m_Mobiles[index]; - set => m_Mobiles[index] = value; - } - - public void Delete() - { - } - - public void SetPassword(string password) - { - m_Password = password; - } - - public bool CheckPassword(string password) => m_Password == password; - - public TestAccount(Mobile[] mobiles) - { - m_Mobiles = mobiles; - foreach (var mobile in mobiles) - if (mobile != null) - mobile.Account = this; - - Length = mobiles.Length; - Count = mobiles.Count(t => t != null); - Limit = mobiles.Length; - } - } - - internal class TestConnectionContext : ConnectionContext - { - public override string ConnectionId { get; set; } - public override IFeatureCollection Features { get; } - public override IDictionary Items { get; set; } - public override IDuplexPipe Transport { get; set; } - } - - [Fact] - public void TestChangeCharacter() - { - var firstMobile = new Mobile(0x1); - firstMobile.DefaultMobileInit(); - firstMobile.Name = "Test Mobile"; - - var account = new TestAccount(new[] {firstMobile, null, null}); - - Span data = new ChangeCharacter(account).Compile(); - - Span expectedData = stackalloc byte[5 + account.Length * 60]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x81); // Packet ID - expectedData.Write(ref pos, (ushort)expectedData.Length); // Length - expectedData.Write(ref pos, (byte)1); // Count of non-null characters - expectedData.Write(ref pos, (byte)0); - - for (var i = 0; i < account.Length; ++i) - { - Mobile m = account[i]; - if (m == null) - { -#if NO_LOCAL_INIT - expectedData.Clear(ref pos, 60); -#else - pos += 60; -#endif - } - else - { - expectedData.WriteAsciiFixed(ref pos, m.Name, 30); -#if NO_LOCAL_INIT - expectedData.Clear(ref pos, 30); // Password (empty) -#else - pos += 30; -#endif - } - } - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestClientVersionReq() - { - Span data = new ClientVersionReq().Compile(); - - Span expectedData = stackalloc byte[] - { - 0xBD, // Packet ID - 0x00, 0x03 // Length - }; - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestDeleteResult() - { - Span data = new DeleteResult(DeleteResultType.BadRequest).Compile(); - - Span expectedData = stackalloc byte[2]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x85); // Packet ID - expectedData.Write(ref pos, (byte)DeleteResultType.BadRequest); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestPopupMessage() - { - Span data = new PopupMessage(PMMessage.IdleWarning).Compile(); - - Span expectedData = stackalloc byte[2]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x53); // Packet ID - expectedData.Write(ref pos, (byte)PMMessage.IdleWarning); - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(ProtocolChanges.Version70610)] - [InlineData(ProtocolChanges.Version6000)] - public void TestSupportedFeatures(ProtocolChanges protocolChanges) - { - var firstMobile = new Mobile(0x1); - firstMobile.DefaultMobileInit(); - firstMobile.Name = "Test Mobile"; - - var account = new TestAccount(new[] {firstMobile, null, null, null, null}); - - NetState ns = new NetState(new TestConnectionContext - { - RemoteEndPoint = IPEndPoint.Parse("127.0.0.1") - }) - { - Account = account, - ProtocolChanges = protocolChanges - }; - - Span data = new SupportedFeatures(ns).Compile(); - - Span expectedData = stackalloc byte[ns.ExtendedSupportedFeatures ? 5 : 3]; - int pos = 0; - - expectedData[pos++] = 0xB9; // Packet ID - - var flags = ExpansionInfo.GetFeatures(Expansion.EJ); - - if (ns.Account.Limit >= 6) - { - flags |= FeatureFlags.LiveAccount; - flags &= ~FeatureFlags.UOTD; - - if (ns.Account.Limit > 6) - flags |= FeatureFlags.SeventhCharacterSlot; - else - flags |= FeatureFlags.SixthCharacterSlot; - } - - if (ns.ExtendedSupportedFeatures) - expectedData.Write(ref pos, (uint)flags); - else - expectedData.Write(ref pos, (ushort)flags); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestLoginConfirm() - { - var m = new Mobile(0x1); - m.DefaultMobileInit(); - m.Body = 0x100; - m.X = 100; - m.Y = 10; - m.Z = -10; - m.Direction = Direction.Down; - m.LogoutMap = Map.Felucca; - - Span data = new LoginConfirm(m).Compile(); - - Span expectedData = stackalloc byte[37]; - - int pos = 0; - expectedData.Write(ref pos, (byte)0x1B); // Packet ID - expectedData.Write(ref pos, m.Serial); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, 0); -#else - pos += 4; -#endif - - expectedData.Write(ref pos, (ushort)m.Body); - expectedData.Write(ref pos, (ushort)m.X); - expectedData.Write(ref pos, (ushort)m.Y); - expectedData.Write(ref pos, (short)m.Z); - expectedData.Write(ref pos, (byte)m.Direction); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); -#else - pos++; -#endif - expectedData.Write(ref pos, 0xFFFFFFFF); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, 0); -#else - pos += 4; -#endif - var map = m.Map; - - if (map == null || map == Map.Internal) - map = m.LogoutMap; - - expectedData.Write(ref pos, (ushort)(map?.Width ?? Map.Felucca.Width)); - expectedData.Write(ref pos, (ushort)(map?.Height ?? Map.Felucca.Height)); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestLoginComplete() - { - Span data = new LoginComplete().Compile(); - - Span expectedData = stackalloc byte[] - { - 0x55 // Packet ID - }; - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestCharacterListUpdate() - { - var firstMobile = new Mobile(0x1); - firstMobile.DefaultMobileInit(); - firstMobile.Name = "Test Mobile"; - - var account = new TestAccount(new[] {firstMobile, null, null, null, null}); - - Span data = new CharacterListUpdate(account).Compile(); - - Span expectedData = stackalloc byte[4 + account.Length * 60]; - - int pos = 0; - expectedData.Write(ref pos, (byte)0x86); // Packet ID - expectedData.Write(ref pos, (ushort)expectedData.Length); // Length - - int highSlot = -1; - for (int i = account.Length - 1; i >= 0; i--) - if (account[i] != null) - { - highSlot = i; - break; - } - - int count = Math.Max(Math.Max(highSlot + 1, account.Limit), 5); - expectedData.Write(ref pos, (byte)count); - - for (int i = 0; i < count; i++) - { - var m = account[i]; - - if (m != null) - { - expectedData.WriteAsciiFixed(ref pos, m.Name, 30); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, 0); - expectedData.Write(ref pos, (ushort)0); -#else - pos += 30; -#endif - } - else - { -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, 0); -#else - pos += 60; -#endif - } - } - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestCharacterList() - { - var firstMobile = new Mobile(0x1); - firstMobile.DefaultMobileInit(); - firstMobile.Name = "Test Mobile"; - - var account = new TestAccount(new[] {firstMobile, null, null, null, null}); - var info = new[] - { - new CityInfo("Test City", "Test Building", 50, 100, 10, -10) - }; - - Span data = new CharacterList(account, info).Compile(); - - Span expectedData = stackalloc byte[11 + account.Length * 60 + info.Length * 89]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xA9); // Packet ID - expectedData.Write(ref pos, (ushort)expectedData.Length); // Length - - int highSlot = -1; - for (int i = account.Length - 1; i >= 0; i--) - if (account[i] != null) - { - highSlot = i; - break; - } - - int count = Math.Max(Math.Max(highSlot + 1, account.Limit), 5); - expectedData.Write(ref pos, (byte)count); - - for (int i = 0; i < count; i++) - { - var m = account[i]; - if (m != null) - { - expectedData.WriteAsciiFixed(ref pos, m.Name, 30); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, 0); - expectedData.Write(ref pos, (ushort)0); -#else - pos += 30; -#endif - } - else - { -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, 0); -#else - pos += 60; -#endif - } - } - - expectedData.Write(ref pos, (byte)info.Length); - - for (int i = 0; i < info.Length; i++) - { - var ci = info[i]; - expectedData.Write(ref pos, (byte)i); - expectedData.WriteAsciiFixed(ref pos, ci.City, 32); - expectedData.WriteAsciiFixed(ref pos, ci.Building, 32); - expectedData.Write(ref pos, ci.X); - expectedData.Write(ref pos, ci.Y); - expectedData.Write(ref pos, ci.Z); - expectedData.Write(ref pos, ci.Map.MapID); - expectedData.Write(ref pos, ci.Description); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, 0); -#else - pos += 4; -#endif - } - - var flags = ExpansionInfo.GetInfo(Expansion.EJ).CharacterListFlags; - if (count > 6) - flags |= CharacterListFlags.SeventhCharacterSlot | - CharacterListFlags.SixthCharacterSlot; // 7th Character Slot - else if (count == 6) - flags |= CharacterListFlags.SixthCharacterSlot; // 6th Character Slot - else if (account.Limit == 1) - flags |= CharacterListFlags.SlotLimit & - CharacterListFlags.OneCharacterSlot; // Limit Characters & One Character - - expectedData.Write(ref pos, (int)flags); - expectedData.Write(ref pos, (short)-1); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestCharacterListOld() - { - var firstMobile = new Mobile(0x1); - firstMobile.DefaultMobileInit(); - firstMobile.Name = "Test Mobile"; - - var account = new TestAccount(new[] {firstMobile, null, null, null, null}); - var info = new[] - { - new CityInfo("Test City", "Test Building", 50, 100, 10, -10) - }; - - Span data = new CharacterListOld(account, info).Compile(); - - Span expectedData = stackalloc byte[9 + account.Length * 60 + info.Length * 63]; - - int pos = 0; - expectedData.Write(ref pos, (byte)0xA9); // Packet ID - expectedData.Write(ref pos, (ushort)expectedData.Length); // Length - - int highSlot = -1; - for (int i = account.Length - 1; i >= 0; i--) - if (account[i] != null) - { - highSlot = i; - break; - } - - int count = Math.Max(Math.Max(highSlot + 1, account.Limit), 5); - expectedData.Write(ref pos, (byte)count); - - for (int i = 0; i < count; i++) - { - var m = account[i]; - if (m != null) - { - expectedData.WriteAsciiFixed(ref pos, m.Name, 30); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, 0); - expectedData.Write(ref pos, (ushort)0); -#else - pos += 30; -#endif - } - else - { -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, 0); -#else - pos += 60; -#endif - } - } - - expectedData.Write(ref pos, (byte)info.Length); - - for (int i = 0; i < info.Length; i++) - { - var ci = info[i]; - expectedData.Write(ref pos, (byte)i); - expectedData.WriteAsciiFixed(ref pos, ci.City, 31); - expectedData.WriteAsciiFixed(ref pos, ci.Building, 31); - } - - var flags = ExpansionInfo.GetInfo(Expansion.EJ).CharacterListFlags; - if (count > 6) - flags |= CharacterListFlags.SeventhCharacterSlot | - CharacterListFlags.SixthCharacterSlot; // 7th Character Slot - else if (count == 6) - flags |= CharacterListFlags.SixthCharacterSlot; // 6th Character Slot - else if (account.Limit == 1) - flags |= CharacterListFlags.SlotLimit & - CharacterListFlags.OneCharacterSlot; // Limit Characters & One Character - - expectedData.Write(ref pos, (int)flags); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestAccountLoginRej() - { - var reason = ALRReason.BadComm; - Span data = new AccountLoginRej(reason).Compile(); - - Span expectedData = stackalloc byte[2]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x82); // Packet ID - expectedData.Write(ref pos, (byte)reason); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestAccountLoginAck() - { - var info = new[] - { - new ServerInfo("Test Server", 0, TimeZoneInfo.Local, IPEndPoint.Parse("127.0.0.1")) - }; - - Span data = new AccountLoginAck(info).Compile(); - - Span expectedData = stackalloc byte[6 + info.Length * 40]; - - int pos = 0; - expectedData.Write(ref pos, (byte)0xA8); // Packet ID - expectedData.Write(ref pos, (ushort)expectedData.Length); - expectedData.Write(ref pos, (byte)0x5D); // Unknown - expectedData.Write(ref pos, (ushort)info.Length); - - for (int i = 0; i < info.Length; i++) - { - var si = info[i]; - expectedData.Write(ref pos, (ushort)i); - expectedData.WriteAsciiFixed(ref pos, si.Name, 32); - expectedData.Write(ref pos, (byte)si.FullPercent); - expectedData.Write(ref pos, (byte)si.TimeZone); - expectedData.Write(ref pos, Utility.GetAddressValue(si.Address.Address)); - } - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestPlayServerAck() - { - var si = new ServerInfo("Test Server", 0, TimeZoneInfo.Local, IPEndPoint.Parse("127.0.0.1")); - - Span data = new PlayServerAck(si).Compile(); - - var addr = Utility.GetAddressValue(si.Address.Address); - - Span expectedData = stackalloc byte[11]; - int pos = 0; - - expectedData.Write(ref pos,(byte)0x8C); // Packet ID - expectedData.WriteLE(ref pos, addr); - expectedData.Write(ref pos, (ushort)si.Address.Port); - expectedData.Write(ref pos, -1); // Auth ID - - AssertThat.Equal(data, expectedData); - } - } -} +using System; +using System.Buffers; +using System.Collections.Generic; +using System.IO.Pipelines; +using System.Linq; +using System.Net; +using Microsoft.AspNetCore.Connections; +using Microsoft.AspNetCore.Http.Features; +using Server.Accounting; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class AccountPacketTests : IClassFixture + { + [Fact] + public void TestChangeCharacter() + { + var firstMobile = new Mobile(0x1); + firstMobile.DefaultMobileInit(); + firstMobile.Name = "Test Mobile"; + + var account = new TestAccount(new[] { firstMobile, null, null }); + + var data = new ChangeCharacter(account).Compile(); + + Span expectedData = stackalloc byte[5 + account.Length * 60]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x81); // Packet ID + expectedData.Write(ref pos, (ushort)expectedData.Length); // Length + expectedData.Write(ref pos, (byte)1); // Count of non-null characters + expectedData.Write(ref pos, (byte)0); + + for (var i = 0; i < account.Length; ++i) + { + var m = account[i]; + if (m == null) + { +#if NO_LOCAL_INIT + expectedData.Clear(ref pos, 60); +#else + pos += 60; +#endif + } + else + { + expectedData.WriteAsciiFixed(ref pos, m.Name, 30); +#if NO_LOCAL_INIT + expectedData.Clear(ref pos, 30); // Password (empty) +#else + pos += 30; +#endif + } + } + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestClientVersionReq() + { + var data = new ClientVersionReq().Compile(); + + Span expectedData = stackalloc byte[] + { + 0xBD, // Packet ID + 0x00, 0x03 // Length + }; + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestDeleteResult() + { + var data = new DeleteResult(DeleteResultType.BadRequest).Compile(); + + Span expectedData = stackalloc byte[2]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x85); // Packet ID + expectedData.Write(ref pos, (byte)DeleteResultType.BadRequest); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestPopupMessage() + { + var data = new PopupMessage(PMMessage.IdleWarning).Compile(); + + Span expectedData = stackalloc byte[2]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x53); // Packet ID + expectedData.Write(ref pos, (byte)PMMessage.IdleWarning); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(ProtocolChanges.Version70610)] + [InlineData(ProtocolChanges.Version6000)] + public void TestSupportedFeatures(ProtocolChanges protocolChanges) + { + var firstMobile = new Mobile(0x1); + firstMobile.DefaultMobileInit(); + firstMobile.Name = "Test Mobile"; + + var account = new TestAccount(new[] { firstMobile, null, null, null, null }); + + var ns = new NetState( + new TestConnectionContext + { + RemoteEndPoint = IPEndPoint.Parse("127.0.0.1") + } + ) + { + Account = account, + ProtocolChanges = protocolChanges + }; + + var data = new SupportedFeatures(ns).Compile(); + + Span expectedData = stackalloc byte[ns.ExtendedSupportedFeatures ? 5 : 3]; + var pos = 0; + + expectedData[pos++] = 0xB9; // Packet ID + + var flags = ExpansionInfo.GetFeatures(Expansion.EJ); + + if (ns.Account.Limit >= 6) + { + flags |= FeatureFlags.LiveAccount; + flags &= ~FeatureFlags.UOTD; + + if (ns.Account.Limit > 6) + flags |= FeatureFlags.SeventhCharacterSlot; + else + flags |= FeatureFlags.SixthCharacterSlot; + } + + if (ns.ExtendedSupportedFeatures) + expectedData.Write(ref pos, (uint)flags); + else + expectedData.Write(ref pos, (ushort)flags); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestLoginConfirm() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + m.Body = 0x100; + m.X = 100; + m.Y = 10; + m.Z = -10; + m.Direction = Direction.Down; + m.LogoutMap = Map.Felucca; + + var data = new LoginConfirm(m).Compile(); + + Span expectedData = stackalloc byte[37]; + + var pos = 0; + expectedData.Write(ref pos, (byte)0x1B); // Packet ID + expectedData.Write(ref pos, m.Serial); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, 0); +#else + pos += 4; +#endif + + expectedData.Write(ref pos, (ushort)m.Body); + expectedData.Write(ref pos, (ushort)m.X); + expectedData.Write(ref pos, (ushort)m.Y); + expectedData.Write(ref pos, (short)m.Z); + expectedData.Write(ref pos, (byte)m.Direction); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); +#else + pos++; +#endif + expectedData.Write(ref pos, 0xFFFFFFFF); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, 0); +#else + pos += 4; +#endif + var map = m.Map; + + if (map == null || map == Map.Internal) + map = m.LogoutMap; + + expectedData.Write(ref pos, (ushort)(map?.Width ?? Map.Felucca.Width)); + expectedData.Write(ref pos, (ushort)(map?.Height ?? Map.Felucca.Height)); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestLoginComplete() + { + var data = new LoginComplete().Compile(); + + Span expectedData = stackalloc byte[] + { + 0x55 // Packet ID + }; + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestCharacterListUpdate() + { + var firstMobile = new Mobile(0x1); + firstMobile.DefaultMobileInit(); + firstMobile.Name = "Test Mobile"; + + var account = new TestAccount(new[] { firstMobile, null, null, null, null }); + + var data = new CharacterListUpdate(account).Compile(); + + Span expectedData = stackalloc byte[4 + account.Length * 60]; + + var pos = 0; + expectedData.Write(ref pos, (byte)0x86); // Packet ID + expectedData.Write(ref pos, (ushort)expectedData.Length); // Length + + var highSlot = -1; + for (var i = account.Length - 1; i >= 0; i--) + if (account[i] != null) + { + highSlot = i; + break; + } + + var count = Math.Max(Math.Max(highSlot + 1, account.Limit), 5); + expectedData.Write(ref pos, (byte)count); + + for (var i = 0; i < count; i++) + { + var m = account[i]; + + if (m != null) + { + expectedData.WriteAsciiFixed(ref pos, m.Name, 30); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, 0); + expectedData.Write(ref pos, (ushort)0); +#else + pos += 30; +#endif + } + else + { +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, 0); +#else + pos += 60; +#endif + } + } + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestCharacterList() + { + var firstMobile = new Mobile(0x1); + firstMobile.DefaultMobileInit(); + firstMobile.Name = "Test Mobile"; + + var account = new TestAccount(new[] { firstMobile, null, null, null, null }); + var info = new[] + { + new CityInfo("Test City", "Test Building", 50, 100, 10, -10) + }; + + var data = new CharacterList(account, info).Compile(); + + Span expectedData = stackalloc byte[11 + account.Length * 60 + info.Length * 89]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xA9); // Packet ID + expectedData.Write(ref pos, (ushort)expectedData.Length); // Length + + var highSlot = -1; + for (var i = account.Length - 1; i >= 0; i--) + if (account[i] != null) + { + highSlot = i; + break; + } + + var count = Math.Max(Math.Max(highSlot + 1, account.Limit), 5); + expectedData.Write(ref pos, (byte)count); + + for (var i = 0; i < count; i++) + { + var m = account[i]; + if (m != null) + { + expectedData.WriteAsciiFixed(ref pos, m.Name, 30); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, 0); + expectedData.Write(ref pos, (ushort)0); +#else + pos += 30; +#endif + } + else + { +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, 0); +#else + pos += 60; +#endif + } + } + + expectedData.Write(ref pos, (byte)info.Length); + + for (var i = 0; i < info.Length; i++) + { + var ci = info[i]; + expectedData.Write(ref pos, (byte)i); + expectedData.WriteAsciiFixed(ref pos, ci.City, 32); + expectedData.WriteAsciiFixed(ref pos, ci.Building, 32); + expectedData.Write(ref pos, ci.X); + expectedData.Write(ref pos, ci.Y); + expectedData.Write(ref pos, ci.Z); + expectedData.Write(ref pos, ci.Map.MapID); + expectedData.Write(ref pos, ci.Description); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, 0); +#else + pos += 4; +#endif + } + + var flags = ExpansionInfo.GetInfo(Expansion.EJ).CharacterListFlags; + if (count > 6) + flags |= CharacterListFlags.SeventhCharacterSlot | + CharacterListFlags.SixthCharacterSlot; // 7th Character Slot + else if (count == 6) + flags |= CharacterListFlags.SixthCharacterSlot; // 6th Character Slot + else if (account.Limit == 1) + flags |= CharacterListFlags.SlotLimit & + CharacterListFlags.OneCharacterSlot; // Limit Characters & One Character + + expectedData.Write(ref pos, (int)flags); + expectedData.Write(ref pos, (short)-1); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestCharacterListOld() + { + var firstMobile = new Mobile(0x1); + firstMobile.DefaultMobileInit(); + firstMobile.Name = "Test Mobile"; + + var account = new TestAccount(new[] { firstMobile, null, null, null, null }); + var info = new[] + { + new CityInfo("Test City", "Test Building", 50, 100, 10, -10) + }; + + var data = new CharacterListOld(account, info).Compile(); + + Span expectedData = stackalloc byte[9 + account.Length * 60 + info.Length * 63]; + + var pos = 0; + expectedData.Write(ref pos, (byte)0xA9); // Packet ID + expectedData.Write(ref pos, (ushort)expectedData.Length); // Length + + var highSlot = -1; + for (var i = account.Length - 1; i >= 0; i--) + if (account[i] != null) + { + highSlot = i; + break; + } + + var count = Math.Max(Math.Max(highSlot + 1, account.Limit), 5); + expectedData.Write(ref pos, (byte)count); + + for (var i = 0; i < count; i++) + { + var m = account[i]; + if (m != null) + { + expectedData.WriteAsciiFixed(ref pos, m.Name, 30); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, 0); + expectedData.Write(ref pos, (ushort)0); +#else + pos += 30; +#endif + } + else + { +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, 0); +#else + pos += 60; +#endif + } + } + + expectedData.Write(ref pos, (byte)info.Length); + + for (var i = 0; i < info.Length; i++) + { + var ci = info[i]; + expectedData.Write(ref pos, (byte)i); + expectedData.WriteAsciiFixed(ref pos, ci.City, 31); + expectedData.WriteAsciiFixed(ref pos, ci.Building, 31); + } + + var flags = ExpansionInfo.GetInfo(Expansion.EJ).CharacterListFlags; + if (count > 6) + flags |= CharacterListFlags.SeventhCharacterSlot | + CharacterListFlags.SixthCharacterSlot; // 7th Character Slot + else if (count == 6) + flags |= CharacterListFlags.SixthCharacterSlot; // 6th Character Slot + else if (account.Limit == 1) + flags |= CharacterListFlags.SlotLimit & + CharacterListFlags.OneCharacterSlot; // Limit Characters & One Character + + expectedData.Write(ref pos, (int)flags); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestAccountLoginRej() + { + var reason = ALRReason.BadComm; + var data = new AccountLoginRej(reason).Compile(); + + Span expectedData = stackalloc byte[2]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x82); // Packet ID + expectedData.Write(ref pos, (byte)reason); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestAccountLoginAck() + { + var info = new[] + { + new ServerInfo("Test Server", 0, TimeZoneInfo.Local, IPEndPoint.Parse("127.0.0.1")) + }; + + var data = new AccountLoginAck(info).Compile(); + + Span expectedData = stackalloc byte[6 + info.Length * 40]; + + var pos = 0; + expectedData.Write(ref pos, (byte)0xA8); // Packet ID + expectedData.Write(ref pos, (ushort)expectedData.Length); + expectedData.Write(ref pos, (byte)0x5D); // Unknown + expectedData.Write(ref pos, (ushort)info.Length); + + for (var i = 0; i < info.Length; i++) + { + var si = info[i]; + expectedData.Write(ref pos, (ushort)i); + expectedData.WriteAsciiFixed(ref pos, si.Name, 32); + expectedData.Write(ref pos, (byte)si.FullPercent); + expectedData.Write(ref pos, (byte)si.TimeZone); + expectedData.Write(ref pos, Utility.GetAddressValue(si.Address.Address)); + } + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestPlayServerAck() + { + var si = new ServerInfo("Test Server", 0, TimeZoneInfo.Local, IPEndPoint.Parse("127.0.0.1")); + + var data = new PlayServerAck(si).Compile(); + + var addr = Utility.GetAddressValue(si.Address.Address); + + Span expectedData = stackalloc byte[11]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x8C); // Packet ID + expectedData.WriteLE(ref pos, addr); + expectedData.Write(ref pos, (ushort)si.Address.Port); + expectedData.Write(ref pos, -1); // Auth ID + + AssertThat.Equal(data, expectedData); + } + + internal class TestAccount : IAccount, IComparable + { + private readonly Mobile[] m_Mobiles; + private string m_Password; + + public TestAccount(Mobile[] mobiles) + { + m_Mobiles = mobiles; + foreach (var mobile in mobiles) + if (mobile != null) + mobile.Account = this; + + Length = mobiles.Length; + Count = mobiles.Count(t => t != null); + Limit = mobiles.Length; + } + + public int TotalGold { get; private set; } + public int TotalPlat { get; private set; } + + public bool DepositGold(int amount) + { + TotalGold += amount; + return true; + } + + public bool DepositPlat(int amount) + { + TotalPlat += amount; + return true; + } + + public bool WithdrawGold(int amount) + { + if (TotalGold - amount < 0) return false; + + TotalGold -= amount; + return true; + } + + public bool WithdrawPlat(int amount) + { + if (TotalPlat - amount < 0) return false; + + TotalPlat -= amount; + return true; + } + + public long GetTotalGold() => TotalGold + TotalPlat * 100; + + public int CompareTo(IAccount other) => other == null ? 1 : Username.CompareTo(other.Username); + + public string Username { get; set; } + public string Email { get; set; } + public AccessLevel AccessLevel { get; set; } + public int Length { get; } + public int Limit { get; } + public int Count { get; } + + public Mobile this[int index] + { + get => m_Mobiles[index]; + set => m_Mobiles[index] = value; + } + + public void Delete() + { + } + + public void SetPassword(string password) + { + m_Password = password; + } + + public bool CheckPassword(string password) => m_Password == password; + + public int CompareTo(TestAccount other) => other == null ? 1 : Username.CompareTo(other.Username); + } + + internal class TestConnectionContext : ConnectionContext + { + public override string ConnectionId { get; set; } + public override IFeatureCollection Features { get; } + public override IDictionary Items { get; set; } + public override IDuplexPipe Transport { get; set; } + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/ArrowPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/ArrowPacketTests.cs index 5d1f25743..1ce42e310 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/ArrowPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/ArrowPacketTests.cs @@ -1,90 +1,90 @@ -using System; -using System.Buffers; -using Server.Network; -using Xunit; - -namespace Server.Tests.Network.Packets -{ - public class ArrowPacketTests - { - [Fact] - public void TestCancelArrow() - { - Span data = new CancelArrow().Compile(); - - Span expectedData = stackalloc byte[6]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xBA); // Packet ID - expectedData.Write(ref pos, (byte)0); // Command - expectedData.Write(ref pos, 0xFFFFFFFF); // X, Y - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(0, 0)] - [InlineData(100, 10)] - [InlineData(100000, 100000)] - public void TestSetArrow(int x, int y) - { - Span data = new SetArrow(x, y).Compile(); - - Span expectedData = stackalloc byte[6]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xBA); // Packet ID - expectedData.Write(ref pos, (byte)0x01); // Command - expectedData.Write(ref pos, (ushort)x); - expectedData.Write(ref pos, (ushort)y); - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(0, 0)] - [InlineData(100, 10)] - [InlineData(100000, 100000)] - public void TestCancelArrowHS(int x, int y) - { - Serial serial = 0x01; - Span data = new CancelArrowHS(x, y, serial).Compile(); - - Span expectedData = stackalloc byte[10]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xBA); // Packet ID -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); // Command -#else - pos++; -#endif - expectedData.Write(ref pos, (ushort)x); - expectedData.Write(ref pos, (ushort)y); - expectedData.Write(ref pos, serial); - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(0, 0)] - [InlineData(100, 10)] - [InlineData(100000, 100000)] - public void TestSetArrowHS(int x, int y) - { - Serial serial = 0x01; - Span data = new SetArrowHS(x, y, serial).Compile(); - - Span expectedData = stackalloc byte[10]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xBA); // Packet ID - expectedData.Write(ref pos, (byte)0x01); // Command - expectedData.Write(ref pos, (ushort)x); - expectedData.Write(ref pos, (ushort)y); - expectedData.Write(ref pos, serial); - - AssertThat.Equal(data, expectedData); - } - } -} +using System; +using System.Buffers; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class ArrowPacketTests + { + [Fact] + public void TestCancelArrow() + { + var data = new CancelArrow().Compile(); + + Span expectedData = stackalloc byte[6]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xBA); // Packet ID + expectedData.Write(ref pos, (byte)0); // Command + expectedData.Write(ref pos, 0xFFFFFFFF); // X, Y + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(0, 0)] + [InlineData(100, 10)] + [InlineData(100000, 100000)] + public void TestSetArrow(int x, int y) + { + var data = new SetArrow(x, y).Compile(); + + Span expectedData = stackalloc byte[6]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xBA); // Packet ID + expectedData.Write(ref pos, (byte)0x01); // Command + expectedData.Write(ref pos, (ushort)x); + expectedData.Write(ref pos, (ushort)y); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(0, 0)] + [InlineData(100, 10)] + [InlineData(100000, 100000)] + public void TestCancelArrowHS(int x, int y) + { + Serial serial = 0x01; + var data = new CancelArrowHS(x, y, serial).Compile(); + + Span expectedData = stackalloc byte[10]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xBA); // Packet ID +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); // Command +#else + pos++; +#endif + expectedData.Write(ref pos, (ushort)x); + expectedData.Write(ref pos, (ushort)y); + expectedData.Write(ref pos, serial); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(0, 0)] + [InlineData(100, 10)] + [InlineData(100000, 100000)] + public void TestSetArrowHS(int x, int y) + { + Serial serial = 0x01; + var data = new SetArrowHS(x, y, serial).Compile(); + + Span expectedData = stackalloc byte[10]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xBA); // Packet ID + expectedData.Write(ref pos, (byte)0x01); // Command + expectedData.Write(ref pos, (ushort)x); + expectedData.Write(ref pos, (ushort)y); + expectedData.Write(ref pos, serial); + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/AttributeNormalizerTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/AttributeNormalizerTests.cs index 0feb9c990..c349bbe65 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/AttributeNormalizerTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/AttributeNormalizerTests.cs @@ -1,92 +1,92 @@ -using System; -using System.Buffers; -using Server.Network; -using Xunit; - -namespace Server.Tests.Network.Packets -{ - public class AttributeNormalizerTests - { - [Fact] - public void TestAttributeNormalizerEnabled() - { - AttributeNormalizer.Enabled = true; - AttributeNormalizer.Maximum = 25; - - PacketWriter stream = new PacketWriter(4); - - const ushort cur = 50; - const ushort max = 100; - - AttributeNormalizer.Write(stream, cur, max); - - Span expectedData = stackalloc byte[4]; - int pos = 0; - expectedData.Write(ref pos, (ushort)AttributeNormalizer.Maximum); - expectedData.Write(ref pos, (ushort)(cur * 25 / max)); - - AssertThat.Equal(stream.ToArray(), expectedData); - } - - [Fact] - public void TestAttributeNormalizerReversedEnabled() - { - AttributeNormalizer.Enabled = true; - AttributeNormalizer.Maximum = 25; - - PacketWriter stream = new PacketWriter(4); - - const ushort cur = 50; - const ushort max = 100; - - AttributeNormalizer.WriteReverse(stream, cur, max); - - Span expectedData = stackalloc byte[4]; - int pos = 0; - expectedData.Write(ref pos, (ushort)(cur * 25 / max)); - expectedData.Write(ref pos, (ushort)AttributeNormalizer.Maximum); - - AssertThat.Equal(stream.ToArray(), expectedData); - } - - [Fact] - public void TestAttributeNormalizerDisabled() - { - AttributeNormalizer.Enabled = false; - - PacketWriter stream = new PacketWriter(4); - - const ushort cur = 50; - const ushort max = 100; - - AttributeNormalizer.Write(stream, cur, max); - - Span expectedData = stackalloc byte[4]; - int pos = 0; - expectedData.Write(ref pos, max); - expectedData.Write(ref pos, cur); - - AssertThat.Equal(stream.ToArray(), expectedData); - } - - [Fact] - public void TestAttributeNormalizerReversedDisabled() - { - AttributeNormalizer.Enabled = false; - - PacketWriter stream = new PacketWriter(4); - - const ushort cur = 50; - const ushort max = 100; - - AttributeNormalizer.WriteReverse(stream, cur, max); - - Span expectedData = stackalloc byte[4]; - int pos = 0; - expectedData.Write(ref pos, cur); - expectedData.Write(ref pos, max); - - AssertThat.Equal(stream.ToArray(), expectedData); - } - } -} +using System; +using System.Buffers; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class AttributeNormalizerTests + { + [Fact] + public void TestAttributeNormalizerEnabled() + { + AttributeNormalizer.Enabled = true; + AttributeNormalizer.Maximum = 25; + + var stream = new PacketWriter(4); + + const ushort cur = 50; + const ushort max = 100; + + AttributeNormalizer.Write(stream, cur, max); + + Span expectedData = stackalloc byte[4]; + var pos = 0; + expectedData.Write(ref pos, (ushort)AttributeNormalizer.Maximum); + expectedData.Write(ref pos, (ushort)(cur * 25 / max)); + + AssertThat.Equal(stream.ToArray(), expectedData); + } + + [Fact] + public void TestAttributeNormalizerReversedEnabled() + { + AttributeNormalizer.Enabled = true; + AttributeNormalizer.Maximum = 25; + + var stream = new PacketWriter(4); + + const ushort cur = 50; + const ushort max = 100; + + AttributeNormalizer.WriteReverse(stream, cur, max); + + Span expectedData = stackalloc byte[4]; + var pos = 0; + expectedData.Write(ref pos, (ushort)(cur * 25 / max)); + expectedData.Write(ref pos, (ushort)AttributeNormalizer.Maximum); + + AssertThat.Equal(stream.ToArray(), expectedData); + } + + [Fact] + public void TestAttributeNormalizerDisabled() + { + AttributeNormalizer.Enabled = false; + + var stream = new PacketWriter(4); + + const ushort cur = 50; + const ushort max = 100; + + AttributeNormalizer.Write(stream, cur, max); + + Span expectedData = stackalloc byte[4]; + var pos = 0; + expectedData.Write(ref pos, max); + expectedData.Write(ref pos, cur); + + AssertThat.Equal(stream.ToArray(), expectedData); + } + + [Fact] + public void TestAttributeNormalizerReversedDisabled() + { + AttributeNormalizer.Enabled = false; + + var stream = new PacketWriter(4); + + const ushort cur = 50; + const ushort max = 100; + + AttributeNormalizer.WriteReverse(stream, cur, max); + + Span expectedData = stackalloc byte[4]; + var pos = 0; + expectedData.Write(ref pos, cur); + expectedData.Write(ref pos, max); + + AssertThat.Equal(stream.ToArray(), expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/CombatPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/CombatPacketTests.cs index 016ec4878..01aab527d 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/CombatPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/CombatPacketTests.cs @@ -1,80 +1,80 @@ -using System; -using System.Buffers; -using Server.Network; -using Xunit; - -namespace Server.Tests.Network.Packets -{ - public class CombatPacketTests - { - [Fact] - public void TestSwing() - { - Serial attacker = 0x1000; - Serial defender = 0x2000; - - Span data = new Swing(attacker, defender).Compile(); - - Span expectedData = stackalloc byte[10]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x2F); // Packet ID -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); -#else - pos++; -#endif - - expectedData.Write(ref pos, attacker); - expectedData.Write(ref pos, defender); - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public void TestSetWarMode(bool warmode) - { - Span data = new SetWarMode(warmode).Compile(); - - Span expectedData = stackalloc byte[5]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x72); // Packet ID - expectedData.Write(ref pos, warmode); - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); -#else - pos++; -#endif - - expectedData.Write(ref pos, (byte)0x32); - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); -#else - pos++; -#endif - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestChangeCombatant() - { - Serial combatant = 0x1000; - - Span data = new ChangeCombatant(combatant).Compile(); - - Span expectedData = stackalloc byte[5]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xAA); // Packet ID - expectedData.Write(ref pos, combatant); - - AssertThat.Equal(data, expectedData); - } - } -} +using System; +using System.Buffers; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class CombatPacketTests + { + [Fact] + public void TestSwing() + { + Serial attacker = 0x1000; + Serial defender = 0x2000; + + var data = new Swing(attacker, defender).Compile(); + + Span expectedData = stackalloc byte[10]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x2F); // Packet ID +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); +#else + pos++; +#endif + + expectedData.Write(ref pos, attacker); + expectedData.Write(ref pos, defender); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void TestSetWarMode(bool warmode) + { + var data = new SetWarMode(warmode).Compile(); + + Span expectedData = stackalloc byte[5]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x72); // Packet ID + expectedData.Write(ref pos, warmode); + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); +#else + pos++; +#endif + + expectedData.Write(ref pos, (byte)0x32); + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); +#else + pos++; +#endif + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestChangeCombatant() + { + Serial combatant = 0x1000; + + var data = new ChangeCombatant(combatant).Compile(); + + Span expectedData = stackalloc byte[5]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xAA); // Packet ID + expectedData.Write(ref pos, combatant); + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/DamagePacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/DamagePacketTests.cs index 0bf590844..fd4c501a6 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/DamagePacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/DamagePacketTests.cs @@ -1,56 +1,56 @@ -using System; -using System.Buffers; -using Server.Network; -using Xunit; - -namespace Server.Tests.Network.Packets -{ - public class DamagePacketTests : IClassFixture - { - [Theory] - [InlineData(10, 10)] - [InlineData(-5, 0)] - [InlineData(1024, 0xFF)] - public void TestDamagePacketOld(int inputAmount, byte expectedAmount) - { - var m = new Mobile(0x1); - m.DefaultMobileInit(); - - Span data = new DamagePacketOld(m.Serial, inputAmount).Compile(); - - Span expectedData = stackalloc byte[11]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xBF); // Packet ID - expectedData.Write(ref pos, (ushort)11); // Length - expectedData.Write(ref pos, (ushort)0x22); // Sub-packet - expectedData.Write(ref pos, (byte)0x01); // Command - expectedData.Write(ref pos, m.Serial); - expectedData.Write(ref pos, expectedAmount); - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(10, 10)] - [InlineData(-5, 0)] - [InlineData(1024, 1024)] - [InlineData(100000, 0xFFFF)] - public void TestDamage(int inputAmount, ushort expectedAmount) - { - var m = new Mobile(0x1); - m.DefaultMobileInit(); - - Span data = new DamagePacket(m.Serial, inputAmount).Compile(); - - Span expectedData = stackalloc byte[7]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x0B); // Packet ID - expectedData.Write(ref pos, m.Serial); - expectedData.Write(ref pos, expectedAmount); - - AssertThat.Equal(data, expectedData); - } - } -} +using System; +using System.Buffers; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class DamagePacketTests : IClassFixture + { + [Theory] + [InlineData(10, 10)] + [InlineData(-5, 0)] + [InlineData(1024, 0xFF)] + public void TestDamagePacketOld(int inputAmount, byte expectedAmount) + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var data = new DamagePacketOld(m.Serial, inputAmount).Compile(); + + Span expectedData = stackalloc byte[11]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xBF); // Packet ID + expectedData.Write(ref pos, (ushort)11); // Length + expectedData.Write(ref pos, (ushort)0x22); // Sub-packet + expectedData.Write(ref pos, (byte)0x01); // Command + expectedData.Write(ref pos, m.Serial); + expectedData.Write(ref pos, expectedAmount); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(10, 10)] + [InlineData(-5, 0)] + [InlineData(1024, 1024)] + [InlineData(100000, 0xFFFF)] + public void TestDamage(int inputAmount, ushort expectedAmount) + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var data = new DamagePacket(m.Serial, inputAmount).Compile(); + + Span expectedData = stackalloc byte[7]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x0B); // Packet ID + expectedData.Write(ref pos, m.Serial); + expectedData.Write(ref pos, expectedAmount); + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/DisplayHuePickerTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/DisplayHuePickerTests.cs index d7410d954..7116df5ba 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/DisplayHuePickerTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/DisplayHuePickerTests.cs @@ -1,34 +1,34 @@ -using System; -using System.Buffers; -using Server.HuePickers; -using Server.Network; -using Xunit; - -namespace Server.Tests.Network.Packets -{ - public class DisplayHuePickerTests - { - [Fact] - public void TestDisplayHuePicker() - { - const ushort itemID = 0xFF01; - var huePicker = new HuePicker(itemID); - - Span data = new DisplayHuePicker(huePicker).Compile(); - - Span expectedData = stackalloc byte[9]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x95); - expectedData.Write(ref pos, huePicker.Serial); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (ushort)0); -#else - pos += 2; -#endif - expectedData.Write(ref pos, itemID); - - AssertThat.Equal(data, expectedData); - } - } -} +using System; +using System.Buffers; +using Server.HuePickers; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class DisplayHuePickerTests + { + [Fact] + public void TestDisplayHuePicker() + { + const ushort itemID = 0xFF01; + var huePicker = new HuePicker(itemID); + + var data = new DisplayHuePicker(huePicker).Compile(); + + Span expectedData = stackalloc byte[9]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x95); + expectedData.Write(ref pos, huePicker.Serial); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (ushort)0); +#else + pos += 2; +#endif + expectedData.Write(ref pos, itemID); + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/EffectPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/EffectPacketTests.cs index 70ca135d0..3e938bc44 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/EffectPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/EffectPacketTests.cs @@ -1,182 +1,204 @@ -using System; -using System.Buffers; -using Server.Network; -using Xunit; - -namespace Server.Tests.Network.Packets -{ - public class EffectPackets - { - [Fact] - public void TestParticleEffect() - { - EffectType effectType = EffectType.Moving; - Serial serial = 0x4000; - Serial from = 0x1000; - Serial to = 0x2000; - var itemId = 0x100; - Point3D fromPoint = new Point3D(1000, 100, -10); - Point3D toPoint = new Point3D(1500, 500, 0); - byte speed = 3; - byte duration = 2; - bool direction = false; - bool explode = false; - int hue = 0x1024; - int renderMode = 1; - ushort effect = 3; - ushort explodeEffect = 0; - ushort explodeSound = 0; - byte layer = 9; - ushort unknown = 0; - - Span data = new ParticleEffect( - effectType, from, to, itemId, - fromPoint, toPoint, speed, duration, - direction, explode, hue, renderMode, - effect, explodeEffect, explodeSound, serial, - layer, unknown - ).Compile(); - - Span expectedData = stackalloc byte[49]; - - int pos = 0; - expectedData.Write(ref pos, (byte)0xC7); // Packet ID - expectedData.Write(ref pos, (byte)effectType); - expectedData.Write(ref pos, from); - expectedData.Write(ref pos, to); - expectedData.Write(ref pos, (ushort)itemId); - expectedData.Write(ref pos, fromPoint); - expectedData.Write(ref pos, toPoint); - expectedData.Write(ref pos, speed); - expectedData.Write(ref pos, duration); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (ushort)0); -#else - pos += 2; -#endif - expectedData.Write(ref pos, direction); - expectedData.Write(ref pos, explode); - expectedData.Write(ref pos, hue); - expectedData.Write(ref pos, renderMode); - expectedData.Write(ref pos, effect); - expectedData.Write(ref pos, explodeEffect); - expectedData.Write(ref pos, explodeSound); - expectedData.Write(ref pos, serial); - expectedData.Write(ref pos, layer); - expectedData.Write(ref pos, unknown); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestHuedEffect() - { - EffectType effectType = EffectType.Moving; - Serial serial = 0x4000; - Serial from = 0x1000; - Serial to = 0x2000; - var itemId = 0x100; - Point3D fromPoint = new Point3D(1000, 100, -10); - Point3D toPoint = new Point3D(1500, 500, 0); - byte speed = 3; - byte duration = 2; - bool direction = false; - bool explode = false; - int hue = 0x1024; - int renderMode = 1; - - Span data = new HuedEffect( - effectType, from, to, itemId, - fromPoint, toPoint, speed, duration, - direction, explode, hue, renderMode - ).Compile(); - - Span expectedData = stackalloc byte[36]; - - int pos = 0; - expectedData.Write(ref pos, (byte)0xC0); // Packet ID - expectedData.Write(ref pos, (byte)effectType); - expectedData.Write(ref pos, from); - expectedData.Write(ref pos, to); - expectedData.Write(ref pos, (ushort)itemId); - expectedData.Write(ref pos, fromPoint); - expectedData.Write(ref pos, toPoint); - expectedData.Write(ref pos, speed); - expectedData.Write(ref pos, duration); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (ushort)0); -#else - pos += 2; -#endif - expectedData.Write(ref pos, direction); - expectedData.Write(ref pos, explode); - expectedData.Write(ref pos, hue); - expectedData.Write(ref pos, renderMode); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestScreenEffect() - { - var type = ScreenEffectType.FadeOut; - Span data = new ScreenEffect(type).Compile(); - - Span expectedData = stackalloc byte[28]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x70); // Packet ID - expectedData.Write(ref pos, (byte)0x04); // Effect -#if NO_LOCAL_INIT - expectedData.Write(ref pos, 0); - expectedData.Write(ref pos, 0); -#else - pos += 8; -#endif - - expectedData.Write(ref pos, (ushort)type); // Screen Effect Type - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, 0); - expectedData.Write(ref pos, 0); - expectedData.Write(ref pos, 0); - expectedData.Write(ref pos, 0); -#endif - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestBoltEffect() - { - IEntity entity = new Entity(0x1000, new Point3D(1000, 100, -10), Map.Felucca); - var hue = 0x1024; - Span data = new BoltEffect(entity, hue).Compile(); - - Span expectedData = stackalloc byte[36]; - int pos = 0; - expectedData.Write(ref pos, (byte)0xC0); // Packet ID - expectedData.Write(ref pos, (byte)0x01); // Effect - - - expectedData.Write(ref pos, entity.Serial); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, 0); - expectedData.Write(ref pos, (ushort)0); -#else - pos += 6; -#endif - expectedData.Write(ref pos, entity.Location); - expectedData.Write(ref pos, entity.Location); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, 0); - expectedData.Write(ref pos, (ushort)0); -#else - pos += 6; -#endif - expectedData.Write(ref pos, hue); - - AssertThat.Equal(data, expectedData); - } - } -} +using System; +using System.Buffers; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class EffectPackets + { + [Fact] + public void TestParticleEffect() + { + var effectType = EffectType.Moving; + Serial serial = 0x4000; + Serial from = 0x1000; + Serial to = 0x2000; + var itemId = 0x100; + var fromPoint = new Point3D(1000, 100, -10); + var toPoint = new Point3D(1500, 500, 0); + byte speed = 3; + byte duration = 2; + var direction = false; + var explode = false; + var hue = 0x1024; + var renderMode = 1; + ushort effect = 3; + ushort explodeEffect = 0; + ushort explodeSound = 0; + byte layer = 9; + ushort unknown = 0; + + var data = new ParticleEffect( + effectType, + from, + to, + itemId, + fromPoint, + toPoint, + speed, + duration, + direction, + explode, + hue, + renderMode, + effect, + explodeEffect, + explodeSound, + serial, + layer, + unknown + ).Compile(); + + Span expectedData = stackalloc byte[49]; + + var pos = 0; + expectedData.Write(ref pos, (byte)0xC7); // Packet ID + expectedData.Write(ref pos, (byte)effectType); + expectedData.Write(ref pos, from); + expectedData.Write(ref pos, to); + expectedData.Write(ref pos, (ushort)itemId); + expectedData.Write(ref pos, fromPoint); + expectedData.Write(ref pos, toPoint); + expectedData.Write(ref pos, speed); + expectedData.Write(ref pos, duration); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (ushort)0); +#else + pos += 2; +#endif + expectedData.Write(ref pos, direction); + expectedData.Write(ref pos, explode); + expectedData.Write(ref pos, hue); + expectedData.Write(ref pos, renderMode); + expectedData.Write(ref pos, effect); + expectedData.Write(ref pos, explodeEffect); + expectedData.Write(ref pos, explodeSound); + expectedData.Write(ref pos, serial); + expectedData.Write(ref pos, layer); + expectedData.Write(ref pos, unknown); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestHuedEffect() + { + var effectType = EffectType.Moving; + Serial serial = 0x4000; + Serial from = 0x1000; + Serial to = 0x2000; + var itemId = 0x100; + var fromPoint = new Point3D(1000, 100, -10); + var toPoint = new Point3D(1500, 500, 0); + byte speed = 3; + byte duration = 2; + var direction = false; + var explode = false; + var hue = 0x1024; + var renderMode = 1; + + var data = new HuedEffect( + effectType, + from, + to, + itemId, + fromPoint, + toPoint, + speed, + duration, + direction, + explode, + hue, + renderMode + ).Compile(); + + Span expectedData = stackalloc byte[36]; + + var pos = 0; + expectedData.Write(ref pos, (byte)0xC0); // Packet ID + expectedData.Write(ref pos, (byte)effectType); + expectedData.Write(ref pos, from); + expectedData.Write(ref pos, to); + expectedData.Write(ref pos, (ushort)itemId); + expectedData.Write(ref pos, fromPoint); + expectedData.Write(ref pos, toPoint); + expectedData.Write(ref pos, speed); + expectedData.Write(ref pos, duration); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (ushort)0); +#else + pos += 2; +#endif + expectedData.Write(ref pos, direction); + expectedData.Write(ref pos, explode); + expectedData.Write(ref pos, hue); + expectedData.Write(ref pos, renderMode); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestScreenEffect() + { + var type = ScreenEffectType.FadeOut; + var data = new ScreenEffect(type).Compile(); + + Span expectedData = stackalloc byte[28]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x70); // Packet ID + expectedData.Write(ref pos, (byte)0x04); // Effect +#if NO_LOCAL_INIT + expectedData.Write(ref pos, 0); + expectedData.Write(ref pos, 0); +#else + pos += 8; +#endif + + expectedData.Write(ref pos, (ushort)type); // Screen Effect Type + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, 0); + expectedData.Write(ref pos, 0); + expectedData.Write(ref pos, 0); + expectedData.Write(ref pos, 0); +#endif + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestBoltEffect() + { + IEntity entity = new Entity(0x1000, new Point3D(1000, 100, -10), Map.Felucca); + var hue = 0x1024; + var data = new BoltEffect(entity, hue).Compile(); + + Span expectedData = stackalloc byte[36]; + var pos = 0; + expectedData.Write(ref pos, (byte)0xC0); // Packet ID + expectedData.Write(ref pos, (byte)0x01); // Effect + + + expectedData.Write(ref pos, entity.Serial); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, 0); + expectedData.Write(ref pos, (ushort)0); +#else + pos += 6; +#endif + expectedData.Write(ref pos, entity.Location); + expectedData.Write(ref pos, entity.Location); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, 0); + expectedData.Write(ref pos, (ushort)0); +#else + pos += 6; +#endif + expectedData.Write(ref pos, hue); + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/EquipmentPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/EquipmentPacketTests.cs index 59e190dd8..9130751e3 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/EquipmentPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/EquipmentPacketTests.cs @@ -1,97 +1,97 @@ -using System; -using System.Buffers; -using Server.Network; -using Xunit; - -namespace Server.Tests.Network.Packets -{ - public class EquipmentPacketTests : IClassFixture - { - [Fact] - public void TestDisplayEquipmentInfo() - { - var m = new Mobile(0x1); - m.DefaultMobileInit(); - - var item = new Item(Serial.LastItem + 1); - - var info = new EquipmentInfo( - 500000, - m, - false, - new [] - { - new EquipInfoAttribute(500001, 1), - new EquipInfoAttribute(500002, 2), - new EquipInfoAttribute(500002, 3) - } - ); - - Span data = new DisplayEquipmentInfo(item, info).Compile(); - - var attrs = info.Attributes; - - int length = 17 + (info.Unidentified ? 4 : 0) + attrs.Length * 6; - if (info.Crafter != null) length += 6 + (info.Crafter.Name?.Length ?? 0); - - Span expectedData = stackalloc byte[length]; - - int pos = 0; - - expectedData.Write(ref pos, (byte)0xBF); // Packet ID - expectedData.Write(ref pos, (ushort)length); // Length - expectedData.Write(ref pos, (ushort)0x10); // Subcommand - expectedData.Write(ref pos, item.Serial); - expectedData.Write(ref pos, info.Number); - if (info.Crafter != null) - { - var name = info.Crafter.Name ?? ""; - expectedData.Write(ref pos, -3); - expectedData.Write(ref pos, (ushort)name.Length); - expectedData.WriteAscii(ref pos, name); - } - - if (info.Unidentified) expectedData.Write(ref pos, -4); - - for (var i = 0; i < attrs.Length; i++) - { - var attr = attrs[i]; - expectedData.Write(ref pos, attr.Number); - expectedData.Write(ref pos, (ushort)attr.Charges); - } - - expectedData.Write(ref pos, (-1)); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestEquipUpdate() - { - var m = new Mobile(0x1); - m.DefaultMobileInit(); - - var item = new Item(Serial.LastItem + 1) { Parent = m }; - - Span data = new EquipUpdate(item).Compile(); - - Span expectedData = stackalloc byte[15]; - int pos = 0; - expectedData.Write(ref pos, (byte)0x2E); // Packet ID - expectedData.Write(ref pos, item.Serial); - expectedData.Write(ref pos, (ushort)item.ItemID); - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); -#else - pos++; -#endif - - expectedData.Write(ref pos, (byte)item.Layer); - expectedData.Write(ref pos, item.Parent.Serial); - expectedData.Write(ref pos, (ushort)item.Hue); - - AssertThat.Equal(data, expectedData); - } - } -} +using System; +using System.Buffers; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class EquipmentPacketTests : IClassFixture + { + [Fact] + public void TestDisplayEquipmentInfo() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var item = new Item(Serial.LastItem + 1); + + var info = new EquipmentInfo( + 500000, + m, + false, + new[] + { + new EquipInfoAttribute(500001, 1), + new EquipInfoAttribute(500002, 2), + new EquipInfoAttribute(500002, 3) + } + ); + + var data = new DisplayEquipmentInfo(item, info).Compile(); + + var attrs = info.Attributes; + + var length = 17 + (info.Unidentified ? 4 : 0) + attrs.Length * 6; + if (info.Crafter != null) length += 6 + (info.Crafter.Name?.Length ?? 0); + + Span expectedData = stackalloc byte[length]; + + var pos = 0; + + expectedData.Write(ref pos, (byte)0xBF); // Packet ID + expectedData.Write(ref pos, (ushort)length); // Length + expectedData.Write(ref pos, (ushort)0x10); // Subcommand + expectedData.Write(ref pos, item.Serial); + expectedData.Write(ref pos, info.Number); + if (info.Crafter != null) + { + var name = info.Crafter.Name ?? ""; + expectedData.Write(ref pos, -3); + expectedData.Write(ref pos, (ushort)name.Length); + expectedData.WriteAscii(ref pos, name); + } + + if (info.Unidentified) expectedData.Write(ref pos, -4); + + for (var i = 0; i < attrs.Length; i++) + { + var attr = attrs[i]; + expectedData.Write(ref pos, attr.Number); + expectedData.Write(ref pos, (ushort)attr.Charges); + } + + expectedData.Write(ref pos, -1); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestEquipUpdate() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var item = new Item(Serial.LastItem + 1) { Parent = m }; + + var data = new EquipUpdate(item).Compile(); + + Span expectedData = stackalloc byte[15]; + var pos = 0; + expectedData.Write(ref pos, (byte)0x2E); // Packet ID + expectedData.Write(ref pos, item.Serial); + expectedData.Write(ref pos, (ushort)item.ItemID); + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); +#else + pos++; +#endif + + expectedData.Write(ref pos, (byte)item.Layer); + expectedData.Write(ref pos, item.Parent.Serial); + expectedData.Write(ref pos, (ushort)item.Hue); + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/GumpPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/GumpPacketTests.cs index 4c6b2cbe2..430bc2f61 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/GumpPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/GumpPacketTests.cs @@ -1,250 +1,254 @@ -using System; -using System.Buffers; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using Server.Gumps; -using Server.Network; -using Xunit; - -namespace Server.Tests.Network.Packets -{ - public class GumpPacketTests - { - [Fact] - public void TestCloseGump() - { - var typeId = 100; - var buttonId = 10; - - Span data = new CloseGump(typeId, buttonId).Compile(); - - Span expectedData = stackalloc byte[13]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xBF); // Packet ID - expectedData.Write(ref pos, (ushort)0xD); // Length - expectedData.Write(ref pos, (ushort)0x4); // Close Gump - expectedData.Write(ref pos, typeId); - expectedData.Write(ref pos, buttonId); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestDisplaySignGump() - { - Serial gumpSerial = 0x1000; - var gumpId = 100; - var unknownString = "This is an unknown string"; - var caption = "This is a caption"; - - Span data = new DisplaySignGump(gumpSerial, gumpId, unknownString, caption).Compile(); - - Span expectedData = stackalloc byte[15 + unknownString.Length + caption.Length]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x8B); - expectedData.Write(ref pos, (ushort)expectedData.Length); - expectedData.Write(ref pos, gumpSerial); - expectedData.Write(ref pos, (ushort)gumpId); - expectedData.Write(ref pos, (ushort)(unknownString.Length + 1)); - expectedData.WriteAsciiNull(ref pos, unknownString); - expectedData.Write(ref pos, (ushort)(caption.Length + 1)); - expectedData.WriteAsciiNull(ref pos, caption); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestFastGumpPacket() - { - NetState ns = new NetState(new AccountPacketTests.TestConnectionContext - { - RemoteEndPoint = IPEndPoint.Parse("127.0.0.1"), - }); - - var gump = new ResurrectGump(2); - - Span data = gump.Compile(ns).Compile(); - - Span expectedData = stackalloc byte[0x1000]; - - int pos = 0; - - expectedData[pos++] = 0xB0; // Packet ID - pos += 2; // Length - - expectedData.Write(ref pos, gump.Serial); - expectedData.Write(ref pos, gump.TypeID); - expectedData.Write(ref pos, gump.X); - expectedData.Write(ref pos, gump.Y); - pos += 2; // Layout Length - - int layoutLength = 0; - - if (!gump.Draggable) - { - expectedData.Write(ref pos, GumpUtilities.NoMoveBuffer); - layoutLength += GumpUtilities.NoMove.Length; - } - - if (!gump.Closable) - { - expectedData.Write(ref pos, GumpUtilities.NoCloseBuffer); - layoutLength += GumpUtilities.NoClose.Length; - } - - if (!gump.Disposable) - { - expectedData.Write(ref pos, GumpUtilities.NoDisposeBuffer); - layoutLength += GumpUtilities.NoDispose.Length; - } - - if (!gump.Resizable) - { - expectedData.Write(ref pos, GumpUtilities.NoResizeBuffer); - layoutLength += GumpUtilities.NoResize.Length; - } - - foreach (var entry in gump.Entries) - { - var str = entry.Compile(ns); - expectedData.WriteAscii(ref pos, str); - layoutLength += str.Length; // ASCII so 1:1 - } - - expectedData.Slice(19, 2).Write((ushort)layoutLength); - expectedData.Write(ref pos, (ushort)gump.Strings.Count); - - for (var i = 0; i < gump.Strings.Count; ++i) - expectedData.WriteBigUni(ref pos, gump.Strings[i] ?? ""); - - expectedData.Slice(1, 2).Write((ushort)pos); // Length - - expectedData = expectedData.Slice(0, pos); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestPackedGumpPacket() - { - NetState ns = new NetState(new AccountPacketTests.TestConnectionContext - { - RemoteEndPoint = IPEndPoint.Parse("127.0.0.1"), - }) - { - ProtocolChanges = ProtocolChanges.Unpack - }; - - var gump = new ResurrectGump(2); - - Span data = gump.Compile(ns).Compile(); - - Span expectedData = stackalloc byte[0x1000]; - - int pos = 0; - - expectedData[pos++] = 0xDD; // Packet ID - pos += 2; // Length - - expectedData.Write(ref pos, gump.Serial); - expectedData.Write(ref pos, gump.TypeID); - expectedData.Write(ref pos, gump.X); - expectedData.Write(ref pos, gump.Y); - - var layoutList = new List(); - int bufferLength = 1; // Null terminated - - if (!gump.Draggable) - { - layoutList.Add(GumpUtilities.NoMove); - bufferLength += GumpUtilities.NoMove.Length; - } - - if (!gump.Closable) - { - layoutList.Add(GumpUtilities.NoClose); - bufferLength += GumpUtilities.NoClose.Length; - } - - if (!gump.Disposable) - { - layoutList.Add(GumpUtilities.NoDispose); - bufferLength += GumpUtilities.NoDispose.Length; - } - - if (!gump.Resizable) - { - layoutList.Add(GumpUtilities.NoResize); - bufferLength += GumpUtilities.NoResize.Length; - } - - foreach (var entry in gump.Entries) - { - var str = entry.Compile(ns); - bufferLength += str.Length; - layoutList.Add(str); - } - - IMemoryOwner memOwner = SlabMemoryPool.Shared.Rent(bufferLength); - - Span buffer = memOwner.Memory.Span; - int bufferPos = 0; - - foreach (var layout in layoutList) - buffer.WriteAscii(ref bufferPos, layout); - -#if NO_LOCAL_INIT - buffer.Write(ref bufferPos, (byte)0); // Layout terminator -#else - bufferPos++; -#endif - - expectedData.WritePacked(ref pos, buffer.Slice(0, bufferPos)); - memOwner.Dispose(); - - expectedData.Write(ref pos, gump.Strings.Count); - bufferLength = gump.Strings.Sum(str => 2 + str.Length * 2); - memOwner = SlabMemoryPool.Shared.Rent(bufferLength); - buffer = memOwner.Memory.Span; - bufferPos = 0; - - foreach (var str in gump.Strings) - buffer.WriteBigUni(ref bufferPos, str); - - expectedData.WritePacked(ref pos, buffer.Slice(0, bufferPos)); - - // Length - expectedData.Slice(1, 2).Write((ushort)pos); - expectedData = expectedData.Slice(0, pos); - - AssertThat.Equal(data, expectedData); - } - } - - public class ResurrectGump : Gump - { - public ResurrectGump(int msg) : base(100, 0) - { - AddPage(0); - - AddBackground(0, 0, 400, 350, 2600); - - AddHtmlLocalized(0, 20, 400, 35, 1011022); //
Resurrection
- - /* It is possible for you to be resurrected here by this healer. Do you wish to try?
- * CONTINUE - You chose to try to come back to life now.
- * CANCEL - You prefer to remain a ghost for now. - */ - AddHtmlLocalized(50, 55, 300, 140, 1011023 + msg, true, true); - - AddButton(200, 227, 4005, 4007, 0); - AddHtmlLocalized(235, 230, 110, 35, 1011012); // CANCEL - - AddButton(65, 227, 4005, 4007, 1); - AddHtmlLocalized(100, 230, 110, 35, 1011011); // CONTINUE - } - } -} +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using Server.Gumps; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class GumpPacketTests + { + [Fact] + public void TestCloseGump() + { + var typeId = 100; + var buttonId = 10; + + var data = new CloseGump(typeId, buttonId).Compile(); + + Span expectedData = stackalloc byte[13]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xBF); // Packet ID + expectedData.Write(ref pos, (ushort)0xD); // Length + expectedData.Write(ref pos, (ushort)0x4); // Close Gump + expectedData.Write(ref pos, typeId); + expectedData.Write(ref pos, buttonId); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestDisplaySignGump() + { + Serial gumpSerial = 0x1000; + var gumpId = 100; + var unknownString = "This is an unknown string"; + var caption = "This is a caption"; + + var data = new DisplaySignGump(gumpSerial, gumpId, unknownString, caption).Compile(); + + Span expectedData = stackalloc byte[15 + unknownString.Length + caption.Length]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x8B); + expectedData.Write(ref pos, (ushort)expectedData.Length); + expectedData.Write(ref pos, gumpSerial); + expectedData.Write(ref pos, (ushort)gumpId); + expectedData.Write(ref pos, (ushort)(unknownString.Length + 1)); + expectedData.WriteAsciiNull(ref pos, unknownString); + expectedData.Write(ref pos, (ushort)(caption.Length + 1)); + expectedData.WriteAsciiNull(ref pos, caption); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestFastGumpPacket() + { + var ns = new NetState( + new AccountPacketTests.TestConnectionContext + { + RemoteEndPoint = IPEndPoint.Parse("127.0.0.1") + } + ); + + var gump = new ResurrectGump(2); + + var data = gump.Compile(ns).Compile(); + + Span expectedData = stackalloc byte[0x1000]; + + var pos = 0; + + expectedData[pos++] = 0xB0; // Packet ID + pos += 2; // Length + + expectedData.Write(ref pos, gump.Serial); + expectedData.Write(ref pos, gump.TypeID); + expectedData.Write(ref pos, gump.X); + expectedData.Write(ref pos, gump.Y); + pos += 2; // Layout Length + + var layoutLength = 0; + + if (!gump.Draggable) + { + expectedData.Write(ref pos, GumpUtilities.NoMoveBuffer); + layoutLength += GumpUtilities.NoMove.Length; + } + + if (!gump.Closable) + { + expectedData.Write(ref pos, GumpUtilities.NoCloseBuffer); + layoutLength += GumpUtilities.NoClose.Length; + } + + if (!gump.Disposable) + { + expectedData.Write(ref pos, GumpUtilities.NoDisposeBuffer); + layoutLength += GumpUtilities.NoDispose.Length; + } + + if (!gump.Resizable) + { + expectedData.Write(ref pos, GumpUtilities.NoResizeBuffer); + layoutLength += GumpUtilities.NoResize.Length; + } + + foreach (var entry in gump.Entries) + { + var str = entry.Compile(ns); + expectedData.WriteAscii(ref pos, str); + layoutLength += str.Length; // ASCII so 1:1 + } + + expectedData.Slice(19, 2).Write((ushort)layoutLength); + expectedData.Write(ref pos, (ushort)gump.Strings.Count); + + for (var i = 0; i < gump.Strings.Count; ++i) + expectedData.WriteBigUni(ref pos, gump.Strings[i] ?? ""); + + expectedData.Slice(1, 2).Write((ushort)pos); // Length + + expectedData = expectedData.Slice(0, pos); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestPackedGumpPacket() + { + var ns = new NetState( + new AccountPacketTests.TestConnectionContext + { + RemoteEndPoint = IPEndPoint.Parse("127.0.0.1") + } + ) + { + ProtocolChanges = ProtocolChanges.Unpack + }; + + var gump = new ResurrectGump(2); + + var data = gump.Compile(ns).Compile(); + + Span expectedData = stackalloc byte[0x1000]; + + var pos = 0; + + expectedData[pos++] = 0xDD; // Packet ID + pos += 2; // Length + + expectedData.Write(ref pos, gump.Serial); + expectedData.Write(ref pos, gump.TypeID); + expectedData.Write(ref pos, gump.X); + expectedData.Write(ref pos, gump.Y); + + var layoutList = new List(); + var bufferLength = 1; // Null terminated + + if (!gump.Draggable) + { + layoutList.Add(GumpUtilities.NoMove); + bufferLength += GumpUtilities.NoMove.Length; + } + + if (!gump.Closable) + { + layoutList.Add(GumpUtilities.NoClose); + bufferLength += GumpUtilities.NoClose.Length; + } + + if (!gump.Disposable) + { + layoutList.Add(GumpUtilities.NoDispose); + bufferLength += GumpUtilities.NoDispose.Length; + } + + if (!gump.Resizable) + { + layoutList.Add(GumpUtilities.NoResize); + bufferLength += GumpUtilities.NoResize.Length; + } + + foreach (var entry in gump.Entries) + { + var str = entry.Compile(ns); + bufferLength += str.Length; + layoutList.Add(str); + } + + var memOwner = SlabMemoryPool.Shared.Rent(bufferLength); + + var buffer = memOwner.Memory.Span; + var bufferPos = 0; + + foreach (var layout in layoutList) + buffer.WriteAscii(ref bufferPos, layout); + +#if NO_LOCAL_INIT + buffer.Write(ref bufferPos, (byte)0); // Layout terminator +#else + bufferPos++; +#endif + + expectedData.WritePacked(ref pos, buffer.Slice(0, bufferPos)); + memOwner.Dispose(); + + expectedData.Write(ref pos, gump.Strings.Count); + bufferLength = gump.Strings.Sum(str => 2 + str.Length * 2); + memOwner = SlabMemoryPool.Shared.Rent(bufferLength); + buffer = memOwner.Memory.Span; + bufferPos = 0; + + foreach (var str in gump.Strings) + buffer.WriteBigUni(ref bufferPos, str); + + expectedData.WritePacked(ref pos, buffer.Slice(0, bufferPos)); + + // Length + expectedData.Slice(1, 2).Write((ushort)pos); + expectedData = expectedData.Slice(0, pos); + + AssertThat.Equal(data, expectedData); + } + } + + public class ResurrectGump : Gump + { + public ResurrectGump(int msg) : base(100, 0) + { + AddPage(0); + + AddBackground(0, 0, 400, 350, 2600); + + AddHtmlLocalized(0, 20, 400, 35, 1011022); //
Resurrection
+ + /* It is possible for you to be resurrected here by this healer. Do you wish to try?
+ * CONTINUE - You chose to try to come back to life now.
+ * CANCEL - You prefer to remain a ghost for now. + */ + AddHtmlLocalized(50, 55, 300, 140, 1011023 + msg, true, true); + + AddButton(200, 227, 4005, 4007, 0); + AddHtmlLocalized(235, 230, 110, 35, 1011012); // CANCEL + + AddButton(65, 227, 4005, 4007, 1); + AddHtmlLocalized(100, 230, 110, 35, 1011011); // CONTINUE + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/ItemPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/ItemPacketTests.cs index 7ad5b59fb..ffa5ab808 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/ItemPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/ItemPacketTests.cs @@ -1,555 +1,573 @@ -using System; -using System.Buffers; -using Server.Items; -using Server.Network; -using Xunit; - -namespace Server.Tests.Network.Packets -{ - public class ItemPacketTests : IClassFixture - { - [Fact] - public void TestWorldItemPacket() - { - Serial serial = 0x1000; - var itemId = 1; - - // Move to fixture - TileData.ItemTable[itemId] = new ItemData( - "Test Item Data", TileFlag.Generic, 1, 1, 1, 1, 1 - ); - - Item item = new Item(serial) - { - ItemID = itemId, - Hue = 0x1024, - Amount = 10, - Location = new Point3D(1000, 100, -10), - Direction = Direction.Left - }; - - Span data = new WorldItem(item).Compile(); - - Span expectedData = stackalloc byte[20]; // Max size - int pos = 0; - - expectedData.Write(ref pos, (byte)0x1A); - pos += 2; // Length - - if (item.Amount != 0) - expectedData.Write(ref pos, serial | 0x80000000); - else - expectedData.Write(ref pos, serial & 0x7FFFFFFF); - - if (item is BaseMulti) - expectedData.Write(ref pos, (ushort)(item.ItemID | 0x4000)); - else - expectedData.Write(ref pos, (ushort)item.ItemID); - - if (item.Amount != 0) - expectedData.Write(ref pos, (ushort)item.Amount); - - byte direction = (byte)item.Direction; - ushort x = (ushort)(item.X & 0x7FFF); - - if (direction != 0) - x |= 0x8000; - - expectedData.Write(ref pos, x); - - int hue = item.Hue; - int flags = item.GetPacketFlags(); - ushort y = (ushort)(item.Y & 0x3FFF); - - if (hue != 0) y |= 0x8000; - if (flags != 0) y |= 0x4000; - - expectedData.Write(ref pos, y); - - if (direction != 0) - expectedData.Write(ref pos, direction); - - expectedData.Write(ref pos, (byte)item.Z); - - if (hue != 0) - expectedData.Write(ref pos, (ushort)hue); - - if (flags != 0) - expectedData.Write(ref pos, (byte)flags); - - // Length - expectedData.Slice(1, 2).Write((ushort)pos); - - // Slice the data to match in size - data = data.Slice(0, pos); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestWorldItemSAPacket() - { - Serial serial = 0x1000; - ushort itemId = 1; - - // Move to fixture - TileData.ItemTable[itemId] = new ItemData( - "Test Item Data", TileFlag.Generic, 1, 1, 1, 1, 1 - ); - - Item item = new Item(serial) - { - ItemID = itemId, - Hue = 0x1024, - Amount = 10, - Location = new Point3D(1000, 100, -10) - }; - - var loc = item.Location; - var isMulti = item is BaseMulti; - - Span data = new WorldItemSA(item).Compile(); - - Span expectedData = stackalloc byte[24]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xF3); // Packet ID - expectedData.Write(ref pos, (ushort)0x1); - expectedData.Write(ref pos, (byte)(isMulti ? 0x2 : 0x00)); // Item Type (Regular, or Multi) - expectedData.Write(ref pos, item.Serial); - expectedData.Write(ref pos, (ushort)(item.ItemID & (isMulti ? 0x3FFF : 0xFFFF))); - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0) -#else - pos++; -#endif - - expectedData.Write(ref pos, (ushort)item.Amount); // Amount (min?) - expectedData.Write(ref pos, (ushort)item.Amount); // Amount (max?) - expectedData.Write(ref pos, loc); // X, Y, Z - expectedData.Write(ref pos, (byte)item.Light); // Light - expectedData.Write(ref pos, (ushort)item.Hue); // Hue - expectedData.Write(ref pos, (byte)item.GetPacketFlags()); // Flags - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestWorldItemHSPacket() - { - Serial serial = 0x1000; - var itemId = 1; - - // Move to fixture - TileData.ItemTable[itemId] = new ItemData( - "Test Item Data", TileFlag.Generic, 1, 1, 1, 1, 1 - ); - - Item item = new Item(serial) - { - ItemID = itemId, - Hue = 0x1024, - Amount = 10, - Location = new Point3D(1000, 100, -10) - }; - - var loc = item.Location; - var isMulti = item is BaseMulti; - - Span data = new WorldItemHS(item).Compile(); - - Span expectedData = stackalloc byte[26]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xF3); // Packet ID - expectedData.Write(ref pos, (ushort)0x1); - expectedData.Write(ref pos, (byte)(isMulti ? 0x2 : 0x00)); // Item Type (Regular, or Multi) - expectedData.Write(ref pos, item.Serial); - expectedData.Write(ref pos, (ushort)(item.ItemID & (isMulti ? 0x3FFF : 0xFFFF))); - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); -#else - pos++; -#endif - - expectedData.Write(ref pos, (ushort)item.Amount); // Amount (min?) - expectedData.Write(ref pos, (ushort)item.Amount); // Amount (max?) - expectedData.Write(ref pos, loc); // X, Y, Z - expectedData.Write(ref pos, (byte)item.Light); // Light - expectedData.Write(ref pos, (ushort)item.Hue); // Hue - expectedData.Write(ref pos, (byte)item.GetPacketFlags()); // Flags - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (ushort)0); // ?? -#endif - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestContainerDisplay() - { - Serial serial = 0x1000; - ushort gumpId = 100; - - Span data = new ContainerDisplay(serial, gumpId).Compile(); - - Span expectedData = stackalloc byte[7]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x24); // Packet ID - expectedData.Write(ref pos, serial); - expectedData.Write(ref pos, gumpId); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestContainerDisplayHS() - { - Serial serial = 0x1000; - ushort gumpId = 100; - - Span data = new ContainerDisplayHS(serial, gumpId).Compile(); - - Span expectedData = stackalloc byte[9]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x24); // Packet ID - expectedData.Write(ref pos, serial); - expectedData.Write(ref pos, gumpId); - expectedData.Write(ref pos, (ushort)0x7D); // Max Items? - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestDisplaySpellbook() - { - Serial serial = 0x1000; - - Span data = new DisplaySpellbook(serial).Compile(); - - Span expectedData = stackalloc byte[7]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x24); // Packet ID - expectedData.Write(ref pos, serial); - expectedData.Write(ref pos, (ushort)0xFFFF); // Gump ID - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestDisplaySpellbookHS() - { - Serial serial = 0x1000; - - Span data = new DisplaySpellbookHS(serial).Compile(); - - Span expectedData = stackalloc byte[9]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x24); // Packet ID - expectedData.Write(ref pos, serial); - expectedData.Write(ref pos, (ushort)0xFFFF); // Gump ID - expectedData.Write(ref pos, (ushort)0x7D); // Max Items? - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestNewSpellbookContent() - { - Serial serial = 0x1000; - ushort graphic = 100; - ushort offset = 10; - ulong content = 0x123456789ABCDEF0; - - Span data = new NewSpellbookContent(serial, graphic, offset, content).Compile(); - - Span expectedData = stackalloc byte[23]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xBF); // Packet ID - expectedData.Write(ref pos, (ushort)0x17); // Length - expectedData.Write(ref pos, (ushort)0x1B); // Sub-packet - expectedData.Write(ref pos, (ushort)0x1); // Command - expectedData.Write(ref pos, serial); - expectedData.Write(ref pos, graphic); - expectedData.Write(ref pos, offset); - expectedData.WriteLE(ref pos, content); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestSpellbookContent() - { - Serial serial = 0x1000; - ushort offset = 10; - ulong content = 0x123456789ABCDEF0; - - Span data = new SpellbookContent(serial, offset, content).Compile(); - - Span expectedData = stackalloc byte[5 + 64 * 19]; // Max size - int pos = 0; - - expectedData.Write(ref pos, (byte)0x3C); // Packet ID - pos += 4; // Length + spell count - - ushort count = 0; - - for (var i = 0; i < 64; i++) - if ((content & (1ul << i)) != 0) - { - expectedData.Write(ref pos, 0x7FFFFFFF - i); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (ushort)0); - expectedData.Write(ref pos, (byte)0); -#else - pos += 3; -#endif - expectedData.Write(ref pos, (ushort)(i + offset)); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, 0); // X. Y -#else - pos += 4; -#endif - expectedData.Write(ref pos, serial); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (ushort)0); -#else - pos += 2; -#endif - count++; - } - - expectedData.Slice(1, 2).Write((ushort)pos); // Length - expectedData.Slice(3, 2).Write(count); // Count - - expectedData = expectedData.Slice(0, pos); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestSpellbookContent6017() - { - Serial serial = 0x1000; - ushort offset = 10; - ulong content = 0x123456789ABCDEF0; - - Span data = new SpellbookContent6017(serial, offset, content).Compile(); - - Span expectedData = stackalloc byte[5 + 64 * 20]; // Max size - int pos = 0; - - expectedData.Write(ref pos, (byte)0x3C); // Packet ID - pos += 4; // Length + spell count - - ushort count = 0; - - for (var i = 0; i < 64; i++) - if ((content & (1ul << i)) != 0) - { - expectedData.Write(ref pos, 0x7FFFFFFF - i); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (ushort)0); - expectedData.Write(ref pos, (byte)0); -#else - pos += 3; -#endif - expectedData.Write(ref pos, (ushort)(i + offset)); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, 0); // X. Y - expectedData.Write(ref pos, (byte)0); // Grid Location -#else - pos += 5; -#endif - expectedData.Write(ref pos, serial); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (ushort)0); -#else - pos += 2; -#endif - count++; - } - - expectedData.Slice(1, 2).Write((ushort)pos); // Length - expectedData.Slice(3, 2).Write(count); // Count - - expectedData = expectedData.Slice(0, pos); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestContainerContentUpdate() - { - Serial serial = 0x1; - Item item = new Item(serial); - - Span data = new ContainerContentUpdate(item).Compile(); - - Span expectedData = stackalloc byte[20]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x25); // Packet ID - expectedData.Write(ref pos, item.Serial); - expectedData.Write(ref pos, (ushort)item.ItemID); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); // ItemID offset -#else - pos++; -#endif - expectedData.Write(ref pos, (ushort)Math.Min(item.Amount, ushort.MaxValue)); - expectedData.Write(ref pos, (ushort)item.X); - expectedData.Write(ref pos, (ushort)item.Y); - expectedData.Write(ref pos, item.Parent?.Serial ?? Serial.Zero); - expectedData.Write(ref pos, (ushort)(item.QuestItem ? Item.QuestItemHue : item.Hue)); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestContainerContentUpdate6017() - { - Serial serial = 0x1; - Item item = new Item(serial); - - Span data = new ContainerContentUpdate6017(item).Compile(); - - Span expectedData = stackalloc byte[21]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x25); // Packet ID - expectedData.Write(ref pos, item.Serial); - expectedData.Write(ref pos, (ushort)item.ItemID); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); // ItemID offset -#else - pos++; -#endif - expectedData.Write(ref pos, (ushort)Math.Min(item.Amount, ushort.MaxValue)); - expectedData.Write(ref pos, (ushort)item.X); - expectedData.Write(ref pos, (ushort)item.Y); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); // Grid Location? -#else - pos++; -#endif - expectedData.Write(ref pos, item.Parent?.Serial ?? Serial.Zero); - expectedData.Write(ref pos, (ushort)(item.QuestItem ? Item.QuestItemHue : item.Hue)); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestContainerContent() - { - Container cont = new Container(Serial.LastItem + 1); - cont.AddItem(new Item(Serial.LastItem + 2)); - - var m = new Mobile(0x1); - m.DefaultMobileInit(); - - Span data = new ContainerContent(m, cont).Compile(); - - Span expectedData = stackalloc byte[5 + cont.Items.Count * 19]; // Max Size - int pos = 0; - - expectedData.Write(ref pos, (byte)0x3C); // Packet ID - pos += 4; // Length + Count - - ushort count = 0; - - int itemCount = cont.Items.Count; - for (var i = 0; i < itemCount; i++) - { - var child = cont.Items[i]; - if (child.Deleted || !m.CanSee(child)) - continue; - - expectedData.Write(ref pos, child.Serial); - expectedData.Write(ref pos, (ushort)child.ItemID); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); // ItemID offset -#else - pos++; -#endif - expectedData.Write(ref pos, (ushort)Math.Min(child.Amount, ushort.MaxValue)); - expectedData.Write(ref pos, (ushort)child.X); - expectedData.Write(ref pos, (ushort)child.Y); - expectedData.Write(ref pos, cont.Serial); - expectedData.Write(ref pos, (ushort)(child.QuestItem ? Item.QuestItemHue : child.Hue)); - - count++; - } - - expectedData.Slice(1, 2).Write((ushort)pos); // Length - expectedData.Slice(3, 2).Write(count); // Count - - expectedData = expectedData.Slice(0, pos); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestContainerContent6017() - { - Container cont = new Container(Serial.LastItem + 1); - cont.AddItem(new Item(Serial.LastItem + 2)); - - var m = new Mobile(0x1); - m.DefaultMobileInit(); - - Span data = new ContainerContent6017(m, cont).Compile(); - - Span expectedData = stackalloc byte[5 + cont.Items.Count * 20]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x3C); // Packet ID - pos += 4; // Length + Count - - ushort count = 0; - - int itemCount = cont.Items.Count; - for (var i = 0; i < itemCount; i++) - { - var child = cont.Items[i]; - if (child.Deleted || !m.CanSee(child)) - continue; - - expectedData.Write(ref pos, child.Serial); - expectedData.Write(ref pos, (ushort)child.ItemID); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); // ItemID offset -#else - pos++; -#endif - expectedData.Write(ref pos, (ushort)Math.Min(child.Amount, ushort.MaxValue)); - expectedData.Write(ref pos, (ushort)child.X); - expectedData.Write(ref pos, (ushort)child.Y); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); // Grid Location? -#else - pos++; -#endif - expectedData.Write(ref pos, cont.Serial); - expectedData.Write(ref pos, (ushort)(child.QuestItem ? Item.QuestItemHue : child.Hue)); - - count++; - } - - expectedData.Slice(1, 2).Write((ushort)pos); // Length - expectedData.Slice(3, 2).Write(count); // Count - - expectedData = expectedData.Slice(0, pos); - - AssertThat.Equal(data, expectedData); - } - } -} +using System; +using System.Buffers; +using Server.Items; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class ItemPacketTests : IClassFixture + { + [Fact] + public void TestWorldItemPacket() + { + Serial serial = 0x1000; + var itemId = 1; + + // Move to fixture + TileData.ItemTable[itemId] = new ItemData( + "Test Item Data", + TileFlag.Generic, + 1, + 1, + 1, + 1, + 1 + ); + + var item = new Item(serial) + { + ItemID = itemId, + Hue = 0x1024, + Amount = 10, + Location = new Point3D(1000, 100, -10), + Direction = Direction.Left + }; + + var data = new WorldItem(item).Compile(); + + Span expectedData = stackalloc byte[20]; // Max size + var pos = 0; + + expectedData.Write(ref pos, (byte)0x1A); + pos += 2; // Length + + if (item.Amount != 0) + expectedData.Write(ref pos, serial | 0x80000000); + else + expectedData.Write(ref pos, serial & 0x7FFFFFFF); + + if (item is BaseMulti) + expectedData.Write(ref pos, (ushort)(item.ItemID | 0x4000)); + else + expectedData.Write(ref pos, (ushort)item.ItemID); + + if (item.Amount != 0) + expectedData.Write(ref pos, (ushort)item.Amount); + + var direction = (byte)item.Direction; + var x = (ushort)(item.X & 0x7FFF); + + if (direction != 0) + x |= 0x8000; + + expectedData.Write(ref pos, x); + + var hue = item.Hue; + var flags = item.GetPacketFlags(); + var y = (ushort)(item.Y & 0x3FFF); + + if (hue != 0) y |= 0x8000; + if (flags != 0) y |= 0x4000; + + expectedData.Write(ref pos, y); + + if (direction != 0) + expectedData.Write(ref pos, direction); + + expectedData.Write(ref pos, (byte)item.Z); + + if (hue != 0) + expectedData.Write(ref pos, (ushort)hue); + + if (flags != 0) + expectedData.Write(ref pos, (byte)flags); + + // Length + expectedData.Slice(1, 2).Write((ushort)pos); + + // Slice the data to match in size + data = data.Slice(0, pos); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestWorldItemSAPacket() + { + Serial serial = 0x1000; + ushort itemId = 1; + + // Move to fixture + TileData.ItemTable[itemId] = new ItemData( + "Test Item Data", + TileFlag.Generic, + 1, + 1, + 1, + 1, + 1 + ); + + var item = new Item(serial) + { + ItemID = itemId, + Hue = 0x1024, + Amount = 10, + Location = new Point3D(1000, 100, -10) + }; + + var loc = item.Location; + var isMulti = item is BaseMulti; + + var data = new WorldItemSA(item).Compile(); + + Span expectedData = stackalloc byte[24]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xF3); // Packet ID + expectedData.Write(ref pos, (ushort)0x1); + expectedData.Write(ref pos, (byte)(isMulti ? 0x2 : 0x00)); // Item Type (Regular, or Multi) + expectedData.Write(ref pos, item.Serial); + expectedData.Write(ref pos, (ushort)(item.ItemID & (isMulti ? 0x3FFF : 0xFFFF))); + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0) +#else + pos++; +#endif + + expectedData.Write(ref pos, (ushort)item.Amount); // Amount (min?) + expectedData.Write(ref pos, (ushort)item.Amount); // Amount (max?) + expectedData.Write(ref pos, loc); // X, Y, Z + expectedData.Write(ref pos, (byte)item.Light); // Light + expectedData.Write(ref pos, (ushort)item.Hue); // Hue + expectedData.Write(ref pos, (byte)item.GetPacketFlags()); // Flags + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestWorldItemHSPacket() + { + Serial serial = 0x1000; + var itemId = 1; + + // Move to fixture + TileData.ItemTable[itemId] = new ItemData( + "Test Item Data", + TileFlag.Generic, + 1, + 1, + 1, + 1, + 1 + ); + + var item = new Item(serial) + { + ItemID = itemId, + Hue = 0x1024, + Amount = 10, + Location = new Point3D(1000, 100, -10) + }; + + var loc = item.Location; + var isMulti = item is BaseMulti; + + var data = new WorldItemHS(item).Compile(); + + Span expectedData = stackalloc byte[26]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xF3); // Packet ID + expectedData.Write(ref pos, (ushort)0x1); + expectedData.Write(ref pos, (byte)(isMulti ? 0x2 : 0x00)); // Item Type (Regular, or Multi) + expectedData.Write(ref pos, item.Serial); + expectedData.Write(ref pos, (ushort)(item.ItemID & (isMulti ? 0x3FFF : 0xFFFF))); + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); +#else + pos++; +#endif + + expectedData.Write(ref pos, (ushort)item.Amount); // Amount (min?) + expectedData.Write(ref pos, (ushort)item.Amount); // Amount (max?) + expectedData.Write(ref pos, loc); // X, Y, Z + expectedData.Write(ref pos, (byte)item.Light); // Light + expectedData.Write(ref pos, (ushort)item.Hue); // Hue + expectedData.Write(ref pos, (byte)item.GetPacketFlags()); // Flags + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (ushort)0); // ?? +#endif + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestContainerDisplay() + { + Serial serial = 0x1000; + ushort gumpId = 100; + + var data = new ContainerDisplay(serial, gumpId).Compile(); + + Span expectedData = stackalloc byte[7]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x24); // Packet ID + expectedData.Write(ref pos, serial); + expectedData.Write(ref pos, gumpId); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestContainerDisplayHS() + { + Serial serial = 0x1000; + ushort gumpId = 100; + + var data = new ContainerDisplayHS(serial, gumpId).Compile(); + + Span expectedData = stackalloc byte[9]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x24); // Packet ID + expectedData.Write(ref pos, serial); + expectedData.Write(ref pos, gumpId); + expectedData.Write(ref pos, (ushort)0x7D); // Max Items? + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestDisplaySpellbook() + { + Serial serial = 0x1000; + + var data = new DisplaySpellbook(serial).Compile(); + + Span expectedData = stackalloc byte[7]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x24); // Packet ID + expectedData.Write(ref pos, serial); + expectedData.Write(ref pos, (ushort)0xFFFF); // Gump ID + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestDisplaySpellbookHS() + { + Serial serial = 0x1000; + + var data = new DisplaySpellbookHS(serial).Compile(); + + Span expectedData = stackalloc byte[9]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x24); // Packet ID + expectedData.Write(ref pos, serial); + expectedData.Write(ref pos, (ushort)0xFFFF); // Gump ID + expectedData.Write(ref pos, (ushort)0x7D); // Max Items? + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestNewSpellbookContent() + { + Serial serial = 0x1000; + ushort graphic = 100; + ushort offset = 10; + ulong content = 0x123456789ABCDEF0; + + var data = new NewSpellbookContent(serial, graphic, offset, content).Compile(); + + Span expectedData = stackalloc byte[23]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xBF); // Packet ID + expectedData.Write(ref pos, (ushort)0x17); // Length + expectedData.Write(ref pos, (ushort)0x1B); // Sub-packet + expectedData.Write(ref pos, (ushort)0x1); // Command + expectedData.Write(ref pos, serial); + expectedData.Write(ref pos, graphic); + expectedData.Write(ref pos, offset); + expectedData.WriteLE(ref pos, content); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestSpellbookContent() + { + Serial serial = 0x1000; + ushort offset = 10; + ulong content = 0x123456789ABCDEF0; + + var data = new SpellbookContent(serial, offset, content).Compile(); + + Span expectedData = stackalloc byte[5 + 64 * 19]; // Max size + var pos = 0; + + expectedData.Write(ref pos, (byte)0x3C); // Packet ID + pos += 4; // Length + spell count + + ushort count = 0; + + for (var i = 0; i < 64; i++) + if ((content & (1ul << i)) != 0) + { + expectedData.Write(ref pos, 0x7FFFFFFF - i); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (ushort)0); + expectedData.Write(ref pos, (byte)0); +#else + pos += 3; +#endif + expectedData.Write(ref pos, (ushort)(i + offset)); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, 0); // X. Y +#else + pos += 4; +#endif + expectedData.Write(ref pos, serial); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (ushort)0); +#else + pos += 2; +#endif + count++; + } + + expectedData.Slice(1, 2).Write((ushort)pos); // Length + expectedData.Slice(3, 2).Write(count); // Count + + expectedData = expectedData.Slice(0, pos); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestSpellbookContent6017() + { + Serial serial = 0x1000; + ushort offset = 10; + ulong content = 0x123456789ABCDEF0; + + var data = new SpellbookContent6017(serial, offset, content).Compile(); + + Span expectedData = stackalloc byte[5 + 64 * 20]; // Max size + var pos = 0; + + expectedData.Write(ref pos, (byte)0x3C); // Packet ID + pos += 4; // Length + spell count + + ushort count = 0; + + for (var i = 0; i < 64; i++) + if ((content & (1ul << i)) != 0) + { + expectedData.Write(ref pos, 0x7FFFFFFF - i); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (ushort)0); + expectedData.Write(ref pos, (byte)0); +#else + pos += 3; +#endif + expectedData.Write(ref pos, (ushort)(i + offset)); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, 0); // X. Y + expectedData.Write(ref pos, (byte)0); // Grid Location +#else + pos += 5; +#endif + expectedData.Write(ref pos, serial); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (ushort)0); +#else + pos += 2; +#endif + count++; + } + + expectedData.Slice(1, 2).Write((ushort)pos); // Length + expectedData.Slice(3, 2).Write(count); // Count + + expectedData = expectedData.Slice(0, pos); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestContainerContentUpdate() + { + Serial serial = 0x1; + var item = new Item(serial); + + var data = new ContainerContentUpdate(item).Compile(); + + Span expectedData = stackalloc byte[20]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x25); // Packet ID + expectedData.Write(ref pos, item.Serial); + expectedData.Write(ref pos, (ushort)item.ItemID); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); // ItemID offset +#else + pos++; +#endif + expectedData.Write(ref pos, (ushort)Math.Min(item.Amount, ushort.MaxValue)); + expectedData.Write(ref pos, (ushort)item.X); + expectedData.Write(ref pos, (ushort)item.Y); + expectedData.Write(ref pos, item.Parent?.Serial ?? Serial.Zero); + expectedData.Write(ref pos, (ushort)(item.QuestItem ? Item.QuestItemHue : item.Hue)); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestContainerContentUpdate6017() + { + Serial serial = 0x1; + var item = new Item(serial); + + var data = new ContainerContentUpdate6017(item).Compile(); + + Span expectedData = stackalloc byte[21]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x25); // Packet ID + expectedData.Write(ref pos, item.Serial); + expectedData.Write(ref pos, (ushort)item.ItemID); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); // ItemID offset +#else + pos++; +#endif + expectedData.Write(ref pos, (ushort)Math.Min(item.Amount, ushort.MaxValue)); + expectedData.Write(ref pos, (ushort)item.X); + expectedData.Write(ref pos, (ushort)item.Y); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); // Grid Location? +#else + pos++; +#endif + expectedData.Write(ref pos, item.Parent?.Serial ?? Serial.Zero); + expectedData.Write(ref pos, (ushort)(item.QuestItem ? Item.QuestItemHue : item.Hue)); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestContainerContent() + { + var cont = new Container(Serial.LastItem + 1); + cont.AddItem(new Item(Serial.LastItem + 2)); + + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var data = new ContainerContent(m, cont).Compile(); + + Span expectedData = stackalloc byte[5 + cont.Items.Count * 19]; // Max Size + var pos = 0; + + expectedData.Write(ref pos, (byte)0x3C); // Packet ID + pos += 4; // Length + Count + + ushort count = 0; + + var itemCount = cont.Items.Count; + for (var i = 0; i < itemCount; i++) + { + var child = cont.Items[i]; + if (child.Deleted || !m.CanSee(child)) + continue; + + expectedData.Write(ref pos, child.Serial); + expectedData.Write(ref pos, (ushort)child.ItemID); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); // ItemID offset +#else + pos++; +#endif + expectedData.Write(ref pos, (ushort)Math.Min(child.Amount, ushort.MaxValue)); + expectedData.Write(ref pos, (ushort)child.X); + expectedData.Write(ref pos, (ushort)child.Y); + expectedData.Write(ref pos, cont.Serial); + expectedData.Write(ref pos, (ushort)(child.QuestItem ? Item.QuestItemHue : child.Hue)); + + count++; + } + + expectedData.Slice(1, 2).Write((ushort)pos); // Length + expectedData.Slice(3, 2).Write(count); // Count + + expectedData = expectedData.Slice(0, pos); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestContainerContent6017() + { + var cont = new Container(Serial.LastItem + 1); + cont.AddItem(new Item(Serial.LastItem + 2)); + + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var data = new ContainerContent6017(m, cont).Compile(); + + Span expectedData = stackalloc byte[5 + cont.Items.Count * 20]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x3C); // Packet ID + pos += 4; // Length + Count + + ushort count = 0; + + var itemCount = cont.Items.Count; + for (var i = 0; i < itemCount; i++) + { + var child = cont.Items[i]; + if (child.Deleted || !m.CanSee(child)) + continue; + + expectedData.Write(ref pos, child.Serial); + expectedData.Write(ref pos, (ushort)child.ItemID); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); // ItemID offset +#else + pos++; +#endif + expectedData.Write(ref pos, (ushort)Math.Min(child.Amount, ushort.MaxValue)); + expectedData.Write(ref pos, (ushort)child.X); + expectedData.Write(ref pos, (ushort)child.Y); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); // Grid Location? +#else + pos++; +#endif + expectedData.Write(ref pos, cont.Serial); + expectedData.Write(ref pos, (ushort)(child.QuestItem ? Item.QuestItemHue : child.Hue)); + + count++; + } + + expectedData.Slice(1, 2).Write((ushort)pos); // Length + expectedData.Slice(3, 2).Write(count); // Count + + expectedData = expectedData.Slice(0, pos); + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/LightPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/LightPacketTests.cs index 959cb3532..e986508e7 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/LightPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/LightPacketTests.cs @@ -1,42 +1,42 @@ -using System; -using System.Buffers; -using Server.Network; -using Xunit; - -namespace Server.Tests.Network.Packets -{ - public class LightPacketTests - { - [Fact] - public void TestGlobalLightLevel() - { - byte lightLevel = 5; - Span data = new GlobalLightLevel(lightLevel).Compile(); - - Span expectedData = stackalloc byte[2]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x4F); // Packet ID - expectedData.Write(ref pos, lightLevel); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestPersonalLightLevel() - { - Serial serial = 0x1; - byte lightLevel = 5; - Span data = new PersonalLightLevel(serial, lightLevel).Compile(); - - Span expectedData = stackalloc byte[6]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x4E); // Packet ID - expectedData.Write(ref pos, serial); - expectedData.Write(ref pos, lightLevel); - - AssertThat.Equal(data, expectedData); - } - } -} +using System; +using System.Buffers; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class LightPacketTests + { + [Fact] + public void TestGlobalLightLevel() + { + byte lightLevel = 5; + var data = new GlobalLightLevel(lightLevel).Compile(); + + Span expectedData = stackalloc byte[2]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x4F); // Packet ID + expectedData.Write(ref pos, lightLevel); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestPersonalLightLevel() + { + Serial serial = 0x1; + byte lightLevel = 5; + var data = new PersonalLightLevel(serial, lightLevel).Compile(); + + Span expectedData = stackalloc byte[6]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x4E); // Packet ID + expectedData.Write(ref pos, serial); + expectedData.Write(ref pos, lightLevel); + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/MapPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/MapPacketTests.cs index 8ceaacd53..660a4aa66 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/MapPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/MapPacketTests.cs @@ -1,62 +1,62 @@ -using System; -using Server.Network; -using Xunit; - -namespace Server.Tests.Network.Packets -{ - public class MapPatchesTests : IClassFixture - { - [Fact] - public void TestMapPatches() - { - Span data = new MapPatches().Compile(); - - Span expectedData = stackalloc byte[] - { - 0xBF, // Packet ID - 0x00, 0x29, // Length - 0x00, 0x18, // Sub-packet - 0x00, 0x00, 0x00, 0x04, // 4 maps - 0x00, 0x00, 0x00, 0x00, // Felucca - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // Trammel - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // Ilshenar - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // Malas - 0x00, 0x00, 0x00, 0x00 - }; - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestInvalidMapEnable() - { - Span data = new InvalidMapEnable().Compile(); - - Span expectedData = stackalloc byte[] - { - 0xC6 // Packet ID - }; - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestMapChange() - { - Span data = new MapChange(Map.Felucca).Compile(); - - Span expectedData = stackalloc byte[] - { - 0xBF, // Packet ID - 0x00, 0x06, // Length - 0x00, 0x08, // Sub-packet - 0x00 // Felucca - }; - - AssertThat.Equal(data, expectedData); - } - } -} +using System; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class MapPatchesTests : IClassFixture + { + [Fact] + public void TestMapPatches() + { + var data = new MapPatches().Compile(); + + Span expectedData = stackalloc byte[] + { + 0xBF, // Packet ID + 0x00, 0x29, // Length + 0x00, 0x18, // Sub-packet + 0x00, 0x00, 0x00, 0x04, // 4 maps + 0x00, 0x00, 0x00, 0x00, // Felucca + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, // Trammel + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, // Ilshenar + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, // Malas + 0x00, 0x00, 0x00, 0x00 + }; + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestInvalidMapEnable() + { + var data = new InvalidMapEnable().Compile(); + + Span expectedData = stackalloc byte[] + { + 0xC6 // Packet ID + }; + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestMapChange() + { + var data = new MapChange(Map.Felucca).Compile(); + + Span expectedData = stackalloc byte[] + { + 0xBF, // Packet ID + 0x00, 0x06, // Length + 0x00, 0x08, // Sub-packet + 0x00 // Felucca + }; + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/MenuPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/MenuPacketTests.cs index 4bb7c32eb..63ad0997c 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/MenuPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/MenuPacketTests.cs @@ -1,240 +1,240 @@ -using System; -using System.Buffers; -using System.Collections.Generic; -using System.Linq; -using Server.ContextMenus; -using Server.Menus.ItemLists; -using Server.Menus.Questions; -using Server.Network; -using Xunit; - -namespace Server.Tests.Network.Packets -{ - internal class ContextMenuItem : Item - { - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - list.Add(new ContextMenuEntry(500000)); - list.Add(new ContextMenuEntry(500001)); - list.Add(new ContextMenuEntry(500002)); - } - - public ContextMenuItem(Serial serial) : base(serial) - { - } - } - - public class MenuPacketTests : IClassFixture - { - [Fact] - public void TestDisplayItemListMenu() - { - var menu = new ItemListMenu( - "Which item would you choose?", - new[] - { - new ItemListEntry("Item 1", 0x01), - new ItemListEntry("Item 2", 0x100), - new ItemListEntry("Item 3", 0x1000, 250) - } - ); - - Span data = new DisplayItemListMenu(menu).Compile(); - - string question = menu.Question; - int questionLength = Math.Min(255, question.Length); - int entriesCount = 0; - int length = 11 + questionLength; - - foreach (var entry in menu.Entries) - { - length += 5 + entry.Name.Length; - if (entriesCount == 255) - break; - - entriesCount++; - } - - Span expectedData = stackalloc byte[length]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x7C); // Packet ID - expectedData.Write(ref pos, (ushort)length); - expectedData.Write(ref pos, menu.Serial); - expectedData.Write(ref pos, (ushort)0x00); - expectedData.Write(ref pos, (byte)questionLength); - expectedData.WriteAscii(ref pos, question, 255); - expectedData.Write(ref pos, (byte)entriesCount); - for (int i = 0; i < entriesCount; i++) - { - var entry = menu.Entries[i]; - expectedData.Write(ref pos, (ushort)entry.ItemID); - expectedData.Write(ref pos, (ushort)entry.Hue); - string name = entry.Name?.Trim() ?? ""; - expectedData.Write(ref pos, (byte)Math.Min(255, name.Length)); - expectedData.WriteAscii(ref pos, name, 255); - } - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestDisplayQuestionMenu() - { - var menu = new QuestionMenu( - "Which option would you choose?", - new[] - { - "Option 1", - "Option 2", - "Option 3" - } - ); - - Span data = new DisplayQuestionMenu(menu).Compile(); - - string question = menu.Question; - int questionLength = Math.Min(255, question.Length); - int answersCount = 0; - int length = 11 + questionLength; - - foreach (var answer in menu.Answers) - { - length += 5 + answer.Length; - if (answersCount == 255) - break; - - answersCount++; - } - - Span expectedData = stackalloc byte[length]; - - int pos = 0; - - expectedData.Write(ref pos, (byte)0x7C); // Packet ID - expectedData.Write(ref pos, (ushort)length); - expectedData.Write(ref pos, menu.Serial); - expectedData.Write(ref pos, (ushort)0x00); - expectedData.Write(ref pos, (byte)question.Length); - expectedData.WriteAscii(ref pos, question, 255); - expectedData.Write(ref pos, (byte)answersCount); - for (int i = 0; i < answersCount; i++) - { - var answer = menu.Answers[i]; -#if NO_LOCAL_INIT - expectedData.Write(ref pos, 0); -#else - pos += 4; -#endif - expectedData.Write(ref pos, (byte)Math.Min(255, answer.Length)); - expectedData.WriteAscii(ref pos, answer, 255); - } - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestDisplayContextMenu() - { - var m = new Mobile(0x1); - m.DefaultMobileInit(); - - var item = new ContextMenuItem(Serial.LastItem + 1); - var menu = new ContextMenu(m, item); - - Span data = new DisplayContextMenu(menu).Compile(); - - int length = 12 + menu.Entries.Length * 8; - - Span expectedData = stackalloc byte[length]; - - int pos = 0; - expectedData.Write(ref pos, (byte)0xBF); // Packet ID - expectedData.Write(ref pos, (ushort)length); // Length - expectedData.Write(ref pos, (ushort)0x14); // Command - expectedData.Write(ref pos, (ushort)0x02); // Subcommand - expectedData.Write(ref pos, menu.Target.Serial); - var entries = menu.Entries; - - expectedData.Write(ref pos, (byte)entries.Length); - - for (int i = 0; i < entries.Length; i++) - { - var entry = entries[i]; - expectedData.Write(ref pos, entry.Number); - expectedData.Write(ref pos, (ushort)i); - - var flags = entry.Flags; - - var range = entry.Range; - - if (range == -1) - range = 18; - - if (!(entry.Enabled && menu.From.InRange(item.GetWorldLocation(), range))) - flags |= CMEFlags.Disabled; - - expectedData.Write(ref pos, (ushort)flags); - } - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestDisplayContextMenuOld() - { - var m = new Mobile(0x1); - m.DefaultMobileInit(); - - var item = new ContextMenuItem(Serial.LastItem + 1); - var menu = new ContextMenu(m, item); - - Span data = new DisplayContextMenuOld(menu).Compile(); - - int length = 12 + menu.Entries.Sum(entry => 6 + ((entry.Color & 0xFFFF) != 0xFFFF ? 2 : 0)); - - Span expectedData = stackalloc byte[length]; - - int pos = 0; - expectedData.Write(ref pos, (byte)0xBF); // Packet ID - expectedData.Write(ref pos, (ushort)length); // Length - expectedData.Write(ref pos, (ushort)0x14); // Command - expectedData.Write(ref pos, (ushort)0x01); // Subcommand - expectedData.Write(ref pos, menu.Target.Serial); - var entries = menu.Entries; - - expectedData.Write(ref pos, (byte)entries.Length); - - for (int i = 0; i < entries.Length; i++) - { - var entry = entries[i]; - expectedData.Write(ref pos, (ushort)i); - expectedData.Write(ref pos, (ushort)(entry.Number - 3000000)); - - var flags = entry.Flags; - - var color = entry.Color & 0xFFFF; - - if (color != 0xFFFF) - flags |= CMEFlags.Colored; - - var range = entry.Range; - - if (range == -1) - range = 18; - - if (!(entry.Enabled && menu.From.InRange(item.GetWorldLocation(), range))) - flags |= CMEFlags.Disabled; - - expectedData.Write(ref pos, (ushort)flags); - - if ((flags & CMEFlags.Colored) != 0) - expectedData.Write(ref pos, (ushort)color); - } - - AssertThat.Equal(data, expectedData); - } - } -} +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Linq; +using Server.ContextMenus; +using Server.Menus.ItemLists; +using Server.Menus.Questions; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + internal class ContextMenuItem : Item + { + public ContextMenuItem(Serial serial) : base(serial) + { + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + list.Add(new ContextMenuEntry(500000)); + list.Add(new ContextMenuEntry(500001)); + list.Add(new ContextMenuEntry(500002)); + } + } + + public class MenuPacketTests : IClassFixture + { + [Fact] + public void TestDisplayItemListMenu() + { + var menu = new ItemListMenu( + "Which item would you choose?", + new[] + { + new ItemListEntry("Item 1", 0x01), + new ItemListEntry("Item 2", 0x100), + new ItemListEntry("Item 3", 0x1000, 250) + } + ); + + var data = new DisplayItemListMenu(menu).Compile(); + + var question = menu.Question; + var questionLength = Math.Min(255, question.Length); + var entriesCount = 0; + var length = 11 + questionLength; + + foreach (var entry in menu.Entries) + { + length += 5 + entry.Name.Length; + if (entriesCount == 255) + break; + + entriesCount++; + } + + Span expectedData = stackalloc byte[length]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x7C); // Packet ID + expectedData.Write(ref pos, (ushort)length); + expectedData.Write(ref pos, menu.Serial); + expectedData.Write(ref pos, (ushort)0x00); + expectedData.Write(ref pos, (byte)questionLength); + expectedData.WriteAscii(ref pos, question, 255); + expectedData.Write(ref pos, (byte)entriesCount); + for (var i = 0; i < entriesCount; i++) + { + var entry = menu.Entries[i]; + expectedData.Write(ref pos, (ushort)entry.ItemID); + expectedData.Write(ref pos, (ushort)entry.Hue); + var name = entry.Name?.Trim() ?? ""; + expectedData.Write(ref pos, (byte)Math.Min(255, name.Length)); + expectedData.WriteAscii(ref pos, name, 255); + } + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestDisplayQuestionMenu() + { + var menu = new QuestionMenu( + "Which option would you choose?", + new[] + { + "Option 1", + "Option 2", + "Option 3" + } + ); + + var data = new DisplayQuestionMenu(menu).Compile(); + + var question = menu.Question; + var questionLength = Math.Min(255, question.Length); + var answersCount = 0; + var length = 11 + questionLength; + + foreach (var answer in menu.Answers) + { + length += 5 + answer.Length; + if (answersCount == 255) + break; + + answersCount++; + } + + Span expectedData = stackalloc byte[length]; + + var pos = 0; + + expectedData.Write(ref pos, (byte)0x7C); // Packet ID + expectedData.Write(ref pos, (ushort)length); + expectedData.Write(ref pos, menu.Serial); + expectedData.Write(ref pos, (ushort)0x00); + expectedData.Write(ref pos, (byte)question.Length); + expectedData.WriteAscii(ref pos, question, 255); + expectedData.Write(ref pos, (byte)answersCount); + for (var i = 0; i < answersCount; i++) + { + var answer = menu.Answers[i]; +#if NO_LOCAL_INIT + expectedData.Write(ref pos, 0); +#else + pos += 4; +#endif + expectedData.Write(ref pos, (byte)Math.Min(255, answer.Length)); + expectedData.WriteAscii(ref pos, answer, 255); + } + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestDisplayContextMenu() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var item = new ContextMenuItem(Serial.LastItem + 1); + var menu = new ContextMenu(m, item); + + var data = new DisplayContextMenu(menu).Compile(); + + var length = 12 + menu.Entries.Length * 8; + + Span expectedData = stackalloc byte[length]; + + var pos = 0; + expectedData.Write(ref pos, (byte)0xBF); // Packet ID + expectedData.Write(ref pos, (ushort)length); // Length + expectedData.Write(ref pos, (ushort)0x14); // Command + expectedData.Write(ref pos, (ushort)0x02); // Subcommand + expectedData.Write(ref pos, menu.Target.Serial); + var entries = menu.Entries; + + expectedData.Write(ref pos, (byte)entries.Length); + + for (var i = 0; i < entries.Length; i++) + { + var entry = entries[i]; + expectedData.Write(ref pos, entry.Number); + expectedData.Write(ref pos, (ushort)i); + + var flags = entry.Flags; + + var range = entry.Range; + + if (range == -1) + range = 18; + + if (!(entry.Enabled && menu.From.InRange(item.GetWorldLocation(), range))) + flags |= CMEFlags.Disabled; + + expectedData.Write(ref pos, (ushort)flags); + } + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestDisplayContextMenuOld() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var item = new ContextMenuItem(Serial.LastItem + 1); + var menu = new ContextMenu(m, item); + + var data = new DisplayContextMenuOld(menu).Compile(); + + var length = 12 + menu.Entries.Sum(entry => 6 + ((entry.Color & 0xFFFF) != 0xFFFF ? 2 : 0)); + + Span expectedData = stackalloc byte[length]; + + var pos = 0; + expectedData.Write(ref pos, (byte)0xBF); // Packet ID + expectedData.Write(ref pos, (ushort)length); // Length + expectedData.Write(ref pos, (ushort)0x14); // Command + expectedData.Write(ref pos, (ushort)0x01); // Subcommand + expectedData.Write(ref pos, menu.Target.Serial); + var entries = menu.Entries; + + expectedData.Write(ref pos, (byte)entries.Length); + + for (var i = 0; i < entries.Length; i++) + { + var entry = entries[i]; + expectedData.Write(ref pos, (ushort)i); + expectedData.Write(ref pos, (ushort)(entry.Number - 3000000)); + + var flags = entry.Flags; + + var color = entry.Color & 0xFFFF; + + if (color != 0xFFFF) + flags |= CMEFlags.Colored; + + var range = entry.Range; + + if (range == -1) + range = 18; + + if (!(entry.Enabled && menu.From.InRange(item.GetWorldLocation(), range))) + flags |= CMEFlags.Disabled; + + expectedData.Write(ref pos, (ushort)flags); + + if ((flags & CMEFlags.Colored) != 0) + expectedData.Write(ref pos, (ushort)color); + } + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/MessageTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/MessageTests.cs index 289115bdd..b190d70e4 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/MessageTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/MessageTests.cs @@ -1,191 +1,191 @@ -using System; -using System.Buffers; -using Xunit; -using Server.Network; - -namespace Server.Tests.Network.Packets -{ - public class MessageTests - { - [Fact] - public void TestMessageLocalized() - { - Serial serial = 0x1; - int graphic = 0x100; - var messageType = MessageType.Label; - int hue = 1024; - int font = 3; - int number = 150000; - string name = "Stuff"; - string args = "Arguments"; - - Span data = new MessageLocalized( - serial, - graphic, - messageType, - hue, - font, - number, - name, - args - ).Compile(); - - Span expectedData = stackalloc byte[50 + args.Length * 2]; - int pos = 0; - expectedData.Write(ref pos, (byte)0xC1); // Packet ID - expectedData.Write(ref pos, (ushort)expectedData.Length); // Length - - expectedData.Write(ref pos, serial); - expectedData.Write(ref pos, (ushort)graphic); - expectedData.Write(ref pos, (byte)messageType); - expectedData.Write(ref pos, (ushort)hue); - expectedData.Write(ref pos, (ushort)font); - expectedData.Write(ref pos, number); - expectedData.WriteAsciiFixed(ref pos, name, 30); - expectedData.WriteLittleUniNull(ref pos, args); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestMessageLocalizedAffix() - { - Serial serial = 0x1; - int graphic = 0x100; - var messageType = MessageType.Label; - int hue = 1024; - int font = 3; - int number = 150000; - string name = "Stuff"; - string args = "Arguments"; - var affixType = AffixType.System; - string affix = "Affix"; - - Span data = new MessageLocalizedAffix( - serial, - graphic, - messageType, - hue, - font, - number, - name, - affixType, - affix, - args - ).Compile(); - - Span expectedData = stackalloc byte[52 + affix.Length + args.Length * 2]; - int pos = 0; - expectedData.Write(ref pos, (byte)0xCC); // Packet ID - expectedData.Write(ref pos, (ushort)expectedData.Length); // Length - - expectedData.Write(ref pos, serial); - expectedData.Write(ref pos, (ushort)graphic); - expectedData.Write(ref pos, (byte)messageType); - expectedData.Write(ref pos, (ushort)hue); - expectedData.Write(ref pos, (ushort)font); - expectedData.Write(ref pos, number); - expectedData.Write(ref pos, (byte)affixType); - expectedData.WriteAsciiFixed(ref pos, name, 30); - expectedData.WriteAsciiNull(ref pos, affix); - expectedData.WriteBigUniNull(ref pos, args); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestAsciiMessage() - { - Serial serial = 0x1; - int graphic = 0x100; - var messageType = MessageType.Label; - int hue = 1024; - int font = 3; - string name = "Stuff"; - string text = "Some Text"; - - Span data = new AsciiMessage( - serial, - graphic, - messageType, - hue, - font, - name, - text - ).Compile(); - - Span expectedData = stackalloc byte[45 + text.Length]; - int pos = 0; - expectedData.Write(ref pos, (byte)0x1C); // Packet ID - expectedData.Write(ref pos, (ushort)expectedData.Length); // Length - - expectedData.Write(ref pos, serial); - expectedData.Write(ref pos, (ushort)graphic); - expectedData.Write(ref pos, (byte)messageType); - expectedData.Write(ref pos, (ushort)hue); - expectedData.Write(ref pos, (ushort)font); - expectedData.WriteAsciiFixed(ref pos, name, 30); - expectedData.WriteAsciiNull(ref pos, text); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestUnicodeMessage() - { - Serial serial = 0x1; - int graphic = 0x100; - var messageType = MessageType.Label; - int hue = 1024; - int font = 3; - string lang = "ENU"; - string name = "Stuff"; - string text = "Some Text"; - - Span data = new UnicodeMessage( - serial, - graphic, - messageType, - hue, - font, - lang, - name, - text - ).Compile(); - - Span expectedData = stackalloc byte[50 + text.Length * 2]; - int pos = 0; - expectedData.Write(ref pos, (byte)0xAE); // Packet ID - expectedData.Write(ref pos, (ushort)expectedData.Length); // Length - - expectedData.Write(ref pos, serial); - expectedData.Write(ref pos, (ushort)graphic); - expectedData.Write(ref pos, (byte)messageType); - expectedData.Write(ref pos, (ushort)hue); - expectedData.Write(ref pos, (ushort)font); - expectedData.WriteAsciiFixed(ref pos, lang, 4); - expectedData.WriteAsciiFixed(ref pos, name, 30); - expectedData.WriteBigUniNull(ref pos, text); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestFollowMessage() - { - Serial serial = 0x1; - Serial serial2 = 0x2; - - Span data = new FollowMessage(serial, serial2).Compile(); - - Span expectedData = stackalloc byte[9]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x15); // Packet ID - expectedData.Write(ref pos, serial); - expectedData.Write(ref pos, serial2); - - AssertThat.Equal(data, expectedData); - } - } -} +using System; +using System.Buffers; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class MessageTests + { + [Fact] + public void TestMessageLocalized() + { + Serial serial = 0x1; + var graphic = 0x100; + var messageType = MessageType.Label; + var hue = 1024; + var font = 3; + var number = 150000; + var name = "Stuff"; + var args = "Arguments"; + + var data = new MessageLocalized( + serial, + graphic, + messageType, + hue, + font, + number, + name, + args + ).Compile(); + + Span expectedData = stackalloc byte[50 + args.Length * 2]; + var pos = 0; + expectedData.Write(ref pos, (byte)0xC1); // Packet ID + expectedData.Write(ref pos, (ushort)expectedData.Length); // Length + + expectedData.Write(ref pos, serial); + expectedData.Write(ref pos, (ushort)graphic); + expectedData.Write(ref pos, (byte)messageType); + expectedData.Write(ref pos, (ushort)hue); + expectedData.Write(ref pos, (ushort)font); + expectedData.Write(ref pos, number); + expectedData.WriteAsciiFixed(ref pos, name, 30); + expectedData.WriteLittleUniNull(ref pos, args); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestMessageLocalizedAffix() + { + Serial serial = 0x1; + var graphic = 0x100; + var messageType = MessageType.Label; + var hue = 1024; + var font = 3; + var number = 150000; + var name = "Stuff"; + var args = "Arguments"; + var affixType = AffixType.System; + var affix = "Affix"; + + var data = new MessageLocalizedAffix( + serial, + graphic, + messageType, + hue, + font, + number, + name, + affixType, + affix, + args + ).Compile(); + + Span expectedData = stackalloc byte[52 + affix.Length + args.Length * 2]; + var pos = 0; + expectedData.Write(ref pos, (byte)0xCC); // Packet ID + expectedData.Write(ref pos, (ushort)expectedData.Length); // Length + + expectedData.Write(ref pos, serial); + expectedData.Write(ref pos, (ushort)graphic); + expectedData.Write(ref pos, (byte)messageType); + expectedData.Write(ref pos, (ushort)hue); + expectedData.Write(ref pos, (ushort)font); + expectedData.Write(ref pos, number); + expectedData.Write(ref pos, (byte)affixType); + expectedData.WriteAsciiFixed(ref pos, name, 30); + expectedData.WriteAsciiNull(ref pos, affix); + expectedData.WriteBigUniNull(ref pos, args); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestAsciiMessage() + { + Serial serial = 0x1; + var graphic = 0x100; + var messageType = MessageType.Label; + var hue = 1024; + var font = 3; + var name = "Stuff"; + var text = "Some Text"; + + var data = new AsciiMessage( + serial, + graphic, + messageType, + hue, + font, + name, + text + ).Compile(); + + Span expectedData = stackalloc byte[45 + text.Length]; + var pos = 0; + expectedData.Write(ref pos, (byte)0x1C); // Packet ID + expectedData.Write(ref pos, (ushort)expectedData.Length); // Length + + expectedData.Write(ref pos, serial); + expectedData.Write(ref pos, (ushort)graphic); + expectedData.Write(ref pos, (byte)messageType); + expectedData.Write(ref pos, (ushort)hue); + expectedData.Write(ref pos, (ushort)font); + expectedData.WriteAsciiFixed(ref pos, name, 30); + expectedData.WriteAsciiNull(ref pos, text); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestUnicodeMessage() + { + Serial serial = 0x1; + var graphic = 0x100; + var messageType = MessageType.Label; + var hue = 1024; + var font = 3; + var lang = "ENU"; + var name = "Stuff"; + var text = "Some Text"; + + var data = new UnicodeMessage( + serial, + graphic, + messageType, + hue, + font, + lang, + name, + text + ).Compile(); + + Span expectedData = stackalloc byte[50 + text.Length * 2]; + var pos = 0; + expectedData.Write(ref pos, (byte)0xAE); // Packet ID + expectedData.Write(ref pos, (ushort)expectedData.Length); // Length + + expectedData.Write(ref pos, serial); + expectedData.Write(ref pos, (ushort)graphic); + expectedData.Write(ref pos, (byte)messageType); + expectedData.Write(ref pos, (ushort)hue); + expectedData.Write(ref pos, (ushort)font); + expectedData.WriteAsciiFixed(ref pos, lang, 4); + expectedData.WriteAsciiFixed(ref pos, name, 30); + expectedData.WriteBigUniNull(ref pos, text); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestFollowMessage() + { + Serial serial = 0x1; + Serial serial2 = 0x2; + + var data = new FollowMessage(serial, serial2).Compile(); + + Span expectedData = stackalloc byte[9]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x15); // Packet ID + expectedData.Write(ref pos, serial); + expectedData.Write(ref pos, serial2); + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/MobilePacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/MobilePacketTests.cs index 1647dc55e..d649f791f 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/MobilePacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/MobilePacketTests.cs @@ -1,871 +1,890 @@ -using System; -using System.Buffers; -using System.Net; -using Server.Network; -using Xunit; - -namespace Server.Tests.Network.Packets -{ - public class MobilePacketTests : IClassFixture - { - [Fact] - public void TestDeathAnimation() - { - Serial killed = 0x1; - Serial corpse = 0x1000; - - Span data = new DeathAnimation(killed, corpse).Compile(); - - Span expectedData = stackalloc byte[13]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xAF); // Packet ID - expectedData.Write(ref pos, killed); - expectedData.Write(ref pos, corpse); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, 0); -#endif - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestBondStatus() - { - Serial petSerial = 0x1; - bool bonded = true; - - Span data = new BondedStatus(petSerial, bonded).Compile(); - - Span expectedData = stackalloc byte[11]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xBF); // Packet ID - expectedData.Write(ref pos, (ushort)0x0B); // Length - expectedData.Write(ref pos, (ushort)0x19); // Sub-packet - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); // Command -#else - pos++; -#endif - - expectedData.Write(ref pos, petSerial); - expectedData.Write(ref pos, bonded); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestMobileMoving() - { - var m = new Mobile(0x1); - m.DefaultMobileInit(); - - int noto = 10; - - Span data = new MobileMoving(m, noto).Compile(); - - Span expectedData = stackalloc byte[17]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x77); // Packet ID - expectedData.Write(ref pos, m.Serial); - expectedData.Write(ref pos, (ushort)m.Body); - expectedData.Write(ref pos, m.Location); - expectedData.Write(ref pos, (byte)m.Direction); - expectedData.Write(ref pos, (ushort)m.Hue); - expectedData.Write(ref pos, (byte)m.GetPacketFlags()); - expectedData.Write(ref pos, (byte)noto); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestMobileMovingOld() - { - var m = new Mobile(0x1); - m.DefaultMobileInit(); - - int noto = 10; - - Span data = new MobileMoving(m, noto).Compile(); - - Span expectedData = stackalloc byte[17]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x77); // Packet ID - expectedData.Write(ref pos, m.Serial); - expectedData.Write(ref pos, (ushort)m.Body); - expectedData.Write(ref pos, m.Location); - expectedData.Write(ref pos, (byte)m.Direction); - expectedData.Write(ref pos, (ushort)m.Hue); - expectedData.Write(ref pos, (byte)m.GetOldPacketFlags()); - expectedData.Write(ref pos, (byte)noto); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestMobileHits() - { - var m = new Mobile(0x1); - m.DefaultMobileInit(); - - Span data = new MobileHits(m).Compile(); - - Span expectedData = stackalloc byte[9]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xA1); // Packet ID - expectedData.Write(ref pos, m.Serial); - expectedData.WriteAttribute(ref pos, m.Hits, m.HitsMax, false); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestMobileHitsN() - { - var m = new Mobile(0x1); - m.DefaultMobileInit(); - - Span data = new MobileHitsN(m).Compile(); - - Span expectedData = stackalloc byte[9]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xA1); // Packet ID - expectedData.Write(ref pos, m.Serial); - expectedData.WriteAttribute(ref pos, m.Hits, m.HitsMax, true); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestMobileMana() - { - var m = new Mobile(0x1); - m.DefaultMobileInit(); - - Span data = new MobileMana(m).Compile(); - - Span expectedData = stackalloc byte[9]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xA2); // Packet ID - expectedData.Write(ref pos, m.Serial); - expectedData.WriteAttribute(ref pos, m.Mana, m.ManaMax, false); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestMobileManaN() - { - var m = new Mobile(0x1); - m.DefaultMobileInit(); - - Span data = new MobileManaN(m).Compile(); - - Span expectedData = stackalloc byte[9]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xA2); // Packet ID - expectedData.Write(ref pos, m.Serial); - expectedData.WriteAttribute(ref pos, m.Mana, m.ManaMax, true); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestMobileStam() - { - var m = new Mobile(0x1); - m.DefaultMobileInit(); - - Span data = new MobileStam(m).Compile(); - - Span expectedData = stackalloc byte[9]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xA3); // Packet ID - expectedData.Write(ref pos, m.Serial); - expectedData.WriteAttribute(ref pos, m.Stam, m.StamMax, false); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestMobileStamN() - { - var m = new Mobile(0x1); - m.DefaultMobileInit(); - - Span data = new MobileStamN(m).Compile(); - - Span expectedData = stackalloc byte[9]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xA3); // Packet ID - expectedData.Write(ref pos, m.Serial); - expectedData.WriteAttribute(ref pos, m.Stam, m.StamMax, true); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestMobileAttributes() - { - var m = new Mobile(0x1); - m.DefaultMobileInit(); - - Span data = new MobileAttributes(m).Compile(); - - Span expectedData = stackalloc byte[17]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x2D); // Packet ID - expectedData.Write(ref pos, m.Serial); - expectedData.WriteAttribute(ref pos, m.Hits, m.HitsMax, false); - expectedData.WriteAttribute(ref pos, m.Mana, m.ManaMax, false); - expectedData.WriteAttribute(ref pos, m.Stam, m.StamMax, false); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestMobileAttributesN() - { - var m = new Mobile(0x1); - m.DefaultMobileInit(); - - Span data = new MobileAttributesN(m).Compile(); - - Span expectedData = stackalloc byte[17]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x2D); // Packet ID - expectedData.Write(ref pos, m.Serial); - expectedData.WriteAttribute(ref pos, m.Hits, m.HitsMax, true); - expectedData.WriteAttribute(ref pos, m.Mana, m.ManaMax, true); - expectedData.WriteAttribute(ref pos, m.Stam, m.StamMax, true); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestMobileName() - { - var m = new Mobile(0x1) - { - Name = "Some Really Long Mobile Name That Gets Cut off", - }; - m.DefaultMobileInit(); - - Span data = new MobileName(m).Compile(); - - Span expectedData = stackalloc byte[37]; - int pos = 0; - expectedData.Write(ref pos, (byte)0x98); - expectedData.Write(ref pos, (ushort)0x25); - expectedData.Write(ref pos, m.Serial); - expectedData.WriteAsciiFixed(ref pos, m.Name ?? "", 29); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); -#endif - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestMobileAnimation() - { - Serial mobile = 0x1; - int action = 200; - int frameCount = 5; - int repeatCount = 1; - bool reverse = false; - bool repeat = false; - byte delay = 5; - - Span data = new MobileAnimation( - mobile, - action, - frameCount, - repeatCount, - !reverse, - repeat, - delay - ).Compile(); - - Span expectedData = stackalloc byte[14]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x6E); - expectedData.Write(ref pos, mobile); - expectedData.Write(ref pos, (ushort)action); - expectedData.Write(ref pos, (ushort)frameCount); - expectedData.Write(ref pos, (ushort)repeatCount); - expectedData.Write(ref pos, reverse); - expectedData.Write(ref pos, repeat); - expectedData.Write(ref pos, delay); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestNewMobileAnimation() - { - Serial mobile = 0x1; - int action = 200; - int frameCount = 5; - byte delay = 5; - - Span data = new NewMobileAnimation( - mobile, - action, - frameCount, - delay - ).Compile(); - - Span expectedData = stackalloc byte[10]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xE2); - expectedData.Write(ref pos, mobile); - expectedData.Write(ref pos, (ushort)action); - expectedData.Write(ref pos, (ushort)frameCount); - expectedData.Write(ref pos, delay); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestMobileStatusCompact() - { - var m = new Mobile(0x1); - m.DefaultMobileInit(); - - bool canBeRenamed = false; - - Span data = new MobileStatusCompact(canBeRenamed, m).Compile(); - - Span expectedData = stackalloc byte[43]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x11); // Packet ID - expectedData.Write(ref pos, (ushort)expectedData.Length); // Length - - expectedData.Write(ref pos, m.Serial); - expectedData.WriteAsciiFixed(ref pos, m.Name ?? "", 30); - - expectedData.WriteReverseAttribute(ref pos, m.Hits, m.HitsMax, true); - expectedData.Write(ref pos, canBeRenamed); - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); // type -#endif - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(ProtocolChanges.Version70610)] - [InlineData(ProtocolChanges.Version400a)] - [InlineData(ProtocolChanges.Version502b)] - public void TestMobileStatusExtended(ProtocolChanges changes) - { - var beholder = new Mobile(0x1) - { - Name = "Random Mobile 1" - }; - beholder.DefaultMobileInit(); - - var beheld = new Mobile(0x2) - { - Name = "Random Mobile 2" - }; - beheld.DefaultMobileInit(); - - NetState ns = new NetState(new AccountPacketTests.TestConnectionContext - { - RemoteEndPoint = IPEndPoint.Parse("127.0.0.1") - }) - { - ProtocolChanges = changes - }; - - Span data = new MobileStatus(beholder, beheld, ns).Compile(); - - Span expectedData = stackalloc byte[121]; // Max Size - int pos = 0; - - expectedData.Write(ref pos, (byte)0x11); - pos += 2; // Length - - int type; - bool notSelf = beholder != beheld; - - if (notSelf) type = 0; - else if (Core.HS && ns.ExtendedStatus) type = 6; - else if (Core.ML && ns.SupportsExpansion(Expansion.ML)) type = 5; - else type = Core.AOS ? 4 : 3; - - expectedData.Write(ref pos, beheld.Serial); - expectedData.WriteAsciiFixed(ref pos, beheld.Name, 30); - - expectedData.WriteReverseAttribute(ref pos, beheld.Hits, beheld.HitsMax, notSelf); - - expectedData.Write(ref pos, beheld.CanBeRenamedBy(beheld)); - expectedData.Write(ref pos, (byte)type); - - if (type > 0) - { - expectedData.Write(ref pos, beheld.Female); - expectedData.Write(ref pos, (ushort)beheld.Str); - expectedData.Write(ref pos, (ushort)beheld.Dex); - expectedData.Write(ref pos, (ushort)beheld.Int); - - expectedData.WriteReverseAttribute(ref pos, beheld.Stam, beheld.StamMax, notSelf); - expectedData.WriteReverseAttribute(ref pos, beheld.Mana, beheld.ManaMax, notSelf); - - expectedData.Write(ref pos, beheld.TotalGold); - expectedData.Write(ref pos, (ushort)(Core.AOS ? beheld.PhysicalResistance : (int)(beheld.ArmorRating + 0.5))); - expectedData.Write(ref pos, (ushort)(Mobile.BodyWeight + beheld.TotalWeight)); - - if (type >= 5) - { - expectedData.Write(ref pos, (ushort)beheld.MaxWeight); - expectedData.Write(ref pos, (byte)(beheld.Race.RaceID + 1)); // 0x00 for a non-ML enabled account - } - - expectedData.Write(ref pos, (ushort)beheld.StatCap); - expectedData.Write(ref pos, (byte)beheld.Followers); - expectedData.Write(ref pos, (byte)beheld.FollowersMax); - - if (type >= 4) - { - expectedData.Write(ref pos, (ushort)beheld.FireResistance); - expectedData.Write(ref pos, (ushort)beheld.ColdResistance); - expectedData.Write(ref pos, (ushort)beheld.PoisonResistance); - expectedData.Write(ref pos, (ushort)beheld.EnergyResistance); - expectedData.Write(ref pos, (ushort)beheld.Luck); - } - - int min = 0; - int max = 0; - beheld.Weapon?.GetStatusDamage(beheld, out min, out max); - - expectedData.Write(ref pos, (ushort)min); - expectedData.Write(ref pos, (ushort)max); - - expectedData.Write(ref pos, beheld.TithingPoints); - - if (type >= 6) - for (var i = 0; i < 15; ++i) - expectedData.Write(ref pos, (ushort)beheld.GetAOSStatus(i)); - } - - expectedData.Slice(1, 2).Write((ushort)pos); // Length - - expectedData = expectedData.Slice(0, pos); - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData("None")] - [InlineData("Lesser")] - [InlineData("Lethal")] - public void TestHealthbarPoison(string pName) - { - var p = Poison.GetPoison(pName); - Mobile m = new Mobile(0x1); - m.DefaultMobileInit(); - m.Poison = p; - - Span data = new HealthbarPoison(m).Compile(); - - Span expectedData = stackalloc byte[12]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x17); // Packet ID - expectedData.Write(ref pos, (ushort)12); // Length - expectedData.Write(ref pos, m.Serial); - expectedData.Write(ref pos, 0x10001); // Show Bar?, Poison Bar - expectedData.Write(ref pos, (byte)((p?.Level ?? -1) + 1)); - - AssertThat.Equal(data, expectedData); - Assert.Equal(p?.Level, m.Poison?.Level); - } - - [Theory] - [InlineData(false, false)] - [InlineData(true, false)] - [InlineData(false, true)] - [InlineData(true, true)] - public void TestYellowBar(bool isBlessed, bool isYellowHealth) - { - Mobile m = new Mobile(0x1); - m.DefaultMobileInit(); - m.Blessed = isBlessed; - m.YellowHealthbar = isYellowHealth; - - Span data = new HealthbarYellow(m).Compile(); - - Span expectedData = stackalloc byte[12]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x17); // Packet ID - expectedData.Write(ref pos, (ushort)12); // Length - expectedData.Write(ref pos, m.Serial); - expectedData.Write(ref pos, 0x10002); // Show Bar?, Yellow Bar - expectedData.Write(ref pos, isBlessed || isYellowHealth); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestMobileUpdate() - { - Mobile m = new Mobile(0x1); - m.DefaultMobileInit(); - - Span data = new MobileUpdate(m).Compile(); - - Span expectedData = stackalloc byte[19]; - int pos = 0; - - var hue = m.SolidHueOverride >= 0 ? m.SolidHueOverride : m.Hue; - - expectedData.Write(ref pos, (byte)0x20); // Packet ID - expectedData.Write(ref pos, m.Serial); - expectedData.Write(ref pos, (ushort)m.Body); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); // Unknown -#else - pos++; -#endif - expectedData.Write(ref pos, (ushort)hue); - expectedData.Write(ref pos, (byte)m.GetPacketFlags()); - expectedData.Write(ref pos, (ushort)m.X); - expectedData.Write(ref pos, (ushort)m.Y); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (ushort)2); // Unknown -#else - pos += 2; -#endif - expectedData.Write(ref pos, (byte)m.Direction); - expectedData.Write(ref pos, (byte)m.Z); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestMobileUpdateOld() - { - Mobile m = new Mobile(0x1); - m.DefaultMobileInit(); - - Span data = new MobileUpdateOld(m).Compile(); - - Span expectedData = stackalloc byte[19]; - int pos = 0; - - var hue = m.SolidHueOverride >= 0 ? m.SolidHueOverride : m.Hue; - - expectedData.Write(ref pos, (byte)0x20); // Packet ID - expectedData.Write(ref pos, m.Serial); - expectedData.Write(ref pos, (ushort)m.Body); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); // Unknown -#else - pos++; -#endif - expectedData.Write(ref pos, (ushort)hue); - expectedData.Write(ref pos, (byte)m.GetOldPacketFlags()); - expectedData.Write(ref pos, (ushort)m.X); - expectedData.Write(ref pos, (ushort)m.Y); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (ushort)2); // Unknown -#else - pos += 2; -#endif - expectedData.Write(ref pos, (byte)m.Direction); - expectedData.Write(ref pos, (byte)m.Z); - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(0, 0, 0, 0)] - [InlineData(10, 1024, 0, 0)] - [InlineData(10, 1024, 11, 2048)] - public void TestMobileIncoming(int hairItemId, int hairHue, int facialHairItemId, int facialHairHue) - { - var beholder = new Mobile(0x1) - { - Name = "Random Mobile 1" - }; - beholder.DefaultMobileInit(); - - var beheld = new Mobile(0x2) - { - Name = "Random Mobile 2" - }; - beheld.DefaultMobileInit(); - beheld.AddItem(new Item((Serial)0x1000) - { - Layer = Layer.OneHanded - }); - - // Test Dupe - beheld.AddItem(new Item((Serial)0x1001) - { - Layer = Layer.OneHanded - }); - - beheld.HairItemID = hairItemId; - beheld.HairHue = hairHue; - beheld.FacialHairItemID = facialHairItemId; - beheld.FacialHairHue = facialHairHue; - - Span data = new MobileIncoming(beholder, beheld).Compile(); - - Span layers = stackalloc bool[256]; -#if NO_LOCAL_INIT - layers.Clear(); -#endif - - var items = beheld.Items; - int count = items.Count; - - if (beheld.HairItemID > 0) - count++; - if (beheld.FacialHairItemID > 0) - count++; - - int length = 23 + count * 9; // Max Size - - Span expectedData = stackalloc byte[length]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x78); - pos += 2; // Length - - var isSolidHue = beheld.SolidHueOverride >= 0; - - expectedData.Write(ref pos, beheld.Serial); - expectedData.Write(ref pos, (ushort)beheld.Body); - expectedData.Write(ref pos, (ushort)beheld.X); - expectedData.Write(ref pos, (ushort)beheld.Y); - expectedData.Write(ref pos, (byte)beheld.Z); - expectedData.Write(ref pos, (byte)beheld.Direction); - expectedData.Write(ref pos, (ushort)(isSolidHue ? beheld.SolidHueOverride : beheld.Hue)); - expectedData.Write(ref pos, (byte)beheld.GetPacketFlags()); - expectedData.Write(ref pos, (byte)Notoriety.Compute(beholder, beheld)); - - byte layer; - - for (int i = 0; i < items.Count; i++) - { - var item = items[i]; - - layer = (byte)item.Layer; - - if (!item.Deleted && !layers[layer] && beholder.CanSee(item)) - { - layers[layer] = true; - - expectedData.Write(ref pos, item.Serial); - expectedData.Write(ref pos, (ushort)(item.ItemID & 0xFFFF)); - expectedData.Write(ref pos, layer); - expectedData.Write(ref pos, (ushort)(isSolidHue ? beheld.SolidHueOverride : item.Hue)); - } - } - - layer = (byte)Layer.Hair; - var itemId = beheld.HairItemID & 0xFFFF; - - if (itemId > 0 && !layers[layer]) - { - expectedData.Write(ref pos, HairInfo.FakeSerial(beheld)); - expectedData.Write(ref pos, (ushort)itemId); - expectedData.Write(ref pos, layer); - expectedData.Write(ref pos, (ushort)(isSolidHue ? beheld.SolidHueOverride : beheld.HairHue)); - } - - layer = (byte)Layer.FacialHair; - itemId = beheld.FacialHairItemID & 0xFFFF; - - if (itemId > 0 && !layers[layer]) - { - expectedData.Write(ref pos, FacialHairInfo.FakeSerial(beheld)); - expectedData.Write(ref pos, (ushort)itemId); - expectedData.Write(ref pos, layer); - expectedData.Write(ref pos, (ushort)(isSolidHue ? beheld.SolidHueOverride : beheld.FacialHairHue)); - } - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, 0); // Zero serial, terminate list -#else - pos += 4; -#endif - - expectedData.Slice(1, 2).Write((ushort)pos); // Length - expectedData = expectedData.Slice(0, pos); - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(ProtocolChanges.Version6000, 0, 0, 0, 0)] - [InlineData(ProtocolChanges.Version6000, 10, 1024, 0, 0)] - [InlineData(ProtocolChanges.Version6000, 10, 1024, 11, 2048)] - [InlineData(ProtocolChanges.Version7000, 0, 0, 0, 0)] - [InlineData(ProtocolChanges.Version7000, 10, 1024, 0, 0)] - [InlineData(ProtocolChanges.Version7000, 10, 1024, 11, 2048)] - public void TestMobileIncomingOld(ProtocolChanges protocolChanges, int hairItemId, int hairHue, int facialHairItemId, int facialHairHue) - { - var beholder = new Mobile(0x1) - { - Name = "Random Mobile 1" - }; - beholder.DefaultMobileInit(); - - var beheld = new Mobile(0x2) - { - Name = "Random Mobile 2" - }; - beheld.DefaultMobileInit(); - beheld.AddItem(new Item((Serial)0x1000) - { - Layer = Layer.OneHanded - }); - - // Test Dupe - beheld.AddItem(new Item((Serial)0x1001) - { - Layer = Layer.OneHanded - }); - - beheld.HairItemID = hairItemId; - beheld.HairHue = hairHue; - beheld.FacialHairItemID = facialHairItemId; - beheld.FacialHairHue = facialHairHue; - - NetState ns = new NetState(new AccountPacketTests.TestConnectionContext - { - RemoteEndPoint = IPEndPoint.Parse("127.0.0.1") - }) - { - ProtocolChanges = protocolChanges - }; - - Span data = (ns.StygianAbyss ? (Packet)new MobileIncomingSA(beholder, beheld) : new MobileIncomingOld(beholder, beheld)) - .Compile(); - - Span layers = stackalloc bool[256]; -#if NO_LOCAL_INIT - layers.Clear(); -#endif - - var items = beheld.Items; - int count = items.Count; - - if (beheld.HairItemID > 0) - count++; - if (beheld.FacialHairItemID > 0) - count++; - - int length = 23 + count * 9; // Max Size - - Span expectedData = stackalloc byte[length]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x78); - pos += 2; // Length - - var isSolidHue = beheld.SolidHueOverride >= 0; - - expectedData.Write(ref pos, beheld.Serial); - expectedData.Write(ref pos, (ushort)beheld.Body); - expectedData.Write(ref pos, (ushort)beheld.X); - expectedData.Write(ref pos, (ushort)beheld.Y); - expectedData.Write(ref pos, (byte)beheld.Z); - expectedData.Write(ref pos, (byte)beheld.Direction); - expectedData.Write(ref pos, (ushort)(isSolidHue ? beheld.SolidHueOverride : beheld.Hue)); - expectedData.Write(ref pos, (byte)(ns.StygianAbyss ? beheld.GetOldPacketFlags() : beheld.GetPacketFlags())); - expectedData.Write(ref pos, (byte)Notoriety.Compute(beholder, beheld)); - - byte layer; - int itemId; - int hue; - - for (int i = 0; i < items.Count; i++) - { - var item = items[i]; - - layer = (byte)item.Layer; - - if (!item.Deleted && !layers[layer] && beholder.CanSee(item)) - { - layers[layer] = true; - itemId = item.ItemID & 0x7FFF; - hue = isSolidHue ? beheld.SolidHueOverride : item.Hue; - - if (hue != 0) - itemId |= 0x8000; - - expectedData.Write(ref pos, item.Serial); - expectedData.Write(ref pos, (ushort)itemId); - expectedData.Write(ref pos, layer); - expectedData.Write(ref pos, (ushort)hue); - } - } - - layer = (byte)Layer.Hair; - itemId = beheld.HairItemID & 0x7FFF; - - if (itemId > 0 && !layers[layer]) - { - hue = isSolidHue ? beheld.SolidHueOverride : beheld.HairHue; - - if (hue != 0) - itemId |= 0x8000; - - expectedData.Write(ref pos, HairInfo.FakeSerial(beheld)); - expectedData.Write(ref pos, (ushort)itemId); - expectedData.Write(ref pos, layer); - expectedData.Write(ref pos, (ushort)hue); - } - - layer = (byte)Layer.FacialHair; - itemId = beheld.FacialHairItemID & 0x7FFF; - - if (itemId > 0 && !layers[layer]) - { - hue = isSolidHue ? beheld.SolidHueOverride : beheld.FacialHairHue; - - if (hue != 0) - itemId |= 0x8000; - - expectedData.Write(ref pos, FacialHairInfo.FakeSerial(beheld)); - expectedData.Write(ref pos, (ushort)itemId); - expectedData.Write(ref pos, layer); - expectedData.Write(ref pos, (ushort)hue); - } - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, 0); // Zero serial, terminate list -#else - pos += 4; -#endif - - expectedData.Slice(1, 2).Write((ushort)pos); // Length - expectedData = expectedData.Slice(0, pos); - - AssertThat.Equal(data, expectedData); - } - } -} +using System; +using System.Buffers; +using System.Net; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class MobilePacketTests : IClassFixture + { + [Fact] + public void TestDeathAnimation() + { + Serial killed = 0x1; + Serial corpse = 0x1000; + + var data = new DeathAnimation(killed, corpse).Compile(); + + Span expectedData = stackalloc byte[13]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xAF); // Packet ID + expectedData.Write(ref pos, killed); + expectedData.Write(ref pos, corpse); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, 0); +#endif + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestBondStatus() + { + Serial petSerial = 0x1; + var bonded = true; + + var data = new BondedStatus(petSerial, bonded).Compile(); + + Span expectedData = stackalloc byte[11]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xBF); // Packet ID + expectedData.Write(ref pos, (ushort)0x0B); // Length + expectedData.Write(ref pos, (ushort)0x19); // Sub-packet + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); // Command +#else + pos++; +#endif + + expectedData.Write(ref pos, petSerial); + expectedData.Write(ref pos, bonded); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestMobileMoving() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var noto = 10; + + var data = new MobileMoving(m, noto).Compile(); + + Span expectedData = stackalloc byte[17]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x77); // Packet ID + expectedData.Write(ref pos, m.Serial); + expectedData.Write(ref pos, (ushort)m.Body); + expectedData.Write(ref pos, m.Location); + expectedData.Write(ref pos, (byte)m.Direction); + expectedData.Write(ref pos, (ushort)m.Hue); + expectedData.Write(ref pos, (byte)m.GetPacketFlags()); + expectedData.Write(ref pos, (byte)noto); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestMobileMovingOld() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var noto = 10; + + var data = new MobileMoving(m, noto).Compile(); + + Span expectedData = stackalloc byte[17]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x77); // Packet ID + expectedData.Write(ref pos, m.Serial); + expectedData.Write(ref pos, (ushort)m.Body); + expectedData.Write(ref pos, m.Location); + expectedData.Write(ref pos, (byte)m.Direction); + expectedData.Write(ref pos, (ushort)m.Hue); + expectedData.Write(ref pos, (byte)m.GetOldPacketFlags()); + expectedData.Write(ref pos, (byte)noto); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestMobileHits() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var data = new MobileHits(m).Compile(); + + Span expectedData = stackalloc byte[9]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xA1); // Packet ID + expectedData.Write(ref pos, m.Serial); + expectedData.WriteAttribute(ref pos, m.Hits, m.HitsMax, false); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestMobileHitsN() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var data = new MobileHitsN(m).Compile(); + + Span expectedData = stackalloc byte[9]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xA1); // Packet ID + expectedData.Write(ref pos, m.Serial); + expectedData.WriteAttribute(ref pos, m.Hits, m.HitsMax, true); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestMobileMana() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var data = new MobileMana(m).Compile(); + + Span expectedData = stackalloc byte[9]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xA2); // Packet ID + expectedData.Write(ref pos, m.Serial); + expectedData.WriteAttribute(ref pos, m.Mana, m.ManaMax, false); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestMobileManaN() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var data = new MobileManaN(m).Compile(); + + Span expectedData = stackalloc byte[9]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xA2); // Packet ID + expectedData.Write(ref pos, m.Serial); + expectedData.WriteAttribute(ref pos, m.Mana, m.ManaMax, true); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestMobileStam() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var data = new MobileStam(m).Compile(); + + Span expectedData = stackalloc byte[9]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xA3); // Packet ID + expectedData.Write(ref pos, m.Serial); + expectedData.WriteAttribute(ref pos, m.Stam, m.StamMax, false); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestMobileStamN() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var data = new MobileStamN(m).Compile(); + + Span expectedData = stackalloc byte[9]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xA3); // Packet ID + expectedData.Write(ref pos, m.Serial); + expectedData.WriteAttribute(ref pos, m.Stam, m.StamMax, true); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestMobileAttributes() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var data = new MobileAttributes(m).Compile(); + + Span expectedData = stackalloc byte[17]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x2D); // Packet ID + expectedData.Write(ref pos, m.Serial); + expectedData.WriteAttribute(ref pos, m.Hits, m.HitsMax, false); + expectedData.WriteAttribute(ref pos, m.Mana, m.ManaMax, false); + expectedData.WriteAttribute(ref pos, m.Stam, m.StamMax, false); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestMobileAttributesN() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var data = new MobileAttributesN(m).Compile(); + + Span expectedData = stackalloc byte[17]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x2D); // Packet ID + expectedData.Write(ref pos, m.Serial); + expectedData.WriteAttribute(ref pos, m.Hits, m.HitsMax, true); + expectedData.WriteAttribute(ref pos, m.Mana, m.ManaMax, true); + expectedData.WriteAttribute(ref pos, m.Stam, m.StamMax, true); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestMobileName() + { + var m = new Mobile(0x1) + { + Name = "Some Really Long Mobile Name That Gets Cut off" + }; + m.DefaultMobileInit(); + + var data = new MobileName(m).Compile(); + + Span expectedData = stackalloc byte[37]; + var pos = 0; + expectedData.Write(ref pos, (byte)0x98); + expectedData.Write(ref pos, (ushort)0x25); + expectedData.Write(ref pos, m.Serial); + expectedData.WriteAsciiFixed(ref pos, m.Name ?? "", 29); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); +#endif + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestMobileAnimation() + { + Serial mobile = 0x1; + var action = 200; + var frameCount = 5; + var repeatCount = 1; + var reverse = false; + var repeat = false; + byte delay = 5; + + var data = new MobileAnimation( + mobile, + action, + frameCount, + repeatCount, + !reverse, + repeat, + delay + ).Compile(); + + Span expectedData = stackalloc byte[14]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x6E); + expectedData.Write(ref pos, mobile); + expectedData.Write(ref pos, (ushort)action); + expectedData.Write(ref pos, (ushort)frameCount); + expectedData.Write(ref pos, (ushort)repeatCount); + expectedData.Write(ref pos, reverse); + expectedData.Write(ref pos, repeat); + expectedData.Write(ref pos, delay); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestNewMobileAnimation() + { + Serial mobile = 0x1; + var action = 200; + var frameCount = 5; + byte delay = 5; + + var data = new NewMobileAnimation( + mobile, + action, + frameCount, + delay + ).Compile(); + + Span expectedData = stackalloc byte[10]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xE2); + expectedData.Write(ref pos, mobile); + expectedData.Write(ref pos, (ushort)action); + expectedData.Write(ref pos, (ushort)frameCount); + expectedData.Write(ref pos, delay); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestMobileStatusCompact() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var canBeRenamed = false; + + var data = new MobileStatusCompact(canBeRenamed, m).Compile(); + + Span expectedData = stackalloc byte[43]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x11); // Packet ID + expectedData.Write(ref pos, (ushort)expectedData.Length); // Length + + expectedData.Write(ref pos, m.Serial); + expectedData.WriteAsciiFixed(ref pos, m.Name ?? "", 30); + + expectedData.WriteReverseAttribute(ref pos, m.Hits, m.HitsMax, true); + expectedData.Write(ref pos, canBeRenamed); + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); // type +#endif + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(ProtocolChanges.Version70610)] + [InlineData(ProtocolChanges.Version400a)] + [InlineData(ProtocolChanges.Version502b)] + public void TestMobileStatusExtended(ProtocolChanges changes) + { + var beholder = new Mobile(0x1) + { + Name = "Random Mobile 1" + }; + beholder.DefaultMobileInit(); + + var beheld = new Mobile(0x2) + { + Name = "Random Mobile 2" + }; + beheld.DefaultMobileInit(); + + var ns = new NetState( + new AccountPacketTests.TestConnectionContext + { + RemoteEndPoint = IPEndPoint.Parse("127.0.0.1") + } + ) + { + ProtocolChanges = changes + }; + + var data = new MobileStatus(beholder, beheld, ns).Compile(); + + Span expectedData = stackalloc byte[121]; // Max Size + var pos = 0; + + expectedData.Write(ref pos, (byte)0x11); + pos += 2; // Length + + int type; + var notSelf = beholder != beheld; + + if (notSelf) type = 0; + else if (Core.HS && ns.ExtendedStatus) type = 6; + else if (Core.ML && ns.SupportsExpansion(Expansion.ML)) type = 5; + else type = Core.AOS ? 4 : 3; + + expectedData.Write(ref pos, beheld.Serial); + expectedData.WriteAsciiFixed(ref pos, beheld.Name, 30); + + expectedData.WriteReverseAttribute(ref pos, beheld.Hits, beheld.HitsMax, notSelf); + + expectedData.Write(ref pos, beheld.CanBeRenamedBy(beheld)); + expectedData.Write(ref pos, (byte)type); + + if (type > 0) + { + expectedData.Write(ref pos, beheld.Female); + expectedData.Write(ref pos, (ushort)beheld.Str); + expectedData.Write(ref pos, (ushort)beheld.Dex); + expectedData.Write(ref pos, (ushort)beheld.Int); + + expectedData.WriteReverseAttribute(ref pos, beheld.Stam, beheld.StamMax, notSelf); + expectedData.WriteReverseAttribute(ref pos, beheld.Mana, beheld.ManaMax, notSelf); + + expectedData.Write(ref pos, beheld.TotalGold); + expectedData.Write( + ref pos, + (ushort)(Core.AOS ? beheld.PhysicalResistance : (int)(beheld.ArmorRating + 0.5)) + ); + expectedData.Write(ref pos, (ushort)(Mobile.BodyWeight + beheld.TotalWeight)); + + if (type >= 5) + { + expectedData.Write(ref pos, (ushort)beheld.MaxWeight); + expectedData.Write(ref pos, (byte)(beheld.Race.RaceID + 1)); // 0x00 for a non-ML enabled account + } + + expectedData.Write(ref pos, (ushort)beheld.StatCap); + expectedData.Write(ref pos, (byte)beheld.Followers); + expectedData.Write(ref pos, (byte)beheld.FollowersMax); + + if (type >= 4) + { + expectedData.Write(ref pos, (ushort)beheld.FireResistance); + expectedData.Write(ref pos, (ushort)beheld.ColdResistance); + expectedData.Write(ref pos, (ushort)beheld.PoisonResistance); + expectedData.Write(ref pos, (ushort)beheld.EnergyResistance); + expectedData.Write(ref pos, (ushort)beheld.Luck); + } + + var min = 0; + var max = 0; + beheld.Weapon?.GetStatusDamage(beheld, out min, out max); + + expectedData.Write(ref pos, (ushort)min); + expectedData.Write(ref pos, (ushort)max); + + expectedData.Write(ref pos, beheld.TithingPoints); + + if (type >= 6) + for (var i = 0; i < 15; ++i) + expectedData.Write(ref pos, (ushort)beheld.GetAOSStatus(i)); + } + + expectedData.Slice(1, 2).Write((ushort)pos); // Length + + expectedData = expectedData.Slice(0, pos); + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData("None")] + [InlineData("Lesser")] + [InlineData("Lethal")] + public void TestHealthbarPoison(string pName) + { + var p = Poison.GetPoison(pName); + var m = new Mobile(0x1); + m.DefaultMobileInit(); + m.Poison = p; + + var data = new HealthbarPoison(m).Compile(); + + Span expectedData = stackalloc byte[12]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x17); // Packet ID + expectedData.Write(ref pos, (ushort)12); // Length + expectedData.Write(ref pos, m.Serial); + expectedData.Write(ref pos, 0x10001); // Show Bar?, Poison Bar + expectedData.Write(ref pos, (byte)((p?.Level ?? -1) + 1)); + + AssertThat.Equal(data, expectedData); + Assert.Equal(p?.Level, m.Poison?.Level); + } + + [Theory] + [InlineData(false, false)] + [InlineData(true, false)] + [InlineData(false, true)] + [InlineData(true, true)] + public void TestYellowBar(bool isBlessed, bool isYellowHealth) + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + m.Blessed = isBlessed; + m.YellowHealthbar = isYellowHealth; + + var data = new HealthbarYellow(m).Compile(); + + Span expectedData = stackalloc byte[12]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x17); // Packet ID + expectedData.Write(ref pos, (ushort)12); // Length + expectedData.Write(ref pos, m.Serial); + expectedData.Write(ref pos, 0x10002); // Show Bar?, Yellow Bar + expectedData.Write(ref pos, isBlessed || isYellowHealth); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestMobileUpdate() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var data = new MobileUpdate(m).Compile(); + + Span expectedData = stackalloc byte[19]; + var pos = 0; + + var hue = m.SolidHueOverride >= 0 ? m.SolidHueOverride : m.Hue; + + expectedData.Write(ref pos, (byte)0x20); // Packet ID + expectedData.Write(ref pos, m.Serial); + expectedData.Write(ref pos, (ushort)m.Body); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); // Unknown +#else + pos++; +#endif + expectedData.Write(ref pos, (ushort)hue); + expectedData.Write(ref pos, (byte)m.GetPacketFlags()); + expectedData.Write(ref pos, (ushort)m.X); + expectedData.Write(ref pos, (ushort)m.Y); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (ushort)2); // Unknown +#else + pos += 2; +#endif + expectedData.Write(ref pos, (byte)m.Direction); + expectedData.Write(ref pos, (byte)m.Z); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestMobileUpdateOld() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var data = new MobileUpdateOld(m).Compile(); + + Span expectedData = stackalloc byte[19]; + var pos = 0; + + var hue = m.SolidHueOverride >= 0 ? m.SolidHueOverride : m.Hue; + + expectedData.Write(ref pos, (byte)0x20); // Packet ID + expectedData.Write(ref pos, m.Serial); + expectedData.Write(ref pos, (ushort)m.Body); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); // Unknown +#else + pos++; +#endif + expectedData.Write(ref pos, (ushort)hue); + expectedData.Write(ref pos, (byte)m.GetOldPacketFlags()); + expectedData.Write(ref pos, (ushort)m.X); + expectedData.Write(ref pos, (ushort)m.Y); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (ushort)2); // Unknown +#else + pos += 2; +#endif + expectedData.Write(ref pos, (byte)m.Direction); + expectedData.Write(ref pos, (byte)m.Z); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(0, 0, 0, 0)] + [InlineData(10, 1024, 0, 0)] + [InlineData(10, 1024, 11, 2048)] + public void TestMobileIncoming(int hairItemId, int hairHue, int facialHairItemId, int facialHairHue) + { + var beholder = new Mobile(0x1) + { + Name = "Random Mobile 1" + }; + beholder.DefaultMobileInit(); + + var beheld = new Mobile(0x2) + { + Name = "Random Mobile 2" + }; + beheld.DefaultMobileInit(); + beheld.AddItem( + new Item((Serial)0x1000) + { + Layer = Layer.OneHanded + } + ); + + // Test Dupe + beheld.AddItem( + new Item((Serial)0x1001) + { + Layer = Layer.OneHanded + } + ); + + beheld.HairItemID = hairItemId; + beheld.HairHue = hairHue; + beheld.FacialHairItemID = facialHairItemId; + beheld.FacialHairHue = facialHairHue; + + var data = new MobileIncoming(beholder, beheld).Compile(); + + Span layers = stackalloc bool[256]; +#if NO_LOCAL_INIT + layers.Clear(); +#endif + + var items = beheld.Items; + var count = items.Count; + + if (beheld.HairItemID > 0) + count++; + if (beheld.FacialHairItemID > 0) + count++; + + var length = 23 + count * 9; // Max Size + + Span expectedData = stackalloc byte[length]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x78); + pos += 2; // Length + + var isSolidHue = beheld.SolidHueOverride >= 0; + + expectedData.Write(ref pos, beheld.Serial); + expectedData.Write(ref pos, (ushort)beheld.Body); + expectedData.Write(ref pos, (ushort)beheld.X); + expectedData.Write(ref pos, (ushort)beheld.Y); + expectedData.Write(ref pos, (byte)beheld.Z); + expectedData.Write(ref pos, (byte)beheld.Direction); + expectedData.Write(ref pos, (ushort)(isSolidHue ? beheld.SolidHueOverride : beheld.Hue)); + expectedData.Write(ref pos, (byte)beheld.GetPacketFlags()); + expectedData.Write(ref pos, (byte)Notoriety.Compute(beholder, beheld)); + + byte layer; + + for (var i = 0; i < items.Count; i++) + { + var item = items[i]; + + layer = (byte)item.Layer; + + if (!item.Deleted && !layers[layer] && beholder.CanSee(item)) + { + layers[layer] = true; + + expectedData.Write(ref pos, item.Serial); + expectedData.Write(ref pos, (ushort)(item.ItemID & 0xFFFF)); + expectedData.Write(ref pos, layer); + expectedData.Write(ref pos, (ushort)(isSolidHue ? beheld.SolidHueOverride : item.Hue)); + } + } + + layer = (byte)Layer.Hair; + var itemId = beheld.HairItemID & 0xFFFF; + + if (itemId > 0 && !layers[layer]) + { + expectedData.Write(ref pos, HairInfo.FakeSerial(beheld)); + expectedData.Write(ref pos, (ushort)itemId); + expectedData.Write(ref pos, layer); + expectedData.Write(ref pos, (ushort)(isSolidHue ? beheld.SolidHueOverride : beheld.HairHue)); + } + + layer = (byte)Layer.FacialHair; + itemId = beheld.FacialHairItemID & 0xFFFF; + + if (itemId > 0 && !layers[layer]) + { + expectedData.Write(ref pos, FacialHairInfo.FakeSerial(beheld)); + expectedData.Write(ref pos, (ushort)itemId); + expectedData.Write(ref pos, layer); + expectedData.Write(ref pos, (ushort)(isSolidHue ? beheld.SolidHueOverride : beheld.FacialHairHue)); + } + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, 0); // Zero serial, terminate list +#else + pos += 4; +#endif + + expectedData.Slice(1, 2).Write((ushort)pos); // Length + expectedData = expectedData.Slice(0, pos); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(ProtocolChanges.Version6000, 0, 0, 0, 0)] + [InlineData(ProtocolChanges.Version6000, 10, 1024, 0, 0)] + [InlineData(ProtocolChanges.Version6000, 10, 1024, 11, 2048)] + [InlineData(ProtocolChanges.Version7000, 0, 0, 0, 0)] + [InlineData(ProtocolChanges.Version7000, 10, 1024, 0, 0)] + [InlineData(ProtocolChanges.Version7000, 10, 1024, 11, 2048)] + public void TestMobileIncomingOld( + ProtocolChanges protocolChanges, int hairItemId, int hairHue, int facialHairItemId, int facialHairHue + ) + { + var beholder = new Mobile(0x1) + { + Name = "Random Mobile 1" + }; + beholder.DefaultMobileInit(); + + var beheld = new Mobile(0x2) + { + Name = "Random Mobile 2" + }; + beheld.DefaultMobileInit(); + beheld.AddItem( + new Item((Serial)0x1000) + { + Layer = Layer.OneHanded + } + ); + + // Test Dupe + beheld.AddItem( + new Item((Serial)0x1001) + { + Layer = Layer.OneHanded + } + ); + + beheld.HairItemID = hairItemId; + beheld.HairHue = hairHue; + beheld.FacialHairItemID = facialHairItemId; + beheld.FacialHairHue = facialHairHue; + + var ns = new NetState( + new AccountPacketTests.TestConnectionContext + { + RemoteEndPoint = IPEndPoint.Parse("127.0.0.1") + } + ) + { + ProtocolChanges = protocolChanges + }; + + var data = (ns.StygianAbyss + ? (Packet)new MobileIncomingSA(beholder, beheld) + : new MobileIncomingOld(beholder, beheld)) + .Compile(); + + Span layers = stackalloc bool[256]; +#if NO_LOCAL_INIT + layers.Clear(); +#endif + + var items = beheld.Items; + var count = items.Count; + + if (beheld.HairItemID > 0) + count++; + if (beheld.FacialHairItemID > 0) + count++; + + var length = 23 + count * 9; // Max Size + + Span expectedData = stackalloc byte[length]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x78); + pos += 2; // Length + + var isSolidHue = beheld.SolidHueOverride >= 0; + + expectedData.Write(ref pos, beheld.Serial); + expectedData.Write(ref pos, (ushort)beheld.Body); + expectedData.Write(ref pos, (ushort)beheld.X); + expectedData.Write(ref pos, (ushort)beheld.Y); + expectedData.Write(ref pos, (byte)beheld.Z); + expectedData.Write(ref pos, (byte)beheld.Direction); + expectedData.Write(ref pos, (ushort)(isSolidHue ? beheld.SolidHueOverride : beheld.Hue)); + expectedData.Write(ref pos, (byte)(ns.StygianAbyss ? beheld.GetOldPacketFlags() : beheld.GetPacketFlags())); + expectedData.Write(ref pos, (byte)Notoriety.Compute(beholder, beheld)); + + byte layer; + int itemId; + int hue; + + for (var i = 0; i < items.Count; i++) + { + var item = items[i]; + + layer = (byte)item.Layer; + + if (!item.Deleted && !layers[layer] && beholder.CanSee(item)) + { + layers[layer] = true; + itemId = item.ItemID & 0x7FFF; + hue = isSolidHue ? beheld.SolidHueOverride : item.Hue; + + if (hue != 0) + itemId |= 0x8000; + + expectedData.Write(ref pos, item.Serial); + expectedData.Write(ref pos, (ushort)itemId); + expectedData.Write(ref pos, layer); + expectedData.Write(ref pos, (ushort)hue); + } + } + + layer = (byte)Layer.Hair; + itemId = beheld.HairItemID & 0x7FFF; + + if (itemId > 0 && !layers[layer]) + { + hue = isSolidHue ? beheld.SolidHueOverride : beheld.HairHue; + + if (hue != 0) + itemId |= 0x8000; + + expectedData.Write(ref pos, HairInfo.FakeSerial(beheld)); + expectedData.Write(ref pos, (ushort)itemId); + expectedData.Write(ref pos, layer); + expectedData.Write(ref pos, (ushort)hue); + } + + layer = (byte)Layer.FacialHair; + itemId = beheld.FacialHairItemID & 0x7FFF; + + if (itemId > 0 && !layers[layer]) + { + hue = isSolidHue ? beheld.SolidHueOverride : beheld.FacialHairHue; + + if (hue != 0) + itemId |= 0x8000; + + expectedData.Write(ref pos, FacialHairInfo.FakeSerial(beheld)); + expectedData.Write(ref pos, (ushort)itemId); + expectedData.Write(ref pos, layer); + expectedData.Write(ref pos, (ushort)hue); + } + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, 0); // Zero serial, terminate list +#else + pos += 4; +#endif + + expectedData.Slice(1, 2).Write((ushort)pos); // Length + expectedData = expectedData.Slice(0, pos); + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/MovementPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/MovementPacketTests.cs index 4da64e50b..db5ab6826 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/MovementPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/MovementPacketTests.cs @@ -1,112 +1,112 @@ -using System; -using System.Buffers; -using Server.Network; -using Xunit; - -namespace Server.Tests.Network.Packets -{ - public class MovementPacketTests : IClassFixture - { - [Theory] - [InlineData(0)] - [InlineData(1)] - [InlineData(2)] - public void TestSpeedControl(byte speedControl) - { - Span data = new SpeedControl(speedControl).Compile(); - - Span expectedData = stackalloc byte[6]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xBF); // Packet ID - expectedData.Write(ref pos, (ushort)6); // Length - expectedData.Write(ref pos, (ushort)0x26); // Command - expectedData.Write(ref pos, speedControl); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestMovePlayer() - { - const Direction d = Direction.Left; - Span data = new MovePlayer(d).Compile(); - - Span expectedData = stackalloc byte[2]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x97); // Packet ID - expectedData.Write(ref pos, (byte)d); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestMovementRej() - { - Mobile m = new Mobile(0x1); - m.DefaultMobileInit(); - - const byte seq = 100; - - Span data = new MovementRej(seq, m).Compile(); - - Span expectedData = stackalloc byte[8]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x21); // Packet ID - expectedData.Write(ref pos, seq); - expectedData.Write(ref pos, (short)m.X); - expectedData.Write(ref pos, (short)m.Y); - expectedData.Write(ref pos, (byte)m.Direction); - expectedData.Write(ref pos, (byte)m.Z); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestMovementAck() - { - Mobile m = new Mobile(0x1); - m.DefaultMobileInit(); - - const byte seq = 100; - int noto = Notoriety.Compute(m, m); - - Span data = MovementAck.Instantiate(seq, m).Compile(); - - Span expectedData = stackalloc byte[3]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x22); // Packet ID - expectedData.Write(ref pos, seq); - expectedData.Write(ref pos, (byte)noto); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestNullFastwalkStack() - { - Span data = new NullFastwalkStack().Compile(); - - Span expectedData = stackalloc byte[29]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xBF); // Packet ID - expectedData.Write(ref pos, (ushort)29); // Length - expectedData.Write(ref pos, (short)0x1); // Sub-packet - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, 0); // Key 1 - expectedData.Write(ref pos, 0); // Key 2 - expectedData.Write(ref pos, 0); // Key 3 - expectedData.Write(ref pos, 0); // Key 4 - expectedData.Write(ref pos, 0); // Key 5 - expectedData.Write(ref pos, 0); // Key 6 -#endif - - AssertThat.Equal(data, expectedData); - } - } -} +using System; +using System.Buffers; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class MovementPacketTests : IClassFixture + { + [Theory] + [InlineData(0)] + [InlineData(1)] + [InlineData(2)] + public void TestSpeedControl(byte speedControl) + { + var data = new SpeedControl(speedControl).Compile(); + + Span expectedData = stackalloc byte[6]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xBF); // Packet ID + expectedData.Write(ref pos, (ushort)6); // Length + expectedData.Write(ref pos, (ushort)0x26); // Command + expectedData.Write(ref pos, speedControl); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestMovePlayer() + { + const Direction d = Direction.Left; + var data = new MovePlayer(d).Compile(); + + Span expectedData = stackalloc byte[2]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x97); // Packet ID + expectedData.Write(ref pos, (byte)d); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestMovementRej() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + const byte seq = 100; + + var data = new MovementRej(seq, m).Compile(); + + Span expectedData = stackalloc byte[8]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x21); // Packet ID + expectedData.Write(ref pos, seq); + expectedData.Write(ref pos, (short)m.X); + expectedData.Write(ref pos, (short)m.Y); + expectedData.Write(ref pos, (byte)m.Direction); + expectedData.Write(ref pos, (byte)m.Z); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestMovementAck() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + const byte seq = 100; + var noto = Notoriety.Compute(m, m); + + var data = MovementAck.Instantiate(seq, m).Compile(); + + Span expectedData = stackalloc byte[3]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x22); // Packet ID + expectedData.Write(ref pos, seq); + expectedData.Write(ref pos, (byte)noto); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestNullFastwalkStack() + { + var data = new NullFastwalkStack().Compile(); + + Span expectedData = stackalloc byte[29]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xBF); // Packet ID + expectedData.Write(ref pos, (ushort)29); // Length + expectedData.Write(ref pos, (short)0x1); // Sub-packet + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, 0); // Key 1 + expectedData.Write(ref pos, 0); // Key 2 + expectedData.Write(ref pos, 0); // Key 3 + expectedData.Write(ref pos, 0); // Key 4 + expectedData.Write(ref pos, 0); // Key 5 + expectedData.Write(ref pos, 0); // Key 6 +#endif + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/ObjectHelpResponseTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/ObjectHelpResponseTests.cs index 6e42e857f..91a228328 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/ObjectHelpResponseTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/ObjectHelpResponseTests.cs @@ -1,31 +1,31 @@ -using System; -using System.Buffers; -using Server.Network; -using Xunit; - -namespace Server.Tests.Network.Packets -{ - public class ObjectHelpResponseTests - { - [Fact] - public void TestObjectHelpResponse() - { - Serial s = 0x100; - string text = "This is some testing text"; - - Span data = new ObjectHelpResponse(s, text).Compile(); - - int length = 9 + text.Length * 2; - - Span expectedData = stackalloc byte[length]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xB7); // Packet ID - expectedData.Write(ref pos, (ushort)length); // Length - expectedData.Write(ref pos, s); - expectedData.WriteBigUniNull(ref pos, text); - - AssertThat.Equal(data, expectedData); - } - } -} +using System; +using System.Buffers; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class ObjectHelpResponseTests + { + [Fact] + public void TestObjectHelpResponse() + { + Serial s = 0x100; + var text = "This is some testing text"; + + var data = new ObjectHelpResponse(s, text).Compile(); + + var length = 9 + text.Length * 2; + + Span expectedData = stackalloc byte[length]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xB7); // Packet ID + expectedData.Write(ref pos, (ushort)length); // Length + expectedData.Write(ref pos, s); + expectedData.WriteBigUniNull(ref pos, text); + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/PlayerPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/PlayerPacketTests.cs index 7d5c13abc..81523a3b6 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/PlayerPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/PlayerPacketTests.cs @@ -1,521 +1,521 @@ -using System; -using System.Buffers; -using Server.Network; -using Xunit; - -namespace Server.Tests.Network.Packets -{ - public class PlayerPacketTests : IClassFixture - { - [Fact] - public void TestStatLockInfo() - { - Mobile m = new Mobile(0x1); - m.DefaultMobileInit(); - - Span data = new StatLockInfo(m).Compile(); - - Span expectedData = stackalloc byte[12]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xBF); // Packet ID - expectedData.Write(ref pos, (ushort)12); // Length - expectedData.Write(ref pos, (ushort)0x19); // Sub-packet - expectedData.Write(ref pos, (byte)2); // Command - expectedData.Write(ref pos, m.Serial); - expectedData.Write(ref pos, (ushort)(((int)m.StrLock << 4) | ((int)m.DexLock << 2) | (int)m.IntLock)); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestChangeUpdateRange() - { - byte range = 10; - Span data = new ChangeUpdateRange(range).Compile(); - - Span expectedData = stackalloc byte[2]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xC8); // Packet ID - expectedData.Write(ref pos, range); - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void TestDeathStatus(bool isDead) - { - Span data = new DeathStatus(isDead).Compile(); - - Span expectedData = stackalloc byte[2]; - int pos = 0; - - const byte dead = 0; - const byte alive = 2; - expectedData.Write(ref pos, (byte)0x2C); // Packet ID - expectedData.Write(ref pos, isDead ? dead : alive); - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(0, true)] - [InlineData(0, false)] - [InlineData(100, true)] - [InlineData(1000, false)] - public void TestSpecialAbility(int abilityId, bool active) - { - Span data = new ToggleSpecialAbility(abilityId, active).Compile(); - - Span expectedData = stackalloc byte[8]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xBF); // Packet ID - expectedData.Write(ref pos, (ushort)0x8); // Length - expectedData.Write(ref pos, (ushort)0x25); // Sub-packet - expectedData.Write(ref pos, (ushort)abilityId); - expectedData.Write(ref pos, active); - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData("This is a header", "This is a body", "This is a footer")] - [InlineData(null, null, null)] - public void TestDisplayProfile(string header, string body, string footer) - { - Serial m = 0x1000; - - Span data = new DisplayProfile(m, header, body, footer).Compile(); - - header ??= ""; - body ??= ""; - footer ??= ""; - - int length = 12 + header.Length + footer.Length * 2 + body.Length * 2; - - Span expectedData = stackalloc byte[length]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xB8); // Packet ID - expectedData.Write(ref pos, (ushort)length); // Length - expectedData.Write(ref pos, m); // Mobile Serial or Serial.Zero - expectedData.WriteAsciiNull(ref pos, header); - expectedData.WriteBigUniNull(ref pos, footer); - expectedData.WriteBigUniNull(ref pos, body); - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(LRReason.CannotLift)] - [InlineData(LRReason.TryToSteal)] - public void TestLiftRej(LRReason reason) - { - Span data = new LiftRej(reason).Compile(); - - Span expectedData = stackalloc byte[2]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x27); // Packet ID - expectedData.Write(ref pos, (byte)reason); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestLogoutAck() - { - Span data = new LogoutAck().Compile(); - - Span expectedData = stackalloc byte[2]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xD1); // Packet ID - expectedData.Write(ref pos, (byte)0x1); // 1 - Ack - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(1, 2, 3)] - [InlineData(4, 5, 6)] - public void TestWeather(int type, int density, int temp) - { - Span data = new Weather(type, density, temp).Compile(); - - Span expectedData = stackalloc byte[4]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x65); // Packet ID - expectedData.Write(ref pos, (byte)type); - expectedData.Write(ref pos, (byte)density); - expectedData.Write(ref pos, (byte)temp); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestRemoveEntity() - { - Serial e = 0x1000; - Span data = new RemoveEntity(e).Compile(); - - Span expectedData = stackalloc byte[5]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x1D); // Packet ID - expectedData.Write(ref pos, e); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestServerChange() - { - Point3D p = new Point3D(100, 1000, 1); - Map map = Map.Felucca; - Span data = new ServerChange(p, map).Compile(); - - Span expectedData = stackalloc byte[16]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x76); // Packet ID - expectedData.Write(ref pos, (ushort)p.X); - expectedData.Write(ref pos, (ushort)p.Y); - expectedData.Write(ref pos, (short)p.Z); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); // Unknown - expectedData.Write(ref pos, 0); // Server X, Server Y -#else - pos += 5; -#endif - expectedData.Write(ref pos, (ushort)map.Width); // Server Width - expectedData.Write(ref pos, (ushort)map.Height); // Server Height - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestSkillUpdate() - { - Mobile m = new Mobile(0x1); - m.DefaultMobileInit(); - - Skills skills = m.Skills; - m.Skills[SkillName.Alchemy].BaseFixedPoint = 1000; // GM Alchemy - - Span data = new SkillUpdate(skills).Compile(); - - int length = 6 + skills.Length * 9; - Span expectedData = stackalloc byte[length]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x3A); // Packet ID - expectedData.Write(ref pos, (ushort)length); // Length - expectedData.Write(ref pos, (byte)0x02); // type: absolute, capped - - for (int i = 0; i < skills.Length; i++) - { - var s = skills[i]; - - var v = s.NonRacialValue; - var uv = Math.Clamp((int)(v * 10), 0, 0xFFFF); - - expectedData.Write(ref pos, (ushort)(s.Info.SkillID + 1)); - expectedData.Write(ref pos, (ushort)uv); - expectedData.Write(ref pos, (ushort)s.BaseFixedPoint); - expectedData.Write(ref pos, (byte)s.Lock); - expectedData.Write(ref pos, (ushort)s.CapFixedPoint); - } - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(0)] - [InlineData(10)] - [InlineData(255)] - public void TestSequence(byte num) - { - Span data = new Sequence(num).Compile(); - - Span expectedData = stackalloc byte[2]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x7B); // Packet ID - expectedData.Write(ref pos, num); - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(SkillName.Alchemy, 0, 1)] - [InlineData(SkillName.Archery, 10, 1000)] - [InlineData(SkillName.Begging, 100000, 1000)] - public void TestSkillChange(SkillName skillName, int baseFixedPoint, int capFixedPoint) - { - // TODO: Eliminate all of this and just create a Skill directly - Mobile m = new Mobile(0x1); - m.DefaultMobileInit(); - - Skill skill = m.Skills[skillName]; - skill.BaseFixedPoint = baseFixedPoint; - skill.CapFixedPoint = capFixedPoint; - - Span data = new SkillChange(skill).Compile(); - - Span expectedData = stackalloc byte[13]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x3A); // Packet ID - expectedData.Write(ref pos, (ushort)13); // Length - expectedData.Write(ref pos, (byte)0xDF); // type: delta, capped - - var v = skill.NonRacialValue; - var uv = Math.Clamp((int)(v * 10), 0, 0xFFFF); - - expectedData.Write(ref pos, (ushort)skill.Info.SkillID); - expectedData.Write(ref pos, (ushort)uv); - expectedData.Write(ref pos, (ushort)skill.BaseFixedPoint); - expectedData.Write(ref pos, (byte)skill.Lock); - expectedData.Write(ref pos, (ushort)skill.CapFixedPoint); - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(null)] - [InlineData("")] - [InlineData("This is a URL, I promise")] - public void TestLaunchBrowser(string url) - { - Span data = new LaunchBrowser(url).Compile(); - - url ??= ""; - - int length = 4 + url.Length; - Span expectedData = stackalloc byte[length]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xA5); // Packet ID - expectedData.Write(ref pos, (ushort)length); // Length - expectedData.WriteAsciiNull(ref pos, url); // Note: use punycode for unicode URLs - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestDragEffect() - { - Entity src = new Entity(0x1, new Point3D(1000, 100, 10), Map.Felucca); - Entity targ = new Entity(0x2, new Point3D(1125, 125, 5), Map.Felucca); - var itemID = 0x384; - var hue = 1024; - var amount = 25; - - Span data = new DragEffect(src, targ, itemID, hue, amount).Compile(); - - Span expectedData = stackalloc byte[26]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x23); // Packet ID - expectedData.Write(ref pos, (ushort)itemID); - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); -#else - pos++; -#endif - - expectedData.Write(ref pos, (ushort)hue); - expectedData.Write(ref pos, (ushort)amount); - expectedData.Write(ref pos, src.Serial); - expectedData.Write(ref pos, src.Location); - expectedData.Write(ref pos, targ.Serial); - expectedData.Write(ref pos, targ.Location); - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(1, false)] - [InlineData(2, true)] - public void TestSeasonChange(int season, bool playSound) - { - Span data = new SeasonChange(season, playSound).Compile(); - - Span expectedData = stackalloc byte[3]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xBC); // Packet ID - expectedData.Write(ref pos, (byte)season); - expectedData.Write(ref pos, playSound); - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(0x1024, "Test Title", true, true)] - [InlineData(0x1024, "Test Title", false, true)] - [InlineData(0x1024, "Test Title", true, false)] - public void TestDisplayPaperdoll(uint m, string title, bool warmode, bool canLift) - { - Span data = new DisplayPaperdoll(m, title, warmode, canLift).Compile(); - - Span expectedData = stackalloc byte[66]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x88); // Packet ID - expectedData.Write(ref pos, m); - expectedData.WriteAsciiFixed(ref pos, title, 60); - byte flags = 0x00; - if (warmode) - flags |= 0x01; - if (canLift) - flags |= 0x02; - - expectedData.Write(ref pos, flags); - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(10, 1000, 10, 5)] - public void TestPlaySound(ushort soundID, int x, int y, int z) - { - Point3D p = new Point3D(x, y, z); - - Span data = new PlaySound(soundID, p).Compile(); - - Span expectedData = stackalloc byte[12]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x54); // Packet ID - expectedData.Write(ref pos, (byte)1); // Flags - expectedData.Write(ref pos, soundID); - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (ushort)0); // Volume -#else - pos += 2; -#endif - - expectedData.Write(ref pos, (ushort)p.X); - expectedData.Write(ref pos, (ushort)p.Y); - expectedData.Write(ref pos, (short)p.Z); - - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(MusicName.Approach)] - [InlineData(MusicName.Combat1)] - [InlineData(MusicName.ValoriaShips)] - public void TestPlayMusic(MusicName music) - { - Span data = new PlayMusic(music).Compile(); - - Span expectedData = stackalloc byte[3]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x6D); // Packet ID - expectedData.Write(ref pos, (ushort)music); // Flags - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(10, 1, "Some text")] - [InlineData(100, 10, "Some more text")] - public void TestScrollMessage(int type, int tip, string text) - { - Span data = new ScrollMessage(type, tip, text).Compile(); - - text ??= ""; - int length = 10 + text.Length; - Span expectedData = stackalloc byte[length]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xA6); // Packet ID - expectedData.Write(ref pos, (ushort)length); // Length - expectedData.Write(ref pos, (byte)type); - expectedData.Write(ref pos, tip); - expectedData.Write(ref pos, (ushort)text.Length); - expectedData.WriteAscii(ref pos, text); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestCurrentTime() - { - DateTime date = DateTime.Parse("2020-01-01 14:10:05"); - - Span data = new CurrentTime(date).Compile(); - - Span expectedData = stackalloc byte[4]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x5B); // Packet ID - expectedData.Write(ref pos, (byte)date.Hour); - expectedData.Write(ref pos, (byte)date.Minute); - expectedData.Write(ref pos, (byte)date.Second); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestPathfindMessage() - { - var p = new Point3D(1000, 10, 1); - Span data = new PathfindMessage(p).Compile(); - - Span expectedData = stackalloc byte[7]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x38); // Packet ID - expectedData.Write(ref pos, (ushort)p.X); - expectedData.Write(ref pos, (ushort)p.Y); - expectedData.Write(ref pos, (short)p.Z); - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(0)] - [InlineData(10)] - [InlineData(100)] - public void TestPingAck(byte ping) - { - Span data = new PingAck(ping).Compile(); - - Span expectedData = stackalloc byte[2]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x73); // Packet ID - expectedData.Write(ref pos, ping); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestClearAbility() - { - Span data = new ClearWeaponAbility().Compile(); - - Span expectedData = stackalloc byte[5]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xBF); // Packet ID - expectedData.Write(ref pos, (ushort)5); // Length - expectedData.Write(ref pos, (ushort)0x21); // Sub-packet - - AssertThat.Equal(data, expectedData); - } - } -} +using System; +using System.Buffers; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class PlayerPacketTests : IClassFixture + { + [Fact] + public void TestStatLockInfo() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var data = new StatLockInfo(m).Compile(); + + Span expectedData = stackalloc byte[12]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xBF); // Packet ID + expectedData.Write(ref pos, (ushort)12); // Length + expectedData.Write(ref pos, (ushort)0x19); // Sub-packet + expectedData.Write(ref pos, (byte)2); // Command + expectedData.Write(ref pos, m.Serial); + expectedData.Write(ref pos, (ushort)(((int)m.StrLock << 4) | ((int)m.DexLock << 2) | (int)m.IntLock)); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestChangeUpdateRange() + { + byte range = 10; + var data = new ChangeUpdateRange(range).Compile(); + + Span expectedData = stackalloc byte[2]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xC8); // Packet ID + expectedData.Write(ref pos, range); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void TestDeathStatus(bool isDead) + { + var data = new DeathStatus(isDead).Compile(); + + Span expectedData = stackalloc byte[2]; + var pos = 0; + + const byte dead = 0; + const byte alive = 2; + expectedData.Write(ref pos, (byte)0x2C); // Packet ID + expectedData.Write(ref pos, isDead ? dead : alive); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(0, true)] + [InlineData(0, false)] + [InlineData(100, true)] + [InlineData(1000, false)] + public void TestSpecialAbility(int abilityId, bool active) + { + var data = new ToggleSpecialAbility(abilityId, active).Compile(); + + Span expectedData = stackalloc byte[8]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xBF); // Packet ID + expectedData.Write(ref pos, (ushort)0x8); // Length + expectedData.Write(ref pos, (ushort)0x25); // Sub-packet + expectedData.Write(ref pos, (ushort)abilityId); + expectedData.Write(ref pos, active); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData("This is a header", "This is a body", "This is a footer")] + [InlineData(null, null, null)] + public void TestDisplayProfile(string header, string body, string footer) + { + Serial m = 0x1000; + + var data = new DisplayProfile(m, header, body, footer).Compile(); + + header ??= ""; + body ??= ""; + footer ??= ""; + + var length = 12 + header.Length + footer.Length * 2 + body.Length * 2; + + Span expectedData = stackalloc byte[length]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xB8); // Packet ID + expectedData.Write(ref pos, (ushort)length); // Length + expectedData.Write(ref pos, m); // Mobile Serial or Serial.Zero + expectedData.WriteAsciiNull(ref pos, header); + expectedData.WriteBigUniNull(ref pos, footer); + expectedData.WriteBigUniNull(ref pos, body); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(LRReason.CannotLift)] + [InlineData(LRReason.TryToSteal)] + public void TestLiftRej(LRReason reason) + { + var data = new LiftRej(reason).Compile(); + + Span expectedData = stackalloc byte[2]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x27); // Packet ID + expectedData.Write(ref pos, (byte)reason); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestLogoutAck() + { + var data = new LogoutAck().Compile(); + + Span expectedData = stackalloc byte[2]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xD1); // Packet ID + expectedData.Write(ref pos, (byte)0x1); // 1 - Ack + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(1, 2, 3)] + [InlineData(4, 5, 6)] + public void TestWeather(int type, int density, int temp) + { + var data = new Weather(type, density, temp).Compile(); + + Span expectedData = stackalloc byte[4]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x65); // Packet ID + expectedData.Write(ref pos, (byte)type); + expectedData.Write(ref pos, (byte)density); + expectedData.Write(ref pos, (byte)temp); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestRemoveEntity() + { + Serial e = 0x1000; + var data = new RemoveEntity(e).Compile(); + + Span expectedData = stackalloc byte[5]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x1D); // Packet ID + expectedData.Write(ref pos, e); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestServerChange() + { + var p = new Point3D(100, 1000, 1); + var map = Map.Felucca; + var data = new ServerChange(p, map).Compile(); + + Span expectedData = stackalloc byte[16]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x76); // Packet ID + expectedData.Write(ref pos, (ushort)p.X); + expectedData.Write(ref pos, (ushort)p.Y); + expectedData.Write(ref pos, (short)p.Z); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); // Unknown + expectedData.Write(ref pos, 0); // Server X, Server Y +#else + pos += 5; +#endif + expectedData.Write(ref pos, (ushort)map.Width); // Server Width + expectedData.Write(ref pos, (ushort)map.Height); // Server Height + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestSkillUpdate() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var skills = m.Skills; + m.Skills[SkillName.Alchemy].BaseFixedPoint = 1000; // GM Alchemy + + var data = new SkillUpdate(skills).Compile(); + + var length = 6 + skills.Length * 9; + Span expectedData = stackalloc byte[length]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x3A); // Packet ID + expectedData.Write(ref pos, (ushort)length); // Length + expectedData.Write(ref pos, (byte)0x02); // type: absolute, capped + + for (var i = 0; i < skills.Length; i++) + { + var s = skills[i]; + + var v = s.NonRacialValue; + var uv = Math.Clamp((int)(v * 10), 0, 0xFFFF); + + expectedData.Write(ref pos, (ushort)(s.Info.SkillID + 1)); + expectedData.Write(ref pos, (ushort)uv); + expectedData.Write(ref pos, (ushort)s.BaseFixedPoint); + expectedData.Write(ref pos, (byte)s.Lock); + expectedData.Write(ref pos, (ushort)s.CapFixedPoint); + } + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(0)] + [InlineData(10)] + [InlineData(255)] + public void TestSequence(byte num) + { + var data = new Sequence(num).Compile(); + + Span expectedData = stackalloc byte[2]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x7B); // Packet ID + expectedData.Write(ref pos, num); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(SkillName.Alchemy, 0, 1)] + [InlineData(SkillName.Archery, 10, 1000)] + [InlineData(SkillName.Begging, 100000, 1000)] + public void TestSkillChange(SkillName skillName, int baseFixedPoint, int capFixedPoint) + { + // TODO: Eliminate all of this and just create a Skill directly + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var skill = m.Skills[skillName]; + skill.BaseFixedPoint = baseFixedPoint; + skill.CapFixedPoint = capFixedPoint; + + var data = new SkillChange(skill).Compile(); + + Span expectedData = stackalloc byte[13]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x3A); // Packet ID + expectedData.Write(ref pos, (ushort)13); // Length + expectedData.Write(ref pos, (byte)0xDF); // type: delta, capped + + var v = skill.NonRacialValue; + var uv = Math.Clamp((int)(v * 10), 0, 0xFFFF); + + expectedData.Write(ref pos, (ushort)skill.Info.SkillID); + expectedData.Write(ref pos, (ushort)uv); + expectedData.Write(ref pos, (ushort)skill.BaseFixedPoint); + expectedData.Write(ref pos, (byte)skill.Lock); + expectedData.Write(ref pos, (ushort)skill.CapFixedPoint); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData("This is a URL, I promise")] + public void TestLaunchBrowser(string url) + { + var data = new LaunchBrowser(url).Compile(); + + url ??= ""; + + var length = 4 + url.Length; + Span expectedData = stackalloc byte[length]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xA5); // Packet ID + expectedData.Write(ref pos, (ushort)length); // Length + expectedData.WriteAsciiNull(ref pos, url); // Note: use punycode for unicode URLs + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestDragEffect() + { + var src = new Entity(0x1, new Point3D(1000, 100, 10), Map.Felucca); + var targ = new Entity(0x2, new Point3D(1125, 125, 5), Map.Felucca); + var itemID = 0x384; + var hue = 1024; + var amount = 25; + + var data = new DragEffect(src, targ, itemID, hue, amount).Compile(); + + Span expectedData = stackalloc byte[26]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x23); // Packet ID + expectedData.Write(ref pos, (ushort)itemID); + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); +#else + pos++; +#endif + + expectedData.Write(ref pos, (ushort)hue); + expectedData.Write(ref pos, (ushort)amount); + expectedData.Write(ref pos, src.Serial); + expectedData.Write(ref pos, src.Location); + expectedData.Write(ref pos, targ.Serial); + expectedData.Write(ref pos, targ.Location); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(1, false)] + [InlineData(2, true)] + public void TestSeasonChange(int season, bool playSound) + { + var data = new SeasonChange(season, playSound).Compile(); + + Span expectedData = stackalloc byte[3]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xBC); // Packet ID + expectedData.Write(ref pos, (byte)season); + expectedData.Write(ref pos, playSound); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(0x1024, "Test Title", true, true)] + [InlineData(0x1024, "Test Title", false, true)] + [InlineData(0x1024, "Test Title", true, false)] + public void TestDisplayPaperdoll(uint m, string title, bool warmode, bool canLift) + { + var data = new DisplayPaperdoll(m, title, warmode, canLift).Compile(); + + Span expectedData = stackalloc byte[66]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x88); // Packet ID + expectedData.Write(ref pos, m); + expectedData.WriteAsciiFixed(ref pos, title, 60); + byte flags = 0x00; + if (warmode) + flags |= 0x01; + if (canLift) + flags |= 0x02; + + expectedData.Write(ref pos, flags); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(10, 1000, 10, 5)] + public void TestPlaySound(ushort soundID, int x, int y, int z) + { + var p = new Point3D(x, y, z); + + var data = new PlaySound(soundID, p).Compile(); + + Span expectedData = stackalloc byte[12]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x54); // Packet ID + expectedData.Write(ref pos, (byte)1); // Flags + expectedData.Write(ref pos, soundID); + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (ushort)0); // Volume +#else + pos += 2; +#endif + + expectedData.Write(ref pos, (ushort)p.X); + expectedData.Write(ref pos, (ushort)p.Y); + expectedData.Write(ref pos, (short)p.Z); + + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(MusicName.Approach)] + [InlineData(MusicName.Combat1)] + [InlineData(MusicName.ValoriaShips)] + public void TestPlayMusic(MusicName music) + { + var data = new PlayMusic(music).Compile(); + + Span expectedData = stackalloc byte[3]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x6D); // Packet ID + expectedData.Write(ref pos, (ushort)music); // Flags + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(10, 1, "Some text")] + [InlineData(100, 10, "Some more text")] + public void TestScrollMessage(int type, int tip, string text) + { + var data = new ScrollMessage(type, tip, text).Compile(); + + text ??= ""; + var length = 10 + text.Length; + Span expectedData = stackalloc byte[length]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xA6); // Packet ID + expectedData.Write(ref pos, (ushort)length); // Length + expectedData.Write(ref pos, (byte)type); + expectedData.Write(ref pos, tip); + expectedData.Write(ref pos, (ushort)text.Length); + expectedData.WriteAscii(ref pos, text); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestCurrentTime() + { + var date = DateTime.Parse("2020-01-01 14:10:05"); + + var data = new CurrentTime(date).Compile(); + + Span expectedData = stackalloc byte[4]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x5B); // Packet ID + expectedData.Write(ref pos, (byte)date.Hour); + expectedData.Write(ref pos, (byte)date.Minute); + expectedData.Write(ref pos, (byte)date.Second); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestPathfindMessage() + { + var p = new Point3D(1000, 10, 1); + var data = new PathfindMessage(p).Compile(); + + Span expectedData = stackalloc byte[7]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x38); // Packet ID + expectedData.Write(ref pos, (ushort)p.X); + expectedData.Write(ref pos, (ushort)p.Y); + expectedData.Write(ref pos, (short)p.Z); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(0)] + [InlineData(10)] + [InlineData(100)] + public void TestPingAck(byte ping) + { + var data = new PingAck(ping).Compile(); + + Span expectedData = stackalloc byte[2]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x73); // Packet ID + expectedData.Write(ref pos, ping); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestClearAbility() + { + var data = new ClearWeaponAbility().Compile(); + + Span expectedData = stackalloc byte[5]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xBF); // Packet ID + expectedData.Write(ref pos, (ushort)5); // Length + expectedData.Write(ref pos, (ushort)0x21); // Sub-packet + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/SecureTradePacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/SecureTradePacketTests.cs index 1b8228613..28551081a 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/SecureTradePacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/SecureTradePacketTests.cs @@ -1,171 +1,171 @@ -using System; -using System.Buffers; -using Server.Items; -using Server.Network; -using Xunit; - -namespace Server.Tests.Network.Packets -{ - public class SecureTradePacketTests : IClassFixture - { - [Theory] - [InlineData("short-name")] - [InlineData("this is a really long name that is more than 30 characters, probably")] - public void TestDisplaySecureTrade(string name) - { - var m = new Mobile(0x1); - m.DefaultMobileInit(); - - var firstCont = new Container(Serial.LastItem + 1); - var secondCont = new Container(Serial.LastItem + 2); - - Span data = new DisplaySecureTrade(m, firstCont, secondCont, name).Compile(); - - bool hasName = name.Length > 0; - - Span expectedData = stackalloc byte[17 + (hasName ? 30 : 0)]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x6F); // Packet ID - expectedData.Write(ref pos, (ushort)0x2F); // Length - expectedData.Write(ref pos, (byte)TradeFlag.Display); // Command - expectedData.Write(ref pos, m.Serial); - expectedData.Write(ref pos, firstCont.Serial); - expectedData.Write(ref pos, secondCont.Serial); - expectedData.Write(ref pos, hasName); - if (hasName) - expectedData.WriteAsciiFixed(ref pos, name, 30); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestCloseSecureTrade() - { - var cont = new Container(Serial.LastItem + 1); - - Span data = new CloseSecureTrade(cont).Compile(); - - Span expectedData = stackalloc byte[8]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x6F); // Packet ID - expectedData.Write(ref pos, (ushort)0x8); // Length - expectedData.Write(ref pos, (byte)TradeFlag.Close); // Command - expectedData.Write(ref pos, cont.Serial); - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(true, false)] // Update first - [InlineData(false, true)] // Update second - public void TestUpdateSecureTrade(bool first, bool second) - { - var firstCont = new Container(Serial.LastItem + 1); - var secondCont = new Container(Serial.LastItem + 2); - - Container cont = first ? firstCont : secondCont; - Span data = new UpdateSecureTrade(cont, first, second).Compile(); - - Span expectedData = stackalloc byte[16]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x6F); // Packet ID - expectedData.Write(ref pos, (ushort)0x10); // Length - expectedData.Write(ref pos, (byte)TradeFlag.Update); // Command - expectedData.Write(ref pos, cont.Serial); - expectedData.Write(ref pos, first ? 1 : 0); // true if first - expectedData.Write(ref pos, second ? 1 : 0); // true if second - - AssertThat.Equal(data, expectedData); - } - - [Theory] - [InlineData(100000, 30, TradeFlag.UpdateGold)] - [InlineData(250000, 50000, TradeFlag.UpdateLedger)] - public void TestUpdateGoldSecureTrade(int gold, int plat, TradeFlag flag) - { - var cont = new Container(Serial.LastItem + 1); - Span data = new UpdateSecureTrade(cont, flag, gold, plat).Compile(); - - Span expectedData = stackalloc byte[16]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x6F); // Packet ID - expectedData.Write(ref pos, (ushort)0x10); // Length - expectedData.Write(ref pos, (byte)flag); // Command - expectedData.Write(ref pos, cont.Serial); - expectedData.Write(ref pos, gold); - expectedData.Write(ref pos, plat); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestSecureTradeEquip() - { - var m = new Mobile(0x1); - m.DefaultMobileInit(); - - var cont = new Container(Serial.LastItem + 1); - var itemInCont = new Item(Serial.LastItem + 2) { Parent = cont }; - - Span data = new SecureTradeEquip(itemInCont, m).Compile(); - Span expectedData = stackalloc byte[20]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x25); // Packet ID - expectedData.Write(ref pos, itemInCont.Serial); - expectedData.Write(ref pos, (short)itemInCont.ItemID); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); -#else - pos++; -#endif - expectedData.Write(ref pos, (short)itemInCont.Amount); - expectedData.Write(ref pos, (short)itemInCont.X); - expectedData.Write(ref pos, (short)itemInCont.Y); - expectedData.Write(ref pos, m.Serial); - expectedData.Write(ref pos, (short)itemInCont.Hue); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestSecureTradeEquip6017() - { - var m = new Mobile(0x1); - m.DefaultMobileInit(); - - var cont = new Container(Serial.LastItem + 1); - var itemInCont = new Item(Serial.LastItem + 2) { Parent = cont }; - - Span data = new SecureTradeEquip6017(itemInCont, m).Compile(); - - Span expectedData = stackalloc byte[21]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x25); // Packet ID - expectedData.Write(ref pos, itemInCont.Serial); - expectedData.Write(ref pos, (short)itemInCont.ItemID); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); -#else - pos++; -#endif - expectedData.Write(ref pos, (short)itemInCont.Amount); - expectedData.Write(ref pos, (short)itemInCont.X); - expectedData.Write(ref pos, (short)itemInCont.Y); -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); -#else - pos++; -#endif - expectedData.Write(ref pos, m.Serial); - expectedData.Write(ref pos, (short)itemInCont.Hue); - - AssertThat.Equal(data, expectedData); - } - } -} +using System; +using System.Buffers; +using Server.Items; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class SecureTradePacketTests : IClassFixture + { + [Theory] + [InlineData("short-name")] + [InlineData("this is a really long name that is more than 30 characters, probably")] + public void TestDisplaySecureTrade(string name) + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var firstCont = new Container(Serial.LastItem + 1); + var secondCont = new Container(Serial.LastItem + 2); + + var data = new DisplaySecureTrade(m, firstCont, secondCont, name).Compile(); + + var hasName = name.Length > 0; + + Span expectedData = stackalloc byte[17 + (hasName ? 30 : 0)]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x6F); // Packet ID + expectedData.Write(ref pos, (ushort)0x2F); // Length + expectedData.Write(ref pos, (byte)TradeFlag.Display); // Command + expectedData.Write(ref pos, m.Serial); + expectedData.Write(ref pos, firstCont.Serial); + expectedData.Write(ref pos, secondCont.Serial); + expectedData.Write(ref pos, hasName); + if (hasName) + expectedData.WriteAsciiFixed(ref pos, name, 30); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestCloseSecureTrade() + { + var cont = new Container(Serial.LastItem + 1); + + var data = new CloseSecureTrade(cont).Compile(); + + Span expectedData = stackalloc byte[8]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x6F); // Packet ID + expectedData.Write(ref pos, (ushort)0x8); // Length + expectedData.Write(ref pos, (byte)TradeFlag.Close); // Command + expectedData.Write(ref pos, cont.Serial); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(true, false)] // Update first + [InlineData(false, true)] // Update second + public void TestUpdateSecureTrade(bool first, bool second) + { + var firstCont = new Container(Serial.LastItem + 1); + var secondCont = new Container(Serial.LastItem + 2); + + var cont = first ? firstCont : secondCont; + var data = new UpdateSecureTrade(cont, first, second).Compile(); + + Span expectedData = stackalloc byte[16]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x6F); // Packet ID + expectedData.Write(ref pos, (ushort)0x10); // Length + expectedData.Write(ref pos, (byte)TradeFlag.Update); // Command + expectedData.Write(ref pos, cont.Serial); + expectedData.Write(ref pos, first ? 1 : 0); // true if first + expectedData.Write(ref pos, second ? 1 : 0); // true if second + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(100000, 30, TradeFlag.UpdateGold)] + [InlineData(250000, 50000, TradeFlag.UpdateLedger)] + public void TestUpdateGoldSecureTrade(int gold, int plat, TradeFlag flag) + { + var cont = new Container(Serial.LastItem + 1); + var data = new UpdateSecureTrade(cont, flag, gold, plat).Compile(); + + Span expectedData = stackalloc byte[16]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x6F); // Packet ID + expectedData.Write(ref pos, (ushort)0x10); // Length + expectedData.Write(ref pos, (byte)flag); // Command + expectedData.Write(ref pos, cont.Serial); + expectedData.Write(ref pos, gold); + expectedData.Write(ref pos, plat); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestSecureTradeEquip() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var cont = new Container(Serial.LastItem + 1); + var itemInCont = new Item(Serial.LastItem + 2) { Parent = cont }; + + var data = new SecureTradeEquip(itemInCont, m).Compile(); + Span expectedData = stackalloc byte[20]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x25); // Packet ID + expectedData.Write(ref pos, itemInCont.Serial); + expectedData.Write(ref pos, (short)itemInCont.ItemID); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); +#else + pos++; +#endif + expectedData.Write(ref pos, (short)itemInCont.Amount); + expectedData.Write(ref pos, (short)itemInCont.X); + expectedData.Write(ref pos, (short)itemInCont.Y); + expectedData.Write(ref pos, m.Serial); + expectedData.Write(ref pos, (short)itemInCont.Hue); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestSecureTradeEquip6017() + { + var m = new Mobile(0x1); + m.DefaultMobileInit(); + + var cont = new Container(Serial.LastItem + 1); + var itemInCont = new Item(Serial.LastItem + 2) { Parent = cont }; + + var data = new SecureTradeEquip6017(itemInCont, m).Compile(); + + Span expectedData = stackalloc byte[21]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x25); // Packet ID + expectedData.Write(ref pos, itemInCont.Serial); + expectedData.Write(ref pos, (short)itemInCont.ItemID); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); +#else + pos++; +#endif + expectedData.Write(ref pos, (short)itemInCont.Amount); + expectedData.Write(ref pos, (short)itemInCont.X); + expectedData.Write(ref pos, (short)itemInCont.Y); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); +#else + pos++; +#endif + expectedData.Write(ref pos, m.Serial); + expectedData.Write(ref pos, (short)itemInCont.Hue); + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/TargetPacketsTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/TargetPacketsTests.cs index 6bb26c7bf..1fd035520 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/TargetPacketsTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/TargetPacketsTests.cs @@ -1,161 +1,161 @@ -using System; -using System.Buffers; -using Server.Network; -using Server.Targeting; -using Xunit; - -namespace Server.Tests.Network.Packets -{ - public class TestMultiTarget : MultiTarget - { - public TestMultiTarget( - int multiID, - Point3D offset, - int range = 10, - bool allowGround = true, - TargetFlags flags = TargetFlags.None - ) : base(multiID, offset, range, allowGround, flags) - { - } - } - - public class TestTarget : Target - { - public TestTarget( - int range, - bool allowGround, - TargetFlags flags - ) : base(range, allowGround, flags) - { - } - } - - public class TargetPacketsTests - { - [Fact] - public void TestMultiTargetReqHS() - { - int multiID = 0x1024; - Point3D p = new Point3D(1000, 100, 10); - MultiTarget t = new TestMultiTarget(multiID, p); - - Span data = new MultiTargetReqHS(t).Compile(); - - Span expectedData = stackalloc byte[30]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x99); // Packet ID - expectedData.Write(ref pos, t.AllowGround); - expectedData.Write(ref pos, t.TargetID); - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, 0); - expectedData.Write(ref pos, (ushort)0); - expectedData.Write(ref pos, (ushort)0); - expectedData.Write(ref pos, (byte)0); - expectedData.Write(ref pos, (byte)0); - expectedData.Write(ref pos, (ushort)0); -#else - pos += 12; -#endif - - expectedData.Write(ref pos, (short)t.MultiID); - expectedData.Write(ref pos, (ushort)t.Offset.X); - expectedData.Write(ref pos, (ushort)t.Offset.Y); - expectedData.Write(ref pos, (short)t.Offset.Z); - -#if NO_LOCAL_INIT - // Hue (4 bytes) - expectedData.Write(ref pos, 0); -#endif - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestMultiTargetReq() - { - int multiID = 0x1024; - Point3D p = new Point3D(1000, 100, 10); - MultiTarget t = new TestMultiTarget(multiID, p); - - Span data = new MultiTargetReq(t).Compile(); - - Span expectedData = stackalloc byte[26]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x99); // Packet ID - expectedData.Write(ref pos, t.AllowGround); - expectedData.Write(ref pos, t.TargetID); - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, 0); - expectedData.Write(ref pos, (ushort)0); - expectedData.Write(ref pos, (ushort)0); - expectedData.Write(ref pos, (byte)0); - expectedData.Write(ref pos, (byte)0); - expectedData.Write(ref pos, (ushort)0); -#else - pos += 12; -#endif - - expectedData.Write(ref pos, (short)t.MultiID); - expectedData.Write(ref pos, (ushort)t.Offset.X); - expectedData.Write(ref pos, (ushort)t.Offset.Y); - expectedData.Write(ref pos, (short)t.Offset.Z); - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestCancelTarget() - { - Span data = new CancelTarget().Compile(); - - Span expectedData = stackalloc byte[19]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x6C); // Packet ID - expectedData.Write(ref pos, (byte)0); - expectedData.Write(ref pos, 0); - expectedData.Write(ref pos, (byte)3); // Beneficial / Harmful - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, 0); - expectedData.Write(ref pos, (ushort)0); - expectedData.Write(ref pos, (ushort)0); - expectedData.Write(ref pos, (byte)0); - expectedData.Write(ref pos, (byte)0); - expectedData.Write(ref pos, (ushort)0); -#endif - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestTargetReq() - { - var t = new TestTarget(10, true, TargetFlags.Beneficial); - Span data = new TargetReq(t).Compile(); - - Span expectedData = stackalloc byte[19]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x6C); // Packet ID - expectedData.Write(ref pos, t.AllowGround); - expectedData.Write(ref pos, t.TargetID); - expectedData.Write(ref pos, (byte)t.Flags); - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, 0); - expectedData.Write(ref pos, (ushort)0); - expectedData.Write(ref pos, (ushort)0); - expectedData.Write(ref pos, (byte)0); - expectedData.Write(ref pos, (byte)0); - expectedData.Write(ref pos, (ushort)0); -#endif - - AssertThat.Equal(data, expectedData); - } - } -} +using System; +using System.Buffers; +using Server.Network; +using Server.Targeting; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class TestMultiTarget : MultiTarget + { + public TestMultiTarget( + int multiID, + Point3D offset, + int range = 10, + bool allowGround = true, + TargetFlags flags = TargetFlags.None + ) : base(multiID, offset, range, allowGround, flags) + { + } + } + + public class TestTarget : Target + { + public TestTarget( + int range, + bool allowGround, + TargetFlags flags + ) : base(range, allowGround, flags) + { + } + } + + public class TargetPacketsTests + { + [Fact] + public void TestMultiTargetReqHS() + { + var multiID = 0x1024; + var p = new Point3D(1000, 100, 10); + MultiTarget t = new TestMultiTarget(multiID, p); + + var data = new MultiTargetReqHS(t).Compile(); + + Span expectedData = stackalloc byte[30]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x99); // Packet ID + expectedData.Write(ref pos, t.AllowGround); + expectedData.Write(ref pos, t.TargetID); + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, 0); + expectedData.Write(ref pos, (ushort)0); + expectedData.Write(ref pos, (ushort)0); + expectedData.Write(ref pos, (byte)0); + expectedData.Write(ref pos, (byte)0); + expectedData.Write(ref pos, (ushort)0); +#else + pos += 12; +#endif + + expectedData.Write(ref pos, (short)t.MultiID); + expectedData.Write(ref pos, (ushort)t.Offset.X); + expectedData.Write(ref pos, (ushort)t.Offset.Y); + expectedData.Write(ref pos, (short)t.Offset.Z); + +#if NO_LOCAL_INIT + // Hue (4 bytes) + expectedData.Write(ref pos, 0); +#endif + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestMultiTargetReq() + { + var multiID = 0x1024; + var p = new Point3D(1000, 100, 10); + MultiTarget t = new TestMultiTarget(multiID, p); + + var data = new MultiTargetReq(t).Compile(); + + Span expectedData = stackalloc byte[26]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x99); // Packet ID + expectedData.Write(ref pos, t.AllowGround); + expectedData.Write(ref pos, t.TargetID); + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, 0); + expectedData.Write(ref pos, (ushort)0); + expectedData.Write(ref pos, (ushort)0); + expectedData.Write(ref pos, (byte)0); + expectedData.Write(ref pos, (byte)0); + expectedData.Write(ref pos, (ushort)0); +#else + pos += 12; +#endif + + expectedData.Write(ref pos, (short)t.MultiID); + expectedData.Write(ref pos, (ushort)t.Offset.X); + expectedData.Write(ref pos, (ushort)t.Offset.Y); + expectedData.Write(ref pos, (short)t.Offset.Z); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestCancelTarget() + { + var data = new CancelTarget().Compile(); + + Span expectedData = stackalloc byte[19]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x6C); // Packet ID + expectedData.Write(ref pos, (byte)0); + expectedData.Write(ref pos, 0); + expectedData.Write(ref pos, (byte)3); // Beneficial / Harmful + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, 0); + expectedData.Write(ref pos, (ushort)0); + expectedData.Write(ref pos, (ushort)0); + expectedData.Write(ref pos, (byte)0); + expectedData.Write(ref pos, (byte)0); + expectedData.Write(ref pos, (ushort)0); +#endif + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestTargetReq() + { + var t = new TestTarget(10, true, TargetFlags.Beneficial); + var data = new TargetReq(t).Compile(); + + Span expectedData = stackalloc byte[19]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x6C); // Packet ID + expectedData.Write(ref pos, t.AllowGround); + expectedData.Write(ref pos, t.TargetID); + expectedData.Write(ref pos, (byte)t.Flags); + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, 0); + expectedData.Write(ref pos, (ushort)0); + expectedData.Write(ref pos, (ushort)0); + expectedData.Write(ref pos, (byte)0); + expectedData.Write(ref pos, (byte)0); + expectedData.Write(ref pos, (ushort)0); +#endif + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/UnicodePromptTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/UnicodePromptTests.cs index 8de43d3be..8219ad434 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/UnicodePromptTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/UnicodePromptTests.cs @@ -1,37 +1,37 @@ -using System; -using System.Buffers; -using Server.Network; -using Server.Prompts; -using Xunit; - -namespace Server.Tests.Network.Packets -{ - internal class TestPrompt : Prompt - { - } - - public class UnicodePromptTests - { - [Fact] - public void TestUnicodePrompt() - { - var prompt = new TestPrompt(); - Span data = new UnicodePrompt(prompt).Compile(); - - Span expectedData = stackalloc byte[21]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0xC2); // Packet ID - expectedData.Write(ref pos, (ushort)0x15); // Length - expectedData.Write(ref pos, prompt.Serial); - expectedData.Write(ref pos, prompt.Serial); - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (ulong)0); - expectedData.Write(ref pos, (ushort)0); -#endif - - AssertThat.Equal(data, expectedData); - } - } -} +using System; +using System.Buffers; +using Server.Network; +using Server.Prompts; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + internal class TestPrompt : Prompt + { + } + + public class UnicodePromptTests + { + [Fact] + public void TestUnicodePrompt() + { + var prompt = new TestPrompt(); + var data = new UnicodePrompt(prompt).Compile(); + + Span expectedData = stackalloc byte[21]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0xC2); // Packet ID + expectedData.Write(ref pos, (ushort)0x15); // Length + expectedData.Write(ref pos, prompt.Serial); + expectedData.Write(ref pos, prompt.Serial); + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (ulong)0); + expectedData.Write(ref pos, (ushort)0); +#endif + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/VendorBuyPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/VendorBuyPacketTests.cs index b8196e843..3c3282872 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/VendorBuyPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/VendorBuyPacketTests.cs @@ -1,198 +1,198 @@ -using System; -using System.Buffers; -using System.Collections.Generic; -using System.Linq; -using Server.Items; -using Server.Network; -using Xunit; - -namespace Server.Tests.Network.Packets -{ - public class VendorBuyPacketTests : IClassFixture - { - [Fact] - public void TestVendorBuyContent() - { - var cont = new Container(Serial.LastItem + 1); - - var buyStates = new List - { - new BuyItemState("First Item", cont.Serial, Serial.NewItem, 10, 1, 0x01, 0), - new BuyItemState("Second Item", cont.Serial, Serial.NewItem, 20, 2, 0x0A, 0), - new BuyItemState("Third Item", cont.Serial, Serial.NewItem, 30, 10, 0x0F, 0) - }; - - Span data = new VendorBuyContent(buyStates).Compile(); - - Span expectedData = stackalloc byte[5 + buyStates.Count * 19]; - - int pos = 0; - - expectedData.Write(ref pos, (byte)0x3C); // Packet ID - expectedData.Write(ref pos, (ushort)expectedData.Length); // Length - expectedData.Write(ref pos, (ushort)buyStates.Count); // Count - - for (int i = buyStates.Count - 1; i >= 0; i--) - { - BuyItemState buyState = buyStates[i]; - - expectedData.Write(ref pos, buyState.MySerial); - expectedData.Write(ref pos, (ushort)buyState.ItemID); - pos++; // ItemID Offset - expectedData.Write(ref pos, (ushort)buyState.Amount); - expectedData.Write(ref pos, (ushort)(i + 1)); // X - expectedData.Write(ref pos, (ushort)1); // Y - expectedData.Write(ref pos, buyState.ContainerSerial); - expectedData.Write(ref pos, (ushort)buyState.Hue); - } - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestVendorBuyContent6017() - { - var cont = new Container(Serial.LastItem + 1); - - var buyStates = new List - { - new BuyItemState("First Item", cont.Serial, Serial.NewItem, 10, 1, 0x01, 0), - new BuyItemState("Second Item", cont.Serial, Serial.NewItem, 20, 2, 0x0A, 0), - new BuyItemState("Third Item", cont.Serial, Serial.NewItem, 30, 10, 0x0F, 0) - }; - - Span data = new VendorBuyContent6017(buyStates).Compile(); - - Span expectedData = stackalloc byte[5 + buyStates.Count * 20]; - - int pos = 0; - - expectedData.Write(ref pos, (byte)0x3C); // Packet ID - expectedData.Write(ref pos, (ushort)expectedData.Length); // Length - expectedData.Write(ref pos, (ushort)buyStates.Count); // Count - - for (int i = buyStates.Count - 1; i >= 0; i--) - { - BuyItemState buyState = buyStates[i]; - - expectedData.Write(ref pos, buyState.MySerial); - expectedData.Write(ref pos, (ushort)buyState.ItemID); - pos++; // ItemID Offset - expectedData.Write(ref pos, (ushort)buyState.Amount); - expectedData.Write(ref pos, (ushort)(i + 1)); // X - expectedData.Write(ref pos, (ushort)1); // Y -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); // Grid Location? -#else - pos++; -#endif - expectedData.Write(ref pos, buyState.ContainerSerial); - expectedData.Write(ref pos, (ushort)buyState.Hue); - } - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestDisplayBuyList() - { - var vendor = new Mobile(0x1); - vendor.DefaultMobileInit(); - - Span data = new DisplayBuyList(vendor).Compile(); - - Span expectedData = stackalloc byte[7]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x24); // Packet ID - expectedData.Write(ref pos, vendor.Serial); - expectedData.Write(ref pos, (ushort)0x30); // Buy gump - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestDisplayBuyListHS() - { - var vendor = new Mobile(0x1); - vendor.DefaultMobileInit(); - - Span data = new DisplayBuyListHS(vendor).Compile(); - - Span expectedData = stackalloc byte[9]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x24); // Packet ID - expectedData.Write(ref pos, vendor.Serial); - expectedData.Write(ref pos, (ushort)0x30); // Buy gump - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (ushort)0); -#endif - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestVendorBuyList() - { - var vendor = new Mobile(0x1); - vendor.DefaultMobileInit(); - - var cont = new Container(Serial.LastItem + 1); - - var buyStates = new List - { - new BuyItemState("First Item", cont.Serial, Serial.NewItem, 10, 1, 0x01, 0), - new BuyItemState("Second Item", cont.Serial, Serial.NewItem, 20, 2, 0x0A, 0), - new BuyItemState("Third Item", cont.Serial, Serial.NewItem, 30, 10, 0x0F, 0) - }; - - Span data = new VendorBuyList(vendor, buyStates).Compile(); - - int length = 8 + buyStates.Sum(state => 6 + state.Description.Length); - - Span expectedData = stackalloc byte[length]; - - int pos = 0; - - expectedData.Write(ref pos, (byte)0x74); // Packet ID - expectedData.Write(ref pos, (ushort)expectedData.Length); // Length - expectedData.Write(ref pos, Serial.MinusOne); // Vendor Buy Pack Serial or -1 - expectedData.Write(ref pos, (byte)buyStates.Count); - - for (int i = 0; i < buyStates.Count; i++) - { - BuyItemState state = buyStates[i]; - expectedData.Write(ref pos, state.Price); - var description = state.Description ?? ""; - expectedData.Write(ref pos, (byte)Math.Min(255, description.Length + 1)); - expectedData.WriteAsciiNull(ref pos, description, 255); - } - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestEndVendorBuy() - { - var vendor = new Mobile(0x1); - vendor.DefaultMobileInit(); - - Span data = new EndVendorBuy(vendor).Compile(); - - Span expectedData = stackalloc byte[8]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x3B); // Packet ID - expectedData.Write(ref pos, (ushort)0x8); // Length - expectedData.Write(ref pos, vendor.Serial); - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)-); -#endif - - AssertThat.Equal(data, expectedData); - } - } -} +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Linq; +using Server.Items; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class VendorBuyPacketTests : IClassFixture + { + [Fact] + public void TestVendorBuyContent() + { + var cont = new Container(Serial.LastItem + 1); + + var buyStates = new List + { + new BuyItemState("First Item", cont.Serial, Serial.NewItem, 10, 1, 0x01, 0), + new BuyItemState("Second Item", cont.Serial, Serial.NewItem, 20, 2, 0x0A, 0), + new BuyItemState("Third Item", cont.Serial, Serial.NewItem, 30, 10, 0x0F, 0) + }; + + var data = new VendorBuyContent(buyStates).Compile(); + + Span expectedData = stackalloc byte[5 + buyStates.Count * 19]; + + var pos = 0; + + expectedData.Write(ref pos, (byte)0x3C); // Packet ID + expectedData.Write(ref pos, (ushort)expectedData.Length); // Length + expectedData.Write(ref pos, (ushort)buyStates.Count); // Count + + for (var i = buyStates.Count - 1; i >= 0; i--) + { + var buyState = buyStates[i]; + + expectedData.Write(ref pos, buyState.MySerial); + expectedData.Write(ref pos, (ushort)buyState.ItemID); + pos++; // ItemID Offset + expectedData.Write(ref pos, (ushort)buyState.Amount); + expectedData.Write(ref pos, (ushort)(i + 1)); // X + expectedData.Write(ref pos, (ushort)1); // Y + expectedData.Write(ref pos, buyState.ContainerSerial); + expectedData.Write(ref pos, (ushort)buyState.Hue); + } + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestVendorBuyContent6017() + { + var cont = new Container(Serial.LastItem + 1); + + var buyStates = new List + { + new BuyItemState("First Item", cont.Serial, Serial.NewItem, 10, 1, 0x01, 0), + new BuyItemState("Second Item", cont.Serial, Serial.NewItem, 20, 2, 0x0A, 0), + new BuyItemState("Third Item", cont.Serial, Serial.NewItem, 30, 10, 0x0F, 0) + }; + + var data = new VendorBuyContent6017(buyStates).Compile(); + + Span expectedData = stackalloc byte[5 + buyStates.Count * 20]; + + var pos = 0; + + expectedData.Write(ref pos, (byte)0x3C); // Packet ID + expectedData.Write(ref pos, (ushort)expectedData.Length); // Length + expectedData.Write(ref pos, (ushort)buyStates.Count); // Count + + for (var i = buyStates.Count - 1; i >= 0; i--) + { + var buyState = buyStates[i]; + + expectedData.Write(ref pos, buyState.MySerial); + expectedData.Write(ref pos, (ushort)buyState.ItemID); + pos++; // ItemID Offset + expectedData.Write(ref pos, (ushort)buyState.Amount); + expectedData.Write(ref pos, (ushort)(i + 1)); // X + expectedData.Write(ref pos, (ushort)1); // Y +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); // Grid Location? +#else + pos++; +#endif + expectedData.Write(ref pos, buyState.ContainerSerial); + expectedData.Write(ref pos, (ushort)buyState.Hue); + } + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestDisplayBuyList() + { + var vendor = new Mobile(0x1); + vendor.DefaultMobileInit(); + + var data = new DisplayBuyList(vendor).Compile(); + + Span expectedData = stackalloc byte[7]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x24); // Packet ID + expectedData.Write(ref pos, vendor.Serial); + expectedData.Write(ref pos, (ushort)0x30); // Buy gump + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestDisplayBuyListHS() + { + var vendor = new Mobile(0x1); + vendor.DefaultMobileInit(); + + var data = new DisplayBuyListHS(vendor).Compile(); + + Span expectedData = stackalloc byte[9]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x24); // Packet ID + expectedData.Write(ref pos, vendor.Serial); + expectedData.Write(ref pos, (ushort)0x30); // Buy gump + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (ushort)0); +#endif + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestVendorBuyList() + { + var vendor = new Mobile(0x1); + vendor.DefaultMobileInit(); + + var cont = new Container(Serial.LastItem + 1); + + var buyStates = new List + { + new BuyItemState("First Item", cont.Serial, Serial.NewItem, 10, 1, 0x01, 0), + new BuyItemState("Second Item", cont.Serial, Serial.NewItem, 20, 2, 0x0A, 0), + new BuyItemState("Third Item", cont.Serial, Serial.NewItem, 30, 10, 0x0F, 0) + }; + + var data = new VendorBuyList(vendor, buyStates).Compile(); + + var length = 8 + buyStates.Sum(state => 6 + state.Description.Length); + + Span expectedData = stackalloc byte[length]; + + var pos = 0; + + expectedData.Write(ref pos, (byte)0x74); // Packet ID + expectedData.Write(ref pos, (ushort)expectedData.Length); // Length + expectedData.Write(ref pos, Serial.MinusOne); // Vendor Buy Pack Serial or -1 + expectedData.Write(ref pos, (byte)buyStates.Count); + + for (var i = 0; i < buyStates.Count; i++) + { + var state = buyStates[i]; + expectedData.Write(ref pos, state.Price); + var description = state.Description ?? ""; + expectedData.Write(ref pos, (byte)Math.Min(255, description.Length + 1)); + expectedData.WriteAsciiNull(ref pos, description, 255); + } + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestEndVendorBuy() + { + var vendor = new Mobile(0x1); + vendor.DefaultMobileInit(); + + var data = new EndVendorBuy(vendor).Compile(); + + Span expectedData = stackalloc byte[8]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x3B); // Packet ID + expectedData.Write(ref pos, (ushort)0x8); // Length + expectedData.Write(ref pos, vendor.Serial); + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)-); +#endif + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/VendorSellPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/VendorSellPacketTests.cs index f3b9bd2e3..96826e26e 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/VendorSellPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/VendorSellPacketTests.cs @@ -1,81 +1,82 @@ -using System; -using System.Buffers; -using System.Collections.Generic; -using System.Linq; -using Server.Network; -using Xunit; - -namespace Server.Tests.Network.Packets -{ - public class VendorSellPacketTests : IClassFixture - { - [Fact] - public void TestVendorSellList() - { - var vendor = new Mobile(0x1); - vendor.DefaultMobileInit(); - - var item1 = new Item(Serial.LastItem + 1); - var item2 = new Item(Serial.LastItem + 2) { Name = "Second Item" }; - var item3 = new Item(Serial.LastItem + 3); - - var sellStates = new List - { - new SellItemState(item1, 100, "Item 1"), - new SellItemState(item2, 100000, "Item 2"), - new SellItemState(item3, 1, "Item 3") - }; - - Span data = new VendorSellList(vendor, sellStates).Compile(); - - int length = 9 + 14 * 3 + sellStates.Sum(state => - (string.IsNullOrWhiteSpace(state.Item.Name) ? state.Name ?? "" : state.Item.Name.Trim()).Length - ); - - Span expectedData = stackalloc byte[length]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x9E); // Packet ID - expectedData.Write(ref pos, (ushort)length); - expectedData.Write(ref pos, vendor.Serial); - expectedData.Write(ref pos, (ushort)sellStates.Count); - - for (int i = 0; i < sellStates.Count; i++) - { - SellItemState state = sellStates[i]; - expectedData.Write(ref pos, state.Item.Serial); - expectedData.Write(ref pos, (ushort)state.Item.ItemID); - expectedData.Write(ref pos, (ushort)state.Item.Hue); - expectedData.Write(ref pos, (ushort)state.Item.Amount); - expectedData.Write(ref pos, (ushort)state.Price); - string name = string.IsNullOrWhiteSpace(state.Item.Name) ? state.Name ?? "" : state.Item.Name.Trim(); - expectedData.Write(ref pos, (ushort)name.Length); - expectedData.WriteAscii(ref pos, name); - } - - AssertThat.Equal(data, expectedData); - } - - [Fact] - public void TestEndVendorSell() - { - var vendor = new Mobile(0x1); - vendor.DefaultMobileInit(); - - Span data = new EndVendorBuy(vendor).Compile(); - - Span expectedData = stackalloc byte[8]; - int pos = 0; - - expectedData.Write(ref pos, (byte)0x3B); // Packet ID - expectedData.Write(ref pos, (ushort)0x08); // Length - expectedData.Write(ref pos, vendor.Serial); - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (byte)0); -#endif - - AssertThat.Equal(data, expectedData); - } - } -} +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Linq; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class VendorSellPacketTests : IClassFixture + { + [Fact] + public void TestVendorSellList() + { + var vendor = new Mobile(0x1); + vendor.DefaultMobileInit(); + + var item1 = new Item(Serial.LastItem + 1); + var item2 = new Item(Serial.LastItem + 2) { Name = "Second Item" }; + var item3 = new Item(Serial.LastItem + 3); + + var sellStates = new List + { + new SellItemState(item1, 100, "Item 1"), + new SellItemState(item2, 100000, "Item 2"), + new SellItemState(item3, 1, "Item 3") + }; + + var data = new VendorSellList(vendor, sellStates).Compile(); + + var length = 9 + 14 * 3 + sellStates.Sum( + state => + (string.IsNullOrWhiteSpace(state.Item.Name) ? state.Name ?? "" : state.Item.Name.Trim()).Length + ); + + Span expectedData = stackalloc byte[length]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x9E); // Packet ID + expectedData.Write(ref pos, (ushort)length); + expectedData.Write(ref pos, vendor.Serial); + expectedData.Write(ref pos, (ushort)sellStates.Count); + + for (var i = 0; i < sellStates.Count; i++) + { + var state = sellStates[i]; + expectedData.Write(ref pos, state.Item.Serial); + expectedData.Write(ref pos, (ushort)state.Item.ItemID); + expectedData.Write(ref pos, (ushort)state.Item.Hue); + expectedData.Write(ref pos, (ushort)state.Item.Amount); + expectedData.Write(ref pos, (ushort)state.Price); + var name = string.IsNullOrWhiteSpace(state.Item.Name) ? state.Name ?? "" : state.Item.Name.Trim(); + expectedData.Write(ref pos, (ushort)name.Length); + expectedData.WriteAscii(ref pos, name); + } + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestEndVendorSell() + { + var vendor = new Mobile(0x1); + vendor.DefaultMobileInit(); + + var data = new EndVendorBuy(vendor).Compile(); + + Span expectedData = stackalloc byte[8]; + var pos = 0; + + expectedData.Write(ref pos, (byte)0x3B); // Packet ID + expectedData.Write(ref pos, (ushort)0x08); // Length + expectedData.Write(ref pos, vendor.Serial); + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); +#endif + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/PacketTestUtilities.cs b/Projects/Server.Tests/Network/Packets/PacketTestUtilities.cs index 005db4744..88d00b770 100644 --- a/Projects/Server.Tests/Network/Packets/PacketTestUtilities.cs +++ b/Projects/Server.Tests/Network/Packets/PacketTestUtilities.cs @@ -1,13 +1,13 @@ -using System; -using System.Runtime.CompilerServices; -using Server.Network; - -namespace Server.Tests.Network.Packets -{ - public static class PacketTestUtilities - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Span Compile(this Packet p) => - p.Compile(false, out int length).AsSpan(0, length); - } -} +using System; +using System.Runtime.CompilerServices; +using Server.Network; + +namespace Server.Tests.Network.Packets +{ + public static class PacketTestUtilities + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Span Compile(this Packet p) => + p.Compile(false, out var length).AsSpan(0, length); + } +} diff --git a/Projects/Server.Tests/Server.Tests.csproj b/Projects/Server.Tests/Server.Tests.csproj index 7d8574de0..21a2a5b0c 100644 --- a/Projects/Server.Tests/Server.Tests.csproj +++ b/Projects/Server.Tests/Server.Tests.csproj @@ -1,13 +1,13 @@ - - - false - - - - - - - - - - + + + false + + + + + + + + + + diff --git a/Projects/Server.Tests/ServerFixture.cs b/Projects/Server.Tests/ServerFixture.cs index 2c084c854..bf3da700a 100644 --- a/Projects/Server.Tests/ServerFixture.cs +++ b/Projects/Server.Tests/ServerFixture.cs @@ -1,28 +1,26 @@ -using System; -// using Server.Misc; - -namespace Server.Tests -{ - public class ServerFixture : IDisposable - { - - // Global setup - static ServerFixture() - { - Core.Expansion = Expansion.EJ; - - // Load Configurations - ServerConfiguration.Load(true); - - // Configure / Initialize - TestMapDefinitions.ConfigureTestMapDefinitions(); - - // Load the world - World.Load(); - } - - public void Dispose() - { - } - } -} +using System; + +namespace Server.Tests +{ + public class ServerFixture : IDisposable + { + // Global setup + static ServerFixture() + { + Core.Expansion = Expansion.EJ; + + // Load Configurations + ServerConfiguration.Load(true); + + // Configure / Initialize + TestMapDefinitions.ConfigureTestMapDefinitions(); + + // Load the world + World.Load(); + } + + public void Dispose() + { + } + } +} diff --git a/Projects/Server.Tests/TestMapDefinitions.cs b/Projects/Server.Tests/TestMapDefinitions.cs index 98fd6e6f7..a94ae799a 100644 --- a/Projects/Server.Tests/TestMapDefinitions.cs +++ b/Projects/Server.Tests/TestMapDefinitions.cs @@ -1,33 +1,34 @@ -namespace Server -{ - public static class TestMapDefinitions - { - public static void ConfigureTestMapDefinitions() - { - RegisterMap(0, 0, 0, 7168, 4096, 4, "Felucca", MapRules.FeluccaRules); - RegisterMap(1, 1, 1, 7168, 4096, 0, "Trammel", MapRules.TrammelRules); - RegisterMap(2, 2, 2, 2304, 1600, 1, "Ilshenar", MapRules.TrammelRules); - RegisterMap(3, 3, 3, 2560, 2048, 1, "Malas", MapRules.TrammelRules); - RegisterMap(4, 4, 4, 1448, 1448, 1, "Tokuno", MapRules.TrammelRules); - RegisterMap(5, 5, 5, 1280, 4096, 1, "TerMur", MapRules.TrammelRules); - - RegisterMap(0x7F, 0x7F, 0x7F, Map.SectorSize, Map.SectorSize, 1, "Internal", MapRules.Internal); - } - - private static void RegisterMap( - int mapIndex, - int mapID, - int fileIndex, - int width, - int height, - int season, - string name, - MapRules rules) - { - Map newMap = new Map(mapID, mapIndex, fileIndex, width, height, season, name, rules); - - Map.Maps[mapIndex] = newMap; - Map.AllMaps.Add(newMap); - } - } -} +namespace Server +{ + public static class TestMapDefinitions + { + public static void ConfigureTestMapDefinitions() + { + RegisterMap(0, 0, 0, 7168, 4096, 4, "Felucca", MapRules.FeluccaRules); + RegisterMap(1, 1, 1, 7168, 4096, 0, "Trammel", MapRules.TrammelRules); + RegisterMap(2, 2, 2, 2304, 1600, 1, "Ilshenar", MapRules.TrammelRules); + RegisterMap(3, 3, 3, 2560, 2048, 1, "Malas", MapRules.TrammelRules); + RegisterMap(4, 4, 4, 1448, 1448, 1, "Tokuno", MapRules.TrammelRules); + RegisterMap(5, 5, 5, 1280, 4096, 1, "TerMur", MapRules.TrammelRules); + + RegisterMap(0x7F, 0x7F, 0x7F, Map.SectorSize, Map.SectorSize, 1, "Internal", MapRules.Internal); + } + + private static void RegisterMap( + int mapIndex, + int mapID, + int fileIndex, + int width, + int height, + int season, + string name, + MapRules rules + ) + { + var newMap = new Map(mapID, mapIndex, fileIndex, width, height, season, name, rules); + + Map.Maps[mapIndex] = newMap; + Map.AllMaps.Add(newMap); + } + } +} diff --git a/Projects/Server.Tests/Utility/TestStringHelpers.cs b/Projects/Server.Tests/Utility/TestStringHelpers.cs index ea5718aa3..df5c2151d 100644 --- a/Projects/Server.Tests/Utility/TestStringHelpers.cs +++ b/Projects/Server.Tests/Utility/TestStringHelpers.cs @@ -1,18 +1,18 @@ -using Xunit; - -namespace Server.Tests -{ - public class TestStringHelpers - { - [Theory] - [InlineData(null, "default value", "default value")] - [InlineData("", "default value", "default value")] - [InlineData("this is a valid string", "default value", "this is a valid string")] - public void TestIsNullOrDefault(string value, string defaultValue, string expected) - { - string actual = value.IsNullOrDefault(defaultValue); - - Assert.Equal(expected, actual); - } - } -} +using Xunit; + +namespace Server.Tests +{ + public class TestStringHelpers + { + [Theory] + [InlineData(null, "default value", "default value")] + [InlineData("", "default value", "default value")] + [InlineData("this is a valid string", "default value", "this is a valid string")] + public void TestIsNullOrDefault(string value, string defaultValue, string expected) + { + var actual = value.IsNullOrDefault(defaultValue); + + Assert.Equal(expected, actual); + } + } +} diff --git a/Projects/Server.Tests/packages.lock.json b/Projects/Server.Tests/packages.lock.json index dc1e12289..84bec4ce7 100644 --- a/Projects/Server.Tests/packages.lock.json +++ b/Projects/Server.Tests/packages.lock.json @@ -9145,9151 +9145,6 @@ "runtime.any.System.Threading.Timer": "4.3.0" } } - }, - ".NETCoreApp,Version=v5.0": { - "coverlet.collector": { - "type": "Direct", - "requested": "[1.3.0, )", - "resolved": "1.3.0", - "contentHash": "t8pnf5SX2ya0RX4vjoxsbhDMQCZJcpPun2neHKJ4FouMmObylo25FvoOydvf3Bl+l+IzWw7u2vjEeCBHnleB9g==" - }, - "Microsoft.NET.Test.Sdk": { - "type": "Direct", - "requested": "[16.7.0, )", - "resolved": "16.7.0", - "contentHash": "sF0iQqII3WEOdcDwM+bNog2zrRM48MHtKP3T3scfZmlh5IvFIBRfS0kGH9AGOMpTqmpkTYuMkEUkSaz94aWYkA==", - "dependencies": { - "Microsoft.CodeCoverage": "16.7.0", - "Microsoft.TestPlatform.TestHost": "16.7.0" - } - }, - "xunit": { - "type": "Direct", - "requested": "[2.4.1, )", - "resolved": "2.4.1", - "contentHash": "XNR3Yz9QTtec16O0aKcO6+baVNpXmOnPUxDkCY97J+8krUYxPvXT1szYYEUdKk4sB8GOI2YbAjRIOm8ZnXRfzQ==", - "dependencies": { - "xunit.analyzers": "0.10.0", - "xunit.assert": "[2.4.1]", - "xunit.core": "[2.4.1]" - } - }, - "xunit.runner.visualstudio": { - "type": "Direct", - "requested": "[2.4.3, )", - "resolved": "2.4.3", - "contentHash": "kZZSmOmKA8OBlAJaquPXnJJLM9RwQ27H7BMVqfMLUcTi9xHinWGJiWksa3D4NEtz0wZ/nxd2mogObvBgJKCRhQ==" - }, - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.AspNetCore.Connections.Abstractions": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "d9QNKLjOIb+O8fW+Xolhw0ZpOP1nzJi822qthXUhZqzb1PpL/xD4tmZfeE6IRXlRmQOAKDKg38mDEDTaMPGy1w==", - "dependencies": { - "Microsoft.AspNetCore.Http.Features": "3.1.5", - "System.IO.Pipelines": "4.7.1" - } - }, - "Microsoft.AspNetCore.Http.Features": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "I+G1L5363H2oCdMxHv2vtbluRgb4e33Gv6zJd8Uj93bBRFbE4MZlb3cB9PvRAYpSB0xbK216/qRtHmQJBzWIcg==", - "dependencies": { - "Microsoft.Extensions.Primitives": "3.1.5", - "System.IO.Pipelines": "4.7.1" - } - }, - "Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "RmWkwrdmpquJa3Tvui4AhNEy+LeqeDgd85RPNjamwKNjVSUW+Yaz8n1pKPz4IiqDJ+3XfdmaLjP9TSVnXSDNuA==", - "dependencies": { - "Libuv": "1.10.0", - "Microsoft.AspNetCore.Connections.Abstractions": "3.1.5", - "Microsoft.Extensions.Logging.Abstractions": "3.1.5", - "Microsoft.Extensions.Options": "3.1.5" - } - }, - "Microsoft.CodeCoverage": { - "type": "Transitive", - "resolved": "16.7.0", - "contentHash": "przIisHDudyAtmh0hx8GCW8lOlJ7Zi0OX8LVrLlyFvaIPl6shGVhcPFjwAtY8cuSEpjc/Rpu9+BuJcphcXpyrA==" - }, - "Microsoft.CSharp": { - "type": "Transitive", - "resolved": "4.0.1", - "contentHash": "17h8b5mXa87XYKrrVqdgZ38JefSUqLChUQpXgSnpzsM0nDOhE40FTeNWOJ/YmySGV6tG6T8+hjz6vxbknHJr6A==", - "dependencies": { - "System.Collections": "4.0.11", - "System.Diagnostics.Debug": "4.0.11", - "System.Dynamic.Runtime": "4.0.11", - "System.Globalization": "4.0.11", - "System.Linq": "4.1.0", - "System.Linq.Expressions": "4.1.0", - "System.ObjectModel": "4.0.12", - "System.Reflection": "4.1.0", - "System.Reflection.Extensions": "4.0.1", - "System.Reflection.Primitives": "4.0.1", - "System.Reflection.TypeExtensions": "4.1.0", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Runtime.InteropServices": "4.1.0", - "System.Threading": "4.0.11" - } - }, - "Microsoft.Extensions.Configuration.Abstractions": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "VBcAk6s9izZr04WCzNqOh1Sxz2RbVSh0G79MfpHSDv16cUJtSEYEHody9ZnF71LBEktzdu6cvDFBOFMh43q0iA==", - "dependencies": { - "Microsoft.Extensions.Primitives": "3.1.5" - } - }, - "Microsoft.Extensions.DependencyInjection.Abstractions": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "2VSCj2TZPMdeEi279Lawi6qJQu4+sEWizSOYrhY6hapyS1jxn1jVUZT1Ugv68bya+x8+3lD4+RqhUZql9PhISQ==" - }, - "Microsoft.Extensions.FileProviders.Abstractions": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "LrEQ97jhSWw84Y1m+CJfvh9qTUUswt27au54QYn2x5PCMPPgR+yAv/4VTJKMGSSI9T4scSLBXZ/fVhT4fPTCtA==", - "dependencies": { - "Microsoft.Extensions.Primitives": "3.1.5" - } - }, - "Microsoft.Extensions.Hosting.Abstractions": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "e57iK9spITqHE7qNgC3IowzK+PK5NC2rmVY4Sz+ZoDNO24nIsgllIRbanSbt2wQz7Iy/N8Jm3C1sXqKc8zEOMQ==", - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "3.1.5", - "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.5", - "Microsoft.Extensions.FileProviders.Abstractions": "3.1.5", - "Microsoft.Extensions.Logging.Abstractions": "3.1.5" - } - }, - "Microsoft.Extensions.Logging.Abstractions": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "ZvwowjRSWXewdPI+whPFXgwF4Qme6Q9KV9SCPEITSGiqHLArct7q5hTBtTzj3GPsVLjTqehvTg6Bd/EQk9JS0A==" - }, - "Microsoft.Extensions.Options": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "f+JT/7lkKBMp/Ak2tVjO+TD7o+UoCfjnExkZNn0PZIso8kIXrqNy6x42Lrxf4Q0pW3JMf9ExmL2EQlvk2XnFAg==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.5", - "Microsoft.Extensions.Primitives": "3.1.5" - } - }, - "Microsoft.Extensions.Primitives": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "6bLdjSAQix82oP2tsuX9MM2yjgUFFOkSZYyRSKoUULilw2cg0Y0H+dnugwYlfj8Jd7yjd/+QSdNBqEyYhTYv0w==" - }, - "Microsoft.NETCore.Platforms": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" - }, - "Microsoft.NETCore.Targets": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" - }, - "Microsoft.TestPlatform.ObjectModel": { - "type": "Transitive", - "resolved": "16.7.0", - "contentHash": "1/49rMeZXCdlAd0bCBcL6zicQm+lCNOW5N0d7DdNUdtFASCWTQ2u8MauoFT3zwYsZDcC/3q6zLnt723EGeQwZg==", - "dependencies": { - "NuGet.Frameworks": "5.0.0" - } - }, - "Microsoft.TestPlatform.TestHost": { - "type": "Transitive", - "resolved": "16.7.0", - "contentHash": "5yWCRl3oI6Hj9ikgthc/QoyvwUD7CbWnZZjgm8jqZ4HZawAEDNpXLRjYkhWAtZ/sOfbC7lFSV1Pmk87FmNxuSA==", - "dependencies": { - "Microsoft.TestPlatform.ObjectModel": "16.7.0", - "Newtonsoft.Json": "9.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "NETStandard.Library": { - "type": "Transitive", - "resolved": "1.6.1", - "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.AppContext": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Console": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tools": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.Compression": "4.3.0", - "System.IO.Compression.ZipFile": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Linq": "4.3.0", - "System.Linq.Expressions": "4.3.0", - "System.Net.Http": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Net.Sockets": "4.3.0", - "System.ObjectModel": "4.3.0", - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Text.RegularExpressions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.Timer": "4.3.0", - "System.Xml.ReaderWriter": "4.3.0", - "System.Xml.XDocument": "4.3.0" - } - }, - "Newtonsoft.Json": { - "type": "Transitive", - "resolved": "9.0.1", - "contentHash": "U82mHQSKaIk+lpSVCbWYKNavmNH1i5xrExDEquU1i6I5pV6UMOqRnJRSlKO3cMPfcpp0RgDY+8jUXHdQ4IfXvw==", - "dependencies": { - "Microsoft.CSharp": "4.0.1", - "System.Collections": "4.0.11", - "System.Diagnostics.Debug": "4.0.11", - "System.Dynamic.Runtime": "4.0.11", - "System.Globalization": "4.0.11", - "System.IO": "4.1.0", - "System.Linq": "4.1.0", - "System.Linq.Expressions": "4.1.0", - "System.ObjectModel": "4.0.12", - "System.Reflection": "4.1.0", - "System.Reflection.Extensions": "4.0.1", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Runtime.Serialization.Primitives": "4.1.1", - "System.Text.Encoding": "4.0.11", - "System.Text.Encoding.Extensions": "4.0.11", - "System.Text.RegularExpressions": "4.1.0", - "System.Threading": "4.0.11", - "System.Threading.Tasks": "4.0.11", - "System.Xml.ReaderWriter": "4.0.11", - "System.Xml.XDocument": "4.0.11" - } - }, - "NuGet.Frameworks": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "c5JVjuVAm4f7E9Vj+v09Z9s2ZsqFDjBpcsyS3M9xRo0bEdm/LVZSzLxxNvfvAwRiiE8nwe1h2G4OwiwlzFKXlA==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw==" - }, - "runtime.native.System": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "runtime.native.System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "runtime.native.System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", - "dependencies": { - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" - } - }, - "runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NS1U+700m4KFRHR5o4vo9DSlTmlCKu/u7dtE5sUHVIPB+xpXxYQvgBgA6wEIeCz6Yfn0Z52/72WYsToCEPJnrw==", - "dependencies": { - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg==" - }, - "System.AppContext": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Collections.Concurrent": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Diagnostics.DiagnosticSource": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "tD6kosZnTAGdrEa0tZSuFyunMbt/5KYDnHdndJYGqZoNy00XVXyACd5d6KnE1YgYv3ne2CjtAfNXo/fwEhnKUA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Dynamic.Runtime": { - "type": "Transitive", - "resolved": "4.0.11", - "contentHash": "db34f6LHYM0U0JpE+sOmjar27BnqTVkbLJhgfwMpTdgTigG/Hna3m2MYVwnFzGGKnEJk2UXFuoVTr8WUbU91/A==", - "dependencies": { - "System.Collections": "4.0.11", - "System.Diagnostics.Debug": "4.0.11", - "System.Globalization": "4.0.11", - "System.Linq": "4.1.0", - "System.Linq.Expressions": "4.1.0", - "System.ObjectModel": "4.0.12", - "System.Reflection": "4.1.0", - "System.Reflection.Emit": "4.0.1", - "System.Reflection.Emit.ILGeneration": "4.0.1", - "System.Reflection.Primitives": "4.0.1", - "System.Reflection.TypeExtensions": "4.1.0", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Threading": "4.0.11" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.IO.Compression": "4.3.0" - } - }, - "System.IO.Compression.ZipFile": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.IO": "4.3.0", - "System.IO.Compression": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.IO.FileSystem.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "System.IO.Pipelines": { - "type": "Transitive", - "resolved": "4.7.2", - "contentHash": "rGIIhoY3lUdn9rWeuGdgeZZ0P+SpJ1wZI5g8TnXqgvuhFgUP7iP9Nt5FZebYInQZQxqnwjPxdYYBE5l/8PJmqQ==" - }, - "System.Linq": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0" - } - }, - "System.Linq.Expressions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Linq": "4.3.0", - "System.ObjectModel": "4.3.0", - "System.Reflection": "4.3.0", - "System.Reflection.Emit": "4.3.0", - "System.Reflection.Emit.ILGeneration": "4.3.0", - "System.Reflection.Emit.Lightweight": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Reflection.TypeExtensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.DiagnosticSource": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.ObjectModel": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Reflection.Emit": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", - "dependencies": { - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Reflection.Emit.ILGeneration": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Reflection.Emit.ILGeneration": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Reflection.Emit.Lightweight": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Emit.ILGeneration": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Reflection.TypeExtensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Runtime.Numerics": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", - "dependencies": { - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Serialization.Primitives": { - "type": "Transitive", - "resolved": "4.1.1", - "contentHash": "HZ6Du5QrTG8MNJbf4e4qMO3JRAkIboGT5Fk804uZtg3Gq516S7hAqTm2UZKUHa7/6HUGdVy3AqMQKbns06G/cg==", - "dependencies": { - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Text.RegularExpressions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "System.Threading": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Threading.Tasks.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "npvJkVKl5rKXrtl1Kkm6OhOUaYGEiF9wFbppFRWSMoApKzt2PiPHT2Bb8a5sAWxprvdOAtvaARS9QYMznEUtug==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Xml.ReaderWriter": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Text.RegularExpressions": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.Tasks.Extensions": "4.3.0" - } - }, - "System.Xml.XDocument": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tools": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Xml.ReaderWriter": "4.3.0" - } - }, - "xunit.abstractions": { - "type": "Transitive", - "resolved": "2.0.3", - "contentHash": "pot1I4YOxlWjIb5jmwvvQNbTrZ3lJQ+jUGkGjWE3hEFM0l5gOnBWS+H3qsex68s5cO52g+44vpGzhAt+42vwKg==" - }, - "xunit.analyzers": { - "type": "Transitive", - "resolved": "0.10.0", - "contentHash": "4/IDFCJfIeg6bix9apmUtIMwvOsiwqdEexeO/R2D4GReIGPLIRODTpId/l4LRSrAJk9lEO3Zx1H0Zx6uohJDNg==" - }, - "xunit.assert": { - "type": "Transitive", - "resolved": "2.4.1", - "contentHash": "O/Oe0BS5RmSsM+LQOb041TzuPo5MdH2Rov+qXGS37X+KFG1Hxz7kopYklM5+1Y+tRGeXrOx5+Xne1RuqLFQoyQ==", - "dependencies": { - "NETStandard.Library": "1.6.1" - } - }, - "xunit.core": { - "type": "Transitive", - "resolved": "2.4.1", - "contentHash": "Zsj5OMU6JasNGERXZy8s72+pcheG6Q15atS5XpZXqAtULuyQiQ6XNnUsp1gyfC6WgqScqMvySiEHmHcOG6Eg0Q==", - "dependencies": { - "xunit.extensibility.core": "[2.4.1]", - "xunit.extensibility.execution": "[2.4.1]" - } - }, - "xunit.extensibility.core": { - "type": "Transitive", - "resolved": "2.4.1", - "contentHash": "yKZKm/8QNZnBnGZFD9SewkllHBiK0DThybQD/G4PiAmQjKtEZyHi6ET70QPU9KtSMJGRYS6Syk7EyR2EVDU4Kg==", - "dependencies": { - "NETStandard.Library": "1.6.1", - "xunit.abstractions": "2.0.3" - } - }, - "xunit.extensibility.execution": { - "type": "Transitive", - "resolved": "2.4.1", - "contentHash": "7e/1jqBpcb7frLkB6XDrHCGXAbKN4Rtdb88epYxCSRQuZDRW8UtTfdTEVpdTl8s4T56e07hOBVd4G0OdCxIY2A==", - "dependencies": { - "NETStandard.Library": "1.6.1", - "xunit.extensibility.core": "[2.4.1]" - } - }, - "ModernUO": { - "type": "Project", - "dependencies": { - "Microsoft.AspNetCore.Connections.Abstractions": "3.1.5", - "Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv": "3.1.5", - "Microsoft.Extensions.Hosting.Abstractions": "3.1.5", - "System.IO.Pipelines": "4.7.2", - "Zlib.Bindings": "1.2.0" - } - } - }, - ".NETCoreApp,Version=v5.0/centos.7-x64": { - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "S/GPBmfPBB48ZghLxdDR7kDAJVAqgAuThyDJho3OLP5OS4tWD2ydyL8LKm8lhiBxce10OKe9X2zZ6DUjAqEbPg==" - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.any.System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "w4ehZJ+AwXYmGwYu+rMvym6RvMaRiUEQR1u6dwcyuKHxz8Heu/mO9AG1MquEgTyucnhv3M43X0iKpDOoN17C0w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw==" - }, - "runtime.native.System": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.rhel.7-x64.runtime.native.System": "4.3.0" - } - }, - "runtime.native.System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.rhel.7-x64.runtime.native.System.IO.Compression": "4.3.0" - } - }, - "runtime.native.System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.rhel.7-x64.runtime.native.System.Net.Http": "4.3.0" - } - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g==" - }, - "runtime.rhel.7-x64.runtime.native.System": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FgYyVbr9KS9223IxpMTiFnjCN27sehWdnebTngl32eMX6qL6qaCrCjnBeoytG0oAGcNgBlz/CJw75dHVCGv3SQ==" - }, - "runtime.rhel.7-x64.runtime.native.System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I1CSIJ9ZWrkegeTfOYvV/+pBolwy5wLipuPzlc223urJmrtifIWTZObbcupQWI2slIrtXkVUaUYVgZhq+HLQyQ==" - }, - "runtime.rhel.7-x64.runtime.native.System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lf3Zml87TF+bxQnUYnEtRQUc+YyWKFna4xWL2UPeHm/fOo5HtMHNCG96WQCPwte2OXv7WfQeOK5OGam8lqKJBA==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JSEiU9EvE2vJTHUuHnSg9le8XDbvZmjZ/3PhLviICzY1TTDE7c/uNYVtE9qTA9PAOZsqccy5lxvfaZOeBhT3tA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "4NcLbqajFaD3PvhOdmbieeBlKY4d8/kBfgJ5g28n6k1jWEICabvLM62gvmUS/CvyfvcZxVanKPl+E9LhPzfXZw==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.NameResolution": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.unix.System.Console": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tools": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.IO.Compression": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.DiagnosticSource": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.Net.Sockets": "4.3.0" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Extensions": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Security.Claims": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Security.Principal": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I1tkfQlAoMM2URscUtpcRo/hX0jinXx6a/KUtEQoz3owaYwl3qwsO8cbzYVVnjxrzxjHo3nJC+62uolgeGIS9A==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.ThreadPool": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Timer": "4.3.0" - } - } - }, - ".NETCoreApp,Version=v5.0/centos.8-x64": { - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "S/GPBmfPBB48ZghLxdDR7kDAJVAqgAuThyDJho3OLP5OS4tWD2ydyL8LKm8lhiBxce10OKe9X2zZ6DUjAqEbPg==" - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.any.System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "w4ehZJ+AwXYmGwYu+rMvym6RvMaRiUEQR1u6dwcyuKHxz8Heu/mO9AG1MquEgTyucnhv3M43X0iKpDOoN17C0w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw==" - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JSEiU9EvE2vJTHUuHnSg9le8XDbvZmjZ/3PhLviICzY1TTDE7c/uNYVtE9qTA9PAOZsqccy5lxvfaZOeBhT3tA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "4NcLbqajFaD3PvhOdmbieeBlKY4d8/kBfgJ5g28n6k1jWEICabvLM62gvmUS/CvyfvcZxVanKPl+E9LhPzfXZw==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.NameResolution": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.unix.System.Console": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tools": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.IO.Compression": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.DiagnosticSource": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.Net.Sockets": "4.3.0" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Extensions": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Security.Claims": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Security.Principal": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I1tkfQlAoMM2URscUtpcRo/hX0jinXx6a/KUtEQoz3owaYwl3qwsO8cbzYVVnjxrzxjHo3nJC+62uolgeGIS9A==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.ThreadPool": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Timer": "4.3.0" - } - } - }, - ".NETCoreApp,Version=v5.0/debian.10-x64": { - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "S/GPBmfPBB48ZghLxdDR7kDAJVAqgAuThyDJho3OLP5OS4tWD2ydyL8LKm8lhiBxce10OKe9X2zZ6DUjAqEbPg==" - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.any.System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "w4ehZJ+AwXYmGwYu+rMvym6RvMaRiUEQR1u6dwcyuKHxz8Heu/mO9AG1MquEgTyucnhv3M43X0iKpDOoN17C0w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw==" - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JSEiU9EvE2vJTHUuHnSg9le8XDbvZmjZ/3PhLviICzY1TTDE7c/uNYVtE9qTA9PAOZsqccy5lxvfaZOeBhT3tA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "4NcLbqajFaD3PvhOdmbieeBlKY4d8/kBfgJ5g28n6k1jWEICabvLM62gvmUS/CvyfvcZxVanKPl+E9LhPzfXZw==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.NameResolution": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.unix.System.Console": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tools": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.IO.Compression": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.DiagnosticSource": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.Net.Sockets": "4.3.0" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Extensions": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Security.Claims": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Security.Principal": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I1tkfQlAoMM2URscUtpcRo/hX0jinXx6a/KUtEQoz3owaYwl3qwsO8cbzYVVnjxrzxjHo3nJC+62uolgeGIS9A==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.ThreadPool": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Timer": "4.3.0" - } - } - }, - ".NETCoreApp,Version=v5.0/debian.9-x64": { - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "S/GPBmfPBB48ZghLxdDR7kDAJVAqgAuThyDJho3OLP5OS4tWD2ydyL8LKm8lhiBxce10OKe9X2zZ6DUjAqEbPg==" - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.any.System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "w4ehZJ+AwXYmGwYu+rMvym6RvMaRiUEQR1u6dwcyuKHxz8Heu/mO9AG1MquEgTyucnhv3M43X0iKpDOoN17C0w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw==" - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JSEiU9EvE2vJTHUuHnSg9le8XDbvZmjZ/3PhLviICzY1TTDE7c/uNYVtE9qTA9PAOZsqccy5lxvfaZOeBhT3tA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "4NcLbqajFaD3PvhOdmbieeBlKY4d8/kBfgJ5g28n6k1jWEICabvLM62gvmUS/CvyfvcZxVanKPl+E9LhPzfXZw==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.NameResolution": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.unix.System.Console": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tools": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.IO.Compression": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.DiagnosticSource": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.Net.Sockets": "4.3.0" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Extensions": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Security.Claims": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Security.Principal": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I1tkfQlAoMM2URscUtpcRo/hX0jinXx6a/KUtEQoz3owaYwl3qwsO8cbzYVVnjxrzxjHo3nJC+62uolgeGIS9A==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.ThreadPool": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Timer": "4.3.0" - } - } - }, - ".NETCoreApp,Version=v5.0/osx-x64": { - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "S/GPBmfPBB48ZghLxdDR7kDAJVAqgAuThyDJho3OLP5OS4tWD2ydyL8LKm8lhiBxce10OKe9X2zZ6DUjAqEbPg==" - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.any.System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "w4ehZJ+AwXYmGwYu+rMvym6RvMaRiUEQR1u6dwcyuKHxz8Heu/mO9AG1MquEgTyucnhv3M43X0iKpDOoN17C0w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw==" - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JSEiU9EvE2vJTHUuHnSg9le8XDbvZmjZ/3PhLviICzY1TTDE7c/uNYVtE9qTA9PAOZsqccy5lxvfaZOeBhT3tA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "4NcLbqajFaD3PvhOdmbieeBlKY4d8/kBfgJ5g28n6k1jWEICabvLM62gvmUS/CvyfvcZxVanKPl+E9LhPzfXZw==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.NameResolution": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.unix.System.Console": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tools": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.IO.Compression": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.DiagnosticSource": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.Net.Sockets": "4.3.0" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Extensions": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Security.Claims": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Security.Principal": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I1tkfQlAoMM2URscUtpcRo/hX0jinXx6a/KUtEQoz3owaYwl3qwsO8cbzYVVnjxrzxjHo3nJC+62uolgeGIS9A==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.ThreadPool": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Timer": "4.3.0" - } - } - }, - ".NETCoreApp,Version=v5.0/ubuntu.16.04-x64": { - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "S/GPBmfPBB48ZghLxdDR7kDAJVAqgAuThyDJho3OLP5OS4tWD2ydyL8LKm8lhiBxce10OKe9X2zZ6DUjAqEbPg==" - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.any.System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "w4ehZJ+AwXYmGwYu+rMvym6RvMaRiUEQR1u6dwcyuKHxz8Heu/mO9AG1MquEgTyucnhv3M43X0iKpDOoN17C0w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw==" - }, - "runtime.native.System": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.ubuntu.16.04-x64.runtime.native.System": "4.3.0" - } - }, - "runtime.native.System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression": "4.3.0" - } - }, - "runtime.native.System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http": "4.3.0" - } - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "vz5FoBq1abtDHjZdytIbxi5U34p1cqw6fX64R2x/ShSkRmfYUkN0cpD10Aw6Rafv5DZrH3/wpLLlBIxcIWXuRQ==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2WXdHgtDMRBcNhYLLOevPFBo+fhxc6JFwQWpDlCf1KcMIsr+yMjJI7ahIv9vmWhCUYVs1NcB9jo/RFUajCGPMw==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FXboIWG+yLuZVXqgZZmUyqKOuQx/MzPSrPW/OS3pRxLrFd7EQor9F4ZAunmZ3wcout51SMinZIWwOzkAVHnEBg==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JSEiU9EvE2vJTHUuHnSg9le8XDbvZmjZ/3PhLviICzY1TTDE7c/uNYVtE9qTA9PAOZsqccy5lxvfaZOeBhT3tA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "4NcLbqajFaD3PvhOdmbieeBlKY4d8/kBfgJ5g28n6k1jWEICabvLM62gvmUS/CvyfvcZxVanKPl+E9LhPzfXZw==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.NameResolution": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.unix.System.Console": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tools": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.IO.Compression": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.DiagnosticSource": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.Net.Sockets": "4.3.0" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Extensions": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Security.Claims": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Security.Principal": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I1tkfQlAoMM2URscUtpcRo/hX0jinXx6a/KUtEQoz3owaYwl3qwsO8cbzYVVnjxrzxjHo3nJC+62uolgeGIS9A==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.ThreadPool": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Timer": "4.3.0" - } - } - }, - ".NETCoreApp,Version=v5.0/ubuntu.18.04-x64": { - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "S/GPBmfPBB48ZghLxdDR7kDAJVAqgAuThyDJho3OLP5OS4tWD2ydyL8LKm8lhiBxce10OKe9X2zZ6DUjAqEbPg==" - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.any.System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "w4ehZJ+AwXYmGwYu+rMvym6RvMaRiUEQR1u6dwcyuKHxz8Heu/mO9AG1MquEgTyucnhv3M43X0iKpDOoN17C0w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw==" - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JSEiU9EvE2vJTHUuHnSg9le8XDbvZmjZ/3PhLviICzY1TTDE7c/uNYVtE9qTA9PAOZsqccy5lxvfaZOeBhT3tA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "4NcLbqajFaD3PvhOdmbieeBlKY4d8/kBfgJ5g28n6k1jWEICabvLM62gvmUS/CvyfvcZxVanKPl+E9LhPzfXZw==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.NameResolution": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.unix.System.Console": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tools": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.IO.Compression": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.DiagnosticSource": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.Net.Sockets": "4.3.0" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Extensions": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Security.Claims": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Security.Principal": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I1tkfQlAoMM2URscUtpcRo/hX0jinXx6a/KUtEQoz3owaYwl3qwsO8cbzYVVnjxrzxjHo3nJC+62uolgeGIS9A==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.ThreadPool": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Timer": "4.3.0" - } - } - }, - ".NETCoreApp,Version=v5.0/ubuntu.20.04-x64": { - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "S/GPBmfPBB48ZghLxdDR7kDAJVAqgAuThyDJho3OLP5OS4tWD2ydyL8LKm8lhiBxce10OKe9X2zZ6DUjAqEbPg==" - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.any.System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "w4ehZJ+AwXYmGwYu+rMvym6RvMaRiUEQR1u6dwcyuKHxz8Heu/mO9AG1MquEgTyucnhv3M43X0iKpDOoN17C0w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw==" - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JSEiU9EvE2vJTHUuHnSg9le8XDbvZmjZ/3PhLviICzY1TTDE7c/uNYVtE9qTA9PAOZsqccy5lxvfaZOeBhT3tA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "4NcLbqajFaD3PvhOdmbieeBlKY4d8/kBfgJ5g28n6k1jWEICabvLM62gvmUS/CvyfvcZxVanKPl+E9LhPzfXZw==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.NameResolution": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.unix.System.Console": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tools": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.IO.Compression": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.DiagnosticSource": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.Net.Sockets": "4.3.0" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Extensions": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Security.Claims": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Security.Principal": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I1tkfQlAoMM2URscUtpcRo/hX0jinXx6a/KUtEQoz3owaYwl3qwsO8cbzYVVnjxrzxjHo3nJC+62uolgeGIS9A==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.ThreadPool": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Timer": "4.3.0" - } - } - }, - ".NETCoreApp,Version=v5.0/win-x64": { - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.win.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "S/GPBmfPBB48ZghLxdDR7kDAJVAqgAuThyDJho3OLP5OS4tWD2ydyL8LKm8lhiBxce10OKe9X2zZ6DUjAqEbPg==" - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.any.System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "w4ehZJ+AwXYmGwYu+rMvym6RvMaRiUEQR1u6dwcyuKHxz8Heu/mO9AG1MquEgTyucnhv3M43X0iKpDOoN17C0w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw==" - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg==" - }, - "runtime.win.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NU51SEt/ZaD2MF48sJ17BIqx7rjeNNLXUevfMOjqQIetdndXwYjZfZsT6jD+rSWp/FYxjesdK4xUSl4OTEI0jw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "runtime.win.System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "RRACWygml5dnmfgC1SW6tLGsFgwsUAKFtvhdyHnIEz4EhWyrd7pacDdY95CacQJy7BMXRDRCejC9aCRC0Y1sQA==", - "dependencies": { - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "runtime.win.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hHHP0WCStene2jjeYcuDkETozUYF/3sHVRHAEOgS3L15hlip24ssqCTnJC28Z03Wpo078oMcJd0H4egD2aJI8g==" - }, - "runtime.win.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z37zcSCpXuGCYtFbqYO0TwOVXxS2d+BXgSoDFZmRg8BC4Cuy54edjyIvhhcfCrDQA9nl+EPFTgHN54dRAK7mNA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Overlapped": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "runtime.win.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lkXXykakvXUU+Zq2j0pC6EO20lEhijjqMc01XXpp1CJN+DeCwl3nsj4t5Xbpz3kA7yQyTqw6d9SyIzsyLsV3zA==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "runtime.win.System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FK/2gX6MmuLIKNCGsV59Fe4IYrLrI5n9pQ1jh477wiivEM/NCXDT2dRetH5FSfY0bQ+VgTLcS3zcmjQ8my3nxQ==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Net.NameResolution": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Overlapped": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "runtime.win.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "RkgHVhUPvzZxuUubiZe8yr/6CypRVXj0VBzaR8hsqQ8f+rUo7e4PWrHTLOCjd8fBMGWCrY//fi7Ku3qXD7oHRw==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.win.System.Console": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.win.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tools": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.IO.Compression": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.win.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.DiagnosticSource": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.win.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.win.System.Net.Sockets": "4.3.0" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Extensions": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.win.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Security.Claims": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Security.Principal": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I1tkfQlAoMM2URscUtpcRo/hX0jinXx6a/KUtEQoz3owaYwl3qwsO8cbzYVVnjxrzxjHo3nJC+62uolgeGIS9A==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading.Overlapped": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m3HQ2dPiX/DSTpf+yJt8B0c+SRvzfqAJKx+QDWi+VLhz8svLT23MVjEOHPF/KiSLeArKU/iHescrbLd3yVgyNg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Timer": "4.3.0" - } - } } } } \ No newline at end of file diff --git a/Projects/Server/packages.lock.json b/Projects/Server/packages.lock.json index ed0a904ca..f05c3ec35 100644 --- a/Projects/Server/packages.lock.json +++ b/Projects/Server/packages.lock.json @@ -254,260 +254,6 @@ "Microsoft.NETCore.Platforms": "1.0.1" } } - }, - ".NETCoreApp,Version=v5.0": { - "Microsoft.AspNetCore.Connections.Abstractions": { - "type": "Direct", - "requested": "[3.1.5, )", - "resolved": "3.1.5", - "contentHash": "d9QNKLjOIb+O8fW+Xolhw0ZpOP1nzJi822qthXUhZqzb1PpL/xD4tmZfeE6IRXlRmQOAKDKg38mDEDTaMPGy1w==", - "dependencies": { - "Microsoft.AspNetCore.Http.Features": "3.1.5", - "System.IO.Pipelines": "4.7.1" - } - }, - "Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv": { - "type": "Direct", - "requested": "[3.1.5, )", - "resolved": "3.1.5", - "contentHash": "RmWkwrdmpquJa3Tvui4AhNEy+LeqeDgd85RPNjamwKNjVSUW+Yaz8n1pKPz4IiqDJ+3XfdmaLjP9TSVnXSDNuA==", - "dependencies": { - "Libuv": "1.10.0", - "Microsoft.AspNetCore.Connections.Abstractions": "3.1.5", - "Microsoft.Extensions.Logging.Abstractions": "3.1.5", - "Microsoft.Extensions.Options": "3.1.5" - } - }, - "Microsoft.Extensions.Hosting.Abstractions": { - "type": "Direct", - "requested": "[3.1.5, )", - "resolved": "3.1.5", - "contentHash": "e57iK9spITqHE7qNgC3IowzK+PK5NC2rmVY4Sz+ZoDNO24nIsgllIRbanSbt2wQz7Iy/N8Jm3C1sXqKc8zEOMQ==", - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "3.1.5", - "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.5", - "Microsoft.Extensions.FileProviders.Abstractions": "3.1.5", - "Microsoft.Extensions.Logging.Abstractions": "3.1.5" - } - }, - "System.IO.Pipelines": { - "type": "Direct", - "requested": "[4.7.2, )", - "resolved": "4.7.2", - "contentHash": "rGIIhoY3lUdn9rWeuGdgeZZ0P+SpJ1wZI5g8TnXqgvuhFgUP7iP9Nt5FZebYInQZQxqnwjPxdYYBE5l/8PJmqQ==" - }, - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.AspNetCore.Http.Features": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "I+G1L5363H2oCdMxHv2vtbluRgb4e33Gv6zJd8Uj93bBRFbE4MZlb3cB9PvRAYpSB0xbK216/qRtHmQJBzWIcg==", - "dependencies": { - "Microsoft.Extensions.Primitives": "3.1.5", - "System.IO.Pipelines": "4.7.1" - } - }, - "Microsoft.Extensions.Configuration.Abstractions": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "VBcAk6s9izZr04WCzNqOh1Sxz2RbVSh0G79MfpHSDv16cUJtSEYEHody9ZnF71LBEktzdu6cvDFBOFMh43q0iA==", - "dependencies": { - "Microsoft.Extensions.Primitives": "3.1.5" - } - }, - "Microsoft.Extensions.DependencyInjection.Abstractions": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "2VSCj2TZPMdeEi279Lawi6qJQu4+sEWizSOYrhY6hapyS1jxn1jVUZT1Ugv68bya+x8+3lD4+RqhUZql9PhISQ==" - }, - "Microsoft.Extensions.FileProviders.Abstractions": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "LrEQ97jhSWw84Y1m+CJfvh9qTUUswt27au54QYn2x5PCMPPgR+yAv/4VTJKMGSSI9T4scSLBXZ/fVhT4fPTCtA==", - "dependencies": { - "Microsoft.Extensions.Primitives": "3.1.5" - } - }, - "Microsoft.Extensions.Logging.Abstractions": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "ZvwowjRSWXewdPI+whPFXgwF4Qme6Q9KV9SCPEITSGiqHLArct7q5hTBtTzj3GPsVLjTqehvTg6Bd/EQk9JS0A==" - }, - "Microsoft.Extensions.Options": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "f+JT/7lkKBMp/Ak2tVjO+TD7o+UoCfjnExkZNn0PZIso8kIXrqNy6x42Lrxf4Q0pW3JMf9ExmL2EQlvk2XnFAg==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.5", - "Microsoft.Extensions.Primitives": "3.1.5" - } - }, - "Microsoft.Extensions.Primitives": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "6bLdjSAQix82oP2tsuX9MM2yjgUFFOkSZYyRSKoUULilw2cg0Y0H+dnugwYlfj8Jd7yjd/+QSdNBqEyYhTYv0w==" - }, - "Microsoft.NETCore.Platforms": { - "type": "Transitive", - "resolved": "1.0.1", - "contentHash": "2G6OjjJzwBfNOO8myRV/nFrbTw5iA+DEm0N+qUqhrOmaVtn4pC77h38I1jsXGw5VH55+dPfQsqHD0We9sCl9FQ==" - } - }, - ".NETCoreApp,Version=v5.0/centos.7-x64": { - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - } - }, - ".NETCoreApp,Version=v5.0/centos.8-x64": { - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - } - }, - ".NETCoreApp,Version=v5.0/debian.10-x64": { - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - } - }, - ".NETCoreApp,Version=v5.0/debian.9-x64": { - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - } - }, - ".NETCoreApp,Version=v5.0/osx-x64": { - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - } - }, - ".NETCoreApp,Version=v5.0/ubuntu.16.04-x64": { - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - } - }, - ".NETCoreApp,Version=v5.0/ubuntu.18.04-x64": { - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - } - }, - ".NETCoreApp,Version=v5.0/ubuntu.20.04-x64": { - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - } - }, - ".NETCoreApp,Version=v5.0/win-x64": { - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - } } } } \ No newline at end of file diff --git a/Projects/UOContent.Tests/Accounting/Security/PasswordProtectionTest.cs b/Projects/UOContent.Tests/Accounting/Security/PasswordProtectionTest.cs index 3ca0707e7..014777b35 100644 --- a/Projects/UOContent.Tests/Accounting/Security/PasswordProtectionTest.cs +++ b/Projects/UOContent.Tests/Accounting/Security/PasswordProtectionTest.cs @@ -1,46 +1,46 @@ -using System; -using Server.Accounting; -using Server.Accounting.Security; -using Xunit; - -namespace Server.Tests.Accounting.Security -{ - public class PasswordProtectionTest - { - private const string plainPassword = "hello-good-sir"; - - [Theory] - [InlineData(typeof(Argon2PasswordProtection))] - [InlineData(typeof(PBKDF2PasswordProtection))] - [InlineData(typeof(SHA2PasswordProtection))] - [InlineData(typeof(SHA1PasswordProtection))] - [InlineData(typeof(MD5PasswordProtection))] - public void TestValidates(Type protectionType) - { - IPasswordProtection passwordProtection = Activator.CreateInstance(protectionType) as IPasswordProtection; - if (passwordProtection == null) - Assert.False(true, $"{protectionType.Name} is not an IPasswordProtection."); - - string encryptedPassword = passwordProtection.EncryptPassword(plainPassword); - - Assert.True(passwordProtection.ValidatePassword(encryptedPassword, plainPassword)); - } - - [Theory] - [InlineData(typeof(Argon2PasswordProtection))] - [InlineData(typeof(PBKDF2PasswordProtection))] - [InlineData(typeof(SHA2PasswordProtection))] - [InlineData(typeof(SHA1PasswordProtection))] - [InlineData(typeof(MD5PasswordProtection))] - public void TestPasswordDoesNotValidate(Type protectionType) - { - IPasswordProtection passwordProtection = Activator.CreateInstance(protectionType) as IPasswordProtection; - if (passwordProtection == null) - Assert.False(true, $"{protectionType.Name} is not an IPasswordProtection."); - - string encryptedPassword = passwordProtection.EncryptPassword(plainPassword); - - Assert.False(passwordProtection.ValidatePassword(encryptedPassword, "Not the same password")); - } - } -} +using System; +using Server.Accounting; +using Server.Accounting.Security; +using Xunit; + +namespace Server.Tests.Accounting.Security +{ + public class PasswordProtectionTest + { + private const string plainPassword = "hello-good-sir"; + + [Theory] + [InlineData(typeof(Argon2PasswordProtection))] + [InlineData(typeof(PBKDF2PasswordProtection))] + [InlineData(typeof(SHA2PasswordProtection))] + [InlineData(typeof(SHA1PasswordProtection))] + [InlineData(typeof(MD5PasswordProtection))] + public void TestValidates(Type protectionType) + { + var passwordProtection = Activator.CreateInstance(protectionType) as IPasswordProtection; + if (passwordProtection == null) + Assert.False(true, $"{protectionType.Name} is not an IPasswordProtection."); + + var encryptedPassword = passwordProtection.EncryptPassword(plainPassword); + + Assert.True(passwordProtection.ValidatePassword(encryptedPassword, plainPassword)); + } + + [Theory] + [InlineData(typeof(Argon2PasswordProtection))] + [InlineData(typeof(PBKDF2PasswordProtection))] + [InlineData(typeof(SHA2PasswordProtection))] + [InlineData(typeof(SHA1PasswordProtection))] + [InlineData(typeof(MD5PasswordProtection))] + public void TestPasswordDoesNotValidate(Type protectionType) + { + var passwordProtection = Activator.CreateInstance(protectionType) as IPasswordProtection; + if (passwordProtection == null) + Assert.False(true, $"{protectionType.Name} is not an IPasswordProtection."); + + var encryptedPassword = passwordProtection.EncryptPassword(plainPassword); + + Assert.False(passwordProtection.ValidatePassword(encryptedPassword, "Not the same password")); + } + } +} diff --git a/Projects/UOContent.Tests/Misc/HexStringConverterTest.cs b/Projects/UOContent.Tests/Misc/HexStringConverterTest.cs index 9ed3b73b1..c655246e0 100644 --- a/Projects/UOContent.Tests/Misc/HexStringConverterTest.cs +++ b/Projects/UOContent.Tests/Misc/HexStringConverterTest.cs @@ -1,20 +1,20 @@ -using System; -using Xunit; -using Server.Misc; - -namespace Server.Tests.Accounting -{ - public class HexStringConverterTest - { - [Theory] - [InlineData("ABCDEF1234", new byte[]{ 0xAB, 0xCD, 0xEF, 0x12, 0x34 })] - public void ConvertsProperly(string input, byte[] bytes) - { - Span outputBytes = stackalloc byte[input.Length / 2]; - HexStringConverter.GetBytes(input, outputBytes); - - Assert.Equal(bytes, outputBytes.ToArray()); - Assert.Equal(input, HexStringConverter.GetString(bytes)); - } - } -} +using System; +using Server.Misc; +using Xunit; + +namespace Server.Tests.Accounting +{ + public class HexStringConverterTest + { + [Theory] + [InlineData("ABCDEF1234", new byte[] { 0xAB, 0xCD, 0xEF, 0x12, 0x34 })] + public void ConvertsProperly(string input, byte[] bytes) + { + Span outputBytes = stackalloc byte[input.Length / 2]; + HexStringConverter.GetBytes(input, outputBytes); + + Assert.Equal(bytes, outputBytes.ToArray()); + Assert.Equal(input, HexStringConverter.GetString(bytes)); + } + } +} diff --git a/Projects/UOContent.Tests/UOContent.Tests.csproj b/Projects/UOContent.Tests/UOContent.Tests.csproj index 1023b38b7..a7a469b30 100644 --- a/Projects/UOContent.Tests/UOContent.Tests.csproj +++ b/Projects/UOContent.Tests/UOContent.Tests.csproj @@ -1,13 +1,13 @@ - - - false - - - - - - - - - - + + + false + + + + + + + + + + diff --git a/Projects/UOContent.Tests/packages.lock.json b/Projects/UOContent.Tests/packages.lock.json index a4d68f1d7..7efbf3799 100644 --- a/Projects/UOContent.Tests/packages.lock.json +++ b/Projects/UOContent.Tests/packages.lock.json @@ -9577,9583 +9577,6 @@ "resolved": "1.2.0", "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" } - }, - ".NETCoreApp,Version=v5.0": { - "coverlet.collector": { - "type": "Direct", - "requested": "[1.3.0, )", - "resolved": "1.3.0", - "contentHash": "t8pnf5SX2ya0RX4vjoxsbhDMQCZJcpPun2neHKJ4FouMmObylo25FvoOydvf3Bl+l+IzWw7u2vjEeCBHnleB9g==" - }, - "Microsoft.NET.Test.Sdk": { - "type": "Direct", - "requested": "[16.7.0, )", - "resolved": "16.7.0", - "contentHash": "sF0iQqII3WEOdcDwM+bNog2zrRM48MHtKP3T3scfZmlh5IvFIBRfS0kGH9AGOMpTqmpkTYuMkEUkSaz94aWYkA==", - "dependencies": { - "Microsoft.CodeCoverage": "16.7.0", - "Microsoft.TestPlatform.TestHost": "16.7.0" - } - }, - "xunit": { - "type": "Direct", - "requested": "[2.4.1, )", - "resolved": "2.4.1", - "contentHash": "XNR3Yz9QTtec16O0aKcO6+baVNpXmOnPUxDkCY97J+8krUYxPvXT1szYYEUdKk4sB8GOI2YbAjRIOm8ZnXRfzQ==", - "dependencies": { - "xunit.analyzers": "0.10.0", - "xunit.assert": "[2.4.1]", - "xunit.core": "[2.4.1]" - } - }, - "xunit.runner.visualstudio": { - "type": "Direct", - "requested": "[2.4.3, )", - "resolved": "2.4.3", - "contentHash": "kZZSmOmKA8OBlAJaquPXnJJLM9RwQ27H7BMVqfMLUcTi9xHinWGJiWksa3D4NEtz0wZ/nxd2mogObvBgJKCRhQ==" - }, - "Argon2.Bindings": { - "type": "Transitive", - "resolved": "1.6.0", - "contentHash": "fj3n8L2UHJnQOfDy6phuJvu01u80TNEOx0Nkbtj7/G7pDmfRe0InLwHaQMmT59/8TOSDVLEDoi54D/yM8o7qZA==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "MailKit": { - "type": "Transitive", - "resolved": "2.8.0", - "contentHash": "oAbRyAfzymGSxOZRyDAeYwjZubWgj9b9e2CUp2bzMDMQ/2DRdvWkzSXIuVxLpR6QKA5MMixYkowyo1RSV16Atw==", - "dependencies": { - "MimeKit": "2.9.1", - "System.Net.NameResolution": "4.3.0", - "System.Net.Security": "4.3.2", - "System.Runtime.Serialization.Primitives": "4.3.0" - } - }, - "Microsoft.AspNetCore.Connections.Abstractions": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "d9QNKLjOIb+O8fW+Xolhw0ZpOP1nzJi822qthXUhZqzb1PpL/xD4tmZfeE6IRXlRmQOAKDKg38mDEDTaMPGy1w==", - "dependencies": { - "Microsoft.AspNetCore.Http.Features": "3.1.5", - "System.IO.Pipelines": "4.7.1" - } - }, - "Microsoft.AspNetCore.Http.Features": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "I+G1L5363H2oCdMxHv2vtbluRgb4e33Gv6zJd8Uj93bBRFbE4MZlb3cB9PvRAYpSB0xbK216/qRtHmQJBzWIcg==", - "dependencies": { - "Microsoft.Extensions.Primitives": "3.1.5", - "System.IO.Pipelines": "4.7.1" - } - }, - "Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "RmWkwrdmpquJa3Tvui4AhNEy+LeqeDgd85RPNjamwKNjVSUW+Yaz8n1pKPz4IiqDJ+3XfdmaLjP9TSVnXSDNuA==", - "dependencies": { - "Libuv": "1.10.0", - "Microsoft.AspNetCore.Connections.Abstractions": "3.1.5", - "Microsoft.Extensions.Logging.Abstractions": "3.1.5", - "Microsoft.Extensions.Options": "3.1.5" - } - }, - "Microsoft.CodeCoverage": { - "type": "Transitive", - "resolved": "16.7.0", - "contentHash": "przIisHDudyAtmh0hx8GCW8lOlJ7Zi0OX8LVrLlyFvaIPl6shGVhcPFjwAtY8cuSEpjc/Rpu9+BuJcphcXpyrA==" - }, - "Microsoft.CSharp": { - "type": "Transitive", - "resolved": "4.0.1", - "contentHash": "17h8b5mXa87XYKrrVqdgZ38JefSUqLChUQpXgSnpzsM0nDOhE40FTeNWOJ/YmySGV6tG6T8+hjz6vxbknHJr6A==", - "dependencies": { - "System.Collections": "4.0.11", - "System.Diagnostics.Debug": "4.0.11", - "System.Dynamic.Runtime": "4.0.11", - "System.Globalization": "4.0.11", - "System.Linq": "4.1.0", - "System.Linq.Expressions": "4.1.0", - "System.ObjectModel": "4.0.12", - "System.Reflection": "4.1.0", - "System.Reflection.Extensions": "4.0.1", - "System.Reflection.Primitives": "4.0.1", - "System.Reflection.TypeExtensions": "4.1.0", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Runtime.InteropServices": "4.1.0", - "System.Threading": "4.0.11" - } - }, - "Microsoft.Extensions.Configuration.Abstractions": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "VBcAk6s9izZr04WCzNqOh1Sxz2RbVSh0G79MfpHSDv16cUJtSEYEHody9ZnF71LBEktzdu6cvDFBOFMh43q0iA==", - "dependencies": { - "Microsoft.Extensions.Primitives": "3.1.5" - } - }, - "Microsoft.Extensions.DependencyInjection.Abstractions": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "2VSCj2TZPMdeEi279Lawi6qJQu4+sEWizSOYrhY6hapyS1jxn1jVUZT1Ugv68bya+x8+3lD4+RqhUZql9PhISQ==" - }, - "Microsoft.Extensions.FileProviders.Abstractions": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "LrEQ97jhSWw84Y1m+CJfvh9qTUUswt27au54QYn2x5PCMPPgR+yAv/4VTJKMGSSI9T4scSLBXZ/fVhT4fPTCtA==", - "dependencies": { - "Microsoft.Extensions.Primitives": "3.1.5" - } - }, - "Microsoft.Extensions.Hosting.Abstractions": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "e57iK9spITqHE7qNgC3IowzK+PK5NC2rmVY4Sz+ZoDNO24nIsgllIRbanSbt2wQz7Iy/N8Jm3C1sXqKc8zEOMQ==", - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "3.1.5", - "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.5", - "Microsoft.Extensions.FileProviders.Abstractions": "3.1.5", - "Microsoft.Extensions.Logging.Abstractions": "3.1.5" - } - }, - "Microsoft.Extensions.Logging.Abstractions": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "ZvwowjRSWXewdPI+whPFXgwF4Qme6Q9KV9SCPEITSGiqHLArct7q5hTBtTzj3GPsVLjTqehvTg6Bd/EQk9JS0A==" - }, - "Microsoft.Extensions.Options": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "f+JT/7lkKBMp/Ak2tVjO+TD7o+UoCfjnExkZNn0PZIso8kIXrqNy6x42Lrxf4Q0pW3JMf9ExmL2EQlvk2XnFAg==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.5", - "Microsoft.Extensions.Primitives": "3.1.5" - } - }, - "Microsoft.Extensions.Primitives": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "6bLdjSAQix82oP2tsuX9MM2yjgUFFOkSZYyRSKoUULilw2cg0Y0H+dnugwYlfj8Jd7yjd/+QSdNBqEyYhTYv0w==" - }, - "Microsoft.NETCore.Platforms": { - "type": "Transitive", - "resolved": "2.0.0", - "contentHash": "VdLJOCXhZaEMY7Hm2GKiULmn7IEPFE4XC5LPSfBVCUIA8YLZVh846gtfBJalsPQF2PlzdD7ecX7DZEulJ402ZQ==" - }, - "Microsoft.NETCore.Targets": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" - }, - "Microsoft.TestPlatform.ObjectModel": { - "type": "Transitive", - "resolved": "16.7.0", - "contentHash": "1/49rMeZXCdlAd0bCBcL6zicQm+lCNOW5N0d7DdNUdtFASCWTQ2u8MauoFT3zwYsZDcC/3q6zLnt723EGeQwZg==", - "dependencies": { - "NuGet.Frameworks": "5.0.0" - } - }, - "Microsoft.TestPlatform.TestHost": { - "type": "Transitive", - "resolved": "16.7.0", - "contentHash": "5yWCRl3oI6Hj9ikgthc/QoyvwUD7CbWnZZjgm8jqZ4HZawAEDNpXLRjYkhWAtZ/sOfbC7lFSV1Pmk87FmNxuSA==", - "dependencies": { - "Microsoft.TestPlatform.ObjectModel": "16.7.0", - "Newtonsoft.Json": "9.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "MimeKit": { - "type": "Transitive", - "resolved": "2.9.1", - "contentHash": "0XUFf9DEZiLROC7cWvCOqn2uXekNIWztZdpBsaJcvPrndqWpap32jLgQ2kribNj+rhRqK8vpDy9Uvg714v6KBg==", - "dependencies": { - "Portable.BouncyCastle": "1.8.5", - "System.Reflection.TypeExtensions": "4.4.0", - "System.Text.Encoding.CodePages": "4.4.0" - } - }, - "NETStandard.Library": { - "type": "Transitive", - "resolved": "1.6.1", - "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.AppContext": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Console": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tools": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.Compression": "4.3.0", - "System.IO.Compression.ZipFile": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Linq": "4.3.0", - "System.Linq.Expressions": "4.3.0", - "System.Net.Http": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Net.Sockets": "4.3.0", - "System.ObjectModel": "4.3.0", - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Text.RegularExpressions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.Timer": "4.3.0", - "System.Xml.ReaderWriter": "4.3.0", - "System.Xml.XDocument": "4.3.0" - } - }, - "Newtonsoft.Json": { - "type": "Transitive", - "resolved": "9.0.1", - "contentHash": "U82mHQSKaIk+lpSVCbWYKNavmNH1i5xrExDEquU1i6I5pV6UMOqRnJRSlKO3cMPfcpp0RgDY+8jUXHdQ4IfXvw==", - "dependencies": { - "Microsoft.CSharp": "4.0.1", - "System.Collections": "4.0.11", - "System.Diagnostics.Debug": "4.0.11", - "System.Dynamic.Runtime": "4.0.11", - "System.Globalization": "4.0.11", - "System.IO": "4.1.0", - "System.Linq": "4.1.0", - "System.Linq.Expressions": "4.1.0", - "System.ObjectModel": "4.0.12", - "System.Reflection": "4.1.0", - "System.Reflection.Extensions": "4.0.1", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Runtime.Serialization.Primitives": "4.1.1", - "System.Text.Encoding": "4.0.11", - "System.Text.Encoding.Extensions": "4.0.11", - "System.Text.RegularExpressions": "4.1.0", - "System.Threading": "4.0.11", - "System.Threading.Tasks": "4.0.11", - "System.Xml.ReaderWriter": "4.0.11", - "System.Xml.XDocument": "4.0.11" - } - }, - "NuGet.Frameworks": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "c5JVjuVAm4f7E9Vj+v09Z9s2ZsqFDjBpcsyS3M9xRo0bEdm/LVZSzLxxNvfvAwRiiE8nwe1h2G4OwiwlzFKXlA==" - }, - "Portable.BouncyCastle": { - "type": "Transitive", - "resolved": "1.8.5", - "contentHash": "EaCgmntbH1sOzemRTqyXSqYjB6pLH7VCYHhhDYZ59guHSD5qPwhIYa7kfy0QUlmTRt9IXhaXdFhNuBUArp70Ng==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" - }, - "runtime.native.System": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "runtime.native.System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "runtime.native.System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "runtime.native.System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M2nN92ePS8BgQ2oi6Jj3PlTUzadYSIWLdZrHY1n1ZcW9o4wAQQ6W+aQ2lfq1ysZQfVCgDwY58alUdowrzezztg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", - "dependencies": { - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" - } - }, - "runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "QR1OwtwehHxSeQvZKXe+iSd+d3XZNkEcuWMFYa2i0aG1l+lR739HPicKMlTbJst3spmeekDVBUS7SeS26s4U/g==", - "dependencies": { - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" - } - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" - }, - "System.AppContext": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Collections.Concurrent": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Diagnostics.DiagnosticSource": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "tD6kosZnTAGdrEa0tZSuFyunMbt/5KYDnHdndJYGqZoNy00XVXyACd5d6KnE1YgYv3ne2CjtAfNXo/fwEhnKUA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Dynamic.Runtime": { - "type": "Transitive", - "resolved": "4.0.11", - "contentHash": "db34f6LHYM0U0JpE+sOmjar27BnqTVkbLJhgfwMpTdgTigG/Hna3m2MYVwnFzGGKnEJk2UXFuoVTr8WUbU91/A==", - "dependencies": { - "System.Collections": "4.0.11", - "System.Diagnostics.Debug": "4.0.11", - "System.Globalization": "4.0.11", - "System.Linq": "4.1.0", - "System.Linq.Expressions": "4.1.0", - "System.ObjectModel": "4.0.12", - "System.Reflection": "4.1.0", - "System.Reflection.Emit": "4.0.1", - "System.Reflection.Emit.ILGeneration": "4.0.1", - "System.Reflection.Primitives": "4.0.1", - "System.Reflection.TypeExtensions": "4.1.0", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Threading": "4.0.11" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.IO.Compression": "4.3.0" - } - }, - "System.IO.Compression.ZipFile": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.IO": "4.3.0", - "System.IO.Compression": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.IO.FileSystem.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "System.IO.Pipelines": { - "type": "Transitive", - "resolved": "4.7.2", - "contentHash": "rGIIhoY3lUdn9rWeuGdgeZZ0P+SpJ1wZI5g8TnXqgvuhFgUP7iP9Nt5FZebYInQZQxqnwjPxdYYBE5l/8PJmqQ==" - }, - "System.Linq": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0" - } - }, - "System.Linq.Expressions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Linq": "4.3.0", - "System.ObjectModel": "4.3.0", - "System.Reflection": "4.3.0", - "System.Reflection.Emit": "4.3.0", - "System.Reflection.Emit.ILGeneration": "4.3.0", - "System.Reflection.Emit.Lightweight": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Reflection.TypeExtensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.DiagnosticSource": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Security": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.ObjectModel": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Reflection.Emit": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", - "dependencies": { - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Reflection.Emit.ILGeneration": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Reflection.Emit.ILGeneration": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Reflection.Emit.Lightweight": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Emit.ILGeneration": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Reflection.TypeExtensions": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "dkmh/ySlwnXJp/1qYP9uyKkCK1CXR/REFzl7abHcArxBcV91mY2CgrrzSRA5Z/X4MevJWwXsklGRdR3A7K9zbg==" - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Runtime.Numerics": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", - "dependencies": { - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Serialization.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Wz+0KOukJGAlXjtKr+5Xpuxf8+c8739RI1C+A2BoQZT+wMCCoMDDdO8/4IRHfaVINqL78GO8dW8G2lW/e45Mcw==", - "dependencies": { - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Security.Claims": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Security.Principal": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I1tkfQlAoMM2URscUtpcRo/hX0jinXx6a/KUtEQoz3owaYwl3qwsO8cbzYVVnjxrzxjHo3nJC+62uolgeGIS9A==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "6JX7ZdaceBiLKLkYt8zJcp4xTJd1uYyXXEkPw6mnlUIjh1gZPIVKPtRXPmY5kLf6DwZmf5YLwR3QUrRonl7l0A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "2.0.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Text.RegularExpressions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "System.Threading": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Threading.Tasks.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "npvJkVKl5rKXrtl1Kkm6OhOUaYGEiF9wFbppFRWSMoApKzt2PiPHT2Bb8a5sAWxprvdOAtvaARS9QYMznEUtug==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.ThreadPool": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Xml.ReaderWriter": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Text.RegularExpressions": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.Tasks.Extensions": "4.3.0" - } - }, - "System.Xml.XDocument": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tools": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Xml.ReaderWriter": "4.3.0" - } - }, - "xunit.abstractions": { - "type": "Transitive", - "resolved": "2.0.3", - "contentHash": "pot1I4YOxlWjIb5jmwvvQNbTrZ3lJQ+jUGkGjWE3hEFM0l5gOnBWS+H3qsex68s5cO52g+44vpGzhAt+42vwKg==" - }, - "xunit.analyzers": { - "type": "Transitive", - "resolved": "0.10.0", - "contentHash": "4/IDFCJfIeg6bix9apmUtIMwvOsiwqdEexeO/R2D4GReIGPLIRODTpId/l4LRSrAJk9lEO3Zx1H0Zx6uohJDNg==" - }, - "xunit.assert": { - "type": "Transitive", - "resolved": "2.4.1", - "contentHash": "O/Oe0BS5RmSsM+LQOb041TzuPo5MdH2Rov+qXGS37X+KFG1Hxz7kopYklM5+1Y+tRGeXrOx5+Xne1RuqLFQoyQ==", - "dependencies": { - "NETStandard.Library": "1.6.1" - } - }, - "xunit.core": { - "type": "Transitive", - "resolved": "2.4.1", - "contentHash": "Zsj5OMU6JasNGERXZy8s72+pcheG6Q15atS5XpZXqAtULuyQiQ6XNnUsp1gyfC6WgqScqMvySiEHmHcOG6Eg0Q==", - "dependencies": { - "xunit.extensibility.core": "[2.4.1]", - "xunit.extensibility.execution": "[2.4.1]" - } - }, - "xunit.extensibility.core": { - "type": "Transitive", - "resolved": "2.4.1", - "contentHash": "yKZKm/8QNZnBnGZFD9SewkllHBiK0DThybQD/G4PiAmQjKtEZyHi6ET70QPU9KtSMJGRYS6Syk7EyR2EVDU4Kg==", - "dependencies": { - "NETStandard.Library": "1.6.1", - "xunit.abstractions": "2.0.3" - } - }, - "xunit.extensibility.execution": { - "type": "Transitive", - "resolved": "2.4.1", - "contentHash": "7e/1jqBpcb7frLkB6XDrHCGXAbKN4Rtdb88epYxCSRQuZDRW8UtTfdTEVpdTl8s4T56e07hOBVd4G0OdCxIY2A==", - "dependencies": { - "NETStandard.Library": "1.6.1", - "xunit.extensibility.core": "[2.4.1]" - } - }, - "Zlib.Bindings": { - "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "ModernUO": { - "type": "Project", - "dependencies": { - "Microsoft.AspNetCore.Connections.Abstractions": "3.1.5", - "Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv": "3.1.5", - "Microsoft.Extensions.Hosting.Abstractions": "3.1.5", - "System.IO.Pipelines": "4.7.2", - "Zlib.Bindings": "1.2.0" - } - }, - "uocontent": { - "type": "Project", - "dependencies": { - "Argon2.Bindings": "1.6.0", - "MailKit": "2.8.0", - "Microsoft.AspNetCore.Connections.Abstractions": "3.1.5", - "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.5", - "Microsoft.Extensions.Hosting.Abstractions": "3.1.5", - "Microsoft.Extensions.Logging.Abstractions": "3.1.5", - "Zlib.Bindings": "1.2.0" - } - } - }, - ".NETCoreApp,Version=v5.0/centos.7-x64": { - "Argon2.Bindings": { - "type": "Transitive", - "resolved": "1.6.0", - "contentHash": "fj3n8L2UHJnQOfDy6phuJvu01u80TNEOx0Nkbtj7/G7pDmfRe0InLwHaQMmT59/8TOSDVLEDoi54D/yM8o7qZA==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "S/GPBmfPBB48ZghLxdDR7kDAJVAqgAuThyDJho3OLP5OS4tWD2ydyL8LKm8lhiBxce10OKe9X2zZ6DUjAqEbPg==" - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.any.System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "w4ehZJ+AwXYmGwYu+rMvym6RvMaRiUEQR1u6dwcyuKHxz8Heu/mO9AG1MquEgTyucnhv3M43X0iKpDOoN17C0w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" - }, - "runtime.native.System": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.rhel.7-x64.runtime.native.System": "4.3.0" - } - }, - "runtime.native.System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.rhel.7-x64.runtime.native.System.IO.Compression": "4.3.0" - } - }, - "runtime.native.System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.rhel.7-x64.runtime.native.System.Net.Http": "4.3.0" - } - }, - "runtime.native.System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M2nN92ePS8BgQ2oi6Jj3PlTUzadYSIWLdZrHY1n1ZcW9o4wAQQ6W+aQ2lfq1ysZQfVCgDwY58alUdowrzezztg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.rhel.7-x64.runtime.native.System.Net.Security": "4.3.0" - } - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" - }, - "runtime.rhel.7-x64.runtime.native.System": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FgYyVbr9KS9223IxpMTiFnjCN27sehWdnebTngl32eMX6qL6qaCrCjnBeoytG0oAGcNgBlz/CJw75dHVCGv3SQ==" - }, - "runtime.rhel.7-x64.runtime.native.System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I1CSIJ9ZWrkegeTfOYvV/+pBolwy5wLipuPzlc223urJmrtifIWTZObbcupQWI2slIrtXkVUaUYVgZhq+HLQyQ==" - }, - "runtime.rhel.7-x64.runtime.native.System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lf3Zml87TF+bxQnUYnEtRQUc+YyWKFna4xWL2UPeHm/fOo5HtMHNCG96WQCPwte2OXv7WfQeOK5OGam8lqKJBA==" - }, - "runtime.rhel.7-x64.runtime.native.System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qyNeven0cnu+iqfuCSGPCPJeoM2dcQ6lPUtJVPHXoyRKindqTpzdLzAr5OkkmX1P5vOWtf4OOPikSwo6GoJkLg==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JSEiU9EvE2vJTHUuHnSg9le8XDbvZmjZ/3PhLviICzY1TTDE7c/uNYVtE9qTA9PAOZsqccy5lxvfaZOeBhT3tA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "4NcLbqajFaD3PvhOdmbieeBlKY4d8/kBfgJ5g28n6k1jWEICabvLM62gvmUS/CvyfvcZxVanKPl+E9LhPzfXZw==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.NameResolution": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.unix.System.Console": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tools": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.IO.Compression": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.DiagnosticSource": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Security": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.Net.Sockets": "4.3.0" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Extensions": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "6JX7ZdaceBiLKLkYt8zJcp4xTJd1uYyXXEkPw6mnlUIjh1gZPIVKPtRXPmY5kLf6DwZmf5YLwR3QUrRonl7l0A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "2.0.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.ThreadPool": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Timer": "4.3.0" - } - }, - "Zlib.Bindings": { - "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - } - }, - ".NETCoreApp,Version=v5.0/centos.8-x64": { - "Argon2.Bindings": { - "type": "Transitive", - "resolved": "1.6.0", - "contentHash": "fj3n8L2UHJnQOfDy6phuJvu01u80TNEOx0Nkbtj7/G7pDmfRe0InLwHaQMmT59/8TOSDVLEDoi54D/yM8o7qZA==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "S/GPBmfPBB48ZghLxdDR7kDAJVAqgAuThyDJho3OLP5OS4tWD2ydyL8LKm8lhiBxce10OKe9X2zZ6DUjAqEbPg==" - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.any.System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "w4ehZJ+AwXYmGwYu+rMvym6RvMaRiUEQR1u6dwcyuKHxz8Heu/mO9AG1MquEgTyucnhv3M43X0iKpDOoN17C0w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JSEiU9EvE2vJTHUuHnSg9le8XDbvZmjZ/3PhLviICzY1TTDE7c/uNYVtE9qTA9PAOZsqccy5lxvfaZOeBhT3tA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "4NcLbqajFaD3PvhOdmbieeBlKY4d8/kBfgJ5g28n6k1jWEICabvLM62gvmUS/CvyfvcZxVanKPl+E9LhPzfXZw==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.NameResolution": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.unix.System.Console": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tools": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.IO.Compression": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.DiagnosticSource": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Security": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.Net.Sockets": "4.3.0" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Extensions": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "6JX7ZdaceBiLKLkYt8zJcp4xTJd1uYyXXEkPw6mnlUIjh1gZPIVKPtRXPmY5kLf6DwZmf5YLwR3QUrRonl7l0A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "2.0.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.ThreadPool": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Timer": "4.3.0" - } - }, - "Zlib.Bindings": { - "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - } - }, - ".NETCoreApp,Version=v5.0/debian.10-x64": { - "Argon2.Bindings": { - "type": "Transitive", - "resolved": "1.6.0", - "contentHash": "fj3n8L2UHJnQOfDy6phuJvu01u80TNEOx0Nkbtj7/G7pDmfRe0InLwHaQMmT59/8TOSDVLEDoi54D/yM8o7qZA==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "S/GPBmfPBB48ZghLxdDR7kDAJVAqgAuThyDJho3OLP5OS4tWD2ydyL8LKm8lhiBxce10OKe9X2zZ6DUjAqEbPg==" - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.any.System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "w4ehZJ+AwXYmGwYu+rMvym6RvMaRiUEQR1u6dwcyuKHxz8Heu/mO9AG1MquEgTyucnhv3M43X0iKpDOoN17C0w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JSEiU9EvE2vJTHUuHnSg9le8XDbvZmjZ/3PhLviICzY1TTDE7c/uNYVtE9qTA9PAOZsqccy5lxvfaZOeBhT3tA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "4NcLbqajFaD3PvhOdmbieeBlKY4d8/kBfgJ5g28n6k1jWEICabvLM62gvmUS/CvyfvcZxVanKPl+E9LhPzfXZw==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.NameResolution": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.unix.System.Console": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tools": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.IO.Compression": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.DiagnosticSource": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Security": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.Net.Sockets": "4.3.0" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Extensions": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "6JX7ZdaceBiLKLkYt8zJcp4xTJd1uYyXXEkPw6mnlUIjh1gZPIVKPtRXPmY5kLf6DwZmf5YLwR3QUrRonl7l0A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "2.0.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.ThreadPool": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Timer": "4.3.0" - } - }, - "Zlib.Bindings": { - "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - } - }, - ".NETCoreApp,Version=v5.0/debian.9-x64": { - "Argon2.Bindings": { - "type": "Transitive", - "resolved": "1.6.0", - "contentHash": "fj3n8L2UHJnQOfDy6phuJvu01u80TNEOx0Nkbtj7/G7pDmfRe0InLwHaQMmT59/8TOSDVLEDoi54D/yM8o7qZA==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "S/GPBmfPBB48ZghLxdDR7kDAJVAqgAuThyDJho3OLP5OS4tWD2ydyL8LKm8lhiBxce10OKe9X2zZ6DUjAqEbPg==" - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.any.System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "w4ehZJ+AwXYmGwYu+rMvym6RvMaRiUEQR1u6dwcyuKHxz8Heu/mO9AG1MquEgTyucnhv3M43X0iKpDOoN17C0w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JSEiU9EvE2vJTHUuHnSg9le8XDbvZmjZ/3PhLviICzY1TTDE7c/uNYVtE9qTA9PAOZsqccy5lxvfaZOeBhT3tA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "4NcLbqajFaD3PvhOdmbieeBlKY4d8/kBfgJ5g28n6k1jWEICabvLM62gvmUS/CvyfvcZxVanKPl+E9LhPzfXZw==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.NameResolution": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.unix.System.Console": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tools": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.IO.Compression": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.DiagnosticSource": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Security": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.Net.Sockets": "4.3.0" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Extensions": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "6JX7ZdaceBiLKLkYt8zJcp4xTJd1uYyXXEkPw6mnlUIjh1gZPIVKPtRXPmY5kLf6DwZmf5YLwR3QUrRonl7l0A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "2.0.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.ThreadPool": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Timer": "4.3.0" - } - }, - "Zlib.Bindings": { - "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - } - }, - ".NETCoreApp,Version=v5.0/osx-x64": { - "Argon2.Bindings": { - "type": "Transitive", - "resolved": "1.6.0", - "contentHash": "fj3n8L2UHJnQOfDy6phuJvu01u80TNEOx0Nkbtj7/G7pDmfRe0InLwHaQMmT59/8TOSDVLEDoi54D/yM8o7qZA==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "S/GPBmfPBB48ZghLxdDR7kDAJVAqgAuThyDJho3OLP5OS4tWD2ydyL8LKm8lhiBxce10OKe9X2zZ6DUjAqEbPg==" - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.any.System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "w4ehZJ+AwXYmGwYu+rMvym6RvMaRiUEQR1u6dwcyuKHxz8Heu/mO9AG1MquEgTyucnhv3M43X0iKpDOoN17C0w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JSEiU9EvE2vJTHUuHnSg9le8XDbvZmjZ/3PhLviICzY1TTDE7c/uNYVtE9qTA9PAOZsqccy5lxvfaZOeBhT3tA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "4NcLbqajFaD3PvhOdmbieeBlKY4d8/kBfgJ5g28n6k1jWEICabvLM62gvmUS/CvyfvcZxVanKPl+E9LhPzfXZw==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.NameResolution": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.unix.System.Console": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tools": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.IO.Compression": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.DiagnosticSource": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Security": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.Net.Sockets": "4.3.0" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Extensions": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "6JX7ZdaceBiLKLkYt8zJcp4xTJd1uYyXXEkPw6mnlUIjh1gZPIVKPtRXPmY5kLf6DwZmf5YLwR3QUrRonl7l0A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "2.0.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.ThreadPool": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Timer": "4.3.0" - } - }, - "Zlib.Bindings": { - "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - } - }, - ".NETCoreApp,Version=v5.0/ubuntu.16.04-x64": { - "Argon2.Bindings": { - "type": "Transitive", - "resolved": "1.6.0", - "contentHash": "fj3n8L2UHJnQOfDy6phuJvu01u80TNEOx0Nkbtj7/G7pDmfRe0InLwHaQMmT59/8TOSDVLEDoi54D/yM8o7qZA==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "S/GPBmfPBB48ZghLxdDR7kDAJVAqgAuThyDJho3OLP5OS4tWD2ydyL8LKm8lhiBxce10OKe9X2zZ6DUjAqEbPg==" - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.any.System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "w4ehZJ+AwXYmGwYu+rMvym6RvMaRiUEQR1u6dwcyuKHxz8Heu/mO9AG1MquEgTyucnhv3M43X0iKpDOoN17C0w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" - }, - "runtime.native.System": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.ubuntu.16.04-x64.runtime.native.System": "4.3.0" - } - }, - "runtime.native.System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression": "4.3.0" - } - }, - "runtime.native.System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http": "4.3.0" - } - }, - "runtime.native.System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M2nN92ePS8BgQ2oi6Jj3PlTUzadYSIWLdZrHY1n1ZcW9o4wAQQ6W+aQ2lfq1ysZQfVCgDwY58alUdowrzezztg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security": "4.3.0" - } - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "vz5FoBq1abtDHjZdytIbxi5U34p1cqw6fX64R2x/ShSkRmfYUkN0cpD10Aw6Rafv5DZrH3/wpLLlBIxcIWXuRQ==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2WXdHgtDMRBcNhYLLOevPFBo+fhxc6JFwQWpDlCf1KcMIsr+yMjJI7ahIv9vmWhCUYVs1NcB9jo/RFUajCGPMw==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FXboIWG+yLuZVXqgZZmUyqKOuQx/MzPSrPW/OS3pRxLrFd7EQor9F4ZAunmZ3wcout51SMinZIWwOzkAVHnEBg==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "amUh4OUzit/SN6bWlc0ksEXhxAfWssejPDzYRHDS6Xzk4dQ2zFsHxR8n8KpGqOv0IZazaroXL0HgY7ime3gv8w==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JSEiU9EvE2vJTHUuHnSg9le8XDbvZmjZ/3PhLviICzY1TTDE7c/uNYVtE9qTA9PAOZsqccy5lxvfaZOeBhT3tA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "4NcLbqajFaD3PvhOdmbieeBlKY4d8/kBfgJ5g28n6k1jWEICabvLM62gvmUS/CvyfvcZxVanKPl+E9LhPzfXZw==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.NameResolution": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.unix.System.Console": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tools": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.IO.Compression": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.DiagnosticSource": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Security": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.Net.Sockets": "4.3.0" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Extensions": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "6JX7ZdaceBiLKLkYt8zJcp4xTJd1uYyXXEkPw6mnlUIjh1gZPIVKPtRXPmY5kLf6DwZmf5YLwR3QUrRonl7l0A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "2.0.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.ThreadPool": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Timer": "4.3.0" - } - }, - "Zlib.Bindings": { - "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - } - }, - ".NETCoreApp,Version=v5.0/ubuntu.18.04-x64": { - "Argon2.Bindings": { - "type": "Transitive", - "resolved": "1.6.0", - "contentHash": "fj3n8L2UHJnQOfDy6phuJvu01u80TNEOx0Nkbtj7/G7pDmfRe0InLwHaQMmT59/8TOSDVLEDoi54D/yM8o7qZA==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "S/GPBmfPBB48ZghLxdDR7kDAJVAqgAuThyDJho3OLP5OS4tWD2ydyL8LKm8lhiBxce10OKe9X2zZ6DUjAqEbPg==" - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.any.System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "w4ehZJ+AwXYmGwYu+rMvym6RvMaRiUEQR1u6dwcyuKHxz8Heu/mO9AG1MquEgTyucnhv3M43X0iKpDOoN17C0w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JSEiU9EvE2vJTHUuHnSg9le8XDbvZmjZ/3PhLviICzY1TTDE7c/uNYVtE9qTA9PAOZsqccy5lxvfaZOeBhT3tA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "4NcLbqajFaD3PvhOdmbieeBlKY4d8/kBfgJ5g28n6k1jWEICabvLM62gvmUS/CvyfvcZxVanKPl+E9LhPzfXZw==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.NameResolution": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.unix.System.Console": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tools": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.IO.Compression": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.DiagnosticSource": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Security": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.Net.Sockets": "4.3.0" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Extensions": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "6JX7ZdaceBiLKLkYt8zJcp4xTJd1uYyXXEkPw6mnlUIjh1gZPIVKPtRXPmY5kLf6DwZmf5YLwR3QUrRonl7l0A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "2.0.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.ThreadPool": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Timer": "4.3.0" - } - }, - "Zlib.Bindings": { - "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - } - }, - ".NETCoreApp,Version=v5.0/ubuntu.20.04-x64": { - "Argon2.Bindings": { - "type": "Transitive", - "resolved": "1.6.0", - "contentHash": "fj3n8L2UHJnQOfDy6phuJvu01u80TNEOx0Nkbtj7/G7pDmfRe0InLwHaQMmT59/8TOSDVLEDoi54D/yM8o7qZA==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "S/GPBmfPBB48ZghLxdDR7kDAJVAqgAuThyDJho3OLP5OS4tWD2ydyL8LKm8lhiBxce10OKe9X2zZ6DUjAqEbPg==" - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.any.System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "w4ehZJ+AwXYmGwYu+rMvym6RvMaRiUEQR1u6dwcyuKHxz8Heu/mO9AG1MquEgTyucnhv3M43X0iKpDOoN17C0w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JSEiU9EvE2vJTHUuHnSg9le8XDbvZmjZ/3PhLviICzY1TTDE7c/uNYVtE9qTA9PAOZsqccy5lxvfaZOeBhT3tA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "4NcLbqajFaD3PvhOdmbieeBlKY4d8/kBfgJ5g28n6k1jWEICabvLM62gvmUS/CvyfvcZxVanKPl+E9LhPzfXZw==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.NameResolution": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.unix.System.Console": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tools": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.IO.Compression": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.DiagnosticSource": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Security": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.Net.Sockets": "4.3.0" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Extensions": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "6JX7ZdaceBiLKLkYt8zJcp4xTJd1uYyXXEkPw6mnlUIjh1gZPIVKPtRXPmY5kLf6DwZmf5YLwR3QUrRonl7l0A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "2.0.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.ThreadPool": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Timer": "4.3.0" - } - }, - "Zlib.Bindings": { - "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - } - }, - ".NETCoreApp,Version=v5.0/win-x64": { - "Argon2.Bindings": { - "type": "Transitive", - "resolved": "1.6.0", - "contentHash": "fj3n8L2UHJnQOfDy6phuJvu01u80TNEOx0Nkbtj7/G7pDmfRe0InLwHaQMmT59/8TOSDVLEDoi54D/yM8o7qZA==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.win.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "S/GPBmfPBB48ZghLxdDR7kDAJVAqgAuThyDJho3OLP5OS4tWD2ydyL8LKm8lhiBxce10OKe9X2zZ6DUjAqEbPg==" - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cPhT+Vqu52+cQQrDai/V91gubXUnDKNRvlBnH+hOgtGyHdC17aQIU64EaehwAQymd7kJA5rSrVRNfDYrbhnzyA==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.any.System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "w4ehZJ+AwXYmGwYu+rMvym6RvMaRiUEQR1u6dwcyuKHxz8Heu/mO9AG1MquEgTyucnhv3M43X0iKpDOoN17C0w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" - }, - "runtime.win.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NU51SEt/ZaD2MF48sJ17BIqx7rjeNNLXUevfMOjqQIetdndXwYjZfZsT6jD+rSWp/FYxjesdK4xUSl4OTEI0jw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "runtime.win.System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "RRACWygml5dnmfgC1SW6tLGsFgwsUAKFtvhdyHnIEz4EhWyrd7pacDdY95CacQJy7BMXRDRCejC9aCRC0Y1sQA==", - "dependencies": { - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "runtime.win.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hHHP0WCStene2jjeYcuDkETozUYF/3sHVRHAEOgS3L15hlip24ssqCTnJC28Z03Wpo078oMcJd0H4egD2aJI8g==" - }, - "runtime.win.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z37zcSCpXuGCYtFbqYO0TwOVXxS2d+BXgSoDFZmRg8BC4Cuy54edjyIvhhcfCrDQA9nl+EPFTgHN54dRAK7mNA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Overlapped": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "runtime.win.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lkXXykakvXUU+Zq2j0pC6EO20lEhijjqMc01XXpp1CJN+DeCwl3nsj4t5Xbpz3kA7yQyTqw6d9SyIzsyLsV3zA==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "runtime.win.System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FK/2gX6MmuLIKNCGsV59Fe4IYrLrI5n9pQ1jh477wiivEM/NCXDT2dRetH5FSfY0bQ+VgTLcS3zcmjQ8my3nxQ==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Net.NameResolution": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Overlapped": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "runtime.win.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "RkgHVhUPvzZxuUubiZe8yr/6CypRVXj0VBzaR8hsqQ8f+rUo7e4PWrHTLOCjd8fBMGWCrY//fi7Ku3qXD7oHRw==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Console": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.win.System.Console": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.win.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tools": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tools": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.Compression": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.IO.Compression": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.win.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.DiagnosticSource": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.win.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Security": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" - } - }, - "System.Net.Sockets": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.win.System.Net.Sockets": "4.3.0" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Extensions": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.win.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Reflection.Extensions": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Security.Claims": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Security.Principal": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "6JX7ZdaceBiLKLkYt8zJcp4xTJd1uYyXXEkPw6mnlUIjh1gZPIVKPtRXPmY5kLf6DwZmf5YLwR3QUrRonl7l0A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "2.0.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading.Overlapped": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m3HQ2dPiX/DSTpf+yJt8B0c+SRvzfqAJKx+QDWi+VLhz8svLT23MVjEOHPF/KiSLeArKU/iHescrbLd3yVgyNg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.Timer": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Timer": "4.3.0" - } - }, - "Zlib.Bindings": { - "type": "Transitive", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - } } } } \ No newline at end of file diff --git a/Projects/UOContent/Accounting/AccessRestrictions.cs b/Projects/UOContent/Accounting/AccessRestrictions.cs index 49389abb8..c35ef0efa 100644 --- a/Projects/UOContent/Accounting/AccessRestrictions.cs +++ b/Projects/UOContent/Accounting/AccessRestrictions.cs @@ -1,46 +1,46 @@ -using System; -using System.IO; -using System.Net; -using Server.Misc; - -namespace Server -{ - public class AccessRestrictions - { - public static void Initialize() - { - EventSink.SocketConnect += EventSink_SocketConnect; - } - - private static void EventSink_SocketConnect(SocketConnectEventArgs e) - { - try - { - IPAddress ip = ((IPEndPoint)e.Context.RemoteEndPoint).Address; - - if (Firewall.IsBlocked(ip)) - { - Console.WriteLine("Client: {0}: Firewall blocked connection attempt.", ip); - e.AllowConnection = false; - return; - } - - if (IPLimiter.SocketBlock && !IPLimiter.Verify(ip)) - { - Console.WriteLine("Client: {0}: Past IP limit threshold", ip); - - using (StreamWriter op = new StreamWriter("ipLimits.log", true)) - { - op.WriteLine("{0}\tPast IP limit threshold\t{1}", ip, DateTime.UtcNow); - } - - e.AllowConnection = false; - } - } - catch - { - e.AllowConnection = false; - } - } - } -} +using System; +using System.IO; +using System.Net; +using Server.Misc; + +namespace Server +{ + public class AccessRestrictions + { + public static void Initialize() + { + EventSink.SocketConnect += EventSink_SocketConnect; + } + + private static void EventSink_SocketConnect(SocketConnectEventArgs e) + { + try + { + var ip = ((IPEndPoint)e.Context.RemoteEndPoint).Address; + + if (Firewall.IsBlocked(ip)) + { + Console.WriteLine("Client: {0}: Firewall blocked connection attempt.", ip); + e.AllowConnection = false; + return; + } + + if (IPLimiter.SocketBlock && !IPLimiter.Verify(ip)) + { + Console.WriteLine("Client: {0}: Past IP limit threshold", ip); + + using (var op = new StreamWriter("ipLimits.log", true)) + { + op.WriteLine("{0}\tPast IP limit threshold\t{1}", ip, DateTime.UtcNow); + } + + e.AllowConnection = false; + } + } + catch + { + e.AllowConnection = false; + } + } + } +} diff --git a/Projects/UOContent/Accounting/Account.cs b/Projects/UOContent/Accounting/Account.cs index b83a69dbc..ded506daa 100644 --- a/Projects/UOContent/Accounting/Account.cs +++ b/Projects/UOContent/Accounting/Account.cs @@ -1,1049 +1,1076 @@ -using System; -using System.Collections.Generic; -using System.Net; -using System.Xml; -using Server.Accounting.Security; -using Server.Misc; -using Server.Mobiles; -using Server.Multis; -using Server.Network; - -namespace Server.Accounting -{ - public class Account : IAccount, IComparable - { - public static readonly TimeSpan YoungDuration = TimeSpan.FromHours(40.0); - public static readonly TimeSpan InactiveDuration = TimeSpan.FromDays(180.0); - public static readonly TimeSpan EmptyInactiveDuration = TimeSpan.FromDays(30.0); - - private AccessLevel m_AccessLevel; - private TimeSpan m_TotalGameTime; - private List m_Comments; - private List m_Tags; - private readonly Mobile[] m_Mobiles; - private PasswordProtectionAlgorithm m_PasswordAlgorithm; - - /// - /// Deletes the account, all characters of the account, and all houses of those characters - /// - public void Delete() - { - for (int i = 0; i < Length; ++i) - { - Mobile m = this[i]; - - if (m == null) - continue; - - List list = BaseHouse.GetHouses(m); - - for (int j = 0; j < list.Count; ++j) - list[j].Delete(); - - m.Delete(); - - m.Account = null; - m_Mobiles[i] = null; - } - - if (LoginIPs.Length != 0 && AccountHandler.IPTable.ContainsKey(LoginIPs[0])) - --AccountHandler.IPTable[LoginIPs[0]]; - - Accounts.Remove(Username); - } - - /// - /// Object detailing information about the hardware of the last person to log into this account - /// - public HardwareInfo HardwareInfo { get; set; } - - /// - /// List of IP addresses for restricted access. '*' wildcard supported. If the array contains zero entries, all IP addresses are allowed. - /// - public string[] IPRestrictions { get; set; } - - /// - /// List of IP addresses which have successfully logged into this account. - /// - public IPAddress[] LoginIPs { get; set; } - - /// - /// List of account comments. Type of contained objects is AccountComment. - /// - public List Comments => m_Comments ?? (m_Comments = new List()); - - /// - /// List of account tags. Type of contained objects is AccountTag. - /// - public List Tags => m_Tags ?? (m_Tags = new List()); - - /// - /// Account username. Case insensitive validation. - /// - public string Username { get; set; } - - /// - /// Account email address. - /// - public string Email { get; set; } - - /// - /// Account username and password. May be null. - /// - public string Password { get; set; } - - /// - /// Initial AccessLevel for new characters created on this account. - /// - public AccessLevel AccessLevel - { - get => m_AccessLevel; - set => m_AccessLevel = value; - } - - /// - /// Internal bitfield of account flags. Consider using direct access properties (Banned, Young), or GetFlag/SetFlag methods - /// - public int Flags { get; set; } - - /// - /// Gets or sets a flag indicating if this account is banned. - /// - public bool Banned - { - get - { - bool isBanned = GetFlag(0); - - if (!isBanned) - return false; - - if (GetBanTags(out DateTime banTime, out TimeSpan banDuration)) - if (banDuration != TimeSpan.MaxValue && DateTime.UtcNow >= banTime + banDuration) - { - SetUnspecifiedBan(null); // clear - Banned = false; - return false; - } - - return true; - } - set => SetFlag(0, value); - } - - /// - /// Gets or sets a flag indicating if the characters created on this account will have the young status. - /// - public bool Young - { - get => !GetFlag(1); - set - { - SetFlag(1, !value); - - m_YoungTimer?.Stop(); - m_YoungTimer = null; - } - } - - /// - /// The date and time of when this account was created. - /// - public DateTime Created { get; } - - /// - /// Gets or sets the date and time when this account was last accessed. - /// - public DateTime LastLogin { get; set; } - - /// - /// An account is considered inactive based upon LastLogin and InactiveDuration. If the account is empty, it is based upon EmptyInactiveDuration - /// - public bool Inactive - { - get - { - if (AccessLevel != AccessLevel.Player) - return false; - - TimeSpan inactiveLength = DateTime.UtcNow - LastLogin; - - return inactiveLength > (Count == 0 ? EmptyInactiveDuration : InactiveDuration); - } - } - - /// - /// Gets the total game time of this account, also considering the game time of characters - /// that have been deleted. - /// - public TimeSpan TotalGameTime - { - get - { - for (int i = 0; i < m_Mobiles.Length; i++) - if (m_Mobiles[i] is PlayerMobile m && m.NetState != null) - return m_TotalGameTime + (DateTime.UtcNow - m.SessionStart); - - return m_TotalGameTime; - } - } - - /// - /// Gets the value of a specific flag in the Flags bitfield. - /// - /// The zero-based flag index. - public bool GetFlag(int index) => (Flags & 1 << index) != 0; - - /// - /// Sets the value of a specific flag in the Flags bitfield. - /// - /// The zero-based flag index. - /// The value to set. - public void SetFlag(int index, bool value) - { - if (value) - Flags |= 1 << index; - else - Flags &= ~(1 << index); - } - - /// - /// Adds a new tag to this account. This method does not check for duplicate names. - /// - /// New tag name. - /// New tag value. - public void AddTag(string name, string value) - { - Tags.Add(new AccountTag(name, value)); - } - - /// - /// Removes all tags with the specified name from this account. - /// - /// Tag name to remove. - public void RemoveTag(string name) - { - for (int i = Tags.Count - 1; i >= 0; --i) - { - if (i >= Tags.Count) - continue; - - AccountTag tag = Tags[i]; - - if (tag.Name == name) - Tags.RemoveAt(i); - } - } - - /// - /// Modifies an existing tag or adds a new tag if no tag exists. - /// - /// Tag name. - /// Tag value. - public void SetTag(string name, string value) - { - for (int i = 0; i < Tags.Count; ++i) - { - AccountTag tag = Tags[i]; - - if (tag.Name == name) - { - tag.Value = value; - return; - } - } - - AddTag(name, value); - } - - /// - /// Gets the value of a tag -or- null if there are no tags with the specified name. - /// - /// Name of the desired tag value. - public string GetTag(string name) - { - for (int i = 0; i < Tags.Count; ++i) - { - AccountTag tag = Tags[i]; - - if (tag.Name == name) - return tag.Value; - } - - return null; - } - - public void SetUnspecifiedBan(Mobile from) - { - SetBanTags(from, DateTime.MinValue, TimeSpan.Zero); - } - - public void SetBanTags(Mobile from, DateTime banTime, TimeSpan banDuration) - { - if (from == null) - RemoveTag("BanDealer"); - else - SetTag("BanDealer", from.ToString()); - - if (banTime == DateTime.MinValue) - RemoveTag("BanTime"); - else - SetTag("BanTime", XmlConvert.ToString(banTime, XmlDateTimeSerializationMode.Utc)); - - if (banDuration == TimeSpan.Zero) - RemoveTag("BanDuration"); - else - SetTag("BanDuration", banDuration.ToString()); - } - - public bool GetBanTags(out DateTime banTime, out TimeSpan banDuration) - { - string tagDuration = GetTag("BanDuration"); - - banTime = Utility.GetXMLDateTime(GetTag("BanTime"), DateTime.MinValue); - - if (tagDuration == "Infinite") - banDuration = TimeSpan.MaxValue; - else if (tagDuration != null) - banDuration = Utility.ToTimeSpan(tagDuration); - else - banDuration = TimeSpan.Zero; - - return banTime != DateTime.MinValue && banDuration != TimeSpan.Zero; - } - - public void SetPassword(string plainPassword) - { - Password = AccountSecurity.CurrentPasswordProtection.EncryptPassword(plainPassword); - m_PasswordAlgorithm = AccountSecurity.CurrentAlgorithm; - } - - public bool CheckPassword(string plainPassword) - { - string phrase = m_PasswordAlgorithm == PasswordProtectionAlgorithm.SHA1 ? $"{Username}{plainPassword}" : plainPassword; - - bool ok = AccountSecurity.GetPasswordProtection(m_PasswordAlgorithm).ValidatePassword(Password, phrase); - if (!ok) - return false; - - // Upgrade the password protection in case we change the algorithm - if (m_PasswordAlgorithm != AccountSecurity.CurrentAlgorithm) - SetPassword(plainPassword); - - return true; - } - - private Timer m_YoungTimer; - - public static void Initialize() - { - EventSink.Connected += EventSink_Connected; - EventSink.Disconnected += EventSink_Disconnected; - EventSink.Login += EventSink_Login; - } - - private static void EventSink_Connected(Mobile m) - { - if (!(m.Account is Account acc)) - return; - - if (acc.Young && acc.m_YoungTimer == null) - { - acc.m_YoungTimer = new YoungTimer(acc); - acc.m_YoungTimer.Start(); - } - } - - private static void EventSink_Disconnected(Mobile m) - { - if (!(m.Account is Account acc)) - return; - - if (acc.m_YoungTimer != null) - { - acc.m_YoungTimer.Stop(); - acc.m_YoungTimer = null; - } - - if (!(m is PlayerMobile pm)) - return; - - acc.m_TotalGameTime += DateTime.UtcNow - pm.SessionStart; - } - - private static void EventSink_Login(Mobile m) - { - if (!(m is PlayerMobile pm)) - return; - - if (!(m.Account is Account acc)) - return; - - if (pm.Young && acc.Young) - { - TimeSpan ts = YoungDuration - acc.TotalGameTime; - int hours = Math.Max((int)ts.TotalHours, 0); - - m.SendAsciiMessage("You will enjoy the benefits and relatively safe status of a young player for {0} more hour{1}.", hours, hours != 1 ? "s" : ""); - } - } - - public void RemoveYoungStatus(int message) - { - Young = false; - - for (int i = 0; i < m_Mobiles.Length; i++) - if (m_Mobiles[i] is PlayerMobile m && m.Young) - { - m.Young = false; - - if (m.NetState != null) - { - if (message > 0) - m.SendLocalizedMessage(message); - - m.SendLocalizedMessage(1019039); // You are no longer considered a young player of Ultima Online, and are no longer subject to the limitations and benefits of being in that caste. - } - } - } - - public void CheckYoung() - { - if (TotalGameTime >= YoungDuration) - RemoveYoungStatus(1019038); // You are old enough to be considered an adult, and have outgrown your status as a young player! - } - - private class YoungTimer : Timer - { - private readonly Account m_Account; - - public YoungTimer(Account account) - : base(TimeSpan.FromMinutes(1.0), TimeSpan.FromMinutes(1.0)) - { - m_Account = account; - - Priority = TimerPriority.FiveSeconds; - } - - protected override void OnTick() - { - m_Account.CheckYoung(); - } - } - - public Account(string username, string password) - { - Username = username; - - SetPassword(password); - - m_AccessLevel = AccessLevel.Player; - - Created = LastLogin = DateTime.UtcNow; - m_TotalGameTime = TimeSpan.Zero; - - m_Mobiles = new Mobile[7]; - - IPRestrictions = Array.Empty(); - LoginIPs = Array.Empty(); - - Accounts.Add(this); - } - - private bool UpgradePassword(string password, PasswordProtectionAlgorithm algorithm) - { - if (password == null || algorithm < m_PasswordAlgorithm) return false; - - m_PasswordAlgorithm = algorithm; - Password = password?.Replace("-", string.Empty); - return true; - } - - public Account(XmlElement node) - { - Username = Utility.GetText(node["username"], "empty"); - - Enum.TryParse(Utility.GetText(node["passwordAlgorithm"], null), true, out m_PasswordAlgorithm); - - // Backward compatibility with RunUO/ServUO - if (m_PasswordAlgorithm == PasswordProtectionAlgorithm.None) - { - bool upgraded = - UpgradePassword(Utility.GetText(node["newSecureCryptPassword"], null), PasswordProtectionAlgorithm.SHA2) || - UpgradePassword(Utility.GetText(node["newCryptPassword"], null), PasswordProtectionAlgorithm.SHA1) || - UpgradePassword(Utility.GetText(node["cryptPassword"], null), PasswordProtectionAlgorithm.MD5); - - // Automatically upgrade plain passwords to current algorithm. - if (!upgraded) - SetPassword(Utility.GetText(node["password"], null)); - } - else - Password = Utility.GetText(node["password"], null); - - Enum.TryParse(Utility.GetText(node["accessLevel"], "Player"), true, out m_AccessLevel); - Flags = Utility.GetXMLInt32(Utility.GetText(node["flags"], "0"), 0); - Created = Utility.GetXMLDateTime(Utility.GetText(node["created"], null), DateTime.UtcNow); - LastLogin = Utility.GetXMLDateTime(Utility.GetText(node["lastLogin"], null), DateTime.UtcNow); - - TotalGold = Utility.GetXMLInt32(Utility.GetText(node["totalGold"], "0"), 0); - TotalPlat = Utility.GetXMLInt32(Utility.GetText(node["totalPlat"], "0"), 0); - - m_Mobiles = LoadMobiles(node); - m_Comments = LoadComments(node); - m_Tags = LoadTags(node); - LoginIPs = LoadAddressList(node); - IPRestrictions = LoadAccessCheck(node); - - for (int i = 0; i < m_Mobiles.Length; ++i) - if (m_Mobiles[i] != null) - m_Mobiles[i].Account = this; - - TimeSpan totalGameTime = Utility.GetXMLTimeSpan(Utility.GetText(node["totalGameTime"], null), TimeSpan.Zero); - if (totalGameTime == TimeSpan.Zero) - for (int i = 0; i < m_Mobiles.Length; i++) - if (m_Mobiles[i] is PlayerMobile m) - totalGameTime += m.GameTime; - - m_TotalGameTime = totalGameTime; - - if (Young) - CheckYoung(); - - Accounts.Add(this); - } - - /// - /// Deserializes a list of string values from an xml element. Null values are not added to the list. - /// - /// The XmlElement from which to deserialize. - /// String list. Value will never be null. - public static string[] LoadAccessCheck(XmlElement node) - { - string[] stringList; - XmlElement accessCheck = node["accessCheck"]; - - if (accessCheck != null) - { - List list = new List(); - - foreach (XmlElement ip in accessCheck.GetElementsByTagName("ip")) - { - string text = Utility.GetText(ip, null); - - if (text != null) - list.Add(text); - } - - stringList = list.ToArray(); - } - else - { - stringList = Array.Empty(); - } - - return stringList; - } - - /// - /// Deserializes a list of IPAddress values from an xml element. - /// - /// The XmlElement from which to deserialize. - /// Address list. Value will never be null. - public static IPAddress[] LoadAddressList(XmlElement node) - { - IPAddress[] list; - XmlElement addressList = node["addressList"]; - - if (addressList != null) - { - int count = Utility.GetXMLInt32(Utility.GetAttribute(addressList, "count", "0"), 0); - - list = new IPAddress[count]; - - count = 0; - - foreach (XmlElement ip in addressList.GetElementsByTagName("ip")) - if (count < list.Length) - if (IPAddress.TryParse(Utility.GetText(ip, null), out IPAddress address)) - { - list[count] = Utility.Intern(address); - count++; - } - - if (count != list.Length) - { - IPAddress[] old = list; - list = new IPAddress[count]; - - for (int i = 0; i < count && i < old.Length; ++i) - list[i] = old[i]; - } - } - else - { - list = Array.Empty(); - } - - return list; - } - - /// - /// Deserializes a list of Mobile instances from an xml element. - /// - /// The XmlElement instance from which to deserialize. - /// Mobile list. Value will never be null. - public static Mobile[] LoadMobiles(XmlElement node) - { - Mobile[] list = new Mobile[7]; - XmlElement chars = node["chars"]; - - // int length = Accounts.GetInt32( Accounts.GetAttribute( chars, "length", "6" ), 6 ); - // list = new Mobile[length]; - // Above is legacy, no longer used - - if (chars != null) - foreach (XmlElement ele in chars.GetElementsByTagName("char")) - try - { - int index = Utility.GetXMLInt32(Utility.GetAttribute(ele, "index", "0"), 0); - uint serial = Utility.GetXMLUInt32(Utility.GetText(ele, "0"), 0); - - if (index >= 0 && index < list.Length) - list[index] = World.FindMobile(serial); - } - catch - { - // ignored - } - - return list; - } - - /// - /// Deserializes a list of AccountComment instances from an xml element. - /// - /// The XmlElement from which to deserialize. - /// Comment list. Value will never be null. - public static List LoadComments(XmlElement node) - { - List list = null; - XmlElement comments = node["comments"]; - - if (comments != null) - { - list = new List(); - - foreach (XmlElement comment in comments.GetElementsByTagName("comment")) - try { list.Add(new AccountComment(comment)); } - catch - { - // ignored - } - } - - return list; - } - - /// - /// Deserializes a list of AccountTag instances from an xml element. - /// - /// The XmlElement from which to deserialize. - /// Tag list. Value will never be null. - public static List LoadTags(XmlElement node) - { - List list = null; - XmlElement tags = node["tags"]; - - if (tags != null) - { - list = new List(); - - foreach (XmlElement tag in tags.GetElementsByTagName("tag")) - try { list.Add(new AccountTag(tag)); } - catch - { - // ignored - } - } - - return list; - } - - /// - /// Checks if a specific NetState is allowed access to this account. - /// - /// NetState instance to check. - /// True if allowed, false if not. - public bool HasAccess(NetState ns) => ns != null && HasAccess(ns.Address); - - public bool HasAccess(IPAddress ipAddress) - { - AccessLevel level = AccountHandler.LockdownLevel; - - if (level > AccessLevel.Player) - { - bool hasAccess = false; - - if (m_AccessLevel >= level) - hasAccess = true; - else - for (int i = 0; !hasAccess && i < Length; ++i) - { - Mobile m = this[i]; - - if (m?.AccessLevel >= level) - hasAccess = true; - } - - Console.WriteLine("{0} {1}", hasAccess ? "yes" : "no", m_AccessLevel); - - if (!hasAccess) - return false; - } - - bool accessAllowed = IPRestrictions.Length == 0 || IPLimiter.IsExempt(ipAddress); - - for (int i = 0; !accessAllowed && i < IPRestrictions.Length; ++i) - accessAllowed = Utility.IPMatch(IPRestrictions[i], ipAddress); - - return accessAllowed; - } - - /// - /// Records the IP address of 'ns' in its 'LoginIPs' list. - /// - /// NetState instance to record. - public void LogAccess(NetState ns) - { - if (ns != null) LogAccess(ns.Address); - } - - public void LogAccess(IPAddress ipAddress) - { - if (IPLimiter.IsExempt(ipAddress)) - return; - - if (LoginIPs.Length == 0) - { - if (AccountHandler.IPTable.ContainsKey(ipAddress)) - AccountHandler.IPTable[ipAddress]++; - else - AccountHandler.IPTable[ipAddress] = 1; - } - - bool contains = false; - - for (int i = 0; !contains && i < LoginIPs.Length; ++i) - contains = LoginIPs[i].Equals(ipAddress); - - if (contains) - return; - - IPAddress[] old = LoginIPs; - LoginIPs = new IPAddress[old.Length + 1]; - - for (int i = 0; i < old.Length; ++i) - LoginIPs[i] = old[i]; - - LoginIPs[old.Length] = ipAddress; - } - - /// - /// Checks if a specific NetState is allowed access to this account. If true, the NetState IPAddress is added to the address list. - /// - /// NetState instance to check. - /// True if allowed, false if not. - public bool CheckAccess(NetState ns) => ns != null && CheckAccess(ns.Address); - - public bool CheckAccess(IPAddress ipAddress) - { - bool hasAccess = HasAccess(ipAddress); - - if (hasAccess) - LogAccess(ipAddress); - - return hasAccess; - } - - /// - /// Serializes this Account instance to an XmlTextWriter. - /// - /// The XmlTextWriter instance from which to serialize. - public void Save(XmlTextWriter xml) - { - xml.WriteStartElement("account"); - - xml.WriteStartElement("username"); - xml.WriteString(Username); - xml.WriteEndElement(); - - xml.WriteStartElement("passwordAlgorithm"); - xml.WriteString(m_PasswordAlgorithm.ToString()); - xml.WriteEndElement(); - - xml.WriteStartElement("password"); - xml.WriteString(Password); - xml.WriteEndElement(); - - if (m_AccessLevel != AccessLevel.Player) - { - xml.WriteStartElement("accessLevel"); - xml.WriteString(m_AccessLevel.ToString()); - xml.WriteEndElement(); - } - - if (Flags != 0) - { - xml.WriteStartElement("flags"); - xml.WriteString(XmlConvert.ToString(Flags)); - xml.WriteEndElement(); - } - - xml.WriteStartElement("created"); - xml.WriteString(XmlConvert.ToString(Created, XmlDateTimeSerializationMode.Utc)); - xml.WriteEndElement(); - - xml.WriteStartElement("lastLogin"); - xml.WriteString(XmlConvert.ToString(LastLogin, XmlDateTimeSerializationMode.Utc)); - xml.WriteEndElement(); - - xml.WriteStartElement("totalGameTime"); - xml.WriteString(XmlConvert.ToString(TotalGameTime)); - xml.WriteEndElement(); - - xml.WriteStartElement("chars"); - - for (int i = 0; i < m_Mobiles.Length; ++i) - { - Mobile m = m_Mobiles[i]; - - if (m?.Deleted == false) - { - xml.WriteStartElement("char"); - xml.WriteAttributeString("index", i.ToString()); - xml.WriteString(m.Serial.Value.ToString()); - xml.WriteEndElement(); - } - } - - xml.WriteEndElement(); - - if (m_Comments?.Count > 0) - { - xml.WriteStartElement("comments"); - - for (int i = 0; i < m_Comments.Count; ++i) - m_Comments[i].Save(xml); - - xml.WriteEndElement(); - } - - if (m_Tags?.Count > 0) - { - xml.WriteStartElement("tags"); - - for (int i = 0; i < m_Tags.Count; ++i) - m_Tags[i].Save(xml); - - xml.WriteEndElement(); - } - - if (LoginIPs.Length > 0) - { - xml.WriteStartElement("addressList"); - - xml.WriteAttributeString("count", LoginIPs.Length.ToString()); - - for (int i = 0; i < LoginIPs.Length; ++i) - { - xml.WriteStartElement("ip"); - xml.WriteString(LoginIPs[i].ToString()); - xml.WriteEndElement(); - } - - xml.WriteEndElement(); - } - - if (IPRestrictions.Length > 0) - { - xml.WriteStartElement("accessCheck"); - - for (int i = 0; i < IPRestrictions.Length; ++i) - { - xml.WriteStartElement("ip"); - xml.WriteString(IPRestrictions[i]); - xml.WriteEndElement(); - } - - xml.WriteEndElement(); - } - - xml.WriteStartElement("totalGold"); - xml.WriteString(XmlConvert.ToString(TotalGold)); - xml.WriteEndElement(); - - xml.WriteStartElement("totalPlat"); - xml.WriteString(XmlConvert.ToString(TotalPlat)); - xml.WriteEndElement(); - - xml.WriteEndElement(); - } - - /// - /// Gets the current number of characters on this account. - /// - public int Count - { - get - { - int count = 0; - - for (int i = 0; i < Length; i++) - if (this[i] != null) - count++; - - return count; - } - } - - /// - /// Gets the maximum amount of characters allowed to be created on this account. Values other than 1, 5, 6, or 7 are not supported by the client. - /// - public int Limit => Core.SA ? 7 : Core.AOS ? 6 : 5; - - /// - /// Gets the maximum amount of characters that this account can hold. - /// - public int Length => m_Mobiles.Length; - - /// - /// Gets or sets the character at a specified index for this account. Out of bound index values are handled; null returned for get, ignored for set. - /// - public Mobile this[int index] - { - get - { - if (index >= 0 && index < m_Mobiles.Length) - { - Mobile m = m_Mobiles[index]; - - if (m?.Deleted != true) - return m; - - // This is the only place that clears a mobile for garbage collection - // outside of an entire account deletion. - m.Account = null; - m_Mobiles[index] = null; - } - - return null; - } - set - { - if (index >= 0 && index < m_Mobiles.Length) - { - if (m_Mobiles[index] != null) - m_Mobiles[index].Account = null; - - m_Mobiles[index] = value; - - if (m_Mobiles[index] != null) - m_Mobiles[index].Account = this; - } - } - } - - public override string ToString() => Username; - - public int CompareTo(Account other) => other == null ? 1 : Username.CompareTo(other.Username); - - public int CompareTo(IAccount other) => other == null ? 1 : Username.CompareTo(other.Username); - - /// - /// This amount represents the current amount of Gold owned by the player. - /// The value does not include the value of Platinum and ranges from - /// 0 to 999,999,999 by default. - /// - [CommandProperty(AccessLevel.Administrator)] - public int TotalGold { get; private set; } - - /// - /// This amount represents the current amount of Platinum owned by the player. - /// The value does not include the value of Gold and ranges from - /// 0 to 2,147,483,647 by default. - /// One Platinum represents the value of CurrencyThreshold in Gold. - /// - [CommandProperty(AccessLevel.Administrator)] - public int TotalPlat { get; private set; } - - /// - /// Attempts to deposit the given amount of Gold into this account. - /// If the given amount is greater than the CurrencyThreshold, - /// Platinum will be deposited to offset the difference. - /// - /// Amount to deposit. - /// True if successful, false if amount given is less than or equal to zero. - public bool DepositGold(int amount) - { - if (amount <= 0) return false; - - int plat = Math.DivRem(amount, AccountGold.CurrencyThreshold, out int gold); - TotalPlat += plat; - TotalGold += gold; - - return true; - } - - /// - /// Attempts to deposit the given amount of Platinum into this account. - /// - /// Amount to deposit. - /// True if successful, false if amount given is less than or equal to zero. - public bool DepositPlat(int amount) - { - if (amount <= 0) return false; - - TotalPlat += amount; - return true; - } - - /// - /// Attempts to withdraw the given amount of Gold from this account. - /// If the given amount is greater than the CurrencyThreshold, - /// Platinum will be withdrawn to offset the difference. - /// - /// Amount to withdraw. - /// True if successful, false if balance was too low. - public bool WithdrawGold(int amount) - { - if (amount <= 0) return true; - if (amount > TotalGold) return false; - - TotalGold -= amount; - - return true; - } - - /// - /// Attempts to withdraw the given amount of Platinum from this account. - /// - /// Amount to withdraw. - /// True if successful, false if balance was too low. - public bool WithdrawPlat(int amount) - { - if (amount <= 0) return true; - if (amount > TotalPlat) return false; - - TotalPlat -= amount; - - return true; - } - - /// - /// Returns total gold inclusive of platinum. - /// This is strictly for backwards compatibility - /// - /// Total gold, capped at Int32.MaxValue - public long GetTotalGold() => TotalGold + TotalPlat * AccountGold.CurrencyThreshold; - } -} +using System; +using System.Collections.Generic; +using System.Net; +using System.Xml; +using Server.Accounting.Security; +using Server.Misc; +using Server.Mobiles; +using Server.Multis; +using Server.Network; + +namespace Server.Accounting +{ + public class Account : IAccount, IComparable + { + public static readonly TimeSpan YoungDuration = TimeSpan.FromHours(40.0); + public static readonly TimeSpan InactiveDuration = TimeSpan.FromDays(180.0); + public static readonly TimeSpan EmptyInactiveDuration = TimeSpan.FromDays(30.0); + private readonly Mobile[] m_Mobiles; + + private AccessLevel m_AccessLevel; + private List m_Comments; + private PasswordProtectionAlgorithm m_PasswordAlgorithm; + private List m_Tags; + private TimeSpan m_TotalGameTime; + + private Timer m_YoungTimer; + + public Account(string username, string password) + { + Username = username; + + SetPassword(password); + + m_AccessLevel = AccessLevel.Player; + + Created = LastLogin = DateTime.UtcNow; + m_TotalGameTime = TimeSpan.Zero; + + m_Mobiles = new Mobile[7]; + + IPRestrictions = Array.Empty(); + LoginIPs = Array.Empty(); + + Accounts.Add(this); + } + + public Account(XmlElement node) + { + Username = Utility.GetText(node["username"], "empty"); + + Enum.TryParse(Utility.GetText(node["passwordAlgorithm"], null), true, out m_PasswordAlgorithm); + + // Backward compatibility with RunUO/ServUO + if (m_PasswordAlgorithm == PasswordProtectionAlgorithm.None) + { + var upgraded = + UpgradePassword( + Utility.GetText(node["newSecureCryptPassword"], null), + PasswordProtectionAlgorithm.SHA2 + ) || + UpgradePassword(Utility.GetText(node["newCryptPassword"], null), PasswordProtectionAlgorithm.SHA1) || + UpgradePassword(Utility.GetText(node["cryptPassword"], null), PasswordProtectionAlgorithm.MD5); + + // Automatically upgrade plain passwords to current algorithm. + if (!upgraded) + SetPassword(Utility.GetText(node["password"], null)); + } + else + { + Password = Utility.GetText(node["password"], null); + } + + Enum.TryParse(Utility.GetText(node["accessLevel"], "Player"), true, out m_AccessLevel); + Flags = Utility.GetXMLInt32(Utility.GetText(node["flags"], "0"), 0); + Created = Utility.GetXMLDateTime(Utility.GetText(node["created"], null), DateTime.UtcNow); + LastLogin = Utility.GetXMLDateTime(Utility.GetText(node["lastLogin"], null), DateTime.UtcNow); + + TotalGold = Utility.GetXMLInt32(Utility.GetText(node["totalGold"], "0"), 0); + TotalPlat = Utility.GetXMLInt32(Utility.GetText(node["totalPlat"], "0"), 0); + + m_Mobiles = LoadMobiles(node); + m_Comments = LoadComments(node); + m_Tags = LoadTags(node); + LoginIPs = LoadAddressList(node); + IPRestrictions = LoadAccessCheck(node); + + for (var i = 0; i < m_Mobiles.Length; ++i) + if (m_Mobiles[i] != null) + m_Mobiles[i].Account = this; + + var totalGameTime = Utility.GetXMLTimeSpan(Utility.GetText(node["totalGameTime"], null), TimeSpan.Zero); + if (totalGameTime == TimeSpan.Zero) + for (var i = 0; i < m_Mobiles.Length; i++) + if (m_Mobiles[i] is PlayerMobile m) + totalGameTime += m.GameTime; + + m_TotalGameTime = totalGameTime; + + if (Young) + CheckYoung(); + + Accounts.Add(this); + } + + /// + /// Object detailing information about the hardware of the last person to log into this account + /// + public HardwareInfo HardwareInfo { get; set; } + + /// + /// List of IP addresses for restricted access. '*' wildcard supported. If the array contains zero entries, all IP addresses + /// are allowed. + /// + public string[] IPRestrictions { get; set; } + + /// + /// List of IP addresses which have successfully logged into this account. + /// + public IPAddress[] LoginIPs { get; set; } + + /// + /// List of account comments. Type of contained objects is AccountComment. + /// + public List Comments => m_Comments ?? (m_Comments = new List()); + + /// + /// List of account tags. Type of contained objects is AccountTag. + /// + public List Tags => m_Tags ?? (m_Tags = new List()); + + /// + /// Account username and password. May be null. + /// + public string Password { get; set; } + + /// + /// Internal bitfield of account flags. Consider using direct access properties (Banned, Young), or GetFlag/SetFlag methods + /// + public int Flags { get; set; } + + /// + /// Gets or sets a flag indicating if this account is banned. + /// + public bool Banned + { + get + { + var isBanned = GetFlag(0); + + if (!isBanned) + return false; + + if (GetBanTags(out var banTime, out var banDuration)) + if (banDuration != TimeSpan.MaxValue && DateTime.UtcNow >= banTime + banDuration) + { + SetUnspecifiedBan(null); // clear + Banned = false; + return false; + } + + return true; + } + set => SetFlag(0, value); + } + + /// + /// Gets or sets a flag indicating if the characters created on this account will have the young status. + /// + public bool Young + { + get => !GetFlag(1); + set + { + SetFlag(1, !value); + + m_YoungTimer?.Stop(); + m_YoungTimer = null; + } + } + + /// + /// The date and time of when this account was created. + /// + public DateTime Created { get; } + + /// + /// Gets or sets the date and time when this account was last accessed. + /// + public DateTime LastLogin { get; set; } + + /// + /// An account is considered inactive based upon LastLogin and InactiveDuration. If the account is empty, it is based upon + /// EmptyInactiveDuration + /// + public bool Inactive + { + get + { + if (AccessLevel != AccessLevel.Player) + return false; + + var inactiveLength = DateTime.UtcNow - LastLogin; + + return inactiveLength > (Count == 0 ? EmptyInactiveDuration : InactiveDuration); + } + } + + /// + /// Gets the total game time of this account, also considering the game time of characters + /// that have been deleted. + /// + public TimeSpan TotalGameTime + { + get + { + for (var i = 0; i < m_Mobiles.Length; i++) + if (m_Mobiles[i] is PlayerMobile m && m.NetState != null) + return m_TotalGameTime + (DateTime.UtcNow - m.SessionStart); + + return m_TotalGameTime; + } + } + + /// + /// Deletes the account, all characters of the account, and all houses of those characters + /// + public void Delete() + { + for (var i = 0; i < Length; ++i) + { + var m = this[i]; + + if (m == null) + continue; + + var list = BaseHouse.GetHouses(m); + + for (var j = 0; j < list.Count; ++j) + list[j].Delete(); + + m.Delete(); + + m.Account = null; + m_Mobiles[i] = null; + } + + if (LoginIPs.Length != 0 && AccountHandler.IPTable.ContainsKey(LoginIPs[0])) + --AccountHandler.IPTable[LoginIPs[0]]; + + Accounts.Remove(Username); + } + + /// + /// Account username. Case insensitive validation. + /// + public string Username { get; set; } + + /// + /// Account email address. + /// + public string Email { get; set; } + + /// + /// Initial AccessLevel for new characters created on this account. + /// + public AccessLevel AccessLevel + { + get => m_AccessLevel; + set => m_AccessLevel = value; + } + + public void SetPassword(string plainPassword) + { + Password = AccountSecurity.CurrentPasswordProtection.EncryptPassword(plainPassword); + m_PasswordAlgorithm = AccountSecurity.CurrentAlgorithm; + } + + public bool CheckPassword(string plainPassword) + { + var phrase = m_PasswordAlgorithm == PasswordProtectionAlgorithm.SHA1 + ? $"{Username}{plainPassword}" + : plainPassword; + + var ok = AccountSecurity.GetPasswordProtection(m_PasswordAlgorithm).ValidatePassword(Password, phrase); + if (!ok) + return false; + + // Upgrade the password protection in case we change the algorithm + if (m_PasswordAlgorithm != AccountSecurity.CurrentAlgorithm) + SetPassword(plainPassword); + + return true; + } + + /// + /// Gets the current number of characters on this account. + /// + public int Count + { + get + { + var count = 0; + + for (var i = 0; i < Length; i++) + if (this[i] != null) + count++; + + return count; + } + } + + /// + /// Gets the maximum amount of characters allowed to be created on this account. Values other than 1, 5, 6, or 7 are not + /// supported by the client. + /// + public int Limit => Core.SA ? 7 : + Core.AOS ? 6 : 5; + + /// + /// Gets the maximum amount of characters that this account can hold. + /// + public int Length => m_Mobiles.Length; + + /// + /// Gets or sets the character at a specified index for this account. Out of bound index values are handled; null returned + /// for get, ignored for set. + /// + public Mobile this[int index] + { + get + { + if (index >= 0 && index < m_Mobiles.Length) + { + var m = m_Mobiles[index]; + + if (m?.Deleted != true) + return m; + + // This is the only place that clears a mobile for garbage collection + // outside of an entire account deletion. + m.Account = null; + m_Mobiles[index] = null; + } + + return null; + } + set + { + if (index >= 0 && index < m_Mobiles.Length) + { + if (m_Mobiles[index] != null) + m_Mobiles[index].Account = null; + + m_Mobiles[index] = value; + + if (m_Mobiles[index] != null) + m_Mobiles[index].Account = this; + } + } + } + + public int CompareTo(IAccount other) => other == null ? 1 : Username.CompareTo(other.Username); + + /// + /// This amount represents the current amount of Gold owned by the player. + /// The value does not include the value of Platinum and ranges from + /// 0 to 999,999,999 by default. + /// + [CommandProperty(AccessLevel.Administrator)] + public int TotalGold { get; private set; } + + /// + /// This amount represents the current amount of Platinum owned by the player. + /// The value does not include the value of Gold and ranges from + /// 0 to 2,147,483,647 by default. + /// One Platinum represents the value of CurrencyThreshold in Gold. + /// + [CommandProperty(AccessLevel.Administrator)] + public int TotalPlat { get; private set; } + + /// + /// Attempts to deposit the given amount of Gold into this account. + /// If the given amount is greater than the CurrencyThreshold, + /// Platinum will be deposited to offset the difference. + /// + /// Amount to deposit. + /// True if successful, false if amount given is less than or equal to zero. + public bool DepositGold(int amount) + { + if (amount <= 0) return false; + + var plat = Math.DivRem(amount, AccountGold.CurrencyThreshold, out var gold); + TotalPlat += plat; + TotalGold += gold; + + return true; + } + + /// + /// Attempts to deposit the given amount of Platinum into this account. + /// + /// Amount to deposit. + /// True if successful, false if amount given is less than or equal to zero. + public bool DepositPlat(int amount) + { + if (amount <= 0) return false; + + TotalPlat += amount; + return true; + } + + /// + /// Attempts to withdraw the given amount of Gold from this account. + /// If the given amount is greater than the CurrencyThreshold, + /// Platinum will be withdrawn to offset the difference. + /// + /// Amount to withdraw. + /// True if successful, false if balance was too low. + public bool WithdrawGold(int amount) + { + if (amount <= 0) return true; + if (amount > TotalGold) return false; + + TotalGold -= amount; + + return true; + } + + /// + /// Attempts to withdraw the given amount of Platinum from this account. + /// + /// Amount to withdraw. + /// True if successful, false if balance was too low. + public bool WithdrawPlat(int amount) + { + if (amount <= 0) return true; + if (amount > TotalPlat) return false; + + TotalPlat -= amount; + + return true; + } + + /// + /// Returns total gold inclusive of platinum. + /// This is strictly for backwards compatibility + /// + /// Total gold, capped at Int32.MaxValue + public long GetTotalGold() => TotalGold + TotalPlat * AccountGold.CurrencyThreshold; + + public int CompareTo(Account other) => other == null ? 1 : Username.CompareTo(other.Username); + + /// + /// Gets the value of a specific flag in the Flags bitfield. + /// + /// The zero-based flag index. + public bool GetFlag(int index) => (Flags & (1 << index)) != 0; + + /// + /// Sets the value of a specific flag in the Flags bitfield. + /// + /// The zero-based flag index. + /// The value to set. + public void SetFlag(int index, bool value) + { + if (value) + Flags |= 1 << index; + else + Flags &= ~(1 << index); + } + + /// + /// Adds a new tag to this account. This method does not check for duplicate names. + /// + /// New tag name. + /// New tag value. + public void AddTag(string name, string value) + { + Tags.Add(new AccountTag(name, value)); + } + + /// + /// Removes all tags with the specified name from this account. + /// + /// Tag name to remove. + public void RemoveTag(string name) + { + for (var i = Tags.Count - 1; i >= 0; --i) + { + if (i >= Tags.Count) + continue; + + var tag = Tags[i]; + + if (tag.Name == name) + Tags.RemoveAt(i); + } + } + + /// + /// Modifies an existing tag or adds a new tag if no tag exists. + /// + /// Tag name. + /// Tag value. + public void SetTag(string name, string value) + { + for (var i = 0; i < Tags.Count; ++i) + { + var tag = Tags[i]; + + if (tag.Name == name) + { + tag.Value = value; + return; + } + } + + AddTag(name, value); + } + + /// + /// Gets the value of a tag -or- null if there are no tags with the specified name. + /// + /// Name of the desired tag value. + public string GetTag(string name) + { + for (var i = 0; i < Tags.Count; ++i) + { + var tag = Tags[i]; + + if (tag.Name == name) + return tag.Value; + } + + return null; + } + + public void SetUnspecifiedBan(Mobile from) + { + SetBanTags(from, DateTime.MinValue, TimeSpan.Zero); + } + + public void SetBanTags(Mobile from, DateTime banTime, TimeSpan banDuration) + { + if (from == null) + RemoveTag("BanDealer"); + else + SetTag("BanDealer", from.ToString()); + + if (banTime == DateTime.MinValue) + RemoveTag("BanTime"); + else + SetTag("BanTime", XmlConvert.ToString(banTime, XmlDateTimeSerializationMode.Utc)); + + if (banDuration == TimeSpan.Zero) + RemoveTag("BanDuration"); + else + SetTag("BanDuration", banDuration.ToString()); + } + + public bool GetBanTags(out DateTime banTime, out TimeSpan banDuration) + { + var tagDuration = GetTag("BanDuration"); + + banTime = Utility.GetXMLDateTime(GetTag("BanTime"), DateTime.MinValue); + + if (tagDuration == "Infinite") + banDuration = TimeSpan.MaxValue; + else if (tagDuration != null) + banDuration = Utility.ToTimeSpan(tagDuration); + else + banDuration = TimeSpan.Zero; + + return banTime != DateTime.MinValue && banDuration != TimeSpan.Zero; + } + + public static void Initialize() + { + EventSink.Connected += EventSink_Connected; + EventSink.Disconnected += EventSink_Disconnected; + EventSink.Login += EventSink_Login; + } + + private static void EventSink_Connected(Mobile m) + { + if (!(m.Account is Account acc)) + return; + + if (acc.Young && acc.m_YoungTimer == null) + { + acc.m_YoungTimer = new YoungTimer(acc); + acc.m_YoungTimer.Start(); + } + } + + private static void EventSink_Disconnected(Mobile m) + { + if (!(m.Account is Account acc)) + return; + + if (acc.m_YoungTimer != null) + { + acc.m_YoungTimer.Stop(); + acc.m_YoungTimer = null; + } + + if (!(m is PlayerMobile pm)) + return; + + acc.m_TotalGameTime += DateTime.UtcNow - pm.SessionStart; + } + + private static void EventSink_Login(Mobile m) + { + if (!(m is PlayerMobile pm)) + return; + + if (!(m.Account is Account acc)) + return; + + if (pm.Young && acc.Young) + { + var ts = YoungDuration - acc.TotalGameTime; + var hours = Math.Max((int)ts.TotalHours, 0); + + m.SendAsciiMessage( + "You will enjoy the benefits and relatively safe status of a young player for {0} more hour{1}.", + hours, + hours != 1 ? "s" : "" + ); + } + } + + public void RemoveYoungStatus(int message) + { + Young = false; + + for (var i = 0; i < m_Mobiles.Length; i++) + if (m_Mobiles[i] is PlayerMobile m && m.Young) + { + m.Young = false; + + if (m.NetState != null) + { + if (message > 0) + m.SendLocalizedMessage(message); + + m.SendLocalizedMessage( + 1019039 + ); // You are no longer considered a young player of Ultima Online, and are no longer subject to the limitations and benefits of being in that caste. + } + } + } + + public void CheckYoung() + { + if (TotalGameTime >= YoungDuration) + RemoveYoungStatus( + 1019038 + ); // You are old enough to be considered an adult, and have outgrown your status as a young player! + } + + private bool UpgradePassword(string password, PasswordProtectionAlgorithm algorithm) + { + if (password == null || algorithm < m_PasswordAlgorithm) return false; + + m_PasswordAlgorithm = algorithm; + Password = password?.Replace("-", string.Empty); + return true; + } + + /// + /// Deserializes a list of string values from an xml element. Null values are not added to the list. + /// + /// The XmlElement from which to deserialize. + /// String list. Value will never be null. + public static string[] LoadAccessCheck(XmlElement node) + { + string[] stringList; + var accessCheck = node["accessCheck"]; + + if (accessCheck != null) + { + var list = new List(); + + foreach (XmlElement ip in accessCheck.GetElementsByTagName("ip")) + { + var text = Utility.GetText(ip, null); + + if (text != null) + list.Add(text); + } + + stringList = list.ToArray(); + } + else + { + stringList = Array.Empty(); + } + + return stringList; + } + + /// + /// Deserializes a list of IPAddress values from an xml element. + /// + /// The XmlElement from which to deserialize. + /// Address list. Value will never be null. + public static IPAddress[] LoadAddressList(XmlElement node) + { + IPAddress[] list; + var addressList = node["addressList"]; + + if (addressList != null) + { + var count = Utility.GetXMLInt32(Utility.GetAttribute(addressList, "count", "0"), 0); + + list = new IPAddress[count]; + + count = 0; + + foreach (XmlElement ip in addressList.GetElementsByTagName("ip")) + if (count < list.Length) + if (IPAddress.TryParse(Utility.GetText(ip, null), out var address)) + { + list[count] = Utility.Intern(address); + count++; + } + + if (count != list.Length) + { + var old = list; + list = new IPAddress[count]; + + for (var i = 0; i < count && i < old.Length; ++i) + list[i] = old[i]; + } + } + else + { + list = Array.Empty(); + } + + return list; + } + + /// + /// Deserializes a list of Mobile instances from an xml element. + /// + /// The XmlElement instance from which to deserialize. + /// Mobile list. Value will never be null. + public static Mobile[] LoadMobiles(XmlElement node) + { + var list = new Mobile[7]; + var chars = node["chars"]; + + // int length = Accounts.GetInt32( Accounts.GetAttribute( chars, "length", "6" ), 6 ); + // list = new Mobile[length]; + // Above is legacy, no longer used + + if (chars != null) + foreach (XmlElement ele in chars.GetElementsByTagName("char")) + try + { + var index = Utility.GetXMLInt32(Utility.GetAttribute(ele, "index", "0"), 0); + var serial = Utility.GetXMLUInt32(Utility.GetText(ele, "0"), 0); + + if (index >= 0 && index < list.Length) + list[index] = World.FindMobile(serial); + } + catch + { + // ignored + } + + return list; + } + + /// + /// Deserializes a list of AccountComment instances from an xml element. + /// + /// The XmlElement from which to deserialize. + /// Comment list. Value will never be null. + public static List LoadComments(XmlElement node) + { + List list = null; + var comments = node["comments"]; + + if (comments != null) + { + list = new List(); + + foreach (XmlElement comment in comments.GetElementsByTagName("comment")) + try + { + list.Add(new AccountComment(comment)); + } + catch + { + // ignored + } + } + + return list; + } + + /// + /// Deserializes a list of AccountTag instances from an xml element. + /// + /// The XmlElement from which to deserialize. + /// Tag list. Value will never be null. + public static List LoadTags(XmlElement node) + { + List list = null; + var tags = node["tags"]; + + if (tags != null) + { + list = new List(); + + foreach (XmlElement tag in tags.GetElementsByTagName("tag")) + try + { + list.Add(new AccountTag(tag)); + } + catch + { + // ignored + } + } + + return list; + } + + /// + /// Checks if a specific NetState is allowed access to this account. + /// + /// NetState instance to check. + /// True if allowed, false if not. + public bool HasAccess(NetState ns) => ns != null && HasAccess(ns.Address); + + public bool HasAccess(IPAddress ipAddress) + { + var level = AccountHandler.LockdownLevel; + + if (level > AccessLevel.Player) + { + var hasAccess = false; + + if (m_AccessLevel >= level) + hasAccess = true; + else + for (var i = 0; !hasAccess && i < Length; ++i) + { + var m = this[i]; + + if (m?.AccessLevel >= level) + hasAccess = true; + } + + Console.WriteLine("{0} {1}", hasAccess ? "yes" : "no", m_AccessLevel); + + if (!hasAccess) + return false; + } + + var accessAllowed = IPRestrictions.Length == 0 || IPLimiter.IsExempt(ipAddress); + + for (var i = 0; !accessAllowed && i < IPRestrictions.Length; ++i) + accessAllowed = Utility.IPMatch(IPRestrictions[i], ipAddress); + + return accessAllowed; + } + + /// + /// Records the IP address of 'ns' in its 'LoginIPs' list. + /// + /// NetState instance to record. + public void LogAccess(NetState ns) + { + if (ns != null) LogAccess(ns.Address); + } + + public void LogAccess(IPAddress ipAddress) + { + if (IPLimiter.IsExempt(ipAddress)) + return; + + if (LoginIPs.Length == 0) + { + if (AccountHandler.IPTable.ContainsKey(ipAddress)) + AccountHandler.IPTable[ipAddress]++; + else + AccountHandler.IPTable[ipAddress] = 1; + } + + var contains = false; + + for (var i = 0; !contains && i < LoginIPs.Length; ++i) + contains = LoginIPs[i].Equals(ipAddress); + + if (contains) + return; + + var old = LoginIPs; + LoginIPs = new IPAddress[old.Length + 1]; + + for (var i = 0; i < old.Length; ++i) + LoginIPs[i] = old[i]; + + LoginIPs[old.Length] = ipAddress; + } + + /// + /// Checks if a specific NetState is allowed access to this account. If true, the NetState IPAddress is added to the address + /// list. + /// + /// NetState instance to check. + /// True if allowed, false if not. + public bool CheckAccess(NetState ns) => ns != null && CheckAccess(ns.Address); + + public bool CheckAccess(IPAddress ipAddress) + { + var hasAccess = HasAccess(ipAddress); + + if (hasAccess) + LogAccess(ipAddress); + + return hasAccess; + } + + /// + /// Serializes this Account instance to an XmlTextWriter. + /// + /// The XmlTextWriter instance from which to serialize. + public void Save(XmlTextWriter xml) + { + xml.WriteStartElement("account"); + + xml.WriteStartElement("username"); + xml.WriteString(Username); + xml.WriteEndElement(); + + xml.WriteStartElement("passwordAlgorithm"); + xml.WriteString(m_PasswordAlgorithm.ToString()); + xml.WriteEndElement(); + + xml.WriteStartElement("password"); + xml.WriteString(Password); + xml.WriteEndElement(); + + if (m_AccessLevel != AccessLevel.Player) + { + xml.WriteStartElement("accessLevel"); + xml.WriteString(m_AccessLevel.ToString()); + xml.WriteEndElement(); + } + + if (Flags != 0) + { + xml.WriteStartElement("flags"); + xml.WriteString(XmlConvert.ToString(Flags)); + xml.WriteEndElement(); + } + + xml.WriteStartElement("created"); + xml.WriteString(XmlConvert.ToString(Created, XmlDateTimeSerializationMode.Utc)); + xml.WriteEndElement(); + + xml.WriteStartElement("lastLogin"); + xml.WriteString(XmlConvert.ToString(LastLogin, XmlDateTimeSerializationMode.Utc)); + xml.WriteEndElement(); + + xml.WriteStartElement("totalGameTime"); + xml.WriteString(XmlConvert.ToString(TotalGameTime)); + xml.WriteEndElement(); + + xml.WriteStartElement("chars"); + + for (var i = 0; i < m_Mobiles.Length; ++i) + { + var m = m_Mobiles[i]; + + if (m?.Deleted == false) + { + xml.WriteStartElement("char"); + xml.WriteAttributeString("index", i.ToString()); + xml.WriteString(m.Serial.Value.ToString()); + xml.WriteEndElement(); + } + } + + xml.WriteEndElement(); + + if (m_Comments?.Count > 0) + { + xml.WriteStartElement("comments"); + + for (var i = 0; i < m_Comments.Count; ++i) + m_Comments[i].Save(xml); + + xml.WriteEndElement(); + } + + if (m_Tags?.Count > 0) + { + xml.WriteStartElement("tags"); + + for (var i = 0; i < m_Tags.Count; ++i) + m_Tags[i].Save(xml); + + xml.WriteEndElement(); + } + + if (LoginIPs.Length > 0) + { + xml.WriteStartElement("addressList"); + + xml.WriteAttributeString("count", LoginIPs.Length.ToString()); + + for (var i = 0; i < LoginIPs.Length; ++i) + { + xml.WriteStartElement("ip"); + xml.WriteString(LoginIPs[i].ToString()); + xml.WriteEndElement(); + } + + xml.WriteEndElement(); + } + + if (IPRestrictions.Length > 0) + { + xml.WriteStartElement("accessCheck"); + + for (var i = 0; i < IPRestrictions.Length; ++i) + { + xml.WriteStartElement("ip"); + xml.WriteString(IPRestrictions[i]); + xml.WriteEndElement(); + } + + xml.WriteEndElement(); + } + + xml.WriteStartElement("totalGold"); + xml.WriteString(XmlConvert.ToString(TotalGold)); + xml.WriteEndElement(); + + xml.WriteStartElement("totalPlat"); + xml.WriteString(XmlConvert.ToString(TotalPlat)); + xml.WriteEndElement(); + + xml.WriteEndElement(); + } + + public override string ToString() => Username; + + private class YoungTimer : Timer + { + private readonly Account m_Account; + + public YoungTimer(Account account) + : base(TimeSpan.FromMinutes(1.0), TimeSpan.FromMinutes(1.0)) + { + m_Account = account; + + Priority = TimerPriority.FiveSeconds; + } + + protected override void OnTick() + { + m_Account.CheckYoung(); + } + } + } +} diff --git a/Projects/UOContent/Accounting/AccountAttackLimiter.cs b/Projects/UOContent/Accounting/AccountAttackLimiter.cs index 9d304777b..1dc6f743c 100644 --- a/Projects/UOContent/Accounting/AccountAttackLimiter.cs +++ b/Projects/UOContent/Accounting/AccountAttackLimiter.cs @@ -1,132 +1,134 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using Server.Network; - -namespace Server.Accounting -{ - public class AccountAttackLimiter - { - public static bool Enabled; - public static void Configure() - { - Enabled = ServerConfiguration.GetOrUpdateSetting("accountAttackLimiter.enable", true); - } - - private static readonly List m_List = new List(); - - public static void Initialize() - { - if (!Enabled) - return; - - PacketHandlers.RegisterThrottler(0x80, Throttle_Callback); - PacketHandlers.RegisterThrottler(0x91, Throttle_Callback); - PacketHandlers.RegisterThrottler(0xCF, Throttle_Callback); - } - - public static TimeSpan Throttle_Callback(NetState ns) - { - InvalidAccountAccessLog accessLog = FindAccessLog(ns); - - if (accessLog == null) - return TimeSpan.Zero; - - DateTime date = DateTime.UtcNow; - DateTime access = accessLog.LastAccessTime + ComputeThrottle(accessLog.Counts); - return date >= access ? TimeSpan.Zero : date - access; - } - - public static InvalidAccountAccessLog FindAccessLog(NetState ns) - { - if (ns == null) - return null; - - IPAddress ipAddress = ns.Address; - - for (int i = 0; i < m_List.Count; ++i) - { - InvalidAccountAccessLog accessLog = m_List[i]; - - if (accessLog.HasExpired) - m_List.RemoveAt(i--); - else if (accessLog.Address.Equals(ipAddress)) - return accessLog; - } - - return null; - } - - public static void RegisterInvalidAccess(NetState ns) - { - if (ns == null || !Enabled) - return; - - InvalidAccountAccessLog accessLog = FindAccessLog(ns); - - if (accessLog == null) - m_List.Add(accessLog = new InvalidAccountAccessLog(ns.Address)); - - accessLog.Counts += 1; - accessLog.RefreshAccessTime(); - - if (accessLog.Counts >= 3) - try - { - using StreamWriter op = new StreamWriter("throttle.log", true); - op.WriteLine( - "{0}\t{1}\t{2}", - DateTime.UtcNow, - ns, - accessLog.Counts); - } - catch - { - // ignored - } - } - - public static TimeSpan ComputeThrottle(int counts) - { - if (counts >= 15) - return TimeSpan.FromMinutes(5.0); - - if (counts >= 10) - return TimeSpan.FromMinutes(1.0); - - if (counts >= 5) - return TimeSpan.FromSeconds(20.0); - - if (counts >= 3) - return TimeSpan.FromSeconds(10.0); - - if (counts >= 1) - return TimeSpan.FromSeconds(2.0); - - return TimeSpan.Zero; - } - } - - public class InvalidAccountAccessLog - { - public InvalidAccountAccessLog(IPAddress address) - { - Address = address; - RefreshAccessTime(); - } - - public IPAddress Address { get; set; } - - public DateTime LastAccessTime { get; set; } - - public bool HasExpired => DateTime.UtcNow >= LastAccessTime + TimeSpan.FromHours(1.0); - - public int Counts { get; set; } - - public void RefreshAccessTime() - { - LastAccessTime = DateTime.UtcNow; - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using Server.Network; + +namespace Server.Accounting +{ + public class AccountAttackLimiter + { + public static bool Enabled; + + private static readonly List m_List = new List(); + + public static void Configure() + { + Enabled = ServerConfiguration.GetOrUpdateSetting("accountAttackLimiter.enable", true); + } + + public static void Initialize() + { + if (!Enabled) + return; + + PacketHandlers.RegisterThrottler(0x80, Throttle_Callback); + PacketHandlers.RegisterThrottler(0x91, Throttle_Callback); + PacketHandlers.RegisterThrottler(0xCF, Throttle_Callback); + } + + public static TimeSpan Throttle_Callback(NetState ns) + { + var accessLog = FindAccessLog(ns); + + if (accessLog == null) + return TimeSpan.Zero; + + var date = DateTime.UtcNow; + var access = accessLog.LastAccessTime + ComputeThrottle(accessLog.Counts); + return date >= access ? TimeSpan.Zero : date - access; + } + + public static InvalidAccountAccessLog FindAccessLog(NetState ns) + { + if (ns == null) + return null; + + var ipAddress = ns.Address; + + for (var i = 0; i < m_List.Count; ++i) + { + var accessLog = m_List[i]; + + if (accessLog.HasExpired) + m_List.RemoveAt(i--); + else if (accessLog.Address.Equals(ipAddress)) + return accessLog; + } + + return null; + } + + public static void RegisterInvalidAccess(NetState ns) + { + if (ns == null || !Enabled) + return; + + var accessLog = FindAccessLog(ns); + + if (accessLog == null) + m_List.Add(accessLog = new InvalidAccountAccessLog(ns.Address)); + + accessLog.Counts += 1; + accessLog.RefreshAccessTime(); + + if (accessLog.Counts >= 3) + try + { + using var op = new StreamWriter("throttle.log", true); + op.WriteLine( + "{0}\t{1}\t{2}", + DateTime.UtcNow, + ns, + accessLog.Counts + ); + } + catch + { + // ignored + } + } + + public static TimeSpan ComputeThrottle(int counts) + { + if (counts >= 15) + return TimeSpan.FromMinutes(5.0); + + if (counts >= 10) + return TimeSpan.FromMinutes(1.0); + + if (counts >= 5) + return TimeSpan.FromSeconds(20.0); + + if (counts >= 3) + return TimeSpan.FromSeconds(10.0); + + if (counts >= 1) + return TimeSpan.FromSeconds(2.0); + + return TimeSpan.Zero; + } + } + + public class InvalidAccountAccessLog + { + public InvalidAccountAccessLog(IPAddress address) + { + Address = address; + RefreshAccessTime(); + } + + public IPAddress Address { get; set; } + + public DateTime LastAccessTime { get; set; } + + public bool HasExpired => DateTime.UtcNow >= LastAccessTime + TimeSpan.FromHours(1.0); + + public int Counts { get; set; } + + public void RefreshAccessTime() + { + LastAccessTime = DateTime.UtcNow; + } + } +} diff --git a/Projects/UOContent/Accounting/AccountComment.cs b/Projects/UOContent/Accounting/AccountComment.cs index 1516ff868..ee2bdeb64 100644 --- a/Projects/UOContent/Accounting/AccountComment.cs +++ b/Projects/UOContent/Accounting/AccountComment.cs @@ -1,73 +1,73 @@ -using System; -using System.Xml; - -namespace Server.Accounting -{ - public class AccountComment - { - private string m_Content; - - /// - /// Constructs a new AccountComment instance. - /// - /// Initial AddedBy value. - /// Initial Content value. - public AccountComment(string addedBy, string content) - { - AddedBy = addedBy; - m_Content = content; - LastModified = DateTime.UtcNow; - } - - /// - /// Deserializes an AccountComment instance from an xml element. - /// - /// The XmlElement instance from which to deserialize. - public AccountComment(XmlElement node) - { - AddedBy = Utility.GetAttribute(node, "addedBy", "empty"); - LastModified = Utility.GetXMLDateTime(Utility.GetAttribute(node, "lastModified"), DateTime.UtcNow); - m_Content = Utility.GetText(node, ""); - } - - /// - /// A string representing who added this comment. - /// - public string AddedBy { get; } - - /// - /// Gets or sets the body of this comment. Setting this value will reset LastModified. - /// - public string Content - { - get => m_Content; - set - { - m_Content = value; - LastModified = DateTime.UtcNow; - } - } - - /// - /// The date and time when this account was last modified -or- the comment creation time, if never modified. - /// - public DateTime LastModified { get; private set; } - - /// - /// Serializes this AccountComment instance to an XmlTextWriter. - /// - /// The XmlTextWriter instance from which to serialize. - public void Save(XmlTextWriter xml) - { - xml.WriteStartElement("comment"); - - xml.WriteAttributeString("addedBy", AddedBy); - - xml.WriteAttributeString("lastModified", XmlConvert.ToString(LastModified, XmlDateTimeSerializationMode.Utc)); - - xml.WriteString(m_Content); - - xml.WriteEndElement(); - } - } -} \ No newline at end of file +using System; +using System.Xml; + +namespace Server.Accounting +{ + public class AccountComment + { + private string m_Content; + + /// + /// Constructs a new AccountComment instance. + /// + /// Initial AddedBy value. + /// Initial Content value. + public AccountComment(string addedBy, string content) + { + AddedBy = addedBy; + m_Content = content; + LastModified = DateTime.UtcNow; + } + + /// + /// Deserializes an AccountComment instance from an xml element. + /// + /// The XmlElement instance from which to deserialize. + public AccountComment(XmlElement node) + { + AddedBy = Utility.GetAttribute(node, "addedBy", "empty"); + LastModified = Utility.GetXMLDateTime(Utility.GetAttribute(node, "lastModified"), DateTime.UtcNow); + m_Content = Utility.GetText(node, ""); + } + + /// + /// A string representing who added this comment. + /// + public string AddedBy { get; } + + /// + /// Gets or sets the body of this comment. Setting this value will reset LastModified. + /// + public string Content + { + get => m_Content; + set + { + m_Content = value; + LastModified = DateTime.UtcNow; + } + } + + /// + /// The date and time when this account was last modified -or- the comment creation time, if never modified. + /// + public DateTime LastModified { get; private set; } + + /// + /// Serializes this AccountComment instance to an XmlTextWriter. + /// + /// The XmlTextWriter instance from which to serialize. + public void Save(XmlTextWriter xml) + { + xml.WriteStartElement("comment"); + + xml.WriteAttributeString("addedBy", AddedBy); + + xml.WriteAttributeString("lastModified", XmlConvert.ToString(LastModified, XmlDateTimeSerializationMode.Utc)); + + xml.WriteString(m_Content); + + xml.WriteEndElement(); + } + } +} diff --git a/Projects/UOContent/Accounting/AccountHandler.cs b/Projects/UOContent/Accounting/AccountHandler.cs index 8ed22dea3..2b7926e25 100644 --- a/Projects/UOContent/Accounting/AccountHandler.cs +++ b/Projects/UOContent/Accounting/AccountHandler.cs @@ -1,415 +1,430 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using Server.Accounting; -using Server.Engines.Help; -using Server.Network; -using Server.Regions; - -namespace Server.Misc -{ - public class AccountHandler - { - private static int MaxAccountsPerIP; - private static bool AutoAccountCreation; - private static bool RestrictDeletion = !TestCenter.Enabled; - private static TimeSpan DeleteDelay = TimeSpan.FromDays(7.0); - private static bool PasswordCommandEnabled; - - public static void Configure() - { - MaxAccountsPerIP = ServerConfiguration.GetOrUpdateSetting("accountHandler.maxAccountsPerIP", 1); - AutoAccountCreation = ServerConfiguration.GetOrUpdateSetting("accountHandler.enableAutoAccountCreation", true); - PasswordCommandEnabled = ServerConfiguration.GetOrUpdateSetting("accountHandler.enablePlayerPasswordCommand", false); - } - - private static readonly CityInfo[] StartingCities = - { - new CityInfo("New Haven", "New Haven Bank", 1150168, 3667, 2625, 0), - new CityInfo("Yew", "The Empath Abbey", 1075072, 633, 858, 0), - new CityInfo("Minoc", "The Barnacle", 1075073, 2476, 413, 15), - new CityInfo("Britain", "The Wayfarer's Inn", 1075074, 1602, 1591, 20), - new CityInfo("Moonglow", "The Scholars Inn", 1075075, 4408, 1168, 0), - new CityInfo("Trinsic", "The Traveler's Inn", 1075076, 1845, 2745, 0), - new CityInfo("Jhelom", "The Mercenary Inn", 1075078, 1374, 3826, 0), - new CityInfo("Skara Brae", "The Falconer's Inn", 1075079, 618, 2234, 0), - new CityInfo("Vesper", "The Ironwood Inn", 1075080, 2771, 976, 0) - }; - - /* Old Haven/Magincia Locations - new CityInfo( "Britain", "Sweet Dreams Inn", 1496, 1628, 10 ); - // .. - // Trinsic - new CityInfo( "Magincia", "The Great Horns Tavern", 3734, 2222, 20 ), - // Jhelom - // .. - new CityInfo( "Haven", "Buckler's Hideaway", 3667, 2625, 0 ) - - if (Core.AOS) - { - //CityInfo haven = new CityInfo( "Haven", "Uzeraan's Mansion", 3618, 2591, 0 ); - CityInfo haven = new CityInfo( "Haven", "Uzeraan's Mansion", 3503, 2574, 14 ); - StartingCities[StartingCities.Length - 1] = haven; - } - */ - - private static Dictionary m_IPTable; - - private static readonly char[] m_ForbiddenChars = - { - '<', '>', ':', '"', '/', '\\', '|', '?', '*' - }; - - public static AccessLevel LockdownLevel { get; set; } - - public static Dictionary IPTable - { - get - { - if (m_IPTable == null) - { - m_IPTable = new Dictionary(); - - foreach (Account a in Accounts.GetAccounts()) - if (a.LoginIPs.Length > 0) - { - IPAddress ip = a.LoginIPs[0]; - m_IPTable[ip] = (m_IPTable.TryGetValue(ip, out int value) ? value : 0) + 1; - } - } - - return m_IPTable; - } - } - - public static void Initialize() - { - EventSink.DeleteRequest += EventSink_DeleteRequest; - EventSink.AccountLogin += EventSink_AccountLogin; - EventSink.GameLogin += EventSink_GameLogin; - - if (PasswordCommandEnabled) - CommandSystem.Register("Password", AccessLevel.Player, Password_OnCommand); - } - - [Usage("Password ")] - [Description( - "Changes the password of the commanding players account. Requires the same C-class IP address as the account's creator.")] - public static void Password_OnCommand(CommandEventArgs e) - { - Mobile from = e.Mobile; - - if (!(from.Account is Account acct)) - return; - - IPAddress[] accessList = acct.LoginIPs; - - if (accessList.Length == 0) - return; - - NetState ns = from.NetState; - - if (ns == null) - return; - - if (e.Length == 0) - { - from.SendMessage("You must specify the new password."); - return; - } - - if (e.Length == 1) - { - from.SendMessage("To prevent potential typing mistakes, you must type the password twice. Use the format:"); - from.SendMessage("Password \"(newPassword)\" \"(repeated)\""); - return; - } - - string pass = e.GetString(0); - string pass2 = e.GetString(1); - - if (pass != pass2) - { - from.SendMessage("The passwords do not match."); - return; - } - - bool isSafe = true; - - for (int i = 0; isSafe && i < pass.Length; ++i) - isSafe = pass[i] >= 0x20 && pass[i] < 0x7F; - - if (!isSafe) - { - from.SendMessage("That is not a valid password."); - return; - } - - try - { - IPAddress ipAddress = ns.Address; - - if (Utility.IPMatchClassC(accessList[0], ipAddress)) - { - acct.SetPassword(pass); - from.SendMessage("The password to your account has changed."); - } - else - { - PageEntry entry = PageQueue.GetEntry(from); - - if (entry != null) - { - if (entry.Message.StartsWith("[Automated: Change Password]")) - from.SendMessage("You already have a password change request in the help system queue."); - else - from.SendMessage("Your IP address does not match that which created this account."); - } - else if (PageQueue.CheckAllowedToPage(from)) - { - from.SendMessage( - "Your IP address does not match that which created this account. A page has been entered into the help system on your behalf."); - - /* The next available Counselor/Game Master will respond as soon as possible. - * Please check your Journal for messages every few minutes. - */ - from.SendLocalizedMessage(501234, "", 0x35); - - PageQueue.Enqueue(new PageEntry(from, - $"[Automated: Change Password]
Desired password: {pass}
Current IP address: {ipAddress}
Account IP address: {accessList[0]}", - PageType.Account)); - } - } - } - catch - { - // ignored - } - } - - private static void EventSink_DeleteRequest(NetState state, int index) - { - if (!(state.Account is Account acct)) - { - state.Dispose(); - } - else if (index < 0 || index >= acct.Length) - { - state.Send(new DeleteResult(DeleteResultType.BadRequest)); - state.Send(new CharacterListUpdate(acct)); - } - else - { - Mobile m = acct[index]; - - if (m == null) - { - state.Send(new DeleteResult(DeleteResultType.CharNotExist)); - state.Send(new CharacterListUpdate(acct)); - } - else if (m.NetState != null) - { - state.Send(new DeleteResult(DeleteResultType.CharBeingPlayed)); - state.Send(new CharacterListUpdate(acct)); - } - else if (RestrictDeletion && DateTime.UtcNow < m.CreationTime + DeleteDelay) - { - state.Send(new DeleteResult(DeleteResultType.CharTooYoung)); - state.Send(new CharacterListUpdate(acct)); - } - else if (m.AccessLevel == AccessLevel.Player && - Region.Find(m.LogoutLocation, m.LogoutMap).IsPartOf()) // Don't need to check current location, if netstate is null, they're logged out - { - state.Send(new DeleteResult(DeleteResultType.BadRequest)); - state.Send(new CharacterListUpdate(acct)); - } - else - { - Console.WriteLine("Client: {0}: Deleting character {1} (0x{2:X})", state, index, m.Serial.Value); - - acct.Comments.Add(new AccountComment("System", $"Character #{index + 1} {m} deleted by {state}")); - - m.Delete(); - state.Send(new CharacterListUpdate(acct)); - } - } - } - - public static bool CanCreate(IPAddress ip) - { - if (!IPTable.ContainsKey(ip)) - return true; - - return IPTable[ip] < MaxAccountsPerIP; - } - - private static bool IsForbiddenChar(char c) - { - for (int i = 0; i < m_ForbiddenChars.Length; ++i) - if (c == m_ForbiddenChars[i]) - return true; - - return false; - } - - private static Account CreateAccount(NetState state, string un, string pw) - { - if (un.Length == 0 || pw.Length == 0) - return null; - - bool isSafe = !(un.StartsWith(" ") || un.EndsWith(" ") || un.EndsWith(".")); - - for (int i = 0; isSafe && i < un.Length; ++i) - isSafe = un[i] >= 0x20 && un[i] < 0x7F && !IsForbiddenChar(un[i]); - - for (int i = 0; isSafe && i < pw.Length; ++i) - isSafe = pw[i] >= 0x20 && pw[i] < 0x7F; - - if (!isSafe) - return null; - - if (!CanCreate(state.Address)) - { - Console.WriteLine("Login: {0}: Account '{1}' not created, ip already has {2} account{3}.", state, un, - MaxAccountsPerIP, MaxAccountsPerIP == 1 ? "" : "s"); - return null; - } - - Console.WriteLine("Login: {0}: Creating new account '{1}'", state, un); - - Account a = new Account(un, pw); - - return a; - } - - public static void EventSink_AccountLogin(AccountLoginEventArgs e) - { - if (!IPLimiter.SocketBlock && !IPLimiter.Verify(e.State.Address)) - { - e.Accepted = false; - e.RejectReason = ALRReason.InUse; - - Console.WriteLine("Login: {0}: Past IP limit threshold", e.State); - - using (StreamWriter op = new StreamWriter("ipLimits.log", true)) - { - op.WriteLine("{0}\tPast IP limit threshold\t{1}", e.State, DateTime.UtcNow); - } - - return; - } - - string un = e.Username; - string pw = e.Password; - - e.Accepted = false; - - if (!(Accounts.GetAccount(un) is Account acct)) - { - // To prevent someone from making an account of just '' or a bunch of meaningless spaces - if (AutoAccountCreation && un.Trim().Length > 0) - { - e.State.Account = acct = CreateAccount(e.State, un, pw); - e.Accepted = acct?.CheckAccess(e.State) ?? false; - - if (!e.Accepted) - e.RejectReason = ALRReason.BadComm; - } - else - { - Console.WriteLine("Login: {0}: Invalid username '{1}'", e.State, un); - e.RejectReason = ALRReason.Invalid; - } - } - else if (!acct.HasAccess(e.State)) - { - Console.WriteLine("Login: {0}: Access denied for '{1}'", e.State, un); - e.RejectReason = LockdownLevel > AccessLevel.Player ? ALRReason.BadComm : ALRReason.BadPass; - } - else if (!acct.CheckPassword(pw)) - { - Console.WriteLine("Login: {0}: Invalid password for '{1}'", e.State, un); - e.RejectReason = ALRReason.BadPass; - } - else if (acct.Banned) - { - Console.WriteLine("Login: {0}: Banned account '{1}'", e.State, un); - e.RejectReason = ALRReason.Blocked; - } - else - { - Console.WriteLine("Login: {0}: Valid credentials for '{1}'", e.State, un); - e.State.Account = acct; - e.Accepted = true; - - acct.LogAccess(e.State); - } - - if (!e.Accepted) - AccountAttackLimiter.RegisterInvalidAccess(e.State); - } - - public static void EventSink_GameLogin(GameLoginEventArgs e) - { - if (!IPLimiter.SocketBlock && !IPLimiter.Verify(e.State.Address)) - { - e.Accepted = false; - - Console.WriteLine("Login: {0}: Past IP limit threshold", e.State); - - using (StreamWriter op = new StreamWriter("ipLimits.log", true)) - { - op.WriteLine("{0}\tPast IP limit threshold\t{1}", e.State, DateTime.UtcNow); - } - - return; - } - - string un = e.Username; - string pw = e.Password; - - if (!(Accounts.GetAccount(un) is Account acct)) - { - e.Accepted = false; - } - else if (!acct.HasAccess(e.State)) - { - Console.WriteLine("Login: {0}: Access denied for '{1}'", e.State, un); - e.Accepted = false; - } - else if (!acct.CheckPassword(pw)) - { - Console.WriteLine("Login: {0}: Invalid password for '{1}'", e.State, un); - e.Accepted = false; - } - else if (acct.Banned) - { - Console.WriteLine("Login: {0}: Banned account '{1}'", e.State, un); - e.Accepted = false; - } - else - { - acct.LogAccess(e.State); - - Console.WriteLine("Login: {0}: Account '{1}' at character list", e.State, un); - e.State.Account = acct; - e.Accepted = true; - e.CityInfo = StartingCities; - } - - if (!e.Accepted) - AccountAttackLimiter.RegisterInvalidAccess(e.State); - } - - public static bool CheckAccount(Mobile mobCheck, Mobile accCheck) - { - if (accCheck?.Account is Account a) - for (int i = 0; i < a.Length; ++i) - if (a[i] == mobCheck) - return true; - - return false; - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using Server.Accounting; +using Server.Engines.Help; +using Server.Network; +using Server.Regions; + +namespace Server.Misc +{ + public class AccountHandler + { + private static int MaxAccountsPerIP; + private static bool AutoAccountCreation; + private static readonly bool RestrictDeletion = !TestCenter.Enabled; + private static readonly TimeSpan DeleteDelay = TimeSpan.FromDays(7.0); + private static bool PasswordCommandEnabled; + + private static readonly CityInfo[] StartingCities = + { + new CityInfo("New Haven", "New Haven Bank", 1150168, 3667, 2625, 0), + new CityInfo("Yew", "The Empath Abbey", 1075072, 633, 858, 0), + new CityInfo("Minoc", "The Barnacle", 1075073, 2476, 413, 15), + new CityInfo("Britain", "The Wayfarer's Inn", 1075074, 1602, 1591, 20), + new CityInfo("Moonglow", "The Scholars Inn", 1075075, 4408, 1168, 0), + new CityInfo("Trinsic", "The Traveler's Inn", 1075076, 1845, 2745, 0), + new CityInfo("Jhelom", "The Mercenary Inn", 1075078, 1374, 3826, 0), + new CityInfo("Skara Brae", "The Falconer's Inn", 1075079, 618, 2234, 0), + new CityInfo("Vesper", "The Ironwood Inn", 1075080, 2771, 976, 0) + }; + + /* Old Haven/Magincia Locations + new CityInfo( "Britain", "Sweet Dreams Inn", 1496, 1628, 10 ); + // .. + // Trinsic + new CityInfo( "Magincia", "The Great Horns Tavern", 3734, 2222, 20 ), + // Jhelom + // .. + new CityInfo( "Haven", "Buckler's Hideaway", 3667, 2625, 0 ) + + if (Core.AOS) + { + //CityInfo haven = new CityInfo( "Haven", "Uzeraan's Mansion", 3618, 2591, 0 ); + CityInfo haven = new CityInfo( "Haven", "Uzeraan's Mansion", 3503, 2574, 14 ); + StartingCities[StartingCities.Length - 1] = haven; + } + */ + + private static Dictionary m_IPTable; + + private static readonly char[] m_ForbiddenChars = + { + '<', '>', ':', '"', '/', '\\', '|', '?', '*' + }; + + public static AccessLevel LockdownLevel { get; set; } + + public static Dictionary IPTable + { + get + { + if (m_IPTable == null) + { + m_IPTable = new Dictionary(); + + foreach (Account a in Accounts.GetAccounts()) + if (a.LoginIPs.Length > 0) + { + var ip = a.LoginIPs[0]; + m_IPTable[ip] = (m_IPTable.TryGetValue(ip, out var value) ? value : 0) + 1; + } + } + + return m_IPTable; + } + } + + public static void Configure() + { + MaxAccountsPerIP = ServerConfiguration.GetOrUpdateSetting("accountHandler.maxAccountsPerIP", 1); + AutoAccountCreation = ServerConfiguration.GetOrUpdateSetting("accountHandler.enableAutoAccountCreation", true); + PasswordCommandEnabled = ServerConfiguration.GetOrUpdateSetting( + "accountHandler.enablePlayerPasswordCommand", + false + ); + } + + public static void Initialize() + { + EventSink.DeleteRequest += EventSink_DeleteRequest; + EventSink.AccountLogin += EventSink_AccountLogin; + EventSink.GameLogin += EventSink_GameLogin; + + if (PasswordCommandEnabled) + CommandSystem.Register("Password", AccessLevel.Player, Password_OnCommand); + } + + [Usage("Password ")] + [Description( + "Changes the password of the commanding players account. Requires the same C-class IP address as the account's creator." + )] + public static void Password_OnCommand(CommandEventArgs e) + { + var from = e.Mobile; + + if (!(from.Account is Account acct)) + return; + + var accessList = acct.LoginIPs; + + if (accessList.Length == 0) + return; + + var ns = from.NetState; + + if (ns == null) + return; + + if (e.Length == 0) + { + from.SendMessage("You must specify the new password."); + return; + } + + if (e.Length == 1) + { + from.SendMessage("To prevent potential typing mistakes, you must type the password twice. Use the format:"); + from.SendMessage("Password \"(newPassword)\" \"(repeated)\""); + return; + } + + var pass = e.GetString(0); + var pass2 = e.GetString(1); + + if (pass != pass2) + { + from.SendMessage("The passwords do not match."); + return; + } + + var isSafe = true; + + for (var i = 0; isSafe && i < pass.Length; ++i) + isSafe = pass[i] >= 0x20 && pass[i] < 0x7F; + + if (!isSafe) + { + from.SendMessage("That is not a valid password."); + return; + } + + try + { + var ipAddress = ns.Address; + + if (Utility.IPMatchClassC(accessList[0], ipAddress)) + { + acct.SetPassword(pass); + from.SendMessage("The password to your account has changed."); + } + else + { + var entry = PageQueue.GetEntry(from); + + if (entry != null) + { + if (entry.Message.StartsWith("[Automated: Change Password]")) + from.SendMessage("You already have a password change request in the help system queue."); + else + from.SendMessage("Your IP address does not match that which created this account."); + } + else if (PageQueue.CheckAllowedToPage(from)) + { + from.SendMessage( + "Your IP address does not match that which created this account. A page has been entered into the help system on your behalf." + ); + + /* The next available Counselor/Game Master will respond as soon as possible. + * Please check your Journal for messages every few minutes. + */ + from.SendLocalizedMessage(501234, "", 0x35); + + PageQueue.Enqueue( + new PageEntry( + from, + $"[Automated: Change Password]
Desired password: {pass}
Current IP address: {ipAddress}
Account IP address: {accessList[0]}", + PageType.Account + ) + ); + } + } + } + catch + { + // ignored + } + } + + private static void EventSink_DeleteRequest(NetState state, int index) + { + if (!(state.Account is Account acct)) + { + state.Dispose(); + } + else if (index < 0 || index >= acct.Length) + { + state.Send(new DeleteResult(DeleteResultType.BadRequest)); + state.Send(new CharacterListUpdate(acct)); + } + else + { + var m = acct[index]; + + if (m == null) + { + state.Send(new DeleteResult(DeleteResultType.CharNotExist)); + state.Send(new CharacterListUpdate(acct)); + } + else if (m.NetState != null) + { + state.Send(new DeleteResult(DeleteResultType.CharBeingPlayed)); + state.Send(new CharacterListUpdate(acct)); + } + else if (RestrictDeletion && DateTime.UtcNow < m.CreationTime + DeleteDelay) + { + state.Send(new DeleteResult(DeleteResultType.CharTooYoung)); + state.Send(new CharacterListUpdate(acct)); + } + else if (m.AccessLevel == AccessLevel.Player && + Region.Find(m.LogoutLocation, m.LogoutMap).IsPartOf() + ) // Don't need to check current location, if netstate is null, they're logged out + { + state.Send(new DeleteResult(DeleteResultType.BadRequest)); + state.Send(new CharacterListUpdate(acct)); + } + else + { + Console.WriteLine("Client: {0}: Deleting character {1} (0x{2:X})", state, index, m.Serial.Value); + + acct.Comments.Add(new AccountComment("System", $"Character #{index + 1} {m} deleted by {state}")); + + m.Delete(); + state.Send(new CharacterListUpdate(acct)); + } + } + } + + public static bool CanCreate(IPAddress ip) + { + if (!IPTable.ContainsKey(ip)) + return true; + + return IPTable[ip] < MaxAccountsPerIP; + } + + private static bool IsForbiddenChar(char c) + { + for (var i = 0; i < m_ForbiddenChars.Length; ++i) + if (c == m_ForbiddenChars[i]) + return true; + + return false; + } + + private static Account CreateAccount(NetState state, string un, string pw) + { + if (un.Length == 0 || pw.Length == 0) + return null; + + var isSafe = !(un.StartsWith(" ") || un.EndsWith(" ") || un.EndsWith(".")); + + for (var i = 0; isSafe && i < un.Length; ++i) + isSafe = un[i] >= 0x20 && un[i] < 0x7F && !IsForbiddenChar(un[i]); + + for (var i = 0; isSafe && i < pw.Length; ++i) + isSafe = pw[i] >= 0x20 && pw[i] < 0x7F; + + if (!isSafe) + return null; + + if (!CanCreate(state.Address)) + { + Console.WriteLine( + "Login: {0}: Account '{1}' not created, ip already has {2} account{3}.", + state, + un, + MaxAccountsPerIP, + MaxAccountsPerIP == 1 ? "" : "s" + ); + return null; + } + + Console.WriteLine("Login: {0}: Creating new account '{1}'", state, un); + + var a = new Account(un, pw); + + return a; + } + + public static void EventSink_AccountLogin(AccountLoginEventArgs e) + { + if (!IPLimiter.SocketBlock && !IPLimiter.Verify(e.State.Address)) + { + e.Accepted = false; + e.RejectReason = ALRReason.InUse; + + Console.WriteLine("Login: {0}: Past IP limit threshold", e.State); + + using (var op = new StreamWriter("ipLimits.log", true)) + { + op.WriteLine("{0}\tPast IP limit threshold\t{1}", e.State, DateTime.UtcNow); + } + + return; + } + + var un = e.Username; + var pw = e.Password; + + e.Accepted = false; + + if (!(Accounts.GetAccount(un) is Account acct)) + { + // To prevent someone from making an account of just '' or a bunch of meaningless spaces + if (AutoAccountCreation && un.Trim().Length > 0) + { + e.State.Account = acct = CreateAccount(e.State, un, pw); + e.Accepted = acct?.CheckAccess(e.State) ?? false; + + if (!e.Accepted) + e.RejectReason = ALRReason.BadComm; + } + else + { + Console.WriteLine("Login: {0}: Invalid username '{1}'", e.State, un); + e.RejectReason = ALRReason.Invalid; + } + } + else if (!acct.HasAccess(e.State)) + { + Console.WriteLine("Login: {0}: Access denied for '{1}'", e.State, un); + e.RejectReason = LockdownLevel > AccessLevel.Player ? ALRReason.BadComm : ALRReason.BadPass; + } + else if (!acct.CheckPassword(pw)) + { + Console.WriteLine("Login: {0}: Invalid password for '{1}'", e.State, un); + e.RejectReason = ALRReason.BadPass; + } + else if (acct.Banned) + { + Console.WriteLine("Login: {0}: Banned account '{1}'", e.State, un); + e.RejectReason = ALRReason.Blocked; + } + else + { + Console.WriteLine("Login: {0}: Valid credentials for '{1}'", e.State, un); + e.State.Account = acct; + e.Accepted = true; + + acct.LogAccess(e.State); + } + + if (!e.Accepted) + AccountAttackLimiter.RegisterInvalidAccess(e.State); + } + + public static void EventSink_GameLogin(GameLoginEventArgs e) + { + if (!IPLimiter.SocketBlock && !IPLimiter.Verify(e.State.Address)) + { + e.Accepted = false; + + Console.WriteLine("Login: {0}: Past IP limit threshold", e.State); + + using (var op = new StreamWriter("ipLimits.log", true)) + { + op.WriteLine("{0}\tPast IP limit threshold\t{1}", e.State, DateTime.UtcNow); + } + + return; + } + + var un = e.Username; + var pw = e.Password; + + if (!(Accounts.GetAccount(un) is Account acct)) + { + e.Accepted = false; + } + else if (!acct.HasAccess(e.State)) + { + Console.WriteLine("Login: {0}: Access denied for '{1}'", e.State, un); + e.Accepted = false; + } + else if (!acct.CheckPassword(pw)) + { + Console.WriteLine("Login: {0}: Invalid password for '{1}'", e.State, un); + e.Accepted = false; + } + else if (acct.Banned) + { + Console.WriteLine("Login: {0}: Banned account '{1}'", e.State, un); + e.Accepted = false; + } + else + { + acct.LogAccess(e.State); + + Console.WriteLine("Login: {0}: Account '{1}' at character list", e.State, un); + e.State.Account = acct; + e.Accepted = true; + e.CityInfo = StartingCities; + } + + if (!e.Accepted) + AccountAttackLimiter.RegisterInvalidAccess(e.State); + } + + public static bool CheckAccount(Mobile mobCheck, Mobile accCheck) + { + if (accCheck?.Account is Account a) + for (var i = 0; i < a.Length; ++i) + if (a[i] == mobCheck) + return true; + + return false; + } + } +} diff --git a/Projects/UOContent/Accounting/AccountTag.cs b/Projects/UOContent/Accounting/AccountTag.cs index 6689eb1da..ae6b85673 100644 --- a/Projects/UOContent/Accounting/AccountTag.cs +++ b/Projects/UOContent/Accounting/AccountTag.cs @@ -1,50 +1,50 @@ -using System.Xml; - -namespace Server.Accounting -{ - public class AccountTag - { - /// - /// Constructs a new AccountTag instance with a specific name and value. - /// - /// Initial name. - /// Initial value. - public AccountTag(string name, string value) - { - Name = name; - Value = value; - } - - /// - /// Deserializes an AccountTag instance from an xml element. - /// - /// The XmlElement instance from which to deserialize. - public AccountTag(XmlElement node) - { - Name = Utility.GetAttribute(node, "name", "empty"); - Value = Utility.GetText(node, ""); - } - - /// - /// Gets or sets the name of this tag. - /// - public string Name { get; set; } - - /// - /// Gets or sets the value of this tag. - /// - public string Value { get; set; } - - /// - /// Serializes this AccountTag instance to an XmlTextWriter. - /// - /// The XmlTextWriter instance from which to serialize. - public void Save(XmlTextWriter xml) - { - xml.WriteStartElement("tag"); - xml.WriteAttributeString("name", Name); - xml.WriteString(Value); - xml.WriteEndElement(); - } - } -} \ No newline at end of file +using System.Xml; + +namespace Server.Accounting +{ + public class AccountTag + { + /// + /// Constructs a new AccountTag instance with a specific name and value. + /// + /// Initial name. + /// Initial value. + public AccountTag(string name, string value) + { + Name = name; + Value = value; + } + + /// + /// Deserializes an AccountTag instance from an xml element. + /// + /// The XmlElement instance from which to deserialize. + public AccountTag(XmlElement node) + { + Name = Utility.GetAttribute(node, "name", "empty"); + Value = Utility.GetText(node, ""); + } + + /// + /// Gets or sets the name of this tag. + /// + public string Name { get; set; } + + /// + /// Gets or sets the value of this tag. + /// + public string Value { get; set; } + + /// + /// Serializes this AccountTag instance to an XmlTextWriter. + /// + /// The XmlTextWriter instance from which to serialize. + public void Save(XmlTextWriter xml) + { + xml.WriteStartElement("tag"); + xml.WriteAttributeString("name", Name); + xml.WriteString(Value); + xml.WriteEndElement(); + } + } +} diff --git a/Projects/UOContent/Accounting/Accounts.cs b/Projects/UOContent/Accounting/Accounts.cs index bae956a27..1c6a3aa21 100644 --- a/Projects/UOContent/Accounting/Accounts.cs +++ b/Projects/UOContent/Accounting/Accounts.cs @@ -1,92 +1,92 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Xml; - -namespace Server.Accounting -{ - public class Accounts - { - private static Dictionary m_Accounts = new Dictionary(); - - static Accounts() - { - } - - public static int Count => m_Accounts.Count; - - public static void Configure() - { - EventSink.WorldLoad += Load; - EventSink.WorldSave += Save; - } - - public static IEnumerable GetAccounts() => m_Accounts.Values; - - public static IAccount GetAccount(string username) - { - m_Accounts.TryGetValue(username, out IAccount a); - - return a; - } - - public static void Add(IAccount a) - { - m_Accounts[a.Username] = a; - } - - public static void Remove(string username) - { - m_Accounts.Remove(username); - } - - public static void Load() - { - m_Accounts = new Dictionary(32, StringComparer.OrdinalIgnoreCase); - - string filePath = Path.Combine("Saves/Accounts", "accounts.xml"); - - if (!File.Exists(filePath)) - return; - - XmlDocument doc = new XmlDocument(); - doc.Load(filePath); - - XmlElement root = doc["accounts"]; - - foreach (XmlElement account in root.GetElementsByTagName("account")) - try - { - new Account(account); - } - catch - { - Console.WriteLine("Warning: Account instance load failed"); - } - } - - public static void Save(bool message) - { - if (!Directory.Exists("Saves/Accounts")) - Directory.CreateDirectory("Saves/Accounts"); - - string filePath = Path.Combine("Saves/Accounts", "accounts.xml"); - - using StreamWriter op = new StreamWriter(filePath); - XmlTextWriter xml = new XmlTextWriter(op) { Formatting = Formatting.Indented, IndentChar = '\t', Indentation = 1 }; - - xml.WriteStartDocument(true); - - xml.WriteStartElement("accounts"); - - xml.WriteAttributeString("count", m_Accounts.Count.ToString()); - - foreach (Account a in GetAccounts()) - a.Save(xml); - - xml.WriteEndElement(); - - xml.Close(); - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; + +namespace Server.Accounting +{ + public class Accounts + { + private static Dictionary m_Accounts = new Dictionary(); + + static Accounts() + { + } + + public static int Count => m_Accounts.Count; + + public static void Configure() + { + EventSink.WorldLoad += Load; + EventSink.WorldSave += Save; + } + + public static IEnumerable GetAccounts() => m_Accounts.Values; + + public static IAccount GetAccount(string username) + { + m_Accounts.TryGetValue(username, out var a); + + return a; + } + + public static void Add(IAccount a) + { + m_Accounts[a.Username] = a; + } + + public static void Remove(string username) + { + m_Accounts.Remove(username); + } + + public static void Load() + { + m_Accounts = new Dictionary(32, StringComparer.OrdinalIgnoreCase); + + var filePath = Path.Combine("Saves/Accounts", "accounts.xml"); + + if (!File.Exists(filePath)) + return; + + var doc = new XmlDocument(); + doc.Load(filePath); + + var root = doc["accounts"]; + + foreach (XmlElement account in root.GetElementsByTagName("account")) + try + { + new Account(account); + } + catch + { + Console.WriteLine("Warning: Account instance load failed"); + } + } + + public static void Save(bool message) + { + if (!Directory.Exists("Saves/Accounts")) + Directory.CreateDirectory("Saves/Accounts"); + + var filePath = Path.Combine("Saves/Accounts", "accounts.xml"); + + using var op = new StreamWriter(filePath); + var xml = new XmlTextWriter(op) { Formatting = Formatting.Indented, IndentChar = '\t', Indentation = 1 }; + + xml.WriteStartDocument(true); + + xml.WriteStartElement("accounts"); + + xml.WriteAttributeString("count", m_Accounts.Count.ToString()); + + foreach (Account a in GetAccounts()) + a.Save(xml); + + xml.WriteEndElement(); + + xml.Close(); + } + } +} diff --git a/Projects/UOContent/Accounting/Firewall.cs b/Projects/UOContent/Accounting/Firewall.cs index b05aebfb9..a40aefc38 100644 --- a/Projects/UOContent/Accounting/Firewall.cs +++ b/Projects/UOContent/Accounting/Firewall.cs @@ -1,270 +1,270 @@ -using System.Collections.Generic; -using System.IO; -using System.Net; - -namespace Server -{ - public class Firewall - { - static Firewall() - { - List = new List(); - - string path = "firewall.cfg"; - - if (File.Exists(path)) - { - using StreamReader ip = new StreamReader(path); - string line; - - while ((line = ip.ReadLine()) != null) - { - line = line.Trim(); - - if (line.Length == 0) - continue; - - List.Add(ToFirewallEntry(line)); - - /* - object toAdd; - - IPAddress addr; - if (IPAddress.TryParse( line, out addr )) - toAdd = addr; - else - toAdd = line; - - m_Blocked.Add( toAdd.ToString() ); - * */ - } - } - } - - public static List List { get; } - - public static IFirewallEntry ToFirewallEntry(object entry) - { - if (entry is IFirewallEntry firewallEntry) - return firewallEntry; - if (entry is IPAddress address) - return new IPFirewallEntry(address); - if (entry is string s) - return ToFirewallEntry(s); - - return null; - } - - public static IFirewallEntry ToFirewallEntry(string entry) - { - if (IPAddress.TryParse(entry, out IPAddress addr)) - return new IPFirewallEntry(addr); - - // Try CIDR parse - string[] str = entry.Split('/'); - - if (str.Length == 2) - if (IPAddress.TryParse(str[0], out IPAddress cidrPrefix)) - if (int.TryParse(str[1], out int cidrLength)) - return new CIDRFirewallEntry(cidrPrefix, cidrLength); - - return new WildcardIPFirewallEntry(entry); - } - - public static void RemoveAt(int index) - { - List.RemoveAt(index); - Save(); - } - - public static void Remove(object obj) - { - IFirewallEntry entry = ToFirewallEntry(obj); - - if (entry != null) - { - List.Remove(entry); - Save(); - } - } - - public static void Add(object obj) - { - if (obj is IPAddress address) - Add(address); - else if (obj is string s) - Add(s); - else if (obj is IFirewallEntry entry) - Add(entry); - } - - public static void Add(IFirewallEntry entry) - { - if (!List.Contains(entry)) - List.Add(entry); - - Save(); - } - - public static void Add(string pattern) - { - IFirewallEntry entry = ToFirewallEntry(pattern); - - if (!List.Contains(entry)) - List.Add(entry); - - Save(); - } - - public static void Add(IPAddress ip) - { - IFirewallEntry entry = new IPFirewallEntry(ip); - - if (!List.Contains(entry)) - List.Add(entry); - - Save(); - } - - public static void Save() - { - string path = "firewall.cfg"; - - using StreamWriter op = new StreamWriter(path); - for (int i = 0; i < List.Count; ++i) - op.WriteLine(List[i]); - } - - public static bool IsBlocked(IPAddress ip) - { - for (int i = 0; i < List.Count; i++) - if (List[i].IsBlocked(ip)) - return true; - - return false; - /* - bool contains = false; - - for ( int i = 0; !contains && i < m_Blocked.Count; ++i ) - { - if (m_Blocked[i] is IPAddress) - contains = ip.Equals( m_Blocked[i] ); - else if (m_Blocked[i] is String) - { - string s = (string)m_Blocked[i]; - - contains = Utility.IPMatchCIDR( s, ip ); - - if (!contains) - contains = Utility.IPMatch( s, ip ); - } - } - - return contains; - * */ - } - - public interface IFirewallEntry - { - bool IsBlocked(IPAddress address); - } - - public class IPFirewallEntry : IFirewallEntry - { - private readonly IPAddress m_Address; - - public IPFirewallEntry(IPAddress address) => m_Address = address; - - public bool IsBlocked(IPAddress address) => m_Address.Equals(address); - - public override string ToString() => m_Address.ToString(); - - public override bool Equals(object obj) - { - if (obj is IPAddress) - return obj.Equals(m_Address); - if (obj is string s) - { - if (IPAddress.TryParse(s, out IPAddress otherAddress)) - return otherAddress.Equals(m_Address); - } - else if (obj is IPFirewallEntry entry) - { - return m_Address.Equals(entry.m_Address); - } - - return false; - } - - public override int GetHashCode() => m_Address.GetHashCode(); - } - - public class CIDRFirewallEntry : IFirewallEntry - { - private readonly int m_CIDRLength; - private readonly IPAddress m_CIDRPrefix; - - public CIDRFirewallEntry(IPAddress cidrPrefix, int cidrLength) - { - m_CIDRPrefix = cidrPrefix; - m_CIDRLength = cidrLength; - } - - public bool IsBlocked(IPAddress address) => Utility.IPMatchCIDR(m_CIDRPrefix, address, m_CIDRLength); - - public override string ToString() => $"{m_CIDRPrefix}/{m_CIDRLength}"; - - public override bool Equals(object obj) - { - if (obj is string entry) - { - string[] str = entry.Split('/'); - - if (str.Length == 2) - if (IPAddress.TryParse(str[0], out IPAddress cidrPrefix)) - if (int.TryParse(str[1], out int cidrLength)) - return m_CIDRPrefix.Equals(cidrPrefix) && m_CIDRLength.Equals(cidrLength); - } - else if (obj is CIDRFirewallEntry cidrEntry) - { - return m_CIDRPrefix.Equals(cidrEntry.m_CIDRPrefix) && m_CIDRLength.Equals(cidrEntry.m_CIDRLength); - } - - return false; - } - - public override int GetHashCode() => m_CIDRPrefix.GetHashCode() ^ m_CIDRLength.GetHashCode(); - } - - public class WildcardIPFirewallEntry : IFirewallEntry - { - private readonly string m_Entry; - - private bool m_Valid; - - public WildcardIPFirewallEntry(string entry) => m_Entry = entry; - - public bool IsBlocked(IPAddress address) - { - if (!m_Valid) - return false; // Why process if it's invalid? it'll return false anyway after processing it. - - bool matched = Utility.IPMatch(m_Entry, address, out bool valid); - m_Valid = valid; - return matched; - } - - public override string ToString() => m_Entry; - - public override bool Equals(object obj) - { - if (obj is string) - return obj.Equals(m_Entry); - - return obj is WildcardIPFirewallEntry entry && m_Entry.Equals(entry.m_Entry); - } - - public override int GetHashCode() => m_Entry.GetHashCode(); - } - } -} +using System.Collections.Generic; +using System.IO; +using System.Net; + +namespace Server +{ + public class Firewall + { + static Firewall() + { + List = new List(); + + var path = "firewall.cfg"; + + if (File.Exists(path)) + { + using var ip = new StreamReader(path); + string line; + + while ((line = ip.ReadLine()) != null) + { + line = line.Trim(); + + if (line.Length == 0) + continue; + + List.Add(ToFirewallEntry(line)); + + /* + object toAdd; + + IPAddress addr; + if (IPAddress.TryParse( line, out addr )) + toAdd = addr; + else + toAdd = line; + + m_Blocked.Add( toAdd.ToString() ); + * */ + } + } + } + + public static List List { get; } + + public static IFirewallEntry ToFirewallEntry(object entry) + { + if (entry is IFirewallEntry firewallEntry) + return firewallEntry; + if (entry is IPAddress address) + return new IPFirewallEntry(address); + if (entry is string s) + return ToFirewallEntry(s); + + return null; + } + + public static IFirewallEntry ToFirewallEntry(string entry) + { + if (IPAddress.TryParse(entry, out var addr)) + return new IPFirewallEntry(addr); + + // Try CIDR parse + var str = entry.Split('/'); + + if (str.Length == 2) + if (IPAddress.TryParse(str[0], out var cidrPrefix)) + if (int.TryParse(str[1], out var cidrLength)) + return new CIDRFirewallEntry(cidrPrefix, cidrLength); + + return new WildcardIPFirewallEntry(entry); + } + + public static void RemoveAt(int index) + { + List.RemoveAt(index); + Save(); + } + + public static void Remove(object obj) + { + var entry = ToFirewallEntry(obj); + + if (entry != null) + { + List.Remove(entry); + Save(); + } + } + + public static void Add(object obj) + { + if (obj is IPAddress address) + Add(address); + else if (obj is string s) + Add(s); + else if (obj is IFirewallEntry entry) + Add(entry); + } + + public static void Add(IFirewallEntry entry) + { + if (!List.Contains(entry)) + List.Add(entry); + + Save(); + } + + public static void Add(string pattern) + { + var entry = ToFirewallEntry(pattern); + + if (!List.Contains(entry)) + List.Add(entry); + + Save(); + } + + public static void Add(IPAddress ip) + { + IFirewallEntry entry = new IPFirewallEntry(ip); + + if (!List.Contains(entry)) + List.Add(entry); + + Save(); + } + + public static void Save() + { + var path = "firewall.cfg"; + + using var op = new StreamWriter(path); + for (var i = 0; i < List.Count; ++i) + op.WriteLine(List[i]); + } + + public static bool IsBlocked(IPAddress ip) + { + for (var i = 0; i < List.Count; i++) + if (List[i].IsBlocked(ip)) + return true; + + return false; + /* + bool contains = false; + + for ( int i = 0; !contains && i < m_Blocked.Count; ++i ) + { + if (m_Blocked[i] is IPAddress) + contains = ip.Equals( m_Blocked[i] ); + else if (m_Blocked[i] is String) + { + string s = (string)m_Blocked[i]; + + contains = Utility.IPMatchCIDR( s, ip ); + + if (!contains) + contains = Utility.IPMatch( s, ip ); + } + } + + return contains; + * */ + } + + public interface IFirewallEntry + { + bool IsBlocked(IPAddress address); + } + + public class IPFirewallEntry : IFirewallEntry + { + private readonly IPAddress m_Address; + + public IPFirewallEntry(IPAddress address) => m_Address = address; + + public bool IsBlocked(IPAddress address) => m_Address.Equals(address); + + public override string ToString() => m_Address.ToString(); + + public override bool Equals(object obj) + { + if (obj is IPAddress) + return obj.Equals(m_Address); + if (obj is string s) + { + if (IPAddress.TryParse(s, out var otherAddress)) + return otherAddress.Equals(m_Address); + } + else if (obj is IPFirewallEntry entry) + { + return m_Address.Equals(entry.m_Address); + } + + return false; + } + + public override int GetHashCode() => m_Address.GetHashCode(); + } + + public class CIDRFirewallEntry : IFirewallEntry + { + private readonly int m_CIDRLength; + private readonly IPAddress m_CIDRPrefix; + + public CIDRFirewallEntry(IPAddress cidrPrefix, int cidrLength) + { + m_CIDRPrefix = cidrPrefix; + m_CIDRLength = cidrLength; + } + + public bool IsBlocked(IPAddress address) => Utility.IPMatchCIDR(m_CIDRPrefix, address, m_CIDRLength); + + public override string ToString() => $"{m_CIDRPrefix}/{m_CIDRLength}"; + + public override bool Equals(object obj) + { + if (obj is string entry) + { + var str = entry.Split('/'); + + if (str.Length == 2) + if (IPAddress.TryParse(str[0], out var cidrPrefix)) + if (int.TryParse(str[1], out var cidrLength)) + return m_CIDRPrefix.Equals(cidrPrefix) && m_CIDRLength.Equals(cidrLength); + } + else if (obj is CIDRFirewallEntry cidrEntry) + { + return m_CIDRPrefix.Equals(cidrEntry.m_CIDRPrefix) && m_CIDRLength.Equals(cidrEntry.m_CIDRLength); + } + + return false; + } + + public override int GetHashCode() => m_CIDRPrefix.GetHashCode() ^ m_CIDRLength.GetHashCode(); + } + + public class WildcardIPFirewallEntry : IFirewallEntry + { + private readonly string m_Entry; + + private bool m_Valid; + + public WildcardIPFirewallEntry(string entry) => m_Entry = entry; + + public bool IsBlocked(IPAddress address) + { + if (!m_Valid) + return false; // Why process if it's invalid? it'll return false anyway after processing it. + + var matched = Utility.IPMatch(m_Entry, address, out var valid); + m_Valid = valid; + return matched; + } + + public override string ToString() => m_Entry; + + public override bool Equals(object obj) + { + if (obj is string) + return obj.Equals(m_Entry); + + return obj is WildcardIPFirewallEntry entry && m_Entry.Equals(entry.m_Entry); + } + + public override int GetHashCode() => m_Entry.GetHashCode(); + } + } +} diff --git a/Projects/UOContent/Accounting/IPLimiter.cs b/Projects/UOContent/Accounting/IPLimiter.cs index eb148583b..60a8e797e 100644 --- a/Projects/UOContent/Accounting/IPLimiter.cs +++ b/Projects/UOContent/Accounting/IPLimiter.cs @@ -1,53 +1,52 @@ -using System.Collections.Generic; -using System.Linq; -using System.Net; -using Server.Network; - -namespace Server.Misc -{ - public class IPLimiter - { - public static bool Enabled { get; private set; } - public static bool SocketBlock { get; private set; } - public static int MaxAddresses { get; private set; } - - public static void Configure() - { - Enabled = ServerConfiguration.GetOrUpdateSetting("ipLimiter.enable", true); - SocketBlock = ServerConfiguration.GetOrUpdateSetting("ipLimiter.blockAtConnection", true); - MaxAddresses = ServerConfiguration.GetOrUpdateSetting("ipLimiter.maxConnectionsPerIP", 10); - } - - public static IPAddress[] Exemptions = - { - // IPAddress.Parse( "127.0.0.1" ), - }; - - public static bool IsExempt(IPAddress ip) => Exemptions.Contains(ip); - - public static bool Verify(IPAddress ourAddress) - { - if (!Enabled || IsExempt(ourAddress)) - return true; - - List netStates = TcpServer.Instances; - - int count = 0; - - for (int i = 0; i < netStates.Count; ++i) - { - NetState compState = netStates[i]; - - if (ourAddress.Equals(compState.Address)) - { - ++count; - - if (count >= MaxAddresses) - return false; - } - } - - return true; - } - } -} +using System.Linq; +using System.Net; +using Server.Network; + +namespace Server.Misc +{ + public class IPLimiter + { + public static IPAddress[] Exemptions = + { + // IPAddress.Parse( "127.0.0.1" ), + }; + + public static bool Enabled { get; private set; } + public static bool SocketBlock { get; private set; } + public static int MaxAddresses { get; private set; } + + public static void Configure() + { + Enabled = ServerConfiguration.GetOrUpdateSetting("ipLimiter.enable", true); + SocketBlock = ServerConfiguration.GetOrUpdateSetting("ipLimiter.blockAtConnection", true); + MaxAddresses = ServerConfiguration.GetOrUpdateSetting("ipLimiter.maxConnectionsPerIP", 10); + } + + public static bool IsExempt(IPAddress ip) => Exemptions.Contains(ip); + + public static bool Verify(IPAddress ourAddress) + { + if (!Enabled || IsExempt(ourAddress)) + return true; + + var netStates = TcpServer.Instances; + + var count = 0; + + for (var i = 0; i < netStates.Count; ++i) + { + var compState = netStates[i]; + + if (ourAddress.Equals(compState.Address)) + { + ++count; + + if (count >= MaxAddresses) + return false; + } + } + + return true; + } + } +} diff --git a/Projects/UOContent/Accounting/IPasswordProtection.cs b/Projects/UOContent/Accounting/IPasswordProtection.cs index 20c25fe2a..0fdd6ced9 100644 --- a/Projects/UOContent/Accounting/IPasswordProtection.cs +++ b/Projects/UOContent/Accounting/IPasswordProtection.cs @@ -1,8 +1,8 @@ -namespace Server.Accounting -{ - public interface IPasswordProtection - { - string EncryptPassword(string plainPassword); - bool ValidatePassword(string encryptedPassword, string plainPassword); - } -} +namespace Server.Accounting +{ + public interface IPasswordProtection + { + string EncryptPassword(string plainPassword); + bool ValidatePassword(string encryptedPassword, string plainPassword); + } +} diff --git a/Projects/UOContent/Accounting/Security/AccountSecurity.cs b/Projects/UOContent/Accounting/Security/AccountSecurity.cs index 7a8799bf8..15752e734 100644 --- a/Projects/UOContent/Accounting/Security/AccountSecurity.cs +++ b/Projects/UOContent/Accounting/Security/AccountSecurity.cs @@ -1,71 +1,74 @@ -/************************************************************************* - * ModernUO * - * Copyright (C) 2019-2020 - ModernUO Development Team * - * Email: hi@modernuo.com * - * File: AccountSecurity.cs * - * Created: 2020/05/01 - Updated: 2020/05/02 * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see . * - *************************************************************************/ - -using System; - -namespace Server.Accounting.Security -{ - public enum PasswordProtectionAlgorithm - { - // Obsolete algorithms from RunUO. These are not secure! - // They are included for password upgrades only. - None, - MD5, - SHA1, - - // Supported algorithms - SHA2, // ServUO compatibility - PBKDF2, - Argon2 // Recommended algorithm for real security. - } - - public static class AccountSecurity - { - public static PasswordProtectionAlgorithm CurrentAlgorithm { get; set; } - - public static IPasswordProtection CurrentPasswordProtection => GetPasswordProtection(CurrentAlgorithm); - - public static void Configure() - { - CurrentAlgorithm = - ServerConfiguration.GetOrUpdateSetting("accountSecurity.encryptionAlgorithm", PasswordProtectionAlgorithm.Argon2); - - if (CurrentAlgorithm < PasswordProtectionAlgorithm.SHA2) - throw new Exception($"Security: {CurrentAlgorithm} is obsolete and not secure. Do not use it."); - } - - public static IPasswordProtection GetPasswordProtection(PasswordProtectionAlgorithm algorithm) - { - var passwordProtection = algorithm switch - { - PasswordProtectionAlgorithm.MD5 => MD5PasswordProtection.Instance, - PasswordProtectionAlgorithm.SHA1 => SHA1PasswordProtection.Instance, - PasswordProtectionAlgorithm.SHA2 => SHA2PasswordProtection.Instance, - PasswordProtectionAlgorithm.PBKDF2 => PBKDF2PasswordProtection.Instance, - PasswordProtectionAlgorithm.Argon2 => Argon2PasswordProtection.Instance, - PasswordProtectionAlgorithm.None => throw new Exception("Do not use PasswordProtectionAlgorithm.None"), - _ => throw new Exception("No algorithm") - }; - - return passwordProtection; - } - } -} +/************************************************************************* + * ModernUO * + * Copyright (C) 2019-2020 - ModernUO Development Team * + * Email: hi@modernuo.com * + * File: AccountSecurity.cs * + * Created: 2020/05/01 - Updated: 2020/05/02 * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *************************************************************************/ + +using System; + +namespace Server.Accounting.Security +{ + public enum PasswordProtectionAlgorithm + { + // Obsolete algorithms from RunUO. These are not secure! + // They are included for password upgrades only. + None, + MD5, + SHA1, + + // Supported algorithms + SHA2, // ServUO compatibility + PBKDF2, + Argon2 // Recommended algorithm for real security. + } + + public static class AccountSecurity + { + public static PasswordProtectionAlgorithm CurrentAlgorithm { get; set; } + + public static IPasswordProtection CurrentPasswordProtection => GetPasswordProtection(CurrentAlgorithm); + + public static void Configure() + { + CurrentAlgorithm = + ServerConfiguration.GetOrUpdateSetting( + "accountSecurity.encryptionAlgorithm", + PasswordProtectionAlgorithm.Argon2 + ); + + if (CurrentAlgorithm < PasswordProtectionAlgorithm.SHA2) + throw new Exception($"Security: {CurrentAlgorithm} is obsolete and not secure. Do not use it."); + } + + public static IPasswordProtection GetPasswordProtection(PasswordProtectionAlgorithm algorithm) + { + var passwordProtection = algorithm switch + { + PasswordProtectionAlgorithm.MD5 => MD5PasswordProtection.Instance, + PasswordProtectionAlgorithm.SHA1 => SHA1PasswordProtection.Instance, + PasswordProtectionAlgorithm.SHA2 => SHA2PasswordProtection.Instance, + PasswordProtectionAlgorithm.PBKDF2 => PBKDF2PasswordProtection.Instance, + PasswordProtectionAlgorithm.Argon2 => Argon2PasswordProtection.Instance, + PasswordProtectionAlgorithm.None => throw new Exception("Do not use PasswordProtectionAlgorithm.None"), + _ => throw new Exception("No algorithm") + }; + + return passwordProtection; + } + } +} diff --git a/Projects/UOContent/Accounting/Security/Argon2PasswordProtection.cs b/Projects/UOContent/Accounting/Security/Argon2PasswordProtection.cs index 0451cf5e2..74c8a9ec7 100644 --- a/Projects/UOContent/Accounting/Security/Argon2PasswordProtection.cs +++ b/Projects/UOContent/Accounting/Security/Argon2PasswordProtection.cs @@ -1,40 +1,41 @@ -/************************************************************************* - * ModernUO * - * Copyright (C) 2019-2020 - ModernUO Development Team * - * Email: hi@modernuo.com * - * File: Argon2PasswordProtection.cs * - * Created: 2020/05/01 - Updated: 2020/07/25 * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see . * - *************************************************************************/ - -using System.Security.Cryptography; -using Server.Random; - -namespace Server.Accounting.Security -{ - public class Argon2PasswordProtection : IPasswordProtection - { - public static IPasswordProtection Instance = new Argon2PasswordProtection(); - private Argon2PasswordHasher m_PasswordHasher = new Argon2PasswordHasher( - rng: (RandomSources.SecureSource as SecureRandom)?.Generator - ); - - public string EncryptPassword(string plainPassword) => - m_PasswordHasher.Hash(plainPassword); - - public bool ValidatePassword(string encryptedPassword, string plainPassword) => - m_PasswordHasher.Verify(encryptedPassword, plainPassword); - } -} +/************************************************************************* + * ModernUO * + * Copyright (C) 2019-2020 - ModernUO Development Team * + * Email: hi@modernuo.com * + * File: Argon2PasswordProtection.cs * + * Created: 2020/05/01 - Updated: 2020/07/25 * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *************************************************************************/ + +using System.Security.Cryptography; +using Server.Random; + +namespace Server.Accounting.Security +{ + public class Argon2PasswordProtection : IPasswordProtection + { + public static IPasswordProtection Instance = new Argon2PasswordProtection(); + + private readonly Argon2PasswordHasher m_PasswordHasher = new Argon2PasswordHasher( + rng: (RandomSources.SecureSource as SecureRandom)?.Generator + ); + + public string EncryptPassword(string plainPassword) => + m_PasswordHasher.Hash(plainPassword); + + public bool ValidatePassword(string encryptedPassword, string plainPassword) => + m_PasswordHasher.Verify(encryptedPassword, plainPassword); + } +} diff --git a/Projects/UOContent/Accounting/Security/MD5PasswordProtection.cs b/Projects/UOContent/Accounting/Security/MD5PasswordProtection.cs index b5464f7dc..90b6a982b 100644 --- a/Projects/UOContent/Accounting/Security/MD5PasswordProtection.cs +++ b/Projects/UOContent/Accounting/Security/MD5PasswordProtection.cs @@ -1,46 +1,46 @@ -/************************************************************************* - * ModernUO * - * Copyright (C) 2019-2020 - ModernUO Development Team * - * Email: hi@modernuo.com * - * File: MD5PasswordProtection.cs * - * Created: 2020/05/01 - Updated: 2020/05/02 * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see . * - *************************************************************************/ - -using System; -using System.Security.Cryptography; -using System.Text; -using Server.Misc; - -namespace Server.Accounting.Security -{ - public class MD5PasswordProtection : IPasswordProtection - { - public static IPasswordProtection Instance = new MD5PasswordProtection(); - private MD5CryptoServiceProvider m_MD5HashProvider = new MD5CryptoServiceProvider(); - - public string EncryptPassword(string plainPassword) - { - ReadOnlySpan password = plainPassword.AsSpan(0, Math.Min(256, plainPassword.Length)); - byte[] bytes = new byte[Encoding.ASCII.GetByteCount(password)]; - Encoding.ASCII.GetBytes(password, bytes); - - return HexStringConverter.GetString(m_MD5HashProvider.ComputeHash(bytes)); - } - - public bool ValidatePassword(string encryptedPassword, string plainPassword) => - EncryptPassword(plainPassword) == encryptedPassword; - } -} +/************************************************************************* + * ModernUO * + * Copyright (C) 2019-2020 - ModernUO Development Team * + * Email: hi@modernuo.com * + * File: MD5PasswordProtection.cs * + * Created: 2020/05/01 - Updated: 2020/05/02 * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *************************************************************************/ + +using System; +using System.Security.Cryptography; +using System.Text; +using Server.Misc; + +namespace Server.Accounting.Security +{ + public class MD5PasswordProtection : IPasswordProtection + { + public static IPasswordProtection Instance = new MD5PasswordProtection(); + private readonly MD5CryptoServiceProvider m_MD5HashProvider = new MD5CryptoServiceProvider(); + + public string EncryptPassword(string plainPassword) + { + var password = plainPassword.AsSpan(0, Math.Min(256, plainPassword.Length)); + var bytes = new byte[Encoding.ASCII.GetByteCount(password)]; + Encoding.ASCII.GetBytes(password, bytes); + + return HexStringConverter.GetString(m_MD5HashProvider.ComputeHash(bytes)); + } + + public bool ValidatePassword(string encryptedPassword, string plainPassword) => + EncryptPassword(plainPassword) == encryptedPassword; + } +} diff --git a/Projects/UOContent/Accounting/Security/PBKDF2PasswordProtection.cs b/Projects/UOContent/Accounting/Security/PBKDF2PasswordProtection.cs index 1a70b36e8..0c1adc644 100644 --- a/Projects/UOContent/Accounting/Security/PBKDF2PasswordProtection.cs +++ b/Projects/UOContent/Accounting/Security/PBKDF2PasswordProtection.cs @@ -1,67 +1,66 @@ -/************************************************************************* - * ModernUO * - * Copyright (C) 2019-2020 - ModernUO Development Team * - * Email: hi@modernuo.com * - * File: PBKDF2PasswordProtection.cs * - * Created: 2020/04/30 - Updated: 2020/05/01 * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see . * - *************************************************************************/ - -using System; -using System.Buffers.Binary; -using System.Security.Cryptography; -using Server.Misc; - -namespace Server.Accounting.Security -{ - public class PBKDF2PasswordProtection : IPasswordProtection - { - public static IPasswordProtection Instance = new PBKDF2PasswordProtection(); - - private const ushort m_MinIterations = 1024; - private const ushort m_MaxIterations = 1536; - private static readonly HashAlgorithmName m_Algorithm = HashAlgorithmName.SHA256; - private const int m_SaltSize = 8; - private const int m_HashSize = 32; - private const int m_OutputSize = 2 + m_SaltSize + m_HashSize; - - public string EncryptPassword(string plainPassword) - { - Span output = stackalloc byte[m_OutputSize]; - int iterations = Utility.RandomMinMax(m_MinIterations, m_MaxIterations); - BinaryPrimitives.WriteUInt16LittleEndian(output.Slice(0, 2), (ushort)iterations); - - var rfc2898 = new Rfc2898DeriveBytes(plainPassword, m_SaltSize, iterations, m_Algorithm); - rfc2898.Salt.CopyTo(output.Slice(2, m_SaltSize)); - rfc2898.GetBytes(m_HashSize).CopyTo(output.Slice(m_SaltSize + 2)); - - return HexStringConverter.GetString(output); - } - - public bool ValidatePassword(string encryptedPassword, string plainPassword) - { - Span encryptedBytes = stackalloc byte[m_OutputSize]; - HexStringConverter.GetBytes(encryptedPassword, encryptedBytes); - - ushort iterations = BinaryPrimitives.ReadUInt16LittleEndian(encryptedBytes.Slice(0, 2)); - Span salt = encryptedBytes.Slice(2, m_SaltSize); - - ReadOnlySpan hash = - new Rfc2898DeriveBytes(plainPassword, salt.ToArray(), iterations, m_Algorithm).GetBytes(m_HashSize); - - return hash.SequenceEqual(encryptedBytes.Slice(m_SaltSize + 2)); - } - } -} +/************************************************************************* + * ModernUO * + * Copyright (C) 2019-2020 - ModernUO Development Team * + * Email: hi@modernuo.com * + * File: PBKDF2PasswordProtection.cs * + * Created: 2020/04/30 - Updated: 2020/05/01 * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *************************************************************************/ + +using System; +using System.Buffers.Binary; +using System.Security.Cryptography; +using Server.Misc; + +namespace Server.Accounting.Security +{ + public class PBKDF2PasswordProtection : IPasswordProtection + { + private const ushort m_MinIterations = 1024; + private const ushort m_MaxIterations = 1536; + private const int m_SaltSize = 8; + private const int m_HashSize = 32; + private const int m_OutputSize = 2 + m_SaltSize + m_HashSize; + public static IPasswordProtection Instance = new PBKDF2PasswordProtection(); + private static readonly HashAlgorithmName m_Algorithm = HashAlgorithmName.SHA256; + + public string EncryptPassword(string plainPassword) + { + Span output = stackalloc byte[m_OutputSize]; + var iterations = Utility.RandomMinMax(m_MinIterations, m_MaxIterations); + BinaryPrimitives.WriteUInt16LittleEndian(output.Slice(0, 2), (ushort)iterations); + + var rfc2898 = new Rfc2898DeriveBytes(plainPassword, m_SaltSize, iterations, m_Algorithm); + rfc2898.Salt.CopyTo(output.Slice(2, m_SaltSize)); + rfc2898.GetBytes(m_HashSize).CopyTo(output.Slice(m_SaltSize + 2)); + + return HexStringConverter.GetString(output); + } + + public bool ValidatePassword(string encryptedPassword, string plainPassword) + { + Span encryptedBytes = stackalloc byte[m_OutputSize]; + HexStringConverter.GetBytes(encryptedPassword, encryptedBytes); + + var iterations = BinaryPrimitives.ReadUInt16LittleEndian(encryptedBytes.Slice(0, 2)); + var salt = encryptedBytes.Slice(2, m_SaltSize); + + ReadOnlySpan hash = + new Rfc2898DeriveBytes(plainPassword, salt.ToArray(), iterations, m_Algorithm).GetBytes(m_HashSize); + + return hash.SequenceEqual(encryptedBytes.Slice(m_SaltSize + 2)); + } + } +} diff --git a/Projects/UOContent/Accounting/Security/SHA1PasswordProtection.cs b/Projects/UOContent/Accounting/Security/SHA1PasswordProtection.cs index 8c4f34f9a..a2735e783 100644 --- a/Projects/UOContent/Accounting/Security/SHA1PasswordProtection.cs +++ b/Projects/UOContent/Accounting/Security/SHA1PasswordProtection.cs @@ -1,46 +1,46 @@ -/************************************************************************* - * ModernUO * - * Copyright (C) 2019-2020 - ModernUO Development Team * - * Email: hi@modernuo.com * - * File: SHA1PasswordProtection.cs * - * Created: 2020/05/01 - Updated: 2020/05/02 * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see . * - *************************************************************************/ - -using System; -using System.Security.Cryptography; -using System.Text; -using Server.Misc; - -namespace Server.Accounting.Security -{ - public class SHA1PasswordProtection : IPasswordProtection - { - public static IPasswordProtection Instance = new SHA1PasswordProtection(); - private SHA1CryptoServiceProvider m_SHA1HashProvider = new SHA1CryptoServiceProvider(); - - public string EncryptPassword(string plainPassword) - { - ReadOnlySpan password = plainPassword.AsSpan(0, Math.Min(256, plainPassword.Length)); - byte[] bytes = new byte[Encoding.ASCII.GetByteCount(password)]; - Encoding.ASCII.GetBytes(password, bytes); - - return HexStringConverter.GetString(m_SHA1HashProvider.ComputeHash(bytes)); - } - - public bool ValidatePassword(string encryptedPassword, string plainPassword) => - EncryptPassword(plainPassword) == encryptedPassword; - } -} +/************************************************************************* + * ModernUO * + * Copyright (C) 2019-2020 - ModernUO Development Team * + * Email: hi@modernuo.com * + * File: SHA1PasswordProtection.cs * + * Created: 2020/05/01 - Updated: 2020/05/02 * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *************************************************************************/ + +using System; +using System.Security.Cryptography; +using System.Text; +using Server.Misc; + +namespace Server.Accounting.Security +{ + public class SHA1PasswordProtection : IPasswordProtection + { + public static IPasswordProtection Instance = new SHA1PasswordProtection(); + private readonly SHA1CryptoServiceProvider m_SHA1HashProvider = new SHA1CryptoServiceProvider(); + + public string EncryptPassword(string plainPassword) + { + var password = plainPassword.AsSpan(0, Math.Min(256, plainPassword.Length)); + var bytes = new byte[Encoding.ASCII.GetByteCount(password)]; + Encoding.ASCII.GetBytes(password, bytes); + + return HexStringConverter.GetString(m_SHA1HashProvider.ComputeHash(bytes)); + } + + public bool ValidatePassword(string encryptedPassword, string plainPassword) => + EncryptPassword(plainPassword) == encryptedPassword; + } +} diff --git a/Projects/UOContent/Accounting/Security/SHA2PasswordProtection.cs b/Projects/UOContent/Accounting/Security/SHA2PasswordProtection.cs index 5bf5b6617..6f463f606 100644 --- a/Projects/UOContent/Accounting/Security/SHA2PasswordProtection.cs +++ b/Projects/UOContent/Accounting/Security/SHA2PasswordProtection.cs @@ -1,46 +1,46 @@ -/************************************************************************* - * ModernUO * - * Copyright (C) 2019-2020 - ModernUO Development Team * - * Email: hi@modernuo.com * - * File: SHA2PasswordProtection.cs * - * Created: 2020/05/01 - Updated: 2020/05/02 * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see . * - *************************************************************************/ - -using System; -using System.Security.Cryptography; -using System.Text; -using Server.Misc; - -namespace Server.Accounting.Security -{ - public class SHA2PasswordProtection : IPasswordProtection - { - public static IPasswordProtection Instance = new SHA2PasswordProtection(); - private SHA512CryptoServiceProvider m_SHA2HashProvider = new SHA512CryptoServiceProvider(); - - public string EncryptPassword(string plainPassword) - { - ReadOnlySpan password = plainPassword.AsSpan(0, Math.Min(256, plainPassword.Length)); - byte[] bytes = new byte[Encoding.ASCII.GetByteCount(password)]; - Encoding.ASCII.GetBytes(password, bytes); - - return HexStringConverter.GetString(m_SHA2HashProvider.ComputeHash(bytes)); - } - - public bool ValidatePassword(string encryptedPassword, string plainPassword) => - EncryptPassword(plainPassword) == encryptedPassword; - } -} +/************************************************************************* + * ModernUO * + * Copyright (C) 2019-2020 - ModernUO Development Team * + * Email: hi@modernuo.com * + * File: SHA2PasswordProtection.cs * + * Created: 2020/05/01 - Updated: 2020/05/02 * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *************************************************************************/ + +using System; +using System.Security.Cryptography; +using System.Text; +using Server.Misc; + +namespace Server.Accounting.Security +{ + public class SHA2PasswordProtection : IPasswordProtection + { + public static IPasswordProtection Instance = new SHA2PasswordProtection(); + private readonly SHA512CryptoServiceProvider m_SHA2HashProvider = new SHA512CryptoServiceProvider(); + + public string EncryptPassword(string plainPassword) + { + var password = plainPassword.AsSpan(0, Math.Min(256, plainPassword.Length)); + var bytes = new byte[Encoding.ASCII.GetByteCount(password)]; + Encoding.ASCII.GetBytes(password, bytes); + + return HexStringConverter.GetString(m_SHA2HashProvider.ComputeHash(bytes)); + } + + public bool ValidatePassword(string encryptedPassword, string plainPassword) => + EncryptPassword(plainPassword) == encryptedPassword; + } +} diff --git a/Projects/UOContent/Commands/Attributes.cs b/Projects/UOContent/Commands/Attributes.cs index fd30526a9..0703ac091 100644 --- a/Projects/UOContent/Commands/Attributes.cs +++ b/Projects/UOContent/Commands/Attributes.cs @@ -1,25 +1,25 @@ -using System; - -namespace Server -{ - public class UsageAttribute : Attribute - { - public UsageAttribute(string usage) => Usage = usage; - - public string Usage { get; } - } - - public class DescriptionAttribute : Attribute - { - public DescriptionAttribute(string description) => Description = description; - - public string Description { get; } - } - - public class AliasesAttribute : Attribute - { - public AliasesAttribute(params string[] aliases) => Aliases = aliases; - - public string[] Aliases { get; } - } -} \ No newline at end of file +using System; + +namespace Server +{ + public class UsageAttribute : Attribute + { + public UsageAttribute(string usage) => Usage = usage; + + public string Usage { get; } + } + + public class DescriptionAttribute : Attribute + { + public DescriptionAttribute(string description) => Description = description; + + public string Description { get; } + } + + public class AliasesAttribute : Attribute + { + public AliasesAttribute(params string[] aliases) => Aliases = aliases; + + public string[] Aliases { get; } + } +} diff --git a/Projects/UOContent/Commands/Batch.cs b/Projects/UOContent/Commands/Batch.cs index 1037b64e9..ac38a41b0 100644 --- a/Projects/UOContent/Commands/Batch.cs +++ b/Projects/UOContent/Commands/Batch.cs @@ -1,418 +1,424 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using Server.Commands.Generic; -using Server.Gumps; -using Server.Network; - -namespace Server.Commands -{ - public class Batch : BaseCommand - { - public Batch() - { - Commands = new[] { "Batch" }; - ListOptimized = true; - } - - public BaseCommandImplementor Scope { get; set; } - - public string Condition { get; set; } = ""; - - public List BatchCommands { get; } = new List(); - - public override void ExecuteList(CommandEventArgs e, List list) - { - if (list.Count == 0) - { - LogFailure("Nothing was found to use this command on."); - return; - } - - try - { - BaseCommand[] commands = new BaseCommand[BatchCommands.Count]; - CommandEventArgs[] eventArgs = new CommandEventArgs[BatchCommands.Count]; - - for (int i = 0; i < BatchCommands.Count; ++i) - { - BatchCommand bc = BatchCommands[i]; - - bc.GetDetails(out string commandString, out string argString, out string[] args); - - BaseCommand command = Scope.Commands[commandString]; - - commands[i] = command; - eventArgs[i] = new CommandEventArgs(e.Mobile, commandString, argString, args); - - if (command == null) - { - e.Mobile.SendMessage( - "That is either an invalid command name or one that does not support this modifier: {0}.", - commandString); - return; - } - - if (e.Mobile.AccessLevel < command.AccessLevel) - { - e.Mobile.SendMessage("You do not have access to that command: {0}.", commandString); - return; - } - - if (!command.ValidateArgs(Scope, eventArgs[i])) return; - } - - for (int i = 0; i < commands.Length; ++i) - { - BaseCommand command = commands[i]; - BatchCommand bc = BatchCommands[i]; - - if (list.Count > 20) - CommandLogging.Enabled = false; - - List usedList; - - if (Utility.InsensitiveCompare(bc.Object, "Current") == 0) - { - usedList = list; - } - else - { - Dictionary propertyChains = new Dictionary(); - - usedList = new List(list.Count); - - for (int j = 0; j < list.Count; ++j) - { - object obj = list[j]; - - if (obj == null) - continue; - - Type type = obj.GetType(); - string failReason = ""; - - if (!propertyChains.TryGetValue(type, out PropertyInfo[] chain)) - propertyChains[type] = chain = Properties.GetPropertyInfoChain(e.Mobile, type, bc.Object, - PropertyAccess.Read, ref failReason); - - if (chain == null) - continue; - - PropertyInfo endProp = Properties.GetPropertyInfo(ref obj, chain, ref failReason); - - if (endProp == null) - continue; - - try - { - obj = endProp.GetValue(obj, null); - - if (obj != null) - usedList.Add(obj); - } - catch - { - // ignored - } - } - } - - command.ExecuteList(eventArgs[i], usedList); - - if (list.Count > 20) - CommandLogging.Enabled = true; - - command.Flush(e.Mobile, list.Count > 20); - } - } - catch (Exception ex) - { - e.Mobile.SendMessage(ex.Message); - } - } - - public bool Run(Mobile from) - { - if (Scope == null) - { - from.SendMessage("You must select the batch command scope."); - return false; - } - - if (Condition.Length > 0 && !Scope.SupportsConditionals) - { - from.SendMessage("This command scope does not support conditionals."); - return false; - } - - if (Condition.Length > 0 && !Utility.InsensitiveStartsWith(Condition, "where")) - { - from.SendMessage("The condition field must start with \"where\"."); - return false; - } - - string[] args = CommandSystem.Split(Condition); - - Scope.Process(from, this, args); - - return true; - } - - public static void Initialize() - { - CommandSystem.Register("Batch", AccessLevel.Counselor, Batch_OnCommand); - } - - [Usage("Batch")] - [Description("Allows multiple commands to be run at the same time.")] - public static void Batch_OnCommand(CommandEventArgs e) - { - e.Mobile.SendGump(new BatchGump(e.Mobile, new Batch())); - } - } - - public class BatchCommand - { - public BatchCommand(string command, string obj) - { - Command = command; - Object = obj; - } - - public string Command { get; set; } - - public string Object { get; set; } - - public void GetDetails(out string command, out string argString, out string[] args) - { - int indexOf = Command.IndexOf(' '); - - if (indexOf >= 0) - { - argString = Command.Substring(indexOf + 1); - - command = Command.Substring(0, indexOf); - args = CommandSystem.Split(argString); - } - else - { - argString = ""; - command = Command.ToLower(); - args = Array.Empty(); - } - } - } - - public class BatchGump : BaseGridGump - { - private readonly Batch m_Batch; - private readonly Mobile m_From; - - public BatchGump(Mobile from, Batch batch) : base(30, 30) - { - m_From = from; - m_Batch = batch; - - Render(); - } - - public void Render() - { - AddNewPage(); - - /* Header */ - AddEntryHeader(20); - AddEntryHtml(180, Center("Batch Commands")); - AddEntryHeader(20); - AddNewLine(); - - AddEntryHeader(9); - AddEntryLabel(191, "Run Batch"); - AddEntryButton(20, ArrowRightID1, ArrowRightID2, GetButtonID(1, 0, 0), ArrowRightWidth, ArrowRightHeight); - AddNewLine(); - - AddBlankLine(); - - /* Scope */ - AddEntryHeader(20); - AddEntryHtml(180, Center("Scope")); - AddEntryHeader(20); - AddNewLine(); - - AddEntryHeader(9); - AddEntryLabel(191, m_Batch.Scope == null ? "Select Scope" : m_Batch.Scope.Accessors[0]); - AddEntryButton(20, ArrowRightID1, ArrowRightID2, GetButtonID(1, 0, 1), ArrowRightWidth, ArrowRightHeight); - AddNewLine(); - - AddBlankLine(); - - /* Condition */ - AddEntryHeader(20); - AddEntryHtml(180, Center("Condition")); - AddEntryHeader(20); - AddNewLine(); - - AddEntryHeader(9); - AddEntryText(202, 0, m_Batch.Condition); - AddEntryHeader(9); - AddNewLine(); - - AddBlankLine(); - - /* Commands */ - AddEntryHeader(20); - AddEntryHtml(180, Center("Commands")); - AddEntryHeader(20); - - for (int i = 0; i < m_Batch.BatchCommands.Count; ++i) - { - BatchCommand bc = m_Batch.BatchCommands[i]; - - AddNewLine(); - - AddImageTiled(CurrentX, CurrentY, 9, 2, 0x24A8); - AddImageTiled(CurrentX, CurrentY + 2, 2, EntryHeight + OffsetSize + EntryHeight - 4, 0x24A8); - AddImageTiled(CurrentX, CurrentY + EntryHeight + OffsetSize + EntryHeight - 2, 9, 2, 0x24A8); - AddImageTiled(CurrentX + 3, CurrentY + 3, 6, EntryHeight + EntryHeight - 4 - OffsetSize, HeaderGumpID); - - IncreaseX(9); - AddEntryText(202, 1 + i * 2, bc.Command); - AddEntryHeader(9, 2); - - AddNewLine(); - - IncreaseX(9); - AddEntryText(202, 2 + i * 2, bc.Object); - } - - AddNewLine(); - - AddEntryHeader(9); - AddEntryLabel(191, "Add New Command"); - AddEntryButton(20, ArrowRightID1, ArrowRightID2, GetButtonID(1, 0, 2), ArrowRightWidth, ArrowRightHeight); - - FinishPage(); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (!SplitButtonID(info.ButtonID, 1, out int type, out int index)) - return; - - TextRelay entry = info.GetTextEntry(0); - - if (entry != null) - m_Batch.Condition = entry.Text; - - for (int i = m_Batch.BatchCommands.Count - 1; i >= 0; --i) - { - BatchCommand sc = m_Batch.BatchCommands[i]; - - entry = info.GetTextEntry(1 + i * 2); - - if (entry != null) - sc.Command = entry.Text; - - entry = info.GetTextEntry(2 + i * 2); - - if (entry != null) - sc.Object = entry.Text; - - if (sc.Command.Length == 0 && sc.Object.Length == 0) - m_Batch.BatchCommands.RemoveAt(i); - } - - switch (type) - { - case 0: // main - { - switch (index) - { - case 0: // run - { - m_Batch.Run(m_From); - break; - } - case 1: // set scope - { - m_From.SendGump(new BatchScopeGump(m_From, m_Batch)); - return; - } - case 2: // add command - { - m_Batch.BatchCommands.Add(new BatchCommand("", "")); - break; - } - } - - break; - } - } - - m_From.SendGump(new BatchGump(m_From, m_Batch)); - } - } - - public class BatchScopeGump : BaseGridGump - { - private readonly Batch m_Batch; - private readonly Mobile m_From; - - public BatchScopeGump(Mobile from, Batch batch) : base(30, 30) - { - m_From = from; - m_Batch = batch; - - Render(); - } - - public void Render() - { - AddNewPage(); - - /* Header */ - AddEntryHeader(20); - AddEntryHtml(140, Center("Change Scope")); - AddEntryHeader(20); - - /* Options */ - for (int i = 0; i < BaseCommandImplementor.Implementors.Count; ++i) - { - BaseCommandImplementor impl = BaseCommandImplementor.Implementors[i]; - - if (m_From.AccessLevel < impl.AccessLevel) - continue; - - AddNewLine(); - - AddEntryLabel(20 + OffsetSize + 140, impl.Accessors[0]); - AddEntryButton(20, ArrowRightID1, ArrowRightID2, GetButtonID(1, 0, i), ArrowRightWidth, ArrowRightHeight); - } - - FinishPage(); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (SplitButtonID(info.ButtonID, 1, out int type, out int index)) - switch (type) - { - case 0: - { - if (index < BaseCommandImplementor.Implementors.Count) - { - BaseCommandImplementor impl = BaseCommandImplementor.Implementors[index]; - - if (m_From.AccessLevel >= impl.AccessLevel) - m_Batch.Scope = impl; - } - - break; - } - } - - m_From.SendGump(new BatchGump(m_From, m_Batch)); - } - } -} +using System; +using System.Collections.Generic; +using System.Reflection; +using Server.Commands.Generic; +using Server.Gumps; +using Server.Network; + +namespace Server.Commands +{ + public class Batch : BaseCommand + { + public Batch() + { + Commands = new[] { "Batch" }; + ListOptimized = true; + } + + public BaseCommandImplementor Scope { get; set; } + + public string Condition { get; set; } = ""; + + public List BatchCommands { get; } = new List(); + + public override void ExecuteList(CommandEventArgs e, List list) + { + if (list.Count == 0) + { + LogFailure("Nothing was found to use this command on."); + return; + } + + try + { + var commands = new BaseCommand[BatchCommands.Count]; + var eventArgs = new CommandEventArgs[BatchCommands.Count]; + + for (var i = 0; i < BatchCommands.Count; ++i) + { + var bc = BatchCommands[i]; + + bc.GetDetails(out var commandString, out var argString, out var args); + + var command = Scope.Commands[commandString]; + + commands[i] = command; + eventArgs[i] = new CommandEventArgs(e.Mobile, commandString, argString, args); + + if (command == null) + { + e.Mobile.SendMessage( + "That is either an invalid command name or one that does not support this modifier: {0}.", + commandString + ); + return; + } + + if (e.Mobile.AccessLevel < command.AccessLevel) + { + e.Mobile.SendMessage("You do not have access to that command: {0}.", commandString); + return; + } + + if (!command.ValidateArgs(Scope, eventArgs[i])) return; + } + + for (var i = 0; i < commands.Length; ++i) + { + var command = commands[i]; + var bc = BatchCommands[i]; + + if (list.Count > 20) + CommandLogging.Enabled = false; + + List usedList; + + if (Utility.InsensitiveCompare(bc.Object, "Current") == 0) + { + usedList = list; + } + else + { + var propertyChains = new Dictionary(); + + usedList = new List(list.Count); + + for (var j = 0; j < list.Count; ++j) + { + var obj = list[j]; + + if (obj == null) + continue; + + var type = obj.GetType(); + var failReason = ""; + + if (!propertyChains.TryGetValue(type, out var chain)) + propertyChains[type] = chain = Properties.GetPropertyInfoChain( + e.Mobile, + type, + bc.Object, + PropertyAccess.Read, + ref failReason + ); + + if (chain == null) + continue; + + var endProp = Properties.GetPropertyInfo(ref obj, chain, ref failReason); + + if (endProp == null) + continue; + + try + { + obj = endProp.GetValue(obj, null); + + if (obj != null) + usedList.Add(obj); + } + catch + { + // ignored + } + } + } + + command.ExecuteList(eventArgs[i], usedList); + + if (list.Count > 20) + CommandLogging.Enabled = true; + + command.Flush(e.Mobile, list.Count > 20); + } + } + catch (Exception ex) + { + e.Mobile.SendMessage(ex.Message); + } + } + + public bool Run(Mobile from) + { + if (Scope == null) + { + from.SendMessage("You must select the batch command scope."); + return false; + } + + if (Condition.Length > 0 && !Scope.SupportsConditionals) + { + from.SendMessage("This command scope does not support conditionals."); + return false; + } + + if (Condition.Length > 0 && !Utility.InsensitiveStartsWith(Condition, "where")) + { + from.SendMessage("The condition field must start with \"where\"."); + return false; + } + + var args = CommandSystem.Split(Condition); + + Scope.Process(from, this, args); + + return true; + } + + public static void Initialize() + { + CommandSystem.Register("Batch", AccessLevel.Counselor, Batch_OnCommand); + } + + [Usage("Batch")] + [Description("Allows multiple commands to be run at the same time.")] + public static void Batch_OnCommand(CommandEventArgs e) + { + e.Mobile.SendGump(new BatchGump(e.Mobile, new Batch())); + } + } + + public class BatchCommand + { + public BatchCommand(string command, string obj) + { + Command = command; + Object = obj; + } + + public string Command { get; set; } + + public string Object { get; set; } + + public void GetDetails(out string command, out string argString, out string[] args) + { + var indexOf = Command.IndexOf(' '); + + if (indexOf >= 0) + { + argString = Command.Substring(indexOf + 1); + + command = Command.Substring(0, indexOf); + args = CommandSystem.Split(argString); + } + else + { + argString = ""; + command = Command.ToLower(); + args = Array.Empty(); + } + } + } + + public class BatchGump : BaseGridGump + { + private readonly Batch m_Batch; + private readonly Mobile m_From; + + public BatchGump(Mobile from, Batch batch) : base(30, 30) + { + m_From = from; + m_Batch = batch; + + Render(); + } + + public void Render() + { + AddNewPage(); + + /* Header */ + AddEntryHeader(20); + AddEntryHtml(180, Center("Batch Commands")); + AddEntryHeader(20); + AddNewLine(); + + AddEntryHeader(9); + AddEntryLabel(191, "Run Batch"); + AddEntryButton(20, ArrowRightID1, ArrowRightID2, GetButtonID(1, 0, 0), ArrowRightWidth, ArrowRightHeight); + AddNewLine(); + + AddBlankLine(); + + /* Scope */ + AddEntryHeader(20); + AddEntryHtml(180, Center("Scope")); + AddEntryHeader(20); + AddNewLine(); + + AddEntryHeader(9); + AddEntryLabel(191, m_Batch.Scope == null ? "Select Scope" : m_Batch.Scope.Accessors[0]); + AddEntryButton(20, ArrowRightID1, ArrowRightID2, GetButtonID(1, 0, 1), ArrowRightWidth, ArrowRightHeight); + AddNewLine(); + + AddBlankLine(); + + /* Condition */ + AddEntryHeader(20); + AddEntryHtml(180, Center("Condition")); + AddEntryHeader(20); + AddNewLine(); + + AddEntryHeader(9); + AddEntryText(202, 0, m_Batch.Condition); + AddEntryHeader(9); + AddNewLine(); + + AddBlankLine(); + + /* Commands */ + AddEntryHeader(20); + AddEntryHtml(180, Center("Commands")); + AddEntryHeader(20); + + for (var i = 0; i < m_Batch.BatchCommands.Count; ++i) + { + var bc = m_Batch.BatchCommands[i]; + + AddNewLine(); + + AddImageTiled(CurrentX, CurrentY, 9, 2, 0x24A8); + AddImageTiled(CurrentX, CurrentY + 2, 2, EntryHeight + OffsetSize + EntryHeight - 4, 0x24A8); + AddImageTiled(CurrentX, CurrentY + EntryHeight + OffsetSize + EntryHeight - 2, 9, 2, 0x24A8); + AddImageTiled(CurrentX + 3, CurrentY + 3, 6, EntryHeight + EntryHeight - 4 - OffsetSize, HeaderGumpID); + + IncreaseX(9); + AddEntryText(202, 1 + i * 2, bc.Command); + AddEntryHeader(9, 2); + + AddNewLine(); + + IncreaseX(9); + AddEntryText(202, 2 + i * 2, bc.Object); + } + + AddNewLine(); + + AddEntryHeader(9); + AddEntryLabel(191, "Add New Command"); + AddEntryButton(20, ArrowRightID1, ArrowRightID2, GetButtonID(1, 0, 2), ArrowRightWidth, ArrowRightHeight); + + FinishPage(); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (!SplitButtonID(info.ButtonID, 1, out var type, out var index)) + return; + + var entry = info.GetTextEntry(0); + + if (entry != null) + m_Batch.Condition = entry.Text; + + for (var i = m_Batch.BatchCommands.Count - 1; i >= 0; --i) + { + var sc = m_Batch.BatchCommands[i]; + + entry = info.GetTextEntry(1 + i * 2); + + if (entry != null) + sc.Command = entry.Text; + + entry = info.GetTextEntry(2 + i * 2); + + if (entry != null) + sc.Object = entry.Text; + + if (sc.Command.Length == 0 && sc.Object.Length == 0) + m_Batch.BatchCommands.RemoveAt(i); + } + + switch (type) + { + case 0: // main + { + switch (index) + { + case 0: // run + { + m_Batch.Run(m_From); + break; + } + case 1: // set scope + { + m_From.SendGump(new BatchScopeGump(m_From, m_Batch)); + return; + } + case 2: // add command + { + m_Batch.BatchCommands.Add(new BatchCommand("", "")); + break; + } + } + + break; + } + } + + m_From.SendGump(new BatchGump(m_From, m_Batch)); + } + } + + public class BatchScopeGump : BaseGridGump + { + private readonly Batch m_Batch; + private readonly Mobile m_From; + + public BatchScopeGump(Mobile from, Batch batch) : base(30, 30) + { + m_From = from; + m_Batch = batch; + + Render(); + } + + public void Render() + { + AddNewPage(); + + /* Header */ + AddEntryHeader(20); + AddEntryHtml(140, Center("Change Scope")); + AddEntryHeader(20); + + /* Options */ + for (var i = 0; i < BaseCommandImplementor.Implementors.Count; ++i) + { + var impl = BaseCommandImplementor.Implementors[i]; + + if (m_From.AccessLevel < impl.AccessLevel) + continue; + + AddNewLine(); + + AddEntryLabel(20 + OffsetSize + 140, impl.Accessors[0]); + AddEntryButton(20, ArrowRightID1, ArrowRightID2, GetButtonID(1, 0, i), ArrowRightWidth, ArrowRightHeight); + } + + FinishPage(); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (SplitButtonID(info.ButtonID, 1, out var type, out var index)) + switch (type) + { + case 0: + { + if (index < BaseCommandImplementor.Implementors.Count) + { + var impl = BaseCommandImplementor.Implementors[index]; + + if (m_From.AccessLevel >= impl.AccessLevel) + m_Batch.Scope = impl; + } + + break; + } + } + + m_From.SendGump(new BatchGump(m_From, m_Batch)); + } + } +} diff --git a/Projects/UOContent/Commands/BoundingBoxPicker.cs b/Projects/UOContent/Commands/BoundingBoxPicker.cs index 72a11f0ac..b0e0cdb8a 100644 --- a/Projects/UOContent/Commands/BoundingBoxPicker.cs +++ b/Projects/UOContent/Commands/BoundingBoxPicker.cs @@ -1,63 +1,67 @@ -using Server.Targeting; - -namespace Server -{ - public delegate void BoundingBoxCallback(Map map, Point3D start, Point3D end); - - public static class BoundingBoxPicker - { - public static void Begin(Mobile from, BoundingBoxCallback callback) - { - from.SendMessage("Target the first location of the bounding box."); - from.Target = new PickTarget(callback); - } - - private class PickTarget : Target - { - private readonly BoundingBoxCallback m_Callback; - private readonly bool m_First; - private readonly Map m_Map; - private readonly Point3D m_Store; - - public PickTarget(BoundingBoxCallback callback) : this(Point3D.Zero, true, null, callback) - { - } - - public PickTarget(Point3D store, bool first, Map map, BoundingBoxCallback callback) : base(-1, true, TargetFlags.None) - { - m_Store = store; - m_First = first; - m_Map = map; - m_Callback = callback; - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (!(targeted is IPoint3D p)) - return; - - if (p is Item item) - p = item.GetWorldTop(); - - if (m_First) - { - from.SendMessage("Target another location to complete the bounding box."); - from.Target = new PickTarget(new Point3D(p), false, from.Map, m_Callback); - } - else if (from.Map != m_Map) - { - from.SendMessage("Both locations must reside on the same map."); - } - else if (m_Map != null && m_Map != Map.Internal && m_Callback != null) - { - Point3D start = m_Store; - Point3D end = new Point3D(p); - - Utility.FixPoints(ref start, ref end); - - m_Callback(m_Map, start, end); - } - } - } - } -} \ No newline at end of file +using Server.Targeting; + +namespace Server +{ + public delegate void BoundingBoxCallback(Map map, Point3D start, Point3D end); + + public static class BoundingBoxPicker + { + public static void Begin(Mobile from, BoundingBoxCallback callback) + { + from.SendMessage("Target the first location of the bounding box."); + from.Target = new PickTarget(callback); + } + + private class PickTarget : Target + { + private readonly BoundingBoxCallback m_Callback; + private readonly bool m_First; + private readonly Map m_Map; + private readonly Point3D m_Store; + + public PickTarget(BoundingBoxCallback callback) : this(Point3D.Zero, true, null, callback) + { + } + + public PickTarget(Point3D store, bool first, Map map, BoundingBoxCallback callback) : base( + -1, + true, + TargetFlags.None + ) + { + m_Store = store; + m_First = first; + m_Map = map; + m_Callback = callback; + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (!(targeted is IPoint3D p)) + return; + + if (p is Item item) + p = item.GetWorldTop(); + + if (m_First) + { + from.SendMessage("Target another location to complete the bounding box."); + from.Target = new PickTarget(new Point3D(p), false, from.Map, m_Callback); + } + else if (from.Map != m_Map) + { + from.SendMessage("Both locations must reside on the same map."); + } + else if (m_Map != null && m_Map != Map.Internal && m_Callback != null) + { + var start = m_Store; + var end = new Point3D(p); + + Utility.FixPoints(ref start, ref end); + + m_Callback(m_Map, start, end); + } + } + } + } +} diff --git a/Projects/UOContent/Commands/Docs.cs b/Projects/UOContent/Commands/Docs.cs index be373014b..9583c4037 100644 --- a/Projects/UOContent/Commands/Docs.cs +++ b/Projects/UOContent/Commands/Docs.cs @@ -1,2605 +1,2748 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Text; -using Server.Commands.Generic; -using Server.Engines.BulkOrders; -using Server.Items; -using Server.Network; - -namespace Server.Commands -{ - public class Docs - { - private static Dictionary m_Types; - private static Dictionary> m_Namespaces; - - public static void Initialize() - { - CommandSystem.Register("DocGen", AccessLevel.Administrator, DocGen_OnCommand); - } - - [Usage("DocGen")] - [Description("Generates RunUO documentation.")] - private static void DocGen_OnCommand(CommandEventArgs e) - { - World.Broadcast(0x35, true, "Documentation is being generated, please wait."); - Console.WriteLine("Documentation is being generated, please wait."); - - NetState.Pause(); - - DateTime startTime = DateTime.UtcNow; - - bool generated = Document(); - - DateTime endTime = DateTime.UtcNow; - - NetState.Resume(); - - if (generated) - { - World.Broadcast(0x35, true, "Documentation has been completed. The entire process took {0:F1} seconds.", - (endTime - startTime).TotalSeconds); - Console.WriteLine("Documentation complete."); - } - else - { - World.Broadcast(0x35, true, - "Docmentation failed: Documentation directories are locked and in use. Please close all open files and directories and try again."); - Console.WriteLine("Documentation failed."); - } - } - - private static void LoadTypes(Assembly a, Assembly[] asms) - { - Type[] types = a.GetTypes(); - - for (int i = 0; i < types.Length; ++i) - { - Type type = types[i]; - - string nspace = type.Namespace; - - if (nspace == null || type.IsSpecialName) - continue; - - TypeInfo info = new TypeInfo(type); - m_Types[type] = info; - - if (!m_Namespaces.TryGetValue(nspace, out List nspaces)) - m_Namespaces[nspace] = nspaces = new List(); - - nspaces.Add(info); - - Type baseType = info.m_BaseType; - - if (baseType != null && InAssemblies(baseType, asms)) - { - m_Types.TryGetValue(baseType, out TypeInfo baseInfo); - - if (baseInfo == null) - m_Types[baseType] = baseInfo = new TypeInfo(baseType); - - baseInfo.m_Derived ??= new List(); - - baseInfo.m_Derived.Add(info); - } - - Type decType = info.m_Declaring; - - if (decType != null) - { - m_Types.TryGetValue(decType, out TypeInfo decInfo); - - if (decInfo == null) - m_Types[decType] = decInfo = new TypeInfo(decType); - - decInfo.m_Nested ??= new List(); - - decInfo.m_Nested.Add(info); - } - - for (int j = 0; j < info.m_Interfaces.Length; ++j) - { - Type iface = info.m_Interfaces[j]; - - if (!InAssemblies(iface, asms)) - continue; - - m_Types.TryGetValue(iface, out TypeInfo ifaceInfo); - - if (ifaceInfo == null) - m_Types[iface] = ifaceInfo = new TypeInfo(iface); - - ifaceInfo.m_Derived ??= new List(); - - ifaceInfo.m_Derived.Add(info); - } - } - } - - private static bool InAssemblies(Type t, Assembly[] asms) - { - Assembly a = t.Assembly; - - for (int i = 0; i < asms.Length; ++i) - if (a == asms[i]) - return true; - - return false; - } - - private static void DocumentLoadedTypes() - { - using StreamWriter indexHtml = GetWriter("docs/", "overview.html"); - indexHtml.WriteLine(""); - indexHtml.WriteLine(" "); - indexHtml.WriteLine(" RunUO Documentation - Class Overview"); - indexHtml.WriteLine(" "); - indexHtml.WriteLine( - " "); - indexHtml.WriteLine("

Back to the index

"); - indexHtml.WriteLine("

Namespaces

"); - - SortedList> nspaces = new SortedList>(m_Namespaces); - - foreach (KeyValuePair> kvp in nspaces) - { - kvp.Value.Sort(new TypeComparer()); - - SaveNamespace(kvp.Key, kvp.Value, indexHtml); - } - - indexHtml.WriteLine(" "); - indexHtml.WriteLine(""); - } - - private static void SaveNamespace(string name, List types, StreamWriter indexHtml) - { - string fileName = GetFileName("docs/namespaces/", name, ".html"); - - indexHtml.WriteLine(" {1}
", fileName, name); - - using StreamWriter nsHtml = GetWriter("docs/namespaces/", fileName); - nsHtml.WriteLine(""); - nsHtml.WriteLine(" "); - nsHtml.WriteLine(" RunUO Documentation - Class Overview - {0}", name); - nsHtml.WriteLine(" "); - nsHtml.WriteLine( - " "); - nsHtml.WriteLine("

Back to the namespace index

"); - nsHtml.WriteLine("

{0}

", name); - - for (int i = 0; i < types.Count; ++i) - SaveType(types[i], nsHtml, fileName, name); - - nsHtml.WriteLine(" "); - nsHtml.WriteLine(""); - } - - private static void SaveType(TypeInfo info, StreamWriter nsHtml, string nsFileName, string nsName) - { - if (info.m_Declaring == null) - nsHtml.WriteLine($" {info.LinkName("../types/")}
"); - - using StreamWriter typeHtml = GetWriter(info.FileName); - typeHtml.WriteLine(""); - typeHtml.WriteLine(" "); - typeHtml.WriteLine(" RunUO Documentation - Class Overview - {0}", info.TypeName); - typeHtml.WriteLine(" "); - typeHtml.WriteLine( - " "); - typeHtml.WriteLine("

Back to {1}

", nsFileName, nsName); - - if (info.m_Type.IsEnum) - WriteEnum(info, typeHtml); - else - WriteType(info, typeHtml); - - typeHtml.WriteLine(" "); - typeHtml.WriteLine(""); - } - - public static void FormatGeneric(Type type, out string typeName, out string fileName, out string linkName) - { - string name = null; - string fnam = null; - string link = null; - - if (type.IsGenericType) - { - int index = type.Name.IndexOf('`'); - - if (index > 0) - { - string rootType = type.Name.Substring(0, index); - - StringBuilder nameBuilder = new StringBuilder(rootType); - StringBuilder fnamBuilder = new StringBuilder($"docs/types/{SanitizeType(rootType)}"); - StringBuilder linkBuilder; - linkBuilder = DontLink(type) ? - new StringBuilder($"{rootType}") : - new StringBuilder($"{rootType}"); - - nameBuilder.Append("<"); - fnamBuilder.Append("-"); - linkBuilder.Append("<"); - - Type[] typeArguments = type.GetGenericArguments(); - - for (int i = 0; i < typeArguments.Length; i++) - { - if (i != 0) - { - nameBuilder.Append(','); - fnamBuilder.Append(','); - linkBuilder.Append(','); - } - - string sanitizedName = SanitizeType(typeArguments[i].Name); - string aliasedName = AliasForName(sanitizedName); - - nameBuilder.Append(sanitizedName); - fnamBuilder.Append("T"); - if (DontLink(typeArguments[i])) - linkBuilder.Append($"{aliasedName}"); - else - linkBuilder.Append( - $"{aliasedName}"); - } - - nameBuilder.Append(">"); - fnamBuilder.Append("-"); - linkBuilder.Append(">"); - - name = nameBuilder.ToString(); - fnam = fnamBuilder.ToString(); - link = linkBuilder.ToString(); - } - } - - typeName = name ?? type.Name; - - fileName = fnam == null ? $"docs/types/{SanitizeType(type.Name)}.html" : $"{fnam}.html"; - - if (link == null) - linkName = DontLink(type) ? $"{SanitizeType(type.Name)}" - : $"{SanitizeType(type.Name)}"; - else - linkName = link; - - // Console.WriteLine( typeName+":"+fileName+":"+linkName ); - } - - public static string SanitizeType(string name) - { - bool anonymousType = name.Contains("<"); - StringBuilder sb = new StringBuilder(name); - for (int i = 0; i < ReplaceChars.Length; ++i) - sb.Replace(ReplaceChars[i], '-'); - - if (anonymousType) return $"(Anonymous-Type){sb}"; - return sb.ToString(); - } - - public static string AliasForName(string name) - { - for (int i = 0; i < m_AliasLength; ++i) - if (m_Aliases[i, 0] == name) - return m_Aliases[i, 1]; - return name; - } - - /* - // For stuff we don't want to links to - private static string[] m_DontLink = new string[] - { - "List", - "Stack", - "Queue", - "Dictionary", - "LinkedList", - "SortedList", - "SortedDictionary", - "IComparable", - "IComparer", - "ICloneable", - "Type" - }; - - public static bool DontLink( string name ) - { - foreach( string dontLink in m_DontLink ) - if (dontLink == name ) return true; - return false; - } - */ - public static bool DontLink(Type type) - { - if (type.Name == "T" || string.IsNullOrEmpty(type.Namespace) || m_Namespaces == null) - return true; - - if (type.Namespace.StartsWith("Server")) - return false; - - return !m_Namespaces.ContainsKey(type.Namespace); - } - - private class MemberComparer : IComparer - { - public int Compare(object x, object y) - { - if (x == y) - return 0; - - ConstructorInfo aCtor = x as ConstructorInfo; - ConstructorInfo bCtor = y as ConstructorInfo; - - PropertyInfo aProp = x as PropertyInfo; - PropertyInfo bProp = y as PropertyInfo; - - MethodInfo aMethod = x as MethodInfo; - MethodInfo bMethod = y as MethodInfo; - - bool aStatic = GetStaticFor(aCtor, aProp, aMethod); - bool bStatic = GetStaticFor(bCtor, bProp, bMethod); - - if (aStatic && !bStatic) - return -1; - if (!aStatic && bStatic) - return 1; - - int v = 0; - - if (aCtor != null) - { - if (bCtor == null) - v = -1; - } - else if (bCtor != null) - { - v = 1; - } - else if (aProp != null) - { - if (bProp == null) - v = -1; - } - else if (bProp != null) - { - v = 1; - } - - if (v == 0) - v = GetNameFrom(aCtor, aProp, aMethod).CompareTo(GetNameFrom(bCtor, bProp, bMethod)); - - if (v == 0 && aCtor != null && bCtor != null) - v = aCtor.GetParameters().Length.CompareTo(bCtor.GetParameters().Length); - else if (v == 0 && aMethod != null && bMethod != null) - v = aMethod.GetParameters().Length.CompareTo(bMethod.GetParameters().Length); - - return v; - } - - private bool GetStaticFor(ConstructorInfo ctor, PropertyInfo prop, MethodInfo method) - { - if (ctor != null) - return ctor.IsStatic; - if (method != null) - return method.IsStatic; - - if (prop != null) - { - MethodInfo getMethod = prop.GetGetMethod(); - MethodInfo setMethod = prop.GetGetMethod(); - - return getMethod?.IsStatic == true || setMethod?.IsStatic == true; - } - - return false; - } - - private string GetNameFrom(ConstructorInfo ctor, PropertyInfo prop, MethodInfo method) => ctor?.DeclaringType?.Name ?? prop?.Name ?? method?.Name ?? ""; - } - - private class TypeComparer : IComparer - { - public int Compare(TypeInfo x, TypeInfo y) => - x == null && y == null ? 0 : x == null ? -1 : y == null ? 1 : - x.TypeName.CompareTo(y.TypeName); - } - - private class TypeInfo - { - public List m_Derived, m_Nested; - private readonly string m_FileName; - private readonly string m_TypeName; - private readonly string m_LinkName; - public readonly Type[] m_Interfaces; - public readonly Type m_Type; - public readonly Type m_BaseType; - public readonly Type m_Declaring; - - public TypeInfo(Type type) - { - m_Type = type; - - m_BaseType = type.BaseType; - m_Declaring = type.DeclaringType; - m_Interfaces = type.GetInterfaces(); - - FormatGeneric(m_Type, out m_TypeName, out m_FileName, out m_LinkName); - } - - public string FileName => m_FileName; - public string TypeName => m_TypeName; - - public string LinkName(string dirRoot) => m_LinkName.Replace("@directory@", dirRoot); - } - - private static readonly char[] ReplaceChars = "<>".ToCharArray(); - - public static string GetFileName(string root, string name, string ext) - { - if (name.IndexOfAny(ReplaceChars) >= 0) - { - StringBuilder sb = new StringBuilder(name); - - for (int i = 0; i < ReplaceChars.Length; ++i) sb.Replace(ReplaceChars[i], '-'); - - name = sb.ToString(); - } - - int index = 0; - string file = string.Concat(name, ext); - - while (File.Exists(Path.Combine(root, file))) file = string.Concat(name, ++index, ext); - - return file; - } - - private static readonly string m_RootDirectory = Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]); - - private static void EnsureDirectory(string path) - { - path = Path.Combine(m_RootDirectory, path); - - if (!Directory.Exists(path)) - Directory.CreateDirectory(path); - } - - private static void DeleteDirectory(string path) - { - path = Path.Combine(m_RootDirectory, path); - - if (Directory.Exists(path)) - Directory.Delete(path, true); - } - - private static StreamWriter GetWriter(string root, string name) => new StreamWriter(Path.Combine(Path.Combine(m_RootDirectory, root), name)); - - private static StreamWriter GetWriter(string path) => new StreamWriter(Path.Combine(m_RootDirectory, path)); - - private static readonly string[,] m_Aliases = - { - { "System.Object", "object" }, - { "System.String", "string" }, - { "System.Boolean", "bool" }, - { "System.Byte", "byte" }, - { "System.SByte", "sbyte" }, - { "System.Int16", "short" }, - { "System.UInt16", "ushort" }, - { "System.Int32", "int" }, - { "System.UInt32", "uint" }, - { "System.Int64", "long" }, - { "System.UInt64", "ulong" }, - { "System.Single", "float" }, - { "System.Double", "double" }, - { "System.Decimal", "decimal" }, - { "System.Char", "char" }, - { "System.Void", "void" } - }; - - private static readonly int m_AliasLength = m_Aliases.GetLength(0); - - public static string GetPair(Type varType, string name, bool ignoreRef) - { - string prepend = ""; - StringBuilder append = new StringBuilder(); - - Type realType = varType; - - if (varType.IsByRef) - { - if (!ignoreRef) - prepend = RefString; - - realType = varType.GetElementType(); - } - - if (realType?.IsPointer == true) - { - if (realType.IsArray) - { - append.Append('*'); - - do - { - append.Append('['); - - for (int i = 1; i < realType.GetArrayRank(); ++i) - append.Append(','); - - append.Append(']'); - - realType = realType.GetElementType(); - } while (realType?.IsArray == true); - - append.Append(' '); - } - else - { - realType = realType.GetElementType(); - append.Append(" *"); - } - } - else if (realType?.IsArray == true) - { - do - { - append.Append('['); - - for (int i = 1; i < realType.GetArrayRank(); ++i) - append.Append(','); - - append.Append(']'); - - realType = realType.GetElementType(); - } while (realType?.IsArray == true); - - append.Append(' '); - } - else - { - append.Append(' '); - } - - string fullName = realType?.FullName ?? "(-null-)"; - string aliased = null; // = realType.Name; - - if (realType != null && m_Types.TryGetValue(realType, out TypeInfo info)) - { - aliased = $"{info.LinkName(null)}"; - } - else - { - if (realType?.IsGenericType == true) - { - FormatGeneric(realType, out _, out _, out string linkName); - aliased = linkName.Replace("@directory@", null); - } - else - { - for (int i = 0; i < m_AliasLength; ++i) - if (m_Aliases[i, 0] == fullName) - { - aliased = m_Aliases[i, 1]; - break; - } - } - - aliased ??= realType?.Name ?? ""; - } - - return string.Concat(prepend, aliased, append, name); - } - - private static bool Document() - { - try - { - DeleteDirectory("docs/"); - } - catch - { - return false; - } - - EnsureDirectory("docs/"); - EnsureDirectory("docs/namespaces/"); - EnsureDirectory("docs/types/"); - EnsureDirectory("docs/bods/"); - - GenerateStyles(); - GenerateIndex(); - - DocumentCommands(); - DocumentKeywords(); - DocumentBodies(); - - DocumentBulkOrders(); - - m_Types = new Dictionary(); - m_Namespaces = new Dictionary>(); - - List assemblies = new List { Core.Assembly }; - - foreach (Assembly asm in AssemblyHandler.Assemblies) - assemblies.Add(asm); - - Assembly[] asms = assemblies.ToArray(); - - for (int i = 0; i < asms.Length; ++i) - LoadTypes(asms[i], asms); - - DocumentLoadedTypes(); - DocumentConstructibleObjects(); - - return true; - } - - private static void AddIndexLink(StreamWriter html, string filePath, string label, string desc) - { - html.WriteLine("

{2}

", filePath, desc, label); - } - - private static void GenerateStyles() - { - using StreamWriter css = GetWriter("docs/", "styles.css"); - css.WriteLine("body { background-color: #FFFFFF; font-family: verdana, arial; font-size: 11px; }"); - css.WriteLine("a { color: #28435E; }"); - css.WriteLine("a:hover { color: #4878A9; }"); - css.WriteLine("td.header { background-color: #9696AA; font-weight: bold; font-size: 12px; }"); - css.WriteLine("td.lentry { background-color: #D7D7EB; width: 10%; }"); - css.WriteLine("td.rentry { background-color: #FFFFFF; width: 90%; }"); - css.WriteLine("td.entry { background-color: #FFFFFF; }"); - css.WriteLine("td { font-size: 11px; }"); - css.WriteLine(".tbl-border { background-color: #46465A; }"); - - css.WriteLine("td.ir {{ background-color: #{0:X6}; }}", Iron); - css.WriteLine("td.du {{ background-color: #{0:X6}; }}", DullCopper); - css.WriteLine("td.sh {{ background-color: #{0:X6}; }}", ShadowIron); - css.WriteLine("td.co {{ background-color: #{0:X6}; }}", Copper); - css.WriteLine("td.br {{ background-color: #{0:X6}; }}", Bronze); - css.WriteLine("td.go {{ background-color: #{0:X6}; }}", Gold); - css.WriteLine("td.ag {{ background-color: #{0:X6}; }}", Agapite); - css.WriteLine("td.ve {{ background-color: #{0:X6}; }}", Verite); - css.WriteLine("td.va {{ background-color: #{0:X6}; }}", Valorite); - - css.WriteLine("td.cl {{ background-color: #{0:X6}; }}", Cloth); - css.WriteLine("td.pl {{ background-color: #{0:X6}; }}", Plain); - css.WriteLine("td.sp {{ background-color: #{0:X6}; }}", Core.AOS ? SpinedAOS : SpinedLBR); - css.WriteLine("td.ho {{ background-color: #{0:X6}; }}", Core.AOS ? HornedAOS : HornedLBR); - css.WriteLine("td.ba {{ background-color: #{0:X6}; }}", Core.AOS ? BarbedAOS : BarbedLBR); - } - - private static void GenerateIndex() - { - using StreamWriter html = GetWriter("docs/", "index.html"); - html.WriteLine(""); - html.WriteLine(" "); - html.WriteLine(" RunUO Documentation - Index"); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - - AddIndexLink(html, "commands.html", "Commands", - "Every available command. This contains command name, usage, aliases, and description."); - AddIndexLink(html, "objects.html", "Constructible Objects", - "Every constructible item or npc. This contains object name and usage. Hover mouse over parameters to see type description."); - AddIndexLink(html, "keywords.html", "Speech Keywords", - "Lists speech keyword numbers and associated match patterns. These are used in some scripts for multi-language matching of client speech."); - AddIndexLink(html, "bodies.html", "Body List", - "Every usable body number and name. Table is generated from a UO:3D client datafile. If you do not have UO:3D installed, this may be blank."); - AddIndexLink(html, "overview.html", "Class Overview", - "Scripting reference. Contains every class type and contained methods in the core and scripts."); - AddIndexLink(html, "bods/bod_smith_rewards.html", "Bulk Order Rewards: Smithing", - "Reference table for large and small smithing bulk order deed rewards."); - AddIndexLink(html, "bods/bod_tailor_rewards.html", "Bulk Order Rewards: Tailoring", - "Reference table for large and small tailoring bulk order deed rewards."); - - html.WriteLine(" "); - html.WriteLine(""); - } - - private const int Iron = 0xCCCCDD; - private const int DullCopper = 0xAAAAAA; - private const int ShadowIron = 0x777799; - private const int Copper = 0xDDCC99; - private const int Bronze = 0xAA8866; - private const int Gold = 0xDDCC55; - private const int Agapite = 0xDDAAAA; - private const int Verite = 0x99CC77; - private const int Valorite = 0x88AABB; - - private const int Cloth = 0xDDDDDD; - private const int Plain = 0xCCAA88; - private const int SpinedAOS = 0x99BBBB; - private const int HornedAOS = 0xCC8888; - private const int BarbedAOS = 0xAABBAA; - private const int SpinedLBR = 0xAA8833; - private const int HornedLBR = 0xBBBBAA; - private const int BarbedLBR = 0xCCAA88; - - private static void DocumentBulkOrders() - { - using (StreamWriter html = GetWriter("docs/bods/", "bod_smith_rewards.html")) - { - html.WriteLine(""); - html.WriteLine(" "); - html.WriteLine(" RunUO Documentation - Bulk Orders - Smith Rewards"); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - - SmallBOD sbod = new SmallSmithBOD(); - - sbod.Type = typeof(Katana); - sbod.Material = BulkMaterialType.None; - sbod.AmountMax = 10; - - WriteSmithBODHeader(html, "(Small) Weapons"); - sbod.RequireExceptional = false; - DocumentSmithBOD(html, sbod.ComputeRewards(true), "10, 15, 20: Normal", sbod.Material); - sbod.RequireExceptional = true; - DocumentSmithBOD(html, sbod.ComputeRewards(true), "10, 15, 20: Exceptional", sbod.Material); - WriteSmithBODFooter(html); - - html.WriteLine("

"); - html.WriteLine("

"); - - sbod.Type = typeof(PlateArms); - - WriteSmithBODHeader(html, "(Small) Armor: Normal"); - - sbod.RequireExceptional = false; - for (BulkMaterialType mat = BulkMaterialType.None; mat <= BulkMaterialType.Valorite; ++mat) - { - sbod.Material = mat; - sbod.AmountMax = 10; - DocumentSmithBOD(html, sbod.ComputeRewards(true), "10, 15, 20", sbod.Material); - } - - WriteSmithBODFooter(html); - - html.WriteLine("

"); - - WriteSmithBODHeader(html, "(Small) Armor: Exceptional"); - - sbod.RequireExceptional = true; - for (BulkMaterialType mat = BulkMaterialType.None; mat <= BulkMaterialType.Valorite; ++mat) - { - sbod.Material = mat; - - for (int amt = 15; amt <= 20; amt += 5) - { - sbod.AmountMax = amt; - DocumentSmithBOD(html, sbod.ComputeRewards(true), amt == 20 ? "20" : "10, 15", sbod.Material); - } - } - - WriteSmithBODFooter(html); - - html.WriteLine("

"); - html.WriteLine("

"); - - sbod.Delete(); - - WriteSmithLBOD(html, "Ringmail", LargeBulkEntry.LargeRing); - WriteSmithLBOD(html, "Chainmail", LargeBulkEntry.LargeChain); - WriteSmithLBOD(html, "Platemail", LargeBulkEntry.LargePlate); - - html.WriteLine(" "); - html.WriteLine(""); - } - - using (StreamWriter html = GetWriter("docs/bods/", "bod_tailor_rewards.html")) - { - html.WriteLine(""); - html.WriteLine(" "); - html.WriteLine(" RunUO Documentation - Bulk Orders - Tailor Rewards"); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - - SmallBOD sbod = new SmallTailorBOD(); - - WriteTailorBODHeader(html, "Small Bulk Order"); - - html.WriteLine(" "); - html.WriteLine(" Regular: 10, 15"); - html.WriteLine(" "); - - sbod.AmountMax = 10; - sbod.RequireExceptional = false; - - sbod.Type = typeof(SkullCap); - sbod.Material = BulkMaterialType.None; - DocumentTailorBOD(html, sbod.ComputeRewards(true), "10, 15", sbod.Material, sbod.Type); - - sbod.Type = typeof(LeatherCap); - for (BulkMaterialType mat = BulkMaterialType.None; mat <= BulkMaterialType.Barbed; ++mat) - { - if (mat >= BulkMaterialType.DullCopper && mat <= BulkMaterialType.Valorite) - continue; - - sbod.Material = mat; - DocumentTailorBOD(html, sbod.ComputeRewards(true), "10, 15", sbod.Material, sbod.Type); - } - - html.WriteLine(" "); - html.WriteLine(" Regular: 20"); - html.WriteLine(" "); - - sbod.AmountMax = 20; - sbod.RequireExceptional = false; - - sbod.Type = typeof(SkullCap); - sbod.Material = BulkMaterialType.None; - DocumentTailorBOD(html, sbod.ComputeRewards(true), "20", sbod.Material, sbod.Type); - - sbod.Type = typeof(LeatherCap); - for (BulkMaterialType mat = BulkMaterialType.None; mat <= BulkMaterialType.Barbed; ++mat) - { - if (mat >= BulkMaterialType.DullCopper && mat <= BulkMaterialType.Valorite) - continue; - - sbod.Material = mat; - DocumentTailorBOD(html, sbod.ComputeRewards(true), "20", sbod.Material, sbod.Type); - } - - html.WriteLine(" "); - html.WriteLine( - " Exceptional: 10, 15"); - html.WriteLine(" "); - - sbod.AmountMax = 10; - sbod.RequireExceptional = true; - - sbod.Type = typeof(SkullCap); - sbod.Material = BulkMaterialType.None; - DocumentTailorBOD(html, sbod.ComputeRewards(true), "10, 15", sbod.Material, sbod.Type); - - sbod.Type = typeof(LeatherCap); - for (BulkMaterialType mat = BulkMaterialType.None; mat <= BulkMaterialType.Barbed; ++mat) - { - if (mat >= BulkMaterialType.DullCopper && mat <= BulkMaterialType.Valorite) - continue; - - sbod.Material = mat; - DocumentTailorBOD(html, sbod.ComputeRewards(true), "10, 15", sbod.Material, sbod.Type); - } - - html.WriteLine(" "); - html.WriteLine(" Exceptional: 20"); - html.WriteLine(" "); - - sbod.AmountMax = 20; - sbod.RequireExceptional = true; - - sbod.Type = typeof(SkullCap); - sbod.Material = BulkMaterialType.None; - DocumentTailorBOD(html, sbod.ComputeRewards(true), "20", sbod.Material, sbod.Type); - - sbod.Type = typeof(LeatherCap); - for (BulkMaterialType mat = BulkMaterialType.None; mat <= BulkMaterialType.Barbed; ++mat) - { - if (mat >= BulkMaterialType.DullCopper && mat <= BulkMaterialType.Valorite) - continue; - - sbod.Material = mat; - DocumentTailorBOD(html, sbod.ComputeRewards(true), "20", sbod.Material, sbod.Type); - } - - WriteTailorBODFooter(html); - - html.WriteLine("

"); - html.WriteLine("

"); - - sbod.Delete(); - - WriteTailorLBOD(html, "Large Bulk Order: 4-part", LargeBulkEntry.Gypsy, true, true); - WriteTailorLBOD(html, "Large Bulk Order: 5-part", LargeBulkEntry.TownCrier, true, true); - WriteTailorLBOD(html, "Large Bulk Order: 6-part", LargeBulkEntry.MaleLeatherSet, false, true); - - html.WriteLine(" "); - html.WriteLine(""); - } - } - - private static void WriteTailorLBOD(StreamWriter html, string name, SmallBulkEntry[] entries, bool expandCloth, - bool expandPlain) - { - WriteTailorBODHeader(html, name); - - LargeBOD lbod = new LargeTailorBOD(); - - lbod.Entries = LargeBulkEntry.ConvertEntries(lbod, entries); - - Type type = entries[0].Type; - - bool showCloth = !(type.IsSubclassOf(typeof(BaseArmor)) || type.IsSubclassOf(typeof(BaseShoes))); - - html.WriteLine(" "); - html.WriteLine(" Regular"); - html.WriteLine(" "); - - lbod.RequireExceptional = false; - lbod.AmountMax = 10; - - if (showCloth) - { - lbod.Material = BulkMaterialType.None; - - if (expandCloth) - { - lbod.AmountMax = 10; - DocumentTailorBOD(html, lbod.ComputeRewards(true), "10, 15", lbod.Material, type); - lbod.AmountMax = 20; - DocumentTailorBOD(html, lbod.ComputeRewards(true), "20", lbod.Material, type); - } - else - { - lbod.AmountMax = 10; - DocumentTailorBOD(html, lbod.ComputeRewards(true), "10, 15, 20", lbod.Material, type); - } - } - - lbod.Material = BulkMaterialType.None; - - if (expandPlain) - { - lbod.AmountMax = 10; - DocumentTailorBOD(html, lbod.ComputeRewards(true), "10, 15, 20", lbod.Material, typeof(LeatherCap)); - lbod.AmountMax = 20; - DocumentTailorBOD(html, lbod.ComputeRewards(true), "20", lbod.Material, typeof(LeatherCap)); - } - else - { - lbod.AmountMax = 10; - DocumentTailorBOD(html, lbod.ComputeRewards(true), "10, 15, 20", lbod.Material, typeof(LeatherCap)); - } - - for (BulkMaterialType mat = BulkMaterialType.Spined; mat <= BulkMaterialType.Barbed; ++mat) - { - lbod.Material = mat; - lbod.AmountMax = 10; - DocumentTailorBOD(html, lbod.ComputeRewards(true), "10, 15", lbod.Material, type); - lbod.AmountMax = 20; - DocumentTailorBOD(html, lbod.ComputeRewards(true), "20", lbod.Material, type); - } - - html.WriteLine(" "); - html.WriteLine(" Exceptional"); - html.WriteLine(" "); - - lbod.RequireExceptional = true; - lbod.AmountMax = 10; - - if (showCloth) - { - lbod.Material = BulkMaterialType.None; - - if (expandCloth) - { - lbod.AmountMax = 10; - DocumentTailorBOD(html, lbod.ComputeRewards(true), "10, 15", lbod.Material, type); - lbod.AmountMax = 20; - DocumentTailorBOD(html, lbod.ComputeRewards(true), "20", lbod.Material, type); - } - else - { - lbod.AmountMax = 10; - DocumentTailorBOD(html, lbod.ComputeRewards(true), "10, 15, 20", lbod.Material, type); - } - } - - lbod.Material = BulkMaterialType.None; - - if (expandPlain) - { - lbod.AmountMax = 10; - DocumentTailorBOD(html, lbod.ComputeRewards(true), "10, 15, 20", lbod.Material, typeof(LeatherCap)); - lbod.AmountMax = 20; - DocumentTailorBOD(html, lbod.ComputeRewards(true), "20", lbod.Material, typeof(LeatherCap)); - } - else - { - lbod.AmountMax = 10; - DocumentTailorBOD(html, lbod.ComputeRewards(true), "10, 15, 20", lbod.Material, typeof(LeatherCap)); - } - - for (BulkMaterialType mat = BulkMaterialType.Spined; mat <= BulkMaterialType.Barbed; ++mat) - { - lbod.Material = mat; - lbod.AmountMax = 10; - DocumentTailorBOD(html, lbod.ComputeRewards(true), "10, 15", lbod.Material, type); - lbod.AmountMax = 20; - DocumentTailorBOD(html, lbod.ComputeRewards(true), "20", lbod.Material, type); - } - - WriteTailorBODFooter(html); - - html.WriteLine("

"); - html.WriteLine("

"); - } - - private static void WriteTailorBODHeader(StreamWriter html, string title) - { - html.WriteLine(" "); - html.WriteLine("
"); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" ", title); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine(" "); - } - - private static void WriteTailorBODFooter(StreamWriter html) - { - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine( - " "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine("
{0}
\"Colored
\"Colored
\"Colored
\"Colored
\"Colored
\"Colored
Power Scrolls
\"Small
\"Medium
\"Light
\"Dark
\"Brown
\"Polar
\"Clothing
Runic Kits
+5
+10
+15
+20
\"Runic
\"Runic
\"Runic
 
\"Colored
\"Colored
\"Colored
\"Colored
\"Colored
\"Colored
+5
+10
+15
+20
\"Small
\"Medium
\"Light
\"Dark
\"Brown
\"Polar
\"Clothing
\"Runic
\"Runic
\"Runic
Power Scrolls
Runic Kits
"); - } - - private static void DocumentTailorBOD(StreamWriter html, List items, string amt, BulkMaterialType material, - Type type) - { - bool[] rewards = new bool[20]; - - for (int i = 0; i < items.Count; ++i) - { - Item item = items[i].Construct(); - - if (item is Sandals) - { - rewards[5] = true; - } - else if (item is SmallStretchedHideEastDeed || item is SmallStretchedHideSouthDeed) - { - rewards[10] = rewards[11] = true; - } - else if (item is MediumStretchedHideEastDeed || item is MediumStretchedHideSouthDeed) - { - rewards[10] = rewards[11] = true; - } - else if (item is LightFlowerTapestryEastDeed || item is LightFlowerTapestrySouthDeed) - { - rewards[12] = rewards[13] = true; - } - else if (item is DarkFlowerTapestryEastDeed || item is DarkFlowerTapestrySouthDeed) - { - rewards[12] = rewards[13] = true; - } - else if (item is BrownBearRugEastDeed || item is BrownBearRugSouthDeed) - { - rewards[14] = rewards[15] = true; - } - else if (item is PolarBearRugEastDeed || item is PolarBearRugSouthDeed) - { - rewards[14] = rewards[15] = true; - } - else if (item is ClothingBlessDeed) - { - rewards[16] = true; - } - else if (item is PowerScroll ps) - { - if (ps.Value == 105.0) - rewards[6] = true; - else if (ps.Value == 110.0) - rewards[7] = true; - else if (ps.Value == 115.0) - rewards[8] = true; - else if (ps.Value == 120.0) - rewards[9] = true; - } - else if (item is UncutCloth) - { - if (item.Hue == 0x483 || item.Hue == 0x48C || item.Hue == 0x488 || item.Hue == 0x48A) - rewards[0] = true; - else if (item.Hue == 0x495 || item.Hue == 0x48B || item.Hue == 0x486 || item.Hue == 0x485) - rewards[1] = true; - else if (item.Hue == 0x48D || item.Hue == 0x490 || item.Hue == 0x48E || item.Hue == 0x491) - rewards[2] = true; - else if (item.Hue == 0x48F || item.Hue == 0x494 || item.Hue == 0x484 || item.Hue == 0x497) - rewards[3] = true; - else - rewards[4] = true; - } - else if (item is RunicSewingKit rkit) - { - rewards[16 + CraftResources.GetIndex(rkit.Resource)] = true; - } - - item.Delete(); - } - - string style = null; - string name = null; - - switch (material) - { - case BulkMaterialType.None: - { - if (type.IsSubclassOf(typeof(BaseArmor)) || type.IsSubclassOf(typeof(BaseShoes))) - { - style = "pl"; - name = "Plain"; - } - else - { - style = "cl"; - name = "Cloth"; - } - - break; - } - case BulkMaterialType.Spined: - style = "sp"; - name = "Spined"; - break; - case BulkMaterialType.Horned: - style = "ho"; - name = "Horned"; - break; - case BulkMaterialType.Barbed: - style = "ba"; - name = "Barbed"; - break; - } - - html.WriteLine(" "); - html.WriteLine("  - {0} {1}", - name, amt); - - int index = 0; - - while (index < 20) - if (rewards[index]) - { - html.WriteLine("
X
", style); - ++index; - } - else - { - int count = 0; - - while (index < 20 && !rewards[index]) - { - ++count; - ++index; - - if (index == 5 || index == 6 || index == 10 || index == 17) - break; - } - - html.WriteLine("  ", count * 25, - count == 1 ? "" : $" colspan=\"{count}\""); - } - - html.WriteLine(" "); - } - - private static void WriteSmithLBOD(StreamWriter html, string name, SmallBulkEntry[] entries) - { - LargeBOD lbod = new LargeSmithBOD(); - - lbod.Entries = LargeBulkEntry.ConvertEntries(lbod, entries); - - WriteSmithBODHeader(html, $"(Large) {name}: Normal"); - - lbod.RequireExceptional = false; - for (BulkMaterialType mat = BulkMaterialType.None; mat <= BulkMaterialType.Valorite; ++mat) - { - lbod.Material = mat; - lbod.AmountMax = 10; - DocumentSmithBOD(html, lbod.ComputeRewards(true), "10, 15, 20", lbod.Material); - } - - WriteSmithBODFooter(html); - - html.WriteLine("

"); - - WriteSmithBODHeader(html, $"(Large) {name}: Exceptional"); - - lbod.RequireExceptional = true; - for (BulkMaterialType mat = BulkMaterialType.None; mat <= BulkMaterialType.Valorite; ++mat) - { - lbod.Material = mat; - - for (int amt = 15; amt <= 20; amt += 5) - { - lbod.AmountMax = amt; - DocumentSmithBOD(html, lbod.ComputeRewards(true), amt == 20 ? "20" : "10, 15", lbod.Material); - } - } - - WriteSmithBODFooter(html); - - html.WriteLine("

"); - html.WriteLine("

"); - } - - private static void WriteSmithBODHeader(StreamWriter html, string title) - { - html.WriteLine(" "); - html.WriteLine("
"); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" ", title); - html.WriteLine( - " "); - html.WriteLine(" "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - } - - private static void WriteSmithBODFooter(StreamWriter html) - { - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine( - " "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine( - " "); - html.WriteLine(" "); - html.WriteLine("
{0}
\"Sturdy
Gloves
\"Gargoyles
\"Prospectors
\"Powder
\"Colored
Power Scrolls
Runic Hammers
Ancient Hammers
+1
+3
+5
+5
+10
+15
+20
Du
Sh
Co
Br
Go
Ag
Ve
Va
+10
+15
+30
+60
 
\"Sturdy
+1
 
+3
 
+5
 
\"Gargoyles
\"Prospectors
\"Powder
\"Colored
+5
+10
+15
+20
Du
Sh
Co
Br
Go
Ag
Ve
Va
+10
+15
+30
+60
Gloves
Power Scrolls
Runic Hammers
Ancient Hammers
"); - } - - private static void DocumentSmithBOD(StreamWriter html, List items, string amt, BulkMaterialType material) - { - bool[] rewards = new bool[24]; - - for (int i = 0; i < items.Count; ++i) - { - Item item = items[i].Construct(); - - if (item is SturdyPickaxe || item is SturdyShovel) - { - rewards[0] = true; - } - else if (item is LeatherGlovesOfMining) - { - rewards[1] = true; - } - else if (item is StuddedGlovesOfMining) - { - rewards[2] = true; - } - else if (item is RingmailGlovesOfMining) - { - rewards[3] = true; - } - else if (item is GargoylesPickaxe) - { - rewards[4] = true; - } - else if (item is ProspectorsTool) - { - rewards[5] = true; - } - else if (item is PowderOfTemperament) - { - rewards[6] = true; - } - else if (item is ColoredAnvil) - { - rewards[7] = true; - } - else if (item is PowerScroll ps) - { - if (ps.Value == 105.0) - rewards[8] = true; - else if (ps.Value == 110.0) - rewards[9] = true; - else if (ps.Value == 115.0) - rewards[10] = true; - else if (ps.Value == 120.0) - rewards[11] = true; - } - else if (item is RunicHammer rh) - { - rewards[11 + CraftResources.GetIndex(rh.Resource)] = true; - } - else if (item is AncientSmithyHammer ash) - { - if (ash.Bonus == 10) - rewards[20] = true; - else if (ash.Bonus == 15) - rewards[21] = true; - else if (ash.Bonus == 30) - rewards[22] = true; - else if (ash.Bonus == 60) - rewards[23] = true; - } - - item.Delete(); - } - - string style = null; - string name = null; - - switch (material) - { - case BulkMaterialType.None: - style = "ir"; - name = "Iron"; - break; - case BulkMaterialType.DullCopper: - style = "du"; - name = "Dull Copper"; - break; - case BulkMaterialType.ShadowIron: - style = "sh"; - name = "Shadow Iron"; - break; - case BulkMaterialType.Copper: - style = "co"; - name = "Copper"; - break; - case BulkMaterialType.Bronze: - style = "br"; - name = "Bronze"; - break; - case BulkMaterialType.Gold: - style = "go"; - name = "Gold"; - break; - case BulkMaterialType.Agapite: - style = "ag"; - name = "Agapite"; - break; - case BulkMaterialType.Verite: - style = "ve"; - name = "Verite"; - break; - case BulkMaterialType.Valorite: - style = "va"; - name = "Valorite"; - break; - } - - html.WriteLine(" "); - html.WriteLine(" {0} {1}", name, - amt); - - int index = 0; - - while (index < 24) - if (rewards[index]) - { - html.WriteLine("
X
", style); - ++index; - } - else - { - int count = 0; - - while (index < 24 && !rewards[index]) - { - ++count; - ++index; - - if (index == 4 || index == 8 || index == 12 || index == 20) - break; - } - - html.WriteLine("  ", count * 25, - count == 1 ? "" : $" colspan=\"{count}\""); - } - - html.WriteLine(" "); - } - - public static List LoadBodies() - { - List list = new List(); - - string path = Path.Combine(Core.BaseDirectory, "Data/models.txt"); - - if (File.Exists(path)) - { - using StreamReader ip = new StreamReader(path); - string line; - - while ((line = ip.ReadLine()) != null) - { - line = line.Trim(); - - if (line.Length == 0 || line.StartsWith("#")) - continue; - - string[] split = line.Split('\t'); - - if (split.Length >= 9) - { - Body body = Utility.ToInt32(split[0]); - ModelBodyType type = (ModelBodyType)Utility.ToInt32(split[1]); - string name = split[8]; - - BodyEntry entry = new BodyEntry(body, type, name); - - if (!list.Contains(entry)) - list.Add(entry); - } - } - } - - return list; - } - - private static void DocumentBodies() - { - List list = LoadBodies(); - - using StreamWriter html = GetWriter("docs/", "bodies.html"); - html.WriteLine(""); - html.WriteLine(" "); - html.WriteLine(" RunUO Documentation - Body List"); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine("

Back to the index

"); - - if (list.Count > 0) - { - html.WriteLine("

Body List

"); - - list.Sort(new BodyEntrySorter()); - - ModelBodyType lastType = ModelBodyType.Invalid; - - for (int i = 0; i < list.Count; ++i) - { - BodyEntry entry = list[i]; - ModelBodyType type = entry.BodyType; - - if (type != lastType) - { - if (lastType != ModelBodyType.Invalid) - html.WriteLine("
"); - - lastType = type; - - html.WriteLine(" ", type); - - switch (type) - { - case ModelBodyType.Monsters: - html.WriteLine( - " Monsters | Sea | Animals | Human | Equipment

"); - break; - case ModelBodyType.Sea: - html.WriteLine( - " Monsters | Sea | Animals | Human | Equipment

"); - break; - case ModelBodyType.Animals: - html.WriteLine( - " Monsters | Sea | Animals | Human | Equipment

"); - break; - case ModelBodyType.Human: - html.WriteLine( - " Monsters | Sea | Animals | Human | Equipment

"); - break; - case ModelBodyType.Equipment: - html.WriteLine( - " Monsters | Sea | Animals | Human | Equipment

"); - break; - } - - html.WriteLine(" "); - html.WriteLine("
"); - html.WriteLine(" "); - html.WriteLine(" ", - type); - } - - html.WriteLine(" ", - entry.Body.BodyID, entry.Name); - } - - html.WriteLine("
{0}
{0}{1}
"); - } - else - { - html.WriteLine(" This feature requires a UO:3D installation."); - } - - html.WriteLine(" "); - html.WriteLine(""); - } - - private static void DocumentKeywords() - { - List> tables = LoadSpeechFile(); - - using StreamWriter html = GetWriter("docs/", "keywords.html"); - html.WriteLine(""); - html.WriteLine(" "); - html.WriteLine(" RunUO Documentation - Speech Keywords"); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine("

Back to the index

"); - html.WriteLine("

Speech Keywords

"); - - for (int p = 0; p < 1 && p < tables.Count; ++p) - { - Dictionary table = tables[p]; - - html.WriteLine(" "); - html.WriteLine("
"); - html.WriteLine(" "); - html.WriteLine(" "); - - List list = new List(table.Values); - list.Sort(new SpeechEntrySorter()); - - for (int i = 0; i < list.Count; ++i) - { - SpeechEntry entry = list[i]; - - html.Write(" "); - } - - html.WriteLine("
NumberText
0x{0:X4}", entry.Index); - - entry.Strings.Sort(); // ( new EnglishPrioStringSorter() ); - - for (int j = 0; j < entry.Strings.Count; ++j) - { - if (j > 0) - html.Write("
"); - - string v = entry.Strings[j]; - - for (int k = 0; k < v.Length; ++k) - { - char c = v[k]; - - if (c == '<') - html.Write("<"); - else if (c == '>') - html.Write(">"); - else if (c == '&') - html.Write("&"); - else if (c == '"') - html.Write("""); - else if (c == '\'') - html.Write("'"); - else if (c >= 0x20 && c < 0x7F) - html.Write(c); - else - html.Write("&#{0};", (int)c); - } - } - - html.WriteLine("
"); - } - - html.WriteLine(" "); - html.WriteLine(""); - } - - private class SpeechEntry - { - public SpeechEntry(int index) - { - Index = index; - Strings = new List(); - } - - public int Index { get; } - - public List Strings { get; } - } - - private class SpeechEntrySorter : IComparer - { - public int Compare(SpeechEntry x, SpeechEntry y) - { - if (x == null && y == null) return 0; - return x?.Index.CompareTo(y?.Index) ?? 1; - } - } - - private static List> LoadSpeechFile() - { - List> tables = new List>(); - int lastIndex = -1; - - Dictionary table = null; - - string path = Core.FindDataFile("speech.mul", false); - - if (File.Exists(path)) - { - using FileStream ip = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); - BinaryReader bin = new BinaryReader(ip); - - while (bin.PeekChar() >= 0) - { - int index = bin.ReadByte() << 8 | bin.ReadByte(); - int length = bin.ReadByte() << 8 | bin.ReadByte(); - string text = Encoding.UTF8.GetString(bin.ReadBytes(length)).Trim(); - - if (text.Length == 0) - continue; - - if (table == null || lastIndex > index) - { - if (index == 0 && text == "*withdraw*") - tables.Insert(0, table = new Dictionary()); - else - tables.Add(table = new Dictionary()); - } - - lastIndex = index; - - if (!table.TryGetValue(index, out SpeechEntry entry)) - table[index] = entry = new SpeechEntry(index); - - entry.Strings.Add(text); - } - } - - return tables; - } - - public class DocCommandEntry - { - public DocCommandEntry(AccessLevel accessLevel, string name, string[] aliases, string usage, string description) - { - AccessLevel = accessLevel; - Name = name; - Aliases = aliases; - Usage = usage; - Description = description; - } - - public AccessLevel AccessLevel { get; } - - public string Name { get; } - - public string[] Aliases { get; } - - public string Usage { get; } - - public string Description { get; } - } - - public class CommandEntrySorter : IComparer - { - public int Compare(DocCommandEntry a, DocCommandEntry b) - { - if (a == null && b == null) return 0; - - int v = b?.AccessLevel.CompareTo(a?.AccessLevel) ?? 1; - - if (v != 0) - return v; - - return a?.Name.CompareTo(b?.Name) ?? 1; - } - } - - private static void DocumentCommands() - { - using StreamWriter html = GetWriter("docs/", "commands.html"); - html.WriteLine(""); - html.WriteLine(" "); - html.WriteLine(" RunUO Documentation - Commands"); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine("

Back to the index

"); - html.WriteLine("

Commands

"); - - List commands = new List(CommandSystem.Entries.Values); - List list = new List(); - - commands.Sort(); - commands.Reverse(); - Clean(commands); - - for (int i = 0; i < commands.Count; ++i) - { - CommandEntry e = commands[i]; - - MethodInfo mi = e.Handler.Method; - - object[] attrs = mi.GetCustomAttributes(typeof(UsageAttribute), false); - - if (attrs.Length == 0) - continue; - - UsageAttribute usage = attrs[0] as UsageAttribute; - - attrs = mi.GetCustomAttributes(typeof(DescriptionAttribute), false); - - if (attrs.Length == 0) - continue; - - if (usage == null || !(attrs[0] is DescriptionAttribute desc)) - continue; - - attrs = mi.GetCustomAttributes(typeof(AliasesAttribute), false); - - AliasesAttribute aliases = attrs.Length == 0 ? null : attrs[0] as AliasesAttribute; - - string descString = desc.Description.Replace("<", "<").Replace(">", ">"); - - if (aliases == null) - list.Add(new DocCommandEntry(e.AccessLevel, e.Command, null, usage.Usage, descString)); - else - list.Add(new DocCommandEntry(e.AccessLevel, e.Command, aliases.Aliases, usage.Usage, descString)); - } - - for (int i = 0; i < TargetCommands.AllCommands.Count; ++i) - { - BaseCommand command = TargetCommands.AllCommands[i]; - - string usage = command.Usage; - string desc = command.Description; - - if (usage == null || desc == null) - continue; - - string[] cmds = command.Commands; - string cmd = cmds[0]; - string[] aliases = new string[cmds.Length - 1]; - - for (int j = 0; j < aliases.Length; ++j) - aliases[j] = cmds[j + 1]; - - desc = desc.Replace("<", "<").Replace(">", ">"); - - if (command.Supports != CommandSupport.Single) - { - StringBuilder sb = new StringBuilder(50 + desc.Length); - - sb.Append("Modifiers: "); - - if ((command.Supports & CommandSupport.Global) != 0) - sb.Append("Global, "); - - if ((command.Supports & CommandSupport.Online) != 0) - sb.Append("Online, "); - - if ((command.Supports & CommandSupport.Region) != 0) - sb.Append("Region, "); - - if ((command.Supports & CommandSupport.Contained) != 0) - sb.Append("Contained, "); - - if ((command.Supports & CommandSupport.Multi) != 0) - sb.Append("Multi, "); - - if ((command.Supports & CommandSupport.Area) != 0) - sb.Append("Area, "); - - if ((command.Supports & CommandSupport.Self) != 0) - sb.Append("Self, "); - - sb.Remove(sb.Length - 2, 2); - sb.Append("
"); - sb.Append(desc); - - desc = sb.ToString(); - } - - list.Add(new DocCommandEntry(command.AccessLevel, cmd, aliases, usage, desc)); - } - - List commandImpls = BaseCommandImplementor.Implementors; - - for (int i = 0; i < commandImpls.Count; ++i) - { - BaseCommandImplementor command = commandImpls[i]; - - string usage = command.Usage; - string desc = command.Description; - - if (usage == null || desc == null) - continue; - - string[] cmds = command.Accessors; - string cmd = cmds[0]; - string[] aliases = new string[cmds.Length - 1]; - - for (int j = 0; j < aliases.Length; ++j) - aliases[j] = cmds[j + 1]; - - desc = desc.Replace("<", "<").Replace(">", ">"); - - list.Add(new DocCommandEntry(command.AccessLevel, cmd, aliases, usage, desc)); - } - - list.Sort(new CommandEntrySorter()); - - AccessLevel last = AccessLevel.Player; - - foreach (DocCommandEntry e in list) - { - if (e.AccessLevel != last) - { - if (last != AccessLevel.Player) - html.WriteLine("

"); - - last = e.AccessLevel; - - html.WriteLine(" ", last); - - switch (last) - { - case AccessLevel.Administrator: - html.WriteLine( - " Administrator | Game Master | Counselor | Player

"); - break; - case AccessLevel.GameMaster: - html.WriteLine( - " Administrator | Game Master | Counselor | Player

"); - break; - case AccessLevel.Seer: - html.WriteLine( - " Administrator | Game Master | Counselor | Player

"); - break; - case AccessLevel.Counselor: - html.WriteLine( - " Administrator | Game Master | Counselor | Player

"); - break; - case AccessLevel.Player: - html.WriteLine( - " Administrator | Game Master | Counselor | Player

"); - break; - } - - html.WriteLine(" "); - html.WriteLine("
"); - html.WriteLine(" "); - html.WriteLine(" ", - last == AccessLevel.GameMaster ? "Game Master" : last.ToString()); - } - - DocumentCommand(html, e); - } - - html.WriteLine("
{0}
"); - html.WriteLine(" "); - html.WriteLine(""); - } - - public static void Clean(List list) - { - for (int i = 0; i < list.Count; ++i) - { - CommandEntry e = list[i]; - - for (int j = i + 1; j < list.Count; ++j) - { - CommandEntry c = list[j]; - - if (e.Handler.Method == c.Handler.Method) - { - list.RemoveAt(j); - --j; - } - } - } - } - - private static void DocumentCommand(StreamWriter html, DocCommandEntry e) - { - string usage = e.Usage; - string desc = e.Description; - string[] aliases = e.Aliases; - - html.Write(" {0}", e.Name); - - if (aliases == null || aliases.Length == 0) - { - html.Write("Usage: {0}
{1}", - usage.Replace("<", "<").Replace(">", ">"), desc); - } - else - { - html.Write("Usage: {0}
Alias{1}: ", - usage.Replace("<", "<").Replace(">", ">"), aliases.Length == 1 ? "" : "es"); - - for (int i = 0; i < aliases.Length; ++i) - { - if (i != 0) - html.Write(", "); - - html.Write(aliases[i]); - } - - html.Write("
{0}", desc); - } - - html.WriteLine(""); - } - - private static readonly Type typeofItem = typeof(Item); - private static readonly Type typeofMobile = typeof(Mobile); - private static readonly Type typeofMap = typeof(Map); - private static readonly Type typeofCustomEnum = typeof(CustomEnumAttribute); - - private static bool IsConstructible(Type t, out bool isItem) => (isItem = typeofItem.IsAssignableFrom(t)) || typeofMobile.IsAssignableFrom(t); - - private static bool IsConstructible(ConstructorInfo ctor) => ctor.IsDefined(typeof(ConstructibleAttribute), false); - - private static void DocumentConstructibleObjects() - { - List types = new List(m_Types.Values); - types.Sort(new TypeComparer()); - - List<(Type, ConstructorInfo[])> items = new List<(Type, ConstructorInfo[])>(); - List<(Type, ConstructorInfo[])> mobiles = new List<(Type, ConstructorInfo[])>(); - - for (int i = 0; i < types.Count; ++i) - { - Type t = types[i].m_Type; - - if (t.IsAbstract || !IsConstructible(t, out bool isItem)) - continue; - - ConstructorInfo[] ctors = t.GetConstructors(); - bool anyConstructible = false; - - for (int j = 0; !anyConstructible && j < ctors.Length; ++j) - anyConstructible = IsConstructible(ctors[j]); - - if (anyConstructible) (isItem ? items : mobiles).Add((t, ctors)); - } - - using StreamWriter html = GetWriter("docs/", "objects.html"); - html.WriteLine(""); - html.WriteLine(" "); - html.WriteLine(" RunUO Documentation - Constructible Objects"); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine("

Back to the index

"); - html.WriteLine( - "

Constructible Items and Mobiles

"); - - html.WriteLine(" "); - html.WriteLine(" "); - html.WriteLine("
"); - html.WriteLine(" "); - html.WriteLine(" "); - - items.ForEach(tuple => - { - var (type, constructors) = tuple; - DocumentConstructibleObject(html, type, constructors); - }); - - html.WriteLine("
Item NameUsage


"); - - html.WriteLine("
"); - html.WriteLine(" "); - html.WriteLine("
"); - html.WriteLine(" "); - html.WriteLine(" "); - - mobiles.ForEach(tuple => - { - var (type, constructors) = tuple; - DocumentConstructibleObject(html, type, constructors); - }); - - html.WriteLine("
Mobile NameUsage
"); - - html.WriteLine(" "); - html.WriteLine(""); - } - - private static void DocumentConstructibleObject(StreamWriter html, Type t, ConstructorInfo[] ctors) - { - html.Write(" {0}", t.Name); - - bool first = true; - - for (int i = 0; i < ctors.Length; ++i) - { - ConstructorInfo ctor = ctors[i]; - - if (!IsConstructible(ctor)) - continue; - - if (!first) - html.Write("
"); - - first = false; - - html.Write("{0}Add {1}", CommandSystem.Prefix, t.Name); - - ParameterInfo[] parms = ctor.GetParameters(); - - for (int j = 0; j < parms.Length; ++j) - { - html.Write("
{1}", GetTooltipFor(parms[j]), parms[j].Name); - } - } - - html.WriteLine(""); - } - - private const string HtmlNewLine = " "; - - private static readonly object[,] m_Tooltips = - { - { typeof(byte), "Numeric value in the range from 0 to 255, inclusive." }, - { typeof(sbyte), "Numeric value in the range from negative 128 to positive 127, inclusive." }, - { typeof(ushort), "Numeric value in the range from 0 to 65,535, inclusive." }, - { typeof(short), "Numeric value in the range from negative 32,768 to positive 32,767, inclusive." }, - { typeof(uint), "Numeric value in the range from 0 to 4,294,967,295, inclusive." }, - { typeof(int), "Numeric value in the range from negative 2,147,483,648 to positive 2,147,483,647, inclusive." }, - { typeof(ulong), "Numeric value in the range from 0 through about 10^20." }, - { typeof(long), "Numeric value in the approximate range from negative 10^19 through 10^19." }, - { - typeof(string), - "Text value. To specify a value containing spaces, encapsulate the value in quote characters:{0}{0}"Spaced text example"" - }, - { typeof(bool), "Boolean value which can be either True or False." }, - { typeof(Map), "Map or facet name. Possible values include:{0}{0}- Felucca{0}- Trammel{0}- Ilshenar{0}- Malas" }, - { - typeof(Poison), - "Poison name or level. Possible values include:{0}{0}- Lesser{0}- Regular{0}- Greater{0}- Deadly{0}- Lethal" - }, - { - typeof(Point3D), - "Three-dimensional coordinate value. Format as follows:{0}{0}"(, , )"" - } - }; - - private static string GetTooltipFor(ParameterInfo param) - { - Type paramType = param.ParameterType; - - for (int i = 0; i < m_Tooltips.GetLength(0); ++i) - { - Type checkType = (Type)m_Tooltips[i, 0]; - - if (paramType == checkType) - return string.Format((string)m_Tooltips[i, 1], HtmlNewLine); - } - - if (paramType.IsEnum) - { - StringBuilder sb = new StringBuilder(); - - sb.AppendFormat("Enumeration value or name. Possible named values include:{0}", HtmlNewLine); - - string[] names = Enum.GetNames(paramType); - - for (int i = 0; i < names.Length; ++i) - sb.AppendFormat("{0}- {1}", HtmlNewLine, names[i]); - - return sb.ToString(); - } - - if (paramType.IsDefined(typeofCustomEnum, false)) - { - object[] attributes = paramType.GetCustomAttributes(typeofCustomEnum, false); - - if (attributes.Length > 0 && attributes[0] is CustomEnumAttribute attr) - { - StringBuilder sb = new StringBuilder(); - - sb.AppendFormat("Enumeration value or name. Possible named values include:{0}", HtmlNewLine); - - string[] names = attr.Names; - - for (int i = 0; i < names.Length; ++i) - sb.AppendFormat("{0}- {1}", HtmlNewLine, names[i]); - - return sb.ToString(); - } - } - else if (paramType == typeofMap) - { - StringBuilder sb = new StringBuilder(); - - sb.AppendFormat("Enumeration value or name. Possible named values include:{0}", HtmlNewLine); - - string[] names = Map.GetMapNames(); - - for (int i = 0; i < names.Length; ++i) - sb.AppendFormat("{0}- {1}", HtmlNewLine, names[i]); - - return sb.ToString(); - } - - return ""; - } - - private const string RefString = "ref "; - private const string GetString = " get;"; - private const string SetString = " set;"; - - private const string InString = "in "; - private const string OutString = "out "; - - private const string VirtString = "virtual "; - private const string CtorString = "(ctor) "; - private const string StaticString = "(static) "; - - private static void WriteEnum(TypeInfo info, StreamWriter typeHtml) - { - Type type = info.m_Type; - - typeHtml.WriteLine("

{0} (Enum)

", info.TypeName); - - string[] names = Enum.GetNames(type); - - bool flags = type.IsDefined(typeof(FlagsAttribute), false); - string format; - - if (flags) - format = " {0:G} = 0x{1:X}{2}
"; - else - format = " {0:G} = {1:D}{2}
"; - - for (int i = 0; i < names.Length; ++i) - { - object value = Enum.Parse(type, names[i]); - - typeHtml.WriteLine(format, names[i], value, i < names.Length - 1 ? "," : ""); - } - } - - private static void WriteType(TypeInfo info, StreamWriter typeHtml) - { - Type type = info.m_Type; - - typeHtml.Write("

"); - - Type decType = info.m_Declaring; - - if (decType != null) - { - // We are a nested type - - typeHtml.Write('('); - - m_Types.TryGetValue(decType, out TypeInfo decInfo); - - if (decInfo == null) - typeHtml.Write(decType.Name); - else - // typeHtml.Write( "{1}", decInfo.m_FileName, decInfo.m_TypeName ); - typeHtml.Write(decInfo.LinkName(null)); - - typeHtml.Write(") - "); - } - - typeHtml.Write(info.TypeName); - - Type[] ifaces = info.m_Interfaces; - Type baseType = info.m_BaseType; - - int extendCount = 0; - - if (baseType != typeof(object) && baseType != typeof(ValueType) && baseType?.IsPrimitive == false) - { - typeHtml.Write(" : "); - - m_Types.TryGetValue(baseType, out TypeInfo baseInfo); - - if (baseInfo == null) - typeHtml.Write(baseType.Name); - else - typeHtml.Write($"{baseInfo.LinkName(null)}"); - - ++extendCount; - } - - if (ifaces.Length > 0) - { - if (extendCount == 0) - typeHtml.Write(" : "); - - for (int i = 0; i < ifaces.Length; ++i) - { - Type iface = ifaces[i]; - m_Types.TryGetValue(iface, out TypeInfo ifaceInfo); - - if (extendCount != 0) - typeHtml.Write(", "); - - ++extendCount; - - if (ifaceInfo == null) - { - FormatGeneric(iface, out _, out _, out string linkName); - typeHtml.Write($"{linkName.Replace("@directory@", null)}"); - } - else - { - typeHtml.Write($"{ifaceInfo.LinkName(null)}"); - } - } - } - - typeHtml.WriteLine("

"); - - List derived = info.m_Derived; - - if (derived != null) - { - typeHtml.Write("

Derived Types: "); - - derived.Sort(new TypeComparer()); - - for (int i = 0; i < derived.Count; ++i) - { - TypeInfo derivedInfo = derived[i]; - - if (i != 0) - typeHtml.Write(", "); - - // typeHtml.Write( "{1}", derivedInfo.m_FileName, derivedInfo.m_TypeName ); - typeHtml.Write($"{derivedInfo.LinkName(null)}"); - } - - typeHtml.WriteLine("

"); - } - - List nested = info.m_Nested; - - if (nested != null) - { - typeHtml.Write("

Nested Types: "); - - nested.Sort(new TypeComparer()); - - for (int i = 0; i < nested.Count; ++i) - { - TypeInfo nestedInfo = nested[i]; - - if (i != 0) - typeHtml.Write(", "); - - // typeHtml.Write( "{1}", nestedInfo.m_FileName, nestedInfo.m_TypeName ); - typeHtml.Write($"{nestedInfo.LinkName(null)}"); - } - - typeHtml.WriteLine("

"); - } - - MemberInfo[] membs = type.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | - BindingFlags.Instance | BindingFlags.DeclaredOnly); - - Array.Sort(membs, new MemberComparer()); - - for (int i = 0; i < membs.Length; ++i) - { - MemberInfo mi = membs[i]; - - if (mi is PropertyInfo propertyInfo) - WriteProperty(propertyInfo, typeHtml); - else if (mi is ConstructorInfo constructorInfo) - WriteCtor(info.TypeName, constructorInfo, typeHtml); - else if (mi is MethodInfo methodInfo) - WriteMethod(methodInfo, typeHtml); - } - } - - private static void WriteProperty(PropertyInfo pi, StreamWriter html) - { - html.Write(" "); - - MethodInfo getMethod = pi.GetGetMethod(); - MethodInfo setMethod = pi.GetSetMethod(); - - if (getMethod?.IsStatic == true || setMethod?.IsStatic == true) - html.Write(StaticString); - - html.Write(GetPair(pi.PropertyType, pi.Name, false)); - html.Write('('); - - if (pi.CanRead) - html.Write(GetString); - - if (pi.CanWrite) - html.Write(SetString); - - html.WriteLine(" )
"); - } - - private static void WriteCtor(string name, ConstructorInfo ctor, StreamWriter html) - { - if (ctor.IsStatic) - return; - - html.Write(" "); - html.Write(CtorString); - html.Write(name); - html.Write('('); - - ParameterInfo[] parms = ctor.GetParameters(); - - if (parms.Length > 0) - { - html.Write(' '); - - for (int i = 0; i < parms.Length; ++i) - { - ParameterInfo pi = parms[i]; - - if (i != 0) - html.Write(", "); - - if (pi.IsIn) - html.Write(InString); - else if (pi.IsOut) - html.Write(OutString); - - html.Write(GetPair(pi.ParameterType, pi.Name, pi.IsOut)); - } - - html.Write(' '); - } - - html.WriteLine(")
"); - } - - private static void WriteMethod(MethodInfo mi, StreamWriter html) - { - if (mi.IsSpecialName) - return; - - html.Write(" "); - - if (mi.IsStatic) - html.Write(StaticString); - - if (mi.IsVirtual) - html.Write(VirtString); - - html.Write(GetPair(mi.ReturnType, mi.Name, false)); - html.Write('('); - - ParameterInfo[] parms = mi.GetParameters(); - - if (parms.Length > 0) - { - html.Write(' '); - - for (int i = 0; i < parms.Length; ++i) - { - ParameterInfo pi = parms[i]; - - if (i != 0) - html.Write(", "); - - if (pi.IsIn) - html.Write(InString); - else if (pi.IsOut) - html.Write(OutString); - - html.Write(GetPair(pi.ParameterType, pi.Name, pi.IsOut)); - } - - html.Write(' '); - } - - html.WriteLine(")
"); - } - } - - public enum ModelBodyType - { - Invalid = -1, - Monsters, - Sea, - Animals, - Human, - Equipment - } - - public class BodyEntry - { - public BodyEntry(Body body, ModelBodyType bodyType, string name) - { - Body = body; - BodyType = bodyType; - Name = name; - } - - public Body Body { get; } - - public ModelBodyType BodyType { get; } - - public string Name { get; } - - public override bool Equals(object obj) - { - BodyEntry e = obj as BodyEntry; - - return Body == e?.Body && BodyType == e.BodyType && Name == e.Name; - } - - public override int GetHashCode() => Body.BodyID ^ (int)BodyType ^ Name.GetHashCode(); - } - - public class BodyEntrySorter : IComparer - { - public int Compare(BodyEntry a, BodyEntry b) - { - if (a == null && b == null) return 0; - int v = a?.BodyType.CompareTo(b?.BodyType) ?? 1; - - if (v == 0) - v = a?.Body.BodyID.CompareTo(b?.Body.BodyID) ?? 1; - - if (v != 0) - return v; - - return a?.Name.CompareTo(b?.Name) ?? 1; - } - } -} +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Text; +using Server.Commands.Generic; +using Server.Engines.BulkOrders; +using Server.Items; +using Server.Network; + +namespace Server.Commands +{ + public class Docs + { + private const int Iron = 0xCCCCDD; + private const int DullCopper = 0xAAAAAA; + private const int ShadowIron = 0x777799; + private const int Copper = 0xDDCC99; + private const int Bronze = 0xAA8866; + private const int Gold = 0xDDCC55; + private const int Agapite = 0xDDAAAA; + private const int Verite = 0x99CC77; + private const int Valorite = 0x88AABB; + + private const int Cloth = 0xDDDDDD; + private const int Plain = 0xCCAA88; + private const int SpinedAOS = 0x99BBBB; + private const int HornedAOS = 0xCC8888; + private const int BarbedAOS = 0xAABBAA; + private const int SpinedLBR = 0xAA8833; + private const int HornedLBR = 0xBBBBAA; + private const int BarbedLBR = 0xCCAA88; + + private const string HtmlNewLine = " "; + + private const string RefString = "ref "; + private const string GetString = " get;"; + private const string SetString = " set;"; + + private const string InString = "in "; + private const string OutString = "out "; + + private const string VirtString = "virtual "; + private const string CtorString = "(ctor) "; + private const string StaticString = "(static) "; + private static Dictionary m_Types; + private static Dictionary> m_Namespaces; + + private static readonly char[] ReplaceChars = "<>".ToCharArray(); + + private static readonly string m_RootDirectory = Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]); + + private static readonly string[,] m_Aliases = + { + { "System.Object", "object" }, + { "System.String", "string" }, + { "System.Boolean", "bool" }, + { "System.Byte", "byte" }, + { "System.SByte", "sbyte" }, + { "System.Int16", "short" }, + { "System.UInt16", "ushort" }, + { "System.Int32", "int" }, + { "System.UInt32", "uint" }, + { "System.Int64", "long" }, + { "System.UInt64", "ulong" }, + { "System.Single", "float" }, + { "System.Double", "double" }, + { "System.Decimal", "decimal" }, + { "System.Char", "char" }, + { "System.Void", "void" } + }; + + private static readonly int m_AliasLength = m_Aliases.GetLength(0); + + private static readonly Type typeofItem = typeof(Item); + private static readonly Type typeofMobile = typeof(Mobile); + private static readonly Type typeofMap = typeof(Map); + private static readonly Type typeofCustomEnum = typeof(CustomEnumAttribute); + + private static readonly object[,] m_Tooltips = + { + { typeof(byte), "Numeric value in the range from 0 to 255, inclusive." }, + { typeof(sbyte), "Numeric value in the range from negative 128 to positive 127, inclusive." }, + { typeof(ushort), "Numeric value in the range from 0 to 65,535, inclusive." }, + { typeof(short), "Numeric value in the range from negative 32,768 to positive 32,767, inclusive." }, + { typeof(uint), "Numeric value in the range from 0 to 4,294,967,295, inclusive." }, + { typeof(int), "Numeric value in the range from negative 2,147,483,648 to positive 2,147,483,647, inclusive." }, + { typeof(ulong), "Numeric value in the range from 0 through about 10^20." }, + { typeof(long), "Numeric value in the approximate range from negative 10^19 through 10^19." }, + { + typeof(string), + "Text value. To specify a value containing spaces, encapsulate the value in quote characters:{0}{0}"Spaced text example"" + }, + { typeof(bool), "Boolean value which can be either True or False." }, + { typeof(Map), "Map or facet name. Possible values include:{0}{0}- Felucca{0}- Trammel{0}- Ilshenar{0}- Malas" }, + { + typeof(Poison), + "Poison name or level. Possible values include:{0}{0}- Lesser{0}- Regular{0}- Greater{0}- Deadly{0}- Lethal" + }, + { + typeof(Point3D), + "Three-dimensional coordinate value. Format as follows:{0}{0}"(, , )"" + } + }; + + public static void Initialize() + { + CommandSystem.Register("DocGen", AccessLevel.Administrator, DocGen_OnCommand); + } + + [Usage("DocGen")] + [Description("Generates RunUO documentation.")] + private static void DocGen_OnCommand(CommandEventArgs e) + { + World.Broadcast(0x35, true, "Documentation is being generated, please wait."); + Console.WriteLine("Documentation is being generated, please wait."); + + NetState.Pause(); + + var startTime = DateTime.UtcNow; + + var generated = Document(); + + var endTime = DateTime.UtcNow; + + NetState.Resume(); + + if (generated) + { + World.Broadcast( + 0x35, + true, + "Documentation has been completed. The entire process took {0:F1} seconds.", + (endTime - startTime).TotalSeconds + ); + Console.WriteLine("Documentation complete."); + } + else + { + World.Broadcast( + 0x35, + true, + "Docmentation failed: Documentation directories are locked and in use. Please close all open files and directories and try again." + ); + Console.WriteLine("Documentation failed."); + } + } + + private static void LoadTypes(Assembly a, Assembly[] asms) + { + var types = a.GetTypes(); + + for (var i = 0; i < types.Length; ++i) + { + var type = types[i]; + + var nspace = type.Namespace; + + if (nspace == null || type.IsSpecialName) + continue; + + var info = new TypeInfo(type); + m_Types[type] = info; + + if (!m_Namespaces.TryGetValue(nspace, out var nspaces)) + m_Namespaces[nspace] = nspaces = new List(); + + nspaces.Add(info); + + var baseType = info.m_BaseType; + + if (baseType != null && InAssemblies(baseType, asms)) + { + m_Types.TryGetValue(baseType, out var baseInfo); + + if (baseInfo == null) + m_Types[baseType] = baseInfo = new TypeInfo(baseType); + + baseInfo.m_Derived ??= new List(); + + baseInfo.m_Derived.Add(info); + } + + var decType = info.m_Declaring; + + if (decType != null) + { + m_Types.TryGetValue(decType, out var decInfo); + + if (decInfo == null) + m_Types[decType] = decInfo = new TypeInfo(decType); + + decInfo.m_Nested ??= new List(); + + decInfo.m_Nested.Add(info); + } + + for (var j = 0; j < info.m_Interfaces.Length; ++j) + { + var iface = info.m_Interfaces[j]; + + if (!InAssemblies(iface, asms)) + continue; + + m_Types.TryGetValue(iface, out var ifaceInfo); + + if (ifaceInfo == null) + m_Types[iface] = ifaceInfo = new TypeInfo(iface); + + ifaceInfo.m_Derived ??= new List(); + + ifaceInfo.m_Derived.Add(info); + } + } + } + + private static bool InAssemblies(Type t, Assembly[] asms) + { + var a = t.Assembly; + + for (var i = 0; i < asms.Length; ++i) + if (a == asms[i]) + return true; + + return false; + } + + private static void DocumentLoadedTypes() + { + using var indexHtml = GetWriter("docs/", "overview.html"); + indexHtml.WriteLine(""); + indexHtml.WriteLine(" "); + indexHtml.WriteLine(" RunUO Documentation - Class Overview"); + indexHtml.WriteLine(" "); + indexHtml.WriteLine( + " " + ); + indexHtml.WriteLine("

Back to the index

"); + indexHtml.WriteLine("

Namespaces

"); + + var nspaces = new SortedList>(m_Namespaces); + + foreach (var kvp in nspaces) + { + kvp.Value.Sort(new TypeComparer()); + + SaveNamespace(kvp.Key, kvp.Value, indexHtml); + } + + indexHtml.WriteLine(" "); + indexHtml.WriteLine(""); + } + + private static void SaveNamespace(string name, List types, StreamWriter indexHtml) + { + var fileName = GetFileName("docs/namespaces/", name, ".html"); + + indexHtml.WriteLine(" {1}
", fileName, name); + + using var nsHtml = GetWriter("docs/namespaces/", fileName); + nsHtml.WriteLine(""); + nsHtml.WriteLine(" "); + nsHtml.WriteLine(" RunUO Documentation - Class Overview - {0}", name); + nsHtml.WriteLine(" "); + nsHtml.WriteLine( + " " + ); + nsHtml.WriteLine("

Back to the namespace index

"); + nsHtml.WriteLine("

{0}

", name); + + for (var i = 0; i < types.Count; ++i) + SaveType(types[i], nsHtml, fileName, name); + + nsHtml.WriteLine(" "); + nsHtml.WriteLine(""); + } + + private static void SaveType(TypeInfo info, StreamWriter nsHtml, string nsFileName, string nsName) + { + if (info.m_Declaring == null) + nsHtml.WriteLine($" {info.LinkName("../types/")}
"); + + using var typeHtml = GetWriter(info.FileName); + typeHtml.WriteLine(""); + typeHtml.WriteLine(" "); + typeHtml.WriteLine(" RunUO Documentation - Class Overview - {0}", info.TypeName); + typeHtml.WriteLine(" "); + typeHtml.WriteLine( + " " + ); + typeHtml.WriteLine("

Back to {1}

", nsFileName, nsName); + + if (info.m_Type.IsEnum) + WriteEnum(info, typeHtml); + else + WriteType(info, typeHtml); + + typeHtml.WriteLine(" "); + typeHtml.WriteLine(""); + } + + public static void FormatGeneric(Type type, out string typeName, out string fileName, out string linkName) + { + string name = null; + string fnam = null; + string link = null; + + if (type.IsGenericType) + { + var index = type.Name.IndexOf('`'); + + if (index > 0) + { + var rootType = type.Name.Substring(0, index); + + var nameBuilder = new StringBuilder(rootType); + var fnamBuilder = new StringBuilder($"docs/types/{SanitizeType(rootType)}"); + StringBuilder linkBuilder; + linkBuilder = DontLink(type) + ? new StringBuilder($"{rootType}") + : new StringBuilder($"{rootType}"); + + nameBuilder.Append("<"); + fnamBuilder.Append("-"); + linkBuilder.Append("<"); + + var typeArguments = type.GetGenericArguments(); + + for (var i = 0; i < typeArguments.Length; i++) + { + if (i != 0) + { + nameBuilder.Append(','); + fnamBuilder.Append(','); + linkBuilder.Append(','); + } + + var sanitizedName = SanitizeType(typeArguments[i].Name); + var aliasedName = AliasForName(sanitizedName); + + nameBuilder.Append(sanitizedName); + fnamBuilder.Append("T"); + if (DontLink(typeArguments[i])) + linkBuilder.Append($"{aliasedName}"); + else + linkBuilder.Append( + $"{aliasedName}" + ); + } + + nameBuilder.Append(">"); + fnamBuilder.Append("-"); + linkBuilder.Append(">"); + + name = nameBuilder.ToString(); + fnam = fnamBuilder.ToString(); + link = linkBuilder.ToString(); + } + } + + typeName = name ?? type.Name; + + fileName = fnam == null ? $"docs/types/{SanitizeType(type.Name)}.html" : $"{fnam}.html"; + + if (link == null) + linkName = DontLink(type) + ? $"{SanitizeType(type.Name)}" + : $"{SanitizeType(type.Name)}"; + else + linkName = link; + + // Console.WriteLine( typeName+":"+fileName+":"+linkName ); + } + + public static string SanitizeType(string name) + { + var anonymousType = name.Contains("<"); + var sb = new StringBuilder(name); + for (var i = 0; i < ReplaceChars.Length; ++i) + sb.Replace(ReplaceChars[i], '-'); + + if (anonymousType) return $"(Anonymous-Type){sb}"; + return sb.ToString(); + } + + public static string AliasForName(string name) + { + for (var i = 0; i < m_AliasLength; ++i) + if (m_Aliases[i, 0] == name) + return m_Aliases[i, 1]; + return name; + } + + /* + // For stuff we don't want to links to + private static string[] m_DontLink = new string[] + { + "List", + "Stack", + "Queue", + "Dictionary", + "LinkedList", + "SortedList", + "SortedDictionary", + "IComparable", + "IComparer", + "ICloneable", + "Type" + }; + + public static bool DontLink( string name ) + { + foreach( string dontLink in m_DontLink ) + if (dontLink == name ) return true; + return false; + } + */ + public static bool DontLink(Type type) + { + if (type.Name == "T" || string.IsNullOrEmpty(type.Namespace) || m_Namespaces == null) + return true; + + if (type.Namespace.StartsWith("Server")) + return false; + + return !m_Namespaces.ContainsKey(type.Namespace); + } + + public static string GetFileName(string root, string name, string ext) + { + if (name.IndexOfAny(ReplaceChars) >= 0) + { + var sb = new StringBuilder(name); + + for (var i = 0; i < ReplaceChars.Length; ++i) sb.Replace(ReplaceChars[i], '-'); + + name = sb.ToString(); + } + + var index = 0; + var file = string.Concat(name, ext); + + while (File.Exists(Path.Combine(root, file))) file = string.Concat(name, ++index, ext); + + return file; + } + + private static void EnsureDirectory(string path) + { + path = Path.Combine(m_RootDirectory, path); + + if (!Directory.Exists(path)) + Directory.CreateDirectory(path); + } + + private static void DeleteDirectory(string path) + { + path = Path.Combine(m_RootDirectory, path); + + if (Directory.Exists(path)) + Directory.Delete(path, true); + } + + private static StreamWriter GetWriter(string root, string name) => + new StreamWriter(Path.Combine(Path.Combine(m_RootDirectory, root), name)); + + private static StreamWriter GetWriter(string path) => new StreamWriter(Path.Combine(m_RootDirectory, path)); + + public static string GetPair(Type varType, string name, bool ignoreRef) + { + var prepend = ""; + var append = new StringBuilder(); + + var realType = varType; + + if (varType.IsByRef) + { + if (!ignoreRef) + prepend = RefString; + + realType = varType.GetElementType(); + } + + if (realType?.IsPointer == true) + { + if (realType.IsArray) + { + append.Append('*'); + + do + { + append.Append('['); + + for (var i = 1; i < realType.GetArrayRank(); ++i) + append.Append(','); + + append.Append(']'); + + realType = realType.GetElementType(); + } while (realType?.IsArray == true); + + append.Append(' '); + } + else + { + realType = realType.GetElementType(); + append.Append(" *"); + } + } + else if (realType?.IsArray == true) + { + do + { + append.Append('['); + + for (var i = 1; i < realType.GetArrayRank(); ++i) + append.Append(','); + + append.Append(']'); + + realType = realType.GetElementType(); + } while (realType?.IsArray == true); + + append.Append(' '); + } + else + { + append.Append(' '); + } + + var fullName = realType?.FullName ?? "(-null-)"; + string aliased = null; // = realType.Name; + + if (realType != null && m_Types.TryGetValue(realType, out var info)) + { + aliased = $"{info.LinkName(null)}"; + } + else + { + if (realType?.IsGenericType == true) + { + FormatGeneric(realType, out _, out _, out var linkName); + aliased = linkName.Replace("@directory@", null); + } + else + { + for (var i = 0; i < m_AliasLength; ++i) + if (m_Aliases[i, 0] == fullName) + { + aliased = m_Aliases[i, 1]; + break; + } + } + + aliased ??= realType?.Name ?? ""; + } + + return string.Concat(prepend, aliased, append, name); + } + + private static bool Document() + { + try + { + DeleteDirectory("docs/"); + } + catch + { + return false; + } + + EnsureDirectory("docs/"); + EnsureDirectory("docs/namespaces/"); + EnsureDirectory("docs/types/"); + EnsureDirectory("docs/bods/"); + + GenerateStyles(); + GenerateIndex(); + + DocumentCommands(); + DocumentKeywords(); + DocumentBodies(); + + DocumentBulkOrders(); + + m_Types = new Dictionary(); + m_Namespaces = new Dictionary>(); + + var assemblies = new List { Core.Assembly }; + + foreach (var asm in AssemblyHandler.Assemblies) + assemblies.Add(asm); + + var asms = assemblies.ToArray(); + + for (var i = 0; i < asms.Length; ++i) + LoadTypes(asms[i], asms); + + DocumentLoadedTypes(); + DocumentConstructibleObjects(); + + return true; + } + + private static void AddIndexLink(StreamWriter html, string filePath, string label, string desc) + { + html.WriteLine("

{2}

", filePath, desc, label); + } + + private static void GenerateStyles() + { + using var css = GetWriter("docs/", "styles.css"); + css.WriteLine("body { background-color: #FFFFFF; font-family: verdana, arial; font-size: 11px; }"); + css.WriteLine("a { color: #28435E; }"); + css.WriteLine("a:hover { color: #4878A9; }"); + css.WriteLine("td.header { background-color: #9696AA; font-weight: bold; font-size: 12px; }"); + css.WriteLine("td.lentry { background-color: #D7D7EB; width: 10%; }"); + css.WriteLine("td.rentry { background-color: #FFFFFF; width: 90%; }"); + css.WriteLine("td.entry { background-color: #FFFFFF; }"); + css.WriteLine("td { font-size: 11px; }"); + css.WriteLine(".tbl-border { background-color: #46465A; }"); + + css.WriteLine("td.ir {{ background-color: #{0:X6}; }}", Iron); + css.WriteLine("td.du {{ background-color: #{0:X6}; }}", DullCopper); + css.WriteLine("td.sh {{ background-color: #{0:X6}; }}", ShadowIron); + css.WriteLine("td.co {{ background-color: #{0:X6}; }}", Copper); + css.WriteLine("td.br {{ background-color: #{0:X6}; }}", Bronze); + css.WriteLine("td.go {{ background-color: #{0:X6}; }}", Gold); + css.WriteLine("td.ag {{ background-color: #{0:X6}; }}", Agapite); + css.WriteLine("td.ve {{ background-color: #{0:X6}; }}", Verite); + css.WriteLine("td.va {{ background-color: #{0:X6}; }}", Valorite); + + css.WriteLine("td.cl {{ background-color: #{0:X6}; }}", Cloth); + css.WriteLine("td.pl {{ background-color: #{0:X6}; }}", Plain); + css.WriteLine("td.sp {{ background-color: #{0:X6}; }}", Core.AOS ? SpinedAOS : SpinedLBR); + css.WriteLine("td.ho {{ background-color: #{0:X6}; }}", Core.AOS ? HornedAOS : HornedLBR); + css.WriteLine("td.ba {{ background-color: #{0:X6}; }}", Core.AOS ? BarbedAOS : BarbedLBR); + } + + private static void GenerateIndex() + { + using var html = GetWriter("docs/", "index.html"); + html.WriteLine(""); + html.WriteLine(" "); + html.WriteLine(" RunUO Documentation - Index"); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + + AddIndexLink( + html, + "commands.html", + "Commands", + "Every available command. This contains command name, usage, aliases, and description." + ); + AddIndexLink( + html, + "objects.html", + "Constructible Objects", + "Every constructible item or npc. This contains object name and usage. Hover mouse over parameters to see type description." + ); + AddIndexLink( + html, + "keywords.html", + "Speech Keywords", + "Lists speech keyword numbers and associated match patterns. These are used in some scripts for multi-language matching of client speech." + ); + AddIndexLink( + html, + "bodies.html", + "Body List", + "Every usable body number and name. Table is generated from a UO:3D client datafile. If you do not have UO:3D installed, this may be blank." + ); + AddIndexLink( + html, + "overview.html", + "Class Overview", + "Scripting reference. Contains every class type and contained methods in the core and scripts." + ); + AddIndexLink( + html, + "bods/bod_smith_rewards.html", + "Bulk Order Rewards: Smithing", + "Reference table for large and small smithing bulk order deed rewards." + ); + AddIndexLink( + html, + "bods/bod_tailor_rewards.html", + "Bulk Order Rewards: Tailoring", + "Reference table for large and small tailoring bulk order deed rewards." + ); + + html.WriteLine(" "); + html.WriteLine(""); + } + + private static void DocumentBulkOrders() + { + using (var html = GetWriter("docs/bods/", "bod_smith_rewards.html")) + { + html.WriteLine(""); + html.WriteLine(" "); + html.WriteLine(" RunUO Documentation - Bulk Orders - Smith Rewards"); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + + SmallBOD sbod = new SmallSmithBOD(); + + sbod.Type = typeof(Katana); + sbod.Material = BulkMaterialType.None; + sbod.AmountMax = 10; + + WriteSmithBODHeader(html, "(Small) Weapons"); + sbod.RequireExceptional = false; + DocumentSmithBOD(html, sbod.ComputeRewards(true), "10, 15, 20: Normal", sbod.Material); + sbod.RequireExceptional = true; + DocumentSmithBOD(html, sbod.ComputeRewards(true), "10, 15, 20: Exceptional", sbod.Material); + WriteSmithBODFooter(html); + + html.WriteLine("

"); + html.WriteLine("

"); + + sbod.Type = typeof(PlateArms); + + WriteSmithBODHeader(html, "(Small) Armor: Normal"); + + sbod.RequireExceptional = false; + for (var mat = BulkMaterialType.None; mat <= BulkMaterialType.Valorite; ++mat) + { + sbod.Material = mat; + sbod.AmountMax = 10; + DocumentSmithBOD(html, sbod.ComputeRewards(true), "10, 15, 20", sbod.Material); + } + + WriteSmithBODFooter(html); + + html.WriteLine("

"); + + WriteSmithBODHeader(html, "(Small) Armor: Exceptional"); + + sbod.RequireExceptional = true; + for (var mat = BulkMaterialType.None; mat <= BulkMaterialType.Valorite; ++mat) + { + sbod.Material = mat; + + for (var amt = 15; amt <= 20; amt += 5) + { + sbod.AmountMax = amt; + DocumentSmithBOD(html, sbod.ComputeRewards(true), amt == 20 ? "20" : "10, 15", sbod.Material); + } + } + + WriteSmithBODFooter(html); + + html.WriteLine("

"); + html.WriteLine("

"); + + sbod.Delete(); + + WriteSmithLBOD(html, "Ringmail", LargeBulkEntry.LargeRing); + WriteSmithLBOD(html, "Chainmail", LargeBulkEntry.LargeChain); + WriteSmithLBOD(html, "Platemail", LargeBulkEntry.LargePlate); + + html.WriteLine(" "); + html.WriteLine(""); + } + + using (var html = GetWriter("docs/bods/", "bod_tailor_rewards.html")) + { + html.WriteLine(""); + html.WriteLine(" "); + html.WriteLine(" RunUO Documentation - Bulk Orders - Tailor Rewards"); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + + SmallBOD sbod = new SmallTailorBOD(); + + WriteTailorBODHeader(html, "Small Bulk Order"); + + html.WriteLine(" "); + html.WriteLine(" Regular: 10, 15"); + html.WriteLine(" "); + + sbod.AmountMax = 10; + sbod.RequireExceptional = false; + + sbod.Type = typeof(SkullCap); + sbod.Material = BulkMaterialType.None; + DocumentTailorBOD(html, sbod.ComputeRewards(true), "10, 15", sbod.Material, sbod.Type); + + sbod.Type = typeof(LeatherCap); + for (var mat = BulkMaterialType.None; mat <= BulkMaterialType.Barbed; ++mat) + { + if (mat >= BulkMaterialType.DullCopper && mat <= BulkMaterialType.Valorite) + continue; + + sbod.Material = mat; + DocumentTailorBOD(html, sbod.ComputeRewards(true), "10, 15", sbod.Material, sbod.Type); + } + + html.WriteLine(" "); + html.WriteLine(" Regular: 20"); + html.WriteLine(" "); + + sbod.AmountMax = 20; + sbod.RequireExceptional = false; + + sbod.Type = typeof(SkullCap); + sbod.Material = BulkMaterialType.None; + DocumentTailorBOD(html, sbod.ComputeRewards(true), "20", sbod.Material, sbod.Type); + + sbod.Type = typeof(LeatherCap); + for (var mat = BulkMaterialType.None; mat <= BulkMaterialType.Barbed; ++mat) + { + if (mat >= BulkMaterialType.DullCopper && mat <= BulkMaterialType.Valorite) + continue; + + sbod.Material = mat; + DocumentTailorBOD(html, sbod.ComputeRewards(true), "20", sbod.Material, sbod.Type); + } + + html.WriteLine(" "); + html.WriteLine( + " Exceptional: 10, 15" + ); + html.WriteLine(" "); + + sbod.AmountMax = 10; + sbod.RequireExceptional = true; + + sbod.Type = typeof(SkullCap); + sbod.Material = BulkMaterialType.None; + DocumentTailorBOD(html, sbod.ComputeRewards(true), "10, 15", sbod.Material, sbod.Type); + + sbod.Type = typeof(LeatherCap); + for (var mat = BulkMaterialType.None; mat <= BulkMaterialType.Barbed; ++mat) + { + if (mat >= BulkMaterialType.DullCopper && mat <= BulkMaterialType.Valorite) + continue; + + sbod.Material = mat; + DocumentTailorBOD(html, sbod.ComputeRewards(true), "10, 15", sbod.Material, sbod.Type); + } + + html.WriteLine(" "); + html.WriteLine(" Exceptional: 20"); + html.WriteLine(" "); + + sbod.AmountMax = 20; + sbod.RequireExceptional = true; + + sbod.Type = typeof(SkullCap); + sbod.Material = BulkMaterialType.None; + DocumentTailorBOD(html, sbod.ComputeRewards(true), "20", sbod.Material, sbod.Type); + + sbod.Type = typeof(LeatherCap); + for (var mat = BulkMaterialType.None; mat <= BulkMaterialType.Barbed; ++mat) + { + if (mat >= BulkMaterialType.DullCopper && mat <= BulkMaterialType.Valorite) + continue; + + sbod.Material = mat; + DocumentTailorBOD(html, sbod.ComputeRewards(true), "20", sbod.Material, sbod.Type); + } + + WriteTailorBODFooter(html); + + html.WriteLine("

"); + html.WriteLine("

"); + + sbod.Delete(); + + WriteTailorLBOD(html, "Large Bulk Order: 4-part", LargeBulkEntry.Gypsy, true, true); + WriteTailorLBOD(html, "Large Bulk Order: 5-part", LargeBulkEntry.TownCrier, true, true); + WriteTailorLBOD(html, "Large Bulk Order: 6-part", LargeBulkEntry.MaleLeatherSet, false, true); + + html.WriteLine(" "); + html.WriteLine(""); + } + } + + private static void WriteTailorLBOD( + StreamWriter html, string name, SmallBulkEntry[] entries, bool expandCloth, + bool expandPlain + ) + { + WriteTailorBODHeader(html, name); + + LargeBOD lbod = new LargeTailorBOD(); + + lbod.Entries = LargeBulkEntry.ConvertEntries(lbod, entries); + + var type = entries[0].Type; + + var showCloth = !(type.IsSubclassOf(typeof(BaseArmor)) || type.IsSubclassOf(typeof(BaseShoes))); + + html.WriteLine(" "); + html.WriteLine(" Regular"); + html.WriteLine(" "); + + lbod.RequireExceptional = false; + lbod.AmountMax = 10; + + if (showCloth) + { + lbod.Material = BulkMaterialType.None; + + if (expandCloth) + { + lbod.AmountMax = 10; + DocumentTailorBOD(html, lbod.ComputeRewards(true), "10, 15", lbod.Material, type); + lbod.AmountMax = 20; + DocumentTailorBOD(html, lbod.ComputeRewards(true), "20", lbod.Material, type); + } + else + { + lbod.AmountMax = 10; + DocumentTailorBOD(html, lbod.ComputeRewards(true), "10, 15, 20", lbod.Material, type); + } + } + + lbod.Material = BulkMaterialType.None; + + if (expandPlain) + { + lbod.AmountMax = 10; + DocumentTailorBOD(html, lbod.ComputeRewards(true), "10, 15, 20", lbod.Material, typeof(LeatherCap)); + lbod.AmountMax = 20; + DocumentTailorBOD(html, lbod.ComputeRewards(true), "20", lbod.Material, typeof(LeatherCap)); + } + else + { + lbod.AmountMax = 10; + DocumentTailorBOD(html, lbod.ComputeRewards(true), "10, 15, 20", lbod.Material, typeof(LeatherCap)); + } + + for (var mat = BulkMaterialType.Spined; mat <= BulkMaterialType.Barbed; ++mat) + { + lbod.Material = mat; + lbod.AmountMax = 10; + DocumentTailorBOD(html, lbod.ComputeRewards(true), "10, 15", lbod.Material, type); + lbod.AmountMax = 20; + DocumentTailorBOD(html, lbod.ComputeRewards(true), "20", lbod.Material, type); + } + + html.WriteLine(" "); + html.WriteLine(" Exceptional"); + html.WriteLine(" "); + + lbod.RequireExceptional = true; + lbod.AmountMax = 10; + + if (showCloth) + { + lbod.Material = BulkMaterialType.None; + + if (expandCloth) + { + lbod.AmountMax = 10; + DocumentTailorBOD(html, lbod.ComputeRewards(true), "10, 15", lbod.Material, type); + lbod.AmountMax = 20; + DocumentTailorBOD(html, lbod.ComputeRewards(true), "20", lbod.Material, type); + } + else + { + lbod.AmountMax = 10; + DocumentTailorBOD(html, lbod.ComputeRewards(true), "10, 15, 20", lbod.Material, type); + } + } + + lbod.Material = BulkMaterialType.None; + + if (expandPlain) + { + lbod.AmountMax = 10; + DocumentTailorBOD(html, lbod.ComputeRewards(true), "10, 15, 20", lbod.Material, typeof(LeatherCap)); + lbod.AmountMax = 20; + DocumentTailorBOD(html, lbod.ComputeRewards(true), "20", lbod.Material, typeof(LeatherCap)); + } + else + { + lbod.AmountMax = 10; + DocumentTailorBOD(html, lbod.ComputeRewards(true), "10, 15, 20", lbod.Material, typeof(LeatherCap)); + } + + for (var mat = BulkMaterialType.Spined; mat <= BulkMaterialType.Barbed; ++mat) + { + lbod.Material = mat; + lbod.AmountMax = 10; + DocumentTailorBOD(html, lbod.ComputeRewards(true), "10, 15", lbod.Material, type); + lbod.AmountMax = 20; + DocumentTailorBOD(html, lbod.ComputeRewards(true), "20", lbod.Material, type); + } + + WriteTailorBODFooter(html); + + html.WriteLine("

"); + html.WriteLine("

"); + } + + private static void WriteTailorBODHeader(StreamWriter html, string title) + { + html.WriteLine(" "); + html.WriteLine("
"); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" ", title); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine(" "); + } + + private static void WriteTailorBODFooter(StreamWriter html) + { + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine( + " " + ); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine("
{0}
\"Colored
\"Colored
\"Colored
\"Colored
\"Colored
\"Colored
Power Scrolls
\"Small
\"Medium
\"Light
\"Dark
\"Brown
\"Polar
\"Clothing
Runic Kits
+5
+10
+15
+20
\"Runic
\"Runic
\"Runic
 
\"Colored
\"Colored
\"Colored
\"Colored
\"Colored
\"Colored
+5
+10
+15
+20
\"Small
\"Medium
\"Light
\"Dark
\"Brown
\"Polar
\"Clothing
\"Runic
\"Runic
\"Runic
Power Scrolls
Runic Kits
"); + } + + private static void DocumentTailorBOD( + StreamWriter html, List items, string amt, BulkMaterialType material, + Type type + ) + { + var rewards = new bool[20]; + + for (var i = 0; i < items.Count; ++i) + { + var item = items[i].Construct(); + + if (item is Sandals) + { + rewards[5] = true; + } + else if (item is SmallStretchedHideEastDeed || item is SmallStretchedHideSouthDeed) + { + rewards[10] = rewards[11] = true; + } + else if (item is MediumStretchedHideEastDeed || item is MediumStretchedHideSouthDeed) + { + rewards[10] = rewards[11] = true; + } + else if (item is LightFlowerTapestryEastDeed || item is LightFlowerTapestrySouthDeed) + { + rewards[12] = rewards[13] = true; + } + else if (item is DarkFlowerTapestryEastDeed || item is DarkFlowerTapestrySouthDeed) + { + rewards[12] = rewards[13] = true; + } + else if (item is BrownBearRugEastDeed || item is BrownBearRugSouthDeed) + { + rewards[14] = rewards[15] = true; + } + else if (item is PolarBearRugEastDeed || item is PolarBearRugSouthDeed) + { + rewards[14] = rewards[15] = true; + } + else if (item is ClothingBlessDeed) + { + rewards[16] = true; + } + else if (item is PowerScroll ps) + { + if (ps.Value == 105.0) + rewards[6] = true; + else if (ps.Value == 110.0) + rewards[7] = true; + else if (ps.Value == 115.0) + rewards[8] = true; + else if (ps.Value == 120.0) + rewards[9] = true; + } + else if (item is UncutCloth) + { + if (item.Hue == 0x483 || item.Hue == 0x48C || item.Hue == 0x488 || item.Hue == 0x48A) + rewards[0] = true; + else if (item.Hue == 0x495 || item.Hue == 0x48B || item.Hue == 0x486 || item.Hue == 0x485) + rewards[1] = true; + else if (item.Hue == 0x48D || item.Hue == 0x490 || item.Hue == 0x48E || item.Hue == 0x491) + rewards[2] = true; + else if (item.Hue == 0x48F || item.Hue == 0x494 || item.Hue == 0x484 || item.Hue == 0x497) + rewards[3] = true; + else + rewards[4] = true; + } + else if (item is RunicSewingKit rkit) + { + rewards[16 + CraftResources.GetIndex(rkit.Resource)] = true; + } + + item.Delete(); + } + + string style = null; + string name = null; + + switch (material) + { + case BulkMaterialType.None: + { + if (type.IsSubclassOf(typeof(BaseArmor)) || type.IsSubclassOf(typeof(BaseShoes))) + { + style = "pl"; + name = "Plain"; + } + else + { + style = "cl"; + name = "Cloth"; + } + + break; + } + case BulkMaterialType.Spined: + style = "sp"; + name = "Spined"; + break; + case BulkMaterialType.Horned: + style = "ho"; + name = "Horned"; + break; + case BulkMaterialType.Barbed: + style = "ba"; + name = "Barbed"; + break; + } + + html.WriteLine(" "); + html.WriteLine( + "  - {0} {1}", + name, + amt + ); + + var index = 0; + + while (index < 20) + if (rewards[index]) + { + html.WriteLine("
X
", style); + ++index; + } + else + { + var count = 0; + + while (index < 20 && !rewards[index]) + { + ++count; + ++index; + + if (index == 5 || index == 6 || index == 10 || index == 17) + break; + } + + html.WriteLine( + "  ", + count * 25, + count == 1 ? "" : $" colspan=\"{count}\"" + ); + } + + html.WriteLine(" "); + } + + private static void WriteSmithLBOD(StreamWriter html, string name, SmallBulkEntry[] entries) + { + LargeBOD lbod = new LargeSmithBOD(); + + lbod.Entries = LargeBulkEntry.ConvertEntries(lbod, entries); + + WriteSmithBODHeader(html, $"(Large) {name}: Normal"); + + lbod.RequireExceptional = false; + for (var mat = BulkMaterialType.None; mat <= BulkMaterialType.Valorite; ++mat) + { + lbod.Material = mat; + lbod.AmountMax = 10; + DocumentSmithBOD(html, lbod.ComputeRewards(true), "10, 15, 20", lbod.Material); + } + + WriteSmithBODFooter(html); + + html.WriteLine("

"); + + WriteSmithBODHeader(html, $"(Large) {name}: Exceptional"); + + lbod.RequireExceptional = true; + for (var mat = BulkMaterialType.None; mat <= BulkMaterialType.Valorite; ++mat) + { + lbod.Material = mat; + + for (var amt = 15; amt <= 20; amt += 5) + { + lbod.AmountMax = amt; + DocumentSmithBOD(html, lbod.ComputeRewards(true), amt == 20 ? "20" : "10, 15", lbod.Material); + } + } + + WriteSmithBODFooter(html); + + html.WriteLine("

"); + html.WriteLine("

"); + } + + private static void WriteSmithBODHeader(StreamWriter html, string title) + { + html.WriteLine(" "); + html.WriteLine("
"); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" ", title); + html.WriteLine( + " " + ); + html.WriteLine(" "); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + } + + private static void WriteSmithBODFooter(StreamWriter html) + { + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine( + " " + ); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine( + " " + ); + html.WriteLine(" "); + html.WriteLine("
{0}
\"Sturdy
Gloves
\"Gargoyles
\"Prospectors
\"Powder
\"Colored
Power Scrolls
Runic Hammers
Ancient Hammers
+1
+3
+5
+5
+10
+15
+20
Du
Sh
Co
Br
Go
Ag
Ve
Va
+10
+15
+30
+60
 
\"Sturdy
+1
 
+3
 
+5
 
\"Gargoyles
\"Prospectors
\"Powder
\"Colored
+5
+10
+15
+20
Du
Sh
Co
Br
Go
Ag
Ve
Va
+10
+15
+30
+60
Gloves
Power Scrolls
Runic Hammers
Ancient Hammers
"); + } + + private static void DocumentSmithBOD( + StreamWriter html, List items, string amt, BulkMaterialType material + ) + { + var rewards = new bool[24]; + + for (var i = 0; i < items.Count; ++i) + { + var item = items[i].Construct(); + + if (item is SturdyPickaxe || item is SturdyShovel) + { + rewards[0] = true; + } + else if (item is LeatherGlovesOfMining) + { + rewards[1] = true; + } + else if (item is StuddedGlovesOfMining) + { + rewards[2] = true; + } + else if (item is RingmailGlovesOfMining) + { + rewards[3] = true; + } + else if (item is GargoylesPickaxe) + { + rewards[4] = true; + } + else if (item is ProspectorsTool) + { + rewards[5] = true; + } + else if (item is PowderOfTemperament) + { + rewards[6] = true; + } + else if (item is ColoredAnvil) + { + rewards[7] = true; + } + else if (item is PowerScroll ps) + { + if (ps.Value == 105.0) + rewards[8] = true; + else if (ps.Value == 110.0) + rewards[9] = true; + else if (ps.Value == 115.0) + rewards[10] = true; + else if (ps.Value == 120.0) + rewards[11] = true; + } + else if (item is RunicHammer rh) + { + rewards[11 + CraftResources.GetIndex(rh.Resource)] = true; + } + else if (item is AncientSmithyHammer ash) + { + if (ash.Bonus == 10) + rewards[20] = true; + else if (ash.Bonus == 15) + rewards[21] = true; + else if (ash.Bonus == 30) + rewards[22] = true; + else if (ash.Bonus == 60) + rewards[23] = true; + } + + item.Delete(); + } + + string style = null; + string name = null; + + switch (material) + { + case BulkMaterialType.None: + style = "ir"; + name = "Iron"; + break; + case BulkMaterialType.DullCopper: + style = "du"; + name = "Dull Copper"; + break; + case BulkMaterialType.ShadowIron: + style = "sh"; + name = "Shadow Iron"; + break; + case BulkMaterialType.Copper: + style = "co"; + name = "Copper"; + break; + case BulkMaterialType.Bronze: + style = "br"; + name = "Bronze"; + break; + case BulkMaterialType.Gold: + style = "go"; + name = "Gold"; + break; + case BulkMaterialType.Agapite: + style = "ag"; + name = "Agapite"; + break; + case BulkMaterialType.Verite: + style = "ve"; + name = "Verite"; + break; + case BulkMaterialType.Valorite: + style = "va"; + name = "Valorite"; + break; + } + + html.WriteLine(" "); + html.WriteLine( + " {0} {1}", + name, + amt + ); + + var index = 0; + + while (index < 24) + if (rewards[index]) + { + html.WriteLine("
X
", style); + ++index; + } + else + { + var count = 0; + + while (index < 24 && !rewards[index]) + { + ++count; + ++index; + + if (index == 4 || index == 8 || index == 12 || index == 20) + break; + } + + html.WriteLine( + "  ", + count * 25, + count == 1 ? "" : $" colspan=\"{count}\"" + ); + } + + html.WriteLine(" "); + } + + public static List LoadBodies() + { + var list = new List(); + + var path = Path.Combine(Core.BaseDirectory, "Data/models.txt"); + + if (File.Exists(path)) + { + using var ip = new StreamReader(path); + string line; + + while ((line = ip.ReadLine()) != null) + { + line = line.Trim(); + + if (line.Length == 0 || line.StartsWith("#")) + continue; + + var split = line.Split('\t'); + + if (split.Length >= 9) + { + Body body = Utility.ToInt32(split[0]); + var type = (ModelBodyType)Utility.ToInt32(split[1]); + var name = split[8]; + + var entry = new BodyEntry(body, type, name); + + if (!list.Contains(entry)) + list.Add(entry); + } + } + } + + return list; + } + + private static void DocumentBodies() + { + var list = LoadBodies(); + + using var html = GetWriter("docs/", "bodies.html"); + html.WriteLine(""); + html.WriteLine(" "); + html.WriteLine(" RunUO Documentation - Body List"); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine("

Back to the index

"); + + if (list.Count > 0) + { + html.WriteLine("

Body List

"); + + list.Sort(new BodyEntrySorter()); + + var lastType = ModelBodyType.Invalid; + + for (var i = 0; i < list.Count; ++i) + { + var entry = list[i]; + var type = entry.BodyType; + + if (type != lastType) + { + if (lastType != ModelBodyType.Invalid) + html.WriteLine("
"); + + lastType = type; + + html.WriteLine(" ", type); + + switch (type) + { + case ModelBodyType.Monsters: + html.WriteLine( + " Monsters | Sea | Animals | Human | Equipment

" + ); + break; + case ModelBodyType.Sea: + html.WriteLine( + " Monsters | Sea | Animals | Human | Equipment

" + ); + break; + case ModelBodyType.Animals: + html.WriteLine( + " Monsters | Sea | Animals | Human | Equipment

" + ); + break; + case ModelBodyType.Human: + html.WriteLine( + " Monsters | Sea | Animals | Human | Equipment

" + ); + break; + case ModelBodyType.Equipment: + html.WriteLine( + " Monsters | Sea | Animals | Human | Equipment

" + ); + break; + } + + html.WriteLine(" "); + html.WriteLine("
"); + html.WriteLine(" "); + html.WriteLine( + " ", + type + ); + } + + html.WriteLine( + " ", + entry.Body.BodyID, + entry.Name + ); + } + + html.WriteLine("
{0}
{0}{1}
"); + } + else + { + html.WriteLine(" This feature requires a UO:3D installation."); + } + + html.WriteLine(" "); + html.WriteLine(""); + } + + private static void DocumentKeywords() + { + var tables = LoadSpeechFile(); + + using var html = GetWriter("docs/", "keywords.html"); + html.WriteLine(""); + html.WriteLine(" "); + html.WriteLine(" RunUO Documentation - Speech Keywords"); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine("

Back to the index

"); + html.WriteLine("

Speech Keywords

"); + + for (var p = 0; p < 1 && p < tables.Count; ++p) + { + var table = tables[p]; + + html.WriteLine(" "); + html.WriteLine("
"); + html.WriteLine(" "); + html.WriteLine(" "); + + var list = new List(table.Values); + list.Sort(new SpeechEntrySorter()); + + for (var i = 0; i < list.Count; ++i) + { + var entry = list[i]; + + html.Write(" "); + } + + html.WriteLine("
NumberText
0x{0:X4}", entry.Index); + + entry.Strings.Sort(); // ( new EnglishPrioStringSorter() ); + + for (var j = 0; j < entry.Strings.Count; ++j) + { + if (j > 0) + html.Write("
"); + + var v = entry.Strings[j]; + + for (var k = 0; k < v.Length; ++k) + { + var c = v[k]; + + if (c == '<') + html.Write("<"); + else if (c == '>') + html.Write(">"); + else if (c == '&') + html.Write("&"); + else if (c == '"') + html.Write("""); + else if (c == '\'') + html.Write("'"); + else if (c >= 0x20 && c < 0x7F) + html.Write(c); + else + html.Write("&#{0};", (int)c); + } + } + + html.WriteLine("
"); + } + + html.WriteLine(" "); + html.WriteLine(""); + } + + private static List> LoadSpeechFile() + { + var tables = new List>(); + var lastIndex = -1; + + Dictionary table = null; + + var path = Core.FindDataFile("speech.mul", false); + + if (File.Exists(path)) + { + using var ip = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); + var bin = new BinaryReader(ip); + + while (bin.PeekChar() >= 0) + { + var index = (bin.ReadByte() << 8) | bin.ReadByte(); + var length = (bin.ReadByte() << 8) | bin.ReadByte(); + var text = Encoding.UTF8.GetString(bin.ReadBytes(length)).Trim(); + + if (text.Length == 0) + continue; + + if (table == null || lastIndex > index) + { + if (index == 0 && text == "*withdraw*") + tables.Insert(0, table = new Dictionary()); + else + tables.Add(table = new Dictionary()); + } + + lastIndex = index; + + if (!table.TryGetValue(index, out var entry)) + table[index] = entry = new SpeechEntry(index); + + entry.Strings.Add(text); + } + } + + return tables; + } + + private static void DocumentCommands() + { + using var html = GetWriter("docs/", "commands.html"); + html.WriteLine(""); + html.WriteLine(" "); + html.WriteLine(" RunUO Documentation - Commands"); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine("

Back to the index

"); + html.WriteLine("

Commands

"); + + var commands = new List(CommandSystem.Entries.Values); + var list = new List(); + + commands.Sort(); + commands.Reverse(); + Clean(commands); + + for (var i = 0; i < commands.Count; ++i) + { + var e = commands[i]; + + var mi = e.Handler.Method; + + var attrs = mi.GetCustomAttributes(typeof(UsageAttribute), false); + + if (attrs.Length == 0) + continue; + + var usage = attrs[0] as UsageAttribute; + + attrs = mi.GetCustomAttributes(typeof(DescriptionAttribute), false); + + if (attrs.Length == 0) + continue; + + if (usage == null || !(attrs[0] is DescriptionAttribute desc)) + continue; + + attrs = mi.GetCustomAttributes(typeof(AliasesAttribute), false); + + var aliases = attrs.Length == 0 ? null : attrs[0] as AliasesAttribute; + + var descString = desc.Description.Replace("<", "<").Replace(">", ">"); + + if (aliases == null) + list.Add(new DocCommandEntry(e.AccessLevel, e.Command, null, usage.Usage, descString)); + else + list.Add(new DocCommandEntry(e.AccessLevel, e.Command, aliases.Aliases, usage.Usage, descString)); + } + + for (var i = 0; i < TargetCommands.AllCommands.Count; ++i) + { + var command = TargetCommands.AllCommands[i]; + + var usage = command.Usage; + var desc = command.Description; + + if (usage == null || desc == null) + continue; + + var cmds = command.Commands; + var cmd = cmds[0]; + var aliases = new string[cmds.Length - 1]; + + for (var j = 0; j < aliases.Length; ++j) + aliases[j] = cmds[j + 1]; + + desc = desc.Replace("<", "<").Replace(">", ">"); + + if (command.Supports != CommandSupport.Single) + { + var sb = new StringBuilder(50 + desc.Length); + + sb.Append("Modifiers: "); + + if ((command.Supports & CommandSupport.Global) != 0) + sb.Append("Global, "); + + if ((command.Supports & CommandSupport.Online) != 0) + sb.Append("Online, "); + + if ((command.Supports & CommandSupport.Region) != 0) + sb.Append("Region, "); + + if ((command.Supports & CommandSupport.Contained) != 0) + sb.Append("Contained, "); + + if ((command.Supports & CommandSupport.Multi) != 0) + sb.Append("Multi, "); + + if ((command.Supports & CommandSupport.Area) != 0) + sb.Append("Area, "); + + if ((command.Supports & CommandSupport.Self) != 0) + sb.Append("Self, "); + + sb.Remove(sb.Length - 2, 2); + sb.Append("
"); + sb.Append(desc); + + desc = sb.ToString(); + } + + list.Add(new DocCommandEntry(command.AccessLevel, cmd, aliases, usage, desc)); + } + + var commandImpls = BaseCommandImplementor.Implementors; + + for (var i = 0; i < commandImpls.Count; ++i) + { + var command = commandImpls[i]; + + var usage = command.Usage; + var desc = command.Description; + + if (usage == null || desc == null) + continue; + + var cmds = command.Accessors; + var cmd = cmds[0]; + var aliases = new string[cmds.Length - 1]; + + for (var j = 0; j < aliases.Length; ++j) + aliases[j] = cmds[j + 1]; + + desc = desc.Replace("<", "<").Replace(">", ">"); + + list.Add(new DocCommandEntry(command.AccessLevel, cmd, aliases, usage, desc)); + } + + list.Sort(new CommandEntrySorter()); + + var last = AccessLevel.Player; + + foreach (var e in list) + { + if (e.AccessLevel != last) + { + if (last != AccessLevel.Player) + html.WriteLine("

"); + + last = e.AccessLevel; + + html.WriteLine(" ", last); + + switch (last) + { + case AccessLevel.Administrator: + html.WriteLine( + " Administrator | Game Master | Counselor | Player

" + ); + break; + case AccessLevel.GameMaster: + html.WriteLine( + " Administrator | Game Master | Counselor | Player

" + ); + break; + case AccessLevel.Seer: + html.WriteLine( + " Administrator | Game Master | Counselor | Player

" + ); + break; + case AccessLevel.Counselor: + html.WriteLine( + " Administrator | Game Master | Counselor | Player

" + ); + break; + case AccessLevel.Player: + html.WriteLine( + " Administrator | Game Master | Counselor | Player

" + ); + break; + } + + html.WriteLine(" "); + html.WriteLine("
"); + html.WriteLine(" "); + html.WriteLine( + " ", + last == AccessLevel.GameMaster ? "Game Master" : last.ToString() + ); + } + + DocumentCommand(html, e); + } + + html.WriteLine("
{0}
"); + html.WriteLine(" "); + html.WriteLine(""); + } + + public static void Clean(List list) + { + for (var i = 0; i < list.Count; ++i) + { + var e = list[i]; + + for (var j = i + 1; j < list.Count; ++j) + { + var c = list[j]; + + if (e.Handler.Method == c.Handler.Method) + { + list.RemoveAt(j); + --j; + } + } + } + } + + private static void DocumentCommand(StreamWriter html, DocCommandEntry e) + { + var usage = e.Usage; + var desc = e.Description; + var aliases = e.Aliases; + + html.Write(" {0}", e.Name); + + if (aliases == null || aliases.Length == 0) + { + html.Write( + "Usage: {0}
{1}", + usage.Replace("<", "<").Replace(">", ">"), + desc + ); + } + else + { + html.Write( + "Usage: {0}
Alias{1}: ", + usage.Replace("<", "<").Replace(">", ">"), + aliases.Length == 1 ? "" : "es" + ); + + for (var i = 0; i < aliases.Length; ++i) + { + if (i != 0) + html.Write(", "); + + html.Write(aliases[i]); + } + + html.Write("
{0}", desc); + } + + html.WriteLine(""); + } + + private static bool IsConstructible(Type t, out bool isItem) => + (isItem = typeofItem.IsAssignableFrom(t)) || typeofMobile.IsAssignableFrom(t); + + private static bool IsConstructible(ConstructorInfo ctor) => ctor.IsDefined(typeof(ConstructibleAttribute), false); + + private static void DocumentConstructibleObjects() + { + var types = new List(m_Types.Values); + types.Sort(new TypeComparer()); + + var items = new List<(Type, ConstructorInfo[])>(); + var mobiles = new List<(Type, ConstructorInfo[])>(); + + for (var i = 0; i < types.Count; ++i) + { + var t = types[i].m_Type; + + if (t.IsAbstract || !IsConstructible(t, out var isItem)) + continue; + + var ctors = t.GetConstructors(); + var anyConstructible = false; + + for (var j = 0; !anyConstructible && j < ctors.Length; ++j) + anyConstructible = IsConstructible(ctors[j]); + + if (anyConstructible) (isItem ? items : mobiles).Add((t, ctors)); + } + + using var html = GetWriter("docs/", "objects.html"); + html.WriteLine(""); + html.WriteLine(" "); + html.WriteLine(" RunUO Documentation - Constructible Objects"); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine("

Back to the index

"); + html.WriteLine( + "

Constructible Items and Mobiles

" + ); + + html.WriteLine(" "); + html.WriteLine(" "); + html.WriteLine("
"); + html.WriteLine(" "); + html.WriteLine(" "); + + items.ForEach( + tuple => + { + var (type, constructors) = tuple; + DocumentConstructibleObject(html, type, constructors); + } + ); + + html.WriteLine("
Item NameUsage


"); + + html.WriteLine("
"); + html.WriteLine(" "); + html.WriteLine("
"); + html.WriteLine(" "); + html.WriteLine(" "); + + mobiles.ForEach( + tuple => + { + var (type, constructors) = tuple; + DocumentConstructibleObject(html, type, constructors); + } + ); + + html.WriteLine("
Mobile NameUsage
"); + + html.WriteLine(" "); + html.WriteLine(""); + } + + private static void DocumentConstructibleObject(StreamWriter html, Type t, ConstructorInfo[] ctors) + { + html.Write(" {0}", t.Name); + + var first = true; + + for (var i = 0; i < ctors.Length; ++i) + { + var ctor = ctors[i]; + + if (!IsConstructible(ctor)) + continue; + + if (!first) + html.Write("
"); + + first = false; + + html.Write("{0}Add {1}", CommandSystem.Prefix, t.Name); + + var parms = ctor.GetParameters(); + + for (var j = 0; j < parms.Length; ++j) + { + html.Write("
{1}", GetTooltipFor(parms[j]), parms[j].Name); + } + } + + html.WriteLine(""); + } + + private static string GetTooltipFor(ParameterInfo param) + { + var paramType = param.ParameterType; + + for (var i = 0; i < m_Tooltips.GetLength(0); ++i) + { + var checkType = (Type)m_Tooltips[i, 0]; + + if (paramType == checkType) + return string.Format((string)m_Tooltips[i, 1], HtmlNewLine); + } + + if (paramType.IsEnum) + { + var sb = new StringBuilder(); + + sb.AppendFormat("Enumeration value or name. Possible named values include:{0}", HtmlNewLine); + + var names = Enum.GetNames(paramType); + + for (var i = 0; i < names.Length; ++i) + sb.AppendFormat("{0}- {1}", HtmlNewLine, names[i]); + + return sb.ToString(); + } + + if (paramType.IsDefined(typeofCustomEnum, false)) + { + var attributes = paramType.GetCustomAttributes(typeofCustomEnum, false); + + if (attributes.Length > 0 && attributes[0] is CustomEnumAttribute attr) + { + var sb = new StringBuilder(); + + sb.AppendFormat("Enumeration value or name. Possible named values include:{0}", HtmlNewLine); + + var names = attr.Names; + + for (var i = 0; i < names.Length; ++i) + sb.AppendFormat("{0}- {1}", HtmlNewLine, names[i]); + + return sb.ToString(); + } + } + else if (paramType == typeofMap) + { + var sb = new StringBuilder(); + + sb.AppendFormat("Enumeration value or name. Possible named values include:{0}", HtmlNewLine); + + var names = Map.GetMapNames(); + + for (var i = 0; i < names.Length; ++i) + sb.AppendFormat("{0}- {1}", HtmlNewLine, names[i]); + + return sb.ToString(); + } + + return ""; + } + + private static void WriteEnum(TypeInfo info, StreamWriter typeHtml) + { + var type = info.m_Type; + + typeHtml.WriteLine("

{0} (Enum)

", info.TypeName); + + var names = Enum.GetNames(type); + + var flags = type.IsDefined(typeof(FlagsAttribute), false); + string format; + + if (flags) + format = " {0:G} = 0x{1:X}{2}
"; + else + format = " {0:G} = {1:D}{2}
"; + + for (var i = 0; i < names.Length; ++i) + { + var value = Enum.Parse(type, names[i]); + + typeHtml.WriteLine(format, names[i], value, i < names.Length - 1 ? "," : ""); + } + } + + private static void WriteType(TypeInfo info, StreamWriter typeHtml) + { + var type = info.m_Type; + + typeHtml.Write("

"); + + var decType = info.m_Declaring; + + if (decType != null) + { + // We are a nested type + + typeHtml.Write('('); + + m_Types.TryGetValue(decType, out var decInfo); + + if (decInfo == null) + typeHtml.Write(decType.Name); + else + // typeHtml.Write( "{1}", decInfo.m_FileName, decInfo.m_TypeName ); + typeHtml.Write(decInfo.LinkName(null)); + + typeHtml.Write(") - "); + } + + typeHtml.Write(info.TypeName); + + var ifaces = info.m_Interfaces; + var baseType = info.m_BaseType; + + var extendCount = 0; + + if (baseType != typeof(object) && baseType != typeof(ValueType) && baseType?.IsPrimitive == false) + { + typeHtml.Write(" : "); + + m_Types.TryGetValue(baseType, out var baseInfo); + + if (baseInfo == null) + typeHtml.Write(baseType.Name); + else + typeHtml.Write($"{baseInfo.LinkName(null)}"); + + ++extendCount; + } + + if (ifaces.Length > 0) + { + if (extendCount == 0) + typeHtml.Write(" : "); + + for (var i = 0; i < ifaces.Length; ++i) + { + var iface = ifaces[i]; + m_Types.TryGetValue(iface, out var ifaceInfo); + + if (extendCount != 0) + typeHtml.Write(", "); + + ++extendCount; + + if (ifaceInfo == null) + { + FormatGeneric(iface, out _, out _, out var linkName); + typeHtml.Write($"{linkName.Replace("@directory@", null)}"); + } + else + { + typeHtml.Write($"{ifaceInfo.LinkName(null)}"); + } + } + } + + typeHtml.WriteLine("

"); + + var derived = info.m_Derived; + + if (derived != null) + { + typeHtml.Write("

Derived Types: "); + + derived.Sort(new TypeComparer()); + + for (var i = 0; i < derived.Count; ++i) + { + var derivedInfo = derived[i]; + + if (i != 0) + typeHtml.Write(", "); + + // typeHtml.Write( "{1}", derivedInfo.m_FileName, derivedInfo.m_TypeName ); + typeHtml.Write($"{derivedInfo.LinkName(null)}"); + } + + typeHtml.WriteLine("

"); + } + + var nested = info.m_Nested; + + if (nested != null) + { + typeHtml.Write("

Nested Types: "); + + nested.Sort(new TypeComparer()); + + for (var i = 0; i < nested.Count; ++i) + { + var nestedInfo = nested[i]; + + if (i != 0) + typeHtml.Write(", "); + + // typeHtml.Write( "{1}", nestedInfo.m_FileName, nestedInfo.m_TypeName ); + typeHtml.Write($"{nestedInfo.LinkName(null)}"); + } + + typeHtml.WriteLine("

"); + } + + var membs = type.GetMembers( + BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | + BindingFlags.Instance | BindingFlags.DeclaredOnly + ); + + Array.Sort(membs, new MemberComparer()); + + for (var i = 0; i < membs.Length; ++i) + { + var mi = membs[i]; + + if (mi is PropertyInfo propertyInfo) + WriteProperty(propertyInfo, typeHtml); + else if (mi is ConstructorInfo constructorInfo) + WriteCtor(info.TypeName, constructorInfo, typeHtml); + else if (mi is MethodInfo methodInfo) + WriteMethod(methodInfo, typeHtml); + } + } + + private static void WriteProperty(PropertyInfo pi, StreamWriter html) + { + html.Write(" "); + + var getMethod = pi.GetGetMethod(); + var setMethod = pi.GetSetMethod(); + + if (getMethod?.IsStatic == true || setMethod?.IsStatic == true) + html.Write(StaticString); + + html.Write(GetPair(pi.PropertyType, pi.Name, false)); + html.Write('('); + + if (pi.CanRead) + html.Write(GetString); + + if (pi.CanWrite) + html.Write(SetString); + + html.WriteLine(" )
"); + } + + private static void WriteCtor(string name, ConstructorInfo ctor, StreamWriter html) + { + if (ctor.IsStatic) + return; + + html.Write(" "); + html.Write(CtorString); + html.Write(name); + html.Write('('); + + var parms = ctor.GetParameters(); + + if (parms.Length > 0) + { + html.Write(' '); + + for (var i = 0; i < parms.Length; ++i) + { + var pi = parms[i]; + + if (i != 0) + html.Write(", "); + + if (pi.IsIn) + html.Write(InString); + else if (pi.IsOut) + html.Write(OutString); + + html.Write(GetPair(pi.ParameterType, pi.Name, pi.IsOut)); + } + + html.Write(' '); + } + + html.WriteLine(")
"); + } + + private static void WriteMethod(MethodInfo mi, StreamWriter html) + { + if (mi.IsSpecialName) + return; + + html.Write(" "); + + if (mi.IsStatic) + html.Write(StaticString); + + if (mi.IsVirtual) + html.Write(VirtString); + + html.Write(GetPair(mi.ReturnType, mi.Name, false)); + html.Write('('); + + var parms = mi.GetParameters(); + + if (parms.Length > 0) + { + html.Write(' '); + + for (var i = 0; i < parms.Length; ++i) + { + var pi = parms[i]; + + if (i != 0) + html.Write(", "); + + if (pi.IsIn) + html.Write(InString); + else if (pi.IsOut) + html.Write(OutString); + + html.Write(GetPair(pi.ParameterType, pi.Name, pi.IsOut)); + } + + html.Write(' '); + } + + html.WriteLine(")
"); + } + + private class MemberComparer : IComparer + { + public int Compare(object x, object y) + { + if (x == y) + return 0; + + var aCtor = x as ConstructorInfo; + var bCtor = y as ConstructorInfo; + + var aProp = x as PropertyInfo; + var bProp = y as PropertyInfo; + + var aMethod = x as MethodInfo; + var bMethod = y as MethodInfo; + + var aStatic = GetStaticFor(aCtor, aProp, aMethod); + var bStatic = GetStaticFor(bCtor, bProp, bMethod); + + if (aStatic && !bStatic) + return -1; + if (!aStatic && bStatic) + return 1; + + var v = 0; + + if (aCtor != null) + { + if (bCtor == null) + v = -1; + } + else if (bCtor != null) + { + v = 1; + } + else if (aProp != null) + { + if (bProp == null) + v = -1; + } + else if (bProp != null) + { + v = 1; + } + + if (v == 0) + v = GetNameFrom(aCtor, aProp, aMethod).CompareTo(GetNameFrom(bCtor, bProp, bMethod)); + + if (v == 0 && aCtor != null && bCtor != null) + v = aCtor.GetParameters().Length.CompareTo(bCtor.GetParameters().Length); + else if (v == 0 && aMethod != null && bMethod != null) + v = aMethod.GetParameters().Length.CompareTo(bMethod.GetParameters().Length); + + return v; + } + + private bool GetStaticFor(ConstructorInfo ctor, PropertyInfo prop, MethodInfo method) + { + if (ctor != null) + return ctor.IsStatic; + if (method != null) + return method.IsStatic; + + if (prop != null) + { + var getMethod = prop.GetGetMethod(); + var setMethod = prop.GetGetMethod(); + + return getMethod?.IsStatic == true || setMethod?.IsStatic == true; + } + + return false; + } + + private string GetNameFrom(ConstructorInfo ctor, PropertyInfo prop, MethodInfo method) => + ctor?.DeclaringType?.Name ?? prop?.Name ?? method?.Name ?? ""; + } + + private class TypeComparer : IComparer + { + public int Compare(TypeInfo x, TypeInfo y) => + x == null && y == null ? 0 : + x == null ? -1 : + y == null ? 1 : + x.TypeName.CompareTo(y.TypeName); + } + + private class TypeInfo + { + public readonly Type m_BaseType; + public readonly Type m_Declaring; + private readonly string m_FileName; + public readonly Type[] m_Interfaces; + private readonly string m_LinkName; + public readonly Type m_Type; + private readonly string m_TypeName; + public List m_Derived, m_Nested; + + public TypeInfo(Type type) + { + m_Type = type; + + m_BaseType = type.BaseType; + m_Declaring = type.DeclaringType; + m_Interfaces = type.GetInterfaces(); + + FormatGeneric(m_Type, out m_TypeName, out m_FileName, out m_LinkName); + } + + public string FileName => m_FileName; + public string TypeName => m_TypeName; + + public string LinkName(string dirRoot) => m_LinkName.Replace("@directory@", dirRoot); + } + + private class SpeechEntry + { + public SpeechEntry(int index) + { + Index = index; + Strings = new List(); + } + + public int Index { get; } + + public List Strings { get; } + } + + private class SpeechEntrySorter : IComparer + { + public int Compare(SpeechEntry x, SpeechEntry y) + { + if (x == null && y == null) return 0; + return x?.Index.CompareTo(y?.Index) ?? 1; + } + } + + public class DocCommandEntry + { + public DocCommandEntry(AccessLevel accessLevel, string name, string[] aliases, string usage, string description) + { + AccessLevel = accessLevel; + Name = name; + Aliases = aliases; + Usage = usage; + Description = description; + } + + public AccessLevel AccessLevel { get; } + + public string Name { get; } + + public string[] Aliases { get; } + + public string Usage { get; } + + public string Description { get; } + } + + public class CommandEntrySorter : IComparer + { + public int Compare(DocCommandEntry a, DocCommandEntry b) + { + if (a == null && b == null) return 0; + + var v = b?.AccessLevel.CompareTo(a?.AccessLevel) ?? 1; + + if (v != 0) + return v; + + return a?.Name.CompareTo(b?.Name) ?? 1; + } + } + } + + public enum ModelBodyType + { + Invalid = -1, + Monsters, + Sea, + Animals, + Human, + Equipment + } + + public class BodyEntry + { + public BodyEntry(Body body, ModelBodyType bodyType, string name) + { + Body = body; + BodyType = bodyType; + Name = name; + } + + public Body Body { get; } + + public ModelBodyType BodyType { get; } + + public string Name { get; } + + public override bool Equals(object obj) + { + var e = obj as BodyEntry; + + return Body == e?.Body && BodyType == e.BodyType && Name == e.Name; + } + + public override int GetHashCode() => Body.BodyID ^ (int)BodyType ^ Name.GetHashCode(); + } + + public class BodyEntrySorter : IComparer + { + public int Compare(BodyEntry a, BodyEntry b) + { + if (a == null && b == null) return 0; + var v = a?.BodyType.CompareTo(b?.BodyType) ?? 1; + + if (v == 0) + v = a?.Body.BodyID.CompareTo(b?.Body.BodyID) ?? 1; + + if (v != 0) + return v; + + return a?.Name.CompareTo(b?.Name) ?? 1; + } + } +} diff --git a/Projects/UOContent/Commands/DragEffects.cs b/Projects/UOContent/Commands/DragEffects.cs index fbe967a21..d67d0d393 100644 --- a/Projects/UOContent/Commands/DragEffects.cs +++ b/Projects/UOContent/Commands/DragEffects.cs @@ -1,26 +1,26 @@ -namespace Server.Commands -{ - public static class DragEffects - { - public static void Initialize() - { - CommandSystem.Register("DragEffects", AccessLevel.Developer, DragEffects_OnCommand); - } - - [Usage("DragEffects [enable=false]")] - [Description("Enables or disables the item drag and drop effects.")] - public static void DragEffects_OnCommand(CommandEventArgs e) - { - if (e.Length == 0) - { - e.Mobile.SendMessage("Drag effects are currently {0}.", Mobile.DragEffects ? "enabled" : "disabled"); - } - else - { - Mobile.DragEffects = e.GetBoolean(0); - - e.Mobile.SendMessage("Drag effects have been {0}.", Mobile.DragEffects ? "enabled" : "disabled"); - } - } - } -} \ No newline at end of file +namespace Server.Commands +{ + public static class DragEffects + { + public static void Initialize() + { + CommandSystem.Register("DragEffects", AccessLevel.Developer, DragEffects_OnCommand); + } + + [Usage("DragEffects [enable=false]")] + [Description("Enables or disables the item drag and drop effects.")] + public static void DragEffects_OnCommand(CommandEventArgs e) + { + if (e.Length == 0) + { + e.Mobile.SendMessage("Drag effects are currently {0}.", Mobile.DragEffects ? "enabled" : "disabled"); + } + else + { + Mobile.DragEffects = e.GetBoolean(0); + + e.Mobile.SendMessage("Drag effects have been {0}.", Mobile.DragEffects ? "enabled" : "disabled"); + } + } + } +} diff --git a/Projects/UOContent/Commands/Dupe.cs b/Projects/UOContent/Commands/Dupe.cs index f1bb47b6b..6bb6fb7b0 100644 --- a/Projects/UOContent/Commands/Dupe.cs +++ b/Projects/UOContent/Commands/Dupe.cs @@ -1,136 +1,147 @@ -using System; -using System.Reflection; -using Server.Items; -using Server.Targeting; -using Server.Utilities; - -namespace Server.Commands -{ - public class Dupe - { - public static void Initialize() - { - CommandSystem.Register("Dupe", AccessLevel.GameMaster, Dupe_OnCommand); - CommandSystem.Register("DupeInBag", AccessLevel.GameMaster, DupeInBag_OnCommand); - } - - [Usage("Dupe [amount]")] - [Description("Dupes a targeted item.")] - private static void Dupe_OnCommand(CommandEventArgs e) - { - int amount = 1; - if (e.Length >= 1) - amount = e.GetInt32(0); - e.Mobile.Target = new DupeTarget(false, amount > 0 ? amount : 1); - e.Mobile.SendMessage("What do you wish to dupe?"); - } - - [Usage("DupeInBag ")] - [Description("Dupes an item at it's current location (count) number of times.")] - private static void DupeInBag_OnCommand(CommandEventArgs e) - { - int amount = 1; - if (e.Length >= 1) - amount = e.GetInt32(0); - - e.Mobile.Target = new DupeTarget(true, amount > 0 ? amount : 1); - e.Mobile.SendMessage("What do you wish to dupe?"); - } - - public static void CopyProperties(Item dest, Item src) - { - PropertyInfo[] props = src.GetType().GetProperties(); - - for (int i = 0; i < props.Length; i++) - try - { - if (props[i].CanRead && props[i].CanWrite) props[i].SetValue(dest, props[i].GetValue(src, null), null); - } - catch - { - // Console.WriteLine( "Denied" ); - } - } - - private class DupeTarget : Target - { - private readonly int m_Amount; - private readonly bool m_InBag; - - public DupeTarget(bool inbag, int amount) - : base(15, false, TargetFlags.None) - { - m_InBag = inbag; - m_Amount = amount; - } - - protected override void OnTarget(Mobile from, object targ) - { - bool done = false; - if (!(targ is Item)) - { - from.SendMessage("You can only dupe items."); - return; - } - - CommandLogging.WriteLine(from, "{0} {1} duping {2} (inBag={3}; amount={4})", from.AccessLevel, - CommandLogging.Format(from), CommandLogging.Format(targ), m_InBag, m_Amount); - - Item copy = (Item)targ; - Container pack = null; - - if (m_InBag) - { - if (copy.Parent is Container cont) - pack = cont; - else if (copy.Parent is Mobile m) - pack = m.Backpack; - } - else - { - pack = from.Backpack; - } - - ConstructorInfo c = ActivatorUtil.GetConstructor(copy.GetType()); - if (c != null) - { - var paramList = c.GetParameters(); - object[] args = paramList.Length == 0 ? null : new object[paramList.Length]; - if (args != null) Array.Fill(args, Type.Missing); - try - { - from.SendMessage("Duping {0}...", m_Amount); - for (int i = 0; i < m_Amount; i++) - if (c.Invoke(args) is Item newItem) - { - CopyProperties(newItem, copy); // copy.Dupe( item, copy.Amount ); - copy.OnAfterDuped(newItem); - newItem.Parent = null; - - if (pack != null) - pack.DropItem(newItem); - else - newItem.MoveToWorld(from.Location, from.Map); - - newItem.InvalidateProperties(); - - CommandLogging.WriteLine(from, "{0} {1} duped {2} creating {3}", from.AccessLevel, - CommandLogging.Format(from), CommandLogging.Format(targ), - CommandLogging.Format(newItem)); - } - - from.SendMessage("Done"); - done = true; - } - catch - { - from.SendMessage("Error!"); - return; - } - } - - if (!done) from.SendMessage("Unable to dupe. Item must have a 0 parameter constructor."); - } - } - } -} +using System; +using Server.Items; +using Server.Targeting; +using Server.Utilities; + +namespace Server.Commands +{ + public class Dupe + { + public static void Initialize() + { + CommandSystem.Register("Dupe", AccessLevel.GameMaster, Dupe_OnCommand); + CommandSystem.Register("DupeInBag", AccessLevel.GameMaster, DupeInBag_OnCommand); + } + + [Usage("Dupe [amount]")] + [Description("Dupes a targeted item.")] + private static void Dupe_OnCommand(CommandEventArgs e) + { + var amount = 1; + if (e.Length >= 1) + amount = e.GetInt32(0); + e.Mobile.Target = new DupeTarget(false, amount > 0 ? amount : 1); + e.Mobile.SendMessage("What do you wish to dupe?"); + } + + [Usage("DupeInBag ")] + [Description("Dupes an item at it's current location (count) number of times.")] + private static void DupeInBag_OnCommand(CommandEventArgs e) + { + var amount = 1; + if (e.Length >= 1) + amount = e.GetInt32(0); + + e.Mobile.Target = new DupeTarget(true, amount > 0 ? amount : 1); + e.Mobile.SendMessage("What do you wish to dupe?"); + } + + public static void CopyProperties(Item dest, Item src) + { + var props = src.GetType().GetProperties(); + + for (var i = 0; i < props.Length; i++) + try + { + if (props[i].CanRead && props[i].CanWrite) props[i].SetValue(dest, props[i].GetValue(src, null), null); + } + catch + { + // Console.WriteLine( "Denied" ); + } + } + + private class DupeTarget : Target + { + private readonly int m_Amount; + private readonly bool m_InBag; + + public DupeTarget(bool inbag, int amount) + : base(15, false, TargetFlags.None) + { + m_InBag = inbag; + m_Amount = amount; + } + + protected override void OnTarget(Mobile from, object targ) + { + var done = false; + if (!(targ is Item)) + { + from.SendMessage("You can only dupe items."); + return; + } + + CommandLogging.WriteLine( + from, + "{0} {1} duping {2} (inBag={3}; amount={4})", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(targ), + m_InBag, + m_Amount + ); + + var copy = (Item)targ; + Container pack = null; + + if (m_InBag) + { + if (copy.Parent is Container cont) + pack = cont; + else if (copy.Parent is Mobile m) + pack = m.Backpack; + } + else + { + pack = from.Backpack; + } + + var c = ActivatorUtil.GetConstructor(copy.GetType()); + if (c != null) + { + var paramList = c.GetParameters(); + var args = paramList.Length == 0 ? null : new object[paramList.Length]; + if (args != null) Array.Fill(args, Type.Missing); + try + { + from.SendMessage("Duping {0}...", m_Amount); + for (var i = 0; i < m_Amount; i++) + if (c.Invoke(args) is Item newItem) + { + CopyProperties(newItem, copy); // copy.Dupe( item, copy.Amount ); + copy.OnAfterDuped(newItem); + newItem.Parent = null; + + if (pack != null) + pack.DropItem(newItem); + else + newItem.MoveToWorld(from.Location, from.Map); + + newItem.InvalidateProperties(); + + CommandLogging.WriteLine( + from, + "{0} {1} duped {2} creating {3}", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(targ), + CommandLogging.Format(newItem) + ); + } + + from.SendMessage("Done"); + done = true; + } + catch + { + from.SendMessage("Error!"); + return; + } + } + + if (!done) from.SendMessage("Unable to dupe. Item must have a 0 parameter constructor."); + } + } + } +} diff --git a/Projects/UOContent/Commands/ExportWSC.cs b/Projects/UOContent/Commands/ExportWSC.cs index 0c76648a1..71e9e203d 100644 --- a/Projects/UOContent/Commands/ExportWSC.cs +++ b/Projects/UOContent/Commands/ExportWSC.cs @@ -1,79 +1,79 @@ -using System.Collections.Generic; -using System.IO; -using Server.Items; - -namespace Server.Commands -{ - public class ExportCommand - { - private const string ExportFile = @"C:\Uo\WorldForge\items.wsc"; - - public static void Initialize() - { - CommandSystem.Register("ExportWSC", AccessLevel.Administrator, Export_OnCommand); - } - - public static void Export_OnCommand(CommandEventArgs e) - { - StreamWriter w = new StreamWriter(ExportFile); - List remove = new List(); - int count = 0; - - e.Mobile.SendMessage("Exporting all static items to \"{0}\"...", ExportFile); - e.Mobile.SendMessage("This will delete all static items in the world. Please make a backup."); - - foreach (Item item in World.Items.Values) - if ((item is Static || item is BaseFloor || item is BaseWall) - && item.RootParent == null) - { - w.WriteLine("SECTION WORLDITEM {0}", count); - w.WriteLine("{"); - w.WriteLine("SERIAL {0}", item.Serial); - w.WriteLine("NAME #"); - w.WriteLine("NAME2 #"); - w.WriteLine("ID {0}", item.ItemID); - w.WriteLine("X {0}", item.X); - w.WriteLine("Y {0}", item.Y); - w.WriteLine("Z {0}", item.Z); - w.WriteLine("COLOR {0}", item.Hue); - w.WriteLine("CONT -1"); - w.WriteLine("TYPE 0"); - w.WriteLine("AMOUNT 1"); - w.WriteLine("WEIGHT 255"); - w.WriteLine("OWNER -1"); - w.WriteLine("SPAWN -1"); - w.WriteLine("VALUE 1"); - w.WriteLine("}"); - w.WriteLine(""); - - count++; - remove.Add(item); - w.Flush(); - } - - w.Close(); - - foreach (Item item in remove) - item.Delete(); - - e.Mobile.SendMessage("Export complete. Exported {0} statics.", count); - } - } -} -/*SECTION WORLDITEM 1 -{ -SERIAL 1073741830 -NAME # -NAME2 # -ID 1709 -X 1439 -Y 1613 -Z 20 -CONT -1 -TYPE 12 -AMOUNT 1 -WEIGHT 25500 -OWNER -1 -SPAWN -1 -VALUE 1 -}*/ +using System.Collections.Generic; +using System.IO; +using Server.Items; + +namespace Server.Commands +{ + public class ExportCommand + { + private const string ExportFile = @"C:\Uo\WorldForge\items.wsc"; + + public static void Initialize() + { + CommandSystem.Register("ExportWSC", AccessLevel.Administrator, Export_OnCommand); + } + + public static void Export_OnCommand(CommandEventArgs e) + { + var w = new StreamWriter(ExportFile); + var remove = new List(); + var count = 0; + + e.Mobile.SendMessage("Exporting all static items to \"{0}\"...", ExportFile); + e.Mobile.SendMessage("This will delete all static items in the world. Please make a backup."); + + foreach (var item in World.Items.Values) + if ((item is Static || item is BaseFloor || item is BaseWall) + && item.RootParent == null) + { + w.WriteLine("SECTION WORLDITEM {0}", count); + w.WriteLine("{"); + w.WriteLine("SERIAL {0}", item.Serial); + w.WriteLine("NAME #"); + w.WriteLine("NAME2 #"); + w.WriteLine("ID {0}", item.ItemID); + w.WriteLine("X {0}", item.X); + w.WriteLine("Y {0}", item.Y); + w.WriteLine("Z {0}", item.Z); + w.WriteLine("COLOR {0}", item.Hue); + w.WriteLine("CONT -1"); + w.WriteLine("TYPE 0"); + w.WriteLine("AMOUNT 1"); + w.WriteLine("WEIGHT 255"); + w.WriteLine("OWNER -1"); + w.WriteLine("SPAWN -1"); + w.WriteLine("VALUE 1"); + w.WriteLine("}"); + w.WriteLine(""); + + count++; + remove.Add(item); + w.Flush(); + } + + w.Close(); + + foreach (var item in remove) + item.Delete(); + + e.Mobile.SendMessage("Export complete. Exported {0} statics.", count); + } + } +} +/*SECTION WORLDITEM 1 +{ +SERIAL 1073741830 +NAME # +NAME2 # +ID 1709 +X 1439 +Y 1613 +Z 20 +CONT -1 +TYPE 12 +AMOUNT 1 +WEIGHT 25500 +OWNER -1 +SPAWN -1 +VALUE 1 +}*/ diff --git a/Projects/UOContent/Commands/Generic/Commands/BaseCommand.cs b/Projects/UOContent/Commands/Generic/Commands/BaseCommand.cs index f44d9ab57..14698fd01 100644 --- a/Projects/UOContent/Commands/Generic/Commands/BaseCommand.cs +++ b/Projects/UOContent/Commands/Generic/Commands/BaseCommand.cs @@ -1,131 +1,131 @@ -using System.Collections.Generic; - -namespace Server.Commands.Generic -{ - public enum ObjectTypes - { - Both, - Items, - Mobiles, - All - } - - public abstract class BaseCommand - { - private readonly List m_Responses = new List(); - private readonly List m_Failures = new List(); - - public bool ListOptimized { get; set; } - - public string[] Commands { get; set; } - - public string Usage { get; set; } - - public string Description { get; set; } - - public AccessLevel AccessLevel { get; set; } - - public ObjectTypes ObjectTypes { get; set; } - - public CommandSupport Supports { get; set; } - - public static bool IsAccessible(Mobile from, object obj) - { - if (from.AccessLevel >= AccessLevel.Administrator || obj == null) - return true; - - Mobile mob = null; - - if (obj is Mobile m) - mob = m; - else if (obj is Item item) - mob = item.RootParent as Mobile; - - return mob == null || mob == from || from.AccessLevel > mob.AccessLevel; - } - - public virtual void ExecuteList(CommandEventArgs e, List list) - { - for (int i = 0; i < list.Count; ++i) - Execute(e, list[i]); - } - - public virtual void Execute(CommandEventArgs e, object obj) - { - } - - public virtual bool ValidateArgs(BaseCommandImplementor impl, CommandEventArgs e) => true; - - public void AddResponse(string message) - { - for (int i = 0; i < m_Responses.Count; ++i) - { - MessageEntry entry = m_Responses[i]; - - if (entry.m_Message == message) - { - ++entry.m_Count; - return; - } - } - - if (m_Responses.Count == 10) - return; - - m_Responses.Add(new MessageEntry(message)); - } - - public void LogFailure(string message) - { - for (int i = 0; i < m_Failures.Count; ++i) - { - MessageEntry entry = m_Failures[i]; - - if (entry.m_Message == message) - { - ++entry.m_Count; - return; - } - } - - if (m_Failures.Count == 10) - return; - - m_Failures.Add(new MessageEntry(message)); - } - - public void Flush(Mobile from, bool flushToLog) - { - if (m_Responses.Count > 0) - for (int i = 0; i < m_Responses.Count; ++i) - { - MessageEntry entry = m_Responses[i]; - - from.SendMessage(entry.ToString()); - - if (flushToLog) - CommandLogging.WriteLine(from, entry.ToString()); - } - else - for (int i = 0; i < m_Failures.Count; ++i) - from.SendMessage(m_Failures[i].ToString()); - - m_Responses.Clear(); - m_Failures.Clear(); - } - - private class MessageEntry - { - public int m_Count; - public readonly string m_Message; - - public MessageEntry(string message) - { - m_Message = message; - m_Count = 1; - } - - public override string ToString() => m_Count > 1 ? $"{m_Message} ({m_Count})" : m_Message; - } - } -} \ No newline at end of file +using System.Collections.Generic; + +namespace Server.Commands.Generic +{ + public enum ObjectTypes + { + Both, + Items, + Mobiles, + All + } + + public abstract class BaseCommand + { + private readonly List m_Failures = new List(); + private readonly List m_Responses = new List(); + + public bool ListOptimized { get; set; } + + public string[] Commands { get; set; } + + public string Usage { get; set; } + + public string Description { get; set; } + + public AccessLevel AccessLevel { get; set; } + + public ObjectTypes ObjectTypes { get; set; } + + public CommandSupport Supports { get; set; } + + public static bool IsAccessible(Mobile from, object obj) + { + if (from.AccessLevel >= AccessLevel.Administrator || obj == null) + return true; + + Mobile mob = null; + + if (obj is Mobile m) + mob = m; + else if (obj is Item item) + mob = item.RootParent as Mobile; + + return mob == null || mob == from || from.AccessLevel > mob.AccessLevel; + } + + public virtual void ExecuteList(CommandEventArgs e, List list) + { + for (var i = 0; i < list.Count; ++i) + Execute(e, list[i]); + } + + public virtual void Execute(CommandEventArgs e, object obj) + { + } + + public virtual bool ValidateArgs(BaseCommandImplementor impl, CommandEventArgs e) => true; + + public void AddResponse(string message) + { + for (var i = 0; i < m_Responses.Count; ++i) + { + var entry = m_Responses[i]; + + if (entry.m_Message == message) + { + ++entry.m_Count; + return; + } + } + + if (m_Responses.Count == 10) + return; + + m_Responses.Add(new MessageEntry(message)); + } + + public void LogFailure(string message) + { + for (var i = 0; i < m_Failures.Count; ++i) + { + var entry = m_Failures[i]; + + if (entry.m_Message == message) + { + ++entry.m_Count; + return; + } + } + + if (m_Failures.Count == 10) + return; + + m_Failures.Add(new MessageEntry(message)); + } + + public void Flush(Mobile from, bool flushToLog) + { + if (m_Responses.Count > 0) + for (var i = 0; i < m_Responses.Count; ++i) + { + var entry = m_Responses[i]; + + from.SendMessage(entry.ToString()); + + if (flushToLog) + CommandLogging.WriteLine(from, entry.ToString()); + } + else + for (var i = 0; i < m_Failures.Count; ++i) + from.SendMessage(m_Failures[i].ToString()); + + m_Responses.Clear(); + m_Failures.Clear(); + } + + private class MessageEntry + { + public readonly string m_Message; + public int m_Count; + + public MessageEntry(string message) + { + m_Message = message; + m_Count = 1; + } + + public override string ToString() => m_Count > 1 ? $"{m_Message} ({m_Count})" : m_Message; + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Commands/Commands.cs b/Projects/UOContent/Commands/Generic/Commands/Commands.cs index c5f1cb897..c5c80a450 100644 --- a/Projects/UOContent/Commands/Generic/Commands/Commands.cs +++ b/Projects/UOContent/Commands/Generic/Commands/Commands.cs @@ -1,1112 +1,1216 @@ -using System; -using System.Collections.Generic; -using Server.Accounting; -using Server.Engines.Help; -using Server.Factions; -using Server.Gumps; -using Server.Items; -using Server.Mobiles; -using Server.Multis; -using Server.Network; -using Server.Spells; - -namespace Server.Commands.Generic -{ - public class TargetCommands - { - public static List AllCommands { get; } = new List(); - - public static void Initialize() - { - Register(new KillCommand(true)); - Register(new KillCommand(false)); - Register(new HideCommand(true)); - Register(new HideCommand(false)); - Register(new KickCommand(true)); - Register(new KickCommand(false)); - Register(new FirewallCommand()); - Register(new TeleCommand()); - Register(new SetCommand()); - Register(new AliasedSetCommand(AccessLevel.GameMaster, "Immortal", "blessed", "true", ObjectTypes.Mobiles)); - Register(new AliasedSetCommand(AccessLevel.GameMaster, "Invul", "blessed", "true", ObjectTypes.Mobiles)); - Register(new AliasedSetCommand(AccessLevel.GameMaster, "Mortal", "blessed", "false", ObjectTypes.Mobiles)); - Register(new AliasedSetCommand(AccessLevel.GameMaster, "NoInvul", "blessed", "false", ObjectTypes.Mobiles)); - Register(new AliasedSetCommand(AccessLevel.GameMaster, "Squelch", "squelched", "true", ObjectTypes.Mobiles)); - Register(new AliasedSetCommand(AccessLevel.GameMaster, "Unsquelch", "squelched", "false", ObjectTypes.Mobiles)); - - Register(new AliasedSetCommand(AccessLevel.GameMaster, "ShaveHair", "HairItemID", "0", ObjectTypes.Mobiles)); - Register(new AliasedSetCommand(AccessLevel.GameMaster, "ShaveBeard", "FacialHairItemID", "0", - ObjectTypes.Mobiles)); - - Register(new GetCommand()); - Register(new GetTypeCommand()); - Register(new DeleteCommand()); - Register(new RestockCommand()); - Register(new DismountCommand()); - Register(new AddCommand()); - Register(new AddToPackCommand()); - Register(new TellCommand(true)); - Register(new TellCommand(false)); - Register(new PrivSoundCommand()); - Register(new IncreaseCommand()); - Register(new OpenBrowserCommand()); - Register(new CountCommand()); - Register(new InterfaceCommand()); - Register(new RefreshHouseCommand()); - Register(new ConditionCommand()); - Register(new FactionKickCommand(FactionKickType.Kick)); - Register(new FactionKickCommand(FactionKickType.Ban)); - Register(new FactionKickCommand(FactionKickType.Unban)); - Register(new BringToPackCommand()); - Register(new TraceLockdownCommand()); - Register(new LocationCommand()); - } - - public static void Register(BaseCommand command) - { - AllCommands.Add(command); - - List impls = BaseCommandImplementor.Implementors; - - for (int i = 0; i < impls.Count; ++i) - { - BaseCommandImplementor impl = impls[i]; - - if ((command.Supports & impl.SupportRequirement) != 0) - impl.Register(command); - } - } - } - - public class ConditionCommand : BaseCommand - { - public ConditionCommand() - { - AccessLevel = AccessLevel.GameMaster; - Supports = CommandSupport.Simple | CommandSupport.Complex | CommandSupport.Self; - Commands = new[] { "Condition" }; - ObjectTypes = ObjectTypes.All; - Usage = "Condition "; - Description = "Checks that the given condition matches a targeted object."; - ListOptimized = true; - } - - public override void ExecuteList(CommandEventArgs e, List list) - { - try - { - string[] args = e.Arguments; - ObjectConditional condition = ObjectConditional.Parse(e.Mobile, ref args); - - for (int i = 0; i < list.Count; ++i) - if (condition.CheckCondition(list[i])) - AddResponse("True - that object matches the condition."); - else - AddResponse("False - that object does not match the condition."); - } - catch (Exception ex) - { - e.Mobile.SendMessage(ex.Message); - } - } - } - - public class BringToPackCommand : BaseCommand - { - public BringToPackCommand() - { - AccessLevel = AccessLevel.GameMaster; - Supports = CommandSupport.AllItems; - Commands = new[] { "BringToPack" }; - ObjectTypes = ObjectTypes.Items; - Usage = "BringToPack"; - Description = "Brings a targeted item to your backpack."; - } - - public override void Execute(CommandEventArgs e, object obj) - { - if (obj is Item item) - { - if (e.Mobile.PlaceInBackpack(item)) - AddResponse("The item has been placed in your backpack."); - else - AddResponse("Your backpack could not hold the item."); - } - } - } - - public class RefreshHouseCommand : BaseCommand - { - public RefreshHouseCommand() - { - AccessLevel = AccessLevel.GameMaster; - Supports = CommandSupport.Simple; - Commands = new[] { "RefreshHouse" }; - ObjectTypes = ObjectTypes.Items; - Usage = "RefreshHouse"; - Description = "Refreshes a targeted house sign."; - } - - public override void Execute(CommandEventArgs e, object obj) - { - if (obj is HouseSign sign) - { - BaseHouse house = sign.Owner; - - if (house == null) - { - LogFailure("That sign has no house attached."); - } - else - { - house.RefreshDecay(); - AddResponse("The house has been refreshed."); - } - } - else - { - LogFailure("That is not a house sign."); - } - } - } - - public class CountCommand : BaseCommand - { - public CountCommand() - { - AccessLevel = AccessLevel.GameMaster; - Supports = CommandSupport.Complex; - Commands = new[] { "Count" }; - ObjectTypes = ObjectTypes.All; - Usage = "Count"; - Description = - "Counts the number of objects that a command modifier would use. Generally used with condition arguments."; - ListOptimized = true; - } - - public override void ExecuteList(CommandEventArgs e, List list) - { - if (list.Count == 1) - AddResponse("There is one matching object."); - else - AddResponse($"There are {list.Count} matching objects."); - } - } - - public class OpenBrowserCommand : BaseCommand - { - public OpenBrowserCommand() - { - AccessLevel = AccessLevel.GameMaster; - Supports = CommandSupport.AllMobiles; - Commands = new[] { "OpenBrowser", "OB" }; - ObjectTypes = ObjectTypes.Mobiles; - Usage = "OpenBrowser "; - Description = "Opens the web browser of a targeted player to a specified url."; - } - - public static void OpenBrowser_Callback(Mobile from, bool okay, Mobile gm, string url, bool echo) - { - if (okay) - { - if (echo) - gm.SendMessage("{0} : has opened their web browser to : {1}", from.Name, url); - - from.LaunchBrowser(url); - } - else - { - if (echo) - gm.SendMessage("{0} : has chosen not to open their web browser to : {1}", from.Name, url); - - from.SendMessage("You have chosen not to open your web browser."); - } - } - - public void Execute(CommandEventArgs e, object obj, bool echo) - { - if (e.Length == 1) - { - Mobile mob = (Mobile)obj; - Mobile from = e.Mobile; - - if (mob.Player) - { - NetState ns = mob.NetState; - - if (ns == null) - { - LogFailure("That player is not online."); - } - else - { - string url = e.GetString(0); - - CommandLogging.WriteLine(from, "{0} {1} requesting to open web browser of {2} to {3}", - from.AccessLevel, CommandLogging.Format(from), CommandLogging.Format(mob), url); - - if (echo) - AddResponse("Awaiting user confirmation..."); - else - AddResponse("Open web browser request sent."); - - mob.SendGump(new WarningGump(1060637, 30720, - $"A game master is requesting to open your web browser to the following URL:
{url}", 0xFFC000, - 320, 240, okay => OpenBrowser_Callback(mob, okay, from, url, echo))); - } - } - else - { - LogFailure("That is not a player."); - } - } - else - { - LogFailure("Format: OpenBrowser "); - } - } - - public override void Execute(CommandEventArgs e, object obj) - { - Execute(e, obj, true); - } - - public override void ExecuteList(CommandEventArgs e, List list) - { - for (int i = 0; i < list.Count; ++i) - Execute(e, list[i], false); - } - } - - public class IncreaseCommand : BaseCommand - { - public IncreaseCommand() - { - AccessLevel = AccessLevel.Counselor; - Supports = CommandSupport.All; - Commands = new[] { "Increase", "Inc" }; - ObjectTypes = ObjectTypes.Both; - Usage = "Increase { ...}"; - Description = "Increases the value of a specified property by the specified offset."; - } - - public override void Execute(CommandEventArgs e, object obj) - { - if (obj is BaseMulti) - { - LogFailure("This command does not work on multis."); - } - else if (e.Length >= 2) - { - string result = Properties.IncreaseValue(e.Mobile, obj, e.Arguments); - - if (result == "The property has been increased." || result == "The properties have been increased." || - result == "The property has been decreased." || result == "The properties have been decreased." || - result == "The properties have been changed.") - AddResponse(result); - else - LogFailure(result); - } - else - { - LogFailure("Format: Increase { ...}"); - } - } - } - - public class PrivSoundCommand : BaseCommand - { - public PrivSoundCommand() - { - AccessLevel = AccessLevel.GameMaster; - Supports = CommandSupport.AllMobiles; - Commands = new[] { "PrivSound" }; - ObjectTypes = ObjectTypes.Mobiles; - Usage = "PrivSound "; - Description = "Plays a sound to a given target."; - } - - public override void Execute(CommandEventArgs e, object obj) - { - Mobile from = e.Mobile; - - if (e.Length == 1) - { - int index = e.GetInt32(0); - Mobile mob = (Mobile)obj; - - CommandLogging.WriteLine(from, "{0} {1} playing sound {2} for {3}", from.AccessLevel, - CommandLogging.Format(from), index, CommandLogging.Format(mob)); - mob.Send(new PlaySound(index, mob.Location)); - } - else - { - from.SendMessage("Format: PrivSound "); - } - } - } - - public class TellCommand : BaseCommand - { - private readonly bool m_InGump; - - public TellCommand(bool inGump) - { - m_InGump = inGump; - - AccessLevel = AccessLevel.Counselor; - Supports = CommandSupport.AllMobiles; - ObjectTypes = ObjectTypes.Mobiles; - - if (inGump) - { - Commands = new[] { "Message", "Msg" }; - Usage = "Message \"text\""; - Description = "Sends a message to a targeted player."; - } - else - { - Commands = new[] { "Tell" }; - Usage = "Tell \"text\""; - Description = "Sends a system message to a targeted player."; - } - } - - public override void Execute(CommandEventArgs e, object obj) - { - Mobile mob = (Mobile)obj; - Mobile from = e.Mobile; - - CommandLogging.WriteLine(from, "{0} {1} {2} {3} \"{4}\"", from.AccessLevel, CommandLogging.Format(from), - m_InGump ? "messaging" : "telling", CommandLogging.Format(mob), e.ArgString); - - if (m_InGump) - mob.SendGump(new MessageSentGump(mob, from.Name, e.ArgString)); - else - mob.SendMessage(e.ArgString); - } - } - - public class AddToPackCommand : BaseCommand - { - public AddToPackCommand() - { - AccessLevel = AccessLevel.GameMaster; - Supports = CommandSupport.All; - Commands = new[] { "AddToPack", "AddToCont" }; - ObjectTypes = ObjectTypes.Both; - ListOptimized = true; - Usage = "AddToPack [params] [set { ...}]"; - Description = - "Adds an item by name to the backpack of a targeted player or npc, or a targeted container. Optional constructor parameters. Optional set property list."; - } - - public override void ExecuteList(CommandEventArgs e, List list) - { - if (e.Arguments.Length == 0) - return; - - List packs = new List(list.Count); - - for (int i = 0; i < list.Count; ++i) - { - object obj = list[i]; - Container cont = null; - - if (obj is Mobile mobile) - cont = mobile.Backpack; - else if (obj is Container container) - cont = container; - - if (cont != null) - packs.Add(cont); - else - LogFailure("That is not a container."); - } - - Add.Invoke(e.Mobile, e.Mobile.Location, e.Mobile.Location, e.Arguments, packs); - } - } - - public class AddCommand : BaseCommand - { - public AddCommand() - { - AccessLevel = AccessLevel.GameMaster; - Supports = CommandSupport.Simple | CommandSupport.Self; - Commands = new[] { "Add" }; - ObjectTypes = ObjectTypes.All; - Usage = "Add [ [params] [set { ...}]]"; - Description = - "Adds an item or npc by name to a targeted location. Optional constructor parameters. Optional set property list. If no arguments are specified, this brings up a categorized add menu."; - } - - public override bool ValidateArgs(BaseCommandImplementor impl, CommandEventArgs e) - { - if (e.Length >= 1) - { - Type t = AssemblyHandler.FindFirstTypeForName(e.GetString(0)); - - if (t == null) - { - e.Mobile.SendMessage("No type with that name was found."); - - string match = e.GetString(0).Trim(); - - if (match.Length < 3) - { - e.Mobile.SendMessage("Invalid search string."); - e.Mobile.SendGump(new AddGump(e.Mobile, match, 0, Type.EmptyTypes, false)); - } - else - { - e.Mobile.SendGump(new AddGump(e.Mobile, match, 0, AddGump.Match(match).ToArray(), true)); - } - } - else - { - return true; - } - } - else - { - e.Mobile.SendGump(new CategorizedAddGump(e.Mobile)); - } - - return false; - } - - public override void Execute(CommandEventArgs e, object obj) - { - if (!(obj is IPoint3D p)) - return; - - if (p is Item item) - p = item.GetWorldTop(); - else if (p is Mobile m) - p = m.Location; - - Add.Invoke(e.Mobile, new Point3D(p), new Point3D(p), e.Arguments); - } - } - - public class TeleCommand : BaseCommand - { - public TeleCommand() - { - AccessLevel = AccessLevel.Counselor; - Supports = CommandSupport.Simple; - Commands = new[] { "Teleport", "Tele" }; - ObjectTypes = ObjectTypes.All; - Usage = "Teleport"; - Description = "Teleports your character to a targeted location."; - } - - public override void Execute(CommandEventArgs e, object obj) - { - if (!(obj is IPoint3D p)) - return; - - Mobile from = e.Mobile; - - SpellHelper.GetSurfaceTop(ref p); - - // CommandLogging.WriteLine( from, "{0} {1} teleporting to {2}", from.AccessLevel, CommandLogging.Format( from ), new Point3D( p ) ); - - Point3D fromLoc = from.Location; - Point3D toLoc = new Point3D(p); - - from.Location = toLoc; - from.ProcessDelta(); - - if (!from.Hidden) - { - Effects.SendLocationParticles(EffectItem.Create(fromLoc, from.Map, EffectItem.DefaultDuration), 0x3728, 10, - 10, 2023); - Effects.SendLocationParticles(EffectItem.Create(toLoc, from.Map, EffectItem.DefaultDuration), 0x3728, 10, 10, - 5023); - - from.PlaySound(0x1FE); - } - } - } - - public class DismountCommand : BaseCommand - { - public DismountCommand() - { - AccessLevel = AccessLevel.GameMaster; - Supports = CommandSupport.AllMobiles; - Commands = new[] { "Dismount" }; - ObjectTypes = ObjectTypes.Mobiles; - Usage = "Dismount"; - Description = "Forcefully dismounts a given target."; - } - - public override void Execute(CommandEventArgs e, object obj) - { - Mobile from = e.Mobile; - Mobile mob = (Mobile)obj; - - CommandLogging.WriteLine(from, "{0} {1} dismounting {2}", from.AccessLevel, CommandLogging.Format(from), - CommandLogging.Format(mob)); - - bool takenAction = false; - - for (int i = 0; i < mob.Items.Count; ++i) - { - Item item = mob.Items[i]; - - if (item is IMountItem mountItem) - { - IMount mount = mountItem.Mount; - - if (mount != null) - { - mount.Rider = null; - takenAction = true; - } - - if (mob.Items.IndexOf(item) == -1) - --i; - } - } - - for (int i = 0; i < mob.Items.Count; ++i) - { - Item item = mob.Items[i]; - - if (item.Layer == Layer.Mount) - { - takenAction = true; - item.Delete(); - --i; - } - } - - if (takenAction) - AddResponse("They have been dismounted."); - else - LogFailure("They were not mounted."); - } - } - - public class RestockCommand : BaseCommand - { - public RestockCommand() - { - AccessLevel = AccessLevel.GameMaster; - Supports = CommandSupport.AllNPCs; - Commands = new[] { "Restock" }; - ObjectTypes = ObjectTypes.Mobiles; - Usage = "Restock"; - Description = - "Manually restocks a targeted vendor, refreshing the quantity of every item the vendor sells to the maximum. This also invokes the maximum quantity adjustment algorithms."; - } - - public override void Execute(CommandEventArgs e, object obj) - { - if (obj is BaseVendor vendor) - { - CommandLogging.WriteLine(e.Mobile, "{0} {1} restocking {2}", e.Mobile.AccessLevel, - CommandLogging.Format(e.Mobile), CommandLogging.Format(vendor)); - - vendor.Restock(); - AddResponse("The vendor has been restocked."); - } - else - { - AddResponse("That is not a vendor."); - } - } - } - - public class GetTypeCommand : BaseCommand - { - public GetTypeCommand() - { - AccessLevel = AccessLevel.Counselor; - Supports = CommandSupport.All; - Commands = new[] { "GetType" }; - ObjectTypes = ObjectTypes.All; - Usage = "GetType"; - Description = "Gets the type name of a targeted object."; - } - - public override void Execute(CommandEventArgs e, object obj) - { - if (obj == null) - { - AddResponse("The object is null."); - } - else - { - Type type = obj.GetType(); - - if (type.DeclaringType == null) - AddResponse($"The type of that object is {type.Name}."); - else - AddResponse($"The type of that object is {type.FullName}."); - } - } - } - - public class GetCommand : BaseCommand - { - public GetCommand() - { - AccessLevel = AccessLevel.Counselor; - Supports = CommandSupport.All; - Commands = new[] { "Get" }; - ObjectTypes = ObjectTypes.All; - Usage = "Get "; - Description = "Gets one or more property values by name of a targeted object."; - } - - public override void Execute(CommandEventArgs e, object obj) - { - if (e.Length >= 1) - for (int i = 0; i < e.Length; ++i) - { - string result = Properties.GetValue(e.Mobile, obj, e.GetString(i)); - - if (result == "Property not found." || result == "Property is write only." || - result.StartsWith("Getting this property")) - LogFailure(result); - else - AddResponse(result); - } - else - LogFailure("Format: Get "); - } - } - - public class AliasedSetCommand : BaseCommand - { - private readonly string m_Name; - private readonly string m_Value; - - public AliasedSetCommand(AccessLevel level, string command, string name, string value, ObjectTypes objects) - { - m_Name = name; - m_Value = value; - - AccessLevel = level; - - if (objects == ObjectTypes.Items) - Supports = CommandSupport.AllItems; - else if (objects == ObjectTypes.Mobiles) - Supports = CommandSupport.AllMobiles; - else - Supports = CommandSupport.All; - - Commands = new[] { command }; - ObjectTypes = objects; - Usage = command; - Description = $"Sets the {name} property to {value}."; - } - - public override void Execute(CommandEventArgs e, object obj) - { - string result = Properties.SetValue(e.Mobile, obj, m_Name, m_Value); - - if (result == "Property has been set.") - AddResponse(result); - else - LogFailure(result); - } - } - - public class SetCommand : BaseCommand - { - public SetCommand() - { - AccessLevel = AccessLevel.Counselor; - Supports = CommandSupport.All; - Commands = new[] { "Set" }; - ObjectTypes = ObjectTypes.Both; - Usage = "Set [...]"; - Description = "Sets one or more property values by name of a targeted object."; - } - - public override void Execute(CommandEventArgs e, object obj) - { - if (e.Length >= 2) - for (int i = 0; i + 1 < e.Length; i += 2) - { - string result = Properties.SetValue(e.Mobile, obj, e.GetString(i), e.GetString(i + 1)); - - if (result == "Property has been set.") - AddResponse(result); - else - LogFailure(result); - } - else - LogFailure("Format: Set "); - } - } - - public class DeleteCommand : BaseCommand - { - public DeleteCommand() - { - AccessLevel = AccessLevel.GameMaster; - Supports = CommandSupport.AllNPCs | CommandSupport.AllItems; - Commands = new[] { "Delete", "Remove", "Rm" }; - ObjectTypes = ObjectTypes.Both; - Usage = "Delete"; - Description = "Deletes a targeted item or mobile. Does not delete players."; - } - - private void OnConfirmCallback(Mobile from, bool okay, CommandEventArgs e, List list) - { - bool flushToLog = false; - - if (okay) - { - AddResponse("Delete command confirmed."); - - if (list.Count > 20) - { - CommandLogging.Enabled = false; - NetState.Pause(); - } - - base.ExecuteList(e, list); - - if (list.Count > 20) - { - NetState.Resume(); - flushToLog = true; - CommandLogging.Enabled = true; - } - } - else - { - AddResponse("Delete command aborted."); - } - - Flush(from, flushToLog); - } - - public override void ExecuteList(CommandEventArgs e, List list) - { - if (list.Count > 1) - { - Mobile from = e.Mobile; - from.SendGump(new WarningGump(1060637, 30720, - $"You are about to delete {list.Count} objects. This cannot be undone without a full server revert.

Continue?", - 0xFFC000, 420, 280, okay => OnConfirmCallback(from, okay, e, list))); - AddResponse("Awaiting confirmation..."); - } - else - { - base.ExecuteList(e, list); - } - } - - public override void Execute(CommandEventArgs e, object obj) - { - if (obj is Item item) - { - CommandLogging.WriteLine(e.Mobile, "{0} {1} deleting {2}", e.Mobile.AccessLevel, - CommandLogging.Format(e.Mobile), CommandLogging.Format(item)); - item.Delete(); - AddResponse("The item has been deleted."); - } - else if (obj is Mobile mobile && !mobile.Player) - { - CommandLogging.WriteLine(e.Mobile, "{0} {1} deleting {2}", e.Mobile.AccessLevel, - CommandLogging.Format(e.Mobile), CommandLogging.Format(mobile)); - mobile.Delete(); - AddResponse("The mobile has been deleted."); - } - else - { - LogFailure("That cannot be deleted."); - } - } - } - - public class KillCommand : BaseCommand - { - private readonly bool m_Value; - - public KillCommand(bool value) - { - m_Value = value; - - AccessLevel = AccessLevel.GameMaster; - Supports = CommandSupport.AllMobiles; - Commands = value ? new[] { "Kill" } : new[] { "Resurrect", "Res" }; - ObjectTypes = ObjectTypes.Mobiles; - - if (value) - { - Usage = "Kill"; - Description = "Kills a targeted player or npc."; - } - else - { - Usage = "Resurrect"; - Description = "Resurrects a targeted ghost."; - } - } - - public override void Execute(CommandEventArgs e, object obj) - { - Mobile mob = (Mobile)obj; - Mobile from = e.Mobile; - - if (m_Value) - { - if (!mob.Alive) - { - LogFailure("They are already dead."); - } - else if (!mob.CanBeDamaged()) - { - LogFailure("They cannot be harmed."); - } - else - { - CommandLogging.WriteLine(from, "{0} {1} killing {2}", from.AccessLevel, CommandLogging.Format(from), - CommandLogging.Format(mob)); - mob.Kill(); - - AddResponse("They have been killed."); - } - } - else - { - if (mob.IsDeadBondedPet) - { - if (mob is BaseCreature bc) - { - CommandLogging.WriteLine(from, "{0} {1} resurrecting {2}", from.AccessLevel, - CommandLogging.Format(from), CommandLogging.Format(mob)); - - bc.PlaySound(0x214); - bc.FixedEffect(0x376A, 10, 16); - - bc.ResurrectPet(); - - AddResponse("It has been resurrected."); - } - } - else if (!mob.Alive) - { - CommandLogging.WriteLine(from, "{0} {1} resurrecting {2}", from.AccessLevel, CommandLogging.Format(from), - CommandLogging.Format(mob)); - - mob.PlaySound(0x214); - mob.FixedEffect(0x376A, 10, 16); - - mob.Resurrect(); - - AddResponse("They have been resurrected."); - } - else - { - LogFailure("They are not dead."); - } - } - } - } - - public class HideCommand : BaseCommand - { - private readonly bool m_Value; - - public HideCommand(bool value) - { - m_Value = value; - - AccessLevel = AccessLevel.Counselor; - Supports = CommandSupport.AllMobiles; - Commands = new[] { value ? "Hide" : "Unhide" }; - ObjectTypes = ObjectTypes.Mobiles; - - if (value) - { - Usage = "Hide"; - Description = "Makes a targeted mobile disappear in a puff of smoke."; - } - else - { - Usage = "Unhide"; - Description = "Makes a targeted mobile appear in a puff of smoke."; - } - } - - public override void Execute(CommandEventArgs e, object obj) - { - Mobile m = (Mobile)obj; - - CommandLogging.WriteLine(e.Mobile, "{0} {1} {2} {3}", e.Mobile.AccessLevel, CommandLogging.Format(e.Mobile), - m_Value ? "hiding" : "unhiding", CommandLogging.Format(m)); - - Effects.SendLocationEffect(new Point3D(m.X + 1, m.Y, m.Z + 4), m.Map, 0x3728, 13); - Effects.SendLocationEffect(new Point3D(m.X + 1, m.Y, m.Z), m.Map, 0x3728, 13); - Effects.SendLocationEffect(new Point3D(m.X + 1, m.Y, m.Z - 4), m.Map, 0x3728, 13); - Effects.SendLocationEffect(new Point3D(m.X, m.Y + 1, m.Z + 4), m.Map, 0x3728, 13); - Effects.SendLocationEffect(new Point3D(m.X, m.Y + 1, m.Z), m.Map, 0x3728, 13); - Effects.SendLocationEffect(new Point3D(m.X, m.Y + 1, m.Z - 4), m.Map, 0x3728, 13); - - Effects.SendLocationEffect(new Point3D(m.X + 1, m.Y + 1, m.Z + 11), m.Map, 0x3728, 13); - Effects.SendLocationEffect(new Point3D(m.X + 1, m.Y + 1, m.Z + 7), m.Map, 0x3728, 13); - Effects.SendLocationEffect(new Point3D(m.X + 1, m.Y + 1, m.Z + 3), m.Map, 0x3728, 13); - Effects.SendLocationEffect(new Point3D(m.X + 1, m.Y + 1, m.Z - 1), m.Map, 0x3728, 13); - - m.PlaySound(0x228); - m.Hidden = m_Value; - - if (m_Value) - AddResponse("They have been hidden."); - else - AddResponse("They have been revealed."); - } - } - - public class FirewallCommand : BaseCommand - { - public FirewallCommand() - { - AccessLevel = AccessLevel.Administrator; - Supports = CommandSupport.AllMobiles; - Commands = new[] { "Firewall" }; - ObjectTypes = ObjectTypes.Mobiles; - Usage = "Firewall"; - Description = - "Adds a targeted player to the firewall (list of blocked IP addresses). This command does not ban or kick."; - } - - public override void Execute(CommandEventArgs e, object obj) - { - Mobile from = e.Mobile; - Mobile targ = (Mobile)obj; - NetState state = targ.NetState; - - if (state != null) - { - CommandLogging.WriteLine(from, "{0} {1} firewalling {2}", from.AccessLevel, CommandLogging.Format(from), - CommandLogging.Format(targ)); - - try - { - Firewall.Add(state.Address); - AddResponse("They have been firewalled."); - } - catch (Exception ex) - { - LogFailure(ex.Message); - } - } - else - { - LogFailure("They are not online."); - } - } - } - - public class KickCommand : BaseCommand - { - private readonly bool m_Ban; - - public KickCommand(bool ban) - { - m_Ban = ban; - - AccessLevel = ban ? AccessLevel.Administrator : AccessLevel.GameMaster; - Supports = CommandSupport.AllMobiles; - Commands = new[] { ban ? "Ban" : "Kick" }; - ObjectTypes = ObjectTypes.Mobiles; - - if (ban) - { - Usage = "Ban"; - Description = "Bans the account of a targeted player."; - } - else - { - Usage = "Kick"; - Description = "Disconnects a targeted player."; - } - } - - public override void Execute(CommandEventArgs e, object obj) - { - Mobile from = e.Mobile; - Mobile targ = (Mobile)obj; - - if (from.AccessLevel > targ.AccessLevel) - { - NetState fromState = from.NetState, targState = targ.NetState; - - if (fromState != null && targState != null) - { - if (fromState.Account is Account && targState.Account is Account targAccount) - { - CommandLogging.WriteLine(from, "{0} {1} {2} {3}", from.AccessLevel, CommandLogging.Format(from), - m_Ban ? "banning" : "kicking", CommandLogging.Format(targ)); - - targ.Say("I've been {0}!", m_Ban ? "banned" : "kicked"); - - AddResponse($"They have been {(m_Ban ? "banned" : "kicked")}."); - - targState.Dispose(); - - if (m_Ban) - { - targAccount.Banned = true; - targAccount.SetUnspecifiedBan(from); - from.SendGump(new BanDurationGump(targAccount)); - } - } - } - else if (targState == null) - { - LogFailure("They are not online."); - } - } - else - { - LogFailure("You do not have the required access level to do this."); - } - } - } - - public class TraceLockdownCommand : BaseCommand - { - public TraceLockdownCommand() - { - AccessLevel = AccessLevel.Administrator; - Supports = CommandSupport.Simple; - Commands = new[] { "TraceLockdown" }; - ObjectTypes = ObjectTypes.Items; - Usage = "TraceLockdown"; - Description = "Finds the BaseHouse for which a targeted item is locked down or secured."; - } - - public override void Execute(CommandEventArgs e, object obj) - { - if (!(obj is Item item)) - return; - - if (!item.IsLockedDown && !item.IsSecure) - { - LogFailure("That is not locked down."); - return; - } - - foreach (BaseHouse house in BaseHouse.AllHouses) - if (house.HasSecureItem(item) || house.HasLockedDownItem(item)) - { - e.Mobile.SendGump(new PropertiesGump(e.Mobile, house)); - return; - } - - LogFailure("No house was found."); - } - } -} +using System; +using System.Collections.Generic; +using Server.Accounting; +using Server.Engines.Help; +using Server.Factions; +using Server.Gumps; +using Server.Items; +using Server.Mobiles; +using Server.Multis; +using Server.Network; +using Server.Spells; + +namespace Server.Commands.Generic +{ + public class TargetCommands + { + public static List AllCommands { get; } = new List(); + + public static void Initialize() + { + Register(new KillCommand(true)); + Register(new KillCommand(false)); + Register(new HideCommand(true)); + Register(new HideCommand(false)); + Register(new KickCommand(true)); + Register(new KickCommand(false)); + Register(new FirewallCommand()); + Register(new TeleCommand()); + Register(new SetCommand()); + Register(new AliasedSetCommand(AccessLevel.GameMaster, "Immortal", "blessed", "true", ObjectTypes.Mobiles)); + Register(new AliasedSetCommand(AccessLevel.GameMaster, "Invul", "blessed", "true", ObjectTypes.Mobiles)); + Register(new AliasedSetCommand(AccessLevel.GameMaster, "Mortal", "blessed", "false", ObjectTypes.Mobiles)); + Register(new AliasedSetCommand(AccessLevel.GameMaster, "NoInvul", "blessed", "false", ObjectTypes.Mobiles)); + Register(new AliasedSetCommand(AccessLevel.GameMaster, "Squelch", "squelched", "true", ObjectTypes.Mobiles)); + Register(new AliasedSetCommand(AccessLevel.GameMaster, "Unsquelch", "squelched", "false", ObjectTypes.Mobiles)); + + Register(new AliasedSetCommand(AccessLevel.GameMaster, "ShaveHair", "HairItemID", "0", ObjectTypes.Mobiles)); + Register( + new AliasedSetCommand( + AccessLevel.GameMaster, + "ShaveBeard", + "FacialHairItemID", + "0", + ObjectTypes.Mobiles + ) + ); + + Register(new GetCommand()); + Register(new GetTypeCommand()); + Register(new DeleteCommand()); + Register(new RestockCommand()); + Register(new DismountCommand()); + Register(new AddCommand()); + Register(new AddToPackCommand()); + Register(new TellCommand(true)); + Register(new TellCommand(false)); + Register(new PrivSoundCommand()); + Register(new IncreaseCommand()); + Register(new OpenBrowserCommand()); + Register(new CountCommand()); + Register(new InterfaceCommand()); + Register(new RefreshHouseCommand()); + Register(new ConditionCommand()); + Register(new FactionKickCommand(FactionKickType.Kick)); + Register(new FactionKickCommand(FactionKickType.Ban)); + Register(new FactionKickCommand(FactionKickType.Unban)); + Register(new BringToPackCommand()); + Register(new TraceLockdownCommand()); + Register(new LocationCommand()); + } + + public static void Register(BaseCommand command) + { + AllCommands.Add(command); + + var impls = BaseCommandImplementor.Implementors; + + for (var i = 0; i < impls.Count; ++i) + { + var impl = impls[i]; + + if ((command.Supports & impl.SupportRequirement) != 0) + impl.Register(command); + } + } + } + + public class ConditionCommand : BaseCommand + { + public ConditionCommand() + { + AccessLevel = AccessLevel.GameMaster; + Supports = CommandSupport.Simple | CommandSupport.Complex | CommandSupport.Self; + Commands = new[] { "Condition" }; + ObjectTypes = ObjectTypes.All; + Usage = "Condition "; + Description = "Checks that the given condition matches a targeted object."; + ListOptimized = true; + } + + public override void ExecuteList(CommandEventArgs e, List list) + { + try + { + var args = e.Arguments; + var condition = ObjectConditional.Parse(e.Mobile, ref args); + + for (var i = 0; i < list.Count; ++i) + if (condition.CheckCondition(list[i])) + AddResponse("True - that object matches the condition."); + else + AddResponse("False - that object does not match the condition."); + } + catch (Exception ex) + { + e.Mobile.SendMessage(ex.Message); + } + } + } + + public class BringToPackCommand : BaseCommand + { + public BringToPackCommand() + { + AccessLevel = AccessLevel.GameMaster; + Supports = CommandSupport.AllItems; + Commands = new[] { "BringToPack" }; + ObjectTypes = ObjectTypes.Items; + Usage = "BringToPack"; + Description = "Brings a targeted item to your backpack."; + } + + public override void Execute(CommandEventArgs e, object obj) + { + if (obj is Item item) + { + if (e.Mobile.PlaceInBackpack(item)) + AddResponse("The item has been placed in your backpack."); + else + AddResponse("Your backpack could not hold the item."); + } + } + } + + public class RefreshHouseCommand : BaseCommand + { + public RefreshHouseCommand() + { + AccessLevel = AccessLevel.GameMaster; + Supports = CommandSupport.Simple; + Commands = new[] { "RefreshHouse" }; + ObjectTypes = ObjectTypes.Items; + Usage = "RefreshHouse"; + Description = "Refreshes a targeted house sign."; + } + + public override void Execute(CommandEventArgs e, object obj) + { + if (obj is HouseSign sign) + { + var house = sign.Owner; + + if (house == null) + { + LogFailure("That sign has no house attached."); + } + else + { + house.RefreshDecay(); + AddResponse("The house has been refreshed."); + } + } + else + { + LogFailure("That is not a house sign."); + } + } + } + + public class CountCommand : BaseCommand + { + public CountCommand() + { + AccessLevel = AccessLevel.GameMaster; + Supports = CommandSupport.Complex; + Commands = new[] { "Count" }; + ObjectTypes = ObjectTypes.All; + Usage = "Count"; + Description = + "Counts the number of objects that a command modifier would use. Generally used with condition arguments."; + ListOptimized = true; + } + + public override void ExecuteList(CommandEventArgs e, List list) + { + if (list.Count == 1) + AddResponse("There is one matching object."); + else + AddResponse($"There are {list.Count} matching objects."); + } + } + + public class OpenBrowserCommand : BaseCommand + { + public OpenBrowserCommand() + { + AccessLevel = AccessLevel.GameMaster; + Supports = CommandSupport.AllMobiles; + Commands = new[] { "OpenBrowser", "OB" }; + ObjectTypes = ObjectTypes.Mobiles; + Usage = "OpenBrowser "; + Description = "Opens the web browser of a targeted player to a specified url."; + } + + public static void OpenBrowser_Callback(Mobile from, bool okay, Mobile gm, string url, bool echo) + { + if (okay) + { + if (echo) + gm.SendMessage("{0} : has opened their web browser to : {1}", from.Name, url); + + from.LaunchBrowser(url); + } + else + { + if (echo) + gm.SendMessage("{0} : has chosen not to open their web browser to : {1}", from.Name, url); + + from.SendMessage("You have chosen not to open your web browser."); + } + } + + public void Execute(CommandEventArgs e, object obj, bool echo) + { + if (e.Length == 1) + { + var mob = (Mobile)obj; + var from = e.Mobile; + + if (mob.Player) + { + var ns = mob.NetState; + + if (ns == null) + { + LogFailure("That player is not online."); + } + else + { + var url = e.GetString(0); + + CommandLogging.WriteLine( + from, + "{0} {1} requesting to open web browser of {2} to {3}", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(mob), + url + ); + + if (echo) + AddResponse("Awaiting user confirmation..."); + else + AddResponse("Open web browser request sent."); + + mob.SendGump( + new WarningGump( + 1060637, + 30720, + $"A game master is requesting to open your web browser to the following URL:
{url}", + 0xFFC000, + 320, + 240, + okay => OpenBrowser_Callback(mob, okay, from, url, echo) + ) + ); + } + } + else + { + LogFailure("That is not a player."); + } + } + else + { + LogFailure("Format: OpenBrowser "); + } + } + + public override void Execute(CommandEventArgs e, object obj) + { + Execute(e, obj, true); + } + + public override void ExecuteList(CommandEventArgs e, List list) + { + for (var i = 0; i < list.Count; ++i) + Execute(e, list[i], false); + } + } + + public class IncreaseCommand : BaseCommand + { + public IncreaseCommand() + { + AccessLevel = AccessLevel.Counselor; + Supports = CommandSupport.All; + Commands = new[] { "Increase", "Inc" }; + ObjectTypes = ObjectTypes.Both; + Usage = "Increase { ...}"; + Description = "Increases the value of a specified property by the specified offset."; + } + + public override void Execute(CommandEventArgs e, object obj) + { + if (obj is BaseMulti) + { + LogFailure("This command does not work on multis."); + } + else if (e.Length >= 2) + { + var result = Properties.IncreaseValue(e.Mobile, obj, e.Arguments); + + if (result == "The property has been increased." || result == "The properties have been increased." || + result == "The property has been decreased." || result == "The properties have been decreased." || + result == "The properties have been changed.") + AddResponse(result); + else + LogFailure(result); + } + else + { + LogFailure("Format: Increase { ...}"); + } + } + } + + public class PrivSoundCommand : BaseCommand + { + public PrivSoundCommand() + { + AccessLevel = AccessLevel.GameMaster; + Supports = CommandSupport.AllMobiles; + Commands = new[] { "PrivSound" }; + ObjectTypes = ObjectTypes.Mobiles; + Usage = "PrivSound "; + Description = "Plays a sound to a given target."; + } + + public override void Execute(CommandEventArgs e, object obj) + { + var from = e.Mobile; + + if (e.Length == 1) + { + var index = e.GetInt32(0); + var mob = (Mobile)obj; + + CommandLogging.WriteLine( + from, + "{0} {1} playing sound {2} for {3}", + from.AccessLevel, + CommandLogging.Format(from), + index, + CommandLogging.Format(mob) + ); + mob.Send(new PlaySound(index, mob.Location)); + } + else + { + from.SendMessage("Format: PrivSound "); + } + } + } + + public class TellCommand : BaseCommand + { + private readonly bool m_InGump; + + public TellCommand(bool inGump) + { + m_InGump = inGump; + + AccessLevel = AccessLevel.Counselor; + Supports = CommandSupport.AllMobiles; + ObjectTypes = ObjectTypes.Mobiles; + + if (inGump) + { + Commands = new[] { "Message", "Msg" }; + Usage = "Message \"text\""; + Description = "Sends a message to a targeted player."; + } + else + { + Commands = new[] { "Tell" }; + Usage = "Tell \"text\""; + Description = "Sends a system message to a targeted player."; + } + } + + public override void Execute(CommandEventArgs e, object obj) + { + var mob = (Mobile)obj; + var from = e.Mobile; + + CommandLogging.WriteLine( + from, + "{0} {1} {2} {3} \"{4}\"", + from.AccessLevel, + CommandLogging.Format(from), + m_InGump ? "messaging" : "telling", + CommandLogging.Format(mob), + e.ArgString + ); + + if (m_InGump) + mob.SendGump(new MessageSentGump(mob, from.Name, e.ArgString)); + else + mob.SendMessage(e.ArgString); + } + } + + public class AddToPackCommand : BaseCommand + { + public AddToPackCommand() + { + AccessLevel = AccessLevel.GameMaster; + Supports = CommandSupport.All; + Commands = new[] { "AddToPack", "AddToCont" }; + ObjectTypes = ObjectTypes.Both; + ListOptimized = true; + Usage = "AddToPack [params] [set { ...}]"; + Description = + "Adds an item by name to the backpack of a targeted player or npc, or a targeted container. Optional constructor parameters. Optional set property list."; + } + + public override void ExecuteList(CommandEventArgs e, List list) + { + if (e.Arguments.Length == 0) + return; + + var packs = new List(list.Count); + + for (var i = 0; i < list.Count; ++i) + { + var obj = list[i]; + Container cont = null; + + if (obj is Mobile mobile) + cont = mobile.Backpack; + else if (obj is Container container) + cont = container; + + if (cont != null) + packs.Add(cont); + else + LogFailure("That is not a container."); + } + + Add.Invoke(e.Mobile, e.Mobile.Location, e.Mobile.Location, e.Arguments, packs); + } + } + + public class AddCommand : BaseCommand + { + public AddCommand() + { + AccessLevel = AccessLevel.GameMaster; + Supports = CommandSupport.Simple | CommandSupport.Self; + Commands = new[] { "Add" }; + ObjectTypes = ObjectTypes.All; + Usage = "Add [ [params] [set { ...}]]"; + Description = + "Adds an item or npc by name to a targeted location. Optional constructor parameters. Optional set property list. If no arguments are specified, this brings up a categorized add menu."; + } + + public override bool ValidateArgs(BaseCommandImplementor impl, CommandEventArgs e) + { + if (e.Length >= 1) + { + var t = AssemblyHandler.FindFirstTypeForName(e.GetString(0)); + + if (t == null) + { + e.Mobile.SendMessage("No type with that name was found."); + + var match = e.GetString(0).Trim(); + + if (match.Length < 3) + { + e.Mobile.SendMessage("Invalid search string."); + e.Mobile.SendGump(new AddGump(e.Mobile, match, 0, Type.EmptyTypes, false)); + } + else + { + e.Mobile.SendGump(new AddGump(e.Mobile, match, 0, AddGump.Match(match).ToArray(), true)); + } + } + else + { + return true; + } + } + else + { + e.Mobile.SendGump(new CategorizedAddGump(e.Mobile)); + } + + return false; + } + + public override void Execute(CommandEventArgs e, object obj) + { + if (!(obj is IPoint3D p)) + return; + + if (p is Item item) + p = item.GetWorldTop(); + else if (p is Mobile m) + p = m.Location; + + Add.Invoke(e.Mobile, new Point3D(p), new Point3D(p), e.Arguments); + } + } + + public class TeleCommand : BaseCommand + { + public TeleCommand() + { + AccessLevel = AccessLevel.Counselor; + Supports = CommandSupport.Simple; + Commands = new[] { "Teleport", "Tele" }; + ObjectTypes = ObjectTypes.All; + Usage = "Teleport"; + Description = "Teleports your character to a targeted location."; + } + + public override void Execute(CommandEventArgs e, object obj) + { + if (!(obj is IPoint3D p)) + return; + + var from = e.Mobile; + + SpellHelper.GetSurfaceTop(ref p); + + // CommandLogging.WriteLine( from, "{0} {1} teleporting to {2}", from.AccessLevel, CommandLogging.Format( from ), new Point3D( p ) ); + + var fromLoc = from.Location; + var toLoc = new Point3D(p); + + from.Location = toLoc; + from.ProcessDelta(); + + if (!from.Hidden) + { + Effects.SendLocationParticles( + EffectItem.Create(fromLoc, from.Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 2023 + ); + Effects.SendLocationParticles( + EffectItem.Create(toLoc, from.Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 5023 + ); + + from.PlaySound(0x1FE); + } + } + } + + public class DismountCommand : BaseCommand + { + public DismountCommand() + { + AccessLevel = AccessLevel.GameMaster; + Supports = CommandSupport.AllMobiles; + Commands = new[] { "Dismount" }; + ObjectTypes = ObjectTypes.Mobiles; + Usage = "Dismount"; + Description = "Forcefully dismounts a given target."; + } + + public override void Execute(CommandEventArgs e, object obj) + { + var from = e.Mobile; + var mob = (Mobile)obj; + + CommandLogging.WriteLine( + from, + "{0} {1} dismounting {2}", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(mob) + ); + + var takenAction = false; + + for (var i = 0; i < mob.Items.Count; ++i) + { + var item = mob.Items[i]; + + if (item is IMountItem mountItem) + { + var mount = mountItem.Mount; + + if (mount != null) + { + mount.Rider = null; + takenAction = true; + } + + if (mob.Items.IndexOf(item) == -1) + --i; + } + } + + for (var i = 0; i < mob.Items.Count; ++i) + { + var item = mob.Items[i]; + + if (item.Layer == Layer.Mount) + { + takenAction = true; + item.Delete(); + --i; + } + } + + if (takenAction) + AddResponse("They have been dismounted."); + else + LogFailure("They were not mounted."); + } + } + + public class RestockCommand : BaseCommand + { + public RestockCommand() + { + AccessLevel = AccessLevel.GameMaster; + Supports = CommandSupport.AllNPCs; + Commands = new[] { "Restock" }; + ObjectTypes = ObjectTypes.Mobiles; + Usage = "Restock"; + Description = + "Manually restocks a targeted vendor, refreshing the quantity of every item the vendor sells to the maximum. This also invokes the maximum quantity adjustment algorithms."; + } + + public override void Execute(CommandEventArgs e, object obj) + { + if (obj is BaseVendor vendor) + { + CommandLogging.WriteLine( + e.Mobile, + "{0} {1} restocking {2}", + e.Mobile.AccessLevel, + CommandLogging.Format(e.Mobile), + CommandLogging.Format(vendor) + ); + + vendor.Restock(); + AddResponse("The vendor has been restocked."); + } + else + { + AddResponse("That is not a vendor."); + } + } + } + + public class GetTypeCommand : BaseCommand + { + public GetTypeCommand() + { + AccessLevel = AccessLevel.Counselor; + Supports = CommandSupport.All; + Commands = new[] { "GetType" }; + ObjectTypes = ObjectTypes.All; + Usage = "GetType"; + Description = "Gets the type name of a targeted object."; + } + + public override void Execute(CommandEventArgs e, object obj) + { + if (obj == null) + { + AddResponse("The object is null."); + } + else + { + var type = obj.GetType(); + + if (type.DeclaringType == null) + AddResponse($"The type of that object is {type.Name}."); + else + AddResponse($"The type of that object is {type.FullName}."); + } + } + } + + public class GetCommand : BaseCommand + { + public GetCommand() + { + AccessLevel = AccessLevel.Counselor; + Supports = CommandSupport.All; + Commands = new[] { "Get" }; + ObjectTypes = ObjectTypes.All; + Usage = "Get "; + Description = "Gets one or more property values by name of a targeted object."; + } + + public override void Execute(CommandEventArgs e, object obj) + { + if (e.Length >= 1) + for (var i = 0; i < e.Length; ++i) + { + var result = Properties.GetValue(e.Mobile, obj, e.GetString(i)); + + if (result == "Property not found." || result == "Property is write only." || + result.StartsWith("Getting this property")) + LogFailure(result); + else + AddResponse(result); + } + else + LogFailure("Format: Get "); + } + } + + public class AliasedSetCommand : BaseCommand + { + private readonly string m_Name; + private readonly string m_Value; + + public AliasedSetCommand(AccessLevel level, string command, string name, string value, ObjectTypes objects) + { + m_Name = name; + m_Value = value; + + AccessLevel = level; + + if (objects == ObjectTypes.Items) + Supports = CommandSupport.AllItems; + else if (objects == ObjectTypes.Mobiles) + Supports = CommandSupport.AllMobiles; + else + Supports = CommandSupport.All; + + Commands = new[] { command }; + ObjectTypes = objects; + Usage = command; + Description = $"Sets the {name} property to {value}."; + } + + public override void Execute(CommandEventArgs e, object obj) + { + var result = Properties.SetValue(e.Mobile, obj, m_Name, m_Value); + + if (result == "Property has been set.") + AddResponse(result); + else + LogFailure(result); + } + } + + public class SetCommand : BaseCommand + { + public SetCommand() + { + AccessLevel = AccessLevel.Counselor; + Supports = CommandSupport.All; + Commands = new[] { "Set" }; + ObjectTypes = ObjectTypes.Both; + Usage = "Set [...]"; + Description = "Sets one or more property values by name of a targeted object."; + } + + public override void Execute(CommandEventArgs e, object obj) + { + if (e.Length >= 2) + for (var i = 0; i + 1 < e.Length; i += 2) + { + var result = Properties.SetValue(e.Mobile, obj, e.GetString(i), e.GetString(i + 1)); + + if (result == "Property has been set.") + AddResponse(result); + else + LogFailure(result); + } + else + LogFailure("Format: Set "); + } + } + + public class DeleteCommand : BaseCommand + { + public DeleteCommand() + { + AccessLevel = AccessLevel.GameMaster; + Supports = CommandSupport.AllNPCs | CommandSupport.AllItems; + Commands = new[] { "Delete", "Remove", "Rm" }; + ObjectTypes = ObjectTypes.Both; + Usage = "Delete"; + Description = "Deletes a targeted item or mobile. Does not delete players."; + } + + private void OnConfirmCallback(Mobile from, bool okay, CommandEventArgs e, List list) + { + var flushToLog = false; + + if (okay) + { + AddResponse("Delete command confirmed."); + + if (list.Count > 20) + { + CommandLogging.Enabled = false; + NetState.Pause(); + } + + base.ExecuteList(e, list); + + if (list.Count > 20) + { + NetState.Resume(); + flushToLog = true; + CommandLogging.Enabled = true; + } + } + else + { + AddResponse("Delete command aborted."); + } + + Flush(from, flushToLog); + } + + public override void ExecuteList(CommandEventArgs e, List list) + { + if (list.Count > 1) + { + var from = e.Mobile; + from.SendGump( + new WarningGump( + 1060637, + 30720, + $"You are about to delete {list.Count} objects. This cannot be undone without a full server revert.

Continue?", + 0xFFC000, + 420, + 280, + okay => OnConfirmCallback(from, okay, e, list) + ) + ); + AddResponse("Awaiting confirmation..."); + } + else + { + base.ExecuteList(e, list); + } + } + + public override void Execute(CommandEventArgs e, object obj) + { + if (obj is Item item) + { + CommandLogging.WriteLine( + e.Mobile, + "{0} {1} deleting {2}", + e.Mobile.AccessLevel, + CommandLogging.Format(e.Mobile), + CommandLogging.Format(item) + ); + item.Delete(); + AddResponse("The item has been deleted."); + } + else if (obj is Mobile mobile && !mobile.Player) + { + CommandLogging.WriteLine( + e.Mobile, + "{0} {1} deleting {2}", + e.Mobile.AccessLevel, + CommandLogging.Format(e.Mobile), + CommandLogging.Format(mobile) + ); + mobile.Delete(); + AddResponse("The mobile has been deleted."); + } + else + { + LogFailure("That cannot be deleted."); + } + } + } + + public class KillCommand : BaseCommand + { + private readonly bool m_Value; + + public KillCommand(bool value) + { + m_Value = value; + + AccessLevel = AccessLevel.GameMaster; + Supports = CommandSupport.AllMobiles; + Commands = value ? new[] { "Kill" } : new[] { "Resurrect", "Res" }; + ObjectTypes = ObjectTypes.Mobiles; + + if (value) + { + Usage = "Kill"; + Description = "Kills a targeted player or npc."; + } + else + { + Usage = "Resurrect"; + Description = "Resurrects a targeted ghost."; + } + } + + public override void Execute(CommandEventArgs e, object obj) + { + var mob = (Mobile)obj; + var from = e.Mobile; + + if (m_Value) + { + if (!mob.Alive) + { + LogFailure("They are already dead."); + } + else if (!mob.CanBeDamaged()) + { + LogFailure("They cannot be harmed."); + } + else + { + CommandLogging.WriteLine( + from, + "{0} {1} killing {2}", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(mob) + ); + mob.Kill(); + + AddResponse("They have been killed."); + } + } + else + { + if (mob.IsDeadBondedPet) + { + if (mob is BaseCreature bc) + { + CommandLogging.WriteLine( + from, + "{0} {1} resurrecting {2}", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(mob) + ); + + bc.PlaySound(0x214); + bc.FixedEffect(0x376A, 10, 16); + + bc.ResurrectPet(); + + AddResponse("It has been resurrected."); + } + } + else if (!mob.Alive) + { + CommandLogging.WriteLine( + from, + "{0} {1} resurrecting {2}", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(mob) + ); + + mob.PlaySound(0x214); + mob.FixedEffect(0x376A, 10, 16); + + mob.Resurrect(); + + AddResponse("They have been resurrected."); + } + else + { + LogFailure("They are not dead."); + } + } + } + } + + public class HideCommand : BaseCommand + { + private readonly bool m_Value; + + public HideCommand(bool value) + { + m_Value = value; + + AccessLevel = AccessLevel.Counselor; + Supports = CommandSupport.AllMobiles; + Commands = new[] { value ? "Hide" : "Unhide" }; + ObjectTypes = ObjectTypes.Mobiles; + + if (value) + { + Usage = "Hide"; + Description = "Makes a targeted mobile disappear in a puff of smoke."; + } + else + { + Usage = "Unhide"; + Description = "Makes a targeted mobile appear in a puff of smoke."; + } + } + + public override void Execute(CommandEventArgs e, object obj) + { + var m = (Mobile)obj; + + CommandLogging.WriteLine( + e.Mobile, + "{0} {1} {2} {3}", + e.Mobile.AccessLevel, + CommandLogging.Format(e.Mobile), + m_Value ? "hiding" : "unhiding", + CommandLogging.Format(m) + ); + + Effects.SendLocationEffect(new Point3D(m.X + 1, m.Y, m.Z + 4), m.Map, 0x3728, 13); + Effects.SendLocationEffect(new Point3D(m.X + 1, m.Y, m.Z), m.Map, 0x3728, 13); + Effects.SendLocationEffect(new Point3D(m.X + 1, m.Y, m.Z - 4), m.Map, 0x3728, 13); + Effects.SendLocationEffect(new Point3D(m.X, m.Y + 1, m.Z + 4), m.Map, 0x3728, 13); + Effects.SendLocationEffect(new Point3D(m.X, m.Y + 1, m.Z), m.Map, 0x3728, 13); + Effects.SendLocationEffect(new Point3D(m.X, m.Y + 1, m.Z - 4), m.Map, 0x3728, 13); + + Effects.SendLocationEffect(new Point3D(m.X + 1, m.Y + 1, m.Z + 11), m.Map, 0x3728, 13); + Effects.SendLocationEffect(new Point3D(m.X + 1, m.Y + 1, m.Z + 7), m.Map, 0x3728, 13); + Effects.SendLocationEffect(new Point3D(m.X + 1, m.Y + 1, m.Z + 3), m.Map, 0x3728, 13); + Effects.SendLocationEffect(new Point3D(m.X + 1, m.Y + 1, m.Z - 1), m.Map, 0x3728, 13); + + m.PlaySound(0x228); + m.Hidden = m_Value; + + if (m_Value) + AddResponse("They have been hidden."); + else + AddResponse("They have been revealed."); + } + } + + public class FirewallCommand : BaseCommand + { + public FirewallCommand() + { + AccessLevel = AccessLevel.Administrator; + Supports = CommandSupport.AllMobiles; + Commands = new[] { "Firewall" }; + ObjectTypes = ObjectTypes.Mobiles; + Usage = "Firewall"; + Description = + "Adds a targeted player to the firewall (list of blocked IP addresses). This command does not ban or kick."; + } + + public override void Execute(CommandEventArgs e, object obj) + { + var from = e.Mobile; + var targ = (Mobile)obj; + var state = targ.NetState; + + if (state != null) + { + CommandLogging.WriteLine( + from, + "{0} {1} firewalling {2}", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(targ) + ); + + try + { + Firewall.Add(state.Address); + AddResponse("They have been firewalled."); + } + catch (Exception ex) + { + LogFailure(ex.Message); + } + } + else + { + LogFailure("They are not online."); + } + } + } + + public class KickCommand : BaseCommand + { + private readonly bool m_Ban; + + public KickCommand(bool ban) + { + m_Ban = ban; + + AccessLevel = ban ? AccessLevel.Administrator : AccessLevel.GameMaster; + Supports = CommandSupport.AllMobiles; + Commands = new[] { ban ? "Ban" : "Kick" }; + ObjectTypes = ObjectTypes.Mobiles; + + if (ban) + { + Usage = "Ban"; + Description = "Bans the account of a targeted player."; + } + else + { + Usage = "Kick"; + Description = "Disconnects a targeted player."; + } + } + + public override void Execute(CommandEventArgs e, object obj) + { + var from = e.Mobile; + var targ = (Mobile)obj; + + if (from.AccessLevel > targ.AccessLevel) + { + NetState fromState = from.NetState, targState = targ.NetState; + + if (fromState != null && targState != null) + { + if (fromState.Account is Account && targState.Account is Account targAccount) + { + CommandLogging.WriteLine( + from, + "{0} {1} {2} {3}", + from.AccessLevel, + CommandLogging.Format(from), + m_Ban ? "banning" : "kicking", + CommandLogging.Format(targ) + ); + + targ.Say("I've been {0}!", m_Ban ? "banned" : "kicked"); + + AddResponse($"They have been {(m_Ban ? "banned" : "kicked")}."); + + targState.Dispose(); + + if (m_Ban) + { + targAccount.Banned = true; + targAccount.SetUnspecifiedBan(from); + from.SendGump(new BanDurationGump(targAccount)); + } + } + } + else if (targState == null) + { + LogFailure("They are not online."); + } + } + else + { + LogFailure("You do not have the required access level to do this."); + } + } + } + + public class TraceLockdownCommand : BaseCommand + { + public TraceLockdownCommand() + { + AccessLevel = AccessLevel.Administrator; + Supports = CommandSupport.Simple; + Commands = new[] { "TraceLockdown" }; + ObjectTypes = ObjectTypes.Items; + Usage = "TraceLockdown"; + Description = "Finds the BaseHouse for which a targeted item is locked down or secured."; + } + + public override void Execute(CommandEventArgs e, object obj) + { + if (!(obj is Item item)) + return; + + if (!item.IsLockedDown && !item.IsSecure) + { + LogFailure("That is not locked down."); + return; + } + + foreach (var house in BaseHouse.AllHouses) + if (house.HasSecureItem(item) || house.HasLockedDownItem(item)) + { + e.Mobile.SendGump(new PropertiesGump(e.Mobile, house)); + return; + } + + LogFailure("No house was found."); + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Commands/DesignInsert.cs b/Projects/UOContent/Commands/Generic/Commands/DesignInsert.cs index 84b5c4b26..4de111399 100644 --- a/Projects/UOContent/Commands/Generic/Commands/DesignInsert.cs +++ b/Projects/UOContent/Commands/Generic/Commands/DesignInsert.cs @@ -1,195 +1,204 @@ -using System.Collections.Generic; -using Server.Gumps; -using Server.Items; -using Server.Multis; -using Server.Targeting; - -namespace Server.Commands.Generic -{ - public class DesignInsertCommand : BaseCommand - { - public enum DesignInsertResult - { - Valid, - InvalidItem, - NotInHouse, - OutsideHouseBounds - } - - public DesignInsertCommand() - { - AccessLevel = AccessLevel.GameMaster; - Supports = CommandSupport.Single | CommandSupport.Area; - Commands = new[] { "DesignInsert" }; - ObjectTypes = ObjectTypes.Items; - Usage = "DesignInsert [allItems=false]"; - Description = "Inserts multiple targeted items into a customizable house's design."; - } - - public static void Initialize() - { - TargetCommands.Register(new DesignInsertCommand()); - } - - public static DesignInsertResult ProcessInsert(Item item, bool staticsOnly, out HouseFoundation house) - { - house = null; - - if (item == null || item is BaseMulti || item is HouseSign || (staticsOnly && !(item is Static))) - return DesignInsertResult.InvalidItem; - - house = BaseHouse.FindHouseAt(item) as HouseFoundation; - - if (house == null) - return DesignInsertResult.NotInHouse; - - int x = item.X - house.X; - int y = item.Y - house.Y; - int z = item.Z - house.Z; - - if (!TryInsertIntoState(house.CurrentState, item.ItemID, x, y, z)) - return DesignInsertResult.OutsideHouseBounds; - - TryInsertIntoState(house.DesignState, item.ItemID, x, y, z); - item.Delete(); - - return DesignInsertResult.Valid; - } - - private static bool TryInsertIntoState(DesignState state, int itemID, int x, int y, int z) - { - MultiComponentList mcl = state.Components; - - if (x < mcl.Min.X || y < mcl.Min.Y || x > mcl.Max.X || y > mcl.Max.Y) - return false; - - mcl.Add(itemID, x, y, z); - state.OnRevised(); - - return true; - } - - public override void Execute(CommandEventArgs e, object obj) - { - Target t = new DesignInsertTarget(new List(), e.Length < 1 || !e.GetBoolean(0)); - t.Invoke(e.Mobile, obj); - } - - private class DesignInsertTarget : Target - { - private readonly List m_Foundations; - private readonly bool m_StaticsOnly; - - public DesignInsertTarget(List foundations, bool staticsOnly) - : base(-1, false, TargetFlags.None) - { - m_Foundations = foundations; - m_StaticsOnly = staticsOnly; - } - - protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType) - { - if (m_Foundations.Count != 0) - { - from.SendMessage("Your changes have been committed. Updating..."); - - foreach (HouseFoundation house in m_Foundations) - house.Delta(ItemDelta.Update); - } - } - - protected override void OnTarget(Mobile from, object obj) - { - DesignInsertResult result = ProcessInsert(obj as Item, m_StaticsOnly, out HouseFoundation house); - - switch (result) - { - case DesignInsertResult.Valid: - { - if (m_Foundations.Count == 0) - from.SendMessage( - "The item has been inserted into the house design. Press ESC when you are finished."); - else - from.SendMessage("The item has been inserted into the house design."); - - if (!m_Foundations.Contains(house)) - m_Foundations.Add(house); - - break; - } - case DesignInsertResult.InvalidItem: - { - from.SendMessage("That cannot be inserted. Try again."); - break; - } - case DesignInsertResult.NotInHouse: - case DesignInsertResult.OutsideHouseBounds: - { - from.SendMessage("That item is not inside a customizable house. Try again."); - break; - } - } - - from.Target = new DesignInsertTarget(m_Foundations, m_StaticsOnly); - } - } - - public override void ExecuteList(CommandEventArgs e, List list) - { - Mobile from = e.Mobile; - from.SendGump(new WarningGump(1060637, 30720, - $"You are about to insert {list.Count} objects. This cannot be undone without a full server revert.

Continue?", - 0xFFC000, 420, 280, okay => OnConfirmCallback(from, okay, list, e.Length < 1 || !e.GetBoolean(0)))); - AddResponse("Awaiting confirmation..."); - } - - private void OnConfirmCallback(Mobile from, bool okay, List list, bool staticsOnly) - { - bool flushToLog = false; - - if (okay) - { - List foundations = new List(); - flushToLog = list.Count > 20; - - for (int i = 0; i < list.Count; ++i) - { - DesignInsertResult result = ProcessInsert(list[i] as Item, staticsOnly, out HouseFoundation house); - - switch (result) - { - case DesignInsertResult.Valid: - { - AddResponse("The item has been inserted into the house design."); - - if (!foundations.Contains(house)) - foundations.Add(house); - - break; - } - case DesignInsertResult.InvalidItem: - { - LogFailure("That cannot be inserted."); - break; - } - case DesignInsertResult.NotInHouse: - case DesignInsertResult.OutsideHouseBounds: - { - LogFailure("That item is not inside a customizable house."); - break; - } - } - } - - foreach (HouseFoundation house in foundations) - house.Delta(ItemDelta.Update); - } - else - { - AddResponse("Command aborted."); - } - - Flush(from, flushToLog); - } - } -} \ No newline at end of file +using System.Collections.Generic; +using Server.Gumps; +using Server.Items; +using Server.Multis; +using Server.Targeting; + +namespace Server.Commands.Generic +{ + public class DesignInsertCommand : BaseCommand + { + public enum DesignInsertResult + { + Valid, + InvalidItem, + NotInHouse, + OutsideHouseBounds + } + + public DesignInsertCommand() + { + AccessLevel = AccessLevel.GameMaster; + Supports = CommandSupport.Single | CommandSupport.Area; + Commands = new[] { "DesignInsert" }; + ObjectTypes = ObjectTypes.Items; + Usage = "DesignInsert [allItems=false]"; + Description = "Inserts multiple targeted items into a customizable house's design."; + } + + public static void Initialize() + { + TargetCommands.Register(new DesignInsertCommand()); + } + + public static DesignInsertResult ProcessInsert(Item item, bool staticsOnly, out HouseFoundation house) + { + house = null; + + if (item == null || item is BaseMulti || item is HouseSign || staticsOnly && !(item is Static)) + return DesignInsertResult.InvalidItem; + + house = BaseHouse.FindHouseAt(item) as HouseFoundation; + + if (house == null) + return DesignInsertResult.NotInHouse; + + var x = item.X - house.X; + var y = item.Y - house.Y; + var z = item.Z - house.Z; + + if (!TryInsertIntoState(house.CurrentState, item.ItemID, x, y, z)) + return DesignInsertResult.OutsideHouseBounds; + + TryInsertIntoState(house.DesignState, item.ItemID, x, y, z); + item.Delete(); + + return DesignInsertResult.Valid; + } + + private static bool TryInsertIntoState(DesignState state, int itemID, int x, int y, int z) + { + var mcl = state.Components; + + if (x < mcl.Min.X || y < mcl.Min.Y || x > mcl.Max.X || y > mcl.Max.Y) + return false; + + mcl.Add(itemID, x, y, z); + state.OnRevised(); + + return true; + } + + public override void Execute(CommandEventArgs e, object obj) + { + Target t = new DesignInsertTarget(new List(), e.Length < 1 || !e.GetBoolean(0)); + t.Invoke(e.Mobile, obj); + } + + public override void ExecuteList(CommandEventArgs e, List list) + { + var from = e.Mobile; + from.SendGump( + new WarningGump( + 1060637, + 30720, + $"You are about to insert {list.Count} objects. This cannot be undone without a full server revert.

Continue?", + 0xFFC000, + 420, + 280, + okay => OnConfirmCallback(from, okay, list, e.Length < 1 || !e.GetBoolean(0)) + ) + ); + AddResponse("Awaiting confirmation..."); + } + + private void OnConfirmCallback(Mobile from, bool okay, List list, bool staticsOnly) + { + var flushToLog = false; + + if (okay) + { + var foundations = new List(); + flushToLog = list.Count > 20; + + for (var i = 0; i < list.Count; ++i) + { + var result = ProcessInsert(list[i] as Item, staticsOnly, out var house); + + switch (result) + { + case DesignInsertResult.Valid: + { + AddResponse("The item has been inserted into the house design."); + + if (!foundations.Contains(house)) + foundations.Add(house); + + break; + } + case DesignInsertResult.InvalidItem: + { + LogFailure("That cannot be inserted."); + break; + } + case DesignInsertResult.NotInHouse: + case DesignInsertResult.OutsideHouseBounds: + { + LogFailure("That item is not inside a customizable house."); + break; + } + } + } + + foreach (var house in foundations) + house.Delta(ItemDelta.Update); + } + else + { + AddResponse("Command aborted."); + } + + Flush(from, flushToLog); + } + + private class DesignInsertTarget : Target + { + private readonly List m_Foundations; + private readonly bool m_StaticsOnly; + + public DesignInsertTarget(List foundations, bool staticsOnly) + : base(-1, false, TargetFlags.None) + { + m_Foundations = foundations; + m_StaticsOnly = staticsOnly; + } + + protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType) + { + if (m_Foundations.Count != 0) + { + from.SendMessage("Your changes have been committed. Updating..."); + + foreach (var house in m_Foundations) + house.Delta(ItemDelta.Update); + } + } + + protected override void OnTarget(Mobile from, object obj) + { + var result = ProcessInsert(obj as Item, m_StaticsOnly, out var house); + + switch (result) + { + case DesignInsertResult.Valid: + { + if (m_Foundations.Count == 0) + from.SendMessage( + "The item has been inserted into the house design. Press ESC when you are finished." + ); + else + from.SendMessage("The item has been inserted into the house design."); + + if (!m_Foundations.Contains(house)) + m_Foundations.Add(house); + + break; + } + case DesignInsertResult.InvalidItem: + { + from.SendMessage("That cannot be inserted. Try again."); + break; + } + case DesignInsertResult.NotInHouse: + case DesignInsertResult.OutsideHouseBounds: + { + from.SendMessage("That item is not inside a customizable house. Try again."); + break; + } + } + + from.Target = new DesignInsertTarget(m_Foundations, m_StaticsOnly); + } + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Commands/Interface.cs b/Projects/UOContent/Commands/Generic/Commands/Interface.cs index 6ceab010a..4b49fc921 100644 --- a/Projects/UOContent/Commands/Generic/Commands/Interface.cs +++ b/Projects/UOContent/Commands/Generic/Commands/Interface.cs @@ -1,567 +1,596 @@ -using System.Collections.Generic; -using System.Reflection; -using Server.Gumps; -using Server.Network; -using Server.Targets; - -namespace Server.Commands.Generic -{ - public class InterfaceCommand : BaseCommand - { - public InterfaceCommand() - { - AccessLevel = AccessLevel.GameMaster; - Supports = CommandSupport.Complex | CommandSupport.Simple; - Commands = new[] { "Interface" }; - ObjectTypes = ObjectTypes.Both; - Usage = "Interface [view ]"; - Description = "Opens an interface to interact with matched objects. Generally used with condition arguments."; - ListOptimized = true; - } - - public override void ExecuteList(CommandEventArgs e, List list) - { - if (list.Count > 0) - { - List columns = new List { "Object" }; - - if (e.Length > 0) - { - int offset = 0; - - if (Insensitive.Equals(e.GetString(0), "view")) - ++offset; - - while (offset < e.Length) - columns.Add(e.GetString(offset++)); - } - - e.Mobile.SendGump(new InterfaceGump(e.Mobile, columns.ToArray(), list, 0, null)); - } - else - { - AddResponse("No matching objects found."); - } - } - } - - public class InterfaceGump : BaseGridGump - { - private const int EntriesPerPage = 15; - - private readonly string[] m_Columns; - private readonly Mobile m_From; - - private readonly List m_List; - private readonly int m_Page; - - private readonly object m_Select; - - public InterfaceGump(Mobile from, string[] columns, List list, int page, object select) : base(30, 30) - { - m_From = from; - - m_Columns = columns; - - m_List = list; - m_Page = page; - - m_Select = select; - - Render(); - } - - public void Render() - { - AddNewPage(); - - if (m_Page > 0) - AddEntryButton(20, ArrowLeftID1, ArrowLeftID2, 1, ArrowLeftWidth, ArrowLeftHeight); - else - AddEntryHeader(20); - - AddEntryHtml(40 + m_Columns.Length * 130 - 20 + (m_Columns.Length - 2) * OffsetSize, Center( - $"Page {m_Page + 1} of {(m_List.Count + EntriesPerPage - 1) / EntriesPerPage}")); - - if ((m_Page + 1) * EntriesPerPage < m_List.Count) - AddEntryButton(20, ArrowRightID1, ArrowRightID2, 2, ArrowRightWidth, ArrowRightHeight); - else - AddEntryHeader(20); - - if (m_Columns.Length > 1) - { - AddNewLine(); - - for (int i = 0; i < m_Columns.Length; ++i) - { - if (i > 0 && m_List.Count > 0) - { - object obj = m_List[0]; - - if (obj != null) - { - string failReason = null; - PropertyInfo[] chain = Properties.GetPropertyInfoChain(m_From, obj.GetType(), m_Columns[i], - PropertyAccess.Read, ref failReason); - - if (chain?.Length > 0) - { - m_Columns[i] = ""; - - for (int j = 0; j < chain.Length; ++j) - { - if (j > 0) - m_Columns[i] += '.'; - - m_Columns[i] += chain[j].Name; - } - } - } - } - - AddEntryHtml(130 + (i == 0 ? 40 : 0), m_Columns[i]); - } - - AddEntryHeader(20); - } - - for (int i = m_Page * EntriesPerPage, line = 0; line < EntriesPerPage && i < m_List.Count; ++i, ++line) - { - AddNewLine(); - - object obj = m_List[i]; - bool isDeleted = false; - - if (obj is Item item) - { - if (!(isDeleted = item.Deleted)) - AddEntryHtml(40 + 130, item.GetType().Name); - } - else if (obj is Mobile mob) - { - if (!(isDeleted = mob.Deleted)) - AddEntryHtml(40 + 130, mob.Name); - } - - if (isDeleted) - { - AddEntryHtml(40 + 130, "(deleted)"); - - for (int j = 1; j < m_Columns.Length; ++j) - AddEntryHtml(130, "---"); - - AddEntryHeader(20); - } - else - { - for (int j = 1; j < m_Columns.Length; ++j) - { - object src = obj; - - string value; - string failReason = ""; - - PropertyInfo[] chain = Properties.GetPropertyInfoChain(m_From, src.GetType(), m_Columns[j], - PropertyAccess.Read, ref failReason); - - if (chain == null || chain.Length == 0) - { - value = "---"; - } - else - { - PropertyInfo p = Properties.GetPropertyInfo(ref src, chain, ref failReason); - - if (p == null) - value = "---"; - else - value = PropertiesGump.ValueToString(src, p); - } - - AddEntryHtml(130, value); - } - - bool isSelected = m_Select != null && obj == m_Select; - - AddEntryButton(20, isSelected ? 9762 : ArrowRightID1, isSelected ? 9763 : ArrowRightID2, 3 + i, - ArrowRightWidth, ArrowRightHeight); - } - } - - FinishPage(); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - switch (info.ButtonID) - { - case 1: - { - if (m_Page > 0) - m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page - 1, m_Select)); - - break; - } - case 2: - { - if ((m_Page + 1) * EntriesPerPage < m_List.Count) - m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page + 1, m_Select)); - - break; - } - default: - { - int v = info.ButtonID - 3; - - if (v >= 0 && v < m_List.Count) - { - object obj = m_List[v]; - - if (!BaseCommand.IsAccessible(m_From, obj)) - { - m_From.SendLocalizedMessage(500447); // That is not accessible. - m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page, m_Select)); - break; - } - - if (obj is Item item && !item.Deleted) - m_From.SendGump(new InterfaceItemGump(m_From, m_Columns, m_List, m_Page, item)); - else if (obj is Mobile mobile && !mobile.Deleted) - m_From.SendGump(new InterfaceMobileGump(m_From, m_Columns, m_List, m_Page, mobile)); - else - m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page, m_Select)); - } - - break; - } - } - } - } - - public class InterfaceItemGump : BaseGridGump - { - private readonly string[] m_Columns; - private readonly Mobile m_From; - - private readonly Item m_Item; - - private readonly List m_List; - private readonly int m_Page; - - public InterfaceItemGump(Mobile from, string[] columns, List list, int page, Item item) : base(30, 30) - { - m_From = from; - - m_Columns = columns; - - m_List = list; - m_Page = page; - - m_Item = item; - - Render(); - } - - public void Render() - { - AddNewPage(); - - AddEntryButton(20, ArrowLeftID1, ArrowLeftID2, 1, ArrowLeftWidth, ArrowLeftHeight); - AddEntryHtml(160, m_Item.GetType().Name); - AddEntryHeader(20); - - AddNewLine(); - AddEntryHtml(20 + OffsetSize + 160, "Properties"); - AddEntryButton(20, ArrowRightID1, ArrowRightID2, 2, ArrowRightWidth, ArrowRightHeight); - - AddNewLine(); - AddEntryHtml(20 + OffsetSize + 160, "Delete"); - AddEntryButton(20, ArrowRightID1, ArrowRightID2, 3, ArrowRightWidth, ArrowRightHeight); - - AddNewLine(); - AddEntryHtml(20 + OffsetSize + 160, "Go there"); - AddEntryButton(20, ArrowRightID1, ArrowRightID2, 4, ArrowRightWidth, ArrowRightHeight); - - AddNewLine(); - AddEntryHtml(20 + OffsetSize + 160, "Move to target"); - AddEntryButton(20, ArrowRightID1, ArrowRightID2, 5, ArrowRightWidth, ArrowRightHeight); - - AddNewLine(); - AddEntryHtml(20 + OffsetSize + 160, "Bring to pack"); - AddEntryButton(20, ArrowRightID1, ArrowRightID2, 6, ArrowRightWidth, ArrowRightHeight); - - FinishPage(); - } - - private void InvokeCommand(string ip) - { - CommandSystem.Handle(m_From, $"{CommandSystem.Prefix}{ip}"); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Item.Deleted) - { - m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page, m_Item)); - return; - } - - if (!BaseCommand.IsAccessible(m_From, m_Item)) - { - m_From.SendMessage("That is no longer accessible."); - m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page, m_Item)); - return; - } - - switch (info.ButtonID) - { - case 0: - case 1: - { - m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page, m_Item)); - break; - } - case 2: // Properties - { - m_From.SendGump(new InterfaceItemGump(m_From, m_Columns, m_List, m_Page, m_Item)); - m_From.SendGump(new PropertiesGump(m_From, m_Item)); - break; - } - case 3: // Delete - { - CommandLogging.WriteLine(m_From, "{0} {1} deleting {2}", m_From.AccessLevel, - CommandLogging.Format(m_From), CommandLogging.Format(m_Item)); - m_Item.Delete(); - m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page, m_Item)); - break; - } - case 4: // Go there - { - m_From.SendGump(new InterfaceItemGump(m_From, m_Columns, m_List, m_Page, m_Item)); - InvokeCommand($"Go {m_Item.Serial.Value}"); - break; - } - case 5: // Move to target - { - m_From.SendGump(new InterfaceItemGump(m_From, m_Columns, m_List, m_Page, m_Item)); - m_From.Target = new MoveTarget(m_Item); - break; - } - case 6: // Bring to pack - { - Mobile owner = m_Item.RootParent as Mobile; - - if (owner?.Map != null && owner.Map != Map.Internal && - !BaseCommand.IsAccessible(m_From, owner) /* !m_From.CanSee( owner )*/) - { - m_From.SendMessage("You can not get what you can not see."); - } - else if (owner != null && (owner.Map == null || owner.Map == Map.Internal) && owner.Hidden && - owner.AccessLevel >= m_From.AccessLevel) - { - m_From.SendMessage("You can not get what you can not see."); - } - else - { - m_From.SendGump(new InterfaceItemGump(m_From, m_Columns, m_List, m_Page, m_Item)); - m_From.AddToBackpack(m_Item); - } - - break; - } - } - } - } - - public class InterfaceMobileGump : BaseGridGump - { - private readonly string[] m_Columns; - private readonly Mobile m_From; - - private readonly List m_List; - - private readonly Mobile m_Mobile; - private readonly int m_Page; - - public InterfaceMobileGump(Mobile from, string[] columns, List list, int page, Mobile mob) - : base(30, 30) - { - m_From = from; - - m_Columns = columns; - - m_List = list; - m_Page = page; - - m_Mobile = mob; - - Render(); - } - - public void Render() - { - AddNewPage(); - - AddEntryButton(20, ArrowLeftID1, ArrowLeftID2, 1, ArrowLeftWidth, ArrowLeftHeight); - AddEntryHtml(160, m_Mobile.Name); - AddEntryHeader(20); - - AddNewLine(); - AddEntryHtml(20 + OffsetSize + 160, "Properties"); - AddEntryButton(20, ArrowRightID1, ArrowRightID2, 2, ArrowRightWidth, ArrowRightHeight); - - if (!m_Mobile.Player) - { - AddNewLine(); - AddEntryHtml(20 + OffsetSize + 160, "Delete"); - AddEntryButton(20, ArrowRightID1, ArrowRightID2, 3, ArrowRightWidth, ArrowRightHeight); - } - - if (m_Mobile != m_From) - { - AddNewLine(); - AddEntryHtml(20 + OffsetSize + 160, "Go to there"); - AddEntryButton(20, ArrowRightID1, ArrowRightID2, 4, ArrowRightWidth, ArrowRightHeight); - - AddNewLine(); - AddEntryHtml(20 + OffsetSize + 160, "Bring them here"); - AddEntryButton(20, ArrowRightID1, ArrowRightID2, 5, ArrowRightWidth, ArrowRightHeight); - } - - AddNewLine(); - AddEntryHtml(20 + OffsetSize + 160, "Move to target"); - AddEntryButton(20, ArrowRightID1, ArrowRightID2, 6, ArrowRightWidth, ArrowRightHeight); - - if (m_From == m_Mobile || m_From.AccessLevel > m_Mobile.AccessLevel) - { - AddNewLine(); - if (m_Mobile.Alive) - { - AddEntryHtml(20 + OffsetSize + 160, "Kill"); - AddEntryButton(20, ArrowRightID1, ArrowRightID2, 7, ArrowRightWidth, ArrowRightHeight); - } - else - { - AddEntryHtml(20 + OffsetSize + 160, "Resurrect"); - AddEntryButton(20, ArrowRightID1, ArrowRightID2, 8, ArrowRightWidth, ArrowRightHeight); - } - } - - if (m_Mobile.NetState != null) - { - AddNewLine(); - AddEntryHtml(20 + OffsetSize + 160, "Client"); - AddEntryButton(20, ArrowRightID1, ArrowRightID2, 9, ArrowRightWidth, ArrowRightHeight); - } - - FinishPage(); - } - - private void InvokeCommand(string ip) - { - CommandSystem.Handle(m_From, $"{CommandSystem.Prefix}{ip}"); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Mobile.Deleted) - { - m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page, m_Mobile)); - return; - } - - if (!BaseCommand.IsAccessible(m_From, m_Mobile)) - { - m_From.SendMessage("That is no longer accessible."); - m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page, m_Mobile)); - return; - } - - switch (info.ButtonID) - { - case 0: - case 1: - { - m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page, m_Mobile)); - break; - } - case 2: // Properties - { - m_From.SendGump(new InterfaceMobileGump(m_From, m_Columns, m_List, m_Page, m_Mobile)); - m_From.SendGump(new PropertiesGump(m_From, m_Mobile)); - break; - } - case 3: // Delete - { - if (!m_Mobile.Player) - { - CommandLogging.WriteLine(m_From, "{0} {1} deleting {2}", m_From.AccessLevel, - CommandLogging.Format(m_From), CommandLogging.Format(m_Mobile)); - m_Mobile.Delete(); - m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page, m_Mobile)); - } - - break; - } - case 4: // Go there - { - m_From.SendGump(new InterfaceMobileGump(m_From, m_Columns, m_List, m_Page, m_Mobile)); - InvokeCommand($"Go {m_Mobile.Serial.Value}"); - break; - } - case 5: // Bring them here - { - if (m_From.Map == null || m_From.Map == Map.Internal) - { - m_From.SendMessage("You cannot bring that person here."); - } - else - { - m_From.SendGump(new InterfaceMobileGump(m_From, m_Columns, m_List, m_Page, m_Mobile)); - m_Mobile.MoveToWorld(m_From.Location, m_From.Map); - } - - break; - } - case 6: // Move to target - { - m_From.SendGump(new InterfaceMobileGump(m_From, m_Columns, m_List, m_Page, m_Mobile)); - m_From.Target = new MoveTarget(m_Mobile); - break; - } - case 7: // Kill - { - if (m_From == m_Mobile || m_From.AccessLevel > m_Mobile.AccessLevel) - m_Mobile.Kill(); - - m_From.SendGump(new InterfaceMobileGump(m_From, m_Columns, m_List, m_Page, m_Mobile)); - - break; - } - case 8: // Res - { - if (m_From == m_Mobile || m_From.AccessLevel > m_Mobile.AccessLevel) - { - m_Mobile.PlaySound(0x214); - m_Mobile.FixedEffect(0x376A, 10, 16); - - m_Mobile.Resurrect(); - } - - m_From.SendGump(new InterfaceMobileGump(m_From, m_Columns, m_List, m_Page, m_Mobile)); - - break; - } - case 9: // Client - { - m_From.SendGump(new InterfaceMobileGump(m_From, m_Columns, m_List, m_Page, m_Mobile)); - - if (m_Mobile.NetState != null) - m_From.SendGump(new ClientGump(m_From, m_Mobile.NetState)); - - break; - } - } - } - } -} +using System.Collections.Generic; +using Server.Gumps; +using Server.Network; +using Server.Targets; + +namespace Server.Commands.Generic +{ + public class InterfaceCommand : BaseCommand + { + public InterfaceCommand() + { + AccessLevel = AccessLevel.GameMaster; + Supports = CommandSupport.Complex | CommandSupport.Simple; + Commands = new[] { "Interface" }; + ObjectTypes = ObjectTypes.Both; + Usage = "Interface [view ]"; + Description = "Opens an interface to interact with matched objects. Generally used with condition arguments."; + ListOptimized = true; + } + + public override void ExecuteList(CommandEventArgs e, List list) + { + if (list.Count > 0) + { + var columns = new List { "Object" }; + + if (e.Length > 0) + { + var offset = 0; + + if (Insensitive.Equals(e.GetString(0), "view")) + ++offset; + + while (offset < e.Length) + columns.Add(e.GetString(offset++)); + } + + e.Mobile.SendGump(new InterfaceGump(e.Mobile, columns.ToArray(), list, 0, null)); + } + else + { + AddResponse("No matching objects found."); + } + } + } + + public class InterfaceGump : BaseGridGump + { + private const int EntriesPerPage = 15; + + private readonly string[] m_Columns; + private readonly Mobile m_From; + + private readonly List m_List; + private readonly int m_Page; + + private readonly object m_Select; + + public InterfaceGump(Mobile from, string[] columns, List list, int page, object select) : base(30, 30) + { + m_From = from; + + m_Columns = columns; + + m_List = list; + m_Page = page; + + m_Select = select; + + Render(); + } + + public void Render() + { + AddNewPage(); + + if (m_Page > 0) + AddEntryButton(20, ArrowLeftID1, ArrowLeftID2, 1, ArrowLeftWidth, ArrowLeftHeight); + else + AddEntryHeader(20); + + AddEntryHtml( + 40 + m_Columns.Length * 130 - 20 + (m_Columns.Length - 2) * OffsetSize, + Center( + $"Page {m_Page + 1} of {(m_List.Count + EntriesPerPage - 1) / EntriesPerPage}" + ) + ); + + if ((m_Page + 1) * EntriesPerPage < m_List.Count) + AddEntryButton(20, ArrowRightID1, ArrowRightID2, 2, ArrowRightWidth, ArrowRightHeight); + else + AddEntryHeader(20); + + if (m_Columns.Length > 1) + { + AddNewLine(); + + for (var i = 0; i < m_Columns.Length; ++i) + { + if (i > 0 && m_List.Count > 0) + { + var obj = m_List[0]; + + if (obj != null) + { + string failReason = null; + var chain = Properties.GetPropertyInfoChain( + m_From, + obj.GetType(), + m_Columns[i], + PropertyAccess.Read, + ref failReason + ); + + if (chain?.Length > 0) + { + m_Columns[i] = ""; + + for (var j = 0; j < chain.Length; ++j) + { + if (j > 0) + m_Columns[i] += '.'; + + m_Columns[i] += chain[j].Name; + } + } + } + } + + AddEntryHtml(130 + (i == 0 ? 40 : 0), m_Columns[i]); + } + + AddEntryHeader(20); + } + + for (int i = m_Page * EntriesPerPage, line = 0; line < EntriesPerPage && i < m_List.Count; ++i, ++line) + { + AddNewLine(); + + var obj = m_List[i]; + var isDeleted = false; + + if (obj is Item item) + { + if (!(isDeleted = item.Deleted)) + AddEntryHtml(40 + 130, item.GetType().Name); + } + else if (obj is Mobile mob) + { + if (!(isDeleted = mob.Deleted)) + AddEntryHtml(40 + 130, mob.Name); + } + + if (isDeleted) + { + AddEntryHtml(40 + 130, "(deleted)"); + + for (var j = 1; j < m_Columns.Length; ++j) + AddEntryHtml(130, "---"); + + AddEntryHeader(20); + } + else + { + for (var j = 1; j < m_Columns.Length; ++j) + { + var src = obj; + + string value; + var failReason = ""; + + var chain = Properties.GetPropertyInfoChain( + m_From, + src.GetType(), + m_Columns[j], + PropertyAccess.Read, + ref failReason + ); + + if (chain == null || chain.Length == 0) + { + value = "---"; + } + else + { + var p = Properties.GetPropertyInfo(ref src, chain, ref failReason); + + if (p == null) + value = "---"; + else + value = PropertiesGump.ValueToString(src, p); + } + + AddEntryHtml(130, value); + } + + var isSelected = m_Select != null && obj == m_Select; + + AddEntryButton( + 20, + isSelected ? 9762 : ArrowRightID1, + isSelected ? 9763 : ArrowRightID2, + 3 + i, + ArrowRightWidth, + ArrowRightHeight + ); + } + } + + FinishPage(); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + switch (info.ButtonID) + { + case 1: + { + if (m_Page > 0) + m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page - 1, m_Select)); + + break; + } + case 2: + { + if ((m_Page + 1) * EntriesPerPage < m_List.Count) + m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page + 1, m_Select)); + + break; + } + default: + { + var v = info.ButtonID - 3; + + if (v >= 0 && v < m_List.Count) + { + var obj = m_List[v]; + + if (!BaseCommand.IsAccessible(m_From, obj)) + { + m_From.SendLocalizedMessage(500447); // That is not accessible. + m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page, m_Select)); + break; + } + + if (obj is Item item && !item.Deleted) + m_From.SendGump(new InterfaceItemGump(m_From, m_Columns, m_List, m_Page, item)); + else if (obj is Mobile mobile && !mobile.Deleted) + m_From.SendGump(new InterfaceMobileGump(m_From, m_Columns, m_List, m_Page, mobile)); + else + m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page, m_Select)); + } + + break; + } + } + } + } + + public class InterfaceItemGump : BaseGridGump + { + private readonly string[] m_Columns; + private readonly Mobile m_From; + + private readonly Item m_Item; + + private readonly List m_List; + private readonly int m_Page; + + public InterfaceItemGump(Mobile from, string[] columns, List list, int page, Item item) : base(30, 30) + { + m_From = from; + + m_Columns = columns; + + m_List = list; + m_Page = page; + + m_Item = item; + + Render(); + } + + public void Render() + { + AddNewPage(); + + AddEntryButton(20, ArrowLeftID1, ArrowLeftID2, 1, ArrowLeftWidth, ArrowLeftHeight); + AddEntryHtml(160, m_Item.GetType().Name); + AddEntryHeader(20); + + AddNewLine(); + AddEntryHtml(20 + OffsetSize + 160, "Properties"); + AddEntryButton(20, ArrowRightID1, ArrowRightID2, 2, ArrowRightWidth, ArrowRightHeight); + + AddNewLine(); + AddEntryHtml(20 + OffsetSize + 160, "Delete"); + AddEntryButton(20, ArrowRightID1, ArrowRightID2, 3, ArrowRightWidth, ArrowRightHeight); + + AddNewLine(); + AddEntryHtml(20 + OffsetSize + 160, "Go there"); + AddEntryButton(20, ArrowRightID1, ArrowRightID2, 4, ArrowRightWidth, ArrowRightHeight); + + AddNewLine(); + AddEntryHtml(20 + OffsetSize + 160, "Move to target"); + AddEntryButton(20, ArrowRightID1, ArrowRightID2, 5, ArrowRightWidth, ArrowRightHeight); + + AddNewLine(); + AddEntryHtml(20 + OffsetSize + 160, "Bring to pack"); + AddEntryButton(20, ArrowRightID1, ArrowRightID2, 6, ArrowRightWidth, ArrowRightHeight); + + FinishPage(); + } + + private void InvokeCommand(string ip) + { + CommandSystem.Handle(m_From, $"{CommandSystem.Prefix}{ip}"); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Item.Deleted) + { + m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page, m_Item)); + return; + } + + if (!BaseCommand.IsAccessible(m_From, m_Item)) + { + m_From.SendMessage("That is no longer accessible."); + m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page, m_Item)); + return; + } + + switch (info.ButtonID) + { + case 0: + case 1: + { + m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page, m_Item)); + break; + } + case 2: // Properties + { + m_From.SendGump(new InterfaceItemGump(m_From, m_Columns, m_List, m_Page, m_Item)); + m_From.SendGump(new PropertiesGump(m_From, m_Item)); + break; + } + case 3: // Delete + { + CommandLogging.WriteLine( + m_From, + "{0} {1} deleting {2}", + m_From.AccessLevel, + CommandLogging.Format(m_From), + CommandLogging.Format(m_Item) + ); + m_Item.Delete(); + m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page, m_Item)); + break; + } + case 4: // Go there + { + m_From.SendGump(new InterfaceItemGump(m_From, m_Columns, m_List, m_Page, m_Item)); + InvokeCommand($"Go {m_Item.Serial.Value}"); + break; + } + case 5: // Move to target + { + m_From.SendGump(new InterfaceItemGump(m_From, m_Columns, m_List, m_Page, m_Item)); + m_From.Target = new MoveTarget(m_Item); + break; + } + case 6: // Bring to pack + { + var owner = m_Item.RootParent as Mobile; + + if (owner?.Map != null && owner.Map != Map.Internal && + !BaseCommand.IsAccessible(m_From, owner) /* !m_From.CanSee( owner )*/) + { + m_From.SendMessage("You can not get what you can not see."); + } + else if (owner != null && (owner.Map == null || owner.Map == Map.Internal) && owner.Hidden && + owner.AccessLevel >= m_From.AccessLevel) + { + m_From.SendMessage("You can not get what you can not see."); + } + else + { + m_From.SendGump(new InterfaceItemGump(m_From, m_Columns, m_List, m_Page, m_Item)); + m_From.AddToBackpack(m_Item); + } + + break; + } + } + } + } + + public class InterfaceMobileGump : BaseGridGump + { + private readonly string[] m_Columns; + private readonly Mobile m_From; + + private readonly List m_List; + + private readonly Mobile m_Mobile; + private readonly int m_Page; + + public InterfaceMobileGump(Mobile from, string[] columns, List list, int page, Mobile mob) + : base(30, 30) + { + m_From = from; + + m_Columns = columns; + + m_List = list; + m_Page = page; + + m_Mobile = mob; + + Render(); + } + + public void Render() + { + AddNewPage(); + + AddEntryButton(20, ArrowLeftID1, ArrowLeftID2, 1, ArrowLeftWidth, ArrowLeftHeight); + AddEntryHtml(160, m_Mobile.Name); + AddEntryHeader(20); + + AddNewLine(); + AddEntryHtml(20 + OffsetSize + 160, "Properties"); + AddEntryButton(20, ArrowRightID1, ArrowRightID2, 2, ArrowRightWidth, ArrowRightHeight); + + if (!m_Mobile.Player) + { + AddNewLine(); + AddEntryHtml(20 + OffsetSize + 160, "Delete"); + AddEntryButton(20, ArrowRightID1, ArrowRightID2, 3, ArrowRightWidth, ArrowRightHeight); + } + + if (m_Mobile != m_From) + { + AddNewLine(); + AddEntryHtml(20 + OffsetSize + 160, "Go to there"); + AddEntryButton(20, ArrowRightID1, ArrowRightID2, 4, ArrowRightWidth, ArrowRightHeight); + + AddNewLine(); + AddEntryHtml(20 + OffsetSize + 160, "Bring them here"); + AddEntryButton(20, ArrowRightID1, ArrowRightID2, 5, ArrowRightWidth, ArrowRightHeight); + } + + AddNewLine(); + AddEntryHtml(20 + OffsetSize + 160, "Move to target"); + AddEntryButton(20, ArrowRightID1, ArrowRightID2, 6, ArrowRightWidth, ArrowRightHeight); + + if (m_From == m_Mobile || m_From.AccessLevel > m_Mobile.AccessLevel) + { + AddNewLine(); + if (m_Mobile.Alive) + { + AddEntryHtml(20 + OffsetSize + 160, "Kill"); + AddEntryButton(20, ArrowRightID1, ArrowRightID2, 7, ArrowRightWidth, ArrowRightHeight); + } + else + { + AddEntryHtml(20 + OffsetSize + 160, "Resurrect"); + AddEntryButton(20, ArrowRightID1, ArrowRightID2, 8, ArrowRightWidth, ArrowRightHeight); + } + } + + if (m_Mobile.NetState != null) + { + AddNewLine(); + AddEntryHtml(20 + OffsetSize + 160, "Client"); + AddEntryButton(20, ArrowRightID1, ArrowRightID2, 9, ArrowRightWidth, ArrowRightHeight); + } + + FinishPage(); + } + + private void InvokeCommand(string ip) + { + CommandSystem.Handle(m_From, $"{CommandSystem.Prefix}{ip}"); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Mobile.Deleted) + { + m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page, m_Mobile)); + return; + } + + if (!BaseCommand.IsAccessible(m_From, m_Mobile)) + { + m_From.SendMessage("That is no longer accessible."); + m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page, m_Mobile)); + return; + } + + switch (info.ButtonID) + { + case 0: + case 1: + { + m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page, m_Mobile)); + break; + } + case 2: // Properties + { + m_From.SendGump(new InterfaceMobileGump(m_From, m_Columns, m_List, m_Page, m_Mobile)); + m_From.SendGump(new PropertiesGump(m_From, m_Mobile)); + break; + } + case 3: // Delete + { + if (!m_Mobile.Player) + { + CommandLogging.WriteLine( + m_From, + "{0} {1} deleting {2}", + m_From.AccessLevel, + CommandLogging.Format(m_From), + CommandLogging.Format(m_Mobile) + ); + m_Mobile.Delete(); + m_From.SendGump(new InterfaceGump(m_From, m_Columns, m_List, m_Page, m_Mobile)); + } + + break; + } + case 4: // Go there + { + m_From.SendGump(new InterfaceMobileGump(m_From, m_Columns, m_List, m_Page, m_Mobile)); + InvokeCommand($"Go {m_Mobile.Serial.Value}"); + break; + } + case 5: // Bring them here + { + if (m_From.Map == null || m_From.Map == Map.Internal) + { + m_From.SendMessage("You cannot bring that person here."); + } + else + { + m_From.SendGump(new InterfaceMobileGump(m_From, m_Columns, m_List, m_Page, m_Mobile)); + m_Mobile.MoveToWorld(m_From.Location, m_From.Map); + } + + break; + } + case 6: // Move to target + { + m_From.SendGump(new InterfaceMobileGump(m_From, m_Columns, m_List, m_Page, m_Mobile)); + m_From.Target = new MoveTarget(m_Mobile); + break; + } + case 7: // Kill + { + if (m_From == m_Mobile || m_From.AccessLevel > m_Mobile.AccessLevel) + m_Mobile.Kill(); + + m_From.SendGump(new InterfaceMobileGump(m_From, m_Columns, m_List, m_Page, m_Mobile)); + + break; + } + case 8: // Res + { + if (m_From == m_Mobile || m_From.AccessLevel > m_Mobile.AccessLevel) + { + m_Mobile.PlaySound(0x214); + m_Mobile.FixedEffect(0x376A, 10, 16); + + m_Mobile.Resurrect(); + } + + m_From.SendGump(new InterfaceMobileGump(m_From, m_Columns, m_List, m_Page, m_Mobile)); + + break; + } + case 9: // Client + { + m_From.SendGump(new InterfaceMobileGump(m_From, m_Columns, m_List, m_Page, m_Mobile)); + + if (m_Mobile.NetState != null) + m_From.SendGump(new ClientGump(m_From, m_Mobile.NetState)); + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Extensions/BaseExtension.cs b/Projects/UOContent/Commands/Generic/Extensions/BaseExtension.cs index 78594b8b3..9a339d355 100644 --- a/Projects/UOContent/Commands/Generic/Extensions/BaseExtension.cs +++ b/Projects/UOContent/Commands/Generic/Extensions/BaseExtension.cs @@ -1,130 +1,130 @@ -using System; -using System.Collections.Generic; - -namespace Server.Commands.Generic -{ - public delegate BaseExtension ExtensionConstructor(); - - public sealed class ExtensionInfo - { - public ExtensionInfo(int order, string name, int size, ExtensionConstructor constructor) - { - Name = name; - Size = size; - - Order = order; - - Constructor = constructor; - } - - public static Dictionary Table { get; } = - new Dictionary(StringComparer.InvariantCultureIgnoreCase); - - public int Order { get; } - - public string Name { get; } - - public int Size { get; } - - public bool IsFixedSize => Size >= 0; - - public ExtensionConstructor Constructor { get; } - - public static void Register(ExtensionInfo ext) - { - Table[ext.Name] = ext; - } - } - - public sealed class Extensions : List - { - public bool IsValid(object obj) - { - for (int i = 0; i < Count; ++i) - if (!this[i].IsValid(obj)) - return false; - - return true; - } - - public void Filter(List list) - { - for (int i = 0; i < Count; ++i) - this[i].Filter(list); - } - - public static Extensions Parse(Mobile from, ref string[] args) - { - Extensions parsed = new Extensions(); - - int size = args.Length; - - Type baseType = null; - - for (int i = args.Length - 1; i >= 0; --i) - { - if (!ExtensionInfo.Table.TryGetValue(args[i], out ExtensionInfo extInfo)) - continue; - - if (extInfo.IsFixedSize && i != size - extInfo.Size - 1) - throw new Exception("Invalid extended argument count."); - - BaseExtension ext = extInfo.Constructor(); - - ext.Parse(from, args, i + 1, size - i - 1); - - if (ext is WhereExtension extension) - baseType = extension.Conditional.Type; - - parsed.Add(ext); - - size = i; - } - - parsed.Sort((a, b) => a.Order - b.Order); - - AssemblyEmitter emitter = null; - - foreach (BaseExtension update in parsed) - update.Optimize(from, baseType, ref emitter); - - if (size != args.Length) - { - string[] old = args; - args = new string[size]; - - for (int i = 0; i < args.Length; ++i) - args[i] = old[i]; - } - - return parsed; - } - } - - public abstract class BaseExtension - { - public abstract ExtensionInfo Info { get; } - - public string Name => Info.Name; - - public int Size => Info.Size; - - public bool IsFixedSize => Info.IsFixedSize; - - public int Order => Info.Order; - - public virtual void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly) - { - } - - public virtual void Parse(Mobile from, string[] arguments, int offset, int size) - { - } - - public virtual bool IsValid(object obj) => true; - - public virtual void Filter(List list) - { - } - } -} \ No newline at end of file +using System; +using System.Collections.Generic; + +namespace Server.Commands.Generic +{ + public delegate BaseExtension ExtensionConstructor(); + + public sealed class ExtensionInfo + { + public ExtensionInfo(int order, string name, int size, ExtensionConstructor constructor) + { + Name = name; + Size = size; + + Order = order; + + Constructor = constructor; + } + + public static Dictionary Table { get; } = + new Dictionary(StringComparer.InvariantCultureIgnoreCase); + + public int Order { get; } + + public string Name { get; } + + public int Size { get; } + + public bool IsFixedSize => Size >= 0; + + public ExtensionConstructor Constructor { get; } + + public static void Register(ExtensionInfo ext) + { + Table[ext.Name] = ext; + } + } + + public sealed class Extensions : List + { + public bool IsValid(object obj) + { + for (var i = 0; i < Count; ++i) + if (!this[i].IsValid(obj)) + return false; + + return true; + } + + public void Filter(List list) + { + for (var i = 0; i < Count; ++i) + this[i].Filter(list); + } + + public static Extensions Parse(Mobile from, ref string[] args) + { + var parsed = new Extensions(); + + var size = args.Length; + + Type baseType = null; + + for (var i = args.Length - 1; i >= 0; --i) + { + if (!ExtensionInfo.Table.TryGetValue(args[i], out var extInfo)) + continue; + + if (extInfo.IsFixedSize && i != size - extInfo.Size - 1) + throw new Exception("Invalid extended argument count."); + + var ext = extInfo.Constructor(); + + ext.Parse(from, args, i + 1, size - i - 1); + + if (ext is WhereExtension extension) + baseType = extension.Conditional.Type; + + parsed.Add(ext); + + size = i; + } + + parsed.Sort((a, b) => a.Order - b.Order); + + AssemblyEmitter emitter = null; + + foreach (var update in parsed) + update.Optimize(from, baseType, ref emitter); + + if (size != args.Length) + { + var old = args; + args = new string[size]; + + for (var i = 0; i < args.Length; ++i) + args[i] = old[i]; + } + + return parsed; + } + } + + public abstract class BaseExtension + { + public abstract ExtensionInfo Info { get; } + + public string Name => Info.Name; + + public int Size => Info.Size; + + public bool IsFixedSize => Info.IsFixedSize; + + public int Order => Info.Order; + + public virtual void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly) + { + } + + public virtual void Parse(Mobile from, string[] arguments, int offset, int size) + { + } + + public virtual bool IsValid(object obj) => true; + + public virtual void Filter(List list) + { + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Extensions/Compilers/ConditionalCompiler.cs b/Projects/UOContent/Commands/Generic/Extensions/Compilers/ConditionalCompiler.cs index 673a6c633..ae4521178 100644 --- a/Projects/UOContent/Commands/Generic/Extensions/Compilers/ConditionalCompiler.cs +++ b/Projects/UOContent/Commands/Generic/Extensions/Compilers/ConditionalCompiler.cs @@ -1,523 +1,539 @@ -using System; -using System.Globalization; -using System.Reflection; -using System.Reflection.Emit; -using Server.Utilities; - -namespace Server.Commands.Generic -{ - public interface IConditional - { - bool Verify(object obj); - } - - public interface ICondition - { - // Invoked during the constructor - void Construct(TypeBuilder typeBuilder, ILGenerator il, int index); - - // Target object will be loaded on the stack - void Compile(MethodEmitter emitter); - } - - public sealed class TypeCondition : ICondition - { - public static TypeCondition Default = new TypeCondition(); - - void ICondition.Construct(TypeBuilder typeBuilder, ILGenerator il, int index) - { - } - - void ICondition.Compile(MethodEmitter emitter) - { - // The object was safely cast to be the conditionals type - // If it's null, then the type cast didn't work... - - emitter.LoadNull(); - emitter.Compare(OpCodes.Ceq); - emitter.LogicalNot(); - } - } - - public sealed class PropertyValue - { - public PropertyValue(Type type, object value) - { - Type = type; - Value = value; - } - - public Type Type { get; } - - public object Value { get; private set; } - - public FieldInfo Field { get; private set; } - - public bool HasField => Field != null; - - public void Load(MethodEmitter method) - { - if (Field != null) - { - method.LoadArgument(0); - method.LoadField(Field); - } - else if (Value == null) - { - method.LoadNull(Type); - } - else - { - if (Value is int i) - method.Load(i); - else if (Value is long l) - method.Load(l); - else if (Value is float f) - method.Load(f); - else if (Value is double d) - method.Load(d); - else if (Value is char c) - method.Load(c); - else if (Value is bool b) - method.Load(b); - else if (Value is string s) - method.Load(s); - else if (Value is Enum e) - method.Load(e); - else - throw new InvalidOperationException("Unrecognized comparison value."); - } - } - - public void Acquire(TypeBuilder typeBuilder, ILGenerator il, string fieldName) - { - if (!(Value is string toParse)) - return; - - if (!Type.IsValueType && toParse == "null") - { - Value = null; - } - else if (Type == typeof(string)) - { - if (toParse == @"@""null""") - toParse = "null"; - - Value = toParse; - } - else if (Type.IsEnum) - { - Value = Enum.Parse(Type, toParse, true); - } - else - { - MethodInfo parseMethod; - object[] parseArgs; - - MethodInfo parseNumber = Type.GetMethod( - "Parse", - BindingFlags.Public | BindingFlags.Static, - null, - new[] { typeof(string), typeof(NumberStyles) }, - null); - - if (parseNumber != null) - { - NumberStyles style = NumberStyles.Integer; - - if (Insensitive.StartsWith(toParse, "0x")) - { - style = NumberStyles.HexNumber; - toParse = toParse.Substring(2); - } - - parseMethod = parseNumber; - parseArgs = new object[] { toParse, style }; - } - else - { - MethodInfo parseGeneral = Type.GetMethod( - "Parse", - BindingFlags.Public | BindingFlags.Static, - null, - new[] { typeof(string) }, - null); - - parseMethod = parseGeneral; - parseArgs = new object[] { toParse }; - } - - if (parseMethod != null) - { - Value = parseMethod.Invoke(null, parseArgs); - - if (!Type.IsPrimitive) - { - Field = typeBuilder.DefineField( - fieldName, - Type, - FieldAttributes.Private | FieldAttributes.InitOnly); - - // parseMethod.Invoke(null, - // parseArgs.Length == 2 ? new object[] {toParse, (int) parseArgs[1]} : new object[] {toParse}); - - il.Emit(OpCodes.Ldarg_0); - - il.Emit(OpCodes.Ldstr, toParse); - - if (parseArgs.Length == 2) // dirty evil hack :-( - il.Emit(OpCodes.Ldc_I4, (int)parseArgs[1]); - - il.Emit(OpCodes.Call, parseMethod); - il.Emit(OpCodes.Stfld, Field); - } - } - else - { - throw new InvalidOperationException( - $"Unable to convert string \"{Value}\" into type '{Type}'."); - } - } - } - } - - public abstract class PropertyCondition : ICondition - { - protected bool m_Not; - protected Property m_Property; - - public PropertyCondition(Property property, bool not) - { - m_Property = property; - m_Not = not; - } - - public abstract void Construct(TypeBuilder typeBuilder, ILGenerator il, int index); - - public abstract void Compile(MethodEmitter emitter); - } - - public enum StringOperator - { - Equal, - NotEqual, - - Contains, - - StartsWith, - EndsWith - } - - public sealed class StringCondition : PropertyCondition - { - private readonly bool m_IgnoreCase; - private readonly StringOperator m_Operator; - private readonly PropertyValue m_Value; - - public StringCondition(Property property, bool not, StringOperator op, object value, bool ignoreCase) - : base(property, not) - { - m_Operator = op; - m_Value = new PropertyValue(property.Type, value); - - m_IgnoreCase = ignoreCase; - } - - public override void Construct(TypeBuilder typeBuilder, ILGenerator il, int index) - { - m_Value.Acquire(typeBuilder, il, $"v{index}"); - } - - public override void Compile(MethodEmitter emitter) - { - bool inverse = false; - - string methodName; - - switch (m_Operator) - { - case StringOperator.Equal: - methodName = "Equals"; - break; - - case StringOperator.NotEqual: - methodName = "Equals"; - inverse = true; - break; - - case StringOperator.Contains: - methodName = "Contains"; - break; - - case StringOperator.StartsWith: - methodName = "StartsWith"; - break; - - case StringOperator.EndsWith: - methodName = "EndsWith"; - break; - - default: - throw new InvalidOperationException("Invalid string comparison operator."); - } - - if (m_IgnoreCase || methodName == "Equals") - { - Type type = m_IgnoreCase ? typeof(Insensitive) : typeof(string); - - emitter.BeginCall( - type.GetMethod( - methodName, - BindingFlags.Public | BindingFlags.Static, - null, - new[] - { - typeof(string), - typeof(string) - }, - null)); - - emitter.Chain(m_Property); - m_Value.Load(emitter); - - emitter.FinishCall(); - } - else - { - Label notNull = emitter.CreateLabel(); - Label moveOn = emitter.CreateLabel(); - - LocalBuilder temp = emitter.AcquireTemp(m_Property.Type); - - emitter.Chain(m_Property); - - emitter.StoreLocal(temp); - emitter.LoadLocal(temp); - - emitter.BranchIfTrue(notNull); - - emitter.Load(false); - emitter.Pop(); - emitter.Branch(moveOn); - - emitter.MarkLabel(notNull); - emitter.LoadLocal(temp); - - emitter.BeginCall( - typeof(string).GetMethod( - methodName, - BindingFlags.Public | BindingFlags.Instance, - null, - new[] - { - typeof(string) - }, - null)); - - m_Value.Load(emitter); - - emitter.FinishCall(); - - emitter.MarkLabel(moveOn); - } - - if (m_Not != inverse) - emitter.LogicalNot(); - } - } - - public enum ComparisonOperator - { - Equal, - NotEqual, - Greater, - GreaterEqual, - Lesser, - LesserEqual - } - - public sealed class ComparisonCondition : PropertyCondition - { - private readonly ComparisonOperator m_Operator; - private readonly PropertyValue m_Value; - - public ComparisonCondition(Property property, bool not, ComparisonOperator op, object value) - : base(property, not) - { - m_Operator = op; - m_Value = new PropertyValue(property.Type, value); - } - - public override void Construct(TypeBuilder typeBuilder, ILGenerator il, int index) - { - m_Value.Acquire(typeBuilder, il, $"v{index}"); - } - - public override void Compile(MethodEmitter emitter) - { - emitter.Chain(m_Property); - - bool inverse = false; - - bool couldCompare = - emitter.CompareTo(1, () => { m_Value.Load(emitter); }); - - if (couldCompare) - { - emitter.Load(0); - - switch (m_Operator) - { - case ComparisonOperator.Equal: - emitter.Compare(OpCodes.Ceq); - break; - - case ComparisonOperator.NotEqual: - emitter.Compare(OpCodes.Ceq); - inverse = true; - break; - - case ComparisonOperator.Greater: - emitter.Compare(OpCodes.Cgt); - break; - - case ComparisonOperator.GreaterEqual: - emitter.Compare(OpCodes.Clt); - inverse = true; - break; - - case ComparisonOperator.Lesser: - emitter.Compare(OpCodes.Clt); - break; - - case ComparisonOperator.LesserEqual: - emitter.Compare(OpCodes.Cgt); - inverse = true; - break; - - default: - throw new InvalidOperationException("Invalid comparison operator."); - } - } - else - { - // This type is -not- comparable - // We can only support == and != operations - - m_Value.Load(emitter); - - switch (m_Operator) - { - case ComparisonOperator.Equal: - emitter.Compare(OpCodes.Ceq); - break; - - case ComparisonOperator.NotEqual: - emitter.Compare(OpCodes.Ceq); - inverse = true; - break; - - case ComparisonOperator.Greater: - case ComparisonOperator.GreaterEqual: - case ComparisonOperator.Lesser: - case ComparisonOperator.LesserEqual: - throw new InvalidOperationException("Property does not support relational comparisons."); - - default: - throw new InvalidOperationException("Invalid operator."); - } - } - - if (m_Not != inverse) - emitter.LogicalNot(); - } - } - - public static class ConditionalCompiler - { - public static IConditional Compile(AssemblyEmitter assembly, Type objectType, ICondition[] conditions, int index) - { - TypeBuilder typeBuilder = assembly.DefineType( - $"__conditional{index}", - TypeAttributes.Public, - typeof(object)); - { - ConstructorBuilder ctor = typeBuilder.DefineConstructor( - MethodAttributes.Public, - CallingConventions.Standard, - Type.EmptyTypes); - - ILGenerator il = ctor.GetILGenerator(); - - // : base() - il.Emit(OpCodes.Ldarg_0); - il.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); - - for (int i = 0; i < conditions.Length; ++i) - conditions[i].Construct(typeBuilder, il, i); - - // return; - il.Emit(OpCodes.Ret); - } - - typeBuilder.AddInterfaceImplementation(typeof(IConditional)); - - MethodBuilder compareMethod; - { - MethodEmitter emitter = new MethodEmitter(typeBuilder); - - emitter.Define( - /* name */ "Verify", - /* attr */ MethodAttributes.Public | MethodAttributes.Virtual, - /* return */ typeof(bool), - /* params */ new[] { typeof(object) }); - - LocalBuilder obj = emitter.CreateLocal(objectType); - LocalBuilder eq = emitter.CreateLocal(typeof(bool)); - - emitter.LoadArgument(1); - emitter.CastAs(objectType); - emitter.StoreLocal(obj); - - Label done = emitter.CreateLabel(); - - for (int i = 0; i < conditions.Length; ++i) - { - if (i > 0) - { - emitter.LoadLocal(eq); - - emitter.BranchIfFalse(done); - } - - emitter.LoadLocal(obj); - - conditions[i].Compile(emitter); - - emitter.StoreLocal(eq); - } - - emitter.MarkLabel(done); - - emitter.LoadLocal(eq); - - emitter.Return(); - - typeBuilder.DefineMethodOverride( - emitter.Method, - typeof(IConditional).GetMethod( - "Verify", - new[] - { - typeof(object) - })); - - compareMethod = emitter.Method; - } - - Type conditionalType = typeBuilder.CreateType(); - - return (IConditional)ActivatorUtil.CreateInstance(conditionalType); - } - } -} +using System; +using System.Globalization; +using System.Reflection; +using System.Reflection.Emit; +using Server.Utilities; + +namespace Server.Commands.Generic +{ + public interface IConditional + { + bool Verify(object obj); + } + + public interface ICondition + { + // Invoked during the constructor + void Construct(TypeBuilder typeBuilder, ILGenerator il, int index); + + // Target object will be loaded on the stack + void Compile(MethodEmitter emitter); + } + + public sealed class TypeCondition : ICondition + { + public static TypeCondition Default = new TypeCondition(); + + void ICondition.Construct(TypeBuilder typeBuilder, ILGenerator il, int index) + { + } + + void ICondition.Compile(MethodEmitter emitter) + { + // The object was safely cast to be the conditionals type + // If it's null, then the type cast didn't work... + + emitter.LoadNull(); + emitter.Compare(OpCodes.Ceq); + emitter.LogicalNot(); + } + } + + public sealed class PropertyValue + { + public PropertyValue(Type type, object value) + { + Type = type; + Value = value; + } + + public Type Type { get; } + + public object Value { get; private set; } + + public FieldInfo Field { get; private set; } + + public bool HasField => Field != null; + + public void Load(MethodEmitter method) + { + if (Field != null) + { + method.LoadArgument(0); + method.LoadField(Field); + } + else if (Value == null) + { + method.LoadNull(Type); + } + else + { + if (Value is int i) + method.Load(i); + else if (Value is long l) + method.Load(l); + else if (Value is float f) + method.Load(f); + else if (Value is double d) + method.Load(d); + else if (Value is char c) + method.Load(c); + else if (Value is bool b) + method.Load(b); + else if (Value is string s) + method.Load(s); + else if (Value is Enum e) + method.Load(e); + else + throw new InvalidOperationException("Unrecognized comparison value."); + } + } + + public void Acquire(TypeBuilder typeBuilder, ILGenerator il, string fieldName) + { + if (!(Value is string toParse)) + return; + + if (!Type.IsValueType && toParse == "null") + { + Value = null; + } + else if (Type == typeof(string)) + { + if (toParse == @"@""null""") + toParse = "null"; + + Value = toParse; + } + else if (Type.IsEnum) + { + Value = Enum.Parse(Type, toParse, true); + } + else + { + MethodInfo parseMethod; + object[] parseArgs; + + var parseNumber = Type.GetMethod( + "Parse", + BindingFlags.Public | BindingFlags.Static, + null, + new[] { typeof(string), typeof(NumberStyles) }, + null + ); + + if (parseNumber != null) + { + var style = NumberStyles.Integer; + + if (Insensitive.StartsWith(toParse, "0x")) + { + style = NumberStyles.HexNumber; + toParse = toParse.Substring(2); + } + + parseMethod = parseNumber; + parseArgs = new object[] { toParse, style }; + } + else + { + var parseGeneral = Type.GetMethod( + "Parse", + BindingFlags.Public | BindingFlags.Static, + null, + new[] { typeof(string) }, + null + ); + + parseMethod = parseGeneral; + parseArgs = new object[] { toParse }; + } + + if (parseMethod != null) + { + Value = parseMethod.Invoke(null, parseArgs); + + if (!Type.IsPrimitive) + { + Field = typeBuilder.DefineField( + fieldName, + Type, + FieldAttributes.Private | FieldAttributes.InitOnly + ); + + // parseMethod.Invoke(null, + // parseArgs.Length == 2 ? new object[] {toParse, (int) parseArgs[1]} : new object[] {toParse}); + + il.Emit(OpCodes.Ldarg_0); + + il.Emit(OpCodes.Ldstr, toParse); + + if (parseArgs.Length == 2) // dirty evil hack :-( + il.Emit(OpCodes.Ldc_I4, (int)parseArgs[1]); + + il.Emit(OpCodes.Call, parseMethod); + il.Emit(OpCodes.Stfld, Field); + } + } + else + { + throw new InvalidOperationException( + $"Unable to convert string \"{Value}\" into type '{Type}'." + ); + } + } + } + } + + public abstract class PropertyCondition : ICondition + { + protected bool m_Not; + protected Property m_Property; + + public PropertyCondition(Property property, bool not) + { + m_Property = property; + m_Not = not; + } + + public abstract void Construct(TypeBuilder typeBuilder, ILGenerator il, int index); + + public abstract void Compile(MethodEmitter emitter); + } + + public enum StringOperator + { + Equal, + NotEqual, + + Contains, + + StartsWith, + EndsWith + } + + public sealed class StringCondition : PropertyCondition + { + private readonly bool m_IgnoreCase; + private readonly StringOperator m_Operator; + private readonly PropertyValue m_Value; + + public StringCondition(Property property, bool not, StringOperator op, object value, bool ignoreCase) + : base(property, not) + { + m_Operator = op; + m_Value = new PropertyValue(property.Type, value); + + m_IgnoreCase = ignoreCase; + } + + public override void Construct(TypeBuilder typeBuilder, ILGenerator il, int index) + { + m_Value.Acquire(typeBuilder, il, $"v{index}"); + } + + public override void Compile(MethodEmitter emitter) + { + var inverse = false; + + string methodName; + + switch (m_Operator) + { + case StringOperator.Equal: + methodName = "Equals"; + break; + + case StringOperator.NotEqual: + methodName = "Equals"; + inverse = true; + break; + + case StringOperator.Contains: + methodName = "Contains"; + break; + + case StringOperator.StartsWith: + methodName = "StartsWith"; + break; + + case StringOperator.EndsWith: + methodName = "EndsWith"; + break; + + default: + throw new InvalidOperationException("Invalid string comparison operator."); + } + + if (m_IgnoreCase || methodName == "Equals") + { + var type = m_IgnoreCase ? typeof(Insensitive) : typeof(string); + + emitter.BeginCall( + type.GetMethod( + methodName, + BindingFlags.Public | BindingFlags.Static, + null, + new[] + { + typeof(string), + typeof(string) + }, + null + ) + ); + + emitter.Chain(m_Property); + m_Value.Load(emitter); + + emitter.FinishCall(); + } + else + { + var notNull = emitter.CreateLabel(); + var moveOn = emitter.CreateLabel(); + + var temp = emitter.AcquireTemp(m_Property.Type); + + emitter.Chain(m_Property); + + emitter.StoreLocal(temp); + emitter.LoadLocal(temp); + + emitter.BranchIfTrue(notNull); + + emitter.Load(false); + emitter.Pop(); + emitter.Branch(moveOn); + + emitter.MarkLabel(notNull); + emitter.LoadLocal(temp); + + emitter.BeginCall( + typeof(string).GetMethod( + methodName, + BindingFlags.Public | BindingFlags.Instance, + null, + new[] + { + typeof(string) + }, + null + ) + ); + + m_Value.Load(emitter); + + emitter.FinishCall(); + + emitter.MarkLabel(moveOn); + } + + if (m_Not != inverse) + emitter.LogicalNot(); + } + } + + public enum ComparisonOperator + { + Equal, + NotEqual, + Greater, + GreaterEqual, + Lesser, + LesserEqual + } + + public sealed class ComparisonCondition : PropertyCondition + { + private readonly ComparisonOperator m_Operator; + private readonly PropertyValue m_Value; + + public ComparisonCondition(Property property, bool not, ComparisonOperator op, object value) + : base(property, not) + { + m_Operator = op; + m_Value = new PropertyValue(property.Type, value); + } + + public override void Construct(TypeBuilder typeBuilder, ILGenerator il, int index) + { + m_Value.Acquire(typeBuilder, il, $"v{index}"); + } + + public override void Compile(MethodEmitter emitter) + { + emitter.Chain(m_Property); + + var inverse = false; + + var couldCompare = + emitter.CompareTo(1, () => { m_Value.Load(emitter); }); + + if (couldCompare) + { + emitter.Load(0); + + switch (m_Operator) + { + case ComparisonOperator.Equal: + emitter.Compare(OpCodes.Ceq); + break; + + case ComparisonOperator.NotEqual: + emitter.Compare(OpCodes.Ceq); + inverse = true; + break; + + case ComparisonOperator.Greater: + emitter.Compare(OpCodes.Cgt); + break; + + case ComparisonOperator.GreaterEqual: + emitter.Compare(OpCodes.Clt); + inverse = true; + break; + + case ComparisonOperator.Lesser: + emitter.Compare(OpCodes.Clt); + break; + + case ComparisonOperator.LesserEqual: + emitter.Compare(OpCodes.Cgt); + inverse = true; + break; + + default: + throw new InvalidOperationException("Invalid comparison operator."); + } + } + else + { + // This type is -not- comparable + // We can only support == and != operations + + m_Value.Load(emitter); + + switch (m_Operator) + { + case ComparisonOperator.Equal: + emitter.Compare(OpCodes.Ceq); + break; + + case ComparisonOperator.NotEqual: + emitter.Compare(OpCodes.Ceq); + inverse = true; + break; + + case ComparisonOperator.Greater: + case ComparisonOperator.GreaterEqual: + case ComparisonOperator.Lesser: + case ComparisonOperator.LesserEqual: + throw new InvalidOperationException("Property does not support relational comparisons."); + + default: + throw new InvalidOperationException("Invalid operator."); + } + } + + if (m_Not != inverse) + emitter.LogicalNot(); + } + } + + public static class ConditionalCompiler + { + public static IConditional Compile(AssemblyEmitter assembly, Type objectType, ICondition[] conditions, int index) + { + var typeBuilder = assembly.DefineType( + $"__conditional{index}", + TypeAttributes.Public, + typeof(object) + ); + { + var ctor = typeBuilder.DefineConstructor( + MethodAttributes.Public, + CallingConventions.Standard, + Type.EmptyTypes + ); + + var il = ctor.GetILGenerator(); + + // : base() + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); + + for (var i = 0; i < conditions.Length; ++i) + conditions[i].Construct(typeBuilder, il, i); + + // return; + il.Emit(OpCodes.Ret); + } + + typeBuilder.AddInterfaceImplementation(typeof(IConditional)); + + MethodBuilder compareMethod; + { + var emitter = new MethodEmitter(typeBuilder); + + emitter.Define( + /* name */ "Verify", + /* attr */ + MethodAttributes.Public | MethodAttributes.Virtual, + /* return */ + typeof(bool), + /* params */ + new[] { typeof(object) } + ); + + var obj = emitter.CreateLocal(objectType); + var eq = emitter.CreateLocal(typeof(bool)); + + emitter.LoadArgument(1); + emitter.CastAs(objectType); + emitter.StoreLocal(obj); + + var done = emitter.CreateLabel(); + + for (var i = 0; i < conditions.Length; ++i) + { + if (i > 0) + { + emitter.LoadLocal(eq); + + emitter.BranchIfFalse(done); + } + + emitter.LoadLocal(obj); + + conditions[i].Compile(emitter); + + emitter.StoreLocal(eq); + } + + emitter.MarkLabel(done); + + emitter.LoadLocal(eq); + + emitter.Return(); + + typeBuilder.DefineMethodOverride( + emitter.Method, + typeof(IConditional).GetMethod( + "Verify", + new[] + { + typeof(object) + } + ) + ); + + compareMethod = emitter.Method; + } + + var conditionalType = typeBuilder.CreateType(); + + return (IConditional)ActivatorUtil.CreateInstance(conditionalType); + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Extensions/Compilers/DistinctCompiler.cs b/Projects/UOContent/Commands/Generic/Extensions/Compilers/DistinctCompiler.cs index 79d7f7980..fc86e8651 100644 --- a/Projects/UOContent/Commands/Generic/Extensions/Compilers/DistinctCompiler.cs +++ b/Projects/UOContent/Commands/Generic/Extensions/Compilers/DistinctCompiler.cs @@ -1,224 +1,250 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Reflection.Emit; -using Server.Utilities; - -namespace Server.Commands.Generic -{ - public static class DistinctCompiler - { - public static IComparer Compile(AssemblyEmitter assembly, Type objectType, Property[] props) - { - TypeBuilder typeBuilder = assembly.DefineType( - "__distinct", - TypeAttributes.Public, - typeof(object)); - { - ConstructorBuilder ctor = typeBuilder.DefineConstructor( - MethodAttributes.Public, - CallingConventions.Standard, - Type.EmptyTypes); - - ILGenerator il = ctor.GetILGenerator(); - - // : base() - il.Emit(OpCodes.Ldarg_0); - il.Emit(OpCodes.Call, typeof(T).GetConstructor(Type.EmptyTypes) ?? - throw new Exception($"Could not find empty constructor for type {typeof(T).FullName}")); - - // return; - il.Emit(OpCodes.Ret); - } - - typeBuilder.AddInterfaceImplementation(typeof(IComparer)); - - MethodBuilder compareMethod; - { - MethodEmitter emitter = new MethodEmitter(typeBuilder); - - emitter.Define( - /* name */ "Compare", - /* attr */ MethodAttributes.Public | MethodAttributes.Virtual, - /* return */ typeof(int), - /* params */ new[] { typeof(T), typeof(T) }); - - LocalBuilder a = emitter.CreateLocal(objectType); - LocalBuilder b = emitter.CreateLocal(objectType); - - LocalBuilder v = emitter.CreateLocal(typeof(int)); - - emitter.LoadArgument(1); - emitter.CastAs(objectType); - emitter.StoreLocal(a); - - emitter.LoadArgument(2); - emitter.CastAs(objectType); - emitter.StoreLocal(b); - - emitter.Load(0); - emitter.StoreLocal(v); - - Label end = emitter.CreateLabel(); - - for (int i = 0; i < props.Length; ++i) - { - if (i > 0) - { - emitter.LoadLocal(v); - emitter.BranchIfTrue(end); - } - - Property prop = props[i]; - - emitter.LoadLocal(a); - emitter.Chain(prop); - - bool couldCompare = - emitter.CompareTo(1, () => - { - emitter.LoadLocal(b); - emitter.Chain(prop); - }); - - if (!couldCompare) - throw new InvalidOperationException("Property is not comparable."); - - emitter.StoreLocal(v); - } - - emitter.MarkLabel(end); - - emitter.LoadLocal(v); - emitter.Return(); - - typeBuilder.DefineMethodOverride( - emitter.Method, - typeof(IComparer).GetMethod( - "Compare", - new[] - { - typeof(T), - typeof(T) - }) ?? throw new Exception($"No Compare method found for type {typeof(T).FullName}")); - - compareMethod = emitter.Method; - } - - typeBuilder.AddInterfaceImplementation(typeof(IEqualityComparer)); - { - MethodEmitter emitter = new MethodEmitter(typeBuilder); - - emitter.Define( - /* name */ "Equals", - /* attr */ MethodAttributes.Public | MethodAttributes.Virtual, - /* return */ typeof(bool), - /* params */ new[] { typeof(T), typeof(T) }); - - emitter.Generator.Emit(OpCodes.Ldarg_0); - emitter.Generator.Emit(OpCodes.Ldarg_1); - emitter.Generator.Emit(OpCodes.Ldarg_2); - - emitter.Generator.Emit(OpCodes.Call, compareMethod); - - emitter.Generator.Emit(OpCodes.Ldc_I4_0); - - emitter.Generator.Emit(OpCodes.Ceq); - - emitter.Generator.Emit(OpCodes.Ret); - - typeBuilder.DefineMethodOverride( - emitter.Method, - typeof(IEqualityComparer).GetMethod( - "Equals", - new[] - { - typeof(T), - typeof(T) - }) ?? throw new Exception($"No Equals method found for type {typeof(T).FullName}")); - } - - { - MethodEmitter emitter = new MethodEmitter(typeBuilder); - - emitter.Define( - /* name */ "GetHashCode", - /* attr */ MethodAttributes.Public | MethodAttributes.Virtual, - /* return */ typeof(int), - /* params */ new[] { typeof(T) }); - - LocalBuilder obj = emitter.CreateLocal(objectType); - - emitter.LoadArgument(1); - emitter.CastAs(objectType); - emitter.StoreLocal(obj); - - for (int i = 0; i < props.Length; ++i) - { - Property prop = props[i]; - - emitter.LoadLocal(obj); - emitter.Chain(prop); - - Type active = emitter.Active; - - MethodInfo getHashCode = active.GetMethod("GetHashCode", Type.EmptyTypes); - - getHashCode ??= typeof(T).GetMethod("GetHashCode", Type.EmptyTypes); - - if (active != typeof(int)) - { - if (!active.IsValueType) - { - LocalBuilder value = emitter.AcquireTemp(active); - - Label valueNotNull = emitter.CreateLabel(); - Label done = emitter.CreateLabel(); - - emitter.StoreLocal(value); - emitter.LoadLocal(value); - - emitter.BranchIfTrue(valueNotNull); - - emitter.Load(0); - emitter.Pop(typeof(int)); - - emitter.Branch(done); - - emitter.MarkLabel(valueNotNull); - - emitter.LoadLocal(value); - emitter.Call(getHashCode); - - emitter.ReleaseTemp(value); - - emitter.MarkLabel(done); - } - else - { - emitter.Call(getHashCode); - } - } - - if (i > 0) - emitter.Xor(); - } - - emitter.Return(); - - typeBuilder.DefineMethodOverride( - emitter.Method, - typeof(IEqualityComparer).GetMethod( - "GetHashCode", - new[] - { - typeof(T) - }) ?? throw new Exception($"No GetHashCode method found for type {typeof(T).FullName}")); - } - - Type comparerType = typeBuilder.CreateType(); - - return (IComparer)ActivatorUtil.CreateInstance(comparerType); - } - } -} +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Reflection.Emit; +using Server.Utilities; + +namespace Server.Commands.Generic +{ + public static class DistinctCompiler + { + public static IComparer Compile(AssemblyEmitter assembly, Type objectType, Property[] props) + { + var typeBuilder = assembly.DefineType( + "__distinct", + TypeAttributes.Public, + typeof(object) + ); + { + var ctor = typeBuilder.DefineConstructor( + MethodAttributes.Public, + CallingConventions.Standard, + Type.EmptyTypes + ); + + var il = ctor.GetILGenerator(); + + // : base() + il.Emit(OpCodes.Ldarg_0); + il.Emit( + OpCodes.Call, + typeof(T).GetConstructor(Type.EmptyTypes) ?? + throw new Exception($"Could not find empty constructor for type {typeof(T).FullName}") + ); + + // return; + il.Emit(OpCodes.Ret); + } + + typeBuilder.AddInterfaceImplementation(typeof(IComparer)); + + MethodBuilder compareMethod; + { + var emitter = new MethodEmitter(typeBuilder); + + emitter.Define( + /* name */ "Compare", + /* attr */ + MethodAttributes.Public | MethodAttributes.Virtual, + /* return */ + typeof(int), + /* params */ + new[] { typeof(T), typeof(T) } + ); + + var a = emitter.CreateLocal(objectType); + var b = emitter.CreateLocal(objectType); + + var v = emitter.CreateLocal(typeof(int)); + + emitter.LoadArgument(1); + emitter.CastAs(objectType); + emitter.StoreLocal(a); + + emitter.LoadArgument(2); + emitter.CastAs(objectType); + emitter.StoreLocal(b); + + emitter.Load(0); + emitter.StoreLocal(v); + + var end = emitter.CreateLabel(); + + for (var i = 0; i < props.Length; ++i) + { + if (i > 0) + { + emitter.LoadLocal(v); + emitter.BranchIfTrue(end); + } + + var prop = props[i]; + + emitter.LoadLocal(a); + emitter.Chain(prop); + + var couldCompare = + emitter.CompareTo( + 1, + () => + { + emitter.LoadLocal(b); + emitter.Chain(prop); + } + ); + + if (!couldCompare) + throw new InvalidOperationException("Property is not comparable."); + + emitter.StoreLocal(v); + } + + emitter.MarkLabel(end); + + emitter.LoadLocal(v); + emitter.Return(); + + typeBuilder.DefineMethodOverride( + emitter.Method, + typeof(IComparer).GetMethod( + "Compare", + new[] + { + typeof(T), + typeof(T) + } + ) ?? throw new Exception($"No Compare method found for type {typeof(T).FullName}") + ); + + compareMethod = emitter.Method; + } + + typeBuilder.AddInterfaceImplementation(typeof(IEqualityComparer)); + { + var emitter = new MethodEmitter(typeBuilder); + + emitter.Define( + /* name */ "Equals", + /* attr */ + MethodAttributes.Public | MethodAttributes.Virtual, + /* return */ + typeof(bool), + /* params */ + new[] { typeof(T), typeof(T) } + ); + + emitter.Generator.Emit(OpCodes.Ldarg_0); + emitter.Generator.Emit(OpCodes.Ldarg_1); + emitter.Generator.Emit(OpCodes.Ldarg_2); + + emitter.Generator.Emit(OpCodes.Call, compareMethod); + + emitter.Generator.Emit(OpCodes.Ldc_I4_0); + + emitter.Generator.Emit(OpCodes.Ceq); + + emitter.Generator.Emit(OpCodes.Ret); + + typeBuilder.DefineMethodOverride( + emitter.Method, + typeof(IEqualityComparer).GetMethod( + "Equals", + new[] + { + typeof(T), + typeof(T) + } + ) ?? throw new Exception($"No Equals method found for type {typeof(T).FullName}") + ); + } + + { + var emitter = new MethodEmitter(typeBuilder); + + emitter.Define( + /* name */ "GetHashCode", + /* attr */ + MethodAttributes.Public | MethodAttributes.Virtual, + /* return */ + typeof(int), + /* params */ + new[] { typeof(T) } + ); + + var obj = emitter.CreateLocal(objectType); + + emitter.LoadArgument(1); + emitter.CastAs(objectType); + emitter.StoreLocal(obj); + + for (var i = 0; i < props.Length; ++i) + { + var prop = props[i]; + + emitter.LoadLocal(obj); + emitter.Chain(prop); + + var active = emitter.Active; + + var getHashCode = active.GetMethod("GetHashCode", Type.EmptyTypes); + + getHashCode ??= typeof(T).GetMethod("GetHashCode", Type.EmptyTypes); + + if (active != typeof(int)) + { + if (!active.IsValueType) + { + var value = emitter.AcquireTemp(active); + + var valueNotNull = emitter.CreateLabel(); + var done = emitter.CreateLabel(); + + emitter.StoreLocal(value); + emitter.LoadLocal(value); + + emitter.BranchIfTrue(valueNotNull); + + emitter.Load(0); + emitter.Pop(typeof(int)); + + emitter.Branch(done); + + emitter.MarkLabel(valueNotNull); + + emitter.LoadLocal(value); + emitter.Call(getHashCode); + + emitter.ReleaseTemp(value); + + emitter.MarkLabel(done); + } + else + { + emitter.Call(getHashCode); + } + } + + if (i > 0) + emitter.Xor(); + } + + emitter.Return(); + + typeBuilder.DefineMethodOverride( + emitter.Method, + typeof(IEqualityComparer).GetMethod( + "GetHashCode", + new[] + { + typeof(T) + } + ) ?? throw new Exception($"No GetHashCode method found for type {typeof(T).FullName}") + ); + } + + var comparerType = typeBuilder.CreateType(); + + return (IComparer)ActivatorUtil.CreateInstance(comparerType); + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Extensions/Compilers/SortCompiler.cs b/Projects/UOContent/Commands/Generic/Extensions/Compilers/SortCompiler.cs index 1d837a6d6..9cba852f8 100644 --- a/Projects/UOContent/Commands/Generic/Extensions/Compilers/SortCompiler.cs +++ b/Projects/UOContent/Commands/Generic/Extensions/Compilers/SortCompiler.cs @@ -1,149 +1,163 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Reflection.Emit; -using Server.Utilities; - -namespace Server.Commands.Generic -{ - public sealed class OrderInfo - { - private int m_Order; - - public OrderInfo(Property property, bool isAscending) - { - Property = property; - - IsAscending = isAscending; - } - - public Property Property { get; set; } - - public bool IsAscending - { - get => m_Order > 0; - set => m_Order = value ? +1 : -1; - } - - public bool IsDescending - { - get => m_Order < 0; - set => m_Order = value ? -1 : +1; - } - - public int Sign - { - get => Math.Sign(m_Order); - set - { - m_Order = Math.Sign(value); - - if (m_Order == 0) - throw new InvalidOperationException("Sign cannot be zero."); - } - } - } - - public static class SortCompiler - { - public static IComparer Compile(AssemblyEmitter assembly, Type objectType, OrderInfo[] orders) - { - TypeBuilder typeBuilder = assembly.DefineType( - "__sort", - TypeAttributes.Public, - typeof(T)); - { - ConstructorBuilder ctor = typeBuilder.DefineConstructor( - MethodAttributes.Public, - CallingConventions.Standard, - Type.EmptyTypes); - - ILGenerator il = ctor.GetILGenerator(); - - // : base() - il.Emit(OpCodes.Ldarg_0); - il.Emit(OpCodes.Call, typeof(T).GetConstructor(Type.EmptyTypes) ?? - throw new Exception($"Could not find empty constructor for type {typeof(T).FullName}")); - - // return; - il.Emit(OpCodes.Ret); - } - - typeBuilder.AddInterfaceImplementation(typeof(IComparer)); - { - MethodEmitter emitter = new MethodEmitter(typeBuilder); - - emitter.Define( - /* name */ "Compare", - /* attr */ MethodAttributes.Public | MethodAttributes.Virtual, - /* return */ typeof(int), - /* params */ new[] { typeof(T), typeof(T) }); - - LocalBuilder a = emitter.CreateLocal(objectType); - LocalBuilder b = emitter.CreateLocal(objectType); - - LocalBuilder v = emitter.CreateLocal(typeof(int)); - - emitter.LoadArgument(1); - emitter.CastAs(objectType); - emitter.StoreLocal(a); - - emitter.LoadArgument(2); - emitter.CastAs(objectType); - emitter.StoreLocal(b); - - emitter.Load(0); - emitter.StoreLocal(v); - - Label end = emitter.CreateLabel(); - - for (int i = 0; i < orders.Length; ++i) - { - if (i > 0) - { - emitter.LoadLocal(v); - emitter.BranchIfTrue(end); - } - - OrderInfo orderInfo = orders[i]; - - Property prop = orderInfo.Property; - int sign = orderInfo.Sign; - - emitter.LoadLocal(a); - emitter.Chain(prop); - - bool couldCompare = - emitter.CompareTo(sign, () => - { - emitter.LoadLocal(b); - emitter.Chain(prop); - }); - - if (!couldCompare) - throw new InvalidOperationException("Property is not comparable."); - - emitter.StoreLocal(v); - } - - emitter.MarkLabel(end); - - emitter.LoadLocal(v); - emitter.Return(); - - typeBuilder.DefineMethodOverride( - emitter.Method, - typeof(IComparer).GetMethod( - "Compare", - new[] - { - typeof(T), - typeof(T) - }) ?? throw new Exception($"No Compare method found for type {typeof(T).FullName}")); - } - - Type comparerType = typeBuilder.CreateType(); - return (IComparer)ActivatorUtil.CreateInstance(comparerType); - } - } -} +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Reflection.Emit; +using Server.Utilities; + +namespace Server.Commands.Generic +{ + public sealed class OrderInfo + { + private int m_Order; + + public OrderInfo(Property property, bool isAscending) + { + Property = property; + + IsAscending = isAscending; + } + + public Property Property { get; set; } + + public bool IsAscending + { + get => m_Order > 0; + set => m_Order = value ? +1 : -1; + } + + public bool IsDescending + { + get => m_Order < 0; + set => m_Order = value ? -1 : +1; + } + + public int Sign + { + get => Math.Sign(m_Order); + set + { + m_Order = Math.Sign(value); + + if (m_Order == 0) + throw new InvalidOperationException("Sign cannot be zero."); + } + } + } + + public static class SortCompiler + { + public static IComparer Compile(AssemblyEmitter assembly, Type objectType, OrderInfo[] orders) + { + var typeBuilder = assembly.DefineType( + "__sort", + TypeAttributes.Public, + typeof(T) + ); + { + var ctor = typeBuilder.DefineConstructor( + MethodAttributes.Public, + CallingConventions.Standard, + Type.EmptyTypes + ); + + var il = ctor.GetILGenerator(); + + // : base() + il.Emit(OpCodes.Ldarg_0); + il.Emit( + OpCodes.Call, + typeof(T).GetConstructor(Type.EmptyTypes) ?? + throw new Exception($"Could not find empty constructor for type {typeof(T).FullName}") + ); + + // return; + il.Emit(OpCodes.Ret); + } + + typeBuilder.AddInterfaceImplementation(typeof(IComparer)); + { + var emitter = new MethodEmitter(typeBuilder); + + emitter.Define( + /* name */ "Compare", + /* attr */ + MethodAttributes.Public | MethodAttributes.Virtual, + /* return */ + typeof(int), + /* params */ + new[] { typeof(T), typeof(T) } + ); + + var a = emitter.CreateLocal(objectType); + var b = emitter.CreateLocal(objectType); + + var v = emitter.CreateLocal(typeof(int)); + + emitter.LoadArgument(1); + emitter.CastAs(objectType); + emitter.StoreLocal(a); + + emitter.LoadArgument(2); + emitter.CastAs(objectType); + emitter.StoreLocal(b); + + emitter.Load(0); + emitter.StoreLocal(v); + + var end = emitter.CreateLabel(); + + for (var i = 0; i < orders.Length; ++i) + { + if (i > 0) + { + emitter.LoadLocal(v); + emitter.BranchIfTrue(end); + } + + var orderInfo = orders[i]; + + var prop = orderInfo.Property; + var sign = orderInfo.Sign; + + emitter.LoadLocal(a); + emitter.Chain(prop); + + var couldCompare = + emitter.CompareTo( + sign, + () => + { + emitter.LoadLocal(b); + emitter.Chain(prop); + } + ); + + if (!couldCompare) + throw new InvalidOperationException("Property is not comparable."); + + emitter.StoreLocal(v); + } + + emitter.MarkLabel(end); + + emitter.LoadLocal(v); + emitter.Return(); + + typeBuilder.DefineMethodOverride( + emitter.Method, + typeof(IComparer).GetMethod( + "Compare", + new[] + { + typeof(T), + typeof(T) + } + ) ?? throw new Exception($"No Compare method found for type {typeof(T).FullName}") + ); + } + + var comparerType = typeBuilder.CreateType(); + return (IComparer)ActivatorUtil.CreateInstance(comparerType); + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Extensions/DistinctExtension.cs b/Projects/UOContent/Commands/Generic/Extensions/DistinctExtension.cs index 49f8fc512..b92311113 100644 --- a/Projects/UOContent/Commands/Generic/Extensions/DistinctExtension.cs +++ b/Projects/UOContent/Commands/Generic/Extensions/DistinctExtension.cs @@ -1,80 +1,80 @@ -using System; -using System.Collections.Generic; - -namespace Server.Commands.Generic -{ - public sealed class DistinctExtension : BaseExtension - { - public static ExtensionInfo ExtInfo = - new ExtensionInfo(30, "Distinct", -1, () => new DistinctExtension()); - - private IComparer m_Comparer; - - private readonly List m_Properties; - - public DistinctExtension() => m_Properties = new List(); - - public override ExtensionInfo Info => ExtInfo; - - public static void Initialize() - { - ExtensionInfo.Register(ExtInfo); - } - - public override void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly) - { - if (baseType == null) - throw new Exception("Distinct extension may only be used in combination with an object conditional."); - - foreach (Property prop in m_Properties) - { - prop.BindTo(baseType, PropertyAccess.Read); - prop.CheckAccess(from); - } - - assembly ??= new AssemblyEmitter("__dynamic"); - - m_Comparer = DistinctCompiler.Compile(assembly, baseType, m_Properties.ToArray()); - } - - public override void Parse(Mobile from, string[] arguments, int offset, int size) - { - if (size < 1) - throw new Exception("Invalid distinction syntax."); - - int end = offset + size; - - while (offset < end) - { - string binding = arguments[offset++]; - - m_Properties.Add(new Property(binding)); - } - } - - public override void Filter(List list) - { - if (m_Comparer == null) - throw new InvalidOperationException("The extension must first be optimized."); - - List copy = new List(list); - - copy.Sort(m_Comparer); - - list.Clear(); - - object last = null; - - for (int i = 0; i < copy.Count; ++i) - { - object obj = copy[i]; - - if (last == null || m_Comparer.Compare(obj, last) != 0) - { - list.Add(obj); - last = obj; - } - } - } - } -} +using System; +using System.Collections.Generic; + +namespace Server.Commands.Generic +{ + public sealed class DistinctExtension : BaseExtension + { + public static ExtensionInfo ExtInfo = + new ExtensionInfo(30, "Distinct", -1, () => new DistinctExtension()); + + private readonly List m_Properties; + + private IComparer m_Comparer; + + public DistinctExtension() => m_Properties = new List(); + + public override ExtensionInfo Info => ExtInfo; + + public static void Initialize() + { + ExtensionInfo.Register(ExtInfo); + } + + public override void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly) + { + if (baseType == null) + throw new Exception("Distinct extension may only be used in combination with an object conditional."); + + foreach (var prop in m_Properties) + { + prop.BindTo(baseType, PropertyAccess.Read); + prop.CheckAccess(from); + } + + assembly ??= new AssemblyEmitter("__dynamic"); + + m_Comparer = DistinctCompiler.Compile(assembly, baseType, m_Properties.ToArray()); + } + + public override void Parse(Mobile from, string[] arguments, int offset, int size) + { + if (size < 1) + throw new Exception("Invalid distinction syntax."); + + var end = offset + size; + + while (offset < end) + { + var binding = arguments[offset++]; + + m_Properties.Add(new Property(binding)); + } + } + + public override void Filter(List list) + { + if (m_Comparer == null) + throw new InvalidOperationException("The extension must first be optimized."); + + var copy = new List(list); + + copy.Sort(m_Comparer); + + list.Clear(); + + object last = null; + + for (var i = 0; i < copy.Count; ++i) + { + var obj = copy[i]; + + if (last == null || m_Comparer.Compare(obj, last) != 0) + { + list.Add(obj); + last = obj; + } + } + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Extensions/LimitExtension.cs b/Projects/UOContent/Commands/Generic/Extensions/LimitExtension.cs index 07b589c07..f70068687 100644 --- a/Projects/UOContent/Commands/Generic/Extensions/LimitExtension.cs +++ b/Projects/UOContent/Commands/Generic/Extensions/LimitExtension.cs @@ -1,33 +1,33 @@ -using System; -using System.Collections.Generic; - -namespace Server.Commands.Generic -{ - public sealed class LimitExtension : BaseExtension - { - public static ExtensionInfo ExtInfo = new ExtensionInfo(80, "Limit", 1, () => new LimitExtension()); - - public override ExtensionInfo Info => ExtInfo; - - public int Limit { get; private set; } - - public static void Initialize() - { - ExtensionInfo.Register(ExtInfo); - } - - public override void Parse(Mobile from, string[] arguments, int offset, int size) - { - Limit = Utility.ToInt32(arguments[offset]); - - if (Limit < 0) - throw new Exception("Limit cannot be less than zero."); - } - - public override void Filter(List list) - { - if (list.Count > Limit) - list.RemoveRange(Limit, list.Count - Limit); - } - } -} \ No newline at end of file +using System; +using System.Collections.Generic; + +namespace Server.Commands.Generic +{ + public sealed class LimitExtension : BaseExtension + { + public static ExtensionInfo ExtInfo = new ExtensionInfo(80, "Limit", 1, () => new LimitExtension()); + + public override ExtensionInfo Info => ExtInfo; + + public int Limit { get; private set; } + + public static void Initialize() + { + ExtensionInfo.Register(ExtInfo); + } + + public override void Parse(Mobile from, string[] arguments, int offset, int size) + { + Limit = Utility.ToInt32(arguments[offset]); + + if (Limit < 0) + throw new Exception("Limit cannot be less than zero."); + } + + public override void Filter(List list) + { + if (list.Count > Limit) + list.RemoveRange(Limit, list.Count - Limit); + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Extensions/SortExtension.cs b/Projects/UOContent/Commands/Generic/Extensions/SortExtension.cs index 9124f7d61..13dc5096c 100644 --- a/Projects/UOContent/Commands/Generic/Extensions/SortExtension.cs +++ b/Projects/UOContent/Commands/Generic/Extensions/SortExtension.cs @@ -1,99 +1,99 @@ -using System; -using System.Collections.Generic; - -namespace Server.Commands.Generic -{ - public sealed class SortExtension : BaseExtension - { - public static ExtensionInfo ExtInfo = new ExtensionInfo(40, "Order", -1, () => new SortExtension()); - - private IComparer m_Comparer; - - private readonly List m_Orders; - - public SortExtension() => m_Orders = new List(); - - public override ExtensionInfo Info => ExtInfo; - - public static void Initialize() - { - ExtensionInfo.Register(ExtInfo); - } - - public override void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly) - { - if (baseType == null) - throw new Exception("The ordering extension may only be used in combination with an object conditional."); - - foreach (OrderInfo order in m_Orders) - { - order.Property.BindTo(baseType, PropertyAccess.Read); - order.Property.CheckAccess(from); - } - - assembly ??= new AssemblyEmitter("__dynamic"); - - m_Comparer = SortCompiler.Compile(assembly, baseType, m_Orders.ToArray()); - } - - public override void Parse(Mobile from, string[] arguments, int offset, int size) - { - if (size < 1) - throw new Exception("Invalid ordering syntax."); - - if (Insensitive.Equals(arguments[offset], "by")) - { - ++offset; - --size; - - if (size < 1) - throw new Exception("Invalid ordering syntax."); - } - - int end = offset + size; - - while (offset < end) - { - string binding = arguments[offset++]; - - bool isAscending = true; - - if (offset < end) - { - string next = arguments[offset]; - - switch (next.ToLower()) - { - case "+": - case "up": - case "asc": - case "ascending": - isAscending = true; - ++offset; - break; - - case "-": - case "down": - case "desc": - case "descending": - isAscending = false; - ++offset; - break; - } - } - - Property property = new Property(binding); - - m_Orders.Add(new OrderInfo(property, isAscending)); - } - } - - public override void Filter(List list) - { - if (m_Comparer == null) - throw new InvalidOperationException("The extension must first be optimized."); - - list.Sort(m_Comparer); - } - } -} +using System; +using System.Collections.Generic; + +namespace Server.Commands.Generic +{ + public sealed class SortExtension : BaseExtension + { + public static ExtensionInfo ExtInfo = new ExtensionInfo(40, "Order", -1, () => new SortExtension()); + + private readonly List m_Orders; + + private IComparer m_Comparer; + + public SortExtension() => m_Orders = new List(); + + public override ExtensionInfo Info => ExtInfo; + + public static void Initialize() + { + ExtensionInfo.Register(ExtInfo); + } + + public override void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly) + { + if (baseType == null) + throw new Exception("The ordering extension may only be used in combination with an object conditional."); + + foreach (var order in m_Orders) + { + order.Property.BindTo(baseType, PropertyAccess.Read); + order.Property.CheckAccess(from); + } + + assembly ??= new AssemblyEmitter("__dynamic"); + + m_Comparer = SortCompiler.Compile(assembly, baseType, m_Orders.ToArray()); + } + + public override void Parse(Mobile from, string[] arguments, int offset, int size) + { + if (size < 1) + throw new Exception("Invalid ordering syntax."); + + if (Insensitive.Equals(arguments[offset], "by")) + { + ++offset; + --size; + + if (size < 1) + throw new Exception("Invalid ordering syntax."); + } + + var end = offset + size; + + while (offset < end) + { + var binding = arguments[offset++]; + + var isAscending = true; + + if (offset < end) + { + var next = arguments[offset]; + + switch (next.ToLower()) + { + case "+": + case "up": + case "asc": + case "ascending": + isAscending = true; + ++offset; + break; + + case "-": + case "down": + case "desc": + case "descending": + isAscending = false; + ++offset; + break; + } + } + + var property = new Property(binding); + + m_Orders.Add(new OrderInfo(property, isAscending)); + } + } + + public override void Filter(List list) + { + if (m_Comparer == null) + throw new InvalidOperationException("The extension must first be optimized."); + + list.Sort(m_Comparer); + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Extensions/WhereExtension.cs b/Projects/UOContent/Commands/Generic/Extensions/WhereExtension.cs index fe9f281c1..0703f855a 100644 --- a/Projects/UOContent/Commands/Generic/Extensions/WhereExtension.cs +++ b/Projects/UOContent/Commands/Generic/Extensions/WhereExtension.cs @@ -1,36 +1,36 @@ -using System; - -namespace Server.Commands.Generic -{ - public sealed class WhereExtension : BaseExtension - { - public static ExtensionInfo ExtInfo = new ExtensionInfo(20, "Where", -1, () => new WhereExtension()); - - public override ExtensionInfo Info => ExtInfo; - - public ObjectConditional Conditional { get; private set; } - - public static void Initialize() - { - ExtensionInfo.Register(ExtInfo); - } - - public override void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly) - { - if (baseType == null) - throw new InvalidOperationException("Insanity."); - - Conditional.Compile(ref assembly); - } - - public override void Parse(Mobile from, string[] arguments, int offset, int size) - { - if (size < 1) - throw new Exception("Invalid condition syntax."); - - Conditional = ObjectConditional.ParseDirect(from, arguments, offset, size); - } - - public override bool IsValid(object obj) => Conditional.CheckCondition(obj); - } -} \ No newline at end of file +using System; + +namespace Server.Commands.Generic +{ + public sealed class WhereExtension : BaseExtension + { + public static ExtensionInfo ExtInfo = new ExtensionInfo(20, "Where", -1, () => new WhereExtension()); + + public override ExtensionInfo Info => ExtInfo; + + public ObjectConditional Conditional { get; private set; } + + public static void Initialize() + { + ExtensionInfo.Register(ExtInfo); + } + + public override void Optimize(Mobile from, Type baseType, ref AssemblyEmitter assembly) + { + if (baseType == null) + throw new InvalidOperationException("Insanity."); + + Conditional.Compile(ref assembly); + } + + public override void Parse(Mobile from, string[] arguments, int offset, int size) + { + if (size < 1) + throw new Exception("Invalid condition syntax."); + + Conditional = ObjectConditional.ParseDirect(from, arguments, offset, size); + } + + public override bool IsValid(object obj) => Conditional.CheckCondition(obj); + } +} diff --git a/Projects/UOContent/Commands/Generic/Implementors/AreaCommandImplementor.cs b/Projects/UOContent/Commands/Generic/Implementors/AreaCommandImplementor.cs index e4ef1cca0..306a0ed8d 100644 --- a/Projects/UOContent/Commands/Generic/Implementors/AreaCommandImplementor.cs +++ b/Projects/UOContent/Commands/Generic/Implementors/AreaCommandImplementor.cs @@ -1,61 +1,61 @@ -using System; -using System.Collections.Generic; - -namespace Server.Commands.Generic -{ - public class AreaCommandImplementor : BaseCommandImplementor - { - public AreaCommandImplementor() - { - Accessors = new[] { "Area", "Group" }; - SupportRequirement = CommandSupport.Area; - SupportsConditionals = true; - AccessLevel = AccessLevel.GameMaster; - Usage = "Area [condition]"; - Description = - "Invokes the command on all appropriate objects in a targeted area. Optional condition arguments can further restrict the set of objects."; - - Instance = this; - } - - public static AreaCommandImplementor Instance { get; private set; } - - public override void Process(Mobile from, BaseCommand command, string[] args) - { - BoundingBoxPicker.Begin(from, (map, start, end) => OnTarget(from, map, start, end, command, args)); - } - - public void OnTarget(Mobile from, Map map, Point3D start, Point3D end, BaseCommand command, string[] args) - { - try - { - Rectangle2D rect = new Rectangle2D(start.X, start.Y, end.X - start.X + 1, end.Y - start.Y + 1); - - Extensions ext = Extensions.Parse(from, ref args); - - if (!CheckObjectTypes(from, command, ext, out bool items, out bool mobiles)) - return; - - if (!(items || mobiles)) - return; - - IPooledEnumerable eable = map.GetObjectsInBounds(rect, items, mobiles); - - List objs = new List(); - - foreach (IEntity obj in eable) - if ((!mobiles || obj is Mobile) && BaseCommand.IsAccessible(from, obj) && ext.IsValid(obj)) - objs.Add(obj); - - eable.Free(); - ext.Filter(objs); - - RunCommand(from, objs, command, args); - } - catch (Exception ex) - { - from.SendMessage(ex.Message); - } - } - } -} +using System; +using System.Collections.Generic; + +namespace Server.Commands.Generic +{ + public class AreaCommandImplementor : BaseCommandImplementor + { + public AreaCommandImplementor() + { + Accessors = new[] { "Area", "Group" }; + SupportRequirement = CommandSupport.Area; + SupportsConditionals = true; + AccessLevel = AccessLevel.GameMaster; + Usage = "Area [condition]"; + Description = + "Invokes the command on all appropriate objects in a targeted area. Optional condition arguments can further restrict the set of objects."; + + Instance = this; + } + + public static AreaCommandImplementor Instance { get; private set; } + + public override void Process(Mobile from, BaseCommand command, string[] args) + { + BoundingBoxPicker.Begin(from, (map, start, end) => OnTarget(from, map, start, end, command, args)); + } + + public void OnTarget(Mobile from, Map map, Point3D start, Point3D end, BaseCommand command, string[] args) + { + try + { + var rect = new Rectangle2D(start.X, start.Y, end.X - start.X + 1, end.Y - start.Y + 1); + + var ext = Extensions.Parse(from, ref args); + + if (!CheckObjectTypes(from, command, ext, out var items, out var mobiles)) + return; + + if (!(items || mobiles)) + return; + + var eable = map.GetObjectsInBounds(rect, items, mobiles); + + var objs = new List(); + + foreach (var obj in eable) + if ((!mobiles || obj is Mobile) && BaseCommand.IsAccessible(from, obj) && ext.IsValid(obj)) + objs.Add(obj); + + eable.Free(); + ext.Filter(objs); + + RunCommand(from, objs, command, args); + } + catch (Exception ex) + { + from.SendMessage(ex.Message); + } + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Implementors/BaseCommandImplementor.cs b/Projects/UOContent/Commands/Generic/Implementors/BaseCommandImplementor.cs index e2515fcb5..b8d8a07df 100644 --- a/Projects/UOContent/Commands/Generic/Implementors/BaseCommandImplementor.cs +++ b/Projects/UOContent/Commands/Generic/Implementors/BaseCommandImplementor.cs @@ -1,292 +1,293 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Server.Commands.Generic -{ - [Flags] - public enum CommandSupport - { - Single = 0x0001, - Global = 0x0002, - Online = 0x0004, - Multi = 0x0008, - Area = 0x0010, - Self = 0x0020, - Region = 0x0040, - Contained = 0x0080, - IPAddress = 0x0100, - - All = Single | Global | Online | Multi | Area | Self | Region | Contained | IPAddress, - AllMobiles = All & ~Contained, - AllNPCs = All & ~(IPAddress | Online | Self | Contained), - AllItems = All & ~(IPAddress | Online | Self | Region), - - Simple = Single | Multi, - Complex = Global | Online | Area | Region | Contained | IPAddress - } - - public abstract class BaseCommandImplementor - { - private static List m_Implementors; - - public BaseCommandImplementor() => Commands = new Dictionary(StringComparer.OrdinalIgnoreCase); - - public bool SupportsConditionals { get; set; } - - public string[] Accessors { get; set; } - - public string Usage { get; set; } - - public string Description { get; set; } - - public AccessLevel AccessLevel { get; set; } - - public CommandSupport SupportRequirement { get; set; } - - public Dictionary Commands { get; } - - public static List Implementors - { - get - { - if (m_Implementors == null) - { - m_Implementors = new List(); - RegisterImplementors(); - } - - return m_Implementors; - } - } - - public static void RegisterImplementors() - { - Register(new RegionCommandImplementor()); - Register(new GlobalCommandImplementor()); - Register(new OnlineCommandImplementor()); - Register(new SingleCommandImplementor()); - Register(new SerialCommandImplementor()); - Register(new MultiCommandImplementor()); - Register(new AreaCommandImplementor()); - Register(new SelfCommandImplementor()); - Register(new ContainedCommandImplementor()); - Register(new IPAddressCommandImplementor()); - - Register(new RangeCommandImplementor()); - Register(new ScreenCommandImplementor()); - Register(new FacetCommandImplementor()); - } - - public virtual void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj) - { - obj = null; - } - - public virtual void Register(BaseCommand command) - { - for (int i = 0; i < command.Commands.Length; ++i) - Commands[command.Commands[i]] = command; - } - - public bool CheckObjectTypes(Mobile from, BaseCommand command, Extensions ext, out bool items, out bool mobiles) - { - items = mobiles = false; - - ObjectConditional cond = ObjectConditional.Empty; - - foreach (BaseExtension check in ext) - if (check is WhereExtension extension) - { - cond = extension.Conditional; - - break; - } - - bool condIsItem = cond.IsItem; - bool condIsMobile = cond.IsMobile; - - switch (command.ObjectTypes) - { - case ObjectTypes.All: - case ObjectTypes.Both: - { - if (condIsItem) - items = true; - - if (condIsMobile) - mobiles = true; - - break; - } - case ObjectTypes.Items: - { - if (condIsItem) - { - items = true; - } - else if (condIsMobile) - { - from.SendMessage("You may not use a mobile type condition for this command."); - return false; - } - - break; - } - case ObjectTypes.Mobiles: - { - if (condIsMobile) - { - mobiles = true; - } - else if (condIsItem) - { - from.SendMessage("You may not use an item type condition for this command."); - return false; - } - - break; - } - } - - return true; - } - - public void RunCommand(Mobile from, BaseCommand command, string[] args) - { - try - { - object obj = null; - - Compile(from, command, ref args, ref obj); - - RunCommand(from, obj, command, args); - } - catch (Exception ex) - { - from.SendMessage(ex.Message); - } - } - - public string GenerateArgString(string[] args) - { - if (args.Length == 0) - return ""; - - // NOTE: this does not preserve the case where quotation marks are used on a single word - - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < args.Length; ++i) - { - if (i > 0) - sb.Append(' '); - - if (args[i].IndexOf(' ') >= 0) - { - sb.Append('"'); - sb.Append(args[i]); - sb.Append('"'); - } - else - { - sb.Append(args[i]); - } - } - - return sb.ToString(); - } - - public void RunCommand(Mobile from, object obj, BaseCommand command, string[] args) - { - // try - // { - CommandEventArgs e = new CommandEventArgs(from, command.Commands[0], GenerateArgString(args), args); - - if (!command.ValidateArgs(this, e)) - return; - - bool flushToLog = false; - - if (obj is List list) - { - if (list.Count > 20) - CommandLogging.Enabled = false; - else if (list.Count == 0) - command.LogFailure("Nothing was found to use this command on."); - - command.ExecuteList(e, list); - - if (list.Count > 20) - { - flushToLog = true; - CommandLogging.Enabled = true; - } - } - else if (obj != null) - { - if (command.ListOptimized) - command.ExecuteList(e, new List { obj }); - else - command.Execute(e, obj); - } - - command.Flush(from, flushToLog); - // } - // catch ( Exception ex ) - // { - // from.SendMessage( ex.Message ); - // } - } - - public virtual void Process(Mobile from, BaseCommand command, string[] args) - { - RunCommand(from, command, args); - } - - public virtual void Execute(CommandEventArgs e) - { - if (e.Length >= 1) - { - if (!Commands.TryGetValue(e.GetString(0), out BaseCommand command)) - { - e.Mobile.SendMessage( - "That is either an invalid command name or one that does not support this modifier."); - } - else if (e.Mobile.AccessLevel < command.AccessLevel) - { - e.Mobile.SendMessage("You do not have access to that command."); - } - else - { - string[] oldArgs = e.Arguments; - string[] args = new string[oldArgs.Length - 1]; - - for (int i = 0; i < args.Length; ++i) - args[i] = oldArgs[i + 1]; - - Process(e.Mobile, command, args); - } - } - else - { - e.Mobile.SendMessage("You must supply a command name."); - } - } - - public void Register() - { - if (Accessors == null) - return; - - for (int i = 0; i < Accessors.Length; ++i) - CommandSystem.Register(Accessors[i], AccessLevel, Execute); - } - - public static void Register(BaseCommandImplementor impl) - { - m_Implementors.Add(impl); - impl.Register(); - } - } -} +using System; +using System.Collections.Generic; +using System.Text; + +namespace Server.Commands.Generic +{ + [Flags] + public enum CommandSupport + { + Single = 0x0001, + Global = 0x0002, + Online = 0x0004, + Multi = 0x0008, + Area = 0x0010, + Self = 0x0020, + Region = 0x0040, + Contained = 0x0080, + IPAddress = 0x0100, + + All = Single | Global | Online | Multi | Area | Self | Region | Contained | IPAddress, + AllMobiles = All & ~Contained, + AllNPCs = All & ~(IPAddress | Online | Self | Contained), + AllItems = All & ~(IPAddress | Online | Self | Region), + + Simple = Single | Multi, + Complex = Global | Online | Area | Region | Contained | IPAddress + } + + public abstract class BaseCommandImplementor + { + private static List m_Implementors; + + public BaseCommandImplementor() => Commands = new Dictionary(StringComparer.OrdinalIgnoreCase); + + public bool SupportsConditionals { get; set; } + + public string[] Accessors { get; set; } + + public string Usage { get; set; } + + public string Description { get; set; } + + public AccessLevel AccessLevel { get; set; } + + public CommandSupport SupportRequirement { get; set; } + + public Dictionary Commands { get; } + + public static List Implementors + { + get + { + if (m_Implementors == null) + { + m_Implementors = new List(); + RegisterImplementors(); + } + + return m_Implementors; + } + } + + public static void RegisterImplementors() + { + Register(new RegionCommandImplementor()); + Register(new GlobalCommandImplementor()); + Register(new OnlineCommandImplementor()); + Register(new SingleCommandImplementor()); + Register(new SerialCommandImplementor()); + Register(new MultiCommandImplementor()); + Register(new AreaCommandImplementor()); + Register(new SelfCommandImplementor()); + Register(new ContainedCommandImplementor()); + Register(new IPAddressCommandImplementor()); + + Register(new RangeCommandImplementor()); + Register(new ScreenCommandImplementor()); + Register(new FacetCommandImplementor()); + } + + public virtual void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj) + { + obj = null; + } + + public virtual void Register(BaseCommand command) + { + for (var i = 0; i < command.Commands.Length; ++i) + Commands[command.Commands[i]] = command; + } + + public bool CheckObjectTypes(Mobile from, BaseCommand command, Extensions ext, out bool items, out bool mobiles) + { + items = mobiles = false; + + var cond = ObjectConditional.Empty; + + foreach (var check in ext) + if (check is WhereExtension extension) + { + cond = extension.Conditional; + + break; + } + + var condIsItem = cond.IsItem; + var condIsMobile = cond.IsMobile; + + switch (command.ObjectTypes) + { + case ObjectTypes.All: + case ObjectTypes.Both: + { + if (condIsItem) + items = true; + + if (condIsMobile) + mobiles = true; + + break; + } + case ObjectTypes.Items: + { + if (condIsItem) + { + items = true; + } + else if (condIsMobile) + { + from.SendMessage("You may not use a mobile type condition for this command."); + return false; + } + + break; + } + case ObjectTypes.Mobiles: + { + if (condIsMobile) + { + mobiles = true; + } + else if (condIsItem) + { + from.SendMessage("You may not use an item type condition for this command."); + return false; + } + + break; + } + } + + return true; + } + + public void RunCommand(Mobile from, BaseCommand command, string[] args) + { + try + { + object obj = null; + + Compile(from, command, ref args, ref obj); + + RunCommand(from, obj, command, args); + } + catch (Exception ex) + { + from.SendMessage(ex.Message); + } + } + + public string GenerateArgString(string[] args) + { + if (args.Length == 0) + return ""; + + // NOTE: this does not preserve the case where quotation marks are used on a single word + + var sb = new StringBuilder(); + + for (var i = 0; i < args.Length; ++i) + { + if (i > 0) + sb.Append(' '); + + if (args[i].IndexOf(' ') >= 0) + { + sb.Append('"'); + sb.Append(args[i]); + sb.Append('"'); + } + else + { + sb.Append(args[i]); + } + } + + return sb.ToString(); + } + + public void RunCommand(Mobile from, object obj, BaseCommand command, string[] args) + { + // try + // { + var e = new CommandEventArgs(from, command.Commands[0], GenerateArgString(args), args); + + if (!command.ValidateArgs(this, e)) + return; + + var flushToLog = false; + + if (obj is List list) + { + if (list.Count > 20) + CommandLogging.Enabled = false; + else if (list.Count == 0) + command.LogFailure("Nothing was found to use this command on."); + + command.ExecuteList(e, list); + + if (list.Count > 20) + { + flushToLog = true; + CommandLogging.Enabled = true; + } + } + else if (obj != null) + { + if (command.ListOptimized) + command.ExecuteList(e, new List { obj }); + else + command.Execute(e, obj); + } + + command.Flush(from, flushToLog); + // } + // catch ( Exception ex ) + // { + // from.SendMessage( ex.Message ); + // } + } + + public virtual void Process(Mobile from, BaseCommand command, string[] args) + { + RunCommand(from, command, args); + } + + public virtual void Execute(CommandEventArgs e) + { + if (e.Length >= 1) + { + if (!Commands.TryGetValue(e.GetString(0), out var command)) + { + e.Mobile.SendMessage( + "That is either an invalid command name or one that does not support this modifier." + ); + } + else if (e.Mobile.AccessLevel < command.AccessLevel) + { + e.Mobile.SendMessage("You do not have access to that command."); + } + else + { + var oldArgs = e.Arguments; + var args = new string[oldArgs.Length - 1]; + + for (var i = 0; i < args.Length; ++i) + args[i] = oldArgs[i + 1]; + + Process(e.Mobile, command, args); + } + } + else + { + e.Mobile.SendMessage("You must supply a command name."); + } + } + + public void Register() + { + if (Accessors == null) + return; + + for (var i = 0; i < Accessors.Length; ++i) + CommandSystem.Register(Accessors[i], AccessLevel, Execute); + } + + public static void Register(BaseCommandImplementor impl) + { + m_Implementors.Add(impl); + impl.Register(); + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Implementors/ContainedCommandImplementor.cs b/Projects/UOContent/Commands/Generic/Implementors/ContainedCommandImplementor.cs index 3151ee273..15373dd1d 100644 --- a/Projects/UOContent/Commands/Generic/Implementors/ContainedCommandImplementor.cs +++ b/Projects/UOContent/Commands/Generic/Implementors/ContainedCommandImplementor.cs @@ -1,73 +1,78 @@ -using System; -using System.Collections.Generic; -using Server.Items; -using Server.Targeting; - -namespace Server.Commands.Generic -{ - public class ContainedCommandImplementor : BaseCommandImplementor - { - public ContainedCommandImplementor() - { - Accessors = new[] { "Contained" }; - SupportRequirement = CommandSupport.Contained; - AccessLevel = AccessLevel.GameMaster; - Usage = "Contained [condition]"; - Description = - "Invokes the command on all child items in a targeted container. Optional condition arguments can further restrict the set of objects."; - } - - public override void Process(Mobile from, BaseCommand command, string[] args) - { - if (command.ValidateArgs(this, new CommandEventArgs(from, command.Commands[0], GenerateArgString(args), args))) - from.BeginTarget(-1, command.ObjectTypes == ObjectTypes.All, TargetFlags.None, - (m, targeted, a) => OnTarget(m, targeted, command, a), args); - } - - public void OnTarget(Mobile from, object targeted, BaseCommand command, string[] args) - { - if (!BaseCommand.IsAccessible(from, targeted)) - { - from.SendLocalizedMessage(500447); // That is not accessible. - return; - } - - if (command.ObjectTypes == ObjectTypes.Mobiles) - return; // sanity check - - if (!(targeted is Container cont)) - { - from.SendMessage("That is not a container."); - return; - } - - try - { - Extensions ext = Extensions.Parse(from, ref args); - - if (!CheckObjectTypes(from, command, ext, out bool items, out bool _)) - return; - - if (!items) - { - from.SendMessage("This command only works on items."); - return; - } - - List list = new List(); - - foreach (Item item in cont.FindItemsByType()) - if (ext.IsValid(item)) - list.Add(item); - - ext.Filter(list); - - RunCommand(from, list, command, args); - } - catch (Exception e) - { - from.SendMessage(e.Message); - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Items; +using Server.Targeting; + +namespace Server.Commands.Generic +{ + public class ContainedCommandImplementor : BaseCommandImplementor + { + public ContainedCommandImplementor() + { + Accessors = new[] { "Contained" }; + SupportRequirement = CommandSupport.Contained; + AccessLevel = AccessLevel.GameMaster; + Usage = "Contained [condition]"; + Description = + "Invokes the command on all child items in a targeted container. Optional condition arguments can further restrict the set of objects."; + } + + public override void Process(Mobile from, BaseCommand command, string[] args) + { + if (command.ValidateArgs(this, new CommandEventArgs(from, command.Commands[0], GenerateArgString(args), args))) + from.BeginTarget( + -1, + command.ObjectTypes == ObjectTypes.All, + TargetFlags.None, + (m, targeted, a) => OnTarget(m, targeted, command, a), + args + ); + } + + public void OnTarget(Mobile from, object targeted, BaseCommand command, string[] args) + { + if (!BaseCommand.IsAccessible(from, targeted)) + { + from.SendLocalizedMessage(500447); // That is not accessible. + return; + } + + if (command.ObjectTypes == ObjectTypes.Mobiles) + return; // sanity check + + if (!(targeted is Container cont)) + { + from.SendMessage("That is not a container."); + return; + } + + try + { + var ext = Extensions.Parse(from, ref args); + + if (!CheckObjectTypes(from, command, ext, out var items, out var _)) + return; + + if (!items) + { + from.SendMessage("This command only works on items."); + return; + } + + var list = new List(); + + foreach (var item in cont.FindItemsByType()) + if (ext.IsValid(item)) + list.Add(item); + + ext.Filter(list); + + RunCommand(from, list, command, args); + } + catch (Exception e) + { + from.SendMessage(e.Message); + } + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Implementors/FacetCommandImplementor.cs b/Projects/UOContent/Commands/Generic/Implementors/FacetCommandImplementor.cs index b27f6184f..8726155fa 100644 --- a/Projects/UOContent/Commands/Generic/Implementors/FacetCommandImplementor.cs +++ b/Projects/UOContent/Commands/Generic/Implementors/FacetCommandImplementor.cs @@ -1,31 +1,31 @@ -namespace Server.Commands.Generic -{ - public class FacetCommandImplementor : BaseCommandImplementor - { - public FacetCommandImplementor() - { - Accessors = new[] { "Facet" }; - SupportRequirement = CommandSupport.Area; - SupportsConditionals = true; - AccessLevel = AccessLevel.GameMaster; - Usage = "Facet [condition]"; - Description = - "Invokes the command on all appropriate objects within your facet's map bounds. Optional condition arguments can further restrict the set of objects."; - } - - public override void Process(Mobile from, BaseCommand command, string[] args) - { - AreaCommandImplementor impl = AreaCommandImplementor.Instance; - - if (impl == null) - return; - - Map map = from.Map; - - if (map == null || map == Map.Internal) - return; - - impl.OnTarget(from, map, Point3D.Zero, new Point3D(map.Width - 1, map.Height - 1, 0), command, args); - } - } -} \ No newline at end of file +namespace Server.Commands.Generic +{ + public class FacetCommandImplementor : BaseCommandImplementor + { + public FacetCommandImplementor() + { + Accessors = new[] { "Facet" }; + SupportRequirement = CommandSupport.Area; + SupportsConditionals = true; + AccessLevel = AccessLevel.GameMaster; + Usage = "Facet [condition]"; + Description = + "Invokes the command on all appropriate objects within your facet's map bounds. Optional condition arguments can further restrict the set of objects."; + } + + public override void Process(Mobile from, BaseCommand command, string[] args) + { + var impl = AreaCommandImplementor.Instance; + + if (impl == null) + return; + + var map = from.Map; + + if (map == null || map == Map.Internal) + return; + + impl.OnTarget(from, map, Point3D.Zero, new Point3D(map.Width - 1, map.Height - 1, 0), command, args); + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Implementors/GlobalCommandImplementor.cs b/Projects/UOContent/Commands/Generic/Implementors/GlobalCommandImplementor.cs index e68726237..628c6bfd2 100644 --- a/Projects/UOContent/Commands/Generic/Implementors/GlobalCommandImplementor.cs +++ b/Projects/UOContent/Commands/Generic/Implementors/GlobalCommandImplementor.cs @@ -1,50 +1,50 @@ -using System; -using System.Collections.Generic; - -namespace Server.Commands.Generic -{ - public class GlobalCommandImplementor : BaseCommandImplementor - { - public GlobalCommandImplementor() - { - Accessors = new[] { "Global" }; - SupportRequirement = CommandSupport.Global; - SupportsConditionals = true; - AccessLevel = AccessLevel.Administrator; - Usage = "Global [condition]"; - Description = - "Invokes the command on all appropriate objects in the world. Optional condition arguments can further restrict the set of objects."; - } - - public override void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj) - { - try - { - Extensions ext = Extensions.Parse(from, ref args); - - if (!CheckObjectTypes(from, command, ext, out bool items, out bool mobiles)) - return; - - List list = new List(); - - if (items) - foreach (Item item in World.Items.Values) - if (ext.IsValid(item)) - list.Add(item); - - if (mobiles) - foreach (Mobile mob in World.Mobiles.Values) - if (ext.IsValid(mob)) - list.Add(mob); - - ext.Filter(list); - - obj = list; - } - catch (Exception ex) - { - from.SendMessage(ex.Message); - } - } - } -} \ No newline at end of file +using System; +using System.Collections.Generic; + +namespace Server.Commands.Generic +{ + public class GlobalCommandImplementor : BaseCommandImplementor + { + public GlobalCommandImplementor() + { + Accessors = new[] { "Global" }; + SupportRequirement = CommandSupport.Global; + SupportsConditionals = true; + AccessLevel = AccessLevel.Administrator; + Usage = "Global [condition]"; + Description = + "Invokes the command on all appropriate objects in the world. Optional condition arguments can further restrict the set of objects."; + } + + public override void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj) + { + try + { + var ext = Extensions.Parse(from, ref args); + + if (!CheckObjectTypes(from, command, ext, out var items, out var mobiles)) + return; + + var list = new List(); + + if (items) + foreach (var item in World.Items.Values) + if (ext.IsValid(item)) + list.Add(item); + + if (mobiles) + foreach (var mob in World.Mobiles.Values) + if (ext.IsValid(mob)) + list.Add(mob); + + ext.Filter(list); + + obj = list; + } + catch (Exception ex) + { + from.SendMessage(ex.Message); + } + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Implementors/IPAddressCommandImplementor.cs b/Projects/UOContent/Commands/Generic/Implementors/IPAddressCommandImplementor.cs index 927867b50..b9a85fd02 100644 --- a/Projects/UOContent/Commands/Generic/Implementors/IPAddressCommandImplementor.cs +++ b/Projects/UOContent/Commands/Generic/Implementors/IPAddressCommandImplementor.cs @@ -1,63 +1,63 @@ -using System; -using System.Collections.Generic; -using System.Net; -using Server.Network; - -namespace Server.Commands.Generic -{ - public class IPAddressCommandImplementor : BaseCommandImplementor - { - public IPAddressCommandImplementor() - { - Accessors = new[] { "IPAddress" }; - SupportRequirement = CommandSupport.IPAddress; - SupportsConditionals = true; - AccessLevel = AccessLevel.Administrator; - Usage = "IPAddress [condition]"; - Description = - "Invokes the command on one mobile from each IP address that is logged in. Optional condition arguments can further restrict the set of objects."; - } - - public override void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj) - { - try - { - Extensions ext = Extensions.Parse(from, ref args); - - if (!CheckObjectTypes(from, command, ext, out bool _, out bool mobiles)) - return; - - if (!mobiles) // sanity check - { - command.LogFailure("This command does not support items."); - return; - } - - List list = new List(); - List addresses = new List(); - - List states = TcpServer.Instances; - - for (int i = 0; i < states.Count; ++i) - { - NetState ns = states[i]; - Mobile mob = ns.Mobile; - - if (mob != null && !addresses.Contains(ns.Address) && ext.IsValid(mob)) - { - list.Add(mob); - addresses.Add(ns.Address); - } - } - - ext.Filter(list); - - obj = list; - } - catch (Exception ex) - { - from.SendMessage(ex.Message); - } - } - } -} +using System; +using System.Collections.Generic; +using System.Net; +using Server.Network; + +namespace Server.Commands.Generic +{ + public class IPAddressCommandImplementor : BaseCommandImplementor + { + public IPAddressCommandImplementor() + { + Accessors = new[] { "IPAddress" }; + SupportRequirement = CommandSupport.IPAddress; + SupportsConditionals = true; + AccessLevel = AccessLevel.Administrator; + Usage = "IPAddress [condition]"; + Description = + "Invokes the command on one mobile from each IP address that is logged in. Optional condition arguments can further restrict the set of objects."; + } + + public override void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj) + { + try + { + var ext = Extensions.Parse(from, ref args); + + if (!CheckObjectTypes(from, command, ext, out var _, out var mobiles)) + return; + + if (!mobiles) // sanity check + { + command.LogFailure("This command does not support items."); + return; + } + + var list = new List(); + var addresses = new List(); + + var states = TcpServer.Instances; + + for (var i = 0; i < states.Count; ++i) + { + var ns = states[i]; + var mob = ns.Mobile; + + if (mob != null && !addresses.Contains(ns.Address) && ext.IsValid(mob)) + { + list.Add(mob); + addresses.Add(ns.Address); + } + } + + ext.Filter(list); + + obj = list; + } + catch (Exception ex) + { + from.SendMessage(ex.Message); + } + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Implementors/MultiCommandImplementor.cs b/Projects/UOContent/Commands/Generic/Implementors/MultiCommandImplementor.cs index 67db03b2b..000121a21 100644 --- a/Projects/UOContent/Commands/Generic/Implementors/MultiCommandImplementor.cs +++ b/Projects/UOContent/Commands/Generic/Implementors/MultiCommandImplementor.cs @@ -1,73 +1,88 @@ -using Server.Targeting; - -namespace Server.Commands.Generic -{ - public class MultiCommandImplementor : BaseCommandImplementor - { - public MultiCommandImplementor() - { - Accessors = new[] { "Multi", "m" }; - SupportRequirement = CommandSupport.Multi; - AccessLevel = AccessLevel.Counselor; - Usage = "Multi "; - Description = "Invokes the command on multiple targeted objects."; - } - - public override void Process(Mobile from, BaseCommand command, string[] args) - { - if (command.ValidateArgs(this, new CommandEventArgs(from, command.Commands[0], GenerateArgString(args), args))) - from.BeginTarget(-1, command.ObjectTypes == ObjectTypes.All, TargetFlags.None, - (m, targeted, a) => OnTarget(m, targeted, command, a), args); - } - - public void OnTarget(Mobile from, object targeted, BaseCommand command, string[] args) - { - if (!BaseCommand.IsAccessible(from, targeted)) - { - from.SendLocalizedMessage(500447); // That is not accessible. - from.BeginTarget(-1, command.ObjectTypes == ObjectTypes.All, TargetFlags.None, - (m, t, a) => OnTarget(m, t, command, a), args); - return; - } - - switch (command.ObjectTypes) - { - case ObjectTypes.Both: - { - if (!(targeted is Item || targeted is Mobile)) - { - from.SendMessage("This command does not work on that."); - return; - } - - break; - } - case ObjectTypes.Items: - { - if (!(targeted is Item)) - { - from.SendMessage("This command only works on items."); - return; - } - - break; - } - case ObjectTypes.Mobiles: - { - if (!(targeted is Mobile)) - { - from.SendMessage("This command only works on mobiles."); - return; - } - - break; - } - } - - RunCommand(from, targeted, command, args); - - from.BeginTarget(-1, command.ObjectTypes == ObjectTypes.All, TargetFlags.None, - (m, t, a) => OnTarget(m, t, command, a), args); - } - } -} +using Server.Targeting; + +namespace Server.Commands.Generic +{ + public class MultiCommandImplementor : BaseCommandImplementor + { + public MultiCommandImplementor() + { + Accessors = new[] { "Multi", "m" }; + SupportRequirement = CommandSupport.Multi; + AccessLevel = AccessLevel.Counselor; + Usage = "Multi "; + Description = "Invokes the command on multiple targeted objects."; + } + + public override void Process(Mobile from, BaseCommand command, string[] args) + { + if (command.ValidateArgs(this, new CommandEventArgs(from, command.Commands[0], GenerateArgString(args), args))) + from.BeginTarget( + -1, + command.ObjectTypes == ObjectTypes.All, + TargetFlags.None, + (m, targeted, a) => OnTarget(m, targeted, command, a), + args + ); + } + + public void OnTarget(Mobile from, object targeted, BaseCommand command, string[] args) + { + if (!BaseCommand.IsAccessible(from, targeted)) + { + from.SendLocalizedMessage(500447); // That is not accessible. + from.BeginTarget( + -1, + command.ObjectTypes == ObjectTypes.All, + TargetFlags.None, + (m, t, a) => OnTarget(m, t, command, a), + args + ); + return; + } + + switch (command.ObjectTypes) + { + case ObjectTypes.Both: + { + if (!(targeted is Item || targeted is Mobile)) + { + from.SendMessage("This command does not work on that."); + return; + } + + break; + } + case ObjectTypes.Items: + { + if (!(targeted is Item)) + { + from.SendMessage("This command only works on items."); + return; + } + + break; + } + case ObjectTypes.Mobiles: + { + if (!(targeted is Mobile)) + { + from.SendMessage("This command only works on mobiles."); + return; + } + + break; + } + } + + RunCommand(from, targeted, command, args); + + from.BeginTarget( + -1, + command.ObjectTypes == ObjectTypes.All, + TargetFlags.None, + (m, t, a) => OnTarget(m, t, command, a), + args + ); + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Implementors/ObjectConditional.cs b/Projects/UOContent/Commands/Generic/Implementors/ObjectConditional.cs index bcf9df2ba..cd60c7a45 100644 --- a/Projects/UOContent/Commands/Generic/Implementors/ObjectConditional.cs +++ b/Projects/UOContent/Commands/Generic/Implementors/ObjectConditional.cs @@ -1,194 +1,194 @@ -using System; -using System.Collections.Generic; - -namespace Server.Commands.Generic -{ - public sealed class ObjectConditional - { - private static readonly Type typeofItem = typeof(Item); - private static readonly Type typeofMobile = typeof(Mobile); - - public static readonly ObjectConditional Empty = new ObjectConditional(null, null); - - private IConditional[] m_Conditionals; - - private readonly ICondition[][] m_Conditions; - - public ObjectConditional(Type objectType, ICondition[][] conditions) - { - Type = objectType; - m_Conditions = conditions; - } - - public Type Type { get; } - - public bool IsItem => Type == null || Type == typeofItem || Type.IsSubclassOf(typeofItem); - - public bool IsMobile => Type == null || Type == typeofMobile || Type.IsSubclassOf(typeofMobile); - - public bool HasCompiled => m_Conditionals != null; - - public void Compile(ref AssemblyEmitter emitter) - { - emitter ??= new AssemblyEmitter("__dynamic"); - - m_Conditionals = new IConditional[m_Conditions.Length]; - - for (int i = 0; i < m_Conditionals.Length; ++i) - m_Conditionals[i] = ConditionalCompiler.Compile(emitter, Type, m_Conditions[i], i); - } - - public bool CheckCondition(object obj) - { - if (Type == null) - return true; // null type means no condition - - if (!HasCompiled) - { - AssemblyEmitter emitter = null; - - Compile(ref emitter); - } - - for (int i = 0; i < m_Conditionals.Length; ++i) - if (m_Conditionals[i].Verify(obj)) - return true; - - return false; // all conditions false - } - - public static ObjectConditional Parse(Mobile from, ref string[] args) - { - string[] conditionArgs = null; - - for (int i = 0; i < args.Length; ++i) - if (Insensitive.Equals(args[i], "where")) - { - string[] origArgs = args; - - args = new string[i]; - - for (int j = 0; j < args.Length; ++j) - args[j] = origArgs[j]; - - conditionArgs = new string[origArgs.Length - i - 1]; - - for (int j = 0; j < conditionArgs.Length; ++j) - conditionArgs[j] = origArgs[i + j + 1]; - - break; - } - - return ParseDirect(from, conditionArgs, 0, conditionArgs?.Length ?? 0); - } - - public static ObjectConditional ParseDirect(Mobile from, string[] args, int offset, int size) - { - if (args == null || size == 0) - return Empty; - - int index = 0; - - Type objectType = AssemblyHandler.FindFirstTypeForName(args[offset + index], true); - - if (objectType == null) - throw new Exception($"No type with that name ({args[offset + index]}) was found."); - - ++index; - - List conditions = new List(); - List current = new List(); - - current.Add(TypeCondition.Default); - - while (index < size) - { - string cur = args[offset + index]; - - bool inverse = false; - - if (Insensitive.Equals(cur, "not") || cur == "!") - { - inverse = true; - ++index; - - if (index >= size) - throw new Exception("Improperly formatted object conditional."); - } - else if (Insensitive.Equals(cur, "or") || cur == "||") - { - if (current.Count > 1) - { - conditions.Add(current.ToArray()); - - current.Clear(); - current.Add(TypeCondition.Default); - } - - ++index; - - continue; - } - - string binding = args[offset + index]; - index++; - - if (index >= size) - throw new Exception("Improperly formatted object conditional."); - - string oper = args[offset + index]; - index++; - - if (index >= size) - throw new Exception("Improperly formatted object conditional."); - - string val = args[offset + index]; - index++; - - Property prop = new Property(binding); - - prop.BindTo(objectType, PropertyAccess.Read); - prop.CheckAccess(from); - - var condition = oper switch - { - "=" => (ICondition)new ComparisonCondition(prop, inverse, ComparisonOperator.Equal, val), - "==" => new ComparisonCondition(prop, inverse, ComparisonOperator.Equal, val), - "is" => new ComparisonCondition(prop, inverse, ComparisonOperator.Equal, val), - "!=" => new ComparisonCondition(prop, inverse, ComparisonOperator.NotEqual, val), - ">" => new ComparisonCondition(prop, inverse, ComparisonOperator.Greater, val), - "<" => new ComparisonCondition(prop, inverse, ComparisonOperator.Lesser, val), - ">=" => new ComparisonCondition(prop, inverse, ComparisonOperator.GreaterEqual, val), - "<=" => new ComparisonCondition(prop, inverse, ComparisonOperator.LesserEqual, val), - "==~" => new StringCondition(prop, inverse, StringOperator.Equal, val, true), - "~==" => new StringCondition(prop, inverse, StringOperator.Equal, val, true), - "=~" => new StringCondition(prop, inverse, StringOperator.Equal, val, true), - "~=" => new StringCondition(prop, inverse, StringOperator.Equal, val, true), - "is~" => new StringCondition(prop, inverse, StringOperator.Equal, val, true), - "~is" => new StringCondition(prop, inverse, StringOperator.Equal, val, true), - "!=~" => new StringCondition(prop, inverse, StringOperator.NotEqual, val, true), - "~!=" => new StringCondition(prop, inverse, StringOperator.NotEqual, val, true), - "starts" => new StringCondition(prop, inverse, StringOperator.StartsWith, val, false), - "starts~" => new StringCondition(prop, inverse, StringOperator.StartsWith, val, true), - "~starts" => new StringCondition(prop, inverse, StringOperator.StartsWith, val, true), - "ends" => new StringCondition(prop, inverse, StringOperator.EndsWith, val, false), - "ends~" => new StringCondition(prop, inverse, StringOperator.EndsWith, val, true), - "~ends" => new StringCondition(prop, inverse, StringOperator.EndsWith, val, true), - "contains" => new StringCondition(prop, inverse, StringOperator.Contains, val, false), - "contains~" => new StringCondition(prop, inverse, StringOperator.Contains, val, true), - "~contains" => new StringCondition(prop, inverse, StringOperator.Contains, val, true), - _ => null - }; - - if (condition == null) - throw new InvalidOperationException($"Unrecognized operator (\"{oper}\")."); - - current.Add(condition); - } - - conditions.Add(current.ToArray()); - - return new ObjectConditional(objectType, conditions.ToArray()); - } - } -} +using System; +using System.Collections.Generic; + +namespace Server.Commands.Generic +{ + public sealed class ObjectConditional + { + private static readonly Type typeofItem = typeof(Item); + private static readonly Type typeofMobile = typeof(Mobile); + + public static readonly ObjectConditional Empty = new ObjectConditional(null, null); + + private readonly ICondition[][] m_Conditions; + + private IConditional[] m_Conditionals; + + public ObjectConditional(Type objectType, ICondition[][] conditions) + { + Type = objectType; + m_Conditions = conditions; + } + + public Type Type { get; } + + public bool IsItem => Type == null || Type == typeofItem || Type.IsSubclassOf(typeofItem); + + public bool IsMobile => Type == null || Type == typeofMobile || Type.IsSubclassOf(typeofMobile); + + public bool HasCompiled => m_Conditionals != null; + + public void Compile(ref AssemblyEmitter emitter) + { + emitter ??= new AssemblyEmitter("__dynamic"); + + m_Conditionals = new IConditional[m_Conditions.Length]; + + for (var i = 0; i < m_Conditionals.Length; ++i) + m_Conditionals[i] = ConditionalCompiler.Compile(emitter, Type, m_Conditions[i], i); + } + + public bool CheckCondition(object obj) + { + if (Type == null) + return true; // null type means no condition + + if (!HasCompiled) + { + AssemblyEmitter emitter = null; + + Compile(ref emitter); + } + + for (var i = 0; i < m_Conditionals.Length; ++i) + if (m_Conditionals[i].Verify(obj)) + return true; + + return false; // all conditions false + } + + public static ObjectConditional Parse(Mobile from, ref string[] args) + { + string[] conditionArgs = null; + + for (var i = 0; i < args.Length; ++i) + if (Insensitive.Equals(args[i], "where")) + { + var origArgs = args; + + args = new string[i]; + + for (var j = 0; j < args.Length; ++j) + args[j] = origArgs[j]; + + conditionArgs = new string[origArgs.Length - i - 1]; + + for (var j = 0; j < conditionArgs.Length; ++j) + conditionArgs[j] = origArgs[i + j + 1]; + + break; + } + + return ParseDirect(from, conditionArgs, 0, conditionArgs?.Length ?? 0); + } + + public static ObjectConditional ParseDirect(Mobile from, string[] args, int offset, int size) + { + if (args == null || size == 0) + return Empty; + + var index = 0; + + var objectType = AssemblyHandler.FindFirstTypeForName(args[offset + index], true); + + if (objectType == null) + throw new Exception($"No type with that name ({args[offset + index]}) was found."); + + ++index; + + var conditions = new List(); + var current = new List(); + + current.Add(TypeCondition.Default); + + while (index < size) + { + var cur = args[offset + index]; + + var inverse = false; + + if (Insensitive.Equals(cur, "not") || cur == "!") + { + inverse = true; + ++index; + + if (index >= size) + throw new Exception("Improperly formatted object conditional."); + } + else if (Insensitive.Equals(cur, "or") || cur == "||") + { + if (current.Count > 1) + { + conditions.Add(current.ToArray()); + + current.Clear(); + current.Add(TypeCondition.Default); + } + + ++index; + + continue; + } + + var binding = args[offset + index]; + index++; + + if (index >= size) + throw new Exception("Improperly formatted object conditional."); + + var oper = args[offset + index]; + index++; + + if (index >= size) + throw new Exception("Improperly formatted object conditional."); + + var val = args[offset + index]; + index++; + + var prop = new Property(binding); + + prop.BindTo(objectType, PropertyAccess.Read); + prop.CheckAccess(from); + + var condition = oper switch + { + "=" => (ICondition)new ComparisonCondition(prop, inverse, ComparisonOperator.Equal, val), + "==" => new ComparisonCondition(prop, inverse, ComparisonOperator.Equal, val), + "is" => new ComparisonCondition(prop, inverse, ComparisonOperator.Equal, val), + "!=" => new ComparisonCondition(prop, inverse, ComparisonOperator.NotEqual, val), + ">" => new ComparisonCondition(prop, inverse, ComparisonOperator.Greater, val), + "<" => new ComparisonCondition(prop, inverse, ComparisonOperator.Lesser, val), + ">=" => new ComparisonCondition(prop, inverse, ComparisonOperator.GreaterEqual, val), + "<=" => new ComparisonCondition(prop, inverse, ComparisonOperator.LesserEqual, val), + "==~" => new StringCondition(prop, inverse, StringOperator.Equal, val, true), + "~==" => new StringCondition(prop, inverse, StringOperator.Equal, val, true), + "=~" => new StringCondition(prop, inverse, StringOperator.Equal, val, true), + "~=" => new StringCondition(prop, inverse, StringOperator.Equal, val, true), + "is~" => new StringCondition(prop, inverse, StringOperator.Equal, val, true), + "~is" => new StringCondition(prop, inverse, StringOperator.Equal, val, true), + "!=~" => new StringCondition(prop, inverse, StringOperator.NotEqual, val, true), + "~!=" => new StringCondition(prop, inverse, StringOperator.NotEqual, val, true), + "starts" => new StringCondition(prop, inverse, StringOperator.StartsWith, val, false), + "starts~" => new StringCondition(prop, inverse, StringOperator.StartsWith, val, true), + "~starts" => new StringCondition(prop, inverse, StringOperator.StartsWith, val, true), + "ends" => new StringCondition(prop, inverse, StringOperator.EndsWith, val, false), + "ends~" => new StringCondition(prop, inverse, StringOperator.EndsWith, val, true), + "~ends" => new StringCondition(prop, inverse, StringOperator.EndsWith, val, true), + "contains" => new StringCondition(prop, inverse, StringOperator.Contains, val, false), + "contains~" => new StringCondition(prop, inverse, StringOperator.Contains, val, true), + "~contains" => new StringCondition(prop, inverse, StringOperator.Contains, val, true), + _ => null + }; + + if (condition == null) + throw new InvalidOperationException($"Unrecognized operator (\"{oper}\")."); + + current.Add(condition); + } + + conditions.Add(current.ToArray()); + + return new ObjectConditional(objectType, conditions.ToArray()); + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Implementors/OnlineCommandImplementor.cs b/Projects/UOContent/Commands/Generic/Implementors/OnlineCommandImplementor.cs index 2f80acea7..476b74244 100644 --- a/Projects/UOContent/Commands/Generic/Implementors/OnlineCommandImplementor.cs +++ b/Projects/UOContent/Commands/Generic/Implementors/OnlineCommandImplementor.cs @@ -1,64 +1,64 @@ -using System; -using System.Collections.Generic; -using Server.Network; - -namespace Server.Commands.Generic -{ - public class OnlineCommandImplementor : BaseCommandImplementor - { - public OnlineCommandImplementor() - { - Accessors = new[] { "Online" }; - SupportRequirement = CommandSupport.Online; - SupportsConditionals = true; - AccessLevel = AccessLevel.GameMaster; - Usage = "Online [condition]"; - Description = - "Invokes the command on all mobiles that are currently logged in. Optional condition arguments can further restrict the set of objects."; - } - - public override void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj) - { - try - { - Extensions ext = Extensions.Parse(from, ref args); - - if (!CheckObjectTypes(from, command, ext, out bool _, out bool mobiles)) - return; - - if (!mobiles) // sanity check - { - command.LogFailure("This command does not support items."); - return; - } - - List list = new List(); - - List states = TcpServer.Instances; - - for (int i = 0; i < states.Count; ++i) - { - NetState ns = states[i]; - Mobile mob = ns.Mobile; - - if (mob == null) - continue; - - if (!BaseCommand.IsAccessible(from, mob)) - continue; - - if (ext.IsValid(mob)) - list.Add(mob); - } - - ext.Filter(list); - - obj = list; - } - catch (Exception ex) - { - from.SendMessage(ex.Message); - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Network; + +namespace Server.Commands.Generic +{ + public class OnlineCommandImplementor : BaseCommandImplementor + { + public OnlineCommandImplementor() + { + Accessors = new[] { "Online" }; + SupportRequirement = CommandSupport.Online; + SupportsConditionals = true; + AccessLevel = AccessLevel.GameMaster; + Usage = "Online [condition]"; + Description = + "Invokes the command on all mobiles that are currently logged in. Optional condition arguments can further restrict the set of objects."; + } + + public override void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj) + { + try + { + var ext = Extensions.Parse(from, ref args); + + if (!CheckObjectTypes(from, command, ext, out var _, out var mobiles)) + return; + + if (!mobiles) // sanity check + { + command.LogFailure("This command does not support items."); + return; + } + + var list = new List(); + + var states = TcpServer.Instances; + + for (var i = 0; i < states.Count; ++i) + { + var ns = states[i]; + var mob = ns.Mobile; + + if (mob == null) + continue; + + if (!BaseCommand.IsAccessible(from, mob)) + continue; + + if (ext.IsValid(mob)) + list.Add(mob); + } + + ext.Filter(list); + + obj = list; + } + catch (Exception ex) + { + from.SendMessage(ex.Message); + } + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Implementors/RangeCommandImplementor.cs b/Projects/UOContent/Commands/Generic/Implementors/RangeCommandImplementor.cs index b8d0d44db..f163bcb75 100644 --- a/Projects/UOContent/Commands/Generic/Implementors/RangeCommandImplementor.cs +++ b/Projects/UOContent/Commands/Generic/Implementors/RangeCommandImplementor.cs @@ -1,79 +1,80 @@ -namespace Server.Commands.Generic -{ - public class RangeCommandImplementor : BaseCommandImplementor - { - public RangeCommandImplementor() - { - Accessors = new[] { "Range" }; - SupportRequirement = CommandSupport.Area; - SupportsConditionals = true; - AccessLevel = AccessLevel.GameMaster; - Usage = "Range [condition]"; - Description = - "Invokes the command on all appropriate objects within a specified range of you. Optional condition arguments can further restrict the set of objects."; - - Instance = this; - } - - public static RangeCommandImplementor Instance { get; private set; } - - public override void Execute(CommandEventArgs e) - { - if (e.Length >= 2) - { - int range = e.GetInt32(0); - - if (range < 0) - { - e.Mobile.SendMessage("The range must not be negative."); - } - else - { - Commands.TryGetValue(e.GetString(1), out BaseCommand command); - - if (command == null) - { - e.Mobile.SendMessage( - "That is either an invalid command name or one that does not support this modifier."); - } - else if (e.Mobile.AccessLevel < command.AccessLevel) - { - e.Mobile.SendMessage("You do not have access to that command."); - } - else - { - string[] oldArgs = e.Arguments; - string[] args = new string[oldArgs.Length - 2]; - - for (int i = 0; i < args.Length; ++i) - args[i] = oldArgs[i + 2]; - - Process(range, e.Mobile, command, args); - } - } - } - else - { - e.Mobile.SendMessage("You must supply a range and a command name."); - } - } - - public void Process(int range, Mobile from, BaseCommand command, string[] args) - { - AreaCommandImplementor impl = AreaCommandImplementor.Instance; - - if (impl == null) - return; - - Map map = from.Map; - - if (map == null || map == Map.Internal) - return; - - Point3D start = new Point3D(from.X - range, from.Y - range, from.Z); - Point3D end = new Point3D(from.X + range, from.Y + range, from.Z); - - impl.OnTarget(from, map, start, end, command, args); - } - } -} \ No newline at end of file +namespace Server.Commands.Generic +{ + public class RangeCommandImplementor : BaseCommandImplementor + { + public RangeCommandImplementor() + { + Accessors = new[] { "Range" }; + SupportRequirement = CommandSupport.Area; + SupportsConditionals = true; + AccessLevel = AccessLevel.GameMaster; + Usage = "Range [condition]"; + Description = + "Invokes the command on all appropriate objects within a specified range of you. Optional condition arguments can further restrict the set of objects."; + + Instance = this; + } + + public static RangeCommandImplementor Instance { get; private set; } + + public override void Execute(CommandEventArgs e) + { + if (e.Length >= 2) + { + var range = e.GetInt32(0); + + if (range < 0) + { + e.Mobile.SendMessage("The range must not be negative."); + } + else + { + Commands.TryGetValue(e.GetString(1), out var command); + + if (command == null) + { + e.Mobile.SendMessage( + "That is either an invalid command name or one that does not support this modifier." + ); + } + else if (e.Mobile.AccessLevel < command.AccessLevel) + { + e.Mobile.SendMessage("You do not have access to that command."); + } + else + { + var oldArgs = e.Arguments; + var args = new string[oldArgs.Length - 2]; + + for (var i = 0; i < args.Length; ++i) + args[i] = oldArgs[i + 2]; + + Process(range, e.Mobile, command, args); + } + } + } + else + { + e.Mobile.SendMessage("You must supply a range and a command name."); + } + } + + public void Process(int range, Mobile from, BaseCommand command, string[] args) + { + var impl = AreaCommandImplementor.Instance; + + if (impl == null) + return; + + var map = from.Map; + + if (map == null || map == Map.Internal) + return; + + var start = new Point3D(from.X - range, from.Y - range, from.Z); + var end = new Point3D(from.X + range, from.Y + range, from.Z); + + impl.OnTarget(from, map, start, end, command, args); + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Implementors/RegionCommandImplementor.cs b/Projects/UOContent/Commands/Generic/Implementors/RegionCommandImplementor.cs index 5739236f9..2e657185e 100644 --- a/Projects/UOContent/Commands/Generic/Implementors/RegionCommandImplementor.cs +++ b/Projects/UOContent/Commands/Generic/Implementors/RegionCommandImplementor.cs @@ -1,59 +1,59 @@ -using System; -using System.Collections.Generic; - -namespace Server.Commands.Generic -{ - public class RegionCommandImplementor : BaseCommandImplementor - { - public RegionCommandImplementor() - { - Accessors = new[] { "Region" }; - SupportRequirement = CommandSupport.Region; - SupportsConditionals = true; - AccessLevel = AccessLevel.GameMaster; - Usage = "Region [condition]"; - Description = - "Invokes the command on all appropriate mobiles in your current region. Optional condition arguments can further restrict the set of objects."; - } - - public override void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj) - { - try - { - Extensions ext = Extensions.Parse(from, ref args); - - if (!CheckObjectTypes(from, command, ext, out bool _, out bool mobiles)) - return; - - Region reg = from.Region; - - List list = new List(); - - if (mobiles) - { - foreach (Mobile mob in reg.GetMobiles()) - { - if (!BaseCommand.IsAccessible(from, mob)) - continue; - - if (ext.IsValid(mob)) - list.Add(mob); - } - } - else - { - command.LogFailure("This command does not support items."); - return; - } - - ext.Filter(list); - - obj = list; - } - catch (Exception ex) - { - from.SendMessage(ex.Message); - } - } - } -} \ No newline at end of file +using System; +using System.Collections.Generic; + +namespace Server.Commands.Generic +{ + public class RegionCommandImplementor : BaseCommandImplementor + { + public RegionCommandImplementor() + { + Accessors = new[] { "Region" }; + SupportRequirement = CommandSupport.Region; + SupportsConditionals = true; + AccessLevel = AccessLevel.GameMaster; + Usage = "Region [condition]"; + Description = + "Invokes the command on all appropriate mobiles in your current region. Optional condition arguments can further restrict the set of objects."; + } + + public override void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj) + { + try + { + var ext = Extensions.Parse(from, ref args); + + if (!CheckObjectTypes(from, command, ext, out var _, out var mobiles)) + return; + + var reg = from.Region; + + var list = new List(); + + if (mobiles) + { + foreach (var mob in reg.GetMobiles()) + { + if (!BaseCommand.IsAccessible(from, mob)) + continue; + + if (ext.IsValid(mob)) + list.Add(mob); + } + } + else + { + command.LogFailure("This command does not support items."); + return; + } + + ext.Filter(list); + + obj = list; + } + catch (Exception ex) + { + from.SendMessage(ex.Message); + } + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Implementors/ScreenCommandImplementor.cs b/Projects/UOContent/Commands/Generic/Implementors/ScreenCommandImplementor.cs index 134a4922b..da4c3f1a4 100644 --- a/Projects/UOContent/Commands/Generic/Implementors/ScreenCommandImplementor.cs +++ b/Projects/UOContent/Commands/Generic/Implementors/ScreenCommandImplementor.cs @@ -1,23 +1,23 @@ -namespace Server.Commands.Generic -{ - public class ScreenCommandImplementor : BaseCommandImplementor - { - public ScreenCommandImplementor() - { - Accessors = new[] { "Screen" }; - SupportRequirement = CommandSupport.Area; - SupportsConditionals = true; - AccessLevel = AccessLevel.GameMaster; - Usage = "Screen [condition]"; - Description = - "Invokes the command on all appropriate objects in your screen. Optional condition arguments can further restrict the set of objects."; - } - - public override void Process(Mobile from, BaseCommand command, string[] args) - { - RangeCommandImplementor impl = RangeCommandImplementor.Instance; - - impl?.Process(18, from, command, args); - } - } -} \ No newline at end of file +namespace Server.Commands.Generic +{ + public class ScreenCommandImplementor : BaseCommandImplementor + { + public ScreenCommandImplementor() + { + Accessors = new[] { "Screen" }; + SupportRequirement = CommandSupport.Area; + SupportsConditionals = true; + AccessLevel = AccessLevel.GameMaster; + Usage = "Screen [condition]"; + Description = + "Invokes the command on all appropriate objects in your screen. Optional condition arguments can further restrict the set of objects."; + } + + public override void Process(Mobile from, BaseCommand command, string[] args) + { + var impl = RangeCommandImplementor.Instance; + + impl?.Process(18, from, command, args); + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Implementors/SelfCommandImplementor.cs b/Projects/UOContent/Commands/Generic/Implementors/SelfCommandImplementor.cs index a3c2deafb..fab269b62 100644 --- a/Projects/UOContent/Commands/Generic/Implementors/SelfCommandImplementor.cs +++ b/Projects/UOContent/Commands/Generic/Implementors/SelfCommandImplementor.cs @@ -1,22 +1,22 @@ -namespace Server.Commands.Generic -{ - public class SelfCommandImplementor : BaseCommandImplementor - { - public SelfCommandImplementor() - { - Accessors = new[] { "Self" }; - SupportRequirement = CommandSupport.Self; - AccessLevel = AccessLevel.Counselor; - Usage = "Self "; - Description = "Invokes the command on the commanding player."; - } - - public override void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj) - { - if (command.ObjectTypes == ObjectTypes.Items) - return; // sanity check - - obj = from; - } - } -} \ No newline at end of file +namespace Server.Commands.Generic +{ + public class SelfCommandImplementor : BaseCommandImplementor + { + public SelfCommandImplementor() + { + Accessors = new[] { "Self" }; + SupportRequirement = CommandSupport.Self; + AccessLevel = AccessLevel.Counselor; + Usage = "Self "; + Description = "Invokes the command on the commanding player."; + } + + public override void Compile(Mobile from, BaseCommand command, ref string[] args, ref object obj) + { + if (command.ObjectTypes == ObjectTypes.Items) + return; // sanity check + + obj = from; + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Implementors/SerialCommandImplementor.cs b/Projects/UOContent/Commands/Generic/Implementors/SerialCommandImplementor.cs index 7b0f9133f..51daa43ee 100644 --- a/Projects/UOContent/Commands/Generic/Implementors/SerialCommandImplementor.cs +++ b/Projects/UOContent/Commands/Generic/Implementors/SerialCommandImplementor.cs @@ -1,86 +1,87 @@ -namespace Server.Commands.Generic -{ - public class SerialCommandImplementor : BaseCommandImplementor - { - public SerialCommandImplementor() - { - Accessors = new[] { "Serial" }; - SupportRequirement = CommandSupport.Single; - AccessLevel = AccessLevel.Counselor; - Usage = "Serial "; - Description = "Invokes the command on a single object by serial."; - } - - public override void Execute(CommandEventArgs e) - { - if (e.Length >= 2) - { - Serial serial = e.GetUInt32(0); - - object obj = null; - - if (serial.IsItem) - obj = World.FindItem(serial); - else if (serial.IsMobile) - obj = World.FindMobile(serial); - - if (obj == null) - { - e.Mobile.SendMessage("That is not a valid serial."); - } - else - { - Commands.TryGetValue(e.GetString(1), out BaseCommand command); - - if (command == null) - { - e.Mobile.SendMessage( - "That is either an invalid command name or one that does not support this modifier."); - } - else if (e.Mobile.AccessLevel < command.AccessLevel) - { - e.Mobile.SendMessage("You do not have access to that command."); - } - else - { - switch (command.ObjectTypes) - { - case ObjectTypes.Items: - { - if (!(obj is Item)) - { - e.Mobile.SendMessage("This command only works on items."); - return; - } - - break; - } - case ObjectTypes.Mobiles: - { - if (!(obj is Mobile)) - { - e.Mobile.SendMessage("This command only works on mobiles."); - return; - } - - break; - } - } - - string[] oldArgs = e.Arguments; - string[] args = new string[oldArgs.Length - 2]; - - for (int i = 0; i < args.Length; ++i) - args[i] = oldArgs[i + 2]; - - RunCommand(e.Mobile, obj, command, args); - } - } - } - else - { - e.Mobile.SendMessage("You must supply an object serial and a command name."); - } - } - } -} +namespace Server.Commands.Generic +{ + public class SerialCommandImplementor : BaseCommandImplementor + { + public SerialCommandImplementor() + { + Accessors = new[] { "Serial" }; + SupportRequirement = CommandSupport.Single; + AccessLevel = AccessLevel.Counselor; + Usage = "Serial "; + Description = "Invokes the command on a single object by serial."; + } + + public override void Execute(CommandEventArgs e) + { + if (e.Length >= 2) + { + Serial serial = e.GetUInt32(0); + + object obj = null; + + if (serial.IsItem) + obj = World.FindItem(serial); + else if (serial.IsMobile) + obj = World.FindMobile(serial); + + if (obj == null) + { + e.Mobile.SendMessage("That is not a valid serial."); + } + else + { + Commands.TryGetValue(e.GetString(1), out var command); + + if (command == null) + { + e.Mobile.SendMessage( + "That is either an invalid command name or one that does not support this modifier." + ); + } + else if (e.Mobile.AccessLevel < command.AccessLevel) + { + e.Mobile.SendMessage("You do not have access to that command."); + } + else + { + switch (command.ObjectTypes) + { + case ObjectTypes.Items: + { + if (!(obj is Item)) + { + e.Mobile.SendMessage("This command only works on items."); + return; + } + + break; + } + case ObjectTypes.Mobiles: + { + if (!(obj is Mobile)) + { + e.Mobile.SendMessage("This command only works on mobiles."); + return; + } + + break; + } + } + + var oldArgs = e.Arguments; + var args = new string[oldArgs.Length - 2]; + + for (var i = 0; i < args.Length; ++i) + args[i] = oldArgs[i + 2]; + + RunCommand(e.Mobile, obj, command, args); + } + } + } + else + { + e.Mobile.SendMessage("You must supply an object serial and a command name."); + } + } + } +} diff --git a/Projects/UOContent/Commands/Generic/Implementors/SingleCommandImplementor.cs b/Projects/UOContent/Commands/Generic/Implementors/SingleCommandImplementor.cs index b07a573c5..e05511660 100644 --- a/Projects/UOContent/Commands/Generic/Implementors/SingleCommandImplementor.cs +++ b/Projects/UOContent/Commands/Generic/Implementors/SingleCommandImplementor.cs @@ -1,89 +1,94 @@ -using Server.Targeting; - -namespace Server.Commands.Generic -{ - public class SingleCommandImplementor : BaseCommandImplementor - { - public SingleCommandImplementor() - { - Accessors = new[] { "Single" }; - SupportRequirement = CommandSupport.Single; - AccessLevel = AccessLevel.Counselor; - Usage = "Single "; - Description = - "Invokes the command on a single targeted object. This is the same as just invoking the command directly."; - } - - public override void Register(BaseCommand command) - { - base.Register(command); - - for (int i = 0; i < command.Commands.Length; ++i) - CommandSystem.Register(command.Commands[i], command.AccessLevel, Redirect); - } - - public void Redirect(CommandEventArgs e) - { - Commands.TryGetValue(e.Command, out BaseCommand command); - - if (command == null) - e.Mobile.SendMessage("That is either an invalid command name or one that does not support this modifier."); - else if (e.Mobile.AccessLevel < command.AccessLevel) - e.Mobile.SendMessage("You do not have access to that command."); - else if (command.ValidateArgs(this, e)) - Process(e.Mobile, command, e.Arguments); - } - - public override void Process(Mobile from, BaseCommand command, string[] args) - { - if (command.ValidateArgs(this, new CommandEventArgs(from, command.Commands[0], GenerateArgString(args), args))) - from.BeginTarget(-1, command.ObjectTypes == ObjectTypes.All, TargetFlags.None, - (m, targeted, a) => OnTarget(m, targeted, command, a), args); - } - - public void OnTarget(Mobile from, object targeted, BaseCommand command, string[] args) - { - if (!BaseCommand.IsAccessible(from, targeted)) - { - from.SendLocalizedMessage(500447); // That is not accessible. - return; - } - - switch (command.ObjectTypes) - { - case ObjectTypes.Both: - { - if (!(targeted is Item) && !(targeted is Mobile)) - { - from.SendMessage("This command does not work on that."); - return; - } - - break; - } - case ObjectTypes.Items: - { - if (!(targeted is Item)) - { - from.SendMessage("This command only works on items."); - return; - } - - break; - } - case ObjectTypes.Mobiles: - { - if (!(targeted is Mobile)) - { - from.SendMessage("This command only works on mobiles."); - return; - } - - break; - } - } - - RunCommand(from, targeted, command, args); - } - } -} +using Server.Targeting; + +namespace Server.Commands.Generic +{ + public class SingleCommandImplementor : BaseCommandImplementor + { + public SingleCommandImplementor() + { + Accessors = new[] { "Single" }; + SupportRequirement = CommandSupport.Single; + AccessLevel = AccessLevel.Counselor; + Usage = "Single "; + Description = + "Invokes the command on a single targeted object. This is the same as just invoking the command directly."; + } + + public override void Register(BaseCommand command) + { + base.Register(command); + + for (var i = 0; i < command.Commands.Length; ++i) + CommandSystem.Register(command.Commands[i], command.AccessLevel, Redirect); + } + + public void Redirect(CommandEventArgs e) + { + Commands.TryGetValue(e.Command, out var command); + + if (command == null) + e.Mobile.SendMessage("That is either an invalid command name or one that does not support this modifier."); + else if (e.Mobile.AccessLevel < command.AccessLevel) + e.Mobile.SendMessage("You do not have access to that command."); + else if (command.ValidateArgs(this, e)) + Process(e.Mobile, command, e.Arguments); + } + + public override void Process(Mobile from, BaseCommand command, string[] args) + { + if (command.ValidateArgs(this, new CommandEventArgs(from, command.Commands[0], GenerateArgString(args), args))) + from.BeginTarget( + -1, + command.ObjectTypes == ObjectTypes.All, + TargetFlags.None, + (m, targeted, a) => OnTarget(m, targeted, command, a), + args + ); + } + + public void OnTarget(Mobile from, object targeted, BaseCommand command, string[] args) + { + if (!BaseCommand.IsAccessible(from, targeted)) + { + from.SendLocalizedMessage(500447); // That is not accessible. + return; + } + + switch (command.ObjectTypes) + { + case ObjectTypes.Both: + { + if (!(targeted is Item) && !(targeted is Mobile)) + { + from.SendMessage("This command does not work on that."); + return; + } + + break; + } + case ObjectTypes.Items: + { + if (!(targeted is Item)) + { + from.SendMessage("This command only works on items."); + return; + } + + break; + } + case ObjectTypes.Mobiles: + { + if (!(targeted is Mobile)) + { + from.SendMessage("This command only works on mobiles."); + return; + } + + break; + } + } + + RunCommand(from, targeted, command, args); + } + } +} diff --git a/Projects/UOContent/Commands/Handlers.cs b/Projects/UOContent/Commands/Handlers.cs index 48d3cfad1..921363c99 100644 --- a/Projects/UOContent/Commands/Handlers.cs +++ b/Projects/UOContent/Commands/Handlers.cs @@ -1,959 +1,1052 @@ -using System.Collections.Generic; -using System.Text; -using Server.Commands.Generic; -using Server.Engines.Help; -using Server.Gumps; -using Server.Items; -using Server.Menus.ItemLists; -using Server.Menus.Questions; -using Server.Misc; -using Server.Mobiles; -using Server.Multis; -using Server.Network; -using Server.Spells; -using Server.Targeting; -using Server.Targets; - -namespace Server.Commands -{ - public class CommandHandlers - { - public static void Initialize() - { - CommandSystem.Prefix = "["; - - Register("Go", AccessLevel.Counselor, Go_OnCommand); - - Register("DropHolding", AccessLevel.Counselor, DropHolding_OnCommand); - - Register("GetFollowers", AccessLevel.GameMaster, GetFollowers_OnCommand); - - Register("ClearFacet", AccessLevel.Administrator, ClearFacet_OnCommand); - - Register("Where", AccessLevel.Counselor, Where_OnCommand); - - Register("AutoPageNotify", AccessLevel.Counselor, APN_OnCommand); - Register("APN", AccessLevel.Counselor, APN_OnCommand); - - Register("Animate", AccessLevel.GameMaster, Animate_OnCommand); - - Register("Cast", AccessLevel.Counselor, Cast_OnCommand); - - Register("Stuck", AccessLevel.Counselor, Stuck_OnCommand); - - Register("Help", AccessLevel.Player, Help_OnCommand); - - Register("Save", AccessLevel.Administrator, Save_OnCommand); - Register("BackgroundSave", AccessLevel.Administrator, BackgroundSave_OnCommand); - Register("BGSave", AccessLevel.Administrator, BackgroundSave_OnCommand); - Register("SaveBG", AccessLevel.Administrator, BackgroundSave_OnCommand); - - Register("Move", AccessLevel.GameMaster, Move_OnCommand); - Register("Client", AccessLevel.Counselor, Client_OnCommand); - - Register("SMsg", AccessLevel.Counselor, StaffMessage_OnCommand); - Register("SM", AccessLevel.Counselor, StaffMessage_OnCommand); - Register("S", AccessLevel.Counselor, StaffMessage_OnCommand); - - Register("BCast", AccessLevel.GameMaster, BroadcastMessage_OnCommand); - Register("BC", AccessLevel.GameMaster, BroadcastMessage_OnCommand); - Register("B", AccessLevel.GameMaster, BroadcastMessage_OnCommand); - - Register("Bank", AccessLevel.GameMaster, Bank_OnCommand); - - Register("Echo", AccessLevel.Counselor, Echo_OnCommand); - - Register("Sound", AccessLevel.GameMaster, Sound_OnCommand); - - Register("ViewEquip", AccessLevel.GameMaster, ViewEquip_OnCommand); - - Register("Light", AccessLevel.Counselor, Light_OnCommand); - Register("Stats", AccessLevel.Counselor, Stats_OnCommand); - - Register("SpeedBoost", AccessLevel.Counselor, SpeedBoost_OnCommand); - } - - public static void Register(string command, AccessLevel access, CommandEventHandler handler) - { - CommandSystem.Register(command, access, handler); - } - - [Usage("SpeedBoost [true|false]")] - [Description("Enables a speed boost for the invoker. Disable with parameters.")] - private static void SpeedBoost_OnCommand(CommandEventArgs e) - { - Mobile from = e.Mobile; - - if (e.Length <= 1) - { - if (e.Length == 1 && !e.GetBoolean(0)) - { - from.Send(SpeedControl.Disable); - from.SendMessage("Speed boost has been disabled."); - } - else - { - from.Send(SpeedControl.MountSpeed); - from.SendMessage("Speed boost has been enabled."); - } - } - else - { - from.SendMessage("Format: SpeedBoost [true|false]"); - } - } - - [Usage("Where")] - [Description("Tells the commanding player his coordinates, region, and facet.")] - public static void Where_OnCommand(CommandEventArgs e) - { - Mobile from = e.Mobile; - Map map = from.Map; - - from.SendMessage("You are at {0} {1} {2} in {3}.", from.X, from.Y, from.Z, map); - - if (map != null) - { - Region reg = from.Region; - - if (!reg.IsDefault) - { - StringBuilder builder = new StringBuilder(); - - builder.Append(reg); - reg = reg.Parent; - - while (reg != null) - { - builder.Append($" <- {reg}"); - reg = reg.Parent; - } - - from.SendMessage("Your region is {0}.", builder.ToString()); - } - } - } - - [Usage("DropHolding")] - [Description( - "Drops the item, if any, that a targeted player is holding. The item is placed into their backpack, or if that's full, at their feet.")] - public static void DropHolding_OnCommand(CommandEventArgs e) - { - e.Mobile.BeginTarget(-1, false, TargetFlags.None, DropHolding_OnTarget); - e.Mobile.SendMessage("Target the player to drop what they are holding."); - } - - public static void DropHolding_OnTarget(Mobile from, object obj) - { - if (obj is Mobile targ && targ.Player) - { - Item held = targ.Holding; - - if (held == null) - { - from.SendMessage("They are not holding anything."); - } - else - { - if (from.AccessLevel == AccessLevel.Counselor) - { - PageEntry pe = PageQueue.GetEntry(targ); - - if (pe?.Handler == from) - from.SendMessage("You may only use this command if you are handling their help page."); - else - from.SendMessage("You may only use this command on someone who has paged you."); - - return; - } - - if (targ.AddToBackpack(held)) - from.SendMessage("The item they were holding has been placed into their backpack."); - else - from.SendMessage("The item they were holding has been placed at their feet."); - - held.ClearBounce(); - - targ.Holding = null; - } - } - else - { - from.BeginTarget(-1, false, TargetFlags.None, DropHolding_OnTarget); - from.SendMessage("That is not a player. Try again."); - } - } - - public static void DeleteList_Callback(Mobile from, bool okay, List list) - { - if (okay) - { - CommandLogging.WriteLine(from, "{0} {1} deleting {2} object{3}", from.AccessLevel, - CommandLogging.Format(from), list.Count, list.Count == 1 ? "" : "s"); - - NetState.Pause(); - - for (int i = 0; i < list.Count; ++i) - list[i].Delete(); - - NetState.Resume(); - - from.SendMessage("You have deleted {0} object{1}.", list.Count, list.Count == 1 ? "" : "s"); - } - else - { - from.SendMessage("You have chosen not to delete those objects."); - } - } - - [Usage("ClearFacet")] - [Description("Deletes all items and mobiles in your facet. Players and their inventory will not be deleted.")] - public static void ClearFacet_OnCommand(CommandEventArgs e) - { - Mobile from = e.Mobile; - Map map = from.Map; - - if (map == null || map == Map.Internal) - { - from.SendMessage("You may not run that command here."); - return; - } - - List list = new List(); - - foreach (Item item in World.Items.Values) - if (item.Map == map && item.Parent == null) - list.Add(item); - - foreach (Mobile m in World.Mobiles.Values) - if (m.Map == map && !m.Player) - list.Add(m); - - if (list.Count > 0) - { - CommandLogging.WriteLine(from, "{0} {1} starting facet clear of {2} ({3} object{4})", - from.AccessLevel, CommandLogging.Format(from), map, list.Count, list.Count == 1 ? "" : "s"); - - from.SendGump( - new WarningGump(1060635, 30720, - $"You are about to delete {list.Count} object{(list.Count == 1 ? "" : "s")} from this facet. Do you really wish to continue?", - 0xFFC000, 360, 260, okay => DeleteList_Callback(from, okay, list))); - } - else - { - from.SendMessage("There were no objects found to delete."); - } - } - - [Usage("GetFollowers")] - [Description("Teleports all pets of a targeted player to your location.")] - public static void GetFollowers_OnCommand(CommandEventArgs e) - { - e.Mobile.BeginTarget(-1, false, TargetFlags.None, GetFollowers_OnTarget); - e.Mobile.SendMessage("Target a player to get their pets."); - } - - public static void GetFollowers_OnTarget(Mobile from, object obj) - { - if (obj is PlayerMobile pm) - { - List pets = pm.AllFollowers; - - if (pets.Count > 0) - { - CommandLogging.WriteLine(from, "{0} {1} getting all followers of {2}", from.AccessLevel, - CommandLogging.Format(from), CommandLogging.Format(pm)); - - from.SendMessage("That player has {0} pet{1}.", pets.Count, pets.Count != 1 ? "s" : ""); - - for (int i = 0; i < pets.Count; ++i) - { - Mobile pet = pets[i]; - - if (pet is IMount mount) - mount.Rider = null; // make sure it's dismounted - - pet.MoveToWorld(from.Location, from.Map); - } - } - else - { - from.SendMessage("There were no pets found for that player."); - } - } - else if (obj is Mobile master && master.Player) - { - List pets = new List(); - - foreach (Mobile m in World.Mobiles.Values) - if (m is BaseCreature bc) - if ((bc.Controlled && bc.ControlMaster == master) || (bc.Summoned && bc.SummonMaster == master)) - pets.Add(bc); - - if (pets.Count > 0) - { - CommandLogging.WriteLine(from, "{0} {1} getting all followers of {2}", from.AccessLevel, - CommandLogging.Format(from), CommandLogging.Format(master)); - - from.SendMessage("That player has {0} pet{1}.", pets.Count, pets.Count != 1 ? "s" : ""); - - for (int i = 0; i < pets.Count; ++i) - { - Mobile pet = pets[i]; - - if (pet is IMount mount) - mount.Rider = null; // make sure it's dismounted - - pet.MoveToWorld(from.Location, from.Map); - } - } - else - { - from.SendMessage("There were no pets found for that player."); - } - } - else - { - from.BeginTarget(-1, false, TargetFlags.None, GetFollowers_OnTarget); - from.SendMessage("That is not a player. Try again."); - } - } - - [Usage("ViewEquip")] - [Description("Lists equipment of a targeted mobile. From the list you can move, delete, or open props.")] - public static void ViewEquip_OnCommand(CommandEventArgs e) - { - e.Mobile.Target = new ViewEqTarget(); - } - - [Usage("Sound [toAll=true]")] - [Description( - "Plays a sound to players within 12 tiles of you. The (toAll) argument specifies to everyone, or just those who can see you.")] - public static void Sound_OnCommand(CommandEventArgs e) - { - if (e.Length == 1) - PlaySound(e.Mobile, e.GetInt32(0), true); - else if (e.Length == 2) - PlaySound(e.Mobile, e.GetInt32(0), e.GetBoolean(1)); - else - e.Mobile.SendMessage("Format: Sound [toAll]"); - } - - private static void PlaySound(Mobile m, int index, bool toAll) - { - Map map = m.Map; - - if (map == null) - return; - - CommandLogging.WriteLine(m, "{0} {1} playing sound {2} (toAll={3})", m.AccessLevel, CommandLogging.Format(m), - index, toAll); - - Packet p = new PlaySound(index, m.Location); - - p.Acquire(); - - foreach (NetState state in m.GetClientsInRange(12)) - if (toAll || state.Mobile.CanSee(m)) - state.Send(p); - - p.Release(); - } - - [Usage("Echo ")] - [Description("Relays (text) as a system message.")] - public static void Echo_OnCommand(CommandEventArgs e) - { - string toEcho = e.ArgString.Trim(); - - if (toEcho.Length > 0) - e.Mobile.SendMessage(toEcho); - else - e.Mobile.SendMessage("Format: Echo \"\""); - } - - [Usage("Bank")] - [Description("Opens the bank box of a given target.")] - public static void Bank_OnCommand(CommandEventArgs e) - { - e.Mobile.Target = new BankTarget(); - } - - [Usage("Client")] - [Description("Opens the client gump menu for a given player.")] - private static void Client_OnCommand(CommandEventArgs e) - { - e.Mobile.Target = new ClientTarget(); - } - - [Usage("Move")] - [Description("Repositions a targeted item or mobile.")] - private static void Move_OnCommand(CommandEventArgs e) - { - e.Mobile.Target = new PickMoveTarget(); - } - - [Usage("Save")] - [Description("Saves the world.")] - private static void Save_OnCommand(CommandEventArgs e) - { - AutoSave.Save(); - } - - [Usage("BackgroundSave")] - [Aliases("BGSave", "SaveBG")] - [Description("Saves the world, writing to the disk in the background")] - private static void BackgroundSave_OnCommand(CommandEventArgs e) - { - AutoSave.Save(true); - } - - private static bool FixMap(ref Map map, ref Point3D loc, Item item) => (map != null && map != Map.Internal) || (item.RootParent is Mobile m && FixMap(ref map, ref loc, m)); - - private static bool FixMap(ref Map map, ref Point3D loc, Mobile m) - { - bool validMap = map != null && map != Map.Internal; - - if (!validMap) - { - map = m.LogoutMap; - loc = m.LogoutLocation; - } - - return validMap; - } - - [Usage("Go [name | serial | (x y [z]) | (deg min (N | S) deg min (E | W))]")] - [Description( - "With no arguments, this command brings up the go menu. With one argument, (name), you are moved to that regions \"go location.\" Or, if a numerical value is specified for one argument, (serial), you are moved to that object. Two or three arguments, (x y [z]), will move your character to that location. When six arguments are specified, (deg min (N | S) deg min (E | W)), your character will go to an approximate of those sextant coordinates.")] - private static void Go_OnCommand(CommandEventArgs e) - { - Mobile from = e.Mobile; - - if (e.Length == 0) - { - GoGump.DisplayTo(from); - return; - } - - if (e.Length == 1) - { - try - { - uint ser = e.GetUInt32(0); - - IEntity ent = World.FindEntity(ser); - - if (ent is Item item) - { - Map map = item.Map; - Point3D loc = item.GetWorldLocation(); - - Mobile owner = item.RootParent as Mobile; - - if (owner?.Map != null && owner.Map != Map.Internal && - !BaseCommand.IsAccessible(from, owner) /* !from.CanSee( owner )*/) - { - from.SendMessage("You can not go to what you can not see."); - return; - } - - if (owner != null && (owner.Map == null || owner.Map == Map.Internal) && owner.Hidden && - owner.AccessLevel >= from.AccessLevel) - { - from.SendMessage("You can not go to what you can not see."); - return; - } - - if (!FixMap(ref map, ref loc, item)) - { - from.SendMessage("That is an internal item and you cannot go to it."); - return; - } - - from.MoveToWorld(loc, map); - - return; - } - - if (ent is Mobile m) - { - Map map = m.Map; - Point3D loc = m.Location; - - Mobile owner = m; - - if (owner.Map != null && owner.Map != Map.Internal && - !BaseCommand.IsAccessible(from, owner) /* !from.CanSee( owner )*/) - { - from.SendMessage("You can not go to what you can not see."); - return; - } - - if ((owner.Map == null || owner.Map == Map.Internal) && owner.Hidden && - owner.AccessLevel >= from.AccessLevel) - { - from.SendMessage("You can not go to what you can not see."); - return; - } - - if (!FixMap(ref map, ref loc, m)) - { - from.SendMessage("That is an internal mobile and you cannot go to it."); - return; - } - - from.MoveToWorld(loc, map); - - return; - } - else - { - string name = e.GetString(0); - Map map; - - for (int i = 0; i < Map.AllMaps.Count; ++i) - { - map = Map.AllMaps[i]; - - if (map.MapIndex == 0x7F || map.MapIndex == 0xFF) - continue; - - if (Insensitive.Equals(name, map.Name)) - { - from.Map = map; - return; - } - } - - Dictionary list = from.Map.Regions; - - foreach (KeyValuePair kvp in list) - { - Region r = kvp.Value; - - if (Insensitive.Equals(r.Name, name)) - { - from.Location = new Point3D(r.GoLocation); - return; - } - } - - for (int i = 0; i < Map.AllMaps.Count; ++i) - { - map = Map.AllMaps[i]; - - if (map.MapIndex == 0x7F || map.MapIndex == 0xFF || from.Map == map) - continue; - - foreach (Region r in map.Regions.Values) - if (Insensitive.Equals(r.Name, name)) - { - from.MoveToWorld(r.GoLocation, map); - return; - } - } - - if (ser != 0) - from.SendMessage("No object with that serial was found."); - else - from.SendMessage("No region with that name was found."); - - return; - } - } - catch - { - // ignored - } - - from.SendMessage("Region name not found"); - } - else if (e.Length == 2 || e.Length == 3) - { - Map map = from.Map; - - if (map != null) - try - { - /* - * This to avoid being teleported to (0,0) if trying to teleport - * to a region with spaces in its name. - */ - int x = int.Parse(e.GetString(0)); - int y = int.Parse(e.GetString(1)); - int z = e.Length == 3 ? int.Parse(e.GetString(2)) : map.GetAverageZ(x, y); - - from.Location = new Point3D(x, y, z); - } - catch - { - from.SendMessage("Region name not found."); - } - } - else if (e.Length == 6) - { - Map map = from.Map; - - if (map != null) - { - Point3D p = Sextant.ReverseLookup(map, e.GetInt32(3), e.GetInt32(0), e.GetInt32(4), e.GetInt32(1), - Insensitive.Equals(e.GetString(5), "E"), Insensitive.Equals(e.GetString(2), "S")); - - if (p != Point3D.Zero) - from.Location = p; - else - from.SendMessage("Sextant reverse lookup failed."); - } - } - else - { - from.SendMessage("Format: Go [name | serial | (x y [z]) | (deg min (N | S) deg min (E | W)]"); - } - } - - [Usage("Help")] - [Description("Lists all available commands.")] - public static void Help_OnCommand(CommandEventArgs e) - { - Mobile m = e.Mobile; - - List list = new List(); - - foreach (CommandEntry entry in CommandSystem.Entries.Values) - if (m.AccessLevel >= entry.AccessLevel) - list.Add(entry); - - list.Sort(); - - StringBuilder sb = new StringBuilder(); - - if (list.Count > 0) - sb.Append(list[0].Command); - - for (int i = 1; i < list.Count; ++i) - { - string v = list[i].Command; - - if (sb.Length + 1 + v.Length >= 256) - { - m.SendAsciiMessage(0x482, sb.ToString()); - sb = new StringBuilder(); - sb.Append(v); - } - else - { - sb.Append(' '); - sb.Append(v); - } - } - - if (sb.Length > 0) - m.SendAsciiMessage(0x482, sb.ToString()); - } - - [Usage("SMsg ")] - [Aliases("S", "SM")] - [Description("Broadcasts a message to all online staff.")] - public static void StaffMessage_OnCommand(CommandEventArgs e) - { - BroadcastMessage(AccessLevel.Counselor, e.Mobile.SpeechHue, $"[{e.Mobile.Name}] {e.ArgString}"); - } - - [Usage("BCast ")] - [Aliases("B", "BC")] - [Description("Broadcasts a message to everyone online.")] - public static void BroadcastMessage_OnCommand(CommandEventArgs e) - { - BroadcastMessage(AccessLevel.Player, 0x482, $"Staff message from {e.Mobile.Name}:"); - BroadcastMessage(AccessLevel.Player, 0x482, e.ArgString); - } - - public static void BroadcastMessage(AccessLevel ac, int hue, string message) - { - foreach (NetState state in TcpServer.Instances) - { - Mobile m = state.Mobile; - - if (m?.AccessLevel >= ac) - m.SendMessage(hue, message); - } - } - - [Usage("AutoPageNotify")] - [Aliases("APN")] - [Description("Toggles your auto-page-notify status.")] - public static void APN_OnCommand(CommandEventArgs e) - { - Mobile m = e.Mobile; - - m.AutoPageNotify = !m.AutoPageNotify; - - m.SendMessage("Your auto-page-notify has been turned {0}.", m.AutoPageNotify ? "on" : "off"); - } - - [Usage("Animate ")] - [Description("Makes your character do a specified animation.")] - public static void Animate_OnCommand(CommandEventArgs e) - { - if (e.Length == 6) - e.Mobile.Animate(e.GetInt32(0), e.GetInt32(1), e.GetInt32(2), e.GetBoolean(3), e.GetBoolean(4), - e.GetInt32(5)); - else - e.Mobile.SendMessage("Format: Animate "); - } - - [Usage("Cast ")] - [Description("Casts a spell by name.")] - public static void Cast_OnCommand(CommandEventArgs e) - { - if (e.Length == 1) - { - if (!DesignContext.Check(e.Mobile)) - return; // They are customizing - - Spell spell = SpellRegistry.NewSpell(e.GetString(0), e.Mobile, null); - - if (spell != null) - spell.Cast(); - else - e.Mobile.SendMessage("That spell was not found."); - } - else - { - e.Mobile.SendMessage("Format: Cast "); - } - } - - [Usage("Stuck")] - [Description("Opens a menu of towns, used for teleporting stuck mobiles.")] - public static void Stuck_OnCommand(CommandEventArgs e) - { - e.Mobile.Target = new StuckMenuTarget(); - } - - [Usage("Light ")] - [Description("Set your local lightlevel.")] - public static void Light_OnCommand(CommandEventArgs e) - { - e.Mobile.LightLevel = e.GetInt32(0); - } - - [Usage("Stats")] - [Description("View some stats about the server.")] - public static void Stats_OnCommand(CommandEventArgs e) - { - e.Mobile.SendMessage("Open Connections: {0}", TcpServer.Instances.Count); - e.Mobile.SendMessage("Mobiles: {0}", World.Mobiles.Count); - e.Mobile.SendMessage("Items: {0}", World.Items.Count); - } - - private class ViewEqTarget : Target - { - public ViewEqTarget() : base(-1, false, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (!BaseCommand.IsAccessible(from, targeted)) - { - from.SendLocalizedMessage(500447); // That is not accessible. - return; - } - - if (targeted is Mobile mobile) - from.SendMenu(new EquipMenu(from, mobile, GetEquip(mobile))); - } - - private static ItemListEntry[] GetEquip(Mobile m) - { - ItemListEntry[] entries = new ItemListEntry[m.Items.Count]; - - for (int i = 0; i < m.Items.Count; ++i) - { - Item item = m.Items[i]; - - entries[i] = new ItemListEntry($"{item.Layer}: {item.GetType().Name}", item.ItemID, item.Hue); - } - - return entries; - } - - private class EquipMenu : ItemListMenu - { - private readonly Mobile m_Mobile; - - public EquipMenu(Mobile from, Mobile m, ItemListEntry[] entries) : base("Equipment", entries) - { - m_Mobile = m; - - CommandLogging.WriteLine(from, "{0} {1} viewing equipment of {2}", from.AccessLevel, - CommandLogging.Format(from), CommandLogging.Format(m)); - } - - public override void OnResponse(NetState state, int index) - { - if (index >= 0 && index < m_Mobile.Items.Count) - { - Item item = m_Mobile.Items[index]; - - state.Mobile.SendMenu(new EquipDetailsMenu(m_Mobile, item)); - } - } - - private class EquipDetailsMenu : QuestionMenu - { - private readonly Item m_Item; - private readonly Mobile m_Mobile; - - public EquipDetailsMenu(Mobile m, Item item) : base($"{item.Layer}: {item.GetType().Name}", - new[] { "Move", "Delete", "Props" }) - { - m_Mobile = m; - m_Item = item; - } - - public override void OnCancel(NetState state) - { - state.Mobile.SendMenu(new EquipMenu(state.Mobile, m_Mobile, GetEquip(m_Mobile))); - } - - public override void OnResponse(NetState state, int index) - { - if (index == 0) - { - CommandLogging.WriteLine(state.Mobile, "{0} {1} moving equipment item {2} of {3}", - state.Mobile.AccessLevel, CommandLogging.Format(state.Mobile), CommandLogging.Format(m_Item), - CommandLogging.Format(m_Mobile)); - state.Mobile.Target = new MoveTarget(m_Item); - } - else if (index == 1) - { - CommandLogging.WriteLine(state.Mobile, "{0} {1} deleting equipment item {2} of {3}", - state.Mobile.AccessLevel, CommandLogging.Format(state.Mobile), CommandLogging.Format(m_Item), - CommandLogging.Format(m_Mobile)); - m_Item.Delete(); - } - else if (index == 2) - { - CommandLogging.WriteLine(state.Mobile, - "{0} {1} opening properties for equipment item {2} of {3}", state.Mobile.AccessLevel, - CommandLogging.Format(state.Mobile), CommandLogging.Format(m_Item), - CommandLogging.Format(m_Mobile)); - state.Mobile.SendGump(new PropertiesGump(state.Mobile, m_Item)); - } - } - } - } - } - - private class BankTarget : Target - { - public BankTarget() : base(-1, false, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is Mobile m) - { - BankBox box = m.Player ? m.BankBox : m.FindBankNoCreate(); - - if (box != null) - { - CommandLogging.WriteLine(from, "{0} {1} opening bank box of {2}", from.AccessLevel, - CommandLogging.Format(from), CommandLogging.Format(m)); - - if (from == m) - box.Open(); - else - box.DisplayTo(from); - } - else - { - from.SendMessage("They have no bank box."); - } - } - } - } - - private class DismountTarget : Target - { - public DismountTarget() : base(-1, false, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is Mobile targ) - { - CommandLogging.WriteLine(from, "{0} {1} dismounting {2}", from.AccessLevel, CommandLogging.Format(from), - CommandLogging.Format(targ)); - - for (int i = 0; i < targ.Items.Count; ++i) - { - Item item = targ.Items[i]; - - if (item is IMountItem mountItem) - { - IMount mount = mountItem.Mount; - - if (mount != null) - mount.Rider = null; - - if (targ.Items.IndexOf(item) == -1) - --i; - } - } - - for (int i = 0; i < targ.Items.Count; ++i) - { - Item item = targ.Items[i]; - - if (item.Layer == Layer.Mount) - { - item.Delete(); - --i; - } - } - } - } - } - - private class ClientTarget : Target - { - public ClientTarget() : base(-1, false, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is Mobile targ && targ.NetState != null) - { - CommandLogging.WriteLine(from, "{0} {1} opening client menu of {2}", from.AccessLevel, - CommandLogging.Format(from), CommandLogging.Format(targ)); - from.SendGump(new ClientGump(from, targ.NetState)); - } - } - } - - private class StuckMenuTarget : Target - { - public StuckMenuTarget() : base(-1, false, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is Mobile mobile) - { - if (mobile.AccessLevel >= from.AccessLevel && mobile != from) - from.SendMessage("You can't do that to someone with higher Accesslevel than you!"); - else - from.SendGump(new StuckMenu(from, mobile, false)); - } - } - } - } -} +using System.Collections.Generic; +using System.Text; +using Server.Commands.Generic; +using Server.Engines.Help; +using Server.Gumps; +using Server.Items; +using Server.Menus.ItemLists; +using Server.Menus.Questions; +using Server.Misc; +using Server.Mobiles; +using Server.Multis; +using Server.Network; +using Server.Spells; +using Server.Targeting; +using Server.Targets; + +namespace Server.Commands +{ + public class CommandHandlers + { + public static void Initialize() + { + CommandSystem.Prefix = "["; + + Register("Go", AccessLevel.Counselor, Go_OnCommand); + + Register("DropHolding", AccessLevel.Counselor, DropHolding_OnCommand); + + Register("GetFollowers", AccessLevel.GameMaster, GetFollowers_OnCommand); + + Register("ClearFacet", AccessLevel.Administrator, ClearFacet_OnCommand); + + Register("Where", AccessLevel.Counselor, Where_OnCommand); + + Register("AutoPageNotify", AccessLevel.Counselor, APN_OnCommand); + Register("APN", AccessLevel.Counselor, APN_OnCommand); + + Register("Animate", AccessLevel.GameMaster, Animate_OnCommand); + + Register("Cast", AccessLevel.Counselor, Cast_OnCommand); + + Register("Stuck", AccessLevel.Counselor, Stuck_OnCommand); + + Register("Help", AccessLevel.Player, Help_OnCommand); + + Register("Save", AccessLevel.Administrator, Save_OnCommand); + Register("BackgroundSave", AccessLevel.Administrator, BackgroundSave_OnCommand); + Register("BGSave", AccessLevel.Administrator, BackgroundSave_OnCommand); + Register("SaveBG", AccessLevel.Administrator, BackgroundSave_OnCommand); + + Register("Move", AccessLevel.GameMaster, Move_OnCommand); + Register("Client", AccessLevel.Counselor, Client_OnCommand); + + Register("SMsg", AccessLevel.Counselor, StaffMessage_OnCommand); + Register("SM", AccessLevel.Counselor, StaffMessage_OnCommand); + Register("S", AccessLevel.Counselor, StaffMessage_OnCommand); + + Register("BCast", AccessLevel.GameMaster, BroadcastMessage_OnCommand); + Register("BC", AccessLevel.GameMaster, BroadcastMessage_OnCommand); + Register("B", AccessLevel.GameMaster, BroadcastMessage_OnCommand); + + Register("Bank", AccessLevel.GameMaster, Bank_OnCommand); + + Register("Echo", AccessLevel.Counselor, Echo_OnCommand); + + Register("Sound", AccessLevel.GameMaster, Sound_OnCommand); + + Register("ViewEquip", AccessLevel.GameMaster, ViewEquip_OnCommand); + + Register("Light", AccessLevel.Counselor, Light_OnCommand); + Register("Stats", AccessLevel.Counselor, Stats_OnCommand); + + Register("SpeedBoost", AccessLevel.Counselor, SpeedBoost_OnCommand); + } + + public static void Register(string command, AccessLevel access, CommandEventHandler handler) + { + CommandSystem.Register(command, access, handler); + } + + [Usage("SpeedBoost [true|false]")] + [Description("Enables a speed boost for the invoker. Disable with parameters.")] + private static void SpeedBoost_OnCommand(CommandEventArgs e) + { + var from = e.Mobile; + + if (e.Length <= 1) + { + if (e.Length == 1 && !e.GetBoolean(0)) + { + from.Send(SpeedControl.Disable); + from.SendMessage("Speed boost has been disabled."); + } + else + { + from.Send(SpeedControl.MountSpeed); + from.SendMessage("Speed boost has been enabled."); + } + } + else + { + from.SendMessage("Format: SpeedBoost [true|false]"); + } + } + + [Usage("Where")] + [Description("Tells the commanding player his coordinates, region, and facet.")] + public static void Where_OnCommand(CommandEventArgs e) + { + var from = e.Mobile; + var map = from.Map; + + from.SendMessage("You are at {0} {1} {2} in {3}.", from.X, from.Y, from.Z, map); + + if (map != null) + { + var reg = from.Region; + + if (!reg.IsDefault) + { + var builder = new StringBuilder(); + + builder.Append(reg); + reg = reg.Parent; + + while (reg != null) + { + builder.Append($" <- {reg}"); + reg = reg.Parent; + } + + from.SendMessage("Your region is {0}.", builder.ToString()); + } + } + } + + [Usage("DropHolding")] + [Description( + "Drops the item, if any, that a targeted player is holding. The item is placed into their backpack, or if that's full, at their feet." + )] + public static void DropHolding_OnCommand(CommandEventArgs e) + { + e.Mobile.BeginTarget(-1, false, TargetFlags.None, DropHolding_OnTarget); + e.Mobile.SendMessage("Target the player to drop what they are holding."); + } + + public static void DropHolding_OnTarget(Mobile from, object obj) + { + if (obj is Mobile targ && targ.Player) + { + var held = targ.Holding; + + if (held == null) + { + from.SendMessage("They are not holding anything."); + } + else + { + if (from.AccessLevel == AccessLevel.Counselor) + { + var pe = PageQueue.GetEntry(targ); + + if (pe?.Handler == from) + from.SendMessage("You may only use this command if you are handling their help page."); + else + from.SendMessage("You may only use this command on someone who has paged you."); + + return; + } + + if (targ.AddToBackpack(held)) + from.SendMessage("The item they were holding has been placed into their backpack."); + else + from.SendMessage("The item they were holding has been placed at their feet."); + + held.ClearBounce(); + + targ.Holding = null; + } + } + else + { + from.BeginTarget(-1, false, TargetFlags.None, DropHolding_OnTarget); + from.SendMessage("That is not a player. Try again."); + } + } + + public static void DeleteList_Callback(Mobile from, bool okay, List list) + { + if (okay) + { + CommandLogging.WriteLine( + from, + "{0} {1} deleting {2} object{3}", + from.AccessLevel, + CommandLogging.Format(from), + list.Count, + list.Count == 1 ? "" : "s" + ); + + NetState.Pause(); + + for (var i = 0; i < list.Count; ++i) + list[i].Delete(); + + NetState.Resume(); + + from.SendMessage("You have deleted {0} object{1}.", list.Count, list.Count == 1 ? "" : "s"); + } + else + { + from.SendMessage("You have chosen not to delete those objects."); + } + } + + [Usage("ClearFacet")] + [Description("Deletes all items and mobiles in your facet. Players and their inventory will not be deleted.")] + public static void ClearFacet_OnCommand(CommandEventArgs e) + { + var from = e.Mobile; + var map = from.Map; + + if (map == null || map == Map.Internal) + { + from.SendMessage("You may not run that command here."); + return; + } + + var list = new List(); + + foreach (var item in World.Items.Values) + if (item.Map == map && item.Parent == null) + list.Add(item); + + foreach (var m in World.Mobiles.Values) + if (m.Map == map && !m.Player) + list.Add(m); + + if (list.Count > 0) + { + CommandLogging.WriteLine( + from, + "{0} {1} starting facet clear of {2} ({3} object{4})", + from.AccessLevel, + CommandLogging.Format(from), + map, + list.Count, + list.Count == 1 ? "" : "s" + ); + + from.SendGump( + new WarningGump( + 1060635, + 30720, + $"You are about to delete {list.Count} object{(list.Count == 1 ? "" : "s")} from this facet. Do you really wish to continue?", + 0xFFC000, + 360, + 260, + okay => DeleteList_Callback(from, okay, list) + ) + ); + } + else + { + from.SendMessage("There were no objects found to delete."); + } + } + + [Usage("GetFollowers")] + [Description("Teleports all pets of a targeted player to your location.")] + public static void GetFollowers_OnCommand(CommandEventArgs e) + { + e.Mobile.BeginTarget(-1, false, TargetFlags.None, GetFollowers_OnTarget); + e.Mobile.SendMessage("Target a player to get their pets."); + } + + public static void GetFollowers_OnTarget(Mobile from, object obj) + { + if (obj is PlayerMobile pm) + { + var pets = pm.AllFollowers; + + if (pets.Count > 0) + { + CommandLogging.WriteLine( + from, + "{0} {1} getting all followers of {2}", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(pm) + ); + + from.SendMessage("That player has {0} pet{1}.", pets.Count, pets.Count != 1 ? "s" : ""); + + for (var i = 0; i < pets.Count; ++i) + { + var pet = pets[i]; + + if (pet is IMount mount) + mount.Rider = null; // make sure it's dismounted + + pet.MoveToWorld(from.Location, from.Map); + } + } + else + { + from.SendMessage("There were no pets found for that player."); + } + } + else if (obj is Mobile master && master.Player) + { + var pets = new List(); + + foreach (var m in World.Mobiles.Values) + if (m is BaseCreature bc) + if (bc.Controlled && bc.ControlMaster == master || bc.Summoned && bc.SummonMaster == master) + pets.Add(bc); + + if (pets.Count > 0) + { + CommandLogging.WriteLine( + from, + "{0} {1} getting all followers of {2}", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(master) + ); + + from.SendMessage("That player has {0} pet{1}.", pets.Count, pets.Count != 1 ? "s" : ""); + + for (var i = 0; i < pets.Count; ++i) + { + Mobile pet = pets[i]; + + if (pet is IMount mount) + mount.Rider = null; // make sure it's dismounted + + pet.MoveToWorld(from.Location, from.Map); + } + } + else + { + from.SendMessage("There were no pets found for that player."); + } + } + else + { + from.BeginTarget(-1, false, TargetFlags.None, GetFollowers_OnTarget); + from.SendMessage("That is not a player. Try again."); + } + } + + [Usage("ViewEquip")] + [Description("Lists equipment of a targeted mobile. From the list you can move, delete, or open props.")] + public static void ViewEquip_OnCommand(CommandEventArgs e) + { + e.Mobile.Target = new ViewEqTarget(); + } + + [Usage("Sound [toAll=true]")] + [Description( + "Plays a sound to players within 12 tiles of you. The (toAll) argument specifies to everyone, or just those who can see you." + )] + public static void Sound_OnCommand(CommandEventArgs e) + { + if (e.Length == 1) + PlaySound(e.Mobile, e.GetInt32(0), true); + else if (e.Length == 2) + PlaySound(e.Mobile, e.GetInt32(0), e.GetBoolean(1)); + else + e.Mobile.SendMessage("Format: Sound [toAll]"); + } + + private static void PlaySound(Mobile m, int index, bool toAll) + { + var map = m.Map; + + if (map == null) + return; + + CommandLogging.WriteLine( + m, + "{0} {1} playing sound {2} (toAll={3})", + m.AccessLevel, + CommandLogging.Format(m), + index, + toAll + ); + + Packet p = new PlaySound(index, m.Location); + + p.Acquire(); + + foreach (var state in m.GetClientsInRange(12)) + if (toAll || state.Mobile.CanSee(m)) + state.Send(p); + + p.Release(); + } + + [Usage("Echo ")] + [Description("Relays (text) as a system message.")] + public static void Echo_OnCommand(CommandEventArgs e) + { + var toEcho = e.ArgString.Trim(); + + if (toEcho.Length > 0) + e.Mobile.SendMessage(toEcho); + else + e.Mobile.SendMessage("Format: Echo \"\""); + } + + [Usage("Bank")] + [Description("Opens the bank box of a given target.")] + public static void Bank_OnCommand(CommandEventArgs e) + { + e.Mobile.Target = new BankTarget(); + } + + [Usage("Client")] + [Description("Opens the client gump menu for a given player.")] + private static void Client_OnCommand(CommandEventArgs e) + { + e.Mobile.Target = new ClientTarget(); + } + + [Usage("Move")] + [Description("Repositions a targeted item or mobile.")] + private static void Move_OnCommand(CommandEventArgs e) + { + e.Mobile.Target = new PickMoveTarget(); + } + + [Usage("Save")] + [Description("Saves the world.")] + private static void Save_OnCommand(CommandEventArgs e) + { + AutoSave.Save(); + } + + [Usage("BackgroundSave")] + [Aliases("BGSave", "SaveBG")] + [Description("Saves the world, writing to the disk in the background")] + private static void BackgroundSave_OnCommand(CommandEventArgs e) + { + AutoSave.Save(true); + } + + private static bool FixMap(ref Map map, ref Point3D loc, Item item) => map != null && map != Map.Internal || + item.RootParent is Mobile m && FixMap( + ref map, + ref loc, + m + ); + + private static bool FixMap(ref Map map, ref Point3D loc, Mobile m) + { + var validMap = map != null && map != Map.Internal; + + if (!validMap) + { + map = m.LogoutMap; + loc = m.LogoutLocation; + } + + return validMap; + } + + [Usage("Go [name | serial | (x y [z]) | (deg min (N | S) deg min (E | W))]")] + [Description( + "With no arguments, this command brings up the go menu. With one argument, (name), you are moved to that regions \"go location.\" Or, if a numerical value is specified for one argument, (serial), you are moved to that object. Two or three arguments, (x y [z]), will move your character to that location. When six arguments are specified, (deg min (N | S) deg min (E | W)), your character will go to an approximate of those sextant coordinates." + )] + private static void Go_OnCommand(CommandEventArgs e) + { + var from = e.Mobile; + + if (e.Length == 0) + { + GoGump.DisplayTo(from); + return; + } + + if (e.Length == 1) + { + try + { + var ser = e.GetUInt32(0); + + var ent = World.FindEntity(ser); + + if (ent is Item item) + { + var map = item.Map; + var loc = item.GetWorldLocation(); + + var owner = item.RootParent as Mobile; + + if (owner?.Map != null && owner.Map != Map.Internal && + !BaseCommand.IsAccessible(from, owner) /* !from.CanSee( owner )*/) + { + from.SendMessage("You can not go to what you can not see."); + return; + } + + if (owner != null && (owner.Map == null || owner.Map == Map.Internal) && owner.Hidden && + owner.AccessLevel >= from.AccessLevel) + { + from.SendMessage("You can not go to what you can not see."); + return; + } + + if (!FixMap(ref map, ref loc, item)) + { + from.SendMessage("That is an internal item and you cannot go to it."); + return; + } + + from.MoveToWorld(loc, map); + + return; + } + + if (ent is Mobile m) + { + var map = m.Map; + var loc = m.Location; + + var owner = m; + + if (owner.Map != null && owner.Map != Map.Internal && + !BaseCommand.IsAccessible(from, owner) /* !from.CanSee( owner )*/) + { + from.SendMessage("You can not go to what you can not see."); + return; + } + + if ((owner.Map == null || owner.Map == Map.Internal) && owner.Hidden && + owner.AccessLevel >= from.AccessLevel) + { + from.SendMessage("You can not go to what you can not see."); + return; + } + + if (!FixMap(ref map, ref loc, m)) + { + from.SendMessage("That is an internal mobile and you cannot go to it."); + return; + } + + from.MoveToWorld(loc, map); + + return; + } + else + { + var name = e.GetString(0); + Map map; + + for (var i = 0; i < Map.AllMaps.Count; ++i) + { + map = Map.AllMaps[i]; + + if (map.MapIndex == 0x7F || map.MapIndex == 0xFF) + continue; + + if (Insensitive.Equals(name, map.Name)) + { + from.Map = map; + return; + } + } + + var list = from.Map.Regions; + + foreach (var kvp in list) + { + var r = kvp.Value; + + if (Insensitive.Equals(r.Name, name)) + { + from.Location = new Point3D(r.GoLocation); + return; + } + } + + for (var i = 0; i < Map.AllMaps.Count; ++i) + { + map = Map.AllMaps[i]; + + if (map.MapIndex == 0x7F || map.MapIndex == 0xFF || from.Map == map) + continue; + + foreach (var r in map.Regions.Values) + if (Insensitive.Equals(r.Name, name)) + { + from.MoveToWorld(r.GoLocation, map); + return; + } + } + + if (ser != 0) + from.SendMessage("No object with that serial was found."); + else + from.SendMessage("No region with that name was found."); + + return; + } + } + catch + { + // ignored + } + + from.SendMessage("Region name not found"); + } + else if (e.Length == 2 || e.Length == 3) + { + var map = from.Map; + + if (map != null) + try + { + /* + * This to avoid being teleported to (0,0) if trying to teleport + * to a region with spaces in its name. + */ + var x = int.Parse(e.GetString(0)); + var y = int.Parse(e.GetString(1)); + var z = e.Length == 3 ? int.Parse(e.GetString(2)) : map.GetAverageZ(x, y); + + from.Location = new Point3D(x, y, z); + } + catch + { + from.SendMessage("Region name not found."); + } + } + else if (e.Length == 6) + { + var map = from.Map; + + if (map != null) + { + var p = Sextant.ReverseLookup( + map, + e.GetInt32(3), + e.GetInt32(0), + e.GetInt32(4), + e.GetInt32(1), + Insensitive.Equals(e.GetString(5), "E"), + Insensitive.Equals(e.GetString(2), "S") + ); + + if (p != Point3D.Zero) + from.Location = p; + else + from.SendMessage("Sextant reverse lookup failed."); + } + } + else + { + from.SendMessage("Format: Go [name | serial | (x y [z]) | (deg min (N | S) deg min (E | W)]"); + } + } + + [Usage("Help")] + [Description("Lists all available commands.")] + public static void Help_OnCommand(CommandEventArgs e) + { + var m = e.Mobile; + + var list = new List(); + + foreach (var entry in CommandSystem.Entries.Values) + if (m.AccessLevel >= entry.AccessLevel) + list.Add(entry); + + list.Sort(); + + var sb = new StringBuilder(); + + if (list.Count > 0) + sb.Append(list[0].Command); + + for (var i = 1; i < list.Count; ++i) + { + var v = list[i].Command; + + if (sb.Length + 1 + v.Length >= 256) + { + m.SendAsciiMessage(0x482, sb.ToString()); + sb = new StringBuilder(); + sb.Append(v); + } + else + { + sb.Append(' '); + sb.Append(v); + } + } + + if (sb.Length > 0) + m.SendAsciiMessage(0x482, sb.ToString()); + } + + [Usage("SMsg ")] + [Aliases("S", "SM")] + [Description("Broadcasts a message to all online staff.")] + public static void StaffMessage_OnCommand(CommandEventArgs e) + { + BroadcastMessage(AccessLevel.Counselor, e.Mobile.SpeechHue, $"[{e.Mobile.Name}] {e.ArgString}"); + } + + [Usage("BCast ")] + [Aliases("B", "BC")] + [Description("Broadcasts a message to everyone online.")] + public static void BroadcastMessage_OnCommand(CommandEventArgs e) + { + BroadcastMessage(AccessLevel.Player, 0x482, $"Staff message from {e.Mobile.Name}:"); + BroadcastMessage(AccessLevel.Player, 0x482, e.ArgString); + } + + public static void BroadcastMessage(AccessLevel ac, int hue, string message) + { + foreach (var state in TcpServer.Instances) + { + var m = state.Mobile; + + if (m?.AccessLevel >= ac) + m.SendMessage(hue, message); + } + } + + [Usage("AutoPageNotify")] + [Aliases("APN")] + [Description("Toggles your auto-page-notify status.")] + public static void APN_OnCommand(CommandEventArgs e) + { + var m = e.Mobile; + + m.AutoPageNotify = !m.AutoPageNotify; + + m.SendMessage("Your auto-page-notify has been turned {0}.", m.AutoPageNotify ? "on" : "off"); + } + + [Usage("Animate ")] + [Description("Makes your character do a specified animation.")] + public static void Animate_OnCommand(CommandEventArgs e) + { + if (e.Length == 6) + e.Mobile.Animate( + e.GetInt32(0), + e.GetInt32(1), + e.GetInt32(2), + e.GetBoolean(3), + e.GetBoolean(4), + e.GetInt32(5) + ); + else + e.Mobile.SendMessage("Format: Animate "); + } + + [Usage("Cast ")] + [Description("Casts a spell by name.")] + public static void Cast_OnCommand(CommandEventArgs e) + { + if (e.Length == 1) + { + if (!DesignContext.Check(e.Mobile)) + return; // They are customizing + + var spell = SpellRegistry.NewSpell(e.GetString(0), e.Mobile, null); + + if (spell != null) + spell.Cast(); + else + e.Mobile.SendMessage("That spell was not found."); + } + else + { + e.Mobile.SendMessage("Format: Cast "); + } + } + + [Usage("Stuck")] + [Description("Opens a menu of towns, used for teleporting stuck mobiles.")] + public static void Stuck_OnCommand(CommandEventArgs e) + { + e.Mobile.Target = new StuckMenuTarget(); + } + + [Usage("Light ")] + [Description("Set your local lightlevel.")] + public static void Light_OnCommand(CommandEventArgs e) + { + e.Mobile.LightLevel = e.GetInt32(0); + } + + [Usage("Stats")] + [Description("View some stats about the server.")] + public static void Stats_OnCommand(CommandEventArgs e) + { + e.Mobile.SendMessage("Open Connections: {0}", TcpServer.Instances.Count); + e.Mobile.SendMessage("Mobiles: {0}", World.Mobiles.Count); + e.Mobile.SendMessage("Items: {0}", World.Items.Count); + } + + private class ViewEqTarget : Target + { + public ViewEqTarget() : base(-1, false, TargetFlags.None) + { + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (!BaseCommand.IsAccessible(from, targeted)) + { + from.SendLocalizedMessage(500447); // That is not accessible. + return; + } + + if (targeted is Mobile mobile) + from.SendMenu(new EquipMenu(from, mobile, GetEquip(mobile))); + } + + private static ItemListEntry[] GetEquip(Mobile m) + { + var entries = new ItemListEntry[m.Items.Count]; + + for (var i = 0; i < m.Items.Count; ++i) + { + var item = m.Items[i]; + + entries[i] = new ItemListEntry($"{item.Layer}: {item.GetType().Name}", item.ItemID, item.Hue); + } + + return entries; + } + + private class EquipMenu : ItemListMenu + { + private readonly Mobile m_Mobile; + + public EquipMenu(Mobile from, Mobile m, ItemListEntry[] entries) : base("Equipment", entries) + { + m_Mobile = m; + + CommandLogging.WriteLine( + from, + "{0} {1} viewing equipment of {2}", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(m) + ); + } + + public override void OnResponse(NetState state, int index) + { + if (index >= 0 && index < m_Mobile.Items.Count) + { + var item = m_Mobile.Items[index]; + + state.Mobile.SendMenu(new EquipDetailsMenu(m_Mobile, item)); + } + } + + private class EquipDetailsMenu : QuestionMenu + { + private readonly Item m_Item; + private readonly Mobile m_Mobile; + + public EquipDetailsMenu(Mobile m, Item item) : base( + $"{item.Layer}: {item.GetType().Name}", + new[] { "Move", "Delete", "Props" } + ) + { + m_Mobile = m; + m_Item = item; + } + + public override void OnCancel(NetState state) + { + state.Mobile.SendMenu(new EquipMenu(state.Mobile, m_Mobile, GetEquip(m_Mobile))); + } + + public override void OnResponse(NetState state, int index) + { + if (index == 0) + { + CommandLogging.WriteLine( + state.Mobile, + "{0} {1} moving equipment item {2} of {3}", + state.Mobile.AccessLevel, + CommandLogging.Format(state.Mobile), + CommandLogging.Format(m_Item), + CommandLogging.Format(m_Mobile) + ); + state.Mobile.Target = new MoveTarget(m_Item); + } + else if (index == 1) + { + CommandLogging.WriteLine( + state.Mobile, + "{0} {1} deleting equipment item {2} of {3}", + state.Mobile.AccessLevel, + CommandLogging.Format(state.Mobile), + CommandLogging.Format(m_Item), + CommandLogging.Format(m_Mobile) + ); + m_Item.Delete(); + } + else if (index == 2) + { + CommandLogging.WriteLine( + state.Mobile, + "{0} {1} opening properties for equipment item {2} of {3}", + state.Mobile.AccessLevel, + CommandLogging.Format(state.Mobile), + CommandLogging.Format(m_Item), + CommandLogging.Format(m_Mobile) + ); + state.Mobile.SendGump(new PropertiesGump(state.Mobile, m_Item)); + } + } + } + } + } + + private class BankTarget : Target + { + public BankTarget() : base(-1, false, TargetFlags.None) + { + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted is Mobile m) + { + var box = m.Player ? m.BankBox : m.FindBankNoCreate(); + + if (box != null) + { + CommandLogging.WriteLine( + from, + "{0} {1} opening bank box of {2}", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(m) + ); + + if (from == m) + box.Open(); + else + box.DisplayTo(from); + } + else + { + from.SendMessage("They have no bank box."); + } + } + } + } + + private class DismountTarget : Target + { + public DismountTarget() : base(-1, false, TargetFlags.None) + { + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted is Mobile targ) + { + CommandLogging.WriteLine( + from, + "{0} {1} dismounting {2}", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(targ) + ); + + for (var i = 0; i < targ.Items.Count; ++i) + { + var item = targ.Items[i]; + + if (item is IMountItem mountItem) + { + var mount = mountItem.Mount; + + if (mount != null) + mount.Rider = null; + + if (targ.Items.IndexOf(item) == -1) + --i; + } + } + + for (var i = 0; i < targ.Items.Count; ++i) + { + var item = targ.Items[i]; + + if (item.Layer == Layer.Mount) + { + item.Delete(); + --i; + } + } + } + } + } + + private class ClientTarget : Target + { + public ClientTarget() : base(-1, false, TargetFlags.None) + { + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted is Mobile targ && targ.NetState != null) + { + CommandLogging.WriteLine( + from, + "{0} {1} opening client menu of {2}", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(targ) + ); + from.SendGump(new ClientGump(from, targ.NetState)); + } + } + } + + private class StuckMenuTarget : Target + { + public StuckMenuTarget() : base(-1, false, TargetFlags.None) + { + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted is Mobile mobile) + { + if (mobile.AccessLevel >= from.AccessLevel && mobile != from) + from.SendMessage("You can't do that to someone with higher Accesslevel than you!"); + else + from.SendGump(new StuckMenu(from, mobile, false)); + } + } + } + } +} diff --git a/Projects/UOContent/Commands/HelpInfo.cs b/Projects/UOContent/Commands/HelpInfo.cs index 48dab2c5f..78729ceda 100644 --- a/Projects/UOContent/Commands/HelpInfo.cs +++ b/Projects/UOContent/Commands/HelpInfo.cs @@ -1,394 +1,398 @@ -using System.Collections.Generic; -using System.Reflection; -using System.Text; -using Server.Commands.Generic; -using Server.Gumps; -using Server.Network; -using CommandInfo = Server.Commands.Docs.DocCommandEntry; -using CommandInfoSorter = Server.Commands.Docs.CommandEntrySorter; - -namespace Server.Commands -{ - public class HelpInfo - { - public static Dictionary HelpInfos { get; } = new Dictionary(); - - public static List SortedHelpInfo { get; private set; } = new List(); - - [CallPriority(100)] - public static void Initialize() - { - CommandSystem.Register("HelpInfo", AccessLevel.Player, HelpInfo_OnCommand); - - FillTable(); - } - - [Usage("HelpInfo []")] - [Description( - "Gives information on a specified command, or when no argument specified, displays a gump containing all commands")] - private static void HelpInfo_OnCommand(CommandEventArgs e) - { - if (e.Length > 0) - { - string arg = e.GetString(0).ToLower(); - if (HelpInfos.TryGetValue(arg, out CommandInfo c)) - { - Mobile m = e.Mobile; - - if (m.AccessLevel >= c.AccessLevel) - m.SendGump(new CommandInfoGump(c)); - else - m.SendMessage("You don't have access to that command."); - - return; - } - - e.Mobile.SendMessage($"Command '{arg}' not found!"); - } - - e.Mobile.SendGump(new CommandListGump(0, e.Mobile, null)); - } - - public static void FillTable() - { - List commands = new List(CommandSystem.Entries.Values); - List list = new List(); - - commands.Sort(); - commands.Reverse(); - Docs.Clean(commands); - - for (int i = 0; i < commands.Count; ++i) - { - CommandEntry e = commands[i]; - - MethodInfo mi = e.Handler.Method; - - object[] attrs = mi.GetCustomAttributes(typeof(UsageAttribute), false); - - if (attrs.Length == 0) - continue; - - UsageAttribute usage = attrs[0] as UsageAttribute; - - attrs = mi.GetCustomAttributes(typeof(DescriptionAttribute), false); - - if (attrs.Length == 0) - continue; - - if (usage == null || !(attrs[0] is DescriptionAttribute desc)) - continue; - - attrs = mi.GetCustomAttributes(typeof(AliasesAttribute), false); - - AliasesAttribute aliases = attrs.Length == 0 ? null : attrs[0] as AliasesAttribute; - - string descString = desc.Description.Replace("<", "(").Replace(">", ")"); - - if (aliases == null) - { - list.Add(new CommandInfo(e.AccessLevel, e.Command, null, usage.Usage, descString)); - } - else - { - list.Add(new CommandInfo(e.AccessLevel, e.Command, aliases.Aliases, usage.Usage, descString)); - - for (int j = 0; j < aliases.Aliases.Length; j++) - { - string[] newAliases = new string[aliases.Aliases.Length]; - - aliases.Aliases.CopyTo(newAliases, 0); - - newAliases[j] = e.Command; - - list.Add(new CommandInfo(e.AccessLevel, aliases.Aliases[j], newAliases, usage.Usage, descString)); - } - } - } - - for (int i = 0; i < TargetCommands.AllCommands.Count; ++i) - { - BaseCommand command = TargetCommands.AllCommands[i]; - - string usage = command.Usage; - string desc = command.Description; - - if (usage == null || desc == null) - continue; - - string[] cmds = command.Commands; - string cmd = cmds[0]; - string[] aliases = new string[cmds.Length - 1]; - - for (int j = 0; j < aliases.Length; ++j) - aliases[j] = cmds[j + 1]; - - desc = desc.Replace("<", "(").Replace(">", ")"); - - if (command.Supports != CommandSupport.Single) - { - StringBuilder sb = new StringBuilder(50 + desc.Length); - - sb.Append("Modifiers: "); - - if ((command.Supports & CommandSupport.Global) != 0) - sb.Append("Global, "); - - if ((command.Supports & CommandSupport.Online) != 0) - sb.Append("Online, "); - - if ((command.Supports & CommandSupport.Region) != 0) - sb.Append("Region, "); - - if ((command.Supports & CommandSupport.Contained) != 0) - sb.Append("Contained, "); - - if ((command.Supports & CommandSupport.Multi) != 0) - sb.Append("Multi, "); - - if ((command.Supports & CommandSupport.Area) != 0) - sb.Append("Area, "); - - if ((command.Supports & CommandSupport.Self) != 0) - sb.Append("Self, "); - - sb.Remove(sb.Length - 2, 2); - sb.Append("
"); - sb.Append(desc); - - desc = sb.ToString(); - } - - list.Add(new CommandInfo(command.AccessLevel, cmd, aliases, usage, desc)); - - for (int j = 0; j < aliases.Length; j++) - { - string[] newAliases = new string[aliases.Length]; - - aliases.CopyTo(newAliases, 0); - - newAliases[j] = cmd; - - list.Add(new CommandInfo(command.AccessLevel, aliases[j], newAliases, usage, desc)); - } - } - - List commandImpls = BaseCommandImplementor.Implementors; - - for (int i = 0; i < commandImpls.Count; ++i) - { - BaseCommandImplementor command = commandImpls[i]; - - string usage = command.Usage; - string desc = command.Description; - - if (usage == null || desc == null) - continue; - - string[] cmds = command.Accessors; - string cmd = cmds[0]; - string[] aliases = new string[cmds.Length - 1]; - - for (int j = 0; j < aliases.Length; ++j) - aliases[j] = cmds[j + 1]; - - desc = desc.Replace("<", ")").Replace(">", ")"); - - list.Add(new CommandInfo(command.AccessLevel, cmd, aliases, usage, desc)); - - for (int j = 0; j < aliases.Length; j++) - { - string[] newAliases = new string[aliases.Length]; - - aliases.CopyTo(newAliases, 0); - - newAliases[j] = cmd; - - list.Add(new CommandInfo(command.AccessLevel, aliases[j], newAliases, usage, desc)); - } - } - - list.Sort(new CommandInfoSorter()); - - SortedHelpInfo = list; - - foreach (CommandInfo c in SortedHelpInfo) - if (!HelpInfos.ContainsKey(c.Name.ToLower())) - HelpInfos.Add(c.Name.ToLower(), c); - } - - public class CommandListGump : BaseGridGump - { - private const int EntriesPerPage = 15; - private readonly List m_List; - - private readonly int m_Page; - - public CommandListGump(int page, Mobile from, List list) - : base(30, 30) - { - m_Page = page; - - if (list == null) - { - m_List = new List(); - - foreach (CommandInfo c in SortedHelpInfo) - if (from.AccessLevel >= c.AccessLevel) - m_List.Add(c); - } - else - { - m_List = list; - } - - AddNewPage(); - - if (m_Page > 0) - AddEntryButton(20, ArrowLeftID1, ArrowLeftID2, 1, ArrowLeftWidth, ArrowLeftHeight); - else - AddEntryHeader(20); - - AddEntryHtml(160, Center( - $"Page {m_Page + 1} of {(m_List.Count + EntriesPerPage - 1) / EntriesPerPage}")); - - if ((m_Page + 1) * EntriesPerPage < m_List.Count) - AddEntryButton(20, ArrowRightID1, ArrowRightID2, 2, ArrowRightWidth, ArrowRightHeight); - else - AddEntryHeader(20); - - int last = (int)AccessLevel.Player - 1; - - for (int i = m_Page * EntriesPerPage, line = 0; line < EntriesPerPage && i < m_List.Count; ++i, ++line) - { - CommandInfo c = m_List[i]; - if (from.AccessLevel >= c.AccessLevel) - { - if ((int)c.AccessLevel != last) - { - AddNewLine(); - AddEntryHtml(20 + OffsetSize + 160, Color(c.AccessLevel.ToString(), 0xFF0000)); - AddEntryHeader(20); - line++; - } - - last = (int)c.AccessLevel; - - AddNewLine(); - AddEntryHtml(20 + OffsetSize + 160, c.Name); - AddEntryButton(20, ArrowRightID1, ArrowRightID2, 3 + i, ArrowRightWidth, ArrowRightHeight); - } - } - - FinishPage(); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - Mobile m = sender.Mobile; - switch (info.ButtonID) - { - case 0: - { - m.CloseGump(); - break; - } - case 1: - { - if (m_Page > 0) - m.SendGump(new CommandListGump(m_Page - 1, m, m_List)); - - break; - } - case 2: - { - if ((m_Page + 1) * EntriesPerPage < SortedHelpInfo.Count) - m.SendGump(new CommandListGump(m_Page + 1, m, m_List)); - - break; - } - default: - { - int v = info.ButtonID - 3; - - if (v >= 0 && v < m_List.Count) - { - CommandInfo c = m_List[v]; - - if (m.AccessLevel >= c.AccessLevel) - { - m.SendGump(new CommandInfoGump(c)); - m.SendGump(new CommandListGump(m_Page, m, m_List)); - } - else - { - m.SendMessage("You no longer have access to that command."); - m.SendGump(new CommandListGump(m_Page, m, null)); - } - } - - break; - } - } - } - } - - public class CommandInfoGump : Gump - { - public CommandInfoGump(CommandInfo info, int width = 320, int height = 200) - : base(300, 50) - { - AddPage(0); - - AddBackground(0, 0, width, height, 5054); - - // AddImageTiled( 10, 10, width - 20, 20, 2624 ); - // AddAlphaRegion( 10, 10, width - 20, 20 ); - // AddHtmlLocalized( 10, 10, width - 20, 20, header, headerColor, false, false ); - AddHtml(10, 10, width - 20, 20, Color(Center(info.Name), 0xFF0000)); - - // AddImageTiled( 10, 40, width - 20, height - 80, 2624 ); - // AddAlphaRegion( 10, 40, width - 20, height - 80 ); - - StringBuilder sb = new StringBuilder(); - - sb.Append("Usage: "); - sb.Append(info.Usage.Replace("<", "(").Replace(">", ")")); - sb.Append("
"); - - string[] aliases = info.Aliases; - - if (aliases?.Length > 0) - { - sb.Append($"Alias{(aliases.Length == 1 ? "" : "es")}: "); - - for (int i = 0; i < aliases.Length; ++i) - { - if (i != 0) - sb.Append(", "); - - sb.Append(aliases[i]); - } - - sb.Append("
"); - } - - sb.Append("AccessLevel: "); - sb.Append(info.AccessLevel.ToString()); - sb.Append("
"); - sb.Append("
"); - - sb.Append(info.Description); - - AddHtml(10, 40, width - 20, height - 80, sb.ToString(), false, true); - - // AddImageTiled( 10, height - 30, width - 20, 20, 2624 ); - // AddAlphaRegion( 10, height - 30, width - 20, 20 ); - } - - public string Color(string text, int color) => $"{text}"; - - public string Center(string text) => $"
{text}
"; - } - } -} +using System.Collections.Generic; +using System.Text; +using Server.Commands.Generic; +using Server.Gumps; +using Server.Network; +using CommandInfo = Server.Commands.Docs.DocCommandEntry; +using CommandInfoSorter = Server.Commands.Docs.CommandEntrySorter; + +namespace Server.Commands +{ + public class HelpInfo + { + public static Dictionary HelpInfos { get; } = new Dictionary(); + + public static List SortedHelpInfo { get; private set; } = new List(); + + [CallPriority(100)] + public static void Initialize() + { + CommandSystem.Register("HelpInfo", AccessLevel.Player, HelpInfo_OnCommand); + + FillTable(); + } + + [Usage("HelpInfo []")] + [Description( + "Gives information on a specified command, or when no argument specified, displays a gump containing all commands" + )] + private static void HelpInfo_OnCommand(CommandEventArgs e) + { + if (e.Length > 0) + { + var arg = e.GetString(0).ToLower(); + if (HelpInfos.TryGetValue(arg, out var c)) + { + var m = e.Mobile; + + if (m.AccessLevel >= c.AccessLevel) + m.SendGump(new CommandInfoGump(c)); + else + m.SendMessage("You don't have access to that command."); + + return; + } + + e.Mobile.SendMessage($"Command '{arg}' not found!"); + } + + e.Mobile.SendGump(new CommandListGump(0, e.Mobile, null)); + } + + public static void FillTable() + { + var commands = new List(CommandSystem.Entries.Values); + var list = new List(); + + commands.Sort(); + commands.Reverse(); + Docs.Clean(commands); + + for (var i = 0; i < commands.Count; ++i) + { + var e = commands[i]; + + var mi = e.Handler.Method; + + var attrs = mi.GetCustomAttributes(typeof(UsageAttribute), false); + + if (attrs.Length == 0) + continue; + + var usage = attrs[0] as UsageAttribute; + + attrs = mi.GetCustomAttributes(typeof(DescriptionAttribute), false); + + if (attrs.Length == 0) + continue; + + if (usage == null || !(attrs[0] is DescriptionAttribute desc)) + continue; + + attrs = mi.GetCustomAttributes(typeof(AliasesAttribute), false); + + var aliases = attrs.Length == 0 ? null : attrs[0] as AliasesAttribute; + + var descString = desc.Description.Replace("<", "(").Replace(">", ")"); + + if (aliases == null) + { + list.Add(new CommandInfo(e.AccessLevel, e.Command, null, usage.Usage, descString)); + } + else + { + list.Add(new CommandInfo(e.AccessLevel, e.Command, aliases.Aliases, usage.Usage, descString)); + + for (var j = 0; j < aliases.Aliases.Length; j++) + { + var newAliases = new string[aliases.Aliases.Length]; + + aliases.Aliases.CopyTo(newAliases, 0); + + newAliases[j] = e.Command; + + list.Add(new CommandInfo(e.AccessLevel, aliases.Aliases[j], newAliases, usage.Usage, descString)); + } + } + } + + for (var i = 0; i < TargetCommands.AllCommands.Count; ++i) + { + var command = TargetCommands.AllCommands[i]; + + var usage = command.Usage; + var desc = command.Description; + + if (usage == null || desc == null) + continue; + + var cmds = command.Commands; + var cmd = cmds[0]; + var aliases = new string[cmds.Length - 1]; + + for (var j = 0; j < aliases.Length; ++j) + aliases[j] = cmds[j + 1]; + + desc = desc.Replace("<", "(").Replace(">", ")"); + + if (command.Supports != CommandSupport.Single) + { + var sb = new StringBuilder(50 + desc.Length); + + sb.Append("Modifiers: "); + + if ((command.Supports & CommandSupport.Global) != 0) + sb.Append("Global, "); + + if ((command.Supports & CommandSupport.Online) != 0) + sb.Append("Online, "); + + if ((command.Supports & CommandSupport.Region) != 0) + sb.Append("Region, "); + + if ((command.Supports & CommandSupport.Contained) != 0) + sb.Append("Contained, "); + + if ((command.Supports & CommandSupport.Multi) != 0) + sb.Append("Multi, "); + + if ((command.Supports & CommandSupport.Area) != 0) + sb.Append("Area, "); + + if ((command.Supports & CommandSupport.Self) != 0) + sb.Append("Self, "); + + sb.Remove(sb.Length - 2, 2); + sb.Append("
"); + sb.Append(desc); + + desc = sb.ToString(); + } + + list.Add(new CommandInfo(command.AccessLevel, cmd, aliases, usage, desc)); + + for (var j = 0; j < aliases.Length; j++) + { + var newAliases = new string[aliases.Length]; + + aliases.CopyTo(newAliases, 0); + + newAliases[j] = cmd; + + list.Add(new CommandInfo(command.AccessLevel, aliases[j], newAliases, usage, desc)); + } + } + + var commandImpls = BaseCommandImplementor.Implementors; + + for (var i = 0; i < commandImpls.Count; ++i) + { + var command = commandImpls[i]; + + var usage = command.Usage; + var desc = command.Description; + + if (usage == null || desc == null) + continue; + + var cmds = command.Accessors; + var cmd = cmds[0]; + var aliases = new string[cmds.Length - 1]; + + for (var j = 0; j < aliases.Length; ++j) + aliases[j] = cmds[j + 1]; + + desc = desc.Replace("<", ")").Replace(">", ")"); + + list.Add(new CommandInfo(command.AccessLevel, cmd, aliases, usage, desc)); + + for (var j = 0; j < aliases.Length; j++) + { + var newAliases = new string[aliases.Length]; + + aliases.CopyTo(newAliases, 0); + + newAliases[j] = cmd; + + list.Add(new CommandInfo(command.AccessLevel, aliases[j], newAliases, usage, desc)); + } + } + + list.Sort(new CommandInfoSorter()); + + SortedHelpInfo = list; + + foreach (var c in SortedHelpInfo) + if (!HelpInfos.ContainsKey(c.Name.ToLower())) + HelpInfos.Add(c.Name.ToLower(), c); + } + + public class CommandListGump : BaseGridGump + { + private const int EntriesPerPage = 15; + private readonly List m_List; + + private readonly int m_Page; + + public CommandListGump(int page, Mobile from, List list) + : base(30, 30) + { + m_Page = page; + + if (list == null) + { + m_List = new List(); + + foreach (var c in SortedHelpInfo) + if (from.AccessLevel >= c.AccessLevel) + m_List.Add(c); + } + else + { + m_List = list; + } + + AddNewPage(); + + if (m_Page > 0) + AddEntryButton(20, ArrowLeftID1, ArrowLeftID2, 1, ArrowLeftWidth, ArrowLeftHeight); + else + AddEntryHeader(20); + + AddEntryHtml( + 160, + Center( + $"Page {m_Page + 1} of {(m_List.Count + EntriesPerPage - 1) / EntriesPerPage}" + ) + ); + + if ((m_Page + 1) * EntriesPerPage < m_List.Count) + AddEntryButton(20, ArrowRightID1, ArrowRightID2, 2, ArrowRightWidth, ArrowRightHeight); + else + AddEntryHeader(20); + + var last = (int)AccessLevel.Player - 1; + + for (int i = m_Page * EntriesPerPage, line = 0; line < EntriesPerPage && i < m_List.Count; ++i, ++line) + { + var c = m_List[i]; + if (from.AccessLevel >= c.AccessLevel) + { + if ((int)c.AccessLevel != last) + { + AddNewLine(); + AddEntryHtml(20 + OffsetSize + 160, Color(c.AccessLevel.ToString(), 0xFF0000)); + AddEntryHeader(20); + line++; + } + + last = (int)c.AccessLevel; + + AddNewLine(); + AddEntryHtml(20 + OffsetSize + 160, c.Name); + AddEntryButton(20, ArrowRightID1, ArrowRightID2, 3 + i, ArrowRightWidth, ArrowRightHeight); + } + } + + FinishPage(); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var m = sender.Mobile; + switch (info.ButtonID) + { + case 0: + { + m.CloseGump(); + break; + } + case 1: + { + if (m_Page > 0) + m.SendGump(new CommandListGump(m_Page - 1, m, m_List)); + + break; + } + case 2: + { + if ((m_Page + 1) * EntriesPerPage < SortedHelpInfo.Count) + m.SendGump(new CommandListGump(m_Page + 1, m, m_List)); + + break; + } + default: + { + var v = info.ButtonID - 3; + + if (v >= 0 && v < m_List.Count) + { + var c = m_List[v]; + + if (m.AccessLevel >= c.AccessLevel) + { + m.SendGump(new CommandInfoGump(c)); + m.SendGump(new CommandListGump(m_Page, m, m_List)); + } + else + { + m.SendMessage("You no longer have access to that command."); + m.SendGump(new CommandListGump(m_Page, m, null)); + } + } + + break; + } + } + } + } + + public class CommandInfoGump : Gump + { + public CommandInfoGump(CommandInfo info, int width = 320, int height = 200) + : base(300, 50) + { + AddPage(0); + + AddBackground(0, 0, width, height, 5054); + + // AddImageTiled( 10, 10, width - 20, 20, 2624 ); + // AddAlphaRegion( 10, 10, width - 20, 20 ); + // AddHtmlLocalized( 10, 10, width - 20, 20, header, headerColor, false, false ); + AddHtml(10, 10, width - 20, 20, Color(Center(info.Name), 0xFF0000)); + + // AddImageTiled( 10, 40, width - 20, height - 80, 2624 ); + // AddAlphaRegion( 10, 40, width - 20, height - 80 ); + + var sb = new StringBuilder(); + + sb.Append("Usage: "); + sb.Append(info.Usage.Replace("<", "(").Replace(">", ")")); + sb.Append("
"); + + var aliases = info.Aliases; + + if (aliases?.Length > 0) + { + sb.Append($"Alias{(aliases.Length == 1 ? "" : "es")}: "); + + for (var i = 0; i < aliases.Length; ++i) + { + if (i != 0) + sb.Append(", "); + + sb.Append(aliases[i]); + } + + sb.Append("
"); + } + + sb.Append("AccessLevel: "); + sb.Append(info.AccessLevel.ToString()); + sb.Append("
"); + sb.Append("
"); + + sb.Append(info.Description); + + AddHtml(10, 40, width - 20, height - 80, sb.ToString(), false, true); + + // AddImageTiled( 10, height - 30, width - 20, 20, 2624 ); + // AddAlphaRegion( 10, height - 30, width - 20, 20 ); + } + + public string Color(string text, int color) => $"{text}"; + + public string Center(string text) => $"
{text}
"; + } + } +} diff --git a/Projects/UOContent/Commands/LocationCommand.cs b/Projects/UOContent/Commands/LocationCommand.cs index c34251bea..eb33b5a99 100644 --- a/Projects/UOContent/Commands/LocationCommand.cs +++ b/Projects/UOContent/Commands/LocationCommand.cs @@ -1,63 +1,71 @@ -using System.Collections.Generic; -using System.Globalization; -using Server.Commands.Generic; -using Server.Items; -using Server.Targeting; - -namespace Server.Commands -{ - public class LocationCommand : BaseCommand - { - private static readonly List m_DefaultGraphics = new List { 0x17AF, 0x17B0, 0x17B1, 0x17B2 }; - - public LocationCommand() - { - AccessLevel = AccessLevel.Counselor; - Commands = new[] { "Location", "Loc", "Pos" }; - ObjectTypes = ObjectTypes.All; - Supports = CommandSupport.Single | CommandSupport.Multi; - Usage = "Location [itemIds ...]"; - Description = "Retrieves the positional coordinates of a target. Displaying a message above the item, " - + "mobile, or environment. Environment targets will also have a graphic temporarily displayed " - + "on the tile. This graphic can be changed to the provided list of itemIds."; - } - - public override void Execute(CommandEventArgs e, object obj) - { - if (!(obj is IPoint3D point)) - { - LogFailure("That cannot be located."); - return; - } - - var label = $"(x:{point.X}, y:{point.Y}, z:{point.Z})"; - if (obj is LandTarget || obj is StaticTarget) - { - List graphics; - if (e.Arguments.Length == 0) - graphics = m_DefaultGraphics; - else - { - graphics = new List(); - foreach (var arg in e.Arguments) - { - var numberStyles = arg.ToLower().StartsWith("0x") ? NumberStyles.HexNumber : NumberStyles.Integer; - - if (int.TryParse(arg, numberStyles, CultureInfo.InvariantCulture, out int result)) - graphics.Add(result); - } - } - - var item = EffectItem.Create(new Point3D(point), e.Mobile.Map, EffectItem.DefaultDuration); - foreach (int graphic in graphics) - Effects.SendLocationParticles(item, graphic, 10, 50, 2023); - - item.LabelTo(e.Mobile, label); - } - else if (obj is Mobile entity) entity.SayTo(e.Mobile, label); - else if (obj is Item item) item.LabelTo(e.Mobile, label); - - AddResponse($"Location: {label}"); - } - } -} +using System.Collections.Generic; +using System.Globalization; +using Server.Commands.Generic; +using Server.Items; +using Server.Targeting; + +namespace Server.Commands +{ + public class LocationCommand : BaseCommand + { + private static readonly List m_DefaultGraphics = new List { 0x17AF, 0x17B0, 0x17B1, 0x17B2 }; + + public LocationCommand() + { + AccessLevel = AccessLevel.Counselor; + Commands = new[] { "Location", "Loc", "Pos" }; + ObjectTypes = ObjectTypes.All; + Supports = CommandSupport.Single | CommandSupport.Multi; + Usage = "Location [itemIds ...]"; + Description = "Retrieves the positional coordinates of a target. Displaying a message above the item, " + + "mobile, or environment. Environment targets will also have a graphic temporarily displayed " + + "on the tile. This graphic can be changed to the provided list of itemIds."; + } + + public override void Execute(CommandEventArgs e, object obj) + { + if (!(obj is IPoint3D point)) + { + LogFailure("That cannot be located."); + return; + } + + var label = $"(x:{point.X}, y:{point.Y}, z:{point.Z})"; + if (obj is LandTarget || obj is StaticTarget) + { + List graphics; + if (e.Arguments.Length == 0) + { + graphics = m_DefaultGraphics; + } + else + { + graphics = new List(); + foreach (var arg in e.Arguments) + { + var numberStyles = arg.ToLower().StartsWith("0x") ? NumberStyles.HexNumber : NumberStyles.Integer; + + if (int.TryParse(arg, numberStyles, CultureInfo.InvariantCulture, out var result)) + graphics.Add(result); + } + } + + var item = EffectItem.Create(new Point3D(point), e.Mobile.Map, EffectItem.DefaultDuration); + foreach (var graphic in graphics) + Effects.SendLocationParticles(item, graphic, 10, 50, 2023); + + item.LabelTo(e.Mobile, label); + } + else if (obj is Mobile entity) + { + entity.SayTo(e.Mobile, label); + } + else if (obj is Item item) + { + item.LabelTo(e.Mobile, label); + } + + AddResponse($"Location: {label}"); + } + } +} diff --git a/Projects/UOContent/Commands/Logging.cs b/Projects/UOContent/Commands/Logging.cs index 9fabe8762..736c6dc44 100644 --- a/Projects/UOContent/Commands/Logging.cs +++ b/Projects/UOContent/Commands/Logging.cs @@ -1,136 +1,149 @@ -using System; -using System.IO; -using System.Text; -using Server.Accounting; - -namespace Server.Commands -{ - public class CommandLogging - { - private static readonly char[] m_NotSafe = { '\\', '/', ':', '*', '?', '"', '<', '>', '|' }; - public static bool Enabled { get; set; } = true; - - public static StreamWriter Output { get; private set; } - - public static void Initialize() - { - EventSink.Command += EventSink_Command; - - if (!Directory.Exists("Logs")) - Directory.CreateDirectory("Logs"); - - string directory = "Logs/Commands"; - - if (!Directory.Exists(directory)) - Directory.CreateDirectory(directory); - - try - { - Output = new StreamWriter(Path.Combine(directory, $"{DateTime.UtcNow.ToLongDateString()}.log"), true); - - Output.AutoFlush = true; - - Output.WriteLine("##############################"); - Output.WriteLine("Log started on {0}", DateTime.UtcNow); - Output.WriteLine(); - } - catch - { - // ignored - } - } - - public static object Format(object o) - { - if (o is Mobile m) - { - if (m.Account == null) - return $"{m} (no account)"; - - return $"{m} ('{m.Account.Username}')"; - } - - if (o is Item item) return $"0x{item.Serial.Value:X} ({item.GetType().Name})"; - - return o; - } - - public static void WriteLine(Mobile from, string format, params object[] args) - { - if (!Enabled) - return; - - WriteLine(from, string.Format(format, args)); - } - - public static void WriteLine(Mobile from, string text) - { - if (!Enabled) - return; - - try - { - Output.WriteLine("{0}: {1}: {2}", DateTime.UtcNow, from.NetState, text); - - string path = Core.BaseDirectory; - - string name = !(from.Account is Account acct) ? from.Name : acct.Username; - - AppendPath(ref path, "Logs"); - AppendPath(ref path, "Commands"); - AppendPath(ref path, from.AccessLevel.ToString()); - path = Path.Combine(path, $"{name}.log"); - - using StreamWriter sw = new StreamWriter(path, true); - sw.WriteLine("{0}: {1}: {2}", DateTime.UtcNow, from.NetState, text); - } - catch - { - // ignored - } - } - - public static void AppendPath(ref string path, string toAppend) - { - path = Path.Combine(path, toAppend); - - if (!Directory.Exists(path)) - Directory.CreateDirectory(path); - } - - public static string Safe(string ip) - { - if (ip == null) - return "null"; - - ip = ip.Trim().IsNullOrDefault("empty"); - - bool isSafe = true; - - for (int i = 0; isSafe && i < m_NotSafe.Length; ++i) - isSafe = ip.IndexOf(m_NotSafe[i]) == -1; - - if (isSafe) - return ip; - - StringBuilder sb = new StringBuilder(ip); - - for (int i = 0; i < m_NotSafe.Length; ++i) - sb.Replace(m_NotSafe[i], '_'); - - return sb.ToString(); - } - - public static void EventSink_Command(CommandEventArgs e) - { - WriteLine(e.Mobile, "{0} {1} used command '{2} {3}'", e.Mobile.AccessLevel, Format(e.Mobile), e.Command, - e.ArgString); - } - - public static void LogChangeProperty(Mobile from, object o, string name, string value) - { - WriteLine(from, "{0} {1} set property '{2}' of {3} to '{4}'", from.AccessLevel, Format(from), name, Format(o), - value); - } - } -} +using System; +using System.IO; +using System.Text; +using Server.Accounting; + +namespace Server.Commands +{ + public class CommandLogging + { + private static readonly char[] m_NotSafe = { '\\', '/', ':', '*', '?', '"', '<', '>', '|' }; + public static bool Enabled { get; set; } = true; + + public static StreamWriter Output { get; private set; } + + public static void Initialize() + { + EventSink.Command += EventSink_Command; + + if (!Directory.Exists("Logs")) + Directory.CreateDirectory("Logs"); + + var directory = "Logs/Commands"; + + if (!Directory.Exists(directory)) + Directory.CreateDirectory(directory); + + try + { + Output = new StreamWriter(Path.Combine(directory, $"{DateTime.UtcNow.ToLongDateString()}.log"), true); + + Output.AutoFlush = true; + + Output.WriteLine("##############################"); + Output.WriteLine("Log started on {0}", DateTime.UtcNow); + Output.WriteLine(); + } + catch + { + // ignored + } + } + + public static object Format(object o) + { + if (o is Mobile m) + { + if (m.Account == null) + return $"{m} (no account)"; + + return $"{m} ('{m.Account.Username}')"; + } + + if (o is Item item) return $"0x{item.Serial.Value:X} ({item.GetType().Name})"; + + return o; + } + + public static void WriteLine(Mobile from, string format, params object[] args) + { + if (!Enabled) + return; + + WriteLine(from, string.Format(format, args)); + } + + public static void WriteLine(Mobile from, string text) + { + if (!Enabled) + return; + + try + { + Output.WriteLine("{0}: {1}: {2}", DateTime.UtcNow, from.NetState, text); + + var path = Core.BaseDirectory; + + var name = !(from.Account is Account acct) ? from.Name : acct.Username; + + AppendPath(ref path, "Logs"); + AppendPath(ref path, "Commands"); + AppendPath(ref path, from.AccessLevel.ToString()); + path = Path.Combine(path, $"{name}.log"); + + using var sw = new StreamWriter(path, true); + sw.WriteLine("{0}: {1}: {2}", DateTime.UtcNow, from.NetState, text); + } + catch + { + // ignored + } + } + + public static void AppendPath(ref string path, string toAppend) + { + path = Path.Combine(path, toAppend); + + if (!Directory.Exists(path)) + Directory.CreateDirectory(path); + } + + public static string Safe(string ip) + { + if (ip == null) + return "null"; + + ip = ip.Trim().IsNullOrDefault("empty"); + + var isSafe = true; + + for (var i = 0; isSafe && i < m_NotSafe.Length; ++i) + isSafe = ip.IndexOf(m_NotSafe[i]) == -1; + + if (isSafe) + return ip; + + var sb = new StringBuilder(ip); + + for (var i = 0; i < m_NotSafe.Length; ++i) + sb.Replace(m_NotSafe[i], '_'); + + return sb.ToString(); + } + + public static void EventSink_Command(CommandEventArgs e) + { + WriteLine( + e.Mobile, + "{0} {1} used command '{2} {3}'", + e.Mobile.AccessLevel, + Format(e.Mobile), + e.Command, + e.ArgString + ); + } + + public static void LogChangeProperty(Mobile from, object o, string name, string value) + { + WriteLine( + from, + "{0} {1} set property '{2}' of {3} to '{4}'", + from.AccessLevel, + Format(from), + name, + Format(o), + value + ); + } + } +} diff --git a/Projects/UOContent/Commands/Object Creation/Add.cs b/Projects/UOContent/Commands/Object Creation/Add.cs index 1af92f9cc..59778790c 100644 --- a/Projects/UOContent/Commands/Object Creation/Add.cs +++ b/Projects/UOContent/Commands/Object Creation/Add.cs @@ -1,680 +1,722 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using Server.Items; -using CPA = Server.CommandPropertyAttribute; - -namespace Server.Commands -{ - public class Add - { - private static readonly Type m_EntityType = typeof(IEntity); - - private static readonly Type m_ConstructibleType = typeof(ConstructibleAttribute); - - private static readonly Type m_EnumType = typeof(Enum); - - private static readonly Type m_TypeType = typeof(Type); - - private static readonly Type m_ParsableType = typeof(ParsableAttribute); - - private static readonly Type[] m_ParseTypes = { typeof(string) }; - private static readonly object[] m_ParseArgs = new object[1]; - - private static readonly Type[] m_SignedNumerics = - { - typeof(long), - typeof(int), - typeof(short), - typeof(sbyte) - }; - - private static readonly Type[] m_UnsignedNumerics = - { - typeof(ulong), - typeof(uint), - typeof(ushort), - typeof(byte) - }; - - public static void Initialize() - { - CommandSystem.Register("Tile", AccessLevel.GameMaster, Tile_OnCommand); - CommandSystem.Register("TileRXYZ", AccessLevel.GameMaster, TileRXYZ_OnCommand); - CommandSystem.Register("TileXYZ", AccessLevel.GameMaster, TileXYZ_OnCommand); - CommandSystem.Register("TileZ", AccessLevel.GameMaster, TileZ_OnCommand); - CommandSystem.Register("TileAvg", AccessLevel.GameMaster, TileAvg_OnCommand); - - CommandSystem.Register("Outline", AccessLevel.GameMaster, Outline_OnCommand); - CommandSystem.Register("OutlineRXYZ", AccessLevel.GameMaster, OutlineRXYZ_OnCommand); - CommandSystem.Register("OutlineXYZ", AccessLevel.GameMaster, OutlineXYZ_OnCommand); - CommandSystem.Register("OutlineZ", AccessLevel.GameMaster, OutlineZ_OnCommand); - CommandSystem.Register("OutlineAvg", AccessLevel.GameMaster, OutlineAvg_OnCommand); - } - - public static void Invoke(Mobile from, Point3D start, Point3D end, string[] args, List packs = null, - bool outline = false, bool mapAvg = false) - { - StringBuilder sb = new StringBuilder(); - - sb.AppendFormat("{0} {1} building ", from.AccessLevel, CommandLogging.Format(from)); - - if (start == end) - sb.AppendFormat("at {0} in {1}", start, from.Map); - else - sb.AppendFormat("from {0} to {1} in {2}", start, end, from.Map); - - sb.Append(":"); - - for (int i = 0; i < args.Length; ++i) - sb.AppendFormat(" \"{0}\"", args[i]); - - CommandLogging.WriteLine(from, sb.ToString()); - - string name = args[0]; - - FixArgs(ref args); - - string[,] props = null; - - for (int i = 0; i < args.Length; ++i) - if (Insensitive.Equals(args[i], "set")) - { - int remains = args.Length - i - 1; - - if (remains >= 2) - { - props = new string[remains / 2, 2]; - - remains /= 2; - - for (int j = 0; j < remains; ++j) - { - props[j, 0] = args[i + j * 2 + 1]; - props[j, 1] = args[i + j * 2 + 2]; - } - - FixSetString(ref args, i); - } - - break; - } - - Type type = AssemblyHandler.FindFirstTypeForName(name); - - if (!IsEntity(type)) - { - from.SendMessage("No type with that name was found."); - return; - } - - DateTime time = DateTime.UtcNow; - - int built = BuildObjects(from, type, start, end, args, props, packs, outline, mapAvg); - - if (built > 0) - from.SendMessage("{0} object{1} generated in {2:F1} seconds.", built, built != 1 ? "s" : "", - (DateTime.UtcNow - time).TotalSeconds); - else - SendUsage(type, from); - } - - public static void FixSetString(ref string[] args, int index) - { - string[] old = args; - args = new string[index]; - - Array.Copy(old, 0, args, 0, index); - } - - public static void FixArgs(ref string[] args) - { - string[] old = args; - args = new string[args.Length - 1]; - - Array.Copy(old, 1, args, 0, args.Length); - } - - public static int BuildObjects(Mobile from, Type type, Point3D start, Point3D end, string[] args, string[,] props, - List packs, bool outline = false, bool mapAvg = false) - { - Utility.FixPoints(ref start, ref end); - - PropertyInfo[] realProps = null; - - if (props != null) - { - realProps = new PropertyInfo[props.GetLength(0)]; - - PropertyInfo[] allProps = - type.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public); - - for (int i = 0; i < realProps.Length; ++i) - { - PropertyInfo thisProp = null; - - string propName = props[i, 0]; - - for (int j = 0; thisProp == null && j < allProps.Length; ++j) - if (Insensitive.Equals(propName, allProps[j].Name)) - thisProp = allProps[j]; - - if (thisProp == null) - { - from.SendMessage("Property not found: {0}", propName); - } - else - { - CPA attr = Properties.GetCPA(thisProp); - - if (attr == null) - from.SendMessage("Property ({0}) not found.", propName); - else if (from.AccessLevel < attr.WriteLevel) - from.SendMessage("Setting this property ({0}) requires at least {1} access level.", propName, - Mobile.GetAccessLevelName(attr.WriteLevel)); - else if (!thisProp.CanWrite || attr.ReadOnly) - from.SendMessage("Property ({0}) is read only.", propName); - else - realProps[i] = thisProp; - } - } - } - - ConstructorInfo[] ctors = type.GetConstructors(); - - for (int i = 0; i < ctors.Length; ++i) - { - ConstructorInfo ctor = ctors[i]; - - if (!IsConstructible(ctor, from.AccessLevel)) - continue; - - // Handle optional constructors - ParameterInfo[] paramList = ctor.GetParameters(); - int totalParams = paramList.Count(t => !t.HasDefaultValue); - - if (args.Length >= totalParams && args.Length <= paramList.Length) - { - object[] paramValues = ParseValues(paramList, args); - - if (paramValues == null) - continue; - - int built = Build(from, start, end, ctor, paramValues, props, realProps, packs, outline, mapAvg); - - if (built > 0) - return built; - } - } - - return 0; - } - - public static object[] ParseValues(ParameterInfo[] paramList, string[] args) - { - object[] values = new object[paramList.Length]; - - for (int i = 0, a = 0; i < paramList.Length; i++) - { - ParameterInfo param = paramList[i]; - object value = ParseValue(param.ParameterType, a < args.Length ? args[a++] : null); - - if (value != null) - values[i] = value; - else if (param.HasDefaultValue) - values[i] = Type.Missing; - else - return null; - } - - return values; - } - - public static object ParseValue(Type type, string value) - { - try - { - if (IsEnum(type)) return Enum.Parse(type, value, true); - if (IsType(type)) return AssemblyHandler.FindFirstTypeForName(value); - if (IsParsable(type)) return ParseParsable(type, value); - object obj = value; - - if (value?.StartsWith("0x") == true) - { - if (IsSignedNumeric(type)) - obj = Convert.ToInt64(value.Substring(2), 16); - else if (IsUnsignedNumeric(type)) - obj = Convert.ToUInt64(value.Substring(2), 16); - else - obj = Convert.ToInt32(value.Substring(2), 16); - } - - if (obj == null && !type.IsValueType) - return null; - - return Convert.ChangeType(obj, type); - } - catch - { - return null; - } - } - - public static IEntity Build(Mobile from, ConstructorInfo ctor, object[] values, string[,] props, - PropertyInfo[] realProps, ref bool sendError) - { - object built = ctor.Invoke(values); - - if (built != null && realProps != null) - { - bool hadError = false; - - for (int i = 0; i < realProps.Length; ++i) - { - if (realProps[i] == null) - continue; - - string result = - Properties.InternalSetValue(from, built, built, realProps[i], props[i, 1], props[i, 1], false); - - if (result != "Property has been set.") - { - if (sendError) - from.SendMessage(result); - - hadError = true; - } - } - - if (hadError) - sendError = false; - } - - return (IEntity)built; - } - - public static int Build(Mobile from, Point3D start, Point3D end, ConstructorInfo ctor, object[] values, - string[,] props, PropertyInfo[] realProps, List packs, bool outline = false, bool mapAvg = false) - { - try - { - Map map = from.Map; - - int width = end.X - start.X + 1; - int height = end.Y - start.Y + 1; - - if (outline && (width < 3 || height < 3)) - outline = false; - - int objectCount; - - if (packs != null) - objectCount = packs.Count; - else if (outline) - objectCount = (width + height - 2) * 2; - else - objectCount = width * height; - - if (objectCount >= 20) - from.SendMessage("Constructing {0} objects, please wait.", objectCount); - - bool sendError = true; - - StringBuilder sb = new StringBuilder(); - sb.Append("Serials: "); - - if (packs != null) - { - for (int i = 0; i < packs.Count; ++i) - { - IEntity built = Build(from, ctor, values, props, realProps, ref sendError); - - sb.AppendFormat("0x{0:X}; ", built.Serial.Value); - - if (built is Item item) - packs[i].DropItem(item); - else if (built is Mobile m) - m.MoveToWorld(new Point3D(start.X, start.Y, start.Z), map); - } - } - else - { - int z = start.Z; - - for (int x = start.X; x <= end.X; ++x) - for (int y = start.Y; y <= end.Y; ++y) - { - if (outline && x != start.X && x != end.X && y != start.Y && y != end.Y) - continue; - - if (mapAvg) - z = map.GetAverageZ(x, y); - - IEntity built = Build(from, ctor, values, props, realProps, ref sendError); - - sb.AppendFormat("0x{0:X}; ", built.Serial.Value); - - if (built is Item item) - item.MoveToWorld(new Point3D(x, y, z), map); - else if (built is Mobile m) - m.MoveToWorld(new Point3D(x, y, z), map); - } - } - - CommandLogging.WriteLine(from, sb.ToString()); - - return objectCount; - } - catch (Exception ex) - { - Console.WriteLine(ex); - return 0; - } - } - - public static void SendUsage(Type type, Mobile from) - { - ConstructorInfo[] ctors = type.GetConstructors(); - bool foundCtor = false; - - for (int i = 0; i < ctors.Length; ++i) - { - ConstructorInfo ctor = ctors[i]; - - if (!IsConstructible(ctor, from.AccessLevel)) - continue; - - if (!foundCtor) - { - foundCtor = true; - from.SendMessage("Usage:"); - } - - SendCtor(type, ctor, from); - } - - if (!foundCtor) - from.SendMessage("That type is not marked constructible."); - } - - public static void SendCtor(Type type, ConstructorInfo ctor, Mobile from) - { - ParameterInfo[] paramList = ctor.GetParameters(); - - StringBuilder sb = new StringBuilder(); - - sb.Append(type.Name); - - for (int i = 0; i < paramList.Length; ++i) - { - if (i != 0) - sb.Append(','); - - sb.Append(' '); - - sb.Append(paramList[i].ParameterType.Name); - sb.Append(' '); - sb.Append(paramList[i].Name); - } - - from.SendMessage(sb.ToString()); - } - - private static void TileBox_Callback(Mobile from, Point3D start, Point3D end, TileState ts) - { - bool mapAvg = false; - - switch (ts.m_ZType) - { - case TileZType.Fixed: - { - start.Z = end.Z = ts.m_FixedZ; - break; - } - case TileZType.MapAverage: - { - mapAvg = true; - break; - } - } - - Invoke(from, start, end, ts.m_Args, null, ts.m_Outline, mapAvg); - } - - private static void Internal_OnCommand(CommandEventArgs e, bool outline) - { - Mobile from = e.Mobile; - - if (e.Length >= 1) - BoundingBoxPicker.Begin(from, (map, start, end) => - TileBox_Callback(from, start, end, new TileState(TileZType.Start, 0, e.Arguments, outline))); - else - from.SendMessage("Format: {0} [params] [set {{ ...}}]", - outline ? "Outline" : "Tile"); - } - - private static void InternalRXYZ_OnCommand(CommandEventArgs e, bool outline) - { - if (e.Length >= 6) - { - Point3D p = new Point3D(e.Mobile.X + e.GetInt32(0), e.Mobile.Y + e.GetInt32(1), e.Mobile.Z + e.GetInt32(4)); - Point3D p2 = new Point3D(p.X + e.GetInt32(2) - 1, p.Y + e.GetInt32(3) - 1, p.Z); - - string[] subArgs = new string[e.Length - 5]; - - for (int i = 0; i < subArgs.Length; ++i) - subArgs[i] = e.Arguments[i + 5]; - - Invoke(e.Mobile, p, p2, subArgs, null, outline); - } - else - { - e.Mobile.SendMessage( - "Format: {0}RXYZ [params] [set {{ ...}}]", - outline ? "Outline" : "Tile"); - } - } - - private static void InternalXYZ_OnCommand(CommandEventArgs e, bool outline) - { - if (e.Length >= 6) - { - Point3D p = new Point3D(e.GetInt32(0), e.GetInt32(1), e.GetInt32(4)); - Point3D p2 = new Point3D(p.X + e.GetInt32(2) - 1, p.Y + e.GetInt32(3) - 1, e.GetInt32(4)); - - string[] subArgs = new string[e.Length - 5]; - - for (int i = 0; i < subArgs.Length; ++i) - subArgs[i] = e.Arguments[i + 5]; - - Invoke(e.Mobile, p, p2, subArgs, null, outline); - } - else - { - e.Mobile.SendMessage( - "Format: {0}XYZ [params] [set {{ ...}}]", - outline ? "Outline" : "Tile"); - } - } - - private static void InternalZ_OnCommand(CommandEventArgs e, bool outline) - { - Mobile from = e.Mobile; - - if (e.Length >= 2) - { - string[] subArgs = new string[e.Length - 1]; - - for (int i = 0; i < subArgs.Length; ++i) - subArgs[i] = e.Arguments[i + 1]; - - BoundingBoxPicker.Begin(from, (map, start, end) => - TileBox_Callback(from, start, end, new TileState(TileZType.Fixed, e.GetInt32(0), subArgs, outline))); - } - else - { - from.SendMessage("Format: {0}Z [params] [set {{ ...}}]", - outline ? "Outline" : "Tile"); - } - } - - private static void InternalAvg_OnCommand(CommandEventArgs e, bool outline) - { - Mobile from = e.Mobile; - - if (e.Length >= 1) - BoundingBoxPicker.Begin(from, (map, start, end) => - TileBox_Callback(from, start, end, new TileState(TileZType.MapAverage, 0, e.Arguments, outline))); - else - from.SendMessage("Format: {0}Avg [params] [set {{ ...}}]", - outline ? "Outline" : "Tile"); - } - - [Usage("Tile [params] [set { ...}]")] - [Description( - "Tiles an item or npc by name into a targeted bounding box. Optional constructor parameters. Optional set property list.")] - public static void Tile_OnCommand(CommandEventArgs e) - { - Internal_OnCommand(e, false); - } - - [Usage("TileRXYZ [params] [set { ...}]")] - [Description( - "Tiles an item or npc by name into a given bounding box, (x, y) parameters are relative to your characters position. Optional constructor parameters. Optional set property list.")] - public static void TileRXYZ_OnCommand(CommandEventArgs e) - { - InternalRXYZ_OnCommand(e, false); - } - - [Usage("TileXYZ [params] [set { ...}]")] - [Description( - "Tiles an item or npc by name into a given bounding box. Optional constructor parameters. Optional set property list.")] - public static void TileXYZ_OnCommand(CommandEventArgs e) - { - InternalXYZ_OnCommand(e, false); - } - - [Usage("TileZ [params] [set { ...}]")] - [Description( - "Tiles an item or npc by name into a targeted bounding box at a fixed Z location. Optional constructor parameters. Optional set property list.")] - public static void TileZ_OnCommand(CommandEventArgs e) - { - InternalZ_OnCommand(e, false); - } - - [Usage("TileAvg [params] [set { ...}]")] - [Description( - "Tiles an item or npc by name into a targeted bounding box on the map's average Z elevation. Optional constructor parameters. Optional set property list.")] - public static void TileAvg_OnCommand(CommandEventArgs e) - { - InternalAvg_OnCommand(e, false); - } - - [Usage("Outline [params] [set { ...}]")] - [Description( - "Tiles an item or npc by name around a targeted bounding box. Optional constructor parameters. Optional set property list.")] - public static void Outline_OnCommand(CommandEventArgs e) - { - Internal_OnCommand(e, true); - } - - [Usage("OutlineRXYZ [params] [set { ...}]")] - [Description( - "Tiles an item or npc by name around a given bounding box, (x, y) parameters are relative to your characters position. Optional constructor parameters. Optional set property list.")] - public static void OutlineRXYZ_OnCommand(CommandEventArgs e) - { - InternalRXYZ_OnCommand(e, true); - } - - [Usage("OutlineXYZ [params] [set { ...}]")] - [Description( - "Tiles an item or npc by name around a given bounding box. Optional constructor parameters. Optional set property list.")] - public static void OutlineXYZ_OnCommand(CommandEventArgs e) - { - InternalXYZ_OnCommand(e, true); - } - - [Usage("OutlineZ [params] [set { ...}]")] - [Description( - "Tiles an item or npc by name around a targeted bounding box at a fixed Z location. Optional constructor parameters. Optional set property list.")] - public static void OutlineZ_OnCommand(CommandEventArgs e) - { - InternalZ_OnCommand(e, true); - } - - [Usage("OutlineAvg [params] [set { ...}]")] - [Description( - "Tiles an item or npc by name around a targeted bounding box on the map's average Z elevation. Optional constructor parameters. Optional set property list.")] - public static void OutlineAvg_OnCommand(CommandEventArgs e) - { - InternalAvg_OnCommand(e, true); - } - - public static bool IsEntity(Type t) => m_EntityType.IsAssignableFrom(t); - - public static bool IsConstructible(ConstructorInfo ctor, AccessLevel accessLevel) - { - object[] attrs = ctor.GetCustomAttributes(m_ConstructibleType, false); - - return attrs.Length != 0 && accessLevel >= ((ConstructibleAttribute)attrs[0]).AccessLevel; - } - - public static bool IsEnum(Type type) => type.IsSubclassOf(m_EnumType); - - public static bool IsType(Type type) => type == m_TypeType || type.IsSubclassOf(m_TypeType); - - public static bool IsParsable(Type type) => type.IsDefined(m_ParsableType, false); - - public static object ParseParsable(Type type, string value) - { - MethodInfo method = type.GetMethod("Parse", m_ParseTypes); - - m_ParseArgs[0] = value; - - return method?.Invoke(null, m_ParseArgs); - } - - public static bool IsSignedNumeric(Type type) - { - for (int i = 0; i < m_SignedNumerics.Length; ++i) - if (type == m_SignedNumerics[i]) - return true; - - return false; - } - - public static bool IsUnsignedNumeric(Type type) - { - for (int i = 0; i < m_UnsignedNumerics.Length; ++i) - if (type == m_UnsignedNumerics[i]) - return true; - - return false; - } - - private enum TileZType - { - Start, - Fixed, - MapAverage - } - - private class TileState - { - public readonly string[] m_Args; - public readonly int m_FixedZ; - public readonly bool m_Outline; - public readonly TileZType m_ZType; - - public TileState(TileZType zType, int fixedZ, string[] args, bool outline) - { - m_ZType = zType; - m_FixedZ = fixedZ; - m_Args = args; - m_Outline = outline; - } - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using Server.Items; +using CPA = Server.CommandPropertyAttribute; + +namespace Server.Commands +{ + public class Add + { + private static readonly Type m_EntityType = typeof(IEntity); + + private static readonly Type m_ConstructibleType = typeof(ConstructibleAttribute); + + private static readonly Type m_EnumType = typeof(Enum); + + private static readonly Type m_TypeType = typeof(Type); + + private static readonly Type m_ParsableType = typeof(ParsableAttribute); + + private static readonly Type[] m_ParseTypes = { typeof(string) }; + private static readonly object[] m_ParseArgs = new object[1]; + + private static readonly Type[] m_SignedNumerics = + { + typeof(long), + typeof(int), + typeof(short), + typeof(sbyte) + }; + + private static readonly Type[] m_UnsignedNumerics = + { + typeof(ulong), + typeof(uint), + typeof(ushort), + typeof(byte) + }; + + public static void Initialize() + { + CommandSystem.Register("Tile", AccessLevel.GameMaster, Tile_OnCommand); + CommandSystem.Register("TileRXYZ", AccessLevel.GameMaster, TileRXYZ_OnCommand); + CommandSystem.Register("TileXYZ", AccessLevel.GameMaster, TileXYZ_OnCommand); + CommandSystem.Register("TileZ", AccessLevel.GameMaster, TileZ_OnCommand); + CommandSystem.Register("TileAvg", AccessLevel.GameMaster, TileAvg_OnCommand); + + CommandSystem.Register("Outline", AccessLevel.GameMaster, Outline_OnCommand); + CommandSystem.Register("OutlineRXYZ", AccessLevel.GameMaster, OutlineRXYZ_OnCommand); + CommandSystem.Register("OutlineXYZ", AccessLevel.GameMaster, OutlineXYZ_OnCommand); + CommandSystem.Register("OutlineZ", AccessLevel.GameMaster, OutlineZ_OnCommand); + CommandSystem.Register("OutlineAvg", AccessLevel.GameMaster, OutlineAvg_OnCommand); + } + + public static void Invoke( + Mobile from, Point3D start, Point3D end, string[] args, List packs = null, + bool outline = false, bool mapAvg = false + ) + { + var sb = new StringBuilder(); + + sb.AppendFormat("{0} {1} building ", from.AccessLevel, CommandLogging.Format(from)); + + if (start == end) + sb.AppendFormat("at {0} in {1}", start, from.Map); + else + sb.AppendFormat("from {0} to {1} in {2}", start, end, from.Map); + + sb.Append(":"); + + for (var i = 0; i < args.Length; ++i) + sb.AppendFormat(" \"{0}\"", args[i]); + + CommandLogging.WriteLine(from, sb.ToString()); + + var name = args[0]; + + FixArgs(ref args); + + string[,] props = null; + + for (var i = 0; i < args.Length; ++i) + if (Insensitive.Equals(args[i], "set")) + { + var remains = args.Length - i - 1; + + if (remains >= 2) + { + props = new string[remains / 2, 2]; + + remains /= 2; + + for (var j = 0; j < remains; ++j) + { + props[j, 0] = args[i + j * 2 + 1]; + props[j, 1] = args[i + j * 2 + 2]; + } + + FixSetString(ref args, i); + } + + break; + } + + var type = AssemblyHandler.FindFirstTypeForName(name); + + if (!IsEntity(type)) + { + from.SendMessage("No type with that name was found."); + return; + } + + var time = DateTime.UtcNow; + + var built = BuildObjects(from, type, start, end, args, props, packs, outline, mapAvg); + + if (built > 0) + from.SendMessage( + "{0} object{1} generated in {2:F1} seconds.", + built, + built != 1 ? "s" : "", + (DateTime.UtcNow - time).TotalSeconds + ); + else + SendUsage(type, from); + } + + public static void FixSetString(ref string[] args, int index) + { + var old = args; + args = new string[index]; + + Array.Copy(old, 0, args, 0, index); + } + + public static void FixArgs(ref string[] args) + { + var old = args; + args = new string[args.Length - 1]; + + Array.Copy(old, 1, args, 0, args.Length); + } + + public static int BuildObjects( + Mobile from, Type type, Point3D start, Point3D end, string[] args, string[,] props, + List packs, bool outline = false, bool mapAvg = false + ) + { + Utility.FixPoints(ref start, ref end); + + PropertyInfo[] realProps = null; + + if (props != null) + { + realProps = new PropertyInfo[props.GetLength(0)]; + + var allProps = + type.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public); + + for (var i = 0; i < realProps.Length; ++i) + { + PropertyInfo thisProp = null; + + var propName = props[i, 0]; + + for (var j = 0; thisProp == null && j < allProps.Length; ++j) + if (Insensitive.Equals(propName, allProps[j].Name)) + thisProp = allProps[j]; + + if (thisProp == null) + { + from.SendMessage("Property not found: {0}", propName); + } + else + { + var attr = Properties.GetCPA(thisProp); + + if (attr == null) + from.SendMessage("Property ({0}) not found.", propName); + else if (from.AccessLevel < attr.WriteLevel) + from.SendMessage( + "Setting this property ({0}) requires at least {1} access level.", + propName, + Mobile.GetAccessLevelName(attr.WriteLevel) + ); + else if (!thisProp.CanWrite || attr.ReadOnly) + from.SendMessage("Property ({0}) is read only.", propName); + else + realProps[i] = thisProp; + } + } + } + + var ctors = type.GetConstructors(); + + for (var i = 0; i < ctors.Length; ++i) + { + var ctor = ctors[i]; + + if (!IsConstructible(ctor, from.AccessLevel)) + continue; + + // Handle optional constructors + var paramList = ctor.GetParameters(); + var totalParams = paramList.Count(t => !t.HasDefaultValue); + + if (args.Length >= totalParams && args.Length <= paramList.Length) + { + var paramValues = ParseValues(paramList, args); + + if (paramValues == null) + continue; + + var built = Build(from, start, end, ctor, paramValues, props, realProps, packs, outline, mapAvg); + + if (built > 0) + return built; + } + } + + return 0; + } + + public static object[] ParseValues(ParameterInfo[] paramList, string[] args) + { + var values = new object[paramList.Length]; + + for (int i = 0, a = 0; i < paramList.Length; i++) + { + var param = paramList[i]; + var value = ParseValue(param.ParameterType, a < args.Length ? args[a++] : null); + + if (value != null) + values[i] = value; + else if (param.HasDefaultValue) + values[i] = Type.Missing; + else + return null; + } + + return values; + } + + public static object ParseValue(Type type, string value) + { + try + { + if (IsEnum(type)) return Enum.Parse(type, value, true); + if (IsType(type)) return AssemblyHandler.FindFirstTypeForName(value); + if (IsParsable(type)) return ParseParsable(type, value); + object obj = value; + + if (value?.StartsWith("0x") == true) + { + if (IsSignedNumeric(type)) + obj = Convert.ToInt64(value.Substring(2), 16); + else if (IsUnsignedNumeric(type)) + obj = Convert.ToUInt64(value.Substring(2), 16); + else + obj = Convert.ToInt32(value.Substring(2), 16); + } + + if (obj == null && !type.IsValueType) + return null; + + return Convert.ChangeType(obj, type); + } + catch + { + return null; + } + } + + public static IEntity Build( + Mobile from, ConstructorInfo ctor, object[] values, string[,] props, + PropertyInfo[] realProps, ref bool sendError + ) + { + var built = ctor.Invoke(values); + + if (built != null && realProps != null) + { + var hadError = false; + + for (var i = 0; i < realProps.Length; ++i) + { + if (realProps[i] == null) + continue; + + var result = + Properties.InternalSetValue(from, built, built, realProps[i], props[i, 1], props[i, 1], false); + + if (result != "Property has been set.") + { + if (sendError) + from.SendMessage(result); + + hadError = true; + } + } + + if (hadError) + sendError = false; + } + + return (IEntity)built; + } + + public static int Build( + Mobile from, Point3D start, Point3D end, ConstructorInfo ctor, object[] values, + string[,] props, PropertyInfo[] realProps, List packs, bool outline = false, bool mapAvg = false + ) + { + try + { + var map = from.Map; + + var width = end.X - start.X + 1; + var height = end.Y - start.Y + 1; + + if (outline && (width < 3 || height < 3)) + outline = false; + + int objectCount; + + if (packs != null) + objectCount = packs.Count; + else if (outline) + objectCount = (width + height - 2) * 2; + else + objectCount = width * height; + + if (objectCount >= 20) + from.SendMessage("Constructing {0} objects, please wait.", objectCount); + + var sendError = true; + + var sb = new StringBuilder(); + sb.Append("Serials: "); + + if (packs != null) + { + for (var i = 0; i < packs.Count; ++i) + { + var built = Build(from, ctor, values, props, realProps, ref sendError); + + sb.AppendFormat("0x{0:X}; ", built.Serial.Value); + + if (built is Item item) + packs[i].DropItem(item); + else if (built is Mobile m) + m.MoveToWorld(new Point3D(start.X, start.Y, start.Z), map); + } + } + else + { + var z = start.Z; + + for (var x = start.X; x <= end.X; ++x) + for (var y = start.Y; y <= end.Y; ++y) + { + if (outline && x != start.X && x != end.X && y != start.Y && y != end.Y) + continue; + + if (mapAvg) + z = map.GetAverageZ(x, y); + + var built = Build(from, ctor, values, props, realProps, ref sendError); + + sb.AppendFormat("0x{0:X}; ", built.Serial.Value); + + if (built is Item item) + item.MoveToWorld(new Point3D(x, y, z), map); + else if (built is Mobile m) + m.MoveToWorld(new Point3D(x, y, z), map); + } + } + + CommandLogging.WriteLine(from, sb.ToString()); + + return objectCount; + } + catch (Exception ex) + { + Console.WriteLine(ex); + return 0; + } + } + + public static void SendUsage(Type type, Mobile from) + { + var ctors = type.GetConstructors(); + var foundCtor = false; + + for (var i = 0; i < ctors.Length; ++i) + { + var ctor = ctors[i]; + + if (!IsConstructible(ctor, from.AccessLevel)) + continue; + + if (!foundCtor) + { + foundCtor = true; + from.SendMessage("Usage:"); + } + + SendCtor(type, ctor, from); + } + + if (!foundCtor) + from.SendMessage("That type is not marked constructible."); + } + + public static void SendCtor(Type type, ConstructorInfo ctor, Mobile from) + { + var paramList = ctor.GetParameters(); + + var sb = new StringBuilder(); + + sb.Append(type.Name); + + for (var i = 0; i < paramList.Length; ++i) + { + if (i != 0) + sb.Append(','); + + sb.Append(' '); + + sb.Append(paramList[i].ParameterType.Name); + sb.Append(' '); + sb.Append(paramList[i].Name); + } + + from.SendMessage(sb.ToString()); + } + + private static void TileBox_Callback(Mobile from, Point3D start, Point3D end, TileState ts) + { + var mapAvg = false; + + switch (ts.m_ZType) + { + case TileZType.Fixed: + { + start.Z = end.Z = ts.m_FixedZ; + break; + } + case TileZType.MapAverage: + { + mapAvg = true; + break; + } + } + + Invoke(from, start, end, ts.m_Args, null, ts.m_Outline, mapAvg); + } + + private static void Internal_OnCommand(CommandEventArgs e, bool outline) + { + var from = e.Mobile; + + if (e.Length >= 1) + BoundingBoxPicker.Begin( + from, + (map, start, end) => + TileBox_Callback(from, start, end, new TileState(TileZType.Start, 0, e.Arguments, outline)) + ); + else + from.SendMessage( + "Format: {0} [params] [set {{ ...}}]", + outline ? "Outline" : "Tile" + ); + } + + private static void InternalRXYZ_OnCommand(CommandEventArgs e, bool outline) + { + if (e.Length >= 6) + { + var p = new Point3D(e.Mobile.X + e.GetInt32(0), e.Mobile.Y + e.GetInt32(1), e.Mobile.Z + e.GetInt32(4)); + var p2 = new Point3D(p.X + e.GetInt32(2) - 1, p.Y + e.GetInt32(3) - 1, p.Z); + + var subArgs = new string[e.Length - 5]; + + for (var i = 0; i < subArgs.Length; ++i) + subArgs[i] = e.Arguments[i + 5]; + + Invoke(e.Mobile, p, p2, subArgs, null, outline); + } + else + { + e.Mobile.SendMessage( + "Format: {0}RXYZ [params] [set {{ ...}}]", + outline ? "Outline" : "Tile" + ); + } + } + + private static void InternalXYZ_OnCommand(CommandEventArgs e, bool outline) + { + if (e.Length >= 6) + { + var p = new Point3D(e.GetInt32(0), e.GetInt32(1), e.GetInt32(4)); + var p2 = new Point3D(p.X + e.GetInt32(2) - 1, p.Y + e.GetInt32(3) - 1, e.GetInt32(4)); + + var subArgs = new string[e.Length - 5]; + + for (var i = 0; i < subArgs.Length; ++i) + subArgs[i] = e.Arguments[i + 5]; + + Invoke(e.Mobile, p, p2, subArgs, null, outline); + } + else + { + e.Mobile.SendMessage( + "Format: {0}XYZ [params] [set {{ ...}}]", + outline ? "Outline" : "Tile" + ); + } + } + + private static void InternalZ_OnCommand(CommandEventArgs e, bool outline) + { + var from = e.Mobile; + + if (e.Length >= 2) + { + var subArgs = new string[e.Length - 1]; + + for (var i = 0; i < subArgs.Length; ++i) + subArgs[i] = e.Arguments[i + 1]; + + BoundingBoxPicker.Begin( + from, + (map, start, end) => + TileBox_Callback(from, start, end, new TileState(TileZType.Fixed, e.GetInt32(0), subArgs, outline)) + ); + } + else + { + from.SendMessage( + "Format: {0}Z [params] [set {{ ...}}]", + outline ? "Outline" : "Tile" + ); + } + } + + private static void InternalAvg_OnCommand(CommandEventArgs e, bool outline) + { + var from = e.Mobile; + + if (e.Length >= 1) + BoundingBoxPicker.Begin( + from, + (map, start, end) => + TileBox_Callback(from, start, end, new TileState(TileZType.MapAverage, 0, e.Arguments, outline)) + ); + else + from.SendMessage( + "Format: {0}Avg [params] [set {{ ...}}]", + outline ? "Outline" : "Tile" + ); + } + + [Usage("Tile [params] [set { ...}]")] + [Description( + "Tiles an item or npc by name into a targeted bounding box. Optional constructor parameters. Optional set property list." + )] + public static void Tile_OnCommand(CommandEventArgs e) + { + Internal_OnCommand(e, false); + } + + [Usage("TileRXYZ [params] [set { ...}]")] + [Description( + "Tiles an item or npc by name into a given bounding box, (x, y) parameters are relative to your characters position. Optional constructor parameters. Optional set property list." + )] + public static void TileRXYZ_OnCommand(CommandEventArgs e) + { + InternalRXYZ_OnCommand(e, false); + } + + [Usage("TileXYZ [params] [set { ...}]")] + [Description( + "Tiles an item or npc by name into a given bounding box. Optional constructor parameters. Optional set property list." + )] + public static void TileXYZ_OnCommand(CommandEventArgs e) + { + InternalXYZ_OnCommand(e, false); + } + + [Usage("TileZ [params] [set { ...}]")] + [Description( + "Tiles an item or npc by name into a targeted bounding box at a fixed Z location. Optional constructor parameters. Optional set property list." + )] + public static void TileZ_OnCommand(CommandEventArgs e) + { + InternalZ_OnCommand(e, false); + } + + [Usage("TileAvg [params] [set { ...}]")] + [Description( + "Tiles an item or npc by name into a targeted bounding box on the map's average Z elevation. Optional constructor parameters. Optional set property list." + )] + public static void TileAvg_OnCommand(CommandEventArgs e) + { + InternalAvg_OnCommand(e, false); + } + + [Usage("Outline [params] [set { ...}]")] + [Description( + "Tiles an item or npc by name around a targeted bounding box. Optional constructor parameters. Optional set property list." + )] + public static void Outline_OnCommand(CommandEventArgs e) + { + Internal_OnCommand(e, true); + } + + [Usage("OutlineRXYZ [params] [set { ...}]")] + [Description( + "Tiles an item or npc by name around a given bounding box, (x, y) parameters are relative to your characters position. Optional constructor parameters. Optional set property list." + )] + public static void OutlineRXYZ_OnCommand(CommandEventArgs e) + { + InternalRXYZ_OnCommand(e, true); + } + + [Usage("OutlineXYZ [params] [set { ...}]")] + [Description( + "Tiles an item or npc by name around a given bounding box. Optional constructor parameters. Optional set property list." + )] + public static void OutlineXYZ_OnCommand(CommandEventArgs e) + { + InternalXYZ_OnCommand(e, true); + } + + [Usage("OutlineZ [params] [set { ...}]")] + [Description( + "Tiles an item or npc by name around a targeted bounding box at a fixed Z location. Optional constructor parameters. Optional set property list." + )] + public static void OutlineZ_OnCommand(CommandEventArgs e) + { + InternalZ_OnCommand(e, true); + } + + [Usage("OutlineAvg [params] [set { ...}]")] + [Description( + "Tiles an item or npc by name around a targeted bounding box on the map's average Z elevation. Optional constructor parameters. Optional set property list." + )] + public static void OutlineAvg_OnCommand(CommandEventArgs e) + { + InternalAvg_OnCommand(e, true); + } + + public static bool IsEntity(Type t) => m_EntityType.IsAssignableFrom(t); + + public static bool IsConstructible(ConstructorInfo ctor, AccessLevel accessLevel) + { + var attrs = ctor.GetCustomAttributes(m_ConstructibleType, false); + + return attrs.Length != 0 && accessLevel >= ((ConstructibleAttribute)attrs[0]).AccessLevel; + } + + public static bool IsEnum(Type type) => type.IsSubclassOf(m_EnumType); + + public static bool IsType(Type type) => type == m_TypeType || type.IsSubclassOf(m_TypeType); + + public static bool IsParsable(Type type) => type.IsDefined(m_ParsableType, false); + + public static object ParseParsable(Type type, string value) + { + var method = type.GetMethod("Parse", m_ParseTypes); + + m_ParseArgs[0] = value; + + return method?.Invoke(null, m_ParseArgs); + } + + public static bool IsSignedNumeric(Type type) + { + for (var i = 0; i < m_SignedNumerics.Length; ++i) + if (type == m_SignedNumerics[i]) + return true; + + return false; + } + + public static bool IsUnsignedNumeric(Type type) + { + for (var i = 0; i < m_UnsignedNumerics.Length; ++i) + if (type == m_UnsignedNumerics[i]) + return true; + + return false; + } + + private enum TileZType + { + Start, + Fixed, + MapAverage + } + + private class TileState + { + public readonly string[] m_Args; + public readonly int m_FixedZ; + public readonly bool m_Outline; + public readonly TileZType m_ZType; + + public TileState(TileZType zType, int fixedZ, string[] args, bool outline) + { + m_ZType = zType; + m_FixedZ = fixedZ; + m_Args = args; + m_Outline = outline; + } + } + } +} diff --git a/Projects/UOContent/Commands/Object Creation/AddGump.cs b/Projects/UOContent/Commands/Object Creation/AddGump.cs index 7ee95839a..5b7b7fc44 100644 --- a/Projects/UOContent/Commands/Object Creation/AddGump.cs +++ b/Projects/UOContent/Commands/Object Creation/AddGump.cs @@ -1,250 +1,265 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using Server.Network; -using Server.Targeting; - -namespace Server.Gumps -{ - public class AddGump : Gump - { - private static readonly Type typeofItem = typeof(Item); - private static readonly Type typeofMobile = typeof(Mobile); - private readonly int m_Page; - private readonly Type[] m_SearchResults; - private readonly string m_SearchString; - - public AddGump(Mobile from, string searchString, int page, Type[] searchResults, bool explicitSearch) : base(50, 50) - { - m_SearchString = searchString; - m_SearchResults = searchResults; - m_Page = page; - - from.CloseGump(); - - AddPage(0); - - AddBackground(0, 0, 420, 280, 5054); - - AddImageTiled(10, 10, 400, 20, 2624); - AddAlphaRegion(10, 10, 400, 20); - AddImageTiled(41, 11, 184, 18, 0xBBC); - AddImageTiled(42, 12, 182, 16, 2624); - AddAlphaRegion(42, 12, 182, 16); - - AddButton(10, 9, 4011, 4013, 1); - AddTextEntry(44, 10, 180, 20, 0x480, 0, searchString); - - AddHtmlLocalized(230, 10, 100, 20, 3010005, 0x7FFF); - - AddImageTiled(10, 40, 400, 200, 2624); - AddAlphaRegion(10, 40, 400, 200); - - if (searchResults.Length > 0) - for (int i = page * 10; i < (page + 1) * 10 && i < searchResults.Length; ++i) - { - int index = i % 10; - - AddLabel(44, 39 + index * 20, 0x480, searchResults[i].Name); - AddButton(10, 39 + index * 20, 4023, 4025, 4 + i); - } - else - AddLabel(15, 44, 0x480, explicitSearch ? "Nothing matched your search terms." : "No results to display."); - - AddImageTiled(10, 250, 400, 20, 2624); - AddAlphaRegion(10, 250, 400, 20); - - if (m_Page > 0) - AddButton(10, 249, 4014, 4016, 2); - else - AddImage(10, 249, 4014); - - AddHtmlLocalized(44, 250, 170, 20, 1061028, m_Page > 0 ? 0x7FFF : 0x5EF7); // Previous page - - if ((m_Page + 1) * 10 < searchResults.Length) - AddButton(210, 249, 4005, 4007, 3); - else - AddImage(210, 249, 4005); - - AddHtmlLocalized(244, 250, 170, 20, 1061027, (m_Page + 1) * 10 < searchResults.Length ? 0x7FFF : 0x5EF7); // Next page - } - - public static void Initialize() - { - CommandSystem.Register("AddMenu", AccessLevel.GameMaster, AddMenu_OnCommand); - } - - [Usage("AddMenu [searchString]")] - [Description( - "Opens an add menu, with an optional initial search string. This menu allows you to search for Items or Mobiles and add them interactively.")] - private static void AddMenu_OnCommand(CommandEventArgs e) - { - string val = e.ArgString.Trim(); - Type[] types; - bool explicitSearch = false; - - if (val.Length == 0) - { - types = Type.EmptyTypes; - } - else if (val.Length < 3) - { - e.Mobile.SendMessage("Invalid search string."); - types = Type.EmptyTypes; - } - else - { - types = Match(val).ToArray(); - explicitSearch = true; - } - - e.Mobile.SendGump(new AddGump(e.Mobile, val, 0, types, explicitSearch)); - } - - private static void Match(string match, Type[] types, List results) - { - if (match.Length == 0) - return; - - match = match.ToLower(); - - for (int i = 0; i < types.Length; ++i) - { - Type t = types[i]; - - if ((typeofMobile.IsAssignableFrom(t) || typeofItem.IsAssignableFrom(t)) && - t.Name.ToLower().IndexOf(match) >= 0 && !results.Contains(t)) - { - ConstructorInfo[] ctors = t.GetConstructors(); - - for (int j = 0; j < ctors.Length; ++j) - if (ctors[j].GetParameters().Length == 0 && - ctors[j].IsDefined(typeof(ConstructibleAttribute), false)) - { - results.Add(t); - break; - } - } - } - } - - public static List Match(string match) - { - List results = new List(); - Type[] types; - - Assembly[] asms = AssemblyHandler.Assemblies; - - for (int i = 0; i < asms.Length; ++i) - { - types = AssemblyHandler.GetTypeCache(asms[i]).Types.ToArray(); - Match(match, types, results); - } - - types = AssemblyHandler.GetTypeCache(Core.Assembly).Types.ToArray(); - Match(match, types, results); - - results.Sort(new TypeNameComparer()); - - return results; - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - Mobile from = sender.Mobile; - - switch (info.ButtonID) - { - case 1: // Search - { - TextRelay te = info.GetTextEntry(0); - string match = te?.Text.Trim() ?? ""; - - if (match.Length < 3) - { - from.SendMessage("Invalid search string."); - from.SendGump(new AddGump(from, match, m_Page, m_SearchResults, false)); - } - else - { - from.SendGump(new AddGump(from, match, 0, Match(match).ToArray(), true)); - } - - break; - } - case 2: // Previous page - { - if (m_Page > 0) - from.SendGump(new AddGump(from, m_SearchString, m_Page - 1, m_SearchResults, true)); - - break; - } - case 3: // Next page - { - if ((m_Page + 1) * 10 < m_SearchResults.Length) - from.SendGump(new AddGump(from, m_SearchString, m_Page + 1, m_SearchResults, true)); - - break; - } - default: - { - int index = info.ButtonID - 4; - - if (index >= 0 && index < m_SearchResults.Length) - { - from.SendMessage("Where do you wish to place this object? to cancel."); - from.Target = new InternalTarget(m_SearchResults[index], m_SearchResults, m_SearchString, m_Page); - } - - break; - } - } - } - - private class TypeNameComparer : IComparer - { - public int Compare(Type x, Type y) => x?.Name.CompareTo(y?.Name) ?? 1; - } - - public class InternalTarget : Target - { - private readonly int m_Page; - private readonly Type[] m_SearchResults; - private readonly string m_SearchString; - private readonly Type m_Type; - - public InternalTarget(Type type, Type[] searchResults, string searchString, int page) : base(-1, true, - TargetFlags.None) - { - m_Type = type; - m_SearchResults = searchResults; - m_SearchString = searchString; - m_Page = page; - } - - protected override void OnTarget(Mobile from, object o) - { - if (o is IPoint3D p) - { - p = p switch - { - Item item => item.GetWorldTop(), - Mobile m => m.Location, - _ => p - }; - - Commands.Add.Invoke(from, new Point3D(p), new Point3D(p), new[] { m_Type.Name }); - - from.Target = new InternalTarget(m_Type, m_SearchResults, m_SearchString, m_Page); - } - } - - protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType) - { - if (cancelType == TargetCancelType.Canceled) - from.SendGump(new AddGump(from, m_SearchString, m_Page, m_SearchResults, true)); - } - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using Server.Network; +using Server.Targeting; + +namespace Server.Gumps +{ + public class AddGump : Gump + { + private static readonly Type typeofItem = typeof(Item); + private static readonly Type typeofMobile = typeof(Mobile); + private readonly int m_Page; + private readonly Type[] m_SearchResults; + private readonly string m_SearchString; + + public AddGump(Mobile from, string searchString, int page, Type[] searchResults, bool explicitSearch) : base(50, 50) + { + m_SearchString = searchString; + m_SearchResults = searchResults; + m_Page = page; + + from.CloseGump(); + + AddPage(0); + + AddBackground(0, 0, 420, 280, 5054); + + AddImageTiled(10, 10, 400, 20, 2624); + AddAlphaRegion(10, 10, 400, 20); + AddImageTiled(41, 11, 184, 18, 0xBBC); + AddImageTiled(42, 12, 182, 16, 2624); + AddAlphaRegion(42, 12, 182, 16); + + AddButton(10, 9, 4011, 4013, 1); + AddTextEntry(44, 10, 180, 20, 0x480, 0, searchString); + + AddHtmlLocalized(230, 10, 100, 20, 3010005, 0x7FFF); + + AddImageTiled(10, 40, 400, 200, 2624); + AddAlphaRegion(10, 40, 400, 200); + + if (searchResults.Length > 0) + for (var i = page * 10; i < (page + 1) * 10 && i < searchResults.Length; ++i) + { + var index = i % 10; + + AddLabel(44, 39 + index * 20, 0x480, searchResults[i].Name); + AddButton(10, 39 + index * 20, 4023, 4025, 4 + i); + } + else + AddLabel(15, 44, 0x480, explicitSearch ? "Nothing matched your search terms." : "No results to display."); + + AddImageTiled(10, 250, 400, 20, 2624); + AddAlphaRegion(10, 250, 400, 20); + + if (m_Page > 0) + AddButton(10, 249, 4014, 4016, 2); + else + AddImage(10, 249, 4014); + + AddHtmlLocalized(44, 250, 170, 20, 1061028, m_Page > 0 ? 0x7FFF : 0x5EF7); // Previous page + + if ((m_Page + 1) * 10 < searchResults.Length) + AddButton(210, 249, 4005, 4007, 3); + else + AddImage(210, 249, 4005); + + AddHtmlLocalized( + 244, + 250, + 170, + 20, + 1061027, + (m_Page + 1) * 10 < searchResults.Length ? 0x7FFF : 0x5EF7 + ); // Next page + } + + public static void Initialize() + { + CommandSystem.Register("AddMenu", AccessLevel.GameMaster, AddMenu_OnCommand); + } + + [Usage("AddMenu [searchString]")] + [Description( + "Opens an add menu, with an optional initial search string. This menu allows you to search for Items or Mobiles and add them interactively." + )] + private static void AddMenu_OnCommand(CommandEventArgs e) + { + var val = e.ArgString.Trim(); + Type[] types; + var explicitSearch = false; + + if (val.Length == 0) + { + types = Type.EmptyTypes; + } + else if (val.Length < 3) + { + e.Mobile.SendMessage("Invalid search string."); + types = Type.EmptyTypes; + } + else + { + types = Match(val).ToArray(); + explicitSearch = true; + } + + e.Mobile.SendGump(new AddGump(e.Mobile, val, 0, types, explicitSearch)); + } + + private static void Match(string match, Type[] types, List results) + { + if (match.Length == 0) + return; + + match = match.ToLower(); + + for (var i = 0; i < types.Length; ++i) + { + var t = types[i]; + + if ((typeofMobile.IsAssignableFrom(t) || typeofItem.IsAssignableFrom(t)) && + t.Name.ToLower().IndexOf(match) >= 0 && !results.Contains(t)) + { + var ctors = t.GetConstructors(); + + for (var j = 0; j < ctors.Length; ++j) + if (ctors[j].GetParameters().Length == 0 && + ctors[j].IsDefined(typeof(ConstructibleAttribute), false)) + { + results.Add(t); + break; + } + } + } + } + + public static List Match(string match) + { + var results = new List(); + Type[] types; + + var asms = AssemblyHandler.Assemblies; + + for (var i = 0; i < asms.Length; ++i) + { + types = AssemblyHandler.GetTypeCache(asms[i]).Types.ToArray(); + Match(match, types, results); + } + + types = AssemblyHandler.GetTypeCache(Core.Assembly).Types.ToArray(); + Match(match, types, results); + + results.Sort(new TypeNameComparer()); + + return results; + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var from = sender.Mobile; + + switch (info.ButtonID) + { + case 1: // Search + { + var te = info.GetTextEntry(0); + var match = te?.Text.Trim() ?? ""; + + if (match.Length < 3) + { + from.SendMessage("Invalid search string."); + from.SendGump(new AddGump(from, match, m_Page, m_SearchResults, false)); + } + else + { + from.SendGump(new AddGump(from, match, 0, Match(match).ToArray(), true)); + } + + break; + } + case 2: // Previous page + { + if (m_Page > 0) + from.SendGump(new AddGump(from, m_SearchString, m_Page - 1, m_SearchResults, true)); + + break; + } + case 3: // Next page + { + if ((m_Page + 1) * 10 < m_SearchResults.Length) + from.SendGump(new AddGump(from, m_SearchString, m_Page + 1, m_SearchResults, true)); + + break; + } + default: + { + var index = info.ButtonID - 4; + + if (index >= 0 && index < m_SearchResults.Length) + { + from.SendMessage("Where do you wish to place this object? to cancel."); + from.Target = new InternalTarget( + m_SearchResults[index], + m_SearchResults, + m_SearchString, + m_Page + ); + } + + break; + } + } + } + + private class TypeNameComparer : IComparer + { + public int Compare(Type x, Type y) => x?.Name.CompareTo(y?.Name) ?? 1; + } + + public class InternalTarget : Target + { + private readonly int m_Page; + private readonly Type[] m_SearchResults; + private readonly string m_SearchString; + private readonly Type m_Type; + + public InternalTarget(Type type, Type[] searchResults, string searchString, int page) : base( + -1, + true, + TargetFlags.None + ) + { + m_Type = type; + m_SearchResults = searchResults; + m_SearchString = searchString; + m_Page = page; + } + + protected override void OnTarget(Mobile from, object o) + { + if (o is IPoint3D p) + { + p = p switch + { + Item item => item.GetWorldTop(), + Mobile m => m.Location, + _ => p + }; + + Commands.Add.Invoke(from, new Point3D(p), new Point3D(p), new[] { m_Type.Name }); + + from.Target = new InternalTarget(m_Type, m_SearchResults, m_SearchString, m_Page); + } + } + + protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType) + { + if (cancelType == TargetCancelType.Canceled) + from.SendGump(new AddGump(from, m_SearchString, m_Page, m_SearchResults, true)); + } + } + } +} diff --git a/Projects/UOContent/Commands/Object Creation/CAGCategory.cs b/Projects/UOContent/Commands/Object Creation/CAGCategory.cs index b85933839..985b3f2be 100644 --- a/Projects/UOContent/Commands/Object Creation/CAGCategory.cs +++ b/Projects/UOContent/Commands/Object Creation/CAGCategory.cs @@ -1,28 +1,28 @@ -using Server.Gumps; - -namespace Server.Commands -{ - public class CAGCategory : CAGNode - { - private static CAGCategory m_Root; - - public CAGCategory(string title, CAGCategory parent = null) - { - Title = title; - Parent = parent; - } - - public override string Title { get; } - - public CAGNode[] Nodes { get; set; } - - public CAGCategory Parent { get; } - - public static CAGCategory Root => m_Root ??= CAGLoader.Load(); - - public override void OnClick(Mobile from, int page) - { - from.SendGump(new CategorizedAddGump(from, this)); - } - } -} +using Server.Gumps; + +namespace Server.Commands +{ + public class CAGCategory : CAGNode + { + private static CAGCategory m_Root; + + public CAGCategory(string title, CAGCategory parent = null) + { + Title = title; + Parent = parent; + } + + public override string Title { get; } + + public CAGNode[] Nodes { get; set; } + + public CAGCategory Parent { get; } + + public static CAGCategory Root => m_Root ??= CAGLoader.Load(); + + public override void OnClick(Mobile from, int page) + { + from.SendGump(new CategorizedAddGump(from, this)); + } + } +} diff --git a/Projects/UOContent/Commands/Object Creation/CAGLoader.cs b/Projects/UOContent/Commands/Object Creation/CAGLoader.cs index ec0de56b4..8ddc81b2f 100644 --- a/Projects/UOContent/Commands/Object Creation/CAGLoader.cs +++ b/Projects/UOContent/Commands/Object Creation/CAGLoader.cs @@ -1,68 +1,62 @@ -using System.Collections.Generic; -using System.IO; -using System.Text.Json.Serialization; -using Server.Json; - -namespace Server.Commands -{ - public static class CAGLoader - { - public static CAGCategory Load() - { - var root = new CAGCategory("Add Menu"); - var path = Path.Combine(Core.BaseDirectory, "Data/objects.json"); - - List list = JsonConfig.Deserialize>(path); - - // Not an optimized solution - foreach (var cag in list) - { - var parent = root; - // Navigate through the dot notation categories until we find the last one - var categories = cag.Category.Split("."); - for (int i = 0; i < categories.Length; i++) - { - var category = categories[i]; - var oldParent = parent; - - for (int j = 0; j < parent.Nodes.Length; j++) - { - var node = parent.Nodes[i]; - if (category == node.Title && node is CAGCategory cat) - { - parent = cat; - break; - } - } - - if (parent == oldParent) - parent = new CAGCategory(category, parent); - } - - // Set the objects associated with the child most node - parent.Nodes = new CAGNode[cag.Objects.Length]; - for (int i = 0; i < cag.Objects.Length; i++) - { - var obj = cag.Objects[i]; - obj.Parent = parent; - parent.Nodes[i] = obj; - } - } - - return root; - } - } - - public class CAGJson - { - public CAGJson() - { - } - - [JsonPropertyName("category")] - public string Category { get; set; } - - [JsonPropertyName("objects")] - public CAGObject[] Objects { get; set; } - } -} +using System.Collections.Generic; +using System.IO; +using System.Text.Json.Serialization; +using Server.Json; + +namespace Server.Commands +{ + public static class CAGLoader + { + public static CAGCategory Load() + { + var root = new CAGCategory("Add Menu"); + var path = Path.Combine(Core.BaseDirectory, "Data/objects.json"); + + var list = JsonConfig.Deserialize>(path); + + // Not an optimized solution + foreach (var cag in list) + { + var parent = root; + // Navigate through the dot notation categories until we find the last one + var categories = cag.Category.Split("."); + for (var i = 0; i < categories.Length; i++) + { + var category = categories[i]; + var oldParent = parent; + + for (var j = 0; j < parent.Nodes.Length; j++) + { + var node = parent.Nodes[i]; + if (category == node.Title && node is CAGCategory cat) + { + parent = cat; + break; + } + } + + if (parent == oldParent) + parent = new CAGCategory(category, parent); + } + + // Set the objects associated with the child most node + parent.Nodes = new CAGNode[cag.Objects.Length]; + for (var i = 0; i < cag.Objects.Length; i++) + { + var obj = cag.Objects[i]; + obj.Parent = parent; + parent.Nodes[i] = obj; + } + } + + return root; + } + } + + public class CAGJson + { + [JsonPropertyName("category")] public string Category { get; set; } + + [JsonPropertyName("objects")] public CAGObject[] Objects { get; set; } + } +} diff --git a/Projects/UOContent/Commands/Object Creation/CAGNode.cs b/Projects/UOContent/Commands/Object Creation/CAGNode.cs index 4d6ddc0fb..296e0d5f6 100644 --- a/Projects/UOContent/Commands/Object Creation/CAGNode.cs +++ b/Projects/UOContent/Commands/Object Creation/CAGNode.cs @@ -1,8 +1,8 @@ -namespace Server.Commands -{ - public abstract class CAGNode - { - public abstract string Title { get; } - public abstract void OnClick(Mobile from, int page); - } -} +namespace Server.Commands +{ + public abstract class CAGNode + { + public abstract string Title { get; } + public abstract void OnClick(Mobile from, int page); + } +} diff --git a/Projects/UOContent/Commands/Object Creation/CAGObject.cs b/Projects/UOContent/Commands/Object Creation/CAGObject.cs index d1b70fd6b..32c29cb7a 100644 --- a/Projects/UOContent/Commands/Object Creation/CAGObject.cs +++ b/Projects/UOContent/Commands/Object Creation/CAGObject.cs @@ -1,40 +1,33 @@ -using System; -using System.Text.Json.Serialization; -using Server.Gumps; - -namespace Server.Commands -{ - public class CAGObject : CAGNode - { - public CAGObject() - { - } - - [JsonPropertyName("type")] - public Type Type { get; set; } - - [JsonPropertyName("gfx")] - public int ItemID { get; set; } - - [JsonPropertyName("hue")] - public int? Hue { get; set; } - - public CAGCategory Parent { get; set; } - - public override string Title => Type == null ? "bad type" : Type.Name; - - public override void OnClick(Mobile from, int page) - { - if (Type == null) - { - from.SendMessage("That is an invalid type name."); - } - else - { - CommandSystem.Handle(from, $"{CommandSystem.Prefix}Add {Type.Name}"); - - from.SendGump(new CategorizedAddGump(from, Parent, page)); - } - } - } -} +using System; +using System.Text.Json.Serialization; +using Server.Gumps; + +namespace Server.Commands +{ + public class CAGObject : CAGNode + { + [JsonPropertyName("type")] public Type Type { get; set; } + + [JsonPropertyName("gfx")] public int ItemID { get; set; } + + [JsonPropertyName("hue")] public int? Hue { get; set; } + + public CAGCategory Parent { get; set; } + + public override string Title => Type == null ? "bad type" : Type.Name; + + public override void OnClick(Mobile from, int page) + { + if (Type == null) + { + from.SendMessage("That is an invalid type name."); + } + else + { + CommandSystem.Handle(from, $"{CommandSystem.Prefix}Add {Type.Name}"); + + from.SendGump(new CategorizedAddGump(from, Parent, page)); + } + } + } +} diff --git a/Projects/UOContent/Commands/Object Creation/Categorization.cs b/Projects/UOContent/Commands/Object Creation/Categorization.cs index 2b14f1811..ddea70010 100644 --- a/Projects/UOContent/Commands/Object Creation/Categorization.cs +++ b/Projects/UOContent/Commands/Object Creation/Categorization.cs @@ -1,391 +1,398 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using Server.Items; -using Server.Json; -using Server.Utilities; - -namespace Server.Commands -{ - public static class Categorization - { - private static CategoryEntry m_RootItems, m_RootMobiles; - - private static readonly Type typeofItem = typeof(Item); - private static readonly Type typeofMobile = typeof(Mobile); - private static readonly Type typeofConstructible = typeof(ConstructibleAttribute); - - public static CategoryEntry Items - { - get - { - if (m_RootItems == null) - Load(); - - return m_RootItems; - } - } - - public static CategoryEntry Mobiles - { - get - { - if (m_RootMobiles == null) - Load(); - - return m_RootMobiles; - } - } - - public static void Initialize() - { - CommandSystem.Register("RebuildCategorization", AccessLevel.Administrator, RebuildCategorization_OnCommand); - } - - [Usage("RebuildCategorization")] - [Description("Rebuilds the categorization data file used by the Add command.")] - public static void RebuildCategorization_OnCommand(CommandEventArgs e) - { - CategoryEntry root = new CategoryEntry(null, "Add Menu", new[] { Items, Mobiles }); - - List ceList = new List(); - ceList.AddRange(root.SubCategories); - - Export(ceList, "Data/objects.json"); - - e.Mobile.SendMessage("Categorization menu rebuilt."); - } - - public static void Export(List ceList, string fileName) - { - List list = new List(); - foreach (var ce in ceList) - RecurseExport(list, ce, null); - - JsonConfig.Serialize(fileName, list); - } - - public static void RecurseExport(List list, CategoryEntry ce, string category) - { - category = string.IsNullOrWhiteSpace(category) ? ce.Title : $"{category}{ce.Title}"; - - if (ce.Matched.Count > 0) - list.Add(new CAGJson - { - Category = category, - Objects = ce.Matched.Select(cte => - { - if (cte.Object is Item item) - { - int itemID = item.ItemID; - - if (item is BaseAddon addon && addon.Components.Count == 1) - itemID = addon.Components[0].ItemID; - - if (itemID > TileData.MaxItemValue) - itemID = 1; - - int? hue = item.Hue & 0x7FFF; - - if ((hue & 0x4000) != 0) - hue = 0; - - return new CAGObject - { - Type = cte.Type, - ItemID = itemID, - Hue = hue == 0 ? null : hue - }; - } - - if (cte.Object is Mobile m) - { - int itemID = ShrinkTable.Lookup(m, 1); - - int? hue = m.Hue & 0x7FFF; - - if ((hue & 0x4000) != 0) - hue = 0; - - return new CAGObject - { - Type = cte.Type, - ItemID = itemID, - Hue = hue == 0 ? null : hue - }; - } - - throw new InvalidCastException($"Categorization Type Entry: {cte.Type.Name} is not a valid type."); - }).ToArray() - }); - - List subCats = new List(ce.SubCategories); - - subCats.Sort(new CategorySorter()); - - for (int i = 0; i < subCats.Count; i++) - { - var subCat = subCats[i]; - RecurseExport(list, subCat, category); - } - } - public static void Load() - { - List types = new List(); - - AddTypes(Core.Assembly, types); - - for (int i = 0; i < AssemblyHandler.Assemblies.Length; ++i) - AddTypes(AssemblyHandler.Assemblies[i], types); - - m_RootItems = Load(types, "Data/items.cfg"); - m_RootMobiles = Load(types, "Data/mobiles.cfg"); - } - - private static CategoryEntry Load(List types, string config) - { - CategoryLine[] lines = CategoryLine.Load(config); - - if (lines.Length <= 0) return new CategoryEntry(); - - int index = 0; - CategoryEntry root = new CategoryEntry(null, lines, ref index); - - Fill(root, types); - - return root; - - } - - private static bool IsConstructible(Type type) - { - if (!type.IsSubclassOf(typeofItem) && !type.IsSubclassOf(typeofMobile)) - return false; - - ConstructorInfo ctor = type.GetConstructor(Type.EmptyTypes); - - return ctor?.IsDefined(typeofConstructible, false) == true; - } - - private static void AddTypes(Assembly asm, List types) - { - Type[] allTypes = asm.GetTypes(); - - for (int i = 0; i < allTypes.Length; ++i) - { - Type type = allTypes[i]; - - if (type.IsAbstract) - continue; - - if (IsConstructible(type)) - types.Add(type); - } - } - - private static void Fill(CategoryEntry root, List list) - { - for (int i = 0; i < list.Count; ++i) - { - Type type = list[i]; - CategoryEntry match = GetDeepestMatch(root, type); - - if (match == null) - continue; - - try - { - match.Matched.Add(new CategoryTypeEntry(type)); - } - catch - { - // ignored - } - } - } - - private static CategoryEntry GetDeepestMatch(CategoryEntry root, Type type) - { - if (!root.IsMatch(type)) - return null; - - for (int i = 0; i < root.SubCategories.Length; ++i) - { - CategoryEntry check = GetDeepestMatch(root.SubCategories[i], type); - - if (check != null) - return check; - } - - return root; - } - } - - public class CategorySorter : IComparer - { - public int Compare(CategoryEntry x, CategoryEntry y) - { - string a = x?.Title; - string b = y?.Title; - - return a switch - { - null when b == null => 0, - null => 1, - _ => a.CompareTo(b) - }; - } - } - - public class CategoryTypeSorter : IComparer - { - public int Compare(CategoryTypeEntry x, CategoryTypeEntry y) - { - string a = x?.Type.Name; - string b = y?.Type.Name; - - return a switch - { - null when b == null => 0, - null => 1, - _ => a.CompareTo(b) - }; - } - } - - public class CategoryTypeEntry - { - public CategoryTypeEntry(Type type) - { - Type = type; - Object = ActivatorUtil.CreateInstance(type); - } - - public Type Type { get; } - - public object Object { get; } - } - - public class CategoryEntry - { - public CategoryEntry(CategoryEntry parent = null, string title = "(empty)", CategoryEntry[] subCats = null) - { - Parent = parent; - Title = title; - SubCategories = subCats ?? Array.Empty(); - Matches = Array.Empty(); - Matched = new List(); - } - - public CategoryEntry(CategoryEntry parent, CategoryLine[] lines, ref int index) - { - Parent = parent; - - string text = lines[index].Text; - - int start = text.IndexOf('('); - - if (start < 0) - throw new FormatException($"Input string not correctly formatted ('{text}')"); - - Title = text.Substring(0, start).Trim(); - - int end = text.IndexOf(')', ++start); - - if (end < start) - throw new FormatException($"Input string not correctly formatted ('{text}')"); - - text = text.Substring(start, end - start); - string[] split = text.Split(';'); - - List list = new List(); - - for (int i = 0; i < split.Length; ++i) - { - Type type = AssemblyHandler.FindFirstTypeForName(split[i].Trim()); - - if (type == null) - Console.WriteLine("Match type not found ('{0}')", split[i].Trim()); - else - list.Add(type); - } - - Matches = list.ToArray(); - list.Clear(); - - int ourIndentation = lines[index].Indentation; - - ++index; - - List entryList = new List(); - - while (index < lines.Length && lines[index].Indentation > ourIndentation) - entryList.Add(new CategoryEntry(this, lines, ref index)); - - SubCategories = entryList.ToArray(); - entryList.Clear(); - - Matched = new List(); - } - - public string Title { get; } - - public Type[] Matches { get; } - - public CategoryEntry Parent { get; } - - public CategoryEntry[] SubCategories { get; } - - public List Matched { get; } - - public bool IsMatch(Type type) - { - bool isMatch = false; - - for (int i = 0; !isMatch && i < Matches.Length; ++i) - isMatch = type == Matches[i] || type.IsSubclassOf(Matches[i]); - - return isMatch; - } - } - - public class CategoryLine - { - public CategoryLine(string input) - { - int index; - - for (index = 0; index < input.Length; ++index) - if (char.IsLetter(input, index)) - break; - - if (index >= input.Length) - throw new FormatException($"Input string not correctly formatted ('{input}')"); - - Indentation = index; - Text = input.Substring(index); - } - - public int Indentation { get; } - - public string Text { get; } - - public static CategoryLine[] Load(string path) - { - List list = new List(); - - if (File.Exists(path)) - { - using StreamReader ip = new StreamReader(path); - string line; - - while ((line = ip.ReadLine()) != null) - list.Add(new CategoryLine(line)); - } - - return list.ToArray(); - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using Server.Items; +using Server.Json; +using Server.Utilities; + +namespace Server.Commands +{ + public static class Categorization + { + private static CategoryEntry m_RootItems, m_RootMobiles; + + private static readonly Type typeofItem = typeof(Item); + private static readonly Type typeofMobile = typeof(Mobile); + private static readonly Type typeofConstructible = typeof(ConstructibleAttribute); + + public static CategoryEntry Items + { + get + { + if (m_RootItems == null) + Load(); + + return m_RootItems; + } + } + + public static CategoryEntry Mobiles + { + get + { + if (m_RootMobiles == null) + Load(); + + return m_RootMobiles; + } + } + + public static void Initialize() + { + CommandSystem.Register("RebuildCategorization", AccessLevel.Administrator, RebuildCategorization_OnCommand); + } + + [Usage("RebuildCategorization")] + [Description("Rebuilds the categorization data file used by the Add command.")] + public static void RebuildCategorization_OnCommand(CommandEventArgs e) + { + var root = new CategoryEntry(null, "Add Menu", new[] { Items, Mobiles }); + + var ceList = new List(); + ceList.AddRange(root.SubCategories); + + Export(ceList, "Data/objects.json"); + + e.Mobile.SendMessage("Categorization menu rebuilt."); + } + + public static void Export(List ceList, string fileName) + { + var list = new List(); + foreach (var ce in ceList) + RecurseExport(list, ce, null); + + JsonConfig.Serialize(fileName, list); + } + + public static void RecurseExport(List list, CategoryEntry ce, string category) + { + category = string.IsNullOrWhiteSpace(category) ? ce.Title : $"{category}{ce.Title}"; + + if (ce.Matched.Count > 0) + list.Add( + new CAGJson + { + Category = category, + Objects = ce.Matched.Select( + cte => + { + if (cte.Object is Item item) + { + var itemID = item.ItemID; + + if (item is BaseAddon addon && addon.Components.Count == 1) + itemID = addon.Components[0].ItemID; + + if (itemID > TileData.MaxItemValue) + itemID = 1; + + int? hue = item.Hue & 0x7FFF; + + if ((hue & 0x4000) != 0) + hue = 0; + + return new CAGObject + { + Type = cte.Type, + ItemID = itemID, + Hue = hue == 0 ? null : hue + }; + } + + if (cte.Object is Mobile m) + { + var itemID = ShrinkTable.Lookup(m, 1); + + int? hue = m.Hue & 0x7FFF; + + if ((hue & 0x4000) != 0) + hue = 0; + + return new CAGObject + { + Type = cte.Type, + ItemID = itemID, + Hue = hue == 0 ? null : hue + }; + } + + throw new InvalidCastException( + $"Categorization Type Entry: {cte.Type.Name} is not a valid type." + ); + } + ) + .ToArray() + } + ); + + var subCats = new List(ce.SubCategories); + + subCats.Sort(new CategorySorter()); + + for (var i = 0; i < subCats.Count; i++) + { + var subCat = subCats[i]; + RecurseExport(list, subCat, category); + } + } + + public static void Load() + { + var types = new List(); + + AddTypes(Core.Assembly, types); + + for (var i = 0; i < AssemblyHandler.Assemblies.Length; ++i) + AddTypes(AssemblyHandler.Assemblies[i], types); + + m_RootItems = Load(types, "Data/items.cfg"); + m_RootMobiles = Load(types, "Data/mobiles.cfg"); + } + + private static CategoryEntry Load(List types, string config) + { + var lines = CategoryLine.Load(config); + + if (lines.Length <= 0) return new CategoryEntry(); + + var index = 0; + var root = new CategoryEntry(null, lines, ref index); + + Fill(root, types); + + return root; + } + + private static bool IsConstructible(Type type) + { + if (!type.IsSubclassOf(typeofItem) && !type.IsSubclassOf(typeofMobile)) + return false; + + var ctor = type.GetConstructor(Type.EmptyTypes); + + return ctor?.IsDefined(typeofConstructible, false) == true; + } + + private static void AddTypes(Assembly asm, List types) + { + var allTypes = asm.GetTypes(); + + for (var i = 0; i < allTypes.Length; ++i) + { + var type = allTypes[i]; + + if (type.IsAbstract) + continue; + + if (IsConstructible(type)) + types.Add(type); + } + } + + private static void Fill(CategoryEntry root, List list) + { + for (var i = 0; i < list.Count; ++i) + { + var type = list[i]; + var match = GetDeepestMatch(root, type); + + if (match == null) + continue; + + try + { + match.Matched.Add(new CategoryTypeEntry(type)); + } + catch + { + // ignored + } + } + } + + private static CategoryEntry GetDeepestMatch(CategoryEntry root, Type type) + { + if (!root.IsMatch(type)) + return null; + + for (var i = 0; i < root.SubCategories.Length; ++i) + { + var check = GetDeepestMatch(root.SubCategories[i], type); + + if (check != null) + return check; + } + + return root; + } + } + + public class CategorySorter : IComparer + { + public int Compare(CategoryEntry x, CategoryEntry y) + { + var a = x?.Title; + var b = y?.Title; + + return a switch + { + null when b == null => 0, + null => 1, + _ => a.CompareTo(b) + }; + } + } + + public class CategoryTypeSorter : IComparer + { + public int Compare(CategoryTypeEntry x, CategoryTypeEntry y) + { + var a = x?.Type.Name; + var b = y?.Type.Name; + + return a switch + { + null when b == null => 0, + null => 1, + _ => a.CompareTo(b) + }; + } + } + + public class CategoryTypeEntry + { + public CategoryTypeEntry(Type type) + { + Type = type; + Object = ActivatorUtil.CreateInstance(type); + } + + public Type Type { get; } + + public object Object { get; } + } + + public class CategoryEntry + { + public CategoryEntry(CategoryEntry parent = null, string title = "(empty)", CategoryEntry[] subCats = null) + { + Parent = parent; + Title = title; + SubCategories = subCats ?? Array.Empty(); + Matches = Array.Empty(); + Matched = new List(); + } + + public CategoryEntry(CategoryEntry parent, CategoryLine[] lines, ref int index) + { + Parent = parent; + + var text = lines[index].Text; + + var start = text.IndexOf('('); + + if (start < 0) + throw new FormatException($"Input string not correctly formatted ('{text}')"); + + Title = text.Substring(0, start).Trim(); + + var end = text.IndexOf(')', ++start); + + if (end < start) + throw new FormatException($"Input string not correctly formatted ('{text}')"); + + text = text.Substring(start, end - start); + var split = text.Split(';'); + + var list = new List(); + + for (var i = 0; i < split.Length; ++i) + { + var type = AssemblyHandler.FindFirstTypeForName(split[i].Trim()); + + if (type == null) + Console.WriteLine("Match type not found ('{0}')", split[i].Trim()); + else + list.Add(type); + } + + Matches = list.ToArray(); + list.Clear(); + + var ourIndentation = lines[index].Indentation; + + ++index; + + var entryList = new List(); + + while (index < lines.Length && lines[index].Indentation > ourIndentation) + entryList.Add(new CategoryEntry(this, lines, ref index)); + + SubCategories = entryList.ToArray(); + entryList.Clear(); + + Matched = new List(); + } + + public string Title { get; } + + public Type[] Matches { get; } + + public CategoryEntry Parent { get; } + + public CategoryEntry[] SubCategories { get; } + + public List Matched { get; } + + public bool IsMatch(Type type) + { + var isMatch = false; + + for (var i = 0; !isMatch && i < Matches.Length; ++i) + isMatch = type == Matches[i] || type.IsSubclassOf(Matches[i]); + + return isMatch; + } + } + + public class CategoryLine + { + public CategoryLine(string input) + { + int index; + + for (index = 0; index < input.Length; ++index) + if (char.IsLetter(input, index)) + break; + + if (index >= input.Length) + throw new FormatException($"Input string not correctly formatted ('{input}')"); + + Indentation = index; + Text = input.Substring(index); + } + + public int Indentation { get; } + + public string Text { get; } + + public static CategoryLine[] Load(string path) + { + var list = new List(); + + if (File.Exists(path)) + { + using var ip = new StreamReader(path); + string line; + + while ((line = ip.ReadLine()) != null) + list.Add(new CategoryLine(line)); + } + + return list.ToArray(); + } + } +} diff --git a/Projects/UOContent/Commands/Object Creation/CategorizedAddGump.cs b/Projects/UOContent/Commands/Object Creation/CategorizedAddGump.cs index 93a9c199c..50e32ebed 100644 --- a/Projects/UOContent/Commands/Object Creation/CategorizedAddGump.cs +++ b/Projects/UOContent/Commands/Object Creation/CategorizedAddGump.cs @@ -1,247 +1,274 @@ -using System; -using Server.Commands; -using Server.Network; - -namespace Server.Gumps -{ - public class CategorizedAddGump : Gump - { - public static bool OldStyle = PropsConfig.OldStyle; - - public static readonly int EntryHeight = 24; // PropsConfig.EntryHeight; - - public static readonly int OffsetSize = PropsConfig.OffsetSize; - public static readonly int BorderSize = PropsConfig.BorderSize; - - public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; - public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; - - public static readonly int TextHue = PropsConfig.TextHue; - public static readonly int TextOffsetX = PropsConfig.TextOffsetX; - - public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; - public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; - public static readonly int EntryGumpID = PropsConfig.EntryGumpID; - public static readonly int BackGumpID = PropsConfig.BackGumpID; - public static readonly int SetGumpID = PropsConfig.SetGumpID; - - public static readonly int SetWidth = PropsConfig.SetWidth; - - public static readonly int SetOffsetX = PropsConfig.SetOffsetX, - SetOffsetY = PropsConfig.SetOffsetY + (EntryHeight - 20) / 2 / 2; - - public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; - public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; - - public static readonly int PrevWidth = PropsConfig.PrevWidth; - - public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, - PrevOffsetY = PropsConfig.PrevOffsetY + (EntryHeight - 20) / 2 / 2; - - public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; - public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; - - public static readonly int NextWidth = PropsConfig.NextWidth; - - public static readonly int NextOffsetX = PropsConfig.NextOffsetX, - NextOffsetY = PropsConfig.NextOffsetY + (EntryHeight - 20) / 2 / 2; - - public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; - public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; - - private static readonly bool PrevLabel = false; - private static readonly bool NextLabel = false; - - private static readonly int PrevLabelOffsetX = PrevWidth + 1; - private static readonly int PrevLabelOffsetY = 0; - - private static readonly int NextLabelOffsetX = -29; - private static readonly int NextLabelOffsetY = 0; - - private static readonly int EntryWidth = 180; - private static readonly int EntryCount = 15; - - private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize; - private static readonly int TotalHeight = OffsetSize + (EntryHeight + OffsetSize) * (EntryCount + 1); - - private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; - private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize; - private readonly CAGCategory m_Category; - - private readonly Mobile m_Owner; - private int m_Page; - - public CategorizedAddGump(Mobile owner) : this(owner, CAGCategory.Root) - { - } - - public CategorizedAddGump(Mobile owner, CAGCategory category, int page = 0) : base(GumpOffsetX, GumpOffsetY) - { - owner.CloseGump(); - - m_Owner = owner; - m_Category = category; - - Initialize(page); - } - - public void Initialize(int page) - { - m_Page = page; - - CAGNode[] nodes = m_Category.Nodes; - - int count = Math.Clamp(nodes.Length - page * EntryCount, 0, EntryCount); - - int totalHeight = OffsetSize + (EntryHeight + OffsetSize) * (count + 1); - - AddPage(0); - - AddBackground(0, 0, BackWidth, BorderSize + totalHeight + BorderSize, BackGumpID); - AddImageTiled(BorderSize, BorderSize, TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), totalHeight, - OffsetGumpID); - - int x = BorderSize + OffsetSize; - int y = BorderSize + OffsetSize; - - if (OldStyle) - AddImageTiled(x, y, TotalWidth - OffsetSize * 3 - SetWidth, EntryHeight, HeaderGumpID); - else - AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); - - if (m_Category.Parent != null) - { - AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 1); - - if (PrevLabel) - AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous"); - } - - x += PrevWidth + OffsetSize; - - int emptyWidth = TotalWidth - PrevWidth * 2 - NextWidth - OffsetSize * 5 - - (OldStyle ? SetWidth + OffsetSize : 0); - - if (!OldStyle) - AddImageTiled(x - (OldStyle ? OffsetSize : 0), y, emptyWidth + (OldStyle ? OffsetSize * 2 : 0), EntryHeight, - EntryGumpID); - - AddHtml(x + TextOffsetX, y + (EntryHeight - 20) / 2, emptyWidth - TextOffsetX, EntryHeight, - $"
{m_Category.Title}
"); - - x += emptyWidth + OffsetSize; - - if (OldStyle) - AddImageTiled(x, y, TotalWidth - OffsetSize * 3 - SetWidth, EntryHeight, HeaderGumpID); - else - AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); - - if (page > 0) - { - AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 2); - - if (PrevLabel) - AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous"); - } - - x += PrevWidth + OffsetSize; - - if (!OldStyle) - AddImageTiled(x, y, NextWidth, EntryHeight, HeaderGumpID); - - if ((page + 1) * EntryCount < nodes.Length) - { - AddButton(x + NextOffsetX, y + NextOffsetY, NextButtonID1, NextButtonID2, 3, GumpButtonType.Reply, 1); - - if (NextLabel) - AddLabel(x + NextLabelOffsetX, y + NextLabelOffsetY, TextHue, "Next"); - } - - for (int i = 0, index = page * EntryCount; i < EntryCount && index < nodes.Length; ++i, ++index) - { - x = BorderSize + OffsetSize; - y += EntryHeight + OffsetSize; - - CAGNode node = nodes[index]; - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y + (EntryHeight - 20) / 2, EntryWidth - TextOffsetX, EntryHeight, TextHue, - node.Title); - - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - - AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, i + 4); - - if (node is CAGObject obj) - { - int itemID = obj.ItemID; - - Rectangle2D bounds = ItemBounds.Table[itemID]; - - if (itemID != 1 && bounds.Height < EntryHeight * 2) - { - if (bounds.Height < EntryHeight) - AddItem(x - OffsetSize - 22 - i % 2 * 44 - bounds.Width / 2 - bounds.X, - y + EntryHeight / 2 - bounds.Height / 2 - bounds.Y, itemID); - else - AddItem(x - OffsetSize - 22 - i % 2 * 44 - bounds.Width / 2 - bounds.X, - y + EntryHeight - 1 - bounds.Height - bounds.Y, itemID); - } - } - } - } - - public override void OnResponse(NetState state, RelayInfo info) - { - Mobile from = m_Owner; - - switch (info.ButtonID) - { - case 0: // Closed - { - return; - } - case 1: // Up - { - if (m_Category.Parent != null) - { - int index = Array.IndexOf(m_Category.Parent.Nodes, m_Category) / EntryCount; - - if (index < 0) - index = 0; - - from.SendGump(new CategorizedAddGump(from, m_Category.Parent, index)); - } - - break; - } - case 2: // Previous - { - if (m_Page > 0) - from.SendGump(new CategorizedAddGump(from, m_Category, m_Page - 1)); - - break; - } - case 3: // Next - { - if ((m_Page + 1) * EntryCount < m_Category.Nodes.Length) - from.SendGump(new CategorizedAddGump(from, m_Category, m_Page + 1)); - - break; - } - default: - { - int index = m_Page * EntryCount + (info.ButtonID - 4); - - if (index >= 0 && index < m_Category.Nodes.Length) - m_Category.Nodes[index].OnClick(from, m_Page); - - break; - } - } - } - } -} +using System; +using Server.Commands; +using Server.Network; + +namespace Server.Gumps +{ + public class CategorizedAddGump : Gump + { + public static bool OldStyle = PropsConfig.OldStyle; + + public static readonly int EntryHeight = 24; // PropsConfig.EntryHeight; + + public static readonly int OffsetSize = PropsConfig.OffsetSize; + public static readonly int BorderSize = PropsConfig.BorderSize; + + public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; + public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; + + public static readonly int TextHue = PropsConfig.TextHue; + public static readonly int TextOffsetX = PropsConfig.TextOffsetX; + + public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; + public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; + public static readonly int EntryGumpID = PropsConfig.EntryGumpID; + public static readonly int BackGumpID = PropsConfig.BackGumpID; + public static readonly int SetGumpID = PropsConfig.SetGumpID; + + public static readonly int SetWidth = PropsConfig.SetWidth; + + public static readonly int SetOffsetX = PropsConfig.SetOffsetX, + SetOffsetY = PropsConfig.SetOffsetY + (EntryHeight - 20) / 2 / 2; + + public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; + public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; + + public static readonly int PrevWidth = PropsConfig.PrevWidth; + + public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, + PrevOffsetY = PropsConfig.PrevOffsetY + (EntryHeight - 20) / 2 / 2; + + public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; + public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; + + public static readonly int NextWidth = PropsConfig.NextWidth; + + public static readonly int NextOffsetX = PropsConfig.NextOffsetX, + NextOffsetY = PropsConfig.NextOffsetY + (EntryHeight - 20) / 2 / 2; + + public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; + public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; + + private static readonly bool PrevLabel = false; + private static readonly bool NextLabel = false; + + private static readonly int PrevLabelOffsetX = PrevWidth + 1; + private static readonly int PrevLabelOffsetY = 0; + + private static readonly int NextLabelOffsetX = -29; + private static readonly int NextLabelOffsetY = 0; + + private static readonly int EntryWidth = 180; + private static readonly int EntryCount = 15; + + private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize; + private static readonly int TotalHeight = OffsetSize + (EntryHeight + OffsetSize) * (EntryCount + 1); + + private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; + private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize; + private readonly CAGCategory m_Category; + + private readonly Mobile m_Owner; + private int m_Page; + + public CategorizedAddGump(Mobile owner) : this(owner, CAGCategory.Root) + { + } + + public CategorizedAddGump(Mobile owner, CAGCategory category, int page = 0) : base(GumpOffsetX, GumpOffsetY) + { + owner.CloseGump(); + + m_Owner = owner; + m_Category = category; + + Initialize(page); + } + + public void Initialize(int page) + { + m_Page = page; + + var nodes = m_Category.Nodes; + + var count = Math.Clamp(nodes.Length - page * EntryCount, 0, EntryCount); + + var totalHeight = OffsetSize + (EntryHeight + OffsetSize) * (count + 1); + + AddPage(0); + + AddBackground(0, 0, BackWidth, BorderSize + totalHeight + BorderSize, BackGumpID); + AddImageTiled( + BorderSize, + BorderSize, + TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), + totalHeight, + OffsetGumpID + ); + + var x = BorderSize + OffsetSize; + var y = BorderSize + OffsetSize; + + if (OldStyle) + AddImageTiled(x, y, TotalWidth - OffsetSize * 3 - SetWidth, EntryHeight, HeaderGumpID); + else + AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); + + if (m_Category.Parent != null) + { + AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 1); + + if (PrevLabel) + AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous"); + } + + x += PrevWidth + OffsetSize; + + var emptyWidth = TotalWidth - PrevWidth * 2 - NextWidth - OffsetSize * 5 - + (OldStyle ? SetWidth + OffsetSize : 0); + + if (!OldStyle) + AddImageTiled( + x - (OldStyle ? OffsetSize : 0), + y, + emptyWidth + (OldStyle ? OffsetSize * 2 : 0), + EntryHeight, + EntryGumpID + ); + + AddHtml( + x + TextOffsetX, + y + (EntryHeight - 20) / 2, + emptyWidth - TextOffsetX, + EntryHeight, + $"
{m_Category.Title}
" + ); + + x += emptyWidth + OffsetSize; + + if (OldStyle) + AddImageTiled(x, y, TotalWidth - OffsetSize * 3 - SetWidth, EntryHeight, HeaderGumpID); + else + AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); + + if (page > 0) + { + AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 2); + + if (PrevLabel) + AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous"); + } + + x += PrevWidth + OffsetSize; + + if (!OldStyle) + AddImageTiled(x, y, NextWidth, EntryHeight, HeaderGumpID); + + if ((page + 1) * EntryCount < nodes.Length) + { + AddButton(x + NextOffsetX, y + NextOffsetY, NextButtonID1, NextButtonID2, 3, GumpButtonType.Reply, 1); + + if (NextLabel) + AddLabel(x + NextLabelOffsetX, y + NextLabelOffsetY, TextHue, "Next"); + } + + for (int i = 0, index = page * EntryCount; i < EntryCount && index < nodes.Length; ++i, ++index) + { + x = BorderSize + OffsetSize; + y += EntryHeight + OffsetSize; + + var node = nodes[index]; + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddLabelCropped( + x + TextOffsetX, + y + (EntryHeight - 20) / 2, + EntryWidth - TextOffsetX, + EntryHeight, + TextHue, + node.Title + ); + + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + + AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, i + 4); + + if (node is CAGObject obj) + { + var itemID = obj.ItemID; + + var bounds = ItemBounds.Table[itemID]; + + if (itemID != 1 && bounds.Height < EntryHeight * 2) + { + if (bounds.Height < EntryHeight) + AddItem( + x - OffsetSize - 22 - i % 2 * 44 - bounds.Width / 2 - bounds.X, + y + EntryHeight / 2 - bounds.Height / 2 - bounds.Y, + itemID + ); + else + AddItem( + x - OffsetSize - 22 - i % 2 * 44 - bounds.Width / 2 - bounds.X, + y + EntryHeight - 1 - bounds.Height - bounds.Y, + itemID + ); + } + } + } + } + + public override void OnResponse(NetState state, RelayInfo info) + { + var from = m_Owner; + + switch (info.ButtonID) + { + case 0: // Closed + { + return; + } + case 1: // Up + { + if (m_Category.Parent != null) + { + var index = Array.IndexOf(m_Category.Parent.Nodes, m_Category) / EntryCount; + + if (index < 0) + index = 0; + + from.SendGump(new CategorizedAddGump(from, m_Category.Parent, index)); + } + + break; + } + case 2: // Previous + { + if (m_Page > 0) + from.SendGump(new CategorizedAddGump(from, m_Category, m_Page - 1)); + + break; + } + case 3: // Next + { + if ((m_Page + 1) * EntryCount < m_Category.Nodes.Length) + from.SendGump(new CategorizedAddGump(from, m_Category, m_Page + 1)); + + break; + } + default: + { + var index = m_Page * EntryCount + (info.ButtonID - 4); + + if (index >= 0 && index < m_Category.Nodes.Length) + m_Category.Nodes[index].OnClick(from, m_Page); + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Commands/Object Creation/Decorate.cs b/Projects/UOContent/Commands/Object Creation/Decorate.cs index ac9782e9b..99a7962d0 100644 --- a/Projects/UOContent/Commands/Object Creation/Decorate.cs +++ b/Projects/UOContent/Commands/Object Creation/Decorate.cs @@ -1,1103 +1,1114 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Server.Engines.Quests.Haven; -using Server.Engines.Quests.Necro; -using Server.Engines.Spawners; -using Server.Items; -using Server.Utilities; - -namespace Server.Commands -{ - public static class Decorate - { - private static Mobile m_Mobile; - private static int m_Count; - - public static void Initialize() - { - CommandSystem.Register("Decorate", AccessLevel.Administrator, Decorate_OnCommand); - } - - [Usage("Decorate")] - [Description("Generates world decoration.")] - private static void Decorate_OnCommand(CommandEventArgs e) - { - m_Mobile = e.Mobile; - m_Count = 0; - - m_Mobile.SendMessage("Generating world decoration, please wait."); - - Generate("Data/Decoration/Britannia", Map.Trammel, Map.Felucca); - Generate("Data/Decoration/Trammel", Map.Trammel); - Generate("Data/Decoration/Felucca", Map.Felucca); - Generate("Data/Decoration/Ilshenar", Map.Ilshenar); - Generate("Data/Decoration/Malas", Map.Malas); - Generate("Data/Decoration/Tokuno", Map.Tokuno); - - m_Mobile.SendMessage("World generating complete. {0} items were generated.", m_Count); - } - - public static void Generate(string folder, params Map[] maps) - { - if (!Directory.Exists(folder)) - return; - - string[] files = Directory.GetFiles(folder, "*.cfg"); - - for (int i = 0; i < files.Length; ++i) - { - List list = DecorationList.ReadAll(files[i]); - - for (int j = 0; j < list.Count; ++j) - m_Count += list[j].Generate(maps); - } - } - } - - public class DecorationList - { - private static readonly Type typeofStatic = typeof(Static); - private static readonly Type typeofLocalizedStatic = typeof(LocalizedStatic); - private static readonly Type typeofBaseDoor = typeof(BaseDoor); - private static readonly Type typeofAnkhWest = typeof(AnkhWest); - private static readonly Type typeofAnkhNorth = typeof(AnkhNorth); - private static readonly Type typeofBeverage = typeof(BaseBeverage); - private static readonly Type typeofLocalizedSign = typeof(LocalizedSign); - private static readonly Type typeofMarkContainer = typeof(MarkContainer); - private static readonly Type typeofWarningItem = typeof(WarningItem); - private static readonly Type typeofHintItem = typeof(HintItem); - private static readonly Type typeofCannon = typeof(Cannon); - private static readonly Type typeofSerpentPillar = typeof(SerpentPillar); - - private static readonly Queue m_DeleteQueue = new Queue(); - - private static readonly string[] m_EmptyParams = Array.Empty(); - private List m_Entries; - private int m_ItemID; - private string[] m_Params; - private Type m_Type; - - public Item Construct() - { - if (m_Type == null) - return null; - - Item item; - - try - { - if (m_Type == typeofStatic) - { - item = new Static(m_ItemID); - } - else if (m_Type == typeofLocalizedStatic) - { - int labelNumber = 0; - - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("LabelNumber")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - { - labelNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - break; - } - } - - item = new LocalizedStatic(m_ItemID, labelNumber); - } - else if (m_Type == typeofLocalizedSign) - { - int labelNumber = 0; - - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("LabelNumber")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - { - labelNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - break; - } - } - - item = new LocalizedSign(m_ItemID, labelNumber); - } - else if (m_Type == typeofAnkhWest || m_Type == typeofAnkhNorth) - { - bool bloodied = false; - - for (int i = 0; !bloodied && i < m_Params.Length; ++i) - bloodied = m_Params[i] == "Bloodied"; - - if (m_Type == typeofAnkhWest) - item = new AnkhWest(bloodied); - else - item = new AnkhNorth(bloodied); - } - else if (m_Type == typeofMarkContainer) - { - bool bone = false; - bool locked = false; - Map map = Map.Malas; - - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i] == "Bone") - { - bone = true; - } - else if (m_Params[i] == "Locked") - { - locked = true; - } - else if (m_Params[i].StartsWith("TargetMap")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - map = Map.Parse(m_Params[i].Substring(++indexOf)); - } - - MarkContainer mc = new MarkContainer(bone, locked); - - mc.TargetMap = map; - mc.Description = "strange location"; - - item = mc; - } - else if (m_Type == typeofHintItem) - { - int range = 0; - int messageNumber = 0; - string messageString = null; - int hintNumber = 0; - string hintString = null; - TimeSpan resetDelay = TimeSpan.Zero; - - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("Range")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - range = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("WarningString")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - messageString = m_Params[i].Substring(++indexOf); - } - else if (m_Params[i].StartsWith("WarningNumber")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - messageNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("HintString")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - hintString = m_Params[i].Substring(++indexOf); - } - else if (m_Params[i].StartsWith("HintNumber")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - hintNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("ResetDelay")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - resetDelay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); - } - - HintItem hi = new HintItem(m_ItemID, range, messageNumber, hintNumber); - - hi.WarningString = messageString; - hi.HintString = hintString; - hi.ResetDelay = resetDelay; - - item = hi; - } - else if (m_Type == typeofWarningItem) - { - int range = 0; - int messageNumber = 0; - string messageString = null; - TimeSpan resetDelay = TimeSpan.Zero; - - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("Range")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - range = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("WarningString")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - messageString = m_Params[i].Substring(++indexOf); - } - else if (m_Params[i].StartsWith("WarningNumber")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - messageNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("ResetDelay")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - resetDelay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); - } - - WarningItem wi = new WarningItem(m_ItemID, range, messageNumber); - - wi.WarningString = messageString; - wi.ResetDelay = resetDelay; - - item = wi; - } - else if (m_Type == typeofCannon) - { - CannonDirection direction = CannonDirection.North; - - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("CannonDirection")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - direction = (CannonDirection)Enum.Parse(typeof(CannonDirection), - m_Params[i].Substring(++indexOf), true); - } - - item = new Cannon(direction); - } - else if (m_Type == typeofSerpentPillar) - { - string word = null; - Rectangle2D destination = new Rectangle2D(); - - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("Word")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - word = m_Params[i].Substring(++indexOf); - } - else if (m_Params[i].StartsWith("DestStart")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - destination.Start = Point2D.Parse(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("DestEnd")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - destination.End = Point2D.Parse(m_Params[i].Substring(++indexOf)); - } - - item = new SerpentPillar(word, destination); - } - else if (m_Type.IsSubclassOf(typeofBeverage)) - { - BeverageType content = BeverageType.Liquor; - bool fill = false; - - for (int i = 0; !fill && i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("Content")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - { - content = (BeverageType)Enum.Parse(typeof(BeverageType), m_Params[i].Substring(++indexOf), - true); - fill = true; - } - } - - if (fill) - item = (Item)ActivatorUtil.CreateInstance(m_Type, content); - else - item = (Item)ActivatorUtil.CreateInstance(m_Type); - } - else if (m_Type.IsSubclassOf(typeofBaseDoor)) - { - DoorFacing facing = DoorFacing.WestCW; - - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("Facing")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - { - facing = (DoorFacing)Enum.Parse(typeof(DoorFacing), m_Params[i].Substring(++indexOf), true); - break; - } - } - - item = (Item)ActivatorUtil.CreateInstance(m_Type, facing); - } - else - { - item = (Item)ActivatorUtil.CreateInstance(m_Type); - } - } - catch (Exception e) - { - throw new TypeInitializationException(m_Type.ToString(), e); - } - - if (item is BaseAddon addon) - { - if (addon is MaabusCoffin coffin) - { - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("SpawnLocation")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - coffin.SpawnLocation = Point3D.Parse(m_Params[i].Substring(++indexOf)); - } - } - else if (m_ItemID > 0) - { - List comps = addon.Components; - - for (int i = 0; i < comps.Count; ++i) - { - AddonComponent comp = comps[i]; - - if (comp.Offset == Point3D.Zero) - comp.ItemID = m_ItemID; - } - } - } - else if (item is BaseLight light) - { - bool unlit = false, unprotected = false; - - for (int i = 0; i < m_Params.Length; ++i) - { - if (!unlit && m_Params[i] == "Unlit") - unlit = true; - else if (!unprotected && m_Params[i] == "Unprotected") - unprotected = true; - - if (unlit && unprotected) - break; - } - - if (!unlit) - light.Ignite(); - if (!unprotected) - light.Protected = true; - - if (m_ItemID > 0) - light.ItemID = m_ItemID; - } - else if (item is Spawner sp) - { - sp.NextSpawn = TimeSpan.Zero; - - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("Spawn")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - sp.AddEntry(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("MinDelay")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - sp.MinDelay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("MaxDelay")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - sp.MaxDelay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("NextSpawn")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - sp.NextSpawn = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("Count")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - { - sp.Count = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - for (int se = 0; se < sp.Entries.Count; se++) - sp.Entries[se].SpawnedMaxCount = sp.Count; - } - } - else if (m_Params[i].StartsWith("Team")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - sp.Team = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("HomeRange")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - sp.HomeRange = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("Running")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - sp.Running = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("Group")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - sp.Group = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - } - else if (item is RecallRune rune) - { - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("Description")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - rune.Description = m_Params[i].Substring(++indexOf); - } - else if (m_Params[i].StartsWith("Marked")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - rune.Marked = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("TargetMap")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - rune.TargetMap = Map.Parse(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("Target")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - rune.Target = Point3D.Parse(m_Params[i].Substring(++indexOf)); - } - } - else if (item is SkillTeleporter st) - { - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("Skill")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.Skill = (SkillName)Enum.Parse(typeof(SkillName), m_Params[i].Substring(++indexOf), true); - } - else if (m_Params[i].StartsWith("RequiredFixedPoint")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.Required = Utility.ToInt32(m_Params[i].Substring(++indexOf)) * 0.1; - } - else if (m_Params[i].StartsWith("Required")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.Required = Utility.ToDouble(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("MessageString")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.MessageString = m_Params[i].Substring(++indexOf); - } - else if (m_Params[i].StartsWith("MessageNumber")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.MessageNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("PointDest")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.PointDest = Point3D.Parse(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("MapDest")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.MapDest = Map.Parse(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("Creatures")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.Creatures = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("SourceEffect")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.SourceEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("DestEffect")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.DestEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("SoundID")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.SoundID = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("Delay")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.Delay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); - } - - if (m_ItemID > 0) - st.ItemID = m_ItemID; - } - else if (item is KeywordTeleporter kt) - { - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("Substring")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - kt.Substring = m_Params[i].Substring(++indexOf); - } - else if (m_Params[i].StartsWith("Keyword")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - kt.Keyword = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("Range")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - kt.Range = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("PointDest")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - kt.PointDest = Point3D.Parse(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("MapDest")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - kt.MapDest = Map.Parse(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("Creatures")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - kt.Creatures = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("SourceEffect")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - kt.SourceEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("DestEffect")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - kt.DestEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("SoundID")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - kt.SoundID = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("Delay")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - kt.Delay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); - } - - if (m_ItemID > 0) - kt.ItemID = m_ItemID; - } - else if (item is Teleporter tp) - { - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("PointDest")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - tp.PointDest = Point3D.Parse(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("MapDest")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - tp.MapDest = Map.Parse(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("Creatures")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - tp.Creatures = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("SourceEffect")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - tp.SourceEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("DestEffect")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - tp.DestEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("SoundID")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - tp.SoundID = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("Delay")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - tp.Delay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); - } - - if (m_ItemID > 0) - tp.ItemID = m_ItemID; - } - else if (item is FillableContainer cont) - { - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("ContentType")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - cont.ContentType = (FillableContentType)Enum.Parse(typeof(FillableContentType), - m_Params[i].Substring(++indexOf), true); - } - - if (m_ItemID > 0) - cont.ItemID = m_ItemID; - } - else if (m_ItemID > 0) - { - item.ItemID = m_ItemID; - } - - item.Movable = false; - - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("Light")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - item.Light = (LightType)Enum.Parse(typeof(LightType), m_Params[i].Substring(++indexOf), true); - } - else if (m_Params[i].StartsWith("Hue")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - { - int hue = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - - if (item is DyeTub tub) - tub.DyedHue = hue; - else - item.Hue = hue; - } - } - else if (m_Params[i].StartsWith("Name")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - item.Name = m_Params[i].Substring(++indexOf); - } - else if (m_Params[i].StartsWith("Amount")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - { - // Must supress stackable warnings - - bool wasStackable = item.Stackable; - - item.Stackable = true; - item.Amount = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - item.Stackable = wasStackable; - } - } - - return item; - } - - private static bool FindItem(int x, int y, int z, Map map, Item srcItem) - { - int itemID = srcItem.ItemID; - - bool res = false; - - IPooledEnumerable eable; - - if (srcItem is BaseDoor) - { - eable = map.GetItemsInRange(new Point3D(x, y, z), 1); - - foreach (Item item in eable) - { - if (!(item is BaseDoor)) - continue; - - BaseDoor bd = (BaseDoor)item; - Point3D p; - int bdItemID; - - if (bd.Open) - { - p = new Point3D(bd.X - bd.Offset.X, bd.Y - bd.Offset.Y, bd.Z - bd.Offset.Z); - bdItemID = bd.ClosedID; - } - else - { - p = bd.Location; - bdItemID = bd.ItemID; - } - - if (p.X != x || p.Y != y) - continue; - - if (item.Z == z && bdItemID == itemID) - res = true; - else if (Math.Abs(item.Z - z) < 8) - m_DeleteQueue.Enqueue(item); - } - } - else if ((TileData.ItemTable[itemID & TileData.MaxItemValue].Flags & TileFlag.LightSource) != 0) - { - eable = map.GetItemsInRange(new Point3D(x, y, z), 0); - - LightType lt = srcItem.Light; - string srcName = srcItem.ItemData.Name; - - foreach (Item item in eable) - if (item.Z == z) - { - if (item.ItemID == itemID) - { - if (item.Light != lt) - m_DeleteQueue.Enqueue(item); - else - res = true; - } - else if ((item.ItemData.Flags & TileFlag.LightSource) != 0 && item.ItemData.Name == srcName) - { - m_DeleteQueue.Enqueue(item); - } - } - } - else if (srcItem is Teleporter || srcItem is FillableContainer || srcItem is BaseBook) - { - eable = map.GetItemsInRange(new Point3D(x, y, z), 0); - - Type type = srcItem.GetType(); - - foreach (Item item in eable) - if (item.Z == z && item.ItemID == itemID) - { - if (item.GetType() != type) - m_DeleteQueue.Enqueue(item); - else - res = true; - } - } - else - { - eable = map.GetItemsInRange(new Point3D(x, y, z), 0); - - if (eable.Any(item => item.Z == z && item.ItemID == itemID)) - { - eable.Free(); - return true; - } - } - - eable.Free(); - - while (m_DeleteQueue.Count > 0) - m_DeleteQueue.Dequeue().Delete(); - - return res; - } - - public int Generate(Map[] maps) - { - int count = 0; - - Item item = null; - - for (int i = 0; i < m_Entries.Count; ++i) - { - DecorationEntry entry = m_Entries[i]; - Point3D loc = entry.Location; - string extra = entry.Extra; - - for (int j = 0; j < maps.Length; ++j) - { - try - { - item ??= Construct(); - } - catch (TypeInitializationException e) - { - Console.WriteLine($"{nameof(Generate)}() failed to load type: {e.TypeName}: {e.InnerException?.Message}"); - continue; - } - - if (item == null) - continue; - - if (FindItem(loc.X, loc.Y, loc.Z, maps[j], item)) - { - } - else - { - item.MoveToWorld(loc, maps[j]); - ++count; - - if (item is BaseDoor door) - { - IPooledEnumerable eable = maps[j].GetItemsInRange(loc, 1); - - Type itemType = door.GetType(); - - foreach (BaseDoor link in eable) - if (link != item && link.Z == door.Z && link.GetType() == itemType) - { - door.Link = link; - link.Link = door; - break; - } - - eable.Free(); - } - else if (item is MarkContainer markCont) - { - try - { - markCont.Target = Point3D.Parse(extra); - } - catch - { - // ignored - } - } - - item = null; - } - } - } - - item?.Delete(); - - return count; - } - - public static List ReadAll(string path) - { - using StreamReader ip = new StreamReader(path); - List list = new List(); - DecorationList v; - - while ((v = Read(ip)) != null) - list.Add(v); - - return list; - } - - public static DecorationList Read(StreamReader ip) - { - string line; - - while ((line = ip.ReadLine()) != null) - { - line = line.Trim(); - - if (line.Length > 0 && !line.StartsWith("#")) - break; - } - - if (string.IsNullOrEmpty(line)) - return null; - - DecorationList list = new DecorationList(); - - int indexOf = line.IndexOf(' '); - - list.m_Type = AssemblyHandler.FindFirstTypeForName(line.Substring(0, indexOf++), true); - - if (list.m_Type == null) - throw new ArgumentException($"Type not found for header: '{line}'"); - - line = line.Substring(indexOf); - indexOf = line.IndexOf('('); - if (indexOf >= 0) - { - list.m_ItemID = Utility.ToInt32(line.Substring(0, indexOf - 1)); - - string parms = line.Substring(++indexOf); - - if (line.EndsWith(")")) - parms = parms.Substring(0, parms.Length - 1); - - list.m_Params = parms.Split(';'); - - for (int i = 0; i < list.m_Params.Length; ++i) - list.m_Params[i] = list.m_Params[i].Trim(); - } - else - { - list.m_ItemID = Utility.ToInt32(line); - list.m_Params = m_EmptyParams; - } - - list.m_Entries = new List(); - - while ((line = ip.ReadLine()) != null) - { - line = line.Trim(); - - if (line.Length == 0) - break; - - if (line.StartsWith("#")) - continue; - - list.m_Entries.Add(new DecorationEntry(line)); - } - - return list; - } - } - - public class DecorationEntry - { - public DecorationEntry(string line) - { - Pop(out string x, ref line); - Pop(out string y, ref line); - Pop(out string z, ref line); - - Location = new Point3D(Utility.ToInt32(x), Utility.ToInt32(y), Utility.ToInt32(z)); - Extra = line; - } - - public Point3D Location { get; } - - public string Extra { get; } - - public static void Pop(out string v, ref string line) - { - int space = line.IndexOf(' '); - - if (space >= 0) - { - v = line.Substring(0, space++); - line = line.Substring(space); - } - else - { - v = line; - line = ""; - } - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Server.Engines.Quests.Haven; +using Server.Engines.Quests.Necro; +using Server.Engines.Spawners; +using Server.Items; +using Server.Utilities; + +namespace Server.Commands +{ + public static class Decorate + { + private static Mobile m_Mobile; + private static int m_Count; + + public static void Initialize() + { + CommandSystem.Register("Decorate", AccessLevel.Administrator, Decorate_OnCommand); + } + + [Usage("Decorate")] + [Description("Generates world decoration.")] + private static void Decorate_OnCommand(CommandEventArgs e) + { + m_Mobile = e.Mobile; + m_Count = 0; + + m_Mobile.SendMessage("Generating world decoration, please wait."); + + Generate("Data/Decoration/Britannia", Map.Trammel, Map.Felucca); + Generate("Data/Decoration/Trammel", Map.Trammel); + Generate("Data/Decoration/Felucca", Map.Felucca); + Generate("Data/Decoration/Ilshenar", Map.Ilshenar); + Generate("Data/Decoration/Malas", Map.Malas); + Generate("Data/Decoration/Tokuno", Map.Tokuno); + + m_Mobile.SendMessage("World generating complete. {0} items were generated.", m_Count); + } + + public static void Generate(string folder, params Map[] maps) + { + if (!Directory.Exists(folder)) + return; + + var files = Directory.GetFiles(folder, "*.cfg"); + + for (var i = 0; i < files.Length; ++i) + { + var list = DecorationList.ReadAll(files[i]); + + for (var j = 0; j < list.Count; ++j) + m_Count += list[j].Generate(maps); + } + } + } + + public class DecorationList + { + private static readonly Type typeofStatic = typeof(Static); + private static readonly Type typeofLocalizedStatic = typeof(LocalizedStatic); + private static readonly Type typeofBaseDoor = typeof(BaseDoor); + private static readonly Type typeofAnkhWest = typeof(AnkhWest); + private static readonly Type typeofAnkhNorth = typeof(AnkhNorth); + private static readonly Type typeofBeverage = typeof(BaseBeverage); + private static readonly Type typeofLocalizedSign = typeof(LocalizedSign); + private static readonly Type typeofMarkContainer = typeof(MarkContainer); + private static readonly Type typeofWarningItem = typeof(WarningItem); + private static readonly Type typeofHintItem = typeof(HintItem); + private static readonly Type typeofCannon = typeof(Cannon); + private static readonly Type typeofSerpentPillar = typeof(SerpentPillar); + + private static readonly Queue m_DeleteQueue = new Queue(); + + private static readonly string[] m_EmptyParams = Array.Empty(); + private List m_Entries; + private int m_ItemID; + private string[] m_Params; + private Type m_Type; + + public Item Construct() + { + if (m_Type == null) + return null; + + Item item; + + try + { + if (m_Type == typeofStatic) + { + item = new Static(m_ItemID); + } + else if (m_Type == typeofLocalizedStatic) + { + var labelNumber = 0; + + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("LabelNumber")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + { + labelNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + break; + } + } + + item = new LocalizedStatic(m_ItemID, labelNumber); + } + else if (m_Type == typeofLocalizedSign) + { + var labelNumber = 0; + + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("LabelNumber")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + { + labelNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + break; + } + } + + item = new LocalizedSign(m_ItemID, labelNumber); + } + else if (m_Type == typeofAnkhWest || m_Type == typeofAnkhNorth) + { + var bloodied = false; + + for (var i = 0; !bloodied && i < m_Params.Length; ++i) + bloodied = m_Params[i] == "Bloodied"; + + if (m_Type == typeofAnkhWest) + item = new AnkhWest(bloodied); + else + item = new AnkhNorth(bloodied); + } + else if (m_Type == typeofMarkContainer) + { + var bone = false; + var locked = false; + var map = Map.Malas; + + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i] == "Bone") + { + bone = true; + } + else if (m_Params[i] == "Locked") + { + locked = true; + } + else if (m_Params[i].StartsWith("TargetMap")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + map = Map.Parse(m_Params[i].Substring(++indexOf)); + } + + var mc = new MarkContainer(bone, locked); + + mc.TargetMap = map; + mc.Description = "strange location"; + + item = mc; + } + else if (m_Type == typeofHintItem) + { + var range = 0; + var messageNumber = 0; + string messageString = null; + var hintNumber = 0; + string hintString = null; + var resetDelay = TimeSpan.Zero; + + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("Range")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + range = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("WarningString")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + messageString = m_Params[i].Substring(++indexOf); + } + else if (m_Params[i].StartsWith("WarningNumber")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + messageNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("HintString")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + hintString = m_Params[i].Substring(++indexOf); + } + else if (m_Params[i].StartsWith("HintNumber")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + hintNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("ResetDelay")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + resetDelay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); + } + + var hi = new HintItem(m_ItemID, range, messageNumber, hintNumber); + + hi.WarningString = messageString; + hi.HintString = hintString; + hi.ResetDelay = resetDelay; + + item = hi; + } + else if (m_Type == typeofWarningItem) + { + var range = 0; + var messageNumber = 0; + string messageString = null; + var resetDelay = TimeSpan.Zero; + + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("Range")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + range = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("WarningString")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + messageString = m_Params[i].Substring(++indexOf); + } + else if (m_Params[i].StartsWith("WarningNumber")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + messageNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("ResetDelay")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + resetDelay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); + } + + var wi = new WarningItem(m_ItemID, range, messageNumber); + + wi.WarningString = messageString; + wi.ResetDelay = resetDelay; + + item = wi; + } + else if (m_Type == typeofCannon) + { + var direction = CannonDirection.North; + + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("CannonDirection")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + direction = (CannonDirection)Enum.Parse( + typeof(CannonDirection), + m_Params[i].Substring(++indexOf), + true + ); + } + + item = new Cannon(direction); + } + else if (m_Type == typeofSerpentPillar) + { + string word = null; + var destination = new Rectangle2D(); + + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("Word")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + word = m_Params[i].Substring(++indexOf); + } + else if (m_Params[i].StartsWith("DestStart")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + destination.Start = Point2D.Parse(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("DestEnd")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + destination.End = Point2D.Parse(m_Params[i].Substring(++indexOf)); + } + + item = new SerpentPillar(word, destination); + } + else if (m_Type.IsSubclassOf(typeofBeverage)) + { + var content = BeverageType.Liquor; + var fill = false; + + for (var i = 0; !fill && i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("Content")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + { + content = (BeverageType)Enum.Parse( + typeof(BeverageType), + m_Params[i].Substring(++indexOf), + true + ); + fill = true; + } + } + + if (fill) + item = (Item)ActivatorUtil.CreateInstance(m_Type, content); + else + item = (Item)ActivatorUtil.CreateInstance(m_Type); + } + else if (m_Type.IsSubclassOf(typeofBaseDoor)) + { + var facing = DoorFacing.WestCW; + + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("Facing")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + { + facing = (DoorFacing)Enum.Parse(typeof(DoorFacing), m_Params[i].Substring(++indexOf), true); + break; + } + } + + item = (Item)ActivatorUtil.CreateInstance(m_Type, facing); + } + else + { + item = (Item)ActivatorUtil.CreateInstance(m_Type); + } + } + catch (Exception e) + { + throw new TypeInitializationException(m_Type.ToString(), e); + } + + if (item is BaseAddon addon) + { + if (addon is MaabusCoffin coffin) + { + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("SpawnLocation")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + coffin.SpawnLocation = Point3D.Parse(m_Params[i].Substring(++indexOf)); + } + } + else if (m_ItemID > 0) + { + var comps = addon.Components; + + for (var i = 0; i < comps.Count; ++i) + { + var comp = comps[i]; + + if (comp.Offset == Point3D.Zero) + comp.ItemID = m_ItemID; + } + } + } + else if (item is BaseLight light) + { + bool unlit = false, unprotected = false; + + for (var i = 0; i < m_Params.Length; ++i) + { + if (!unlit && m_Params[i] == "Unlit") + unlit = true; + else if (!unprotected && m_Params[i] == "Unprotected") + unprotected = true; + + if (unlit && unprotected) + break; + } + + if (!unlit) + light.Ignite(); + if (!unprotected) + light.Protected = true; + + if (m_ItemID > 0) + light.ItemID = m_ItemID; + } + else if (item is Spawner sp) + { + sp.NextSpawn = TimeSpan.Zero; + + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("Spawn")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + sp.AddEntry(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("MinDelay")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + sp.MinDelay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("MaxDelay")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + sp.MaxDelay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("NextSpawn")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + sp.NextSpawn = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("Count")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + { + sp.Count = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + for (var se = 0; se < sp.Entries.Count; se++) + sp.Entries[se].SpawnedMaxCount = sp.Count; + } + } + else if (m_Params[i].StartsWith("Team")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + sp.Team = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("HomeRange")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + sp.HomeRange = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("Running")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + sp.Running = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("Group")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + sp.Group = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + } + else if (item is RecallRune rune) + { + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("Description")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + rune.Description = m_Params[i].Substring(++indexOf); + } + else if (m_Params[i].StartsWith("Marked")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + rune.Marked = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("TargetMap")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + rune.TargetMap = Map.Parse(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("Target")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + rune.Target = Point3D.Parse(m_Params[i].Substring(++indexOf)); + } + } + else if (item is SkillTeleporter st) + { + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("Skill")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.Skill = (SkillName)Enum.Parse(typeof(SkillName), m_Params[i].Substring(++indexOf), true); + } + else if (m_Params[i].StartsWith("RequiredFixedPoint")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.Required = Utility.ToInt32(m_Params[i].Substring(++indexOf)) * 0.1; + } + else if (m_Params[i].StartsWith("Required")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.Required = Utility.ToDouble(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("MessageString")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.MessageString = m_Params[i].Substring(++indexOf); + } + else if (m_Params[i].StartsWith("MessageNumber")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.MessageNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("PointDest")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.PointDest = Point3D.Parse(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("MapDest")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.MapDest = Map.Parse(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("Creatures")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.Creatures = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("SourceEffect")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.SourceEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("DestEffect")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.DestEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("SoundID")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.SoundID = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("Delay")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.Delay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); + } + + if (m_ItemID > 0) + st.ItemID = m_ItemID; + } + else if (item is KeywordTeleporter kt) + { + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("Substring")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + kt.Substring = m_Params[i].Substring(++indexOf); + } + else if (m_Params[i].StartsWith("Keyword")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + kt.Keyword = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("Range")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + kt.Range = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("PointDest")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + kt.PointDest = Point3D.Parse(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("MapDest")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + kt.MapDest = Map.Parse(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("Creatures")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + kt.Creatures = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("SourceEffect")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + kt.SourceEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("DestEffect")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + kt.DestEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("SoundID")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + kt.SoundID = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("Delay")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + kt.Delay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); + } + + if (m_ItemID > 0) + kt.ItemID = m_ItemID; + } + else if (item is Teleporter tp) + { + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("PointDest")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + tp.PointDest = Point3D.Parse(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("MapDest")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + tp.MapDest = Map.Parse(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("Creatures")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + tp.Creatures = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("SourceEffect")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + tp.SourceEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("DestEffect")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + tp.DestEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("SoundID")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + tp.SoundID = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("Delay")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + tp.Delay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); + } + + if (m_ItemID > 0) + tp.ItemID = m_ItemID; + } + else if (item is FillableContainer cont) + { + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("ContentType")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + cont.ContentType = (FillableContentType)Enum.Parse( + typeof(FillableContentType), + m_Params[i].Substring(++indexOf), + true + ); + } + + if (m_ItemID > 0) + cont.ItemID = m_ItemID; + } + else if (m_ItemID > 0) + { + item.ItemID = m_ItemID; + } + + item.Movable = false; + + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("Light")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + item.Light = (LightType)Enum.Parse(typeof(LightType), m_Params[i].Substring(++indexOf), true); + } + else if (m_Params[i].StartsWith("Hue")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + { + var hue = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + + if (item is DyeTub tub) + tub.DyedHue = hue; + else + item.Hue = hue; + } + } + else if (m_Params[i].StartsWith("Name")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + item.Name = m_Params[i].Substring(++indexOf); + } + else if (m_Params[i].StartsWith("Amount")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + { + // Must supress stackable warnings + + var wasStackable = item.Stackable; + + item.Stackable = true; + item.Amount = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + item.Stackable = wasStackable; + } + } + + return item; + } + + private static bool FindItem(int x, int y, int z, Map map, Item srcItem) + { + var itemID = srcItem.ItemID; + + var res = false; + + IPooledEnumerable eable; + + if (srcItem is BaseDoor) + { + eable = map.GetItemsInRange(new Point3D(x, y, z), 1); + + foreach (var item in eable) + { + if (!(item is BaseDoor)) + continue; + + var bd = (BaseDoor)item; + Point3D p; + int bdItemID; + + if (bd.Open) + { + p = new Point3D(bd.X - bd.Offset.X, bd.Y - bd.Offset.Y, bd.Z - bd.Offset.Z); + bdItemID = bd.ClosedID; + } + else + { + p = bd.Location; + bdItemID = bd.ItemID; + } + + if (p.X != x || p.Y != y) + continue; + + if (item.Z == z && bdItemID == itemID) + res = true; + else if (Math.Abs(item.Z - z) < 8) + m_DeleteQueue.Enqueue(item); + } + } + else if ((TileData.ItemTable[itemID & TileData.MaxItemValue].Flags & TileFlag.LightSource) != 0) + { + eable = map.GetItemsInRange(new Point3D(x, y, z), 0); + + var lt = srcItem.Light; + var srcName = srcItem.ItemData.Name; + + foreach (var item in eable) + if (item.Z == z) + { + if (item.ItemID == itemID) + { + if (item.Light != lt) + m_DeleteQueue.Enqueue(item); + else + res = true; + } + else if ((item.ItemData.Flags & TileFlag.LightSource) != 0 && item.ItemData.Name == srcName) + { + m_DeleteQueue.Enqueue(item); + } + } + } + else if (srcItem is Teleporter || srcItem is FillableContainer || srcItem is BaseBook) + { + eable = map.GetItemsInRange(new Point3D(x, y, z), 0); + + var type = srcItem.GetType(); + + foreach (var item in eable) + if (item.Z == z && item.ItemID == itemID) + { + if (item.GetType() != type) + m_DeleteQueue.Enqueue(item); + else + res = true; + } + } + else + { + eable = map.GetItemsInRange(new Point3D(x, y, z), 0); + + if (eable.Any(item => item.Z == z && item.ItemID == itemID)) + { + eable.Free(); + return true; + } + } + + eable.Free(); + + while (m_DeleteQueue.Count > 0) + m_DeleteQueue.Dequeue().Delete(); + + return res; + } + + public int Generate(Map[] maps) + { + var count = 0; + + Item item = null; + + for (var i = 0; i < m_Entries.Count; ++i) + { + var entry = m_Entries[i]; + var loc = entry.Location; + var extra = entry.Extra; + + for (var j = 0; j < maps.Length; ++j) + { + try + { + item ??= Construct(); + } + catch (TypeInitializationException e) + { + Console.WriteLine( + $"{nameof(Generate)}() failed to load type: {e.TypeName}: {e.InnerException?.Message}" + ); + continue; + } + + if (item == null) + continue; + + if (FindItem(loc.X, loc.Y, loc.Z, maps[j], item)) + { + } + else + { + item.MoveToWorld(loc, maps[j]); + ++count; + + if (item is BaseDoor door) + { + var eable = maps[j].GetItemsInRange(loc, 1); + + var itemType = door.GetType(); + + foreach (var link in eable) + if (link != item && link.Z == door.Z && link.GetType() == itemType) + { + door.Link = link; + link.Link = door; + break; + } + + eable.Free(); + } + else if (item is MarkContainer markCont) + { + try + { + markCont.Target = Point3D.Parse(extra); + } + catch + { + // ignored + } + } + + item = null; + } + } + } + + item?.Delete(); + + return count; + } + + public static List ReadAll(string path) + { + using var ip = new StreamReader(path); + var list = new List(); + DecorationList v; + + while ((v = Read(ip)) != null) + list.Add(v); + + return list; + } + + public static DecorationList Read(StreamReader ip) + { + string line; + + while ((line = ip.ReadLine()) != null) + { + line = line.Trim(); + + if (line.Length > 0 && !line.StartsWith("#")) + break; + } + + if (string.IsNullOrEmpty(line)) + return null; + + var list = new DecorationList(); + + var indexOf = line.IndexOf(' '); + + list.m_Type = AssemblyHandler.FindFirstTypeForName(line.Substring(0, indexOf++), true); + + if (list.m_Type == null) + throw new ArgumentException($"Type not found for header: '{line}'"); + + line = line.Substring(indexOf); + indexOf = line.IndexOf('('); + if (indexOf >= 0) + { + list.m_ItemID = Utility.ToInt32(line.Substring(0, indexOf - 1)); + + var parms = line.Substring(++indexOf); + + if (line.EndsWith(")")) + parms = parms.Substring(0, parms.Length - 1); + + list.m_Params = parms.Split(';'); + + for (var i = 0; i < list.m_Params.Length; ++i) + list.m_Params[i] = list.m_Params[i].Trim(); + } + else + { + list.m_ItemID = Utility.ToInt32(line); + list.m_Params = m_EmptyParams; + } + + list.m_Entries = new List(); + + while ((line = ip.ReadLine()) != null) + { + line = line.Trim(); + + if (line.Length == 0) + break; + + if (line.StartsWith("#")) + continue; + + list.m_Entries.Add(new DecorationEntry(line)); + } + + return list; + } + } + + public class DecorationEntry + { + public DecorationEntry(string line) + { + Pop(out var x, ref line); + Pop(out var y, ref line); + Pop(out var z, ref line); + + Location = new Point3D(Utility.ToInt32(x), Utility.ToInt32(y), Utility.ToInt32(z)); + Extra = line; + } + + public Point3D Location { get; } + + public string Extra { get; } + + public static void Pop(out string v, ref string line) + { + var space = line.IndexOf(' '); + + if (space >= 0) + { + v = line.Substring(0, space++); + line = line.Substring(space); + } + else + { + v = line; + line = ""; + } + } + } +} diff --git a/Projects/UOContent/Commands/Object Creation/DecorateMag.cs b/Projects/UOContent/Commands/Object Creation/DecorateMag.cs index 14ee9bb86..c29d8461e 100644 --- a/Projects/UOContent/Commands/Object Creation/DecorateMag.cs +++ b/Projects/UOContent/Commands/Object Creation/DecorateMag.cs @@ -1,1092 +1,1101 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Server.Engines.Quests.Haven; -using Server.Engines.Quests.Necro; -using Server.Engines.Spawners; -using Server.Items; -using Server.Utilities; - -namespace Server.Commands -{ - public static class DecorateMag - { - private static Mobile m_Mobile; - private static int m_Count; - - public static void Initialize() - { - CommandSystem.Register("DecorateMag", AccessLevel.Administrator, DecorateMag_OnCommand); - } - - [Usage("DecorateMag")] - [Description("Generates world decoration.")] - private static void DecorateMag_OnCommand(CommandEventArgs e) - { - m_Mobile = e.Mobile; - m_Count = 0; - - m_Mobile.SendMessage("Generating world decoration, please wait."); - - Generate("Data/Decoration/RuinedMaginciaTram", Map.Trammel); - Generate("Data/Decoration/RuinedMaginciaFel", Map.Felucca); - - m_Mobile.SendMessage("World generating complete. {0} items were generated.", m_Count); - } - - public static void Generate(string folder, params Map[] maps) - { - if (!Directory.Exists(folder)) - return; - - string[] files = Directory.GetFiles(folder, "*.cfg"); - - for (int i = 0; i < files.Length; ++i) - { - List list = DecorationListMag.ReadAll(files[i]); - - for (int j = 0; j < list.Count; ++j) - m_Count += list[j].Generate(maps); - } - } - } - - public class DecorationListMag - { - private static readonly Type typeofStatic = typeof(Static); - private static readonly Type typeofLocalizedStatic = typeof(LocalizedStatic); - private static readonly Type typeofBaseDoor = typeof(BaseDoor); - private static readonly Type typeofAnkhWest = typeof(AnkhWest); - private static readonly Type typeofAnkhNorth = typeof(AnkhNorth); - private static readonly Type typeofBeverage = typeof(BaseBeverage); - private static readonly Type typeofLocalizedSign = typeof(LocalizedSign); - private static readonly Type typeofMarkContainer = typeof(MarkContainer); - private static readonly Type typeofWarningItem = typeof(WarningItem); - private static readonly Type typeofHintItem = typeof(HintItem); - private static readonly Type typeofCannon = typeof(Cannon); - private static readonly Type typeofSerpentPillar = typeof(SerpentPillar); - - private static readonly Queue m_DeleteQueue = new Queue(); - - private static readonly string[] m_EmptyParams = Array.Empty(); - private List m_Entries; - private int m_ItemID; - private string[] m_Params; - private Type m_Type; - - public Item Construct() - { - if (m_Type == null) - return null; - - Item item; - - try - { - if (m_Type == typeofStatic) - { - item = new Static(m_ItemID); - } - else if (m_Type == typeofLocalizedStatic) - { - int labelNumber = 0; - - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("LabelNumber")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - { - labelNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - break; - } - } - - item = new LocalizedStatic(m_ItemID, labelNumber); - } - else if (m_Type == typeofLocalizedSign) - { - int labelNumber = 0; - - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("LabelNumber")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - { - labelNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - break; - } - } - - item = new LocalizedSign(m_ItemID, labelNumber); - } - else if (m_Type == typeofAnkhWest || m_Type == typeofAnkhNorth) - { - bool bloodied = false; - - for (int i = 0; !bloodied && i < m_Params.Length; ++i) - bloodied = m_Params[i] == "Bloodied"; - - if (m_Type == typeofAnkhWest) - item = new AnkhWest(bloodied); - else - item = new AnkhNorth(bloodied); - } - else if (m_Type == typeofMarkContainer) - { - bool bone = false; - bool locked = false; - Map map = Map.Malas; - - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i] == "Bone") - { - bone = true; - } - else if (m_Params[i] == "Locked") - { - locked = true; - } - else if (m_Params[i].StartsWith("TargetMap")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - map = Map.Parse(m_Params[i].Substring(++indexOf)); - } - - MarkContainer mc = new MarkContainer(bone, locked); - - mc.TargetMap = map; - mc.Description = "strange location"; - - item = mc; - } - else if (m_Type == typeofHintItem) - { - int range = 0; - int messageNumber = 0; - string messageString = null; - int hintNumber = 0; - string hintString = null; - TimeSpan resetDelay = TimeSpan.Zero; - - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("Range")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - range = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("WarningString")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - messageString = m_Params[i].Substring(++indexOf); - } - else if (m_Params[i].StartsWith("WarningNumber")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - messageNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("HintString")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - hintString = m_Params[i].Substring(++indexOf); - } - else if (m_Params[i].StartsWith("HintNumber")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - hintNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("ResetDelay")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - resetDelay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); - } - - HintItem hi = new HintItem(m_ItemID, range, messageNumber, hintNumber); - - hi.WarningString = messageString; - hi.HintString = hintString; - hi.ResetDelay = resetDelay; - - item = hi; - } - else if (m_Type == typeofWarningItem) - { - int range = 0; - int messageNumber = 0; - string messageString = null; - TimeSpan resetDelay = TimeSpan.Zero; - - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("Range")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - range = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("WarningString")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - messageString = m_Params[i].Substring(++indexOf); - } - else if (m_Params[i].StartsWith("WarningNumber")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - messageNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("ResetDelay")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - resetDelay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); - } - - WarningItem wi = new WarningItem(m_ItemID, range, messageNumber); - - wi.WarningString = messageString; - wi.ResetDelay = resetDelay; - - item = wi; - } - else if (m_Type == typeofCannon) - { - CannonDirection direction = CannonDirection.North; - - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("CannonDirection")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - direction = (CannonDirection)Enum.Parse(typeof(CannonDirection), - m_Params[i].Substring(++indexOf), true); - } - - item = new Cannon(direction); - } - else if (m_Type == typeofSerpentPillar) - { - string word = null; - Rectangle2D destination = new Rectangle2D(); - - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("Word")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - word = m_Params[i].Substring(++indexOf); - } - else if (m_Params[i].StartsWith("DestStart")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - destination.Start = Point2D.Parse(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("DestEnd")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - destination.End = Point2D.Parse(m_Params[i].Substring(++indexOf)); - } - - item = new SerpentPillar(word, destination); - } - else if (m_Type.IsSubclassOf(typeofBeverage)) - { - BeverageType content = BeverageType.Liquor; - bool fill = false; - - for (int i = 0; !fill && i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("Content")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - { - content = (BeverageType)Enum.Parse(typeof(BeverageType), m_Params[i].Substring(++indexOf), - true); - fill = true; - } - } - - if (fill) - item = (Item)ActivatorUtil.CreateInstance(m_Type, content); - else - item = (Item)ActivatorUtil.CreateInstance(m_Type); - } - else if (m_Type.IsSubclassOf(typeofBaseDoor)) - { - DoorFacing facing = DoorFacing.WestCW; - - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("Facing")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - { - facing = (DoorFacing)Enum.Parse(typeof(DoorFacing), m_Params[i].Substring(++indexOf), true); - break; - } - } - - item = (Item)ActivatorUtil.CreateInstance(m_Type, facing); - } - else - { - item = (Item)ActivatorUtil.CreateInstance(m_Type); - } - } - catch (Exception e) - { - throw new Exception($"Bad type: {m_Type}", e); - } - - if (item is BaseAddon addon) - { - if (addon is MaabusCoffin coffin) - { - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("SpawnLocation")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - coffin.SpawnLocation = Point3D.Parse(m_Params[i].Substring(++indexOf)); - } - } - else if (m_ItemID > 0) - { - List comps = addon.Components; - - for (int i = 0; i < comps.Count; ++i) - { - AddonComponent comp = comps[i]; - - if (comp.Offset == Point3D.Zero) - comp.ItemID = m_ItemID; - } - } - } - else if (item is BaseLight light) - { - bool unlit = false, unprotected = false; - - for (int i = 0; i < m_Params.Length; ++i) - { - if (!unlit && m_Params[i] == "Unlit") - unlit = true; - else if (!unprotected && m_Params[i] == "Unprotected") - unprotected = true; - - if (unlit && unprotected) - break; - } - - if (!unlit) - light.Ignite(); - if (!unprotected) - light.Protected = true; - - if (m_ItemID > 0) - light.ItemID = m_ItemID; - } - else if (item is Spawner sp) - { - sp.NextSpawn = TimeSpan.Zero; - - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("Spawn")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - sp.AddEntry(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("MinDelay")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - sp.MinDelay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("MaxDelay")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - sp.MaxDelay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("NextSpawn")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - sp.NextSpawn = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("Count")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - { - sp.Count = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - for (int se = 0; se < sp.Entries.Count; se++) - sp.Entries[se].SpawnedMaxCount = sp.Count; - } - } - else if (m_Params[i].StartsWith("Team")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - sp.Team = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("HomeRange")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - sp.HomeRange = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("Running")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - sp.Running = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("Group")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - sp.Group = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - } - else if (item is RecallRune rune) - { - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("Description")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - rune.Description = m_Params[i].Substring(++indexOf); - } - else if (m_Params[i].StartsWith("Marked")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - rune.Marked = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("TargetMap")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - rune.TargetMap = Map.Parse(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("Target")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - rune.Target = Point3D.Parse(m_Params[i].Substring(++indexOf)); - } - } - else if (item is SkillTeleporter st) - { - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("Skill")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.Skill = (SkillName)Enum.Parse(typeof(SkillName), m_Params[i].Substring(++indexOf), true); - } - else if (m_Params[i].StartsWith("RequiredFixedPoint")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.Required = Utility.ToInt32(m_Params[i].Substring(++indexOf)) * 0.1; - } - else if (m_Params[i].StartsWith("Required")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.Required = Utility.ToDouble(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("MessageString")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.MessageString = m_Params[i].Substring(++indexOf); - } - else if (m_Params[i].StartsWith("MessageNumber")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.MessageNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("PointDest")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.PointDest = Point3D.Parse(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("MapDest")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.MapDest = Map.Parse(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("Creatures")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.Creatures = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("SourceEffect")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.SourceEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("DestEffect")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.DestEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("SoundID")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.SoundID = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("Delay")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - st.Delay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); - } - - if (m_ItemID > 0) - st.ItemID = m_ItemID; - } - else if (item is KeywordTeleporter kt) - { - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("Substring")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - kt.Substring = m_Params[i].Substring(++indexOf); - } - else if (m_Params[i].StartsWith("Keyword")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - kt.Keyword = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("Range")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - kt.Range = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("PointDest")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - kt.PointDest = Point3D.Parse(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("MapDest")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - kt.MapDest = Map.Parse(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("Creatures")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - kt.Creatures = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("SourceEffect")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - kt.SourceEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("DestEffect")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - kt.DestEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("SoundID")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - kt.SoundID = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("Delay")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - kt.Delay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); - } - - if (m_ItemID > 0) - kt.ItemID = m_ItemID; - } - else if (item is Teleporter tp) - { - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("PointDest")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - tp.PointDest = Point3D.Parse(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("MapDest")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - tp.MapDest = Map.Parse(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("Creatures")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - tp.Creatures = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("SourceEffect")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - tp.SourceEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("DestEffect")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - tp.DestEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("SoundID")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - tp.SoundID = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - } - else if (m_Params[i].StartsWith("Delay")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - tp.Delay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); - } - - if (m_ItemID > 0) - tp.ItemID = m_ItemID; - } - else if (item is FillableContainer cont) - { - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("ContentType")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - cont.ContentType = (FillableContentType)Enum.Parse(typeof(FillableContentType), - m_Params[i].Substring(++indexOf), true); - } - - if (m_ItemID > 0) - cont.ItemID = m_ItemID; - } - else if (m_ItemID > 0) - { - item.ItemID = m_ItemID; - } - - item.Movable = false; - - for (int i = 0; i < m_Params.Length; ++i) - if (m_Params[i].StartsWith("Light")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - item.Light = (LightType)Enum.Parse(typeof(LightType), m_Params[i].Substring(++indexOf), true); - } - else if (m_Params[i].StartsWith("Hue")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - { - int hue = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - - if (item is DyeTub tub) - tub.DyedHue = hue; - else - item.Hue = hue; - } - } - else if (m_Params[i].StartsWith("Name")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - item.Name = m_Params[i].Substring(++indexOf); - } - else if (m_Params[i].StartsWith("Amount")) - { - int indexOf = m_Params[i].IndexOf('='); - - if (indexOf >= 0) - { - // Must suppress stackable warnings - - bool wasStackable = item.Stackable; - - item.Stackable = true; - item.Amount = Utility.ToInt32(m_Params[i].Substring(++indexOf)); - item.Stackable = wasStackable; - } - } - - return item; - } - - private static bool FindItem(int x, int y, int z, Map map, Item srcItem) - { - int itemID = srcItem.ItemID; - - bool res = false; - - IPooledEnumerable eable; - - if (srcItem is BaseDoor) - { - eable = map.GetItemsInRange(new Point3D(x, y, z), 1); - - foreach (Item item in eable) - { - if (!(item is BaseDoor)) - continue; - - BaseDoor bd = (BaseDoor)item; - Point3D p; - int bdItemID; - - if (bd.Open) - { - p = new Point3D(bd.X - bd.Offset.X, bd.Y - bd.Offset.Y, bd.Z - bd.Offset.Z); - bdItemID = bd.ClosedID; - } - else - { - p = bd.Location; - bdItemID = bd.ItemID; - } - - if (p.X != x || p.Y != y) - continue; - - if (item.Z == z && bdItemID == itemID) - res = true; - else if (Math.Abs(item.Z - z) < 8) - m_DeleteQueue.Enqueue(item); - } - } - else if ((TileData.ItemTable[itemID & TileData.MaxItemValue].Flags & TileFlag.LightSource) != 0) - { - eable = map.GetItemsInRange(new Point3D(x, y, z), 0); - - LightType lt = srcItem.Light; - string srcName = srcItem.ItemData.Name; - - foreach (Item item in eable) - if (item.Z == z) - { - if (item.ItemID == itemID) - { - if (item.Light != lt) - m_DeleteQueue.Enqueue(item); - else - res = true; - } - else if ((item.ItemData.Flags & TileFlag.LightSource) != 0 && item.ItemData.Name == srcName) - { - m_DeleteQueue.Enqueue(item); - } - } - } - else if (srcItem is Teleporter || srcItem is FillableContainer || srcItem is BaseBook) - { - eable = map.GetItemsInRange(new Point3D(x, y, z), 0); - - Type type = srcItem.GetType(); - - foreach (Item item in eable) - if (item.Z == z && item.ItemID == itemID) - { - if (item.GetType() != type) - m_DeleteQueue.Enqueue(item); - else - res = true; - } - } - else - { - eable = map.GetItemsInRange(new Point3D(x, y, z), 0); - - if (eable.Any(item => item.Z == z && item.ItemID == itemID)) - { - eable.Free(); - return true; - } - } - - eable.Free(); - - while (m_DeleteQueue.Count > 0) - ((Item)m_DeleteQueue.Dequeue()).Delete(); - - return res; - } - - public int Generate(Map[] maps) - { - int count = 0; - - Item item = null; - - for (int i = 0; i < m_Entries.Count; ++i) - { - DecorationEntryMag entry = m_Entries[i]; - Point3D loc = entry.Location; - string extra = entry.Extra; - - for (int j = 0; j < maps.Length; ++j) - { - item ??= Construct(); - - if (item == null) - continue; - - if (FindItem(loc.X, loc.Y, loc.Z, maps[j], item)) - { - } - else - { - item.MoveToWorld(loc, maps[j]); - ++count; - - if (item is BaseDoor door) - { - IPooledEnumerable eable = maps[j].GetItemsInRange(loc, 1); - - Type itemType = door.GetType(); - - foreach (BaseDoor link in eable) - if (link != item && link.Z == door.Z && link.GetType() == itemType) - { - door.Link = link; - link.Link = door; - break; - } - - eable.Free(); - } - else if (item is MarkContainer markCont) - { - try - { - markCont.Target = Point3D.Parse(extra); - } - catch - { - // ignored - } - } - - item = null; - } - } - } - - item?.Delete(); - - return count; - } - - public static List ReadAll(string path) - { - using StreamReader ip = new StreamReader(path); - List list = new List(); - - DecorationListMag v; - while ((v = Read(ip)) != null) - list.Add(v); - - return list; - } - - public static DecorationListMag Read(StreamReader ip) - { - string line; - - while ((line = ip.ReadLine()) != null) - { - line = line.Trim(); - - if (line.Length > 0 && !line.StartsWith("#")) - break; - } - - if (string.IsNullOrEmpty(line)) - return null; - - DecorationListMag list = new DecorationListMag(); - - int indexOf = line.IndexOf(' '); - - list.m_Type = AssemblyHandler.FindFirstTypeForName(line.Substring(0, indexOf++), true); - - if (list.m_Type == null) - throw new ArgumentException($"Type not found for header: '{line}'"); - - line = line.Substring(indexOf); - indexOf = line.IndexOf('('); - if (indexOf >= 0) - { - list.m_ItemID = Utility.ToInt32(line.Substring(0, indexOf - 1)); - - string parms = line.Substring(++indexOf); - - if (line.EndsWith(")")) - parms = parms.Substring(0, parms.Length - 1); - - list.m_Params = parms.Split(';'); - - for (int i = 0; i < list.m_Params.Length; ++i) - list.m_Params[i] = list.m_Params[i].Trim(); - } - else - { - list.m_ItemID = Utility.ToInt32(line); - list.m_Params = m_EmptyParams; - } - - list.m_Entries = new List(); - - while ((line = ip.ReadLine()) != null) - { - line = line.Trim(); - - if (line.Length == 0) - break; - - if (line.StartsWith("#")) - continue; - - list.m_Entries.Add(new DecorationEntryMag(line)); - } - - return list; - } - } - - public class DecorationEntryMag - { - public DecorationEntryMag(string line) - { - Pop(out string x, ref line); - Pop(out string y, ref line); - Pop(out string z, ref line); - - Location = new Point3D(Utility.ToInt32(x), Utility.ToInt32(y), Utility.ToInt32(z)); - Extra = line; - } - - public Point3D Location { get; } - - public string Extra { get; } - - public void Pop(out string v, ref string line) - { - int space = line.IndexOf(' '); - - if (space >= 0) - { - v = line.Substring(0, space++); - line = line.Substring(space); - } - else - { - v = line; - line = ""; - } - } - } -} +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Server.Engines.Quests.Haven; +using Server.Engines.Quests.Necro; +using Server.Engines.Spawners; +using Server.Items; +using Server.Utilities; + +namespace Server.Commands +{ + public static class DecorateMag + { + private static Mobile m_Mobile; + private static int m_Count; + + public static void Initialize() + { + CommandSystem.Register("DecorateMag", AccessLevel.Administrator, DecorateMag_OnCommand); + } + + [Usage("DecorateMag")] + [Description("Generates world decoration.")] + private static void DecorateMag_OnCommand(CommandEventArgs e) + { + m_Mobile = e.Mobile; + m_Count = 0; + + m_Mobile.SendMessage("Generating world decoration, please wait."); + + Generate("Data/Decoration/RuinedMaginciaTram", Map.Trammel); + Generate("Data/Decoration/RuinedMaginciaFel", Map.Felucca); + + m_Mobile.SendMessage("World generating complete. {0} items were generated.", m_Count); + } + + public static void Generate(string folder, params Map[] maps) + { + if (!Directory.Exists(folder)) + return; + + var files = Directory.GetFiles(folder, "*.cfg"); + + for (var i = 0; i < files.Length; ++i) + { + var list = DecorationListMag.ReadAll(files[i]); + + for (var j = 0; j < list.Count; ++j) + m_Count += list[j].Generate(maps); + } + } + } + + public class DecorationListMag + { + private static readonly Type typeofStatic = typeof(Static); + private static readonly Type typeofLocalizedStatic = typeof(LocalizedStatic); + private static readonly Type typeofBaseDoor = typeof(BaseDoor); + private static readonly Type typeofAnkhWest = typeof(AnkhWest); + private static readonly Type typeofAnkhNorth = typeof(AnkhNorth); + private static readonly Type typeofBeverage = typeof(BaseBeverage); + private static readonly Type typeofLocalizedSign = typeof(LocalizedSign); + private static readonly Type typeofMarkContainer = typeof(MarkContainer); + private static readonly Type typeofWarningItem = typeof(WarningItem); + private static readonly Type typeofHintItem = typeof(HintItem); + private static readonly Type typeofCannon = typeof(Cannon); + private static readonly Type typeofSerpentPillar = typeof(SerpentPillar); + + private static readonly Queue m_DeleteQueue = new Queue(); + + private static readonly string[] m_EmptyParams = Array.Empty(); + private List m_Entries; + private int m_ItemID; + private string[] m_Params; + private Type m_Type; + + public Item Construct() + { + if (m_Type == null) + return null; + + Item item; + + try + { + if (m_Type == typeofStatic) + { + item = new Static(m_ItemID); + } + else if (m_Type == typeofLocalizedStatic) + { + var labelNumber = 0; + + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("LabelNumber")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + { + labelNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + break; + } + } + + item = new LocalizedStatic(m_ItemID, labelNumber); + } + else if (m_Type == typeofLocalizedSign) + { + var labelNumber = 0; + + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("LabelNumber")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + { + labelNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + break; + } + } + + item = new LocalizedSign(m_ItemID, labelNumber); + } + else if (m_Type == typeofAnkhWest || m_Type == typeofAnkhNorth) + { + var bloodied = false; + + for (var i = 0; !bloodied && i < m_Params.Length; ++i) + bloodied = m_Params[i] == "Bloodied"; + + if (m_Type == typeofAnkhWest) + item = new AnkhWest(bloodied); + else + item = new AnkhNorth(bloodied); + } + else if (m_Type == typeofMarkContainer) + { + var bone = false; + var locked = false; + var map = Map.Malas; + + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i] == "Bone") + { + bone = true; + } + else if (m_Params[i] == "Locked") + { + locked = true; + } + else if (m_Params[i].StartsWith("TargetMap")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + map = Map.Parse(m_Params[i].Substring(++indexOf)); + } + + var mc = new MarkContainer(bone, locked); + + mc.TargetMap = map; + mc.Description = "strange location"; + + item = mc; + } + else if (m_Type == typeofHintItem) + { + var range = 0; + var messageNumber = 0; + string messageString = null; + var hintNumber = 0; + string hintString = null; + var resetDelay = TimeSpan.Zero; + + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("Range")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + range = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("WarningString")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + messageString = m_Params[i].Substring(++indexOf); + } + else if (m_Params[i].StartsWith("WarningNumber")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + messageNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("HintString")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + hintString = m_Params[i].Substring(++indexOf); + } + else if (m_Params[i].StartsWith("HintNumber")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + hintNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("ResetDelay")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + resetDelay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); + } + + var hi = new HintItem(m_ItemID, range, messageNumber, hintNumber); + + hi.WarningString = messageString; + hi.HintString = hintString; + hi.ResetDelay = resetDelay; + + item = hi; + } + else if (m_Type == typeofWarningItem) + { + var range = 0; + var messageNumber = 0; + string messageString = null; + var resetDelay = TimeSpan.Zero; + + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("Range")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + range = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("WarningString")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + messageString = m_Params[i].Substring(++indexOf); + } + else if (m_Params[i].StartsWith("WarningNumber")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + messageNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("ResetDelay")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + resetDelay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); + } + + var wi = new WarningItem(m_ItemID, range, messageNumber); + + wi.WarningString = messageString; + wi.ResetDelay = resetDelay; + + item = wi; + } + else if (m_Type == typeofCannon) + { + var direction = CannonDirection.North; + + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("CannonDirection")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + direction = (CannonDirection)Enum.Parse( + typeof(CannonDirection), + m_Params[i].Substring(++indexOf), + true + ); + } + + item = new Cannon(direction); + } + else if (m_Type == typeofSerpentPillar) + { + string word = null; + var destination = new Rectangle2D(); + + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("Word")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + word = m_Params[i].Substring(++indexOf); + } + else if (m_Params[i].StartsWith("DestStart")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + destination.Start = Point2D.Parse(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("DestEnd")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + destination.End = Point2D.Parse(m_Params[i].Substring(++indexOf)); + } + + item = new SerpentPillar(word, destination); + } + else if (m_Type.IsSubclassOf(typeofBeverage)) + { + var content = BeverageType.Liquor; + var fill = false; + + for (var i = 0; !fill && i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("Content")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + { + content = (BeverageType)Enum.Parse( + typeof(BeverageType), + m_Params[i].Substring(++indexOf), + true + ); + fill = true; + } + } + + if (fill) + item = (Item)ActivatorUtil.CreateInstance(m_Type, content); + else + item = (Item)ActivatorUtil.CreateInstance(m_Type); + } + else if (m_Type.IsSubclassOf(typeofBaseDoor)) + { + var facing = DoorFacing.WestCW; + + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("Facing")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + { + facing = (DoorFacing)Enum.Parse(typeof(DoorFacing), m_Params[i].Substring(++indexOf), true); + break; + } + } + + item = (Item)ActivatorUtil.CreateInstance(m_Type, facing); + } + else + { + item = (Item)ActivatorUtil.CreateInstance(m_Type); + } + } + catch (Exception e) + { + throw new Exception($"Bad type: {m_Type}", e); + } + + if (item is BaseAddon addon) + { + if (addon is MaabusCoffin coffin) + { + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("SpawnLocation")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + coffin.SpawnLocation = Point3D.Parse(m_Params[i].Substring(++indexOf)); + } + } + else if (m_ItemID > 0) + { + var comps = addon.Components; + + for (var i = 0; i < comps.Count; ++i) + { + var comp = comps[i]; + + if (comp.Offset == Point3D.Zero) + comp.ItemID = m_ItemID; + } + } + } + else if (item is BaseLight light) + { + bool unlit = false, unprotected = false; + + for (var i = 0; i < m_Params.Length; ++i) + { + if (!unlit && m_Params[i] == "Unlit") + unlit = true; + else if (!unprotected && m_Params[i] == "Unprotected") + unprotected = true; + + if (unlit && unprotected) + break; + } + + if (!unlit) + light.Ignite(); + if (!unprotected) + light.Protected = true; + + if (m_ItemID > 0) + light.ItemID = m_ItemID; + } + else if (item is Spawner sp) + { + sp.NextSpawn = TimeSpan.Zero; + + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("Spawn")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + sp.AddEntry(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("MinDelay")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + sp.MinDelay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("MaxDelay")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + sp.MaxDelay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("NextSpawn")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + sp.NextSpawn = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("Count")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + { + sp.Count = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + for (var se = 0; se < sp.Entries.Count; se++) + sp.Entries[se].SpawnedMaxCount = sp.Count; + } + } + else if (m_Params[i].StartsWith("Team")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + sp.Team = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("HomeRange")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + sp.HomeRange = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("Running")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + sp.Running = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("Group")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + sp.Group = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + } + else if (item is RecallRune rune) + { + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("Description")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + rune.Description = m_Params[i].Substring(++indexOf); + } + else if (m_Params[i].StartsWith("Marked")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + rune.Marked = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("TargetMap")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + rune.TargetMap = Map.Parse(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("Target")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + rune.Target = Point3D.Parse(m_Params[i].Substring(++indexOf)); + } + } + else if (item is SkillTeleporter st) + { + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("Skill")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.Skill = (SkillName)Enum.Parse(typeof(SkillName), m_Params[i].Substring(++indexOf), true); + } + else if (m_Params[i].StartsWith("RequiredFixedPoint")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.Required = Utility.ToInt32(m_Params[i].Substring(++indexOf)) * 0.1; + } + else if (m_Params[i].StartsWith("Required")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.Required = Utility.ToDouble(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("MessageString")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.MessageString = m_Params[i].Substring(++indexOf); + } + else if (m_Params[i].StartsWith("MessageNumber")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.MessageNumber = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("PointDest")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.PointDest = Point3D.Parse(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("MapDest")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.MapDest = Map.Parse(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("Creatures")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.Creatures = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("SourceEffect")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.SourceEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("DestEffect")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.DestEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("SoundID")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.SoundID = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("Delay")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + st.Delay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); + } + + if (m_ItemID > 0) + st.ItemID = m_ItemID; + } + else if (item is KeywordTeleporter kt) + { + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("Substring")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + kt.Substring = m_Params[i].Substring(++indexOf); + } + else if (m_Params[i].StartsWith("Keyword")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + kt.Keyword = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("Range")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + kt.Range = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("PointDest")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + kt.PointDest = Point3D.Parse(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("MapDest")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + kt.MapDest = Map.Parse(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("Creatures")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + kt.Creatures = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("SourceEffect")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + kt.SourceEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("DestEffect")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + kt.DestEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("SoundID")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + kt.SoundID = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("Delay")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + kt.Delay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); + } + + if (m_ItemID > 0) + kt.ItemID = m_ItemID; + } + else if (item is Teleporter tp) + { + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("PointDest")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + tp.PointDest = Point3D.Parse(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("MapDest")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + tp.MapDest = Map.Parse(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("Creatures")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + tp.Creatures = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("SourceEffect")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + tp.SourceEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("DestEffect")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + tp.DestEffect = Utility.ToBoolean(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("SoundID")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + tp.SoundID = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + } + else if (m_Params[i].StartsWith("Delay")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + tp.Delay = TimeSpan.Parse(m_Params[i].Substring(++indexOf)); + } + + if (m_ItemID > 0) + tp.ItemID = m_ItemID; + } + else if (item is FillableContainer cont) + { + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("ContentType")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + cont.ContentType = (FillableContentType)Enum.Parse( + typeof(FillableContentType), + m_Params[i].Substring(++indexOf), + true + ); + } + + if (m_ItemID > 0) + cont.ItemID = m_ItemID; + } + else if (m_ItemID > 0) + { + item.ItemID = m_ItemID; + } + + item.Movable = false; + + for (var i = 0; i < m_Params.Length; ++i) + if (m_Params[i].StartsWith("Light")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + item.Light = (LightType)Enum.Parse(typeof(LightType), m_Params[i].Substring(++indexOf), true); + } + else if (m_Params[i].StartsWith("Hue")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + { + var hue = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + + if (item is DyeTub tub) + tub.DyedHue = hue; + else + item.Hue = hue; + } + } + else if (m_Params[i].StartsWith("Name")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + item.Name = m_Params[i].Substring(++indexOf); + } + else if (m_Params[i].StartsWith("Amount")) + { + var indexOf = m_Params[i].IndexOf('='); + + if (indexOf >= 0) + { + // Must suppress stackable warnings + + var wasStackable = item.Stackable; + + item.Stackable = true; + item.Amount = Utility.ToInt32(m_Params[i].Substring(++indexOf)); + item.Stackable = wasStackable; + } + } + + return item; + } + + private static bool FindItem(int x, int y, int z, Map map, Item srcItem) + { + var itemID = srcItem.ItemID; + + var res = false; + + IPooledEnumerable eable; + + if (srcItem is BaseDoor) + { + eable = map.GetItemsInRange(new Point3D(x, y, z), 1); + + foreach (var item in eable) + { + if (!(item is BaseDoor)) + continue; + + var bd = (BaseDoor)item; + Point3D p; + int bdItemID; + + if (bd.Open) + { + p = new Point3D(bd.X - bd.Offset.X, bd.Y - bd.Offset.Y, bd.Z - bd.Offset.Z); + bdItemID = bd.ClosedID; + } + else + { + p = bd.Location; + bdItemID = bd.ItemID; + } + + if (p.X != x || p.Y != y) + continue; + + if (item.Z == z && bdItemID == itemID) + res = true; + else if (Math.Abs(item.Z - z) < 8) + m_DeleteQueue.Enqueue(item); + } + } + else if ((TileData.ItemTable[itemID & TileData.MaxItemValue].Flags & TileFlag.LightSource) != 0) + { + eable = map.GetItemsInRange(new Point3D(x, y, z), 0); + + var lt = srcItem.Light; + var srcName = srcItem.ItemData.Name; + + foreach (var item in eable) + if (item.Z == z) + { + if (item.ItemID == itemID) + { + if (item.Light != lt) + m_DeleteQueue.Enqueue(item); + else + res = true; + } + else if ((item.ItemData.Flags & TileFlag.LightSource) != 0 && item.ItemData.Name == srcName) + { + m_DeleteQueue.Enqueue(item); + } + } + } + else if (srcItem is Teleporter || srcItem is FillableContainer || srcItem is BaseBook) + { + eable = map.GetItemsInRange(new Point3D(x, y, z), 0); + + var type = srcItem.GetType(); + + foreach (var item in eable) + if (item.Z == z && item.ItemID == itemID) + { + if (item.GetType() != type) + m_DeleteQueue.Enqueue(item); + else + res = true; + } + } + else + { + eable = map.GetItemsInRange(new Point3D(x, y, z), 0); + + if (eable.Any(item => item.Z == z && item.ItemID == itemID)) + { + eable.Free(); + return true; + } + } + + eable.Free(); + + while (m_DeleteQueue.Count > 0) + ((Item)m_DeleteQueue.Dequeue()).Delete(); + + return res; + } + + public int Generate(Map[] maps) + { + var count = 0; + + Item item = null; + + for (var i = 0; i < m_Entries.Count; ++i) + { + var entry = m_Entries[i]; + var loc = entry.Location; + var extra = entry.Extra; + + for (var j = 0; j < maps.Length; ++j) + { + item ??= Construct(); + + if (item == null) + continue; + + if (FindItem(loc.X, loc.Y, loc.Z, maps[j], item)) + { + } + else + { + item.MoveToWorld(loc, maps[j]); + ++count; + + if (item is BaseDoor door) + { + var eable = maps[j].GetItemsInRange(loc, 1); + + var itemType = door.GetType(); + + foreach (var link in eable) + if (link != item && link.Z == door.Z && link.GetType() == itemType) + { + door.Link = link; + link.Link = door; + break; + } + + eable.Free(); + } + else if (item is MarkContainer markCont) + { + try + { + markCont.Target = Point3D.Parse(extra); + } + catch + { + // ignored + } + } + + item = null; + } + } + } + + item?.Delete(); + + return count; + } + + public static List ReadAll(string path) + { + using var ip = new StreamReader(path); + var list = new List(); + + DecorationListMag v; + while ((v = Read(ip)) != null) + list.Add(v); + + return list; + } + + public static DecorationListMag Read(StreamReader ip) + { + string line; + + while ((line = ip.ReadLine()) != null) + { + line = line.Trim(); + + if (line.Length > 0 && !line.StartsWith("#")) + break; + } + + if (string.IsNullOrEmpty(line)) + return null; + + var list = new DecorationListMag(); + + var indexOf = line.IndexOf(' '); + + list.m_Type = AssemblyHandler.FindFirstTypeForName(line.Substring(0, indexOf++), true); + + if (list.m_Type == null) + throw new ArgumentException($"Type not found for header: '{line}'"); + + line = line.Substring(indexOf); + indexOf = line.IndexOf('('); + if (indexOf >= 0) + { + list.m_ItemID = Utility.ToInt32(line.Substring(0, indexOf - 1)); + + var parms = line.Substring(++indexOf); + + if (line.EndsWith(")")) + parms = parms.Substring(0, parms.Length - 1); + + list.m_Params = parms.Split(';'); + + for (var i = 0; i < list.m_Params.Length; ++i) + list.m_Params[i] = list.m_Params[i].Trim(); + } + else + { + list.m_ItemID = Utility.ToInt32(line); + list.m_Params = m_EmptyParams; + } + + list.m_Entries = new List(); + + while ((line = ip.ReadLine()) != null) + { + line = line.Trim(); + + if (line.Length == 0) + break; + + if (line.StartsWith("#")) + continue; + + list.m_Entries.Add(new DecorationEntryMag(line)); + } + + return list; + } + } + + public class DecorationEntryMag + { + public DecorationEntryMag(string line) + { + Pop(out var x, ref line); + Pop(out var y, ref line); + Pop(out var z, ref line); + + Location = new Point3D(Utility.ToInt32(x), Utility.ToInt32(y), Utility.ToInt32(z)); + Extra = line; + } + + public Point3D Location { get; } + + public string Extra { get; } + + public void Pop(out string v, ref string line) + { + var space = line.IndexOf(' '); + + if (space >= 0) + { + v = line.Substring(0, space++); + line = line.Substring(space); + } + else + { + v = line; + line = ""; + } + } + } +} diff --git a/Projects/UOContent/Commands/Object Creation/GenTeleporter.cs b/Projects/UOContent/Commands/Object Creation/GenTeleporter.cs index 36ed33cd0..2e66b53b8 100644 --- a/Projects/UOContent/Commands/Object Creation/GenTeleporter.cs +++ b/Projects/UOContent/Commands/Object Creation/GenTeleporter.cs @@ -1,152 +1,154 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text.Json; -using System.Text.Json.Serialization; -using Server.Items; - -namespace Server.Commands -{ - public struct TeleporterDefinition - { - [JsonPropertyName("src")] - public WorldLocation Source { get; set; } - - [JsonPropertyName("dst")] - public WorldLocation Destination { get; set; } - - [JsonPropertyName("back")] - public bool Back { get; set; } - - public override string ToString() => $"{{{Source},{Destination},{Back}}}"; - - public bool Equals(TeleporterDefinition other) => - Source.Equals(other.Source) && Destination.Equals(other.Destination) && Back == other.Back; - - public override bool Equals(object obj) => obj is TeleporterDefinition other && Equals(other); - - public override int GetHashCode() => HashCode.Combine(Source, Destination, Back); - } - - public static class GenTeleporter - { - private const int SuccessHue = 72, WarningHue = 53, ErrorHue = 33; - private static readonly string TeleporterJsonDataPath = Path.Combine("Data", "teleporters.json"); - private static readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions - { - AllowTrailingCommas = true, - PropertyNameCaseInsensitive = true, - ReadCommentHandling = JsonCommentHandling.Skip - }; - - public static void Initialize() - { - CommandSystem.Register("TelGen", AccessLevel.Administrator, GenTeleporter_OnCommand); - CommandSystem.Register("TelGenDelete", AccessLevel.Administrator, TelGenDelete_OnCommand); - } - - [Usage("TelGenDelete")] - [Description("Destroys world/dungeon teleporters for all facets.")] - public static void TelGenDelete_OnCommand(CommandEventArgs e) - { - Mobile from = e.Mobile; - - from.SendMessage("Removing teleporters, please wait."); - int count = 0; - - void ProcessDeletion(TeleporterDefinition x) - { - count += TeleportersCreator.DeleteTeleporters(x.Source); - if (x.Back) count += TeleportersCreator.DeleteTeleporters(x.Destination); - } - - if (!ProcessTeleporterData(from, ProcessDeletion)) - { - if (count > 0) - from.SendMessage(WarningHue, $"Partial Completion, {count} Teleporters Removed."); - return; - } - - from.SendMessage(WarningHue, $"{count} Teleporters Removed."); - } - - [Usage("TelGen")] - [Description("Generates world/dungeon teleporters for all facets.")] - public static void GenTeleporter_OnCommand(CommandEventArgs e) - { - Mobile from = e.Mobile; - - from.SendMessage("Generating teleporters, please wait."); - TeleportersCreator c = new TeleportersCreator(); - - if (!ProcessTeleporterData(from, c.CreateTeleporter)) - { - if (c.DelCount > 0) - from.SendMessage(WarningHue, $"Partial Completion: {c.DelCount} Teleporters Removed."); - if (c.Count > 0) - from.SendMessage(WarningHue, $"Partial Completion: {c.Count} Teleporters Added."); - return; - } - - from.SendMessage(SuccessHue, "Teleporter generating complete."); - from.SendMessage(WarningHue, $"{c.DelCount} Teleporters Removed."); - from.SendMessage(SuccessHue, $"{c.Count} Teleporters Added."); - } - - private static bool ProcessTeleporterData(Mobile m, Action processor) - { - try - { - string json; - using (StreamReader reader = new StreamReader(TeleporterJsonDataPath)) - json = reader.ReadToEnd(); - var teleporters = JsonSerializer.Deserialize>(json, JsonOptions); - for (int i = 0; i < teleporters.Count; i++) - processor(teleporters[i]); - } - catch (Exception ex) - { - Console.WriteLine(ex.ToString()); - m.SendMessage(ErrorHue, $"Failed to load/process data file '{TeleporterJsonDataPath}'"); - return false; - } - - return true; - } - - private class TeleportersCreator - { - public int Count { get; private set; } - public int DelCount { get; private set; } - - private static bool IsWithinZ(int delta) => delta >= -12 && delta <= 12; - - public static int DeleteTeleporters(WorldLocation worldLocation) - { - IPooledEnumerable eable = worldLocation.Map.GetItemsInRange(worldLocation, 0); - var items = eable - .Where(x => !(x is KeywordTeleporter || x is SkillTeleporter) && IsWithinZ(x.Z - worldLocation.Z)); - int count = 0; - foreach (var item in items) - { - count++; - item.Delete(); - } - eable.Free(); - return count; - } - - public void CreateTeleporter(TeleporterDefinition telDef) - { - DelCount += DeleteTeleporters(telDef.Source); - Count++; - new Teleporter(telDef.Destination, telDef.Destination.Map).MoveToWorld(telDef.Source, telDef.Source.Map); - if (!telDef.Back) return; - DelCount += DeleteTeleporters(telDef.Destination); - Count++; - new Teleporter(telDef.Source, telDef.Source.Map).MoveToWorld(telDef.Destination, telDef.Destination.Map); - } - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.Json; +using System.Text.Json.Serialization; +using Server.Items; + +namespace Server.Commands +{ + public struct TeleporterDefinition + { + [JsonPropertyName("src")] public WorldLocation Source { get; set; } + + [JsonPropertyName("dst")] public WorldLocation Destination { get; set; } + + [JsonPropertyName("back")] public bool Back { get; set; } + + public override string ToString() => $"{{{Source},{Destination},{Back}}}"; + + public bool Equals(TeleporterDefinition other) => + Source.Equals(other.Source) && Destination.Equals(other.Destination) && Back == other.Back; + + public override bool Equals(object obj) => obj is TeleporterDefinition other && Equals(other); + + public override int GetHashCode() => HashCode.Combine(Source, Destination, Back); + } + + public static class GenTeleporter + { + private const int SuccessHue = 72, WarningHue = 53, ErrorHue = 33; + private static readonly string TeleporterJsonDataPath = Path.Combine("Data", "teleporters.json"); + + private static readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions + { + AllowTrailingCommas = true, + PropertyNameCaseInsensitive = true, + ReadCommentHandling = JsonCommentHandling.Skip + }; + + public static void Initialize() + { + CommandSystem.Register("TelGen", AccessLevel.Administrator, GenTeleporter_OnCommand); + CommandSystem.Register("TelGenDelete", AccessLevel.Administrator, TelGenDelete_OnCommand); + } + + [Usage("TelGenDelete")] + [Description("Destroys world/dungeon teleporters for all facets.")] + public static void TelGenDelete_OnCommand(CommandEventArgs e) + { + var from = e.Mobile; + + from.SendMessage("Removing teleporters, please wait."); + var count = 0; + + void ProcessDeletion(TeleporterDefinition x) + { + count += TeleportersCreator.DeleteTeleporters(x.Source); + if (x.Back) count += TeleportersCreator.DeleteTeleporters(x.Destination); + } + + if (!ProcessTeleporterData(from, ProcessDeletion)) + { + if (count > 0) + from.SendMessage(WarningHue, $"Partial Completion, {count} Teleporters Removed."); + return; + } + + from.SendMessage(WarningHue, $"{count} Teleporters Removed."); + } + + [Usage("TelGen")] + [Description("Generates world/dungeon teleporters for all facets.")] + public static void GenTeleporter_OnCommand(CommandEventArgs e) + { + var from = e.Mobile; + + from.SendMessage("Generating teleporters, please wait."); + var c = new TeleportersCreator(); + + if (!ProcessTeleporterData(from, c.CreateTeleporter)) + { + if (c.DelCount > 0) + from.SendMessage(WarningHue, $"Partial Completion: {c.DelCount} Teleporters Removed."); + if (c.Count > 0) + from.SendMessage(WarningHue, $"Partial Completion: {c.Count} Teleporters Added."); + return; + } + + from.SendMessage(SuccessHue, "Teleporter generating complete."); + from.SendMessage(WarningHue, $"{c.DelCount} Teleporters Removed."); + from.SendMessage(SuccessHue, $"{c.Count} Teleporters Added."); + } + + private static bool ProcessTeleporterData(Mobile m, Action processor) + { + try + { + string json; + using (var reader = new StreamReader(TeleporterJsonDataPath)) + { + json = reader.ReadToEnd(); + } + + var teleporters = JsonSerializer.Deserialize>(json, JsonOptions); + for (var i = 0; i < teleporters.Count; i++) + processor(teleporters[i]); + } + catch (Exception ex) + { + Console.WriteLine(ex.ToString()); + m.SendMessage(ErrorHue, $"Failed to load/process data file '{TeleporterJsonDataPath}'"); + return false; + } + + return true; + } + + private class TeleportersCreator + { + public int Count { get; private set; } + public int DelCount { get; private set; } + + private static bool IsWithinZ(int delta) => delta >= -12 && delta <= 12; + + public static int DeleteTeleporters(WorldLocation worldLocation) + { + var eable = worldLocation.Map.GetItemsInRange(worldLocation, 0); + var items = eable + .Where(x => !(x is KeywordTeleporter || x is SkillTeleporter) && IsWithinZ(x.Z - worldLocation.Z)); + var count = 0; + foreach (var item in items) + { + count++; + item.Delete(); + } + + eable.Free(); + return count; + } + + public void CreateTeleporter(TeleporterDefinition telDef) + { + DelCount += DeleteTeleporters(telDef.Source); + Count++; + new Teleporter(telDef.Destination, telDef.Destination.Map).MoveToWorld(telDef.Source, telDef.Source.Map); + if (!telDef.Back) return; + DelCount += DeleteTeleporters(telDef.Destination); + Count++; + new Teleporter(telDef.Source, telDef.Source.Map).MoveToWorld(telDef.Destination, telDef.Destination.Map); + } + } + } +} diff --git a/Projects/UOContent/Commands/Profiling.cs b/Projects/UOContent/Commands/Profiling.cs index dd752908e..a8f02cbc5 100644 --- a/Projects/UOContent/Commands/Profiling.cs +++ b/Projects/UOContent/Commands/Profiling.cs @@ -1,360 +1,380 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Server.Diagnostics; - -namespace Server.Commands -{ - public static class Profiling - { - public static void Initialize() - { - CommandSystem.Register("DumpTimers", AccessLevel.Administrator, DumpTimers_OnCommand); - CommandSystem.Register("CountObjects", AccessLevel.Administrator, CountObjects_OnCommand); - CommandSystem.Register("ProfileWorld", AccessLevel.Administrator, ProfileWorld_OnCommand); - CommandSystem.Register("TraceInternal", AccessLevel.Administrator, TraceInternal_OnCommand); - CommandSystem.Register("TraceExpanded", AccessLevel.Administrator, TraceExpanded_OnCommand); - CommandSystem.Register("WriteProfiles", AccessLevel.Administrator, WriteProfiles_OnCommand); - CommandSystem.Register("SetProfiles", AccessLevel.Administrator, SetProfiles_OnCommand); - } - - [Usage("WriteProfiles")] - [Description("Generates a log files containing performance diagnostic information.")] - public static void WriteProfiles_OnCommand(CommandEventArgs e) - { - try - { - using StreamWriter sw = new StreamWriter("profiles.log", true); - sw.WriteLine("# Dump on {0:f}", DateTime.UtcNow); - sw.WriteLine($"# Core profiling for {Core.ProfileTime}"); - - sw.WriteLine("# Packet send"); - BaseProfile.WriteAll(sw, PacketSendProfile.Profiles); - sw.WriteLine(); - - sw.WriteLine("# Packet receive"); - BaseProfile.WriteAll(sw, PacketReceiveProfile.Profiles); - sw.WriteLine(); - - sw.WriteLine("# Timer"); - BaseProfile.WriteAll(sw, TimerProfile.Profiles); - sw.WriteLine(); - - sw.WriteLine("# Gump response"); - BaseProfile.WriteAll(sw, GumpProfile.Profiles); - sw.WriteLine(); - - sw.WriteLine("# Target response"); - BaseProfile.WriteAll(sw, TargetProfile.Profiles); - sw.WriteLine(); - } - catch - { - // ignored - } - } - - [Usage("SetProfiles [true | false]")] - [Description("Enables, disables, or toggles the state of core packet and timer profiling.")] - public static void SetProfiles_OnCommand(CommandEventArgs e) - { - if (e.Length == 1) - Core.Profiling = e.GetBoolean(0); - else - Core.Profiling = !Core.Profiling; - - e.Mobile.SendMessage("Profiling has been {0}.", Core.Profiling ? "enabled" : "disabled"); - } - - [Usage("DumpTimers")] - [Description("Generates a log file of all currently executing timers. Used for tracing timer leaks.")] - public static void DumpTimers_OnCommand(CommandEventArgs e) - { - try - { - using StreamWriter sw = new StreamWriter("timerdump.log", true); - Timer.DumpInfo(sw); - } - catch - { - // ignored - } - } - - [Usage("CountObjects")] - [Description("Generates a log file detailing all item and mobile types in the world.")] - public static void CountObjects_OnCommand(CommandEventArgs e) - { - using (StreamWriter op = new StreamWriter("objects.log")) - { - Dictionary table = new Dictionary(); - - foreach (Item item in World.Items.Values) - { - Type type = item.GetType(); - - table[type] = (table.TryGetValue(type, out int value) ? value : 0) + 1; - } - - List> items = table.ToList(); - table.Clear(); - - foreach (Mobile m in World.Mobiles.Values) - { - Type type = m.GetType(); - - table[type] = (table.TryGetValue(type, out int value) ? value : 0) + 1; - } - - List> mobiles = table.ToList(); - - items.Sort(new CountSorter()); - mobiles.Sort(new CountSorter()); - - op.WriteLine("# Object count table generated on {0}", DateTime.UtcNow); - op.WriteLine(); - op.WriteLine(); - - op.WriteLine("# Items:"); - - items.ForEach(kvp => - op.WriteLine("{0}\t{1:F2}%\t{2}", kvp.Value, 100.0 * kvp.Value / World.Items.Count, kvp.Key)); - - op.WriteLine(); - op.WriteLine(); - - op.WriteLine("#Mobiles:"); - - mobiles.ForEach(kvp => - op.WriteLine("{0}\t{1:F2}%\t{2}", kvp.Value, 100.0 * kvp.Value / World.Mobiles.Count, kvp.Key)); - } - - e.Mobile.SendMessage("Object table has been generated. See the file : /objects.log"); - } - - [Usage("TraceExpanded")] - [Description("Generates a log file describing all items using expanded memory.")] - public static void TraceExpanded_OnCommand(CommandEventArgs e) - { - Dictionary typeTable = new Dictionary(); - - foreach (Item item in World.Items.Values) - { - ExpandFlag flags = item.GetExpandFlags(); - - if ((flags & ~(ExpandFlag.TempFlag | ExpandFlag.SaveFlag)) == 0) - continue; - - Type itemType = item.GetType(); - - do - { - if (!typeTable.TryGetValue(itemType, out int[] countTable)) - typeTable[itemType] = countTable = new int[9]; - - if ((flags & ExpandFlag.Name) != 0) - ++countTable[0]; - - if ((flags & ExpandFlag.Items) != 0) - ++countTable[1]; - - if ((flags & ExpandFlag.Bounce) != 0) - ++countTable[2]; - - if ((flags & ExpandFlag.Holder) != 0) - ++countTable[3]; - - if ((flags & ExpandFlag.Blessed) != 0) - ++countTable[4]; - - /*if (( flags & ExpandFlag.TempFlag ) != 0) - ++countTable[5]; - - if (( flags & ExpandFlag.SaveFlag ) != 0) - ++countTable[6];*/ - - if ((flags & ExpandFlag.Weight) != 0) - ++countTable[7]; - - if ((flags & ExpandFlag.Spawner) != 0) - ++countTable[8]; - - itemType = itemType.BaseType; - } while (itemType != typeof(object)); - } - - try - { - using StreamWriter op = new StreamWriter("expandedItems.log", true); - string[] names = - { - "Name", - "Items", - "Bounce", - "Holder", - "Blessed", - "TempFlag", - "SaveFlag", - "Weight", - "Spawner" - }; - - List> list = typeTable.ToList(); - - list.Sort(new CountsSorter()); - - foreach (KeyValuePair kvp in list) - { - int[] countTable = kvp.Value; - - op.WriteLine("# {0}", kvp.Key.FullName); - - for (int i = 0; i < countTable.Length; ++i) - if (countTable[i] > 0) - op.WriteLine("{0}\t{1:N0}", names[i], countTable[i]); - - op.WriteLine(); - } - } - catch - { - // ignored - } - } - - [Usage("TraceInternal")] - [Description("Generates a log file describing all items in the 'internal' map.")] - public static void TraceInternal_OnCommand(CommandEventArgs e) - { - int totalCount = 0; - Dictionary table = new Dictionary(); - - foreach (Item item in World.Items.Values) - { - if (item.Parent != null || item.Map != Map.Internal) - continue; - - ++totalCount; - - Type type = item.GetType(); - - if (table.TryGetValue(type, out int[] parms)) - { - parms[0]++; - parms[1] += item.Amount; - } - else - table[type] = new[] { 1, item.Amount }; - } - - using StreamWriter op = new StreamWriter("internal.log"); - op.WriteLine("# {0} items found", totalCount); - op.WriteLine("# {0} different types", table.Count); - op.WriteLine(); - op.WriteLine(); - op.WriteLine("Type\t\tCount\t\tAmount\t\tAvg. Amount"); - - foreach (KeyValuePair de in table) - { - int[] parms = de.Value; - - op.WriteLine("{0}\t\t{1}\t\t{2}\t\t{3:F2}", de.Key.Name, parms[0], parms[1], (double)parms[1] / parms[0]); - } - } - - [Usage("ProfileWorld")] - [Description("Prints the amount of data serialized for every object type in your world file.")] - public static void ProfileWorld_OnCommand(CommandEventArgs e) - { - ProfileWorld("items", "worldprofile_items.log"); - ProfileWorld("mobiles", "worldprofile_mobiles.log"); - } - - public static void ProfileWorld(string type, string opFile) - { - try - { - List types = new List(); - - using (BinaryReader bin = new BinaryReader(new FileStream(string.Format("Saves/{0}/{0}.tdb", type), - FileMode.Open, FileAccess.Read, FileShare.Read))) - { - int count = bin.ReadInt32(); - - for (int i = 0; i < count; ++i) - types.Add(AssemblyHandler.FindFirstTypeForName(bin.ReadString())); - } - - long total = 0; - - Dictionary table = new Dictionary(); - - using (BinaryReader bin = new BinaryReader(new FileStream(string.Format("Saves/{0}/{0}.idx", type), - FileMode.Open, FileAccess.Read, FileShare.Read))) - { - int count = bin.ReadInt32(); - - for (int i = 0; i < count; ++i) - { - int typeID = bin.ReadInt32(); - int serial = bin.ReadInt32(); - long pos = bin.ReadInt64(); - int length = bin.ReadInt32(); - Type objType = types[typeID]; - - while (objType != null && objType != typeof(object)) - { - table[objType] = length + (table.TryGetValue(objType, out int value) ? value : 0); - objType = objType.BaseType; - total += length; - } - } - } - - List> list = table.ToList(); - - list.Sort(new CountSorter()); - - using StreamWriter op = new StreamWriter(opFile); - op.WriteLine("# Profile of world {0}", type); - op.WriteLine("# Generated on {0}", DateTime.UtcNow); - op.WriteLine(); - op.WriteLine(); - - list.ForEach(kvp => - op.WriteLine("{0}\t{1:F2}%\t{2}", kvp.Value, 100.0 * kvp.Value / total, kvp.Key)); - } - catch - { - // ignored - } - } - - private class CountSorter : IComparer> - { - public int Compare(KeyValuePair x, KeyValuePair y) - { - int aCount = x.Value; - int bCount = y.Value; - - int v = -aCount.CompareTo(bCount); - - return v != 0 ? v : x.Key.FullName?.CompareTo(y.Key.FullName) ?? -1; - } - } - - private class CountsSorter : IComparer> - { - public int Compare(KeyValuePair x, KeyValuePair y) - { - int aCount = x.Value.Aggregate(0, (t, val) => t + val); - int bCount = y.Value.Aggregate(0, (t, val) => t + val); - - int v = -aCount.CompareTo(bCount); - - return v != 0 ? v : x.Key.FullName?.CompareTo(y.Key.FullName) ?? 1; - } - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Server.Diagnostics; + +namespace Server.Commands +{ + public static class Profiling + { + public static void Initialize() + { + CommandSystem.Register("DumpTimers", AccessLevel.Administrator, DumpTimers_OnCommand); + CommandSystem.Register("CountObjects", AccessLevel.Administrator, CountObjects_OnCommand); + CommandSystem.Register("ProfileWorld", AccessLevel.Administrator, ProfileWorld_OnCommand); + CommandSystem.Register("TraceInternal", AccessLevel.Administrator, TraceInternal_OnCommand); + CommandSystem.Register("TraceExpanded", AccessLevel.Administrator, TraceExpanded_OnCommand); + CommandSystem.Register("WriteProfiles", AccessLevel.Administrator, WriteProfiles_OnCommand); + CommandSystem.Register("SetProfiles", AccessLevel.Administrator, SetProfiles_OnCommand); + } + + [Usage("WriteProfiles")] + [Description("Generates a log files containing performance diagnostic information.")] + public static void WriteProfiles_OnCommand(CommandEventArgs e) + { + try + { + using var sw = new StreamWriter("profiles.log", true); + sw.WriteLine("# Dump on {0:f}", DateTime.UtcNow); + sw.WriteLine($"# Core profiling for {Core.ProfileTime}"); + + sw.WriteLine("# Packet send"); + BaseProfile.WriteAll(sw, PacketSendProfile.Profiles); + sw.WriteLine(); + + sw.WriteLine("# Packet receive"); + BaseProfile.WriteAll(sw, PacketReceiveProfile.Profiles); + sw.WriteLine(); + + sw.WriteLine("# Timer"); + BaseProfile.WriteAll(sw, TimerProfile.Profiles); + sw.WriteLine(); + + sw.WriteLine("# Gump response"); + BaseProfile.WriteAll(sw, GumpProfile.Profiles); + sw.WriteLine(); + + sw.WriteLine("# Target response"); + BaseProfile.WriteAll(sw, TargetProfile.Profiles); + sw.WriteLine(); + } + catch + { + // ignored + } + } + + [Usage("SetProfiles [true | false]")] + [Description("Enables, disables, or toggles the state of core packet and timer profiling.")] + public static void SetProfiles_OnCommand(CommandEventArgs e) + { + if (e.Length == 1) + Core.Profiling = e.GetBoolean(0); + else + Core.Profiling = !Core.Profiling; + + e.Mobile.SendMessage("Profiling has been {0}.", Core.Profiling ? "enabled" : "disabled"); + } + + [Usage("DumpTimers")] + [Description("Generates a log file of all currently executing timers. Used for tracing timer leaks.")] + public static void DumpTimers_OnCommand(CommandEventArgs e) + { + try + { + using var sw = new StreamWriter("timerdump.log", true); + Timer.DumpInfo(sw); + } + catch + { + // ignored + } + } + + [Usage("CountObjects")] + [Description("Generates a log file detailing all item and mobile types in the world.")] + public static void CountObjects_OnCommand(CommandEventArgs e) + { + using (var op = new StreamWriter("objects.log")) + { + var table = new Dictionary(); + + foreach (var item in World.Items.Values) + { + var type = item.GetType(); + + table[type] = (table.TryGetValue(type, out var value) ? value : 0) + 1; + } + + var items = table.ToList(); + table.Clear(); + + foreach (var m in World.Mobiles.Values) + { + var type = m.GetType(); + + table[type] = (table.TryGetValue(type, out var value) ? value : 0) + 1; + } + + var mobiles = table.ToList(); + + items.Sort(new CountSorter()); + mobiles.Sort(new CountSorter()); + + op.WriteLine("# Object count table generated on {0}", DateTime.UtcNow); + op.WriteLine(); + op.WriteLine(); + + op.WriteLine("# Items:"); + + items.ForEach( + kvp => + op.WriteLine("{0}\t{1:F2}%\t{2}", kvp.Value, 100.0 * kvp.Value / World.Items.Count, kvp.Key) + ); + + op.WriteLine(); + op.WriteLine(); + + op.WriteLine("#Mobiles:"); + + mobiles.ForEach( + kvp => + op.WriteLine("{0}\t{1:F2}%\t{2}", kvp.Value, 100.0 * kvp.Value / World.Mobiles.Count, kvp.Key) + ); + } + + e.Mobile.SendMessage("Object table has been generated. See the file : /objects.log"); + } + + [Usage("TraceExpanded")] + [Description("Generates a log file describing all items using expanded memory.")] + public static void TraceExpanded_OnCommand(CommandEventArgs e) + { + var typeTable = new Dictionary(); + + foreach (var item in World.Items.Values) + { + var flags = item.GetExpandFlags(); + + if ((flags & ~(ExpandFlag.TempFlag | ExpandFlag.SaveFlag)) == 0) + continue; + + var itemType = item.GetType(); + + do + { + if (!typeTable.TryGetValue(itemType, out var countTable)) + typeTable[itemType] = countTable = new int[9]; + + if ((flags & ExpandFlag.Name) != 0) + ++countTable[0]; + + if ((flags & ExpandFlag.Items) != 0) + ++countTable[1]; + + if ((flags & ExpandFlag.Bounce) != 0) + ++countTable[2]; + + if ((flags & ExpandFlag.Holder) != 0) + ++countTable[3]; + + if ((flags & ExpandFlag.Blessed) != 0) + ++countTable[4]; + + /*if (( flags & ExpandFlag.TempFlag ) != 0) + ++countTable[5]; + + if (( flags & ExpandFlag.SaveFlag ) != 0) + ++countTable[6];*/ + + if ((flags & ExpandFlag.Weight) != 0) + ++countTable[7]; + + if ((flags & ExpandFlag.Spawner) != 0) + ++countTable[8]; + + itemType = itemType.BaseType; + } while (itemType != typeof(object)); + } + + try + { + using var op = new StreamWriter("expandedItems.log", true); + string[] names = + { + "Name", + "Items", + "Bounce", + "Holder", + "Blessed", + "TempFlag", + "SaveFlag", + "Weight", + "Spawner" + }; + + var list = typeTable.ToList(); + + list.Sort(new CountsSorter()); + + foreach (var kvp in list) + { + var countTable = kvp.Value; + + op.WriteLine("# {0}", kvp.Key.FullName); + + for (var i = 0; i < countTable.Length; ++i) + if (countTable[i] > 0) + op.WriteLine("{0}\t{1:N0}", names[i], countTable[i]); + + op.WriteLine(); + } + } + catch + { + // ignored + } + } + + [Usage("TraceInternal")] + [Description("Generates a log file describing all items in the 'internal' map.")] + public static void TraceInternal_OnCommand(CommandEventArgs e) + { + var totalCount = 0; + var table = new Dictionary(); + + foreach (var item in World.Items.Values) + { + if (item.Parent != null || item.Map != Map.Internal) + continue; + + ++totalCount; + + var type = item.GetType(); + + if (table.TryGetValue(type, out var parms)) + { + parms[0]++; + parms[1] += item.Amount; + } + else + { + table[type] = new[] { 1, item.Amount }; + } + } + + using var op = new StreamWriter("internal.log"); + op.WriteLine("# {0} items found", totalCount); + op.WriteLine("# {0} different types", table.Count); + op.WriteLine(); + op.WriteLine(); + op.WriteLine("Type\t\tCount\t\tAmount\t\tAvg. Amount"); + + foreach (var de in table) + { + var parms = de.Value; + + op.WriteLine("{0}\t\t{1}\t\t{2}\t\t{3:F2}", de.Key.Name, parms[0], parms[1], (double)parms[1] / parms[0]); + } + } + + [Usage("ProfileWorld")] + [Description("Prints the amount of data serialized for every object type in your world file.")] + public static void ProfileWorld_OnCommand(CommandEventArgs e) + { + ProfileWorld("items", "worldprofile_items.log"); + ProfileWorld("mobiles", "worldprofile_mobiles.log"); + } + + public static void ProfileWorld(string type, string opFile) + { + try + { + var types = new List(); + + using (var bin = new BinaryReader( + new FileStream( + string.Format("Saves/{0}/{0}.tdb", type), + FileMode.Open, + FileAccess.Read, + FileShare.Read + ) + )) + { + var count = bin.ReadInt32(); + + for (var i = 0; i < count; ++i) + types.Add(AssemblyHandler.FindFirstTypeForName(bin.ReadString())); + } + + long total = 0; + + var table = new Dictionary(); + + using (var bin = new BinaryReader( + new FileStream( + string.Format("Saves/{0}/{0}.idx", type), + FileMode.Open, + FileAccess.Read, + FileShare.Read + ) + )) + { + var count = bin.ReadInt32(); + + for (var i = 0; i < count; ++i) + { + var typeID = bin.ReadInt32(); + var serial = bin.ReadInt32(); + var pos = bin.ReadInt64(); + var length = bin.ReadInt32(); + var objType = types[typeID]; + + while (objType != null && objType != typeof(object)) + { + table[objType] = length + (table.TryGetValue(objType, out var value) ? value : 0); + objType = objType.BaseType; + total += length; + } + } + } + + var list = table.ToList(); + + list.Sort(new CountSorter()); + + using var op = new StreamWriter(opFile); + op.WriteLine("# Profile of world {0}", type); + op.WriteLine("# Generated on {0}", DateTime.UtcNow); + op.WriteLine(); + op.WriteLine(); + + list.ForEach( + kvp => + op.WriteLine("{0}\t{1:F2}%\t{2}", kvp.Value, 100.0 * kvp.Value / total, kvp.Key) + ); + } + catch + { + // ignored + } + } + + private class CountSorter : IComparer> + { + public int Compare(KeyValuePair x, KeyValuePair y) + { + var aCount = x.Value; + var bCount = y.Value; + + var v = -aCount.CompareTo(bCount); + + return v != 0 ? v : x.Key.FullName?.CompareTo(y.Key.FullName) ?? -1; + } + } + + private class CountsSorter : IComparer> + { + public int Compare(KeyValuePair x, KeyValuePair y) + { + var aCount = x.Value.Aggregate(0, (t, val) => t + val); + var bCount = y.Value.Aggregate(0, (t, val) => t + val); + + var v = -aCount.CompareTo(bCount); + + return v != 0 ? v : x.Key.FullName?.CompareTo(y.Key.FullName) ?? 1; + } + } + } +} diff --git a/Projects/UOContent/Commands/Properties.cs b/Projects/UOContent/Commands/Properties.cs index fd17c1077..832803d21 100644 --- a/Projects/UOContent/Commands/Properties.cs +++ b/Projects/UOContent/Commands/Properties.cs @@ -1,751 +1,767 @@ -using System; -using System.Reflection; -using Server.Commands; -using Server.Commands.Generic; -using Server.Gumps; -using Server.Targeting; -using CPA = Server.CommandPropertyAttribute; - -namespace Server.Commands -{ - [Flags] - public enum PropertyAccess - { - Read = 0x01, - Write = 0x02, - ReadWrite = Read | Write - } - - public static class Properties - { - private static readonly Type typeofCPA = typeof(CPA); - - private static readonly Type typeofSerial = typeof(Serial); - - private static readonly Type typeofType = typeof(Type); - - private static readonly Type typeofChar = typeof(char); - - private static readonly Type typeofString = typeof(string); - - private static readonly Type typeofText = typeof(TextDefinition); - - private static readonly Type typeofTimeSpan = typeof(TimeSpan); - private static readonly Type typeofParsable = typeof(ParsableAttribute); - - private static readonly Type[] m_ParseTypes = { typeof(string) }; - private static readonly object[] m_ParseParams = new object[1]; - - private static readonly Type[] m_NumericTypes = - { - typeof(byte), typeof(sbyte), - typeof(short), typeof(ushort), - typeof(int), typeof(uint), - typeof(long), typeof(ulong) - }; - - public static void Initialize() - { - CommandSystem.Register("Props", AccessLevel.Counselor, Props_OnCommand); - } - - [Usage("Props [serial]")] - [Description("Opens a menu where you can view and edit all properties of a targeted (or specified) object.")] - private static void Props_OnCommand(CommandEventArgs e) - { - if (e.Length == 1) - { - IEntity ent = World.FindEntity(e.GetUInt32(0)); - - if (ent == null) - e.Mobile.SendMessage("No object with that serial was found."); - else if (!BaseCommand.IsAccessible(e.Mobile, ent)) - e.Mobile.SendLocalizedMessage(500447); // That is not accessible. - else - e.Mobile.SendGump(new PropertiesGump(e.Mobile, ent)); - } - else - { - e.Mobile.Target = new PropsTarget(); - } - } - - private static bool CIEqual(string l, string r) => Insensitive.Equals(l, r); - - public static CPA GetCPA(PropertyInfo p) - { - object[] attrs = p.GetCustomAttributes(typeofCPA, false); - - if (attrs.Length == 0) - return null; - - return attrs[0] as CPA; - } - - public static PropertyInfo[] GetPropertyInfoChain(Mobile from, Type type, string propertyString, - PropertyAccess endAccess, ref string failReason) - { - string[] split = propertyString.Split('.'); - - if (split.Length == 0) - return null; - - PropertyInfo[] info = new PropertyInfo[split.Length]; - - for (int i = 0; i < info.Length; ++i) - { - string propertyName = split[i]; - - if (CIEqual(propertyName, "current")) - continue; - - PropertyInfo[] props = type.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public); - - bool isFinal = i == info.Length - 1; - - PropertyAccess access = endAccess; - - if (!isFinal) - access |= PropertyAccess.Read; - - for (int j = 0; j < props.Length; ++j) - { - PropertyInfo p = props[j]; - - if (CIEqual(p.Name, propertyName)) - { - CPA attr = GetCPA(p); - - if (attr == null) - { - failReason = $"Property '{propertyName}' not found."; - return null; - } - - if ((access & PropertyAccess.Read) != 0 && from.AccessLevel < attr.ReadLevel) - { - failReason = - $"You must be at least {Mobile.GetAccessLevelName(attr.ReadLevel)} to get the property '{propertyName}'."; - - return null; - } - - if ((access & PropertyAccess.Write) != 0 && from.AccessLevel < attr.WriteLevel) - { - failReason = - $"You must be at least {Mobile.GetAccessLevelName(attr.WriteLevel)} to set the property '{propertyName}'."; - - return null; - } - - if ((access & PropertyAccess.Read) != 0 && !p.CanRead) - { - failReason = $"Property '{propertyName}' is write only."; - return null; - } - - if ((access & PropertyAccess.Write) != 0 && (!p.CanWrite || attr.ReadOnly) && isFinal) - { - failReason = $"Property '{propertyName}' is read only."; - return null; - } - - info[i] = p; - type = p.PropertyType; - break; - } - } - - if (info[i] == null) - { - failReason = $"Property '{propertyName}' not found."; - return null; - } - } - - return info; - } - - public static PropertyInfo GetPropertyInfo(Mobile from, ref object obj, string propertyName, PropertyAccess access, - ref string failReason) - { - PropertyInfo[] chain = GetPropertyInfoChain(from, obj.GetType(), propertyName, access, ref failReason); - - return chain == null ? null : GetPropertyInfo(ref obj, chain, ref failReason); - } - - public static PropertyInfo GetPropertyInfo(ref object obj, PropertyInfo[] chain, ref string failReason) - { - if (chain == null || chain.Length == 0) - { - failReason = "Property chain is empty."; - return null; - } - - for (int i = 0; i < chain.Length - 1; ++i) - { - if (chain[i] == null) - continue; - - obj = chain[i].GetValue(obj, null); - - if (obj == null) - { - failReason = $"Property '{chain[i]}' is null."; - return null; - } - } - - return chain[^1]; - } - - public static string GetValue(Mobile from, object o, string name) - { - string failReason = ""; - - PropertyInfo[] chain = GetPropertyInfoChain(from, o.GetType(), name, PropertyAccess.Read, ref failReason); - - if (chain == null || chain.Length == 0) - return failReason; - - PropertyInfo p = GetPropertyInfo(ref o, chain, ref failReason); - - return p == null ? failReason : InternalGetValue(o, p, chain); - } - - public static string IncreaseValue(Mobile from, object o, string[] args) - { - // Type type = o.GetType(); - - object[] realObjs = new object[args.Length / 2]; - PropertyInfo[] realProps = new PropertyInfo[args.Length / 2]; - int[] realValues = new int[args.Length / 2]; - - bool positive = false; - bool negative = false; - - for (int i = 0; i < realProps.Length; ++i) - { - string name = args[i * 2]; - - try - { - string valueString = args[1 + i * 2]; - - if (valueString.StartsWith("0x")) - realValues[i] = Convert.ToInt32(valueString.Substring(2), 16); - else - realValues[i] = Convert.ToInt32(valueString); - } - catch - { - return "Offset value could not be parsed."; - } - - if (realValues[i] > 0) - positive = true; - else if (realValues[i] < 0) - negative = true; - else - return "Zero is not a valid value to offset."; - - string failReason = null; - realObjs[i] = o; - realProps[i] = GetPropertyInfo(from, ref realObjs[i], name, PropertyAccess.ReadWrite, ref failReason); - - if (failReason != null) - return failReason; - - if (realProps[i] == null) - return "Property not found."; - } - - for (int i = 0; i < realProps.Length; ++i) - { - object obj = realProps[i].GetValue(realObjs[i], null); - - if (!(obj is IConvertible)) - return "Property is not IConvertable."; - - try - { - long v = (long)Convert.ChangeType(obj, TypeCode.Int64); - v += realValues[i]; - - realProps[i].SetValue(realObjs[i], Convert.ChangeType(v, realProps[i].PropertyType), null); - } - catch - { - return "Value could not be converted"; - } - } - - if (realProps.Length == 1) - { - if (positive) - return "The property has been increased."; - - return "The property has been decreased."; - } - - if (positive && negative) - return "The properties have been changed."; - - if (positive) - return "The properties have been increased."; - - return "The properties have been decreased."; - } - - private static string InternalGetValue(object o, PropertyInfo p, PropertyInfo[] chain = null) - { - Type type = p.PropertyType; - - object value = p.GetValue(o, null); - string toString; - - if (value == null) - toString = "null"; - else if (IsNumeric(type)) - toString = $"{value} (0x{value:X})"; - else if (IsChar(type)) - toString = $"'{value}' ({(int)value} [0x{(int)value:X}])"; - else if (IsString(type)) - toString = (string)value == "null" ? @"@""null""" : $"\"{value}\""; - else if (IsText(type)) - toString = ((TextDefinition)value).Format(false); - else - toString = value.ToString(); - - if (chain == null) - return $"{p.Name} = {toString}"; - - string[] concat = new string[chain.Length * 2 + 1]; - - for (int i = 0; i < chain.Length; ++i) - { - concat[i * 2 + 0] = chain[i].Name; - concat[i * 2 + 1] = i < chain.Length - 1 ? "." : " = "; - } - - concat[^1] = toString; - - return string.Concat(concat); - } - - public static string SetValue(Mobile from, object o, string name, string value) - { - object logObject = o; - - string failReason = ""; - PropertyInfo p = GetPropertyInfo(from, ref o, name, PropertyAccess.Write, ref failReason); - - return p == null ? failReason : InternalSetValue(from, logObject, o, p, name, value, true); - } - - private static bool IsSerial(Type t) => t == typeofSerial; - - private static bool IsType(Type t) => t == typeofType; - - private static bool IsChar(Type t) => t == typeofChar; - - private static bool IsString(Type t) => t == typeofString; - - private static bool IsText(Type t) => t == typeofText; - - private static bool IsEnum(Type t) => t.IsEnum; - - private static bool IsParsable(Type t) => t == typeofTimeSpan || t.IsDefined(typeofParsable, false); - - private static object Parse(object o, Type t, string value) - { - MethodInfo method = t.GetMethod("Parse", m_ParseTypes); - - m_ParseParams[0] = value; - - return method?.Invoke(o, m_ParseParams); - } - - private static bool IsNumeric(Type t) => Array.IndexOf(m_NumericTypes, t) >= 0; - - public static string ConstructFromString(Type type, object obj, string value, ref object constructed) - { - object toSet; - bool isSerial = IsSerial(type); - - if (isSerial) // mutate into int32 - type = m_NumericTypes[4]; - - if (value == "(-null-)" && !type.IsValueType) - value = null; - - if (IsEnum(type)) - try - { - toSet = Enum.Parse(type, value ?? "", true); - } - catch - { - return "That is not a valid enumeration member."; - } - else if (IsType(type)) - try - { - toSet = AssemblyHandler.FindFirstTypeForName(value); - - if (toSet == null) - return "No type with that name was found."; - } - catch - { - return "No type with that name was found."; - } - else if (IsParsable(type)) - try - { - toSet = Parse(obj, type, value); - } - catch - { - return "That is not properly formatted."; - } - else if (value == null) - toSet = null; - else if (value.StartsWith("0x") && IsNumeric(type)) - try - { - toSet = Convert.ChangeType(Convert.ToUInt64(value.Substring(2), 16), type); - } - catch - { - return "That is not properly formatted."; - } - else - try - { - toSet = Convert.ChangeType(value, type); - } - catch - { - return "That is not properly formatted."; - } - - if (isSerial) // mutate back - toSet = (Serial)(toSet ?? Serial.MinusOne); - - constructed = toSet; - return null; - } - - public static string SetDirect(Mobile from, object logObject, object obj, PropertyInfo prop, string givenName, - object toSet, bool shouldLog) - { - try - { - if (toSet is AccessLevel newLevel) - { - AccessLevel reqLevel = AccessLevel.Administrator; - - if (newLevel == AccessLevel.Administrator) - reqLevel = AccessLevel.Developer; - else if (newLevel >= AccessLevel.Developer) - reqLevel = AccessLevel.Owner; - - if (from.AccessLevel < reqLevel) - return "You do not have access to that level."; - } - - if (shouldLog) - CommandLogging.LogChangeProperty(from, logObject, givenName, - toSet?.ToString() ?? "(-null-)"); - - prop.SetValue(obj, toSet, null); - return "Property has been set."; - } - catch - { - return "An exception was caught, the property may not be set."; - } - } - - public static string SetDirect(object obj, PropertyInfo prop, object toSet) - { - try - { - if (toSet is AccessLevel) return "You do not have access to that level."; - - prop.SetValue(obj, toSet, null); - return "Property has been set."; - } - catch - { - return "An exception was caught, the property may not be set."; - } - } - - public static string InternalSetValue(Mobile from, object logobj, object o, PropertyInfo p, string pname, - string value, bool shouldLog) - { - object toSet = null; - string result = ConstructFromString(p.PropertyType, o, value, ref toSet); - - return result ?? SetDirect(from, logobj, o, p, pname, toSet, shouldLog); - } - - public static string InternalSetValue(object o, PropertyInfo p, string value) - { - object toSet = null; - string result = ConstructFromString(p.PropertyType, o, value, ref toSet); - - return result ?? SetDirect(o, p, toSet); - } - - private class PropsTarget : Target - { - public PropsTarget() : base(-1, true, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object o) - { - if (!BaseCommand.IsAccessible(from, o)) - from.SendLocalizedMessage(500447); // That is not accessible. - else - from.SendGump(new PropertiesGump(from, o)); - } - } - } -} - -namespace Server -{ - public abstract class PropertyException : ApplicationException - { - protected Property m_Property; - - public PropertyException(Property property, string message) - : base(message) => - m_Property = property; - - public Property Property => m_Property; - } - - public abstract class BindingException : PropertyException - { - public BindingException(Property property, string message) - : base(property, message) - { - } - } - - public sealed class NotYetBoundException : BindingException - { - public NotYetBoundException(Property property) - : base(property, "Property has not yet been bound.") - { - } - } - - public sealed class AlreadyBoundException : BindingException - { - public AlreadyBoundException(Property property) - : base(property, "Property has already been bound.") - { - } - } - - public sealed class UnknownPropertyException : BindingException - { - public UnknownPropertyException(Property property, string current) - : base(property, $"Property '{current}' not found.") - { - } - } - - public sealed class ReadOnlyException : BindingException - { - public ReadOnlyException(Property property) - : base(property, "Property is read-only.") - { - } - } - - public sealed class WriteOnlyException : BindingException - { - public WriteOnlyException(Property property) - : base(property, "Property is write-only.") - { - } - } - - public abstract class AccessException : PropertyException - { - public AccessException(Property property, string message) - : base(property, message) - { - } - } - - public sealed class InternalAccessException : AccessException - { - public InternalAccessException(Property property) - : base(property, "Property is internal.") - { - } - } - - public abstract class ClearanceException : AccessException - { - public ClearanceException(Property property, AccessLevel playerAccess, AccessLevel neededAccess, string accessType) - : base(property, - $"You must be at least {Mobile.GetAccessLevelName(neededAccess)} to {accessType} this property.") - { - } - - public AccessLevel PlayerAccess { get; set; } - public AccessLevel NeededAccess { get; set; } - } - - public sealed class ReadAccessException : ClearanceException - { - public ReadAccessException(Property property, AccessLevel playerAccess, AccessLevel neededAccess) - : base(property, playerAccess, neededAccess, "read") - { - } - } - - public sealed class WriteAccessException : ClearanceException - { - public WriteAccessException(Property property, AccessLevel playerAccess, AccessLevel neededAccess) - : base(property, playerAccess, neededAccess, "write") - { - } - } - - public sealed class Property - { - private PropertyInfo[] m_Chain; - - public Property(string binding) => Binding = binding; - - public Property(PropertyInfo[] chain) => m_Chain = chain; - - public string Binding { get; } - - public bool IsBound => m_Chain != null; - - public PropertyAccess Access { get; private set; } - - public PropertyInfo[] Chain - { - get - { - if (!IsBound) - throw new NotYetBoundException(this); - - return m_Chain; - } - } - - public Type Type - { - get - { - if (!IsBound) - throw new NotYetBoundException(this); - - return m_Chain[^1].PropertyType; - } - } - - public bool CheckAccess(Mobile from) - { - if (!IsBound) - throw new NotYetBoundException(this); - - for (int i = 0; i < m_Chain.Length; ++i) - { - PropertyInfo prop = m_Chain[i]; - - bool isFinal = i == m_Chain.Length - 1; - - PropertyAccess access = Access; - - if (!isFinal) - access |= PropertyAccess.Read; - - CPA security = Properties.GetCPA(prop); - - if (security == null) - throw new InternalAccessException(this); - - if ((access & PropertyAccess.Read) != 0 && from.AccessLevel < security.ReadLevel) - throw new ReadAccessException(this, from.AccessLevel, security.ReadLevel); - - if ((access & PropertyAccess.Write) != 0 && (from.AccessLevel < security.WriteLevel || security.ReadOnly)) - throw new WriteAccessException(this, from.AccessLevel, security.ReadLevel); - } - - return true; - } - - public void BindTo(Type objectType, PropertyAccess desiredAccess) - { - if (IsBound) - throw new AlreadyBoundException(this); - - string[] split = Binding.Split('.'); - - PropertyInfo[] chain = new PropertyInfo[split.Length]; - - for (int i = 0; i < split.Length; ++i) - { - bool isFinal = i == chain.Length - 1; - - chain[i] = objectType.GetProperty(split[i], - BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase); - - if (chain[i] == null) - throw new UnknownPropertyException(this, split[i]); - - objectType = chain[i].PropertyType; - - PropertyAccess access = desiredAccess; - - if (!isFinal) - access |= PropertyAccess.Read; - - if ((access & PropertyAccess.Read) != 0 && !chain[i].CanRead) - throw new WriteOnlyException(this); - - if ((access & PropertyAccess.Write) != 0 && !chain[i].CanWrite) - throw new ReadOnlyException(this); - } - - Access = desiredAccess; - m_Chain = chain; - } - - public override string ToString() - { - if (!IsBound) - return Binding; - - string[] toJoin = new string[m_Chain.Length]; - - for (int i = 0; i < toJoin.Length; ++i) - toJoin[i] = m_Chain[i].Name; - - return string.Join(".", toJoin); - } - - public static Property Parse(Type type, string binding, PropertyAccess access) - { - Property prop = new Property(binding); - - prop.BindTo(type, access); - - return prop; - } - } -} +using System; +using System.Reflection; +using Server.Commands; +using Server.Commands.Generic; +using Server.Gumps; +using Server.Targeting; +using CPA = Server.CommandPropertyAttribute; + +namespace Server.Commands +{ + [Flags] + public enum PropertyAccess + { + Read = 0x01, + Write = 0x02, + ReadWrite = Read | Write + } + + public static class Properties + { + private static readonly Type typeofCPA = typeof(CPA); + + private static readonly Type typeofSerial = typeof(Serial); + + private static readonly Type typeofType = typeof(Type); + + private static readonly Type typeofChar = typeof(char); + + private static readonly Type typeofString = typeof(string); + + private static readonly Type typeofText = typeof(TextDefinition); + + private static readonly Type typeofTimeSpan = typeof(TimeSpan); + private static readonly Type typeofParsable = typeof(ParsableAttribute); + + private static readonly Type[] m_ParseTypes = { typeof(string) }; + private static readonly object[] m_ParseParams = new object[1]; + + private static readonly Type[] m_NumericTypes = + { + typeof(byte), typeof(sbyte), + typeof(short), typeof(ushort), + typeof(int), typeof(uint), + typeof(long), typeof(ulong) + }; + + public static void Initialize() + { + CommandSystem.Register("Props", AccessLevel.Counselor, Props_OnCommand); + } + + [Usage("Props [serial]")] + [Description("Opens a menu where you can view and edit all properties of a targeted (or specified) object.")] + private static void Props_OnCommand(CommandEventArgs e) + { + if (e.Length == 1) + { + var ent = World.FindEntity(e.GetUInt32(0)); + + if (ent == null) + e.Mobile.SendMessage("No object with that serial was found."); + else if (!BaseCommand.IsAccessible(e.Mobile, ent)) + e.Mobile.SendLocalizedMessage(500447); // That is not accessible. + else + e.Mobile.SendGump(new PropertiesGump(e.Mobile, ent)); + } + else + { + e.Mobile.Target = new PropsTarget(); + } + } + + private static bool CIEqual(string l, string r) => Insensitive.Equals(l, r); + + public static CPA GetCPA(PropertyInfo p) + { + var attrs = p.GetCustomAttributes(typeofCPA, false); + + if (attrs.Length == 0) + return null; + + return attrs[0] as CPA; + } + + public static PropertyInfo[] GetPropertyInfoChain( + Mobile from, Type type, string propertyString, + PropertyAccess endAccess, ref string failReason + ) + { + var split = propertyString.Split('.'); + + if (split.Length == 0) + return null; + + var info = new PropertyInfo[split.Length]; + + for (var i = 0; i < info.Length; ++i) + { + var propertyName = split[i]; + + if (CIEqual(propertyName, "current")) + continue; + + var props = type.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public); + + var isFinal = i == info.Length - 1; + + var access = endAccess; + + if (!isFinal) + access |= PropertyAccess.Read; + + for (var j = 0; j < props.Length; ++j) + { + var p = props[j]; + + if (CIEqual(p.Name, propertyName)) + { + var attr = GetCPA(p); + + if (attr == null) + { + failReason = $"Property '{propertyName}' not found."; + return null; + } + + if ((access & PropertyAccess.Read) != 0 && from.AccessLevel < attr.ReadLevel) + { + failReason = + $"You must be at least {Mobile.GetAccessLevelName(attr.ReadLevel)} to get the property '{propertyName}'."; + + return null; + } + + if ((access & PropertyAccess.Write) != 0 && from.AccessLevel < attr.WriteLevel) + { + failReason = + $"You must be at least {Mobile.GetAccessLevelName(attr.WriteLevel)} to set the property '{propertyName}'."; + + return null; + } + + if ((access & PropertyAccess.Read) != 0 && !p.CanRead) + { + failReason = $"Property '{propertyName}' is write only."; + return null; + } + + if ((access & PropertyAccess.Write) != 0 && (!p.CanWrite || attr.ReadOnly) && isFinal) + { + failReason = $"Property '{propertyName}' is read only."; + return null; + } + + info[i] = p; + type = p.PropertyType; + break; + } + } + + if (info[i] == null) + { + failReason = $"Property '{propertyName}' not found."; + return null; + } + } + + return info; + } + + public static PropertyInfo GetPropertyInfo( + Mobile from, ref object obj, string propertyName, PropertyAccess access, + ref string failReason + ) + { + var chain = GetPropertyInfoChain(from, obj.GetType(), propertyName, access, ref failReason); + + return chain == null ? null : GetPropertyInfo(ref obj, chain, ref failReason); + } + + public static PropertyInfo GetPropertyInfo(ref object obj, PropertyInfo[] chain, ref string failReason) + { + if (chain == null || chain.Length == 0) + { + failReason = "Property chain is empty."; + return null; + } + + for (var i = 0; i < chain.Length - 1; ++i) + { + if (chain[i] == null) + continue; + + obj = chain[i].GetValue(obj, null); + + if (obj == null) + { + failReason = $"Property '{chain[i]}' is null."; + return null; + } + } + + return chain[^1]; + } + + public static string GetValue(Mobile from, object o, string name) + { + var failReason = ""; + + var chain = GetPropertyInfoChain(from, o.GetType(), name, PropertyAccess.Read, ref failReason); + + if (chain == null || chain.Length == 0) + return failReason; + + var p = GetPropertyInfo(ref o, chain, ref failReason); + + return p == null ? failReason : InternalGetValue(o, p, chain); + } + + public static string IncreaseValue(Mobile from, object o, string[] args) + { + // Type type = o.GetType(); + + var realObjs = new object[args.Length / 2]; + var realProps = new PropertyInfo[args.Length / 2]; + var realValues = new int[args.Length / 2]; + + var positive = false; + var negative = false; + + for (var i = 0; i < realProps.Length; ++i) + { + var name = args[i * 2]; + + try + { + var valueString = args[1 + i * 2]; + + if (valueString.StartsWith("0x")) + realValues[i] = Convert.ToInt32(valueString.Substring(2), 16); + else + realValues[i] = Convert.ToInt32(valueString); + } + catch + { + return "Offset value could not be parsed."; + } + + if (realValues[i] > 0) + positive = true; + else if (realValues[i] < 0) + negative = true; + else + return "Zero is not a valid value to offset."; + + string failReason = null; + realObjs[i] = o; + realProps[i] = GetPropertyInfo(from, ref realObjs[i], name, PropertyAccess.ReadWrite, ref failReason); + + if (failReason != null) + return failReason; + + if (realProps[i] == null) + return "Property not found."; + } + + for (var i = 0; i < realProps.Length; ++i) + { + var obj = realProps[i].GetValue(realObjs[i], null); + + if (!(obj is IConvertible)) + return "Property is not IConvertable."; + + try + { + var v = (long)Convert.ChangeType(obj, TypeCode.Int64); + v += realValues[i]; + + realProps[i].SetValue(realObjs[i], Convert.ChangeType(v, realProps[i].PropertyType), null); + } + catch + { + return "Value could not be converted"; + } + } + + if (realProps.Length == 1) + { + if (positive) + return "The property has been increased."; + + return "The property has been decreased."; + } + + if (positive && negative) + return "The properties have been changed."; + + if (positive) + return "The properties have been increased."; + + return "The properties have been decreased."; + } + + private static string InternalGetValue(object o, PropertyInfo p, PropertyInfo[] chain = null) + { + var type = p.PropertyType; + + var value = p.GetValue(o, null); + string toString; + + if (value == null) + toString = "null"; + else if (IsNumeric(type)) + toString = $"{value} (0x{value:X})"; + else if (IsChar(type)) + toString = $"'{value}' ({(int)value} [0x{(int)value:X}])"; + else if (IsString(type)) + toString = (string)value == "null" ? @"@""null""" : $"\"{value}\""; + else if (IsText(type)) + toString = ((TextDefinition)value).Format(false); + else + toString = value.ToString(); + + if (chain == null) + return $"{p.Name} = {toString}"; + + var concat = new string[chain.Length * 2 + 1]; + + for (var i = 0; i < chain.Length; ++i) + { + concat[i * 2 + 0] = chain[i].Name; + concat[i * 2 + 1] = i < chain.Length - 1 ? "." : " = "; + } + + concat[^1] = toString; + + return string.Concat(concat); + } + + public static string SetValue(Mobile from, object o, string name, string value) + { + var logObject = o; + + var failReason = ""; + var p = GetPropertyInfo(from, ref o, name, PropertyAccess.Write, ref failReason); + + return p == null ? failReason : InternalSetValue(from, logObject, o, p, name, value, true); + } + + private static bool IsSerial(Type t) => t == typeofSerial; + + private static bool IsType(Type t) => t == typeofType; + + private static bool IsChar(Type t) => t == typeofChar; + + private static bool IsString(Type t) => t == typeofString; + + private static bool IsText(Type t) => t == typeofText; + + private static bool IsEnum(Type t) => t.IsEnum; + + private static bool IsParsable(Type t) => t == typeofTimeSpan || t.IsDefined(typeofParsable, false); + + private static object Parse(object o, Type t, string value) + { + var method = t.GetMethod("Parse", m_ParseTypes); + + m_ParseParams[0] = value; + + return method?.Invoke(o, m_ParseParams); + } + + private static bool IsNumeric(Type t) => Array.IndexOf(m_NumericTypes, t) >= 0; + + public static string ConstructFromString(Type type, object obj, string value, ref object constructed) + { + object toSet; + var isSerial = IsSerial(type); + + if (isSerial) // mutate into int32 + type = m_NumericTypes[4]; + + if (value == "(-null-)" && !type.IsValueType) + value = null; + + if (IsEnum(type)) + try + { + toSet = Enum.Parse(type, value ?? "", true); + } + catch + { + return "That is not a valid enumeration member."; + } + else if (IsType(type)) + try + { + toSet = AssemblyHandler.FindFirstTypeForName(value); + + if (toSet == null) + return "No type with that name was found."; + } + catch + { + return "No type with that name was found."; + } + else if (IsParsable(type)) + try + { + toSet = Parse(obj, type, value); + } + catch + { + return "That is not properly formatted."; + } + else if (value == null) + toSet = null; + else if (value.StartsWith("0x") && IsNumeric(type)) + try + { + toSet = Convert.ChangeType(Convert.ToUInt64(value.Substring(2), 16), type); + } + catch + { + return "That is not properly formatted."; + } + else + try + { + toSet = Convert.ChangeType(value, type); + } + catch + { + return "That is not properly formatted."; + } + + if (isSerial) // mutate back + toSet = (Serial)(toSet ?? Serial.MinusOne); + + constructed = toSet; + return null; + } + + public static string SetDirect( + Mobile from, object logObject, object obj, PropertyInfo prop, string givenName, + object toSet, bool shouldLog + ) + { + try + { + if (toSet is AccessLevel newLevel) + { + var reqLevel = AccessLevel.Administrator; + + if (newLevel == AccessLevel.Administrator) + reqLevel = AccessLevel.Developer; + else if (newLevel >= AccessLevel.Developer) + reqLevel = AccessLevel.Owner; + + if (from.AccessLevel < reqLevel) + return "You do not have access to that level."; + } + + if (shouldLog) + CommandLogging.LogChangeProperty( + from, + logObject, + givenName, + toSet?.ToString() ?? "(-null-)" + ); + + prop.SetValue(obj, toSet, null); + return "Property has been set."; + } + catch + { + return "An exception was caught, the property may not be set."; + } + } + + public static string SetDirect(object obj, PropertyInfo prop, object toSet) + { + try + { + if (toSet is AccessLevel) return "You do not have access to that level."; + + prop.SetValue(obj, toSet, null); + return "Property has been set."; + } + catch + { + return "An exception was caught, the property may not be set."; + } + } + + public static string InternalSetValue( + Mobile from, object logobj, object o, PropertyInfo p, string pname, + string value, bool shouldLog + ) + { + object toSet = null; + var result = ConstructFromString(p.PropertyType, o, value, ref toSet); + + return result ?? SetDirect(from, logobj, o, p, pname, toSet, shouldLog); + } + + public static string InternalSetValue(object o, PropertyInfo p, string value) + { + object toSet = null; + var result = ConstructFromString(p.PropertyType, o, value, ref toSet); + + return result ?? SetDirect(o, p, toSet); + } + + private class PropsTarget : Target + { + public PropsTarget() : base(-1, true, TargetFlags.None) + { + } + + protected override void OnTarget(Mobile from, object o) + { + if (!BaseCommand.IsAccessible(from, o)) + from.SendLocalizedMessage(500447); // That is not accessible. + else + from.SendGump(new PropertiesGump(from, o)); + } + } + } +} + +namespace Server +{ + public abstract class PropertyException : ApplicationException + { + protected Property m_Property; + + public PropertyException(Property property, string message) + : base(message) => + m_Property = property; + + public Property Property => m_Property; + } + + public abstract class BindingException : PropertyException + { + public BindingException(Property property, string message) + : base(property, message) + { + } + } + + public sealed class NotYetBoundException : BindingException + { + public NotYetBoundException(Property property) + : base(property, "Property has not yet been bound.") + { + } + } + + public sealed class AlreadyBoundException : BindingException + { + public AlreadyBoundException(Property property) + : base(property, "Property has already been bound.") + { + } + } + + public sealed class UnknownPropertyException : BindingException + { + public UnknownPropertyException(Property property, string current) + : base(property, $"Property '{current}' not found.") + { + } + } + + public sealed class ReadOnlyException : BindingException + { + public ReadOnlyException(Property property) + : base(property, "Property is read-only.") + { + } + } + + public sealed class WriteOnlyException : BindingException + { + public WriteOnlyException(Property property) + : base(property, "Property is write-only.") + { + } + } + + public abstract class AccessException : PropertyException + { + public AccessException(Property property, string message) + : base(property, message) + { + } + } + + public sealed class InternalAccessException : AccessException + { + public InternalAccessException(Property property) + : base(property, "Property is internal.") + { + } + } + + public abstract class ClearanceException : AccessException + { + public ClearanceException(Property property, AccessLevel playerAccess, AccessLevel neededAccess, string accessType) + : base( + property, + $"You must be at least {Mobile.GetAccessLevelName(neededAccess)} to {accessType} this property." + ) + { + } + + public AccessLevel PlayerAccess { get; set; } + public AccessLevel NeededAccess { get; set; } + } + + public sealed class ReadAccessException : ClearanceException + { + public ReadAccessException(Property property, AccessLevel playerAccess, AccessLevel neededAccess) + : base(property, playerAccess, neededAccess, "read") + { + } + } + + public sealed class WriteAccessException : ClearanceException + { + public WriteAccessException(Property property, AccessLevel playerAccess, AccessLevel neededAccess) + : base(property, playerAccess, neededAccess, "write") + { + } + } + + public sealed class Property + { + private PropertyInfo[] m_Chain; + + public Property(string binding) => Binding = binding; + + public Property(PropertyInfo[] chain) => m_Chain = chain; + + public string Binding { get; } + + public bool IsBound => m_Chain != null; + + public PropertyAccess Access { get; private set; } + + public PropertyInfo[] Chain + { + get + { + if (!IsBound) + throw new NotYetBoundException(this); + + return m_Chain; + } + } + + public Type Type + { + get + { + if (!IsBound) + throw new NotYetBoundException(this); + + return m_Chain[^1].PropertyType; + } + } + + public bool CheckAccess(Mobile from) + { + if (!IsBound) + throw new NotYetBoundException(this); + + for (var i = 0; i < m_Chain.Length; ++i) + { + var prop = m_Chain[i]; + + var isFinal = i == m_Chain.Length - 1; + + var access = Access; + + if (!isFinal) + access |= PropertyAccess.Read; + + var security = Properties.GetCPA(prop); + + if (security == null) + throw new InternalAccessException(this); + + if ((access & PropertyAccess.Read) != 0 && from.AccessLevel < security.ReadLevel) + throw new ReadAccessException(this, from.AccessLevel, security.ReadLevel); + + if ((access & PropertyAccess.Write) != 0 && (from.AccessLevel < security.WriteLevel || security.ReadOnly)) + throw new WriteAccessException(this, from.AccessLevel, security.ReadLevel); + } + + return true; + } + + public void BindTo(Type objectType, PropertyAccess desiredAccess) + { + if (IsBound) + throw new AlreadyBoundException(this); + + var split = Binding.Split('.'); + + var chain = new PropertyInfo[split.Length]; + + for (var i = 0; i < split.Length; ++i) + { + var isFinal = i == chain.Length - 1; + + chain[i] = objectType.GetProperty( + split[i], + BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase + ); + + if (chain[i] == null) + throw new UnknownPropertyException(this, split[i]); + + objectType = chain[i].PropertyType; + + var access = desiredAccess; + + if (!isFinal) + access |= PropertyAccess.Read; + + if ((access & PropertyAccess.Read) != 0 && !chain[i].CanRead) + throw new WriteOnlyException(this); + + if ((access & PropertyAccess.Write) != 0 && !chain[i].CanWrite) + throw new ReadOnlyException(this); + } + + Access = desiredAccess; + m_Chain = chain; + } + + public override string ToString() + { + if (!IsBound) + return Binding; + + var toJoin = new string[m_Chain.Length]; + + for (var i = 0; i < toJoin.Length; ++i) + toJoin[i] = m_Chain[i].Name; + + return string.Join(".", toJoin); + } + + public static Property Parse(Type type, string binding, PropertyAccess access) + { + var prop = new Property(binding); + + prop.BindTo(type, access); + + return prop; + } + } +} diff --git a/Projects/UOContent/Commands/ShardTime.cs b/Projects/UOContent/Commands/ShardTime.cs index af91bba37..8f0e9818a 100644 --- a/Projects/UOContent/Commands/ShardTime.cs +++ b/Projects/UOContent/Commands/ShardTime.cs @@ -1,19 +1,19 @@ -using System; - -namespace Server.Commands -{ - public class ShardTime - { - public static void Initialize() - { - CommandSystem.Register("Time", AccessLevel.Player, Time_OnCommand); - } - - [Usage("Time")] - [Description("Returns the server's local time.")] - private static void Time_OnCommand(CommandEventArgs e) - { - e.Mobile.SendMessage(DateTime.UtcNow.ToString()); - } - } -} \ No newline at end of file +using System; + +namespace Server.Commands +{ + public class ShardTime + { + public static void Initialize() + { + CommandSystem.Register("Time", AccessLevel.Player, Time_OnCommand); + } + + [Usage("Time")] + [Description("Returns the server's local time.")] + private static void Time_OnCommand(CommandEventArgs e) + { + e.Mobile.SendMessage(DateTime.UtcNow.ToString()); + } + } +} diff --git a/Projects/UOContent/Commands/SignParser.cs b/Projects/UOContent/Commands/SignParser.cs index d4c1fcd00..f379cd831 100644 --- a/Projects/UOContent/Commands/SignParser.cs +++ b/Projects/UOContent/Commands/SignParser.cs @@ -1,136 +1,140 @@ -using System.Collections.Generic; -using System.IO; -using Server.Items; - -namespace Server.Commands -{ - public class SignParser - { - private static readonly Queue m_ToDelete = new Queue(); - - public static void Initialize() - { - CommandSystem.Register("SignGen", AccessLevel.Administrator, SignGen_OnCommand); - } - - [Usage("SignGen")] - [Description("Generates world/shop signs on all facets.")] - public static void SignGen_OnCommand(CommandEventArgs c) - { - Parse(c.Mobile); - } - - public static void Parse(Mobile from) - { - string cfg = Path.Combine(Core.BaseDirectory, "Data/signs.cfg"); - - if (File.Exists(cfg)) - { - List list = new List(); - from.SendMessage("Generating signs, please wait."); - - using (StreamReader ip = new StreamReader(cfg)) - { - string line; - - while ((line = ip.ReadLine()) != null) - { - string[] split = line.Split(' '); - - SignEntry e = new SignEntry( - line.Substring(split[0].Length + 1 + split[1].Length + 1 + split[2].Length + 1 + - split[3].Length + 1 + split[4].Length + 1), - new Point3D(Utility.ToInt32(split[2]), Utility.ToInt32(split[3]), Utility.ToInt32(split[4])), - Utility.ToInt32(split[1]), Utility.ToInt32(split[0])); - - list.Add(e); - } - } - - Map[] brit = { Map.Felucca, Map.Trammel }; - Map[] fel = { Map.Felucca }; - Map[] tram = { Map.Trammel }; - Map[] ilsh = { Map.Ilshenar }; - Map[] malas = { Map.Malas }; - Map[] tokuno = { Map.Tokuno }; - - for (int i = 0; i < list.Count; ++i) - { - SignEntry e = list[i]; - - var maps = e.m_Map switch - { - 0 => brit, - 1 => fel, - 2 => tram, - 3 => ilsh, - 4 => malas, - 5 => tokuno, - _ => null - }; - - for (int j = 0; maps?.Length > j; ++j) - Add_Static(e.m_ItemID, e.m_Location, maps[j], e.m_Text); - } - - from.SendMessage("Sign generating complete."); - } - else - { - from.SendMessage("{0} not found!", cfg); - } - } - - public static void Add_Static(int itemID, Point3D location, Map map, string name) - { - IPooledEnumerable eable = map.GetItemsInRange(location, 0); - - foreach (Item item in eable) - if (item is Sign && item.Z == location.Z && item.ItemID == itemID) - m_ToDelete.Enqueue(item); - - eable.Free(); - - while (m_ToDelete.Count > 0) - m_ToDelete.Dequeue().Delete(); - - Item sign; - - if (name.StartsWith("#")) - { - sign = new LocalizedSign(itemID, Utility.ToInt32(name.Substring(1))); - } - else - { - sign = new Sign(itemID); - sign.Name = name; - } - - if (map == Map.Malas) - { - if (location.X >= 965 && location.Y >= 502 && location.X <= 1012 && location.Y <= 537) - sign.Hue = 0x47E; - else if (location.X >= 1960 && location.Y >= 1278 && location.X < 2106 && location.Y < 1413) - sign.Hue = 0x44E; - } - - sign.MoveToWorld(location, map); - } - - private class SignEntry - { - public readonly int m_ItemID; - public readonly Point3D m_Location; - public readonly int m_Map; - public readonly string m_Text; - - public SignEntry(string text, Point3D pt, int itemID, int mapLoc) - { - m_Text = text; - m_Location = pt; - m_ItemID = itemID; - m_Map = mapLoc; - } - } - } -} +using System.Collections.Generic; +using System.IO; +using Server.Items; + +namespace Server.Commands +{ + public class SignParser + { + private static readonly Queue m_ToDelete = new Queue(); + + public static void Initialize() + { + CommandSystem.Register("SignGen", AccessLevel.Administrator, SignGen_OnCommand); + } + + [Usage("SignGen")] + [Description("Generates world/shop signs on all facets.")] + public static void SignGen_OnCommand(CommandEventArgs c) + { + Parse(c.Mobile); + } + + public static void Parse(Mobile from) + { + var cfg = Path.Combine(Core.BaseDirectory, "Data/signs.cfg"); + + if (File.Exists(cfg)) + { + var list = new List(); + from.SendMessage("Generating signs, please wait."); + + using (var ip = new StreamReader(cfg)) + { + string line; + + while ((line = ip.ReadLine()) != null) + { + var split = line.Split(' '); + + var e = new SignEntry( + line.Substring( + split[0].Length + 1 + split[1].Length + 1 + split[2].Length + 1 + + split[3].Length + 1 + split[4].Length + 1 + ), + new Point3D(Utility.ToInt32(split[2]), Utility.ToInt32(split[3]), Utility.ToInt32(split[4])), + Utility.ToInt32(split[1]), + Utility.ToInt32(split[0]) + ); + + list.Add(e); + } + } + + Map[] brit = { Map.Felucca, Map.Trammel }; + Map[] fel = { Map.Felucca }; + Map[] tram = { Map.Trammel }; + Map[] ilsh = { Map.Ilshenar }; + Map[] malas = { Map.Malas }; + Map[] tokuno = { Map.Tokuno }; + + for (var i = 0; i < list.Count; ++i) + { + var e = list[i]; + + var maps = e.m_Map switch + { + 0 => brit, + 1 => fel, + 2 => tram, + 3 => ilsh, + 4 => malas, + 5 => tokuno, + _ => null + }; + + for (var j = 0; maps?.Length > j; ++j) + Add_Static(e.m_ItemID, e.m_Location, maps[j], e.m_Text); + } + + from.SendMessage("Sign generating complete."); + } + else + { + from.SendMessage("{0} not found!", cfg); + } + } + + public static void Add_Static(int itemID, Point3D location, Map map, string name) + { + var eable = map.GetItemsInRange(location, 0); + + foreach (var item in eable) + if (item is Sign && item.Z == location.Z && item.ItemID == itemID) + m_ToDelete.Enqueue(item); + + eable.Free(); + + while (m_ToDelete.Count > 0) + m_ToDelete.Dequeue().Delete(); + + Item sign; + + if (name.StartsWith("#")) + { + sign = new LocalizedSign(itemID, Utility.ToInt32(name.Substring(1))); + } + else + { + sign = new Sign(itemID); + sign.Name = name; + } + + if (map == Map.Malas) + { + if (location.X >= 965 && location.Y >= 502 && location.X <= 1012 && location.Y <= 537) + sign.Hue = 0x47E; + else if (location.X >= 1960 && location.Y >= 1278 && location.X < 2106 && location.Y < 1413) + sign.Hue = 0x44E; + } + + sign.MoveToWorld(location, map); + } + + private class SignEntry + { + public readonly int m_ItemID; + public readonly Point3D m_Location; + public readonly int m_Map; + public readonly string m_Text; + + public SignEntry(string text, Point3D pt, int itemID, int mapLoc) + { + m_Text = text; + m_Location = pt; + m_ItemID = itemID; + m_Map = mapLoc; + } + } + } +} diff --git a/Projects/UOContent/Commands/Skills.cs b/Projects/UOContent/Commands/Skills.cs index f427111fc..3e8914fcc 100644 --- a/Projects/UOContent/Commands/Skills.cs +++ b/Projects/UOContent/Commands/Skills.cs @@ -1,126 +1,126 @@ -using System; -using Server.Targeting; - -namespace Server.Commands -{ - public class SkillsCommand - { - public static void Initialize() - { - CommandSystem.Register("SetSkill", AccessLevel.GameMaster, SetSkill_OnCommand); - CommandSystem.Register("GetSkill", AccessLevel.GameMaster, GetSkill_OnCommand); - CommandSystem.Register("SetAllSkills", AccessLevel.GameMaster, SetAllSkills_OnCommand); - } - - [Usage("SetSkill ")] - [Description("Sets a skill value by name of a targeted mobile.")] - public static void SetSkill_OnCommand(CommandEventArgs arg) - { - if (arg.Length != 2) - { - arg.Mobile.SendMessage("SetSkill "); - } - else - { - if (Enum.TryParse(arg.GetString(0), true, out SkillName skill)) - arg.Mobile.Target = new SkillTarget(skill, arg.GetDouble(1)); - else - arg.Mobile.SendLocalizedMessage(1005631); // You have specified an invalid skill to set. - } - } - - [Usage("SetAllSkills ")] - [Description("Sets all skill values of a targeted mobile.")] - public static void SetAllSkills_OnCommand(CommandEventArgs arg) - { - if (arg.Length != 1) - arg.Mobile.SendMessage("SetAllSkills "); - else - arg.Mobile.Target = new AllSkillsTarget(arg.GetDouble(0)); - } - - [Usage("GetSkill ")] - [Description("Gets a skill value by name of a targeted mobile.")] - public static void GetSkill_OnCommand(CommandEventArgs arg) - { - if (arg.Length != 1) - { - arg.Mobile.SendMessage("GetSkill "); - } - else - { - if (Enum.TryParse(arg.GetString(0), true, out SkillName skill)) - arg.Mobile.Target = new SkillTarget(skill); - else - arg.Mobile.SendMessage("You have specified an invalid skill to get."); - } - } - - public class AllSkillsTarget : Target - { - private readonly double m_Value; - - public AllSkillsTarget(double value) : base(-1, false, TargetFlags.None) => m_Value = value; - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is Mobile targ) - { - Server.Skills skills = targ.Skills; - - for (int i = 0; i < skills.Length; ++i) - skills[i].Base = m_Value; - - CommandLogging.LogChangeProperty(from, targ, "EverySkill.Base", m_Value.ToString()); - } - else - { - from.SendMessage("That does not have skills!"); - } - } - } - - public class SkillTarget : Target - { - private readonly bool m_Set; - private readonly SkillName m_Skill; - private readonly double m_Value; - - public SkillTarget(SkillName skill, double value) : base(-1, false, TargetFlags.None) - { - m_Set = true; - m_Skill = skill; - m_Value = value; - } - - public SkillTarget(SkillName skill) : base(-1, false, TargetFlags.None) - { - m_Set = false; - m_Skill = skill; - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is Mobile targ) - { - Skill skill = targ.Skills[m_Skill]; - - if (skill == null) - return; - - if (m_Set) - { - skill.Base = m_Value; - CommandLogging.LogChangeProperty(from, targ, $"{m_Skill}.Base", m_Value.ToString()); - } - - from.SendMessage("{0} : {1} (Base: {2})", m_Skill, skill.Value, skill.Base); - } - else - { - from.SendMessage("That does not have skills!"); - } - } - } - } -} \ No newline at end of file +using System; +using Server.Targeting; + +namespace Server.Commands +{ + public class SkillsCommand + { + public static void Initialize() + { + CommandSystem.Register("SetSkill", AccessLevel.GameMaster, SetSkill_OnCommand); + CommandSystem.Register("GetSkill", AccessLevel.GameMaster, GetSkill_OnCommand); + CommandSystem.Register("SetAllSkills", AccessLevel.GameMaster, SetAllSkills_OnCommand); + } + + [Usage("SetSkill ")] + [Description("Sets a skill value by name of a targeted mobile.")] + public static void SetSkill_OnCommand(CommandEventArgs arg) + { + if (arg.Length != 2) + { + arg.Mobile.SendMessage("SetSkill "); + } + else + { + if (Enum.TryParse(arg.GetString(0), true, out SkillName skill)) + arg.Mobile.Target = new SkillTarget(skill, arg.GetDouble(1)); + else + arg.Mobile.SendLocalizedMessage(1005631); // You have specified an invalid skill to set. + } + } + + [Usage("SetAllSkills ")] + [Description("Sets all skill values of a targeted mobile.")] + public static void SetAllSkills_OnCommand(CommandEventArgs arg) + { + if (arg.Length != 1) + arg.Mobile.SendMessage("SetAllSkills "); + else + arg.Mobile.Target = new AllSkillsTarget(arg.GetDouble(0)); + } + + [Usage("GetSkill ")] + [Description("Gets a skill value by name of a targeted mobile.")] + public static void GetSkill_OnCommand(CommandEventArgs arg) + { + if (arg.Length != 1) + { + arg.Mobile.SendMessage("GetSkill "); + } + else + { + if (Enum.TryParse(arg.GetString(0), true, out SkillName skill)) + arg.Mobile.Target = new SkillTarget(skill); + else + arg.Mobile.SendMessage("You have specified an invalid skill to get."); + } + } + + public class AllSkillsTarget : Target + { + private readonly double m_Value; + + public AllSkillsTarget(double value) : base(-1, false, TargetFlags.None) => m_Value = value; + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted is Mobile targ) + { + var skills = targ.Skills; + + for (var i = 0; i < skills.Length; ++i) + skills[i].Base = m_Value; + + CommandLogging.LogChangeProperty(from, targ, "EverySkill.Base", m_Value.ToString()); + } + else + { + from.SendMessage("That does not have skills!"); + } + } + } + + public class SkillTarget : Target + { + private readonly bool m_Set; + private readonly SkillName m_Skill; + private readonly double m_Value; + + public SkillTarget(SkillName skill, double value) : base(-1, false, TargetFlags.None) + { + m_Set = true; + m_Skill = skill; + m_Value = value; + } + + public SkillTarget(SkillName skill) : base(-1, false, TargetFlags.None) + { + m_Set = false; + m_Skill = skill; + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted is Mobile targ) + { + var skill = targ.Skills[m_Skill]; + + if (skill == null) + return; + + if (m_Set) + { + skill.Base = m_Value; + CommandLogging.LogChangeProperty(from, targ, $"{m_Skill}.Base", m_Value.ToString()); + } + + from.SendMessage("{0} : {1} (Base: {2})", m_Skill, skill.Value, skill.Base); + } + else + { + from.SendMessage("That does not have skills!"); + } + } + } + } +} diff --git a/Projects/UOContent/Commands/SkillsMenu.cs b/Projects/UOContent/Commands/SkillsMenu.cs index 6b4e617ab..fbfd6f618 100644 --- a/Projects/UOContent/Commands/SkillsMenu.cs +++ b/Projects/UOContent/Commands/SkillsMenu.cs @@ -1,38 +1,38 @@ -using Server.Gumps; -using Server.Targeting; - -namespace Server.Commands -{ - public class Skills - { - public static void Initialize() - { - Register(); - } - - public static void Register() - { - CommandSystem.Register("Skills", AccessLevel.Counselor, Skills_OnCommand); - } - - [Usage("Skills")] - [Description("Opens a menu where you can view or edit skills of a targeted mobile.")] - private static void Skills_OnCommand(CommandEventArgs e) - { - e.Mobile.Target = new SkillsTarget(); - } - - private class SkillsTarget : Target - { - public SkillsTarget() : base(-1, true, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object o) - { - if (o is Mobile mobile) - from.SendGump(new SkillsGump(from, mobile)); - } - } - } -} \ No newline at end of file +using Server.Gumps; +using Server.Targeting; + +namespace Server.Commands +{ + public class Skills + { + public static void Initialize() + { + Register(); + } + + public static void Register() + { + CommandSystem.Register("Skills", AccessLevel.Counselor, Skills_OnCommand); + } + + [Usage("Skills")] + [Description("Opens a menu where you can view or edit skills of a targeted mobile.")] + private static void Skills_OnCommand(CommandEventArgs e) + { + e.Mobile.Target = new SkillsTarget(); + } + + private class SkillsTarget : Target + { + public SkillsTarget() : base(-1, true, TargetFlags.None) + { + } + + protected override void OnTarget(Mobile from, object o) + { + if (o is Mobile mobile) + from.SendGump(new SkillsGump(from, mobile)); + } + } + } +} diff --git a/Projects/UOContent/Commands/Statics.cs b/Projects/UOContent/Commands/Statics.cs index 790146bb2..68f25df59 100644 --- a/Projects/UOContent/Commands/Statics.cs +++ b/Projects/UOContent/Commands/Statics.cs @@ -1,579 +1,725 @@ -using System.Collections.Generic; -using System.IO; -using Server.Commands; -using Server.Gumps; -using Server.Items; - -namespace Server -{ - public class Statics - { - private const string BaseFreezeWarning = "{0} " + - "Those items will be removed from the world and placed into the server data files. " + - "Other players will not see the changes unless you distribute your data files to them.

" + - "This operation may not complete unless the server and client are using different data files. " + - "If you receive a message stating 'output data files could not be opened,' then you are probably sharing data files. " + - "Create a new directory for the world data files (statics*.mul and staidx*.mul) and add that to Scritps/Misc/DataPath.cs.

" + - "The change will be in effect immediately on the server, however, you must restart your client and update it's data files for the changes to become visible. " + - "It is strongly recommended that you make backup of the data files mentioned above. " + - "Do you wish to proceed?"; - - private const string BaseUnfreezeWarning = "{0} " + - "Those items will be removed from the static files and exchanged with unmovable dynamic items. " + - "Other players will not see the changes unless you distribute your data files to them.

" + - "This operation may not complete unless the server and client are using different data files. " + - "If you receive a message stating 'output data files could not be opened,' then you are probably sharing data files. " + - "Create a new directory for the world data files (statics*.mul and staidx*.mul) and add that to Scritps/Misc/DataPath.cs.

" + - "The change will be in effect immediately on the server, however, you must restart your client and update it's data files for the changes to become visible. " + - "It is strongly recommended that you make backup of the data files mentioned above. " + - "Do you wish to proceed?"; - - private static readonly Point3D NullP3D = new Point3D(int.MinValue, int.MinValue, int.MinValue); - - private static byte[] m_Buffer; - - private static StaticTile[] m_TileBuffer = new StaticTile[128]; - - public static void Initialize() - { - CommandSystem.Register("Freeze", AccessLevel.Administrator, Freeze_OnCommand); - CommandSystem.Register("FreezeMap", AccessLevel.Administrator, FreezeMap_OnCommand); - CommandSystem.Register("FreezeWorld", AccessLevel.Administrator, FreezeWorld_OnCommand); - - CommandSystem.Register("Unfreeze", AccessLevel.Administrator, Unfreeze_OnCommand); - CommandSystem.Register("UnfreezeMap", AccessLevel.Administrator, UnfreezeMap_OnCommand); - CommandSystem.Register("UnfreezeWorld", AccessLevel.Administrator, UnfreezeWorld_OnCommand); - } - - public delegate void FreezeCallback(Mobile from, bool okay, StateInfo si); - - [Usage("Freeze")] - [Description("Makes a targeted area of dynamic items static.")] - public static void Freeze_OnCommand(CommandEventArgs e) - { - Mobile from = e.Mobile; - BoundingBoxPicker.Begin(from, (map, start, end) => FreezeBox_Callback(from, map, start, end)); - } - - [Usage("FreezeMap")] - [Description("Makes every dynamic item in your map static.")] - public static void FreezeMap_OnCommand(CommandEventArgs e) - { - Mobile from = e.Mobile; - Map map = from.Map; - - if (map != null && map != Map.Internal) - SendWarning(from, "You are about to freeze all items in {0}.", BaseFreezeWarning, map, NullP3D, - NullP3D, FreezeWarning_Callback); - } - - [Usage("FreezeWorld")] - [Description("Makes every dynamic item on all maps static.")] - public static void FreezeWorld_OnCommand(CommandEventArgs e) - { - SendWarning(e.Mobile, "You are about to freeze every item on every map.", BaseFreezeWarning, null, - NullP3D, NullP3D, FreezeWarning_Callback); - } - - public static void SendWarning(Mobile m, string header, string baseWarning, Map map, Point3D start, Point3D end, - FreezeCallback callback) - { - m.SendGump(new WarningGump(1060635, 30720, string.Format(baseWarning, string.Format(header, map)), 0xFFC000, 420, - 400, okay => callback(m, okay, new StateInfo(map, start, end)))); - } - - private static void FreezeBox_Callback(Mobile from, Map map, Point3D start, Point3D end) - { - SendWarning(from, "You are about to freeze a section of items.", BaseFreezeWarning, map, start, end, - FreezeWarning_Callback); - } - - private static void FreezeWarning_Callback(Mobile from, bool okay, StateInfo si) - { - if (!okay) - return; - - Freeze(from, si.m_Map, si.m_Start, si.m_End); - } - - public static void Freeze(Mobile from, Map targetMap, Point3D start3d, Point3D end3d) - { - Dictionary> mapTable = new Dictionary>(); - - if (start3d == NullP3D && end3d == NullP3D) - { - if (targetMap == null) - CommandLogging.WriteLine(from, "{0} {1} invoking freeze for every item in every map", from.AccessLevel, - CommandLogging.Format(from)); - else - CommandLogging.WriteLine(from, "{0} {1} invoking freeze for every item in {0}", from.AccessLevel, - CommandLogging.Format(from), targetMap); - - foreach (Item item in World.Items.Values) - { - if (targetMap != null && item.Map != targetMap) - continue; - - if (item.Parent != null) - continue; - - if (item is Static || item is BaseFloor || item is BaseWall) - { - Map itemMap = item.Map; - - if (itemMap == null || itemMap == Map.Internal) - continue; - - if (!mapTable.TryGetValue(itemMap, out Dictionary table)) - mapTable[itemMap] = table = new Dictionary(); - - Point2D p = new Point2D(item.X >> 3, item.Y >> 3); - - if (!table.TryGetValue(p, out DeltaState state)) - table[p] = state = new DeltaState(p); - - state.m_List.Add(item); - } - } - } - else if (targetMap != null) - { - Point2D start = targetMap.Bound(new Point2D(start3d)), end = targetMap.Bound(new Point2D(end3d)); - - CommandLogging.WriteLine(from, "{0} {1} invoking freeze from {2} to {3} in {4}", from.AccessLevel, - CommandLogging.Format(from), start, end, targetMap); - - IPooledEnumerable eable = - targetMap.GetItemsInBounds(new Rectangle2D(start.X, start.Y, end.X - start.X + 1, end.Y - start.Y + 1)); - - foreach (Item item in eable) - if (item is Static || item is BaseFloor || item is BaseWall) - { - Map itemMap = item.Map; - - if (itemMap == null || itemMap == Map.Internal) - continue; - - if (!mapTable.TryGetValue(itemMap, out Dictionary table)) - mapTable[itemMap] = table = new Dictionary(); - - Point2D p = new Point2D(item.X >> 3, item.Y >> 3); - - if (!table.TryGetValue(p, out DeltaState state)) - table[p] = state = new DeltaState(p); - - state.m_List.Add(item); - } - - eable.Free(); - } - - if (mapTable.Count == 0) - { - from.SendGump(new NoticeGump(1060637, 30720, - "No freezable items were found. Only the following item types are frozen:
- Static
- BaseFloor
- BaseWall", - 0xFFC000, 320, 240)); - return; - } - - bool badDataFile = false; - - int totalFrozen = 0; - - foreach (KeyValuePair> de in mapTable) - { - Map map = de.Key; - Dictionary table = de.Value; - - TileMatrix matrix = map.Tiles; - - using FileStream idxStream = OpenWrite(matrix.IndexStream); - using FileStream mulStream = OpenWrite(matrix.DataStream); - if (idxStream == null || mulStream == null) - { - badDataFile = true; - continue; - } - - BinaryReader idxReader = new BinaryReader(idxStream); - - BinaryWriter idxWriter = new BinaryWriter(idxStream); - BinaryWriter mulWriter = new BinaryWriter(mulStream); - - foreach (DeltaState state in table.Values) - { - StaticTile[] oldTiles = ReadStaticBlock(idxReader, mulStream, state.m_X, state.m_Y, - matrix.BlockWidth, matrix.BlockHeight, out int oldTileCount); - - if (oldTileCount < 0) - continue; - - int newTileCount = 0; - StaticTile[] newTiles = new StaticTile[state.m_List.Count]; - - for (int i = 0; i < state.m_List.Count; ++i) - { - Item item = state.m_List[i]; - - int xOffset = item.X - state.m_X * 8; - int yOffset = item.Y - state.m_Y * 8; - - if (xOffset < 0 || xOffset >= 8 || yOffset < 0 || yOffset >= 8) - continue; - - StaticTile newTile = new StaticTile((ushort)item.ItemID, (byte)xOffset, (byte)yOffset, - (sbyte)item.Z, (short)item.Hue); - - newTiles[newTileCount++] = newTile; - - item.Delete(); - - ++totalFrozen; - } - - int mulPos = -1; - int length = -1; - int extra = 0; - - if (oldTileCount + newTileCount > 0) - { - mulWriter.Seek(0, SeekOrigin.End); - - mulPos = (int)mulWriter.BaseStream.Position; - length = (oldTileCount + newTileCount) * 7; - extra = 1; - - for (int i = 0; i < oldTileCount; ++i) - { - StaticTile toWrite = oldTiles[i]; - - mulWriter.Write((ushort)toWrite.ID); - mulWriter.Write((byte)toWrite.X); - mulWriter.Write((byte)toWrite.Y); - mulWriter.Write((sbyte)toWrite.Z); - mulWriter.Write((short)toWrite.Hue); - } - - for (int i = 0; i < newTileCount; ++i) - { - StaticTile toWrite = newTiles[i]; - - mulWriter.Write((ushort)toWrite.ID); - mulWriter.Write((byte)toWrite.X); - mulWriter.Write((byte)toWrite.Y); - mulWriter.Write((sbyte)toWrite.Z); - mulWriter.Write((short)toWrite.Hue); - } - - mulWriter.Flush(); - } - - int idxPos = (state.m_X * matrix.BlockHeight + state.m_Y) * 12; - - idxWriter.Seek(idxPos, SeekOrigin.Begin); - idxWriter.Write(mulPos); - idxWriter.Write(length); - idxWriter.Write(extra); - - idxWriter.Flush(); - - matrix.SetStaticBlock(state.m_X, state.m_Y, null); - } - } - - if (totalFrozen == 0 && badDataFile) - from.SendGump(new NoticeGump(1060637, 30720, - "Output data files could not be opened and the freeze operation has been aborted.

This probably means your server and client are using the same data files. Instructions on how to resolve this can be found in the first warning window.", - 0xFFC000, 320, 240)); - else - from.SendGump(new NoticeGump(1060637, 30720, - $"Freeze operation completed successfully.

{totalFrozen} item{(totalFrozen != 1 ? "s were" : " was")} frozen.

You must restart your client and update it's data files to see the changes.", - 0xFFC000, 320, 240)); - } - - [Usage("Unfreeze")] - [Description("Makes a targeted area of static items dynamic.")] - public static void Unfreeze_OnCommand(CommandEventArgs e) - { - Mobile from = e.Mobile; - BoundingBoxPicker.Begin(from, (map, start, end) => UnfreezeBox_Callback(from, map, start, end)); - } - - [Usage("UnfreezeMap")] - [Description("Makes every static item in your map dynamic.")] - public static void UnfreezeMap_OnCommand(CommandEventArgs e) - { - Map map = e.Mobile.Map; - - if (map != null && map != Map.Internal) - SendWarning(e.Mobile, "You are about to unfreeze all items in {0}.", BaseUnfreezeWarning, map, - NullP3D, NullP3D, UnfreezeWarning_Callback); - } - - [Usage("UnfreezeWorld")] - [Description("Makes every static item on all maps dynamic.")] - public static void UnfreezeWorld_OnCommand(CommandEventArgs e) - { - SendWarning(e.Mobile, "You are about to unfreeze every item on every map.", BaseUnfreezeWarning, null, - NullP3D, NullP3D, UnfreezeWarning_Callback); - } - - private static void UnfreezeBox_Callback(Mobile from, Map map, Point3D start, Point3D end) - { - SendWarning(from, "You are about to unfreeze a section of items.", BaseUnfreezeWarning, map, start, end, - UnfreezeWarning_Callback); - } - - private static void UnfreezeWarning_Callback(Mobile from, bool okay, StateInfo si) - { - if (!okay) - return; - - Unfreeze(from, si.m_Map, si.m_Start, si.m_End); - } - - private static void DoUnfreeze(Map map, Point2D start, Point2D end, ref bool badDataFile, ref int totalUnfrozen) - { - start = map.Bound(start); - end = map.Bound(end); - - int xStartBlock = start.X >> 3; - int yStartBlock = start.Y >> 3; - int xEndBlock = end.X >> 3; - int yEndBlock = end.Y >> 3; - - int xTileStart = start.X, yTileStart = start.Y; - int xTileWidth = end.X - start.X + 1, yTileHeight = end.Y - start.Y + 1; - - TileMatrix matrix = map.Tiles; - - using FileStream idxStream = OpenWrite(matrix.IndexStream); - using FileStream mulStream = OpenWrite(matrix.DataStream); - if (idxStream == null || mulStream == null) - { - badDataFile = true; - return; - } - - BinaryReader idxReader = new BinaryReader(idxStream); - - BinaryWriter idxWriter = new BinaryWriter(idxStream); - BinaryWriter mulWriter = new BinaryWriter(mulStream); - - for (int x = xStartBlock; x <= xEndBlock; ++x) - for (int y = yStartBlock; y <= yEndBlock; ++y) - { - StaticTile[] oldTiles = ReadStaticBlock(idxReader, mulStream, x, y, matrix.BlockWidth, - matrix.BlockHeight, out int oldTileCount); - - if (oldTileCount < 0) - continue; - - int newTileCount = 0; - StaticTile[] newTiles = new StaticTile[oldTileCount]; - - int baseX = (x << 3) - xTileStart, baseY = (y << 3) - yTileStart; - - for (int i = 0; i < oldTileCount; ++i) - { - StaticTile oldTile = oldTiles[i]; - - int px = baseX + oldTile.X; - int py = baseY + oldTile.Y; - - if (px < 0 || px >= xTileWidth || py < 0 || py >= yTileHeight) - { - newTiles[newTileCount++] = oldTile; - } - else - { - ++totalUnfrozen; - - Item item = new Static(oldTile.ID); - - item.Hue = oldTile.Hue; - - item.MoveToWorld(new Point3D(px + xTileStart, py + yTileStart, oldTile.Z), map); - } - } - - int mulPos = -1; - int length = -1; - int extra = 0; - - if (newTileCount > 0) - { - mulWriter.Seek(0, SeekOrigin.End); - - mulPos = (int)mulWriter.BaseStream.Position; - length = newTileCount * 7; - extra = 1; - - for (int i = 0; i < newTileCount; ++i) - { - StaticTile toWrite = newTiles[i]; - - mulWriter.Write((ushort)toWrite.ID); - mulWriter.Write((byte)toWrite.X); - mulWriter.Write((byte)toWrite.Y); - mulWriter.Write((sbyte)toWrite.Z); - mulWriter.Write((short)toWrite.Hue); - } - - mulWriter.Flush(); - } - - int idxPos = (x * matrix.BlockHeight + y) * 12; - - idxWriter.Seek(idxPos, SeekOrigin.Begin); - idxWriter.Write(mulPos); - idxWriter.Write(length); - idxWriter.Write(extra); - - idxWriter.Flush(); - - matrix.SetStaticBlock(x, y, null); - } - } - - public static void DoUnfreeze(Map map, ref bool badDataFile, ref int totalUnfrozen) - { - DoUnfreeze(map, Point2D.Zero, new Point2D(map.Width - 1, map.Height - 1), ref badDataFile, ref totalUnfrozen); - } - - public static void Unfreeze(Mobile from, Map map, Point3D start, Point3D end) - { - int totalUnfrozen = 0; - bool badDataFile = false; - - if (map == null) - { - CommandLogging.WriteLine(from, "{0} {1} invoking unfreeze for every item in every map", from.AccessLevel, - CommandLogging.Format(from)); - - DoUnfreeze(Map.Felucca, ref badDataFile, ref totalUnfrozen); - DoUnfreeze(Map.Trammel, ref badDataFile, ref totalUnfrozen); - DoUnfreeze(Map.Ilshenar, ref badDataFile, ref totalUnfrozen); - DoUnfreeze(Map.Malas, ref badDataFile, ref totalUnfrozen); - DoUnfreeze(Map.Tokuno, ref badDataFile, ref totalUnfrozen); - } - else if (start == NullP3D && end == NullP3D) - { - CommandLogging.WriteLine(from, "{0} {1} invoking unfreeze for every item in {2}", from.AccessLevel, - CommandLogging.Format(from), map); - - DoUnfreeze(map, ref badDataFile, ref totalUnfrozen); - } - else - { - CommandLogging.WriteLine(from, "{0} {1} invoking unfreeze from {2} to {3} in {4}", from.AccessLevel, - CommandLogging.Format(from), new Point2D(start), new Point2D(end), map); - - DoUnfreeze(map, new Point2D(start), new Point2D(end), ref badDataFile, ref totalUnfrozen); - } - - if (totalUnfrozen == 0 && badDataFile) - from.SendGump(new NoticeGump(1060637, 30720, - "Output data files could not be opened and the unfreeze operation has been aborted.

This probably means your server and client are using the same data files. Instructions on how to resolve this can be found in the first warning window.", - 0xFFC000, 320, 240)); - else - from.SendGump(new NoticeGump(1060637, 30720, - $"Unfreeze operation completed successfully.

{totalUnfrozen} item{(totalUnfrozen != 1 ? "s were" : " was")} unfrozen.

You must restart your client and update it's data files to see the changes.", - 0xFFC000, 320, 240)); - } - - private static FileStream OpenWrite(FileStream orig) - { - if (orig == null) - return null; - - try - { - return new FileStream(orig.Name, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite); - } - catch - { - return null; - } - } - - private static StaticTile[] ReadStaticBlock(BinaryReader idxReader, FileStream mulStream, int x, int y, int width, - int height, out int count) - { - try - { - if (x < 0 || x >= width || y < 0 || y >= height) - { - count = -1; - return m_TileBuffer; - } - - idxReader.BaseStream.Seek((x * height + y) * 12, SeekOrigin.Begin); - - int lookup = idxReader.ReadInt32(); - int length = idxReader.ReadInt32(); - - if (lookup < 0 || length <= 0) - { - count = 0; - } - else - { - count = length / 7; - - mulStream.Seek(lookup, SeekOrigin.Begin); - - if (m_TileBuffer.Length < count) - m_TileBuffer = new StaticTile[count]; - - StaticTile[] staTiles = m_TileBuffer; - - if (m_Buffer == null || length > m_Buffer.Length) - m_Buffer = new byte[length]; - - mulStream.Read(m_Buffer, 0, length); - - int index = 0; - - for (int i = 0; i < count; ++i) - staTiles[i].Set((ushort)(m_Buffer[index++] | m_Buffer[index++] << 8), - m_Buffer[index++], m_Buffer[index++], (sbyte)m_Buffer[index++], - (short)(m_Buffer[index++] | m_Buffer[index++] << 8)); - } - } - catch - { - count = -1; - } - - return m_TileBuffer; - } - - private class DeltaState - { - public readonly List m_List; - public readonly int m_X; - public readonly int m_Y; - - public DeltaState(Point2D p) - { - m_X = p.X; - m_Y = p.Y; - m_List = new List(); - } - } - - public class StateInfo - { - public Map m_Map; - public Point3D m_Start, m_End; - - public StateInfo(Map map, Point3D start, Point3D end) - { - m_Map = map; - m_Start = start; - m_End = end; - } - } - } -} +using System.Collections.Generic; +using System.IO; +using Server.Commands; +using Server.Gumps; +using Server.Items; + +namespace Server +{ + public class Statics + { + public delegate void FreezeCallback(Mobile from, bool okay, StateInfo si); + + private const string BaseFreezeWarning = "{0} " + + "Those items will be removed from the world and placed into the server data files. " + + "Other players will not see the changes unless you distribute your data files to them.

" + + "This operation may not complete unless the server and client are using different data files. " + + "If you receive a message stating 'output data files could not be opened,' then you are probably sharing data files. " + + "Create a new directory for the world data files (statics*.mul and staidx*.mul) and add that to Scritps/Misc/DataPath.cs.

" + + "The change will be in effect immediately on the server, however, you must restart your client and update it's data files for the changes to become visible. " + + "It is strongly recommended that you make backup of the data files mentioned above. " + + "Do you wish to proceed?"; + + private const string BaseUnfreezeWarning = "{0} " + + "Those items will be removed from the static files and exchanged with unmovable dynamic items. " + + "Other players will not see the changes unless you distribute your data files to them.

" + + "This operation may not complete unless the server and client are using different data files. " + + "If you receive a message stating 'output data files could not be opened,' then you are probably sharing data files. " + + "Create a new directory for the world data files (statics*.mul and staidx*.mul) and add that to Scritps/Misc/DataPath.cs.

" + + "The change will be in effect immediately on the server, however, you must restart your client and update it's data files for the changes to become visible. " + + "It is strongly recommended that you make backup of the data files mentioned above. " + + "Do you wish to proceed?"; + + private static readonly Point3D NullP3D = new Point3D(int.MinValue, int.MinValue, int.MinValue); + + private static byte[] m_Buffer; + + private static StaticTile[] m_TileBuffer = new StaticTile[128]; + + public static void Initialize() + { + CommandSystem.Register("Freeze", AccessLevel.Administrator, Freeze_OnCommand); + CommandSystem.Register("FreezeMap", AccessLevel.Administrator, FreezeMap_OnCommand); + CommandSystem.Register("FreezeWorld", AccessLevel.Administrator, FreezeWorld_OnCommand); + + CommandSystem.Register("Unfreeze", AccessLevel.Administrator, Unfreeze_OnCommand); + CommandSystem.Register("UnfreezeMap", AccessLevel.Administrator, UnfreezeMap_OnCommand); + CommandSystem.Register("UnfreezeWorld", AccessLevel.Administrator, UnfreezeWorld_OnCommand); + } + + [Usage("Freeze")] + [Description("Makes a targeted area of dynamic items static.")] + public static void Freeze_OnCommand(CommandEventArgs e) + { + var from = e.Mobile; + BoundingBoxPicker.Begin(from, (map, start, end) => FreezeBox_Callback(from, map, start, end)); + } + + [Usage("FreezeMap")] + [Description("Makes every dynamic item in your map static.")] + public static void FreezeMap_OnCommand(CommandEventArgs e) + { + var from = e.Mobile; + var map = from.Map; + + if (map != null && map != Map.Internal) + SendWarning( + from, + "You are about to freeze all items in {0}.", + BaseFreezeWarning, + map, + NullP3D, + NullP3D, + FreezeWarning_Callback + ); + } + + [Usage("FreezeWorld")] + [Description("Makes every dynamic item on all maps static.")] + public static void FreezeWorld_OnCommand(CommandEventArgs e) + { + SendWarning( + e.Mobile, + "You are about to freeze every item on every map.", + BaseFreezeWarning, + null, + NullP3D, + NullP3D, + FreezeWarning_Callback + ); + } + + public static void SendWarning( + Mobile m, string header, string baseWarning, Map map, Point3D start, Point3D end, + FreezeCallback callback + ) + { + m.SendGump( + new WarningGump( + 1060635, + 30720, + string.Format(baseWarning, string.Format(header, map)), + 0xFFC000, + 420, + 400, + okay => callback(m, okay, new StateInfo(map, start, end)) + ) + ); + } + + private static void FreezeBox_Callback(Mobile from, Map map, Point3D start, Point3D end) + { + SendWarning( + from, + "You are about to freeze a section of items.", + BaseFreezeWarning, + map, + start, + end, + FreezeWarning_Callback + ); + } + + private static void FreezeWarning_Callback(Mobile from, bool okay, StateInfo si) + { + if (!okay) + return; + + Freeze(from, si.m_Map, si.m_Start, si.m_End); + } + + public static void Freeze(Mobile from, Map targetMap, Point3D start3d, Point3D end3d) + { + var mapTable = new Dictionary>(); + + if (start3d == NullP3D && end3d == NullP3D) + { + if (targetMap == null) + CommandLogging.WriteLine( + from, + "{0} {1} invoking freeze for every item in every map", + from.AccessLevel, + CommandLogging.Format(from) + ); + else + CommandLogging.WriteLine( + from, + "{0} {1} invoking freeze for every item in {0}", + from.AccessLevel, + CommandLogging.Format(from), + targetMap + ); + + foreach (var item in World.Items.Values) + { + if (targetMap != null && item.Map != targetMap) + continue; + + if (item.Parent != null) + continue; + + if (item is Static || item is BaseFloor || item is BaseWall) + { + var itemMap = item.Map; + + if (itemMap == null || itemMap == Map.Internal) + continue; + + if (!mapTable.TryGetValue(itemMap, out var table)) + mapTable[itemMap] = table = new Dictionary(); + + var p = new Point2D(item.X >> 3, item.Y >> 3); + + if (!table.TryGetValue(p, out var state)) + table[p] = state = new DeltaState(p); + + state.m_List.Add(item); + } + } + } + else if (targetMap != null) + { + Point2D start = targetMap.Bound(new Point2D(start3d)), end = targetMap.Bound(new Point2D(end3d)); + + CommandLogging.WriteLine( + from, + "{0} {1} invoking freeze from {2} to {3} in {4}", + from.AccessLevel, + CommandLogging.Format(from), + start, + end, + targetMap + ); + + var eable = + targetMap.GetItemsInBounds(new Rectangle2D(start.X, start.Y, end.X - start.X + 1, end.Y - start.Y + 1)); + + foreach (var item in eable) + if (item is Static || item is BaseFloor || item is BaseWall) + { + var itemMap = item.Map; + + if (itemMap == null || itemMap == Map.Internal) + continue; + + if (!mapTable.TryGetValue(itemMap, out var table)) + mapTable[itemMap] = table = new Dictionary(); + + var p = new Point2D(item.X >> 3, item.Y >> 3); + + if (!table.TryGetValue(p, out var state)) + table[p] = state = new DeltaState(p); + + state.m_List.Add(item); + } + + eable.Free(); + } + + if (mapTable.Count == 0) + { + from.SendGump( + new NoticeGump( + 1060637, + 30720, + "No freezable items were found. Only the following item types are frozen:
- Static
- BaseFloor
- BaseWall", + 0xFFC000, + 320, + 240 + ) + ); + return; + } + + var badDataFile = false; + + var totalFrozen = 0; + + foreach (var de in mapTable) + { + var map = de.Key; + var table = de.Value; + + var matrix = map.Tiles; + + using var idxStream = OpenWrite(matrix.IndexStream); + using var mulStream = OpenWrite(matrix.DataStream); + if (idxStream == null || mulStream == null) + { + badDataFile = true; + continue; + } + + var idxReader = new BinaryReader(idxStream); + + var idxWriter = new BinaryWriter(idxStream); + var mulWriter = new BinaryWriter(mulStream); + + foreach (var state in table.Values) + { + var oldTiles = ReadStaticBlock( + idxReader, + mulStream, + state.m_X, + state.m_Y, + matrix.BlockWidth, + matrix.BlockHeight, + out var oldTileCount + ); + + if (oldTileCount < 0) + continue; + + var newTileCount = 0; + var newTiles = new StaticTile[state.m_List.Count]; + + for (var i = 0; i < state.m_List.Count; ++i) + { + var item = state.m_List[i]; + + var xOffset = item.X - state.m_X * 8; + var yOffset = item.Y - state.m_Y * 8; + + if (xOffset < 0 || xOffset >= 8 || yOffset < 0 || yOffset >= 8) + continue; + + var newTile = new StaticTile( + (ushort)item.ItemID, + (byte)xOffset, + (byte)yOffset, + (sbyte)item.Z, + (short)item.Hue + ); + + newTiles[newTileCount++] = newTile; + + item.Delete(); + + ++totalFrozen; + } + + var mulPos = -1; + var length = -1; + var extra = 0; + + if (oldTileCount + newTileCount > 0) + { + mulWriter.Seek(0, SeekOrigin.End); + + mulPos = (int)mulWriter.BaseStream.Position; + length = (oldTileCount + newTileCount) * 7; + extra = 1; + + for (var i = 0; i < oldTileCount; ++i) + { + var toWrite = oldTiles[i]; + + mulWriter.Write((ushort)toWrite.ID); + mulWriter.Write((byte)toWrite.X); + mulWriter.Write((byte)toWrite.Y); + mulWriter.Write((sbyte)toWrite.Z); + mulWriter.Write((short)toWrite.Hue); + } + + for (var i = 0; i < newTileCount; ++i) + { + var toWrite = newTiles[i]; + + mulWriter.Write((ushort)toWrite.ID); + mulWriter.Write((byte)toWrite.X); + mulWriter.Write((byte)toWrite.Y); + mulWriter.Write((sbyte)toWrite.Z); + mulWriter.Write((short)toWrite.Hue); + } + + mulWriter.Flush(); + } + + var idxPos = (state.m_X * matrix.BlockHeight + state.m_Y) * 12; + + idxWriter.Seek(idxPos, SeekOrigin.Begin); + idxWriter.Write(mulPos); + idxWriter.Write(length); + idxWriter.Write(extra); + + idxWriter.Flush(); + + matrix.SetStaticBlock(state.m_X, state.m_Y, null); + } + } + + if (totalFrozen == 0 && badDataFile) + from.SendGump( + new NoticeGump( + 1060637, + 30720, + "Output data files could not be opened and the freeze operation has been aborted.

This probably means your server and client are using the same data files. Instructions on how to resolve this can be found in the first warning window.", + 0xFFC000, + 320, + 240 + ) + ); + else + from.SendGump( + new NoticeGump( + 1060637, + 30720, + $"Freeze operation completed successfully.

{totalFrozen} item{(totalFrozen != 1 ? "s were" : " was")} frozen.

You must restart your client and update it's data files to see the changes.", + 0xFFC000, + 320, + 240 + ) + ); + } + + [Usage("Unfreeze")] + [Description("Makes a targeted area of static items dynamic.")] + public static void Unfreeze_OnCommand(CommandEventArgs e) + { + var from = e.Mobile; + BoundingBoxPicker.Begin(from, (map, start, end) => UnfreezeBox_Callback(from, map, start, end)); + } + + [Usage("UnfreezeMap")] + [Description("Makes every static item in your map dynamic.")] + public static void UnfreezeMap_OnCommand(CommandEventArgs e) + { + var map = e.Mobile.Map; + + if (map != null && map != Map.Internal) + SendWarning( + e.Mobile, + "You are about to unfreeze all items in {0}.", + BaseUnfreezeWarning, + map, + NullP3D, + NullP3D, + UnfreezeWarning_Callback + ); + } + + [Usage("UnfreezeWorld")] + [Description("Makes every static item on all maps dynamic.")] + public static void UnfreezeWorld_OnCommand(CommandEventArgs e) + { + SendWarning( + e.Mobile, + "You are about to unfreeze every item on every map.", + BaseUnfreezeWarning, + null, + NullP3D, + NullP3D, + UnfreezeWarning_Callback + ); + } + + private static void UnfreezeBox_Callback(Mobile from, Map map, Point3D start, Point3D end) + { + SendWarning( + from, + "You are about to unfreeze a section of items.", + BaseUnfreezeWarning, + map, + start, + end, + UnfreezeWarning_Callback + ); + } + + private static void UnfreezeWarning_Callback(Mobile from, bool okay, StateInfo si) + { + if (!okay) + return; + + Unfreeze(from, si.m_Map, si.m_Start, si.m_End); + } + + private static void DoUnfreeze(Map map, Point2D start, Point2D end, ref bool badDataFile, ref int totalUnfrozen) + { + start = map.Bound(start); + end = map.Bound(end); + + var xStartBlock = start.X >> 3; + var yStartBlock = start.Y >> 3; + var xEndBlock = end.X >> 3; + var yEndBlock = end.Y >> 3; + + int xTileStart = start.X, yTileStart = start.Y; + int xTileWidth = end.X - start.X + 1, yTileHeight = end.Y - start.Y + 1; + + var matrix = map.Tiles; + + using var idxStream = OpenWrite(matrix.IndexStream); + using var mulStream = OpenWrite(matrix.DataStream); + if (idxStream == null || mulStream == null) + { + badDataFile = true; + return; + } + + var idxReader = new BinaryReader(idxStream); + + var idxWriter = new BinaryWriter(idxStream); + var mulWriter = new BinaryWriter(mulStream); + + for (var x = xStartBlock; x <= xEndBlock; ++x) + for (var y = yStartBlock; y <= yEndBlock; ++y) + { + var oldTiles = ReadStaticBlock( + idxReader, + mulStream, + x, + y, + matrix.BlockWidth, + matrix.BlockHeight, + out var oldTileCount + ); + + if (oldTileCount < 0) + continue; + + var newTileCount = 0; + var newTiles = new StaticTile[oldTileCount]; + + int baseX = (x << 3) - xTileStart, baseY = (y << 3) - yTileStart; + + for (var i = 0; i < oldTileCount; ++i) + { + var oldTile = oldTiles[i]; + + var px = baseX + oldTile.X; + var py = baseY + oldTile.Y; + + if (px < 0 || px >= xTileWidth || py < 0 || py >= yTileHeight) + { + newTiles[newTileCount++] = oldTile; + } + else + { + ++totalUnfrozen; + + Item item = new Static(oldTile.ID); + + item.Hue = oldTile.Hue; + + item.MoveToWorld(new Point3D(px + xTileStart, py + yTileStart, oldTile.Z), map); + } + } + + var mulPos = -1; + var length = -1; + var extra = 0; + + if (newTileCount > 0) + { + mulWriter.Seek(0, SeekOrigin.End); + + mulPos = (int)mulWriter.BaseStream.Position; + length = newTileCount * 7; + extra = 1; + + for (var i = 0; i < newTileCount; ++i) + { + var toWrite = newTiles[i]; + + mulWriter.Write((ushort)toWrite.ID); + mulWriter.Write((byte)toWrite.X); + mulWriter.Write((byte)toWrite.Y); + mulWriter.Write((sbyte)toWrite.Z); + mulWriter.Write((short)toWrite.Hue); + } + + mulWriter.Flush(); + } + + var idxPos = (x * matrix.BlockHeight + y) * 12; + + idxWriter.Seek(idxPos, SeekOrigin.Begin); + idxWriter.Write(mulPos); + idxWriter.Write(length); + idxWriter.Write(extra); + + idxWriter.Flush(); + + matrix.SetStaticBlock(x, y, null); + } + } + + public static void DoUnfreeze(Map map, ref bool badDataFile, ref int totalUnfrozen) + { + DoUnfreeze(map, Point2D.Zero, new Point2D(map.Width - 1, map.Height - 1), ref badDataFile, ref totalUnfrozen); + } + + public static void Unfreeze(Mobile from, Map map, Point3D start, Point3D end) + { + var totalUnfrozen = 0; + var badDataFile = false; + + if (map == null) + { + CommandLogging.WriteLine( + from, + "{0} {1} invoking unfreeze for every item in every map", + from.AccessLevel, + CommandLogging.Format(from) + ); + + DoUnfreeze(Map.Felucca, ref badDataFile, ref totalUnfrozen); + DoUnfreeze(Map.Trammel, ref badDataFile, ref totalUnfrozen); + DoUnfreeze(Map.Ilshenar, ref badDataFile, ref totalUnfrozen); + DoUnfreeze(Map.Malas, ref badDataFile, ref totalUnfrozen); + DoUnfreeze(Map.Tokuno, ref badDataFile, ref totalUnfrozen); + } + else if (start == NullP3D && end == NullP3D) + { + CommandLogging.WriteLine( + from, + "{0} {1} invoking unfreeze for every item in {2}", + from.AccessLevel, + CommandLogging.Format(from), + map + ); + + DoUnfreeze(map, ref badDataFile, ref totalUnfrozen); + } + else + { + CommandLogging.WriteLine( + from, + "{0} {1} invoking unfreeze from {2} to {3} in {4}", + from.AccessLevel, + CommandLogging.Format(from), + new Point2D(start), + new Point2D(end), + map + ); + + DoUnfreeze(map, new Point2D(start), new Point2D(end), ref badDataFile, ref totalUnfrozen); + } + + if (totalUnfrozen == 0 && badDataFile) + from.SendGump( + new NoticeGump( + 1060637, + 30720, + "Output data files could not be opened and the unfreeze operation has been aborted.

This probably means your server and client are using the same data files. Instructions on how to resolve this can be found in the first warning window.", + 0xFFC000, + 320, + 240 + ) + ); + else + from.SendGump( + new NoticeGump( + 1060637, + 30720, + $"Unfreeze operation completed successfully.

{totalUnfrozen} item{(totalUnfrozen != 1 ? "s were" : " was")} unfrozen.

You must restart your client and update it's data files to see the changes.", + 0xFFC000, + 320, + 240 + ) + ); + } + + private static FileStream OpenWrite(FileStream orig) + { + if (orig == null) + return null; + + try + { + return new FileStream(orig.Name, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite); + } + catch + { + return null; + } + } + + private static StaticTile[] ReadStaticBlock( + BinaryReader idxReader, FileStream mulStream, int x, int y, int width, + int height, out int count + ) + { + try + { + if (x < 0 || x >= width || y < 0 || y >= height) + { + count = -1; + return m_TileBuffer; + } + + idxReader.BaseStream.Seek((x * height + y) * 12, SeekOrigin.Begin); + + var lookup = idxReader.ReadInt32(); + var length = idxReader.ReadInt32(); + + if (lookup < 0 || length <= 0) + { + count = 0; + } + else + { + count = length / 7; + + mulStream.Seek(lookup, SeekOrigin.Begin); + + if (m_TileBuffer.Length < count) + m_TileBuffer = new StaticTile[count]; + + var staTiles = m_TileBuffer; + + if (m_Buffer == null || length > m_Buffer.Length) + m_Buffer = new byte[length]; + + mulStream.Read(m_Buffer, 0, length); + + var index = 0; + + for (var i = 0; i < count; ++i) + staTiles[i] + .Set( + (ushort)(m_Buffer[index++] | (m_Buffer[index++] << 8)), + m_Buffer[index++], + m_Buffer[index++], + (sbyte)m_Buffer[index++], + (short)(m_Buffer[index++] | (m_Buffer[index++] << 8)) + ); + } + } + catch + { + count = -1; + } + + return m_TileBuffer; + } + + private class DeltaState + { + public readonly List m_List; + public readonly int m_X; + public readonly int m_Y; + + public DeltaState(Point2D p) + { + m_X = p.X; + m_Y = p.Y; + m_List = new List(); + } + } + + public class StateInfo + { + public Map m_Map; + public Point3D m_Start, m_End; + + public StateInfo(Map map, Point3D start, Point3D end) + { + m_Map = map; + m_Start = start; + m_End = end; + } + } + } +} diff --git a/Projects/UOContent/Commands/VisibilityList.cs b/Projects/UOContent/Commands/VisibilityList.cs index 6f83ffb7d..2b7e27bc2 100644 --- a/Projects/UOContent/Commands/VisibilityList.cs +++ b/Projects/UOContent/Commands/VisibilityList.cs @@ -1,141 +1,142 @@ -using System.Collections.Generic; -using Server.Mobiles; -using Server.Network; -using Server.Targeting; - -namespace Server.Commands -{ - public static class VisibilityList - { - public static void Initialize() - { - EventSink.Login += OnLogin; - - CommandSystem.Register("Vis", AccessLevel.Counselor, Vis_OnCommand); - CommandSystem.Register("VisList", AccessLevel.Counselor, VisList_OnCommand); - CommandSystem.Register("VisClear", AccessLevel.Counselor, VisClear_OnCommand); - } - - public static void OnLogin(Mobile m) - { - (m as PlayerMobile)?.VisibilityList.Clear(); - } - - [Usage("Vis")] - [Description( - "Adds or removes a targeted player from your visibility list. Anyone on your visibility list will be able to see you at all times, even when you're hidden.")] - public static void Vis_OnCommand(CommandEventArgs e) - { - if (e.Mobile is PlayerMobile) - { - e.Mobile.Target = new VisTarget(); - e.Mobile.SendMessage("Select person to add or remove from your visibility list."); - } - } - - [Usage("VisList")] - [Description("Shows the names of everyone in your visibility list.")] - public static void VisList_OnCommand(CommandEventArgs e) - { - if (e.Mobile is PlayerMobile pm) - { - List list = pm.VisibilityList; - - if (list.Count > 0) - { - pm.SendMessage("You are visible to {0} mobile{1}:", list.Count, list.Count == 1 ? "" : "s"); - - for (int i = 0; i < list.Count; ++i) - pm.SendMessage("#{0}: {1}", i + 1, list[i].Name); - } - else - { - pm.SendMessage("Your visibility list is empty."); - } - } - } - - [Usage("VisClear")] - [Description("Removes everyone from your visibility list.")] - public static void VisClear_OnCommand(CommandEventArgs e) - { - if (e.Mobile is PlayerMobile pm) - { - List list = new List(pm.VisibilityList); - - pm.VisibilityList.Clear(); - pm.SendMessage("Your visibility list has been cleared."); - - for (int i = 0; i < list.Count; ++i) - { - Mobile m = list[i]; - - if (!m.CanSee(pm) && Utility.InUpdateRange(m, pm)) - m.Send(pm.RemovePacket); - } - } - } - - private class VisTarget : Target - { - public VisTarget() : base(-1, false, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (from is PlayerMobile pm && targeted is Mobile targ) - { - if (targ.AccessLevel <= pm.AccessLevel) - { - List list = pm.VisibilityList; - - if (list.Contains(targ)) - { - list.Remove(targ); - pm.SendMessage("{0} has been removed from your visibility list.", targ.Name); - } - else - { - list.Add(targ); - pm.SendMessage("{0} has been added to your visibility list.", targ.Name); - } - - if (Utility.InUpdateRange(targ, from)) - { - NetState ns = targ.NetState; - - if (ns != null) - { - if (targ.CanSee(pm)) - { - ns.Send(MobileIncoming.Create(ns, targ, pm)); - - if (ObjectPropertyList.Enabled) - { - ns.Send(pm.OPLPacket); - - foreach (Item item in pm.Items) - ns.Send(item.OPLPacket); - } - } - else - { - ns.Send(pm.RemovePacket); - } - } - } - } - else - { - pm.SendMessage("They can already see you!"); - } - } - else - { - from.SendMessage("Add only mobiles to your visibility list."); - } - } - } - } -} +using System.Collections.Generic; +using Server.Mobiles; +using Server.Network; +using Server.Targeting; + +namespace Server.Commands +{ + public static class VisibilityList + { + public static void Initialize() + { + EventSink.Login += OnLogin; + + CommandSystem.Register("Vis", AccessLevel.Counselor, Vis_OnCommand); + CommandSystem.Register("VisList", AccessLevel.Counselor, VisList_OnCommand); + CommandSystem.Register("VisClear", AccessLevel.Counselor, VisClear_OnCommand); + } + + public static void OnLogin(Mobile m) + { + (m as PlayerMobile)?.VisibilityList.Clear(); + } + + [Usage("Vis")] + [Description( + "Adds or removes a targeted player from your visibility list. Anyone on your visibility list will be able to see you at all times, even when you're hidden." + )] + public static void Vis_OnCommand(CommandEventArgs e) + { + if (e.Mobile is PlayerMobile) + { + e.Mobile.Target = new VisTarget(); + e.Mobile.SendMessage("Select person to add or remove from your visibility list."); + } + } + + [Usage("VisList")] + [Description("Shows the names of everyone in your visibility list.")] + public static void VisList_OnCommand(CommandEventArgs e) + { + if (e.Mobile is PlayerMobile pm) + { + var list = pm.VisibilityList; + + if (list.Count > 0) + { + pm.SendMessage("You are visible to {0} mobile{1}:", list.Count, list.Count == 1 ? "" : "s"); + + for (var i = 0; i < list.Count; ++i) + pm.SendMessage("#{0}: {1}", i + 1, list[i].Name); + } + else + { + pm.SendMessage("Your visibility list is empty."); + } + } + } + + [Usage("VisClear")] + [Description("Removes everyone from your visibility list.")] + public static void VisClear_OnCommand(CommandEventArgs e) + { + if (e.Mobile is PlayerMobile pm) + { + var list = new List(pm.VisibilityList); + + pm.VisibilityList.Clear(); + pm.SendMessage("Your visibility list has been cleared."); + + for (var i = 0; i < list.Count; ++i) + { + var m = list[i]; + + if (!m.CanSee(pm) && Utility.InUpdateRange(m, pm)) + m.Send(pm.RemovePacket); + } + } + } + + private class VisTarget : Target + { + public VisTarget() : base(-1, false, TargetFlags.None) + { + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (from is PlayerMobile pm && targeted is Mobile targ) + { + if (targ.AccessLevel <= pm.AccessLevel) + { + var list = pm.VisibilityList; + + if (list.Contains(targ)) + { + list.Remove(targ); + pm.SendMessage("{0} has been removed from your visibility list.", targ.Name); + } + else + { + list.Add(targ); + pm.SendMessage("{0} has been added to your visibility list.", targ.Name); + } + + if (Utility.InUpdateRange(targ, from)) + { + var ns = targ.NetState; + + if (ns != null) + { + if (targ.CanSee(pm)) + { + ns.Send(MobileIncoming.Create(ns, targ, pm)); + + if (ObjectPropertyList.Enabled) + { + ns.Send(pm.OPLPacket); + + foreach (var item in pm.Items) + ns.Send(item.OPLPacket); + } + } + else + { + ns.Send(pm.RemovePacket); + } + } + } + } + else + { + pm.SendMessage("They can already see you!"); + } + } + else + { + from.SendMessage("Add only mobiles to your visibility list."); + } + } + } + } +} diff --git a/Projects/UOContent/Commands/Wipe.cs b/Projects/UOContent/Commands/Wipe.cs index 6eb0179e7..62dc2bf58 100644 --- a/Projects/UOContent/Commands/Wipe.cs +++ b/Projects/UOContent/Commands/Wipe.cs @@ -1,94 +1,102 @@ -using System; -using System.Collections.Generic; -using Server.Items; -using Server.Multis; - -namespace Server.Commands -{ - public class Wipe - { - [Flags] - public enum WipeType - { - Items = 0x01, - Mobiles = 0x02, - Multis = 0x04, - All = Items | Mobiles | Multis - } - - public static void Initialize() - { - CommandSystem.Register("Wipe", AccessLevel.GameMaster, WipeAll_OnCommand); - CommandSystem.Register("WipeItems", AccessLevel.GameMaster, WipeItems_OnCommand); - CommandSystem.Register("WipeNPCs", AccessLevel.GameMaster, WipeNPCs_OnCommand); - CommandSystem.Register("WipeMultis", AccessLevel.GameMaster, WipeMultis_OnCommand); - } - - [Usage("Wipe")] - [Description("Wipes all items and npcs in a targeted bounding box.")] - private static void WipeAll_OnCommand(CommandEventArgs e) - { - BeginWipe(e.Mobile, WipeType.Items | WipeType.Mobiles); - } - - [Usage("WipeItems")] - [Description("Wipes all items in a targeted bounding box.")] - private static void WipeItems_OnCommand(CommandEventArgs e) - { - BeginWipe(e.Mobile, WipeType.Items); - } - - [Usage("WipeNPCs")] - [Description("Wipes all npcs in a targeted bounding box.")] - private static void WipeNPCs_OnCommand(CommandEventArgs e) - { - BeginWipe(e.Mobile, WipeType.Mobiles); - } - - [Usage("WipeMultis")] - [Description("Wipes all multis in a targeted bounding box.")] - private static void WipeMultis_OnCommand(CommandEventArgs e) - { - BeginWipe(e.Mobile, WipeType.Multis); - } - - public static void BeginWipe(Mobile from, WipeType type) - { - BoundingBoxPicker.Begin(from, (map, start, end) => DoWipe(from, map, start, end, type)); - } - - public static void DoWipe(Mobile from, Map map, Point3D start, Point3D end, WipeType type) - { - CommandLogging.WriteLine(from, "{0} {1} wiping from {2} to {3} in {5} ({4})", from.AccessLevel, - CommandLogging.Format(from), start, end, type, map); - - bool mobiles = (type & WipeType.Mobiles) != 0; - bool multis = (type & WipeType.Multis) != 0; - bool items = (type & WipeType.Items) != 0; - - List toDelete = new List(); - - Rectangle2D rect = new Rectangle2D(start.X, start.Y, end.X - start.X + 1, end.Y - start.Y + 1); - - IPooledEnumerable eable; - - if ((!items && !multis) || !mobiles) - return; - - eable = map.GetObjectsInBounds(rect); - - foreach (IEntity obj in eable) - if (items && obj is Item && !(obj is BaseMulti || obj is HouseSign)) - toDelete.Add(obj); - else if (multis && obj is BaseMulti) - toDelete.Add(obj); - else if (obj is Mobile mobile && !mobile.Player) - toDelete.Add(mobile); - - eable.Free(); - - for (int i = 0; i < toDelete.Count; ++i) - toDelete[i].Delete(); - } - } -} \ No newline at end of file +using System; +using System.Collections.Generic; +using Server.Items; +using Server.Multis; + +namespace Server.Commands +{ + public class Wipe + { + [Flags] + public enum WipeType + { + Items = 0x01, + Mobiles = 0x02, + Multis = 0x04, + All = Items | Mobiles | Multis + } + + public static void Initialize() + { + CommandSystem.Register("Wipe", AccessLevel.GameMaster, WipeAll_OnCommand); + CommandSystem.Register("WipeItems", AccessLevel.GameMaster, WipeItems_OnCommand); + CommandSystem.Register("WipeNPCs", AccessLevel.GameMaster, WipeNPCs_OnCommand); + CommandSystem.Register("WipeMultis", AccessLevel.GameMaster, WipeMultis_OnCommand); + } + + [Usage("Wipe")] + [Description("Wipes all items and npcs in a targeted bounding box.")] + private static void WipeAll_OnCommand(CommandEventArgs e) + { + BeginWipe(e.Mobile, WipeType.Items | WipeType.Mobiles); + } + + [Usage("WipeItems")] + [Description("Wipes all items in a targeted bounding box.")] + private static void WipeItems_OnCommand(CommandEventArgs e) + { + BeginWipe(e.Mobile, WipeType.Items); + } + + [Usage("WipeNPCs")] + [Description("Wipes all npcs in a targeted bounding box.")] + private static void WipeNPCs_OnCommand(CommandEventArgs e) + { + BeginWipe(e.Mobile, WipeType.Mobiles); + } + + [Usage("WipeMultis")] + [Description("Wipes all multis in a targeted bounding box.")] + private static void WipeMultis_OnCommand(CommandEventArgs e) + { + BeginWipe(e.Mobile, WipeType.Multis); + } + + public static void BeginWipe(Mobile from, WipeType type) + { + BoundingBoxPicker.Begin(from, (map, start, end) => DoWipe(from, map, start, end, type)); + } + + public static void DoWipe(Mobile from, Map map, Point3D start, Point3D end, WipeType type) + { + CommandLogging.WriteLine( + from, + "{0} {1} wiping from {2} to {3} in {5} ({4})", + from.AccessLevel, + CommandLogging.Format(from), + start, + end, + type, + map + ); + + var mobiles = (type & WipeType.Mobiles) != 0; + var multis = (type & WipeType.Multis) != 0; + var items = (type & WipeType.Items) != 0; + + var toDelete = new List(); + + var rect = new Rectangle2D(start.X, start.Y, end.X - start.X + 1, end.Y - start.Y + 1); + + IPooledEnumerable eable; + + if (!items && !multis || !mobiles) + return; + + eable = map.GetObjectsInBounds(rect); + + foreach (var obj in eable) + if (items && obj is Item && !(obj is BaseMulti || obj is HouseSign)) + toDelete.Add(obj); + else if (multis && obj is BaseMulti) + toDelete.Add(obj); + else if (obj is Mobile mobile && !mobile.Player) + toDelete.Add(mobile); + + eable.Free(); + + for (var i = 0; i < toDelete.Count; ++i) + toDelete[i].Delete(); + } + } +} diff --git a/Projects/UOContent/Configuration/EmailConfiguration.cs b/Projects/UOContent/Configuration/EmailConfiguration.cs index 842bee43d..bf17729ea 100644 --- a/Projects/UOContent/Configuration/EmailConfiguration.cs +++ b/Projects/UOContent/Configuration/EmailConfiguration.cs @@ -1,96 +1,88 @@ -/************************************************************************* - * ModernUO * - * Copyright (C) 2019-2020 - ModernUO Development Team * - * Email: hi@modernuo.com * - * File: EmailConfiguration.cs * - * Created: 2019/10/04 - Updated: 2020/05/02 * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 3 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see . * - *************************************************************************/ - -using System.IO; -using System.Text.Json.Serialization; -using MimeKit; -using Server.Json; - -namespace Server.Configurations -{ - public static class EmailConfiguration - { - public static readonly bool EmailEnabled; - public static readonly MailboxAddress FromAddress; - public static readonly MailboxAddress CrashAddress; - public static readonly MailboxAddress SpeechLogPageAddress; - public static readonly string EmailServer; - public static readonly int EmailPort; - public static readonly string EmailServerUsername; - public static readonly string EmailServerPassword; - public static readonly int EmailSendRetryCount = 5; // seconds - public static readonly int EmailSendRetryDelay = 2; // seconds - - static EmailConfiguration() - { - string filePath = Path.Join(Core.BaseDirectory, "Configuration/email-settings.json"); - Settings settings = JsonConfig.Deserialize(filePath) ?? new Settings(); - - if (settings.emailServer == null || settings.fromAddress == null) - { - JsonConfig.Serialize(filePath, settings); - return; - } - - EmailEnabled = true; - FromAddress = new MailboxAddress(settings.fromName, settings.fromAddress); - CrashAddress = new MailboxAddress(settings.crashName, settings.crashAddress); - SpeechLogPageAddress = new MailboxAddress(settings.speechLogPageName, settings.speechLogPageAddress); - EmailServer = settings.emailServer; - EmailPort = settings.emailPort; - EmailServerUsername = settings.emailUsername; - EmailServerPassword = settings.emailPassword; - } - - internal class Settings - { - [JsonPropertyName("fromAddress")] - internal string fromAddress { get; set; } - - [JsonPropertyName("fromName")] - internal string fromName { get; set; } - - [JsonPropertyName("crashAddress")] - internal string crashAddress { get; set; } - - [JsonPropertyName("crashName")] - internal string crashName { get; set; } - - [JsonPropertyName("speechLogPageAddress")] - internal string speechLogPageAddress { get; set; } - - [JsonPropertyName("speechLogPageName")] - internal string speechLogPageName { get; set; } - - [JsonPropertyName("emailServer")] - internal string emailServer { get; set; } - - [JsonPropertyName("emailPort")] - internal int emailPort { get; set; } - - [JsonPropertyName("emailUsername")] - internal string emailUsername { get; set; } - - [JsonPropertyName("emailPassword")] - internal string emailPassword { get; set; } - } - } -} +/************************************************************************* + * ModernUO * + * Copyright (C) 2019-2020 - ModernUO Development Team * + * Email: hi@modernuo.com * + * File: EmailConfiguration.cs * + * Created: 2019/10/04 - Updated: 2020/05/02 * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *************************************************************************/ + +using System.IO; +using System.Text.Json.Serialization; +using MimeKit; +using Server.Json; + +namespace Server.Configurations +{ + public static class EmailConfiguration + { + public static readonly bool EmailEnabled; + public static readonly MailboxAddress FromAddress; + public static readonly MailboxAddress CrashAddress; + public static readonly MailboxAddress SpeechLogPageAddress; + public static readonly string EmailServer; + public static readonly int EmailPort; + public static readonly string EmailServerUsername; + public static readonly string EmailServerPassword; + public static readonly int EmailSendRetryCount = 5; // seconds + public static readonly int EmailSendRetryDelay = 2; // seconds + + static EmailConfiguration() + { + var filePath = Path.Join(Core.BaseDirectory, "Configuration/email-settings.json"); + var settings = JsonConfig.Deserialize(filePath) ?? new Settings(); + + if (settings.emailServer == null || settings.fromAddress == null) + { + JsonConfig.Serialize(filePath, settings); + return; + } + + EmailEnabled = true; + FromAddress = new MailboxAddress(settings.fromName, settings.fromAddress); + CrashAddress = new MailboxAddress(settings.crashName, settings.crashAddress); + SpeechLogPageAddress = new MailboxAddress(settings.speechLogPageName, settings.speechLogPageAddress); + EmailServer = settings.emailServer; + EmailPort = settings.emailPort; + EmailServerUsername = settings.emailUsername; + EmailServerPassword = settings.emailPassword; + } + + internal class Settings + { + [JsonPropertyName("fromAddress")] internal string fromAddress { get; set; } + + [JsonPropertyName("fromName")] internal string fromName { get; set; } + + [JsonPropertyName("crashAddress")] internal string crashAddress { get; set; } + + [JsonPropertyName("crashName")] internal string crashName { get; set; } + + [JsonPropertyName("speechLogPageAddress")] + internal string speechLogPageAddress { get; set; } + + [JsonPropertyName("speechLogPageName")] + internal string speechLogPageName { get; set; } + + [JsonPropertyName("emailServer")] internal string emailServer { get; set; } + + [JsonPropertyName("emailPort")] internal int emailPort { get; set; } + + [JsonPropertyName("emailUsername")] internal string emailUsername { get; set; } + + [JsonPropertyName("emailPassword")] internal string emailPassword { get; set; } + } + } +} diff --git a/Projects/UOContent/Configuration/ExpansionConfiguration.cs b/Projects/UOContent/Configuration/ExpansionConfiguration.cs index 33d224b41..dcc52cd98 100644 --- a/Projects/UOContent/Configuration/ExpansionConfiguration.cs +++ b/Projects/UOContent/Configuration/ExpansionConfiguration.cs @@ -1,38 +1,39 @@ -using Server.Accounting; -using Server.Items; -using Server.Network; - -namespace Server -{ - public static class ExpansionConfiguration - { - public static void Configure() - { - Core.Expansion = ServerConfiguration.GetOrUpdateSetting("currentExpansion", Expansion.TOL); - - AccountGold.Enabled = ServerConfiguration.GetSetting("accountGold.enable", Core.TOL); - AccountGold.ConvertOnBank = ServerConfiguration.GetSetting("accountGold.convertOnBank", true); - AccountGold.ConvertOnTrade = ServerConfiguration.GetSetting("accountGold.convertOnTrade", false); - VirtualCheck.UseEditGump = ServerConfiguration.GetSetting("virtualChecks.useEditGump", true); - - Mobile.InsuranceEnabled = ServerConfiguration.GetSetting("insurance.enable", Core.AOS); - ObjectPropertyList.Enabled = ServerConfiguration.GetSetting("opl.enable", Core.AOS); - bool visibleDamage = ServerConfiguration.GetSetting("visibleDamage", Core.AOS); - Mobile.VisibleDamageType = visibleDamage ? VisibleDamageType.Related : VisibleDamageType.None; - Mobile.GuildClickMessage = ServerConfiguration.GetSetting("guildClickMessage", !Core.AOS); - Mobile.AsciiClickMessage = ServerConfiguration.GetSetting("asciiClickMessage", !Core.AOS); - - Mobile.ActionDelay = ServerConfiguration.GetSetting("actionDelay", Core.AOS ? 1000 : 500); - - if (Core.AOS) - { - AOS.DisableStatInfluences(); - - if (ObjectPropertyList.Enabled) - PacketHandlers.SingleClickProps = true; // single click for everything is overridden to check object property list - - Mobile.AOSStatusHandler = AOS.GetStatus; - } - } - } -} +using Server.Accounting; +using Server.Items; +using Server.Network; + +namespace Server +{ + public static class ExpansionConfiguration + { + public static void Configure() + { + Core.Expansion = ServerConfiguration.GetOrUpdateSetting("currentExpansion", Expansion.TOL); + + AccountGold.Enabled = ServerConfiguration.GetSetting("accountGold.enable", Core.TOL); + AccountGold.ConvertOnBank = ServerConfiguration.GetSetting("accountGold.convertOnBank", true); + AccountGold.ConvertOnTrade = ServerConfiguration.GetSetting("accountGold.convertOnTrade", false); + VirtualCheck.UseEditGump = ServerConfiguration.GetSetting("virtualChecks.useEditGump", true); + + Mobile.InsuranceEnabled = ServerConfiguration.GetSetting("insurance.enable", Core.AOS); + ObjectPropertyList.Enabled = ServerConfiguration.GetSetting("opl.enable", Core.AOS); + var visibleDamage = ServerConfiguration.GetSetting("visibleDamage", Core.AOS); + Mobile.VisibleDamageType = visibleDamage ? VisibleDamageType.Related : VisibleDamageType.None; + Mobile.GuildClickMessage = ServerConfiguration.GetSetting("guildClickMessage", !Core.AOS); + Mobile.AsciiClickMessage = ServerConfiguration.GetSetting("asciiClickMessage", !Core.AOS); + + Mobile.ActionDelay = ServerConfiguration.GetSetting("actionDelay", Core.AOS ? 1000 : 500); + + if (Core.AOS) + { + AOS.DisableStatInfluences(); + + if (ObjectPropertyList.Enabled) + PacketHandlers.SingleClickProps = + true; // single click for everything is overridden to check object property list + + Mobile.AOSStatusHandler = AOS.GetStatus; + } + } + } +} diff --git a/Projects/UOContent/Context Menus/AddToParty.cs b/Projects/UOContent/Context Menus/AddToParty.cs index c5a1c3535..9b59f5914 100644 --- a/Projects/UOContent/Context Menus/AddToParty.cs +++ b/Projects/UOContent/Context Menus/AddToParty.cs @@ -1,37 +1,37 @@ -using Server.Engines.PartySystem; - -namespace Server.ContextMenus -{ - public class AddToPartyEntry : ContextMenuEntry - { - private readonly Mobile m_From; - private readonly Mobile m_Target; - - public AddToPartyEntry(Mobile from, Mobile target) : base(0197, 12) - { - m_From = from; - m_Target = target; - } - - public override void OnClick() - { - Party p = Party.Get(m_From); - Party mp = Party.Get(m_Target); - - if (m_From == m_Target) - m_From.SendLocalizedMessage(1005439); // You cannot add yourself to a party. - else if (p != null && p.Leader != m_From) - m_From.SendLocalizedMessage(1005453); // You may only add members to the party if you are the leader. - else if (p != null && p.Members.Count + p.Candidates.Count >= Party.Capacity) - m_From.SendLocalizedMessage(1008095); // You may only have 10 in your party (this includes candidates). - else if (!m_Target.Player) - m_From.SendLocalizedMessage(1005444); // The creature ignores your offer. - else if (mp != null && mp == p) - m_From.SendLocalizedMessage(1005440); // This person is already in your party! - else if (mp != null) - m_From.SendLocalizedMessage(1005441); // This person is already in a party! - else - Party.Invite(m_From, m_Target); - } - } -} \ No newline at end of file +using Server.Engines.PartySystem; + +namespace Server.ContextMenus +{ + public class AddToPartyEntry : ContextMenuEntry + { + private readonly Mobile m_From; + private readonly Mobile m_Target; + + public AddToPartyEntry(Mobile from, Mobile target) : base(0197, 12) + { + m_From = from; + m_Target = target; + } + + public override void OnClick() + { + var p = Party.Get(m_From); + var mp = Party.Get(m_Target); + + if (m_From == m_Target) + m_From.SendLocalizedMessage(1005439); // You cannot add yourself to a party. + else if (p != null && p.Leader != m_From) + m_From.SendLocalizedMessage(1005453); // You may only add members to the party if you are the leader. + else if (p != null && p.Members.Count + p.Candidates.Count >= Party.Capacity) + m_From.SendLocalizedMessage(1008095); // You may only have 10 in your party (this includes candidates). + else if (!m_Target.Player) + m_From.SendLocalizedMessage(1005444); // The creature ignores your offer. + else if (mp != null && mp == p) + m_From.SendLocalizedMessage(1005440); // This person is already in your party! + else if (mp != null) + m_From.SendLocalizedMessage(1005441); // This person is already in a party! + else + Party.Invite(m_From, m_Target); + } + } +} diff --git a/Projects/UOContent/Context Menus/AddToSpellbookEntry.cs b/Projects/UOContent/Context Menus/AddToSpellbookEntry.cs index 415ebda76..8c4f0dcbc 100644 --- a/Projects/UOContent/Context Menus/AddToSpellbookEntry.cs +++ b/Projects/UOContent/Context Menus/AddToSpellbookEntry.cs @@ -1,57 +1,57 @@ -using Server.Items; -using Server.Network; -using Server.Targeting; - -namespace Server.ContextMenus -{ - public class AddToSpellbookEntry : ContextMenuEntry - { - public AddToSpellbookEntry() : base(6144, 3) - { - } - - public override void OnClick() - { - if (Owner.From.CheckAlive() && Owner.Target is SpellScroll scroll) - Owner.From.Target = new InternalTarget(scroll); - } - - private class InternalTarget : Target - { - private readonly SpellScroll m_Scroll; - - public InternalTarget(SpellScroll scroll) : base(3, false, TargetFlags.None) => m_Scroll = scroll; - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is Spellbook book) - if (from.CheckAlive() && !m_Scroll.Deleted && m_Scroll.Movable && m_Scroll.Amount >= 1 && - m_Scroll.CheckItemUse(from)) - { - SpellbookType type = Spellbook.GetTypeForSpell(m_Scroll.SpellID); - - if (type != book.SpellbookType) - { - } - else if (book.HasSpell(m_Scroll.SpellID)) - { - from.SendLocalizedMessage(500179); // That spell is already present in that spellbook. - } - else - { - int val = m_Scroll.SpellID - book.BookOffset; - - if (val >= 0 && val < book.BookCount) - { - book.Content |= (ulong)1 << val; - - m_Scroll.Consume(); - - from.Send(new PlaySound(0x249, book.GetWorldLocation())); - } - } - } - } - } - } -} \ No newline at end of file +using Server.Items; +using Server.Network; +using Server.Targeting; + +namespace Server.ContextMenus +{ + public class AddToSpellbookEntry : ContextMenuEntry + { + public AddToSpellbookEntry() : base(6144, 3) + { + } + + public override void OnClick() + { + if (Owner.From.CheckAlive() && Owner.Target is SpellScroll scroll) + Owner.From.Target = new InternalTarget(scroll); + } + + private class InternalTarget : Target + { + private readonly SpellScroll m_Scroll; + + public InternalTarget(SpellScroll scroll) : base(3, false, TargetFlags.None) => m_Scroll = scroll; + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted is Spellbook book) + if (from.CheckAlive() && !m_Scroll.Deleted && m_Scroll.Movable && m_Scroll.Amount >= 1 && + m_Scroll.CheckItemUse(from)) + { + var type = Spellbook.GetTypeForSpell(m_Scroll.SpellID); + + if (type != book.SpellbookType) + { + } + else if (book.HasSpell(m_Scroll.SpellID)) + { + from.SendLocalizedMessage(500179); // That spell is already present in that spellbook. + } + else + { + var val = m_Scroll.SpellID - book.BookOffset; + + if (val >= 0 && val < book.BookCount) + { + book.Content |= (ulong)1 << val; + + m_Scroll.Consume(); + + from.Send(new PlaySound(0x249, book.GetWorldLocation())); + } + } + } + } + } + } +} diff --git a/Projects/UOContent/Context Menus/EatEntry.cs b/Projects/UOContent/Context Menus/EatEntry.cs index ed9fe1165..453face57 100644 --- a/Projects/UOContent/Context Menus/EatEntry.cs +++ b/Projects/UOContent/Context Menus/EatEntry.cs @@ -1,24 +1,24 @@ -using Server.Items; - -namespace Server.ContextMenus -{ - public class EatEntry : ContextMenuEntry - { - private readonly Food m_Food; - private readonly Mobile m_From; - - public EatEntry(Mobile from, Food food) : base(6135, 1) - { - m_From = from; - m_Food = food; - } - - public override void OnClick() - { - if (m_Food?.Deleted != false || !m_Food.Movable || !m_From.CheckAlive() || !m_Food.CheckItemUse(m_From)) - return; - - m_Food.Eat(m_From); - } - } -} +using Server.Items; + +namespace Server.ContextMenus +{ + public class EatEntry : ContextMenuEntry + { + private readonly Food m_Food; + private readonly Mobile m_From; + + public EatEntry(Mobile from, Food food) : base(6135, 1) + { + m_From = from; + m_Food = food; + } + + public override void OnClick() + { + if (m_Food?.Deleted != false || !m_Food.Movable || !m_From.CheckAlive() || !m_Food.CheckItemUse(m_From)) + return; + + m_Food.Eat(m_From); + } + } +} diff --git a/Projects/UOContent/Context Menus/EjectPlayer.cs b/Projects/UOContent/Context Menus/EjectPlayer.cs index 343d2ea75..91f0f3e9c 100644 --- a/Projects/UOContent/Context Menus/EjectPlayer.cs +++ b/Projects/UOContent/Context Menus/EjectPlayer.cs @@ -1,26 +1,26 @@ -using Server.Multis; - -namespace Server.ContextMenus -{ - public class EjectPlayerEntry : ContextMenuEntry - { - private readonly Mobile m_From; - private readonly Mobile m_Target; - private readonly BaseHouse m_TargetHouse; - - public EjectPlayerEntry(Mobile from, Mobile target) : base(6206, 12) - { - m_From = from; - m_Target = target; - m_TargetHouse = BaseHouse.FindHouseAt(m_Target); - } - - public override void OnClick() - { - if (!m_From.Alive || m_TargetHouse.Deleted || !m_TargetHouse.IsFriend(m_From)) - return; - - m_TargetHouse.Kick(m_From, m_Target); - } - } -} +using Server.Multis; + +namespace Server.ContextMenus +{ + public class EjectPlayerEntry : ContextMenuEntry + { + private readonly Mobile m_From; + private readonly Mobile m_Target; + private readonly BaseHouse m_TargetHouse; + + public EjectPlayerEntry(Mobile from, Mobile target) : base(6206, 12) + { + m_From = from; + m_Target = target; + m_TargetHouse = BaseHouse.FindHouseAt(m_Target); + } + + public override void OnClick() + { + if (!m_From.Alive || m_TargetHouse.Deleted || !m_TargetHouse.IsFriend(m_From)) + return; + + m_TargetHouse.Kick(m_From, m_Target); + } + } +} diff --git a/Projects/UOContent/Context Menus/OpenBankEntry.cs b/Projects/UOContent/Context Menus/OpenBankEntry.cs index a7b19b7ed..35036cbbb 100644 --- a/Projects/UOContent/Context Menus/OpenBankEntry.cs +++ b/Projects/UOContent/Context Menus/OpenBankEntry.cs @@ -1,20 +1,20 @@ -namespace Server.ContextMenus -{ - public class OpenBankEntry : ContextMenuEntry - { - private readonly Mobile m_Banker; - - public OpenBankEntry(Mobile from, Mobile banker) : base(6105, 12) => m_Banker = banker; - - public override void OnClick() - { - if (!Owner.From.CheckAlive()) - return; - - if (Owner.From.Criminal) - m_Banker.Say(500378); // Thou art a criminal and cannot access thy bank box. - else - Owner.From.BankBox.Open(); - } - } -} \ No newline at end of file +namespace Server.ContextMenus +{ + public class OpenBankEntry : ContextMenuEntry + { + private readonly Mobile m_Banker; + + public OpenBankEntry(Mobile from, Mobile banker) : base(6105, 12) => m_Banker = banker; + + public override void OnClick() + { + if (!Owner.From.CheckAlive()) + return; + + if (Owner.From.Criminal) + m_Banker.Say(500378); // Thou art a criminal and cannot access thy bank box. + else + Owner.From.BankBox.Open(); + } + } +} diff --git a/Projects/UOContent/Context Menus/TeachEntry.cs b/Projects/UOContent/Context Menus/TeachEntry.cs index e44d8ff84..5eeed3aad 100644 --- a/Projects/UOContent/Context Menus/TeachEntry.cs +++ b/Projects/UOContent/Context Menus/TeachEntry.cs @@ -1,30 +1,30 @@ -using Server.Mobiles; -using Server.Network; - -namespace Server.ContextMenus -{ - public class TeachEntry : ContextMenuEntry - { - private readonly Mobile m_From; - private readonly BaseCreature m_Mobile; - private readonly SkillName m_Skill; - - public TeachEntry(SkillName skill, BaseCreature m, Mobile from, bool enabled) : base(6000 + (int)skill) - { - m_Skill = skill; - m_Mobile = m; - m_From = from; - - if (!enabled) - Flags |= CMEFlags.Disabled; - } - - public override void OnClick() - { - if (!m_From.CheckAlive()) - return; - - m_Mobile.Teach(m_Skill, m_From, 0, false); - } - } -} \ No newline at end of file +using Server.Mobiles; +using Server.Network; + +namespace Server.ContextMenus +{ + public class TeachEntry : ContextMenuEntry + { + private readonly Mobile m_From; + private readonly BaseCreature m_Mobile; + private readonly SkillName m_Skill; + + public TeachEntry(SkillName skill, BaseCreature m, Mobile from, bool enabled) : base(6000 + (int)skill) + { + m_Skill = skill; + m_Mobile = m; + m_From = from; + + if (!enabled) + Flags |= CMEFlags.Disabled; + } + + public override void OnClick() + { + if (!m_From.CheckAlive()) + return; + + m_Mobile.Teach(m_Skill, m_From, 0, false); + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/BODTarget.cs b/Projects/UOContent/Engines/BulkOrders/BODTarget.cs index 997c9e070..774560158 100644 --- a/Projects/UOContent/Engines/BulkOrders/BODTarget.cs +++ b/Projects/UOContent/Engines/BulkOrders/BODTarget.cs @@ -1,25 +1,25 @@ -using Server.Targeting; - -namespace Server.Engines.BulkOrders -{ - public class BODTarget : Target - { - private readonly BaseBOD m_Deed; - - public BODTarget(BaseBOD deed) : base(18, false, TargetFlags.None) => m_Deed = deed; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Deed.Deleted || !m_Deed.IsChildOf(from.Backpack)) - return; - - if (!(targeted is Item item && item.IsChildOf(from.Backpack))) - { - from.SendLocalizedMessage(1045158); // You must have the item in your backpack to target it. - return; - } - - m_Deed.EndCombine(from, item); - } - } -} +using Server.Targeting; + +namespace Server.Engines.BulkOrders +{ + public class BODTarget : Target + { + private readonly BaseBOD m_Deed; + + public BODTarget(BaseBOD deed) : base(18, false, TargetFlags.None) => m_Deed = deed; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Deed.Deleted || !m_Deed.IsChildOf(from.Backpack)) + return; + + if (!(targeted is Item item && item.IsChildOf(from.Backpack))) + { + from.SendLocalizedMessage(1045158); // You must have the item in your backpack to target it. + return; + } + + m_Deed.EndCombine(from, item); + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/BaseBOD.cs b/Projects/UOContent/Engines/BulkOrders/BaseBOD.cs index dea6a13d9..0a22ac616 100644 --- a/Projects/UOContent/Engines/BulkOrders/BaseBOD.cs +++ b/Projects/UOContent/Engines/BulkOrders/BaseBOD.cs @@ -1,153 +1,167 @@ -using System.Collections.Generic; - -namespace Server.Engines.BulkOrders -{ - public abstract class BaseBOD : Item - { - private int m_AmountMax; - private bool m_RequireExceptional; - private BulkMaterialType m_Material; - - public static BulkMaterialType GetRandomMaterial(BulkMaterialType start, double[] chances) - { - double random = Utility.RandomDouble(); - - for (int i = 0; i < chances.Length; ++i) - { - if (random < chances[i]) - return i == 0 ? BulkMaterialType.None : start + (i - 1); - - random -= chances[i]; - } - - return BulkMaterialType.None; - } - - public BaseBOD(int hue, int amountMax, bool requireExeptional, BulkMaterialType material) : this() - { - Hue = hue; - AmountMax = amountMax; - RequireExceptional = requireExeptional; - Material = material; - } - - public BaseBOD() : base(Core.AOS ? 0x2258 : 0x14EF) - { - Weight = 1.0; - LootType = LootType.Blessed; - } - - public BaseBOD(Serial serial) : base(serial) - { - } - - public abstract bool Complete { get; } - - [CommandProperty(AccessLevel.GameMaster)] - public sealed override int Hue { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int AmountMax - { - get => m_AmountMax; - set { m_AmountMax = value; InvalidateProperties(); } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool RequireExceptional - { - get => m_RequireExceptional; - set { m_RequireExceptional = value; InvalidateProperties(); } - } - - [CommandProperty(AccessLevel.GameMaster)] - public BulkMaterialType Material - { - get => m_Material; - set { m_Material = value; InvalidateProperties(); } - } - - public abstract RewardGroup GetRewardGroup(); - - public abstract int ComputeGold(); - public abstract int ComputeFame(); - public abstract void EndCombine(Mobile from, Item item); - - public virtual void GetRewards(out Item reward, out int gold, out int fame) - { - gold = ComputeGold(); - fame = ComputeFame(); - - List rewards = ComputeRewards(false); - - reward = rewards.RandomElement()?.Construct(); - } - - public virtual List ComputeRewards(bool full) - { - RewardGroup rewardGroup = GetRewardGroup(); - - List list = new List(); - - if (full) - { - for (int i = 0; i < rewardGroup?.Items.Length; ++i) - { - RewardItem reward = rewardGroup.Items[i]; - - if (reward != null) - list.Add(reward); - } - } - else - { - RewardItem reward = rewardGroup.AcquireItem(); - - if (reward != null) - list.Add(reward); - } - - return list; - } - - public virtual void BeginCombine(Mobile from) - { - if (Complete) - from.SendLocalizedMessage(1045166); // The maximum amount of requested items have already been combined to this deed. - else - from.Target = new BODTarget(this); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_AmountMax); - writer.Write(m_RequireExceptional); - writer.Write((int)m_Material); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 0: - { - m_AmountMax = reader.ReadInt(); - m_RequireExceptional = reader.ReadBool(); - m_Material = (BulkMaterialType)reader.ReadInt(); - break; - } - } - - if (Parent == null && Map == Map.Internal && Location == Point3D.Zero) - Delete(); - } - } -} +using System.Collections.Generic; + +namespace Server.Engines.BulkOrders +{ + public abstract class BaseBOD : Item + { + private int m_AmountMax; + private BulkMaterialType m_Material; + private bool m_RequireExceptional; + + public BaseBOD(int hue, int amountMax, bool requireExeptional, BulkMaterialType material) : this() + { + Hue = hue; + AmountMax = amountMax; + RequireExceptional = requireExeptional; + Material = material; + } + + public BaseBOD() : base(Core.AOS ? 0x2258 : 0x14EF) + { + Weight = 1.0; + LootType = LootType.Blessed; + } + + public BaseBOD(Serial serial) : base(serial) + { + } + + public abstract bool Complete { get; } + + [CommandProperty(AccessLevel.GameMaster)] + public sealed override int Hue { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int AmountMax + { + get => m_AmountMax; + set + { + m_AmountMax = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool RequireExceptional + { + get => m_RequireExceptional; + set + { + m_RequireExceptional = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public BulkMaterialType Material + { + get => m_Material; + set + { + m_Material = value; + InvalidateProperties(); + } + } + + public static BulkMaterialType GetRandomMaterial(BulkMaterialType start, double[] chances) + { + var random = Utility.RandomDouble(); + + for (var i = 0; i < chances.Length; ++i) + { + if (random < chances[i]) + return i == 0 ? BulkMaterialType.None : start + (i - 1); + + random -= chances[i]; + } + + return BulkMaterialType.None; + } + + public abstract RewardGroup GetRewardGroup(); + + public abstract int ComputeGold(); + public abstract int ComputeFame(); + public abstract void EndCombine(Mobile from, Item item); + + public virtual void GetRewards(out Item reward, out int gold, out int fame) + { + gold = ComputeGold(); + fame = ComputeFame(); + + var rewards = ComputeRewards(false); + + reward = rewards.RandomElement()?.Construct(); + } + + public virtual List ComputeRewards(bool full) + { + var rewardGroup = GetRewardGroup(); + + var list = new List(); + + if (full) + { + for (var i = 0; i < rewardGroup?.Items.Length; ++i) + { + var reward = rewardGroup.Items[i]; + + if (reward != null) + list.Add(reward); + } + } + else + { + var reward = rewardGroup.AcquireItem(); + + if (reward != null) + list.Add(reward); + } + + return list; + } + + public virtual void BeginCombine(Mobile from) + { + if (Complete) + from.SendLocalizedMessage( + 1045166 + ); // The maximum amount of requested items have already been combined to this deed. + else + from.Target = new BODTarget(this); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_AmountMax); + writer.Write(m_RequireExceptional); + writer.Write((int)m_Material); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 0: + { + m_AmountMax = reader.ReadInt(); + m_RequireExceptional = reader.ReadBool(); + m_Material = (BulkMaterialType)reader.ReadInt(); + break; + } + } + + if (Parent == null && Map == Map.Internal && Location == Point3D.Zero) + Delete(); + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/Books/BOBFilter.cs b/Projects/UOContent/Engines/BulkOrders/Books/BOBFilter.cs index f7aa9da41..dc211ac67 100644 --- a/Projects/UOContent/Engines/BulkOrders/Books/BOBFilter.cs +++ b/Projects/UOContent/Engines/BulkOrders/Books/BOBFilter.cs @@ -1,62 +1,62 @@ -namespace Server.Engines.BulkOrders -{ - public class BOBFilter - { - public BOBFilter() - { - } - - public BOBFilter(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 1: - { - Type = reader.ReadEncodedInt(); - Quality = reader.ReadEncodedInt(); - Material = reader.ReadEncodedInt(); - Quantity = reader.ReadEncodedInt(); - - break; - } - } - } - - public bool IsDefault => Type == 0 && Quality == 0 && Material == 0 && Quantity == 0; - - public int Type { get; set; } - - public int Quality { get; set; } - - public int Material { get; set; } - - public int Quantity { get; set; } - - public void Clear() - { - Type = 0; - Quality = 0; - Material = 0; - Quantity = 0; - } - - public void Serialize(IGenericWriter writer) - { - if (IsDefault) - { - writer.WriteEncodedInt(0); // version - } - else - { - writer.WriteEncodedInt(1); // version - - writer.WriteEncodedInt(Type); - writer.WriteEncodedInt(Quality); - writer.WriteEncodedInt(Material); - writer.WriteEncodedInt(Quantity); - } - } - } -} \ No newline at end of file +namespace Server.Engines.BulkOrders +{ + public class BOBFilter + { + public BOBFilter() + { + } + + public BOBFilter(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 1: + { + Type = reader.ReadEncodedInt(); + Quality = reader.ReadEncodedInt(); + Material = reader.ReadEncodedInt(); + Quantity = reader.ReadEncodedInt(); + + break; + } + } + } + + public bool IsDefault => Type == 0 && Quality == 0 && Material == 0 && Quantity == 0; + + public int Type { get; set; } + + public int Quality { get; set; } + + public int Material { get; set; } + + public int Quantity { get; set; } + + public void Clear() + { + Type = 0; + Quality = 0; + Material = 0; + Quantity = 0; + } + + public void Serialize(IGenericWriter writer) + { + if (IsDefault) + { + writer.WriteEncodedInt(0); // version + } + else + { + writer.WriteEncodedInt(1); // version + + writer.WriteEncodedInt(Type); + writer.WriteEncodedInt(Quality); + writer.WriteEncodedInt(Material); + writer.WriteEncodedInt(Quantity); + } + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/Books/BOBFilterGump.cs b/Projects/UOContent/Engines/BulkOrders/Books/BOBFilterGump.cs index ed5c063b2..d7281cdd0 100644 --- a/Projects/UOContent/Engines/BulkOrders/Books/BOBFilterGump.cs +++ b/Projects/UOContent/Engines/BulkOrders/Books/BOBFilterGump.cs @@ -1,218 +1,231 @@ -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.BulkOrders -{ - public class BOBFilterGump : Gump - { - private const int LabelColor = 0x7FFF; - - private static readonly int[,] m_MaterialFilters = - { - { 1044067, 1 }, // Blacksmithy - { 1062226, 3 }, // Iron - { 1018332, 4 }, // Dull Copper - { 1018333, 5 }, // Shadow Iron - { 1018334, 6 }, // Copper - { 1018335, 7 }, // Bronze - { 0, 0 }, // --Blank-- - { 1018336, 8 }, // Golden - { 1018337, 9 }, // Agapite - { 1018338, 10 }, // Verite - { 1018339, 11 }, // Valorite - { 0, 0 }, // --Blank-- - { 1044094, 2 }, // Tailoring - { 1044286, 12 }, // Cloth - { 1062235, 13 }, // Leather - { 1062236, 14 }, // Spined - { 1062237, 15 }, // Horned - { 1062238, 16 } // Barbed - }; - - private static readonly int[,] m_TypeFilters = - { - { 1062229, 0 }, // All - { 1062224, 1 }, // Small - { 1062225, 2 } // Large - }; - - private static readonly int[,] m_QualityFilters = - { - { 1062229, 0 }, // All - { 1011542, 1 }, // Normal - { 1060636, 2 } // Exceptional - }; - - private static readonly int[,] m_AmountFilters = - { - { 1062229, 0 }, // All - { 1049706, 1 }, // 10 - { 1016007, 2 }, // 15 - { 1062239, 3 } // 20 - }; - - private static readonly int[][,] m_Filters = - { - m_TypeFilters, - m_QualityFilters, - m_MaterialFilters, - m_AmountFilters - }; - - private static readonly int[] m_XOffsets_Type = { 0, 75, 170 }; - private static readonly int[] m_XOffsets_Quality = { 0, 75, 170 }; - private static readonly int[] m_XOffsets_Amount = { 0, 75, 180, 275 }; - private static readonly int[] m_XOffsets_Material = { 0, 105, 210, 305, 390, 485 }; - - private static readonly int[] m_XWidths_Small = { 50, 50, 70, 50 }; - private static readonly int[] m_XWidths_Large = { 80, 50, 50, 50, 50, 50 }; - private readonly BulkOrderBook m_Book; - private readonly PlayerMobile m_From; - - public BOBFilterGump(PlayerMobile from, BulkOrderBook book) : base(12, 24) - { - from.CloseGump(); - from.CloseGump(); - - m_From = from; - m_Book = book; - - BOBFilter f = from.UseOwnFilter ? from.BOBFilter : book.Filter; - - AddPage(0); - - AddBackground(10, 10, 600, 439, 5054); - - AddImageTiled(18, 20, 583, 420, 2624); - AddAlphaRegion(18, 20, 583, 420); - - AddImage(5, 5, 10460); - AddImage(585, 5, 10460); - AddImage(5, 424, 10460); - AddImage(585, 424, 10460); - - AddHtmlLocalized(270, 32, 200, 32, 1062223, LabelColor); // Filter Preference - - AddHtmlLocalized(26, 64, 120, 32, 1062228, LabelColor); // Bulk Order Type - AddFilterList(25, 96, m_XOffsets_Type, 40, m_TypeFilters, m_XWidths_Small, f.Type, 0); - - AddHtmlLocalized(320, 64, 50, 32, 1062215, LabelColor); // Quality - AddFilterList(320, 96, m_XOffsets_Quality, 40, m_QualityFilters, m_XWidths_Small, f.Quality, 1); - - AddHtmlLocalized(26, 160, 120, 32, 1062232, LabelColor); // Material Type - AddFilterList(25, 192, m_XOffsets_Material, 40, m_MaterialFilters, m_XWidths_Large, f.Material, 2); - - AddHtmlLocalized(26, 320, 120, 32, 1062217, LabelColor); // Amount - AddFilterList(25, 352, m_XOffsets_Amount, 40, m_AmountFilters, m_XWidths_Small, f.Quantity, 3); - - AddHtmlLocalized(75, 416, 120, 32, 1062477, from.UseOwnFilter ? LabelColor : 16927); // Set Book Filter - AddButton(40, 416, 4005, 4007, 1); - - AddHtmlLocalized(235, 416, 120, 32, 1062478, from.UseOwnFilter ? 16927 : LabelColor); // Set Your Filter - AddButton(200, 416, 4005, 4007, 2); - - AddHtmlLocalized(405, 416, 120, 32, 1062231, LabelColor); // Clear Filter - AddButton(370, 416, 4005, 4007, 3); - - AddHtmlLocalized(540, 416, 50, 32, 1011046, LabelColor); // APPLY - AddButton(505, 416, 4017, 4018, 0); - } - - private void AddFilterList(int x, int y, int[] xOffsets, int yOffset, int[,] filters, int[] xWidths, int filterValue, - int filterIndex) - { - for (int i = 0; i < filters.GetLength(0); ++i) - { - int number = filters[i, 0]; - - if (number == 0) - continue; - - bool isSelected = filters[i, 1] == filterValue || - (i % xOffsets.Length == 0 && filterValue == 0); - - AddHtmlLocalized(x + 35 + xOffsets[i % xOffsets.Length], y + i / xOffsets.Length * yOffset, - xWidths[i % xOffsets.Length], 32, number, isSelected ? 16927 : LabelColor); - AddButton(x + xOffsets[i % xOffsets.Length], y + i / xOffsets.Length * yOffset, 4005, 4007, - 4 + filterIndex + i * 4); - } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - BOBFilter f = m_From.UseOwnFilter ? m_From.BOBFilter : m_Book.Filter; - - int index = info.ButtonID; - - switch (index) - { - case 0: // Apply - { - m_From.SendGump(new BOBGump(m_From, m_Book)); - - break; - } - case 1: // Set Book Filter - { - m_From.UseOwnFilter = false; - m_From.SendGump(new BOBFilterGump(m_From, m_Book)); - - break; - } - case 2: // Set Your Filter - { - m_From.UseOwnFilter = true; - m_From.SendGump(new BOBFilterGump(m_From, m_Book)); - - break; - } - case 3: // Clear Filter - { - f.Clear(); - m_From.SendGump(new BOBFilterGump(m_From, m_Book)); - - break; - } - default: - { - index -= 4; - - int type = index % 4; - index /= 4; - - if (type >= 0 && type < m_Filters.Length) - { - int[,] filters = m_Filters[type]; - - if (index >= 0 && index < filters.GetLength(0)) - { - if (filters[index, 0] == 0) - break; - - switch (type) - { - case 0: - f.Type = filters[index, 1]; - break; - case 1: - f.Quality = filters[index, 1]; - break; - case 2: - f.Material = filters[index, 1]; - break; - case 3: - f.Quantity = filters[index, 1]; - break; - } - - m_From.SendGump(new BOBFilterGump(m_From, m_Book)); - } - } - - break; - } - } - } - } -} +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.BulkOrders +{ + public class BOBFilterGump : Gump + { + private const int LabelColor = 0x7FFF; + + private static readonly int[,] m_MaterialFilters = + { + { 1044067, 1 }, // Blacksmithy + { 1062226, 3 }, // Iron + { 1018332, 4 }, // Dull Copper + { 1018333, 5 }, // Shadow Iron + { 1018334, 6 }, // Copper + { 1018335, 7 }, // Bronze + { 0, 0 }, // --Blank-- + { 1018336, 8 }, // Golden + { 1018337, 9 }, // Agapite + { 1018338, 10 }, // Verite + { 1018339, 11 }, // Valorite + { 0, 0 }, // --Blank-- + { 1044094, 2 }, // Tailoring + { 1044286, 12 }, // Cloth + { 1062235, 13 }, // Leather + { 1062236, 14 }, // Spined + { 1062237, 15 }, // Horned + { 1062238, 16 } // Barbed + }; + + private static readonly int[,] m_TypeFilters = + { + { 1062229, 0 }, // All + { 1062224, 1 }, // Small + { 1062225, 2 } // Large + }; + + private static readonly int[,] m_QualityFilters = + { + { 1062229, 0 }, // All + { 1011542, 1 }, // Normal + { 1060636, 2 } // Exceptional + }; + + private static readonly int[,] m_AmountFilters = + { + { 1062229, 0 }, // All + { 1049706, 1 }, // 10 + { 1016007, 2 }, // 15 + { 1062239, 3 } // 20 + }; + + private static readonly int[][,] m_Filters = + { + m_TypeFilters, + m_QualityFilters, + m_MaterialFilters, + m_AmountFilters + }; + + private static readonly int[] m_XOffsets_Type = { 0, 75, 170 }; + private static readonly int[] m_XOffsets_Quality = { 0, 75, 170 }; + private static readonly int[] m_XOffsets_Amount = { 0, 75, 180, 275 }; + private static readonly int[] m_XOffsets_Material = { 0, 105, 210, 305, 390, 485 }; + + private static readonly int[] m_XWidths_Small = { 50, 50, 70, 50 }; + private static readonly int[] m_XWidths_Large = { 80, 50, 50, 50, 50, 50 }; + private readonly BulkOrderBook m_Book; + private readonly PlayerMobile m_From; + + public BOBFilterGump(PlayerMobile from, BulkOrderBook book) : base(12, 24) + { + from.CloseGump(); + from.CloseGump(); + + m_From = from; + m_Book = book; + + var f = from.UseOwnFilter ? from.BOBFilter : book.Filter; + + AddPage(0); + + AddBackground(10, 10, 600, 439, 5054); + + AddImageTiled(18, 20, 583, 420, 2624); + AddAlphaRegion(18, 20, 583, 420); + + AddImage(5, 5, 10460); + AddImage(585, 5, 10460); + AddImage(5, 424, 10460); + AddImage(585, 424, 10460); + + AddHtmlLocalized(270, 32, 200, 32, 1062223, LabelColor); // Filter Preference + + AddHtmlLocalized(26, 64, 120, 32, 1062228, LabelColor); // Bulk Order Type + AddFilterList(25, 96, m_XOffsets_Type, 40, m_TypeFilters, m_XWidths_Small, f.Type, 0); + + AddHtmlLocalized(320, 64, 50, 32, 1062215, LabelColor); // Quality + AddFilterList(320, 96, m_XOffsets_Quality, 40, m_QualityFilters, m_XWidths_Small, f.Quality, 1); + + AddHtmlLocalized(26, 160, 120, 32, 1062232, LabelColor); // Material Type + AddFilterList(25, 192, m_XOffsets_Material, 40, m_MaterialFilters, m_XWidths_Large, f.Material, 2); + + AddHtmlLocalized(26, 320, 120, 32, 1062217, LabelColor); // Amount + AddFilterList(25, 352, m_XOffsets_Amount, 40, m_AmountFilters, m_XWidths_Small, f.Quantity, 3); + + AddHtmlLocalized(75, 416, 120, 32, 1062477, from.UseOwnFilter ? LabelColor : 16927); // Set Book Filter + AddButton(40, 416, 4005, 4007, 1); + + AddHtmlLocalized(235, 416, 120, 32, 1062478, from.UseOwnFilter ? 16927 : LabelColor); // Set Your Filter + AddButton(200, 416, 4005, 4007, 2); + + AddHtmlLocalized(405, 416, 120, 32, 1062231, LabelColor); // Clear Filter + AddButton(370, 416, 4005, 4007, 3); + + AddHtmlLocalized(540, 416, 50, 32, 1011046, LabelColor); // APPLY + AddButton(505, 416, 4017, 4018, 0); + } + + private void AddFilterList( + int x, int y, int[] xOffsets, int yOffset, int[,] filters, int[] xWidths, int filterValue, + int filterIndex + ) + { + for (var i = 0; i < filters.GetLength(0); ++i) + { + var number = filters[i, 0]; + + if (number == 0) + continue; + + var isSelected = filters[i, 1] == filterValue || + i % xOffsets.Length == 0 && filterValue == 0; + + AddHtmlLocalized( + x + 35 + xOffsets[i % xOffsets.Length], + y + i / xOffsets.Length * yOffset, + xWidths[i % xOffsets.Length], + 32, + number, + isSelected ? 16927 : LabelColor + ); + AddButton( + x + xOffsets[i % xOffsets.Length], + y + i / xOffsets.Length * yOffset, + 4005, + 4007, + 4 + filterIndex + i * 4 + ); + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var f = m_From.UseOwnFilter ? m_From.BOBFilter : m_Book.Filter; + + var index = info.ButtonID; + + switch (index) + { + case 0: // Apply + { + m_From.SendGump(new BOBGump(m_From, m_Book)); + + break; + } + case 1: // Set Book Filter + { + m_From.UseOwnFilter = false; + m_From.SendGump(new BOBFilterGump(m_From, m_Book)); + + break; + } + case 2: // Set Your Filter + { + m_From.UseOwnFilter = true; + m_From.SendGump(new BOBFilterGump(m_From, m_Book)); + + break; + } + case 3: // Clear Filter + { + f.Clear(); + m_From.SendGump(new BOBFilterGump(m_From, m_Book)); + + break; + } + default: + { + index -= 4; + + var type = index % 4; + index /= 4; + + if (type >= 0 && type < m_Filters.Length) + { + var filters = m_Filters[type]; + + if (index >= 0 && index < filters.GetLength(0)) + { + if (filters[index, 0] == 0) + break; + + switch (type) + { + case 0: + f.Type = filters[index, 1]; + break; + case 1: + f.Quality = filters[index, 1]; + break; + case 2: + f.Material = filters[index, 1]; + break; + case 3: + f.Quantity = filters[index, 1]; + break; + } + + m_From.SendGump(new BOBFilterGump(m_From, m_Book)); + } + } + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/Books/BOBGump.cs b/Projects/UOContent/Engines/BulkOrders/Books/BOBGump.cs index 85037be65..efd324ba8 100644 --- a/Projects/UOContent/Engines/BulkOrders/Books/BOBGump.cs +++ b/Projects/UOContent/Engines/BulkOrders/Books/BOBGump.cs @@ -1,637 +1,658 @@ -using System; -using System.Collections.Generic; -using Server.Gumps; -using Server.Items; -using Server.Mobiles; -using Server.Network; -using Server.Prompts; - -namespace Server.Engines.BulkOrders -{ - public class BOBGump : Gump - { - private const int LabelColor = 0x7FFF; - private readonly BulkOrderBook m_Book; - private readonly PlayerMobile m_From; - private readonly List m_List; - - private int m_Page; - - public BOBGump(PlayerMobile from, BulkOrderBook book, int page = 0, List list = null) : base(12, 24) - { - from.CloseGump(); - from.CloseGump(); - - m_From = from; - m_Book = book; - m_Page = page; - - if (list == null) - { - list = new List(book.Entries.Count); - - for (int i = 0; i < book.Entries.Count; ++i) - { - IBOBEntry entry = book.Entries[i]; - - if (CheckFilter(entry)) - list.Add(entry); - } - } - - m_List = list; - - int index = GetIndexForPage(page); - int count = GetCountForIndex(index); - - int tableIndex = 0; - - PlayerVendor pv = book.RootParent as PlayerVendor; - - bool canDrop = book.IsChildOf(from.Backpack); - bool canBuy = pv != null; - bool canPrice = canDrop || canBuy; - - if (canBuy) - { - VendorItem vi = pv.GetVendorItem(book); - - canBuy = vi?.IsForSale == false; - } - - int width = 600; - - if (!canPrice) - width = 516; - - X = (624 - width) / 2; - - AddPage(0); - - AddBackground(10, 10, width, 439, 5054); - AddImageTiled(18, 20, width - 17, 420, 2624); - - if (canPrice) - { - AddImageTiled(573, 64, 24, 352, 200); - AddImageTiled(493, 64, 78, 352, 1416); - } - - if (canDrop) - AddImageTiled(24, 64, 32, 352, 1416); - - AddImageTiled(58, 64, 36, 352, 200); - AddImageTiled(96, 64, 133, 352, 1416); - AddImageTiled(231, 64, 80, 352, 200); - AddImageTiled(313, 64, 100, 352, 1416); - AddImageTiled(415, 64, 76, 352, 200); - - for (int i = index; i < index + count && i >= 0 && i < list.Count; ++i) - { - IBOBEntry entry = list[i]; - - if (!CheckFilter(entry)) - continue; - - AddImageTiled(24, 94 + tableIndex * 32, canPrice ? 573 : 489, 2, 2624); - tableIndex += entry is BOBLargeEntry largeEntry ? largeEntry.Entries.Length : 1; - } - - AddAlphaRegion(18, 20, width - 17, 420); - AddImage(5, 5, 10460); - AddImage(width - 15, 5, 10460); - AddImage(5, 424, 10460); - AddImage(width - 15, 424, 10460); - - AddHtmlLocalized(canPrice ? 266 : 224, 32, 200, 32, 1062220, LabelColor); // Bulk Order Book - AddHtmlLocalized(63, 64, 200, 32, 1062213, LabelColor); // Type - AddHtmlLocalized(147, 64, 200, 32, 1062214, LabelColor); // Item - AddHtmlLocalized(246, 64, 200, 32, 1062215, LabelColor); // Quality - AddHtmlLocalized(336, 64, 200, 32, 1062216, LabelColor); // Material - AddHtmlLocalized(429, 64, 200, 32, 1062217, LabelColor); // Amount - - AddButton(35, 32, 4005, 4007, 1); - AddHtmlLocalized(70, 32, 200, 32, 1062476, LabelColor); // Set Filter - - BOBFilter f = from.UseOwnFilter ? from.BOBFilter : book.Filter; - - if (f.IsDefault) - AddHtmlLocalized(canPrice ? 470 : 386, 32, 120, 32, 1062475, 16927); // Using No Filter - else if (from.UseOwnFilter) - AddHtmlLocalized(canPrice ? 470 : 386, 32, 120, 32, 1062451, 16927); // Using Your Filter - else - AddHtmlLocalized(canPrice ? 470 : 386, 32, 120, 32, 1062230, 16927); // Using Book Filter - - AddButton(375, 416, 4017, 4018, 0); - AddHtmlLocalized(410, 416, 120, 20, 1011441, LabelColor); // EXIT - - if (canDrop) - AddHtmlLocalized(26, 64, 50, 32, 1062212, LabelColor); // Drop - - if (canPrice) - { - AddHtmlLocalized(516, 64, 200, 32, 1062218, LabelColor); // Price - - if (canBuy) - { - AddHtmlLocalized(576, 64, 200, 32, 1062219, LabelColor); // Buy - } - else - { - AddHtmlLocalized(576, 64, 200, 32, 1062227, LabelColor); // Set - - AddButton(450, 416, 4005, 4007, 4); - AddHtml(485, 416, 120, 20, "Price all"); - } - } - - tableIndex = 0; - - if (page > 0) - { - AddButton(75, 416, 4014, 4016, 2); - AddHtmlLocalized(110, 416, 150, 20, 1011067, LabelColor); // Previous page - } - - if (GetIndexForPage(page + 1) < list.Count) - { - AddButton(225, 416, 4005, 4007, 3); - AddHtmlLocalized(260, 416, 150, 20, 1011066, LabelColor); // Next page - } - - for (int i = index; i < index + count && i >= 0 && i < list.Count; ++i) - { - IBOBEntry entry = list[i]; - - if (!CheckFilter(entry)) - continue; - - if (entry is BOBLargeEntry largeEntry) - { - int y = 96 + tableIndex * 32; - - if (canDrop) - AddButton(35, y + 2, 5602, 5606, 5 + i * 2); - - if (canDrop || (canBuy && entry.Price > 0)) - { - AddButton(579, y + 2, 2117, 2118, 6 + i * 2); - AddLabel(495, y, 1152, entry.Price.ToString()); - } - - AddHtmlLocalized(61, y, 50, 32, 1062225, LabelColor); // Large - - for (int j = 0; j < largeEntry.Entries.Length; ++j) - { - BOBLargeSubEntry sub = largeEntry.Entries[j]; - - AddHtmlLocalized(103, y, 130, 32, sub.Number, LabelColor); - - if (entry.RequireExceptional) - AddHtmlLocalized(235, y, 80, 20, 1060636, LabelColor); // exceptional - else - AddHtmlLocalized(235, y, 80, 20, 1011542, LabelColor); // normal - - TextDefinition name = GetMaterialName(entry.Material, entry.DeedType, sub.ItemType); - - if (name.Number > 0) - AddHtmlLocalized(316, y, 100, 20, name, LabelColor); - else - AddLabel(316, y, 1152, name); - - AddLabel(421, y, 1152, $"{sub.AmountCur} / {entry.AmountMax}"); - - ++tableIndex; - y += 32; - } - } - else - { - BOBSmallEntry smallEntry = (BOBSmallEntry)entry; - - int y = 96 + tableIndex++ * 32; - - if (canDrop) - AddButton(35, y + 2, 5602, 5606, 5 + i * 2); - - if (canDrop || (canBuy && smallEntry.Price > 0)) - { - AddButton(579, y + 2, 2117, 2118, 6 + i * 2); - AddLabel(495, y, 1152, smallEntry.Price.ToString()); - } - - AddHtmlLocalized(61, y, 50, 32, 1062224, LabelColor); // Small - - AddHtmlLocalized(103, y, 130, 32, smallEntry.Number, LabelColor); - - if (smallEntry.RequireExceptional) - AddHtmlLocalized(235, y, 80, 20, 1060636, LabelColor); // exceptional - else - AddHtmlLocalized(235, y, 80, 20, 1011542, LabelColor); // normal - - TextDefinition name = GetMaterialName(smallEntry.Material, smallEntry.DeedType, smallEntry.ItemType); - - if (name.Number > 0) - AddHtmlLocalized(316, y, 100, 20, name, LabelColor); - else - AddLabel(316, y, 1152, name); - - AddLabel(421, y, 1152, $"{smallEntry.AmountCur} / {smallEntry.AmountMax}"); - } - } - } - - public bool CheckFilter(IBOBEntry entry) - { - if (entry is BOBLargeEntry largeEntry) - return CheckFilter(entry.Material, entry.AmountMax, true, entry.RequireExceptional, entry.DeedType, - largeEntry.Entries.Length > 0 ? largeEntry.Entries[0].ItemType : null); - - if (entry is BOBSmallEntry smallEntry) - return CheckFilter(entry.Material, entry.AmountMax, false, entry.RequireExceptional, - entry.DeedType, smallEntry.ItemType); - - return false; - } - - public bool CheckFilter(BulkMaterialType mat, int amountMax, bool isLarge, bool reqExc, BODType deedType, - Type itemType) - { - BOBFilter f = m_From.UseOwnFilter ? m_From.BOBFilter : m_Book.Filter; - - if (f.IsDefault) - return true; - - if (f.Quality == 1 && reqExc) - return false; - if (f.Quality == 2 && !reqExc) - return false; - - if (f.Quantity == 1 && amountMax != 10) - return false; - if (f.Quantity == 2 && amountMax != 15) - return false; - if (f.Quantity == 3 && amountMax != 20) - return false; - - if (f.Type == 1 && isLarge) - return false; - if (f.Type == 2 && !isLarge) - return false; - - return f.Material switch - { - 1 => deedType == BODType.Smith, - 2 => deedType == BODType.Tailor, - 3 => mat == BulkMaterialType.None && BGTClassifier.Classify(deedType, itemType) == BulkGenericType.Iron, - 4 => mat == BulkMaterialType.DullCopper, - 5 => mat == BulkMaterialType.ShadowIron, - 6 => mat == BulkMaterialType.Copper, - 7 => mat == BulkMaterialType.Bronze, - 8 => mat == BulkMaterialType.Gold, - 9 => mat == BulkMaterialType.Agapite, - 10 => mat == BulkMaterialType.Verite, - 11 => mat == BulkMaterialType.Valorite, - 12 => mat == BulkMaterialType.None && BGTClassifier.Classify(deedType, itemType) == BulkGenericType.Cloth, - 13 => mat == BulkMaterialType.None && BGTClassifier.Classify(deedType, itemType) == BulkGenericType.Leather, - 14 => mat == BulkMaterialType.Spined, - 15 => mat == BulkMaterialType.Horned, - 16 => mat == BulkMaterialType.Barbed, - _ => true - }; - } - - public int GetIndexForPage(int page) - { - int index = 0; - - while (page-- > 0) - index += GetCountForIndex(index); - - return index; - } - - public int GetCountForIndex(int index) - { - int slots = 0; - int count = 0; - - List list = m_List; - - for (int i = index; i >= 0 && i < list.Count; ++i) - { - IBOBEntry entry = list[i]; - - if (CheckFilter(entry)) - { - int add = entry is BOBLargeEntry largeEntry ? largeEntry.Entries.Length : 1; - - if (slots + add > 10) - break; - - slots += add; - } - - ++count; - } - - return count; - } - - public int GetPageForIndex(int index, int sizeDropped) - { - if (index <= 0) - return 0; - - int count = 0; - int page = 0; - int i; - - List list = m_List; - for (i = 0; i < index && i < list.Count; i++) - { - IBOBEntry entry = list[i]; - if (!CheckFilter(entry)) - continue; - - int add = entry is BOBLargeEntry largeEntry ? largeEntry.Entries.Length : 1; - count += add; - if (count > 10) - { - page++; - count = add; - } - } - - /* now we are on the page of the bod preceding the dropped one. - * next step: checking whether we have to remain where we are. - * The counter i needs to be incremented as the bod to this very moment - * has not yet been removed from m_List */ - i++; - - /* if, for instance, a big bod of size 6 has been removed, smaller bods - * might fall back into this page. Depending on their sizes, the page needs - * to be adjusted accordingly. This is done now. - */ - if (count + sizeDropped > 10) - { - while (i < list.Count && count <= 10) - { - IBOBEntry entry = list[i]; - if (CheckFilter(entry)) - count += entry is BOBLargeEntry largeEntry ? largeEntry.Entries.Length : 1; - - i++; - } - - if (count > 10) - page++; - } - - return page; - } - - public TextDefinition GetMaterialName(BulkMaterialType mat, BODType type, Type itemType) - { - switch (type) - { - case BODType.Smith: - { - switch (mat) - { - case BulkMaterialType.None: return 1062226; - case BulkMaterialType.DullCopper: return 1018332; - case BulkMaterialType.ShadowIron: return 1018333; - case BulkMaterialType.Copper: return 1018334; - case BulkMaterialType.Bronze: return 1018335; - case BulkMaterialType.Gold: return 1018336; - case BulkMaterialType.Agapite: return 1018337; - case BulkMaterialType.Verite: return 1018338; - case BulkMaterialType.Valorite: return 1018339; - } - - break; - } - case BODType.Tailor: - { - switch (mat) - { - case BulkMaterialType.None: - { - if (itemType.IsSubclassOf(typeof(BaseArmor)) || itemType.IsSubclassOf(typeof(BaseShoes))) - return 1062235; - - return 1044286; - } - case BulkMaterialType.Spined: return 1062236; - case BulkMaterialType.Horned: return 1062237; - case BulkMaterialType.Barbed: return 1062238; - } - - break; - } - } - - return "Invalid"; - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - int index = info.ButtonID; - - switch (index) - { - case 0: // EXIT - { - break; - } - case 1: // Set Filter - { - m_From.SendGump(new BOBFilterGump(m_From, m_Book)); - - break; - } - case 2: // Previous page - { - if (m_Page > 0) - m_From.SendGump(new BOBGump(m_From, m_Book, m_Page - 1, m_List)); - - return; - } - case 3: // Next page - { - if (GetIndexForPage(m_Page + 1) < m_List.Count) - m_From.SendGump(new BOBGump(m_From, m_Book, m_Page + 1, m_List)); - - break; - } - case 4: // Price all - { - if (m_Book.IsChildOf(m_From.Backpack)) - { - m_From.Prompt = new SetPricePrompt(m_Book, null, m_Page, m_List); - m_From.SendMessage("Type in a price for all deeds in the book:"); - } - - break; - } - default: - { - index -= 5; - - int type = index % 2; - index /= 2; - - if (index < 0 || index >= m_List.Count) - break; - - IBOBEntry bobEntry = m_List[index]; - - if (!m_Book.Entries.Contains(bobEntry)) - { - m_From.SendLocalizedMessage(1062382); // The deed selected is not available. - break; - } - - if (type == 0) // Drop - { - if (m_Book.IsChildOf(m_From.Backpack)) - { - Item item = bobEntry.Reconstruct(); - - Container pack = m_From.Backpack; - if (pack?.CheckHold(m_From, item, true, true, 0, - item.PileWeight + item.TotalWeight) != true) - { - m_From.SendLocalizedMessage(503204); // You do not have room in your backpack for this - m_From.SendGump(new BOBGump(m_From, m_Book, m_Page)); - } - else - { - if (m_Book.IsChildOf(m_From.Backpack)) - { - int sizeOfDroppedBod = bobEntry is BOBLargeEntry entry ? entry.Entries.Length : 1; - - m_From.AddToBackpack(item); - m_From.SendLocalizedMessage( - 1045152); // The bulk order deed has been placed in your backpack. - m_Book.Entries.Remove(bobEntry); - m_Book.InvalidateProperties(); - - if (m_Book.Entries.Count / 5 < m_Book.ItemCount) - { - m_Book.ItemCount--; - m_Book.InvalidateItems(); - } - - if (m_Book.Entries.Count > 0) - { - m_Page = GetPageForIndex(index, sizeOfDroppedBod); - m_From.SendGump(new BOBGump(m_From, m_Book, m_Page)); - } - else - { - m_From.SendLocalizedMessage(1062381); // The book is empty. - } - } - } - } - } - else // Set Price | Buy - { - if (m_Book.IsChildOf(m_From.Backpack)) - { - m_From.Prompt = new SetPricePrompt(m_Book, bobEntry, m_Page, m_List); - m_From.SendLocalizedMessage(1062383); // Type in a price for the deed: - } - else if (m_Book.RootParent is PlayerVendor pv) - { - VendorItem vi = pv.GetVendorItem(m_Book); - - if (vi?.IsForSale != false) - return; - - int sizeOfDroppedBod = bobEntry is BOBLargeEntry largeEntry ? largeEntry.Entries.Length : 1; - int price = bobEntry.Price; - - if (price == 0) - { - m_From.SendLocalizedMessage(1062382); // The deed selected is not available. - } - else - { - if (m_Book.Entries.Count > 0) - { - m_Page = GetPageForIndex(index, sizeOfDroppedBod); - m_From.SendGump(new BODBuyGump(m_From, m_Book, bobEntry, m_Page, price)); - } - else - { - m_From.SendLocalizedMessage(1062381); // The book is emptz - } - } - } - } - - break; - } - } - } - - private class SetPricePrompt : Prompt - { - private readonly BulkOrderBook m_Book; - private readonly List m_List; - private readonly IBOBEntry m_Entry; - private readonly int m_Page; - - public SetPricePrompt(BulkOrderBook book, IBOBEntry entry, int page, List list) - { - m_Book = book; - m_Entry = entry; - m_Page = page; - m_List = list; - } - - public override void OnResponse(Mobile from, string text) - { - if (m_Entry != null && !m_Book.Entries.Contains(m_Entry)) - { - from.SendLocalizedMessage(1062382); // The deed selected is not available. - return; - } - - int price = Utility.ToInt32(text); - - if (price < 0 || price > 250000000) - { - from.SendLocalizedMessage(1062390); // The price you requested is outrageous! - } - else if (m_Entry == null) - { - for (int i = 0; i < m_List.Count; ++i) - { - IBOBEntry entry = m_List[i]; - - if (!m_Book.Entries.Contains(entry)) - continue; - - entry.Price = price; - } - - from.SendMessage("Deed prices set."); - - if (from is PlayerMobile mobile) - mobile.SendGump(new BOBGump(mobile, m_Book, m_Page, m_List)); - } - else - { - m_Entry.Price = price; - from.SendLocalizedMessage(1062384); // Deed price set. - if (from is PlayerMobile mobile) - mobile.SendGump(new BOBGump(mobile, m_Book, m_Page, m_List)); - } - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Gumps; +using Server.Items; +using Server.Mobiles; +using Server.Network; +using Server.Prompts; + +namespace Server.Engines.BulkOrders +{ + public class BOBGump : Gump + { + private const int LabelColor = 0x7FFF; + private readonly BulkOrderBook m_Book; + private readonly PlayerMobile m_From; + private readonly List m_List; + + private int m_Page; + + public BOBGump(PlayerMobile from, BulkOrderBook book, int page = 0, List list = null) : base(12, 24) + { + from.CloseGump(); + from.CloseGump(); + + m_From = from; + m_Book = book; + m_Page = page; + + if (list == null) + { + list = new List(book.Entries.Count); + + for (var i = 0; i < book.Entries.Count; ++i) + { + var entry = book.Entries[i]; + + if (CheckFilter(entry)) + list.Add(entry); + } + } + + m_List = list; + + var index = GetIndexForPage(page); + var count = GetCountForIndex(index); + + var tableIndex = 0; + + var pv = book.RootParent as PlayerVendor; + + var canDrop = book.IsChildOf(from.Backpack); + var canBuy = pv != null; + var canPrice = canDrop || canBuy; + + if (canBuy) + { + var vi = pv.GetVendorItem(book); + + canBuy = vi?.IsForSale == false; + } + + var width = 600; + + if (!canPrice) + width = 516; + + X = (624 - width) / 2; + + AddPage(0); + + AddBackground(10, 10, width, 439, 5054); + AddImageTiled(18, 20, width - 17, 420, 2624); + + if (canPrice) + { + AddImageTiled(573, 64, 24, 352, 200); + AddImageTiled(493, 64, 78, 352, 1416); + } + + if (canDrop) + AddImageTiled(24, 64, 32, 352, 1416); + + AddImageTiled(58, 64, 36, 352, 200); + AddImageTiled(96, 64, 133, 352, 1416); + AddImageTiled(231, 64, 80, 352, 200); + AddImageTiled(313, 64, 100, 352, 1416); + AddImageTiled(415, 64, 76, 352, 200); + + for (var i = index; i < index + count && i >= 0 && i < list.Count; ++i) + { + var entry = list[i]; + + if (!CheckFilter(entry)) + continue; + + AddImageTiled(24, 94 + tableIndex * 32, canPrice ? 573 : 489, 2, 2624); + tableIndex += entry is BOBLargeEntry largeEntry ? largeEntry.Entries.Length : 1; + } + + AddAlphaRegion(18, 20, width - 17, 420); + AddImage(5, 5, 10460); + AddImage(width - 15, 5, 10460); + AddImage(5, 424, 10460); + AddImage(width - 15, 424, 10460); + + AddHtmlLocalized(canPrice ? 266 : 224, 32, 200, 32, 1062220, LabelColor); // Bulk Order Book + AddHtmlLocalized(63, 64, 200, 32, 1062213, LabelColor); // Type + AddHtmlLocalized(147, 64, 200, 32, 1062214, LabelColor); // Item + AddHtmlLocalized(246, 64, 200, 32, 1062215, LabelColor); // Quality + AddHtmlLocalized(336, 64, 200, 32, 1062216, LabelColor); // Material + AddHtmlLocalized(429, 64, 200, 32, 1062217, LabelColor); // Amount + + AddButton(35, 32, 4005, 4007, 1); + AddHtmlLocalized(70, 32, 200, 32, 1062476, LabelColor); // Set Filter + + var f = from.UseOwnFilter ? from.BOBFilter : book.Filter; + + if (f.IsDefault) + AddHtmlLocalized(canPrice ? 470 : 386, 32, 120, 32, 1062475, 16927); // Using No Filter + else if (from.UseOwnFilter) + AddHtmlLocalized(canPrice ? 470 : 386, 32, 120, 32, 1062451, 16927); // Using Your Filter + else + AddHtmlLocalized(canPrice ? 470 : 386, 32, 120, 32, 1062230, 16927); // Using Book Filter + + AddButton(375, 416, 4017, 4018, 0); + AddHtmlLocalized(410, 416, 120, 20, 1011441, LabelColor); // EXIT + + if (canDrop) + AddHtmlLocalized(26, 64, 50, 32, 1062212, LabelColor); // Drop + + if (canPrice) + { + AddHtmlLocalized(516, 64, 200, 32, 1062218, LabelColor); // Price + + if (canBuy) + { + AddHtmlLocalized(576, 64, 200, 32, 1062219, LabelColor); // Buy + } + else + { + AddHtmlLocalized(576, 64, 200, 32, 1062227, LabelColor); // Set + + AddButton(450, 416, 4005, 4007, 4); + AddHtml(485, 416, 120, 20, "Price all"); + } + } + + tableIndex = 0; + + if (page > 0) + { + AddButton(75, 416, 4014, 4016, 2); + AddHtmlLocalized(110, 416, 150, 20, 1011067, LabelColor); // Previous page + } + + if (GetIndexForPage(page + 1) < list.Count) + { + AddButton(225, 416, 4005, 4007, 3); + AddHtmlLocalized(260, 416, 150, 20, 1011066, LabelColor); // Next page + } + + for (var i = index; i < index + count && i >= 0 && i < list.Count; ++i) + { + var entry = list[i]; + + if (!CheckFilter(entry)) + continue; + + if (entry is BOBLargeEntry largeEntry) + { + var y = 96 + tableIndex * 32; + + if (canDrop) + AddButton(35, y + 2, 5602, 5606, 5 + i * 2); + + if (canDrop || canBuy && entry.Price > 0) + { + AddButton(579, y + 2, 2117, 2118, 6 + i * 2); + AddLabel(495, y, 1152, entry.Price.ToString()); + } + + AddHtmlLocalized(61, y, 50, 32, 1062225, LabelColor); // Large + + for (var j = 0; j < largeEntry.Entries.Length; ++j) + { + var sub = largeEntry.Entries[j]; + + AddHtmlLocalized(103, y, 130, 32, sub.Number, LabelColor); + + if (entry.RequireExceptional) + AddHtmlLocalized(235, y, 80, 20, 1060636, LabelColor); // exceptional + else + AddHtmlLocalized(235, y, 80, 20, 1011542, LabelColor); // normal + + var name = GetMaterialName(entry.Material, entry.DeedType, sub.ItemType); + + if (name.Number > 0) + AddHtmlLocalized(316, y, 100, 20, name, LabelColor); + else + AddLabel(316, y, 1152, name); + + AddLabel(421, y, 1152, $"{sub.AmountCur} / {entry.AmountMax}"); + + ++tableIndex; + y += 32; + } + } + else + { + var smallEntry = (BOBSmallEntry)entry; + + var y = 96 + tableIndex++ * 32; + + if (canDrop) + AddButton(35, y + 2, 5602, 5606, 5 + i * 2); + + if (canDrop || canBuy && smallEntry.Price > 0) + { + AddButton(579, y + 2, 2117, 2118, 6 + i * 2); + AddLabel(495, y, 1152, smallEntry.Price.ToString()); + } + + AddHtmlLocalized(61, y, 50, 32, 1062224, LabelColor); // Small + + AddHtmlLocalized(103, y, 130, 32, smallEntry.Number, LabelColor); + + if (smallEntry.RequireExceptional) + AddHtmlLocalized(235, y, 80, 20, 1060636, LabelColor); // exceptional + else + AddHtmlLocalized(235, y, 80, 20, 1011542, LabelColor); // normal + + var name = GetMaterialName(smallEntry.Material, smallEntry.DeedType, smallEntry.ItemType); + + if (name.Number > 0) + AddHtmlLocalized(316, y, 100, 20, name, LabelColor); + else + AddLabel(316, y, 1152, name); + + AddLabel(421, y, 1152, $"{smallEntry.AmountCur} / {smallEntry.AmountMax}"); + } + } + } + + public bool CheckFilter(IBOBEntry entry) + { + if (entry is BOBLargeEntry largeEntry) + return CheckFilter( + entry.Material, + entry.AmountMax, + true, + entry.RequireExceptional, + entry.DeedType, + largeEntry.Entries.Length > 0 ? largeEntry.Entries[0].ItemType : null + ); + + if (entry is BOBSmallEntry smallEntry) + return CheckFilter( + entry.Material, + entry.AmountMax, + false, + entry.RequireExceptional, + entry.DeedType, + smallEntry.ItemType + ); + + return false; + } + + public bool CheckFilter( + BulkMaterialType mat, int amountMax, bool isLarge, bool reqExc, BODType deedType, + Type itemType + ) + { + var f = m_From.UseOwnFilter ? m_From.BOBFilter : m_Book.Filter; + + if (f.IsDefault) + return true; + + if (f.Quality == 1 && reqExc) + return false; + if (f.Quality == 2 && !reqExc) + return false; + + if (f.Quantity == 1 && amountMax != 10) + return false; + if (f.Quantity == 2 && amountMax != 15) + return false; + if (f.Quantity == 3 && amountMax != 20) + return false; + + if (f.Type == 1 && isLarge) + return false; + if (f.Type == 2 && !isLarge) + return false; + + return f.Material switch + { + 1 => deedType == BODType.Smith, + 2 => deedType == BODType.Tailor, + 3 => mat == BulkMaterialType.None && BGTClassifier.Classify(deedType, itemType) == BulkGenericType.Iron, + 4 => mat == BulkMaterialType.DullCopper, + 5 => mat == BulkMaterialType.ShadowIron, + 6 => mat == BulkMaterialType.Copper, + 7 => mat == BulkMaterialType.Bronze, + 8 => mat == BulkMaterialType.Gold, + 9 => mat == BulkMaterialType.Agapite, + 10 => mat == BulkMaterialType.Verite, + 11 => mat == BulkMaterialType.Valorite, + 12 => mat == BulkMaterialType.None && BGTClassifier.Classify(deedType, itemType) == BulkGenericType.Cloth, + 13 => mat == BulkMaterialType.None && BGTClassifier.Classify(deedType, itemType) == BulkGenericType.Leather, + 14 => mat == BulkMaterialType.Spined, + 15 => mat == BulkMaterialType.Horned, + 16 => mat == BulkMaterialType.Barbed, + _ => true + }; + } + + public int GetIndexForPage(int page) + { + var index = 0; + + while (page-- > 0) + index += GetCountForIndex(index); + + return index; + } + + public int GetCountForIndex(int index) + { + var slots = 0; + var count = 0; + + var list = m_List; + + for (var i = index; i >= 0 && i < list.Count; ++i) + { + var entry = list[i]; + + if (CheckFilter(entry)) + { + var add = entry is BOBLargeEntry largeEntry ? largeEntry.Entries.Length : 1; + + if (slots + add > 10) + break; + + slots += add; + } + + ++count; + } + + return count; + } + + public int GetPageForIndex(int index, int sizeDropped) + { + if (index <= 0) + return 0; + + var count = 0; + var page = 0; + int i; + + var list = m_List; + for (i = 0; i < index && i < list.Count; i++) + { + var entry = list[i]; + if (!CheckFilter(entry)) + continue; + + var add = entry is BOBLargeEntry largeEntry ? largeEntry.Entries.Length : 1; + count += add; + if (count > 10) + { + page++; + count = add; + } + } + + /* now we are on the page of the bod preceding the dropped one. + * next step: checking whether we have to remain where we are. + * The counter i needs to be incremented as the bod to this very moment + * has not yet been removed from m_List */ + i++; + + /* if, for instance, a big bod of size 6 has been removed, smaller bods + * might fall back into this page. Depending on their sizes, the page needs + * to be adjusted accordingly. This is done now. + */ + if (count + sizeDropped > 10) + { + while (i < list.Count && count <= 10) + { + var entry = list[i]; + if (CheckFilter(entry)) + count += entry is BOBLargeEntry largeEntry ? largeEntry.Entries.Length : 1; + + i++; + } + + if (count > 10) + page++; + } + + return page; + } + + public TextDefinition GetMaterialName(BulkMaterialType mat, BODType type, Type itemType) + { + switch (type) + { + case BODType.Smith: + { + switch (mat) + { + case BulkMaterialType.None: return 1062226; + case BulkMaterialType.DullCopper: return 1018332; + case BulkMaterialType.ShadowIron: return 1018333; + case BulkMaterialType.Copper: return 1018334; + case BulkMaterialType.Bronze: return 1018335; + case BulkMaterialType.Gold: return 1018336; + case BulkMaterialType.Agapite: return 1018337; + case BulkMaterialType.Verite: return 1018338; + case BulkMaterialType.Valorite: return 1018339; + } + + break; + } + case BODType.Tailor: + { + switch (mat) + { + case BulkMaterialType.None: + { + if (itemType.IsSubclassOf(typeof(BaseArmor)) || itemType.IsSubclassOf(typeof(BaseShoes))) + return 1062235; + + return 1044286; + } + case BulkMaterialType.Spined: return 1062236; + case BulkMaterialType.Horned: return 1062237; + case BulkMaterialType.Barbed: return 1062238; + } + + break; + } + } + + return "Invalid"; + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var index = info.ButtonID; + + switch (index) + { + case 0: // EXIT + { + break; + } + case 1: // Set Filter + { + m_From.SendGump(new BOBFilterGump(m_From, m_Book)); + + break; + } + case 2: // Previous page + { + if (m_Page > 0) + m_From.SendGump(new BOBGump(m_From, m_Book, m_Page - 1, m_List)); + + return; + } + case 3: // Next page + { + if (GetIndexForPage(m_Page + 1) < m_List.Count) + m_From.SendGump(new BOBGump(m_From, m_Book, m_Page + 1, m_List)); + + break; + } + case 4: // Price all + { + if (m_Book.IsChildOf(m_From.Backpack)) + { + m_From.Prompt = new SetPricePrompt(m_Book, null, m_Page, m_List); + m_From.SendMessage("Type in a price for all deeds in the book:"); + } + + break; + } + default: + { + index -= 5; + + var type = index % 2; + index /= 2; + + if (index < 0 || index >= m_List.Count) + break; + + var bobEntry = m_List[index]; + + if (!m_Book.Entries.Contains(bobEntry)) + { + m_From.SendLocalizedMessage(1062382); // The deed selected is not available. + break; + } + + if (type == 0) // Drop + { + if (m_Book.IsChildOf(m_From.Backpack)) + { + var item = bobEntry.Reconstruct(); + + var pack = m_From.Backpack; + if (pack?.CheckHold( + m_From, + item, + true, + true, + 0, + item.PileWeight + item.TotalWeight + ) != true) + { + m_From.SendLocalizedMessage(503204); // You do not have room in your backpack for this + m_From.SendGump(new BOBGump(m_From, m_Book, m_Page)); + } + else + { + if (m_Book.IsChildOf(m_From.Backpack)) + { + var sizeOfDroppedBod = bobEntry is BOBLargeEntry entry ? entry.Entries.Length : 1; + + m_From.AddToBackpack(item); + m_From.SendLocalizedMessage( + 1045152 + ); // The bulk order deed has been placed in your backpack. + m_Book.Entries.Remove(bobEntry); + m_Book.InvalidateProperties(); + + if (m_Book.Entries.Count / 5 < m_Book.ItemCount) + { + m_Book.ItemCount--; + m_Book.InvalidateItems(); + } + + if (m_Book.Entries.Count > 0) + { + m_Page = GetPageForIndex(index, sizeOfDroppedBod); + m_From.SendGump(new BOBGump(m_From, m_Book, m_Page)); + } + else + { + m_From.SendLocalizedMessage(1062381); // The book is empty. + } + } + } + } + } + else // Set Price | Buy + { + if (m_Book.IsChildOf(m_From.Backpack)) + { + m_From.Prompt = new SetPricePrompt(m_Book, bobEntry, m_Page, m_List); + m_From.SendLocalizedMessage(1062383); // Type in a price for the deed: + } + else if (m_Book.RootParent is PlayerVendor pv) + { + var vi = pv.GetVendorItem(m_Book); + + if (vi?.IsForSale != false) + return; + + var sizeOfDroppedBod = bobEntry is BOBLargeEntry largeEntry ? largeEntry.Entries.Length : 1; + var price = bobEntry.Price; + + if (price == 0) + { + m_From.SendLocalizedMessage(1062382); // The deed selected is not available. + } + else + { + if (m_Book.Entries.Count > 0) + { + m_Page = GetPageForIndex(index, sizeOfDroppedBod); + m_From.SendGump(new BODBuyGump(m_From, m_Book, bobEntry, m_Page, price)); + } + else + { + m_From.SendLocalizedMessage(1062381); // The book is emptz + } + } + } + } + + break; + } + } + } + + private class SetPricePrompt : Prompt + { + private readonly BulkOrderBook m_Book; + private readonly IBOBEntry m_Entry; + private readonly List m_List; + private readonly int m_Page; + + public SetPricePrompt(BulkOrderBook book, IBOBEntry entry, int page, List list) + { + m_Book = book; + m_Entry = entry; + m_Page = page; + m_List = list; + } + + public override void OnResponse(Mobile from, string text) + { + if (m_Entry != null && !m_Book.Entries.Contains(m_Entry)) + { + from.SendLocalizedMessage(1062382); // The deed selected is not available. + return; + } + + var price = Utility.ToInt32(text); + + if (price < 0 || price > 250000000) + { + from.SendLocalizedMessage(1062390); // The price you requested is outrageous! + } + else if (m_Entry == null) + { + for (var i = 0; i < m_List.Count; ++i) + { + var entry = m_List[i]; + + if (!m_Book.Entries.Contains(entry)) + continue; + + entry.Price = price; + } + + from.SendMessage("Deed prices set."); + + if (from is PlayerMobile mobile) + mobile.SendGump(new BOBGump(mobile, m_Book, m_Page, m_List)); + } + else + { + m_Entry.Price = price; + from.SendLocalizedMessage(1062384); // Deed price set. + if (from is PlayerMobile mobile) + mobile.SendGump(new BOBGump(mobile, m_Book, m_Page, m_List)); + } + } + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/Books/BOBLargeEntry.cs b/Projects/UOContent/Engines/BulkOrders/Books/BOBLargeEntry.cs index 247f9dc6c..62f400da5 100644 --- a/Projects/UOContent/Engines/BulkOrders/Books/BOBLargeEntry.cs +++ b/Projects/UOContent/Engines/BulkOrders/Books/BOBLargeEntry.cs @@ -1,105 +1,107 @@ -namespace Server.Engines.BulkOrders -{ - public class BOBLargeEntry : IBOBEntry - { - public BOBLargeEntry(LargeBOD bod) - { - RequireExceptional = bod.RequireExceptional; - - if (bod is LargeTailorBOD) - DeedType = BODType.Tailor; - else if (bod is LargeSmithBOD) - DeedType = BODType.Smith; - - Material = bod.Material; - AmountMax = bod.AmountMax; - - Entries = new BOBLargeSubEntry[bod.Entries.Length]; - - for (int i = 0; i < Entries.Length; ++i) - Entries[i] = new BOBLargeSubEntry(bod.Entries[i]); - } - - public BOBLargeEntry(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 0: - { - RequireExceptional = reader.ReadBool(); - - DeedType = (BODType)reader.ReadEncodedInt(); - - Material = (BulkMaterialType)reader.ReadEncodedInt(); - AmountMax = reader.ReadEncodedInt(); - Price = reader.ReadEncodedInt(); - - Entries = new BOBLargeSubEntry[reader.ReadEncodedInt()]; - - for (int i = 0; i < Entries.Length; ++i) - Entries[i] = new BOBLargeSubEntry(reader); - - break; - } - } - } - - public bool RequireExceptional { get; } - - public BODType DeedType { get; } - - public BulkMaterialType Material { get; } - - public int AmountMax { get; } - - public int Price { get; set; } - - public BOBLargeSubEntry[] Entries { get; } - - public Item Reconstruct() - { - LargeBOD bod = null; - - if (DeedType == BODType.Smith) - bod = new LargeSmithBOD(AmountMax, RequireExceptional, Material, ReconstructEntries()); - else if (DeedType == BODType.Tailor) - bod = new LargeTailorBOD(AmountMax, RequireExceptional, Material, ReconstructEntries()); - - for (int i = 0; bod?.Entries.Length >= i; ++i) - bod.Entries[i].Owner = bod; - - return bod; - } - - private LargeBulkEntry[] ReconstructEntries() - { - LargeBulkEntry[] entries = new LargeBulkEntry[Entries.Length]; - - for (int i = 0; i < Entries.Length; ++i) - entries[i] = new LargeBulkEntry(null, - new SmallBulkEntry(Entries[i].ItemType, Entries[i].Number, Entries[i].Graphic)) - { Amount = Entries[i].AmountCur }; - - return entries; - } - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(RequireExceptional); - - writer.WriteEncodedInt((int)DeedType); - writer.WriteEncodedInt((int)Material); - writer.WriteEncodedInt(AmountMax); - writer.WriteEncodedInt(Price); - - writer.WriteEncodedInt(Entries.Length); - - for (int i = 0; i < Entries.Length; ++i) - Entries[i].Serialize(writer); - } - } -} +namespace Server.Engines.BulkOrders +{ + public class BOBLargeEntry : IBOBEntry + { + public BOBLargeEntry(LargeBOD bod) + { + RequireExceptional = bod.RequireExceptional; + + if (bod is LargeTailorBOD) + DeedType = BODType.Tailor; + else if (bod is LargeSmithBOD) + DeedType = BODType.Smith; + + Material = bod.Material; + AmountMax = bod.AmountMax; + + Entries = new BOBLargeSubEntry[bod.Entries.Length]; + + for (var i = 0; i < Entries.Length; ++i) + Entries[i] = new BOBLargeSubEntry(bod.Entries[i]); + } + + public BOBLargeEntry(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 0: + { + RequireExceptional = reader.ReadBool(); + + DeedType = (BODType)reader.ReadEncodedInt(); + + Material = (BulkMaterialType)reader.ReadEncodedInt(); + AmountMax = reader.ReadEncodedInt(); + Price = reader.ReadEncodedInt(); + + Entries = new BOBLargeSubEntry[reader.ReadEncodedInt()]; + + for (var i = 0; i < Entries.Length; ++i) + Entries[i] = new BOBLargeSubEntry(reader); + + break; + } + } + } + + public BOBLargeSubEntry[] Entries { get; } + + public bool RequireExceptional { get; } + + public BODType DeedType { get; } + + public BulkMaterialType Material { get; } + + public int AmountMax { get; } + + public int Price { get; set; } + + public Item Reconstruct() + { + LargeBOD bod = null; + + if (DeedType == BODType.Smith) + bod = new LargeSmithBOD(AmountMax, RequireExceptional, Material, ReconstructEntries()); + else if (DeedType == BODType.Tailor) + bod = new LargeTailorBOD(AmountMax, RequireExceptional, Material, ReconstructEntries()); + + for (var i = 0; bod?.Entries.Length >= i; ++i) + bod.Entries[i].Owner = bod; + + return bod; + } + + private LargeBulkEntry[] ReconstructEntries() + { + var entries = new LargeBulkEntry[Entries.Length]; + + for (var i = 0; i < Entries.Length; ++i) + entries[i] = new LargeBulkEntry( + null, + new SmallBulkEntry(Entries[i].ItemType, Entries[i].Number, Entries[i].Graphic) + ) + { Amount = Entries[i].AmountCur }; + + return entries; + } + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(RequireExceptional); + + writer.WriteEncodedInt((int)DeedType); + writer.WriteEncodedInt((int)Material); + writer.WriteEncodedInt(AmountMax); + writer.WriteEncodedInt(Price); + + writer.WriteEncodedInt(Entries.Length); + + for (var i = 0; i < Entries.Length; ++i) + Entries[i].Serialize(writer); + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/Books/BOBLargeSubEntry.cs b/Projects/UOContent/Engines/BulkOrders/Books/BOBLargeSubEntry.cs index ea818c4c2..9621cafde 100644 --- a/Projects/UOContent/Engines/BulkOrders/Books/BOBLargeSubEntry.cs +++ b/Projects/UOContent/Engines/BulkOrders/Books/BOBLargeSubEntry.cs @@ -1,56 +1,56 @@ -using System; - -namespace Server.Engines.BulkOrders -{ - public class BOBLargeSubEntry - { - public BOBLargeSubEntry(LargeBulkEntry lbe) - { - ItemType = lbe.Details.Type; - AmountCur = lbe.Amount; - Number = lbe.Details.Number; - Graphic = lbe.Details.Graphic; - } - - public BOBLargeSubEntry(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 0: - { - string type = reader.ReadString(); - - if (type != null) - ItemType = AssemblyHandler.FindFirstTypeForName(type); - - AmountCur = reader.ReadEncodedInt(); - Number = reader.ReadEncodedInt(); - Graphic = reader.ReadEncodedInt(); - - break; - } - } - } - - public Type ItemType { get; } - - public int AmountCur { get; } - - public int Number { get; } - - public int Graphic { get; } - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(ItemType?.FullName); - - writer.WriteEncodedInt(AmountCur); - writer.WriteEncodedInt(Number); - writer.WriteEncodedInt(Graphic); - } - } -} +using System; + +namespace Server.Engines.BulkOrders +{ + public class BOBLargeSubEntry + { + public BOBLargeSubEntry(LargeBulkEntry lbe) + { + ItemType = lbe.Details.Type; + AmountCur = lbe.Amount; + Number = lbe.Details.Number; + Graphic = lbe.Details.Graphic; + } + + public BOBLargeSubEntry(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 0: + { + var type = reader.ReadString(); + + if (type != null) + ItemType = AssemblyHandler.FindFirstTypeForName(type); + + AmountCur = reader.ReadEncodedInt(); + Number = reader.ReadEncodedInt(); + Graphic = reader.ReadEncodedInt(); + + break; + } + } + } + + public Type ItemType { get; } + + public int AmountCur { get; } + + public int Number { get; } + + public int Graphic { get; } + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(ItemType?.FullName); + + writer.WriteEncodedInt(AmountCur); + writer.WriteEncodedInt(Number); + writer.WriteEncodedInt(Graphic); + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/Books/BOBSmallEntry.cs b/Projects/UOContent/Engines/BulkOrders/Books/BOBSmallEntry.cs index caef12f81..10189dc6f 100644 --- a/Projects/UOContent/Engines/BulkOrders/Books/BOBSmallEntry.cs +++ b/Projects/UOContent/Engines/BulkOrders/Books/BOBSmallEntry.cs @@ -1,100 +1,100 @@ -using System; - -namespace Server.Engines.BulkOrders -{ - public class BOBSmallEntry : IBOBEntry - { - public BOBSmallEntry(SmallBOD bod) - { - ItemType = bod.Type; - RequireExceptional = bod.RequireExceptional; - - if (bod is SmallTailorBOD) - DeedType = BODType.Tailor; - else if (bod is SmallSmithBOD) - DeedType = BODType.Smith; - - Material = bod.Material; - AmountCur = bod.AmountCur; - AmountMax = bod.AmountMax; - Number = bod.Number; - Graphic = bod.Graphic; - } - - public BOBSmallEntry(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 0: - { - string type = reader.ReadString(); - - if (type != null) - ItemType = AssemblyHandler.FindFirstTypeForName(type); - - RequireExceptional = reader.ReadBool(); - - DeedType = (BODType)reader.ReadEncodedInt(); - - Material = (BulkMaterialType)reader.ReadEncodedInt(); - AmountCur = reader.ReadEncodedInt(); - AmountMax = reader.ReadEncodedInt(); - Number = reader.ReadEncodedInt(); - Graphic = reader.ReadEncodedInt(); - Price = reader.ReadEncodedInt(); - - break; - } - } - } - - public Type ItemType { get; } - - public bool RequireExceptional { get; } - - public BODType DeedType { get; } - - public BulkMaterialType Material { get; } - - public int AmountCur { get; } - - public int AmountMax { get; } - - public int Number { get; } - - public int Graphic { get; } - - public int Price { get; set; } - - public Item Reconstruct() - { - SmallBOD bod = null; - - if (DeedType == BODType.Smith) - bod = new SmallSmithBOD(AmountCur, AmountMax, ItemType, Number, Graphic, RequireExceptional, Material); - else if (DeedType == BODType.Tailor) - bod = new SmallTailorBOD(AmountCur, AmountMax, ItemType, Number, Graphic, RequireExceptional, Material); - - return bod; - } - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(ItemType?.FullName); - - writer.Write(RequireExceptional); - - writer.WriteEncodedInt((int)DeedType); - writer.WriteEncodedInt((int)Material); - writer.WriteEncodedInt(AmountCur); - writer.WriteEncodedInt(AmountMax); - writer.WriteEncodedInt(Number); - writer.WriteEncodedInt(Graphic); - writer.WriteEncodedInt(Price); - } - } -} +using System; + +namespace Server.Engines.BulkOrders +{ + public class BOBSmallEntry : IBOBEntry + { + public BOBSmallEntry(SmallBOD bod) + { + ItemType = bod.Type; + RequireExceptional = bod.RequireExceptional; + + if (bod is SmallTailorBOD) + DeedType = BODType.Tailor; + else if (bod is SmallSmithBOD) + DeedType = BODType.Smith; + + Material = bod.Material; + AmountCur = bod.AmountCur; + AmountMax = bod.AmountMax; + Number = bod.Number; + Graphic = bod.Graphic; + } + + public BOBSmallEntry(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 0: + { + var type = reader.ReadString(); + + if (type != null) + ItemType = AssemblyHandler.FindFirstTypeForName(type); + + RequireExceptional = reader.ReadBool(); + + DeedType = (BODType)reader.ReadEncodedInt(); + + Material = (BulkMaterialType)reader.ReadEncodedInt(); + AmountCur = reader.ReadEncodedInt(); + AmountMax = reader.ReadEncodedInt(); + Number = reader.ReadEncodedInt(); + Graphic = reader.ReadEncodedInt(); + Price = reader.ReadEncodedInt(); + + break; + } + } + } + + public Type ItemType { get; } + + public int AmountCur { get; } + + public int Number { get; } + + public int Graphic { get; } + + public bool RequireExceptional { get; } + + public BODType DeedType { get; } + + public BulkMaterialType Material { get; } + + public int AmountMax { get; } + + public int Price { get; set; } + + public Item Reconstruct() + { + SmallBOD bod = null; + + if (DeedType == BODType.Smith) + bod = new SmallSmithBOD(AmountCur, AmountMax, ItemType, Number, Graphic, RequireExceptional, Material); + else if (DeedType == BODType.Tailor) + bod = new SmallTailorBOD(AmountCur, AmountMax, ItemType, Number, Graphic, RequireExceptional, Material); + + return bod; + } + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(ItemType?.FullName); + + writer.Write(RequireExceptional); + + writer.WriteEncodedInt((int)DeedType); + writer.WriteEncodedInt((int)Material); + writer.WriteEncodedInt(AmountCur); + writer.WriteEncodedInt(AmountMax); + writer.WriteEncodedInt(Number); + writer.WriteEncodedInt(Graphic); + writer.WriteEncodedInt(Price); + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/Books/BODBuyGump.cs b/Projects/UOContent/Engines/BulkOrders/Books/BODBuyGump.cs index af337f7e3..32b758fe7 100644 --- a/Projects/UOContent/Engines/BulkOrders/Books/BODBuyGump.cs +++ b/Projects/UOContent/Engines/BulkOrders/Books/BODBuyGump.cs @@ -1,122 +1,131 @@ -using Server.Gumps; -using Server.Items; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.BulkOrders -{ - public class BODBuyGump : Gump - { - private readonly BulkOrderBook m_Book; - private readonly PlayerMobile m_From; - private readonly IBOBEntry m_Entry; - private readonly int m_Page; - private readonly int m_Price; - - public BODBuyGump(PlayerMobile from, BulkOrderBook book, IBOBEntry entry, int page, int price) : base(100, 200) - { - m_From = from; - m_Book = book; - m_Entry = entry; - m_Price = price; - m_Page = page; - - AddPage(0); - - AddBackground(100, 10, 300, 150, 5054); - - AddHtmlLocalized(125, 20, 250, 24, 1019070); // You have agreed to purchase: - AddHtmlLocalized(125, 45, 250, 24, 1045151); // a bulk order deed - - AddHtmlLocalized(125, 70, 250, 24, 1019071); // for the amount of: - AddLabel(125, 95, 0, price.ToString()); - - AddButton(250, 130, 4005, 4007, 1); - AddHtmlLocalized(282, 130, 100, 24, 1011012); // CANCEL - - AddButton(120, 130, 4005, 4007, 2); - AddHtmlLocalized(152, 130, 100, 24, 1011036); // OKAY - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID != 2) - { - m_From.SendLocalizedMessage(503207); // Cancelled purchase. - return; - } - - if (!(m_Book.RootParent is PlayerVendor pv)) - { - m_From.SendLocalizedMessage(1062382); // The deed selected is not available. - return; - } - - if (!m_Book.Entries.Contains(m_Entry)) - { - pv.SayTo(m_From, 1062382); // The deed selected is not available. - return; - } - - int price = 0; - - if (pv.GetVendorItem(m_Book)?.IsForSale == false) - price = m_Entry.Price; - - if (price != m_Price) - { - pv.SayTo(m_From, - "The price has been been changed. If you like, you may offer to purchase the item again."); - return; - } - - if (price == 0) - { - pv.SayTo(m_From, 1062382); // The deed selected is not available. - return; - } - - Item item = m_Entry.Reconstruct(); - - pv.Say(m_From.Name); - - Container pack = m_From.Backpack; - - if (pack?.CheckHold(m_From, item, true, true, 0, - item.PileWeight + item.TotalWeight) != true) - { - pv.SayTo(m_From, 503204); // You do not have room in your backpack for this - m_From.SendGump(new BOBGump(m_From, m_Book, m_Page)); - item.Delete(); - } - else - { - if (pack.ConsumeTotal(typeof(Gold), price) || Banker.Withdraw(m_From, price)) - { - m_Book.Entries.Remove(m_Entry); - m_Book.InvalidateProperties(); - pv.HoldGold += price; - m_From.AddToBackpack(item); - m_From.SendLocalizedMessage( - 1045152); // The bulk order deed has been placed in your backpack. - - if (m_Book.Entries.Count / 5 < m_Book.ItemCount) - { - m_Book.ItemCount--; - m_Book.InvalidateItems(); - } - - if (m_Book.Entries.Count > 0) - m_From.SendGump(new BOBGump(m_From, m_Book, m_Page)); - else - m_From.SendLocalizedMessage(1062381); // The book is empty. - } - else - { - pv.SayTo(m_From, 503205); // You cannot afford this item. - item.Delete(); - } - } - } - } -} +using Server.Gumps; +using Server.Items; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.BulkOrders +{ + public class BODBuyGump : Gump + { + private readonly BulkOrderBook m_Book; + private readonly IBOBEntry m_Entry; + private readonly PlayerMobile m_From; + private readonly int m_Page; + private readonly int m_Price; + + public BODBuyGump(PlayerMobile from, BulkOrderBook book, IBOBEntry entry, int page, int price) : base(100, 200) + { + m_From = from; + m_Book = book; + m_Entry = entry; + m_Price = price; + m_Page = page; + + AddPage(0); + + AddBackground(100, 10, 300, 150, 5054); + + AddHtmlLocalized(125, 20, 250, 24, 1019070); // You have agreed to purchase: + AddHtmlLocalized(125, 45, 250, 24, 1045151); // a bulk order deed + + AddHtmlLocalized(125, 70, 250, 24, 1019071); // for the amount of: + AddLabel(125, 95, 0, price.ToString()); + + AddButton(250, 130, 4005, 4007, 1); + AddHtmlLocalized(282, 130, 100, 24, 1011012); // CANCEL + + AddButton(120, 130, 4005, 4007, 2); + AddHtmlLocalized(152, 130, 100, 24, 1011036); // OKAY + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID != 2) + { + m_From.SendLocalizedMessage(503207); // Cancelled purchase. + return; + } + + if (!(m_Book.RootParent is PlayerVendor pv)) + { + m_From.SendLocalizedMessage(1062382); // The deed selected is not available. + return; + } + + if (!m_Book.Entries.Contains(m_Entry)) + { + pv.SayTo(m_From, 1062382); // The deed selected is not available. + return; + } + + var price = 0; + + if (pv.GetVendorItem(m_Book)?.IsForSale == false) + price = m_Entry.Price; + + if (price != m_Price) + { + pv.SayTo( + m_From, + "The price has been been changed. If you like, you may offer to purchase the item again." + ); + return; + } + + if (price == 0) + { + pv.SayTo(m_From, 1062382); // The deed selected is not available. + return; + } + + var item = m_Entry.Reconstruct(); + + pv.Say(m_From.Name); + + var pack = m_From.Backpack; + + if (pack?.CheckHold( + m_From, + item, + true, + true, + 0, + item.PileWeight + item.TotalWeight + ) != true) + { + pv.SayTo(m_From, 503204); // You do not have room in your backpack for this + m_From.SendGump(new BOBGump(m_From, m_Book, m_Page)); + item.Delete(); + } + else + { + if (pack.ConsumeTotal(typeof(Gold), price) || Banker.Withdraw(m_From, price)) + { + m_Book.Entries.Remove(m_Entry); + m_Book.InvalidateProperties(); + pv.HoldGold += price; + m_From.AddToBackpack(item); + m_From.SendLocalizedMessage( + 1045152 + ); // The bulk order deed has been placed in your backpack. + + if (m_Book.Entries.Count / 5 < m_Book.ItemCount) + { + m_Book.ItemCount--; + m_Book.InvalidateItems(); + } + + if (m_Book.Entries.Count > 0) + m_From.SendGump(new BOBGump(m_From, m_Book, m_Page)); + else + m_From.SendLocalizedMessage(1062381); // The book is empty. + } + else + { + pv.SayTo(m_From, 503205); // You cannot afford this item. + item.Delete(); + } + } + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/Books/BODType.cs b/Projects/UOContent/Engines/BulkOrders/Books/BODType.cs index fbeb7cb5a..1eda0f9ee 100644 --- a/Projects/UOContent/Engines/BulkOrders/Books/BODType.cs +++ b/Projects/UOContent/Engines/BulkOrders/Books/BODType.cs @@ -1,8 +1,8 @@ -namespace Server.Engines.BulkOrders -{ - public enum BODType - { - Smith, - Tailor - } -} \ No newline at end of file +namespace Server.Engines.BulkOrders +{ + public enum BODType + { + Smith, + Tailor + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/Books/BulkOrderBook.cs b/Projects/UOContent/Engines/BulkOrders/Books/BulkOrderBook.cs index 734364c57..fff3fbbe6 100644 --- a/Projects/UOContent/Engines/BulkOrders/Books/BulkOrderBook.cs +++ b/Projects/UOContent/Engines/BulkOrders/Books/BulkOrderBook.cs @@ -1,305 +1,315 @@ -using System.Collections.Generic; -using Server.Gumps; -using Server.Multis; -using Server.Prompts; -using Server.Mobiles; -using Server.ContextMenus; -using Server.Items; - -namespace Server.Engines.BulkOrders -{ - public class BulkOrderBook : Item, ISecurable - { - private string m_BookName; - - [CommandProperty(AccessLevel.GameMaster)] - public string BookName - { - get => m_BookName; - set { m_BookName = value; InvalidateProperties(); } - } - - [CommandProperty(AccessLevel.GameMaster)] - public SecureLevel Level { get; set; } - - public List Entries { get; private set; } - - public BOBFilter Filter { get; private set; } - - public int ItemCount { get; set; } - - [Constructible] - public BulkOrderBook() : base(0x2259) - { - Weight = 1.0; - LootType = LootType.Blessed; - - Entries = new List(); - Filter = new BOBFilter(); - - Level = SecureLevel.CoOwners; - } - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 2)) - from.LocalOverheadMessage(Network.MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - else if (Entries.Count == 0) - from.SendLocalizedMessage(1062381); // The book is empty. - else if (from is PlayerMobile mobile) - mobile.SendGump(new BOBGump(mobile, this)); - } - - public override void OnDoubleClickSecureTrade(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 2)) - { - from.SendLocalizedMessage(500446); // That is too far away. - } - else if (Entries.Count == 0) - { - from.SendLocalizedMessage(1062381); // The book is empty. - } - else - { - from.SendGump(new BOBGump((PlayerMobile)from, this)); - - SecureTrade trade = GetSecureTradeCont()?.Trade; - - if (trade?.From.Mobile == from) - trade.To.Mobile.SendGump(new BOBGump((PlayerMobile)trade.To.Mobile, this)); - else if (trade?.To.Mobile == from) - trade.From.Mobile.SendGump(new BOBGump((PlayerMobile)trade.From.Mobile, this)); - } - } - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (dropped is BaseBOD) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1062385); // You must have the book in your backpack to add deeds to it. - return false; - } - if (!from.Backpack.CheckHold(from, dropped, true, true)) - return false; - if (Entries.Count < 500) - { - if (dropped is LargeBOD bod) - Entries.Add(new BOBLargeEntry(bod)); - else - Entries.Add(new BOBSmallEntry((SmallBOD)dropped)); - - InvalidateProperties(); - - if (Entries.Count / 5 > ItemCount) - { - ItemCount++; - InvalidateItems(); - } - - from.SendSound(0x42, GetWorldLocation()); - from.SendLocalizedMessage(1062386); // Deed added to book. - - if (from is PlayerMobile pm) - pm.SendGump(new BOBGump(pm, this)); - - dropped.Delete(); - - return true; - } - - from.SendLocalizedMessage(1062387); // The book is full of deeds. - return false; - } - - from.SendLocalizedMessage(1062388); // That is not a bulk order deed. - return false; - } - - public override int GetTotal(TotalType type) - { - int total = base.GetTotal(type); - - if (type == TotalType.Items) - total = ItemCount; - - return total; - } - - public void InvalidateItems() - { - if (RootParent is Mobile m) - { - m.UpdateTotals(); - InvalidateContainers(Parent); - } - } - - public void InvalidateContainers(IEntity parent) - { - if (parent is Container c) - { - c.InvalidateProperties(); - InvalidateContainers(c.Parent); - } - } - - public BulkOrderBook(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(2); // version - - writer.Write(ItemCount); - - writer.Write((int)Level); - - writer.Write(m_BookName); - - Filter.Serialize(writer); - - writer.WriteEncodedInt(Entries.Count); - - for (int i = 0; i < Entries.Count; ++i) - { - object obj = Entries[i]; - - if (obj is BOBLargeEntry entry) - { - writer.WriteEncodedInt(0); - entry.Serialize(writer); - } - else - { - writer.WriteEncodedInt(1); - ((BOBSmallEntry)obj).Serialize(writer); - } - } - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 2: - { - ItemCount = reader.ReadInt(); - goto case 1; - } - case 1: - { - Level = (SecureLevel)reader.ReadInt(); - goto case 0; - } - case 0: - { - m_BookName = reader.ReadString(); - - Filter = new BOBFilter(reader); - - int count = reader.ReadEncodedInt(); - - Entries = new List(count); - - for (int i = 0; i < count; ++i) - { - int v = reader.ReadEncodedInt(); - - switch (v) - { - case 0: Entries.Add(new BOBLargeEntry(reader)); break; - case 1: Entries.Add(new BOBSmallEntry(reader)); break; - } - } - - break; - } - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1062344, Entries.Count.ToString()); // Deeds in book: ~1_val~ - - if (!string.IsNullOrEmpty(m_BookName)) - list.Add(1062481, m_BookName); // Book Name: ~1_val~ - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - LabelTo(from, 1062344, Entries.Count.ToString()); // Deeds in book: ~1_val~ - - if (!string.IsNullOrEmpty(m_BookName)) - LabelTo(from, 1062481, m_BookName); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (from.CheckAlive() && IsChildOf(from.Backpack)) - list.Add(new NameBookEntry(from, this)); - - SetSecureLevelEntry.AddTo(from, this, list); - } - - private class NameBookEntry : ContextMenuEntry - { - private readonly Mobile m_From; - private readonly BulkOrderBook m_Book; - - public NameBookEntry(Mobile from, BulkOrderBook book) : base(6216) - { - m_From = from; - m_Book = book; - } - - public override void OnClick() - { - if (m_From.CheckAlive() && m_Book.IsChildOf(m_From.Backpack)) - { - m_From.Prompt = new NameBookPrompt(m_Book); - m_From.SendLocalizedMessage(1062479); // Type in the new name of the book: - } - } - } - - private class NameBookPrompt : Prompt - { - private readonly BulkOrderBook m_Book; - - public NameBookPrompt(BulkOrderBook book) => m_Book = book; - - public override void OnResponse(Mobile from, string text) - { - if (text.Length > 40) - text = text.Substring(0, 40); - - if (from.CheckAlive() && m_Book.IsChildOf(from.Backpack)) - { - m_Book.BookName = Utility.FixHtml(text.Trim()); - - from.SendLocalizedMessage(1062480); // The bulk order book's name has been changed. - } - } - - public override void OnCancel(Mobile from) - { - } - } - } -} +using System.Collections.Generic; +using Server.ContextMenus; +using Server.Gumps; +using Server.Items; +using Server.Mobiles; +using Server.Multis; +using Server.Network; +using Server.Prompts; + +namespace Server.Engines.BulkOrders +{ + public class BulkOrderBook : Item, ISecurable + { + private string m_BookName; + + [Constructible] + public BulkOrderBook() : base(0x2259) + { + Weight = 1.0; + LootType = LootType.Blessed; + + Entries = new List(); + Filter = new BOBFilter(); + + Level = SecureLevel.CoOwners; + } + + public BulkOrderBook(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public string BookName + { + get => m_BookName; + set + { + m_BookName = value; + InvalidateProperties(); + } + } + + public List Entries { get; private set; } + + public BOBFilter Filter { get; private set; } + + public int ItemCount { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public SecureLevel Level { get; set; } + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 2)) + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + else if (Entries.Count == 0) + from.SendLocalizedMessage(1062381); // The book is empty. + else if (from is PlayerMobile mobile) + mobile.SendGump(new BOBGump(mobile, this)); + } + + public override void OnDoubleClickSecureTrade(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 2)) + { + from.SendLocalizedMessage(500446); // That is too far away. + } + else if (Entries.Count == 0) + { + from.SendLocalizedMessage(1062381); // The book is empty. + } + else + { + from.SendGump(new BOBGump((PlayerMobile)from, this)); + + var trade = GetSecureTradeCont()?.Trade; + + if (trade?.From.Mobile == from) + trade.To.Mobile.SendGump(new BOBGump((PlayerMobile)trade.To.Mobile, this)); + else if (trade?.To.Mobile == from) + trade.From.Mobile.SendGump(new BOBGump((PlayerMobile)trade.From.Mobile, this)); + } + } + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (dropped is BaseBOD) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1062385); // You must have the book in your backpack to add deeds to it. + return false; + } + + if (!from.Backpack.CheckHold(from, dropped, true, true)) + return false; + if (Entries.Count < 500) + { + if (dropped is LargeBOD bod) + Entries.Add(new BOBLargeEntry(bod)); + else + Entries.Add(new BOBSmallEntry((SmallBOD)dropped)); + + InvalidateProperties(); + + if (Entries.Count / 5 > ItemCount) + { + ItemCount++; + InvalidateItems(); + } + + from.SendSound(0x42, GetWorldLocation()); + from.SendLocalizedMessage(1062386); // Deed added to book. + + if (from is PlayerMobile pm) + pm.SendGump(new BOBGump(pm, this)); + + dropped.Delete(); + + return true; + } + + from.SendLocalizedMessage(1062387); // The book is full of deeds. + return false; + } + + from.SendLocalizedMessage(1062388); // That is not a bulk order deed. + return false; + } + + public override int GetTotal(TotalType type) + { + var total = base.GetTotal(type); + + if (type == TotalType.Items) + total = ItemCount; + + return total; + } + + public void InvalidateItems() + { + if (RootParent is Mobile m) + { + m.UpdateTotals(); + InvalidateContainers(Parent); + } + } + + public void InvalidateContainers(IEntity parent) + { + if (parent is Container c) + { + c.InvalidateProperties(); + InvalidateContainers(c.Parent); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(2); // version + + writer.Write(ItemCount); + + writer.Write((int)Level); + + writer.Write(m_BookName); + + Filter.Serialize(writer); + + writer.WriteEncodedInt(Entries.Count); + + for (var i = 0; i < Entries.Count; ++i) + { + object obj = Entries[i]; + + if (obj is BOBLargeEntry entry) + { + writer.WriteEncodedInt(0); + entry.Serialize(writer); + } + else + { + writer.WriteEncodedInt(1); + ((BOBSmallEntry)obj).Serialize(writer); + } + } + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 2: + { + ItemCount = reader.ReadInt(); + goto case 1; + } + case 1: + { + Level = (SecureLevel)reader.ReadInt(); + goto case 0; + } + case 0: + { + m_BookName = reader.ReadString(); + + Filter = new BOBFilter(reader); + + var count = reader.ReadEncodedInt(); + + Entries = new List(count); + + for (var i = 0; i < count; ++i) + { + var v = reader.ReadEncodedInt(); + + switch (v) + { + case 0: + Entries.Add(new BOBLargeEntry(reader)); + break; + case 1: + Entries.Add(new BOBSmallEntry(reader)); + break; + } + } + + break; + } + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1062344, Entries.Count.ToString()); // Deeds in book: ~1_val~ + + if (!string.IsNullOrEmpty(m_BookName)) + list.Add(1062481, m_BookName); // Book Name: ~1_val~ + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + LabelTo(from, 1062344, Entries.Count.ToString()); // Deeds in book: ~1_val~ + + if (!string.IsNullOrEmpty(m_BookName)) + LabelTo(from, 1062481, m_BookName); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (from.CheckAlive() && IsChildOf(from.Backpack)) + list.Add(new NameBookEntry(from, this)); + + SetSecureLevelEntry.AddTo(from, this, list); + } + + private class NameBookEntry : ContextMenuEntry + { + private readonly BulkOrderBook m_Book; + private readonly Mobile m_From; + + public NameBookEntry(Mobile from, BulkOrderBook book) : base(6216) + { + m_From = from; + m_Book = book; + } + + public override void OnClick() + { + if (m_From.CheckAlive() && m_Book.IsChildOf(m_From.Backpack)) + { + m_From.Prompt = new NameBookPrompt(m_Book); + m_From.SendLocalizedMessage(1062479); // Type in the new name of the book: + } + } + } + + private class NameBookPrompt : Prompt + { + private readonly BulkOrderBook m_Book; + + public NameBookPrompt(BulkOrderBook book) => m_Book = book; + + public override void OnResponse(Mobile from, string text) + { + if (text.Length > 40) + text = text.Substring(0, 40); + + if (from.CheckAlive() && m_Book.IsChildOf(from.Backpack)) + { + m_Book.BookName = Utility.FixHtml(text.Trim()); + + from.SendLocalizedMessage(1062480); // The bulk order book's name has been changed. + } + } + + public override void OnCancel(Mobile from) + { + } + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/Books/IBOBEntry.cs b/Projects/UOContent/Engines/BulkOrders/Books/IBOBEntry.cs index 61ce92899..38847cd44 100644 --- a/Projects/UOContent/Engines/BulkOrders/Books/IBOBEntry.cs +++ b/Projects/UOContent/Engines/BulkOrders/Books/IBOBEntry.cs @@ -1,12 +1,12 @@ -namespace Server.Engines.BulkOrders -{ - public interface IBOBEntry - { - bool RequireExceptional { get; } - BODType DeedType { get; } - BulkMaterialType Material { get; } - int AmountMax { get; } - int Price { get; set; } - Item Reconstruct(); - } -} \ No newline at end of file +namespace Server.Engines.BulkOrders +{ + public interface IBOBEntry + { + bool RequireExceptional { get; } + BODType DeedType { get; } + BulkMaterialType Material { get; } + int AmountMax { get; } + int Price { get; set; } + Item Reconstruct(); + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/BulkMaterialType.cs b/Projects/UOContent/Engines/BulkOrders/BulkMaterialType.cs index f628d09cf..45c9edf48 100644 --- a/Projects/UOContent/Engines/BulkOrders/BulkMaterialType.cs +++ b/Projects/UOContent/Engines/BulkOrders/BulkMaterialType.cs @@ -1,40 +1,41 @@ -using System; -using Server.Items; - -namespace Server.Engines.BulkOrders -{ - public enum BulkMaterialType - { - None, - DullCopper, - ShadowIron, - Copper, - Bronze, - Gold, - Agapite, - Verite, - Valorite, - Spined, - Horned, - Barbed - } - - public enum BulkGenericType - { - Iron, - Cloth, - Leather - } - - public class BGTClassifier - { - public static BulkGenericType Classify(BODType deedType, Type itemType) - { - if (deedType != BODType.Tailor) - return BulkGenericType.Iron; - - return itemType == null || itemType.IsSubclassOf(typeof(BaseArmor)) || itemType.IsSubclassOf(typeof(BaseShoes)) - ? BulkGenericType.Leather : BulkGenericType.Cloth; - } - } -} +using System; +using Server.Items; + +namespace Server.Engines.BulkOrders +{ + public enum BulkMaterialType + { + None, + DullCopper, + ShadowIron, + Copper, + Bronze, + Gold, + Agapite, + Verite, + Valorite, + Spined, + Horned, + Barbed + } + + public enum BulkGenericType + { + Iron, + Cloth, + Leather + } + + public class BGTClassifier + { + public static BulkGenericType Classify(BODType deedType, Type itemType) + { + if (deedType != BODType.Tailor) + return BulkGenericType.Iron; + + return itemType == null || itemType.IsSubclassOf(typeof(BaseArmor)) || itemType.IsSubclassOf(typeof(BaseShoes)) + ? BulkGenericType.Leather + : BulkGenericType.Cloth; + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/LargeBOD.cs b/Projects/UOContent/Engines/BulkOrders/LargeBOD.cs index ffe8ec0d2..19764b217 100644 --- a/Projects/UOContent/Engines/BulkOrders/LargeBOD.cs +++ b/Projects/UOContent/Engines/BulkOrders/LargeBOD.cs @@ -1,170 +1,179 @@ -using Server.Mobiles; - -namespace Server.Engines.BulkOrders -{ - public abstract class LargeBOD : BaseBOD - { - private LargeBulkEntry[] m_Entries; - - public LargeBulkEntry[] Entries - { - get => m_Entries; - set { m_Entries = value; InvalidateProperties(); } - } - - [CommandProperty(AccessLevel.GameMaster)] - public override bool Complete - { - get - { - for (int i = 0; i < m_Entries.Length; ++i) - if (m_Entries[i].Amount < AmountMax) - return false; - - return true; - } - } - - public override int LabelNumber => 1045151; // a bulk order deed - - public LargeBOD(int hue, int amountMax, bool requireExeptional, BulkMaterialType material, LargeBulkEntry[] entries) : base(hue, amountMax, requireExeptional, material) => - m_Entries = entries; - - public LargeBOD() - { - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1060655); // large bulk order - - if (RequireExceptional) - list.Add(1045141); // All items must be exceptional. - - if (Material != BulkMaterialType.None) - list.Add(LargeBODGump.GetMaterialNumberFor(Material)); // All items must be made with x material. - - list.Add(1060656, AmountMax.ToString()); // amount to make: ~1_val~ - - for (int i = 0; i < m_Entries.Length; ++i) - list.Add(1060658 + i, "#{0}\t{1}", m_Entries[i].Details.Number, m_Entries[i].Amount); // ~1_val~: ~2_val~ - } - - public override void OnDoubleClickNotAccessible(Mobile from) - { - OnDoubleClick(from); - } - - public override void OnDoubleClickSecureTrade(Mobile from) - { - OnDoubleClick(from); - } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack) || InSecureTrade || RootParent is PlayerVendor) - from.SendGump(new LargeBODGump(from, this)); - else - from.SendLocalizedMessage(1045156); // You must have the deed in your backpack to use it. - } - - public override void EndCombine(Mobile from, Item item) - { - if (!(item is SmallBOD small)) - { - from.SendLocalizedMessage(1045159); // That is not a bulk order. - return; - } - - LargeBulkEntry entry = null; - - for (int i = 0; i < m_Entries.Length; ++i) - if (m_Entries[i].Details.Type == small.Type) - { - entry = m_Entries[i]; - break; - } - - if (entry == null) - { - from.SendLocalizedMessage(1045160); // That is not a bulk order for this large request. - } - else if (RequireExceptional && !small.RequireExceptional) - { - from.SendLocalizedMessage(1045161); // Both orders must be of exceptional quality. - } - else if (Material >= BulkMaterialType.DullCopper && Material <= BulkMaterialType.Valorite && - small.Material != Material) - { - from.SendLocalizedMessage(1045162); // Both orders must use the same ore type. - } - else if (Material >= BulkMaterialType.Spined && Material <= BulkMaterialType.Barbed && - small.Material != Material) - { - from.SendLocalizedMessage(1049351); // Both orders must use the same leather type. - } - else if (AmountMax != small.AmountMax) - { - from.SendLocalizedMessage(1045163); // The two orders have different requested amounts and cannot be combined. - } - else if (small.AmountCur < small.AmountMax) - { - from.SendLocalizedMessage(1045164); // The order to combine with is not completed. - } - else if (entry.Amount >= AmountMax) - { - from.SendLocalizedMessage( - 1045166); // The maximum amount of requested items have already been combined to this deed. - } - else - { - entry.Amount += small.AmountCur; - small.Delete(); - - from.SendLocalizedMessage(1045165); // The orders have been combined. - from.SendGump(new LargeBODGump(from, this)); - - if (!Complete) - BeginCombine(from); - } - } - - public LargeBOD(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_Entries.Length); - - for (int i = 0; i < m_Entries.Length; ++i) - m_Entries[i].Serialize(writer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 0: - { - m_Entries = new LargeBulkEntry[reader.ReadInt()]; - - for (int i = 0; i < m_Entries.Length; ++i) - m_Entries[i] = new LargeBulkEntry(this, reader); - - break; - } - } - } - } -} +using Server.Mobiles; + +namespace Server.Engines.BulkOrders +{ + public abstract class LargeBOD : BaseBOD + { + private LargeBulkEntry[] m_Entries; + + public LargeBOD( + int hue, int amountMax, bool requireExeptional, BulkMaterialType material, LargeBulkEntry[] entries + ) : base(hue, amountMax, requireExeptional, material) => + m_Entries = entries; + + public LargeBOD() + { + } + + public LargeBOD(Serial serial) : base(serial) + { + } + + public LargeBulkEntry[] Entries + { + get => m_Entries; + set + { + m_Entries = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public override bool Complete + { + get + { + for (var i = 0; i < m_Entries.Length; ++i) + if (m_Entries[i].Amount < AmountMax) + return false; + + return true; + } + } + + public override int LabelNumber => 1045151; // a bulk order deed + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1060655); // large bulk order + + if (RequireExceptional) + list.Add(1045141); // All items must be exceptional. + + if (Material != BulkMaterialType.None) + list.Add(LargeBODGump.GetMaterialNumberFor(Material)); // All items must be made with x material. + + list.Add(1060656, AmountMax.ToString()); // amount to make: ~1_val~ + + for (var i = 0; i < m_Entries.Length; ++i) + list.Add(1060658 + i, "#{0}\t{1}", m_Entries[i].Details.Number, m_Entries[i].Amount); // ~1_val~: ~2_val~ + } + + public override void OnDoubleClickNotAccessible(Mobile from) + { + OnDoubleClick(from); + } + + public override void OnDoubleClickSecureTrade(Mobile from) + { + OnDoubleClick(from); + } + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack) || InSecureTrade || RootParent is PlayerVendor) + from.SendGump(new LargeBODGump(from, this)); + else + from.SendLocalizedMessage(1045156); // You must have the deed in your backpack to use it. + } + + public override void EndCombine(Mobile from, Item item) + { + if (!(item is SmallBOD small)) + { + from.SendLocalizedMessage(1045159); // That is not a bulk order. + return; + } + + LargeBulkEntry entry = null; + + for (var i = 0; i < m_Entries.Length; ++i) + if (m_Entries[i].Details.Type == small.Type) + { + entry = m_Entries[i]; + break; + } + + if (entry == null) + { + from.SendLocalizedMessage(1045160); // That is not a bulk order for this large request. + } + else if (RequireExceptional && !small.RequireExceptional) + { + from.SendLocalizedMessage(1045161); // Both orders must be of exceptional quality. + } + else if (Material >= BulkMaterialType.DullCopper && Material <= BulkMaterialType.Valorite && + small.Material != Material) + { + from.SendLocalizedMessage(1045162); // Both orders must use the same ore type. + } + else if (Material >= BulkMaterialType.Spined && Material <= BulkMaterialType.Barbed && + small.Material != Material) + { + from.SendLocalizedMessage(1049351); // Both orders must use the same leather type. + } + else if (AmountMax != small.AmountMax) + { + from.SendLocalizedMessage( + 1045163 + ); // The two orders have different requested amounts and cannot be combined. + } + else if (small.AmountCur < small.AmountMax) + { + from.SendLocalizedMessage(1045164); // The order to combine with is not completed. + } + else if (entry.Amount >= AmountMax) + { + from.SendLocalizedMessage( + 1045166 + ); // The maximum amount of requested items have already been combined to this deed. + } + else + { + entry.Amount += small.AmountCur; + small.Delete(); + + from.SendLocalizedMessage(1045165); // The orders have been combined. + from.SendGump(new LargeBODGump(from, this)); + + if (!Complete) + BeginCombine(from); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_Entries.Length); + + for (var i = 0; i < m_Entries.Length; ++i) + m_Entries[i].Serialize(writer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 0: + { + m_Entries = new LargeBulkEntry[reader.ReadInt()]; + + for (var i = 0; i < m_Entries.Length; ++i) + m_Entries[i] = new LargeBulkEntry(this, reader); + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/LargeBODAcceptGump.cs b/Projects/UOContent/Engines/BulkOrders/LargeBODAcceptGump.cs index b2d4d658d..264c7440b 100644 --- a/Projects/UOContent/Engines/BulkOrders/LargeBODAcceptGump.cs +++ b/Projects/UOContent/Engines/BulkOrders/LargeBODAcceptGump.cs @@ -1,110 +1,117 @@ -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.BulkOrders -{ - public class LargeBODAcceptGump : Gump - { - private readonly LargeBOD m_Deed; - private readonly Mobile m_From; - - public LargeBODAcceptGump(Mobile from, LargeBOD deed) : base(50, 50) - { - m_From = from; - m_Deed = deed; - - m_From.CloseGump(); - m_From.CloseGump(); - - LargeBulkEntry[] entries = deed.Entries; - - AddPage(0); - - AddBackground(25, 10, 430, 240 + entries.Length * 24, 5054); - - AddImageTiled(33, 20, 413, 221 + entries.Length * 24, 2624); - AddAlphaRegion(33, 20, 413, 221 + entries.Length * 24); - - AddImage(20, 5, 10460); - AddImage(430, 5, 10460); - AddImage(20, 225 + entries.Length * 24, 10460); - AddImage(430, 225 + entries.Length * 24, 10460); - - AddHtmlLocalized(180, 25, 120, 20, 1045134, 0x7FFF); // A large bulk order - - AddHtmlLocalized(40, 48, 350, 20, 1045135, 0x7FFF); // Ah! Thanks for the goods! Would you help me out? - - AddHtmlLocalized(40, 72, 210, 20, 1045138, 0x7FFF); // Amount to make: - AddLabel(250, 72, 1152, deed.AmountMax.ToString()); - - AddHtmlLocalized(40, 96, 120, 20, 1045137, 0x7FFF); // Items requested: - - int y = 120; - - for (int i = 0; i < entries.Length; ++i, y += 24) - AddHtmlLocalized(40, y, 210, 20, entries[i].Details.Number, 0x7FFF); - - if (deed.RequireExceptional || deed.Material != BulkMaterialType.None) - { - AddHtmlLocalized(40, y, 210, 20, 1045140, 0x7FFF); // Special requirements to meet: - y += 24; - - if (deed.RequireExceptional) - { - AddHtmlLocalized(40, y, 350, 20, 1045141, 0x7FFF); // All items must be exceptional. - y += 24; - } - - if (deed.Material != BulkMaterialType.None) - { - AddHtmlLocalized(40, y, 350, 20, GetMaterialNumberFor(deed.Material), 0x7FFF); // All items must be made with x material. - y += 24; - } - } - - AddHtmlLocalized(40, 192 + entries.Length * 24, 350, 20, 1045139, 0x7FFF); // Do you want to accept this order? - - AddButton(100, 216 + entries.Length * 24, 4005, 4007, 1); - AddHtmlLocalized(135, 216 + entries.Length * 24, 120, 20, 1006044, 0x7FFF); // Ok - - AddButton(275, 216 + entries.Length * 24, 4005, 4007, 0); - AddHtmlLocalized(310, 216 + entries.Length * 24, 120, 20, 1011012, 0x7FFF); // CANCEL - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 1) // Ok - { - if (m_From.PlaceInBackpack(m_Deed)) - { - m_From.SendLocalizedMessage(1045152); // The bulk order deed has been placed in your backpack. - } - else - { - m_From.SendLocalizedMessage(1045150); // There is not enough room in your backpack for the deed. - m_Deed.Delete(); - } - } - else - { - m_Deed.Delete(); - } - } - - public override void OnServerClose(NetState owner) - { - if (m_Deed?.Deleted == false) - m_Deed.Delete(); - } - - public static int GetMaterialNumberFor(BulkMaterialType material) - { - if (material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite) - return 1045142 + (material - BulkMaterialType.DullCopper); - if (material >= BulkMaterialType.Spined && material <= BulkMaterialType.Barbed) - return 1049348 + (material - BulkMaterialType.Spined); - - return 0; - } - } -} +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.BulkOrders +{ + public class LargeBODAcceptGump : Gump + { + private readonly LargeBOD m_Deed; + private readonly Mobile m_From; + + public LargeBODAcceptGump(Mobile from, LargeBOD deed) : base(50, 50) + { + m_From = from; + m_Deed = deed; + + m_From.CloseGump(); + m_From.CloseGump(); + + var entries = deed.Entries; + + AddPage(0); + + AddBackground(25, 10, 430, 240 + entries.Length * 24, 5054); + + AddImageTiled(33, 20, 413, 221 + entries.Length * 24, 2624); + AddAlphaRegion(33, 20, 413, 221 + entries.Length * 24); + + AddImage(20, 5, 10460); + AddImage(430, 5, 10460); + AddImage(20, 225 + entries.Length * 24, 10460); + AddImage(430, 225 + entries.Length * 24, 10460); + + AddHtmlLocalized(180, 25, 120, 20, 1045134, 0x7FFF); // A large bulk order + + AddHtmlLocalized(40, 48, 350, 20, 1045135, 0x7FFF); // Ah! Thanks for the goods! Would you help me out? + + AddHtmlLocalized(40, 72, 210, 20, 1045138, 0x7FFF); // Amount to make: + AddLabel(250, 72, 1152, deed.AmountMax.ToString()); + + AddHtmlLocalized(40, 96, 120, 20, 1045137, 0x7FFF); // Items requested: + + var y = 120; + + for (var i = 0; i < entries.Length; ++i, y += 24) + AddHtmlLocalized(40, y, 210, 20, entries[i].Details.Number, 0x7FFF); + + if (deed.RequireExceptional || deed.Material != BulkMaterialType.None) + { + AddHtmlLocalized(40, y, 210, 20, 1045140, 0x7FFF); // Special requirements to meet: + y += 24; + + if (deed.RequireExceptional) + { + AddHtmlLocalized(40, y, 350, 20, 1045141, 0x7FFF); // All items must be exceptional. + y += 24; + } + + if (deed.Material != BulkMaterialType.None) + { + AddHtmlLocalized( + 40, + y, + 350, + 20, + GetMaterialNumberFor(deed.Material), + 0x7FFF + ); // All items must be made with x material. + y += 24; + } + } + + AddHtmlLocalized(40, 192 + entries.Length * 24, 350, 20, 1045139, 0x7FFF); // Do you want to accept this order? + + AddButton(100, 216 + entries.Length * 24, 4005, 4007, 1); + AddHtmlLocalized(135, 216 + entries.Length * 24, 120, 20, 1006044, 0x7FFF); // Ok + + AddButton(275, 216 + entries.Length * 24, 4005, 4007, 0); + AddHtmlLocalized(310, 216 + entries.Length * 24, 120, 20, 1011012, 0x7FFF); // CANCEL + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 1) // Ok + { + if (m_From.PlaceInBackpack(m_Deed)) + { + m_From.SendLocalizedMessage(1045152); // The bulk order deed has been placed in your backpack. + } + else + { + m_From.SendLocalizedMessage(1045150); // There is not enough room in your backpack for the deed. + m_Deed.Delete(); + } + } + else + { + m_Deed.Delete(); + } + } + + public override void OnServerClose(NetState owner) + { + if (m_Deed?.Deleted == false) + m_Deed.Delete(); + } + + public static int GetMaterialNumberFor(BulkMaterialType material) + { + if (material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite) + return 1045142 + (material - BulkMaterialType.DullCopper); + if (material >= BulkMaterialType.Spined && material <= BulkMaterialType.Barbed) + return 1049348 + (material - BulkMaterialType.Spined); + + return 0; + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/LargeBODGump.cs b/Projects/UOContent/Engines/BulkOrders/LargeBODGump.cs index 1f38babc6..0a1809ffd 100644 --- a/Projects/UOContent/Engines/BulkOrders/LargeBODGump.cs +++ b/Projects/UOContent/Engines/BulkOrders/LargeBODGump.cs @@ -1,98 +1,112 @@ -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.BulkOrders -{ - public class LargeBODGump : Gump - { - private readonly LargeBOD m_Deed; - private readonly Mobile m_From; - - public LargeBODGump(Mobile from, LargeBOD deed) : base(25, 25) - { - m_From = from; - m_Deed = deed; - - m_From.CloseGump(); - m_From.CloseGump(); - - LargeBulkEntry[] entries = deed.Entries; - - AddPage(0); - - AddBackground(50, 10, 455, 236 + entries.Length * 24, 5054); - - AddImageTiled(58, 20, 438, 217 + entries.Length * 24, 2624); - AddAlphaRegion(58, 20, 438, 217 + entries.Length * 24); - - AddImage(45, 5, 10460); - AddImage(480, 5, 10460); - AddImage(45, 221 + entries.Length * 24, 10460); - AddImage(480, 221 + entries.Length * 24, 10460); - - AddHtmlLocalized(225, 25, 120, 20, 1045134, 0x7FFF); // A large bulk order - - AddHtmlLocalized(75, 48, 250, 20, 1045138, 0x7FFF); // Amount to make: - AddLabel(275, 48, 1152, deed.AmountMax.ToString()); - - AddHtmlLocalized(75, 72, 120, 20, 1045137, 0x7FFF); // Items requested: - AddHtmlLocalized(275, 76, 200, 20, 1045153, 0x7FFF); // Amount finished: - - int y = 96; - - for (int i = 0; i < entries.Length; ++i) - { - LargeBulkEntry entry = entries[i]; - SmallBulkEntry details = entry.Details; - - AddHtmlLocalized(75, y, 210, 20, details.Number, 0x7FFF); - AddLabel(275, y, 0x480, entry.Amount.ToString()); - - y += 24; - } - - if (deed.RequireExceptional || deed.Material != BulkMaterialType.None) - { - AddHtmlLocalized(75, y, 200, 20, 1045140, 0x7FFF); // Special requirements to meet: - y += 24; - } - - if (deed.RequireExceptional) - { - AddHtmlLocalized(75, y, 300, 20, 1045141, 0x7FFF); // All items must be exceptional. - y += 24; - } - - if (deed.Material != BulkMaterialType.None) - AddHtmlLocalized(75, y, 300, 20, GetMaterialNumberFor(deed.Material), 0x7FFF); // All items must be made with x material. - - AddButton(125, 168 + entries.Length * 24, 4005, 4007, 2); - AddHtmlLocalized(160, 168 + entries.Length * 24, 300, 20, 1045155, 0x7FFF); // Combine this deed with another deed. - - AddButton(125, 192 + entries.Length * 24, 4005, 4007, 1); - AddHtmlLocalized(160, 192 + entries.Length * 24, 120, 20, 1011441, 0x7FFF); // EXIT - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Deed.Deleted || !m_Deed.IsChildOf(m_From.Backpack)) - return; - - if (info.ButtonID == 2) // Combine - { - m_From.SendGump(new LargeBODGump(m_From, m_Deed)); - m_Deed.BeginCombine(m_From); - } - } - - public static int GetMaterialNumberFor(BulkMaterialType material) - { - if (material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite) - return 1045142 + (material - BulkMaterialType.DullCopper); - if (material >= BulkMaterialType.Spined && material <= BulkMaterialType.Barbed) - return 1049348 + (material - BulkMaterialType.Spined); - - return 0; - } - } -} +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.BulkOrders +{ + public class LargeBODGump : Gump + { + private readonly LargeBOD m_Deed; + private readonly Mobile m_From; + + public LargeBODGump(Mobile from, LargeBOD deed) : base(25, 25) + { + m_From = from; + m_Deed = deed; + + m_From.CloseGump(); + m_From.CloseGump(); + + var entries = deed.Entries; + + AddPage(0); + + AddBackground(50, 10, 455, 236 + entries.Length * 24, 5054); + + AddImageTiled(58, 20, 438, 217 + entries.Length * 24, 2624); + AddAlphaRegion(58, 20, 438, 217 + entries.Length * 24); + + AddImage(45, 5, 10460); + AddImage(480, 5, 10460); + AddImage(45, 221 + entries.Length * 24, 10460); + AddImage(480, 221 + entries.Length * 24, 10460); + + AddHtmlLocalized(225, 25, 120, 20, 1045134, 0x7FFF); // A large bulk order + + AddHtmlLocalized(75, 48, 250, 20, 1045138, 0x7FFF); // Amount to make: + AddLabel(275, 48, 1152, deed.AmountMax.ToString()); + + AddHtmlLocalized(75, 72, 120, 20, 1045137, 0x7FFF); // Items requested: + AddHtmlLocalized(275, 76, 200, 20, 1045153, 0x7FFF); // Amount finished: + + var y = 96; + + for (var i = 0; i < entries.Length; ++i) + { + var entry = entries[i]; + var details = entry.Details; + + AddHtmlLocalized(75, y, 210, 20, details.Number, 0x7FFF); + AddLabel(275, y, 0x480, entry.Amount.ToString()); + + y += 24; + } + + if (deed.RequireExceptional || deed.Material != BulkMaterialType.None) + { + AddHtmlLocalized(75, y, 200, 20, 1045140, 0x7FFF); // Special requirements to meet: + y += 24; + } + + if (deed.RequireExceptional) + { + AddHtmlLocalized(75, y, 300, 20, 1045141, 0x7FFF); // All items must be exceptional. + y += 24; + } + + if (deed.Material != BulkMaterialType.None) + AddHtmlLocalized( + 75, + y, + 300, + 20, + GetMaterialNumberFor(deed.Material), + 0x7FFF + ); // All items must be made with x material. + + AddButton(125, 168 + entries.Length * 24, 4005, 4007, 2); + AddHtmlLocalized( + 160, + 168 + entries.Length * 24, + 300, + 20, + 1045155, + 0x7FFF + ); // Combine this deed with another deed. + + AddButton(125, 192 + entries.Length * 24, 4005, 4007, 1); + AddHtmlLocalized(160, 192 + entries.Length * 24, 120, 20, 1011441, 0x7FFF); // EXIT + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Deed.Deleted || !m_Deed.IsChildOf(m_From.Backpack)) + return; + + if (info.ButtonID == 2) // Combine + { + m_From.SendGump(new LargeBODGump(m_From, m_Deed)); + m_Deed.BeginCombine(m_From); + } + } + + public static int GetMaterialNumberFor(BulkMaterialType material) + { + if (material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite) + return 1045142 + (material - BulkMaterialType.DullCopper); + if (material >= BulkMaterialType.Spined && material <= BulkMaterialType.Barbed) + return 1049348 + (material - BulkMaterialType.Spined); + + return 0; + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/LargeBulkEntry.cs b/Projects/UOContent/Engines/BulkOrders/LargeBulkEntry.cs index 985792ad0..9f8934ad3 100644 --- a/Projects/UOContent/Engines/BulkOrders/LargeBulkEntry.cs +++ b/Projects/UOContent/Engines/BulkOrders/LargeBulkEntry.cs @@ -1,117 +1,121 @@ -using System; -using System.Collections.Generic; - -namespace Server.Engines.BulkOrders -{ - public class LargeBulkEntry - { - private int m_Amount; - - public LargeBOD Owner { get; set; } - - public int Amount - { - get => m_Amount; - set { m_Amount = value; Owner?.InvalidateProperties(); } - } - public SmallBulkEntry Details { get; } - - public static SmallBulkEntry[] LargeRing => GetEntries("Blacksmith", "largering"); - - public static SmallBulkEntry[] LargePlate => GetEntries("Blacksmith", "largeplate"); - - public static SmallBulkEntry[] LargeChain => GetEntries("Blacksmith", "largechain"); - - public static SmallBulkEntry[] LargeAxes => GetEntries("Blacksmith", "largeaxes"); - - public static SmallBulkEntry[] LargeFencing => GetEntries("Blacksmith", "largefencing"); - - public static SmallBulkEntry[] LargeMaces => GetEntries("Blacksmith", "largemaces"); - - public static SmallBulkEntry[] LargePolearms => GetEntries("Blacksmith", "largepolearms"); - - public static SmallBulkEntry[] LargeSwords => GetEntries("Blacksmith", "largeswords"); - - public static SmallBulkEntry[] BoneSet => GetEntries("Tailoring", "boneset"); - - public static SmallBulkEntry[] Farmer => GetEntries("Tailoring", "farmer"); - - public static SmallBulkEntry[] FemaleLeatherSet => GetEntries("Tailoring", "femaleleatherset"); - - public static SmallBulkEntry[] FisherGirl => GetEntries("Tailoring", "fishergirl"); - - public static SmallBulkEntry[] Gypsy => GetEntries("Tailoring", "gypsy"); - - public static SmallBulkEntry[] HatSet => GetEntries("Tailoring", "hatset"); - - public static SmallBulkEntry[] Jester => GetEntries("Tailoring", "jester"); - - public static SmallBulkEntry[] Lady => GetEntries("Tailoring", "lady"); - - public static SmallBulkEntry[] MaleLeatherSet => GetEntries("Tailoring", "maleleatherset"); - - public static SmallBulkEntry[] Pirate => GetEntries("Tailoring", "pirate"); - - public static SmallBulkEntry[] ShoeSet => GetEntries("Tailoring", "shoeset"); - - public static SmallBulkEntry[] StuddedSet => GetEntries("Tailoring", "studdedset"); - - public static SmallBulkEntry[] TownCrier => GetEntries("Tailoring", "towncrier"); - - public static SmallBulkEntry[] Wizard => GetEntries("Tailoring", "wizard"); - - private static Dictionary> m_Cache; - - public static SmallBulkEntry[] GetEntries(string type, string name) - { - m_Cache ??= new Dictionary>(); - - if (!m_Cache.TryGetValue(type, out Dictionary table)) - m_Cache[type] = table = new Dictionary(); - - if (!table.TryGetValue(name, out SmallBulkEntry[] entries)) - table[name] = entries = SmallBulkEntry.LoadEntries(type, name); - - return entries; - } - - public static LargeBulkEntry[] ConvertEntries(LargeBOD owner, SmallBulkEntry[] small) - { - LargeBulkEntry[] large = new LargeBulkEntry[small.Length]; - - for (int i = 0; i < small.Length; ++i) - large[i] = new LargeBulkEntry(owner, small[i]); - - return large; - } - - public LargeBulkEntry(LargeBOD owner, SmallBulkEntry details) - { - Owner = owner; - Details = details; - } - - public LargeBulkEntry(LargeBOD owner, IGenericReader reader) - { - Owner = owner; - m_Amount = reader.ReadInt(); - - Type realType = null; - - string type = reader.ReadString(); - - if (type != null) - realType = AssemblyHandler.FindFirstTypeForName(type); - - Details = new SmallBulkEntry(realType, reader.ReadInt(), reader.ReadInt()); - } - - public void Serialize(IGenericWriter writer) - { - writer.Write(m_Amount); - writer.Write(Details.Type?.FullName); - writer.Write(Details.Number); - writer.Write(Details.Graphic); - } - } -} +using System; +using System.Collections.Generic; + +namespace Server.Engines.BulkOrders +{ + public class LargeBulkEntry + { + private static Dictionary> m_Cache; + private int m_Amount; + + public LargeBulkEntry(LargeBOD owner, SmallBulkEntry details) + { + Owner = owner; + Details = details; + } + + public LargeBulkEntry(LargeBOD owner, IGenericReader reader) + { + Owner = owner; + m_Amount = reader.ReadInt(); + + Type realType = null; + + var type = reader.ReadString(); + + if (type != null) + realType = AssemblyHandler.FindFirstTypeForName(type); + + Details = new SmallBulkEntry(realType, reader.ReadInt(), reader.ReadInt()); + } + + public LargeBOD Owner { get; set; } + + public int Amount + { + get => m_Amount; + set + { + m_Amount = value; + Owner?.InvalidateProperties(); + } + } + + public SmallBulkEntry Details { get; } + + public static SmallBulkEntry[] LargeRing => GetEntries("Blacksmith", "largering"); + + public static SmallBulkEntry[] LargePlate => GetEntries("Blacksmith", "largeplate"); + + public static SmallBulkEntry[] LargeChain => GetEntries("Blacksmith", "largechain"); + + public static SmallBulkEntry[] LargeAxes => GetEntries("Blacksmith", "largeaxes"); + + public static SmallBulkEntry[] LargeFencing => GetEntries("Blacksmith", "largefencing"); + + public static SmallBulkEntry[] LargeMaces => GetEntries("Blacksmith", "largemaces"); + + public static SmallBulkEntry[] LargePolearms => GetEntries("Blacksmith", "largepolearms"); + + public static SmallBulkEntry[] LargeSwords => GetEntries("Blacksmith", "largeswords"); + + public static SmallBulkEntry[] BoneSet => GetEntries("Tailoring", "boneset"); + + public static SmallBulkEntry[] Farmer => GetEntries("Tailoring", "farmer"); + + public static SmallBulkEntry[] FemaleLeatherSet => GetEntries("Tailoring", "femaleleatherset"); + + public static SmallBulkEntry[] FisherGirl => GetEntries("Tailoring", "fishergirl"); + + public static SmallBulkEntry[] Gypsy => GetEntries("Tailoring", "gypsy"); + + public static SmallBulkEntry[] HatSet => GetEntries("Tailoring", "hatset"); + + public static SmallBulkEntry[] Jester => GetEntries("Tailoring", "jester"); + + public static SmallBulkEntry[] Lady => GetEntries("Tailoring", "lady"); + + public static SmallBulkEntry[] MaleLeatherSet => GetEntries("Tailoring", "maleleatherset"); + + public static SmallBulkEntry[] Pirate => GetEntries("Tailoring", "pirate"); + + public static SmallBulkEntry[] ShoeSet => GetEntries("Tailoring", "shoeset"); + + public static SmallBulkEntry[] StuddedSet => GetEntries("Tailoring", "studdedset"); + + public static SmallBulkEntry[] TownCrier => GetEntries("Tailoring", "towncrier"); + + public static SmallBulkEntry[] Wizard => GetEntries("Tailoring", "wizard"); + + public static SmallBulkEntry[] GetEntries(string type, string name) + { + m_Cache ??= new Dictionary>(); + + if (!m_Cache.TryGetValue(type, out var table)) + m_Cache[type] = table = new Dictionary(); + + if (!table.TryGetValue(name, out var entries)) + table[name] = entries = SmallBulkEntry.LoadEntries(type, name); + + return entries; + } + + public static LargeBulkEntry[] ConvertEntries(LargeBOD owner, SmallBulkEntry[] small) + { + var large = new LargeBulkEntry[small.Length]; + + for (var i = 0; i < small.Length; ++i) + large[i] = new LargeBulkEntry(owner, small[i]); + + return large; + } + + public void Serialize(IGenericWriter writer) + { + writer.Write(m_Amount); + writer.Write(Details.Type?.FullName); + writer.Write(Details.Number); + writer.Write(Details.Graphic); + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/LargeSmithBOD.cs b/Projects/UOContent/Engines/BulkOrders/LargeSmithBOD.cs index 51af6ebb8..2767902dc 100644 --- a/Projects/UOContent/Engines/BulkOrders/LargeSmithBOD.cs +++ b/Projects/UOContent/Engines/BulkOrders/LargeSmithBOD.cs @@ -1,86 +1,87 @@ -namespace Server.Engines.BulkOrders -{ - public class LargeSmithBOD : LargeBOD - { - public static double[] m_BlacksmithMaterialChances = - { - 0.501953125, // None - 0.250000000, // Dull Copper - 0.125000000, // Shadow Iron - 0.062500000, // Copper - 0.031250000, // Bronze - 0.015625000, // Gold - 0.007812500, // Agapite - 0.003906250, // Verite - 0.001953125 // Valorite - }; - - [Constructible] - public LargeSmithBOD() - { - LargeBulkEntry[] entries; - bool useMaterials = true; - - int rand = Utility.Random(8); - - entries = rand switch - { - 0 => LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeRing), - 1 => LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargePlate), - 2 => LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeChain), - 3 => LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeAxes), - 4 => LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeFencing), - 5 => LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeMaces), - 6 => LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargePolearms), - 7 => LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeSwords), - _ => LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeRing) - }; - - if (rand > 2 && rand < 8) - useMaterials = false; - - int hue = 0x44E; - int amountMax = Utility.RandomList(10, 15, 20, 20); - bool reqExceptional = Utility.RandomDouble() < 0.825; - - BulkMaterialType material = useMaterials ? GetRandomMaterial(BulkMaterialType.DullCopper, m_BlacksmithMaterialChances) - : BulkMaterialType.None; - - Hue = hue; - AmountMax = amountMax; - Entries = entries; - RequireExceptional = reqExceptional; - Material = material; - } - - public LargeSmithBOD(int amountMax, bool reqExceptional, BulkMaterialType mat, LargeBulkEntry[] entries) - : base(0x44E, amountMax, reqExceptional, mat, entries) - { - } - - public LargeSmithBOD(Serial serial) : base(serial) - { - } - - public override int ComputeFame() => SmithRewardCalculator.Instance.ComputeFame(this); - - public override int ComputeGold() => SmithRewardCalculator.Instance.ComputeGold(this); - - public override RewardGroup GetRewardGroup() => - SmithRewardCalculator.Instance.LookupRewards(SmithRewardCalculator.Instance.ComputePoints(this)); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Engines.BulkOrders +{ + public class LargeSmithBOD : LargeBOD + { + public static double[] m_BlacksmithMaterialChances = + { + 0.501953125, // None + 0.250000000, // Dull Copper + 0.125000000, // Shadow Iron + 0.062500000, // Copper + 0.031250000, // Bronze + 0.015625000, // Gold + 0.007812500, // Agapite + 0.003906250, // Verite + 0.001953125 // Valorite + }; + + [Constructible] + public LargeSmithBOD() + { + LargeBulkEntry[] entries; + var useMaterials = true; + + var rand = Utility.Random(8); + + entries = rand switch + { + 0 => LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeRing), + 1 => LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargePlate), + 2 => LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeChain), + 3 => LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeAxes), + 4 => LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeFencing), + 5 => LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeMaces), + 6 => LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargePolearms), + 7 => LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeSwords), + _ => LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.LargeRing) + }; + + if (rand > 2 && rand < 8) + useMaterials = false; + + var hue = 0x44E; + var amountMax = Utility.RandomList(10, 15, 20, 20); + var reqExceptional = Utility.RandomDouble() < 0.825; + + var material = useMaterials + ? GetRandomMaterial(BulkMaterialType.DullCopper, m_BlacksmithMaterialChances) + : BulkMaterialType.None; + + Hue = hue; + AmountMax = amountMax; + Entries = entries; + RequireExceptional = reqExceptional; + Material = material; + } + + public LargeSmithBOD(int amountMax, bool reqExceptional, BulkMaterialType mat, LargeBulkEntry[] entries) + : base(0x44E, amountMax, reqExceptional, mat, entries) + { + } + + public LargeSmithBOD(Serial serial) : base(serial) + { + } + + public override int ComputeFame() => SmithRewardCalculator.Instance.ComputeFame(this); + + public override int ComputeGold() => SmithRewardCalculator.Instance.ComputeGold(this); + + public override RewardGroup GetRewardGroup() => + SmithRewardCalculator.Instance.LookupRewards(SmithRewardCalculator.Instance.ComputePoints(this)); + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/LargeTailorBOD.cs b/Projects/UOContent/Engines/BulkOrders/LargeTailorBOD.cs index 8a2168fb7..3a256a0ad 100644 --- a/Projects/UOContent/Engines/BulkOrders/LargeTailorBOD.cs +++ b/Projects/UOContent/Engines/BulkOrders/LargeTailorBOD.cs @@ -1,114 +1,115 @@ -namespace Server.Engines.BulkOrders -{ - public class LargeTailorBOD : LargeBOD - { - public static double[] m_TailoringMaterialChances = - { - 0.857421875, // None - 0.125000000, // Spined - 0.015625000, // Horned - 0.001953125 // Barbed - }; - - [Constructible] - public LargeTailorBOD() - { - LargeBulkEntry[] entries; - bool useMaterials = false; - - switch (Utility.Random(14)) - { - default: - entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Farmer); - break; - case 1: - entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.FemaleLeatherSet); - useMaterials = true; - break; - case 2: - entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.FisherGirl); - break; - case 3: - entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Gypsy); - break; - case 4: - entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.HatSet); - break; - case 5: - entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Jester); - break; - case 6: - entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Lady); - break; - case 7: - entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.MaleLeatherSet); - useMaterials = true; - break; - case 8: - entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Pirate); - break; - case 9: - entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.ShoeSet); - useMaterials = Core.ML; - break; - case 10: - entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.StuddedSet); - useMaterials = true; - break; - case 11: - entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.TownCrier); - break; - case 12: - entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Wizard); - break; - case 13: - entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.BoneSet); - useMaterials = true; - break; - } - - int hue = 0x483; - int amountMax = Utility.RandomList(10, 15, 20, 20); - bool reqExceptional = Utility.RandomDouble() < 0.825; - - BulkMaterialType material = useMaterials ? GetRandomMaterial(BulkMaterialType.Spined, m_TailoringMaterialChances) - : BulkMaterialType.None; - - Hue = hue; - AmountMax = amountMax; - Entries = entries; - RequireExceptional = reqExceptional; - Material = material; - } - - public LargeTailorBOD(int amountMax, bool reqExceptional, BulkMaterialType mat, LargeBulkEntry[] entries) - : base(0x483, amountMax, reqExceptional, mat, entries) - { - } - - public LargeTailorBOD(Serial serial) : base(serial) - { - } - - public override int ComputeFame() => TailorRewardCalculator.Instance.ComputeFame(this); - - public override int ComputeGold() => TailorRewardCalculator.Instance.ComputeGold(this); - - public override RewardGroup GetRewardGroup() => - TailorRewardCalculator.Instance.LookupRewards(TailorRewardCalculator.Instance.ComputePoints(this)); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Engines.BulkOrders +{ + public class LargeTailorBOD : LargeBOD + { + public static double[] m_TailoringMaterialChances = + { + 0.857421875, // None + 0.125000000, // Spined + 0.015625000, // Horned + 0.001953125 // Barbed + }; + + [Constructible] + public LargeTailorBOD() + { + LargeBulkEntry[] entries; + var useMaterials = false; + + switch (Utility.Random(14)) + { + default: + entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Farmer); + break; + case 1: + entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.FemaleLeatherSet); + useMaterials = true; + break; + case 2: + entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.FisherGirl); + break; + case 3: + entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Gypsy); + break; + case 4: + entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.HatSet); + break; + case 5: + entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Jester); + break; + case 6: + entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Lady); + break; + case 7: + entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.MaleLeatherSet); + useMaterials = true; + break; + case 8: + entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Pirate); + break; + case 9: + entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.ShoeSet); + useMaterials = Core.ML; + break; + case 10: + entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.StuddedSet); + useMaterials = true; + break; + case 11: + entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.TownCrier); + break; + case 12: + entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.Wizard); + break; + case 13: + entries = LargeBulkEntry.ConvertEntries(this, LargeBulkEntry.BoneSet); + useMaterials = true; + break; + } + + var hue = 0x483; + var amountMax = Utility.RandomList(10, 15, 20, 20); + var reqExceptional = Utility.RandomDouble() < 0.825; + + var material = useMaterials + ? GetRandomMaterial(BulkMaterialType.Spined, m_TailoringMaterialChances) + : BulkMaterialType.None; + + Hue = hue; + AmountMax = amountMax; + Entries = entries; + RequireExceptional = reqExceptional; + Material = material; + } + + public LargeTailorBOD(int amountMax, bool reqExceptional, BulkMaterialType mat, LargeBulkEntry[] entries) + : base(0x483, amountMax, reqExceptional, mat, entries) + { + } + + public LargeTailorBOD(Serial serial) : base(serial) + { + } + + public override int ComputeFame() => TailorRewardCalculator.Instance.ComputeFame(this); + + public override int ComputeGold() => TailorRewardCalculator.Instance.ComputeGold(this); + + public override RewardGroup GetRewardGroup() => + TailorRewardCalculator.Instance.LookupRewards(TailorRewardCalculator.Instance.ComputePoints(this)); + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/Rewards.cs b/Projects/UOContent/Engines/BulkOrders/Rewards.cs index c9b5b9615..4a88b8905 100644 --- a/Projects/UOContent/Engines/BulkOrders/Rewards.cs +++ b/Projects/UOContent/Engines/BulkOrders/Rewards.cs @@ -1,706 +1,788 @@ -using System; -using Server.Items; - -namespace Server.Engines.BulkOrders -{ - public delegate Item ConstructCallback(int type); - - public sealed class RewardType - { - public RewardType(int points, params Type[] types) - { - Points = points; - Types = types; - } - - public int Points { get; } - - public Type[] Types { get; } - - public bool Contains(Type type) - { - for (int i = 0; i < Types.Length; ++i) - if (Types[i] == type) - return true; - - return false; - } - } - - public sealed class RewardItem - { - public RewardItem(int weight, ConstructCallback constructor, int type = 0) - { - Weight = weight; - Constructor = constructor; - Type = type; - } - - public int Weight { get; } - - public ConstructCallback Constructor { get; } - - public int Type { get; } - - public Item Construct() - { - try - { - return Constructor(Type); - } - catch - { - return null; - } - } - } - - public sealed class RewardGroup - { - public RewardGroup(int points, params RewardItem[] items) - { - Points = points; - Items = items; - } - - public int Points { get; } - - public RewardItem[] Items { get; } - - public RewardItem AcquireItem() - { - if (Items.Length == 0) - return null; - if (Items.Length == 1) - return Items[0]; - - int totalWeight = 0; - - for (int i = 0; i < Items.Length; ++i) - totalWeight += Items[i].Weight; - - int randomWeight = Utility.Random(totalWeight); - - for (int i = 0; i < Items.Length; ++i) - { - RewardItem item = Items[i]; - - if (randomWeight < item.Weight) - return item; - - randomWeight -= item.Weight; - } - - return null; - } - } - - public abstract class RewardCalculator - { - public RewardGroup[] Groups { get; set; } - - public abstract int ComputePoints(int quantity, bool exceptional, BulkMaterialType material, int itemCount, - Type type); - - public abstract int ComputeGold(int quantity, bool exceptional, BulkMaterialType material, int itemCount, Type type); - - public virtual int ComputeFame(SmallBOD bod) - { - int points = ComputePoints(bod) / 50; - return points * points; - } - - public virtual int ComputeFame(LargeBOD bod) - { - int points = ComputePoints(bod) / 50; - return points * points; - } - - public virtual int ComputePoints(SmallBOD bod) => ComputePoints(bod.AmountMax, bod.RequireExceptional, bod.Material, 1, bod.Type); - - public virtual int ComputePoints(LargeBOD bod) => - ComputePoints(bod.AmountMax, bod.RequireExceptional, bod.Material, bod.Entries.Length, - bod.Entries[0].Details.Type); - - public virtual int ComputeGold(SmallBOD bod) => ComputeGold(bod.AmountMax, bod.RequireExceptional, bod.Material, 1, bod.Type); - - public virtual int ComputeGold(LargeBOD bod) => - ComputeGold(bod.AmountMax, bod.RequireExceptional, bod.Material, bod.Entries.Length, - bod.Entries[0].Details.Type); - - public virtual RewardGroup LookupRewards(int points) - { - for (int i = Groups.Length - 1; i >= 1; --i) - { - RewardGroup group = Groups[i]; - - if (points >= group.Points) - return group; - } - - return Groups[0]; - } - - public virtual int LookupTypePoints(RewardType[] types, Type type) - { - for (int i = 0; i < types.Length; ++i) - if (types[i].Contains(type)) - return types[i].Points; - - return 0; - } - } - - public sealed class SmithRewardCalculator : RewardCalculator - { - private static readonly ConstructCallback SturdyShovel = CreateSturdyShovel; - private static readonly ConstructCallback SturdyPickaxe = CreateSturdyPickaxe; - private static readonly ConstructCallback MiningGloves = CreateMiningGloves; - private static readonly ConstructCallback GargoylesPickaxe = CreateGargoylesPickaxe; - private static readonly ConstructCallback ProspectorsTool = CreateProspectorsTool; - private static readonly ConstructCallback PowderOfTemperament = CreatePowderOfTemperament; - private static readonly ConstructCallback RunicHammer = CreateRunicHammer; - private static readonly ConstructCallback PowerScroll = CreatePowerScroll; - private static readonly ConstructCallback ColoredAnvil = CreateColoredAnvil; - private static readonly ConstructCallback AncientHammer = CreateAncientHammer; - public static readonly SmithRewardCalculator Instance = new SmithRewardCalculator(); - - private static readonly int[][][] m_GoldTable = - { - new[] // 1-part (regular) - { - new[] { 150, 250, 250, 400, 400, 750, 750, 1200, 1200 }, - new[] { 225, 375, 375, 600, 600, 1125, 1125, 1800, 1800 }, - new[] { 300, 500, 750, 800, 1050, 1500, 2250, 2400, 4000 } - }, - new[] // 1-part (exceptional) - { - new[] { 250, 400, 400, 750, 750, 1500, 1500, 3000, 3000 }, - new[] { 375, 600, 600, 1125, 1125, 2250, 2250, 4500, 4500 }, - new[] { 500, 800, 1200, 1500, 2500, 3000, 6000, 6000, 12000 } - }, - new[] // Ringmail (regular) - { - new[] { 3000, 5000, 5000, 7500, 7500, 10000, 10000, 15000, 15000 }, - new[] { 4500, 7500, 7500, 11250, 11500, 15000, 15000, 22500, 22500 }, - new[] { 6000, 10000, 15000, 15000, 20000, 20000, 30000, 30000, 50000 } - }, - new[] // Ringmail (exceptional) - { - new[] { 5000, 10000, 10000, 15000, 15000, 25000, 25000, 50000, 50000 }, - new[] { 7500, 15000, 15000, 22500, 22500, 37500, 37500, 75000, 75000 }, - new[] { 10000, 20000, 30000, 30000, 50000, 50000, 100000, 100000, 200000 } - }, - new[] // Chainmail (regular) - { - new[] { 4000, 7500, 7500, 10000, 10000, 15000, 15000, 25000, 25000 }, - new[] { 6000, 11250, 11250, 15000, 15000, 22500, 22500, 37500, 37500 }, - new[] { 8000, 15000, 20000, 20000, 30000, 30000, 50000, 50000, 100000 } - }, - new[] // Chainmail (exceptional) - { - new[] { 7500, 15000, 15000, 25000, 25000, 50000, 50000, 100000, 100000 }, - new[] { 11250, 22500, 22500, 37500, 37500, 75000, 75000, 150000, 150000 }, - new[] { 15000, 30000, 50000, 50000, 100000, 100000, 200000, 200000, 200000 } - }, - new[] // Platemail (regular) - { - new[] { 5000, 10000, 10000, 15000, 15000, 25000, 25000, 50000, 50000 }, - new[] { 7500, 15000, 15000, 22500, 22500, 37500, 37500, 75000, 75000 }, - new[] { 10000, 20000, 30000, 30000, 50000, 50000, 100000, 100000, 200000 } - }, - new[] // Platemail (exceptional) - { - new[] { 10000, 25000, 25000, 50000, 50000, 100000, 100000, 100000, 100000 }, - new[] { 15000, 37500, 37500, 75000, 75000, 150000, 150000, 150000, 150000 }, - new[] { 20000, 50000, 100000, 100000, 200000, 200000, 200000, 200000, 200000 } - }, - new[] // 2-part weapons (regular) - { - new[] { 3000, 0, 0, 0, 0, 0, 0, 0, 0 }, - new[] { 4500, 0, 0, 0, 0, 0, 0, 0, 0 }, - new[] { 6000, 0, 0, 0, 0, 0, 0, 0, 0 } - }, - new[] // 2-part weapons (exceptional) - { - new[] { 5000, 0, 0, 0, 0, 0, 0, 0, 0 }, - new[] { 7500, 0, 0, 0, 0, 0, 0, 0, 0 }, - new[] { 10000, 0, 0, 0, 0, 0, 0, 0, 0 } - }, - new[] // 5-part weapons (regular) - { - new[] { 4000, 0, 0, 0, 0, 0, 0, 0, 0 }, - new[] { 6000, 0, 0, 0, 0, 0, 0, 0, 0 }, - new[] { 8000, 0, 0, 0, 0, 0, 0, 0, 0 } - }, - new[] // 5-part weapons (exceptional) - { - new[] { 7500, 0, 0, 0, 0, 0, 0, 0, 0 }, - new[] { 11250, 0, 0, 0, 0, 0, 0, 0, 0 }, - new[] { 15000, 0, 0, 0, 0, 0, 0, 0, 0 } - }, - new[] // 6-part weapons (regular) - { - new[] { 4000, 0, 0, 0, 0, 0, 0, 0, 0 }, - new[] { 6000, 0, 0, 0, 0, 0, 0, 0, 0 }, - new[] { 10000, 0, 0, 0, 0, 0, 0, 0, 0 } - }, - new[] // 6-part weapons (exceptional) - { - new[] { 7500, 0, 0, 0, 0, 0, 0, 0, 0 }, - new[] { 11250, 0, 0, 0, 0, 0, 0, 0, 0 }, - new[] { 15000, 0, 0, 0, 0, 0, 0, 0, 0 } - } - }; - - private readonly RewardType[] m_Types = - { - // Armors - new RewardType(200, typeof(RingmailGloves), typeof(RingmailChest), typeof(RingmailArms), typeof(RingmailLegs)), - new RewardType(300, typeof(ChainCoif), typeof(ChainLegs), typeof(ChainChest)), - new RewardType(400, typeof(PlateArms), typeof(PlateLegs), typeof(PlateHelm), typeof(PlateGorget), - typeof(PlateGloves), typeof(PlateChest)), - - // Weapons - new RewardType(200, typeof(Bardiche), typeof(Halberd)), - new RewardType(300, typeof(Dagger), typeof(ShortSpear), typeof(Spear), typeof(WarFork), - typeof(Kryss)), // OSI put the dagger in there. Odd, ain't it. - new RewardType(350, typeof(Axe), typeof(BattleAxe), typeof(DoubleAxe), typeof(ExecutionersAxe), - typeof(LargeBattleAxe), typeof(TwoHandedAxe)), - new RewardType(350, typeof(Broadsword), typeof(Cutlass), typeof(Katana), typeof(Longsword), - typeof(Scimitar), /*typeof( ThinLongsword ),*/ typeof(VikingSword)), - new RewardType(350, typeof(WarAxe), typeof(HammerPick), typeof(Mace), typeof(Maul), typeof(WarHammer), - typeof(WarMace)) - }; - - public SmithRewardCalculator() - { - Groups = new[] - { - new RewardGroup(0, new RewardItem(1, SturdyShovel)), - new RewardGroup(25, new RewardItem(1, SturdyPickaxe)), - new RewardGroup(50, new RewardItem(45, SturdyShovel), new RewardItem(45, SturdyPickaxe), - new RewardItem(10, MiningGloves, 1)), - new RewardGroup(200, new RewardItem(45, GargoylesPickaxe), new RewardItem(45, ProspectorsTool), - new RewardItem(10, MiningGloves, 3)), - new RewardGroup(400, new RewardItem(2, GargoylesPickaxe), new RewardItem(2, ProspectorsTool), - new RewardItem(1, PowderOfTemperament)), - new RewardGroup(450, new RewardItem(9, PowderOfTemperament), new RewardItem(1, MiningGloves, 5)), - new RewardGroup(500, new RewardItem(1, RunicHammer, 1)), - new RewardGroup(550, new RewardItem(3, RunicHammer, 1), new RewardItem(2, RunicHammer, 2)), - new RewardGroup(600, new RewardItem(1, RunicHammer, 2)), - new RewardGroup(625, new RewardItem(3, RunicHammer, 2), new RewardItem(6, PowerScroll, 5), - new RewardItem(1, ColoredAnvil)), - new RewardGroup(650, new RewardItem(1, RunicHammer, 3)), - new RewardGroup(675, new RewardItem(1, ColoredAnvil), new RewardItem(6, PowerScroll, 10), - new RewardItem(3, RunicHammer, 3)), - new RewardGroup(700, new RewardItem(1, RunicHammer, 4)), - new RewardGroup(750, new RewardItem(1, AncientHammer, 10)), - new RewardGroup(800, new RewardItem(1, PowerScroll, 15)), - new RewardGroup(850, new RewardItem(1, AncientHammer, 15)), - new RewardGroup(900, new RewardItem(1, PowerScroll, 20)), - new RewardGroup(950, new RewardItem(1, RunicHammer, 5)), - new RewardGroup(1000, new RewardItem(1, AncientHammer, 30)), - new RewardGroup(1050, new RewardItem(1, RunicHammer, 6)), - new RewardGroup(1100, new RewardItem(1, AncientHammer, 60)), - new RewardGroup(1150, new RewardItem(1, RunicHammer, 7)), - new RewardGroup(1200, new RewardItem(1, RunicHammer, 8)) - }; - } - - public override int ComputePoints(int quantity, bool exceptional, BulkMaterialType material, int itemCount, - Type type) - { - int points = 0; - - if (quantity == 10) - points += 10; - else if (quantity == 15) - points += 25; - else if (quantity == 20) - points += 50; - - if (exceptional) - points += 200; - - if (itemCount > 1) - points += LookupTypePoints(m_Types, type); - - if (material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite) - points += 200 + 50 * (material - BulkMaterialType.DullCopper); - - return points; - } - - private int ComputeType(Type type, int itemCount) - { - // Item count of 1 means it's a small BOD. - if (itemCount == 1) - return 0; - - int typeIdx = 0; - - // Loop through the RewardTypes defined earlier and find the correct one. - for (; typeIdx < 7; ++typeIdx) - if (m_Types[typeIdx].Contains(type)) - break; - - // Types 5, 6 and 7 are Large Weapon BODs with the same rewards. - if (typeIdx > 5) - typeIdx = 5; - - return (typeIdx + 1) * 2; - } - - public override int ComputeGold(int quantity, bool exceptional, BulkMaterialType material, int itemCount, Type type) - { - int[][][] goldTable = m_GoldTable; - - int typeIndex = ComputeType(type, itemCount); - int quanIndex = quantity switch - { - 20 => 2, - 15 => 1, - _ => 0 - }; - - int mtrlIndex = material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite - ? 1 + (material - BulkMaterialType.DullCopper) - : 0; - - if (exceptional) - typeIndex++; - - int gold = goldTable[typeIndex][quanIndex][mtrlIndex]; - - int min = gold * 9 / 10; - int max = gold * 10 / 9; - - return Utility.RandomMinMax(min, max); - } - - private static Item CreateSturdyShovel(int type) => new SturdyShovel(); - - private static Item CreateSturdyPickaxe(int type) => new SturdyPickaxe(); - - private static Item CreateMiningGloves(int type) - { - return type switch - { - 1 => new LeatherGlovesOfMining(1), - 3 => new StuddedGlovesOfMining(3), - 5 => new RingmailGlovesOfMining(5), - _ => throw new InvalidOperationException() - }; - } - - private static Item CreateGargoylesPickaxe(int type) => new GargoylesPickaxe(); - - private static Item CreateProspectorsTool(int type) => new ProspectorsTool(); - - private static Item CreatePowderOfTemperament(int type) => new PowderOfTemperament(); - - private static Item CreateRunicHammer(int type) - { - if (type >= 1 && type <= 8) - return new RunicHammer(CraftResource.Iron + type, Core.AOS ? 55 - type * 5 : 50); - - throw new InvalidOperationException(); - } - - private static Item CreatePowerScroll(int type) - { - if (type == 5 || type == 10 || type == 15 || type == 20) - return new PowerScroll(SkillName.Blacksmith, 100 + type); - - throw new InvalidOperationException(); - } - - private static Item CreateColoredAnvil(int type) => new ColoredAnvil(); - - private static Item CreateAncientHammer(int type) - { - if (type == 10 || type == 15 || type == 30 || type == 60) - return new AncientSmithyHammer(type); - - throw new InvalidOperationException(); - } - } - - public sealed class TailorRewardCalculator : RewardCalculator - { - private static readonly ConstructCallback Cloth = CreateCloth; - private static readonly ConstructCallback Sandals = CreateSandals; - private static readonly ConstructCallback StretchedHide = CreateStretchedHide; - private static readonly ConstructCallback RunicKit = CreateRunicKit; - private static readonly ConstructCallback Tapestry = CreateTapestry; - private static readonly ConstructCallback PowerScroll = CreatePowerScroll; - private static readonly ConstructCallback BearRug = CreateBearRug; - private static readonly ConstructCallback ClothingBlessDeed = CreateCBD; - public static readonly TailorRewardCalculator Instance = new TailorRewardCalculator(); - - private static readonly int[][][] m_AosGoldTable = - { - new[] // 1-part (regular) - { - new[] { 150, 150, 300, 300 }, - new[] { 225, 225, 450, 450 }, - new[] { 300, 400, 600, 750 } - }, - new[] // 1-part (exceptional) - { - new[] { 300, 300, 600, 600 }, - new[] { 450, 450, 900, 900 }, - new[] { 600, 750, 1200, 1800 } - }, - new[] // 4-part (regular) - { - new[] { 4000, 4000, 5000, 5000 }, - new[] { 6000, 6000, 7500, 7500 }, - new[] { 8000, 10000, 10000, 15000 } - }, - new[] // 4-part (exceptional) - { - new[] { 5000, 5000, 7500, 7500 }, - new[] { 7500, 7500, 11250, 11250 }, - new[] { 10000, 15000, 15000, 20000 } - }, - new[] // 5-part (regular) - { - new[] { 5000, 5000, 7500, 7500 }, - new[] { 7500, 7500, 11250, 11250 }, - new[] { 10000, 15000, 15000, 20000 } - }, - new[] // 5-part (exceptional) - { - new[] { 7500, 7500, 10000, 10000 }, - new[] { 11250, 11250, 15000, 15000 }, - new[] { 15000, 20000, 20000, 30000 } - }, - new[] // 6-part (regular) - { - new[] { 7500, 7500, 10000, 10000 }, - new[] { 11250, 11250, 15000, 15000 }, - new[] { 15000, 20000, 20000, 30000 } - }, - new[] // 6-part (exceptional) - { - new[] { 10000, 10000, 15000, 15000 }, - new[] { 15000, 15000, 22500, 22500 }, - new[] { 20000, 30000, 30000, 50000 } - } - }; - - private static readonly int[][][] m_OldGoldTable = - { - new[] // 1-part (regular) - { - new[] { 150, 150, 300, 300 }, - new[] { 225, 225, 450, 450 }, - new[] { 300, 400, 600, 750 } - }, - new[] // 1-part (exceptional) - { - new[] { 300, 300, 600, 600 }, - new[] { 450, 450, 900, 900 }, - new[] { 600, 750, 1200, 1800 } - }, - new[] // 4-part (regular) - { - new[] { 3000, 3000, 4000, 4000 }, - new[] { 4500, 4500, 6000, 6000 }, - new[] { 6000, 8000, 8000, 10000 } - }, - new[] // 4-part (exceptional) - { - new[] { 4000, 4000, 5000, 5000 }, - new[] { 6000, 6000, 7500, 7500 }, - new[] { 8000, 10000, 10000, 15000 } - }, - new[] // 5-part (regular) - { - new[] { 4000, 4000, 5000, 5000 }, - new[] { 6000, 6000, 7500, 7500 }, - new[] { 8000, 10000, 10000, 15000 } - }, - new[] // 5-part (exceptional) - { - new[] { 5000, 5000, 7500, 7500 }, - new[] { 7500, 7500, 11250, 11250 }, - new[] { 10000, 15000, 15000, 20000 } - }, - new[] // 6-part (regular) - { - new[] { 5000, 5000, 7500, 7500 }, - new[] { 7500, 7500, 11250, 11250 }, - new[] { 10000, 15000, 15000, 20000 } - }, - new[] // 6-part (exceptional) - { - new[] { 7500, 7500, 10000, 10000 }, - new[] { 11250, 11250, 15000, 15000 }, - new[] { 15000, 20000, 20000, 30000 } - } - }; - - public TailorRewardCalculator() - { - Groups = new[] - { - new RewardGroup(0, new RewardItem(1, Cloth)), - new RewardGroup(50, new RewardItem(1, Cloth, 1)), - new RewardGroup(100, new RewardItem(1, Cloth, 2)), - new RewardGroup(150, new RewardItem(9, Cloth, 3), new RewardItem(1, Sandals)), - new RewardGroup(200, new RewardItem(4, Cloth, 4), new RewardItem(1, Sandals)), - new RewardGroup(300, new RewardItem(1, StretchedHide)), - new RewardGroup(350, new RewardItem(1, RunicKit, 1)), - new RewardGroup(400, new RewardItem(2, PowerScroll, 5), new RewardItem(3, Tapestry)), - new RewardGroup(450, new RewardItem(1, BearRug)), - new RewardGroup(500, new RewardItem(1, PowerScroll, 10)), - new RewardGroup(550, new RewardItem(1, ClothingBlessDeed)), - new RewardGroup(575, new RewardItem(1, PowerScroll, 15)), - new RewardGroup(600, new RewardItem(1, RunicKit, 2)), - new RewardGroup(650, new RewardItem(1, PowerScroll, 20)), - new RewardGroup(700, new RewardItem(1, RunicKit, 3)) - }; - } - - public override int ComputePoints(int quantity, bool exceptional, BulkMaterialType material, int itemCount, - Type type) - { - int points = 0; - - if (quantity == 10) - points += 10; - else if (quantity == 15) - points += 25; - else if (quantity == 20) - points += 50; - - if (exceptional) - points += 100; - - if (itemCount == 4) - points += 300; - else if (itemCount == 5) - points += 400; - else if (itemCount == 6) - points += 500; - - if (material == BulkMaterialType.Spined) - points += 50; - else if (material == BulkMaterialType.Horned) - points += 100; - else if (material == BulkMaterialType.Barbed) - points += 150; - - return points; - } - - public override int ComputeGold(int quantity, bool exceptional, BulkMaterialType material, int itemCount, Type type) - { - int[][][] goldTable = Core.AOS ? m_AosGoldTable : m_OldGoldTable; - - int typeIndex = itemCount switch - { - 6 => 3, - 5 => 2, - 4 => 1, - _ => 0 - } * 2 + (exceptional ? 1 : 0); - - int quanIndex = quantity switch - { - 20 => 2, - 15 => 1, - _ => 0 - }; - - int mtrlIndex = material switch - { - BulkMaterialType.Barbed => 3, - BulkMaterialType.Horned => 2, - BulkMaterialType.Spined => 1, - _ => 0 - }; - - int gold = goldTable[typeIndex][quanIndex][mtrlIndex]; - - int min = gold * 9 / 10; - int max = gold * 10 / 9; - - return Utility.RandomMinMax(min, max); - } - - private static readonly int[][] m_ClothHues = - { - new[] { 0x483, 0x48C, 0x488, 0x48A }, - new[] { 0x495, 0x48B, 0x486, 0x485 }, - new[] { 0x48D, 0x490, 0x48E, 0x491 }, - new[] { 0x48F, 0x494, 0x484, 0x497 }, - new[] { 0x489, 0x47F, 0x482, 0x47E } - }; - - private static Item CreateCloth(int type) - { - if (type >= 0 && type < m_ClothHues.Length) - return new UncutCloth(100) {Hue = m_ClothHues[type].RandomElement()}; - - throw new InvalidOperationException(); - } - - private static readonly int[] m_SandalHues = - { - 0x489, 0x47F, 0x482, - 0x47E, 0x48F, 0x494, - 0x484, 0x497 - }; - - private static Item CreateSandals(int type) => new Sandals(m_SandalHues.RandomElement()); - - private static Item CreateStretchedHide(int type) => - Utility.Random(4) switch - { - 1 => new SmallStretchedHideSouthDeed(), - 2 => new MediumStretchedHideEastDeed(), - 3 => new MediumStretchedHideSouthDeed(), - _ => new SmallStretchedHideEastDeed() - }; - - private static Item CreateTapestry(int type) => - Utility.Random(4) switch - { - 1 => new LightFlowerTapestrySouthDeed(), - 2 => new DarkFlowerTapestryEastDeed(), - 3 => new DarkFlowerTapestrySouthDeed(), - _ => new LightFlowerTapestryEastDeed() - }; - - private static Item CreateBearRug(int type) => - Utility.Random(4) switch - { - 1 => new BrownBearRugSouthDeed(), - 2 => new PolarBearRugEastDeed(), - 3 => new PolarBearRugSouthDeed(), - _ => new BrownBearRugEastDeed() - }; - - private static Item CreateRunicKit(int type) - { - if (type >= 1 && type <= 3) - return new RunicSewingKit(CraftResource.RegularLeather + type, 60 - type * 15); - - throw new InvalidOperationException(); - } - - private static Item CreatePowerScroll(int type) - { - if (type == 5 || type == 10 || type == 15 || type == 20) - return new PowerScroll(SkillName.Tailoring, 100 + type); - - throw new InvalidOperationException(); - } - - private static Item CreateCBD(int type) => new ClothingBlessDeed(); - } -} +using System; +using Server.Items; + +namespace Server.Engines.BulkOrders +{ + public delegate Item ConstructCallback(int type); + + public sealed class RewardType + { + public RewardType(int points, params Type[] types) + { + Points = points; + Types = types; + } + + public int Points { get; } + + public Type[] Types { get; } + + public bool Contains(Type type) + { + for (var i = 0; i < Types.Length; ++i) + if (Types[i] == type) + return true; + + return false; + } + } + + public sealed class RewardItem + { + public RewardItem(int weight, ConstructCallback constructor, int type = 0) + { + Weight = weight; + Constructor = constructor; + Type = type; + } + + public int Weight { get; } + + public ConstructCallback Constructor { get; } + + public int Type { get; } + + public Item Construct() + { + try + { + return Constructor(Type); + } + catch + { + return null; + } + } + } + + public sealed class RewardGroup + { + public RewardGroup(int points, params RewardItem[] items) + { + Points = points; + Items = items; + } + + public int Points { get; } + + public RewardItem[] Items { get; } + + public RewardItem AcquireItem() + { + if (Items.Length == 0) + return null; + if (Items.Length == 1) + return Items[0]; + + var totalWeight = 0; + + for (var i = 0; i < Items.Length; ++i) + totalWeight += Items[i].Weight; + + var randomWeight = Utility.Random(totalWeight); + + for (var i = 0; i < Items.Length; ++i) + { + var item = Items[i]; + + if (randomWeight < item.Weight) + return item; + + randomWeight -= item.Weight; + } + + return null; + } + } + + public abstract class RewardCalculator + { + public RewardGroup[] Groups { get; set; } + + public abstract int ComputePoints( + int quantity, bool exceptional, BulkMaterialType material, int itemCount, + Type type + ); + + public abstract int ComputeGold(int quantity, bool exceptional, BulkMaterialType material, int itemCount, Type type); + + public virtual int ComputeFame(SmallBOD bod) + { + var points = ComputePoints(bod) / 50; + return points * points; + } + + public virtual int ComputeFame(LargeBOD bod) + { + var points = ComputePoints(bod) / 50; + return points * points; + } + + public virtual int ComputePoints(SmallBOD bod) => ComputePoints( + bod.AmountMax, + bod.RequireExceptional, + bod.Material, + 1, + bod.Type + ); + + public virtual int ComputePoints(LargeBOD bod) => + ComputePoints( + bod.AmountMax, + bod.RequireExceptional, + bod.Material, + bod.Entries.Length, + bod.Entries[0].Details.Type + ); + + public virtual int ComputeGold(SmallBOD bod) => ComputeGold( + bod.AmountMax, + bod.RequireExceptional, + bod.Material, + 1, + bod.Type + ); + + public virtual int ComputeGold(LargeBOD bod) => + ComputeGold( + bod.AmountMax, + bod.RequireExceptional, + bod.Material, + bod.Entries.Length, + bod.Entries[0].Details.Type + ); + + public virtual RewardGroup LookupRewards(int points) + { + for (var i = Groups.Length - 1; i >= 1; --i) + { + var group = Groups[i]; + + if (points >= group.Points) + return group; + } + + return Groups[0]; + } + + public virtual int LookupTypePoints(RewardType[] types, Type type) + { + for (var i = 0; i < types.Length; ++i) + if (types[i].Contains(type)) + return types[i].Points; + + return 0; + } + } + + public sealed class SmithRewardCalculator : RewardCalculator + { + private static readonly ConstructCallback SturdyShovel = CreateSturdyShovel; + private static readonly ConstructCallback SturdyPickaxe = CreateSturdyPickaxe; + private static readonly ConstructCallback MiningGloves = CreateMiningGloves; + private static readonly ConstructCallback GargoylesPickaxe = CreateGargoylesPickaxe; + private static readonly ConstructCallback ProspectorsTool = CreateProspectorsTool; + private static readonly ConstructCallback PowderOfTemperament = CreatePowderOfTemperament; + private static readonly ConstructCallback RunicHammer = CreateRunicHammer; + private static readonly ConstructCallback PowerScroll = CreatePowerScroll; + private static readonly ConstructCallback ColoredAnvil = CreateColoredAnvil; + private static readonly ConstructCallback AncientHammer = CreateAncientHammer; + public static readonly SmithRewardCalculator Instance = new SmithRewardCalculator(); + + private static readonly int[][][] m_GoldTable = + { + new[] // 1-part (regular) + { + new[] { 150, 250, 250, 400, 400, 750, 750, 1200, 1200 }, + new[] { 225, 375, 375, 600, 600, 1125, 1125, 1800, 1800 }, + new[] { 300, 500, 750, 800, 1050, 1500, 2250, 2400, 4000 } + }, + new[] // 1-part (exceptional) + { + new[] { 250, 400, 400, 750, 750, 1500, 1500, 3000, 3000 }, + new[] { 375, 600, 600, 1125, 1125, 2250, 2250, 4500, 4500 }, + new[] { 500, 800, 1200, 1500, 2500, 3000, 6000, 6000, 12000 } + }, + new[] // Ringmail (regular) + { + new[] { 3000, 5000, 5000, 7500, 7500, 10000, 10000, 15000, 15000 }, + new[] { 4500, 7500, 7500, 11250, 11500, 15000, 15000, 22500, 22500 }, + new[] { 6000, 10000, 15000, 15000, 20000, 20000, 30000, 30000, 50000 } + }, + new[] // Ringmail (exceptional) + { + new[] { 5000, 10000, 10000, 15000, 15000, 25000, 25000, 50000, 50000 }, + new[] { 7500, 15000, 15000, 22500, 22500, 37500, 37500, 75000, 75000 }, + new[] { 10000, 20000, 30000, 30000, 50000, 50000, 100000, 100000, 200000 } + }, + new[] // Chainmail (regular) + { + new[] { 4000, 7500, 7500, 10000, 10000, 15000, 15000, 25000, 25000 }, + new[] { 6000, 11250, 11250, 15000, 15000, 22500, 22500, 37500, 37500 }, + new[] { 8000, 15000, 20000, 20000, 30000, 30000, 50000, 50000, 100000 } + }, + new[] // Chainmail (exceptional) + { + new[] { 7500, 15000, 15000, 25000, 25000, 50000, 50000, 100000, 100000 }, + new[] { 11250, 22500, 22500, 37500, 37500, 75000, 75000, 150000, 150000 }, + new[] { 15000, 30000, 50000, 50000, 100000, 100000, 200000, 200000, 200000 } + }, + new[] // Platemail (regular) + { + new[] { 5000, 10000, 10000, 15000, 15000, 25000, 25000, 50000, 50000 }, + new[] { 7500, 15000, 15000, 22500, 22500, 37500, 37500, 75000, 75000 }, + new[] { 10000, 20000, 30000, 30000, 50000, 50000, 100000, 100000, 200000 } + }, + new[] // Platemail (exceptional) + { + new[] { 10000, 25000, 25000, 50000, 50000, 100000, 100000, 100000, 100000 }, + new[] { 15000, 37500, 37500, 75000, 75000, 150000, 150000, 150000, 150000 }, + new[] { 20000, 50000, 100000, 100000, 200000, 200000, 200000, 200000, 200000 } + }, + new[] // 2-part weapons (regular) + { + new[] { 3000, 0, 0, 0, 0, 0, 0, 0, 0 }, + new[] { 4500, 0, 0, 0, 0, 0, 0, 0, 0 }, + new[] { 6000, 0, 0, 0, 0, 0, 0, 0, 0 } + }, + new[] // 2-part weapons (exceptional) + { + new[] { 5000, 0, 0, 0, 0, 0, 0, 0, 0 }, + new[] { 7500, 0, 0, 0, 0, 0, 0, 0, 0 }, + new[] { 10000, 0, 0, 0, 0, 0, 0, 0, 0 } + }, + new[] // 5-part weapons (regular) + { + new[] { 4000, 0, 0, 0, 0, 0, 0, 0, 0 }, + new[] { 6000, 0, 0, 0, 0, 0, 0, 0, 0 }, + new[] { 8000, 0, 0, 0, 0, 0, 0, 0, 0 } + }, + new[] // 5-part weapons (exceptional) + { + new[] { 7500, 0, 0, 0, 0, 0, 0, 0, 0 }, + new[] { 11250, 0, 0, 0, 0, 0, 0, 0, 0 }, + new[] { 15000, 0, 0, 0, 0, 0, 0, 0, 0 } + }, + new[] // 6-part weapons (regular) + { + new[] { 4000, 0, 0, 0, 0, 0, 0, 0, 0 }, + new[] { 6000, 0, 0, 0, 0, 0, 0, 0, 0 }, + new[] { 10000, 0, 0, 0, 0, 0, 0, 0, 0 } + }, + new[] // 6-part weapons (exceptional) + { + new[] { 7500, 0, 0, 0, 0, 0, 0, 0, 0 }, + new[] { 11250, 0, 0, 0, 0, 0, 0, 0, 0 }, + new[] { 15000, 0, 0, 0, 0, 0, 0, 0, 0 } + } + }; + + private readonly RewardType[] m_Types = + { + // Armors + new RewardType(200, typeof(RingmailGloves), typeof(RingmailChest), typeof(RingmailArms), typeof(RingmailLegs)), + new RewardType(300, typeof(ChainCoif), typeof(ChainLegs), typeof(ChainChest)), + new RewardType( + 400, + typeof(PlateArms), + typeof(PlateLegs), + typeof(PlateHelm), + typeof(PlateGorget), + typeof(PlateGloves), + typeof(PlateChest) + ), + + // Weapons + new RewardType(200, typeof(Bardiche), typeof(Halberd)), + new RewardType( + 300, + typeof(Dagger), + typeof(ShortSpear), + typeof(Spear), + typeof(WarFork), + typeof(Kryss) + ), // OSI put the dagger in there. Odd, ain't it. + new RewardType( + 350, + typeof(Axe), + typeof(BattleAxe), + typeof(DoubleAxe), + typeof(ExecutionersAxe), + typeof(LargeBattleAxe), + typeof(TwoHandedAxe) + ), + new RewardType( + 350, + typeof(Broadsword), + typeof(Cutlass), + typeof(Katana), + typeof(Longsword), + typeof(Scimitar), /*typeof( ThinLongsword ),*/ + typeof(VikingSword) + ), + new RewardType( + 350, + typeof(WarAxe), + typeof(HammerPick), + typeof(Mace), + typeof(Maul), + typeof(WarHammer), + typeof(WarMace) + ) + }; + + public SmithRewardCalculator() + { + Groups = new[] + { + new RewardGroup(0, new RewardItem(1, SturdyShovel)), + new RewardGroup(25, new RewardItem(1, SturdyPickaxe)), + new RewardGroup( + 50, + new RewardItem(45, SturdyShovel), + new RewardItem(45, SturdyPickaxe), + new RewardItem(10, MiningGloves, 1) + ), + new RewardGroup( + 200, + new RewardItem(45, GargoylesPickaxe), + new RewardItem(45, ProspectorsTool), + new RewardItem(10, MiningGloves, 3) + ), + new RewardGroup( + 400, + new RewardItem(2, GargoylesPickaxe), + new RewardItem(2, ProspectorsTool), + new RewardItem(1, PowderOfTemperament) + ), + new RewardGroup(450, new RewardItem(9, PowderOfTemperament), new RewardItem(1, MiningGloves, 5)), + new RewardGroup(500, new RewardItem(1, RunicHammer, 1)), + new RewardGroup(550, new RewardItem(3, RunicHammer, 1), new RewardItem(2, RunicHammer, 2)), + new RewardGroup(600, new RewardItem(1, RunicHammer, 2)), + new RewardGroup( + 625, + new RewardItem(3, RunicHammer, 2), + new RewardItem(6, PowerScroll, 5), + new RewardItem(1, ColoredAnvil) + ), + new RewardGroup(650, new RewardItem(1, RunicHammer, 3)), + new RewardGroup( + 675, + new RewardItem(1, ColoredAnvil), + new RewardItem(6, PowerScroll, 10), + new RewardItem(3, RunicHammer, 3) + ), + new RewardGroup(700, new RewardItem(1, RunicHammer, 4)), + new RewardGroup(750, new RewardItem(1, AncientHammer, 10)), + new RewardGroup(800, new RewardItem(1, PowerScroll, 15)), + new RewardGroup(850, new RewardItem(1, AncientHammer, 15)), + new RewardGroup(900, new RewardItem(1, PowerScroll, 20)), + new RewardGroup(950, new RewardItem(1, RunicHammer, 5)), + new RewardGroup(1000, new RewardItem(1, AncientHammer, 30)), + new RewardGroup(1050, new RewardItem(1, RunicHammer, 6)), + new RewardGroup(1100, new RewardItem(1, AncientHammer, 60)), + new RewardGroup(1150, new RewardItem(1, RunicHammer, 7)), + new RewardGroup(1200, new RewardItem(1, RunicHammer, 8)) + }; + } + + public override int ComputePoints( + int quantity, bool exceptional, BulkMaterialType material, int itemCount, + Type type + ) + { + var points = 0; + + if (quantity == 10) + points += 10; + else if (quantity == 15) + points += 25; + else if (quantity == 20) + points += 50; + + if (exceptional) + points += 200; + + if (itemCount > 1) + points += LookupTypePoints(m_Types, type); + + if (material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite) + points += 200 + 50 * (material - BulkMaterialType.DullCopper); + + return points; + } + + private int ComputeType(Type type, int itemCount) + { + // Item count of 1 means it's a small BOD. + if (itemCount == 1) + return 0; + + var typeIdx = 0; + + // Loop through the RewardTypes defined earlier and find the correct one. + for (; typeIdx < 7; ++typeIdx) + if (m_Types[typeIdx].Contains(type)) + break; + + // Types 5, 6 and 7 are Large Weapon BODs with the same rewards. + if (typeIdx > 5) + typeIdx = 5; + + return (typeIdx + 1) * 2; + } + + public override int ComputeGold(int quantity, bool exceptional, BulkMaterialType material, int itemCount, Type type) + { + var goldTable = m_GoldTable; + + var typeIndex = ComputeType(type, itemCount); + var quanIndex = quantity switch + { + 20 => 2, + 15 => 1, + _ => 0 + }; + + var mtrlIndex = material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite + ? 1 + (material - BulkMaterialType.DullCopper) + : 0; + + if (exceptional) + typeIndex++; + + var gold = goldTable[typeIndex][quanIndex][mtrlIndex]; + + var min = gold * 9 / 10; + var max = gold * 10 / 9; + + return Utility.RandomMinMax(min, max); + } + + private static Item CreateSturdyShovel(int type) => new SturdyShovel(); + + private static Item CreateSturdyPickaxe(int type) => new SturdyPickaxe(); + + private static Item CreateMiningGloves(int type) + { + return type switch + { + 1 => new LeatherGlovesOfMining(1), + 3 => new StuddedGlovesOfMining(3), + 5 => new RingmailGlovesOfMining(5), + _ => throw new InvalidOperationException() + }; + } + + private static Item CreateGargoylesPickaxe(int type) => new GargoylesPickaxe(); + + private static Item CreateProspectorsTool(int type) => new ProspectorsTool(); + + private static Item CreatePowderOfTemperament(int type) => new PowderOfTemperament(); + + private static Item CreateRunicHammer(int type) + { + if (type >= 1 && type <= 8) + return new RunicHammer(CraftResource.Iron + type, Core.AOS ? 55 - type * 5 : 50); + + throw new InvalidOperationException(); + } + + private static Item CreatePowerScroll(int type) + { + if (type == 5 || type == 10 || type == 15 || type == 20) + return new PowerScroll(SkillName.Blacksmith, 100 + type); + + throw new InvalidOperationException(); + } + + private static Item CreateColoredAnvil(int type) => new ColoredAnvil(); + + private static Item CreateAncientHammer(int type) + { + if (type == 10 || type == 15 || type == 30 || type == 60) + return new AncientSmithyHammer(type); + + throw new InvalidOperationException(); + } + } + + public sealed class TailorRewardCalculator : RewardCalculator + { + private static readonly ConstructCallback Cloth = CreateCloth; + private static readonly ConstructCallback Sandals = CreateSandals; + private static readonly ConstructCallback StretchedHide = CreateStretchedHide; + private static readonly ConstructCallback RunicKit = CreateRunicKit; + private static readonly ConstructCallback Tapestry = CreateTapestry; + private static readonly ConstructCallback PowerScroll = CreatePowerScroll; + private static readonly ConstructCallback BearRug = CreateBearRug; + private static readonly ConstructCallback ClothingBlessDeed = CreateCBD; + public static readonly TailorRewardCalculator Instance = new TailorRewardCalculator(); + + private static readonly int[][][] m_AosGoldTable = + { + new[] // 1-part (regular) + { + new[] { 150, 150, 300, 300 }, + new[] { 225, 225, 450, 450 }, + new[] { 300, 400, 600, 750 } + }, + new[] // 1-part (exceptional) + { + new[] { 300, 300, 600, 600 }, + new[] { 450, 450, 900, 900 }, + new[] { 600, 750, 1200, 1800 } + }, + new[] // 4-part (regular) + { + new[] { 4000, 4000, 5000, 5000 }, + new[] { 6000, 6000, 7500, 7500 }, + new[] { 8000, 10000, 10000, 15000 } + }, + new[] // 4-part (exceptional) + { + new[] { 5000, 5000, 7500, 7500 }, + new[] { 7500, 7500, 11250, 11250 }, + new[] { 10000, 15000, 15000, 20000 } + }, + new[] // 5-part (regular) + { + new[] { 5000, 5000, 7500, 7500 }, + new[] { 7500, 7500, 11250, 11250 }, + new[] { 10000, 15000, 15000, 20000 } + }, + new[] // 5-part (exceptional) + { + new[] { 7500, 7500, 10000, 10000 }, + new[] { 11250, 11250, 15000, 15000 }, + new[] { 15000, 20000, 20000, 30000 } + }, + new[] // 6-part (regular) + { + new[] { 7500, 7500, 10000, 10000 }, + new[] { 11250, 11250, 15000, 15000 }, + new[] { 15000, 20000, 20000, 30000 } + }, + new[] // 6-part (exceptional) + { + new[] { 10000, 10000, 15000, 15000 }, + new[] { 15000, 15000, 22500, 22500 }, + new[] { 20000, 30000, 30000, 50000 } + } + }; + + private static readonly int[][][] m_OldGoldTable = + { + new[] // 1-part (regular) + { + new[] { 150, 150, 300, 300 }, + new[] { 225, 225, 450, 450 }, + new[] { 300, 400, 600, 750 } + }, + new[] // 1-part (exceptional) + { + new[] { 300, 300, 600, 600 }, + new[] { 450, 450, 900, 900 }, + new[] { 600, 750, 1200, 1800 } + }, + new[] // 4-part (regular) + { + new[] { 3000, 3000, 4000, 4000 }, + new[] { 4500, 4500, 6000, 6000 }, + new[] { 6000, 8000, 8000, 10000 } + }, + new[] // 4-part (exceptional) + { + new[] { 4000, 4000, 5000, 5000 }, + new[] { 6000, 6000, 7500, 7500 }, + new[] { 8000, 10000, 10000, 15000 } + }, + new[] // 5-part (regular) + { + new[] { 4000, 4000, 5000, 5000 }, + new[] { 6000, 6000, 7500, 7500 }, + new[] { 8000, 10000, 10000, 15000 } + }, + new[] // 5-part (exceptional) + { + new[] { 5000, 5000, 7500, 7500 }, + new[] { 7500, 7500, 11250, 11250 }, + new[] { 10000, 15000, 15000, 20000 } + }, + new[] // 6-part (regular) + { + new[] { 5000, 5000, 7500, 7500 }, + new[] { 7500, 7500, 11250, 11250 }, + new[] { 10000, 15000, 15000, 20000 } + }, + new[] // 6-part (exceptional) + { + new[] { 7500, 7500, 10000, 10000 }, + new[] { 11250, 11250, 15000, 15000 }, + new[] { 15000, 20000, 20000, 30000 } + } + }; + + private static readonly int[][] m_ClothHues = + { + new[] { 0x483, 0x48C, 0x488, 0x48A }, + new[] { 0x495, 0x48B, 0x486, 0x485 }, + new[] { 0x48D, 0x490, 0x48E, 0x491 }, + new[] { 0x48F, 0x494, 0x484, 0x497 }, + new[] { 0x489, 0x47F, 0x482, 0x47E } + }; + + private static readonly int[] m_SandalHues = + { + 0x489, 0x47F, 0x482, + 0x47E, 0x48F, 0x494, + 0x484, 0x497 + }; + + public TailorRewardCalculator() + { + Groups = new[] + { + new RewardGroup(0, new RewardItem(1, Cloth)), + new RewardGroup(50, new RewardItem(1, Cloth, 1)), + new RewardGroup(100, new RewardItem(1, Cloth, 2)), + new RewardGroup(150, new RewardItem(9, Cloth, 3), new RewardItem(1, Sandals)), + new RewardGroup(200, new RewardItem(4, Cloth, 4), new RewardItem(1, Sandals)), + new RewardGroup(300, new RewardItem(1, StretchedHide)), + new RewardGroup(350, new RewardItem(1, RunicKit, 1)), + new RewardGroup(400, new RewardItem(2, PowerScroll, 5), new RewardItem(3, Tapestry)), + new RewardGroup(450, new RewardItem(1, BearRug)), + new RewardGroup(500, new RewardItem(1, PowerScroll, 10)), + new RewardGroup(550, new RewardItem(1, ClothingBlessDeed)), + new RewardGroup(575, new RewardItem(1, PowerScroll, 15)), + new RewardGroup(600, new RewardItem(1, RunicKit, 2)), + new RewardGroup(650, new RewardItem(1, PowerScroll, 20)), + new RewardGroup(700, new RewardItem(1, RunicKit, 3)) + }; + } + + public override int ComputePoints( + int quantity, bool exceptional, BulkMaterialType material, int itemCount, + Type type + ) + { + var points = 0; + + if (quantity == 10) + points += 10; + else if (quantity == 15) + points += 25; + else if (quantity == 20) + points += 50; + + if (exceptional) + points += 100; + + if (itemCount == 4) + points += 300; + else if (itemCount == 5) + points += 400; + else if (itemCount == 6) + points += 500; + + if (material == BulkMaterialType.Spined) + points += 50; + else if (material == BulkMaterialType.Horned) + points += 100; + else if (material == BulkMaterialType.Barbed) + points += 150; + + return points; + } + + public override int ComputeGold(int quantity, bool exceptional, BulkMaterialType material, int itemCount, Type type) + { + var goldTable = Core.AOS ? m_AosGoldTable : m_OldGoldTable; + + var typeIndex = itemCount switch + { + 6 => 3, + 5 => 2, + 4 => 1, + _ => 0 + } * 2 + (exceptional ? 1 : 0); + + var quanIndex = quantity switch + { + 20 => 2, + 15 => 1, + _ => 0 + }; + + var mtrlIndex = material switch + { + BulkMaterialType.Barbed => 3, + BulkMaterialType.Horned => 2, + BulkMaterialType.Spined => 1, + _ => 0 + }; + + var gold = goldTable[typeIndex][quanIndex][mtrlIndex]; + + var min = gold * 9 / 10; + var max = gold * 10 / 9; + + return Utility.RandomMinMax(min, max); + } + + private static Item CreateCloth(int type) + { + if (type >= 0 && type < m_ClothHues.Length) + return new UncutCloth(100) { Hue = m_ClothHues[type].RandomElement() }; + + throw new InvalidOperationException(); + } + + private static Item CreateSandals(int type) => new Sandals(m_SandalHues.RandomElement()); + + private static Item CreateStretchedHide(int type) => + Utility.Random(4) switch + { + 1 => new SmallStretchedHideSouthDeed(), + 2 => new MediumStretchedHideEastDeed(), + 3 => new MediumStretchedHideSouthDeed(), + _ => new SmallStretchedHideEastDeed() + }; + + private static Item CreateTapestry(int type) => + Utility.Random(4) switch + { + 1 => new LightFlowerTapestrySouthDeed(), + 2 => new DarkFlowerTapestryEastDeed(), + 3 => new DarkFlowerTapestrySouthDeed(), + _ => new LightFlowerTapestryEastDeed() + }; + + private static Item CreateBearRug(int type) => + Utility.Random(4) switch + { + 1 => new BrownBearRugSouthDeed(), + 2 => new PolarBearRugEastDeed(), + 3 => new PolarBearRugSouthDeed(), + _ => new BrownBearRugEastDeed() + }; + + private static Item CreateRunicKit(int type) + { + if (type >= 1 && type <= 3) + return new RunicSewingKit(CraftResource.RegularLeather + type, 60 - type * 15); + + throw new InvalidOperationException(); + } + + private static Item CreatePowerScroll(int type) + { + if (type == 5 || type == 10 || type == 15 || type == 20) + return new PowerScroll(SkillName.Tailoring, 100 + type); + + throw new InvalidOperationException(); + } + + private static Item CreateCBD(int type) => new ClothingBlessDeed(); + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/SmallBOD.cs b/Projects/UOContent/Engines/BulkOrders/SmallBOD.cs index 822f4062f..4c2afa6a9 100644 --- a/Projects/UOContent/Engines/BulkOrders/SmallBOD.cs +++ b/Projects/UOContent/Engines/BulkOrders/SmallBOD.cs @@ -1,212 +1,215 @@ -using System; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.BulkOrders -{ - public abstract class SmallBOD : BaseBOD - { - private int m_AmountCur; - private int m_Number; - - public SmallBOD(int hue, int amountCur, int amountMax, Type type, int number, int graphic, bool requireExeptional, - BulkMaterialType material) : base(hue, amountMax, requireExeptional, material) - { - Type = type; - Graphic = graphic; - m_AmountCur = amountCur; - m_Number = number; - } - - public SmallBOD() - { - } - - public SmallBOD(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int AmountCur - { - get => m_AmountCur; - set - { - m_AmountCur = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Type Type { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Number - { - get => m_Number; - set - { - m_Number = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Graphic { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public override bool Complete => m_AmountCur == AmountMax; - - public override int LabelNumber => 1045151; // a bulk order deed - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1060654); // small bulk order - - if (RequireExceptional) - list.Add(1045141); // All items must be exceptional. - - if (Material != BulkMaterialType.None) - list.Add(SmallBODGump.GetMaterialNumberFor(Material)); // All items must be made with x material. - - list.Add(1060656, AmountMax.ToString()); // amount to make: ~1_val~ - list.Add(1060658, "#{0}\t{1}", m_Number, m_AmountCur); // ~1_val~: ~2_val~ - } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack) || InSecureTrade || RootParent is PlayerVendor) - from.SendGump(new SmallBODGump(from, this)); - else - from.SendLocalizedMessage(1045156); // You must have the deed in your backpack to use it. - } - - public override void OnDoubleClickNotAccessible(Mobile from) - { - OnDoubleClick(from); - } - - public override void OnDoubleClickSecureTrade(Mobile from) - { - OnDoubleClick(from); - } - - public static BulkMaterialType GetMaterial(CraftResource resource) - { - return resource switch - { - CraftResource.DullCopper => BulkMaterialType.DullCopper, - CraftResource.ShadowIron => BulkMaterialType.ShadowIron, - CraftResource.Copper => BulkMaterialType.Copper, - CraftResource.Bronze => BulkMaterialType.Bronze, - CraftResource.Gold => BulkMaterialType.Gold, - CraftResource.Agapite => BulkMaterialType.Agapite, - CraftResource.Verite => BulkMaterialType.Verite, - CraftResource.Valorite => BulkMaterialType.Valorite, - CraftResource.SpinedLeather => BulkMaterialType.Spined, - CraftResource.HornedLeather => BulkMaterialType.Horned, - CraftResource.BarbedLeather => BulkMaterialType.Barbed, - _ => BulkMaterialType.None - }; - } - - public override void EndCombine(Mobile from, Item item) - { - Type objectType = item.GetType(); - - if (m_AmountCur >= AmountMax) - { - from.SendLocalizedMessage( - 1045166); // The maximum amount of requested items have already been combined to this deed. - } - else if (Type == null || (objectType != Type && !objectType.IsSubclassOf(Type)) || - (!(item is BaseWeapon) && !(item is BaseArmor) && !(item is BaseClothing))) - { - from.SendLocalizedMessage(1045169); // The item is not in the request. - } - else - { - BaseArmor armor = item as BaseArmor; - BaseClothing clothing = item as BaseClothing; - - BulkMaterialType material = GetMaterial(armor?.Resource ?? clothing?.Resource ?? CraftResource.None); - - if (Material >= BulkMaterialType.DullCopper && Material <= BulkMaterialType.Valorite && - material != Material) - { - from.SendLocalizedMessage(1045168); // The item is not made from the requested ore. - } - else if (Material >= BulkMaterialType.Spined && Material <= BulkMaterialType.Barbed && - material != Material) - { - from.SendLocalizedMessage(1049352); // The item is not made from the requested leather type. - } - else - { - bool isExceptional; - - if (item is BaseWeapon weapon) - isExceptional = weapon.Quality == WeaponQuality.Exceptional; - else if (armor != null) - isExceptional = armor.Quality == ArmorQuality.Exceptional; - else - isExceptional = clothing.Quality == ClothingQuality.Exceptional; - - if (RequireExceptional && !isExceptional) - { - from.SendLocalizedMessage(1045167); // The item must be exceptional. - } - else - { - item.Delete(); - ++AmountCur; - - from.SendLocalizedMessage(1045170); // The item has been combined with the deed. - from.SendGump(new SmallBODGump(from, this)); - - if (m_AmountCur < AmountMax) - BeginCombine(from); - } - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_AmountCur); - writer.Write(Type?.FullName); - writer.Write(m_Number); - writer.Write(Graphic); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_AmountCur = reader.ReadInt(); - - string type = reader.ReadString(); - - if (type != null) - Type = AssemblyHandler.FindFirstTypeForName(type); - - m_Number = reader.ReadInt(); - Graphic = reader.ReadInt(); - break; - } - } - } - } -} +using System; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.BulkOrders +{ + public abstract class SmallBOD : BaseBOD + { + private int m_AmountCur; + private int m_Number; + + public SmallBOD( + int hue, int amountCur, int amountMax, Type type, int number, int graphic, bool requireExeptional, + BulkMaterialType material + ) : base(hue, amountMax, requireExeptional, material) + { + Type = type; + Graphic = graphic; + m_AmountCur = amountCur; + m_Number = number; + } + + public SmallBOD() + { + } + + public SmallBOD(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int AmountCur + { + get => m_AmountCur; + set + { + m_AmountCur = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Type Type { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Number + { + get => m_Number; + set + { + m_Number = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Graphic { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public override bool Complete => m_AmountCur == AmountMax; + + public override int LabelNumber => 1045151; // a bulk order deed + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1060654); // small bulk order + + if (RequireExceptional) + list.Add(1045141); // All items must be exceptional. + + if (Material != BulkMaterialType.None) + list.Add(SmallBODGump.GetMaterialNumberFor(Material)); // All items must be made with x material. + + list.Add(1060656, AmountMax.ToString()); // amount to make: ~1_val~ + list.Add(1060658, "#{0}\t{1}", m_Number, m_AmountCur); // ~1_val~: ~2_val~ + } + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack) || InSecureTrade || RootParent is PlayerVendor) + from.SendGump(new SmallBODGump(from, this)); + else + from.SendLocalizedMessage(1045156); // You must have the deed in your backpack to use it. + } + + public override void OnDoubleClickNotAccessible(Mobile from) + { + OnDoubleClick(from); + } + + public override void OnDoubleClickSecureTrade(Mobile from) + { + OnDoubleClick(from); + } + + public static BulkMaterialType GetMaterial(CraftResource resource) + { + return resource switch + { + CraftResource.DullCopper => BulkMaterialType.DullCopper, + CraftResource.ShadowIron => BulkMaterialType.ShadowIron, + CraftResource.Copper => BulkMaterialType.Copper, + CraftResource.Bronze => BulkMaterialType.Bronze, + CraftResource.Gold => BulkMaterialType.Gold, + CraftResource.Agapite => BulkMaterialType.Agapite, + CraftResource.Verite => BulkMaterialType.Verite, + CraftResource.Valorite => BulkMaterialType.Valorite, + CraftResource.SpinedLeather => BulkMaterialType.Spined, + CraftResource.HornedLeather => BulkMaterialType.Horned, + CraftResource.BarbedLeather => BulkMaterialType.Barbed, + _ => BulkMaterialType.None + }; + } + + public override void EndCombine(Mobile from, Item item) + { + var objectType = item.GetType(); + + if (m_AmountCur >= AmountMax) + { + from.SendLocalizedMessage( + 1045166 + ); // The maximum amount of requested items have already been combined to this deed. + } + else if (Type == null || objectType != Type && !objectType.IsSubclassOf(Type) || + !(item is BaseWeapon) && !(item is BaseArmor) && !(item is BaseClothing)) + { + from.SendLocalizedMessage(1045169); // The item is not in the request. + } + else + { + var armor = item as BaseArmor; + var clothing = item as BaseClothing; + + var material = GetMaterial(armor?.Resource ?? clothing?.Resource ?? CraftResource.None); + + if (Material >= BulkMaterialType.DullCopper && Material <= BulkMaterialType.Valorite && + material != Material) + { + from.SendLocalizedMessage(1045168); // The item is not made from the requested ore. + } + else if (Material >= BulkMaterialType.Spined && Material <= BulkMaterialType.Barbed && + material != Material) + { + from.SendLocalizedMessage(1049352); // The item is not made from the requested leather type. + } + else + { + bool isExceptional; + + if (item is BaseWeapon weapon) + isExceptional = weapon.Quality == WeaponQuality.Exceptional; + else if (armor != null) + isExceptional = armor.Quality == ArmorQuality.Exceptional; + else + isExceptional = clothing.Quality == ClothingQuality.Exceptional; + + if (RequireExceptional && !isExceptional) + { + from.SendLocalizedMessage(1045167); // The item must be exceptional. + } + else + { + item.Delete(); + ++AmountCur; + + from.SendLocalizedMessage(1045170); // The item has been combined with the deed. + from.SendGump(new SmallBODGump(from, this)); + + if (m_AmountCur < AmountMax) + BeginCombine(from); + } + } + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_AmountCur); + writer.Write(Type?.FullName); + writer.Write(m_Number); + writer.Write(Graphic); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_AmountCur = reader.ReadInt(); + + var type = reader.ReadString(); + + if (type != null) + Type = AssemblyHandler.FindFirstTypeForName(type); + + m_Number = reader.ReadInt(); + Graphic = reader.ReadInt(); + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/SmallBODAcceptGump.cs b/Projects/UOContent/Engines/BulkOrders/SmallBODAcceptGump.cs index cee36c998..48b915013 100644 --- a/Projects/UOContent/Engines/BulkOrders/SmallBODAcceptGump.cs +++ b/Projects/UOContent/Engines/BulkOrders/SmallBODAcceptGump.cs @@ -1,98 +1,104 @@ -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.BulkOrders -{ - public class SmallBODAcceptGump : Gump - { - private readonly SmallBOD m_Deed; - private readonly Mobile m_From; - - public SmallBODAcceptGump(Mobile from, SmallBOD deed) : base(50, 50) - { - m_From = from; - m_Deed = deed; - - m_From.CloseGump(); - m_From.CloseGump(); - - AddPage(0); - - AddBackground(25, 10, 430, 264, 5054); - - AddImageTiled(33, 20, 413, 245, 2624); - AddAlphaRegion(33, 20, 413, 245); - - AddImage(20, 5, 10460); - AddImage(430, 5, 10460); - AddImage(20, 249, 10460); - AddImage(430, 249, 10460); - - AddHtmlLocalized(190, 25, 120, 20, 1045133, 0x7FFF); // A bulk order - AddHtmlLocalized(40, 48, 350, 20, 1045135, 0x7FFF); // Ah! Thanks for the goods! Would you help me out? - - AddHtmlLocalized(40, 72, 210, 20, 1045138, 0x7FFF); // Amount to make: - AddLabel(250, 72, 1152, deed.AmountMax.ToString()); - - AddHtmlLocalized(40, 96, 120, 20, 1045136, 0x7FFF); // Item requested: - AddItem(385, 96, deed.Graphic); - AddHtmlLocalized(40, 120, 210, 20, deed.Number, 0xFFFFFF); - - if (deed.RequireExceptional || deed.Material != BulkMaterialType.None) - { - AddHtmlLocalized(40, 144, 210, 20, 1045140, 0x7FFF); // Special requirements to meet: - - if (deed.RequireExceptional) - AddHtmlLocalized(40, 168, 350, 20, 1045141, 0x7FFF); // All items must be exceptional. - - if (deed.Material != BulkMaterialType.None) - AddHtmlLocalized(40, deed.RequireExceptional ? 192 : 168, 350, 20, GetMaterialNumberFor(deed.Material), - 0x7FFF); // All items must be made with x material. - } - - AddHtmlLocalized(40, 216, 350, 20, 1045139, 0x7FFF); // Do you want to accept this order? - - AddButton(100, 240, 4005, 4007, 1); - AddHtmlLocalized(135, 240, 120, 20, 1006044, 0x7FFF); // Ok - - AddButton(275, 240, 4005, 4007, 0); - AddHtmlLocalized(310, 240, 120, 20, 1011012, 0x7FFF); // CANCEL - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 1) // Ok - { - if (m_From.PlaceInBackpack(m_Deed)) - { - m_From.SendLocalizedMessage(1045152); // The bulk order deed has been placed in your backpack. - } - else - { - m_From.SendLocalizedMessage(1045150); // There is not enough room in your backpack for the deed. - m_Deed.Delete(); - } - } - else - { - m_Deed.Delete(); - } - } - - public override void OnServerClose(NetState owner) - { - if (m_Deed?.Deleted == false) - m_Deed.Delete(); - } - - public static int GetMaterialNumberFor(BulkMaterialType material) - { - if (material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite) - return 1045142 + (material - BulkMaterialType.DullCopper); - if (material >= BulkMaterialType.Spined && material <= BulkMaterialType.Barbed) - return 1049348 + (material - BulkMaterialType.Spined); - - return 0; - } - } -} +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.BulkOrders +{ + public class SmallBODAcceptGump : Gump + { + private readonly SmallBOD m_Deed; + private readonly Mobile m_From; + + public SmallBODAcceptGump(Mobile from, SmallBOD deed) : base(50, 50) + { + m_From = from; + m_Deed = deed; + + m_From.CloseGump(); + m_From.CloseGump(); + + AddPage(0); + + AddBackground(25, 10, 430, 264, 5054); + + AddImageTiled(33, 20, 413, 245, 2624); + AddAlphaRegion(33, 20, 413, 245); + + AddImage(20, 5, 10460); + AddImage(430, 5, 10460); + AddImage(20, 249, 10460); + AddImage(430, 249, 10460); + + AddHtmlLocalized(190, 25, 120, 20, 1045133, 0x7FFF); // A bulk order + AddHtmlLocalized(40, 48, 350, 20, 1045135, 0x7FFF); // Ah! Thanks for the goods! Would you help me out? + + AddHtmlLocalized(40, 72, 210, 20, 1045138, 0x7FFF); // Amount to make: + AddLabel(250, 72, 1152, deed.AmountMax.ToString()); + + AddHtmlLocalized(40, 96, 120, 20, 1045136, 0x7FFF); // Item requested: + AddItem(385, 96, deed.Graphic); + AddHtmlLocalized(40, 120, 210, 20, deed.Number, 0xFFFFFF); + + if (deed.RequireExceptional || deed.Material != BulkMaterialType.None) + { + AddHtmlLocalized(40, 144, 210, 20, 1045140, 0x7FFF); // Special requirements to meet: + + if (deed.RequireExceptional) + AddHtmlLocalized(40, 168, 350, 20, 1045141, 0x7FFF); // All items must be exceptional. + + if (deed.Material != BulkMaterialType.None) + AddHtmlLocalized( + 40, + deed.RequireExceptional ? 192 : 168, + 350, + 20, + GetMaterialNumberFor(deed.Material), + 0x7FFF + ); // All items must be made with x material. + } + + AddHtmlLocalized(40, 216, 350, 20, 1045139, 0x7FFF); // Do you want to accept this order? + + AddButton(100, 240, 4005, 4007, 1); + AddHtmlLocalized(135, 240, 120, 20, 1006044, 0x7FFF); // Ok + + AddButton(275, 240, 4005, 4007, 0); + AddHtmlLocalized(310, 240, 120, 20, 1011012, 0x7FFF); // CANCEL + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 1) // Ok + { + if (m_From.PlaceInBackpack(m_Deed)) + { + m_From.SendLocalizedMessage(1045152); // The bulk order deed has been placed in your backpack. + } + else + { + m_From.SendLocalizedMessage(1045150); // There is not enough room in your backpack for the deed. + m_Deed.Delete(); + } + } + else + { + m_Deed.Delete(); + } + } + + public override void OnServerClose(NetState owner) + { + if (m_Deed?.Deleted == false) + m_Deed.Delete(); + } + + public static int GetMaterialNumberFor(BulkMaterialType material) + { + if (material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite) + return 1045142 + (material - BulkMaterialType.DullCopper); + if (material >= BulkMaterialType.Spined && material <= BulkMaterialType.Barbed) + return 1049348 + (material - BulkMaterialType.Spined); + + return 0; + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/SmallBODGump.cs b/Projects/UOContent/Engines/BulkOrders/SmallBODGump.cs index 53d8b45b0..e15e1b10e 100644 --- a/Projects/UOContent/Engines/BulkOrders/SmallBODGump.cs +++ b/Projects/UOContent/Engines/BulkOrders/SmallBODGump.cs @@ -1,82 +1,88 @@ -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.BulkOrders -{ - public class SmallBODGump : Gump - { - private readonly SmallBOD m_Deed; - private readonly Mobile m_From; - - public SmallBODGump(Mobile from, SmallBOD deed) : base(25, 25) - { - m_From = from; - m_Deed = deed; - - m_From.CloseGump(); - m_From.CloseGump(); - - AddPage(0); - - AddBackground(50, 10, 455, 260, 5054); - AddImageTiled(58, 20, 438, 241, 2624); - AddAlphaRegion(58, 20, 438, 241); - - AddImage(45, 5, 10460); - AddImage(480, 5, 10460); - AddImage(45, 245, 10460); - AddImage(480, 245, 10460); - - AddHtmlLocalized(225, 25, 120, 20, 1045133, 0x7FFF); // A bulk order - - AddHtmlLocalized(75, 48, 250, 20, 1045138, 0x7FFF); // Amount to make: - AddLabel(275, 48, 1152, deed.AmountMax.ToString()); - - AddHtmlLocalized(275, 76, 200, 20, 1045153, 0x7FFF); // Amount finished: - AddHtmlLocalized(75, 72, 120, 20, 1045136, 0x7FFF); // Item requested: - - AddItem(410, 72, deed.Graphic); - - AddHtmlLocalized(75, 96, 210, 20, deed.Number, 0x7FFF); - AddLabel(275, 96, 0x480, deed.AmountCur.ToString()); - - if (deed.RequireExceptional || deed.Material != BulkMaterialType.None) - AddHtmlLocalized(75, 120, 200, 20, 1045140, 0x7FFF); // Special requirements to meet: - - if (deed.RequireExceptional) - AddHtmlLocalized(75, 144, 300, 20, 1045141, 0x7FFF); // All items must be exceptional. - - if (deed.Material != BulkMaterialType.None) - AddHtmlLocalized(75, deed.RequireExceptional ? 168 : 144, 300, 20, GetMaterialNumberFor(deed.Material), - 0x7FFF); // All items must be made with x material. - - AddButton(125, 192, 4005, 4007, 2); - AddHtmlLocalized(160, 192, 300, 20, 1045154, 0x7FFF); // Combine this deed with the item requested. - - AddButton(125, 216, 4005, 4007, 1); - AddHtmlLocalized(160, 216, 120, 20, 1011441, 0x7FFF); // EXIT - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Deed.Deleted || !m_Deed.IsChildOf(m_From.Backpack)) - return; - - if (info.ButtonID == 2) // Combine - { - m_From.SendGump(new SmallBODGump(m_From, m_Deed)); - m_Deed.BeginCombine(m_From); - } - } - - public static int GetMaterialNumberFor(BulkMaterialType material) - { - if (material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite) - return 1045142 + (material - BulkMaterialType.DullCopper); - if (material >= BulkMaterialType.Spined && material <= BulkMaterialType.Barbed) - return 1049348 + (material - BulkMaterialType.Spined); - - return 0; - } - } -} +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.BulkOrders +{ + public class SmallBODGump : Gump + { + private readonly SmallBOD m_Deed; + private readonly Mobile m_From; + + public SmallBODGump(Mobile from, SmallBOD deed) : base(25, 25) + { + m_From = from; + m_Deed = deed; + + m_From.CloseGump(); + m_From.CloseGump(); + + AddPage(0); + + AddBackground(50, 10, 455, 260, 5054); + AddImageTiled(58, 20, 438, 241, 2624); + AddAlphaRegion(58, 20, 438, 241); + + AddImage(45, 5, 10460); + AddImage(480, 5, 10460); + AddImage(45, 245, 10460); + AddImage(480, 245, 10460); + + AddHtmlLocalized(225, 25, 120, 20, 1045133, 0x7FFF); // A bulk order + + AddHtmlLocalized(75, 48, 250, 20, 1045138, 0x7FFF); // Amount to make: + AddLabel(275, 48, 1152, deed.AmountMax.ToString()); + + AddHtmlLocalized(275, 76, 200, 20, 1045153, 0x7FFF); // Amount finished: + AddHtmlLocalized(75, 72, 120, 20, 1045136, 0x7FFF); // Item requested: + + AddItem(410, 72, deed.Graphic); + + AddHtmlLocalized(75, 96, 210, 20, deed.Number, 0x7FFF); + AddLabel(275, 96, 0x480, deed.AmountCur.ToString()); + + if (deed.RequireExceptional || deed.Material != BulkMaterialType.None) + AddHtmlLocalized(75, 120, 200, 20, 1045140, 0x7FFF); // Special requirements to meet: + + if (deed.RequireExceptional) + AddHtmlLocalized(75, 144, 300, 20, 1045141, 0x7FFF); // All items must be exceptional. + + if (deed.Material != BulkMaterialType.None) + AddHtmlLocalized( + 75, + deed.RequireExceptional ? 168 : 144, + 300, + 20, + GetMaterialNumberFor(deed.Material), + 0x7FFF + ); // All items must be made with x material. + + AddButton(125, 192, 4005, 4007, 2); + AddHtmlLocalized(160, 192, 300, 20, 1045154, 0x7FFF); // Combine this deed with the item requested. + + AddButton(125, 216, 4005, 4007, 1); + AddHtmlLocalized(160, 216, 120, 20, 1011441, 0x7FFF); // EXIT + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Deed.Deleted || !m_Deed.IsChildOf(m_From.Backpack)) + return; + + if (info.ButtonID == 2) // Combine + { + m_From.SendGump(new SmallBODGump(m_From, m_Deed)); + m_Deed.BeginCombine(m_From); + } + } + + public static int GetMaterialNumberFor(BulkMaterialType material) + { + if (material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Valorite) + return 1045142 + (material - BulkMaterialType.DullCopper); + if (material >= BulkMaterialType.Spined && material <= BulkMaterialType.Barbed) + return 1049348 + (material - BulkMaterialType.Spined); + + return 0; + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/SmallBulkEntry.cs b/Projects/UOContent/Engines/BulkOrders/SmallBulkEntry.cs index e4194768e..163aca8ad 100644 --- a/Projects/UOContent/Engines/BulkOrders/SmallBulkEntry.cs +++ b/Projects/UOContent/Engines/BulkOrders/SmallBulkEntry.cs @@ -1,87 +1,94 @@ -using System; -using System.Collections.Generic; -using System.IO; - -namespace Server.Engines.BulkOrders -{ - public class SmallBulkEntry - { - public Type Type { get; } - - public int Number { get; } - - public int Graphic { get; } - - public SmallBulkEntry(Type type, int number, int graphic) - { - Type = type; - Number = number; - Graphic = graphic; - } - - public static SmallBulkEntry[] BlacksmithWeapons => GetEntries("Blacksmith", "weapons"); - - public static SmallBulkEntry[] BlacksmithArmor => GetEntries("Blacksmith", "armor"); - - public static SmallBulkEntry[] TailorCloth => GetEntries("Tailoring", "cloth"); - - public static SmallBulkEntry[] TailorLeather => GetEntries("Tailoring", "leather"); - - private static Dictionary> m_Cache; - - public static SmallBulkEntry[] GetEntries(string type, string name) - { - if (m_Cache == null) - m_Cache = new Dictionary>(); - - if (!m_Cache.TryGetValue(type, out Dictionary table)) - m_Cache[type] = table = new Dictionary(); - - if (!table.TryGetValue(name, out SmallBulkEntry[] entries)) - table[name] = entries = LoadEntries(type, name); - - return entries; - } - - public static SmallBulkEntry[] LoadEntries(string type, string name) => LoadEntries($"Data/Bulk Orders/{type}/{name}.cfg"); - - public static SmallBulkEntry[] LoadEntries(string path) - { - path = Path.Combine(Core.BaseDirectory, path); - - List list = new List(); - - if (File.Exists(path)) - { - using StreamReader ip = new StreamReader(path); - string line; - - while ((line = ip.ReadLine()) != null) - { - if (line.Length == 0 || line.StartsWith("#")) - continue; - - try - { - string[] split = line.Split('\t'); - - if (split.Length >= 2) - { - Type type = AssemblyHandler.FindFirstTypeForName(split[0]); - int graphic = Utility.ToInt32(split[^1]); - - if (type != null && graphic > 0) - list.Add(new SmallBulkEntry(type, graphic < 0x4000 ? 1020000 + graphic : 1078872 + graphic, graphic)); - } - } - catch - { - // ignored - } - } - } - - return list.ToArray(); - } - } -} +using System; +using System.Collections.Generic; +using System.IO; + +namespace Server.Engines.BulkOrders +{ + public class SmallBulkEntry + { + private static Dictionary> m_Cache; + + public SmallBulkEntry(Type type, int number, int graphic) + { + Type = type; + Number = number; + Graphic = graphic; + } + + public Type Type { get; } + + public int Number { get; } + + public int Graphic { get; } + + public static SmallBulkEntry[] BlacksmithWeapons => GetEntries("Blacksmith", "weapons"); + + public static SmallBulkEntry[] BlacksmithArmor => GetEntries("Blacksmith", "armor"); + + public static SmallBulkEntry[] TailorCloth => GetEntries("Tailoring", "cloth"); + + public static SmallBulkEntry[] TailorLeather => GetEntries("Tailoring", "leather"); + + public static SmallBulkEntry[] GetEntries(string type, string name) + { + if (m_Cache == null) + m_Cache = new Dictionary>(); + + if (!m_Cache.TryGetValue(type, out var table)) + m_Cache[type] = table = new Dictionary(); + + if (!table.TryGetValue(name, out var entries)) + table[name] = entries = LoadEntries(type, name); + + return entries; + } + + public static SmallBulkEntry[] LoadEntries(string type, string name) => + LoadEntries($"Data/Bulk Orders/{type}/{name}.cfg"); + + public static SmallBulkEntry[] LoadEntries(string path) + { + path = Path.Combine(Core.BaseDirectory, path); + + var list = new List(); + + if (File.Exists(path)) + { + using var ip = new StreamReader(path); + string line; + + while ((line = ip.ReadLine()) != null) + { + if (line.Length == 0 || line.StartsWith("#")) + continue; + + try + { + var split = line.Split('\t'); + + if (split.Length >= 2) + { + var type = AssemblyHandler.FindFirstTypeForName(split[0]); + var graphic = Utility.ToInt32(split[^1]); + + if (type != null && graphic > 0) + list.Add( + new SmallBulkEntry( + type, + graphic < 0x4000 ? 1020000 + graphic : 1078872 + graphic, + graphic + ) + ); + } + } + catch + { + // ignored + } + } + } + + return list.ToArray(); + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/SmallSmithBOD.cs b/Projects/UOContent/Engines/BulkOrders/SmallSmithBOD.cs index 99d34f9cc..fa8152815 100644 --- a/Projects/UOContent/Engines/BulkOrders/SmallSmithBOD.cs +++ b/Projects/UOContent/Engines/BulkOrders/SmallSmithBOD.cs @@ -1,172 +1,173 @@ -using System; -using System.Collections.Generic; -using Server.Engines.Craft; - -namespace Server.Engines.BulkOrders -{ - public class SmallSmithBOD : SmallBOD - { - public static double[] m_BlacksmithMaterialChances = - { - 0.501953125, // None - 0.250000000, // Dull Copper - 0.125000000, // Shadow Iron - 0.062500000, // Copper - 0.031250000, // Bronze - 0.015625000, // Gold - 0.007812500, // Agapite - 0.003906250, // Verite - 0.001953125 // Valorite - }; - - private SmallSmithBOD(SmallBulkEntry entry, BulkMaterialType mat, int amountMax, bool reqExceptional) - : base(0x44E, 0, amountMax, entry.Type, entry.Number, entry.Graphic, reqExceptional, mat) - { - } - - [Constructible] - public SmallSmithBOD() - { - bool useMaterials = Utility.RandomBool(); - - SmallBulkEntry[] entries = useMaterials ? SmallBulkEntry.BlacksmithArmor : - SmallBulkEntry.BlacksmithWeapons; - - if (entries.Length <= 0) - return; - - int hue = 0x44E; - int amountMax = Utility.RandomList(10, 15, 20); - - BulkMaterialType material = useMaterials ? GetRandomMaterial(BulkMaterialType.DullCopper, m_BlacksmithMaterialChances) - : BulkMaterialType.None; - - bool reqExceptional = Utility.RandomBool() || material == BulkMaterialType.None; - - SmallBulkEntry entry = entries.RandomElement(); - - Hue = hue; - AmountMax = amountMax; - Type = entry.Type; - Number = entry.Number; - Graphic = entry.Graphic; - RequireExceptional = reqExceptional; - Material = material; - } - - public SmallSmithBOD(int amountCur, int amountMax, Type type, int number, int graphic, bool reqExceptional, - BulkMaterialType mat) : base(0x44E, amountCur, amountMax, type, number, graphic, reqExceptional, mat) - { - } - - public SmallSmithBOD(Serial serial) : base(serial) - { - } - - public override int ComputeFame() => SmithRewardCalculator.Instance.ComputeFame(this); - - public override int ComputeGold() => SmithRewardCalculator.Instance.ComputeGold(this); - - public override RewardGroup GetRewardGroup() => - SmithRewardCalculator.Instance.LookupRewards(SmithRewardCalculator.Instance.ComputePoints(this)); - - public static SmallSmithBOD CreateRandomFor(Mobile m) - { - bool useMaterials = Utility.RandomBool(); - - SmallBulkEntry[] entries = useMaterials ? SmallBulkEntry.BlacksmithArmor : - SmallBulkEntry.BlacksmithWeapons; - - if (entries.Length <= 0) - return null; - - double theirSkill = m.Skills.Blacksmith.Base; - int amountMax; - - if (theirSkill >= 70.1) - amountMax = Utility.RandomList(10, 15, 20, 20); - else if (theirSkill >= 50.1) - amountMax = Utility.RandomList(10, 15, 15, 20); - else - amountMax = Utility.RandomList(10, 10, 15, 20); - - BulkMaterialType material = BulkMaterialType.None; - - if (useMaterials && theirSkill >= 70.1) - for (int i = 0; i < 20; ++i) - { - BulkMaterialType check = GetRandomMaterial(BulkMaterialType.DullCopper, m_BlacksmithMaterialChances); - - var skillReq = check switch - { - BulkMaterialType.DullCopper => 65.0, - BulkMaterialType.ShadowIron => 70.0, - BulkMaterialType.Copper => 75.0, - BulkMaterialType.Bronze => 80.0, - BulkMaterialType.Gold => 85.0, - BulkMaterialType.Agapite => 90.0, - BulkMaterialType.Verite => 95.0, - BulkMaterialType.Valorite => 100.0, - BulkMaterialType.Spined => 65.0, - BulkMaterialType.Horned => 80.0, - BulkMaterialType.Barbed => 99.0, - _ => 0.0 - }; - - if (theirSkill >= skillReq) - { - material = check; - break; - } - } - - double excChance = theirSkill >= 70.1 ? (theirSkill + 80.0) / 200.0 : 0.0; - - bool reqExceptional = excChance > Utility.RandomDouble(); - - CraftSystem system = DefBlacksmithy.CraftSystem; - - List validEntries = new List(); - - for (int i = 0; i < entries.Length; ++i) - { - CraftItem item = system.CraftItems.SearchFor(entries[i].Type); - - if (item != null) - { - bool allRequiredSkills = true; - double chance = item.GetSuccessChance(m, null, system, false, out allRequiredSkills); - - if (allRequiredSkills && chance >= 0.0) - { - if (reqExceptional) - chance = item.GetExceptionalChance(system, chance, m); - - if (chance > 0.0) - validEntries.Add(entries[i]); - } - } - } - - if (validEntries.Count <= 0) - return null; - - SmallBulkEntry entry = validEntries.RandomElement(); - return new SmallSmithBOD(entry, material, amountMax, reqExceptional); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using System.Collections.Generic; +using Server.Engines.Craft; + +namespace Server.Engines.BulkOrders +{ + public class SmallSmithBOD : SmallBOD + { + public static double[] m_BlacksmithMaterialChances = + { + 0.501953125, // None + 0.250000000, // Dull Copper + 0.125000000, // Shadow Iron + 0.062500000, // Copper + 0.031250000, // Bronze + 0.015625000, // Gold + 0.007812500, // Agapite + 0.003906250, // Verite + 0.001953125 // Valorite + }; + + private SmallSmithBOD(SmallBulkEntry entry, BulkMaterialType mat, int amountMax, bool reqExceptional) + : base(0x44E, 0, amountMax, entry.Type, entry.Number, entry.Graphic, reqExceptional, mat) + { + } + + [Constructible] + public SmallSmithBOD() + { + var useMaterials = Utility.RandomBool(); + + var entries = useMaterials ? SmallBulkEntry.BlacksmithArmor : SmallBulkEntry.BlacksmithWeapons; + + if (entries.Length <= 0) + return; + + var hue = 0x44E; + var amountMax = Utility.RandomList(10, 15, 20); + + var material = useMaterials + ? GetRandomMaterial(BulkMaterialType.DullCopper, m_BlacksmithMaterialChances) + : BulkMaterialType.None; + + var reqExceptional = Utility.RandomBool() || material == BulkMaterialType.None; + + var entry = entries.RandomElement(); + + Hue = hue; + AmountMax = amountMax; + Type = entry.Type; + Number = entry.Number; + Graphic = entry.Graphic; + RequireExceptional = reqExceptional; + Material = material; + } + + public SmallSmithBOD( + int amountCur, int amountMax, Type type, int number, int graphic, bool reqExceptional, + BulkMaterialType mat + ) : base(0x44E, amountCur, amountMax, type, number, graphic, reqExceptional, mat) + { + } + + public SmallSmithBOD(Serial serial) : base(serial) + { + } + + public override int ComputeFame() => SmithRewardCalculator.Instance.ComputeFame(this); + + public override int ComputeGold() => SmithRewardCalculator.Instance.ComputeGold(this); + + public override RewardGroup GetRewardGroup() => + SmithRewardCalculator.Instance.LookupRewards(SmithRewardCalculator.Instance.ComputePoints(this)); + + public static SmallSmithBOD CreateRandomFor(Mobile m) + { + var useMaterials = Utility.RandomBool(); + + var entries = useMaterials ? SmallBulkEntry.BlacksmithArmor : SmallBulkEntry.BlacksmithWeapons; + + if (entries.Length <= 0) + return null; + + var theirSkill = m.Skills.Blacksmith.Base; + int amountMax; + + if (theirSkill >= 70.1) + amountMax = Utility.RandomList(10, 15, 20, 20); + else if (theirSkill >= 50.1) + amountMax = Utility.RandomList(10, 15, 15, 20); + else + amountMax = Utility.RandomList(10, 10, 15, 20); + + var material = BulkMaterialType.None; + + if (useMaterials && theirSkill >= 70.1) + for (var i = 0; i < 20; ++i) + { + var check = GetRandomMaterial(BulkMaterialType.DullCopper, m_BlacksmithMaterialChances); + + var skillReq = check switch + { + BulkMaterialType.DullCopper => 65.0, + BulkMaterialType.ShadowIron => 70.0, + BulkMaterialType.Copper => 75.0, + BulkMaterialType.Bronze => 80.0, + BulkMaterialType.Gold => 85.0, + BulkMaterialType.Agapite => 90.0, + BulkMaterialType.Verite => 95.0, + BulkMaterialType.Valorite => 100.0, + BulkMaterialType.Spined => 65.0, + BulkMaterialType.Horned => 80.0, + BulkMaterialType.Barbed => 99.0, + _ => 0.0 + }; + + if (theirSkill >= skillReq) + { + material = check; + break; + } + } + + var excChance = theirSkill >= 70.1 ? (theirSkill + 80.0) / 200.0 : 0.0; + + var reqExceptional = excChance > Utility.RandomDouble(); + + var system = DefBlacksmithy.CraftSystem; + + var validEntries = new List(); + + for (var i = 0; i < entries.Length; ++i) + { + var item = system.CraftItems.SearchFor(entries[i].Type); + + if (item != null) + { + var allRequiredSkills = true; + var chance = item.GetSuccessChance(m, null, system, false, out allRequiredSkills); + + if (allRequiredSkills && chance >= 0.0) + { + if (reqExceptional) + chance = item.GetExceptionalChance(system, chance, m); + + if (chance > 0.0) + validEntries.Add(entries[i]); + } + } + } + + if (validEntries.Count <= 0) + return null; + + var entry = validEntries.RandomElement(); + return new SmallSmithBOD(entry, material, amountMax, reqExceptional); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/BulkOrders/SmallTailorBOD.cs b/Projects/UOContent/Engines/BulkOrders/SmallTailorBOD.cs index 00b3496af..138e97d30 100644 --- a/Projects/UOContent/Engines/BulkOrders/SmallTailorBOD.cs +++ b/Projects/UOContent/Engines/BulkOrders/SmallTailorBOD.cs @@ -1,172 +1,175 @@ -using System; -using System.Collections.Generic; -using Server.Engines.Craft; - -namespace Server.Engines.BulkOrders -{ - public class SmallTailorBOD : SmallBOD - { - public static double[] m_TailoringMaterialChances = - { - 0.857421875, // None - 0.125000000, // Spined - 0.015625000, // Horned - 0.001953125 // Barbed - }; - - private SmallTailorBOD(SmallBulkEntry entry, BulkMaterialType mat, int amountMax, bool reqExceptional) - : base(0x483, 0, amountMax, entry.Type, entry.Number, entry.Graphic, reqExceptional, mat) - { - } - - [Constructible] - public SmallTailorBOD() - { - bool useMaterials = Utility.RandomBool(); - SmallBulkEntry[] entries = useMaterials ? SmallBulkEntry.TailorLeather : SmallBulkEntry.TailorCloth; - - if (entries.Length <= 0) - return; - - int hue = 0x483; - int amountMax = Utility.RandomList(10, 15, 20); - - BulkMaterialType material = useMaterials ? GetRandomMaterial(BulkMaterialType.Spined, m_TailoringMaterialChances) - : BulkMaterialType.None; - - bool reqExceptional = Utility.RandomBool() || material == BulkMaterialType.None; - SmallBulkEntry entry = entries.RandomElement(); - - Hue = hue; - AmountMax = amountMax; - Type = entry.Type; - Number = entry.Number; - Graphic = entry.Graphic; - RequireExceptional = reqExceptional; - Material = material; - } - - public SmallTailorBOD(int amountCur, int amountMax, Type type, int number, int graphic, bool reqExceptional, - BulkMaterialType mat) : base(0x483, amountCur, amountMax, type, number, graphic, reqExceptional, mat) - { - } - - public SmallTailorBOD(Serial serial) : base(serial) - { - } - - public override int ComputeFame() => TailorRewardCalculator.Instance.ComputeFame(this); - - public override int ComputeGold() => TailorRewardCalculator.Instance.ComputeGold(this); - - public override RewardGroup GetRewardGroup() => - TailorRewardCalculator.Instance.LookupRewards(TailorRewardCalculator.Instance.ComputePoints(this)); - - public static SmallTailorBOD CreateRandomFor(Mobile m) - { - SmallBulkEntry[] entries; - bool useMaterials = Utility.RandomBool(); - - double theirSkill = m.Skills.Tailoring.Base; - - // Ugly, but the easiest leather BOD is Leather Cap which requires at least 6.2 skill. - if (useMaterials && theirSkill >= 6.2) - entries = SmallBulkEntry.TailorLeather; - else - entries = SmallBulkEntry.TailorCloth; - - if (entries.Length > 0) - { - int amountMax; - - if (theirSkill >= 70.1) - amountMax = Utility.RandomList(10, 15, 20, 20); - else if (theirSkill >= 50.1) - amountMax = Utility.RandomList(10, 15, 15, 20); - else - amountMax = Utility.RandomList(10, 10, 15, 20); - - BulkMaterialType material = BulkMaterialType.None; - - if (useMaterials && theirSkill >= 70.1) - for (int i = 0; i < 20; ++i) - { - BulkMaterialType check = GetRandomMaterial(BulkMaterialType.Spined, m_TailoringMaterialChances); - - var skillReq = check switch - { - BulkMaterialType.DullCopper => 65.0, - BulkMaterialType.Bronze => 80.0, - BulkMaterialType.Gold => 85.0, - BulkMaterialType.Agapite => 90.0, - BulkMaterialType.Verite => 95.0, - BulkMaterialType.Valorite => 100.0, - BulkMaterialType.Spined => 65.0, - BulkMaterialType.Horned => 80.0, - BulkMaterialType.Barbed => 99.0, - _ => 0.0 - }; - - if (theirSkill >= skillReq) - { - material = check; - break; - } - } - - double excChance = 0.0; - - if (theirSkill >= 70.1) - excChance = (theirSkill + 80.0) / 200.0; - - bool reqExceptional = excChance > Utility.RandomDouble(); - - CraftSystem system = DefTailoring.CraftSystem; - - List validEntries = new List(); - - for (int i = 0; i < entries.Length; ++i) - { - CraftItem item = system.CraftItems.SearchFor(entries[i].Type); - - if (item != null) - { - bool allRequiredSkills = true; - double chance = item.GetSuccessChance(m, null, system, false, out allRequiredSkills); - - if (allRequiredSkills && chance >= 0.0) - { - if (reqExceptional) - chance = item.GetExceptionalChance(system, chance, m); - - if (chance > 0.0) - validEntries.Add(entries[i]); - } - } - } - - if (validEntries.Count > 0) - { - SmallBulkEntry entry = validEntries.RandomElement(); - return new SmallTailorBOD(entry, material, amountMax, reqExceptional); - } - } - - return null; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using System.Collections.Generic; +using Server.Engines.Craft; + +namespace Server.Engines.BulkOrders +{ + public class SmallTailorBOD : SmallBOD + { + public static double[] m_TailoringMaterialChances = + { + 0.857421875, // None + 0.125000000, // Spined + 0.015625000, // Horned + 0.001953125 // Barbed + }; + + private SmallTailorBOD(SmallBulkEntry entry, BulkMaterialType mat, int amountMax, bool reqExceptional) + : base(0x483, 0, amountMax, entry.Type, entry.Number, entry.Graphic, reqExceptional, mat) + { + } + + [Constructible] + public SmallTailorBOD() + { + var useMaterials = Utility.RandomBool(); + var entries = useMaterials ? SmallBulkEntry.TailorLeather : SmallBulkEntry.TailorCloth; + + if (entries.Length <= 0) + return; + + var hue = 0x483; + var amountMax = Utility.RandomList(10, 15, 20); + + var material = useMaterials + ? GetRandomMaterial(BulkMaterialType.Spined, m_TailoringMaterialChances) + : BulkMaterialType.None; + + var reqExceptional = Utility.RandomBool() || material == BulkMaterialType.None; + var entry = entries.RandomElement(); + + Hue = hue; + AmountMax = amountMax; + Type = entry.Type; + Number = entry.Number; + Graphic = entry.Graphic; + RequireExceptional = reqExceptional; + Material = material; + } + + public SmallTailorBOD( + int amountCur, int amountMax, Type type, int number, int graphic, bool reqExceptional, + BulkMaterialType mat + ) : base(0x483, amountCur, amountMax, type, number, graphic, reqExceptional, mat) + { + } + + public SmallTailorBOD(Serial serial) : base(serial) + { + } + + public override int ComputeFame() => TailorRewardCalculator.Instance.ComputeFame(this); + + public override int ComputeGold() => TailorRewardCalculator.Instance.ComputeGold(this); + + public override RewardGroup GetRewardGroup() => + TailorRewardCalculator.Instance.LookupRewards(TailorRewardCalculator.Instance.ComputePoints(this)); + + public static SmallTailorBOD CreateRandomFor(Mobile m) + { + SmallBulkEntry[] entries; + var useMaterials = Utility.RandomBool(); + + var theirSkill = m.Skills.Tailoring.Base; + + // Ugly, but the easiest leather BOD is Leather Cap which requires at least 6.2 skill. + if (useMaterials && theirSkill >= 6.2) + entries = SmallBulkEntry.TailorLeather; + else + entries = SmallBulkEntry.TailorCloth; + + if (entries.Length > 0) + { + int amountMax; + + if (theirSkill >= 70.1) + amountMax = Utility.RandomList(10, 15, 20, 20); + else if (theirSkill >= 50.1) + amountMax = Utility.RandomList(10, 15, 15, 20); + else + amountMax = Utility.RandomList(10, 10, 15, 20); + + var material = BulkMaterialType.None; + + if (useMaterials && theirSkill >= 70.1) + for (var i = 0; i < 20; ++i) + { + var check = GetRandomMaterial(BulkMaterialType.Spined, m_TailoringMaterialChances); + + var skillReq = check switch + { + BulkMaterialType.DullCopper => 65.0, + BulkMaterialType.Bronze => 80.0, + BulkMaterialType.Gold => 85.0, + BulkMaterialType.Agapite => 90.0, + BulkMaterialType.Verite => 95.0, + BulkMaterialType.Valorite => 100.0, + BulkMaterialType.Spined => 65.0, + BulkMaterialType.Horned => 80.0, + BulkMaterialType.Barbed => 99.0, + _ => 0.0 + }; + + if (theirSkill >= skillReq) + { + material = check; + break; + } + } + + var excChance = 0.0; + + if (theirSkill >= 70.1) + excChance = (theirSkill + 80.0) / 200.0; + + var reqExceptional = excChance > Utility.RandomDouble(); + + var system = DefTailoring.CraftSystem; + + var validEntries = new List(); + + for (var i = 0; i < entries.Length; ++i) + { + var item = system.CraftItems.SearchFor(entries[i].Type); + + if (item != null) + { + var allRequiredSkills = true; + var chance = item.GetSuccessChance(m, null, system, false, out allRequiredSkills); + + if (allRequiredSkills && chance >= 0.0) + { + if (reqExceptional) + chance = item.GetExceptionalChance(system, chance, m); + + if (chance > 0.0) + validEntries.Add(entries[i]); + } + } + } + + if (validEntries.Count > 0) + { + var entry = validEntries.RandomElement(); + return new SmallTailorBOD(entry, material, amountMax, reqExceptional); + } + } + + return null; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/CannedEvil/ChampionAltar.cs b/Projects/UOContent/Engines/CannedEvil/ChampionAltar.cs index b015e62e5..d05680bf7 100644 --- a/Projects/UOContent/Engines/CannedEvil/ChampionAltar.cs +++ b/Projects/UOContent/Engines/CannedEvil/ChampionAltar.cs @@ -1,51 +1,51 @@ -using Server.Items; - -namespace Server.Engines.CannedEvil -{ - public class ChampionAltar : PentagramAddon - { - private ChampionSpawn m_Spawn; - - public ChampionAltar(ChampionSpawn spawn) => m_Spawn = spawn; - - public ChampionAltar(Serial serial) : base(serial) - { - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Spawn?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Spawn); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Spawn = reader.ReadItem() as ChampionSpawn; - - if (m_Spawn == null) - Delete(); - - break; - } - } - } - } -} \ No newline at end of file +using Server.Items; + +namespace Server.Engines.CannedEvil +{ + public class ChampionAltar : PentagramAddon + { + private ChampionSpawn m_Spawn; + + public ChampionAltar(ChampionSpawn spawn) => m_Spawn = spawn; + + public ChampionAltar(Serial serial) : base(serial) + { + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Spawn?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Spawn); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Spawn = reader.ReadItem() as ChampionSpawn; + + if (m_Spawn == null) + Delete(); + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/CannedEvil/ChampionPlatform.cs b/Projects/UOContent/Engines/CannedEvil/ChampionPlatform.cs index 9bb47771f..9df80d08d 100644 --- a/Projects/UOContent/Engines/CannedEvil/ChampionPlatform.cs +++ b/Projects/UOContent/Engines/CannedEvil/ChampionPlatform.cs @@ -1,85 +1,85 @@ -using Server.Items; - -namespace Server.Engines.CannedEvil -{ - public class ChampionPlatform : BaseAddon - { - private ChampionSpawn m_Spawn; - - public ChampionPlatform(ChampionSpawn spawn) - { - m_Spawn = spawn; - - for (int x = -2; x <= 2; ++x) - for (int y = -2; y <= 2; ++y) - AddComponent(0x750, x, y, -5); - - for (int x = -1; x <= 1; ++x) - for (int y = -1; y <= 1; ++y) - AddComponent(0x750, x, y, 0); - - for (int i = -1; i <= 1; ++i) - { - AddComponent(0x751, i, 2, 0); - AddComponent(0x752, 2, i, 0); - - AddComponent(0x753, i, -2, 0); - AddComponent(0x754, -2, i, 0); - } - - AddComponent(0x759, -2, -2, 0); - AddComponent(0x75A, 2, 2, 0); - AddComponent(0x75B, -2, 2, 0); - AddComponent(0x75C, 2, -2, 0); - } - - public ChampionPlatform(Serial serial) : base(serial) - { - } - - public void AddComponent(int id, int x, int y, int z) - { - AddonComponent ac = new AddonComponent(id); - - ac.Hue = 0x497; - - AddComponent(ac, x, y, z); - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Spawn?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Spawn); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Spawn = reader.ReadItem() as ChampionSpawn; - - if (m_Spawn == null) - Delete(); - - break; - } - } - } - } -} \ No newline at end of file +using Server.Items; + +namespace Server.Engines.CannedEvil +{ + public class ChampionPlatform : BaseAddon + { + private ChampionSpawn m_Spawn; + + public ChampionPlatform(ChampionSpawn spawn) + { + m_Spawn = spawn; + + for (var x = -2; x <= 2; ++x) + for (var y = -2; y <= 2; ++y) + AddComponent(0x750, x, y, -5); + + for (var x = -1; x <= 1; ++x) + for (var y = -1; y <= 1; ++y) + AddComponent(0x750, x, y, 0); + + for (var i = -1; i <= 1; ++i) + { + AddComponent(0x751, i, 2, 0); + AddComponent(0x752, 2, i, 0); + + AddComponent(0x753, i, -2, 0); + AddComponent(0x754, -2, i, 0); + } + + AddComponent(0x759, -2, -2, 0); + AddComponent(0x75A, 2, 2, 0); + AddComponent(0x75B, -2, 2, 0); + AddComponent(0x75C, 2, -2, 0); + } + + public ChampionPlatform(Serial serial) : base(serial) + { + } + + public void AddComponent(int id, int x, int y, int z) + { + var ac = new AddonComponent(id); + + ac.Hue = 0x497; + + AddComponent(ac, x, y, z); + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Spawn?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Spawn); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Spawn = reader.ReadItem() as ChampionSpawn; + + if (m_Spawn == null) + Delete(); + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/CannedEvil/ChampionSkull.cs b/Projects/UOContent/Engines/CannedEvil/ChampionSkull.cs index 10c12bb8e..0dec4310a 100644 --- a/Projects/UOContent/Engines/CannedEvil/ChampionSkull.cs +++ b/Projects/UOContent/Engines/CannedEvil/ChampionSkull.cs @@ -1,80 +1,80 @@ -using Server.Engines.CannedEvil; - -namespace Server.Items -{ - public class ChampionSkull : Item - { - private ChampionSkullType m_Type; - - [Constructible] - public ChampionSkull(ChampionSkullType type) : base(0x1AE1) - { - m_Type = type; - LootType = LootType.Cursed; - - // TODO: All hue values - Hue = type switch - { - ChampionSkullType.Power => 0x159, - ChampionSkullType.Venom => 0x172, - ChampionSkullType.Greed => 0x1EE, - ChampionSkullType.Death => 0x025, - ChampionSkullType.Pain => 0x035, - _ => Hue - }; - } - - public ChampionSkull(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public ChampionSkullType Type - { - get => m_Type; - set - { - m_Type = value; - InvalidateProperties(); - } - } - - public override int LabelNumber => 1049479 + (int)m_Type; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write((int)m_Type); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - case 0: - { - m_Type = (ChampionSkullType)reader.ReadInt(); - - break; - } - } - - if (version == 0) - { - if (LootType != LootType.Cursed) - LootType = LootType.Cursed; - - if (Insured) - Insured = false; - } - } - } -} \ No newline at end of file +using Server.Engines.CannedEvil; + +namespace Server.Items +{ + public class ChampionSkull : Item + { + private ChampionSkullType m_Type; + + [Constructible] + public ChampionSkull(ChampionSkullType type) : base(0x1AE1) + { + m_Type = type; + LootType = LootType.Cursed; + + // TODO: All hue values + Hue = type switch + { + ChampionSkullType.Power => 0x159, + ChampionSkullType.Venom => 0x172, + ChampionSkullType.Greed => 0x1EE, + ChampionSkullType.Death => 0x025, + ChampionSkullType.Pain => 0x035, + _ => Hue + }; + } + + public ChampionSkull(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public ChampionSkullType Type + { + get => m_Type; + set + { + m_Type = value; + InvalidateProperties(); + } + } + + public override int LabelNumber => 1049479 + (int)m_Type; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write((int)m_Type); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + case 0: + { + m_Type = (ChampionSkullType)reader.ReadInt(); + + break; + } + } + + if (version == 0) + { + if (LootType != LootType.Cursed) + LootType = LootType.Cursed; + + if (Insured) + Insured = false; + } + } + } +} diff --git a/Projects/UOContent/Engines/CannedEvil/ChampionSkullBrazier.cs b/Projects/UOContent/Engines/CannedEvil/ChampionSkullBrazier.cs index fca9514b3..54547da96 100644 --- a/Projects/UOContent/Engines/CannedEvil/ChampionSkullBrazier.cs +++ b/Projects/UOContent/Engines/CannedEvil/ChampionSkullBrazier.cs @@ -1,181 +1,181 @@ -using Server.Items; -using Server.Mobiles; -using Server.Targeting; - -namespace Server.Engines.CannedEvil -{ - public class ChampionSkullBrazier : AddonComponent - { - private Item m_Skull; - private ChampionSkullType m_Type; - - public ChampionSkullBrazier(ChampionSkullPlatform platform, ChampionSkullType type) : base(0x19BB) - { - Hue = 0x455; - Light = LightType.Circle300; - - Platform = platform; - m_Type = type; - } - - public ChampionSkullBrazier(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public ChampionSkullPlatform Platform { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public ChampionSkullType Type - { - get => m_Type; - set - { - m_Type = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Item Skull - { - get => m_Skull; - set - { - m_Skull = value; - Platform?.Validate(); - } - } - - public override int LabelNumber => 1049489 + (int)m_Type; - - public override void OnDoubleClick(Mobile from) - { - Platform?.Validate(); - - BeginSacrifice(from); - } - - public void BeginSacrifice(Mobile from) - { - if (Deleted) - return; - - if (m_Skull?.Deleted == true) - Skull = null; - - if (from.Map != Map || !from.InRange(GetWorldLocation(), 3)) - { - from.SendLocalizedMessage(500446); // That is too far away. - } - else if (!Harrower.CanSpawn) - { - from.SendMessage("The harrower has already been spawned."); - } - else if (m_Skull == null) - { - from.SendLocalizedMessage(1049485); // What would you like to sacrifice? - from.Target = new SacrificeTarget(this); - } - else - { - SendLocalizedMessageTo(from, 1049487, ""); // I already have my champions awakening skull! - } - } - - public void EndSacrifice(Mobile from, ChampionSkull skull) - { - if (Deleted) - return; - - if (m_Skull?.Deleted == true) - Skull = null; - - if (from.Map != Map || !from.InRange(GetWorldLocation(), 3)) - { - from.SendLocalizedMessage(500446); // That is too far away. - } - else if (!Harrower.CanSpawn) - { - from.SendMessage("The harrower has already been spawned."); - } - else if (skull == null) - { - SendLocalizedMessageTo(from, 1049488, ""); // That is not my champions awakening skull! - } - else if (m_Skull != null) - { - SendLocalizedMessageTo(from, 1049487, ""); // I already have my champions awakening skull! - } - else if (!skull.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1049486); // You can only sacrifice items that are in your backpack! - } - else - { - if (skull.Type == Type) - { - skull.Movable = false; - skull.MoveToWorld(GetWorldTop(), Map); - - Skull = skull; - } - else - { - SendLocalizedMessageTo(from, 1049488, ""); // That is not my champions awakening skull! - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write((int)m_Type); - writer.Write(Platform); - writer.Write(m_Skull); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Type = (ChampionSkullType)reader.ReadInt(); - Platform = reader.ReadItem() as ChampionSkullPlatform; - m_Skull = reader.ReadItem(); - - if (Platform == null) - Delete(); - - break; - } - } - - if (Hue == 0x497) - Hue = 0x455; - - if (Light != LightType.Circle300) - Light = LightType.Circle300; - } - - private class SacrificeTarget : Target - { - private readonly ChampionSkullBrazier m_Brazier; - - public SacrificeTarget(ChampionSkullBrazier brazier) : base(12, false, TargetFlags.None) => m_Brazier = brazier; - - protected override void OnTarget(Mobile from, object targeted) - { - m_Brazier.EndSacrifice(from, targeted as ChampionSkull); - } - } - } -} +using Server.Items; +using Server.Mobiles; +using Server.Targeting; + +namespace Server.Engines.CannedEvil +{ + public class ChampionSkullBrazier : AddonComponent + { + private Item m_Skull; + private ChampionSkullType m_Type; + + public ChampionSkullBrazier(ChampionSkullPlatform platform, ChampionSkullType type) : base(0x19BB) + { + Hue = 0x455; + Light = LightType.Circle300; + + Platform = platform; + m_Type = type; + } + + public ChampionSkullBrazier(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public ChampionSkullPlatform Platform { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public ChampionSkullType Type + { + get => m_Type; + set + { + m_Type = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Item Skull + { + get => m_Skull; + set + { + m_Skull = value; + Platform?.Validate(); + } + } + + public override int LabelNumber => 1049489 + (int)m_Type; + + public override void OnDoubleClick(Mobile from) + { + Platform?.Validate(); + + BeginSacrifice(from); + } + + public void BeginSacrifice(Mobile from) + { + if (Deleted) + return; + + if (m_Skull?.Deleted == true) + Skull = null; + + if (from.Map != Map || !from.InRange(GetWorldLocation(), 3)) + { + from.SendLocalizedMessage(500446); // That is too far away. + } + else if (!Harrower.CanSpawn) + { + from.SendMessage("The harrower has already been spawned."); + } + else if (m_Skull == null) + { + from.SendLocalizedMessage(1049485); // What would you like to sacrifice? + from.Target = new SacrificeTarget(this); + } + else + { + SendLocalizedMessageTo(from, 1049487, ""); // I already have my champions awakening skull! + } + } + + public void EndSacrifice(Mobile from, ChampionSkull skull) + { + if (Deleted) + return; + + if (m_Skull?.Deleted == true) + Skull = null; + + if (from.Map != Map || !from.InRange(GetWorldLocation(), 3)) + { + from.SendLocalizedMessage(500446); // That is too far away. + } + else if (!Harrower.CanSpawn) + { + from.SendMessage("The harrower has already been spawned."); + } + else if (skull == null) + { + SendLocalizedMessageTo(from, 1049488, ""); // That is not my champions awakening skull! + } + else if (m_Skull != null) + { + SendLocalizedMessageTo(from, 1049487, ""); // I already have my champions awakening skull! + } + else if (!skull.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1049486); // You can only sacrifice items that are in your backpack! + } + else + { + if (skull.Type == Type) + { + skull.Movable = false; + skull.MoveToWorld(GetWorldTop(), Map); + + Skull = skull; + } + else + { + SendLocalizedMessageTo(from, 1049488, ""); // That is not my champions awakening skull! + } + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write((int)m_Type); + writer.Write(Platform); + writer.Write(m_Skull); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Type = (ChampionSkullType)reader.ReadInt(); + Platform = reader.ReadItem() as ChampionSkullPlatform; + m_Skull = reader.ReadItem(); + + if (Platform == null) + Delete(); + + break; + } + } + + if (Hue == 0x497) + Hue = 0x455; + + if (Light != LightType.Circle300) + Light = LightType.Circle300; + } + + private class SacrificeTarget : Target + { + private readonly ChampionSkullBrazier m_Brazier; + + public SacrificeTarget(ChampionSkullBrazier brazier) : base(12, false, TargetFlags.None) => m_Brazier = brazier; + + protected override void OnTarget(Mobile from, object targeted) + { + m_Brazier.EndSacrifice(from, targeted as ChampionSkull); + } + } + } +} diff --git a/Projects/UOContent/Engines/CannedEvil/ChampionSkullPlatform.cs b/Projects/UOContent/Engines/CannedEvil/ChampionSkullPlatform.cs index 4a1d3994f..a9d0a5ad8 100644 --- a/Projects/UOContent/Engines/CannedEvil/ChampionSkullPlatform.cs +++ b/Projects/UOContent/Engines/CannedEvil/ChampionSkullPlatform.cs @@ -1,125 +1,125 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.CannedEvil -{ - public class ChampionSkullPlatform : BaseAddon - { - private ChampionSkullBrazier m_Power, m_Enlightenment, m_Venom, m_Pain, m_Greed, m_Death; - - [Constructible] - public ChampionSkullPlatform() - { - AddComponent(new AddonComponent(0x71A), -1, -1, -1); - AddComponent(new AddonComponent(0x709), 0, -1, -1); - AddComponent(new AddonComponent(0x709), 1, -1, -1); - AddComponent(new AddonComponent(0x709), -1, 0, -1); - AddComponent(new AddonComponent(0x709), 0, 0, -1); - AddComponent(new AddonComponent(0x709), 1, 0, -1); - AddComponent(new AddonComponent(0x709), -1, 1, -1); - AddComponent(new AddonComponent(0x709), 0, 1, -1); - AddComponent(new AddonComponent(0x71B), 1, 1, -1); - - AddComponent(new AddonComponent(0x50F), 0, -1, 4); - AddComponent(m_Power = new ChampionSkullBrazier(this, ChampionSkullType.Power), 0, -1, 5); - - AddComponent(new AddonComponent(0x50F), 1, -1, 4); - AddComponent(m_Enlightenment = new ChampionSkullBrazier(this, ChampionSkullType.Enlightenment), 1, -1, 5); - - AddComponent(new AddonComponent(0x50F), -1, 0, 4); - AddComponent(m_Venom = new ChampionSkullBrazier(this, ChampionSkullType.Venom), -1, 0, 5); - - AddComponent(new AddonComponent(0x50F), 1, 0, 4); - AddComponent(m_Pain = new ChampionSkullBrazier(this, ChampionSkullType.Pain), 1, 0, 5); - - AddComponent(new AddonComponent(0x50F), -1, 1, 4); - AddComponent(m_Greed = new ChampionSkullBrazier(this, ChampionSkullType.Greed), -1, 1, 5); - - AddComponent(new AddonComponent(0x50F), 0, 1, 4); - AddComponent(m_Death = new ChampionSkullBrazier(this, ChampionSkullType.Death), 0, 1, 5); - - AddonComponent comp = new LocalizedAddonComponent(0x20D2, 1049495); - comp.Hue = 0x482; - AddComponent(comp, 0, 0, 5); - - comp = new LocalizedAddonComponent(0x0BCF, 1049496); - comp.Hue = 0x482; - AddComponent(comp, 0, 2, -7); - - comp = new LocalizedAddonComponent(0x0BD0, 1049497); - comp.Hue = 0x482; - AddComponent(comp, 2, 0, -7); - } - - public ChampionSkullPlatform(Serial serial) : base(serial) - { - } - - public void Validate() - { - if (Validate(m_Power) && Validate(m_Enlightenment) && Validate(m_Venom) && Validate(m_Pain) && - Validate(m_Greed) && Validate(m_Death)) - { - Mobile harrower = Harrower.Spawn(new Point3D(X, Y, Z + 6), Map); - - if (harrower == null) - return; - - Clear(m_Power); - Clear(m_Enlightenment); - Clear(m_Venom); - Clear(m_Pain); - Clear(m_Greed); - Clear(m_Death); - } - } - - public void Clear(ChampionSkullBrazier brazier) - { - if (brazier != null) - { - Effects.SendBoltEffect(brazier); - - brazier.Skull?.Delete(); - } - } - - public bool Validate(ChampionSkullBrazier brazier) => brazier?.Skull?.Deleted == false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Power); - writer.Write(m_Enlightenment); - writer.Write(m_Venom); - writer.Write(m_Pain); - writer.Write(m_Greed); - writer.Write(m_Death); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Power = reader.ReadItem() as ChampionSkullBrazier; - m_Enlightenment = reader.ReadItem() as ChampionSkullBrazier; - m_Venom = reader.ReadItem() as ChampionSkullBrazier; - m_Pain = reader.ReadItem() as ChampionSkullBrazier; - m_Greed = reader.ReadItem() as ChampionSkullBrazier; - m_Death = reader.ReadItem() as ChampionSkullBrazier; - - break; - } - } - } - } -} +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.CannedEvil +{ + public class ChampionSkullPlatform : BaseAddon + { + private ChampionSkullBrazier m_Power, m_Enlightenment, m_Venom, m_Pain, m_Greed, m_Death; + + [Constructible] + public ChampionSkullPlatform() + { + AddComponent(new AddonComponent(0x71A), -1, -1, -1); + AddComponent(new AddonComponent(0x709), 0, -1, -1); + AddComponent(new AddonComponent(0x709), 1, -1, -1); + AddComponent(new AddonComponent(0x709), -1, 0, -1); + AddComponent(new AddonComponent(0x709), 0, 0, -1); + AddComponent(new AddonComponent(0x709), 1, 0, -1); + AddComponent(new AddonComponent(0x709), -1, 1, -1); + AddComponent(new AddonComponent(0x709), 0, 1, -1); + AddComponent(new AddonComponent(0x71B), 1, 1, -1); + + AddComponent(new AddonComponent(0x50F), 0, -1, 4); + AddComponent(m_Power = new ChampionSkullBrazier(this, ChampionSkullType.Power), 0, -1, 5); + + AddComponent(new AddonComponent(0x50F), 1, -1, 4); + AddComponent(m_Enlightenment = new ChampionSkullBrazier(this, ChampionSkullType.Enlightenment), 1, -1, 5); + + AddComponent(new AddonComponent(0x50F), -1, 0, 4); + AddComponent(m_Venom = new ChampionSkullBrazier(this, ChampionSkullType.Venom), -1, 0, 5); + + AddComponent(new AddonComponent(0x50F), 1, 0, 4); + AddComponent(m_Pain = new ChampionSkullBrazier(this, ChampionSkullType.Pain), 1, 0, 5); + + AddComponent(new AddonComponent(0x50F), -1, 1, 4); + AddComponent(m_Greed = new ChampionSkullBrazier(this, ChampionSkullType.Greed), -1, 1, 5); + + AddComponent(new AddonComponent(0x50F), 0, 1, 4); + AddComponent(m_Death = new ChampionSkullBrazier(this, ChampionSkullType.Death), 0, 1, 5); + + AddonComponent comp = new LocalizedAddonComponent(0x20D2, 1049495); + comp.Hue = 0x482; + AddComponent(comp, 0, 0, 5); + + comp = new LocalizedAddonComponent(0x0BCF, 1049496); + comp.Hue = 0x482; + AddComponent(comp, 0, 2, -7); + + comp = new LocalizedAddonComponent(0x0BD0, 1049497); + comp.Hue = 0x482; + AddComponent(comp, 2, 0, -7); + } + + public ChampionSkullPlatform(Serial serial) : base(serial) + { + } + + public void Validate() + { + if (Validate(m_Power) && Validate(m_Enlightenment) && Validate(m_Venom) && Validate(m_Pain) && + Validate(m_Greed) && Validate(m_Death)) + { + Mobile harrower = Harrower.Spawn(new Point3D(X, Y, Z + 6), Map); + + if (harrower == null) + return; + + Clear(m_Power); + Clear(m_Enlightenment); + Clear(m_Venom); + Clear(m_Pain); + Clear(m_Greed); + Clear(m_Death); + } + } + + public void Clear(ChampionSkullBrazier brazier) + { + if (brazier != null) + { + Effects.SendBoltEffect(brazier); + + brazier.Skull?.Delete(); + } + } + + public bool Validate(ChampionSkullBrazier brazier) => brazier?.Skull?.Deleted == false; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Power); + writer.Write(m_Enlightenment); + writer.Write(m_Venom); + writer.Write(m_Pain); + writer.Write(m_Greed); + writer.Write(m_Death); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Power = reader.ReadItem() as ChampionSkullBrazier; + m_Enlightenment = reader.ReadItem() as ChampionSkullBrazier; + m_Venom = reader.ReadItem() as ChampionSkullBrazier; + m_Pain = reader.ReadItem() as ChampionSkullBrazier; + m_Greed = reader.ReadItem() as ChampionSkullBrazier; + m_Death = reader.ReadItem() as ChampionSkullBrazier; + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/CannedEvil/ChampionSkullType.cs b/Projects/UOContent/Engines/CannedEvil/ChampionSkullType.cs index 797b368cb..e48f02292 100644 --- a/Projects/UOContent/Engines/CannedEvil/ChampionSkullType.cs +++ b/Projects/UOContent/Engines/CannedEvil/ChampionSkullType.cs @@ -1,12 +1,12 @@ -namespace Server.Engines.CannedEvil -{ - public enum ChampionSkullType - { - Power, - Enlightenment, - Venom, - Pain, - Greed, - Death - } -} \ No newline at end of file +namespace Server.Engines.CannedEvil +{ + public enum ChampionSkullType + { + Power, + Enlightenment, + Venom, + Pain, + Greed, + Death + } +} diff --git a/Projects/UOContent/Engines/CannedEvil/ChampionSpawn.cs b/Projects/UOContent/Engines/CannedEvil/ChampionSpawn.cs index ba3748531..4fdf90dc8 100644 --- a/Projects/UOContent/Engines/CannedEvil/ChampionSpawn.cs +++ b/Projects/UOContent/Engines/CannedEvil/ChampionSpawn.cs @@ -1,1210 +1,1232 @@ -using System; -using System.Collections.Generic; -using Server.Gumps; -using Server.Items; -using Server.Mobiles; -using Server.Regions; -using Server.Utilities; - -namespace Server.Engines.CannedEvil -{ - public class ChampionSpawn : Item - { - private const int Level1 = 4; // First spawn level from 0-4 red skulls - private const int Level2 = 8; // Second spawn level from 5-8 red skulls - private const int Level3 = 12; // Third spawn level from 9-12 red skulls - - private bool m_Active; - private ChampionAltar m_Altar; - private List m_Creatures; - - private Dictionary m_DamageEntries; - - private IdolOfTheChampion m_Idol; - private int m_Kills; - private ChampionPlatform m_Platform; - private List m_RedSkulls; - private ChampionSpawnRegion m_Region; - - // private int m_SpawnRange; - private Rectangle2D m_SpawnArea; - private int m_SPawnSzMod; - - private Timer m_Timer, m_RestartTimer; - private ChampionSpawnType m_Type; - private List m_WhiteSkulls; - - [Constructible] - public ChampionSpawn() : base(0xBD2) - { - Movable = false; - Visible = false; - - m_Creatures = new List(); - m_RedSkulls = new List(); - m_WhiteSkulls = new List(); - - m_Platform = new ChampionPlatform(this); - m_Altar = new ChampionAltar(this); - m_Idol = new IdolOfTheChampion(this); - - ExpireDelay = TimeSpan.FromMinutes(10.0); - RestartDelay = TimeSpan.FromMinutes(10.0); - - m_DamageEntries = new Dictionary(); - - Timer.DelayCall(SetInitialSpawnArea); - } - - public ChampionSpawn(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int SpawnSzMod - { - get => m_SPawnSzMod < 1 || m_SPawnSzMod > 12 ? 12 : m_SPawnSzMod; - set => m_SPawnSzMod = value < 1 || value > 12 ? 12 : value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool ConfinedRoaming { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool HasBeenAdvanced { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool RandomizeType { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Kills - { - get => m_Kills; - set - { - m_Kills = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Rectangle2D SpawnArea - { - get => m_SpawnArea; - set - { - m_SpawnArea = value; - InvalidateProperties(); - UpdateRegion(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan RestartDelay { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime RestartTime { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan ExpireDelay { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime ExpireTime { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public ChampionSpawnType Type - { - get => m_Type; - set - { - m_Type = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Active - { - get => m_Active; - set - { - if (value) - Start(); - else - Stop(); - - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Champion { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Level - { - get => m_RedSkulls.Count; - set - { - for (int i = m_RedSkulls.Count - 1; i >= value; --i) - { - m_RedSkulls[i].Delete(); - m_RedSkulls.RemoveAt(i); - } - - for (int i = m_RedSkulls.Count; i < value; ++i) - { - Item skull = new Item(0x1854); - - skull.Hue = 0x26; - skull.Movable = false; - skull.Light = LightType.Circle150; - - skull.MoveToWorld(GetRedSkullLocation(i), Map); - - m_RedSkulls.Add(skull); - } - - InvalidateProperties(); - } - } - - public int MaxKills => m_SPawnSzMod * (250 / 12) - Level * m_SPawnSzMod; - - public void SetInitialSpawnArea() - { - // Previous default used to be 24; - SpawnArea = new Rectangle2D(new Point2D(X - 24, Y - 24), new Point2D(X + 24, Y + 24)); - } - - public void UpdateRegion() - { - m_Region?.Unregister(); - - if (!Deleted && Map != Map.Internal) - { - m_Region = new ChampionSpawnRegion(this); - m_Region.Register(); - } - - /* - if (m_Region == null) - { - m_Region = new ChampionSpawnRegion( this ); - } - else - { - m_Region.Unregister(); - //Why doesn't Region allow me to set it's map/Area myself? >< - m_Region = new ChampionSpawnRegion( this ); - } - */ - } - - public bool IsChampionSpawn(Mobile m) => m_Creatures.Contains(m); - - public void SetWhiteSkullCount(int val) - { - for (int i = m_WhiteSkulls.Count - 1; i >= val; --i) - { - m_WhiteSkulls[i].Delete(); - m_WhiteSkulls.RemoveAt(i); - } - - for (int i = m_WhiteSkulls.Count; i < val; ++i) - { - Item skull = new Item(0x1854); - - skull.Movable = false; - skull.Light = LightType.Circle150; - - skull.MoveToWorld(GetWhiteSkullLocation(i), Map); - - m_WhiteSkulls.Add(skull); - - Effects.PlaySound(skull.Location, skull.Map, 0x29); - Effects.SendLocationEffect(new Point3D(skull.X + 1, skull.Y + 1, skull.Z), skull.Map, 0x3728, 10); - } - } - - public void Start() - { - if (m_Active || Deleted) - return; - - m_Active = true; - HasBeenAdvanced = false; - - m_Timer?.Stop(); - - m_Timer = new SliceTimer(this); - m_Timer.Start(); - - m_RestartTimer?.Stop(); - - m_RestartTimer = null; - - if (m_Altar != null) - { - if (Champion != null) - m_Altar.Hue = 0x26; - else - m_Altar.Hue = 0; - } - - if (m_Platform != null) - m_Platform.Hue = 0x452; - } - - public void Stop() - { - if (!m_Active || Deleted) - return; - - m_Active = false; - HasBeenAdvanced = false; - - m_Timer?.Stop(); - - m_Timer = null; - - m_RestartTimer?.Stop(); - - m_RestartTimer = null; - - if (m_Altar != null) - m_Altar.Hue = 0; - - if (m_Platform != null) - m_Platform.Hue = 0x497; - } - - public void BeginRestart(TimeSpan ts) - { - m_RestartTimer?.Stop(); - - RestartTime = DateTime.UtcNow + ts; - - m_RestartTimer = new RestartTimer(this, ts); - m_RestartTimer.Start(); - } - - public void EndRestart() - { - if (RandomizeType) - Type = Utility.Random(5) switch - { - 0 => ChampionSpawnType.VerminHorde, - 1 => ChampionSpawnType.UnholyTerror, - 2 => ChampionSpawnType.ColdBlood, - 3 => ChampionSpawnType.Abyss, - 4 => ChampionSpawnType.Arachnid, - _ => Type - }; - - HasBeenAdvanced = false; - - Start(); - } - - private ScrollofTranscendence CreateRandomSoT(bool felucca) - { - int level = Utility.RandomMinMax(1, 5); - - if (felucca) - level += 5; - - return ScrollofTranscendence.CreateRandom(level, level); - } - - public static void GiveScrollTo(Mobile killer, SpecialScroll scroll) - { - if (scroll == null || killer == null) // sanity - return; - - if (scroll is ScrollofTranscendence) - killer.SendLocalizedMessage(1094936); // You have received a Scroll of Transcendence! - else - killer.SendLocalizedMessage(1049524); // You have received a scroll of power! - - if (killer.Alive) - killer.AddToBackpack(scroll); - else - { - if (killer.Corpse.Deleted == false) - killer.Corpse.DropItem(scroll); - else - killer.AddToBackpack(scroll); - } - - // Justice reward - PlayerMobile pm = (PlayerMobile)killer; - for (int j = 0; j < pm.JusticeProtectors.Count; ++j) - { - Mobile prot = pm.JusticeProtectors[j]; - - if (prot.Map != killer.Map || prot.Kills >= 5 || prot.Criminal || - !JusticeVirtue.CheckMapRegion(killer, prot)) - continue; - - var chance = VirtueHelper.GetLevel(prot, VirtueName.Justice) switch - { - VirtueLevel.Seeker => 60, - VirtueLevel.Follower => 80, - VirtueLevel.Knight => 100, - _ => 0 - }; - - if (chance > Utility.Random(100)) - try - { - prot.SendLocalizedMessage(1049368); // You have been rewarded for your dedication to Justice! - - if (ActivatorUtil.CreateInstance(scroll.GetType()) is SpecialScroll scrollDupe) - { - scrollDupe.Skill = scroll.Skill; - scrollDupe.Value = scroll.Value; - prot.AddToBackpack(scrollDupe); - } - } - catch - { - // ignored - } - } - } - - public void OnSlice() - { - if (!m_Active || Deleted) - return; - - if (Champion != null) - { - if (Champion.Deleted) - { - RegisterDamageTo(Champion); - - if (Champion is BaseChampion champion) - AwardArtifact(champion.GetArtifact()); - - m_DamageEntries.Clear(); - - if (m_Platform != null) - m_Platform.Hue = 0x497; - - if (m_Altar != null) - { - m_Altar.Hue = 0; - - if (!Core.ML || Map == Map.Felucca) - new StarRoomGate(m_Altar.Location, m_Altar.Map, true); - } - - Champion = null; - Stop(); - - BeginRestart(RestartDelay); - } - } - else - { - int kills = m_Kills; - - for (int i = 0; i < m_Creatures.Count; ++i) - { - Mobile m = m_Creatures[i]; - - if (m.Deleted) - { - if (m.Corpse?.Deleted == false) - ((Corpse)m.Corpse).BeginDecay(TimeSpan.FromMinutes(1)); - - m_Creatures.RemoveAt(i); - --i; - ++m_Kills; - - Mobile killer = m.FindMostRecentDamager(false); - - RegisterDamageTo(m); - - if (killer is BaseCreature bc) - killer = bc.GetMaster(); - - if (killer is PlayerMobile pm) - { - if (Core.ML) - { - if (Map == Map.Felucca) - if (Utility.RandomDouble() < 0.001) - { - double random = Utility.Random(49); - - if (random <= 24) - { - ScrollofTranscendence SoTF = CreateRandomSoT(true); - GiveScrollTo(pm, SoTF); - } - else - { - PowerScroll PS = PowerScroll.CreateRandomNoCraft(5, 5); - GiveScrollTo(pm, PS); - } - } - - if (Map == Map.Ilshenar || Map == Map.Tokuno || Map == Map.Malas) - if (Utility.RandomDouble() < 0.0015) - { - pm.SendLocalizedMessage(1094936); // You have received a Scroll of Transcendence! - ScrollofTranscendence SoTT = CreateRandomSoT(false); - pm.AddToBackpack(SoTT); - } - } - - int mobSubLevel = GetSubLevelFor(m) + 1; - - if (mobSubLevel >= 0) - { - bool gainedPath = false; - - int pointsToGain = mobSubLevel * 40; - - if (VirtueHelper.Award(pm, VirtueName.Valor, pointsToGain, ref gainedPath)) - { - if (gainedPath) - m.SendLocalizedMessage(1054032); // You have gained a path in Valor! - else - m.SendLocalizedMessage(1054030); // You have gained in Valor! - - // No delay on Valor gains - } - - PlayerMobile.ChampionTitleInfo info = pm.ChampionTitles; - - info.Award(m_Type, mobSubLevel); - } - } - } - } - - // Only really needed once. - if (m_Kills > kills) - InvalidateProperties(); - - double n = m_Kills / (double)MaxKills; - int p = (int)(n * 100); - - if (p >= 90) - AdvanceLevel(); - else if (p > 0) - SetWhiteSkullCount(p / 20); - - if (DateTime.UtcNow >= ExpireTime) - Expire(); - - Respawn(); - } - } - - public void AdvanceLevel() - { - ExpireTime = DateTime.UtcNow + ExpireDelay; - - if (Level < 16) - { - m_Kills = 0; - ++Level; - InvalidateProperties(); - SetWhiteSkullCount(0); - - if (m_Altar != null) - { - Effects.PlaySound(m_Altar.Location, m_Altar.Map, 0x29); - Effects.SendLocationEffect(new Point3D(m_Altar.X + 1, m_Altar.Y + 1, m_Altar.Z), m_Altar.Map, 0x3728, - 10); - } - } - else - { - SpawnChampion(); - } - } - - public void SpawnChampion() - { - if (m_Altar != null) - m_Altar.Hue = 0x26; - - if (m_Platform != null) - m_Platform.Hue = 0x452; - - m_Kills = 0; - Level = 0; - InvalidateProperties(); - SetWhiteSkullCount(0); - - try - { - Champion = ActivatorUtil.CreateInstance(ChampionSpawnInfo.GetInfo(m_Type).Champion) as Mobile; - } - catch - { - // ignored - } - - Champion?.MoveToWorld(new Point3D(X, Y, Z - 15), Map); - } - - public void Respawn() - { - if (!m_Active || Deleted || Champion != null) - return; - - while (m_Creatures.Count < m_SPawnSzMod * (200 / 12) - GetSubLevel() * m_SPawnSzMod * (40 / 12)) - { - Mobile m = Spawn(); - - if (m == null) - return; - - Point3D loc = GetSpawnLocation(); - - // Allow creatures to turn into Paragons at Ilshenar champions. - m.OnBeforeSpawn(loc, Map); - - m_Creatures.Add(m); - m.MoveToWorld(loc, Map); - - if (m is BaseCreature bc) - { - bc.Tamable = false; - - if (!ConfinedRoaming) - { - bc.Home = Location; - bc.RangeHome = - (int)(Math.Sqrt(m_SpawnArea.Width * m_SpawnArea.Width + - m_SpawnArea.Height * m_SpawnArea.Height) / 2); - } - else - { - bc.Home = bc.Location; - - Point2D xWall1 = new Point2D(m_SpawnArea.X, bc.Y); - Point2D xWall2 = new Point2D(m_SpawnArea.X + m_SpawnArea.Width, bc.Y); - Point2D yWall1 = new Point2D(bc.X, m_SpawnArea.Y); - Point2D yWall2 = new Point2D(bc.X, m_SpawnArea.Y + m_SpawnArea.Height); - - double minXDist = Math.Min(bc.GetDistanceToSqrt(xWall1), bc.GetDistanceToSqrt(xWall2)); - double minYDist = Math.Min(bc.GetDistanceToSqrt(yWall1), bc.GetDistanceToSqrt(yWall2)); - - bc.RangeHome = (int)Math.Min(minXDist, minYDist); - } - } - } - } - - public Point3D GetSpawnLocation() - { - Map map = Map; - - if (map == null) - return Location; - - // Try 20 times to find a spawnable location. - for (int i = 0; i < 20; i++) - { - /* - int x = Location.X + (Utility.Random( (m_SpawnRange * 2) + 1 ) - m_SpawnRange); - int y = Location.Y + (Utility.Random( (m_SpawnRange * 2) + 1 ) - m_SpawnRange); - */ - - int x = Utility.Random(m_SpawnArea.X, m_SpawnArea.Width); - int y = Utility.Random(m_SpawnArea.Y, m_SpawnArea.Height); - - int z = Map.GetAverageZ(x, y); - - if (Map.CanSpawnMobile(new Point2D(x, y), z)) - return new Point3D(x, y, z); - - /* try @ platform Z if map z fails */ - if (Map.CanSpawnMobile(new Point2D(x, y), m_Platform.Location.Z)) - return new Point3D(x, y, m_Platform.Location.Z); - } - - return Location; - } - - public int GetSubLevel() - { - int level = Level; - - if (level <= Level1) - return 0; - if (level <= Level2) - return 1; - if (level <= Level3) - return 2; - - return 3; - } - - public int GetSubLevelFor(Mobile m) - { - Type[][] types = ChampionSpawnInfo.GetInfo(m_Type).SpawnTypes; - Type t = m.GetType(); - - for (int i = 0; i < types.GetLength(0); i++) - { - Type[] individualTypes = types[i]; - - for (int j = 0; j < individualTypes.Length; j++) - if (t == individualTypes[j]) - return i; - } - - return -1; - } - - public Mobile Spawn() - { - Type[][] types = ChampionSpawnInfo.GetInfo(m_Type).SpawnTypes; - - int v = GetSubLevel(); - - if (v >= 0 && v < types.Length) - return Spawn(types[v]); - - return null; - } - - public Mobile Spawn(params Type[] types) - { - try - { - return ActivatorUtil.CreateInstance(types.RandomElement()) as Mobile; - } - catch - { - return null; - } - } - - public void Expire() - { - m_Kills = 0; - - if (m_WhiteSkulls.Count == 0) - { - // They didn't even get 20%, go back a level - - if (Level > 0) - --Level; - - InvalidateProperties(); - } - else - { - SetWhiteSkullCount(0); - } - - ExpireTime = DateTime.UtcNow + ExpireDelay; - } - - public Point3D GetRedSkullLocation(int index) - { - int x, y; - - if (index < 5) - { - x = index - 2; - y = -2; - } - else if (index < 9) - { - x = 2; - y = index - 6; - } - else if (index < 13) - { - x = 10 - index; - y = 2; - } - else - { - x = -2; - y = 14 - index; - } - - return new Point3D(X + x, Y + y, Z - 15); - } - - public Point3D GetWhiteSkullLocation(int index) - { - int x, y; - - switch (index) - { - default: - x = -1; - y = -1; - break; - case 1: - x = 1; - y = -1; - break; - case 2: - x = 1; - y = 1; - break; - case 3: - x = -1; - y = 1; - break; - } - - return new Point3D(X + x, Y + y, Z - 15); - } - - public override void AddNameProperty(ObjectPropertyList list) - { - list.Add("champion spawn"); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_Active) - { - list.Add(1060742); // active - list.Add(1060658, "Type\t{0}", m_Type); // ~1_val~: ~2_val~ - list.Add(1060659, "Level\t{0}", Level); // ~1_val~: ~2_val~ - list.Add(1060660, "Kills\t{0} of {1} ({2:F1}%)", m_Kills, MaxKills, - 100.0 * ((double)m_Kills / MaxKills)); // ~1_val~: ~2_val~ - // list.Add( 1060661, "Spawn Range\t{0}", m_SpawnRange ); // ~1_val~: ~2_val~ - } - else - { - list.Add(1060743); // inactive - } - } - - public override void OnSingleClick(Mobile from) - { - if (m_Active) - LabelTo(from, "{0} (Active; Level: {1}; Kills: {2}/{3})", m_Type, Level, m_Kills, MaxKills); - else - LabelTo(from, "{0} (Inactive)", m_Type); - } - - public override void OnDoubleClick(Mobile from) - { - from.SendGump(new PropertiesGump(from, this)); - } - - public override void OnLocationChange(Point3D oldLoc) - { - if (Deleted) - return; - - if (m_Platform != null) - m_Platform.Location = new Point3D(X, Y, Z - 20); - - if (m_Altar != null) - m_Altar.Location = new Point3D(X, Y, Z - 15); - - if (m_Idol != null) - m_Idol.Location = new Point3D(X, Y, Z - 15); - - if (m_RedSkulls != null) - for (int i = 0; i < m_RedSkulls.Count; ++i) - m_RedSkulls[i].Location = GetRedSkullLocation(i); - - if (m_WhiteSkulls != null) - for (int i = 0; i < m_WhiteSkulls.Count; ++i) - m_WhiteSkulls[i].Location = GetWhiteSkullLocation(i); - - m_SpawnArea.X += Location.X - oldLoc.X; - m_SpawnArea.Y += Location.Y - oldLoc.Y; - - UpdateRegion(); - } - - public override void OnMapChange() - { - if (Deleted) - return; - - if (m_Platform != null) - m_Platform.Map = Map; - - if (m_Altar != null) - m_Altar.Map = Map; - - if (m_Idol != null) - m_Idol.Map = Map; - - if (m_RedSkulls != null) - for (int i = 0; i < m_RedSkulls.Count; ++i) - m_RedSkulls[i].Map = Map; - - if (m_WhiteSkulls != null) - for (int i = 0; i < m_WhiteSkulls.Count; ++i) - m_WhiteSkulls[i].Map = Map; - - UpdateRegion(); - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Platform?.Delete(); - - m_Altar?.Delete(); - - m_Idol?.Delete(); - - if (m_RedSkulls != null) - { - for (int i = 0; i < m_RedSkulls.Count; ++i) - m_RedSkulls[i].Delete(); - - m_RedSkulls.Clear(); - } - - if (m_WhiteSkulls != null) - { - for (int i = 0; i < m_WhiteSkulls.Count; ++i) - m_WhiteSkulls[i].Delete(); - - m_WhiteSkulls.Clear(); - } - - if (m_Creatures != null) - { - for (int i = 0; i < m_Creatures.Count; ++i) - { - Mobile mob = m_Creatures[i]; - - if (!mob.Player) - mob.Delete(); - } - - m_Creatures.Clear(); - } - - if (Champion?.Player == false) - Champion.Delete(); - - Stop(); - - UpdateRegion(); - } - - public virtual void RegisterDamageTo(Mobile m) - { - if (m == null) - return; - - foreach (DamageEntry de in m.DamageEntries) - { - if (de.HasExpired) - continue; - - Mobile damager = de.Damager; - - Mobile master = damager.GetDamageMaster(m); - - if (master != null) - damager = master; - - RegisterDamage(damager, de.DamageGiven); - } - } - - public void RegisterDamage(Mobile from, int amount) - { - if (from?.Player != true) - return; - - m_DamageEntries[from] = amount + (m_DamageEntries.TryGetValue(from, out int value) ? value : 0); - } - - public void AwardArtifact(Item artifact) - { - if (artifact == null) - return; - - int totalDamage = 0; - - Dictionary validEntries = new Dictionary(); - - foreach (KeyValuePair kvp in m_DamageEntries) - if (IsEligible(kvp.Key, artifact)) - { - validEntries.Add(kvp.Key, kvp.Value); - totalDamage += kvp.Value; - } - - int randomDamage = Utility.RandomMinMax(1, totalDamage); - - totalDamage = 0; - - foreach (KeyValuePair kvp in validEntries) - { - totalDamage += kvp.Value; - - if (totalDamage >= randomDamage) - { - GiveArtifact(kvp.Key, artifact); - return; - } - } - - artifact.Delete(); - } - - public void GiveArtifact(Mobile to, Item artifact) - { - if (to == null || artifact == null) - return; - - Container pack = to.Backpack; - - if (pack?.TryDropItem(to, artifact, false) != true) - artifact.Delete(); - else - to.SendLocalizedMessage( - 1062317); // For your valor in combating the fallen beast, a special artifact has been bestowed on you. - } - - public bool IsEligible(Mobile m, Item artifact) => - m.Player && m.Alive && m.Region != null && m.Region == m_Region && - m.Backpack?.CheckHold(m, artifact, false) == true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(6); // version - - writer.Write(m_SPawnSzMod); - writer.Write(m_DamageEntries.Count); - foreach (KeyValuePair kvp in m_DamageEntries) - { - writer.Write(kvp.Key); - writer.Write(kvp.Value); - } - - writer.Write(ConfinedRoaming); - writer.WriteItem(m_Idol); - writer.Write(HasBeenAdvanced); - writer.Write(m_SpawnArea); - - writer.Write(RandomizeType); - - // writer.Write( m_SpawnRange ); - writer.Write(m_Kills); - - writer.Write(m_Active); - writer.Write((int)m_Type); - writer.Write(m_Creatures, true); - writer.Write(m_RedSkulls, true); - writer.Write(m_WhiteSkulls, true); - writer.WriteItem(m_Platform); - writer.WriteItem(m_Altar); - writer.Write(ExpireDelay); - writer.WriteDeltaTime(ExpireTime); - writer.Write(Champion); - writer.Write(RestartDelay); - - writer.Write(m_RestartTimer != null); - - if (m_RestartTimer != null) - writer.WriteDeltaTime(RestartTime); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - m_DamageEntries = new Dictionary(); - - int version = reader.ReadInt(); - - switch (version) - { - case 6: - { - m_SPawnSzMod = reader.ReadInt(); - goto case 5; - } - case 5: - { - int entries = reader.ReadInt(); - for (int i = 0; i < entries; ++i) - { - Mobile m = reader.ReadMobile(); - int damage = reader.ReadInt(); - - if (m == null) - continue; - - m_DamageEntries.Add(m, damage); - } - - goto case 4; - } - case 4: - { - ConfinedRoaming = reader.ReadBool(); - m_Idol = reader.ReadItem(); - HasBeenAdvanced = reader.ReadBool(); - - goto case 3; - } - case 3: - { - m_SpawnArea = reader.ReadRect2D(); - - goto case 2; - } - case 2: - { - RandomizeType = reader.ReadBool(); - - goto case 1; - } - case 1: - { - if (version < 3) - { - int oldRange = reader.ReadInt(); - - m_SpawnArea = new Rectangle2D(new Point2D(X - oldRange, Y - oldRange), - new Point2D(X + oldRange, Y + oldRange)); - } - - m_Kills = reader.ReadInt(); - - goto case 0; - } - case 0: - { - if (version < 1) - m_SpawnArea = - new Rectangle2D(new Point2D(X - 24, Y - 24), new Point2D(X + 24, Y + 24)); // Default was 24 - - bool active = reader.ReadBool(); - m_Type = (ChampionSpawnType)reader.ReadInt(); - m_Creatures = reader.ReadStrongMobileList(); - m_RedSkulls = reader.ReadStrongItemList(); - m_WhiteSkulls = reader.ReadStrongItemList(); - m_Platform = reader.ReadItem(); - m_Altar = reader.ReadItem(); - ExpireDelay = reader.ReadTimeSpan(); - ExpireTime = reader.ReadDeltaTime(); - Champion = reader.ReadMobile(); - RestartDelay = reader.ReadTimeSpan(); - - if (reader.ReadBool()) - { - RestartTime = reader.ReadDeltaTime(); - BeginRestart(RestartTime - DateTime.UtcNow); - } - - if (version < 4) - { - m_Idol = new IdolOfTheChampion(this); - m_Idol.MoveToWorld(new Point3D(X, Y, Z - 15), Map); - } - - if (m_Platform == null || m_Altar == null || m_Idol == null) - Delete(); - else if (active) - Start(); - - break; - } - } - - Timer.DelayCall(UpdateRegion); - } - } - - public class ChampionSpawnRegion : BaseRegion - { - public ChampionSpawnRegion(ChampionSpawn spawn) : base(null, spawn.Map, Find(spawn.Location, spawn.Map), - spawn.SpawnArea) => - ChampionSpawn = spawn; - - public override bool YoungProtected => false; - - public ChampionSpawn ChampionSpawn { get; } - - public override bool AllowHousing(Mobile from, Point3D p) => false; - - public override void AlterLightLevel(Mobile m, ref int global, ref int personal) - { - base.AlterLightLevel(m, ref global, ref personal); - global = Math.Max(global, - 1 + ChampionSpawn - .Level); // This is a guesstimate. TODO: Verify & get exact values // OSI testing: at 2 red skulls, light = 0x3 ; 1 red = 0x3.; 3 = 8; 9 = 0xD 8 = 0xD 12 = 0x12 10 = 0xD - } - } - - public class IdolOfTheChampion : Item - { - public IdolOfTheChampion(ChampionSpawn spawn) : base(0x1F18) - { - Spawn = spawn; - Movable = false; - } - - public IdolOfTheChampion(Serial serial) : base(serial) - { - } - - public ChampionSpawn Spawn { get; private set; } - - public override string DefaultName => "Idol of the Champion"; - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - Spawn?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(Spawn); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Spawn = reader.ReadItem() as ChampionSpawn; - - if (Spawn == null) - Delete(); - - break; - } - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Gumps; +using Server.Items; +using Server.Mobiles; +using Server.Regions; +using Server.Utilities; + +namespace Server.Engines.CannedEvil +{ + public class ChampionSpawn : Item + { + private const int Level1 = 4; // First spawn level from 0-4 red skulls + private const int Level2 = 8; // Second spawn level from 5-8 red skulls + private const int Level3 = 12; // Third spawn level from 9-12 red skulls + + private bool m_Active; + private ChampionAltar m_Altar; + private List m_Creatures; + + private Dictionary m_DamageEntries; + + private IdolOfTheChampion m_Idol; + private int m_Kills; + private ChampionPlatform m_Platform; + private List m_RedSkulls; + private ChampionSpawnRegion m_Region; + + // private int m_SpawnRange; + private Rectangle2D m_SpawnArea; + private int m_SPawnSzMod; + + private Timer m_Timer, m_RestartTimer; + private ChampionSpawnType m_Type; + private List m_WhiteSkulls; + + [Constructible] + public ChampionSpawn() : base(0xBD2) + { + Movable = false; + Visible = false; + + m_Creatures = new List(); + m_RedSkulls = new List(); + m_WhiteSkulls = new List(); + + m_Platform = new ChampionPlatform(this); + m_Altar = new ChampionAltar(this); + m_Idol = new IdolOfTheChampion(this); + + ExpireDelay = TimeSpan.FromMinutes(10.0); + RestartDelay = TimeSpan.FromMinutes(10.0); + + m_DamageEntries = new Dictionary(); + + Timer.DelayCall(SetInitialSpawnArea); + } + + public ChampionSpawn(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int SpawnSzMod + { + get => m_SPawnSzMod < 1 || m_SPawnSzMod > 12 ? 12 : m_SPawnSzMod; + set => m_SPawnSzMod = value < 1 || value > 12 ? 12 : value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool ConfinedRoaming { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool HasBeenAdvanced { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool RandomizeType { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Kills + { + get => m_Kills; + set + { + m_Kills = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Rectangle2D SpawnArea + { + get => m_SpawnArea; + set + { + m_SpawnArea = value; + InvalidateProperties(); + UpdateRegion(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan RestartDelay { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime RestartTime { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan ExpireDelay { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime ExpireTime { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public ChampionSpawnType Type + { + get => m_Type; + set + { + m_Type = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Active + { + get => m_Active; + set + { + if (value) + Start(); + else + Stop(); + + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Champion { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Level + { + get => m_RedSkulls.Count; + set + { + for (var i = m_RedSkulls.Count - 1; i >= value; --i) + { + m_RedSkulls[i].Delete(); + m_RedSkulls.RemoveAt(i); + } + + for (var i = m_RedSkulls.Count; i < value; ++i) + { + var skull = new Item(0x1854); + + skull.Hue = 0x26; + skull.Movable = false; + skull.Light = LightType.Circle150; + + skull.MoveToWorld(GetRedSkullLocation(i), Map); + + m_RedSkulls.Add(skull); + } + + InvalidateProperties(); + } + } + + public int MaxKills => m_SPawnSzMod * (250 / 12) - Level * m_SPawnSzMod; + + public void SetInitialSpawnArea() + { + // Previous default used to be 24; + SpawnArea = new Rectangle2D(new Point2D(X - 24, Y - 24), new Point2D(X + 24, Y + 24)); + } + + public void UpdateRegion() + { + m_Region?.Unregister(); + + if (!Deleted && Map != Map.Internal) + { + m_Region = new ChampionSpawnRegion(this); + m_Region.Register(); + } + + /* + if (m_Region == null) + { + m_Region = new ChampionSpawnRegion( this ); + } + else + { + m_Region.Unregister(); + //Why doesn't Region allow me to set it's map/Area myself? >< + m_Region = new ChampionSpawnRegion( this ); + } + */ + } + + public bool IsChampionSpawn(Mobile m) => m_Creatures.Contains(m); + + public void SetWhiteSkullCount(int val) + { + for (var i = m_WhiteSkulls.Count - 1; i >= val; --i) + { + m_WhiteSkulls[i].Delete(); + m_WhiteSkulls.RemoveAt(i); + } + + for (var i = m_WhiteSkulls.Count; i < val; ++i) + { + var skull = new Item(0x1854); + + skull.Movable = false; + skull.Light = LightType.Circle150; + + skull.MoveToWorld(GetWhiteSkullLocation(i), Map); + + m_WhiteSkulls.Add(skull); + + Effects.PlaySound(skull.Location, skull.Map, 0x29); + Effects.SendLocationEffect(new Point3D(skull.X + 1, skull.Y + 1, skull.Z), skull.Map, 0x3728, 10); + } + } + + public void Start() + { + if (m_Active || Deleted) + return; + + m_Active = true; + HasBeenAdvanced = false; + + m_Timer?.Stop(); + + m_Timer = new SliceTimer(this); + m_Timer.Start(); + + m_RestartTimer?.Stop(); + + m_RestartTimer = null; + + if (m_Altar != null) + { + if (Champion != null) + m_Altar.Hue = 0x26; + else + m_Altar.Hue = 0; + } + + if (m_Platform != null) + m_Platform.Hue = 0x452; + } + + public void Stop() + { + if (!m_Active || Deleted) + return; + + m_Active = false; + HasBeenAdvanced = false; + + m_Timer?.Stop(); + + m_Timer = null; + + m_RestartTimer?.Stop(); + + m_RestartTimer = null; + + if (m_Altar != null) + m_Altar.Hue = 0; + + if (m_Platform != null) + m_Platform.Hue = 0x497; + } + + public void BeginRestart(TimeSpan ts) + { + m_RestartTimer?.Stop(); + + RestartTime = DateTime.UtcNow + ts; + + m_RestartTimer = new RestartTimer(this, ts); + m_RestartTimer.Start(); + } + + public void EndRestart() + { + if (RandomizeType) + Type = Utility.Random(5) switch + { + 0 => ChampionSpawnType.VerminHorde, + 1 => ChampionSpawnType.UnholyTerror, + 2 => ChampionSpawnType.ColdBlood, + 3 => ChampionSpawnType.Abyss, + 4 => ChampionSpawnType.Arachnid, + _ => Type + }; + + HasBeenAdvanced = false; + + Start(); + } + + private ScrollofTranscendence CreateRandomSoT(bool felucca) + { + var level = Utility.RandomMinMax(1, 5); + + if (felucca) + level += 5; + + return ScrollofTranscendence.CreateRandom(level, level); + } + + public static void GiveScrollTo(Mobile killer, SpecialScroll scroll) + { + if (scroll == null || killer == null) // sanity + return; + + if (scroll is ScrollofTranscendence) + killer.SendLocalizedMessage(1094936); // You have received a Scroll of Transcendence! + else + killer.SendLocalizedMessage(1049524); // You have received a scroll of power! + + if (killer.Alive) + { + killer.AddToBackpack(scroll); + } + else + { + if (killer.Corpse.Deleted == false) + killer.Corpse.DropItem(scroll); + else + killer.AddToBackpack(scroll); + } + + // Justice reward + var pm = (PlayerMobile)killer; + for (var j = 0; j < pm.JusticeProtectors.Count; ++j) + { + var prot = pm.JusticeProtectors[j]; + + if (prot.Map != killer.Map || prot.Kills >= 5 || prot.Criminal || + !JusticeVirtue.CheckMapRegion(killer, prot)) + continue; + + var chance = VirtueHelper.GetLevel(prot, VirtueName.Justice) switch + { + VirtueLevel.Seeker => 60, + VirtueLevel.Follower => 80, + VirtueLevel.Knight => 100, + _ => 0 + }; + + if (chance > Utility.Random(100)) + try + { + prot.SendLocalizedMessage(1049368); // You have been rewarded for your dedication to Justice! + + if (ActivatorUtil.CreateInstance(scroll.GetType()) is SpecialScroll scrollDupe) + { + scrollDupe.Skill = scroll.Skill; + scrollDupe.Value = scroll.Value; + prot.AddToBackpack(scrollDupe); + } + } + catch + { + // ignored + } + } + } + + public void OnSlice() + { + if (!m_Active || Deleted) + return; + + if (Champion != null) + { + if (Champion.Deleted) + { + RegisterDamageTo(Champion); + + if (Champion is BaseChampion champion) + AwardArtifact(champion.GetArtifact()); + + m_DamageEntries.Clear(); + + if (m_Platform != null) + m_Platform.Hue = 0x497; + + if (m_Altar != null) + { + m_Altar.Hue = 0; + + if (!Core.ML || Map == Map.Felucca) + new StarRoomGate(m_Altar.Location, m_Altar.Map, true); + } + + Champion = null; + Stop(); + + BeginRestart(RestartDelay); + } + } + else + { + var kills = m_Kills; + + for (var i = 0; i < m_Creatures.Count; ++i) + { + var m = m_Creatures[i]; + + if (m.Deleted) + { + if (m.Corpse?.Deleted == false) + ((Corpse)m.Corpse).BeginDecay(TimeSpan.FromMinutes(1)); + + m_Creatures.RemoveAt(i); + --i; + ++m_Kills; + + var killer = m.FindMostRecentDamager(false); + + RegisterDamageTo(m); + + if (killer is BaseCreature bc) + killer = bc.GetMaster(); + + if (killer is PlayerMobile pm) + { + if (Core.ML) + { + if (Map == Map.Felucca) + if (Utility.RandomDouble() < 0.001) + { + double random = Utility.Random(49); + + if (random <= 24) + { + var SoTF = CreateRandomSoT(true); + GiveScrollTo(pm, SoTF); + } + else + { + var PS = PowerScroll.CreateRandomNoCraft(5, 5); + GiveScrollTo(pm, PS); + } + } + + if (Map == Map.Ilshenar || Map == Map.Tokuno || Map == Map.Malas) + if (Utility.RandomDouble() < 0.0015) + { + pm.SendLocalizedMessage(1094936); // You have received a Scroll of Transcendence! + var SoTT = CreateRandomSoT(false); + pm.AddToBackpack(SoTT); + } + } + + var mobSubLevel = GetSubLevelFor(m) + 1; + + if (mobSubLevel >= 0) + { + var gainedPath = false; + + var pointsToGain = mobSubLevel * 40; + + if (VirtueHelper.Award(pm, VirtueName.Valor, pointsToGain, ref gainedPath)) + { + if (gainedPath) + m.SendLocalizedMessage(1054032); // You have gained a path in Valor! + else + m.SendLocalizedMessage(1054030); // You have gained in Valor! + + // No delay on Valor gains + } + + var info = pm.ChampionTitles; + + info.Award(m_Type, mobSubLevel); + } + } + } + } + + // Only really needed once. + if (m_Kills > kills) + InvalidateProperties(); + + var n = m_Kills / (double)MaxKills; + var p = (int)(n * 100); + + if (p >= 90) + AdvanceLevel(); + else if (p > 0) + SetWhiteSkullCount(p / 20); + + if (DateTime.UtcNow >= ExpireTime) + Expire(); + + Respawn(); + } + } + + public void AdvanceLevel() + { + ExpireTime = DateTime.UtcNow + ExpireDelay; + + if (Level < 16) + { + m_Kills = 0; + ++Level; + InvalidateProperties(); + SetWhiteSkullCount(0); + + if (m_Altar != null) + { + Effects.PlaySound(m_Altar.Location, m_Altar.Map, 0x29); + Effects.SendLocationEffect( + new Point3D(m_Altar.X + 1, m_Altar.Y + 1, m_Altar.Z), + m_Altar.Map, + 0x3728, + 10 + ); + } + } + else + { + SpawnChampion(); + } + } + + public void SpawnChampion() + { + if (m_Altar != null) + m_Altar.Hue = 0x26; + + if (m_Platform != null) + m_Platform.Hue = 0x452; + + m_Kills = 0; + Level = 0; + InvalidateProperties(); + SetWhiteSkullCount(0); + + try + { + Champion = ActivatorUtil.CreateInstance(ChampionSpawnInfo.GetInfo(m_Type).Champion) as Mobile; + } + catch + { + // ignored + } + + Champion?.MoveToWorld(new Point3D(X, Y, Z - 15), Map); + } + + public void Respawn() + { + if (!m_Active || Deleted || Champion != null) + return; + + while (m_Creatures.Count < m_SPawnSzMod * (200 / 12) - GetSubLevel() * m_SPawnSzMod * (40 / 12)) + { + var m = Spawn(); + + if (m == null) + return; + + var loc = GetSpawnLocation(); + + // Allow creatures to turn into Paragons at Ilshenar champions. + m.OnBeforeSpawn(loc, Map); + + m_Creatures.Add(m); + m.MoveToWorld(loc, Map); + + if (m is BaseCreature bc) + { + bc.Tamable = false; + + if (!ConfinedRoaming) + { + bc.Home = Location; + bc.RangeHome = + (int)(Math.Sqrt( + m_SpawnArea.Width * m_SpawnArea.Width + + m_SpawnArea.Height * m_SpawnArea.Height + ) / 2); + } + else + { + bc.Home = bc.Location; + + var xWall1 = new Point2D(m_SpawnArea.X, bc.Y); + var xWall2 = new Point2D(m_SpawnArea.X + m_SpawnArea.Width, bc.Y); + var yWall1 = new Point2D(bc.X, m_SpawnArea.Y); + var yWall2 = new Point2D(bc.X, m_SpawnArea.Y + m_SpawnArea.Height); + + var minXDist = Math.Min(bc.GetDistanceToSqrt(xWall1), bc.GetDistanceToSqrt(xWall2)); + var minYDist = Math.Min(bc.GetDistanceToSqrt(yWall1), bc.GetDistanceToSqrt(yWall2)); + + bc.RangeHome = (int)Math.Min(minXDist, minYDist); + } + } + } + } + + public Point3D GetSpawnLocation() + { + var map = Map; + + if (map == null) + return Location; + + // Try 20 times to find a spawnable location. + for (var i = 0; i < 20; i++) + { + /* + int x = Location.X + (Utility.Random( (m_SpawnRange * 2) + 1 ) - m_SpawnRange); + int y = Location.Y + (Utility.Random( (m_SpawnRange * 2) + 1 ) - m_SpawnRange); + */ + + var x = Utility.Random(m_SpawnArea.X, m_SpawnArea.Width); + var y = Utility.Random(m_SpawnArea.Y, m_SpawnArea.Height); + + var z = Map.GetAverageZ(x, y); + + if (Map.CanSpawnMobile(new Point2D(x, y), z)) + return new Point3D(x, y, z); + + /* try @ platform Z if map z fails */ + if (Map.CanSpawnMobile(new Point2D(x, y), m_Platform.Location.Z)) + return new Point3D(x, y, m_Platform.Location.Z); + } + + return Location; + } + + public int GetSubLevel() + { + var level = Level; + + if (level <= Level1) + return 0; + if (level <= Level2) + return 1; + if (level <= Level3) + return 2; + + return 3; + } + + public int GetSubLevelFor(Mobile m) + { + var types = ChampionSpawnInfo.GetInfo(m_Type).SpawnTypes; + var t = m.GetType(); + + for (var i = 0; i < types.GetLength(0); i++) + { + var individualTypes = types[i]; + + for (var j = 0; j < individualTypes.Length; j++) + if (t == individualTypes[j]) + return i; + } + + return -1; + } + + public Mobile Spawn() + { + var types = ChampionSpawnInfo.GetInfo(m_Type).SpawnTypes; + + var v = GetSubLevel(); + + if (v >= 0 && v < types.Length) + return Spawn(types[v]); + + return null; + } + + public Mobile Spawn(params Type[] types) + { + try + { + return ActivatorUtil.CreateInstance(types.RandomElement()) as Mobile; + } + catch + { + return null; + } + } + + public void Expire() + { + m_Kills = 0; + + if (m_WhiteSkulls.Count == 0) + { + // They didn't even get 20%, go back a level + + if (Level > 0) + --Level; + + InvalidateProperties(); + } + else + { + SetWhiteSkullCount(0); + } + + ExpireTime = DateTime.UtcNow + ExpireDelay; + } + + public Point3D GetRedSkullLocation(int index) + { + int x, y; + + if (index < 5) + { + x = index - 2; + y = -2; + } + else if (index < 9) + { + x = 2; + y = index - 6; + } + else if (index < 13) + { + x = 10 - index; + y = 2; + } + else + { + x = -2; + y = 14 - index; + } + + return new Point3D(X + x, Y + y, Z - 15); + } + + public Point3D GetWhiteSkullLocation(int index) + { + int x, y; + + switch (index) + { + default: + x = -1; + y = -1; + break; + case 1: + x = 1; + y = -1; + break; + case 2: + x = 1; + y = 1; + break; + case 3: + x = -1; + y = 1; + break; + } + + return new Point3D(X + x, Y + y, Z - 15); + } + + public override void AddNameProperty(ObjectPropertyList list) + { + list.Add("champion spawn"); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_Active) + { + list.Add(1060742); // active + list.Add(1060658, "Type\t{0}", m_Type); // ~1_val~: ~2_val~ + list.Add(1060659, "Level\t{0}", Level); // ~1_val~: ~2_val~ + list.Add( + 1060660, + "Kills\t{0} of {1} ({2:F1}%)", + m_Kills, + MaxKills, + 100.0 * ((double)m_Kills / MaxKills) + ); // ~1_val~: ~2_val~ + // list.Add( 1060661, "Spawn Range\t{0}", m_SpawnRange ); // ~1_val~: ~2_val~ + } + else + { + list.Add(1060743); // inactive + } + } + + public override void OnSingleClick(Mobile from) + { + if (m_Active) + LabelTo(from, "{0} (Active; Level: {1}; Kills: {2}/{3})", m_Type, Level, m_Kills, MaxKills); + else + LabelTo(from, "{0} (Inactive)", m_Type); + } + + public override void OnDoubleClick(Mobile from) + { + from.SendGump(new PropertiesGump(from, this)); + } + + public override void OnLocationChange(Point3D oldLoc) + { + if (Deleted) + return; + + if (m_Platform != null) + m_Platform.Location = new Point3D(X, Y, Z - 20); + + if (m_Altar != null) + m_Altar.Location = new Point3D(X, Y, Z - 15); + + if (m_Idol != null) + m_Idol.Location = new Point3D(X, Y, Z - 15); + + if (m_RedSkulls != null) + for (var i = 0; i < m_RedSkulls.Count; ++i) + m_RedSkulls[i].Location = GetRedSkullLocation(i); + + if (m_WhiteSkulls != null) + for (var i = 0; i < m_WhiteSkulls.Count; ++i) + m_WhiteSkulls[i].Location = GetWhiteSkullLocation(i); + + m_SpawnArea.X += Location.X - oldLoc.X; + m_SpawnArea.Y += Location.Y - oldLoc.Y; + + UpdateRegion(); + } + + public override void OnMapChange() + { + if (Deleted) + return; + + if (m_Platform != null) + m_Platform.Map = Map; + + if (m_Altar != null) + m_Altar.Map = Map; + + if (m_Idol != null) + m_Idol.Map = Map; + + if (m_RedSkulls != null) + for (var i = 0; i < m_RedSkulls.Count; ++i) + m_RedSkulls[i].Map = Map; + + if (m_WhiteSkulls != null) + for (var i = 0; i < m_WhiteSkulls.Count; ++i) + m_WhiteSkulls[i].Map = Map; + + UpdateRegion(); + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Platform?.Delete(); + + m_Altar?.Delete(); + + m_Idol?.Delete(); + + if (m_RedSkulls != null) + { + for (var i = 0; i < m_RedSkulls.Count; ++i) + m_RedSkulls[i].Delete(); + + m_RedSkulls.Clear(); + } + + if (m_WhiteSkulls != null) + { + for (var i = 0; i < m_WhiteSkulls.Count; ++i) + m_WhiteSkulls[i].Delete(); + + m_WhiteSkulls.Clear(); + } + + if (m_Creatures != null) + { + for (var i = 0; i < m_Creatures.Count; ++i) + { + var mob = m_Creatures[i]; + + if (!mob.Player) + mob.Delete(); + } + + m_Creatures.Clear(); + } + + if (Champion?.Player == false) + Champion.Delete(); + + Stop(); + + UpdateRegion(); + } + + public virtual void RegisterDamageTo(Mobile m) + { + if (m == null) + return; + + foreach (var de in m.DamageEntries) + { + if (de.HasExpired) + continue; + + var damager = de.Damager; + + var master = damager.GetDamageMaster(m); + + if (master != null) + damager = master; + + RegisterDamage(damager, de.DamageGiven); + } + } + + public void RegisterDamage(Mobile from, int amount) + { + if (from?.Player != true) + return; + + m_DamageEntries[from] = amount + (m_DamageEntries.TryGetValue(from, out var value) ? value : 0); + } + + public void AwardArtifact(Item artifact) + { + if (artifact == null) + return; + + var totalDamage = 0; + + var validEntries = new Dictionary(); + + foreach (var kvp in m_DamageEntries) + if (IsEligible(kvp.Key, artifact)) + { + validEntries.Add(kvp.Key, kvp.Value); + totalDamage += kvp.Value; + } + + var randomDamage = Utility.RandomMinMax(1, totalDamage); + + totalDamage = 0; + + foreach (var kvp in validEntries) + { + totalDamage += kvp.Value; + + if (totalDamage >= randomDamage) + { + GiveArtifact(kvp.Key, artifact); + return; + } + } + + artifact.Delete(); + } + + public void GiveArtifact(Mobile to, Item artifact) + { + if (to == null || artifact == null) + return; + + var pack = to.Backpack; + + if (pack?.TryDropItem(to, artifact, false) != true) + artifact.Delete(); + else + to.SendLocalizedMessage( + 1062317 + ); // For your valor in combating the fallen beast, a special artifact has been bestowed on you. + } + + public bool IsEligible(Mobile m, Item artifact) => + m.Player && m.Alive && m.Region != null && m.Region == m_Region && + m.Backpack?.CheckHold(m, artifact, false) == true; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(6); // version + + writer.Write(m_SPawnSzMod); + writer.Write(m_DamageEntries.Count); + foreach (var kvp in m_DamageEntries) + { + writer.Write(kvp.Key); + writer.Write(kvp.Value); + } + + writer.Write(ConfinedRoaming); + writer.WriteItem(m_Idol); + writer.Write(HasBeenAdvanced); + writer.Write(m_SpawnArea); + + writer.Write(RandomizeType); + + // writer.Write( m_SpawnRange ); + writer.Write(m_Kills); + + writer.Write(m_Active); + writer.Write((int)m_Type); + writer.Write(m_Creatures, true); + writer.Write(m_RedSkulls, true); + writer.Write(m_WhiteSkulls, true); + writer.WriteItem(m_Platform); + writer.WriteItem(m_Altar); + writer.Write(ExpireDelay); + writer.WriteDeltaTime(ExpireTime); + writer.Write(Champion); + writer.Write(RestartDelay); + + writer.Write(m_RestartTimer != null); + + if (m_RestartTimer != null) + writer.WriteDeltaTime(RestartTime); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + m_DamageEntries = new Dictionary(); + + var version = reader.ReadInt(); + + switch (version) + { + case 6: + { + m_SPawnSzMod = reader.ReadInt(); + goto case 5; + } + case 5: + { + var entries = reader.ReadInt(); + for (var i = 0; i < entries; ++i) + { + var m = reader.ReadMobile(); + var damage = reader.ReadInt(); + + if (m == null) + continue; + + m_DamageEntries.Add(m, damage); + } + + goto case 4; + } + case 4: + { + ConfinedRoaming = reader.ReadBool(); + m_Idol = reader.ReadItem(); + HasBeenAdvanced = reader.ReadBool(); + + goto case 3; + } + case 3: + { + m_SpawnArea = reader.ReadRect2D(); + + goto case 2; + } + case 2: + { + RandomizeType = reader.ReadBool(); + + goto case 1; + } + case 1: + { + if (version < 3) + { + var oldRange = reader.ReadInt(); + + m_SpawnArea = new Rectangle2D( + new Point2D(X - oldRange, Y - oldRange), + new Point2D(X + oldRange, Y + oldRange) + ); + } + + m_Kills = reader.ReadInt(); + + goto case 0; + } + case 0: + { + if (version < 1) + m_SpawnArea = + new Rectangle2D(new Point2D(X - 24, Y - 24), new Point2D(X + 24, Y + 24)); // Default was 24 + + var active = reader.ReadBool(); + m_Type = (ChampionSpawnType)reader.ReadInt(); + m_Creatures = reader.ReadStrongMobileList(); + m_RedSkulls = reader.ReadStrongItemList(); + m_WhiteSkulls = reader.ReadStrongItemList(); + m_Platform = reader.ReadItem(); + m_Altar = reader.ReadItem(); + ExpireDelay = reader.ReadTimeSpan(); + ExpireTime = reader.ReadDeltaTime(); + Champion = reader.ReadMobile(); + RestartDelay = reader.ReadTimeSpan(); + + if (reader.ReadBool()) + { + RestartTime = reader.ReadDeltaTime(); + BeginRestart(RestartTime - DateTime.UtcNow); + } + + if (version < 4) + { + m_Idol = new IdolOfTheChampion(this); + m_Idol.MoveToWorld(new Point3D(X, Y, Z - 15), Map); + } + + if (m_Platform == null || m_Altar == null || m_Idol == null) + Delete(); + else if (active) + Start(); + + break; + } + } + + Timer.DelayCall(UpdateRegion); + } + } + + public class ChampionSpawnRegion : BaseRegion + { + public ChampionSpawnRegion(ChampionSpawn spawn) : base( + null, + spawn.Map, + Find(spawn.Location, spawn.Map), + spawn.SpawnArea + ) => + ChampionSpawn = spawn; + + public override bool YoungProtected => false; + + public ChampionSpawn ChampionSpawn { get; } + + public override bool AllowHousing(Mobile from, Point3D p) => false; + + public override void AlterLightLevel(Mobile m, ref int global, ref int personal) + { + base.AlterLightLevel(m, ref global, ref personal); + global = Math.Max( + global, + 1 + ChampionSpawn + .Level + ); // This is a guesstimate. TODO: Verify & get exact values // OSI testing: at 2 red skulls, light = 0x3 ; 1 red = 0x3.; 3 = 8; 9 = 0xD 8 = 0xD 12 = 0x12 10 = 0xD + } + } + + public class IdolOfTheChampion : Item + { + public IdolOfTheChampion(ChampionSpawn spawn) : base(0x1F18) + { + Spawn = spawn; + Movable = false; + } + + public IdolOfTheChampion(Serial serial) : base(serial) + { + } + + public ChampionSpawn Spawn { get; private set; } + + public override string DefaultName => "Idol of the Champion"; + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + Spawn?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(Spawn); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Spawn = reader.ReadItem() as ChampionSpawn; + + if (Spawn == null) + Delete(); + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/CannedEvil/ChampionSpawnType.cs b/Projects/UOContent/Engines/CannedEvil/ChampionSpawnType.cs index 328de63f0..ab166ee66 100644 --- a/Projects/UOContent/Engines/CannedEvil/ChampionSpawnType.cs +++ b/Projects/UOContent/Engines/CannedEvil/ChampionSpawnType.cs @@ -1,133 +1,174 @@ -using System; -using Server.Mobiles; - -namespace Server.Engines.CannedEvil -{ - public enum ChampionSpawnType - { - Abyss, - Arachnid, - ColdBlood, - ForestLord, - VerminHorde, - UnholyTerror, - SleepingDragon, - Glade, - Pestilence - } - - public class ChampionSpawnInfo - { - public ChampionSpawnInfo(string name, Type champion, string[] levelNames, Type[][] spawnTypes) - { - Name = name; - Champion = champion; - LevelNames = levelNames; - SpawnTypes = spawnTypes; - } - - public string Name { get; } - - public Type Champion { get; } - - public Type[][] SpawnTypes { get; } - - public string[] LevelNames { get; } - - public static ChampionSpawnInfo[] Table { get; } = - { - new ChampionSpawnInfo("Abyss", typeof(Semidar), new[] { "Foe", "Assassin", "Conqueror" }, new[] // Abyss - { - // Abyss - new[] { typeof(GreaterMongbat), typeof(Imp) }, // Level 1 - new[] { typeof(Gargoyle), typeof(Harpy) }, // Level 2 - new[] { typeof(FireGargoyle), typeof(StoneGargoyle) }, // Level 3 - new[] { typeof(Daemon), typeof(Succubus) } // Level 4 - }), - new ChampionSpawnInfo("Arachnid", typeof(Mephitis), new[] { "Bane", "Killer", "Vanquisher" }, new[] // Arachnid - { - // Arachnid - new[] { typeof(Scorpion), typeof(GiantSpider) }, // Level 1 - new[] { typeof(TerathanDrone), typeof(TerathanWarrior) }, // Level 2 - new[] { typeof(DreadSpider), typeof(TerathanMatriarch) }, // Level 3 - new[] { typeof(PoisonElemental), typeof(TerathanAvenger) } // Level 4 - }), - new ChampionSpawnInfo("Cold Blood", typeof(Rikktor), new[] { "Blight", "Slayer", "Destroyer" }, - new[] // Cold Blood - { - // Cold Blood - new[] { typeof(Lizardman), typeof(Snake) }, // Level 1 - new[] { typeof(LavaLizard), typeof(OphidianWarrior) }, // Level 2 - new[] { typeof(Drake), typeof(OphidianArchmage) }, // Level 3 - new[] { typeof(Dragon), typeof(OphidianKnight) } // Level 4 - }), - new ChampionSpawnInfo("Forest Lord", typeof(LordOaks), new[] { "Enemy", "Curse", "Slaughterer" }, - new[] // Forest Lord - { - // Forest Lord - new[] { typeof(Pixie), typeof(ShadowWisp) }, // Level 1 - new[] { typeof(Kirin), typeof(Wisp) }, // Level 2 - new[] { typeof(Centaur), typeof(Unicorn) }, // Level 3 - new[] { typeof(EtherealWarrior), typeof(SerpentineDragon) } // Level 4 - }), - new ChampionSpawnInfo("Vermin Horde", typeof(Barracoon), new[] { "Adversary", "Subjugator", "Eradicator" }, - new[] // Vermin Horde - { - // Vermin Horde - new[] { typeof(GiantRat), typeof(Slime) }, // Level 1 - new[] { typeof(DireWolf), typeof(Ratman) }, // Level 2 - new[] { typeof(HellHound), typeof(RatmanMage) }, // Level 3 - new[] { typeof(RatmanArcher), typeof(SilverSerpent) } // Level 4 - }), - new ChampionSpawnInfo("Unholy Terror", typeof(Neira), new[] { "Scourge", "Punisher", "Nemesis" }, - new[] // Unholy Terror - { - // Unholy Terror - Core.AOS - ? new[] - { - typeof(Bogle), typeof(Ghoul), typeof(Shade), typeof(Spectre), typeof(Wraith) - } // Level 1 (Pre-AoS) - : new[] { typeof(Ghoul), typeof(Shade), typeof(Spectre), typeof(Wraith) }, // Level 1 - - new[] { typeof(BoneMagi), typeof(Mummy), typeof(SkeletalMage) }, // Level 2 - new[] { typeof(BoneKnight), typeof(Lich), typeof(SkeletalKnight) }, // Level 3 - new[] { typeof(LichLord), typeof(RottingCorpse) } // Level 4 - }), - new ChampionSpawnInfo("Sleeping Dragon", typeof(Serado), new[] { "Rival", "Challenger", "Antagonist" }, new[] - { - // Unholy Terror - new[] { typeof(DeathwatchBeetleHatchling), typeof(Lizardman) }, - new[] { typeof(DeathwatchBeetle), typeof(Kappa) }, - new[] { typeof(LesserHiryu), typeof(RevenantLion) }, - new[] { typeof(Hiryu), typeof(Oni) } - }), - new ChampionSpawnInfo("Glade", typeof(Twaulo), new[] { "Banisher", "Enforcer", "Eradicator" }, new[] - { - // Glade - new[] { typeof(Pixie), typeof(ShadowWisp) }, - new[] { typeof(Centaur), typeof(MLDryad) }, - new[] { typeof(Satyr), typeof(CuSidhe) }, - new[] { typeof(FeralTreefellow), typeof(RagingGrizzlyBear) } - }), - new ChampionSpawnInfo("The Corrupt", typeof(Ilhenir), new[] { "Cleanser", "Expunger", "Depurator" }, new[] - { - // Unholy Terror - new[] { typeof(PlagueSpawn), typeof(Bogling) }, - new[] { typeof(PlagueBeast), typeof(BogThing) }, - new[] { typeof(PlagueBeastLord), typeof(InterredGrizzle) }, - new[] { typeof(FetidEssence), typeof(PestilentBandage) } - }) - }; - - public static ChampionSpawnInfo GetInfo(ChampionSpawnType type) - { - int v = (int)type; - - if (v < 0 || v >= Table.Length) - v = 0; - - return Table[v]; - } - } -} \ No newline at end of file +using System; +using Server.Mobiles; + +namespace Server.Engines.CannedEvil +{ + public enum ChampionSpawnType + { + Abyss, + Arachnid, + ColdBlood, + ForestLord, + VerminHorde, + UnholyTerror, + SleepingDragon, + Glade, + Pestilence + } + + public class ChampionSpawnInfo + { + public ChampionSpawnInfo(string name, Type champion, string[] levelNames, Type[][] spawnTypes) + { + Name = name; + Champion = champion; + LevelNames = levelNames; + SpawnTypes = spawnTypes; + } + + public string Name { get; } + + public Type Champion { get; } + + public Type[][] SpawnTypes { get; } + + public string[] LevelNames { get; } + + public static ChampionSpawnInfo[] Table { get; } = + { + new ChampionSpawnInfo( + "Abyss", + typeof(Semidar), + new[] { "Foe", "Assassin", "Conqueror" }, + new[] // Abyss + { + // Abyss + new[] { typeof(GreaterMongbat), typeof(Imp) }, // Level 1 + new[] { typeof(Gargoyle), typeof(Harpy) }, // Level 2 + new[] { typeof(FireGargoyle), typeof(StoneGargoyle) }, // Level 3 + new[] { typeof(Daemon), typeof(Succubus) } // Level 4 + } + ), + new ChampionSpawnInfo( + "Arachnid", + typeof(Mephitis), + new[] { "Bane", "Killer", "Vanquisher" }, + new[] // Arachnid + { + // Arachnid + new[] { typeof(Scorpion), typeof(GiantSpider) }, // Level 1 + new[] { typeof(TerathanDrone), typeof(TerathanWarrior) }, // Level 2 + new[] { typeof(DreadSpider), typeof(TerathanMatriarch) }, // Level 3 + new[] { typeof(PoisonElemental), typeof(TerathanAvenger) } // Level 4 + } + ), + new ChampionSpawnInfo( + "Cold Blood", + typeof(Rikktor), + new[] { "Blight", "Slayer", "Destroyer" }, + new[] // Cold Blood + { + // Cold Blood + new[] { typeof(Lizardman), typeof(Snake) }, // Level 1 + new[] { typeof(LavaLizard), typeof(OphidianWarrior) }, // Level 2 + new[] { typeof(Drake), typeof(OphidianArchmage) }, // Level 3 + new[] { typeof(Dragon), typeof(OphidianKnight) } // Level 4 + } + ), + new ChampionSpawnInfo( + "Forest Lord", + typeof(LordOaks), + new[] { "Enemy", "Curse", "Slaughterer" }, + new[] // Forest Lord + { + // Forest Lord + new[] { typeof(Pixie), typeof(ShadowWisp) }, // Level 1 + new[] { typeof(Kirin), typeof(Wisp) }, // Level 2 + new[] { typeof(Centaur), typeof(Unicorn) }, // Level 3 + new[] { typeof(EtherealWarrior), typeof(SerpentineDragon) } // Level 4 + } + ), + new ChampionSpawnInfo( + "Vermin Horde", + typeof(Barracoon), + new[] { "Adversary", "Subjugator", "Eradicator" }, + new[] // Vermin Horde + { + // Vermin Horde + new[] { typeof(GiantRat), typeof(Slime) }, // Level 1 + new[] { typeof(DireWolf), typeof(Ratman) }, // Level 2 + new[] { typeof(HellHound), typeof(RatmanMage) }, // Level 3 + new[] { typeof(RatmanArcher), typeof(SilverSerpent) } // Level 4 + } + ), + new ChampionSpawnInfo( + "Unholy Terror", + typeof(Neira), + new[] { "Scourge", "Punisher", "Nemesis" }, + new[] // Unholy Terror + { + // Unholy Terror + Core.AOS + ? new[] + { + typeof(Bogle), typeof(Ghoul), typeof(Shade), typeof(Spectre), typeof(Wraith) + } // Level 1 (Pre-AoS) + : new[] { typeof(Ghoul), typeof(Shade), typeof(Spectre), typeof(Wraith) }, // Level 1 + + new[] { typeof(BoneMagi), typeof(Mummy), typeof(SkeletalMage) }, // Level 2 + new[] { typeof(BoneKnight), typeof(Lich), typeof(SkeletalKnight) }, // Level 3 + new[] { typeof(LichLord), typeof(RottingCorpse) } // Level 4 + } + ), + new ChampionSpawnInfo( + "Sleeping Dragon", + typeof(Serado), + new[] { "Rival", "Challenger", "Antagonist" }, + new[] + { + // Unholy Terror + new[] { typeof(DeathwatchBeetleHatchling), typeof(Lizardman) }, + new[] { typeof(DeathwatchBeetle), typeof(Kappa) }, + new[] { typeof(LesserHiryu), typeof(RevenantLion) }, + new[] { typeof(Hiryu), typeof(Oni) } + } + ), + new ChampionSpawnInfo( + "Glade", + typeof(Twaulo), + new[] { "Banisher", "Enforcer", "Eradicator" }, + new[] + { + // Glade + new[] { typeof(Pixie), typeof(ShadowWisp) }, + new[] { typeof(Centaur), typeof(MLDryad) }, + new[] { typeof(Satyr), typeof(CuSidhe) }, + new[] { typeof(FeralTreefellow), typeof(RagingGrizzlyBear) } + } + ), + new ChampionSpawnInfo( + "The Corrupt", + typeof(Ilhenir), + new[] { "Cleanser", "Expunger", "Depurator" }, + new[] + { + // Unholy Terror + new[] { typeof(PlagueSpawn), typeof(Bogling) }, + new[] { typeof(PlagueBeast), typeof(BogThing) }, + new[] { typeof(PlagueBeastLord), typeof(InterredGrizzle) }, + new[] { typeof(FetidEssence), typeof(PestilentBandage) } + } + ) + }; + + public static ChampionSpawnInfo GetInfo(ChampionSpawnType type) + { + var v = (int)type; + + if (v < 0 || v >= Table.Length) + v = 0; + + return Table[v]; + } + } +} diff --git a/Projects/UOContent/Engines/CannedEvil/HarrowerGate.cs b/Projects/UOContent/Engines/CannedEvil/HarrowerGate.cs index 8709a32cc..389ef8dae 100644 --- a/Projects/UOContent/Engines/CannedEvil/HarrowerGate.cs +++ b/Projects/UOContent/Engines/CannedEvil/HarrowerGate.cs @@ -1,56 +1,56 @@ -namespace Server.Items -{ - public class HarrowerGate : Moongate - { - private Mobile m_Harrower; - - public HarrowerGate(Mobile harrower, Point3D loc, Map map, Point3D targLoc, Map targMap) : base(targLoc, targMap) - { - m_Harrower = harrower; - - Dispellable = false; - ItemID = 0x1FD4; - Light = LightType.Circle300; - - MoveToWorld(loc, map); - } - - public HarrowerGate(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1049498; // dark moongate - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Harrower); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Harrower = reader.ReadMobile(); - - if (m_Harrower == null) - Delete(); - - break; - } - } - - if (Light != LightType.Circle300) - Light = LightType.Circle300; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class HarrowerGate : Moongate + { + private Mobile m_Harrower; + + public HarrowerGate(Mobile harrower, Point3D loc, Map map, Point3D targLoc, Map targMap) : base(targLoc, targMap) + { + m_Harrower = harrower; + + Dispellable = false; + ItemID = 0x1FD4; + Light = LightType.Circle300; + + MoveToWorld(loc, map); + } + + public HarrowerGate(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1049498; // dark moongate + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Harrower); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Harrower = reader.ReadMobile(); + + if (m_Harrower == null) + Delete(); + + break; + } + } + + if (Light != LightType.Circle300) + Light = LightType.Circle300; + } + } +} diff --git a/Projects/UOContent/Engines/CannedEvil/RestartTimer.cs b/Projects/UOContent/Engines/CannedEvil/RestartTimer.cs index 7b30fbfd7..494066791 100644 --- a/Projects/UOContent/Engines/CannedEvil/RestartTimer.cs +++ b/Projects/UOContent/Engines/CannedEvil/RestartTimer.cs @@ -1,20 +1,20 @@ -using System; - -namespace Server.Engines.CannedEvil -{ - public class RestartTimer : Timer - { - private readonly ChampionSpawn m_Spawn; - - public RestartTimer(ChampionSpawn spawn, TimeSpan delay) : base(delay) - { - m_Spawn = spawn; - Priority = TimerPriority.FiveSeconds; - } - - protected override void OnTick() - { - m_Spawn.EndRestart(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Engines.CannedEvil +{ + public class RestartTimer : Timer + { + private readonly ChampionSpawn m_Spawn; + + public RestartTimer(ChampionSpawn spawn, TimeSpan delay) : base(delay) + { + m_Spawn = spawn; + Priority = TimerPriority.FiveSeconds; + } + + protected override void OnTick() + { + m_Spawn.EndRestart(); + } + } +} diff --git a/Projects/UOContent/Engines/CannedEvil/SliceTimer.cs b/Projects/UOContent/Engines/CannedEvil/SliceTimer.cs index 99b69495d..8a9abc2a1 100644 --- a/Projects/UOContent/Engines/CannedEvil/SliceTimer.cs +++ b/Projects/UOContent/Engines/CannedEvil/SliceTimer.cs @@ -1,20 +1,20 @@ -using System; - -namespace Server.Engines.CannedEvil -{ - public class SliceTimer : Timer - { - private readonly ChampionSpawn m_Spawn; - - public SliceTimer(ChampionSpawn spawn) : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)) - { - m_Spawn = spawn; - Priority = TimerPriority.OneSecond; - } - - protected override void OnTick() - { - m_Spawn.OnSlice(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Engines.CannedEvil +{ + public class SliceTimer : Timer + { + private readonly ChampionSpawn m_Spawn; + + public SliceTimer(ChampionSpawn spawn) : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)) + { + m_Spawn = spawn; + Priority = TimerPriority.OneSecond; + } + + protected override void OnTick() + { + m_Spawn.OnSlice(); + } + } +} diff --git a/Projects/UOContent/Engines/CannedEvil/StarRoomGate.cs b/Projects/UOContent/Engines/CannedEvil/StarRoomGate.cs index b8787d637..fa7991f74 100644 --- a/Projects/UOContent/Engines/CannedEvil/StarRoomGate.cs +++ b/Projects/UOContent/Engines/CannedEvil/StarRoomGate.cs @@ -1,96 +1,96 @@ -using System; - -namespace Server.Items -{ - public class StarRoomGate : Moongate - { - private bool m_Decays; - private DateTime m_DecayTime; - private Timer m_Timer; - - [Constructible] - public StarRoomGate(Point3D loc, Map map, bool decays) : this(decays) - { - MoveToWorld(loc, map); - Effects.PlaySound(loc, map, 0x20E); - } - - [Constructible] - public StarRoomGate(bool decays = false) : base(new Point3D(5143, 1774, 0), Map.Felucca) - { - Dispellable = false; - ItemID = 0x1FD4; - - if (decays) - { - m_Decays = true; - m_DecayTime = DateTime.UtcNow + TimeSpan.FromMinutes(2.0); - - m_Timer = new InternalTimer(this, m_DecayTime); - m_Timer.Start(); - } - } - - public StarRoomGate(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1049498; // dark moongate - - public override void OnAfterDelete() - { - m_Timer?.Stop(); - - base.OnAfterDelete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Decays); - - if (m_Decays) - writer.WriteDeltaTime(m_DecayTime); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Decays = reader.ReadBool(); - - if (m_Decays) - { - m_DecayTime = reader.ReadDeltaTime(); - - m_Timer = new InternalTimer(this, m_DecayTime); - m_Timer.Start(); - } - - break; - } - } - } - - private class InternalTimer : Timer - { - private readonly Item m_Item; - - public InternalTimer(Item item, DateTime end) : base(end - DateTime.UtcNow) => m_Item = item; - - protected override void OnTick() - { - m_Item.Delete(); - } - } - } -} +using System; + +namespace Server.Items +{ + public class StarRoomGate : Moongate + { + private bool m_Decays; + private DateTime m_DecayTime; + private Timer m_Timer; + + [Constructible] + public StarRoomGate(Point3D loc, Map map, bool decays) : this(decays) + { + MoveToWorld(loc, map); + Effects.PlaySound(loc, map, 0x20E); + } + + [Constructible] + public StarRoomGate(bool decays = false) : base(new Point3D(5143, 1774, 0), Map.Felucca) + { + Dispellable = false; + ItemID = 0x1FD4; + + if (decays) + { + m_Decays = true; + m_DecayTime = DateTime.UtcNow + TimeSpan.FromMinutes(2.0); + + m_Timer = new InternalTimer(this, m_DecayTime); + m_Timer.Start(); + } + } + + public StarRoomGate(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1049498; // dark moongate + + public override void OnAfterDelete() + { + m_Timer?.Stop(); + + base.OnAfterDelete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Decays); + + if (m_Decays) + writer.WriteDeltaTime(m_DecayTime); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Decays = reader.ReadBool(); + + if (m_Decays) + { + m_DecayTime = reader.ReadDeltaTime(); + + m_Timer = new InternalTimer(this, m_DecayTime); + m_Timer.Start(); + } + + break; + } + } + } + + private class InternalTimer : Timer + { + private readonly Item m_Item; + + public InternalTimer(Item item, DateTime end) : base(end - DateTime.UtcNow) => m_Item = item; + + protected override void OnTick() + { + m_Item.Delete(); + } + } + } +} diff --git a/Projects/UOContent/Engines/Chat/Channel.cs b/Projects/UOContent/Engines/Chat/Channel.cs index f58a7ef14..a4de585e2 100644 --- a/Projects/UOContent/Engines/Chat/Channel.cs +++ b/Projects/UOContent/Engines/Chat/Channel.cs @@ -1,416 +1,429 @@ -using System.Collections.Generic; - -namespace Server.Engines.Chat -{ - public class Channel - { - private string m_Name; - private string m_Password; - private readonly List m_Users; - private readonly List m_Banned; - private readonly List m_Moderators; - private readonly List m_Voices; - private bool m_VoiceRestricted; - - public Channel(string name) - { - m_Name = name; - - m_Users = new List(); - m_Banned = new List(); - m_Moderators = new List(); - m_Voices = new List(); - } - - public Channel(string name, string password) : this(name) => m_Password = password; - - public string Name - { - get => m_Name; - set - { - SendCommand(ChatCommand.RemoveChannel, m_Name); - m_Name = value; - SendCommand(ChatCommand.AddChannel, m_Name); - SendCommand(ChatCommand.JoinedChannel, m_Name); - } - } - - public string Password - { - get => m_Password; - set => m_Password = value?.Trim().IsNullOrDefault(null); - } - - public bool VoiceRestricted - { - get => m_VoiceRestricted; - set - { - m_VoiceRestricted = value; - - if (value) - SendMessage(56); // From now on, only moderators will have speaking privileges in this conference by default. - else - SendMessage(55); // From now on, everyone in the conference will have speaking privileges by default. - } - } - - public bool AlwaysAvailable { get; set; } - - public static List Channels { get; } = new List(); - - public bool Contains(ChatUser user) => m_Users.Contains(user); - - public bool IsBanned(ChatUser user) => m_Banned.Contains(user); - - public bool CanTalk(ChatUser user) => !m_VoiceRestricted || m_Voices.Contains(user) || m_Moderators.Contains(user); - - public bool IsModerator(ChatUser user) => m_Moderators.Contains(user); - - public bool IsVoiced(ChatUser user) => m_Voices.Contains(user); - - public bool ValidatePassword(string password) => m_Password == null || Insensitive.Equals(m_Password, password); - - public bool ValidateModerator(ChatUser user) - { - if (user != null && !IsModerator(user)) - { - user.SendMessage(29); // You must have operator status to do this. - return false; - } - - return true; - } - - public bool ValidateAccess(ChatUser from, ChatUser target) - { - if (from == null || target == null || from.Mobile.AccessLevel >= target.Mobile.AccessLevel) - return true; - - from.Mobile.SendMessage("Your access level is too low to do this."); - return false; - } - - public bool AddUser(ChatUser user, string password = null) - { - if (Contains(user)) - { - user.SendMessage(46, m_Name); // You are already in the conference '%1'. - return true; - } - - if (IsBanned(user)) - { - user.SendMessage(64); // You have been banned from this conference. - return false; - } - - if (!ValidatePassword(password)) - { - user.SendMessage(34); // That is not the correct password. - return false; - } - - user.CurrentChannel?.RemoveUser(user); // Remove them from their current channel first - - ChatSystem.SendCommandTo(user.Mobile, ChatCommand.JoinedChannel, m_Name); - - SendCommand(ChatCommand.AddUserToChannel, user.GetColorCharacter() + user.Username); - - m_Users.Add(user); - user.CurrentChannel = this; - - if (user.Mobile.AccessLevel >= AccessLevel.GameMaster || (!AlwaysAvailable && m_Users.Count == 1)) - AddModerator(user); - - SendUsersTo(user); - - return true; - } - - public void RemoveUser(ChatUser user) - { - if (Contains(user)) - { - m_Users.Remove(user); - user.CurrentChannel = null; - - if (m_Moderators.Contains(user)) - m_Moderators.Remove(user); - - if (m_Voices.Contains(user)) - m_Voices.Remove(user); - - SendCommand(ChatCommand.RemoveUserFromChannel, user, user.Username); - ChatSystem.SendCommandTo(user.Mobile, ChatCommand.LeaveChannel); - - if (m_Users.Count == 0 && !AlwaysAvailable) - RemoveChannel(this); - } - } - - public void AddBan(ChatUser user, ChatUser moderator = null) - { - if (!ValidateModerator(moderator) || !ValidateAccess(moderator, user)) - return; - - if (!m_Banned.Contains(user)) - m_Banned.Add(user); - - Kick(user, moderator, true); - } - - public void RemoveBan(ChatUser user) - { - if (m_Banned.Contains(user)) - m_Banned.Remove(user); - } - - public void Kick(ChatUser user, ChatUser moderator = null) - { - Kick(user, moderator, false); - } - - public void Kick(ChatUser user, ChatUser moderator, bool wasBanned) - { - if (!ValidateModerator(moderator) || !ValidateAccess(moderator, user)) - return; - - if (Contains(user)) - { - if (moderator != null) - { - if (wasBanned) - user.SendMessage(63, - moderator.Username); // %1, a conference moderator, has banned you from the conference. - else - user.SendMessage(45, - moderator.Username); // %1, a conference moderator, has kicked you out of the conference. - } - - RemoveUser(user); - ChatSystem.SendCommandTo(user.Mobile, ChatCommand.AddUserToChannel, - user.GetColorCharacter() + user.Username); - - SendMessage(44, user.Username); // %1 has been kicked out of the conference. - } - - if (wasBanned) - moderator?.SendMessage(62, user.Username); // You are banning %1 from this conference. - } - - public void AddVoiced(ChatUser user, ChatUser moderator = null) - { - if (!ValidateModerator(moderator)) - return; - - if (!IsBanned(user) && !IsModerator(user) && !IsVoiced(user)) - { - m_Voices.Add(user); - - if (moderator != null) - user.SendMessage(54, - moderator - .Username); // %1, a conference moderator, has granted you speaking privileges in this conference. - - SendMessage(52, user, user.Username); // %1 now has speaking privileges in this conference. - SendCommand(ChatCommand.AddUserToChannel, user, user.GetColorCharacter() + user.Username); - } - } - - public void RemoveVoiced(ChatUser user, ChatUser moderator) - { - if (!ValidateModerator(moderator) || !ValidateAccess(moderator, user)) - return; - - if (!IsModerator(user) && IsVoiced(user)) - { - m_Voices.Remove(user); - - if (moderator != null) - user.SendMessage(53, - moderator - .Username); // %1, a conference moderator, has removed your speaking privileges for this conference. - - SendMessage(51, user, user.Username); // %1 no longer has speaking privileges in this conference. - SendCommand(ChatCommand.AddUserToChannel, user, user.GetColorCharacter() + user.Username); - } - } - - public void AddModerator(ChatUser user, ChatUser moderator = null) - { - if (!ValidateModerator(moderator)) - return; - - if (IsBanned(user) || IsModerator(user)) - return; - - if (IsVoiced(user)) - m_Voices.Remove(user); - - m_Moderators.Add(user); - - if (moderator != null) - user.SendMessage(50, moderator.Username); // %1 has made you a conference moderator. - - SendMessage(48, user, user.Username); // %1 is now a conference moderator. - SendCommand(ChatCommand.AddUserToChannel, user.GetColorCharacter() + user.Username); - } - - public void RemoveModerator(ChatUser user, ChatUser moderator = null) - { - if (!ValidateModerator(moderator) || !ValidateAccess(moderator, user)) - return; - - if (IsModerator(user)) - { - m_Moderators.Remove(user); - - if (moderator != null) - user.SendMessage(49, moderator.Username); // %1 has removed you from the list of conference moderators. - - SendMessage(47, user, user.Username); // %1 is no longer a conference moderator. - SendCommand(ChatCommand.AddUserToChannel, user.GetColorCharacter() + user.Username); - } - } - - public void SendMessage(int number, string param1 = null) - { - SendMessage(number, null, param1); - } - - public void SendMessage(int number, ChatUser initiator, string param1 = null, string param2 = null) - { - for (int i = 0; i < m_Users.Count; ++i) - { - ChatUser user = m_Users[i]; - - if (user == initiator) - continue; - - if (user.CheckOnline()) - user.SendMessage(number, param1, param2); - else if (!Contains(user)) - --i; - } - } - - public void SendIgnorableMessage(int number, ChatUser from, string param1, string param2) - { - for (int i = 0; i < m_Users.Count; ++i) - { - ChatUser user = m_Users[i]; - - if (user.IsIgnored(from)) - continue; - - if (user.CheckOnline()) - user.SendMessage(number, from.Mobile, param1, param2); - else if (!Contains(user)) - --i; - } - } - - public void SendCommand(ChatCommand command, string param1 = null, string param2 = null) - { - SendCommand(command, null, param1, param2); - } - - public void SendCommand(ChatCommand command, ChatUser initiator, string param1 = null, string param2 = null) - { - for (int i = 0; i < m_Users.Count; ++i) - { - ChatUser user = m_Users[i]; - - if (user == initiator) - continue; - - if (user.CheckOnline()) - ChatSystem.SendCommandTo(user.Mobile, command, param1, param2); - else if (!Contains(user)) - --i; - } - } - - public void SendUsersTo(ChatUser to) - { - for (int i = 0; i < m_Users.Count; ++i) - { - ChatUser user = m_Users[i]; - - ChatSystem.SendCommandTo(to.Mobile, ChatCommand.AddUserToChannel, user.GetColorCharacter() + user.Username); - } - } - - public static void SendChannelsTo(ChatUser user) - { - for (int i = 0; i < Channels.Count; ++i) - { - Channel channel = Channels[i]; - - if (!channel.IsBanned(user)) - ChatSystem.SendCommandTo(user.Mobile, ChatCommand.AddChannel, channel.Name, "0"); - } - } - - public static Channel AddChannel(string name, string password = null) - { - Channel channel = FindChannelByName(name); - - if (channel == null) - { - channel = new Channel(name, password); - Channels.Add(channel); - } - - ChatUser.GlobalSendCommand(ChatCommand.AddChannel, name, "0"); - - return channel; - } - - public static void RemoveChannel(string name) - { - RemoveChannel(FindChannelByName(name)); - } - - public static void RemoveChannel(Channel channel) - { - if (channel == null) - return; - - if (Channels.Contains(channel) && channel.m_Users.Count == 0) - { - ChatUser.GlobalSendCommand(ChatCommand.RemoveChannel, channel.Name); - - channel.m_Moderators.Clear(); - channel.m_Voices.Clear(); - - Channels.Remove(channel); - } - } - - public static Channel FindChannelByName(string name) - { - for (int i = 0; i < Channels.Count; ++i) - { - Channel channel = Channels[i]; - - if (channel.m_Name == name) - return channel; - } - - return null; - } - - public static void Initialize() - { - AddStaticChannel("Newbie Help"); - } - - public static void AddStaticChannel(string name) - { - AddChannel(name).AlwaysAvailable = true; - } - } -} +using System.Collections.Generic; + +namespace Server.Engines.Chat +{ + public class Channel + { + private readonly List m_Banned; + private readonly List m_Moderators; + private readonly List m_Users; + private readonly List m_Voices; + private string m_Name; + private string m_Password; + private bool m_VoiceRestricted; + + public Channel(string name) + { + m_Name = name; + + m_Users = new List(); + m_Banned = new List(); + m_Moderators = new List(); + m_Voices = new List(); + } + + public Channel(string name, string password) : this(name) => m_Password = password; + + public string Name + { + get => m_Name; + set + { + SendCommand(ChatCommand.RemoveChannel, m_Name); + m_Name = value; + SendCommand(ChatCommand.AddChannel, m_Name); + SendCommand(ChatCommand.JoinedChannel, m_Name); + } + } + + public string Password + { + get => m_Password; + set => m_Password = value?.Trim().IsNullOrDefault(null); + } + + public bool VoiceRestricted + { + get => m_VoiceRestricted; + set + { + m_VoiceRestricted = value; + + if (value) + SendMessage( + 56 + ); // From now on, only moderators will have speaking privileges in this conference by default. + else + SendMessage(55); // From now on, everyone in the conference will have speaking privileges by default. + } + } + + public bool AlwaysAvailable { get; set; } + + public static List Channels { get; } = new List(); + + public bool Contains(ChatUser user) => m_Users.Contains(user); + + public bool IsBanned(ChatUser user) => m_Banned.Contains(user); + + public bool CanTalk(ChatUser user) => !m_VoiceRestricted || m_Voices.Contains(user) || m_Moderators.Contains(user); + + public bool IsModerator(ChatUser user) => m_Moderators.Contains(user); + + public bool IsVoiced(ChatUser user) => m_Voices.Contains(user); + + public bool ValidatePassword(string password) => m_Password == null || Insensitive.Equals(m_Password, password); + + public bool ValidateModerator(ChatUser user) + { + if (user != null && !IsModerator(user)) + { + user.SendMessage(29); // You must have operator status to do this. + return false; + } + + return true; + } + + public bool ValidateAccess(ChatUser from, ChatUser target) + { + if (from == null || target == null || from.Mobile.AccessLevel >= target.Mobile.AccessLevel) + return true; + + from.Mobile.SendMessage("Your access level is too low to do this."); + return false; + } + + public bool AddUser(ChatUser user, string password = null) + { + if (Contains(user)) + { + user.SendMessage(46, m_Name); // You are already in the conference '%1'. + return true; + } + + if (IsBanned(user)) + { + user.SendMessage(64); // You have been banned from this conference. + return false; + } + + if (!ValidatePassword(password)) + { + user.SendMessage(34); // That is not the correct password. + return false; + } + + user.CurrentChannel?.RemoveUser(user); // Remove them from their current channel first + + ChatSystem.SendCommandTo(user.Mobile, ChatCommand.JoinedChannel, m_Name); + + SendCommand(ChatCommand.AddUserToChannel, user.GetColorCharacter() + user.Username); + + m_Users.Add(user); + user.CurrentChannel = this; + + if (user.Mobile.AccessLevel >= AccessLevel.GameMaster || !AlwaysAvailable && m_Users.Count == 1) + AddModerator(user); + + SendUsersTo(user); + + return true; + } + + public void RemoveUser(ChatUser user) + { + if (Contains(user)) + { + m_Users.Remove(user); + user.CurrentChannel = null; + + if (m_Moderators.Contains(user)) + m_Moderators.Remove(user); + + if (m_Voices.Contains(user)) + m_Voices.Remove(user); + + SendCommand(ChatCommand.RemoveUserFromChannel, user, user.Username); + ChatSystem.SendCommandTo(user.Mobile, ChatCommand.LeaveChannel); + + if (m_Users.Count == 0 && !AlwaysAvailable) + RemoveChannel(this); + } + } + + public void AddBan(ChatUser user, ChatUser moderator = null) + { + if (!ValidateModerator(moderator) || !ValidateAccess(moderator, user)) + return; + + if (!m_Banned.Contains(user)) + m_Banned.Add(user); + + Kick(user, moderator, true); + } + + public void RemoveBan(ChatUser user) + { + if (m_Banned.Contains(user)) + m_Banned.Remove(user); + } + + public void Kick(ChatUser user, ChatUser moderator = null) + { + Kick(user, moderator, false); + } + + public void Kick(ChatUser user, ChatUser moderator, bool wasBanned) + { + if (!ValidateModerator(moderator) || !ValidateAccess(moderator, user)) + return; + + if (Contains(user)) + { + if (moderator != null) + { + if (wasBanned) + user.SendMessage( + 63, + moderator.Username + ); // %1, a conference moderator, has banned you from the conference. + else + user.SendMessage( + 45, + moderator.Username + ); // %1, a conference moderator, has kicked you out of the conference. + } + + RemoveUser(user); + ChatSystem.SendCommandTo( + user.Mobile, + ChatCommand.AddUserToChannel, + user.GetColorCharacter() + user.Username + ); + + SendMessage(44, user.Username); // %1 has been kicked out of the conference. + } + + if (wasBanned) + moderator?.SendMessage(62, user.Username); // You are banning %1 from this conference. + } + + public void AddVoiced(ChatUser user, ChatUser moderator = null) + { + if (!ValidateModerator(moderator)) + return; + + if (!IsBanned(user) && !IsModerator(user) && !IsVoiced(user)) + { + m_Voices.Add(user); + + if (moderator != null) + user.SendMessage( + 54, + moderator + .Username + ); // %1, a conference moderator, has granted you speaking privileges in this conference. + + SendMessage(52, user, user.Username); // %1 now has speaking privileges in this conference. + SendCommand(ChatCommand.AddUserToChannel, user, user.GetColorCharacter() + user.Username); + } + } + + public void RemoveVoiced(ChatUser user, ChatUser moderator) + { + if (!ValidateModerator(moderator) || !ValidateAccess(moderator, user)) + return; + + if (!IsModerator(user) && IsVoiced(user)) + { + m_Voices.Remove(user); + + if (moderator != null) + user.SendMessage( + 53, + moderator + .Username + ); // %1, a conference moderator, has removed your speaking privileges for this conference. + + SendMessage(51, user, user.Username); // %1 no longer has speaking privileges in this conference. + SendCommand(ChatCommand.AddUserToChannel, user, user.GetColorCharacter() + user.Username); + } + } + + public void AddModerator(ChatUser user, ChatUser moderator = null) + { + if (!ValidateModerator(moderator)) + return; + + if (IsBanned(user) || IsModerator(user)) + return; + + if (IsVoiced(user)) + m_Voices.Remove(user); + + m_Moderators.Add(user); + + if (moderator != null) + user.SendMessage(50, moderator.Username); // %1 has made you a conference moderator. + + SendMessage(48, user, user.Username); // %1 is now a conference moderator. + SendCommand(ChatCommand.AddUserToChannel, user.GetColorCharacter() + user.Username); + } + + public void RemoveModerator(ChatUser user, ChatUser moderator = null) + { + if (!ValidateModerator(moderator) || !ValidateAccess(moderator, user)) + return; + + if (IsModerator(user)) + { + m_Moderators.Remove(user); + + if (moderator != null) + user.SendMessage(49, moderator.Username); // %1 has removed you from the list of conference moderators. + + SendMessage(47, user, user.Username); // %1 is no longer a conference moderator. + SendCommand(ChatCommand.AddUserToChannel, user.GetColorCharacter() + user.Username); + } + } + + public void SendMessage(int number, string param1 = null) + { + SendMessage(number, null, param1); + } + + public void SendMessage(int number, ChatUser initiator, string param1 = null, string param2 = null) + { + for (var i = 0; i < m_Users.Count; ++i) + { + var user = m_Users[i]; + + if (user == initiator) + continue; + + if (user.CheckOnline()) + user.SendMessage(number, param1, param2); + else if (!Contains(user)) + --i; + } + } + + public void SendIgnorableMessage(int number, ChatUser from, string param1, string param2) + { + for (var i = 0; i < m_Users.Count; ++i) + { + var user = m_Users[i]; + + if (user.IsIgnored(from)) + continue; + + if (user.CheckOnline()) + user.SendMessage(number, from.Mobile, param1, param2); + else if (!Contains(user)) + --i; + } + } + + public void SendCommand(ChatCommand command, string param1 = null, string param2 = null) + { + SendCommand(command, null, param1, param2); + } + + public void SendCommand(ChatCommand command, ChatUser initiator, string param1 = null, string param2 = null) + { + for (var i = 0; i < m_Users.Count; ++i) + { + var user = m_Users[i]; + + if (user == initiator) + continue; + + if (user.CheckOnline()) + ChatSystem.SendCommandTo(user.Mobile, command, param1, param2); + else if (!Contains(user)) + --i; + } + } + + public void SendUsersTo(ChatUser to) + { + for (var i = 0; i < m_Users.Count; ++i) + { + var user = m_Users[i]; + + ChatSystem.SendCommandTo(to.Mobile, ChatCommand.AddUserToChannel, user.GetColorCharacter() + user.Username); + } + } + + public static void SendChannelsTo(ChatUser user) + { + for (var i = 0; i < Channels.Count; ++i) + { + var channel = Channels[i]; + + if (!channel.IsBanned(user)) + ChatSystem.SendCommandTo(user.Mobile, ChatCommand.AddChannel, channel.Name, "0"); + } + } + + public static Channel AddChannel(string name, string password = null) + { + var channel = FindChannelByName(name); + + if (channel == null) + { + channel = new Channel(name, password); + Channels.Add(channel); + } + + ChatUser.GlobalSendCommand(ChatCommand.AddChannel, name, "0"); + + return channel; + } + + public static void RemoveChannel(string name) + { + RemoveChannel(FindChannelByName(name)); + } + + public static void RemoveChannel(Channel channel) + { + if (channel == null) + return; + + if (Channels.Contains(channel) && channel.m_Users.Count == 0) + { + ChatUser.GlobalSendCommand(ChatCommand.RemoveChannel, channel.Name); + + channel.m_Moderators.Clear(); + channel.m_Voices.Clear(); + + Channels.Remove(channel); + } + } + + public static Channel FindChannelByName(string name) + { + for (var i = 0; i < Channels.Count; ++i) + { + var channel = Channels[i]; + + if (channel.m_Name == name) + return channel; + } + + return null; + } + + public static void Initialize() + { + AddStaticChannel("Newbie Help"); + } + + public static void AddStaticChannel(string name) + { + AddChannel(name).AlwaysAvailable = true; + } + } +} diff --git a/Projects/UOContent/Engines/Chat/Chat.cs b/Projects/UOContent/Engines/Chat/Chat.cs index 2f38299bb..dd07b6834 100644 --- a/Projects/UOContent/Engines/Chat/Chat.cs +++ b/Projects/UOContent/Engines/Chat/Chat.cs @@ -1,151 +1,151 @@ -using System; -using System.IO; -using Server.Accounting; -using Server.Misc; -using Server.Network; - -namespace Server.Engines.Chat -{ - public class ChatSystem - { - public static bool Enabled { get; set; } = true; - - public static void Initialize() - { - PacketHandlers.Register(0xB5, 0x40, true, OpenChatWindowRequest); - PacketHandlers.Register(0xB3, 0, true, ChatAction); - } - - public static void SendCommandTo(Mobile to, ChatCommand type, string param1 = null, string param2 = null) - { - to?.Send(new ChatMessagePacket(null, (int)type + 20, param1, param2)); - } - - public static void OpenChatWindowRequest(NetState state, PacketReader pvSrc) - { - Mobile from = state.Mobile; - - if (!Enabled) - { - from.SendMessage("The chat system has been disabled."); - return; - } - - pvSrc.Seek(2, SeekOrigin.Begin); - string chatName = pvSrc.ReadUnicodeStringSafe(0x40 - 2 >> 1).Trim(); - - Account acct = state.Account as Account; - - string accountChatName = null; - - if (acct != null) - accountChatName = acct.GetTag("ChatName"); - - accountChatName = accountChatName?.Trim(); - - if (!string.IsNullOrEmpty(accountChatName)) - { - if (chatName.Length > 0 && chatName != accountChatName) - from.SendMessage("You cannot change chat nickname once it has been set."); - } - else - { - if (chatName.Length == 0) - { - SendCommandTo(from, ChatCommand.AskNewNickname); - return; - } - - if (NameVerification.Validate(chatName, 2, 31, true, true, true, 0, NameVerification.SpaceDashPeriodQuote) && - chatName.ToLower().IndexOf("system") == -1) - { - // TODO: Optimize this search - - foreach (Account checkAccount in Accounts.GetAccounts()) - { - string existingName = checkAccount.GetTag("ChatName"); - - if (existingName != null) - { - existingName = existingName.Trim(); - - if (Insensitive.Equals(existingName, chatName)) - { - from.SendMessage("Nickname already in use."); - SendCommandTo(from, ChatCommand.AskNewNickname); - return; - } - } - } - - accountChatName = chatName; - - acct?.AddTag("ChatName", chatName); - } - else - { - from.SendLocalizedMessage(501173); // That name is disallowed. - SendCommandTo(from, ChatCommand.AskNewNickname); - return; - } - } - - SendCommandTo(from, ChatCommand.OpenChatWindow, accountChatName); - ChatUser.AddChatUser(from); - } - - public static ChatUser SearchForUser(ChatUser from, string name) - { - ChatUser user = ChatUser.GetChatUser(name); - - if (user == null) - from.SendMessage(32, name); // There is no player named '%1'. - - return user; - } - - public static void ChatAction(NetState state, PacketReader pvSrc) - { - if (!Enabled) - return; - - try - { - Mobile from = state.Mobile; - ChatUser user = ChatUser.GetChatUser(from); - - if (user == null) - return; - - string lang = pvSrc.ReadStringSafe(4); - int actionID = pvSrc.ReadInt16(); - string param = pvSrc.ReadUnicodeString(); - - ChatActionHandler handler = ChatActionHandlers.GetHandler(actionID); - - if (handler != null) - { - Channel channel = user.CurrentChannel; - - if (handler.RequireConference && channel == null) - /* You must be in a conference to do this. - * To join a conference, select one from the Conference menu. - */ - user.SendMessage(31); - else if (handler.RequireModerator && !user.IsModerator) - user.SendMessage(29); // You must have operator status to do this. - else - handler.Callback(user, channel, param); - } - else - { - Console.WriteLine("Client: {0}: Unknown chat action 0x{1:X}: {2}", state, actionID, param); - } - } - catch (Exception e) - { - Console.WriteLine(e); - } - } - } -} +using System; +using System.IO; +using Server.Accounting; +using Server.Misc; +using Server.Network; + +namespace Server.Engines.Chat +{ + public class ChatSystem + { + public static bool Enabled { get; set; } = true; + + public static void Initialize() + { + PacketHandlers.Register(0xB5, 0x40, true, OpenChatWindowRequest); + PacketHandlers.Register(0xB3, 0, true, ChatAction); + } + + public static void SendCommandTo(Mobile to, ChatCommand type, string param1 = null, string param2 = null) + { + to?.Send(new ChatMessagePacket(null, (int)type + 20, param1, param2)); + } + + public static void OpenChatWindowRequest(NetState state, PacketReader pvSrc) + { + var from = state.Mobile; + + if (!Enabled) + { + from.SendMessage("The chat system has been disabled."); + return; + } + + pvSrc.Seek(2, SeekOrigin.Begin); + var chatName = pvSrc.ReadUnicodeStringSafe((0x40 - 2) >> 1).Trim(); + + var acct = state.Account as Account; + + string accountChatName = null; + + if (acct != null) + accountChatName = acct.GetTag("ChatName"); + + accountChatName = accountChatName?.Trim(); + + if (!string.IsNullOrEmpty(accountChatName)) + { + if (chatName.Length > 0 && chatName != accountChatName) + from.SendMessage("You cannot change chat nickname once it has been set."); + } + else + { + if (chatName.Length == 0) + { + SendCommandTo(from, ChatCommand.AskNewNickname); + return; + } + + if (NameVerification.Validate(chatName, 2, 31, true, true, true, 0, NameVerification.SpaceDashPeriodQuote) && + chatName.ToLower().IndexOf("system") == -1) + { + // TODO: Optimize this search + + foreach (Account checkAccount in Accounts.GetAccounts()) + { + var existingName = checkAccount.GetTag("ChatName"); + + if (existingName != null) + { + existingName = existingName.Trim(); + + if (Insensitive.Equals(existingName, chatName)) + { + from.SendMessage("Nickname already in use."); + SendCommandTo(from, ChatCommand.AskNewNickname); + return; + } + } + } + + accountChatName = chatName; + + acct?.AddTag("ChatName", chatName); + } + else + { + from.SendLocalizedMessage(501173); // That name is disallowed. + SendCommandTo(from, ChatCommand.AskNewNickname); + return; + } + } + + SendCommandTo(from, ChatCommand.OpenChatWindow, accountChatName); + ChatUser.AddChatUser(from); + } + + public static ChatUser SearchForUser(ChatUser from, string name) + { + var user = ChatUser.GetChatUser(name); + + if (user == null) + from.SendMessage(32, name); // There is no player named '%1'. + + return user; + } + + public static void ChatAction(NetState state, PacketReader pvSrc) + { + if (!Enabled) + return; + + try + { + var from = state.Mobile; + var user = ChatUser.GetChatUser(from); + + if (user == null) + return; + + var lang = pvSrc.ReadStringSafe(4); + int actionID = pvSrc.ReadInt16(); + var param = pvSrc.ReadUnicodeString(); + + var handler = ChatActionHandlers.GetHandler(actionID); + + if (handler != null) + { + var channel = user.CurrentChannel; + + if (handler.RequireConference && channel == null) + /* You must be in a conference to do this. + * To join a conference, select one from the Conference menu. + */ + user.SendMessage(31); + else if (handler.RequireModerator && !user.IsModerator) + user.SendMessage(29); // You must have operator status to do this. + else + handler.Callback(user, channel, param); + } + else + { + Console.WriteLine("Client: {0}: Unknown chat action 0x{1:X}: {2}", state, actionID, param); + } + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + } +} diff --git a/Projects/UOContent/Engines/Chat/ChatActionHandler.cs b/Projects/UOContent/Engines/Chat/ChatActionHandler.cs index 9f11a6af2..897fbaae6 100644 --- a/Projects/UOContent/Engines/Chat/ChatActionHandler.cs +++ b/Projects/UOContent/Engines/Chat/ChatActionHandler.cs @@ -1,20 +1,20 @@ -namespace Server.Engines.Chat -{ - public delegate void OnChatAction(ChatUser from, Channel channel, string param); - - public class ChatActionHandler - { - public ChatActionHandler(bool requireModerator, bool requireConference, OnChatAction callback) - { - RequireModerator = requireModerator; - RequireConference = requireConference; - Callback = callback; - } - - public bool RequireModerator { get; } - - public bool RequireConference { get; } - - public OnChatAction Callback { get; } - } -} \ No newline at end of file +namespace Server.Engines.Chat +{ + public delegate void OnChatAction(ChatUser from, Channel channel, string param); + + public class ChatActionHandler + { + public ChatActionHandler(bool requireModerator, bool requireConference, OnChatAction callback) + { + RequireModerator = requireModerator; + RequireConference = requireConference; + Callback = callback; + } + + public bool RequireModerator { get; } + + public bool RequireConference { get; } + + public OnChatAction Callback { get; } + } +} diff --git a/Projects/UOContent/Engines/Chat/ChatActionHandlers.cs b/Projects/UOContent/Engines/Chat/ChatActionHandlers.cs index 802281dba..4470f2e7d 100644 --- a/Projects/UOContent/Engines/Chat/ChatActionHandlers.cs +++ b/Projects/UOContent/Engines/Chat/ChatActionHandlers.cs @@ -1,353 +1,357 @@ -namespace Server.Engines.Chat -{ - public class ChatActionHandlers - { - private static readonly ChatActionHandler[] m_Handlers; - - static ChatActionHandlers() - { - m_Handlers = new ChatActionHandler[0x100]; - - Register(0x41, true, true, ChangeChannelPassword); - - Register(0x58, false, false, LeaveChat); - - Register(0x61, false, true, ChannelMessage); - Register(0x62, false, false, JoinChannel); - Register(0x63, false, false, JoinNewChannel); - Register(0x64, true, true, RenameChannel); - Register(0x65, false, false, PrivateMessage); - Register(0x66, false, false, AddIgnore); - Register(0x67, false, false, RemoveIgnore); - Register(0x68, false, false, ToggleIgnore); - Register(0x69, true, true, AddVoice); - Register(0x6A, true, true, RemoveVoice); - Register(0x6B, true, true, ToggleVoice); - Register(0x6C, true, true, AddModerator); - Register(0x6D, true, true, RemoveModerator); - Register(0x6E, true, true, ToggleModerator); - Register(0x6F, false, false, AllowPrivateMessages); - Register(0x70, false, false, DisallowPrivateMessages); - Register(0x71, false, false, TogglePrivateMessages); - Register(0x72, false, false, ShowCharacterName); - Register(0x73, false, false, HideCharacterName); - Register(0x74, false, false, ToggleCharacterName); - Register(0x75, false, false, QueryWhoIs); - Register(0x76, true, true, Kick); - Register(0x77, true, true, EnableDefaultVoice); - Register(0x78, true, true, DisableDefaultVoice); - Register(0x79, true, true, ToggleDefaultVoice); - Register(0x7A, false, true, EmoteMessage); - } - - public static void Register(int actionID, bool requireModerator, bool requireConference, OnChatAction callback) - { - if (actionID >= 0 && actionID < m_Handlers.Length) - m_Handlers[actionID] = new ChatActionHandler(requireModerator, requireConference, callback); - } - - public static ChatActionHandler GetHandler(int actionID) - { - if (actionID >= 0 && actionID < m_Handlers.Length) - return m_Handlers[actionID]; - - return null; - } - - public static void ChannelMessage(ChatUser from, Channel channel, string param) - { - if (channel.CanTalk(from)) - channel.SendIgnorableMessage(57, from, from.GetColorCharacter() + from.Username, param); // %1: %2 - else - from.SendMessage(36); // The moderator of this conference has not given you speaking privileges. - } - - public static void EmoteMessage(ChatUser from, Channel channel, string param) - { - if (channel.CanTalk(from)) - channel.SendIgnorableMessage(58, from, from.GetColorCharacter() + from.Username, param); // %1 %2 - else - from.SendMessage(36); // The moderator of this conference has not given you speaking privileges. - } - - public static void PrivateMessage(ChatUser from, Channel channel, string param) - { - int indexOf = param.IndexOf(' '); - - string name = param.Substring(0, indexOf); - string text = param.Substring(indexOf + 1); - - ChatUser target = ChatSystem.SearchForUser(from, name); - - if (target == null) - return; - - if (target.IsIgnored(from)) - from.SendMessage(35, - target.Username); // %1 has chosen to ignore you. None of your messages to them will get through. - else if (target.IgnorePrivateMessage) - from.SendMessage(42, target.Username); // %1 has chosen to not receive private messages at the moment. - else - target.SendMessage(59, from.Mobile, from.GetColorCharacter() + from.Username, text); // [%1]: %2 - } - - public static void LeaveChat(ChatUser from, Channel channel, string param) - { - ChatUser.RemoveChatUser(from); - } - - public static void ChangeChannelPassword(ChatUser from, Channel channel, string param) - { - channel.Password = param; - from.SendMessage(60); // The password to the conference has been changed. - } - - public static void AllowPrivateMessages(ChatUser from, Channel channel, string param) - { - from.IgnorePrivateMessage = false; - from.SendMessage(37); // You can now receive private messages. - } - - public static void DisallowPrivateMessages(ChatUser from, Channel channel, string param) - { - from.IgnorePrivateMessage = true; - /* You will no longer receive private messages. - * Those who send you a message will be notified that you are blocking incoming messages. - */ - from.SendMessage(38); - } - - public static void TogglePrivateMessages(ChatUser from, Channel channel, string param) - { - from.IgnorePrivateMessage = !from.IgnorePrivateMessage; - from.SendMessage(from.IgnorePrivateMessage ? 38 : 37); // See above for messages - } - - public static void ShowCharacterName(ChatUser from, Channel channel, string param) - { - from.Anonymous = false; - from.SendMessage( - 39); // You are now showing your character name to any players who inquire with the whois command. - } - - public static void HideCharacterName(ChatUser from, Channel channel, string param) - { - from.Anonymous = true; - from.SendMessage( - 40); // You are no longer showing your character name to any players who inquire with the whois command. - } - - public static void ToggleCharacterName(ChatUser from, Channel channel, string param) - { - from.Anonymous = !from.Anonymous; - from.SendMessage(from.Anonymous ? 40 : 39); // See above for messages - } - - public static void JoinChannel(ChatUser from, Channel channel, string param) - { - string name; - string password = null; - - int start = param.IndexOf('\"'); - - if (start >= 0) - { - int end = param.IndexOf('\"', ++start); - - if (end >= 0) - { - name = param.Substring(start, end - start); - password = param.Substring(++end); - } - else - { - name = param.Substring(start); - } - } - else - { - int indexOf = param.IndexOf(' '); - - if (indexOf >= 0) - { - name = param.Substring(0, indexOf++); - password = param.Substring(indexOf); - } - else - { - name = param; - } - } - - password = password?.Trim().IsNullOrDefault(null); - - Channel joined = Channel.FindChannelByName(name); - - if (joined == null) - from.SendMessage(33, name); // There is no conference named '%1'. - else - joined.AddUser(from, password); - } - - public static void JoinNewChannel(ChatUser from, Channel channel, string param) - { - if ((param = param.Trim()).Length == 0) - return; - - string name; - string password = null; - - int start = param.IndexOf('{'); - - if (start >= 0) - { - name = param.Substring(0, start++); - - int end = param.IndexOf('}', start); - - if (end >= start) - password = param.Substring(start, end - start); - } - else - { - name = param; - } - - password = password?.Trim().IsNullOrDefault(null); - - Channel.AddChannel(name, password).AddUser(from, password); - } - - public static void AddIgnore(ChatUser from, Channel channel, string param) - { - ChatUser target = ChatSystem.SearchForUser(from, param); - - if (target == null) - return; - - from.AddIgnored(target); - } - - public static void RemoveIgnore(ChatUser from, Channel channel, string param) - { - ChatUser target = ChatSystem.SearchForUser(from, param); - - if (target == null) - return; - - from.RemoveIgnored(target); - } - - public static void ToggleIgnore(ChatUser from, Channel channel, string param) - { - ChatUser target = ChatSystem.SearchForUser(from, param); - - if (target == null) - return; - - if (from.IsIgnored(target)) - from.RemoveIgnored(target); - else - from.AddIgnored(target); - } - - public static void AddVoice(ChatUser from, Channel channel, string param) - { - ChatUser target = ChatSystem.SearchForUser(from, param); - - if (target != null) - channel.AddVoiced(target, from); - } - - public static void RemoveVoice(ChatUser from, Channel channel, string param) - { - ChatUser target = ChatSystem.SearchForUser(from, param); - - if (target != null) - channel.RemoveVoiced(target, from); - } - - public static void ToggleVoice(ChatUser from, Channel channel, string param) - { - ChatUser target = ChatSystem.SearchForUser(from, param); - - if (target == null) - return; - - if (channel.IsVoiced(target)) - channel.RemoveVoiced(target, from); - else - channel.AddVoiced(target, from); - } - - public static void AddModerator(ChatUser from, Channel channel, string param) - { - ChatUser target = ChatSystem.SearchForUser(from, param); - - if (target != null) - channel.AddModerator(target, from); - } - - public static void RemoveModerator(ChatUser from, Channel channel, string param) - { - ChatUser target = ChatSystem.SearchForUser(from, param); - - if (target != null) - channel.RemoveModerator(target, from); - } - - public static void ToggleModerator(ChatUser from, Channel channel, string param) - { - ChatUser target = ChatSystem.SearchForUser(from, param); - - if (target == null) - return; - - if (channel.IsModerator(target)) - channel.RemoveModerator(target, from); - else - channel.AddModerator(target, from); - } - - public static void RenameChannel(ChatUser from, Channel channel, string param) - { - channel.Name = param; - } - - public static void QueryWhoIs(ChatUser from, Channel channel, string param) - { - ChatUser target = ChatSystem.SearchForUser(from, param); - - if (target == null) - return; - - if (target.Anonymous) - from.SendMessage(41, target.Username); // %1 is remaining anonymous. - else - from.SendMessage(43, target.Username, target.Mobile.Name); // %2 is known in the lands of Britannia as %2. - } - - public static void Kick(ChatUser from, Channel channel, string param) - { - ChatUser target = ChatSystem.SearchForUser(from, param); - - if (target != null) - channel.Kick(target, from); - } - - public static void EnableDefaultVoice(ChatUser from, Channel channel, string param) - { - channel.VoiceRestricted = false; - } - - public static void DisableDefaultVoice(ChatUser from, Channel channel, string param) - { - channel.VoiceRestricted = true; - } - - public static void ToggleDefaultVoice(ChatUser from, Channel channel, string param) - { - channel.VoiceRestricted = !channel.VoiceRestricted; - } - } -} +namespace Server.Engines.Chat +{ + public class ChatActionHandlers + { + private static readonly ChatActionHandler[] m_Handlers; + + static ChatActionHandlers() + { + m_Handlers = new ChatActionHandler[0x100]; + + Register(0x41, true, true, ChangeChannelPassword); + + Register(0x58, false, false, LeaveChat); + + Register(0x61, false, true, ChannelMessage); + Register(0x62, false, false, JoinChannel); + Register(0x63, false, false, JoinNewChannel); + Register(0x64, true, true, RenameChannel); + Register(0x65, false, false, PrivateMessage); + Register(0x66, false, false, AddIgnore); + Register(0x67, false, false, RemoveIgnore); + Register(0x68, false, false, ToggleIgnore); + Register(0x69, true, true, AddVoice); + Register(0x6A, true, true, RemoveVoice); + Register(0x6B, true, true, ToggleVoice); + Register(0x6C, true, true, AddModerator); + Register(0x6D, true, true, RemoveModerator); + Register(0x6E, true, true, ToggleModerator); + Register(0x6F, false, false, AllowPrivateMessages); + Register(0x70, false, false, DisallowPrivateMessages); + Register(0x71, false, false, TogglePrivateMessages); + Register(0x72, false, false, ShowCharacterName); + Register(0x73, false, false, HideCharacterName); + Register(0x74, false, false, ToggleCharacterName); + Register(0x75, false, false, QueryWhoIs); + Register(0x76, true, true, Kick); + Register(0x77, true, true, EnableDefaultVoice); + Register(0x78, true, true, DisableDefaultVoice); + Register(0x79, true, true, ToggleDefaultVoice); + Register(0x7A, false, true, EmoteMessage); + } + + public static void Register(int actionID, bool requireModerator, bool requireConference, OnChatAction callback) + { + if (actionID >= 0 && actionID < m_Handlers.Length) + m_Handlers[actionID] = new ChatActionHandler(requireModerator, requireConference, callback); + } + + public static ChatActionHandler GetHandler(int actionID) + { + if (actionID >= 0 && actionID < m_Handlers.Length) + return m_Handlers[actionID]; + + return null; + } + + public static void ChannelMessage(ChatUser from, Channel channel, string param) + { + if (channel.CanTalk(from)) + channel.SendIgnorableMessage(57, from, from.GetColorCharacter() + from.Username, param); // %1: %2 + else + from.SendMessage(36); // The moderator of this conference has not given you speaking privileges. + } + + public static void EmoteMessage(ChatUser from, Channel channel, string param) + { + if (channel.CanTalk(from)) + channel.SendIgnorableMessage(58, from, from.GetColorCharacter() + from.Username, param); // %1 %2 + else + from.SendMessage(36); // The moderator of this conference has not given you speaking privileges. + } + + public static void PrivateMessage(ChatUser from, Channel channel, string param) + { + var indexOf = param.IndexOf(' '); + + var name = param.Substring(0, indexOf); + var text = param.Substring(indexOf + 1); + + var target = ChatSystem.SearchForUser(from, name); + + if (target == null) + return; + + if (target.IsIgnored(from)) + from.SendMessage( + 35, + target.Username + ); // %1 has chosen to ignore you. None of your messages to them will get through. + else if (target.IgnorePrivateMessage) + from.SendMessage(42, target.Username); // %1 has chosen to not receive private messages at the moment. + else + target.SendMessage(59, from.Mobile, from.GetColorCharacter() + from.Username, text); // [%1]: %2 + } + + public static void LeaveChat(ChatUser from, Channel channel, string param) + { + ChatUser.RemoveChatUser(from); + } + + public static void ChangeChannelPassword(ChatUser from, Channel channel, string param) + { + channel.Password = param; + from.SendMessage(60); // The password to the conference has been changed. + } + + public static void AllowPrivateMessages(ChatUser from, Channel channel, string param) + { + from.IgnorePrivateMessage = false; + from.SendMessage(37); // You can now receive private messages. + } + + public static void DisallowPrivateMessages(ChatUser from, Channel channel, string param) + { + from.IgnorePrivateMessage = true; + /* You will no longer receive private messages. + * Those who send you a message will be notified that you are blocking incoming messages. + */ + from.SendMessage(38); + } + + public static void TogglePrivateMessages(ChatUser from, Channel channel, string param) + { + from.IgnorePrivateMessage = !from.IgnorePrivateMessage; + from.SendMessage(from.IgnorePrivateMessage ? 38 : 37); // See above for messages + } + + public static void ShowCharacterName(ChatUser from, Channel channel, string param) + { + from.Anonymous = false; + from.SendMessage( + 39 + ); // You are now showing your character name to any players who inquire with the whois command. + } + + public static void HideCharacterName(ChatUser from, Channel channel, string param) + { + from.Anonymous = true; + from.SendMessage( + 40 + ); // You are no longer showing your character name to any players who inquire with the whois command. + } + + public static void ToggleCharacterName(ChatUser from, Channel channel, string param) + { + from.Anonymous = !from.Anonymous; + from.SendMessage(from.Anonymous ? 40 : 39); // See above for messages + } + + public static void JoinChannel(ChatUser from, Channel channel, string param) + { + string name; + string password = null; + + var start = param.IndexOf('\"'); + + if (start >= 0) + { + var end = param.IndexOf('\"', ++start); + + if (end >= 0) + { + name = param.Substring(start, end - start); + password = param.Substring(++end); + } + else + { + name = param.Substring(start); + } + } + else + { + var indexOf = param.IndexOf(' '); + + if (indexOf >= 0) + { + name = param.Substring(0, indexOf++); + password = param.Substring(indexOf); + } + else + { + name = param; + } + } + + password = password?.Trim().IsNullOrDefault(null); + + var joined = Channel.FindChannelByName(name); + + if (joined == null) + from.SendMessage(33, name); // There is no conference named '%1'. + else + joined.AddUser(from, password); + } + + public static void JoinNewChannel(ChatUser from, Channel channel, string param) + { + if ((param = param.Trim()).Length == 0) + return; + + string name; + string password = null; + + var start = param.IndexOf('{'); + + if (start >= 0) + { + name = param.Substring(0, start++); + + var end = param.IndexOf('}', start); + + if (end >= start) + password = param.Substring(start, end - start); + } + else + { + name = param; + } + + password = password?.Trim().IsNullOrDefault(null); + + Channel.AddChannel(name, password).AddUser(from, password); + } + + public static void AddIgnore(ChatUser from, Channel channel, string param) + { + var target = ChatSystem.SearchForUser(from, param); + + if (target == null) + return; + + from.AddIgnored(target); + } + + public static void RemoveIgnore(ChatUser from, Channel channel, string param) + { + var target = ChatSystem.SearchForUser(from, param); + + if (target == null) + return; + + from.RemoveIgnored(target); + } + + public static void ToggleIgnore(ChatUser from, Channel channel, string param) + { + var target = ChatSystem.SearchForUser(from, param); + + if (target == null) + return; + + if (from.IsIgnored(target)) + from.RemoveIgnored(target); + else + from.AddIgnored(target); + } + + public static void AddVoice(ChatUser from, Channel channel, string param) + { + var target = ChatSystem.SearchForUser(from, param); + + if (target != null) + channel.AddVoiced(target, from); + } + + public static void RemoveVoice(ChatUser from, Channel channel, string param) + { + var target = ChatSystem.SearchForUser(from, param); + + if (target != null) + channel.RemoveVoiced(target, from); + } + + public static void ToggleVoice(ChatUser from, Channel channel, string param) + { + var target = ChatSystem.SearchForUser(from, param); + + if (target == null) + return; + + if (channel.IsVoiced(target)) + channel.RemoveVoiced(target, from); + else + channel.AddVoiced(target, from); + } + + public static void AddModerator(ChatUser from, Channel channel, string param) + { + var target = ChatSystem.SearchForUser(from, param); + + if (target != null) + channel.AddModerator(target, from); + } + + public static void RemoveModerator(ChatUser from, Channel channel, string param) + { + var target = ChatSystem.SearchForUser(from, param); + + if (target != null) + channel.RemoveModerator(target, from); + } + + public static void ToggleModerator(ChatUser from, Channel channel, string param) + { + var target = ChatSystem.SearchForUser(from, param); + + if (target == null) + return; + + if (channel.IsModerator(target)) + channel.RemoveModerator(target, from); + else + channel.AddModerator(target, from); + } + + public static void RenameChannel(ChatUser from, Channel channel, string param) + { + channel.Name = param; + } + + public static void QueryWhoIs(ChatUser from, Channel channel, string param) + { + var target = ChatSystem.SearchForUser(from, param); + + if (target == null) + return; + + if (target.Anonymous) + from.SendMessage(41, target.Username); // %1 is remaining anonymous. + else + from.SendMessage(43, target.Username, target.Mobile.Name); // %2 is known in the lands of Britannia as %2. + } + + public static void Kick(ChatUser from, Channel channel, string param) + { + var target = ChatSystem.SearchForUser(from, param); + + if (target != null) + channel.Kick(target, from); + } + + public static void EnableDefaultVoice(ChatUser from, Channel channel, string param) + { + channel.VoiceRestricted = false; + } + + public static void DisableDefaultVoice(ChatUser from, Channel channel, string param) + { + channel.VoiceRestricted = true; + } + + public static void ToggleDefaultVoice(ChatUser from, Channel channel, string param) + { + channel.VoiceRestricted = !channel.VoiceRestricted; + } + } +} diff --git a/Projects/UOContent/Engines/Chat/ChatCommand.cs b/Projects/UOContent/Engines/Chat/ChatCommand.cs index bd7b81e4e..6aea6349b 100644 --- a/Projects/UOContent/Engines/Chat/ChatCommand.cs +++ b/Projects/UOContent/Engines/Chat/ChatCommand.cs @@ -1,50 +1,50 @@ -namespace Server.Engines.Chat -{ - public enum ChatCommand - { - /// - /// Add a channel to top list. - /// - AddChannel = 0x3E8, - - /// - /// Remove channel from top list. - /// - RemoveChannel = 0x3E9, - - /// - /// Queries for a new chat nickname. - /// - AskNewNickname = 0x3EB, - - /// - /// Closes the chat window. - /// - CloseChatWindow = 0x3EC, - - /// - /// Opens the chat window. - /// - OpenChatWindow = 0x3ED, - - /// - /// Add a user to current channel. - /// - AddUserToChannel = 0x3EE, - - /// - /// Remove a user from current channel. - /// - RemoveUserFromChannel = 0x3EF, - - /// - /// Send a message putting generic conference name at top when player leaves a channel. - /// - LeaveChannel = 0x3F0, - - /// - /// Send a message putting Channel name at top and telling player he joined the channel. - /// - JoinedChannel = 0x3F1 - } -} \ No newline at end of file +namespace Server.Engines.Chat +{ + public enum ChatCommand + { + /// + /// Add a channel to top list. + /// + AddChannel = 0x3E8, + + /// + /// Remove channel from top list. + /// + RemoveChannel = 0x3E9, + + /// + /// Queries for a new chat nickname. + /// + AskNewNickname = 0x3EB, + + /// + /// Closes the chat window. + /// + CloseChatWindow = 0x3EC, + + /// + /// Opens the chat window. + /// + OpenChatWindow = 0x3ED, + + /// + /// Add a user to current channel. + /// + AddUserToChannel = 0x3EE, + + /// + /// Remove a user from current channel. + /// + RemoveUserFromChannel = 0x3EF, + + /// + /// Send a message putting generic conference name at top when player leaves a channel. + /// + LeaveChannel = 0x3F0, + + /// + /// Send a message putting Channel name at top and telling player he joined the channel. + /// + JoinedChannel = 0x3F1 + } +} diff --git a/Projects/UOContent/Engines/Chat/ChatUser.cs b/Projects/UOContent/Engines/Chat/ChatUser.cs index 1a02c2924..7735b18c0 100644 --- a/Projects/UOContent/Engines/Chat/ChatUser.cs +++ b/Projects/UOContent/Engines/Chat/ChatUser.cs @@ -1,207 +1,209 @@ -using System.Collections.Generic; -using Server.Accounting; - -namespace Server.Engines.Chat -{ - public class ChatUser - { - public const char NormalColorCharacter = '0'; - public const char ModeratorColorCharacter = '1'; - public const char VoicedColorCharacter = '2'; - - private static readonly List m_Users = new List(); - private static readonly Dictionary m_Table = new Dictionary(); - - public ChatUser(Mobile m) - { - Mobile = m; - Ignored = new List(); - Ignoring = new List(); - } - - public Mobile Mobile { get; } - - public List Ignored { get; } - - public List Ignoring { get; } - - public string Username - { - get - { - if (Mobile.Account is Account acct) - return acct.GetTag("ChatName"); - - return null; - } - set - { - if (Mobile.Account is Account acct) - acct.SetTag("ChatName", value); - } - } - - public Channel CurrentChannel { get; set; } - - public bool IsOnline => Mobile.NetState != null; - - public bool Anonymous { get; set; } - - public bool IgnorePrivateMessage { get; set; } - - public bool IsModerator => CurrentChannel?.IsModerator(this) == true; - - public char GetColorCharacter() => - IsModerator ? ModeratorColorCharacter : - CurrentChannel?.IsVoiced(this) == true ? VoicedColorCharacter : NormalColorCharacter; - - public bool CheckOnline() - { - if (IsOnline) - return true; - - RemoveChatUser(this); - return false; - } - - public void SendMessage(int number, string param1 = null, string param2 = null) - { - if (Mobile.NetState != null) - Mobile.Send(new ChatMessagePacket(Mobile, number, param1, param2)); - } - - public void SendMessage(int number, Mobile from, string param1, string param2) - { - if (Mobile.NetState != null) - Mobile.Send(new ChatMessagePacket(from, number, param1, param2)); - } - - public bool IsIgnored(ChatUser check) => Ignored.Contains(check); - - public void AddIgnored(ChatUser user) - { - if (IsIgnored(user)) - { - SendMessage(22, user.Username); // You are already ignoring %1. - } - else - { - Ignored.Add(user); - user.Ignoring.Add(this); - - SendMessage(23, user.Username); // You are now ignoring %1. - } - } - - public void RemoveIgnored(ChatUser user) - { - if (IsIgnored(user)) - { - Ignored.Remove(user); - user.Ignoring.Remove(this); - - SendMessage(24, user.Username); // You are no longer ignoring %1. - - if (Ignored.Count == 0) - SendMessage(26); // You are no longer ignoring anyone. - } - else - { - SendMessage(25, user.Username); // You are not ignoring %1. - } - } - - public static ChatUser AddChatUser(Mobile from) - { - ChatUser user = GetChatUser(from); - - if (user != null) - return user; - - user = new ChatUser(from); - - m_Users.Add(user); - m_Table[from] = user; - - Channel.SendChannelsTo(user); - - List list = Channel.Channels; - - for (int i = 0; i < list.Count; ++i) - { - Channel c = list[i]; - - if (c.AddUser(user)) - break; - } - - // ChatSystem.SendCommandTo( user.m_Mobile, ChatCommand.AddUserToChannel, user.GetColorCharacter() + user.Username ); - - return user; - } - - public static void RemoveChatUser(ChatUser user) - { - if (user == null) - return; - - for (int i = 0; i < user.Ignoring.Count; ++i) - user.Ignoring[i].RemoveIgnored(user); - - if (m_Users.Contains(user)) - { - ChatSystem.SendCommandTo(user.Mobile, ChatCommand.CloseChatWindow); - - user.CurrentChannel?.RemoveUser(user); - - m_Users.Remove(user); - m_Table.Remove(user.Mobile); - } - } - - public static void RemoveChatUser(Mobile from) - { - ChatUser user = GetChatUser(from); - - RemoveChatUser(user); - } - - public static ChatUser GetChatUser(Mobile from) - { - m_Table.TryGetValue(from, out ChatUser c); - return c; - } - - public static ChatUser GetChatUser(string username) - { - for (int i = 0; i < m_Users.Count; ++i) - { - ChatUser user = m_Users[i]; - - if (user.Username == username) - return user; - } - - return null; - } - - public static void GlobalSendCommand(ChatCommand command, string param1, string param2 = null) - { - GlobalSendCommand(command, null, param1, param2); - } - - public static void GlobalSendCommand(ChatCommand command, ChatUser initiator = null, string param1 = null, string param2 = null) - { - for (int i = 0; i < m_Users.Count; ++i) - { - ChatUser user = m_Users[i]; - - if (user == initiator) - continue; - - if (user.CheckOnline()) - ChatSystem.SendCommandTo(user.Mobile, command, param1, param2); - } - } - } -} +using System.Collections.Generic; +using Server.Accounting; + +namespace Server.Engines.Chat +{ + public class ChatUser + { + public const char NormalColorCharacter = '0'; + public const char ModeratorColorCharacter = '1'; + public const char VoicedColorCharacter = '2'; + + private static readonly List m_Users = new List(); + private static readonly Dictionary m_Table = new Dictionary(); + + public ChatUser(Mobile m) + { + Mobile = m; + Ignored = new List(); + Ignoring = new List(); + } + + public Mobile Mobile { get; } + + public List Ignored { get; } + + public List Ignoring { get; } + + public string Username + { + get + { + if (Mobile.Account is Account acct) + return acct.GetTag("ChatName"); + + return null; + } + set + { + if (Mobile.Account is Account acct) + acct.SetTag("ChatName", value); + } + } + + public Channel CurrentChannel { get; set; } + + public bool IsOnline => Mobile.NetState != null; + + public bool Anonymous { get; set; } + + public bool IgnorePrivateMessage { get; set; } + + public bool IsModerator => CurrentChannel?.IsModerator(this) == true; + + public char GetColorCharacter() => + IsModerator ? ModeratorColorCharacter : + CurrentChannel?.IsVoiced(this) == true ? VoicedColorCharacter : NormalColorCharacter; + + public bool CheckOnline() + { + if (IsOnline) + return true; + + RemoveChatUser(this); + return false; + } + + public void SendMessage(int number, string param1 = null, string param2 = null) + { + if (Mobile.NetState != null) + Mobile.Send(new ChatMessagePacket(Mobile, number, param1, param2)); + } + + public void SendMessage(int number, Mobile from, string param1, string param2) + { + if (Mobile.NetState != null) + Mobile.Send(new ChatMessagePacket(from, number, param1, param2)); + } + + public bool IsIgnored(ChatUser check) => Ignored.Contains(check); + + public void AddIgnored(ChatUser user) + { + if (IsIgnored(user)) + { + SendMessage(22, user.Username); // You are already ignoring %1. + } + else + { + Ignored.Add(user); + user.Ignoring.Add(this); + + SendMessage(23, user.Username); // You are now ignoring %1. + } + } + + public void RemoveIgnored(ChatUser user) + { + if (IsIgnored(user)) + { + Ignored.Remove(user); + user.Ignoring.Remove(this); + + SendMessage(24, user.Username); // You are no longer ignoring %1. + + if (Ignored.Count == 0) + SendMessage(26); // You are no longer ignoring anyone. + } + else + { + SendMessage(25, user.Username); // You are not ignoring %1. + } + } + + public static ChatUser AddChatUser(Mobile from) + { + var user = GetChatUser(from); + + if (user != null) + return user; + + user = new ChatUser(from); + + m_Users.Add(user); + m_Table[from] = user; + + Channel.SendChannelsTo(user); + + var list = Channel.Channels; + + for (var i = 0; i < list.Count; ++i) + { + var c = list[i]; + + if (c.AddUser(user)) + break; + } + + // ChatSystem.SendCommandTo( user.m_Mobile, ChatCommand.AddUserToChannel, user.GetColorCharacter() + user.Username ); + + return user; + } + + public static void RemoveChatUser(ChatUser user) + { + if (user == null) + return; + + for (var i = 0; i < user.Ignoring.Count; ++i) + user.Ignoring[i].RemoveIgnored(user); + + if (m_Users.Contains(user)) + { + ChatSystem.SendCommandTo(user.Mobile, ChatCommand.CloseChatWindow); + + user.CurrentChannel?.RemoveUser(user); + + m_Users.Remove(user); + m_Table.Remove(user.Mobile); + } + } + + public static void RemoveChatUser(Mobile from) + { + var user = GetChatUser(from); + + RemoveChatUser(user); + } + + public static ChatUser GetChatUser(Mobile from) + { + m_Table.TryGetValue(from, out var c); + return c; + } + + public static ChatUser GetChatUser(string username) + { + for (var i = 0; i < m_Users.Count; ++i) + { + var user = m_Users[i]; + + if (user.Username == username) + return user; + } + + return null; + } + + public static void GlobalSendCommand(ChatCommand command, string param1, string param2 = null) + { + GlobalSendCommand(command, null, param1, param2); + } + + public static void GlobalSendCommand( + ChatCommand command, ChatUser initiator = null, string param1 = null, string param2 = null + ) + { + for (var i = 0; i < m_Users.Count; ++i) + { + var user = m_Users[i]; + + if (user == initiator) + continue; + + if (user.CheckOnline()) + ChatSystem.SendCommandTo(user.Mobile, command, param1, param2); + } + } + } +} diff --git a/Projects/UOContent/Engines/Chat/Chatold.cs b/Projects/UOContent/Engines/Chat/Chatold.cs index a0e65be65..3bd8adda7 100644 --- a/Projects/UOContent/Engines/Chat/Chatold.cs +++ b/Projects/UOContent/Engines/Chat/Chatold.cs @@ -1,15 +1,15 @@ -namespace Server.Chat -{ - public static class ChatSystem - { - public static void Initialize() - { - EventSink.ChatRequest += EventSink_ChatRequest; - } - - private static void EventSink_ChatRequest(Mobile m) - { - m.SendMessage("Chat is not currently supported."); - } - } -} +namespace Server.Chat +{ + public static class ChatSystem + { + public static void Initialize() + { + EventSink.ChatRequest += EventSink_ChatRequest; + } + + private static void EventSink_ChatRequest(Mobile m) + { + m.SendMessage("Chat is not currently supported."); + } + } +} diff --git a/Projects/UOContent/Engines/Chat/Packets.cs b/Projects/UOContent/Engines/Chat/Packets.cs index 04bec8725..34d7d0519 100644 --- a/Projects/UOContent/Engines/Chat/Packets.cs +++ b/Projects/UOContent/Engines/Chat/Packets.cs @@ -1,25 +1,25 @@ -using Server.Network; - -namespace Server.Engines.Chat -{ - public sealed class ChatMessagePacket : Packet - { - public ChatMessagePacket(Mobile who, int number, string param1, string param2) : base(0xB2) - { - param1 ??= string.Empty; - param2 ??= string.Empty; - - EnsureCapacity(13 + (param1.Length + param2.Length) * 2); - - Stream.Write((ushort)(number - 20)); - - if (who != null) - Stream.WriteAsciiFixed(who.Language, 4); - else - Stream.Write(0); - - Stream.WriteBigUniNull(param1); - Stream.WriteBigUniNull(param2); - } - } -} +using Server.Network; + +namespace Server.Engines.Chat +{ + public sealed class ChatMessagePacket : Packet + { + public ChatMessagePacket(Mobile who, int number, string param1, string param2) : base(0xB2) + { + param1 ??= string.Empty; + param2 ??= string.Empty; + + EnsureCapacity(13 + (param1.Length + param2.Length) * 2); + + Stream.Write((ushort)(number - 20)); + + if (who != null) + Stream.WriteAsciiFixed(who.Language, 4); + else + Stream.Write(0); + + Stream.WriteBigUniNull(param1); + Stream.WriteBigUniNull(param2); + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/AcceptDuelGump.cs b/Projects/UOContent/Engines/ConPVP/AcceptDuelGump.cs index 7e77d37ba..9994c11fa 100644 --- a/Projects/UOContent/Engines/ConPVP/AcceptDuelGump.cs +++ b/Projects/UOContent/Engines/ConPVP/AcceptDuelGump.cs @@ -1,274 +1,289 @@ -using System; -using System.Collections.Generic; -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.ConPVP -{ - public class AcceptDuelGump : Gump - { - private const int LabelColor32 = 0xFFFFFF; - private const int BlackColor32 = 0x000008; - - private static readonly Dictionary> m_IgnoreLists = new Dictionary>(); - - private bool m_Active = true; - private readonly Mobile m_Challenger; - private readonly Mobile m_Challenged; - private readonly DuelContext m_Context; - private readonly Participant m_Participant; - private readonly int m_Slot; - - public AcceptDuelGump(Mobile challenger, Mobile challenged, DuelContext context, Participant p, int slot) : base(50, - 50) - { - m_Challenger = challenger; - m_Challenged = challenged; - m_Context = context; - m_Participant = p; - m_Slot = slot; - - challenged.CloseGump(); - - Closable = false; - - AddPage(0); - - // AddBackground( 0, 0, 400, 220, 9150 ); - AddBackground(1, 1, 398, 218, 3600); - // AddBackground( 16, 15, 369, 189, 9100 ); - - AddImageTiled(16, 15, 369, 189, 3604); - AddAlphaRegion(16, 15, 369, 189); - - AddImage(215, -43, 0xEE40); - // AddImage( 330, 141, 0x8BA ); - - AddHtml(22 - 1, 22, 294, 20, Color(Center("Duel Challenge"), BlackColor32)); - AddHtml(22 + 1, 22, 294, 20, Color(Center("Duel Challenge"), BlackColor32)); - AddHtml(22, 22 - 1, 294, 20, Color(Center("Duel Challenge"), BlackColor32)); - AddHtml(22, 22 + 1, 294, 20, Color(Center("Duel Challenge"), BlackColor32)); - AddHtml(22, 22, 294, 20, Color(Center("Duel Challenge"), LabelColor32)); - - string fmt; - - if (p.Contains(challenger)) - fmt = "You have been asked to join sides with {0} in a duel. Do you accept?"; - else - fmt = "You have been challenged to a duel from {0}. Do you accept?"; - - AddHtml(22 - 1, 50, 294, 40, Color(string.Format(fmt, challenger.Name), BlackColor32)); - AddHtml(22 + 1, 50, 294, 40, Color(string.Format(fmt, challenger.Name), BlackColor32)); - AddHtml(22, 50 - 1, 294, 40, Color(string.Format(fmt, challenger.Name), BlackColor32)); - AddHtml(22, 50 + 1, 294, 40, Color(string.Format(fmt, challenger.Name), BlackColor32)); - AddHtml(22, 50, 294, 40, Color(string.Format(fmt, challenger.Name), 0xB0C868)); - - AddImageTiled(32, 88, 264, 1, 9107); - AddImageTiled(42, 90, 264, 1, 9157); - - AddRadio(24, 100, 9727, 9730, true, 1); - AddHtml(60 - 1, 105, 250, 20, Color("Yes, I will fight this duel.", BlackColor32)); - AddHtml(60 + 1, 105, 250, 20, Color("Yes, I will fight this duel.", BlackColor32)); - AddHtml(60, 105 - 1, 250, 20, Color("Yes, I will fight this duel.", BlackColor32)); - AddHtml(60, 105 + 1, 250, 20, Color("Yes, I will fight this duel.", BlackColor32)); - AddHtml(60, 105, 250, 20, Color("Yes, I will fight this duel.", LabelColor32)); - - AddRadio(24, 135, 9727, 9730, false, 2); - AddHtml(60 - 1, 140, 250, 20, Color("No, I do not wish to fight.", BlackColor32)); - AddHtml(60 + 1, 140, 250, 20, Color("No, I do not wish to fight.", BlackColor32)); - AddHtml(60, 140 - 1, 250, 20, Color("No, I do not wish to fight.", BlackColor32)); - AddHtml(60, 140 + 1, 250, 20, Color("No, I do not wish to fight.", BlackColor32)); - AddHtml(60, 140, 250, 20, Color("No, I do not wish to fight.", LabelColor32)); - - AddRadio(24, 170, 9727, 9730, false, 3); - AddHtml(60 - 1, 175, 250, 20, Color("No, knave. Do not ask again.", BlackColor32)); - AddHtml(60 + 1, 175, 250, 20, Color("No, knave. Do not ask again.", BlackColor32)); - AddHtml(60, 175 - 1, 250, 20, Color("No, knave. Do not ask again.", BlackColor32)); - AddHtml(60, 175 + 1, 250, 20, Color("No, knave. Do not ask again.", BlackColor32)); - AddHtml(60, 175, 250, 20, Color("No, knave. Do not ask again.", LabelColor32)); - - AddButton(314, 173, 247, 248, 1); - - Timer.DelayCall(TimeSpan.FromSeconds(15.0), AutoReject); - } - - public string Center(string text) => $"
{text}
"; - - public string Color(string text, int color) => $"{text}"; - - public void AutoReject() - { - if (!m_Active) - return; - - m_Active = false; - - m_Challenged.CloseGump(); - - m_Challenger.SendMessage("{0} seems unresponsive.", m_Challenged.Name); - m_Challenged.SendMessage("You decline the challenge."); - } - - public static void BeginIgnore(Mobile source, Mobile toIgnore) - { - if (!m_IgnoreLists.TryGetValue(source, out List list)) - m_IgnoreLists[source] = list = new List(); - - for (int i = 0; i < list.Count; ++i) - { - IgnoreEntry ie = list[i]; - - if (ie.Ignored == toIgnore) - { - ie.Refresh(); - return; - } - - if (ie.Expired) - list.RemoveAt(i--); - } - - list.Add(new IgnoreEntry(toIgnore)); - } - - public static bool IsIgnored(Mobile source, Mobile check) - { - if (!m_IgnoreLists.TryGetValue(source, out List list)) - return false; - - for (int i = 0; i < list.Count; ++i) - { - IgnoreEntry ie = list[i]; - - if (ie.Expired) - list.RemoveAt(i--); - else if (ie.Ignored == check) - return true; - } - - return false; - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID != 1 || !m_Active || !m_Context.Registered) - return; - - m_Active = false; - - if (!m_Context.Participants.Contains(m_Participant)) - return; - - if (info.IsSwitched(1)) - { - if (!(m_Challenged is PlayerMobile pm)) - return; - - if (pm.DuelContext != null) - { - if (pm.DuelContext.Initiator == pm) - pm.SendMessage(0x22, "You have already started a duel."); - else - pm.SendMessage(0x22, "You have already been challenged in a duel."); - - m_Challenger.SendMessage("{0} cannot fight because they are already assigned to another duel.", pm.Name); - } - else if (DuelContext.CheckCombat(pm)) - { - pm.SendMessage(0x22, - "You have recently been in combat with another player and must wait before starting a duel."); - m_Challenger.SendMessage( - "{0} cannot fight because they have recently been in combat with another player.", pm.Name); - } - else if (TournamentController.IsActive) - { - pm.SendMessage(0x22, "A tournament is currently active and you may not duel."); - m_Challenger.SendMessage(0x22, "A tournament is currently active and you may not duel."); - } - else - { - bool added = false; - - if (m_Slot >= 0 && m_Slot < m_Participant.Players.Length && m_Participant.Players[m_Slot] == null) - { - added = true; - m_Participant.Players[m_Slot] = new DuelPlayer(m_Challenged, m_Participant); - } - else - { - for (int i = 0; i < m_Participant.Players.Length; ++i) - if (m_Participant.Players[i] == null) - { - added = true; - m_Participant.Players[i] = new DuelPlayer(m_Challenged, m_Participant); - break; - } - } - - if (added) - { - m_Challenger.SendMessage("{0} has accepted the request.", m_Challenged.Name); - m_Challenged.SendMessage("You have accepted the request from {0}.", m_Challenger.Name); - - NetState ns = m_Challenger.NetState; - - if (ns != null) - foreach (Gump g in ns.Gumps) - { - if (g is ParticipantGump pg && pg.Participant == m_Participant) - { - m_Challenger.SendGump(new ParticipantGump(m_Challenger, m_Context, m_Participant)); - break; - } - - if (g is DuelContextGump dcg && dcg.Context == m_Context) - { - m_Challenger.SendGump(new DuelContextGump(m_Challenger, m_Context)); - break; - } - } - } - else - { - m_Challenger.SendMessage("The participant list was full and so {0} could not join.", - m_Challenged.Name); - m_Challenged.SendMessage( - "The participant list was full and so you could not join the fight {1} {0}.", m_Challenger.Name, - m_Participant.Contains(m_Challenger) ? "with" : "against"); - } - } - } - else - { - if (info.IsSwitched(3)) - BeginIgnore(m_Challenged, m_Challenger); - - m_Challenger.SendMessage("{0} does not wish to fight.", m_Challenged.Name); - m_Challenged.SendMessage("You chose not to fight {1} {0}.", m_Challenger.Name, - m_Participant.Contains(m_Challenger) ? "with" : "against"); - } - } - - private class IgnoreEntry - { - private static readonly TimeSpan ExpireDelay = TimeSpan.FromMinutes(15.0); - public DateTime m_Expire; - public readonly Mobile m_Ignored; - - public IgnoreEntry(Mobile ignored) - { - m_Ignored = ignored; - Refresh(); - } - - public Mobile Ignored => m_Ignored; - public bool Expired => DateTime.UtcNow >= m_Expire; - - public void Refresh() - { - m_Expire = DateTime.UtcNow + ExpireDelay; - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.ConPVP +{ + public class AcceptDuelGump : Gump + { + private const int LabelColor32 = 0xFFFFFF; + private const int BlackColor32 = 0x000008; + + private static readonly Dictionary> m_IgnoreLists = + new Dictionary>(); + + private readonly Mobile m_Challenged; + private readonly Mobile m_Challenger; + private readonly DuelContext m_Context; + private readonly Participant m_Participant; + private readonly int m_Slot; + + private bool m_Active = true; + + public AcceptDuelGump(Mobile challenger, Mobile challenged, DuelContext context, Participant p, int slot) : base( + 50, + 50 + ) + { + m_Challenger = challenger; + m_Challenged = challenged; + m_Context = context; + m_Participant = p; + m_Slot = slot; + + challenged.CloseGump(); + + Closable = false; + + AddPage(0); + + // AddBackground( 0, 0, 400, 220, 9150 ); + AddBackground(1, 1, 398, 218, 3600); + // AddBackground( 16, 15, 369, 189, 9100 ); + + AddImageTiled(16, 15, 369, 189, 3604); + AddAlphaRegion(16, 15, 369, 189); + + AddImage(215, -43, 0xEE40); + // AddImage( 330, 141, 0x8BA ); + + AddHtml(22 - 1, 22, 294, 20, Color(Center("Duel Challenge"), BlackColor32)); + AddHtml(22 + 1, 22, 294, 20, Color(Center("Duel Challenge"), BlackColor32)); + AddHtml(22, 22 - 1, 294, 20, Color(Center("Duel Challenge"), BlackColor32)); + AddHtml(22, 22 + 1, 294, 20, Color(Center("Duel Challenge"), BlackColor32)); + AddHtml(22, 22, 294, 20, Color(Center("Duel Challenge"), LabelColor32)); + + string fmt; + + if (p.Contains(challenger)) + fmt = "You have been asked to join sides with {0} in a duel. Do you accept?"; + else + fmt = "You have been challenged to a duel from {0}. Do you accept?"; + + AddHtml(22 - 1, 50, 294, 40, Color(string.Format(fmt, challenger.Name), BlackColor32)); + AddHtml(22 + 1, 50, 294, 40, Color(string.Format(fmt, challenger.Name), BlackColor32)); + AddHtml(22, 50 - 1, 294, 40, Color(string.Format(fmt, challenger.Name), BlackColor32)); + AddHtml(22, 50 + 1, 294, 40, Color(string.Format(fmt, challenger.Name), BlackColor32)); + AddHtml(22, 50, 294, 40, Color(string.Format(fmt, challenger.Name), 0xB0C868)); + + AddImageTiled(32, 88, 264, 1, 9107); + AddImageTiled(42, 90, 264, 1, 9157); + + AddRadio(24, 100, 9727, 9730, true, 1); + AddHtml(60 - 1, 105, 250, 20, Color("Yes, I will fight this duel.", BlackColor32)); + AddHtml(60 + 1, 105, 250, 20, Color("Yes, I will fight this duel.", BlackColor32)); + AddHtml(60, 105 - 1, 250, 20, Color("Yes, I will fight this duel.", BlackColor32)); + AddHtml(60, 105 + 1, 250, 20, Color("Yes, I will fight this duel.", BlackColor32)); + AddHtml(60, 105, 250, 20, Color("Yes, I will fight this duel.", LabelColor32)); + + AddRadio(24, 135, 9727, 9730, false, 2); + AddHtml(60 - 1, 140, 250, 20, Color("No, I do not wish to fight.", BlackColor32)); + AddHtml(60 + 1, 140, 250, 20, Color("No, I do not wish to fight.", BlackColor32)); + AddHtml(60, 140 - 1, 250, 20, Color("No, I do not wish to fight.", BlackColor32)); + AddHtml(60, 140 + 1, 250, 20, Color("No, I do not wish to fight.", BlackColor32)); + AddHtml(60, 140, 250, 20, Color("No, I do not wish to fight.", LabelColor32)); + + AddRadio(24, 170, 9727, 9730, false, 3); + AddHtml(60 - 1, 175, 250, 20, Color("No, knave. Do not ask again.", BlackColor32)); + AddHtml(60 + 1, 175, 250, 20, Color("No, knave. Do not ask again.", BlackColor32)); + AddHtml(60, 175 - 1, 250, 20, Color("No, knave. Do not ask again.", BlackColor32)); + AddHtml(60, 175 + 1, 250, 20, Color("No, knave. Do not ask again.", BlackColor32)); + AddHtml(60, 175, 250, 20, Color("No, knave. Do not ask again.", LabelColor32)); + + AddButton(314, 173, 247, 248, 1); + + Timer.DelayCall(TimeSpan.FromSeconds(15.0), AutoReject); + } + + public string Center(string text) => $"
{text}
"; + + public string Color(string text, int color) => $"{text}"; + + public void AutoReject() + { + if (!m_Active) + return; + + m_Active = false; + + m_Challenged.CloseGump(); + + m_Challenger.SendMessage("{0} seems unresponsive.", m_Challenged.Name); + m_Challenged.SendMessage("You decline the challenge."); + } + + public static void BeginIgnore(Mobile source, Mobile toIgnore) + { + if (!m_IgnoreLists.TryGetValue(source, out var list)) + m_IgnoreLists[source] = list = new List(); + + for (var i = 0; i < list.Count; ++i) + { + var ie = list[i]; + + if (ie.Ignored == toIgnore) + { + ie.Refresh(); + return; + } + + if (ie.Expired) + list.RemoveAt(i--); + } + + list.Add(new IgnoreEntry(toIgnore)); + } + + public static bool IsIgnored(Mobile source, Mobile check) + { + if (!m_IgnoreLists.TryGetValue(source, out var list)) + return false; + + for (var i = 0; i < list.Count; ++i) + { + var ie = list[i]; + + if (ie.Expired) + list.RemoveAt(i--); + else if (ie.Ignored == check) + return true; + } + + return false; + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID != 1 || !m_Active || !m_Context.Registered) + return; + + m_Active = false; + + if (!m_Context.Participants.Contains(m_Participant)) + return; + + if (info.IsSwitched(1)) + { + if (!(m_Challenged is PlayerMobile pm)) + return; + + if (pm.DuelContext != null) + { + if (pm.DuelContext.Initiator == pm) + pm.SendMessage(0x22, "You have already started a duel."); + else + pm.SendMessage(0x22, "You have already been challenged in a duel."); + + m_Challenger.SendMessage("{0} cannot fight because they are already assigned to another duel.", pm.Name); + } + else if (DuelContext.CheckCombat(pm)) + { + pm.SendMessage( + 0x22, + "You have recently been in combat with another player and must wait before starting a duel." + ); + m_Challenger.SendMessage( + "{0} cannot fight because they have recently been in combat with another player.", + pm.Name + ); + } + else if (TournamentController.IsActive) + { + pm.SendMessage(0x22, "A tournament is currently active and you may not duel."); + m_Challenger.SendMessage(0x22, "A tournament is currently active and you may not duel."); + } + else + { + var added = false; + + if (m_Slot >= 0 && m_Slot < m_Participant.Players.Length && m_Participant.Players[m_Slot] == null) + { + added = true; + m_Participant.Players[m_Slot] = new DuelPlayer(m_Challenged, m_Participant); + } + else + { + for (var i = 0; i < m_Participant.Players.Length; ++i) + if (m_Participant.Players[i] == null) + { + added = true; + m_Participant.Players[i] = new DuelPlayer(m_Challenged, m_Participant); + break; + } + } + + if (added) + { + m_Challenger.SendMessage("{0} has accepted the request.", m_Challenged.Name); + m_Challenged.SendMessage("You have accepted the request from {0}.", m_Challenger.Name); + + var ns = m_Challenger.NetState; + + if (ns != null) + foreach (var g in ns.Gumps) + { + if (g is ParticipantGump pg && pg.Participant == m_Participant) + { + m_Challenger.SendGump(new ParticipantGump(m_Challenger, m_Context, m_Participant)); + break; + } + + if (g is DuelContextGump dcg && dcg.Context == m_Context) + { + m_Challenger.SendGump(new DuelContextGump(m_Challenger, m_Context)); + break; + } + } + } + else + { + m_Challenger.SendMessage( + "The participant list was full and so {0} could not join.", + m_Challenged.Name + ); + m_Challenged.SendMessage( + "The participant list was full and so you could not join the fight {1} {0}.", + m_Challenger.Name, + m_Participant.Contains(m_Challenger) ? "with" : "against" + ); + } + } + } + else + { + if (info.IsSwitched(3)) + BeginIgnore(m_Challenged, m_Challenger); + + m_Challenger.SendMessage("{0} does not wish to fight.", m_Challenged.Name); + m_Challenged.SendMessage( + "You chose not to fight {1} {0}.", + m_Challenger.Name, + m_Participant.Contains(m_Challenger) ? "with" : "against" + ); + } + } + + private class IgnoreEntry + { + private static readonly TimeSpan ExpireDelay = TimeSpan.FromMinutes(15.0); + public readonly Mobile m_Ignored; + public DateTime m_Expire; + + public IgnoreEntry(Mobile ignored) + { + m_Ignored = ignored; + Refresh(); + } + + public Mobile Ignored => m_Ignored; + public bool Expired => DateTime.UtcNow >= m_Expire; + + public void Refresh() + { + m_Expire = DateTime.UtcNow + ExpireDelay; + } + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Arena.cs b/Projects/UOContent/Engines/ConPVP/Arena.cs index 78c096c14..6c1e4aa51 100644 --- a/Projects/UOContent/Engines/ConPVP/Arena.cs +++ b/Projects/UOContent/Engines/ConPVP/Arena.cs @@ -1,783 +1,783 @@ -using System; -using System.Collections.Generic; -using Server.Gumps; -using Server.Mobiles; -using Server.Multis; - -namespace Server.Engines.ConPVP -{ - public class ArenaController : Item - { - [Constructible] - public ArenaController() : base(0x1B7A) - { - Visible = false; - Movable = false; - - Arena = new Arena(); - - Instances.Add(this); - } - - public ArenaController(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public Arena Arena { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsPrivate { get; set; } - - public override string DefaultName => "arena controller"; - - public static List Instances { get; set; } = new List(); - - public override void OnDelete() - { - base.OnDelete(); - - Instances.Remove(this); - Arena.Delete(); - } - - public override void OnDoubleClick(Mobile from) - { - if (from.AccessLevel >= AccessLevel.GameMaster) - from.SendGump(new PropertiesGump(from, Arena)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - - writer.Write(IsPrivate); - - Arena.Serialize(writer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - IsPrivate = reader.ReadBool(); - - goto case 0; - } - case 0: - { - Arena = new Arena(reader); - break; - } - } - - Instances.Add(this); - } - } - - [PropertyObject] - public class ArenaStartPoints - { - public ArenaStartPoints(Point3D[] points = null) => Points = points ?? new Point3D[8]; - - public ArenaStartPoints(IGenericReader reader) - { - Points = new Point3D[reader.ReadEncodedInt()]; - - for (int i = 0; i < Points.Length; ++i) - Points[i] = reader.ReadPoint3D(); - } - - public Point3D[] Points { get; } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D EdgeWest - { - get => Points[0]; - set => Points[0] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D EdgeEast - { - get => Points[1]; - set => Points[1] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D EdgeNorth - { - get => Points[2]; - set => Points[2] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D EdgeSouth - { - get => Points[3]; - set => Points[3] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D CornerNW - { - get => Points[4]; - set => Points[4] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D CornerSE - { - get => Points[5]; - set => Points[5] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D CornerSW - { - get => Points[6]; - set => Points[6] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D CornerNE - { - get => Points[7]; - set => Points[7] = value; - } - - public override string ToString() => "..."; - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(Points.Length); - - for (int i = 0; i < Points.Length; ++i) - writer.Write(Points[i]); - } - } - - [PropertyObject] - public class Arena : IComparable - { - private bool m_Active; - private Rectangle2D m_Bounds; - private Map m_Facet; - private Point3D m_GateOut; - - private bool m_IsGuarded; - private string m_Name; - - private SafeZone m_Region; - - private TournamentController m_Tournament; - private Rectangle2D m_Zone; - - public Arena() - { - Points = new ArenaStartPoints(); - Players = new List(); - } - - public Arena(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 7: - { - m_IsGuarded = reader.ReadBool(); - - goto case 6; - } - case 6: - { - Ladder = reader.ReadItem() as LadderController; - - goto case 5; - } - case 5: - { - m_Tournament = reader.ReadItem() as TournamentController; - Announcer = reader.ReadMobile(); - - goto case 4; - } - case 4: - { - m_Name = reader.ReadString(); - - goto case 3; - } - case 3: - { - m_Zone = reader.ReadRect2D(); - - goto case 2; - } - case 2: - { - GateIn = reader.ReadPoint3D(); - m_GateOut = reader.ReadPoint3D(); - Teleporter = reader.ReadItem(); - - goto case 1; - } - case 1: - { - Players = reader.ReadStrongMobileList(); - - goto case 0; - } - case 0: - { - m_Facet = reader.ReadMap(); - m_Bounds = reader.ReadRect2D(); - Outside = reader.ReadPoint3D(); - Wall = reader.ReadPoint3D(); - - if (version == 0) - { - reader.ReadBool(); - Players = new List(); - } - - m_Active = reader.ReadBool(); - Points = new ArenaStartPoints(reader); - - if (m_Active) - { - Arenas.Add(this); - Arenas.Sort(); - } - - break; - } - } - - if (m_Zone.Start != Point2D.Zero && m_Zone.End != Point2D.Zero && m_Facet != null) - m_Region = new SafeZone(m_Zone, Outside, m_Facet, m_IsGuarded); - - if (IsOccupied) - Timer.DelayCall(TimeSpan.FromSeconds(2.0), Evict); - - if (m_Tournament != null) - Timer.DelayCall(AttachToTournament_Sandbox); - } - - [CommandProperty(AccessLevel.GameMaster)] - public LadderController Ladder { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsGuarded - { - get => m_IsGuarded; - set - { - m_IsGuarded = value; - - if (m_Region != null) - m_Region.Disabled = !m_IsGuarded; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public TournamentController Tournament - { - get => m_Tournament; - set - { - m_Tournament?.Tournament.Arenas.Remove(this); - - m_Tournament = value; - - m_Tournament?.Tournament.Arenas.Add(this); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Announcer { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public string Name - { - get => m_Name; - set - { - m_Name = value; - if (m_Active) Arenas.Sort(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Map Facet - { - get => m_Facet; - set - { - m_Facet = value; - - if (Teleporter != null) - Teleporter.Map = value; - - m_Region?.Unregister(); - - if (m_Zone.Start != Point2D.Zero && m_Zone.End != Point2D.Zero && m_Facet != null) - m_Region = new SafeZone(m_Zone, Outside, m_Facet, m_IsGuarded); - else - m_Region = null; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Rectangle2D Bounds - { - get => m_Bounds; - set => m_Bounds = value; - } - - public int Spectators => m_Region == null ? 0 : Math.Max(m_Region.GetPlayerCount() - Players.Count, 0); - - [CommandProperty(AccessLevel.GameMaster)] - public Rectangle2D Zone - { - get => m_Zone; - set - { - m_Zone = value; - - if (m_Zone.Start != Point2D.Zero && m_Zone.End != Point2D.Zero && m_Facet != null) - { - m_Region?.Unregister(); - - m_Region = new SafeZone(m_Zone, Outside, m_Facet, m_IsGuarded); - } - else - { - m_Region?.Unregister(); - - m_Region = null; - } - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D Outside { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D GateIn { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D GateOut - { - get => m_GateOut; - set - { - m_GateOut = value; - if (Teleporter != null) - Teleporter.Location = m_GateOut; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D Wall { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsOccupied => Players.Count > 0; - - [CommandProperty(AccessLevel.GameMaster)] - public ArenaStartPoints Points { get; private set; } - - public Item Teleporter { get; set; } - - public List Players { get; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Active - { - get => m_Active; - set - { - if (m_Active == value) - return; - - m_Active = value; - - if (m_Active) - { - Arenas.Add(this); - Arenas.Sort(); - } - else - { - Arenas.Remove(this); - } - } - } - - [CommandProperty(AccessLevel.Administrator, AccessLevel.Administrator)] - public bool ForceEvict - { - get => false; - set - { - if (value) Evict(); - } - } - - public static List Arenas { get; } = new List(); - - public int CompareTo(Arena c) - { - string a = m_Name; - string b = c.m_Name; - - if (a == null && b == null) - return 0; - if (a == null) - return -1; - if (b == null) - return +1; - - return a.CompareTo(b); - } - - public Ladder AcquireLadder() => Ladder?.Ladder ?? ConPVP.Ladder.Instance; - - public void Delete() - { - Active = false; - m_Region?.Unregister(); - m_Region = null; - } - - public override string ToString() => "..."; - - public Point3D GetBaseStartPoint(int index) => Points.Points[Math.Max(index, 0) % Points.Points.Length]; - - public void MoveInside(DuelPlayer[] players, int index) - { - index = Math.Min(index, 0) % Points.Points.Length; - - Point3D start = Points.Points[index]; - - int offset = 0; - - Point2D[] offsets = index < 4 ? m_EdgeOffsets : m_CornerOffsets; - int[,] matrix = m_Rotate[index]; - - for (int i = 0; i < players.Length; ++i) - { - DuelPlayer pl = players[i]; - - if (pl == null) - continue; - - Mobile mob = pl.Mobile; - - Point2D p; - - if (offset < offsets.Length) - p = offsets[offset++]; - else - p = offsets[^1]; - - p.X = p.X * matrix[0, 0] + p.Y * matrix[0, 1]; - p.Y = p.X * matrix[1, 0] + p.Y * matrix[1, 1]; - - mob.MoveToWorld(new Point3D(start.X + p.X, start.Y + p.Y, start.Z), m_Facet); - mob.Direction = mob.GetDirectionTo(Wall); - - Players.Add(mob); - } - } - - private void AttachToTournament_Sandbox() - { - m_Tournament?.Tournament.Arenas.Add(this); - } - - public void Evict() - { - Point3D loc; - Map facet; - - if (m_Facet == null) - { - loc = new Point3D(2715, 2165, 0); - facet = Map.Felucca; - } - else - { - loc = Outside; - facet = m_Facet; - } - - bool hasBounds = m_Bounds.Start != Point2D.Zero && m_Bounds.End != Point2D.Zero; - - for (int i = 0; i < Players.Count; ++i) - { - Mobile mob = Players[i]; - - if (mob == null) - continue; - - if (mob.Map == Map.Internal) - { - if ((m_Facet == null || mob.LogoutMap == m_Facet) && - (!hasBounds || m_Bounds.Contains(mob.LogoutLocation))) - mob.LogoutLocation = loc; - } - else if ((m_Facet == null || mob.Map == m_Facet) && (!hasBounds || m_Bounds.Contains(mob.Location))) - { - mob.MoveToWorld(loc, facet); - } - - mob.Combatant = null; - mob.Frozen = false; - DuelContext.Debuff(mob); - DuelContext.CancelSpell(mob); - } - - if (hasBounds) - { - List pets = new List(); - - foreach (Mobile mob in facet.GetMobilesInBounds(m_Bounds)) - if (mob is BaseCreature pet && pet.Controlled && pet.ControlMaster != null && - Players.Contains(pet.ControlMaster)) - pets.Add(pet); - - foreach (Mobile pet in pets) - { - pet.Combatant = null; - pet.Frozen = false; - - pet.MoveToWorld(loc, facet); - } - } - - Players.Clear(); - } - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(7); - - writer.Write(m_IsGuarded); - - writer.Write(Ladder); - - writer.Write(m_Tournament); - writer.Write(Announcer); - - writer.Write(m_Name); - - writer.Write(m_Zone); - - writer.Write(GateIn); - writer.Write(m_GateOut); - writer.Write(Teleporter); - - writer.Write(Players); - - writer.Write(m_Facet); - writer.Write(m_Bounds); - writer.Write(Outside); - writer.Write(Wall); - writer.Write(m_Active); - - Points.Serialize(writer); - } - - public static Arena FindArena(List players) - { - Preferences prefs = Preferences.Instance; - - if (prefs == null) - return FindArena(); - - if (Arenas.Count == 0) - return null; - - if (players.Count > 0) - { - Mobile first = players[0]; - - List allControllers = ArenaController.Instances; - - for (int i = 0; i < allControllers.Count; ++i) - { - ArenaController controller = allControllers[i]; - - if (controller?.Deleted == false && controller.Arena != null && controller.IsPrivate && - controller.Map == first.Map && first.InRange(controller, 24)) - { - BaseHouse house = BaseHouse.FindHouseAt(controller); - bool allNear = true; - - for (int j = 0; j < players.Count; ++j) - { - Mobile check = players[j]; - bool isNear; - - if (house == null) - isNear = controller.Map == check.Map && check.InRange(controller, 24); - else - isNear = BaseHouse.FindHouseAt(check) == house; - - if (!isNear) - { - allNear = false; - break; - } - } - - if (allNear) - return controller.Arena; - } - } - } - - List arenas = new List(); - - for (int i = 0; i < Arenas.Count; ++i) - { - Arena arena = Arenas[i]; - - if (!arena.IsOccupied) - arenas.Add(new ArenaEntry(arena)); - } - - if (arenas.Count == 0) - return Arenas[0]; - - int tc = 0; - - for (int i = 0; i < arenas.Count; ++i) - { - ArenaEntry ae = arenas[i]; - - for (int j = 0; j < players.Count; ++j) - { - PreferencesEntry pe = prefs.Find(players[j]); - - if (pe.Disliked.Contains(ae.m_Arena.Name)) - ++ae.m_VotesAgainst; - else - ++ae.m_VotesFor; - } - - tc += ae.Value; - } - - int rn = Utility.Random(tc); - - for (int i = 0; i < arenas.Count; ++i) - { - ArenaEntry ae = arenas[i]; - - if (rn < ae.Value) - return ae.m_Arena; - - rn -= ae.Value; - } - - return arenas.RandomElement().m_Arena; - } - - public static Arena FindArena() - { - if (Arenas.Count == 0) - return null; - - int offset = Utility.Random(Arenas.Count); - - for (int i = 0; i < Arenas.Count; ++i) - { - Arena arena = Arenas[(i + offset) % Arenas.Count]; - - if (!arena.IsOccupied) - return arena; - } - - return Arenas[offset]; - } - - private class ArenaEntry - { - public readonly Arena m_Arena; - public int m_VotesAgainst; - public int m_VotesFor; - - public ArenaEntry(Arena arena) => m_Arena = arena; - - public int Value => m_VotesFor; - } - - private static readonly Point2D[] m_EdgeOffsets = - { - /* - * /\ - * /\/\ - * /\/\/\ - * \/\/\/ - * \/\/\ - * \/\/ - */ - new Point2D(0, 0), - new Point2D(0, -1), - new Point2D(0, +1), - new Point2D(1, 0), - new Point2D(1, -1), - new Point2D(1, +1), - new Point2D(2, 0), - new Point2D(2, -1), - new Point2D(2, +1), - new Point2D(3, 0) - }; - - // nw corner - private static readonly Point2D[] m_CornerOffsets = - { - /* - * /\ - * /\/\ - * /\/\/\ - * /\/\/\/\ - * \/\/\/\/ - */ - new Point2D(0, 0), - new Point2D(0, 1), - new Point2D(1, 0), - new Point2D(1, 1), - new Point2D(0, 2), - new Point2D(2, 0), - new Point2D(2, 1), - new Point2D(1, 2), - new Point2D(0, 3), - new Point2D(3, 0) - }; - - private static readonly int[][,] m_Rotate = - { - new[,] { { +1, 0 }, { 0, +1 } }, // west - new[,] { { -1, 0 }, { 0, -1 } }, // east - new[,] { { 0, +1 }, { +1, 0 } }, // north - new[,] { { 0, -1 }, { -1, 0 } }, // south - new[,] { { +1, 0 }, { 0, +1 } }, // nw - new[,] { { -1, 0 }, { 0, -1 } }, // se - new[,] { { 0, +1 }, { +1, 0 } }, // sw - new[,] { { 0, -1 }, { -1, 0 } } // ne - }; - } -} +using System; +using System.Collections.Generic; +using Server.Gumps; +using Server.Mobiles; +using Server.Multis; + +namespace Server.Engines.ConPVP +{ + public class ArenaController : Item + { + [Constructible] + public ArenaController() : base(0x1B7A) + { + Visible = false; + Movable = false; + + Arena = new Arena(); + + Instances.Add(this); + } + + public ArenaController(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public Arena Arena { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsPrivate { get; set; } + + public override string DefaultName => "arena controller"; + + public static List Instances { get; set; } = new List(); + + public override void OnDelete() + { + base.OnDelete(); + + Instances.Remove(this); + Arena.Delete(); + } + + public override void OnDoubleClick(Mobile from) + { + if (from.AccessLevel >= AccessLevel.GameMaster) + from.SendGump(new PropertiesGump(from, Arena)); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + + writer.Write(IsPrivate); + + Arena.Serialize(writer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + IsPrivate = reader.ReadBool(); + + goto case 0; + } + case 0: + { + Arena = new Arena(reader); + break; + } + } + + Instances.Add(this); + } + } + + [PropertyObject] + public class ArenaStartPoints + { + public ArenaStartPoints(Point3D[] points = null) => Points = points ?? new Point3D[8]; + + public ArenaStartPoints(IGenericReader reader) + { + Points = new Point3D[reader.ReadEncodedInt()]; + + for (var i = 0; i < Points.Length; ++i) + Points[i] = reader.ReadPoint3D(); + } + + public Point3D[] Points { get; } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D EdgeWest + { + get => Points[0]; + set => Points[0] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D EdgeEast + { + get => Points[1]; + set => Points[1] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D EdgeNorth + { + get => Points[2]; + set => Points[2] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D EdgeSouth + { + get => Points[3]; + set => Points[3] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D CornerNW + { + get => Points[4]; + set => Points[4] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D CornerSE + { + get => Points[5]; + set => Points[5] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D CornerSW + { + get => Points[6]; + set => Points[6] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D CornerNE + { + get => Points[7]; + set => Points[7] = value; + } + + public override string ToString() => "..."; + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(Points.Length); + + for (var i = 0; i < Points.Length; ++i) + writer.Write(Points[i]); + } + } + + [PropertyObject] + public class Arena : IComparable + { + private static readonly Point2D[] m_EdgeOffsets = + { + /* + * /\ + * /\/\ + * /\/\/\ + * \/\/\/ + * \/\/\ + * \/\/ + */ + new Point2D(0, 0), + new Point2D(0, -1), + new Point2D(0, +1), + new Point2D(1, 0), + new Point2D(1, -1), + new Point2D(1, +1), + new Point2D(2, 0), + new Point2D(2, -1), + new Point2D(2, +1), + new Point2D(3, 0) + }; + + // nw corner + private static readonly Point2D[] m_CornerOffsets = + { + /* + * /\ + * /\/\ + * /\/\/\ + * /\/\/\/\ + * \/\/\/\/ + */ + new Point2D(0, 0), + new Point2D(0, 1), + new Point2D(1, 0), + new Point2D(1, 1), + new Point2D(0, 2), + new Point2D(2, 0), + new Point2D(2, 1), + new Point2D(1, 2), + new Point2D(0, 3), + new Point2D(3, 0) + }; + + private static readonly int[][,] m_Rotate = + { + new[,] { { +1, 0 }, { 0, +1 } }, // west + new[,] { { -1, 0 }, { 0, -1 } }, // east + new[,] { { 0, +1 }, { +1, 0 } }, // north + new[,] { { 0, -1 }, { -1, 0 } }, // south + new[,] { { +1, 0 }, { 0, +1 } }, // nw + new[,] { { -1, 0 }, { 0, -1 } }, // se + new[,] { { 0, +1 }, { +1, 0 } }, // sw + new[,] { { 0, -1 }, { -1, 0 } } // ne + }; + + private bool m_Active; + private Rectangle2D m_Bounds; + private Map m_Facet; + private Point3D m_GateOut; + + private bool m_IsGuarded; + private string m_Name; + + private SafeZone m_Region; + + private TournamentController m_Tournament; + private Rectangle2D m_Zone; + + public Arena() + { + Points = new ArenaStartPoints(); + Players = new List(); + } + + public Arena(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 7: + { + m_IsGuarded = reader.ReadBool(); + + goto case 6; + } + case 6: + { + Ladder = reader.ReadItem() as LadderController; + + goto case 5; + } + case 5: + { + m_Tournament = reader.ReadItem() as TournamentController; + Announcer = reader.ReadMobile(); + + goto case 4; + } + case 4: + { + m_Name = reader.ReadString(); + + goto case 3; + } + case 3: + { + m_Zone = reader.ReadRect2D(); + + goto case 2; + } + case 2: + { + GateIn = reader.ReadPoint3D(); + m_GateOut = reader.ReadPoint3D(); + Teleporter = reader.ReadItem(); + + goto case 1; + } + case 1: + { + Players = reader.ReadStrongMobileList(); + + goto case 0; + } + case 0: + { + m_Facet = reader.ReadMap(); + m_Bounds = reader.ReadRect2D(); + Outside = reader.ReadPoint3D(); + Wall = reader.ReadPoint3D(); + + if (version == 0) + { + reader.ReadBool(); + Players = new List(); + } + + m_Active = reader.ReadBool(); + Points = new ArenaStartPoints(reader); + + if (m_Active) + { + Arenas.Add(this); + Arenas.Sort(); + } + + break; + } + } + + if (m_Zone.Start != Point2D.Zero && m_Zone.End != Point2D.Zero && m_Facet != null) + m_Region = new SafeZone(m_Zone, Outside, m_Facet, m_IsGuarded); + + if (IsOccupied) + Timer.DelayCall(TimeSpan.FromSeconds(2.0), Evict); + + if (m_Tournament != null) + Timer.DelayCall(AttachToTournament_Sandbox); + } + + [CommandProperty(AccessLevel.GameMaster)] + public LadderController Ladder { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsGuarded + { + get => m_IsGuarded; + set + { + m_IsGuarded = value; + + if (m_Region != null) + m_Region.Disabled = !m_IsGuarded; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public TournamentController Tournament + { + get => m_Tournament; + set + { + m_Tournament?.Tournament.Arenas.Remove(this); + + m_Tournament = value; + + m_Tournament?.Tournament.Arenas.Add(this); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Announcer { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public string Name + { + get => m_Name; + set + { + m_Name = value; + if (m_Active) Arenas.Sort(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Map Facet + { + get => m_Facet; + set + { + m_Facet = value; + + if (Teleporter != null) + Teleporter.Map = value; + + m_Region?.Unregister(); + + if (m_Zone.Start != Point2D.Zero && m_Zone.End != Point2D.Zero && m_Facet != null) + m_Region = new SafeZone(m_Zone, Outside, m_Facet, m_IsGuarded); + else + m_Region = null; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Rectangle2D Bounds + { + get => m_Bounds; + set => m_Bounds = value; + } + + public int Spectators => m_Region == null ? 0 : Math.Max(m_Region.GetPlayerCount() - Players.Count, 0); + + [CommandProperty(AccessLevel.GameMaster)] + public Rectangle2D Zone + { + get => m_Zone; + set + { + m_Zone = value; + + if (m_Zone.Start != Point2D.Zero && m_Zone.End != Point2D.Zero && m_Facet != null) + { + m_Region?.Unregister(); + + m_Region = new SafeZone(m_Zone, Outside, m_Facet, m_IsGuarded); + } + else + { + m_Region?.Unregister(); + + m_Region = null; + } + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D Outside { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D GateIn { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D GateOut + { + get => m_GateOut; + set + { + m_GateOut = value; + if (Teleporter != null) + Teleporter.Location = m_GateOut; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D Wall { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsOccupied => Players.Count > 0; + + [CommandProperty(AccessLevel.GameMaster)] + public ArenaStartPoints Points { get; } + + public Item Teleporter { get; set; } + + public List Players { get; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Active + { + get => m_Active; + set + { + if (m_Active == value) + return; + + m_Active = value; + + if (m_Active) + { + Arenas.Add(this); + Arenas.Sort(); + } + else + { + Arenas.Remove(this); + } + } + } + + [CommandProperty(AccessLevel.Administrator, AccessLevel.Administrator)] + public bool ForceEvict + { + get => false; + set + { + if (value) Evict(); + } + } + + public static List Arenas { get; } = new List(); + + public int CompareTo(Arena c) + { + var a = m_Name; + var b = c.m_Name; + + if (a == null && b == null) + return 0; + if (a == null) + return -1; + if (b == null) + return +1; + + return a.CompareTo(b); + } + + public Ladder AcquireLadder() => Ladder?.Ladder ?? ConPVP.Ladder.Instance; + + public void Delete() + { + Active = false; + m_Region?.Unregister(); + m_Region = null; + } + + public override string ToString() => "..."; + + public Point3D GetBaseStartPoint(int index) => Points.Points[Math.Max(index, 0) % Points.Points.Length]; + + public void MoveInside(DuelPlayer[] players, int index) + { + index = Math.Min(index, 0) % Points.Points.Length; + + var start = Points.Points[index]; + + var offset = 0; + + var offsets = index < 4 ? m_EdgeOffsets : m_CornerOffsets; + var matrix = m_Rotate[index]; + + for (var i = 0; i < players.Length; ++i) + { + var pl = players[i]; + + if (pl == null) + continue; + + var mob = pl.Mobile; + + Point2D p; + + if (offset < offsets.Length) + p = offsets[offset++]; + else + p = offsets[^1]; + + p.X = p.X * matrix[0, 0] + p.Y * matrix[0, 1]; + p.Y = p.X * matrix[1, 0] + p.Y * matrix[1, 1]; + + mob.MoveToWorld(new Point3D(start.X + p.X, start.Y + p.Y, start.Z), m_Facet); + mob.Direction = mob.GetDirectionTo(Wall); + + Players.Add(mob); + } + } + + private void AttachToTournament_Sandbox() + { + m_Tournament?.Tournament.Arenas.Add(this); + } + + public void Evict() + { + Point3D loc; + Map facet; + + if (m_Facet == null) + { + loc = new Point3D(2715, 2165, 0); + facet = Map.Felucca; + } + else + { + loc = Outside; + facet = m_Facet; + } + + var hasBounds = m_Bounds.Start != Point2D.Zero && m_Bounds.End != Point2D.Zero; + + for (var i = 0; i < Players.Count; ++i) + { + var mob = Players[i]; + + if (mob == null) + continue; + + if (mob.Map == Map.Internal) + { + if ((m_Facet == null || mob.LogoutMap == m_Facet) && + (!hasBounds || m_Bounds.Contains(mob.LogoutLocation))) + mob.LogoutLocation = loc; + } + else if ((m_Facet == null || mob.Map == m_Facet) && (!hasBounds || m_Bounds.Contains(mob.Location))) + { + mob.MoveToWorld(loc, facet); + } + + mob.Combatant = null; + mob.Frozen = false; + DuelContext.Debuff(mob); + DuelContext.CancelSpell(mob); + } + + if (hasBounds) + { + var pets = new List(); + + foreach (var mob in facet.GetMobilesInBounds(m_Bounds)) + if (mob is BaseCreature pet && pet.Controlled && pet.ControlMaster != null && + Players.Contains(pet.ControlMaster)) + pets.Add(pet); + + foreach (var pet in pets) + { + pet.Combatant = null; + pet.Frozen = false; + + pet.MoveToWorld(loc, facet); + } + } + + Players.Clear(); + } + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(7); + + writer.Write(m_IsGuarded); + + writer.Write(Ladder); + + writer.Write(m_Tournament); + writer.Write(Announcer); + + writer.Write(m_Name); + + writer.Write(m_Zone); + + writer.Write(GateIn); + writer.Write(m_GateOut); + writer.Write(Teleporter); + + writer.Write(Players); + + writer.Write(m_Facet); + writer.Write(m_Bounds); + writer.Write(Outside); + writer.Write(Wall); + writer.Write(m_Active); + + Points.Serialize(writer); + } + + public static Arena FindArena(List players) + { + var prefs = Preferences.Instance; + + if (prefs == null) + return FindArena(); + + if (Arenas.Count == 0) + return null; + + if (players.Count > 0) + { + var first = players[0]; + + var allControllers = ArenaController.Instances; + + for (var i = 0; i < allControllers.Count; ++i) + { + var controller = allControllers[i]; + + if (controller?.Deleted == false && controller.Arena != null && controller.IsPrivate && + controller.Map == first.Map && first.InRange(controller, 24)) + { + var house = BaseHouse.FindHouseAt(controller); + var allNear = true; + + for (var j = 0; j < players.Count; ++j) + { + var check = players[j]; + bool isNear; + + if (house == null) + isNear = controller.Map == check.Map && check.InRange(controller, 24); + else + isNear = BaseHouse.FindHouseAt(check) == house; + + if (!isNear) + { + allNear = false; + break; + } + } + + if (allNear) + return controller.Arena; + } + } + } + + var arenas = new List(); + + for (var i = 0; i < Arenas.Count; ++i) + { + var arena = Arenas[i]; + + if (!arena.IsOccupied) + arenas.Add(new ArenaEntry(arena)); + } + + if (arenas.Count == 0) + return Arenas[0]; + + var tc = 0; + + for (var i = 0; i < arenas.Count; ++i) + { + var ae = arenas[i]; + + for (var j = 0; j < players.Count; ++j) + { + var pe = prefs.Find(players[j]); + + if (pe.Disliked.Contains(ae.m_Arena.Name)) + ++ae.m_VotesAgainst; + else + ++ae.m_VotesFor; + } + + tc += ae.Value; + } + + var rn = Utility.Random(tc); + + for (var i = 0; i < arenas.Count; ++i) + { + var ae = arenas[i]; + + if (rn < ae.Value) + return ae.m_Arena; + + rn -= ae.Value; + } + + return arenas.RandomElement().m_Arena; + } + + public static Arena FindArena() + { + if (Arenas.Count == 0) + return null; + + var offset = Utility.Random(Arenas.Count); + + for (var i = 0; i < Arenas.Count; ++i) + { + var arena = Arenas[(i + offset) % Arenas.Count]; + + if (!arena.IsOccupied) + return arena; + } + + return Arenas[offset]; + } + + private class ArenaEntry + { + public readonly Arena m_Arena; + public int m_VotesAgainst; + public int m_VotesFor; + + public ArenaEntry(Arena arena) => m_Arena = arena; + + public int Value => m_VotesFor; + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/DuelContext.cs b/Projects/UOContent/Engines/ConPVP/DuelContext.cs index a20102c34..8eb597302 100644 --- a/Projects/UOContent/Engines/ConPVP/DuelContext.cs +++ b/Projects/UOContent/Engines/ConPVP/DuelContext.cs @@ -1,2442 +1,2504 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using Server.Engines.PartySystem; -using Server.Factions; -using Server.Gumps; -using Server.Items; -using Server.Mobiles; -using Server.Network; -using Server.Regions; -using Server.Spells; -using Server.Spells.Bushido; -using Server.Spells.Chivalry; -using Server.Spells.Fourth; -using Server.Spells.Necromancy; -using Server.Spells.Ninjitsu; -using Server.Spells.Second; -using Server.Spells.Seventh; -using Server.Spells.Spellweaving; -using Server.Targeting; - -namespace Server.Engines.ConPVP -{ - public delegate void CountdownCallback(int count); - - public class DuelContext - { - private static readonly TimeSpan CombatDelay = TimeSpan.FromSeconds(30.0); - private static readonly TimeSpan AutoTieDelay = TimeSpan.FromMinutes(15.0); - - private Timer m_AutoTieTimer; - - private Timer m_Countdown; - - public EventGame m_EventGame; - private Map m_GateFacet; - - private Point3D m_GatePoint; - public TourneyMatch m_Match; - - public Arena m_OverrideArena; - - private Timer m_SDWarnTimer, m_SDActivateTimer; - public Tournament m_Tournament; - - private readonly List m_Walls = new List(); - - private bool m_Yielding; - - public DuelContext(Mobile initiator, RulesetLayout layout, bool addNew = true) - { - Initiator = initiator; - Participants = new List(); - Ruleset = new Ruleset(layout); - Ruleset.ApplyDefault(layout.Defaults[0]); - - if (addNew) - { - Participants.Add(new Participant(this, 1)); - Participants.Add(new Participant(this, 1)); - Participants[0].Add(initiator); - } - } - - public bool Rematch { get; private set; } - - public bool ReadyWait { get; private set; } - - public int ReadyCount { get; private set; } - - public bool Registered { get; private set; } = true; - - public bool Finished { get; private set; } - - public bool Started { get; private set; } - - public Mobile Initiator { get; } - - public List Participants { get; } - - public Ruleset Ruleset { get; private set; } - - public Arena Arena { get; private set; } - - public bool Tied { get; private set; } - - public bool IsSuddenDeath { get; set; } - - public bool IsOneVsOne => Participants.Count == 2 && Participants[0].Players.Length == 1 && - Participants[1].Players.Length == 1; - - public bool StartedBeginCountdown { get; private set; } - - public bool StartedReadyCountdown { get; private set; } - - public Tournament Tournament => m_Tournament; - - private bool CantDoAnything(Mobile mob) => m_EventGame?.CantDoAnything(mob) == true; - - public static bool IsFreeConsume(Mobile mob) - { - if (!(mob is PlayerMobile pm) || pm.DuelContext?.m_EventGame == null) - return false; - - return pm.DuelContext.m_EventGame.FreeConsume; - } - - public void DelayBounce(TimeSpan ts, Mobile mob, Container corpse) - { - Timer.DelayCall(ts, DelayBounce_Callback, mob, corpse); - } - - public static bool AllowSpecialMove(Mobile from, string name, SpecialMove move) => (from as PlayerMobile)?.DuelContext?.InstAllowSpecialMove(from, name, move) != false; - - public bool InstAllowSpecialMove(Mobile from, string name, SpecialMove move) - { - if (!StartedBeginCountdown) - return true; - - DuelPlayer pl = Find(from); - - if (pl?.Eliminated != false) - return true; - - if (CantDoAnything(from)) - return false; - - string title = null; - - if (move is NinjaMove) - title = "Bushido"; - else if (move is SamuraiMove) - title = "Ninjitsu"; - - if (title == null || name == null || Ruleset.GetOption(title, name)) - return true; - - from.SendMessage("The dueling ruleset prevents you from using this move."); - return false; - } - - public bool AllowSpellCast(Mobile from, Spell spell) - { - if (!StartedBeginCountdown) - return true; - - if (Find(from)?.Eliminated != false) - return true; - - if (CantDoAnything(from)) - return false; - - if (spell is RecallSpell) - from.SendMessage("You may not cast this spell."); - - string title; - string option; - - switch (spell) - { - case ArcanistSpell _: - title = "Spellweaving"; - option = spell.Name; - break; - case PaladinSpell _: - title = "Chivalry"; - option = spell.Name; - break; - case NecromancerSpell _: - title = "Necromancy"; - option = spell.Name; - break; - case NinjaSpell _: - title = "Ninjitsu"; - option = spell.Name; - break; - case SamuraiSpell _: - title = "Bushido"; - option = spell.Name; - break; - case MagerySpell magerySpell: - title = magerySpell.Circle switch - { - SpellCircle.First => "1st Circle", - SpellCircle.Second => "2nd Circle", - SpellCircle.Third => "3rd Circle", - SpellCircle.Fourth => "4th Circle", - SpellCircle.Fifth => "5th Circle", - SpellCircle.Sixth => "6th Circle", - SpellCircle.Seventh => "7th Circle", - SpellCircle.Eighth => "8th Circle", - _ => null - }; - - option = magerySpell.Name; - break; - default: - title = "Other Spell"; - option = spell.Name; - break; - } - - if (title == null || option == null || Ruleset.GetOption(title, option)) - return true; - - from.SendMessage("The dueling ruleset prevents you from casting this spell."); - return false; - } - - public bool AllowItemEquip(Mobile from, Item item) - { - if (!StartedBeginCountdown) - return true; - - DuelPlayer pl = Find(from); - - if (pl?.Eliminated != false) - return true; - - if (item is Dagger || CheckItemEquip(from, item)) - return true; - - from.SendMessage("The dueling ruleset prevents you from equipping this item."); - return false; - } - - public static bool AllowSpecialAbility(Mobile from, string name, bool message) - { - if (!(from is PlayerMobile pm)) - return true; - - DuelContext dc = pm.DuelContext; - - // No DuelContext or InstAllowSpecialAbility - return dc?.InstAllowSpecialAbility(from, name, message) != false; - } - - public bool InstAllowSpecialAbility(Mobile from, string name, bool message) - { - if (!StartedBeginCountdown) - return true; - - DuelPlayer pl = Find(from); - - if (pl?.Eliminated != false) - return true; - - if (CantDoAnything(from)) - return false; - - if (Ruleset.GetOption("Combat Abilities", name)) - return true; - - if (message) - from.SendMessage("The dueling ruleset prevents you from using this combat ability."); - - return false; - } - - public bool CheckItemEquip(Mobile from, Item item) - { - if (item is Fists) - { - if (!Ruleset.GetOption("Weapons", "Wrestling")) - return false; - } - else if (item is BaseArmor armor) - { - if (armor.ProtectionLevel > ArmorProtectionLevel.Regular && !Ruleset.GetOption("Armor", "Magical")) - return false; - - if (!Core.AOS && armor.Resource != armor.DefaultResource && !Ruleset.GetOption("Armor", "Colored")) - return false; - - if (armor is BaseShield && !Ruleset.GetOption("Armor", "Shields")) - return false; - } - else if (item is BaseWeapon weapon) - { - if ((weapon.DamageLevel > WeaponDamageLevel.Regular || weapon.AccuracyLevel > WeaponAccuracyLevel.Regular) && - !Ruleset.GetOption("Weapons", "Magical")) - return false; - - if (!Core.AOS && weapon.Resource != CraftResource.Iron && weapon.Resource != CraftResource.None && - !Ruleset.GetOption("Weapons", "Runics")) - return false; - - if (weapon is BaseRanged && !Ruleset.GetOption("Weapons", "Ranged")) - return false; - - if (!(weapon is BaseRanged) && !Ruleset.GetOption("Weapons", "Melee")) - return false; - - if (weapon.PoisonCharges > 0 && weapon.Poison != null && !Ruleset.GetOption("Weapons", "Poisoned")) - return false; - - if (weapon is BaseWand && !Ruleset.GetOption("Items", "Wands")) - return false; - } - - return true; - } - - public bool AllowSkillUse(Mobile from, SkillName skill) - { - if (!StartedBeginCountdown) - return true; - - DuelPlayer pl = Find(from); - - if (pl?.Eliminated != false) - return true; - - if (CantDoAnything(from)) - return false; - - int id = (int)skill; - - if (id >= 0 && id < SkillInfo.Table.Length) - if (Ruleset.GetOption("Skills", SkillInfo.Table[id].Name)) - return true; - - from.SendMessage("The dueling ruleset prevents you from using this skill."); - return false; - } - - public bool AllowItemUse(Mobile from, Item item) - { - if (!StartedBeginCountdown) - return true; - - DuelPlayer pl = Find(from); - - if (pl?.Eliminated != false) - return true; - - if (!(item is BaseRefreshPotion)) - if (CantDoAnything(from)) - return false; - - string title = null, option = null; - - if (item is BasePotion) - { - title = "Potions"; - - if (item is BaseAgilityPotion) - option = "Agility"; - else if (item is BaseCurePotion) - option = "Cure"; - else if (item is BaseHealPotion) - option = "Heal"; - else if (item is NightSightPotion) - option = "Nightsight"; - else if (item is BasePoisonPotion) - option = "Poison"; - else if (item is BaseStrengthPotion) - option = "Strength"; - else if (item is BaseExplosionPotion) - option = "Explosion"; - else if (item is BaseRefreshPotion) - option = "Refresh"; - } - else if (item is Bandage) - { - title = "Items"; - option = "Bandages"; - } - else if (item is TrappableContainer container) - { - if (container.TrapType != TrapType.None) - { - title = "Items"; - option = "Trapped Containers"; - } - } - else if (item is Bola) - { - title = "Items"; - option = "Bolas"; - } - else if (item is OrangePetals) - { - title = "Items"; - option = "Orange Petals"; - } - else if (item is EtherealMount || item.Layer == Layer.Mount) - { - title = "Items"; - option = "Mounts"; - } - else if (item is LeatherNinjaBelt) - { - title = "Items"; - option = "Shurikens"; - } - else if (item is Fukiya) - { - title = "Items"; - option = "Fukiya Darts"; - } - else if (item is FireHorn) - { - title = "Items"; - option = "Fire Horns"; - } - else if (item is BaseWand) - { - title = "Items"; - option = "Wands"; - } - - if (title != null && option != null && StartedBeginCountdown && !Started) - { - from.SendMessage("You may not use this item before the duel begins."); - return false; - } - - if (item is BasePotion && !(item is BaseExplosionPotion) && !(item is BaseRefreshPotion) && IsSuddenDeath) - { - from.SendMessage(0x22, "You may not drink potions in sudden death."); - return false; - } - - if (item is Bandage && IsSuddenDeath) - { - from.SendMessage(0x22, "You may not use bandages in sudden death."); - return false; - } - - if (title == null || option == null || Ruleset.GetOption(title, option)) - return true; - - from.SendMessage("The dueling ruleset prevents you from using this item."); - return false; - } - - private void DelayBounce_Callback(Mobile mob, Container corpse) - { - RemoveAggressions(mob); - SendOutside(mob); - Refresh(mob, corpse); - Debuff(mob); - CancelSpell(mob); - mob.Frozen = false; - } - - public void OnMapChanged(Mobile mob) - { - OnLocationChanged(mob); - } - - public void OnLocationChanged(Mobile mob) - { - if (!Registered || !StartedBeginCountdown || Finished) - return; - - Arena arena = Arena; - - if (arena == null) - return; - - if (mob.Map == arena.Facet && arena.Bounds.Contains(mob.Location)) - return; - - DuelPlayer pl = Find(mob); - - if (pl?.Eliminated != false) - return; - - if (mob.Map == Map.Internal) - if (mob.LogoutMap == arena.Facet && arena.Bounds.Contains(mob.LogoutLocation)) - mob.LogoutLocation = arena.Outside; - - pl.Eliminated = true; - - mob.LocalOverheadMessage(MessageType.Regular, 0x22, false, "You have forfeited your position in the duel."); - mob.NonlocalOverheadMessage(MessageType.Regular, 0x22, false, - $"{mob.Name} has forfeited by leaving the dueling arena."); - - Participant winner = CheckCompletion(); - - if (winner != null) - Finish(winner); - } - - public void OnDeath(Mobile mob, Container corpse) - { - if (!Registered || !Started) - return; - - DuelPlayer pl = Find(mob); - - if (pl?.Eliminated != false || m_EventGame?.OnDeath(mob, corpse) == false) - return; - - pl.Eliminated = true; - - if (mob.Poison != null) - mob.Poison = null; - - Requip(mob, corpse); - DelayBounce(TimeSpan.FromSeconds(4.0), mob, corpse); - - Participant winner = CheckCompletion(); - - if (winner != null) - { - Finish(winner); - } - else if (!m_Yielding) - { - mob.LocalOverheadMessage(MessageType.Regular, 0x22, false, "You have been defeated."); - mob.NonlocalOverheadMessage(MessageType.Regular, 0x22, false, $"{mob.Name} has been defeated."); - } - } - - public bool CheckFull() - { - for (int i = 0; i < Participants.Count; ++i) - { - Participant p = Participants[i]; - - if (p.HasOpenSlot) - return false; - } - - return true; - } - - public void Requip(Mobile from, Container cont) - { - if (!(cont is Corpse corpse)) - return; - - List items = new List(corpse.Items); - - bool didntFit = false; - - Container pack = from.Backpack; - - for (int i = 0; !didntFit && i < items.Count; ++i) - { - Item item = items[i]; - - if (item.Layer == Layer.Hair || item.Layer == Layer.FacialHair || !item.Movable) - continue; - - if (pack != null) - pack.DropItem(item); - else - didntFit = true; - } - - corpse.Carved = true; - - if (corpse.ItemID == 0x2006) - { - corpse.ProcessDelta(); - corpse.SendRemovePacket(); - corpse.ItemID = Utility.Random(0xECA, 9); // bone graphic - corpse.Hue = 0; - corpse.ProcessDelta(); - - Mobile killer = from.FindMostRecentDamager(false); - - if (killer?.Player == true) - killer.AddToBackpack(new Head(m_Tournament == null ? HeadType.Duel : HeadType.Tournament, from.Name)); - } - - from.PlaySound(0x3E3); - - if (didntFit) - from.SendLocalizedMessage(1062472); // You gather some of your belongings. The rest remain on the corpse. - else - from.SendLocalizedMessage(1062471); // You quickly gather all of your belongings. - } - - public void Refresh(Mobile mob, Container cont) - { - if (!mob.Alive) - { - mob.Resurrect(); - - if (mob.FindItemOnLayer(Layer.OuterTorso) is DeathRobe robe) - robe.Delete(); - - if (cont is Corpse corpse) - for (int i = 0; i < corpse.EquipItems.Count; ++i) - { - Item item = corpse.EquipItems[i]; - - if (item.Movable && item.Layer != Layer.Hair && item.Layer != Layer.FacialHair && - item.IsChildOf(mob.Backpack)) - mob.EquipItem(item); - } - } - - mob.Hits = mob.HitsMax; - mob.Stam = mob.StamMax; - mob.Mana = mob.ManaMax; - - mob.Poison = null; - } - - public void SendOutside(Mobile mob) - { - if (Arena == null) - return; - - mob.Combatant = null; - mob.MoveToWorld(Arena.Outside, Arena.Facet); - } - - public void Finish(Participant winner) - { - if (Finished) - return; - - EndAutoTie(); - StopSDTimers(); - - Finished = true; - - for (int i = 0; i < winner.Players.Length; ++i) - { - DuelPlayer pl = winner.Players[i]; - - if (pl?.Eliminated == false) - DelayBounce(TimeSpan.FromSeconds(8.0), pl.Mobile, null); - } - - winner.Broadcast(0x59, null, - winner.Players.Length == 1 ? "{0} has won the duel." : "{0} and {1} team have won the duel.", - winner.Players.Length == 1 ? "You have won the duel." : "Your team has won the duel."); - - if (m_Tournament != null && winner.TourneyPart != null) - { - m_Match.Winner = winner.TourneyPart; - winner.TourneyPart.WonMatch(m_Match); - m_Tournament.HandleWon(Arena, m_Match, winner.TourneyPart); - } - - for (int i = 0; i < Participants.Count; ++i) - { - Participant loser = Participants[i]; - - if (loser != winner) - { - loser.Broadcast(0x22, null, - loser.Players.Length == 1 ? "{0} has lost the duel." : "{0} and {1} team have lost the duel.", - loser.Players.Length == 1 ? "You have lost the duel." : "Your team has lost the duel."); - - if (m_Tournament != null) - loser.TourneyPart?.LostMatch(m_Match); - } - - for (int j = 0; j < loser.Players.Length; ++j) - if (loser.Players[j] != null) - { - RemoveAggressions(loser.Players[j].Mobile); - loser.Players[j].Mobile.Delta(MobileDelta.Noto); - loser.Players[j].Mobile.CloseGump(); - - if (m_Tournament != null) - loser.Players[j].Mobile.SendEverything(); - } - } - - if (IsOneVsOne) - { - DuelPlayer dp1 = Participants[0].Players[0]; - DuelPlayer dp2 = Participants[1].Players[0]; - - if (dp1 != null && dp2 != null) - { - Award(dp1.Mobile, dp2.Mobile, dp1.Participant == winner); - Award(dp2.Mobile, dp1.Mobile, dp2.Participant == winner); - } - } - - m_EventGame?.OnStop(); - - Timer.DelayCall(TimeSpan.FromSeconds(9.0), UnregisterRematch); - } - - public void Award(Mobile us, Mobile them, bool won) - { - Ladder ladder = Arena == null ? Ladder.Instance : Arena.AcquireLadder(); - - if (ladder == null) - return; - - LadderEntry ourEntry = ladder.Find(us); - LadderEntry theirEntry = ladder.Find(them); - - if (ourEntry == null || theirEntry == null) - return; - - int xpGain = Ladder.GetExperienceGain(ourEntry, theirEntry, won); - - if (xpGain == 0) - return; - - if (m_Tournament != null) - xpGain *= xpGain > 0 ? 5 : 2; - - if (won) - ++ourEntry.Wins; - else - ++ourEntry.Losses; - - int oldLevel = Ladder.GetLevel(ourEntry.Experience); - - ourEntry.Experience += xpGain; - - if (ourEntry.Experience < 0) - ourEntry.Experience = 0; - - ladder.UpdateEntry(ourEntry); - - int newLevel = Ladder.GetLevel(ourEntry.Experience); - - if (newLevel > oldLevel) - us.SendMessage(0x59, "You have achieved level {0}!", newLevel); - else if (newLevel < oldLevel) - us.SendMessage(0x22, "You have lost a level. You are now at {0}.", newLevel); - } - - public void UnregisterRematch() - { - Unregister(true); - } - - public void Unregister() - { - Unregister(false); - } - - public void Unregister(bool queryRematch) - { - DestroyWall(); - - if (!Registered) - return; - - Registered = false; - - Arena?.Evict(); - - StopSDTimers(); - - for (int i = 0; i < Participants.Count; ++i) - { - Participant p = Participants[i]; - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer pl = p.Players[j]; - - if (pl == null) - continue; - - if (pl.Mobile is PlayerMobile mobile) - mobile.DuelPlayer = null; - - CloseAllGumps(pl); - } - } - - if (queryRematch && m_Tournament == null) - QueryRematch(); - } - - public void QueryRematch() - { - DuelContext dc = new DuelContext(Initiator, Ruleset.Layout, false); - - dc.Ruleset = Ruleset; - dc.Rematch = true; - - dc.Participants.Clear(); - - for (int i = 0; i < Participants.Count; ++i) - { - Participant oldPart = Participants[i]; - Participant newPart = new Participant(dc, oldPart.Players.Length); - - for (int j = 0; j < oldPart.Players.Length; ++j) - { - DuelPlayer oldPlayer = oldPart.Players[j]; - - if (oldPlayer != null) - newPart.Players[j] = new DuelPlayer(oldPlayer.Mobile, newPart); - } - - dc.Participants.Add(newPart); - } - - dc.CloseAllGumps(); - dc.SendReadyUpGump(); - } - - public DuelPlayer Find(Mobile mob) - { - if (mob is PlayerMobile pm) - { - if (pm.DuelContext == this) - return pm.DuelPlayer; - - return null; - } - - for (int i = 0; i < Participants.Count; ++i) - { - Participant p = Participants[i]; - DuelPlayer pl = p.Find(mob); - - if (pl != null) - return pl; - } - - return null; - } - - public bool IsAlly(Mobile m1, Mobile m2) - { - DuelPlayer pl1 = Find(m1); - DuelPlayer pl2 = Find(m2); - - return pl1 != null && pl1.Participant == pl2?.Participant; - } - - public Participant CheckCompletion() - { - Participant winner = null; - - bool hasWinner = false; - int eliminated = 0; - - for (int i = 0; i < Participants.Count; ++i) - { - Participant p = Participants[i]; - - if (p.Eliminated) - { - ++eliminated; - - if (eliminated == Participants.Count - 1) - hasWinner = true; - } - else - { - winner = p; - } - } - - return hasWinner ? winner ?? Participants[0] : null; - } - - public void StartCountdown(int count, CountdownCallback cb) - { - cb(count); - m_Countdown = Timer.DelayCall(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0), count, - () => Countdown_Callback(--count, cb)); - } - - public void StopCountdown() - { - m_Countdown?.Stop(); - m_Countdown = null; - } - - private void Countdown_Callback(int count, CountdownCallback cb) - { - if (count == 0) - StopCountdown(); - - cb(count); - } - - public void StopSDTimers() - { - m_SDWarnTimer?.Stop(); - - m_SDWarnTimer = null; - - m_SDActivateTimer?.Stop(); - - m_SDActivateTimer = null; - } - - public void StartSuddenDeath(TimeSpan timeUntilActive) - { - m_SDWarnTimer?.Stop(); - - m_SDWarnTimer = Timer.DelayCall(TimeSpan.FromMinutes(timeUntilActive.TotalMinutes * 0.9), WarnSuddenDeath); - - m_SDActivateTimer?.Stop(); - - m_SDActivateTimer = Timer.DelayCall(timeUntilActive, ActivateSuddenDeath); - } - - public void WarnSuddenDeath() - { - for (int i = 0; i < Participants.Count; ++i) - { - Participant p = Participants[i]; - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer pl = p.Players[j]; - - if (pl?.Eliminated != false) - continue; - - pl.Mobile.SendSound(0x1E1); - pl.Mobile.SendMessage(0x22, "Warning! Warning! Warning!"); - pl.Mobile.SendMessage(0x22, "Sudden death will be active soon!"); - } - } - - m_Tournament?.Alert(Arena, "Sudden death will be active soon!"); - - m_SDWarnTimer?.Stop(); - - m_SDWarnTimer = null; - } - - public static bool CheckSuddenDeath(Mobile mob) => mob is PlayerMobile pm && pm.DuelPlayer?.Eliminated == false && pm.DuelContext?.IsSuddenDeath == true; - - public void ActivateSuddenDeath() - { - for (int i = 0; i < Participants.Count; ++i) - { - Participant p = Participants[i]; - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer pl = p.Players[j]; - - if (pl?.Eliminated != false) - continue; - - pl.Mobile.SendSound(0x1E1); - pl.Mobile.SendMessage(0x22, "Warning! Warning! Warning!"); - pl.Mobile.SendMessage(0x22, - "Sudden death has ACTIVATED. You are now unable to perform any beneficial actions."); - } - } - - m_Tournament?.Alert(Arena, "Sudden death has been activated!"); - - IsSuddenDeath = true; - - m_SDActivateTimer?.Stop(); - - m_SDActivateTimer = null; - } - - public void BeginAutoTie() - { - m_AutoTieTimer?.Stop(); - - TimeSpan ts = m_Tournament == null || m_Tournament.TourneyType == TourneyType.Standard - ? AutoTieDelay - : TimeSpan.FromMinutes(90.0); - - m_AutoTieTimer = Timer.DelayCall(ts, InvokeAutoTie); - } - - public void EndAutoTie() - { - m_AutoTieTimer?.Stop(); - - m_AutoTieTimer = null; - } - - public void InvokeAutoTie() - { - m_AutoTieTimer = null; - - if (!Started || Finished) - return; - - Tied = true; - Finished = true; - - StopSDTimers(); - - List remaining = new List(); - - for (int i = 0; i < Participants.Count; ++i) - { - Participant p = Participants[i]; - - if (p.Eliminated) - { - p.Broadcast(0x22, null, - p.Players.Length == 1 ? "{0} has lost the duel." : "{0} and {1} team have lost the duel.", - p.Players.Length == 1 ? "You have lost the duel." : "Your team has lost the duel."); - } - else - { - p.Broadcast(0x59, null, - p.Players.Length == 1 - ? "{0} has tied the duel due to time expiration." - : "{0} and {1} team have tied the duel due to time expiration.", - p.Players.Length == 1 - ? "You have tied the duel due to time expiration." - : "Your team has tied the duel due to time expiration."); - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer pl = p.Players[j]; - - if (pl?.Eliminated == false) - DelayBounce(TimeSpan.FromSeconds(8.0), pl.Mobile, null); - } - - if (p.TourneyPart != null) - remaining.Add(p.TourneyPart); - } - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer pl = p.Players[j]; - - if (pl != null) - { - pl.Mobile.Delta(MobileDelta.Noto); - pl.Mobile.SendEverything(); - } - } - } - - m_Tournament?.HandleTie(Arena, m_Match, remaining); - - Timer.DelayCall(TimeSpan.FromSeconds(10.0), Unregister); - } - - public static void Initialize() - { - EventSink.Speech += EventSink_Speech; - EventSink.Login += EventSink_Login; - - CommandSystem.Register("vli", AccessLevel.GameMaster, vli_oc); - } - - private static void vli_oc(CommandEventArgs e) - { - e.Mobile.BeginTarget(-1, false, TargetFlags.None, vli_ot); - } - - private static void vli_ot(Mobile from, object obj) - { - if (obj is PlayerMobile pm) - { - Ladder ladder = Ladder.Instance; - - if (ladder == null) - return; - - LadderEntry entry = ladder.Find(pm); - - if (entry != null) - from.SendGump(new PropertiesGump(from, entry)); - } - } - - public static bool CheckCombat(Mobile m) => - m.Aggressed.Any(info => info.Defender.Player && DateTime.UtcNow - info.LastCombatTime < CombatDelay) || - m.Aggressors.Any(info => info.Attacker.Player && DateTime.UtcNow - info.LastCombatTime < CombatDelay); - - private static void EventSink_Login(Mobile m) - { - if (!(m is PlayerMobile pm)) - return; - - DuelContext dc = pm.DuelContext; - - if (dc == null) - return; - - if (dc.ReadyWait && pm.DuelPlayer.Ready && !dc.Started && !dc.StartedBeginCountdown && !dc.Finished) - { - if (dc.m_Tournament == null) - pm.SendGump(new ReadyGump(pm, dc, dc.ReadyCount)); - } - else if (dc.ReadyWait && !dc.StartedBeginCountdown && !dc.Started && !dc.Finished) - { - if (dc.m_Tournament == null) - pm.SendGump(new ReadyUpGump(pm, dc)); - } - else if (dc.Initiator == pm && !dc.ReadyWait && !dc.StartedBeginCountdown && !dc.Started && !dc.Finished) - { - pm.SendGump(new DuelContextGump(pm, dc)); - } - } - - private static void ViewLadder_OnTarget(Mobile from, object obj, Ladder ladder) - { - if (obj is PlayerMobile pm) - { - LadderEntry entry = ladder.Find(pm); - - if (entry == null) - return; // sanity - - string text = - $"{{0}} are ranked {LadderGump.Rank(entry.Index + 1)} at level {Ladder.GetLevel(entry.Experience)}."; - - pm.PrivateOverheadMessage(MessageType.Regular, pm.SpeechHue, true, - string.Format(text, from == pm ? "You" : "They"), from.NetState); - } - else if (obj is Mobile mob) - { - if (mob.Body.IsHuman) - mob.PrivateOverheadMessage(MessageType.Regular, mob.SpeechHue, false, - "I'm not a duelist, and quite frankly, I resent the implication.", from.NetState); - else - mob.PrivateOverheadMessage(MessageType.Regular, 0x3B2, true, "It's probably better than you.", - from.NetState); - } - else - { - from.SendMessage("That's not a player."); - } - } - - private static void EventSink_Speech(SpeechEventArgs e) - { - if (e.Handled) - return; - - if (!(e.Mobile is PlayerMobile pm)) - return; - - if (Insensitive.Contains(e.Speech, "i wish to duel")) - { - if (!pm.CheckAlive()) - { - } - else if (pm.Region.IsPartOf()) - { - } - else if (CheckCombat(pm)) - { - e.Mobile.SendMessage(0x22, - "You have recently been in combat with another player and must wait before starting a duel."); - } - else if (pm.DuelContext != null) - { - if (pm.DuelContext.Initiator == pm) - e.Mobile.SendMessage(0x22, "You have already started a duel."); - else - e.Mobile.SendMessage(0x22, "You have already been challenged in a duel."); - } - else if (TournamentController.IsActive) - { - e.Mobile.SendMessage(0x22, "You may not start a duel while a tournament is active."); - } - else - { - pm.SendGump(new DuelContextGump(pm, new DuelContext(pm, RulesetLayout.Root))); - e.Handled = true; - } - } - else if (Insensitive.Equals(e.Speech, "change arena preferences")) - { - if (!pm.CheckAlive()) - { - } - else - { - Preferences prefs = Preferences.Instance; - - if (prefs != null) - { - e.Mobile.CloseGump(); - e.Mobile.SendGump(new PreferencesGump(e.Mobile, prefs)); - } - } - } - else if (Insensitive.Equals(e.Speech, "showladder")) - { - e.Blocked = true; - if (!pm.CheckAlive()) - { - } - else - { - Ladder instance = Ladder.Instance; - - if (instance == null) - { - // pm.SendMessage( "Ladder not yet initialized." ); - } - else - { - LadderEntry entry = instance.Find(pm); - - if (entry == null) - return; // sanity - - string text = - $"{{0}} {{1}} ranked {LadderGump.Rank(entry.Index + 1)} at level {Ladder.GetLevel(entry.Experience)}."; - - pm.LocalOverheadMessage(MessageType.Regular, pm.SpeechHue, true, string.Format(text, "You", "are")); - pm.NonlocalOverheadMessage(MessageType.Regular, pm.SpeechHue, true, - string.Format(text, pm.Name, "is")); - - // pm.PublicOverheadMessage( MessageType.Regular, pm.SpeechHue, true, String.Format( "Level {0} with {1} win{2} and {3} loss{4}.", Ladder.GetLevel( entry.Experience ), entry.Wins, entry.Wins==1?"":"s", entry.Losses, entry.Losses==1?"":"es" ) ); - // pm.PublicOverheadMessage( MessageType.Regular, pm.SpeechHue, true, String.Format( "Level {0} with {1} win{2} and {3} loss{4}.", Ladder.GetLevel( entry.Experience ), entry.Wins, entry.Wins==1?"":"s", entry.Losses, entry.Losses==1?"":"es" ) ); - } - } - } - else if (Insensitive.Equals(e.Speech, "viewladder")) - { - e.Blocked = true; - - if (!pm.CheckAlive()) - { - } - else - { - Ladder instance = Ladder.Instance; - - if (instance == null) - { - // pm.SendMessage( "Ladder not yet initialized." ); - } - else - { - pm.SendMessage("Target a player to view their ranking and level."); - pm.BeginTarget(16, false, TargetFlags.None, ViewLadder_OnTarget, instance); - } - } - } - else if (Insensitive.Contains(e.Speech, "i yield")) - { - if (!pm.CheckAlive()) - { - } - else if (pm.DuelContext == null) - { - } - else if (pm.DuelContext.Finished) - { - e.Mobile.SendMessage(0x22, "The duel is already finished."); - } - else if (!pm.DuelContext.Started) - { - DuelContext dc = pm.DuelContext; - Mobile init = dc.Initiator; - - if (pm.DuelContext.StartedBeginCountdown) - { - e.Mobile.SendMessage(0x22, "The duel has not yet started."); - } - else - { - DuelPlayer pl = pm.DuelContext.Find(pm); - - if (pl == null) - return; - - Participant p = pl.Participant; - - if (!pm.DuelContext.ReadyWait) // still setting stuff up - { - p.Broadcast(0x22, null, "{0} has yielded.", "You have yielded."); - - if (init == pm) - { - dc.Unregister(); - } - else - { - p.Nullify(pl); - pm.DuelPlayer = null; - - NetState ns = init.NetState; - - if (ns != null) - foreach (Gump g in ns.Gumps) - { - if (g is ParticipantGump pg && pg.Participant == p) - { - init.SendGump(new ParticipantGump(init, dc, p)); - break; - } - - if (g is DuelContextGump dcg && dcg.Context == dc) - { - init.SendGump(new DuelContextGump(init, dc)); - break; - } - } - } - } - else if (!pm.DuelContext.StartedReadyCountdown) // at ready stage - { - p.Broadcast(0x22, null, "{0} has yielded.", "You have yielded."); - - dc.m_Yielding = true; - dc.RejectReady(pm, null); - dc.m_Yielding = false; - - if (init == pm) - { - dc.Unregister(); - } - else if (dc.Registered) - { - p.Nullify(pl); - pm.DuelPlayer = null; - - NetState ns = init.NetState; - - if (ns != null) - { - bool send = true; - - foreach (Gump g in ns.Gumps) - { - if (g is ParticipantGump pg && pg.Participant == p) - { - init.SendGump(new ParticipantGump(init, dc, p)); - send = false; - break; - } - - if (g is DuelContextGump dcg && dcg.Context == dc) - { - init.SendGump(new DuelContextGump(init, dc)); - send = false; - break; - } - } - - if (send) - init.SendGump(new DuelContextGump(init, dc)); - } - } - } - else - { - pm.DuelContext.m_Countdown?.Stop(); - pm.DuelContext.m_Countdown = null; - - pm.DuelContext.StartedReadyCountdown = false; - p.Broadcast(0x22, null, "{0} has yielded.", "You have yielded."); - - dc.m_Yielding = true; - dc.RejectReady(pm, null); - dc.m_Yielding = false; - - if (init == pm) - { - dc.Unregister(); - } - else if (dc.Registered) - { - p.Nullify(pl); - pm.DuelPlayer = null; - - NetState ns = init.NetState; - - if (ns != null) - { - bool send = true; - - foreach (Gump g in ns.Gumps) - { - if (g is ParticipantGump pg && pg.Participant == p) - { - init.SendGump(new ParticipantGump(init, dc, p)); - send = false; - break; - } - - if (g is DuelContextGump dcg && dcg.Context == dc) - { - init.SendGump(new DuelContextGump(init, dc)); - send = false; - break; - } - } - - if (send) - init.SendGump(new DuelContextGump(init, dc)); - } - } - } - } - } - else - { - DuelPlayer pl = pm.DuelContext.Find(pm); - - if (pl != null) - { - if (pm.DuelContext.IsOneVsOne) - { - e.Mobile.SendMessage(0x22, "You may not yield a 1 on 1 match."); - } - else if (pl.Eliminated) - { - e.Mobile.SendMessage(0x22, "You have already been eliminated."); - } - else - { - pm.LocalOverheadMessage(MessageType.Regular, 0x22, false, "You have yielded."); - pm.NonlocalOverheadMessage(MessageType.Regular, 0x22, false, $"{pm.Name} has yielded."); - - pm.DuelContext.m_Yielding = true; - pm.Kill(); - pm.DuelContext.m_Yielding = false; - - if (pm.Alive) // invul, ... - { - pl.Eliminated = true; - - pm.DuelContext.RemoveAggressions(pm); - pm.DuelContext.SendOutside(pm); - pm.DuelContext.Refresh(pm, null); - Debuff(pm); - CancelSpell(pm); - pm.Frozen = false; - - Participant winner = pm.DuelContext.CheckCompletion(); - - if (winner != null) - pm.DuelContext.Finish(winner); - } - } - } - else - { - e.Mobile.SendMessage(0x22, "BUG: Unable to find duel context."); - } - } - } - } - - public void CloseAllGumps(DuelPlayer pl) - { - pl.Mobile.CloseGump(); - pl.Mobile.CloseGump(); - pl.Mobile.CloseGump(); - pl.Mobile.CloseGump(); - pl.Mobile.CloseGump(); - pl.Mobile.CloseGump(); - pl.Mobile.CloseGump(); - } - - public void CloseAllGumps() - { - for (int i = 0; i < Participants.Count; ++i) - { - Participant p = Participants[i]; - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer pl = p.Players[j]; - - if (pl != null) - CloseAllGumps(pl); - } - } - } - - public void RejectReady(Mobile rejector, string page) - { - if (StartedReadyCountdown) - return; // sanity - - for (int i = 0; i < Participants.Count; ++i) - { - Participant p = Participants[i]; - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer pl = p.Players[j]; - - if (pl == null) - continue; - - pl.Ready = false; - - Mobile mob = pl.Mobile; - - if (page == null) // yield - { - if (mob != rejector) - mob.SendMessage(0x22, "{0} has yielded.", rejector.Name); - } - else - { - if (mob == rejector) - mob.SendMessage(0x22, "You have rejected the {0}.", Rematch ? "rematch" : page); - else - mob.SendMessage(0x22, "{0} has rejected the {1}.", rejector.Name, Rematch ? "rematch" : page); - } - - // Close all of them? - mob.CloseGump(); - mob.CloseGump(); - mob.CloseGump(); - } - } - - if (Rematch) - Unregister(); - else if (!m_Yielding) - Initiator.SendGump(new DuelContextGump(Initiator, this)); - - ReadyWait = false; - ReadyCount = 0; - } - - public void SendReadyGump() - { - SendReadyGump(-1); - } - - public static void Debuff(Mobile mob) - { - mob.RemoveStatMod("[Magic] Str Offset"); - mob.RemoveStatMod("[Magic] Dex Offset"); - mob.RemoveStatMod("[Magic] Int Offset"); - mob.RemoveStatMod("Concussion"); - mob.RemoveStatMod("blood-rose"); - mob.RemoveStatMod("clarity-potion"); - - OrangePetals.RemoveContext(mob); - - mob.Paralyzed = false; - mob.Hidden = false; - - if (!Core.AOS) - { - mob.MagicDamageAbsorb = 0; - mob.MeleeDamageAbsorb = 0; - ProtectionSpell.Registry.Remove(mob); - - ArchProtectionSpell.RemoveEntry(mob); - - mob.EndAction(); - } - - TransformationSpellHelper.RemoveContext(mob, true); - AnimalForm.RemoveContext(mob, true); - - if (DisguiseTimers.IsDisguised(mob)) - DisguiseTimers.StopTimer(mob); - - if (!mob.CanBeginAction()) - { - mob.BodyMod = 0; - mob.HueMod = -1; - mob.EndAction(); - } - - BaseArmor.ValidateMobile(mob); - BaseClothing.ValidateMobile(mob); - - mob.Hits = mob.HitsMax; - mob.Stam = mob.StamMax; - mob.Mana = mob.ManaMax; - - mob.Poison = null; - } - - public static void CancelSpell(Mobile mob) - { - if (mob.Spell is Spell spell) - spell.Disturb(DisturbType.Kill); - - Target.Cancel(mob); - } - - public void DestroyWall() - { - for (int i = 0; i < m_Walls.Count; ++i) - m_Walls[i].Delete(); - - m_Walls.Clear(); - } - - public void CreateWall() - { - if (Arena == null) - return; - - Point3D start = Arena.Points.EdgeWest; - Point3D wall = Arena.Wall; - - int dx = start.X - wall.X; - int dy = start.Y - wall.Y; - int rx = dx - dy; - int ry = dx + dy; - - bool eastToWest; - - if (rx >= 0 && ry >= 0) - eastToWest = false; - else if (rx >= 0) - eastToWest = true; - else if (ry >= 0) - eastToWest = true; - else - eastToWest = false; - - Effects.PlaySound(wall, Arena.Facet, 0x1F6); - - for (int i = -1; i <= 1; ++i) - { - Point3D loc = new Point3D(eastToWest ? wall.X + i : wall.X, eastToWest ? wall.Y : wall.Y + i, wall.Z); - - InternalWall created = new InternalWall(); - - created.Appear(loc, Arena.Facet); - - m_Walls.Add(created); - } - } - - public void BuildParties() - { - for (int i = 0; i < Participants.Count; ++i) - { - Participant p = Participants[i]; - - if (p.Players.Length > 1) - { - List players = new List(); - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer dp = p.Players[j]; - - if (dp == null) - continue; - - players.Add(dp.Mobile); - } - - if (players.Count > 1) - for (int leaderIndex = 0; leaderIndex + 1 < players.Count; leaderIndex += Party.Capacity) - { - Mobile leader = players[leaderIndex]; - Party party = Party.Get(leader); - - if (party == null) - { - leader.Party = party = new Party(leader); - } - else if (party.Leader != leader) - { - party.SendPublicMessage(leader, "I leave this party to fight in a duel."); - party.Remove(leader); - leader.Party = party = new Party(leader); - } - - for (int j = leaderIndex + 1; j < players.Count && j < leaderIndex + Party.Capacity; ++j) - { - Mobile player = players[j]; - Party existing = Party.Get(player); - - if (existing == party) - continue; - - if (party.Members.Count + party.Candidates.Count >= Party.Capacity) - { - player.SendMessage( - "You could not be added to the team party because it is at full capacity."); - leader.SendMessage( - "{0} could not be added to the team party because it is at full capacity."); - } - else - { - if (existing != null) - { - existing.SendPublicMessage(player, "I leave this party to fight in a duel."); - existing.Remove(player); - } - - party.OnAccept(player, true); - } - } - } - } - } - } - - public void ClearIllegalItems() - { - for (int i = 0; i < Participants.Count; ++i) - { - Participant p = Participants[i]; - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer pl = p.Players[j]; - - if (pl == null) - continue; - - ClearIllegalItems(pl.Mobile); - } - } - } - - public void ClearIllegalItems(Mobile mob) - { - if (mob.StunReady && !AllowSpecialAbility(mob, "Stun", false)) - mob.StunReady = false; - - if (mob.DisarmReady && !AllowSpecialAbility(mob, "Disarm", false)) - mob.DisarmReady = false; - - Container pack = mob.Backpack; - - if (pack == null) - return; - - for (int i = mob.Items.Count - 1; i >= 0; --i) - { - if (i >= mob.Items.Count) - continue; // sanity - - Item item = mob.Items[i]; - - if (!CheckItemEquip(mob, item)) - { - pack.DropItem(item); - - if (item is BaseWeapon) - mob.SendLocalizedMessage(1062001, - item.Name ?? $"#{item.LabelNumber}"); // You can no longer wield your ~1_WEAPON~ - else if (item is BaseArmor && !(item is BaseShield)) - mob.SendLocalizedMessage(1062002, - item.Name ?? $"#{item.LabelNumber}"); // You can no longer wear your ~1_ARMOR~ - else - mob.SendLocalizedMessage(1062003, - item.Name ?? $"#{item.LabelNumber}"); // You can no longer equip your ~1_SHIELD~ - } - } - - Item inHand = mob.Holding; - - if (inHand != null && !CheckItemEquip(mob, inHand)) - { - mob.Holding = null; - - BounceInfo bi = inHand.GetBounce(); - - if (bi.Parent == mob) - pack.DropItem(inHand); - else - inHand.Bounce(mob); - - inHand.ClearBounce(); - } - } - - private void MessageRuleset(Mobile mob) - { - if (Ruleset == null) return; - - Ruleset ruleset = Ruleset; - Ruleset basedef = ruleset.Base; - - mob.SendMessage("Ruleset: {0}", basedef.Title); - - BitArray defs; - - if (ruleset.Flavors.Count > 0) - { - defs = new BitArray(basedef.Options); - - for (int i = 0; i < ruleset.Flavors.Count; ++i) - { - defs.Or(ruleset.Flavors[i].Options); - - mob.SendMessage(" + {0}", ruleset.Flavors[i].Title); - } - } - else - { - defs = basedef.Options; - } - - int changes = 0; - - BitArray opts = ruleset.Options; - - for (int i = 0; i < opts.Length; ++i) - if (defs[i] != opts[i]) - { - string name = ruleset.Layout.FindByIndex(i); - - if (name != null) // sanity - { - ++changes; - - if (changes == 1) mob.SendMessage("Modifications:"); - - mob.SendMessage("{0}: {1}", name, opts[i] ? "enabled" : "disabled"); - } - } - } - - public void SendBeginGump(int count) - { - if (!Registered || Finished) - return; - - if (count == 10) - { - CreateWall(); - BuildParties(); - ClearIllegalItems(); - } - else if (count == 0) - { - DestroyWall(); - } - - StartedBeginCountdown = true; - - if (count == 0) - { - Started = true; - BeginAutoTie(); - } - - for (int i = 0; i < Participants.Count; ++i) - { - Participant p = Participants[i]; - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer pl = p.Players[j]; - - if (pl == null) - continue; - - Mobile mob = pl.Mobile; - - if (count > 0) - { - if (count == 10) - { - mob.CloseGump(); - mob.CloseGump(); - mob.CloseGump(); - mob.SendGump(new BeginGump(count)); - } - - mob.Frozen = true; - } - else - { - mob.CloseGump(); - mob.Frozen = false; - } - } - } - } - - public void RemoveAggressions(Mobile mob) - { - for (int i = 0; i < Participants.Count; ++i) - { - Participant p = Participants[i]; - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer dp = p.Players[j]; - - if (dp == null || dp.Mobile == mob) - continue; - - mob.RemoveAggressed(dp.Mobile); - mob.RemoveAggressor(dp.Mobile); - dp.Mobile.RemoveAggressed(mob); - dp.Mobile.RemoveAggressor(mob); - } - } - } - - public void SendReadyUpGump() - { - if (!Registered) - return; - - ReadyWait = true; - ReadyCount = -1; - - for (int i = 0; i < Participants.Count; ++i) - { - Participant p = Participants[i]; - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer pl = p.Players[j]; - - Mobile mob = pl?.Mobile; - - if (mob != null && m_Tournament == null) - { - mob.CloseGump(); - mob.SendGump(new ReadyUpGump(mob, this)); - } - } - } - } - - public string ValidateStart() - { - if (m_Tournament == null && TournamentController.IsActive) - return "a tournament is active"; - - for (int i = 0; i < Participants.Count; ++i) - { - Participant p = Participants[i]; - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer dp = p.Players[j]; - - if (dp == null) - return "a slot is empty"; - - if (dp.Mobile.Region.IsPartOf()) - return $"{dp.Mobile.Name} is in jail"; - - if (Sigil.ExistsOn(dp.Mobile)) - return $"{dp.Mobile.Name} is holding a sigil"; - - if (!dp.Mobile.Alive) - { - if (m_Tournament == null) - return $"{dp.Mobile.Name} is dead"; - dp.Mobile.Resurrect(); - } - - if (m_Tournament == null && CheckCombat(dp.Mobile)) - return $"{dp.Mobile.Name} is in combat"; - - if (dp.Mobile.Mounted) - { - IMount mount = dp.Mobile.Mount; - - if (m_Tournament != null && mount != null) - mount.Rider = null; - else - return $"{dp.Mobile.Name} is mounted"; - } - } - } - - return null; - } - - public void SendReadyGump(int count) - { - if (!Registered) - return; - - if (count != -1) - StartedReadyCountdown = true; - - ReadyCount = count; - - if (count == 0) - { - string error = ValidateStart(); - - if (error != null) - { - for (int i = 0; i < Participants.Count; ++i) - { - Participant p = Participants[i]; - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer dp = p.Players[j]; - - dp?.Mobile.SendMessage("The duel could not be started because {0}.", error); - } - } - - StartCountdown(10, SendReadyGump); - - return; - } - - ReadyWait = false; - - List players = new List(); - - for (int i = 0; i < Participants.Count; ++i) - { - Participant p = Participants[i]; - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer dp = p.Players[j]; - - if (dp != null) - players.Add(dp.Mobile); - } - } - - Arena arena = m_OverrideArena ?? Arena.FindArena(players); - - if (arena == null) - { - for (int i = 0; i < Participants.Count; ++i) - { - Participant p = Participants[i]; - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer dp = p.Players[j]; - - dp?.Mobile.SendMessage( - "The duel could not be started because there are no arenas. If you want to stop waiting for a free arena, yield the duel."); - } - } - - StartCountdown(10, SendReadyGump); - return; - } - - if (!arena.IsOccupied) - { - Arena = arena; - - if (Initiator.Map == Map.Internal) - { - m_GatePoint = Initiator.LogoutLocation; - m_GateFacet = Initiator.LogoutMap; - } - else - { - m_GatePoint = Initiator.Location; - m_GateFacet = Initiator.Map; - } - - if (!(arena.Teleporter is ExitTeleporter tp)) - { - arena.Teleporter = tp = new ExitTeleporter(); - tp.MoveToWorld(arena.GateOut == Point3D.Zero ? arena.Outside : arena.GateOut, arena.Facet); - } - - ArenaMoongate mg = new ArenaMoongate(arena.GateIn == Point3D.Zero ? arena.Outside : arena.GateIn, - arena.Facet, tp); - - StartedBeginCountdown = true; - - for (int i = 0; i < Participants.Count; ++i) - { - Participant p = Participants[i]; - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer pl = p.Players[j]; - - if (pl == null) - continue; - - tp.Register(pl.Mobile); - - pl.Mobile.Frozen = false; // reset timer just in case - pl.Mobile.Frozen = true; - - Debuff(pl.Mobile); - CancelSpell(pl.Mobile); - - pl.Mobile.Delta(MobileDelta.Noto); - } - - arena.MoveInside(p.Players, i); - } - - m_EventGame?.OnStart(); - - StartCountdown(10, SendBeginGump); - - mg.Appear(m_GatePoint, m_GateFacet); - } - else - { - for (int i = 0; i < Participants.Count; ++i) - { - Participant p = Participants[i]; - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer dp = p.Players[j]; - - dp?.Mobile.SendMessage( - "The duel could not be started because all arenas are full. If you want to stop waiting for a free arena, yield the duel."); - } - } - - StartCountdown(10, SendReadyGump); - } - - return; - } - - ReadyWait = true; - - bool isAllReady = true; - - for (int i = 0; i < Participants.Count; ++i) - { - Participant p = Participants[i]; - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer pl = p.Players[j]; - - if (pl == null) - continue; - - Mobile mob = pl.Mobile; - - if (pl.Ready) - { - if (m_Tournament == null) - { - mob.CloseGump(); - mob.SendGump(new ReadyGump(mob, this, count)); - } - } - else - { - isAllReady = false; - } - } - } - - if (count == -1 && isAllReady) - StartCountdown(3, SendReadyGump); - } - - private class InternalWall : Item - { - public InternalWall() : base(0x80) => Movable = false; - - public InternalWall(Serial serial) : base(serial) - { - } - - public void Appear(Point3D loc, Map map) - { - MoveToWorld(loc, map); - - Effects.SendLocationParticles(this, 0x376A, 9, 10, 5025); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Delete(); - } - } - - private class ReturnEntry - { - private DateTime m_Expire; - - public ReturnEntry(Mobile mob) - { - Mobile = mob; - - Update(); - } - - public ReturnEntry(Mobile mob, Point3D loc, Map facet) - { - Mobile = mob; - Location = loc; - Facet = facet; - m_Expire = DateTime.UtcNow + TimeSpan.FromMinutes(30.0); - } - - public Mobile Mobile { get; } - - public Point3D Location { get; private set; } - - public Map Facet { get; private set; } - - public bool Expired => DateTime.UtcNow >= m_Expire; - - public void Return() - { - if (Facet == Map.Internal || Facet == null) - return; - - if (Mobile.Map == Map.Internal) - { - Mobile.LogoutLocation = Location; - Mobile.LogoutMap = Facet; - } - else - { - Mobile.Location = Location; - Mobile.Map = Facet; - } - } - - public void Update() - { - m_Expire = DateTime.UtcNow + TimeSpan.FromMinutes(30.0); - - if (Mobile.Map == Map.Internal) - { - Facet = Mobile.LogoutMap; - Location = Mobile.LogoutLocation; - } - else - { - Facet = Mobile.Map; - Location = Mobile.Location; - } - } - } - - private class ExitTeleporter : Item - { - private List m_Entries; - - public ExitTeleporter() : base(0x1822) - { - m_Entries = new List(); - - Hue = 0x482; - Movable = false; - } - - public ExitTeleporter(Serial serial) : base(serial) - { - } - - public override string DefaultName => "return teleporter"; - - public void Register(Mobile mob) - { - ReturnEntry entry = Find(mob); - - if (entry != null) - { - entry.Update(); - return; - } - - m_Entries.Add(new ReturnEntry(mob)); - } - - private ReturnEntry Find(Mobile mob) - { - for (int i = 0; i < m_Entries.Count; ++i) - { - ReturnEntry entry = m_Entries[i]; - - if (entry.Mobile == mob) - return entry; - if (entry.Expired) - m_Entries.RemoveAt(i--); - } - - return null; - } - - public override bool OnMoveOver(Mobile m) - { - if (!base.OnMoveOver(m)) - return false; - - ReturnEntry entry = Find(m); - - if (entry != null) - { - entry.Return(); - - Effects.PlaySound(GetWorldLocation(), Map, 0x1FE); - Effects.PlaySound(m.Location, m.Map, 0x1FE); - - m_Entries.Remove(entry); - - return false; - } - - m.SendLocalizedMessage(1049383); // The teleporter doesn't seem to work for you. - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.WriteEncodedInt(m_Entries.Count); - - for (int i = 0; i < m_Entries.Count; ++i) - { - ReturnEntry entry = m_Entries[i]; - - writer.Write(entry.Mobile); - writer.Write(entry.Location); - writer.Write(entry.Facet); - - if (entry.Expired) - m_Entries.RemoveAt(i--); - } - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - int count = reader.ReadEncodedInt(); - - m_Entries = new List(count); - - for (int i = 0; i < count; ++i) - { - Mobile mob = reader.ReadMobile(); - Point3D loc = reader.ReadPoint3D(); - Map map = reader.ReadMap(); - - m_Entries.Add(new ReturnEntry(mob, loc, map)); - } - - break; - } - } - } - } - - private class ArenaMoongate : ConfirmationMoongate - { - private readonly ExitTeleporter m_Teleporter; - - public ArenaMoongate(Point3D target, Map map, ExitTeleporter tp) : base(target, map) - { - m_Teleporter = tp; - - ItemID = 0x1FD4; - Dispellable = false; - - GumpWidth = 300; - GumpHeight = 150; - MessageColor = 0xFFC000; - MessageString = "Are you sure you wish to spectate this duel?"; - TitleColor = 0x7800; - TitleNumber = 1062051; // Gate Warning - - Timer.DelayCall(TimeSpan.FromSeconds(10.0), Delete); - } - - public ArenaMoongate(Serial serial) : base(serial) - { - } - - public override string DefaultName => "spectator moongate"; - - public override void CheckGate(Mobile m, int range) - { - if (CheckCombat(m)) - m.SendMessage(0x22, - "You have recently been in combat with another player and cannot use this moongate."); - else - base.CheckGate(m, range); - } - - public override void UseGate(Mobile m) - { - if (CheckCombat(m)) - { - m.SendMessage(0x22, - "You have recently been in combat with another player and cannot use this moongate."); - } - else - { - if (m_Teleporter?.Deleted == false) - m_Teleporter.Register(m); - - base.UseGate(m); - } - } - - public void Appear(Point3D loc, Map map) - { - Effects.PlaySound(loc, map, 0x20E); - MoveToWorld(loc, map); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Delete(); - } - } - } -} +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using Server.Engines.PartySystem; +using Server.Factions; +using Server.Gumps; +using Server.Items; +using Server.Mobiles; +using Server.Network; +using Server.Regions; +using Server.Spells; +using Server.Spells.Bushido; +using Server.Spells.Chivalry; +using Server.Spells.Fourth; +using Server.Spells.Necromancy; +using Server.Spells.Ninjitsu; +using Server.Spells.Second; +using Server.Spells.Seventh; +using Server.Spells.Spellweaving; +using Server.Targeting; + +namespace Server.Engines.ConPVP +{ + public delegate void CountdownCallback(int count); + + public class DuelContext + { + private static readonly TimeSpan CombatDelay = TimeSpan.FromSeconds(30.0); + private static readonly TimeSpan AutoTieDelay = TimeSpan.FromMinutes(15.0); + + private readonly List m_Walls = new List(); + + private Timer m_AutoTieTimer; + + private Timer m_Countdown; + + public EventGame m_EventGame; + private Map m_GateFacet; + + private Point3D m_GatePoint; + public TourneyMatch m_Match; + + public Arena m_OverrideArena; + + private Timer m_SDWarnTimer, m_SDActivateTimer; + public Tournament m_Tournament; + + private bool m_Yielding; + + public DuelContext(Mobile initiator, RulesetLayout layout, bool addNew = true) + { + Initiator = initiator; + Participants = new List(); + Ruleset = new Ruleset(layout); + Ruleset.ApplyDefault(layout.Defaults[0]); + + if (addNew) + { + Participants.Add(new Participant(this, 1)); + Participants.Add(new Participant(this, 1)); + Participants[0].Add(initiator); + } + } + + public bool Rematch { get; private set; } + + public bool ReadyWait { get; private set; } + + public int ReadyCount { get; private set; } + + public bool Registered { get; private set; } = true; + + public bool Finished { get; private set; } + + public bool Started { get; private set; } + + public Mobile Initiator { get; } + + public List Participants { get; } + + public Ruleset Ruleset { get; private set; } + + public Arena Arena { get; private set; } + + public bool Tied { get; private set; } + + public bool IsSuddenDeath { get; set; } + + public bool IsOneVsOne => Participants.Count == 2 && Participants[0].Players.Length == 1 && + Participants[1].Players.Length == 1; + + public bool StartedBeginCountdown { get; private set; } + + public bool StartedReadyCountdown { get; private set; } + + public Tournament Tournament => m_Tournament; + + private bool CantDoAnything(Mobile mob) => m_EventGame?.CantDoAnything(mob) == true; + + public static bool IsFreeConsume(Mobile mob) + { + if (!(mob is PlayerMobile pm) || pm.DuelContext?.m_EventGame == null) + return false; + + return pm.DuelContext.m_EventGame.FreeConsume; + } + + public void DelayBounce(TimeSpan ts, Mobile mob, Container corpse) + { + Timer.DelayCall(ts, DelayBounce_Callback, mob, corpse); + } + + public static bool AllowSpecialMove(Mobile from, string name, SpecialMove move) => + (from as PlayerMobile)?.DuelContext?.InstAllowSpecialMove(from, name, move) != false; + + public bool InstAllowSpecialMove(Mobile from, string name, SpecialMove move) + { + if (!StartedBeginCountdown) + return true; + + var pl = Find(from); + + if (pl?.Eliminated != false) + return true; + + if (CantDoAnything(from)) + return false; + + string title = null; + + if (move is NinjaMove) + title = "Bushido"; + else if (move is SamuraiMove) + title = "Ninjitsu"; + + if (title == null || name == null || Ruleset.GetOption(title, name)) + return true; + + from.SendMessage("The dueling ruleset prevents you from using this move."); + return false; + } + + public bool AllowSpellCast(Mobile from, Spell spell) + { + if (!StartedBeginCountdown) + return true; + + if (Find(from)?.Eliminated != false) + return true; + + if (CantDoAnything(from)) + return false; + + if (spell is RecallSpell) + from.SendMessage("You may not cast this spell."); + + string title; + string option; + + switch (spell) + { + case ArcanistSpell _: + title = "Spellweaving"; + option = spell.Name; + break; + case PaladinSpell _: + title = "Chivalry"; + option = spell.Name; + break; + case NecromancerSpell _: + title = "Necromancy"; + option = spell.Name; + break; + case NinjaSpell _: + title = "Ninjitsu"; + option = spell.Name; + break; + case SamuraiSpell _: + title = "Bushido"; + option = spell.Name; + break; + case MagerySpell magerySpell: + title = magerySpell.Circle switch + { + SpellCircle.First => "1st Circle", + SpellCircle.Second => "2nd Circle", + SpellCircle.Third => "3rd Circle", + SpellCircle.Fourth => "4th Circle", + SpellCircle.Fifth => "5th Circle", + SpellCircle.Sixth => "6th Circle", + SpellCircle.Seventh => "7th Circle", + SpellCircle.Eighth => "8th Circle", + _ => null + }; + + option = magerySpell.Name; + break; + default: + title = "Other Spell"; + option = spell.Name; + break; + } + + if (title == null || option == null || Ruleset.GetOption(title, option)) + return true; + + from.SendMessage("The dueling ruleset prevents you from casting this spell."); + return false; + } + + public bool AllowItemEquip(Mobile from, Item item) + { + if (!StartedBeginCountdown) + return true; + + var pl = Find(from); + + if (pl?.Eliminated != false) + return true; + + if (item is Dagger || CheckItemEquip(from, item)) + return true; + + from.SendMessage("The dueling ruleset prevents you from equipping this item."); + return false; + } + + public static bool AllowSpecialAbility(Mobile from, string name, bool message) + { + if (!(from is PlayerMobile pm)) + return true; + + var dc = pm.DuelContext; + + // No DuelContext or InstAllowSpecialAbility + return dc?.InstAllowSpecialAbility(from, name, message) != false; + } + + public bool InstAllowSpecialAbility(Mobile from, string name, bool message) + { + if (!StartedBeginCountdown) + return true; + + var pl = Find(from); + + if (pl?.Eliminated != false) + return true; + + if (CantDoAnything(from)) + return false; + + if (Ruleset.GetOption("Combat Abilities", name)) + return true; + + if (message) + from.SendMessage("The dueling ruleset prevents you from using this combat ability."); + + return false; + } + + public bool CheckItemEquip(Mobile from, Item item) + { + if (item is Fists) + { + if (!Ruleset.GetOption("Weapons", "Wrestling")) + return false; + } + else if (item is BaseArmor armor) + { + if (armor.ProtectionLevel > ArmorProtectionLevel.Regular && !Ruleset.GetOption("Armor", "Magical")) + return false; + + if (!Core.AOS && armor.Resource != armor.DefaultResource && !Ruleset.GetOption("Armor", "Colored")) + return false; + + if (armor is BaseShield && !Ruleset.GetOption("Armor", "Shields")) + return false; + } + else if (item is BaseWeapon weapon) + { + if ((weapon.DamageLevel > WeaponDamageLevel.Regular || weapon.AccuracyLevel > WeaponAccuracyLevel.Regular) && + !Ruleset.GetOption("Weapons", "Magical")) + return false; + + if (!Core.AOS && weapon.Resource != CraftResource.Iron && weapon.Resource != CraftResource.None && + !Ruleset.GetOption("Weapons", "Runics")) + return false; + + if (weapon is BaseRanged && !Ruleset.GetOption("Weapons", "Ranged")) + return false; + + if (!(weapon is BaseRanged) && !Ruleset.GetOption("Weapons", "Melee")) + return false; + + if (weapon.PoisonCharges > 0 && weapon.Poison != null && !Ruleset.GetOption("Weapons", "Poisoned")) + return false; + + if (weapon is BaseWand && !Ruleset.GetOption("Items", "Wands")) + return false; + } + + return true; + } + + public bool AllowSkillUse(Mobile from, SkillName skill) + { + if (!StartedBeginCountdown) + return true; + + var pl = Find(from); + + if (pl?.Eliminated != false) + return true; + + if (CantDoAnything(from)) + return false; + + var id = (int)skill; + + if (id >= 0 && id < SkillInfo.Table.Length) + if (Ruleset.GetOption("Skills", SkillInfo.Table[id].Name)) + return true; + + from.SendMessage("The dueling ruleset prevents you from using this skill."); + return false; + } + + public bool AllowItemUse(Mobile from, Item item) + { + if (!StartedBeginCountdown) + return true; + + var pl = Find(from); + + if (pl?.Eliminated != false) + return true; + + if (!(item is BaseRefreshPotion)) + if (CantDoAnything(from)) + return false; + + string title = null, option = null; + + if (item is BasePotion) + { + title = "Potions"; + + if (item is BaseAgilityPotion) + option = "Agility"; + else if (item is BaseCurePotion) + option = "Cure"; + else if (item is BaseHealPotion) + option = "Heal"; + else if (item is NightSightPotion) + option = "Nightsight"; + else if (item is BasePoisonPotion) + option = "Poison"; + else if (item is BaseStrengthPotion) + option = "Strength"; + else if (item is BaseExplosionPotion) + option = "Explosion"; + else if (item is BaseRefreshPotion) + option = "Refresh"; + } + else if (item is Bandage) + { + title = "Items"; + option = "Bandages"; + } + else if (item is TrappableContainer container) + { + if (container.TrapType != TrapType.None) + { + title = "Items"; + option = "Trapped Containers"; + } + } + else if (item is Bola) + { + title = "Items"; + option = "Bolas"; + } + else if (item is OrangePetals) + { + title = "Items"; + option = "Orange Petals"; + } + else if (item is EtherealMount || item.Layer == Layer.Mount) + { + title = "Items"; + option = "Mounts"; + } + else if (item is LeatherNinjaBelt) + { + title = "Items"; + option = "Shurikens"; + } + else if (item is Fukiya) + { + title = "Items"; + option = "Fukiya Darts"; + } + else if (item is FireHorn) + { + title = "Items"; + option = "Fire Horns"; + } + else if (item is BaseWand) + { + title = "Items"; + option = "Wands"; + } + + if (title != null && option != null && StartedBeginCountdown && !Started) + { + from.SendMessage("You may not use this item before the duel begins."); + return false; + } + + if (item is BasePotion && !(item is BaseExplosionPotion) && !(item is BaseRefreshPotion) && IsSuddenDeath) + { + from.SendMessage(0x22, "You may not drink potions in sudden death."); + return false; + } + + if (item is Bandage && IsSuddenDeath) + { + from.SendMessage(0x22, "You may not use bandages in sudden death."); + return false; + } + + if (title == null || option == null || Ruleset.GetOption(title, option)) + return true; + + from.SendMessage("The dueling ruleset prevents you from using this item."); + return false; + } + + private void DelayBounce_Callback(Mobile mob, Container corpse) + { + RemoveAggressions(mob); + SendOutside(mob); + Refresh(mob, corpse); + Debuff(mob); + CancelSpell(mob); + mob.Frozen = false; + } + + public void OnMapChanged(Mobile mob) + { + OnLocationChanged(mob); + } + + public void OnLocationChanged(Mobile mob) + { + if (!Registered || !StartedBeginCountdown || Finished) + return; + + var arena = Arena; + + if (arena == null) + return; + + if (mob.Map == arena.Facet && arena.Bounds.Contains(mob.Location)) + return; + + var pl = Find(mob); + + if (pl?.Eliminated != false) + return; + + if (mob.Map == Map.Internal) + if (mob.LogoutMap == arena.Facet && arena.Bounds.Contains(mob.LogoutLocation)) + mob.LogoutLocation = arena.Outside; + + pl.Eliminated = true; + + mob.LocalOverheadMessage(MessageType.Regular, 0x22, false, "You have forfeited your position in the duel."); + mob.NonlocalOverheadMessage( + MessageType.Regular, + 0x22, + false, + $"{mob.Name} has forfeited by leaving the dueling arena." + ); + + var winner = CheckCompletion(); + + if (winner != null) + Finish(winner); + } + + public void OnDeath(Mobile mob, Container corpse) + { + if (!Registered || !Started) + return; + + var pl = Find(mob); + + if (pl?.Eliminated != false || m_EventGame?.OnDeath(mob, corpse) == false) + return; + + pl.Eliminated = true; + + if (mob.Poison != null) + mob.Poison = null; + + Requip(mob, corpse); + DelayBounce(TimeSpan.FromSeconds(4.0), mob, corpse); + + var winner = CheckCompletion(); + + if (winner != null) + { + Finish(winner); + } + else if (!m_Yielding) + { + mob.LocalOverheadMessage(MessageType.Regular, 0x22, false, "You have been defeated."); + mob.NonlocalOverheadMessage(MessageType.Regular, 0x22, false, $"{mob.Name} has been defeated."); + } + } + + public bool CheckFull() + { + for (var i = 0; i < Participants.Count; ++i) + { + var p = Participants[i]; + + if (p.HasOpenSlot) + return false; + } + + return true; + } + + public void Requip(Mobile from, Container cont) + { + if (!(cont is Corpse corpse)) + return; + + var items = new List(corpse.Items); + + var didntFit = false; + + var pack = from.Backpack; + + for (var i = 0; !didntFit && i < items.Count; ++i) + { + var item = items[i]; + + if (item.Layer == Layer.Hair || item.Layer == Layer.FacialHair || !item.Movable) + continue; + + if (pack != null) + pack.DropItem(item); + else + didntFit = true; + } + + corpse.Carved = true; + + if (corpse.ItemID == 0x2006) + { + corpse.ProcessDelta(); + corpse.SendRemovePacket(); + corpse.ItemID = Utility.Random(0xECA, 9); // bone graphic + corpse.Hue = 0; + corpse.ProcessDelta(); + + var killer = from.FindMostRecentDamager(false); + + if (killer?.Player == true) + killer.AddToBackpack(new Head(m_Tournament == null ? HeadType.Duel : HeadType.Tournament, from.Name)); + } + + from.PlaySound(0x3E3); + + if (didntFit) + from.SendLocalizedMessage(1062472); // You gather some of your belongings. The rest remain on the corpse. + else + from.SendLocalizedMessage(1062471); // You quickly gather all of your belongings. + } + + public void Refresh(Mobile mob, Container cont) + { + if (!mob.Alive) + { + mob.Resurrect(); + + if (mob.FindItemOnLayer(Layer.OuterTorso) is DeathRobe robe) + robe.Delete(); + + if (cont is Corpse corpse) + for (var i = 0; i < corpse.EquipItems.Count; ++i) + { + var item = corpse.EquipItems[i]; + + if (item.Movable && item.Layer != Layer.Hair && item.Layer != Layer.FacialHair && + item.IsChildOf(mob.Backpack)) + mob.EquipItem(item); + } + } + + mob.Hits = mob.HitsMax; + mob.Stam = mob.StamMax; + mob.Mana = mob.ManaMax; + + mob.Poison = null; + } + + public void SendOutside(Mobile mob) + { + if (Arena == null) + return; + + mob.Combatant = null; + mob.MoveToWorld(Arena.Outside, Arena.Facet); + } + + public void Finish(Participant winner) + { + if (Finished) + return; + + EndAutoTie(); + StopSDTimers(); + + Finished = true; + + for (var i = 0; i < winner.Players.Length; ++i) + { + var pl = winner.Players[i]; + + if (pl?.Eliminated == false) + DelayBounce(TimeSpan.FromSeconds(8.0), pl.Mobile, null); + } + + winner.Broadcast( + 0x59, + null, + winner.Players.Length == 1 ? "{0} has won the duel." : "{0} and {1} team have won the duel.", + winner.Players.Length == 1 ? "You have won the duel." : "Your team has won the duel." + ); + + if (m_Tournament != null && winner.TourneyPart != null) + { + m_Match.Winner = winner.TourneyPart; + winner.TourneyPart.WonMatch(m_Match); + m_Tournament.HandleWon(Arena, m_Match, winner.TourneyPart); + } + + for (var i = 0; i < Participants.Count; ++i) + { + var loser = Participants[i]; + + if (loser != winner) + { + loser.Broadcast( + 0x22, + null, + loser.Players.Length == 1 ? "{0} has lost the duel." : "{0} and {1} team have lost the duel.", + loser.Players.Length == 1 ? "You have lost the duel." : "Your team has lost the duel." + ); + + if (m_Tournament != null) + loser.TourneyPart?.LostMatch(m_Match); + } + + for (var j = 0; j < loser.Players.Length; ++j) + if (loser.Players[j] != null) + { + RemoveAggressions(loser.Players[j].Mobile); + loser.Players[j].Mobile.Delta(MobileDelta.Noto); + loser.Players[j].Mobile.CloseGump(); + + if (m_Tournament != null) + loser.Players[j].Mobile.SendEverything(); + } + } + + if (IsOneVsOne) + { + var dp1 = Participants[0].Players[0]; + var dp2 = Participants[1].Players[0]; + + if (dp1 != null && dp2 != null) + { + Award(dp1.Mobile, dp2.Mobile, dp1.Participant == winner); + Award(dp2.Mobile, dp1.Mobile, dp2.Participant == winner); + } + } + + m_EventGame?.OnStop(); + + Timer.DelayCall(TimeSpan.FromSeconds(9.0), UnregisterRematch); + } + + public void Award(Mobile us, Mobile them, bool won) + { + var ladder = Arena == null ? Ladder.Instance : Arena.AcquireLadder(); + + if (ladder == null) + return; + + var ourEntry = ladder.Find(us); + var theirEntry = ladder.Find(them); + + if (ourEntry == null || theirEntry == null) + return; + + var xpGain = Ladder.GetExperienceGain(ourEntry, theirEntry, won); + + if (xpGain == 0) + return; + + if (m_Tournament != null) + xpGain *= xpGain > 0 ? 5 : 2; + + if (won) + ++ourEntry.Wins; + else + ++ourEntry.Losses; + + var oldLevel = Ladder.GetLevel(ourEntry.Experience); + + ourEntry.Experience += xpGain; + + if (ourEntry.Experience < 0) + ourEntry.Experience = 0; + + ladder.UpdateEntry(ourEntry); + + var newLevel = Ladder.GetLevel(ourEntry.Experience); + + if (newLevel > oldLevel) + us.SendMessage(0x59, "You have achieved level {0}!", newLevel); + else if (newLevel < oldLevel) + us.SendMessage(0x22, "You have lost a level. You are now at {0}.", newLevel); + } + + public void UnregisterRematch() + { + Unregister(true); + } + + public void Unregister() + { + Unregister(false); + } + + public void Unregister(bool queryRematch) + { + DestroyWall(); + + if (!Registered) + return; + + Registered = false; + + Arena?.Evict(); + + StopSDTimers(); + + for (var i = 0; i < Participants.Count; ++i) + { + var p = Participants[i]; + + for (var j = 0; j < p.Players.Length; ++j) + { + var pl = p.Players[j]; + + if (pl == null) + continue; + + if (pl.Mobile is PlayerMobile mobile) + mobile.DuelPlayer = null; + + CloseAllGumps(pl); + } + } + + if (queryRematch && m_Tournament == null) + QueryRematch(); + } + + public void QueryRematch() + { + var dc = new DuelContext(Initiator, Ruleset.Layout, false); + + dc.Ruleset = Ruleset; + dc.Rematch = true; + + dc.Participants.Clear(); + + for (var i = 0; i < Participants.Count; ++i) + { + var oldPart = Participants[i]; + var newPart = new Participant(dc, oldPart.Players.Length); + + for (var j = 0; j < oldPart.Players.Length; ++j) + { + var oldPlayer = oldPart.Players[j]; + + if (oldPlayer != null) + newPart.Players[j] = new DuelPlayer(oldPlayer.Mobile, newPart); + } + + dc.Participants.Add(newPart); + } + + dc.CloseAllGumps(); + dc.SendReadyUpGump(); + } + + public DuelPlayer Find(Mobile mob) + { + if (mob is PlayerMobile pm) + { + if (pm.DuelContext == this) + return pm.DuelPlayer; + + return null; + } + + for (var i = 0; i < Participants.Count; ++i) + { + var p = Participants[i]; + var pl = p.Find(mob); + + if (pl != null) + return pl; + } + + return null; + } + + public bool IsAlly(Mobile m1, Mobile m2) + { + var pl1 = Find(m1); + var pl2 = Find(m2); + + return pl1 != null && pl1.Participant == pl2?.Participant; + } + + public Participant CheckCompletion() + { + Participant winner = null; + + var hasWinner = false; + var eliminated = 0; + + for (var i = 0; i < Participants.Count; ++i) + { + var p = Participants[i]; + + if (p.Eliminated) + { + ++eliminated; + + if (eliminated == Participants.Count - 1) + hasWinner = true; + } + else + { + winner = p; + } + } + + return hasWinner ? winner ?? Participants[0] : null; + } + + public void StartCountdown(int count, CountdownCallback cb) + { + cb(count); + m_Countdown = Timer.DelayCall( + TimeSpan.FromSeconds(1.0), + TimeSpan.FromSeconds(1.0), + count, + () => Countdown_Callback(--count, cb) + ); + } + + public void StopCountdown() + { + m_Countdown?.Stop(); + m_Countdown = null; + } + + private void Countdown_Callback(int count, CountdownCallback cb) + { + if (count == 0) + StopCountdown(); + + cb(count); + } + + public void StopSDTimers() + { + m_SDWarnTimer?.Stop(); + + m_SDWarnTimer = null; + + m_SDActivateTimer?.Stop(); + + m_SDActivateTimer = null; + } + + public void StartSuddenDeath(TimeSpan timeUntilActive) + { + m_SDWarnTimer?.Stop(); + + m_SDWarnTimer = Timer.DelayCall(TimeSpan.FromMinutes(timeUntilActive.TotalMinutes * 0.9), WarnSuddenDeath); + + m_SDActivateTimer?.Stop(); + + m_SDActivateTimer = Timer.DelayCall(timeUntilActive, ActivateSuddenDeath); + } + + public void WarnSuddenDeath() + { + for (var i = 0; i < Participants.Count; ++i) + { + var p = Participants[i]; + + for (var j = 0; j < p.Players.Length; ++j) + { + var pl = p.Players[j]; + + if (pl?.Eliminated != false) + continue; + + pl.Mobile.SendSound(0x1E1); + pl.Mobile.SendMessage(0x22, "Warning! Warning! Warning!"); + pl.Mobile.SendMessage(0x22, "Sudden death will be active soon!"); + } + } + + m_Tournament?.Alert(Arena, "Sudden death will be active soon!"); + + m_SDWarnTimer?.Stop(); + + m_SDWarnTimer = null; + } + + public static bool CheckSuddenDeath(Mobile mob) => mob is PlayerMobile pm && pm.DuelPlayer?.Eliminated == false && + pm.DuelContext?.IsSuddenDeath == true; + + public void ActivateSuddenDeath() + { + for (var i = 0; i < Participants.Count; ++i) + { + var p = Participants[i]; + + for (var j = 0; j < p.Players.Length; ++j) + { + var pl = p.Players[j]; + + if (pl?.Eliminated != false) + continue; + + pl.Mobile.SendSound(0x1E1); + pl.Mobile.SendMessage(0x22, "Warning! Warning! Warning!"); + pl.Mobile.SendMessage( + 0x22, + "Sudden death has ACTIVATED. You are now unable to perform any beneficial actions." + ); + } + } + + m_Tournament?.Alert(Arena, "Sudden death has been activated!"); + + IsSuddenDeath = true; + + m_SDActivateTimer?.Stop(); + + m_SDActivateTimer = null; + } + + public void BeginAutoTie() + { + m_AutoTieTimer?.Stop(); + + var ts = m_Tournament == null || m_Tournament.TourneyType == TourneyType.Standard + ? AutoTieDelay + : TimeSpan.FromMinutes(90.0); + + m_AutoTieTimer = Timer.DelayCall(ts, InvokeAutoTie); + } + + public void EndAutoTie() + { + m_AutoTieTimer?.Stop(); + + m_AutoTieTimer = null; + } + + public void InvokeAutoTie() + { + m_AutoTieTimer = null; + + if (!Started || Finished) + return; + + Tied = true; + Finished = true; + + StopSDTimers(); + + var remaining = new List(); + + for (var i = 0; i < Participants.Count; ++i) + { + var p = Participants[i]; + + if (p.Eliminated) + { + p.Broadcast( + 0x22, + null, + p.Players.Length == 1 ? "{0} has lost the duel." : "{0} and {1} team have lost the duel.", + p.Players.Length == 1 ? "You have lost the duel." : "Your team has lost the duel." + ); + } + else + { + p.Broadcast( + 0x59, + null, + p.Players.Length == 1 + ? "{0} has tied the duel due to time expiration." + : "{0} and {1} team have tied the duel due to time expiration.", + p.Players.Length == 1 + ? "You have tied the duel due to time expiration." + : "Your team has tied the duel due to time expiration." + ); + + for (var j = 0; j < p.Players.Length; ++j) + { + var pl = p.Players[j]; + + if (pl?.Eliminated == false) + DelayBounce(TimeSpan.FromSeconds(8.0), pl.Mobile, null); + } + + if (p.TourneyPart != null) + remaining.Add(p.TourneyPart); + } + + for (var j = 0; j < p.Players.Length; ++j) + { + var pl = p.Players[j]; + + if (pl != null) + { + pl.Mobile.Delta(MobileDelta.Noto); + pl.Mobile.SendEverything(); + } + } + } + + m_Tournament?.HandleTie(Arena, m_Match, remaining); + + Timer.DelayCall(TimeSpan.FromSeconds(10.0), Unregister); + } + + public static void Initialize() + { + EventSink.Speech += EventSink_Speech; + EventSink.Login += EventSink_Login; + + CommandSystem.Register("vli", AccessLevel.GameMaster, vli_oc); + } + + private static void vli_oc(CommandEventArgs e) + { + e.Mobile.BeginTarget(-1, false, TargetFlags.None, vli_ot); + } + + private static void vli_ot(Mobile from, object obj) + { + if (obj is PlayerMobile pm) + { + var ladder = Ladder.Instance; + + if (ladder == null) + return; + + var entry = ladder.Find(pm); + + if (entry != null) + from.SendGump(new PropertiesGump(from, entry)); + } + } + + public static bool CheckCombat(Mobile m) => + m.Aggressed.Any(info => info.Defender.Player && DateTime.UtcNow - info.LastCombatTime < CombatDelay) || + m.Aggressors.Any(info => info.Attacker.Player && DateTime.UtcNow - info.LastCombatTime < CombatDelay); + + private static void EventSink_Login(Mobile m) + { + if (!(m is PlayerMobile pm)) + return; + + var dc = pm.DuelContext; + + if (dc == null) + return; + + if (dc.ReadyWait && pm.DuelPlayer.Ready && !dc.Started && !dc.StartedBeginCountdown && !dc.Finished) + { + if (dc.m_Tournament == null) + pm.SendGump(new ReadyGump(pm, dc, dc.ReadyCount)); + } + else if (dc.ReadyWait && !dc.StartedBeginCountdown && !dc.Started && !dc.Finished) + { + if (dc.m_Tournament == null) + pm.SendGump(new ReadyUpGump(pm, dc)); + } + else if (dc.Initiator == pm && !dc.ReadyWait && !dc.StartedBeginCountdown && !dc.Started && !dc.Finished) + { + pm.SendGump(new DuelContextGump(pm, dc)); + } + } + + private static void ViewLadder_OnTarget(Mobile from, object obj, Ladder ladder) + { + if (obj is PlayerMobile pm) + { + var entry = ladder.Find(pm); + + if (entry == null) + return; // sanity + + var text = + $"{{0}} are ranked {LadderGump.Rank(entry.Index + 1)} at level {Ladder.GetLevel(entry.Experience)}."; + + pm.PrivateOverheadMessage( + MessageType.Regular, + pm.SpeechHue, + true, + string.Format(text, from == pm ? "You" : "They"), + from.NetState + ); + } + else if (obj is Mobile mob) + { + if (mob.Body.IsHuman) + mob.PrivateOverheadMessage( + MessageType.Regular, + mob.SpeechHue, + false, + "I'm not a duelist, and quite frankly, I resent the implication.", + from.NetState + ); + else + mob.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + true, + "It's probably better than you.", + from.NetState + ); + } + else + { + from.SendMessage("That's not a player."); + } + } + + private static void EventSink_Speech(SpeechEventArgs e) + { + if (e.Handled) + return; + + if (!(e.Mobile is PlayerMobile pm)) + return; + + if (Insensitive.Contains(e.Speech, "i wish to duel")) + { + if (!pm.CheckAlive()) + { + } + else if (pm.Region.IsPartOf()) + { + } + else if (CheckCombat(pm)) + { + e.Mobile.SendMessage( + 0x22, + "You have recently been in combat with another player and must wait before starting a duel." + ); + } + else if (pm.DuelContext != null) + { + if (pm.DuelContext.Initiator == pm) + e.Mobile.SendMessage(0x22, "You have already started a duel."); + else + e.Mobile.SendMessage(0x22, "You have already been challenged in a duel."); + } + else if (TournamentController.IsActive) + { + e.Mobile.SendMessage(0x22, "You may not start a duel while a tournament is active."); + } + else + { + pm.SendGump(new DuelContextGump(pm, new DuelContext(pm, RulesetLayout.Root))); + e.Handled = true; + } + } + else if (Insensitive.Equals(e.Speech, "change arena preferences")) + { + if (!pm.CheckAlive()) + { + } + else + { + var prefs = Preferences.Instance; + + if (prefs != null) + { + e.Mobile.CloseGump(); + e.Mobile.SendGump(new PreferencesGump(e.Mobile, prefs)); + } + } + } + else if (Insensitive.Equals(e.Speech, "showladder")) + { + e.Blocked = true; + if (!pm.CheckAlive()) + { + } + else + { + var instance = Ladder.Instance; + + if (instance == null) + { + // pm.SendMessage( "Ladder not yet initialized." ); + } + else + { + var entry = instance.Find(pm); + + if (entry == null) + return; // sanity + + var text = + $"{{0}} {{1}} ranked {LadderGump.Rank(entry.Index + 1)} at level {Ladder.GetLevel(entry.Experience)}."; + + pm.LocalOverheadMessage(MessageType.Regular, pm.SpeechHue, true, string.Format(text, "You", "are")); + pm.NonlocalOverheadMessage( + MessageType.Regular, + pm.SpeechHue, + true, + string.Format(text, pm.Name, "is") + ); + + // pm.PublicOverheadMessage( MessageType.Regular, pm.SpeechHue, true, String.Format( "Level {0} with {1} win{2} and {3} loss{4}.", Ladder.GetLevel( entry.Experience ), entry.Wins, entry.Wins==1?"":"s", entry.Losses, entry.Losses==1?"":"es" ) ); + // pm.PublicOverheadMessage( MessageType.Regular, pm.SpeechHue, true, String.Format( "Level {0} with {1} win{2} and {3} loss{4}.", Ladder.GetLevel( entry.Experience ), entry.Wins, entry.Wins==1?"":"s", entry.Losses, entry.Losses==1?"":"es" ) ); + } + } + } + else if (Insensitive.Equals(e.Speech, "viewladder")) + { + e.Blocked = true; + + if (!pm.CheckAlive()) + { + } + else + { + var instance = Ladder.Instance; + + if (instance == null) + { + // pm.SendMessage( "Ladder not yet initialized." ); + } + else + { + pm.SendMessage("Target a player to view their ranking and level."); + pm.BeginTarget(16, false, TargetFlags.None, ViewLadder_OnTarget, instance); + } + } + } + else if (Insensitive.Contains(e.Speech, "i yield")) + { + if (!pm.CheckAlive()) + { + } + else if (pm.DuelContext == null) + { + } + else if (pm.DuelContext.Finished) + { + e.Mobile.SendMessage(0x22, "The duel is already finished."); + } + else if (!pm.DuelContext.Started) + { + var dc = pm.DuelContext; + var init = dc.Initiator; + + if (pm.DuelContext.StartedBeginCountdown) + { + e.Mobile.SendMessage(0x22, "The duel has not yet started."); + } + else + { + var pl = pm.DuelContext.Find(pm); + + if (pl == null) + return; + + var p = pl.Participant; + + if (!pm.DuelContext.ReadyWait) // still setting stuff up + { + p.Broadcast(0x22, null, "{0} has yielded.", "You have yielded."); + + if (init == pm) + { + dc.Unregister(); + } + else + { + p.Nullify(pl); + pm.DuelPlayer = null; + + var ns = init.NetState; + + if (ns != null) + foreach (var g in ns.Gumps) + { + if (g is ParticipantGump pg && pg.Participant == p) + { + init.SendGump(new ParticipantGump(init, dc, p)); + break; + } + + if (g is DuelContextGump dcg && dcg.Context == dc) + { + init.SendGump(new DuelContextGump(init, dc)); + break; + } + } + } + } + else if (!pm.DuelContext.StartedReadyCountdown) // at ready stage + { + p.Broadcast(0x22, null, "{0} has yielded.", "You have yielded."); + + dc.m_Yielding = true; + dc.RejectReady(pm, null); + dc.m_Yielding = false; + + if (init == pm) + { + dc.Unregister(); + } + else if (dc.Registered) + { + p.Nullify(pl); + pm.DuelPlayer = null; + + var ns = init.NetState; + + if (ns != null) + { + var send = true; + + foreach (var g in ns.Gumps) + { + if (g is ParticipantGump pg && pg.Participant == p) + { + init.SendGump(new ParticipantGump(init, dc, p)); + send = false; + break; + } + + if (g is DuelContextGump dcg && dcg.Context == dc) + { + init.SendGump(new DuelContextGump(init, dc)); + send = false; + break; + } + } + + if (send) + init.SendGump(new DuelContextGump(init, dc)); + } + } + } + else + { + pm.DuelContext.m_Countdown?.Stop(); + pm.DuelContext.m_Countdown = null; + + pm.DuelContext.StartedReadyCountdown = false; + p.Broadcast(0x22, null, "{0} has yielded.", "You have yielded."); + + dc.m_Yielding = true; + dc.RejectReady(pm, null); + dc.m_Yielding = false; + + if (init == pm) + { + dc.Unregister(); + } + else if (dc.Registered) + { + p.Nullify(pl); + pm.DuelPlayer = null; + + var ns = init.NetState; + + if (ns != null) + { + var send = true; + + foreach (var g in ns.Gumps) + { + if (g is ParticipantGump pg && pg.Participant == p) + { + init.SendGump(new ParticipantGump(init, dc, p)); + send = false; + break; + } + + if (g is DuelContextGump dcg && dcg.Context == dc) + { + init.SendGump(new DuelContextGump(init, dc)); + send = false; + break; + } + } + + if (send) + init.SendGump(new DuelContextGump(init, dc)); + } + } + } + } + } + else + { + var pl = pm.DuelContext.Find(pm); + + if (pl != null) + { + if (pm.DuelContext.IsOneVsOne) + { + e.Mobile.SendMessage(0x22, "You may not yield a 1 on 1 match."); + } + else if (pl.Eliminated) + { + e.Mobile.SendMessage(0x22, "You have already been eliminated."); + } + else + { + pm.LocalOverheadMessage(MessageType.Regular, 0x22, false, "You have yielded."); + pm.NonlocalOverheadMessage(MessageType.Regular, 0x22, false, $"{pm.Name} has yielded."); + + pm.DuelContext.m_Yielding = true; + pm.Kill(); + pm.DuelContext.m_Yielding = false; + + if (pm.Alive) // invul, ... + { + pl.Eliminated = true; + + pm.DuelContext.RemoveAggressions(pm); + pm.DuelContext.SendOutside(pm); + pm.DuelContext.Refresh(pm, null); + Debuff(pm); + CancelSpell(pm); + pm.Frozen = false; + + var winner = pm.DuelContext.CheckCompletion(); + + if (winner != null) + pm.DuelContext.Finish(winner); + } + } + } + else + { + e.Mobile.SendMessage(0x22, "BUG: Unable to find duel context."); + } + } + } + } + + public void CloseAllGumps(DuelPlayer pl) + { + pl.Mobile.CloseGump(); + pl.Mobile.CloseGump(); + pl.Mobile.CloseGump(); + pl.Mobile.CloseGump(); + pl.Mobile.CloseGump(); + pl.Mobile.CloseGump(); + pl.Mobile.CloseGump(); + } + + public void CloseAllGumps() + { + for (var i = 0; i < Participants.Count; ++i) + { + var p = Participants[i]; + + for (var j = 0; j < p.Players.Length; ++j) + { + var pl = p.Players[j]; + + if (pl != null) + CloseAllGumps(pl); + } + } + } + + public void RejectReady(Mobile rejector, string page) + { + if (StartedReadyCountdown) + return; // sanity + + for (var i = 0; i < Participants.Count; ++i) + { + var p = Participants[i]; + + for (var j = 0; j < p.Players.Length; ++j) + { + var pl = p.Players[j]; + + if (pl == null) + continue; + + pl.Ready = false; + + var mob = pl.Mobile; + + if (page == null) // yield + { + if (mob != rejector) + mob.SendMessage(0x22, "{0} has yielded.", rejector.Name); + } + else + { + if (mob == rejector) + mob.SendMessage(0x22, "You have rejected the {0}.", Rematch ? "rematch" : page); + else + mob.SendMessage(0x22, "{0} has rejected the {1}.", rejector.Name, Rematch ? "rematch" : page); + } + + // Close all of them? + mob.CloseGump(); + mob.CloseGump(); + mob.CloseGump(); + } + } + + if (Rematch) + Unregister(); + else if (!m_Yielding) + Initiator.SendGump(new DuelContextGump(Initiator, this)); + + ReadyWait = false; + ReadyCount = 0; + } + + public void SendReadyGump() + { + SendReadyGump(-1); + } + + public static void Debuff(Mobile mob) + { + mob.RemoveStatMod("[Magic] Str Offset"); + mob.RemoveStatMod("[Magic] Dex Offset"); + mob.RemoveStatMod("[Magic] Int Offset"); + mob.RemoveStatMod("Concussion"); + mob.RemoveStatMod("blood-rose"); + mob.RemoveStatMod("clarity-potion"); + + OrangePetals.RemoveContext(mob); + + mob.Paralyzed = false; + mob.Hidden = false; + + if (!Core.AOS) + { + mob.MagicDamageAbsorb = 0; + mob.MeleeDamageAbsorb = 0; + ProtectionSpell.Registry.Remove(mob); + + ArchProtectionSpell.RemoveEntry(mob); + + mob.EndAction(); + } + + TransformationSpellHelper.RemoveContext(mob, true); + AnimalForm.RemoveContext(mob, true); + + if (DisguiseTimers.IsDisguised(mob)) + DisguiseTimers.StopTimer(mob); + + if (!mob.CanBeginAction()) + { + mob.BodyMod = 0; + mob.HueMod = -1; + mob.EndAction(); + } + + BaseArmor.ValidateMobile(mob); + BaseClothing.ValidateMobile(mob); + + mob.Hits = mob.HitsMax; + mob.Stam = mob.StamMax; + mob.Mana = mob.ManaMax; + + mob.Poison = null; + } + + public static void CancelSpell(Mobile mob) + { + if (mob.Spell is Spell spell) + spell.Disturb(DisturbType.Kill); + + Target.Cancel(mob); + } + + public void DestroyWall() + { + for (var i = 0; i < m_Walls.Count; ++i) + m_Walls[i].Delete(); + + m_Walls.Clear(); + } + + public void CreateWall() + { + if (Arena == null) + return; + + var start = Arena.Points.EdgeWest; + var wall = Arena.Wall; + + var dx = start.X - wall.X; + var dy = start.Y - wall.Y; + var rx = dx - dy; + var ry = dx + dy; + + bool eastToWest; + + if (rx >= 0 && ry >= 0) + eastToWest = false; + else if (rx >= 0) + eastToWest = true; + else if (ry >= 0) + eastToWest = true; + else + eastToWest = false; + + Effects.PlaySound(wall, Arena.Facet, 0x1F6); + + for (var i = -1; i <= 1; ++i) + { + var loc = new Point3D(eastToWest ? wall.X + i : wall.X, eastToWest ? wall.Y : wall.Y + i, wall.Z); + + var created = new InternalWall(); + + created.Appear(loc, Arena.Facet); + + m_Walls.Add(created); + } + } + + public void BuildParties() + { + for (var i = 0; i < Participants.Count; ++i) + { + var p = Participants[i]; + + if (p.Players.Length > 1) + { + var players = new List(); + + for (var j = 0; j < p.Players.Length; ++j) + { + var dp = p.Players[j]; + + if (dp == null) + continue; + + players.Add(dp.Mobile); + } + + if (players.Count > 1) + for (var leaderIndex = 0; leaderIndex + 1 < players.Count; leaderIndex += Party.Capacity) + { + var leader = players[leaderIndex]; + var party = Party.Get(leader); + + if (party == null) + { + leader.Party = party = new Party(leader); + } + else if (party.Leader != leader) + { + party.SendPublicMessage(leader, "I leave this party to fight in a duel."); + party.Remove(leader); + leader.Party = party = new Party(leader); + } + + for (var j = leaderIndex + 1; j < players.Count && j < leaderIndex + Party.Capacity; ++j) + { + var player = players[j]; + var existing = Party.Get(player); + + if (existing == party) + continue; + + if (party.Members.Count + party.Candidates.Count >= Party.Capacity) + { + player.SendMessage( + "You could not be added to the team party because it is at full capacity." + ); + leader.SendMessage( + "{0} could not be added to the team party because it is at full capacity." + ); + } + else + { + if (existing != null) + { + existing.SendPublicMessage(player, "I leave this party to fight in a duel."); + existing.Remove(player); + } + + party.OnAccept(player, true); + } + } + } + } + } + } + + public void ClearIllegalItems() + { + for (var i = 0; i < Participants.Count; ++i) + { + var p = Participants[i]; + + for (var j = 0; j < p.Players.Length; ++j) + { + var pl = p.Players[j]; + + if (pl == null) + continue; + + ClearIllegalItems(pl.Mobile); + } + } + } + + public void ClearIllegalItems(Mobile mob) + { + if (mob.StunReady && !AllowSpecialAbility(mob, "Stun", false)) + mob.StunReady = false; + + if (mob.DisarmReady && !AllowSpecialAbility(mob, "Disarm", false)) + mob.DisarmReady = false; + + var pack = mob.Backpack; + + if (pack == null) + return; + + for (var i = mob.Items.Count - 1; i >= 0; --i) + { + if (i >= mob.Items.Count) + continue; // sanity + + var item = mob.Items[i]; + + if (!CheckItemEquip(mob, item)) + { + pack.DropItem(item); + + if (item is BaseWeapon) + mob.SendLocalizedMessage( + 1062001, + item.Name ?? $"#{item.LabelNumber}" + ); // You can no longer wield your ~1_WEAPON~ + else if (item is BaseArmor && !(item is BaseShield)) + mob.SendLocalizedMessage( + 1062002, + item.Name ?? $"#{item.LabelNumber}" + ); // You can no longer wear your ~1_ARMOR~ + else + mob.SendLocalizedMessage( + 1062003, + item.Name ?? $"#{item.LabelNumber}" + ); // You can no longer equip your ~1_SHIELD~ + } + } + + var inHand = mob.Holding; + + if (inHand != null && !CheckItemEquip(mob, inHand)) + { + mob.Holding = null; + + var bi = inHand.GetBounce(); + + if (bi.Parent == mob) + pack.DropItem(inHand); + else + inHand.Bounce(mob); + + inHand.ClearBounce(); + } + } + + private void MessageRuleset(Mobile mob) + { + if (Ruleset == null) return; + + var ruleset = Ruleset; + var basedef = ruleset.Base; + + mob.SendMessage("Ruleset: {0}", basedef.Title); + + BitArray defs; + + if (ruleset.Flavors.Count > 0) + { + defs = new BitArray(basedef.Options); + + for (var i = 0; i < ruleset.Flavors.Count; ++i) + { + defs.Or(ruleset.Flavors[i].Options); + + mob.SendMessage(" + {0}", ruleset.Flavors[i].Title); + } + } + else + { + defs = basedef.Options; + } + + var changes = 0; + + var opts = ruleset.Options; + + for (var i = 0; i < opts.Length; ++i) + if (defs[i] != opts[i]) + { + var name = ruleset.Layout.FindByIndex(i); + + if (name != null) // sanity + { + ++changes; + + if (changes == 1) mob.SendMessage("Modifications:"); + + mob.SendMessage("{0}: {1}", name, opts[i] ? "enabled" : "disabled"); + } + } + } + + public void SendBeginGump(int count) + { + if (!Registered || Finished) + return; + + if (count == 10) + { + CreateWall(); + BuildParties(); + ClearIllegalItems(); + } + else if (count == 0) + { + DestroyWall(); + } + + StartedBeginCountdown = true; + + if (count == 0) + { + Started = true; + BeginAutoTie(); + } + + for (var i = 0; i < Participants.Count; ++i) + { + var p = Participants[i]; + + for (var j = 0; j < p.Players.Length; ++j) + { + var pl = p.Players[j]; + + if (pl == null) + continue; + + var mob = pl.Mobile; + + if (count > 0) + { + if (count == 10) + { + mob.CloseGump(); + mob.CloseGump(); + mob.CloseGump(); + mob.SendGump(new BeginGump(count)); + } + + mob.Frozen = true; + } + else + { + mob.CloseGump(); + mob.Frozen = false; + } + } + } + } + + public void RemoveAggressions(Mobile mob) + { + for (var i = 0; i < Participants.Count; ++i) + { + var p = Participants[i]; + + for (var j = 0; j < p.Players.Length; ++j) + { + var dp = p.Players[j]; + + if (dp == null || dp.Mobile == mob) + continue; + + mob.RemoveAggressed(dp.Mobile); + mob.RemoveAggressor(dp.Mobile); + dp.Mobile.RemoveAggressed(mob); + dp.Mobile.RemoveAggressor(mob); + } + } + } + + public void SendReadyUpGump() + { + if (!Registered) + return; + + ReadyWait = true; + ReadyCount = -1; + + for (var i = 0; i < Participants.Count; ++i) + { + var p = Participants[i]; + + for (var j = 0; j < p.Players.Length; ++j) + { + var pl = p.Players[j]; + + var mob = pl?.Mobile; + + if (mob != null && m_Tournament == null) + { + mob.CloseGump(); + mob.SendGump(new ReadyUpGump(mob, this)); + } + } + } + } + + public string ValidateStart() + { + if (m_Tournament == null && TournamentController.IsActive) + return "a tournament is active"; + + for (var i = 0; i < Participants.Count; ++i) + { + var p = Participants[i]; + + for (var j = 0; j < p.Players.Length; ++j) + { + var dp = p.Players[j]; + + if (dp == null) + return "a slot is empty"; + + if (dp.Mobile.Region.IsPartOf()) + return $"{dp.Mobile.Name} is in jail"; + + if (Sigil.ExistsOn(dp.Mobile)) + return $"{dp.Mobile.Name} is holding a sigil"; + + if (!dp.Mobile.Alive) + { + if (m_Tournament == null) + return $"{dp.Mobile.Name} is dead"; + dp.Mobile.Resurrect(); + } + + if (m_Tournament == null && CheckCombat(dp.Mobile)) + return $"{dp.Mobile.Name} is in combat"; + + if (dp.Mobile.Mounted) + { + var mount = dp.Mobile.Mount; + + if (m_Tournament != null && mount != null) + mount.Rider = null; + else + return $"{dp.Mobile.Name} is mounted"; + } + } + } + + return null; + } + + public void SendReadyGump(int count) + { + if (!Registered) + return; + + if (count != -1) + StartedReadyCountdown = true; + + ReadyCount = count; + + if (count == 0) + { + var error = ValidateStart(); + + if (error != null) + { + for (var i = 0; i < Participants.Count; ++i) + { + var p = Participants[i]; + + for (var j = 0; j < p.Players.Length; ++j) + { + var dp = p.Players[j]; + + dp?.Mobile.SendMessage("The duel could not be started because {0}.", error); + } + } + + StartCountdown(10, SendReadyGump); + + return; + } + + ReadyWait = false; + + var players = new List(); + + for (var i = 0; i < Participants.Count; ++i) + { + var p = Participants[i]; + + for (var j = 0; j < p.Players.Length; ++j) + { + var dp = p.Players[j]; + + if (dp != null) + players.Add(dp.Mobile); + } + } + + var arena = m_OverrideArena ?? Arena.FindArena(players); + + if (arena == null) + { + for (var i = 0; i < Participants.Count; ++i) + { + var p = Participants[i]; + + for (var j = 0; j < p.Players.Length; ++j) + { + var dp = p.Players[j]; + + dp?.Mobile.SendMessage( + "The duel could not be started because there are no arenas. If you want to stop waiting for a free arena, yield the duel." + ); + } + } + + StartCountdown(10, SendReadyGump); + return; + } + + if (!arena.IsOccupied) + { + Arena = arena; + + if (Initiator.Map == Map.Internal) + { + m_GatePoint = Initiator.LogoutLocation; + m_GateFacet = Initiator.LogoutMap; + } + else + { + m_GatePoint = Initiator.Location; + m_GateFacet = Initiator.Map; + } + + if (!(arena.Teleporter is ExitTeleporter tp)) + { + arena.Teleporter = tp = new ExitTeleporter(); + tp.MoveToWorld(arena.GateOut == Point3D.Zero ? arena.Outside : arena.GateOut, arena.Facet); + } + + var mg = new ArenaMoongate( + arena.GateIn == Point3D.Zero ? arena.Outside : arena.GateIn, + arena.Facet, + tp + ); + + StartedBeginCountdown = true; + + for (var i = 0; i < Participants.Count; ++i) + { + var p = Participants[i]; + + for (var j = 0; j < p.Players.Length; ++j) + { + var pl = p.Players[j]; + + if (pl == null) + continue; + + tp.Register(pl.Mobile); + + pl.Mobile.Frozen = false; // reset timer just in case + pl.Mobile.Frozen = true; + + Debuff(pl.Mobile); + CancelSpell(pl.Mobile); + + pl.Mobile.Delta(MobileDelta.Noto); + } + + arena.MoveInside(p.Players, i); + } + + m_EventGame?.OnStart(); + + StartCountdown(10, SendBeginGump); + + mg.Appear(m_GatePoint, m_GateFacet); + } + else + { + for (var i = 0; i < Participants.Count; ++i) + { + var p = Participants[i]; + + for (var j = 0; j < p.Players.Length; ++j) + { + var dp = p.Players[j]; + + dp?.Mobile.SendMessage( + "The duel could not be started because all arenas are full. If you want to stop waiting for a free arena, yield the duel." + ); + } + } + + StartCountdown(10, SendReadyGump); + } + + return; + } + + ReadyWait = true; + + var isAllReady = true; + + for (var i = 0; i < Participants.Count; ++i) + { + var p = Participants[i]; + + for (var j = 0; j < p.Players.Length; ++j) + { + var pl = p.Players[j]; + + if (pl == null) + continue; + + var mob = pl.Mobile; + + if (pl.Ready) + { + if (m_Tournament == null) + { + mob.CloseGump(); + mob.SendGump(new ReadyGump(mob, this, count)); + } + } + else + { + isAllReady = false; + } + } + } + + if (count == -1 && isAllReady) + StartCountdown(3, SendReadyGump); + } + + private class InternalWall : Item + { + public InternalWall() : base(0x80) => Movable = false; + + public InternalWall(Serial serial) : base(serial) + { + } + + public void Appear(Point3D loc, Map map) + { + MoveToWorld(loc, map); + + Effects.SendLocationParticles(this, 0x376A, 9, 10, 5025); + } + + 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(); + + Delete(); + } + } + + private class ReturnEntry + { + private DateTime m_Expire; + + public ReturnEntry(Mobile mob) + { + Mobile = mob; + + Update(); + } + + public ReturnEntry(Mobile mob, Point3D loc, Map facet) + { + Mobile = mob; + Location = loc; + Facet = facet; + m_Expire = DateTime.UtcNow + TimeSpan.FromMinutes(30.0); + } + + public Mobile Mobile { get; } + + public Point3D Location { get; private set; } + + public Map Facet { get; private set; } + + public bool Expired => DateTime.UtcNow >= m_Expire; + + public void Return() + { + if (Facet == Map.Internal || Facet == null) + return; + + if (Mobile.Map == Map.Internal) + { + Mobile.LogoutLocation = Location; + Mobile.LogoutMap = Facet; + } + else + { + Mobile.Location = Location; + Mobile.Map = Facet; + } + } + + public void Update() + { + m_Expire = DateTime.UtcNow + TimeSpan.FromMinutes(30.0); + + if (Mobile.Map == Map.Internal) + { + Facet = Mobile.LogoutMap; + Location = Mobile.LogoutLocation; + } + else + { + Facet = Mobile.Map; + Location = Mobile.Location; + } + } + } + + private class ExitTeleporter : Item + { + private List m_Entries; + + public ExitTeleporter() : base(0x1822) + { + m_Entries = new List(); + + Hue = 0x482; + Movable = false; + } + + public ExitTeleporter(Serial serial) : base(serial) + { + } + + public override string DefaultName => "return teleporter"; + + public void Register(Mobile mob) + { + var entry = Find(mob); + + if (entry != null) + { + entry.Update(); + return; + } + + m_Entries.Add(new ReturnEntry(mob)); + } + + private ReturnEntry Find(Mobile mob) + { + for (var i = 0; i < m_Entries.Count; ++i) + { + var entry = m_Entries[i]; + + if (entry.Mobile == mob) + return entry; + if (entry.Expired) + m_Entries.RemoveAt(i--); + } + + return null; + } + + public override bool OnMoveOver(Mobile m) + { + if (!base.OnMoveOver(m)) + return false; + + var entry = Find(m); + + if (entry != null) + { + entry.Return(); + + Effects.PlaySound(GetWorldLocation(), Map, 0x1FE); + Effects.PlaySound(m.Location, m.Map, 0x1FE); + + m_Entries.Remove(entry); + + return false; + } + + m.SendLocalizedMessage(1049383); // The teleporter doesn't seem to work for you. + return true; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + writer.WriteEncodedInt(m_Entries.Count); + + for (var i = 0; i < m_Entries.Count; ++i) + { + var entry = m_Entries[i]; + + writer.Write(entry.Mobile); + writer.Write(entry.Location); + writer.Write(entry.Facet); + + if (entry.Expired) + m_Entries.RemoveAt(i--); + } + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + var count = reader.ReadEncodedInt(); + + m_Entries = new List(count); + + for (var i = 0; i < count; ++i) + { + var mob = reader.ReadMobile(); + var loc = reader.ReadPoint3D(); + var map = reader.ReadMap(); + + m_Entries.Add(new ReturnEntry(mob, loc, map)); + } + + break; + } + } + } + } + + private class ArenaMoongate : ConfirmationMoongate + { + private readonly ExitTeleporter m_Teleporter; + + public ArenaMoongate(Point3D target, Map map, ExitTeleporter tp) : base(target, map) + { + m_Teleporter = tp; + + ItemID = 0x1FD4; + Dispellable = false; + + GumpWidth = 300; + GumpHeight = 150; + MessageColor = 0xFFC000; + MessageString = "Are you sure you wish to spectate this duel?"; + TitleColor = 0x7800; + TitleNumber = 1062051; // Gate Warning + + Timer.DelayCall(TimeSpan.FromSeconds(10.0), Delete); + } + + public ArenaMoongate(Serial serial) : base(serial) + { + } + + public override string DefaultName => "spectator moongate"; + + public override void CheckGate(Mobile m, int range) + { + if (CheckCombat(m)) + m.SendMessage( + 0x22, + "You have recently been in combat with another player and cannot use this moongate." + ); + else + base.CheckGate(m, range); + } + + public override void UseGate(Mobile m) + { + if (CheckCombat(m)) + { + m.SendMessage( + 0x22, + "You have recently been in combat with another player and cannot use this moongate." + ); + } + else + { + if (m_Teleporter?.Deleted == false) + m_Teleporter.Register(m); + + base.UseGate(m); + } + } + + public void Appear(Point3D loc, Map map) + { + Effects.PlaySound(loc, map, 0x20E); + MoveToWorld(loc, map); + } + + 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(); + + Delete(); + } + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/DuelTeleporterAddon.cs b/Projects/UOContent/Engines/ConPVP/DuelTeleporterAddon.cs index 524642320..e7d7d6a15 100644 --- a/Projects/UOContent/Engines/ConPVP/DuelTeleporterAddon.cs +++ b/Projects/UOContent/Engines/ConPVP/DuelTeleporterAddon.cs @@ -1,89 +1,89 @@ -using Server.Items; - -namespace Server.Engines.ConPVP -{ - public enum DuelTeleporterType - { - Squares = 6095, - Buds = 6104, - Flowers = 6113, - Spikes = 6122, - Arrows = 6140, - Links = 6149 - } - - public class DuelTeleporterAddon : BaseAddon - { - [Constructible] - public DuelTeleporterAddon(DuelTeleporterType type = DuelTeleporterType.Squares) - { - int itemID = (int)type; - - AddComponent(new AddonComponent(itemID + 0), -1, -1, 5); - AddComponent(new AddonComponent(itemID + 1), -1, 0, 5); - AddComponent(new AddonComponent(itemID + 2), 0, -1, 5); - AddComponent(new AddonComponent(itemID + 3), -1, +1, 5); - AddComponent(new AddonComponent(itemID + 4), 0, 0, 5); - AddComponent(new AddonComponent(itemID + 5), +1, -1, 5); - AddComponent(new AddonComponent(itemID + 6), 0, +1, 5); - AddComponent(new AddonComponent(itemID + 7), +1, 0, 5); - AddComponent(new AddonComponent(itemID + 8), +1, +1, 5); - - AddComponent(new AddonComponent(0x759), -2, -2, 0); - AddComponent(new AddonComponent(0x75A), +2, +2, 0); - AddComponent(new AddonComponent(0x75B), -2, +2, 0); - AddComponent(new AddonComponent(0x75C), +2, -2, 0); - - AddComponent(new AddonComponent(0x751), -1, +2, 0); - AddComponent(new AddonComponent(0x751), 0, +2, 0); - AddComponent(new AddonComponent(0x751), +1, +2, 0); - - AddComponent(new AddonComponent(0x752), +2, -1, 0); - AddComponent(new AddonComponent(0x752), +2, 0, 0); - AddComponent(new AddonComponent(0x752), +2, +1, 0); - - AddComponent(new AddonComponent(0x753), -1, -2, 0); - AddComponent(new AddonComponent(0x753), 0, -2, 0); - AddComponent(new AddonComponent(0x753), +1, -2, 0); - - AddComponent(new AddonComponent(0x754), -2, -1, 0); - AddComponent(new AddonComponent(0x754), -2, 0, 0); - AddComponent(new AddonComponent(0x754), -2, +1, 0); - } - - public DuelTeleporterAddon(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public DuelTeleporterType Type - { - get - { - if (Components.Count > 0) - return (DuelTeleporterType)Components[0].ItemID; - - return DuelTeleporterType.Squares; - } - set - { - for (int i = 0; i < Components.Count && i < 9; ++i) - Components[i].ItemID = i + (int)value; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using Server.Items; + +namespace Server.Engines.ConPVP +{ + public enum DuelTeleporterType + { + Squares = 6095, + Buds = 6104, + Flowers = 6113, + Spikes = 6122, + Arrows = 6140, + Links = 6149 + } + + public class DuelTeleporterAddon : BaseAddon + { + [Constructible] + public DuelTeleporterAddon(DuelTeleporterType type = DuelTeleporterType.Squares) + { + var itemID = (int)type; + + AddComponent(new AddonComponent(itemID + 0), -1, -1, 5); + AddComponent(new AddonComponent(itemID + 1), -1, 0, 5); + AddComponent(new AddonComponent(itemID + 2), 0, -1, 5); + AddComponent(new AddonComponent(itemID + 3), -1, +1, 5); + AddComponent(new AddonComponent(itemID + 4), 0, 0, 5); + AddComponent(new AddonComponent(itemID + 5), +1, -1, 5); + AddComponent(new AddonComponent(itemID + 6), 0, +1, 5); + AddComponent(new AddonComponent(itemID + 7), +1, 0, 5); + AddComponent(new AddonComponent(itemID + 8), +1, +1, 5); + + AddComponent(new AddonComponent(0x759), -2, -2, 0); + AddComponent(new AddonComponent(0x75A), +2, +2, 0); + AddComponent(new AddonComponent(0x75B), -2, +2, 0); + AddComponent(new AddonComponent(0x75C), +2, -2, 0); + + AddComponent(new AddonComponent(0x751), -1, +2, 0); + AddComponent(new AddonComponent(0x751), 0, +2, 0); + AddComponent(new AddonComponent(0x751), +1, +2, 0); + + AddComponent(new AddonComponent(0x752), +2, -1, 0); + AddComponent(new AddonComponent(0x752), +2, 0, 0); + AddComponent(new AddonComponent(0x752), +2, +1, 0); + + AddComponent(new AddonComponent(0x753), -1, -2, 0); + AddComponent(new AddonComponent(0x753), 0, -2, 0); + AddComponent(new AddonComponent(0x753), +1, -2, 0); + + AddComponent(new AddonComponent(0x754), -2, -1, 0); + AddComponent(new AddonComponent(0x754), -2, 0, 0); + AddComponent(new AddonComponent(0x754), -2, +1, 0); + } + + public DuelTeleporterAddon(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public DuelTeleporterType Type + { + get + { + if (Components.Count > 0) + return (DuelTeleporterType)Components[0].ItemID; + + return DuelTeleporterType.Squares; + } + set + { + for (var i = 0; i < Components.Count && i < 9; ++i) + Components[i].ItemID = i + (int)value; + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Games/BombingRun.cs b/Projects/UOContent/Engines/ConPVP/Games/BombingRun.cs index e07ada51a..34427529d 100644 --- a/Projects/UOContent/Engines/ConPVP/Games/BombingRun.cs +++ b/Projects/UOContent/Engines/ConPVP/Games/BombingRun.cs @@ -1,1770 +1,1807 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Server.Gumps; -using Server.Items; -using Server.Mobiles; -using Server.Network; -using Server.Targeting; - -namespace Server.Engines.ConPVP -{ - public class BRBomb : Item - { - private bool m_Flying; - - private readonly BRGame m_Game; - - private readonly List m_Helpers; - - private readonly Point3DList m_Path = new Point3DList(); - private int m_PathIdx; - private readonly EffectTimer m_Timer; - - public BRBomb(BRGame game) : base(0x103C) // 0x103C = bread, 0x1042 = pie, 0x1364 = rock, 0x13a8 = pillow, 0x2256 = bagball - { - Movable = false; - Hue = 0x35; - - m_Game = game; - - m_Helpers = new List(); - - m_Timer = new EffectTimer(this); - m_Timer.Start(); - } - - public BRBomb(Serial serial) : base(serial) - { - } - - public override string DefaultName => "da bomb"; - - public Mobile Thrower { get; private set; } - - private Mobile FindOwner(IEntity parent) - { - if (parent is Item item) - return item.RootParent as Mobile; - - if (parent is Mobile mobile) - return mobile; - - return null; - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - break; - } - } - - Timer.DelayCall(Delete); // delete this after the world loads - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void OnAdded(IEntity parent) - { - base.OnAdded(parent); - - Mobile mob = FindOwner(parent); - - if (mob != null) - mob.SolidHueOverride = 0x0499; - } - - public override void OnRemoved(IEntity parent) - { - base.OnRemoved(parent); - - Mobile mob = FindOwner(parent); - - if (mob != null && m_Game != null) - mob.SolidHueOverride = m_Game.GetColor(mob); - } - - public void DropTo(Mobile mob, Mobile killer) - { - if (mob?.Deleted == false) - MoveToWorld(mob.Location, mob.Map); - else if (killer?.Deleted == false) - MoveToWorld(killer.Location, killer.Map); - else - m_Game?.ReturnBomb(); - } - - public override bool OnMoveOver(Mobile m) - { - if (m_Flying || !Visible || m_Game == null || m?.Alive != true) - return true; - - BRTeamInfo useTeam = m_Game.GetTeamInfo(m); - return useTeam == null || TakeBomb(m, useTeam, "picked up"); - } - - public override void OnLocationChange(Point3D oldLocation) - { - base.OnLocationChange(oldLocation); - - if (m_Flying || !Visible || m_Game == null || Parent != null) - return; - - IPooledEnumerable eable = GetClientsInRange(0); - foreach (NetState ns in eable) - { - Mobile m = ns.Mobile; - - if (m?.Player != true || !m.Alive) - continue; - - BRTeamInfo useTeam = m_Game.GetTeamInfo(m); - if (useTeam != null) - TakeBomb(m, useTeam, "got"); - } - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Timer?.Stop(); - } - - public override void OnDoubleClick(Mobile m) - { - if (m_Game == null || !Visible || m?.Alive != true) - return; - - if (!m_Flying && IsChildOf(m.Backpack)) - m.Target = new BombTarget(this, m); - else if (Parent == null) - if (m.InRange(Location, 1) && m.Location.Z != Z) - { - BRTeamInfo useTeam = m_Game.GetTeamInfo(m); - if (useTeam == null) - return; - - TakeBomb(m, useTeam, "grabbed"); - } - } - - private bool OnBombTarget(Mobile from, object obj) - { - if (m_Game == null) - return true; - - if (!IsChildOf(from.Backpack)) - return true; - - // don't let them throw it to themselves - if (obj == from) - return false; - - if (!(obj is IPoint3D)) - return false; - - Point3D pt = new Point3D((IPoint3D)obj); - - if (obj is Mobile) - pt.Z += 10; - else if (obj is Item item) - pt.Z += item.ItemData.CalcHeight + 1; - - m_Flying = true; - Visible = false; - Thrower = from; - MoveToWorld(GetWorldLocation(), from.Map); - - BeginFlight(pt); - return true; - } - - private void HitObject(Point3D ballLoc, int objZ, int objHeight) - { - DoAnim(GetWorldLocation(), ballLoc, Map); - MoveToWorld(ballLoc); - - m_Path.Clear(); - m_PathIdx = 0; - - Timer.DelayCall(TimeSpan.FromSeconds(0.05), ContinueFlight); - } - - private bool CheckCatch(Mobile m, Point3D myLoc) - { - if (m?.Alive != true || !m.Player || m_Game == null) - return false; - - if (m_Game.GetTeamInfo(m) == null) - return false; - - int zdiff = myLoc.Z - m.Z; - - return zdiff >= 0 && (zdiff < 12 || zdiff < 16 && Utility.RandomBool()); - } - - private void DoAnim(Point3D start, Point3D end, Map map) - { - Effects.SendMovingEffect(new Entity(Serial.Zero, start, map), new Entity(Serial.Zero, end, map), - ItemID, 15, 0, false, false, Hue); - } - - private void DoCatch(Mobile m) - { - m_Flying = false; - Visible = true; - - if (m?.Alive != true || !m.Player || m_Game == null) - return; - - BRTeamInfo useTeam = m_Game.GetTeamInfo(m); - - if (useTeam == null) - return; - - DoAnim(GetWorldLocation(), m.Location, m.Map); - - string verb = "caught"; - - if (Thrower != null && m_Game.GetTeamInfo(Thrower) != useTeam) - verb = "intercepted"; - - if (!TakeBomb(m, useTeam, verb)) - MoveToWorld(m.Location, m.Map); - } - - private void BeginFlight(Point3D dest) - { - Point3D org = GetWorldLocation(); - - org.Z += 10; // always add 10 at the start cause we're coming from a mobile's eye level - - /*if (org.X > dest.X || ( org.X == dest.X && org.Y > dest.Y ) || ( org.X == dest.X && org.Y == dest.Y && org.Z > dest.Z )) - { - Point3D swap = org; - org = dest; - dest = swap; - }*/ - - List list = new List(); - - int xd = dest.X - org.X; - int yd = dest.Y - org.Y; - int zd = dest.Z - org.Z; - double dist2d = Math.Sqrt(xd * xd + yd * yd); - double dist3d = zd == 0 ? dist2d : Math.Sqrt(dist2d * dist2d + zd * zd); - - double rise = yd / dist3d; - double run = xd / dist3d; - double zslp = zd / dist3d; - - double x = org.X; - double y = org.Y; - double z = org.Z; - while (Utility.NumberBetween(x, dest.X, org.X, 0.5) && Utility.NumberBetween(y, dest.Y, org.Y, 0.5) && - Utility.NumberBetween(z, dest.Z, org.Z, 0.5)) - { - int ix = (int)Math.Round(x); - int iy = (int)Math.Round(y); - int iz = (int)Math.Round(z); - - if (list.Count > 0) - { - Point3D p = list[^1]; - - if (p.X != ix || p.Y != iy || p.Z != iz) - list.Add(new Point3D(ix, iy, iz)); - } - else - { - list.Add(new Point3D(ix, iy, iz)); - } - - x += run; - y += rise; - z += zslp; - } - - if (list.Count > 0 && list[^1] != dest) - list.Add(dest); - - /*if (dist3d > 4 && ( dest.X != org.X || dest.Y != org.Y )) - { - int count = list.Count; - int i; - int climb = count / 2; - if (climb > 3) - climb = 3; - - for ( i = 0; i < climb; i++ ) - { - p = ((Point3D)list[i]); - p.Z += (i+1) * 4; - list[i] = p; - } - - for ( ; i < count - climb; i++ ) - { - p = ((Point3D)list[i]); - p.Z += 16; - list[i] = p; - } - - for ( i = climb; i > 0; i-- ) - { - p = ((Point3D)list[i]); - p.Z += i * 4; - list[i] = p; - } - }*/ - - if (dist2d > 1) - { - int count = list.Count; - double height = count * 2 * (Utility.RandomDouble() * 0.40 + 0.10); // 10 - 50% - double coeff = -height / (count * count / 4.0); - - for (int i = 0; i < count; i++) - { - Point3D p = list[i]; - - int xp = i - count / 2; - - p.Z += (int)Math.Ceiling(coeff * xp * xp + height); - - list[i] = p; - } - } - - m_Path.Clear(); - for (int i = 0; i < list.Count; i++) - m_Path.Add(list[i]); - - m_PathIdx = 0; - - ContinueFlight(); - } - - private void ContinueFlight() - { - int height; - bool found = false; - - if (m_PathIdx < m_Path.Count && Map?.Tiles != null && Map != Map.Internal) - { - int pathCheckEnd = m_PathIdx + 5; - - if (m_Path.Count < pathCheckEnd) - pathCheckEnd = m_Path.Count; - - Visible = false; - - if (m_PathIdx > 0) // move to the next location - MoveToWorld(m_Path[m_PathIdx - 1]); - - Point3D pTop = new Point3D(GetWorldLocation()), pBottom = new Point3D(m_Path[pathCheckEnd - 1]); - Utility.FixPoints(ref pTop, ref pBottom); - - for (int i = m_PathIdx; i < pathCheckEnd; i++) - { - Point3D point = m_Path[i]; - - LandTile landTile = Map.Tiles.GetLandTile(point.X, point.Y); - int landZ = 0, landAvg = 0, landTop = 0; - Map.GetAverageZ(point.X, point.Y, ref landZ, ref landAvg, ref landTop); - - if (landZ <= point.Z && landTop >= point.Z && !landTile.Ignored) - { - HitObject(point, landTop, 0); - return; - } - - StaticTile[] statics = Map.Tiles.GetStaticTiles(point.X, point.Y, true); - - if (landTile.ID == 0x244 && statics.Length == 0) // 0x244 = invalid land tile - { - IPooledEnumerable eable = Map.GetItemsInRange(point, 0); - - bool empty = eable.All(item => item == this); - - eable.Free(); - - if (empty) - { - HitObject(point, landTop, 0); - return; - } - } - - for (int j = 0; j < statics.Length; j++) - { - StaticTile t = statics[j]; - - ItemData id = TileData.ItemTable[t.ID & TileData.MaxItemValue]; - height = id.CalcHeight; - - if (t.Z <= point.Z && t.Z + height >= point.Z && - (id.Flags & (TileFlag.Impassable | TileFlag.Wall | TileFlag.NoShoot)) != 0) - { - if (i > m_PathIdx) - point = m_Path[i - 1]; - else - point = GetWorldLocation(); - HitObject(point, t.Z, height); - return; - } - } - } - - Rectangle2D rect = new Rectangle2D(pTop.X, pTop.Y, pBottom.X - pTop.X + 1, pBottom.Y - pTop.Y + 1); - - IPooledEnumerable area = Map.GetItemsInBounds(rect); - foreach (Item i in area) - { - if (i == this || i.ItemID >= 0x4000) - continue; - - if (i is BRGoal) - { - height = 17; - } - else if (i is Blocker) - { - height = 20; - } - else - { - ItemData id = i.ItemData; - if ((id.Flags & (TileFlag.Impassable | TileFlag.Wall | TileFlag.NoShoot)) == 0) - continue; - height = id.CalcHeight; - } - - Point3D point = i.Location; - Point3D loc = i.Location; - for (int j = m_PathIdx; j < pathCheckEnd; j++) - { - point = m_Path[j]; - - if (loc.X == point.X && loc.Y == point.Y && - (i is Blocker || (loc.Z <= point.Z && loc.Z + height >= point.Z))) - { - found = true; - if (j > m_PathIdx) - point = m_Path[j - 1]; - else - point = GetWorldLocation(); - break; - } - } - - if (!found) - continue; - - area.Free(); - if (i is BRGoal goal) - { - Point3D oldLoc = new Point3D(GetWorldLocation()); - if (CheckScore(goal, Thrower, 3)) - DoAnim(oldLoc, point, Map); - else - HitObject(point, loc.Z, height); - } - else - { - HitObject(point, loc.Z, height); - } - - return; - } - - area.Free(); - - IPooledEnumerable clients = Map.GetClientsInBounds(rect); - foreach (NetState ns in clients) - { - Mobile m = ns.Mobile; - - if (m == null || m == Thrower) - continue; - - Point3D point; - Point3D loc = m.Location; - - for (int j = m_PathIdx; j < pathCheckEnd && !found; j++) - { - point = m_Path[j]; - - if (loc.X == point.X && loc.Y == point.Y && - loc.Z <= point.Z && loc.Z + 16 >= point.Z) - found = CheckCatch(m, point); - } - - if (!found) - continue; - - clients.Free(); - - // TODO: probably need to change this a lot... - DoCatch(m); - - return; - } - - clients.Free(); - - m_PathIdx = pathCheckEnd; - - if (m_PathIdx > 0 && m_PathIdx - 1 < m_Path.Count) - DoAnim(GetWorldLocation(), m_Path[m_PathIdx - 1], Map); - - Timer.DelayCall(TimeSpan.FromSeconds(0.1), ContinueFlight); - } - else - { - if (m_PathIdx > 0 && m_PathIdx - 1 < m_Path.Count) - MoveToWorld(m_Path[m_PathIdx - 1]); - else if (m_Path.Count > 0) - MoveToWorld(m_Path.Last); - - int myZ = Map?.GetAverageZ(X, Y) ?? 0; - - StaticTile[] statics = Map?.Tiles?.GetStaticTiles(X, Y, true); - - if (statics != null) - for (int j = 0; j < statics.Length; j++) - { - StaticTile t = statics[j]; - - ItemData id = TileData.ItemTable[t.ID & TileData.MaxItemValue]; - height = id.CalcHeight; - - if (t.Z + height > myZ && t.Z + height <= Z) - myZ = t.Z + height; - } - - IPooledEnumerable eable = GetItemsInRange(0); - foreach (Item item in eable) - if (item.Visible && item != this) - { - height = item.ItemData.CalcHeight; - if (item.Z + height > myZ && item.Z + height <= Z) - myZ = item.Z + height; - } - - eable.Free(); - - Z = myZ; - m_Flying = false; - Visible = true; - - m_Path.Clear(); - m_PathIdx = 0; - } - } - - public bool CheckScore(BRGoal goal, Mobile m, int points) - { - if (m_Game == null || m == null || goal == null) - return false; - - BRTeamInfo team = m_Game.GetTeamInfo(m); - if (team == null || goal.Team == null || team == goal.Team) - return false; - - if (points > 3) - m_Game.Alert("Touchdown {0} ({1})!", team.Name, m.Name); - else - m_Game.Alert("Field goal {0} ({1})!", team.Name, m.Name); - - for (int i = m_Helpers.Count - 1; i >= 0; i--) - { - Mobile mob = m_Helpers[i]; - - BRPlayerInfo pi = team[mob]; - if (pi != null) - { - if (mob == m) - pi.Captures += points; - - pi.Score += points + 1; - - points /= 2; - } - } - - m_Game.ReturnBomb(); - - m_Flying = false; - Visible = true; - m_Path.Clear(); - m_PathIdx = 0; - - Target.Cancel(m); - - return true; - } - - private bool TakeBomb(Mobile m, BRTeamInfo team, string verb) - { - if (!m.Player || !m.Alive || m.NetState == null) - return false; - - if (m.PlaceInBackpack(this)) - { - m.RevealingAction(); - - m.LocalOverheadMessage(MessageType.Regular, 0x59, false, "You got the bomb!"); - m_Game.Alert("{1} ({2}) {0} the bomb!", verb, m.Name, team.Name); - - m.Target = new BombTarget(this, m); - - if (m_Helpers.Contains(m)) - m_Helpers.Remove(m); - - if (m_Helpers.Count > 0) - { - Mobile last = m_Helpers[0]; - - if (m_Game.GetTeamInfo(last) != team) - m_Helpers.Clear(); - } - - m_Helpers.Add(m); - - return true; - } - - return false; - } - - private class EffectTimer : Timer - { - private readonly BRBomb m_Bomb; - private int m_Count; - - public EffectTimer(BRBomb bomb) : base(TimeSpan.Zero, TimeSpan.FromSeconds(1.0)) - { - m_Bomb = bomb; - m_Count = 0; - Priority = TimerPriority.FiftyMS; - } - - protected override void OnTick() - { - if (m_Bomb.Parent == null && m_Bomb.m_Game?.Controller != null) - { - if (!m_Bomb.m_Flying && m_Bomb.Map != Map.Internal) - Effects.SendLocationEffect(m_Bomb.GetWorldLocation(), m_Bomb.Map, 0x377A, 16, 10, m_Bomb.Hue, 0); - - if (m_Bomb.Location != m_Bomb.m_Game.Controller.BombHome) - { - if (++m_Count >= 30) - { - m_Bomb.m_Game.ReturnBomb(); - m_Bomb.m_Game.Alert("The bomb has been returned to it's starting point."); - - m_Count = 0; - m_Bomb.m_Helpers.Clear(); - } - } - else - { - m_Count = 0; - } - } - else - { - m_Count = 0; - } - } - } - - private class BombTarget : Target - { - private readonly BRBomb m_Bomb; - private readonly Mobile m_Mob; - private bool m_Resend = true; - - public BombTarget(BRBomb bomb, Mobile from) : base(10, true, TargetFlags.None) - { - CheckLOS = false; - - m_Bomb = bomb; - m_Mob = from; - - m_Mob.SendMessage(0x26, "Where do you want to throw it?"); - } - - protected override void OnTarget(Mobile from, object targeted) - { - m_Resend = !m_Bomb.OnBombTarget(from, targeted); - } - - protected override void OnTargetUntargetable(Mobile from, object targeted) - { - m_Resend = !m_Bomb.OnBombTarget(from, targeted); - } - - protected override void OnTargetFinish(Mobile from) - { - base.OnTargetFinish(from); - - // has to be delayed in case some other target canceled us... - if (m_Resend) - Timer.DelayCall(ResendBombTarget); - } - - private void ResendBombTarget() - { - // Make sure they still have the bomb, then give them the target back - if (m_Bomb?.Deleted == false && m_Mob?.Deleted == false && m_Mob.Alive && m_Bomb.IsChildOf(m_Mob)) - m_Mob.Target = new BombTarget(m_Bomb, m_Mob); - } - } - } - - public class BRGoal : BaseAddon - { - private bool m_North; - - private BRTeamInfo m_Team; - - [Constructible] - public BRGoal() - { - ItemID = 0x51D; - Hue = 0x84C; - Visible = true; - - Remake(); - } - - public BRGoal(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool North - { - get => m_North; - set - { - m_North = value; - Remake(); - } - } - - public override string DefaultName => "Bombing Run Goal"; - - public override bool ShareHue => false; - - public BRTeamInfo Team - { - get => m_Team; - set - { - m_Team = value; - if (m_Team != null && m_Team.Color != 0) - Hue = m_Team.Color; - else - Hue = 0x84C; - } - } - - private static AddonComponent SetHue(AddonComponent ac, int hue) - { - ac.Hue = hue; - return ac; - } - - private void Remake() - { - foreach (AddonComponent ac in Components) - { - ac.Addon = null; - ac.Delete(); - } - - Components.Clear(); - - // stairs - AddComponent(new AddonComponent(0x74D), -1, +1, -5); - AddComponent(new AddonComponent(0x71F), 0, +1, -5); - AddComponent(new AddonComponent(0x74B), +1, +1, -5); - AddComponent(new AddonComponent(0x736), +1, 0, -5); - AddComponent(new AddonComponent(0x74C), +1, -1, -5); - AddComponent(new AddonComponent(0x737), 0, -1, -5); - AddComponent(new AddonComponent(0x74A), -1, -1, -5); - AddComponent(new AddonComponent(0x749), -1, 0, -5); - - // Center Sparkle - AddComponent(new AddonComponent(0x375A), 0, 0, -1); - - if (!m_North) - { - // Pillars - AddComponent(new AddonComponent(0x0CE), 0, +1, -2); - AddComponent(new AddonComponent(0x0CC), 0, -1, -2); - AddComponent(new AddonComponent(0x0D0), 0, 0, -2); - - // Yellow parts - AddComponent(SetHue(new AddonComponent(0x0DF), 0x499), 0, +1, 7); - AddComponent(SetHue(new AddonComponent(0x0DF), 0x499), 0, 0, 16); - AddComponent(SetHue(new AddonComponent(0x0DF), 0x499), 0, -1, 7); - - // Blue Sparkles - AddComponent(SetHue(new AddonComponent(0x377A), 0x84C), 0, +1, 12); - AddComponent(SetHue(new AddonComponent(0x377A), 0x84C), 0, +1, -1); - AddComponent(SetHue(new AddonComponent(0x377A), 0x84C), 0, -1, 12); - AddComponent(SetHue(new AddonComponent(0x377A), 0x84C), 0, -1, -1); - } - else - { - // Pillars - AddComponent(new AddonComponent(0x0CF), +1, 0, -2); - AddComponent(new AddonComponent(0x0CC), -1, 0, -2); - AddComponent(new AddonComponent(0x0D1), 0, 0, -2); - - // Yellow parts - AddComponent(SetHue(new AddonComponent(0x0DF), 0x499), +1, 0, 7); - AddComponent(SetHue(new AddonComponent(0x0DF), 0x499), 0, 0, 16); - AddComponent(SetHue(new AddonComponent(0x0DF), 0x499), -1, 0, 7); - - // Blue Sparkles - AddComponent(SetHue(new AddonComponent(0x377A), 0x84C), +1, 0, 12); - AddComponent(SetHue(new AddonComponent(0x377A), 0x84C), +1, 0, -1); - AddComponent(SetHue(new AddonComponent(0x377A), 0x84C), -1, 0, 12); - AddComponent(SetHue(new AddonComponent(0x377A), 0x84C), -1, 0, -1); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(m_North); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_North = reader.ReadBool(); - goto case 0; - } - case 0: - { - break; - } - } - - Hue = 0x84C; - } - - public override bool OnMoveOver(Mobile m) - { - if (!Visible) - return true; - - if (m?.Player != true || !m.Alive || m.Backpack == null || m_Team?.Game == null) - return true; - - if (!base.OnMoveOver(m)) - return false; - - if (m_Team != null && m_Team.Color != 0) - Hue = m_Team.Color; - else - Hue = 0x84C; - - m.Backpack.FindItemByType()?.CheckScore(this, m, 7); - return true; - } - } - - public sealed class BRBoard : Item - { - public BRTeamInfo m_TeamInfo; - - [Constructible] - public BRBoard() - : base(7774) => - Movable = false; - - public BRBoard(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "Scoreboard"; - - public override void OnDoubleClick(Mobile from) - { - if (m_TeamInfo?.Game != null) - { - from.CloseGump(); - from.SendGump(new BRBoardGump(from, m_TeamInfo.Game)); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BRBoardGump : Gump - { - private const int LabelColor32 = 0xFFFFFF; - private const int BlackColor32 = 0x000000; - - // private BRGame m_Game; - - public BRBoardGump(Mobile mob, BRGame game, BRTeamInfo section = null) : base(60, 60) - { - // m_Game = game; - - BRTeamInfo ourTeam = game.GetTeamInfo(mob); - - List entries = new List(); - int total = 0; - - if (section == null) - { - for (int i = 0; i < game.Context.Participants.Count; ++i) - { - BRTeamInfo teamInfo = game.Controller.TeamInfo[i % game.Controller.TeamInfo.Length]; - - if (teamInfo == null) - continue; - - entries.Add(teamInfo); - } - - total = entries.Count; - } - else - foreach (BRPlayerInfo player in section.Players.Values) - if (player.Score > 0) - total++; - - entries.Sort(); - - int height = 0; - - if (section == null) - height = 73 + entries.Count * 75 + 28; - - Closable = false; - - AddPage(0); - - AddBackground(1, 1, 398, height, 3600); - - AddImageTiled(16, 15, 369, height - 29, 3604); - - for (int i = 0; i < total; i += 1) - AddImageTiled(22, 58 + i * 75, 357, 70, 0x2430); - - AddAlphaRegion(16, 15, 369, height - 29); - - AddImage(215, -45, 0xEE40); - // AddImage( 330, 141, 0x8BA ); - - AddBorderedText(22, 22, 294, 20, Center("BR Scoreboard"), LabelColor32, BlackColor32); - - AddImageTiled(32, 50, 264, 1, 9107); - AddImageTiled(42, 52, 264, 1, 9157); - - if (section == null) - for (int i = 0; i < entries.Count; ++i) - { - BRTeamInfo teamInfo = entries[i]; - - AddImage(30, 70 + i * 75, 10152); - AddImage(30, 85 + i * 75, 10151); - AddImage(30, 100 + i * 75, 10151); - AddImage(30, 106 + i * 75, 10154); - - AddImage(24, 60 + i * 75, teamInfo == ourTeam ? 9730 : 9727, teamInfo.Color - 1); - - int nameColor = LabelColor32; - int borderColor = BlackColor32; - - switch (teamInfo.Color) - { - case 0x47E: - nameColor = 0xFFFFFF; - break; - - case 0x4F2: - nameColor = 0x3399FF; - break; - - case 0x4F7: - nameColor = 0x33FF33; - break; - - case 0x4FC: - nameColor = 0xFF00FF; - break; - - case 0x021: - nameColor = 0xFF3333; - break; - - case 0x01A: - nameColor = 0xFF66FF; - break; - - case 0x455: - nameColor = 0x333333; - borderColor = 0xFFFFFF; - break; - } - - AddBorderedText(60, 65 + i * 75, 250, 20, $"{LadderGump.Rank(1 + i)}: {teamInfo.Name}", nameColor, - borderColor); - - AddBorderedText(50 + 10, 85 + i * 75, 100, 20, "Score:", 0xFFC000, BlackColor32); - AddBorderedText(50 + 15, 105 + i * 75, 100, 20, teamInfo.Score.ToString("N0"), 0xFFC000, BlackColor32); - - AddBorderedText(110 + 10, 85 + i * 75, 100, 20, "Kills:", 0xFFC000, BlackColor32); - AddBorderedText(110 + 15, 105 + i * 75, 100, 20, teamInfo.Kills.ToString("N0"), 0xFFC000, BlackColor32); - - AddBorderedText(160 + 10, 85 + i * 75, 100, 20, "Points:", 0xFFC000, BlackColor32); - AddBorderedText(160 + 15, 105 + i * 75, 100, 20, teamInfo.Captures.ToString("N0"), 0xFFC000, - BlackColor32); - - BRPlayerInfo pl = teamInfo.Leader; - - AddBorderedText(235 + 10, 85 + i * 75, 250, 20, "Leader:", 0xFFC000, BlackColor32); - - if (pl != null) - AddBorderedText(235 + 15, 105 + i * 75, 250, 20, pl.Player.Name, 0xFFC000, BlackColor32); - } - - AddButton(314, height - 42, 247, 248, 1); - } - - public string Center(string text) => $"
{text}
"; - - public string Color(string text, int color) => $"{text}"; - - private void AddBorderedText(int x, int y, int width, int height, string text, int color, int borderColor) - { - AddColoredText(x - 1, y - 1, width, height, text, borderColor); - AddColoredText(x - 1, y + 1, width, height, text, borderColor); - AddColoredText(x + 1, y - 1, width, height, text, borderColor); - AddColoredText(x + 1, y + 1, width, height, text, borderColor); - AddColoredText(x, y, width, height, text, color); - } - - private void AddColoredText(int x, int y, int width, int height, string text, int color) - { - if (color == 0) - AddHtml(x, y, width, height, text); - else - AddHtml(x, y, width, height, Color(text, color)); - } - } - - public sealed class BRPlayerInfo : IRankedCTF, IComparable - { - private int m_Captures; - - private int m_Kills; - - private int m_Score; - private readonly BRTeamInfo m_TeamInfo; - - public BRPlayerInfo(BRTeamInfo teamInfo, Mobile player) - { - m_TeamInfo = teamInfo; - Player = player; - } - - public Mobile Player { get; } - - public int CompareTo(BRPlayerInfo pi) - { - int res = pi.Captures.CompareTo(Captures); - if (res != 0) - return res; - - res = pi.Score.CompareTo(Score); - - if (res == 0) - res = pi.Kills.CompareTo(Kills); - - return res; - } - - public string Name => Player.Name; - - public int Kills - { - get => m_Kills; - set - { - m_TeamInfo.Kills += value - m_Kills; - m_Kills = value; - } - } - - public int Captures - { - get => m_Captures; - set - { - m_TeamInfo.Captures += value - m_Captures; - m_Captures = value; - } - } - - public int Score - { - get => m_Score; - set - { - m_TeamInfo.Score += value - m_Score; - m_Score = value; - - if (m_TeamInfo.Leader == null || m_Score > m_TeamInfo.Leader.Score) - m_TeamInfo.Leader = this; - } - } - } - - [PropertyObject] - public sealed class BRTeamInfo : IRankedCTF, IComparable - { - private BRGoal m_Goal; - - public BRTeamInfo(int teamID) - { - TeamID = teamID; - Players = new Dictionary(); - } - - public BRTeamInfo(int teamID, IGenericReader ip) - { - TeamID = teamID; - Players = new Dictionary(); - - int version = ip.ReadEncodedInt(); - - switch (version) - { - case 0: - { - Board = ip.ReadItem() as BRBoard; - TeamName = ip.ReadString(); - Color = ip.ReadEncodedInt(); - m_Goal = ip.ReadItem() as BRGoal; - break; - } - } - } - - public BRGame Game { get; set; } - - public int TeamID { get; } - - public BRPlayerInfo Leader { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public BRBoard Board { get; set; } - - public Dictionary Players { get; } - - public BRPlayerInfo this[Mobile mob] - { - get - { - if (mob == null) - return null; - - if (!Players.TryGetValue(mob, out BRPlayerInfo val)) - Players[mob] = val = new BRPlayerInfo(this, mob); - - return val; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Color { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public string TeamName { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public BRGoal Goal - { - get => m_Goal; - set - { - m_Goal = value; - if (m_Goal != null) - m_Goal.Team = this; - } - } - - public int CompareTo(BRTeamInfo ti) - { - int res = ti.Captures.CompareTo(Captures); - if (res == 0) - { - res = ti.Score.CompareTo(Score); - - if (res == 0) - res = ti.Kills.CompareTo(Kills); - } - - return res; - } - - public string Name => $"{TeamName} Team"; - - public int Kills { get; set; } - - public int Captures { get; set; } - - public int Score { get; set; } - - public void Reset() - { - Kills = 0; - Captures = 0; - Score = 0; - - Leader = null; - - Players.Clear(); - - if (Board != null) - Board.m_TeamInfo = this; - if (m_Goal != null) - m_Goal.Team = this; - } - - public void Serialize(IGenericWriter op) - { - op.WriteEncodedInt(0); // version - - op.Write(Board); - - op.Write(TeamName); - - op.WriteEncodedInt(Color); - - op.Write(m_Goal); - } - - public override string ToString() - { - if (TeamName != null) - return $"({Name}) ..."; - return "..."; - } - } - - public sealed class BRController : EventController - { - [Constructible] - public BRController() - { - Visible = false; - Movable = false; - - Duration = TimeSpan.FromMinutes(30.0); - - BombHome = Point3D.Zero; - - TeamInfo = new BRTeamInfo[4]; - - for (int i = 0; i < TeamInfo.Length; ++i) - TeamInfo[i] = new BRTeamInfo(i); - } - - public BRController(Serial serial) - : base(serial) - { - } - - public BRTeamInfo[] TeamInfo { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public BRTeamInfo Team1 => TeamInfo[0]; - - [CommandProperty(AccessLevel.GameMaster)] - public BRTeamInfo Team2 => TeamInfo[1]; - - [CommandProperty(AccessLevel.GameMaster)] - public BRTeamInfo Team3 => TeamInfo[2]; - - [CommandProperty(AccessLevel.GameMaster)] - public BRTeamInfo Team4 => TeamInfo[3]; - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan Duration { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D BombHome { get; set; } - - public override string Title => "Bombing Run"; - public override string DefaultName => "Bombing Run Controller"; - - public override string GetTeamName(int teamID) => TeamInfo[teamID % TeamInfo.Length].Name; - - public override EventGame Construct(DuelContext context) => new BRGame(this, context); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(BombHome); - - writer.Write(Duration); - - writer.WriteEncodedInt(TeamInfo.Length); - - for (int i = 0; i < TeamInfo.Length; ++i) - TeamInfo[i].Serialize(writer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - BombHome = reader.ReadPoint3D(); - - Duration = reader.ReadTimeSpan(); - - TeamInfo = new BRTeamInfo[reader.ReadEncodedInt()]; - - for (int i = 0; i < TeamInfo.Length; ++i) - TeamInfo[i] = new BRTeamInfo(i, reader); - - break; - } - } - } - } - - public sealed class BRGame : EventGame - { - private BRBomb m_Bomb; - - private Timer m_FinishTimer; - - private TimerCallback m_UnhideCallback; - - public BRGame(BRController controller, DuelContext context) : base(context) => Controller = controller; - - public BRController Controller { get; } - - public Map Facet - { - get - { - if (m_Context.Arena != null) - return m_Context.Arena.Facet; - - return Controller.Map; - } - } - - public override bool CantDoAnything(Mobile mob) => mob.Backpack?.FindItemByType() != null && GetTeamInfo(mob) != null; - - public void ReturnBomb() - { - if (m_Bomb != null && Controller != null) - { - m_UnhideCallback ??= UnhideBomb; - m_Bomb.Visible = false; - m_Bomb.MoveToWorld(Controller.BombHome, Controller.Map); - Timer.DelayCall(TimeSpan.FromSeconds(Utility.RandomMinMax(5, 15)), m_UnhideCallback); - } - } - - private void UnhideBomb() - { - if (m_Bomb != null) - { - m_Bomb.Visible = true; - m_Bomb.OnLocationChange(m_Bomb.Location); - } - } - - public void Alert(string text) - { - m_Context.m_Tournament?.Alert(text); - - for (int i = 0; i < m_Context.Participants.Count; ++i) - { - Participant p = m_Context.Participants[i]; - - for (int j = 0; j < p.Players.Length; ++j) - if (p.Players[j] != null) - p.Players[j].Mobile.SendMessage(0x35, text); - } - } - - public void Alert(string format, params object[] args) - { - Alert(string.Format(format, args)); - } - - public BRTeamInfo GetTeamInfo(Mobile mob) - { - int teamID = GetTeamID(mob); - - if (teamID >= 0) - return Controller.TeamInfo[teamID % Controller.TeamInfo.Length]; - - return null; - } - - public int GetTeamID(Mobile mob) - { - if (!(mob is PlayerMobile pm)) - return mob is BaseCreature creature ? creature.Team - 1 : -1; - - if (pm.DuelContext == null || pm.DuelContext != m_Context) - return -1; - - if (pm.DuelPlayer?.Eliminated != false) - return -1; - - return pm.DuelContext.Participants.IndexOf(pm.DuelPlayer.Participant); - } - - public int GetColor(Mobile mob) => GetTeamInfo(mob)?.Color ?? -1; - - private void ApplyHues(Participant p, int hueOverride) - { - for (int i = 0; i < p.Players.Length; ++i) - if (p.Players[i] != null) - p.Players[i].Mobile.SolidHueOverride = hueOverride; - } - - public void DelayBounce(TimeSpan ts, Mobile mob, Container corpse) - { - Timer.DelayCall(ts, DelayBounce_Callback, mob, corpse); - } - - private void DelayBounce_Callback(Mobile mob, Container corpse) - { - DuelPlayer dp = (mob as PlayerMobile)?.DuelPlayer; - - m_Context.RemoveAggressions(mob); - - if (dp?.Eliminated == false) - mob.MoveToWorld(m_Context.Arena.GetBaseStartPoint(GetTeamID(mob)), Facet); - else - m_Context.SendOutside(mob); - - m_Context.Refresh(mob, corpse); - DuelContext.Debuff(mob); - DuelContext.CancelSpell(mob); - mob.Frozen = false; - } - - public override bool OnDeath(Mobile mob, Container corpse) - { - Mobile killer = mob.FindMostRecentDamager(false); - - bool hadBomb = false; - - corpse.FindItemsByType(false).ForEach(bomb => - { - hadBomb = true; - bomb.DropTo(mob, killer); - }); - - mob.Backpack?.FindItemsByType(false).ForEach(bomb => - { - hadBomb = true; - bomb.DropTo(mob, killer); - }); - - if (killer?.Player == true) - { - BRTeamInfo teamInfo = GetTeamInfo(killer); - BRTeamInfo victInfo = GetTeamInfo(mob); - - if (teamInfo != null && teamInfo != victInfo) - { - BRPlayerInfo playerInfo = teamInfo[killer]; - - if (playerInfo != null) - { - playerInfo.Kills += 1; - playerInfo.Score += 1; // base frag - - if (hadBomb) - playerInfo.Score += 4; // fragged bomb carrier - } - } - } - - mob.CloseGump(); - mob.SendGump(new BRBoardGump(mob, this)); - - m_Context.Requip(mob, corpse); - DelayBounce(TimeSpan.FromSeconds(30.0), mob, corpse); - - return false; - } - - public override void OnStart() - { - for (int i = 0; i < Controller.TeamInfo.Length; ++i) - { - BRTeamInfo teamInfo = Controller.TeamInfo[i]; - - teamInfo.Game = this; - teamInfo.Reset(); - } - - for (int i = 0; i < m_Context.Participants.Count; ++i) - ApplyHues(m_Context.Participants[i], - Controller.TeamInfo[i % Controller.TeamInfo.Length].Color); - - m_FinishTimer?.Stop(); - - m_Bomb = new BRBomb(this); - ReturnBomb(); - - m_FinishTimer = Timer.DelayCall(Controller.Duration, Finish_Callback); - } - - private void Finish_Callback() - { - List teams = new List(); - - for (int i = 0; i < m_Context.Participants.Count; ++i) - { - BRTeamInfo teamInfo = Controller.TeamInfo[i % Controller.TeamInfo.Length]; - - if (teamInfo != null) - teams.Add(teamInfo); - } - - teams.Sort(); - - Tournament tourney = m_Context.m_Tournament; - - StringBuilder sb = new StringBuilder(); - - if (tourney != null) - { - if (tourney.TourneyType == TourneyType.FreeForAll) - { - sb.Append(m_Context.Participants.Count * tourney.PlayersPerParticipant); - sb.Append("-man FFA"); - } - else if (tourney.TourneyType == TourneyType.RandomTeam) - { - sb.Append(tourney.ParticipantsPerMatch); - sb.Append("-team"); - } - else if (tourney.TourneyType == TourneyType.RedVsBlue) - { - sb.Append("Red v Blue"); - } - else if (tourney.TourneyType == TourneyType.Faction) - { - sb.Append(tourney.ParticipantsPerMatch); - sb.Append("-team Faction"); - } - else - { - for (int i = 0; i < tourney.ParticipantsPerMatch; ++i) - { - if (sb.Length > 0) - sb.Append('v'); - - sb.Append(tourney.PlayersPerParticipant); - } - } - } - - if (Controller != null) - sb.Append(' ').Append(Controller.Title); - - string title = sb.ToString(); - - BRTeamInfo winner = teams.Count > 0 ? teams[0] : null; - - for (int i = 0; i < teams.Count; ++i) - { - TrophyRank rank = i switch - { - 0 => TrophyRank.Gold, - 1 => TrophyRank.Silver, - _ => TrophyRank.Bronze - }; - - BRPlayerInfo leader = teams[i].Leader; - - foreach (BRPlayerInfo pl in teams[i].Players.Values) - { - Mobile mob = pl.Player; - - if (mob == null) - continue; - - sb = new StringBuilder(); - - sb.Append(title); - - if (pl == leader) - sb.Append(" Leader"); - - if (pl.Score > 0) - { - sb.Append(": "); - - // sb.Append( pl.Score.ToString( "N0" ) ); - // sb.Append( pl.Score == 1 ? " point" : " points" ); - - sb.Append(pl.Kills.ToString("N0")); - sb.Append(pl.Kills == 1 ? " kill" : " kills"); - - if (pl.Captures > 0) - { - sb.Append(", "); - sb.Append(pl.Captures.ToString("N0")); - sb.Append(pl.Captures == 1 ? " point" : " points"); - } - } - - Item item = new Trophy(sb.ToString(), rank); - - if (pl == leader) - item.ItemID = 4810; - - item.Name = $"{item.Name}, {teams[i].Name.ToLower()} team"; - - if (!mob.PlaceInBackpack(item)) - mob.BankBox.DropItem(item); - - int cash = pl.Score * 250; - - if (cash > 0) - { - item = new BankCheck(cash); - - if (!mob.PlaceInBackpack(item)) - mob.BankBox.DropItem(item); - - mob.SendMessage( - "You have been awarded a {0} trophy and {1:N0}gp for your participation in this tournament.", - rank.ToString().ToLower(), cash); - } - else - { - mob.SendMessage("You have been awarded a {0} trophy for your participation in this tournament.", - rank.ToString().ToLower()); - } - } - } - - for (int i = 0; i < m_Context.Participants.Count; ++i) - { - Participant p = m_Context.Participants[i]; - - if (p?.Players == null) - continue; - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer dp = p.Players[j]; - - if (dp?.Mobile != null) - { - dp.Mobile.CloseGump(); - dp.Mobile.SendGump(new BRBoardGump(dp.Mobile, this)); - } - } - - if (i == winner?.TeamID) - continue; - - if (p.Players != null) - for (int j = 0; j < p.Players.Length; ++j) - if (p.Players[j] != null) - p.Players[j].Eliminated = true; - } - - if (winner != null) - m_Context.Finish(m_Context.Participants[winner.TeamID]); - } - - public override void OnStop() - { - for (int i = 0; i < Controller.TeamInfo.Length; ++i) - { - BRTeamInfo teamInfo = Controller.TeamInfo[i]; - - if (teamInfo.Board != null) - teamInfo.Board.m_TeamInfo = null; - - teamInfo.Game = null; - } - - ReturnBomb(); - - m_Bomb?.Delete(); - - for (int i = 0; i < m_Context.Participants.Count; ++i) - ApplyHues(m_Context.Participants[i], -1); - - m_FinishTimer?.Stop(); - m_FinishTimer = null; - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Server.Gumps; +using Server.Items; +using Server.Mobiles; +using Server.Network; +using Server.Targeting; + +namespace Server.Engines.ConPVP +{ + public class BRBomb : Item + { + private readonly BRGame m_Game; + + private readonly List m_Helpers; + + private readonly Point3DList m_Path = new Point3DList(); + private readonly EffectTimer m_Timer; + private bool m_Flying; + private int m_PathIdx; + + public BRBomb(BRGame game) : + base(0x103C) // 0x103C = bread, 0x1042 = pie, 0x1364 = rock, 0x13a8 = pillow, 0x2256 = bagball + { + Movable = false; + Hue = 0x35; + + m_Game = game; + + m_Helpers = new List(); + + m_Timer = new EffectTimer(this); + m_Timer.Start(); + } + + public BRBomb(Serial serial) : base(serial) + { + } + + public override string DefaultName => "da bomb"; + + public Mobile Thrower { get; private set; } + + private Mobile FindOwner(IEntity parent) + { + if (parent is Item item) + return item.RootParent as Mobile; + + if (parent is Mobile mobile) + return mobile; + + return null; + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + break; + } + } + + Timer.DelayCall(Delete); // delete this after the world loads + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void OnAdded(IEntity parent) + { + base.OnAdded(parent); + + var mob = FindOwner(parent); + + if (mob != null) + mob.SolidHueOverride = 0x0499; + } + + public override void OnRemoved(IEntity parent) + { + base.OnRemoved(parent); + + var mob = FindOwner(parent); + + if (mob != null && m_Game != null) + mob.SolidHueOverride = m_Game.GetColor(mob); + } + + public void DropTo(Mobile mob, Mobile killer) + { + if (mob?.Deleted == false) + MoveToWorld(mob.Location, mob.Map); + else if (killer?.Deleted == false) + MoveToWorld(killer.Location, killer.Map); + else + m_Game?.ReturnBomb(); + } + + public override bool OnMoveOver(Mobile m) + { + if (m_Flying || !Visible || m_Game == null || m?.Alive != true) + return true; + + var useTeam = m_Game.GetTeamInfo(m); + return useTeam == null || TakeBomb(m, useTeam, "picked up"); + } + + public override void OnLocationChange(Point3D oldLocation) + { + base.OnLocationChange(oldLocation); + + if (m_Flying || !Visible || m_Game == null || Parent != null) + return; + + var eable = GetClientsInRange(0); + foreach (var ns in eable) + { + var m = ns.Mobile; + + if (m?.Player != true || !m.Alive) + continue; + + var useTeam = m_Game.GetTeamInfo(m); + if (useTeam != null) + TakeBomb(m, useTeam, "got"); + } + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Timer?.Stop(); + } + + public override void OnDoubleClick(Mobile m) + { + if (m_Game == null || !Visible || m?.Alive != true) + return; + + if (!m_Flying && IsChildOf(m.Backpack)) + m.Target = new BombTarget(this, m); + else if (Parent == null) + if (m.InRange(Location, 1) && m.Location.Z != Z) + { + var useTeam = m_Game.GetTeamInfo(m); + if (useTeam == null) + return; + + TakeBomb(m, useTeam, "grabbed"); + } + } + + private bool OnBombTarget(Mobile from, object obj) + { + if (m_Game == null) + return true; + + if (!IsChildOf(from.Backpack)) + return true; + + // don't let them throw it to themselves + if (obj == from) + return false; + + if (!(obj is IPoint3D)) + return false; + + var pt = new Point3D((IPoint3D)obj); + + if (obj is Mobile) + pt.Z += 10; + else if (obj is Item item) + pt.Z += item.ItemData.CalcHeight + 1; + + m_Flying = true; + Visible = false; + Thrower = from; + MoveToWorld(GetWorldLocation(), from.Map); + + BeginFlight(pt); + return true; + } + + private void HitObject(Point3D ballLoc, int objZ, int objHeight) + { + DoAnim(GetWorldLocation(), ballLoc, Map); + MoveToWorld(ballLoc); + + m_Path.Clear(); + m_PathIdx = 0; + + Timer.DelayCall(TimeSpan.FromSeconds(0.05), ContinueFlight); + } + + private bool CheckCatch(Mobile m, Point3D myLoc) + { + if (m?.Alive != true || !m.Player || m_Game == null) + return false; + + if (m_Game.GetTeamInfo(m) == null) + return false; + + var zdiff = myLoc.Z - m.Z; + + return zdiff >= 0 && (zdiff < 12 || zdiff < 16 && Utility.RandomBool()); + } + + private void DoAnim(Point3D start, Point3D end, Map map) + { + Effects.SendMovingEffect( + new Entity(Serial.Zero, start, map), + new Entity(Serial.Zero, end, map), + ItemID, + 15, + 0, + false, + false, + Hue + ); + } + + private void DoCatch(Mobile m) + { + m_Flying = false; + Visible = true; + + if (m?.Alive != true || !m.Player || m_Game == null) + return; + + var useTeam = m_Game.GetTeamInfo(m); + + if (useTeam == null) + return; + + DoAnim(GetWorldLocation(), m.Location, m.Map); + + var verb = "caught"; + + if (Thrower != null && m_Game.GetTeamInfo(Thrower) != useTeam) + verb = "intercepted"; + + if (!TakeBomb(m, useTeam, verb)) + MoveToWorld(m.Location, m.Map); + } + + private void BeginFlight(Point3D dest) + { + var org = GetWorldLocation(); + + org.Z += 10; // always add 10 at the start cause we're coming from a mobile's eye level + + /*if (org.X > dest.X || ( org.X == dest.X && org.Y > dest.Y ) || ( org.X == dest.X && org.Y == dest.Y && org.Z > dest.Z )) + { + Point3D swap = org; + org = dest; + dest = swap; + }*/ + + var list = new List(); + + var xd = dest.X - org.X; + var yd = dest.Y - org.Y; + var zd = dest.Z - org.Z; + var dist2d = Math.Sqrt(xd * xd + yd * yd); + var dist3d = zd == 0 ? dist2d : Math.Sqrt(dist2d * dist2d + zd * zd); + + var rise = yd / dist3d; + var run = xd / dist3d; + var zslp = zd / dist3d; + + double x = org.X; + double y = org.Y; + double z = org.Z; + while (Utility.NumberBetween(x, dest.X, org.X, 0.5) && Utility.NumberBetween(y, dest.Y, org.Y, 0.5) && + Utility.NumberBetween(z, dest.Z, org.Z, 0.5)) + { + var ix = (int)Math.Round(x); + var iy = (int)Math.Round(y); + var iz = (int)Math.Round(z); + + if (list.Count > 0) + { + var p = list[^1]; + + if (p.X != ix || p.Y != iy || p.Z != iz) + list.Add(new Point3D(ix, iy, iz)); + } + else + { + list.Add(new Point3D(ix, iy, iz)); + } + + x += run; + y += rise; + z += zslp; + } + + if (list.Count > 0 && list[^1] != dest) + list.Add(dest); + + /*if (dist3d > 4 && ( dest.X != org.X || dest.Y != org.Y )) + { + int count = list.Count; + int i; + int climb = count / 2; + if (climb > 3) + climb = 3; + + for ( i = 0; i < climb; i++ ) + { + p = ((Point3D)list[i]); + p.Z += (i+1) * 4; + list[i] = p; + } + + for ( ; i < count - climb; i++ ) + { + p = ((Point3D)list[i]); + p.Z += 16; + list[i] = p; + } + + for ( i = climb; i > 0; i-- ) + { + p = ((Point3D)list[i]); + p.Z += i * 4; + list[i] = p; + } + }*/ + + if (dist2d > 1) + { + var count = list.Count; + var height = count * 2 * (Utility.RandomDouble() * 0.40 + 0.10); // 10 - 50% + var coeff = -height / (count * count / 4.0); + + for (var i = 0; i < count; i++) + { + var p = list[i]; + + var xp = i - count / 2; + + p.Z += (int)Math.Ceiling(coeff * xp * xp + height); + + list[i] = p; + } + } + + m_Path.Clear(); + for (var i = 0; i < list.Count; i++) + m_Path.Add(list[i]); + + m_PathIdx = 0; + + ContinueFlight(); + } + + private void ContinueFlight() + { + int height; + var found = false; + + if (m_PathIdx < m_Path.Count && Map?.Tiles != null && Map != Map.Internal) + { + var pathCheckEnd = m_PathIdx + 5; + + if (m_Path.Count < pathCheckEnd) + pathCheckEnd = m_Path.Count; + + Visible = false; + + if (m_PathIdx > 0) // move to the next location + MoveToWorld(m_Path[m_PathIdx - 1]); + + Point3D pTop = new Point3D(GetWorldLocation()), pBottom = new Point3D(m_Path[pathCheckEnd - 1]); + Utility.FixPoints(ref pTop, ref pBottom); + + for (var i = m_PathIdx; i < pathCheckEnd; i++) + { + var point = m_Path[i]; + + var landTile = Map.Tiles.GetLandTile(point.X, point.Y); + int landZ = 0, landAvg = 0, landTop = 0; + Map.GetAverageZ(point.X, point.Y, ref landZ, ref landAvg, ref landTop); + + if (landZ <= point.Z && landTop >= point.Z && !landTile.Ignored) + { + HitObject(point, landTop, 0); + return; + } + + var statics = Map.Tiles.GetStaticTiles(point.X, point.Y, true); + + if (landTile.ID == 0x244 && statics.Length == 0) // 0x244 = invalid land tile + { + var eable = Map.GetItemsInRange(point, 0); + + var empty = eable.All(item => item == this); + + eable.Free(); + + if (empty) + { + HitObject(point, landTop, 0); + return; + } + } + + for (var j = 0; j < statics.Length; j++) + { + var t = statics[j]; + + var id = TileData.ItemTable[t.ID & TileData.MaxItemValue]; + height = id.CalcHeight; + + if (t.Z <= point.Z && t.Z + height >= point.Z && + (id.Flags & (TileFlag.Impassable | TileFlag.Wall | TileFlag.NoShoot)) != 0) + { + if (i > m_PathIdx) + point = m_Path[i - 1]; + else + point = GetWorldLocation(); + HitObject(point, t.Z, height); + return; + } + } + } + + var rect = new Rectangle2D(pTop.X, pTop.Y, pBottom.X - pTop.X + 1, pBottom.Y - pTop.Y + 1); + + var area = Map.GetItemsInBounds(rect); + foreach (var i in area) + { + if (i == this || i.ItemID >= 0x4000) + continue; + + if (i is BRGoal) + { + height = 17; + } + else if (i is Blocker) + { + height = 20; + } + else + { + var id = i.ItemData; + if ((id.Flags & (TileFlag.Impassable | TileFlag.Wall | TileFlag.NoShoot)) == 0) + continue; + height = id.CalcHeight; + } + + var point = i.Location; + var loc = i.Location; + for (var j = m_PathIdx; j < pathCheckEnd; j++) + { + point = m_Path[j]; + + if (loc.X == point.X && loc.Y == point.Y && + (i is Blocker || loc.Z <= point.Z && loc.Z + height >= point.Z)) + { + found = true; + if (j > m_PathIdx) + point = m_Path[j - 1]; + else + point = GetWorldLocation(); + break; + } + } + + if (!found) + continue; + + area.Free(); + if (i is BRGoal goal) + { + var oldLoc = new Point3D(GetWorldLocation()); + if (CheckScore(goal, Thrower, 3)) + DoAnim(oldLoc, point, Map); + else + HitObject(point, loc.Z, height); + } + else + { + HitObject(point, loc.Z, height); + } + + return; + } + + area.Free(); + + var clients = Map.GetClientsInBounds(rect); + foreach (var ns in clients) + { + var m = ns.Mobile; + + if (m == null || m == Thrower) + continue; + + Point3D point; + var loc = m.Location; + + for (var j = m_PathIdx; j < pathCheckEnd && !found; j++) + { + point = m_Path[j]; + + if (loc.X == point.X && loc.Y == point.Y && + loc.Z <= point.Z && loc.Z + 16 >= point.Z) + found = CheckCatch(m, point); + } + + if (!found) + continue; + + clients.Free(); + + // TODO: probably need to change this a lot... + DoCatch(m); + + return; + } + + clients.Free(); + + m_PathIdx = pathCheckEnd; + + if (m_PathIdx > 0 && m_PathIdx - 1 < m_Path.Count) + DoAnim(GetWorldLocation(), m_Path[m_PathIdx - 1], Map); + + Timer.DelayCall(TimeSpan.FromSeconds(0.1), ContinueFlight); + } + else + { + if (m_PathIdx > 0 && m_PathIdx - 1 < m_Path.Count) + MoveToWorld(m_Path[m_PathIdx - 1]); + else if (m_Path.Count > 0) + MoveToWorld(m_Path.Last); + + var myZ = Map?.GetAverageZ(X, Y) ?? 0; + + var statics = Map?.Tiles?.GetStaticTiles(X, Y, true); + + if (statics != null) + for (var j = 0; j < statics.Length; j++) + { + var t = statics[j]; + + var id = TileData.ItemTable[t.ID & TileData.MaxItemValue]; + height = id.CalcHeight; + + if (t.Z + height > myZ && t.Z + height <= Z) + myZ = t.Z + height; + } + + var eable = GetItemsInRange(0); + foreach (var item in eable) + if (item.Visible && item != this) + { + height = item.ItemData.CalcHeight; + if (item.Z + height > myZ && item.Z + height <= Z) + myZ = item.Z + height; + } + + eable.Free(); + + Z = myZ; + m_Flying = false; + Visible = true; + + m_Path.Clear(); + m_PathIdx = 0; + } + } + + public bool CheckScore(BRGoal goal, Mobile m, int points) + { + if (m_Game == null || m == null || goal == null) + return false; + + var team = m_Game.GetTeamInfo(m); + if (team == null || goal.Team == null || team == goal.Team) + return false; + + if (points > 3) + m_Game.Alert("Touchdown {0} ({1})!", team.Name, m.Name); + else + m_Game.Alert("Field goal {0} ({1})!", team.Name, m.Name); + + for (var i = m_Helpers.Count - 1; i >= 0; i--) + { + var mob = m_Helpers[i]; + + var pi = team[mob]; + if (pi != null) + { + if (mob == m) + pi.Captures += points; + + pi.Score += points + 1; + + points /= 2; + } + } + + m_Game.ReturnBomb(); + + m_Flying = false; + Visible = true; + m_Path.Clear(); + m_PathIdx = 0; + + Target.Cancel(m); + + return true; + } + + private bool TakeBomb(Mobile m, BRTeamInfo team, string verb) + { + if (!m.Player || !m.Alive || m.NetState == null) + return false; + + if (m.PlaceInBackpack(this)) + { + m.RevealingAction(); + + m.LocalOverheadMessage(MessageType.Regular, 0x59, false, "You got the bomb!"); + m_Game.Alert("{1} ({2}) {0} the bomb!", verb, m.Name, team.Name); + + m.Target = new BombTarget(this, m); + + if (m_Helpers.Contains(m)) + m_Helpers.Remove(m); + + if (m_Helpers.Count > 0) + { + var last = m_Helpers[0]; + + if (m_Game.GetTeamInfo(last) != team) + m_Helpers.Clear(); + } + + m_Helpers.Add(m); + + return true; + } + + return false; + } + + private class EffectTimer : Timer + { + private readonly BRBomb m_Bomb; + private int m_Count; + + public EffectTimer(BRBomb bomb) : base(TimeSpan.Zero, TimeSpan.FromSeconds(1.0)) + { + m_Bomb = bomb; + m_Count = 0; + Priority = TimerPriority.FiftyMS; + } + + protected override void OnTick() + { + if (m_Bomb.Parent == null && m_Bomb.m_Game?.Controller != null) + { + if (!m_Bomb.m_Flying && m_Bomb.Map != Map.Internal) + Effects.SendLocationEffect(m_Bomb.GetWorldLocation(), m_Bomb.Map, 0x377A, 16, 10, m_Bomb.Hue, 0); + + if (m_Bomb.Location != m_Bomb.m_Game.Controller.BombHome) + { + if (++m_Count >= 30) + { + m_Bomb.m_Game.ReturnBomb(); + m_Bomb.m_Game.Alert("The bomb has been returned to it's starting point."); + + m_Count = 0; + m_Bomb.m_Helpers.Clear(); + } + } + else + { + m_Count = 0; + } + } + else + { + m_Count = 0; + } + } + } + + private class BombTarget : Target + { + private readonly BRBomb m_Bomb; + private readonly Mobile m_Mob; + private bool m_Resend = true; + + public BombTarget(BRBomb bomb, Mobile from) : base(10, true, TargetFlags.None) + { + CheckLOS = false; + + m_Bomb = bomb; + m_Mob = from; + + m_Mob.SendMessage(0x26, "Where do you want to throw it?"); + } + + protected override void OnTarget(Mobile from, object targeted) + { + m_Resend = !m_Bomb.OnBombTarget(from, targeted); + } + + protected override void OnTargetUntargetable(Mobile from, object targeted) + { + m_Resend = !m_Bomb.OnBombTarget(from, targeted); + } + + protected override void OnTargetFinish(Mobile from) + { + base.OnTargetFinish(from); + + // has to be delayed in case some other target canceled us... + if (m_Resend) + Timer.DelayCall(ResendBombTarget); + } + + private void ResendBombTarget() + { + // Make sure they still have the bomb, then give them the target back + if (m_Bomb?.Deleted == false && m_Mob?.Deleted == false && m_Mob.Alive && m_Bomb.IsChildOf(m_Mob)) + m_Mob.Target = new BombTarget(m_Bomb, m_Mob); + } + } + } + + public class BRGoal : BaseAddon + { + private bool m_North; + + private BRTeamInfo m_Team; + + [Constructible] + public BRGoal() + { + ItemID = 0x51D; + Hue = 0x84C; + Visible = true; + + Remake(); + } + + public BRGoal(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool North + { + get => m_North; + set + { + m_North = value; + Remake(); + } + } + + public override string DefaultName => "Bombing Run Goal"; + + public override bool ShareHue => false; + + public BRTeamInfo Team + { + get => m_Team; + set + { + m_Team = value; + if (m_Team != null && m_Team.Color != 0) + Hue = m_Team.Color; + else + Hue = 0x84C; + } + } + + private static AddonComponent SetHue(AddonComponent ac, int hue) + { + ac.Hue = hue; + return ac; + } + + private void Remake() + { + foreach (var ac in Components) + { + ac.Addon = null; + ac.Delete(); + } + + Components.Clear(); + + // stairs + AddComponent(new AddonComponent(0x74D), -1, +1, -5); + AddComponent(new AddonComponent(0x71F), 0, +1, -5); + AddComponent(new AddonComponent(0x74B), +1, +1, -5); + AddComponent(new AddonComponent(0x736), +1, 0, -5); + AddComponent(new AddonComponent(0x74C), +1, -1, -5); + AddComponent(new AddonComponent(0x737), 0, -1, -5); + AddComponent(new AddonComponent(0x74A), -1, -1, -5); + AddComponent(new AddonComponent(0x749), -1, 0, -5); + + // Center Sparkle + AddComponent(new AddonComponent(0x375A), 0, 0, -1); + + if (!m_North) + { + // Pillars + AddComponent(new AddonComponent(0x0CE), 0, +1, -2); + AddComponent(new AddonComponent(0x0CC), 0, -1, -2); + AddComponent(new AddonComponent(0x0D0), 0, 0, -2); + + // Yellow parts + AddComponent(SetHue(new AddonComponent(0x0DF), 0x499), 0, +1, 7); + AddComponent(SetHue(new AddonComponent(0x0DF), 0x499), 0, 0, 16); + AddComponent(SetHue(new AddonComponent(0x0DF), 0x499), 0, -1, 7); + + // Blue Sparkles + AddComponent(SetHue(new AddonComponent(0x377A), 0x84C), 0, +1, 12); + AddComponent(SetHue(new AddonComponent(0x377A), 0x84C), 0, +1, -1); + AddComponent(SetHue(new AddonComponent(0x377A), 0x84C), 0, -1, 12); + AddComponent(SetHue(new AddonComponent(0x377A), 0x84C), 0, -1, -1); + } + else + { + // Pillars + AddComponent(new AddonComponent(0x0CF), +1, 0, -2); + AddComponent(new AddonComponent(0x0CC), -1, 0, -2); + AddComponent(new AddonComponent(0x0D1), 0, 0, -2); + + // Yellow parts + AddComponent(SetHue(new AddonComponent(0x0DF), 0x499), +1, 0, 7); + AddComponent(SetHue(new AddonComponent(0x0DF), 0x499), 0, 0, 16); + AddComponent(SetHue(new AddonComponent(0x0DF), 0x499), -1, 0, 7); + + // Blue Sparkles + AddComponent(SetHue(new AddonComponent(0x377A), 0x84C), +1, 0, 12); + AddComponent(SetHue(new AddonComponent(0x377A), 0x84C), +1, 0, -1); + AddComponent(SetHue(new AddonComponent(0x377A), 0x84C), -1, 0, 12); + AddComponent(SetHue(new AddonComponent(0x377A), 0x84C), -1, 0, -1); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(m_North); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_North = reader.ReadBool(); + goto case 0; + } + case 0: + { + break; + } + } + + Hue = 0x84C; + } + + public override bool OnMoveOver(Mobile m) + { + if (!Visible) + return true; + + if (m?.Player != true || !m.Alive || m.Backpack == null || m_Team?.Game == null) + return true; + + if (!base.OnMoveOver(m)) + return false; + + if (m_Team != null && m_Team.Color != 0) + Hue = m_Team.Color; + else + Hue = 0x84C; + + m.Backpack.FindItemByType()?.CheckScore(this, m, 7); + return true; + } + } + + public sealed class BRBoard : Item + { + public BRTeamInfo m_TeamInfo; + + [Constructible] + public BRBoard() + : base(7774) => + Movable = false; + + public BRBoard(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "Scoreboard"; + + public override void OnDoubleClick(Mobile from) + { + if (m_TeamInfo?.Game != null) + { + from.CloseGump(); + from.SendGump(new BRBoardGump(from, m_TeamInfo.Game)); + } + } + + 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(); + } + } + + public class BRBoardGump : Gump + { + private const int LabelColor32 = 0xFFFFFF; + private const int BlackColor32 = 0x000000; + + // private BRGame m_Game; + + public BRBoardGump(Mobile mob, BRGame game, BRTeamInfo section = null) : base(60, 60) + { + // m_Game = game; + + var ourTeam = game.GetTeamInfo(mob); + + var entries = new List(); + var total = 0; + + if (section == null) + { + for (var i = 0; i < game.Context.Participants.Count; ++i) + { + var teamInfo = game.Controller.TeamInfo[i % game.Controller.TeamInfo.Length]; + + if (teamInfo == null) + continue; + + entries.Add(teamInfo); + } + + total = entries.Count; + } + else + { + foreach (var player in section.Players.Values) + if (player.Score > 0) + total++; + } + + entries.Sort(); + + var height = 0; + + if (section == null) + height = 73 + entries.Count * 75 + 28; + + Closable = false; + + AddPage(0); + + AddBackground(1, 1, 398, height, 3600); + + AddImageTiled(16, 15, 369, height - 29, 3604); + + for (var i = 0; i < total; i += 1) + AddImageTiled(22, 58 + i * 75, 357, 70, 0x2430); + + AddAlphaRegion(16, 15, 369, height - 29); + + AddImage(215, -45, 0xEE40); + // AddImage( 330, 141, 0x8BA ); + + AddBorderedText(22, 22, 294, 20, Center("BR Scoreboard"), LabelColor32, BlackColor32); + + AddImageTiled(32, 50, 264, 1, 9107); + AddImageTiled(42, 52, 264, 1, 9157); + + if (section == null) + for (var i = 0; i < entries.Count; ++i) + { + var teamInfo = entries[i]; + + AddImage(30, 70 + i * 75, 10152); + AddImage(30, 85 + i * 75, 10151); + AddImage(30, 100 + i * 75, 10151); + AddImage(30, 106 + i * 75, 10154); + + AddImage(24, 60 + i * 75, teamInfo == ourTeam ? 9730 : 9727, teamInfo.Color - 1); + + var nameColor = LabelColor32; + var borderColor = BlackColor32; + + switch (teamInfo.Color) + { + case 0x47E: + nameColor = 0xFFFFFF; + break; + + case 0x4F2: + nameColor = 0x3399FF; + break; + + case 0x4F7: + nameColor = 0x33FF33; + break; + + case 0x4FC: + nameColor = 0xFF00FF; + break; + + case 0x021: + nameColor = 0xFF3333; + break; + + case 0x01A: + nameColor = 0xFF66FF; + break; + + case 0x455: + nameColor = 0x333333; + borderColor = 0xFFFFFF; + break; + } + + AddBorderedText( + 60, + 65 + i * 75, + 250, + 20, + $"{LadderGump.Rank(1 + i)}: {teamInfo.Name}", + nameColor, + borderColor + ); + + AddBorderedText(50 + 10, 85 + i * 75, 100, 20, "Score:", 0xFFC000, BlackColor32); + AddBorderedText(50 + 15, 105 + i * 75, 100, 20, teamInfo.Score.ToString("N0"), 0xFFC000, BlackColor32); + + AddBorderedText(110 + 10, 85 + i * 75, 100, 20, "Kills:", 0xFFC000, BlackColor32); + AddBorderedText(110 + 15, 105 + i * 75, 100, 20, teamInfo.Kills.ToString("N0"), 0xFFC000, BlackColor32); + + AddBorderedText(160 + 10, 85 + i * 75, 100, 20, "Points:", 0xFFC000, BlackColor32); + AddBorderedText( + 160 + 15, + 105 + i * 75, + 100, + 20, + teamInfo.Captures.ToString("N0"), + 0xFFC000, + BlackColor32 + ); + + var pl = teamInfo.Leader; + + AddBorderedText(235 + 10, 85 + i * 75, 250, 20, "Leader:", 0xFFC000, BlackColor32); + + if (pl != null) + AddBorderedText(235 + 15, 105 + i * 75, 250, 20, pl.Player.Name, 0xFFC000, BlackColor32); + } + + AddButton(314, height - 42, 247, 248, 1); + } + + public string Center(string text) => $"
{text}
"; + + public string Color(string text, int color) => $"{text}"; + + private void AddBorderedText(int x, int y, int width, int height, string text, int color, int borderColor) + { + AddColoredText(x - 1, y - 1, width, height, text, borderColor); + AddColoredText(x - 1, y + 1, width, height, text, borderColor); + AddColoredText(x + 1, y - 1, width, height, text, borderColor); + AddColoredText(x + 1, y + 1, width, height, text, borderColor); + AddColoredText(x, y, width, height, text, color); + } + + private void AddColoredText(int x, int y, int width, int height, string text, int color) + { + if (color == 0) + AddHtml(x, y, width, height, text); + else + AddHtml(x, y, width, height, Color(text, color)); + } + } + + public sealed class BRPlayerInfo : IRankedCTF, IComparable + { + private readonly BRTeamInfo m_TeamInfo; + private int m_Captures; + + private int m_Kills; + + private int m_Score; + + public BRPlayerInfo(BRTeamInfo teamInfo, Mobile player) + { + m_TeamInfo = teamInfo; + Player = player; + } + + public Mobile Player { get; } + + public int CompareTo(BRPlayerInfo pi) + { + var res = pi.Captures.CompareTo(Captures); + if (res != 0) + return res; + + res = pi.Score.CompareTo(Score); + + if (res == 0) + res = pi.Kills.CompareTo(Kills); + + return res; + } + + public string Name => Player.Name; + + public int Kills + { + get => m_Kills; + set + { + m_TeamInfo.Kills += value - m_Kills; + m_Kills = value; + } + } + + public int Captures + { + get => m_Captures; + set + { + m_TeamInfo.Captures += value - m_Captures; + m_Captures = value; + } + } + + public int Score + { + get => m_Score; + set + { + m_TeamInfo.Score += value - m_Score; + m_Score = value; + + if (m_TeamInfo.Leader == null || m_Score > m_TeamInfo.Leader.Score) + m_TeamInfo.Leader = this; + } + } + } + + [PropertyObject] + public sealed class BRTeamInfo : IRankedCTF, IComparable + { + private BRGoal m_Goal; + + public BRTeamInfo(int teamID) + { + TeamID = teamID; + Players = new Dictionary(); + } + + public BRTeamInfo(int teamID, IGenericReader ip) + { + TeamID = teamID; + Players = new Dictionary(); + + var version = ip.ReadEncodedInt(); + + switch (version) + { + case 0: + { + Board = ip.ReadItem() as BRBoard; + TeamName = ip.ReadString(); + Color = ip.ReadEncodedInt(); + m_Goal = ip.ReadItem() as BRGoal; + break; + } + } + } + + public BRGame Game { get; set; } + + public int TeamID { get; } + + public BRPlayerInfo Leader { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public BRBoard Board { get; set; } + + public Dictionary Players { get; } + + public BRPlayerInfo this[Mobile mob] + { + get + { + if (mob == null) + return null; + + if (!Players.TryGetValue(mob, out var val)) + Players[mob] = val = new BRPlayerInfo(this, mob); + + return val; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Color { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public string TeamName { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public BRGoal Goal + { + get => m_Goal; + set + { + m_Goal = value; + if (m_Goal != null) + m_Goal.Team = this; + } + } + + public int CompareTo(BRTeamInfo ti) + { + var res = ti.Captures.CompareTo(Captures); + if (res == 0) + { + res = ti.Score.CompareTo(Score); + + if (res == 0) + res = ti.Kills.CompareTo(Kills); + } + + return res; + } + + public string Name => $"{TeamName} Team"; + + public int Kills { get; set; } + + public int Captures { get; set; } + + public int Score { get; set; } + + public void Reset() + { + Kills = 0; + Captures = 0; + Score = 0; + + Leader = null; + + Players.Clear(); + + if (Board != null) + Board.m_TeamInfo = this; + if (m_Goal != null) + m_Goal.Team = this; + } + + public void Serialize(IGenericWriter op) + { + op.WriteEncodedInt(0); // version + + op.Write(Board); + + op.Write(TeamName); + + op.WriteEncodedInt(Color); + + op.Write(m_Goal); + } + + public override string ToString() + { + if (TeamName != null) + return $"({Name}) ..."; + return "..."; + } + } + + public sealed class BRController : EventController + { + [Constructible] + public BRController() + { + Visible = false; + Movable = false; + + Duration = TimeSpan.FromMinutes(30.0); + + BombHome = Point3D.Zero; + + TeamInfo = new BRTeamInfo[4]; + + for (var i = 0; i < TeamInfo.Length; ++i) + TeamInfo[i] = new BRTeamInfo(i); + } + + public BRController(Serial serial) + : base(serial) + { + } + + public BRTeamInfo[] TeamInfo { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public BRTeamInfo Team1 => TeamInfo[0]; + + [CommandProperty(AccessLevel.GameMaster)] + public BRTeamInfo Team2 => TeamInfo[1]; + + [CommandProperty(AccessLevel.GameMaster)] + public BRTeamInfo Team3 => TeamInfo[2]; + + [CommandProperty(AccessLevel.GameMaster)] + public BRTeamInfo Team4 => TeamInfo[3]; + + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan Duration { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D BombHome { get; set; } + + public override string Title => "Bombing Run"; + public override string DefaultName => "Bombing Run Controller"; + + public override string GetTeamName(int teamID) => TeamInfo[teamID % TeamInfo.Length].Name; + + public override EventGame Construct(DuelContext context) => new BRGame(this, context); + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + writer.Write(BombHome); + + writer.Write(Duration); + + writer.WriteEncodedInt(TeamInfo.Length); + + for (var i = 0; i < TeamInfo.Length; ++i) + TeamInfo[i].Serialize(writer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + BombHome = reader.ReadPoint3D(); + + Duration = reader.ReadTimeSpan(); + + TeamInfo = new BRTeamInfo[reader.ReadEncodedInt()]; + + for (var i = 0; i < TeamInfo.Length; ++i) + TeamInfo[i] = new BRTeamInfo(i, reader); + + break; + } + } + } + } + + public sealed class BRGame : EventGame + { + private BRBomb m_Bomb; + + private Timer m_FinishTimer; + + private TimerCallback m_UnhideCallback; + + public BRGame(BRController controller, DuelContext context) : base(context) => Controller = controller; + + public BRController Controller { get; } + + public Map Facet + { + get + { + if (m_Context.Arena != null) + return m_Context.Arena.Facet; + + return Controller.Map; + } + } + + public override bool CantDoAnything(Mobile mob) => + mob.Backpack?.FindItemByType() != null && GetTeamInfo(mob) != null; + + public void ReturnBomb() + { + if (m_Bomb != null && Controller != null) + { + m_UnhideCallback ??= UnhideBomb; + m_Bomb.Visible = false; + m_Bomb.MoveToWorld(Controller.BombHome, Controller.Map); + Timer.DelayCall(TimeSpan.FromSeconds(Utility.RandomMinMax(5, 15)), m_UnhideCallback); + } + } + + private void UnhideBomb() + { + if (m_Bomb != null) + { + m_Bomb.Visible = true; + m_Bomb.OnLocationChange(m_Bomb.Location); + } + } + + public void Alert(string text) + { + m_Context.m_Tournament?.Alert(text); + + for (var i = 0; i < m_Context.Participants.Count; ++i) + { + var p = m_Context.Participants[i]; + + for (var j = 0; j < p.Players.Length; ++j) + if (p.Players[j] != null) + p.Players[j].Mobile.SendMessage(0x35, text); + } + } + + public void Alert(string format, params object[] args) + { + Alert(string.Format(format, args)); + } + + public BRTeamInfo GetTeamInfo(Mobile mob) + { + var teamID = GetTeamID(mob); + + if (teamID >= 0) + return Controller.TeamInfo[teamID % Controller.TeamInfo.Length]; + + return null; + } + + public int GetTeamID(Mobile mob) + { + if (!(mob is PlayerMobile pm)) + return mob is BaseCreature creature ? creature.Team - 1 : -1; + + if (pm.DuelContext == null || pm.DuelContext != m_Context) + return -1; + + if (pm.DuelPlayer?.Eliminated != false) + return -1; + + return pm.DuelContext.Participants.IndexOf(pm.DuelPlayer.Participant); + } + + public int GetColor(Mobile mob) => GetTeamInfo(mob)?.Color ?? -1; + + private void ApplyHues(Participant p, int hueOverride) + { + for (var i = 0; i < p.Players.Length; ++i) + if (p.Players[i] != null) + p.Players[i].Mobile.SolidHueOverride = hueOverride; + } + + public void DelayBounce(TimeSpan ts, Mobile mob, Container corpse) + { + Timer.DelayCall(ts, DelayBounce_Callback, mob, corpse); + } + + private void DelayBounce_Callback(Mobile mob, Container corpse) + { + var dp = (mob as PlayerMobile)?.DuelPlayer; + + m_Context.RemoveAggressions(mob); + + if (dp?.Eliminated == false) + mob.MoveToWorld(m_Context.Arena.GetBaseStartPoint(GetTeamID(mob)), Facet); + else + m_Context.SendOutside(mob); + + m_Context.Refresh(mob, corpse); + DuelContext.Debuff(mob); + DuelContext.CancelSpell(mob); + mob.Frozen = false; + } + + public override bool OnDeath(Mobile mob, Container corpse) + { + var killer = mob.FindMostRecentDamager(false); + + var hadBomb = false; + + corpse.FindItemsByType(false) + .ForEach( + bomb => + { + hadBomb = true; + bomb.DropTo(mob, killer); + } + ); + + mob.Backpack?.FindItemsByType(false) + .ForEach( + bomb => + { + hadBomb = true; + bomb.DropTo(mob, killer); + } + ); + + if (killer?.Player == true) + { + var teamInfo = GetTeamInfo(killer); + var victInfo = GetTeamInfo(mob); + + if (teamInfo != null && teamInfo != victInfo) + { + var playerInfo = teamInfo[killer]; + + if (playerInfo != null) + { + playerInfo.Kills += 1; + playerInfo.Score += 1; // base frag + + if (hadBomb) + playerInfo.Score += 4; // fragged bomb carrier + } + } + } + + mob.CloseGump(); + mob.SendGump(new BRBoardGump(mob, this)); + + m_Context.Requip(mob, corpse); + DelayBounce(TimeSpan.FromSeconds(30.0), mob, corpse); + + return false; + } + + public override void OnStart() + { + for (var i = 0; i < Controller.TeamInfo.Length; ++i) + { + var teamInfo = Controller.TeamInfo[i]; + + teamInfo.Game = this; + teamInfo.Reset(); + } + + for (var i = 0; i < m_Context.Participants.Count; ++i) + ApplyHues( + m_Context.Participants[i], + Controller.TeamInfo[i % Controller.TeamInfo.Length].Color + ); + + m_FinishTimer?.Stop(); + + m_Bomb = new BRBomb(this); + ReturnBomb(); + + m_FinishTimer = Timer.DelayCall(Controller.Duration, Finish_Callback); + } + + private void Finish_Callback() + { + var teams = new List(); + + for (var i = 0; i < m_Context.Participants.Count; ++i) + { + var teamInfo = Controller.TeamInfo[i % Controller.TeamInfo.Length]; + + if (teamInfo != null) + teams.Add(teamInfo); + } + + teams.Sort(); + + var tourney = m_Context.m_Tournament; + + var sb = new StringBuilder(); + + if (tourney != null) + { + if (tourney.TourneyType == TourneyType.FreeForAll) + { + sb.Append(m_Context.Participants.Count * tourney.PlayersPerParticipant); + sb.Append("-man FFA"); + } + else if (tourney.TourneyType == TourneyType.RandomTeam) + { + sb.Append(tourney.ParticipantsPerMatch); + sb.Append("-team"); + } + else if (tourney.TourneyType == TourneyType.RedVsBlue) + { + sb.Append("Red v Blue"); + } + else if (tourney.TourneyType == TourneyType.Faction) + { + sb.Append(tourney.ParticipantsPerMatch); + sb.Append("-team Faction"); + } + else + { + for (var i = 0; i < tourney.ParticipantsPerMatch; ++i) + { + if (sb.Length > 0) + sb.Append('v'); + + sb.Append(tourney.PlayersPerParticipant); + } + } + } + + if (Controller != null) + sb.Append(' ').Append(Controller.Title); + + var title = sb.ToString(); + + var winner = teams.Count > 0 ? teams[0] : null; + + for (var i = 0; i < teams.Count; ++i) + { + var rank = i switch + { + 0 => TrophyRank.Gold, + 1 => TrophyRank.Silver, + _ => TrophyRank.Bronze + }; + + var leader = teams[i].Leader; + + foreach (var pl in teams[i].Players.Values) + { + var mob = pl.Player; + + if (mob == null) + continue; + + sb = new StringBuilder(); + + sb.Append(title); + + if (pl == leader) + sb.Append(" Leader"); + + if (pl.Score > 0) + { + sb.Append(": "); + + // sb.Append( pl.Score.ToString( "N0" ) ); + // sb.Append( pl.Score == 1 ? " point" : " points" ); + + sb.Append(pl.Kills.ToString("N0")); + sb.Append(pl.Kills == 1 ? " kill" : " kills"); + + if (pl.Captures > 0) + { + sb.Append(", "); + sb.Append(pl.Captures.ToString("N0")); + sb.Append(pl.Captures == 1 ? " point" : " points"); + } + } + + Item item = new Trophy(sb.ToString(), rank); + + if (pl == leader) + item.ItemID = 4810; + + item.Name = $"{item.Name}, {teams[i].Name.ToLower()} team"; + + if (!mob.PlaceInBackpack(item)) + mob.BankBox.DropItem(item); + + var cash = pl.Score * 250; + + if (cash > 0) + { + item = new BankCheck(cash); + + if (!mob.PlaceInBackpack(item)) + mob.BankBox.DropItem(item); + + mob.SendMessage( + "You have been awarded a {0} trophy and {1:N0}gp for your participation in this tournament.", + rank.ToString().ToLower(), + cash + ); + } + else + { + mob.SendMessage( + "You have been awarded a {0} trophy for your participation in this tournament.", + rank.ToString().ToLower() + ); + } + } + } + + for (var i = 0; i < m_Context.Participants.Count; ++i) + { + var p = m_Context.Participants[i]; + + if (p?.Players == null) + continue; + + for (var j = 0; j < p.Players.Length; ++j) + { + var dp = p.Players[j]; + + if (dp?.Mobile != null) + { + dp.Mobile.CloseGump(); + dp.Mobile.SendGump(new BRBoardGump(dp.Mobile, this)); + } + } + + if (i == winner?.TeamID) + continue; + + if (p.Players != null) + for (var j = 0; j < p.Players.Length; ++j) + if (p.Players[j] != null) + p.Players[j].Eliminated = true; + } + + if (winner != null) + m_Context.Finish(m_Context.Participants[winner.TeamID]); + } + + public override void OnStop() + { + for (var i = 0; i < Controller.TeamInfo.Length; ++i) + { + var teamInfo = Controller.TeamInfo[i]; + + if (teamInfo.Board != null) + teamInfo.Board.m_TeamInfo = null; + + teamInfo.Game = null; + } + + ReturnBomb(); + + m_Bomb?.Delete(); + + for (var i = 0; i < m_Context.Participants.Count; ++i) + ApplyHues(m_Context.Participants[i], -1); + + m_FinishTimer?.Stop(); + m_FinishTimer = null; + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Games/CTF.cs b/Projects/UOContent/Engines/ConPVP/Games/CTF.cs index e3a981549..7c9a3c4d4 100644 --- a/Projects/UOContent/Engines/ConPVP/Games/CTF.cs +++ b/Projects/UOContent/Engines/ConPVP/Games/CTF.cs @@ -1,1181 +1,1229 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Server.Gumps; -using Server.Items; -using Server.Mobiles; -using Server.Network; -using Server.Targeting; - -namespace Server.Engines.ConPVP -{ - public sealed class CTFBoard : Item - { - public CTFTeamInfo m_TeamInfo; - - [Constructible] - public CTFBoard() - : base(7774) => - Movable = false; - - public CTFBoard(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "scoreboard"; - - public override void OnDoubleClick(Mobile from) - { - if (m_TeamInfo?.Game != null) - { - from.CloseGump(); - from.SendGump(new CTFBoardGump(from, m_TeamInfo.Game)); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class CTFBoardGump : Gump - { - private const int LabelColor32 = 0xFFFFFF; - private const int BlackColor32 = 0x000000; - - private CTFGame m_Game; - - public CTFBoardGump(Mobile mob, CTFGame game, CTFTeamInfo section = null) - : base(60, 60) - { - m_Game = game; - - CTFTeamInfo ourTeam = game.GetTeamInfo(mob); - - List entries = new List(); - - if (section == null) - for (int i = 0; i < game.Context.Participants.Count; ++i) - { - CTFTeamInfo teamInfo = game.Controller.TeamInfo[i % 8]; - - if (teamInfo?.Flag == null) - continue; - - entries.Add(teamInfo); - } - else - foreach (CTFPlayerInfo player in section.Players.Values) - if (player.Score > 0) - entries.Add(player); - - entries.Sort((a, b) => b.Score - a.Score); - - int height = 0; - - if (section == null) - height = 73 + entries.Count * 75 + 28; - - Closable = false; - - AddPage(0); - - AddBackground(1, 1, 398, height, 3600); - - AddImageTiled(16, 15, 369, height - 29, 3604); - - for (int i = 0; i < entries.Count; i += 1) - AddImageTiled(22, 58 + i * 75, 357, 70, 0x2430); - - AddAlphaRegion(16, 15, 369, height - 29); - - AddImage(215, -45, 0xEE40); - // AddImage( 330, 141, 0x8BA ); - - AddBorderedText(22, 22, 294, 20, Center("CTF Scoreboard"), LabelColor32, BlackColor32); - - AddImageTiled(32, 50, 264, 1, 9107); - AddImageTiled(42, 52, 264, 1, 9157); - - if (section == null) - for (int i = 0; i < entries.Count; ++i) - { - CTFTeamInfo teamInfo = entries[i] as CTFTeamInfo; - - if (teamInfo == null) - continue; - - AddImage(30, 70 + i * 75, 10152); - AddImage(30, 85 + i * 75, 10151); - AddImage(30, 100 + i * 75, 10151); - AddImage(30, 106 + i * 75, 10154); - - AddImage(24, 60 + i * 75, teamInfo == ourTeam ? 9730 : 9727, teamInfo.Color - 1); - - int nameColor = LabelColor32; - int borderColor = BlackColor32; - - switch (teamInfo.Color) - { - case 0x47E: - nameColor = 0xFFFFFF; - break; - - case 0x4F2: - nameColor = 0x3399FF; - break; - - case 0x4F7: - nameColor = 0x33FF33; - break; - - case 0x4FC: - nameColor = 0xFF00FF; - break; - - case 0x021: - nameColor = 0xFF3333; - break; - - case 0x01A: - nameColor = 0xFF66FF; - break; - - case 0x455: - nameColor = 0x333333; - borderColor = 0xFFFFFF; - break; - } - - AddBorderedText(60, 65 + i * 75, 250, 20, $"{LadderGump.Rank(1 + i)}: {teamInfo.Name} Team", nameColor, - borderColor); - - AddBorderedText(50 + 10, 85 + i * 75, 100, 20, "Score:", 0xFFC000, BlackColor32); - AddBorderedText(50 + 15, 105 + i * 75, 100, 20, teamInfo.Score.ToString("N0"), 0xFFC000, BlackColor32); - - AddBorderedText(110 + 10, 85 + i * 75, 100, 20, "Kills:", 0xFFC000, BlackColor32); - AddBorderedText(110 + 15, 105 + i * 75, 100, 20, teamInfo.Kills.ToString("N0"), 0xFFC000, BlackColor32); - - AddBorderedText(160 + 10, 85 + i * 75, 100, 20, "Captures:", 0xFFC000, BlackColor32); - AddBorderedText(160 + 15, 105 + i * 75, 100, 20, teamInfo.Captures.ToString("N0"), 0xFFC000, - BlackColor32); - - CTFPlayerInfo pl = teamInfo.Leader; - - AddBorderedText(235 + 10, 85 + i * 75, 250, 20, "Leader:", 0xFFC000, BlackColor32); - - if (pl != null) - AddBorderedText(235 + 15, 105 + i * 75, 250, 20, pl.Player.Name, 0xFFC000, BlackColor32); - } - - AddButton(314, height - 42, 247, 248, 1); - } - - public string Center(string text) => $"
{text}
"; - - public string Color(string text, int color) => $"{text}"; - - private void AddBorderedText(int x, int y, int width, int height, string text, int color, int borderColor) - { - AddColoredText(x - 1, y - 1, width, height, text, borderColor); - AddColoredText(x - 1, y + 1, width, height, text, borderColor); - AddColoredText(x + 1, y - 1, width, height, text, borderColor); - AddColoredText(x + 1, y + 1, width, height, text, borderColor); - AddColoredText(x, y, width, height, text, color); - } - - private void AddColoredText(int x, int y, int width, int height, string text, int color) - { - if (color == 0) - AddHtml(x, y, width, height, text); - else - AddHtml(x, y, width, height, Color(text, color)); - } - } - - public sealed class CTFFlag : Item - { - public Mobile m_Fragger; - public DateTime m_FragTime; - - private int m_ReturnCount; - - public Mobile m_Returner; - public DateTime m_ReturnTime; - private Timer m_ReturnTimer; - public CTFTeamInfo m_TeamInfo; - - [Constructible] - public CTFFlag() - : base(5643) => - Movable = false; - - public CTFFlag(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "old people cookies"; - - public override void OnDoubleClick(Mobile from) - { - if (m_TeamInfo?.Game != null) - { - CTFTeamInfo ourTeam = m_TeamInfo; - CTFTeamInfo useTeam = m_TeamInfo.Game.GetTeamInfo(from); - - if (ourTeam == null || useTeam == null) - return; - - if (IsChildOf(from.Backpack)) - { - from.BeginTarget(1, false, TargetFlags.None, Flag_OnTarget); - } - else if (!from.InRange(this, 1) || !from.InLOS(this)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x26, 1019045); // I can't reach that - } - else if (ourTeam == useTeam) - { - if (Location == m_TeamInfo.Origin && Map == m_TeamInfo.Game.Facet) - { - from.Send(new UnicodeMessage(Serial, ItemID, MessageType.Regular, 0x3B2, 3, "ENU", Name, - "Touch me not for I am chaste.")); - } - else - { - CTFPlayerInfo playerInfo = useTeam[from]; - - if (playerInfo != null) - playerInfo.Score += 4; // return - - m_Returner = from; - m_ReturnTime = DateTime.UtcNow; - - SendHome(); - - from.LocalOverheadMessage(MessageType.Regular, 0x59, false, "You returned the cookies!"); - m_TeamInfo.Game.Alert("The {1} cookies have been returned by {0}.", from.Name, ourTeam.Name); - } - } - else if (!from.PlaceInBackpack(this)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x26, false, "I can't hold that."); - } - else - { - from.RevealingAction(); - - from.LocalOverheadMessage(MessageType.Regular, 0x59, false, "You stole the cookies!"); - m_TeamInfo.Game.Alert("The {1} cookies have been stolen by {0} ({2}).", from.Name, ourTeam.Name, - useTeam.Name); - - BeginCountdown(120); - } - } - } - - public override void Delete() - { - if (Parent != null) - { - SendHome(); - return; - } - - base.Delete(); - } - - public void DropTo(Mobile mob, Mobile killer) - { - m_Fragger = killer; - m_FragTime = DateTime.UtcNow; - - if (mob != null) - { - MoveToWorld(new Point3D(mob.X, mob.Y, mob.Z + 2), mob.Map); - - m_ReturnCount = Math.Min(m_ReturnCount, 10); - } - else - { - SendHome(); - } - } - - private void StopCountdown() - { - m_ReturnTimer?.Stop(); - - m_ReturnTimer = null; - } - - private void BeginCountdown(int returnCount) - { - StopCountdown(); - - m_ReturnTimer = Timer.DelayCall(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0), Countdown_OnTick); - m_ReturnCount = returnCount; - } - - private void Countdown_OnTick() - { - Mobile owner = RootParent as Mobile; - - switch (m_ReturnCount) - { - case 60: - case 30: - case 15: - case 10: - case 5: - case 4: - case 3: - case 2: - case 1: - { - owner?.SendMessage(0x26, "You have {0} {1} to capture the cookies!", m_ReturnCount, - m_ReturnCount == 1 ? "second" : "seconds"); - - break; - } - - case 0: - { - if (owner != null) - { - owner.SendMessage(0x26, "You have taken too long to capture the cookies!"); - owner.Kill(); - } - - SendHome(); - - m_TeamInfo?.Game?.Alert("The {0} cookies have been returned.", m_TeamInfo.Name); - - return; - } - } - - --m_ReturnCount; - } - - private void Flag_OnTarget(Mobile from, object obj) - { - if (m_TeamInfo == null) - return; - - if (!IsChildOf(from.Backpack)) - return; - - CTFTeamInfo ourTeam = m_TeamInfo; - CTFTeamInfo useTeam = m_TeamInfo.Game.GetTeamInfo(from); - - if (obj is CTFFlag) - { - if (obj == useTeam.Flag) - { - from.LocalOverheadMessage(MessageType.Regular, 0x59, false, "You captured the cookies!"); - m_TeamInfo.Game.Alert("{0} captured the {1} cookies!", from.Name, ourTeam.Name); - - SendHome(); - - CTFPlayerInfo playerInfo = useTeam[from]; - - if (playerInfo != null) - { - playerInfo.Captures += 1; - playerInfo.Score += 50; // capture - - CTFFlag teamFlag = useTeam.Flag; - - if (teamFlag.m_Fragger != null && - DateTime.UtcNow < teamFlag.m_FragTime + TimeSpan.FromSeconds(5.0) && - m_TeamInfo.Game.GetTeamInfo(teamFlag.m_Fragger) == useTeam) - { - CTFPlayerInfo assistInfo = useTeam[teamFlag.m_Fragger]; - - if (assistInfo != null) - assistInfo.Score += 6; // frag assist - } - - if (teamFlag.m_Returner != null && - DateTime.UtcNow < teamFlag.m_ReturnTime + TimeSpan.FromSeconds(5.0)) - { - CTFPlayerInfo assistInfo = useTeam[teamFlag.m_Returner]; - - if (assistInfo != null) - assistInfo.Score += 4; // return assist - } - } - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x26, false, "Those are not my cookies."); - } - } - else if (obj is Mobile passTo) - { - CTFTeamInfo passTeam = m_TeamInfo.Game.GetTeamInfo(passTo); - - if (passTo == from) - from.LocalOverheadMessage(MessageType.Regular, 0x26, false, "I can't pass to them."); - else if (passTeam == useTeam && passTo.PlaceInBackpack(this)) - passTo.LocalOverheadMessage(MessageType.Regular, 0x59, false, - $"{from.Name} has passed you the cookies!"); - else - from.LocalOverheadMessage(MessageType.Regular, 0x26, false, "I can't pass to them."); - } - } - - public void SendHome() - { - StopCountdown(); - - if (m_TeamInfo == null) - return; - - MoveToWorld(m_TeamInfo.Origin, m_TeamInfo.Game.Facet); - } - - private Mobile FindOwner(IEntity parent) - { - if (parent is Item item) - return item.RootParent as Mobile; - - if (parent is Mobile mobile) - return mobile; - - return null; - } - - public override void OnAdded(IEntity parent) - { - base.OnAdded(parent); - - Mobile mob = FindOwner(parent); - - if (mob != null) - mob.SolidHueOverride = 0x4001; - } - - public override void OnRemoved(IEntity parent) - { - base.OnRemoved(parent); - - Mobile mob = FindOwner(parent); - - if (mob != null) - mob.SolidHueOverride = m_TeamInfo?.Game.GetColor(mob) ?? -1; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public interface IRankedCTF - { - int Kills { get; } - int Captures { get; } - int Score { get; } - string Name { get; } - } - - public sealed class CTFPlayerInfo : IRankedCTF - { - private int m_Captures; - - private int m_Kills; - - private int m_Score; - private readonly CTFTeamInfo m_TeamInfo; - - public CTFPlayerInfo(CTFTeamInfo teamInfo, Mobile player) - { - m_TeamInfo = teamInfo; - Player = player; - } - - public Mobile Player { get; } - - string IRankedCTF.Name => Player.Name; - - public int Kills - { - get => m_Kills; - set - { - m_TeamInfo.Kills += value - m_Kills; - m_Kills = value; - } - } - - public int Captures - { - get => m_Captures; - set - { - m_TeamInfo.Captures += value - m_Captures; - m_Captures = value; - } - } - - public int Score - { - get => m_Score; - set - { - m_TeamInfo.Score += value - m_Score; - m_Score = value; - - if (m_TeamInfo.Leader == null || m_Score > m_TeamInfo.Leader.Score) - m_TeamInfo.Leader = this; - } - } - } - - [PropertyObject] - public sealed class CTFTeamInfo : IRankedCTF - { - public CTFTeamInfo(int teamID) - { - TeamID = teamID; - Players = new Dictionary(); - } - - public CTFTeamInfo(int teamID, IGenericReader ip) - { - TeamID = teamID; - Players = new Dictionary(); - - int version = ip.ReadEncodedInt(); - - switch (version) - { - case 2: - { - Board = ip.ReadItem() as CTFBoard; - - goto case 1; - } - case 1: - { - Name = ip.ReadString(); - - goto case 0; - } - case 0: - { - Color = ip.ReadEncodedInt(); - - Flag = ip.ReadItem() as CTFFlag; - Origin = ip.ReadPoint3D(); - break; - } - } - } - - public CTFGame Game { get; set; } - - public int TeamID { get; } - - public CTFPlayerInfo Leader { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public CTFBoard Board { get; set; } - - public Dictionary Players { get; } - - public CTFPlayerInfo this[Mobile mob] - { - get - { - if (mob == null) - return null; - - if (!Players.TryGetValue(mob, out CTFPlayerInfo val)) - Players[mob] = val = new CTFPlayerInfo(this, mob); - - return val; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Color { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public string Name { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public CTFFlag Flag { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D Origin { get; set; } - - string IRankedCTF.Name => $"{Name} Team"; - - public int Kills { get; set; } - - public int Captures { get; set; } - - public int Score { get; set; } - - public void Reset() - { - Kills = 0; - Captures = 0; - - Score = 0; - - Leader = null; - - Players.Clear(); - - if (Flag != null) - { - Flag.m_TeamInfo = this; - Flag.Hue = Color; - Flag.SendHome(); - } - - if (Board != null) - Board.m_TeamInfo = this; - } - - public void Serialize(IGenericWriter op) - { - op.WriteEncodedInt(2); // version - - op.Write(Board); - - op.Write(Name); - - op.WriteEncodedInt(Color); - - op.Write(Flag); - op.Write(Origin); - } - - public override string ToString() => "..."; - } - - public sealed class CTFController : EventController - { - [Constructible] - public CTFController() - { - Visible = false; - Movable = false; - - Duration = TimeSpan.FromMinutes(30.0); - - TeamInfo = new CTFTeamInfo[8]; - - for (int i = 0; i < TeamInfo.Length; ++i) - TeamInfo[i] = new CTFTeamInfo(i); - } - - public CTFController(Serial serial) - : base(serial) - { - } - - public CTFTeamInfo[] TeamInfo { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public CTFTeamInfo Team1 => TeamInfo[0]; - - [CommandProperty(AccessLevel.GameMaster)] - public CTFTeamInfo Team2 => TeamInfo[1]; - - [CommandProperty(AccessLevel.GameMaster)] - public CTFTeamInfo Team3 => TeamInfo[2]; - - [CommandProperty(AccessLevel.GameMaster)] - public CTFTeamInfo Team4 => TeamInfo[3]; - - [CommandProperty(AccessLevel.GameMaster)] - public CTFTeamInfo Team5 => TeamInfo[4]; - - [CommandProperty(AccessLevel.GameMaster)] - public CTFTeamInfo Team6 => TeamInfo[5]; - - [CommandProperty(AccessLevel.GameMaster)] - public CTFTeamInfo Team7 => TeamInfo[6]; - - [CommandProperty(AccessLevel.GameMaster)] - public CTFTeamInfo Team8 => TeamInfo[7]; - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan Duration { get; set; } - - public override string Title => "CTF"; - - public override string GetTeamName(int teamID) => TeamInfo[teamID % TeamInfo.Length].Name; - - public override EventGame Construct(DuelContext context) => new CTFGame(this, context); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(2); - - writer.Write(Duration); - - writer.WriteEncodedInt(TeamInfo.Length); - - for (int i = 0; i < TeamInfo.Length; ++i) - TeamInfo[i].Serialize(writer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 2: - { - Duration = reader.ReadTimeSpan(); - - goto case 1; - } - case 1: - { - TeamInfo = new CTFTeamInfo[reader.ReadEncodedInt()]; - - for (int i = 0; i < TeamInfo.Length; ++i) - TeamInfo[i] = new CTFTeamInfo(i, reader); - - break; - } - case 0: - { - TeamInfo = new CTFTeamInfo[8]; - - for (int i = 0; i < TeamInfo.Length; ++i) - TeamInfo[i] = new CTFTeamInfo(i); - - break; - } - } - - if (version < 2) - Duration = TimeSpan.FromMinutes(30.0); - } - } - - public sealed class CTFGame : EventGame - { - private Timer m_FinishTimer; - - public CTFGame(CTFController controller, DuelContext context) : base(context) => Controller = controller; - - public CTFController Controller { get; } - - public Map Facet - { - get - { - if (m_Context.Arena != null) - return m_Context.Arena.Facet; - - return Controller.Map; - } - } - - public static void Initialize() - { - for (int i = 0x7C9; i <= 0x7D0; ++i) - TileData.ItemTable[i].Flags |= TileFlag.NoShoot; - } - - public void Alert(string text) - { - m_Context.m_Tournament?.Alert(text); - - for (int i = 0; i < m_Context.Participants.Count; ++i) - { - Participant p = m_Context.Participants[i]; - - for (int j = 0; j < p.Players.Length; ++j) - if (p.Players[j] != null) - p.Players[j].Mobile.SendMessage(0x35, text); - } - } - - public void Alert(string format, params object[] args) - { - Alert(string.Format(format, args)); - } - - public CTFTeamInfo GetTeamInfo(Mobile mob) - { - int teamID = GetTeamID(mob); - - if (teamID >= 0) - return Controller.TeamInfo[teamID % Controller.TeamInfo.Length]; - - return null; - } - - public int GetTeamID(Mobile mob) - { - if (!(mob is PlayerMobile pm)) - return -1; - - if (pm.DuelContext == null || pm.DuelContext != m_Context) - return -1; - - if (pm.DuelPlayer?.Eliminated != false) - return -1; - - return pm.DuelContext.Participants.IndexOf(pm.DuelPlayer.Participant); - } - - public int GetColor(Mobile mob) - { - CTFTeamInfo teamInfo = GetTeamInfo(mob); - - if (teamInfo != null) - return teamInfo.Color; - - return -1; - } - - private void ApplyHues(Participant p, int hueOverride) - { - for (int i = 0; i < p.Players.Length; ++i) - if (p.Players[i] != null) - p.Players[i].Mobile.SolidHueOverride = hueOverride; - } - - public void DelayBounce(TimeSpan ts, Mobile mob, Container corpse) - { - Timer.DelayCall(ts, DelayBounce_Callback, mob, corpse); - } - - private void DelayBounce_Callback(Mobile mob, Container corpse) - { - DuelPlayer dp = (mob as PlayerMobile)?.DuelPlayer; - - m_Context.RemoveAggressions(mob); - - if (dp?.Eliminated == false) - mob.MoveToWorld(m_Context.Arena.GetBaseStartPoint(GetTeamID(mob)), Facet); - else - m_Context.SendOutside(mob); - - m_Context.Refresh(mob, corpse); - DuelContext.Debuff(mob); - DuelContext.CancelSpell(mob); - mob.Frozen = false; - } - - public override bool OnDeath(Mobile mob, Container corpse) - { - Mobile killer = mob.FindMostRecentDamager(false); - - bool hadFlag = false; - - corpse.FindItemsByType(false).ForEach(flag => - { - hadFlag = true; - flag.DropTo(mob, killer); - }); - - mob.Backpack?.FindItemsByType(false).ForEach(flag => - { - hadFlag = true; - flag.DropTo(mob, killer); - }); - - if (killer?.Player == true) - { - CTFTeamInfo teamInfo = GetTeamInfo(killer); - CTFTeamInfo victInfo = GetTeamInfo(mob); - - if (teamInfo != null && teamInfo != victInfo) - { - CTFPlayerInfo playerInfo = teamInfo[killer]; - - if (playerInfo != null) - { - playerInfo.Kills += 1; - playerInfo.Score += 1; // base frag - - if (hadFlag) - playerInfo.Score += 4; // fragged flag carrier - - if (mob.InRange(teamInfo.Origin, 24) && mob.Map == Facet) - playerInfo.Score += 1; // fragged in base -- guarding - - for (int i = 0; i < Controller.TeamInfo.Length; ++i) - { - if (Controller.TeamInfo[i] == teamInfo) - continue; - - Mobile ourFlagCarrier = null; - - if (Controller.TeamInfo[i].Flag != null) - ourFlagCarrier = Controller.TeamInfo[i].Flag.RootParent as Mobile; - - if (ourFlagCarrier != null && GetTeamInfo(ourFlagCarrier) == teamInfo) - { - if (ourFlagCarrier.Aggressors.Any(aggr => aggr.Defender == ourFlagCarrier && aggr.Attacker == mob)) - playerInfo.Score += 2; // helped defend guy capturing enemy flag - - if (mob.Map == ourFlagCarrier.Map && ourFlagCarrier.InRange(mob, 12)) - playerInfo.Score += 1; // helped defend guy capturing enemy flag - } - } - } - } - } - - mob.CloseGump(); - mob.SendGump(new CTFBoardGump(mob, this)); - - m_Context.Requip(mob, corpse); - DelayBounce(TimeSpan.FromSeconds(30.0), mob, corpse); - - return false; - } - - public override void OnStart() - { - for (int i = 0; i < Controller.TeamInfo.Length; ++i) - { - CTFTeamInfo teamInfo = Controller.TeamInfo[i]; - - teamInfo.Game = this; - teamInfo.Reset(); - } - - for (int i = 0; i < m_Context.Participants.Count; ++i) - ApplyHues(m_Context.Participants[i], Controller.TeamInfo[i % 8].Color); - - m_FinishTimer?.Stop(); - - m_FinishTimer = Timer.DelayCall(Controller.Duration, Finish_Callback); - } - - private void Finish_Callback() - { - List teams = new List(); - - for (int i = 0; i < m_Context.Participants.Count; ++i) - { - CTFTeamInfo teamInfo = Controller.TeamInfo[i % 8]; - - if (teamInfo?.Flag == null) - continue; - - teams.Add(teamInfo); - } - - teams.Sort((a, b) => b.Score - a.Score); - - Tournament tourney = m_Context.m_Tournament; - - StringBuilder sb = new StringBuilder(); - - if (tourney != null) - { - if (tourney.TourneyType == TourneyType.FreeForAll) - { - sb.Append(m_Context.Participants.Count * tourney.PlayersPerParticipant); - sb.Append("-man FFA"); - } - else if (tourney.TourneyType == TourneyType.RandomTeam) - { - sb.Append(tourney.ParticipantsPerMatch); - sb.Append("-team"); - } - else if (tourney.TourneyType == TourneyType.RedVsBlue) - { - sb.Append("Red v Blue"); - } - else if (tourney.TourneyType == TourneyType.Faction) - { - sb.Append(tourney.ParticipantsPerMatch); - sb.Append("-team Faction"); - } - else - { - for (int i = 0; i < tourney.ParticipantsPerMatch; ++i) - { - if (sb.Length > 0) - sb.Append('v'); - - sb.Append(tourney.PlayersPerParticipant); - } - } - } - - if (Controller != null) - sb.Append(' ').Append(Controller.Title); - - string title = sb.ToString(); - - CTFTeamInfo winner = teams.Count > 0 ? teams[0] : null; - - for (int i = 0; i < teams.Count; ++i) - { - TrophyRank rank = TrophyRank.Bronze; - - if (i == 0) - rank = TrophyRank.Gold; - else if (i == 1) - rank = TrophyRank.Silver; - - CTFPlayerInfo leader = teams[i].Leader; - - foreach (CTFPlayerInfo pl in teams[i].Players.Values) - { - Mobile mob = pl.Player; - - if (mob == null) - continue; - - // "Red v Blue CTF Champion" - - sb = new StringBuilder(); - - sb.Append(title); - - if (pl == leader) - sb.Append(" Leader"); - - if (pl.Score > 0) - { - sb.Append(": "); - - sb.Append(pl.Score.ToString("N0")); - sb.Append(pl.Score == 1 ? " point" : " points"); - - if (pl.Kills > 0) - { - sb.Append(", "); - sb.Append(pl.Kills.ToString("N0")); - sb.Append(pl.Kills == 1 ? " kill" : " kills"); - } - - if (pl.Captures > 0) - { - sb.Append(", "); - sb.Append(pl.Captures.ToString("N0")); - sb.Append(pl.Captures == 1 ? " capture" : " captures"); - } - } - - Item item = new Trophy(sb.ToString(), rank); - - if (pl == leader) - item.ItemID = 4810; - - item.Name = $"{item.Name}, {teams[i].Name.ToLower()} team"; - - if (!mob.PlaceInBackpack(item)) - mob.BankBox.DropItem(item); - - int cash = pl.Score * 250; - - if (cash > 0) - { - item = new BankCheck(cash); - - if (!mob.PlaceInBackpack(item)) - mob.BankBox.DropItem(item); - - mob.SendMessage( - "You have been awarded a {0} trophy and {1:N0}gp for your participation in this tournament.", - rank.ToString().ToLower(), cash); - } - else - { - mob.SendMessage("You have been awarded a {0} trophy for your participation in this tournament.", - rank.ToString().ToLower()); - } - } - } - - for (int i = 0; i < m_Context.Participants.Count; ++i) - { - Participant p = m_Context.Participants[i]; - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer dp = p.Players[j]; - - if (dp?.Mobile != null) - { - dp.Mobile.CloseGump(); - dp.Mobile.SendGump(new CTFBoardGump(dp.Mobile, this)); - } - } - - if (i == winner?.TeamID) - continue; - - for (int j = 0; j < p.Players.Length; ++j) - if (p.Players[j] != null) - p.Players[j].Eliminated = true; - } - - if (winner != null) - m_Context.Finish(m_Context.Participants[winner.TeamID]); - } - - public override void OnStop() - { - for (int i = 0; i < Controller.TeamInfo.Length; ++i) - { - CTFTeamInfo teamInfo = Controller.TeamInfo[i]; - - if (teamInfo.Flag != null) - { - teamInfo.Flag.SendHome(); - teamInfo.Flag.m_TeamInfo = null; - } - - if (teamInfo.Board != null) - teamInfo.Board.m_TeamInfo = null; - - teamInfo.Game = null; - } - - for (int i = 0; i < m_Context.Participants.Count; ++i) - ApplyHues(m_Context.Participants[i], -1); - - m_FinishTimer?.Stop(); - - m_FinishTimer = null; - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Server.Gumps; +using Server.Items; +using Server.Mobiles; +using Server.Network; +using Server.Targeting; + +namespace Server.Engines.ConPVP +{ + public sealed class CTFBoard : Item + { + public CTFTeamInfo m_TeamInfo; + + [Constructible] + public CTFBoard() + : base(7774) => + Movable = false; + + public CTFBoard(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "scoreboard"; + + public override void OnDoubleClick(Mobile from) + { + if (m_TeamInfo?.Game != null) + { + from.CloseGump(); + from.SendGump(new CTFBoardGump(from, m_TeamInfo.Game)); + } + } + + 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(); + } + } + + public class CTFBoardGump : Gump + { + private const int LabelColor32 = 0xFFFFFF; + private const int BlackColor32 = 0x000000; + + private CTFGame m_Game; + + public CTFBoardGump(Mobile mob, CTFGame game, CTFTeamInfo section = null) + : base(60, 60) + { + m_Game = game; + + var ourTeam = game.GetTeamInfo(mob); + + var entries = new List(); + + if (section == null) + for (var i = 0; i < game.Context.Participants.Count; ++i) + { + var teamInfo = game.Controller.TeamInfo[i % 8]; + + if (teamInfo?.Flag == null) + continue; + + entries.Add(teamInfo); + } + else + foreach (var player in section.Players.Values) + if (player.Score > 0) + entries.Add(player); + + entries.Sort((a, b) => b.Score - a.Score); + + var height = 0; + + if (section == null) + height = 73 + entries.Count * 75 + 28; + + Closable = false; + + AddPage(0); + + AddBackground(1, 1, 398, height, 3600); + + AddImageTiled(16, 15, 369, height - 29, 3604); + + for (var i = 0; i < entries.Count; i += 1) + AddImageTiled(22, 58 + i * 75, 357, 70, 0x2430); + + AddAlphaRegion(16, 15, 369, height - 29); + + AddImage(215, -45, 0xEE40); + // AddImage( 330, 141, 0x8BA ); + + AddBorderedText(22, 22, 294, 20, Center("CTF Scoreboard"), LabelColor32, BlackColor32); + + AddImageTiled(32, 50, 264, 1, 9107); + AddImageTiled(42, 52, 264, 1, 9157); + + if (section == null) + for (var i = 0; i < entries.Count; ++i) + { + var teamInfo = entries[i] as CTFTeamInfo; + + if (teamInfo == null) + continue; + + AddImage(30, 70 + i * 75, 10152); + AddImage(30, 85 + i * 75, 10151); + AddImage(30, 100 + i * 75, 10151); + AddImage(30, 106 + i * 75, 10154); + + AddImage(24, 60 + i * 75, teamInfo == ourTeam ? 9730 : 9727, teamInfo.Color - 1); + + var nameColor = LabelColor32; + var borderColor = BlackColor32; + + switch (teamInfo.Color) + { + case 0x47E: + nameColor = 0xFFFFFF; + break; + + case 0x4F2: + nameColor = 0x3399FF; + break; + + case 0x4F7: + nameColor = 0x33FF33; + break; + + case 0x4FC: + nameColor = 0xFF00FF; + break; + + case 0x021: + nameColor = 0xFF3333; + break; + + case 0x01A: + nameColor = 0xFF66FF; + break; + + case 0x455: + nameColor = 0x333333; + borderColor = 0xFFFFFF; + break; + } + + AddBorderedText( + 60, + 65 + i * 75, + 250, + 20, + $"{LadderGump.Rank(1 + i)}: {teamInfo.Name} Team", + nameColor, + borderColor + ); + + AddBorderedText(50 + 10, 85 + i * 75, 100, 20, "Score:", 0xFFC000, BlackColor32); + AddBorderedText(50 + 15, 105 + i * 75, 100, 20, teamInfo.Score.ToString("N0"), 0xFFC000, BlackColor32); + + AddBorderedText(110 + 10, 85 + i * 75, 100, 20, "Kills:", 0xFFC000, BlackColor32); + AddBorderedText(110 + 15, 105 + i * 75, 100, 20, teamInfo.Kills.ToString("N0"), 0xFFC000, BlackColor32); + + AddBorderedText(160 + 10, 85 + i * 75, 100, 20, "Captures:", 0xFFC000, BlackColor32); + AddBorderedText( + 160 + 15, + 105 + i * 75, + 100, + 20, + teamInfo.Captures.ToString("N0"), + 0xFFC000, + BlackColor32 + ); + + var pl = teamInfo.Leader; + + AddBorderedText(235 + 10, 85 + i * 75, 250, 20, "Leader:", 0xFFC000, BlackColor32); + + if (pl != null) + AddBorderedText(235 + 15, 105 + i * 75, 250, 20, pl.Player.Name, 0xFFC000, BlackColor32); + } + + AddButton(314, height - 42, 247, 248, 1); + } + + public string Center(string text) => $"
{text}
"; + + public string Color(string text, int color) => $"{text}"; + + private void AddBorderedText(int x, int y, int width, int height, string text, int color, int borderColor) + { + AddColoredText(x - 1, y - 1, width, height, text, borderColor); + AddColoredText(x - 1, y + 1, width, height, text, borderColor); + AddColoredText(x + 1, y - 1, width, height, text, borderColor); + AddColoredText(x + 1, y + 1, width, height, text, borderColor); + AddColoredText(x, y, width, height, text, color); + } + + private void AddColoredText(int x, int y, int width, int height, string text, int color) + { + if (color == 0) + AddHtml(x, y, width, height, text); + else + AddHtml(x, y, width, height, Color(text, color)); + } + } + + public sealed class CTFFlag : Item + { + public Mobile m_Fragger; + public DateTime m_FragTime; + + private int m_ReturnCount; + + public Mobile m_Returner; + public DateTime m_ReturnTime; + private Timer m_ReturnTimer; + public CTFTeamInfo m_TeamInfo; + + [Constructible] + public CTFFlag() + : base(5643) => + Movable = false; + + public CTFFlag(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "old people cookies"; + + public override void OnDoubleClick(Mobile from) + { + if (m_TeamInfo?.Game != null) + { + var ourTeam = m_TeamInfo; + var useTeam = m_TeamInfo.Game.GetTeamInfo(from); + + if (ourTeam == null || useTeam == null) + return; + + if (IsChildOf(from.Backpack)) + { + from.BeginTarget(1, false, TargetFlags.None, Flag_OnTarget); + } + else if (!from.InRange(this, 1) || !from.InLOS(this)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x26, 1019045); // I can't reach that + } + else if (ourTeam == useTeam) + { + if (Location == m_TeamInfo.Origin && Map == m_TeamInfo.Game.Facet) + { + from.Send( + new UnicodeMessage( + Serial, + ItemID, + MessageType.Regular, + 0x3B2, + 3, + "ENU", + Name, + "Touch me not for I am chaste." + ) + ); + } + else + { + var playerInfo = useTeam[from]; + + if (playerInfo != null) + playerInfo.Score += 4; // return + + m_Returner = from; + m_ReturnTime = DateTime.UtcNow; + + SendHome(); + + from.LocalOverheadMessage(MessageType.Regular, 0x59, false, "You returned the cookies!"); + m_TeamInfo.Game.Alert("The {1} cookies have been returned by {0}.", from.Name, ourTeam.Name); + } + } + else if (!from.PlaceInBackpack(this)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x26, false, "I can't hold that."); + } + else + { + from.RevealingAction(); + + from.LocalOverheadMessage(MessageType.Regular, 0x59, false, "You stole the cookies!"); + m_TeamInfo.Game.Alert( + "The {1} cookies have been stolen by {0} ({2}).", + from.Name, + ourTeam.Name, + useTeam.Name + ); + + BeginCountdown(120); + } + } + } + + public override void Delete() + { + if (Parent != null) + { + SendHome(); + return; + } + + base.Delete(); + } + + public void DropTo(Mobile mob, Mobile killer) + { + m_Fragger = killer; + m_FragTime = DateTime.UtcNow; + + if (mob != null) + { + MoveToWorld(new Point3D(mob.X, mob.Y, mob.Z + 2), mob.Map); + + m_ReturnCount = Math.Min(m_ReturnCount, 10); + } + else + { + SendHome(); + } + } + + private void StopCountdown() + { + m_ReturnTimer?.Stop(); + + m_ReturnTimer = null; + } + + private void BeginCountdown(int returnCount) + { + StopCountdown(); + + m_ReturnTimer = Timer.DelayCall(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0), Countdown_OnTick); + m_ReturnCount = returnCount; + } + + private void Countdown_OnTick() + { + var owner = RootParent as Mobile; + + switch (m_ReturnCount) + { + case 60: + case 30: + case 15: + case 10: + case 5: + case 4: + case 3: + case 2: + case 1: + { + owner?.SendMessage( + 0x26, + "You have {0} {1} to capture the cookies!", + m_ReturnCount, + m_ReturnCount == 1 ? "second" : "seconds" + ); + + break; + } + + case 0: + { + if (owner != null) + { + owner.SendMessage(0x26, "You have taken too long to capture the cookies!"); + owner.Kill(); + } + + SendHome(); + + m_TeamInfo?.Game?.Alert("The {0} cookies have been returned.", m_TeamInfo.Name); + + return; + } + } + + --m_ReturnCount; + } + + private void Flag_OnTarget(Mobile from, object obj) + { + if (m_TeamInfo == null) + return; + + if (!IsChildOf(from.Backpack)) + return; + + var ourTeam = m_TeamInfo; + var useTeam = m_TeamInfo.Game.GetTeamInfo(from); + + if (obj is CTFFlag) + { + if (obj == useTeam.Flag) + { + from.LocalOverheadMessage(MessageType.Regular, 0x59, false, "You captured the cookies!"); + m_TeamInfo.Game.Alert("{0} captured the {1} cookies!", from.Name, ourTeam.Name); + + SendHome(); + + var playerInfo = useTeam[from]; + + if (playerInfo != null) + { + playerInfo.Captures += 1; + playerInfo.Score += 50; // capture + + var teamFlag = useTeam.Flag; + + if (teamFlag.m_Fragger != null && + DateTime.UtcNow < teamFlag.m_FragTime + TimeSpan.FromSeconds(5.0) && + m_TeamInfo.Game.GetTeamInfo(teamFlag.m_Fragger) == useTeam) + { + var assistInfo = useTeam[teamFlag.m_Fragger]; + + if (assistInfo != null) + assistInfo.Score += 6; // frag assist + } + + if (teamFlag.m_Returner != null && + DateTime.UtcNow < teamFlag.m_ReturnTime + TimeSpan.FromSeconds(5.0)) + { + var assistInfo = useTeam[teamFlag.m_Returner]; + + if (assistInfo != null) + assistInfo.Score += 4; // return assist + } + } + } + else + { + from.LocalOverheadMessage(MessageType.Regular, 0x26, false, "Those are not my cookies."); + } + } + else if (obj is Mobile passTo) + { + var passTeam = m_TeamInfo.Game.GetTeamInfo(passTo); + + if (passTo == from) + from.LocalOverheadMessage(MessageType.Regular, 0x26, false, "I can't pass to them."); + else if (passTeam == useTeam && passTo.PlaceInBackpack(this)) + passTo.LocalOverheadMessage( + MessageType.Regular, + 0x59, + false, + $"{from.Name} has passed you the cookies!" + ); + else + from.LocalOverheadMessage(MessageType.Regular, 0x26, false, "I can't pass to them."); + } + } + + public void SendHome() + { + StopCountdown(); + + if (m_TeamInfo == null) + return; + + MoveToWorld(m_TeamInfo.Origin, m_TeamInfo.Game.Facet); + } + + private Mobile FindOwner(IEntity parent) + { + if (parent is Item item) + return item.RootParent as Mobile; + + if (parent is Mobile mobile) + return mobile; + + return null; + } + + public override void OnAdded(IEntity parent) + { + base.OnAdded(parent); + + var mob = FindOwner(parent); + + if (mob != null) + mob.SolidHueOverride = 0x4001; + } + + public override void OnRemoved(IEntity parent) + { + base.OnRemoved(parent); + + var mob = FindOwner(parent); + + if (mob != null) + mob.SolidHueOverride = m_TeamInfo?.Game.GetColor(mob) ?? -1; + } + + 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(); + } + } + + public interface IRankedCTF + { + int Kills { get; } + int Captures { get; } + int Score { get; } + string Name { get; } + } + + public sealed class CTFPlayerInfo : IRankedCTF + { + private readonly CTFTeamInfo m_TeamInfo; + private int m_Captures; + + private int m_Kills; + + private int m_Score; + + public CTFPlayerInfo(CTFTeamInfo teamInfo, Mobile player) + { + m_TeamInfo = teamInfo; + Player = player; + } + + public Mobile Player { get; } + + string IRankedCTF.Name => Player.Name; + + public int Kills + { + get => m_Kills; + set + { + m_TeamInfo.Kills += value - m_Kills; + m_Kills = value; + } + } + + public int Captures + { + get => m_Captures; + set + { + m_TeamInfo.Captures += value - m_Captures; + m_Captures = value; + } + } + + public int Score + { + get => m_Score; + set + { + m_TeamInfo.Score += value - m_Score; + m_Score = value; + + if (m_TeamInfo.Leader == null || m_Score > m_TeamInfo.Leader.Score) + m_TeamInfo.Leader = this; + } + } + } + + [PropertyObject] + public sealed class CTFTeamInfo : IRankedCTF + { + public CTFTeamInfo(int teamID) + { + TeamID = teamID; + Players = new Dictionary(); + } + + public CTFTeamInfo(int teamID, IGenericReader ip) + { + TeamID = teamID; + Players = new Dictionary(); + + var version = ip.ReadEncodedInt(); + + switch (version) + { + case 2: + { + Board = ip.ReadItem() as CTFBoard; + + goto case 1; + } + case 1: + { + Name = ip.ReadString(); + + goto case 0; + } + case 0: + { + Color = ip.ReadEncodedInt(); + + Flag = ip.ReadItem() as CTFFlag; + Origin = ip.ReadPoint3D(); + break; + } + } + } + + public CTFGame Game { get; set; } + + public int TeamID { get; } + + public CTFPlayerInfo Leader { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public CTFBoard Board { get; set; } + + public Dictionary Players { get; } + + public CTFPlayerInfo this[Mobile mob] + { + get + { + if (mob == null) + return null; + + if (!Players.TryGetValue(mob, out var val)) + Players[mob] = val = new CTFPlayerInfo(this, mob); + + return val; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Color { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public string Name { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public CTFFlag Flag { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D Origin { get; set; } + + string IRankedCTF.Name => $"{Name} Team"; + + public int Kills { get; set; } + + public int Captures { get; set; } + + public int Score { get; set; } + + public void Reset() + { + Kills = 0; + Captures = 0; + + Score = 0; + + Leader = null; + + Players.Clear(); + + if (Flag != null) + { + Flag.m_TeamInfo = this; + Flag.Hue = Color; + Flag.SendHome(); + } + + if (Board != null) + Board.m_TeamInfo = this; + } + + public void Serialize(IGenericWriter op) + { + op.WriteEncodedInt(2); // version + + op.Write(Board); + + op.Write(Name); + + op.WriteEncodedInt(Color); + + op.Write(Flag); + op.Write(Origin); + } + + public override string ToString() => "..."; + } + + public sealed class CTFController : EventController + { + [Constructible] + public CTFController() + { + Visible = false; + Movable = false; + + Duration = TimeSpan.FromMinutes(30.0); + + TeamInfo = new CTFTeamInfo[8]; + + for (var i = 0; i < TeamInfo.Length; ++i) + TeamInfo[i] = new CTFTeamInfo(i); + } + + public CTFController(Serial serial) + : base(serial) + { + } + + public CTFTeamInfo[] TeamInfo { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public CTFTeamInfo Team1 => TeamInfo[0]; + + [CommandProperty(AccessLevel.GameMaster)] + public CTFTeamInfo Team2 => TeamInfo[1]; + + [CommandProperty(AccessLevel.GameMaster)] + public CTFTeamInfo Team3 => TeamInfo[2]; + + [CommandProperty(AccessLevel.GameMaster)] + public CTFTeamInfo Team4 => TeamInfo[3]; + + [CommandProperty(AccessLevel.GameMaster)] + public CTFTeamInfo Team5 => TeamInfo[4]; + + [CommandProperty(AccessLevel.GameMaster)] + public CTFTeamInfo Team6 => TeamInfo[5]; + + [CommandProperty(AccessLevel.GameMaster)] + public CTFTeamInfo Team7 => TeamInfo[6]; + + [CommandProperty(AccessLevel.GameMaster)] + public CTFTeamInfo Team8 => TeamInfo[7]; + + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan Duration { get; set; } + + public override string Title => "CTF"; + + public override string GetTeamName(int teamID) => TeamInfo[teamID % TeamInfo.Length].Name; + + public override EventGame Construct(DuelContext context) => new CTFGame(this, context); + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(2); + + writer.Write(Duration); + + writer.WriteEncodedInt(TeamInfo.Length); + + for (var i = 0; i < TeamInfo.Length; ++i) + TeamInfo[i].Serialize(writer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 2: + { + Duration = reader.ReadTimeSpan(); + + goto case 1; + } + case 1: + { + TeamInfo = new CTFTeamInfo[reader.ReadEncodedInt()]; + + for (var i = 0; i < TeamInfo.Length; ++i) + TeamInfo[i] = new CTFTeamInfo(i, reader); + + break; + } + case 0: + { + TeamInfo = new CTFTeamInfo[8]; + + for (var i = 0; i < TeamInfo.Length; ++i) + TeamInfo[i] = new CTFTeamInfo(i); + + break; + } + } + + if (version < 2) + Duration = TimeSpan.FromMinutes(30.0); + } + } + + public sealed class CTFGame : EventGame + { + private Timer m_FinishTimer; + + public CTFGame(CTFController controller, DuelContext context) : base(context) => Controller = controller; + + public CTFController Controller { get; } + + public Map Facet + { + get + { + if (m_Context.Arena != null) + return m_Context.Arena.Facet; + + return Controller.Map; + } + } + + public static void Initialize() + { + for (var i = 0x7C9; i <= 0x7D0; ++i) + TileData.ItemTable[i].Flags |= TileFlag.NoShoot; + } + + public void Alert(string text) + { + m_Context.m_Tournament?.Alert(text); + + for (var i = 0; i < m_Context.Participants.Count; ++i) + { + var p = m_Context.Participants[i]; + + for (var j = 0; j < p.Players.Length; ++j) + if (p.Players[j] != null) + p.Players[j].Mobile.SendMessage(0x35, text); + } + } + + public void Alert(string format, params object[] args) + { + Alert(string.Format(format, args)); + } + + public CTFTeamInfo GetTeamInfo(Mobile mob) + { + var teamID = GetTeamID(mob); + + if (teamID >= 0) + return Controller.TeamInfo[teamID % Controller.TeamInfo.Length]; + + return null; + } + + public int GetTeamID(Mobile mob) + { + if (!(mob is PlayerMobile pm)) + return -1; + + if (pm.DuelContext == null || pm.DuelContext != m_Context) + return -1; + + if (pm.DuelPlayer?.Eliminated != false) + return -1; + + return pm.DuelContext.Participants.IndexOf(pm.DuelPlayer.Participant); + } + + public int GetColor(Mobile mob) + { + var teamInfo = GetTeamInfo(mob); + + if (teamInfo != null) + return teamInfo.Color; + + return -1; + } + + private void ApplyHues(Participant p, int hueOverride) + { + for (var i = 0; i < p.Players.Length; ++i) + if (p.Players[i] != null) + p.Players[i].Mobile.SolidHueOverride = hueOverride; + } + + public void DelayBounce(TimeSpan ts, Mobile mob, Container corpse) + { + Timer.DelayCall(ts, DelayBounce_Callback, mob, corpse); + } + + private void DelayBounce_Callback(Mobile mob, Container corpse) + { + var dp = (mob as PlayerMobile)?.DuelPlayer; + + m_Context.RemoveAggressions(mob); + + if (dp?.Eliminated == false) + mob.MoveToWorld(m_Context.Arena.GetBaseStartPoint(GetTeamID(mob)), Facet); + else + m_Context.SendOutside(mob); + + m_Context.Refresh(mob, corpse); + DuelContext.Debuff(mob); + DuelContext.CancelSpell(mob); + mob.Frozen = false; + } + + public override bool OnDeath(Mobile mob, Container corpse) + { + var killer = mob.FindMostRecentDamager(false); + + var hadFlag = false; + + corpse.FindItemsByType(false) + .ForEach( + flag => + { + hadFlag = true; + flag.DropTo(mob, killer); + } + ); + + mob.Backpack?.FindItemsByType(false) + .ForEach( + flag => + { + hadFlag = true; + flag.DropTo(mob, killer); + } + ); + + if (killer?.Player == true) + { + var teamInfo = GetTeamInfo(killer); + var victInfo = GetTeamInfo(mob); + + if (teamInfo != null && teamInfo != victInfo) + { + var playerInfo = teamInfo[killer]; + + if (playerInfo != null) + { + playerInfo.Kills += 1; + playerInfo.Score += 1; // base frag + + if (hadFlag) + playerInfo.Score += 4; // fragged flag carrier + + if (mob.InRange(teamInfo.Origin, 24) && mob.Map == Facet) + playerInfo.Score += 1; // fragged in base -- guarding + + for (var i = 0; i < Controller.TeamInfo.Length; ++i) + { + if (Controller.TeamInfo[i] == teamInfo) + continue; + + Mobile ourFlagCarrier = null; + + if (Controller.TeamInfo[i].Flag != null) + ourFlagCarrier = Controller.TeamInfo[i].Flag.RootParent as Mobile; + + if (ourFlagCarrier != null && GetTeamInfo(ourFlagCarrier) == teamInfo) + { + if (ourFlagCarrier.Aggressors.Any( + aggr => aggr.Defender == ourFlagCarrier && aggr.Attacker == mob + )) + playerInfo.Score += 2; // helped defend guy capturing enemy flag + + if (mob.Map == ourFlagCarrier.Map && ourFlagCarrier.InRange(mob, 12)) + playerInfo.Score += 1; // helped defend guy capturing enemy flag + } + } + } + } + } + + mob.CloseGump(); + mob.SendGump(new CTFBoardGump(mob, this)); + + m_Context.Requip(mob, corpse); + DelayBounce(TimeSpan.FromSeconds(30.0), mob, corpse); + + return false; + } + + public override void OnStart() + { + for (var i = 0; i < Controller.TeamInfo.Length; ++i) + { + var teamInfo = Controller.TeamInfo[i]; + + teamInfo.Game = this; + teamInfo.Reset(); + } + + for (var i = 0; i < m_Context.Participants.Count; ++i) + ApplyHues(m_Context.Participants[i], Controller.TeamInfo[i % 8].Color); + + m_FinishTimer?.Stop(); + + m_FinishTimer = Timer.DelayCall(Controller.Duration, Finish_Callback); + } + + private void Finish_Callback() + { + var teams = new List(); + + for (var i = 0; i < m_Context.Participants.Count; ++i) + { + var teamInfo = Controller.TeamInfo[i % 8]; + + if (teamInfo?.Flag == null) + continue; + + teams.Add(teamInfo); + } + + teams.Sort((a, b) => b.Score - a.Score); + + var tourney = m_Context.m_Tournament; + + var sb = new StringBuilder(); + + if (tourney != null) + { + if (tourney.TourneyType == TourneyType.FreeForAll) + { + sb.Append(m_Context.Participants.Count * tourney.PlayersPerParticipant); + sb.Append("-man FFA"); + } + else if (tourney.TourneyType == TourneyType.RandomTeam) + { + sb.Append(tourney.ParticipantsPerMatch); + sb.Append("-team"); + } + else if (tourney.TourneyType == TourneyType.RedVsBlue) + { + sb.Append("Red v Blue"); + } + else if (tourney.TourneyType == TourneyType.Faction) + { + sb.Append(tourney.ParticipantsPerMatch); + sb.Append("-team Faction"); + } + else + { + for (var i = 0; i < tourney.ParticipantsPerMatch; ++i) + { + if (sb.Length > 0) + sb.Append('v'); + + sb.Append(tourney.PlayersPerParticipant); + } + } + } + + if (Controller != null) + sb.Append(' ').Append(Controller.Title); + + var title = sb.ToString(); + + var winner = teams.Count > 0 ? teams[0] : null; + + for (var i = 0; i < teams.Count; ++i) + { + var rank = TrophyRank.Bronze; + + if (i == 0) + rank = TrophyRank.Gold; + else if (i == 1) + rank = TrophyRank.Silver; + + var leader = teams[i].Leader; + + foreach (var pl in teams[i].Players.Values) + { + var mob = pl.Player; + + if (mob == null) + continue; + + // "Red v Blue CTF Champion" + + sb = new StringBuilder(); + + sb.Append(title); + + if (pl == leader) + sb.Append(" Leader"); + + if (pl.Score > 0) + { + sb.Append(": "); + + sb.Append(pl.Score.ToString("N0")); + sb.Append(pl.Score == 1 ? " point" : " points"); + + if (pl.Kills > 0) + { + sb.Append(", "); + sb.Append(pl.Kills.ToString("N0")); + sb.Append(pl.Kills == 1 ? " kill" : " kills"); + } + + if (pl.Captures > 0) + { + sb.Append(", "); + sb.Append(pl.Captures.ToString("N0")); + sb.Append(pl.Captures == 1 ? " capture" : " captures"); + } + } + + Item item = new Trophy(sb.ToString(), rank); + + if (pl == leader) + item.ItemID = 4810; + + item.Name = $"{item.Name}, {teams[i].Name.ToLower()} team"; + + if (!mob.PlaceInBackpack(item)) + mob.BankBox.DropItem(item); + + var cash = pl.Score * 250; + + if (cash > 0) + { + item = new BankCheck(cash); + + if (!mob.PlaceInBackpack(item)) + mob.BankBox.DropItem(item); + + mob.SendMessage( + "You have been awarded a {0} trophy and {1:N0}gp for your participation in this tournament.", + rank.ToString().ToLower(), + cash + ); + } + else + { + mob.SendMessage( + "You have been awarded a {0} trophy for your participation in this tournament.", + rank.ToString().ToLower() + ); + } + } + } + + for (var i = 0; i < m_Context.Participants.Count; ++i) + { + var p = m_Context.Participants[i]; + + for (var j = 0; j < p.Players.Length; ++j) + { + var dp = p.Players[j]; + + if (dp?.Mobile != null) + { + dp.Mobile.CloseGump(); + dp.Mobile.SendGump(new CTFBoardGump(dp.Mobile, this)); + } + } + + if (i == winner?.TeamID) + continue; + + for (var j = 0; j < p.Players.Length; ++j) + if (p.Players[j] != null) + p.Players[j].Eliminated = true; + } + + if (winner != null) + m_Context.Finish(m_Context.Participants[winner.TeamID]); + } + + public override void OnStop() + { + for (var i = 0; i < Controller.TeamInfo.Length; ++i) + { + var teamInfo = Controller.TeamInfo[i]; + + if (teamInfo.Flag != null) + { + teamInfo.Flag.SendHome(); + teamInfo.Flag.m_TeamInfo = null; + } + + if (teamInfo.Board != null) + teamInfo.Board.m_TeamInfo = null; + + teamInfo.Game = null; + } + + for (var i = 0; i < m_Context.Participants.Count; ++i) + ApplyHues(m_Context.Participants[i], -1); + + m_FinishTimer?.Stop(); + + m_FinishTimer = null; + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Games/DoubleDom.cs b/Projects/UOContent/Engines/ConPVP/Games/DoubleDom.cs index 89322c54c..b4f09b62a 100644 --- a/Projects/UOContent/Engines/ConPVP/Games/DoubleDom.cs +++ b/Projects/UOContent/Engines/ConPVP/Games/DoubleDom.cs @@ -1,1079 +1,1100 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Server.Gumps; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.ConPVP -{ - public sealed class DDBoard : Item - { - public DDTeamInfo m_TeamInfo; - - [Constructible] - public DDBoard() - : base(7774) => - Movable = false; - - public DDBoard(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "scoreboard"; - - public override void OnDoubleClick(Mobile from) - { - if (m_TeamInfo?.Game != null) - { - from.CloseGump(); - from.SendGump(new DDBoardGump(from, m_TeamInfo.Game)); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DDBoardGump : Gump - { - private const int LabelColor32 = 0xFFFFFF; - private const int BlackColor32 = 0x000000; - - // private DDGame m_Game; - - public DDBoardGump(Mobile mob, DDGame game, DDTeamInfo section = null) - : base(60, 60) - { - // m_Game = game; - - DDTeamInfo ourTeam = game.GetTeamInfo(mob); - - List entries = new List(); - - if (section == null) - for (int i = 0; i < game.Context.Participants.Count; ++i) - { - DDTeamInfo teamInfo = game.Controller.TeamInfo[i % game.Controller.TeamInfo.Length]; - - if (teamInfo != null) - entries.Add(teamInfo); - } - else - foreach (DDPlayerInfo player in section.Players.Values) - if (player.Score > 0) - entries.Add(player); - - entries.Sort((a, b) => b.Score - a.Score); - - int height = 0; - - if (section == null) - height = 73 + entries.Count * 75 + 28; - - Closable = false; - - AddPage(0); - - AddBackground(1, 1, 398, height, 3600); - - AddImageTiled(16, 15, 369, height - 29, 3604); - - for (int i = 0; i < entries.Count; i += 1) - AddImageTiled(22, 58 + i * 75, 357, 70, 0x2430); - - AddAlphaRegion(16, 15, 369, height - 29); - - AddImage(215, -45, 0xEE40); - // AddImage( 330, 141, 0x8BA ); - - AddBorderedText(22, 22, 294, 20, Center("DD Scoreboard"), LabelColor32, BlackColor32); - - AddImageTiled(32, 50, 264, 1, 9107); - AddImageTiled(42, 52, 264, 1, 9157); - - if (section == null) - for (int i = 0; i < entries.Count; ++i) - { - DDTeamInfo teamInfo = entries[i] as DDTeamInfo; - - AddImage(30, 70 + i * 75, 10152); - AddImage(30, 85 + i * 75, 10151); - AddImage(30, 100 + i * 75, 10151); - AddImage(30, 106 + i * 75, 10154); - - AddImage(24, 60 + i * 75, teamInfo == ourTeam ? 9730 : 9727, teamInfo.Color - 1); - - int nameColor = LabelColor32; - int borderColor = BlackColor32; - - switch (teamInfo.Color) - { - case 0x47E: - nameColor = 0xFFFFFF; - break; - - case 0x4F2: - nameColor = 0x3399FF; - break; - - case 0x4F7: - nameColor = 0x33FF33; - break; - - case 0x4FC: - nameColor = 0xFF00FF; - break; - - case 0x021: - nameColor = 0xFF3333; - break; - - case 0x01A: - nameColor = 0xFF66FF; - break; - - case 0x455: - nameColor = 0x333333; - borderColor = 0xFFFFFF; - break; - } - - AddBorderedText(60, 65 + i * 75, 250, 20, $"{LadderGump.Rank(1 + i)}: {teamInfo.Name}", nameColor, - borderColor); - - AddBorderedText(50 + 10, 85 + i * 75, 100, 20, "Score:", 0xFFC000, BlackColor32); - AddBorderedText(50 + 15, 105 + i * 75, 100, 20, teamInfo.Score.ToString("N0"), 0xFFC000, BlackColor32); - - AddBorderedText(110 + 10, 85 + i * 75, 100, 20, "Kills:", 0xFFC000, BlackColor32); - AddBorderedText(110 + 15, 105 + i * 75, 100, 20, teamInfo.Kills.ToString("N0"), 0xFFC000, BlackColor32); - - AddBorderedText(160 + 10, 85 + i * 75, 100, 20, "Captures:", 0xFFC000, BlackColor32); - AddBorderedText(160 + 15, 105 + i * 75, 100, 20, teamInfo.Captures.ToString("N0"), 0xFFC000, - BlackColor32); - - DDPlayerInfo pl = teamInfo.Leader; - - AddBorderedText(235 + 10, 85 + i * 75, 250, 20, "Leader:", 0xFFC000, BlackColor32); - - if (pl != null) - AddBorderedText(235 + 15, 105 + i * 75, 250, 20, pl.Player.Name, 0xFFC000, BlackColor32); - } - - AddButton(314, height - 42, 247, 248, 1); - } - - public string Center(string text) => $"
{text}
"; - - public string Color(string text, int color) => $"{text}"; - - private void AddBorderedText(int x, int y, int width, int height, string text, int color, int borderColor) - { - AddColoredText(x - 1, y - 1, width, height, text, borderColor); - AddColoredText(x - 1, y + 1, width, height, text, borderColor); - AddColoredText(x + 1, y - 1, width, height, text, borderColor); - AddColoredText(x + 1, y + 1, width, height, text, borderColor); - AddColoredText(x, y, width, height, text, color); - } - - private void AddColoredText(int x, int y, int width, int height, string text, int color) - { - if (color == 0) - AddHtml(x, y, width, height, text); - else - AddHtml(x, y, width, height, Color(text, color)); - } - } - - public sealed class DDPlayerInfo : IRankedCTF - { - private int m_Captures; - - private int m_Kills; - - private int m_Score; - private readonly DDTeamInfo m_TeamInfo; - - public DDPlayerInfo(DDTeamInfo teamInfo, Mobile player) - { - m_TeamInfo = teamInfo; - Player = player; - } - - public Mobile Player { get; } - - public string Name => Player.Name; - - public int Kills - { - get => m_Kills; - set - { - m_TeamInfo.Kills += value - m_Kills; - m_Kills = value; - } - } - - public int Captures - { - get => m_Captures; - set - { - m_TeamInfo.Captures += value - m_Captures; - m_Captures = value; - } - } - - public int Score - { - get => m_Score; - set - { - m_TeamInfo.Score += value - m_Score; - m_Score = value; - - if (m_TeamInfo.Leader == null || m_Score > m_TeamInfo.Leader.Score) - m_TeamInfo.Leader = this; - } - } - } - - [PropertyObject] - public sealed class DDTeamInfo : IRankedCTF - { - public DDTeamInfo(int teamID) - { - TeamID = teamID; - Players = new Dictionary(); - } - - public DDTeamInfo(int teamID, IGenericReader ip) - { - TeamID = teamID; - Players = new Dictionary(); - - int version = ip.ReadEncodedInt(); - - switch (version) - { - case 0: - { - Board = ip.ReadItem() as DDBoard; - TeamName = ip.ReadString(); - Color = ip.ReadEncodedInt(); - Origin = ip.ReadPoint3D(); - break; - } - } - } - - public DDGame Game { get; set; } - - public int TeamID { get; } - - public DDPlayerInfo Leader { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DDBoard Board { get; set; } - - public Dictionary Players { get; } - - public DDPlayerInfo this[Mobile mob] - { - get - { - if (mob == null) - return null; - - if (!Players.TryGetValue(mob, out DDPlayerInfo val)) - Players[mob] = val = new DDPlayerInfo(this, mob); - - return val; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Color { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public string TeamName { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D Origin { get; set; } - - public string Name => $"{TeamName} Team"; - - public int Kills { get; set; } - - public int Captures { get; set; } - - public int Score { get; set; } - - public void Reset() - { - Kills = 0; - Captures = 0; - - Score = 0; - - Leader = null; - - Players.Clear(); - - if (Board != null) - Board.m_TeamInfo = this; - } - - public void Serialize(IGenericWriter op) - { - op.WriteEncodedInt(0); // version - - op.Write(Board); - op.Write(TeamName); - op.WriteEncodedInt(Color); - op.Write(Origin); - } - - public override string ToString() => "..."; - } - - public sealed class DDController : EventController - { - [Constructible] - public DDController() - { - Visible = false; - Movable = false; - - Duration = TimeSpan.FromMinutes(30.0); - - TeamInfo = new DDTeamInfo[2]; - - for (int i = 0; i < TeamInfo.Length; ++i) - TeamInfo[i] = new DDTeamInfo(i); - } - - public DDController(Serial serial) - : base(serial) - { - } - - public DDTeamInfo[] TeamInfo { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DDTeamInfo Team1 => TeamInfo[0]; - - [CommandProperty(AccessLevel.GameMaster)] - public DDTeamInfo Team2 => TeamInfo[1]; - - [CommandProperty(AccessLevel.GameMaster)] - public DDWayPoint PointA { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DDWayPoint PointB { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan Duration { get; set; } - - public override string Title => "DoubleDom"; - - public override string DefaultName => "DD Controller"; - - public override string GetTeamName(int teamID) => TeamInfo[teamID % TeamInfo.Length].Name; - - public override EventGame Construct(DuelContext context) => new DDGame(this, context); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(Duration); - - writer.WriteEncodedInt(TeamInfo.Length); - - for (int i = 0; i < TeamInfo.Length; ++i) - TeamInfo[i].Serialize(writer); - - writer.Write(PointA); - writer.Write(PointB); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Duration = reader.ReadTimeSpan(); - TeamInfo = new DDTeamInfo[reader.ReadEncodedInt()]; - - for (int i = 0; i < TeamInfo.Length; ++i) - TeamInfo[i] = new DDTeamInfo(i, reader); - - PointA = reader.ReadItem() as DDWayPoint; - PointB = reader.ReadItem() as DDWayPoint; - - break; - } - } - } - } - - public sealed class DDGame : EventGame - { - private int m_CapStage; - - private bool m_Capturable = true; - private Timer m_CaptureTimer; - - private Timer m_FinishTimer; - private Timer m_UncaptureTimer; - - public DDGame(DDController controller, DuelContext context) : base(context) => Controller = controller; - - public DDController Controller { get; } - - public Map Facet - { - get - { - if (m_Context.Arena != null) - return m_Context.Arena.Facet; - - return Controller.Map; - } - } - - public void Alert(string text) - { - m_Context.m_Tournament?.Alert(text); - - for (int i = 0; i < m_Context.Participants.Count; ++i) - { - Participant p = m_Context.Participants[i]; - - for (int j = 0; j < p.Players.Length; ++j) - if (p.Players[j] != null) - p.Players[j].Mobile.SendMessage(0x35, text); - } - } - - public void Alert(string format, params object[] args) - { - Alert(string.Format(format, args)); - } - - public DDTeamInfo GetTeamInfo(Mobile mob) - { - int teamID = GetTeamID(mob); - - if (teamID >= 0) - return Controller.TeamInfo[teamID % Controller.TeamInfo.Length]; - - return null; - } - - public int GetTeamID(Mobile mob) - { - if (!(mob is PlayerMobile pm)) - return -1; - - if (pm.DuelContext == null || pm.DuelContext != m_Context) - return -1; - - if (pm.DuelPlayer?.Eliminated != false) - return -1; - - return pm.DuelContext.Participants.IndexOf(pm.DuelPlayer.Participant); - } - - public int GetColor(Mobile mob) => GetTeamInfo(mob)?.Color ?? -1; - - private void ApplyHues(Participant p, int hueOverride) - { - for (int i = 0; i < p.Players.Length; ++i) - if (p.Players[i] != null) - p.Players[i].Mobile.SolidHueOverride = hueOverride; - } - - public void DelayBounce(TimeSpan ts, Mobile mob, Container corpse) - { - Timer.DelayCall(ts, DelayBounce_Callback, mob, corpse); - } - - private void DelayBounce_Callback(Mobile mob, Container corpse) - { - DuelPlayer dp = (mob as PlayerMobile)?.DuelPlayer; - - m_Context.RemoveAggressions(mob); - - if (dp?.Eliminated == false) - mob.MoveToWorld(m_Context.Arena.GetBaseStartPoint(GetTeamID(mob)), Facet); - else - m_Context.SendOutside(mob); - - m_Context.Refresh(mob, corpse); - DuelContext.Debuff(mob); - DuelContext.CancelSpell(mob); - mob.Frozen = false; - } - - public override bool OnDeath(Mobile mob, Container corpse) - { - Mobile killer = mob.FindMostRecentDamager(false); - - if (killer?.Player == true) - { - DDTeamInfo teamInfo = GetTeamInfo(killer); - DDTeamInfo victInfo = GetTeamInfo(mob); - - if (teamInfo != null && teamInfo != victInfo) - { - DDPlayerInfo playerInfo = teamInfo[killer]; - - if (playerInfo != null) - { - playerInfo.Kills += 1; - playerInfo.Score += 1; // base frag - - // extra points for killing someone on the waypoint - if (Controller.PointA != null) - if (mob.InRange(Controller.PointA, 2)) - playerInfo.Score += 1; - - if (Controller.PointB != null) - if (mob.InRange(Controller.PointB, 2)) - playerInfo.Score += 1; - } - - playerInfo = victInfo[mob]; - if (playerInfo != null) - playerInfo.Score -= 1; - } - } - - mob.CloseGump(); - mob.SendGump(new DDBoardGump(mob, this)); - - m_Context.Requip(mob, corpse); - DelayBounce(TimeSpan.FromSeconds(30.0), mob, corpse); - - return false; - } - - public override void OnStart() - { - m_Capturable = true; - - if (m_CaptureTimer != null) - { - m_CaptureTimer.Stop(); - m_CaptureTimer = null; - } - - if (m_UncaptureTimer != null) - { - m_UncaptureTimer.Stop(); - m_UncaptureTimer = null; - } - - for (int i = 0; i < Controller.TeamInfo.Length; ++i) - { - DDTeamInfo teamInfo = Controller.TeamInfo[i]; - - teamInfo.Game = this; - teamInfo.Reset(); - } - - if (Controller.PointA != null) - Controller.PointA.Game = this; - - if (Controller.PointB != null) - Controller.PointB.Game = this; - - for (int i = 0; i < m_Context.Participants.Count; ++i) - ApplyHues(m_Context.Participants[i], - Controller.TeamInfo[i % Controller.TeamInfo.Length].Color); - - m_FinishTimer?.Stop(); - m_FinishTimer = Timer.DelayCall(Controller.Duration, Finish_Callback); - } - - private void Finish_Callback() - { - List teams = new List(); - - for (int i = 0; i < m_Context.Participants.Count; ++i) - { - DDTeamInfo teamInfo = Controller.TeamInfo[i % Controller.TeamInfo.Length]; - - if (teamInfo != null) - teams.Add(teamInfo); - } - - teams.Sort((a, b) => b.Score - a.Score); - - Tournament tourney = m_Context.m_Tournament; - - StringBuilder sb = new StringBuilder(); - - if (tourney != null) - { - if (tourney.TourneyType == TourneyType.FreeForAll) - { - sb.Append(m_Context.Participants.Count * tourney.PlayersPerParticipant); - sb.Append("-man FFA"); - } - else if (tourney.TourneyType == TourneyType.RandomTeam) - { - sb.Append(tourney.ParticipantsPerMatch); - sb.Append("-team"); - } - else if (tourney.TourneyType == TourneyType.RedVsBlue) - { - sb.Append("Red v Blue"); - } - else if (tourney.TourneyType == TourneyType.Faction) - { - sb.Append(tourney.ParticipantsPerMatch); - sb.Append("-team Faction"); - } - else - { - for (int i = 0; i < tourney.ParticipantsPerMatch; ++i) - { - if (sb.Length > 0) - sb.Append('v'); - - sb.Append(tourney.PlayersPerParticipant); - } - } - } - - if (Controller != null) - sb.Append(' ').Append(Controller.Title); - - string title = sb.ToString(); - - DDTeamInfo winner = teams.Count > 0 ? teams[0] : null; - - for (int i = 0; i < teams.Count; ++i) - { - TrophyRank rank = TrophyRank.Bronze; - - if (i == 0) - rank = TrophyRank.Gold; - else if (i == 1) - rank = TrophyRank.Silver; - - DDPlayerInfo leader = teams[i].Leader; - - foreach (DDPlayerInfo pl in teams[i].Players.Values) - { - Mobile mob = pl.Player; - - if (mob == null) - continue; - - // "Red v Blue DD Champion" - - sb = new StringBuilder(); - - sb.Append(title); - - if (pl == leader) - sb.Append(" Leader"); - - if (pl.Score > 0) - { - sb.Append(": "); - - sb.Append(pl.Score.ToString("N0")); - sb.Append(pl.Score == 1 ? " point" : " points"); - - if (pl.Kills > 0) - { - sb.Append(", "); - sb.Append(pl.Kills.ToString("N0")); - sb.Append(pl.Kills == 1 ? " kill" : " kills"); - } - - if (pl.Captures > 0) - { - sb.Append(", "); - sb.Append(pl.Captures.ToString("N0")); - sb.Append(pl.Captures == 1 ? " capture" : " captures"); - } - } - - Item item = new Trophy(sb.ToString(), rank); - - if (pl == leader) - item.ItemID = 4810; - - item.Name = $"{item.Name}, {teams[i].Name.ToLower()} team"; - - if (!mob.PlaceInBackpack(item)) - mob.BankBox.DropItem(item); - - int cash = pl.Score * 250; - - if (cash > 0) - { - item = new BankCheck(cash); - - if (!mob.PlaceInBackpack(item)) - mob.BankBox.DropItem(item); - - mob.SendMessage( - "You have been awarded a {0} trophy and {1:N0}gp for your participation in this tournament.", - rank.ToString().ToLower(), cash); - } - else - { - mob.SendMessage("You have been awarded a {0} trophy for your participation in this tournament.", - rank.ToString().ToLower()); - } - } - } - - for (int i = 0; i < m_Context.Participants.Count; ++i) - { - Participant p = m_Context.Participants[i]; - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer dp = p.Players[j]; - - if (dp?.Mobile != null) - { - dp.Mobile.CloseGump(); - dp.Mobile.SendGump(new DDBoardGump(dp.Mobile, this)); - } - } - - if (i == winner.TeamID) - continue; - - for (int j = 0; j < p.Players.Length; ++j) - if (p.Players[j] != null) - p.Players[j].Eliminated = true; - } - - m_Context.Finish(m_Context.Participants[winner.TeamID]); - } - - public override void OnStop() - { - for (int i = 0; i < Controller.TeamInfo.Length; ++i) - { - DDTeamInfo teamInfo = Controller.TeamInfo[i]; - - if (teamInfo.Board != null) - teamInfo.Board.m_TeamInfo = null; - - teamInfo.Game = null; - } - - if (Controller.PointA != null) - Controller.PointA.Game = null; - - if (Controller.PointB != null) - Controller.PointB.Game = null; - - m_Capturable = false; - - if (m_CaptureTimer != null) - { - m_CaptureTimer.Stop(); - m_CaptureTimer = null; - } - - if (m_UncaptureTimer != null) - { - m_UncaptureTimer.Stop(); - m_UncaptureTimer = null; - } - - for (int i = 0; i < m_Context.Participants.Count; ++i) - ApplyHues(m_Context.Participants[i], -1); - - m_FinishTimer?.Stop(); - m_FinishTimer = null; - } - - public void Dominate(DDWayPoint point, Mobile from, DDTeamInfo team) - { - if (point == null || from == null || team == null || !m_Capturable) - return; - - bool wasDom = Controller.PointA?.TeamOwner == Controller.PointB?.TeamOwner && Controller.PointA?.TeamOwner != null; - - point.TeamOwner = team; - Alert("{0} has captured {1}!", team.Name, point.Name); - - bool isDom = Controller.PointA?.TeamOwner == Controller.PointB?.TeamOwner && Controller.PointA?.TeamOwner != null; - - if (wasDom && !isDom) - { - Alert("Domination averted!"); - - Controller.PointA?.SetNonCaptureHue(); - Controller.PointB?.SetNonCaptureHue(); - m_CaptureTimer?.Stop(); - m_CaptureTimer = null; - } - - if (!wasDom && isDom) - { - m_CapStage = 0; - m_CaptureTimer = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromSeconds(1.0), CaptureTick); - } - } - - private void CaptureTick() - { - DDTeamInfo team = Controller.PointA?.TeamOwner ?? Controller.PointB?.TeamOwner; - - if (team == null) - { - m_Capturable = true; - m_CaptureTimer?.Stop(); - m_CaptureTimer = null; - return; - } - - if (++m_CapStage < 10) - { - Alert("{0} is dominating... {1}", team.Name, 10 - m_CapStage); - - Controller.PointA?.SetCaptureHue(m_CapStage); - Controller.PointB?.SetCaptureHue(m_CapStage); - } - else - { - Alert("{0} has scored!", team.Name); - - team.Score += 100; - team.Captures += 1; - - m_Capturable = false; - m_CapStage = 0; - m_CaptureTimer.Stop(); - m_CaptureTimer = null; - - if (Controller.PointA != null) - { - Controller.PointA.TeamOwner = null; - Controller.PointA.SetUncapturableHue(); - } - - if (Controller.PointB != null) - { - Controller.PointB.TeamOwner = null; - Controller.PointB.SetUncapturableHue(); - } - - m_UncaptureTimer = Timer.DelayCall(TimeSpan.FromSeconds(30.0), UncaptureTick); - m_UncaptureTimer.Start(); - } - } - - private void UncaptureTick() - { - m_Capturable = true; - - if (m_CaptureTimer != null) - { - m_CaptureTimer.Stop(); - m_CaptureTimer = null; - } - - if (m_UncaptureTimer != null) - { - m_UncaptureTimer.Stop(); - m_UncaptureTimer = null; - } - - if (Controller.PointA != null) - { - Controller.PointA.TeamOwner = null; - Controller.PointA.SetNonCaptureHue(); - } - - if (Controller.PointB != null) - { - Controller.PointB.TeamOwner = null; - Controller.PointB.SetNonCaptureHue(); - } - } - } - - public class DDWayPoint : BaseAddon - { - public const int UncapturableHue = 0x497; - public const int NonCapturedHue = 0x38A; - private DDGame m_Game; - private DDTeamInfo m_TeamOwner; - - [Constructible] - public DDWayPoint() - { - ItemID = 0x519; - Visible = true; - Name = "SET MY NAME"; - - AddComponent(new DDStep(0x7A8), -1, -1, -5); - AddComponent(new DDStep(0x7A6), 0, -1, -5); - AddComponent(new DDStep(0x7AA), 1, -1, -5); - - AddComponent(new DDStep(0x7A5), 1, 0, -5); - - AddComponent(new DDStep(0x7A9), 1, 1, -5); - AddComponent(new DDStep(0x7A4), 0, 1, -5); - AddComponent(new DDStep(0x7AB), -1, 1, -5); - - AddComponent(new DDStep(0x7A7), -1, 0, -5); - - SetUncapturableHue(); - } - - public DDWayPoint(Serial serial) : base(serial) - { - } - - public override bool ShareHue => false; - - public DDGame Game - { - get => m_Game; - set - { - m_Game = value; - m_TeamOwner = null; - - if (m_Game != null) - SetNonCaptureHue(); - else - SetUncapturableHue(); - } - } - - public DDTeamInfo TeamOwner - { - get => m_TeamOwner; - set - { - m_TeamOwner = value; - - SetNonCaptureHue(); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public void SetUncapturableHue() - { - for (int i = 0; i < Components.Count; i++) - Components[i].Hue = UncapturableHue; - Hue = UncapturableHue; - } - - public void SetNonCaptureHue() - { - for (int i = 0; i < Components.Count; i++) - Components[i].Hue = NonCapturedHue; - - if (m_TeamOwner != null) - Hue = m_TeamOwner.Color; - else - Hue = NonCapturedHue; - } - - public void SetCaptureHue(int stage) - { - if (m_TeamOwner == null) - return; - - Hue = m_TeamOwner.Color; - - for (int i = 0; i < Components.Count; i++) - if (i < stage) - Components[i].Hue = m_TeamOwner.Color; - else - Components[i].Hue = NonCapturedHue; - } - - public override bool OnMoveOver(Mobile from) - { - if (m_Game == null) - { - SetUncapturableHue(); - } - else if (from.Alive) - { - DDTeamInfo team = m_Game.GetTeamInfo(from); - - if (team != null && team != TeamOwner) - m_Game.Dominate(this, from, team); - } - - return true; - } - - public class DDStep : AddonComponent - { - public DDStep(int itemID) : base(itemID) => Visible = true; - - public DDStep(Serial serial) : base(serial) - { - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override bool OnMoveOver(Mobile m) => Addon.OnMoveOver(m); - } - } -} +using System; +using System.Collections.Generic; +using System.Text; +using Server.Gumps; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.ConPVP +{ + public sealed class DDBoard : Item + { + public DDTeamInfo m_TeamInfo; + + [Constructible] + public DDBoard() + : base(7774) => + Movable = false; + + public DDBoard(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "scoreboard"; + + public override void OnDoubleClick(Mobile from) + { + if (m_TeamInfo?.Game != null) + { + from.CloseGump(); + from.SendGump(new DDBoardGump(from, m_TeamInfo.Game)); + } + } + + 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(); + } + } + + public class DDBoardGump : Gump + { + private const int LabelColor32 = 0xFFFFFF; + private const int BlackColor32 = 0x000000; + + // private DDGame m_Game; + + public DDBoardGump(Mobile mob, DDGame game, DDTeamInfo section = null) + : base(60, 60) + { + // m_Game = game; + + var ourTeam = game.GetTeamInfo(mob); + + var entries = new List(); + + if (section == null) + for (var i = 0; i < game.Context.Participants.Count; ++i) + { + var teamInfo = game.Controller.TeamInfo[i % game.Controller.TeamInfo.Length]; + + if (teamInfo != null) + entries.Add(teamInfo); + } + else + foreach (var player in section.Players.Values) + if (player.Score > 0) + entries.Add(player); + + entries.Sort((a, b) => b.Score - a.Score); + + var height = 0; + + if (section == null) + height = 73 + entries.Count * 75 + 28; + + Closable = false; + + AddPage(0); + + AddBackground(1, 1, 398, height, 3600); + + AddImageTiled(16, 15, 369, height - 29, 3604); + + for (var i = 0; i < entries.Count; i += 1) + AddImageTiled(22, 58 + i * 75, 357, 70, 0x2430); + + AddAlphaRegion(16, 15, 369, height - 29); + + AddImage(215, -45, 0xEE40); + // AddImage( 330, 141, 0x8BA ); + + AddBorderedText(22, 22, 294, 20, Center("DD Scoreboard"), LabelColor32, BlackColor32); + + AddImageTiled(32, 50, 264, 1, 9107); + AddImageTiled(42, 52, 264, 1, 9157); + + if (section == null) + for (var i = 0; i < entries.Count; ++i) + { + var teamInfo = entries[i] as DDTeamInfo; + + AddImage(30, 70 + i * 75, 10152); + AddImage(30, 85 + i * 75, 10151); + AddImage(30, 100 + i * 75, 10151); + AddImage(30, 106 + i * 75, 10154); + + AddImage(24, 60 + i * 75, teamInfo == ourTeam ? 9730 : 9727, teamInfo.Color - 1); + + var nameColor = LabelColor32; + var borderColor = BlackColor32; + + switch (teamInfo.Color) + { + case 0x47E: + nameColor = 0xFFFFFF; + break; + + case 0x4F2: + nameColor = 0x3399FF; + break; + + case 0x4F7: + nameColor = 0x33FF33; + break; + + case 0x4FC: + nameColor = 0xFF00FF; + break; + + case 0x021: + nameColor = 0xFF3333; + break; + + case 0x01A: + nameColor = 0xFF66FF; + break; + + case 0x455: + nameColor = 0x333333; + borderColor = 0xFFFFFF; + break; + } + + AddBorderedText( + 60, + 65 + i * 75, + 250, + 20, + $"{LadderGump.Rank(1 + i)}: {teamInfo.Name}", + nameColor, + borderColor + ); + + AddBorderedText(50 + 10, 85 + i * 75, 100, 20, "Score:", 0xFFC000, BlackColor32); + AddBorderedText(50 + 15, 105 + i * 75, 100, 20, teamInfo.Score.ToString("N0"), 0xFFC000, BlackColor32); + + AddBorderedText(110 + 10, 85 + i * 75, 100, 20, "Kills:", 0xFFC000, BlackColor32); + AddBorderedText(110 + 15, 105 + i * 75, 100, 20, teamInfo.Kills.ToString("N0"), 0xFFC000, BlackColor32); + + AddBorderedText(160 + 10, 85 + i * 75, 100, 20, "Captures:", 0xFFC000, BlackColor32); + AddBorderedText( + 160 + 15, + 105 + i * 75, + 100, + 20, + teamInfo.Captures.ToString("N0"), + 0xFFC000, + BlackColor32 + ); + + var pl = teamInfo.Leader; + + AddBorderedText(235 + 10, 85 + i * 75, 250, 20, "Leader:", 0xFFC000, BlackColor32); + + if (pl != null) + AddBorderedText(235 + 15, 105 + i * 75, 250, 20, pl.Player.Name, 0xFFC000, BlackColor32); + } + + AddButton(314, height - 42, 247, 248, 1); + } + + public string Center(string text) => $"
{text}
"; + + public string Color(string text, int color) => $"{text}"; + + private void AddBorderedText(int x, int y, int width, int height, string text, int color, int borderColor) + { + AddColoredText(x - 1, y - 1, width, height, text, borderColor); + AddColoredText(x - 1, y + 1, width, height, text, borderColor); + AddColoredText(x + 1, y - 1, width, height, text, borderColor); + AddColoredText(x + 1, y + 1, width, height, text, borderColor); + AddColoredText(x, y, width, height, text, color); + } + + private void AddColoredText(int x, int y, int width, int height, string text, int color) + { + if (color == 0) + AddHtml(x, y, width, height, text); + else + AddHtml(x, y, width, height, Color(text, color)); + } + } + + public sealed class DDPlayerInfo : IRankedCTF + { + private readonly DDTeamInfo m_TeamInfo; + private int m_Captures; + + private int m_Kills; + + private int m_Score; + + public DDPlayerInfo(DDTeamInfo teamInfo, Mobile player) + { + m_TeamInfo = teamInfo; + Player = player; + } + + public Mobile Player { get; } + + public string Name => Player.Name; + + public int Kills + { + get => m_Kills; + set + { + m_TeamInfo.Kills += value - m_Kills; + m_Kills = value; + } + } + + public int Captures + { + get => m_Captures; + set + { + m_TeamInfo.Captures += value - m_Captures; + m_Captures = value; + } + } + + public int Score + { + get => m_Score; + set + { + m_TeamInfo.Score += value - m_Score; + m_Score = value; + + if (m_TeamInfo.Leader == null || m_Score > m_TeamInfo.Leader.Score) + m_TeamInfo.Leader = this; + } + } + } + + [PropertyObject] + public sealed class DDTeamInfo : IRankedCTF + { + public DDTeamInfo(int teamID) + { + TeamID = teamID; + Players = new Dictionary(); + } + + public DDTeamInfo(int teamID, IGenericReader ip) + { + TeamID = teamID; + Players = new Dictionary(); + + var version = ip.ReadEncodedInt(); + + switch (version) + { + case 0: + { + Board = ip.ReadItem() as DDBoard; + TeamName = ip.ReadString(); + Color = ip.ReadEncodedInt(); + Origin = ip.ReadPoint3D(); + break; + } + } + } + + public DDGame Game { get; set; } + + public int TeamID { get; } + + public DDPlayerInfo Leader { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DDBoard Board { get; set; } + + public Dictionary Players { get; } + + public DDPlayerInfo this[Mobile mob] + { + get + { + if (mob == null) + return null; + + if (!Players.TryGetValue(mob, out var val)) + Players[mob] = val = new DDPlayerInfo(this, mob); + + return val; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Color { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public string TeamName { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D Origin { get; set; } + + public string Name => $"{TeamName} Team"; + + public int Kills { get; set; } + + public int Captures { get; set; } + + public int Score { get; set; } + + public void Reset() + { + Kills = 0; + Captures = 0; + + Score = 0; + + Leader = null; + + Players.Clear(); + + if (Board != null) + Board.m_TeamInfo = this; + } + + public void Serialize(IGenericWriter op) + { + op.WriteEncodedInt(0); // version + + op.Write(Board); + op.Write(TeamName); + op.WriteEncodedInt(Color); + op.Write(Origin); + } + + public override string ToString() => "..."; + } + + public sealed class DDController : EventController + { + [Constructible] + public DDController() + { + Visible = false; + Movable = false; + + Duration = TimeSpan.FromMinutes(30.0); + + TeamInfo = new DDTeamInfo[2]; + + for (var i = 0; i < TeamInfo.Length; ++i) + TeamInfo[i] = new DDTeamInfo(i); + } + + public DDController(Serial serial) + : base(serial) + { + } + + public DDTeamInfo[] TeamInfo { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DDTeamInfo Team1 => TeamInfo[0]; + + [CommandProperty(AccessLevel.GameMaster)] + public DDTeamInfo Team2 => TeamInfo[1]; + + [CommandProperty(AccessLevel.GameMaster)] + public DDWayPoint PointA { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DDWayPoint PointB { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan Duration { get; set; } + + public override string Title => "DoubleDom"; + + public override string DefaultName => "DD Controller"; + + public override string GetTeamName(int teamID) => TeamInfo[teamID % TeamInfo.Length].Name; + + public override EventGame Construct(DuelContext context) => new DDGame(this, context); + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + writer.Write(Duration); + + writer.WriteEncodedInt(TeamInfo.Length); + + for (var i = 0; i < TeamInfo.Length; ++i) + TeamInfo[i].Serialize(writer); + + writer.Write(PointA); + writer.Write(PointB); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Duration = reader.ReadTimeSpan(); + TeamInfo = new DDTeamInfo[reader.ReadEncodedInt()]; + + for (var i = 0; i < TeamInfo.Length; ++i) + TeamInfo[i] = new DDTeamInfo(i, reader); + + PointA = reader.ReadItem() as DDWayPoint; + PointB = reader.ReadItem() as DDWayPoint; + + break; + } + } + } + } + + public sealed class DDGame : EventGame + { + private int m_CapStage; + + private bool m_Capturable = true; + private Timer m_CaptureTimer; + + private Timer m_FinishTimer; + private Timer m_UncaptureTimer; + + public DDGame(DDController controller, DuelContext context) : base(context) => Controller = controller; + + public DDController Controller { get; } + + public Map Facet + { + get + { + if (m_Context.Arena != null) + return m_Context.Arena.Facet; + + return Controller.Map; + } + } + + public void Alert(string text) + { + m_Context.m_Tournament?.Alert(text); + + for (var i = 0; i < m_Context.Participants.Count; ++i) + { + var p = m_Context.Participants[i]; + + for (var j = 0; j < p.Players.Length; ++j) + if (p.Players[j] != null) + p.Players[j].Mobile.SendMessage(0x35, text); + } + } + + public void Alert(string format, params object[] args) + { + Alert(string.Format(format, args)); + } + + public DDTeamInfo GetTeamInfo(Mobile mob) + { + var teamID = GetTeamID(mob); + + if (teamID >= 0) + return Controller.TeamInfo[teamID % Controller.TeamInfo.Length]; + + return null; + } + + public int GetTeamID(Mobile mob) + { + if (!(mob is PlayerMobile pm)) + return -1; + + if (pm.DuelContext == null || pm.DuelContext != m_Context) + return -1; + + if (pm.DuelPlayer?.Eliminated != false) + return -1; + + return pm.DuelContext.Participants.IndexOf(pm.DuelPlayer.Participant); + } + + public int GetColor(Mobile mob) => GetTeamInfo(mob)?.Color ?? -1; + + private void ApplyHues(Participant p, int hueOverride) + { + for (var i = 0; i < p.Players.Length; ++i) + if (p.Players[i] != null) + p.Players[i].Mobile.SolidHueOverride = hueOverride; + } + + public void DelayBounce(TimeSpan ts, Mobile mob, Container corpse) + { + Timer.DelayCall(ts, DelayBounce_Callback, mob, corpse); + } + + private void DelayBounce_Callback(Mobile mob, Container corpse) + { + var dp = (mob as PlayerMobile)?.DuelPlayer; + + m_Context.RemoveAggressions(mob); + + if (dp?.Eliminated == false) + mob.MoveToWorld(m_Context.Arena.GetBaseStartPoint(GetTeamID(mob)), Facet); + else + m_Context.SendOutside(mob); + + m_Context.Refresh(mob, corpse); + DuelContext.Debuff(mob); + DuelContext.CancelSpell(mob); + mob.Frozen = false; + } + + public override bool OnDeath(Mobile mob, Container corpse) + { + var killer = mob.FindMostRecentDamager(false); + + if (killer?.Player == true) + { + var teamInfo = GetTeamInfo(killer); + var victInfo = GetTeamInfo(mob); + + if (teamInfo != null && teamInfo != victInfo) + { + var playerInfo = teamInfo[killer]; + + if (playerInfo != null) + { + playerInfo.Kills += 1; + playerInfo.Score += 1; // base frag + + // extra points for killing someone on the waypoint + if (Controller.PointA != null) + if (mob.InRange(Controller.PointA, 2)) + playerInfo.Score += 1; + + if (Controller.PointB != null) + if (mob.InRange(Controller.PointB, 2)) + playerInfo.Score += 1; + } + + playerInfo = victInfo[mob]; + if (playerInfo != null) + playerInfo.Score -= 1; + } + } + + mob.CloseGump(); + mob.SendGump(new DDBoardGump(mob, this)); + + m_Context.Requip(mob, corpse); + DelayBounce(TimeSpan.FromSeconds(30.0), mob, corpse); + + return false; + } + + public override void OnStart() + { + m_Capturable = true; + + if (m_CaptureTimer != null) + { + m_CaptureTimer.Stop(); + m_CaptureTimer = null; + } + + if (m_UncaptureTimer != null) + { + m_UncaptureTimer.Stop(); + m_UncaptureTimer = null; + } + + for (var i = 0; i < Controller.TeamInfo.Length; ++i) + { + var teamInfo = Controller.TeamInfo[i]; + + teamInfo.Game = this; + teamInfo.Reset(); + } + + if (Controller.PointA != null) + Controller.PointA.Game = this; + + if (Controller.PointB != null) + Controller.PointB.Game = this; + + for (var i = 0; i < m_Context.Participants.Count; ++i) + ApplyHues( + m_Context.Participants[i], + Controller.TeamInfo[i % Controller.TeamInfo.Length].Color + ); + + m_FinishTimer?.Stop(); + m_FinishTimer = Timer.DelayCall(Controller.Duration, Finish_Callback); + } + + private void Finish_Callback() + { + var teams = new List(); + + for (var i = 0; i < m_Context.Participants.Count; ++i) + { + var teamInfo = Controller.TeamInfo[i % Controller.TeamInfo.Length]; + + if (teamInfo != null) + teams.Add(teamInfo); + } + + teams.Sort((a, b) => b.Score - a.Score); + + var tourney = m_Context.m_Tournament; + + var sb = new StringBuilder(); + + if (tourney != null) + { + if (tourney.TourneyType == TourneyType.FreeForAll) + { + sb.Append(m_Context.Participants.Count * tourney.PlayersPerParticipant); + sb.Append("-man FFA"); + } + else if (tourney.TourneyType == TourneyType.RandomTeam) + { + sb.Append(tourney.ParticipantsPerMatch); + sb.Append("-team"); + } + else if (tourney.TourneyType == TourneyType.RedVsBlue) + { + sb.Append("Red v Blue"); + } + else if (tourney.TourneyType == TourneyType.Faction) + { + sb.Append(tourney.ParticipantsPerMatch); + sb.Append("-team Faction"); + } + else + { + for (var i = 0; i < tourney.ParticipantsPerMatch; ++i) + { + if (sb.Length > 0) + sb.Append('v'); + + sb.Append(tourney.PlayersPerParticipant); + } + } + } + + if (Controller != null) + sb.Append(' ').Append(Controller.Title); + + var title = sb.ToString(); + + var winner = teams.Count > 0 ? teams[0] : null; + + for (var i = 0; i < teams.Count; ++i) + { + var rank = TrophyRank.Bronze; + + if (i == 0) + rank = TrophyRank.Gold; + else if (i == 1) + rank = TrophyRank.Silver; + + var leader = teams[i].Leader; + + foreach (var pl in teams[i].Players.Values) + { + var mob = pl.Player; + + if (mob == null) + continue; + + // "Red v Blue DD Champion" + + sb = new StringBuilder(); + + sb.Append(title); + + if (pl == leader) + sb.Append(" Leader"); + + if (pl.Score > 0) + { + sb.Append(": "); + + sb.Append(pl.Score.ToString("N0")); + sb.Append(pl.Score == 1 ? " point" : " points"); + + if (pl.Kills > 0) + { + sb.Append(", "); + sb.Append(pl.Kills.ToString("N0")); + sb.Append(pl.Kills == 1 ? " kill" : " kills"); + } + + if (pl.Captures > 0) + { + sb.Append(", "); + sb.Append(pl.Captures.ToString("N0")); + sb.Append(pl.Captures == 1 ? " capture" : " captures"); + } + } + + Item item = new Trophy(sb.ToString(), rank); + + if (pl == leader) + item.ItemID = 4810; + + item.Name = $"{item.Name}, {teams[i].Name.ToLower()} team"; + + if (!mob.PlaceInBackpack(item)) + mob.BankBox.DropItem(item); + + var cash = pl.Score * 250; + + if (cash > 0) + { + item = new BankCheck(cash); + + if (!mob.PlaceInBackpack(item)) + mob.BankBox.DropItem(item); + + mob.SendMessage( + "You have been awarded a {0} trophy and {1:N0}gp for your participation in this tournament.", + rank.ToString().ToLower(), + cash + ); + } + else + { + mob.SendMessage( + "You have been awarded a {0} trophy for your participation in this tournament.", + rank.ToString().ToLower() + ); + } + } + } + + for (var i = 0; i < m_Context.Participants.Count; ++i) + { + var p = m_Context.Participants[i]; + + for (var j = 0; j < p.Players.Length; ++j) + { + var dp = p.Players[j]; + + if (dp?.Mobile != null) + { + dp.Mobile.CloseGump(); + dp.Mobile.SendGump(new DDBoardGump(dp.Mobile, this)); + } + } + + if (i == winner.TeamID) + continue; + + for (var j = 0; j < p.Players.Length; ++j) + if (p.Players[j] != null) + p.Players[j].Eliminated = true; + } + + m_Context.Finish(m_Context.Participants[winner.TeamID]); + } + + public override void OnStop() + { + for (var i = 0; i < Controller.TeamInfo.Length; ++i) + { + var teamInfo = Controller.TeamInfo[i]; + + if (teamInfo.Board != null) + teamInfo.Board.m_TeamInfo = null; + + teamInfo.Game = null; + } + + if (Controller.PointA != null) + Controller.PointA.Game = null; + + if (Controller.PointB != null) + Controller.PointB.Game = null; + + m_Capturable = false; + + if (m_CaptureTimer != null) + { + m_CaptureTimer.Stop(); + m_CaptureTimer = null; + } + + if (m_UncaptureTimer != null) + { + m_UncaptureTimer.Stop(); + m_UncaptureTimer = null; + } + + for (var i = 0; i < m_Context.Participants.Count; ++i) + ApplyHues(m_Context.Participants[i], -1); + + m_FinishTimer?.Stop(); + m_FinishTimer = null; + } + + public void Dominate(DDWayPoint point, Mobile from, DDTeamInfo team) + { + if (point == null || from == null || team == null || !m_Capturable) + return; + + var wasDom = Controller.PointA?.TeamOwner == Controller.PointB?.TeamOwner && + Controller.PointA?.TeamOwner != null; + + point.TeamOwner = team; + Alert("{0} has captured {1}!", team.Name, point.Name); + + var isDom = Controller.PointA?.TeamOwner == Controller.PointB?.TeamOwner && Controller.PointA?.TeamOwner != null; + + if (wasDom && !isDom) + { + Alert("Domination averted!"); + + Controller.PointA?.SetNonCaptureHue(); + Controller.PointB?.SetNonCaptureHue(); + m_CaptureTimer?.Stop(); + m_CaptureTimer = null; + } + + if (!wasDom && isDom) + { + m_CapStage = 0; + m_CaptureTimer = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromSeconds(1.0), CaptureTick); + } + } + + private void CaptureTick() + { + var team = Controller.PointA?.TeamOwner ?? Controller.PointB?.TeamOwner; + + if (team == null) + { + m_Capturable = true; + m_CaptureTimer?.Stop(); + m_CaptureTimer = null; + return; + } + + if (++m_CapStage < 10) + { + Alert("{0} is dominating... {1}", team.Name, 10 - m_CapStage); + + Controller.PointA?.SetCaptureHue(m_CapStage); + Controller.PointB?.SetCaptureHue(m_CapStage); + } + else + { + Alert("{0} has scored!", team.Name); + + team.Score += 100; + team.Captures += 1; + + m_Capturable = false; + m_CapStage = 0; + m_CaptureTimer.Stop(); + m_CaptureTimer = null; + + if (Controller.PointA != null) + { + Controller.PointA.TeamOwner = null; + Controller.PointA.SetUncapturableHue(); + } + + if (Controller.PointB != null) + { + Controller.PointB.TeamOwner = null; + Controller.PointB.SetUncapturableHue(); + } + + m_UncaptureTimer = Timer.DelayCall(TimeSpan.FromSeconds(30.0), UncaptureTick); + m_UncaptureTimer.Start(); + } + } + + private void UncaptureTick() + { + m_Capturable = true; + + if (m_CaptureTimer != null) + { + m_CaptureTimer.Stop(); + m_CaptureTimer = null; + } + + if (m_UncaptureTimer != null) + { + m_UncaptureTimer.Stop(); + m_UncaptureTimer = null; + } + + if (Controller.PointA != null) + { + Controller.PointA.TeamOwner = null; + Controller.PointA.SetNonCaptureHue(); + } + + if (Controller.PointB != null) + { + Controller.PointB.TeamOwner = null; + Controller.PointB.SetNonCaptureHue(); + } + } + } + + public class DDWayPoint : BaseAddon + { + public const int UncapturableHue = 0x497; + public const int NonCapturedHue = 0x38A; + private DDGame m_Game; + private DDTeamInfo m_TeamOwner; + + [Constructible] + public DDWayPoint() + { + ItemID = 0x519; + Visible = true; + Name = "SET MY NAME"; + + AddComponent(new DDStep(0x7A8), -1, -1, -5); + AddComponent(new DDStep(0x7A6), 0, -1, -5); + AddComponent(new DDStep(0x7AA), 1, -1, -5); + + AddComponent(new DDStep(0x7A5), 1, 0, -5); + + AddComponent(new DDStep(0x7A9), 1, 1, -5); + AddComponent(new DDStep(0x7A4), 0, 1, -5); + AddComponent(new DDStep(0x7AB), -1, 1, -5); + + AddComponent(new DDStep(0x7A7), -1, 0, -5); + + SetUncapturableHue(); + } + + public DDWayPoint(Serial serial) : base(serial) + { + } + + public override bool ShareHue => false; + + public DDGame Game + { + get => m_Game; + set + { + m_Game = value; + m_TeamOwner = null; + + if (m_Game != null) + SetNonCaptureHue(); + else + SetUncapturableHue(); + } + } + + public DDTeamInfo TeamOwner + { + get => m_TeamOwner; + set + { + m_TeamOwner = value; + + SetNonCaptureHue(); + } + } + + 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(); + } + + public void SetUncapturableHue() + { + for (var i = 0; i < Components.Count; i++) + Components[i].Hue = UncapturableHue; + Hue = UncapturableHue; + } + + public void SetNonCaptureHue() + { + for (var i = 0; i < Components.Count; i++) + Components[i].Hue = NonCapturedHue; + + if (m_TeamOwner != null) + Hue = m_TeamOwner.Color; + else + Hue = NonCapturedHue; + } + + public void SetCaptureHue(int stage) + { + if (m_TeamOwner == null) + return; + + Hue = m_TeamOwner.Color; + + for (var i = 0; i < Components.Count; i++) + if (i < stage) + Components[i].Hue = m_TeamOwner.Color; + else + Components[i].Hue = NonCapturedHue; + } + + public override bool OnMoveOver(Mobile from) + { + if (m_Game == null) + { + SetUncapturableHue(); + } + else if (from.Alive) + { + var team = m_Game.GetTeamInfo(from); + + if (team != null && team != TeamOwner) + m_Game.Dominate(this, from, team); + } + + return true; + } + + public class DDStep : AddonComponent + { + public DDStep(int itemID) : base(itemID) => Visible = true; + + public DDStep(Serial serial) : base(serial) + { + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override bool OnMoveOver(Mobile m) => Addon.OnMoveOver(m); + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Games/EventGame.cs b/Projects/UOContent/Engines/ConPVP/Games/EventGame.cs index 1bfcc96dc..62a086d38 100644 --- a/Projects/UOContent/Engines/ConPVP/Games/EventGame.cs +++ b/Projects/UOContent/Engines/ConPVP/Games/EventGame.cs @@ -1,68 +1,68 @@ -using Server.Gumps; -using Server.Items; - -namespace Server.Engines.ConPVP -{ - public abstract class EventController : Item - { - public EventController() - : base(0x1B7A) - { - Visible = false; - Movable = false; - } - - public EventController(Serial serial) - : base(serial) - { - } - - public abstract string Title { get; } - public abstract EventGame Construct(DuelContext dc); - - public abstract string GetTeamName(int teamID); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - if (from.AccessLevel >= AccessLevel.GameMaster) - from.SendGump(new PropertiesGump(from, this)); - } - } - - public abstract class EventGame - { - protected DuelContext m_Context; - - public EventGame(DuelContext context) => m_Context = context; - - public DuelContext Context => m_Context; - - public virtual bool FreeConsume => true; - - public virtual bool OnDeath(Mobile mob, Container corpse) => true; - - public virtual bool CantDoAnything(Mobile mob) => false; - - public virtual void OnStart() - { - } - - public virtual void OnStop() - { - } - } -} \ No newline at end of file +using Server.Gumps; +using Server.Items; + +namespace Server.Engines.ConPVP +{ + public abstract class EventController : Item + { + public EventController() + : base(0x1B7A) + { + Visible = false; + Movable = false; + } + + public EventController(Serial serial) + : base(serial) + { + } + + public abstract string Title { get; } + public abstract EventGame Construct(DuelContext dc); + + public abstract string GetTeamName(int teamID); + + 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(); + } + + public override void OnDoubleClick(Mobile from) + { + if (from.AccessLevel >= AccessLevel.GameMaster) + from.SendGump(new PropertiesGump(from, this)); + } + } + + public abstract class EventGame + { + protected DuelContext m_Context; + + public EventGame(DuelContext context) => m_Context = context; + + public DuelContext Context => m_Context; + + public virtual bool FreeConsume => true; + + public virtual bool OnDeath(Mobile mob, Container corpse) => true; + + public virtual bool CantDoAnything(Mobile mob) => false; + + public virtual void OnStart() + { + } + + public virtual void OnStop() + { + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Games/KingOfTheHill.cs b/Projects/UOContent/Engines/ConPVP/Games/KingOfTheHill.cs index fbde6e57a..6419556b0 100644 --- a/Projects/UOContent/Engines/ConPVP/Games/KingOfTheHill.cs +++ b/Projects/UOContent/Engines/ConPVP/Games/KingOfTheHill.cs @@ -1,1156 +1,1173 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Server.Gumps; -using Server.Items; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.ConPVP -{ - public class HillOfTheKing : Item - { - private KHGame m_Game; - private KingTimer m_KingTimer; - - [Constructible] - public HillOfTheKing() - : base(0x520) - { - ScoreInterval = 10; - m_Game = null; - King = null; - Movable = false; - - Name = "the hill"; - } - - public HillOfTheKing(Serial s) - : base(s) - { - } - - public Mobile King { get; private set; } - - public KHGame Game - { - get => m_Game; - set - { - if (m_Game != value) - { - m_KingTimer?.Stop(); - m_Game = value; - King = null; - } - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int ScoreInterval { get; set; } - - public int CapturesSoFar - { - get - { - if (m_KingTimer != null) - return m_KingTimer.Captures; - return 0; - } - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - ScoreInterval = reader.ReadEncodedInt(); - break; - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.WriteEncodedInt(ScoreInterval); - } - - private bool CanBeKing(Mobile m) - { - // Game running? - if (m_Game == null) - return false; - - // Mobile exists and is alive and is a player? - if (m?.Deleted != false || !m.Alive || !m.Player) - return false; - - // Not current king (or they are the current king) - if (King != null && King != m) - return false; - - // They are on a team - return m_Game.GetTeamInfo(m) != null; - } - - public override bool OnMoveOver(Mobile m) - { - if (m_Game == null || m?.Alive != true) - return base.OnMoveOver(m); - - if (CanBeKing(m)) - { - if (base.OnMoveOver(m)) - { - ReKingify(m); - return true; - } - } - else - { - // Decrease their stam a little so they don't keep pushing someone out of the way - if (m.AccessLevel == AccessLevel.Player && m.Stam >= m.StamMax) - m.Stam -= 5; - } - - return false; - } - - public override bool OnMoveOff(Mobile m) - { - if (base.OnMoveOff(m)) - { - if (King == m) - DeKingify(); - - return true; - } - - return false; - } - - public virtual void OnKingDied(Mobile king, KHTeamInfo kingTeam, Mobile killer, KHTeamInfo killerTeam) - { - if (m_Game != null && CapturesSoFar > 0 && killer != null && king != null && kingTeam != null && - killerTeam != null) - { - string kingName = king.Name ?? ""; - string killerName = killer.Name ?? ""; - - m_Game.Alert("{0} ({1}) was dethroned by {2} ({3})!", kingName, kingTeam.Name, killerName, killerTeam.Name); - } - - DeKingify(); - } - - private void DeKingify() - { - PublicOverheadMessage(MessageType.Regular, 0x0481, false, "Free!"); - - m_KingTimer?.Stop(); - - King = null; - } - - private void ReKingify(Mobile m) - { - if (m_Game == null || m == null) - return; - - if (m_Game.GetTeamInfo(m) == null) - return; - - King = m; - - m_KingTimer ??= new KingTimer(this); - m_KingTimer.Stop(); - m_KingTimer.StartHillTicker(); - - if (King.Name != null) - PublicOverheadMessage(MessageType.Regular, 0x0481, false, $"Taken by {King.Name}!"); - } - - private class KingTimer : Timer - { - private int m_Counter; - private readonly HillOfTheKing m_Hill; - - public KingTimer(HillOfTheKing hill) - : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)) - { - m_Hill = hill; - Captures = 0; - m_Counter = 0; - - Priority = TimerPriority.FiftyMS; - } - - public int Captures { get; private set; } - - public void StartHillTicker() - { - Captures = 0; - m_Counter = 0; - - Start(); - } - - protected override void OnTick() - { - KHPlayerInfo pi = null; - - if (m_Hill?.Deleted != false || m_Hill.Game == null) - { - Stop(); - return; - } - - if (m_Hill.King?.Deleted != false || !m_Hill.King.Alive) - { - m_Hill.DeKingify(); - Stop(); - return; - } - - KHTeamInfo ti = m_Hill.Game.GetTeamInfo(m_Hill.King); - if (ti != null) - pi = ti[m_Hill.King]; - - if (ti == null || pi == null) - { - // error, bail - m_Hill.DeKingify(); - Stop(); - return; - } - - m_Counter++; - - m_Hill.King.RevealingAction(); - - if (m_Counter >= m_Hill.ScoreInterval) - { - string hill = m_Hill.Name.IsNullOrDefault("the hill"); - string king = m_Hill.King.Name ?? ""; - - m_Hill.Game.Alert("{0} ({1}) is king of {2}!", king, ti.Name, hill); - - m_Hill.PublicOverheadMessage(MessageType.Regular, 0x0481, false, "Capture!"); - - pi.Captures++; - Captures++; - - pi.Score += m_Counter; - - m_Counter = 0; - } - else - { - m_Hill.PublicOverheadMessage(MessageType.Regular, 0x0481, false, - (m_Hill.ScoreInterval - m_Counter).ToString()); - } - } - } - } - - public class KHBoard : Item - { - private KHController m_Controller; - public KHGame m_Game; - - [Constructible] - public KHBoard() - : base(7774) - { - Name = "King of the Hill Scoreboard"; - Movable = false; - } - - public KHBoard(Serial serial) - : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public KHController Controller - { - get => m_Controller; - set - { - if (m_Controller != value) - { - m_Controller?.RemoveBoard(this); - m_Controller = value; - m_Controller?.AddBoard(this); - } - } - } - - public override void OnDoubleClick(Mobile from) - { - if (m_Game != null) - { - from.CloseGump(); - from.SendGump(new KHBoardGump(from, m_Game)); - } - else - { - from.SendMessage("There is no King of the Hill game in progress."); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(m_Controller); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Controller = reader.ReadItem() as KHController; - break; - } - } - } - } - - public sealed class KHBoardGump : Gump - { - private const int LabelColor32 = 0xFFFFFF; - private const int BlackColor32 = 0x000000; - - private KHGame m_Game; - - public KHBoardGump(Mobile mob, KHGame game) - : base(60, 60) - { - m_Game = game; - - KHTeamInfo ourTeam = game.GetTeamInfo(mob); - - List entries = new List(); - - for (int i = 0; i < game.Context.Participants.Count; ++i) - { - KHTeamInfo teamInfo = game.Controller.TeamInfo[i % game.Controller.TeamInfo.Length]; - - if (teamInfo != null) - entries.Add(teamInfo); - } - - entries.Sort(); - /* - delegate( IRankedCTF a, IRankedCTF b ) - { - return b.Score - a.Score; - } );*/ - - int height = 73 + entries.Count * 75 + 28; - - Closable = false; - - AddPage(0); - - AddBackground(1, 1, 398, height, 3600); - - AddImageTiled(16, 15, 369, height - 29, 3604); - - for (int i = 0; i < entries.Count; i += 1) - AddImageTiled(22, 58 + i * 75, 357, 70, 0x2430); - - AddAlphaRegion(16, 15, 369, height - 29); - - AddImage(215, -45, 0xEE40); - // AddImage( 330, 141, 0x8BA ); - - AddBorderedText(22, 22, 294, 20, Center("King of the Hill Scoreboard"), LabelColor32, BlackColor32); - - AddImageTiled(32, 50, 264, 1, 9107); - AddImageTiled(42, 52, 264, 1, 9157); - - for (int i = 0; i < entries.Count; ++i) - { - KHTeamInfo teamInfo = entries[i]; - - AddImage(30, 70 + i * 75, 10152); - AddImage(30, 85 + i * 75, 10151); - AddImage(30, 100 + i * 75, 10151); - AddImage(30, 106 + i * 75, 10154); - - AddImage(24, 60 + i * 75, teamInfo == ourTeam ? 9730 : 9727, teamInfo.Color - 1); - - int nameColor = LabelColor32; - int borderColor = BlackColor32; - - switch (teamInfo.Color) - { - case 0x47E: - nameColor = 0xFFFFFF; - break; - - case 0x4F2: - nameColor = 0x3399FF; - break; - - case 0x4F7: - nameColor = 0x33FF33; - break; - - case 0x4FC: - nameColor = 0xFF00FF; - break; - - case 0x021: - nameColor = 0xFF3333; - break; - - case 0x01A: - nameColor = 0xFF66FF; - break; - - case 0x455: - nameColor = 0x333333; - borderColor = 0xFFFFFF; - break; - } - - AddBorderedText(60, 65 + i * 75, 250, 20, $"{LadderGump.Rank(1 + i)}: {teamInfo.Name}", nameColor, - borderColor); - - AddBorderedText(50 + 10, 85 + i * 75, 100, 20, "Score:", 0xFFC000, BlackColor32); - AddBorderedText(50 + 15, 105 + i * 75, 100, 20, teamInfo.Score.ToString("N0"), 0xFFC000, BlackColor32); - - AddBorderedText(110 + 10, 85 + i * 75, 100, 20, "Kills:", 0xFFC000, BlackColor32); - AddBorderedText(110 + 15, 105 + i * 75, 100, 20, teamInfo.Kills.ToString("N0"), 0xFFC000, BlackColor32); - - AddBorderedText(160 + 10, 85 + i * 75, 100, 20, "Captures:", 0xFFC000, BlackColor32); - AddBorderedText(160 + 15, 105 + i * 75, 100, 20, teamInfo.Captures.ToString("N0"), 0xFFC000, BlackColor32); - - string leader = teamInfo.Leader?.Name ?? "(none)"; - - AddBorderedText(235 + 10, 85 + i * 75, 250, 20, "Leader:", 0xFFC000, BlackColor32); - AddBorderedText(235 + 15, 105 + i * 75, 250, 20, leader, 0xFFC000, BlackColor32); - } - - AddButton(314, height - 42, 247, 248, 1); - } - - public string Center(string text) => $"
{text}
"; - - public string Color(string text, int color) => $"{text}"; - - private void AddBorderedText(int x, int y, int width, int height, string text, int color, int borderColor) - { - AddColoredText(x - 1, y - 1, width, height, text, borderColor); - AddColoredText(x - 1, y + 1, width, height, text, borderColor); - AddColoredText(x + 1, y - 1, width, height, text, borderColor); - AddColoredText(x + 1, y + 1, width, height, text, borderColor); - AddColoredText(x, y, width, height, text, color); - } - - private void AddColoredText(int x, int y, int width, int height, string text, int color) - { - if (color == 0) - AddHtml(x, y, width, height, text); - else - AddHtml(x, y, width, height, Color(text, color)); - } - } - - public sealed class KHPlayerInfo : IRankedCTF, IComparable - { - private int m_Captures; - - private int m_Kills; - private int m_Score; - private readonly KHTeamInfo m_TeamInfo; - - public KHPlayerInfo(KHTeamInfo teamInfo, Mobile player) - { - m_TeamInfo = teamInfo; - Player = player; - } - - public Mobile Player { get; } - - public int CompareTo(KHPlayerInfo pi) - { - int res = pi.Score.CompareTo(Score); - if (res != 0) - return res; - - res = pi.Captures.CompareTo(Captures); - - return res != 0 ? res : pi.Kills.CompareTo(Kills); - } - - public string Name => Player.Name ?? ""; - - public int Kills - { - get => m_Kills; - set - { - m_TeamInfo.Kills += value - m_Kills; - m_Kills = value; - } - } - - public int Captures - { - get => m_Captures; - set - { - m_TeamInfo.Captures += value - m_Captures; - m_Captures = value; - } - } - - public int Score - { - get => m_Score; - set - { - m_TeamInfo.Score += value - m_Score; - m_Score = value; - - if (m_TeamInfo.Leader == null || m_Score > m_TeamInfo.Leader.Score) - m_TeamInfo.Leader = this; - } - } - } - - [PropertyObject] - public sealed class KHTeamInfo : IRankedCTF, IComparable - { - public KHTeamInfo(int teamID) - { - TeamID = teamID; - Players = new Dictionary(); - } - - public KHTeamInfo(int teamID, IGenericReader ip) - { - TeamID = teamID; - Players = new Dictionary(); - - int version = ip.ReadEncodedInt(); - - switch (version) - { - case 0: - { - TeamName = ip.ReadString(); - Color = ip.ReadEncodedInt(); - break; - } - } - } - - public KHGame Game { get; set; } - - public int TeamID { get; } - - public KHPlayerInfo Leader { get; set; } - - public Dictionary Players { get; } - - public KHPlayerInfo this[Mobile mob] - { - get - { - if (mob == null) - return null; - - if (!Players.TryGetValue(mob, out KHPlayerInfo val)) - Players[mob] = val = new KHPlayerInfo(this, mob); - - return val; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Color { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public string TeamName { get; set; } - - public int CompareTo(KHTeamInfo ti) - { - int res = ti.Score.CompareTo(Score); - if (res != 0) - return res; - - res = ti.Captures.CompareTo(Captures); - - if (res == 0) - res = ti.Kills.CompareTo(Kills); - - return res; - } - - public string Name => $"{TeamName ?? "(none)"} Team"; - - public int Kills { get; set; } - - public int Captures { get; set; } - - public int Score { get; set; } - - public void Reset() - { - Kills = 0; - Captures = 0; - Score = 0; - - Leader = null; - - Players.Clear(); - } - - public void Serialize(IGenericWriter op) - { - op.WriteEncodedInt(0); // version - - op.Write(TeamName); - op.WriteEncodedInt(Color); - } - - public override string ToString() => TeamName != null ? $"({Name}) ..." : "..."; - } - - public sealed class KHController : EventController - { - private int m_ScoreInterval; - - [Constructible] - public KHController() - { - Visible = false; - Movable = false; - - Name = "King of the Hill Controller"; - - Duration = TimeSpan.FromMinutes(30.0); - Boards = new List(); - Hills = new HillOfTheKing[4]; - TeamInfo = new KHTeamInfo[8]; - - for (int i = 0; i < TeamInfo.Length; ++i) - TeamInfo[i] = new KHTeamInfo(i); - } - - public KHController(Serial serial) - : base(serial) - { - } - - public KHTeamInfo[] TeamInfo { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public KHTeamInfo Team1_W => TeamInfo[0]; - - [CommandProperty(AccessLevel.GameMaster)] - public KHTeamInfo Team2_E => TeamInfo[1]; - - [CommandProperty(AccessLevel.GameMaster)] - public KHTeamInfo Team3_N => TeamInfo[2]; - - [CommandProperty(AccessLevel.GameMaster)] - public KHTeamInfo Team4_S => TeamInfo[3]; - - [CommandProperty(AccessLevel.GameMaster)] - public KHTeamInfo Team5_NW => TeamInfo[4]; - - [CommandProperty(AccessLevel.GameMaster)] - public KHTeamInfo Team6_SE => TeamInfo[5]; - - [CommandProperty(AccessLevel.GameMaster)] - public KHTeamInfo Team7_SW => TeamInfo[6]; - - [CommandProperty(AccessLevel.GameMaster)] - public KHTeamInfo Team8_NE => TeamInfo[7]; - - public HillOfTheKing[] Hills { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public HillOfTheKing Hill1 - { - get => Hills[0]; - set => Hills[0] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public HillOfTheKing Hill2 - { - get => Hills[1]; - set => Hills[1] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public HillOfTheKing Hill3 - { - get => Hills[2]; - set => Hills[2] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public HillOfTheKing Hill4 - { - get => Hills[3]; - set => Hills[3] = value; - } - - public List Boards { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan Duration { get; set; } - - public override string Title => "King of the Hill"; - - public override string GetTeamName(int teamID) => TeamInfo[teamID % TeamInfo.Length].Name; - - public override EventGame Construct(DuelContext context) => new KHGame(this, context); - - public void RemoveBoard(KHBoard b) - { - if (b != null) - { - Boards.Remove(b); - b.m_Game = null; - } - } - - public void AddBoard(KHBoard b) - { - if (b != null) - Boards.Add(b); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.WriteEncodedInt(m_ScoreInterval); - writer.Write(Duration); - - writer.WriteItemList(Boards, true); - - writer.WriteEncodedInt(Hills.Length); - for (int i = 0; i < Hills.Length; ++i) - writer.Write(Hills[i]); - - writer.WriteEncodedInt(TeamInfo.Length); - for (int i = 0; i < TeamInfo.Length; ++i) - TeamInfo[i].Serialize(writer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_ScoreInterval = reader.ReadEncodedInt(); - - Duration = reader.ReadTimeSpan(); - - Boards = reader.ReadStrongItemList(); - - Hills = new HillOfTheKing[reader.ReadEncodedInt()]; - for (int i = 0; i < Hills.Length; ++i) - Hills[i] = reader.ReadItem() as HillOfTheKing; - - TeamInfo = new KHTeamInfo[reader.ReadEncodedInt()]; - for (int i = 0; i < TeamInfo.Length; ++i) - TeamInfo[i] = new KHTeamInfo(i, reader); - - break; - } - } - } - } - - public sealed class KHGame : EventGame - { - private Timer m_FinishTimer; - - public KHGame(KHController controller, DuelContext context) : base(context) => Controller = controller; - - public KHController Controller { get; } - - public Map Facet - { - get - { - if (m_Context?.Arena != null) - return m_Context.Arena.Facet; - - return Controller.Map; - } - } - - public override bool CantDoAnything(Mobile mob) - { - if (mob != null && GetTeamInfo(mob) != null && Controller != null) - for (int i = 0; i < Controller.Hills.Length; i++) - if (Controller.Hills[i]?.King == mob) - return true; - - return false; - } - - public void Alert(string text) - { - m_Context.m_Tournament?.Alert(text); - - for (int i = 0; i < m_Context.Participants.Count; ++i) - { - Participant p = m_Context.Participants[i]; - - for (int j = 0; j < p.Players.Length; ++j) - if (p.Players[j] != null) - p.Players[j].Mobile.SendMessage(0x35, text); - } - } - - public void Alert(string format, params object[] args) - { - Alert(string.Format(format, args)); - } - - public KHTeamInfo GetTeamInfo(Mobile mob) - { - int teamID = GetTeamID(mob); - - if (teamID >= 0) - return Controller.TeamInfo[teamID % Controller.TeamInfo.Length]; - - return null; - } - - public int GetTeamID(Mobile mob) - { - if (!(mob is PlayerMobile pm)) - return mob is BaseCreature creature ? creature.Team - 1 : -1; - - if (pm.DuelContext == null || pm.DuelContext != m_Context) - return -1; - - if (pm.DuelPlayer?.Eliminated != false) - return -1; - - return pm.DuelContext.Participants.IndexOf(pm.DuelPlayer.Participant); - } - - public int GetColor(Mobile mob) => GetTeamInfo(mob)?.Color ?? -1; - - private void ApplyHues(Participant p, int hueOverride) - { - for (int i = 0; i < p.Players.Length; ++i) - if (p.Players[i] != null) - p.Players[i].Mobile.SolidHueOverride = hueOverride; - } - - public void DelayBounce(TimeSpan ts, Mobile mob, Container corpse) - { - Timer.DelayCall(ts, DelayBounce_Callback, mob, corpse); - } - - private void DelayBounce_Callback(Mobile mob, Container corpse) - { - DuelPlayer dp = (mob as PlayerMobile)?.DuelPlayer; - - m_Context.RemoveAggressions(mob); - - if (dp?.Eliminated == false) - mob.MoveToWorld(m_Context.Arena.GetBaseStartPoint(GetTeamID(mob)), Facet); - else - m_Context.SendOutside(mob); - - m_Context.Refresh(mob, corpse); - DuelContext.Debuff(mob); - DuelContext.CancelSpell(mob); - mob.Frozen = false; - - if (corpse?.Deleted == false) - Timer.DelayCall(TimeSpan.FromSeconds(30), corpse.Delete); - } - - public override bool OnDeath(Mobile mob, Container corpse) - { - Mobile killer = mob.FindMostRecentDamager(false); - KHTeamInfo teamInfo = null; - KHTeamInfo victInfo = GetTeamInfo(mob); - int bonus = 0; - - if (killer?.Player == true) - teamInfo = GetTeamInfo(killer); - - for (int i = 0; i < Controller.Hills.Length; i++) - { - if (Controller.Hills[i] == null) - continue; - - if (Controller.Hills[i].King == mob) - { - bonus += Controller.Hills[i].CapturesSoFar; - Controller.Hills[i].OnKingDied(mob, victInfo, killer, teamInfo); - } - - if (Controller.Hills[i].King == killer) - bonus += 2; - } - - if (teamInfo != null && teamInfo != victInfo) - { - KHPlayerInfo playerInfo = teamInfo[killer]; - - if (playerInfo != null) - { - playerInfo.Kills += 1; - playerInfo.Score += 1 + bonus; - } - } - - mob.CloseGump(); - mob.SendGump(new KHBoardGump(mob, this)); - - m_Context.Requip(mob, corpse); - DelayBounce(TimeSpan.FromSeconds(30.0), mob, corpse); - - return false; - } - - public override void OnStart() - { - for (int i = 0; i < Controller.TeamInfo.Length; ++i) - { - KHTeamInfo teamInfo = Controller.TeamInfo[i]; - - teamInfo.Game = this; - teamInfo.Reset(); - } - - for (int i = 0; i < m_Context.Participants.Count; ++i) - ApplyHues(m_Context.Participants[i], - Controller.TeamInfo[i % Controller.TeamInfo.Length].Color); - - m_FinishTimer?.Stop(); - - for (int i = 0; i < Controller.Hills.Length; i++) - if (Controller.Hills[i] != null) - Controller.Hills[i].Game = this; - - foreach (KHBoard board in Controller.Boards) - if (board?.Deleted == false) - board.m_Game = this; - - m_FinishTimer = Timer.DelayCall(Controller.Duration, Finish_Callback); - } - - private void Finish_Callback() - { - List teams = new List(); - - for (int i = 0; i < m_Context.Participants.Count; ++i) - { - KHTeamInfo teamInfo = Controller.TeamInfo[i % Controller.TeamInfo.Length]; - - if (teamInfo != null) - teams.Add(teamInfo); - } - - teams.Sort(); - - Tournament tourney = m_Context.m_Tournament; - - StringBuilder sb = new StringBuilder(); - - if (tourney != null) - { - if (tourney.TourneyType == TourneyType.FreeForAll) - { - sb.Append(m_Context.Participants.Count * tourney.PlayersPerParticipant); - sb.Append("-man FFA"); - } - else if (tourney.TourneyType == TourneyType.RandomTeam) - { - sb.Append(tourney.ParticipantsPerMatch); - sb.Append("-team"); - } - else if (tourney.TourneyType == TourneyType.RedVsBlue) - { - sb.Append("Red v Blue"); - } - else - { - for (int i = 0; i < tourney.ParticipantsPerMatch; ++i) - { - if (sb.Length > 0) - sb.Append('v'); - - sb.Append(tourney.PlayersPerParticipant); - } - } - } - - if (Controller != null) - sb.Append(' ').Append(Controller.Title); - - string title = sb.ToString(); - - KHTeamInfo winner = teams.Count > 0 ? teams[0] : null; - - for (int i = 0; i < teams.Count; ++i) - { - TrophyRank rank = TrophyRank.Bronze; - - if (i == 0) - rank = TrophyRank.Gold; - else if (i == 1) - rank = TrophyRank.Silver; - - KHPlayerInfo leader = teams[i].Leader; - - foreach (KHPlayerInfo pl in teams[i].Players.Values) - { - Mobile mob = pl.Player; - - if (mob == null) - continue; - - sb = new StringBuilder(); - - sb.Append(title); - - if (pl == leader) - sb.Append(" Leader"); - - if (pl.Score > 0) - { - sb.Append(": "); - - sb.Append(pl.Score.ToString("N0")); - sb.Append(pl.Score == 1 ? " point" : " points"); - - sb.Append(", "); - sb.Append(pl.Kills.ToString("N0")); - sb.Append(pl.Kills == 1 ? " kill" : " kills"); - - if (pl.Captures > 0) - { - sb.Append(", "); - sb.Append(pl.Captures.ToString("N0")); - sb.Append(pl.Captures == 1 ? " capture" : " captures"); - } - } - - Item item = new Trophy(sb.ToString(), rank); - - if (pl == leader) - item.ItemID = 4810; - - item.Name = $"{item.Name}, {teams[i].Name.ToLower()}"; - - if (!mob.PlaceInBackpack(item)) - mob.BankBox.DropItem(item); - - int cash = pl.Score * 250; - - if (cash > 0) - { - item = new BankCheck(cash); - - if (!mob.PlaceInBackpack(item)) - mob.BankBox.DropItem(item); - - mob.SendMessage( - "You have been awarded a {0} trophy and {1:N0}gp for your participation in this game.", - rank.ToString().ToLower(), cash); - } - else - { - mob.SendMessage("You have been awarded a {0} trophy for your participation in this game.", - rank.ToString().ToLower()); - } - } - } - - for (int i = 0; i < m_Context.Participants.Count; ++i) - { - Participant p = m_Context.Participants[i]; - if (p.Players == null) - continue; - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer dp = p.Players[j]; - - if (dp?.Mobile != null) - { - dp.Mobile.CloseGump(); - dp.Mobile.SendGump(new KHBoardGump(dp.Mobile, this)); - } - } - - if (i == winner?.TeamID) - continue; - - if (p.Players != null) - for (int j = 0; j < p.Players.Length; ++j) - if (p.Players[j] != null) - p.Players[j].Eliminated = true; - } - - if (winner != null) - m_Context.Finish(m_Context.Participants[winner.TeamID]); - } - - public override void OnStop() - { - for (int i = 0; i < Controller.TeamInfo.Length; ++i) - Controller.TeamInfo[i].Game = null; - - for (int i = 0; i < Controller.Hills.Length; ++i) - if (Controller.Hills[i] != null) - Controller.Hills[i].Game = null; - - foreach (KHBoard board in Controller.Boards) - if (board != null) - board.m_Game = null; - - for (int i = 0; i < m_Context.Participants.Count; ++i) - ApplyHues(m_Context.Participants[i], -1); - - m_FinishTimer?.Stop(); - m_FinishTimer = null; - } - } -} +using System; +using System.Collections.Generic; +using System.Text; +using Server.Gumps; +using Server.Items; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.ConPVP +{ + public class HillOfTheKing : Item + { + private KHGame m_Game; + private KingTimer m_KingTimer; + + [Constructible] + public HillOfTheKing() + : base(0x520) + { + ScoreInterval = 10; + m_Game = null; + King = null; + Movable = false; + + Name = "the hill"; + } + + public HillOfTheKing(Serial s) + : base(s) + { + } + + public Mobile King { get; private set; } + + public KHGame Game + { + get => m_Game; + set + { + if (m_Game != value) + { + m_KingTimer?.Stop(); + m_Game = value; + King = null; + } + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int ScoreInterval { get; set; } + + public int CapturesSoFar + { + get + { + if (m_KingTimer != null) + return m_KingTimer.Captures; + return 0; + } + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + ScoreInterval = reader.ReadEncodedInt(); + break; + } + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.WriteEncodedInt(ScoreInterval); + } + + private bool CanBeKing(Mobile m) + { + // Game running? + if (m_Game == null) + return false; + + // Mobile exists and is alive and is a player? + if (m?.Deleted != false || !m.Alive || !m.Player) + return false; + + // Not current king (or they are the current king) + if (King != null && King != m) + return false; + + // They are on a team + return m_Game.GetTeamInfo(m) != null; + } + + public override bool OnMoveOver(Mobile m) + { + if (m_Game == null || m?.Alive != true) + return base.OnMoveOver(m); + + if (CanBeKing(m)) + { + if (base.OnMoveOver(m)) + { + ReKingify(m); + return true; + } + } + else + { + // Decrease their stam a little so they don't keep pushing someone out of the way + if (m.AccessLevel == AccessLevel.Player && m.Stam >= m.StamMax) + m.Stam -= 5; + } + + return false; + } + + public override bool OnMoveOff(Mobile m) + { + if (base.OnMoveOff(m)) + { + if (King == m) + DeKingify(); + + return true; + } + + return false; + } + + public virtual void OnKingDied(Mobile king, KHTeamInfo kingTeam, Mobile killer, KHTeamInfo killerTeam) + { + if (m_Game != null && CapturesSoFar > 0 && killer != null && king != null && kingTeam != null && + killerTeam != null) + { + var kingName = king.Name ?? ""; + var killerName = killer.Name ?? ""; + + m_Game.Alert("{0} ({1}) was dethroned by {2} ({3})!", kingName, kingTeam.Name, killerName, killerTeam.Name); + } + + DeKingify(); + } + + private void DeKingify() + { + PublicOverheadMessage(MessageType.Regular, 0x0481, false, "Free!"); + + m_KingTimer?.Stop(); + + King = null; + } + + private void ReKingify(Mobile m) + { + if (m_Game == null || m == null) + return; + + if (m_Game.GetTeamInfo(m) == null) + return; + + King = m; + + m_KingTimer ??= new KingTimer(this); + m_KingTimer.Stop(); + m_KingTimer.StartHillTicker(); + + if (King.Name != null) + PublicOverheadMessage(MessageType.Regular, 0x0481, false, $"Taken by {King.Name}!"); + } + + private class KingTimer : Timer + { + private readonly HillOfTheKing m_Hill; + private int m_Counter; + + public KingTimer(HillOfTheKing hill) + : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)) + { + m_Hill = hill; + Captures = 0; + m_Counter = 0; + + Priority = TimerPriority.FiftyMS; + } + + public int Captures { get; private set; } + + public void StartHillTicker() + { + Captures = 0; + m_Counter = 0; + + Start(); + } + + protected override void OnTick() + { + KHPlayerInfo pi = null; + + if (m_Hill?.Deleted != false || m_Hill.Game == null) + { + Stop(); + return; + } + + if (m_Hill.King?.Deleted != false || !m_Hill.King.Alive) + { + m_Hill.DeKingify(); + Stop(); + return; + } + + var ti = m_Hill.Game.GetTeamInfo(m_Hill.King); + if (ti != null) + pi = ti[m_Hill.King]; + + if (ti == null || pi == null) + { + // error, bail + m_Hill.DeKingify(); + Stop(); + return; + } + + m_Counter++; + + m_Hill.King.RevealingAction(); + + if (m_Counter >= m_Hill.ScoreInterval) + { + var hill = m_Hill.Name.IsNullOrDefault("the hill"); + var king = m_Hill.King.Name ?? ""; + + m_Hill.Game.Alert("{0} ({1}) is king of {2}!", king, ti.Name, hill); + + m_Hill.PublicOverheadMessage(MessageType.Regular, 0x0481, false, "Capture!"); + + pi.Captures++; + Captures++; + + pi.Score += m_Counter; + + m_Counter = 0; + } + else + { + m_Hill.PublicOverheadMessage( + MessageType.Regular, + 0x0481, + false, + (m_Hill.ScoreInterval - m_Counter).ToString() + ); + } + } + } + } + + public class KHBoard : Item + { + private KHController m_Controller; + public KHGame m_Game; + + [Constructible] + public KHBoard() + : base(7774) + { + Name = "King of the Hill Scoreboard"; + Movable = false; + } + + public KHBoard(Serial serial) + : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public KHController Controller + { + get => m_Controller; + set + { + if (m_Controller != value) + { + m_Controller?.RemoveBoard(this); + m_Controller = value; + m_Controller?.AddBoard(this); + } + } + } + + public override void OnDoubleClick(Mobile from) + { + if (m_Game != null) + { + from.CloseGump(); + from.SendGump(new KHBoardGump(from, m_Game)); + } + else + { + from.SendMessage("There is no King of the Hill game in progress."); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + writer.Write(m_Controller); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Controller = reader.ReadItem() as KHController; + break; + } + } + } + } + + public sealed class KHBoardGump : Gump + { + private const int LabelColor32 = 0xFFFFFF; + private const int BlackColor32 = 0x000000; + + private KHGame m_Game; + + public KHBoardGump(Mobile mob, KHGame game) + : base(60, 60) + { + m_Game = game; + + var ourTeam = game.GetTeamInfo(mob); + + var entries = new List(); + + for (var i = 0; i < game.Context.Participants.Count; ++i) + { + var teamInfo = game.Controller.TeamInfo[i % game.Controller.TeamInfo.Length]; + + if (teamInfo != null) + entries.Add(teamInfo); + } + + entries.Sort(); + /* + delegate( IRankedCTF a, IRankedCTF b ) + { + return b.Score - a.Score; + } );*/ + + var height = 73 + entries.Count * 75 + 28; + + Closable = false; + + AddPage(0); + + AddBackground(1, 1, 398, height, 3600); + + AddImageTiled(16, 15, 369, height - 29, 3604); + + for (var i = 0; i < entries.Count; i += 1) + AddImageTiled(22, 58 + i * 75, 357, 70, 0x2430); + + AddAlphaRegion(16, 15, 369, height - 29); + + AddImage(215, -45, 0xEE40); + // AddImage( 330, 141, 0x8BA ); + + AddBorderedText(22, 22, 294, 20, Center("King of the Hill Scoreboard"), LabelColor32, BlackColor32); + + AddImageTiled(32, 50, 264, 1, 9107); + AddImageTiled(42, 52, 264, 1, 9157); + + for (var i = 0; i < entries.Count; ++i) + { + var teamInfo = entries[i]; + + AddImage(30, 70 + i * 75, 10152); + AddImage(30, 85 + i * 75, 10151); + AddImage(30, 100 + i * 75, 10151); + AddImage(30, 106 + i * 75, 10154); + + AddImage(24, 60 + i * 75, teamInfo == ourTeam ? 9730 : 9727, teamInfo.Color - 1); + + var nameColor = LabelColor32; + var borderColor = BlackColor32; + + switch (teamInfo.Color) + { + case 0x47E: + nameColor = 0xFFFFFF; + break; + + case 0x4F2: + nameColor = 0x3399FF; + break; + + case 0x4F7: + nameColor = 0x33FF33; + break; + + case 0x4FC: + nameColor = 0xFF00FF; + break; + + case 0x021: + nameColor = 0xFF3333; + break; + + case 0x01A: + nameColor = 0xFF66FF; + break; + + case 0x455: + nameColor = 0x333333; + borderColor = 0xFFFFFF; + break; + } + + AddBorderedText( + 60, + 65 + i * 75, + 250, + 20, + $"{LadderGump.Rank(1 + i)}: {teamInfo.Name}", + nameColor, + borderColor + ); + + AddBorderedText(50 + 10, 85 + i * 75, 100, 20, "Score:", 0xFFC000, BlackColor32); + AddBorderedText(50 + 15, 105 + i * 75, 100, 20, teamInfo.Score.ToString("N0"), 0xFFC000, BlackColor32); + + AddBorderedText(110 + 10, 85 + i * 75, 100, 20, "Kills:", 0xFFC000, BlackColor32); + AddBorderedText(110 + 15, 105 + i * 75, 100, 20, teamInfo.Kills.ToString("N0"), 0xFFC000, BlackColor32); + + AddBorderedText(160 + 10, 85 + i * 75, 100, 20, "Captures:", 0xFFC000, BlackColor32); + AddBorderedText(160 + 15, 105 + i * 75, 100, 20, teamInfo.Captures.ToString("N0"), 0xFFC000, BlackColor32); + + var leader = teamInfo.Leader?.Name ?? "(none)"; + + AddBorderedText(235 + 10, 85 + i * 75, 250, 20, "Leader:", 0xFFC000, BlackColor32); + AddBorderedText(235 + 15, 105 + i * 75, 250, 20, leader, 0xFFC000, BlackColor32); + } + + AddButton(314, height - 42, 247, 248, 1); + } + + public string Center(string text) => $"
{text}
"; + + public string Color(string text, int color) => $"{text}"; + + private void AddBorderedText(int x, int y, int width, int height, string text, int color, int borderColor) + { + AddColoredText(x - 1, y - 1, width, height, text, borderColor); + AddColoredText(x - 1, y + 1, width, height, text, borderColor); + AddColoredText(x + 1, y - 1, width, height, text, borderColor); + AddColoredText(x + 1, y + 1, width, height, text, borderColor); + AddColoredText(x, y, width, height, text, color); + } + + private void AddColoredText(int x, int y, int width, int height, string text, int color) + { + if (color == 0) + AddHtml(x, y, width, height, text); + else + AddHtml(x, y, width, height, Color(text, color)); + } + } + + public sealed class KHPlayerInfo : IRankedCTF, IComparable + { + private readonly KHTeamInfo m_TeamInfo; + private int m_Captures; + + private int m_Kills; + private int m_Score; + + public KHPlayerInfo(KHTeamInfo teamInfo, Mobile player) + { + m_TeamInfo = teamInfo; + Player = player; + } + + public Mobile Player { get; } + + public int CompareTo(KHPlayerInfo pi) + { + var res = pi.Score.CompareTo(Score); + if (res != 0) + return res; + + res = pi.Captures.CompareTo(Captures); + + return res != 0 ? res : pi.Kills.CompareTo(Kills); + } + + public string Name => Player.Name ?? ""; + + public int Kills + { + get => m_Kills; + set + { + m_TeamInfo.Kills += value - m_Kills; + m_Kills = value; + } + } + + public int Captures + { + get => m_Captures; + set + { + m_TeamInfo.Captures += value - m_Captures; + m_Captures = value; + } + } + + public int Score + { + get => m_Score; + set + { + m_TeamInfo.Score += value - m_Score; + m_Score = value; + + if (m_TeamInfo.Leader == null || m_Score > m_TeamInfo.Leader.Score) + m_TeamInfo.Leader = this; + } + } + } + + [PropertyObject] + public sealed class KHTeamInfo : IRankedCTF, IComparable + { + public KHTeamInfo(int teamID) + { + TeamID = teamID; + Players = new Dictionary(); + } + + public KHTeamInfo(int teamID, IGenericReader ip) + { + TeamID = teamID; + Players = new Dictionary(); + + var version = ip.ReadEncodedInt(); + + switch (version) + { + case 0: + { + TeamName = ip.ReadString(); + Color = ip.ReadEncodedInt(); + break; + } + } + } + + public KHGame Game { get; set; } + + public int TeamID { get; } + + public KHPlayerInfo Leader { get; set; } + + public Dictionary Players { get; } + + public KHPlayerInfo this[Mobile mob] + { + get + { + if (mob == null) + return null; + + if (!Players.TryGetValue(mob, out var val)) + Players[mob] = val = new KHPlayerInfo(this, mob); + + return val; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Color { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public string TeamName { get; set; } + + public int CompareTo(KHTeamInfo ti) + { + var res = ti.Score.CompareTo(Score); + if (res != 0) + return res; + + res = ti.Captures.CompareTo(Captures); + + if (res == 0) + res = ti.Kills.CompareTo(Kills); + + return res; + } + + public string Name => $"{TeamName ?? "(none)"} Team"; + + public int Kills { get; set; } + + public int Captures { get; set; } + + public int Score { get; set; } + + public void Reset() + { + Kills = 0; + Captures = 0; + Score = 0; + + Leader = null; + + Players.Clear(); + } + + public void Serialize(IGenericWriter op) + { + op.WriteEncodedInt(0); // version + + op.Write(TeamName); + op.WriteEncodedInt(Color); + } + + public override string ToString() => TeamName != null ? $"({Name}) ..." : "..."; + } + + public sealed class KHController : EventController + { + private int m_ScoreInterval; + + [Constructible] + public KHController() + { + Visible = false; + Movable = false; + + Name = "King of the Hill Controller"; + + Duration = TimeSpan.FromMinutes(30.0); + Boards = new List(); + Hills = new HillOfTheKing[4]; + TeamInfo = new KHTeamInfo[8]; + + for (var i = 0; i < TeamInfo.Length; ++i) + TeamInfo[i] = new KHTeamInfo(i); + } + + public KHController(Serial serial) + : base(serial) + { + } + + public KHTeamInfo[] TeamInfo { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public KHTeamInfo Team1_W => TeamInfo[0]; + + [CommandProperty(AccessLevel.GameMaster)] + public KHTeamInfo Team2_E => TeamInfo[1]; + + [CommandProperty(AccessLevel.GameMaster)] + public KHTeamInfo Team3_N => TeamInfo[2]; + + [CommandProperty(AccessLevel.GameMaster)] + public KHTeamInfo Team4_S => TeamInfo[3]; + + [CommandProperty(AccessLevel.GameMaster)] + public KHTeamInfo Team5_NW => TeamInfo[4]; + + [CommandProperty(AccessLevel.GameMaster)] + public KHTeamInfo Team6_SE => TeamInfo[5]; + + [CommandProperty(AccessLevel.GameMaster)] + public KHTeamInfo Team7_SW => TeamInfo[6]; + + [CommandProperty(AccessLevel.GameMaster)] + public KHTeamInfo Team8_NE => TeamInfo[7]; + + public HillOfTheKing[] Hills { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public HillOfTheKing Hill1 + { + get => Hills[0]; + set => Hills[0] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public HillOfTheKing Hill2 + { + get => Hills[1]; + set => Hills[1] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public HillOfTheKing Hill3 + { + get => Hills[2]; + set => Hills[2] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public HillOfTheKing Hill4 + { + get => Hills[3]; + set => Hills[3] = value; + } + + public List Boards { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan Duration { get; set; } + + public override string Title => "King of the Hill"; + + public override string GetTeamName(int teamID) => TeamInfo[teamID % TeamInfo.Length].Name; + + public override EventGame Construct(DuelContext context) => new KHGame(this, context); + + public void RemoveBoard(KHBoard b) + { + if (b != null) + { + Boards.Remove(b); + b.m_Game = null; + } + } + + public void AddBoard(KHBoard b) + { + if (b != null) + Boards.Add(b); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + writer.WriteEncodedInt(m_ScoreInterval); + writer.Write(Duration); + + writer.WriteItemList(Boards, true); + + writer.WriteEncodedInt(Hills.Length); + for (var i = 0; i < Hills.Length; ++i) + writer.Write(Hills[i]); + + writer.WriteEncodedInt(TeamInfo.Length); + for (var i = 0; i < TeamInfo.Length; ++i) + TeamInfo[i].Serialize(writer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_ScoreInterval = reader.ReadEncodedInt(); + + Duration = reader.ReadTimeSpan(); + + Boards = reader.ReadStrongItemList(); + + Hills = new HillOfTheKing[reader.ReadEncodedInt()]; + for (var i = 0; i < Hills.Length; ++i) + Hills[i] = reader.ReadItem() as HillOfTheKing; + + TeamInfo = new KHTeamInfo[reader.ReadEncodedInt()]; + for (var i = 0; i < TeamInfo.Length; ++i) + TeamInfo[i] = new KHTeamInfo(i, reader); + + break; + } + } + } + } + + public sealed class KHGame : EventGame + { + private Timer m_FinishTimer; + + public KHGame(KHController controller, DuelContext context) : base(context) => Controller = controller; + + public KHController Controller { get; } + + public Map Facet + { + get + { + if (m_Context?.Arena != null) + return m_Context.Arena.Facet; + + return Controller.Map; + } + } + + public override bool CantDoAnything(Mobile mob) + { + if (mob != null && GetTeamInfo(mob) != null && Controller != null) + for (var i = 0; i < Controller.Hills.Length; i++) + if (Controller.Hills[i]?.King == mob) + return true; + + return false; + } + + public void Alert(string text) + { + m_Context.m_Tournament?.Alert(text); + + for (var i = 0; i < m_Context.Participants.Count; ++i) + { + var p = m_Context.Participants[i]; + + for (var j = 0; j < p.Players.Length; ++j) + if (p.Players[j] != null) + p.Players[j].Mobile.SendMessage(0x35, text); + } + } + + public void Alert(string format, params object[] args) + { + Alert(string.Format(format, args)); + } + + public KHTeamInfo GetTeamInfo(Mobile mob) + { + var teamID = GetTeamID(mob); + + if (teamID >= 0) + return Controller.TeamInfo[teamID % Controller.TeamInfo.Length]; + + return null; + } + + public int GetTeamID(Mobile mob) + { + if (!(mob is PlayerMobile pm)) + return mob is BaseCreature creature ? creature.Team - 1 : -1; + + if (pm.DuelContext == null || pm.DuelContext != m_Context) + return -1; + + if (pm.DuelPlayer?.Eliminated != false) + return -1; + + return pm.DuelContext.Participants.IndexOf(pm.DuelPlayer.Participant); + } + + public int GetColor(Mobile mob) => GetTeamInfo(mob)?.Color ?? -1; + + private void ApplyHues(Participant p, int hueOverride) + { + for (var i = 0; i < p.Players.Length; ++i) + if (p.Players[i] != null) + p.Players[i].Mobile.SolidHueOverride = hueOverride; + } + + public void DelayBounce(TimeSpan ts, Mobile mob, Container corpse) + { + Timer.DelayCall(ts, DelayBounce_Callback, mob, corpse); + } + + private void DelayBounce_Callback(Mobile mob, Container corpse) + { + var dp = (mob as PlayerMobile)?.DuelPlayer; + + m_Context.RemoveAggressions(mob); + + if (dp?.Eliminated == false) + mob.MoveToWorld(m_Context.Arena.GetBaseStartPoint(GetTeamID(mob)), Facet); + else + m_Context.SendOutside(mob); + + m_Context.Refresh(mob, corpse); + DuelContext.Debuff(mob); + DuelContext.CancelSpell(mob); + mob.Frozen = false; + + if (corpse?.Deleted == false) + Timer.DelayCall(TimeSpan.FromSeconds(30), corpse.Delete); + } + + public override bool OnDeath(Mobile mob, Container corpse) + { + var killer = mob.FindMostRecentDamager(false); + KHTeamInfo teamInfo = null; + var victInfo = GetTeamInfo(mob); + var bonus = 0; + + if (killer?.Player == true) + teamInfo = GetTeamInfo(killer); + + for (var i = 0; i < Controller.Hills.Length; i++) + { + if (Controller.Hills[i] == null) + continue; + + if (Controller.Hills[i].King == mob) + { + bonus += Controller.Hills[i].CapturesSoFar; + Controller.Hills[i].OnKingDied(mob, victInfo, killer, teamInfo); + } + + if (Controller.Hills[i].King == killer) + bonus += 2; + } + + if (teamInfo != null && teamInfo != victInfo) + { + var playerInfo = teamInfo[killer]; + + if (playerInfo != null) + { + playerInfo.Kills += 1; + playerInfo.Score += 1 + bonus; + } + } + + mob.CloseGump(); + mob.SendGump(new KHBoardGump(mob, this)); + + m_Context.Requip(mob, corpse); + DelayBounce(TimeSpan.FromSeconds(30.0), mob, corpse); + + return false; + } + + public override void OnStart() + { + for (var i = 0; i < Controller.TeamInfo.Length; ++i) + { + var teamInfo = Controller.TeamInfo[i]; + + teamInfo.Game = this; + teamInfo.Reset(); + } + + for (var i = 0; i < m_Context.Participants.Count; ++i) + ApplyHues( + m_Context.Participants[i], + Controller.TeamInfo[i % Controller.TeamInfo.Length].Color + ); + + m_FinishTimer?.Stop(); + + for (var i = 0; i < Controller.Hills.Length; i++) + if (Controller.Hills[i] != null) + Controller.Hills[i].Game = this; + + foreach (var board in Controller.Boards) + if (board?.Deleted == false) + board.m_Game = this; + + m_FinishTimer = Timer.DelayCall(Controller.Duration, Finish_Callback); + } + + private void Finish_Callback() + { + var teams = new List(); + + for (var i = 0; i < m_Context.Participants.Count; ++i) + { + var teamInfo = Controller.TeamInfo[i % Controller.TeamInfo.Length]; + + if (teamInfo != null) + teams.Add(teamInfo); + } + + teams.Sort(); + + var tourney = m_Context.m_Tournament; + + var sb = new StringBuilder(); + + if (tourney != null) + { + if (tourney.TourneyType == TourneyType.FreeForAll) + { + sb.Append(m_Context.Participants.Count * tourney.PlayersPerParticipant); + sb.Append("-man FFA"); + } + else if (tourney.TourneyType == TourneyType.RandomTeam) + { + sb.Append(tourney.ParticipantsPerMatch); + sb.Append("-team"); + } + else if (tourney.TourneyType == TourneyType.RedVsBlue) + { + sb.Append("Red v Blue"); + } + else + { + for (var i = 0; i < tourney.ParticipantsPerMatch; ++i) + { + if (sb.Length > 0) + sb.Append('v'); + + sb.Append(tourney.PlayersPerParticipant); + } + } + } + + if (Controller != null) + sb.Append(' ').Append(Controller.Title); + + var title = sb.ToString(); + + var winner = teams.Count > 0 ? teams[0] : null; + + for (var i = 0; i < teams.Count; ++i) + { + var rank = TrophyRank.Bronze; + + if (i == 0) + rank = TrophyRank.Gold; + else if (i == 1) + rank = TrophyRank.Silver; + + var leader = teams[i].Leader; + + foreach (var pl in teams[i].Players.Values) + { + var mob = pl.Player; + + if (mob == null) + continue; + + sb = new StringBuilder(); + + sb.Append(title); + + if (pl == leader) + sb.Append(" Leader"); + + if (pl.Score > 0) + { + sb.Append(": "); + + sb.Append(pl.Score.ToString("N0")); + sb.Append(pl.Score == 1 ? " point" : " points"); + + sb.Append(", "); + sb.Append(pl.Kills.ToString("N0")); + sb.Append(pl.Kills == 1 ? " kill" : " kills"); + + if (pl.Captures > 0) + { + sb.Append(", "); + sb.Append(pl.Captures.ToString("N0")); + sb.Append(pl.Captures == 1 ? " capture" : " captures"); + } + } + + Item item = new Trophy(sb.ToString(), rank); + + if (pl == leader) + item.ItemID = 4810; + + item.Name = $"{item.Name}, {teams[i].Name.ToLower()}"; + + if (!mob.PlaceInBackpack(item)) + mob.BankBox.DropItem(item); + + var cash = pl.Score * 250; + + if (cash > 0) + { + item = new BankCheck(cash); + + if (!mob.PlaceInBackpack(item)) + mob.BankBox.DropItem(item); + + mob.SendMessage( + "You have been awarded a {0} trophy and {1:N0}gp for your participation in this game.", + rank.ToString().ToLower(), + cash + ); + } + else + { + mob.SendMessage( + "You have been awarded a {0} trophy for your participation in this game.", + rank.ToString().ToLower() + ); + } + } + } + + for (var i = 0; i < m_Context.Participants.Count; ++i) + { + var p = m_Context.Participants[i]; + if (p.Players == null) + continue; + + for (var j = 0; j < p.Players.Length; ++j) + { + var dp = p.Players[j]; + + if (dp?.Mobile != null) + { + dp.Mobile.CloseGump(); + dp.Mobile.SendGump(new KHBoardGump(dp.Mobile, this)); + } + } + + if (i == winner?.TeamID) + continue; + + if (p.Players != null) + for (var j = 0; j < p.Players.Length; ++j) + if (p.Players[j] != null) + p.Players[j].Eliminated = true; + } + + if (winner != null) + m_Context.Finish(m_Context.Participants[winner.TeamID]); + } + + public override void OnStop() + { + for (var i = 0; i < Controller.TeamInfo.Length; ++i) + Controller.TeamInfo[i].Game = null; + + for (var i = 0; i < Controller.Hills.Length; ++i) + if (Controller.Hills[i] != null) + Controller.Hills[i].Game = null; + + foreach (var board in Controller.Boards) + if (board != null) + board.m_Game = null; + + for (var i = 0; i < m_Context.Participants.Count; ++i) + ApplyHues(m_Context.Participants[i], -1); + + m_FinishTimer?.Stop(); + m_FinishTimer = null; + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Games/TourneyMatch.cs b/Projects/UOContent/Engines/ConPVP/Games/TourneyMatch.cs index 525c9cd54..e7eb4dcb8 100644 --- a/Projects/UOContent/Engines/ConPVP/Games/TourneyMatch.cs +++ b/Projects/UOContent/Engines/ConPVP/Games/TourneyMatch.cs @@ -1,122 +1,129 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Server.Network; - -namespace Server.Engines.ConPVP -{ - public class TourneyMatch - { - public TourneyMatch(List participants) - { - Participants = participants; - - for (int i = 0; i < participants.Count; ++i) - { - TourneyParticipant part = participants[i]; - - StringBuilder sb = new StringBuilder(); - - sb.Append("Matched in a duel against "); - - if (participants.Count > 2) - sb.AppendFormat("{0} other {1}: ", participants.Count - 1, - part.Players.Count == 1 ? "players" : "teams"); - - bool hasAppended = false; - - for (int j = 0; j < participants.Count; ++j) - { - if (i == j) - continue; - - if (hasAppended) - sb.Append(", "); - - sb.Append(participants[j].NameList); - hasAppended = true; - } - - sb.Append("."); - - part.AddLog(sb.ToString()); - } - } - - public List Participants { get; set; } - - public TourneyParticipant Winner { get; set; } - - public DuelContext Context { get; set; } - - public bool InProgress => Context?.Registered == true; - - public void Start(Arena arena, Tournament tourney) - { - TourneyParticipant first = Participants[0]; - - DuelContext dc = new DuelContext(first.Players[0], tourney.Ruleset.Layout, false); - dc.Ruleset.Options.SetAll(false); - dc.Ruleset.Options.Or(tourney.Ruleset.Options); - - for (int i = 0; i < Participants.Count; ++i) - { - TourneyParticipant tourneyPart = Participants[i]; - Participant duelPart = new Participant(dc, tourneyPart.Players.Count) - { - TourneyPart = tourneyPart - }; - - for (int j = 0; j < tourneyPart.Players.Count; ++j) - duelPart.Add(tourneyPart.Players[j]); - - for (int j = 0; j < duelPart.Players.Length; ++j) - if (duelPart.Players[j] != null) - duelPart.Players[j].Ready = true; - - dc.Participants.Add(duelPart); - } - - if (tourney.EventController != null) - dc.m_EventGame = tourney.EventController.Construct(dc); - - dc.m_Tournament = tourney; - dc.m_Match = this; - - dc.m_OverrideArena = arena; - - if (tourney.SuddenDeath > TimeSpan.Zero && - (tourney.SuddenDeathRounds == 0 || tourney.Pyramid.Levels.Count <= tourney.SuddenDeathRounds)) - dc.StartSuddenDeath(tourney.SuddenDeath); - - dc.SendReadyGump(0); - - if (dc.StartedBeginCountdown) - { - Context = dc; - - for (int i = 0; i < Participants.Count; ++i) - { - TourneyParticipant p = Participants[i]; - - for (int j = 0; j < p.Players.Count; ++j) - { - Mobile mob = p.Players[j]; - - foreach (Mobile view in mob.GetMobilesInRange(18)) - if (!mob.CanSee(view)) - mob.Send(view.RemovePacket); - - mob.LocalOverheadMessage(MessageType.Emote, 0x3B2, false, - "* Your mind focuses intently on the fight and all other distractions fade away *"); - } - } - } - else - { - dc.Unregister(); - dc.StopCountdown(); - } - } - } -} +using System; +using System.Collections.Generic; +using System.Text; +using Server.Network; + +namespace Server.Engines.ConPVP +{ + public class TourneyMatch + { + public TourneyMatch(List participants) + { + Participants = participants; + + for (var i = 0; i < participants.Count; ++i) + { + var part = participants[i]; + + var sb = new StringBuilder(); + + sb.Append("Matched in a duel against "); + + if (participants.Count > 2) + sb.AppendFormat( + "{0} other {1}: ", + participants.Count - 1, + part.Players.Count == 1 ? "players" : "teams" + ); + + var hasAppended = false; + + for (var j = 0; j < participants.Count; ++j) + { + if (i == j) + continue; + + if (hasAppended) + sb.Append(", "); + + sb.Append(participants[j].NameList); + hasAppended = true; + } + + sb.Append("."); + + part.AddLog(sb.ToString()); + } + } + + public List Participants { get; set; } + + public TourneyParticipant Winner { get; set; } + + public DuelContext Context { get; set; } + + public bool InProgress => Context?.Registered == true; + + public void Start(Arena arena, Tournament tourney) + { + var first = Participants[0]; + + var dc = new DuelContext(first.Players[0], tourney.Ruleset.Layout, false); + dc.Ruleset.Options.SetAll(false); + dc.Ruleset.Options.Or(tourney.Ruleset.Options); + + for (var i = 0; i < Participants.Count; ++i) + { + var tourneyPart = Participants[i]; + var duelPart = new Participant(dc, tourneyPart.Players.Count) + { + TourneyPart = tourneyPart + }; + + for (var j = 0; j < tourneyPart.Players.Count; ++j) + duelPart.Add(tourneyPart.Players[j]); + + for (var j = 0; j < duelPart.Players.Length; ++j) + if (duelPart.Players[j] != null) + duelPart.Players[j].Ready = true; + + dc.Participants.Add(duelPart); + } + + if (tourney.EventController != null) + dc.m_EventGame = tourney.EventController.Construct(dc); + + dc.m_Tournament = tourney; + dc.m_Match = this; + + dc.m_OverrideArena = arena; + + if (tourney.SuddenDeath > TimeSpan.Zero && + (tourney.SuddenDeathRounds == 0 || tourney.Pyramid.Levels.Count <= tourney.SuddenDeathRounds)) + dc.StartSuddenDeath(tourney.SuddenDeath); + + dc.SendReadyGump(0); + + if (dc.StartedBeginCountdown) + { + Context = dc; + + for (var i = 0; i < Participants.Count; ++i) + { + var p = Participants[i]; + + for (var j = 0; j < p.Players.Count; ++j) + { + var mob = p.Players[j]; + + foreach (var view in mob.GetMobilesInRange(18)) + if (!mob.CanSee(view)) + mob.Send(view.RemovePacket); + + mob.LocalOverheadMessage( + MessageType.Emote, + 0x3B2, + false, + "* Your mind focuses intently on the fight and all other distractions fade away *" + ); + } + } + } + else + { + dc.Unregister(); + dc.StopCountdown(); + } + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Gumps/AcceptTeamGump.cs b/Projects/UOContent/Engines/ConPVP/Gumps/AcceptTeamGump.cs index 37ec2a5ff..281293dd1 100644 --- a/Projects/UOContent/Engines/ConPVP/Gumps/AcceptTeamGump.cs +++ b/Projects/UOContent/Engines/ConPVP/Gumps/AcceptTeamGump.cs @@ -1,349 +1,412 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Text; -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.ConPVP -{ - public class AcceptTeamGump : Gump - { - private const int BlackColor32 = 0x000008; - private const int LabelColor32 = 0xFFFFFF; - private bool m_Active; - - private readonly Mobile m_From; - private readonly List m_Players; - private readonly Mobile m_Registrar; - private readonly Mobile m_Requested; - private readonly Tournament m_Tournament; - - public AcceptTeamGump(Mobile from, Mobile requested, Tournament tourney, Mobile registrar, List players) : base(50, 50) - { - m_From = from; - m_Requested = requested; - m_Tournament = tourney; - m_Registrar = registrar; - m_Players = players; - - m_Active = true; - - Ruleset ruleset = tourney.Ruleset; - Ruleset basedef = ruleset.Base; - - int height = 185 + 35 + 60 + 12; - - int changes = 0; - - BitArray defs; - - if (ruleset.Flavors.Count > 0) - { - defs = new BitArray(basedef.Options); - - for (int i = 0; i < ruleset.Flavors.Count; ++i) - defs.Or(ruleset.Flavors[i].Options); - - height += ruleset.Flavors.Count * 18; - } - else - { - defs = basedef.Options; - } - - BitArray opts = ruleset.Options; - - for (int i = 0; i < opts.Length; ++i) - if (defs[i] != opts[i]) - ++changes; - - height += changes * 22; - - height += 10 + 22 + 25 + 25; - - Closable = false; - - AddPage(0); - - AddBackground(1, 1, 398, height, 3600); - - AddImageTiled(16, 15, 369, height - 29, 3604); - AddAlphaRegion(16, 15, 369, height - 29); - - AddImage(215, -43, 0xEE40); - - StringBuilder sb = new StringBuilder(); - - if (tourney.TourneyType == TourneyType.FreeForAll) - { - sb.Append("FFA"); - } - else if (tourney.TourneyType == TourneyType.RandomTeam) - { - sb.Append(tourney.ParticipantsPerMatch); - sb.Append("-Team"); - } - else if (tourney.TourneyType == TourneyType.Faction) - { - sb.Append(tourney.ParticipantsPerMatch); - sb.Append("-Team Faction"); - } - else if (tourney.TourneyType == TourneyType.RedVsBlue) - { - sb.Append("Red v Blue"); - } - else - { - for (int i = 0; i < tourney.ParticipantsPerMatch; ++i) - { - if (sb.Length > 0) - sb.Append('v'); - - sb.Append(tourney.PlayersPerParticipant); - } - } - - if (tourney.EventController != null) - sb.Append(' ').Append(tourney.EventController.Title); - - sb.Append(" Tournament Invitation"); - - AddBorderedText(22, 22, 294, 20, Center(sb.ToString()), LabelColor32, BlackColor32); - - AddBorderedText(22, 50, 294, 40, - $"You have been asked to partner with {from.Name} in a tournament. Do you accept?", - 0xB0C868, BlackColor32); - - AddImageTiled(32, 88, 264, 1, 9107); - AddImageTiled(42, 90, 264, 1, 9157); - - int y = 100; - - var groupText = tourney.GroupType switch - { - GroupingType.HighVsLow => "High vs Low", - GroupingType.Nearest => "Closest opponent", - GroupingType.Random => "Random", - _ => null - }; - - AddBorderedText(35, y, 190, 20, $"Grouping: {groupText}", LabelColor32, BlackColor32); - y += 20; - - var tieText = tourney.TieType switch - { - TieType.Random => "Random", - TieType.Highest => "Highest advances", - TieType.Lowest => "Lowest advances", - TieType.FullAdvancement => tourney.ParticipantsPerMatch == 2 ? "Both advance" : "Everyone advances", - TieType.FullElimination => tourney.ParticipantsPerMatch == 2 ? "Both eliminated" : "Everyone eliminated", - _ => null - }; - - AddBorderedText(35, y, 190, 20, $"Tiebreaker: {tieText}", LabelColor32, BlackColor32); - y += 20; - - string sdText = "Off"; - - if (tourney.SuddenDeath > TimeSpan.Zero) - { - sdText = $"{(int)tourney.SuddenDeath.TotalMinutes}:{tourney.SuddenDeath.Seconds:D2}"; - - if (tourney.SuddenDeathRounds > 0) - sdText = $"{sdText} (first {tourney.SuddenDeathRounds} rounds)"; - else - sdText = $"{sdText} (all rounds)"; - } - - AddBorderedText(35, y, 240, 20, $"Sudden Death: {sdText}", LabelColor32, BlackColor32); - y += 20; - - y += 6; - AddImageTiled(32, y - 1, 264, 1, 9107); - AddImageTiled(42, y + 1, 264, 1, 9157); - y += 6; - - AddBorderedText(35, y, 190, 20, $"Ruleset: {basedef.Title}", LabelColor32, BlackColor32); - y += 20; - - for (int i = 0; i < ruleset.Flavors.Count; ++i, y += 18) - AddBorderedText(35, y, 190, 20, $" + {ruleset.Flavors[i].Title}", LabelColor32, BlackColor32); - - y += 4; - - if (changes > 0) - { - AddBorderedText(35, y, 190, 20, "Modifications:", LabelColor32, BlackColor32); - y += 20; - - for (int i = 0; i < opts.Length; ++i) - if (defs[i] != opts[i]) - { - string name = ruleset.Layout.FindByIndex(i); - - if (name != null) // sanity - { - AddImage(35, y, opts[i] ? 0xD3 : 0xD2); - AddBorderedText(60, y, 165, 22, name, LabelColor32, BlackColor32); - } - - y += 22; - } - } - else - { - AddBorderedText(35, y, 190, 20, "Modifications: None", LabelColor32, BlackColor32); - y += 20; - } - - y += 8; - AddImageTiled(32, y - 1, 264, 1, 9107); - AddImageTiled(42, y + 1, 264, 1, 9157); - y += 8; - - AddRadio(24, y, 9727, 9730, true, 1); - AddBorderedText(60, y + 5, 250, 20, "Yes, I will join them.", LabelColor32, BlackColor32); - y += 35; - - AddRadio(24, y, 9727, 9730, false, 2); - AddBorderedText(60, y + 5, 250, 20, "No, I do not wish to fight.", LabelColor32, BlackColor32); - y += 35; - - AddRadio(24, y, 9727, 9730, false, 3); - AddBorderedText(60, y + 5, 270, 20, "No, most certainly not. Do not ask again.", LabelColor32, BlackColor32); - y += 35; - - y -= 3; - AddButton(314, y, 247, 248, 1); - - Timer.DelayCall(TimeSpan.FromSeconds(15.0), AutoReject); - } - - public string Center(string text) => $"
{text}
"; - - public string Color(string text, int color) => $"{text}"; - - private void AddBorderedText(int x, int y, int width, int height, string text, int color, int borderColor) - { - AddColoredText(x - 1, y - 1, width, height, text, borderColor); - AddColoredText(x - 1, y + 1, width, height, text, borderColor); - AddColoredText(x + 1, y - 1, width, height, text, borderColor); - AddColoredText(x + 1, y + 1, width, height, text, borderColor); - AddColoredText(x, y, width, height, text, color); - } - - private void AddColoredText(int x, int y, int width, int height, string text, int color) - { - if (color == 0) - AddHtml(x, y, width, height, text); - else - AddHtml(x, y, width, height, Color(text, color)); - } - - public void AutoReject() - { - if (!m_Active) - return; - - m_Active = false; - - m_Requested.CloseGump(); - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - - if (m_Registrar != null) - { - m_Registrar.PrivateOverheadMessage(MessageType.Regular, - 0x22, false, $"{m_Requested.Name} seems unresponsive.", m_From.NetState); - - m_Registrar.PrivateOverheadMessage(MessageType.Regular, - 0x22, false, $"You have declined the partnership with {m_From.Name}.", m_Requested.NetState); - } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - Mobile from = m_From; - Mobile mob = m_Requested; - - if (info.ButtonID != 1 || !m_Active) - return; - - m_Active = false; - - if (info.IsSwitched(1)) - { - if (!(mob is PlayerMobile pm)) - return; - - if (AcceptDuelGump.IsIgnored(mob, from) || mob.Blessed) - { - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - - m_Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x22, false, "They ignore your invitation.", from.NetState); - } - else if (pm.DuelContext != null) - { - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - - m_Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x22, false, "They are already assigned to another duel.", from.NetState); - } - else if (m_Players.Contains(mob)) - { - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - - m_Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x22, false, "You have already named them as a team member.", from.NetState); - } - else if (m_Tournament.HasParticipant(mob)) - { - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - - m_Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x22, false, "They have already entered this tournament.", from.NetState); - } - else if (m_Players.Count >= m_Tournament.PlayersPerParticipant) - { - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - - m_Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x22, false, "Your team is full.", from.NetState); - } - else - { - m_Players.Add(mob); - - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - - if (m_Registrar != null) - { - m_Registrar.PrivateOverheadMessage(MessageType.Regular, - 0x59, false, $"{mob.Name} has accepted your offer of partnership.", from.NetState); - - m_Registrar.PrivateOverheadMessage(MessageType.Regular, - 0x59, false, $"You have accepted the partnership with {from.Name}.", mob.NetState); - } - } - } - else - { - if (info.IsSwitched(3)) - AcceptDuelGump.BeginIgnore(m_Requested, m_From); - - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - - if (m_Registrar != null) - { - m_Registrar.PrivateOverheadMessage(MessageType.Regular, - 0x22, false, $"{mob.Name} has declined your offer of partnership.", from.NetState); - - m_Registrar.PrivateOverheadMessage(MessageType.Regular, - 0x22, false, $"You have declined the partnership with {from.Name}.", mob.NetState); - } - } - } - } -} +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.ConPVP +{ + public class AcceptTeamGump : Gump + { + private const int BlackColor32 = 0x000008; + private const int LabelColor32 = 0xFFFFFF; + + private readonly Mobile m_From; + private readonly List m_Players; + private readonly Mobile m_Registrar; + private readonly Mobile m_Requested; + private readonly Tournament m_Tournament; + private bool m_Active; + + public AcceptTeamGump( + Mobile from, Mobile requested, Tournament tourney, Mobile registrar, List players + ) : base(50, 50) + { + m_From = from; + m_Requested = requested; + m_Tournament = tourney; + m_Registrar = registrar; + m_Players = players; + + m_Active = true; + + var ruleset = tourney.Ruleset; + var basedef = ruleset.Base; + + var height = 185 + 35 + 60 + 12; + + var changes = 0; + + BitArray defs; + + if (ruleset.Flavors.Count > 0) + { + defs = new BitArray(basedef.Options); + + for (var i = 0; i < ruleset.Flavors.Count; ++i) + defs.Or(ruleset.Flavors[i].Options); + + height += ruleset.Flavors.Count * 18; + } + else + { + defs = basedef.Options; + } + + var opts = ruleset.Options; + + for (var i = 0; i < opts.Length; ++i) + if (defs[i] != opts[i]) + ++changes; + + height += changes * 22; + + height += 10 + 22 + 25 + 25; + + Closable = false; + + AddPage(0); + + AddBackground(1, 1, 398, height, 3600); + + AddImageTiled(16, 15, 369, height - 29, 3604); + AddAlphaRegion(16, 15, 369, height - 29); + + AddImage(215, -43, 0xEE40); + + var sb = new StringBuilder(); + + if (tourney.TourneyType == TourneyType.FreeForAll) + { + sb.Append("FFA"); + } + else if (tourney.TourneyType == TourneyType.RandomTeam) + { + sb.Append(tourney.ParticipantsPerMatch); + sb.Append("-Team"); + } + else if (tourney.TourneyType == TourneyType.Faction) + { + sb.Append(tourney.ParticipantsPerMatch); + sb.Append("-Team Faction"); + } + else if (tourney.TourneyType == TourneyType.RedVsBlue) + { + sb.Append("Red v Blue"); + } + else + { + for (var i = 0; i < tourney.ParticipantsPerMatch; ++i) + { + if (sb.Length > 0) + sb.Append('v'); + + sb.Append(tourney.PlayersPerParticipant); + } + } + + if (tourney.EventController != null) + sb.Append(' ').Append(tourney.EventController.Title); + + sb.Append(" Tournament Invitation"); + + AddBorderedText(22, 22, 294, 20, Center(sb.ToString()), LabelColor32, BlackColor32); + + AddBorderedText( + 22, + 50, + 294, + 40, + $"You have been asked to partner with {from.Name} in a tournament. Do you accept?", + 0xB0C868, + BlackColor32 + ); + + AddImageTiled(32, 88, 264, 1, 9107); + AddImageTiled(42, 90, 264, 1, 9157); + + var y = 100; + + var groupText = tourney.GroupType switch + { + GroupingType.HighVsLow => "High vs Low", + GroupingType.Nearest => "Closest opponent", + GroupingType.Random => "Random", + _ => null + }; + + AddBorderedText(35, y, 190, 20, $"Grouping: {groupText}", LabelColor32, BlackColor32); + y += 20; + + var tieText = tourney.TieType switch + { + TieType.Random => "Random", + TieType.Highest => "Highest advances", + TieType.Lowest => "Lowest advances", + TieType.FullAdvancement => tourney.ParticipantsPerMatch == 2 ? "Both advance" : "Everyone advances", + TieType.FullElimination => tourney.ParticipantsPerMatch == 2 ? "Both eliminated" : "Everyone eliminated", + _ => null + }; + + AddBorderedText(35, y, 190, 20, $"Tiebreaker: {tieText}", LabelColor32, BlackColor32); + y += 20; + + var sdText = "Off"; + + if (tourney.SuddenDeath > TimeSpan.Zero) + { + sdText = $"{(int)tourney.SuddenDeath.TotalMinutes}:{tourney.SuddenDeath.Seconds:D2}"; + + if (tourney.SuddenDeathRounds > 0) + sdText = $"{sdText} (first {tourney.SuddenDeathRounds} rounds)"; + else + sdText = $"{sdText} (all rounds)"; + } + + AddBorderedText(35, y, 240, 20, $"Sudden Death: {sdText}", LabelColor32, BlackColor32); + y += 20; + + y += 6; + AddImageTiled(32, y - 1, 264, 1, 9107); + AddImageTiled(42, y + 1, 264, 1, 9157); + y += 6; + + AddBorderedText(35, y, 190, 20, $"Ruleset: {basedef.Title}", LabelColor32, BlackColor32); + y += 20; + + for (var i = 0; i < ruleset.Flavors.Count; ++i, y += 18) + AddBorderedText(35, y, 190, 20, $" + {ruleset.Flavors[i].Title}", LabelColor32, BlackColor32); + + y += 4; + + if (changes > 0) + { + AddBorderedText(35, y, 190, 20, "Modifications:", LabelColor32, BlackColor32); + y += 20; + + for (var i = 0; i < opts.Length; ++i) + if (defs[i] != opts[i]) + { + var name = ruleset.Layout.FindByIndex(i); + + if (name != null) // sanity + { + AddImage(35, y, opts[i] ? 0xD3 : 0xD2); + AddBorderedText(60, y, 165, 22, name, LabelColor32, BlackColor32); + } + + y += 22; + } + } + else + { + AddBorderedText(35, y, 190, 20, "Modifications: None", LabelColor32, BlackColor32); + y += 20; + } + + y += 8; + AddImageTiled(32, y - 1, 264, 1, 9107); + AddImageTiled(42, y + 1, 264, 1, 9157); + y += 8; + + AddRadio(24, y, 9727, 9730, true, 1); + AddBorderedText(60, y + 5, 250, 20, "Yes, I will join them.", LabelColor32, BlackColor32); + y += 35; + + AddRadio(24, y, 9727, 9730, false, 2); + AddBorderedText(60, y + 5, 250, 20, "No, I do not wish to fight.", LabelColor32, BlackColor32); + y += 35; + + AddRadio(24, y, 9727, 9730, false, 3); + AddBorderedText(60, y + 5, 270, 20, "No, most certainly not. Do not ask again.", LabelColor32, BlackColor32); + y += 35; + + y -= 3; + AddButton(314, y, 247, 248, 1); + + Timer.DelayCall(TimeSpan.FromSeconds(15.0), AutoReject); + } + + public string Center(string text) => $"
{text}
"; + + public string Color(string text, int color) => $"{text}"; + + private void AddBorderedText(int x, int y, int width, int height, string text, int color, int borderColor) + { + AddColoredText(x - 1, y - 1, width, height, text, borderColor); + AddColoredText(x - 1, y + 1, width, height, text, borderColor); + AddColoredText(x + 1, y - 1, width, height, text, borderColor); + AddColoredText(x + 1, y + 1, width, height, text, borderColor); + AddColoredText(x, y, width, height, text, color); + } + + private void AddColoredText(int x, int y, int width, int height, string text, int color) + { + if (color == 0) + AddHtml(x, y, width, height, text); + else + AddHtml(x, y, width, height, Color(text, color)); + } + + public void AutoReject() + { + if (!m_Active) + return; + + m_Active = false; + + m_Requested.CloseGump(); + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + + if (m_Registrar != null) + { + m_Registrar.PrivateOverheadMessage( + MessageType.Regular, + 0x22, + false, + $"{m_Requested.Name} seems unresponsive.", + m_From.NetState + ); + + m_Registrar.PrivateOverheadMessage( + MessageType.Regular, + 0x22, + false, + $"You have declined the partnership with {m_From.Name}.", + m_Requested.NetState + ); + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var from = m_From; + var mob = m_Requested; + + if (info.ButtonID != 1 || !m_Active) + return; + + m_Active = false; + + if (info.IsSwitched(1)) + { + if (!(mob is PlayerMobile pm)) + return; + + if (AcceptDuelGump.IsIgnored(mob, from) || mob.Blessed) + { + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + + m_Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x22, + false, + "They ignore your invitation.", + from.NetState + ); + } + else if (pm.DuelContext != null) + { + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + + m_Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x22, + false, + "They are already assigned to another duel.", + from.NetState + ); + } + else if (m_Players.Contains(mob)) + { + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + + m_Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x22, + false, + "You have already named them as a team member.", + from.NetState + ); + } + else if (m_Tournament.HasParticipant(mob)) + { + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + + m_Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x22, + false, + "They have already entered this tournament.", + from.NetState + ); + } + else if (m_Players.Count >= m_Tournament.PlayersPerParticipant) + { + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + + m_Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x22, + false, + "Your team is full.", + from.NetState + ); + } + else + { + m_Players.Add(mob); + + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + + if (m_Registrar != null) + { + m_Registrar.PrivateOverheadMessage( + MessageType.Regular, + 0x59, + false, + $"{mob.Name} has accepted your offer of partnership.", + from.NetState + ); + + m_Registrar.PrivateOverheadMessage( + MessageType.Regular, + 0x59, + false, + $"You have accepted the partnership with {from.Name}.", + mob.NetState + ); + } + } + } + else + { + if (info.IsSwitched(3)) + AcceptDuelGump.BeginIgnore(m_Requested, m_From); + + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + + if (m_Registrar != null) + { + m_Registrar.PrivateOverheadMessage( + MessageType.Regular, + 0x22, + false, + $"{mob.Name} has declined your offer of partnership.", + from.NetState + ); + + m_Registrar.PrivateOverheadMessage( + MessageType.Regular, + 0x22, + false, + $"You have declined the partnership with {from.Name}.", + mob.NetState + ); + } + } + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Gumps/ArenaGump.cs b/Projects/UOContent/Engines/ConPVP/Gumps/ArenaGump.cs index 98d2f42ee..0f2e2260e 100644 --- a/Projects/UOContent/Engines/ConPVP/Gumps/ArenaGump.cs +++ b/Projects/UOContent/Engines/ConPVP/Gumps/ArenaGump.cs @@ -1,276 +1,278 @@ -using System.Collections.Generic; -using System.Text; -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.ConPVP -{ - public class ArenasMoongate : Item - { - [Constructible] - public ArenasMoongate() : base(0x1FD4) - { - Movable = false; - Light = LightType.Circle300; - } - - public ArenasMoongate(Serial serial) : base(serial) - { - } - - public override string DefaultName => "arena moongate"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - Light = LightType.Circle300; - } - - public bool UseGate(Mobile from) - { - if (DuelContext.CheckCombat(from)) - { - from.SendMessage(0x22, "You have recently been in combat with another player and cannot use this moongate."); - return false; - } - - if (from.Spell != null) - { - from.SendLocalizedMessage(1049616); // You are too busy to do that at the moment. - return false; - } - - from.CloseGump(); - from.SendGump(new ArenaGump(from, this)); - - if (!from.Hidden || from.AccessLevel == AccessLevel.Player) - Effects.PlaySound(from.Location, from.Map, 0x20E); - - return true; - } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(GetWorldLocation(), 1)) - UseGate(from); - else - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that - } - - public override bool OnMoveOver(Mobile m) => !m.Player || UseGate(m); - } - - public class ArenaGump : Gump - { - private readonly List m_Arenas; - - private int m_ColumnX = 12; - private readonly Mobile m_From; - private readonly ArenasMoongate m_Gate; - - public ArenaGump(Mobile from, ArenasMoongate gate) : base(50, 50) - { - m_From = from; - m_Gate = gate; - m_Arenas = Arena.Arenas; - - AddPage(0); - - int height = 12 + 20 + m_Arenas.Count * 31 + 24 + 12; - - AddBackground(0, 0, 499 + 40, height, 0x2436); - - List list = m_Arenas; - - for (int i = 1; i < list.Count; i += 2) - AddImageTiled(12, 32 + i * 31, 475 + 40, 30, 0x2430); - - AddAlphaRegion(10, 10, 479 + 40, height - 20); - - AddColumnHeader(35, null); - AddColumnHeader(115, "Arena"); - AddColumnHeader(325, "Participants"); - AddColumnHeader(40, "Obs"); - - AddButton(499 + 40 - 12 - 63 - 4 - 63, height - 12 - 24, 247, 248, 1); - AddButton(499 + 40 - 12 - 63, height - 12 - 24, 241, 242, 2); - - for (int i = 0; i < list.Count; ++i) - { - Arena ar = list[i]; - - int x = 12; - int y = 32 + i * 31; - - int color = ar.Players.Count > 0 ? 0xCCFFCC : 0xCCCCCC; - - AddRadio(x + 3, y + 1, 9727, 9730, false, i); - x += 35; - - AddBorderedText(x + 5, y + 5, 115 - 5, ar.Name ?? "(no name)", color, 0); - x += 115; - - StringBuilder sb = new StringBuilder(); - - if (ar.Players.Count > 0) - { - Ladder ladder = Ladder.Instance; - - if (ladder == null) - continue; - - LadderEntry p1 = null, p2 = null, p3 = null, p4 = null; - - for (int j = 0; j < ar.Players.Count; ++j) - { - Mobile mob = ar.Players[j]; - LadderEntry c = ladder.Find(mob); - - if (p1 == null || c.Index < p1.Index) - { - p4 = p3; - p3 = p2; - p2 = p1; - p1 = c; - } - else if (p2 == null || c.Index < p2.Index) - { - p4 = p3; - p3 = p2; - p2 = c; - } - else if (p3 == null || c.Index < p3.Index) - { - p4 = p3; - p3 = c; - } - else if (p4 == null || c.Index < p4.Index) - { - p4 = c; - } - } - - Append(sb, p1); - Append(sb, p2); - Append(sb, p3); - Append(sb, p4); - - if (ar.Players.Count > 4) - sb.Append(", ..."); - } - else - { - sb.Append("Empty"); - } - - AddBorderedText(x + 5, y + 5, 325 - 5, sb.ToString(), color, 0); - x += 325; - - AddBorderedText(x, y + 5, 40, Center(ar.Spectators.ToString()), color, 0); - } - } - - private void Append(StringBuilder sb, LadderEntry le) - { - if (le == null) - return; - - if (sb.Length > 0) - sb.Append(", "); - - sb.Append(le.Mobile.Name); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID != 1) - return; - - int[] switches = info.Switches; - - if (switches.Length == 0) - return; - - int opt = switches[0]; - - if (opt < 0 || opt >= m_Arenas.Count) - return; - - Arena arena = m_Arenas[opt]; - - if (!m_From.InRange(m_Gate.GetWorldLocation(), 1) || m_From.Map != m_Gate.Map) - { - m_From.SendLocalizedMessage(1019002); // You are too far away to use the gate. - } - else if (DuelContext.CheckCombat(m_From)) - { - m_From.SendMessage(0x22, - "You have recently been in combat with another player and cannot use this moongate."); - } - else if (m_From.Spell != null) - { - m_From.SendLocalizedMessage(1049616); // You are too busy to do that at the moment. - } - else if (m_From.Map == arena.Facet && arena.Zone.Contains(m_From)) - { - m_From.SendLocalizedMessage(1019003); // You are already there. - } - else - { - BaseCreature.TeleportPets(m_From, arena.GateIn, arena.Facet); - - m_From.Combatant = null; - m_From.Warmode = false; - m_From.Hidden = true; - - m_From.MoveToWorld(arena.GateIn, arena.Facet); - - Effects.PlaySound(arena.GateIn, arena.Facet, 0x1FE); - } - } - - public string Center(string text) => $"
{text}
"; - - public string Color(string text, int color) => $"{text}"; - - private void AddBorderedText(int x, int y, int width, string text, int color, int borderColor) - { - /*AddColoredText( x - 1, y, width, text, borderColor ); - AddColoredText( x + 1, y, width, text, borderColor ); - AddColoredText( x, y - 1, width, text, borderColor ); - AddColoredText( x, y + 1, width, text, borderColor );*/ - /*AddColoredText( x - 1, y - 1, width, text, borderColor ); - AddColoredText( x + 1, y + 1, width, text, borderColor );*/ - AddColoredText(x, y, width, text, color); - } - - private void AddColoredText(int x, int y, int width, string text, int color) - { - if (color == 0) - AddHtml(x, y, width, 20, text); - else - AddHtml(x, y, width, 20, Color(text, color)); - } - - private void AddColumnHeader(int width, string name) - { - AddBackground(m_ColumnX, 12, width, 20, 0x242C); - AddImageTiled(m_ColumnX + 2, 14, width - 4, 16, 0x2430); - - if (name != null) - AddBorderedText(m_ColumnX, 13, width, Center(name), 0xFFFFFF, 0); - - m_ColumnX += width; - } - } -} +using System.Collections.Generic; +using System.Text; +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.ConPVP +{ + public class ArenasMoongate : Item + { + [Constructible] + public ArenasMoongate() : base(0x1FD4) + { + Movable = false; + Light = LightType.Circle300; + } + + public ArenasMoongate(Serial serial) : base(serial) + { + } + + public override string DefaultName => "arena moongate"; + + 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(); + Light = LightType.Circle300; + } + + public bool UseGate(Mobile from) + { + if (DuelContext.CheckCombat(from)) + { + from.SendMessage(0x22, "You have recently been in combat with another player and cannot use this moongate."); + return false; + } + + if (from.Spell != null) + { + from.SendLocalizedMessage(1049616); // You are too busy to do that at the moment. + return false; + } + + from.CloseGump(); + from.SendGump(new ArenaGump(from, this)); + + if (!from.Hidden || from.AccessLevel == AccessLevel.Player) + Effects.PlaySound(from.Location, from.Map, 0x20E); + + return true; + } + + public override void OnDoubleClick(Mobile from) + { + if (from.InRange(GetWorldLocation(), 1)) + UseGate(from); + else + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that + } + + public override bool OnMoveOver(Mobile m) => !m.Player || UseGate(m); + } + + public class ArenaGump : Gump + { + private readonly List m_Arenas; + private readonly Mobile m_From; + private readonly ArenasMoongate m_Gate; + + private int m_ColumnX = 12; + + public ArenaGump(Mobile from, ArenasMoongate gate) : base(50, 50) + { + m_From = from; + m_Gate = gate; + m_Arenas = Arena.Arenas; + + AddPage(0); + + var height = 12 + 20 + m_Arenas.Count * 31 + 24 + 12; + + AddBackground(0, 0, 499 + 40, height, 0x2436); + + var list = m_Arenas; + + for (var i = 1; i < list.Count; i += 2) + AddImageTiled(12, 32 + i * 31, 475 + 40, 30, 0x2430); + + AddAlphaRegion(10, 10, 479 + 40, height - 20); + + AddColumnHeader(35, null); + AddColumnHeader(115, "Arena"); + AddColumnHeader(325, "Participants"); + AddColumnHeader(40, "Obs"); + + AddButton(499 + 40 - 12 - 63 - 4 - 63, height - 12 - 24, 247, 248, 1); + AddButton(499 + 40 - 12 - 63, height - 12 - 24, 241, 242, 2); + + for (var i = 0; i < list.Count; ++i) + { + var ar = list[i]; + + var x = 12; + var y = 32 + i * 31; + + var color = ar.Players.Count > 0 ? 0xCCFFCC : 0xCCCCCC; + + AddRadio(x + 3, y + 1, 9727, 9730, false, i); + x += 35; + + AddBorderedText(x + 5, y + 5, 115 - 5, ar.Name ?? "(no name)", color, 0); + x += 115; + + var sb = new StringBuilder(); + + if (ar.Players.Count > 0) + { + var ladder = Ladder.Instance; + + if (ladder == null) + continue; + + LadderEntry p1 = null, p2 = null, p3 = null, p4 = null; + + for (var j = 0; j < ar.Players.Count; ++j) + { + var mob = ar.Players[j]; + var c = ladder.Find(mob); + + if (p1 == null || c.Index < p1.Index) + { + p4 = p3; + p3 = p2; + p2 = p1; + p1 = c; + } + else if (p2 == null || c.Index < p2.Index) + { + p4 = p3; + p3 = p2; + p2 = c; + } + else if (p3 == null || c.Index < p3.Index) + { + p4 = p3; + p3 = c; + } + else if (p4 == null || c.Index < p4.Index) + { + p4 = c; + } + } + + Append(sb, p1); + Append(sb, p2); + Append(sb, p3); + Append(sb, p4); + + if (ar.Players.Count > 4) + sb.Append(", ..."); + } + else + { + sb.Append("Empty"); + } + + AddBorderedText(x + 5, y + 5, 325 - 5, sb.ToString(), color, 0); + x += 325; + + AddBorderedText(x, y + 5, 40, Center(ar.Spectators.ToString()), color, 0); + } + } + + private void Append(StringBuilder sb, LadderEntry le) + { + if (le == null) + return; + + if (sb.Length > 0) + sb.Append(", "); + + sb.Append(le.Mobile.Name); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID != 1) + return; + + var switches = info.Switches; + + if (switches.Length == 0) + return; + + var opt = switches[0]; + + if (opt < 0 || opt >= m_Arenas.Count) + return; + + var arena = m_Arenas[opt]; + + if (!m_From.InRange(m_Gate.GetWorldLocation(), 1) || m_From.Map != m_Gate.Map) + { + m_From.SendLocalizedMessage(1019002); // You are too far away to use the gate. + } + else if (DuelContext.CheckCombat(m_From)) + { + m_From.SendMessage( + 0x22, + "You have recently been in combat with another player and cannot use this moongate." + ); + } + else if (m_From.Spell != null) + { + m_From.SendLocalizedMessage(1049616); // You are too busy to do that at the moment. + } + else if (m_From.Map == arena.Facet && arena.Zone.Contains(m_From)) + { + m_From.SendLocalizedMessage(1019003); // You are already there. + } + else + { + BaseCreature.TeleportPets(m_From, arena.GateIn, arena.Facet); + + m_From.Combatant = null; + m_From.Warmode = false; + m_From.Hidden = true; + + m_From.MoveToWorld(arena.GateIn, arena.Facet); + + Effects.PlaySound(arena.GateIn, arena.Facet, 0x1FE); + } + } + + public string Center(string text) => $"
{text}
"; + + public string Color(string text, int color) => $"{text}"; + + private void AddBorderedText(int x, int y, int width, string text, int color, int borderColor) + { + /*AddColoredText( x - 1, y, width, text, borderColor ); + AddColoredText( x + 1, y, width, text, borderColor ); + AddColoredText( x, y - 1, width, text, borderColor ); + AddColoredText( x, y + 1, width, text, borderColor );*/ + /*AddColoredText( x - 1, y - 1, width, text, borderColor ); + AddColoredText( x + 1, y + 1, width, text, borderColor );*/ + AddColoredText(x, y, width, text, color); + } + + private void AddColoredText(int x, int y, int width, string text, int color) + { + if (color == 0) + AddHtml(x, y, width, 20, text); + else + AddHtml(x, y, width, 20, Color(text, color)); + } + + private void AddColumnHeader(int width, string name) + { + AddBackground(m_ColumnX, 12, width, 20, 0x242C); + AddImageTiled(m_ColumnX + 2, 14, width - 4, 16, 0x2430); + + if (name != null) + AddBorderedText(m_ColumnX, 13, width, Center(name), 0xFFFFFF, 0); + + m_ColumnX += width; + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Gumps/BeginGump.cs b/Projects/UOContent/Engines/ConPVP/Gumps/BeginGump.cs index 2414e770e..0eda38ff0 100644 --- a/Projects/UOContent/Engines/ConPVP/Gumps/BeginGump.cs +++ b/Projects/UOContent/Engines/ConPVP/Gumps/BeginGump.cs @@ -1,66 +1,96 @@ -using Server.Gumps; - -namespace Server.Engines.ConPVP -{ - public class BeginGump : Gump - { - private const int LabelColor32 = 0xFFFFFF; - private const int BlackColor32 = 0x000008; - - public BeginGump(int count) : base(50, 50) - { - AddPage(0); - - const int offset = 50; - - AddBackground(1, 1, 398, 202 - offset, 3600); - - AddImageTiled(16, 15, 369, 173 - offset, 3604); - AddAlphaRegion(16, 15, 369, 173 - offset); - - AddImage(215, -43, 0xEE40); - - AddHtml(22 - 1, 22, 294, 20, Color(Center("Duel Countdown"), BlackColor32)); - AddHtml(22 + 1, 22, 294, 20, Color(Center("Duel Countdown"), BlackColor32)); - AddHtml(22, 22 - 1, 294, 20, Color(Center("Duel Countdown"), BlackColor32)); - AddHtml(22, 22 + 1, 294, 20, Color(Center("Duel Countdown"), BlackColor32)); - AddHtml(22, 22, 294, 20, Color(Center("Duel Countdown"), LabelColor32)); - - AddHtml(22 - 1, 50, 294, 80, - Color( - "The arranged duel is about to begin. During this countdown period you may not cast spells and you may not move. This message will close automatically when the period ends.", - BlackColor32)); - AddHtml(22 + 1, 50, 294, 80, - Color( - "The arranged duel is about to begin. During this countdown period you may not cast spells and you may not move. This message will close automatically when the period ends.", - BlackColor32)); - AddHtml(22, 50 - 1, 294, 80, - Color( - "The arranged duel is about to begin. During this countdown period you may not cast spells and you may not move. This message will close automatically when the period ends.", - BlackColor32)); - AddHtml(22, 50 + 1, 294, 80, - Color( - "The arranged duel is about to begin. During this countdown period you may not cast spells and you may not move. This message will close automatically when the period ends.", - BlackColor32)); - AddHtml(22, 50, 294, 80, - Color( - "The arranged duel is about to begin. During this countdown period you may not cast spells and you may not move. This message will close automatically when the period ends.", - 0xFFCC66)); - - /*AddImageTiled( 32, 128, 264, 1, 9107 ); - AddImageTiled( 42, 130, 264, 1, 9157 ); - - AddHtml( 60-1, 140, 250, 20, Color( String.Format( "Duel will begin in {0} second{1}.", count, count==1?"":"s", BlackColor32 ), BlackColor32 ), false, false ); - AddHtml( 60+1, 140, 250, 20, Color( String.Format( "Duel will begin in {0} second{1}.", count, count==1?"":"s", BlackColor32 ), BlackColor32 ), false, false ); - AddHtml( 60, 140-1, 250, 20, Color( String.Format( "Duel will begin in {0} second{1}.", count, count==1?"":"s", BlackColor32 ), BlackColor32 ), false, false ); - AddHtml( 60, 140+1, 250, 20, Color( String.Format( "Duel will begin in {0} second{1}.", count, count==1?"":"s", BlackColor32 ), BlackColor32 ), false, false ); - AddHtml( 60, 140, 250, 20, Color( String.Format( "Duel will begin in {0} second{1}.", count, count==1?"":"s", 0x66AACC ), 0x66AACC ), false, false );*/ - - AddButton(314 - 50, 157 - offset, 247, 248, 1); - } - - public string Center(string text) => $"
{text}
"; - - public string Color(string text, int color) => $"{text}"; - } -} +using Server.Gumps; + +namespace Server.Engines.ConPVP +{ + public class BeginGump : Gump + { + private const int LabelColor32 = 0xFFFFFF; + private const int BlackColor32 = 0x000008; + + public BeginGump(int count) : base(50, 50) + { + AddPage(0); + + const int offset = 50; + + AddBackground(1, 1, 398, 202 - offset, 3600); + + AddImageTiled(16, 15, 369, 173 - offset, 3604); + AddAlphaRegion(16, 15, 369, 173 - offset); + + AddImage(215, -43, 0xEE40); + + AddHtml(22 - 1, 22, 294, 20, Color(Center("Duel Countdown"), BlackColor32)); + AddHtml(22 + 1, 22, 294, 20, Color(Center("Duel Countdown"), BlackColor32)); + AddHtml(22, 22 - 1, 294, 20, Color(Center("Duel Countdown"), BlackColor32)); + AddHtml(22, 22 + 1, 294, 20, Color(Center("Duel Countdown"), BlackColor32)); + AddHtml(22, 22, 294, 20, Color(Center("Duel Countdown"), LabelColor32)); + + AddHtml( + 22 - 1, + 50, + 294, + 80, + Color( + "The arranged duel is about to begin. During this countdown period you may not cast spells and you may not move. This message will close automatically when the period ends.", + BlackColor32 + ) + ); + AddHtml( + 22 + 1, + 50, + 294, + 80, + Color( + "The arranged duel is about to begin. During this countdown period you may not cast spells and you may not move. This message will close automatically when the period ends.", + BlackColor32 + ) + ); + AddHtml( + 22, + 50 - 1, + 294, + 80, + Color( + "The arranged duel is about to begin. During this countdown period you may not cast spells and you may not move. This message will close automatically when the period ends.", + BlackColor32 + ) + ); + AddHtml( + 22, + 50 + 1, + 294, + 80, + Color( + "The arranged duel is about to begin. During this countdown period you may not cast spells and you may not move. This message will close automatically when the period ends.", + BlackColor32 + ) + ); + AddHtml( + 22, + 50, + 294, + 80, + Color( + "The arranged duel is about to begin. During this countdown period you may not cast spells and you may not move. This message will close automatically when the period ends.", + 0xFFCC66 + ) + ); + + /*AddImageTiled( 32, 128, 264, 1, 9107 ); + AddImageTiled( 42, 130, 264, 1, 9157 ); + + AddHtml( 60-1, 140, 250, 20, Color( String.Format( "Duel will begin in {0} second{1}.", count, count==1?"":"s", BlackColor32 ), BlackColor32 ), false, false ); + AddHtml( 60+1, 140, 250, 20, Color( String.Format( "Duel will begin in {0} second{1}.", count, count==1?"":"s", BlackColor32 ), BlackColor32 ), false, false ); + AddHtml( 60, 140-1, 250, 20, Color( String.Format( "Duel will begin in {0} second{1}.", count, count==1?"":"s", BlackColor32 ), BlackColor32 ), false, false ); + AddHtml( 60, 140+1, 250, 20, Color( String.Format( "Duel will begin in {0} second{1}.", count, count==1?"":"s", BlackColor32 ), BlackColor32 ), false, false ); + AddHtml( 60, 140, 250, 20, Color( String.Format( "Duel will begin in {0} second{1}.", count, count==1?"":"s", 0x66AACC ), 0x66AACC ), false, false );*/ + + AddButton(314 - 50, 157 - offset, 247, 248, 1); + } + + public string Center(string text) => $"
{text}
"; + + public string Color(string text, int color) => $"{text}"; + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Gumps/ConfirmSignupGump.cs b/Projects/UOContent/Engines/ConPVP/Gumps/ConfirmSignupGump.cs index 62b501c14..2bce20b93 100644 --- a/Projects/UOContent/Engines/ConPVP/Gumps/ConfirmSignupGump.cs +++ b/Projects/UOContent/Engines/ConPVP/Gumps/ConfirmSignupGump.cs @@ -1,530 +1,636 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Text; -using Server.Factions; -using Server.Gumps; -using Server.Mobiles; -using Server.Network; -using Server.Targeting; - -namespace Server.Engines.ConPVP -{ - public class ConfirmSignupGump : Gump - { - private const int BlackColor32 = 0x000008; - private const int LabelColor32 = 0xFFFFFF; - private readonly Mobile m_From; - private readonly List m_Players; - private readonly Mobile m_Registrar; - private readonly Tournament m_Tournament; - - public ConfirmSignupGump(Mobile from, Mobile registrar, Tournament tourney, List players) : base(50, 50) - { - m_From = from; - m_Registrar = registrar; - m_Tournament = tourney; - m_Players = players; - - m_From.CloseGump(); - m_From.CloseGump(); - m_From.CloseGump(); - m_From.CloseGump(); - - Ruleset ruleset = tourney.Ruleset; - Ruleset basedef = ruleset.Base; - - int height = 185 + 60 + 12; - - int changes = 0; - - BitArray defs; - - if (ruleset.Flavors.Count > 0) - { - defs = new BitArray(basedef.Options); - - for (int i = 0; i < ruleset.Flavors.Count; ++i) - defs.Or(ruleset.Flavors[i].Options); - - height += ruleset.Flavors.Count * 18; - } - else - { - defs = basedef.Options; - } - - BitArray opts = ruleset.Options; - - for (int i = 0; i < opts.Length; ++i) - if (defs[i] != opts[i]) - ++changes; - - height += changes * 22; - - height += 10 + 22 + 25 + 25; - - if (tourney.PlayersPerParticipant > 1) - height += 36 + tourney.PlayersPerParticipant * 20; - - Closable = false; - - AddPage(0); - - // AddBackground( 0, 0, 400, 220, 9150 ); - AddBackground(1, 1, 398, height, 3600); - // AddBackground( 16, 15, 369, 189, 9100 ); - - AddImageTiled(16, 15, 369, height - 29, 3604); - AddAlphaRegion(16, 15, 369, height - 29); - - AddImage(215, -43, 0xEE40); - // AddImage( 330, 141, 0x8BA ); - - StringBuilder sb = new StringBuilder(); - - if (tourney.TourneyType == TourneyType.FreeForAll) - { - sb.Append("FFA"); - } - else if (tourney.TourneyType == TourneyType.RandomTeam) - { - sb.Append(tourney.ParticipantsPerMatch); - sb.Append("-Team"); - } - else if (tourney.TourneyType == TourneyType.Faction) - { - sb.Append(tourney.ParticipantsPerMatch); - sb.Append("-Team Faction"); - } - else if (tourney.TourneyType == TourneyType.RedVsBlue) - { - sb.Append("Red v Blue"); - } - else - { - for (int i = 0; i < tourney.ParticipantsPerMatch; ++i) - { - if (sb.Length > 0) - sb.Append('v'); - - sb.Append(tourney.PlayersPerParticipant); - } - } - - if (tourney.EventController != null) - sb.Append(' ').Append(tourney.EventController.Title); - - sb.Append(" Tournament Signup"); - - AddBorderedText(22, 22, 294, 20, Center(sb.ToString()), LabelColor32, BlackColor32); - AddBorderedText(22, 50, 294, 40, "You have requested to join the tournament. Do you accept the rules?", 0xB0C868, - BlackColor32); - - AddImageTiled(32, 88, 264, 1, 9107); - AddImageTiled(42, 90, 264, 1, 9157); - - int y = 100; - - var groupText = tourney.GroupType switch - { - GroupingType.HighVsLow => "High vs Low", - GroupingType.Nearest => "Closest opponent", - GroupingType.Random => "Random", - _ => null - }; - - AddBorderedText(35, y, 190, 20, $"Grouping: {groupText}", LabelColor32, BlackColor32); - y += 20; - - var tieText = tourney.TieType switch - { - TieType.Random => "Random", - TieType.Highest => "Highest advances", - TieType.Lowest => "Lowest advances", - TieType.FullAdvancement => tourney.ParticipantsPerMatch == 2 ? "Both advance" : "Everyone advances", - TieType.FullElimination => tourney.ParticipantsPerMatch == 2 ? "Both eliminated" : "Everyone eliminated", - _ => null - }; - - AddBorderedText(35, y, 190, 20, $"Tiebreaker: {tieText}", LabelColor32, BlackColor32); - y += 20; - - string sdText = "Off"; - - if (tourney.SuddenDeath > TimeSpan.Zero) - { - sdText = $"{(int)tourney.SuddenDeath.TotalMinutes}:{tourney.SuddenDeath.Seconds:D2}"; - - if (tourney.SuddenDeathRounds > 0) - sdText = $"{sdText} (first {tourney.SuddenDeathRounds} rounds)"; - else - sdText = $"{sdText} (all rounds)"; - } - - AddBorderedText(35, y, 240, 20, $"Sudden Death: {sdText}", LabelColor32, BlackColor32); - y += 20; - - y += 6; - AddImageTiled(32, y - 1, 264, 1, 9107); - AddImageTiled(42, y + 1, 264, 1, 9157); - y += 6; - - AddBorderedText(35, y, 190, 20, $"Ruleset: {basedef.Title}", LabelColor32, BlackColor32); - y += 20; - - for (int i = 0; i < ruleset.Flavors.Count; ++i, y += 18) - AddBorderedText(35, y, 190, 20, $" + {ruleset.Flavors[i].Title}", LabelColor32, BlackColor32); - - y += 4; - - if (changes > 0) - { - AddBorderedText(35, y, 190, 20, "Modifications:", LabelColor32, BlackColor32); - y += 20; - - for (int i = 0; i < opts.Length; ++i) - if (defs[i] != opts[i]) - { - string name = ruleset.Layout.FindByIndex(i); - - if (name != null) // sanity - { - AddImage(35, y, opts[i] ? 0xD3 : 0xD2); - AddBorderedText(60, y, 165, 22, name, LabelColor32, BlackColor32); - } - - y += 22; - } - } - else - { - AddBorderedText(35, y, 190, 20, "Modifications: None", LabelColor32, BlackColor32); - y += 20; - } - - if (tourney.PlayersPerParticipant > 1) - { - y += 8; - AddImageTiled(32, y - 1, 264, 1, 9107); - AddImageTiled(42, y + 1, 264, 1, 9157); - y += 8; - - AddBorderedText(35, y, 190, 20, "Your Team", LabelColor32, BlackColor32); - y += 20; - - for (int i = 0; i < players.Count; ++i, y += 20) - { - if (i == 0) - AddImage(35, y, 0xD2); - else - AddGoldenButton(35, y, 1 + i); - - AddBorderedText(60, y, 200, 20, players[i].Name, LabelColor32, BlackColor32); - } - - for (int i = players.Count; i < tourney.PlayersPerParticipant; ++i, y += 20) - { - if (i == 0) - AddImage(35, y, 0xD2); - else - AddGoldenButton(35, y, 1 + i); - - AddBorderedText(60, y, 200, 20, "(Empty)", LabelColor32, BlackColor32); - } - } - - y += 8; - AddImageTiled(32, y - 1, 264, 1, 9107); - AddImageTiled(42, y + 1, 264, 1, 9157); - y += 8; - - AddRadio(24, y, 9727, 9730, true, 1); - AddBorderedText(60, y + 5, 250, 20, "Yes, I wish to join the tournament.", LabelColor32, BlackColor32); - y += 35; - - AddRadio(24, y, 9727, 9730, false, 2); - AddBorderedText(60, y + 5, 250, 20, "No, I do not wish to join.", LabelColor32, BlackColor32); - y += 35; - - y -= 3; - AddButton(314, y, 247, 248, 1); - } - - public string Center(string text) => $"
{text}
"; - - public string Color(string text, int color) => $"{text}"; - - private void AddBorderedText(int x, int y, int width, int height, string text, int color, int borderColor) - { - AddColoredText(x - 1, y - 1, width, height, text, borderColor); - AddColoredText(x - 1, y + 1, width, height, text, borderColor); - AddColoredText(x + 1, y - 1, width, height, text, borderColor); - AddColoredText(x + 1, y + 1, width, height, text, borderColor); - AddColoredText(x, y, width, height, text, color); - } - - private void AddColoredText(int x, int y, int width, int height, string text, int color) - { - if (color == 0) - AddHtml(x, y, width, height, text); - else - AddHtml(x, y, width, height, Color(text, color)); - } - - public void AddGoldenButton(int x, int y, int bid) - { - AddButton(x, y, 0xD2, 0xD2, bid); - AddButton(x + 3, y + 3, 0xD8, 0xD8, bid); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 1 && info.IsSwitched(1)) - { - Tournament tourney = m_Tournament; - Mobile from = m_From; - - switch (tourney.Stage) - { - case TournamentStage.Fighting: - { - if (m_Registrar != null) - { - if (m_Tournament.HasParticipant(from)) - m_Registrar.PrivateOverheadMessage(MessageType.Regular, - 0x35, false, "Excuse me? You are already signed up.", from.NetState); - else - m_Registrar.PrivateOverheadMessage(MessageType.Regular, - 0x22, false, "The tournament has already begun. You are too late to signup now.", - from.NetState); - } - - break; - } - case TournamentStage.Inactive: - { - m_Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x35, false, "The tournament is closed.", from.NetState); - - break; - } - case TournamentStage.Signup: - { - if (m_Players.Count != tourney.PlayersPerParticipant) - { - m_Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x35, false, "You have not yet chosen your team.", from.NetState); - - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - break; - } - - Ladder ladder = Ladder.Instance; - - for (int i = 0; i < m_Players.Count; ++i) - { - Mobile mob = m_Players[i]; - - LadderEntry entry = ladder?.Find(mob); - - if (entry != null && Ladder.GetLevel(entry.Experience) < tourney.LevelRequirement) - { - if (m_Registrar != null) - { - if (mob == from) - m_Registrar.PrivateOverheadMessage(MessageType.Regular, - 0x35, false, "You have not yet proven yourself a worthy dueler.", from.NetState); - else - m_Registrar.PrivateOverheadMessage(MessageType.Regular, - 0x35, false, $"{mob.Name} has not yet proven themselves a worthy dueler.", - from.NetState); - } - - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - return; - } - - if (tourney.IsFactionRestricted && Faction.Find(mob) == null) - { - m_Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x35, false, "Only those who have declared their faction allegiance may participate.", - from.NetState); - - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - return; - } - - if (tourney.HasParticipant(mob)) - { - if (m_Registrar != null) - { - if (mob == from) - m_Registrar.PrivateOverheadMessage(MessageType.Regular, - 0x35, false, "You have already entered this tournament.", from.NetState); - else - m_Registrar.PrivateOverheadMessage(MessageType.Regular, - 0x35, false, $"{mob.Name} has already entered this tournament.", from.NetState); - } - - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - return; - } - - if (mob is PlayerMobile mobile && mobile.DuelContext != null) - { - if (mob == from) - m_Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x35, false, - "You are already assigned to a duel. You must yield it before joining this tournament.", - from.NetState); - else - m_Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x35, false, - $"{mobile.Name} is already assigned to a duel. They must yield it before joining this tournament.", - from.NetState); - - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - return; - } - } - - if (m_Registrar != null) - { - string fmt; - - if (tourney.PlayersPerParticipant == 1) - fmt = - "As you say m'{0}. I've written your name to the bracket. The tournament will begin {1}."; - else if (tourney.PlayersPerParticipant == 2) - fmt = - "As you wish m'{0}. The tournament will begin {1}, but first you must name your partner."; - else - fmt = "As you wish m'{0}. The tournament will begin {1}, but first you must name your team."; - - string timeUntil; - int minutesUntil = (int)Math.Round((tourney.SignupStart + tourney.SignupPeriod - DateTime.UtcNow) - .TotalMinutes); - - if (minutesUntil == 0) - timeUntil = "momentarily"; - else - timeUntil = $"in {minutesUntil} minute{(minutesUntil == 1 ? "" : "s")}"; - - m_Registrar.PrivateOverheadMessage(MessageType.Regular, - 0x35, false, string.Format(fmt, from.Female ? "Lady" : "Lord", timeUntil), from.NetState); - } - - TourneyParticipant part = new TourneyParticipant(from); - part.Players.Clear(); - part.Players.AddRange(m_Players); - - tourney.Participants.Add(part); - - break; - } - } - } - else if (info.ButtonID > 1) - { - int index = info.ButtonID - 1; - - if (index > 0 && index < m_Players.Count) - { - m_Players.RemoveAt(index); - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - } - else if (m_Players.Count < m_Tournament.PlayersPerParticipant) - { - m_From.BeginTarget(12, false, TargetFlags.None, AddPlayer_OnTarget); - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - } - } - } - - private void AddPlayer_OnTarget(Mobile from, object obj) - { - if (!(obj is Mobile mob) || mob == from) - { - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - - m_Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x22, false, "Excuse me?", from.NetState); - } - else if (!mob.Player) - { - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - - if (mob.Body.IsHuman) - mob.SayTo(from, 1005443); // Nay, I would rather stay here and watch a nail rust. - else - mob.SayTo(from, 1005444); // The creature ignores your offer. - } - else if (AcceptDuelGump.IsIgnored(mob, from) || mob.Blessed) - { - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - - m_Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x22, false, "They ignore your invitation.", from.NetState); - } - else - { - if (!(mob is PlayerMobile pm)) - return; - - if (pm.DuelContext != null) - { - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - - m_Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x22, false, "They are already assigned to another duel.", from.NetState); - } - else if (mob.HasGump()) - { - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - - m_Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x22, false, "They have already been offered a partnership.", from.NetState); - } - else if (mob.HasGump()) - { - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - - m_Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x22, false, "They are already trying to join this tournament.", from.NetState); - } - else if (m_Players.Contains(mob)) - { - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - - m_Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x22, false, "You have already named them as a team member.", from.NetState); - } - else if (m_Tournament.HasParticipant(mob)) - { - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - - m_Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x22, false, "They have already entered this tournament.", from.NetState); - } - else if (m_Players.Count >= m_Tournament.PlayersPerParticipant) - { - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - - m_Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x22, false, "Your team is full.", from.NetState); - } - else - { - m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); - mob.SendGump(new AcceptTeamGump(from, mob, m_Tournament, m_Registrar, m_Players)); - - m_Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x59, false, - $"As you command m'{(from.Female ? "Lady" : "Lord")}. I've given your offer to {mob.Name}.", - from.NetState); - } - } - } - } -} +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using Server.Factions; +using Server.Gumps; +using Server.Mobiles; +using Server.Network; +using Server.Targeting; + +namespace Server.Engines.ConPVP +{ + public class ConfirmSignupGump : Gump + { + private const int BlackColor32 = 0x000008; + private const int LabelColor32 = 0xFFFFFF; + private readonly Mobile m_From; + private readonly List m_Players; + private readonly Mobile m_Registrar; + private readonly Tournament m_Tournament; + + public ConfirmSignupGump(Mobile from, Mobile registrar, Tournament tourney, List players) : base(50, 50) + { + m_From = from; + m_Registrar = registrar; + m_Tournament = tourney; + m_Players = players; + + m_From.CloseGump(); + m_From.CloseGump(); + m_From.CloseGump(); + m_From.CloseGump(); + + var ruleset = tourney.Ruleset; + var basedef = ruleset.Base; + + var height = 185 + 60 + 12; + + var changes = 0; + + BitArray defs; + + if (ruleset.Flavors.Count > 0) + { + defs = new BitArray(basedef.Options); + + for (var i = 0; i < ruleset.Flavors.Count; ++i) + defs.Or(ruleset.Flavors[i].Options); + + height += ruleset.Flavors.Count * 18; + } + else + { + defs = basedef.Options; + } + + var opts = ruleset.Options; + + for (var i = 0; i < opts.Length; ++i) + if (defs[i] != opts[i]) + ++changes; + + height += changes * 22; + + height += 10 + 22 + 25 + 25; + + if (tourney.PlayersPerParticipant > 1) + height += 36 + tourney.PlayersPerParticipant * 20; + + Closable = false; + + AddPage(0); + + // AddBackground( 0, 0, 400, 220, 9150 ); + AddBackground(1, 1, 398, height, 3600); + // AddBackground( 16, 15, 369, 189, 9100 ); + + AddImageTiled(16, 15, 369, height - 29, 3604); + AddAlphaRegion(16, 15, 369, height - 29); + + AddImage(215, -43, 0xEE40); + // AddImage( 330, 141, 0x8BA ); + + var sb = new StringBuilder(); + + if (tourney.TourneyType == TourneyType.FreeForAll) + { + sb.Append("FFA"); + } + else if (tourney.TourneyType == TourneyType.RandomTeam) + { + sb.Append(tourney.ParticipantsPerMatch); + sb.Append("-Team"); + } + else if (tourney.TourneyType == TourneyType.Faction) + { + sb.Append(tourney.ParticipantsPerMatch); + sb.Append("-Team Faction"); + } + else if (tourney.TourneyType == TourneyType.RedVsBlue) + { + sb.Append("Red v Blue"); + } + else + { + for (var i = 0; i < tourney.ParticipantsPerMatch; ++i) + { + if (sb.Length > 0) + sb.Append('v'); + + sb.Append(tourney.PlayersPerParticipant); + } + } + + if (tourney.EventController != null) + sb.Append(' ').Append(tourney.EventController.Title); + + sb.Append(" Tournament Signup"); + + AddBorderedText(22, 22, 294, 20, Center(sb.ToString()), LabelColor32, BlackColor32); + AddBorderedText( + 22, + 50, + 294, + 40, + "You have requested to join the tournament. Do you accept the rules?", + 0xB0C868, + BlackColor32 + ); + + AddImageTiled(32, 88, 264, 1, 9107); + AddImageTiled(42, 90, 264, 1, 9157); + + var y = 100; + + var groupText = tourney.GroupType switch + { + GroupingType.HighVsLow => "High vs Low", + GroupingType.Nearest => "Closest opponent", + GroupingType.Random => "Random", + _ => null + }; + + AddBorderedText(35, y, 190, 20, $"Grouping: {groupText}", LabelColor32, BlackColor32); + y += 20; + + var tieText = tourney.TieType switch + { + TieType.Random => "Random", + TieType.Highest => "Highest advances", + TieType.Lowest => "Lowest advances", + TieType.FullAdvancement => tourney.ParticipantsPerMatch == 2 ? "Both advance" : "Everyone advances", + TieType.FullElimination => tourney.ParticipantsPerMatch == 2 ? "Both eliminated" : "Everyone eliminated", + _ => null + }; + + AddBorderedText(35, y, 190, 20, $"Tiebreaker: {tieText}", LabelColor32, BlackColor32); + y += 20; + + var sdText = "Off"; + + if (tourney.SuddenDeath > TimeSpan.Zero) + { + sdText = $"{(int)tourney.SuddenDeath.TotalMinutes}:{tourney.SuddenDeath.Seconds:D2}"; + + if (tourney.SuddenDeathRounds > 0) + sdText = $"{sdText} (first {tourney.SuddenDeathRounds} rounds)"; + else + sdText = $"{sdText} (all rounds)"; + } + + AddBorderedText(35, y, 240, 20, $"Sudden Death: {sdText}", LabelColor32, BlackColor32); + y += 20; + + y += 6; + AddImageTiled(32, y - 1, 264, 1, 9107); + AddImageTiled(42, y + 1, 264, 1, 9157); + y += 6; + + AddBorderedText(35, y, 190, 20, $"Ruleset: {basedef.Title}", LabelColor32, BlackColor32); + y += 20; + + for (var i = 0; i < ruleset.Flavors.Count; ++i, y += 18) + AddBorderedText(35, y, 190, 20, $" + {ruleset.Flavors[i].Title}", LabelColor32, BlackColor32); + + y += 4; + + if (changes > 0) + { + AddBorderedText(35, y, 190, 20, "Modifications:", LabelColor32, BlackColor32); + y += 20; + + for (var i = 0; i < opts.Length; ++i) + if (defs[i] != opts[i]) + { + var name = ruleset.Layout.FindByIndex(i); + + if (name != null) // sanity + { + AddImage(35, y, opts[i] ? 0xD3 : 0xD2); + AddBorderedText(60, y, 165, 22, name, LabelColor32, BlackColor32); + } + + y += 22; + } + } + else + { + AddBorderedText(35, y, 190, 20, "Modifications: None", LabelColor32, BlackColor32); + y += 20; + } + + if (tourney.PlayersPerParticipant > 1) + { + y += 8; + AddImageTiled(32, y - 1, 264, 1, 9107); + AddImageTiled(42, y + 1, 264, 1, 9157); + y += 8; + + AddBorderedText(35, y, 190, 20, "Your Team", LabelColor32, BlackColor32); + y += 20; + + for (var i = 0; i < players.Count; ++i, y += 20) + { + if (i == 0) + AddImage(35, y, 0xD2); + else + AddGoldenButton(35, y, 1 + i); + + AddBorderedText(60, y, 200, 20, players[i].Name, LabelColor32, BlackColor32); + } + + for (var i = players.Count; i < tourney.PlayersPerParticipant; ++i, y += 20) + { + if (i == 0) + AddImage(35, y, 0xD2); + else + AddGoldenButton(35, y, 1 + i); + + AddBorderedText(60, y, 200, 20, "(Empty)", LabelColor32, BlackColor32); + } + } + + y += 8; + AddImageTiled(32, y - 1, 264, 1, 9107); + AddImageTiled(42, y + 1, 264, 1, 9157); + y += 8; + + AddRadio(24, y, 9727, 9730, true, 1); + AddBorderedText(60, y + 5, 250, 20, "Yes, I wish to join the tournament.", LabelColor32, BlackColor32); + y += 35; + + AddRadio(24, y, 9727, 9730, false, 2); + AddBorderedText(60, y + 5, 250, 20, "No, I do not wish to join.", LabelColor32, BlackColor32); + y += 35; + + y -= 3; + AddButton(314, y, 247, 248, 1); + } + + public string Center(string text) => $"
{text}
"; + + public string Color(string text, int color) => $"{text}"; + + private void AddBorderedText(int x, int y, int width, int height, string text, int color, int borderColor) + { + AddColoredText(x - 1, y - 1, width, height, text, borderColor); + AddColoredText(x - 1, y + 1, width, height, text, borderColor); + AddColoredText(x + 1, y - 1, width, height, text, borderColor); + AddColoredText(x + 1, y + 1, width, height, text, borderColor); + AddColoredText(x, y, width, height, text, color); + } + + private void AddColoredText(int x, int y, int width, int height, string text, int color) + { + if (color == 0) + AddHtml(x, y, width, height, text); + else + AddHtml(x, y, width, height, Color(text, color)); + } + + public void AddGoldenButton(int x, int y, int bid) + { + AddButton(x, y, 0xD2, 0xD2, bid); + AddButton(x + 3, y + 3, 0xD8, 0xD8, bid); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 1 && info.IsSwitched(1)) + { + var tourney = m_Tournament; + var from = m_From; + + switch (tourney.Stage) + { + case TournamentStage.Fighting: + { + if (m_Registrar != null) + { + if (m_Tournament.HasParticipant(from)) + m_Registrar.PrivateOverheadMessage( + MessageType.Regular, + 0x35, + false, + "Excuse me? You are already signed up.", + from.NetState + ); + else + m_Registrar.PrivateOverheadMessage( + MessageType.Regular, + 0x22, + false, + "The tournament has already begun. You are too late to signup now.", + from.NetState + ); + } + + break; + } + case TournamentStage.Inactive: + { + m_Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x35, + false, + "The tournament is closed.", + from.NetState + ); + + break; + } + case TournamentStage.Signup: + { + if (m_Players.Count != tourney.PlayersPerParticipant) + { + m_Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x35, + false, + "You have not yet chosen your team.", + from.NetState + ); + + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + break; + } + + var ladder = Ladder.Instance; + + for (var i = 0; i < m_Players.Count; ++i) + { + var mob = m_Players[i]; + + var entry = ladder?.Find(mob); + + if (entry != null && Ladder.GetLevel(entry.Experience) < tourney.LevelRequirement) + { + if (m_Registrar != null) + { + if (mob == from) + m_Registrar.PrivateOverheadMessage( + MessageType.Regular, + 0x35, + false, + "You have not yet proven yourself a worthy dueler.", + from.NetState + ); + else + m_Registrar.PrivateOverheadMessage( + MessageType.Regular, + 0x35, + false, + $"{mob.Name} has not yet proven themselves a worthy dueler.", + from.NetState + ); + } + + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + return; + } + + if (tourney.IsFactionRestricted && Faction.Find(mob) == null) + { + m_Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x35, + false, + "Only those who have declared their faction allegiance may participate.", + from.NetState + ); + + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + return; + } + + if (tourney.HasParticipant(mob)) + { + if (m_Registrar != null) + { + if (mob == from) + m_Registrar.PrivateOverheadMessage( + MessageType.Regular, + 0x35, + false, + "You have already entered this tournament.", + from.NetState + ); + else + m_Registrar.PrivateOverheadMessage( + MessageType.Regular, + 0x35, + false, + $"{mob.Name} has already entered this tournament.", + from.NetState + ); + } + + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + return; + } + + if (mob is PlayerMobile mobile && mobile.DuelContext != null) + { + if (mob == from) + m_Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x35, + false, + "You are already assigned to a duel. You must yield it before joining this tournament.", + from.NetState + ); + else + m_Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x35, + false, + $"{mobile.Name} is already assigned to a duel. They must yield it before joining this tournament.", + from.NetState + ); + + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + return; + } + } + + if (m_Registrar != null) + { + string fmt; + + if (tourney.PlayersPerParticipant == 1) + fmt = + "As you say m'{0}. I've written your name to the bracket. The tournament will begin {1}."; + else if (tourney.PlayersPerParticipant == 2) + fmt = + "As you wish m'{0}. The tournament will begin {1}, but first you must name your partner."; + else + fmt = + "As you wish m'{0}. The tournament will begin {1}, but first you must name your team."; + + string timeUntil; + var minutesUntil = (int)Math.Round( + (tourney.SignupStart + tourney.SignupPeriod - DateTime.UtcNow) + .TotalMinutes + ); + + if (minutesUntil == 0) + timeUntil = "momentarily"; + else + timeUntil = $"in {minutesUntil} minute{(minutesUntil == 1 ? "" : "s")}"; + + m_Registrar.PrivateOverheadMessage( + MessageType.Regular, + 0x35, + false, + string.Format(fmt, from.Female ? "Lady" : "Lord", timeUntil), + from.NetState + ); + } + + var part = new TourneyParticipant(from); + part.Players.Clear(); + part.Players.AddRange(m_Players); + + tourney.Participants.Add(part); + + break; + } + } + } + else if (info.ButtonID > 1) + { + var index = info.ButtonID - 1; + + if (index > 0 && index < m_Players.Count) + { + m_Players.RemoveAt(index); + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + } + else if (m_Players.Count < m_Tournament.PlayersPerParticipant) + { + m_From.BeginTarget(12, false, TargetFlags.None, AddPlayer_OnTarget); + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + } + } + } + + private void AddPlayer_OnTarget(Mobile from, object obj) + { + if (!(obj is Mobile mob) || mob == from) + { + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + + m_Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x22, + false, + "Excuse me?", + from.NetState + ); + } + else if (!mob.Player) + { + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + + if (mob.Body.IsHuman) + mob.SayTo(from, 1005443); // Nay, I would rather stay here and watch a nail rust. + else + mob.SayTo(from, 1005444); // The creature ignores your offer. + } + else if (AcceptDuelGump.IsIgnored(mob, from) || mob.Blessed) + { + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + + m_Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x22, + false, + "They ignore your invitation.", + from.NetState + ); + } + else + { + if (!(mob is PlayerMobile pm)) + return; + + if (pm.DuelContext != null) + { + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + + m_Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x22, + false, + "They are already assigned to another duel.", + from.NetState + ); + } + else if (mob.HasGump()) + { + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + + m_Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x22, + false, + "They have already been offered a partnership.", + from.NetState + ); + } + else if (mob.HasGump()) + { + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + + m_Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x22, + false, + "They are already trying to join this tournament.", + from.NetState + ); + } + else if (m_Players.Contains(mob)) + { + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + + m_Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x22, + false, + "You have already named them as a team member.", + from.NetState + ); + } + else if (m_Tournament.HasParticipant(mob)) + { + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + + m_Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x22, + false, + "They have already entered this tournament.", + from.NetState + ); + } + else if (m_Players.Count >= m_Tournament.PlayersPerParticipant) + { + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + + m_Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x22, + false, + "Your team is full.", + from.NetState + ); + } + else + { + m_From.SendGump(new ConfirmSignupGump(m_From, m_Registrar, m_Tournament, m_Players)); + mob.SendGump(new AcceptTeamGump(from, mob, m_Tournament, m_Registrar, m_Players)); + + m_Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x59, + false, + $"As you command m'{(from.Female ? "Lady" : "Lord")}. I've given your offer to {mob.Name}.", + from.NetState + ); + } + } + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Gumps/DuelContextGump.cs b/Projects/UOContent/Engines/ConPVP/Gumps/DuelContextGump.cs index f68005345..820f7acee 100644 --- a/Projects/UOContent/Engines/ConPVP/Gumps/DuelContextGump.cs +++ b/Projects/UOContent/Engines/ConPVP/Gumps/DuelContextGump.cs @@ -1,136 +1,147 @@ -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.ConPVP -{ - public class DuelContextGump : Gump - { - public DuelContextGump(Mobile from, DuelContext context) : base(50, 50) - { - From = from; - Context = context; - - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - - int count = context.Participants.Count; - - if (count < 3) - count = 3; - - int height = 35 + 10 + 22 + 30 + 22 + 22 + 2 + count * 22 + 2 + 30; - - AddPage(0); - - AddBackground(0, 0, 300, height, 9250); - AddBackground(10, 10, 280, height - 20, 0xDAC); - - AddHtml(35, 25, 230, 20, Center("Duel Setup")); - - int x = 35; - int y = 47; - - AddGoldenButtonLabeled(x, y, 1, "Rules"); - y += 22; - AddGoldenButtonLabeled(x, y, 2, "Start"); - y += 22; - AddGoldenButtonLabeled(x, y, 3, "Add Participant"); - y += 30; - - AddHtml(35, y, 230, 20, Center("Participants")); - y += 22; - - for (int i = 0; i < context.Participants.Count; ++i) - { - Participant p = context.Participants[i]; - - AddGoldenButtonLabeled(x, y, 4 + i, - string.Format(p.Count == 1 ? "Player {0}: {3}" : "Team {0}: {1}/{2}: {3}", 1 + i, p.FilledSlots, p.Count, - p.NameList)); - y += 22; - } - } - - public Mobile From { get; } - - public DuelContext Context { get; } - - public string Center(string text) => $"
{text}
"; - - public void AddGoldenButton(int x, int y, int bid) - { - AddButton(x, y, 0xD2, 0xD2, bid); - AddButton(x + 3, y + 3, 0xD8, 0xD8, bid); - } - - public void AddGoldenButtonLabeled(int x, int y, int bid, string text) - { - AddGoldenButton(x, y, bid); - AddHtml(x + 25, y, 200, 20, text); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (!Context.Registered) - return; - - int index = info.ButtonID; - - switch (index) - { - case -1: // CloseGump - { - break; - } - case 0: // closed - { - Context.Unregister(); - break; - } - case 1: // Rules - { - // m_From.SendGump( new RulesetGump( m_From, m_Context.Ruleset, m_Context.Ruleset.Layout, m_Context ) ); - From.SendGump(new PickRulesetGump(From, Context, Context.Ruleset)); - break; - } - case 2: // Start - { - if (Context.CheckFull()) - { - Context.CloseAllGumps(); - Context.SendReadyUpGump(); - // m_Context.SendReadyGump(); - } - else - { - From.SendMessage("You cannot start the duel before all participating players have been assigned."); - From.SendGump(new DuelContextGump(From, Context)); - } - - break; - } - case 3: // New Participant - { - if (Context.Participants.Count < 10) - Context.Participants.Add(new Participant(Context, 1)); - else - From.SendMessage("The number of participating parties may not be increased further."); - - From.SendGump(new DuelContextGump(From, Context)); - - break; - } - default: // Participant - { - index -= 4; - - if (index >= 0 && index < Context.Participants.Count) - From.SendGump(new ParticipantGump(From, Context, Context.Participants[index])); - - break; - } - } - } - } -} +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.ConPVP +{ + public class DuelContextGump : Gump + { + public DuelContextGump(Mobile from, DuelContext context) : base(50, 50) + { + From = from; + Context = context; + + from.CloseGump(); + from.CloseGump(); + from.CloseGump(); + + var count = context.Participants.Count; + + if (count < 3) + count = 3; + + var height = 35 + 10 + 22 + 30 + 22 + 22 + 2 + count * 22 + 2 + 30; + + AddPage(0); + + AddBackground(0, 0, 300, height, 9250); + AddBackground(10, 10, 280, height - 20, 0xDAC); + + AddHtml(35, 25, 230, 20, Center("Duel Setup")); + + var x = 35; + var y = 47; + + AddGoldenButtonLabeled(x, y, 1, "Rules"); + y += 22; + AddGoldenButtonLabeled(x, y, 2, "Start"); + y += 22; + AddGoldenButtonLabeled(x, y, 3, "Add Participant"); + y += 30; + + AddHtml(35, y, 230, 20, Center("Participants")); + y += 22; + + for (var i = 0; i < context.Participants.Count; ++i) + { + var p = context.Participants[i]; + + AddGoldenButtonLabeled( + x, + y, + 4 + i, + string.Format( + p.Count == 1 ? "Player {0}: {3}" : "Team {0}: {1}/{2}: {3}", + 1 + i, + p.FilledSlots, + p.Count, + p.NameList + ) + ); + y += 22; + } + } + + public Mobile From { get; } + + public DuelContext Context { get; } + + public string Center(string text) => $"
{text}
"; + + public void AddGoldenButton(int x, int y, int bid) + { + AddButton(x, y, 0xD2, 0xD2, bid); + AddButton(x + 3, y + 3, 0xD8, 0xD8, bid); + } + + public void AddGoldenButtonLabeled(int x, int y, int bid, string text) + { + AddGoldenButton(x, y, bid); + AddHtml(x + 25, y, 200, 20, text); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (!Context.Registered) + return; + + var index = info.ButtonID; + + switch (index) + { + case -1: // CloseGump + { + break; + } + case 0: // closed + { + Context.Unregister(); + break; + } + case 1: // Rules + { + // m_From.SendGump( new RulesetGump( m_From, m_Context.Ruleset, m_Context.Ruleset.Layout, m_Context ) ); + From.SendGump(new PickRulesetGump(From, Context, Context.Ruleset)); + break; + } + case 2: // Start + { + if (Context.CheckFull()) + { + Context.CloseAllGumps(); + Context.SendReadyUpGump(); + // m_Context.SendReadyGump(); + } + else + { + From.SendMessage( + "You cannot start the duel before all participating players have been assigned." + ); + From.SendGump(new DuelContextGump(From, Context)); + } + + break; + } + case 3: // New Participant + { + if (Context.Participants.Count < 10) + Context.Participants.Add(new Participant(Context, 1)); + else + From.SendMessage("The number of participating parties may not be increased further."); + + From.SendGump(new DuelContextGump(From, Context)); + + break; + } + default: // Participant + { + index -= 4; + + if (index >= 0 && index < Context.Participants.Count) + From.SendGump(new ParticipantGump(From, Context, Context.Participants[index])); + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Gumps/LadderGump.cs b/Projects/UOContent/Engines/ConPVP/Gumps/LadderGump.cs index c691d272d..8676caee9 100644 --- a/Projects/UOContent/Engines/ConPVP/Gumps/LadderGump.cs +++ b/Projects/UOContent/Engines/ConPVP/Gumps/LadderGump.cs @@ -1,239 +1,246 @@ -using System; -using System.Collections.Generic; -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.ConPVP -{ - public class LadderItem : Item - { - [Constructible] - public LadderItem() : base(0x117F) => Movable = false; - - public LadderItem(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public LadderController Ladder { get; set; } - - public override string DefaultName => "1v1 leaderboard"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - - writer.Write(Ladder); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - Ladder = reader.ReadItem(); - break; - } - } - } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(GetWorldLocation(), 2)) - { - Ladder ladder = ConPVP.Ladder.Instance ?? Ladder.Ladder; - - if (ladder != null) - { - from.CloseGump(); - from.SendGump(new LadderGump(ladder)); - } - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that - } - } - } - - public class LadderGump : Gump - { - private int m_ColumnX = 12; - private readonly Ladder m_Ladder; - - private readonly List m_List; - private readonly int m_Page; - - public LadderGump(Ladder ladder, int page = 0) : base(50, 50) - { - m_Ladder = ladder; - m_Page = page; - - AddPage(0); - - m_List = new List(ladder.Entries); - - int lc = Math.Min(m_List.Count, 150); - - int start = page * 15; - int end = start + 15; - - if (end > lc) - end = lc; - - int ct = end - start; - - int height = 12 + 20 + ct * 20 + 23 + 12; - - AddBackground(0, 0, 499, height, 0x2436); - - for (int i = start + 1; i < end; i += 2) - AddImageTiled(12, 32 + (i - start) * 20, 475, 20, 0x2430); - - AddAlphaRegion(10, 10, 479, height - 20); - - if (page > 0) - AddButton(446, height - 12 - 2 - 16, 0x15E3, 0x15E7, 1); - else - AddImage(446, height - 12 - 2 - 16, 0x2626); - - if ((page + 1) * 15 < lc) - AddButton(466, height - 12 - 2 - 16, 0x15E1, 0x15E5, 2); - else - AddImage(466, height - 12 - 2 - 16, 0x2622); - - AddHtml(16, height - 12 - 2 - 18, 400, 20, - Color(string.Format("Top {3} of {0:N0} duelists, page {1} of {2}", m_List.Count, page + 1, (lc + 14) / 15, lc), - 0xFFC000)); - - AddColumnHeader(75, "Rank"); - AddColumnHeader(115, "Level"); - AddColumnHeader(50, "Guild"); - AddColumnHeader(115, "Name"); - AddColumnHeader(60, "Wins"); - AddColumnHeader(60, "Losses"); - - for (int i = start; i < end && i < lc; ++i) - { - LadderEntry entry = m_List[i]; - - int y = 32 + (i - start) * 20; - int x = 12; - - AddBorderedText(x, y, 75, Center(Rank(i + 1)), 0xFFFFFF, 0); - x += 75; - - /*AddImage( 20, y + 5, 0x2616, 0x96C ); - AddImage( 22, y + 5, 0x2616, 0x96C ); - AddImage( 20, y + 7, 0x2616, 0x96C ); - AddImage( 22, y + 7, 0x2616, 0x96C ); - - AddImage( 21, y + 6, 0x2616, 0x454 );*/ - - AddImage(x + 3, y + 4, 0x805); - - int xp = entry.Experience; - int level = Ladder.GetLevel(xp); - - Ladder.GetLevelInfo(level, out int xpBase, out int xpAdvance); - - int width; - - int xpOffset = xp - xpBase; - - if (xpOffset >= xpAdvance) - width = 109; // level 50 - else - width = (109 * xpOffset + xpAdvance / 2) / (xpAdvance - 1); - - // AddImageTiled( 21, y + 6, width, 8, 0x2617 ); - AddImageTiled(x + 3, y + 4, width, 11, 0x806); - AddBorderedText(x, y, 115, Center(level.ToString()), 0xFFFFFF, 0); - x += 115; - - Mobile mob = entry.Mobile; - - if (mob.Guild != null) - AddBorderedText(x, y, 50, Center(mob.Guild.Abbreviation), 0xFFFFFF, 0); - - x += 50; - - AddBorderedText(x + 5, y, 115 - 5, mob.Name, 0xFFFFFF, 0); - x += 115; - - AddBorderedText(x, y, 60, Center(entry.Wins.ToString()), 0xFFFFFF, 0); - x += 60; - - AddBorderedText(x, y, 60, Center(entry.Losses.ToString()), 0xFFFFFF, 0); - x += 60; - - // AddBorderedText( 292 + 15, y, 115 - 30, String.Format( "{0}
/
{1}
", entry.Wins, entry.Losses ), 0xFFC000, 0 ); - } - } - - public static string Rank(int num) - { - string numStr = num.ToString("N0"); - - if (num % 100 > 10 && num % 100 < 20) - return $"{numStr}th"; - - return (num % 10) switch - { - 1 => $"{numStr}st", - 2 => $"{numStr}nd", - 3 => $"{numStr}rd", - _ => $"{numStr}th" - }; - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - Mobile from = sender.Mobile; - - if (info.ButtonID == 1 && m_Page > 0) - from.SendGump(new LadderGump(m_Ladder, m_Page - 1)); - else if (info.ButtonID == 2 && (m_Page + 1) * 15 < Math.Min(m_List.Count, 150)) - from.SendGump(new LadderGump(m_Ladder, m_Page + 1)); - } - - public string Center(string text) => $"
{text}
"; - - public string Color(string text, int color) => $"{text}"; - - private void AddBorderedText(int x, int y, int width, string text, int color, int borderColor) - { - /*AddColoredText( x - 1, y, width, text, borderColor ); - AddColoredText( x + 1, y, width, text, borderColor ); - AddColoredText( x, y - 1, width, text, borderColor ); - AddColoredText( x, y + 1, width, text, borderColor );*/ - /*AddColoredText( x - 1, y - 1, width, text, borderColor ); - AddColoredText( x + 1, y + 1, width, text, borderColor );*/ - AddColoredText(x, y, width, text, color); - } - - private void AddColoredText(int x, int y, int width, string text, int color) - { - if (color == 0) - AddHtml(x, y, width, 20, text); - else - AddHtml(x, y, width, 20, Color(text, color)); - } - - private void AddColumnHeader(int width, string name) - { - AddBackground(m_ColumnX, 12, width, 20, 0x242C); - AddImageTiled(m_ColumnX + 2, 14, width - 4, 16, 0x2430); - AddBorderedText(m_ColumnX, 13, width, Center(name), 0xFFFFFF, 0); - - m_ColumnX += width; - } - } -} +using System; +using System.Collections.Generic; +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.ConPVP +{ + public class LadderItem : Item + { + [Constructible] + public LadderItem() : base(0x117F) => Movable = false; + + public LadderItem(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public LadderController Ladder { get; set; } + + public override string DefaultName => "1v1 leaderboard"; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + + writer.Write(Ladder); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + Ladder = reader.ReadItem(); + break; + } + } + } + + public override void OnDoubleClick(Mobile from) + { + if (from.InRange(GetWorldLocation(), 2)) + { + var ladder = ConPVP.Ladder.Instance ?? Ladder.Ladder; + + if (ladder != null) + { + from.CloseGump(); + from.SendGump(new LadderGump(ladder)); + } + } + else + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that + } + } + } + + public class LadderGump : Gump + { + private readonly Ladder m_Ladder; + + private readonly List m_List; + private readonly int m_Page; + private int m_ColumnX = 12; + + public LadderGump(Ladder ladder, int page = 0) : base(50, 50) + { + m_Ladder = ladder; + m_Page = page; + + AddPage(0); + + m_List = new List(ladder.Entries); + + var lc = Math.Min(m_List.Count, 150); + + var start = page * 15; + var end = start + 15; + + if (end > lc) + end = lc; + + var ct = end - start; + + var height = 12 + 20 + ct * 20 + 23 + 12; + + AddBackground(0, 0, 499, height, 0x2436); + + for (var i = start + 1; i < end; i += 2) + AddImageTiled(12, 32 + (i - start) * 20, 475, 20, 0x2430); + + AddAlphaRegion(10, 10, 479, height - 20); + + if (page > 0) + AddButton(446, height - 12 - 2 - 16, 0x15E3, 0x15E7, 1); + else + AddImage(446, height - 12 - 2 - 16, 0x2626); + + if ((page + 1) * 15 < lc) + AddButton(466, height - 12 - 2 - 16, 0x15E1, 0x15E5, 2); + else + AddImage(466, height - 12 - 2 - 16, 0x2622); + + AddHtml( + 16, + height - 12 - 2 - 18, + 400, + 20, + Color( + string.Format("Top {3} of {0:N0} duelists, page {1} of {2}", m_List.Count, page + 1, (lc + 14) / 15, lc), + 0xFFC000 + ) + ); + + AddColumnHeader(75, "Rank"); + AddColumnHeader(115, "Level"); + AddColumnHeader(50, "Guild"); + AddColumnHeader(115, "Name"); + AddColumnHeader(60, "Wins"); + AddColumnHeader(60, "Losses"); + + for (var i = start; i < end && i < lc; ++i) + { + var entry = m_List[i]; + + var y = 32 + (i - start) * 20; + var x = 12; + + AddBorderedText(x, y, 75, Center(Rank(i + 1)), 0xFFFFFF, 0); + x += 75; + + /*AddImage( 20, y + 5, 0x2616, 0x96C ); + AddImage( 22, y + 5, 0x2616, 0x96C ); + AddImage( 20, y + 7, 0x2616, 0x96C ); + AddImage( 22, y + 7, 0x2616, 0x96C ); + + AddImage( 21, y + 6, 0x2616, 0x454 );*/ + + AddImage(x + 3, y + 4, 0x805); + + var xp = entry.Experience; + var level = Ladder.GetLevel(xp); + + Ladder.GetLevelInfo(level, out var xpBase, out var xpAdvance); + + int width; + + var xpOffset = xp - xpBase; + + if (xpOffset >= xpAdvance) + width = 109; // level 50 + else + width = (109 * xpOffset + xpAdvance / 2) / (xpAdvance - 1); + + // AddImageTiled( 21, y + 6, width, 8, 0x2617 ); + AddImageTiled(x + 3, y + 4, width, 11, 0x806); + AddBorderedText(x, y, 115, Center(level.ToString()), 0xFFFFFF, 0); + x += 115; + + var mob = entry.Mobile; + + if (mob.Guild != null) + AddBorderedText(x, y, 50, Center(mob.Guild.Abbreviation), 0xFFFFFF, 0); + + x += 50; + + AddBorderedText(x + 5, y, 115 - 5, mob.Name, 0xFFFFFF, 0); + x += 115; + + AddBorderedText(x, y, 60, Center(entry.Wins.ToString()), 0xFFFFFF, 0); + x += 60; + + AddBorderedText(x, y, 60, Center(entry.Losses.ToString()), 0xFFFFFF, 0); + x += 60; + + // AddBorderedText( 292 + 15, y, 115 - 30, String.Format( "{0}
/
{1}
", entry.Wins, entry.Losses ), 0xFFC000, 0 ); + } + } + + public static string Rank(int num) + { + var numStr = num.ToString("N0"); + + if (num % 100 > 10 && num % 100 < 20) + return $"{numStr}th"; + + return (num % 10) switch + { + 1 => $"{numStr}st", + 2 => $"{numStr}nd", + 3 => $"{numStr}rd", + _ => $"{numStr}th" + }; + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var from = sender.Mobile; + + if (info.ButtonID == 1 && m_Page > 0) + from.SendGump(new LadderGump(m_Ladder, m_Page - 1)); + else if (info.ButtonID == 2 && (m_Page + 1) * 15 < Math.Min(m_List.Count, 150)) + from.SendGump(new LadderGump(m_Ladder, m_Page + 1)); + } + + public string Center(string text) => $"
{text}
"; + + public string Color(string text, int color) => $"{text}"; + + private void AddBorderedText(int x, int y, int width, string text, int color, int borderColor) + { + /*AddColoredText( x - 1, y, width, text, borderColor ); + AddColoredText( x + 1, y, width, text, borderColor ); + AddColoredText( x, y - 1, width, text, borderColor ); + AddColoredText( x, y + 1, width, text, borderColor );*/ + /*AddColoredText( x - 1, y - 1, width, text, borderColor ); + AddColoredText( x + 1, y + 1, width, text, borderColor );*/ + AddColoredText(x, y, width, text, color); + } + + private void AddColoredText(int x, int y, int width, string text, int color) + { + if (color == 0) + AddHtml(x, y, width, 20, text); + else + AddHtml(x, y, width, 20, Color(text, color)); + } + + private void AddColumnHeader(int width, string name) + { + AddBackground(m_ColumnX, 12, width, 20, 0x242C); + AddImageTiled(m_ColumnX + 2, 14, width - 4, 16, 0x2430); + AddBorderedText(m_ColumnX, 13, width, Center(name), 0xFFFFFF, 0); + + m_ColumnX += width; + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Gumps/ParticipantGump.cs b/Projects/UOContent/Engines/ConPVP/Gumps/ParticipantGump.cs index 6f8fc9008..efa9660fa 100644 --- a/Projects/UOContent/Engines/ConPVP/Gumps/ParticipantGump.cs +++ b/Projects/UOContent/Engines/ConPVP/Gumps/ParticipantGump.cs @@ -1,250 +1,255 @@ -using Server.Gumps; -using Server.Mobiles; -using Server.Network; -using Server.Targeting; - -namespace Server.Engines.ConPVP -{ - public class ParticipantGump : Gump - { - public ParticipantGump(Mobile from, DuelContext context, Participant p) : base(50, 50) - { - From = from; - Context = context; - Participant = p; - - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - - int count = p.Players.Length; - - if (count < 4) - count = 4; - - AddPage(0); - - int height = 35 + 10 + 22 + 22 + 30 + 22 + 2 + count * 22 + 2 + 30; - - AddBackground(0, 0, 300, height, 9250); - AddBackground(10, 10, 280, height - 20, 0xDAC); - - AddButton(240, 25, 0xFB1, 0xFB3, 3); - - // AddButton( 223, 54, 0x265A, 0x265A, 4, ); - - AddHtml(35, 25, 230, 20, Center("Participant Setup")); - - int x = 35; - int y = 47; - - AddHtml(x, y, 200, 20, $"Team Size: {p.Players.Length}"); - y += 22; - - AddGoldenButtonLabeled(x + 20, y, 1, "Increase"); - y += 22; - AddGoldenButtonLabeled(x + 20, y, 2, "Decrease"); - y += 30; - - AddHtml(35, y, 230, 20, Center("Players")); - y += 22; - - for (int i = 0; i < p.Players.Length; ++i) - { - DuelPlayer pl = p.Players[i]; - - AddGoldenButtonLabeled(x, y, 5 + i, $"{1 + i}: {(pl == null ? "Empty" : pl.Mobile.Name)}"); - y += 22; - } - } - - public Mobile From { get; } - - public DuelContext Context { get; } - - public Participant Participant { get; } - - public string Center(string text) => $"
{text}
"; - - public void AddGoldenButton(int x, int y, int bid) - { - AddButton(x, y, 0xD2, 0xD2, bid); - AddButton(x + 3, y + 3, 0xD8, 0xD8, bid); - } - - public void AddGoldenButtonLabeled(int x, int y, int bid, string text) - { - AddGoldenButton(x, y, bid); - AddHtml(x + 25, y, 200, 20, text); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (!Context.Registered) - return; - - int bid = info.ButtonID; - - if (bid == 0) - { - From.SendGump(new DuelContextGump(From, Context)); - } - else if (bid == 1) - { - if (Participant.Count < 8) - Participant.Resize(Participant.Count + 1); - else - From.SendMessage("You may not raise the team size any further."); - - From.SendGump(new ParticipantGump(From, Context, Participant)); - } - else if (bid == 2) - { - if (Participant.Count > 1 && Participant.Count > Participant.FilledSlots) - Participant.Resize(Participant.Count - 1); - else - From.SendMessage("You may not lower the team size any further."); - - From.SendGump(new ParticipantGump(From, Context, Participant)); - } - else if (bid == 3) - { - if (Participant.FilledSlots > 0) - { - From.SendMessage("There is at least one currently active player. You must remove them first."); - From.SendGump(new ParticipantGump(From, Context, Participant)); - } - else if (Context.Participants.Count > 2) - { - /*Container cont = m_Participant.Stakes; - - if (cont != null) - cont.Delete();*/ - - Context.Participants.Remove(Participant); - From.SendGump(new DuelContextGump(From, Context)); - } - else - { - From.SendMessage("Duels must have at least two participating parties."); - From.SendGump(new ParticipantGump(From, Context, Participant)); - } - } - /*else if (bid == 4) - { - m_From.SendGump( new ParticipantGump( m_From, m_Context, m_Participant ) ); - - Container cont = m_Participant.Stakes; - - if (cont != null && !cont.Deleted) - { - cont.DisplayTo( m_From ); - - Item[] checks = cont.FindItemsByType( typeof( BankCheck ) ); - - int gold = cont.TotalGold; - - for ( int i = 0; i < checks.Length; ++i ) - gold += ((BankCheck)checks[i]).Worth; - - m_From.SendMessage( "This container has {0} item{1} and {2} stone{3}. In gold or check form there is a total of {4:D}gp.", cont.TotalItems, cont.TotalItems==1?"":"s", cont.TotalWeight, cont.TotalWeight==1?"":"s", gold ); - } - }*/ - else - { - bid -= 5; - - if (bid >= 0 && bid < Participant.Players.Length) - { - if (Participant.Players[bid] == null) - { - From.Target = new ParticipantTarget(Context, Participant, bid); - From.SendMessage("Target a player."); - } - else - { - Participant.Players[bid].Mobile.SendMessage("You have been removed from the duel."); - - if (Participant.Players[bid].Mobile is PlayerMobile) - ((PlayerMobile)Participant.Players[bid].Mobile).DuelPlayer = null; - - Participant.Players[bid] = null; - From.SendMessage("They have been removed from the duel."); - From.SendGump(new ParticipantGump(From, Context, Participant)); - } - } - } - } - - private class ParticipantTarget : Target - { - private readonly DuelContext m_Context; - private readonly int m_Index; - private readonly Participant m_Participant; - - public ParticipantTarget(DuelContext context, Participant p, int index) : base(12, false, TargetFlags.None) - { - m_Context = context; - m_Participant = p; - m_Index = index; - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (!m_Context.Registered) - return; - - int index = m_Index; - - if (index < 0 || index >= m_Participant.Players.Length) - return; - - if (!(targeted is Mobile mob)) - { - from.SendMessage("That is not a player."); - } - else if (!mob.Player) - { - if (mob.Body.IsHuman) - mob.SayTo(from, 1005443); // Nay, I would rather stay here and watch a nail rust. - else - mob.SayTo(from, 1005444); // The creature ignores your offer. - } - else if (AcceptDuelGump.IsIgnored(mob, from) || mob.Blessed) - { - from.SendMessage("They ignore your offer."); - } - else - { - if (!(mob is PlayerMobile pm)) - return; - - if (pm.DuelContext != null) - { - from.SendMessage("{0} cannot fight because they are already assigned to another duel.", pm.Name); - } - else if (DuelContext.CheckCombat(pm)) - { - from.SendMessage("{0} cannot fight because they have recently been in combat with another player.", - pm.Name); - } - else if (mob.HasGump()) - { - from.SendMessage("{0} has already been offered a duel."); - } - else - { - from.SendMessage("You send {0} to {1}.", - m_Participant.Find(from) == null ? "a challenge" : "an invitation", mob.Name); - mob.SendGump(new AcceptDuelGump(from, mob, m_Context, m_Participant, m_Index)); - } - } - } - - protected override void OnTargetFinish(Mobile from) - { - from.SendGump(new ParticipantGump(from, m_Context, m_Participant)); - } - } - } -} +using Server.Gumps; +using Server.Mobiles; +using Server.Network; +using Server.Targeting; + +namespace Server.Engines.ConPVP +{ + public class ParticipantGump : Gump + { + public ParticipantGump(Mobile from, DuelContext context, Participant p) : base(50, 50) + { + From = from; + Context = context; + Participant = p; + + from.CloseGump(); + from.CloseGump(); + from.CloseGump(); + + var count = p.Players.Length; + + if (count < 4) + count = 4; + + AddPage(0); + + var height = 35 + 10 + 22 + 22 + 30 + 22 + 2 + count * 22 + 2 + 30; + + AddBackground(0, 0, 300, height, 9250); + AddBackground(10, 10, 280, height - 20, 0xDAC); + + AddButton(240, 25, 0xFB1, 0xFB3, 3); + + // AddButton( 223, 54, 0x265A, 0x265A, 4, ); + + AddHtml(35, 25, 230, 20, Center("Participant Setup")); + + var x = 35; + var y = 47; + + AddHtml(x, y, 200, 20, $"Team Size: {p.Players.Length}"); + y += 22; + + AddGoldenButtonLabeled(x + 20, y, 1, "Increase"); + y += 22; + AddGoldenButtonLabeled(x + 20, y, 2, "Decrease"); + y += 30; + + AddHtml(35, y, 230, 20, Center("Players")); + y += 22; + + for (var i = 0; i < p.Players.Length; ++i) + { + var pl = p.Players[i]; + + AddGoldenButtonLabeled(x, y, 5 + i, $"{1 + i}: {(pl == null ? "Empty" : pl.Mobile.Name)}"); + y += 22; + } + } + + public Mobile From { get; } + + public DuelContext Context { get; } + + public Participant Participant { get; } + + public string Center(string text) => $"
{text}
"; + + public void AddGoldenButton(int x, int y, int bid) + { + AddButton(x, y, 0xD2, 0xD2, bid); + AddButton(x + 3, y + 3, 0xD8, 0xD8, bid); + } + + public void AddGoldenButtonLabeled(int x, int y, int bid, string text) + { + AddGoldenButton(x, y, bid); + AddHtml(x + 25, y, 200, 20, text); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (!Context.Registered) + return; + + var bid = info.ButtonID; + + if (bid == 0) + { + From.SendGump(new DuelContextGump(From, Context)); + } + else if (bid == 1) + { + if (Participant.Count < 8) + Participant.Resize(Participant.Count + 1); + else + From.SendMessage("You may not raise the team size any further."); + + From.SendGump(new ParticipantGump(From, Context, Participant)); + } + else if (bid == 2) + { + if (Participant.Count > 1 && Participant.Count > Participant.FilledSlots) + Participant.Resize(Participant.Count - 1); + else + From.SendMessage("You may not lower the team size any further."); + + From.SendGump(new ParticipantGump(From, Context, Participant)); + } + else if (bid == 3) + { + if (Participant.FilledSlots > 0) + { + From.SendMessage("There is at least one currently active player. You must remove them first."); + From.SendGump(new ParticipantGump(From, Context, Participant)); + } + else if (Context.Participants.Count > 2) + { + /*Container cont = m_Participant.Stakes; + + if (cont != null) + cont.Delete();*/ + + Context.Participants.Remove(Participant); + From.SendGump(new DuelContextGump(From, Context)); + } + else + { + From.SendMessage("Duels must have at least two participating parties."); + From.SendGump(new ParticipantGump(From, Context, Participant)); + } + } + /*else if (bid == 4) + { + m_From.SendGump( new ParticipantGump( m_From, m_Context, m_Participant ) ); + + Container cont = m_Participant.Stakes; + + if (cont != null && !cont.Deleted) + { + cont.DisplayTo( m_From ); + + Item[] checks = cont.FindItemsByType( typeof( BankCheck ) ); + + int gold = cont.TotalGold; + + for ( int i = 0; i < checks.Length; ++i ) + gold += ((BankCheck)checks[i]).Worth; + + m_From.SendMessage( "This container has {0} item{1} and {2} stone{3}. In gold or check form there is a total of {4:D}gp.", cont.TotalItems, cont.TotalItems==1?"":"s", cont.TotalWeight, cont.TotalWeight==1?"":"s", gold ); + } + }*/ + else + { + bid -= 5; + + if (bid >= 0 && bid < Participant.Players.Length) + { + if (Participant.Players[bid] == null) + { + From.Target = new ParticipantTarget(Context, Participant, bid); + From.SendMessage("Target a player."); + } + else + { + Participant.Players[bid].Mobile.SendMessage("You have been removed from the duel."); + + if (Participant.Players[bid].Mobile is PlayerMobile) + ((PlayerMobile)Participant.Players[bid].Mobile).DuelPlayer = null; + + Participant.Players[bid] = null; + From.SendMessage("They have been removed from the duel."); + From.SendGump(new ParticipantGump(From, Context, Participant)); + } + } + } + } + + private class ParticipantTarget : Target + { + private readonly DuelContext m_Context; + private readonly int m_Index; + private readonly Participant m_Participant; + + public ParticipantTarget(DuelContext context, Participant p, int index) : base(12, false, TargetFlags.None) + { + m_Context = context; + m_Participant = p; + m_Index = index; + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (!m_Context.Registered) + return; + + var index = m_Index; + + if (index < 0 || index >= m_Participant.Players.Length) + return; + + if (!(targeted is Mobile mob)) + { + from.SendMessage("That is not a player."); + } + else if (!mob.Player) + { + if (mob.Body.IsHuman) + mob.SayTo(from, 1005443); // Nay, I would rather stay here and watch a nail rust. + else + mob.SayTo(from, 1005444); // The creature ignores your offer. + } + else if (AcceptDuelGump.IsIgnored(mob, from) || mob.Blessed) + { + from.SendMessage("They ignore your offer."); + } + else + { + if (!(mob is PlayerMobile pm)) + return; + + if (pm.DuelContext != null) + { + from.SendMessage("{0} cannot fight because they are already assigned to another duel.", pm.Name); + } + else if (DuelContext.CheckCombat(pm)) + { + from.SendMessage( + "{0} cannot fight because they have recently been in combat with another player.", + pm.Name + ); + } + else if (mob.HasGump()) + { + from.SendMessage("{0} has already been offered a duel."); + } + else + { + from.SendMessage( + "You send {0} to {1}.", + m_Participant.Find(from) == null ? "a challenge" : "an invitation", + mob.Name + ); + mob.SendGump(new AcceptDuelGump(from, mob, m_Context, m_Participant, m_Index)); + } + } + } + + protected override void OnTargetFinish(Mobile from) + { + from.SendGump(new ParticipantGump(from, m_Context, m_Participant)); + } + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Gumps/PickRulesetGump.cs b/Projects/UOContent/Engines/ConPVP/Gumps/PickRulesetGump.cs index 4c9c395c6..28f5cda58 100644 --- a/Projects/UOContent/Engines/ConPVP/Gumps/PickRulesetGump.cs +++ b/Projects/UOContent/Engines/ConPVP/Gumps/PickRulesetGump.cs @@ -1,123 +1,123 @@ -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.ConPVP -{ - public class PickRulesetGump : Gump - { - private readonly DuelContext m_Context; - private readonly Ruleset[] m_Defaults; - private readonly Ruleset[] m_Flavors; - private readonly Mobile m_From; - private readonly Ruleset m_Ruleset; - - public PickRulesetGump(Mobile from, DuelContext context, Ruleset ruleset) : base(50, 50) - { - m_From = from; - m_Context = context; - m_Ruleset = ruleset; - m_Defaults = ruleset.Layout.Defaults; - m_Flavors = ruleset.Layout.Flavors; - - int height = 25 + 20 + (m_Defaults.Length + 1) * 22 + 6 + 20 + m_Flavors.Length * 22 + 25; - - AddPage(0); - - AddBackground(0, 0, 260, height, 9250); - AddBackground(10, 10, 240, height - 20, 0xDAC); - - AddHtml(35, 25, 190, 20, Center("Rules")); - - int y = 25 + 20; - - for (int i = 0; i < m_Defaults.Length; ++i) - { - Ruleset cur = m_Defaults[i]; - - AddHtml(35 + 14, y, 176, 20, cur.Title); - - if (ruleset.Base == cur && !ruleset.Changed) - AddImage(35, y + 4, 0x939); - else if (ruleset.Base == cur) - AddButton(35, y + 4, 0x93A, 0x939, 2 + i); - else - AddButton(35, y + 4, 0x938, 0x939, 2 + i); - - y += 22; - } - - AddHtml(35 + 14, y, 176, 20, "Custom"); - AddButton(35, y + 4, ruleset.Changed ? 0x939 : 0x938, 0x939, 1); - - y += 22; - y += 6; - - AddHtml(35, y, 190, 20, Center("Flavors")); - y += 20; - - for (int i = 0; i < m_Flavors.Length; ++i) - { - Ruleset cur = m_Flavors[i]; - - AddHtml(35 + 14, y, 176, 20, cur.Title); - - if (ruleset.Flavors.Contains(cur)) - AddButton(35, y + 4, 0x939, 0x938, 2 + m_Defaults.Length + i); - else - AddButton(35, y + 4, 0x938, 0x939, 2 + m_Defaults.Length + i); - - y += 22; - } - } - - public string Center(string text) => $"
{text}
"; - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Context?.Registered == false) - return; - - switch (info.ButtonID) - { - case 0: // closed - { - if (m_Context != null) - m_From.SendGump(new DuelContextGump(m_From, m_Context)); - - break; - } - case 1: // customize - { - m_From.SendGump(new RulesetGump(m_From, m_Ruleset, m_Ruleset.Layout, m_Context)); - break; - } - default: - { - int idx = info.ButtonID - 2; - - if (idx >= 0 && idx < m_Defaults.Length) - { - m_Ruleset.ApplyDefault(m_Defaults[idx]); - m_From.SendGump(new PickRulesetGump(m_From, m_Context, m_Ruleset)); - } - else - { - idx -= m_Defaults.Length; - - if (idx >= 0 && idx < m_Flavors.Length) - { - if (m_Ruleset.Flavors.Contains(m_Flavors[idx])) - m_Ruleset.RemoveFlavor(m_Flavors[idx]); - else - m_Ruleset.AddFlavor(m_Flavors[idx]); - - m_From.SendGump(new PickRulesetGump(m_From, m_Context, m_Ruleset)); - } - } - - break; - } - } - } - } -} +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.ConPVP +{ + public class PickRulesetGump : Gump + { + private readonly DuelContext m_Context; + private readonly Ruleset[] m_Defaults; + private readonly Ruleset[] m_Flavors; + private readonly Mobile m_From; + private readonly Ruleset m_Ruleset; + + public PickRulesetGump(Mobile from, DuelContext context, Ruleset ruleset) : base(50, 50) + { + m_From = from; + m_Context = context; + m_Ruleset = ruleset; + m_Defaults = ruleset.Layout.Defaults; + m_Flavors = ruleset.Layout.Flavors; + + var height = 25 + 20 + (m_Defaults.Length + 1) * 22 + 6 + 20 + m_Flavors.Length * 22 + 25; + + AddPage(0); + + AddBackground(0, 0, 260, height, 9250); + AddBackground(10, 10, 240, height - 20, 0xDAC); + + AddHtml(35, 25, 190, 20, Center("Rules")); + + var y = 25 + 20; + + for (var i = 0; i < m_Defaults.Length; ++i) + { + var cur = m_Defaults[i]; + + AddHtml(35 + 14, y, 176, 20, cur.Title); + + if (ruleset.Base == cur && !ruleset.Changed) + AddImage(35, y + 4, 0x939); + else if (ruleset.Base == cur) + AddButton(35, y + 4, 0x93A, 0x939, 2 + i); + else + AddButton(35, y + 4, 0x938, 0x939, 2 + i); + + y += 22; + } + + AddHtml(35 + 14, y, 176, 20, "Custom"); + AddButton(35, y + 4, ruleset.Changed ? 0x939 : 0x938, 0x939, 1); + + y += 22; + y += 6; + + AddHtml(35, y, 190, 20, Center("Flavors")); + y += 20; + + for (var i = 0; i < m_Flavors.Length; ++i) + { + var cur = m_Flavors[i]; + + AddHtml(35 + 14, y, 176, 20, cur.Title); + + if (ruleset.Flavors.Contains(cur)) + AddButton(35, y + 4, 0x939, 0x938, 2 + m_Defaults.Length + i); + else + AddButton(35, y + 4, 0x938, 0x939, 2 + m_Defaults.Length + i); + + y += 22; + } + } + + public string Center(string text) => $"
{text}
"; + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Context?.Registered == false) + return; + + switch (info.ButtonID) + { + case 0: // closed + { + if (m_Context != null) + m_From.SendGump(new DuelContextGump(m_From, m_Context)); + + break; + } + case 1: // customize + { + m_From.SendGump(new RulesetGump(m_From, m_Ruleset, m_Ruleset.Layout, m_Context)); + break; + } + default: + { + var idx = info.ButtonID - 2; + + if (idx >= 0 && idx < m_Defaults.Length) + { + m_Ruleset.ApplyDefault(m_Defaults[idx]); + m_From.SendGump(new PickRulesetGump(m_From, m_Context, m_Ruleset)); + } + else + { + idx -= m_Defaults.Length; + + if (idx >= 0 && idx < m_Flavors.Length) + { + if (m_Ruleset.Flavors.Contains(m_Flavors[idx])) + m_Ruleset.RemoveFlavor(m_Flavors[idx]); + else + m_Ruleset.AddFlavor(m_Flavors[idx]); + + m_From.SendGump(new PickRulesetGump(m_From, m_Context, m_Ruleset)); + } + } + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Gumps/ReadyGump.cs b/Projects/UOContent/Engines/ConPVP/Gumps/ReadyGump.cs index ee7c31a3e..0313723f8 100644 --- a/Projects/UOContent/Engines/ConPVP/Gumps/ReadyGump.cs +++ b/Projects/UOContent/Engines/ConPVP/Gumps/ReadyGump.cs @@ -1,106 +1,105 @@ -using System.Collections.Generic; -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.ConPVP -{ - public class ReadyGump : Gump - { - private DuelContext m_Context; - private int m_Count; - private Mobile m_From; - - public ReadyGump(Mobile from, DuelContext context, int count) : base(50, 50) - { - m_From = from; - m_Context = context; - m_Count = count; - - List parts = context.Participants; - - int height = 25 + 20; - - for (int i = 0; i < parts.Count; ++i) - { - Participant p = parts[i]; - - height += 4; - - if (p.Players.Length > 1) - height += 22; - - height += p.Players.Length * 22; - } - - height += 25; - - Closable = false; - Draggable = false; - - AddPage(0); - - AddBackground(0, 0, 260, height, 9250); - AddBackground(10, 10, 240, height - 20, 0xDAC); - - if (count == -1) - { - AddHtml(35, 25, 190, 20, Center("Ready")); - } - else - { - AddHtml(35, 25, 190, 20, Center("Starting")); - AddHtml(35, 25, 190, 20, $"
{count}"); - } - - int y = 25 + 20; - - for (int i = 0; i < parts.Count; ++i) - { - Participant p = parts[i]; - - y += 4; - - bool isAllReady = true; - int yStore = y; - int offset = 0; - - if (p.Players.Length > 1) - { - AddHtml(35 + 14, y, 176, 20, $"Participant #{i + 1}"); - y += 22; - offset = 10; - } - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer pl = p.Players[j]; - - if (pl?.Ready == true) - { - AddImage(35 + offset, y + 4, 0x939); - } - else - { - AddImage(35 + offset, y + 4, 0x938); - isAllReady = false; - } - - string name = pl == null ? "(Empty)" : pl.Mobile.Name; - - AddHtml(35 + offset + 14, y, 166, 20, name); - - y += 22; - } - - if (p.Players.Length > 1) - AddImage(35, yStore + 4, isAllReady ? 0x939 : 0x938); - } - } - - public string Center(string text) => $"
{text}
"; - - public override void OnResponse(NetState sender, RelayInfo info) - { - } - } -} +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.ConPVP +{ + public class ReadyGump : Gump + { + private DuelContext m_Context; + private int m_Count; + private Mobile m_From; + + public ReadyGump(Mobile from, DuelContext context, int count) : base(50, 50) + { + m_From = from; + m_Context = context; + m_Count = count; + + var parts = context.Participants; + + var height = 25 + 20; + + for (var i = 0; i < parts.Count; ++i) + { + var p = parts[i]; + + height += 4; + + if (p.Players.Length > 1) + height += 22; + + height += p.Players.Length * 22; + } + + height += 25; + + Closable = false; + Draggable = false; + + AddPage(0); + + AddBackground(0, 0, 260, height, 9250); + AddBackground(10, 10, 240, height - 20, 0xDAC); + + if (count == -1) + { + AddHtml(35, 25, 190, 20, Center("Ready")); + } + else + { + AddHtml(35, 25, 190, 20, Center("Starting")); + AddHtml(35, 25, 190, 20, $"
{count}"); + } + + var y = 25 + 20; + + for (var i = 0; i < parts.Count; ++i) + { + var p = parts[i]; + + y += 4; + + var isAllReady = true; + var yStore = y; + var offset = 0; + + if (p.Players.Length > 1) + { + AddHtml(35 + 14, y, 176, 20, $"Participant #{i + 1}"); + y += 22; + offset = 10; + } + + for (var j = 0; j < p.Players.Length; ++j) + { + var pl = p.Players[j]; + + if (pl?.Ready == true) + { + AddImage(35 + offset, y + 4, 0x939); + } + else + { + AddImage(35 + offset, y + 4, 0x938); + isAllReady = false; + } + + var name = pl == null ? "(Empty)" : pl.Mobile.Name; + + AddHtml(35 + offset + 14, y, 166, 20, name); + + y += 22; + } + + if (p.Players.Length > 1) + AddImage(35, yStore + 4, isAllReady ? 0x939 : 0x938); + } + } + + public string Center(string text) => $"
{text}
"; + + public override void OnResponse(NetState sender, RelayInfo info) + { + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Gumps/ReadyUpGump.cs b/Projects/UOContent/Engines/ConPVP/Gumps/ReadyUpGump.cs index 04c63cd9b..ad2daaafe 100644 --- a/Projects/UOContent/Engines/ConPVP/Gumps/ReadyUpGump.cs +++ b/Projects/UOContent/Engines/ConPVP/Gumps/ReadyUpGump.cs @@ -1,222 +1,221 @@ -using System.Collections; -using System.Collections.Generic; -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.ConPVP -{ - public class ReadyUpGump : Gump - { - private readonly DuelContext m_Context; - private readonly Mobile m_From; - - public ReadyUpGump(Mobile from, DuelContext context) : base(50, 50) - { - m_From = from; - m_Context = context; - - Closable = false; - AddPage(0); - - if (context.Rematch) - { - int height = 25 + 20 + 10 + 22 + 25; - - AddBackground(0, 0, 210, height, 9250); - AddBackground(10, 10, 190, height - 20, 0xDAC); - - AddHtml(35, 25, 140, 20, Center("Rematch?")); - - AddButton(35, 55, 247, 248, 1); - AddButton(115, 55, 242, 241, 2); - } - else - { - AddPage(1); - - List parts = context.Participants; - - int height = 25 + 20; - - for (int i = 0; i < parts.Count; ++i) - { - Participant p = parts[i]; - - height += 4; - - if (p.Players.Length > 1) - height += 22; - - height += p.Players.Length * 22; - } - - height += 10 + 22 + 25; - - AddBackground(0, 0, 260, height, 9250); - AddBackground(10, 10, 240, height - 20, 0xDAC); - - AddHtml(35, 25, 190, 20, Center("Participants")); - - int y = 20 + 25; - - for (int i = 0; i < parts.Count; ++i) - { - Participant p = parts[i]; - - y += 4; - - int offset = 0; - - if (p.Players.Length > 1) - { - AddHtml(35, y, 176, 20, $"Team #{i + 1}"); - y += 22; - offset = 10; - } - - for (int j = 0; j < p.Players.Length; ++j) - { - DuelPlayer pl = p.Players[j]; - - string name = pl == null ? "(Empty)" : pl.Mobile.Name; - - AddHtml(35 + offset, y, 166, 20, name); - - y += 22; - } - } - - y += 8; - - AddHtml(35, y, 176, 20, "Continue?"); - - y -= 2; - - AddButton(102, y, 247, 248, 0, GumpButtonType.Page, 2); - AddButton(169, y, 242, 241, 2); - - AddPage(2); - - Ruleset ruleset = context.Ruleset; - Ruleset basedef = ruleset.Base; - - height = 25 + 20 + 5 + 20 + 20 + 4; - - int changes = 0; - - BitArray defs; - - if (ruleset.Flavors.Count > 0) - { - defs = new BitArray(basedef.Options); - - for (int i = 0; i < ruleset.Flavors.Count; ++i) - defs.Or(ruleset.Flavors[i].Options); - - height += ruleset.Flavors.Count * 18; - } - else - { - defs = basedef.Options; - } - - BitArray opts = ruleset.Options; - - for (int i = 0; i < opts.Length; ++i) - if (defs[i] != opts[i]) - ++changes; - - height += changes * 22; - - height += 10 + 22 + 25; - - AddBackground(0, 0, 260, height, 9250); - AddBackground(10, 10, 240, height - 20, 0xDAC); - - AddHtml(35, 25, 190, 20, Center("Rules")); - - AddHtml(35, 50, 190, 20, $"Set: {basedef.Title}"); - - y = 70; - - for (int i = 0; i < ruleset.Flavors.Count; ++i, y += 18) - AddHtml(35, y, 190, 20, $" + {ruleset.Flavors[i].Title}"); - - y += 4; - - if (changes > 0) - { - AddHtml(35, y, 190, 20, "Modifications:"); - y += 20; - - for (int i = 0; i < opts.Length; ++i) - if (defs[i] != opts[i]) - { - string name = ruleset.Layout.FindByIndex(i); - - if (name != null) // sanity - { - AddImage(35, y, opts[i] ? 0xD3 : 0xD2); - AddHtml(60, y, 165, 22, name); - } - - y += 22; - } - } - else - { - AddHtml(35, y, 190, 20, "Modifications: None"); - y += 20; - } - - y += 8; - - AddHtml(35, y, 176, 20, "Continue?"); - - y -= 2; - - AddButton(102, y, 247, 248, 1); - AddButton(169, y, 242, 241, 3); - } - } - - public string Center(string text) => $"
{text}
"; - - public void AddGoldenButton(int x, int y, int bid) - { - AddButton(x, y, 0xD2, 0xD2, bid); - AddButton(x + 3, y + 3, 0xD8, 0xD8, bid); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (!m_Context.Registered || !m_Context.ReadyWait) - return; - - switch (info.ButtonID) - { - case 1: // okay - { - if (!(m_From is PlayerMobile pm)) - break; - - pm.DuelPlayer.Ready = true; - m_Context.SendReadyGump(); - - break; - } - case 2: // reject participants - { - m_Context.RejectReady(m_From, "participants"); - break; - } - case 3: // reject rules - { - m_Context.RejectReady(m_From, "rules"); - break; - } - } - } - } -} +using System.Collections; +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.ConPVP +{ + public class ReadyUpGump : Gump + { + private readonly DuelContext m_Context; + private readonly Mobile m_From; + + public ReadyUpGump(Mobile from, DuelContext context) : base(50, 50) + { + m_From = from; + m_Context = context; + + Closable = false; + AddPage(0); + + if (context.Rematch) + { + var height = 25 + 20 + 10 + 22 + 25; + + AddBackground(0, 0, 210, height, 9250); + AddBackground(10, 10, 190, height - 20, 0xDAC); + + AddHtml(35, 25, 140, 20, Center("Rematch?")); + + AddButton(35, 55, 247, 248, 1); + AddButton(115, 55, 242, 241, 2); + } + else + { + AddPage(1); + + var parts = context.Participants; + + var height = 25 + 20; + + for (var i = 0; i < parts.Count; ++i) + { + var p = parts[i]; + + height += 4; + + if (p.Players.Length > 1) + height += 22; + + height += p.Players.Length * 22; + } + + height += 10 + 22 + 25; + + AddBackground(0, 0, 260, height, 9250); + AddBackground(10, 10, 240, height - 20, 0xDAC); + + AddHtml(35, 25, 190, 20, Center("Participants")); + + var y = 20 + 25; + + for (var i = 0; i < parts.Count; ++i) + { + var p = parts[i]; + + y += 4; + + var offset = 0; + + if (p.Players.Length > 1) + { + AddHtml(35, y, 176, 20, $"Team #{i + 1}"); + y += 22; + offset = 10; + } + + for (var j = 0; j < p.Players.Length; ++j) + { + var pl = p.Players[j]; + + var name = pl == null ? "(Empty)" : pl.Mobile.Name; + + AddHtml(35 + offset, y, 166, 20, name); + + y += 22; + } + } + + y += 8; + + AddHtml(35, y, 176, 20, "Continue?"); + + y -= 2; + + AddButton(102, y, 247, 248, 0, GumpButtonType.Page, 2); + AddButton(169, y, 242, 241, 2); + + AddPage(2); + + var ruleset = context.Ruleset; + var basedef = ruleset.Base; + + height = 25 + 20 + 5 + 20 + 20 + 4; + + var changes = 0; + + BitArray defs; + + if (ruleset.Flavors.Count > 0) + { + defs = new BitArray(basedef.Options); + + for (var i = 0; i < ruleset.Flavors.Count; ++i) + defs.Or(ruleset.Flavors[i].Options); + + height += ruleset.Flavors.Count * 18; + } + else + { + defs = basedef.Options; + } + + var opts = ruleset.Options; + + for (var i = 0; i < opts.Length; ++i) + if (defs[i] != opts[i]) + ++changes; + + height += changes * 22; + + height += 10 + 22 + 25; + + AddBackground(0, 0, 260, height, 9250); + AddBackground(10, 10, 240, height - 20, 0xDAC); + + AddHtml(35, 25, 190, 20, Center("Rules")); + + AddHtml(35, 50, 190, 20, $"Set: {basedef.Title}"); + + y = 70; + + for (var i = 0; i < ruleset.Flavors.Count; ++i, y += 18) + AddHtml(35, y, 190, 20, $" + {ruleset.Flavors[i].Title}"); + + y += 4; + + if (changes > 0) + { + AddHtml(35, y, 190, 20, "Modifications:"); + y += 20; + + for (var i = 0; i < opts.Length; ++i) + if (defs[i] != opts[i]) + { + var name = ruleset.Layout.FindByIndex(i); + + if (name != null) // sanity + { + AddImage(35, y, opts[i] ? 0xD3 : 0xD2); + AddHtml(60, y, 165, 22, name); + } + + y += 22; + } + } + else + { + AddHtml(35, y, 190, 20, "Modifications: None"); + y += 20; + } + + y += 8; + + AddHtml(35, y, 176, 20, "Continue?"); + + y -= 2; + + AddButton(102, y, 247, 248, 1); + AddButton(169, y, 242, 241, 3); + } + } + + public string Center(string text) => $"
{text}
"; + + public void AddGoldenButton(int x, int y, int bid) + { + AddButton(x, y, 0xD2, 0xD2, bid); + AddButton(x + 3, y + 3, 0xD8, 0xD8, bid); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (!m_Context.Registered || !m_Context.ReadyWait) + return; + + switch (info.ButtonID) + { + case 1: // okay + { + if (!(m_From is PlayerMobile pm)) + break; + + pm.DuelPlayer.Ready = true; + m_Context.SendReadyGump(); + + break; + } + case 2: // reject participants + { + m_Context.RejectReady(m_From, "participants"); + break; + } + case 3: // reject rules + { + m_Context.RejectReady(m_From, "rules"); + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Gumps/RulesetGump.cs b/Projects/UOContent/Engines/ConPVP/Gumps/RulesetGump.cs index 712a68eb3..7a6309b07 100644 --- a/Projects/UOContent/Engines/ConPVP/Gumps/RulesetGump.cs +++ b/Projects/UOContent/Engines/ConPVP/Gumps/RulesetGump.cs @@ -1,123 +1,123 @@ -using System.Collections; -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.ConPVP -{ - public class RulesetGump : Gump - { - private readonly DuelContext m_DuelContext; - private readonly Mobile m_From; - private readonly RulesetLayout m_Page; - private readonly bool m_ReadOnly; - private readonly Ruleset m_Ruleset; - - public RulesetGump(Mobile from, Ruleset ruleset, RulesetLayout page, DuelContext duelContext, bool readOnly = false) - : base(readOnly ? 310 : 50, 50) - { - m_From = from; - m_Ruleset = ruleset; - m_Page = page; - m_DuelContext = duelContext; - m_ReadOnly = readOnly; - - Draggable = !readOnly; - - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - - RulesetLayout depthCounter = page; - - while (depthCounter != null) - depthCounter = depthCounter.Parent; - - int count = page.Children.Length + page.Options.Length; - - AddPage(0); - - int height = 35 + 10 + 2 + count * 22 + 2 + 30; - - AddBackground(0, 0, 260, height, 9250); - AddBackground(10, 10, 240, height - 20, 0xDAC); - - AddHtml(35, 25, 190, 20, Center(page.Title)); - - int x = 35; - int y = 47; - - for (int i = 0; i < page.Children.Length; ++i) - { - AddGoldenButton(x, y, 1 + i); - AddHtml(x + 25, y, 250, 22, page.Children[i].Title); - - y += 22; - } - - for (int i = 0; i < page.Options.Length; ++i) - { - bool enabled = ruleset.Options[page.Offset + i]; - - if (readOnly) - AddImage(x, y, enabled ? 0xD3 : 0xD2); - else - AddCheck(x, y, 0xD2, 0xD3, enabled, i); - - AddHtml(x + 25, y, 250, 22, page.Options[i]); - - y += 22; - } - } - - public string Center(string text) => $"
{text}
"; - - public void AddGoldenButton(int x, int y, int bid) - { - AddButton(x, y, 0xD2, 0xD2, bid); - AddButton(x + 3, y + 3, 0xD8, 0xD8, bid); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_DuelContext?.Registered == false) - return; - - if (!m_ReadOnly) - { - BitArray opts = new BitArray(m_Page.Options.Length); - - for (int i = 0; i < info.Switches.Length; ++i) - { - int sid = info.Switches[i]; - - if (sid >= 0 && sid < m_Page.Options.Length) - opts[sid] = true; - } - - for (int i = 0; i < opts.Length; ++i) - if (m_Ruleset.Options[m_Page.Offset + i] != opts[i]) - { - m_Ruleset.Options[m_Page.Offset + i] = opts[i]; - m_Ruleset.Changed = true; - } - } - - int bid = info.ButtonID; - - if (bid == 0) - { - if (m_Page.Parent != null) - m_From.SendGump(new RulesetGump(m_From, m_Ruleset, m_Page.Parent, m_DuelContext, m_ReadOnly)); - else if (!m_ReadOnly) - m_From.SendGump(new PickRulesetGump(m_From, m_DuelContext, m_Ruleset)); - } - else - { - bid -= 1; - - if (bid >= 0 && bid < m_Page.Children.Length) - m_From.SendGump(new RulesetGump(m_From, m_Ruleset, m_Page.Children[bid], m_DuelContext, m_ReadOnly)); - } - } - } -} +using System.Collections; +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.ConPVP +{ + public class RulesetGump : Gump + { + private readonly DuelContext m_DuelContext; + private readonly Mobile m_From; + private readonly RulesetLayout m_Page; + private readonly bool m_ReadOnly; + private readonly Ruleset m_Ruleset; + + public RulesetGump(Mobile from, Ruleset ruleset, RulesetLayout page, DuelContext duelContext, bool readOnly = false) + : base(readOnly ? 310 : 50, 50) + { + m_From = from; + m_Ruleset = ruleset; + m_Page = page; + m_DuelContext = duelContext; + m_ReadOnly = readOnly; + + Draggable = !readOnly; + + from.CloseGump(); + from.CloseGump(); + from.CloseGump(); + + var depthCounter = page; + + while (depthCounter != null) + depthCounter = depthCounter.Parent; + + var count = page.Children.Length + page.Options.Length; + + AddPage(0); + + var height = 35 + 10 + 2 + count * 22 + 2 + 30; + + AddBackground(0, 0, 260, height, 9250); + AddBackground(10, 10, 240, height - 20, 0xDAC); + + AddHtml(35, 25, 190, 20, Center(page.Title)); + + var x = 35; + var y = 47; + + for (var i = 0; i < page.Children.Length; ++i) + { + AddGoldenButton(x, y, 1 + i); + AddHtml(x + 25, y, 250, 22, page.Children[i].Title); + + y += 22; + } + + for (var i = 0; i < page.Options.Length; ++i) + { + var enabled = ruleset.Options[page.Offset + i]; + + if (readOnly) + AddImage(x, y, enabled ? 0xD3 : 0xD2); + else + AddCheck(x, y, 0xD2, 0xD3, enabled, i); + + AddHtml(x + 25, y, 250, 22, page.Options[i]); + + y += 22; + } + } + + public string Center(string text) => $"
{text}
"; + + public void AddGoldenButton(int x, int y, int bid) + { + AddButton(x, y, 0xD2, 0xD2, bid); + AddButton(x + 3, y + 3, 0xD8, 0xD8, bid); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_DuelContext?.Registered == false) + return; + + if (!m_ReadOnly) + { + var opts = new BitArray(m_Page.Options.Length); + + for (var i = 0; i < info.Switches.Length; ++i) + { + var sid = info.Switches[i]; + + if (sid >= 0 && sid < m_Page.Options.Length) + opts[sid] = true; + } + + for (var i = 0; i < opts.Length; ++i) + if (m_Ruleset.Options[m_Page.Offset + i] != opts[i]) + { + m_Ruleset.Options[m_Page.Offset + i] = opts[i]; + m_Ruleset.Changed = true; + } + } + + var bid = info.ButtonID; + + if (bid == 0) + { + if (m_Page.Parent != null) + m_From.SendGump(new RulesetGump(m_From, m_Ruleset, m_Page.Parent, m_DuelContext, m_ReadOnly)); + else if (!m_ReadOnly) + m_From.SendGump(new PickRulesetGump(m_From, m_DuelContext, m_Ruleset)); + } + else + { + bid -= 1; + + if (bid >= 0 && bid < m_Page.Children.Length) + m_From.SendGump(new RulesetGump(m_From, m_Ruleset, m_Page.Children[bid], m_DuelContext, m_ReadOnly)); + } + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Gumps/TournamentBracketGump.cs b/Projects/UOContent/Engines/ConPVP/Gumps/TournamentBracketGump.cs index e03a5b432..e4aa81b3e 100644 --- a/Projects/UOContent/Engines/ConPVP/Gumps/TournamentBracketGump.cs +++ b/Projects/UOContent/Engines/ConPVP/Gumps/TournamentBracketGump.cs @@ -1,829 +1,977 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Text; -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.ConPVP -{ - public enum TourneyBracketGumpType - { - Index, - Rules_Info, - Participant_List, - Participant_Info, - Round_List, - Round_Info, - Match_Info, - Player_Info - } - - public class TournamentBracketGump : Gump - { - private const int BlackColor32 = 0x000008; - private const int LabelColor32 = 0xFFFFFF; - private readonly Mobile m_From; - private readonly List m_List; - private readonly object m_Object; - private readonly int m_Page; - private int m_PerPage; - private readonly Tournament m_Tournament; - private readonly TourneyBracketGumpType m_Type; - - public TournamentBracketGump(Mobile from, Tournament tourney, TourneyBracketGumpType type, - List list = null, int page = 0, object obj = null) : base(50, 50) - { - m_From = from; - m_Tournament = tourney; - m_Type = type; - m_List = list; - m_Page = page; - m_Object = obj; - m_PerPage = 12; - - switch (type) - { - case TourneyBracketGumpType.Index: - { - AddPage(0); - AddBackground(0, 0, 300, 300, 9380); - - StringBuilder sb = new StringBuilder(); - - if (tourney.TourneyType == TourneyType.FreeForAll) - { - sb.Append("FFA"); - } - else if (tourney.TourneyType == TourneyType.RandomTeam) - { - sb.Append(tourney.ParticipantsPerMatch); - sb.Append("-Team"); - } - else if (tourney.TourneyType == TourneyType.RedVsBlue) - { - sb.Append("Red v Blue"); - } - else if (tourney.TourneyType == TourneyType.Faction) - { - sb.Append(tourney.ParticipantsPerMatch); - sb.Append("-Team Faction"); - } - else - { - for (int i = 0; i < tourney.ParticipantsPerMatch; ++i) - { - if (sb.Length > 0) - sb.Append('v'); - - sb.Append(tourney.PlayersPerParticipant); - } - } - - if (tourney.EventController != null) - sb.Append(' ').Append(tourney.EventController.Title); - - sb.Append(" Tournament Bracket"); - - AddHtml(25, 35, 250, 20, Center(sb.ToString())); - - AddRightArrow(25, 53, ToButtonID(0, 4), "Rules"); - AddRightArrow(25, 71, ToButtonID(0, 1), "Participants"); - - if (m_Tournament.Stage == TournamentStage.Signup) - { - TimeSpan until = m_Tournament.SignupStart + m_Tournament.SignupPeriod - DateTime.UtcNow; - string text; - int secs = (int)until.TotalSeconds; - - if (secs > 0) - { - int mins = secs / 60; - secs %= 60; - - if (mins > 0 && secs > 0) - text = - $"The tournament will begin in {mins} minute{(mins == 1 ? "" : "s")} and {secs} second{(secs == 1 ? "" : "s")}."; - else if (mins > 0) - text = $"The tournament will begin in {mins} minute{(mins == 1 ? "" : "s")}."; - else if (secs > 0) - text = $"The tournament will begin in {secs} second{(secs == 1 ? "" : "s")}."; - else - text = "The tournament will begin shortly."; - } - else - { - text = "The tournament will begin shortly."; - } - - AddHtml(25, 92, 250, 40, text); - } - else - { - AddRightArrow(25, 89, ToButtonID(0, 2), "Rounds"); - } - - break; - } - case TourneyBracketGumpType.Rules_Info: - { - Ruleset ruleset = tourney.Ruleset; - Ruleset basedef = ruleset.Base; - - BitArray defs; - - if (ruleset.Flavors.Count > 0) - { - defs = new BitArray(basedef.Options); - - for (int i = 0; i < ruleset.Flavors.Count; ++i) - defs.Or(ruleset.Flavors[i].Options); - } - else - { - defs = basedef.Options; - } - - int changes = 0; - - BitArray opts = ruleset.Options; - - for (int i = 0; i < opts.Length; ++i) - if (defs[i] != opts[i]) - ++changes; - - AddPage(0); - AddBackground(0, 0, 300, - 60 + 18 + 20 + 20 + 20 + 8 + 20 + ruleset.Flavors.Count * 18 + 4 + 20 + changes * 22 + 6, 9380); - - AddLeftArrow(25, 11, ToButtonID(0, 0)); - AddHtml(25, 35, 250, 20, Center("Rules")); - - int y = 53; - - var groupText = tourney.GroupType switch - { - GroupingType.HighVsLow => "High vs Low", - GroupingType.Nearest => "Closest opponent", - GroupingType.Random => "Random", - _ => null - }; - - AddHtml(35, y, 190, 20, $"Grouping: {groupText}"); - y += 20; - - var tieText = tourney.TieType switch - { - TieType.Random => "Random", - TieType.Highest => "Highest advances", - TieType.Lowest => "Lowest advances", - TieType.FullAdvancement => tourney.ParticipantsPerMatch == 2 ? "Both advance" : "Everyone advances", - TieType.FullElimination => tourney.ParticipantsPerMatch == 2 ? "Both eliminated" : "Everyone eliminated", - _ => null - }; - - AddHtml(35, y, 190, 20, $"Tiebreaker: {tieText}"); - y += 20; - - string sdText = "Off"; - - if (tourney.SuddenDeath > TimeSpan.Zero) - { - sdText = $"{(int)tourney.SuddenDeath.TotalMinutes}:{tourney.SuddenDeath.Seconds:D2}"; - - if (tourney.SuddenDeathRounds > 0) - sdText = $"{sdText} (first {tourney.SuddenDeathRounds} rounds)"; - else - sdText = $"{sdText} (all rounds)"; - } - - AddHtml(35, y, 240, 20, $"Sudden Death: {sdText}"); - y += 20; - - y += 8; - - AddHtml(35, y, 190, 20, $"Ruleset: {basedef.Title}"); - y += 20; - - for (int i = 0; i < ruleset.Flavors.Count; ++i, y += 18) - AddHtml(35, y, 190, 20, $" + {ruleset.Flavors[i].Title}"); - - y += 4; - - if (changes > 0) - { - AddHtml(35, y, 190, 20, "Modifications:"); - y += 20; - - for (int i = 0; i < opts.Length; ++i) - if (defs[i] != opts[i]) - { - string name = ruleset.Layout.FindByIndex(i); - - if (name != null) // sanity - { - AddImage(35, y, opts[i] ? 0xD3 : 0xD2); - AddHtml(60, y, 165, 22, name); - } - - y += 22; - } - } - else - { - AddHtml(35, y, 190, 20, "Modifications: None"); - } - - break; - } - case TourneyBracketGumpType.Participant_List: - { - AddPage(0); - AddBackground(0, 0, 300, 300, 9380); - - List pList = m_List != null - ? Utility.CastListCovariant(m_List) - : new List(tourney.Participants); - - AddLeftArrow(25, 11, ToButtonID(0, 0)); - AddHtml(25, 35, 250, 20, Center($"{pList.Count} Participant{(pList.Count == 1 ? "" : "s")}")); - - StartPage(out int index, out int count, out int y, 12); - - for (int i = 0; i < count; ++i, y += 18) - { - TourneyParticipant part = pList[index + i]; - string name = part.NameList; - - if (m_Tournament.TourneyType != TourneyType.Standard && part.Players.Count == 1) - if (part.Players[0] is PlayerMobile pm && pm.DuelPlayer != null) - name = Color(name, pm.DuelPlayer.Eliminated ? 0x6633333 : 0x336666); - - AddRightArrow(25, y, ToButtonID(2, index + i), name); - } - - break; - } - case TourneyBracketGumpType.Participant_Info: - { - if (!(obj is TourneyParticipant part)) - break; - - AddPage(0); - AddBackground(0, 0, 300, 60 + 18 + 20 + part.Players.Count * 18 + 20 + 20 + 160, 9380); - - AddLeftArrow(25, 11, ToButtonID(0, 1)); - AddHtml(25, 35, 250, 20, Center("Participants")); - - int y = 53; - - AddHtml(25, y, 200, 20, part.Players.Count == 1 ? "Players" : "Team"); - y += 20; - - for (int i = 0; i < part.Players.Count; ++i) - { - Mobile mob = part.Players[i]; - string name = mob.Name; - - if (m_Tournament.TourneyType != TourneyType.Standard) - if (mob is PlayerMobile pm && pm.DuelPlayer != null) - name = Color(name, pm.DuelPlayer.Eliminated ? 0x6633333 : 0x336666); - - AddRightArrow(35, y, ToButtonID(4, i), name); - y += 18; - } - - AddHtml(25, y, 200, 20, - $"Free Advances: {(part.FreeAdvances == 0 ? "None" : part.FreeAdvances.ToString())}"); - y += 20; - - AddHtml(25, y, 200, 20, "Log:"); - y += 20; - - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < part.Log.Count; ++i) - { - if (sb.Length > 0) - sb.Append("
"); - - sb.Append(part.Log[i]); - } - - if (sb.Length == 0) - sb.Append("Nothing logged yet."); - - AddHtml(25, y, 250, 150, Color(sb.ToString(), BlackColor32), false, true); - - break; - } - case TourneyBracketGumpType.Player_Info: - { - AddPage(0); - AddBackground(0, 0, 300, 300, 9380); - - AddLeftArrow(25, 11, ToButtonID(0, 3)); - AddHtml(25, 35, 250, 20, Center("Participants")); - - if (!(obj is Mobile mob)) - break; - - Ladder ladder = Ladder.Instance; - LadderEntry entry = ladder?.Find(mob); - - AddHtml(25, 53, 250, 20, $"Name: {mob.Name}"); - AddHtml(25, 73, 250, 20, - $"Guild: {(mob.Guild == null ? "None" : $"{mob.Guild.Name} [{mob.Guild.Abbreviation}]")}"); - AddHtml(25, 93, 250, 20, $"Rank: {(entry == null ? "N/A" : LadderGump.Rank(entry.Index + 1))}"); - AddHtml(25, 113, 250, 20, $"Level: {(entry == null ? 0 : Ladder.GetLevel(entry.Experience))}"); - AddHtml(25, 133, 250, 20, $"Wins: {entry?.Wins ?? 0:N0}"); - AddHtml(25, 153, 250, 20, $"Losses: {entry?.Losses ?? 0:N0}"); - - break; - } - case TourneyBracketGumpType.Round_List: - { - AddPage(0); - AddBackground(0, 0, 300, 300, 9380); - - AddLeftArrow(25, 11, ToButtonID(0, 0)); - AddHtml(25, 35, 250, 20, Center("Rounds")); - - // List levelsList = m_List != null - // ? Utility.CastListCovariant(m_List) - // : new List(tourney.Pyramid.Levels); - - StartPage(out int index, out int count, out int y, 12); - - for (int i = 0; i < count; ++i, y += 18) - AddRightArrow(25, y, ToButtonID(3, index + i), $"Round #{index + i + 1}"); - - break; - } - case TourneyBracketGumpType.Round_Info: - { - AddPage(0); - AddBackground(0, 0, 300, 300, 9380); - - AddLeftArrow(25, 11, ToButtonID(0, 2)); - AddHtml(25, 35, 250, 20, Center("Rounds")); - - if (!(m_Object is PyramidLevel level)) - break; - - List matchesList = m_List != null - ? Utility.CastListCovariant(m_List) - : new List(level.Matches); - - AddRightArrow(25, 53, ToButtonID(5, 0), - $"Free Advance: {(level.FreeAdvance == null ? "None" : level.FreeAdvance.NameList)}"); - - AddHtml(25, 73, 200, 20, $"{matchesList.Count} Match{(matchesList.Count == 1 ? "" : "es")}"); - - StartPage(out int index, out int count, out int y, 10); - - for (int i = 0; i < count; ++i, y += 18) - { - TourneyMatch match = matchesList[index + i]; - - int color = -1; - - if (match.InProgress) - color = 0x336666; - else if (match.Context != null && match.Winner == null) - color = 0x666666; - - StringBuilder sb = new StringBuilder(); - - if (m_Tournament.TourneyType == TourneyType.Standard) - for (int j = 0; j < match.Participants.Count; ++j) - { - if (sb.Length > 0) - sb.Append(" vs "); - - TourneyParticipant part = match.Participants[j]; - string txt = part.NameList; - - if (color == -1 && match.Context != null && match.Winner == part) - txt = Color(txt, 0x336633); - else if (color == -1 && match.Context != null) - txt = Color(txt, 0x663333); - - sb.Append(txt); - } - else if (m_Tournament.EventController != null || m_Tournament.TourneyType == TourneyType.RandomTeam || - m_Tournament.TourneyType == TourneyType.RedVsBlue || - m_Tournament.TourneyType == TourneyType.Faction) - for (int j = 0; j < match.Participants.Count; ++j) - { - if (sb.Length > 0) - sb.Append(" vs "); - - TourneyParticipant part = match.Participants[j]; - string txt; - - if (m_Tournament.EventController != null) - { - txt = $"Team {m_Tournament.EventController.GetTeamName(j)} ({part.Players.Count})"; - } - else if (m_Tournament.TourneyType == TourneyType.RandomTeam) - { - txt = $"Team {j + 1} ({part.Players.Count})"; - } - else if (m_Tournament.TourneyType == TourneyType.Faction) - { - if (m_Tournament.ParticipantsPerMatch == 4) - { - string name = "(null)"; - - switch (j) - { - case 0: - { - name = "Minax"; - break; - } - case 1: - { - name = "Council of Mages"; - break; - } - case 2: - { - name = "True Britannians"; - break; - } - case 3: - { - name = "Shadowlords"; - break; - } - } - - txt = $"{name} ({part.Players.Count})"; - } - else if (m_Tournament.ParticipantsPerMatch == 2) - { - txt = $"{(j == 0 ? "Evil" : "Hero")} Team ({part.Players.Count})"; - } - else - { - txt = $"Team {j + 1} ({part.Players.Count})"; - } - } - else - { - txt = $"Team {(j == 0 ? "Red" : "Blue")} ({part.Players.Count})"; - } - - if (color == -1 && match.Context != null && match.Winner == part) - txt = Color(txt, 0x336633); - else if (color == -1 && match.Context != null) - txt = Color(txt, 0x663333); - - sb.Append(txt); - } - else if (m_Tournament.TourneyType == TourneyType.FreeForAll) sb.Append("Free For All"); - - string str = sb.ToString(); - - if (color >= 0) - str = Color(str, color); - - AddRightArrow(25, y, ToButtonID(5, index + i + 1), str); - } - - break; - } - case TourneyBracketGumpType.Match_Info: - { - if (!(obj is TourneyMatch match)) - break; - - int ct = m_Tournament.TourneyType == TourneyType.FreeForAll ? 2 : match.Participants.Count; - - AddPage(0); - AddBackground(0, 0, 300, 60 + 18 + 20 + 20 + 20 + ct * 18 + 6, 9380); - - AddLeftArrow(25, 11, ToButtonID(0, 5)); - AddHtml(25, 35, 250, 20, Center("Rounds")); - - AddHtml(25, 53, 250, 20, $"Winner: {(match.Winner == null ? "N/A" : match.Winner.NameList)}"); - AddHtml(25, 73, 250, 20, - $"State: {(match.InProgress ? "In progress" : match.Context != null ? "Complete" : "Waiting")}"); - AddHtml(25, 93, 250, 20, "Participants:"); - - if (m_Tournament.TourneyType == TourneyType.Standard) - for (int i = 0; i < match.Participants.Count; ++i) - { - TourneyParticipant part = match.Participants[i]; - - AddRightArrow(25, 113 + i * 18, ToButtonID(6, i), part.NameList); - } - else if (m_Tournament.EventController != null || m_Tournament.TourneyType == TourneyType.RandomTeam || - m_Tournament.TourneyType == TourneyType.RedVsBlue || - m_Tournament.TourneyType == TourneyType.Faction) - for (int i = 0; i < match.Participants.Count; ++i) - { - TourneyParticipant part = match.Participants[i]; - - if (m_Tournament.EventController != null) - { - AddRightArrow(25, 113 + i * 18, ToButtonID(6, i), - $"Team {m_Tournament.EventController.GetTeamName(i)} ({part.Players.Count})"); - } - else if (m_Tournament.TourneyType == TourneyType.RandomTeam) - { - AddRightArrow(25, 113 + i * 18, ToButtonID(6, i), - $"Team {i + 1} ({part.Players.Count})"); - } - else if (m_Tournament.TourneyType == TourneyType.Faction) - { - if (m_Tournament.ParticipantsPerMatch == 4) - { - string name = "(null)"; - - switch (i) - { - case 0: - { - name = "Minax"; - break; - } - case 1: - { - name = "Council of Mages"; - break; - } - case 2: - { - name = "True Britannians"; - break; - } - case 3: - { - name = "Shadowlords"; - break; - } - } - - AddRightArrow(25, 113 + i * 18, ToButtonID(6, i), - $"{name} ({part.Players.Count})"); - } - else if (m_Tournament.ParticipantsPerMatch == 2) - { - AddRightArrow(25, 113 + i * 18, ToButtonID(6, i), - $"{(i == 0 ? "Evil" : "Hero")} Team ({part.Players.Count})"); - } - else - { - AddRightArrow(25, 113 + i * 18, ToButtonID(6, i), - $"Team {i + 1} ({part.Players.Count})"); - } - } - else - { - AddRightArrow(25, 113 + i * 18, ToButtonID(6, i), - $"Team {(i == 0 ? "Red" : "Blue")} ({part.Players.Count})"); - } - } - else if (m_Tournament.TourneyType == TourneyType.FreeForAll) - AddHtml(25, 113, 250, 20, "Free For All"); - - break; - } - } - } - - public string Center(string text) => $"
{text}
"; - - public string Color(string text, int color) => $"{text}"; - - private void AddBorderedText(int x, int y, int width, int height, string text, int color, int borderColor) - { - AddColoredText(x - 1, y - 1, width, height, text, borderColor); - AddColoredText(x - 1, y + 1, width, height, text, borderColor); - AddColoredText(x + 1, y - 1, width, height, text, borderColor); - AddColoredText(x + 1, y + 1, width, height, text, borderColor); - AddColoredText(x, y, width, height, text, color); - } - - private void AddColoredText(int x, int y, int width, int height, string text, int color) - { - if (color == 0) - AddHtml(x, y, width, height, text); - else - AddHtml(x, y, width, height, Color(text, color)); - } - - public void AddRightArrow(int x, int y, int bid, string text) - { - AddButton(x, y, 0x15E1, 0x15E5, bid); - - if (text != null) - AddHtml(x + 20, y - 1, 230, 20, text); - } - - public void AddRightArrow(int x, int y, int bid) - { - AddRightArrow(x, y, bid, null); - } - - public void AddLeftArrow(int x, int y, int bid, string text) - { - AddButton(x, y, 0x15E3, 0x15E7, bid); - - if (text != null) - AddHtml(x + 20, y - 1, 230, 20, text); - } - - public void AddLeftArrow(int x, int y, int bid) - { - AddLeftArrow(x, y, bid, null); - } - - public int ToButtonID(int type, int index) => 1 + index * 7 + type; - - public bool FromButtonID(int bid, out int type, out int index) - { - type = (bid - 1) % 7; - index = (bid - 1) / 7; - return bid >= 1; - } - - public void StartPage(out int index, out int count, out int y, int perPage) - { - m_PerPage = perPage; - - index = Math.Max(m_Page * perPage, 0); - count = Math.Clamp(m_List.Count - index, 0, perPage); - - y = 53 + (12 - perPage) * 18; - - if (m_Page > 0) - AddLeftArrow(242, 35, ToButtonID(1, 0)); - - if ((m_Page + 1) * perPage < m_List.Count) - AddRightArrow(260, 35, ToButtonID(1, 1)); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (!FromButtonID(info.ButtonID, out int type, out int index)) - return; - - switch (type) - { - case 0: - { - switch (index) - { - case 0: - m_From.SendGump(new TournamentBracketGump(m_From, m_Tournament, TourneyBracketGumpType.Index)); - break; - case 1: - m_From.SendGump(new TournamentBracketGump(m_From, m_Tournament, - TourneyBracketGumpType.Participant_List)); - break; - case 2: - m_From.SendGump(new TournamentBracketGump(m_From, m_Tournament, TourneyBracketGumpType.Round_List)); - break; - case 4: - m_From.SendGump(new TournamentBracketGump(m_From, m_Tournament, TourneyBracketGumpType.Rules_Info)); - break; - case 3: - { - Mobile mob = m_Object as Mobile; - - for (int i = 0; i < m_Tournament.Participants.Count; ++i) - { - TourneyParticipant part = m_Tournament.Participants[i]; - - if (part.Players.Contains(mob)) - { - m_From.SendGump(new TournamentBracketGump(m_From, m_Tournament, - TourneyBracketGumpType.Participant_Info, null, 0, part)); - break; - } - } - - break; - } - case 5: - { - if (!(m_Object is TourneyMatch match)) - break; - - for (int i = 0; i < m_Tournament.Pyramid.Levels.Count; ++i) - { - PyramidLevel level = m_Tournament.Pyramid.Levels[i]; - - if (level.Matches.Contains(match)) - m_From.SendGump(new TournamentBracketGump(m_From, m_Tournament, - TourneyBracketGumpType.Round_Info, null, 0, level)); - } - - break; - } - } - - break; - } - case 1: - { - switch (index) - { - case 0: - { - if (m_List != null && m_Page > 0) - m_From.SendGump(new TournamentBracketGump(m_From, m_Tournament, m_Type, m_List, m_Page - 1, - m_Object)); - - break; - } - case 1: - { - if (m_List != null && (m_Page + 1) * m_PerPage < m_List.Count) - m_From.SendGump(new TournamentBracketGump(m_From, m_Tournament, m_Type, m_List, m_Page + 1, - m_Object)); - - break; - } - } - - break; - } - case 2: - { - if (m_Type != TourneyBracketGumpType.Participant_List) - break; - - if (index >= 0 && index < m_List.Count) - m_From.SendGump(new TournamentBracketGump(m_From, m_Tournament, - TourneyBracketGumpType.Participant_Info, null, 0, m_List[index])); - - break; - } - case 3: - { - if (m_Type != TourneyBracketGumpType.Round_List) - break; - - if (index >= 0 && index < m_List.Count) - m_From.SendGump(new TournamentBracketGump(m_From, m_Tournament, TourneyBracketGumpType.Round_Info, - null, 0, m_List[index])); - - break; - } - case 4: - { - if (m_Type != TourneyBracketGumpType.Participant_Info) - break; - - if (m_Object is TourneyParticipant part && index >= 0 && index < part.Players.Count) - m_From.SendGump(new TournamentBracketGump(m_From, m_Tournament, TourneyBracketGumpType.Player_Info, - null, 0, part.Players[index])); - - break; - } - case 5: - { - if (m_Type != TourneyBracketGumpType.Round_Info) - break; - - if (!(m_Object is PyramidLevel level)) - break; - - if (index == 0) - { - if (level.FreeAdvance != null) - m_From.SendGump(new TournamentBracketGump(m_From, m_Tournament, - TourneyBracketGumpType.Participant_Info, null, 0, level.FreeAdvance)); - else - m_From.SendGump( - new TournamentBracketGump(m_From, m_Tournament, m_Type, m_List, m_Page, m_Object)); - } - else if (index >= 1 && index <= level.Matches.Count) - { - m_From.SendGump(new TournamentBracketGump(m_From, m_Tournament, TourneyBracketGumpType.Match_Info, - null, 0, level.Matches[index - 1])); - } - - break; - } - case 6: - { - if (m_Type != TourneyBracketGumpType.Match_Info) - break; - - if (m_Object is TourneyMatch match && index >= 0 && index < match.Participants.Count) - m_From.SendGump(new TournamentBracketGump(m_From, m_Tournament, - TourneyBracketGumpType.Participant_Info, null, 0, match.Participants[index])); - - break; - } - } - } - } -} +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.ConPVP +{ + public enum TourneyBracketGumpType + { + Index, + Rules_Info, + Participant_List, + Participant_Info, + Round_List, + Round_Info, + Match_Info, + Player_Info + } + + public class TournamentBracketGump : Gump + { + private const int BlackColor32 = 0x000008; + private const int LabelColor32 = 0xFFFFFF; + private readonly Mobile m_From; + private readonly List m_List; + private readonly object m_Object; + private readonly int m_Page; + private readonly Tournament m_Tournament; + private readonly TourneyBracketGumpType m_Type; + private int m_PerPage; + + public TournamentBracketGump( + Mobile from, Tournament tourney, TourneyBracketGumpType type, + List list = null, int page = 0, object obj = null + ) : base(50, 50) + { + m_From = from; + m_Tournament = tourney; + m_Type = type; + m_List = list; + m_Page = page; + m_Object = obj; + m_PerPage = 12; + + switch (type) + { + case TourneyBracketGumpType.Index: + { + AddPage(0); + AddBackground(0, 0, 300, 300, 9380); + + var sb = new StringBuilder(); + + if (tourney.TourneyType == TourneyType.FreeForAll) + { + sb.Append("FFA"); + } + else if (tourney.TourneyType == TourneyType.RandomTeam) + { + sb.Append(tourney.ParticipantsPerMatch); + sb.Append("-Team"); + } + else if (tourney.TourneyType == TourneyType.RedVsBlue) + { + sb.Append("Red v Blue"); + } + else if (tourney.TourneyType == TourneyType.Faction) + { + sb.Append(tourney.ParticipantsPerMatch); + sb.Append("-Team Faction"); + } + else + { + for (var i = 0; i < tourney.ParticipantsPerMatch; ++i) + { + if (sb.Length > 0) + sb.Append('v'); + + sb.Append(tourney.PlayersPerParticipant); + } + } + + if (tourney.EventController != null) + sb.Append(' ').Append(tourney.EventController.Title); + + sb.Append(" Tournament Bracket"); + + AddHtml(25, 35, 250, 20, Center(sb.ToString())); + + AddRightArrow(25, 53, ToButtonID(0, 4), "Rules"); + AddRightArrow(25, 71, ToButtonID(0, 1), "Participants"); + + if (m_Tournament.Stage == TournamentStage.Signup) + { + var until = m_Tournament.SignupStart + m_Tournament.SignupPeriod - DateTime.UtcNow; + string text; + var secs = (int)until.TotalSeconds; + + if (secs > 0) + { + var mins = secs / 60; + secs %= 60; + + if (mins > 0 && secs > 0) + text = + $"The tournament will begin in {mins} minute{(mins == 1 ? "" : "s")} and {secs} second{(secs == 1 ? "" : "s")}."; + else if (mins > 0) + text = $"The tournament will begin in {mins} minute{(mins == 1 ? "" : "s")}."; + else if (secs > 0) + text = $"The tournament will begin in {secs} second{(secs == 1 ? "" : "s")}."; + else + text = "The tournament will begin shortly."; + } + else + { + text = "The tournament will begin shortly."; + } + + AddHtml(25, 92, 250, 40, text); + } + else + { + AddRightArrow(25, 89, ToButtonID(0, 2), "Rounds"); + } + + break; + } + case TourneyBracketGumpType.Rules_Info: + { + var ruleset = tourney.Ruleset; + var basedef = ruleset.Base; + + BitArray defs; + + if (ruleset.Flavors.Count > 0) + { + defs = new BitArray(basedef.Options); + + for (var i = 0; i < ruleset.Flavors.Count; ++i) + defs.Or(ruleset.Flavors[i].Options); + } + else + { + defs = basedef.Options; + } + + var changes = 0; + + var opts = ruleset.Options; + + for (var i = 0; i < opts.Length; ++i) + if (defs[i] != opts[i]) + ++changes; + + AddPage(0); + AddBackground( + 0, + 0, + 300, + 60 + 18 + 20 + 20 + 20 + 8 + 20 + ruleset.Flavors.Count * 18 + 4 + 20 + changes * 22 + 6, + 9380 + ); + + AddLeftArrow(25, 11, ToButtonID(0, 0)); + AddHtml(25, 35, 250, 20, Center("Rules")); + + var y = 53; + + var groupText = tourney.GroupType switch + { + GroupingType.HighVsLow => "High vs Low", + GroupingType.Nearest => "Closest opponent", + GroupingType.Random => "Random", + _ => null + }; + + AddHtml(35, y, 190, 20, $"Grouping: {groupText}"); + y += 20; + + var tieText = tourney.TieType switch + { + TieType.Random => "Random", + TieType.Highest => "Highest advances", + TieType.Lowest => "Lowest advances", + TieType.FullAdvancement => tourney.ParticipantsPerMatch == 2 + ? "Both advance" + : "Everyone advances", + TieType.FullElimination => tourney.ParticipantsPerMatch == 2 + ? "Both eliminated" + : "Everyone eliminated", + _ => null + }; + + AddHtml(35, y, 190, 20, $"Tiebreaker: {tieText}"); + y += 20; + + var sdText = "Off"; + + if (tourney.SuddenDeath > TimeSpan.Zero) + { + sdText = $"{(int)tourney.SuddenDeath.TotalMinutes}:{tourney.SuddenDeath.Seconds:D2}"; + + if (tourney.SuddenDeathRounds > 0) + sdText = $"{sdText} (first {tourney.SuddenDeathRounds} rounds)"; + else + sdText = $"{sdText} (all rounds)"; + } + + AddHtml(35, y, 240, 20, $"Sudden Death: {sdText}"); + y += 20; + + y += 8; + + AddHtml(35, y, 190, 20, $"Ruleset: {basedef.Title}"); + y += 20; + + for (var i = 0; i < ruleset.Flavors.Count; ++i, y += 18) + AddHtml(35, y, 190, 20, $" + {ruleset.Flavors[i].Title}"); + + y += 4; + + if (changes > 0) + { + AddHtml(35, y, 190, 20, "Modifications:"); + y += 20; + + for (var i = 0; i < opts.Length; ++i) + if (defs[i] != opts[i]) + { + var name = ruleset.Layout.FindByIndex(i); + + if (name != null) // sanity + { + AddImage(35, y, opts[i] ? 0xD3 : 0xD2); + AddHtml(60, y, 165, 22, name); + } + + y += 22; + } + } + else + { + AddHtml(35, y, 190, 20, "Modifications: None"); + } + + break; + } + case TourneyBracketGumpType.Participant_List: + { + AddPage(0); + AddBackground(0, 0, 300, 300, 9380); + + var pList = m_List != null + ? Utility.CastListCovariant(m_List) + : new List(tourney.Participants); + + AddLeftArrow(25, 11, ToButtonID(0, 0)); + AddHtml(25, 35, 250, 20, Center($"{pList.Count} Participant{(pList.Count == 1 ? "" : "s")}")); + + StartPage(out var index, out var count, out var y, 12); + + for (var i = 0; i < count; ++i, y += 18) + { + var part = pList[index + i]; + var name = part.NameList; + + if (m_Tournament.TourneyType != TourneyType.Standard && part.Players.Count == 1) + if (part.Players[0] is PlayerMobile pm && pm.DuelPlayer != null) + name = Color(name, pm.DuelPlayer.Eliminated ? 0x6633333 : 0x336666); + + AddRightArrow(25, y, ToButtonID(2, index + i), name); + } + + break; + } + case TourneyBracketGumpType.Participant_Info: + { + if (!(obj is TourneyParticipant part)) + break; + + AddPage(0); + AddBackground(0, 0, 300, 60 + 18 + 20 + part.Players.Count * 18 + 20 + 20 + 160, 9380); + + AddLeftArrow(25, 11, ToButtonID(0, 1)); + AddHtml(25, 35, 250, 20, Center("Participants")); + + var y = 53; + + AddHtml(25, y, 200, 20, part.Players.Count == 1 ? "Players" : "Team"); + y += 20; + + for (var i = 0; i < part.Players.Count; ++i) + { + var mob = part.Players[i]; + var name = mob.Name; + + if (m_Tournament.TourneyType != TourneyType.Standard) + if (mob is PlayerMobile pm && pm.DuelPlayer != null) + name = Color(name, pm.DuelPlayer.Eliminated ? 0x6633333 : 0x336666); + + AddRightArrow(35, y, ToButtonID(4, i), name); + y += 18; + } + + AddHtml( + 25, + y, + 200, + 20, + $"Free Advances: {(part.FreeAdvances == 0 ? "None" : part.FreeAdvances.ToString())}" + ); + y += 20; + + AddHtml(25, y, 200, 20, "Log:"); + y += 20; + + var sb = new StringBuilder(); + + for (var i = 0; i < part.Log.Count; ++i) + { + if (sb.Length > 0) + sb.Append("
"); + + sb.Append(part.Log[i]); + } + + if (sb.Length == 0) + sb.Append("Nothing logged yet."); + + AddHtml(25, y, 250, 150, Color(sb.ToString(), BlackColor32), false, true); + + break; + } + case TourneyBracketGumpType.Player_Info: + { + AddPage(0); + AddBackground(0, 0, 300, 300, 9380); + + AddLeftArrow(25, 11, ToButtonID(0, 3)); + AddHtml(25, 35, 250, 20, Center("Participants")); + + if (!(obj is Mobile mob)) + break; + + var ladder = Ladder.Instance; + var entry = ladder?.Find(mob); + + AddHtml(25, 53, 250, 20, $"Name: {mob.Name}"); + AddHtml( + 25, + 73, + 250, + 20, + $"Guild: {(mob.Guild == null ? "None" : $"{mob.Guild.Name} [{mob.Guild.Abbreviation}]")}" + ); + AddHtml(25, 93, 250, 20, $"Rank: {(entry == null ? "N/A" : LadderGump.Rank(entry.Index + 1))}"); + AddHtml(25, 113, 250, 20, $"Level: {(entry == null ? 0 : Ladder.GetLevel(entry.Experience))}"); + AddHtml(25, 133, 250, 20, $"Wins: {entry?.Wins ?? 0:N0}"); + AddHtml(25, 153, 250, 20, $"Losses: {entry?.Losses ?? 0:N0}"); + + break; + } + case TourneyBracketGumpType.Round_List: + { + AddPage(0); + AddBackground(0, 0, 300, 300, 9380); + + AddLeftArrow(25, 11, ToButtonID(0, 0)); + AddHtml(25, 35, 250, 20, Center("Rounds")); + + // List levelsList = m_List != null + // ? Utility.CastListCovariant(m_List) + // : new List(tourney.Pyramid.Levels); + + StartPage(out var index, out var count, out var y, 12); + + for (var i = 0; i < count; ++i, y += 18) + AddRightArrow(25, y, ToButtonID(3, index + i), $"Round #{index + i + 1}"); + + break; + } + case TourneyBracketGumpType.Round_Info: + { + AddPage(0); + AddBackground(0, 0, 300, 300, 9380); + + AddLeftArrow(25, 11, ToButtonID(0, 2)); + AddHtml(25, 35, 250, 20, Center("Rounds")); + + if (!(m_Object is PyramidLevel level)) + break; + + var matchesList = m_List != null + ? Utility.CastListCovariant(m_List) + : new List(level.Matches); + + AddRightArrow( + 25, + 53, + ToButtonID(5, 0), + $"Free Advance: {(level.FreeAdvance == null ? "None" : level.FreeAdvance.NameList)}" + ); + + AddHtml(25, 73, 200, 20, $"{matchesList.Count} Match{(matchesList.Count == 1 ? "" : "es")}"); + + StartPage(out var index, out var count, out var y, 10); + + for (var i = 0; i < count; ++i, y += 18) + { + var match = matchesList[index + i]; + + var color = -1; + + if (match.InProgress) + color = 0x336666; + else if (match.Context != null && match.Winner == null) + color = 0x666666; + + var sb = new StringBuilder(); + + if (m_Tournament.TourneyType == TourneyType.Standard) + for (var j = 0; j < match.Participants.Count; ++j) + { + if (sb.Length > 0) + sb.Append(" vs "); + + var part = match.Participants[j]; + var txt = part.NameList; + + if (color == -1 && match.Context != null && match.Winner == part) + txt = Color(txt, 0x336633); + else if (color == -1 && match.Context != null) + txt = Color(txt, 0x663333); + + sb.Append(txt); + } + else if (m_Tournament.EventController != null || + m_Tournament.TourneyType == TourneyType.RandomTeam || + m_Tournament.TourneyType == TourneyType.RedVsBlue || + m_Tournament.TourneyType == TourneyType.Faction) + for (var j = 0; j < match.Participants.Count; ++j) + { + if (sb.Length > 0) + sb.Append(" vs "); + + var part = match.Participants[j]; + string txt; + + if (m_Tournament.EventController != null) + { + txt = $"Team {m_Tournament.EventController.GetTeamName(j)} ({part.Players.Count})"; + } + else if (m_Tournament.TourneyType == TourneyType.RandomTeam) + { + txt = $"Team {j + 1} ({part.Players.Count})"; + } + else if (m_Tournament.TourneyType == TourneyType.Faction) + { + if (m_Tournament.ParticipantsPerMatch == 4) + { + var name = "(null)"; + + switch (j) + { + case 0: + { + name = "Minax"; + break; + } + case 1: + { + name = "Council of Mages"; + break; + } + case 2: + { + name = "True Britannians"; + break; + } + case 3: + { + name = "Shadowlords"; + break; + } + } + + txt = $"{name} ({part.Players.Count})"; + } + else if (m_Tournament.ParticipantsPerMatch == 2) + { + txt = $"{(j == 0 ? "Evil" : "Hero")} Team ({part.Players.Count})"; + } + else + { + txt = $"Team {j + 1} ({part.Players.Count})"; + } + } + else + { + txt = $"Team {(j == 0 ? "Red" : "Blue")} ({part.Players.Count})"; + } + + if (color == -1 && match.Context != null && match.Winner == part) + txt = Color(txt, 0x336633); + else if (color == -1 && match.Context != null) + txt = Color(txt, 0x663333); + + sb.Append(txt); + } + else if (m_Tournament.TourneyType == TourneyType.FreeForAll) sb.Append("Free For All"); + + var str = sb.ToString(); + + if (color >= 0) + str = Color(str, color); + + AddRightArrow(25, y, ToButtonID(5, index + i + 1), str); + } + + break; + } + case TourneyBracketGumpType.Match_Info: + { + if (!(obj is TourneyMatch match)) + break; + + var ct = m_Tournament.TourneyType == TourneyType.FreeForAll ? 2 : match.Participants.Count; + + AddPage(0); + AddBackground(0, 0, 300, 60 + 18 + 20 + 20 + 20 + ct * 18 + 6, 9380); + + AddLeftArrow(25, 11, ToButtonID(0, 5)); + AddHtml(25, 35, 250, 20, Center("Rounds")); + + AddHtml(25, 53, 250, 20, $"Winner: {(match.Winner == null ? "N/A" : match.Winner.NameList)}"); + AddHtml( + 25, + 73, + 250, + 20, + $"State: {(match.InProgress ? "In progress" : match.Context != null ? "Complete" : "Waiting")}" + ); + AddHtml(25, 93, 250, 20, "Participants:"); + + if (m_Tournament.TourneyType == TourneyType.Standard) + for (var i = 0; i < match.Participants.Count; ++i) + { + var part = match.Participants[i]; + + AddRightArrow(25, 113 + i * 18, ToButtonID(6, i), part.NameList); + } + else if (m_Tournament.EventController != null || + m_Tournament.TourneyType == TourneyType.RandomTeam || + m_Tournament.TourneyType == TourneyType.RedVsBlue || + m_Tournament.TourneyType == TourneyType.Faction) + for (var i = 0; i < match.Participants.Count; ++i) + { + var part = match.Participants[i]; + + if (m_Tournament.EventController != null) + { + AddRightArrow( + 25, + 113 + i * 18, + ToButtonID(6, i), + $"Team {m_Tournament.EventController.GetTeamName(i)} ({part.Players.Count})" + ); + } + else if (m_Tournament.TourneyType == TourneyType.RandomTeam) + { + AddRightArrow( + 25, + 113 + i * 18, + ToButtonID(6, i), + $"Team {i + 1} ({part.Players.Count})" + ); + } + else if (m_Tournament.TourneyType == TourneyType.Faction) + { + if (m_Tournament.ParticipantsPerMatch == 4) + { + var name = "(null)"; + + switch (i) + { + case 0: + { + name = "Minax"; + break; + } + case 1: + { + name = "Council of Mages"; + break; + } + case 2: + { + name = "True Britannians"; + break; + } + case 3: + { + name = "Shadowlords"; + break; + } + } + + AddRightArrow( + 25, + 113 + i * 18, + ToButtonID(6, i), + $"{name} ({part.Players.Count})" + ); + } + else if (m_Tournament.ParticipantsPerMatch == 2) + { + AddRightArrow( + 25, + 113 + i * 18, + ToButtonID(6, i), + $"{(i == 0 ? "Evil" : "Hero")} Team ({part.Players.Count})" + ); + } + else + { + AddRightArrow( + 25, + 113 + i * 18, + ToButtonID(6, i), + $"Team {i + 1} ({part.Players.Count})" + ); + } + } + else + { + AddRightArrow( + 25, + 113 + i * 18, + ToButtonID(6, i), + $"Team {(i == 0 ? "Red" : "Blue")} ({part.Players.Count})" + ); + } + } + else if (m_Tournament.TourneyType == TourneyType.FreeForAll) + AddHtml(25, 113, 250, 20, "Free For All"); + + break; + } + } + } + + public string Center(string text) => $"
{text}
"; + + public string Color(string text, int color) => $"{text}"; + + private void AddBorderedText(int x, int y, int width, int height, string text, int color, int borderColor) + { + AddColoredText(x - 1, y - 1, width, height, text, borderColor); + AddColoredText(x - 1, y + 1, width, height, text, borderColor); + AddColoredText(x + 1, y - 1, width, height, text, borderColor); + AddColoredText(x + 1, y + 1, width, height, text, borderColor); + AddColoredText(x, y, width, height, text, color); + } + + private void AddColoredText(int x, int y, int width, int height, string text, int color) + { + if (color == 0) + AddHtml(x, y, width, height, text); + else + AddHtml(x, y, width, height, Color(text, color)); + } + + public void AddRightArrow(int x, int y, int bid, string text) + { + AddButton(x, y, 0x15E1, 0x15E5, bid); + + if (text != null) + AddHtml(x + 20, y - 1, 230, 20, text); + } + + public void AddRightArrow(int x, int y, int bid) + { + AddRightArrow(x, y, bid, null); + } + + public void AddLeftArrow(int x, int y, int bid, string text) + { + AddButton(x, y, 0x15E3, 0x15E7, bid); + + if (text != null) + AddHtml(x + 20, y - 1, 230, 20, text); + } + + public void AddLeftArrow(int x, int y, int bid) + { + AddLeftArrow(x, y, bid, null); + } + + public int ToButtonID(int type, int index) => 1 + index * 7 + type; + + public bool FromButtonID(int bid, out int type, out int index) + { + type = (bid - 1) % 7; + index = (bid - 1) / 7; + return bid >= 1; + } + + public void StartPage(out int index, out int count, out int y, int perPage) + { + m_PerPage = perPage; + + index = Math.Max(m_Page * perPage, 0); + count = Math.Clamp(m_List.Count - index, 0, perPage); + + y = 53 + (12 - perPage) * 18; + + if (m_Page > 0) + AddLeftArrow(242, 35, ToButtonID(1, 0)); + + if ((m_Page + 1) * perPage < m_List.Count) + AddRightArrow(260, 35, ToButtonID(1, 1)); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (!FromButtonID(info.ButtonID, out var type, out var index)) + return; + + switch (type) + { + case 0: + { + switch (index) + { + case 0: + m_From.SendGump( + new TournamentBracketGump(m_From, m_Tournament, TourneyBracketGumpType.Index) + ); + break; + case 1: + m_From.SendGump( + new TournamentBracketGump( + m_From, + m_Tournament, + TourneyBracketGumpType.Participant_List + ) + ); + break; + case 2: + m_From.SendGump( + new TournamentBracketGump(m_From, m_Tournament, TourneyBracketGumpType.Round_List) + ); + break; + case 4: + m_From.SendGump( + new TournamentBracketGump(m_From, m_Tournament, TourneyBracketGumpType.Rules_Info) + ); + break; + case 3: + { + var mob = m_Object as Mobile; + + for (var i = 0; i < m_Tournament.Participants.Count; ++i) + { + var part = m_Tournament.Participants[i]; + + if (part.Players.Contains(mob)) + { + m_From.SendGump( + new TournamentBracketGump( + m_From, + m_Tournament, + TourneyBracketGumpType.Participant_Info, + null, + 0, + part + ) + ); + break; + } + } + + break; + } + case 5: + { + if (!(m_Object is TourneyMatch match)) + break; + + for (var i = 0; i < m_Tournament.Pyramid.Levels.Count; ++i) + { + var level = m_Tournament.Pyramid.Levels[i]; + + if (level.Matches.Contains(match)) + m_From.SendGump( + new TournamentBracketGump( + m_From, + m_Tournament, + TourneyBracketGumpType.Round_Info, + null, + 0, + level + ) + ); + } + + break; + } + } + + break; + } + case 1: + { + switch (index) + { + case 0: + { + if (m_List != null && m_Page > 0) + m_From.SendGump( + new TournamentBracketGump( + m_From, + m_Tournament, + m_Type, + m_List, + m_Page - 1, + m_Object + ) + ); + + break; + } + case 1: + { + if (m_List != null && (m_Page + 1) * m_PerPage < m_List.Count) + m_From.SendGump( + new TournamentBracketGump( + m_From, + m_Tournament, + m_Type, + m_List, + m_Page + 1, + m_Object + ) + ); + + break; + } + } + + break; + } + case 2: + { + if (m_Type != TourneyBracketGumpType.Participant_List) + break; + + if (index >= 0 && index < m_List.Count) + m_From.SendGump( + new TournamentBracketGump( + m_From, + m_Tournament, + TourneyBracketGumpType.Participant_Info, + null, + 0, + m_List[index] + ) + ); + + break; + } + case 3: + { + if (m_Type != TourneyBracketGumpType.Round_List) + break; + + if (index >= 0 && index < m_List.Count) + m_From.SendGump( + new TournamentBracketGump( + m_From, + m_Tournament, + TourneyBracketGumpType.Round_Info, + null, + 0, + m_List[index] + ) + ); + + break; + } + case 4: + { + if (m_Type != TourneyBracketGumpType.Participant_Info) + break; + + if (m_Object is TourneyParticipant part && index >= 0 && index < part.Players.Count) + m_From.SendGump( + new TournamentBracketGump( + m_From, + m_Tournament, + TourneyBracketGumpType.Player_Info, + null, + 0, + part.Players[index] + ) + ); + + break; + } + case 5: + { + if (m_Type != TourneyBracketGumpType.Round_Info) + break; + + if (!(m_Object is PyramidLevel level)) + break; + + if (index == 0) + { + if (level.FreeAdvance != null) + m_From.SendGump( + new TournamentBracketGump( + m_From, + m_Tournament, + TourneyBracketGumpType.Participant_Info, + null, + 0, + level.FreeAdvance + ) + ); + else + m_From.SendGump( + new TournamentBracketGump(m_From, m_Tournament, m_Type, m_List, m_Page, m_Object) + ); + } + else if (index >= 1 && index <= level.Matches.Count) + { + m_From.SendGump( + new TournamentBracketGump( + m_From, + m_Tournament, + TourneyBracketGumpType.Match_Info, + null, + 0, + level.Matches[index - 1] + ) + ); + } + + break; + } + case 6: + { + if (m_Type != TourneyBracketGumpType.Match_Info) + break; + + if (m_Object is TourneyMatch match && index >= 0 && index < match.Participants.Count) + m_From.SendGump( + new TournamentBracketGump( + m_From, + m_Tournament, + TourneyBracketGumpType.Participant_Info, + null, + 0, + match.Participants[index] + ) + ); + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Ladder.cs b/Projects/UOContent/Engines/ConPVP/Ladder.cs index 8aae31ee9..60bd341bd 100644 --- a/Projects/UOContent/Engines/ConPVP/Ladder.cs +++ b/Projects/UOContent/Engines/ConPVP/Ladder.cs @@ -1,357 +1,357 @@ -using System; -using System.Collections.Generic; - -namespace Server.Engines.ConPVP -{ - public class LadderController : Item - { - [Constructible] - public LadderController() : base(0x1B7A) - { - Visible = false; - Movable = false; - - Ladder = new Ladder(); - - Ladder.Instance ??= Ladder; - } - - public LadderController(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.Administrator)] - public Ladder Ladder { get; private set; } - - public override string DefaultName => "ladder controller"; - - public override void Delete() - { - if (Ladder.Instance == Ladder) - Ladder.Instance = null; - - base.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - - Ladder.Serialize(writer); - - writer.Write(Ladder.Instance == Ladder); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - case 0: - { - Ladder = new Ladder(reader); - - if (version < 1 || reader.ReadBool()) - Ladder.Instance = Ladder; - - break; - } - } - } - } - - public class Ladder - { - private static readonly int[] m_ShortLevels = - { - 1, - 2, - 3, 3, - 4, 4, - 5, 5, 5, - 6, 6, 6, - 7, 7, 7, 7, - 8, 8, 8, 8, - 9, 9, 9, 9, 9 - }; - - private static readonly int[] m_BaseXP = - { - 0, 100, 200, 400, 600, 900, 1200, 1600, 2000, 2500 - }; - - private static readonly int[] m_LossFactors = - { - 10, - 11, 11, - 25, 25, - 43, 43, - 67, 67 - }; - - private static readonly int[,] m_OffsetScalar = - { - /* { win, los } */ - /* -6 */ { 175, 25 }, - /* -5 */ { 165, 35 }, - /* -4 */ { 155, 45 }, - /* -3 */ { 145, 55 }, - /* -2 */ { 130, 70 }, - /* -1 */ { 115, 85 }, - /* 0 */ { 100, 100 }, - /* +1 */ { 90, 110 }, - /* +2 */ { 80, 120 }, - /* +3 */ { 70, 130 }, - /* +4 */ { 60, 140 }, - /* +5 */ { 50, 150 }, - /* +6 */ { 40, 160 } - }; - - public List Entries { get; } = new List(); - - private readonly Dictionary m_Table; - - public Ladder() => m_Table = new Dictionary(); - - public Ladder(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 1: - case 0: - { - int count = reader.ReadEncodedInt(); - - m_Table = new Dictionary(count); - Entries = new List(count); - - for (int i = 0; i < count; ++i) - { - LadderEntry entry = new LadderEntry(reader, this, version); - - if (entry.Mobile != null) - { - m_Table[entry.Mobile] = entry; - entry.Index = Entries.Count; - Entries.Add(entry); - } - } - - if (version == 0) - { - Entries.Sort(); - - for (int i = 0; i < Entries.Count; ++i) - { - LadderEntry entry = Entries[i]; - - entry.Index = i; - } - } - - break; - } - } - } - - public static Ladder Instance { get; set; } - - public static int GetLevel(int xp) - { - if (xp >= 22500) - return 50; - if (xp >= 2500) - return 10 + (xp - 2500) / 500; - - return m_ShortLevels[Math.Max(xp, 0) / 100]; - } - - public static void GetLevelInfo(int level, out int xpBase, out int xpAdvance) - { - if (level >= 10) - { - xpBase = 2500 + (level - 10) * 500; - xpAdvance = 500; - } - else - { - xpBase = m_BaseXP[level - 1]; - xpAdvance = m_BaseXP[level] - xpBase; - } - } - - public static int GetLossFactor(int level) - { - if (level >= 10) - return 100; - - return m_LossFactors[level - 1]; - } - - public static int GetOffsetScalar(int ourLevel, int theirLevel, bool win) - { - int x = ourLevel - theirLevel; - - if (x < -6 || x > +6) - return 0; - - int y = win ? 0 : 1; - - return m_OffsetScalar[x + 6, y]; - } - - public static int GetExperienceGain(LadderEntry us, LadderEntry them, bool weWon) - { - if (us == null || them == null) - return 0; - - int ourLevel = GetLevel(us.Experience); - int theirLevel = GetLevel(them.Experience); - - int scalar = GetOffsetScalar(ourLevel, theirLevel, weWon); - - if (scalar == 0) - return 0; - - int xp = 25 * scalar; - - if (!weWon) - xp = xp * GetLossFactor(ourLevel) / 100; - - xp /= 100; - - if (xp <= 0) - xp = 1; - - return xp * (weWon ? 1 : -1); - } - - private int Swap(int idx, int newIdx) - { - LadderEntry hold = Entries[idx]; - - Entries[idx] = Entries[newIdx]; - Entries[newIdx] = hold; - - Entries[idx].Index = idx; - Entries[newIdx].Index = newIdx; - - return newIdx; - } - - public void UpdateEntry(LadderEntry entry) - { - int index = entry.Index; - - if (index >= 0 && index < Entries.Count) - { - while (index - 1 >= 0 && entry.CompareTo(Entries[index - 1]) < 0) - index = Swap(index, index - 1); - - while (index + 1 < Entries.Count && entry.CompareTo(Entries[index + 1]) > 0) - index = Swap(index, index + 1); - } - } - - public LadderEntry Find(Mobile mob) - { - if (m_Table.TryGetValue(mob, out LadderEntry entry)) - { - m_Table[mob] = entry = new LadderEntry(mob, this); - entry.Index = Entries.Count; - Entries.Add(entry); - } - - return entry; - } - - public LadderEntry FindNoCreate(Mobile mob) - { - m_Table.TryGetValue(mob, out LadderEntry entry); - return entry; - } - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(1); // version; - - writer.WriteEncodedInt(Entries.Count); - - for (int i = 0; i < Entries.Count; ++i) - Entries[i].Serialize(writer); - } - } - - public class LadderEntry : IComparable - { - private int m_Experience; - private readonly Ladder m_Ladder; - - public LadderEntry(Mobile mob, Ladder ladder) - { - m_Ladder = ladder; - Mobile = mob; - } - - public LadderEntry(IGenericReader reader, Ladder ladder, int version) - { - m_Ladder = ladder; - - switch (version) - { - case 1: - case 0: - { - Mobile = reader.ReadMobile(); - m_Experience = reader.ReadEncodedInt(); - Wins = reader.ReadEncodedInt(); - Losses = reader.ReadEncodedInt(); - - break; - } - } - } - - public Mobile Mobile { get; } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public int Experience - { - get => m_Experience; - set - { - m_Experience = value; - m_Ladder.UpdateEntry(this); - } - } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public int Wins { get; set; } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public int Losses { get; set; } - - public int Index { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Rank => Index; - - public int CompareTo(LadderEntry l) => (l?.m_Experience ?? 0) - m_Experience; - - public void Serialize(IGenericWriter writer) - { - writer.Write(Mobile); - writer.WriteEncodedInt(m_Experience); - writer.WriteEncodedInt(Wins); - writer.WriteEncodedInt(Losses); - } - } -} +using System; +using System.Collections.Generic; + +namespace Server.Engines.ConPVP +{ + public class LadderController : Item + { + [Constructible] + public LadderController() : base(0x1B7A) + { + Visible = false; + Movable = false; + + Ladder = new Ladder(); + + Ladder.Instance ??= Ladder; + } + + public LadderController(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.Administrator)] + public Ladder Ladder { get; private set; } + + public override string DefaultName => "ladder controller"; + + public override void Delete() + { + if (Ladder.Instance == Ladder) + Ladder.Instance = null; + + base.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + + Ladder.Serialize(writer); + + writer.Write(Ladder.Instance == Ladder); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + case 0: + { + Ladder = new Ladder(reader); + + if (version < 1 || reader.ReadBool()) + Ladder.Instance = Ladder; + + break; + } + } + } + } + + public class Ladder + { + private static readonly int[] m_ShortLevels = + { + 1, + 2, + 3, 3, + 4, 4, + 5, 5, 5, + 6, 6, 6, + 7, 7, 7, 7, + 8, 8, 8, 8, + 9, 9, 9, 9, 9 + }; + + private static readonly int[] m_BaseXP = + { + 0, 100, 200, 400, 600, 900, 1200, 1600, 2000, 2500 + }; + + private static readonly int[] m_LossFactors = + { + 10, + 11, 11, + 25, 25, + 43, 43, + 67, 67 + }; + + private static readonly int[,] m_OffsetScalar = + { + /* { win, los } */ + /* -6 */ { 175, 25 }, + /* -5 */ { 165, 35 }, + /* -4 */ { 155, 45 }, + /* -3 */ { 145, 55 }, + /* -2 */ { 130, 70 }, + /* -1 */ { 115, 85 }, + /* 0 */ { 100, 100 }, + /* +1 */ { 90, 110 }, + /* +2 */ { 80, 120 }, + /* +3 */ { 70, 130 }, + /* +4 */ { 60, 140 }, + /* +5 */ { 50, 150 }, + /* +6 */ { 40, 160 } + }; + + private readonly Dictionary m_Table; + + public Ladder() => m_Table = new Dictionary(); + + public Ladder(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 1: + case 0: + { + var count = reader.ReadEncodedInt(); + + m_Table = new Dictionary(count); + Entries = new List(count); + + for (var i = 0; i < count; ++i) + { + var entry = new LadderEntry(reader, this, version); + + if (entry.Mobile != null) + { + m_Table[entry.Mobile] = entry; + entry.Index = Entries.Count; + Entries.Add(entry); + } + } + + if (version == 0) + { + Entries.Sort(); + + for (var i = 0; i < Entries.Count; ++i) + { + var entry = Entries[i]; + + entry.Index = i; + } + } + + break; + } + } + } + + public List Entries { get; } = new List(); + + public static Ladder Instance { get; set; } + + public static int GetLevel(int xp) + { + if (xp >= 22500) + return 50; + if (xp >= 2500) + return 10 + (xp - 2500) / 500; + + return m_ShortLevels[Math.Max(xp, 0) / 100]; + } + + public static void GetLevelInfo(int level, out int xpBase, out int xpAdvance) + { + if (level >= 10) + { + xpBase = 2500 + (level - 10) * 500; + xpAdvance = 500; + } + else + { + xpBase = m_BaseXP[level - 1]; + xpAdvance = m_BaseXP[level] - xpBase; + } + } + + public static int GetLossFactor(int level) + { + if (level >= 10) + return 100; + + return m_LossFactors[level - 1]; + } + + public static int GetOffsetScalar(int ourLevel, int theirLevel, bool win) + { + var x = ourLevel - theirLevel; + + if (x < -6 || x > +6) + return 0; + + var y = win ? 0 : 1; + + return m_OffsetScalar[x + 6, y]; + } + + public static int GetExperienceGain(LadderEntry us, LadderEntry them, bool weWon) + { + if (us == null || them == null) + return 0; + + var ourLevel = GetLevel(us.Experience); + var theirLevel = GetLevel(them.Experience); + + var scalar = GetOffsetScalar(ourLevel, theirLevel, weWon); + + if (scalar == 0) + return 0; + + var xp = 25 * scalar; + + if (!weWon) + xp = xp * GetLossFactor(ourLevel) / 100; + + xp /= 100; + + if (xp <= 0) + xp = 1; + + return xp * (weWon ? 1 : -1); + } + + private int Swap(int idx, int newIdx) + { + var hold = Entries[idx]; + + Entries[idx] = Entries[newIdx]; + Entries[newIdx] = hold; + + Entries[idx].Index = idx; + Entries[newIdx].Index = newIdx; + + return newIdx; + } + + public void UpdateEntry(LadderEntry entry) + { + var index = entry.Index; + + if (index >= 0 && index < Entries.Count) + { + while (index - 1 >= 0 && entry.CompareTo(Entries[index - 1]) < 0) + index = Swap(index, index - 1); + + while (index + 1 < Entries.Count && entry.CompareTo(Entries[index + 1]) > 0) + index = Swap(index, index + 1); + } + } + + public LadderEntry Find(Mobile mob) + { + if (m_Table.TryGetValue(mob, out var entry)) + { + m_Table[mob] = entry = new LadderEntry(mob, this); + entry.Index = Entries.Count; + Entries.Add(entry); + } + + return entry; + } + + public LadderEntry FindNoCreate(Mobile mob) + { + m_Table.TryGetValue(mob, out var entry); + return entry; + } + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(1); // version; + + writer.WriteEncodedInt(Entries.Count); + + for (var i = 0; i < Entries.Count; ++i) + Entries[i].Serialize(writer); + } + } + + public class LadderEntry : IComparable + { + private readonly Ladder m_Ladder; + private int m_Experience; + + public LadderEntry(Mobile mob, Ladder ladder) + { + m_Ladder = ladder; + Mobile = mob; + } + + public LadderEntry(IGenericReader reader, Ladder ladder, int version) + { + m_Ladder = ladder; + + switch (version) + { + case 1: + case 0: + { + Mobile = reader.ReadMobile(); + m_Experience = reader.ReadEncodedInt(); + Wins = reader.ReadEncodedInt(); + Losses = reader.ReadEncodedInt(); + + break; + } + } + } + + public Mobile Mobile { get; } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public int Experience + { + get => m_Experience; + set + { + m_Experience = value; + m_Ladder.UpdateEntry(this); + } + } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public int Wins { get; set; } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public int Losses { get; set; } + + public int Index { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Rank => Index; + + public int CompareTo(LadderEntry l) => (l?.m_Experience ?? 0) - m_Experience; + + public void Serialize(IGenericWriter writer) + { + writer.Write(Mobile); + writer.WriteEncodedInt(m_Experience); + writer.WriteEncodedInt(Wins); + writer.WriteEncodedInt(Losses); + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Participant.cs b/Projects/UOContent/Engines/ConPVP/Participant.cs index 686e2a7cd..43f21f712 100644 --- a/Projects/UOContent/Engines/ConPVP/Participant.cs +++ b/Projects/UOContent/Engines/ConPVP/Participant.cs @@ -1,225 +1,233 @@ -using System; -using System.Text; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.ConPVP -{ - public class Participant - { - public Participant(DuelContext context, int count) - { - Context = context; - // m_Stakes = new StakesContainer( context, this ); - Resize(count); - } - - public int Count => Players.Length; - public DuelPlayer[] Players { get; private set; } - - public DuelContext Context { get; } - - public TourneyParticipant TourneyPart { get; set; } - - public int FilledSlots - { - get - { - int count = 0; - - for (int i = 0; i < Players.Length; ++i) - if (Players[i] != null) - ++count; - - return count; - } - } - - public bool HasOpenSlot - { - get - { - for (int i = 0; i < Players.Length; ++i) - if (Players[i] == null) - return true; - - return false; - } - } - - public bool Eliminated - { - get - { - for (int i = 0; i < Players.Length; ++i) - if (Players[i]?.Eliminated == false) - return false; - - return true; - } - } - - public string NameList - { - get - { - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < Players.Length; ++i) - { - if (Players[i] == null) - continue; - - Mobile mob = Players[i].Mobile; - - if (sb.Length > 0) - sb.Append(", "); - - sb.Append(mob.Name); - } - - return sb.Length == 0 ? "Empty" : sb.ToString(); - } - } - - public DuelPlayer Find(Mobile mob) - { - if (mob is PlayerMobile pm) - { - if (pm.DuelContext == Context && pm.DuelPlayer.Participant == this) - return pm.DuelPlayer; - - return null; - } - - for (int i = 0; i < Players.Length; ++i) - if (Players[i]?.Mobile == mob) - return Players[i]; - - return null; - } - - public bool Contains(Mobile mob) => Find(mob) != null; - - public void Broadcast(int hue, string message, string nonLocalOverhead, string localOverhead) - { - for (int i = 0; i < Players.Length; ++i) - if (Players[i] != null) - { - if (message != null) - Players[i].Mobile.SendMessage(hue, message); - - if (nonLocalOverhead != null) - Players[i].Mobile.NonlocalOverheadMessage(MessageType.Regular, hue, false, - string.Format(nonLocalOverhead, Players[i].Mobile.Name, - Players[i].Mobile.Female ? "her" : "his")); - - if (localOverhead != null) - Players[i].Mobile.LocalOverheadMessage(MessageType.Regular, hue, false, localOverhead); - } - } - - public void Nullify(DuelPlayer player) - { - if (player == null) - return; - - int index = Array.IndexOf(Players, player); - - if (index == -1) - return; - - Players[index] = null; - } - - public void Remove(DuelPlayer player) - { - if (player == null) - return; - - int index = Array.IndexOf(Players, player); - - if (index == -1) - return; - - DuelPlayer[] old = Players; - Players = new DuelPlayer[old.Length - 1]; - - for (int i = 0; i < index; ++i) - Players[i] = old[i]; - - for (int i = index + 1; i < old.Length; ++i) - Players[i - 1] = old[i]; - } - - public void Remove(Mobile player) - { - Remove(Find(player)); - } - - public void Add(Mobile player) - { - if (Contains(player)) - return; - - for (int i = 0; i < Players.Length; ++i) - if (Players[i] == null) - { - Players[i] = new DuelPlayer(player, this); - return; - } - - Resize(Players.Length + 1); - Players[^1] = new DuelPlayer(player, this); - } - - public void Resize(int count) - { - DuelPlayer[] old = Players; - Players = new DuelPlayer[count]; - - if (old != null) - { - int ct = 0; - - for (int i = 0; i < old.Length; ++i) - if (old[i] != null && ct < count) - Players[ct++] = old[i]; - } - } - } - - public class DuelPlayer - { - private bool m_Eliminated; - - public DuelPlayer(Mobile mob, Participant p) - { - Mobile = mob; - Participant = p; - - if (mob is PlayerMobile mobile) - mobile.DuelPlayer = this; - } - - public Mobile Mobile { get; } - - public bool Ready { get; set; } - - public bool Eliminated - { - get => m_Eliminated; - set - { - m_Eliminated = value; - if (Participant.Context.m_Tournament != null && m_Eliminated) - { - Participant.Context.m_Tournament.OnEliminated(this); - Mobile.SendEverything(); - } - } - } - - public Participant Participant { get; set; } - } -} +using System; +using System.Text; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.ConPVP +{ + public class Participant + { + public Participant(DuelContext context, int count) + { + Context = context; + // m_Stakes = new StakesContainer( context, this ); + Resize(count); + } + + public int Count => Players.Length; + public DuelPlayer[] Players { get; private set; } + + public DuelContext Context { get; } + + public TourneyParticipant TourneyPart { get; set; } + + public int FilledSlots + { + get + { + var count = 0; + + for (var i = 0; i < Players.Length; ++i) + if (Players[i] != null) + ++count; + + return count; + } + } + + public bool HasOpenSlot + { + get + { + for (var i = 0; i < Players.Length; ++i) + if (Players[i] == null) + return true; + + return false; + } + } + + public bool Eliminated + { + get + { + for (var i = 0; i < Players.Length; ++i) + if (Players[i]?.Eliminated == false) + return false; + + return true; + } + } + + public string NameList + { + get + { + var sb = new StringBuilder(); + + for (var i = 0; i < Players.Length; ++i) + { + if (Players[i] == null) + continue; + + var mob = Players[i].Mobile; + + if (sb.Length > 0) + sb.Append(", "); + + sb.Append(mob.Name); + } + + return sb.Length == 0 ? "Empty" : sb.ToString(); + } + } + + public DuelPlayer Find(Mobile mob) + { + if (mob is PlayerMobile pm) + { + if (pm.DuelContext == Context && pm.DuelPlayer.Participant == this) + return pm.DuelPlayer; + + return null; + } + + for (var i = 0; i < Players.Length; ++i) + if (Players[i]?.Mobile == mob) + return Players[i]; + + return null; + } + + public bool Contains(Mobile mob) => Find(mob) != null; + + public void Broadcast(int hue, string message, string nonLocalOverhead, string localOverhead) + { + for (var i = 0; i < Players.Length; ++i) + if (Players[i] != null) + { + if (message != null) + Players[i].Mobile.SendMessage(hue, message); + + if (nonLocalOverhead != null) + Players[i] + .Mobile.NonlocalOverheadMessage( + MessageType.Regular, + hue, + false, + string.Format( + nonLocalOverhead, + Players[i].Mobile.Name, + Players[i].Mobile.Female ? "her" : "his" + ) + ); + + if (localOverhead != null) + Players[i].Mobile.LocalOverheadMessage(MessageType.Regular, hue, false, localOverhead); + } + } + + public void Nullify(DuelPlayer player) + { + if (player == null) + return; + + var index = Array.IndexOf(Players, player); + + if (index == -1) + return; + + Players[index] = null; + } + + public void Remove(DuelPlayer player) + { + if (player == null) + return; + + var index = Array.IndexOf(Players, player); + + if (index == -1) + return; + + var old = Players; + Players = new DuelPlayer[old.Length - 1]; + + for (var i = 0; i < index; ++i) + Players[i] = old[i]; + + for (var i = index + 1; i < old.Length; ++i) + Players[i - 1] = old[i]; + } + + public void Remove(Mobile player) + { + Remove(Find(player)); + } + + public void Add(Mobile player) + { + if (Contains(player)) + return; + + for (var i = 0; i < Players.Length; ++i) + if (Players[i] == null) + { + Players[i] = new DuelPlayer(player, this); + return; + } + + Resize(Players.Length + 1); + Players[^1] = new DuelPlayer(player, this); + } + + public void Resize(int count) + { + var old = Players; + Players = new DuelPlayer[count]; + + if (old != null) + { + var ct = 0; + + for (var i = 0; i < old.Length; ++i) + if (old[i] != null && ct < count) + Players[ct++] = old[i]; + } + } + } + + public class DuelPlayer + { + private bool m_Eliminated; + + public DuelPlayer(Mobile mob, Participant p) + { + Mobile = mob; + Participant = p; + + if (mob is PlayerMobile mobile) + mobile.DuelPlayer = this; + } + + public Mobile Mobile { get; } + + public bool Ready { get; set; } + + public bool Eliminated + { + get => m_Eliminated; + set + { + m_Eliminated = value; + if (Participant.Context.m_Tournament != null && m_Eliminated) + { + Participant.Context.m_Tournament.OnEliminated(this); + Mobile.SendEverything(); + } + } + } + + public Participant Participant { get; set; } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Preferences.cs b/Projects/UOContent/Engines/ConPVP/Preferences.cs index 625893e1a..081861510 100644 --- a/Projects/UOContent/Engines/ConPVP/Preferences.cs +++ b/Projects/UOContent/Engines/ConPVP/Preferences.cs @@ -1,271 +1,271 @@ -using System.Collections.Generic; -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.ConPVP -{ - public class PreferencesController : Item - { - [Constructible] - public PreferencesController() : base(0x1B7A) - { - Visible = false; - Movable = false; - - Preferences = new Preferences(); - - if (Preferences.Instance == null) - Preferences.Instance = Preferences; - else - Delete(); - } - - public PreferencesController(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.Administrator)] - public Preferences Preferences { get; private set; } - - public override string DefaultName => "preferences controller"; - - public override void Delete() - { - if (Preferences.Instance != Preferences) - base.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - Preferences.Serialize(writer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Preferences = new Preferences(reader); - Preferences.Instance = Preferences; - break; - } - } - } - } - - public class Preferences - { - private readonly Dictionary m_Table; - - public Preferences() - { - m_Table = new Dictionary(); - Entries = new List(); - } - - public Preferences(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 0: - { - int count = reader.ReadEncodedInt(); - - m_Table = new Dictionary(count); - Entries = new List(count); - - for (int i = 0; i < count; ++i) - { - PreferencesEntry entry = new PreferencesEntry(reader, version); - - if (entry.Mobile != null) - { - m_Table[entry.Mobile] = entry; - Entries.Add(entry); - } - } - - break; - } - } - } - - public List Entries { get; } - - public static Preferences Instance { get; set; } - - public PreferencesEntry Find(Mobile mob) - { - if (m_Table.TryGetValue(mob, out PreferencesEntry entry)) - { - m_Table[mob] = entry = new PreferencesEntry(mob); - Entries.Add(entry); - } - - return entry; - } - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version; - - writer.WriteEncodedInt(Entries.Count); - - for (int i = 0; i < Entries.Count; ++i) - Entries[i].Serialize(writer); - } - } - - public class PreferencesEntry - { - public PreferencesEntry(Mobile mob) - { - Mobile = mob; - Disliked = new List(); - } - - public PreferencesEntry(IGenericReader reader, int version) - { - switch (version) - { - case 0: - { - Mobile = reader.ReadMobile(); - - int count = reader.ReadEncodedInt(); - - Disliked = new List(count); - - for (int i = 0; i < count; ++i) - Disliked.Add(reader.ReadString()); - - break; - } - } - } - - public Mobile Mobile { get; } - - public List Disliked { get; } - - public void Serialize(IGenericWriter writer) - { - writer.Write(Mobile); - - writer.WriteEncodedInt(Disliked.Count); - - for (int i = 0; i < Disliked.Count; ++i) - writer.Write(Disliked[i]); - } - } - - public class PreferencesGump : Gump - { - private int m_ColumnX = 12; - private readonly PreferencesEntry m_Entry; - - public PreferencesGump(Mobile from, Preferences prefs) : base(50, 50) - { - m_Entry = prefs.Find(from); - - if (m_Entry == null) - return; - - List arenas = Arena.Arenas; - - AddPage(0); - - int height = 12 + 20 + arenas.Count * 31 + 24 + 12; - - AddBackground(0, 0, 499 + 40 - 365, height, 0x2436); - - for (int i = 1; i < arenas.Count; i += 2) - AddImageTiled(12, 32 + i * 31, 475 + 40 - 365, 30, 0x2430); - - AddAlphaRegion(10, 10, 479 + 40 - 365, height - 20); - - AddColumnHeader(35, null); - AddColumnHeader(115, "Arena"); - - AddButton(499 + 40 - 365 - 12 - 63 - 4 - 63, height - 12 - 24, 247, 248, 1); - AddButton(499 + 40 - 365 - 12 - 63, height - 12 - 24, 241, 242, 2); - - for (int i = 0; i < arenas.Count; ++i) - { - Arena ar = arenas[i]; - - string name = ar.Name ?? "(no name)"; - - int x = 12; - int y = 32 + i * 31; - - int color = 0xCCFFCC; - - AddCheck(x + 3, y + 1, 9730, 9727, m_Entry.Disliked.Contains(name), i); - x += 35; - - AddBorderedText(x + 5, y + 5, 115 - 5, name, color, 0); - } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Entry == null) - return; - - if (info.ButtonID != 1) - return; - - m_Entry.Disliked.Clear(); - - List arenas = Arena.Arenas; - - for (int i = 0; i < info.Switches.Length; ++i) - { - int idx = info.Switches[i]; - - if (idx >= 0 && idx < arenas.Count) - m_Entry.Disliked.Add(arenas[idx].Name); - } - } - - public string Center(string text) => $"
{text}
"; - - public string Color(string text, int color) => $"{text}"; - - private void AddBorderedText(int x, int y, int width, string text, int color, int borderColor) - { - AddColoredText(x, y, width, text, color); - } - - private void AddColoredText(int x, int y, int width, string text, int color) - { - if (color == 0) - AddHtml(x, y, width, 20, text); - else - AddHtml(x, y, width, 20, Color(text, color)); - } - - private void AddColumnHeader(int width, string name) - { - AddBackground(m_ColumnX, 12, width, 20, 0x242C); - AddImageTiled(m_ColumnX + 2, 14, width - 4, 16, 0x2430); - - if (name != null) - AddBorderedText(m_ColumnX, 13, width, Center(name), 0xFFFFFF, 0); - - m_ColumnX += width; - } - } -} +using System.Collections.Generic; +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.ConPVP +{ + public class PreferencesController : Item + { + [Constructible] + public PreferencesController() : base(0x1B7A) + { + Visible = false; + Movable = false; + + Preferences = new Preferences(); + + if (Preferences.Instance == null) + Preferences.Instance = Preferences; + else + Delete(); + } + + public PreferencesController(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.Administrator)] + public Preferences Preferences { get; private set; } + + public override string DefaultName => "preferences controller"; + + public override void Delete() + { + if (Preferences.Instance != Preferences) + base.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + Preferences.Serialize(writer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Preferences = new Preferences(reader); + Preferences.Instance = Preferences; + break; + } + } + } + } + + public class Preferences + { + private readonly Dictionary m_Table; + + public Preferences() + { + m_Table = new Dictionary(); + Entries = new List(); + } + + public Preferences(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 0: + { + var count = reader.ReadEncodedInt(); + + m_Table = new Dictionary(count); + Entries = new List(count); + + for (var i = 0; i < count; ++i) + { + var entry = new PreferencesEntry(reader, version); + + if (entry.Mobile != null) + { + m_Table[entry.Mobile] = entry; + Entries.Add(entry); + } + } + + break; + } + } + } + + public List Entries { get; } + + public static Preferences Instance { get; set; } + + public PreferencesEntry Find(Mobile mob) + { + if (m_Table.TryGetValue(mob, out var entry)) + { + m_Table[mob] = entry = new PreferencesEntry(mob); + Entries.Add(entry); + } + + return entry; + } + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version; + + writer.WriteEncodedInt(Entries.Count); + + for (var i = 0; i < Entries.Count; ++i) + Entries[i].Serialize(writer); + } + } + + public class PreferencesEntry + { + public PreferencesEntry(Mobile mob) + { + Mobile = mob; + Disliked = new List(); + } + + public PreferencesEntry(IGenericReader reader, int version) + { + switch (version) + { + case 0: + { + Mobile = reader.ReadMobile(); + + var count = reader.ReadEncodedInt(); + + Disliked = new List(count); + + for (var i = 0; i < count; ++i) + Disliked.Add(reader.ReadString()); + + break; + } + } + } + + public Mobile Mobile { get; } + + public List Disliked { get; } + + public void Serialize(IGenericWriter writer) + { + writer.Write(Mobile); + + writer.WriteEncodedInt(Disliked.Count); + + for (var i = 0; i < Disliked.Count; ++i) + writer.Write(Disliked[i]); + } + } + + public class PreferencesGump : Gump + { + private readonly PreferencesEntry m_Entry; + private int m_ColumnX = 12; + + public PreferencesGump(Mobile from, Preferences prefs) : base(50, 50) + { + m_Entry = prefs.Find(from); + + if (m_Entry == null) + return; + + var arenas = Arena.Arenas; + + AddPage(0); + + var height = 12 + 20 + arenas.Count * 31 + 24 + 12; + + AddBackground(0, 0, 499 + 40 - 365, height, 0x2436); + + for (var i = 1; i < arenas.Count; i += 2) + AddImageTiled(12, 32 + i * 31, 475 + 40 - 365, 30, 0x2430); + + AddAlphaRegion(10, 10, 479 + 40 - 365, height - 20); + + AddColumnHeader(35, null); + AddColumnHeader(115, "Arena"); + + AddButton(499 + 40 - 365 - 12 - 63 - 4 - 63, height - 12 - 24, 247, 248, 1); + AddButton(499 + 40 - 365 - 12 - 63, height - 12 - 24, 241, 242, 2); + + for (var i = 0; i < arenas.Count; ++i) + { + var ar = arenas[i]; + + var name = ar.Name ?? "(no name)"; + + var x = 12; + var y = 32 + i * 31; + + var color = 0xCCFFCC; + + AddCheck(x + 3, y + 1, 9730, 9727, m_Entry.Disliked.Contains(name), i); + x += 35; + + AddBorderedText(x + 5, y + 5, 115 - 5, name, color, 0); + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Entry == null) + return; + + if (info.ButtonID != 1) + return; + + m_Entry.Disliked.Clear(); + + var arenas = Arena.Arenas; + + for (var i = 0; i < info.Switches.Length; ++i) + { + var idx = info.Switches[i]; + + if (idx >= 0 && idx < arenas.Count) + m_Entry.Disliked.Add(arenas[idx].Name); + } + } + + public string Center(string text) => $"
{text}
"; + + public string Color(string text, int color) => $"{text}"; + + private void AddBorderedText(int x, int y, int width, string text, int color, int borderColor) + { + AddColoredText(x, y, width, text, color); + } + + private void AddColoredText(int x, int y, int width, string text, int color) + { + if (color == 0) + AddHtml(x, y, width, 20, text); + else + AddHtml(x, y, width, 20, Color(text, color)); + } + + private void AddColumnHeader(int width, string name) + { + AddBackground(m_ColumnX, 12, width, 20, 0x242C); + AddImageTiled(m_ColumnX + 2, 14, width - 4, 16, 0x2430); + + if (name != null) + AddBorderedText(m_ColumnX, 13, width, Center(name), 0xFFFFFF, 0); + + m_ColumnX += width; + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Ruleset.cs b/Projects/UOContent/Engines/ConPVP/Ruleset.cs index e61beb157..0176cf80d 100644 --- a/Projects/UOContent/Engines/ConPVP/Ruleset.cs +++ b/Projects/UOContent/Engines/ConPVP/Ruleset.cs @@ -1,102 +1,102 @@ -using System.Collections; -using System.Collections.Generic; - -namespace Server.Engines.ConPVP -{ - public class Ruleset - { - public Ruleset(RulesetLayout layout) - { - Layout = layout; - Options = new BitArray(layout.TotalLength); - } - - public RulesetLayout Layout { get; } - - public BitArray Options { get; private set; } - - public string Title { get; set; } - - public Ruleset Base { get; private set; } - - public List Flavors { get; } = new List(); - - public bool Changed { get; set; } - - public void ApplyDefault(Ruleset newDefault) - { - Base = newDefault; - Changed = false; - - Options = new BitArray(newDefault.Options); - - ApplyFlavorsTo(this); - } - - public void ApplyFlavorsTo(Ruleset ruleset) - { - for (int i = 0; i < Flavors.Count; ++i) - { - Ruleset flavor = Flavors[i]; - - Options.Or(flavor.Options); - } - } - - public void AddFlavor(Ruleset flavor) - { - if (Flavors.Contains(flavor)) - return; - - Flavors.Add(flavor); - Options.Or(flavor.Options); - } - - public void RemoveFlavor(Ruleset flavor) - { - if (!Flavors.Contains(flavor)) - return; - - Flavors.Remove(flavor); - Options.And(flavor.Options.Not()); - flavor.Options.Not(); - } - - public void SetOptionRange(string title, bool value) - { - RulesetLayout layout = Layout.FindByTitle(title); - - if (layout == null) - return; - - for (int i = 0; i < layout.TotalLength; ++i) - Options[i + layout.Offset] = value; - - Changed = true; - } - - public bool GetOption(string title, string option) - { - int index = 0; - RulesetLayout layout = Layout.FindByOption(title, option, ref index); - - if (layout == null) - return true; - - return Options[layout.Offset + index]; - } - - public void SetOption(string title, string option, bool value) - { - int index = 0; - RulesetLayout layout = Layout.FindByOption(title, option, ref index); - - if (layout == null) - return; - - Options[layout.Offset + index] = value; - - Changed = true; - } - } -} \ No newline at end of file +using System.Collections; +using System.Collections.Generic; + +namespace Server.Engines.ConPVP +{ + public class Ruleset + { + public Ruleset(RulesetLayout layout) + { + Layout = layout; + Options = new BitArray(layout.TotalLength); + } + + public RulesetLayout Layout { get; } + + public BitArray Options { get; private set; } + + public string Title { get; set; } + + public Ruleset Base { get; private set; } + + public List Flavors { get; } = new List(); + + public bool Changed { get; set; } + + public void ApplyDefault(Ruleset newDefault) + { + Base = newDefault; + Changed = false; + + Options = new BitArray(newDefault.Options); + + ApplyFlavorsTo(this); + } + + public void ApplyFlavorsTo(Ruleset ruleset) + { + for (var i = 0; i < Flavors.Count; ++i) + { + var flavor = Flavors[i]; + + Options.Or(flavor.Options); + } + } + + public void AddFlavor(Ruleset flavor) + { + if (Flavors.Contains(flavor)) + return; + + Flavors.Add(flavor); + Options.Or(flavor.Options); + } + + public void RemoveFlavor(Ruleset flavor) + { + if (!Flavors.Contains(flavor)) + return; + + Flavors.Remove(flavor); + Options.And(flavor.Options.Not()); + flavor.Options.Not(); + } + + public void SetOptionRange(string title, bool value) + { + var layout = Layout.FindByTitle(title); + + if (layout == null) + return; + + for (var i = 0; i < layout.TotalLength; ++i) + Options[i + layout.Offset] = value; + + Changed = true; + } + + public bool GetOption(string title, string option) + { + var index = 0; + var layout = Layout.FindByOption(title, option, ref index); + + if (layout == null) + return true; + + return Options[layout.Offset + index]; + } + + public void SetOption(string title, string option, bool value) + { + var index = 0; + var layout = Layout.FindByOption(title, option, ref index); + + if (layout == null) + return; + + Options[layout.Offset + index] = value; + + Changed = true; + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/RulesetLayout.cs b/Projects/UOContent/Engines/ConPVP/RulesetLayout.cs index 7a6075172..e9fff89e4 100644 --- a/Projects/UOContent/Engines/ConPVP/RulesetLayout.cs +++ b/Projects/UOContent/Engines/ConPVP/RulesetLayout.cs @@ -1,743 +1,871 @@ -using System; -using System.Collections.Generic; - -namespace Server.Engines.ConPVP -{ - public class RulesetLayout - { - private static RulesetLayout m_Root; - - public RulesetLayout(string title, string[] options) : this(title, title, Array.Empty(), options) - { - } - - public RulesetLayout(string title, string description, string[] options) : this(title, description, - Array.Empty(), options) - { - } - - public RulesetLayout(string title, RulesetLayout[] children) : this(title, title, children, Array.Empty()) - { - } - - public RulesetLayout(string title, string description, RulesetLayout[] children) : this(title, description, children, - Array.Empty()) - { - } - - public RulesetLayout(string title, RulesetLayout[] children, string[] options) : this(title, title, children, - options) - { - } - - public RulesetLayout(string title, string description, RulesetLayout[] children, string[] options) - { - Title = title; - Description = description; - Children = children; - Options = options; - - for (int i = 0; i < children.Length; ++i) - children[i].Parent = this; - } - - public static RulesetLayout Root - { - get - { - if (m_Root != null) - return m_Root; - - List entries = new List - { - new RulesetLayout("Spells", - new[] - { - new RulesetLayout("1st Circle", "Spells", - new[] - { - "Reactive Armor", "Clumsy", "Create Food", "Feeblemind", "Heal", "Magic Arrow", "Night Sight", - "Weaken" - }), - new RulesetLayout("2nd Circle", "Spells", - new[] { "Agility", "Cunning", "Cure", "Harm", "Magic Trap", "Untrap", "Protection", "Strength" }), - new RulesetLayout("3rd Circle", "Spells", - new[] - { - "Bless", "Fireball", "Magic Lock", "Poison", "Telekinesis", "Teleport", "Unlock Spell", - "Wall of Stone" - }), - new RulesetLayout("4th Circle", "Spells", - new[] - { - "Arch Cure", "Arch Protection", "Curse", "Fire Field", "Greater Heal", "Lightning", "Mana Drain", - "Recall" - }), - new RulesetLayout("5th Circle", "Spells", - new[] - { - "Blade Spirits", "Dispel Field", "Incognito", "Magic Reflection", "Mind Blast", "Paralyze", - "Poison Field", "Summon Creature" - }), - new RulesetLayout("6th Circle", "Spells", - new[] - { - "Dispel", "Energy Bolt", "Explosion", "Invisibility", "Mark", "Mass Curse", "Paralyze Field", - "Reveal" - }), - new RulesetLayout("7th Circle", "Spells", - new[] - { - "Chain Lightning", "Energy Field", "Flame Strike", "Gate Travel", "Mana Vampire", "Mass Dispel", - "Meteor Swarm", "Polymorph" - }), - new RulesetLayout("8th Circle", "Spells", - new[] - { - "Earthquake", "Energy Vortex", "Resurrection", "Air Elemental", "Summon Daemon", "Earth Elemental", - "Fire Elemental", "Water Elemental" - }) - }) - }; - - if (Core.AOS) - { - entries.Add(new RulesetLayout("Chivalry", new[] - { - "Cleanse by Fire", - "Close Wounds", - "Consecrate Weapon", - "Dispel Evil", - "Divine Fury", - "Enemy of One", - "Holy Light", - "Noble Sacrifice", - "Remove Curse", - "Sacred Journey" - })); - - entries.Add(new RulesetLayout("Necromancy", new[] - { - "Animate Dead", - "Blood Oath", - "Corpse Skin", - "Curse Weapon", - "Evil Omen", - "Horrific Beast", - "Lich Form", - "Mind Rot", - "Pain Spike", - "Poison Strike", - "Strangle", - "Summon Familiar", - "Vampiric Embrace", - "Vengeful Spirit", - "Wither", - "Wraith Form" - })); - - if (Core.SE) - { - entries.Add(new RulesetLayout("Bushido", new[] - { - "Confidence", - "Counter Attack", - "Evasion", - "Honorable Execution", - "Lightning Strike", - "Momentum Strike" - })); - - entries.Add(new RulesetLayout("Ninjitsu", new[] - { - "Animal Form", - "Backstab", - "Death Strike", - "Focus Attack", - "Ki Attack", - "Mirror Image", - "Shadow Jump", - "Suprise Attack" - })); - - if (Core.ML) - entries.Add(new RulesetLayout("Spellweaving", new[] - { - "Arcane Circle", - "Arcane Empowerment", - "Attune Weapon", - "Dryad Allure", - "Essence of Wind", - "Ethereal Voyage", - "Gift of Life", - "Gift of Renewal", - "Immolating Weapon", - "Nature's Fury", - "Reaper Form", - "Summon Fey", - "Summon Fiend", - "Thunderstorm", - "Wildfire", - "Word of Death" - })); - } - } - - if (Core.AOS) - { - if (Core.SE) - entries.Add(new RulesetLayout("Combat Abilities", new[] - { - "Stun", - "Disarm", - "Armor Ignore", - "Bleed Attack", - "Concussion Blow", - "Crushing Blow", - "Disarm", - "Dismount", - "Double Strike", - "Infectious Strike", - "Mortal Strike", - "Moving Shot", - "Paralyzing Blow", - "Shadow Strike", - "Whirlwind Attack", - "Riding Swipe", - "Frenzied Whirlwind", - "Block", - "Defense Mastery", - "Nerve Strike", - "Talon Strike", - "Feint", - "Dual Wield", - "Double Shot", - "Armor Pierce" - })); - else - entries.Add(new RulesetLayout("Combat Abilities", new[] - { - "Stun", - "Disarm", - "Armor Ignore", - "Bleed Attack", - "Concussion Blow", - "Crushing Blow", - "Disarm", - "Dismount", - "Double Strike", - "Infectious Strike", - "Mortal Strike", - "Moving Shot", - "Paralyzing Blow", - "Shadow Strike", - "Whirlwind Attack" - })); - } - else - { - entries.Add(new RulesetLayout("Combat Abilities", new[] - { - "Stun", - "Disarm", - "Concussion Blow", - "Crushing Blow", - "Paralyzing Blow" - })); - } - - entries.Add(new RulesetLayout("Skills", new[] - { - "Anatomy", - "Detect Hidden", - "Evaluating Intelligence", - "Hiding", - "Poisoning", - "Snooping", - "Stealing", - "Spirit Speak", - "Stealth" - })); - - if (Core.AOS) - { - entries.Add(new RulesetLayout("Weapons", new[] - { - "Magical", - "Melee", - "Ranged", - "Poisoned", - "Wrestling" - })); - - entries.Add(new RulesetLayout("Armor", new[] - { - "Magical", - "Shields" - })); - } - else - { - entries.Add(new RulesetLayout("Weapons", new[] - { - "Magical", - "Melee", - "Ranged", - "Poisoned", - "Wrestling", - "Runics" - })); - - entries.Add(new RulesetLayout("Armor", new[] - { - "Magical", - "Shields", - "Colored" - })); - } - - if (Core.SE) - entries.Add(new RulesetLayout("Items", new[] - { - new RulesetLayout("Potions", new[] - { - "Agility", - "Cure", - "Explosion", - "Heal", - "Nightsight", - "Poison", - "Refresh", - "Strength" - }) - }, - new[] - { - "Bandages", - "Wands", - "Trapped Containers", - "Bolas", - "Mounts", - "Orange Petals", - "Shurikens", - "Fukiya Darts", - "Fire Horns" - })); - else - entries.Add(new RulesetLayout("Items", new[] - { - new RulesetLayout("Potions", new[] - { - "Agility", - "Cure", - "Explosion", - "Heal", - "Nightsight", - "Poison", - "Refresh", - "Strength" - }) - }, - new[] - { - "Bandages", - "Wands", - "Trapped Containers", - "Bolas", - "Mounts", - "Orange Petals", - "Fire Horns" - })); - - m_Root = new RulesetLayout("Rules", entries.ToArray()); - m_Root.ComputeOffsets(); - - // Set up default rulesets - - if (!Core.AOS) - { - Ruleset m5x = new Ruleset(m_Root); - - m5x.Title = "Mage 5x"; - - m5x.SetOptionRange("Spells", true); - - m5x.SetOption("Spells", "Wall of Stone", false); - m5x.SetOption("Spells", "Fire Field", false); - m5x.SetOption("Spells", "Poison Field", false); - m5x.SetOption("Spells", "Energy Field", false); - m5x.SetOption("Spells", "Reactive Armor", false); - m5x.SetOption("Spells", "Protection", false); - m5x.SetOption("Spells", "Teleport", false); - m5x.SetOption("Spells", "Wall of Stone", false); - m5x.SetOption("Spells", "Arch Protection", false); - m5x.SetOption("Spells", "Recall", false); - m5x.SetOption("Spells", "Blade Spirits", false); - m5x.SetOption("Spells", "Incognito", false); - m5x.SetOption("Spells", "Magic Reflection", false); - m5x.SetOption("Spells", "Paralyze", false); - m5x.SetOption("Spells", "Summon Creature", false); - m5x.SetOption("Spells", "Invisibility", false); - m5x.SetOption("Spells", "Mark", false); - m5x.SetOption("Spells", "Paralyze Field", false); - m5x.SetOption("Spells", "Energy Field", false); - m5x.SetOption("Spells", "Gate Travel", false); - m5x.SetOption("Spells", "Polymorph", false); - m5x.SetOption("Spells", "Energy Vortex", false); - m5x.SetOption("Spells", "Air Elemental", false); - m5x.SetOption("Spells", "Summon Daemon", false); - m5x.SetOption("Spells", "Earth Elemental", false); - m5x.SetOption("Spells", "Fire Elemental", false); - m5x.SetOption("Spells", "Water Elemental", false); - m5x.SetOption("Spells", "Earthquake", false); - m5x.SetOption("Spells", "Meteor Swarm", false); - m5x.SetOption("Spells", "Chain Lightning", false); - m5x.SetOption("Spells", "Resurrection", false); - - m5x.SetOption("Weapons", "Wrestling", true); - - m5x.SetOption("Skills", "Anatomy", true); - m5x.SetOption("Skills", "Detect Hidden", true); - m5x.SetOption("Skills", "Evaluating Intelligence", true); - - m5x.SetOption("Items", "Trapped Containers", true); - - Ruleset m7x = new Ruleset(m_Root); - - m7x.Title = "Mage 7x"; - - m7x.SetOptionRange("Spells", true); - - m7x.SetOption("Spells", "Wall of Stone", false); - m7x.SetOption("Spells", "Fire Field", false); - m7x.SetOption("Spells", "Poison Field", false); - m7x.SetOption("Spells", "Energy Field", false); - m7x.SetOption("Spells", "Reactive Armor", false); - m7x.SetOption("Spells", "Protection", false); - m7x.SetOption("Spells", "Teleport", false); - m7x.SetOption("Spells", "Wall of Stone", false); - m7x.SetOption("Spells", "Arch Protection", false); - m7x.SetOption("Spells", "Recall", false); - m7x.SetOption("Spells", "Blade Spirits", false); - m7x.SetOption("Spells", "Incognito", false); - m7x.SetOption("Spells", "Magic Reflection", false); - m7x.SetOption("Spells", "Paralyze", false); - m7x.SetOption("Spells", "Summon Creature", false); - m7x.SetOption("Spells", "Invisibility", false); - m7x.SetOption("Spells", "Mark", false); - m7x.SetOption("Spells", "Paralyze Field", false); - m7x.SetOption("Spells", "Energy Field", false); - m7x.SetOption("Spells", "Gate Travel", false); - m7x.SetOption("Spells", "Polymorph", false); - m7x.SetOption("Spells", "Energy Vortex", false); - m7x.SetOption("Spells", "Air Elemental", false); - m7x.SetOption("Spells", "Summon Daemon", false); - m7x.SetOption("Spells", "Earth Elemental", false); - m7x.SetOption("Spells", "Fire Elemental", false); - m7x.SetOption("Spells", "Water Elemental", false); - m7x.SetOption("Spells", "Earthquake", false); - m7x.SetOption("Spells", "Meteor Swarm", false); - m7x.SetOption("Spells", "Chain Lightning", false); - m7x.SetOption("Spells", "Resurrection", false); - - m7x.SetOption("Combat Abilities", "Stun", true); - - m7x.SetOption("Skills", "Anatomy", true); - m7x.SetOption("Skills", "Detect Hidden", true); - m7x.SetOption("Skills", "Poisoning", true); - m7x.SetOption("Skills", "Evaluating Intelligence", true); - - m7x.SetOption("Weapons", "Wrestling", true); - - m7x.SetOption("Potions", "Refresh", true); - m7x.SetOption("Items", "Trapped Containers", true); - m7x.SetOption("Items", "Bandages", true); - - Ruleset s7x = new Ruleset(m_Root); - - s7x.Title = "Standard 7x"; - - s7x.SetOptionRange("Spells", true); - - s7x.SetOption("Spells", "Wall of Stone", false); - s7x.SetOption("Spells", "Fire Field", false); - s7x.SetOption("Spells", "Poison Field", false); - s7x.SetOption("Spells", "Energy Field", false); - s7x.SetOption("Spells", "Teleport", false); - s7x.SetOption("Spells", "Wall of Stone", false); - s7x.SetOption("Spells", "Arch Protection", false); - s7x.SetOption("Spells", "Recall", false); - s7x.SetOption("Spells", "Blade Spirits", false); - s7x.SetOption("Spells", "Incognito", false); - s7x.SetOption("Spells", "Magic Reflection", false); - s7x.SetOption("Spells", "Paralyze", false); - s7x.SetOption("Spells", "Summon Creature", false); - s7x.SetOption("Spells", "Invisibility", false); - s7x.SetOption("Spells", "Mark", false); - s7x.SetOption("Spells", "Paralyze Field", false); - s7x.SetOption("Spells", "Energy Field", false); - s7x.SetOption("Spells", "Gate Travel", false); - s7x.SetOption("Spells", "Polymorph", false); - s7x.SetOption("Spells", "Energy Vortex", false); - s7x.SetOption("Spells", "Air Elemental", false); - s7x.SetOption("Spells", "Summon Daemon", false); - s7x.SetOption("Spells", "Earth Elemental", false); - s7x.SetOption("Spells", "Fire Elemental", false); - s7x.SetOption("Spells", "Water Elemental", false); - s7x.SetOption("Spells", "Earthquake", false); - s7x.SetOption("Spells", "Meteor Swarm", false); - s7x.SetOption("Spells", "Chain Lightning", false); - s7x.SetOption("Spells", "Resurrection", false); - - s7x.SetOptionRange("Combat Abilities", true); - - s7x.SetOption("Skills", "Anatomy", true); - s7x.SetOption("Skills", "Detect Hidden", true); - s7x.SetOption("Skills", "Poisoning", true); - s7x.SetOption("Skills", "Evaluating Intelligence", true); - - s7x.SetOptionRange("Weapons", true); - s7x.SetOption("Weapons", "Runics", false); - s7x.SetOptionRange("Armor", true); - - s7x.SetOption("Potions", "Refresh", true); - s7x.SetOption("Items", "Bandages", true); - s7x.SetOption("Items", "Trapped Containers", true); - - m_Root.Defaults = new[] { m5x, m7x, s7x }; - } - else - { - Ruleset all = new Ruleset(m_Root); - - all.Title = "Standard All Skills"; - - all.SetOptionRange("Spells", true); - - all.SetOption("Spells", "Wall of Stone", false); - all.SetOption("Spells", "Fire Field", false); - all.SetOption("Spells", "Poison Field", false); - all.SetOption("Spells", "Energy Field", false); - all.SetOption("Spells", "Teleport", false); - all.SetOption("Spells", "Wall of Stone", false); - all.SetOption("Spells", "Arch Protection", false); - all.SetOption("Spells", "Recall", false); - all.SetOption("Spells", "Blade Spirits", false); - all.SetOption("Spells", "Incognito", false); - all.SetOption("Spells", "Magic Reflection", false); - all.SetOption("Spells", "Paralyze", false); - all.SetOption("Spells", "Summon Creature", false); - all.SetOption("Spells", "Invisibility", false); - all.SetOption("Spells", "Mark", false); - all.SetOption("Spells", "Paralyze Field", false); - all.SetOption("Spells", "Energy Field", false); - all.SetOption("Spells", "Gate Travel", false); - all.SetOption("Spells", "Polymorph", false); - all.SetOption("Spells", "Energy Vortex", false); - all.SetOption("Spells", "Air Elemental", false); - all.SetOption("Spells", "Summon Daemon", false); - all.SetOption("Spells", "Earth Elemental", false); - all.SetOption("Spells", "Fire Elemental", false); - all.SetOption("Spells", "Water Elemental", false); - all.SetOption("Spells", "Earthquake", false); - all.SetOption("Spells", "Meteor Swarm", false); - all.SetOption("Spells", "Chain Lightning", false); - all.SetOption("Spells", "Resurrection", false); - - all.SetOptionRange("Necromancy", true); - all.SetOption("Necromancy", "Summon Familiar", false); - all.SetOption("Necromancy", "Vengeful Spirit", false); - all.SetOption("Necromancy", "Animate Dead", false); - all.SetOption("Necromancy", "Wither", false); - all.SetOption("Necromancy", "Poison Strike", false); - - all.SetOptionRange("Chivalry", true); - all.SetOption("Chivalry", "Sacred Journey", false); - all.SetOption("Chivalry", "Enemy of One", false); - all.SetOption("Chivalry", "Noble Sacrifice", false); - - all.SetOptionRange("Combat Abilities", true); - all.SetOption("Combat Abilities", "Paralyzing Blow", false); - all.SetOption("Combat Abilities", "Shadow Strike", false); - - all.SetOption("Skills", "Anatomy", true); - all.SetOption("Skills", "Detect Hidden", true); - all.SetOption("Skills", "Poisoning", true); - all.SetOption("Skills", "Spirit Speak", true); - all.SetOption("Skills", "Evaluating Intelligence", true); - - all.SetOptionRange("Weapons", true); - all.SetOption("Weapons", "Poisoned", false); - - all.SetOptionRange("Armor", true); - - all.SetOptionRange("Ninjitsu", true); - all.SetOption("Ninjitsu", "Animal Form", false); - all.SetOption("Ninjitsu", "Mirror Image", false); - all.SetOption("Ninjitsu", "Backstab", false); - all.SetOption("Ninjitsu", "Suprise Attack", false); - all.SetOption("Ninjitsu", "Shadow Jump", false); - - all.SetOptionRange("Bushido", true); - - all.SetOptionRange("Spellweaving", true); - all.SetOption("Spellweaving", "Gift of Life", false); - all.SetOption("Spellweaving", "Summon Fey", false); - all.SetOption("Spellweaving", "Summon Fiend", false); - all.SetOption("Spellweaving", "Nature's Fury", false); - - all.SetOption("Potions", "Refresh", true); - all.SetOption("Items", "Bandages", true); - all.SetOption("Items", "Trapped Containers", true); - - m_Root.Defaults = new[] { all }; - } - - // Set up flavors - - Ruleset pots = new Ruleset(m_Root) { Title = "Potions" }; - - pots.SetOptionRange("Potions", true); - pots.SetOption("Potions", "Explosion", false); - - Ruleset para = new Ruleset(m_Root) { Title = "Paralyze" }; - - para.SetOption("Spells", "Paralyze", true); - para.SetOption("Spells", "Paralyze Field", true); - para.SetOption("Combat Abilities", "Paralyzing Blow", true); - - Ruleset fields = new Ruleset(m_Root) { Title = "Fields" }; - - fields.SetOption("Spells", "Wall of Stone", true); - fields.SetOption("Spells", "Fire Field", true); - fields.SetOption("Spells", "Poison Field", true); - fields.SetOption("Spells", "Energy Field", true); - fields.SetOption("Spells", "Wildfire", true); - - Ruleset area = new Ruleset(m_Root) { Title = "Area Effect" }; - - area.SetOption("Spells", "Earthquake", true); - area.SetOption("Spells", "Meteor Swarm", true); - area.SetOption("Spells", "Chain Lightning", true); - area.SetOption("Necromancy", "Wither", true); - area.SetOption("Necromancy", "Poison Strike", true); - - Ruleset summons = new Ruleset(m_Root) { Title = "Summons" }; - - summons.SetOption("Spells", "Blade Spirits", true); - summons.SetOption("Spells", "Energy Vortex", true); - summons.SetOption("Spells", "Air Elemental", true); - summons.SetOption("Spells", "Summon Daemon", true); - summons.SetOption("Spells", "Earth Elemental", true); - summons.SetOption("Spells", "Fire Elemental", true); - summons.SetOption("Spells", "Water Elemental", true); - summons.SetOption("Necromancy", "Summon Familiar", true); - summons.SetOption("Necromancy", "Vengeful Spirit", true); - summons.SetOption("Necromancy", "Animate Dead", true); - summons.SetOption("Ninjitsu", "Mirror Image", true); - summons.SetOption("Spellweaving", "Summon Fey", true); - summons.SetOption("Spellweaving", "Summon Fiend", true); - summons.SetOption("Spellweaving", "Nature's Fury", true); - - m_Root.Flavors = new[] { pots, para, fields, area, summons }; - - return m_Root; - } - } - - public string Title { get; } - - public string Description { get; } - - public string[] Options { get; } - - public int Offset { get; private set; } - - public int TotalLength { get; private set; } - - public RulesetLayout Parent { get; private set; } - - public RulesetLayout[] Children { get; } - - public Ruleset[] Defaults { get; set; } - - public Ruleset[] Flavors { get; set; } - - public RulesetLayout FindByTitle(string title) - { - if (Title == title) - return this; - - for (int i = 0; i < Children.Length; ++i) - { - RulesetLayout layout = Children[i].FindByTitle(title); - - if (layout != null) - return layout; - } - - return null; - } - - public string FindByIndex(int index) - { - if (index >= Offset && index < Offset + Options.Length) - return $"{Description}: {Options[index - Offset]}"; - - for (int i = 0; i < Children.Length; ++i) - { - string opt = Children[i].FindByIndex(index); - - if (opt != null) - return opt; - } - - return null; - } - - public RulesetLayout FindByOption(string title, string option, ref int index) - { - if (title == null || Title == title) - { - index = GetOptionIndex(option); - - if (index >= 0) - return this; - - title = null; - } - - for (int i = 0; i < Children.Length; ++i) - { - RulesetLayout layout = Children[i].FindByOption(title, option, ref index); - - if (layout != null) - return layout; - } - - return null; - } - - public int GetOptionIndex(string option) => Array.IndexOf(Options, option); - - public void ComputeOffsets() - { - int offset = 0; - - RecurseComputeOffsets(ref offset); - } - - private int RecurseComputeOffsets(ref int offset) - { - Offset = offset; - - offset += Options.Length; - TotalLength += Options.Length; - - for (int i = 0; i < Children.Length; ++i) - TotalLength += Children[i].RecurseComputeOffsets(ref offset); - - return TotalLength; - } - } -} +using System; +using System.Collections.Generic; + +namespace Server.Engines.ConPVP +{ + public class RulesetLayout + { + private static RulesetLayout m_Root; + + public RulesetLayout(string title, string[] options) : this(title, title, Array.Empty(), options) + { + } + + public RulesetLayout(string title, string description, string[] options) : this( + title, + description, + Array.Empty(), + options + ) + { + } + + public RulesetLayout(string title, RulesetLayout[] children) : this(title, title, children, Array.Empty()) + { + } + + public RulesetLayout(string title, string description, RulesetLayout[] children) : this( + title, + description, + children, + Array.Empty() + ) + { + } + + public RulesetLayout(string title, RulesetLayout[] children, string[] options) : this( + title, + title, + children, + options + ) + { + } + + public RulesetLayout(string title, string description, RulesetLayout[] children, string[] options) + { + Title = title; + Description = description; + Children = children; + Options = options; + + for (var i = 0; i < children.Length; ++i) + children[i].Parent = this; + } + + public static RulesetLayout Root + { + get + { + if (m_Root != null) + return m_Root; + + var entries = new List + { + new RulesetLayout( + "Spells", + new[] + { + new RulesetLayout( + "1st Circle", + "Spells", + new[] + { + "Reactive Armor", "Clumsy", "Create Food", "Feeblemind", "Heal", "Magic Arrow", + "Night Sight", + "Weaken" + } + ), + new RulesetLayout( + "2nd Circle", + "Spells", + new[] + { + "Agility", "Cunning", "Cure", "Harm", "Magic Trap", "Untrap", "Protection", "Strength" + } + ), + new RulesetLayout( + "3rd Circle", + "Spells", + new[] + { + "Bless", "Fireball", "Magic Lock", "Poison", "Telekinesis", "Teleport", "Unlock Spell", + "Wall of Stone" + } + ), + new RulesetLayout( + "4th Circle", + "Spells", + new[] + { + "Arch Cure", "Arch Protection", "Curse", "Fire Field", "Greater Heal", "Lightning", + "Mana Drain", + "Recall" + } + ), + new RulesetLayout( + "5th Circle", + "Spells", + new[] + { + "Blade Spirits", "Dispel Field", "Incognito", "Magic Reflection", "Mind Blast", + "Paralyze", + "Poison Field", "Summon Creature" + } + ), + new RulesetLayout( + "6th Circle", + "Spells", + new[] + { + "Dispel", "Energy Bolt", "Explosion", "Invisibility", "Mark", "Mass Curse", + "Paralyze Field", + "Reveal" + } + ), + new RulesetLayout( + "7th Circle", + "Spells", + new[] + { + "Chain Lightning", "Energy Field", "Flame Strike", "Gate Travel", "Mana Vampire", + "Mass Dispel", + "Meteor Swarm", "Polymorph" + } + ), + new RulesetLayout( + "8th Circle", + "Spells", + new[] + { + "Earthquake", "Energy Vortex", "Resurrection", "Air Elemental", "Summon Daemon", + "Earth Elemental", + "Fire Elemental", "Water Elemental" + } + ) + } + ) + }; + + if (Core.AOS) + { + entries.Add( + new RulesetLayout( + "Chivalry", + new[] + { + "Cleanse by Fire", + "Close Wounds", + "Consecrate Weapon", + "Dispel Evil", + "Divine Fury", + "Enemy of One", + "Holy Light", + "Noble Sacrifice", + "Remove Curse", + "Sacred Journey" + } + ) + ); + + entries.Add( + new RulesetLayout( + "Necromancy", + new[] + { + "Animate Dead", + "Blood Oath", + "Corpse Skin", + "Curse Weapon", + "Evil Omen", + "Horrific Beast", + "Lich Form", + "Mind Rot", + "Pain Spike", + "Poison Strike", + "Strangle", + "Summon Familiar", + "Vampiric Embrace", + "Vengeful Spirit", + "Wither", + "Wraith Form" + } + ) + ); + + if (Core.SE) + { + entries.Add( + new RulesetLayout( + "Bushido", + new[] + { + "Confidence", + "Counter Attack", + "Evasion", + "Honorable Execution", + "Lightning Strike", + "Momentum Strike" + } + ) + ); + + entries.Add( + new RulesetLayout( + "Ninjitsu", + new[] + { + "Animal Form", + "Backstab", + "Death Strike", + "Focus Attack", + "Ki Attack", + "Mirror Image", + "Shadow Jump", + "Suprise Attack" + } + ) + ); + + if (Core.ML) + entries.Add( + new RulesetLayout( + "Spellweaving", + new[] + { + "Arcane Circle", + "Arcane Empowerment", + "Attune Weapon", + "Dryad Allure", + "Essence of Wind", + "Ethereal Voyage", + "Gift of Life", + "Gift of Renewal", + "Immolating Weapon", + "Nature's Fury", + "Reaper Form", + "Summon Fey", + "Summon Fiend", + "Thunderstorm", + "Wildfire", + "Word of Death" + } + ) + ); + } + } + + if (Core.AOS) + { + if (Core.SE) + entries.Add( + new RulesetLayout( + "Combat Abilities", + new[] + { + "Stun", + "Disarm", + "Armor Ignore", + "Bleed Attack", + "Concussion Blow", + "Crushing Blow", + "Disarm", + "Dismount", + "Double Strike", + "Infectious Strike", + "Mortal Strike", + "Moving Shot", + "Paralyzing Blow", + "Shadow Strike", + "Whirlwind Attack", + "Riding Swipe", + "Frenzied Whirlwind", + "Block", + "Defense Mastery", + "Nerve Strike", + "Talon Strike", + "Feint", + "Dual Wield", + "Double Shot", + "Armor Pierce" + } + ) + ); + else + entries.Add( + new RulesetLayout( + "Combat Abilities", + new[] + { + "Stun", + "Disarm", + "Armor Ignore", + "Bleed Attack", + "Concussion Blow", + "Crushing Blow", + "Disarm", + "Dismount", + "Double Strike", + "Infectious Strike", + "Mortal Strike", + "Moving Shot", + "Paralyzing Blow", + "Shadow Strike", + "Whirlwind Attack" + } + ) + ); + } + else + { + entries.Add( + new RulesetLayout( + "Combat Abilities", + new[] + { + "Stun", + "Disarm", + "Concussion Blow", + "Crushing Blow", + "Paralyzing Blow" + } + ) + ); + } + + entries.Add( + new RulesetLayout( + "Skills", + new[] + { + "Anatomy", + "Detect Hidden", + "Evaluating Intelligence", + "Hiding", + "Poisoning", + "Snooping", + "Stealing", + "Spirit Speak", + "Stealth" + } + ) + ); + + if (Core.AOS) + { + entries.Add( + new RulesetLayout( + "Weapons", + new[] + { + "Magical", + "Melee", + "Ranged", + "Poisoned", + "Wrestling" + } + ) + ); + + entries.Add( + new RulesetLayout( + "Armor", + new[] + { + "Magical", + "Shields" + } + ) + ); + } + else + { + entries.Add( + new RulesetLayout( + "Weapons", + new[] + { + "Magical", + "Melee", + "Ranged", + "Poisoned", + "Wrestling", + "Runics" + } + ) + ); + + entries.Add( + new RulesetLayout( + "Armor", + new[] + { + "Magical", + "Shields", + "Colored" + } + ) + ); + } + + if (Core.SE) + entries.Add( + new RulesetLayout( + "Items", + new[] + { + new RulesetLayout( + "Potions", + new[] + { + "Agility", + "Cure", + "Explosion", + "Heal", + "Nightsight", + "Poison", + "Refresh", + "Strength" + } + ) + }, + new[] + { + "Bandages", + "Wands", + "Trapped Containers", + "Bolas", + "Mounts", + "Orange Petals", + "Shurikens", + "Fukiya Darts", + "Fire Horns" + } + ) + ); + else + entries.Add( + new RulesetLayout( + "Items", + new[] + { + new RulesetLayout( + "Potions", + new[] + { + "Agility", + "Cure", + "Explosion", + "Heal", + "Nightsight", + "Poison", + "Refresh", + "Strength" + } + ) + }, + new[] + { + "Bandages", + "Wands", + "Trapped Containers", + "Bolas", + "Mounts", + "Orange Petals", + "Fire Horns" + } + ) + ); + + m_Root = new RulesetLayout("Rules", entries.ToArray()); + m_Root.ComputeOffsets(); + + // Set up default rulesets + + if (!Core.AOS) + { + var m5x = new Ruleset(m_Root); + + m5x.Title = "Mage 5x"; + + m5x.SetOptionRange("Spells", true); + + m5x.SetOption("Spells", "Wall of Stone", false); + m5x.SetOption("Spells", "Fire Field", false); + m5x.SetOption("Spells", "Poison Field", false); + m5x.SetOption("Spells", "Energy Field", false); + m5x.SetOption("Spells", "Reactive Armor", false); + m5x.SetOption("Spells", "Protection", false); + m5x.SetOption("Spells", "Teleport", false); + m5x.SetOption("Spells", "Wall of Stone", false); + m5x.SetOption("Spells", "Arch Protection", false); + m5x.SetOption("Spells", "Recall", false); + m5x.SetOption("Spells", "Blade Spirits", false); + m5x.SetOption("Spells", "Incognito", false); + m5x.SetOption("Spells", "Magic Reflection", false); + m5x.SetOption("Spells", "Paralyze", false); + m5x.SetOption("Spells", "Summon Creature", false); + m5x.SetOption("Spells", "Invisibility", false); + m5x.SetOption("Spells", "Mark", false); + m5x.SetOption("Spells", "Paralyze Field", false); + m5x.SetOption("Spells", "Energy Field", false); + m5x.SetOption("Spells", "Gate Travel", false); + m5x.SetOption("Spells", "Polymorph", false); + m5x.SetOption("Spells", "Energy Vortex", false); + m5x.SetOption("Spells", "Air Elemental", false); + m5x.SetOption("Spells", "Summon Daemon", false); + m5x.SetOption("Spells", "Earth Elemental", false); + m5x.SetOption("Spells", "Fire Elemental", false); + m5x.SetOption("Spells", "Water Elemental", false); + m5x.SetOption("Spells", "Earthquake", false); + m5x.SetOption("Spells", "Meteor Swarm", false); + m5x.SetOption("Spells", "Chain Lightning", false); + m5x.SetOption("Spells", "Resurrection", false); + + m5x.SetOption("Weapons", "Wrestling", true); + + m5x.SetOption("Skills", "Anatomy", true); + m5x.SetOption("Skills", "Detect Hidden", true); + m5x.SetOption("Skills", "Evaluating Intelligence", true); + + m5x.SetOption("Items", "Trapped Containers", true); + + var m7x = new Ruleset(m_Root); + + m7x.Title = "Mage 7x"; + + m7x.SetOptionRange("Spells", true); + + m7x.SetOption("Spells", "Wall of Stone", false); + m7x.SetOption("Spells", "Fire Field", false); + m7x.SetOption("Spells", "Poison Field", false); + m7x.SetOption("Spells", "Energy Field", false); + m7x.SetOption("Spells", "Reactive Armor", false); + m7x.SetOption("Spells", "Protection", false); + m7x.SetOption("Spells", "Teleport", false); + m7x.SetOption("Spells", "Wall of Stone", false); + m7x.SetOption("Spells", "Arch Protection", false); + m7x.SetOption("Spells", "Recall", false); + m7x.SetOption("Spells", "Blade Spirits", false); + m7x.SetOption("Spells", "Incognito", false); + m7x.SetOption("Spells", "Magic Reflection", false); + m7x.SetOption("Spells", "Paralyze", false); + m7x.SetOption("Spells", "Summon Creature", false); + m7x.SetOption("Spells", "Invisibility", false); + m7x.SetOption("Spells", "Mark", false); + m7x.SetOption("Spells", "Paralyze Field", false); + m7x.SetOption("Spells", "Energy Field", false); + m7x.SetOption("Spells", "Gate Travel", false); + m7x.SetOption("Spells", "Polymorph", false); + m7x.SetOption("Spells", "Energy Vortex", false); + m7x.SetOption("Spells", "Air Elemental", false); + m7x.SetOption("Spells", "Summon Daemon", false); + m7x.SetOption("Spells", "Earth Elemental", false); + m7x.SetOption("Spells", "Fire Elemental", false); + m7x.SetOption("Spells", "Water Elemental", false); + m7x.SetOption("Spells", "Earthquake", false); + m7x.SetOption("Spells", "Meteor Swarm", false); + m7x.SetOption("Spells", "Chain Lightning", false); + m7x.SetOption("Spells", "Resurrection", false); + + m7x.SetOption("Combat Abilities", "Stun", true); + + m7x.SetOption("Skills", "Anatomy", true); + m7x.SetOption("Skills", "Detect Hidden", true); + m7x.SetOption("Skills", "Poisoning", true); + m7x.SetOption("Skills", "Evaluating Intelligence", true); + + m7x.SetOption("Weapons", "Wrestling", true); + + m7x.SetOption("Potions", "Refresh", true); + m7x.SetOption("Items", "Trapped Containers", true); + m7x.SetOption("Items", "Bandages", true); + + var s7x = new Ruleset(m_Root); + + s7x.Title = "Standard 7x"; + + s7x.SetOptionRange("Spells", true); + + s7x.SetOption("Spells", "Wall of Stone", false); + s7x.SetOption("Spells", "Fire Field", false); + s7x.SetOption("Spells", "Poison Field", false); + s7x.SetOption("Spells", "Energy Field", false); + s7x.SetOption("Spells", "Teleport", false); + s7x.SetOption("Spells", "Wall of Stone", false); + s7x.SetOption("Spells", "Arch Protection", false); + s7x.SetOption("Spells", "Recall", false); + s7x.SetOption("Spells", "Blade Spirits", false); + s7x.SetOption("Spells", "Incognito", false); + s7x.SetOption("Spells", "Magic Reflection", false); + s7x.SetOption("Spells", "Paralyze", false); + s7x.SetOption("Spells", "Summon Creature", false); + s7x.SetOption("Spells", "Invisibility", false); + s7x.SetOption("Spells", "Mark", false); + s7x.SetOption("Spells", "Paralyze Field", false); + s7x.SetOption("Spells", "Energy Field", false); + s7x.SetOption("Spells", "Gate Travel", false); + s7x.SetOption("Spells", "Polymorph", false); + s7x.SetOption("Spells", "Energy Vortex", false); + s7x.SetOption("Spells", "Air Elemental", false); + s7x.SetOption("Spells", "Summon Daemon", false); + s7x.SetOption("Spells", "Earth Elemental", false); + s7x.SetOption("Spells", "Fire Elemental", false); + s7x.SetOption("Spells", "Water Elemental", false); + s7x.SetOption("Spells", "Earthquake", false); + s7x.SetOption("Spells", "Meteor Swarm", false); + s7x.SetOption("Spells", "Chain Lightning", false); + s7x.SetOption("Spells", "Resurrection", false); + + s7x.SetOptionRange("Combat Abilities", true); + + s7x.SetOption("Skills", "Anatomy", true); + s7x.SetOption("Skills", "Detect Hidden", true); + s7x.SetOption("Skills", "Poisoning", true); + s7x.SetOption("Skills", "Evaluating Intelligence", true); + + s7x.SetOptionRange("Weapons", true); + s7x.SetOption("Weapons", "Runics", false); + s7x.SetOptionRange("Armor", true); + + s7x.SetOption("Potions", "Refresh", true); + s7x.SetOption("Items", "Bandages", true); + s7x.SetOption("Items", "Trapped Containers", true); + + m_Root.Defaults = new[] { m5x, m7x, s7x }; + } + else + { + var all = new Ruleset(m_Root); + + all.Title = "Standard All Skills"; + + all.SetOptionRange("Spells", true); + + all.SetOption("Spells", "Wall of Stone", false); + all.SetOption("Spells", "Fire Field", false); + all.SetOption("Spells", "Poison Field", false); + all.SetOption("Spells", "Energy Field", false); + all.SetOption("Spells", "Teleport", false); + all.SetOption("Spells", "Wall of Stone", false); + all.SetOption("Spells", "Arch Protection", false); + all.SetOption("Spells", "Recall", false); + all.SetOption("Spells", "Blade Spirits", false); + all.SetOption("Spells", "Incognito", false); + all.SetOption("Spells", "Magic Reflection", false); + all.SetOption("Spells", "Paralyze", false); + all.SetOption("Spells", "Summon Creature", false); + all.SetOption("Spells", "Invisibility", false); + all.SetOption("Spells", "Mark", false); + all.SetOption("Spells", "Paralyze Field", false); + all.SetOption("Spells", "Energy Field", false); + all.SetOption("Spells", "Gate Travel", false); + all.SetOption("Spells", "Polymorph", false); + all.SetOption("Spells", "Energy Vortex", false); + all.SetOption("Spells", "Air Elemental", false); + all.SetOption("Spells", "Summon Daemon", false); + all.SetOption("Spells", "Earth Elemental", false); + all.SetOption("Spells", "Fire Elemental", false); + all.SetOption("Spells", "Water Elemental", false); + all.SetOption("Spells", "Earthquake", false); + all.SetOption("Spells", "Meteor Swarm", false); + all.SetOption("Spells", "Chain Lightning", false); + all.SetOption("Spells", "Resurrection", false); + + all.SetOptionRange("Necromancy", true); + all.SetOption("Necromancy", "Summon Familiar", false); + all.SetOption("Necromancy", "Vengeful Spirit", false); + all.SetOption("Necromancy", "Animate Dead", false); + all.SetOption("Necromancy", "Wither", false); + all.SetOption("Necromancy", "Poison Strike", false); + + all.SetOptionRange("Chivalry", true); + all.SetOption("Chivalry", "Sacred Journey", false); + all.SetOption("Chivalry", "Enemy of One", false); + all.SetOption("Chivalry", "Noble Sacrifice", false); + + all.SetOptionRange("Combat Abilities", true); + all.SetOption("Combat Abilities", "Paralyzing Blow", false); + all.SetOption("Combat Abilities", "Shadow Strike", false); + + all.SetOption("Skills", "Anatomy", true); + all.SetOption("Skills", "Detect Hidden", true); + all.SetOption("Skills", "Poisoning", true); + all.SetOption("Skills", "Spirit Speak", true); + all.SetOption("Skills", "Evaluating Intelligence", true); + + all.SetOptionRange("Weapons", true); + all.SetOption("Weapons", "Poisoned", false); + + all.SetOptionRange("Armor", true); + + all.SetOptionRange("Ninjitsu", true); + all.SetOption("Ninjitsu", "Animal Form", false); + all.SetOption("Ninjitsu", "Mirror Image", false); + all.SetOption("Ninjitsu", "Backstab", false); + all.SetOption("Ninjitsu", "Suprise Attack", false); + all.SetOption("Ninjitsu", "Shadow Jump", false); + + all.SetOptionRange("Bushido", true); + + all.SetOptionRange("Spellweaving", true); + all.SetOption("Spellweaving", "Gift of Life", false); + all.SetOption("Spellweaving", "Summon Fey", false); + all.SetOption("Spellweaving", "Summon Fiend", false); + all.SetOption("Spellweaving", "Nature's Fury", false); + + all.SetOption("Potions", "Refresh", true); + all.SetOption("Items", "Bandages", true); + all.SetOption("Items", "Trapped Containers", true); + + m_Root.Defaults = new[] { all }; + } + + // Set up flavors + + var pots = new Ruleset(m_Root) { Title = "Potions" }; + + pots.SetOptionRange("Potions", true); + pots.SetOption("Potions", "Explosion", false); + + var para = new Ruleset(m_Root) { Title = "Paralyze" }; + + para.SetOption("Spells", "Paralyze", true); + para.SetOption("Spells", "Paralyze Field", true); + para.SetOption("Combat Abilities", "Paralyzing Blow", true); + + var fields = new Ruleset(m_Root) { Title = "Fields" }; + + fields.SetOption("Spells", "Wall of Stone", true); + fields.SetOption("Spells", "Fire Field", true); + fields.SetOption("Spells", "Poison Field", true); + fields.SetOption("Spells", "Energy Field", true); + fields.SetOption("Spells", "Wildfire", true); + + var area = new Ruleset(m_Root) { Title = "Area Effect" }; + + area.SetOption("Spells", "Earthquake", true); + area.SetOption("Spells", "Meteor Swarm", true); + area.SetOption("Spells", "Chain Lightning", true); + area.SetOption("Necromancy", "Wither", true); + area.SetOption("Necromancy", "Poison Strike", true); + + var summons = new Ruleset(m_Root) { Title = "Summons" }; + + summons.SetOption("Spells", "Blade Spirits", true); + summons.SetOption("Spells", "Energy Vortex", true); + summons.SetOption("Spells", "Air Elemental", true); + summons.SetOption("Spells", "Summon Daemon", true); + summons.SetOption("Spells", "Earth Elemental", true); + summons.SetOption("Spells", "Fire Elemental", true); + summons.SetOption("Spells", "Water Elemental", true); + summons.SetOption("Necromancy", "Summon Familiar", true); + summons.SetOption("Necromancy", "Vengeful Spirit", true); + summons.SetOption("Necromancy", "Animate Dead", true); + summons.SetOption("Ninjitsu", "Mirror Image", true); + summons.SetOption("Spellweaving", "Summon Fey", true); + summons.SetOption("Spellweaving", "Summon Fiend", true); + summons.SetOption("Spellweaving", "Nature's Fury", true); + + m_Root.Flavors = new[] { pots, para, fields, area, summons }; + + return m_Root; + } + } + + public string Title { get; } + + public string Description { get; } + + public string[] Options { get; } + + public int Offset { get; private set; } + + public int TotalLength { get; private set; } + + public RulesetLayout Parent { get; private set; } + + public RulesetLayout[] Children { get; } + + public Ruleset[] Defaults { get; set; } + + public Ruleset[] Flavors { get; set; } + + public RulesetLayout FindByTitle(string title) + { + if (Title == title) + return this; + + for (var i = 0; i < Children.Length; ++i) + { + var layout = Children[i].FindByTitle(title); + + if (layout != null) + return layout; + } + + return null; + } + + public string FindByIndex(int index) + { + if (index >= Offset && index < Offset + Options.Length) + return $"{Description}: {Options[index - Offset]}"; + + for (var i = 0; i < Children.Length; ++i) + { + var opt = Children[i].FindByIndex(index); + + if (opt != null) + return opt; + } + + return null; + } + + public RulesetLayout FindByOption(string title, string option, ref int index) + { + if (title == null || Title == title) + { + index = GetOptionIndex(option); + + if (index >= 0) + return this; + + title = null; + } + + for (var i = 0; i < Children.Length; ++i) + { + var layout = Children[i].FindByOption(title, option, ref index); + + if (layout != null) + return layout; + } + + return null; + } + + public int GetOptionIndex(string option) => Array.IndexOf(Options, option); + + public void ComputeOffsets() + { + var offset = 0; + + RecurseComputeOffsets(ref offset); + } + + private int RecurseComputeOffsets(ref int offset) + { + Offset = offset; + + offset += Options.Length; + TotalLength += Options.Length; + + for (var i = 0; i < Children.Length; ++i) + TotalLength += Children[i].RecurseComputeOffsets(ref offset); + + return TotalLength; + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/SafeZone.cs b/Projects/UOContent/Engines/ConPVP/SafeZone.cs index 212324942..9c0dc75cd 100644 --- a/Projects/UOContent/Engines/ConPVP/SafeZone.cs +++ b/Projects/UOContent/Engines/ConPVP/SafeZone.cs @@ -1,60 +1,60 @@ -using Server.Factions; -using Server.Mobiles; -using Server.Regions; - -namespace Server.Engines.ConPVP -{ - public class SafeZone : GuardedRegion - { - public static readonly int SafeZonePriority = HouseRegion.HousePriority + 1; - - /*public override bool AllowReds => true;*/ - - public SafeZone(Rectangle2D area, Point3D goloc, Map map, bool isGuarded) : base(null, map, SafeZonePriority, area) - { - GoLocation = goloc; - - Disabled = !isGuarded; - - Register(); - } - - public override bool AllowHousing(Mobile from, Point3D p) => from.AccessLevel >= AccessLevel.GameMaster && base.AllowHousing(from, p); - - public override bool OnMoveInto(Mobile m, Direction d, Point3D newLocation, Point3D oldLocation) - { - if (m.Player && Sigil.ExistsOn(m)) - { - m.SendMessage(0x22, "You are holding a sigil and cannot enter this zone."); - return false; - } - - PlayerMobile pm = m as PlayerMobile ?? - (m is BaseCreature bc && bc.Summoned ? - bc.SummonMaster as PlayerMobile : null); - - if (pm?.DuelContext?.StartedBeginCountdown == true) - return true; - - if (DuelContext.CheckCombat(m)) - { - m.SendMessage(0x22, "You have recently been in combat and cannot enter this zone."); - return false; - } - - return base.OnMoveInto(m, d, newLocation, oldLocation); - } - - public override void OnEnter(Mobile m) - { - m.SendMessage("You have entered a dueling safezone. No combat other than duels are allowed in this zone."); - } - - public override void OnExit(Mobile m) - { - m.SendMessage("You have left a dueling safezone. Combat is now unrestricted."); - } - - public override bool CanUseStuckMenu(Mobile m) => false; - } -} +using Server.Factions; +using Server.Mobiles; +using Server.Regions; + +namespace Server.Engines.ConPVP +{ + public class SafeZone : GuardedRegion + { + public static readonly int SafeZonePriority = HouseRegion.HousePriority + 1; + + /*public override bool AllowReds => true;*/ + + public SafeZone(Rectangle2D area, Point3D goloc, Map map, bool isGuarded) : base(null, map, SafeZonePriority, area) + { + GoLocation = goloc; + + Disabled = !isGuarded; + + Register(); + } + + public override bool AllowHousing(Mobile from, Point3D p) => + from.AccessLevel >= AccessLevel.GameMaster && base.AllowHousing(from, p); + + public override bool OnMoveInto(Mobile m, Direction d, Point3D newLocation, Point3D oldLocation) + { + if (m.Player && Sigil.ExistsOn(m)) + { + m.SendMessage(0x22, "You are holding a sigil and cannot enter this zone."); + return false; + } + + var pm = m as PlayerMobile ?? + (m is BaseCreature bc && bc.Summoned ? bc.SummonMaster as PlayerMobile : null); + + if (pm?.DuelContext?.StartedBeginCountdown == true) + return true; + + if (DuelContext.CheckCombat(m)) + { + m.SendMessage(0x22, "You have recently been in combat and cannot enter this zone."); + return false; + } + + return base.OnMoveInto(m, d, newLocation, oldLocation); + } + + public override void OnEnter(Mobile m) + { + m.SendMessage("You have entered a dueling safezone. No combat other than duels are allowed in this zone."); + } + + public override void OnExit(Mobile m) + { + m.SendMessage("You have left a dueling safezone. Combat is now unrestricted."); + } + + public override bool CanUseStuckMenu(Mobile m) => false; + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Tournament.cs b/Projects/UOContent/Engines/ConPVP/Tournament.cs index d204a0562..d35fd90c0 100644 --- a/Projects/UOContent/Engines/ConPVP/Tournament.cs +++ b/Projects/UOContent/Engines/ConPVP/Tournament.cs @@ -1,892 +1,938 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Server.Factions; -using Server.Items; -using Server.Network; -using Server.Regions; - -namespace Server.Engines.ConPVP -{ - public enum TournamentStage - { - Inactive, - Signup, - Fighting - } - - public enum GroupingType - { - HighVsLow, - Nearest, - Random - } - - public enum TieType - { - Random, - Highest, - Lowest, - FullElimination, - FullAdvancement - } - - public enum TourneyType - { - Standard, - FreeForAll, - RandomTeam, - RedVsBlue, - Faction - } - - [PropertyObject] - public class Tournament - { - private static readonly TimeSpan SliceInterval = TimeSpan.FromSeconds(12.0); - private int m_ParticipantsPerMatch; - private int m_PlayersPerParticipant; - - public Tournament(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 5: - { - FactionRestricted = reader.ReadBool(); - - goto case 4; - } - case 4: - { - EventController = reader.ReadItem() as EventController; - - goto case 3; - } - case 3: - { - SuddenDeathRounds = reader.ReadEncodedInt(); - - goto case 2; - } - case 2: - { - TourneyType = (TourneyType)reader.ReadEncodedInt(); - - goto case 1; - } - case 1: - { - GroupType = (GroupingType)reader.ReadEncodedInt(); - TieType = (TieType)reader.ReadEncodedInt(); - SignupPeriod = reader.ReadTimeSpan(); - - goto case 0; - } - case 0: - { - if (version < 3) - SuddenDeathRounds = 3; - - m_ParticipantsPerMatch = reader.ReadEncodedInt(); - m_PlayersPerParticipant = reader.ReadEncodedInt(); - SignupPeriod = reader.ReadTimeSpan(); - CurrentStage = TournamentStage.Inactive; - Pyramid = new TourneyPyramid(); - Ruleset = new Ruleset(RulesetLayout.Root); - Ruleset.ApplyDefault(Ruleset.Layout.Defaults[0]); - Participants = new List(); - Undefeated = new List(); - Arenas = new List(); - - break; - } - } - - Timer.DelayCall(SliceInterval, SliceInterval, Slice); - } - - public Tournament() - { - m_ParticipantsPerMatch = 2; - m_PlayersPerParticipant = 1; - Pyramid = new TourneyPyramid(); - Ruleset = new Ruleset(RulesetLayout.Root); - Ruleset.ApplyDefault(Ruleset.Layout.Defaults[0]); - Participants = new List(); - Undefeated = new List(); - Arenas = new List(); - SignupPeriod = TimeSpan.FromMinutes(10.0); - - Timer.DelayCall(SliceInterval, SliceInterval, Slice); - } - - public bool IsNotoRestricted => TourneyType != TourneyType.Standard; - - [CommandProperty(AccessLevel.GameMaster)] - public EventController EventController { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int SuddenDeathRounds { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public TourneyType TourneyType { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public GroupingType GroupType { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public TieType TieType { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan SuddenDeath { get; set; } - - public Ruleset Ruleset { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int ParticipantsPerMatch - { - get => m_ParticipantsPerMatch; - set => m_ParticipantsPerMatch = Math.Clamp(value, 2, 10); - } - - [CommandProperty(AccessLevel.GameMaster)] - public int PlayersPerParticipant - { - get => m_PlayersPerParticipant; - set => m_PlayersPerParticipant = Math.Clamp(value, 1, 10); - } - - [CommandProperty(AccessLevel.GameMaster)] - public int LevelRequirement { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool FactionRestricted { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan SignupPeriod { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime SignupStart { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public TournamentStage CurrentStage { get; private set; } - - public TournamentStage Stage - { - get => CurrentStage; - set => CurrentStage = value; - } - - public TourneyPyramid Pyramid { get; set; } - - public List Arenas { get; set; } - - public List Participants { get; set; } - - public List Undefeated { get; set; } - - public bool IsFactionRestricted => FactionRestricted || TourneyType == TourneyType.Faction; - - public bool HasParticipant(Mobile mob) - { - for (int i = 0; i < Participants.Count; ++i) - if (Participants[i].Players.Contains(mob)) - return true; - - return false; - } - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(5); // version - - writer.Write(FactionRestricted); - - writer.Write(EventController); - - writer.WriteEncodedInt(SuddenDeathRounds); - - writer.WriteEncodedInt((int)TourneyType); - - writer.WriteEncodedInt((int)GroupType); - writer.WriteEncodedInt((int)TieType); - writer.Write(SuddenDeath); - - writer.WriteEncodedInt(m_ParticipantsPerMatch); - writer.WriteEncodedInt(m_PlayersPerParticipant); - writer.Write(SignupPeriod); - } - - public void HandleTie(Arena arena, TourneyMatch match, List remaining) - { - if (remaining.Count == 1) - HandleWon(arena, match, remaining[0]); - - if (remaining.Count < 2) - return; - - StringBuilder sb = new StringBuilder(); - - sb.Append("The match has ended in a tie "); - - sb.Append(remaining.Count == 2 ? "between " : "among "); - - sb.Append(remaining.Count); - - sb.Append(remaining[0].Players.Count == 1 ? " players: " : " teams: "); - - bool hasAppended = false; - - for (int j = 0; j < match.Participants.Count; ++j) - { - TourneyParticipant part = match.Participants[j]; - - if (remaining.Contains(part)) - { - if (hasAppended) - sb.Append(", "); - - sb.Append(part.NameList); - hasAppended = true; - } - else - { - Undefeated.Remove(part); - } - } - - sb.Append(". "); - - string whole = remaining.Count == 2 ? "both" : "all"; - - TieType tieType = TieType; - - if (tieType == TieType.FullElimination && remaining.Count >= Undefeated.Count) - tieType = TieType.FullAdvancement; - - switch (tieType) - { - case TieType.FullAdvancement: - { - sb.AppendFormat("In accordance with the rules, {0} parties are advanced.", whole); - break; - } - case TieType.FullElimination: - { - for (int j = 0; j < remaining.Count; ++j) - Undefeated.Remove(remaining[j]); - - sb.AppendFormat("In accordance with the rules, {0} parties are eliminated.", whole); - break; - } - case TieType.Random: - { - TourneyParticipant advanced = remaining.RandomElement(); - - for (int i = 0; i < remaining.Count; ++i) - if (remaining[i] != advanced) - Undefeated.Remove(remaining[i]); - - if (advanced != null) - sb.AppendFormat("In accordance with the rules, {0} {1} advanced.", advanced.NameList, - advanced.Players.Count == 1 ? "is" : "are"); - - break; - } - case TieType.Highest: - { - TourneyParticipant advanced = null; - - for (int i = 0; i < remaining.Count; ++i) - { - TourneyParticipant part = remaining[i]; - - if (advanced == null || part.TotalLadderXP > advanced.TotalLadderXP) - advanced = part; - } - - for (int i = 0; i < remaining.Count; ++i) - if (remaining[i] != advanced) - Undefeated.Remove(remaining[i]); - - if (advanced != null) - sb.AppendFormat("In accordance with the rules, {0} {1} advanced.", advanced.NameList, - advanced.Players.Count == 1 ? "is" : "are"); - - break; - } - case TieType.Lowest: - { - TourneyParticipant advanced = null; - - for (int i = 0; i < remaining.Count; ++i) - { - TourneyParticipant part = remaining[i]; - - if (advanced == null || part.TotalLadderXP < advanced.TotalLadderXP) - advanced = part; - } - - for (int i = 0; i < remaining.Count; ++i) - if (remaining[i] != advanced) - Undefeated.Remove(remaining[i]); - - if (advanced != null) - sb.AppendFormat("In accordance with the rules, {0} {1} advanced.", advanced.NameList, - advanced.Players.Count == 1 ? "is" : "are"); - - break; - } - } - - Alert(arena, sb.ToString()); - } - - public void OnEliminated(DuelPlayer player) - { - Participant part = player.Participant; - - if (!part.Eliminated) - return; - - if (TourneyType == TourneyType.FreeForAll) - { - int rem = 0; - - for (int i = 0; i < part.Context.Participants.Count; ++i) - if (part.Context.Participants[i]?.Eliminated == false) - ++rem; - - TourneyParticipant tp = part.TourneyPart; - - if (tp == null) - return; - - if (rem == 1) - GiveAwards(tp.Players, TrophyRank.Silver, ComputeCashAward() / 2); - else if (rem == 2) - GiveAwards(tp.Players, TrophyRank.Bronze, ComputeCashAward() / 4); - } - } - - public void HandleWon(Arena arena, TourneyMatch match, TourneyParticipant winner) - { - StringBuilder sb = new StringBuilder(); - - sb.Append("The match is complete. "); - sb.Append(winner.NameList); - - if (winner.Players.Count > 1) - sb.Append(" have bested "); - else - sb.Append(" has bested "); - - if (match.Participants.Count > 2) - sb.AppendFormat("{0} other {1}: ", match.Participants.Count - 1, - winner.Players.Count == 1 ? "players" : "teams"); - - bool hasAppended = false; - - for (int j = 0; j < match.Participants.Count; ++j) - { - TourneyParticipant part = match.Participants[j]; - - if (part == winner) - continue; - - Undefeated.Remove(part); - - if (hasAppended) - sb.Append(", "); - - sb.Append(part.NameList); - hasAppended = true; - } - - sb.Append("."); - - if (TourneyType == TourneyType.Standard) - Alert(arena, sb.ToString()); - } - - private int ComputeCashAward() => Participants.Count * m_PlayersPerParticipant * 2500; - - private void GiveAwards() - { - switch (TourneyType) - { - case TourneyType.FreeForAll: - { - if (Pyramid.Levels.Count < 1) - break; - - PyramidLevel top = Pyramid.Levels[^1]; - - if (top.FreeAdvance != null || top.Matches.Count != 1) - break; - - TourneyMatch match = top.Matches[0]; - TourneyParticipant winner = match.Winner; - - if (winner != null) - GiveAwards(winner.Players, TrophyRank.Gold, ComputeCashAward()); - - break; - } - case TourneyType.Standard: - { - if (Pyramid.Levels.Count < 2) - break; - - PyramidLevel top = Pyramid.Levels[^1]; - - if (top.FreeAdvance != null || top.Matches.Count != 1) - break; - - int cash = ComputeCashAward(); - - TourneyMatch match = top.Matches[0]; - TourneyParticipant winner = match.Winner; - - for (int i = 0; i < match.Participants.Count; ++i) - { - TourneyParticipant part = match.Participants[i]; - - if (part == winner) - GiveAwards(part.Players, TrophyRank.Gold, cash); - else - GiveAwards(part.Players, TrophyRank.Silver, cash / 2); - } - - PyramidLevel next = Pyramid.Levels[^2]; - - if (next.Matches.Count > 2) - break; - - for (int i = 0; i < next.Matches.Count; ++i) - { - match = next.Matches[i]; - winner = match.Winner; - - for (int j = 0; j < match.Participants.Count; ++j) - { - TourneyParticipant part = match.Participants[j]; - - if (part != winner) - GiveAwards(part.Players, TrophyRank.Bronze, cash / 4); - } - } - - break; - } - } - } - - private void GiveAwards(List players, TrophyRank rank, int cash) - { - if (players.Count == 0) - return; - - if (players.Count > 1) - cash /= players.Count - 1; - - cash += 500; - cash /= 1000; - cash *= 1000; - - StringBuilder sb = new StringBuilder(); - - if (TourneyType == TourneyType.FreeForAll) - { - sb.Append(Participants.Count * m_PlayersPerParticipant); - sb.Append("-man FFA"); - } - else if (TourneyType == TourneyType.RandomTeam) - { - sb.Append(m_ParticipantsPerMatch); - sb.Append("-Team"); - } - else if (TourneyType == TourneyType.Faction) - { - sb.Append(m_ParticipantsPerMatch); - sb.Append("-Team Faction"); - } - else if (TourneyType == TourneyType.RedVsBlue) - { - sb.Append("Red v Blue"); - } - else - { - for (int i = 0; i < m_ParticipantsPerMatch; ++i) - { - if (sb.Length > 0) - sb.Append('v'); - - sb.Append(m_PlayersPerParticipant); - } - } - - if (EventController != null) - sb.Append(' ').Append(EventController.Title); - - sb.Append(" Champion"); - - string title = sb.ToString(); - - for (int i = 0; i < players.Count; ++i) - { - Mobile mob = players[i]; - - if (mob?.Deleted != false) - continue; - - Item item = new Trophy(title, rank); - - if (!mob.PlaceInBackpack(item)) - mob.BankBox.DropItem(item); - - if (cash > 0) - { - item = new BankCheck(cash); - - if (!mob.PlaceInBackpack(item)) - mob.BankBox.DropItem(item); - - mob.SendMessage( - "You have been awarded a {0} trophy and {1:N0}gp for your participation in this tournament.", - rank.ToString().ToLower(), cash); - } - else - { - mob.SendMessage("You have been awarded a {0} trophy for your participation in this tournament.", - rank.ToString().ToLower()); - } - } - } - - public void Slice() - { - if (CurrentStage == TournamentStage.Signup) - { - TimeSpan until = SignupStart + SignupPeriod - DateTime.UtcNow; - - if (until <= TimeSpan.Zero) - { - for (int i = Participants.Count - 1; i >= 0; --i) - { - TourneyParticipant part = Participants[i]; - bool bad = false; - - for (int j = 0; j < part.Players.Count; ++j) - { - Mobile check = part.Players[j]; - - if (check.Deleted || check.Map == null || check.Map == Map.Internal || !check.Alive || - Sigil.ExistsOn(check) || check.Region.IsPartOf()) - { - bad = true; - break; - } - } - - if (bad) - { - for (int j = 0; j < part.Players.Count; ++j) - part.Players[j].SendMessage("You have been disqualified from the tournament."); - - Participants.RemoveAt(i); - } - } - - if (Participants.Count >= 2) - { - CurrentStage = TournamentStage.Fighting; - - Undefeated.Clear(); - - Pyramid.Levels.Clear(); - Pyramid.AddLevel(m_ParticipantsPerMatch, Participants, GroupType, TourneyType); - - PyramidLevel level = Pyramid.Levels[0]; - - if (level.FreeAdvance != null) - Undefeated.Add(level.FreeAdvance); - - for (int i = 0; i < level.Matches.Count; ++i) - { - TourneyMatch match = level.Matches[i]; - - Undefeated.AddRange(match.Participants); - } - - Alert("Hear ye! Hear ye!", "The tournament will begin shortly."); - } - else - { - /*Alert( "Is this all?", "Pitiful. Signup extended." ); - m_SignupStart = DateTime.UtcNow;*/ - - Alert("Is this all?", "Pitiful. Tournament cancelled."); - CurrentStage = TournamentStage.Inactive; - } - } - else if (Math.Abs(until.TotalSeconds - TimeSpan.FromMinutes(1.0).TotalSeconds) < - SliceInterval.TotalSeconds / 2) - { - Alert("Last call!", "If you wish to enter the tournament, sign up with the registrar now."); - } - else if (Math.Abs(until.TotalSeconds - TimeSpan.FromMinutes(5.0).TotalSeconds) < - SliceInterval.TotalSeconds / 2) - { - Alert("The tournament will begin in 5 minutes.", "Sign up now before it's too late."); - } - } - else if (CurrentStage == TournamentStage.Fighting) - { - if (Undefeated.Count == 1) - { - TourneyParticipant winner = Undefeated[0]; - - try - { - if (EventController != null) - { - Alert("The tournament has completed!", - $"Team {EventController.GetTeamName(Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner))} has won!"); - } - else if (TourneyType == TourneyType.RandomTeam) - { - Alert("The tournament has completed!", - $"Team {Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) + 1} has won!"); - } - else if (TourneyType == TourneyType.Faction) - { - if (m_ParticipantsPerMatch == 4) - { - string name = "(null)"; - - switch (Pyramid.Levels[0].Matches[0].Participants.IndexOf( - winner)) - { - case 0: - { - name = "Minax"; - break; - } - case 1: - { - name = "Council of Mages"; - break; - } - case 2: - { - name = "True Britannians"; - break; - } - case 3: - { - name = "Shadowlords"; - break; - } - } - - Alert("The tournament has completed!", $"The {name} team has won!"); - } - else if (m_ParticipantsPerMatch == 2) - { - Alert("The tournament has completed!", - $"The {(Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) == 0 ? "Evil" : "Hero")} team has won!"); - } - else - { - Alert("The tournament has completed!", - $"Team {Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) + 1} has won!"); - } - } - else if (TourneyType == TourneyType.RedVsBlue) - { - Alert("The tournament has completed!", - $"Team {(Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) == 0 ? "Red" : "Blue")} has won!"); - } - else - { - Alert("The tournament has completed!", - $"{winner.NameList} {(winner.Players.Count > 1 ? "are" : "is")} the champion{(winner.Players.Count == 1 ? "" : "s")}."); - } - } - catch - { - // ignored - } - - GiveAwards(); - - CurrentStage = TournamentStage.Inactive; - Undefeated.Clear(); - } - else if (Pyramid.Levels.Count > 0) - { - PyramidLevel activeLevel = Pyramid.Levels[^1]; - bool stillGoing = false; - - for (int i = 0; i < activeLevel.Matches.Count; ++i) - { - TourneyMatch match = activeLevel.Matches[i]; - - if (match.Winner == null) - { - stillGoing = true; - - if (!match.InProgress) - for (int j = 0; j < Arenas.Count; ++j) - { - Arena arena = Arenas[j]; - - if (!arena.IsOccupied) - { - match.Start(arena, this); - break; - } - } - } - } - - if (!stillGoing) - { - for (int i = Undefeated.Count - 1; i >= 0; --i) - { - TourneyParticipant part = Undefeated[i]; - bool bad = false; - - for (int j = 0; j < part.Players.Count; ++j) - { - Mobile check = part.Players[j]; - - if (check.Deleted || check.Map == null || check.Map == Map.Internal || !check.Alive || - Sigil.ExistsOn(check) || check.Region.IsPartOf()) - { - bad = true; - break; - } - } - - if (!bad) - continue; - - for (int j = 0; j < part.Players.Count; ++j) - part.Players[j].SendMessage("You have been disqualified from the tournament."); - - Undefeated.RemoveAt(i); - - if (Undefeated.Count == 1) - { - TourneyParticipant winner = Undefeated[0]; - - try - { - if (EventController != null) - { - Alert("The tournament has completed!", - $"Team {EventController.GetTeamName(Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner))} has won"); - } - else if (TourneyType == TourneyType.RandomTeam) - { - Alert("The tournament has completed!", - $"Team {Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) + 1} has won!"); - } - else if (TourneyType == TourneyType.Faction) - { - if (m_ParticipantsPerMatch == 4) - { - string name = "(null)"; - - switch (Pyramid.Levels[0].Matches[0] - .Participants.IndexOf(winner)) - { - case 0: - { - name = "Minax"; - break; - } - case 1: - { - name = "Council of Mages"; - break; - } - case 2: - { - name = "True Britannians"; - break; - } - case 3: - { - name = "Shadowlords"; - break; - } - } - - Alert("The tournament has completed!", $"The {name} team has won!"); - } - else if (m_ParticipantsPerMatch == 2) - { - Alert("The tournament has completed!", - $"The {(Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) == 0 ? "Evil" : "Hero")} team has won!"); - } - else - { - Alert("The tournament has completed!", - $"Team {Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) + 1} has won!"); - } - } - else if (TourneyType == TourneyType.RedVsBlue) - { - Alert("The tournament has completed!", - $"Team {(Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) == 0 ? "Red" : "Blue")} has won!"); - } - else - { - Alert("The tournament has completed!", - $"{winner.NameList} {(winner.Players.Count > 1 ? "are" : "is")} the champion{(winner.Players.Count == 1 ? "" : "s")}."); - } - } - catch - { - // ignored - } - - GiveAwards(); - - CurrentStage = TournamentStage.Inactive; - Undefeated.Clear(); - break; - } - } - - if (Undefeated.Count > 1) - Pyramid.AddLevel(m_ParticipantsPerMatch, Undefeated, GroupType, TourneyType); - } - } - } - } - - public void Alert(params string[] alerts) - { - for (int i = 0; i < Arenas.Count; ++i) - Alert(Arenas[i], alerts); - } - - public void Alert(Arena arena, params string[] alerts) - { - if (arena?.Announcer != null) - for (int j = 0; j < alerts.Length; ++j) - { - string alert = alerts[j]; - Timer.DelayCall(TimeSpan.FromSeconds(Math.Max(j - 0.5, 0.0)), - () => arena.Announcer.PublicOverheadMessage(MessageType.Regular, 0x35, false, alert)); - } - } - } -} +using System; +using System.Collections.Generic; +using System.Text; +using Server.Factions; +using Server.Items; +using Server.Network; +using Server.Regions; + +namespace Server.Engines.ConPVP +{ + public enum TournamentStage + { + Inactive, + Signup, + Fighting + } + + public enum GroupingType + { + HighVsLow, + Nearest, + Random + } + + public enum TieType + { + Random, + Highest, + Lowest, + FullElimination, + FullAdvancement + } + + public enum TourneyType + { + Standard, + FreeForAll, + RandomTeam, + RedVsBlue, + Faction + } + + [PropertyObject] + public class Tournament + { + private static readonly TimeSpan SliceInterval = TimeSpan.FromSeconds(12.0); + private int m_ParticipantsPerMatch; + private int m_PlayersPerParticipant; + + public Tournament(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 5: + { + FactionRestricted = reader.ReadBool(); + + goto case 4; + } + case 4: + { + EventController = reader.ReadItem() as EventController; + + goto case 3; + } + case 3: + { + SuddenDeathRounds = reader.ReadEncodedInt(); + + goto case 2; + } + case 2: + { + TourneyType = (TourneyType)reader.ReadEncodedInt(); + + goto case 1; + } + case 1: + { + GroupType = (GroupingType)reader.ReadEncodedInt(); + TieType = (TieType)reader.ReadEncodedInt(); + SignupPeriod = reader.ReadTimeSpan(); + + goto case 0; + } + case 0: + { + if (version < 3) + SuddenDeathRounds = 3; + + m_ParticipantsPerMatch = reader.ReadEncodedInt(); + m_PlayersPerParticipant = reader.ReadEncodedInt(); + SignupPeriod = reader.ReadTimeSpan(); + CurrentStage = TournamentStage.Inactive; + Pyramid = new TourneyPyramid(); + Ruleset = new Ruleset(RulesetLayout.Root); + Ruleset.ApplyDefault(Ruleset.Layout.Defaults[0]); + Participants = new List(); + Undefeated = new List(); + Arenas = new List(); + + break; + } + } + + Timer.DelayCall(SliceInterval, SliceInterval, Slice); + } + + public Tournament() + { + m_ParticipantsPerMatch = 2; + m_PlayersPerParticipant = 1; + Pyramid = new TourneyPyramid(); + Ruleset = new Ruleset(RulesetLayout.Root); + Ruleset.ApplyDefault(Ruleset.Layout.Defaults[0]); + Participants = new List(); + Undefeated = new List(); + Arenas = new List(); + SignupPeriod = TimeSpan.FromMinutes(10.0); + + Timer.DelayCall(SliceInterval, SliceInterval, Slice); + } + + public bool IsNotoRestricted => TourneyType != TourneyType.Standard; + + [CommandProperty(AccessLevel.GameMaster)] + public EventController EventController { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int SuddenDeathRounds { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public TourneyType TourneyType { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public GroupingType GroupType { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public TieType TieType { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan SuddenDeath { get; set; } + + public Ruleset Ruleset { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int ParticipantsPerMatch + { + get => m_ParticipantsPerMatch; + set => m_ParticipantsPerMatch = Math.Clamp(value, 2, 10); + } + + [CommandProperty(AccessLevel.GameMaster)] + public int PlayersPerParticipant + { + get => m_PlayersPerParticipant; + set => m_PlayersPerParticipant = Math.Clamp(value, 1, 10); + } + + [CommandProperty(AccessLevel.GameMaster)] + public int LevelRequirement { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool FactionRestricted { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan SignupPeriod { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime SignupStart { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public TournamentStage CurrentStage { get; private set; } + + public TournamentStage Stage + { + get => CurrentStage; + set => CurrentStage = value; + } + + public TourneyPyramid Pyramid { get; set; } + + public List Arenas { get; set; } + + public List Participants { get; set; } + + public List Undefeated { get; set; } + + public bool IsFactionRestricted => FactionRestricted || TourneyType == TourneyType.Faction; + + public bool HasParticipant(Mobile mob) + { + for (var i = 0; i < Participants.Count; ++i) + if (Participants[i].Players.Contains(mob)) + return true; + + return false; + } + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(5); // version + + writer.Write(FactionRestricted); + + writer.Write(EventController); + + writer.WriteEncodedInt(SuddenDeathRounds); + + writer.WriteEncodedInt((int)TourneyType); + + writer.WriteEncodedInt((int)GroupType); + writer.WriteEncodedInt((int)TieType); + writer.Write(SuddenDeath); + + writer.WriteEncodedInt(m_ParticipantsPerMatch); + writer.WriteEncodedInt(m_PlayersPerParticipant); + writer.Write(SignupPeriod); + } + + public void HandleTie(Arena arena, TourneyMatch match, List remaining) + { + if (remaining.Count == 1) + HandleWon(arena, match, remaining[0]); + + if (remaining.Count < 2) + return; + + var sb = new StringBuilder(); + + sb.Append("The match has ended in a tie "); + + sb.Append(remaining.Count == 2 ? "between " : "among "); + + sb.Append(remaining.Count); + + sb.Append(remaining[0].Players.Count == 1 ? " players: " : " teams: "); + + var hasAppended = false; + + for (var j = 0; j < match.Participants.Count; ++j) + { + var part = match.Participants[j]; + + if (remaining.Contains(part)) + { + if (hasAppended) + sb.Append(", "); + + sb.Append(part.NameList); + hasAppended = true; + } + else + { + Undefeated.Remove(part); + } + } + + sb.Append(". "); + + var whole = remaining.Count == 2 ? "both" : "all"; + + var tieType = TieType; + + if (tieType == TieType.FullElimination && remaining.Count >= Undefeated.Count) + tieType = TieType.FullAdvancement; + + switch (tieType) + { + case TieType.FullAdvancement: + { + sb.AppendFormat("In accordance with the rules, {0} parties are advanced.", whole); + break; + } + case TieType.FullElimination: + { + for (var j = 0; j < remaining.Count; ++j) + Undefeated.Remove(remaining[j]); + + sb.AppendFormat("In accordance with the rules, {0} parties are eliminated.", whole); + break; + } + case TieType.Random: + { + var advanced = remaining.RandomElement(); + + for (var i = 0; i < remaining.Count; ++i) + if (remaining[i] != advanced) + Undefeated.Remove(remaining[i]); + + if (advanced != null) + sb.AppendFormat( + "In accordance with the rules, {0} {1} advanced.", + advanced.NameList, + advanced.Players.Count == 1 ? "is" : "are" + ); + + break; + } + case TieType.Highest: + { + TourneyParticipant advanced = null; + + for (var i = 0; i < remaining.Count; ++i) + { + var part = remaining[i]; + + if (advanced == null || part.TotalLadderXP > advanced.TotalLadderXP) + advanced = part; + } + + for (var i = 0; i < remaining.Count; ++i) + if (remaining[i] != advanced) + Undefeated.Remove(remaining[i]); + + if (advanced != null) + sb.AppendFormat( + "In accordance with the rules, {0} {1} advanced.", + advanced.NameList, + advanced.Players.Count == 1 ? "is" : "are" + ); + + break; + } + case TieType.Lowest: + { + TourneyParticipant advanced = null; + + for (var i = 0; i < remaining.Count; ++i) + { + var part = remaining[i]; + + if (advanced == null || part.TotalLadderXP < advanced.TotalLadderXP) + advanced = part; + } + + for (var i = 0; i < remaining.Count; ++i) + if (remaining[i] != advanced) + Undefeated.Remove(remaining[i]); + + if (advanced != null) + sb.AppendFormat( + "In accordance with the rules, {0} {1} advanced.", + advanced.NameList, + advanced.Players.Count == 1 ? "is" : "are" + ); + + break; + } + } + + Alert(arena, sb.ToString()); + } + + public void OnEliminated(DuelPlayer player) + { + var part = player.Participant; + + if (!part.Eliminated) + return; + + if (TourneyType == TourneyType.FreeForAll) + { + var rem = 0; + + for (var i = 0; i < part.Context.Participants.Count; ++i) + if (part.Context.Participants[i]?.Eliminated == false) + ++rem; + + var tp = part.TourneyPart; + + if (tp == null) + return; + + if (rem == 1) + GiveAwards(tp.Players, TrophyRank.Silver, ComputeCashAward() / 2); + else if (rem == 2) + GiveAwards(tp.Players, TrophyRank.Bronze, ComputeCashAward() / 4); + } + } + + public void HandleWon(Arena arena, TourneyMatch match, TourneyParticipant winner) + { + var sb = new StringBuilder(); + + sb.Append("The match is complete. "); + sb.Append(winner.NameList); + + if (winner.Players.Count > 1) + sb.Append(" have bested "); + else + sb.Append(" has bested "); + + if (match.Participants.Count > 2) + sb.AppendFormat( + "{0} other {1}: ", + match.Participants.Count - 1, + winner.Players.Count == 1 ? "players" : "teams" + ); + + var hasAppended = false; + + for (var j = 0; j < match.Participants.Count; ++j) + { + var part = match.Participants[j]; + + if (part == winner) + continue; + + Undefeated.Remove(part); + + if (hasAppended) + sb.Append(", "); + + sb.Append(part.NameList); + hasAppended = true; + } + + sb.Append("."); + + if (TourneyType == TourneyType.Standard) + Alert(arena, sb.ToString()); + } + + private int ComputeCashAward() => Participants.Count * m_PlayersPerParticipant * 2500; + + private void GiveAwards() + { + switch (TourneyType) + { + case TourneyType.FreeForAll: + { + if (Pyramid.Levels.Count < 1) + break; + + var top = Pyramid.Levels[^1]; + + if (top.FreeAdvance != null || top.Matches.Count != 1) + break; + + var match = top.Matches[0]; + var winner = match.Winner; + + if (winner != null) + GiveAwards(winner.Players, TrophyRank.Gold, ComputeCashAward()); + + break; + } + case TourneyType.Standard: + { + if (Pyramid.Levels.Count < 2) + break; + + var top = Pyramid.Levels[^1]; + + if (top.FreeAdvance != null || top.Matches.Count != 1) + break; + + var cash = ComputeCashAward(); + + var match = top.Matches[0]; + var winner = match.Winner; + + for (var i = 0; i < match.Participants.Count; ++i) + { + var part = match.Participants[i]; + + if (part == winner) + GiveAwards(part.Players, TrophyRank.Gold, cash); + else + GiveAwards(part.Players, TrophyRank.Silver, cash / 2); + } + + var next = Pyramid.Levels[^2]; + + if (next.Matches.Count > 2) + break; + + for (var i = 0; i < next.Matches.Count; ++i) + { + match = next.Matches[i]; + winner = match.Winner; + + for (var j = 0; j < match.Participants.Count; ++j) + { + var part = match.Participants[j]; + + if (part != winner) + GiveAwards(part.Players, TrophyRank.Bronze, cash / 4); + } + } + + break; + } + } + } + + private void GiveAwards(List players, TrophyRank rank, int cash) + { + if (players.Count == 0) + return; + + if (players.Count > 1) + cash /= players.Count - 1; + + cash += 500; + cash /= 1000; + cash *= 1000; + + var sb = new StringBuilder(); + + if (TourneyType == TourneyType.FreeForAll) + { + sb.Append(Participants.Count * m_PlayersPerParticipant); + sb.Append("-man FFA"); + } + else if (TourneyType == TourneyType.RandomTeam) + { + sb.Append(m_ParticipantsPerMatch); + sb.Append("-Team"); + } + else if (TourneyType == TourneyType.Faction) + { + sb.Append(m_ParticipantsPerMatch); + sb.Append("-Team Faction"); + } + else if (TourneyType == TourneyType.RedVsBlue) + { + sb.Append("Red v Blue"); + } + else + { + for (var i = 0; i < m_ParticipantsPerMatch; ++i) + { + if (sb.Length > 0) + sb.Append('v'); + + sb.Append(m_PlayersPerParticipant); + } + } + + if (EventController != null) + sb.Append(' ').Append(EventController.Title); + + sb.Append(" Champion"); + + var title = sb.ToString(); + + for (var i = 0; i < players.Count; ++i) + { + var mob = players[i]; + + if (mob?.Deleted != false) + continue; + + Item item = new Trophy(title, rank); + + if (!mob.PlaceInBackpack(item)) + mob.BankBox.DropItem(item); + + if (cash > 0) + { + item = new BankCheck(cash); + + if (!mob.PlaceInBackpack(item)) + mob.BankBox.DropItem(item); + + mob.SendMessage( + "You have been awarded a {0} trophy and {1:N0}gp for your participation in this tournament.", + rank.ToString().ToLower(), + cash + ); + } + else + { + mob.SendMessage( + "You have been awarded a {0} trophy for your participation in this tournament.", + rank.ToString().ToLower() + ); + } + } + } + + public void Slice() + { + if (CurrentStage == TournamentStage.Signup) + { + var until = SignupStart + SignupPeriod - DateTime.UtcNow; + + if (until <= TimeSpan.Zero) + { + for (var i = Participants.Count - 1; i >= 0; --i) + { + var part = Participants[i]; + var bad = false; + + for (var j = 0; j < part.Players.Count; ++j) + { + var check = part.Players[j]; + + if (check.Deleted || check.Map == null || check.Map == Map.Internal || !check.Alive || + Sigil.ExistsOn(check) || check.Region.IsPartOf()) + { + bad = true; + break; + } + } + + if (bad) + { + for (var j = 0; j < part.Players.Count; ++j) + part.Players[j].SendMessage("You have been disqualified from the tournament."); + + Participants.RemoveAt(i); + } + } + + if (Participants.Count >= 2) + { + CurrentStage = TournamentStage.Fighting; + + Undefeated.Clear(); + + Pyramid.Levels.Clear(); + Pyramid.AddLevel(m_ParticipantsPerMatch, Participants, GroupType, TourneyType); + + var level = Pyramid.Levels[0]; + + if (level.FreeAdvance != null) + Undefeated.Add(level.FreeAdvance); + + for (var i = 0; i < level.Matches.Count; ++i) + { + var match = level.Matches[i]; + + Undefeated.AddRange(match.Participants); + } + + Alert("Hear ye! Hear ye!", "The tournament will begin shortly."); + } + else + { + /*Alert( "Is this all?", "Pitiful. Signup extended." ); + m_SignupStart = DateTime.UtcNow;*/ + + Alert("Is this all?", "Pitiful. Tournament cancelled."); + CurrentStage = TournamentStage.Inactive; + } + } + else if (Math.Abs(until.TotalSeconds - TimeSpan.FromMinutes(1.0).TotalSeconds) < + SliceInterval.TotalSeconds / 2) + { + Alert("Last call!", "If you wish to enter the tournament, sign up with the registrar now."); + } + else if (Math.Abs(until.TotalSeconds - TimeSpan.FromMinutes(5.0).TotalSeconds) < + SliceInterval.TotalSeconds / 2) + { + Alert("The tournament will begin in 5 minutes.", "Sign up now before it's too late."); + } + } + else if (CurrentStage == TournamentStage.Fighting) + { + if (Undefeated.Count == 1) + { + var winner = Undefeated[0]; + + try + { + if (EventController != null) + { + Alert( + "The tournament has completed!", + $"Team {EventController.GetTeamName(Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner))} has won!" + ); + } + else if (TourneyType == TourneyType.RandomTeam) + { + Alert( + "The tournament has completed!", + $"Team {Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) + 1} has won!" + ); + } + else if (TourneyType == TourneyType.Faction) + { + if (m_ParticipantsPerMatch == 4) + { + var name = "(null)"; + + switch (Pyramid.Levels[0] + .Matches[0] + .Participants.IndexOf( + winner + )) + { + case 0: + { + name = "Minax"; + break; + } + case 1: + { + name = "Council of Mages"; + break; + } + case 2: + { + name = "True Britannians"; + break; + } + case 3: + { + name = "Shadowlords"; + break; + } + } + + Alert("The tournament has completed!", $"The {name} team has won!"); + } + else if (m_ParticipantsPerMatch == 2) + { + Alert( + "The tournament has completed!", + $"The {(Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) == 0 ? "Evil" : "Hero")} team has won!" + ); + } + else + { + Alert( + "The tournament has completed!", + $"Team {Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) + 1} has won!" + ); + } + } + else if (TourneyType == TourneyType.RedVsBlue) + { + Alert( + "The tournament has completed!", + $"Team {(Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) == 0 ? "Red" : "Blue")} has won!" + ); + } + else + { + Alert( + "The tournament has completed!", + $"{winner.NameList} {(winner.Players.Count > 1 ? "are" : "is")} the champion{(winner.Players.Count == 1 ? "" : "s")}." + ); + } + } + catch + { + // ignored + } + + GiveAwards(); + + CurrentStage = TournamentStage.Inactive; + Undefeated.Clear(); + } + else if (Pyramid.Levels.Count > 0) + { + var activeLevel = Pyramid.Levels[^1]; + var stillGoing = false; + + for (var i = 0; i < activeLevel.Matches.Count; ++i) + { + var match = activeLevel.Matches[i]; + + if (match.Winner == null) + { + stillGoing = true; + + if (!match.InProgress) + for (var j = 0; j < Arenas.Count; ++j) + { + var arena = Arenas[j]; + + if (!arena.IsOccupied) + { + match.Start(arena, this); + break; + } + } + } + } + + if (!stillGoing) + { + for (var i = Undefeated.Count - 1; i >= 0; --i) + { + var part = Undefeated[i]; + var bad = false; + + for (var j = 0; j < part.Players.Count; ++j) + { + var check = part.Players[j]; + + if (check.Deleted || check.Map == null || check.Map == Map.Internal || !check.Alive || + Sigil.ExistsOn(check) || check.Region.IsPartOf()) + { + bad = true; + break; + } + } + + if (!bad) + continue; + + for (var j = 0; j < part.Players.Count; ++j) + part.Players[j].SendMessage("You have been disqualified from the tournament."); + + Undefeated.RemoveAt(i); + + if (Undefeated.Count == 1) + { + var winner = Undefeated[0]; + + try + { + if (EventController != null) + { + Alert( + "The tournament has completed!", + $"Team {EventController.GetTeamName(Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner))} has won" + ); + } + else if (TourneyType == TourneyType.RandomTeam) + { + Alert( + "The tournament has completed!", + $"Team {Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) + 1} has won!" + ); + } + else if (TourneyType == TourneyType.Faction) + { + if (m_ParticipantsPerMatch == 4) + { + var name = "(null)"; + + switch (Pyramid.Levels[0] + .Matches[0] + .Participants.IndexOf(winner)) + { + case 0: + { + name = "Minax"; + break; + } + case 1: + { + name = "Council of Mages"; + break; + } + case 2: + { + name = "True Britannians"; + break; + } + case 3: + { + name = "Shadowlords"; + break; + } + } + + Alert("The tournament has completed!", $"The {name} team has won!"); + } + else if (m_ParticipantsPerMatch == 2) + { + Alert( + "The tournament has completed!", + $"The {(Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) == 0 ? "Evil" : "Hero")} team has won!" + ); + } + else + { + Alert( + "The tournament has completed!", + $"Team {Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) + 1} has won!" + ); + } + } + else if (TourneyType == TourneyType.RedVsBlue) + { + Alert( + "The tournament has completed!", + $"Team {(Pyramid.Levels[0].Matches[0].Participants.IndexOf(winner) == 0 ? "Red" : "Blue")} has won!" + ); + } + else + { + Alert( + "The tournament has completed!", + $"{winner.NameList} {(winner.Players.Count > 1 ? "are" : "is")} the champion{(winner.Players.Count == 1 ? "" : "s")}." + ); + } + } + catch + { + // ignored + } + + GiveAwards(); + + CurrentStage = TournamentStage.Inactive; + Undefeated.Clear(); + break; + } + } + + if (Undefeated.Count > 1) + Pyramid.AddLevel(m_ParticipantsPerMatch, Undefeated, GroupType, TourneyType); + } + } + } + } + + public void Alert(params string[] alerts) + { + for (var i = 0; i < Arenas.Count; ++i) + Alert(Arenas[i], alerts); + } + + public void Alert(Arena arena, params string[] alerts) + { + if (arena?.Announcer != null) + for (var j = 0; j < alerts.Length; ++j) + { + var alert = alerts[j]; + Timer.DelayCall( + TimeSpan.FromSeconds(Math.Max(j - 0.5, 0.0)), + () => arena.Announcer.PublicOverheadMessage(MessageType.Regular, 0x35, false, alert) + ); + } + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/TournamentBracketItem.cs b/Projects/UOContent/Engines/ConPVP/TournamentBracketItem.cs index e3b9ba3e6..a2a2cf009 100644 --- a/Projects/UOContent/Engines/ConPVP/TournamentBracketItem.cs +++ b/Projects/UOContent/Engines/ConPVP/TournamentBracketItem.cs @@ -1,62 +1,62 @@ -using Server.Network; - -namespace Server.Engines.ConPVP -{ - public class TournamentBracketItem : Item - { - [Constructible] - public TournamentBracketItem() : base(3774) => Movable = false; - - public TournamentBracketItem(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public TournamentController Tournament { get; set; } - - public override string DefaultName => "tournament bracket"; - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that - } - else - { - Tournament tourney = Tournament?.Tournament; - - if (tourney != null) - { - from.CloseGump(); - from.SendGump(new TournamentBracketGump(from, tourney, TourneyBracketGumpType.Index)); - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(Tournament); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Tournament = reader.ReadItem() as TournamentController; - break; - } - } - } - } -} \ No newline at end of file +using Server.Network; + +namespace Server.Engines.ConPVP +{ + public class TournamentBracketItem : Item + { + [Constructible] + public TournamentBracketItem() : base(3774) => Movable = false; + + public TournamentBracketItem(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public TournamentController Tournament { get; set; } + + public override string DefaultName => "tournament bracket"; + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that + } + else + { + var tourney = Tournament?.Tournament; + + if (tourney != null) + { + from.CloseGump(); + from.SendGump(new TournamentBracketGump(from, tourney, TourneyBracketGumpType.Index)); + } + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + writer.Write(Tournament); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Tournament = reader.ReadItem() as TournamentController; + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/TournamentController.cs b/Projects/UOContent/Engines/ConPVP/TournamentController.cs index 8944c83c5..5454f0182 100644 --- a/Projects/UOContent/Engines/ConPVP/TournamentController.cs +++ b/Projects/UOContent/Engines/ConPVP/TournamentController.cs @@ -1,137 +1,139 @@ -using System; -using System.Collections.Generic; -using Server.ContextMenus; -using Server.Gumps; - -namespace Server.Engines.ConPVP -{ - public class TournamentController : Item - { - private static readonly List m_Instances = new List(); - - [Constructible] - public TournamentController() : base(0x1B7A) - { - Visible = false; - Movable = false; - - Tournament = new Tournament(); - m_Instances.Add(this); - } - - public TournamentController(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public Tournament Tournament { get; private set; } - - public static bool IsActive - { - get - { - for (int i = 0; i < m_Instances.Count; ++i) - { - TournamentController controller = m_Instances[i]; - - if (controller?.Deleted == false && controller.Tournament != null && - controller.Tournament.Stage != TournamentStage.Inactive) - return true; - } - - return false; - } - } - - public override string DefaultName => "tournament controller"; - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (from.AccessLevel >= AccessLevel.GameMaster && Tournament != null) - { - list.Add(new EditEntry(Tournament)); - - if (Tournament.CurrentStage == TournamentStage.Inactive) - list.Add(new StartEntry(Tournament)); - } - } - - public override void OnDoubleClick(Mobile from) - { - if (from.AccessLevel >= AccessLevel.GameMaster && Tournament != null) - { - from.CloseGump(); - from.CloseGump(); - from.SendGump(new PickRulesetGump(from, null, Tournament.Ruleset)); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - Tournament.Serialize(writer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Tournament = new Tournament(reader); - break; - } - } - - m_Instances.Add(this); - } - - public override void OnDelete() - { - base.OnDelete(); - - m_Instances.Remove(this); - } - - private class EditEntry : ContextMenuEntry - { - private readonly Tournament m_Tournament; - - public EditEntry(Tournament tourney) : base(5101) => m_Tournament = tourney; - - public override void OnClick() - { - Owner.From.SendGump(new PropertiesGump(Owner.From, m_Tournament)); - } - } - - private class StartEntry : ContextMenuEntry - { - private readonly Tournament m_Tournament; - - public StartEntry(Tournament tourney) : base(5113) => m_Tournament = tourney; - - public override void OnClick() - { - if (m_Tournament.Stage == TournamentStage.Inactive) - { - m_Tournament.SignupStart = DateTime.UtcNow; - m_Tournament.Stage = TournamentStage.Signup; - m_Tournament.Participants.Clear(); - m_Tournament.Pyramid.Levels.Clear(); - m_Tournament.Alert("Hear ye! Hear ye!", - "Tournament signup has opened. You can enter by signing up with the registrar."); - } - } - } - } -} +using System; +using System.Collections.Generic; +using Server.ContextMenus; +using Server.Gumps; + +namespace Server.Engines.ConPVP +{ + public class TournamentController : Item + { + private static readonly List m_Instances = new List(); + + [Constructible] + public TournamentController() : base(0x1B7A) + { + Visible = false; + Movable = false; + + Tournament = new Tournament(); + m_Instances.Add(this); + } + + public TournamentController(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public Tournament Tournament { get; private set; } + + public static bool IsActive + { + get + { + for (var i = 0; i < m_Instances.Count; ++i) + { + var controller = m_Instances[i]; + + if (controller?.Deleted == false && controller.Tournament != null && + controller.Tournament.Stage != TournamentStage.Inactive) + return true; + } + + return false; + } + } + + public override string DefaultName => "tournament controller"; + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (from.AccessLevel >= AccessLevel.GameMaster && Tournament != null) + { + list.Add(new EditEntry(Tournament)); + + if (Tournament.CurrentStage == TournamentStage.Inactive) + list.Add(new StartEntry(Tournament)); + } + } + + public override void OnDoubleClick(Mobile from) + { + if (from.AccessLevel >= AccessLevel.GameMaster && Tournament != null) + { + from.CloseGump(); + from.CloseGump(); + from.SendGump(new PickRulesetGump(from, null, Tournament.Ruleset)); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + Tournament.Serialize(writer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Tournament = new Tournament(reader); + break; + } + } + + m_Instances.Add(this); + } + + public override void OnDelete() + { + base.OnDelete(); + + m_Instances.Remove(this); + } + + private class EditEntry : ContextMenuEntry + { + private readonly Tournament m_Tournament; + + public EditEntry(Tournament tourney) : base(5101) => m_Tournament = tourney; + + public override void OnClick() + { + Owner.From.SendGump(new PropertiesGump(Owner.From, m_Tournament)); + } + } + + private class StartEntry : ContextMenuEntry + { + private readonly Tournament m_Tournament; + + public StartEntry(Tournament tourney) : base(5113) => m_Tournament = tourney; + + public override void OnClick() + { + if (m_Tournament.Stage == TournamentStage.Inactive) + { + m_Tournament.SignupStart = DateTime.UtcNow; + m_Tournament.Stage = TournamentStage.Signup; + m_Tournament.Participants.Clear(); + m_Tournament.Pyramid.Levels.Clear(); + m_Tournament.Alert( + "Hear ye! Hear ye!", + "Tournament signup has opened. You can enter by signing up with the registrar." + ); + } + } + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/TournamentPyramid.cs b/Projects/UOContent/Engines/ConPVP/TournamentPyramid.cs index 75ef25732..8c8059cfd 100644 --- a/Projects/UOContent/Engines/ConPVP/TournamentPyramid.cs +++ b/Projects/UOContent/Engines/ConPVP/TournamentPyramid.cs @@ -1,180 +1,183 @@ -using System.Collections.Generic; -using Server.Ethics; -using Server.Factions; - -namespace Server.Engines.ConPVP -{ - public class TourneyPyramid - { - public TourneyPyramid() => Levels = new List(); - - public List Levels { get; set; } - - public void AddLevel(int partsPerMatch, List participants, GroupingType groupType, TourneyType tourneyType) - { - List copy = new List(participants); - - if (groupType == GroupingType.Nearest || groupType == GroupingType.HighVsLow) - copy.Sort(); - - PyramidLevel level = new PyramidLevel(); - - switch (tourneyType) - { - case TourneyType.RedVsBlue: - { - TourneyParticipant[] parts = new TourneyParticipant[2]; - - for (int i = 0; i < parts.Length; ++i) - parts[i] = new TourneyParticipant(new List()); - - for (int i = 0; i < copy.Count; ++i) - { - List players = copy[i].Players; - - for (int j = 0; j < players.Count; ++j) - { - Mobile mob = players[j]; - - if (mob.Kills >= 5) - parts[0].Players.Add(mob); - else - parts[1].Players.Add(mob); - } - } - - level.Matches.Add(new TourneyMatch(new List(parts))); - break; - } - case TourneyType.Faction: - { - TourneyParticipant[] parts = new TourneyParticipant[partsPerMatch]; - - for (int i = 0; i < parts.Length; ++i) - parts[i] = new TourneyParticipant(new List()); - - for (int i = 0; i < copy.Count; ++i) - { - List players = copy[i].Players; - - for (int j = 0; j < players.Count; ++j) - { - Mobile mob = players[j]; - - int index = -1; - - if (partsPerMatch == 4) - { - Faction fac = Faction.Find(mob); - - if (fac != null) - index = fac.Definition.Sort; - } - else if (partsPerMatch == 2) - { - if (Ethic.Evil.IsEligible(mob)) - index = 0; - else if (Ethic.Hero.IsEligible(mob)) index = 1; - } - - if (index < 0 || index >= partsPerMatch) index = i % partsPerMatch; - - parts[index].Players.Add(mob); - } - } - - level.Matches.Add(new TourneyMatch(new List(parts))); - break; - } - case TourneyType.RandomTeam: - { - TourneyParticipant[] parts = new TourneyParticipant[partsPerMatch]; - - for (int i = 0; i < partsPerMatch; ++i) - parts[i] = new TourneyParticipant(new List()); - - for (int i = 0; i < copy.Count; ++i) - parts[i % parts.Length].Players.AddRange(copy[i].Players); - - level.Matches.Add(new TourneyMatch(new List(parts))); - break; - } - case TourneyType.FreeForAll: - { - level.Matches.Add(new TourneyMatch(copy)); - break; - } - case TourneyType.Standard: - { - if (partsPerMatch >= 2 && participants.Count % partsPerMatch == 1) - { - int lowAdvances = int.MaxValue; - - for (int i = 0; i < participants.Count; ++i) - { - TourneyParticipant p = participants[i]; - - if (p.FreeAdvances < lowAdvances) - lowAdvances = p.FreeAdvances; - } - - List toAdvance = new List(); - - for (int i = 0; i < participants.Count; ++i) - { - TourneyParticipant p = participants[i]; - - if (p.FreeAdvances == lowAdvances) - toAdvance.Add(p); - } - - if (toAdvance.Count == 0) - toAdvance = copy; // sanity - - var random = toAdvance.RandomElement(); - - random.AddLog( - "Advanced automatically due to an odd number of challengers."); - level.FreeAdvance = random; - ++level.FreeAdvance.FreeAdvances; - copy.Remove(random); - } - - while (copy.Count >= partsPerMatch) - { - List thisMatch = new List(); - - for (int i = 0; i < partsPerMatch; ++i) - { - var idx = groupType switch - { - GroupingType.HighVsLow => i * (copy.Count - 1) / (partsPerMatch - 1), - GroupingType.Nearest => 0, - GroupingType.Random => Utility.Random(copy.Count), - _ => 0 - }; - - thisMatch.Add(copy[idx]); - copy.RemoveAt(idx); - } - - level.Matches.Add(new TourneyMatch(thisMatch)); - } - - if (copy.Count > 1) - level.Matches.Add(new TourneyMatch(copy)); - - break; - } - } - - Levels.Add(level); - } - } - - public class PyramidLevel - { - public List Matches { get; set; } = new List(); - public TourneyParticipant FreeAdvance { get; set; } - } -} +using System.Collections.Generic; +using Server.Ethics; +using Server.Factions; + +namespace Server.Engines.ConPVP +{ + public class TourneyPyramid + { + public TourneyPyramid() => Levels = new List(); + + public List Levels { get; set; } + + public void AddLevel( + int partsPerMatch, List participants, GroupingType groupType, TourneyType tourneyType + ) + { + var copy = new List(participants); + + if (groupType == GroupingType.Nearest || groupType == GroupingType.HighVsLow) + copy.Sort(); + + var level = new PyramidLevel(); + + switch (tourneyType) + { + case TourneyType.RedVsBlue: + { + var parts = new TourneyParticipant[2]; + + for (var i = 0; i < parts.Length; ++i) + parts[i] = new TourneyParticipant(new List()); + + for (var i = 0; i < copy.Count; ++i) + { + var players = copy[i].Players; + + for (var j = 0; j < players.Count; ++j) + { + var mob = players[j]; + + if (mob.Kills >= 5) + parts[0].Players.Add(mob); + else + parts[1].Players.Add(mob); + } + } + + level.Matches.Add(new TourneyMatch(new List(parts))); + break; + } + case TourneyType.Faction: + { + var parts = new TourneyParticipant[partsPerMatch]; + + for (var i = 0; i < parts.Length; ++i) + parts[i] = new TourneyParticipant(new List()); + + for (var i = 0; i < copy.Count; ++i) + { + var players = copy[i].Players; + + for (var j = 0; j < players.Count; ++j) + { + var mob = players[j]; + + var index = -1; + + if (partsPerMatch == 4) + { + var fac = Faction.Find(mob); + + if (fac != null) + index = fac.Definition.Sort; + } + else if (partsPerMatch == 2) + { + if (Ethic.Evil.IsEligible(mob)) + index = 0; + else if (Ethic.Hero.IsEligible(mob)) index = 1; + } + + if (index < 0 || index >= partsPerMatch) index = i % partsPerMatch; + + parts[index].Players.Add(mob); + } + } + + level.Matches.Add(new TourneyMatch(new List(parts))); + break; + } + case TourneyType.RandomTeam: + { + var parts = new TourneyParticipant[partsPerMatch]; + + for (var i = 0; i < partsPerMatch; ++i) + parts[i] = new TourneyParticipant(new List()); + + for (var i = 0; i < copy.Count; ++i) + parts[i % parts.Length].Players.AddRange(copy[i].Players); + + level.Matches.Add(new TourneyMatch(new List(parts))); + break; + } + case TourneyType.FreeForAll: + { + level.Matches.Add(new TourneyMatch(copy)); + break; + } + case TourneyType.Standard: + { + if (partsPerMatch >= 2 && participants.Count % partsPerMatch == 1) + { + var lowAdvances = int.MaxValue; + + for (var i = 0; i < participants.Count; ++i) + { + var p = participants[i]; + + if (p.FreeAdvances < lowAdvances) + lowAdvances = p.FreeAdvances; + } + + var toAdvance = new List(); + + for (var i = 0; i < participants.Count; ++i) + { + var p = participants[i]; + + if (p.FreeAdvances == lowAdvances) + toAdvance.Add(p); + } + + if (toAdvance.Count == 0) + toAdvance = copy; // sanity + + var random = toAdvance.RandomElement(); + + random.AddLog( + "Advanced automatically due to an odd number of challengers." + ); + level.FreeAdvance = random; + ++level.FreeAdvance.FreeAdvances; + copy.Remove(random); + } + + while (copy.Count >= partsPerMatch) + { + var thisMatch = new List(); + + for (var i = 0; i < partsPerMatch; ++i) + { + var idx = groupType switch + { + GroupingType.HighVsLow => i * (copy.Count - 1) / (partsPerMatch - 1), + GroupingType.Nearest => 0, + GroupingType.Random => Utility.Random(copy.Count), + _ => 0 + }; + + thisMatch.Add(copy[idx]); + copy.RemoveAt(idx); + } + + level.Matches.Add(new TourneyMatch(thisMatch)); + } + + if (copy.Count > 1) + level.Matches.Add(new TourneyMatch(copy)); + + break; + } + } + + Levels.Add(level); + } + } + + public class PyramidLevel + { + public List Matches { get; set; } = new List(); + public TourneyParticipant FreeAdvance { get; set; } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/TournamentRegistrar.cs b/Projects/UOContent/Engines/ConPVP/TournamentRegistrar.cs index bb491abea..4f8e42d44 100644 --- a/Projects/UOContent/Engines/ConPVP/TournamentRegistrar.cs +++ b/Projects/UOContent/Engines/ConPVP/TournamentRegistrar.cs @@ -1,93 +1,101 @@ -using System; -using Server.Factions; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.ConPVP -{ - public class TournamentRegistrar : Banker - { - [Constructible] - public TournamentRegistrar() - { - Timer.DelayCall(TimeSpan.FromSeconds(30.0), TimeSpan.FromSeconds(30.0), Announce_Callback); - } - - public TournamentRegistrar(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public TournamentController Tournament { get; set; } - - private void Announce_Callback() - { - Tournament tourney = Tournament?.Tournament; - - if (tourney?.Stage == TournamentStage.Signup) - PublicOverheadMessage(MessageType.Regular, 0x35, false, - "Come one, come all! Do you aspire to be a fighter of great renown? Join this tournament and show the world your abilities."); - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - base.OnMovement(m, oldLocation); - - Tournament tourney = Tournament?.Tournament; - - if (InRange(m, 4) && !InRange(oldLocation, 4) && tourney != null && tourney.Stage == TournamentStage.Signup && - m.CanBeginAction(this)) - { - Ladder ladder = Ladder.Instance; - - LadderEntry entry = ladder?.Find(m); - - if (entry != null && Ladder.GetLevel(entry.Experience) < tourney.LevelRequirement) - return; - - if (tourney.IsFactionRestricted && Faction.Find(m) == null) return; - - if (tourney.HasParticipant(m)) - return; - - PrivateOverheadMessage(MessageType.Regular, 0x35, false, - $"Hello m'{(m.Female ? "Lady" : "Lord")}. Dost thou wish to enter this tournament? You need only to write your name in this book.", - m.NetState); - m.BeginAction(this); - Timer.DelayCall(TimeSpan.FromSeconds(10.0), ReleaseLock_Callback, m); - } - } - - public void ReleaseLock_Callback(Mobile m) - { - m.EndAction(this); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(Tournament); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Tournament = reader.ReadItem() as TournamentController; - break; - } - } - - Timer.DelayCall(TimeSpan.FromSeconds(30.0), TimeSpan.FromSeconds(30.0), Announce_Callback); - } - } -} +using System; +using Server.Factions; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.ConPVP +{ + public class TournamentRegistrar : Banker + { + [Constructible] + public TournamentRegistrar() + { + Timer.DelayCall(TimeSpan.FromSeconds(30.0), TimeSpan.FromSeconds(30.0), Announce_Callback); + } + + public TournamentRegistrar(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public TournamentController Tournament { get; set; } + + private void Announce_Callback() + { + var tourney = Tournament?.Tournament; + + if (tourney?.Stage == TournamentStage.Signup) + PublicOverheadMessage( + MessageType.Regular, + 0x35, + false, + "Come one, come all! Do you aspire to be a fighter of great renown? Join this tournament and show the world your abilities." + ); + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + base.OnMovement(m, oldLocation); + + var tourney = Tournament?.Tournament; + + if (InRange(m, 4) && !InRange(oldLocation, 4) && tourney != null && tourney.Stage == TournamentStage.Signup && + m.CanBeginAction(this)) + { + var ladder = Ladder.Instance; + + var entry = ladder?.Find(m); + + if (entry != null && Ladder.GetLevel(entry.Experience) < tourney.LevelRequirement) + return; + + if (tourney.IsFactionRestricted && Faction.Find(m) == null) return; + + if (tourney.HasParticipant(m)) + return; + + PrivateOverheadMessage( + MessageType.Regular, + 0x35, + false, + $"Hello m'{(m.Female ? "Lady" : "Lord")}. Dost thou wish to enter this tournament? You need only to write your name in this book.", + m.NetState + ); + m.BeginAction(this); + Timer.DelayCall(TimeSpan.FromSeconds(10.0), ReleaseLock_Callback, m); + } + } + + public void ReleaseLock_Callback(Mobile m) + { + m.EndAction(this); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + writer.Write(Tournament); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Tournament = reader.ReadItem() as TournamentController; + break; + } + } + + Timer.DelayCall(TimeSpan.FromSeconds(30.0), TimeSpan.FromSeconds(30.0), Announce_Callback); + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/TournamentSignupItem.cs b/Projects/UOContent/Engines/ConPVP/TournamentSignupItem.cs index 1078775ee..988e4d39a 100644 --- a/Projects/UOContent/Engines/ConPVP/TournamentSignupItem.cs +++ b/Projects/UOContent/Engines/ConPVP/TournamentSignupItem.cs @@ -1,146 +1,189 @@ -using System.Collections.Generic; -using Server.Factions; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.ConPVP -{ - public class TournamentSignupItem : Item - { - [Constructible] - public TournamentSignupItem() : base(4029) => Movable = false; - - public TournamentSignupItem(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public TournamentController Tournament { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Registrar { get; set; } - - public override string DefaultName => "tournament signup book"; - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that - } - else - { - Tournament tourney = Tournament?.Tournament; - - if (tourney == null) - return; - - if (Registrar != null) - Registrar.Direction = Registrar.GetDirectionTo(this); - - switch (tourney.Stage) - { - case TournamentStage.Fighting: - { - if (Registrar != null) - { - if (tourney.HasParticipant(from)) - Registrar.PrivateOverheadMessage(MessageType.Regular, - 0x35, false, "Excuse me? You are already signed up.", from.NetState); - else - Registrar.PrivateOverheadMessage(MessageType.Regular, - 0x22, false, "The tournament has already begun. You are too late to signup now.", - from.NetState); - } - - break; - } - case TournamentStage.Inactive: - { - Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x35, false, "The tournament is closed.", from.NetState); - - break; - } - case TournamentStage.Signup: - { - Ladder ladder = Ladder.Instance; - LadderEntry entry = ladder?.Find(from); - - if (entry != null && Ladder.GetLevel(entry.Experience) < tourney.LevelRequirement) - { - Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x35, false, "You have not yet proven yourself a worthy dueler.", from.NetState); - - break; - } - - if (tourney.IsFactionRestricted && Faction.Find(from) == null) - { - Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x35, false, "Only those who have declared their faction allegiance may participate.", - from.NetState); - - break; - } - - if (from.HasGump()) - { - Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x22, false, "You must first respond to the offer I've given you.", from.NetState); - } - else if (from.HasGump()) - { - Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x22, false, "You must first cancel your duel offer.", from.NetState); - } - else if (from is PlayerMobile mobile && mobile.DuelContext != null) - { - Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x22, false, "You are already participating in a duel.", mobile.NetState); - } - else if (!tourney.HasParticipant(from)) - { - from.CloseGump(); - from.SendGump(new ConfirmSignupGump(from, Registrar, tourney, new List { from })); - } - else - { - Registrar?.PrivateOverheadMessage(MessageType.Regular, - 0x35, false, "You have already entered this tournament.", from.NetState); - } - - break; - } - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(Tournament); - writer.Write(Registrar); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Tournament = reader.ReadItem() as TournamentController; - Registrar = reader.ReadMobile(); - break; - } - } - } - } -} +using System.Collections.Generic; +using Server.Factions; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.ConPVP +{ + public class TournamentSignupItem : Item + { + [Constructible] + public TournamentSignupItem() : base(4029) => Movable = false; + + public TournamentSignupItem(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public TournamentController Tournament { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Registrar { get; set; } + + public override string DefaultName => "tournament signup book"; + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that + } + else + { + var tourney = Tournament?.Tournament; + + if (tourney == null) + return; + + if (Registrar != null) + Registrar.Direction = Registrar.GetDirectionTo(this); + + switch (tourney.Stage) + { + case TournamentStage.Fighting: + { + if (Registrar != null) + { + if (tourney.HasParticipant(from)) + Registrar.PrivateOverheadMessage( + MessageType.Regular, + 0x35, + false, + "Excuse me? You are already signed up.", + from.NetState + ); + else + Registrar.PrivateOverheadMessage( + MessageType.Regular, + 0x22, + false, + "The tournament has already begun. You are too late to signup now.", + from.NetState + ); + } + + break; + } + case TournamentStage.Inactive: + { + Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x35, + false, + "The tournament is closed.", + from.NetState + ); + + break; + } + case TournamentStage.Signup: + { + var ladder = Ladder.Instance; + var entry = ladder?.Find(from); + + if (entry != null && Ladder.GetLevel(entry.Experience) < tourney.LevelRequirement) + { + Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x35, + false, + "You have not yet proven yourself a worthy dueler.", + from.NetState + ); + + break; + } + + if (tourney.IsFactionRestricted && Faction.Find(from) == null) + { + Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x35, + false, + "Only those who have declared their faction allegiance may participate.", + from.NetState + ); + + break; + } + + if (from.HasGump()) + { + Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x22, + false, + "You must first respond to the offer I've given you.", + from.NetState + ); + } + else if (from.HasGump()) + { + Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x22, + false, + "You must first cancel your duel offer.", + from.NetState + ); + } + else if (from is PlayerMobile mobile && mobile.DuelContext != null) + { + Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x22, + false, + "You are already participating in a duel.", + mobile.NetState + ); + } + else if (!tourney.HasParticipant(from)) + { + from.CloseGump(); + from.SendGump(new ConfirmSignupGump(from, Registrar, tourney, new List { from })); + } + else + { + Registrar?.PrivateOverheadMessage( + MessageType.Regular, + 0x35, + false, + "You have already entered this tournament.", + from.NetState + ); + } + + break; + } + } + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + writer.Write(Tournament); + writer.Write(Registrar); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Tournament = reader.ReadItem() as TournamentController; + Registrar = reader.ReadMobile(); + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/TourneyParticipant.cs b/Projects/UOContent/Engines/ConPVP/TourneyParticipant.cs index e8ca8982a..dba66f17c 100644 --- a/Projects/UOContent/Engines/ConPVP/TourneyParticipant.cs +++ b/Projects/UOContent/Engines/ConPVP/TourneyParticipant.cs @@ -1,103 +1,103 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Server.Engines.ConPVP -{ - public class TourneyParticipant : IComparable - { - public TourneyParticipant(Mobile owner) - { - Log = new List(); - Players = new List { owner }; - } - - public TourneyParticipant(List players) - { - Log = new List(); - Players = players; - } - - public List Players { get; set; } - - public List Log { get; set; } - - public int FreeAdvances { get; set; } - - public int TotalLadderXP - { - get - { - Ladder ladder = Ladder.Instance; - - if (ladder == null) - return 0; - - int total = 0; - - for (int i = 0; i < Players.Count; ++i) - { - Mobile mob = Players[i]; - LadderEntry entry = ladder.Find(mob); - - if (entry != null) - total += entry.Experience; - } - - return total; - } - } - - public string NameList - { - get - { - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < Players.Count; ++i) - { - if (Players[i] == null) - continue; - - Mobile mob = Players[i]; - - if (sb.Length > 0) - { - if (Players.Count == 2) - sb.Append(" and "); - else if (i + 1 < Players.Count) - sb.Append(", "); - else - sb.Append(", and "); - } - - sb.Append(mob.Name); - } - - return sb.Length == 0 ? "Empty" : sb.ToString(); - } - } - - public int CompareTo(TourneyParticipant p) => p.TotalLadderXP - TotalLadderXP; - - public void AddLog(string text) - { - Log.Add(text); - } - - public void AddLog(string format, params object[] args) - { - AddLog(string.Format(format, args)); - } - - public void WonMatch(TourneyMatch match) - { - AddLog("Match won."); - } - - public void LostMatch(TourneyMatch match) - { - AddLog("Match lost."); - } - } -} +using System; +using System.Collections.Generic; +using System.Text; + +namespace Server.Engines.ConPVP +{ + public class TourneyParticipant : IComparable + { + public TourneyParticipant(Mobile owner) + { + Log = new List(); + Players = new List { owner }; + } + + public TourneyParticipant(List players) + { + Log = new List(); + Players = players; + } + + public List Players { get; set; } + + public List Log { get; set; } + + public int FreeAdvances { get; set; } + + public int TotalLadderXP + { + get + { + var ladder = Ladder.Instance; + + if (ladder == null) + return 0; + + var total = 0; + + for (var i = 0; i < Players.Count; ++i) + { + var mob = Players[i]; + var entry = ladder.Find(mob); + + if (entry != null) + total += entry.Experience; + } + + return total; + } + } + + public string NameList + { + get + { + var sb = new StringBuilder(); + + for (var i = 0; i < Players.Count; ++i) + { + if (Players[i] == null) + continue; + + var mob = Players[i]; + + if (sb.Length > 0) + { + if (Players.Count == 2) + sb.Append(" and "); + else if (i + 1 < Players.Count) + sb.Append(", "); + else + sb.Append(", and "); + } + + sb.Append(mob.Name); + } + + return sb.Length == 0 ? "Empty" : sb.ToString(); + } + } + + public int CompareTo(TourneyParticipant p) => p.TotalLadderXP - TotalLadderXP; + + public void AddLog(string text) + { + Log.Add(text); + } + + public void AddLog(string format, params object[] args) + { + AddLog(string.Format(format, args)); + } + + public void WonMatch(TourneyMatch match) + { + AddLog("Match won."); + } + + public void LostMatch(TourneyMatch match) + { + AddLog("Match lost."); + } + } +} diff --git a/Projects/UOContent/Engines/ConPVP/Trophy.cs b/Projects/UOContent/Engines/ConPVP/Trophy.cs index caf4561da..f6e39dd14 100644 --- a/Projects/UOContent/Engines/ConPVP/Trophy.cs +++ b/Projects/UOContent/Engines/ConPVP/Trophy.cs @@ -1,113 +1,113 @@ -using System; - -namespace Server.Items -{ - public enum TrophyRank - { - Bronze, - Silver, - Gold - } - - [Flippable(5020, 4647)] - public class Trophy : Item - { - private TrophyRank m_Rank; - - [Constructible] - public Trophy(string title, TrophyRank rank) : base(5020) - { - Title = title; - m_Rank = rank; - Date = DateTime.UtcNow; - - LootType = LootType.Blessed; - - UpdateStyle(); - } - - public Trophy(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public string Title { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public TrophyRank Rank - { - get => m_Rank; - set - { - m_Rank = value; - UpdateStyle(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Owner { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime Date { get; private set; } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(Title); - writer.Write((int)m_Rank); - writer.Write(Owner); - writer.Write(Date); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Title = reader.ReadString(); - m_Rank = (TrophyRank)reader.ReadInt(); - Owner = reader.ReadMobile(); - Date = reader.ReadDateTime(); - - if (version == 0) - LootType = LootType.Blessed; - } - - public override void OnAdded(IEntity parent) - { - base.OnAdded(parent); - - Owner ??= RootParent as Mobile; - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - if (Owner != null) - LabelTo(from, "{0} -- {1}", Title, Owner.RawName); - else if (Title != null) - LabelTo(from, Title); - - if (Date != DateTime.MinValue) - LabelTo(from, Date.ToString("d")); - } - - public void UpdateStyle() - { - Name = $"{m_Rank.ToString().ToLower()} trophy"; - - Hue = m_Rank switch - { - TrophyRank.Gold => 2213, - TrophyRank.Silver => 0, - TrophyRank.Bronze => 2206, - _ => Hue - }; - } - } -} +using System; + +namespace Server.Items +{ + public enum TrophyRank + { + Bronze, + Silver, + Gold + } + + [Flippable(5020, 4647)] + public class Trophy : Item + { + private TrophyRank m_Rank; + + [Constructible] + public Trophy(string title, TrophyRank rank) : base(5020) + { + Title = title; + m_Rank = rank; + Date = DateTime.UtcNow; + + LootType = LootType.Blessed; + + UpdateStyle(); + } + + public Trophy(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public string Title { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public TrophyRank Rank + { + get => m_Rank; + set + { + m_Rank = value; + UpdateStyle(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Owner { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime Date { get; private set; } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(Title); + writer.Write((int)m_Rank); + writer.Write(Owner); + writer.Write(Date); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + Title = reader.ReadString(); + m_Rank = (TrophyRank)reader.ReadInt(); + Owner = reader.ReadMobile(); + Date = reader.ReadDateTime(); + + if (version == 0) + LootType = LootType.Blessed; + } + + public override void OnAdded(IEntity parent) + { + base.OnAdded(parent); + + Owner ??= RootParent as Mobile; + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + if (Owner != null) + LabelTo(from, "{0} -- {1}", Title, Owner.RawName); + else if (Title != null) + LabelTo(from, Title); + + if (Date != DateTime.MinValue) + LabelTo(from, Date.ToString("d")); + } + + public void UpdateStyle() + { + Name = $"{m_Rank.ToString().ToLower()} trophy"; + + Hue = m_Rank switch + { + TrophyRank.Gold => 2213, + TrophyRank.Silver => 0, + TrophyRank.Bronze => 2206, + _ => Hue + }; + } + } +} diff --git a/Projects/UOContent/Engines/Craft/Core/CraftCollectionExtensions.cs b/Projects/UOContent/Engines/Craft/Core/CraftCollectionExtensions.cs index a1d4528d9..8f8ba61fc 100644 --- a/Projects/UOContent/Engines/Craft/Core/CraftCollectionExtensions.cs +++ b/Projects/UOContent/Engines/Craft/Core/CraftCollectionExtensions.cs @@ -1,49 +1,49 @@ -using System; -using System.Collections.Generic; - -namespace Server.Engines.Craft -{ - public static class CraftCollectionExtensions - { - public static int SearchFor(this List list, TextDefinition groupName) - { - for (int i = 0; i < list.Count; i++) - { - CraftGroup craftGroup = list[i]; - - int nameNumber = craftGroup.NameNumber; - string nameString = craftGroup.NameString; - - if (nameNumber != 0 && nameNumber == groupName.Number || - nameString != null && nameString == groupName.String) - return i; - } - - return -1; - } - - public static CraftItem SearchForSubclass(this List list, Type type) - { - for (int i = 0; i < list.Count; i++) - { - CraftItem craftItem = list[i]; - - if (craftItem.ItemType == type || type.IsSubclassOf(craftItem.ItemType)) - return craftItem; - } - - return null; - } - - public static CraftItem SearchFor(this List list, Type type) - { - for (int i = 0; i < list.Count; i++) - { - CraftItem craftItem = list[i]; - if (craftItem.ItemType == type) return craftItem; - } - - return null; - } - } -} +using System; +using System.Collections.Generic; + +namespace Server.Engines.Craft +{ + public static class CraftCollectionExtensions + { + public static int SearchFor(this List list, TextDefinition groupName) + { + for (var i = 0; i < list.Count; i++) + { + var craftGroup = list[i]; + + var nameNumber = craftGroup.NameNumber; + var nameString = craftGroup.NameString; + + if (nameNumber != 0 && nameNumber == groupName.Number || + nameString != null && nameString == groupName.String) + return i; + } + + return -1; + } + + public static CraftItem SearchForSubclass(this List list, Type type) + { + for (var i = 0; i < list.Count; i++) + { + var craftItem = list[i]; + + if (craftItem.ItemType == type || type.IsSubclassOf(craftItem.ItemType)) + return craftItem; + } + + return null; + } + + public static CraftItem SearchFor(this List list, Type type) + { + for (var i = 0; i < list.Count; i++) + { + var craftItem = list[i]; + if (craftItem.ItemType == type) return craftItem; + } + + return null; + } + } +} diff --git a/Projects/UOContent/Engines/Craft/Core/CraftContext.cs b/Projects/UOContent/Engines/Craft/Core/CraftContext.cs index 151dbcd70..dcaf0a8ce 100644 --- a/Projects/UOContent/Engines/Craft/Core/CraftContext.cs +++ b/Projects/UOContent/Engines/Craft/Core/CraftContext.cs @@ -1,55 +1,55 @@ -using System.Collections.Generic; - -namespace Server.Engines.Craft -{ - public enum CraftMarkOption - { - MarkItem, - DoNotMark, - PromptForMark - } - - public class CraftContext - { - public CraftContext() - { - Items = new List(); - LastResourceIndex = -1; - LastResourceIndex2 = -1; - LastGroupIndex = -1; - } - - public List Items { get; } - - public int LastResourceIndex { get; set; } - - public int LastResourceIndex2 { get; set; } - - public int LastGroupIndex { get; set; } - - public bool DoNotColor { get; set; } - - public CraftMarkOption MarkOption { get; set; } - - public CraftItem LastMade - { - get - { - if (Items.Count > 0) - return Items[0]; - - return null; - } - } - - public void OnMade(CraftItem item) - { - Items.Remove(item); - - if (Items.Count == 10) - Items.RemoveAt(9); - - Items.Insert(0, item); - } - } -} \ No newline at end of file +using System.Collections.Generic; + +namespace Server.Engines.Craft +{ + public enum CraftMarkOption + { + MarkItem, + DoNotMark, + PromptForMark + } + + public class CraftContext + { + public CraftContext() + { + Items = new List(); + LastResourceIndex = -1; + LastResourceIndex2 = -1; + LastGroupIndex = -1; + } + + public List Items { get; } + + public int LastResourceIndex { get; set; } + + public int LastResourceIndex2 { get; set; } + + public int LastGroupIndex { get; set; } + + public bool DoNotColor { get; set; } + + public CraftMarkOption MarkOption { get; set; } + + public CraftItem LastMade + { + get + { + if (Items.Count > 0) + return Items[0]; + + return null; + } + } + + public void OnMade(CraftItem item) + { + Items.Remove(item); + + if (Items.Count == 10) + Items.RemoveAt(9); + + Items.Insert(0, item); + } + } +} diff --git a/Projects/UOContent/Engines/Craft/Core/CraftGroup.cs b/Projects/UOContent/Engines/Craft/Core/CraftGroup.cs index b72e64525..52d75d9af 100644 --- a/Projects/UOContent/Engines/Craft/Core/CraftGroup.cs +++ b/Projects/UOContent/Engines/Craft/Core/CraftGroup.cs @@ -1,25 +1,25 @@ -using System.Collections.Generic; - -namespace Server.Engines.Craft -{ - public class CraftGroup - { - public CraftGroup(TextDefinition groupName) - { - NameNumber = groupName; - NameString = groupName; - CraftItems = new List(); - } - - public List CraftItems { get; } - - public string NameString { get; } - - public int NameNumber { get; } - - public void AddCraftItem(CraftItem craftItem) - { - CraftItems.Add(craftItem); - } - } -} +using System.Collections.Generic; + +namespace Server.Engines.Craft +{ + public class CraftGroup + { + public CraftGroup(TextDefinition groupName) + { + NameNumber = groupName; + NameString = groupName; + CraftItems = new List(); + } + + public List CraftItems { get; } + + public string NameString { get; } + + public int NameNumber { get; } + + public void AddCraftItem(CraftItem craftItem) + { + CraftItems.Add(craftItem); + } + } +} diff --git a/Projects/UOContent/Engines/Craft/Core/CraftGump.cs b/Projects/UOContent/Engines/Craft/Core/CraftGump.cs index d11c700b5..675b7a4f1 100644 --- a/Projects/UOContent/Engines/Craft/Core/CraftGump.cs +++ b/Projects/UOContent/Engines/Craft/Core/CraftGump.cs @@ -1,599 +1,629 @@ -using System; -using System.Collections.Generic; -using Server.Gumps; -using Server.Items; -using Server.Network; - -namespace Server.Engines.Craft -{ - public class CraftGump : Gump - { - private const int LabelHue = 0x480; - private const int LabelColor = 0x7FFF; - private const int FontColor = 0xFFFFFF; - private readonly CraftSystem m_CraftSystem; - private readonly Mobile m_From; - - private readonly CraftPage m_Page; - private readonly BaseTool m_Tool; - - public CraftGump(Mobile from, CraftSystem craftSystem, BaseTool tool, object notice, CraftPage page = CraftPage.None) : base(40, 40) - { - m_From = from; - m_CraftSystem = craftSystem; - m_Tool = tool; - m_Page = page; - - CraftContext context = craftSystem.GetContext(from); - - from.CloseGump(); - from.CloseGump(); - - AddPage(0); - - AddBackground(0, 0, 530, 437, 5054); - AddImageTiled(10, 10, 510, 22, 2624); - AddImageTiled(10, 292, 150, 45, 2624); - AddImageTiled(165, 292, 355, 45, 2624); - AddImageTiled(10, 342, 510, 85, 2624); - AddImageTiled(10, 37, 200, 250, 2624); - AddImageTiled(215, 37, 305, 250, 2624); - AddAlphaRegion(10, 10, 510, 417); - - if (craftSystem.GumpTitleNumber > 0) - AddHtmlLocalized(10, 12, 510, 20, craftSystem.GumpTitleNumber, LabelColor); - else - AddHtml(10, 12, 510, 20, craftSystem.GumpTitleString); - - AddHtmlLocalized(10, 37, 200, 22, 1044010, LabelColor); //
CATEGORIES
- AddHtmlLocalized(215, 37, 305, 22, 1044011, LabelColor); //
SELECTIONS
- AddHtmlLocalized(10, 302, 150, 25, 1044012, LabelColor); //
NOTICES
- - AddButton(15, 402, 4017, 4019, 0); - AddHtmlLocalized(50, 405, 150, 18, 1011441, LabelColor); // EXIT - - AddButton(270, 402, 4005, 4007, GetButtonID(6, 2)); - AddHtmlLocalized(305, 405, 150, 18, 1044013, LabelColor); // MAKE LAST - - // Mark option - if (craftSystem.MarkOption) - { - AddButton(270, 362, 4005, 4007, GetButtonID(6, 6)); - AddHtmlLocalized(305, 365, 150, 18, 1044017 + (context == null ? 0 : (int)context.MarkOption), LabelColor); // MARK ITEM - } - // **************************************** - - // Resmelt option - if (craftSystem.Resmelt) - { - AddButton(15, 342, 4005, 4007, GetButtonID(6, 1)); - AddHtmlLocalized(50, 345, 150, 18, 1044259, LabelColor); // SMELT ITEM - } - // **************************************** - - // Repair option - if (craftSystem.Repair) - { - AddButton(270, 342, 4005, 4007, GetButtonID(6, 5)); - AddHtmlLocalized(305, 345, 150, 18, 1044260, LabelColor); // REPAIR ITEM - } - // **************************************** - - // Enhance option - if (craftSystem.CanEnhance) - { - AddButton(270, 382, 4005, 4007, GetButtonID(6, 8)); - AddHtmlLocalized(305, 385, 150, 18, 1061001, LabelColor); // ENHANCE ITEM - } - // **************************************** - - if (notice is int noticeInt && noticeInt > 0) - AddHtmlLocalized(170, 295, 350, 40, noticeInt, LabelColor); - else if (notice is string) - AddHtml(170, 295, 350, 40, $"{notice}"); - - // If the system has more than one resource - if (craftSystem.CraftSubRes.Init) - { - string nameString = craftSystem.CraftSubRes.NameString; - int nameNumber = craftSystem.CraftSubRes.NameNumber; - - int resIndex = context?.LastResourceIndex ?? -1; - - Type resourceType = craftSystem.CraftSubRes.ResType; - - if (resIndex > -1) - { - CraftSubRes subResource = craftSystem.CraftSubRes.GetAt(resIndex); - - nameString = subResource.NameString; - nameNumber = subResource.NameNumber; - resourceType = subResource.ItemType; - } - - int resourceCount = 0; - - if (from.Backpack != null) - { - Item[] items = from.Backpack.FindItemsByType(resourceType); - - for (int i = 0; i < items.Length; ++i) - resourceCount += items[i].Amount; - } - - AddButton(15, 362, 4005, 4007, GetButtonID(6, 0)); - - if (nameNumber > 0) - AddHtmlLocalized(50, 365, 250, 18, nameNumber, resourceCount.ToString(), LabelColor); - else - AddLabel(50, 362, LabelHue, $"{nameString} ({resourceCount} Available)"); - } - // **************************************** - - // For dragon scales - if (craftSystem.CraftSubRes2.Init) - { - string nameString = craftSystem.CraftSubRes2.NameString; - int nameNumber = craftSystem.CraftSubRes2.NameNumber; - - int resIndex = context?.LastResourceIndex2 ?? -1; - - Type resourceType = craftSystem.CraftSubRes2.ResType; - - if (resIndex > -1) - { - CraftSubRes subResource = craftSystem.CraftSubRes2.GetAt(resIndex); - - nameString = subResource.NameString; - nameNumber = subResource.NameNumber; - resourceType = subResource.ItemType; - } - - int resourceCount = 0; - - if (from.Backpack != null) - { - Item[] items = from.Backpack.FindItemsByType(resourceType); - - for (int i = 0; i < items.Length; ++i) - resourceCount += items[i].Amount; - } - - AddButton(15, 382, 4005, 4007, GetButtonID(6, 7)); - - if (nameNumber > 0) - AddHtmlLocalized(50, 385, 250, 18, nameNumber, resourceCount.ToString(), LabelColor); - else - AddLabel(50, 385, LabelHue, $"{nameString} ({resourceCount} Available)"); - } - // **************************************** - - CreateGroupList(); - - if (page == CraftPage.PickResource) - CreateResList(false, from); - else if (page == CraftPage.PickResource2) - CreateResList(true, from); - else if (context?.LastGroupIndex > -1) - CreateItemList(context.LastGroupIndex); - } - - public void CreateResList(bool opt, Mobile from) - { - CraftSubResCol res = opt ? m_CraftSystem.CraftSubRes2 : m_CraftSystem.CraftSubRes; - - for (int i = 0; i < res.Count; ++i) - { - int index = i % 10; - - CraftSubRes subResource = res[i]; - - if (index == 0) - { - if (i > 0) - AddButton(485, 260, 4005, 4007, 0, GumpButtonType.Page, i / 10 + 1); - - AddPage(i / 10 + 1); - - if (i > 0) - AddButton(455, 260, 4014, 4015, 0, GumpButtonType.Page, i / 10); - - CraftContext context = m_CraftSystem.GetContext(m_From); - - AddButton(220, 260, 4005, 4007, GetButtonID(6, 4)); - AddHtmlLocalized(255, 263, 200, 18, context?.DoNotColor != true ? 1061591 : 1061590, - LabelColor); - } - - int resourceCount = 0; - - if (from.Backpack != null) - { - Item[] items = from.Backpack.FindItemsByType(subResource.ItemType); - - for (int j = 0; j < items.Length; ++j) - resourceCount += items[j].Amount; - } - - AddButton(220, 60 + index * 20, 4005, 4007, GetButtonID(5, i)); - - if (subResource.NameNumber > 0) - AddHtmlLocalized(255, 63 + index * 20, 250, 18, subResource.NameNumber, resourceCount.ToString(), - LabelColor); - else - AddLabel(255, 60 + index * 20, LabelHue, $"{subResource.NameString} ({resourceCount})"); - } - } - - public void CreateMakeLastList() - { - CraftContext context = m_CraftSystem.GetContext(m_From); - - if (context == null) - return; - - List items = context.Items; - - if (items.Count > 0) - for (int i = 0; i < items.Count; ++i) - { - int index = i % 10; - - CraftItem craftItem = items[i]; - - if (index == 0) - { - if (i > 0) - { - AddButton(370, 260, 4005, 4007, 0, GumpButtonType.Page, i / 10 + 1); - AddHtmlLocalized(405, 263, 100, 18, 1044045, LabelColor); // NEXT PAGE - } - - AddPage(i / 10 + 1); - - if (i > 0) - { - AddButton(220, 260, 4014, 4015, 0, GumpButtonType.Page, i / 10); - AddHtmlLocalized(255, 263, 100, 18, 1044044, LabelColor); // PREV PAGE - } - } - - AddButton(220, 60 + index * 20, 4005, 4007, GetButtonID(3, i)); - - if (craftItem.NameNumber > 0) - AddHtmlLocalized(255, 63 + index * 20, 220, 18, craftItem.NameNumber, LabelColor); - else - AddLabel(255, 60 + index * 20, LabelHue, craftItem.NameString); - - AddButton(480, 60 + index * 20, 4011, 4012, GetButtonID(4, i)); - } - else - AddHtmlLocalized(230, 62, 200, 22, 1044165, LabelColor); // You haven't made anything yet. - } - - public void CreateItemList(int selectedGroup) - { - if (selectedGroup == 501) // 501 : Last 10 - { - CreateMakeLastList(); - return; - } - - CraftGroup craftGroup = m_CraftSystem.CraftGroups[selectedGroup]; - List craftItemCol = craftGroup.CraftItems; - - for (int i = 0; i < craftItemCol.Count; ++i) - { - int index = i % 10; - - CraftItem craftItem = craftItemCol[i]; - - if (index == 0) - { - if (i > 0) - { - AddButton(370, 260, 4005, 4007, 0, GumpButtonType.Page, i / 10 + 1); - AddHtmlLocalized(405, 263, 100, 18, 1044045, LabelColor); // NEXT PAGE - } - - AddPage(i / 10 + 1); - - if (i > 0) - { - AddButton(220, 260, 4014, 4015, 0, GumpButtonType.Page, i / 10); - AddHtmlLocalized(255, 263, 100, 18, 1044044, LabelColor); // PREV PAGE - } - } - - AddButton(220, 60 + index * 20, 4005, 4007, GetButtonID(1, i)); - - if (craftItem.NameNumber > 0) - AddHtmlLocalized(255, 63 + index * 20, 220, 18, craftItem.NameNumber, LabelColor); - else - AddLabel(255, 60 + index * 20, LabelHue, craftItem.NameString); - - AddButton(480, 60 + index * 20, 4011, 4012, GetButtonID(2, i)); - } - } - - public int CreateGroupList() - { - List craftGroupCol = m_CraftSystem.CraftGroups; - - AddButton(15, 60, 4005, 4007, GetButtonID(6, 3)); - AddHtmlLocalized(50, 63, 150, 18, 1044014, LabelColor); // LAST TEN - - for (int i = 0; i < craftGroupCol.Count; i++) - { - CraftGroup craftGroup = craftGroupCol[i]; - - AddButton(15, 80 + i * 20, 4005, 4007, GetButtonID(0, i)); - - if (craftGroup.NameNumber > 0) - AddHtmlLocalized(50, 83 + i * 20, 150, 18, craftGroup.NameNumber, LabelColor); - else - AddLabel(50, 80 + i * 20, LabelHue, craftGroup.NameString); - } - - return craftGroupCol.Count; - } - - public static int GetButtonID(int type, int index) => 1 + type + index * 7; - - public void CraftItem(CraftItem item) - { - int num = m_CraftSystem.CanCraft(m_From, m_Tool, item.ItemType); - - if (num > 0) - { - m_From.SendGump(new CraftGump(m_From, m_CraftSystem, m_Tool, num)); - } - else - { - Type type = null; - - CraftContext context = m_CraftSystem.GetContext(m_From); - - if (context != null) - { - CraftSubResCol res = item.UseSubRes2 ? m_CraftSystem.CraftSubRes2 : m_CraftSystem.CraftSubRes; - int resIndex = item.UseSubRes2 ? context.LastResourceIndex2 : context.LastResourceIndex; - - if (resIndex >= 0 && resIndex < res.Count) - type = res.GetAt(resIndex).ItemType; - } - - m_CraftSystem.CreateItem(m_From, item.ItemType, type, m_Tool, item); - } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID <= 0) - return; // Canceled - - int buttonID = info.ButtonID - 1; - int type = buttonID % 7; - int index = buttonID / 7; - - CraftSystem system = m_CraftSystem; - List groups = system.CraftGroups; - CraftContext context = system.GetContext(m_From); - - switch (type) - { - case 0: // Show group - { - if (context == null) - break; - - if (index >= 0 && index < groups.Count) - { - context.LastGroupIndex = index; - m_From.SendGump(new CraftGump(m_From, system, m_Tool, null)); - } - - break; - } - case 1: // Create item - { - if (context == null) - break; - - int groupIndex = context.LastGroupIndex; - - if (groupIndex >= 0 && groupIndex < groups.Count) - { - CraftGroup group = groups[groupIndex]; - - if (index >= 0 && index < group.CraftItems.Count) - CraftItem(group.CraftItems[index]); - } - - break; - } - case 2: // Item details - { - if (context == null) - break; - - int groupIndex = context.LastGroupIndex; - - if (groupIndex >= 0 && groupIndex < groups.Count) - { - CraftGroup group = groups[groupIndex]; - - if (index >= 0 && index < group.CraftItems.Count) - m_From.SendGump(new CraftGumpItem(m_From, system, group.CraftItems[index], m_Tool)); - } - - break; - } - case 3: // Create item (last 10) - { - if (context == null) - break; - - List lastTen = context.Items; - - if (index >= 0 && index < lastTen.Count) - CraftItem(lastTen[index]); - - break; - } - case 4: // Item details (last 10) - { - if (context == null) - break; - - List lastTen = context.Items; - - if (index >= 0 && index < lastTen.Count) - m_From.SendGump(new CraftGumpItem(m_From, system, lastTen[index], m_Tool)); - - break; - } - case 5: // Resource selected - { - if (m_Page == CraftPage.PickResource && index >= 0 && index < system.CraftSubRes.Count) - { - CraftSubRes res = system.CraftSubRes.GetAt(index); - - if (m_From.Skills[system.MainSkill].Base < res.RequiredSkill) - { - m_From.SendGump(new CraftGump(m_From, system, m_Tool, res.Message)); - } - else - { - if (context != null) - context.LastResourceIndex = index; - - m_From.SendGump(new CraftGump(m_From, system, m_Tool, null)); - } - } - else if (m_Page == CraftPage.PickResource2 && index >= 0 && index < system.CraftSubRes2.Count) - { - CraftSubRes res = system.CraftSubRes2.GetAt(index); - - if (m_From.Skills[system.MainSkill].Base < res.RequiredSkill) - { - m_From.SendGump(new CraftGump(m_From, system, m_Tool, res.Message)); - } - else - { - if (context != null) - context.LastResourceIndex2 = index; - - m_From.SendGump(new CraftGump(m_From, system, m_Tool, null)); - } - } - - break; - } - case 6: // Misc. buttons - { - switch (index) - { - case 0: // Resource selection - { - if (system.CraftSubRes.Init) - m_From.SendGump(new CraftGump(m_From, system, m_Tool, null, CraftPage.PickResource)); - - break; - } - case 1: // Smelt item - { - if (system.Resmelt) - Resmelt.Do(m_From, system, m_Tool); - - break; - } - case 2: // Make last - { - if (context == null) - break; - - CraftItem item = context.LastMade; - - if (item != null) - CraftItem(item); - else - m_From.SendGump(new CraftGump(m_From, m_CraftSystem, m_Tool, 1044165, - m_Page)); // You haven't made anything yet. - - break; - } - case 3: // Last 10 - { - if (context == null) - break; - - context.LastGroupIndex = 501; - m_From.SendGump(new CraftGump(m_From, system, m_Tool, null)); - - break; - } - case 4: // Toggle use resource hue - { - if (context == null) - break; - - context.DoNotColor = !context.DoNotColor; - - m_From.SendGump(new CraftGump(m_From, m_CraftSystem, m_Tool, null, m_Page)); - - break; - } - case 5: // Repair item - { - if (system.Repair) - Repair.Do(m_From, system, m_Tool); - - break; - } - case 6: // Toggle mark option - { - if (context == null || !system.MarkOption) - break; - - context.MarkOption = context.MarkOption switch - { - CraftMarkOption.MarkItem => CraftMarkOption.DoNotMark, - CraftMarkOption.DoNotMark => CraftMarkOption.PromptForMark, - CraftMarkOption.PromptForMark => CraftMarkOption.MarkItem, - _ => context.MarkOption - }; - - m_From.SendGump(new CraftGump(m_From, m_CraftSystem, m_Tool, null, m_Page)); - - break; - } - case 7: // Resource selection 2 - { - if (system.CraftSubRes2.Init) - m_From.SendGump(new CraftGump(m_From, system, m_Tool, null, CraftPage.PickResource2)); - - break; - } - case 8: // Enhance item - { - if (system.CanEnhance) - Enhance.BeginTarget(m_From, system, m_Tool); - - break; - } - } - - break; - } - } - } - - public enum CraftPage - { - None, - PickResource, - PickResource2 - } - } -} +using System; +using Server.Gumps; +using Server.Items; +using Server.Network; + +namespace Server.Engines.Craft +{ + public class CraftGump : Gump + { + public enum CraftPage + { + None, + PickResource, + PickResource2 + } + + private const int LabelHue = 0x480; + private const int LabelColor = 0x7FFF; + private const int FontColor = 0xFFFFFF; + private readonly CraftSystem m_CraftSystem; + private readonly Mobile m_From; + + private readonly CraftPage m_Page; + private readonly BaseTool m_Tool; + + public CraftGump( + Mobile from, CraftSystem craftSystem, BaseTool tool, object notice, CraftPage page = CraftPage.None + ) : base(40, 40) + { + m_From = from; + m_CraftSystem = craftSystem; + m_Tool = tool; + m_Page = page; + + var context = craftSystem.GetContext(from); + + from.CloseGump(); + from.CloseGump(); + + AddPage(0); + + AddBackground(0, 0, 530, 437, 5054); + AddImageTiled(10, 10, 510, 22, 2624); + AddImageTiled(10, 292, 150, 45, 2624); + AddImageTiled(165, 292, 355, 45, 2624); + AddImageTiled(10, 342, 510, 85, 2624); + AddImageTiled(10, 37, 200, 250, 2624); + AddImageTiled(215, 37, 305, 250, 2624); + AddAlphaRegion(10, 10, 510, 417); + + if (craftSystem.GumpTitleNumber > 0) + AddHtmlLocalized(10, 12, 510, 20, craftSystem.GumpTitleNumber, LabelColor); + else + AddHtml(10, 12, 510, 20, craftSystem.GumpTitleString); + + AddHtmlLocalized(10, 37, 200, 22, 1044010, LabelColor); //
CATEGORIES
+ AddHtmlLocalized(215, 37, 305, 22, 1044011, LabelColor); //
SELECTIONS
+ AddHtmlLocalized(10, 302, 150, 25, 1044012, LabelColor); //
NOTICES
+ + AddButton(15, 402, 4017, 4019, 0); + AddHtmlLocalized(50, 405, 150, 18, 1011441, LabelColor); // EXIT + + AddButton(270, 402, 4005, 4007, GetButtonID(6, 2)); + AddHtmlLocalized(305, 405, 150, 18, 1044013, LabelColor); // MAKE LAST + + // Mark option + if (craftSystem.MarkOption) + { + AddButton(270, 362, 4005, 4007, GetButtonID(6, 6)); + AddHtmlLocalized( + 305, + 365, + 150, + 18, + 1044017 + (context == null ? 0 : (int)context.MarkOption), + LabelColor + ); // MARK ITEM + } + // **************************************** + + // Resmelt option + if (craftSystem.Resmelt) + { + AddButton(15, 342, 4005, 4007, GetButtonID(6, 1)); + AddHtmlLocalized(50, 345, 150, 18, 1044259, LabelColor); // SMELT ITEM + } + // **************************************** + + // Repair option + if (craftSystem.Repair) + { + AddButton(270, 342, 4005, 4007, GetButtonID(6, 5)); + AddHtmlLocalized(305, 345, 150, 18, 1044260, LabelColor); // REPAIR ITEM + } + // **************************************** + + // Enhance option + if (craftSystem.CanEnhance) + { + AddButton(270, 382, 4005, 4007, GetButtonID(6, 8)); + AddHtmlLocalized(305, 385, 150, 18, 1061001, LabelColor); // ENHANCE ITEM + } + // **************************************** + + if (notice is int noticeInt && noticeInt > 0) + AddHtmlLocalized(170, 295, 350, 40, noticeInt, LabelColor); + else if (notice is string) + AddHtml(170, 295, 350, 40, $"{notice}"); + + // If the system has more than one resource + if (craftSystem.CraftSubRes.Init) + { + var nameString = craftSystem.CraftSubRes.NameString; + var nameNumber = craftSystem.CraftSubRes.NameNumber; + + var resIndex = context?.LastResourceIndex ?? -1; + + var resourceType = craftSystem.CraftSubRes.ResType; + + if (resIndex > -1) + { + var subResource = craftSystem.CraftSubRes.GetAt(resIndex); + + nameString = subResource.NameString; + nameNumber = subResource.NameNumber; + resourceType = subResource.ItemType; + } + + var resourceCount = 0; + + if (from.Backpack != null) + { + var items = from.Backpack.FindItemsByType(resourceType); + + for (var i = 0; i < items.Length; ++i) + resourceCount += items[i].Amount; + } + + AddButton(15, 362, 4005, 4007, GetButtonID(6, 0)); + + if (nameNumber > 0) + AddHtmlLocalized(50, 365, 250, 18, nameNumber, resourceCount.ToString(), LabelColor); + else + AddLabel(50, 362, LabelHue, $"{nameString} ({resourceCount} Available)"); + } + // **************************************** + + // For dragon scales + if (craftSystem.CraftSubRes2.Init) + { + var nameString = craftSystem.CraftSubRes2.NameString; + var nameNumber = craftSystem.CraftSubRes2.NameNumber; + + var resIndex = context?.LastResourceIndex2 ?? -1; + + var resourceType = craftSystem.CraftSubRes2.ResType; + + if (resIndex > -1) + { + var subResource = craftSystem.CraftSubRes2.GetAt(resIndex); + + nameString = subResource.NameString; + nameNumber = subResource.NameNumber; + resourceType = subResource.ItemType; + } + + var resourceCount = 0; + + if (from.Backpack != null) + { + var items = from.Backpack.FindItemsByType(resourceType); + + for (var i = 0; i < items.Length; ++i) + resourceCount += items[i].Amount; + } + + AddButton(15, 382, 4005, 4007, GetButtonID(6, 7)); + + if (nameNumber > 0) + AddHtmlLocalized(50, 385, 250, 18, nameNumber, resourceCount.ToString(), LabelColor); + else + AddLabel(50, 385, LabelHue, $"{nameString} ({resourceCount} Available)"); + } + // **************************************** + + CreateGroupList(); + + if (page == CraftPage.PickResource) + CreateResList(false, from); + else if (page == CraftPage.PickResource2) + CreateResList(true, from); + else if (context?.LastGroupIndex > -1) + CreateItemList(context.LastGroupIndex); + } + + public void CreateResList(bool opt, Mobile from) + { + var res = opt ? m_CraftSystem.CraftSubRes2 : m_CraftSystem.CraftSubRes; + + for (var i = 0; i < res.Count; ++i) + { + var index = i % 10; + + var subResource = res[i]; + + if (index == 0) + { + if (i > 0) + AddButton(485, 260, 4005, 4007, 0, GumpButtonType.Page, i / 10 + 1); + + AddPage(i / 10 + 1); + + if (i > 0) + AddButton(455, 260, 4014, 4015, 0, GumpButtonType.Page, i / 10); + + var context = m_CraftSystem.GetContext(m_From); + + AddButton(220, 260, 4005, 4007, GetButtonID(6, 4)); + AddHtmlLocalized( + 255, + 263, + 200, + 18, + context?.DoNotColor != true ? 1061591 : 1061590, + LabelColor + ); + } + + var resourceCount = 0; + + if (from.Backpack != null) + { + var items = from.Backpack.FindItemsByType(subResource.ItemType); + + for (var j = 0; j < items.Length; ++j) + resourceCount += items[j].Amount; + } + + AddButton(220, 60 + index * 20, 4005, 4007, GetButtonID(5, i)); + + if (subResource.NameNumber > 0) + AddHtmlLocalized( + 255, + 63 + index * 20, + 250, + 18, + subResource.NameNumber, + resourceCount.ToString(), + LabelColor + ); + else + AddLabel(255, 60 + index * 20, LabelHue, $"{subResource.NameString} ({resourceCount})"); + } + } + + public void CreateMakeLastList() + { + var context = m_CraftSystem.GetContext(m_From); + + if (context == null) + return; + + var items = context.Items; + + if (items.Count > 0) + for (var i = 0; i < items.Count; ++i) + { + var index = i % 10; + + var craftItem = items[i]; + + if (index == 0) + { + if (i > 0) + { + AddButton(370, 260, 4005, 4007, 0, GumpButtonType.Page, i / 10 + 1); + AddHtmlLocalized(405, 263, 100, 18, 1044045, LabelColor); // NEXT PAGE + } + + AddPage(i / 10 + 1); + + if (i > 0) + { + AddButton(220, 260, 4014, 4015, 0, GumpButtonType.Page, i / 10); + AddHtmlLocalized(255, 263, 100, 18, 1044044, LabelColor); // PREV PAGE + } + } + + AddButton(220, 60 + index * 20, 4005, 4007, GetButtonID(3, i)); + + if (craftItem.NameNumber > 0) + AddHtmlLocalized(255, 63 + index * 20, 220, 18, craftItem.NameNumber, LabelColor); + else + AddLabel(255, 60 + index * 20, LabelHue, craftItem.NameString); + + AddButton(480, 60 + index * 20, 4011, 4012, GetButtonID(4, i)); + } + else + AddHtmlLocalized(230, 62, 200, 22, 1044165, LabelColor); // You haven't made anything yet. + } + + public void CreateItemList(int selectedGroup) + { + if (selectedGroup == 501) // 501 : Last 10 + { + CreateMakeLastList(); + return; + } + + var craftGroup = m_CraftSystem.CraftGroups[selectedGroup]; + var craftItemCol = craftGroup.CraftItems; + + for (var i = 0; i < craftItemCol.Count; ++i) + { + var index = i % 10; + + var craftItem = craftItemCol[i]; + + if (index == 0) + { + if (i > 0) + { + AddButton(370, 260, 4005, 4007, 0, GumpButtonType.Page, i / 10 + 1); + AddHtmlLocalized(405, 263, 100, 18, 1044045, LabelColor); // NEXT PAGE + } + + AddPage(i / 10 + 1); + + if (i > 0) + { + AddButton(220, 260, 4014, 4015, 0, GumpButtonType.Page, i / 10); + AddHtmlLocalized(255, 263, 100, 18, 1044044, LabelColor); // PREV PAGE + } + } + + AddButton(220, 60 + index * 20, 4005, 4007, GetButtonID(1, i)); + + if (craftItem.NameNumber > 0) + AddHtmlLocalized(255, 63 + index * 20, 220, 18, craftItem.NameNumber, LabelColor); + else + AddLabel(255, 60 + index * 20, LabelHue, craftItem.NameString); + + AddButton(480, 60 + index * 20, 4011, 4012, GetButtonID(2, i)); + } + } + + public int CreateGroupList() + { + var craftGroupCol = m_CraftSystem.CraftGroups; + + AddButton(15, 60, 4005, 4007, GetButtonID(6, 3)); + AddHtmlLocalized(50, 63, 150, 18, 1044014, LabelColor); // LAST TEN + + for (var i = 0; i < craftGroupCol.Count; i++) + { + var craftGroup = craftGroupCol[i]; + + AddButton(15, 80 + i * 20, 4005, 4007, GetButtonID(0, i)); + + if (craftGroup.NameNumber > 0) + AddHtmlLocalized(50, 83 + i * 20, 150, 18, craftGroup.NameNumber, LabelColor); + else + AddLabel(50, 80 + i * 20, LabelHue, craftGroup.NameString); + } + + return craftGroupCol.Count; + } + + public static int GetButtonID(int type, int index) => 1 + type + index * 7; + + public void CraftItem(CraftItem item) + { + var num = m_CraftSystem.CanCraft(m_From, m_Tool, item.ItemType); + + if (num > 0) + { + m_From.SendGump(new CraftGump(m_From, m_CraftSystem, m_Tool, num)); + } + else + { + Type type = null; + + var context = m_CraftSystem.GetContext(m_From); + + if (context != null) + { + var res = item.UseSubRes2 ? m_CraftSystem.CraftSubRes2 : m_CraftSystem.CraftSubRes; + var resIndex = item.UseSubRes2 ? context.LastResourceIndex2 : context.LastResourceIndex; + + if (resIndex >= 0 && resIndex < res.Count) + type = res.GetAt(resIndex).ItemType; + } + + m_CraftSystem.CreateItem(m_From, item.ItemType, type, m_Tool, item); + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID <= 0) + return; // Canceled + + var buttonID = info.ButtonID - 1; + var type = buttonID % 7; + var index = buttonID / 7; + + var system = m_CraftSystem; + var groups = system.CraftGroups; + var context = system.GetContext(m_From); + + switch (type) + { + case 0: // Show group + { + if (context == null) + break; + + if (index >= 0 && index < groups.Count) + { + context.LastGroupIndex = index; + m_From.SendGump(new CraftGump(m_From, system, m_Tool, null)); + } + + break; + } + case 1: // Create item + { + if (context == null) + break; + + var groupIndex = context.LastGroupIndex; + + if (groupIndex >= 0 && groupIndex < groups.Count) + { + var group = groups[groupIndex]; + + if (index >= 0 && index < group.CraftItems.Count) + CraftItem(group.CraftItems[index]); + } + + break; + } + case 2: // Item details + { + if (context == null) + break; + + var groupIndex = context.LastGroupIndex; + + if (groupIndex >= 0 && groupIndex < groups.Count) + { + var group = groups[groupIndex]; + + if (index >= 0 && index < group.CraftItems.Count) + m_From.SendGump(new CraftGumpItem(m_From, system, group.CraftItems[index], m_Tool)); + } + + break; + } + case 3: // Create item (last 10) + { + if (context == null) + break; + + var lastTen = context.Items; + + if (index >= 0 && index < lastTen.Count) + CraftItem(lastTen[index]); + + break; + } + case 4: // Item details (last 10) + { + if (context == null) + break; + + var lastTen = context.Items; + + if (index >= 0 && index < lastTen.Count) + m_From.SendGump(new CraftGumpItem(m_From, system, lastTen[index], m_Tool)); + + break; + } + case 5: // Resource selected + { + if (m_Page == CraftPage.PickResource && index >= 0 && index < system.CraftSubRes.Count) + { + var res = system.CraftSubRes.GetAt(index); + + if (m_From.Skills[system.MainSkill].Base < res.RequiredSkill) + { + m_From.SendGump(new CraftGump(m_From, system, m_Tool, res.Message)); + } + else + { + if (context != null) + context.LastResourceIndex = index; + + m_From.SendGump(new CraftGump(m_From, system, m_Tool, null)); + } + } + else if (m_Page == CraftPage.PickResource2 && index >= 0 && index < system.CraftSubRes2.Count) + { + var res = system.CraftSubRes2.GetAt(index); + + if (m_From.Skills[system.MainSkill].Base < res.RequiredSkill) + { + m_From.SendGump(new CraftGump(m_From, system, m_Tool, res.Message)); + } + else + { + if (context != null) + context.LastResourceIndex2 = index; + + m_From.SendGump(new CraftGump(m_From, system, m_Tool, null)); + } + } + + break; + } + case 6: // Misc. buttons + { + switch (index) + { + case 0: // Resource selection + { + if (system.CraftSubRes.Init) + m_From.SendGump(new CraftGump(m_From, system, m_Tool, null, CraftPage.PickResource)); + + break; + } + case 1: // Smelt item + { + if (system.Resmelt) + Resmelt.Do(m_From, system, m_Tool); + + break; + } + case 2: // Make last + { + if (context == null) + break; + + var item = context.LastMade; + + if (item != null) + CraftItem(item); + else + m_From.SendGump( + new CraftGump( + m_From, + m_CraftSystem, + m_Tool, + 1044165, + m_Page + ) + ); // You haven't made anything yet. + + break; + } + case 3: // Last 10 + { + if (context == null) + break; + + context.LastGroupIndex = 501; + m_From.SendGump(new CraftGump(m_From, system, m_Tool, null)); + + break; + } + case 4: // Toggle use resource hue + { + if (context == null) + break; + + context.DoNotColor = !context.DoNotColor; + + m_From.SendGump(new CraftGump(m_From, m_CraftSystem, m_Tool, null, m_Page)); + + break; + } + case 5: // Repair item + { + if (system.Repair) + Repair.Do(m_From, system, m_Tool); + + break; + } + case 6: // Toggle mark option + { + if (context == null || !system.MarkOption) + break; + + context.MarkOption = context.MarkOption switch + { + CraftMarkOption.MarkItem => CraftMarkOption.DoNotMark, + CraftMarkOption.DoNotMark => CraftMarkOption.PromptForMark, + CraftMarkOption.PromptForMark => CraftMarkOption.MarkItem, + _ => context.MarkOption + }; + + m_From.SendGump(new CraftGump(m_From, m_CraftSystem, m_Tool, null, m_Page)); + + break; + } + case 7: // Resource selection 2 + { + if (system.CraftSubRes2.Init) + m_From.SendGump( + new CraftGump(m_From, system, m_Tool, null, CraftPage.PickResource2) + ); + + break; + } + case 8: // Enhance item + { + if (system.CanEnhance) + Enhance.BeginTarget(m_From, system, m_Tool); + + break; + } + } + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Craft/Core/CraftGumpItem.cs b/Projects/UOContent/Engines/Craft/Core/CraftGumpItem.cs index f359b9dc9..e7d7f40e9 100644 --- a/Projects/UOContent/Engines/Craft/Core/CraftGumpItem.cs +++ b/Projects/UOContent/Engines/Craft/Core/CraftGumpItem.cs @@ -1,273 +1,322 @@ -using System; -using Server.Gumps; -using Server.Items; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.Craft -{ - public class CraftGumpItem : Gump - { - private const int LabelHue = 0x480; // 0x384 - private const int RedLabelHue = 0x20; - - private const int LabelColor = 0x7FFF; - private const int RedLabelColor = 0x6400; - - private const int GreyLabelColor = 0x3DEF; - - private static readonly Type typeofBlankScroll = typeof(BlankScroll); - private static readonly Type typeofSpellScroll = typeof(SpellScroll); - private readonly CraftItem m_CraftItem; - private readonly CraftSystem m_CraftSystem; - private readonly Mobile m_From; - - private int m_OtherCount; - - private bool m_ShowExceptionalChance; - private readonly BaseTool m_Tool; - - public CraftGumpItem(Mobile from, CraftSystem craftSystem, CraftItem craftItem, BaseTool tool) : base(40, 40) - { - m_From = from; - m_CraftSystem = craftSystem; - m_CraftItem = craftItem; - m_Tool = tool; - - from.CloseGump(); - from.CloseGump(); - - AddPage(0); - AddBackground(0, 0, 530, 417, 5054); - AddImageTiled(10, 10, 510, 22, 2624); - AddImageTiled(10, 37, 150, 148, 2624); - AddImageTiled(165, 37, 355, 90, 2624); - AddImageTiled(10, 190, 155, 22, 2624); - AddImageTiled(10, 217, 150, 53, 2624); - AddImageTiled(165, 132, 355, 80, 2624); - AddImageTiled(10, 275, 155, 22, 2624); - AddImageTiled(10, 302, 150, 53, 2624); - AddImageTiled(165, 217, 355, 80, 2624); - AddImageTiled(10, 360, 155, 22, 2624); - AddImageTiled(165, 302, 355, 80, 2624); - AddImageTiled(10, 387, 510, 22, 2624); - AddAlphaRegion(10, 10, 510, 399); - - AddHtmlLocalized(170, 40, 150, 20, 1044053, LabelColor); // ITEM - AddHtmlLocalized(10, 192, 150, 22, 1044054, LabelColor); //
SKILLS
- AddHtmlLocalized(10, 277, 150, 22, 1044055, LabelColor); //
MATERIALS
- AddHtmlLocalized(10, 362, 150, 22, 1044056, LabelColor); //
OTHER
- - if (craftSystem.GumpTitleNumber > 0) - AddHtmlLocalized(10, 12, 510, 20, craftSystem.GumpTitleNumber, LabelColor); - else - AddHtml(10, 12, 510, 20, craftSystem.GumpTitleString); - - AddButton(15, 387, 4014, 4016, 0); - AddHtmlLocalized(50, 390, 150, 18, 1044150, LabelColor); // BACK - - bool needsRecipe = craftItem.Recipe != null && from is PlayerMobile mobile && - !mobile.HasRecipe(craftItem.Recipe); - - if (needsRecipe) - { - AddButton(270, 387, 4005, 4007, 0, GumpButtonType.Page); - AddHtmlLocalized(305, 390, 150, 18, 1044151, GreyLabelColor); // MAKE NOW - } - else - { - AddButton(270, 387, 4005, 4007, 1); - AddHtmlLocalized(305, 390, 150, 18, 1044151, LabelColor); // MAKE NOW - } - - if (craftItem.NameNumber > 0) - AddHtmlLocalized(330, 40, 180, 18, craftItem.NameNumber, LabelColor); - else - AddLabel(330, 40, LabelHue, craftItem.NameString); - - if (craftItem.UseAllRes) - AddHtmlLocalized(170, 302 + m_OtherCount++ * 20, 310, 18, 1048176, LabelColor); // Makes as many as possible at once - - DrawItem(); - DrawSkill(); - DrawResource(); - - /* - if (craftItem.RequiresSE) - AddHtmlLocalized( 170, 302 + (m_OtherCount++ * 20), 310, 18, 1063363, LabelColor, false, false ); //* Requires the "Samurai Empire" expansion - * */ - - if (craftItem.RequiredExpansion != Expansion.None) - { - bool supportsEx = from.NetState?.SupportsExpansion(craftItem.RequiredExpansion) == true; - TextDefinition.AddHtmlText(this, 170, 302 + m_OtherCount++ * 20, 310, 18, - RequiredExpansionMessage(craftItem.RequiredExpansion), false, false, - supportsEx ? LabelColor : RedLabelColor, supportsEx ? LabelHue : RedLabelHue); - } - - if (needsRecipe) - AddHtmlLocalized(170, 302 + m_OtherCount++ * 20, 310, 18, 1073620, RedLabelColor); // You have not learned this recipe. - } - - private TextDefinition RequiredExpansionMessage(Expansion expansion) - { - return expansion switch - { - Expansion.SE => (TextDefinition)1063363, // * Requires the "Samurai Empire" expansion - Expansion.ML => (TextDefinition)1072651, // * Requires the "Mondain's Legacy" expansion - _ => (TextDefinition)$"* Requires the \"{ExpansionInfo.GetInfo(expansion).Name}\" expansion" - }; - } - - public void DrawItem() - { - Type type = m_CraftItem.ItemType; - - AddItem(20, 50, CraftItem.ItemIDOf(type), m_CraftItem.ItemHue); - - if (m_CraftItem.IsMarkable(type)) - { - AddHtmlLocalized(170, 302 + m_OtherCount++ * 20, 310, 18, 1044059, LabelColor); // This item may hold its maker's mark - m_ShowExceptionalChance = true; - } - } - - public void DrawSkill() - { - for (int i = 0; i < m_CraftItem.Skills.Count; i++) - { - CraftSkill skill = m_CraftItem.Skills[i]; - double minSkill = Math.Max(skill.MinSkill, 0); - - AddHtmlLocalized(170, 132 + i * 20, 200, 18, AosSkillBonuses.GetLabel(skill.SkillToMake), LabelColor); - AddLabel(430, 132 + i * 20, LabelHue, $"{minSkill:F1}"); - } - - CraftSubResCol res = m_CraftItem.UseSubRes2 ? m_CraftSystem.CraftSubRes2 : m_CraftSystem.CraftSubRes; - int resIndex = -1; - - CraftContext context = m_CraftSystem.GetContext(m_From); - - if (context != null) - resIndex = m_CraftItem.UseSubRes2 ? context.LastResourceIndex2 : context.LastResourceIndex; - - double chance = m_CraftItem.GetSuccessChance(m_From, resIndex > -1 ? res.GetAt(resIndex).ItemType : null, - m_CraftSystem, false, out _); - - AddHtmlLocalized(170, 80, 250, 18, 1044057, LabelColor); // Success Chance: - AddLabel(430, 80, LabelHue, $"{Math.Clamp(chance, 0, 1) * 100:F1}%"); - - if (m_ShowExceptionalChance) - { - double exceptChance = Math.Clamp(m_CraftItem.GetExceptionalChance(m_CraftSystem, chance, m_From), 0, 1.0); - - AddHtmlLocalized(170, 100, 250, 18, 1044058, 32767); // Exceptional Chance: - AddLabel(430, 100, LabelHue, $"{exceptChance * 100:F1}%"); - } - } - - public void DrawResource() - { - bool retainedColor = false; - - CraftContext context = m_CraftSystem.GetContext(m_From); - - CraftSubResCol res = m_CraftItem.UseSubRes2 ? m_CraftSystem.CraftSubRes2 : m_CraftSystem.CraftSubRes; - int resIndex = -1; - - if (context != null) - resIndex = m_CraftItem.UseSubRes2 ? context.LastResourceIndex2 : context.LastResourceIndex; - - bool cropScroll = m_CraftItem.Resources.Count > 1 - && m_CraftItem.Resources[^1].ItemType == typeofBlankScroll - && typeofSpellScroll.IsAssignableFrom(m_CraftItem.ItemType); - - for (int i = 0; i < m_CraftItem.Resources.Count - (cropScroll ? 1 : 0) && i < 4; i++) - { - Type type; - string nameString; - int nameNumber; - - CraftRes craftResource = m_CraftItem.Resources[i]; - - type = craftResource.ItemType; - nameString = craftResource.NameString; - nameNumber = craftResource.NameNumber; - - // Resource Mutation - if (type == res.ResType && resIndex > -1) - { - CraftSubRes subResource = res.GetAt(resIndex); - - type = subResource.ItemType; - - nameString = subResource.NameString; - nameNumber = subResource.GenericNameNumber; - - if (nameNumber <= 0) - nameNumber = subResource.NameNumber; - } - // ****************** - - if (!retainedColor && m_CraftItem.RetainsColorFrom(m_CraftSystem, type)) - { - retainedColor = true; - AddHtmlLocalized(170, 302 + m_OtherCount++ * 20, 310, 18, 1044152, LabelColor); // * The item retains the color of this material - AddLabel(500, 219 + i * 20, LabelHue, "*"); - } - - if (nameNumber > 0) - AddHtmlLocalized(170, 219 + i * 20, 310, 18, nameNumber, LabelColor); - else - AddLabel(170, 219 + i * 20, LabelHue, nameString); - - AddLabel(430, 219 + i * 20, LabelHue, craftResource.Amount.ToString()); - } - - if (m_CraftItem.NameNumber == 1041267) // runebook - { - AddHtmlLocalized(170, 219 + m_CraftItem.Resources.Count * 20, 310, 18, 1044447, LabelColor); - AddLabel(430, 219 + m_CraftItem.Resources.Count * 20, LabelHue, "1"); - } - - if (cropScroll) - AddHtmlLocalized(170, 302 + m_OtherCount++ * 20, 360, 18, 1044379, LabelColor); // Inscribing scrolls also requires a blank scroll and mana. - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - // Back Button - if (info.ButtonID == 0) - { - CraftGump craftGump = new CraftGump(m_From, m_CraftSystem, m_Tool, null); - m_From.SendGump(craftGump); - } - else // Make Button - { - int num = m_CraftSystem.CanCraft(m_From, m_Tool, m_CraftItem.ItemType); - - if (num > 0) - { - m_From.SendGump(new CraftGump(m_From, m_CraftSystem, m_Tool, num)); - } - else - { - Type type = null; - - CraftContext context = m_CraftSystem.GetContext(m_From); - - if (context != null) - { - CraftSubResCol res = m_CraftItem.UseSubRes2 ? m_CraftSystem.CraftSubRes2 : m_CraftSystem.CraftSubRes; - int resIndex = m_CraftItem.UseSubRes2 ? context.LastResourceIndex2 : context.LastResourceIndex; - - if (resIndex > -1) - type = res.GetAt(resIndex).ItemType; - } - - m_CraftSystem.CreateItem(m_From, m_CraftItem.ItemType, type, m_Tool, m_CraftItem); - } - } - } - } -} +using System; +using Server.Gumps; +using Server.Items; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.Craft +{ + public class CraftGumpItem : Gump + { + private const int LabelHue = 0x480; // 0x384 + private const int RedLabelHue = 0x20; + + private const int LabelColor = 0x7FFF; + private const int RedLabelColor = 0x6400; + + private const int GreyLabelColor = 0x3DEF; + + private static readonly Type typeofBlankScroll = typeof(BlankScroll); + private static readonly Type typeofSpellScroll = typeof(SpellScroll); + private readonly CraftItem m_CraftItem; + private readonly CraftSystem m_CraftSystem; + private readonly Mobile m_From; + private readonly BaseTool m_Tool; + + private int m_OtherCount; + + private bool m_ShowExceptionalChance; + + public CraftGumpItem(Mobile from, CraftSystem craftSystem, CraftItem craftItem, BaseTool tool) : base(40, 40) + { + m_From = from; + m_CraftSystem = craftSystem; + m_CraftItem = craftItem; + m_Tool = tool; + + from.CloseGump(); + from.CloseGump(); + + AddPage(0); + AddBackground(0, 0, 530, 417, 5054); + AddImageTiled(10, 10, 510, 22, 2624); + AddImageTiled(10, 37, 150, 148, 2624); + AddImageTiled(165, 37, 355, 90, 2624); + AddImageTiled(10, 190, 155, 22, 2624); + AddImageTiled(10, 217, 150, 53, 2624); + AddImageTiled(165, 132, 355, 80, 2624); + AddImageTiled(10, 275, 155, 22, 2624); + AddImageTiled(10, 302, 150, 53, 2624); + AddImageTiled(165, 217, 355, 80, 2624); + AddImageTiled(10, 360, 155, 22, 2624); + AddImageTiled(165, 302, 355, 80, 2624); + AddImageTiled(10, 387, 510, 22, 2624); + AddAlphaRegion(10, 10, 510, 399); + + AddHtmlLocalized(170, 40, 150, 20, 1044053, LabelColor); // ITEM + AddHtmlLocalized(10, 192, 150, 22, 1044054, LabelColor); //
SKILLS
+ AddHtmlLocalized(10, 277, 150, 22, 1044055, LabelColor); //
MATERIALS
+ AddHtmlLocalized(10, 362, 150, 22, 1044056, LabelColor); //
OTHER
+ + if (craftSystem.GumpTitleNumber > 0) + AddHtmlLocalized(10, 12, 510, 20, craftSystem.GumpTitleNumber, LabelColor); + else + AddHtml(10, 12, 510, 20, craftSystem.GumpTitleString); + + AddButton(15, 387, 4014, 4016, 0); + AddHtmlLocalized(50, 390, 150, 18, 1044150, LabelColor); // BACK + + var needsRecipe = craftItem.Recipe != null && from is PlayerMobile mobile && + !mobile.HasRecipe(craftItem.Recipe); + + if (needsRecipe) + { + AddButton(270, 387, 4005, 4007, 0, GumpButtonType.Page); + AddHtmlLocalized(305, 390, 150, 18, 1044151, GreyLabelColor); // MAKE NOW + } + else + { + AddButton(270, 387, 4005, 4007, 1); + AddHtmlLocalized(305, 390, 150, 18, 1044151, LabelColor); // MAKE NOW + } + + if (craftItem.NameNumber > 0) + AddHtmlLocalized(330, 40, 180, 18, craftItem.NameNumber, LabelColor); + else + AddLabel(330, 40, LabelHue, craftItem.NameString); + + if (craftItem.UseAllRes) + AddHtmlLocalized( + 170, + 302 + m_OtherCount++ * 20, + 310, + 18, + 1048176, + LabelColor + ); // Makes as many as possible at once + + DrawItem(); + DrawSkill(); + DrawResource(); + + /* + if (craftItem.RequiresSE) + AddHtmlLocalized( 170, 302 + (m_OtherCount++ * 20), 310, 18, 1063363, LabelColor, false, false ); //* Requires the "Samurai Empire" expansion + * */ + + if (craftItem.RequiredExpansion != Expansion.None) + { + var supportsEx = from.NetState?.SupportsExpansion(craftItem.RequiredExpansion) == true; + TextDefinition.AddHtmlText( + this, + 170, + 302 + m_OtherCount++ * 20, + 310, + 18, + RequiredExpansionMessage(craftItem.RequiredExpansion), + false, + false, + supportsEx ? LabelColor : RedLabelColor, + supportsEx ? LabelHue : RedLabelHue + ); + } + + if (needsRecipe) + AddHtmlLocalized( + 170, + 302 + m_OtherCount++ * 20, + 310, + 18, + 1073620, + RedLabelColor + ); // You have not learned this recipe. + } + + private TextDefinition RequiredExpansionMessage(Expansion expansion) + { + return expansion switch + { + Expansion.SE => (TextDefinition)1063363, // * Requires the "Samurai Empire" expansion + Expansion.ML => (TextDefinition)1072651, // * Requires the "Mondain's Legacy" expansion + _ => (TextDefinition)$"* Requires the \"{ExpansionInfo.GetInfo(expansion).Name}\" expansion" + }; + } + + public void DrawItem() + { + var type = m_CraftItem.ItemType; + + AddItem(20, 50, CraftItem.ItemIDOf(type), m_CraftItem.ItemHue); + + if (m_CraftItem.IsMarkable(type)) + { + AddHtmlLocalized( + 170, + 302 + m_OtherCount++ * 20, + 310, + 18, + 1044059, + LabelColor + ); // This item may hold its maker's mark + m_ShowExceptionalChance = true; + } + } + + public void DrawSkill() + { + for (var i = 0; i < m_CraftItem.Skills.Count; i++) + { + var skill = m_CraftItem.Skills[i]; + var minSkill = Math.Max(skill.MinSkill, 0); + + AddHtmlLocalized(170, 132 + i * 20, 200, 18, AosSkillBonuses.GetLabel(skill.SkillToMake), LabelColor); + AddLabel(430, 132 + i * 20, LabelHue, $"{minSkill:F1}"); + } + + var res = m_CraftItem.UseSubRes2 ? m_CraftSystem.CraftSubRes2 : m_CraftSystem.CraftSubRes; + var resIndex = -1; + + var context = m_CraftSystem.GetContext(m_From); + + if (context != null) + resIndex = m_CraftItem.UseSubRes2 ? context.LastResourceIndex2 : context.LastResourceIndex; + + var chance = m_CraftItem.GetSuccessChance( + m_From, + resIndex > -1 ? res.GetAt(resIndex).ItemType : null, + m_CraftSystem, + false, + out _ + ); + + AddHtmlLocalized(170, 80, 250, 18, 1044057, LabelColor); // Success Chance: + AddLabel(430, 80, LabelHue, $"{Math.Clamp(chance, 0, 1) * 100:F1}%"); + + if (m_ShowExceptionalChance) + { + var exceptChance = Math.Clamp(m_CraftItem.GetExceptionalChance(m_CraftSystem, chance, m_From), 0, 1.0); + + AddHtmlLocalized(170, 100, 250, 18, 1044058, 32767); // Exceptional Chance: + AddLabel(430, 100, LabelHue, $"{exceptChance * 100:F1}%"); + } + } + + public void DrawResource() + { + var retainedColor = false; + + var context = m_CraftSystem.GetContext(m_From); + + var res = m_CraftItem.UseSubRes2 ? m_CraftSystem.CraftSubRes2 : m_CraftSystem.CraftSubRes; + var resIndex = -1; + + if (context != null) + resIndex = m_CraftItem.UseSubRes2 ? context.LastResourceIndex2 : context.LastResourceIndex; + + var cropScroll = m_CraftItem.Resources.Count > 1 + && m_CraftItem.Resources[^1].ItemType == typeofBlankScroll + && typeofSpellScroll.IsAssignableFrom(m_CraftItem.ItemType); + + for (var i = 0; i < m_CraftItem.Resources.Count - (cropScroll ? 1 : 0) && i < 4; i++) + { + Type type; + string nameString; + int nameNumber; + + var craftResource = m_CraftItem.Resources[i]; + + type = craftResource.ItemType; + nameString = craftResource.NameString; + nameNumber = craftResource.NameNumber; + + // Resource Mutation + if (type == res.ResType && resIndex > -1) + { + var subResource = res.GetAt(resIndex); + + type = subResource.ItemType; + + nameString = subResource.NameString; + nameNumber = subResource.GenericNameNumber; + + if (nameNumber <= 0) + nameNumber = subResource.NameNumber; + } + // ****************** + + if (!retainedColor && m_CraftItem.RetainsColorFrom(m_CraftSystem, type)) + { + retainedColor = true; + AddHtmlLocalized( + 170, + 302 + m_OtherCount++ * 20, + 310, + 18, + 1044152, + LabelColor + ); // * The item retains the color of this material + AddLabel(500, 219 + i * 20, LabelHue, "*"); + } + + if (nameNumber > 0) + AddHtmlLocalized(170, 219 + i * 20, 310, 18, nameNumber, LabelColor); + else + AddLabel(170, 219 + i * 20, LabelHue, nameString); + + AddLabel(430, 219 + i * 20, LabelHue, craftResource.Amount.ToString()); + } + + if (m_CraftItem.NameNumber == 1041267) // runebook + { + AddHtmlLocalized(170, 219 + m_CraftItem.Resources.Count * 20, 310, 18, 1044447, LabelColor); + AddLabel(430, 219 + m_CraftItem.Resources.Count * 20, LabelHue, "1"); + } + + if (cropScroll) + AddHtmlLocalized( + 170, + 302 + m_OtherCount++ * 20, + 360, + 18, + 1044379, + LabelColor + ); // Inscribing scrolls also requires a blank scroll and mana. + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + // Back Button + if (info.ButtonID == 0) + { + var craftGump = new CraftGump(m_From, m_CraftSystem, m_Tool, null); + m_From.SendGump(craftGump); + } + else // Make Button + { + var num = m_CraftSystem.CanCraft(m_From, m_Tool, m_CraftItem.ItemType); + + if (num > 0) + { + m_From.SendGump(new CraftGump(m_From, m_CraftSystem, m_Tool, num)); + } + else + { + Type type = null; + + var context = m_CraftSystem.GetContext(m_From); + + if (context != null) + { + var res = m_CraftItem.UseSubRes2 ? m_CraftSystem.CraftSubRes2 : m_CraftSystem.CraftSubRes; + var resIndex = m_CraftItem.UseSubRes2 ? context.LastResourceIndex2 : context.LastResourceIndex; + + if (resIndex > -1) + type = res.GetAt(resIndex).ItemType; + } + + m_CraftSystem.CreateItem(m_From, m_CraftItem.ItemType, type, m_Tool, m_CraftItem); + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Craft/Core/CraftItem.cs b/Projects/UOContent/Engines/Craft/Core/CraftItem.cs index c658dbefb..15ed5cc98 100644 --- a/Projects/UOContent/Engines/Craft/Core/CraftItem.cs +++ b/Projects/UOContent/Engines/Craft/Core/CraftItem.cs @@ -1,1206 +1,1289 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Server.Commands; -using Server.Factions; -using Server.Items; -using Server.Mobiles; -using Server.Utilities; - -namespace Server.Engines.Craft -{ - public enum ConsumeType - { - All, - Half, - None - } - - public interface ICraftable - { - int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, - CraftItem craftItem, int resHue); - } - - public class CraftItem - { - private static readonly Dictionary _itemIds = new Dictionary(); - private int m_ResAmount; - - private int m_ResHue; - private CraftSystem m_System; - - public CraftItem(Type type, TextDefinition groupName, TextDefinition name) - { - Resources = new List(); - Skills = new List(); - - ItemType = type; - - GroupNameString = groupName; - NameString = name; - - GroupNameNumber = groupName; - NameNumber = name; - - RequiredBeverage = BeverageType.Water; - } - - public bool ForceNonExceptional { get; set; } - - public Expansion RequiredExpansion { get; set; } - - public Recipe Recipe { get; private set; } - - public BeverageType RequiredBeverage { get; set; } - - public int Mana { get; set; } - - public int Hits { get; set; } - - public int Stam { get; set; } - - public bool UseSubRes2 { get; set; } - - public bool UseAllRes { get; set; } - - public bool NeedHeat { get; set; } - - public bool NeedOven { get; set; } - - public bool NeedMill { get; set; } - - public Type ItemType { get; } - - public int ItemHue { get; set; } - - public string GroupNameString { get; } - - public int GroupNameNumber { get; } - - public string NameString { get; } - - public int NameNumber { get; } - - public List Resources { get; } - - public List Skills { get; } - - public void AddRecipe(int id, CraftSystem system) - { - if (Recipe != null) - { - Console.WriteLine("Warning: Attempted add of recipe #{0} to the crafting of {1} in CraftSystem {2}.", id, - ItemType.Name, system); - return; - } - - Recipe = new Recipe(id, system, this); - } - - public static int LabelNumber(Type type) - { - int number = ItemIDOf(type); - - if (number >= 0x4000) - number += 1078872; - else - number += 1020000; - - return number; - } - - public static int ItemIDOf(Type type) - { - if (_itemIds.TryGetValue(type, out int itemId)) - return itemId; - - if (type == typeof(FactionExplosionTrap)) - itemId = 14034; - else if (type == typeof(FactionGasTrap)) - itemId = 4523; - else if (type == typeof(FactionSawTrap)) - itemId = 4359; - else if (type == typeof(FactionSpikeTrap)) itemId = 4517; - - if (itemId == 0) - { - object[] attrs = type.GetCustomAttributes(typeof(CraftItemIDAttribute), false); - - if (attrs.Length > 0) - { - CraftItemIDAttribute craftItemID = (CraftItemIDAttribute)attrs[0]; - itemId = craftItemID.ItemID; - } - } - - if (itemId == 0) - { - Item item = null; - - try - { - item = ActivatorUtil.CreateInstance(type) as Item; - } - catch - { - // ignored - } - - if (item != null) - { - itemId = item.ItemID; - item.Delete(); - } - } - - _itemIds[type] = itemId; - - return itemId; - } - - public void AddRes(Type type, TextDefinition name, int amount) - { - AddRes(type, name, amount, ""); - } - - public void AddRes(Type type, TextDefinition name, int amount, TextDefinition message) - { - CraftRes craftRes = new CraftRes(type, name, amount, message); - Resources.Add(craftRes); - } - - public void AddSkill(SkillName skillToMake, double minSkill, double maxSkill) - { - CraftSkill craftSkill = new CraftSkill(skillToMake, minSkill, maxSkill); - Skills.Add(craftSkill); - } - - public bool ConsumeAttributes(Mobile from, ref object message, bool consume) - { - bool consumMana; - bool consumHits; - bool consumStam; - - if (Hits > 0 && from.Hits < Hits) - { - message = "You lack the required hit points to make that."; - return false; - } - - consumHits = consume; - - if (Mana > 0 && from.Mana < Mana) - { - message = "You lack the required mana to make that."; - return false; - } - - consumMana = consume; - - if (Stam > 0 && from.Stam < Stam) - { - message = "You lack the required stamina to make that."; - return false; - } - - consumStam = consume; - - if (consumMana) - from.Mana -= Mana; - - if (consumHits) - from.Hits -= Hits; - - if (consumStam) - from.Stam -= Stam; - - return true; - } - - public bool IsMarkable(Type type) - { - if (ForceNonExceptional) // Don't even display the stuff for marking if it can't ever be exceptional. - return false; - - for (int i = 0; i < m_MarkableTable.Length; ++i) - if (type == m_MarkableTable[i] || type.IsSubclassOf(m_MarkableTable[i])) - return true; - - return false; - } - - public static bool RetainsColor(Type type) - { - bool neverColor = false; - - for (int i = 0; !neverColor && i < m_NeverColorTable.Length; ++i) - neverColor = type == m_NeverColorTable[i] || type.IsSubclassOf(m_NeverColorTable[i]); - - if (neverColor) - return false; - - bool inItemTable = false; - - for (int i = 0; !inItemTable && i < m_ColoredItemTable.Length; ++i) - inItemTable = type == m_ColoredItemTable[i] || type.IsSubclassOf(m_ColoredItemTable[i]); - - return inItemTable; - } - - public bool RetainsColorFrom(CraftSystem system, Type type) - { - if (system.RetainsColorFrom(this, type)) - return true; - - bool inItemTable = RetainsColor(ItemType); - - if (!inItemTable) - return false; - - bool inResourceTable = false; - - for (int i = 0; !inResourceTable && i < m_ColoredResourceTable.Length; ++i) - inResourceTable = type == m_ColoredResourceTable[i] || type.IsSubclassOf(m_ColoredResourceTable[i]); - - return inResourceTable; - } - - public bool Find(Mobile from, int[] itemIDs) - { - Map map = from.Map; - - if (map == null) - return false; - - IPooledEnumerable eable = map.GetItemsInRange(from.Location, 2); - bool found = eable.Any(item => item.Z + 16 > item.Z && item.Z + 16 > item.Z && Find(item.ItemID, itemIDs)); - eable.Free(); - - if (found) - return true; - - for (int x = -2; x <= 2; ++x) - for (int y = -2; y <= 2; ++y) - { - int vx = from.X + x; - int vy = from.Y + y; - - StaticTile[] tiles = map.Tiles.GetStaticTiles(vx, vy, true); - - for (int i = 0; i < tiles.Length; ++i) - { - int z = tiles[i].Z; - int id = tiles[i].ID; - - if (z + 16 > from.Z && from.Z + 16 > z && Find(id, itemIDs)) - return true; - } - } - - return false; - } - - public static bool Find(int itemID, int[] itemIDs) - { - bool contains = false; - - for (int i = 0; !contains && i < itemIDs.Length; i += 2) - contains = itemID >= itemIDs[i] && itemID <= itemIDs[i + 1]; - - return contains; - } - - public bool IsQuantityType(Type[][] types) => - types.Any(check => check.Any(t => typeof(IHasQuantity).IsAssignableFrom(t))); - - public int ConsumeQuantity(Container cont, Type[][] types, int[] amounts) - { - if (types.Length != amounts.Length) - throw new ArgumentException(); - - Item[][] items = new Item[types.Length][]; - int[] totals = new int[types.Length]; - - for (int i = 0; i < types.Length; ++i) - { - items[i] = cont.FindItemsByType(types[i]); - - for (int j = 0; j < items[i].Length; ++j) - if (!(items[i][j] is IHasQuantity hq)) - { - totals[i] += items[i][j].Amount; - } - else - { - if (hq is BaseBeverage beverage && beverage.Content != RequiredBeverage) - continue; - - totals[i] += hq.Quantity; - } - - if (totals[i] < amounts[i]) - return i; - } - - for (int i = 0; i < types.Length; ++i) - { - int need = amounts[i]; - - for (int j = 0; j < items[i].Length; ++j) - { - Item item = items[i][j]; - - if (!(item is IHasQuantity hq)) - { - int theirAmount = item.Amount; - - if (theirAmount < need) - { - item.Delete(); - need -= theirAmount; - } - else - { - item.Consume(need); - break; - } - } - else - { - if (hq is BaseBeverage beverage && beverage.Content != RequiredBeverage) - continue; - - int theirAmount = hq.Quantity; - - if (theirAmount < need) - { - hq.Quantity -= theirAmount; - need -= theirAmount; - } - else - { - hq.Quantity -= need; - break; - } - } - } - } - - return -1; - } - - public int GetQuantity(Container cont, Type[] types) - { - Item[] items = cont.FindItemsByType(types); - - int amount = 0; - - for (int i = 0; i < items.Length; ++i) - if (!(items[i] is IHasQuantity hq)) - { - amount += items[i].Amount; - } - else - { - if (hq is BaseBeverage beverage && beverage.Content != RequiredBeverage) - continue; - - amount += hq.Quantity; - } - - return amount; - } - - public bool ConsumeRes(Mobile from, Type typeRes, CraftSystem craftSystem, ref int resHue, ref int maxAmount, - ConsumeType consumeType, ref object message) => - ConsumeRes(from, typeRes, craftSystem, ref resHue, ref maxAmount, consumeType, ref message, false); - - public bool ConsumeRes(Mobile from, Type typeRes, CraftSystem craftSystem, ref int resHue, ref int maxAmount, - ConsumeType consumeType, ref object message, bool isFailure) - { - Container ourPack = from.Backpack; - - if (ourPack == null) - return false; - - if (NeedHeat && !Find(from, m_HeatSources)) - { - message = 1044487; // You must be near a fire source to cook. - return false; - } - - if (NeedOven && !Find(from, m_Ovens)) - { - message = 1044493; // You must be near an oven to bake that. - return false; - } - - if (NeedMill && !Find(from, m_Mills)) - { - message = 1044491; // You must be near a flour mill to do that. - return false; - } - - Type[][] types = new Type[Resources.Count][]; - int[] amounts = new int[Resources.Count]; - - maxAmount = int.MaxValue; - - CraftSubResCol resCol = UseSubRes2 ? craftSystem.CraftSubRes2 : craftSystem.CraftSubRes; - - CraftRes res; - for (int i = 0; i < types.Length; ++i) - { - CraftRes craftRes = Resources[i]; - Type baseType = craftRes.ItemType; - - // Resource Mutation - if (baseType == resCol.ResType && typeRes != null) - { - baseType = typeRes; - - CraftSubRes subResource = resCol.SearchFor(baseType); - - if (subResource != null && from.Skills[craftSystem.MainSkill].Base < subResource.RequiredSkill) - { - message = subResource.Message; - return false; - } - } - // ****************** - - for (int j = 0; types[i] == null && j < m_TypesTable.Length; ++j) - if (m_TypesTable[j][0] == baseType) - types[i] = m_TypesTable[j]; - - if (types[i] == null) - types[i] = new[] { baseType }; - - amounts[i] = craftRes.Amount; - - // For stackable items that can ben crafted more than one at a time - if (UseAllRes) - { - int tempAmount = ourPack.GetAmount(types[i]); - tempAmount /= amounts[i]; - if (tempAmount < maxAmount) - { - maxAmount = tempAmount; - - if (maxAmount == 0) - { - res = Resources[i]; - - if (res.MessageNumber > 0) - message = res.MessageNumber; - else if (!string.IsNullOrEmpty(res.MessageString)) - message = res.MessageString; - else - message = 502925; // You don't have the resources required to make that item. - - return false; - } - } - } - // **************************** - - if (isFailure && !craftSystem.ConsumeOnFailure(from, types[i][0], this)) - amounts[i] = 0; - } - - // We adjust the amount of each resource to consume the max possible - if (UseAllRes) - for (int i = 0; i < amounts.Length; ++i) - amounts[i] *= maxAmount; - else - maxAmount = -1; - - RecallRune consumeExtra = null; - - if (NameNumber == 1041267) - { - // Runebooks are a special case, they need a blank recall rune - consumeExtra = ourPack.FindItemsByType().Find(rune => !rune.Marked); - - if (consumeExtra == null) - { - message = 1044253; // You don't have the components needed to make that. - return false; - } - } - - int index; - - // Consume ALL - if (consumeType == ConsumeType.All) - { - m_ResHue = 0; - m_ResAmount = 0; - m_System = craftSystem; - - if (IsQuantityType(types)) - index = ConsumeQuantity(ourPack, types, amounts); - else - index = ourPack.ConsumeTotalGrouped(types, amounts, true, OnResourceConsumed, CheckHueGrouping); - - resHue = m_ResHue; - } - // Consume Half ( for use all resource craft type ) - else if (consumeType == ConsumeType.Half) - { - for (int i = 0; i < amounts.Length; i++) - { - amounts[i] /= 2; - - if (amounts[i] < 1) - amounts[i] = 1; - } - - m_ResHue = 0; - m_ResAmount = 0; - m_System = craftSystem; - - if (IsQuantityType(types)) - index = ConsumeQuantity(ourPack, types, amounts); - else - index = ourPack.ConsumeTotalGrouped(types, amounts, true, OnResourceConsumed, CheckHueGrouping); - - resHue = m_ResHue; - } - else // ConstumeType.None ( it's basically used to know if the crafter has enough resource before starting the process ) - { - index = -1; - - // TODO: Optimize this - if (IsQuantityType(types)) - for (int i = 0; i < types.Length; i++) - if (GetQuantity(ourPack, types[i]) < amounts[i]) - { - index = i; - break; - } - else - { - for (int j = 0; j < types.Length; j++) - if (ourPack.GetBestGroupAmount(types[j], true, CheckHueGrouping) < amounts[j]) - { - index = j; - break; - } - } - } - - if (index == -1) - { - if (consumeType != ConsumeType.None) - consumeExtra?.Delete(); - - return true; - } - - res = Resources[index]; - - if (res.MessageNumber > 0) - message = res.MessageNumber; - else if (!string.IsNullOrEmpty(res.MessageString)) - message = res.MessageString; - else - message = 502925; // You don't have the resources required to make that item. - - return false; - } - - private void OnResourceConsumed(Item item, int amount) - { - if (!RetainsColorFrom(m_System, item.GetType())) - return; - - if (amount >= m_ResAmount) - { - m_ResHue = item.Hue; - m_ResAmount = amount; - } - } - - private int CheckHueGrouping(Item a, Item b) => b.Hue.CompareTo(a.Hue); - - public double GetExceptionalChance(CraftSystem system, double chance, Mobile from) - { - if (ForceNonExceptional) - return 0.0; - - double bonus = 0.0; - - if (from.Talisman is BaseTalisman talisman && talisman.Skill == system.MainSkill) - { - chance -= talisman.SuccessBonus / 100.0; - bonus = talisman.ExceptionalBonus / 100.0; - } - - switch (system.ECA) - { - default: - chance -= 0.6; - break; - case CraftECA.FiftyPercentChanceMinusTenPercent: - chance = chance * 0.5 - 0.1; - break; - case CraftECA.ChanceMinusSixtyToFourtyFive: - chance -= Math.Clamp(0.60 - (from.Skills[system.MainSkill].Value - 95.0) * 0.03, 0.45, 0.60); - break; - } - - return chance > 0 ? chance + bonus : chance; - } - - public bool CheckSkills(Mobile from, Type typeRes, CraftSystem craftSystem, ref int quality, - ref bool allRequiredSkills) => - CheckSkills(from, typeRes, craftSystem, ref quality, out allRequiredSkills, true); - - public bool CheckSkills(Mobile from, Type typeRes, CraftSystem craftSystem, ref int quality, - out bool allRequiredSkills, bool gainSkills) - { - double chance = GetSuccessChance(from, typeRes, craftSystem, gainSkills, out allRequiredSkills); - - if (GetExceptionalChance(craftSystem, chance, from) > Utility.RandomDouble()) - quality = 2; - - return chance > Utility.RandomDouble(); - } - - public double GetSuccessChance(Mobile from, Type typeRes, CraftSystem craftSystem, bool gainSkills, - out bool allRequiredSkills) - { - double minMainSkill = 0.0; - double maxMainSkill = 0.0; - double valMainSkill = 0.0; - - allRequiredSkills = true; - - for (int i = 0; i < Skills.Count; i++) - { - CraftSkill craftSkill = Skills[i]; - - double minSkill = craftSkill.MinSkill; - double maxSkill = craftSkill.MaxSkill; - double valSkill = from.Skills[craftSkill.SkillToMake].Value; - - if (valSkill < minSkill) - allRequiredSkills = false; - - if (craftSkill.SkillToMake == craftSystem.MainSkill) - { - minMainSkill = minSkill; - maxMainSkill = maxSkill; - valMainSkill = valSkill; - } - - if (gainSkills) // This is a passive check. Success chance is entirely dependant on the main skill - from.CheckSkill(craftSkill.SkillToMake, minSkill, maxSkill); - } - - double chance; - - if (allRequiredSkills) - chance = craftSystem.GetChanceAtMin(this) + (valMainSkill - minMainSkill) / (maxMainSkill - minMainSkill) * - (1.0 - craftSystem.GetChanceAtMin(this)); - else - chance = 0.0; - - if (allRequiredSkills && from.Talisman is BaseTalisman talisman && talisman.Skill == craftSystem.MainSkill) - chance += talisman.SuccessBonus / 100.0; - - if (allRequiredSkills && valMainSkill == maxMainSkill) - chance = 1.0; - - return chance; - } - - public void Craft(Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool) - { - if (from.BeginAction()) - { - if (RequiredExpansion == Expansion.None || - from.NetState?.SupportsExpansion(RequiredExpansion) == true) - { - bool allRequiredSkills; - double chance = GetSuccessChance(from, typeRes, craftSystem, false, out allRequiredSkills); - - if (allRequiredSkills && chance >= 0.0) - { - if (Recipe == null || (from as PlayerMobile)?.HasRecipe(Recipe) != false) - { - int badCraft = craftSystem.CanCraft(from, tool, ItemType); - - if (badCraft <= 0) - { - int resHue = 0; - int maxAmount = 0; - object message = null; - - if (ConsumeRes(from, typeRes, craftSystem, ref resHue, ref maxAmount, ConsumeType.None, - ref message)) - { - message = null; - - if (ConsumeAttributes(from, ref message, false)) - { - CraftContext context = craftSystem.GetContext(from); - - context?.OnMade(this); - - int iMin = craftSystem.MinCraftEffect; - int iMax = craftSystem.MaxCraftEffect - iMin + 1; - int iRandom = Utility.Random(iMax); - iRandom += iMin + 1; - new InternalTimer(from, craftSystem, this, typeRes, tool, iRandom).Start(); - } - else - { - from.EndAction(); - from.SendGump(new CraftGump(from, craftSystem, tool, message)); - } - } - else - { - from.EndAction(); - from.SendGump(new CraftGump(from, craftSystem, tool, message)); - } - } - else - { - from.EndAction(); - from.SendGump(new CraftGump(from, craftSystem, tool, badCraft)); - } - } - else - { - from.EndAction(); - from.SendGump(new CraftGump(from, craftSystem, tool, - 1072847)); // You must learn that recipe from a scroll. - } - } - else - { - from.EndAction(); - from.SendGump(new CraftGump(from, craftSystem, tool, - 1044153)); // You don't have the required skills to attempt this item. - } - } - else - { - from.EndAction(); - from.SendGump(new CraftGump(from, craftSystem, tool, - RequiredExpansionMessage(RequiredExpansion))); // The {0} expansion is required to attempt this item. - } - } - else - { - from.SendLocalizedMessage(500119); // You must wait to perform another action - } - } - - // Eventually convert to TextDefinition, but that requires that we convert all the gumps to ues it too. Not that it wouldn't be a bad idea. - private object RequiredExpansionMessage(Expansion expansion) - { - return expansion switch - { - Expansion.SE => 1063307, // The "Samurai Empire" expansion is required to attempt this item. - Expansion.ML => 1072650, // The "Mondain's Legacy" expansion is required to attempt this item. - _ => $"The \"{ExpansionInfo.GetInfo(expansion).Name}\" expansion is required to attempt this item." - }; - } - - public void CompleteCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, - BaseTool tool, CustomCraft customCraft) - { - int badCraft = craftSystem.CanCraft(from, tool, ItemType); - - if (badCraft > 0) - { - if (tool?.Deleted == false && tool.UsesRemaining > 0) - from.SendGump(new CraftGump(from, craftSystem, tool, badCraft)); - else - from.SendLocalizedMessage(badCraft); - - return; - } - - int checkResHue = 0, checkMaxAmount = 0; - object checkMessage = null; - - // Not enough resource to craft it - if (!(ConsumeRes(from, typeRes, craftSystem, ref checkResHue, ref checkMaxAmount, ConsumeType.None, - ref checkMessage) - && ConsumeAttributes(from, ref checkMessage, false))) - { - if (tool?.Deleted == false && tool.UsesRemaining > 0) - from.SendGump(new CraftGump(from, craftSystem, tool, checkMessage)); - else if (checkMessage is int messageInt && messageInt > 0) - from.SendLocalizedMessage(messageInt); - else - from.SendMessage(checkMessage.ToString()); - - return; - } - - bool toolBroken = false; - - int ignored = 1; - int endquality = 1; - - bool allRequiredSkills = true; - - if (CheckSkills(from, typeRes, craftSystem, ref ignored, ref allRequiredSkills)) - { - // Resource - int resHue = 0; - int maxAmount = 0; - - object message = null; - - // Not enough resource to craft it - if (!(ConsumeRes(from, typeRes, craftSystem, ref resHue, ref maxAmount, ConsumeType.All, ref message) - && ConsumeAttributes(from, ref message, true))) - { - if (tool?.Deleted == false && tool.UsesRemaining > 0) - from.SendGump(new CraftGump(from, craftSystem, tool, message)); - else if (message is int messageIn && messageIn > 0) - from.SendLocalizedMessage(messageIn); - else - from.SendMessage(message.ToString()); - - return; - } - - tool.UsesRemaining--; - - if (craftSystem is DefBlacksmithy) - if (from.FindItemOnLayer(Layer.OneHanded) is AncientSmithyHammer hammer && hammer != tool) - { - hammer.UsesRemaining--; - if (hammer.UsesRemaining < 1) - hammer.Delete(); - } - - if (tool.UsesRemaining < 1 && tool.BreakOnDepletion) - toolBroken = true; - - if (toolBroken) - tool.Delete(); - - int num = 0; - - Item item; - if (customCraft != null) - { - item = customCraft.CompleteCraft(out num); - } - else if (typeof(MapItem).IsAssignableFrom(ItemType) && from.Map != Map.Trammel && from.Map != Map.Felucca) - { - item = new IndecipherableMap(); - from.SendLocalizedMessage(1070800); // The map you create becomes mysteriously indecipherable. - } - else - { - item = ActivatorUtil.CreateInstance(ItemType) as Item; - } - - if (item != null) - { - if (item is ICraftable craftable) - endquality = craftable.OnCraft(quality, makersMark, from, craftSystem, typeRes, tool, this, resHue); - else if (item.Hue == 0) - item.Hue = resHue; - - if (maxAmount > 0) - { - if (!item.Stackable && item is IUsesRemaining remaining) - remaining.UsesRemaining *= maxAmount; - else - item.Amount = maxAmount; - } - - from.AddToBackpack(item); - - if (from.AccessLevel > AccessLevel.Player) - CommandLogging.WriteLine(from, "Crafting {0} with craft system {1}", CommandLogging.Format(item), - craftSystem.GetType().Name); - - // from.PlaySound( 0x57 ); - } - - if (num == 0) - num = craftSystem.PlayEndingEffect(from, false, true, toolBroken, endquality, makersMark, this); - - bool queryFactionImbue = false; - int availableSilver = 0; - FactionItemDefinition def = null; - Faction faction = null; - - if (item is IFactionItem) - { - def = FactionItemDefinition.Identify(item); - - if (def != null) - { - faction = Faction.Find(from); - - if (faction != null) - { - Town town = Town.FromRegion(from.Region); - - if (town?.Owner == faction) - { - Container pack = from.Backpack; - - if (pack != null) - { - availableSilver = pack.GetAmount(typeof(Silver)); - - if (availableSilver >= def.SilverCost) - queryFactionImbue = Faction.IsNearType(from, def.VendorType, 12); - } - } - } - } - } - - // TODO: Scroll imbuing - - if (queryFactionImbue) - from.SendGump(new FactionImbueGump(quality, item, from, craftSystem, tool, num, availableSilver, faction, - def)); - else if (tool?.Deleted == false && tool.UsesRemaining > 0) - from.SendGump(new CraftGump(from, craftSystem, tool, num)); - else if (num > 0) - from.SendLocalizedMessage(num); - } - else if (!allRequiredSkills) - { - if (tool?.Deleted == false && tool.UsesRemaining > 0) - from.SendGump(new CraftGump(from, craftSystem, tool, 1044153)); - else - from.SendLocalizedMessage(1044153); // You don't have the required skills to attempt this item. - } - else - { - ConsumeType consumeType = UseAllRes ? ConsumeType.Half : ConsumeType.All; - int resHue = 0; - int maxAmount = 0; - - object message = null; - - // Not enough resource to craft it - if (!ConsumeRes(from, typeRes, craftSystem, ref resHue, ref maxAmount, consumeType, ref message, true)) - { - if (tool?.Deleted == false && tool.UsesRemaining > 0) - from.SendGump(new CraftGump(from, craftSystem, tool, message)); - else if (message is int messageInt && messageInt > 0) - from.SendLocalizedMessage(messageInt); - else - from.SendMessage(message.ToString()); - - return; - } - - tool.UsesRemaining--; - - if (tool.UsesRemaining < 1 && tool.BreakOnDepletion) - toolBroken = true; - - if (toolBroken) - tool.Delete(); - - // SkillCheck failed. - int num = craftSystem.PlayEndingEffect(from, true, true, toolBroken, endquality, false, this); - - if (!tool.Deleted && tool.UsesRemaining > 0) - from.SendGump(new CraftGump(from, craftSystem, tool, num)); - else if (num > 0) - from.SendLocalizedMessage(num); - } - } - - private class InternalTimer : Timer - { - private readonly CraftItem m_CraftItem; - private readonly CraftSystem m_CraftSystem; - private readonly Mobile m_From; - private int m_iCount; - private readonly int m_iCountMax; - private readonly BaseTool m_Tool; - private readonly Type m_TypeRes; - - public InternalTimer(Mobile from, CraftSystem craftSystem, CraftItem craftItem, Type typeRes, BaseTool tool, - int iCountMax) : base(TimeSpan.Zero, TimeSpan.FromSeconds(craftSystem.Delay), iCountMax) - { - m_From = from; - m_CraftItem = craftItem; - m_iCount = 0; - m_iCountMax = iCountMax; - m_CraftSystem = craftSystem; - m_TypeRes = typeRes; - m_Tool = tool; - } - - protected override void OnTick() - { - m_iCount++; - - m_From.DisruptiveAction(); - - if (m_iCount < m_iCountMax) - { - m_CraftSystem.PlayCraftEffect(m_From); - } - else - { - m_From.EndAction(); - - int badCraft = m_CraftSystem.CanCraft(m_From, m_Tool, m_CraftItem.ItemType); - - if (badCraft > 0) - { - if (m_Tool?.Deleted == false && m_Tool.UsesRemaining > 0) - m_From.SendGump(new CraftGump(m_From, m_CraftSystem, m_Tool, badCraft)); - else - m_From.SendLocalizedMessage(badCraft); - - return; - } - - int quality = 1; - bool allRequiredSkills = true; - - m_CraftItem.CheckSkills(m_From, m_TypeRes, m_CraftSystem, ref quality, out allRequiredSkills, false); - - CraftContext context = m_CraftSystem.GetContext(m_From); - - if (context == null) - return; - - if (typeof(CustomCraft).IsAssignableFrom(m_CraftItem.ItemType)) - { - CustomCraft cc = null; - - try - { - cc = ActivatorUtil.CreateInstance(m_CraftItem.ItemType, m_From, m_CraftItem, m_CraftSystem, - m_TypeRes, m_Tool, quality) as CustomCraft; - } - catch - { - // ignored - } - - cc?.EndCraftAction(); - - return; - } - - bool makersMark = false; - - if (quality == 2 && m_From.Skills[m_CraftSystem.MainSkill].Base >= 100.0) - makersMark = m_CraftItem.IsMarkable(m_CraftItem.ItemType); - - if (makersMark && context.MarkOption == CraftMarkOption.PromptForMark) - { - m_From.SendGump(new QueryMakersMarkGump(quality, m_From, m_CraftItem, m_CraftSystem, m_TypeRes, - m_Tool)); - } - else - { - if (context.MarkOption == CraftMarkOption.DoNotMark) - makersMark = false; - - m_CraftItem.CompleteCraft(quality, makersMark, m_From, m_CraftSystem, m_TypeRes, m_Tool, null); - } - } - } - } - - private static readonly int[] m_HeatSources = - { - 0x461, 0x48E, // Sandstone oven/fireplace - 0x92B, 0x96C, // Stone oven/fireplace - 0xDE3, 0xDE9, // Campfire - 0xFAC, 0xFAC, // Firepit - 0x184A, 0x184C, // Heating stand (left) - 0x184E, 0x1850, // Heating stand (right) - 0x398C, 0x399F, // Fire field - 0x2DDB, 0x2DDC, // Elven stove - 0x19AA, 0x19BB, // Veteran Reward Brazier - 0x197A, 0x19A9, // Large Forge - 0x0FB1, 0x0FB1, // Small Forge - 0x2DD8, 0x2DD8 // Elven Forge - }; - - private static readonly int[] m_Ovens = - { - 0x461, 0x46F, // Sandstone oven - 0x92B, 0x93F, // Stone oven - 0x2DDB, 0x2DDC // Elven stove - }; - - private static readonly int[] m_Mills = - { - 0x1920, 0x1921, 0x1922, 0x1923, 0x1924, 0x1295, 0x1926, 0x1928, - 0x192C, 0x192D, 0x192E, 0x129F, 0x1930, 0x1931, 0x1932, 0x1934 - }; - - private static readonly Type[][] m_TypesTable = - { - new[] { typeof(Log), typeof(Board) }, - new[] { typeof(HeartwoodLog), typeof(HeartwoodBoard) }, - new[] { typeof(BloodwoodLog), typeof(BloodwoodBoard) }, - new[] { typeof(FrostwoodLog), typeof(FrostwoodBoard) }, - new[] { typeof(OakLog), typeof(OakBoard) }, - new[] { typeof(AshLog), typeof(AshBoard) }, - new[] { typeof(YewLog), typeof(YewBoard) }, - new[] { typeof(Leather), typeof(Hides) }, - new[] { typeof(SpinedLeather), typeof(SpinedHides) }, - new[] { typeof(HornedLeather), typeof(HornedHides) }, - new[] { typeof(BarbedLeather), typeof(BarbedHides) }, - new[] { typeof(BlankMap), typeof(BlankScroll) }, - new[] { typeof(Cloth), typeof(UncutCloth) }, - new[] { typeof(CheeseWheel), typeof(CheeseWedge) }, - new[] { typeof(Pumpkin), typeof(SmallPumpkin) }, - new[] { typeof(WoodenBowlOfPeas), typeof(PewterBowlOfPeas) } - }; - - private static readonly Type[] m_ColoredItemTable = - { - typeof(BaseWeapon), typeof(BaseArmor), typeof(BaseClothing), - typeof(BaseJewel), typeof(DragonBardingDeed) - }; - - private static readonly Type[] m_ColoredResourceTable = - { - typeof(BaseIngot), typeof(BaseOre), - typeof(BaseLeather), typeof(BaseHides), - typeof(UncutCloth), typeof(Cloth), - typeof(BaseGranite), typeof(BaseScales) - }; - - private static readonly Type[] m_MarkableTable = - { - typeof(BaseArmor), - typeof(BaseWeapon), - typeof(BaseClothing), - typeof(BaseInstrument), - typeof(DragonBardingDeed), - typeof(BaseTool), - typeof(BaseHarvestTool), - typeof(FukiyaDarts), typeof(Shuriken), - typeof(Spellbook), typeof(Runebook), - typeof(BaseQuiver) - }; - - private static readonly Type[] m_NeverColorTable = - { - typeof(OrcHelm) - }; - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using Server.Commands; +using Server.Factions; +using Server.Items; +using Server.Mobiles; +using Server.Utilities; + +namespace Server.Engines.Craft +{ + public enum ConsumeType + { + All, + Half, + None + } + + public interface ICraftable + { + int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, + CraftItem craftItem, int resHue + ); + } + + public class CraftItem + { + private static readonly Dictionary _itemIds = new Dictionary(); + + private static readonly int[] m_HeatSources = + { + 0x461, 0x48E, // Sandstone oven/fireplace + 0x92B, 0x96C, // Stone oven/fireplace + 0xDE3, 0xDE9, // Campfire + 0xFAC, 0xFAC, // Firepit + 0x184A, 0x184C, // Heating stand (left) + 0x184E, 0x1850, // Heating stand (right) + 0x398C, 0x399F, // Fire field + 0x2DDB, 0x2DDC, // Elven stove + 0x19AA, 0x19BB, // Veteran Reward Brazier + 0x197A, 0x19A9, // Large Forge + 0x0FB1, 0x0FB1, // Small Forge + 0x2DD8, 0x2DD8 // Elven Forge + }; + + private static readonly int[] m_Ovens = + { + 0x461, 0x46F, // Sandstone oven + 0x92B, 0x93F, // Stone oven + 0x2DDB, 0x2DDC // Elven stove + }; + + private static readonly int[] m_Mills = + { + 0x1920, 0x1921, 0x1922, 0x1923, 0x1924, 0x1295, 0x1926, 0x1928, + 0x192C, 0x192D, 0x192E, 0x129F, 0x1930, 0x1931, 0x1932, 0x1934 + }; + + private static readonly Type[][] m_TypesTable = + { + new[] { typeof(Log), typeof(Board) }, + new[] { typeof(HeartwoodLog), typeof(HeartwoodBoard) }, + new[] { typeof(BloodwoodLog), typeof(BloodwoodBoard) }, + new[] { typeof(FrostwoodLog), typeof(FrostwoodBoard) }, + new[] { typeof(OakLog), typeof(OakBoard) }, + new[] { typeof(AshLog), typeof(AshBoard) }, + new[] { typeof(YewLog), typeof(YewBoard) }, + new[] { typeof(Leather), typeof(Hides) }, + new[] { typeof(SpinedLeather), typeof(SpinedHides) }, + new[] { typeof(HornedLeather), typeof(HornedHides) }, + new[] { typeof(BarbedLeather), typeof(BarbedHides) }, + new[] { typeof(BlankMap), typeof(BlankScroll) }, + new[] { typeof(Cloth), typeof(UncutCloth) }, + new[] { typeof(CheeseWheel), typeof(CheeseWedge) }, + new[] { typeof(Pumpkin), typeof(SmallPumpkin) }, + new[] { typeof(WoodenBowlOfPeas), typeof(PewterBowlOfPeas) } + }; + + private static readonly Type[] m_ColoredItemTable = + { + typeof(BaseWeapon), typeof(BaseArmor), typeof(BaseClothing), + typeof(BaseJewel), typeof(DragonBardingDeed) + }; + + private static readonly Type[] m_ColoredResourceTable = + { + typeof(BaseIngot), typeof(BaseOre), + typeof(BaseLeather), typeof(BaseHides), + typeof(UncutCloth), typeof(Cloth), + typeof(BaseGranite), typeof(BaseScales) + }; + + private static readonly Type[] m_MarkableTable = + { + typeof(BaseArmor), + typeof(BaseWeapon), + typeof(BaseClothing), + typeof(BaseInstrument), + typeof(DragonBardingDeed), + typeof(BaseTool), + typeof(BaseHarvestTool), + typeof(FukiyaDarts), typeof(Shuriken), + typeof(Spellbook), typeof(Runebook), + typeof(BaseQuiver) + }; + + private static readonly Type[] m_NeverColorTable = + { + typeof(OrcHelm) + }; + + private int m_ResAmount; + + private int m_ResHue; + private CraftSystem m_System; + + public CraftItem(Type type, TextDefinition groupName, TextDefinition name) + { + Resources = new List(); + Skills = new List(); + + ItemType = type; + + GroupNameString = groupName; + NameString = name; + + GroupNameNumber = groupName; + NameNumber = name; + + RequiredBeverage = BeverageType.Water; + } + + public bool ForceNonExceptional { get; set; } + + public Expansion RequiredExpansion { get; set; } + + public Recipe Recipe { get; private set; } + + public BeverageType RequiredBeverage { get; set; } + + public int Mana { get; set; } + + public int Hits { get; set; } + + public int Stam { get; set; } + + public bool UseSubRes2 { get; set; } + + public bool UseAllRes { get; set; } + + public bool NeedHeat { get; set; } + + public bool NeedOven { get; set; } + + public bool NeedMill { get; set; } + + public Type ItemType { get; } + + public int ItemHue { get; set; } + + public string GroupNameString { get; } + + public int GroupNameNumber { get; } + + public string NameString { get; } + + public int NameNumber { get; } + + public List Resources { get; } + + public List Skills { get; } + + public void AddRecipe(int id, CraftSystem system) + { + if (Recipe != null) + { + Console.WriteLine( + "Warning: Attempted add of recipe #{0} to the crafting of {1} in CraftSystem {2}.", + id, + ItemType.Name, + system + ); + return; + } + + Recipe = new Recipe(id, system, this); + } + + public static int LabelNumber(Type type) + { + var number = ItemIDOf(type); + + if (number >= 0x4000) + number += 1078872; + else + number += 1020000; + + return number; + } + + public static int ItemIDOf(Type type) + { + if (_itemIds.TryGetValue(type, out var itemId)) + return itemId; + + if (type == typeof(FactionExplosionTrap)) + itemId = 14034; + else if (type == typeof(FactionGasTrap)) + itemId = 4523; + else if (type == typeof(FactionSawTrap)) + itemId = 4359; + else if (type == typeof(FactionSpikeTrap)) itemId = 4517; + + if (itemId == 0) + { + var attrs = type.GetCustomAttributes(typeof(CraftItemIDAttribute), false); + + if (attrs.Length > 0) + { + var craftItemID = (CraftItemIDAttribute)attrs[0]; + itemId = craftItemID.ItemID; + } + } + + if (itemId == 0) + { + Item item = null; + + try + { + item = ActivatorUtil.CreateInstance(type) as Item; + } + catch + { + // ignored + } + + if (item != null) + { + itemId = item.ItemID; + item.Delete(); + } + } + + _itemIds[type] = itemId; + + return itemId; + } + + public void AddRes(Type type, TextDefinition name, int amount) + { + AddRes(type, name, amount, ""); + } + + public void AddRes(Type type, TextDefinition name, int amount, TextDefinition message) + { + var craftRes = new CraftRes(type, name, amount, message); + Resources.Add(craftRes); + } + + public void AddSkill(SkillName skillToMake, double minSkill, double maxSkill) + { + var craftSkill = new CraftSkill(skillToMake, minSkill, maxSkill); + Skills.Add(craftSkill); + } + + public bool ConsumeAttributes(Mobile from, ref object message, bool consume) + { + bool consumMana; + bool consumHits; + bool consumStam; + + if (Hits > 0 && from.Hits < Hits) + { + message = "You lack the required hit points to make that."; + return false; + } + + consumHits = consume; + + if (Mana > 0 && from.Mana < Mana) + { + message = "You lack the required mana to make that."; + return false; + } + + consumMana = consume; + + if (Stam > 0 && from.Stam < Stam) + { + message = "You lack the required stamina to make that."; + return false; + } + + consumStam = consume; + + if (consumMana) + from.Mana -= Mana; + + if (consumHits) + from.Hits -= Hits; + + if (consumStam) + from.Stam -= Stam; + + return true; + } + + public bool IsMarkable(Type type) + { + if (ForceNonExceptional) // Don't even display the stuff for marking if it can't ever be exceptional. + return false; + + for (var i = 0; i < m_MarkableTable.Length; ++i) + if (type == m_MarkableTable[i] || type.IsSubclassOf(m_MarkableTable[i])) + return true; + + return false; + } + + public static bool RetainsColor(Type type) + { + var neverColor = false; + + for (var i = 0; !neverColor && i < m_NeverColorTable.Length; ++i) + neverColor = type == m_NeverColorTable[i] || type.IsSubclassOf(m_NeverColorTable[i]); + + if (neverColor) + return false; + + var inItemTable = false; + + for (var i = 0; !inItemTable && i < m_ColoredItemTable.Length; ++i) + inItemTable = type == m_ColoredItemTable[i] || type.IsSubclassOf(m_ColoredItemTable[i]); + + return inItemTable; + } + + public bool RetainsColorFrom(CraftSystem system, Type type) + { + if (system.RetainsColorFrom(this, type)) + return true; + + var inItemTable = RetainsColor(ItemType); + + if (!inItemTable) + return false; + + var inResourceTable = false; + + for (var i = 0; !inResourceTable && i < m_ColoredResourceTable.Length; ++i) + inResourceTable = type == m_ColoredResourceTable[i] || type.IsSubclassOf(m_ColoredResourceTable[i]); + + return inResourceTable; + } + + public bool Find(Mobile from, int[] itemIDs) + { + var map = from.Map; + + if (map == null) + return false; + + var eable = map.GetItemsInRange(from.Location, 2); + var found = eable.Any(item => item.Z + 16 > item.Z && item.Z + 16 > item.Z && Find(item.ItemID, itemIDs)); + eable.Free(); + + if (found) + return true; + + for (var x = -2; x <= 2; ++x) + for (var y = -2; y <= 2; ++y) + { + var vx = from.X + x; + var vy = from.Y + y; + + var tiles = map.Tiles.GetStaticTiles(vx, vy, true); + + for (var i = 0; i < tiles.Length; ++i) + { + var z = tiles[i].Z; + var id = tiles[i].ID; + + if (z + 16 > from.Z && from.Z + 16 > z && Find(id, itemIDs)) + return true; + } + } + + return false; + } + + public static bool Find(int itemID, int[] itemIDs) + { + var contains = false; + + for (var i = 0; !contains && i < itemIDs.Length; i += 2) + contains = itemID >= itemIDs[i] && itemID <= itemIDs[i + 1]; + + return contains; + } + + public bool IsQuantityType(Type[][] types) => + types.Any(check => check.Any(t => typeof(IHasQuantity).IsAssignableFrom(t))); + + public int ConsumeQuantity(Container cont, Type[][] types, int[] amounts) + { + if (types.Length != amounts.Length) + throw new ArgumentException(); + + var items = new Item[types.Length][]; + var totals = new int[types.Length]; + + for (var i = 0; i < types.Length; ++i) + { + items[i] = cont.FindItemsByType(types[i]); + + for (var j = 0; j < items[i].Length; ++j) + if (!(items[i][j] is IHasQuantity hq)) + { + totals[i] += items[i][j].Amount; + } + else + { + if (hq is BaseBeverage beverage && beverage.Content != RequiredBeverage) + continue; + + totals[i] += hq.Quantity; + } + + if (totals[i] < amounts[i]) + return i; + } + + for (var i = 0; i < types.Length; ++i) + { + var need = amounts[i]; + + for (var j = 0; j < items[i].Length; ++j) + { + var item = items[i][j]; + + if (!(item is IHasQuantity hq)) + { + var theirAmount = item.Amount; + + if (theirAmount < need) + { + item.Delete(); + need -= theirAmount; + } + else + { + item.Consume(need); + break; + } + } + else + { + if (hq is BaseBeverage beverage && beverage.Content != RequiredBeverage) + continue; + + var theirAmount = hq.Quantity; + + if (theirAmount < need) + { + hq.Quantity -= theirAmount; + need -= theirAmount; + } + else + { + hq.Quantity -= need; + break; + } + } + } + } + + return -1; + } + + public int GetQuantity(Container cont, Type[] types) + { + var items = cont.FindItemsByType(types); + + var amount = 0; + + for (var i = 0; i < items.Length; ++i) + if (!(items[i] is IHasQuantity hq)) + { + amount += items[i].Amount; + } + else + { + if (hq is BaseBeverage beverage && beverage.Content != RequiredBeverage) + continue; + + amount += hq.Quantity; + } + + return amount; + } + + public bool ConsumeRes( + Mobile from, Type typeRes, CraftSystem craftSystem, ref int resHue, ref int maxAmount, + ConsumeType consumeType, ref object message + ) => + ConsumeRes(from, typeRes, craftSystem, ref resHue, ref maxAmount, consumeType, ref message, false); + + public bool ConsumeRes( + Mobile from, Type typeRes, CraftSystem craftSystem, ref int resHue, ref int maxAmount, + ConsumeType consumeType, ref object message, bool isFailure + ) + { + var ourPack = from.Backpack; + + if (ourPack == null) + return false; + + if (NeedHeat && !Find(from, m_HeatSources)) + { + message = 1044487; // You must be near a fire source to cook. + return false; + } + + if (NeedOven && !Find(from, m_Ovens)) + { + message = 1044493; // You must be near an oven to bake that. + return false; + } + + if (NeedMill && !Find(from, m_Mills)) + { + message = 1044491; // You must be near a flour mill to do that. + return false; + } + + var types = new Type[Resources.Count][]; + var amounts = new int[Resources.Count]; + + maxAmount = int.MaxValue; + + var resCol = UseSubRes2 ? craftSystem.CraftSubRes2 : craftSystem.CraftSubRes; + + CraftRes res; + for (var i = 0; i < types.Length; ++i) + { + var craftRes = Resources[i]; + var baseType = craftRes.ItemType; + + // Resource Mutation + if (baseType == resCol.ResType && typeRes != null) + { + baseType = typeRes; + + var subResource = resCol.SearchFor(baseType); + + if (subResource != null && from.Skills[craftSystem.MainSkill].Base < subResource.RequiredSkill) + { + message = subResource.Message; + return false; + } + } + // ****************** + + for (var j = 0; types[i] == null && j < m_TypesTable.Length; ++j) + if (m_TypesTable[j][0] == baseType) + types[i] = m_TypesTable[j]; + + if (types[i] == null) + types[i] = new[] { baseType }; + + amounts[i] = craftRes.Amount; + + // For stackable items that can ben crafted more than one at a time + if (UseAllRes) + { + var tempAmount = ourPack.GetAmount(types[i]); + tempAmount /= amounts[i]; + if (tempAmount < maxAmount) + { + maxAmount = tempAmount; + + if (maxAmount == 0) + { + res = Resources[i]; + + if (res.MessageNumber > 0) + message = res.MessageNumber; + else if (!string.IsNullOrEmpty(res.MessageString)) + message = res.MessageString; + else + message = 502925; // You don't have the resources required to make that item. + + return false; + } + } + } + // **************************** + + if (isFailure && !craftSystem.ConsumeOnFailure(from, types[i][0], this)) + amounts[i] = 0; + } + + // We adjust the amount of each resource to consume the max possible + if (UseAllRes) + for (var i = 0; i < amounts.Length; ++i) + amounts[i] *= maxAmount; + else + maxAmount = -1; + + RecallRune consumeExtra = null; + + if (NameNumber == 1041267) + { + // Runebooks are a special case, they need a blank recall rune + consumeExtra = ourPack.FindItemsByType().Find(rune => !rune.Marked); + + if (consumeExtra == null) + { + message = 1044253; // You don't have the components needed to make that. + return false; + } + } + + int index; + + // Consume ALL + if (consumeType == ConsumeType.All) + { + m_ResHue = 0; + m_ResAmount = 0; + m_System = craftSystem; + + if (IsQuantityType(types)) + index = ConsumeQuantity(ourPack, types, amounts); + else + index = ourPack.ConsumeTotalGrouped(types, amounts, true, OnResourceConsumed, CheckHueGrouping); + + resHue = m_ResHue; + } + // Consume Half ( for use all resource craft type ) + else if (consumeType == ConsumeType.Half) + { + for (var i = 0; i < amounts.Length; i++) + { + amounts[i] /= 2; + + if (amounts[i] < 1) + amounts[i] = 1; + } + + m_ResHue = 0; + m_ResAmount = 0; + m_System = craftSystem; + + if (IsQuantityType(types)) + index = ConsumeQuantity(ourPack, types, amounts); + else + index = ourPack.ConsumeTotalGrouped(types, amounts, true, OnResourceConsumed, CheckHueGrouping); + + resHue = m_ResHue; + } + else // ConstumeType.None ( it's basically used to know if the crafter has enough resource before starting the process ) + { + index = -1; + + // TODO: Optimize this + if (IsQuantityType(types)) + for (var i = 0; i < types.Length; i++) + if (GetQuantity(ourPack, types[i]) < amounts[i]) + { + index = i; + break; + } + else + { + for (var j = 0; j < types.Length; j++) + if (ourPack.GetBestGroupAmount(types[j], true, CheckHueGrouping) < amounts[j]) + { + index = j; + break; + } + } + } + + if (index == -1) + { + if (consumeType != ConsumeType.None) + consumeExtra?.Delete(); + + return true; + } + + res = Resources[index]; + + if (res.MessageNumber > 0) + message = res.MessageNumber; + else if (!string.IsNullOrEmpty(res.MessageString)) + message = res.MessageString; + else + message = 502925; // You don't have the resources required to make that item. + + return false; + } + + private void OnResourceConsumed(Item item, int amount) + { + if (!RetainsColorFrom(m_System, item.GetType())) + return; + + if (amount >= m_ResAmount) + { + m_ResHue = item.Hue; + m_ResAmount = amount; + } + } + + private int CheckHueGrouping(Item a, Item b) => b.Hue.CompareTo(a.Hue); + + public double GetExceptionalChance(CraftSystem system, double chance, Mobile from) + { + if (ForceNonExceptional) + return 0.0; + + var bonus = 0.0; + + if (from.Talisman is BaseTalisman talisman && talisman.Skill == system.MainSkill) + { + chance -= talisman.SuccessBonus / 100.0; + bonus = talisman.ExceptionalBonus / 100.0; + } + + switch (system.ECA) + { + default: + chance -= 0.6; + break; + case CraftECA.FiftyPercentChanceMinusTenPercent: + chance = chance * 0.5 - 0.1; + break; + case CraftECA.ChanceMinusSixtyToFourtyFive: + chance -= Math.Clamp(0.60 - (from.Skills[system.MainSkill].Value - 95.0) * 0.03, 0.45, 0.60); + break; + } + + return chance > 0 ? chance + bonus : chance; + } + + public bool CheckSkills( + Mobile from, Type typeRes, CraftSystem craftSystem, ref int quality, + ref bool allRequiredSkills + ) => + CheckSkills(from, typeRes, craftSystem, ref quality, out allRequiredSkills, true); + + public bool CheckSkills( + Mobile from, Type typeRes, CraftSystem craftSystem, ref int quality, + out bool allRequiredSkills, bool gainSkills + ) + { + var chance = GetSuccessChance(from, typeRes, craftSystem, gainSkills, out allRequiredSkills); + + if (GetExceptionalChance(craftSystem, chance, from) > Utility.RandomDouble()) + quality = 2; + + return chance > Utility.RandomDouble(); + } + + public double GetSuccessChance( + Mobile from, Type typeRes, CraftSystem craftSystem, bool gainSkills, + out bool allRequiredSkills + ) + { + var minMainSkill = 0.0; + var maxMainSkill = 0.0; + var valMainSkill = 0.0; + + allRequiredSkills = true; + + for (var i = 0; i < Skills.Count; i++) + { + var craftSkill = Skills[i]; + + var minSkill = craftSkill.MinSkill; + var maxSkill = craftSkill.MaxSkill; + var valSkill = from.Skills[craftSkill.SkillToMake].Value; + + if (valSkill < minSkill) + allRequiredSkills = false; + + if (craftSkill.SkillToMake == craftSystem.MainSkill) + { + minMainSkill = minSkill; + maxMainSkill = maxSkill; + valMainSkill = valSkill; + } + + if (gainSkills) // This is a passive check. Success chance is entirely dependant on the main skill + from.CheckSkill(craftSkill.SkillToMake, minSkill, maxSkill); + } + + double chance; + + if (allRequiredSkills) + chance = craftSystem.GetChanceAtMin(this) + (valMainSkill - minMainSkill) / (maxMainSkill - minMainSkill) * + (1.0 - craftSystem.GetChanceAtMin(this)); + else + chance = 0.0; + + if (allRequiredSkills && from.Talisman is BaseTalisman talisman && talisman.Skill == craftSystem.MainSkill) + chance += talisman.SuccessBonus / 100.0; + + if (allRequiredSkills && valMainSkill == maxMainSkill) + chance = 1.0; + + return chance; + } + + public void Craft(Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool) + { + if (from.BeginAction()) + { + if (RequiredExpansion == Expansion.None || + from.NetState?.SupportsExpansion(RequiredExpansion) == true) + { + bool allRequiredSkills; + var chance = GetSuccessChance(from, typeRes, craftSystem, false, out allRequiredSkills); + + if (allRequiredSkills && chance >= 0.0) + { + if (Recipe == null || (from as PlayerMobile)?.HasRecipe(Recipe) != false) + { + var badCraft = craftSystem.CanCraft(from, tool, ItemType); + + if (badCraft <= 0) + { + var resHue = 0; + var maxAmount = 0; + object message = null; + + if (ConsumeRes( + from, + typeRes, + craftSystem, + ref resHue, + ref maxAmount, + ConsumeType.None, + ref message + )) + { + message = null; + + if (ConsumeAttributes(from, ref message, false)) + { + var context = craftSystem.GetContext(from); + + context?.OnMade(this); + + var iMin = craftSystem.MinCraftEffect; + var iMax = craftSystem.MaxCraftEffect - iMin + 1; + var iRandom = Utility.Random(iMax); + iRandom += iMin + 1; + new InternalTimer(from, craftSystem, this, typeRes, tool, iRandom).Start(); + } + else + { + from.EndAction(); + from.SendGump(new CraftGump(from, craftSystem, tool, message)); + } + } + else + { + from.EndAction(); + from.SendGump(new CraftGump(from, craftSystem, tool, message)); + } + } + else + { + from.EndAction(); + from.SendGump(new CraftGump(from, craftSystem, tool, badCraft)); + } + } + else + { + from.EndAction(); + from.SendGump( + new CraftGump( + from, + craftSystem, + tool, + 1072847 + ) + ); // You must learn that recipe from a scroll. + } + } + else + { + from.EndAction(); + from.SendGump( + new CraftGump( + from, + craftSystem, + tool, + 1044153 + ) + ); // You don't have the required skills to attempt this item. + } + } + else + { + from.EndAction(); + from.SendGump( + new CraftGump( + from, + craftSystem, + tool, + RequiredExpansionMessage(RequiredExpansion) + ) + ); // The {0} expansion is required to attempt this item. + } + } + else + { + from.SendLocalizedMessage(500119); // You must wait to perform another action + } + } + + // Eventually convert to TextDefinition, but that requires that we convert all the gumps to ues it too. Not that it wouldn't be a bad idea. + private object RequiredExpansionMessage(Expansion expansion) + { + return expansion switch + { + Expansion.SE => 1063307, // The "Samurai Empire" expansion is required to attempt this item. + Expansion.ML => 1072650, // The "Mondain's Legacy" expansion is required to attempt this item. + _ => $"The \"{ExpansionInfo.GetInfo(expansion).Name}\" expansion is required to attempt this item." + }; + } + + public void CompleteCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, + BaseTool tool, CustomCraft customCraft + ) + { + var badCraft = craftSystem.CanCraft(from, tool, ItemType); + + if (badCraft > 0) + { + if (tool?.Deleted == false && tool.UsesRemaining > 0) + from.SendGump(new CraftGump(from, craftSystem, tool, badCraft)); + else + from.SendLocalizedMessage(badCraft); + + return; + } + + int checkResHue = 0, checkMaxAmount = 0; + object checkMessage = null; + + // Not enough resource to craft it + if (!(ConsumeRes( + from, + typeRes, + craftSystem, + ref checkResHue, + ref checkMaxAmount, + ConsumeType.None, + ref checkMessage + ) + && ConsumeAttributes(from, ref checkMessage, false))) + { + if (tool?.Deleted == false && tool.UsesRemaining > 0) + from.SendGump(new CraftGump(from, craftSystem, tool, checkMessage)); + else if (checkMessage is int messageInt && messageInt > 0) + from.SendLocalizedMessage(messageInt); + else + from.SendMessage(checkMessage.ToString()); + + return; + } + + var toolBroken = false; + + var ignored = 1; + var endquality = 1; + + var allRequiredSkills = true; + + if (CheckSkills(from, typeRes, craftSystem, ref ignored, ref allRequiredSkills)) + { + // Resource + var resHue = 0; + var maxAmount = 0; + + object message = null; + + // Not enough resource to craft it + if (!(ConsumeRes(from, typeRes, craftSystem, ref resHue, ref maxAmount, ConsumeType.All, ref message) + && ConsumeAttributes(from, ref message, true))) + { + if (tool?.Deleted == false && tool.UsesRemaining > 0) + from.SendGump(new CraftGump(from, craftSystem, tool, message)); + else if (message is int messageIn && messageIn > 0) + from.SendLocalizedMessage(messageIn); + else + from.SendMessage(message.ToString()); + + return; + } + + tool.UsesRemaining--; + + if (craftSystem is DefBlacksmithy) + if (from.FindItemOnLayer(Layer.OneHanded) is AncientSmithyHammer hammer && hammer != tool) + { + hammer.UsesRemaining--; + if (hammer.UsesRemaining < 1) + hammer.Delete(); + } + + if (tool.UsesRemaining < 1 && tool.BreakOnDepletion) + toolBroken = true; + + if (toolBroken) + tool.Delete(); + + var num = 0; + + Item item; + if (customCraft != null) + { + item = customCraft.CompleteCraft(out num); + } + else if (typeof(MapItem).IsAssignableFrom(ItemType) && from.Map != Map.Trammel && from.Map != Map.Felucca) + { + item = new IndecipherableMap(); + from.SendLocalizedMessage(1070800); // The map you create becomes mysteriously indecipherable. + } + else + { + item = ActivatorUtil.CreateInstance(ItemType) as Item; + } + + if (item != null) + { + if (item is ICraftable craftable) + endquality = craftable.OnCraft(quality, makersMark, from, craftSystem, typeRes, tool, this, resHue); + else if (item.Hue == 0) + item.Hue = resHue; + + if (maxAmount > 0) + { + if (!item.Stackable && item is IUsesRemaining remaining) + remaining.UsesRemaining *= maxAmount; + else + item.Amount = maxAmount; + } + + from.AddToBackpack(item); + + if (from.AccessLevel > AccessLevel.Player) + CommandLogging.WriteLine( + from, + "Crafting {0} with craft system {1}", + CommandLogging.Format(item), + craftSystem.GetType().Name + ); + + // from.PlaySound( 0x57 ); + } + + if (num == 0) + num = craftSystem.PlayEndingEffect(from, false, true, toolBroken, endquality, makersMark, this); + + var queryFactionImbue = false; + var availableSilver = 0; + FactionItemDefinition def = null; + Faction faction = null; + + if (item is IFactionItem) + { + def = FactionItemDefinition.Identify(item); + + if (def != null) + { + faction = Faction.Find(from); + + if (faction != null) + { + var town = Town.FromRegion(from.Region); + + if (town?.Owner == faction) + { + var pack = from.Backpack; + + if (pack != null) + { + availableSilver = pack.GetAmount(typeof(Silver)); + + if (availableSilver >= def.SilverCost) + queryFactionImbue = Faction.IsNearType(from, def.VendorType, 12); + } + } + } + } + } + + // TODO: Scroll imbuing + + if (queryFactionImbue) + from.SendGump( + new FactionImbueGump( + quality, + item, + from, + craftSystem, + tool, + num, + availableSilver, + faction, + def + ) + ); + else if (tool?.Deleted == false && tool.UsesRemaining > 0) + from.SendGump(new CraftGump(from, craftSystem, tool, num)); + else if (num > 0) + from.SendLocalizedMessage(num); + } + else if (!allRequiredSkills) + { + if (tool?.Deleted == false && tool.UsesRemaining > 0) + from.SendGump(new CraftGump(from, craftSystem, tool, 1044153)); + else + from.SendLocalizedMessage(1044153); // You don't have the required skills to attempt this item. + } + else + { + var consumeType = UseAllRes ? ConsumeType.Half : ConsumeType.All; + var resHue = 0; + var maxAmount = 0; + + object message = null; + + // Not enough resource to craft it + if (!ConsumeRes(from, typeRes, craftSystem, ref resHue, ref maxAmount, consumeType, ref message, true)) + { + if (tool?.Deleted == false && tool.UsesRemaining > 0) + from.SendGump(new CraftGump(from, craftSystem, tool, message)); + else if (message is int messageInt && messageInt > 0) + from.SendLocalizedMessage(messageInt); + else + from.SendMessage(message.ToString()); + + return; + } + + tool.UsesRemaining--; + + if (tool.UsesRemaining < 1 && tool.BreakOnDepletion) + toolBroken = true; + + if (toolBroken) + tool.Delete(); + + // SkillCheck failed. + var num = craftSystem.PlayEndingEffect(from, true, true, toolBroken, endquality, false, this); + + if (!tool.Deleted && tool.UsesRemaining > 0) + from.SendGump(new CraftGump(from, craftSystem, tool, num)); + else if (num > 0) + from.SendLocalizedMessage(num); + } + } + + private class InternalTimer : Timer + { + private readonly CraftItem m_CraftItem; + private readonly CraftSystem m_CraftSystem; + private readonly Mobile m_From; + private readonly int m_iCountMax; + private readonly BaseTool m_Tool; + private readonly Type m_TypeRes; + private int m_iCount; + + public InternalTimer( + Mobile from, CraftSystem craftSystem, CraftItem craftItem, Type typeRes, BaseTool tool, + int iCountMax + ) : base(TimeSpan.Zero, TimeSpan.FromSeconds(craftSystem.Delay), iCountMax) + { + m_From = from; + m_CraftItem = craftItem; + m_iCount = 0; + m_iCountMax = iCountMax; + m_CraftSystem = craftSystem; + m_TypeRes = typeRes; + m_Tool = tool; + } + + protected override void OnTick() + { + m_iCount++; + + m_From.DisruptiveAction(); + + if (m_iCount < m_iCountMax) + { + m_CraftSystem.PlayCraftEffect(m_From); + } + else + { + m_From.EndAction(); + + var badCraft = m_CraftSystem.CanCraft(m_From, m_Tool, m_CraftItem.ItemType); + + if (badCraft > 0) + { + if (m_Tool?.Deleted == false && m_Tool.UsesRemaining > 0) + m_From.SendGump(new CraftGump(m_From, m_CraftSystem, m_Tool, badCraft)); + else + m_From.SendLocalizedMessage(badCraft); + + return; + } + + var quality = 1; + var allRequiredSkills = true; + + m_CraftItem.CheckSkills(m_From, m_TypeRes, m_CraftSystem, ref quality, out allRequiredSkills, false); + + var context = m_CraftSystem.GetContext(m_From); + + if (context == null) + return; + + if (typeof(CustomCraft).IsAssignableFrom(m_CraftItem.ItemType)) + { + CustomCraft cc = null; + + try + { + cc = ActivatorUtil.CreateInstance( + m_CraftItem.ItemType, + m_From, + m_CraftItem, + m_CraftSystem, + m_TypeRes, + m_Tool, + quality + ) as CustomCraft; + } + catch + { + // ignored + } + + cc?.EndCraftAction(); + + return; + } + + var makersMark = false; + + if (quality == 2 && m_From.Skills[m_CraftSystem.MainSkill].Base >= 100.0) + makersMark = m_CraftItem.IsMarkable(m_CraftItem.ItemType); + + if (makersMark && context.MarkOption == CraftMarkOption.PromptForMark) + { + m_From.SendGump( + new QueryMakersMarkGump( + quality, + m_From, + m_CraftItem, + m_CraftSystem, + m_TypeRes, + m_Tool + ) + ); + } + else + { + if (context.MarkOption == CraftMarkOption.DoNotMark) + makersMark = false; + + m_CraftItem.CompleteCraft(quality, makersMark, m_From, m_CraftSystem, m_TypeRes, m_Tool, null); + } + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Craft/Core/CraftItemIDAttribute.cs b/Projects/UOContent/Engines/Craft/Core/CraftItemIDAttribute.cs index ac0a2d76d..440b2a2c9 100644 --- a/Projects/UOContent/Engines/Craft/Core/CraftItemIDAttribute.cs +++ b/Projects/UOContent/Engines/Craft/Core/CraftItemIDAttribute.cs @@ -1,12 +1,12 @@ -using System; - -namespace Server.Engines.Craft -{ - [AttributeUsage(AttributeTargets.Class)] - public class CraftItemIDAttribute : Attribute - { - public CraftItemIDAttribute(int itemID) => ItemID = itemID; - - public int ItemID { get; } - } -} \ No newline at end of file +using System; + +namespace Server.Engines.Craft +{ + [AttributeUsage(AttributeTargets.Class)] + public class CraftItemIDAttribute : Attribute + { + public CraftItemIDAttribute(int itemID) => ItemID = itemID; + + public int ItemID { get; } + } +} diff --git a/Projects/UOContent/Engines/Craft/Core/CraftRes.cs b/Projects/UOContent/Engines/Craft/Core/CraftRes.cs index 9fc4bfbb8..9d681c6ee 100644 --- a/Projects/UOContent/Engines/Craft/Core/CraftRes.cs +++ b/Projects/UOContent/Engines/Craft/Core/CraftRes.cs @@ -1,41 +1,41 @@ -using System; - -namespace Server.Engines.Craft -{ - public class CraftRes - { - public CraftRes(Type type, TextDefinition name, int amount, TextDefinition message = null) - { - ItemType = type; - Amount = amount; - - NameNumber = name; - MessageNumber = message; - - NameString = name; - MessageString = message; - } - - public Type ItemType { get; } - - public string MessageString { get; } - - public int MessageNumber { get; } - - public string NameString { get; } - - public int NameNumber { get; } - - public int Amount { get; } - - public void SendMessage(Mobile from) - { - if (MessageNumber > 0) - from.SendLocalizedMessage(MessageNumber); - else if (!string.IsNullOrEmpty(MessageString)) - from.SendMessage(MessageString); - else - from.SendLocalizedMessage(502925); // You don't have the resources required to make that item. - } - } -} +using System; + +namespace Server.Engines.Craft +{ + public class CraftRes + { + public CraftRes(Type type, TextDefinition name, int amount, TextDefinition message = null) + { + ItemType = type; + Amount = amount; + + NameNumber = name; + MessageNumber = message; + + NameString = name; + MessageString = message; + } + + public Type ItemType { get; } + + public string MessageString { get; } + + public int MessageNumber { get; } + + public string NameString { get; } + + public int NameNumber { get; } + + public int Amount { get; } + + public void SendMessage(Mobile from) + { + if (MessageNumber > 0) + from.SendLocalizedMessage(MessageNumber); + else if (!string.IsNullOrEmpty(MessageString)) + from.SendMessage(MessageString); + else + from.SendLocalizedMessage(502925); // You don't have the resources required to make that item. + } + } +} diff --git a/Projects/UOContent/Engines/Craft/Core/CraftSkill.cs b/Projects/UOContent/Engines/Craft/Core/CraftSkill.cs index afbfae234..1fb747acb 100644 --- a/Projects/UOContent/Engines/Craft/Core/CraftSkill.cs +++ b/Projects/UOContent/Engines/Craft/Core/CraftSkill.cs @@ -1,18 +1,18 @@ -namespace Server.Engines.Craft -{ - public class CraftSkill - { - public CraftSkill(SkillName skillToMake, double minSkill, double maxSkill) - { - SkillToMake = skillToMake; - MinSkill = minSkill; - MaxSkill = maxSkill; - } - - public SkillName SkillToMake { get; } - - public double MinSkill { get; } - - public double MaxSkill { get; } - } -} \ No newline at end of file +namespace Server.Engines.Craft +{ + public class CraftSkill + { + public CraftSkill(SkillName skillToMake, double minSkill, double maxSkill) + { + SkillToMake = skillToMake; + MinSkill = minSkill; + MaxSkill = maxSkill; + } + + public SkillName SkillToMake { get; } + + public double MinSkill { get; } + + public double MaxSkill { get; } + } +} diff --git a/Projects/UOContent/Engines/Craft/Core/CraftSubRes.cs b/Projects/UOContent/Engines/Craft/Core/CraftSubRes.cs index 88b63a2ec..c0c552029 100644 --- a/Projects/UOContent/Engines/Craft/Core/CraftSubRes.cs +++ b/Projects/UOContent/Engines/Craft/Core/CraftSubRes.cs @@ -1,34 +1,39 @@ -using System; - -namespace Server.Engines.Craft -{ - public class CraftSubRes - { - public CraftSubRes(Type type, TextDefinition name, double reqSkill, object message) : this(type, name, reqSkill, 0, - message) - { - } - - public CraftSubRes(Type type, TextDefinition name, double reqSkill, int genericNameNumber, object message) - { - ItemType = type; - NameNumber = name; - NameString = name; - RequiredSkill = reqSkill; - GenericNameNumber = genericNameNumber; - Message = message; - } - - public Type ItemType { get; } - - public string NameString { get; } - - public int NameNumber { get; } - - public int GenericNameNumber { get; } - - public object Message { get; } - - public double RequiredSkill { get; } - } -} +using System; + +namespace Server.Engines.Craft +{ + public class CraftSubRes + { + public CraftSubRes(Type type, TextDefinition name, double reqSkill, object message) : this( + type, + name, + reqSkill, + 0, + message + ) + { + } + + public CraftSubRes(Type type, TextDefinition name, double reqSkill, int genericNameNumber, object message) + { + ItemType = type; + NameNumber = name; + NameString = name; + RequiredSkill = reqSkill; + GenericNameNumber = genericNameNumber; + Message = message; + } + + public Type ItemType { get; } + + public string NameString { get; } + + public int NameNumber { get; } + + public int GenericNameNumber { get; } + + public object Message { get; } + + public double RequiredSkill { get; } + } +} diff --git a/Projects/UOContent/Engines/Craft/Core/CraftSubResCol.cs b/Projects/UOContent/Engines/Craft/Core/CraftSubResCol.cs index 535ba1655..ff0d931d9 100644 --- a/Projects/UOContent/Engines/Craft/Core/CraftSubResCol.cs +++ b/Projects/UOContent/Engines/Craft/Core/CraftSubResCol.cs @@ -1,31 +1,31 @@ -using System; -using System.Collections.Generic; - -namespace Server.Engines.Craft -{ - public class CraftSubResCol : List - { - public CraftSubResCol() => Init = false; - - public bool Init { get; set; } - - public Type ResType { get; set; } - - public string NameString { get; set; } - - public int NameNumber { get; set; } - - public CraftSubRes GetAt(int index) => this[index]; - - public CraftSubRes SearchFor(Type type) - { - for (int i = 0; i < Count; i++) - { - CraftSubRes craftSubRes = this[i]; - if (craftSubRes.ItemType == type) return craftSubRes; - } - - return null; - } - } -} +using System; +using System.Collections.Generic; + +namespace Server.Engines.Craft +{ + public class CraftSubResCol : List + { + public CraftSubResCol() => Init = false; + + public bool Init { get; set; } + + public Type ResType { get; set; } + + public string NameString { get; set; } + + public int NameNumber { get; set; } + + public CraftSubRes GetAt(int index) => this[index]; + + public CraftSubRes SearchFor(Type type) + { + for (var i = 0; i < Count; i++) + { + var craftSubRes = this[i]; + if (craftSubRes.ItemType == type) return craftSubRes; + } + + return null; + } + } +} diff --git a/Projects/UOContent/Engines/Craft/Core/CraftSystem.cs b/Projects/UOContent/Engines/Craft/Core/CraftSystem.cs index bc42239ae..87132e6f9 100644 --- a/Projects/UOContent/Engines/Craft/Core/CraftSystem.cs +++ b/Projects/UOContent/Engines/Craft/Core/CraftSystem.cs @@ -1,327 +1,337 @@ -using System; -using System.Collections.Generic; -using Server.Items; - -namespace Server.Engines.Craft -{ - public enum CraftECA - { - ChanceMinusSixty, - FiftyPercentChanceMinusTenPercent, - ChanceMinusSixtyToFourtyFive - } - - public abstract class CraftSystem - { - private readonly Dictionary m_ContextTable = new Dictionary(); - private readonly List m_RareRecipes; - private readonly List m_Recipes; - - public CraftSystem(int minCraftEffect, int maxCraftEffect, double delay) - { - MinCraftEffect = minCraftEffect; - MaxCraftEffect = maxCraftEffect; - Delay = delay; - - CraftItems = new List(); - CraftGroups = new List(); - CraftSubRes = new CraftSubResCol(); - CraftSubRes2 = new CraftSubResCol(); - - m_Recipes = new List(); - m_RareRecipes = new List(); - - InitCraftList(); - } - - public int MinCraftEffect { get; } - - public int MaxCraftEffect { get; } - - public double Delay { get; } - - public List CraftItems { get; } - - public List CraftGroups { get; } - - public CraftSubResCol CraftSubRes { get; } - - public CraftSubResCol CraftSubRes2 { get; } - - public abstract SkillName MainSkill { get; } - - public virtual int GumpTitleNumber => 0; - public virtual string GumpTitleString => ""; - - public virtual CraftECA ECA => CraftECA.ChanceMinusSixty; - - public bool Resmelt { get; set; } - - public bool Repair { get; set; } - - public bool MarkOption { get; set; } - - public bool CanEnhance { get; set; } - - public abstract double GetChanceAtMin(CraftItem item); - - public virtual bool RetainsColorFrom(CraftItem item, Type type) => false; - - public CraftContext GetContext(Mobile m) - { - if (m == null) - return null; - - if (m.Deleted) - { - m_ContextTable.Remove(m); - return null; - } - - if (!m_ContextTable.TryGetValue(m, out CraftContext c)) - m_ContextTable[m] = c = new CraftContext(); - - return c; - } - - public void OnMade(Mobile m, CraftItem item) - { - GetContext(m)?.OnMade(item); - } - - public virtual bool ConsumeOnFailure(Mobile from, Type resourceType, CraftItem craftItem) => true; - - public void CreateItem(Mobile from, Type type, Type typeRes, BaseTool tool, CraftItem realCraftItem) - { - // Verify if the type is in the list of the craftable item - if (CraftItems.SearchFor(type) != null) - realCraftItem.Craft(from, this, typeRes, tool); - } - - public int RandomRecipe() - { - if (m_Recipes.Count == 0) - return -1; - - return m_Recipes.RandomElement(); - } - - public int RandomRareRecipe() - { - if (m_RareRecipes.Count == 0) - return -1; - - return m_RareRecipes.RandomElement(); - } - - public int AddCraft(Type typeItem, TextDefinition group, TextDefinition name, double minSkill, double maxSkill, - Type typeRes, TextDefinition nameRes, int amount) => - AddCraft(typeItem, group, name, MainSkill, minSkill, maxSkill, typeRes, nameRes, amount, ""); - - public int AddCraft(Type typeItem, TextDefinition group, TextDefinition name, double minSkill, double maxSkill, - Type typeRes, TextDefinition nameRes, int amount, TextDefinition message) => - AddCraft(typeItem, group, name, MainSkill, minSkill, maxSkill, typeRes, nameRes, amount, message); - - public int AddCraft(Type typeItem, TextDefinition group, TextDefinition name, SkillName skillToMake, double minSkill, - double maxSkill, Type typeRes, TextDefinition nameRes, int amount) => - AddCraft(typeItem, group, name, skillToMake, minSkill, maxSkill, typeRes, nameRes, amount, ""); - - public int AddCraft(Type typeItem, TextDefinition group, TextDefinition name, SkillName skillToMake, double minSkill, - double maxSkill, Type typeRes, TextDefinition nameRes, int amount, TextDefinition message) - { - CraftItem craftItem = new CraftItem(typeItem, group, name); - craftItem.AddRes(typeRes, nameRes, amount, message); - craftItem.AddSkill(skillToMake, minSkill, maxSkill); - - DoGroup(group, craftItem); - CraftItems.Add(craftItem); - return CraftItems.Count - 1; - } - - private void DoGroup(TextDefinition groupName, CraftItem craftItem) - { - int index = CraftGroups.SearchFor(groupName); - - if (index == -1) - { - CraftGroup craftGroup = new CraftGroup(groupName); - craftGroup.AddCraftItem(craftItem); - CraftGroups.Add(craftGroup); - } - else - { - CraftGroups[index].AddCraftItem(craftItem); - } - } - - public void SetItemHue(int index, int hue) - { - CraftItems[index].ItemHue = hue; - } - - public void SetManaReq(int index, int mana) - { - CraftItems[index].Mana = mana; - } - - public void SetStamReq(int index, int stam) - { - CraftItems[index].Stam = stam; - } - - public void SetHitsReq(int index, int hits) - { - CraftItems[index].Hits = hits; - } - - public void SetUseAllRes(int index, bool useAll) - { - CraftItems[index].UseAllRes = useAll; - } - - public void SetNeedHeat(int index, bool needHeat) - { - CraftItems[index].NeedHeat = needHeat; - } - - public void SetNeedOven(int index, bool needOven) - { - CraftItems[index].NeedOven = needOven; - } - - public void SetBeverageType(int index, BeverageType requiredBeverage) - { - CraftItems[index].RequiredBeverage = requiredBeverage; - } - - public void SetNeedMill(int index, bool needMill) - { - CraftItems[index].NeedMill = needMill; - } - - public void SetNeededExpansion(int index, Expansion expansion) - { - CraftItems[index].RequiredExpansion = expansion; - } - - public void AddRes(int index, Type type, TextDefinition name, int amount) - { - AddRes(index, type, name, amount, ""); - } - - public void AddRes(int index, Type type, TextDefinition name, int amount, TextDefinition message) - { - CraftItems[index].AddRes(type, name, amount, message); - } - - public void AddSkill(int index, SkillName skillToMake, double minSkill, double maxSkill) - { - CraftItems[index].AddSkill(skillToMake, minSkill, maxSkill); - } - - public void SetUseSubRes2(int index, bool val) - { - CraftItems[index].UseSubRes2 = val; - } - - private void AddRecipeBase(int index, int id) - { - CraftItems[index].AddRecipe(id, this); - } - - public void AddRecipe(int index, int id) - { - AddRecipeBase(index, id); - m_Recipes.Add(id); - } - - public void AddRareRecipe(int index, int id) - { - AddRecipeBase(index, id); - m_RareRecipes.Add(id); - } - - public void AddQuestRecipe(int index, int id) - { - AddRecipeBase(index, id); - } - - public void ForceNonExceptional(int index) - { - CraftItems[index].ForceNonExceptional = true; - } - - public void SetSubRes(Type type, string name) - { - CraftSubRes.ResType = type; - CraftSubRes.NameString = name; - CraftSubRes.Init = true; - } - - public void SetSubRes(Type type, int name) - { - CraftSubRes.ResType = type; - CraftSubRes.NameNumber = name; - CraftSubRes.Init = true; - } - - public void AddSubRes(Type type, int name, double reqSkill, object message) - { - CraftSubRes craftSubRes = new CraftSubRes(type, name, reqSkill, message); - CraftSubRes.Add(craftSubRes); - } - - public void AddSubRes(Type type, int name, double reqSkill, int genericName, object message) - { - CraftSubRes craftSubRes = new CraftSubRes(type, name, reqSkill, genericName, message); - CraftSubRes.Add(craftSubRes); - } - - public void AddSubRes(Type type, string name, double reqSkill, object message) - { - CraftSubRes craftSubRes = new CraftSubRes(type, name, reqSkill, message); - CraftSubRes.Add(craftSubRes); - } - - public void SetSubRes2(Type type, string name) - { - CraftSubRes2.ResType = type; - CraftSubRes2.NameString = name; - CraftSubRes2.Init = true; - } - - public void SetSubRes2(Type type, int name) - { - CraftSubRes2.ResType = type; - CraftSubRes2.NameNumber = name; - CraftSubRes2.Init = true; - } - - public void AddSubRes2(Type type, int name, double reqSkill, object message) - { - CraftSubRes craftSubRes = new CraftSubRes(type, name, reqSkill, message); - CraftSubRes2.Add(craftSubRes); - } - - public void AddSubRes2(Type type, int name, double reqSkill, int genericName, object message) - { - CraftSubRes craftSubRes = new CraftSubRes(type, name, reqSkill, genericName, message); - CraftSubRes2.Add(craftSubRes); - } - - public void AddSubRes2(Type type, string name, double reqSkill, object message) - { - CraftSubRes craftSubRes = new CraftSubRes(type, name, reqSkill, message); - CraftSubRes2.Add(craftSubRes); - } - - public abstract void InitCraftList(); - - public abstract void PlayCraftEffect(Mobile from); - - public abstract int PlayEndingEffect(Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, - bool makersMark, CraftItem item); - - public abstract int CanCraft(Mobile from, BaseTool tool, Type itemType); - } -} +using System; +using System.Collections.Generic; +using Server.Items; + +namespace Server.Engines.Craft +{ + public enum CraftECA + { + ChanceMinusSixty, + FiftyPercentChanceMinusTenPercent, + ChanceMinusSixtyToFourtyFive + } + + public abstract class CraftSystem + { + private readonly Dictionary m_ContextTable = new Dictionary(); + private readonly List m_RareRecipes; + private readonly List m_Recipes; + + public CraftSystem(int minCraftEffect, int maxCraftEffect, double delay) + { + MinCraftEffect = minCraftEffect; + MaxCraftEffect = maxCraftEffect; + Delay = delay; + + CraftItems = new List(); + CraftGroups = new List(); + CraftSubRes = new CraftSubResCol(); + CraftSubRes2 = new CraftSubResCol(); + + m_Recipes = new List(); + m_RareRecipes = new List(); + + InitCraftList(); + } + + public int MinCraftEffect { get; } + + public int MaxCraftEffect { get; } + + public double Delay { get; } + + public List CraftItems { get; } + + public List CraftGroups { get; } + + public CraftSubResCol CraftSubRes { get; } + + public CraftSubResCol CraftSubRes2 { get; } + + public abstract SkillName MainSkill { get; } + + public virtual int GumpTitleNumber => 0; + public virtual string GumpTitleString => ""; + + public virtual CraftECA ECA => CraftECA.ChanceMinusSixty; + + public bool Resmelt { get; set; } + + public bool Repair { get; set; } + + public bool MarkOption { get; set; } + + public bool CanEnhance { get; set; } + + public abstract double GetChanceAtMin(CraftItem item); + + public virtual bool RetainsColorFrom(CraftItem item, Type type) => false; + + public CraftContext GetContext(Mobile m) + { + if (m == null) + return null; + + if (m.Deleted) + { + m_ContextTable.Remove(m); + return null; + } + + if (!m_ContextTable.TryGetValue(m, out var c)) + m_ContextTable[m] = c = new CraftContext(); + + return c; + } + + public void OnMade(Mobile m, CraftItem item) + { + GetContext(m)?.OnMade(item); + } + + public virtual bool ConsumeOnFailure(Mobile from, Type resourceType, CraftItem craftItem) => true; + + public void CreateItem(Mobile from, Type type, Type typeRes, BaseTool tool, CraftItem realCraftItem) + { + // Verify if the type is in the list of the craftable item + if (CraftItems.SearchFor(type) != null) + realCraftItem.Craft(from, this, typeRes, tool); + } + + public int RandomRecipe() + { + if (m_Recipes.Count == 0) + return -1; + + return m_Recipes.RandomElement(); + } + + public int RandomRareRecipe() + { + if (m_RareRecipes.Count == 0) + return -1; + + return m_RareRecipes.RandomElement(); + } + + public int AddCraft( + Type typeItem, TextDefinition group, TextDefinition name, double minSkill, double maxSkill, + Type typeRes, TextDefinition nameRes, int amount + ) => + AddCraft(typeItem, group, name, MainSkill, minSkill, maxSkill, typeRes, nameRes, amount, ""); + + public int AddCraft( + Type typeItem, TextDefinition group, TextDefinition name, double minSkill, double maxSkill, + Type typeRes, TextDefinition nameRes, int amount, TextDefinition message + ) => + AddCraft(typeItem, group, name, MainSkill, minSkill, maxSkill, typeRes, nameRes, amount, message); + + public int AddCraft( + Type typeItem, TextDefinition group, TextDefinition name, SkillName skillToMake, double minSkill, + double maxSkill, Type typeRes, TextDefinition nameRes, int amount + ) => + AddCraft(typeItem, group, name, skillToMake, minSkill, maxSkill, typeRes, nameRes, amount, ""); + + public int AddCraft( + Type typeItem, TextDefinition group, TextDefinition name, SkillName skillToMake, double minSkill, + double maxSkill, Type typeRes, TextDefinition nameRes, int amount, TextDefinition message + ) + { + var craftItem = new CraftItem(typeItem, group, name); + craftItem.AddRes(typeRes, nameRes, amount, message); + craftItem.AddSkill(skillToMake, minSkill, maxSkill); + + DoGroup(group, craftItem); + CraftItems.Add(craftItem); + return CraftItems.Count - 1; + } + + private void DoGroup(TextDefinition groupName, CraftItem craftItem) + { + var index = CraftGroups.SearchFor(groupName); + + if (index == -1) + { + var craftGroup = new CraftGroup(groupName); + craftGroup.AddCraftItem(craftItem); + CraftGroups.Add(craftGroup); + } + else + { + CraftGroups[index].AddCraftItem(craftItem); + } + } + + public void SetItemHue(int index, int hue) + { + CraftItems[index].ItemHue = hue; + } + + public void SetManaReq(int index, int mana) + { + CraftItems[index].Mana = mana; + } + + public void SetStamReq(int index, int stam) + { + CraftItems[index].Stam = stam; + } + + public void SetHitsReq(int index, int hits) + { + CraftItems[index].Hits = hits; + } + + public void SetUseAllRes(int index, bool useAll) + { + CraftItems[index].UseAllRes = useAll; + } + + public void SetNeedHeat(int index, bool needHeat) + { + CraftItems[index].NeedHeat = needHeat; + } + + public void SetNeedOven(int index, bool needOven) + { + CraftItems[index].NeedOven = needOven; + } + + public void SetBeverageType(int index, BeverageType requiredBeverage) + { + CraftItems[index].RequiredBeverage = requiredBeverage; + } + + public void SetNeedMill(int index, bool needMill) + { + CraftItems[index].NeedMill = needMill; + } + + public void SetNeededExpansion(int index, Expansion expansion) + { + CraftItems[index].RequiredExpansion = expansion; + } + + public void AddRes(int index, Type type, TextDefinition name, int amount) + { + AddRes(index, type, name, amount, ""); + } + + public void AddRes(int index, Type type, TextDefinition name, int amount, TextDefinition message) + { + CraftItems[index].AddRes(type, name, amount, message); + } + + public void AddSkill(int index, SkillName skillToMake, double minSkill, double maxSkill) + { + CraftItems[index].AddSkill(skillToMake, minSkill, maxSkill); + } + + public void SetUseSubRes2(int index, bool val) + { + CraftItems[index].UseSubRes2 = val; + } + + private void AddRecipeBase(int index, int id) + { + CraftItems[index].AddRecipe(id, this); + } + + public void AddRecipe(int index, int id) + { + AddRecipeBase(index, id); + m_Recipes.Add(id); + } + + public void AddRareRecipe(int index, int id) + { + AddRecipeBase(index, id); + m_RareRecipes.Add(id); + } + + public void AddQuestRecipe(int index, int id) + { + AddRecipeBase(index, id); + } + + public void ForceNonExceptional(int index) + { + CraftItems[index].ForceNonExceptional = true; + } + + public void SetSubRes(Type type, string name) + { + CraftSubRes.ResType = type; + CraftSubRes.NameString = name; + CraftSubRes.Init = true; + } + + public void SetSubRes(Type type, int name) + { + CraftSubRes.ResType = type; + CraftSubRes.NameNumber = name; + CraftSubRes.Init = true; + } + + public void AddSubRes(Type type, int name, double reqSkill, object message) + { + var craftSubRes = new CraftSubRes(type, name, reqSkill, message); + CraftSubRes.Add(craftSubRes); + } + + public void AddSubRes(Type type, int name, double reqSkill, int genericName, object message) + { + var craftSubRes = new CraftSubRes(type, name, reqSkill, genericName, message); + CraftSubRes.Add(craftSubRes); + } + + public void AddSubRes(Type type, string name, double reqSkill, object message) + { + var craftSubRes = new CraftSubRes(type, name, reqSkill, message); + CraftSubRes.Add(craftSubRes); + } + + public void SetSubRes2(Type type, string name) + { + CraftSubRes2.ResType = type; + CraftSubRes2.NameString = name; + CraftSubRes2.Init = true; + } + + public void SetSubRes2(Type type, int name) + { + CraftSubRes2.ResType = type; + CraftSubRes2.NameNumber = name; + CraftSubRes2.Init = true; + } + + public void AddSubRes2(Type type, int name, double reqSkill, object message) + { + var craftSubRes = new CraftSubRes(type, name, reqSkill, message); + CraftSubRes2.Add(craftSubRes); + } + + public void AddSubRes2(Type type, int name, double reqSkill, int genericName, object message) + { + var craftSubRes = new CraftSubRes(type, name, reqSkill, genericName, message); + CraftSubRes2.Add(craftSubRes); + } + + public void AddSubRes2(Type type, string name, double reqSkill, object message) + { + var craftSubRes = new CraftSubRes(type, name, reqSkill, message); + CraftSubRes2.Add(craftSubRes); + } + + public abstract void InitCraftList(); + + public abstract void PlayCraftEffect(Mobile from); + + public abstract int PlayEndingEffect( + Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, + bool makersMark, CraftItem item + ); + + public abstract int CanCraft(Mobile from, BaseTool tool, Type itemType); + } +} diff --git a/Projects/UOContent/Engines/Craft/Core/CustomCraft.cs b/Projects/UOContent/Engines/Craft/Core/CustomCraft.cs index 133994f4e..5dc4c3144 100644 --- a/Projects/UOContent/Engines/Craft/Core/CustomCraft.cs +++ b/Projects/UOContent/Engines/Craft/Core/CustomCraft.cs @@ -1,34 +1,36 @@ -using System; -using Server.Items; - -namespace Server.Engines.Craft -{ - public abstract class CustomCraft - { - public CustomCraft(Mobile from, CraftItem craftItem, CraftSystem craftSystem, Type typeRes, BaseTool tool, - int quality) - { - From = from; - CraftItem = craftItem; - CraftSystem = craftSystem; - TypeRes = typeRes; - Tool = tool; - Quality = quality; - } - - public Mobile From { get; } - - public CraftItem CraftItem { get; } - - public CraftSystem CraftSystem { get; } - - public Type TypeRes { get; } - - public BaseTool Tool { get; } - - public int Quality { get; } - - public abstract void EndCraftAction(); - public abstract Item CompleteCraft(out int message); - } -} \ No newline at end of file +using System; +using Server.Items; + +namespace Server.Engines.Craft +{ + public abstract class CustomCraft + { + public CustomCraft( + Mobile from, CraftItem craftItem, CraftSystem craftSystem, Type typeRes, BaseTool tool, + int quality + ) + { + From = from; + CraftItem = craftItem; + CraftSystem = craftSystem; + TypeRes = typeRes; + Tool = tool; + Quality = quality; + } + + public Mobile From { get; } + + public CraftItem CraftItem { get; } + + public CraftSystem CraftSystem { get; } + + public Type TypeRes { get; } + + public BaseTool Tool { get; } + + public int Quality { get; } + + public abstract void EndCraftAction(); + public abstract Item CompleteCraft(out int message); + } +} diff --git a/Projects/UOContent/Engines/Craft/Core/Enhance.cs b/Projects/UOContent/Engines/Craft/Core/Enhance.cs index b08a91886..238fff02b 100644 --- a/Projects/UOContent/Engines/Craft/Core/Enhance.cs +++ b/Projects/UOContent/Engines/Craft/Core/Enhance.cs @@ -1,324 +1,377 @@ -using System; -using Server.Items; -using Server.Targeting; - -namespace Server.Engines.Craft -{ - public enum EnhanceResult - { - None, - NotInBackpack, - BadItem, - BadResource, - AlreadyEnhanced, - Success, - Failure, - Broken, - NoResources, - NoSkill - } - - public class Enhance - { - public static EnhanceResult Invoke(Mobile from, CraftSystem craftSystem, BaseTool tool, Item item, - CraftResource resource, Type resType, ref object resMessage) - { - if (item == null) - return EnhanceResult.BadItem; - - if (!item.IsChildOf(from.Backpack)) - return EnhanceResult.NotInBackpack; - - if (!(item is BaseArmor) && !(item is BaseWeapon)) - return EnhanceResult.BadItem; - - if (item is IArcaneEquip eq && eq.IsArcane) - return EnhanceResult.BadItem; - - if (CraftResources.IsStandard(resource)) - return EnhanceResult.BadResource; - - int num = craftSystem.CanCraft(from, tool, item.GetType()); - - if (num > 0) - { - resMessage = num; - return EnhanceResult.None; - } - - CraftItem craftItem = craftSystem.CraftItems.SearchFor(item.GetType()); - - if (craftItem == null || craftItem.Resources.Count == 0) - return EnhanceResult.BadItem; - - if (craftItem.GetSuccessChance(from, resType, craftSystem, false, out _) <= 0.0) - return EnhanceResult.NoSkill; - - CraftResourceInfo info = CraftResources.GetInfo(resource); - - if (info == null || info.ResourceTypes.Length == 0) - return EnhanceResult.BadResource; - - CraftAttributeInfo attributes = info.AttributeInfo; - - if (attributes == null) - return EnhanceResult.BadResource; - - int resHue = 0, maxAmount = 0; - - if (!craftItem.ConsumeRes(from, resType, craftSystem, ref resHue, ref maxAmount, ConsumeType.None, - ref resMessage)) - return EnhanceResult.NoResources; - - if (craftSystem is DefBlacksmithy) - if (from.FindItemOnLayer(Layer.OneHanded) is AncientSmithyHammer hammer) - { - hammer.UsesRemaining--; - if (hammer.UsesRemaining < 1) - hammer.Delete(); - } - - int phys = 0, fire = 0, cold = 0, pois = 0, nrgy = 0; - int dura, luck, lreq, dinc = 0; - int baseChance; - - bool physBonus = false; - bool fireBonus; - bool coldBonus; - bool nrgyBonus; - bool poisBonus; - bool duraBonus; - bool luckBonus; - bool lreqBonus; - bool dincBonus; - - if (item is BaseWeapon weapon) - { - if (!CraftResources.IsStandard(weapon.Resource)) - return EnhanceResult.AlreadyEnhanced; - - baseChance = 20; - - dura = weapon.MaxHitPoints; - luck = weapon.Attributes.Luck; - lreq = weapon.WeaponAttributes.LowerStatReq; - dinc = weapon.Attributes.WeaponDamage; - - fireBonus = attributes.WeaponFireDamage > 0; - coldBonus = attributes.WeaponColdDamage > 0; - nrgyBonus = attributes.WeaponEnergyDamage > 0; - poisBonus = attributes.WeaponPoisonDamage > 0; - - duraBonus = attributes.WeaponDurability > 0; - luckBonus = attributes.WeaponLuck > 0; - lreqBonus = attributes.WeaponLowerRequirements > 0; - dincBonus = dinc > 0; - } - else - { - BaseArmor armor = (BaseArmor)item; - - if (!CraftResources.IsStandard(armor.Resource)) - return EnhanceResult.AlreadyEnhanced; - - baseChance = 20; - - phys = armor.PhysicalResistance; - fire = armor.FireResistance; - cold = armor.ColdResistance; - pois = armor.PoisonResistance; - nrgy = armor.EnergyResistance; - - dura = armor.MaxHitPoints; - luck = armor.Attributes.Luck; - lreq = armor.ArmorAttributes.LowerStatReq; - - physBonus = attributes.ArmorPhysicalResist > 0; - fireBonus = attributes.ArmorFireResist > 0; - coldBonus = attributes.ArmorColdResist > 0; - nrgyBonus = attributes.ArmorEnergyResist > 0; - poisBonus = attributes.ArmorPoisonResist > 0; - - duraBonus = attributes.ArmorDurability > 0; - luckBonus = attributes.ArmorLuck > 0; - lreqBonus = attributes.ArmorLowerRequirements > 0; - dincBonus = false; - } - - int skill = from.Skills[craftSystem.MainSkill].Fixed / 10; - - if (skill >= 100) - baseChance -= (skill - 90) / 10; - - EnhanceResult res = EnhanceResult.Success; - - if (physBonus) - CheckResult(ref res, baseChance + phys); - - if (fireBonus) - CheckResult(ref res, baseChance + fire); - - if (coldBonus) - CheckResult(ref res, baseChance + cold); - - if (nrgyBonus) - CheckResult(ref res, baseChance + nrgy); - - if (poisBonus) - CheckResult(ref res, baseChance + pois); - - if (duraBonus) - CheckResult(ref res, baseChance + dura / 40); - - if (luckBonus) - CheckResult(ref res, baseChance + 10 + luck / 2); - - if (lreqBonus) - CheckResult(ref res, baseChance + lreq / 4); - - if (dincBonus) - CheckResult(ref res, baseChance + dinc / 4); - - switch (res) - { - case EnhanceResult.Broken: - { - if (!craftItem.ConsumeRes(from, resType, craftSystem, ref resHue, ref maxAmount, ConsumeType.Half, - ref resMessage)) - return EnhanceResult.NoResources; - - item.Delete(); - break; - } - case EnhanceResult.Success: - { - if (!craftItem.ConsumeRes(from, resType, craftSystem, ref resHue, ref maxAmount, ConsumeType.All, - ref resMessage)) - return EnhanceResult.NoResources; - - if (item is BaseWeapon w) - { - w.Resource = resource; - - int hue = w.GetElementalDamageHue(); - if (hue > 0) - w.Hue = hue; - } - else - { - ((BaseArmor)item).Resource = resource; - } - - break; - } - case EnhanceResult.Failure: - { - if (!craftItem.ConsumeRes(from, resType, craftSystem, ref resHue, ref maxAmount, ConsumeType.Half, - ref resMessage)) - return EnhanceResult.NoResources; - - break; - } - } - - return res; - } - - public static void CheckResult(ref EnhanceResult res, int chance) - { - if (res != EnhanceResult.Success) - return; // we've already failed.. - - int random = Utility.Random(100); - - if (random < 10) - res = EnhanceResult.Failure; - else if (chance > random) - res = EnhanceResult.Broken; - } - - public static void BeginTarget(Mobile from, CraftSystem craftSystem, BaseTool tool) - { - CraftContext context = craftSystem.GetContext(from); - - if (context == null) - return; - - int lastRes = context.LastResourceIndex; - CraftSubResCol subRes = craftSystem.CraftSubRes; - - if (lastRes >= 0 && lastRes < subRes.Count) - { - CraftSubRes res = subRes.GetAt(lastRes); - - if (from.Skills[craftSystem.MainSkill].Value < res.RequiredSkill) - { - from.SendGump(new CraftGump(from, craftSystem, tool, res.Message)); - } - else - { - CraftResource resource = CraftResources.GetFromType(res.ItemType); - - if (resource != CraftResource.None) - { - from.Target = new InternalTarget(craftSystem, tool, res.ItemType, resource); - from.SendLocalizedMessage( - 1061004); // Target an item to enhance with the properties of your selected material. - } - else - { - from.SendGump(new CraftGump(from, craftSystem, tool, - 1061010)); // You must select a special material in order to enhance an item with its properties. - } - } - } - else - { - from.SendGump(new CraftGump(from, craftSystem, tool, - 1061010)); // You must select a special material in order to enhance an item with its properties. - } - } - - private class InternalTarget : Target - { - private readonly CraftSystem m_CraftSystem; - private readonly CraftResource m_Resource; - private readonly Type m_ResourceType; - private readonly BaseTool m_Tool; - - public InternalTarget(CraftSystem craftSystem, BaseTool tool, Type resourceType, CraftResource resource) : base( - 2, false, TargetFlags.None) - { - m_CraftSystem = craftSystem; - m_Tool = tool; - m_ResourceType = resourceType; - m_Resource = resource; - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is Item item) - { - object message = null; - EnhanceResult res = Enhance.Invoke(from, m_CraftSystem, m_Tool, item, m_Resource, m_ResourceType, - ref message); - - message = res switch - { - EnhanceResult.NotInBackpack => 1061005, - EnhanceResult.AlreadyEnhanced => 1061012, - EnhanceResult.BadItem => 1061011, - EnhanceResult.BadResource => 1061010, - EnhanceResult.Broken => 1061080, - EnhanceResult.Failure => 1061082, - EnhanceResult.Success => 1061008, - EnhanceResult.NoSkill => 1044153, - _ => message - }; - - from.SendGump(new CraftGump(from, m_CraftSystem, m_Tool, message)); - } - } - } - } -} +using System; +using Server.Items; +using Server.Targeting; + +namespace Server.Engines.Craft +{ + public enum EnhanceResult + { + None, + NotInBackpack, + BadItem, + BadResource, + AlreadyEnhanced, + Success, + Failure, + Broken, + NoResources, + NoSkill + } + + public class Enhance + { + public static EnhanceResult Invoke( + Mobile from, CraftSystem craftSystem, BaseTool tool, Item item, + CraftResource resource, Type resType, ref object resMessage + ) + { + if (item == null) + return EnhanceResult.BadItem; + + if (!item.IsChildOf(from.Backpack)) + return EnhanceResult.NotInBackpack; + + if (!(item is BaseArmor) && !(item is BaseWeapon)) + return EnhanceResult.BadItem; + + if (item is IArcaneEquip eq && eq.IsArcane) + return EnhanceResult.BadItem; + + if (CraftResources.IsStandard(resource)) + return EnhanceResult.BadResource; + + var num = craftSystem.CanCraft(from, tool, item.GetType()); + + if (num > 0) + { + resMessage = num; + return EnhanceResult.None; + } + + var craftItem = craftSystem.CraftItems.SearchFor(item.GetType()); + + if (craftItem == null || craftItem.Resources.Count == 0) + return EnhanceResult.BadItem; + + if (craftItem.GetSuccessChance(from, resType, craftSystem, false, out _) <= 0.0) + return EnhanceResult.NoSkill; + + var info = CraftResources.GetInfo(resource); + + if (info == null || info.ResourceTypes.Length == 0) + return EnhanceResult.BadResource; + + var attributes = info.AttributeInfo; + + if (attributes == null) + return EnhanceResult.BadResource; + + int resHue = 0, maxAmount = 0; + + if (!craftItem.ConsumeRes( + from, + resType, + craftSystem, + ref resHue, + ref maxAmount, + ConsumeType.None, + ref resMessage + )) + return EnhanceResult.NoResources; + + if (craftSystem is DefBlacksmithy) + if (from.FindItemOnLayer(Layer.OneHanded) is AncientSmithyHammer hammer) + { + hammer.UsesRemaining--; + if (hammer.UsesRemaining < 1) + hammer.Delete(); + } + + int phys = 0, fire = 0, cold = 0, pois = 0, nrgy = 0; + int dura, luck, lreq, dinc = 0; + int baseChance; + + var physBonus = false; + bool fireBonus; + bool coldBonus; + bool nrgyBonus; + bool poisBonus; + bool duraBonus; + bool luckBonus; + bool lreqBonus; + bool dincBonus; + + if (item is BaseWeapon weapon) + { + if (!CraftResources.IsStandard(weapon.Resource)) + return EnhanceResult.AlreadyEnhanced; + + baseChance = 20; + + dura = weapon.MaxHitPoints; + luck = weapon.Attributes.Luck; + lreq = weapon.WeaponAttributes.LowerStatReq; + dinc = weapon.Attributes.WeaponDamage; + + fireBonus = attributes.WeaponFireDamage > 0; + coldBonus = attributes.WeaponColdDamage > 0; + nrgyBonus = attributes.WeaponEnergyDamage > 0; + poisBonus = attributes.WeaponPoisonDamage > 0; + + duraBonus = attributes.WeaponDurability > 0; + luckBonus = attributes.WeaponLuck > 0; + lreqBonus = attributes.WeaponLowerRequirements > 0; + dincBonus = dinc > 0; + } + else + { + var armor = (BaseArmor)item; + + if (!CraftResources.IsStandard(armor.Resource)) + return EnhanceResult.AlreadyEnhanced; + + baseChance = 20; + + phys = armor.PhysicalResistance; + fire = armor.FireResistance; + cold = armor.ColdResistance; + pois = armor.PoisonResistance; + nrgy = armor.EnergyResistance; + + dura = armor.MaxHitPoints; + luck = armor.Attributes.Luck; + lreq = armor.ArmorAttributes.LowerStatReq; + + physBonus = attributes.ArmorPhysicalResist > 0; + fireBonus = attributes.ArmorFireResist > 0; + coldBonus = attributes.ArmorColdResist > 0; + nrgyBonus = attributes.ArmorEnergyResist > 0; + poisBonus = attributes.ArmorPoisonResist > 0; + + duraBonus = attributes.ArmorDurability > 0; + luckBonus = attributes.ArmorLuck > 0; + lreqBonus = attributes.ArmorLowerRequirements > 0; + dincBonus = false; + } + + var skill = from.Skills[craftSystem.MainSkill].Fixed / 10; + + if (skill >= 100) + baseChance -= (skill - 90) / 10; + + var res = EnhanceResult.Success; + + if (physBonus) + CheckResult(ref res, baseChance + phys); + + if (fireBonus) + CheckResult(ref res, baseChance + fire); + + if (coldBonus) + CheckResult(ref res, baseChance + cold); + + if (nrgyBonus) + CheckResult(ref res, baseChance + nrgy); + + if (poisBonus) + CheckResult(ref res, baseChance + pois); + + if (duraBonus) + CheckResult(ref res, baseChance + dura / 40); + + if (luckBonus) + CheckResult(ref res, baseChance + 10 + luck / 2); + + if (lreqBonus) + CheckResult(ref res, baseChance + lreq / 4); + + if (dincBonus) + CheckResult(ref res, baseChance + dinc / 4); + + switch (res) + { + case EnhanceResult.Broken: + { + if (!craftItem.ConsumeRes( + from, + resType, + craftSystem, + ref resHue, + ref maxAmount, + ConsumeType.Half, + ref resMessage + )) + return EnhanceResult.NoResources; + + item.Delete(); + break; + } + case EnhanceResult.Success: + { + if (!craftItem.ConsumeRes( + from, + resType, + craftSystem, + ref resHue, + ref maxAmount, + ConsumeType.All, + ref resMessage + )) + return EnhanceResult.NoResources; + + if (item is BaseWeapon w) + { + w.Resource = resource; + + var hue = w.GetElementalDamageHue(); + if (hue > 0) + w.Hue = hue; + } + else + { + ((BaseArmor)item).Resource = resource; + } + + break; + } + case EnhanceResult.Failure: + { + if (!craftItem.ConsumeRes( + from, + resType, + craftSystem, + ref resHue, + ref maxAmount, + ConsumeType.Half, + ref resMessage + )) + return EnhanceResult.NoResources; + + break; + } + } + + return res; + } + + public static void CheckResult(ref EnhanceResult res, int chance) + { + if (res != EnhanceResult.Success) + return; // we've already failed.. + + var random = Utility.Random(100); + + if (random < 10) + res = EnhanceResult.Failure; + else if (chance > random) + res = EnhanceResult.Broken; + } + + public static void BeginTarget(Mobile from, CraftSystem craftSystem, BaseTool tool) + { + var context = craftSystem.GetContext(from); + + if (context == null) + return; + + var lastRes = context.LastResourceIndex; + var subRes = craftSystem.CraftSubRes; + + if (lastRes >= 0 && lastRes < subRes.Count) + { + var res = subRes.GetAt(lastRes); + + if (from.Skills[craftSystem.MainSkill].Value < res.RequiredSkill) + { + from.SendGump(new CraftGump(from, craftSystem, tool, res.Message)); + } + else + { + var resource = CraftResources.GetFromType(res.ItemType); + + if (resource != CraftResource.None) + { + from.Target = new InternalTarget(craftSystem, tool, res.ItemType, resource); + from.SendLocalizedMessage( + 1061004 + ); // Target an item to enhance with the properties of your selected material. + } + else + { + from.SendGump( + new CraftGump( + from, + craftSystem, + tool, + 1061010 + ) + ); // You must select a special material in order to enhance an item with its properties. + } + } + } + else + { + from.SendGump( + new CraftGump( + from, + craftSystem, + tool, + 1061010 + ) + ); // You must select a special material in order to enhance an item with its properties. + } + } + + private class InternalTarget : Target + { + private readonly CraftSystem m_CraftSystem; + private readonly CraftResource m_Resource; + private readonly Type m_ResourceType; + private readonly BaseTool m_Tool; + + public InternalTarget(CraftSystem craftSystem, BaseTool tool, Type resourceType, CraftResource resource) : base( + 2, + false, + TargetFlags.None + ) + { + m_CraftSystem = craftSystem; + m_Tool = tool; + m_ResourceType = resourceType; + m_Resource = resource; + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted is Item item) + { + object message = null; + var res = Enhance.Invoke( + from, + m_CraftSystem, + m_Tool, + item, + m_Resource, + m_ResourceType, + ref message + ); + + message = res switch + { + EnhanceResult.NotInBackpack => 1061005, + EnhanceResult.AlreadyEnhanced => 1061012, + EnhanceResult.BadItem => 1061011, + EnhanceResult.BadResource => 1061010, + EnhanceResult.Broken => 1061080, + EnhanceResult.Failure => 1061082, + EnhanceResult.Success => 1061008, + EnhanceResult.NoSkill => 1044153, + _ => message + }; + + from.SendGump(new CraftGump(from, m_CraftSystem, m_Tool, message)); + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Craft/Core/QueryMakersMarkGump.cs b/Projects/UOContent/Engines/Craft/Core/QueryMakersMarkGump.cs index a6b99b856..af36d136d 100644 --- a/Projects/UOContent/Engines/Craft/Core/QueryMakersMarkGump.cs +++ b/Projects/UOContent/Engines/Craft/Core/QueryMakersMarkGump.cs @@ -1,55 +1,57 @@ -using System; -using Server.Gumps; -using Server.Items; -using Server.Network; - -namespace Server.Engines.Craft -{ - public class QueryMakersMarkGump : Gump - { - private readonly CraftItem m_CraftItem; - private readonly CraftSystem m_CraftSystem; - private readonly Mobile m_From; - private readonly int m_Quality; - private readonly BaseTool m_Tool; - private readonly Type m_TypeRes; - - public QueryMakersMarkGump(int quality, Mobile from, CraftItem craftItem, CraftSystem craftSystem, Type typeRes, - BaseTool tool) : base(100, 200) - { - from.CloseGump(); - - m_Quality = quality; - m_From = from; - m_CraftItem = craftItem; - m_CraftSystem = craftSystem; - m_TypeRes = typeRes; - m_Tool = tool; - - AddPage(0); - - AddBackground(0, 0, 220, 170, 5054); - AddBackground(10, 10, 200, 150, 3000); - - AddHtmlLocalized(20, 20, 180, 80, 1018317); // Do you wish to place your maker's mark on this item? - - AddHtmlLocalized(55, 100, 140, 25, 1011011); // CONTINUE - AddButton(20, 100, 4005, 4007, 1); - - AddHtmlLocalized(55, 125, 140, 25, 1011012); // CANCEL - AddButton(20, 125, 4005, 4007, 0); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - bool makersMark = info.ButtonID == 1; - - if (makersMark) - m_From.SendLocalizedMessage(501808); // You mark the item. - else - m_From.SendLocalizedMessage(501809); // Cancelled mark. - - m_CraftItem.CompleteCraft(m_Quality, makersMark, m_From, m_CraftSystem, m_TypeRes, m_Tool, null); - } - } -} +using System; +using Server.Gumps; +using Server.Items; +using Server.Network; + +namespace Server.Engines.Craft +{ + public class QueryMakersMarkGump : Gump + { + private readonly CraftItem m_CraftItem; + private readonly CraftSystem m_CraftSystem; + private readonly Mobile m_From; + private readonly int m_Quality; + private readonly BaseTool m_Tool; + private readonly Type m_TypeRes; + + public QueryMakersMarkGump( + int quality, Mobile from, CraftItem craftItem, CraftSystem craftSystem, Type typeRes, + BaseTool tool + ) : base(100, 200) + { + from.CloseGump(); + + m_Quality = quality; + m_From = from; + m_CraftItem = craftItem; + m_CraftSystem = craftSystem; + m_TypeRes = typeRes; + m_Tool = tool; + + AddPage(0); + + AddBackground(0, 0, 220, 170, 5054); + AddBackground(10, 10, 200, 150, 3000); + + AddHtmlLocalized(20, 20, 180, 80, 1018317); // Do you wish to place your maker's mark on this item? + + AddHtmlLocalized(55, 100, 140, 25, 1011011); // CONTINUE + AddButton(20, 100, 4005, 4007, 1); + + AddHtmlLocalized(55, 125, 140, 25, 1011012); // CANCEL + AddButton(20, 125, 4005, 4007, 0); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var makersMark = info.ButtonID == 1; + + if (makersMark) + m_From.SendLocalizedMessage(501808); // You mark the item. + else + m_From.SendLocalizedMessage(501809); // Cancelled mark. + + m_CraftItem.CompleteCraft(m_Quality, makersMark, m_From, m_CraftSystem, m_TypeRes, m_Tool, null); + } + } +} diff --git a/Projects/UOContent/Engines/Craft/Core/Recipes.cs b/Projects/UOContent/Engines/Craft/Core/Recipes.cs index fe9154f40..93d9c9854 100644 --- a/Projects/UOContent/Engines/Craft/Core/Recipes.cs +++ b/Projects/UOContent/Engines/Craft/Core/Recipes.cs @@ -1,88 +1,99 @@ -using System; -using System.Collections.Generic; -using Server.Mobiles; -using Server.Targeting; - -namespace Server.Engines.Craft -{ - public class Recipe - { - private TextDefinition m_TD; - - public Recipe(int id, CraftSystem system, CraftItem item) - { - ID = id; - CraftSystem = system; - CraftItem = item; - - if (Recipes.ContainsKey(id)) - throw new Exception("Attempting to create recipe with preexisting ID."); - - Recipes.Add(id, this); - LargestRecipeID = Math.Max(id, LargestRecipeID); - } - - public static Dictionary Recipes { get; } = new Dictionary(); - - public static int LargestRecipeID { get; private set; } - - public CraftSystem CraftSystem { get; set; } - - public CraftItem CraftItem { get; set; } - - public int ID { get; } - - public TextDefinition TextDefinition => m_TD ?? (m_TD = new TextDefinition(CraftItem.NameNumber, CraftItem.NameString)); - - public static void Initialize() - { - CommandSystem.Register("LearnAllRecipes", AccessLevel.GameMaster, LearnAllRecipes_OnCommand); - CommandSystem.Register("ForgetAllRecipes", AccessLevel.GameMaster, ForgetAllRecipes_OnCommand); - } - - [Usage("LearnAllRecipes")] - [Description("Teaches a player all available recipes.")] - private static void LearnAllRecipes_OnCommand(CommandEventArgs e) - { - Mobile m = e.Mobile; - m.SendMessage("Target a player to teach them all of the recipes."); - - m.BeginTarget(-1, false, TargetFlags.None, (from, targeted) => - { - if (targeted is PlayerMobile mobile) - { - foreach (KeyValuePair kvp in Recipes) - mobile.AcquireRecipe(kvp.Key); - - from.SendMessage("You teach them all of the recipes."); - } - else - { - from.SendMessage("That is not a player!"); - } - }); - } - - [Usage("ForgetAllRecipes")] - [Description("Makes a player forget all the recipes they've learned.")] - private static void ForgetAllRecipes_OnCommand(CommandEventArgs e) - { - Mobile m = e.Mobile; - m.SendMessage("Target a player to have them forget all of the recipes they've learned."); - - m.BeginTarget(-1, false, TargetFlags.None, (from, targeted) => - { - if (targeted is PlayerMobile mobile) - { - mobile.ResetRecipes(); - - from.SendMessage("They forget all their recipes."); - } - else - { - from.SendMessage("That is not a player!"); - } - }); - } - } -} +using System; +using System.Collections.Generic; +using Server.Mobiles; +using Server.Targeting; + +namespace Server.Engines.Craft +{ + public class Recipe + { + private TextDefinition m_TD; + + public Recipe(int id, CraftSystem system, CraftItem item) + { + ID = id; + CraftSystem = system; + CraftItem = item; + + if (Recipes.ContainsKey(id)) + throw new Exception("Attempting to create recipe with preexisting ID."); + + Recipes.Add(id, this); + LargestRecipeID = Math.Max(id, LargestRecipeID); + } + + public static Dictionary Recipes { get; } = new Dictionary(); + + public static int LargestRecipeID { get; private set; } + + public CraftSystem CraftSystem { get; set; } + + public CraftItem CraftItem { get; set; } + + public int ID { get; } + + public TextDefinition TextDefinition => + m_TD ?? (m_TD = new TextDefinition(CraftItem.NameNumber, CraftItem.NameString)); + + public static void Initialize() + { + CommandSystem.Register("LearnAllRecipes", AccessLevel.GameMaster, LearnAllRecipes_OnCommand); + CommandSystem.Register("ForgetAllRecipes", AccessLevel.GameMaster, ForgetAllRecipes_OnCommand); + } + + [Usage("LearnAllRecipes")] + [Description("Teaches a player all available recipes.")] + private static void LearnAllRecipes_OnCommand(CommandEventArgs e) + { + var m = e.Mobile; + m.SendMessage("Target a player to teach them all of the recipes."); + + m.BeginTarget( + -1, + false, + TargetFlags.None, + (from, targeted) => + { + if (targeted is PlayerMobile mobile) + { + foreach (var kvp in Recipes) + mobile.AcquireRecipe(kvp.Key); + + from.SendMessage("You teach them all of the recipes."); + } + else + { + from.SendMessage("That is not a player!"); + } + } + ); + } + + [Usage("ForgetAllRecipes")] + [Description("Makes a player forget all the recipes they've learned.")] + private static void ForgetAllRecipes_OnCommand(CommandEventArgs e) + { + var m = e.Mobile; + m.SendMessage("Target a player to have them forget all of the recipes they've learned."); + + m.BeginTarget( + -1, + false, + TargetFlags.None, + (from, targeted) => + { + if (targeted is PlayerMobile mobile) + { + mobile.ResetRecipes(); + + from.SendMessage("They forget all their recipes."); + } + else + { + from.SendMessage("That is not a player!"); + } + } + ); + } + } +} diff --git a/Projects/UOContent/Engines/Craft/Core/Repair.cs b/Projects/UOContent/Engines/Craft/Core/Repair.cs index 31cbf521a..0a01ed422 100644 --- a/Projects/UOContent/Engines/Craft/Core/Repair.cs +++ b/Projects/UOContent/Engines/Craft/Core/Repair.cs @@ -1,490 +1,492 @@ -using System; -using Server.Items; -using Server.Mobiles; -using Server.Targeting; - -namespace Server.Engines.Craft -{ - public class Repair - { - public static void Do(Mobile from, CraftSystem craftSystem, BaseTool tool) - { - from.Target = new InternalTarget(craftSystem, tool); - from.SendLocalizedMessage(1044276); // Target an item to repair. - } - - public static void Do(Mobile from, CraftSystem craftSystem, RepairDeed deed) - { - from.Target = new InternalTarget(craftSystem, deed); - from.SendLocalizedMessage(1044276); // Target an item to repair. - } - - private class InternalTarget : Target - { - private readonly CraftSystem m_CraftSystem; - private readonly RepairDeed m_Deed; - private readonly BaseTool m_Tool; - - public InternalTarget(CraftSystem craftSystem, BaseTool tool) : base(2, false, TargetFlags.None) - { - m_CraftSystem = craftSystem; - m_Tool = tool; - } - - public InternalTarget(CraftSystem craftSystem, RepairDeed deed) : base(2, false, TargetFlags.None) - { - m_CraftSystem = craftSystem; - m_Deed = deed; - } - - private int GetWeakenChance(Mobile mob, SkillName skill, int curHits, int maxHits) => 40 + (maxHits - curHits) - (int)((m_Deed?.SkillLevel ?? mob.Skills[skill].Value) / 10); - - private bool CheckWeaken(Mobile mob, SkillName skill, int curHits, int maxHits) => GetWeakenChance(mob, skill, curHits, maxHits) > Utility.Random(100); - - private int GetRepairDifficulty(int curHits, int maxHits) => (maxHits - curHits) * 1250 / Math.Max(maxHits, 1) - 250; - - private bool CheckRepairDifficulty(Mobile mob, SkillName skill, int curHits, int maxHits) - { - double difficulty = GetRepairDifficulty(curHits, maxHits) * 0.1; - - if (m_Deed != null) - { - double value = m_Deed.SkillLevel; - double minSkill = difficulty - 25.0; - double maxSkill = difficulty + 25; - - if (value < minSkill) - return false; // Too difficult - if (value >= maxSkill) - return true; // No challenge - - double chance = (value - minSkill) / (maxSkill - minSkill); - - return chance >= Utility.RandomDouble(); - } - - return mob.CheckSkill(skill, difficulty - 25.0, difficulty + 25.0); - } - - private bool CheckDeed(Mobile from) - { - if (m_Deed != null) return m_Deed.Check(from); - - return true; - } - - private bool IsSpecialClothing(BaseClothing clothing) - { - // Clothing repairable but not craftable - - if (m_CraftSystem is DefTailoring) - return clothing is BearMask - || clothing is DeerMask - || clothing is TheMostKnowledgePerson - || clothing is TheRobeOfBritanniaAri - || clothing is EmbroideredOakLeafCloak; - - return false; - } - - private bool IsSpecialWeapon(BaseWeapon weapon) - { - // Weapons repairable but not craftable - - if (m_CraftSystem is DefTinkering) - return weapon is Cleaver - || weapon is Hatchet - || weapon is Pickaxe - || weapon is ButcherKnife - || weapon is SkinningKnife; - - if (m_CraftSystem is DefCarpentry) - { - return weapon is Club - || weapon is BlackStaff - || weapon is MagicWand - - // TODO: Make these items craftable - || weapon is WildStaff; - } - - if (m_CraftSystem is DefBlacksmithy) - { - return weapon is Pitchfork - - // TODO: Make these items craftable - || weapon is RadiantScimitar - || weapon is WarCleaver - || weapon is ElvenSpellblade - || weapon is AssassinSpike - || weapon is Leafblade - || weapon is RuneBlade - || weapon is ElvenMachete - || weapon is OrnateAxe - || weapon is DiamondMace; - } - - // TODO: Make these items craftable - if (m_CraftSystem is DefBowFletching) - return weapon is ElvenCompositeLongbow - || weapon is MagicalShortbow; - - return false; - } - - private bool IsSpecialArmor(BaseArmor armor) - { - // Armor repairable but not craftable - - // TODO: Make these items craftable - if (m_CraftSystem is DefTailoring) - return armor is LeafTonlet - || armor is LeafArms - || armor is LeafChest - || armor is LeafGloves - || armor is LeafGorget - || armor is LeafLegs - || armor is HideChest - || armor is HideGloves - || armor is HideGorget - || armor is HidePants - || armor is HidePauldrons; - - if (m_CraftSystem is DefCarpentry) - return armor is WingedHelm - || armor is RavenHelm - || armor is VultureHelm - || armor is WoodlandArms - || armor is WoodlandChest - || armor is WoodlandGloves - || armor is WoodlandGorget - || armor is WoodlandLegs; - if (m_CraftSystem is DefBlacksmithy) - return armor is Circlet - || armor is RoyalCirclet - || armor is GemmedCirclet; - - return false; - } - - protected override void OnTarget(Mobile from, object targeted) - { - int number; - - if (!CheckDeed(from)) - return; - - bool usingDeed = m_Deed != null; - bool toDelete = false; - - // TODO: Make an IRepairable - - if (m_CraftSystem.CanCraft(from, m_Tool, targeted.GetType()) == 1044267) - { - number = 1044282; // You must be near a forge and and anvil to repair items. * Yes, there are two and's * - } - else if (m_CraftSystem is DefTinkering && targeted is Golem g) - { - int damage = g.HitsMax - g.Hits; - - if (g.IsDeadBondedPet) - { - number = 500426; // You can't repair that. - } - else if (damage <= 0) - { - number = 500423; // That is already in full repair. - } - else - { - double skillValue = usingDeed ? m_Deed.SkillLevel : from.Skills.Tinkering.Value; - - if (skillValue < 60.0) - { - number = - 1044153; // You don't have the required skills to attempt this item. //TODO: How does OSI handle this with deeds with golems? - } - else if (!from.CanBeginAction()) - { - number = 501789; // You must wait before trying again. - } - else - { - if (damage > (int)(skillValue * 0.3)) - damage = (int)(skillValue * 0.3); - - damage += 30; - - if (!from.CheckSkill(SkillName.Tinkering, 0.0, 100.0)) - damage /= 2; - - Container pack = from.Backpack; - - if (pack != null) - { - int v = pack.ConsumeUpTo(typeof(IronIngot), (damage + 4) / 5); - - if (v > 0) - { - g.Hits += v * 5; - - number = 1044279; // You repair the item. - toDelete = true; - - from.BeginAction(); - Timer.DelayCall(TimeSpan.FromSeconds(12.0), from.EndAction); - } - else - { - number = 1044037; // You do not have sufficient metal to make that. - } - } - else - { - number = 1044037; // You do not have sufficient metal to make that. - } - } - } - } - else if (targeted is BaseWeapon weapon) - { - SkillName skill = m_CraftSystem.MainSkill; - int toWeaken = 0; - - if (Core.AOS) - { - toWeaken = 1; - } - else if (skill != SkillName.Tailoring) - { - double skillLevel = usingDeed ? m_Deed.SkillLevel : from.Skills[skill].Base; - - if (skillLevel >= 90.0) - toWeaken = 1; - else if (skillLevel >= 70.0) - toWeaken = 2; - else - toWeaken = 3; - } - - if (m_CraftSystem.CraftItems.SearchForSubclass(weapon.GetType()) == null && !IsSpecialWeapon(weapon)) - { - number = usingDeed - ? 1061136 - : 1044277; // That item cannot be repaired. // You cannot repair that item with this type of repair contract. - } - else if (!weapon.IsChildOf(from.Backpack) && (!Core.ML || weapon.Parent != from)) - { - number = 1044275; // The item must be in your backpack to repair it. - } - else if (!Core.AOS && weapon.PoisonCharges != 0) - { - number = 1005012; // You cannot repair an item while a caustic substance is on it. - } - else if (weapon.MaxHitPoints <= 0 || weapon.HitPoints == weapon.MaxHitPoints) - { - number = 1044281; // That item is in full repair - } - else if (weapon.MaxHitPoints <= toWeaken) - { - number = 1044278; // That item has been repaired many times, and will break if repairs are attempted again. - } - else - { - if (CheckWeaken(from, skill, weapon.HitPoints, weapon.MaxHitPoints)) - { - weapon.MaxHitPoints -= toWeaken; - weapon.HitPoints = Math.Max(0, weapon.HitPoints - toWeaken); - } - - if (CheckRepairDifficulty(from, skill, weapon.HitPoints, weapon.MaxHitPoints)) - { - number = 1044279; // You repair the item. - m_CraftSystem.PlayCraftEffect(from); - weapon.HitPoints = weapon.MaxHitPoints; - } - else - { - number = usingDeed - ? 1061137 - : 1044280; // You fail to repair the item. [And the contract is destroyed] - m_CraftSystem.PlayCraftEffect(from); - } - - toDelete = true; - } - } - else if (targeted is BaseArmor armor) - { - SkillName skill = m_CraftSystem.MainSkill; - int toWeaken = 0; - - if (Core.AOS) - { - toWeaken = 1; - } - else if (skill != SkillName.Tailoring) - { - double skillLevel = usingDeed ? m_Deed.SkillLevel : from.Skills[skill].Base; - - if (skillLevel >= 90.0) - toWeaken = 1; - else if (skillLevel >= 70.0) - toWeaken = 2; - else - toWeaken = 3; - } - - if (m_CraftSystem.CraftItems.SearchForSubclass(armor.GetType()) == null && !IsSpecialArmor(armor)) - { - number = usingDeed - ? 1061136 - : 1044277; // That item cannot be repaired. // You cannot repair that item with this type of repair contract. - } - else if (!armor.IsChildOf(from.Backpack) && (!Core.ML || armor.Parent != from)) - { - number = 1044275; // The item must be in your backpack to repair it. - } - else if (armor.MaxHitPoints <= 0 || armor.HitPoints == armor.MaxHitPoints) - { - number = 1044281; // That item is in full repair - } - else if (armor.MaxHitPoints <= toWeaken) - { - number = 1044278; // That item has been repaired many times, and will break if repairs are attempted again. - } - else - { - if (CheckWeaken(from, skill, armor.HitPoints, armor.MaxHitPoints)) - { - armor.MaxHitPoints -= toWeaken; - armor.HitPoints = Math.Max(0, armor.HitPoints - toWeaken); - } - - if (CheckRepairDifficulty(from, skill, armor.HitPoints, armor.MaxHitPoints)) - { - number = 1044279; // You repair the item. - m_CraftSystem.PlayCraftEffect(from); - armor.HitPoints = armor.MaxHitPoints; - } - else - { - number = usingDeed - ? 1061137 - : 1044280; // You fail to repair the item. [And the contract is destroyed] - m_CraftSystem.PlayCraftEffect(from); - } - - toDelete = true; - } - } - else if (targeted is BaseClothing clothing) - { - SkillName skill = m_CraftSystem.MainSkill; - int toWeaken = 0; - - if (Core.AOS) - { - toWeaken = 1; - } - else if (skill != SkillName.Tailoring) - { - double skillLevel = usingDeed ? m_Deed.SkillLevel : from.Skills[skill].Base; - - if (skillLevel >= 90.0) - toWeaken = 1; - else if (skillLevel >= 70.0) - toWeaken = 2; - else - toWeaken = 3; - } - - if (m_CraftSystem.CraftItems.SearchForSubclass(clothing.GetType()) == null && - !IsSpecialClothing(clothing) && !(clothing is TribalMask || clothing is HornedTribalMask)) - { - number = usingDeed - ? 1061136 - : 1044277; // That item cannot be repaired. // You cannot repair that item with this type of repair contract. - } - else if (!clothing.IsChildOf(from.Backpack) && (!Core.ML || clothing.Parent != from)) - { - number = 1044275; // The item must be in your backpack to repair it. - } - else if (clothing.MaxHitPoints <= 0 || clothing.HitPoints == clothing.MaxHitPoints) - { - number = 1044281; // That item is in full repair - } - else if (clothing.MaxHitPoints <= toWeaken) - { - number = 1044278; // That item has been repaired many times, and will break if repairs are attempted again. - } - else - { - if (CheckWeaken(from, skill, clothing.HitPoints, clothing.MaxHitPoints)) - { - clothing.MaxHitPoints -= toWeaken; - clothing.HitPoints = Math.Max(0, clothing.HitPoints - toWeaken); - } - - if (CheckRepairDifficulty(from, skill, clothing.HitPoints, clothing.MaxHitPoints)) - { - number = 1044279; // You repair the item. - m_CraftSystem.PlayCraftEffect(from); - clothing.HitPoints = clothing.MaxHitPoints; - } - else - { - number = usingDeed - ? 1061137 - : 1044280; // You fail to repair the item. [And the contract is destroyed] - m_CraftSystem.PlayCraftEffect(from); - } - - toDelete = true; - } - } - else if (!usingDeed && targeted is BlankScroll scroll) - { - SkillName skill = m_CraftSystem.MainSkill; - - if (from.Skills[skill].Value >= 50.0) - { - scroll.Consume(1); - RepairDeed deed = new RepairDeed(RepairDeed.GetTypeFor(m_CraftSystem), from.Skills[skill].Value, - from); - from.AddToBackpack(deed); - - number = 500442; // You create the item and put it in your backpack. - } - else - { - number = 1047005; // You must be at least apprentice level to create a repair service contract. - } - } - else if (targeted is Item) - { - number = usingDeed - ? 1061136 - : 1044277; // That item cannot be repaired. // You cannot repair that item with this type of repair contract. - } - else - { - number = 500426; // You can't repair that. - } - - if (!usingDeed) - { - CraftContext context = m_CraftSystem.GetContext(from); - from.SendGump(new CraftGump(from, m_CraftSystem, m_Tool, number)); - } - else - { - from.SendLocalizedMessage(number); - - if (toDelete) - m_Deed.Delete(); - } - } - } - } -} \ No newline at end of file +using System; +using Server.Items; +using Server.Mobiles; +using Server.Targeting; + +namespace Server.Engines.Craft +{ + public class Repair + { + public static void Do(Mobile from, CraftSystem craftSystem, BaseTool tool) + { + from.Target = new InternalTarget(craftSystem, tool); + from.SendLocalizedMessage(1044276); // Target an item to repair. + } + + public static void Do(Mobile from, CraftSystem craftSystem, RepairDeed deed) + { + from.Target = new InternalTarget(craftSystem, deed); + from.SendLocalizedMessage(1044276); // Target an item to repair. + } + + private class InternalTarget : Target + { + private readonly CraftSystem m_CraftSystem; + private readonly RepairDeed m_Deed; + private readonly BaseTool m_Tool; + + public InternalTarget(CraftSystem craftSystem, BaseTool tool) : base(2, false, TargetFlags.None) + { + m_CraftSystem = craftSystem; + m_Tool = tool; + } + + public InternalTarget(CraftSystem craftSystem, RepairDeed deed) : base(2, false, TargetFlags.None) + { + m_CraftSystem = craftSystem; + m_Deed = deed; + } + + private int GetWeakenChance(Mobile mob, SkillName skill, int curHits, int maxHits) => 40 + (maxHits - curHits) - + (int)((m_Deed?.SkillLevel ?? mob.Skills[skill].Value) / 10); + + private bool CheckWeaken(Mobile mob, SkillName skill, int curHits, int maxHits) => + GetWeakenChance(mob, skill, curHits, maxHits) > Utility.Random(100); + + private int GetRepairDifficulty(int curHits, int maxHits) => + (maxHits - curHits) * 1250 / Math.Max(maxHits, 1) - 250; + + private bool CheckRepairDifficulty(Mobile mob, SkillName skill, int curHits, int maxHits) + { + var difficulty = GetRepairDifficulty(curHits, maxHits) * 0.1; + + if (m_Deed != null) + { + var value = m_Deed.SkillLevel; + var minSkill = difficulty - 25.0; + var maxSkill = difficulty + 25; + + if (value < minSkill) + return false; // Too difficult + if (value >= maxSkill) + return true; // No challenge + + var chance = (value - minSkill) / (maxSkill - minSkill); + + return chance >= Utility.RandomDouble(); + } + + return mob.CheckSkill(skill, difficulty - 25.0, difficulty + 25.0); + } + + private bool CheckDeed(Mobile from) + { + if (m_Deed != null) return m_Deed.Check(from); + + return true; + } + + private bool IsSpecialClothing(BaseClothing clothing) + { + // Clothing repairable but not craftable + + if (m_CraftSystem is DefTailoring) + return clothing is BearMask + || clothing is DeerMask + || clothing is TheMostKnowledgePerson + || clothing is TheRobeOfBritanniaAri + || clothing is EmbroideredOakLeafCloak; + + return false; + } + + private bool IsSpecialWeapon(BaseWeapon weapon) + { + // Weapons repairable but not craftable + + if (m_CraftSystem is DefTinkering) + return weapon is Cleaver + || weapon is Hatchet + || weapon is Pickaxe + || weapon is ButcherKnife + || weapon is SkinningKnife; + + if (m_CraftSystem is DefCarpentry) + return weapon is Club + || weapon is BlackStaff + || weapon is MagicWand + + // TODO: Make these items craftable + || weapon is WildStaff; + + if (m_CraftSystem is DefBlacksmithy) + return weapon is Pitchfork + + // TODO: Make these items craftable + || weapon is RadiantScimitar + || weapon is WarCleaver + || weapon is ElvenSpellblade + || weapon is AssassinSpike + || weapon is Leafblade + || weapon is RuneBlade + || weapon is ElvenMachete + || weapon is OrnateAxe + || weapon is DiamondMace; + + // TODO: Make these items craftable + if (m_CraftSystem is DefBowFletching) + return weapon is ElvenCompositeLongbow + || weapon is MagicalShortbow; + + return false; + } + + private bool IsSpecialArmor(BaseArmor armor) + { + // Armor repairable but not craftable + + // TODO: Make these items craftable + if (m_CraftSystem is DefTailoring) + return armor is LeafTonlet + || armor is LeafArms + || armor is LeafChest + || armor is LeafGloves + || armor is LeafGorget + || armor is LeafLegs + || armor is HideChest + || armor is HideGloves + || armor is HideGorget + || armor is HidePants + || armor is HidePauldrons; + + if (m_CraftSystem is DefCarpentry) + return armor is WingedHelm + || armor is RavenHelm + || armor is VultureHelm + || armor is WoodlandArms + || armor is WoodlandChest + || armor is WoodlandGloves + || armor is WoodlandGorget + || armor is WoodlandLegs; + if (m_CraftSystem is DefBlacksmithy) + return armor is Circlet + || armor is RoyalCirclet + || armor is GemmedCirclet; + + return false; + } + + protected override void OnTarget(Mobile from, object targeted) + { + int number; + + if (!CheckDeed(from)) + return; + + var usingDeed = m_Deed != null; + var toDelete = false; + + // TODO: Make an IRepairable + + if (m_CraftSystem.CanCraft(from, m_Tool, targeted.GetType()) == 1044267) + { + number = 1044282; // You must be near a forge and and anvil to repair items. * Yes, there are two and's * + } + else if (m_CraftSystem is DefTinkering && targeted is Golem g) + { + var damage = g.HitsMax - g.Hits; + + if (g.IsDeadBondedPet) + { + number = 500426; // You can't repair that. + } + else if (damage <= 0) + { + number = 500423; // That is already in full repair. + } + else + { + var skillValue = usingDeed ? m_Deed.SkillLevel : from.Skills.Tinkering.Value; + + if (skillValue < 60.0) + { + number = + 1044153; // You don't have the required skills to attempt this item. //TODO: How does OSI handle this with deeds with golems? + } + else if (!from.CanBeginAction()) + { + number = 501789; // You must wait before trying again. + } + else + { + if (damage > (int)(skillValue * 0.3)) + damage = (int)(skillValue * 0.3); + + damage += 30; + + if (!from.CheckSkill(SkillName.Tinkering, 0.0, 100.0)) + damage /= 2; + + var pack = from.Backpack; + + if (pack != null) + { + var v = pack.ConsumeUpTo(typeof(IronIngot), (damage + 4) / 5); + + if (v > 0) + { + g.Hits += v * 5; + + number = 1044279; // You repair the item. + toDelete = true; + + from.BeginAction(); + Timer.DelayCall(TimeSpan.FromSeconds(12.0), from.EndAction); + } + else + { + number = 1044037; // You do not have sufficient metal to make that. + } + } + else + { + number = 1044037; // You do not have sufficient metal to make that. + } + } + } + } + else if (targeted is BaseWeapon weapon) + { + var skill = m_CraftSystem.MainSkill; + var toWeaken = 0; + + if (Core.AOS) + { + toWeaken = 1; + } + else if (skill != SkillName.Tailoring) + { + var skillLevel = usingDeed ? m_Deed.SkillLevel : from.Skills[skill].Base; + + if (skillLevel >= 90.0) + toWeaken = 1; + else if (skillLevel >= 70.0) + toWeaken = 2; + else + toWeaken = 3; + } + + if (m_CraftSystem.CraftItems.SearchForSubclass(weapon.GetType()) == null && !IsSpecialWeapon(weapon)) + { + number = usingDeed + ? 1061136 + : 1044277; // That item cannot be repaired. // You cannot repair that item with this type of repair contract. + } + else if (!weapon.IsChildOf(from.Backpack) && (!Core.ML || weapon.Parent != from)) + { + number = 1044275; // The item must be in your backpack to repair it. + } + else if (!Core.AOS && weapon.PoisonCharges != 0) + { + number = 1005012; // You cannot repair an item while a caustic substance is on it. + } + else if (weapon.MaxHitPoints <= 0 || weapon.HitPoints == weapon.MaxHitPoints) + { + number = 1044281; // That item is in full repair + } + else if (weapon.MaxHitPoints <= toWeaken) + { + number = 1044278; // That item has been repaired many times, and will break if repairs are attempted again. + } + else + { + if (CheckWeaken(from, skill, weapon.HitPoints, weapon.MaxHitPoints)) + { + weapon.MaxHitPoints -= toWeaken; + weapon.HitPoints = Math.Max(0, weapon.HitPoints - toWeaken); + } + + if (CheckRepairDifficulty(from, skill, weapon.HitPoints, weapon.MaxHitPoints)) + { + number = 1044279; // You repair the item. + m_CraftSystem.PlayCraftEffect(from); + weapon.HitPoints = weapon.MaxHitPoints; + } + else + { + number = usingDeed + ? 1061137 + : 1044280; // You fail to repair the item. [And the contract is destroyed] + m_CraftSystem.PlayCraftEffect(from); + } + + toDelete = true; + } + } + else if (targeted is BaseArmor armor) + { + var skill = m_CraftSystem.MainSkill; + var toWeaken = 0; + + if (Core.AOS) + { + toWeaken = 1; + } + else if (skill != SkillName.Tailoring) + { + var skillLevel = usingDeed ? m_Deed.SkillLevel : from.Skills[skill].Base; + + if (skillLevel >= 90.0) + toWeaken = 1; + else if (skillLevel >= 70.0) + toWeaken = 2; + else + toWeaken = 3; + } + + if (m_CraftSystem.CraftItems.SearchForSubclass(armor.GetType()) == null && !IsSpecialArmor(armor)) + { + number = usingDeed + ? 1061136 + : 1044277; // That item cannot be repaired. // You cannot repair that item with this type of repair contract. + } + else if (!armor.IsChildOf(from.Backpack) && (!Core.ML || armor.Parent != from)) + { + number = 1044275; // The item must be in your backpack to repair it. + } + else if (armor.MaxHitPoints <= 0 || armor.HitPoints == armor.MaxHitPoints) + { + number = 1044281; // That item is in full repair + } + else if (armor.MaxHitPoints <= toWeaken) + { + number = 1044278; // That item has been repaired many times, and will break if repairs are attempted again. + } + else + { + if (CheckWeaken(from, skill, armor.HitPoints, armor.MaxHitPoints)) + { + armor.MaxHitPoints -= toWeaken; + armor.HitPoints = Math.Max(0, armor.HitPoints - toWeaken); + } + + if (CheckRepairDifficulty(from, skill, armor.HitPoints, armor.MaxHitPoints)) + { + number = 1044279; // You repair the item. + m_CraftSystem.PlayCraftEffect(from); + armor.HitPoints = armor.MaxHitPoints; + } + else + { + number = usingDeed + ? 1061137 + : 1044280; // You fail to repair the item. [And the contract is destroyed] + m_CraftSystem.PlayCraftEffect(from); + } + + toDelete = true; + } + } + else if (targeted is BaseClothing clothing) + { + var skill = m_CraftSystem.MainSkill; + var toWeaken = 0; + + if (Core.AOS) + { + toWeaken = 1; + } + else if (skill != SkillName.Tailoring) + { + var skillLevel = usingDeed ? m_Deed.SkillLevel : from.Skills[skill].Base; + + if (skillLevel >= 90.0) + toWeaken = 1; + else if (skillLevel >= 70.0) + toWeaken = 2; + else + toWeaken = 3; + } + + if (m_CraftSystem.CraftItems.SearchForSubclass(clothing.GetType()) == null && + !IsSpecialClothing(clothing) && !(clothing is TribalMask || clothing is HornedTribalMask)) + { + number = usingDeed + ? 1061136 + : 1044277; // That item cannot be repaired. // You cannot repair that item with this type of repair contract. + } + else if (!clothing.IsChildOf(from.Backpack) && (!Core.ML || clothing.Parent != from)) + { + number = 1044275; // The item must be in your backpack to repair it. + } + else if (clothing.MaxHitPoints <= 0 || clothing.HitPoints == clothing.MaxHitPoints) + { + number = 1044281; // That item is in full repair + } + else if (clothing.MaxHitPoints <= toWeaken) + { + number = 1044278; // That item has been repaired many times, and will break if repairs are attempted again. + } + else + { + if (CheckWeaken(from, skill, clothing.HitPoints, clothing.MaxHitPoints)) + { + clothing.MaxHitPoints -= toWeaken; + clothing.HitPoints = Math.Max(0, clothing.HitPoints - toWeaken); + } + + if (CheckRepairDifficulty(from, skill, clothing.HitPoints, clothing.MaxHitPoints)) + { + number = 1044279; // You repair the item. + m_CraftSystem.PlayCraftEffect(from); + clothing.HitPoints = clothing.MaxHitPoints; + } + else + { + number = usingDeed + ? 1061137 + : 1044280; // You fail to repair the item. [And the contract is destroyed] + m_CraftSystem.PlayCraftEffect(from); + } + + toDelete = true; + } + } + else if (!usingDeed && targeted is BlankScroll scroll) + { + var skill = m_CraftSystem.MainSkill; + + if (from.Skills[skill].Value >= 50.0) + { + scroll.Consume(1); + var deed = new RepairDeed( + RepairDeed.GetTypeFor(m_CraftSystem), + from.Skills[skill].Value, + from + ); + from.AddToBackpack(deed); + + number = 500442; // You create the item and put it in your backpack. + } + else + { + number = 1047005; // You must be at least apprentice level to create a repair service contract. + } + } + else if (targeted is Item) + { + number = usingDeed + ? 1061136 + : 1044277; // That item cannot be repaired. // You cannot repair that item with this type of repair contract. + } + else + { + number = 500426; // You can't repair that. + } + + if (!usingDeed) + { + var context = m_CraftSystem.GetContext(from); + from.SendGump(new CraftGump(from, m_CraftSystem, m_Tool, number)); + } + else + { + from.SendLocalizedMessage(number); + + if (toDelete) + m_Deed.Delete(); + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Craft/Core/Resmelt.cs b/Projects/UOContent/Engines/Craft/Core/Resmelt.cs index 9c88bb60c..dde4b3703 100644 --- a/Projects/UOContent/Engines/Craft/Core/Resmelt.cs +++ b/Projects/UOContent/Engines/Craft/Core/Resmelt.cs @@ -1,162 +1,161 @@ -using System; -using Server.Ethics; -using Server.Items; -using Server.Targeting; -using Server.Utilities; - -namespace Server.Engines.Craft -{ - public enum SmeltResult - { - Success, - Invalid, - NoSkill - } - - public static class Resmelt - { - public static void Do(Mobile from, CraftSystem craftSystem, BaseTool tool) - { - int num = craftSystem.CanCraft(from, tool, null); - - if (num > 0 && num != 1044267) - { - from.SendGump(new CraftGump(from, craftSystem, tool, num)); - } - else - { - from.Target = new InternalTarget(craftSystem, tool); - from.SendLocalizedMessage(1044273); // Target an item to recycle. - } - } - - private class InternalTarget : Target - { - private readonly CraftSystem m_CraftSystem; - private readonly BaseTool m_Tool; - - public InternalTarget(CraftSystem craftSystem, BaseTool tool) : base(2, false, TargetFlags.None) - { - m_CraftSystem = craftSystem; - m_Tool = tool; - } - - private SmeltResult Resmelt(Mobile from, Item item, CraftResource resource) - { - try - { - if (Ethic.IsImbued(item)) - return SmeltResult.Invalid; - - if (CraftResources.GetType(resource) != CraftResourceType.Metal) - return SmeltResult.Invalid; - - CraftResourceInfo info = CraftResources.GetInfo(resource); - - if (info == null || info.ResourceTypes.Length == 0) - return SmeltResult.Invalid; - - CraftItem craftItem = m_CraftSystem.CraftItems.SearchFor(item.GetType()); - - if (craftItem == null || craftItem.Resources.Count == 0) - return SmeltResult.Invalid; - - CraftRes craftResource = craftItem.Resources[0]; - - if (craftResource.Amount < 2) - return SmeltResult.Invalid; // Not enough metal to resmelt - - var difficulty = resource switch - { - CraftResource.DullCopper => 65.0, - CraftResource.ShadowIron => 70.0, - CraftResource.Copper => 75.0, - CraftResource.Bronze => 80.0, - CraftResource.Gold => 85.0, - CraftResource.Agapite => 90.0, - CraftResource.Verite => 95.0, - CraftResource.Valorite => 99.0, - _ => 0.0 - }; - - if (difficulty > from.Skills.Mining.Value) - return SmeltResult.NoSkill; - - Type resourceType = info.ResourceTypes[0]; - Item ingot = (Item)ActivatorUtil.CreateInstance(resourceType); - - if (item is DragonBardingDeed || item is BaseArmor armor && armor.PlayerConstructed || - item is BaseWeapon weapon && weapon.PlayerConstructed || - item is BaseClothing clothing && clothing.PlayerConstructed) - ingot.Amount = craftResource.Amount / 2; - else - ingot.Amount = 1; - - item.Delete(); - from.AddToBackpack(ingot); - - from.PlaySound(0x2A); - from.PlaySound(0x240); - return SmeltResult.Success; - } - catch - { - // ignored - } - - return SmeltResult.Invalid; - } - - protected override void OnTarget(Mobile from, object targeted) - { - int num = m_CraftSystem.CanCraft(from, m_Tool, null); - - if (num > 0) - { - if (num == 1044267) - { - DefBlacksmithy.CheckAnvilAndForge(from, 2, out bool anvil, out bool forge); - - if (!anvil) - num = 1044266; // You must be near an anvil - else if (!forge) - num = 1044265; // You must be near a forge. - } - - from.SendGump(new CraftGump(from, m_CraftSystem, m_Tool, num)); - } - else - { - SmeltResult result = SmeltResult.Invalid; - bool isStoreBought = false; - int message; - - if (targeted is BaseArmor armor) - { - result = Resmelt(from, armor, armor.Resource); - isStoreBought = !armor.PlayerConstructed; - } - else if (targeted is BaseWeapon weapon) - { - result = Resmelt(from, weapon, weapon.Resource); - isStoreBought = !weapon.PlayerConstructed; - } - else if (targeted is DragonBardingDeed deed) - { - result = Resmelt(from, deed, deed.Resource); - } - - message = result switch - { - SmeltResult.Invalid => 1044272, - SmeltResult.NoSkill => 1044269, - SmeltResult.Success => isStoreBought ? 500418 : 1044270, - _ => 1044272 - }; - - from.SendGump(new CraftGump(from, m_CraftSystem, m_Tool, message)); - } - } - } - } -} +using Server.Ethics; +using Server.Items; +using Server.Targeting; +using Server.Utilities; + +namespace Server.Engines.Craft +{ + public enum SmeltResult + { + Success, + Invalid, + NoSkill + } + + public static class Resmelt + { + public static void Do(Mobile from, CraftSystem craftSystem, BaseTool tool) + { + var num = craftSystem.CanCraft(from, tool, null); + + if (num > 0 && num != 1044267) + { + from.SendGump(new CraftGump(from, craftSystem, tool, num)); + } + else + { + from.Target = new InternalTarget(craftSystem, tool); + from.SendLocalizedMessage(1044273); // Target an item to recycle. + } + } + + private class InternalTarget : Target + { + private readonly CraftSystem m_CraftSystem; + private readonly BaseTool m_Tool; + + public InternalTarget(CraftSystem craftSystem, BaseTool tool) : base(2, false, TargetFlags.None) + { + m_CraftSystem = craftSystem; + m_Tool = tool; + } + + private SmeltResult Resmelt(Mobile from, Item item, CraftResource resource) + { + try + { + if (Ethic.IsImbued(item)) + return SmeltResult.Invalid; + + if (CraftResources.GetType(resource) != CraftResourceType.Metal) + return SmeltResult.Invalid; + + var info = CraftResources.GetInfo(resource); + + if (info == null || info.ResourceTypes.Length == 0) + return SmeltResult.Invalid; + + var craftItem = m_CraftSystem.CraftItems.SearchFor(item.GetType()); + + if (craftItem == null || craftItem.Resources.Count == 0) + return SmeltResult.Invalid; + + var craftResource = craftItem.Resources[0]; + + if (craftResource.Amount < 2) + return SmeltResult.Invalid; // Not enough metal to resmelt + + var difficulty = resource switch + { + CraftResource.DullCopper => 65.0, + CraftResource.ShadowIron => 70.0, + CraftResource.Copper => 75.0, + CraftResource.Bronze => 80.0, + CraftResource.Gold => 85.0, + CraftResource.Agapite => 90.0, + CraftResource.Verite => 95.0, + CraftResource.Valorite => 99.0, + _ => 0.0 + }; + + if (difficulty > from.Skills.Mining.Value) + return SmeltResult.NoSkill; + + var resourceType = info.ResourceTypes[0]; + var ingot = (Item)ActivatorUtil.CreateInstance(resourceType); + + if (item is DragonBardingDeed || item is BaseArmor armor && armor.PlayerConstructed || + item is BaseWeapon weapon && weapon.PlayerConstructed || + item is BaseClothing clothing && clothing.PlayerConstructed) + ingot.Amount = craftResource.Amount / 2; + else + ingot.Amount = 1; + + item.Delete(); + from.AddToBackpack(ingot); + + from.PlaySound(0x2A); + from.PlaySound(0x240); + return SmeltResult.Success; + } + catch + { + // ignored + } + + return SmeltResult.Invalid; + } + + protected override void OnTarget(Mobile from, object targeted) + { + var num = m_CraftSystem.CanCraft(from, m_Tool, null); + + if (num > 0) + { + if (num == 1044267) + { + DefBlacksmithy.CheckAnvilAndForge(from, 2, out var anvil, out var forge); + + if (!anvil) + num = 1044266; // You must be near an anvil + else if (!forge) + num = 1044265; // You must be near a forge. + } + + from.SendGump(new CraftGump(from, m_CraftSystem, m_Tool, num)); + } + else + { + var result = SmeltResult.Invalid; + var isStoreBought = false; + int message; + + if (targeted is BaseArmor armor) + { + result = Resmelt(from, armor, armor.Resource); + isStoreBought = !armor.PlayerConstructed; + } + else if (targeted is BaseWeapon weapon) + { + result = Resmelt(from, weapon, weapon.Resource); + isStoreBought = !weapon.PlayerConstructed; + } + else if (targeted is DragonBardingDeed deed) + { + result = Resmelt(from, deed, deed.Resource); + } + + message = result switch + { + SmeltResult.Invalid => 1044272, + SmeltResult.NoSkill => 1044269, + SmeltResult.Success => isStoreBought ? 500418 : 1044270, + _ => 1044272 + }; + + from.SendGump(new CraftGump(from, m_CraftSystem, m_Tool, message)); + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Craft/DefAlchemy.cs b/Projects/UOContent/Engines/Craft/DefAlchemy.cs index fb55f8614..69e076be7 100644 --- a/Projects/UOContent/Engines/Craft/DefAlchemy.cs +++ b/Projects/UOContent/Engines/Craft/DefAlchemy.cs @@ -1,169 +1,306 @@ -using System; -using Server.Items; - -namespace Server.Engines.Craft -{ - public class DefAlchemy : CraftSystem - { - private static CraftSystem m_CraftSystem; - - private static readonly Type typeofPotion = typeof(BasePotion); - - private DefAlchemy() : base(1, 1, 1.25) // base( 1, 1, 3.1 ) - { - } - - public override SkillName MainSkill => SkillName.Alchemy; - - public override int GumpTitleNumber => 1044001; - - public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefAlchemy()); - - public override double GetChanceAtMin(CraftItem item) => 0.0; - - public override int CanCraft(Mobile from, BaseTool tool, Type itemType) - { - if (tool?.Deleted != false || tool.UsesRemaining < 0) - return 1044038; // You have worn out your tool! - - if (!BaseTool.CheckAccessible(tool, from)) - return 1044263; // The tool must be on your person to use. - - return 0; - } - - public override void PlayCraftEffect(Mobile from) - { - from.PlaySound(0x242); - } - - public static bool IsPotion(Type type) => typeofPotion.IsAssignableFrom(type); - - public override int PlayEndingEffect(Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, - bool makersMark, CraftItem item) - { - if (toolBroken) - from.SendLocalizedMessage(1044038); // You have worn out your tool - - if (failed) - { - if (IsPotion(item.ItemType)) - { - from.AddToBackpack(new Bottle()); - return 500287; // You fail to create a useful potion. - } - - return 1044043; // You failed to create the item, and some of your materials are lost. - } - - from.PlaySound(0x240); // Sound of a filling bottle - - if (IsPotion(item.ItemType)) - { - if (quality == -1) - return 1048136; // You create the potion and pour it into a keg. - return 500279; // You pour the potion into a bottle... - } - - return 1044154; // You create the item. - } - - public override void InitCraftList() - { - int index; - - // Refresh Potion - index = AddCraft(typeof(RefreshPotion), 1044530, 1044538, -25, 25.0, typeof(BlackPearl), 1044353, 1, 1044361); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - index = AddCraft(typeof(TotalRefreshPotion), 1044530, 1044539, 25.0, 75.0, typeof(BlackPearl), 1044353, 5, - 1044361); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - - // Agility Potion - index = AddCraft(typeof(AgilityPotion), 1044531, 1044540, 15.0, 65.0, typeof(Bloodmoss), 1044354, 1, 1044362); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - index = AddCraft(typeof(GreaterAgilityPotion), 1044531, 1044541, 35.0, 85.0, typeof(Bloodmoss), 1044354, 3, - 1044362); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - - // Nightsight Potion - index = AddCraft(typeof(NightSightPotion), 1044532, 1044542, -25.0, 25.0, typeof(SpidersSilk), 1044360, 1, - 1044368); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - - // Heal Potion - index = AddCraft(typeof(LesserHealPotion), 1044533, 1044543, -25.0, 25.0, typeof(Ginseng), 1044356, 1, 1044364); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - index = AddCraft(typeof(HealPotion), 1044533, 1044544, 15.0, 65.0, typeof(Ginseng), 1044356, 3, 1044364); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - index = AddCraft(typeof(GreaterHealPotion), 1044533, 1044545, 55.0, 105.0, typeof(Ginseng), 1044356, 7, 1044364); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - - // Strength Potion - index = AddCraft(typeof(StrengthPotion), 1044534, 1044546, 25.0, 75.0, typeof(MandrakeRoot), 1044357, 2, - 1044365); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - index = AddCraft(typeof(GreaterStrengthPotion), 1044534, 1044547, 45.0, 95.0, typeof(MandrakeRoot), 1044357, 5, - 1044365); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - - // Poison Potion - index = AddCraft(typeof(LesserPoisonPotion), 1044535, 1044548, -5.0, 45.0, typeof(Nightshade), 1044358, 1, - 1044366); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - index = AddCraft(typeof(PoisonPotion), 1044535, 1044549, 15.0, 65.0, typeof(Nightshade), 1044358, 2, 1044366); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - index = AddCraft(typeof(GreaterPoisonPotion), 1044535, 1044550, 55.0, 105.0, typeof(Nightshade), 1044358, 4, - 1044366); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - index = AddCraft(typeof(DeadlyPoisonPotion), 1044535, 1044551, 90.0, 140.0, typeof(Nightshade), 1044358, 8, - 1044366); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - - // Cure Potion - index = AddCraft(typeof(LesserCurePotion), 1044536, 1044552, -10.0, 40.0, typeof(Garlic), 1044355, 1, 1044363); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - index = AddCraft(typeof(CurePotion), 1044536, 1044553, 25.0, 75.0, typeof(Garlic), 1044355, 3, 1044363); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - index = AddCraft(typeof(GreaterCurePotion), 1044536, 1044554, 65.0, 115.0, typeof(Garlic), 1044355, 6, 1044363); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - - // Explosion Potion - index = AddCraft(typeof(LesserExplosionPotion), 1044537, 1044555, 5.0, 55.0, typeof(SulfurousAsh), 1044359, 3, - 1044367); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - index = AddCraft(typeof(ExplosionPotion), 1044537, 1044556, 35.0, 85.0, typeof(SulfurousAsh), 1044359, 5, - 1044367); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - index = AddCraft(typeof(GreaterExplosionPotion), 1044537, 1044557, 65.0, 115.0, typeof(SulfurousAsh), 1044359, - 10, 1044367); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - - if (Core.SE) - { - index = AddCraft(typeof(SmokeBomb), 1044537, 1030248, 90.0, 120.0, typeof(Eggs), 1044477, 1, 1044253); - AddRes(index, typeof(Ginseng), 1044356, 3, 1044364); - SetNeededExpansion(index, Expansion.SE); - - // Conflagration Potions - index = AddCraft(typeof(ConflagrationPotion), 1044109, 1072096, 55.0, 105.0, typeof(GraveDust), 1023983, 5, - 1044253); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(GreaterConflagrationPotion), 1044109, 1072099, 65.0, 115.0, typeof(GraveDust), - 1023983, 10, 1044253); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - SetNeededExpansion(index, Expansion.SE); - // Confusion Blast Potions - index = AddCraft(typeof(ConfusionBlastPotion), 1044109, 1072106, 55.0, 105.0, typeof(PigIron), 1023978, 5, - 1044253); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(GreaterConfusionBlastPotion), 1044109, 1072109, 65.0, 115.0, typeof(PigIron), - 1023978, 10, 1044253); - AddRes(index, typeof(Bottle), 1044529, 1, 500315); - SetNeededExpansion(index, Expansion.SE); - } - } - } -} +using System; +using Server.Items; + +namespace Server.Engines.Craft +{ + public class DefAlchemy : CraftSystem + { + private static CraftSystem m_CraftSystem; + + private static readonly Type typeofPotion = typeof(BasePotion); + + private DefAlchemy() : base(1, 1, 1.25) // base( 1, 1, 3.1 ) + { + } + + public override SkillName MainSkill => SkillName.Alchemy; + + public override int GumpTitleNumber => 1044001; + + public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefAlchemy()); + + public override double GetChanceAtMin(CraftItem item) => 0.0; + + public override int CanCraft(Mobile from, BaseTool tool, Type itemType) + { + if (tool?.Deleted != false || tool.UsesRemaining < 0) + return 1044038; // You have worn out your tool! + + if (!BaseTool.CheckAccessible(tool, from)) + return 1044263; // The tool must be on your person to use. + + return 0; + } + + public override void PlayCraftEffect(Mobile from) + { + from.PlaySound(0x242); + } + + public static bool IsPotion(Type type) => typeofPotion.IsAssignableFrom(type); + + public override int PlayEndingEffect( + Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, + bool makersMark, CraftItem item + ) + { + if (toolBroken) + from.SendLocalizedMessage(1044038); // You have worn out your tool + + if (failed) + { + if (IsPotion(item.ItemType)) + { + from.AddToBackpack(new Bottle()); + return 500287; // You fail to create a useful potion. + } + + return 1044043; // You failed to create the item, and some of your materials are lost. + } + + from.PlaySound(0x240); // Sound of a filling bottle + + if (IsPotion(item.ItemType)) + { + if (quality == -1) + return 1048136; // You create the potion and pour it into a keg. + return 500279; // You pour the potion into a bottle... + } + + return 1044154; // You create the item. + } + + public override void InitCraftList() + { + int index; + + // Refresh Potion + index = AddCraft(typeof(RefreshPotion), 1044530, 1044538, -25, 25.0, typeof(BlackPearl), 1044353, 1, 1044361); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + index = AddCraft( + typeof(TotalRefreshPotion), + 1044530, + 1044539, + 25.0, + 75.0, + typeof(BlackPearl), + 1044353, + 5, + 1044361 + ); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + + // Agility Potion + index = AddCraft(typeof(AgilityPotion), 1044531, 1044540, 15.0, 65.0, typeof(Bloodmoss), 1044354, 1, 1044362); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + index = AddCraft( + typeof(GreaterAgilityPotion), + 1044531, + 1044541, + 35.0, + 85.0, + typeof(Bloodmoss), + 1044354, + 3, + 1044362 + ); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + + // Nightsight Potion + index = AddCraft( + typeof(NightSightPotion), + 1044532, + 1044542, + -25.0, + 25.0, + typeof(SpidersSilk), + 1044360, + 1, + 1044368 + ); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + + // Heal Potion + index = AddCraft(typeof(LesserHealPotion), 1044533, 1044543, -25.0, 25.0, typeof(Ginseng), 1044356, 1, 1044364); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + index = AddCraft(typeof(HealPotion), 1044533, 1044544, 15.0, 65.0, typeof(Ginseng), 1044356, 3, 1044364); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + index = AddCraft(typeof(GreaterHealPotion), 1044533, 1044545, 55.0, 105.0, typeof(Ginseng), 1044356, 7, 1044364); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + + // Strength Potion + index = AddCraft( + typeof(StrengthPotion), + 1044534, + 1044546, + 25.0, + 75.0, + typeof(MandrakeRoot), + 1044357, + 2, + 1044365 + ); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + index = AddCraft( + typeof(GreaterStrengthPotion), + 1044534, + 1044547, + 45.0, + 95.0, + typeof(MandrakeRoot), + 1044357, + 5, + 1044365 + ); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + + // Poison Potion + index = AddCraft( + typeof(LesserPoisonPotion), + 1044535, + 1044548, + -5.0, + 45.0, + typeof(Nightshade), + 1044358, + 1, + 1044366 + ); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + index = AddCraft(typeof(PoisonPotion), 1044535, 1044549, 15.0, 65.0, typeof(Nightshade), 1044358, 2, 1044366); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + index = AddCraft( + typeof(GreaterPoisonPotion), + 1044535, + 1044550, + 55.0, + 105.0, + typeof(Nightshade), + 1044358, + 4, + 1044366 + ); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + index = AddCraft( + typeof(DeadlyPoisonPotion), + 1044535, + 1044551, + 90.0, + 140.0, + typeof(Nightshade), + 1044358, + 8, + 1044366 + ); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + + // Cure Potion + index = AddCraft(typeof(LesserCurePotion), 1044536, 1044552, -10.0, 40.0, typeof(Garlic), 1044355, 1, 1044363); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + index = AddCraft(typeof(CurePotion), 1044536, 1044553, 25.0, 75.0, typeof(Garlic), 1044355, 3, 1044363); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + index = AddCraft(typeof(GreaterCurePotion), 1044536, 1044554, 65.0, 115.0, typeof(Garlic), 1044355, 6, 1044363); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + + // Explosion Potion + index = AddCraft( + typeof(LesserExplosionPotion), + 1044537, + 1044555, + 5.0, + 55.0, + typeof(SulfurousAsh), + 1044359, + 3, + 1044367 + ); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + index = AddCraft( + typeof(ExplosionPotion), + 1044537, + 1044556, + 35.0, + 85.0, + typeof(SulfurousAsh), + 1044359, + 5, + 1044367 + ); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + index = AddCraft( + typeof(GreaterExplosionPotion), + 1044537, + 1044557, + 65.0, + 115.0, + typeof(SulfurousAsh), + 1044359, + 10, + 1044367 + ); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + + if (Core.SE) + { + index = AddCraft(typeof(SmokeBomb), 1044537, 1030248, 90.0, 120.0, typeof(Eggs), 1044477, 1, 1044253); + AddRes(index, typeof(Ginseng), 1044356, 3, 1044364); + SetNeededExpansion(index, Expansion.SE); + + // Conflagration Potions + index = AddCraft( + typeof(ConflagrationPotion), + 1044109, + 1072096, + 55.0, + 105.0, + typeof(GraveDust), + 1023983, + 5, + 1044253 + ); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft( + typeof(GreaterConflagrationPotion), + 1044109, + 1072099, + 65.0, + 115.0, + typeof(GraveDust), + 1023983, + 10, + 1044253 + ); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + SetNeededExpansion(index, Expansion.SE); + // Confusion Blast Potions + index = AddCraft( + typeof(ConfusionBlastPotion), + 1044109, + 1072106, + 55.0, + 105.0, + typeof(PigIron), + 1023978, + 5, + 1044253 + ); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft( + typeof(GreaterConfusionBlastPotion), + 1044109, + 1072109, + 65.0, + 115.0, + typeof(PigIron), + 1023978, + 10, + 1044253 + ); + AddRes(index, typeof(Bottle), 1044529, 1, 500315); + SetNeededExpansion(index, Expansion.SE); + } + } + } +} diff --git a/Projects/UOContent/Engines/Craft/DefBlacksmithy.cs b/Projects/UOContent/Engines/Craft/DefBlacksmithy.cs index 1b9ac5caf..0e3a6f3c7 100644 --- a/Projects/UOContent/Engines/Craft/DefBlacksmithy.cs +++ b/Projects/UOContent/Engines/Craft/DefBlacksmithy.cs @@ -1,749 +1,1309 @@ -using System; -using Server.Items; - -namespace Server.Engines.Craft -{ - public class DefBlacksmithy : CraftSystem - { - private static CraftSystem m_CraftSystem; - - private static readonly Type typeofAnvil = typeof(AnvilAttribute); - private static readonly Type typeofForge = typeof(ForgeAttribute); - - private DefBlacksmithy() : base(1, 1, 1.25) // base( 1, 2, 1.7 ) - { - /* - - base( MinCraftEffect, MaxCraftEffect, Delay ) - - MinCraftEffect : The minimum number of time the mobile will play the craft effect - MaxCraftEffect : The maximum number of time the mobile will play the craft effect - Delay : The delay between each craft effect - - Example: (3, 6, 1.7) would make the mobile do the PlayCraftEffect override - function between 3 and 6 time, with a 1.7 second delay each time. - - */ - } - - public override SkillName MainSkill => SkillName.Blacksmith; - - public override int GumpTitleNumber => 1044002; - - public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefBlacksmithy()); - - public override CraftECA ECA => CraftECA.ChanceMinusSixtyToFourtyFive; - - public override double GetChanceAtMin(CraftItem item) => 0.0; - - public static void CheckAnvilAndForge(Mobile from, int range, out bool anvil, out bool forge) - { - anvil = false; - forge = false; - - Map map = from.Map; - - if (map == null) - return; - - IPooledEnumerable eable = map.GetItemsInRange(from.Location, range); - - foreach (Item item in eable) - { - Type type = item.GetType(); - - bool isAnvil = type.IsDefined(typeofAnvil, false) || item.ItemID == 4015 || item.ItemID == 4016 || - item.ItemID == 0x2DD5 || item.ItemID == 0x2DD6; - bool isForge = type.IsDefined(typeofForge, false) || item.ItemID == 4017 || - (item.ItemID >= 6522 && item.ItemID <= 6569) || item.ItemID == 0x2DD8; - - if (isAnvil || isForge) - { - if (from.Z + 16 < item.Z || item.Z + 16 < from.Z || !from.InLOS(item)) - continue; - - anvil = anvil || isAnvil; - forge = forge || isForge; - - if (anvil && forge) - break; - } - } - - eable.Free(); - - for (int x = -range; (!anvil || !forge) && x <= range; ++x) - for (int y = -range; (!anvil || !forge) && y <= range; ++y) - { - StaticTile[] tiles = map.Tiles.GetStaticTiles(from.X + x, from.Y + y, true); - - for (int i = 0; (!anvil || !forge) && i < tiles.Length; ++i) - { - int id = tiles[i].ID; - - bool isAnvil = id == 4015 || id == 4016 || id == 0x2DD5 || id == 0x2DD6; - bool isForge = id == 4017 || (id >= 6522 && id <= 6569) || id == 0x2DD8; - - if (isAnvil || isForge) - { - if (from.Z + 16 < tiles[i].Z || tiles[i].Z + 16 < from.Z || - !from.InLOS(new Point3D(from.X + x, from.Y + y, tiles[i].Z + tiles[i].Height / 2 + 1))) - continue; - - anvil = anvil || isAnvil; - forge = forge || isForge; - } - } - } - } - - public override int CanCraft(Mobile from, BaseTool tool, Type itemType) - { - if (tool?.Deleted != false || tool.UsesRemaining < 0) - return 1044038; // You have worn out your tool! - if (!BaseTool.CheckTool(tool, from)) - return 1048146; // If you have a tool equipped, you must use that tool. - if (!BaseTool.CheckAccessible(tool, from)) - return 1044263; // The tool must be on your person to use. - - CheckAnvilAndForge(from, 2, out bool anvil, out bool forge); - - if (anvil && forge) - return 0; - - return 1044267; // You must be near an anvil and a forge to smith items. - } - - public override void PlayCraftEffect(Mobile from) - { - // no animation, instant sound - // if (from.Body.Type == BodyType.Human && !from.Mounted) - // from.Animate( 9, 5, 1, true, false, 0 ); - // new InternalTimer( from ).Start(); - - from.PlaySound(0x2A); - } - - public override int PlayEndingEffect(Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, - bool makersMark, CraftItem item) - { - if (toolBroken) - from.SendLocalizedMessage(1044038); // You have worn out your tool - - if (failed) - { - if (lostMaterial) - return 1044043; // You failed to create the item, and some of your materials are lost. - return 1044157; // You failed to create the item, but no materials were lost. - } - - if (quality == 0) - return 502785; // You were barely able to make this item. It's quality is below average. - if (makersMark && quality == 2) - return 1044156; // You create an exceptional quality item and affix your maker's mark. - if (quality == 2) - return 1044155; // You create an exceptional quality item. - return 1044154; // You create the item. - } - - public override void InitCraftList() - { - /* - Syntax for a SIMPLE craft item - AddCraft( ObjectType, Group, MinSkill, MaxSkill, ResourceType, Amount, Message ) - - ObjectType : The type of the object you want to add to the build list. - Group : The group in which the object will be showed in the craft menu. - MinSkill : The minimum of skill value - MaxSkill : The maximum of skill value - ResourceType : The type of the resource the mobile need to create the item - Amount : The amount of the ResourceType it need to create the item - Message : String or Int for Localized. The message that will be sent to the mobile, if the specified resource is missing. - - Syntax for a COMPLEX craft item. A complex item is an item that need either more than - only one skill, or more than only one resource. - - Coming soon.... - */ - - AddCraft(typeof(RingmailGloves), 1011076, 1025099, 12.0, 62.0, typeof(IronIngot), 1044036, 10, 1044037); - AddCraft(typeof(RingmailLegs), 1011076, 1025104, 19.4, 69.4, typeof(IronIngot), 1044036, 16, 1044037); - AddCraft(typeof(RingmailArms), 1011076, 1025103, 16.9, 66.9, typeof(IronIngot), 1044036, 14, 1044037); - AddCraft(typeof(RingmailChest), 1011076, 1025100, 21.9, 71.9, typeof(IronIngot), 1044036, 18, 1044037); - - AddCraft(typeof(ChainCoif), 1011077, 1025051, 14.5, 64.5, typeof(IronIngot), 1044036, 10, 1044037); - AddCraft(typeof(ChainLegs), 1011077, 1025054, 36.7, 86.7, typeof(IronIngot), 1044036, 18, 1044037); - AddCraft(typeof(ChainChest), 1011077, 1025055, 39.1, 89.1, typeof(IronIngot), 1044036, 20, 1044037); - - int index; - - AddCraft(typeof(PlateArms), 1011078, 1025136, 66.3, 116.3, typeof(IronIngot), 1044036, 18, 1044037); - AddCraft(typeof(PlateGloves), 1011078, 1025140, 58.9, 108.9, typeof(IronIngot), 1044036, 12, 1044037); - AddCraft(typeof(PlateGorget), 1011078, 1025139, 56.4, 106.4, typeof(IronIngot), 1044036, 10, 1044037); - AddCraft(typeof(PlateLegs), 1011078, 1025137, 68.8, 118.8, typeof(IronIngot), 1044036, 20, 1044037); - AddCraft(typeof(PlateChest), 1011078, 1046431, 75.0, 125.0, typeof(IronIngot), 1044036, 25, 1044037); - AddCraft(typeof(FemalePlateChest), 1011078, 1046430, 44.1, 94.1, typeof(IronIngot), 1044036, 20, 1044037); - - if (Core.AOS) // exact pre-aos functionality unknown - AddCraft(typeof(DragonBardingDeed), 1011078, 1053012, 72.5, 122.5, typeof(IronIngot), 1044036, 750, 1044037); - - if (Core.SE) - { - index = AddCraft(typeof(PlateMempo), 1011078, 1030180, 80.0, 130.0, typeof(IronIngot), 1044036, 18, 1044037); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(PlateDo), 1011078, 1030184, 80.0, 130.0, typeof(IronIngot), 1044036, 28, - 1044037); // Double check skill - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(PlateHiroSode), 1011078, 1030187, 80.0, 130.0, typeof(IronIngot), 1044036, 16, - 1044037); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(PlateSuneate), 1011078, 1030195, 65.0, 115.0, typeof(IronIngot), 1044036, 20, - 1044037); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(PlateHaidate), 1011078, 1030200, 65.0, 115.0, typeof(IronIngot), 1044036, 20, - 1044037); - SetNeededExpansion(index, Expansion.SE); - } - - AddCraft(typeof(Bascinet), 1011079, 1025132, 8.3, 58.3, typeof(IronIngot), 1044036, 15, 1044037); - AddCraft(typeof(CloseHelm), 1011079, 1025128, 37.9, 87.9, typeof(IronIngot), 1044036, 15, 1044037); - AddCraft(typeof(Helmet), 1011079, 1025130, 37.9, 87.9, typeof(IronIngot), 1044036, 15, 1044037); - AddCraft(typeof(NorseHelm), 1011079, 1025134, 37.9, 87.9, typeof(IronIngot), 1044036, 15, 1044037); - AddCraft(typeof(PlateHelm), 1011079, 1025138, 62.6, 112.6, typeof(IronIngot), 1044036, 15, 1044037); - - if (Core.SE) - { - index = AddCraft(typeof(ChainHatsuburi), 1011079, 1030175, 30.0, 80.0, typeof(IronIngot), 1044036, 20, - 1044037); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(PlateHatsuburi), 1011079, 1030176, 45.0, 95.0, typeof(IronIngot), 1044036, 20, - 1044037); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(HeavyPlateJingasa), 1011079, 1030178, 45.0, 95.0, typeof(IronIngot), 1044036, 20, - 1044037); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(LightPlateJingasa), 1011079, 1030188, 45.0, 95.0, typeof(IronIngot), 1044036, 20, - 1044037); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(SmallPlateJingasa), 1011079, 1030191, 45.0, 95.0, typeof(IronIngot), 1044036, 20, - 1044037); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(DecorativePlateKabuto), 1011079, 1030179, 90.0, 140.0, typeof(IronIngot), 1044036, - 25, 1044037); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(PlateBattleKabuto), 1011079, 1030192, 90.0, 140.0, typeof(IronIngot), 1044036, 25, - 1044037); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(StandardPlateKabuto), 1011079, 1030196, 90.0, 140.0, typeof(IronIngot), 1044036, 25, - 1044037); - SetNeededExpansion(index, Expansion.SE); - - if (Core.ML) - { - index = AddCraft(typeof(Circlet), 1011079, 1032645, 62.1, 112.1, typeof(IronIngot), 1044036, 6, 1044037); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(RoyalCirclet), 1011079, 1032646, 70.0, 120.0, typeof(IronIngot), 1044036, 6, - 1044037); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(GemmedCirclet), 1011079, 1032647, 75.0, 125.0, typeof(IronIngot), 1044036, 6, - 1044037); - AddRes(index, typeof(Tourmaline), 1044237, 1, 1044240); - AddRes(index, typeof(Amethyst), 1044236, 1, 1044240); - AddRes(index, typeof(BlueDiamond), 1032696, 1, 1044240); - SetNeededExpansion(index, Expansion.ML); - } - } - - AddCraft(typeof(Buckler), 1011080, 1027027, -25.0, 25.0, typeof(IronIngot), 1044036, 10, 1044037); - AddCraft(typeof(BronzeShield), 1011080, 1027026, -15.2, 34.8, typeof(IronIngot), 1044036, 12, 1044037); - AddCraft(typeof(HeaterShield), 1011080, 1027030, 24.3, 74.3, typeof(IronIngot), 1044036, 18, 1044037); - AddCraft(typeof(MetalShield), 1011080, 1027035, -10.2, 39.8, typeof(IronIngot), 1044036, 14, 1044037); - AddCraft(typeof(MetalKiteShield), 1011080, 1027028, 4.6, 54.6, typeof(IronIngot), 1044036, 16, 1044037); - AddCraft(typeof(WoodenKiteShield), 1011080, 1027032, -15.2, 34.8, typeof(IronIngot), 1044036, 8, 1044037); - - if (Core.AOS) - { - AddCraft(typeof(ChaosShield), 1011080, 1027107, 85.0, 135.0, typeof(IronIngot), 1044036, 25, 1044037); - AddCraft(typeof(OrderShield), 1011080, 1027108, 85.0, 135.0, typeof(IronIngot), 1044036, 25, 1044037); - } - - if (Core.AOS) - AddCraft(typeof(BoneHarvester), 1011081, 1029915, 33.0, 83.0, typeof(IronIngot), 1044036, 10, 1044037); - - AddCraft(typeof(Broadsword), 1011081, 1023934, 35.4, 85.4, typeof(IronIngot), 1044036, 10, 1044037); - - if (Core.AOS) - AddCraft(typeof(CrescentBlade), 1011081, 1029921, 45.0, 95.0, typeof(IronIngot), 1044036, 14, 1044037); - - AddCraft(typeof(Cutlass), 1011081, 1025185, 24.3, 74.3, typeof(IronIngot), 1044036, 8, 1044037); - AddCraft(typeof(Dagger), 1011081, 1023921, -0.4, 49.6, typeof(IronIngot), 1044036, 3, 1044037); - AddCraft(typeof(Katana), 1011081, 1025119, 44.1, 94.1, typeof(IronIngot), 1044036, 8, 1044037); - AddCraft(typeof(Kryss), 1011081, 1025121, 36.7, 86.7, typeof(IronIngot), 1044036, 8, 1044037); - AddCraft(typeof(Longsword), 1011081, 1023937, 28.0, 78.0, typeof(IronIngot), 1044036, 12, 1044037); - AddCraft(typeof(Scimitar), 1011081, 1025046, 31.7, 81.7, typeof(IronIngot), 1044036, 10, 1044037); - AddCraft(typeof(VikingSword), 1011081, 1025049, 24.3, 74.3, typeof(IronIngot), 1044036, 14, 1044037); - - if (Core.SE) - { - index = AddCraft(typeof(NoDachi), 1011081, 1030221, 75.0, 125.0, typeof(IronIngot), 1044036, 18, 1044037); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(Wakizashi), 1011081, 1030223, 50.0, 100.0, typeof(IronIngot), 1044036, 8, 1044037); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(Lajatang), 1011081, 1030226, 80.0, 130.0, typeof(IronIngot), 1044036, 25, 1044037); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(Daisho), 1011081, 1030228, 60.0, 110.0, typeof(IronIngot), 1044036, 15, 1044037); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(Tekagi), 1011081, 1030230, 55.0, 105.0, typeof(IronIngot), 1044036, 12, 1044037); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(Shuriken), 1011081, 1030231, 45.0, 95.0, typeof(IronIngot), 1044036, 5, 1044037); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(Kama), 1011081, 1030232, 40.0, 90.0, typeof(IronIngot), 1044036, 14, 1044037); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(Sai), 1011081, 1030234, 50.0, 100.0, typeof(IronIngot), 1044036, 12, 1044037); - SetNeededExpansion(index, Expansion.SE); - - if (Core.ML) - { - index = AddCraft(typeof(RadiantScimitar), 1011081, 1031571, 75.0, 125.0, typeof(IronIngot), 1044036, 15, - 1044037); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(WarCleaver), 1011081, 1031567, 70.0, 120.0, typeof(IronIngot), 1044036, 18, - 1044037); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(ElvenSpellblade), 1011081, 1031564, 70.0, 120.0, typeof(IronIngot), 1044036, 14, - 1044037); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(AssassinSpike), 1011081, 1031565, 70.0, 120.0, typeof(IronIngot), 1044036, 9, - 1044037); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(Leafblade), 1011081, 1031566, 70.0, 120.0, typeof(IronIngot), 1044036, 12, - 1044037); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(RuneBlade), 1011081, 1031570, 70.0, 120.0, typeof(IronIngot), 1044036, 15, - 1044037); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(ElvenMachete), 1011081, 1031573, 70.0, 120.0, typeof(IronIngot), 1044036, 14, - 1044037); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(RuneCarvingKnife), 1011081, 1072915, 70.0, 120.0, typeof(IronIngot), 1044036, 9, - 1044037); - AddRes(index, typeof(DreadHornMane), 1032682, 1, 1053098); - AddRes(index, typeof(Putrefication), 1032678, 10, 1053098); - AddRes(index, typeof(Muculent), 1032680, 10, 1053098); - AddRareRecipe(index, 0); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(ColdForgedBlade), 1011081, 1072916, 70.0, 120.0, typeof(IronIngot), 1044036, 18, - 1044037); - AddRes(index, typeof(GrizzledBones), 1032684, 1, 1053098); - AddRes(index, typeof(Taint), 1032684, 10, 1053098); - AddRes(index, typeof(Blight), 1032675, 10, 1053098); - AddRareRecipe(index, 1); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(OverseerSunderedBlade), 1011081, 1072920, 70.0, 120.0, typeof(IronIngot), - 1044036, 15, 1044037); - AddRes(index, typeof(GrizzledBones), 1032684, 1, 1053098); - AddRes(index, typeof(Blight), 1032675, 10, 1053098); - AddRes(index, typeof(Scourge), 1032677, 10, 1053098); - AddRareRecipe(index, 2); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(LuminousRuneBlade), 1011081, 1072922, 70.0, 120.0, typeof(IronIngot), 1044036, - 15, 1044037); - AddRes(index, typeof(GrizzledBones), 1032684, 1, 1053098); - AddRes(index, typeof(Corruption), 1032676, 10, 1053098); - AddRes(index, typeof(Putrefication), 1032678, 10, 1053098); - AddRareRecipe(index, 3); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(TrueSpellblade), 1011081, 1073513, 75.0, 125.0, typeof(IronIngot), 1044036, 14, - 1044037); - AddRes(index, typeof(BlueDiamond), 1032696, 1, 1044240); - AddRecipe(index, 4); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(IcySpellblade), 1011081, 1073514, 75.0, 125.0, typeof(IronIngot), 1044036, 14, - 1044037); - AddRes(index, typeof(Turquoise), 1032691, 1, 1044240); - AddRecipe(index, 5); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(FierySpellblade), 1011081, 1073515, 75.0, 125.0, typeof(IronIngot), 1044036, 14, - 1044037); - AddRes(index, typeof(FireRuby), 1032695, 1, 1044240); - AddRecipe(index, 6); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(SpellbladeOfDefense), 1011081, 1073516, 75.0, 125.0, typeof(IronIngot), 1044036, - 18, 1044037); - AddRes(index, typeof(WhitePearl), 1032694, 1, 1044240); - AddRecipe(index, 7); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(TrueAssassinSpike), 1011081, 1073517, 75.0, 125.0, typeof(IronIngot), 1044036, 9, - 1044037); - AddRes(index, typeof(DarkSapphire), 1032690, 1, 1044240); - AddRecipe(index, 8); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(ChargedAssassinSpike), 1011081, 1073518, 75.0, 125.0, typeof(IronIngot), 1044036, - 9, 1044037); - AddRes(index, typeof(EcruCitrine), 1032693, 1, 1044240); - AddRecipe(index, 9); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(MagekillerAssassinSpike), 1011081, 1073519, 75.0, 125.0, typeof(IronIngot), - 1044036, 9, 1044037); - AddRes(index, typeof(BrilliantAmber), 1032697, 1, 1044240); - AddRecipe(index, 10); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(WoundingAssassinSpike), 1011081, 1073520, 75.0, 125.0, typeof(IronIngot), - 1044036, 9, 1044037); - AddRes(index, typeof(PerfectEmerald), 1032692, 1, 1044240); - AddRecipe(index, 11); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(TrueLeafblade), 1011081, 1073521, 75.0, 125.0, typeof(IronIngot), 1044036, 12, - 1044037); - AddRes(index, typeof(BlueDiamond), 1032696, 1, 1044240); - AddRecipe(index, 12); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(Luckblade), 1011081, 1073522, 75.0, 125.0, typeof(IronIngot), 1044036, 12, - 1044037); - AddRes(index, typeof(WhitePearl), 1032694, 1, 1044240); - AddRecipe(index, 13); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(MagekillerLeafblade), 1011081, 1073523, 75.0, 125.0, typeof(IronIngot), 1044036, - 12, 1044037); - AddRes(index, typeof(FireRuby), 1032695, 1, 1044240); - AddRecipe(index, 14); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(LeafbladeOfEase), 1011081, 1073524, 75.0, 125.0, typeof(IronIngot), 1044036, 12, - 1044037); - AddRes(index, typeof(PerfectEmerald), 1032692, 1, 1044240); - AddRecipe(index, 15); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(KnightsWarCleaver), 1011081, 1073525, 75.0, 125.0, typeof(IronIngot), 1044036, - 18, 1044037); - AddRes(index, typeof(PerfectEmerald), 1032692, 1, 1044240); - AddRecipe(index, 16); - SetNeededExpansion(index, Expansion.ML); - - // TODO - index = AddCraft(typeof(ButchersWarCleaver), 1011081, 1073526, 75.0, 125.0, typeof(IronIngot), 1044036, - 18, 1044037); - AddRes(index, typeof(Turquoise), 1032691, 1, 1044240); - AddRecipe(index, 17); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(SerratedWarCleaver), 1011081, 1073527, 75.0, 125.0, typeof(IronIngot), 1044036, - 18, 1044037); - AddRes(index, typeof(EcruCitrine), 1032693, 1, 1044240); - AddRecipe(index, 18); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(TrueWarCleaver), 1011081, 1073528, 75.0, 125.0, typeof(IronIngot), 1044036, 18, - 1044037); - AddRes(index, typeof(BrilliantAmber), 1032697, 1, 1044240); - AddRecipe(index, 19); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(AdventurersMachete), 1011081, 1073533, 75.0, 125.0, typeof(IronIngot), 1044036, - 14, 1044037); - AddRes(index, typeof(WhitePearl), 1032694, 1, 1044240); - AddRecipe(index, 20); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(OrcishMachete), 1011081, 1073534, 75.0, 125.0, typeof(IronIngot), 1044036, 14, - 1044037); - AddRes(index, typeof(Scourge), 1072136, 1, 1042081); - AddRecipe(index, 21); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(MacheteOfDefense), 1011081, 1073535, 75.0, 125.0, typeof(IronIngot), 1044036, 14, - 1044037); - AddRes(index, typeof(BrilliantAmber), 1032697, 1, 1044240); - AddRecipe(index, 22); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(DiseasedMachete), 1011081, 1073536, 75.0, 125.0, typeof(IronIngot), 1044036, 14, - 1044037); - AddRes(index, typeof(Blight), 1072134, 1, 1042081); - AddRecipe(index, 23); - SetNeededExpansion(index, Expansion.ML); - - // TODO - index = AddCraft(typeof(Runesabre), 1011081, 1073537, 75.0, 125.0, typeof(IronIngot), 1044036, 15, - 1044037); - AddRes(index, typeof(Turquoise), 1032691, 1, 1044240); - AddRecipe(index, 24); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(MagesRuneBlade), 1011081, 1073538, 75.0, 125.0, typeof(IronIngot), 1044036, 15, - 1044037); - AddRes(index, typeof(BlueDiamond), 1032696, 1, 1044240); - AddRecipe(index, 25); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(RuneBladeOfKnowledge), 1011081, 1073539, 75.0, 125.0, typeof(IronIngot), 1044036, - 15, 1044037); - AddRes(index, typeof(EcruCitrine), 1032693, 1, 1044240); - AddRecipe(index, 26); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(CorruptedRuneBlade), 1011081, 1073540, 75.0, 125.0, typeof(IronIngot), 1044036, - 15, 1044037); - AddRes(index, typeof(Corruption), 1072135, 1, 1042081); - AddRecipe(index, 27); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(TrueRadiantScimitar), 1011081, 1073541, 75.0, 125.0, typeof(IronIngot), 1044036, - 15, 1044037); - AddRes(index, typeof(BrilliantAmber), 1032697, 1, 1044240); - AddRecipe(index, 28); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(DarkglowScimitar), 1011081, 1073542, 75.0, 125.0, typeof(IronIngot), 1044036, 15, - 1044037); - AddRes(index, typeof(DarkSapphire), 1032690, 1, 1044240); - AddRecipe(index, 29); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(IcyScimitar), 1011081, 1073543, 75.0, 125.0, typeof(IronIngot), 1044036, 15, - 1044037); - AddRes(index, typeof(DarkSapphire), 1032690, 1, 1044240); - AddRecipe(index, 30); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(TwinklingScimitar), 1011081, 1073544, 75.0, 125.0, typeof(IronIngot), 1044036, - 15, 1044037); - AddRes(index, typeof(DarkSapphire), 1032690, 1, 1044240); - AddRecipe(index, 31); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(BoneMachete), 1011081, 1020526, 45.0, 95.0, typeof(IronIngot), 1044036, 20, - 1044037); - AddRes(index, typeof(Bone), 1049064, 6, 1049063); - AddQuestRecipe(index, 32); - SetNeededExpansion(index, Expansion.ML); - } - } - - AddCraft(typeof(Axe), 1011082, 1023913, 34.2, 84.2, typeof(IronIngot), 1044036, 14, 1044037); - AddCraft(typeof(BattleAxe), 1011082, 1023911, 30.5, 80.5, typeof(IronIngot), 1044036, 14, 1044037); - AddCraft(typeof(DoubleAxe), 1011082, 1023915, 29.3, 79.3, typeof(IronIngot), 1044036, 12, 1044037); - AddCraft(typeof(ExecutionersAxe), 1011082, 1023909, 34.2, 84.2, typeof(IronIngot), 1044036, 14, 1044037); - AddCraft(typeof(LargeBattleAxe), 1011082, 1025115, 28.0, 78.0, typeof(IronIngot), 1044036, 12, 1044037); - AddCraft(typeof(TwoHandedAxe), 1011082, 1025187, 33.0, 83.0, typeof(IronIngot), 1044036, 16, 1044037); - AddCraft(typeof(WarAxe), 1011082, 1025040, 39.1, 89.1, typeof(IronIngot), 1044036, 16, 1044037); - - if (Core.ML) - { - index = AddCraft(typeof(OrnateAxe), 1011082, 1031572, 70.0, 120.0, typeof(IronIngot), 1044036, 18, 1044037); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(GuardianAxe), 1011082, 1073545, 75.0, 125.0, typeof(IronIngot), 1044036, 15, - 1044037); - AddRes(index, typeof(BlueDiamond), 1032696, 1, 1044240); - AddRecipe(index, 33); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(SingingAxe), 1011082, 1073546, 75.0, 125.0, typeof(IronIngot), 1044036, 15, 1044037); - AddRes(index, typeof(BrilliantAmber), 1032697, 1, 1044240); - AddRecipe(index, 34); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(ThunderingAxe), 1011082, 1073547, 75.0, 125.0, typeof(IronIngot), 1044036, 15, - 1044037); - AddRes(index, typeof(EcruCitrine), 1032693, 1, 1044240); - AddRecipe(index, 35); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(HeavyOrnateAxe), 1011082, 1073548, 75.0, 125.0, typeof(IronIngot), 1044036, 15, - 1044037); - AddRes(index, typeof(Turquoise), 1032691, 1, 1044240); - AddRecipe(index, 36); - SetNeededExpansion(index, Expansion.ML); - } - - AddCraft(typeof(Bardiche), 1011083, 1023917, 31.7, 81.7, typeof(IronIngot), 1044036, 18, 1044037); - - if (Core.AOS) - AddCraft(typeof(BladedStaff), 1011083, 1029917, 40.0, 90.0, typeof(IronIngot), 1044036, 12, 1044037); - - if (Core.AOS) - AddCraft(typeof(DoubleBladedStaff), 1011083, 1029919, 45.0, 95.0, typeof(IronIngot), 1044036, 16, 1044037); - - AddCraft(typeof(Halberd), 1011083, 1025183, 39.1, 89.1, typeof(IronIngot), 1044036, 20, 1044037); - - if (Core.AOS) - AddCraft(typeof(Lance), 1011083, 1029920, 48.0, 98.0, typeof(IronIngot), 1044036, 20, 1044037); - - if (Core.AOS) - AddCraft(typeof(Pike), 1011083, 1029918, 47.0, 97.0, typeof(IronIngot), 1044036, 12, 1044037); - - AddCraft(typeof(ShortSpear), 1011083, 1025123, 45.3, 95.3, typeof(IronIngot), 1044036, 6, 1044037); - - if (Core.AOS) - AddCraft(typeof(Scythe), 1011083, 1029914, 39.0, 89.0, typeof(IronIngot), 1044036, 14, 1044037); - - AddCraft(typeof(Spear), 1011083, 1023938, 49.0, 99.0, typeof(IronIngot), 1044036, 12, 1044037); - AddCraft(typeof(WarFork), 1011083, 1025125, 42.9, 92.9, typeof(IronIngot), 1044036, 12, 1044037); - - // Not craftable (is this an AOS change ??) - // AddCraft( typeof( Pitchfork ), 1011083, 1023720, 36.1, 86.1, typeof( IronIngot ), 1044036, 12, 1044037 ); - - AddCraft(typeof(HammerPick), 1011084, 1025181, 34.2, 84.2, typeof(IronIngot), 1044036, 16, 1044037); - AddCraft(typeof(Mace), 1011084, 1023932, 14.5, 64.5, typeof(IronIngot), 1044036, 6, 1044037); - AddCraft(typeof(Maul), 1011084, 1025179, 19.4, 69.4, typeof(IronIngot), 1044036, 10, 1044037); - - if (Core.AOS) - AddCraft(typeof(Scepter), 1011084, 1029916, 21.4, 71.4, typeof(IronIngot), 1044036, 10, 1044037); - - AddCraft(typeof(WarMace), 1011084, 1025127, 28.0, 78.0, typeof(IronIngot), 1044036, 14, 1044037); - AddCraft(typeof(WarHammer), 1011084, 1025177, 34.2, 84.2, typeof(IronIngot), 1044036, 16, 1044037); - - if (Core.SE) - { - index = AddCraft(typeof(Tessen), 1011084, 1030222, 85.0, 135.0, typeof(IronIngot), 1044036, 16, 1044037); - AddSkill(index, SkillName.Tailoring, 50.0, 55.0); - AddRes(index, typeof(Cloth), 1044286, 10, 1044287); - SetNeededExpansion(index, Expansion.SE); - } - - if (Core.ML) - { - index = AddCraft(typeof(DiamondMace), 1011084, 1031556, 70.0, 120.0, typeof(IronIngot), 1044036, 20, - 1044037); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(ShardThrasher), 1011084, 1072918, 70.0, 120.0, typeof(IronIngot), 1044036, 20, - 1044037); - AddRes(index, typeof(EyeOfTheTravesty), 1073126, 1, 1042081); - AddRes(index, typeof(Muculent), 1072139, 10, 1042081); - AddRes(index, typeof(Corruption), 1072135, 10, 1042081); - AddRareRecipe(index, 37); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(RubyMace), 1011084, 1073529, 75.0, 125.0, typeof(IronIngot), 1044036, 20, 1044037); - AddRes(index, typeof(FireRuby), 1032695, 1, 1044240); - AddRecipe(index, 38); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(EmeraldMace), 1011084, 1073530, 75.0, 125.0, typeof(IronIngot), 1044036, 20, - 1044037); - AddRes(index, typeof(PerfectEmerald), 1032692, 1, 1044240); - AddRecipe(index, 39); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(SapphireMace), 1011084, 1073531, 75.0, 125.0, typeof(IronIngot), 1044036, 20, - 1044037); - AddRes(index, typeof(DarkSapphire), 1032690, 1, 1044240); - AddRecipe(index, 40); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(SilverEtchedMace), 1011084, 1073532, 75.0, 125.0, typeof(IronIngot), 1044036, 20, - 1044037); - AddRes(index, typeof(BlueDiamond), 1032696, 1, 1044240); - AddRecipe(index, 41); - SetNeededExpansion(index, Expansion.ML); - } - - index = AddCraft(typeof(DragonGloves), 1053114, 1029795, 68.9, 118.9, typeof(RedScales), 1060883, 16, 1060884); - SetUseSubRes2(index, true); - - index = AddCraft(typeof(DragonHelm), 1053114, 1029797, 72.6, 122.6, typeof(RedScales), 1060883, 20, 1060884); - SetUseSubRes2(index, true); - - index = AddCraft(typeof(DragonLegs), 1053114, 1029799, 78.8, 128.8, typeof(RedScales), 1060883, 28, 1060884); - SetUseSubRes2(index, true); - - index = AddCraft(typeof(DragonArms), 1053114, 1029815, 76.3, 126.3, typeof(RedScales), 1060883, 24, 1060884); - SetUseSubRes2(index, true); - - index = AddCraft(typeof(DragonChest), 1053114, 1029793, 85.0, 135.0, typeof(RedScales), 1060883, 36, 1060884); - SetUseSubRes2(index, true); - - // Set the overridable material - SetSubRes(typeof(IronIngot), 1044022); - - // Add every material you want the player to be able to choose from - // This will override the overridable material - AddSubRes(typeof(IronIngot), 1044022, 00.0, 1044036, 1044267); - AddSubRes(typeof(DullCopperIngot), 1044023, 65.0, 1044036, 1044268); - AddSubRes(typeof(ShadowIronIngot), 1044024, 70.0, 1044036, 1044268); - AddSubRes(typeof(CopperIngot), 1044025, 75.0, 1044036, 1044268); - AddSubRes(typeof(BronzeIngot), 1044026, 80.0, 1044036, 1044268); - AddSubRes(typeof(GoldIngot), 1044027, 85.0, 1044036, 1044268); - AddSubRes(typeof(AgapiteIngot), 1044028, 90.0, 1044036, 1044268); - AddSubRes(typeof(VeriteIngot), 1044029, 95.0, 1044036, 1044268); - AddSubRes(typeof(ValoriteIngot), 1044030, 99.0, 1044036, 1044268); - - SetSubRes2(typeof(RedScales), 1060875); - - AddSubRes2(typeof(RedScales), 1060875, 0.0, 1053137, 1044268); - AddSubRes2(typeof(YellowScales), 1060876, 0.0, 1053137, 1044268); - AddSubRes2(typeof(BlackScales), 1060877, 0.0, 1053137, 1044268); - AddSubRes2(typeof(GreenScales), 1060878, 0.0, 1053137, 1044268); - AddSubRes2(typeof(WhiteScales), 1060879, 0.0, 1053137, 1044268); - AddSubRes2(typeof(BlueScales), 1060880, 0.0, 1053137, 1044268); - - Resmelt = true; - Repair = true; - MarkOption = true; - CanEnhance = Core.AOS; - } - - // Delay to synchronize the sound with the hit on the anvil - private class InternalTimer : Timer - { - private readonly Mobile m_From; - - public InternalTimer(Mobile from) : base(TimeSpan.FromSeconds(0.7)) => m_From = from; - - protected override void OnTick() - { - m_From.PlaySound(0x2A); - } - } - } - - public class ForgeAttribute : Attribute - { - } - - public class AnvilAttribute : Attribute - { - } -} +using System; +using Server.Items; + +namespace Server.Engines.Craft +{ + public class DefBlacksmithy : CraftSystem + { + private static CraftSystem m_CraftSystem; + + private static readonly Type typeofAnvil = typeof(AnvilAttribute); + private static readonly Type typeofForge = typeof(ForgeAttribute); + + private DefBlacksmithy() : base(1, 1, 1.25) // base( 1, 2, 1.7 ) + { + /* + + base( MinCraftEffect, MaxCraftEffect, Delay ) + + MinCraftEffect : The minimum number of time the mobile will play the craft effect + MaxCraftEffect : The maximum number of time the mobile will play the craft effect + Delay : The delay between each craft effect + + Example: (3, 6, 1.7) would make the mobile do the PlayCraftEffect override + function between 3 and 6 time, with a 1.7 second delay each time. + + */ + } + + public override SkillName MainSkill => SkillName.Blacksmith; + + public override int GumpTitleNumber => 1044002; + + public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefBlacksmithy()); + + public override CraftECA ECA => CraftECA.ChanceMinusSixtyToFourtyFive; + + public override double GetChanceAtMin(CraftItem item) => 0.0; + + public static void CheckAnvilAndForge(Mobile from, int range, out bool anvil, out bool forge) + { + anvil = false; + forge = false; + + var map = from.Map; + + if (map == null) + return; + + var eable = map.GetItemsInRange(from.Location, range); + + foreach (var item in eable) + { + var type = item.GetType(); + + var isAnvil = type.IsDefined(typeofAnvil, false) || item.ItemID == 4015 || item.ItemID == 4016 || + item.ItemID == 0x2DD5 || item.ItemID == 0x2DD6; + var isForge = type.IsDefined(typeofForge, false) || item.ItemID == 4017 || + item.ItemID >= 6522 && item.ItemID <= 6569 || item.ItemID == 0x2DD8; + + if (isAnvil || isForge) + { + if (from.Z + 16 < item.Z || item.Z + 16 < from.Z || !from.InLOS(item)) + continue; + + anvil = anvil || isAnvil; + forge = forge || isForge; + + if (anvil && forge) + break; + } + } + + eable.Free(); + + for (var x = -range; (!anvil || !forge) && x <= range; ++x) + for (var y = -range; (!anvil || !forge) && y <= range; ++y) + { + var tiles = map.Tiles.GetStaticTiles(from.X + x, from.Y + y, true); + + for (var i = 0; (!anvil || !forge) && i < tiles.Length; ++i) + { + var id = tiles[i].ID; + + var isAnvil = id == 4015 || id == 4016 || id == 0x2DD5 || id == 0x2DD6; + var isForge = id == 4017 || id >= 6522 && id <= 6569 || id == 0x2DD8; + + if (isAnvil || isForge) + { + if (from.Z + 16 < tiles[i].Z || tiles[i].Z + 16 < from.Z || + !from.InLOS(new Point3D(from.X + x, from.Y + y, tiles[i].Z + tiles[i].Height / 2 + 1))) + continue; + + anvil = anvil || isAnvil; + forge = forge || isForge; + } + } + } + } + + public override int CanCraft(Mobile from, BaseTool tool, Type itemType) + { + if (tool?.Deleted != false || tool.UsesRemaining < 0) + return 1044038; // You have worn out your tool! + if (!BaseTool.CheckTool(tool, from)) + return 1048146; // If you have a tool equipped, you must use that tool. + if (!BaseTool.CheckAccessible(tool, from)) + return 1044263; // The tool must be on your person to use. + + CheckAnvilAndForge(from, 2, out var anvil, out var forge); + + if (anvil && forge) + return 0; + + return 1044267; // You must be near an anvil and a forge to smith items. + } + + public override void PlayCraftEffect(Mobile from) + { + // no animation, instant sound + // if (from.Body.Type == BodyType.Human && !from.Mounted) + // from.Animate( 9, 5, 1, true, false, 0 ); + // new InternalTimer( from ).Start(); + + from.PlaySound(0x2A); + } + + public override int PlayEndingEffect( + Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, + bool makersMark, CraftItem item + ) + { + if (toolBroken) + from.SendLocalizedMessage(1044038); // You have worn out your tool + + if (failed) + { + if (lostMaterial) + return 1044043; // You failed to create the item, and some of your materials are lost. + return 1044157; // You failed to create the item, but no materials were lost. + } + + if (quality == 0) + return 502785; // You were barely able to make this item. It's quality is below average. + if (makersMark && quality == 2) + return 1044156; // You create an exceptional quality item and affix your maker's mark. + if (quality == 2) + return 1044155; // You create an exceptional quality item. + return 1044154; // You create the item. + } + + public override void InitCraftList() + { + /* + Syntax for a SIMPLE craft item + AddCraft( ObjectType, Group, MinSkill, MaxSkill, ResourceType, Amount, Message ) + + ObjectType : The type of the object you want to add to the build list. + Group : The group in which the object will be showed in the craft menu. + MinSkill : The minimum of skill value + MaxSkill : The maximum of skill value + ResourceType : The type of the resource the mobile need to create the item + Amount : The amount of the ResourceType it need to create the item + Message : String or Int for Localized. The message that will be sent to the mobile, if the specified resource is missing. + + Syntax for a COMPLEX craft item. A complex item is an item that need either more than + only one skill, or more than only one resource. + + Coming soon.... + */ + + AddCraft(typeof(RingmailGloves), 1011076, 1025099, 12.0, 62.0, typeof(IronIngot), 1044036, 10, 1044037); + AddCraft(typeof(RingmailLegs), 1011076, 1025104, 19.4, 69.4, typeof(IronIngot), 1044036, 16, 1044037); + AddCraft(typeof(RingmailArms), 1011076, 1025103, 16.9, 66.9, typeof(IronIngot), 1044036, 14, 1044037); + AddCraft(typeof(RingmailChest), 1011076, 1025100, 21.9, 71.9, typeof(IronIngot), 1044036, 18, 1044037); + + AddCraft(typeof(ChainCoif), 1011077, 1025051, 14.5, 64.5, typeof(IronIngot), 1044036, 10, 1044037); + AddCraft(typeof(ChainLegs), 1011077, 1025054, 36.7, 86.7, typeof(IronIngot), 1044036, 18, 1044037); + AddCraft(typeof(ChainChest), 1011077, 1025055, 39.1, 89.1, typeof(IronIngot), 1044036, 20, 1044037); + + int index; + + AddCraft(typeof(PlateArms), 1011078, 1025136, 66.3, 116.3, typeof(IronIngot), 1044036, 18, 1044037); + AddCraft(typeof(PlateGloves), 1011078, 1025140, 58.9, 108.9, typeof(IronIngot), 1044036, 12, 1044037); + AddCraft(typeof(PlateGorget), 1011078, 1025139, 56.4, 106.4, typeof(IronIngot), 1044036, 10, 1044037); + AddCraft(typeof(PlateLegs), 1011078, 1025137, 68.8, 118.8, typeof(IronIngot), 1044036, 20, 1044037); + AddCraft(typeof(PlateChest), 1011078, 1046431, 75.0, 125.0, typeof(IronIngot), 1044036, 25, 1044037); + AddCraft(typeof(FemalePlateChest), 1011078, 1046430, 44.1, 94.1, typeof(IronIngot), 1044036, 20, 1044037); + + if (Core.AOS) // exact pre-aos functionality unknown + AddCraft(typeof(DragonBardingDeed), 1011078, 1053012, 72.5, 122.5, typeof(IronIngot), 1044036, 750, 1044037); + + if (Core.SE) + { + index = AddCraft(typeof(PlateMempo), 1011078, 1030180, 80.0, 130.0, typeof(IronIngot), 1044036, 18, 1044037); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(PlateDo), + 1011078, + 1030184, + 80.0, + 130.0, + typeof(IronIngot), + 1044036, + 28, + 1044037 + ); // Double check skill + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(PlateHiroSode), + 1011078, + 1030187, + 80.0, + 130.0, + typeof(IronIngot), + 1044036, + 16, + 1044037 + ); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(PlateSuneate), + 1011078, + 1030195, + 65.0, + 115.0, + typeof(IronIngot), + 1044036, + 20, + 1044037 + ); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(PlateHaidate), + 1011078, + 1030200, + 65.0, + 115.0, + typeof(IronIngot), + 1044036, + 20, + 1044037 + ); + SetNeededExpansion(index, Expansion.SE); + } + + AddCraft(typeof(Bascinet), 1011079, 1025132, 8.3, 58.3, typeof(IronIngot), 1044036, 15, 1044037); + AddCraft(typeof(CloseHelm), 1011079, 1025128, 37.9, 87.9, typeof(IronIngot), 1044036, 15, 1044037); + AddCraft(typeof(Helmet), 1011079, 1025130, 37.9, 87.9, typeof(IronIngot), 1044036, 15, 1044037); + AddCraft(typeof(NorseHelm), 1011079, 1025134, 37.9, 87.9, typeof(IronIngot), 1044036, 15, 1044037); + AddCraft(typeof(PlateHelm), 1011079, 1025138, 62.6, 112.6, typeof(IronIngot), 1044036, 15, 1044037); + + if (Core.SE) + { + index = AddCraft( + typeof(ChainHatsuburi), + 1011079, + 1030175, + 30.0, + 80.0, + typeof(IronIngot), + 1044036, + 20, + 1044037 + ); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(PlateHatsuburi), + 1011079, + 1030176, + 45.0, + 95.0, + typeof(IronIngot), + 1044036, + 20, + 1044037 + ); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(HeavyPlateJingasa), + 1011079, + 1030178, + 45.0, + 95.0, + typeof(IronIngot), + 1044036, + 20, + 1044037 + ); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(LightPlateJingasa), + 1011079, + 1030188, + 45.0, + 95.0, + typeof(IronIngot), + 1044036, + 20, + 1044037 + ); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(SmallPlateJingasa), + 1011079, + 1030191, + 45.0, + 95.0, + typeof(IronIngot), + 1044036, + 20, + 1044037 + ); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(DecorativePlateKabuto), + 1011079, + 1030179, + 90.0, + 140.0, + typeof(IronIngot), + 1044036, + 25, + 1044037 + ); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(PlateBattleKabuto), + 1011079, + 1030192, + 90.0, + 140.0, + typeof(IronIngot), + 1044036, + 25, + 1044037 + ); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(StandardPlateKabuto), + 1011079, + 1030196, + 90.0, + 140.0, + typeof(IronIngot), + 1044036, + 25, + 1044037 + ); + SetNeededExpansion(index, Expansion.SE); + + if (Core.ML) + { + index = AddCraft(typeof(Circlet), 1011079, 1032645, 62.1, 112.1, typeof(IronIngot), 1044036, 6, 1044037); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(RoyalCirclet), + 1011079, + 1032646, + 70.0, + 120.0, + typeof(IronIngot), + 1044036, + 6, + 1044037 + ); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(GemmedCirclet), + 1011079, + 1032647, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 6, + 1044037 + ); + AddRes(index, typeof(Tourmaline), 1044237, 1, 1044240); + AddRes(index, typeof(Amethyst), 1044236, 1, 1044240); + AddRes(index, typeof(BlueDiamond), 1032696, 1, 1044240); + SetNeededExpansion(index, Expansion.ML); + } + } + + AddCraft(typeof(Buckler), 1011080, 1027027, -25.0, 25.0, typeof(IronIngot), 1044036, 10, 1044037); + AddCraft(typeof(BronzeShield), 1011080, 1027026, -15.2, 34.8, typeof(IronIngot), 1044036, 12, 1044037); + AddCraft(typeof(HeaterShield), 1011080, 1027030, 24.3, 74.3, typeof(IronIngot), 1044036, 18, 1044037); + AddCraft(typeof(MetalShield), 1011080, 1027035, -10.2, 39.8, typeof(IronIngot), 1044036, 14, 1044037); + AddCraft(typeof(MetalKiteShield), 1011080, 1027028, 4.6, 54.6, typeof(IronIngot), 1044036, 16, 1044037); + AddCraft(typeof(WoodenKiteShield), 1011080, 1027032, -15.2, 34.8, typeof(IronIngot), 1044036, 8, 1044037); + + if (Core.AOS) + { + AddCraft(typeof(ChaosShield), 1011080, 1027107, 85.0, 135.0, typeof(IronIngot), 1044036, 25, 1044037); + AddCraft(typeof(OrderShield), 1011080, 1027108, 85.0, 135.0, typeof(IronIngot), 1044036, 25, 1044037); + } + + if (Core.AOS) + AddCraft(typeof(BoneHarvester), 1011081, 1029915, 33.0, 83.0, typeof(IronIngot), 1044036, 10, 1044037); + + AddCraft(typeof(Broadsword), 1011081, 1023934, 35.4, 85.4, typeof(IronIngot), 1044036, 10, 1044037); + + if (Core.AOS) + AddCraft(typeof(CrescentBlade), 1011081, 1029921, 45.0, 95.0, typeof(IronIngot), 1044036, 14, 1044037); + + AddCraft(typeof(Cutlass), 1011081, 1025185, 24.3, 74.3, typeof(IronIngot), 1044036, 8, 1044037); + AddCraft(typeof(Dagger), 1011081, 1023921, -0.4, 49.6, typeof(IronIngot), 1044036, 3, 1044037); + AddCraft(typeof(Katana), 1011081, 1025119, 44.1, 94.1, typeof(IronIngot), 1044036, 8, 1044037); + AddCraft(typeof(Kryss), 1011081, 1025121, 36.7, 86.7, typeof(IronIngot), 1044036, 8, 1044037); + AddCraft(typeof(Longsword), 1011081, 1023937, 28.0, 78.0, typeof(IronIngot), 1044036, 12, 1044037); + AddCraft(typeof(Scimitar), 1011081, 1025046, 31.7, 81.7, typeof(IronIngot), 1044036, 10, 1044037); + AddCraft(typeof(VikingSword), 1011081, 1025049, 24.3, 74.3, typeof(IronIngot), 1044036, 14, 1044037); + + if (Core.SE) + { + index = AddCraft(typeof(NoDachi), 1011081, 1030221, 75.0, 125.0, typeof(IronIngot), 1044036, 18, 1044037); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft(typeof(Wakizashi), 1011081, 1030223, 50.0, 100.0, typeof(IronIngot), 1044036, 8, 1044037); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft(typeof(Lajatang), 1011081, 1030226, 80.0, 130.0, typeof(IronIngot), 1044036, 25, 1044037); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft(typeof(Daisho), 1011081, 1030228, 60.0, 110.0, typeof(IronIngot), 1044036, 15, 1044037); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft(typeof(Tekagi), 1011081, 1030230, 55.0, 105.0, typeof(IronIngot), 1044036, 12, 1044037); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft(typeof(Shuriken), 1011081, 1030231, 45.0, 95.0, typeof(IronIngot), 1044036, 5, 1044037); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft(typeof(Kama), 1011081, 1030232, 40.0, 90.0, typeof(IronIngot), 1044036, 14, 1044037); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft(typeof(Sai), 1011081, 1030234, 50.0, 100.0, typeof(IronIngot), 1044036, 12, 1044037); + SetNeededExpansion(index, Expansion.SE); + + if (Core.ML) + { + index = AddCraft( + typeof(RadiantScimitar), + 1011081, + 1031571, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 15, + 1044037 + ); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(WarCleaver), + 1011081, + 1031567, + 70.0, + 120.0, + typeof(IronIngot), + 1044036, + 18, + 1044037 + ); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(ElvenSpellblade), + 1011081, + 1031564, + 70.0, + 120.0, + typeof(IronIngot), + 1044036, + 14, + 1044037 + ); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(AssassinSpike), + 1011081, + 1031565, + 70.0, + 120.0, + typeof(IronIngot), + 1044036, + 9, + 1044037 + ); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(Leafblade), + 1011081, + 1031566, + 70.0, + 120.0, + typeof(IronIngot), + 1044036, + 12, + 1044037 + ); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(RuneBlade), + 1011081, + 1031570, + 70.0, + 120.0, + typeof(IronIngot), + 1044036, + 15, + 1044037 + ); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(ElvenMachete), + 1011081, + 1031573, + 70.0, + 120.0, + typeof(IronIngot), + 1044036, + 14, + 1044037 + ); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(RuneCarvingKnife), + 1011081, + 1072915, + 70.0, + 120.0, + typeof(IronIngot), + 1044036, + 9, + 1044037 + ); + AddRes(index, typeof(DreadHornMane), 1032682, 1, 1053098); + AddRes(index, typeof(Putrefication), 1032678, 10, 1053098); + AddRes(index, typeof(Muculent), 1032680, 10, 1053098); + AddRareRecipe(index, 0); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(ColdForgedBlade), + 1011081, + 1072916, + 70.0, + 120.0, + typeof(IronIngot), + 1044036, + 18, + 1044037 + ); + AddRes(index, typeof(GrizzledBones), 1032684, 1, 1053098); + AddRes(index, typeof(Taint), 1032684, 10, 1053098); + AddRes(index, typeof(Blight), 1032675, 10, 1053098); + AddRareRecipe(index, 1); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(OverseerSunderedBlade), + 1011081, + 1072920, + 70.0, + 120.0, + typeof(IronIngot), + 1044036, + 15, + 1044037 + ); + AddRes(index, typeof(GrizzledBones), 1032684, 1, 1053098); + AddRes(index, typeof(Blight), 1032675, 10, 1053098); + AddRes(index, typeof(Scourge), 1032677, 10, 1053098); + AddRareRecipe(index, 2); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(LuminousRuneBlade), + 1011081, + 1072922, + 70.0, + 120.0, + typeof(IronIngot), + 1044036, + 15, + 1044037 + ); + AddRes(index, typeof(GrizzledBones), 1032684, 1, 1053098); + AddRes(index, typeof(Corruption), 1032676, 10, 1053098); + AddRes(index, typeof(Putrefication), 1032678, 10, 1053098); + AddRareRecipe(index, 3); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(TrueSpellblade), + 1011081, + 1073513, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 14, + 1044037 + ); + AddRes(index, typeof(BlueDiamond), 1032696, 1, 1044240); + AddRecipe(index, 4); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(IcySpellblade), + 1011081, + 1073514, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 14, + 1044037 + ); + AddRes(index, typeof(Turquoise), 1032691, 1, 1044240); + AddRecipe(index, 5); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(FierySpellblade), + 1011081, + 1073515, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 14, + 1044037 + ); + AddRes(index, typeof(FireRuby), 1032695, 1, 1044240); + AddRecipe(index, 6); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(SpellbladeOfDefense), + 1011081, + 1073516, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 18, + 1044037 + ); + AddRes(index, typeof(WhitePearl), 1032694, 1, 1044240); + AddRecipe(index, 7); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(TrueAssassinSpike), + 1011081, + 1073517, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 9, + 1044037 + ); + AddRes(index, typeof(DarkSapphire), 1032690, 1, 1044240); + AddRecipe(index, 8); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(ChargedAssassinSpike), + 1011081, + 1073518, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 9, + 1044037 + ); + AddRes(index, typeof(EcruCitrine), 1032693, 1, 1044240); + AddRecipe(index, 9); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(MagekillerAssassinSpike), + 1011081, + 1073519, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 9, + 1044037 + ); + AddRes(index, typeof(BrilliantAmber), 1032697, 1, 1044240); + AddRecipe(index, 10); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(WoundingAssassinSpike), + 1011081, + 1073520, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 9, + 1044037 + ); + AddRes(index, typeof(PerfectEmerald), 1032692, 1, 1044240); + AddRecipe(index, 11); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(TrueLeafblade), + 1011081, + 1073521, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 12, + 1044037 + ); + AddRes(index, typeof(BlueDiamond), 1032696, 1, 1044240); + AddRecipe(index, 12); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(Luckblade), + 1011081, + 1073522, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 12, + 1044037 + ); + AddRes(index, typeof(WhitePearl), 1032694, 1, 1044240); + AddRecipe(index, 13); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(MagekillerLeafblade), + 1011081, + 1073523, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 12, + 1044037 + ); + AddRes(index, typeof(FireRuby), 1032695, 1, 1044240); + AddRecipe(index, 14); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(LeafbladeOfEase), + 1011081, + 1073524, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 12, + 1044037 + ); + AddRes(index, typeof(PerfectEmerald), 1032692, 1, 1044240); + AddRecipe(index, 15); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(KnightsWarCleaver), + 1011081, + 1073525, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 18, + 1044037 + ); + AddRes(index, typeof(PerfectEmerald), 1032692, 1, 1044240); + AddRecipe(index, 16); + SetNeededExpansion(index, Expansion.ML); + + // TODO + index = AddCraft( + typeof(ButchersWarCleaver), + 1011081, + 1073526, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 18, + 1044037 + ); + AddRes(index, typeof(Turquoise), 1032691, 1, 1044240); + AddRecipe(index, 17); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(SerratedWarCleaver), + 1011081, + 1073527, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 18, + 1044037 + ); + AddRes(index, typeof(EcruCitrine), 1032693, 1, 1044240); + AddRecipe(index, 18); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(TrueWarCleaver), + 1011081, + 1073528, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 18, + 1044037 + ); + AddRes(index, typeof(BrilliantAmber), 1032697, 1, 1044240); + AddRecipe(index, 19); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(AdventurersMachete), + 1011081, + 1073533, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 14, + 1044037 + ); + AddRes(index, typeof(WhitePearl), 1032694, 1, 1044240); + AddRecipe(index, 20); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(OrcishMachete), + 1011081, + 1073534, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 14, + 1044037 + ); + AddRes(index, typeof(Scourge), 1072136, 1, 1042081); + AddRecipe(index, 21); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(MacheteOfDefense), + 1011081, + 1073535, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 14, + 1044037 + ); + AddRes(index, typeof(BrilliantAmber), 1032697, 1, 1044240); + AddRecipe(index, 22); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(DiseasedMachete), + 1011081, + 1073536, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 14, + 1044037 + ); + AddRes(index, typeof(Blight), 1072134, 1, 1042081); + AddRecipe(index, 23); + SetNeededExpansion(index, Expansion.ML); + + // TODO + index = AddCraft( + typeof(Runesabre), + 1011081, + 1073537, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 15, + 1044037 + ); + AddRes(index, typeof(Turquoise), 1032691, 1, 1044240); + AddRecipe(index, 24); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(MagesRuneBlade), + 1011081, + 1073538, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 15, + 1044037 + ); + AddRes(index, typeof(BlueDiamond), 1032696, 1, 1044240); + AddRecipe(index, 25); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(RuneBladeOfKnowledge), + 1011081, + 1073539, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 15, + 1044037 + ); + AddRes(index, typeof(EcruCitrine), 1032693, 1, 1044240); + AddRecipe(index, 26); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(CorruptedRuneBlade), + 1011081, + 1073540, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 15, + 1044037 + ); + AddRes(index, typeof(Corruption), 1072135, 1, 1042081); + AddRecipe(index, 27); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(TrueRadiantScimitar), + 1011081, + 1073541, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 15, + 1044037 + ); + AddRes(index, typeof(BrilliantAmber), 1032697, 1, 1044240); + AddRecipe(index, 28); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(DarkglowScimitar), + 1011081, + 1073542, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 15, + 1044037 + ); + AddRes(index, typeof(DarkSapphire), 1032690, 1, 1044240); + AddRecipe(index, 29); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(IcyScimitar), + 1011081, + 1073543, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 15, + 1044037 + ); + AddRes(index, typeof(DarkSapphire), 1032690, 1, 1044240); + AddRecipe(index, 30); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(TwinklingScimitar), + 1011081, + 1073544, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 15, + 1044037 + ); + AddRes(index, typeof(DarkSapphire), 1032690, 1, 1044240); + AddRecipe(index, 31); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(BoneMachete), + 1011081, + 1020526, + 45.0, + 95.0, + typeof(IronIngot), + 1044036, + 20, + 1044037 + ); + AddRes(index, typeof(Bone), 1049064, 6, 1049063); + AddQuestRecipe(index, 32); + SetNeededExpansion(index, Expansion.ML); + } + } + + AddCraft(typeof(Axe), 1011082, 1023913, 34.2, 84.2, typeof(IronIngot), 1044036, 14, 1044037); + AddCraft(typeof(BattleAxe), 1011082, 1023911, 30.5, 80.5, typeof(IronIngot), 1044036, 14, 1044037); + AddCraft(typeof(DoubleAxe), 1011082, 1023915, 29.3, 79.3, typeof(IronIngot), 1044036, 12, 1044037); + AddCraft(typeof(ExecutionersAxe), 1011082, 1023909, 34.2, 84.2, typeof(IronIngot), 1044036, 14, 1044037); + AddCraft(typeof(LargeBattleAxe), 1011082, 1025115, 28.0, 78.0, typeof(IronIngot), 1044036, 12, 1044037); + AddCraft(typeof(TwoHandedAxe), 1011082, 1025187, 33.0, 83.0, typeof(IronIngot), 1044036, 16, 1044037); + AddCraft(typeof(WarAxe), 1011082, 1025040, 39.1, 89.1, typeof(IronIngot), 1044036, 16, 1044037); + + if (Core.ML) + { + index = AddCraft(typeof(OrnateAxe), 1011082, 1031572, 70.0, 120.0, typeof(IronIngot), 1044036, 18, 1044037); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(GuardianAxe), + 1011082, + 1073545, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 15, + 1044037 + ); + AddRes(index, typeof(BlueDiamond), 1032696, 1, 1044240); + AddRecipe(index, 33); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft(typeof(SingingAxe), 1011082, 1073546, 75.0, 125.0, typeof(IronIngot), 1044036, 15, 1044037); + AddRes(index, typeof(BrilliantAmber), 1032697, 1, 1044240); + AddRecipe(index, 34); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(ThunderingAxe), + 1011082, + 1073547, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 15, + 1044037 + ); + AddRes(index, typeof(EcruCitrine), 1032693, 1, 1044240); + AddRecipe(index, 35); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(HeavyOrnateAxe), + 1011082, + 1073548, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 15, + 1044037 + ); + AddRes(index, typeof(Turquoise), 1032691, 1, 1044240); + AddRecipe(index, 36); + SetNeededExpansion(index, Expansion.ML); + } + + AddCraft(typeof(Bardiche), 1011083, 1023917, 31.7, 81.7, typeof(IronIngot), 1044036, 18, 1044037); + + if (Core.AOS) + AddCraft(typeof(BladedStaff), 1011083, 1029917, 40.0, 90.0, typeof(IronIngot), 1044036, 12, 1044037); + + if (Core.AOS) + AddCraft(typeof(DoubleBladedStaff), 1011083, 1029919, 45.0, 95.0, typeof(IronIngot), 1044036, 16, 1044037); + + AddCraft(typeof(Halberd), 1011083, 1025183, 39.1, 89.1, typeof(IronIngot), 1044036, 20, 1044037); + + if (Core.AOS) + AddCraft(typeof(Lance), 1011083, 1029920, 48.0, 98.0, typeof(IronIngot), 1044036, 20, 1044037); + + if (Core.AOS) + AddCraft(typeof(Pike), 1011083, 1029918, 47.0, 97.0, typeof(IronIngot), 1044036, 12, 1044037); + + AddCraft(typeof(ShortSpear), 1011083, 1025123, 45.3, 95.3, typeof(IronIngot), 1044036, 6, 1044037); + + if (Core.AOS) + AddCraft(typeof(Scythe), 1011083, 1029914, 39.0, 89.0, typeof(IronIngot), 1044036, 14, 1044037); + + AddCraft(typeof(Spear), 1011083, 1023938, 49.0, 99.0, typeof(IronIngot), 1044036, 12, 1044037); + AddCraft(typeof(WarFork), 1011083, 1025125, 42.9, 92.9, typeof(IronIngot), 1044036, 12, 1044037); + + // Not craftable (is this an AOS change ??) + // AddCraft( typeof( Pitchfork ), 1011083, 1023720, 36.1, 86.1, typeof( IronIngot ), 1044036, 12, 1044037 ); + + AddCraft(typeof(HammerPick), 1011084, 1025181, 34.2, 84.2, typeof(IronIngot), 1044036, 16, 1044037); + AddCraft(typeof(Mace), 1011084, 1023932, 14.5, 64.5, typeof(IronIngot), 1044036, 6, 1044037); + AddCraft(typeof(Maul), 1011084, 1025179, 19.4, 69.4, typeof(IronIngot), 1044036, 10, 1044037); + + if (Core.AOS) + AddCraft(typeof(Scepter), 1011084, 1029916, 21.4, 71.4, typeof(IronIngot), 1044036, 10, 1044037); + + AddCraft(typeof(WarMace), 1011084, 1025127, 28.0, 78.0, typeof(IronIngot), 1044036, 14, 1044037); + AddCraft(typeof(WarHammer), 1011084, 1025177, 34.2, 84.2, typeof(IronIngot), 1044036, 16, 1044037); + + if (Core.SE) + { + index = AddCraft(typeof(Tessen), 1011084, 1030222, 85.0, 135.0, typeof(IronIngot), 1044036, 16, 1044037); + AddSkill(index, SkillName.Tailoring, 50.0, 55.0); + AddRes(index, typeof(Cloth), 1044286, 10, 1044287); + SetNeededExpansion(index, Expansion.SE); + } + + if (Core.ML) + { + index = AddCraft( + typeof(DiamondMace), + 1011084, + 1031556, + 70.0, + 120.0, + typeof(IronIngot), + 1044036, + 20, + 1044037 + ); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(ShardThrasher), + 1011084, + 1072918, + 70.0, + 120.0, + typeof(IronIngot), + 1044036, + 20, + 1044037 + ); + AddRes(index, typeof(EyeOfTheTravesty), 1073126, 1, 1042081); + AddRes(index, typeof(Muculent), 1072139, 10, 1042081); + AddRes(index, typeof(Corruption), 1072135, 10, 1042081); + AddRareRecipe(index, 37); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft(typeof(RubyMace), 1011084, 1073529, 75.0, 125.0, typeof(IronIngot), 1044036, 20, 1044037); + AddRes(index, typeof(FireRuby), 1032695, 1, 1044240); + AddRecipe(index, 38); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(EmeraldMace), + 1011084, + 1073530, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 20, + 1044037 + ); + AddRes(index, typeof(PerfectEmerald), 1032692, 1, 1044240); + AddRecipe(index, 39); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(SapphireMace), + 1011084, + 1073531, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 20, + 1044037 + ); + AddRes(index, typeof(DarkSapphire), 1032690, 1, 1044240); + AddRecipe(index, 40); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(SilverEtchedMace), + 1011084, + 1073532, + 75.0, + 125.0, + typeof(IronIngot), + 1044036, + 20, + 1044037 + ); + AddRes(index, typeof(BlueDiamond), 1032696, 1, 1044240); + AddRecipe(index, 41); + SetNeededExpansion(index, Expansion.ML); + } + + index = AddCraft(typeof(DragonGloves), 1053114, 1029795, 68.9, 118.9, typeof(RedScales), 1060883, 16, 1060884); + SetUseSubRes2(index, true); + + index = AddCraft(typeof(DragonHelm), 1053114, 1029797, 72.6, 122.6, typeof(RedScales), 1060883, 20, 1060884); + SetUseSubRes2(index, true); + + index = AddCraft(typeof(DragonLegs), 1053114, 1029799, 78.8, 128.8, typeof(RedScales), 1060883, 28, 1060884); + SetUseSubRes2(index, true); + + index = AddCraft(typeof(DragonArms), 1053114, 1029815, 76.3, 126.3, typeof(RedScales), 1060883, 24, 1060884); + SetUseSubRes2(index, true); + + index = AddCraft(typeof(DragonChest), 1053114, 1029793, 85.0, 135.0, typeof(RedScales), 1060883, 36, 1060884); + SetUseSubRes2(index, true); + + // Set the overridable material + SetSubRes(typeof(IronIngot), 1044022); + + // Add every material you want the player to be able to choose from + // This will override the overridable material + AddSubRes(typeof(IronIngot), 1044022, 00.0, 1044036, 1044267); + AddSubRes(typeof(DullCopperIngot), 1044023, 65.0, 1044036, 1044268); + AddSubRes(typeof(ShadowIronIngot), 1044024, 70.0, 1044036, 1044268); + AddSubRes(typeof(CopperIngot), 1044025, 75.0, 1044036, 1044268); + AddSubRes(typeof(BronzeIngot), 1044026, 80.0, 1044036, 1044268); + AddSubRes(typeof(GoldIngot), 1044027, 85.0, 1044036, 1044268); + AddSubRes(typeof(AgapiteIngot), 1044028, 90.0, 1044036, 1044268); + AddSubRes(typeof(VeriteIngot), 1044029, 95.0, 1044036, 1044268); + AddSubRes(typeof(ValoriteIngot), 1044030, 99.0, 1044036, 1044268); + + SetSubRes2(typeof(RedScales), 1060875); + + AddSubRes2(typeof(RedScales), 1060875, 0.0, 1053137, 1044268); + AddSubRes2(typeof(YellowScales), 1060876, 0.0, 1053137, 1044268); + AddSubRes2(typeof(BlackScales), 1060877, 0.0, 1053137, 1044268); + AddSubRes2(typeof(GreenScales), 1060878, 0.0, 1053137, 1044268); + AddSubRes2(typeof(WhiteScales), 1060879, 0.0, 1053137, 1044268); + AddSubRes2(typeof(BlueScales), 1060880, 0.0, 1053137, 1044268); + + Resmelt = true; + Repair = true; + MarkOption = true; + CanEnhance = Core.AOS; + } + + // Delay to synchronize the sound with the hit on the anvil + private class InternalTimer : Timer + { + private readonly Mobile m_From; + + public InternalTimer(Mobile from) : base(TimeSpan.FromSeconds(0.7)) => m_From = from; + + protected override void OnTick() + { + m_From.PlaySound(0x2A); + } + } + } + + public class ForgeAttribute : Attribute + { + } + + public class AnvilAttribute : Attribute + { + } +} diff --git a/Projects/UOContent/Engines/Craft/DefBowFletching.cs b/Projects/UOContent/Engines/Craft/DefBowFletching.cs index aef47c32c..a662ebc7b 100644 --- a/Projects/UOContent/Engines/Craft/DefBowFletching.cs +++ b/Projects/UOContent/Engines/Craft/DefBowFletching.cs @@ -1,203 +1,241 @@ -using System; -using Server.Items; - -namespace Server.Engines.Craft -{ - public class DefBowFletching : CraftSystem - { - private static CraftSystem m_CraftSystem; - - private DefBowFletching() : base(1, 1, 1.25) // base( 1, 2, 1.7 ) - { - } - - public override SkillName MainSkill => SkillName.Fletching; - - public override int GumpTitleNumber => 1044006; - - public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefBowFletching()); - - public override CraftECA ECA => CraftECA.FiftyPercentChanceMinusTenPercent; - - public override double GetChanceAtMin(CraftItem item) => 0.5; - - public override int CanCraft(Mobile from, BaseTool tool, Type itemType) - { - if (tool?.Deleted != false || tool.UsesRemaining < 0) - return 1044038; // You have worn out your tool! - if (!BaseTool.CheckAccessible(tool, from)) - return 1044263; // The tool must be on your person to use. - - return 0; - } - - public override void PlayCraftEffect(Mobile from) - { - // no animation - // if (from.Body.Type == BodyType.Human && !from.Mounted) - // from.Animate( 33, 5, 1, true, false, 0 ); - - from.PlaySound(0x55); - } - - public override int PlayEndingEffect(Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, - bool makersMark, CraftItem item) - { - if (toolBroken) - from.SendLocalizedMessage(1044038); // You have worn out your tool - - if (failed) - { - if (lostMaterial) - return 1044043; // You failed to create the item, and some of your materials are lost. - return 1044157; // You failed to create the item, but no materials were lost. - } - - if (quality == 0) - return 502785; // You were barely able to make this item. It's quality is below average. - if (makersMark && quality == 2) - return 1044156; // You create an exceptional quality item and affix your maker's mark. - if (quality == 2) - return 1044155; // You create an exceptional quality item. - return 1044154; // You create the item. - } - - public override void InitCraftList() - { - int index; - - // Materials - AddCraft(typeof(Kindling), 1044457, 1023553, 0.0, 00.0, typeof(Log), 1044041, 1, 1044351); - - index = AddCraft(typeof(Shaft), 1044457, 1027124, 0.0, 40.0, typeof(Log), 1044041, 1, 1044351); - SetUseAllRes(index, true); - - // Ammunition - index = AddCraft(typeof(Arrow), 1044565, 1023903, 0.0, 40.0, typeof(Shaft), 1044560, 1, 1044561); - AddRes(index, typeof(Feather), 1044562, 1, 1044563); - SetUseAllRes(index, true); - - index = AddCraft(typeof(Bolt), 1044565, 1027163, 0.0, 40.0, typeof(Shaft), 1044560, 1, 1044561); - AddRes(index, typeof(Feather), 1044562, 1, 1044563); - SetUseAllRes(index, true); - - if (Core.SE) - { - index = AddCraft(typeof(FukiyaDarts), 1044565, 1030246, 50.0, 90.0, typeof(Log), 1044041, 1, 1044351); - SetUseAllRes(index, true); - SetNeededExpansion(index, Expansion.SE); - } - - // Weapons - AddCraft(typeof(Bow), 1044566, 1025042, 30.0, 70.0, typeof(Log), 1044041, 7, 1044351); - AddCraft(typeof(Crossbow), 1044566, 1023919, 60.0, 100.0, typeof(Log), 1044041, 7, 1044351); - AddCraft(typeof(HeavyCrossbow), 1044566, 1025117, 80.0, 120.0, typeof(Log), 1044041, 10, 1044351); - - if (Core.AOS) - { - AddCraft(typeof(CompositeBow), 1044566, 1029922, 70.0, 110.0, typeof(Log), 1044041, 7, 1044351); - AddCraft(typeof(RepeatingCrossbow), 1044566, 1029923, 90.0, 130.0, typeof(Log), 1044041, 10, 1044351); - } - - if (Core.SE) - { - index = AddCraft(typeof(Yumi), 1044566, 1030224, 90.0, 130.0, typeof(Log), 1044041, 10, 1044351); - SetNeededExpansion(index, Expansion.SE); - } - - if (Core.ML) - { - index = AddCraft(typeof(BlightGrippedLongbow), 1044566, 1072907, 75.0, 125.0, typeof(Log), 1044041, 20, - 1044351); - AddRes(index, typeof(LardOfParoxysmus), 1032681, 1, 1053098); - AddRes(index, typeof(Blight), 1032675, 10, 1053098); - AddRes(index, typeof(Corruption), 1032676, 10, 1053098); - AddRareRecipe(index, 200); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - /* TODO - index = AddCraft( typeof( FaerieFire ), 1044566, 1072908, 75.0, 125.0, typeof( Log ), 1044041, 20, 1044351 ); - AddRes( index, typeof( LardOfParoxysmus ), 1032681, 1, 1053098 ); - AddRes( index, typeof( Putrefication ), 1032678, 10, 1053098 ); - AddRes( index, typeof( Taint ), 1032679, 10, 1053098 ); - AddRareRecipe( index, 201 ); - ForceNonExceptional( index ); - SetNeededExpansion( index, Expansion.ML ); - */ - - index = AddCraft(typeof(SilvanisFeywoodBow), 1044566, 1072955, 75.0, 125.0, typeof(Log), 1044041, 20, - 1044351); - AddRes(index, typeof(LardOfParoxysmus), 1032681, 1, 1053098); - AddRes(index, typeof(Scourge), 1032677, 10, 1053098); - AddRes(index, typeof(Muculent), 1032680, 10, 1053098); - AddRareRecipe(index, 202); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - /* TODO - index = AddCraft( typeof( MischiefMaker ), 1044566, 1072910, 75.0, 125.0, typeof( Log ), 1044041, 15, 1044351 ); - AddRes( index, typeof( DreadHornMane ), 1032682, 1, 1053098 ); - AddRes( index, typeof( Corruption ), 1032676, 10, 1053098 ); - AddRes( index, typeof( Putrefication ), 1032678, 10, 1053098 ); - AddRareRecipe( index, 203 ); - ForceNonExceptional( index ); - SetNeededExpansion( index, Expansion.ML ); - */ - - index = AddCraft(typeof(TheNightReaper), 1044566, 1072912, 75.0, 125.0, typeof(Log), 1044041, 10, 1044351); - AddRes(index, typeof(DreadHornMane), 1032682, 1, 1053098); - AddRes(index, typeof(Blight), 1032675, 10, 1053098); - AddRes(index, typeof(Scourge), 1032677, 10, 1053098); - AddRareRecipe(index, 204); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(BarbedLongbow), 1044566, 1073505, 75.0, 125.0, typeof(Log), 1044041, 20, 1044351); - AddRes(index, typeof(FireRuby), 1026254, 1, 1053098); - AddRecipe(index, 205); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(SlayerLongbow), 1044566, 1073506, 75.0, 125.0, typeof(Log), 1044041, 20, 1044351); - AddRes(index, typeof(BrilliantAmber), 1026256, 1, 1053098); - AddRecipe(index, 206); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(FrozenLongbow), 1044566, 1073507, 75.0, 125.0, typeof(Log), 1044041, 20, 1044351); - AddRes(index, typeof(Turquoise), 1026250, 1, 1053098); - AddRecipe(index, 207); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(LongbowOfMight), 1044566, 1073508, 75.0, 125.0, typeof(Log), 1044041, 10, 1044351); - AddRes(index, typeof(BlueDiamond), 1026255, 1, 1053098); - AddRecipe(index, 208); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(RangersShortbow), 1044566, 1073509, 75.0, 125.0, typeof(Log), 1044041, 15, 1044351); - AddRes(index, typeof(PerfectEmerald), 1026251, 1, 1053098); - AddRecipe(index, 209); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(LightweightShortbow), 1044566, 1073510, 75.0, 125.0, typeof(Log), 1044041, 15, - 1044351); - AddRes(index, typeof(WhitePearl), 1026253, 1, 1053098); - AddRecipe(index, 210); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(MysticalShortbow), 1044566, 1073511, 75.0, 125.0, typeof(Log), 1044041, 15, 1044351); - AddRes(index, typeof(EcruCitrine), 1026252, 1, 1053098); - AddRecipe(index, 211); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(AssassinsShortbow), 1044566, 1073512, 75.0, 125.0, typeof(Log), 1044041, 15, - 1044351); - AddRes(index, typeof(DarkSapphire), 1026249, 1, 1053098); - AddRecipe(index, 212); - SetNeededExpansion(index, Expansion.ML); - } - - MarkOption = true; - Repair = Core.AOS; - } - } -} +using System; +using Server.Items; + +namespace Server.Engines.Craft +{ + public class DefBowFletching : CraftSystem + { + private static CraftSystem m_CraftSystem; + + private DefBowFletching() : base(1, 1, 1.25) // base( 1, 2, 1.7 ) + { + } + + public override SkillName MainSkill => SkillName.Fletching; + + public override int GumpTitleNumber => 1044006; + + public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefBowFletching()); + + public override CraftECA ECA => CraftECA.FiftyPercentChanceMinusTenPercent; + + public override double GetChanceAtMin(CraftItem item) => 0.5; + + public override int CanCraft(Mobile from, BaseTool tool, Type itemType) + { + if (tool?.Deleted != false || tool.UsesRemaining < 0) + return 1044038; // You have worn out your tool! + if (!BaseTool.CheckAccessible(tool, from)) + return 1044263; // The tool must be on your person to use. + + return 0; + } + + public override void PlayCraftEffect(Mobile from) + { + // no animation + // if (from.Body.Type == BodyType.Human && !from.Mounted) + // from.Animate( 33, 5, 1, true, false, 0 ); + + from.PlaySound(0x55); + } + + public override int PlayEndingEffect( + Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, + bool makersMark, CraftItem item + ) + { + if (toolBroken) + from.SendLocalizedMessage(1044038); // You have worn out your tool + + if (failed) + { + if (lostMaterial) + return 1044043; // You failed to create the item, and some of your materials are lost. + return 1044157; // You failed to create the item, but no materials were lost. + } + + if (quality == 0) + return 502785; // You were barely able to make this item. It's quality is below average. + if (makersMark && quality == 2) + return 1044156; // You create an exceptional quality item and affix your maker's mark. + if (quality == 2) + return 1044155; // You create an exceptional quality item. + return 1044154; // You create the item. + } + + public override void InitCraftList() + { + int index; + + // Materials + AddCraft(typeof(Kindling), 1044457, 1023553, 0.0, 00.0, typeof(Log), 1044041, 1, 1044351); + + index = AddCraft(typeof(Shaft), 1044457, 1027124, 0.0, 40.0, typeof(Log), 1044041, 1, 1044351); + SetUseAllRes(index, true); + + // Ammunition + index = AddCraft(typeof(Arrow), 1044565, 1023903, 0.0, 40.0, typeof(Shaft), 1044560, 1, 1044561); + AddRes(index, typeof(Feather), 1044562, 1, 1044563); + SetUseAllRes(index, true); + + index = AddCraft(typeof(Bolt), 1044565, 1027163, 0.0, 40.0, typeof(Shaft), 1044560, 1, 1044561); + AddRes(index, typeof(Feather), 1044562, 1, 1044563); + SetUseAllRes(index, true); + + if (Core.SE) + { + index = AddCraft(typeof(FukiyaDarts), 1044565, 1030246, 50.0, 90.0, typeof(Log), 1044041, 1, 1044351); + SetUseAllRes(index, true); + SetNeededExpansion(index, Expansion.SE); + } + + // Weapons + AddCraft(typeof(Bow), 1044566, 1025042, 30.0, 70.0, typeof(Log), 1044041, 7, 1044351); + AddCraft(typeof(Crossbow), 1044566, 1023919, 60.0, 100.0, typeof(Log), 1044041, 7, 1044351); + AddCraft(typeof(HeavyCrossbow), 1044566, 1025117, 80.0, 120.0, typeof(Log), 1044041, 10, 1044351); + + if (Core.AOS) + { + AddCraft(typeof(CompositeBow), 1044566, 1029922, 70.0, 110.0, typeof(Log), 1044041, 7, 1044351); + AddCraft(typeof(RepeatingCrossbow), 1044566, 1029923, 90.0, 130.0, typeof(Log), 1044041, 10, 1044351); + } + + if (Core.SE) + { + index = AddCraft(typeof(Yumi), 1044566, 1030224, 90.0, 130.0, typeof(Log), 1044041, 10, 1044351); + SetNeededExpansion(index, Expansion.SE); + } + + if (Core.ML) + { + index = AddCraft( + typeof(BlightGrippedLongbow), + 1044566, + 1072907, + 75.0, + 125.0, + typeof(Log), + 1044041, + 20, + 1044351 + ); + AddRes(index, typeof(LardOfParoxysmus), 1032681, 1, 1053098); + AddRes(index, typeof(Blight), 1032675, 10, 1053098); + AddRes(index, typeof(Corruption), 1032676, 10, 1053098); + AddRareRecipe(index, 200); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + /* TODO + index = AddCraft( typeof( FaerieFire ), 1044566, 1072908, 75.0, 125.0, typeof( Log ), 1044041, 20, 1044351 ); + AddRes( index, typeof( LardOfParoxysmus ), 1032681, 1, 1053098 ); + AddRes( index, typeof( Putrefication ), 1032678, 10, 1053098 ); + AddRes( index, typeof( Taint ), 1032679, 10, 1053098 ); + AddRareRecipe( index, 201 ); + ForceNonExceptional( index ); + SetNeededExpansion( index, Expansion.ML ); + */ + + index = AddCraft( + typeof(SilvanisFeywoodBow), + 1044566, + 1072955, + 75.0, + 125.0, + typeof(Log), + 1044041, + 20, + 1044351 + ); + AddRes(index, typeof(LardOfParoxysmus), 1032681, 1, 1053098); + AddRes(index, typeof(Scourge), 1032677, 10, 1053098); + AddRes(index, typeof(Muculent), 1032680, 10, 1053098); + AddRareRecipe(index, 202); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + /* TODO + index = AddCraft( typeof( MischiefMaker ), 1044566, 1072910, 75.0, 125.0, typeof( Log ), 1044041, 15, 1044351 ); + AddRes( index, typeof( DreadHornMane ), 1032682, 1, 1053098 ); + AddRes( index, typeof( Corruption ), 1032676, 10, 1053098 ); + AddRes( index, typeof( Putrefication ), 1032678, 10, 1053098 ); + AddRareRecipe( index, 203 ); + ForceNonExceptional( index ); + SetNeededExpansion( index, Expansion.ML ); + */ + + index = AddCraft(typeof(TheNightReaper), 1044566, 1072912, 75.0, 125.0, typeof(Log), 1044041, 10, 1044351); + AddRes(index, typeof(DreadHornMane), 1032682, 1, 1053098); + AddRes(index, typeof(Blight), 1032675, 10, 1053098); + AddRes(index, typeof(Scourge), 1032677, 10, 1053098); + AddRareRecipe(index, 204); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft(typeof(BarbedLongbow), 1044566, 1073505, 75.0, 125.0, typeof(Log), 1044041, 20, 1044351); + AddRes(index, typeof(FireRuby), 1026254, 1, 1053098); + AddRecipe(index, 205); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft(typeof(SlayerLongbow), 1044566, 1073506, 75.0, 125.0, typeof(Log), 1044041, 20, 1044351); + AddRes(index, typeof(BrilliantAmber), 1026256, 1, 1053098); + AddRecipe(index, 206); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft(typeof(FrozenLongbow), 1044566, 1073507, 75.0, 125.0, typeof(Log), 1044041, 20, 1044351); + AddRes(index, typeof(Turquoise), 1026250, 1, 1053098); + AddRecipe(index, 207); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft(typeof(LongbowOfMight), 1044566, 1073508, 75.0, 125.0, typeof(Log), 1044041, 10, 1044351); + AddRes(index, typeof(BlueDiamond), 1026255, 1, 1053098); + AddRecipe(index, 208); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft(typeof(RangersShortbow), 1044566, 1073509, 75.0, 125.0, typeof(Log), 1044041, 15, 1044351); + AddRes(index, typeof(PerfectEmerald), 1026251, 1, 1053098); + AddRecipe(index, 209); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(LightweightShortbow), + 1044566, + 1073510, + 75.0, + 125.0, + typeof(Log), + 1044041, + 15, + 1044351 + ); + AddRes(index, typeof(WhitePearl), 1026253, 1, 1053098); + AddRecipe(index, 210); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft(typeof(MysticalShortbow), 1044566, 1073511, 75.0, 125.0, typeof(Log), 1044041, 15, 1044351); + AddRes(index, typeof(EcruCitrine), 1026252, 1, 1053098); + AddRecipe(index, 211); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(AssassinsShortbow), + 1044566, + 1073512, + 75.0, + 125.0, + typeof(Log), + 1044041, + 15, + 1044351 + ); + AddRes(index, typeof(DarkSapphire), 1026249, 1, 1053098); + AddRecipe(index, 212); + SetNeededExpansion(index, Expansion.ML); + } + + MarkOption = true; + Repair = Core.AOS; + } + } +} diff --git a/Projects/UOContent/Engines/Craft/DefCarpentry.cs b/Projects/UOContent/Engines/Craft/DefCarpentry.cs index 8598fcb8f..6c918d785 100644 --- a/Projects/UOContent/Engines/Craft/DefCarpentry.cs +++ b/Projects/UOContent/Engines/Craft/DefCarpentry.cs @@ -1,536 +1,853 @@ -using System; -using Server.Items; - -namespace Server.Engines.Craft -{ - public class DefCarpentry : CraftSystem - { - private static CraftSystem m_CraftSystem; - - private DefCarpentry() : base(1, 1, 1.25) // base( 1, 1, 3.0 ) - { - } - - public override SkillName MainSkill => SkillName.Carpentry; - - public override int GumpTitleNumber => 1044004; - - public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefCarpentry()); - - public override double GetChanceAtMin(CraftItem item) => 0.5; - - public override int CanCraft(Mobile from, BaseTool tool, Type itemType) - { - if (tool?.Deleted != false || tool.UsesRemaining < 0) - return 1044038; // You have worn out your tool! - if (!BaseTool.CheckAccessible(tool, from)) - return 1044263; // The tool must be on your person to use. - - return 0; - } - - public override void PlayCraftEffect(Mobile from) - { - // no animation - // if (from.Body.Type == BodyType.Human && !from.Mounted) - // from.Animate( 9, 5, 1, true, false, 0 ); - - from.PlaySound(0x23D); - } - - public override int PlayEndingEffect(Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, - bool makersMark, CraftItem item) - { - if (toolBroken) - from.SendLocalizedMessage(1044038); // You have worn out your tool - - if (failed) - { - if (lostMaterial) - return 1044043; // You failed to create the item, and some of your materials are lost. - return 1044157; // You failed to create the item, but no materials were lost. - } - - if (quality == 0) - return 502785; // You were barely able to make this item. It's quality is below average. - if (makersMark && quality == 2) - return 1044156; // You create an exceptional quality item and affix your maker's mark. - if (quality == 2) - return 1044155; // You create an exceptional quality item. - return 1044154; // You create the item. - } - - public override void InitCraftList() - { - int index = -1; - - // Other Items - if (Core.Expansion == Expansion.AOS || Core.Expansion == Expansion.SE) - { - index = AddCraft(typeof(Board), 1044294, 1027127, 0.0, 0.0, typeof(Log), 1044466, 1, 1044465); - SetUseAllRes(index, true); - } - - AddCraft(typeof(BarrelStaves), 1044294, 1027857, 00.0, 25.0, typeof(Log), 1044041, 5, 1044351); - AddCraft(typeof(BarrelLid), 1044294, 1027608, 11.0, 36.0, typeof(Log), 1044041, 4, 1044351); - AddCraft(typeof(ShortMusicStand), 1044294, 1044313, 78.9, 103.9, typeof(Log), 1044041, 15, 1044351); - AddCraft(typeof(TallMusicStand), 1044294, 1044315, 81.5, 106.5, typeof(Log), 1044041, 20, 1044351); - AddCraft(typeof(Easel), 1044294, 1044317, 86.8, 111.8, typeof(Log), 1044041, 20, 1044351); - - if (Core.SE) - { - index = AddCraft(typeof(RedHangingLantern), 1044294, 1029412, 65.0, 90.0, typeof(Log), 1044041, 5, 1044351); - AddRes(index, typeof(BlankScroll), 1044377, 10, 1044378); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(WhiteHangingLantern), 1044294, 1029416, 65.0, 90.0, typeof(Log), 1044041, 5, - 1044351); - AddRes(index, typeof(BlankScroll), 1044377, 10, 1044378); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(ShojiScreen), 1044294, 1029423, 80.0, 105.0, typeof(Log), 1044041, 75, 1044351); - AddSkill(index, SkillName.Tailoring, 50.0, 55.0); - AddRes(index, typeof(Cloth), 1044286, 60, 1044287); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(BambooScreen), 1044294, 1029428, 80.0, 105.0, typeof(Log), 1044041, 75, 1044351); - AddSkill(index, SkillName.Tailoring, 50.0, 55.0); - AddRes(index, typeof(Cloth), 1044286, 60, 1044287); - SetNeededExpansion(index, Expansion.SE); - } - - if (Core.AOS) // Duplicate Entries to preserve ordering depending on era - { - index = AddCraft(typeof(FishingPole), 1044294, 1023519, 68.4, 93.4, typeof(Log), 1044041, 5, - 1044351); // This is in the categor of Other during AoS - AddSkill(index, SkillName.Tailoring, 40.0, 45.0); - AddRes(index, typeof(Cloth), 1044286, 5, 1044287); - } - - if (Core.ML) - { - index = AddCraft(typeof(RunedSwitch), 1044294, 1072896, 70.0, 120.0, typeof(Log), 1044041, 2, 1044351); - AddRes(index, typeof(EnchantedSwitch), 1072893, 1, 1053098); - AddRes(index, typeof(RunedPrism), 1073465, 1, 1053098); - AddRes(index, typeof(JeweledFiligree), 1072894, 1, 1053098); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(WarriorStatueSouthDeed), 1044294, 1072887, 0.0, 35.0, typeof(Log), 1044041, 250, - 1044351); - AddRecipe(index, 300); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(WarriorStatueEastDeed), 1044294, 1072888, 0.0, 35.0, typeof(Log), 1044041, 250, - 1044351); - AddRecipe(index, 301); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(SquirrelStatueSouthDeed), 1044294, 1072884, 0.0, 35.0, typeof(Log), 1044041, 250, - 1044351); - AddRecipe(index, 302); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(SquirrelStatueEastDeed), 1044294, 1073398, 0.0, 35.0, typeof(Log), 1044041, 250, - 1044351); - AddRecipe(index, 303); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(AcidProofRope), 1044294, 1074886, 80, 130.0, typeof(GreaterStrengthPotion), 1073466, - 2, 1044253); - AddRes(index, typeof(ProtectionScroll), 1044395, 1, 1053098); - AddRes(index, typeof(SwitchItem), 1032127, 1, 1053098); - AddRareRecipe(index, 304); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - } - - // Furniture - AddCraft(typeof(FootStool), 1044291, 1022910, 11.0, 36.0, typeof(Log), 1044041, 9, 1044351); - AddCraft(typeof(Stool), 1044291, 1022602, 11.0, 36.0, typeof(Log), 1044041, 9, 1044351); - AddCraft(typeof(BambooChair), 1044291, 1044300, 21.0, 46.0, typeof(Log), 1044041, 13, 1044351); - AddCraft(typeof(WoodenChair), 1044291, 1044301, 21.0, 46.0, typeof(Log), 1044041, 13, 1044351); - AddCraft(typeof(FancyWoodenChairCushion), 1044291, 1044302, 42.1, 67.1, typeof(Log), 1044041, 15, 1044351); - AddCraft(typeof(WoodenChairCushion), 1044291, 1044303, 42.1, 67.1, typeof(Log), 1044041, 13, 1044351); - AddCraft(typeof(WoodenBench), 1044291, 1022860, 52.6, 77.6, typeof(Log), 1044041, 17, 1044351); - AddCraft(typeof(WoodenThrone), 1044291, 1044304, 52.6, 77.6, typeof(Log), 1044041, 17, 1044351); - AddCraft(typeof(Throne), 1044291, 1044305, 73.6, 98.6, typeof(Log), 1044041, 19, 1044351); - AddCraft(typeof(Nightstand), 1044291, 1044306, 42.1, 67.1, typeof(Log), 1044041, 17, 1044351); - AddCraft(typeof(WritingTable), 1044291, 1022890, 63.1, 88.1, typeof(Log), 1044041, 17, 1044351); - AddCraft(typeof(YewWoodTable), 1044291, 1044307, 63.1, 88.1, typeof(Log), 1044041, 23, 1044351); - AddCraft(typeof(LargeTable), 1044291, 1044308, 84.2, 109.2, typeof(Log), 1044041, 27, 1044351); - - if (Core.SE) - { - index = AddCraft(typeof(ElegantLowTable), 1044291, 1030265, 80.0, 105.0, typeof(Log), 1044041, 35, 1044351); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(PlainLowTable), 1044291, 1030266, 80.0, 105.0, typeof(Log), 1044041, 35, 1044351); - SetNeededExpansion(index, Expansion.SE); - } - - if (Core.ML) - { - index = AddCraft(typeof(OrnateElvenChair), 1044291, 1072870, 80.0, 105.0, typeof(Log), 1044041, 30, 1044351); - AddRecipe(index, 305); - SetNeededExpansion(index, Expansion.ML); - } - - // Containers - AddCraft(typeof(WoodenBox), 1044292, 1023709, 21.0, 46.0, typeof(Log), 1044041, 10, 1044351); - AddCraft(typeof(SmallCrate), 1044292, 1044309, 10.0, 35.0, typeof(Log), 1044041, 8, 1044351); - AddCraft(typeof(MediumCrate), 1044292, 1044310, 31.0, 56.0, typeof(Log), 1044041, 15, 1044351); - AddCraft(typeof(LargeCrate), 1044292, 1044311, 47.3, 72.3, typeof(Log), 1044041, 18, 1044351); - AddCraft(typeof(WoodenChest), 1044292, 1023650, 73.6, 98.6, typeof(Log), 1044041, 20, 1044351); - AddCraft(typeof(EmptyBookcase), 1044292, 1022718, 31.5, 56.5, typeof(Log), 1044041, 25, 1044351); - AddCraft(typeof(FancyArmoire), 1044292, 1044312, 84.2, 109.2, typeof(Log), 1044041, 35, 1044351); - AddCraft(typeof(Armoire), 1044292, 1022643, 84.2, 109.2, typeof(Log), 1044041, 35, 1044351); - - if (Core.SE) - { - index = AddCraft(typeof(PlainWoodenChest), 1044292, 1030251, 90.0, 115.0, typeof(Log), 1044041, 30, 1044351); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(OrnateWoodenChest), 1044292, 1030253, 90.0, 115.0, typeof(Log), 1044041, 30, - 1044351); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(GildedWoodenChest), 1044292, 1030255, 90.0, 115.0, typeof(Log), 1044041, 30, - 1044351); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(WoodenFootLocker), 1044292, 1030257, 90.0, 115.0, typeof(Log), 1044041, 30, 1044351); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(FinishedWoodenChest), 1044292, 1030259, 90.0, 115.0, typeof(Log), 1044041, 30, - 1044351); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(TallCabinet), 1044292, 1030261, 90.0, 115.0, typeof(Log), 1044041, 35, 1044351); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(ShortCabinet), 1044292, 1030263, 90.0, 115.0, typeof(Log), 1044041, 35, 1044351); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(RedArmoire), 1044292, 1030328, 90.0, 115.0, typeof(Log), 1044041, 40, 1044351); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(ElegantArmoire), 1044292, 1030330, 90.0, 115.0, typeof(Log), 1044041, 40, 1044351); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(MapleArmoire), 1044292, 1030332, 90.0, 115.0, typeof(Log), 1044041, 40, 1044351); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(CherryArmoire), 1044292, 1030334, 90.0, 115.0, typeof(Log), 1044041, 40, 1044351); - SetNeededExpansion(index, Expansion.SE); - } - - index = AddCraft(typeof(Keg), 1044292, 1023711, 57.8, 82.8, typeof(BarrelStaves), 1044288, 3, 1044253); - AddRes(index, typeof(BarrelHoops), 1044289, 1, 1044253); - AddRes(index, typeof(BarrelLid), 1044251, 1, 1044253); - - if (Core.ML) - { - index = AddCraft(typeof(ArcaneBookshelfSouthDeed), 1044292, 1072871, 94.7, 119.7, typeof(Log), 1044041, 80, - 1044351); - AddRecipe(index, 306); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(ArcaneBookshelfEastDeed), 1044292, 1073371, 94.7, 119.7, typeof(Log), 1044041, 80, - 1044351); - AddRecipe(index, 307); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - /* TODO - index = AddCraft( typeof( OrnateElvenChestSouthDeed ), 1044292, 1072862, 94.7, 119.7, typeof( Log ), 1044041, 40, 1044351 ); - AddRecipe( index, 308 ); - ForceNonExceptional( index ); - SetNeededExpansion( index, Expansion.ML ); - - index = AddCraft( typeof( OrnateElvenChestEastDeed ), 1044292, 1073383, 94.7, 119.7, typeof( Log ), 1044041, 40, 1044351 ); - AddRecipe( index, 309 ); - ForceNonExceptional( index ); - SetNeededExpansion( index, Expansion.ML ); - */ - - index = AddCraft(typeof(ElvenDresserSouthDeed), 1044292, 1072864, 75.0, 100.0, typeof(Log), 1044041, 45, - 1044351); - AddRecipe(index, 310); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(ElvenDresserEastDeed), 1044292, 1073388, 75.0, 100.0, typeof(Log), 1044041, 45, - 1044351); - AddRecipe(index, 311); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - /* TODO - index = AddCraft( typeof( FancyElvenArmoire ), 1044292, 1072866, 80.0, 105.0, typeof( Log ), 1044041, 60, 1044351 ); - AddRecipe( index, 312 ); - ForceNonExceptional( index ); - SetNeededExpansion( index, Expansion.ML ); - */ - } - - // Staves and Shields - AddCraft(typeof(ShepherdsCrook), Core.ML ? 1044566 : 1044295, 1023713, 78.9, 103.9, typeof(Log), 1044041, 7, - 1044351); - AddCraft(typeof(QuarterStaff), Core.ML ? 1044566 : 1044295, 1023721, 73.6, 98.6, typeof(Log), 1044041, 6, - 1044351); - AddCraft(typeof(GnarledStaff), Core.ML ? 1044566 : 1044295, 1025112, 78.9, 103.9, typeof(Log), 1044041, 7, - 1044351); - AddCraft(typeof(WoodenShield), Core.ML ? 1062760 : 1044295, 1027034, 52.6, 77.6, typeof(Log), 1044041, 9, - 1044351); - - if (!Core.AOS) // Duplicate Entries to preserve ordering depending on era - { - index = AddCraft(typeof(FishingPole), Core.ML ? 1044294 : 1044295, 1023519, 68.4, 93.4, typeof(Log), 1044041, - 5, 1044351); // This is in the categor of Other during AoS - AddSkill(index, SkillName.Tailoring, 40.0, 45.0); - AddRes(index, typeof(Cloth), 1044286, 5, 1044287); - } - - if (Core.SE) - { - index = AddCraft(typeof(Bokuto), Core.ML ? 1044566 : 1044295, 1030227, 70.0, 95.0, typeof(Log), 1044041, 6, - 1044351); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(Fukiya), Core.ML ? 1044566 : 1044295, 1030229, 60.0, 85.0, typeof(Log), 1044041, 6, - 1044351); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(Tetsubo), Core.ML ? 1044566 : 1044295, 1030225, 80.0, 140.3, typeof(Log), 1044041, - 10, 1044351); - SetNeededExpansion(index, Expansion.SE); - } - - if (Core.ML) - { - index = AddCraft(typeof(PhantomStaff), 1044566, 1072919, 90.0, 130.0, typeof(Log), 1044041, 16, 1044351); - AddRes(index, typeof(DiseasedBark), 1032683, 1, 1053098); - AddRes(index, typeof(Putrefication), 1032678, 10, 1053098); - AddRes(index, typeof(Taint), 1032679, 10, 1053098); - AddRareRecipe(index, 313); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(ArcanistsWildStaff), 1044566, 1073549, 63.8, 113.8, typeof(Log), 1044041, 16, - 1044351); - AddRes(index, typeof(WhitePearl), 1026253, 1, 1053098); - AddRecipe(index, 314); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(AncientWildStaff), 1044566, 1073550, 63.8, 113.8, typeof(Log), 1044041, 16, 1044351); - AddRes(index, typeof(PerfectEmerald), 1026251, 1, 1053098); - AddRecipe(index, 315); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(ThornedWildStaff), 1044566, 1073551, 63.8, 113.8, typeof(Log), 1044041, 16, 1044351); - AddRes(index, typeof(FireRuby), 1026254, 1, 1053098); - AddRecipe(index, 316); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(HardenedWildStaff), 1044566, 1073552, 63.8, 113.8, typeof(Log), 1044041, 16, - 1044351); - AddRes(index, typeof(Turquoise), 1026250, 1, 1053098); - AddRecipe(index, 317); - SetNeededExpansion(index, Expansion.ML); - } - - // Armor - if (Core.ML) - { - index = AddCraft(typeof(IronwoodCrown), 1062760, 1072924, 85.0, 120.0, typeof(Log), 1044041, 10, 1044351); - AddRes(index, typeof(DiseasedBark), 1032683, 1, 1053098); - AddRes(index, typeof(Corruption), 1032676, 10, 1053098); - AddRes(index, typeof(Putrefication), 1032678, 10, 1053098); - AddRareRecipe(index, 318); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(BrambleCoat), 1062760, 1072925, 85.0, 120.0, typeof(Log), 1044041, 10, 1044351); - AddRes(index, typeof(DiseasedBark), 1032683, 1, 1053098); - AddRes(index, typeof(Taint), 1032679, 10, 1053098); - AddRes(index, typeof(Scourge), 1032677, 10, 1053098); - AddRareRecipe(index, 319); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - } - - // Instruments - index = AddCraft(typeof(LapHarp), 1044293, 1023762, 63.1, 88.1, typeof(Log), 1044041, 20, 1044351); - AddSkill(index, SkillName.Musicianship, 45.0, 50.0); - AddRes(index, typeof(Cloth), 1044286, 10, 1044287); - - index = AddCraft(typeof(Harp), 1044293, 1023761, 78.9, 103.9, typeof(Log), 1044041, 35, 1044351); - AddSkill(index, SkillName.Musicianship, 45.0, 50.0); - AddRes(index, typeof(Cloth), 1044286, 15, 1044287); - - index = AddCraft(typeof(Drums), 1044293, 1023740, 57.8, 82.8, typeof(Log), 1044041, 20, 1044351); - AddSkill(index, SkillName.Musicianship, 45.0, 50.0); - AddRes(index, typeof(Cloth), 1044286, 10, 1044287); - - index = AddCraft(typeof(Lute), 1044293, 1023763, 68.4, 93.4, typeof(Log), 1044041, 25, 1044351); - AddSkill(index, SkillName.Musicianship, 45.0, 50.0); - AddRes(index, typeof(Cloth), 1044286, 10, 1044287); - - index = AddCraft(typeof(Tambourine), 1044293, 1023741, 57.8, 82.8, typeof(Log), 1044041, 15, 1044351); - AddSkill(index, SkillName.Musicianship, 45.0, 50.0); - AddRes(index, typeof(Cloth), 1044286, 10, 1044287); - - index = AddCraft(typeof(TambourineTassel), 1044293, 1044320, 57.8, 82.8, typeof(Log), 1044041, 15, 1044351); - AddSkill(index, SkillName.Musicianship, 45.0, 50.0); - AddRes(index, typeof(Cloth), 1044286, 15, 1044287); - - if (Core.SE) - { - index = AddCraft(typeof(BambooFlute), 1044293, 1030247, 80.0, 105.0, typeof(Log), 1044041, 15, 1044351); - AddSkill(index, SkillName.Musicianship, 45.0, 50.0); - SetNeededExpansion(index, Expansion.SE); - } - - if (Core.ML) - { - index = AddCraft(typeof(TallElvenBedSouthDeed), 1044290, 1072858, 94.7, 119.7, typeof(Log), 1044041, 200, - 1044351); - AddSkill(index, SkillName.Tailoring, 75.0, 80.0); - AddRes(index, typeof(Cloth), 1044286, 100, 1044287); - AddRecipe(index, 320); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(TallElvenBedEastDeed), 1044290, 1072859, 94.7, 119.7, typeof(Log), 1044041, 200, - 1044351); - AddSkill(index, SkillName.Tailoring, 75.0, 80.0); - AddRes(index, typeof(Cloth), 1044286, 100, 1044287); - AddRecipe(index, 321); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - } - - // Misc - index = AddCraft(typeof(SmallBedSouthDeed), 1044290, 1044321, 94.7, 119.8, typeof(Log), 1044041, 100, 1044351); - AddSkill(index, SkillName.Tailoring, 75.0, 80.0); - AddRes(index, typeof(Cloth), 1044286, 100, 1044287); - index = AddCraft(typeof(SmallBedEastDeed), 1044290, 1044322, 94.7, 119.8, typeof(Log), 1044041, 100, 1044351); - AddSkill(index, SkillName.Tailoring, 75.0, 80.0); - AddRes(index, typeof(Cloth), 1044286, 100, 1044287); - index = AddCraft(typeof(LargeBedSouthDeed), 1044290, 1044323, 94.7, 119.8, typeof(Log), 1044041, 150, 1044351); - AddSkill(index, SkillName.Tailoring, 75.0, 80.0); - AddRes(index, typeof(Cloth), 1044286, 150, 1044287); - index = AddCraft(typeof(LargeBedEastDeed), 1044290, 1044324, 94.7, 119.8, typeof(Log), 1044041, 150, 1044351); - AddSkill(index, SkillName.Tailoring, 75.0, 80.0); - AddRes(index, typeof(Cloth), 1044286, 150, 1044287); - AddCraft(typeof(DartBoardSouthDeed), 1044290, 1044325, 15.7, 40.7, typeof(Log), 1044041, 5, 1044351); - AddCraft(typeof(DartBoardEastDeed), 1044290, 1044326, 15.7, 40.7, typeof(Log), 1044041, 5, 1044351); - AddCraft(typeof(BallotBoxDeed), 1044290, 1044327, 47.3, 72.3, typeof(Log), 1044041, 5, 1044351); - index = AddCraft(typeof(PentagramDeed), 1044290, 1044328, 100.0, 125.0, typeof(Log), 1044041, 100, 1044351); - AddSkill(index, SkillName.Magery, 75.0, 80.0); - AddRes(index, typeof(IronIngot), 1044036, 40, 1044037); - index = AddCraft(typeof(AbbatoirDeed), 1044290, 1044329, 100.0, 125.0, typeof(Log), 1044041, 100, 1044351); - AddSkill(index, SkillName.Magery, 50.0, 55.0); - AddRes(index, typeof(IronIngot), 1044036, 40, 1044037); - - if (Core.AOS) - { - AddCraft(typeof(PlayerBBEast), 1044290, 1062420, 85.0, 110.0, typeof(Log), 1044041, 50, 1044351); - AddCraft(typeof(PlayerBBSouth), 1044290, 1062421, 85.0, 110.0, typeof(Log), 1044041, 50, 1044351); - } - - // Blacksmithy - This changed to Anvils and Forges (1111809) for SA - index = AddCraft(typeof(SmallForgeDeed), 1044296, 1044330, 73.6, 98.6, typeof(Log), 1044041, 5, 1044351); - AddSkill(index, SkillName.Blacksmith, 75.0, 80.0); - AddRes(index, typeof(IronIngot), 1044036, 75, 1044037); - index = AddCraft(typeof(LargeForgeEastDeed), 1044296, 1044331, 78.9, 103.9, typeof(Log), 1044041, 5, 1044351); - AddSkill(index, SkillName.Blacksmith, 80.0, 85.0); - AddRes(index, typeof(IronIngot), 1044036, 100, 1044037); - index = AddCraft(typeof(LargeForgeSouthDeed), 1044296, 1044332, 78.9, 103.9, typeof(Log), 1044041, 5, 1044351); - AddSkill(index, SkillName.Blacksmith, 80.0, 85.0); - AddRes(index, typeof(IronIngot), 1044036, 100, 1044037); - index = AddCraft(typeof(AnvilEastDeed), 1044296, 1044333, 73.6, 98.6, typeof(Log), 1044041, 5, 1044351); - AddSkill(index, SkillName.Blacksmith, 75.0, 80.0); - AddRes(index, typeof(IronIngot), 1044036, 150, 1044037); - index = AddCraft(typeof(AnvilSouthDeed), 1044296, 1044334, 73.6, 98.6, typeof(Log), 1044041, 5, 1044351); - AddSkill(index, SkillName.Blacksmith, 75.0, 80.0); - AddRes(index, typeof(IronIngot), 1044036, 150, 1044037); - - // Training - index = AddCraft(typeof(TrainingDummyEastDeed), 1044297, 1044335, 68.4, 93.4, typeof(Log), 1044041, 55, 1044351); - AddSkill(index, SkillName.Tailoring, 50.0, 55.0); - AddRes(index, typeof(Cloth), 1044286, 60, 1044287); - index = AddCraft(typeof(TrainingDummySouthDeed), 1044297, 1044336, 68.4, 93.4, typeof(Log), 1044041, 55, - 1044351); - AddSkill(index, SkillName.Tailoring, 50.0, 55.0); - AddRes(index, typeof(Cloth), 1044286, 60, 1044287); - index = AddCraft(typeof(PickpocketDipEastDeed), 1044297, 1044337, 73.6, 98.6, typeof(Log), 1044041, 65, 1044351); - AddSkill(index, SkillName.Tailoring, 50.0, 55.0); - AddRes(index, typeof(Cloth), 1044286, 60, 1044287); - index = AddCraft(typeof(PickpocketDipSouthDeed), 1044297, 1044338, 73.6, 98.6, typeof(Log), 1044041, 65, - 1044351); - AddSkill(index, SkillName.Tailoring, 50.0, 55.0); - AddRes(index, typeof(Cloth), 1044286, 60, 1044287); - - // Tailoring - index = AddCraft(typeof(Dressform), 1044298, 1044339, 63.1, 88.1, typeof(Log), 1044041, 25, 1044351); - AddSkill(index, SkillName.Tailoring, 65.0, 70.0); - AddRes(index, typeof(Cloth), 1044286, 10, 1044287); - index = AddCraft(typeof(SpinningwheelEastDeed), 1044298, 1044341, 73.6, 98.6, typeof(Log), 1044041, 75, 1044351); - AddSkill(index, SkillName.Tailoring, 65.0, 70.0); - AddRes(index, typeof(Cloth), 1044286, 25, 1044287); - index = AddCraft(typeof(SpinningwheelSouthDeed), 1044298, 1044342, 73.6, 98.6, typeof(Log), 1044041, 75, - 1044351); - AddSkill(index, SkillName.Tailoring, 65.0, 70.0); - AddRes(index, typeof(Cloth), 1044286, 25, 1044287); - index = AddCraft(typeof(LoomEastDeed), 1044298, 1044343, 84.2, 109.2, typeof(Log), 1044041, 85, 1044351); - AddSkill(index, SkillName.Tailoring, 65.0, 70.0); - AddRes(index, typeof(Cloth), 1044286, 25, 1044287); - index = AddCraft(typeof(LoomSouthDeed), 1044298, 1044344, 84.2, 109.2, typeof(Log), 1044041, 85, 1044351); - AddSkill(index, SkillName.Tailoring, 65.0, 70.0); - AddRes(index, typeof(Cloth), 1044286, 25, 1044287); - - // Cooking - index = AddCraft(typeof(StoneOvenEastDeed), Core.ML ? 1044298 : 1044299, 1044345, 68.4, 93.4, typeof(Log), - 1044041, 85, 1044351); - AddSkill(index, SkillName.Tinkering, 50.0, 55.0); - AddRes(index, typeof(IronIngot), 1044036, 125, 1044037); - index = AddCraft(typeof(StoneOvenSouthDeed), Core.ML ? 1044298 : 1044299, 1044346, 68.4, 93.4, typeof(Log), - 1044041, 85, 1044351); - AddSkill(index, SkillName.Tinkering, 50.0, 55.0); - AddRes(index, typeof(IronIngot), 1044036, 125, 1044037); - index = AddCraft(typeof(FlourMillEastDeed), Core.ML ? 1044298 : 1044299, 1044347, 94.7, 119.7, typeof(Log), - 1044041, 100, 1044351); - AddSkill(index, SkillName.Tinkering, 50.0, 55.0); - AddRes(index, typeof(IronIngot), 1044036, 50, 1044037); - index = AddCraft(typeof(FlourMillSouthDeed), Core.ML ? 1044298 : 1044299, 1044348, 94.7, 119.7, typeof(Log), - 1044041, 100, 1044351); - AddSkill(index, SkillName.Tinkering, 50.0, 55.0); - AddRes(index, typeof(IronIngot), 1044036, 50, 1044037); - AddCraft(typeof(WaterTroughEastDeed), Core.ML ? 1044298 : 1044299, 1044349, 94.7, 119.7, typeof(Log), 1044041, - 150, 1044351); - AddCraft(typeof(WaterTroughSouthDeed), Core.ML ? 1044298 : 1044299, 1044350, 94.7, 119.7, typeof(Log), 1044041, - 150, 1044351); - - MarkOption = true; - Repair = Core.AOS; - - SetSubRes(typeof(Log), 1072643); - - // Add every material you want the player to be able to choose from - // This will override the overridable material TODO: Verify the required skill amount - AddSubRes(typeof(Log), 1072643, 00.0, 1044041, 1072652); - AddSubRes(typeof(OakLog), 1072644, 65.0, 1044041, 1072652); - AddSubRes(typeof(AshLog), 1072645, 80.0, 1044041, 1072652); - AddSubRes(typeof(YewLog), 1072646, 95.0, 1044041, 1072652); - AddSubRes(typeof(HeartwoodLog), 1072647, 100.0, 1044041, 1072652); - AddSubRes(typeof(BloodwoodLog), 1072648, 100.0, 1044041, 1072652); - AddSubRes(typeof(FrostwoodLog), 1072649, 100.0, 1044041, 1072652); - } - } -} +using System; +using Server.Items; + +namespace Server.Engines.Craft +{ + public class DefCarpentry : CraftSystem + { + private static CraftSystem m_CraftSystem; + + private DefCarpentry() : base(1, 1, 1.25) // base( 1, 1, 3.0 ) + { + } + + public override SkillName MainSkill => SkillName.Carpentry; + + public override int GumpTitleNumber => 1044004; + + public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefCarpentry()); + + public override double GetChanceAtMin(CraftItem item) => 0.5; + + public override int CanCraft(Mobile from, BaseTool tool, Type itemType) + { + if (tool?.Deleted != false || tool.UsesRemaining < 0) + return 1044038; // You have worn out your tool! + if (!BaseTool.CheckAccessible(tool, from)) + return 1044263; // The tool must be on your person to use. + + return 0; + } + + public override void PlayCraftEffect(Mobile from) + { + // no animation + // if (from.Body.Type == BodyType.Human && !from.Mounted) + // from.Animate( 9, 5, 1, true, false, 0 ); + + from.PlaySound(0x23D); + } + + public override int PlayEndingEffect( + Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, + bool makersMark, CraftItem item + ) + { + if (toolBroken) + from.SendLocalizedMessage(1044038); // You have worn out your tool + + if (failed) + { + if (lostMaterial) + return 1044043; // You failed to create the item, and some of your materials are lost. + return 1044157; // You failed to create the item, but no materials were lost. + } + + if (quality == 0) + return 502785; // You were barely able to make this item. It's quality is below average. + if (makersMark && quality == 2) + return 1044156; // You create an exceptional quality item and affix your maker's mark. + if (quality == 2) + return 1044155; // You create an exceptional quality item. + return 1044154; // You create the item. + } + + public override void InitCraftList() + { + var index = -1; + + // Other Items + if (Core.Expansion == Expansion.AOS || Core.Expansion == Expansion.SE) + { + index = AddCraft(typeof(Board), 1044294, 1027127, 0.0, 0.0, typeof(Log), 1044466, 1, 1044465); + SetUseAllRes(index, true); + } + + AddCraft(typeof(BarrelStaves), 1044294, 1027857, 00.0, 25.0, typeof(Log), 1044041, 5, 1044351); + AddCraft(typeof(BarrelLid), 1044294, 1027608, 11.0, 36.0, typeof(Log), 1044041, 4, 1044351); + AddCraft(typeof(ShortMusicStand), 1044294, 1044313, 78.9, 103.9, typeof(Log), 1044041, 15, 1044351); + AddCraft(typeof(TallMusicStand), 1044294, 1044315, 81.5, 106.5, typeof(Log), 1044041, 20, 1044351); + AddCraft(typeof(Easel), 1044294, 1044317, 86.8, 111.8, typeof(Log), 1044041, 20, 1044351); + + if (Core.SE) + { + index = AddCraft(typeof(RedHangingLantern), 1044294, 1029412, 65.0, 90.0, typeof(Log), 1044041, 5, 1044351); + AddRes(index, typeof(BlankScroll), 1044377, 10, 1044378); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(WhiteHangingLantern), + 1044294, + 1029416, + 65.0, + 90.0, + typeof(Log), + 1044041, + 5, + 1044351 + ); + AddRes(index, typeof(BlankScroll), 1044377, 10, 1044378); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft(typeof(ShojiScreen), 1044294, 1029423, 80.0, 105.0, typeof(Log), 1044041, 75, 1044351); + AddSkill(index, SkillName.Tailoring, 50.0, 55.0); + AddRes(index, typeof(Cloth), 1044286, 60, 1044287); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft(typeof(BambooScreen), 1044294, 1029428, 80.0, 105.0, typeof(Log), 1044041, 75, 1044351); + AddSkill(index, SkillName.Tailoring, 50.0, 55.0); + AddRes(index, typeof(Cloth), 1044286, 60, 1044287); + SetNeededExpansion(index, Expansion.SE); + } + + if (Core.AOS) // Duplicate Entries to preserve ordering depending on era + { + index = AddCraft( + typeof(FishingPole), + 1044294, + 1023519, + 68.4, + 93.4, + typeof(Log), + 1044041, + 5, + 1044351 + ); // This is in the categor of Other during AoS + AddSkill(index, SkillName.Tailoring, 40.0, 45.0); + AddRes(index, typeof(Cloth), 1044286, 5, 1044287); + } + + if (Core.ML) + { + index = AddCraft(typeof(RunedSwitch), 1044294, 1072896, 70.0, 120.0, typeof(Log), 1044041, 2, 1044351); + AddRes(index, typeof(EnchantedSwitch), 1072893, 1, 1053098); + AddRes(index, typeof(RunedPrism), 1073465, 1, 1053098); + AddRes(index, typeof(JeweledFiligree), 1072894, 1, 1053098); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(WarriorStatueSouthDeed), + 1044294, + 1072887, + 0.0, + 35.0, + typeof(Log), + 1044041, + 250, + 1044351 + ); + AddRecipe(index, 300); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(WarriorStatueEastDeed), + 1044294, + 1072888, + 0.0, + 35.0, + typeof(Log), + 1044041, + 250, + 1044351 + ); + AddRecipe(index, 301); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(SquirrelStatueSouthDeed), + 1044294, + 1072884, + 0.0, + 35.0, + typeof(Log), + 1044041, + 250, + 1044351 + ); + AddRecipe(index, 302); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(SquirrelStatueEastDeed), + 1044294, + 1073398, + 0.0, + 35.0, + typeof(Log), + 1044041, + 250, + 1044351 + ); + AddRecipe(index, 303); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(AcidProofRope), + 1044294, + 1074886, + 80, + 130.0, + typeof(GreaterStrengthPotion), + 1073466, + 2, + 1044253 + ); + AddRes(index, typeof(ProtectionScroll), 1044395, 1, 1053098); + AddRes(index, typeof(SwitchItem), 1032127, 1, 1053098); + AddRareRecipe(index, 304); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + } + + // Furniture + AddCraft(typeof(FootStool), 1044291, 1022910, 11.0, 36.0, typeof(Log), 1044041, 9, 1044351); + AddCraft(typeof(Stool), 1044291, 1022602, 11.0, 36.0, typeof(Log), 1044041, 9, 1044351); + AddCraft(typeof(BambooChair), 1044291, 1044300, 21.0, 46.0, typeof(Log), 1044041, 13, 1044351); + AddCraft(typeof(WoodenChair), 1044291, 1044301, 21.0, 46.0, typeof(Log), 1044041, 13, 1044351); + AddCraft(typeof(FancyWoodenChairCushion), 1044291, 1044302, 42.1, 67.1, typeof(Log), 1044041, 15, 1044351); + AddCraft(typeof(WoodenChairCushion), 1044291, 1044303, 42.1, 67.1, typeof(Log), 1044041, 13, 1044351); + AddCraft(typeof(WoodenBench), 1044291, 1022860, 52.6, 77.6, typeof(Log), 1044041, 17, 1044351); + AddCraft(typeof(WoodenThrone), 1044291, 1044304, 52.6, 77.6, typeof(Log), 1044041, 17, 1044351); + AddCraft(typeof(Throne), 1044291, 1044305, 73.6, 98.6, typeof(Log), 1044041, 19, 1044351); + AddCraft(typeof(Nightstand), 1044291, 1044306, 42.1, 67.1, typeof(Log), 1044041, 17, 1044351); + AddCraft(typeof(WritingTable), 1044291, 1022890, 63.1, 88.1, typeof(Log), 1044041, 17, 1044351); + AddCraft(typeof(YewWoodTable), 1044291, 1044307, 63.1, 88.1, typeof(Log), 1044041, 23, 1044351); + AddCraft(typeof(LargeTable), 1044291, 1044308, 84.2, 109.2, typeof(Log), 1044041, 27, 1044351); + + if (Core.SE) + { + index = AddCraft(typeof(ElegantLowTable), 1044291, 1030265, 80.0, 105.0, typeof(Log), 1044041, 35, 1044351); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft(typeof(PlainLowTable), 1044291, 1030266, 80.0, 105.0, typeof(Log), 1044041, 35, 1044351); + SetNeededExpansion(index, Expansion.SE); + } + + if (Core.ML) + { + index = AddCraft(typeof(OrnateElvenChair), 1044291, 1072870, 80.0, 105.0, typeof(Log), 1044041, 30, 1044351); + AddRecipe(index, 305); + SetNeededExpansion(index, Expansion.ML); + } + + // Containers + AddCraft(typeof(WoodenBox), 1044292, 1023709, 21.0, 46.0, typeof(Log), 1044041, 10, 1044351); + AddCraft(typeof(SmallCrate), 1044292, 1044309, 10.0, 35.0, typeof(Log), 1044041, 8, 1044351); + AddCraft(typeof(MediumCrate), 1044292, 1044310, 31.0, 56.0, typeof(Log), 1044041, 15, 1044351); + AddCraft(typeof(LargeCrate), 1044292, 1044311, 47.3, 72.3, typeof(Log), 1044041, 18, 1044351); + AddCraft(typeof(WoodenChest), 1044292, 1023650, 73.6, 98.6, typeof(Log), 1044041, 20, 1044351); + AddCraft(typeof(EmptyBookcase), 1044292, 1022718, 31.5, 56.5, typeof(Log), 1044041, 25, 1044351); + AddCraft(typeof(FancyArmoire), 1044292, 1044312, 84.2, 109.2, typeof(Log), 1044041, 35, 1044351); + AddCraft(typeof(Armoire), 1044292, 1022643, 84.2, 109.2, typeof(Log), 1044041, 35, 1044351); + + if (Core.SE) + { + index = AddCraft(typeof(PlainWoodenChest), 1044292, 1030251, 90.0, 115.0, typeof(Log), 1044041, 30, 1044351); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(OrnateWoodenChest), + 1044292, + 1030253, + 90.0, + 115.0, + typeof(Log), + 1044041, + 30, + 1044351 + ); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(GildedWoodenChest), + 1044292, + 1030255, + 90.0, + 115.0, + typeof(Log), + 1044041, + 30, + 1044351 + ); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft(typeof(WoodenFootLocker), 1044292, 1030257, 90.0, 115.0, typeof(Log), 1044041, 30, 1044351); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(FinishedWoodenChest), + 1044292, + 1030259, + 90.0, + 115.0, + typeof(Log), + 1044041, + 30, + 1044351 + ); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft(typeof(TallCabinet), 1044292, 1030261, 90.0, 115.0, typeof(Log), 1044041, 35, 1044351); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft(typeof(ShortCabinet), 1044292, 1030263, 90.0, 115.0, typeof(Log), 1044041, 35, 1044351); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft(typeof(RedArmoire), 1044292, 1030328, 90.0, 115.0, typeof(Log), 1044041, 40, 1044351); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft(typeof(ElegantArmoire), 1044292, 1030330, 90.0, 115.0, typeof(Log), 1044041, 40, 1044351); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft(typeof(MapleArmoire), 1044292, 1030332, 90.0, 115.0, typeof(Log), 1044041, 40, 1044351); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft(typeof(CherryArmoire), 1044292, 1030334, 90.0, 115.0, typeof(Log), 1044041, 40, 1044351); + SetNeededExpansion(index, Expansion.SE); + } + + index = AddCraft(typeof(Keg), 1044292, 1023711, 57.8, 82.8, typeof(BarrelStaves), 1044288, 3, 1044253); + AddRes(index, typeof(BarrelHoops), 1044289, 1, 1044253); + AddRes(index, typeof(BarrelLid), 1044251, 1, 1044253); + + if (Core.ML) + { + index = AddCraft( + typeof(ArcaneBookshelfSouthDeed), + 1044292, + 1072871, + 94.7, + 119.7, + typeof(Log), + 1044041, + 80, + 1044351 + ); + AddRecipe(index, 306); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(ArcaneBookshelfEastDeed), + 1044292, + 1073371, + 94.7, + 119.7, + typeof(Log), + 1044041, + 80, + 1044351 + ); + AddRecipe(index, 307); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + /* TODO + index = AddCraft( typeof( OrnateElvenChestSouthDeed ), 1044292, 1072862, 94.7, 119.7, typeof( Log ), 1044041, 40, 1044351 ); + AddRecipe( index, 308 ); + ForceNonExceptional( index ); + SetNeededExpansion( index, Expansion.ML ); + + index = AddCraft( typeof( OrnateElvenChestEastDeed ), 1044292, 1073383, 94.7, 119.7, typeof( Log ), 1044041, 40, 1044351 ); + AddRecipe( index, 309 ); + ForceNonExceptional( index ); + SetNeededExpansion( index, Expansion.ML ); + */ + + index = AddCraft( + typeof(ElvenDresserSouthDeed), + 1044292, + 1072864, + 75.0, + 100.0, + typeof(Log), + 1044041, + 45, + 1044351 + ); + AddRecipe(index, 310); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(ElvenDresserEastDeed), + 1044292, + 1073388, + 75.0, + 100.0, + typeof(Log), + 1044041, + 45, + 1044351 + ); + AddRecipe(index, 311); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + /* TODO + index = AddCraft( typeof( FancyElvenArmoire ), 1044292, 1072866, 80.0, 105.0, typeof( Log ), 1044041, 60, 1044351 ); + AddRecipe( index, 312 ); + ForceNonExceptional( index ); + SetNeededExpansion( index, Expansion.ML ); + */ + } + + // Staves and Shields + AddCraft( + typeof(ShepherdsCrook), + Core.ML ? 1044566 : 1044295, + 1023713, + 78.9, + 103.9, + typeof(Log), + 1044041, + 7, + 1044351 + ); + AddCraft( + typeof(QuarterStaff), + Core.ML ? 1044566 : 1044295, + 1023721, + 73.6, + 98.6, + typeof(Log), + 1044041, + 6, + 1044351 + ); + AddCraft( + typeof(GnarledStaff), + Core.ML ? 1044566 : 1044295, + 1025112, + 78.9, + 103.9, + typeof(Log), + 1044041, + 7, + 1044351 + ); + AddCraft( + typeof(WoodenShield), + Core.ML ? 1062760 : 1044295, + 1027034, + 52.6, + 77.6, + typeof(Log), + 1044041, + 9, + 1044351 + ); + + if (!Core.AOS) // Duplicate Entries to preserve ordering depending on era + { + index = AddCraft( + typeof(FishingPole), + Core.ML ? 1044294 : 1044295, + 1023519, + 68.4, + 93.4, + typeof(Log), + 1044041, + 5, + 1044351 + ); // This is in the categor of Other during AoS + AddSkill(index, SkillName.Tailoring, 40.0, 45.0); + AddRes(index, typeof(Cloth), 1044286, 5, 1044287); + } + + if (Core.SE) + { + index = AddCraft( + typeof(Bokuto), + Core.ML ? 1044566 : 1044295, + 1030227, + 70.0, + 95.0, + typeof(Log), + 1044041, + 6, + 1044351 + ); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(Fukiya), + Core.ML ? 1044566 : 1044295, + 1030229, + 60.0, + 85.0, + typeof(Log), + 1044041, + 6, + 1044351 + ); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(Tetsubo), + Core.ML ? 1044566 : 1044295, + 1030225, + 80.0, + 140.3, + typeof(Log), + 1044041, + 10, + 1044351 + ); + SetNeededExpansion(index, Expansion.SE); + } + + if (Core.ML) + { + index = AddCraft(typeof(PhantomStaff), 1044566, 1072919, 90.0, 130.0, typeof(Log), 1044041, 16, 1044351); + AddRes(index, typeof(DiseasedBark), 1032683, 1, 1053098); + AddRes(index, typeof(Putrefication), 1032678, 10, 1053098); + AddRes(index, typeof(Taint), 1032679, 10, 1053098); + AddRareRecipe(index, 313); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(ArcanistsWildStaff), + 1044566, + 1073549, + 63.8, + 113.8, + typeof(Log), + 1044041, + 16, + 1044351 + ); + AddRes(index, typeof(WhitePearl), 1026253, 1, 1053098); + AddRecipe(index, 314); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft(typeof(AncientWildStaff), 1044566, 1073550, 63.8, 113.8, typeof(Log), 1044041, 16, 1044351); + AddRes(index, typeof(PerfectEmerald), 1026251, 1, 1053098); + AddRecipe(index, 315); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft(typeof(ThornedWildStaff), 1044566, 1073551, 63.8, 113.8, typeof(Log), 1044041, 16, 1044351); + AddRes(index, typeof(FireRuby), 1026254, 1, 1053098); + AddRecipe(index, 316); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(HardenedWildStaff), + 1044566, + 1073552, + 63.8, + 113.8, + typeof(Log), + 1044041, + 16, + 1044351 + ); + AddRes(index, typeof(Turquoise), 1026250, 1, 1053098); + AddRecipe(index, 317); + SetNeededExpansion(index, Expansion.ML); + } + + // Armor + if (Core.ML) + { + index = AddCraft(typeof(IronwoodCrown), 1062760, 1072924, 85.0, 120.0, typeof(Log), 1044041, 10, 1044351); + AddRes(index, typeof(DiseasedBark), 1032683, 1, 1053098); + AddRes(index, typeof(Corruption), 1032676, 10, 1053098); + AddRes(index, typeof(Putrefication), 1032678, 10, 1053098); + AddRareRecipe(index, 318); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft(typeof(BrambleCoat), 1062760, 1072925, 85.0, 120.0, typeof(Log), 1044041, 10, 1044351); + AddRes(index, typeof(DiseasedBark), 1032683, 1, 1053098); + AddRes(index, typeof(Taint), 1032679, 10, 1053098); + AddRes(index, typeof(Scourge), 1032677, 10, 1053098); + AddRareRecipe(index, 319); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + } + + // Instruments + index = AddCraft(typeof(LapHarp), 1044293, 1023762, 63.1, 88.1, typeof(Log), 1044041, 20, 1044351); + AddSkill(index, SkillName.Musicianship, 45.0, 50.0); + AddRes(index, typeof(Cloth), 1044286, 10, 1044287); + + index = AddCraft(typeof(Harp), 1044293, 1023761, 78.9, 103.9, typeof(Log), 1044041, 35, 1044351); + AddSkill(index, SkillName.Musicianship, 45.0, 50.0); + AddRes(index, typeof(Cloth), 1044286, 15, 1044287); + + index = AddCraft(typeof(Drums), 1044293, 1023740, 57.8, 82.8, typeof(Log), 1044041, 20, 1044351); + AddSkill(index, SkillName.Musicianship, 45.0, 50.0); + AddRes(index, typeof(Cloth), 1044286, 10, 1044287); + + index = AddCraft(typeof(Lute), 1044293, 1023763, 68.4, 93.4, typeof(Log), 1044041, 25, 1044351); + AddSkill(index, SkillName.Musicianship, 45.0, 50.0); + AddRes(index, typeof(Cloth), 1044286, 10, 1044287); + + index = AddCraft(typeof(Tambourine), 1044293, 1023741, 57.8, 82.8, typeof(Log), 1044041, 15, 1044351); + AddSkill(index, SkillName.Musicianship, 45.0, 50.0); + AddRes(index, typeof(Cloth), 1044286, 10, 1044287); + + index = AddCraft(typeof(TambourineTassel), 1044293, 1044320, 57.8, 82.8, typeof(Log), 1044041, 15, 1044351); + AddSkill(index, SkillName.Musicianship, 45.0, 50.0); + AddRes(index, typeof(Cloth), 1044286, 15, 1044287); + + if (Core.SE) + { + index = AddCraft(typeof(BambooFlute), 1044293, 1030247, 80.0, 105.0, typeof(Log), 1044041, 15, 1044351); + AddSkill(index, SkillName.Musicianship, 45.0, 50.0); + SetNeededExpansion(index, Expansion.SE); + } + + if (Core.ML) + { + index = AddCraft( + typeof(TallElvenBedSouthDeed), + 1044290, + 1072858, + 94.7, + 119.7, + typeof(Log), + 1044041, + 200, + 1044351 + ); + AddSkill(index, SkillName.Tailoring, 75.0, 80.0); + AddRes(index, typeof(Cloth), 1044286, 100, 1044287); + AddRecipe(index, 320); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(TallElvenBedEastDeed), + 1044290, + 1072859, + 94.7, + 119.7, + typeof(Log), + 1044041, + 200, + 1044351 + ); + AddSkill(index, SkillName.Tailoring, 75.0, 80.0); + AddRes(index, typeof(Cloth), 1044286, 100, 1044287); + AddRecipe(index, 321); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + } + + // Misc + index = AddCraft(typeof(SmallBedSouthDeed), 1044290, 1044321, 94.7, 119.8, typeof(Log), 1044041, 100, 1044351); + AddSkill(index, SkillName.Tailoring, 75.0, 80.0); + AddRes(index, typeof(Cloth), 1044286, 100, 1044287); + index = AddCraft(typeof(SmallBedEastDeed), 1044290, 1044322, 94.7, 119.8, typeof(Log), 1044041, 100, 1044351); + AddSkill(index, SkillName.Tailoring, 75.0, 80.0); + AddRes(index, typeof(Cloth), 1044286, 100, 1044287); + index = AddCraft(typeof(LargeBedSouthDeed), 1044290, 1044323, 94.7, 119.8, typeof(Log), 1044041, 150, 1044351); + AddSkill(index, SkillName.Tailoring, 75.0, 80.0); + AddRes(index, typeof(Cloth), 1044286, 150, 1044287); + index = AddCraft(typeof(LargeBedEastDeed), 1044290, 1044324, 94.7, 119.8, typeof(Log), 1044041, 150, 1044351); + AddSkill(index, SkillName.Tailoring, 75.0, 80.0); + AddRes(index, typeof(Cloth), 1044286, 150, 1044287); + AddCraft(typeof(DartBoardSouthDeed), 1044290, 1044325, 15.7, 40.7, typeof(Log), 1044041, 5, 1044351); + AddCraft(typeof(DartBoardEastDeed), 1044290, 1044326, 15.7, 40.7, typeof(Log), 1044041, 5, 1044351); + AddCraft(typeof(BallotBoxDeed), 1044290, 1044327, 47.3, 72.3, typeof(Log), 1044041, 5, 1044351); + index = AddCraft(typeof(PentagramDeed), 1044290, 1044328, 100.0, 125.0, typeof(Log), 1044041, 100, 1044351); + AddSkill(index, SkillName.Magery, 75.0, 80.0); + AddRes(index, typeof(IronIngot), 1044036, 40, 1044037); + index = AddCraft(typeof(AbbatoirDeed), 1044290, 1044329, 100.0, 125.0, typeof(Log), 1044041, 100, 1044351); + AddSkill(index, SkillName.Magery, 50.0, 55.0); + AddRes(index, typeof(IronIngot), 1044036, 40, 1044037); + + if (Core.AOS) + { + AddCraft(typeof(PlayerBBEast), 1044290, 1062420, 85.0, 110.0, typeof(Log), 1044041, 50, 1044351); + AddCraft(typeof(PlayerBBSouth), 1044290, 1062421, 85.0, 110.0, typeof(Log), 1044041, 50, 1044351); + } + + // Blacksmithy - This changed to Anvils and Forges (1111809) for SA + index = AddCraft(typeof(SmallForgeDeed), 1044296, 1044330, 73.6, 98.6, typeof(Log), 1044041, 5, 1044351); + AddSkill(index, SkillName.Blacksmith, 75.0, 80.0); + AddRes(index, typeof(IronIngot), 1044036, 75, 1044037); + index = AddCraft(typeof(LargeForgeEastDeed), 1044296, 1044331, 78.9, 103.9, typeof(Log), 1044041, 5, 1044351); + AddSkill(index, SkillName.Blacksmith, 80.0, 85.0); + AddRes(index, typeof(IronIngot), 1044036, 100, 1044037); + index = AddCraft(typeof(LargeForgeSouthDeed), 1044296, 1044332, 78.9, 103.9, typeof(Log), 1044041, 5, 1044351); + AddSkill(index, SkillName.Blacksmith, 80.0, 85.0); + AddRes(index, typeof(IronIngot), 1044036, 100, 1044037); + index = AddCraft(typeof(AnvilEastDeed), 1044296, 1044333, 73.6, 98.6, typeof(Log), 1044041, 5, 1044351); + AddSkill(index, SkillName.Blacksmith, 75.0, 80.0); + AddRes(index, typeof(IronIngot), 1044036, 150, 1044037); + index = AddCraft(typeof(AnvilSouthDeed), 1044296, 1044334, 73.6, 98.6, typeof(Log), 1044041, 5, 1044351); + AddSkill(index, SkillName.Blacksmith, 75.0, 80.0); + AddRes(index, typeof(IronIngot), 1044036, 150, 1044037); + + // Training + index = AddCraft(typeof(TrainingDummyEastDeed), 1044297, 1044335, 68.4, 93.4, typeof(Log), 1044041, 55, 1044351); + AddSkill(index, SkillName.Tailoring, 50.0, 55.0); + AddRes(index, typeof(Cloth), 1044286, 60, 1044287); + index = AddCraft( + typeof(TrainingDummySouthDeed), + 1044297, + 1044336, + 68.4, + 93.4, + typeof(Log), + 1044041, + 55, + 1044351 + ); + AddSkill(index, SkillName.Tailoring, 50.0, 55.0); + AddRes(index, typeof(Cloth), 1044286, 60, 1044287); + index = AddCraft(typeof(PickpocketDipEastDeed), 1044297, 1044337, 73.6, 98.6, typeof(Log), 1044041, 65, 1044351); + AddSkill(index, SkillName.Tailoring, 50.0, 55.0); + AddRes(index, typeof(Cloth), 1044286, 60, 1044287); + index = AddCraft( + typeof(PickpocketDipSouthDeed), + 1044297, + 1044338, + 73.6, + 98.6, + typeof(Log), + 1044041, + 65, + 1044351 + ); + AddSkill(index, SkillName.Tailoring, 50.0, 55.0); + AddRes(index, typeof(Cloth), 1044286, 60, 1044287); + + // Tailoring + index = AddCraft(typeof(Dressform), 1044298, 1044339, 63.1, 88.1, typeof(Log), 1044041, 25, 1044351); + AddSkill(index, SkillName.Tailoring, 65.0, 70.0); + AddRes(index, typeof(Cloth), 1044286, 10, 1044287); + index = AddCraft(typeof(SpinningwheelEastDeed), 1044298, 1044341, 73.6, 98.6, typeof(Log), 1044041, 75, 1044351); + AddSkill(index, SkillName.Tailoring, 65.0, 70.0); + AddRes(index, typeof(Cloth), 1044286, 25, 1044287); + index = AddCraft( + typeof(SpinningwheelSouthDeed), + 1044298, + 1044342, + 73.6, + 98.6, + typeof(Log), + 1044041, + 75, + 1044351 + ); + AddSkill(index, SkillName.Tailoring, 65.0, 70.0); + AddRes(index, typeof(Cloth), 1044286, 25, 1044287); + index = AddCraft(typeof(LoomEastDeed), 1044298, 1044343, 84.2, 109.2, typeof(Log), 1044041, 85, 1044351); + AddSkill(index, SkillName.Tailoring, 65.0, 70.0); + AddRes(index, typeof(Cloth), 1044286, 25, 1044287); + index = AddCraft(typeof(LoomSouthDeed), 1044298, 1044344, 84.2, 109.2, typeof(Log), 1044041, 85, 1044351); + AddSkill(index, SkillName.Tailoring, 65.0, 70.0); + AddRes(index, typeof(Cloth), 1044286, 25, 1044287); + + // Cooking + index = AddCraft( + typeof(StoneOvenEastDeed), + Core.ML ? 1044298 : 1044299, + 1044345, + 68.4, + 93.4, + typeof(Log), + 1044041, + 85, + 1044351 + ); + AddSkill(index, SkillName.Tinkering, 50.0, 55.0); + AddRes(index, typeof(IronIngot), 1044036, 125, 1044037); + index = AddCraft( + typeof(StoneOvenSouthDeed), + Core.ML ? 1044298 : 1044299, + 1044346, + 68.4, + 93.4, + typeof(Log), + 1044041, + 85, + 1044351 + ); + AddSkill(index, SkillName.Tinkering, 50.0, 55.0); + AddRes(index, typeof(IronIngot), 1044036, 125, 1044037); + index = AddCraft( + typeof(FlourMillEastDeed), + Core.ML ? 1044298 : 1044299, + 1044347, + 94.7, + 119.7, + typeof(Log), + 1044041, + 100, + 1044351 + ); + AddSkill(index, SkillName.Tinkering, 50.0, 55.0); + AddRes(index, typeof(IronIngot), 1044036, 50, 1044037); + index = AddCraft( + typeof(FlourMillSouthDeed), + Core.ML ? 1044298 : 1044299, + 1044348, + 94.7, + 119.7, + typeof(Log), + 1044041, + 100, + 1044351 + ); + AddSkill(index, SkillName.Tinkering, 50.0, 55.0); + AddRes(index, typeof(IronIngot), 1044036, 50, 1044037); + AddCraft( + typeof(WaterTroughEastDeed), + Core.ML ? 1044298 : 1044299, + 1044349, + 94.7, + 119.7, + typeof(Log), + 1044041, + 150, + 1044351 + ); + AddCraft( + typeof(WaterTroughSouthDeed), + Core.ML ? 1044298 : 1044299, + 1044350, + 94.7, + 119.7, + typeof(Log), + 1044041, + 150, + 1044351 + ); + + MarkOption = true; + Repair = Core.AOS; + + SetSubRes(typeof(Log), 1072643); + + // Add every material you want the player to be able to choose from + // This will override the overridable material TODO: Verify the required skill amount + AddSubRes(typeof(Log), 1072643, 00.0, 1044041, 1072652); + AddSubRes(typeof(OakLog), 1072644, 65.0, 1044041, 1072652); + AddSubRes(typeof(AshLog), 1072645, 80.0, 1044041, 1072652); + AddSubRes(typeof(YewLog), 1072646, 95.0, 1044041, 1072652); + AddSubRes(typeof(HeartwoodLog), 1072647, 100.0, 1044041, 1072652); + AddSubRes(typeof(BloodwoodLog), 1072648, 100.0, 1044041, 1072652); + AddSubRes(typeof(FrostwoodLog), 1072649, 100.0, 1044041, 1072652); + } + } +} diff --git a/Projects/UOContent/Engines/Craft/DefCartography.cs b/Projects/UOContent/Engines/Craft/DefCartography.cs index 370664838..7d5bba0ed 100644 --- a/Projects/UOContent/Engines/Craft/DefCartography.cs +++ b/Projects/UOContent/Engines/Craft/DefCartography.cs @@ -1,67 +1,69 @@ -using System; -using Server.Items; - -namespace Server.Engines.Craft -{ - public class DefCartography : CraftSystem - { - private static CraftSystem m_CraftSystem; - - private DefCartography() : base(1, 1, 1.25) // base( 1, 1, 3.0 ) - { - } - - public override SkillName MainSkill => SkillName.Cartography; - - public override int GumpTitleNumber => 1044008; - - public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefCartography()); - - public override double GetChanceAtMin(CraftItem item) => 0.0; - - public override int CanCraft(Mobile from, BaseTool tool, Type itemType) - { - if (tool?.Deleted != false || tool.UsesRemaining < 0) - return 1044038; // You have worn out your tool! - if (!BaseTool.CheckAccessible(tool, from)) - return 1044263; // The tool must be on your person to use. - - return 0; - } - - public override void PlayCraftEffect(Mobile from) - { - from.PlaySound(0x249); - } - - public override int PlayEndingEffect(Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, - bool makersMark, CraftItem item) - { - if (toolBroken) - from.SendLocalizedMessage(1044038); // You have worn out your tool - - if (failed) - { - if (lostMaterial) - return 1044043; // You failed to create the item, and some of your materials are lost. - return 1044157; // You failed to create the item, but no materials were lost. - } - - if (quality == 0) - return 502785; // You were barely able to make this item. It's quality is below average. - if (makersMark && quality == 2) - return 1044156; // You create an exceptional quality item and affix your maker's mark. - if (quality == 2) - return 1044155; // You create an exceptional quality item. - return 1044154; // You create the item. - } - - public override void InitCraftList() - { - AddCraft(typeof(LocalMap), 1044448, 1015230, 10.0, 70.0, typeof(BlankMap), 1044449, 1, 1044450); - AddCraft(typeof(CityMap), 1044448, 1015231, 25.0, 85.0, typeof(BlankMap), 1044449, 1, 1044450); - AddCraft(typeof(SeaChart), 1044448, 1015232, 35.0, 95.0, typeof(BlankMap), 1044449, 1, 1044450); - AddCraft(typeof(WorldMap), 1044448, 1015233, 39.5, 99.5, typeof(BlankMap), 1044449, 1, 1044450); - } - } -} +using System; +using Server.Items; + +namespace Server.Engines.Craft +{ + public class DefCartography : CraftSystem + { + private static CraftSystem m_CraftSystem; + + private DefCartography() : base(1, 1, 1.25) // base( 1, 1, 3.0 ) + { + } + + public override SkillName MainSkill => SkillName.Cartography; + + public override int GumpTitleNumber => 1044008; + + public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefCartography()); + + public override double GetChanceAtMin(CraftItem item) => 0.0; + + public override int CanCraft(Mobile from, BaseTool tool, Type itemType) + { + if (tool?.Deleted != false || tool.UsesRemaining < 0) + return 1044038; // You have worn out your tool! + if (!BaseTool.CheckAccessible(tool, from)) + return 1044263; // The tool must be on your person to use. + + return 0; + } + + public override void PlayCraftEffect(Mobile from) + { + from.PlaySound(0x249); + } + + public override int PlayEndingEffect( + Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, + bool makersMark, CraftItem item + ) + { + if (toolBroken) + from.SendLocalizedMessage(1044038); // You have worn out your tool + + if (failed) + { + if (lostMaterial) + return 1044043; // You failed to create the item, and some of your materials are lost. + return 1044157; // You failed to create the item, but no materials were lost. + } + + if (quality == 0) + return 502785; // You were barely able to make this item. It's quality is below average. + if (makersMark && quality == 2) + return 1044156; // You create an exceptional quality item and affix your maker's mark. + if (quality == 2) + return 1044155; // You create an exceptional quality item. + return 1044154; // You create the item. + } + + public override void InitCraftList() + { + AddCraft(typeof(LocalMap), 1044448, 1015230, 10.0, 70.0, typeof(BlankMap), 1044449, 1, 1044450); + AddCraft(typeof(CityMap), 1044448, 1015231, 25.0, 85.0, typeof(BlankMap), 1044449, 1, 1044450); + AddCraft(typeof(SeaChart), 1044448, 1015232, 35.0, 95.0, typeof(BlankMap), 1044449, 1, 1044450); + AddCraft(typeof(WorldMap), 1044448, 1015233, 39.5, 99.5, typeof(BlankMap), 1044449, 1, 1044450); + } + } +} diff --git a/Projects/UOContent/Engines/Craft/DefCooking.cs b/Projects/UOContent/Engines/Craft/DefCooking.cs index d22978e5e..4864fd1dd 100644 --- a/Projects/UOContent/Engines/Craft/DefCooking.cs +++ b/Projects/UOContent/Engines/Craft/DefCooking.cs @@ -1,284 +1,421 @@ -using System; -using Server.Items; - -namespace Server.Engines.Craft -{ - public class DefCooking : CraftSystem - { - private static CraftSystem m_CraftSystem; - - private DefCooking() : base(1, 1, 1.25) // base( 1, 1, 1.5 ) - { - } - - public override SkillName MainSkill => SkillName.Cooking; - - public override int GumpTitleNumber => 1044003; - - public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefCooking()); - - public override CraftECA ECA => CraftECA.ChanceMinusSixtyToFourtyFive; - - public override double GetChanceAtMin(CraftItem item) => 0.0; - - public override int CanCraft(Mobile from, BaseTool tool, Type itemType) - { - if (tool?.Deleted != false || tool.UsesRemaining < 0) - return 1044038; // You have worn out your tool! - - if (!BaseTool.CheckAccessible(tool, from)) - return 1044263; // The tool must be on your person to use. - - return 0; - } - - public override void PlayCraftEffect(Mobile from) - { - } - - public override int PlayEndingEffect(Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, - bool makersMark, CraftItem item) - { - if (toolBroken) - from.SendLocalizedMessage(1044038); // You have worn out your tool - - if (failed) - { - if (lostMaterial) - return 1044043; // You failed to create the item, and some of your materials are lost. - return 1044157; // You failed to create the item, but no materials were lost. - } - - if (quality == 0) - return 502785; // You were barely able to make this item. It's quality is below average. - if (makersMark && quality == 2) - return 1044156; // You create an exceptional quality item and affix your maker's mark. - if (quality == 2) - return 1044155; // You create an exceptional quality item. - return 1044154; // You create the item. - } - - public override void InitCraftList() - { - int index; - - /* Begin Ingredients */ - index = AddCraft(typeof(SackFlour), 1044495, 1024153, 0.0, 100.0, typeof(WheatSheaf), 1044489, 2, 1044490); - SetNeedMill(index, true); - - index = AddCraft(typeof(Dough), 1044495, 1024157, 0.0, 100.0, typeof(SackFlour), 1044468, 1, 1044253); - AddRes(index, typeof(BaseBeverage), 1046458, 1, 1044253); - - index = AddCraft(typeof(SweetDough), 1044495, 1041340, 0.0, 100.0, typeof(Dough), 1044469, 1, 1044253); - AddRes(index, typeof(JarHoney), 1044472, 1, 1044253); - - index = AddCraft(typeof(CakeMix), 1044495, 1041002, 0.0, 100.0, typeof(SackFlour), 1044468, 1, 1044253); - AddRes(index, typeof(SweetDough), 1044475, 1, 1044253); - - index = AddCraft(typeof(CookieMix), 1044495, 1024159, 0.0, 100.0, typeof(JarHoney), 1044472, 1, 1044253); - AddRes(index, typeof(SweetDough), 1044475, 1, 1044253); - - if (Core.ML) - { - index = AddCraft(typeof(CocoaButter), 1044495, 1079998, 0.0, 100.0, typeof(CocoaPulp), 1080530, 1, 1044253); - SetItemHue(index, 0x457); - SetNeededExpansion(index, Expansion.ML); - SetNeedOven(index, true); - - index = AddCraft(typeof(CocoaLiquor), 1044495, 1079999, 0.0, 100.0, typeof(CocoaPulp), 1080530, 1, 1044253); - AddRes(index, typeof(EmptyPewterBowl), 1025629, 1, 1044253); - SetItemHue(index, 0x46A); - SetNeededExpansion(index, Expansion.ML); - SetNeedOven(index, true); - } - /* End Ingredients */ - - /* Begin Preparations */ - index = AddCraft(typeof(UnbakedQuiche), 1044496, 1041339, 0.0, 100.0, typeof(Dough), 1044469, 1, 1044253); - AddRes(index, typeof(Eggs), 1044477, 1, 1044253); - - // TODO: This must also support chicken and lamb legs - index = AddCraft(typeof(UnbakedMeatPie), 1044496, 1041338, 0.0, 100.0, typeof(Dough), 1044469, 1, 1044253); - AddRes(index, typeof(RawRibs), 1044482, 1, 1044253); - - index = AddCraft(typeof(UncookedSausagePizza), 1044496, 1041337, 0.0, 100.0, typeof(Dough), 1044469, 1, 1044253); - AddRes(index, typeof(Sausage), 1044483, 1, 1044253); - - index = AddCraft(typeof(UncookedCheesePizza), 1044496, 1041341, 0.0, 100.0, typeof(Dough), 1044469, 1, 1044253); - AddRes(index, typeof(CheeseWheel), 1044486, 1, 1044253); - - index = AddCraft(typeof(UnbakedFruitPie), 1044496, 1041334, 0.0, 100.0, typeof(Dough), 1044469, 1, 1044253); - AddRes(index, typeof(Pear), 1044481, 1, 1044253); - - index = AddCraft(typeof(UnbakedPeachCobbler), 1044496, 1041335, 0.0, 100.0, typeof(Dough), 1044469, 1, 1044253); - AddRes(index, typeof(Peach), 1044480, 1, 1044253); - - index = AddCraft(typeof(UnbakedApplePie), 1044496, 1041336, 0.0, 100.0, typeof(Dough), 1044469, 1, 1044253); - AddRes(index, typeof(Apple), 1044479, 1, 1044253); - - index = AddCraft(typeof(UnbakedPumpkinPie), 1044496, 1041342, 0.0, 100.0, typeof(Dough), 1044469, 1, 1044253); - AddRes(index, typeof(Pumpkin), 1044484, 1, 1044253); - - if (Core.SE) - { - index = AddCraft(typeof(GreenTea), 1044496, 1030315, 80.0, 130.0, typeof(GreenTeaBasket), 1030316, 1, - 1044253); - AddRes(index, typeof(BaseBeverage), 1046458, 1, 1044253); - SetNeededExpansion(index, Expansion.SE); - SetNeedOven(index, true); - - index = AddCraft(typeof(WasabiClumps), 1044496, 1029451, 70.0, 120.0, typeof(BaseBeverage), 1046458, 1, - 1044253); - AddRes(index, typeof(WoodenBowlOfPeas), 1025633, 3, 1044253); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(SushiRolls), 1044496, 1030303, 90.0, 120.0, typeof(BaseBeverage), 1046458, 1, - 1044253); - AddRes(index, typeof(RawFishSteak), 1044476, 10, 1044253); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(SushiPlatter), 1044496, 1030305, 90.0, 120.0, typeof(BaseBeverage), 1046458, 1, - 1044253); - AddRes(index, typeof(RawFishSteak), 1044476, 10, 1044253); - SetNeededExpansion(index, Expansion.SE); - } - - index = AddCraft(typeof(TribalPaint), 1044496, 1040000, Core.ML ? 55.0 : 80.0, Core.ML ? 105.0 : 80.0, - typeof(SackFlour), 1044468, 1, 1044253); - AddRes(index, typeof(TribalBerry), 1046460, 1, 1044253); - - if (Core.SE) - { - index = AddCraft(typeof(EggBomb), 1044496, 1030249, 90.0, 120.0, typeof(Eggs), 1044477, 1, 1044253); - AddRes(index, typeof(SackFlour), 1044468, 3, 1044253); - SetNeededExpansion(index, Expansion.SE); - } - /* End Preparations */ - - /* Begin Baking */ - index = AddCraft(typeof(BreadLoaf), 1044497, 1024156, 0.0, 100.0, typeof(Dough), 1044469, 1, 1044253); - SetNeedOven(index, true); - - index = AddCraft(typeof(Cookies), 1044497, 1025643, 0.0, 100.0, typeof(CookieMix), 1044474, 1, 1044253); - SetNeedOven(index, true); - - index = AddCraft(typeof(Cake), 1044497, 1022537, 0.0, 100.0, typeof(CakeMix), 1044471, 1, 1044253); - SetNeedOven(index, true); - - index = AddCraft(typeof(Muffins), 1044497, 1022539, 0.0, 100.0, typeof(SweetDough), 1044475, 1, 1044253); - SetNeedOven(index, true); - - index = AddCraft(typeof(Quiche), 1044497, 1041345, 0.0, 100.0, typeof(UnbakedQuiche), 1044518, 1, 1044253); - SetNeedOven(index, true); - - index = AddCraft(typeof(MeatPie), 1044497, 1041347, 0.0, 100.0, typeof(UnbakedMeatPie), 1044519, 1, 1044253); - SetNeedOven(index, true); - - index = AddCraft(typeof(SausagePizza), 1044497, 1044517, 0.0, 100.0, typeof(UncookedSausagePizza), 1044520, 1, - 1044253); - SetNeedOven(index, true); - - index = AddCraft(typeof(CheesePizza), 1044497, 1044516, 0.0, 100.0, typeof(UncookedCheesePizza), 1044521, 1, - 1044253); - SetNeedOven(index, true); - - index = AddCraft(typeof(FruitPie), 1044497, 1041346, 0.0, 100.0, typeof(UnbakedFruitPie), 1044522, 1, 1044253); - SetNeedOven(index, true); - - index = AddCraft(typeof(PeachCobbler), 1044497, 1041344, 0.0, 100.0, typeof(UnbakedPeachCobbler), 1044523, 1, - 1044253); - SetNeedOven(index, true); - - index = AddCraft(typeof(ApplePie), 1044497, 1041343, 0.0, 100.0, typeof(UnbakedApplePie), 1044524, 1, 1044253); - SetNeedOven(index, true); - - index = AddCraft(typeof(PumpkinPie), 1044497, 1041348, 0.0, 100.0, typeof(UnbakedPumpkinPie), 1046461, 1, - 1044253); - SetNeedOven(index, true); - - if (Core.SE) - { - index = AddCraft(typeof(MisoSoup), 1044497, 1030317, 60.0, 110.0, typeof(RawFishSteak), 1044476, 1, 1044253); - AddRes(index, typeof(BaseBeverage), 1046458, 1, 1044253); - SetNeededExpansion(index, Expansion.SE); - SetNeedOven(index, true); - - index = AddCraft(typeof(WhiteMisoSoup), 1044497, 1030318, 60.0, 110.0, typeof(RawFishSteak), 1044476, 1, - 1044253); - AddRes(index, typeof(BaseBeverage), 1046458, 1, 1044253); - SetNeededExpansion(index, Expansion.SE); - SetNeedOven(index, true); - - index = AddCraft(typeof(RedMisoSoup), 1044497, 1030319, 60.0, 110.0, typeof(RawFishSteak), 1044476, 1, - 1044253); - AddRes(index, typeof(BaseBeverage), 1046458, 1, 1044253); - SetNeededExpansion(index, Expansion.SE); - SetNeedOven(index, true); - - index = AddCraft(typeof(AwaseMisoSoup), 1044497, 1030320, 60.0, 110.0, typeof(RawFishSteak), 1044476, 1, - 1044253); - AddRes(index, typeof(BaseBeverage), 1046458, 1, 1044253); - SetNeededExpansion(index, Expansion.SE); - SetNeedOven(index, true); - } - /* End Baking */ - - /* Begin Barbecue */ - index = AddCraft(typeof(CookedBird), 1044498, 1022487, 0.0, 100.0, typeof(RawBird), 1044470, 1, 1044253); - SetNeedHeat(index, true); - SetUseAllRes(index, true); - - index = AddCraft(typeof(ChickenLeg), 1044498, 1025640, 0.0, 100.0, typeof(RawChickenLeg), 1044473, 1, 1044253); - SetNeedHeat(index, true); - SetUseAllRes(index, true); - - index = AddCraft(typeof(FishSteak), 1044498, 1022427, 0.0, 100.0, typeof(RawFishSteak), 1044476, 1, 1044253); - SetNeedHeat(index, true); - SetUseAllRes(index, true); - - index = AddCraft(typeof(FriedEggs), 1044498, 1022486, 0.0, 100.0, typeof(Eggs), 1044477, 1, 1044253); - SetNeedHeat(index, true); - SetUseAllRes(index, true); - - index = AddCraft(typeof(LambLeg), 1044498, 1025642, 0.0, 100.0, typeof(RawLambLeg), 1044478, 1, 1044253); - SetNeedHeat(index, true); - SetUseAllRes(index, true); - - index = AddCraft(typeof(Ribs), 1044498, 1022546, 0.0, 100.0, typeof(RawRibs), 1044485, 1, 1044253); - SetNeedHeat(index, true); - SetUseAllRes(index, true); - /* End Barbecue */ - - /* Begin Chocolatiering */ - if (Core.ML) - { - index = AddCraft(typeof(DarkChocolate), 1080001, 1079994, 15.0, 100.0, typeof(SackOfSugar), 1079997, 1, - 1044253); - AddRes(index, typeof(CocoaButter), 1079998, 1, 1044253); - AddRes(index, typeof(CocoaLiquor), 1079999, 1, 1044253); - SetItemHue(index, 0x465); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(MilkChocolate), 1080001, 1079995, 32.5, 107.5, typeof(SackOfSugar), 1079997, 1, - 1044253); - AddRes(index, typeof(CocoaButter), 1079998, 1, 1044253); - AddRes(index, typeof(CocoaLiquor), 1079999, 1, 1044253); - AddRes(index, typeof(BaseBeverage), 1022544, 1, 1044253); - SetBeverageType(index, BeverageType.Milk); - SetItemHue(index, 0x461); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(WhiteChocolate), 1080001, 1079996, 52.5, 127.5, typeof(SackOfSugar), 1079997, 1, - 1044253); - AddRes(index, typeof(CocoaButter), 1079998, 1, 1044253); - AddRes(index, typeof(Vanilla), 1080000, 1, 1044253); - AddRes(index, typeof(BaseBeverage), 1022544, 1, 1044253); - SetBeverageType(index, BeverageType.Milk); - SetItemHue(index, 0x47E); - SetNeededExpansion(index, Expansion.ML); - } - - /* End Chocolatiering */ - } - } -} +using System; +using Server.Items; + +namespace Server.Engines.Craft +{ + public class DefCooking : CraftSystem + { + private static CraftSystem m_CraftSystem; + + private DefCooking() : base(1, 1, 1.25) // base( 1, 1, 1.5 ) + { + } + + public override SkillName MainSkill => SkillName.Cooking; + + public override int GumpTitleNumber => 1044003; + + public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefCooking()); + + public override CraftECA ECA => CraftECA.ChanceMinusSixtyToFourtyFive; + + public override double GetChanceAtMin(CraftItem item) => 0.0; + + public override int CanCraft(Mobile from, BaseTool tool, Type itemType) + { + if (tool?.Deleted != false || tool.UsesRemaining < 0) + return 1044038; // You have worn out your tool! + + if (!BaseTool.CheckAccessible(tool, from)) + return 1044263; // The tool must be on your person to use. + + return 0; + } + + public override void PlayCraftEffect(Mobile from) + { + } + + public override int PlayEndingEffect( + Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, + bool makersMark, CraftItem item + ) + { + if (toolBroken) + from.SendLocalizedMessage(1044038); // You have worn out your tool + + if (failed) + { + if (lostMaterial) + return 1044043; // You failed to create the item, and some of your materials are lost. + return 1044157; // You failed to create the item, but no materials were lost. + } + + if (quality == 0) + return 502785; // You were barely able to make this item. It's quality is below average. + if (makersMark && quality == 2) + return 1044156; // You create an exceptional quality item and affix your maker's mark. + if (quality == 2) + return 1044155; // You create an exceptional quality item. + return 1044154; // You create the item. + } + + public override void InitCraftList() + { + int index; + + /* Begin Ingredients */ + index = AddCraft(typeof(SackFlour), 1044495, 1024153, 0.0, 100.0, typeof(WheatSheaf), 1044489, 2, 1044490); + SetNeedMill(index, true); + + index = AddCraft(typeof(Dough), 1044495, 1024157, 0.0, 100.0, typeof(SackFlour), 1044468, 1, 1044253); + AddRes(index, typeof(BaseBeverage), 1046458, 1, 1044253); + + index = AddCraft(typeof(SweetDough), 1044495, 1041340, 0.0, 100.0, typeof(Dough), 1044469, 1, 1044253); + AddRes(index, typeof(JarHoney), 1044472, 1, 1044253); + + index = AddCraft(typeof(CakeMix), 1044495, 1041002, 0.0, 100.0, typeof(SackFlour), 1044468, 1, 1044253); + AddRes(index, typeof(SweetDough), 1044475, 1, 1044253); + + index = AddCraft(typeof(CookieMix), 1044495, 1024159, 0.0, 100.0, typeof(JarHoney), 1044472, 1, 1044253); + AddRes(index, typeof(SweetDough), 1044475, 1, 1044253); + + if (Core.ML) + { + index = AddCraft(typeof(CocoaButter), 1044495, 1079998, 0.0, 100.0, typeof(CocoaPulp), 1080530, 1, 1044253); + SetItemHue(index, 0x457); + SetNeededExpansion(index, Expansion.ML); + SetNeedOven(index, true); + + index = AddCraft(typeof(CocoaLiquor), 1044495, 1079999, 0.0, 100.0, typeof(CocoaPulp), 1080530, 1, 1044253); + AddRes(index, typeof(EmptyPewterBowl), 1025629, 1, 1044253); + SetItemHue(index, 0x46A); + SetNeededExpansion(index, Expansion.ML); + SetNeedOven(index, true); + } + /* End Ingredients */ + + /* Begin Preparations */ + index = AddCraft(typeof(UnbakedQuiche), 1044496, 1041339, 0.0, 100.0, typeof(Dough), 1044469, 1, 1044253); + AddRes(index, typeof(Eggs), 1044477, 1, 1044253); + + // TODO: This must also support chicken and lamb legs + index = AddCraft(typeof(UnbakedMeatPie), 1044496, 1041338, 0.0, 100.0, typeof(Dough), 1044469, 1, 1044253); + AddRes(index, typeof(RawRibs), 1044482, 1, 1044253); + + index = AddCraft(typeof(UncookedSausagePizza), 1044496, 1041337, 0.0, 100.0, typeof(Dough), 1044469, 1, 1044253); + AddRes(index, typeof(Sausage), 1044483, 1, 1044253); + + index = AddCraft(typeof(UncookedCheesePizza), 1044496, 1041341, 0.0, 100.0, typeof(Dough), 1044469, 1, 1044253); + AddRes(index, typeof(CheeseWheel), 1044486, 1, 1044253); + + index = AddCraft(typeof(UnbakedFruitPie), 1044496, 1041334, 0.0, 100.0, typeof(Dough), 1044469, 1, 1044253); + AddRes(index, typeof(Pear), 1044481, 1, 1044253); + + index = AddCraft(typeof(UnbakedPeachCobbler), 1044496, 1041335, 0.0, 100.0, typeof(Dough), 1044469, 1, 1044253); + AddRes(index, typeof(Peach), 1044480, 1, 1044253); + + index = AddCraft(typeof(UnbakedApplePie), 1044496, 1041336, 0.0, 100.0, typeof(Dough), 1044469, 1, 1044253); + AddRes(index, typeof(Apple), 1044479, 1, 1044253); + + index = AddCraft(typeof(UnbakedPumpkinPie), 1044496, 1041342, 0.0, 100.0, typeof(Dough), 1044469, 1, 1044253); + AddRes(index, typeof(Pumpkin), 1044484, 1, 1044253); + + if (Core.SE) + { + index = AddCraft( + typeof(GreenTea), + 1044496, + 1030315, + 80.0, + 130.0, + typeof(GreenTeaBasket), + 1030316, + 1, + 1044253 + ); + AddRes(index, typeof(BaseBeverage), 1046458, 1, 1044253); + SetNeededExpansion(index, Expansion.SE); + SetNeedOven(index, true); + + index = AddCraft( + typeof(WasabiClumps), + 1044496, + 1029451, + 70.0, + 120.0, + typeof(BaseBeverage), + 1046458, + 1, + 1044253 + ); + AddRes(index, typeof(WoodenBowlOfPeas), 1025633, 3, 1044253); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(SushiRolls), + 1044496, + 1030303, + 90.0, + 120.0, + typeof(BaseBeverage), + 1046458, + 1, + 1044253 + ); + AddRes(index, typeof(RawFishSteak), 1044476, 10, 1044253); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(SushiPlatter), + 1044496, + 1030305, + 90.0, + 120.0, + typeof(BaseBeverage), + 1046458, + 1, + 1044253 + ); + AddRes(index, typeof(RawFishSteak), 1044476, 10, 1044253); + SetNeededExpansion(index, Expansion.SE); + } + + index = AddCraft( + typeof(TribalPaint), + 1044496, + 1040000, + Core.ML ? 55.0 : 80.0, + Core.ML ? 105.0 : 80.0, + typeof(SackFlour), + 1044468, + 1, + 1044253 + ); + AddRes(index, typeof(TribalBerry), 1046460, 1, 1044253); + + if (Core.SE) + { + index = AddCraft(typeof(EggBomb), 1044496, 1030249, 90.0, 120.0, typeof(Eggs), 1044477, 1, 1044253); + AddRes(index, typeof(SackFlour), 1044468, 3, 1044253); + SetNeededExpansion(index, Expansion.SE); + } + /* End Preparations */ + + /* Begin Baking */ + index = AddCraft(typeof(BreadLoaf), 1044497, 1024156, 0.0, 100.0, typeof(Dough), 1044469, 1, 1044253); + SetNeedOven(index, true); + + index = AddCraft(typeof(Cookies), 1044497, 1025643, 0.0, 100.0, typeof(CookieMix), 1044474, 1, 1044253); + SetNeedOven(index, true); + + index = AddCraft(typeof(Cake), 1044497, 1022537, 0.0, 100.0, typeof(CakeMix), 1044471, 1, 1044253); + SetNeedOven(index, true); + + index = AddCraft(typeof(Muffins), 1044497, 1022539, 0.0, 100.0, typeof(SweetDough), 1044475, 1, 1044253); + SetNeedOven(index, true); + + index = AddCraft(typeof(Quiche), 1044497, 1041345, 0.0, 100.0, typeof(UnbakedQuiche), 1044518, 1, 1044253); + SetNeedOven(index, true); + + index = AddCraft(typeof(MeatPie), 1044497, 1041347, 0.0, 100.0, typeof(UnbakedMeatPie), 1044519, 1, 1044253); + SetNeedOven(index, true); + + index = AddCraft( + typeof(SausagePizza), + 1044497, + 1044517, + 0.0, + 100.0, + typeof(UncookedSausagePizza), + 1044520, + 1, + 1044253 + ); + SetNeedOven(index, true); + + index = AddCraft( + typeof(CheesePizza), + 1044497, + 1044516, + 0.0, + 100.0, + typeof(UncookedCheesePizza), + 1044521, + 1, + 1044253 + ); + SetNeedOven(index, true); + + index = AddCraft(typeof(FruitPie), 1044497, 1041346, 0.0, 100.0, typeof(UnbakedFruitPie), 1044522, 1, 1044253); + SetNeedOven(index, true); + + index = AddCraft( + typeof(PeachCobbler), + 1044497, + 1041344, + 0.0, + 100.0, + typeof(UnbakedPeachCobbler), + 1044523, + 1, + 1044253 + ); + SetNeedOven(index, true); + + index = AddCraft(typeof(ApplePie), 1044497, 1041343, 0.0, 100.0, typeof(UnbakedApplePie), 1044524, 1, 1044253); + SetNeedOven(index, true); + + index = AddCraft( + typeof(PumpkinPie), + 1044497, + 1041348, + 0.0, + 100.0, + typeof(UnbakedPumpkinPie), + 1046461, + 1, + 1044253 + ); + SetNeedOven(index, true); + + if (Core.SE) + { + index = AddCraft(typeof(MisoSoup), 1044497, 1030317, 60.0, 110.0, typeof(RawFishSteak), 1044476, 1, 1044253); + AddRes(index, typeof(BaseBeverage), 1046458, 1, 1044253); + SetNeededExpansion(index, Expansion.SE); + SetNeedOven(index, true); + + index = AddCraft( + typeof(WhiteMisoSoup), + 1044497, + 1030318, + 60.0, + 110.0, + typeof(RawFishSteak), + 1044476, + 1, + 1044253 + ); + AddRes(index, typeof(BaseBeverage), 1046458, 1, 1044253); + SetNeededExpansion(index, Expansion.SE); + SetNeedOven(index, true); + + index = AddCraft( + typeof(RedMisoSoup), + 1044497, + 1030319, + 60.0, + 110.0, + typeof(RawFishSteak), + 1044476, + 1, + 1044253 + ); + AddRes(index, typeof(BaseBeverage), 1046458, 1, 1044253); + SetNeededExpansion(index, Expansion.SE); + SetNeedOven(index, true); + + index = AddCraft( + typeof(AwaseMisoSoup), + 1044497, + 1030320, + 60.0, + 110.0, + typeof(RawFishSteak), + 1044476, + 1, + 1044253 + ); + AddRes(index, typeof(BaseBeverage), 1046458, 1, 1044253); + SetNeededExpansion(index, Expansion.SE); + SetNeedOven(index, true); + } + /* End Baking */ + + /* Begin Barbecue */ + index = AddCraft(typeof(CookedBird), 1044498, 1022487, 0.0, 100.0, typeof(RawBird), 1044470, 1, 1044253); + SetNeedHeat(index, true); + SetUseAllRes(index, true); + + index = AddCraft(typeof(ChickenLeg), 1044498, 1025640, 0.0, 100.0, typeof(RawChickenLeg), 1044473, 1, 1044253); + SetNeedHeat(index, true); + SetUseAllRes(index, true); + + index = AddCraft(typeof(FishSteak), 1044498, 1022427, 0.0, 100.0, typeof(RawFishSteak), 1044476, 1, 1044253); + SetNeedHeat(index, true); + SetUseAllRes(index, true); + + index = AddCraft(typeof(FriedEggs), 1044498, 1022486, 0.0, 100.0, typeof(Eggs), 1044477, 1, 1044253); + SetNeedHeat(index, true); + SetUseAllRes(index, true); + + index = AddCraft(typeof(LambLeg), 1044498, 1025642, 0.0, 100.0, typeof(RawLambLeg), 1044478, 1, 1044253); + SetNeedHeat(index, true); + SetUseAllRes(index, true); + + index = AddCraft(typeof(Ribs), 1044498, 1022546, 0.0, 100.0, typeof(RawRibs), 1044485, 1, 1044253); + SetNeedHeat(index, true); + SetUseAllRes(index, true); + /* End Barbecue */ + + /* Begin Chocolatiering */ + if (Core.ML) + { + index = AddCraft( + typeof(DarkChocolate), + 1080001, + 1079994, + 15.0, + 100.0, + typeof(SackOfSugar), + 1079997, + 1, + 1044253 + ); + AddRes(index, typeof(CocoaButter), 1079998, 1, 1044253); + AddRes(index, typeof(CocoaLiquor), 1079999, 1, 1044253); + SetItemHue(index, 0x465); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(MilkChocolate), + 1080001, + 1079995, + 32.5, + 107.5, + typeof(SackOfSugar), + 1079997, + 1, + 1044253 + ); + AddRes(index, typeof(CocoaButter), 1079998, 1, 1044253); + AddRes(index, typeof(CocoaLiquor), 1079999, 1, 1044253); + AddRes(index, typeof(BaseBeverage), 1022544, 1, 1044253); + SetBeverageType(index, BeverageType.Milk); + SetItemHue(index, 0x461); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(WhiteChocolate), + 1080001, + 1079996, + 52.5, + 127.5, + typeof(SackOfSugar), + 1079997, + 1, + 1044253 + ); + AddRes(index, typeof(CocoaButter), 1079998, 1, 1044253); + AddRes(index, typeof(Vanilla), 1080000, 1, 1044253); + AddRes(index, typeof(BaseBeverage), 1022544, 1, 1044253); + SetBeverageType(index, BeverageType.Milk); + SetItemHue(index, 0x47E); + SetNeededExpansion(index, Expansion.ML); + } + + /* End Chocolatiering */ + } + } +} diff --git a/Projects/UOContent/Engines/Craft/DefGlassblowing.cs b/Projects/UOContent/Engines/Craft/DefGlassblowing.cs index 9b901e456..1320d0a6e 100644 --- a/Projects/UOContent/Engines/Craft/DefGlassblowing.cs +++ b/Projects/UOContent/Engines/Craft/DefGlassblowing.cs @@ -1,110 +1,112 @@ -using System; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Craft -{ - public class DefGlassblowing : CraftSystem - { - private static CraftSystem m_CraftSystem; - - private DefGlassblowing() : base(1, 1, 1.25) // base( 1, 2, 1.7 ) - { - } - - public override SkillName MainSkill => SkillName.Alchemy; - - public override int GumpTitleNumber => 1044622; - - public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefGlassblowing()); - - public override double GetChanceAtMin(CraftItem item) => item.ItemType == typeof(HollowPrism) ? 0.5 : 0.0; - - public override int CanCraft(Mobile from, BaseTool tool, Type itemType) - { - if (tool?.Deleted != false || tool.UsesRemaining < 0) - return 1044038; // You have worn out your tool! - if (!BaseTool.CheckTool(tool, from)) - return 1048146; // If you have a tool equipped, you must use that tool. - if (!(from is PlayerMobile mobile && mobile.Glassblowing && mobile.Skills.Alchemy.Base >= 100.0)) - return 1044634; // You havent learned glassblowing. - if (!BaseTool.CheckAccessible(tool, from)) - return 1044263; // The tool must be on your person to use. - - DefBlacksmithy.CheckAnvilAndForge(from, 2, out _, out bool forge); - - return forge ? 0 : 1044628; // You must be near a forge to blow glass. - } - - public override void PlayCraftEffect(Mobile from) - { - from.PlaySound(0x2B); // bellows - - // if (from.Body.Type == BodyType.Human && !from.Mounted) - // from.Animate( 9, 5, 1, true, false, 0 ); - - // new InternalTimer( from ).Start(); - } - - public override int PlayEndingEffect(Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, - bool makersMark, CraftItem item) - { - if (toolBroken) - from.SendLocalizedMessage(1044038); // You have worn out your tool - - if (failed) - { - if (lostMaterial) - return 1044043; // You failed to create the item, and some of your materials are lost. - return 1044157; // You failed to create the item, but no materials were lost. - } - - from.PlaySound(0x41); // glass breaking - - if (quality == 0) - return 502785; // You were barely able to make this item. It's quality is below average. - if (makersMark && quality == 2) - return 1044156; // You create an exceptional quality item and affix your maker's mark. - if (quality == 2) - return 1044155; // You create an exceptional quality item. - return 1044154; // You create the item. - } - - public override void InitCraftList() - { - int index = AddCraft(typeof(Bottle), 1044050, 1023854, 52.5, 102.5, typeof(Sand), 1044625, 1, 1044627); - SetUseAllRes(index, true); - - AddCraft(typeof(SmallFlask), 1044050, 1044610, 52.5, 102.5, typeof(Sand), 1044625, 2, 1044627); - AddCraft(typeof(MediumFlask), 1044050, 1044611, 52.5, 102.5, typeof(Sand), 1044625, 3, 1044627); - AddCraft(typeof(CurvedFlask), 1044050, 1044612, 55.0, 105.0, typeof(Sand), 1044625, 2, 1044627); - AddCraft(typeof(LongFlask), 1044050, 1044613, 57.5, 107.5, typeof(Sand), 1044625, 4, 1044627); - AddCraft(typeof(LargeFlask), 1044050, 1044623, 60.0, 110.0, typeof(Sand), 1044625, 5, 1044627); - AddCraft(typeof(AniSmallBlueFlask), 1044050, 1044614, 60.0, 110.0, typeof(Sand), 1044625, 5, 1044627); - AddCraft(typeof(AniLargeVioletFlask), 1044050, 1044615, 60.0, 110.0, typeof(Sand), 1044625, 5, 1044627); - AddCraft(typeof(AniRedRibbedFlask), 1044050, 1044624, 60.0, 110.0, typeof(Sand), 1044625, 7, 1044627); - AddCraft(typeof(EmptyVialsWRack), 1044050, 1044616, 65.0, 115.0, typeof(Sand), 1044625, 8, 1044627); - AddCraft(typeof(FullVialsWRack), 1044050, 1044617, 65.0, 115.0, typeof(Sand), 1044625, 9, 1044627); - AddCraft(typeof(SpinningHourglass), 1044050, 1044618, 75.0, 125.0, typeof(Sand), 1044625, 10, 1044627); - - if (Core.ML) - { - index = AddCraft(typeof(HollowPrism), 1044050, 1072895, 100.0, 150.0, typeof(Sand), 1044625, 8, 1044627); - SetNeededExpansion(index, Expansion.ML); - } - } - - // Delay to synchronize the sound with the hit on the anvil - private class InternalTimer : Timer - { - private readonly Mobile m_From; - - public InternalTimer(Mobile from) : base(TimeSpan.FromSeconds(0.7)) => m_From = from; - - protected override void OnTick() - { - m_From.PlaySound(0x2A); - } - } - } -} +using System; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Craft +{ + public class DefGlassblowing : CraftSystem + { + private static CraftSystem m_CraftSystem; + + private DefGlassblowing() : base(1, 1, 1.25) // base( 1, 2, 1.7 ) + { + } + + public override SkillName MainSkill => SkillName.Alchemy; + + public override int GumpTitleNumber => 1044622; + + public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefGlassblowing()); + + public override double GetChanceAtMin(CraftItem item) => item.ItemType == typeof(HollowPrism) ? 0.5 : 0.0; + + public override int CanCraft(Mobile from, BaseTool tool, Type itemType) + { + if (tool?.Deleted != false || tool.UsesRemaining < 0) + return 1044038; // You have worn out your tool! + if (!BaseTool.CheckTool(tool, from)) + return 1048146; // If you have a tool equipped, you must use that tool. + if (!(from is PlayerMobile mobile && mobile.Glassblowing && mobile.Skills.Alchemy.Base >= 100.0)) + return 1044634; // You havent learned glassblowing. + if (!BaseTool.CheckAccessible(tool, from)) + return 1044263; // The tool must be on your person to use. + + DefBlacksmithy.CheckAnvilAndForge(from, 2, out _, out var forge); + + return forge ? 0 : 1044628; // You must be near a forge to blow glass. + } + + public override void PlayCraftEffect(Mobile from) + { + from.PlaySound(0x2B); // bellows + + // if (from.Body.Type == BodyType.Human && !from.Mounted) + // from.Animate( 9, 5, 1, true, false, 0 ); + + // new InternalTimer( from ).Start(); + } + + public override int PlayEndingEffect( + Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, + bool makersMark, CraftItem item + ) + { + if (toolBroken) + from.SendLocalizedMessage(1044038); // You have worn out your tool + + if (failed) + { + if (lostMaterial) + return 1044043; // You failed to create the item, and some of your materials are lost. + return 1044157; // You failed to create the item, but no materials were lost. + } + + from.PlaySound(0x41); // glass breaking + + if (quality == 0) + return 502785; // You were barely able to make this item. It's quality is below average. + if (makersMark && quality == 2) + return 1044156; // You create an exceptional quality item and affix your maker's mark. + if (quality == 2) + return 1044155; // You create an exceptional quality item. + return 1044154; // You create the item. + } + + public override void InitCraftList() + { + var index = AddCraft(typeof(Bottle), 1044050, 1023854, 52.5, 102.5, typeof(Sand), 1044625, 1, 1044627); + SetUseAllRes(index, true); + + AddCraft(typeof(SmallFlask), 1044050, 1044610, 52.5, 102.5, typeof(Sand), 1044625, 2, 1044627); + AddCraft(typeof(MediumFlask), 1044050, 1044611, 52.5, 102.5, typeof(Sand), 1044625, 3, 1044627); + AddCraft(typeof(CurvedFlask), 1044050, 1044612, 55.0, 105.0, typeof(Sand), 1044625, 2, 1044627); + AddCraft(typeof(LongFlask), 1044050, 1044613, 57.5, 107.5, typeof(Sand), 1044625, 4, 1044627); + AddCraft(typeof(LargeFlask), 1044050, 1044623, 60.0, 110.0, typeof(Sand), 1044625, 5, 1044627); + AddCraft(typeof(AniSmallBlueFlask), 1044050, 1044614, 60.0, 110.0, typeof(Sand), 1044625, 5, 1044627); + AddCraft(typeof(AniLargeVioletFlask), 1044050, 1044615, 60.0, 110.0, typeof(Sand), 1044625, 5, 1044627); + AddCraft(typeof(AniRedRibbedFlask), 1044050, 1044624, 60.0, 110.0, typeof(Sand), 1044625, 7, 1044627); + AddCraft(typeof(EmptyVialsWRack), 1044050, 1044616, 65.0, 115.0, typeof(Sand), 1044625, 8, 1044627); + AddCraft(typeof(FullVialsWRack), 1044050, 1044617, 65.0, 115.0, typeof(Sand), 1044625, 9, 1044627); + AddCraft(typeof(SpinningHourglass), 1044050, 1044618, 75.0, 125.0, typeof(Sand), 1044625, 10, 1044627); + + if (Core.ML) + { + index = AddCraft(typeof(HollowPrism), 1044050, 1072895, 100.0, 150.0, typeof(Sand), 1044625, 8, 1044627); + SetNeededExpansion(index, Expansion.ML); + } + } + + // Delay to synchronize the sound with the hit on the anvil + private class InternalTimer : Timer + { + private readonly Mobile m_From; + + public InternalTimer(Mobile from) : base(TimeSpan.FromSeconds(0.7)) => m_From = from; + + protected override void OnTick() + { + m_From.PlaySound(0x2A); + } + } + } +} diff --git a/Projects/UOContent/Engines/Craft/DefInscription.cs b/Projects/UOContent/Engines/Craft/DefInscription.cs index ab528747b..8694e5dc5 100644 --- a/Projects/UOContent/Engines/Craft/DefInscription.cs +++ b/Projects/UOContent/Engines/Craft/DefInscription.cs @@ -1,398 +1,594 @@ -using System; -using Server.Engines.BulkOrders; -using Server.Items; -using Server.Spells; -using Server.Utilities; - -namespace Server.Engines.Craft -{ - public class DefInscription : CraftSystem - { - private static CraftSystem m_CraftSystem; - - private static readonly Type typeofSpellScroll = typeof(SpellScroll); - - private int m_Circle, m_Mana; - - private int m_Index; - - private readonly Type[] m_RegTypes = - { - typeof(BlackPearl), - typeof(Bloodmoss), - typeof(Garlic), - typeof(Ginseng), - typeof(MandrakeRoot), - typeof(Nightshade), - typeof(SulfurousAsh), - typeof(SpidersSilk) - }; - - private DefInscription() - : base(1, 1, 1.25) // base( 1, 1, 3.0 ) - { - } - - public override SkillName MainSkill => SkillName.Inscribe; - - public override int GumpTitleNumber => 1044009; - - public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefInscription()); - - public override double GetChanceAtMin(CraftItem item) => 0.0; - - public override int CanCraft(Mobile from, BaseTool tool, Type typeItem) - { - if (tool?.Deleted != false || tool.UsesRemaining < 0) - return 1044038; // You have worn out your tool! - if (!BaseTool.CheckAccessible(tool, from)) - return 1044263; // The tool must be on your person to use. - - if (typeItem != null) - { - object o = ActivatorUtil.CreateInstance(typeItem); - - if (o is SpellScroll scroll) - { - bool hasSpell = Spellbook.Find(from, scroll.SpellID)?.HasSpell(scroll.SpellID) == true; - - scroll.Delete(); - - return hasSpell ? 0 : 1042404; // null : You don't have that spell! - } - - if (o is Item item) item.Delete(); - } - - return 0; - } - - public override void PlayCraftEffect(Mobile from) - { - from.PlaySound(0x249); - } - - public override int PlayEndingEffect(Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, - bool makersMark, CraftItem item) - { - if (toolBroken) - from.SendLocalizedMessage(1044038); // You have worn out your tool - - if (!typeofSpellScroll.IsAssignableFrom(item.ItemType)) // not a scroll - { - if (failed) - { - if (lostMaterial) - return 1044043; // You failed to create the item, and some of your materials are lost. - return 1044157; // You failed to create the item, but no materials were lost. - } - - if (quality == 0) - return 502785; // You were barely able to make this item. It's quality is below average. - if (makersMark && quality == 2) - return 1044156; // You create an exceptional quality item and affix your maker's mark. - if (quality == 2) - return 1044155; // You create an exceptional quality item. - return 1044154; // You create the item. - } - - if (failed) - return 501630; // You fail to inscribe the scroll, and the scroll is ruined. - return 501629; // You inscribe the spell and put the scroll in your backpack. - } - - private void AddSpell(Type type, params Reg[] regs) - { - double minSkill, maxSkill; - - switch (m_Circle) - { - default: - minSkill = -25.0; - maxSkill = 25.0; - break; - case 1: - minSkill = -10.8; - maxSkill = 39.2; - break; - case 2: - minSkill = 03.5; - maxSkill = 53.5; - break; - case 3: - minSkill = 17.8; - maxSkill = 67.8; - break; - case 4: - minSkill = 32.1; - maxSkill = 82.1; - break; - case 5: - minSkill = 46.4; - maxSkill = 96.4; - break; - case 6: - minSkill = 60.7; - maxSkill = 110.7; - break; - case 7: - minSkill = 75.0; - maxSkill = 125.0; - break; - } - - int index = AddCraft(type, 1044369 + m_Circle, 1044381 + m_Index++, minSkill, maxSkill, m_RegTypes[(int)regs[0]], - 1044353 + (int)regs[0], 1, 1044361 + (int)regs[0]); - - for (int i = 1; i < regs.Length; ++i) - AddRes(index, m_RegTypes[(int)regs[i]], 1044353 + (int)regs[i], 1, 1044361 + (int)regs[i]); - - AddRes(index, typeof(BlankScroll), 1044377, 1, 1044378); - - SetManaReq(index, m_Mana); - } - - private void AddNecroSpell(int spell, int mana, double minSkill, Type type, params Type[] regs) - { - int index = AddCraft(type, 1061677, 1060509 + spell, minSkill, minSkill + 1.0, regs[0], - CraftItem.LabelNumber(regs[0]), 1, - 501627); // Yes, on OSI it's only 1.0 skill diff'. Don't blame me, blame OSI. - - for (int i = 1; i < regs.Length; ++i) - AddRes(index, regs[i], CraftItem.LabelNumber(regs[0]), 1, 501627); - - AddRes(index, typeof(BlankScroll), 1044377, 1, 1044378); - SetManaReq(index, mana); - } - - private void AddMysticismSpell(int spell, int mana, double minSkill, double maxSkill, Type type, params Type[] regs) - { - int index = AddCraft(type, 1111671, 1031678 + spell, minSkill, maxSkill, regs[0], CraftItem.LabelNumber(regs[0]), - 1, 501627); - - for (int i = 1; i < regs.Length; ++i) - AddRes(index, regs[i], CraftItem.LabelNumber(regs[i]), 1, 501627); - - AddRes(index, typeof(BlankScroll), 1044377, 1, 1044378); - SetManaReq(index, mana); - } - - public override void InitCraftList() - { - m_Circle = 0; - m_Mana = 4; - - AddSpell(typeof(ReactiveArmorScroll), Reg.Garlic, Reg.SpidersSilk, Reg.SulfurousAsh); - AddSpell(typeof(ClumsyScroll), Reg.Bloodmoss, Reg.Nightshade); - AddSpell(typeof(CreateFoodScroll), Reg.Garlic, Reg.Ginseng, Reg.MandrakeRoot); - AddSpell(typeof(FeeblemindScroll), Reg.Nightshade, Reg.Ginseng); - AddSpell(typeof(HealScroll), Reg.Garlic, Reg.Ginseng, Reg.SpidersSilk); - AddSpell(typeof(MagicArrowScroll), Reg.SulfurousAsh); - AddSpell(typeof(NightSightScroll), Reg.SpidersSilk, Reg.SulfurousAsh); - AddSpell(typeof(WeakenScroll), Reg.Garlic, Reg.Nightshade); - - m_Circle = 1; - m_Mana = 6; - - AddSpell(typeof(AgilityScroll), Reg.Bloodmoss, Reg.MandrakeRoot); - AddSpell(typeof(CunningScroll), Reg.Nightshade, Reg.MandrakeRoot); - AddSpell(typeof(CureScroll), Reg.Garlic, Reg.Ginseng); - AddSpell(typeof(HarmScroll), Reg.Nightshade, Reg.SpidersSilk); - AddSpell(typeof(MagicTrapScroll), Reg.Garlic, Reg.SpidersSilk, Reg.SulfurousAsh); - AddSpell(typeof(MagicUnTrapScroll), Reg.Bloodmoss, Reg.SulfurousAsh); - AddSpell(typeof(ProtectionScroll), Reg.Garlic, Reg.Ginseng, Reg.SulfurousAsh); - AddSpell(typeof(StrengthScroll), Reg.Nightshade, Reg.MandrakeRoot); - - m_Circle = 2; - m_Mana = 9; - - AddSpell(typeof(BlessScroll), Reg.Garlic, Reg.MandrakeRoot); - AddSpell(typeof(FireballScroll), Reg.BlackPearl); - AddSpell(typeof(MagicLockScroll), Reg.Bloodmoss, Reg.Garlic, Reg.SulfurousAsh); - AddSpell(typeof(PoisonScroll), Reg.Nightshade); - AddSpell(typeof(TelekinesisScroll), Reg.Bloodmoss, Reg.MandrakeRoot); - AddSpell(typeof(TeleportScroll), Reg.Bloodmoss, Reg.MandrakeRoot); - AddSpell(typeof(UnlockScroll), Reg.Bloodmoss, Reg.SulfurousAsh); - AddSpell(typeof(WallOfStoneScroll), Reg.Bloodmoss, Reg.Garlic); - - m_Circle = 3; - m_Mana = 11; - - AddSpell(typeof(ArchCureScroll), Reg.Garlic, Reg.Ginseng, Reg.MandrakeRoot); - AddSpell(typeof(ArchProtectionScroll), Reg.Garlic, Reg.Ginseng, Reg.MandrakeRoot, Reg.SulfurousAsh); - AddSpell(typeof(CurseScroll), Reg.Garlic, Reg.Nightshade, Reg.SulfurousAsh); - AddSpell(typeof(FireFieldScroll), Reg.BlackPearl, Reg.SpidersSilk, Reg.SulfurousAsh); - AddSpell(typeof(GreaterHealScroll), Reg.Garlic, Reg.SpidersSilk, Reg.MandrakeRoot, Reg.Ginseng); - AddSpell(typeof(LightningScroll), Reg.MandrakeRoot, Reg.SulfurousAsh); - AddSpell(typeof(ManaDrainScroll), Reg.BlackPearl, Reg.SpidersSilk, Reg.MandrakeRoot); - AddSpell(typeof(RecallScroll), Reg.BlackPearl, Reg.Bloodmoss, Reg.MandrakeRoot); - - m_Circle = 4; - m_Mana = 14; - - AddSpell(typeof(BladeSpiritsScroll), Reg.BlackPearl, Reg.Nightshade, Reg.MandrakeRoot); - AddSpell(typeof(DispelFieldScroll), Reg.BlackPearl, Reg.Garlic, Reg.SpidersSilk, Reg.SulfurousAsh); - AddSpell(typeof(IncognitoScroll), Reg.Bloodmoss, Reg.Garlic, Reg.Nightshade); - AddSpell(typeof(MagicReflectScroll), Reg.Garlic, Reg.MandrakeRoot, Reg.SpidersSilk); - AddSpell(typeof(MindBlastScroll), Reg.BlackPearl, Reg.MandrakeRoot, Reg.Nightshade, Reg.SulfurousAsh); - AddSpell(typeof(ParalyzeScroll), Reg.Garlic, Reg.MandrakeRoot, Reg.SpidersSilk); - AddSpell(typeof(PoisonFieldScroll), Reg.BlackPearl, Reg.Nightshade, Reg.SpidersSilk); - AddSpell(typeof(SummonCreatureScroll), Reg.Bloodmoss, Reg.MandrakeRoot, Reg.SpidersSilk); - - m_Circle = 5; - m_Mana = 20; - - AddSpell(typeof(DispelScroll), Reg.Garlic, Reg.MandrakeRoot, Reg.SulfurousAsh); - AddSpell(typeof(EnergyBoltScroll), Reg.BlackPearl, Reg.Nightshade); - AddSpell(typeof(ExplosionScroll), Reg.Bloodmoss, Reg.MandrakeRoot); - AddSpell(typeof(InvisibilityScroll), Reg.Bloodmoss, Reg.Nightshade); - AddSpell(typeof(MarkScroll), Reg.Bloodmoss, Reg.BlackPearl, Reg.MandrakeRoot); - AddSpell(typeof(MassCurseScroll), Reg.Garlic, Reg.MandrakeRoot, Reg.Nightshade, Reg.SulfurousAsh); - AddSpell(typeof(ParalyzeFieldScroll), Reg.BlackPearl, Reg.Ginseng, Reg.SpidersSilk); - AddSpell(typeof(RevealScroll), Reg.Bloodmoss, Reg.SulfurousAsh); - - m_Circle = 6; - m_Mana = 40; - - AddSpell(typeof(ChainLightningScroll), Reg.BlackPearl, Reg.Bloodmoss, Reg.MandrakeRoot, Reg.SulfurousAsh); - AddSpell(typeof(EnergyFieldScroll), Reg.BlackPearl, Reg.MandrakeRoot, Reg.SpidersSilk, Reg.SulfurousAsh); - AddSpell(typeof(FlamestrikeScroll), Reg.SpidersSilk, Reg.SulfurousAsh); - AddSpell(typeof(GateTravelScroll), Reg.BlackPearl, Reg.MandrakeRoot, Reg.SulfurousAsh); - AddSpell(typeof(ManaVampireScroll), Reg.BlackPearl, Reg.Bloodmoss, Reg.MandrakeRoot, Reg.SpidersSilk); - AddSpell(typeof(MassDispelScroll), Reg.BlackPearl, Reg.Garlic, Reg.MandrakeRoot, Reg.SulfurousAsh); - AddSpell(typeof(MeteorSwarmScroll), Reg.Bloodmoss, Reg.MandrakeRoot, Reg.SulfurousAsh, Reg.SpidersSilk); - AddSpell(typeof(PolymorphScroll), Reg.Bloodmoss, Reg.MandrakeRoot, Reg.SpidersSilk); - - m_Circle = 7; - m_Mana = 50; - - AddSpell(typeof(EarthquakeScroll), Reg.Bloodmoss, Reg.MandrakeRoot, Reg.Ginseng, Reg.SulfurousAsh); - AddSpell(typeof(EnergyVortexScroll), Reg.BlackPearl, Reg.Bloodmoss, Reg.MandrakeRoot, Reg.Nightshade); - AddSpell(typeof(ResurrectionScroll), Reg.Bloodmoss, Reg.Garlic, Reg.Ginseng); - AddSpell(typeof(SummonAirElementalScroll), Reg.Bloodmoss, Reg.MandrakeRoot, Reg.SpidersSilk); - AddSpell(typeof(SummonDaemonScroll), Reg.Bloodmoss, Reg.MandrakeRoot, Reg.SpidersSilk, Reg.SulfurousAsh); - AddSpell(typeof(SummonEarthElementalScroll), Reg.Bloodmoss, Reg.MandrakeRoot, Reg.SpidersSilk); - AddSpell(typeof(SummonFireElementalScroll), Reg.Bloodmoss, Reg.MandrakeRoot, Reg.SpidersSilk, Reg.SulfurousAsh); - AddSpell(typeof(SummonWaterElementalScroll), Reg.Bloodmoss, Reg.MandrakeRoot, Reg.SpidersSilk); - - if (Core.SE) - { - AddNecroSpell(0, 23, 39.6, typeof(AnimateDeadScroll), Reagent.GraveDust, Reagent.DaemonBlood); - AddNecroSpell(1, 13, 19.6, typeof(BloodOathScroll), Reagent.DaemonBlood); - AddNecroSpell(2, 11, 19.6, typeof(CorpseSkinScroll), Reagent.BatWing, Reagent.GraveDust); - AddNecroSpell(3, 7, 19.6, typeof(CurseWeaponScroll), Reagent.PigIron); - AddNecroSpell(4, 11, 19.6, typeof(EvilOmenScroll), Reagent.BatWing, Reagent.NoxCrystal); - AddNecroSpell(5, 11, 39.6, typeof(HorrificBeastScroll), Reagent.BatWing, Reagent.DaemonBlood); - AddNecroSpell(6, 23, 69.6, typeof(LichFormScroll), Reagent.GraveDust, Reagent.DaemonBlood, - Reagent.NoxCrystal); - AddNecroSpell(7, 17, 29.6, typeof(MindRotScroll), Reagent.BatWing, Reagent.DaemonBlood, Reagent.PigIron); - AddNecroSpell(8, 5, 19.6, typeof(PainSpikeScroll), Reagent.GraveDust, Reagent.PigIron); - AddNecroSpell(9, 17, 49.6, typeof(PoisonStrikeScroll), Reagent.NoxCrystal); - AddNecroSpell(10, 29, 64.6, typeof(StrangleScroll), Reagent.DaemonBlood, Reagent.NoxCrystal); - AddNecroSpell(11, 17, 29.6, typeof(SummonFamiliarScroll), Reagent.BatWing, Reagent.GraveDust, - Reagent.DaemonBlood); - AddNecroSpell(12, 23, 98.6, typeof(VampiricEmbraceScroll), Reagent.BatWing, Reagent.NoxCrystal, - Reagent.PigIron); - AddNecroSpell(13, 41, 79.6, typeof(VengefulSpiritScroll), Reagent.BatWing, Reagent.GraveDust, - Reagent.PigIron); - AddNecroSpell(14, 23, 59.6, typeof(WitherScroll), Reagent.GraveDust, Reagent.NoxCrystal, Reagent.PigIron); - AddNecroSpell(15, 17, 79.6, typeof(WraithFormScroll), Reagent.NoxCrystal, Reagent.PigIron); - AddNecroSpell(16, 40, 79.6, typeof(ExorcismScroll), Reagent.NoxCrystal, Reagent.GraveDust); - } - - int index; - - if (Core.ML) - { - index = AddCraft(typeof(EnchantedSwitch), 1044294, 1072893, 45.0, 95.0, typeof(BlankScroll), 1044377, 1, - 1044378); - AddRes(index, typeof(SpidersSilk), 1044360, 1, 1044253); - AddRes(index, typeof(BlackPearl), 1044353, 1, 1044253); - AddRes(index, typeof(SwitchItem), 1073464, 1, 1044253); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(RunedPrism), 1044294, 1073465, 45.0, 95.0, typeof(BlankScroll), 1044377, 1, 1044378); - AddRes(index, typeof(SpidersSilk), 1044360, 1, 1044253); - AddRes(index, typeof(BlackPearl), 1044353, 1, 1044253); - AddRes(index, typeof(HollowPrism), 1072895, 1, 1044253); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - } - - // Runebook - index = AddCraft(typeof(Runebook), 1044294, 1041267, 45.0, 95.0, typeof(BlankScroll), 1044377, 8, 1044378); - AddRes(index, typeof(RecallScroll), 1044445, 1, 1044253); - AddRes(index, typeof(GateTravelScroll), 1044446, 1, 1044253); - - if (Core.AOS) - AddCraft(typeof(BulkOrderBook), 1044294, 1028793, 65.0, 115.0, typeof(BlankScroll), 1044377, 10, 1044378); - - if (Core.SE) AddCraft(typeof(Spellbook), 1044294, 1023834, 50.0, 126, typeof(BlankScroll), 1044377, 10, 1044378); - - /* TODO - if (Core.ML) - { - index = AddCraft( typeof( ScrappersCompendium ), 1044294, 1072940, 75.0, 125.0, typeof( BlankScroll ), 1044377, 100, 1044378 ); - AddRes( index, typeof( DreadHornMane ), 1032682, 1, 1044253 ); - AddRes( index, typeof( Taint ), 1032679, 10, 1044253 ); - AddRes( index, typeof( Corruption ), 1032676, 10, 1044253 ); - AddRareRecipe( index, 400 ); - ForceNonExceptional( index ); - SetNeededExpansion( index, Expansion.ML ); - } - */ - - if (Core.SA) - { - AddCraft(typeof(MysticSpellbook), 1044294, 1031677, 50.0, 150.0, typeof(BlankScroll), 1044377, 10, 1044378); - - AddMysticismSpell(0, 4, -25.0, 25.0, typeof(NetherBoltScroll), Reagent.BlackPearl, Reagent.SulfurousAsh); - AddMysticismSpell(1, 4, -25.0, 25.0, typeof(HealingStoneScroll), Reagent.Bone, Reagent.Garlic, - Reagent.Ginseng, Reagent.SpidersSilk); - AddMysticismSpell(2, 6, -10.8, 39.2, typeof(PurgeMagicScroll), Reagent.FertileDirt, Reagent.Garlic, - Reagent.MandrakeRoot, Reagent.SulfurousAsh); - AddMysticismSpell(3, 6, -10.8, 39.2, typeof(EnchantScroll), Reagent.SpidersSilk, Reagent.MandrakeRoot, - Reagent.SulfurousAsh); - AddMysticismSpell(4, 9, 3.5, 53.5, typeof(SleepScroll), Reagent.Nightshade, Reagent.SpidersSilk, - Reagent.BlackPearl); - AddMysticismSpell(5, 9, 3.5, 53.5, typeof(EagleStrikeScroll), Reagent.Bloodmoss, Reagent.Bone, - Reagent.SpidersSilk, Reagent.MandrakeRoot); - AddMysticismSpell(6, 11, 17.8, 67.8, typeof(AnimatedWeaponScroll), Reagent.Bone, Reagent.BlackPearl, - Reagent.MandrakeRoot, Reagent.Nightshade); - AddMysticismSpell(7, 11, 17.8, 67.8, typeof(StoneFormScroll), Reagent.Bloodmoss, Reagent.FertileDirt, - Reagent.Garlic); - AddMysticismSpell(8, 14, 32.1, 82.1, typeof(SpellTriggerScroll), Reagent.DragonsBlood, Reagent.Garlic, - Reagent.MandrakeRoot, Reagent.SpidersSilk); - AddMysticismSpell(9, 14, 32.1, 82.1, typeof(MassSleepScroll), Reagent.Ginseng, Reagent.Nightshade, - Reagent.SpidersSilk); - AddMysticismSpell(10, 20, 46.4, 96.4, typeof(CleansingWindsScroll), Reagent.DragonsBlood, Reagent.Garlic, - Reagent.Ginseng, Reagent.MandrakeRoot); - AddMysticismSpell(11, 20, 46.4, 96.4, typeof(BombardScroll), Reagent.Bloodmoss, Reagent.DragonsBlood, - Reagent.Garlic, Reagent.SulfurousAsh); - AddMysticismSpell(12, 40, 60.7, 110.7, typeof(SpellPlagueScroll), Reagent.DaemonBone, Reagent.DragonsBlood, - Reagent.Nightshade, Reagent.SulfurousAsh); - AddMysticismSpell(13, 40, 60.7, 110.7, typeof(HailStormScroll), Reagent.DragonsBlood, Reagent.Bloodmoss, - Reagent.BlackPearl, Reagent.MandrakeRoot); - AddMysticismSpell(14, 50, 75.0, 125.0, typeof(NetherCycloneScroll), Reagent.MandrakeRoot, Reagent.Nightshade, - Reagent.SulfurousAsh, Reagent.Bloodmoss); - AddMysticismSpell(15, 50, 75.0, 125.0, typeof(RisingColossusScroll), Reagent.DaemonBone, - Reagent.DragonsBlood, Reagent.FertileDirt, Reagent.Nightshade); - } - - MarkOption = true; - } - - private enum Reg - { - BlackPearl, - Bloodmoss, - Garlic, - Ginseng, - MandrakeRoot, - Nightshade, - SulfurousAsh, - SpidersSilk - } - } -} +using System; +using Server.Engines.BulkOrders; +using Server.Items; +using Server.Spells; +using Server.Utilities; + +namespace Server.Engines.Craft +{ + public class DefInscription : CraftSystem + { + private static CraftSystem m_CraftSystem; + + private static readonly Type typeofSpellScroll = typeof(SpellScroll); + + private readonly Type[] m_RegTypes = + { + typeof(BlackPearl), + typeof(Bloodmoss), + typeof(Garlic), + typeof(Ginseng), + typeof(MandrakeRoot), + typeof(Nightshade), + typeof(SulfurousAsh), + typeof(SpidersSilk) + }; + + private int m_Circle, m_Mana; + + private int m_Index; + + private DefInscription() + : base(1, 1, 1.25) // base( 1, 1, 3.0 ) + { + } + + public override SkillName MainSkill => SkillName.Inscribe; + + public override int GumpTitleNumber => 1044009; + + public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefInscription()); + + public override double GetChanceAtMin(CraftItem item) => 0.0; + + public override int CanCraft(Mobile from, BaseTool tool, Type typeItem) + { + if (tool?.Deleted != false || tool.UsesRemaining < 0) + return 1044038; // You have worn out your tool! + if (!BaseTool.CheckAccessible(tool, from)) + return 1044263; // The tool must be on your person to use. + + if (typeItem != null) + { + var o = ActivatorUtil.CreateInstance(typeItem); + + if (o is SpellScroll scroll) + { + var hasSpell = Spellbook.Find(from, scroll.SpellID)?.HasSpell(scroll.SpellID) == true; + + scroll.Delete(); + + return hasSpell ? 0 : 1042404; // null : You don't have that spell! + } + + if (o is Item item) item.Delete(); + } + + return 0; + } + + public override void PlayCraftEffect(Mobile from) + { + from.PlaySound(0x249); + } + + public override int PlayEndingEffect( + Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, + bool makersMark, CraftItem item + ) + { + if (toolBroken) + from.SendLocalizedMessage(1044038); // You have worn out your tool + + if (!typeofSpellScroll.IsAssignableFrom(item.ItemType)) // not a scroll + { + if (failed) + { + if (lostMaterial) + return 1044043; // You failed to create the item, and some of your materials are lost. + return 1044157; // You failed to create the item, but no materials were lost. + } + + if (quality == 0) + return 502785; // You were barely able to make this item. It's quality is below average. + if (makersMark && quality == 2) + return 1044156; // You create an exceptional quality item and affix your maker's mark. + if (quality == 2) + return 1044155; // You create an exceptional quality item. + return 1044154; // You create the item. + } + + if (failed) + return 501630; // You fail to inscribe the scroll, and the scroll is ruined. + return 501629; // You inscribe the spell and put the scroll in your backpack. + } + + private void AddSpell(Type type, params Reg[] regs) + { + double minSkill, maxSkill; + + switch (m_Circle) + { + default: + minSkill = -25.0; + maxSkill = 25.0; + break; + case 1: + minSkill = -10.8; + maxSkill = 39.2; + break; + case 2: + minSkill = 03.5; + maxSkill = 53.5; + break; + case 3: + minSkill = 17.8; + maxSkill = 67.8; + break; + case 4: + minSkill = 32.1; + maxSkill = 82.1; + break; + case 5: + minSkill = 46.4; + maxSkill = 96.4; + break; + case 6: + minSkill = 60.7; + maxSkill = 110.7; + break; + case 7: + minSkill = 75.0; + maxSkill = 125.0; + break; + } + + var index = AddCraft( + type, + 1044369 + m_Circle, + 1044381 + m_Index++, + minSkill, + maxSkill, + m_RegTypes[(int)regs[0]], + 1044353 + (int)regs[0], + 1, + 1044361 + (int)regs[0] + ); + + for (var i = 1; i < regs.Length; ++i) + AddRes(index, m_RegTypes[(int)regs[i]], 1044353 + (int)regs[i], 1, 1044361 + (int)regs[i]); + + AddRes(index, typeof(BlankScroll), 1044377, 1, 1044378); + + SetManaReq(index, m_Mana); + } + + private void AddNecroSpell(int spell, int mana, double minSkill, Type type, params Type[] regs) + { + var index = AddCraft( + type, + 1061677, + 1060509 + spell, + minSkill, + minSkill + 1.0, + regs[0], + CraftItem.LabelNumber(regs[0]), + 1, + 501627 + ); // Yes, on OSI it's only 1.0 skill diff'. Don't blame me, blame OSI. + + for (var i = 1; i < regs.Length; ++i) + AddRes(index, regs[i], CraftItem.LabelNumber(regs[0]), 1, 501627); + + AddRes(index, typeof(BlankScroll), 1044377, 1, 1044378); + SetManaReq(index, mana); + } + + private void AddMysticismSpell(int spell, int mana, double minSkill, double maxSkill, Type type, params Type[] regs) + { + var index = AddCraft( + type, + 1111671, + 1031678 + spell, + minSkill, + maxSkill, + regs[0], + CraftItem.LabelNumber(regs[0]), + 1, + 501627 + ); + + for (var i = 1; i < regs.Length; ++i) + AddRes(index, regs[i], CraftItem.LabelNumber(regs[i]), 1, 501627); + + AddRes(index, typeof(BlankScroll), 1044377, 1, 1044378); + SetManaReq(index, mana); + } + + public override void InitCraftList() + { + m_Circle = 0; + m_Mana = 4; + + AddSpell(typeof(ReactiveArmorScroll), Reg.Garlic, Reg.SpidersSilk, Reg.SulfurousAsh); + AddSpell(typeof(ClumsyScroll), Reg.Bloodmoss, Reg.Nightshade); + AddSpell(typeof(CreateFoodScroll), Reg.Garlic, Reg.Ginseng, Reg.MandrakeRoot); + AddSpell(typeof(FeeblemindScroll), Reg.Nightshade, Reg.Ginseng); + AddSpell(typeof(HealScroll), Reg.Garlic, Reg.Ginseng, Reg.SpidersSilk); + AddSpell(typeof(MagicArrowScroll), Reg.SulfurousAsh); + AddSpell(typeof(NightSightScroll), Reg.SpidersSilk, Reg.SulfurousAsh); + AddSpell(typeof(WeakenScroll), Reg.Garlic, Reg.Nightshade); + + m_Circle = 1; + m_Mana = 6; + + AddSpell(typeof(AgilityScroll), Reg.Bloodmoss, Reg.MandrakeRoot); + AddSpell(typeof(CunningScroll), Reg.Nightshade, Reg.MandrakeRoot); + AddSpell(typeof(CureScroll), Reg.Garlic, Reg.Ginseng); + AddSpell(typeof(HarmScroll), Reg.Nightshade, Reg.SpidersSilk); + AddSpell(typeof(MagicTrapScroll), Reg.Garlic, Reg.SpidersSilk, Reg.SulfurousAsh); + AddSpell(typeof(MagicUnTrapScroll), Reg.Bloodmoss, Reg.SulfurousAsh); + AddSpell(typeof(ProtectionScroll), Reg.Garlic, Reg.Ginseng, Reg.SulfurousAsh); + AddSpell(typeof(StrengthScroll), Reg.Nightshade, Reg.MandrakeRoot); + + m_Circle = 2; + m_Mana = 9; + + AddSpell(typeof(BlessScroll), Reg.Garlic, Reg.MandrakeRoot); + AddSpell(typeof(FireballScroll), Reg.BlackPearl); + AddSpell(typeof(MagicLockScroll), Reg.Bloodmoss, Reg.Garlic, Reg.SulfurousAsh); + AddSpell(typeof(PoisonScroll), Reg.Nightshade); + AddSpell(typeof(TelekinesisScroll), Reg.Bloodmoss, Reg.MandrakeRoot); + AddSpell(typeof(TeleportScroll), Reg.Bloodmoss, Reg.MandrakeRoot); + AddSpell(typeof(UnlockScroll), Reg.Bloodmoss, Reg.SulfurousAsh); + AddSpell(typeof(WallOfStoneScroll), Reg.Bloodmoss, Reg.Garlic); + + m_Circle = 3; + m_Mana = 11; + + AddSpell(typeof(ArchCureScroll), Reg.Garlic, Reg.Ginseng, Reg.MandrakeRoot); + AddSpell(typeof(ArchProtectionScroll), Reg.Garlic, Reg.Ginseng, Reg.MandrakeRoot, Reg.SulfurousAsh); + AddSpell(typeof(CurseScroll), Reg.Garlic, Reg.Nightshade, Reg.SulfurousAsh); + AddSpell(typeof(FireFieldScroll), Reg.BlackPearl, Reg.SpidersSilk, Reg.SulfurousAsh); + AddSpell(typeof(GreaterHealScroll), Reg.Garlic, Reg.SpidersSilk, Reg.MandrakeRoot, Reg.Ginseng); + AddSpell(typeof(LightningScroll), Reg.MandrakeRoot, Reg.SulfurousAsh); + AddSpell(typeof(ManaDrainScroll), Reg.BlackPearl, Reg.SpidersSilk, Reg.MandrakeRoot); + AddSpell(typeof(RecallScroll), Reg.BlackPearl, Reg.Bloodmoss, Reg.MandrakeRoot); + + m_Circle = 4; + m_Mana = 14; + + AddSpell(typeof(BladeSpiritsScroll), Reg.BlackPearl, Reg.Nightshade, Reg.MandrakeRoot); + AddSpell(typeof(DispelFieldScroll), Reg.BlackPearl, Reg.Garlic, Reg.SpidersSilk, Reg.SulfurousAsh); + AddSpell(typeof(IncognitoScroll), Reg.Bloodmoss, Reg.Garlic, Reg.Nightshade); + AddSpell(typeof(MagicReflectScroll), Reg.Garlic, Reg.MandrakeRoot, Reg.SpidersSilk); + AddSpell(typeof(MindBlastScroll), Reg.BlackPearl, Reg.MandrakeRoot, Reg.Nightshade, Reg.SulfurousAsh); + AddSpell(typeof(ParalyzeScroll), Reg.Garlic, Reg.MandrakeRoot, Reg.SpidersSilk); + AddSpell(typeof(PoisonFieldScroll), Reg.BlackPearl, Reg.Nightshade, Reg.SpidersSilk); + AddSpell(typeof(SummonCreatureScroll), Reg.Bloodmoss, Reg.MandrakeRoot, Reg.SpidersSilk); + + m_Circle = 5; + m_Mana = 20; + + AddSpell(typeof(DispelScroll), Reg.Garlic, Reg.MandrakeRoot, Reg.SulfurousAsh); + AddSpell(typeof(EnergyBoltScroll), Reg.BlackPearl, Reg.Nightshade); + AddSpell(typeof(ExplosionScroll), Reg.Bloodmoss, Reg.MandrakeRoot); + AddSpell(typeof(InvisibilityScroll), Reg.Bloodmoss, Reg.Nightshade); + AddSpell(typeof(MarkScroll), Reg.Bloodmoss, Reg.BlackPearl, Reg.MandrakeRoot); + AddSpell(typeof(MassCurseScroll), Reg.Garlic, Reg.MandrakeRoot, Reg.Nightshade, Reg.SulfurousAsh); + AddSpell(typeof(ParalyzeFieldScroll), Reg.BlackPearl, Reg.Ginseng, Reg.SpidersSilk); + AddSpell(typeof(RevealScroll), Reg.Bloodmoss, Reg.SulfurousAsh); + + m_Circle = 6; + m_Mana = 40; + + AddSpell(typeof(ChainLightningScroll), Reg.BlackPearl, Reg.Bloodmoss, Reg.MandrakeRoot, Reg.SulfurousAsh); + AddSpell(typeof(EnergyFieldScroll), Reg.BlackPearl, Reg.MandrakeRoot, Reg.SpidersSilk, Reg.SulfurousAsh); + AddSpell(typeof(FlamestrikeScroll), Reg.SpidersSilk, Reg.SulfurousAsh); + AddSpell(typeof(GateTravelScroll), Reg.BlackPearl, Reg.MandrakeRoot, Reg.SulfurousAsh); + AddSpell(typeof(ManaVampireScroll), Reg.BlackPearl, Reg.Bloodmoss, Reg.MandrakeRoot, Reg.SpidersSilk); + AddSpell(typeof(MassDispelScroll), Reg.BlackPearl, Reg.Garlic, Reg.MandrakeRoot, Reg.SulfurousAsh); + AddSpell(typeof(MeteorSwarmScroll), Reg.Bloodmoss, Reg.MandrakeRoot, Reg.SulfurousAsh, Reg.SpidersSilk); + AddSpell(typeof(PolymorphScroll), Reg.Bloodmoss, Reg.MandrakeRoot, Reg.SpidersSilk); + + m_Circle = 7; + m_Mana = 50; + + AddSpell(typeof(EarthquakeScroll), Reg.Bloodmoss, Reg.MandrakeRoot, Reg.Ginseng, Reg.SulfurousAsh); + AddSpell(typeof(EnergyVortexScroll), Reg.BlackPearl, Reg.Bloodmoss, Reg.MandrakeRoot, Reg.Nightshade); + AddSpell(typeof(ResurrectionScroll), Reg.Bloodmoss, Reg.Garlic, Reg.Ginseng); + AddSpell(typeof(SummonAirElementalScroll), Reg.Bloodmoss, Reg.MandrakeRoot, Reg.SpidersSilk); + AddSpell(typeof(SummonDaemonScroll), Reg.Bloodmoss, Reg.MandrakeRoot, Reg.SpidersSilk, Reg.SulfurousAsh); + AddSpell(typeof(SummonEarthElementalScroll), Reg.Bloodmoss, Reg.MandrakeRoot, Reg.SpidersSilk); + AddSpell(typeof(SummonFireElementalScroll), Reg.Bloodmoss, Reg.MandrakeRoot, Reg.SpidersSilk, Reg.SulfurousAsh); + AddSpell(typeof(SummonWaterElementalScroll), Reg.Bloodmoss, Reg.MandrakeRoot, Reg.SpidersSilk); + + if (Core.SE) + { + AddNecroSpell(0, 23, 39.6, typeof(AnimateDeadScroll), Reagent.GraveDust, Reagent.DaemonBlood); + AddNecroSpell(1, 13, 19.6, typeof(BloodOathScroll), Reagent.DaemonBlood); + AddNecroSpell(2, 11, 19.6, typeof(CorpseSkinScroll), Reagent.BatWing, Reagent.GraveDust); + AddNecroSpell(3, 7, 19.6, typeof(CurseWeaponScroll), Reagent.PigIron); + AddNecroSpell(4, 11, 19.6, typeof(EvilOmenScroll), Reagent.BatWing, Reagent.NoxCrystal); + AddNecroSpell(5, 11, 39.6, typeof(HorrificBeastScroll), Reagent.BatWing, Reagent.DaemonBlood); + AddNecroSpell( + 6, + 23, + 69.6, + typeof(LichFormScroll), + Reagent.GraveDust, + Reagent.DaemonBlood, + Reagent.NoxCrystal + ); + AddNecroSpell(7, 17, 29.6, typeof(MindRotScroll), Reagent.BatWing, Reagent.DaemonBlood, Reagent.PigIron); + AddNecroSpell(8, 5, 19.6, typeof(PainSpikeScroll), Reagent.GraveDust, Reagent.PigIron); + AddNecroSpell(9, 17, 49.6, typeof(PoisonStrikeScroll), Reagent.NoxCrystal); + AddNecroSpell(10, 29, 64.6, typeof(StrangleScroll), Reagent.DaemonBlood, Reagent.NoxCrystal); + AddNecroSpell( + 11, + 17, + 29.6, + typeof(SummonFamiliarScroll), + Reagent.BatWing, + Reagent.GraveDust, + Reagent.DaemonBlood + ); + AddNecroSpell( + 12, + 23, + 98.6, + typeof(VampiricEmbraceScroll), + Reagent.BatWing, + Reagent.NoxCrystal, + Reagent.PigIron + ); + AddNecroSpell( + 13, + 41, + 79.6, + typeof(VengefulSpiritScroll), + Reagent.BatWing, + Reagent.GraveDust, + Reagent.PigIron + ); + AddNecroSpell(14, 23, 59.6, typeof(WitherScroll), Reagent.GraveDust, Reagent.NoxCrystal, Reagent.PigIron); + AddNecroSpell(15, 17, 79.6, typeof(WraithFormScroll), Reagent.NoxCrystal, Reagent.PigIron); + AddNecroSpell(16, 40, 79.6, typeof(ExorcismScroll), Reagent.NoxCrystal, Reagent.GraveDust); + } + + int index; + + if (Core.ML) + { + index = AddCraft( + typeof(EnchantedSwitch), + 1044294, + 1072893, + 45.0, + 95.0, + typeof(BlankScroll), + 1044377, + 1, + 1044378 + ); + AddRes(index, typeof(SpidersSilk), 1044360, 1, 1044253); + AddRes(index, typeof(BlackPearl), 1044353, 1, 1044253); + AddRes(index, typeof(SwitchItem), 1073464, 1, 1044253); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft(typeof(RunedPrism), 1044294, 1073465, 45.0, 95.0, typeof(BlankScroll), 1044377, 1, 1044378); + AddRes(index, typeof(SpidersSilk), 1044360, 1, 1044253); + AddRes(index, typeof(BlackPearl), 1044353, 1, 1044253); + AddRes(index, typeof(HollowPrism), 1072895, 1, 1044253); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + } + + // Runebook + index = AddCraft(typeof(Runebook), 1044294, 1041267, 45.0, 95.0, typeof(BlankScroll), 1044377, 8, 1044378); + AddRes(index, typeof(RecallScroll), 1044445, 1, 1044253); + AddRes(index, typeof(GateTravelScroll), 1044446, 1, 1044253); + + if (Core.AOS) + AddCraft(typeof(BulkOrderBook), 1044294, 1028793, 65.0, 115.0, typeof(BlankScroll), 1044377, 10, 1044378); + + if (Core.SE) AddCraft(typeof(Spellbook), 1044294, 1023834, 50.0, 126, typeof(BlankScroll), 1044377, 10, 1044378); + + /* TODO + if (Core.ML) + { + index = AddCraft( typeof( ScrappersCompendium ), 1044294, 1072940, 75.0, 125.0, typeof( BlankScroll ), 1044377, 100, 1044378 ); + AddRes( index, typeof( DreadHornMane ), 1032682, 1, 1044253 ); + AddRes( index, typeof( Taint ), 1032679, 10, 1044253 ); + AddRes( index, typeof( Corruption ), 1032676, 10, 1044253 ); + AddRareRecipe( index, 400 ); + ForceNonExceptional( index ); + SetNeededExpansion( index, Expansion.ML ); + } + */ + + if (Core.SA) + { + AddCraft(typeof(MysticSpellbook), 1044294, 1031677, 50.0, 150.0, typeof(BlankScroll), 1044377, 10, 1044378); + + AddMysticismSpell(0, 4, -25.0, 25.0, typeof(NetherBoltScroll), Reagent.BlackPearl, Reagent.SulfurousAsh); + AddMysticismSpell( + 1, + 4, + -25.0, + 25.0, + typeof(HealingStoneScroll), + Reagent.Bone, + Reagent.Garlic, + Reagent.Ginseng, + Reagent.SpidersSilk + ); + AddMysticismSpell( + 2, + 6, + -10.8, + 39.2, + typeof(PurgeMagicScroll), + Reagent.FertileDirt, + Reagent.Garlic, + Reagent.MandrakeRoot, + Reagent.SulfurousAsh + ); + AddMysticismSpell( + 3, + 6, + -10.8, + 39.2, + typeof(EnchantScroll), + Reagent.SpidersSilk, + Reagent.MandrakeRoot, + Reagent.SulfurousAsh + ); + AddMysticismSpell( + 4, + 9, + 3.5, + 53.5, + typeof(SleepScroll), + Reagent.Nightshade, + Reagent.SpidersSilk, + Reagent.BlackPearl + ); + AddMysticismSpell( + 5, + 9, + 3.5, + 53.5, + typeof(EagleStrikeScroll), + Reagent.Bloodmoss, + Reagent.Bone, + Reagent.SpidersSilk, + Reagent.MandrakeRoot + ); + AddMysticismSpell( + 6, + 11, + 17.8, + 67.8, + typeof(AnimatedWeaponScroll), + Reagent.Bone, + Reagent.BlackPearl, + Reagent.MandrakeRoot, + Reagent.Nightshade + ); + AddMysticismSpell( + 7, + 11, + 17.8, + 67.8, + typeof(StoneFormScroll), + Reagent.Bloodmoss, + Reagent.FertileDirt, + Reagent.Garlic + ); + AddMysticismSpell( + 8, + 14, + 32.1, + 82.1, + typeof(SpellTriggerScroll), + Reagent.DragonsBlood, + Reagent.Garlic, + Reagent.MandrakeRoot, + Reagent.SpidersSilk + ); + AddMysticismSpell( + 9, + 14, + 32.1, + 82.1, + typeof(MassSleepScroll), + Reagent.Ginseng, + Reagent.Nightshade, + Reagent.SpidersSilk + ); + AddMysticismSpell( + 10, + 20, + 46.4, + 96.4, + typeof(CleansingWindsScroll), + Reagent.DragonsBlood, + Reagent.Garlic, + Reagent.Ginseng, + Reagent.MandrakeRoot + ); + AddMysticismSpell( + 11, + 20, + 46.4, + 96.4, + typeof(BombardScroll), + Reagent.Bloodmoss, + Reagent.DragonsBlood, + Reagent.Garlic, + Reagent.SulfurousAsh + ); + AddMysticismSpell( + 12, + 40, + 60.7, + 110.7, + typeof(SpellPlagueScroll), + Reagent.DaemonBone, + Reagent.DragonsBlood, + Reagent.Nightshade, + Reagent.SulfurousAsh + ); + AddMysticismSpell( + 13, + 40, + 60.7, + 110.7, + typeof(HailStormScroll), + Reagent.DragonsBlood, + Reagent.Bloodmoss, + Reagent.BlackPearl, + Reagent.MandrakeRoot + ); + AddMysticismSpell( + 14, + 50, + 75.0, + 125.0, + typeof(NetherCycloneScroll), + Reagent.MandrakeRoot, + Reagent.Nightshade, + Reagent.SulfurousAsh, + Reagent.Bloodmoss + ); + AddMysticismSpell( + 15, + 50, + 75.0, + 125.0, + typeof(RisingColossusScroll), + Reagent.DaemonBone, + Reagent.DragonsBlood, + Reagent.FertileDirt, + Reagent.Nightshade + ); + } + + MarkOption = true; + } + + private enum Reg + { + BlackPearl, + Bloodmoss, + Garlic, + Ginseng, + MandrakeRoot, + Nightshade, + SulfurousAsh, + SpidersSilk + } + } +} diff --git a/Projects/UOContent/Engines/Craft/DefMasonry.cs b/Projects/UOContent/Engines/Craft/DefMasonry.cs index 3c8ad51ad..dc73c8b5b 100644 --- a/Projects/UOContent/Engines/Craft/DefMasonry.cs +++ b/Projects/UOContent/Engines/Craft/DefMasonry.cs @@ -1,124 +1,135 @@ -using System; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Craft -{ - public class DefMasonry : CraftSystem - { - private static CraftSystem m_CraftSystem; - - private DefMasonry() : base(1, 1, 1.25) // base( 1, 2, 1.7 ) - { - } - - public override SkillName MainSkill => SkillName.Carpentry; - - public override int GumpTitleNumber => 1044500; - - public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefMasonry()); - - public override double GetChanceAtMin(CraftItem item) => 0.0; - - public override bool RetainsColorFrom(CraftItem item, Type type) => true; - - public override int CanCraft(Mobile from, BaseTool tool, Type itemType) - { - if (tool?.Deleted != false || tool.UsesRemaining < 0) - return 1044038; // You have worn out your tool! - if (!BaseTool.CheckTool(tool, from)) - return 1048146; // If you have a tool equipped, you must use that tool. - if (!(from is PlayerMobile mobile && mobile.Masonry && mobile.Skills.Carpentry.Base >= 100.0)) - return 1044633; // You havent learned stonecraft. - if (!BaseTool.CheckAccessible(tool, from)) - return 1044263; // The tool must be on your person to use. - - return 0; - } - - public override void PlayCraftEffect(Mobile from) - { - // no effects - // if (from.Body.Type == BodyType.Human && !from.Mounted) - // from.Animate( 9, 5, 1, true, false, 0 ); - // new InternalTimer( from ).Start(); - } - - public override int PlayEndingEffect(Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, - bool makersMark, CraftItem item) - { - if (toolBroken) - from.SendLocalizedMessage(1044038); // You have worn out your tool - - if (failed) - { - if (lostMaterial) - return 1044043; // You failed to create the item, and some of your materials are lost. - return 1044157; // You failed to create the item, but no materials were lost. - } - - if (quality == 0) - return 502785; // You were barely able to make this item. It's quality is below average. - if (makersMark && quality == 2) - return 1044156; // You create an exceptional quality item and affix your maker's mark. - if (quality == 2) - return 1044155; // You create an exceptional quality item. - return 1044154; // You create the item. - } - - public override void InitCraftList() - { - // Decorations - AddCraft(typeof(Vase), 1044501, 1022888, 52.5, 102.5, typeof(Granite), 1044514, 1, 1044513); - AddCraft(typeof(LargeVase), 1044501, 1022887, 52.5, 102.5, typeof(Granite), 1044514, 3, 1044513); - - if (Core.SE) - { - int index = AddCraft(typeof(SmallUrn), 1044501, 1029244, 82.0, 132.0, typeof(Granite), 1044514, 3, 1044513); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(SmallTowerSculpture), 1044501, 1029242, 82.0, 132.0, typeof(Granite), 1044514, 3, - 1044513); - SetNeededExpansion(index, Expansion.SE); - } - - // Furniture - AddCraft(typeof(StoneChair), 1044502, 1024635, 55.0, 105.0, typeof(Granite), 1044514, 4, 1044513); - AddCraft(typeof(MediumStoneTableEastDeed), 1044502, 1044508, 65.0, 115.0, typeof(Granite), 1044514, 6, 1044513); - AddCraft(typeof(MediumStoneTableSouthDeed), 1044502, 1044509, 65.0, 115.0, typeof(Granite), 1044514, 6, 1044513); - AddCraft(typeof(LargeStoneTableEastDeed), 1044502, 1044511, 75.0, 125.0, typeof(Granite), 1044514, 9, 1044513); - AddCraft(typeof(LargeStoneTableSouthDeed), 1044502, 1044512, 75.0, 125.0, typeof(Granite), 1044514, 9, 1044513); - - // Statues - AddCraft(typeof(StatueSouth), 1044503, 1044505, 60.0, 120.0, typeof(Granite), 1044514, 3, 1044513); - AddCraft(typeof(StatueNorth), 1044503, 1044506, 60.0, 120.0, typeof(Granite), 1044514, 3, 1044513); - AddCraft(typeof(StatueEast), 1044503, 1044507, 60.0, 120.0, typeof(Granite), 1044514, 3, 1044513); - AddCraft(typeof(StatuePegasus), 1044503, 1044510, 70.0, 130.0, typeof(Granite), 1044514, 4, 1044513); - - SetSubRes(typeof(Granite), 1044525); - - AddSubRes(typeof(Granite), 1044525, 00.0, 1044514, 1044526); - AddSubRes(typeof(DullCopperGranite), 1044023, 65.0, 1044514, 1044527); - AddSubRes(typeof(ShadowIronGranite), 1044024, 70.0, 1044514, 1044527); - AddSubRes(typeof(CopperGranite), 1044025, 75.0, 1044514, 1044527); - AddSubRes(typeof(BronzeGranite), 1044026, 80.0, 1044514, 1044527); - AddSubRes(typeof(GoldGranite), 1044027, 85.0, 1044514, 1044527); - AddSubRes(typeof(AgapiteGranite), 1044028, 90.0, 1044514, 1044527); - AddSubRes(typeof(VeriteGranite), 1044029, 95.0, 1044514, 1044527); - AddSubRes(typeof(ValoriteGranite), 1044030, 99.0, 1044514, 1044527); - } - - // Delay to synchronize the sound with the hit on the anvil - private class InternalTimer : Timer - { - private readonly Mobile m_From; - - public InternalTimer(Mobile from) : base(TimeSpan.FromSeconds(0.7)) => m_From = from; - - protected override void OnTick() - { - m_From.PlaySound(0x23D); - } - } - } -} +using System; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Craft +{ + public class DefMasonry : CraftSystem + { + private static CraftSystem m_CraftSystem; + + private DefMasonry() : base(1, 1, 1.25) // base( 1, 2, 1.7 ) + { + } + + public override SkillName MainSkill => SkillName.Carpentry; + + public override int GumpTitleNumber => 1044500; + + public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefMasonry()); + + public override double GetChanceAtMin(CraftItem item) => 0.0; + + public override bool RetainsColorFrom(CraftItem item, Type type) => true; + + public override int CanCraft(Mobile from, BaseTool tool, Type itemType) + { + if (tool?.Deleted != false || tool.UsesRemaining < 0) + return 1044038; // You have worn out your tool! + if (!BaseTool.CheckTool(tool, from)) + return 1048146; // If you have a tool equipped, you must use that tool. + if (!(from is PlayerMobile mobile && mobile.Masonry && mobile.Skills.Carpentry.Base >= 100.0)) + return 1044633; // You havent learned stonecraft. + if (!BaseTool.CheckAccessible(tool, from)) + return 1044263; // The tool must be on your person to use. + + return 0; + } + + public override void PlayCraftEffect(Mobile from) + { + // no effects + // if (from.Body.Type == BodyType.Human && !from.Mounted) + // from.Animate( 9, 5, 1, true, false, 0 ); + // new InternalTimer( from ).Start(); + } + + public override int PlayEndingEffect( + Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, + bool makersMark, CraftItem item + ) + { + if (toolBroken) + from.SendLocalizedMessage(1044038); // You have worn out your tool + + if (failed) + { + if (lostMaterial) + return 1044043; // You failed to create the item, and some of your materials are lost. + return 1044157; // You failed to create the item, but no materials were lost. + } + + if (quality == 0) + return 502785; // You were barely able to make this item. It's quality is below average. + if (makersMark && quality == 2) + return 1044156; // You create an exceptional quality item and affix your maker's mark. + if (quality == 2) + return 1044155; // You create an exceptional quality item. + return 1044154; // You create the item. + } + + public override void InitCraftList() + { + // Decorations + AddCraft(typeof(Vase), 1044501, 1022888, 52.5, 102.5, typeof(Granite), 1044514, 1, 1044513); + AddCraft(typeof(LargeVase), 1044501, 1022887, 52.5, 102.5, typeof(Granite), 1044514, 3, 1044513); + + if (Core.SE) + { + var index = AddCraft(typeof(SmallUrn), 1044501, 1029244, 82.0, 132.0, typeof(Granite), 1044514, 3, 1044513); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(SmallTowerSculpture), + 1044501, + 1029242, + 82.0, + 132.0, + typeof(Granite), + 1044514, + 3, + 1044513 + ); + SetNeededExpansion(index, Expansion.SE); + } + + // Furniture + AddCraft(typeof(StoneChair), 1044502, 1024635, 55.0, 105.0, typeof(Granite), 1044514, 4, 1044513); + AddCraft(typeof(MediumStoneTableEastDeed), 1044502, 1044508, 65.0, 115.0, typeof(Granite), 1044514, 6, 1044513); + AddCraft(typeof(MediumStoneTableSouthDeed), 1044502, 1044509, 65.0, 115.0, typeof(Granite), 1044514, 6, 1044513); + AddCraft(typeof(LargeStoneTableEastDeed), 1044502, 1044511, 75.0, 125.0, typeof(Granite), 1044514, 9, 1044513); + AddCraft(typeof(LargeStoneTableSouthDeed), 1044502, 1044512, 75.0, 125.0, typeof(Granite), 1044514, 9, 1044513); + + // Statues + AddCraft(typeof(StatueSouth), 1044503, 1044505, 60.0, 120.0, typeof(Granite), 1044514, 3, 1044513); + AddCraft(typeof(StatueNorth), 1044503, 1044506, 60.0, 120.0, typeof(Granite), 1044514, 3, 1044513); + AddCraft(typeof(StatueEast), 1044503, 1044507, 60.0, 120.0, typeof(Granite), 1044514, 3, 1044513); + AddCraft(typeof(StatuePegasus), 1044503, 1044510, 70.0, 130.0, typeof(Granite), 1044514, 4, 1044513); + + SetSubRes(typeof(Granite), 1044525); + + AddSubRes(typeof(Granite), 1044525, 00.0, 1044514, 1044526); + AddSubRes(typeof(DullCopperGranite), 1044023, 65.0, 1044514, 1044527); + AddSubRes(typeof(ShadowIronGranite), 1044024, 70.0, 1044514, 1044527); + AddSubRes(typeof(CopperGranite), 1044025, 75.0, 1044514, 1044527); + AddSubRes(typeof(BronzeGranite), 1044026, 80.0, 1044514, 1044527); + AddSubRes(typeof(GoldGranite), 1044027, 85.0, 1044514, 1044527); + AddSubRes(typeof(AgapiteGranite), 1044028, 90.0, 1044514, 1044527); + AddSubRes(typeof(VeriteGranite), 1044029, 95.0, 1044514, 1044527); + AddSubRes(typeof(ValoriteGranite), 1044030, 99.0, 1044514, 1044527); + } + + // Delay to synchronize the sound with the hit on the anvil + private class InternalTimer : Timer + { + private readonly Mobile m_From; + + public InternalTimer(Mobile from) : base(TimeSpan.FromSeconds(0.7)) => m_From = from; + + protected override void OnTick() + { + m_From.PlaySound(0x23D); + } + } + } +} diff --git a/Projects/UOContent/Engines/Craft/DefTailoring.cs b/Projects/UOContent/Engines/Craft/DefTailoring.cs index 433780791..cb864936f 100644 --- a/Projects/UOContent/Engines/Craft/DefTailoring.cs +++ b/Projects/UOContent/Engines/Craft/DefTailoring.cs @@ -1,383 +1,601 @@ -using System; -using Server.Items; - -namespace Server.Engines.Craft -{ - public class DefTailoring : CraftSystem - { - private static CraftSystem m_CraftSystem; - - private static readonly Type[] m_TailorColorables = - { - typeof(GozaMatEastDeed), typeof(GozaMatSouthDeed), - typeof(SquareGozaMatEastDeed), typeof(SquareGozaMatSouthDeed), - typeof(BrocadeGozaMatEastDeed), typeof(BrocadeGozaMatSouthDeed), - typeof(BrocadeSquareGozaMatEastDeed), typeof(BrocadeSquareGozaMatSouthDeed) - }; - - private DefTailoring() : base(1, 1, 1.25) // base( 1, 1, 4.5 ) - { - } - - public override SkillName MainSkill => SkillName.Tailoring; - - public override int GumpTitleNumber => 1044005; - - public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefTailoring()); - - public override CraftECA ECA => CraftECA.ChanceMinusSixtyToFourtyFive; - - public override double GetChanceAtMin(CraftItem item) => 0.5; - - public override int CanCraft(Mobile from, BaseTool tool, Type itemType) - { - if (tool?.Deleted != false || tool.UsesRemaining < 0) - return 1044038; // You have worn out your tool! - - if (!BaseTool.CheckAccessible(tool, from)) - return 1044263; // The tool must be on your person to use. - - return 0; - } - - public override bool RetainsColorFrom(CraftItem item, Type type) - { - if (type != typeof(Cloth) && type != typeof(UncutCloth)) - return false; - - type = item.ItemType; - - bool contains = false; - - for (int i = 0; !contains && i < m_TailorColorables.Length; ++i) - contains = m_TailorColorables[i] == type; - - return contains; - } - - public override void PlayCraftEffect(Mobile from) - { - from.PlaySound(0x248); - } - - public override int PlayEndingEffect(Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, - bool makersMark, CraftItem item) - { - if (toolBroken) - from.SendLocalizedMessage(1044038); // You have worn out your tool - - if (failed) - { - if (lostMaterial) - return 1044043; // You failed to create the item, and some of your materials are lost. - return 1044157; // You failed to create the item, but no materials were lost. - } - - if (quality == 0) - return 502785; // You were barely able to make this item. It's quality is below average. - if (makersMark && quality == 2) - return 1044156; // You create an exceptional quality item and affix your maker's mark. - if (quality == 2) - return 1044155; // You create an exceptional quality item. - return 1044154; // You create the item. - } - - public override void InitCraftList() - { - int index; - - AddCraft(typeof(SkullCap), 1011375, 1025444, 0.0, 25.0, typeof(Cloth), 1044286, 2, 1044287); - AddCraft(typeof(Bandana), 1011375, 1025440, 0.0, 25.0, typeof(Cloth), 1044286, 2, 1044287); - AddCraft(typeof(FloppyHat), 1011375, 1025907, 6.2, 31.2, typeof(Cloth), 1044286, 11, 1044287); - AddCraft(typeof(Cap), 1011375, 1025909, 6.2, 31.2, typeof(Cloth), 1044286, 11, 1044287); - AddCraft(typeof(WideBrimHat), 1011375, 1025908, 6.2, 31.2, typeof(Cloth), 1044286, 12, 1044287); - AddCraft(typeof(StrawHat), 1011375, 1025911, 6.2, 31.2, typeof(Cloth), 1044286, 10, 1044287); - AddCraft(typeof(TallStrawHat), 1011375, 1025910, 6.7, 31.7, typeof(Cloth), 1044286, 13, 1044287); - AddCraft(typeof(WizardsHat), 1011375, 1025912, 7.2, 32.2, typeof(Cloth), 1044286, 15, 1044287); - AddCraft(typeof(Bonnet), 1011375, 1025913, 6.2, 31.2, typeof(Cloth), 1044286, 11, 1044287); - AddCraft(typeof(FeatheredHat), 1011375, 1025914, 6.2, 31.2, typeof(Cloth), 1044286, 12, 1044287); - AddCraft(typeof(TricorneHat), 1011375, 1025915, 6.2, 31.2, typeof(Cloth), 1044286, 12, 1044287); - AddCraft(typeof(JesterHat), 1011375, 1025916, 7.2, 32.2, typeof(Cloth), 1044286, 15, 1044287); - - if (Core.AOS) - AddCraft(typeof(FlowerGarland), 1011375, 1028965, 10.0, 35.0, typeof(Cloth), 1044286, 5, 1044287); - - if (Core.SE) - { - index = AddCraft(typeof(ClothNinjaHood), 1011375, 1030202, 80.0, 105.0, typeof(Cloth), 1044286, 13, 1044287); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(Kasa), 1011375, 1030211, 60.0, 85.0, typeof(Cloth), 1044286, 12, 1044287); - SetNeededExpansion(index, Expansion.SE); - } - - AddCraft(typeof(Doublet), 1015269, 1028059, 0, 25.0, typeof(Cloth), 1044286, 8, 1044287); - AddCraft(typeof(Shirt), 1015269, 1025399, 20.7, 45.7, typeof(Cloth), 1044286, 8, 1044287); - AddCraft(typeof(FancyShirt), 1015269, 1027933, 24.8, 49.8, typeof(Cloth), 1044286, 8, 1044287); - AddCraft(typeof(Tunic), 1015269, 1028097, 00.0, 25.0, typeof(Cloth), 1044286, 12, 1044287); - AddCraft(typeof(Surcoat), 1015269, 1028189, 8.2, 33.2, typeof(Cloth), 1044286, 14, 1044287); - AddCraft(typeof(PlainDress), 1015269, 1027937, 12.4, 37.4, typeof(Cloth), 1044286, 10, 1044287); - AddCraft(typeof(FancyDress), 1015269, 1027935, 33.1, 58.1, typeof(Cloth), 1044286, 12, 1044287); - AddCraft(typeof(Cloak), 1015269, 1025397, 41.4, 66.4, typeof(Cloth), 1044286, 14, 1044287); - AddCraft(typeof(Robe), 1015269, 1027939, 53.9, 78.9, typeof(Cloth), 1044286, 16, 1044287); - AddCraft(typeof(JesterSuit), 1015269, 1028095, 8.2, 33.2, typeof(Cloth), 1044286, 24, 1044287); - - if (Core.AOS) - { - AddCraft(typeof(FurCape), 1015269, 1028969, 35.0, 60.0, typeof(Cloth), 1044286, 13, 1044287); - AddCraft(typeof(GildedDress), 1015269, 1028973, 37.5, 62.5, typeof(Cloth), 1044286, 16, 1044287); - AddCraft(typeof(FormalShirt), 1015269, 1028975, 26.0, 51.0, typeof(Cloth), 1044286, 16, 1044287); - } - - if (Core.SE) - { - index = AddCraft(typeof(ClothNinjaJacket), 1015269, 1030207, 75.0, 100.0, typeof(Cloth), 1044286, 12, - 1044287); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(Kamishimo), 1015269, 1030212, 75.0, 100.0, typeof(Cloth), 1044286, 15, 1044287); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(HakamaShita), 1015269, 1030215, 40.0, 65.0, typeof(Cloth), 1044286, 14, 1044287); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(MaleKimono), 1015269, 1030189, 50.0, 75.0, typeof(Cloth), 1044286, 16, 1044287); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(FemaleKimono), 1015269, 1030190, 50.0, 75.0, typeof(Cloth), 1044286, 16, 1044287); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(JinBaori), 1015269, 1030220, 30.0, 55.0, typeof(Cloth), 1044286, 12, 1044287); - SetNeededExpansion(index, Expansion.SE); - } - - AddCraft(typeof(ShortPants), 1015279, 1025422, 24.8, 49.8, typeof(Cloth), 1044286, 6, 1044287); - AddCraft(typeof(LongPants), 1015279, 1025433, 24.8, 49.8, typeof(Cloth), 1044286, 8, 1044287); - AddCraft(typeof(Kilt), 1015279, 1025431, 20.7, 45.7, typeof(Cloth), 1044286, 8, 1044287); - AddCraft(typeof(Skirt), 1015279, 1025398, 29.0, 54.0, typeof(Cloth), 1044286, 10, 1044287); - - if (Core.AOS) - AddCraft(typeof(FurSarong), 1015279, 1028971, 35.0, 60.0, typeof(Cloth), 1044286, 12, 1044287); - - if (Core.SE) - { - index = AddCraft(typeof(Hakama), 1015279, 1030213, 50.0, 75.0, typeof(Cloth), 1044286, 16, 1044287); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(TattsukeHakama), 1015279, 1030214, 50.0, 75.0, typeof(Cloth), 1044286, 16, 1044287); - SetNeededExpansion(index, Expansion.SE); - } - - AddCraft(typeof(BodySash), 1015283, 1025441, 4.1, 29.1, typeof(Cloth), 1044286, 4, 1044287); - AddCraft(typeof(HalfApron), 1015283, 1025435, 20.7, 45.7, typeof(Cloth), 1044286, 6, 1044287); - AddCraft(typeof(FullApron), 1015283, 1025437, 29.0, 54.0, typeof(Cloth), 1044286, 10, 1044287); - - if (Core.SE) - { - index = AddCraft(typeof(Obi), 1015283, 1030219, 20.0, 45.0, typeof(Cloth), 1044286, 6, 1044287); - SetNeededExpansion(index, Expansion.SE); - } - - if (Core.ML) - { - index = AddCraft(typeof(ElvenQuiver), 1015283, 1032657, 65.0, 115.0, typeof(Leather), 1044462, 28, 1044463); - AddRecipe(index, 501); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(QuiverOfFire), 1015283, 1073109, 65.0, 115.0, typeof(Leather), 1044462, 28, 1044463); - AddRes(index, typeof(FireRuby), 1032695, 15, 1042081); - AddRecipe(index, 502); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(QuiverOfIce), 1015283, 1073110, 65.0, 115.0, typeof(Leather), 1044462, 28, 1044463); - AddRes(index, typeof(WhitePearl), 1032694, 15, 1042081); - AddRecipe(index, 503); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(QuiverOfBlight), 1015283, 1073111, 65.0, 115.0, typeof(Leather), 1044462, 28, - 1044463); - AddRes(index, typeof(Blight), 1032675, 10, 1042081); - AddRecipe(index, 504); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(QuiverOfLightning), 1015283, 1073112, 65.0, 115.0, typeof(Leather), 1044462, 28, - 1044463); - AddRes(index, typeof(Corruption), 1032676, 10, 1042081); - AddRecipe(index, 505); - SetNeededExpansion(index, Expansion.ML); - } - - AddCraft(typeof(OilCloth), 1015283, 1041498, 74.6, 99.6, typeof(Cloth), 1044286, 1, 1044287); - - if (Core.SE) - { - index = AddCraft(typeof(GozaMatEastDeed), 1015283, 1030404, 55.0, 80.0, typeof(Cloth), 1044286, 25, 1044287); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(GozaMatSouthDeed), 1015283, 1030405, 55.0, 80.0, typeof(Cloth), 1044286, 25, - 1044287); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(SquareGozaMatEastDeed), 1015283, 1030407, 55.0, 80.0, typeof(Cloth), 1044286, 25, - 1044287); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(SquareGozaMatSouthDeed), 1015283, 1030406, 55.0, 80.0, typeof(Cloth), 1044286, 25, - 1044287); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(BrocadeGozaMatEastDeed), 1015283, 1030408, 55.0, 80.0, typeof(Cloth), 1044286, 25, - 1044287); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(BrocadeGozaMatSouthDeed), 1015283, 1030409, 55.0, 80.0, typeof(Cloth), 1044286, 25, - 1044287); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(BrocadeSquareGozaMatEastDeed), 1015283, 1030411, 55.0, 80.0, typeof(Cloth), 1044286, - 25, 1044287); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(BrocadeSquareGozaMatSouthDeed), 1015283, 1030410, 55.0, 80.0, typeof(Cloth), 1044286, - 25, 1044287); - SetNeededExpansion(index, Expansion.SE); - } - - if (Core.AOS) - AddCraft(typeof(FurBoots), 1015288, 1028967, 50.0, 75.0, typeof(Cloth), 1044286, 12, 1044287); - - if (Core.SE) - { - index = AddCraft(typeof(NinjaTabi), 1015288, 1030210, 70.0, 95.0, typeof(Cloth), 1044286, 10, 1044287); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(SamuraiTabi), 1015288, 1030209, 20.0, 45.0, typeof(Cloth), 1044286, 6, 1044287); - SetNeededExpansion(index, Expansion.SE); - } - - AddCraft(typeof(Sandals), 1015288, 1025901, 12.4, 37.4, typeof(Leather), 1044462, 4, 1044463); - AddCraft(typeof(Shoes), 1015288, 1025904, 16.5, 41.5, typeof(Leather), 1044462, 6, 1044463); - AddCraft(typeof(Boots), 1015288, 1025899, 33.1, 58.1, typeof(Leather), 1044462, 8, 1044463); - AddCraft(typeof(ThighBoots), 1015288, 1025906, 41.4, 66.4, typeof(Leather), 1044462, 10, 1044463); - - if (Core.ML) - { - index = AddCraft(typeof(SpellWovenBritches), 1015293, 1072929, 92.5, 117.5, typeof(Leather), 1044462, 15, - 1044463); - AddRes(index, typeof(EyeOfTheTravesty), 1032685, 1, 1044253); - AddRes(index, typeof(Putrefication), 1032678, 10, 1044253); - AddRes(index, typeof(Scourge), 1032677, 10, 1044253); - AddRareRecipe(index, 506); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(SongWovenMantle), 1015293, 1072931, 92.5, 117.5, typeof(Leather), 1044462, 15, - 1044463); - AddRes(index, typeof(EyeOfTheTravesty), 1032685, 1, 1044253); - AddRes(index, typeof(Blight), 1032675, 10, 1044253); - AddRes(index, typeof(Muculent), 1032680, 10, 1044253); - AddRareRecipe(index, 507); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(StitchersMittens), 1015293, 1072932, 92.5, 117.5, typeof(Leather), 1044462, 15, - 1044463); - AddRes(index, typeof(CapturedEssence), 1032686, 1, 1044253); - AddRes(index, typeof(Corruption), 1032676, 10, 1044253); - AddRes(index, typeof(Taint), 1032679, 10, 1044253); - AddRareRecipe(index, 508); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - } - - AddCraft(typeof(LeatherGorget), 1015293, 1025063, 53.9, 78.9, typeof(Leather), 1044462, 4, 1044463); - AddCraft(typeof(LeatherCap), 1015293, 1027609, 6.2, 31.2, typeof(Leather), 1044462, 2, 1044463); - AddCraft(typeof(LeatherGloves), 1015293, 1025062, 51.8, 76.8, typeof(Leather), 1044462, 3, 1044463); - AddCraft(typeof(LeatherArms), 1015293, 1025061, 53.9, 78.9, typeof(Leather), 1044462, 4, 1044463); - AddCraft(typeof(LeatherLegs), 1015293, 1025067, 66.3, 91.3, typeof(Leather), 1044462, 10, 1044463); - AddCraft(typeof(LeatherChest), 1015293, 1025068, 70.5, 95.5, typeof(Leather), 1044462, 12, 1044463); - - if (Core.SE) - { - index = AddCraft(typeof(LeatherJingasa), 1015293, 1030177, 45.0, 70.0, typeof(Leather), 1044462, 4, 1044463); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(LeatherMempo), 1015293, 1030181, 80.0, 105.0, typeof(Leather), 1044462, 8, 1044463); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(LeatherDo), 1015293, 1030182, 75.0, 100.0, typeof(Leather), 1044462, 12, 1044463); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(LeatherHiroSode), 1015293, 1030185, 55.0, 80.0, typeof(Leather), 1044462, 5, - 1044463); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(LeatherSuneate), 1015293, 1030193, 68.0, 93.0, typeof(Leather), 1044462, 12, - 1044463); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(LeatherHaidate), 1015293, 1030197, 68.0, 93.0, typeof(Leather), 1044462, 12, - 1044463); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(LeatherNinjaPants), 1015293, 1030204, 80.0, 105.0, typeof(Leather), 1044462, 13, - 1044463); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(LeatherNinjaJacket), 1015293, 1030206, 85.0, 110.0, typeof(Leather), 1044462, 13, - 1044463); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(LeatherNinjaBelt), 1015293, 1030203, 50.0, 75.0, typeof(Leather), 1044462, 5, - 1044463); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(LeatherNinjaMitts), 1015293, 1030205, 65.0, 90.0, typeof(Leather), 1044462, 12, - 1044463); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(LeatherNinjaHood), 1015293, 1030201, 90.0, 115.0, typeof(Leather), 1044462, 14, - 1044463); - SetNeededExpansion(index, Expansion.SE); - } - - AddCraft(typeof(StuddedGorget), 1015300, 1025078, 78.8, 103.8, typeof(Leather), 1044462, 6, 1044463); - AddCraft(typeof(StuddedGloves), 1015300, 1025077, 82.9, 107.9, typeof(Leather), 1044462, 8, 1044463); - AddCraft(typeof(StuddedArms), 1015300, 1025076, 87.1, 112.1, typeof(Leather), 1044462, 10, 1044463); - AddCraft(typeof(StuddedLegs), 1015300, 1025082, 91.2, 116.2, typeof(Leather), 1044462, 12, 1044463); - AddCraft(typeof(StuddedChest), 1015300, 1025083, 94.0, 119.0, typeof(Leather), 1044462, 14, 1044463); - - if (Core.SE) - { - index = AddCraft(typeof(StuddedMempo), 1015300, 1030216, 80.0, 105.0, typeof(Leather), 1044462, 8, 1044463); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(StuddedDo), 1015300, 1030183, 95.0, 120.0, typeof(Leather), 1044462, 14, 1044463); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(StuddedHiroSode), 1015300, 1030186, 85.0, 110.0, typeof(Leather), 1044462, 8, - 1044463); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(StuddedSuneate), 1015300, 1030194, 92.0, 117.0, typeof(Leather), 1044462, 14, - 1044463); - SetNeededExpansion(index, Expansion.SE); - index = AddCraft(typeof(StuddedHaidate), 1015300, 1030198, 92.0, 117.0, typeof(Leather), 1044462, 14, - 1044463); - SetNeededExpansion(index, Expansion.SE); - } - - AddCraft(typeof(LeatherShorts), 1015306, 1027168, 62.2, 87.2, typeof(Leather), 1044462, 8, 1044463); - AddCraft(typeof(LeatherSkirt), 1015306, 1027176, 58.0, 83.0, typeof(Leather), 1044462, 6, 1044463); - AddCraft(typeof(LeatherBustierArms), 1015306, 1027178, 58.0, 83.0, typeof(Leather), 1044462, 6, 1044463); - AddCraft(typeof(StuddedBustierArms), 1015306, 1027180, 82.9, 107.9, typeof(Leather), 1044462, 8, 1044463); - AddCraft(typeof(FemaleLeatherChest), 1015306, 1027174, 62.2, 87.2, typeof(Leather), 1044462, 8, 1044463); - AddCraft(typeof(FemaleStuddedChest), 1015306, 1027170, 87.1, 112.1, typeof(Leather), 1044462, 10, 1044463); - - index = AddCraft(typeof(BoneHelm), 1049149, 1025206, 85.0, 110.0, typeof(Leather), 1044462, 4, 1044463); - AddRes(index, typeof(Bone), 1049064, 2, 1049063); - - index = AddCraft(typeof(BoneGloves), 1049149, 1025205, 89.0, 114.0, typeof(Leather), 1044462, 6, 1044463); - AddRes(index, typeof(Bone), 1049064, 2, 1049063); - - index = AddCraft(typeof(BoneArms), 1049149, 1025203, 92.0, 117.0, typeof(Leather), 1044462, 8, 1044463); - AddRes(index, typeof(Bone), 1049064, 4, 1049063); - - index = AddCraft(typeof(BoneLegs), 1049149, 1025202, 95.0, 120.0, typeof(Leather), 1044462, 10, 1044463); - AddRes(index, typeof(Bone), 1049064, 6, 1049063); - - index = AddCraft(typeof(BoneChest), 1049149, 1025199, 96.0, 121.0, typeof(Leather), 1044462, 12, 1044463); - AddRes(index, typeof(Bone), 1049064, 10, 1049063); - - index = AddCraft(typeof(OrcHelm), 1049149, 1027947, 90.0, 115.0, typeof(Leather), 1044462, 6, 1044463); - AddRes(index, typeof(Bone), 1049064, 4, 1049063); - - // Set the overridable material - SetSubRes(typeof(Leather), 1049150); - - // Add every material you want the player to be able to choose from - // This will override the overridable material - AddSubRes(typeof(Leather), 1049150, 00.0, 1044462, 1049311); - AddSubRes(typeof(SpinedLeather), 1049151, 65.0, 1044462, 1049311); - AddSubRes(typeof(HornedLeather), 1049152, 80.0, 1044462, 1049311); - AddSubRes(typeof(BarbedLeather), 1049153, 99.0, 1044462, 1049311); - - MarkOption = true; - Repair = Core.AOS; - CanEnhance = Core.AOS; - } - } -} +using System; +using Server.Items; + +namespace Server.Engines.Craft +{ + public class DefTailoring : CraftSystem + { + private static CraftSystem m_CraftSystem; + + private static readonly Type[] m_TailorColorables = + { + typeof(GozaMatEastDeed), typeof(GozaMatSouthDeed), + typeof(SquareGozaMatEastDeed), typeof(SquareGozaMatSouthDeed), + typeof(BrocadeGozaMatEastDeed), typeof(BrocadeGozaMatSouthDeed), + typeof(BrocadeSquareGozaMatEastDeed), typeof(BrocadeSquareGozaMatSouthDeed) + }; + + private DefTailoring() : base(1, 1, 1.25) // base( 1, 1, 4.5 ) + { + } + + public override SkillName MainSkill => SkillName.Tailoring; + + public override int GumpTitleNumber => 1044005; + + public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefTailoring()); + + public override CraftECA ECA => CraftECA.ChanceMinusSixtyToFourtyFive; + + public override double GetChanceAtMin(CraftItem item) => 0.5; + + public override int CanCraft(Mobile from, BaseTool tool, Type itemType) + { + if (tool?.Deleted != false || tool.UsesRemaining < 0) + return 1044038; // You have worn out your tool! + + if (!BaseTool.CheckAccessible(tool, from)) + return 1044263; // The tool must be on your person to use. + + return 0; + } + + public override bool RetainsColorFrom(CraftItem item, Type type) + { + if (type != typeof(Cloth) && type != typeof(UncutCloth)) + return false; + + type = item.ItemType; + + var contains = false; + + for (var i = 0; !contains && i < m_TailorColorables.Length; ++i) + contains = m_TailorColorables[i] == type; + + return contains; + } + + public override void PlayCraftEffect(Mobile from) + { + from.PlaySound(0x248); + } + + public override int PlayEndingEffect( + Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, + bool makersMark, CraftItem item + ) + { + if (toolBroken) + from.SendLocalizedMessage(1044038); // You have worn out your tool + + if (failed) + { + if (lostMaterial) + return 1044043; // You failed to create the item, and some of your materials are lost. + return 1044157; // You failed to create the item, but no materials were lost. + } + + if (quality == 0) + return 502785; // You were barely able to make this item. It's quality is below average. + if (makersMark && quality == 2) + return 1044156; // You create an exceptional quality item and affix your maker's mark. + if (quality == 2) + return 1044155; // You create an exceptional quality item. + return 1044154; // You create the item. + } + + public override void InitCraftList() + { + int index; + + AddCraft(typeof(SkullCap), 1011375, 1025444, 0.0, 25.0, typeof(Cloth), 1044286, 2, 1044287); + AddCraft(typeof(Bandana), 1011375, 1025440, 0.0, 25.0, typeof(Cloth), 1044286, 2, 1044287); + AddCraft(typeof(FloppyHat), 1011375, 1025907, 6.2, 31.2, typeof(Cloth), 1044286, 11, 1044287); + AddCraft(typeof(Cap), 1011375, 1025909, 6.2, 31.2, typeof(Cloth), 1044286, 11, 1044287); + AddCraft(typeof(WideBrimHat), 1011375, 1025908, 6.2, 31.2, typeof(Cloth), 1044286, 12, 1044287); + AddCraft(typeof(StrawHat), 1011375, 1025911, 6.2, 31.2, typeof(Cloth), 1044286, 10, 1044287); + AddCraft(typeof(TallStrawHat), 1011375, 1025910, 6.7, 31.7, typeof(Cloth), 1044286, 13, 1044287); + AddCraft(typeof(WizardsHat), 1011375, 1025912, 7.2, 32.2, typeof(Cloth), 1044286, 15, 1044287); + AddCraft(typeof(Bonnet), 1011375, 1025913, 6.2, 31.2, typeof(Cloth), 1044286, 11, 1044287); + AddCraft(typeof(FeatheredHat), 1011375, 1025914, 6.2, 31.2, typeof(Cloth), 1044286, 12, 1044287); + AddCraft(typeof(TricorneHat), 1011375, 1025915, 6.2, 31.2, typeof(Cloth), 1044286, 12, 1044287); + AddCraft(typeof(JesterHat), 1011375, 1025916, 7.2, 32.2, typeof(Cloth), 1044286, 15, 1044287); + + if (Core.AOS) + AddCraft(typeof(FlowerGarland), 1011375, 1028965, 10.0, 35.0, typeof(Cloth), 1044286, 5, 1044287); + + if (Core.SE) + { + index = AddCraft(typeof(ClothNinjaHood), 1011375, 1030202, 80.0, 105.0, typeof(Cloth), 1044286, 13, 1044287); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft(typeof(Kasa), 1011375, 1030211, 60.0, 85.0, typeof(Cloth), 1044286, 12, 1044287); + SetNeededExpansion(index, Expansion.SE); + } + + AddCraft(typeof(Doublet), 1015269, 1028059, 0, 25.0, typeof(Cloth), 1044286, 8, 1044287); + AddCraft(typeof(Shirt), 1015269, 1025399, 20.7, 45.7, typeof(Cloth), 1044286, 8, 1044287); + AddCraft(typeof(FancyShirt), 1015269, 1027933, 24.8, 49.8, typeof(Cloth), 1044286, 8, 1044287); + AddCraft(typeof(Tunic), 1015269, 1028097, 00.0, 25.0, typeof(Cloth), 1044286, 12, 1044287); + AddCraft(typeof(Surcoat), 1015269, 1028189, 8.2, 33.2, typeof(Cloth), 1044286, 14, 1044287); + AddCraft(typeof(PlainDress), 1015269, 1027937, 12.4, 37.4, typeof(Cloth), 1044286, 10, 1044287); + AddCraft(typeof(FancyDress), 1015269, 1027935, 33.1, 58.1, typeof(Cloth), 1044286, 12, 1044287); + AddCraft(typeof(Cloak), 1015269, 1025397, 41.4, 66.4, typeof(Cloth), 1044286, 14, 1044287); + AddCraft(typeof(Robe), 1015269, 1027939, 53.9, 78.9, typeof(Cloth), 1044286, 16, 1044287); + AddCraft(typeof(JesterSuit), 1015269, 1028095, 8.2, 33.2, typeof(Cloth), 1044286, 24, 1044287); + + if (Core.AOS) + { + AddCraft(typeof(FurCape), 1015269, 1028969, 35.0, 60.0, typeof(Cloth), 1044286, 13, 1044287); + AddCraft(typeof(GildedDress), 1015269, 1028973, 37.5, 62.5, typeof(Cloth), 1044286, 16, 1044287); + AddCraft(typeof(FormalShirt), 1015269, 1028975, 26.0, 51.0, typeof(Cloth), 1044286, 16, 1044287); + } + + if (Core.SE) + { + index = AddCraft( + typeof(ClothNinjaJacket), + 1015269, + 1030207, + 75.0, + 100.0, + typeof(Cloth), + 1044286, + 12, + 1044287 + ); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft(typeof(Kamishimo), 1015269, 1030212, 75.0, 100.0, typeof(Cloth), 1044286, 15, 1044287); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft(typeof(HakamaShita), 1015269, 1030215, 40.0, 65.0, typeof(Cloth), 1044286, 14, 1044287); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft(typeof(MaleKimono), 1015269, 1030189, 50.0, 75.0, typeof(Cloth), 1044286, 16, 1044287); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft(typeof(FemaleKimono), 1015269, 1030190, 50.0, 75.0, typeof(Cloth), 1044286, 16, 1044287); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft(typeof(JinBaori), 1015269, 1030220, 30.0, 55.0, typeof(Cloth), 1044286, 12, 1044287); + SetNeededExpansion(index, Expansion.SE); + } + + AddCraft(typeof(ShortPants), 1015279, 1025422, 24.8, 49.8, typeof(Cloth), 1044286, 6, 1044287); + AddCraft(typeof(LongPants), 1015279, 1025433, 24.8, 49.8, typeof(Cloth), 1044286, 8, 1044287); + AddCraft(typeof(Kilt), 1015279, 1025431, 20.7, 45.7, typeof(Cloth), 1044286, 8, 1044287); + AddCraft(typeof(Skirt), 1015279, 1025398, 29.0, 54.0, typeof(Cloth), 1044286, 10, 1044287); + + if (Core.AOS) + AddCraft(typeof(FurSarong), 1015279, 1028971, 35.0, 60.0, typeof(Cloth), 1044286, 12, 1044287); + + if (Core.SE) + { + index = AddCraft(typeof(Hakama), 1015279, 1030213, 50.0, 75.0, typeof(Cloth), 1044286, 16, 1044287); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft(typeof(TattsukeHakama), 1015279, 1030214, 50.0, 75.0, typeof(Cloth), 1044286, 16, 1044287); + SetNeededExpansion(index, Expansion.SE); + } + + AddCraft(typeof(BodySash), 1015283, 1025441, 4.1, 29.1, typeof(Cloth), 1044286, 4, 1044287); + AddCraft(typeof(HalfApron), 1015283, 1025435, 20.7, 45.7, typeof(Cloth), 1044286, 6, 1044287); + AddCraft(typeof(FullApron), 1015283, 1025437, 29.0, 54.0, typeof(Cloth), 1044286, 10, 1044287); + + if (Core.SE) + { + index = AddCraft(typeof(Obi), 1015283, 1030219, 20.0, 45.0, typeof(Cloth), 1044286, 6, 1044287); + SetNeededExpansion(index, Expansion.SE); + } + + if (Core.ML) + { + index = AddCraft(typeof(ElvenQuiver), 1015283, 1032657, 65.0, 115.0, typeof(Leather), 1044462, 28, 1044463); + AddRecipe(index, 501); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft(typeof(QuiverOfFire), 1015283, 1073109, 65.0, 115.0, typeof(Leather), 1044462, 28, 1044463); + AddRes(index, typeof(FireRuby), 1032695, 15, 1042081); + AddRecipe(index, 502); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft(typeof(QuiverOfIce), 1015283, 1073110, 65.0, 115.0, typeof(Leather), 1044462, 28, 1044463); + AddRes(index, typeof(WhitePearl), 1032694, 15, 1042081); + AddRecipe(index, 503); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(QuiverOfBlight), + 1015283, + 1073111, + 65.0, + 115.0, + typeof(Leather), + 1044462, + 28, + 1044463 + ); + AddRes(index, typeof(Blight), 1032675, 10, 1042081); + AddRecipe(index, 504); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(QuiverOfLightning), + 1015283, + 1073112, + 65.0, + 115.0, + typeof(Leather), + 1044462, + 28, + 1044463 + ); + AddRes(index, typeof(Corruption), 1032676, 10, 1042081); + AddRecipe(index, 505); + SetNeededExpansion(index, Expansion.ML); + } + + AddCraft(typeof(OilCloth), 1015283, 1041498, 74.6, 99.6, typeof(Cloth), 1044286, 1, 1044287); + + if (Core.SE) + { + index = AddCraft(typeof(GozaMatEastDeed), 1015283, 1030404, 55.0, 80.0, typeof(Cloth), 1044286, 25, 1044287); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft( + typeof(GozaMatSouthDeed), + 1015283, + 1030405, + 55.0, + 80.0, + typeof(Cloth), + 1044286, + 25, + 1044287 + ); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft( + typeof(SquareGozaMatEastDeed), + 1015283, + 1030407, + 55.0, + 80.0, + typeof(Cloth), + 1044286, + 25, + 1044287 + ); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft( + typeof(SquareGozaMatSouthDeed), + 1015283, + 1030406, + 55.0, + 80.0, + typeof(Cloth), + 1044286, + 25, + 1044287 + ); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft( + typeof(BrocadeGozaMatEastDeed), + 1015283, + 1030408, + 55.0, + 80.0, + typeof(Cloth), + 1044286, + 25, + 1044287 + ); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft( + typeof(BrocadeGozaMatSouthDeed), + 1015283, + 1030409, + 55.0, + 80.0, + typeof(Cloth), + 1044286, + 25, + 1044287 + ); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft( + typeof(BrocadeSquareGozaMatEastDeed), + 1015283, + 1030411, + 55.0, + 80.0, + typeof(Cloth), + 1044286, + 25, + 1044287 + ); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft( + typeof(BrocadeSquareGozaMatSouthDeed), + 1015283, + 1030410, + 55.0, + 80.0, + typeof(Cloth), + 1044286, + 25, + 1044287 + ); + SetNeededExpansion(index, Expansion.SE); + } + + if (Core.AOS) + AddCraft(typeof(FurBoots), 1015288, 1028967, 50.0, 75.0, typeof(Cloth), 1044286, 12, 1044287); + + if (Core.SE) + { + index = AddCraft(typeof(NinjaTabi), 1015288, 1030210, 70.0, 95.0, typeof(Cloth), 1044286, 10, 1044287); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft(typeof(SamuraiTabi), 1015288, 1030209, 20.0, 45.0, typeof(Cloth), 1044286, 6, 1044287); + SetNeededExpansion(index, Expansion.SE); + } + + AddCraft(typeof(Sandals), 1015288, 1025901, 12.4, 37.4, typeof(Leather), 1044462, 4, 1044463); + AddCraft(typeof(Shoes), 1015288, 1025904, 16.5, 41.5, typeof(Leather), 1044462, 6, 1044463); + AddCraft(typeof(Boots), 1015288, 1025899, 33.1, 58.1, typeof(Leather), 1044462, 8, 1044463); + AddCraft(typeof(ThighBoots), 1015288, 1025906, 41.4, 66.4, typeof(Leather), 1044462, 10, 1044463); + + if (Core.ML) + { + index = AddCraft( + typeof(SpellWovenBritches), + 1015293, + 1072929, + 92.5, + 117.5, + typeof(Leather), + 1044462, + 15, + 1044463 + ); + AddRes(index, typeof(EyeOfTheTravesty), 1032685, 1, 1044253); + AddRes(index, typeof(Putrefication), 1032678, 10, 1044253); + AddRes(index, typeof(Scourge), 1032677, 10, 1044253); + AddRareRecipe(index, 506); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(SongWovenMantle), + 1015293, + 1072931, + 92.5, + 117.5, + typeof(Leather), + 1044462, + 15, + 1044463 + ); + AddRes(index, typeof(EyeOfTheTravesty), 1032685, 1, 1044253); + AddRes(index, typeof(Blight), 1032675, 10, 1044253); + AddRes(index, typeof(Muculent), 1032680, 10, 1044253); + AddRareRecipe(index, 507); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(StitchersMittens), + 1015293, + 1072932, + 92.5, + 117.5, + typeof(Leather), + 1044462, + 15, + 1044463 + ); + AddRes(index, typeof(CapturedEssence), 1032686, 1, 1044253); + AddRes(index, typeof(Corruption), 1032676, 10, 1044253); + AddRes(index, typeof(Taint), 1032679, 10, 1044253); + AddRareRecipe(index, 508); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + } + + AddCraft(typeof(LeatherGorget), 1015293, 1025063, 53.9, 78.9, typeof(Leather), 1044462, 4, 1044463); + AddCraft(typeof(LeatherCap), 1015293, 1027609, 6.2, 31.2, typeof(Leather), 1044462, 2, 1044463); + AddCraft(typeof(LeatherGloves), 1015293, 1025062, 51.8, 76.8, typeof(Leather), 1044462, 3, 1044463); + AddCraft(typeof(LeatherArms), 1015293, 1025061, 53.9, 78.9, typeof(Leather), 1044462, 4, 1044463); + AddCraft(typeof(LeatherLegs), 1015293, 1025067, 66.3, 91.3, typeof(Leather), 1044462, 10, 1044463); + AddCraft(typeof(LeatherChest), 1015293, 1025068, 70.5, 95.5, typeof(Leather), 1044462, 12, 1044463); + + if (Core.SE) + { + index = AddCraft(typeof(LeatherJingasa), 1015293, 1030177, 45.0, 70.0, typeof(Leather), 1044462, 4, 1044463); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft(typeof(LeatherMempo), 1015293, 1030181, 80.0, 105.0, typeof(Leather), 1044462, 8, 1044463); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft(typeof(LeatherDo), 1015293, 1030182, 75.0, 100.0, typeof(Leather), 1044462, 12, 1044463); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft( + typeof(LeatherHiroSode), + 1015293, + 1030185, + 55.0, + 80.0, + typeof(Leather), + 1044462, + 5, + 1044463 + ); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft( + typeof(LeatherSuneate), + 1015293, + 1030193, + 68.0, + 93.0, + typeof(Leather), + 1044462, + 12, + 1044463 + ); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft( + typeof(LeatherHaidate), + 1015293, + 1030197, + 68.0, + 93.0, + typeof(Leather), + 1044462, + 12, + 1044463 + ); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft( + typeof(LeatherNinjaPants), + 1015293, + 1030204, + 80.0, + 105.0, + typeof(Leather), + 1044462, + 13, + 1044463 + ); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft( + typeof(LeatherNinjaJacket), + 1015293, + 1030206, + 85.0, + 110.0, + typeof(Leather), + 1044462, + 13, + 1044463 + ); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft( + typeof(LeatherNinjaBelt), + 1015293, + 1030203, + 50.0, + 75.0, + typeof(Leather), + 1044462, + 5, + 1044463 + ); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft( + typeof(LeatherNinjaMitts), + 1015293, + 1030205, + 65.0, + 90.0, + typeof(Leather), + 1044462, + 12, + 1044463 + ); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft( + typeof(LeatherNinjaHood), + 1015293, + 1030201, + 90.0, + 115.0, + typeof(Leather), + 1044462, + 14, + 1044463 + ); + SetNeededExpansion(index, Expansion.SE); + } + + AddCraft(typeof(StuddedGorget), 1015300, 1025078, 78.8, 103.8, typeof(Leather), 1044462, 6, 1044463); + AddCraft(typeof(StuddedGloves), 1015300, 1025077, 82.9, 107.9, typeof(Leather), 1044462, 8, 1044463); + AddCraft(typeof(StuddedArms), 1015300, 1025076, 87.1, 112.1, typeof(Leather), 1044462, 10, 1044463); + AddCraft(typeof(StuddedLegs), 1015300, 1025082, 91.2, 116.2, typeof(Leather), 1044462, 12, 1044463); + AddCraft(typeof(StuddedChest), 1015300, 1025083, 94.0, 119.0, typeof(Leather), 1044462, 14, 1044463); + + if (Core.SE) + { + index = AddCraft(typeof(StuddedMempo), 1015300, 1030216, 80.0, 105.0, typeof(Leather), 1044462, 8, 1044463); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft(typeof(StuddedDo), 1015300, 1030183, 95.0, 120.0, typeof(Leather), 1044462, 14, 1044463); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft( + typeof(StuddedHiroSode), + 1015300, + 1030186, + 85.0, + 110.0, + typeof(Leather), + 1044462, + 8, + 1044463 + ); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft( + typeof(StuddedSuneate), + 1015300, + 1030194, + 92.0, + 117.0, + typeof(Leather), + 1044462, + 14, + 1044463 + ); + SetNeededExpansion(index, Expansion.SE); + index = AddCraft( + typeof(StuddedHaidate), + 1015300, + 1030198, + 92.0, + 117.0, + typeof(Leather), + 1044462, + 14, + 1044463 + ); + SetNeededExpansion(index, Expansion.SE); + } + + AddCraft(typeof(LeatherShorts), 1015306, 1027168, 62.2, 87.2, typeof(Leather), 1044462, 8, 1044463); + AddCraft(typeof(LeatherSkirt), 1015306, 1027176, 58.0, 83.0, typeof(Leather), 1044462, 6, 1044463); + AddCraft(typeof(LeatherBustierArms), 1015306, 1027178, 58.0, 83.0, typeof(Leather), 1044462, 6, 1044463); + AddCraft(typeof(StuddedBustierArms), 1015306, 1027180, 82.9, 107.9, typeof(Leather), 1044462, 8, 1044463); + AddCraft(typeof(FemaleLeatherChest), 1015306, 1027174, 62.2, 87.2, typeof(Leather), 1044462, 8, 1044463); + AddCraft(typeof(FemaleStuddedChest), 1015306, 1027170, 87.1, 112.1, typeof(Leather), 1044462, 10, 1044463); + + index = AddCraft(typeof(BoneHelm), 1049149, 1025206, 85.0, 110.0, typeof(Leather), 1044462, 4, 1044463); + AddRes(index, typeof(Bone), 1049064, 2, 1049063); + + index = AddCraft(typeof(BoneGloves), 1049149, 1025205, 89.0, 114.0, typeof(Leather), 1044462, 6, 1044463); + AddRes(index, typeof(Bone), 1049064, 2, 1049063); + + index = AddCraft(typeof(BoneArms), 1049149, 1025203, 92.0, 117.0, typeof(Leather), 1044462, 8, 1044463); + AddRes(index, typeof(Bone), 1049064, 4, 1049063); + + index = AddCraft(typeof(BoneLegs), 1049149, 1025202, 95.0, 120.0, typeof(Leather), 1044462, 10, 1044463); + AddRes(index, typeof(Bone), 1049064, 6, 1049063); + + index = AddCraft(typeof(BoneChest), 1049149, 1025199, 96.0, 121.0, typeof(Leather), 1044462, 12, 1044463); + AddRes(index, typeof(Bone), 1049064, 10, 1049063); + + index = AddCraft(typeof(OrcHelm), 1049149, 1027947, 90.0, 115.0, typeof(Leather), 1044462, 6, 1044463); + AddRes(index, typeof(Bone), 1049064, 4, 1049063); + + // Set the overridable material + SetSubRes(typeof(Leather), 1049150); + + // Add every material you want the player to be able to choose from + // This will override the overridable material + AddSubRes(typeof(Leather), 1049150, 00.0, 1044462, 1049311); + AddSubRes(typeof(SpinedLeather), 1049151, 65.0, 1044462, 1049311); + AddSubRes(typeof(HornedLeather), 1049152, 80.0, 1044462, 1049311); + AddSubRes(typeof(BarbedLeather), 1049153, 99.0, 1044462, 1049311); + + MarkOption = true; + Repair = Core.AOS; + CanEnhance = Core.AOS; + } + } +} diff --git a/Projects/UOContent/Engines/Craft/DefTinkering.cs b/Projects/UOContent/Engines/Craft/DefTinkering.cs index 4d287b744..c7bc8e4fe 100644 --- a/Projects/UOContent/Engines/Craft/DefTinkering.cs +++ b/Projects/UOContent/Engines/Craft/DefTinkering.cs @@ -1,506 +1,701 @@ -using System; -using Server.Factions; -using Server.Items; -using Server.Targeting; - -namespace Server.Engines.Craft -{ - public class DefTinkering : CraftSystem - { - private static CraftSystem m_CraftSystem; - - private static readonly Type[] m_TinkerColorables = - { - typeof(ForkLeft), typeof(ForkRight), - typeof(SpoonLeft), typeof(SpoonRight), - typeof(KnifeLeft), typeof(KnifeRight), - typeof(Plate), - typeof(Goblet), typeof(PewterMug), - typeof(KeyRing), - typeof(Candelabra), typeof(Scales), - typeof(Key), typeof(Globe), - typeof(Spyglass), typeof(Lantern), - typeof(HeatingStand) - }; - - private DefTinkering() : base(1, 1, 1.25) // base( 1, 1, 3.0 ) - { - } - - public override SkillName MainSkill => SkillName.Tinkering; - - public override int GumpTitleNumber => 1044007; - - public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefTinkering()); - - public override double GetChanceAtMin(CraftItem item) - { - if (item.NameNumber == 1044258 || item.NameNumber == 1046445) // potion keg and faction trap removal kit - return 0.5; // 50% - - return 0.0; // 0% - } - - public override int CanCraft(Mobile from, BaseTool tool, Type itemType) - { - if (tool?.Deleted != false || tool.UsesRemaining < 0) - return 1044038; // You have worn out your tool! - if (!BaseTool.CheckAccessible(tool, from)) - return 1044263; // The tool must be on your person to use. - if (itemType != null && - (itemType.IsSubclassOf(typeof(BaseFactionTrapDeed)) || itemType == typeof(FactionTrapRemovalKit)) && - Faction.Find(from) == null) - return 1044573; // You have to be in a faction to do that. - - return 0; - } - - public override bool RetainsColorFrom(CraftItem item, Type type) - { - if (!type.IsSubclassOf(typeof(BaseIngot))) - return false; - - type = item.ItemType; - - bool contains = false; - - for (int i = 0; !contains && i < m_TinkerColorables.Length; ++i) - contains = m_TinkerColorables[i] == type; - - return contains; - } - - public override void PlayCraftEffect(Mobile from) - { - // no sound - // from.PlaySound( 0x241 ); - } - - public override int PlayEndingEffect(Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, - bool makersMark, CraftItem item) - { - if (toolBroken) - from.SendLocalizedMessage(1044038); // You have worn out your tool - - if (failed) - { - if (lostMaterial) - return 1044043; // You failed to create the item, and some of your materials are lost. - return 1044157; // You failed to create the item, but no materials were lost. - } - - if (quality == 0) - return 502785; // You were barely able to make this item. It's quality is below average. - if (makersMark && quality == 2) - return 1044156; // You create an exceptional quality item and affix your maker's mark. - if (quality == 2) - return 1044155; // You create an exceptional quality item. - return 1044154; // You create the item. - } - - public override bool ConsumeOnFailure(Mobile from, Type resourceType, CraftItem craftItem) - { - if (resourceType == typeof(Silver)) - return false; - - return base.ConsumeOnFailure(from, resourceType, craftItem); - } - - public void AddJewelrySet(GemType gemType, Type itemType) - { - int offset = (int)gemType - 1; - - int index = AddCraft(typeof(GoldRing), 1044049, 1044176 + offset, 40.0, 90.0, typeof(IronIngot), 1044036, 2, - 1044037); - AddRes(index, itemType, 1044231 + offset, 1, 1044240); - - index = AddCraft(typeof(SilverBeadNecklace), 1044049, 1044185 + offset, 40.0, 90.0, typeof(IronIngot), 1044036, - 2, 1044037); - AddRes(index, itemType, 1044231 + offset, 1, 1044240); - - index = AddCraft(typeof(GoldNecklace), 1044049, 1044194 + offset, 40.0, 90.0, typeof(IronIngot), 1044036, 2, - 1044037); - AddRes(index, itemType, 1044231 + offset, 1, 1044240); - - index = AddCraft(typeof(GoldEarrings), 1044049, 1044203 + offset, 40.0, 90.0, typeof(IronIngot), 1044036, 2, - 1044037); - AddRes(index, itemType, 1044231 + offset, 1, 1044240); - - index = AddCraft(typeof(GoldBeadNecklace), 1044049, 1044212 + offset, 40.0, 90.0, typeof(IronIngot), 1044036, 2, - 1044037); - AddRes(index, itemType, 1044231 + offset, 1, 1044240); - - index = AddCraft(typeof(GoldBracelet), 1044049, 1044221 + offset, 40.0, 90.0, typeof(IronIngot), 1044036, 2, - 1044037); - AddRes(index, itemType, 1044231 + offset, 1, 1044240); - } - - public override void InitCraftList() - { - int index; - - AddCraft(typeof(JointingPlane), 1044042, 1024144, 0.0, 50.0, typeof(Log), 1044041, 4, 1044351); - AddCraft(typeof(MouldingPlane), 1044042, 1024140, 0.0, 50.0, typeof(Log), 1044041, 4, 1044351); - AddCraft(typeof(SmoothingPlane), 1044042, 1024146, 0.0, 50.0, typeof(Log), 1044041, 4, 1044351); - AddCraft(typeof(ClockFrame), 1044042, 1024173, 0.0, 50.0, typeof(Log), 1044041, 6, 1044351); - AddCraft(typeof(Axle), 1044042, 1024187, -25.0, 25.0, typeof(Log), 1044041, 2, 1044351); - AddCraft(typeof(RollingPin), 1044042, 1024163, 0.0, 50.0, typeof(Log), 1044041, 5, 1044351); - - if (Core.SE) - { - index = AddCraft(typeof(Nunchaku), 1044042, 1030158, 70.0, 120.0, typeof(IronIngot), 1044036, 3, 1044037); - AddRes(index, typeof(Log), 1044041, 8, 1044351); - SetNeededExpansion(index, Expansion.SE); - } - - AddCraft(typeof(Scissors), 1044046, 1023998, 5.0, 55.0, typeof(IronIngot), 1044036, 2, 1044037); - AddCraft(typeof(MortarPestle), 1044046, 1023739, 20.0, 70.0, typeof(IronIngot), 1044036, 3, 1044037); - AddCraft(typeof(Scorp), 1044046, 1024327, 30.0, 80.0, typeof(IronIngot), 1044036, 2, 1044037); - AddCraft(typeof(TinkerTools), 1044046, 1044164, 10.0, 60.0, typeof(IronIngot), 1044036, 2, 1044037); - AddCraft(typeof(Hatchet), 1044046, 1023907, 30.0, 80.0, typeof(IronIngot), 1044036, 4, 1044037); - AddCraft(typeof(DrawKnife), 1044046, 1024324, 30.0, 80.0, typeof(IronIngot), 1044036, 2, 1044037); - AddCraft(typeof(SewingKit), 1044046, 1023997, 10.0, 70.0, typeof(IronIngot), 1044036, 2, 1044037); - AddCraft(typeof(Saw), 1044046, 1024148, 30.0, 80.0, typeof(IronIngot), 1044036, 4, 1044037); - AddCraft(typeof(DovetailSaw), 1044046, 1024136, 30.0, 80.0, typeof(IronIngot), 1044036, 4, 1044037); - AddCraft(typeof(Froe), 1044046, 1024325, 30.0, 80.0, typeof(IronIngot), 1044036, 2, 1044037); - AddCraft(typeof(Shovel), 1044046, 1023898, 40.0, 90.0, typeof(IronIngot), 1044036, 4, 1044037); - AddCraft(typeof(Hammer), 1044046, 1024138, 30.0, 80.0, typeof(IronIngot), 1044036, 1, 1044037); - AddCraft(typeof(Tongs), 1044046, 1024028, 35.0, 85.0, typeof(IronIngot), 1044036, 1, 1044037); - AddCraft(typeof(SmithHammer), 1044046, 1025091, 40.0, 90.0, typeof(IronIngot), 1044036, 4, 1044037); - AddCraft(typeof(SledgeHammer), 1044046, 1024021, 40.0, 90.0, typeof(IronIngot), 1044036, 4, 1044037); - AddCraft(typeof(Inshave), 1044046, 1024326, 30.0, 80.0, typeof(IronIngot), 1044036, 2, 1044037); - AddCraft(typeof(Pickaxe), 1044046, 1023718, 40.0, 90.0, typeof(IronIngot), 1044036, 4, 1044037); - AddCraft(typeof(Lockpick), 1044046, 1025371, 45.0, 95.0, typeof(IronIngot), 1044036, 1, 1044037); - AddCraft(typeof(Skillet), 1044046, 1044567, 30.0, 80.0, typeof(IronIngot), 1044036, 4, 1044037); - AddCraft(typeof(FlourSifter), 1044046, 1024158, 50.0, 100.0, typeof(IronIngot), 1044036, 3, 1044037); - AddCraft(typeof(FletcherTools), 1044046, 1044166, 35.0, 85.0, typeof(IronIngot), 1044036, 3, 1044037); - AddCraft(typeof(MapmakersPen), 1044046, 1044167, 25.0, 75.0, typeof(IronIngot), 1044036, 1, 1044037); - AddCraft(typeof(ScribesPen), 1044046, 1044168, 25.0, 75.0, typeof(IronIngot), 1044036, 1, 1044037); - - AddCraft(typeof(Gears), 1044047, 1024179, 5.0, 55.0, typeof(IronIngot), 1044036, 2, 1044037); - AddCraft(typeof(ClockParts), 1044047, 1024175, 25.0, 75.0, typeof(IronIngot), 1044036, 1, 1044037); - AddCraft(typeof(BarrelTap), 1044047, 1024100, 35.0, 85.0, typeof(IronIngot), 1044036, 2, 1044037); - AddCraft(typeof(Springs), 1044047, 1024189, 5.0, 55.0, typeof(IronIngot), 1044036, 2, 1044037); - AddCraft(typeof(SextantParts), 1044047, 1024185, 30.0, 80.0, typeof(IronIngot), 1044036, 4, 1044037); - AddCraft(typeof(BarrelHoops), 1044047, 1024321, -15.0, 35.0, typeof(IronIngot), 1044036, 5, 1044037); - AddCraft(typeof(Hinge), 1044047, 1024181, 5.0, 55.0, typeof(IronIngot), 1044036, 2, 1044037); - AddCraft(typeof(BolaBall), 1044047, 1023699, 45.0, 95.0, typeof(IronIngot), 1044036, 10, 1044037); - - if (Core.ML) - { - index = AddCraft(typeof(JeweledFiligree), 1044047, 1072894, 70.0, 110.0, typeof(IronIngot), 1044036, 2, - 1044037); - AddRes(index, typeof(StarSapphire), 1044231, 1, 1044253); - AddRes(index, typeof(Ruby), 1044234, 1, 1044253); - SetNeededExpansion(index, Expansion.ML); - } - - AddCraft(typeof(ButcherKnife), 1044048, 1025110, 25.0, 75.0, typeof(IronIngot), 1044036, 2, 1044037); - AddCraft(typeof(SpoonLeft), 1044048, 1044158, 0.0, 50.0, typeof(IronIngot), 1044036, 1, 1044037); - AddCraft(typeof(SpoonRight), 1044048, 1044159, 0.0, 50.0, typeof(IronIngot), 1044036, 1, 1044037); - AddCraft(typeof(Plate), 1044048, 1022519, 0.0, 50.0, typeof(IronIngot), 1044036, 2, 1044037); - AddCraft(typeof(ForkLeft), 1044048, 1044160, 0.0, 50.0, typeof(IronIngot), 1044036, 1, 1044037); - AddCraft(typeof(ForkRight), 1044048, 1044161, 0.0, 50.0, typeof(IronIngot), 1044036, 1, 1044037); - AddCraft(typeof(Cleaver), 1044048, 1023778, 20.0, 70.0, typeof(IronIngot), 1044036, 3, 1044037); - AddCraft(typeof(KnifeLeft), 1044048, 1044162, 0.0, 50.0, typeof(IronIngot), 1044036, 1, 1044037); - AddCraft(typeof(KnifeRight), 1044048, 1044163, 0.0, 50.0, typeof(IronIngot), 1044036, 1, 1044037); - AddCraft(typeof(Goblet), 1044048, 1022458, 10.0, 60.0, typeof(IronIngot), 1044036, 2, 1044037); - AddCraft(typeof(PewterMug), 1044048, 1024097, 10.0, 60.0, typeof(IronIngot), 1044036, 2, 1044037); - AddCraft(typeof(SkinningKnife), 1044048, 1023781, 25.0, 75.0, typeof(IronIngot), 1044036, 2, 1044037); - - AddCraft(typeof(KeyRing), 1044050, 1024113, 10.0, 60.0, typeof(IronIngot), 1044036, 2, 1044037); - AddCraft(typeof(Candelabra), 1044050, 1022599, 55.0, 105.0, typeof(IronIngot), 1044036, 4, 1044037); - AddCraft(typeof(Scales), 1044050, 1026225, 60.0, 110.0, typeof(IronIngot), 1044036, 4, 1044037); - AddCraft(typeof(Key), 1044050, 1024112, 20.0, 70.0, typeof(IronIngot), 1044036, 3, 1044037); - AddCraft(typeof(Globe), 1044050, 1024167, 55.0, 105.0, typeof(IronIngot), 1044036, 4, 1044037); - AddCraft(typeof(Spyglass), 1044050, 1025365, 60.0, 110.0, typeof(IronIngot), 1044036, 4, 1044037); - AddCraft(typeof(Lantern), 1044050, 1022597, 30.0, 80.0, typeof(IronIngot), 1044036, 2, 1044037); - AddCraft(typeof(HeatingStand), 1044050, 1026217, 60.0, 110.0, typeof(IronIngot), 1044036, 4, 1044037); - - if (Core.SE) - { - index = AddCraft(typeof(ShojiLantern), 1044050, 1029404, 65.0, 115.0, typeof(IronIngot), 1044036, 10, - 1044037); - AddRes(index, typeof(Log), 1044041, 5, 1044351); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(PaperLantern), 1044050, 1029406, 65.0, 115.0, typeof(IronIngot), 1044036, 10, - 1044037); - AddRes(index, typeof(Log), 1044041, 5, 1044351); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(RoundPaperLantern), 1044050, 1029418, 65.0, 115.0, typeof(IronIngot), 1044036, 10, - 1044037); - AddRes(index, typeof(Log), 1044041, 5, 1044351); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(WindChimes), 1044050, 1030290, 80.0, 130.0, typeof(IronIngot), 1044036, 15, 1044037); - SetNeededExpansion(index, Expansion.SE); - - index = AddCraft(typeof(FancyWindChimes), 1044050, 1030291, 80.0, 130.0, typeof(IronIngot), 1044036, 15, - 1044037); - SetNeededExpansion(index, Expansion.SE); - } - - AddJewelrySet(GemType.StarSapphire, typeof(StarSapphire)); - AddJewelrySet(GemType.Emerald, typeof(Emerald)); - AddJewelrySet(GemType.Sapphire, typeof(Sapphire)); - AddJewelrySet(GemType.Ruby, typeof(Ruby)); - AddJewelrySet(GemType.Citrine, typeof(Citrine)); - AddJewelrySet(GemType.Amethyst, typeof(Amethyst)); - AddJewelrySet(GemType.Tourmaline, typeof(Tourmaline)); - AddJewelrySet(GemType.Amber, typeof(Amber)); - AddJewelrySet(GemType.Diamond, typeof(Diamond)); - - index = AddCraft(typeof(AxleGears), 1044051, 1024177, 0.0, 0.0, typeof(Axle), 1044169, 1, 1044253); - AddRes(index, typeof(Gears), 1044254, 1, 1044253); - - index = AddCraft(typeof(ClockParts), 1044051, 1024175, 0.0, 0.0, typeof(AxleGears), 1044170, 1, 1044253); - AddRes(index, typeof(Springs), 1044171, 1, 1044253); - - index = AddCraft(typeof(SextantParts), 1044051, 1024185, 0.0, 0.0, typeof(AxleGears), 1044170, 1, 1044253); - AddRes(index, typeof(Hinge), 1044172, 1, 1044253); - - index = AddCraft(typeof(ClockRight), 1044051, 1044257, 0.0, 0.0, typeof(ClockFrame), 1044174, 1, 1044253); - AddRes(index, typeof(ClockParts), 1044173, 1, 1044253); - - index = AddCraft(typeof(ClockLeft), 1044051, 1044256, 0.0, 0.0, typeof(ClockFrame), 1044174, 1, 1044253); - AddRes(index, typeof(ClockParts), 1044173, 1, 1044253); - - AddCraft(typeof(Sextant), 1044051, 1024183, 0.0, 0.0, typeof(SextantParts), 1044175, 1, 1044253); - - index = AddCraft(typeof(Bola), 1044051, 1046441, 60.0, 80.0, typeof(BolaBall), 1046440, 4, 1042613); - AddRes(index, typeof(Leather), 1044462, 3, 1044463); - - index = AddCraft(typeof(PotionKeg), 1044051, 1044258, 75.0, 100.0, typeof(Keg), 1044255, 1, 1044253); - AddRes(index, typeof(Bottle), 1044250, 10, 1044253); - AddRes(index, typeof(BarrelLid), 1044251, 1, 1044253); - AddRes(index, typeof(BarrelTap), 1044252, 1, 1044253); - - // Dart Trap - index = AddCraft(typeof(DartTrapCraft), 1044052, 1024396, 30.0, 80.0, typeof(IronIngot), 1044036, 1, 1044037); - AddRes(index, typeof(Bolt), 1044570, 1, 1044253); - - // Poison Trap - index = AddCraft(typeof(PoisonTrapCraft), 1044052, 1044593, 30.0, 80.0, typeof(IronIngot), 1044036, 1, 1044037); - AddRes(index, typeof(BasePoisonPotion), 1044571, 1, 1044253); - - // Explosion Trap - index = AddCraft(typeof(ExplosionTrapCraft), 1044052, 1044597, 55.0, 105.0, typeof(IronIngot), 1044036, 1, - 1044037); - AddRes(index, typeof(BaseExplosionPotion), 1044569, 1, 1044253); - - // Faction Gas Trap - index = AddCraft(typeof(FactionGasTrapDeed), 1044052, 1044598, 65.0, 115.0, typeof(Silver), 1044572, - Core.AOS ? 250 : 1000, 1044253); - AddRes(index, typeof(IronIngot), 1044036, 10, 1044037); - AddRes(index, typeof(BasePoisonPotion), 1044571, 1, 1044253); - - // Faction explosion Trap - index = AddCraft(typeof(FactionExplosionTrapDeed), 1044052, 1044599, 65.0, 115.0, typeof(Silver), 1044572, - Core.AOS ? 250 : 1000, 1044253); - AddRes(index, typeof(IronIngot), 1044036, 10, 1044037); - AddRes(index, typeof(BaseExplosionPotion), 1044569, 1, 1044253); - - // Faction Saw Trap - index = AddCraft(typeof(FactionSawTrapDeed), 1044052, 1044600, 65.0, 115.0, typeof(Silver), 1044572, - Core.AOS ? 250 : 1000, 1044253); - AddRes(index, typeof(IronIngot), 1044036, 10, 1044037); - AddRes(index, typeof(Gears), 1044254, 1, 1044253); - - // Faction Spike Trap - index = AddCraft(typeof(FactionSpikeTrapDeed), 1044052, 1044601, 65.0, 115.0, typeof(Silver), 1044572, - Core.AOS ? 250 : 1000, 1044253); - AddRes(index, typeof(IronIngot), 1044036, 10, 1044037); - AddRes(index, typeof(Springs), 1044171, 1, 1044253); - - // Faction trap removal kit - index = AddCraft(typeof(FactionTrapRemovalKit), 1044052, 1046445, 90.0, 115.0, typeof(Silver), 1044572, 500, - 1044253); - AddRes(index, typeof(IronIngot), 1044036, 10, 1044037); - - // Magic Jewelry - if (Core.ML) - { - index = AddCraft(typeof(ResilientBracer), 1073107, 1072933, 100.0, 125.0, typeof(IronIngot), 1044036, 2, - 1044037); - AddRes(index, typeof(CapturedEssence), 1032686, 1, 1044253); - AddRes(index, typeof(BlueDiamond), 1032696, 10, 1044253); - AddRes(index, typeof(Diamond), 1062608, 50, 1044253); - AddRareRecipe(index, 600); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(EssenceOfBattle), 1073107, 1072935, 100.0, 125.0, typeof(IronIngot), 1044036, 2, - 1044037); - AddRes(index, typeof(CapturedEssence), 1032686, 1, 1044253); - AddRes(index, typeof(FireRuby), 1032695, 10, 1044253); - AddRes(index, typeof(Ruby), 1062603, 50, 1044253); - AddRareRecipe(index, 601); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - - index = AddCraft(typeof(PendantOfTheMagi), 1073107, 1072937, 100.0, 125.0, typeof(IronIngot), 1044036, 2, - 1044037); - AddRes(index, typeof(EyeOfTheTravesty), 1032685, 1, 1044253); - AddRes(index, typeof(WhitePearl), 1032694, 10, 1044253); - AddRes(index, typeof(StarSapphire), 1062600, 50, 1044253); - AddRareRecipe(index, 602); - ForceNonExceptional(index); - SetNeededExpansion(index, Expansion.ML); - } - - // Set the overridable material - SetSubRes(typeof(IronIngot), 1044022); - - // Add every material you want the player to be able to choose from - // This will override the overridable material - AddSubRes(typeof(IronIngot), 1044022, 00.0, 1044036, 1044267); - AddSubRes(typeof(DullCopperIngot), 1044023, 65.0, 1044036, 1044268); - AddSubRes(typeof(ShadowIronIngot), 1044024, 70.0, 1044036, 1044268); - AddSubRes(typeof(CopperIngot), 1044025, 75.0, 1044036, 1044268); - AddSubRes(typeof(BronzeIngot), 1044026, 80.0, 1044036, 1044268); - AddSubRes(typeof(GoldIngot), 1044027, 85.0, 1044036, 1044268); - AddSubRes(typeof(AgapiteIngot), 1044028, 90.0, 1044036, 1044268); - AddSubRes(typeof(VeriteIngot), 1044029, 95.0, 1044036, 1044268); - AddSubRes(typeof(ValoriteIngot), 1044030, 99.0, 1044036, 1044268); - - MarkOption = true; - Repair = true; - CanEnhance = Core.AOS; - } - } - - public abstract class TrapCraft : CustomCraft - { - public TrapCraft(Mobile from, CraftItem craftItem, CraftSystem craftSystem, Type typeRes, BaseTool tool, int quality) - : base(from, craftItem, craftSystem, typeRes, tool, quality) - { - } - - public LockableContainer Container { get; private set; } - - public abstract TrapType TrapType { get; } - - private int Verify(LockableContainer container) - { - if (container == null || container.KeyValue == 0) - return 1005638; // You can only trap lockable chests. - if (From.Map != container.Map || !From.InRange(container.GetWorldLocation(), 2)) - return 500446; // That is too far away. - if (!container.Movable) - return 502944; // You cannot trap this item because it is locked down. - if (!container.IsAccessibleTo(From)) - return 502946; // That belongs to someone else. - if (container.Locked) - return 502943; // You can only trap an unlocked object. - if (container.TrapType != TrapType.None) - return 502945; // You can only place one trap on an object at a time. - - return 0; - } - - private bool Acquire(object target, out int message) - { - LockableContainer container = target as LockableContainer; - - message = Verify(container); - - if (message > 0) return false; - - Container = container; - return true; - } - - public override void EndCraftAction() - { - From.SendLocalizedMessage(502921); // What would you like to set a trap on? - From.Target = new ContainerTarget(this); - } - - public override Item CompleteCraft(out int message) - { - message = Verify(Container); - - if (message == 0) - { - int trapLevel = (int)(From.Skills.Tinkering.Value / 10); - - Container.TrapType = TrapType; - Container.TrapPower = trapLevel * 9; - Container.TrapLevel = trapLevel; - Container.TrapOnLockpick = true; - - message = 1005639; // Trap is disabled until you lock the chest. - } - - return null; - } - - private class ContainerTarget : Target - { - private readonly TrapCraft m_TrapCraft; - - public ContainerTarget(TrapCraft trapCraft) : base(-1, false, TargetFlags.None) => m_TrapCraft = trapCraft; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_TrapCraft.Acquire(targeted, out int message)) - m_TrapCraft.CraftItem.CompleteCraft(m_TrapCraft.Quality, false, m_TrapCraft.From, - m_TrapCraft.CraftSystem, m_TrapCraft.TypeRes, m_TrapCraft.Tool, m_TrapCraft); - else - Failure(message); - } - - protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType) - { - if (cancelType == TargetCancelType.Canceled) - Failure(0); - } - - private void Failure(int message) - { - Mobile from = m_TrapCraft.From; - BaseTool tool = m_TrapCraft.Tool; - - if (tool?.Deleted == false && tool.UsesRemaining > 0) - from.SendGump(new CraftGump(from, m_TrapCraft.CraftSystem, tool, message)); - else if (message > 0) - from.SendLocalizedMessage(message); - } - } - } - - [CraftItemID(0x1BFC)] - public class DartTrapCraft : TrapCraft - { - public DartTrapCraft(Mobile from, CraftItem craftItem, CraftSystem craftSystem, Type typeRes, BaseTool tool, - int quality) : base(from, craftItem, craftSystem, typeRes, tool, quality) - { - } - - public override TrapType TrapType => TrapType.DartTrap; - } - - [CraftItemID(0x113E)] - public class PoisonTrapCraft : TrapCraft - { - public PoisonTrapCraft(Mobile from, CraftItem craftItem, CraftSystem craftSystem, Type typeRes, BaseTool tool, - int quality) : base(from, craftItem, craftSystem, typeRes, tool, quality) - { - } - - public override TrapType TrapType => TrapType.PoisonTrap; - } - - [CraftItemID(0x370C)] - public class ExplosionTrapCraft : TrapCraft - { - public ExplosionTrapCraft(Mobile from, CraftItem craftItem, CraftSystem craftSystem, Type typeRes, BaseTool tool, - int quality) : base(from, craftItem, craftSystem, typeRes, tool, quality) - { - } - - public override TrapType TrapType => TrapType.ExplosionTrap; - } -} +using System; +using Server.Factions; +using Server.Items; +using Server.Targeting; + +namespace Server.Engines.Craft +{ + public class DefTinkering : CraftSystem + { + private static CraftSystem m_CraftSystem; + + private static readonly Type[] m_TinkerColorables = + { + typeof(ForkLeft), typeof(ForkRight), + typeof(SpoonLeft), typeof(SpoonRight), + typeof(KnifeLeft), typeof(KnifeRight), + typeof(Plate), + typeof(Goblet), typeof(PewterMug), + typeof(KeyRing), + typeof(Candelabra), typeof(Scales), + typeof(Key), typeof(Globe), + typeof(Spyglass), typeof(Lantern), + typeof(HeatingStand) + }; + + private DefTinkering() : base(1, 1, 1.25) // base( 1, 1, 3.0 ) + { + } + + public override SkillName MainSkill => SkillName.Tinkering; + + public override int GumpTitleNumber => 1044007; + + public static CraftSystem CraftSystem => m_CraftSystem ?? (m_CraftSystem = new DefTinkering()); + + public override double GetChanceAtMin(CraftItem item) + { + if (item.NameNumber == 1044258 || item.NameNumber == 1046445) // potion keg and faction trap removal kit + return 0.5; // 50% + + return 0.0; // 0% + } + + public override int CanCraft(Mobile from, BaseTool tool, Type itemType) + { + if (tool?.Deleted != false || tool.UsesRemaining < 0) + return 1044038; // You have worn out your tool! + if (!BaseTool.CheckAccessible(tool, from)) + return 1044263; // The tool must be on your person to use. + if (itemType != null && + (itemType.IsSubclassOf(typeof(BaseFactionTrapDeed)) || itemType == typeof(FactionTrapRemovalKit)) && + Faction.Find(from) == null) + return 1044573; // You have to be in a faction to do that. + + return 0; + } + + public override bool RetainsColorFrom(CraftItem item, Type type) + { + if (!type.IsSubclassOf(typeof(BaseIngot))) + return false; + + type = item.ItemType; + + var contains = false; + + for (var i = 0; !contains && i < m_TinkerColorables.Length; ++i) + contains = m_TinkerColorables[i] == type; + + return contains; + } + + public override void PlayCraftEffect(Mobile from) + { + // no sound + // from.PlaySound( 0x241 ); + } + + public override int PlayEndingEffect( + Mobile from, bool failed, bool lostMaterial, bool toolBroken, int quality, + bool makersMark, CraftItem item + ) + { + if (toolBroken) + from.SendLocalizedMessage(1044038); // You have worn out your tool + + if (failed) + { + if (lostMaterial) + return 1044043; // You failed to create the item, and some of your materials are lost. + return 1044157; // You failed to create the item, but no materials were lost. + } + + if (quality == 0) + return 502785; // You were barely able to make this item. It's quality is below average. + if (makersMark && quality == 2) + return 1044156; // You create an exceptional quality item and affix your maker's mark. + if (quality == 2) + return 1044155; // You create an exceptional quality item. + return 1044154; // You create the item. + } + + public override bool ConsumeOnFailure(Mobile from, Type resourceType, CraftItem craftItem) + { + if (resourceType == typeof(Silver)) + return false; + + return base.ConsumeOnFailure(from, resourceType, craftItem); + } + + public void AddJewelrySet(GemType gemType, Type itemType) + { + var offset = (int)gemType - 1; + + var index = AddCraft( + typeof(GoldRing), + 1044049, + 1044176 + offset, + 40.0, + 90.0, + typeof(IronIngot), + 1044036, + 2, + 1044037 + ); + AddRes(index, itemType, 1044231 + offset, 1, 1044240); + + index = AddCraft( + typeof(SilverBeadNecklace), + 1044049, + 1044185 + offset, + 40.0, + 90.0, + typeof(IronIngot), + 1044036, + 2, + 1044037 + ); + AddRes(index, itemType, 1044231 + offset, 1, 1044240); + + index = AddCraft( + typeof(GoldNecklace), + 1044049, + 1044194 + offset, + 40.0, + 90.0, + typeof(IronIngot), + 1044036, + 2, + 1044037 + ); + AddRes(index, itemType, 1044231 + offset, 1, 1044240); + + index = AddCraft( + typeof(GoldEarrings), + 1044049, + 1044203 + offset, + 40.0, + 90.0, + typeof(IronIngot), + 1044036, + 2, + 1044037 + ); + AddRes(index, itemType, 1044231 + offset, 1, 1044240); + + index = AddCraft( + typeof(GoldBeadNecklace), + 1044049, + 1044212 + offset, + 40.0, + 90.0, + typeof(IronIngot), + 1044036, + 2, + 1044037 + ); + AddRes(index, itemType, 1044231 + offset, 1, 1044240); + + index = AddCraft( + typeof(GoldBracelet), + 1044049, + 1044221 + offset, + 40.0, + 90.0, + typeof(IronIngot), + 1044036, + 2, + 1044037 + ); + AddRes(index, itemType, 1044231 + offset, 1, 1044240); + } + + public override void InitCraftList() + { + int index; + + AddCraft(typeof(JointingPlane), 1044042, 1024144, 0.0, 50.0, typeof(Log), 1044041, 4, 1044351); + AddCraft(typeof(MouldingPlane), 1044042, 1024140, 0.0, 50.0, typeof(Log), 1044041, 4, 1044351); + AddCraft(typeof(SmoothingPlane), 1044042, 1024146, 0.0, 50.0, typeof(Log), 1044041, 4, 1044351); + AddCraft(typeof(ClockFrame), 1044042, 1024173, 0.0, 50.0, typeof(Log), 1044041, 6, 1044351); + AddCraft(typeof(Axle), 1044042, 1024187, -25.0, 25.0, typeof(Log), 1044041, 2, 1044351); + AddCraft(typeof(RollingPin), 1044042, 1024163, 0.0, 50.0, typeof(Log), 1044041, 5, 1044351); + + if (Core.SE) + { + index = AddCraft(typeof(Nunchaku), 1044042, 1030158, 70.0, 120.0, typeof(IronIngot), 1044036, 3, 1044037); + AddRes(index, typeof(Log), 1044041, 8, 1044351); + SetNeededExpansion(index, Expansion.SE); + } + + AddCraft(typeof(Scissors), 1044046, 1023998, 5.0, 55.0, typeof(IronIngot), 1044036, 2, 1044037); + AddCraft(typeof(MortarPestle), 1044046, 1023739, 20.0, 70.0, typeof(IronIngot), 1044036, 3, 1044037); + AddCraft(typeof(Scorp), 1044046, 1024327, 30.0, 80.0, typeof(IronIngot), 1044036, 2, 1044037); + AddCraft(typeof(TinkerTools), 1044046, 1044164, 10.0, 60.0, typeof(IronIngot), 1044036, 2, 1044037); + AddCraft(typeof(Hatchet), 1044046, 1023907, 30.0, 80.0, typeof(IronIngot), 1044036, 4, 1044037); + AddCraft(typeof(DrawKnife), 1044046, 1024324, 30.0, 80.0, typeof(IronIngot), 1044036, 2, 1044037); + AddCraft(typeof(SewingKit), 1044046, 1023997, 10.0, 70.0, typeof(IronIngot), 1044036, 2, 1044037); + AddCraft(typeof(Saw), 1044046, 1024148, 30.0, 80.0, typeof(IronIngot), 1044036, 4, 1044037); + AddCraft(typeof(DovetailSaw), 1044046, 1024136, 30.0, 80.0, typeof(IronIngot), 1044036, 4, 1044037); + AddCraft(typeof(Froe), 1044046, 1024325, 30.0, 80.0, typeof(IronIngot), 1044036, 2, 1044037); + AddCraft(typeof(Shovel), 1044046, 1023898, 40.0, 90.0, typeof(IronIngot), 1044036, 4, 1044037); + AddCraft(typeof(Hammer), 1044046, 1024138, 30.0, 80.0, typeof(IronIngot), 1044036, 1, 1044037); + AddCraft(typeof(Tongs), 1044046, 1024028, 35.0, 85.0, typeof(IronIngot), 1044036, 1, 1044037); + AddCraft(typeof(SmithHammer), 1044046, 1025091, 40.0, 90.0, typeof(IronIngot), 1044036, 4, 1044037); + AddCraft(typeof(SledgeHammer), 1044046, 1024021, 40.0, 90.0, typeof(IronIngot), 1044036, 4, 1044037); + AddCraft(typeof(Inshave), 1044046, 1024326, 30.0, 80.0, typeof(IronIngot), 1044036, 2, 1044037); + AddCraft(typeof(Pickaxe), 1044046, 1023718, 40.0, 90.0, typeof(IronIngot), 1044036, 4, 1044037); + AddCraft(typeof(Lockpick), 1044046, 1025371, 45.0, 95.0, typeof(IronIngot), 1044036, 1, 1044037); + AddCraft(typeof(Skillet), 1044046, 1044567, 30.0, 80.0, typeof(IronIngot), 1044036, 4, 1044037); + AddCraft(typeof(FlourSifter), 1044046, 1024158, 50.0, 100.0, typeof(IronIngot), 1044036, 3, 1044037); + AddCraft(typeof(FletcherTools), 1044046, 1044166, 35.0, 85.0, typeof(IronIngot), 1044036, 3, 1044037); + AddCraft(typeof(MapmakersPen), 1044046, 1044167, 25.0, 75.0, typeof(IronIngot), 1044036, 1, 1044037); + AddCraft(typeof(ScribesPen), 1044046, 1044168, 25.0, 75.0, typeof(IronIngot), 1044036, 1, 1044037); + + AddCraft(typeof(Gears), 1044047, 1024179, 5.0, 55.0, typeof(IronIngot), 1044036, 2, 1044037); + AddCraft(typeof(ClockParts), 1044047, 1024175, 25.0, 75.0, typeof(IronIngot), 1044036, 1, 1044037); + AddCraft(typeof(BarrelTap), 1044047, 1024100, 35.0, 85.0, typeof(IronIngot), 1044036, 2, 1044037); + AddCraft(typeof(Springs), 1044047, 1024189, 5.0, 55.0, typeof(IronIngot), 1044036, 2, 1044037); + AddCraft(typeof(SextantParts), 1044047, 1024185, 30.0, 80.0, typeof(IronIngot), 1044036, 4, 1044037); + AddCraft(typeof(BarrelHoops), 1044047, 1024321, -15.0, 35.0, typeof(IronIngot), 1044036, 5, 1044037); + AddCraft(typeof(Hinge), 1044047, 1024181, 5.0, 55.0, typeof(IronIngot), 1044036, 2, 1044037); + AddCraft(typeof(BolaBall), 1044047, 1023699, 45.0, 95.0, typeof(IronIngot), 1044036, 10, 1044037); + + if (Core.ML) + { + index = AddCraft( + typeof(JeweledFiligree), + 1044047, + 1072894, + 70.0, + 110.0, + typeof(IronIngot), + 1044036, + 2, + 1044037 + ); + AddRes(index, typeof(StarSapphire), 1044231, 1, 1044253); + AddRes(index, typeof(Ruby), 1044234, 1, 1044253); + SetNeededExpansion(index, Expansion.ML); + } + + AddCraft(typeof(ButcherKnife), 1044048, 1025110, 25.0, 75.0, typeof(IronIngot), 1044036, 2, 1044037); + AddCraft(typeof(SpoonLeft), 1044048, 1044158, 0.0, 50.0, typeof(IronIngot), 1044036, 1, 1044037); + AddCraft(typeof(SpoonRight), 1044048, 1044159, 0.0, 50.0, typeof(IronIngot), 1044036, 1, 1044037); + AddCraft(typeof(Plate), 1044048, 1022519, 0.0, 50.0, typeof(IronIngot), 1044036, 2, 1044037); + AddCraft(typeof(ForkLeft), 1044048, 1044160, 0.0, 50.0, typeof(IronIngot), 1044036, 1, 1044037); + AddCraft(typeof(ForkRight), 1044048, 1044161, 0.0, 50.0, typeof(IronIngot), 1044036, 1, 1044037); + AddCraft(typeof(Cleaver), 1044048, 1023778, 20.0, 70.0, typeof(IronIngot), 1044036, 3, 1044037); + AddCraft(typeof(KnifeLeft), 1044048, 1044162, 0.0, 50.0, typeof(IronIngot), 1044036, 1, 1044037); + AddCraft(typeof(KnifeRight), 1044048, 1044163, 0.0, 50.0, typeof(IronIngot), 1044036, 1, 1044037); + AddCraft(typeof(Goblet), 1044048, 1022458, 10.0, 60.0, typeof(IronIngot), 1044036, 2, 1044037); + AddCraft(typeof(PewterMug), 1044048, 1024097, 10.0, 60.0, typeof(IronIngot), 1044036, 2, 1044037); + AddCraft(typeof(SkinningKnife), 1044048, 1023781, 25.0, 75.0, typeof(IronIngot), 1044036, 2, 1044037); + + AddCraft(typeof(KeyRing), 1044050, 1024113, 10.0, 60.0, typeof(IronIngot), 1044036, 2, 1044037); + AddCraft(typeof(Candelabra), 1044050, 1022599, 55.0, 105.0, typeof(IronIngot), 1044036, 4, 1044037); + AddCraft(typeof(Scales), 1044050, 1026225, 60.0, 110.0, typeof(IronIngot), 1044036, 4, 1044037); + AddCraft(typeof(Key), 1044050, 1024112, 20.0, 70.0, typeof(IronIngot), 1044036, 3, 1044037); + AddCraft(typeof(Globe), 1044050, 1024167, 55.0, 105.0, typeof(IronIngot), 1044036, 4, 1044037); + AddCraft(typeof(Spyglass), 1044050, 1025365, 60.0, 110.0, typeof(IronIngot), 1044036, 4, 1044037); + AddCraft(typeof(Lantern), 1044050, 1022597, 30.0, 80.0, typeof(IronIngot), 1044036, 2, 1044037); + AddCraft(typeof(HeatingStand), 1044050, 1026217, 60.0, 110.0, typeof(IronIngot), 1044036, 4, 1044037); + + if (Core.SE) + { + index = AddCraft( + typeof(ShojiLantern), + 1044050, + 1029404, + 65.0, + 115.0, + typeof(IronIngot), + 1044036, + 10, + 1044037 + ); + AddRes(index, typeof(Log), 1044041, 5, 1044351); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(PaperLantern), + 1044050, + 1029406, + 65.0, + 115.0, + typeof(IronIngot), + 1044036, + 10, + 1044037 + ); + AddRes(index, typeof(Log), 1044041, 5, 1044351); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(RoundPaperLantern), + 1044050, + 1029418, + 65.0, + 115.0, + typeof(IronIngot), + 1044036, + 10, + 1044037 + ); + AddRes(index, typeof(Log), 1044041, 5, 1044351); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft(typeof(WindChimes), 1044050, 1030290, 80.0, 130.0, typeof(IronIngot), 1044036, 15, 1044037); + SetNeededExpansion(index, Expansion.SE); + + index = AddCraft( + typeof(FancyWindChimes), + 1044050, + 1030291, + 80.0, + 130.0, + typeof(IronIngot), + 1044036, + 15, + 1044037 + ); + SetNeededExpansion(index, Expansion.SE); + } + + AddJewelrySet(GemType.StarSapphire, typeof(StarSapphire)); + AddJewelrySet(GemType.Emerald, typeof(Emerald)); + AddJewelrySet(GemType.Sapphire, typeof(Sapphire)); + AddJewelrySet(GemType.Ruby, typeof(Ruby)); + AddJewelrySet(GemType.Citrine, typeof(Citrine)); + AddJewelrySet(GemType.Amethyst, typeof(Amethyst)); + AddJewelrySet(GemType.Tourmaline, typeof(Tourmaline)); + AddJewelrySet(GemType.Amber, typeof(Amber)); + AddJewelrySet(GemType.Diamond, typeof(Diamond)); + + index = AddCraft(typeof(AxleGears), 1044051, 1024177, 0.0, 0.0, typeof(Axle), 1044169, 1, 1044253); + AddRes(index, typeof(Gears), 1044254, 1, 1044253); + + index = AddCraft(typeof(ClockParts), 1044051, 1024175, 0.0, 0.0, typeof(AxleGears), 1044170, 1, 1044253); + AddRes(index, typeof(Springs), 1044171, 1, 1044253); + + index = AddCraft(typeof(SextantParts), 1044051, 1024185, 0.0, 0.0, typeof(AxleGears), 1044170, 1, 1044253); + AddRes(index, typeof(Hinge), 1044172, 1, 1044253); + + index = AddCraft(typeof(ClockRight), 1044051, 1044257, 0.0, 0.0, typeof(ClockFrame), 1044174, 1, 1044253); + AddRes(index, typeof(ClockParts), 1044173, 1, 1044253); + + index = AddCraft(typeof(ClockLeft), 1044051, 1044256, 0.0, 0.0, typeof(ClockFrame), 1044174, 1, 1044253); + AddRes(index, typeof(ClockParts), 1044173, 1, 1044253); + + AddCraft(typeof(Sextant), 1044051, 1024183, 0.0, 0.0, typeof(SextantParts), 1044175, 1, 1044253); + + index = AddCraft(typeof(Bola), 1044051, 1046441, 60.0, 80.0, typeof(BolaBall), 1046440, 4, 1042613); + AddRes(index, typeof(Leather), 1044462, 3, 1044463); + + index = AddCraft(typeof(PotionKeg), 1044051, 1044258, 75.0, 100.0, typeof(Keg), 1044255, 1, 1044253); + AddRes(index, typeof(Bottle), 1044250, 10, 1044253); + AddRes(index, typeof(BarrelLid), 1044251, 1, 1044253); + AddRes(index, typeof(BarrelTap), 1044252, 1, 1044253); + + // Dart Trap + index = AddCraft(typeof(DartTrapCraft), 1044052, 1024396, 30.0, 80.0, typeof(IronIngot), 1044036, 1, 1044037); + AddRes(index, typeof(Bolt), 1044570, 1, 1044253); + + // Poison Trap + index = AddCraft(typeof(PoisonTrapCraft), 1044052, 1044593, 30.0, 80.0, typeof(IronIngot), 1044036, 1, 1044037); + AddRes(index, typeof(BasePoisonPotion), 1044571, 1, 1044253); + + // Explosion Trap + index = AddCraft( + typeof(ExplosionTrapCraft), + 1044052, + 1044597, + 55.0, + 105.0, + typeof(IronIngot), + 1044036, + 1, + 1044037 + ); + AddRes(index, typeof(BaseExplosionPotion), 1044569, 1, 1044253); + + // Faction Gas Trap + index = AddCraft( + typeof(FactionGasTrapDeed), + 1044052, + 1044598, + 65.0, + 115.0, + typeof(Silver), + 1044572, + Core.AOS ? 250 : 1000, + 1044253 + ); + AddRes(index, typeof(IronIngot), 1044036, 10, 1044037); + AddRes(index, typeof(BasePoisonPotion), 1044571, 1, 1044253); + + // Faction explosion Trap + index = AddCraft( + typeof(FactionExplosionTrapDeed), + 1044052, + 1044599, + 65.0, + 115.0, + typeof(Silver), + 1044572, + Core.AOS ? 250 : 1000, + 1044253 + ); + AddRes(index, typeof(IronIngot), 1044036, 10, 1044037); + AddRes(index, typeof(BaseExplosionPotion), 1044569, 1, 1044253); + + // Faction Saw Trap + index = AddCraft( + typeof(FactionSawTrapDeed), + 1044052, + 1044600, + 65.0, + 115.0, + typeof(Silver), + 1044572, + Core.AOS ? 250 : 1000, + 1044253 + ); + AddRes(index, typeof(IronIngot), 1044036, 10, 1044037); + AddRes(index, typeof(Gears), 1044254, 1, 1044253); + + // Faction Spike Trap + index = AddCraft( + typeof(FactionSpikeTrapDeed), + 1044052, + 1044601, + 65.0, + 115.0, + typeof(Silver), + 1044572, + Core.AOS ? 250 : 1000, + 1044253 + ); + AddRes(index, typeof(IronIngot), 1044036, 10, 1044037); + AddRes(index, typeof(Springs), 1044171, 1, 1044253); + + // Faction trap removal kit + index = AddCraft( + typeof(FactionTrapRemovalKit), + 1044052, + 1046445, + 90.0, + 115.0, + typeof(Silver), + 1044572, + 500, + 1044253 + ); + AddRes(index, typeof(IronIngot), 1044036, 10, 1044037); + + // Magic Jewelry + if (Core.ML) + { + index = AddCraft( + typeof(ResilientBracer), + 1073107, + 1072933, + 100.0, + 125.0, + typeof(IronIngot), + 1044036, + 2, + 1044037 + ); + AddRes(index, typeof(CapturedEssence), 1032686, 1, 1044253); + AddRes(index, typeof(BlueDiamond), 1032696, 10, 1044253); + AddRes(index, typeof(Diamond), 1062608, 50, 1044253); + AddRareRecipe(index, 600); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(EssenceOfBattle), + 1073107, + 1072935, + 100.0, + 125.0, + typeof(IronIngot), + 1044036, + 2, + 1044037 + ); + AddRes(index, typeof(CapturedEssence), 1032686, 1, 1044253); + AddRes(index, typeof(FireRuby), 1032695, 10, 1044253); + AddRes(index, typeof(Ruby), 1062603, 50, 1044253); + AddRareRecipe(index, 601); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + + index = AddCraft( + typeof(PendantOfTheMagi), + 1073107, + 1072937, + 100.0, + 125.0, + typeof(IronIngot), + 1044036, + 2, + 1044037 + ); + AddRes(index, typeof(EyeOfTheTravesty), 1032685, 1, 1044253); + AddRes(index, typeof(WhitePearl), 1032694, 10, 1044253); + AddRes(index, typeof(StarSapphire), 1062600, 50, 1044253); + AddRareRecipe(index, 602); + ForceNonExceptional(index); + SetNeededExpansion(index, Expansion.ML); + } + + // Set the overridable material + SetSubRes(typeof(IronIngot), 1044022); + + // Add every material you want the player to be able to choose from + // This will override the overridable material + AddSubRes(typeof(IronIngot), 1044022, 00.0, 1044036, 1044267); + AddSubRes(typeof(DullCopperIngot), 1044023, 65.0, 1044036, 1044268); + AddSubRes(typeof(ShadowIronIngot), 1044024, 70.0, 1044036, 1044268); + AddSubRes(typeof(CopperIngot), 1044025, 75.0, 1044036, 1044268); + AddSubRes(typeof(BronzeIngot), 1044026, 80.0, 1044036, 1044268); + AddSubRes(typeof(GoldIngot), 1044027, 85.0, 1044036, 1044268); + AddSubRes(typeof(AgapiteIngot), 1044028, 90.0, 1044036, 1044268); + AddSubRes(typeof(VeriteIngot), 1044029, 95.0, 1044036, 1044268); + AddSubRes(typeof(ValoriteIngot), 1044030, 99.0, 1044036, 1044268); + + MarkOption = true; + Repair = true; + CanEnhance = Core.AOS; + } + } + + public abstract class TrapCraft : CustomCraft + { + public TrapCraft(Mobile from, CraftItem craftItem, CraftSystem craftSystem, Type typeRes, BaseTool tool, int quality) + : base(from, craftItem, craftSystem, typeRes, tool, quality) + { + } + + public LockableContainer Container { get; private set; } + + public abstract TrapType TrapType { get; } + + private int Verify(LockableContainer container) + { + if (container == null || container.KeyValue == 0) + return 1005638; // You can only trap lockable chests. + if (From.Map != container.Map || !From.InRange(container.GetWorldLocation(), 2)) + return 500446; // That is too far away. + if (!container.Movable) + return 502944; // You cannot trap this item because it is locked down. + if (!container.IsAccessibleTo(From)) + return 502946; // That belongs to someone else. + if (container.Locked) + return 502943; // You can only trap an unlocked object. + if (container.TrapType != TrapType.None) + return 502945; // You can only place one trap on an object at a time. + + return 0; + } + + private bool Acquire(object target, out int message) + { + var container = target as LockableContainer; + + message = Verify(container); + + if (message > 0) return false; + + Container = container; + return true; + } + + public override void EndCraftAction() + { + From.SendLocalizedMessage(502921); // What would you like to set a trap on? + From.Target = new ContainerTarget(this); + } + + public override Item CompleteCraft(out int message) + { + message = Verify(Container); + + if (message == 0) + { + var trapLevel = (int)(From.Skills.Tinkering.Value / 10); + + Container.TrapType = TrapType; + Container.TrapPower = trapLevel * 9; + Container.TrapLevel = trapLevel; + Container.TrapOnLockpick = true; + + message = 1005639; // Trap is disabled until you lock the chest. + } + + return null; + } + + private class ContainerTarget : Target + { + private readonly TrapCraft m_TrapCraft; + + public ContainerTarget(TrapCraft trapCraft) : base(-1, false, TargetFlags.None) => m_TrapCraft = trapCraft; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_TrapCraft.Acquire(targeted, out var message)) + m_TrapCraft.CraftItem.CompleteCraft( + m_TrapCraft.Quality, + false, + m_TrapCraft.From, + m_TrapCraft.CraftSystem, + m_TrapCraft.TypeRes, + m_TrapCraft.Tool, + m_TrapCraft + ); + else + Failure(message); + } + + protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType) + { + if (cancelType == TargetCancelType.Canceled) + Failure(0); + } + + private void Failure(int message) + { + var from = m_TrapCraft.From; + var tool = m_TrapCraft.Tool; + + if (tool?.Deleted == false && tool.UsesRemaining > 0) + from.SendGump(new CraftGump(from, m_TrapCraft.CraftSystem, tool, message)); + else if (message > 0) + from.SendLocalizedMessage(message); + } + } + } + + [CraftItemID(0x1BFC)] + public class DartTrapCraft : TrapCraft + { + public DartTrapCraft( + Mobile from, CraftItem craftItem, CraftSystem craftSystem, Type typeRes, BaseTool tool, + int quality + ) : base(from, craftItem, craftSystem, typeRes, tool, quality) + { + } + + public override TrapType TrapType => TrapType.DartTrap; + } + + [CraftItemID(0x113E)] + public class PoisonTrapCraft : TrapCraft + { + public PoisonTrapCraft( + Mobile from, CraftItem craftItem, CraftSystem craftSystem, Type typeRes, BaseTool tool, + int quality + ) : base(from, craftItem, craftSystem, typeRes, tool, quality) + { + } + + public override TrapType TrapType => TrapType.PoisonTrap; + } + + [CraftItemID(0x370C)] + public class ExplosionTrapCraft : TrapCraft + { + public ExplosionTrapCraft( + Mobile from, CraftItem craftItem, CraftSystem craftSystem, Type typeRes, BaseTool tool, + int quality + ) : base(from, craftItem, craftSystem, typeRes, tool, quality) + { + } + + public override TrapType TrapType => TrapType.ExplosionTrap; + } +} diff --git a/Projects/UOContent/Engines/Doom/GauntletSpawner.cs b/Projects/UOContent/Engines/Doom/GauntletSpawner.cs index ae226f253..6fa9e2c39 100644 --- a/Projects/UOContent/Engines/Doom/GauntletSpawner.cs +++ b/Projects/UOContent/Engines/Doom/GauntletSpawner.cs @@ -1,639 +1,643 @@ -using System; -using System.Collections.Generic; -using Server.Items; -using Server.Mobiles; -using Server.Regions; -using Server.Utilities; - -namespace Server.Engines.Doom -{ - public enum GauntletSpawnerState - { - InSequence, - InProgress, - Completed - } - - public class GauntletSpawner : Item - { - public const int PlayersPerSpawn = 5; - - public const int InSequenceItemHue = 0x000; - public const int InProgressItemHue = 0x676; - public const int CompletedItemHue = 0x455; - - private GauntletSpawnerState m_State; - - private Timer m_Timer; - - [Constructible] - public GauntletSpawner(string typeName = null) : base(0x36FE) - { - Visible = false; - Movable = false; - - TypeName = typeName; - Creatures = new List(); - Traps = new List(); - } - - public GauntletSpawner(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public string TypeName { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public BaseDoor Door { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public BaseAddon Addon { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public GauntletSpawner Sequence { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool HasCompleted - { - get - { - if (Creatures.Count == 0) - return false; - - for (int i = 0; i < Creatures.Count; ++i) - { - Mobile mob = Creatures[i]; - - if (!mob.Deleted) - return false; - } - - return true; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Rectangle2D RegionBounds { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public GauntletSpawnerState State - { - get => m_State; - set - { - if (m_State == value) - return; - - m_State = value; - - int hue = 0; - bool lockDoors = m_State == GauntletSpawnerState.InProgress; - - hue = m_State switch - { - GauntletSpawnerState.InSequence => InSequenceItemHue, - GauntletSpawnerState.InProgress => InProgressItemHue, - GauntletSpawnerState.Completed => CompletedItemHue, - _ => hue - }; - - if (Door != null) - { - Door.Hue = hue; - Door.Locked = lockDoors; - - if (lockDoors) - { - Door.KeyValue = Key.RandomValue(); - Door.Open = false; - } - - if (Door.Link != null) - { - Door.Link.Hue = hue; - Door.Link.Locked = lockDoors; - - if (lockDoors) - { - Door.Link.KeyValue = Key.RandomValue(); - Door.Open = false; - } - } - } - - if (Addon != null) - Addon.Hue = hue; - - if (m_State == GauntletSpawnerState.InProgress) - { - CreateRegion(); - FullSpawn(); - - m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0), Slice); - } - else - { - ClearCreatures(); - ClearTraps(); - DestroyRegion(); - - m_Timer?.Stop(); - - m_Timer = null; - } - } - } - - public List Creatures { get; set; } - - public List Traps { get; set; } - - public Region Region { get; set; } - - public override string DefaultName => "doom spawner"; - - public virtual void CreateRegion() - { - if (Region != null) - return; - - Map map = Map; - - if (map == null || map == Map.Internal) - return; - - Region = new GauntletRegion(this, map); - } - - public virtual void DestroyRegion() - { - Region?.Unregister(); - - Region = null; - } - - public virtual int ComputeTrapCount() - { - int area = RegionBounds.Width * RegionBounds.Height; - - return area / 100; - } - - public virtual void ClearTraps() - { - for (int i = 0; i < Traps.Count; ++i) - Traps[i].Delete(); - - Traps.Clear(); - } - - public virtual void SpawnTrap() - { - Map map = Map; - - if (map == null) - return; - - BaseTrap trap; - - int random = Utility.Random(100); - - if (random < 22) - trap = new SawTrap(Utility.RandomBool() ? SawTrapType.WestFloor : SawTrapType.NorthFloor); - else if (random < 44) - trap = new SpikeTrap(Utility.RandomBool() ? SpikeTrapType.WestFloor : SpikeTrapType.NorthFloor); - else if (random < 66) - trap = new GasTrap(Utility.RandomBool() ? GasTrapType.NorthWall : GasTrapType.WestWall); - else if (random < 88) - trap = new FireColumnTrap(); - else - trap = new MushroomTrap(); - - if (trap is FireColumnTrap || trap is MushroomTrap) - trap.Hue = 0x451; - - // try 10 times to find a valid location - for (int i = 0; i < 10; ++i) - { - int x = Utility.Random(RegionBounds.X, RegionBounds.Width); - int y = Utility.Random(RegionBounds.Y, RegionBounds.Height); - int z = Z; - - if (!map.CanFit(x, y, z, 16, false, false)) - z = map.GetAverageZ(x, y); - - if (!map.CanFit(x, y, z, 16, false, false)) - continue; - - trap.MoveToWorld(new Point3D(x, y, z), map); - Traps.Add(trap); - - return; - } - - trap.Delete(); - } - - public virtual int ComputeSpawnCount() - { - int playerCount = 0; - - Map map = Map; - - if (map != null) - { - Point3D loc = GetWorldLocation(); - - Region reg = Region.Find(loc, map).GetRegion("Doom Gauntlet"); - - if (reg != null) - playerCount = reg.GetPlayerCount(); - } - - if (playerCount == 0 && Region != null) - playerCount = Region.GetPlayerCount(); - - return Math.Max((playerCount + PlayersPerSpawn - 1) / PlayersPerSpawn, 1); - } - - public virtual void ClearCreatures() - { - for (int i = 0; i < Creatures.Count; ++i) - Creatures[i].Delete(); - - Creatures.Clear(); - } - - public virtual void FullSpawn() - { - ClearCreatures(); - - int count = ComputeSpawnCount(); - - for (int i = 0; i < count; ++i) - Spawn(); - - ClearTraps(); - - count = ComputeTrapCount(); - - for (int i = 0; i < count; ++i) - SpawnTrap(); - } - - public virtual void Spawn() - { - try - { - if (TypeName == null) - return; - - Type type = AssemblyHandler.FindFirstTypeForName(TypeName, true); - - if (type == null) - return; - - object obj = ActivatorUtil.CreateInstance(type); - - if (obj is Item item) - { - item.Delete(); - } - else if (obj is Mobile mob) - { - mob.MoveToWorld(GetWorldLocation(), Map); - - Creatures.Add(mob); - } - } - catch - { - // ignored - } - } - - public virtual void RecurseReset() - { - if (m_State != GauntletSpawnerState.InSequence) - { - State = GauntletSpawnerState.InSequence; - - if (Sequence?.Deleted == false) - Sequence.RecurseReset(); - } - } - - public virtual void Slice() - { - if (m_State != GauntletSpawnerState.InProgress) - return; - - int count = ComputeSpawnCount(); - - for (int i = Creatures.Count; i < count; ++i) - Spawn(); - - if (HasCompleted) - { - State = GauntletSpawnerState.Completed; - - if (Sequence?.Deleted == false) - { - if (Sequence.State == GauntletSpawnerState.Completed) - RecurseReset(); - - Sequence.State = GauntletSpawnerState.InProgress; - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(RegionBounds); - - writer.WriteItemList(Traps, false); - - writer.Write(Creatures, false); - - writer.Write(TypeName); - writer.WriteItem(Door); - writer.WriteItem(Addon); - writer.WriteItem(Sequence); - - writer.Write((int)m_State); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - RegionBounds = reader.ReadRect2D(); - Traps = reader.ReadStrongItemList(); - - goto case 0; - } - case 0: - { - if (version < 1) - { - Traps = new List(); - RegionBounds = new Rectangle2D(X - 40, Y - 40, 80, 80); - } - - Creatures = reader.ReadStrongMobileList(); - - TypeName = reader.ReadString(); - Door = reader.ReadItem(); - Addon = reader.ReadItem(); - Sequence = reader.ReadItem(); - - State = (GauntletSpawnerState)reader.ReadInt(); - - break; - } - } - } - - public static void Initialize() - { - CommandSystem.Register("GenGauntlet", AccessLevel.Administrator, GenGauntlet_OnCommand); - } - - public static void CreateTeleporter(int xFrom, int yFrom, int xTo, int yTo) - { - Static telePad = new Static(0x1822); - Teleporter teleItem = new Teleporter(new Point3D(xTo, yTo, -1), Map.Malas); - - telePad.Hue = 0x482; - telePad.MoveToWorld(new Point3D(xFrom, yFrom, -1), Map.Malas); - - teleItem.MoveToWorld(new Point3D(xFrom, yFrom, -1), Map.Malas); - - teleItem.SourceEffect = true; - teleItem.DestEffect = true; - teleItem.SoundID = 0x1FE; - } - - public static BaseDoor CreateDoorSet(int xDoor, int yDoor, bool doorEastToWest, int hue) - { - BaseDoor hiDoor = new MetalDoor(doorEastToWest ? DoorFacing.NorthCCW : DoorFacing.WestCW); - BaseDoor loDoor = new MetalDoor(doorEastToWest ? DoorFacing.SouthCW : DoorFacing.EastCCW); - - hiDoor.MoveToWorld(new Point3D(xDoor, yDoor, -1), Map.Malas); - loDoor.MoveToWorld(new Point3D(xDoor + (doorEastToWest ? 0 : 1), yDoor + (doorEastToWest ? 1 : 0), -1), - Map.Malas); - - hiDoor.Link = loDoor; - loDoor.Link = hiDoor; - - hiDoor.Hue = hue; - loDoor.Hue = hue; - - return hiDoor; - } - - public static GauntletSpawner CreateSpawner(string typeName, int xSpawner, int ySpawner, int xDoor, int yDoor, - int xPentagram, int yPentagram, bool doorEastToWest, int xStart, int yStart, int xWidth, int yHeight) - { - GauntletSpawner spawner = new GauntletSpawner(typeName); - - spawner.MoveToWorld(new Point3D(xSpawner, ySpawner, -1), Map.Malas); - - if (xDoor > 0 && yDoor > 0) - spawner.Door = CreateDoorSet(xDoor, yDoor, doorEastToWest, 0); - - spawner.RegionBounds = new Rectangle2D(xStart, yStart, xWidth, yHeight); - - if (xPentagram > 0 && yPentagram > 0) - { - PentagramAddon pentagram = new PentagramAddon(); - - pentagram.MoveToWorld(new Point3D(xPentagram, yPentagram, -1), Map.Malas); - - spawner.Addon = pentagram; - } - - return spawner; - } - - public static void CreatePricedHealer(int price, int x, int y) - { - PricedHealer healer = new PricedHealer(price); - - healer.MoveToWorld(new Point3D(x, y, -1), Map.Malas); - - healer.Home = healer.Location; - healer.RangeHome = 5; - } - - public static void CreateMorphItem(int x, int y, int inactiveItemID, int activeItemID, int range, int hue) - { - MorphItem item = new MorphItem(inactiveItemID, activeItemID, range); - - item.Hue = hue; - item.MoveToWorld(new Point3D(x, y, -1), Map.Malas); - } - - public static void CreateVarietyDealer(int x, int y) - { - VarietyDealer dealer = new VarietyDealer(); - - /* Begin outfit */ - dealer.Name = "Nix"; - dealer.Title = "the Variety Dealer"; - - dealer.Body = 400; - dealer.Female = false; - dealer.Hue = 0x8835; - - List items = new List(dealer.Items); - - for (int i = 0; i < items.Count; ++i) - { - Item item = items[i]; - - if (item.Layer != Layer.ShopBuy && item.Layer != Layer.ShopResale && item.Layer != Layer.ShopSell) - item.Delete(); - } - - dealer.HairItemID = 0x2049; // Pig Tails - dealer.HairHue = 0x482; - - dealer.FacialHairItemID = 0x203E; - dealer.FacialHairHue = 0x482; - - dealer.AddItem(new FloppyHat(1)); - dealer.AddItem(new Robe(1)); - - dealer.AddItem(new LanternOfSouls()); - - dealer.AddItem(new Sandals(0x482)); - /* End outfit */ - - dealer.MoveToWorld(new Point3D(x, y, -1), Map.Malas); - - dealer.Home = dealer.Location; - dealer.RangeHome = 2; - } - - public static void GenGauntlet_OnCommand(CommandEventArgs e) - { - /* Begin healer room */ - CreatePricedHealer(5000, 387, 400); - CreateTeleporter(390, 407, 394, 405); - - BaseDoor healerDoor = CreateDoorSet(393, 404, true, 0x44E); - - healerDoor.Locked = true; - healerDoor.KeyValue = Key.RandomValue(); - - if (healerDoor.Link != null) - { - healerDoor.Link.Locked = true; - healerDoor.Link.KeyValue = Key.RandomValue(); - } - /* End healer room */ - - /* Begin supply room */ - CreateMorphItem(433, 371, 0x29F, 0x116, 3, 0x44E); - CreateMorphItem(433, 372, 0x29F, 0x115, 3, 0x44E); - - CreateVarietyDealer(492, 369); - - for (int x = 434; x <= 478; ++x) - for (int y = 371; y <= 372; ++y) - { - Static item = new Static(0x524); - - item.Hue = 1; - item.MoveToWorld(new Point3D(x, y, -1), Map.Malas); - } - /* End supply room */ - - /* Begin gauntlet cycle */ - CreateTeleporter(471, 428, 474, 428); - CreateTeleporter(462, 494, 462, 498); - CreateTeleporter(403, 502, 399, 506); - CreateTeleporter(357, 476, 356, 480); - CreateTeleporter(361, 433, 357, 434); - - GauntletSpawner sp1 = CreateSpawner("DarknightCreeper", 491, 456, 473, 432, 417, 426, true, 473, 412, 39, 60); - GauntletSpawner sp2 = CreateSpawner("FleshRenderer", 482, 520, 468, 496, 426, 422, false, 448, 496, 56, 48); - GauntletSpawner sp3 = CreateSpawner("Impaler", 406, 538, 408, 504, 432, 430, false, 376, 504, 64, 48); - GauntletSpawner sp4 = CreateSpawner("ShadowKnight", 335, 512, 360, 478, 424, 439, false, 300, 478, 72, 64); - GauntletSpawner sp5 = CreateSpawner("AbysmalHorror", 326, 433, 360, 429, 416, 435, true, 300, 408, 60, 56); - GauntletSpawner sp6 = CreateSpawner("DemonKnight", 423, 430, 0, 0, 423, 430, true, 392, 392, 72, 96); - - sp1.Sequence = sp2; - sp2.Sequence = sp3; - sp3.Sequence = sp4; - sp4.Sequence = sp5; - sp5.Sequence = sp6; - sp6.Sequence = sp1; - - sp1.State = GauntletSpawnerState.InProgress; - /* End gauntlet cycle */ - - /* Begin exit gate */ - ConfirmationMoongate gate = new ConfirmationMoongate(); - - gate.Dispellable = false; - - gate.Target = new Point3D(2350, 1270, -85); - gate.TargetMap = Map.Malas; - - gate.GumpWidth = 420; - gate.GumpHeight = 280; - - gate.MessageColor = 0x7F00; - gate.MessageNumber = 1062109; // You are about to exit Dungeon Doom. Do you wish to continue? - - gate.TitleColor = 0x7800; - gate.TitleNumber = 1062108; // Please verify... - - gate.Hue = 0x44E; - - gate.MoveToWorld(new Point3D(433, 326, 4), Map.Malas); - /* End exit gate */ - } - } - - public class GauntletRegion : BaseRegion - { - private GauntletSpawner m_Spawner; - - public GauntletRegion(GauntletSpawner spawner, Map map) - : base(null, map, Find(spawner.Location, spawner.Map), spawner.RegionBounds) - { - m_Spawner = spawner; - - GoLocation = spawner.Location; - - Register(); - } - - public override void AlterLightLevel(Mobile m, ref int global, ref int personal) - { - global = 12; - } - - public override void OnEnter(Mobile m) - { - } - - public override void OnExit(Mobile m) - { - } - } -} +using System; +using System.Collections.Generic; +using Server.Items; +using Server.Mobiles; +using Server.Regions; +using Server.Utilities; + +namespace Server.Engines.Doom +{ + public enum GauntletSpawnerState + { + InSequence, + InProgress, + Completed + } + + public class GauntletSpawner : Item + { + public const int PlayersPerSpawn = 5; + + public const int InSequenceItemHue = 0x000; + public const int InProgressItemHue = 0x676; + public const int CompletedItemHue = 0x455; + + private GauntletSpawnerState m_State; + + private Timer m_Timer; + + [Constructible] + public GauntletSpawner(string typeName = null) : base(0x36FE) + { + Visible = false; + Movable = false; + + TypeName = typeName; + Creatures = new List(); + Traps = new List(); + } + + public GauntletSpawner(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public string TypeName { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public BaseDoor Door { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public BaseAddon Addon { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public GauntletSpawner Sequence { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool HasCompleted + { + get + { + if (Creatures.Count == 0) + return false; + + for (var i = 0; i < Creatures.Count; ++i) + { + var mob = Creatures[i]; + + if (!mob.Deleted) + return false; + } + + return true; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Rectangle2D RegionBounds { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public GauntletSpawnerState State + { + get => m_State; + set + { + if (m_State == value) + return; + + m_State = value; + + var hue = 0; + var lockDoors = m_State == GauntletSpawnerState.InProgress; + + hue = m_State switch + { + GauntletSpawnerState.InSequence => InSequenceItemHue, + GauntletSpawnerState.InProgress => InProgressItemHue, + GauntletSpawnerState.Completed => CompletedItemHue, + _ => hue + }; + + if (Door != null) + { + Door.Hue = hue; + Door.Locked = lockDoors; + + if (lockDoors) + { + Door.KeyValue = Key.RandomValue(); + Door.Open = false; + } + + if (Door.Link != null) + { + Door.Link.Hue = hue; + Door.Link.Locked = lockDoors; + + if (lockDoors) + { + Door.Link.KeyValue = Key.RandomValue(); + Door.Open = false; + } + } + } + + if (Addon != null) + Addon.Hue = hue; + + if (m_State == GauntletSpawnerState.InProgress) + { + CreateRegion(); + FullSpawn(); + + m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0), Slice); + } + else + { + ClearCreatures(); + ClearTraps(); + DestroyRegion(); + + m_Timer?.Stop(); + + m_Timer = null; + } + } + } + + public List Creatures { get; set; } + + public List Traps { get; set; } + + public Region Region { get; set; } + + public override string DefaultName => "doom spawner"; + + public virtual void CreateRegion() + { + if (Region != null) + return; + + var map = Map; + + if (map == null || map == Map.Internal) + return; + + Region = new GauntletRegion(this, map); + } + + public virtual void DestroyRegion() + { + Region?.Unregister(); + + Region = null; + } + + public virtual int ComputeTrapCount() + { + var area = RegionBounds.Width * RegionBounds.Height; + + return area / 100; + } + + public virtual void ClearTraps() + { + for (var i = 0; i < Traps.Count; ++i) + Traps[i].Delete(); + + Traps.Clear(); + } + + public virtual void SpawnTrap() + { + var map = Map; + + if (map == null) + return; + + BaseTrap trap; + + var random = Utility.Random(100); + + if (random < 22) + trap = new SawTrap(Utility.RandomBool() ? SawTrapType.WestFloor : SawTrapType.NorthFloor); + else if (random < 44) + trap = new SpikeTrap(Utility.RandomBool() ? SpikeTrapType.WestFloor : SpikeTrapType.NorthFloor); + else if (random < 66) + trap = new GasTrap(Utility.RandomBool() ? GasTrapType.NorthWall : GasTrapType.WestWall); + else if (random < 88) + trap = new FireColumnTrap(); + else + trap = new MushroomTrap(); + + if (trap is FireColumnTrap || trap is MushroomTrap) + trap.Hue = 0x451; + + // try 10 times to find a valid location + for (var i = 0; i < 10; ++i) + { + var x = Utility.Random(RegionBounds.X, RegionBounds.Width); + var y = Utility.Random(RegionBounds.Y, RegionBounds.Height); + var z = Z; + + if (!map.CanFit(x, y, z, 16, false, false)) + z = map.GetAverageZ(x, y); + + if (!map.CanFit(x, y, z, 16, false, false)) + continue; + + trap.MoveToWorld(new Point3D(x, y, z), map); + Traps.Add(trap); + + return; + } + + trap.Delete(); + } + + public virtual int ComputeSpawnCount() + { + var playerCount = 0; + + var map = Map; + + if (map != null) + { + var loc = GetWorldLocation(); + + var reg = Region.Find(loc, map).GetRegion("Doom Gauntlet"); + + if (reg != null) + playerCount = reg.GetPlayerCount(); + } + + if (playerCount == 0 && Region != null) + playerCount = Region.GetPlayerCount(); + + return Math.Max((playerCount + PlayersPerSpawn - 1) / PlayersPerSpawn, 1); + } + + public virtual void ClearCreatures() + { + for (var i = 0; i < Creatures.Count; ++i) + Creatures[i].Delete(); + + Creatures.Clear(); + } + + public virtual void FullSpawn() + { + ClearCreatures(); + + var count = ComputeSpawnCount(); + + for (var i = 0; i < count; ++i) + Spawn(); + + ClearTraps(); + + count = ComputeTrapCount(); + + for (var i = 0; i < count; ++i) + SpawnTrap(); + } + + public virtual void Spawn() + { + try + { + if (TypeName == null) + return; + + var type = AssemblyHandler.FindFirstTypeForName(TypeName, true); + + if (type == null) + return; + + var obj = ActivatorUtil.CreateInstance(type); + + if (obj is Item item) + { + item.Delete(); + } + else if (obj is Mobile mob) + { + mob.MoveToWorld(GetWorldLocation(), Map); + + Creatures.Add(mob); + } + } + catch + { + // ignored + } + } + + public virtual void RecurseReset() + { + if (m_State != GauntletSpawnerState.InSequence) + { + State = GauntletSpawnerState.InSequence; + + if (Sequence?.Deleted == false) + Sequence.RecurseReset(); + } + } + + public virtual void Slice() + { + if (m_State != GauntletSpawnerState.InProgress) + return; + + var count = ComputeSpawnCount(); + + for (var i = Creatures.Count; i < count; ++i) + Spawn(); + + if (HasCompleted) + { + State = GauntletSpawnerState.Completed; + + if (Sequence?.Deleted == false) + { + if (Sequence.State == GauntletSpawnerState.Completed) + RecurseReset(); + + Sequence.State = GauntletSpawnerState.InProgress; + } + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(RegionBounds); + + writer.WriteItemList(Traps, false); + + writer.Write(Creatures, false); + + writer.Write(TypeName); + writer.WriteItem(Door); + writer.WriteItem(Addon); + writer.WriteItem(Sequence); + + writer.Write((int)m_State); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + RegionBounds = reader.ReadRect2D(); + Traps = reader.ReadStrongItemList(); + + goto case 0; + } + case 0: + { + if (version < 1) + { + Traps = new List(); + RegionBounds = new Rectangle2D(X - 40, Y - 40, 80, 80); + } + + Creatures = reader.ReadStrongMobileList(); + + TypeName = reader.ReadString(); + Door = reader.ReadItem(); + Addon = reader.ReadItem(); + Sequence = reader.ReadItem(); + + State = (GauntletSpawnerState)reader.ReadInt(); + + break; + } + } + } + + public static void Initialize() + { + CommandSystem.Register("GenGauntlet", AccessLevel.Administrator, GenGauntlet_OnCommand); + } + + public static void CreateTeleporter(int xFrom, int yFrom, int xTo, int yTo) + { + var telePad = new Static(0x1822); + var teleItem = new Teleporter(new Point3D(xTo, yTo, -1), Map.Malas); + + telePad.Hue = 0x482; + telePad.MoveToWorld(new Point3D(xFrom, yFrom, -1), Map.Malas); + + teleItem.MoveToWorld(new Point3D(xFrom, yFrom, -1), Map.Malas); + + teleItem.SourceEffect = true; + teleItem.DestEffect = true; + teleItem.SoundID = 0x1FE; + } + + public static BaseDoor CreateDoorSet(int xDoor, int yDoor, bool doorEastToWest, int hue) + { + BaseDoor hiDoor = new MetalDoor(doorEastToWest ? DoorFacing.NorthCCW : DoorFacing.WestCW); + BaseDoor loDoor = new MetalDoor(doorEastToWest ? DoorFacing.SouthCW : DoorFacing.EastCCW); + + hiDoor.MoveToWorld(new Point3D(xDoor, yDoor, -1), Map.Malas); + loDoor.MoveToWorld( + new Point3D(xDoor + (doorEastToWest ? 0 : 1), yDoor + (doorEastToWest ? 1 : 0), -1), + Map.Malas + ); + + hiDoor.Link = loDoor; + loDoor.Link = hiDoor; + + hiDoor.Hue = hue; + loDoor.Hue = hue; + + return hiDoor; + } + + public static GauntletSpawner CreateSpawner( + string typeName, int xSpawner, int ySpawner, int xDoor, int yDoor, + int xPentagram, int yPentagram, bool doorEastToWest, int xStart, int yStart, int xWidth, int yHeight + ) + { + var spawner = new GauntletSpawner(typeName); + + spawner.MoveToWorld(new Point3D(xSpawner, ySpawner, -1), Map.Malas); + + if (xDoor > 0 && yDoor > 0) + spawner.Door = CreateDoorSet(xDoor, yDoor, doorEastToWest, 0); + + spawner.RegionBounds = new Rectangle2D(xStart, yStart, xWidth, yHeight); + + if (xPentagram > 0 && yPentagram > 0) + { + var pentagram = new PentagramAddon(); + + pentagram.MoveToWorld(new Point3D(xPentagram, yPentagram, -1), Map.Malas); + + spawner.Addon = pentagram; + } + + return spawner; + } + + public static void CreatePricedHealer(int price, int x, int y) + { + var healer = new PricedHealer(price); + + healer.MoveToWorld(new Point3D(x, y, -1), Map.Malas); + + healer.Home = healer.Location; + healer.RangeHome = 5; + } + + public static void CreateMorphItem(int x, int y, int inactiveItemID, int activeItemID, int range, int hue) + { + var item = new MorphItem(inactiveItemID, activeItemID, range); + + item.Hue = hue; + item.MoveToWorld(new Point3D(x, y, -1), Map.Malas); + } + + public static void CreateVarietyDealer(int x, int y) + { + var dealer = new VarietyDealer(); + + /* Begin outfit */ + dealer.Name = "Nix"; + dealer.Title = "the Variety Dealer"; + + dealer.Body = 400; + dealer.Female = false; + dealer.Hue = 0x8835; + + var items = new List(dealer.Items); + + for (var i = 0; i < items.Count; ++i) + { + var item = items[i]; + + if (item.Layer != Layer.ShopBuy && item.Layer != Layer.ShopResale && item.Layer != Layer.ShopSell) + item.Delete(); + } + + dealer.HairItemID = 0x2049; // Pig Tails + dealer.HairHue = 0x482; + + dealer.FacialHairItemID = 0x203E; + dealer.FacialHairHue = 0x482; + + dealer.AddItem(new FloppyHat(1)); + dealer.AddItem(new Robe(1)); + + dealer.AddItem(new LanternOfSouls()); + + dealer.AddItem(new Sandals(0x482)); + /* End outfit */ + + dealer.MoveToWorld(new Point3D(x, y, -1), Map.Malas); + + dealer.Home = dealer.Location; + dealer.RangeHome = 2; + } + + public static void GenGauntlet_OnCommand(CommandEventArgs e) + { + /* Begin healer room */ + CreatePricedHealer(5000, 387, 400); + CreateTeleporter(390, 407, 394, 405); + + var healerDoor = CreateDoorSet(393, 404, true, 0x44E); + + healerDoor.Locked = true; + healerDoor.KeyValue = Key.RandomValue(); + + if (healerDoor.Link != null) + { + healerDoor.Link.Locked = true; + healerDoor.Link.KeyValue = Key.RandomValue(); + } + /* End healer room */ + + /* Begin supply room */ + CreateMorphItem(433, 371, 0x29F, 0x116, 3, 0x44E); + CreateMorphItem(433, 372, 0x29F, 0x115, 3, 0x44E); + + CreateVarietyDealer(492, 369); + + for (var x = 434; x <= 478; ++x) + for (var y = 371; y <= 372; ++y) + { + var item = new Static(0x524); + + item.Hue = 1; + item.MoveToWorld(new Point3D(x, y, -1), Map.Malas); + } + /* End supply room */ + + /* Begin gauntlet cycle */ + CreateTeleporter(471, 428, 474, 428); + CreateTeleporter(462, 494, 462, 498); + CreateTeleporter(403, 502, 399, 506); + CreateTeleporter(357, 476, 356, 480); + CreateTeleporter(361, 433, 357, 434); + + var sp1 = CreateSpawner("DarknightCreeper", 491, 456, 473, 432, 417, 426, true, 473, 412, 39, 60); + var sp2 = CreateSpawner("FleshRenderer", 482, 520, 468, 496, 426, 422, false, 448, 496, 56, 48); + var sp3 = CreateSpawner("Impaler", 406, 538, 408, 504, 432, 430, false, 376, 504, 64, 48); + var sp4 = CreateSpawner("ShadowKnight", 335, 512, 360, 478, 424, 439, false, 300, 478, 72, 64); + var sp5 = CreateSpawner("AbysmalHorror", 326, 433, 360, 429, 416, 435, true, 300, 408, 60, 56); + var sp6 = CreateSpawner("DemonKnight", 423, 430, 0, 0, 423, 430, true, 392, 392, 72, 96); + + sp1.Sequence = sp2; + sp2.Sequence = sp3; + sp3.Sequence = sp4; + sp4.Sequence = sp5; + sp5.Sequence = sp6; + sp6.Sequence = sp1; + + sp1.State = GauntletSpawnerState.InProgress; + /* End gauntlet cycle */ + + /* Begin exit gate */ + var gate = new ConfirmationMoongate(); + + gate.Dispellable = false; + + gate.Target = new Point3D(2350, 1270, -85); + gate.TargetMap = Map.Malas; + + gate.GumpWidth = 420; + gate.GumpHeight = 280; + + gate.MessageColor = 0x7F00; + gate.MessageNumber = 1062109; // You are about to exit Dungeon Doom. Do you wish to continue? + + gate.TitleColor = 0x7800; + gate.TitleNumber = 1062108; // Please verify... + + gate.Hue = 0x44E; + + gate.MoveToWorld(new Point3D(433, 326, 4), Map.Malas); + /* End exit gate */ + } + } + + public class GauntletRegion : BaseRegion + { + private GauntletSpawner m_Spawner; + + public GauntletRegion(GauntletSpawner spawner, Map map) + : base(null, map, Find(spawner.Location, spawner.Map), spawner.RegionBounds) + { + m_Spawner = spawner; + + GoLocation = spawner.Location; + + Register(); + } + + public override void AlterLightLevel(Mobile m, ref int global, ref int personal) + { + global = 12; + } + + public override void OnEnter(Mobile m) + { + } + + public override void OnExit(Mobile m) + { + } + } +} diff --git a/Projects/UOContent/Engines/Doom/LeverPuzzle/LeverPuzzleController.cs b/Projects/UOContent/Engines/Doom/LeverPuzzle/LeverPuzzleController.cs index cf3a5ea0b..c90d79d79 100644 --- a/Projects/UOContent/Engines/Doom/LeverPuzzle/LeverPuzzleController.cs +++ b/Projects/UOContent/Engines/Doom/LeverPuzzle/LeverPuzzleController.cs @@ -1,605 +1,634 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Server.Mobiles; -using Server.Network; -using Server.Spells; - -namespace Server.Engines.Doom -{ - public class LeverPuzzleController : Item - { - private static bool installed; - - public static string[] Msgs = - { - "You are pinned down by the weight of the boulder!!!", // 0 - "A speeding rock hits you in the head!", // 1 - "OUCH!" // 2 - }; - /* font&hue for above msgs. index matches */ - - public static int[][] MsgParams = - { - new[] { 0x66d, 3 }, - new[] { 0x66d, 3 }, - new[] { 0x34, 3 } - }; - /* World data for items */ - - public static int[][] TA = - { - new[] { 316, 64, 5 }, /* 3D Coords for levers */ - new[] { 323, 58, 5 }, - new[] { 332, 63, 5 }, - new[] { 323, 71, 5 }, - - new[] { 324, 64 }, /* 2D Coords for standing regions */ - new[] { 316, 65 }, - new[] { 324, 58 }, - new[] { 332, 64 }, - new[] { 323, 72 }, - - new[] { 468, 92, -1 }, new[] { 0x181D, 0x482 }, /* 3D coord, itemid+hue for L.R. teles */ - new[] { 469, 92, -1 }, new[] { 0x1821, 0x3fd }, - new[] { 470, 92, -1 }, new[] { 0x1825, 0x66d }, - - new[] { 319, 70, 18 }, new[] { 0x12d8 }, /* 3D coord, itemid for statues */ - new[] { 329, 60, 18 }, new[] { 0x12d9 }, - - new[] { 469, 96, 6 } /* 3D Coords for Fake Box */ - }; - - /* CLILOC data for statue "correct souls" messages */ - - public static int[] Statue_Msg = { 1050009, 1050007, 1050008, 1050008 }; - - /* Exit & Enter locations for the lamp room */ - - public static Point3D lr_Exit = new Point3D(353, 172, -1); - public static Point3D lr_Enter = new Point3D(467, 96, -1); - - /* "Center" location in puzzle */ - - public static Point3D lp_Center = new Point3D(324, 64, -1); - - /* Lamp Room Area */ - - public static Rectangle2D lr_Rect = new Rectangle2D(465, 92, 10, 10); - - /* Lamp Room area Poison message data */ - - public static int[][] PA = - { - new[] { 0, 0, 0xA6 }, - new[] { 1050001, 0x485, 0xAA }, - new[] { 1050003, 0x485, 0xAC }, - new[] { 1050056, 0x485, 0xA8 }, - new[] { 1050057, 0x485, 0xA4 }, - new[] { 1062091, 0x23F3, 0xAC } - }; - - public static Poison[] PA2 = - { - Poison.Lesser, - Poison.Regular, - Poison.Greater, - Poison.Deadly, - Poison.Lethal, - Poison.Lethal - }; - - /* SOUNDS */ - - private static readonly int[] fs = { 0x144, 0x154 }; - private static readonly int[] ms = { 0x144, 0x14B }; - private static readonly int[] fs2 = { 0x13F, 0x154 }; - private static readonly int[] ms2 = { 0x13F, 0x14B }; - private static readonly int[] cs1 = { 0x244 }; - private static readonly int[] exp = { 0x307 }; - private Timer l_Timer; - private LampRoomBox m_Box; - private Region m_LampRoom; - - private List m_Levers; - private List m_Statues; - private List m_Teles; - private List m_Tiles; - - private Timer m_Timer; - - public LeverPuzzleController() : base(0x1822) - { - Movable = false; - Hue = 0x4c; - installed = true; - int i = 0; - - m_Levers = new List(); /* codes are 0x1 shifted left x # of bits, easily handled here */ - for (; i < 4; i++) - m_Levers.Add(AddLeverPuzzlePart(TA[i], new LeverPuzzleLever((ushort)(1 << i), this))); - - m_Tiles = new List(); - for (; i < 9; i++) - m_Tiles.Add(new LeverPuzzleRegion(this, TA[i])); - - m_Teles = new List(); - for (; i < 15; i++) - m_Teles.Add(AddLeverPuzzlePart(TA[i], new LampRoomTeleporter(TA[++i]))); - - m_Statues = new List(); - for (; i < 19; i++) - m_Statues.Add(AddLeverPuzzlePart(TA[i], new LeverPuzzleStatue(TA[++i], this))); - - if (!installed) - Delete(); - else - Enabled = true; - - m_Box = (LampRoomBox)AddLeverPuzzlePart(TA[i], new LampRoomBox(this)); - m_LampRoom = new LampRoomRegion(this); - GenKey(); - } - - public LeverPuzzleController(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public ushort MyKey { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public ushort TheirKey { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Enabled { get; set; } - - public Mobile Successful { get; private set; } - - public bool CircleComplete - { - get /* OSI: all 5 must be occupied */ - { - for (int i = 0; i < 5; i++) - if (GetOccupant(i) == null) - return false; - return true; - } - } - - public static void Initialize() - { - CommandSystem.Register("GenLeverPuzzle", AccessLevel.Administrator, GenLampPuzzle_OnCommand); - } - - [Usage("GenLeverPuzzle")] - [Description("Generates lamp room and lever puzzle in doom.")] - public static void GenLampPuzzle_OnCommand(CommandEventArgs e) - { - if (Map.Malas.GetItemsInRange(lp_Center, 0).OfType().Any()) - { - e.Mobile.SendMessage("Lamp room puzzle already exists: please delete the existing controller first ..."); - return; - } - - e.Mobile.SendMessage("Generating Lamp Room puzzle..."); - new LeverPuzzleController().MoveToWorld(lp_Center, Map.Malas); - - if (!installed) - e.Mobile.SendMessage("There was a problem generating the puzzle."); - else - e.Mobile.SendMessage("Lamp room puzzle successfully generated."); - } - - public static Item AddLeverPuzzlePart(int[] loc, Item newitem) - { - if (newitem?.Deleted != false) - installed = false; - else - newitem.MoveToWorld(new Point3D(loc[0], loc[1], loc[2]), Map.Malas); - - return newitem; - } - - public override void OnDelete() - { - KillTimers(); - base.OnDelete(); - } - - public override void OnAfterDelete() - { - NukeItemList(m_Teles); - NukeItemList(m_Statues); - NukeItemList(m_Levers); - - m_LampRoom?.Unregister(); - if (m_Tiles != null) - foreach (LeverPuzzleRegion region in m_Tiles) - region.Unregister(); - if (m_Box?.Deleted == false) - m_Box.Delete(); - } - - public static void NukeItemList(List list) - { - if (list?.Count > 0) - foreach (Item item in list) - if (item?.Deleted == false) - item.Delete(); - } - - public virtual PlayerMobile GetOccupant(int index) - { - LeverPuzzleRegion region = m_Tiles[index]; - - if (region?.Occupant?.Alive == true) return (PlayerMobile)region.Occupant; - return null; - } - - public virtual LeverPuzzleStatue GetStatue(int index) - { - LeverPuzzleStatue statue = (LeverPuzzleStatue)m_Statues[index]; - return statue?.Deleted == false ? statue : null; - } - - public virtual LeverPuzzleLever GetLever(int index) - { - LeverPuzzleLever lever = (LeverPuzzleLever)m_Levers[index]; - - return lever?.Deleted == false ? lever : null; - } - - public virtual void PuzzleStatus(int message, string fstring = null) - { - for (int i = 0; i < 2; i++) - { - Item s; - if ((s = GetStatue(i)) != null) - s.PublicOverheadMessage(MessageType.Regular, 0x3B2, message, fstring); - } - } - - public virtual void ResetPuzzle() - { - PuzzleStatus(1062053); - ResetLevers(); - } - - public virtual void ResetLevers() - { - for (int i = 0; i < 4; i++) - { - Item l; - if ((l = GetLever(i)) != null) - { - l.ItemID = 0x108E; - Effects.PlaySound(l.Location, Map, 0x3E8); - } - } - - TheirKey ^= TheirKey; - } - - public virtual void KillTimers() - { - if (l_Timer?.Running == true) l_Timer.Stop(); - if (m_Timer?.Running == true) m_Timer.Stop(); - } - - public virtual void RemoveSuccessful() - { - Successful = null; - } - - public virtual void LeverPulled(ushort code) - { - int correct = 0; - - KillTimers(); - - /* if one bit in each of the four nibbles is set, this is false */ - - if ((TheirKey = (ushort)(code | (TheirKey <<= 4))) < 0x0FFF) - { - l_Timer = Timer.DelayCall(TimeSpan.FromSeconds(30.0), ResetPuzzle); - return; - } - - if (!CircleComplete) - { - PuzzleStatus(1050004); // The circle is the key... - } - else - { - Mobile player; - if (TheirKey == MyKey) - { - GenKey(); - if ((Successful = player = GetOccupant(0)) != null) - { - SendLocationEffect(lp_Center, 0x1153, 0, 60, 1); - PlaySounds(lp_Center, cs1); - - Effects.SendBoltEffect(player, true); - player.MoveToWorld(lr_Enter, Map.Malas); - - m_Timer = new LampRoomTimer(this); - m_Timer.Start(); - Enabled = false; - } - } - else - { - for (int i = 0; i < 16; i++) /* Count matching SET bits, ie correct codes */ - if ((MyKey >> i & 1) == 1 && (TheirKey >> i & 1) == 1) - correct++; - - PuzzleStatus(Statue_Msg[correct], correct > 0 ? correct.ToString() : null); - - for (int i = 0; i < 5; i++) - if ((player = GetOccupant(i)) != null) - new RockTimer(player, this).Start(); - } - } - - ResetLevers(); - } - - public virtual void GenKey() - { - Span ca = stackalloc ushort[]{ 1, 2, 4, 8 }; - ca.Shuffle(); - - for (int i = 0; i < 4; i++) MyKey = (ushort)(ca[i] | (MyKey <<= 4)); - } - - private static bool IsValidDamagable(Mobile m) => - m?.Deleted == false && - (m.Player && m.Alive || - m is BaseCreature bc && (bc.Controlled || bc.Summoned) && !bc.IsDeadBondedPet); - - public static void MoveMobileOut(Mobile m) - { - if (m != null) - { - if (m is PlayerMobile && !m.Alive && m.Corpse?.Deleted == false) - m.Corpse.MoveToWorld(lr_Exit, Map.Malas); - - BaseCreature.TeleportPets(m, lr_Exit, Map.Malas); - m.Location = lr_Exit; - m.ProcessDelta(); - } - } - - public static bool AniSafe(Mobile m) => m?.BodyMod == 0 && m.Alive && !TransformationSpellHelper.UnderTransformation(m); - - public static IEntity ZAdjustedIEFromMobile(Mobile m, int zDelta) => new Entity(Serial.Zero, new Point3D(m.X, m.Y, m.Z + zDelta), m.Map); - - public static void DoDamage(Mobile m, int min, int max, bool poison) - { - if (m?.Deleted == false && m.Alive) - { - int damage = Utility.Random(min, max); - AOS.Damage(m, damage, poison ? 0 : 100, 0, 0, poison ? 100 : 0, 0); - } - } - - public static Point3D RandomPointIn(Point3D point, int range) => RandomPointIn(point.X - range, point.Y - range, range * 2, range * 2, point.Z); - - public static Point3D RandomPointIn(Rectangle2D rect, int z) => RandomPointIn(rect.X, rect.Y, rect.Height, rect.Width, z); - - public static Point3D RandomPointIn(int x, int y, int x2, int y2, int z) => new Point3D(Utility.Random(x, x2), Utility.Random(y, y2), z); - - public static void PlaySounds(Point3D location, int[] sounds) - { - foreach (int soundid in sounds) - Effects.PlaySound(location, Map.Malas, soundid); - } - - public static void PlayEffect(IEntity from, IEntity to, int itemid, int speed, bool explodes) - { - Effects.SendMovingParticles(from, to, itemid, speed, 0, true, explodes, 2, 0, 0); - } - - public static void SendLocationEffect(IPoint3D p, int itemID, int speed, int duration, int hue) - { - Effects.SendPacket(p, Map.Malas, new LocationEffect(p, itemID, speed, duration, hue, 0)); - } - - public static void PlayerSendASCII(Mobile player, int index) - { - player.Send(new AsciiMessage(Serial.MinusOne, 0xFFFF, MessageType.Label, MsgParams[index][0], - MsgParams[index][1], null, Msgs[index])); - } - - /* I cant find any better way to send "speech" using fonts other than default */ - public static void POHMessage(Mobile from, int index) - { - Packet p = new AsciiMessage(from.Serial, from.Body, MessageType.Regular, MsgParams[index][0], - MsgParams[index][1], from.Name, Msgs[index]); - p.Acquire(); - foreach (NetState state in from.Map.GetClientsInRange(from.Location)) - state.Send(p); - - Packet.Release(p); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - writer.WriteItemList(m_Levers, true); - writer.WriteItemList(m_Statues, true); - writer.WriteItemList(m_Teles, true); - writer.Write(m_Box); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Levers = reader.ReadStrongItemList(); - m_Statues = reader.ReadStrongItemList(); - m_Teles = reader.ReadStrongItemList(); - - m_Box = reader.ReadItem() as LampRoomBox; - - m_Tiles = new List(); - for (int i = 4; i < 9; i++) - m_Tiles.Add(new LeverPuzzleRegion(this, TA[i])); - - m_LampRoom = new LampRoomRegion(this); - Enabled = true; - TheirKey = 0; - MyKey = 0; - GenKey(); - } - - public class RockTimer : Timer - { - private int Count; - private LeverPuzzleController m_Controller; - private readonly Mobile m_Player; - - public RockTimer(Mobile player, LeverPuzzleController controller) - : base(TimeSpan.Zero, TimeSpan.FromSeconds(.25)) - { - Count = 0; - m_Player = player; - m_Controller = controller; - } - - private int Rock() => 0x1363 + Utility.Random(0, 11); - - protected override void OnTick() - { - if (m_Player == null || m_Player.Map != Map.Malas) - { - Stop(); - } - else - { - Count++; - if (Count == 1) /* TODO consolidate */ - { - m_Player.Paralyze(TimeSpan.FromSeconds(2)); - Effects.SendTargetEffect(m_Player, 0x11B7, 20, 10); - PlayerSendASCII(m_Player, 0); // You are pinned down ... - - PlaySounds(m_Player.Location, !m_Player.Female ? fs : ms); - PlayEffect(ZAdjustedIEFromMobile(m_Player, 50), m_Player, 0x11B7, 20, false); - } - else if (Count == 2) - { - DoDamage(m_Player, 80, 90, false); - Effects.SendTargetEffect(m_Player, 0x36BD, 20, 10); - PlaySounds(m_Player.Location, exp); - PlayerSendASCII(m_Player, 1); // A speeding rock ... - - if (AniSafe(m_Player)) m_Player.Animate(21, 10, 1, true, true, 0); - } - else if (Count == 3) - { - Stop(); - - Effects.SendTargetEffect(m_Player, 0x36B0, 20, 10); - PlayerSendASCII(m_Player, 1); // A speeding rock ... - PlaySounds(m_Player.Location, !m_Player.Female ? fs2 : ms2); - - int j = Utility.Random(6, 10); - for (int i = 0; i < j; i++) - { - IEntity m_IEntity = new Entity(Serial.Zero, RandomPointIn(m_Player.Location, 10), m_Player.Map); - - List mobiles = m_IEntity.Map.GetMobilesInRange(m_IEntity.Location, 2).ToList(); - - for (int k = 0; k < mobiles.Count; k++) - if (IsValidDamagable(mobiles[k]) && mobiles[k] != m_Player) - { - PlayEffect(m_Player, mobiles[k], Rock(), 8, true); - DoDamage(mobiles[k], 25, 30, false); - - if (mobiles[k].Player) POHMessage(mobiles[k], 2); // OUCH! - } - - PlayEffect(m_Player, m_IEntity, Rock(), 8, false); - } - } - } - } - } - - public class LampRoomKickTimer : Timer - { - private readonly Mobile m; - - public LampRoomKickTimer(Mobile player) - : base(TimeSpan.FromSeconds(.25)) => - m = player; - - protected override void OnTick() - { - MoveMobileOut(m); - } - } - - public class LampRoomTimer : Timer - { - public int level; - public LeverPuzzleController m_Controller; - public int ticks; - - public LampRoomTimer(LeverPuzzleController controller) - : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0)) - { - level = 0; - ticks = 0; - m_Controller = controller; - } - - protected override void OnTick() - { - ticks++; - List mobiles = m_Controller.m_LampRoom.GetMobiles(); - - if (ticks >= 71 || m_Controller.m_LampRoom.GetPlayerCount() == 0) - { - foreach (Mobile mobile in mobiles) - if (mobile?.Deleted == false && !mobile.IsDeadBondedPet) - mobile.Kill(); - m_Controller.Enabled = true; - Stop(); - } - else - { - if (ticks % 12 == 0) level++; - foreach (Mobile mobile in mobiles) - if (IsValidDamagable(mobile)) - { - if (ticks % 2 == 0 && level == 5) - { - if (mobile.Player) - { - mobile.Say(1062092); - if (AniSafe(mobile)) mobile.Animate(32, 5, 1, true, false, 0); - } - - DoDamage(mobile, 15, 20, true); - } - - if (Utility.Random((int)(level & ~0xfffffffc), 3) == 3) - mobile.ApplyPoison(mobile, PA2[level]); - if (ticks % 12 == 0 && level > 0 && mobile.Player) - mobile.SendLocalizedMessage(PA[level][0], null, PA[level][1]); - } - - for (int i = 0; i <= level; i++) - SendLocationEffect(RandomPointIn(lr_Rect, -1), 0x36B0, Utility.Random(150, 200), 0, PA[level][2]); - } - } - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using Server.Mobiles; +using Server.Network; +using Server.Spells; + +namespace Server.Engines.Doom +{ + public class LeverPuzzleController : Item + { + private static bool installed; + + public static string[] Msgs = + { + "You are pinned down by the weight of the boulder!!!", // 0 + "A speeding rock hits you in the head!", // 1 + "OUCH!" // 2 + }; + /* font&hue for above msgs. index matches */ + + public static int[][] MsgParams = + { + new[] { 0x66d, 3 }, + new[] { 0x66d, 3 }, + new[] { 0x34, 3 } + }; + /* World data for items */ + + public static int[][] TA = + { + new[] { 316, 64, 5 }, /* 3D Coords for levers */ + new[] { 323, 58, 5 }, + new[] { 332, 63, 5 }, + new[] { 323, 71, 5 }, + + new[] { 324, 64 }, /* 2D Coords for standing regions */ + new[] { 316, 65 }, + new[] { 324, 58 }, + new[] { 332, 64 }, + new[] { 323, 72 }, + + new[] { 468, 92, -1 }, new[] { 0x181D, 0x482 }, /* 3D coord, itemid+hue for L.R. teles */ + new[] { 469, 92, -1 }, new[] { 0x1821, 0x3fd }, + new[] { 470, 92, -1 }, new[] { 0x1825, 0x66d }, + + new[] { 319, 70, 18 }, new[] { 0x12d8 }, /* 3D coord, itemid for statues */ + new[] { 329, 60, 18 }, new[] { 0x12d9 }, + + new[] { 469, 96, 6 } /* 3D Coords for Fake Box */ + }; + + /* CLILOC data for statue "correct souls" messages */ + + public static int[] Statue_Msg = { 1050009, 1050007, 1050008, 1050008 }; + + /* Exit & Enter locations for the lamp room */ + + public static Point3D lr_Exit = new Point3D(353, 172, -1); + public static Point3D lr_Enter = new Point3D(467, 96, -1); + + /* "Center" location in puzzle */ + + public static Point3D lp_Center = new Point3D(324, 64, -1); + + /* Lamp Room Area */ + + public static Rectangle2D lr_Rect = new Rectangle2D(465, 92, 10, 10); + + /* Lamp Room area Poison message data */ + + public static int[][] PA = + { + new[] { 0, 0, 0xA6 }, + new[] { 1050001, 0x485, 0xAA }, + new[] { 1050003, 0x485, 0xAC }, + new[] { 1050056, 0x485, 0xA8 }, + new[] { 1050057, 0x485, 0xA4 }, + new[] { 1062091, 0x23F3, 0xAC } + }; + + public static Poison[] PA2 = + { + Poison.Lesser, + Poison.Regular, + Poison.Greater, + Poison.Deadly, + Poison.Lethal, + Poison.Lethal + }; + + /* SOUNDS */ + + private static readonly int[] fs = { 0x144, 0x154 }; + private static readonly int[] ms = { 0x144, 0x14B }; + private static readonly int[] fs2 = { 0x13F, 0x154 }; + private static readonly int[] ms2 = { 0x13F, 0x14B }; + private static readonly int[] cs1 = { 0x244 }; + private static readonly int[] exp = { 0x307 }; + private Timer l_Timer; + private LampRoomBox m_Box; + private Region m_LampRoom; + + private List m_Levers; + private List m_Statues; + private List m_Teles; + private List m_Tiles; + + private Timer m_Timer; + + public LeverPuzzleController() : base(0x1822) + { + Movable = false; + Hue = 0x4c; + installed = true; + var i = 0; + + m_Levers = new List(); /* codes are 0x1 shifted left x # of bits, easily handled here */ + for (; i < 4; i++) + m_Levers.Add(AddLeverPuzzlePart(TA[i], new LeverPuzzleLever((ushort)(1 << i), this))); + + m_Tiles = new List(); + for (; i < 9; i++) + m_Tiles.Add(new LeverPuzzleRegion(this, TA[i])); + + m_Teles = new List(); + for (; i < 15; i++) + m_Teles.Add(AddLeverPuzzlePart(TA[i], new LampRoomTeleporter(TA[++i]))); + + m_Statues = new List(); + for (; i < 19; i++) + m_Statues.Add(AddLeverPuzzlePart(TA[i], new LeverPuzzleStatue(TA[++i], this))); + + if (!installed) + Delete(); + else + Enabled = true; + + m_Box = (LampRoomBox)AddLeverPuzzlePart(TA[i], new LampRoomBox(this)); + m_LampRoom = new LampRoomRegion(this); + GenKey(); + } + + public LeverPuzzleController(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public ushort MyKey { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public ushort TheirKey { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Enabled { get; set; } + + public Mobile Successful { get; private set; } + + public bool CircleComplete + { + get /* OSI: all 5 must be occupied */ + { + for (var i = 0; i < 5; i++) + if (GetOccupant(i) == null) + return false; + return true; + } + } + + public static void Initialize() + { + CommandSystem.Register("GenLeverPuzzle", AccessLevel.Administrator, GenLampPuzzle_OnCommand); + } + + [Usage("GenLeverPuzzle")] + [Description("Generates lamp room and lever puzzle in doom.")] + public static void GenLampPuzzle_OnCommand(CommandEventArgs e) + { + if (Map.Malas.GetItemsInRange(lp_Center, 0).OfType().Any()) + { + e.Mobile.SendMessage("Lamp room puzzle already exists: please delete the existing controller first ..."); + return; + } + + e.Mobile.SendMessage("Generating Lamp Room puzzle..."); + new LeverPuzzleController().MoveToWorld(lp_Center, Map.Malas); + + if (!installed) + e.Mobile.SendMessage("There was a problem generating the puzzle."); + else + e.Mobile.SendMessage("Lamp room puzzle successfully generated."); + } + + public static Item AddLeverPuzzlePart(int[] loc, Item newitem) + { + if (newitem?.Deleted != false) + installed = false; + else + newitem.MoveToWorld(new Point3D(loc[0], loc[1], loc[2]), Map.Malas); + + return newitem; + } + + public override void OnDelete() + { + KillTimers(); + base.OnDelete(); + } + + public override void OnAfterDelete() + { + NukeItemList(m_Teles); + NukeItemList(m_Statues); + NukeItemList(m_Levers); + + m_LampRoom?.Unregister(); + if (m_Tiles != null) + foreach (var region in m_Tiles) + region.Unregister(); + if (m_Box?.Deleted == false) + m_Box.Delete(); + } + + public static void NukeItemList(List list) + { + if (list?.Count > 0) + foreach (var item in list) + if (item?.Deleted == false) + item.Delete(); + } + + public virtual PlayerMobile GetOccupant(int index) + { + var region = m_Tiles[index]; + + if (region?.Occupant?.Alive == true) return (PlayerMobile)region.Occupant; + return null; + } + + public virtual LeverPuzzleStatue GetStatue(int index) + { + var statue = (LeverPuzzleStatue)m_Statues[index]; + return statue?.Deleted == false ? statue : null; + } + + public virtual LeverPuzzleLever GetLever(int index) + { + var lever = (LeverPuzzleLever)m_Levers[index]; + + return lever?.Deleted == false ? lever : null; + } + + public virtual void PuzzleStatus(int message, string fstring = null) + { + for (var i = 0; i < 2; i++) + { + Item s; + if ((s = GetStatue(i)) != null) + s.PublicOverheadMessage(MessageType.Regular, 0x3B2, message, fstring); + } + } + + public virtual void ResetPuzzle() + { + PuzzleStatus(1062053); + ResetLevers(); + } + + public virtual void ResetLevers() + { + for (var i = 0; i < 4; i++) + { + Item l; + if ((l = GetLever(i)) != null) + { + l.ItemID = 0x108E; + Effects.PlaySound(l.Location, Map, 0x3E8); + } + } + + TheirKey ^= TheirKey; + } + + public virtual void KillTimers() + { + if (l_Timer?.Running == true) l_Timer.Stop(); + if (m_Timer?.Running == true) m_Timer.Stop(); + } + + public virtual void RemoveSuccessful() + { + Successful = null; + } + + public virtual void LeverPulled(ushort code) + { + var correct = 0; + + KillTimers(); + + /* if one bit in each of the four nibbles is set, this is false */ + + if ((TheirKey = (ushort)(code | (TheirKey <<= 4))) < 0x0FFF) + { + l_Timer = Timer.DelayCall(TimeSpan.FromSeconds(30.0), ResetPuzzle); + return; + } + + if (!CircleComplete) + { + PuzzleStatus(1050004); // The circle is the key... + } + else + { + Mobile player; + if (TheirKey == MyKey) + { + GenKey(); + if ((Successful = player = GetOccupant(0)) != null) + { + SendLocationEffect(lp_Center, 0x1153, 0, 60, 1); + PlaySounds(lp_Center, cs1); + + Effects.SendBoltEffect(player, true); + player.MoveToWorld(lr_Enter, Map.Malas); + + m_Timer = new LampRoomTimer(this); + m_Timer.Start(); + Enabled = false; + } + } + else + { + for (var i = 0; i < 16; i++) /* Count matching SET bits, ie correct codes */ + if (((MyKey >> i) & 1) == 1 && ((TheirKey >> i) & 1) == 1) + correct++; + + PuzzleStatus(Statue_Msg[correct], correct > 0 ? correct.ToString() : null); + + for (var i = 0; i < 5; i++) + if ((player = GetOccupant(i)) != null) + new RockTimer(player, this).Start(); + } + } + + ResetLevers(); + } + + public virtual void GenKey() + { + Span ca = stackalloc ushort[] { 1, 2, 4, 8 }; + ca.Shuffle(); + + for (var i = 0; i < 4; i++) MyKey = (ushort)(ca[i] | (MyKey <<= 4)); + } + + private static bool IsValidDamagable(Mobile m) => + m?.Deleted == false && + (m.Player && m.Alive || + m is BaseCreature bc && (bc.Controlled || bc.Summoned) && !bc.IsDeadBondedPet); + + public static void MoveMobileOut(Mobile m) + { + if (m != null) + { + if (m is PlayerMobile && !m.Alive && m.Corpse?.Deleted == false) + m.Corpse.MoveToWorld(lr_Exit, Map.Malas); + + BaseCreature.TeleportPets(m, lr_Exit, Map.Malas); + m.Location = lr_Exit; + m.ProcessDelta(); + } + } + + public static bool AniSafe(Mobile m) => + m?.BodyMod == 0 && m.Alive && !TransformationSpellHelper.UnderTransformation(m); + + public static IEntity ZAdjustedIEFromMobile(Mobile m, int zDelta) => new Entity( + Serial.Zero, + new Point3D(m.X, m.Y, m.Z + zDelta), + m.Map + ); + + public static void DoDamage(Mobile m, int min, int max, bool poison) + { + if (m?.Deleted == false && m.Alive) + { + var damage = Utility.Random(min, max); + AOS.Damage(m, damage, poison ? 0 : 100, 0, 0, poison ? 100 : 0, 0); + } + } + + public static Point3D RandomPointIn(Point3D point, int range) => RandomPointIn( + point.X - range, + point.Y - range, + range * 2, + range * 2, + point.Z + ); + + public static Point3D RandomPointIn(Rectangle2D rect, int z) => + RandomPointIn(rect.X, rect.Y, rect.Height, rect.Width, z); + + public static Point3D RandomPointIn(int x, int y, int x2, int y2, int z) => + new Point3D(Utility.Random(x, x2), Utility.Random(y, y2), z); + + public static void PlaySounds(Point3D location, int[] sounds) + { + foreach (var soundid in sounds) + Effects.PlaySound(location, Map.Malas, soundid); + } + + public static void PlayEffect(IEntity from, IEntity to, int itemid, int speed, bool explodes) + { + Effects.SendMovingParticles(from, to, itemid, speed, 0, true, explodes, 2, 0, 0); + } + + public static void SendLocationEffect(IPoint3D p, int itemID, int speed, int duration, int hue) + { + Effects.SendPacket(p, Map.Malas, new LocationEffect(p, itemID, speed, duration, hue, 0)); + } + + public static void PlayerSendASCII(Mobile player, int index) + { + player.Send( + new AsciiMessage( + Serial.MinusOne, + 0xFFFF, + MessageType.Label, + MsgParams[index][0], + MsgParams[index][1], + null, + Msgs[index] + ) + ); + } + + /* I cant find any better way to send "speech" using fonts other than default */ + public static void POHMessage(Mobile from, int index) + { + Packet p = new AsciiMessage( + from.Serial, + from.Body, + MessageType.Regular, + MsgParams[index][0], + MsgParams[index][1], + from.Name, + Msgs[index] + ); + p.Acquire(); + foreach (var state in from.Map.GetClientsInRange(from.Location)) + state.Send(p); + + Packet.Release(p); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(0); // version + writer.WriteItemList(m_Levers, true); + writer.WriteItemList(m_Statues, true); + writer.WriteItemList(m_Teles, true); + writer.Write(m_Box); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Levers = reader.ReadStrongItemList(); + m_Statues = reader.ReadStrongItemList(); + m_Teles = reader.ReadStrongItemList(); + + m_Box = reader.ReadItem() as LampRoomBox; + + m_Tiles = new List(); + for (var i = 4; i < 9; i++) + m_Tiles.Add(new LeverPuzzleRegion(this, TA[i])); + + m_LampRoom = new LampRoomRegion(this); + Enabled = true; + TheirKey = 0; + MyKey = 0; + GenKey(); + } + + public class RockTimer : Timer + { + private readonly Mobile m_Player; + private int Count; + private LeverPuzzleController m_Controller; + + public RockTimer(Mobile player, LeverPuzzleController controller) + : base(TimeSpan.Zero, TimeSpan.FromSeconds(.25)) + { + Count = 0; + m_Player = player; + m_Controller = controller; + } + + private int Rock() => 0x1363 + Utility.Random(0, 11); + + protected override void OnTick() + { + if (m_Player == null || m_Player.Map != Map.Malas) + { + Stop(); + } + else + { + Count++; + if (Count == 1) /* TODO consolidate */ + { + m_Player.Paralyze(TimeSpan.FromSeconds(2)); + Effects.SendTargetEffect(m_Player, 0x11B7, 20, 10); + PlayerSendASCII(m_Player, 0); // You are pinned down ... + + PlaySounds(m_Player.Location, !m_Player.Female ? fs : ms); + PlayEffect(ZAdjustedIEFromMobile(m_Player, 50), m_Player, 0x11B7, 20, false); + } + else if (Count == 2) + { + DoDamage(m_Player, 80, 90, false); + Effects.SendTargetEffect(m_Player, 0x36BD, 20, 10); + PlaySounds(m_Player.Location, exp); + PlayerSendASCII(m_Player, 1); // A speeding rock ... + + if (AniSafe(m_Player)) m_Player.Animate(21, 10, 1, true, true, 0); + } + else if (Count == 3) + { + Stop(); + + Effects.SendTargetEffect(m_Player, 0x36B0, 20, 10); + PlayerSendASCII(m_Player, 1); // A speeding rock ... + PlaySounds(m_Player.Location, !m_Player.Female ? fs2 : ms2); + + var j = Utility.Random(6, 10); + for (var i = 0; i < j; i++) + { + IEntity m_IEntity = new Entity(Serial.Zero, RandomPointIn(m_Player.Location, 10), m_Player.Map); + + var mobiles = m_IEntity.Map.GetMobilesInRange(m_IEntity.Location, 2).ToList(); + + for (var k = 0; k < mobiles.Count; k++) + if (IsValidDamagable(mobiles[k]) && mobiles[k] != m_Player) + { + PlayEffect(m_Player, mobiles[k], Rock(), 8, true); + DoDamage(mobiles[k], 25, 30, false); + + if (mobiles[k].Player) POHMessage(mobiles[k], 2); // OUCH! + } + + PlayEffect(m_Player, m_IEntity, Rock(), 8, false); + } + } + } + } + } + + public class LampRoomKickTimer : Timer + { + private readonly Mobile m; + + public LampRoomKickTimer(Mobile player) + : base(TimeSpan.FromSeconds(.25)) => + m = player; + + protected override void OnTick() + { + MoveMobileOut(m); + } + } + + public class LampRoomTimer : Timer + { + public int level; + public LeverPuzzleController m_Controller; + public int ticks; + + public LampRoomTimer(LeverPuzzleController controller) + : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0)) + { + level = 0; + ticks = 0; + m_Controller = controller; + } + + protected override void OnTick() + { + ticks++; + var mobiles = m_Controller.m_LampRoom.GetMobiles(); + + if (ticks >= 71 || m_Controller.m_LampRoom.GetPlayerCount() == 0) + { + foreach (var mobile in mobiles) + if (mobile?.Deleted == false && !mobile.IsDeadBondedPet) + mobile.Kill(); + m_Controller.Enabled = true; + Stop(); + } + else + { + if (ticks % 12 == 0) level++; + foreach (var mobile in mobiles) + if (IsValidDamagable(mobile)) + { + if (ticks % 2 == 0 && level == 5) + { + if (mobile.Player) + { + mobile.Say(1062092); + if (AniSafe(mobile)) mobile.Animate(32, 5, 1, true, false, 0); + } + + DoDamage(mobile, 15, 20, true); + } + + if (Utility.Random((int)(level & ~0xfffffffc), 3) == 3) + mobile.ApplyPoison(mobile, PA2[level]); + if (ticks % 12 == 0 && level > 0 && mobile.Player) + mobile.SendLocalizedMessage(PA[level][0], null, PA[level][1]); + } + + for (var i = 0; i <= level; i++) + SendLocationEffect(RandomPointIn(lr_Rect, -1), 0x36B0, Utility.Random(150, 200), 0, PA[level][2]); + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Doom/LeverPuzzle/LeverPuzzleItems.cs b/Projects/UOContent/Engines/Doom/LeverPuzzle/LeverPuzzleItems.cs index 05417dbae..5865ba98d 100644 --- a/Projects/UOContent/Engines/Doom/LeverPuzzle/LeverPuzzleItems.cs +++ b/Projects/UOContent/Engines/Doom/LeverPuzzle/LeverPuzzleItems.cs @@ -1,205 +1,205 @@ -using System; -using Server.Mobiles; -using Server.Network; -using Server.Spells; - -namespace Server.Engines.Doom -{ - public class LampRoomBox : Item - { - private LeverPuzzleController m_Controller; - private Mobile m_Wanderer; - - public LampRoomBox(LeverPuzzleController controller) : base(0xe80) - { - m_Controller = controller; - ItemID = 0xe80; - Movable = false; - } - - public LampRoomBox(Serial serial) : base(serial) - { - } - - public override void OnDoubleClick(Mobile m) - { - if (!m.InRange(GetWorldLocation(), 3)) - return; - if (m_Controller.Enabled) - return; - - if (m_Wanderer?.Alive != true) - { - m_Wanderer = new WandererOfTheVoid(); - m_Wanderer.MoveToWorld(LeverPuzzleController.lr_Enter, Map.Malas); - m_Wanderer.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1060002); // I am the guardian of... - Timer.DelayCall(TimeSpan.FromSeconds(5.0), CallBackMessage); - } - } - - public void CallBackMessage() - { - PublicOverheadMessage(MessageType.Regular, 0x3B2, 1060003, ""); // You try to pry the box open... - } - - public override void OnAfterDelete() - { - if (m_Controller?.Deleted == false) - m_Controller.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - writer.Write(m_Controller); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - m_Controller = reader.ReadItem() as LeverPuzzleController; - } - } - - public class LeverPuzzleStatue : Item - { - private LeverPuzzleController m_Controller; - - public LeverPuzzleStatue(int[] dat, LeverPuzzleController controller) : base(dat[0]) - { - m_Controller = controller; - Hue = 0x44E; - Movable = false; - } - - public LeverPuzzleStatue(Serial serial) : base(serial) - { - } - - public override void OnAfterDelete() - { - if (m_Controller?.Deleted == false) - m_Controller.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - writer.Write(m_Controller); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - m_Controller = reader.ReadItem() as LeverPuzzleController; - } - } - - public class LeverPuzzleLever : Item - { - private LeverPuzzleController m_Controller; - - public LeverPuzzleLever(ushort code, LeverPuzzleController controller) : base(0x108E) - { - m_Controller = controller; - Code = code; - Hue = 0x66D; - Movable = false; - } - - public LeverPuzzleLever(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public ushort Code { get; private set; } - - public override void OnDoubleClick(Mobile m) - { - if (m != null && m_Controller.Enabled) - { - ItemID ^= 2; - Effects.PlaySound(Location, Map, 0x3E8); - m_Controller.LeverPulled(Code); - } - else - { - m?.SendLocalizedMessage(1060001); // You throw the switch, but the mechanism cannot be engaged again so soon. - } - } - - public override void OnAfterDelete() - { - if (m_Controller?.Deleted == false) - m_Controller.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - writer.Write(Code); - writer.Write(m_Controller); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - Code = reader.ReadUShort(); - m_Controller = reader.ReadItem() as LeverPuzzleController; - } - } - - [TypeAlias("Server.Engines.Doom.LampRoomTelePorter")] - public class LampRoomTeleporter : Item - { - public LampRoomTeleporter(int[] dat) - { - Hue = dat[1]; - ItemID = dat[0]; - Movable = false; - } - - public LampRoomTeleporter(Serial serial) : base(serial) - { - } - - public override bool HandlesOnMovement => true; - - public override bool OnMoveOver(Mobile m) - { - if (m is PlayerMobile) - { - if (SpellHelper.CheckCombat(m)) - { - m.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle?? - } - else - { - BaseCreature.TeleportPets(m, LeverPuzzleController.lr_Exit, Map.Malas); - m.MoveToWorld(LeverPuzzleController.lr_Exit, Map.Malas); - return false; - } - } - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} +using System; +using Server.Mobiles; +using Server.Network; +using Server.Spells; + +namespace Server.Engines.Doom +{ + public class LampRoomBox : Item + { + private LeverPuzzleController m_Controller; + private Mobile m_Wanderer; + + public LampRoomBox(LeverPuzzleController controller) : base(0xe80) + { + m_Controller = controller; + ItemID = 0xe80; + Movable = false; + } + + public LampRoomBox(Serial serial) : base(serial) + { + } + + public override void OnDoubleClick(Mobile m) + { + if (!m.InRange(GetWorldLocation(), 3)) + return; + if (m_Controller.Enabled) + return; + + if (m_Wanderer?.Alive != true) + { + m_Wanderer = new WandererOfTheVoid(); + m_Wanderer.MoveToWorld(LeverPuzzleController.lr_Enter, Map.Malas); + m_Wanderer.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1060002); // I am the guardian of... + Timer.DelayCall(TimeSpan.FromSeconds(5.0), CallBackMessage); + } + } + + public void CallBackMessage() + { + PublicOverheadMessage(MessageType.Regular, 0x3B2, 1060003, ""); // You try to pry the box open... + } + + public override void OnAfterDelete() + { + if (m_Controller?.Deleted == false) + m_Controller.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(0); // version + writer.Write(m_Controller); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + m_Controller = reader.ReadItem() as LeverPuzzleController; + } + } + + public class LeverPuzzleStatue : Item + { + private LeverPuzzleController m_Controller; + + public LeverPuzzleStatue(int[] dat, LeverPuzzleController controller) : base(dat[0]) + { + m_Controller = controller; + Hue = 0x44E; + Movable = false; + } + + public LeverPuzzleStatue(Serial serial) : base(serial) + { + } + + public override void OnAfterDelete() + { + if (m_Controller?.Deleted == false) + m_Controller.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(0); // version + writer.Write(m_Controller); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + m_Controller = reader.ReadItem() as LeverPuzzleController; + } + } + + public class LeverPuzzleLever : Item + { + private LeverPuzzleController m_Controller; + + public LeverPuzzleLever(ushort code, LeverPuzzleController controller) : base(0x108E) + { + m_Controller = controller; + Code = code; + Hue = 0x66D; + Movable = false; + } + + public LeverPuzzleLever(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public ushort Code { get; private set; } + + public override void OnDoubleClick(Mobile m) + { + if (m != null && m_Controller.Enabled) + { + ItemID ^= 2; + Effects.PlaySound(Location, Map, 0x3E8); + m_Controller.LeverPulled(Code); + } + else + { + m?.SendLocalizedMessage(1060001); // You throw the switch, but the mechanism cannot be engaged again so soon. + } + } + + public override void OnAfterDelete() + { + if (m_Controller?.Deleted == false) + m_Controller.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(0); // version + writer.Write(Code); + writer.Write(m_Controller); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + Code = reader.ReadUShort(); + m_Controller = reader.ReadItem() as LeverPuzzleController; + } + } + + [TypeAlias("Server.Engines.Doom.LampRoomTelePorter")] + public class LampRoomTeleporter : Item + { + public LampRoomTeleporter(int[] dat) + { + Hue = dat[1]; + ItemID = dat[0]; + Movable = false; + } + + public LampRoomTeleporter(Serial serial) : base(serial) + { + } + + public override bool HandlesOnMovement => true; + + public override bool OnMoveOver(Mobile m) + { + if (m is PlayerMobile) + { + if (SpellHelper.CheckCombat(m)) + { + m.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle?? + } + else + { + BaseCreature.TeleportPets(m, LeverPuzzleController.lr_Exit, Map.Malas); + m.MoveToWorld(LeverPuzzleController.lr_Exit, Map.Malas); + return false; + } + } + + return true; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Doom/LeverPuzzle/LeverPuzzleRegions.cs b/Projects/UOContent/Engines/Doom/LeverPuzzle/LeverPuzzleRegions.cs index 2c8594027..8c2810923 100644 --- a/Projects/UOContent/Engines/Doom/LeverPuzzle/LeverPuzzleRegions.cs +++ b/Projects/UOContent/Engines/Doom/LeverPuzzle/LeverPuzzleRegions.cs @@ -1,99 +1,100 @@ -using Server.Mobiles; -using Server.Regions; - -namespace Server.Engines.Doom -{ - public class LampRoomRegion : BaseRegion - { - private readonly LeverPuzzleController m_Controller; - - public LampRoomRegion(LeverPuzzleController controller) - : base(null, Map.Malas, Find(LeverPuzzleController.lr_Enter, Map.Malas), LeverPuzzleController.lr_Rect) - { - m_Controller = controller; - Register(); - } - - public static void Initialize() - { - EventSink.Login += OnLogin; - } - - public static void OnLogin(Mobile m) - { - Rectangle2D rect = LeverPuzzleController.lr_Rect; - if (m.X >= rect.X && m.X <= rect.X + 10 && m.Y >= rect.Y && m.Y <= rect.Y + 10 && m.Map == Map.Internal) - { - Timer kick = new LeverPuzzleController.LampRoomKickTimer(m); - kick.Start(); - } - } - - public override void OnEnter(Mobile m) - { - if (m == null || m is WandererOfTheVoid) - return; - - if (m.AccessLevel > AccessLevel.Player) - return; - - if (m_Controller.Successful != null) - { - if (m is PlayerMobile) - { - if (m == m_Controller.Successful) return; - } - else if (m is BaseCreature bc && ((bc.Controlled && bc.ControlMaster == m_Controller.Successful) || - bc.Summoned)) - { - return; - } - } - - Timer kick = new LeverPuzzleController.LampRoomKickTimer(m); - kick.Start(); - } - - public override void OnExit(Mobile m) - { - if (m != null && m == m_Controller.Successful) - m_Controller.RemoveSuccessful(); - } - - public override void OnDeath(Mobile m) - { - if (m?.Deleted != false || m is WandererOfTheVoid) - return; - Timer kick = new LeverPuzzleController.LampRoomKickTimer(m); - kick.Start(); - } - - public override bool OnSkillUse(Mobile m, int Skill) /* just in case */ => m_Controller.Successful != null && (m.AccessLevel != AccessLevel.Player || m == m_Controller.Successful); - } - - public class LeverPuzzleRegion : BaseRegion - { - public Mobile m_Occupant; - - public LeverPuzzleRegion(LeverPuzzleController controller, int[] loc) - : base(null, Map.Malas, Find(LeverPuzzleController.lr_Enter, Map.Malas), new Rectangle2D(loc[0], loc[1], 1, 1)) - { - Register(); - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Occupant => m_Occupant?.Alive == true ? m_Occupant : null; - - public override void OnEnter(Mobile m) - { - if (m != null && m_Occupant == null && m is PlayerMobile && m.Alive) - m_Occupant = m; - } - - public override void OnExit(Mobile m) - { - if (m != null && m == m_Occupant) - m_Occupant = null; - } - } -} +using Server.Mobiles; +using Server.Regions; + +namespace Server.Engines.Doom +{ + public class LampRoomRegion : BaseRegion + { + private readonly LeverPuzzleController m_Controller; + + public LampRoomRegion(LeverPuzzleController controller) + : base(null, Map.Malas, Find(LeverPuzzleController.lr_Enter, Map.Malas), LeverPuzzleController.lr_Rect) + { + m_Controller = controller; + Register(); + } + + public static void Initialize() + { + EventSink.Login += OnLogin; + } + + public static void OnLogin(Mobile m) + { + var rect = LeverPuzzleController.lr_Rect; + if (m.X >= rect.X && m.X <= rect.X + 10 && m.Y >= rect.Y && m.Y <= rect.Y + 10 && m.Map == Map.Internal) + { + Timer kick = new LeverPuzzleController.LampRoomKickTimer(m); + kick.Start(); + } + } + + public override void OnEnter(Mobile m) + { + if (m == null || m is WandererOfTheVoid) + return; + + if (m.AccessLevel > AccessLevel.Player) + return; + + if (m_Controller.Successful != null) + { + if (m is PlayerMobile) + { + if (m == m_Controller.Successful) return; + } + else if (m is BaseCreature bc && (bc.Controlled && bc.ControlMaster == m_Controller.Successful || + bc.Summoned)) + { + return; + } + } + + Timer kick = new LeverPuzzleController.LampRoomKickTimer(m); + kick.Start(); + } + + public override void OnExit(Mobile m) + { + if (m != null && m == m_Controller.Successful) + m_Controller.RemoveSuccessful(); + } + + public override void OnDeath(Mobile m) + { + if (m?.Deleted != false || m is WandererOfTheVoid) + return; + Timer kick = new LeverPuzzleController.LampRoomKickTimer(m); + kick.Start(); + } + + public override bool OnSkillUse(Mobile m, int Skill) /* just in case */ => m_Controller.Successful != null && + (m.AccessLevel != AccessLevel.Player || m == m_Controller.Successful); + } + + public class LeverPuzzleRegion : BaseRegion + { + public Mobile m_Occupant; + + public LeverPuzzleRegion(LeverPuzzleController controller, int[] loc) + : base(null, Map.Malas, Find(LeverPuzzleController.lr_Enter, Map.Malas), new Rectangle2D(loc[0], loc[1], 1, 1)) + { + Register(); + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Occupant => m_Occupant?.Alive == true ? m_Occupant : null; + + public override void OnEnter(Mobile m) + { + if (m != null && m_Occupant == null && m is PlayerMobile && m.Alive) + m_Occupant = m; + } + + public override void OnExit(Mobile m) + { + if (m != null && m == m_Occupant) + m_Occupant = null; + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Core/Ethic.cs b/Projects/UOContent/Engines/Ethics/Core/Ethic.cs index 509f94737..8cf674545 100644 --- a/Projects/UOContent/Engines/Ethics/Core/Ethic.cs +++ b/Projects/UOContent/Engines/Ethics/Core/Ethic.cs @@ -1,223 +1,222 @@ -using System.Linq; -using Server.Ethics.Evil; -using Server.Ethics.Hero; -using Server.Items; -using Server.Mobiles; - -namespace Server.Ethics -{ - public abstract class Ethic - { - public static bool Enabled { get; private set; } - - public static readonly Ethic Hero = new HeroEthic(); - public static readonly Ethic Evil = new EvilEthic(); - - public static readonly Ethic[] Ethics = - { - Hero, - Evil - }; - - protected EthicDefinition m_Definition; - - protected PlayerCollection m_Players; - - public Ethic() => m_Players = new PlayerCollection(); - - public EthicDefinition Definition => m_Definition; - - public PlayerCollection Players => m_Players; - - public static Ethic Find(Item item) - { - if ((item.SavedFlags & 0x100) != 0) - { - if (item.Hue == Hero.Definition.PrimaryHue) - return Hero; - - item.SavedFlags &= ~0x100; - } - - if ((item.SavedFlags & 0x200) != 0) - { - if (item.Hue == Evil.Definition.PrimaryHue) - return Evil; - - item.SavedFlags &= ~0x200; - } - - return null; - } - - public static bool CheckTrade(Mobile from, Mobile to, Mobile newOwner, Item item) - { - Ethic itemEthic = Find(item); - - if (itemEthic == null || Find(newOwner) == itemEthic) - return true; - - if (itemEthic == Hero) - (from == newOwner ? to : from).SendMessage("Only heros may receive this item."); - else if (itemEthic == Evil) - (from == newOwner ? to : from).SendMessage("Only the evil may receive this item."); - - return false; - } - - public static bool CheckEquip(Mobile from, Item item) - { - Ethic itemEthic = Find(item); - - if (itemEthic == null || Find(from) == itemEthic) - return true; - - if (itemEthic == Hero) - from.SendMessage("Only heros may wear this item."); - else if (itemEthic == Evil) - from.SendMessage("Only the evil may wear this item."); - - return false; - } - - public static bool IsImbued(Item item) => IsImbued(item, false); - - public static bool IsImbued(Item item, bool recurse) - { - if (Find(item) != null) - return true; - - if (recurse) - foreach (Item child in item.Items) - if (IsImbued(child, true)) - return true; - - return false; - } - - public static void Initialize() - { - Enabled = ServerConfiguration.GetOrUpdateSetting("ethics.enable", false); - - if (Enabled) - EventSink.Speech += EventSink_Speech; - } - - public static void EventSink_Speech(SpeechEventArgs e) - { - if (e.Blocked || e.Handled) - return; - - Player pl = Player.Find(e.Mobile); - - if (pl == null) - { - for (int i = 0; i < Ethics.Length; ++i) - { - Ethic ethic = Ethics[i]; - - if (!ethic.IsEligible(e.Mobile)) - continue; - - if (!Insensitive.Equals(ethic.Definition.JoinPhrase.String, e.Speech)) - continue; - - if (!e.Mobile.GetItemsInRange(2).Any(item => item is AnkhNorth || item is AnkhWest)) - continue; - - pl = new Player(ethic, e.Mobile); - - pl.Attach(); - - e.Mobile.FixedEffect(0x373A, 10, 30); - e.Mobile.PlaySound(0x209); - - e.Handled = true; - break; - } - } - else - { - if (e.Mobile is PlayerMobile mobile && mobile.DuelContext != null) - return; - - Ethic ethic = pl.Ethic; - - for (int i = 0; i < ethic.Definition.Powers.Length; ++i) - { - Power power = ethic.Definition.Powers[i]; - - if (!Insensitive.Equals(power.Definition.Phrase.String, e.Speech)) - continue; - - if (!power.CheckInvoke(pl)) - continue; - - power.BeginInvoke(pl); - e.Handled = true; - - break; - } - } - } - - public static Ethic Find(Mobile mob) => Find(mob, false, false); - - public static Ethic Find(Mobile mob, bool inherit) => Find(mob, inherit, false); - - public static Ethic Find(Mobile mob, bool inherit, bool allegiance) - { - Player pl = Player.Find(mob); - - if (pl != null) - return pl.Ethic; - - if (inherit && mob is BaseCreature bc) - { - if (bc.Controlled) - return Find(bc.ControlMaster, false); - if (bc.Summoned) - return Find(bc.SummonMaster, false); - if (allegiance) - return bc.EthicAllegiance; - } - - return null; - } - - public abstract bool IsEligible(Mobile mob); - - public virtual void Deserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 0: - { - int playerCount = reader.ReadEncodedInt(); - - for (int i = 0; i < playerCount; ++i) - { - Player pl = new Player(this, reader); - - if (pl.Mobile != null) - Timer.DelayCall(pl.CheckAttach); - } - - break; - } - } - } - - public virtual void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.WriteEncodedInt(m_Players.Count); - - for (int i = 0; i < m_Players.Count; ++i) - m_Players[i].Serialize(writer); - } - } -} +using System.Linq; +using Server.Ethics.Evil; +using Server.Ethics.Hero; +using Server.Items; +using Server.Mobiles; + +namespace Server.Ethics +{ + public abstract class Ethic + { + public static readonly Ethic Hero = new HeroEthic(); + public static readonly Ethic Evil = new EvilEthic(); + + public static readonly Ethic[] Ethics = + { + Hero, + Evil + }; + + protected EthicDefinition m_Definition; + + protected PlayerCollection m_Players; + + public Ethic() => m_Players = new PlayerCollection(); + public static bool Enabled { get; private set; } + + public EthicDefinition Definition => m_Definition; + + public PlayerCollection Players => m_Players; + + public static Ethic Find(Item item) + { + if ((item.SavedFlags & 0x100) != 0) + { + if (item.Hue == Hero.Definition.PrimaryHue) + return Hero; + + item.SavedFlags &= ~0x100; + } + + if ((item.SavedFlags & 0x200) != 0) + { + if (item.Hue == Evil.Definition.PrimaryHue) + return Evil; + + item.SavedFlags &= ~0x200; + } + + return null; + } + + public static bool CheckTrade(Mobile from, Mobile to, Mobile newOwner, Item item) + { + var itemEthic = Find(item); + + if (itemEthic == null || Find(newOwner) == itemEthic) + return true; + + if (itemEthic == Hero) + (from == newOwner ? to : from).SendMessage("Only heros may receive this item."); + else if (itemEthic == Evil) + (from == newOwner ? to : from).SendMessage("Only the evil may receive this item."); + + return false; + } + + public static bool CheckEquip(Mobile from, Item item) + { + var itemEthic = Find(item); + + if (itemEthic == null || Find(from) == itemEthic) + return true; + + if (itemEthic == Hero) + from.SendMessage("Only heros may wear this item."); + else if (itemEthic == Evil) + from.SendMessage("Only the evil may wear this item."); + + return false; + } + + public static bool IsImbued(Item item) => IsImbued(item, false); + + public static bool IsImbued(Item item, bool recurse) + { + if (Find(item) != null) + return true; + + if (recurse) + foreach (var child in item.Items) + if (IsImbued(child, true)) + return true; + + return false; + } + + public static void Initialize() + { + Enabled = ServerConfiguration.GetOrUpdateSetting("ethics.enable", false); + + if (Enabled) + EventSink.Speech += EventSink_Speech; + } + + public static void EventSink_Speech(SpeechEventArgs e) + { + if (e.Blocked || e.Handled) + return; + + var pl = Player.Find(e.Mobile); + + if (pl == null) + { + for (var i = 0; i < Ethics.Length; ++i) + { + var ethic = Ethics[i]; + + if (!ethic.IsEligible(e.Mobile)) + continue; + + if (!Insensitive.Equals(ethic.Definition.JoinPhrase.String, e.Speech)) + continue; + + if (!e.Mobile.GetItemsInRange(2).Any(item => item is AnkhNorth || item is AnkhWest)) + continue; + + pl = new Player(ethic, e.Mobile); + + pl.Attach(); + + e.Mobile.FixedEffect(0x373A, 10, 30); + e.Mobile.PlaySound(0x209); + + e.Handled = true; + break; + } + } + else + { + if (e.Mobile is PlayerMobile mobile && mobile.DuelContext != null) + return; + + var ethic = pl.Ethic; + + for (var i = 0; i < ethic.Definition.Powers.Length; ++i) + { + var power = ethic.Definition.Powers[i]; + + if (!Insensitive.Equals(power.Definition.Phrase.String, e.Speech)) + continue; + + if (!power.CheckInvoke(pl)) + continue; + + power.BeginInvoke(pl); + e.Handled = true; + + break; + } + } + } + + public static Ethic Find(Mobile mob) => Find(mob, false, false); + + public static Ethic Find(Mobile mob, bool inherit) => Find(mob, inherit, false); + + public static Ethic Find(Mobile mob, bool inherit, bool allegiance) + { + var pl = Player.Find(mob); + + if (pl != null) + return pl.Ethic; + + if (inherit && mob is BaseCreature bc) + { + if (bc.Controlled) + return Find(bc.ControlMaster, false); + if (bc.Summoned) + return Find(bc.SummonMaster, false); + if (allegiance) + return bc.EthicAllegiance; + } + + return null; + } + + public abstract bool IsEligible(Mobile mob); + + public virtual void Deserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 0: + { + var playerCount = reader.ReadEncodedInt(); + + for (var i = 0; i < playerCount; ++i) + { + var pl = new Player(this, reader); + + if (pl.Mobile != null) + Timer.DelayCall(pl.CheckAttach); + } + + break; + } + } + } + + public virtual void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.WriteEncodedInt(m_Players.Count); + + for (var i = 0; i < m_Players.Count; ++i) + m_Players[i].Serialize(writer); + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Core/Persistance.cs b/Projects/UOContent/Engines/Ethics/Core/Persistance.cs index 0bfd67ad9..f3c819c30 100644 --- a/Projects/UOContent/Engines/Ethics/Core/Persistance.cs +++ b/Projects/UOContent/Engines/Ethics/Core/Persistance.cs @@ -1,57 +1,57 @@ -namespace Server.Ethics -{ - public class EthicsPersistance : Item - { - [Constructible] - public EthicsPersistance() - : base(1) - { - Movable = false; - - if (Instance?.Deleted != false) - Instance = this; - else - base.Delete(); - } - - public EthicsPersistance(Serial serial) - : base(serial) => - Instance = this; - - public static EthicsPersistance Instance { get; private set; } - - public override string DefaultName => "Ethics Persistance - Internal"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - for (int i = 0; i < Ethic.Ethics.Length; ++i) - Ethic.Ethics[i].Serialize(writer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - for (int i = 0; i < Ethic.Ethics.Length; ++i) - Ethic.Ethics[i].Deserialize(reader); - - break; - } - } - } - - public override void Delete() - { - } - } -} +namespace Server.Ethics +{ + public class EthicsPersistance : Item + { + [Constructible] + public EthicsPersistance() + : base(1) + { + Movable = false; + + if (Instance?.Deleted != false) + Instance = this; + else + base.Delete(); + } + + public EthicsPersistance(Serial serial) + : base(serial) => + Instance = this; + + public static EthicsPersistance Instance { get; private set; } + + public override string DefaultName => "Ethics Persistance - Internal"; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + for (var i = 0; i < Ethic.Ethics.Length; ++i) + Ethic.Ethics[i].Serialize(writer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + for (var i = 0; i < Ethic.Ethics.Length; ++i) + Ethic.Ethics[i].Deserialize(reader); + + break; + } + } + } + + public override void Delete() + { + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Core/Player.cs b/Projects/UOContent/Engines/Ethics/Core/Player.cs index cb1a44980..2eded0130 100644 --- a/Projects/UOContent/Engines/Ethics/Core/Player.cs +++ b/Projects/UOContent/Engines/Ethics/Core/Player.cs @@ -1,157 +1,157 @@ -using System; -using System.Collections.ObjectModel; -using Server.Mobiles; - -namespace Server.Ethics -{ - public class PlayerCollection : Collection - { - } - - [PropertyObject] - public class Player - { - private DateTime m_Shield; - - public Player(Ethic ethic, Mobile mobile) - { - Ethic = ethic; - Mobile = mobile; - - Power = 5; - History = 5; - } - - public Player(Ethic ethic, IGenericReader reader) - { - Ethic = ethic; - - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 0: - { - Mobile = reader.ReadMobile(); - - Power = reader.ReadEncodedInt(); - History = reader.ReadEncodedInt(); - - Steed = reader.ReadMobile(); - Familiar = reader.ReadMobile(); - - m_Shield = reader.ReadDeltaTime(); - - break; - } - } - } - - public Ethic Ethic { get; } - - public Mobile Mobile { get; } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public int Power { get; set; } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public int History { get; set; } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public Mobile Steed { get; set; } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public Mobile Familiar { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsShielded - { - get - { - if (m_Shield == DateTime.MinValue) - return false; - - if (DateTime.UtcNow < m_Shield + TimeSpan.FromHours(1.0)) - return true; - - FinishShield(); - return false; - } - } - - public static Player Find(Mobile mob) => Find(mob, false); - - public static Player Find(Mobile mob, bool inherit) - { - PlayerMobile pm = mob as PlayerMobile; - - if (pm == null) - { - if (inherit && mob is BaseCreature bc) - { - if (bc.Controlled) - pm = bc.ControlMaster as PlayerMobile; - else if (bc.Summoned) - pm = bc.SummonMaster as PlayerMobile; - } - - if (pm == null) - return null; - } - - Player pl = pm.EthicPlayer; - - if (pl?.Ethic.IsEligible(pl.Mobile) == false) - pm.EthicPlayer = pl = null; - - return pl; - } - - public void BeginShield() - { - m_Shield = DateTime.UtcNow; - } - - public void FinishShield() - { - m_Shield = DateTime.MinValue; - } - - public void CheckAttach() - { - if (Ethic.IsEligible(Mobile)) - Attach(); - } - - public void Attach() - { - if (Mobile is PlayerMobile mobile) - mobile.EthicPlayer = this; - - Ethic.Players.Add(this); - } - - public void Detach() - { - if (Mobile is PlayerMobile mobile) - mobile.EthicPlayer = null; - - Ethic.Players.Remove(this); - } - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(Mobile); - - writer.WriteEncodedInt(Power); - writer.WriteEncodedInt(History); - - writer.Write(Steed); - writer.Write(Familiar); - - writer.WriteDeltaTime(m_Shield); - } - } -} +using System; +using System.Collections.ObjectModel; +using Server.Mobiles; + +namespace Server.Ethics +{ + public class PlayerCollection : Collection + { + } + + [PropertyObject] + public class Player + { + private DateTime m_Shield; + + public Player(Ethic ethic, Mobile mobile) + { + Ethic = ethic; + Mobile = mobile; + + Power = 5; + History = 5; + } + + public Player(Ethic ethic, IGenericReader reader) + { + Ethic = ethic; + + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 0: + { + Mobile = reader.ReadMobile(); + + Power = reader.ReadEncodedInt(); + History = reader.ReadEncodedInt(); + + Steed = reader.ReadMobile(); + Familiar = reader.ReadMobile(); + + m_Shield = reader.ReadDeltaTime(); + + break; + } + } + } + + public Ethic Ethic { get; } + + public Mobile Mobile { get; } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public int Power { get; set; } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public int History { get; set; } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public Mobile Steed { get; set; } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public Mobile Familiar { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsShielded + { + get + { + if (m_Shield == DateTime.MinValue) + return false; + + if (DateTime.UtcNow < m_Shield + TimeSpan.FromHours(1.0)) + return true; + + FinishShield(); + return false; + } + } + + public static Player Find(Mobile mob) => Find(mob, false); + + public static Player Find(Mobile mob, bool inherit) + { + var pm = mob as PlayerMobile; + + if (pm == null) + { + if (inherit && mob is BaseCreature bc) + { + if (bc.Controlled) + pm = bc.ControlMaster as PlayerMobile; + else if (bc.Summoned) + pm = bc.SummonMaster as PlayerMobile; + } + + if (pm == null) + return null; + } + + var pl = pm.EthicPlayer; + + if (pl?.Ethic.IsEligible(pl.Mobile) == false) + pm.EthicPlayer = pl = null; + + return pl; + } + + public void BeginShield() + { + m_Shield = DateTime.UtcNow; + } + + public void FinishShield() + { + m_Shield = DateTime.MinValue; + } + + public void CheckAttach() + { + if (Ethic.IsEligible(Mobile)) + Attach(); + } + + public void Attach() + { + if (Mobile is PlayerMobile mobile) + mobile.EthicPlayer = this; + + Ethic.Players.Add(this); + } + + public void Detach() + { + if (Mobile is PlayerMobile mobile) + mobile.EthicPlayer = null; + + Ethic.Players.Remove(this); + } + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(Mobile); + + writer.WriteEncodedInt(Power); + writer.WriteEncodedInt(History); + + writer.Write(Steed); + writer.Write(Familiar); + + writer.WriteDeltaTime(m_Shield); + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Core/Power.cs b/Projects/UOContent/Engines/Ethics/Core/Power.cs index 2e50bc2de..8282ffaa6 100644 --- a/Projects/UOContent/Engines/Ethics/Core/Power.cs +++ b/Projects/UOContent/Engines/Ethics/Core/Power.cs @@ -1,33 +1,37 @@ -using Server.Network; - -namespace Server.Ethics -{ - public abstract class Power - { - protected PowerDefinition m_Definition; - - public PowerDefinition Definition => m_Definition; - - public virtual bool CheckInvoke(Player from) - { - if (!from.Mobile.CheckAlive()) - return false; - - if (from.Power < m_Definition.Power) - { - from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, - "You lack the power to invoke this ability."); - return false; - } - - return true; - } - - public abstract void BeginInvoke(Player from); - - public virtual void FinishInvoke(Player from) - { - from.Power -= m_Definition.Power; - } - } -} \ No newline at end of file +using Server.Network; + +namespace Server.Ethics +{ + public abstract class Power + { + protected PowerDefinition m_Definition; + + public PowerDefinition Definition => m_Definition; + + public virtual bool CheckInvoke(Player from) + { + if (!from.Mobile.CheckAlive()) + return false; + + if (from.Power < m_Definition.Power) + { + from.Mobile.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + false, + "You lack the power to invoke this ability." + ); + return false; + } + + return true; + } + + public abstract void BeginInvoke(Player from); + + public virtual void FinishInvoke(Player from) + { + from.Power -= m_Definition.Power; + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Definitions/EthicDefinition.cs b/Projects/UOContent/Engines/Ethics/Definitions/EthicDefinition.cs index 980c3e5a6..ab183cafd 100644 --- a/Projects/UOContent/Engines/Ethics/Definitions/EthicDefinition.cs +++ b/Projects/UOContent/Engines/Ethics/Definitions/EthicDefinition.cs @@ -1,28 +1,30 @@ -namespace Server.Ethics -{ - public class EthicDefinition - { - public EthicDefinition(int primaryHue, TextDefinition title, TextDefinition adjunct, TextDefinition joinPhrase, - Power[] powers) - { - PrimaryHue = primaryHue; - - Title = title; - Adjunct = adjunct; - - JoinPhrase = joinPhrase; - - Powers = powers; - } - - public int PrimaryHue { get; } - - public TextDefinition Title { get; } - - public TextDefinition Adjunct { get; } - - public TextDefinition JoinPhrase { get; } - - public Power[] Powers { get; } - } -} \ No newline at end of file +namespace Server.Ethics +{ + public class EthicDefinition + { + public EthicDefinition( + int primaryHue, TextDefinition title, TextDefinition adjunct, TextDefinition joinPhrase, + Power[] powers + ) + { + PrimaryHue = primaryHue; + + Title = title; + Adjunct = adjunct; + + JoinPhrase = joinPhrase; + + Powers = powers; + } + + public int PrimaryHue { get; } + + public TextDefinition Title { get; } + + public TextDefinition Adjunct { get; } + + public TextDefinition JoinPhrase { get; } + + public Power[] Powers { get; } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Definitions/PowerDefinition.cs b/Projects/UOContent/Engines/Ethics/Definitions/PowerDefinition.cs index 714966ea1..81a698d39 100644 --- a/Projects/UOContent/Engines/Ethics/Definitions/PowerDefinition.cs +++ b/Projects/UOContent/Engines/Ethics/Definitions/PowerDefinition.cs @@ -1,22 +1,22 @@ -namespace Server.Ethics -{ - public class PowerDefinition - { - public PowerDefinition(int power, TextDefinition name, TextDefinition phrase, TextDefinition description) - { - Power = power; - - Name = name; - Phrase = phrase; - Description = description; - } - - public int Power { get; } - - public TextDefinition Name { get; } - - public TextDefinition Phrase { get; } - - public TextDefinition Description { get; } - } -} \ No newline at end of file +namespace Server.Ethics +{ + public class PowerDefinition + { + public PowerDefinition(int power, TextDefinition name, TextDefinition phrase, TextDefinition description) + { + Power = power; + + Name = name; + Phrase = phrase; + Description = description; + } + + public int Power { get; } + + public TextDefinition Name { get; } + + public TextDefinition Phrase { get; } + + public TextDefinition Description { get; } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Evil/Ethic.cs b/Projects/UOContent/Engines/Ethics/Evil/Ethic.cs index d0d53f6e3..e895cad31 100644 --- a/Projects/UOContent/Engines/Ethics/Evil/Ethic.cs +++ b/Projects/UOContent/Engines/Ethics/Evil/Ethic.cs @@ -1,33 +1,35 @@ -using Server.Factions; - -namespace Server.Ethics.Evil -{ - public sealed class EvilEthic : Ethic - { - public EvilEthic() - { - m_Definition = new EthicDefinition( - 0x455, - "Evil", "(Evil)", - "I am evil incarnate", - new Power[] - { - new UnholySense(), - new UnholyItem(), - new SummonFamiliar(), - new VileBlade(), - new Blight(), - new UnholyShield(), - new UnholySteed(), - new UnholyWord() - }); - } - - public override bool IsEligible(Mobile mob) - { - Faction fac = Faction.Find(mob); - - return fac is Minax || fac is Shadowlords; - } - } -} \ No newline at end of file +using Server.Factions; + +namespace Server.Ethics.Evil +{ + public sealed class EvilEthic : Ethic + { + public EvilEthic() + { + m_Definition = new EthicDefinition( + 0x455, + "Evil", + "(Evil)", + "I am evil incarnate", + new Power[] + { + new UnholySense(), + new UnholyItem(), + new SummonFamiliar(), + new VileBlade(), + new Blight(), + new UnholyShield(), + new UnholySteed(), + new UnholyWord() + } + ); + } + + public override bool IsEligible(Mobile mob) + { + var fac = Faction.Find(mob); + + return fac is Minax || fac is Shadowlords; + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Evil/Mobiles/UnholyFamiliar.cs b/Projects/UOContent/Engines/Ethics/Evil/Mobiles/UnholyFamiliar.cs index 5c0e91750..6db604873 100644 --- a/Projects/UOContent/Engines/Ethics/Evil/Mobiles/UnholyFamiliar.cs +++ b/Projects/UOContent/Engines/Ethics/Evil/Mobiles/UnholyFamiliar.cs @@ -1,83 +1,83 @@ -using Server.Ethics; - -namespace Server.Mobiles -{ - public class UnholyFamiliar : BaseCreature - { - [Constructible] - public UnholyFamiliar() - : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) - { - Body = 99; - BaseSoundID = 0xE5; - - SetStr(96, 120); - SetDex(81, 105); - SetInt(36, 60); - - SetHits(58, 72); - SetMana(0); - - SetDamage(11, 17); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 20, 25); - SetResistance(ResistanceType.Fire, 10, 20); - SetResistance(ResistanceType.Cold, 5, 10); - SetResistance(ResistanceType.Poison, 5, 10); - SetResistance(ResistanceType.Energy, 10, 15); - - SetSkill(SkillName.MagicResist, 57.6, 75.0); - SetSkill(SkillName.Tactics, 50.1, 70.0); - SetSkill(SkillName.Wrestling, 60.1, 80.0); - - Fame = 2500; - Karma = 2500; - - VirtualArmor = 22; - - Tamable = false; - ControlSlots = 1; - } - - public UnholyFamiliar(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "an evil corpse"; - public override bool IsDispellable => false; - public override bool IsBondable => false; - public override string DefaultName => "a dark wolf"; - - public override int Meat => 1; - public override int Hides => 7; - public override FoodType FavoriteFood => FoodType.Meat; - public override PackInstinct PackInstinct => PackInstinct.Canine; - - public override string ApplyNameSuffix(string suffix) - { - if (suffix.Length == 0) - suffix = Ethic.Evil.Definition.Adjunct.String; - else - suffix = $"{suffix} {Ethic.Evil.Definition.Adjunct.String}"; - - return base.ApplyNameSuffix(suffix); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Ethics; + +namespace Server.Mobiles +{ + public class UnholyFamiliar : BaseCreature + { + [Constructible] + public UnholyFamiliar() + : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 99; + BaseSoundID = 0xE5; + + SetStr(96, 120); + SetDex(81, 105); + SetInt(36, 60); + + SetHits(58, 72); + SetMana(0); + + SetDamage(11, 17); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 20, 25); + SetResistance(ResistanceType.Fire, 10, 20); + SetResistance(ResistanceType.Cold, 5, 10); + SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Energy, 10, 15); + + SetSkill(SkillName.MagicResist, 57.6, 75.0); + SetSkill(SkillName.Tactics, 50.1, 70.0); + SetSkill(SkillName.Wrestling, 60.1, 80.0); + + Fame = 2500; + Karma = 2500; + + VirtualArmor = 22; + + Tamable = false; + ControlSlots = 1; + } + + public UnholyFamiliar(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "an evil corpse"; + public override bool IsDispellable => false; + public override bool IsBondable => false; + public override string DefaultName => "a dark wolf"; + + public override int Meat => 1; + public override int Hides => 7; + public override FoodType FavoriteFood => FoodType.Meat; + public override PackInstinct PackInstinct => PackInstinct.Canine; + + public override string ApplyNameSuffix(string suffix) + { + if (suffix.Length == 0) + suffix = Ethic.Evil.Definition.Adjunct.String; + else + suffix = $"{suffix} {Ethic.Evil.Definition.Adjunct.String}"; + + return base.ApplyNameSuffix(suffix); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Evil/Mobiles/UnholySteed.cs b/Projects/UOContent/Engines/Ethics/Evil/Mobiles/UnholySteed.cs index 5dc9b6b57..d3d4e820d 100644 --- a/Projects/UOContent/Engines/Ethics/Evil/Mobiles/UnholySteed.cs +++ b/Projects/UOContent/Engines/Ethics/Evil/Mobiles/UnholySteed.cs @@ -1,88 +1,88 @@ -using Server.Ethics; - -namespace Server.Mobiles -{ - public class UnholySteed : BaseMount - { - [Constructible] - public UnholySteed() - : base("a dark steed", 0x74, 0x3EA7, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) - { - SetStr(496, 525); - SetDex(86, 105); - SetInt(86, 125); - - SetHits(298, 315); - - SetDamage(16, 22); - - SetDamageType(ResistanceType.Physical, 40); - SetDamageType(ResistanceType.Fire, 40); - SetDamageType(ResistanceType.Energy, 20); - - SetResistance(ResistanceType.Physical, 55, 65); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 20, 30); - - SetSkill(SkillName.MagicResist, 25.1, 30.0); - SetSkill(SkillName.Tactics, 97.6, 100.0); - SetSkill(SkillName.Wrestling, 80.5, 92.5); - - Fame = 14000; - Karma = -14000; - - VirtualArmor = 60; - - Tamable = false; - ControlSlots = 1; - } - - public UnholySteed(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "an unholy corpse"; - public override bool IsDispellable => false; - public override bool IsBondable => false; - - public override bool HasBreath => true; - public override bool CanBreath => true; - - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - - public override string ApplyNameSuffix(string suffix) - { - if (suffix.Length == 0) - suffix = Ethic.Evil.Definition.Adjunct.String; - else - suffix = $"{suffix} {Ethic.Evil.Definition.Adjunct.String}"; - - return base.ApplyNameSuffix(suffix); - } - - public override void OnDoubleClick(Mobile from) - { - if (Ethic.Find(from) != Ethic.Evil) - from.SendMessage("You may not ride this steed."); - else - base.OnDoubleClick(from); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Ethics; + +namespace Server.Mobiles +{ + public class UnholySteed : BaseMount + { + [Constructible] + public UnholySteed() + : base("a dark steed", 0x74, 0x3EA7, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + SetStr(496, 525); + SetDex(86, 105); + SetInt(86, 125); + + SetHits(298, 315); + + SetDamage(16, 22); + + SetDamageType(ResistanceType.Physical, 40); + SetDamageType(ResistanceType.Fire, 40); + SetDamageType(ResistanceType.Energy, 20); + + SetResistance(ResistanceType.Physical, 55, 65); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 20, 30); + + SetSkill(SkillName.MagicResist, 25.1, 30.0); + SetSkill(SkillName.Tactics, 97.6, 100.0); + SetSkill(SkillName.Wrestling, 80.5, 92.5); + + Fame = 14000; + Karma = -14000; + + VirtualArmor = 60; + + Tamable = false; + ControlSlots = 1; + } + + public UnholySteed(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "an unholy corpse"; + public override bool IsDispellable => false; + public override bool IsBondable => false; + + public override bool HasBreath => true; + public override bool CanBreath => true; + + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + + public override string ApplyNameSuffix(string suffix) + { + if (suffix.Length == 0) + suffix = Ethic.Evil.Definition.Adjunct.String; + else + suffix = $"{suffix} {Ethic.Evil.Definition.Adjunct.String}"; + + return base.ApplyNameSuffix(suffix); + } + + public override void OnDoubleClick(Mobile from) + { + if (Ethic.Find(from) != Ethic.Evil) + from.SendMessage("You may not ride this steed."); + else + base.OnDoubleClick(from); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Evil/Powers/Blight.cs b/Projects/UOContent/Engines/Ethics/Evil/Powers/Blight.cs index 6dd061d3d..b916eb0ee 100644 --- a/Projects/UOContent/Engines/Ethics/Evil/Powers/Blight.cs +++ b/Projects/UOContent/Engines/Ethics/Evil/Powers/Blight.cs @@ -1,73 +1,74 @@ -using System; -using Server.Network; -using Server.Spells; -using Server.Targeting; - -namespace Server.Ethics.Evil -{ - public sealed class Blight : Power - { - public Blight() => - m_Definition = new PowerDefinition( - 15, - "Blight", - "Velgo Ontawl", - ""); - - public override void BeginInvoke(Player from) - { - from.Mobile.BeginTarget(12, true, TargetFlags.None, Power_OnTarget, from); - from.Mobile.SendMessage("Where do you wish to blight?"); - } - - private void Power_OnTarget(Mobile fromMobile, object obj, Player from) - { - if (!(obj is IPoint3D p)) - return; - - if (!CheckInvoke(from)) - return; - - bool powerFunctioned = false; - - SpellHelper.GetSurfaceTop(ref p); - - foreach (Mobile mob in from.Mobile.GetMobilesInRange(6)) - { - if (mob == from.Mobile || !SpellHelper.ValidIndirectTarget(from.Mobile, mob)) - continue; - - if (mob.GetStatMod("Holy Curse") != null) - continue; - - if (!from.Mobile.CanBeHarmful(mob, false)) - continue; - - from.Mobile.DoHarmful(mob, true); - - mob.AddStatMod(new StatMod(StatType.All, "Holy Curse", -10, TimeSpan.FromMinutes(30.0))); - - mob.FixedParticles(0x374A, 10, 15, 5028, EffectLayer.Waist); - mob.PlaySound(0x1FB); - - powerFunctioned = true; - } - - if (powerFunctioned) - { - SpellHelper.Turn(from.Mobile, p); - - Effects.PlaySound(p, from.Mobile.Map, 0x1FB); - - from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You curse the area."); - - FinishInvoke(from); - } - else - { - from.Mobile.FixedEffect(0x3735, 6, 30); - from.Mobile.PlaySound(0x5C); - } - } - } -} \ No newline at end of file +using System; +using Server.Network; +using Server.Spells; +using Server.Targeting; + +namespace Server.Ethics.Evil +{ + public sealed class Blight : Power + { + public Blight() => + m_Definition = new PowerDefinition( + 15, + "Blight", + "Velgo Ontawl", + "" + ); + + public override void BeginInvoke(Player from) + { + from.Mobile.BeginTarget(12, true, TargetFlags.None, Power_OnTarget, from); + from.Mobile.SendMessage("Where do you wish to blight?"); + } + + private void Power_OnTarget(Mobile fromMobile, object obj, Player from) + { + if (!(obj is IPoint3D p)) + return; + + if (!CheckInvoke(from)) + return; + + var powerFunctioned = false; + + SpellHelper.GetSurfaceTop(ref p); + + foreach (var mob in from.Mobile.GetMobilesInRange(6)) + { + if (mob == from.Mobile || !SpellHelper.ValidIndirectTarget(from.Mobile, mob)) + continue; + + if (mob.GetStatMod("Holy Curse") != null) + continue; + + if (!from.Mobile.CanBeHarmful(mob, false)) + continue; + + from.Mobile.DoHarmful(mob, true); + + mob.AddStatMod(new StatMod(StatType.All, "Holy Curse", -10, TimeSpan.FromMinutes(30.0))); + + mob.FixedParticles(0x374A, 10, 15, 5028, EffectLayer.Waist); + mob.PlaySound(0x1FB); + + powerFunctioned = true; + } + + if (powerFunctioned) + { + SpellHelper.Turn(from.Mobile, p); + + Effects.PlaySound(p, from.Mobile.Map, 0x1FB); + + from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You curse the area."); + + FinishInvoke(from); + } + else + { + from.Mobile.FixedEffect(0x3735, 6, 30); + from.Mobile.PlaySound(0x5C); + } + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Evil/Powers/SummonFamiliar.cs b/Projects/UOContent/Engines/Ethics/Evil/Powers/SummonFamiliar.cs index 32a5c3fd1..972384619 100644 --- a/Projects/UOContent/Engines/Ethics/Evil/Powers/SummonFamiliar.cs +++ b/Projects/UOContent/Engines/Ethics/Evil/Powers/SummonFamiliar.cs @@ -1,43 +1,44 @@ -using System; -using Server.Mobiles; -using Server.Network; - -namespace Server.Ethics.Evil -{ - public sealed class SummonFamiliar : Power - { - public SummonFamiliar() => - m_Definition = new PowerDefinition( - 5, - "Summon Familiar", - "Trubechs Vingir", - ""); - - public override void BeginInvoke(Player from) - { - if (from.Familiar?.Deleted == true) - from.Familiar = null; - - if (from.Familiar != null) - { - from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You already have an unholy familiar."); - return; - } - - if (from.Mobile.Followers + 1 > from.Mobile.FollowersMax) - { - from.Mobile.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. - return; - } - - UnholyFamiliar familiar = new UnholyFamiliar(); - - if (BaseCreature.Summon(familiar, from.Mobile, from.Mobile.Location, 0x217, TimeSpan.FromHours(1.0))) - { - from.Familiar = familiar; - - FinishInvoke(from); - } - } - } -} +using System; +using Server.Mobiles; +using Server.Network; + +namespace Server.Ethics.Evil +{ + public sealed class SummonFamiliar : Power + { + public SummonFamiliar() => + m_Definition = new PowerDefinition( + 5, + "Summon Familiar", + "Trubechs Vingir", + "" + ); + + public override void BeginInvoke(Player from) + { + if (from.Familiar?.Deleted == true) + from.Familiar = null; + + if (from.Familiar != null) + { + from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You already have an unholy familiar."); + return; + } + + if (from.Mobile.Followers + 1 > from.Mobile.FollowersMax) + { + from.Mobile.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. + return; + } + + var familiar = new UnholyFamiliar(); + + if (BaseCreature.Summon(familiar, from.Mobile, from.Mobile.Location, 0x217, TimeSpan.FromHours(1.0))) + { + from.Familiar = familiar; + + FinishInvoke(from); + } + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Evil/Powers/UnholyItem.cs b/Projects/UOContent/Engines/Ethics/Evil/Powers/UnholyItem.cs index 28e65068f..2b06ede51 100644 --- a/Projects/UOContent/Engines/Ethics/Evil/Powers/UnholyItem.cs +++ b/Projects/UOContent/Engines/Ethics/Evil/Powers/UnholyItem.cs @@ -1,65 +1,70 @@ -using Server.Items; -using Server.Network; -using Server.Targeting; - -namespace Server.Ethics.Evil -{ - public sealed class UnholyItem : Power - { - public UnholyItem() => - m_Definition = new PowerDefinition( - 5, - "Unholy Item", - "Vidda K'balc", - ""); - - public override void BeginInvoke(Player from) - { - from.Mobile.BeginTarget(12, false, TargetFlags.None, Power_OnTarget, from); - from.Mobile.SendMessage("Which item do you wish to imbue?"); - } - - private void Power_OnTarget(Mobile fromMobile, object obj, Player from) - { - if (!(obj is Item item)) - { - from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You may not imbue that."); - return; - } - - if (item.Parent != from.Mobile) - { - from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, - "You may only imbue items you are wearing."); - return; - } - - if ((item.SavedFlags & 0x300) != 0) - { - from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "That has already beem imbued."); - return; - } - - bool canImbue = (item is Spellbook || item is BaseClothing || item is BaseArmor || item is BaseWeapon) && - item.Name == null; - - if (canImbue) - { - if (!CheckInvoke(from)) - return; - - item.Hue = Ethic.Evil.Definition.PrimaryHue; - item.SavedFlags |= 0x200; - - from.Mobile.FixedEffect(0x375A, 10, 20); - from.Mobile.PlaySound(0x209); - - FinishInvoke(from); - } - else - { - from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You may not imbue that."); - } - } - } -} \ No newline at end of file +using Server.Items; +using Server.Network; +using Server.Targeting; + +namespace Server.Ethics.Evil +{ + public sealed class UnholyItem : Power + { + public UnholyItem() => + m_Definition = new PowerDefinition( + 5, + "Unholy Item", + "Vidda K'balc", + "" + ); + + public override void BeginInvoke(Player from) + { + from.Mobile.BeginTarget(12, false, TargetFlags.None, Power_OnTarget, from); + from.Mobile.SendMessage("Which item do you wish to imbue?"); + } + + private void Power_OnTarget(Mobile fromMobile, object obj, Player from) + { + if (!(obj is Item item)) + { + from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You may not imbue that."); + return; + } + + if (item.Parent != from.Mobile) + { + from.Mobile.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + false, + "You may only imbue items you are wearing." + ); + return; + } + + if ((item.SavedFlags & 0x300) != 0) + { + from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "That has already beem imbued."); + return; + } + + var canImbue = (item is Spellbook || item is BaseClothing || item is BaseArmor || item is BaseWeapon) && + item.Name == null; + + if (canImbue) + { + if (!CheckInvoke(from)) + return; + + item.Hue = Ethic.Evil.Definition.PrimaryHue; + item.SavedFlags |= 0x200; + + from.Mobile.FixedEffect(0x375A, 10, 20); + from.Mobile.PlaySound(0x209); + + FinishInvoke(from); + } + else + { + from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You may not imbue that."); + } + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Evil/Powers/UnholySense.cs b/Projects/UOContent/Engines/Ethics/Evil/Powers/UnholySense.cs index 433b0961d..dfbe5924a 100644 --- a/Projects/UOContent/Engines/Ethics/Evil/Powers/UnholySense.cs +++ b/Projects/UOContent/Engines/Ethics/Evil/Powers/UnholySense.cs @@ -1,91 +1,92 @@ -using System; -using System.Text; -using Server.Network; - -namespace Server.Ethics.Evil -{ - public sealed class UnholySense : Power - { - public UnholySense() => - m_Definition = new PowerDefinition( - 0, - "Unholy Sense", - "Drewrok Velgo", - ""); - - public override void BeginInvoke(Player from) - { - Ethic opposition = Ethic.Hero; - - int enemyCount = 0; - - int maxRange = 18 + from.Power; - - Player primary = null; - - foreach (Player pl in opposition.Players) - { - Mobile mob = pl.Mobile; - - if (mob == null || mob.Map != from.Mobile.Map || !mob.Alive) - continue; - - if (!mob.InRange(from.Mobile, Math.Max(18, maxRange - pl.Power))) - continue; - - if (primary == null || pl.Power > primary.Power) - primary = pl; - - ++enemyCount; - } - - StringBuilder sb = new StringBuilder(); - - sb.Append("You sense "); - sb.Append(enemyCount == 0 ? "no" : enemyCount.ToString()); - sb.Append(enemyCount == 1 ? " enemy" : " enemies"); - - if (primary != null) - { - sb.Append(", and a strong presense"); - - switch (from.Mobile.GetDirectionTo(primary.Mobile)) - { - case Direction.West: - sb.Append(" to the west."); - break; - case Direction.East: - sb.Append(" to the east."); - break; - case Direction.North: - sb.Append(" to the north."); - break; - case Direction.South: - sb.Append(" to the south."); - break; - - case Direction.Up: - sb.Append(" to the north-west."); - break; - case Direction.Down: - sb.Append(" to the south-east."); - break; - case Direction.Left: - sb.Append(" to the south-west."); - break; - case Direction.Right: - sb.Append(" to the north-east."); - break; - } - } - else - { - sb.Append('.'); - } - - from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x59, false, sb.ToString()); - - FinishInvoke(from); - } - } -} \ No newline at end of file +using System; +using System.Text; +using Server.Network; + +namespace Server.Ethics.Evil +{ + public sealed class UnholySense : Power + { + public UnholySense() => + m_Definition = new PowerDefinition( + 0, + "Unholy Sense", + "Drewrok Velgo", + "" + ); + + public override void BeginInvoke(Player from) + { + var opposition = Ethic.Hero; + + var enemyCount = 0; + + var maxRange = 18 + from.Power; + + Player primary = null; + + foreach (var pl in opposition.Players) + { + var mob = pl.Mobile; + + if (mob == null || mob.Map != from.Mobile.Map || !mob.Alive) + continue; + + if (!mob.InRange(from.Mobile, Math.Max(18, maxRange - pl.Power))) + continue; + + if (primary == null || pl.Power > primary.Power) + primary = pl; + + ++enemyCount; + } + + var sb = new StringBuilder(); + + sb.Append("You sense "); + sb.Append(enemyCount == 0 ? "no" : enemyCount.ToString()); + sb.Append(enemyCount == 1 ? " enemy" : " enemies"); + + if (primary != null) + { + sb.Append(", and a strong presense"); + + switch (from.Mobile.GetDirectionTo(primary.Mobile)) + { + case Direction.West: + sb.Append(" to the west."); + break; + case Direction.East: + sb.Append(" to the east."); + break; + case Direction.North: + sb.Append(" to the north."); + break; + case Direction.South: + sb.Append(" to the south."); + break; + + case Direction.Up: + sb.Append(" to the north-west."); + break; + case Direction.Down: + sb.Append(" to the south-east."); + break; + case Direction.Left: + sb.Append(" to the south-west."); + break; + case Direction.Right: + sb.Append(" to the north-east."); + break; + } + } + else + { + sb.Append('.'); + } + + from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x59, false, sb.ToString()); + + FinishInvoke(from); + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Evil/Powers/UnholyShield.cs b/Projects/UOContent/Engines/Ethics/Evil/Powers/UnholyShield.cs index 8cabacc31..42186b10e 100644 --- a/Projects/UOContent/Engines/Ethics/Evil/Powers/UnholyShield.cs +++ b/Projects/UOContent/Engines/Ethics/Evil/Powers/UnholyShield.cs @@ -1,31 +1,40 @@ -using Server.Network; - -namespace Server.Ethics.Evil -{ - public sealed class UnholyShield : Power - { - public UnholyShield() => - m_Definition = new PowerDefinition( - 20, - "Unholy Shield", - "Velgo K'blac", - ""); - - public override void BeginInvoke(Player from) - { - if (from.IsShielded) - { - from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, - "You are already under the protection of an unholy shield."); - return; - } - - from.BeginShield(); - - from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, - "You are now under the protection of an unholy shield."); - - FinishInvoke(from); - } - } -} \ No newline at end of file +using Server.Network; + +namespace Server.Ethics.Evil +{ + public sealed class UnholyShield : Power + { + public UnholyShield() => + m_Definition = new PowerDefinition( + 20, + "Unholy Shield", + "Velgo K'blac", + "" + ); + + public override void BeginInvoke(Player from) + { + if (from.IsShielded) + { + from.Mobile.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + false, + "You are already under the protection of an unholy shield." + ); + return; + } + + from.BeginShield(); + + from.Mobile.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + false, + "You are now under the protection of an unholy shield." + ); + + FinishInvoke(from); + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Evil/Powers/UnholySteed.cs b/Projects/UOContent/Engines/Ethics/Evil/Powers/UnholySteed.cs index 471eda197..770d6b95e 100644 --- a/Projects/UOContent/Engines/Ethics/Evil/Powers/UnholySteed.cs +++ b/Projects/UOContent/Engines/Ethics/Evil/Powers/UnholySteed.cs @@ -1,43 +1,44 @@ -using System; -using Server.Mobiles; -using Server.Network; - -namespace Server.Ethics.Evil -{ - public sealed class UnholySteed : Power - { - public UnholySteed() => - m_Definition = new PowerDefinition( - 30, - "Unholy Steed", - "Trubechs Yeliab", - ""); - - public override void BeginInvoke(Player from) - { - if (from.Steed?.Deleted == true) - from.Steed = null; - - if (from.Steed != null) - { - from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You already have an unholy steed."); - return; - } - - if (from.Mobile.Followers + 1 > from.Mobile.FollowersMax) - { - from.Mobile.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. - return; - } - - Mobiles.UnholySteed steed = new Mobiles.UnholySteed(); - - if (BaseCreature.Summon(steed, from.Mobile, from.Mobile.Location, 0x217, TimeSpan.FromHours(1.0))) - { - from.Steed = steed; - - FinishInvoke(from); - } - } - } -} +using System; +using Server.Mobiles; +using Server.Network; + +namespace Server.Ethics.Evil +{ + public sealed class UnholySteed : Power + { + public UnholySteed() => + m_Definition = new PowerDefinition( + 30, + "Unholy Steed", + "Trubechs Yeliab", + "" + ); + + public override void BeginInvoke(Player from) + { + if (from.Steed?.Deleted == true) + from.Steed = null; + + if (from.Steed != null) + { + from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You already have an unholy steed."); + return; + } + + if (from.Mobile.Followers + 1 > from.Mobile.FollowersMax) + { + from.Mobile.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. + return; + } + + var steed = new Mobiles.UnholySteed(); + + if (BaseCreature.Summon(steed, from.Mobile, from.Mobile.Location, 0x217, TimeSpan.FromHours(1.0))) + { + from.Steed = steed; + + FinishInvoke(from); + } + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Evil/Powers/UnholyWord.cs b/Projects/UOContent/Engines/Ethics/Evil/Powers/UnholyWord.cs index 1891e33ab..881880c48 100644 --- a/Projects/UOContent/Engines/Ethics/Evil/Powers/UnholyWord.cs +++ b/Projects/UOContent/Engines/Ethics/Evil/Powers/UnholyWord.cs @@ -1,16 +1,17 @@ -namespace Server.Ethics.Evil -{ - public sealed class UnholyWord : Power - { - public UnholyWord() => - m_Definition = new PowerDefinition( - 100, - "Unholy Word", - "Velgo Oostrac", - ""); - - public override void BeginInvoke(Player from) - { - } - } -} \ No newline at end of file +namespace Server.Ethics.Evil +{ + public sealed class UnholyWord : Power + { + public UnholyWord() => + m_Definition = new PowerDefinition( + 100, + "Unholy Word", + "Velgo Oostrac", + "" + ); + + public override void BeginInvoke(Player from) + { + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Evil/Powers/VileBlade.cs b/Projects/UOContent/Engines/Ethics/Evil/Powers/VileBlade.cs index bdb4caea1..fa0a180d2 100644 --- a/Projects/UOContent/Engines/Ethics/Evil/Powers/VileBlade.cs +++ b/Projects/UOContent/Engines/Ethics/Evil/Powers/VileBlade.cs @@ -1,16 +1,17 @@ -namespace Server.Ethics.Evil -{ - public sealed class VileBlade : Power - { - public VileBlade() => - m_Definition = new PowerDefinition( - 10, - "Vile Blade", - "Velgo Reyam", - ""); - - public override void BeginInvoke(Player from) - { - } - } -} \ No newline at end of file +namespace Server.Ethics.Evil +{ + public sealed class VileBlade : Power + { + public VileBlade() => + m_Definition = new PowerDefinition( + 10, + "Vile Blade", + "Velgo Reyam", + "" + ); + + public override void BeginInvoke(Player from) + { + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Hero/Ethic.cs b/Projects/UOContent/Engines/Ethics/Hero/Ethic.cs index 6dd4e530d..74d8906cf 100644 --- a/Projects/UOContent/Engines/Ethics/Hero/Ethic.cs +++ b/Projects/UOContent/Engines/Ethics/Hero/Ethic.cs @@ -1,36 +1,38 @@ -using Server.Factions; - -namespace Server.Ethics.Hero -{ - public sealed class HeroEthic : Ethic - { - public HeroEthic() - { - m_Definition = new EthicDefinition( - 0x482, - "Hero", "(Hero)", - "I will defend the virtues", - new Power[] - { - new HolySense(), - new HolyItem(), - new SummonFamiliar(), - new HolyBlade(), - new Bless(), - new HolyShield(), - new HolySteed(), - new HolyWord() - }); - } - - public override bool IsEligible(Mobile mob) - { - if (mob.Kills >= 5) - return false; - - Faction fac = Faction.Find(mob); - - return fac is TrueBritannians || fac is CouncilOfMages; - } - } -} \ No newline at end of file +using Server.Factions; + +namespace Server.Ethics.Hero +{ + public sealed class HeroEthic : Ethic + { + public HeroEthic() + { + m_Definition = new EthicDefinition( + 0x482, + "Hero", + "(Hero)", + "I will defend the virtues", + new Power[] + { + new HolySense(), + new HolyItem(), + new SummonFamiliar(), + new HolyBlade(), + new Bless(), + new HolyShield(), + new HolySteed(), + new HolyWord() + } + ); + } + + public override bool IsEligible(Mobile mob) + { + if (mob.Kills >= 5) + return false; + + var fac = Faction.Find(mob); + + return fac is TrueBritannians || fac is CouncilOfMages; + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Hero/Mobiles/HolyFamiliar.cs b/Projects/UOContent/Engines/Ethics/Hero/Mobiles/HolyFamiliar.cs index 88e438fea..9beb71215 100644 --- a/Projects/UOContent/Engines/Ethics/Hero/Mobiles/HolyFamiliar.cs +++ b/Projects/UOContent/Engines/Ethics/Hero/Mobiles/HolyFamiliar.cs @@ -1,84 +1,84 @@ -using Server.Ethics; - -namespace Server.Mobiles -{ - public class HolyFamiliar : BaseCreature - { - [Constructible] - public HolyFamiliar() - : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) - { - Body = 100; - BaseSoundID = 0xE5; - - SetStr(96, 120); - SetDex(81, 105); - SetInt(36, 60); - - SetHits(58, 72); - SetMana(0); - - SetDamage(11, 17); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 20, 25); - SetResistance(ResistanceType.Fire, 10, 20); - SetResistance(ResistanceType.Cold, 5, 10); - SetResistance(ResistanceType.Poison, 5, 10); - SetResistance(ResistanceType.Energy, 10, 15); - - SetSkill(SkillName.MagicResist, 57.6, 75.0); - SetSkill(SkillName.Tactics, 50.1, 70.0); - SetSkill(SkillName.Wrestling, 60.1, 80.0); - - Fame = 2500; - Karma = 2500; - - VirtualArmor = 22; - - Tamable = false; - ControlSlots = 1; - } - - public HolyFamiliar(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a holy corpse"; - public override bool IsDispellable => false; - public override bool IsBondable => false; - - public override string DefaultName => "a silver wolf"; - - public override int Meat => 1; - public override int Hides => 7; - public override FoodType FavoriteFood => FoodType.Meat; - public override PackInstinct PackInstinct => PackInstinct.Canine; - - public override string ApplyNameSuffix(string suffix) - { - if (suffix.Length == 0) - suffix = Ethic.Hero.Definition.Adjunct.String; - else - suffix = $"{suffix} {Ethic.Hero.Definition.Adjunct.String}"; - - return base.ApplyNameSuffix(suffix); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Ethics; + +namespace Server.Mobiles +{ + public class HolyFamiliar : BaseCreature + { + [Constructible] + public HolyFamiliar() + : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 100; + BaseSoundID = 0xE5; + + SetStr(96, 120); + SetDex(81, 105); + SetInt(36, 60); + + SetHits(58, 72); + SetMana(0); + + SetDamage(11, 17); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 20, 25); + SetResistance(ResistanceType.Fire, 10, 20); + SetResistance(ResistanceType.Cold, 5, 10); + SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Energy, 10, 15); + + SetSkill(SkillName.MagicResist, 57.6, 75.0); + SetSkill(SkillName.Tactics, 50.1, 70.0); + SetSkill(SkillName.Wrestling, 60.1, 80.0); + + Fame = 2500; + Karma = 2500; + + VirtualArmor = 22; + + Tamable = false; + ControlSlots = 1; + } + + public HolyFamiliar(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a holy corpse"; + public override bool IsDispellable => false; + public override bool IsBondable => false; + + public override string DefaultName => "a silver wolf"; + + public override int Meat => 1; + public override int Hides => 7; + public override FoodType FavoriteFood => FoodType.Meat; + public override PackInstinct PackInstinct => PackInstinct.Canine; + + public override string ApplyNameSuffix(string suffix) + { + if (suffix.Length == 0) + suffix = Ethic.Hero.Definition.Adjunct.String; + else + suffix = $"{suffix} {Ethic.Hero.Definition.Adjunct.String}"; + + return base.ApplyNameSuffix(suffix); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Hero/Mobiles/HolySteed.cs b/Projects/UOContent/Engines/Ethics/Hero/Mobiles/HolySteed.cs index 1e3518994..30669520b 100644 --- a/Projects/UOContent/Engines/Ethics/Hero/Mobiles/HolySteed.cs +++ b/Projects/UOContent/Engines/Ethics/Hero/Mobiles/HolySteed.cs @@ -1,88 +1,88 @@ -using Server.Ethics; - -namespace Server.Mobiles -{ - public class HolySteed : BaseMount - { - [Constructible] - public HolySteed() - : base("a silver steed", 0x75, 0x3EA8, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) - { - SetStr(496, 525); - SetDex(86, 105); - SetInt(86, 125); - - SetHits(298, 315); - - SetDamage(16, 22); - - SetDamageType(ResistanceType.Physical, 40); - SetDamageType(ResistanceType.Fire, 40); - SetDamageType(ResistanceType.Energy, 20); - - SetResistance(ResistanceType.Physical, 55, 65); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 20, 30); - - SetSkill(SkillName.MagicResist, 25.1, 30.0); - SetSkill(SkillName.Tactics, 97.6, 100.0); - SetSkill(SkillName.Wrestling, 80.5, 92.5); - - Fame = 14000; - Karma = 14000; - - VirtualArmor = 60; - - Tamable = false; - ControlSlots = 1; - } - - public HolySteed(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a holy corpse"; - public override bool IsDispellable => false; - public override bool IsBondable => false; - - public override bool HasBreath => true; - public override bool CanBreath => true; - - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - - public override string ApplyNameSuffix(string suffix) - { - if (suffix.Length == 0) - suffix = Ethic.Hero.Definition.Adjunct.String; - else - suffix = $"{suffix} {Ethic.Hero.Definition.Adjunct.String}"; - - return base.ApplyNameSuffix(suffix); - } - - public override void OnDoubleClick(Mobile from) - { - if (Ethic.Find(from) != Ethic.Hero) - from.SendMessage("You may not ride this steed."); - else - base.OnDoubleClick(from); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Ethics; + +namespace Server.Mobiles +{ + public class HolySteed : BaseMount + { + [Constructible] + public HolySteed() + : base("a silver steed", 0x75, 0x3EA8, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + SetStr(496, 525); + SetDex(86, 105); + SetInt(86, 125); + + SetHits(298, 315); + + SetDamage(16, 22); + + SetDamageType(ResistanceType.Physical, 40); + SetDamageType(ResistanceType.Fire, 40); + SetDamageType(ResistanceType.Energy, 20); + + SetResistance(ResistanceType.Physical, 55, 65); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 20, 30); + + SetSkill(SkillName.MagicResist, 25.1, 30.0); + SetSkill(SkillName.Tactics, 97.6, 100.0); + SetSkill(SkillName.Wrestling, 80.5, 92.5); + + Fame = 14000; + Karma = 14000; + + VirtualArmor = 60; + + Tamable = false; + ControlSlots = 1; + } + + public HolySteed(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a holy corpse"; + public override bool IsDispellable => false; + public override bool IsBondable => false; + + public override bool HasBreath => true; + public override bool CanBreath => true; + + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + + public override string ApplyNameSuffix(string suffix) + { + if (suffix.Length == 0) + suffix = Ethic.Hero.Definition.Adjunct.String; + else + suffix = $"{suffix} {Ethic.Hero.Definition.Adjunct.String}"; + + return base.ApplyNameSuffix(suffix); + } + + public override void OnDoubleClick(Mobile from) + { + if (Ethic.Find(from) != Ethic.Hero) + from.SendMessage("You may not ride this steed."); + else + base.OnDoubleClick(from); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Hero/Powers/Bless.cs b/Projects/UOContent/Engines/Ethics/Hero/Powers/Bless.cs index 73a1c0b66..5d59ac64c 100644 --- a/Projects/UOContent/Engines/Ethics/Hero/Powers/Bless.cs +++ b/Projects/UOContent/Engines/Ethics/Hero/Powers/Bless.cs @@ -1,73 +1,74 @@ -using System; -using Server.Network; -using Server.Spells; -using Server.Targeting; - -namespace Server.Ethics.Hero -{ - public sealed class Bless : Power - { - public Bless() => - m_Definition = new PowerDefinition( - 15, - "Bless", - "Erstok Ontawl", - ""); - - public override void BeginInvoke(Player from) - { - from.Mobile.BeginTarget(12, true, TargetFlags.None, Power_OnTarget, from); - from.Mobile.SendMessage("Where do you wish to bless?"); - } - - private void Power_OnTarget(Mobile fromMobile, object obj, Player from) - { - if (!(obj is IPoint3D p)) - return; - - if (!CheckInvoke(from)) - return; - - bool powerFunctioned = false; - - SpellHelper.GetSurfaceTop(ref p); - - foreach (Mobile mob in from.Mobile.GetMobilesInRange(6)) - { - if (mob != from.Mobile && SpellHelper.ValidIndirectTarget(from.Mobile, mob)) - continue; - - if (mob.GetStatMod("Holy Bless") != null) - continue; - - if (!from.Mobile.CanBeBeneficial(mob, false)) - continue; - - from.Mobile.DoBeneficial(mob); - - mob.AddStatMod(new StatMod(StatType.All, "Holy Bless", 10, TimeSpan.FromMinutes(30.0))); - - mob.FixedParticles(0x373A, 10, 15, 5018, EffectLayer.Waist); - mob.PlaySound(0x1EA); - - powerFunctioned = true; - } - - if (powerFunctioned) - { - SpellHelper.Turn(from.Mobile, p); - - Effects.PlaySound(p, from.Mobile.Map, 0x299); - - from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You consecrate the area."); - - FinishInvoke(from); - } - else - { - from.Mobile.FixedEffect(0x3735, 6, 30); - from.Mobile.PlaySound(0x5C); - } - } - } -} \ No newline at end of file +using System; +using Server.Network; +using Server.Spells; +using Server.Targeting; + +namespace Server.Ethics.Hero +{ + public sealed class Bless : Power + { + public Bless() => + m_Definition = new PowerDefinition( + 15, + "Bless", + "Erstok Ontawl", + "" + ); + + public override void BeginInvoke(Player from) + { + from.Mobile.BeginTarget(12, true, TargetFlags.None, Power_OnTarget, from); + from.Mobile.SendMessage("Where do you wish to bless?"); + } + + private void Power_OnTarget(Mobile fromMobile, object obj, Player from) + { + if (!(obj is IPoint3D p)) + return; + + if (!CheckInvoke(from)) + return; + + var powerFunctioned = false; + + SpellHelper.GetSurfaceTop(ref p); + + foreach (var mob in from.Mobile.GetMobilesInRange(6)) + { + if (mob != from.Mobile && SpellHelper.ValidIndirectTarget(from.Mobile, mob)) + continue; + + if (mob.GetStatMod("Holy Bless") != null) + continue; + + if (!from.Mobile.CanBeBeneficial(mob, false)) + continue; + + from.Mobile.DoBeneficial(mob); + + mob.AddStatMod(new StatMod(StatType.All, "Holy Bless", 10, TimeSpan.FromMinutes(30.0))); + + mob.FixedParticles(0x373A, 10, 15, 5018, EffectLayer.Waist); + mob.PlaySound(0x1EA); + + powerFunctioned = true; + } + + if (powerFunctioned) + { + SpellHelper.Turn(from.Mobile, p); + + Effects.PlaySound(p, from.Mobile.Map, 0x299); + + from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You consecrate the area."); + + FinishInvoke(from); + } + else + { + from.Mobile.FixedEffect(0x3735, 6, 30); + from.Mobile.PlaySound(0x5C); + } + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Hero/Powers/HolyBlade.cs b/Projects/UOContent/Engines/Ethics/Hero/Powers/HolyBlade.cs index 4035c3e36..72820862e 100644 --- a/Projects/UOContent/Engines/Ethics/Hero/Powers/HolyBlade.cs +++ b/Projects/UOContent/Engines/Ethics/Hero/Powers/HolyBlade.cs @@ -1,16 +1,17 @@ -namespace Server.Ethics.Hero -{ - public sealed class HolyBlade : Power - { - public HolyBlade() => - m_Definition = new PowerDefinition( - 10, - "Holy Blade", - "Erstok Reyam", - ""); - - public override void BeginInvoke(Player from) - { - } - } -} \ No newline at end of file +namespace Server.Ethics.Hero +{ + public sealed class HolyBlade : Power + { + public HolyBlade() => + m_Definition = new PowerDefinition( + 10, + "Holy Blade", + "Erstok Reyam", + "" + ); + + public override void BeginInvoke(Player from) + { + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Hero/Powers/HolyItem.cs b/Projects/UOContent/Engines/Ethics/Hero/Powers/HolyItem.cs index daa340842..b4e2a3f7f 100644 --- a/Projects/UOContent/Engines/Ethics/Hero/Powers/HolyItem.cs +++ b/Projects/UOContent/Engines/Ethics/Hero/Powers/HolyItem.cs @@ -1,65 +1,70 @@ -using Server.Items; -using Server.Network; -using Server.Targeting; - -namespace Server.Ethics.Hero -{ - public sealed class HolyItem : Power - { - public HolyItem() => - m_Definition = new PowerDefinition( - 5, - "Holy Item", - "Vidda K'balc", - ""); - - public override void BeginInvoke(Player from) - { - from.Mobile.BeginTarget(12, false, TargetFlags.None, Power_OnTarget, from); - from.Mobile.SendMessage("Which item do you wish to imbue?"); - } - - private void Power_OnTarget(Mobile fromMobile, object obj, Player from) - { - if (!(obj is Item item)) - { - from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You may not imbue that."); - return; - } - - if (item.Parent != from.Mobile) - { - from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, - "You may only imbue items you are wearing."); - return; - } - - if ((item.SavedFlags & 0x300) != 0) - { - from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "That has already beem imbued."); - return; - } - - bool canImbue = (item is Spellbook || item is BaseClothing || item is BaseArmor || item is BaseWeapon) && - item.Name == null; - - if (canImbue) - { - if (!CheckInvoke(from)) - return; - - item.Hue = Ethic.Hero.Definition.PrimaryHue; - item.SavedFlags |= 0x100; - - from.Mobile.FixedEffect(0x375A, 10, 20); - from.Mobile.PlaySound(0x209); - - FinishInvoke(from); - } - else - { - from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You may not imbue that."); - } - } - } -} \ No newline at end of file +using Server.Items; +using Server.Network; +using Server.Targeting; + +namespace Server.Ethics.Hero +{ + public sealed class HolyItem : Power + { + public HolyItem() => + m_Definition = new PowerDefinition( + 5, + "Holy Item", + "Vidda K'balc", + "" + ); + + public override void BeginInvoke(Player from) + { + from.Mobile.BeginTarget(12, false, TargetFlags.None, Power_OnTarget, from); + from.Mobile.SendMessage("Which item do you wish to imbue?"); + } + + private void Power_OnTarget(Mobile fromMobile, object obj, Player from) + { + if (!(obj is Item item)) + { + from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You may not imbue that."); + return; + } + + if (item.Parent != from.Mobile) + { + from.Mobile.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + false, + "You may only imbue items you are wearing." + ); + return; + } + + if ((item.SavedFlags & 0x300) != 0) + { + from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "That has already beem imbued."); + return; + } + + var canImbue = (item is Spellbook || item is BaseClothing || item is BaseArmor || item is BaseWeapon) && + item.Name == null; + + if (canImbue) + { + if (!CheckInvoke(from)) + return; + + item.Hue = Ethic.Hero.Definition.PrimaryHue; + item.SavedFlags |= 0x100; + + from.Mobile.FixedEffect(0x375A, 10, 20); + from.Mobile.PlaySound(0x209); + + FinishInvoke(from); + } + else + { + from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You may not imbue that."); + } + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Hero/Powers/HolySense.cs b/Projects/UOContent/Engines/Ethics/Hero/Powers/HolySense.cs index bb7ef8999..b0782ed15 100644 --- a/Projects/UOContent/Engines/Ethics/Hero/Powers/HolySense.cs +++ b/Projects/UOContent/Engines/Ethics/Hero/Powers/HolySense.cs @@ -1,91 +1,92 @@ -using System; -using System.Text; -using Server.Network; - -namespace Server.Ethics.Hero -{ - public sealed class HolySense : Power - { - public HolySense() => - m_Definition = new PowerDefinition( - 0, - "Holy Sense", - "Drewrok Erstok", - ""); - - public override void BeginInvoke(Player from) - { - Ethic opposition = Ethic.Evil; - - int enemyCount = 0; - - int maxRange = 18 + from.Power; - - Player primary = null; - - foreach (Player pl in opposition.Players) - { - Mobile mob = pl.Mobile; - - if (mob == null || mob.Map != from.Mobile.Map || !mob.Alive) - continue; - - if (!mob.InRange(from.Mobile, Math.Max(18, maxRange - pl.Power))) - continue; - - if (primary == null || pl.Power > primary.Power) - primary = pl; - - ++enemyCount; - } - - StringBuilder sb = new StringBuilder(); - - sb.Append("You sense "); - sb.Append(enemyCount == 0 ? "no" : enemyCount.ToString()); - sb.Append(enemyCount == 1 ? " enemy" : " enemies"); - - if (primary != null) - { - sb.Append(", and a strong presense"); - - switch (from.Mobile.GetDirectionTo(primary.Mobile)) - { - case Direction.West: - sb.Append(" to the west."); - break; - case Direction.East: - sb.Append(" to the east."); - break; - case Direction.North: - sb.Append(" to the north."); - break; - case Direction.South: - sb.Append(" to the south."); - break; - - case Direction.Up: - sb.Append(" to the north-west."); - break; - case Direction.Down: - sb.Append(" to the south-east."); - break; - case Direction.Left: - sb.Append(" to the south-west."); - break; - case Direction.Right: - sb.Append(" to the north-east."); - break; - } - } - else - { - sb.Append('.'); - } - - from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x59, false, sb.ToString()); - - FinishInvoke(from); - } - } -} \ No newline at end of file +using System; +using System.Text; +using Server.Network; + +namespace Server.Ethics.Hero +{ + public sealed class HolySense : Power + { + public HolySense() => + m_Definition = new PowerDefinition( + 0, + "Holy Sense", + "Drewrok Erstok", + "" + ); + + public override void BeginInvoke(Player from) + { + var opposition = Ethic.Evil; + + var enemyCount = 0; + + var maxRange = 18 + from.Power; + + Player primary = null; + + foreach (var pl in opposition.Players) + { + var mob = pl.Mobile; + + if (mob == null || mob.Map != from.Mobile.Map || !mob.Alive) + continue; + + if (!mob.InRange(from.Mobile, Math.Max(18, maxRange - pl.Power))) + continue; + + if (primary == null || pl.Power > primary.Power) + primary = pl; + + ++enemyCount; + } + + var sb = new StringBuilder(); + + sb.Append("You sense "); + sb.Append(enemyCount == 0 ? "no" : enemyCount.ToString()); + sb.Append(enemyCount == 1 ? " enemy" : " enemies"); + + if (primary != null) + { + sb.Append(", and a strong presense"); + + switch (from.Mobile.GetDirectionTo(primary.Mobile)) + { + case Direction.West: + sb.Append(" to the west."); + break; + case Direction.East: + sb.Append(" to the east."); + break; + case Direction.North: + sb.Append(" to the north."); + break; + case Direction.South: + sb.Append(" to the south."); + break; + + case Direction.Up: + sb.Append(" to the north-west."); + break; + case Direction.Down: + sb.Append(" to the south-east."); + break; + case Direction.Left: + sb.Append(" to the south-west."); + break; + case Direction.Right: + sb.Append(" to the north-east."); + break; + } + } + else + { + sb.Append('.'); + } + + from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x59, false, sb.ToString()); + + FinishInvoke(from); + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Hero/Powers/HolyShield.cs b/Projects/UOContent/Engines/Ethics/Hero/Powers/HolyShield.cs index 9b5b46a37..c313a36ce 100644 --- a/Projects/UOContent/Engines/Ethics/Hero/Powers/HolyShield.cs +++ b/Projects/UOContent/Engines/Ethics/Hero/Powers/HolyShield.cs @@ -1,31 +1,40 @@ -using Server.Network; - -namespace Server.Ethics.Hero -{ - public sealed class HolyShield : Power - { - public HolyShield() => - m_Definition = new PowerDefinition( - 20, - "Holy Shield", - "Erstok K'blac", - ""); - - public override void BeginInvoke(Player from) - { - if (from.IsShielded) - { - from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, - "You are already under the protection of a holy shield."); - return; - } - - from.BeginShield(); - - from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, - "You are now under the protection of a holy shield."); - - FinishInvoke(from); - } - } -} \ No newline at end of file +using Server.Network; + +namespace Server.Ethics.Hero +{ + public sealed class HolyShield : Power + { + public HolyShield() => + m_Definition = new PowerDefinition( + 20, + "Holy Shield", + "Erstok K'blac", + "" + ); + + public override void BeginInvoke(Player from) + { + if (from.IsShielded) + { + from.Mobile.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + false, + "You are already under the protection of a holy shield." + ); + return; + } + + from.BeginShield(); + + from.Mobile.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + false, + "You are now under the protection of a holy shield." + ); + + FinishInvoke(from); + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Hero/Powers/HolySteed.cs b/Projects/UOContent/Engines/Ethics/Hero/Powers/HolySteed.cs index 05d1bdfab..386f71a9a 100644 --- a/Projects/UOContent/Engines/Ethics/Hero/Powers/HolySteed.cs +++ b/Projects/UOContent/Engines/Ethics/Hero/Powers/HolySteed.cs @@ -1,43 +1,44 @@ -using System; -using Server.Mobiles; -using Server.Network; - -namespace Server.Ethics.Hero -{ - public sealed class HolySteed : Power - { - public HolySteed() => - m_Definition = new PowerDefinition( - 30, - "Holy Steed", - "Trubechs Yeliab", - ""); - - public override void BeginInvoke(Player from) - { - if (from.Steed?.Deleted == true) - from.Steed = null; - - if (from.Steed != null) - { - from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You already have a holy steed."); - return; - } - - if (from.Mobile.Followers + 1 > from.Mobile.FollowersMax) - { - from.Mobile.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. - return; - } - - Mobiles.HolySteed steed = new Mobiles.HolySteed(); - - if (BaseCreature.Summon(steed, from.Mobile, from.Mobile.Location, 0x217, TimeSpan.FromHours(1.0))) - { - from.Steed = steed; - - FinishInvoke(from); - } - } - } -} +using System; +using Server.Mobiles; +using Server.Network; + +namespace Server.Ethics.Hero +{ + public sealed class HolySteed : Power + { + public HolySteed() => + m_Definition = new PowerDefinition( + 30, + "Holy Steed", + "Trubechs Yeliab", + "" + ); + + public override void BeginInvoke(Player from) + { + if (from.Steed?.Deleted == true) + from.Steed = null; + + if (from.Steed != null) + { + from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You already have a holy steed."); + return; + } + + if (from.Mobile.Followers + 1 > from.Mobile.FollowersMax) + { + from.Mobile.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. + return; + } + + var steed = new Mobiles.HolySteed(); + + if (BaseCreature.Summon(steed, from.Mobile, from.Mobile.Location, 0x217, TimeSpan.FromHours(1.0))) + { + from.Steed = steed; + + FinishInvoke(from); + } + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Hero/Powers/HolyWord.cs b/Projects/UOContent/Engines/Ethics/Hero/Powers/HolyWord.cs index 03e658cae..0cace0ef4 100644 --- a/Projects/UOContent/Engines/Ethics/Hero/Powers/HolyWord.cs +++ b/Projects/UOContent/Engines/Ethics/Hero/Powers/HolyWord.cs @@ -1,16 +1,17 @@ -namespace Server.Ethics.Hero -{ - public sealed class HolyWord : Power - { - public HolyWord() => - m_Definition = new PowerDefinition( - 100, - "Holy Word", - "Erstok Oostrac", - ""); - - public override void BeginInvoke(Player from) - { - } - } -} \ No newline at end of file +namespace Server.Ethics.Hero +{ + public sealed class HolyWord : Power + { + public HolyWord() => + m_Definition = new PowerDefinition( + 100, + "Holy Word", + "Erstok Oostrac", + "" + ); + + public override void BeginInvoke(Player from) + { + } + } +} diff --git a/Projects/UOContent/Engines/Ethics/Hero/Powers/SummonFamiliar.cs b/Projects/UOContent/Engines/Ethics/Hero/Powers/SummonFamiliar.cs index c68b421a8..f52741c00 100644 --- a/Projects/UOContent/Engines/Ethics/Hero/Powers/SummonFamiliar.cs +++ b/Projects/UOContent/Engines/Ethics/Hero/Powers/SummonFamiliar.cs @@ -1,43 +1,44 @@ -using System; -using Server.Mobiles; -using Server.Network; - -namespace Server.Ethics.Hero -{ - public sealed class SummonFamiliar : Power - { - public SummonFamiliar() => - m_Definition = new PowerDefinition( - 5, - "Summon Familiar", - "Trubechs Vingir", - ""); - - public override void BeginInvoke(Player from) - { - if (from.Familiar?.Deleted == true) - from.Familiar = null; - - if (from.Familiar != null) - { - from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You already have a holy familiar."); - return; - } - - if (from.Mobile.Followers + 1 > from.Mobile.FollowersMax) - { - from.Mobile.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. - return; - } - - HolyFamiliar familiar = new HolyFamiliar(); - - if (BaseCreature.Summon(familiar, from.Mobile, from.Mobile.Location, 0x217, TimeSpan.FromHours(1.0))) - { - from.Familiar = familiar; - - FinishInvoke(from); - } - } - } -} +using System; +using Server.Mobiles; +using Server.Network; + +namespace Server.Ethics.Hero +{ + public sealed class SummonFamiliar : Power + { + public SummonFamiliar() => + m_Definition = new PowerDefinition( + 5, + "Summon Familiar", + "Trubechs Vingir", + "" + ); + + public override void BeginInvoke(Player from) + { + if (from.Familiar?.Deleted == true) + from.Familiar = null; + + if (from.Familiar != null) + { + from.Mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You already have a holy familiar."); + return; + } + + if (from.Mobile.Followers + 1 > from.Mobile.FollowersMax) + { + from.Mobile.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. + return; + } + + var familiar = new HolyFamiliar(); + + if (BaseCreature.Summon(familiar, from.Mobile, from.Mobile.Location, 0x217, TimeSpan.FromHours(1.0))) + { + from.Familiar = familiar; + + FinishInvoke(from); + } + } + } +} diff --git a/Projects/UOContent/Engines/Events/BroadcastEvent.cs b/Projects/UOContent/Engines/Events/BroadcastEvent.cs index fd703e648..aa0b9467c 100644 --- a/Projects/UOContent/Engines/Events/BroadcastEvent.cs +++ b/Projects/UOContent/Engines/Events/BroadcastEvent.cs @@ -1,32 +1,30 @@ -namespace Server.Engines.Events -{ - public class BroadcastEvent : IEvent - { - private readonly int _hue = 0; - private readonly string _text = ""; - public static void Initialize() - { - /* - EventScheduler.Instance.ScheduleEvent(new BroadcastEvent(22, "Test Message Please Ignore 2min"), 0, 0, TimeSpan.FromMinutes(2.0)); - EventScheduler.Instance.ScheduleEvent(new BroadcastEvent(33, "Test Message Please Ignore 3min"), 0, 0, TimeSpan.FromMinutes(3.0)); - EventScheduler.Instance.ScheduleEvent(new BroadcastEvent(44, "Test Message Please Ignore 4min"), 0, 0, TimeSpan.FromMinutes(4.0)); - */ - } - - public BroadcastEvent(int hue, string text) - { - _hue = hue; - _text = text; - } - - public override string ToString() - { - return $"Broadcast: {_text}"; - } - - public void OnEventScheduled() - { - World.Broadcast(_hue, true, _text); - } - } -} +namespace Server.Engines.Events +{ + public class BroadcastEvent : IEvent + { + private readonly int _hue; + private readonly string _text = ""; + + public BroadcastEvent(int hue, string text) + { + _hue = hue; + _text = text; + } + + public void OnEventScheduled() + { + World.Broadcast(_hue, true, _text); + } + + public static void Initialize() + { + /* + EventScheduler.Instance.ScheduleEvent(new BroadcastEvent(22, "Test Message Please Ignore 2min"), 0, 0, TimeSpan.FromMinutes(2.0)); + EventScheduler.Instance.ScheduleEvent(new BroadcastEvent(33, "Test Message Please Ignore 3min"), 0, 0, TimeSpan.FromMinutes(3.0)); + EventScheduler.Instance.ScheduleEvent(new BroadcastEvent(44, "Test Message Please Ignore 4min"), 0, 0, TimeSpan.FromMinutes(4.0)); + */ + } + + public override string ToString() => $"Broadcast: {_text}"; + } +} diff --git a/Projects/UOContent/Engines/Events/EventScheduler.cs b/Projects/UOContent/Engines/Events/EventScheduler.cs index 312468422..8c6e4551f 100644 --- a/Projects/UOContent/Engines/Events/EventScheduler.cs +++ b/Projects/UOContent/Engines/Events/EventScheduler.cs @@ -1,88 +1,89 @@ -using System; -using System.Collections.Generic; - -namespace Server.Engines.Events -{ - public interface IEvent - { - void OnEventScheduled(); - } - - public class EventScheduleEntry - { - public DateTime NextOccurrence { get; private set; } - public TimeSpan Interval { get; private set; } - private TimeSpan _offset; - private readonly IEvent _event; - - public EventScheduleEntry(IEvent e, DateTime firstSpawn, TimeSpan interval, TimeSpan offset) - { - _offset = offset; - _event = e; - Interval = interval; - NextOccurrence = firstSpawn; - } - - public void Occur() - { - NextOccurrence += Interval; - - _event?.OnEventScheduled(); - } - - public override string ToString() - { - return _event?.ToString(); - } - } - public class EventScheduler : Timer - { - private static EventScheduler _instance; - private readonly List _schedule = new List(); - - public static EventScheduler Instance => _instance ??= new EventScheduler(); - public static List AvailableEvents { get; } = new List(); - - private EventScheduler() : base(TimeSpan.Zero, TimeSpan.FromSeconds(1.0)) - { - } - - public static void Initialize() - { - Instance.Start(); - } - - public void ScheduleEvent(IEvent e, int hour, int min) - { - ScheduleEvent(e, hour, min, TimeSpan.FromDays(1.0)); - } - - public void ScheduleEvent(IEvent e, int hour, int min, TimeSpan interval) - { - DateTime now = DateTime.UtcNow; - DateTime firstRun = new DateTime(now.Year, now.Month, now.Day, hour, min, 0); - - while (now > firstRun) - firstRun += interval; - - ScheduleEvent(new EventScheduleEntry(e, firstRun, interval, TimeSpan.FromHours(hour) + TimeSpan.FromMinutes(min))); - } - - public void ScheduleEvent(EventScheduleEntry e) - { - _schedule.Add(e); - } - - public void RemoveEvent(EventScheduleEntry entry) - { - _schedule.Remove(entry); - } - - protected override void OnTick() - { - foreach (EventScheduleEntry entry in _schedule) - if (entry.NextOccurrence <= DateTime.UtcNow) - entry.Occur(); - } - } -} +using System; +using System.Collections.Generic; + +namespace Server.Engines.Events +{ + public interface IEvent + { + void OnEventScheduled(); + } + + public class EventScheduleEntry + { + private readonly IEvent _event; + private TimeSpan _offset; + + public EventScheduleEntry(IEvent e, DateTime firstSpawn, TimeSpan interval, TimeSpan offset) + { + _offset = offset; + _event = e; + Interval = interval; + NextOccurrence = firstSpawn; + } + + public DateTime NextOccurrence { get; private set; } + public TimeSpan Interval { get; } + + public void Occur() + { + NextOccurrence += Interval; + + _event?.OnEventScheduled(); + } + + public override string ToString() => _event?.ToString(); + } + + public class EventScheduler : Timer + { + private static EventScheduler _instance; + private readonly List _schedule = new List(); + + private EventScheduler() : base(TimeSpan.Zero, TimeSpan.FromSeconds(1.0)) + { + } + + public static EventScheduler Instance => _instance ??= new EventScheduler(); + public static List AvailableEvents { get; } = new List(); + + public static void Initialize() + { + Instance.Start(); + } + + public void ScheduleEvent(IEvent e, int hour, int min) + { + ScheduleEvent(e, hour, min, TimeSpan.FromDays(1.0)); + } + + public void ScheduleEvent(IEvent e, int hour, int min, TimeSpan interval) + { + var now = DateTime.UtcNow; + var firstRun = new DateTime(now.Year, now.Month, now.Day, hour, min, 0); + + while (now > firstRun) + firstRun += interval; + + ScheduleEvent( + new EventScheduleEntry(e, firstRun, interval, TimeSpan.FromHours(hour) + TimeSpan.FromMinutes(min)) + ); + } + + public void ScheduleEvent(EventScheduleEntry e) + { + _schedule.Add(e); + } + + public void RemoveEvent(EventScheduleEntry entry) + { + _schedule.Remove(entry); + } + + protected override void OnTick() + { + foreach (var entry in _schedule) + if (entry.NextOccurrence <= DateTime.UtcNow) + entry.Occur(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Core/Election.cs b/Projects/UOContent/Engines/Factions/Core/Election.cs index c4b5ce12c..c61d4dd1d 100644 --- a/Projects/UOContent/Engines/Factions/Core/Election.cs +++ b/Projects/UOContent/Engines/Factions/Core/Election.cs @@ -1,523 +1,525 @@ -using System; -using System.Collections.Generic; -using System.Net; -using Server.Mobiles; - -namespace Server.Factions -{ - public class Election - { - public const int MaxCandidates = 10; - public const int CandidateRank = 5; - public static readonly TimeSpan PendingPeriod = TimeSpan.FromDays(5.0); - public static readonly TimeSpan CampaignPeriod = TimeSpan.FromDays(1.0); - public static readonly TimeSpan VotingPeriod = TimeSpan.FromDays(3.0); - - private Timer m_Timer; - - public Election(Faction faction) - { - Faction = faction; - Candidates = new List(); - - StartTimer(); - } - - public Election(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 0: - { - Faction = Faction.ReadReference(reader); - - LastStateTime = reader.ReadDateTime(); - CurrentState = (ElectionState)reader.ReadEncodedInt(); - - Candidates = new List(); - - int count = reader.ReadEncodedInt(); - - for (int i = 0; i < count; ++i) - { - Candidate cd = new Candidate(reader); - - if (cd.Mobile != null) - Candidates.Add(cd); - } - - break; - } - } - - StartTimer(); - } - - public Faction Faction { get; } - - public List Candidates { get; } - - public ElectionState State - { - get => CurrentState; - set - { - CurrentState = value; - LastStateTime = DateTime.UtcNow; - } - } - - public DateTime LastStateTime { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public ElectionState CurrentState { get; private set; } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public TimeSpan NextStateTime - { - get - { - var period = CurrentState switch - { - ElectionState.Pending => PendingPeriod, - ElectionState.Election => VotingPeriod, - ElectionState.Campaign => CampaignPeriod, - _ => PendingPeriod - }; - - TimeSpan until = LastStateTime + period - DateTime.UtcNow; - - if (until < TimeSpan.Zero) - until = TimeSpan.Zero; - - return until; - } - set - { - var period = CurrentState switch - { - ElectionState.Pending => PendingPeriod, - ElectionState.Election => VotingPeriod, - ElectionState.Campaign => CampaignPeriod, - _ => PendingPeriod - }; - - LastStateTime = DateTime.UtcNow - period + value; - } - } - - public void StartTimer() - { - m_Timer = Timer.DelayCall(TimeSpan.FromMinutes(1.0), TimeSpan.FromMinutes(1.0), Slice); - } - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - Faction.WriteReference(writer, Faction); - - writer.Write(LastStateTime); - writer.WriteEncodedInt((int)CurrentState); - - writer.WriteEncodedInt(Candidates.Count); - - for (int i = 0; i < Candidates.Count; ++i) - Candidates[i].Serialize(writer); - } - - public void AddCandidate(Mobile mob) - { - if (IsCandidate(mob)) - return; - - Candidates.Add(new Candidate(mob)); - mob.SendLocalizedMessage(1010117); // You are now running for office. - } - - public void RemoveVoter(Mobile mob) - { - if (CurrentState == ElectionState.Election) - for (int i = 0; i < Candidates.Count; ++i) - { - List voters = Candidates[i].Voters; - - for (int j = 0; j < voters.Count; ++j) - { - Voter voter = voters[j]; - - if (voter.From == mob) - voters.RemoveAt(j--); - } - } - } - - public void RemoveCandidate(Mobile mob) - { - Candidate cd = FindCandidate(mob); - - if (cd == null) - return; - - Candidates.Remove(cd); - mob.SendLocalizedMessage(1038031); - - if (CurrentState == ElectionState.Election) - { - if (Candidates.Count == 1) - { - Faction.Broadcast( - 1038031); // There are no longer any valid candidates in the Faction Commander election. - - Candidate winner = Candidates[0]; - - Mobile winMob = winner.Mobile; - PlayerState pl = PlayerState.Find(winMob); - - if (pl == null || pl.Faction != Faction || winMob == Faction.Commander) - { - Faction.Broadcast(1038026); // Faction leadership has not changed. - } - else - { - Faction.Broadcast(1038028); // The faction has a new commander. - Faction.Commander = winMob; - } - - Candidates.Clear(); - State = ElectionState.Pending; - } - else if (Candidates.Count == 0) // well, I guess this'll never happen - { - Faction.Broadcast( - 1038031); // There are no longer any valid candidates in the Faction Commander election. - - Candidates.Clear(); - State = ElectionState.Pending; - } - } - } - - public bool IsCandidate(Mobile mob) => FindCandidate(mob) != null; - - public bool CanVote(Mobile mob) => CurrentState == ElectionState.Election && !HasVoted(mob); - - public bool HasVoted(Mobile mob) => FindVoter(mob) != null; - - public Candidate FindCandidate(Mobile mob) - { - for (int i = 0; i < Candidates.Count; ++i) - if (Candidates[i].Mobile == mob) - return Candidates[i]; - - return null; - } - - public Candidate FindVoter(Mobile mob) - { - for (int i = 0; i < Candidates.Count; ++i) - { - List voters = Candidates[i].Voters; - - for (int j = 0; j < voters.Count; ++j) - { - Voter voter = voters[j]; - - if (voter.From == mob) - return Candidates[i]; - } - } - - return null; - } - - public bool CanBeCandidate(Mobile mob) - { - if (IsCandidate(mob)) - return false; - - if (Candidates.Count >= MaxCandidates) - return false; - - if (CurrentState != ElectionState.Campaign) - return false; // sanity.. - - PlayerState pl = PlayerState.Find(mob); - - return pl != null && pl.Faction == Faction && pl.Rank.Rank >= CandidateRank; - } - - public void Slice() - { - if (Faction.Election != this) - { - m_Timer?.Stop(); - - m_Timer = null; - - return; - } - - switch (CurrentState) - { - case ElectionState.Pending: - { - if (LastStateTime + PendingPeriod > DateTime.UtcNow) - break; - - Faction.Broadcast(1038023); // Campaigning for the Faction Commander election has begun. - - Candidates.Clear(); - State = ElectionState.Campaign; - - break; - } - case ElectionState.Campaign: - { - if (LastStateTime + CampaignPeriod > DateTime.UtcNow) - break; - - if (Candidates.Count == 0) - { - Faction.Broadcast(1038025); // Nobody ran for office. - State = ElectionState.Pending; - } - else if (Candidates.Count == 1) - { - Faction.Broadcast(1038029); // Only one member ran for office. - - Candidate winner = Candidates[0]; - - Mobile mob = winner.Mobile; - PlayerState pl = PlayerState.Find(mob); - - if (pl == null || pl.Faction != Faction || mob == Faction.Commander) - { - Faction.Broadcast(1038026); // Faction leadership has not changed. - } - else - { - Faction.Broadcast(1038028); // The faction has a new commander. - Faction.Commander = mob; - } - - Candidates.Clear(); - State = ElectionState.Pending; - } - else - { - Faction.Broadcast(1038030); - State = ElectionState.Election; - } - - break; - } - case ElectionState.Election: - { - if (LastStateTime + VotingPeriod > DateTime.UtcNow) - break; - - Faction.Broadcast(1038024); // The results for the Faction Commander election are in - - Candidate winner = null; - - for (int i = 0; i < Candidates.Count; ++i) - { - Candidate cd = Candidates[i]; - - PlayerState pl = PlayerState.Find(cd.Mobile); - - if (pl == null || pl.Faction != Faction) - continue; - - // cd.CleanMuleVotes(); - - if (winner == null || cd.Votes > winner.Votes) - winner = cd; - } - - if (winner == null) - { - Faction.Broadcast(1038026); // Faction leadership has not changed. - } - else if (winner.Mobile == Faction.Commander) - { - Faction.Broadcast(1038027); // The incumbent won the election. - } - else - { - Faction.Broadcast(1038028); // The faction has a new commander. - Faction.Commander = winner.Mobile; - } - - Candidates.Clear(); - State = ElectionState.Pending; - - break; - } - } - } - } - - public class Voter - { - public Voter(Mobile from, Mobile candidate) - { - From = from; - Candidate = candidate; - - if (From.NetState != null) - Address = From.NetState.Address; - else - Address = IPAddress.None; - - Time = DateTime.UtcNow; - } - - public Voter(IGenericReader reader, Mobile candidate) - { - Candidate = candidate; - - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 0: - { - From = reader.ReadMobile(); - Address = Utility.Intern(reader.ReadIPAddress()); - Time = reader.ReadDateTime(); - - break; - } - } - } - - public Mobile From { get; } - - public Mobile Candidate { get; } - - public IPAddress Address { get; } - - public DateTime Time { get; } - - public object[] AcquireFields() - { - TimeSpan gameTime = TimeSpan.Zero; - - if (From is PlayerMobile mobile) - gameTime = mobile.GameTime; - - int kp = 0; - - PlayerState pl = PlayerState.Find(From); - - if (pl != null) - kp = pl.KillPoints; - - int sk = From.Skills.Total; - - int factorSkills = 50 + sk * 100 / 10000; - int factorKillPts = 100 + kp * 2; - int factorGameTime = 50 + (int)(gameTime.Ticks * 100 / TimeSpan.TicksPerDay); - - int totalFactor = Math.Clamp(factorSkills * factorKillPts * Math.Max(factorGameTime, 100) / 10000, 0, 100); - - return new object[] { From, Address, Time, totalFactor }; - } - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); - - writer.Write(From); - writer.Write(Address); - writer.Write(Time); - } - } - - public class Candidate - { - public Candidate(Mobile mob) - { - Mobile = mob; - Voters = new List(); - } - - public Candidate(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 1: - { - Mobile = reader.ReadMobile(); - - int count = reader.ReadEncodedInt(); - Voters = new List(count); - - for (int i = 0; i < count; ++i) - { - Voter voter = new Voter(reader, Mobile); - - if (voter.From != null) - Voters.Add(voter); - } - - break; - } - case 0: - { - Mobile = reader.ReadMobile(); - - List mobs = reader.ReadStrongMobileList(); - Voters = new List(mobs.Count); - - for (int i = 0; i < mobs.Count; ++i) - Voters.Add(new Voter(mobs[i], Mobile)); - - break; - } - } - } - - public Mobile Mobile { get; } - - public List Voters { get; } - - public int Votes => Voters.Count; - - public void CleanMuleVotes() - { - for (int i = 0; i < Voters.Count; ++i) - { - Voter voter = Voters[i]; - - if ((int)voter.AcquireFields()[3] < 90) - Voters.RemoveAt(i--); - } - } - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(1); // version - - writer.Write(Mobile); - - writer.WriteEncodedInt(Voters.Count); - - for (int i = 0; i < Voters.Count; ++i) - Voters[i].Serialize(writer); - } - } - - public enum ElectionState - { - Pending, - Campaign, - Election - } -} +using System; +using System.Collections.Generic; +using System.Net; +using Server.Mobiles; + +namespace Server.Factions +{ + public class Election + { + public const int MaxCandidates = 10; + public const int CandidateRank = 5; + public static readonly TimeSpan PendingPeriod = TimeSpan.FromDays(5.0); + public static readonly TimeSpan CampaignPeriod = TimeSpan.FromDays(1.0); + public static readonly TimeSpan VotingPeriod = TimeSpan.FromDays(3.0); + + private Timer m_Timer; + + public Election(Faction faction) + { + Faction = faction; + Candidates = new List(); + + StartTimer(); + } + + public Election(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 0: + { + Faction = Faction.ReadReference(reader); + + LastStateTime = reader.ReadDateTime(); + CurrentState = (ElectionState)reader.ReadEncodedInt(); + + Candidates = new List(); + + var count = reader.ReadEncodedInt(); + + for (var i = 0; i < count; ++i) + { + var cd = new Candidate(reader); + + if (cd.Mobile != null) + Candidates.Add(cd); + } + + break; + } + } + + StartTimer(); + } + + public Faction Faction { get; } + + public List Candidates { get; } + + public ElectionState State + { + get => CurrentState; + set + { + CurrentState = value; + LastStateTime = DateTime.UtcNow; + } + } + + public DateTime LastStateTime { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public ElectionState CurrentState { get; private set; } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public TimeSpan NextStateTime + { + get + { + var period = CurrentState switch + { + ElectionState.Pending => PendingPeriod, + ElectionState.Election => VotingPeriod, + ElectionState.Campaign => CampaignPeriod, + _ => PendingPeriod + }; + + var until = LastStateTime + period - DateTime.UtcNow; + + if (until < TimeSpan.Zero) + until = TimeSpan.Zero; + + return until; + } + set + { + var period = CurrentState switch + { + ElectionState.Pending => PendingPeriod, + ElectionState.Election => VotingPeriod, + ElectionState.Campaign => CampaignPeriod, + _ => PendingPeriod + }; + + LastStateTime = DateTime.UtcNow - period + value; + } + } + + public void StartTimer() + { + m_Timer = Timer.DelayCall(TimeSpan.FromMinutes(1.0), TimeSpan.FromMinutes(1.0), Slice); + } + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + Faction.WriteReference(writer, Faction); + + writer.Write(LastStateTime); + writer.WriteEncodedInt((int)CurrentState); + + writer.WriteEncodedInt(Candidates.Count); + + for (var i = 0; i < Candidates.Count; ++i) + Candidates[i].Serialize(writer); + } + + public void AddCandidate(Mobile mob) + { + if (IsCandidate(mob)) + return; + + Candidates.Add(new Candidate(mob)); + mob.SendLocalizedMessage(1010117); // You are now running for office. + } + + public void RemoveVoter(Mobile mob) + { + if (CurrentState == ElectionState.Election) + for (var i = 0; i < Candidates.Count; ++i) + { + var voters = Candidates[i].Voters; + + for (var j = 0; j < voters.Count; ++j) + { + var voter = voters[j]; + + if (voter.From == mob) + voters.RemoveAt(j--); + } + } + } + + public void RemoveCandidate(Mobile mob) + { + var cd = FindCandidate(mob); + + if (cd == null) + return; + + Candidates.Remove(cd); + mob.SendLocalizedMessage(1038031); + + if (CurrentState == ElectionState.Election) + { + if (Candidates.Count == 1) + { + Faction.Broadcast( + 1038031 + ); // There are no longer any valid candidates in the Faction Commander election. + + var winner = Candidates[0]; + + var winMob = winner.Mobile; + var pl = PlayerState.Find(winMob); + + if (pl == null || pl.Faction != Faction || winMob == Faction.Commander) + { + Faction.Broadcast(1038026); // Faction leadership has not changed. + } + else + { + Faction.Broadcast(1038028); // The faction has a new commander. + Faction.Commander = winMob; + } + + Candidates.Clear(); + State = ElectionState.Pending; + } + else if (Candidates.Count == 0) // well, I guess this'll never happen + { + Faction.Broadcast( + 1038031 + ); // There are no longer any valid candidates in the Faction Commander election. + + Candidates.Clear(); + State = ElectionState.Pending; + } + } + } + + public bool IsCandidate(Mobile mob) => FindCandidate(mob) != null; + + public bool CanVote(Mobile mob) => CurrentState == ElectionState.Election && !HasVoted(mob); + + public bool HasVoted(Mobile mob) => FindVoter(mob) != null; + + public Candidate FindCandidate(Mobile mob) + { + for (var i = 0; i < Candidates.Count; ++i) + if (Candidates[i].Mobile == mob) + return Candidates[i]; + + return null; + } + + public Candidate FindVoter(Mobile mob) + { + for (var i = 0; i < Candidates.Count; ++i) + { + var voters = Candidates[i].Voters; + + for (var j = 0; j < voters.Count; ++j) + { + var voter = voters[j]; + + if (voter.From == mob) + return Candidates[i]; + } + } + + return null; + } + + public bool CanBeCandidate(Mobile mob) + { + if (IsCandidate(mob)) + return false; + + if (Candidates.Count >= MaxCandidates) + return false; + + if (CurrentState != ElectionState.Campaign) + return false; // sanity.. + + var pl = PlayerState.Find(mob); + + return pl != null && pl.Faction == Faction && pl.Rank.Rank >= CandidateRank; + } + + public void Slice() + { + if (Faction.Election != this) + { + m_Timer?.Stop(); + + m_Timer = null; + + return; + } + + switch (CurrentState) + { + case ElectionState.Pending: + { + if (LastStateTime + PendingPeriod > DateTime.UtcNow) + break; + + Faction.Broadcast(1038023); // Campaigning for the Faction Commander election has begun. + + Candidates.Clear(); + State = ElectionState.Campaign; + + break; + } + case ElectionState.Campaign: + { + if (LastStateTime + CampaignPeriod > DateTime.UtcNow) + break; + + if (Candidates.Count == 0) + { + Faction.Broadcast(1038025); // Nobody ran for office. + State = ElectionState.Pending; + } + else if (Candidates.Count == 1) + { + Faction.Broadcast(1038029); // Only one member ran for office. + + var winner = Candidates[0]; + + var mob = winner.Mobile; + var pl = PlayerState.Find(mob); + + if (pl == null || pl.Faction != Faction || mob == Faction.Commander) + { + Faction.Broadcast(1038026); // Faction leadership has not changed. + } + else + { + Faction.Broadcast(1038028); // The faction has a new commander. + Faction.Commander = mob; + } + + Candidates.Clear(); + State = ElectionState.Pending; + } + else + { + Faction.Broadcast(1038030); + State = ElectionState.Election; + } + + break; + } + case ElectionState.Election: + { + if (LastStateTime + VotingPeriod > DateTime.UtcNow) + break; + + Faction.Broadcast(1038024); // The results for the Faction Commander election are in + + Candidate winner = null; + + for (var i = 0; i < Candidates.Count; ++i) + { + var cd = Candidates[i]; + + var pl = PlayerState.Find(cd.Mobile); + + if (pl == null || pl.Faction != Faction) + continue; + + // cd.CleanMuleVotes(); + + if (winner == null || cd.Votes > winner.Votes) + winner = cd; + } + + if (winner == null) + { + Faction.Broadcast(1038026); // Faction leadership has not changed. + } + else if (winner.Mobile == Faction.Commander) + { + Faction.Broadcast(1038027); // The incumbent won the election. + } + else + { + Faction.Broadcast(1038028); // The faction has a new commander. + Faction.Commander = winner.Mobile; + } + + Candidates.Clear(); + State = ElectionState.Pending; + + break; + } + } + } + } + + public class Voter + { + public Voter(Mobile from, Mobile candidate) + { + From = from; + Candidate = candidate; + + if (From.NetState != null) + Address = From.NetState.Address; + else + Address = IPAddress.None; + + Time = DateTime.UtcNow; + } + + public Voter(IGenericReader reader, Mobile candidate) + { + Candidate = candidate; + + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 0: + { + From = reader.ReadMobile(); + Address = Utility.Intern(reader.ReadIPAddress()); + Time = reader.ReadDateTime(); + + break; + } + } + } + + public Mobile From { get; } + + public Mobile Candidate { get; } + + public IPAddress Address { get; } + + public DateTime Time { get; } + + public object[] AcquireFields() + { + var gameTime = TimeSpan.Zero; + + if (From is PlayerMobile mobile) + gameTime = mobile.GameTime; + + var kp = 0; + + var pl = PlayerState.Find(From); + + if (pl != null) + kp = pl.KillPoints; + + var sk = From.Skills.Total; + + var factorSkills = 50 + sk * 100 / 10000; + var factorKillPts = 100 + kp * 2; + var factorGameTime = 50 + (int)(gameTime.Ticks * 100 / TimeSpan.TicksPerDay); + + var totalFactor = Math.Clamp(factorSkills * factorKillPts * Math.Max(factorGameTime, 100) / 10000, 0, 100); + + return new object[] { From, Address, Time, totalFactor }; + } + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); + + writer.Write(From); + writer.Write(Address); + writer.Write(Time); + } + } + + public class Candidate + { + public Candidate(Mobile mob) + { + Mobile = mob; + Voters = new List(); + } + + public Candidate(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 1: + { + Mobile = reader.ReadMobile(); + + var count = reader.ReadEncodedInt(); + Voters = new List(count); + + for (var i = 0; i < count; ++i) + { + var voter = new Voter(reader, Mobile); + + if (voter.From != null) + Voters.Add(voter); + } + + break; + } + case 0: + { + Mobile = reader.ReadMobile(); + + var mobs = reader.ReadStrongMobileList(); + Voters = new List(mobs.Count); + + for (var i = 0; i < mobs.Count; ++i) + Voters.Add(new Voter(mobs[i], Mobile)); + + break; + } + } + } + + public Mobile Mobile { get; } + + public List Voters { get; } + + public int Votes => Voters.Count; + + public void CleanMuleVotes() + { + for (var i = 0; i < Voters.Count; ++i) + { + var voter = Voters[i]; + + if ((int)voter.AcquireFields()[3] < 90) + Voters.RemoveAt(i--); + } + } + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(1); // version + + writer.Write(Mobile); + + writer.WriteEncodedInt(Voters.Count); + + for (var i = 0; i < Voters.Count; ++i) + Voters[i].Serialize(writer); + } + } + + public enum ElectionState + { + Pending, + Campaign, + Election + } +} diff --git a/Projects/UOContent/Engines/Factions/Core/Faction.cs b/Projects/UOContent/Engines/Factions/Core/Faction.cs index b6fead34c..9f94b1411 100644 --- a/Projects/UOContent/Engines/Factions/Core/Faction.cs +++ b/Projects/UOContent/Engines/Factions/Core/Faction.cs @@ -1,1327 +1,1349 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Server.Accounting; -using Server.Commands.Generic; -using Server.Engines.ConPVP; -using Server.Ethics; -using Server.Guilds; -using Server.Items; -using Server.Mobiles; -using Server.Prompts; -using Server.Targeting; - -namespace Server.Factions -{ - [CustomEnum(new[] { "Minax", "Council of Mages", "True Britannians", "Shadowlords" })] - public abstract class Faction : IComparable - { - public const int StabilityFactor = 300; // 300% greater (3 times) than smallest faction - public const int StabilityActivation = 200; // Stability code goes into effect when largest faction has > 200 people - - public static readonly TimeSpan LeavePeriod = TimeSpan.FromDays(3.0); - - public static readonly Map Facet = Map.Felucca; - - private FactionDefinition m_Definition; - public int ZeroRankOffset; - - public Faction() => State = new FactionState(this); - - public StrongholdRegion StrongholdRegion { get; set; } - - public FactionDefinition Definition - { - get => m_Definition; - set - { - m_Definition = value; - StrongholdRegion = new StrongholdRegion(this); - } - } - - public FactionState State { get; set; } - - public Election Election - { - get => State.Election; - set => State.Election = value; - } - - public Mobile Commander - { - get => State.Commander; - set => State.Commander = value; - } - - public int Tithe - { - get => State.Tithe; - set => State.Tithe = value; - } - - public int Silver - { - get => State.Silver; - set => State.Silver = value; - } - - public List Members - { - get => State.Members; - set => State.Members = value; - } - - public bool FactionMessageReady => State.FactionMessageReady; - - public virtual int MaximumTraps => 15; - - public List Traps - { - get => State.Traps; - set => State.Traps = value; - } - - public static List Factions => Reflector.Factions; - - public int CompareTo(Faction f) => m_Definition.Sort - (f?.m_Definition.Sort ?? 0); - - public void Broadcast(string text) - { - Broadcast(0x3B2, text); - } - - public void Broadcast(int hue, string text) - { - List members = Members; - - for (int i = 0; i < members.Count; ++i) - members[i].Mobile.SendMessage(hue, text); - } - - public void Broadcast(int number) - { - List members = Members; - - for (int i = 0; i < members.Count; ++i) - members[i].Mobile.SendLocalizedMessage(number); - } - - public void Broadcast(string format, params object[] args) - { - Broadcast(string.Format(format, args)); - } - - public void Broadcast(int hue, string format, params object[] args) - { - Broadcast(hue, string.Format(format, args)); - } - - public void BeginBroadcast(Mobile from) - { - from.SendLocalizedMessage(1010265); // Enter Faction Message - from.Prompt = new BroadcastPrompt(this); - } - - public void EndBroadcast(Mobile from, string text) - { - if (from.AccessLevel == AccessLevel.Player) - State.RegisterBroadcast(); - - Broadcast(Definition.HueBroadcast, "{0} [Commander] {1} : {2}", from.Name, Definition.FriendlyName, text); - } - - public static void HandleAtrophy() - { - foreach (Faction f in Factions) - if (!f.State.IsAtrophyReady) - return; - - List activePlayers = new List(); - - foreach (Faction f in Factions) - foreach (PlayerState ps in f.Members) - if (ps.KillPoints > 0 && ps.IsActive) - activePlayers.Add(ps); - - int distrib = 0; - - foreach (Faction f in Factions) - distrib += f.State.CheckAtrophy(); - - if (activePlayers.Count == 0) - return; - - for (int i = 0; i < distrib; ++i) - activePlayers.RandomElement().KillPoints++; - } - - public static void DistributePoints(int distrib) - { - List activePlayers = new List(); - - foreach (Faction f in Factions) - foreach (PlayerState ps in f.Members) - if (ps.KillPoints > 0 && ps.IsActive) - activePlayers.Add(ps); - - if (activePlayers.Count > 0) - for (int i = 0; i < distrib; ++i) - activePlayers.RandomElement().KillPoints++; - } - - public void BeginHonorLeadership(Mobile from) - { - from.SendLocalizedMessage(502090); // Click on the player whom you wish to honor. - from.BeginTarget(12, false, TargetFlags.None, HonorLeadership_OnTarget); - } - - public void HonorLeadership_OnTarget(Mobile from, object obj) - { - if (obj is Mobile recv) - { - PlayerState giveState = PlayerState.Find(from); - PlayerState recvState = PlayerState.Find(recv); - - if (giveState == null) - return; - - if (recvState == null || recvState.Faction != giveState.Faction) - { - from.SendLocalizedMessage(1042497); // Only faction mates can be honored this way. - } - else if (giveState.KillPoints < 5) - { - from.SendLocalizedMessage(1042499); // You must have at least five kill points to honor them. - } - else - { - recvState.LastHonorTime = DateTime.UtcNow; - giveState.KillPoints -= 5; - recvState.KillPoints += 4; - - // TODO: Confirm no message sent to giver - recv.SendLocalizedMessage(1042500); // You have been honored with four kill points. - } - } - else - { - from.SendLocalizedMessage(1042496); // You may only honor another player. - } - } - - public virtual void AddMember(Mobile mob) - { - Members.Insert(ZeroRankOffset, new PlayerState(mob, this, Members)); - - mob.AddToBackpack(FactionItem.Imbue(new Robe(), this, false, Definition.HuePrimary)); - mob.SendLocalizedMessage(1010374); // You have been granted a robe which signifies your faction - - mob.InvalidateProperties(); - mob.Delta(MobileDelta.Noto); - - mob.FixedEffect(0x373A, 10, 30); - mob.PlaySound(0x209); - } - - public static bool IsNearType(Mobile mob, Type type, int range) - { - bool mobs = type.IsSubclassOf(typeof(Mobile)); - bool items = type.IsSubclassOf(typeof(Item)); - - if (!(items || mobs)) - return false; - - IPooledEnumerable eable = mob.Map.GetObjectsInRange(mob.Location, range, items, mobs); - bool isInstance = eable.Any(type.IsInstanceOfType); - eable.Free(); - - return isInstance; - } - - public static bool IsNearType(Mobile mob, Type[] types, int range) - { - IPooledEnumerable eable = mob.GetObjectsInRange(range); - bool found = eable.Any(obj => types.Any(t => t.IsInstanceOfType(obj))); - eable.Free(); - return found; - } - - public void RemovePlayerState(PlayerState pl) - { - if (pl == null || !Members.Contains(pl)) - return; - - int killPoints = pl.KillPoints; - - if (pl.RankIndex != -1) - { - while (pl.RankIndex + 1 < ZeroRankOffset) - { - PlayerState pNext = Members[pl.RankIndex + 1]; - Members[pl.RankIndex + 1] = pl; - Members[pl.RankIndex] = pNext; - pl.RankIndex++; - pNext.RankIndex--; - } - - ZeroRankOffset--; - } - - Members.Remove(pl); - - PlayerMobile pm = (PlayerMobile)pl.Mobile; - if (pm == null) - return; - - Mobile mob = pl.Mobile; - if (pm.FactionPlayerState == pl) - { - pm.FactionPlayerState = null; - - mob.InvalidateProperties(); - mob.Delta(MobileDelta.Noto); - - if (Election.IsCandidate(mob)) - Election.RemoveCandidate(mob); - - if (pl.Finance != null) - pl.Finance.Finance = null; - - if (pl.Sheriff != null) - pl.Sheriff.Sheriff = null; - - Election.RemoveVoter(mob); - - if (Commander == mob) - Commander = null; - - pm.ValidateEquipment(); - } - - if (killPoints > 0) - DistributePoints(killPoints); - } - - public void RemoveMember(Mobile mob) - { - PlayerState pl = PlayerState.Find(mob); - - if (pl == null || !Members.Contains(pl)) - return; - - int killPoints = pl.KillPoints; - - // Ordinarily, through normal faction removal, this will never find any sigils. - // Only with a leave delay less than the ReturnPeriod or a Faction Kick/Ban, will this ever do anything - mob.Backpack?.FindItemsByType().ForEach(sigil => sigil.ReturnHome()); - - if (pl.RankIndex != -1) - { - while (pl.RankIndex + 1 < ZeroRankOffset) - { - PlayerState pNext = Members[pl.RankIndex + 1]; - Members[pl.RankIndex + 1] = pl; - Members[pl.RankIndex] = pNext; - pl.RankIndex++; - pNext.RankIndex--; - } - - ZeroRankOffset--; - } - - Members.Remove(pl); - - if (mob is PlayerMobile mobile) - mobile.FactionPlayerState = null; - - mob.InvalidateProperties(); - mob.Delta(MobileDelta.Noto); - - if (Election.IsCandidate(mob)) - Election.RemoveCandidate(mob); - - Election.RemoveVoter(mob); - - if (pl.Finance != null) - pl.Finance.Finance = null; - - if (pl.Sheriff != null) - pl.Sheriff.Sheriff = null; - - if (Commander == mob) - Commander = null; - - if (mob is PlayerMobile playerMobile) - playerMobile.ValidateEquipment(); - - if (killPoints > 0) - DistributePoints(killPoints); - } - - public void JoinGuilded(PlayerMobile mob, Guild guild) - { - if (mob.Young) - { - guild.RemoveMember(mob); - mob.SendLocalizedMessage( - 1042283); // You have been kicked out of your guild! Young players may not remain in a guild which is allied with a faction. - } - else if (AlreadyHasCharInFaction(mob)) - { - guild.RemoveMember(mob); - mob.SendLocalizedMessage(1005281); // You have been kicked out of your guild due to factional overlap - } - else if (IsFactionBanned(mob)) - { - guild.RemoveMember(mob); - mob.SendLocalizedMessage(1005052); // You are currently banned from the faction system - } - else - { - AddMember(mob); - mob.SendLocalizedMessage(1042756, true, $" {m_Definition.FriendlyName}"); // You are now joining a faction: - } - } - - public void JoinAlone(Mobile mob) - { - AddMember(mob); - mob.SendLocalizedMessage(1005058); // You have joined the faction - } - - private bool AlreadyHasCharInFaction(Mobile mob) - { - if (mob.Account is Account acct) - for (int i = 0; i < acct.Length; ++i) - { - Mobile c = acct[i]; - - if (Find(c) != null) - return true; - } - - return false; - } - - public static bool IsFactionBanned(Mobile mob) - { - if (!(mob.Account is Account acct)) - return false; - - return acct.GetTag("FactionBanned") != null; - } - - public void OnJoinAccepted(Mobile mob) - { - if (!(mob is PlayerMobile pm)) - return; // sanity - - PlayerState pl = PlayerState.Find(pm); - - if (pm.Young) - { - pm.SendLocalizedMessage(1010104); // You cannot join a faction as a young player - } - else if (pl?.IsLeaving == true) - { - pm.SendLocalizedMessage( - 1005051); // You cannot use the faction stone until you have finished quitting your current faction - } - else if (AlreadyHasCharInFaction(pm)) - { - pm.SendLocalizedMessage( - 1005059); // You cannot join a faction because you already declared your allegiance with another character - } - else if (IsFactionBanned(mob)) - { - pm.SendLocalizedMessage(1005052); // You are currently banned from the faction system - } - else if (pm.Guild != null) - { - Guild guild = pm.Guild as Guild; - - if (guild?.Leader != pm) - { - pm.SendLocalizedMessage( - 1005057); // You cannot join a faction because you are in a guild and not the guildmaster - } - else if (guild.Type != GuildType.Regular) - { - pm.SendLocalizedMessage( - 1042161); // You cannot join a faction because your guild is an Order or Chaos type. - } - else if (!Guild.NewGuildSystem && guild.Enemies?.Count > 0) // CAN join w/wars in new system - { - pm.SendLocalizedMessage(1005056); // You cannot join a faction with active Wars - } - else if (Guild.NewGuildSystem && guild.Alliance != null) - { - pm.SendLocalizedMessage( - 1080454); // Your guild cannot join a faction while in alliance with non-factioned guilds. - } - else if (!CanHandleInflux(guild.Members.Count)) - { - pm.SendLocalizedMessage( - 1018031); // In the interest of faction stability, this faction declines to accept new members for now. - } - else - { - List members = new List(guild.Members); - - for (int i = 0; i < members.Count; ++i) - { - if (!(members[i] is PlayerMobile member)) - continue; - - JoinGuilded(member, guild); - } - } - } - else if (!CanHandleInflux(1)) - { - pm.SendLocalizedMessage( - 1018031); // In the interest of faction stability, this faction declines to accept new members for now. - } - else - { - JoinAlone(mob); - } - } - - public bool IsCommander(Mobile mob) - { - if (mob == null) - return false; - - return mob.AccessLevel >= AccessLevel.GameMaster || mob == Commander; - } - - public override string ToString() => m_Definition.FriendlyName; - - public static bool CheckLeaveTimer(Mobile mob) - { - PlayerState pl = PlayerState.Find(mob); - - if (pl?.IsLeaving != true) - return false; - - if (pl.Leaving + LeavePeriod >= DateTime.UtcNow) - return false; - - mob.SendLocalizedMessage(1005163); // You have now quit your faction - - pl.Faction.RemoveMember(mob); - - return true; - } - - public static void Initialize() - { - EventSink.Login += EventSink_Login; - EventSink.Logout += EventSink_Logout; - - Timer.DelayCall(TimeSpan.FromMinutes(1.0), TimeSpan.FromMinutes(10.0), HandleAtrophy); - - Timer.DelayCall(TimeSpan.FromSeconds(30.0), TimeSpan.FromSeconds(30.0), ProcessTick); - - CommandSystem.Register("FactionElection", AccessLevel.GameMaster, FactionElection_OnCommand); - CommandSystem.Register("FactionCommander", AccessLevel.Administrator, FactionCommander_OnCommand); - CommandSystem.Register("FactionItemReset", AccessLevel.Administrator, FactionItemReset_OnCommand); - CommandSystem.Register("FactionReset", AccessLevel.Administrator, FactionReset_OnCommand); - CommandSystem.Register("FactionTownReset", AccessLevel.Administrator, FactionTownReset_OnCommand); - } - - public static void FactionTownReset_OnCommand(CommandEventArgs e) - { - List monoliths = BaseMonolith.Monoliths; - - for (int i = 0; i < monoliths.Count; ++i) - monoliths[i].Sigil = null; - - List towns = Town.Towns; - - for (int i = 0; i < towns.Count; ++i) - { - towns[i].Silver = 0; - towns[i].Sheriff = null; - towns[i].Finance = null; - towns[i].Tax = 0; - towns[i].Owner = null; - } - - List sigils = Sigil.Sigils; - - for (int i = 0; i < sigils.Count; ++i) - { - sigils[i].Corrupted = null; - sigils[i].Corrupting = null; - sigils[i].LastStolen = DateTime.MinValue; - sigils[i].GraceStart = DateTime.MinValue; - sigils[i].CorruptionStart = DateTime.MinValue; - sigils[i].PurificationStart = DateTime.MinValue; - sigils[i].LastMonolith = null; - sigils[i].ReturnHome(); - } - - List factions = Factions; - - for (int i = 0; i < factions.Count; ++i) - { - Faction f = factions[i]; - - List list = new List(f.State.FactionItems); - - for (int j = 0; j < list.Count; ++j) - { - FactionItem fi = list[j]; - - if (fi.Expiration == DateTime.MinValue) - fi.Item.Delete(); - else - fi.Detach(); - } - } - } - - public static void FactionReset_OnCommand(CommandEventArgs e) - { - List monoliths = BaseMonolith.Monoliths; - - for (int i = 0; i < monoliths.Count; ++i) - monoliths[i].Sigil = null; - - List towns = Town.Towns; - - for (int i = 0; i < towns.Count; ++i) - { - towns[i].Silver = 0; - towns[i].Sheriff = null; - towns[i].Finance = null; - towns[i].Tax = 0; - towns[i].Owner = null; - } - - List sigils = Sigil.Sigils; - - for (int i = 0; i < sigils.Count; ++i) - { - sigils[i].Corrupted = null; - sigils[i].Corrupting = null; - sigils[i].LastStolen = DateTime.MinValue; - sigils[i].GraceStart = DateTime.MinValue; - sigils[i].CorruptionStart = DateTime.MinValue; - sigils[i].PurificationStart = DateTime.MinValue; - sigils[i].LastMonolith = null; - sigils[i].ReturnHome(); - } - - List factions = Factions; - - for (int i = 0; i < factions.Count; ++i) - { - Faction f = factions[i]; - - List playerStateList = new List(f.Members); - - for (int j = 0; j < playerStateList.Count; ++j) - f.RemoveMember(playerStateList[j].Mobile); - - List factionItemList = new List(f.State.FactionItems); - - for (int j = 0; j < factionItemList.Count; ++j) - { - FactionItem fi = factionItemList[j]; - - if (fi.Expiration == DateTime.MinValue) - fi.Item.Delete(); - else - fi.Detach(); - } - - List factionTrapList = new List(f.Traps); - - for (int j = 0; j < factionTrapList.Count; ++j) - factionTrapList[j].Delete(); - } - } - - public static void FactionItemReset_OnCommand(CommandEventArgs e) - { - List items = new List(); - - foreach (Item item in World.Items.Values) - if (item is IFactionItem && !(item is HoodedShroudOfShadows)) - items.Add(item); - - int[] hues = new int[Factions.Count * 2]; - - for (int i = 0; i < Factions.Count; ++i) - { - hues[0 + i * 2] = Factions[i].Definition.HuePrimary; - hues[1 + i * 2] = Factions[i].Definition.HueSecondary; - } - - int count = 0; - - for (int i = 0; i < items.Count; ++i) - { - Item item = items[i]; - IFactionItem fci = (IFactionItem)item; - - if (fci.FactionItemState != null || item.LootType != LootType.Blessed) - continue; - - bool isHued = false; - - for (int j = 0; j < hues.Length; ++j) - if (item.Hue == hues[j]) - { - isHued = true; - break; - } - - if (isHued) - { - fci.FactionItemState = null; - ++count; - } - } - - e.Mobile.SendMessage("{0} items reset", count); - } - - public static void FactionCommander_OnCommand(CommandEventArgs e) - { - e.Mobile.SendMessage("Target a player to make them the faction commander."); - e.Mobile.BeginTarget(-1, false, TargetFlags.None, FactionCommander_OnTarget); - } - - public static void FactionCommander_OnTarget(Mobile from, object obj) - { - if (obj is PlayerMobile mobile) - { - Mobile targ = mobile; - PlayerState pl = PlayerState.Find(targ); - - if (pl != null) - { - pl.Faction.Commander = targ; - from.SendMessage("You have appointed them as the faction commander."); - } - else - { - from.SendMessage("They are not in a faction."); - } - } - else - { - from.SendMessage("That is not a player."); - } - } - - public static void FactionElection_OnCommand(CommandEventArgs e) - { - e.Mobile.SendMessage("Target a faction stone to open its election properties."); - e.Mobile.BeginTarget(-1, false, TargetFlags.None, FactionElection_OnTarget); - } - - public static void FactionElection_OnTarget(Mobile from, object obj) - { - if (obj is FactionStone stone) - { - Faction faction = stone.Faction; - - if (faction != null) - from.SendGump(new ElectionManagementGump(faction.Election)); - // from.SendGump( new Gumps.PropertiesGump( from, faction.Election ) ); - else - from.SendMessage("That stone has no faction assigned."); - } - else - { - from.SendMessage("That is not a faction stone."); - } - } - - public static void FactionKick_OnCommand(CommandEventArgs e) - { - e.Mobile.SendMessage("Target a player to remove them from their faction."); - e.Mobile.BeginTarget(-1, false, TargetFlags.None, FactionKick_OnTarget); - } - - public static void FactionKick_OnTarget(Mobile from, object obj) - { - if (obj is Mobile mob) - { - PlayerState pl = PlayerState.Find(mob); - - if (pl != null) - { - pl.Faction.RemoveMember(mob); - - mob.SendMessage("You have been kicked from your faction."); - from.SendMessage("They have been kicked from their faction."); - } - else - { - from.SendMessage("They are not in a faction."); - } - } - else - { - from.SendMessage("That is not a player."); - } - } - - public static void ProcessTick() - { - List sigils = Sigil.Sigils; - - for (int i = 0; i < sigils.Count; ++i) - { - Sigil sigil = sigils[i]; - - if (!sigil.IsBeingCorrupted && sigil.GraceStart != DateTime.MinValue && - sigil.GraceStart + Sigil.CorruptionGrace < DateTime.UtcNow) - { - if (sigil.LastMonolith is StrongholdMonolith && - (sigil.Corrupted == null || sigil.LastMonolith.Faction != sigil.Corrupted)) - { - sigil.Corrupting = sigil.LastMonolith.Faction; - sigil.CorruptionStart = DateTime.UtcNow; - } - else - { - sigil.Corrupting = null; - sigil.CorruptionStart = DateTime.MinValue; - } - - sigil.GraceStart = DateTime.MinValue; - } - - if (sigil.LastMonolith?.Sigil == null) - { - if (sigil.LastStolen + Sigil.ReturnPeriod < DateTime.UtcNow) - sigil.ReturnHome(); - } - else - { - if (sigil.IsBeingCorrupted && sigil.CorruptionStart + Sigil.CorruptionPeriod < DateTime.UtcNow) - { - sigil.Corrupted = sigil.Corrupting; - sigil.Corrupting = null; - sigil.CorruptionStart = DateTime.MinValue; - sigil.GraceStart = DateTime.MinValue; - } - else if (sigil.IsPurifying && sigil.PurificationStart + Sigil.PurificationPeriod < DateTime.UtcNow) - { - sigil.PurificationStart = DateTime.MinValue; - sigil.Corrupted = null; - sigil.Corrupting = null; - sigil.CorruptionStart = DateTime.MinValue; - sigil.GraceStart = DateTime.MinValue; - } - } - } - } - - public static void HandleDeath(Mobile mob) - { - HandleDeath(mob, null); - } - - public int AwardSilver(Mobile mob, int silver) - { - if (silver <= 0) - return 0; - - int tithed = silver * Tithe / 100; - - Silver += tithed; - - silver = silver - tithed; - - if (silver > 0) - mob.AddToBackpack(new Silver(silver)); - - return silver; - } - - public static Faction FindSmallestFaction() - { - List factions = Factions; - Faction smallest = null; - - for (int i = 0; i < factions.Count; ++i) - { - Faction faction = factions[i]; - - if (smallest == null || faction.Members.Count < smallest.Members.Count) - smallest = faction; - } - - return smallest; - } - - public static bool StabilityActive() - { - List factions = Factions; - - for (int i = 0; i < factions.Count; ++i) - { - Faction faction = factions[i]; - - if (faction.Members.Count > StabilityActivation) - return true; - } - - return false; - } - - public bool CanHandleInflux(int influx) - { - if (!StabilityActive()) - return true; - - Faction smallest = FindSmallestFaction(); - - if (smallest == null) - return true; // sanity - - if ((Members.Count + influx) * 100 / StabilityFactor > smallest.Members.Count) - return false; - - return true; - } - - public static void HandleDeath(Mobile victim, Mobile killer) - { - killer ??= victim.FindMostRecentDamager(true); - - PlayerState killerState = PlayerState.Find(killer); - Container killerPack = killer?.Backpack; - victim.Backpack?.FindItemsByType().ForEach(sigil => - { - if (killerState == null || killerPack == null) - { - sigil.ReturnHome(); - return; - } - - if (killer?.GetDistanceToSqrt(victim) > 64) - { - sigil.ReturnHome(); - killer.SendLocalizedMessage(1042230); // The sigil has gone back to its home location. - } - else if (Sigil.ExistsOn(killer)) - { - sigil.ReturnHome(); - killer?.SendLocalizedMessage( - 1010258); // The sigil has gone back to its home location because you already have a sigil. - } - else if (!killerPack.TryDropItem(killer, sigil, false)) - { - sigil.ReturnHome(); - killer?.SendLocalizedMessage(1010259); // The sigil has gone home because your backpack is full. - } - }); - - if (killerState == null) - return; - - if (victim is BaseCreature bc) - { - Faction victimFaction = bc.FactionAllegiance; - - if (bc.Map == Facet && victimFaction != null && killerState.Faction != victimFaction) - { - int silver = killerState.Faction.AwardSilver(killer, bc.FactionSilverWorth); - - if (silver > 0) - killer?.SendLocalizedMessage(1042748, - silver.ToString("N0")); // Thou hast earned ~1_AMOUNT~ silver for vanquishing the vile creature. - } - - if (bc.Map == Facet && bc.GetEthicAllegiance(killer) == BaseCreature.Allegiance.Enemy) - { - Player killerEPL = Player.Find(killer); - - if (killerEPL != null && 100 - killerEPL.Power > Utility.Random(100)) - { - ++killerEPL.Power; - ++killerEPL.History; - } - } - - return; - } - - PlayerState victimState = PlayerState.Find(victim); - - if (victimState == null) - return; - - if (victim.Region.IsPartOf()) - return; - - if (killer == victim || killerState.Faction != victimState.Faction) - ApplySkillLoss(victim); - - if (killerState.Faction != victimState.Faction) - { - if (victimState.KillPoints <= -6) - { - killer?.SendLocalizedMessage(501693); // This victim is not worth enough to get kill points from. - - Player killerEPL = Player.Find(killer); - Player victimEPL = Player.Find(victim); - - if (killerEPL != null && victimEPL?.Power > 0 && victimState.CanGiveSilverTo(killer)) - { - int powerTransfer = Math.Max(1, victimEPL.Power / 5); - - if (powerTransfer > 100 - killerEPL.Power) - powerTransfer = 100 - killerEPL.Power; - - if (powerTransfer > 0) - { - victimEPL.Power -= (powerTransfer + 1) / 2; - killerEPL.Power += powerTransfer; - - killerEPL.History += powerTransfer; - - victimState.OnGivenSilverTo(killer); - } - } - } - else - { - int award = Math.Max(victimState.KillPoints / 10, 1); - - if (award > 40) - award = 40; - - if (victimState.CanGiveSilverTo(killer)) - { - PowerFactionItem.CheckSpawn(killer, victim); - - if (victimState.KillPoints > 0) - { - victimState.IsActive = true; - - if (Utility.Random(3) < 1) - killerState.IsActive = true; - - int silver = killerState.Faction.AwardSilver(killer, award * 40); - - if (silver > 0) - killer?.SendLocalizedMessage(1042736, - $"{silver:N0} silver\t{victim.Name}"); // You have earned ~1_SILVER_AMOUNT~ pieces for vanquishing ~2_PLAYER_NAME~! - } - - victimState.KillPoints -= award; - killerState.KillPoints += award; - - int offset = award != 1 ? 0 : 2; // for pluralization - - string args = $"{award}\t{victim.Name}\t{killer?.Name}"; - - killer?.SendLocalizedMessage(1042737 + offset, - args); // Thou hast been honored with ~1_KILL_POINTS~ kill point(s) for vanquishing ~2_DEAD_PLAYER~! - victim.SendLocalizedMessage(1042738 + offset, - args); // Thou has lost ~1_KILL_POINTS~ kill point(s) to ~3_ATTACKER_NAME~ for being vanquished! - - Player killerEPL = Player.Find(killer); - Player victimEPL = Player.Find(victim); - - if (killerEPL != null && victimEPL?.Power > 0) - { - int powerTransfer = Math.Max(1, victimEPL.Power / 5); - - if (powerTransfer > 100 - killerEPL.Power) - powerTransfer = 100 - killerEPL.Power; - - if (powerTransfer > 0) - { - victimEPL.Power -= (powerTransfer + 1) / 2; - killerEPL.Power += powerTransfer; - - killerEPL.History += powerTransfer; - } - } - - victimState.OnGivenSilverTo(killer); - } - else - { - killer?.SendLocalizedMessage( - 1042231); // You have recently defeated this enemy and thus their death brings you no honor. - } - } - } - } - - private static void EventSink_Logout(Mobile m) - { - m.Backpack?.FindItemsByType().ForEach(sigil => sigil.ReturnHome()); - } - - private static void EventSink_Login(Mobile m) => CheckLeaveTimer(m); - - public static void WriteReference(IGenericWriter writer, Faction fact) - { - int idx = Factions.IndexOf(fact); - - writer.WriteEncodedInt(idx + 1); - } - - public static Faction ReadReference(IGenericReader reader) - { - int idx = reader.ReadEncodedInt() - 1; - - return idx >= 0 && idx < Factions.Count ? Factions[idx] : null; - } - - public static Faction Find(Mobile mob, bool inherit = false, bool creatureAllegiances = false) - { - PlayerState pl = PlayerState.Find(mob); - - if (pl != null) - return pl.Faction; - - if (inherit && mob is BaseCreature bc) - { - if (bc.Controlled) - return Find(bc.ControlMaster); - if (bc.Summoned) - return Find(bc.SummonMaster); - if (creatureAllegiances && bc is BaseFactionGuard guard) - return guard.Faction; - if (creatureAllegiances) - return bc.FactionAllegiance; - } - - return null; - } - - public static Faction Parse(string name) - { - List factions = Factions; - - for (int i = 0; i < factions.Count; ++i) - { - Faction faction = factions[i]; - - if (Insensitive.Equals(faction.Definition.FriendlyName, name)) - return faction; - } - - return null; - } - - private class BroadcastPrompt : Prompt - { - private readonly Faction m_Faction; - - public BroadcastPrompt(Faction faction) => m_Faction = faction; - - public override void OnResponse(Mobile from, string text) - { - m_Faction.EndBroadcast(from, text); - } - } - - public const double SkillLossFactor = 1.0 / 3; - public static readonly TimeSpan SkillLossPeriod = TimeSpan.FromMinutes(20.0); - - private static readonly Dictionary m_SkillLoss = new Dictionary(); - - private class SkillLossContext - { - public List m_Mods; - public Timer m_Timer; - } - - public static bool InSkillLoss(Mobile mob) => m_SkillLoss.ContainsKey(mob); - - public static void ApplySkillLoss(Mobile mob) - { - if (InSkillLoss(mob)) - return; - - SkillLossContext context = new SkillLossContext(); - m_SkillLoss[mob] = context; - - List mods = context.m_Mods = new List(); - - for (int i = 0; i < mob.Skills.Length; ++i) - { - Skill sk = mob.Skills[i]; - double baseValue = sk.Base; - - if (baseValue > 0) - { - SkillMod mod = new DefaultSkillMod(sk.SkillName, true, -(baseValue * SkillLossFactor)); - - mods.Add(mod); - mob.AddSkillMod(mod); - } - } - - context.m_Timer = Timer.DelayCall(SkillLossPeriod, ClearSkillLoss_Event, mob); - } - - private static void ClearSkillLoss_Event(Mobile mob) => ClearSkillLoss(mob); - - public static bool ClearSkillLoss(Mobile mob) - { - if (!m_SkillLoss.TryGetValue(mob, out SkillLossContext context)) - return false; - - m_SkillLoss.Remove(mob); - - List mods = context.m_Mods; - - for (int i = 0; i < mods.Count; ++i) - mob.RemoveSkillMod(mods[i]); - - context.m_Timer.Stop(); - - return true; - } - } - - public enum FactionKickType - { - Kick, - Ban, - Unban - } - - public class FactionKickCommand : BaseCommand - { - private readonly FactionKickType m_KickType; - - public FactionKickCommand(FactionKickType kickType) - { - m_KickType = kickType; - - AccessLevel = AccessLevel.GameMaster; - Supports = CommandSupport.AllMobiles; - ObjectTypes = ObjectTypes.Mobiles; - - switch (m_KickType) - { - case FactionKickType.Kick: - { - Commands = new[] { "FactionKick" }; - Usage = "FactionKick"; - Description = - "Kicks the targeted player out of his current faction. This does not prevent them from rejoining."; - break; - } - case FactionKickType.Ban: - { - Commands = new[] { "FactionBan" }; - Usage = "FactionBan"; - Description = - "Bans the account of a targeted player from joining factions. All players on the account are removed from their current faction, if any."; - break; - } - case FactionKickType.Unban: - { - Commands = new[] { "FactionUnban" }; - Usage = "FactionUnban"; - Description = "Unbans the account of a targeted player from joining factions."; - break; - } - } - } - - public override void Execute(CommandEventArgs e, object obj) - { - Mobile mob = (Mobile)obj; - - switch (m_KickType) - { - case FactionKickType.Kick: - { - PlayerState pl = PlayerState.Find(mob); - - if (pl != null) - { - pl.Faction.RemoveMember(mob); - mob.SendMessage("You have been kicked from your faction."); - AddResponse("They have been kicked from their faction."); - } - else - { - LogFailure("They are not in a faction."); - } - - break; - } - case FactionKickType.Ban: - { - if (mob.Account is Account acct) - { - if (acct.GetTag("FactionBanned") == null) - { - acct.SetTag("FactionBanned", "true"); - AddResponse("The account has been banned from joining factions."); - } - else - { - AddResponse("The account is already banned from joining factions."); - } - - for (int i = 0; i < acct.Length; ++i) - { - mob = acct[i]; - - if (mob != null) - { - PlayerState pl = PlayerState.Find(mob); - - if (pl != null) - { - pl.Faction.RemoveMember(mob); - mob.SendMessage("You have been kicked from your faction."); - AddResponse("They have been kicked from their faction."); - } - } - } - } - else - { - LogFailure("They have no assigned account."); - } - - break; - } - case FactionKickType.Unban: - { - if (mob.Account is Account acct) - { - if (acct.GetTag("FactionBanned") == null) - { - AddResponse("The account is not already banned from joining factions."); - } - else - { - acct.RemoveTag("FactionBanned"); - AddResponse("The account may now freely join factions."); - } - } - else - { - LogFailure("They have no assigned account."); - } - - break; - } - } - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using Server.Accounting; +using Server.Commands.Generic; +using Server.Engines.ConPVP; +using Server.Ethics; +using Server.Guilds; +using Server.Items; +using Server.Mobiles; +using Server.Prompts; +using Server.Targeting; + +namespace Server.Factions +{ + [CustomEnum(new[] { "Minax", "Council of Mages", "True Britannians", "Shadowlords" })] + public abstract class Faction : IComparable + { + public const int StabilityFactor = 300; // 300% greater (3 times) than smallest faction + public const int StabilityActivation = 200; // Stability code goes into effect when largest faction has > 200 people + + public const double SkillLossFactor = 1.0 / 3; + + public static readonly TimeSpan LeavePeriod = TimeSpan.FromDays(3.0); + + public static readonly Map Facet = Map.Felucca; + public static readonly TimeSpan SkillLossPeriod = TimeSpan.FromMinutes(20.0); + + private static readonly Dictionary + m_SkillLoss = new Dictionary(); + + private FactionDefinition m_Definition; + public int ZeroRankOffset; + + public Faction() => State = new FactionState(this); + + public StrongholdRegion StrongholdRegion { get; set; } + + public FactionDefinition Definition + { + get => m_Definition; + set + { + m_Definition = value; + StrongholdRegion = new StrongholdRegion(this); + } + } + + public FactionState State { get; set; } + + public Election Election + { + get => State.Election; + set => State.Election = value; + } + + public Mobile Commander + { + get => State.Commander; + set => State.Commander = value; + } + + public int Tithe + { + get => State.Tithe; + set => State.Tithe = value; + } + + public int Silver + { + get => State.Silver; + set => State.Silver = value; + } + + public List Members + { + get => State.Members; + set => State.Members = value; + } + + public bool FactionMessageReady => State.FactionMessageReady; + + public virtual int MaximumTraps => 15; + + public List Traps + { + get => State.Traps; + set => State.Traps = value; + } + + public static List Factions => Reflector.Factions; + + public int CompareTo(Faction f) => m_Definition.Sort - (f?.m_Definition.Sort ?? 0); + + public void Broadcast(string text) + { + Broadcast(0x3B2, text); + } + + public void Broadcast(int hue, string text) + { + var members = Members; + + for (var i = 0; i < members.Count; ++i) + members[i].Mobile.SendMessage(hue, text); + } + + public void Broadcast(int number) + { + var members = Members; + + for (var i = 0; i < members.Count; ++i) + members[i].Mobile.SendLocalizedMessage(number); + } + + public void Broadcast(string format, params object[] args) + { + Broadcast(string.Format(format, args)); + } + + public void Broadcast(int hue, string format, params object[] args) + { + Broadcast(hue, string.Format(format, args)); + } + + public void BeginBroadcast(Mobile from) + { + from.SendLocalizedMessage(1010265); // Enter Faction Message + from.Prompt = new BroadcastPrompt(this); + } + + public void EndBroadcast(Mobile from, string text) + { + if (from.AccessLevel == AccessLevel.Player) + State.RegisterBroadcast(); + + Broadcast(Definition.HueBroadcast, "{0} [Commander] {1} : {2}", from.Name, Definition.FriendlyName, text); + } + + public static void HandleAtrophy() + { + foreach (var f in Factions) + if (!f.State.IsAtrophyReady) + return; + + var activePlayers = new List(); + + foreach (var f in Factions) + foreach (var ps in f.Members) + if (ps.KillPoints > 0 && ps.IsActive) + activePlayers.Add(ps); + + var distrib = 0; + + foreach (var f in Factions) + distrib += f.State.CheckAtrophy(); + + if (activePlayers.Count == 0) + return; + + for (var i = 0; i < distrib; ++i) + activePlayers.RandomElement().KillPoints++; + } + + public static void DistributePoints(int distrib) + { + var activePlayers = new List(); + + foreach (var f in Factions) + foreach (var ps in f.Members) + if (ps.KillPoints > 0 && ps.IsActive) + activePlayers.Add(ps); + + if (activePlayers.Count > 0) + for (var i = 0; i < distrib; ++i) + activePlayers.RandomElement().KillPoints++; + } + + public void BeginHonorLeadership(Mobile from) + { + from.SendLocalizedMessage(502090); // Click on the player whom you wish to honor. + from.BeginTarget(12, false, TargetFlags.None, HonorLeadership_OnTarget); + } + + public void HonorLeadership_OnTarget(Mobile from, object obj) + { + if (obj is Mobile recv) + { + var giveState = PlayerState.Find(from); + var recvState = PlayerState.Find(recv); + + if (giveState == null) + return; + + if (recvState == null || recvState.Faction != giveState.Faction) + { + from.SendLocalizedMessage(1042497); // Only faction mates can be honored this way. + } + else if (giveState.KillPoints < 5) + { + from.SendLocalizedMessage(1042499); // You must have at least five kill points to honor them. + } + else + { + recvState.LastHonorTime = DateTime.UtcNow; + giveState.KillPoints -= 5; + recvState.KillPoints += 4; + + // TODO: Confirm no message sent to giver + recv.SendLocalizedMessage(1042500); // You have been honored with four kill points. + } + } + else + { + from.SendLocalizedMessage(1042496); // You may only honor another player. + } + } + + public virtual void AddMember(Mobile mob) + { + Members.Insert(ZeroRankOffset, new PlayerState(mob, this, Members)); + + mob.AddToBackpack(FactionItem.Imbue(new Robe(), this, false, Definition.HuePrimary)); + mob.SendLocalizedMessage(1010374); // You have been granted a robe which signifies your faction + + mob.InvalidateProperties(); + mob.Delta(MobileDelta.Noto); + + mob.FixedEffect(0x373A, 10, 30); + mob.PlaySound(0x209); + } + + public static bool IsNearType(Mobile mob, Type type, int range) + { + var mobs = type.IsSubclassOf(typeof(Mobile)); + var items = type.IsSubclassOf(typeof(Item)); + + if (!(items || mobs)) + return false; + + var eable = mob.Map.GetObjectsInRange(mob.Location, range, items, mobs); + var isInstance = eable.Any(type.IsInstanceOfType); + eable.Free(); + + return isInstance; + } + + public static bool IsNearType(Mobile mob, Type[] types, int range) + { + var eable = mob.GetObjectsInRange(range); + var found = eable.Any(obj => types.Any(t => t.IsInstanceOfType(obj))); + eable.Free(); + return found; + } + + public void RemovePlayerState(PlayerState pl) + { + if (pl == null || !Members.Contains(pl)) + return; + + var killPoints = pl.KillPoints; + + if (pl.RankIndex != -1) + { + while (pl.RankIndex + 1 < ZeroRankOffset) + { + var pNext = Members[pl.RankIndex + 1]; + Members[pl.RankIndex + 1] = pl; + Members[pl.RankIndex] = pNext; + pl.RankIndex++; + pNext.RankIndex--; + } + + ZeroRankOffset--; + } + + Members.Remove(pl); + + var pm = (PlayerMobile)pl.Mobile; + if (pm == null) + return; + + var mob = pl.Mobile; + if (pm.FactionPlayerState == pl) + { + pm.FactionPlayerState = null; + + mob.InvalidateProperties(); + mob.Delta(MobileDelta.Noto); + + if (Election.IsCandidate(mob)) + Election.RemoveCandidate(mob); + + if (pl.Finance != null) + pl.Finance.Finance = null; + + if (pl.Sheriff != null) + pl.Sheriff.Sheriff = null; + + Election.RemoveVoter(mob); + + if (Commander == mob) + Commander = null; + + pm.ValidateEquipment(); + } + + if (killPoints > 0) + DistributePoints(killPoints); + } + + public void RemoveMember(Mobile mob) + { + var pl = PlayerState.Find(mob); + + if (pl == null || !Members.Contains(pl)) + return; + + var killPoints = pl.KillPoints; + + // Ordinarily, through normal faction removal, this will never find any sigils. + // Only with a leave delay less than the ReturnPeriod or a Faction Kick/Ban, will this ever do anything + mob.Backpack?.FindItemsByType().ForEach(sigil => sigil.ReturnHome()); + + if (pl.RankIndex != -1) + { + while (pl.RankIndex + 1 < ZeroRankOffset) + { + var pNext = Members[pl.RankIndex + 1]; + Members[pl.RankIndex + 1] = pl; + Members[pl.RankIndex] = pNext; + pl.RankIndex++; + pNext.RankIndex--; + } + + ZeroRankOffset--; + } + + Members.Remove(pl); + + if (mob is PlayerMobile mobile) + mobile.FactionPlayerState = null; + + mob.InvalidateProperties(); + mob.Delta(MobileDelta.Noto); + + if (Election.IsCandidate(mob)) + Election.RemoveCandidate(mob); + + Election.RemoveVoter(mob); + + if (pl.Finance != null) + pl.Finance.Finance = null; + + if (pl.Sheriff != null) + pl.Sheriff.Sheriff = null; + + if (Commander == mob) + Commander = null; + + if (mob is PlayerMobile playerMobile) + playerMobile.ValidateEquipment(); + + if (killPoints > 0) + DistributePoints(killPoints); + } + + public void JoinGuilded(PlayerMobile mob, Guild guild) + { + if (mob.Young) + { + guild.RemoveMember(mob); + mob.SendLocalizedMessage( + 1042283 + ); // You have been kicked out of your guild! Young players may not remain in a guild which is allied with a faction. + } + else if (AlreadyHasCharInFaction(mob)) + { + guild.RemoveMember(mob); + mob.SendLocalizedMessage(1005281); // You have been kicked out of your guild due to factional overlap + } + else if (IsFactionBanned(mob)) + { + guild.RemoveMember(mob); + mob.SendLocalizedMessage(1005052); // You are currently banned from the faction system + } + else + { + AddMember(mob); + mob.SendLocalizedMessage(1042756, true, $" {m_Definition.FriendlyName}"); // You are now joining a faction: + } + } + + public void JoinAlone(Mobile mob) + { + AddMember(mob); + mob.SendLocalizedMessage(1005058); // You have joined the faction + } + + private bool AlreadyHasCharInFaction(Mobile mob) + { + if (mob.Account is Account acct) + for (var i = 0; i < acct.Length; ++i) + { + var c = acct[i]; + + if (Find(c) != null) + return true; + } + + return false; + } + + public static bool IsFactionBanned(Mobile mob) + { + if (!(mob.Account is Account acct)) + return false; + + return acct.GetTag("FactionBanned") != null; + } + + public void OnJoinAccepted(Mobile mob) + { + if (!(mob is PlayerMobile pm)) + return; // sanity + + var pl = PlayerState.Find(pm); + + if (pm.Young) + { + pm.SendLocalizedMessage(1010104); // You cannot join a faction as a young player + } + else if (pl?.IsLeaving == true) + { + pm.SendLocalizedMessage( + 1005051 + ); // You cannot use the faction stone until you have finished quitting your current faction + } + else if (AlreadyHasCharInFaction(pm)) + { + pm.SendLocalizedMessage( + 1005059 + ); // You cannot join a faction because you already declared your allegiance with another character + } + else if (IsFactionBanned(mob)) + { + pm.SendLocalizedMessage(1005052); // You are currently banned from the faction system + } + else if (pm.Guild != null) + { + var guild = pm.Guild as Guild; + + if (guild?.Leader != pm) + { + pm.SendLocalizedMessage( + 1005057 + ); // You cannot join a faction because you are in a guild and not the guildmaster + } + else if (guild.Type != GuildType.Regular) + { + pm.SendLocalizedMessage( + 1042161 + ); // You cannot join a faction because your guild is an Order or Chaos type. + } + else if (!Guild.NewGuildSystem && guild.Enemies?.Count > 0) // CAN join w/wars in new system + { + pm.SendLocalizedMessage(1005056); // You cannot join a faction with active Wars + } + else if (Guild.NewGuildSystem && guild.Alliance != null) + { + pm.SendLocalizedMessage( + 1080454 + ); // Your guild cannot join a faction while in alliance with non-factioned guilds. + } + else if (!CanHandleInflux(guild.Members.Count)) + { + pm.SendLocalizedMessage( + 1018031 + ); // In the interest of faction stability, this faction declines to accept new members for now. + } + else + { + var members = new List(guild.Members); + + for (var i = 0; i < members.Count; ++i) + { + if (!(members[i] is PlayerMobile member)) + continue; + + JoinGuilded(member, guild); + } + } + } + else if (!CanHandleInflux(1)) + { + pm.SendLocalizedMessage( + 1018031 + ); // In the interest of faction stability, this faction declines to accept new members for now. + } + else + { + JoinAlone(mob); + } + } + + public bool IsCommander(Mobile mob) + { + if (mob == null) + return false; + + return mob.AccessLevel >= AccessLevel.GameMaster || mob == Commander; + } + + public override string ToString() => m_Definition.FriendlyName; + + public static bool CheckLeaveTimer(Mobile mob) + { + var pl = PlayerState.Find(mob); + + if (pl?.IsLeaving != true) + return false; + + if (pl.Leaving + LeavePeriod >= DateTime.UtcNow) + return false; + + mob.SendLocalizedMessage(1005163); // You have now quit your faction + + pl.Faction.RemoveMember(mob); + + return true; + } + + public static void Initialize() + { + EventSink.Login += EventSink_Login; + EventSink.Logout += EventSink_Logout; + + Timer.DelayCall(TimeSpan.FromMinutes(1.0), TimeSpan.FromMinutes(10.0), HandleAtrophy); + + Timer.DelayCall(TimeSpan.FromSeconds(30.0), TimeSpan.FromSeconds(30.0), ProcessTick); + + CommandSystem.Register("FactionElection", AccessLevel.GameMaster, FactionElection_OnCommand); + CommandSystem.Register("FactionCommander", AccessLevel.Administrator, FactionCommander_OnCommand); + CommandSystem.Register("FactionItemReset", AccessLevel.Administrator, FactionItemReset_OnCommand); + CommandSystem.Register("FactionReset", AccessLevel.Administrator, FactionReset_OnCommand); + CommandSystem.Register("FactionTownReset", AccessLevel.Administrator, FactionTownReset_OnCommand); + } + + public static void FactionTownReset_OnCommand(CommandEventArgs e) + { + var monoliths = BaseMonolith.Monoliths; + + for (var i = 0; i < monoliths.Count; ++i) + monoliths[i].Sigil = null; + + var towns = Town.Towns; + + for (var i = 0; i < towns.Count; ++i) + { + towns[i].Silver = 0; + towns[i].Sheriff = null; + towns[i].Finance = null; + towns[i].Tax = 0; + towns[i].Owner = null; + } + + var sigils = Sigil.Sigils; + + for (var i = 0; i < sigils.Count; ++i) + { + sigils[i].Corrupted = null; + sigils[i].Corrupting = null; + sigils[i].LastStolen = DateTime.MinValue; + sigils[i].GraceStart = DateTime.MinValue; + sigils[i].CorruptionStart = DateTime.MinValue; + sigils[i].PurificationStart = DateTime.MinValue; + sigils[i].LastMonolith = null; + sigils[i].ReturnHome(); + } + + var factions = Factions; + + for (var i = 0; i < factions.Count; ++i) + { + var f = factions[i]; + + var list = new List(f.State.FactionItems); + + for (var j = 0; j < list.Count; ++j) + { + var fi = list[j]; + + if (fi.Expiration == DateTime.MinValue) + fi.Item.Delete(); + else + fi.Detach(); + } + } + } + + public static void FactionReset_OnCommand(CommandEventArgs e) + { + var monoliths = BaseMonolith.Monoliths; + + for (var i = 0; i < monoliths.Count; ++i) + monoliths[i].Sigil = null; + + var towns = Town.Towns; + + for (var i = 0; i < towns.Count; ++i) + { + towns[i].Silver = 0; + towns[i].Sheriff = null; + towns[i].Finance = null; + towns[i].Tax = 0; + towns[i].Owner = null; + } + + var sigils = Sigil.Sigils; + + for (var i = 0; i < sigils.Count; ++i) + { + sigils[i].Corrupted = null; + sigils[i].Corrupting = null; + sigils[i].LastStolen = DateTime.MinValue; + sigils[i].GraceStart = DateTime.MinValue; + sigils[i].CorruptionStart = DateTime.MinValue; + sigils[i].PurificationStart = DateTime.MinValue; + sigils[i].LastMonolith = null; + sigils[i].ReturnHome(); + } + + var factions = Factions; + + for (var i = 0; i < factions.Count; ++i) + { + var f = factions[i]; + + var playerStateList = new List(f.Members); + + for (var j = 0; j < playerStateList.Count; ++j) + f.RemoveMember(playerStateList[j].Mobile); + + var factionItemList = new List(f.State.FactionItems); + + for (var j = 0; j < factionItemList.Count; ++j) + { + var fi = factionItemList[j]; + + if (fi.Expiration == DateTime.MinValue) + fi.Item.Delete(); + else + fi.Detach(); + } + + var factionTrapList = new List(f.Traps); + + for (var j = 0; j < factionTrapList.Count; ++j) + factionTrapList[j].Delete(); + } + } + + public static void FactionItemReset_OnCommand(CommandEventArgs e) + { + var items = new List(); + + foreach (var item in World.Items.Values) + if (item is IFactionItem && !(item is HoodedShroudOfShadows)) + items.Add(item); + + var hues = new int[Factions.Count * 2]; + + for (var i = 0; i < Factions.Count; ++i) + { + hues[0 + i * 2] = Factions[i].Definition.HuePrimary; + hues[1 + i * 2] = Factions[i].Definition.HueSecondary; + } + + var count = 0; + + for (var i = 0; i < items.Count; ++i) + { + var item = items[i]; + var fci = (IFactionItem)item; + + if (fci.FactionItemState != null || item.LootType != LootType.Blessed) + continue; + + var isHued = false; + + for (var j = 0; j < hues.Length; ++j) + if (item.Hue == hues[j]) + { + isHued = true; + break; + } + + if (isHued) + { + fci.FactionItemState = null; + ++count; + } + } + + e.Mobile.SendMessage("{0} items reset", count); + } + + public static void FactionCommander_OnCommand(CommandEventArgs e) + { + e.Mobile.SendMessage("Target a player to make them the faction commander."); + e.Mobile.BeginTarget(-1, false, TargetFlags.None, FactionCommander_OnTarget); + } + + public static void FactionCommander_OnTarget(Mobile from, object obj) + { + if (obj is PlayerMobile mobile) + { + Mobile targ = mobile; + var pl = PlayerState.Find(targ); + + if (pl != null) + { + pl.Faction.Commander = targ; + from.SendMessage("You have appointed them as the faction commander."); + } + else + { + from.SendMessage("They are not in a faction."); + } + } + else + { + from.SendMessage("That is not a player."); + } + } + + public static void FactionElection_OnCommand(CommandEventArgs e) + { + e.Mobile.SendMessage("Target a faction stone to open its election properties."); + e.Mobile.BeginTarget(-1, false, TargetFlags.None, FactionElection_OnTarget); + } + + public static void FactionElection_OnTarget(Mobile from, object obj) + { + if (obj is FactionStone stone) + { + var faction = stone.Faction; + + if (faction != null) + from.SendGump(new ElectionManagementGump(faction.Election)); + // from.SendGump( new Gumps.PropertiesGump( from, faction.Election ) ); + else + from.SendMessage("That stone has no faction assigned."); + } + else + { + from.SendMessage("That is not a faction stone."); + } + } + + public static void FactionKick_OnCommand(CommandEventArgs e) + { + e.Mobile.SendMessage("Target a player to remove them from their faction."); + e.Mobile.BeginTarget(-1, false, TargetFlags.None, FactionKick_OnTarget); + } + + public static void FactionKick_OnTarget(Mobile from, object obj) + { + if (obj is Mobile mob) + { + var pl = PlayerState.Find(mob); + + if (pl != null) + { + pl.Faction.RemoveMember(mob); + + mob.SendMessage("You have been kicked from your faction."); + from.SendMessage("They have been kicked from their faction."); + } + else + { + from.SendMessage("They are not in a faction."); + } + } + else + { + from.SendMessage("That is not a player."); + } + } + + public static void ProcessTick() + { + var sigils = Sigil.Sigils; + + for (var i = 0; i < sigils.Count; ++i) + { + var sigil = sigils[i]; + + if (!sigil.IsBeingCorrupted && sigil.GraceStart != DateTime.MinValue && + sigil.GraceStart + Sigil.CorruptionGrace < DateTime.UtcNow) + { + if (sigil.LastMonolith is StrongholdMonolith && + (sigil.Corrupted == null || sigil.LastMonolith.Faction != sigil.Corrupted)) + { + sigil.Corrupting = sigil.LastMonolith.Faction; + sigil.CorruptionStart = DateTime.UtcNow; + } + else + { + sigil.Corrupting = null; + sigil.CorruptionStart = DateTime.MinValue; + } + + sigil.GraceStart = DateTime.MinValue; + } + + if (sigil.LastMonolith?.Sigil == null) + { + if (sigil.LastStolen + Sigil.ReturnPeriod < DateTime.UtcNow) + sigil.ReturnHome(); + } + else + { + if (sigil.IsBeingCorrupted && sigil.CorruptionStart + Sigil.CorruptionPeriod < DateTime.UtcNow) + { + sigil.Corrupted = sigil.Corrupting; + sigil.Corrupting = null; + sigil.CorruptionStart = DateTime.MinValue; + sigil.GraceStart = DateTime.MinValue; + } + else if (sigil.IsPurifying && sigil.PurificationStart + Sigil.PurificationPeriod < DateTime.UtcNow) + { + sigil.PurificationStart = DateTime.MinValue; + sigil.Corrupted = null; + sigil.Corrupting = null; + sigil.CorruptionStart = DateTime.MinValue; + sigil.GraceStart = DateTime.MinValue; + } + } + } + } + + public static void HandleDeath(Mobile mob) + { + HandleDeath(mob, null); + } + + public int AwardSilver(Mobile mob, int silver) + { + if (silver <= 0) + return 0; + + var tithed = silver * Tithe / 100; + + Silver += tithed; + + silver = silver - tithed; + + if (silver > 0) + mob.AddToBackpack(new Silver(silver)); + + return silver; + } + + public static Faction FindSmallestFaction() + { + var factions = Factions; + Faction smallest = null; + + for (var i = 0; i < factions.Count; ++i) + { + var faction = factions[i]; + + if (smallest == null || faction.Members.Count < smallest.Members.Count) + smallest = faction; + } + + return smallest; + } + + public static bool StabilityActive() + { + var factions = Factions; + + for (var i = 0; i < factions.Count; ++i) + { + var faction = factions[i]; + + if (faction.Members.Count > StabilityActivation) + return true; + } + + return false; + } + + public bool CanHandleInflux(int influx) + { + if (!StabilityActive()) + return true; + + var smallest = FindSmallestFaction(); + + if (smallest == null) + return true; // sanity + + if ((Members.Count + influx) * 100 / StabilityFactor > smallest.Members.Count) + return false; + + return true; + } + + public static void HandleDeath(Mobile victim, Mobile killer) + { + killer ??= victim.FindMostRecentDamager(true); + + var killerState = PlayerState.Find(killer); + var killerPack = killer?.Backpack; + victim.Backpack?.FindItemsByType() + .ForEach( + sigil => + { + if (killerState == null || killerPack == null) + { + sigil.ReturnHome(); + return; + } + + if (killer?.GetDistanceToSqrt(victim) > 64) + { + sigil.ReturnHome(); + killer.SendLocalizedMessage(1042230); // The sigil has gone back to its home location. + } + else if (Sigil.ExistsOn(killer)) + { + sigil.ReturnHome(); + killer?.SendLocalizedMessage( + 1010258 + ); // The sigil has gone back to its home location because you already have a sigil. + } + else if (!killerPack.TryDropItem(killer, sigil, false)) + { + sigil.ReturnHome(); + killer?.SendLocalizedMessage(1010259); // The sigil has gone home because your backpack is full. + } + } + ); + + if (killerState == null) + return; + + if (victim is BaseCreature bc) + { + var victimFaction = bc.FactionAllegiance; + + if (bc.Map == Facet && victimFaction != null && killerState.Faction != victimFaction) + { + var silver = killerState.Faction.AwardSilver(killer, bc.FactionSilverWorth); + + if (silver > 0) + killer?.SendLocalizedMessage( + 1042748, + silver.ToString("N0") + ); // Thou hast earned ~1_AMOUNT~ silver for vanquishing the vile creature. + } + + if (bc.Map == Facet && bc.GetEthicAllegiance(killer) == BaseCreature.Allegiance.Enemy) + { + var killerEPL = Player.Find(killer); + + if (killerEPL != null && 100 - killerEPL.Power > Utility.Random(100)) + { + ++killerEPL.Power; + ++killerEPL.History; + } + } + + return; + } + + var victimState = PlayerState.Find(victim); + + if (victimState == null) + return; + + if (victim.Region.IsPartOf()) + return; + + if (killer == victim || killerState.Faction != victimState.Faction) + ApplySkillLoss(victim); + + if (killerState.Faction != victimState.Faction) + { + if (victimState.KillPoints <= -6) + { + killer?.SendLocalizedMessage(501693); // This victim is not worth enough to get kill points from. + + var killerEPL = Player.Find(killer); + var victimEPL = Player.Find(victim); + + if (killerEPL != null && victimEPL?.Power > 0 && victimState.CanGiveSilverTo(killer)) + { + var powerTransfer = Math.Max(1, victimEPL.Power / 5); + + if (powerTransfer > 100 - killerEPL.Power) + powerTransfer = 100 - killerEPL.Power; + + if (powerTransfer > 0) + { + victimEPL.Power -= (powerTransfer + 1) / 2; + killerEPL.Power += powerTransfer; + + killerEPL.History += powerTransfer; + + victimState.OnGivenSilverTo(killer); + } + } + } + else + { + var award = Math.Max(victimState.KillPoints / 10, 1); + + if (award > 40) + award = 40; + + if (victimState.CanGiveSilverTo(killer)) + { + PowerFactionItem.CheckSpawn(killer, victim); + + if (victimState.KillPoints > 0) + { + victimState.IsActive = true; + + if (Utility.Random(3) < 1) + killerState.IsActive = true; + + var silver = killerState.Faction.AwardSilver(killer, award * 40); + + if (silver > 0) + killer?.SendLocalizedMessage( + 1042736, + $"{silver:N0} silver\t{victim.Name}" + ); // You have earned ~1_SILVER_AMOUNT~ pieces for vanquishing ~2_PLAYER_NAME~! + } + + victimState.KillPoints -= award; + killerState.KillPoints += award; + + var offset = award != 1 ? 0 : 2; // for pluralization + + var args = $"{award}\t{victim.Name}\t{killer?.Name}"; + + killer?.SendLocalizedMessage( + 1042737 + offset, + args + ); // Thou hast been honored with ~1_KILL_POINTS~ kill point(s) for vanquishing ~2_DEAD_PLAYER~! + victim.SendLocalizedMessage( + 1042738 + offset, + args + ); // Thou has lost ~1_KILL_POINTS~ kill point(s) to ~3_ATTACKER_NAME~ for being vanquished! + + var killerEPL = Player.Find(killer); + var victimEPL = Player.Find(victim); + + if (killerEPL != null && victimEPL?.Power > 0) + { + var powerTransfer = Math.Max(1, victimEPL.Power / 5); + + if (powerTransfer > 100 - killerEPL.Power) + powerTransfer = 100 - killerEPL.Power; + + if (powerTransfer > 0) + { + victimEPL.Power -= (powerTransfer + 1) / 2; + killerEPL.Power += powerTransfer; + + killerEPL.History += powerTransfer; + } + } + + victimState.OnGivenSilverTo(killer); + } + else + { + killer?.SendLocalizedMessage( + 1042231 + ); // You have recently defeated this enemy and thus their death brings you no honor. + } + } + } + } + + private static void EventSink_Logout(Mobile m) + { + m.Backpack?.FindItemsByType().ForEach(sigil => sigil.ReturnHome()); + } + + private static void EventSink_Login(Mobile m) => CheckLeaveTimer(m); + + public static void WriteReference(IGenericWriter writer, Faction fact) + { + var idx = Factions.IndexOf(fact); + + writer.WriteEncodedInt(idx + 1); + } + + public static Faction ReadReference(IGenericReader reader) + { + var idx = reader.ReadEncodedInt() - 1; + + return idx >= 0 && idx < Factions.Count ? Factions[idx] : null; + } + + public static Faction Find(Mobile mob, bool inherit = false, bool creatureAllegiances = false) + { + var pl = PlayerState.Find(mob); + + if (pl != null) + return pl.Faction; + + if (inherit && mob is BaseCreature bc) + { + if (bc.Controlled) + return Find(bc.ControlMaster); + if (bc.Summoned) + return Find(bc.SummonMaster); + if (creatureAllegiances && bc is BaseFactionGuard guard) + return guard.Faction; + if (creatureAllegiances) + return bc.FactionAllegiance; + } + + return null; + } + + public static Faction Parse(string name) + { + var factions = Factions; + + for (var i = 0; i < factions.Count; ++i) + { + var faction = factions[i]; + + if (Insensitive.Equals(faction.Definition.FriendlyName, name)) + return faction; + } + + return null; + } + + public static bool InSkillLoss(Mobile mob) => m_SkillLoss.ContainsKey(mob); + + public static void ApplySkillLoss(Mobile mob) + { + if (InSkillLoss(mob)) + return; + + var context = new SkillLossContext(); + m_SkillLoss[mob] = context; + + var mods = context.m_Mods = new List(); + + for (var i = 0; i < mob.Skills.Length; ++i) + { + var sk = mob.Skills[i]; + var baseValue = sk.Base; + + if (baseValue > 0) + { + SkillMod mod = new DefaultSkillMod(sk.SkillName, true, -(baseValue * SkillLossFactor)); + + mods.Add(mod); + mob.AddSkillMod(mod); + } + } + + context.m_Timer = Timer.DelayCall(SkillLossPeriod, ClearSkillLoss_Event, mob); + } + + private static void ClearSkillLoss_Event(Mobile mob) => ClearSkillLoss(mob); + + public static bool ClearSkillLoss(Mobile mob) + { + if (!m_SkillLoss.TryGetValue(mob, out var context)) + return false; + + m_SkillLoss.Remove(mob); + + var mods = context.m_Mods; + + for (var i = 0; i < mods.Count; ++i) + mob.RemoveSkillMod(mods[i]); + + context.m_Timer.Stop(); + + return true; + } + + private class BroadcastPrompt : Prompt + { + private readonly Faction m_Faction; + + public BroadcastPrompt(Faction faction) => m_Faction = faction; + + public override void OnResponse(Mobile from, string text) + { + m_Faction.EndBroadcast(from, text); + } + } + + private class SkillLossContext + { + public List m_Mods; + public Timer m_Timer; + } + } + + public enum FactionKickType + { + Kick, + Ban, + Unban + } + + public class FactionKickCommand : BaseCommand + { + private readonly FactionKickType m_KickType; + + public FactionKickCommand(FactionKickType kickType) + { + m_KickType = kickType; + + AccessLevel = AccessLevel.GameMaster; + Supports = CommandSupport.AllMobiles; + ObjectTypes = ObjectTypes.Mobiles; + + switch (m_KickType) + { + case FactionKickType.Kick: + { + Commands = new[] { "FactionKick" }; + Usage = "FactionKick"; + Description = + "Kicks the targeted player out of his current faction. This does not prevent them from rejoining."; + break; + } + case FactionKickType.Ban: + { + Commands = new[] { "FactionBan" }; + Usage = "FactionBan"; + Description = + "Bans the account of a targeted player from joining factions. All players on the account are removed from their current faction, if any."; + break; + } + case FactionKickType.Unban: + { + Commands = new[] { "FactionUnban" }; + Usage = "FactionUnban"; + Description = "Unbans the account of a targeted player from joining factions."; + break; + } + } + } + + public override void Execute(CommandEventArgs e, object obj) + { + var mob = (Mobile)obj; + + switch (m_KickType) + { + case FactionKickType.Kick: + { + var pl = PlayerState.Find(mob); + + if (pl != null) + { + pl.Faction.RemoveMember(mob); + mob.SendMessage("You have been kicked from your faction."); + AddResponse("They have been kicked from their faction."); + } + else + { + LogFailure("They are not in a faction."); + } + + break; + } + case FactionKickType.Ban: + { + if (mob.Account is Account acct) + { + if (acct.GetTag("FactionBanned") == null) + { + acct.SetTag("FactionBanned", "true"); + AddResponse("The account has been banned from joining factions."); + } + else + { + AddResponse("The account is already banned from joining factions."); + } + + for (var i = 0; i < acct.Length; ++i) + { + mob = acct[i]; + + if (mob != null) + { + var pl = PlayerState.Find(mob); + + if (pl != null) + { + pl.Faction.RemoveMember(mob); + mob.SendMessage("You have been kicked from your faction."); + AddResponse("They have been kicked from their faction."); + } + } + } + } + else + { + LogFailure("They have no assigned account."); + } + + break; + } + case FactionKickType.Unban: + { + if (mob.Account is Account acct) + { + if (acct.GetTag("FactionBanned") == null) + { + AddResponse("The account is not already banned from joining factions."); + } + else + { + acct.RemoveTag("FactionBanned"); + AddResponse("The account may now freely join factions."); + } + } + else + { + LogFailure("They have no assigned account."); + } + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Core/FactionItem.cs b/Projects/UOContent/Engines/Factions/Core/FactionItem.cs index 031f206fd..17eb4f68b 100644 --- a/Projects/UOContent/Engines/Factions/Core/FactionItem.cs +++ b/Projects/UOContent/Engines/Factions/Core/FactionItem.cs @@ -1,137 +1,138 @@ -using System; - -namespace Server.Factions -{ - public interface IFactionItem - { - FactionItem FactionItemState { get; set; } - } - - public class FactionItem - { - public static readonly TimeSpan ExpirationPeriod = TimeSpan.FromDays(21.0); - - public FactionItem(Item item, Faction faction) - { - Item = item; - Faction = faction; - } - - public FactionItem(IGenericReader reader, Faction faction) - { - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 0: - { - Item = reader.ReadItem(); - Expiration = reader.ReadDateTime(); - break; - } - } - - Faction = faction; - } - - public Item Item { get; } - - public Faction Faction { get; } - - public DateTime Expiration { get; private set; } - - public bool HasExpired - { - get - { - if (Item?.Deleted != false) - return true; - - return Expiration != DateTime.MinValue && DateTime.UtcNow >= Expiration; - } - } - - public void StartExpiration() - { - Expiration = DateTime.UtcNow + ExpirationPeriod; - } - - public void CheckAttach() - { - if (!HasExpired) - Attach(); - else - Detach(); - } - - public void Attach() - { - if (Item is IFactionItem item) - item.FactionItemState = this; - - Faction?.State.FactionItems.Add(this); - } - - public void Detach() - { - if (Item is IFactionItem item) - item.FactionItemState = null; - - if (Faction?.State.FactionItems.Contains(this) == true) - Faction.State.FactionItems.Remove(this); - } - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); - - writer.Write(Item); - writer.Write(Expiration); - } - - public static int GetMaxWearables(Mobile mob) - { - PlayerState pl = PlayerState.Find(mob); - - return pl == null ? 0 : pl.Faction.IsCommander(mob) ? 9 : pl.Rank.MaxWearables; - } - - public static FactionItem Find(Item item) - { - if (item is IFactionItem factionItem) - { - FactionItem state = factionItem.FactionItemState; - - if (state?.HasExpired == true) - { - state.Detach(); - state = null; - } - - return state; - } - - return null; - } - - public static Item Imbue(Item item, Faction faction, bool expire, int hue) - { - if (!(item is IFactionItem)) - return item; - - FactionItem state = Find(item); - - if (state == null) - { - state = new FactionItem(item, faction); - state.Attach(); - } - - if (expire) - state.StartExpiration(); - - item.Hue = hue; - return item; - } - } -} +using System; + +namespace Server.Factions +{ + public interface IFactionItem + { + FactionItem FactionItemState { get; set; } + } + + public class FactionItem + { + public static readonly TimeSpan ExpirationPeriod = TimeSpan.FromDays(21.0); + + public FactionItem(Item item, Faction faction) + { + Item = item; + Faction = faction; + } + + public FactionItem(IGenericReader reader, Faction faction) + { + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 0: + { + Item = reader.ReadItem(); + Expiration = reader.ReadDateTime(); + break; + } + } + + Faction = faction; + } + + public Item Item { get; } + + public Faction Faction { get; } + + public DateTime Expiration { get; private set; } + + public bool HasExpired + { + get + { + if (Item?.Deleted != false) + return true; + + return Expiration != DateTime.MinValue && DateTime.UtcNow >= Expiration; + } + } + + public void StartExpiration() + { + Expiration = DateTime.UtcNow + ExpirationPeriod; + } + + public void CheckAttach() + { + if (!HasExpired) + Attach(); + else + Detach(); + } + + public void Attach() + { + if (Item is IFactionItem item) + item.FactionItemState = this; + + Faction?.State.FactionItems.Add(this); + } + + public void Detach() + { + if (Item is IFactionItem item) + item.FactionItemState = null; + + if (Faction?.State.FactionItems.Contains(this) == true) + Faction.State.FactionItems.Remove(this); + } + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); + + writer.Write(Item); + writer.Write(Expiration); + } + + public static int GetMaxWearables(Mobile mob) + { + var pl = PlayerState.Find(mob); + + return pl == null ? 0 : + pl.Faction.IsCommander(mob) ? 9 : pl.Rank.MaxWearables; + } + + public static FactionItem Find(Item item) + { + if (item is IFactionItem factionItem) + { + var state = factionItem.FactionItemState; + + if (state?.HasExpired == true) + { + state.Detach(); + state = null; + } + + return state; + } + + return null; + } + + public static Item Imbue(Item item, Faction faction, bool expire, int hue) + { + if (!(item is IFactionItem)) + return item; + + var state = Find(item); + + if (state == null) + { + state = new FactionItem(item, faction); + state.Attach(); + } + + if (expire) + state.StartExpiration(); + + item.Hue = hue; + return item; + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Core/FactionState.cs b/Projects/UOContent/Engines/Factions/Core/FactionState.cs index 875f16fef..73e958f66 100644 --- a/Projects/UOContent/Engines/Factions/Core/FactionState.cs +++ b/Projects/UOContent/Engines/Factions/Core/FactionState.cs @@ -1,273 +1,273 @@ -using System; -using System.Collections.Generic; - -namespace Server.Factions -{ - public class FactionState - { - private const int BroadcastsPerPeriod = 2; - private static readonly TimeSpan BroadcastPeriod = TimeSpan.FromHours(1.0); - private Mobile m_Commander; - private readonly Faction m_Faction; - - private readonly DateTime[] m_LastBroadcasts = new DateTime[BroadcastsPerPeriod]; - - public FactionState(Faction faction) - { - m_Faction = faction; - Tithe = 50; - Members = new List(); - Election = new Election(faction); - FactionItems = new List(); - Traps = new List(); - } - - public FactionState(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 5: - { - LastAtrophy = reader.ReadDateTime(); - goto case 4; - } - case 4: - { - int count = reader.ReadEncodedInt(); - - for (int i = 0; i < count; ++i) - { - DateTime time = reader.ReadDateTime(); - - if (i < m_LastBroadcasts.Length) - m_LastBroadcasts[i] = time; - } - - goto case 3; - } - case 3: - case 2: - case 1: - { - Election = new Election(reader); - - goto case 0; - } - case 0: - { - m_Faction = Faction.ReadReference(reader); - - m_Commander = reader.ReadMobile(); - - if (version < 5) - LastAtrophy = DateTime.UtcNow; - - if (version < 4) - { - DateTime time = reader.ReadDateTime(); - - if (m_LastBroadcasts.Length > 0) - m_LastBroadcasts[0] = time; - } - - Tithe = reader.ReadEncodedInt(); - Silver = reader.ReadEncodedInt(); - - int memberCount = reader.ReadEncodedInt(); - - Members = new List(); - - for (int i = 0; i < memberCount; ++i) - { - PlayerState pl = new PlayerState(reader, m_Faction, Members); - - if (pl.Mobile != null) - Members.Add(pl); - } - - m_Faction.State = this; - - m_Faction.ZeroRankOffset = Members.Count; - Members.Sort(); - - for (int i = Members.Count - 1; i >= 0; i--) - { - PlayerState player = Members[i]; - - if (player.KillPoints <= 0) - m_Faction.ZeroRankOffset = i; - else - player.RankIndex = i; - } - - FactionItems = new List(); - - if (version >= 2) - { - int factionItemCount = reader.ReadEncodedInt(); - - for (int i = 0; i < factionItemCount; ++i) - { - FactionItem factionItem = new FactionItem(reader, m_Faction); - - Timer.DelayCall(factionItem.CheckAttach); // sandbox attachment - } - } - - Traps = new List(); - - if (version >= 3) - { - int factionTrapCount = reader.ReadEncodedInt(); - - for (int i = 0; i < factionTrapCount; ++i) - if (reader.ReadItem() is BaseFactionTrap trap && !trap.CheckDecay()) - Traps.Add(trap); - } - - break; - } - } - - if (version < 1) - Election = new Election(m_Faction); - } - - public DateTime LastAtrophy { get; set; } - - public bool FactionMessageReady - { - get - { - for (int i = 0; i < m_LastBroadcasts.Length; ++i) - if (DateTime.UtcNow >= m_LastBroadcasts[i] + BroadcastPeriod) - return true; - - return false; - } - } - - public bool IsAtrophyReady => DateTime.UtcNow >= LastAtrophy + TimeSpan.FromHours(47.0); - - public List FactionItems { get; set; } - - public List Traps { get; set; } - - public Election Election { get; set; } - - public Mobile Commander - { - get => m_Commander; - set - { - m_Commander?.InvalidateProperties(); - - m_Commander = value; - - if (m_Commander != null) - { - m_Commander.SendLocalizedMessage(1042227); // You have been elected Commander of your faction - - m_Commander.InvalidateProperties(); - - PlayerState pl = PlayerState.Find(m_Commander); - - if (pl?.Finance != null) - pl.Finance.Finance = null; - - if (pl?.Sheriff != null) - pl.Sheriff.Sheriff = null; - } - } - } - - public int Tithe { get; set; } - - public int Silver { get; set; } - - public List Members { get; set; } - - public int CheckAtrophy() - { - if (DateTime.UtcNow < LastAtrophy + TimeSpan.FromHours(47.0)) - return 0; - - int distrib = 0; - LastAtrophy = DateTime.UtcNow; - - List members = new List(Members); - - for (int i = 0; i < members.Count; ++i) - { - PlayerState ps = members[i]; - - if (ps.IsActive) - { - ps.IsActive = false; - continue; - } - - if (ps.KillPoints > 0) - { - int atrophy = (ps.KillPoints + 9) / 10; - ps.KillPoints -= atrophy; - distrib += atrophy; - } - } - - return distrib; - } - - public void RegisterBroadcast() - { - for (int i = 0; i < m_LastBroadcasts.Length; ++i) - if (DateTime.UtcNow >= m_LastBroadcasts[i] + BroadcastPeriod) - { - m_LastBroadcasts[i] = DateTime.UtcNow; - break; - } - } - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(5); // version - - writer.Write(LastAtrophy); - - writer.WriteEncodedInt(m_LastBroadcasts.Length); - - for (int i = 0; i < m_LastBroadcasts.Length; ++i) - writer.Write(m_LastBroadcasts[i]); - - Election.Serialize(writer); - - Faction.WriteReference(writer, m_Faction); - - writer.Write(m_Commander); - - writer.WriteEncodedInt(Tithe); - writer.WriteEncodedInt(Silver); - - writer.WriteEncodedInt(Members.Count); - - for (int i = 0; i < Members.Count; ++i) - { - PlayerState pl = Members[i]; - - pl.Serialize(writer); - } - - writer.WriteEncodedInt(FactionItems.Count); - - for (int i = 0; i < FactionItems.Count; ++i) - FactionItems[i].Serialize(writer); - - writer.WriteEncodedInt(Traps.Count); - - for (int i = 0; i < Traps.Count; ++i) - writer.Write(Traps[i]); - } - } -} +using System; +using System.Collections.Generic; + +namespace Server.Factions +{ + public class FactionState + { + private const int BroadcastsPerPeriod = 2; + private static readonly TimeSpan BroadcastPeriod = TimeSpan.FromHours(1.0); + private readonly Faction m_Faction; + + private readonly DateTime[] m_LastBroadcasts = new DateTime[BroadcastsPerPeriod]; + private Mobile m_Commander; + + public FactionState(Faction faction) + { + m_Faction = faction; + Tithe = 50; + Members = new List(); + Election = new Election(faction); + FactionItems = new List(); + Traps = new List(); + } + + public FactionState(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 5: + { + LastAtrophy = reader.ReadDateTime(); + goto case 4; + } + case 4: + { + var count = reader.ReadEncodedInt(); + + for (var i = 0; i < count; ++i) + { + var time = reader.ReadDateTime(); + + if (i < m_LastBroadcasts.Length) + m_LastBroadcasts[i] = time; + } + + goto case 3; + } + case 3: + case 2: + case 1: + { + Election = new Election(reader); + + goto case 0; + } + case 0: + { + m_Faction = Faction.ReadReference(reader); + + m_Commander = reader.ReadMobile(); + + if (version < 5) + LastAtrophy = DateTime.UtcNow; + + if (version < 4) + { + var time = reader.ReadDateTime(); + + if (m_LastBroadcasts.Length > 0) + m_LastBroadcasts[0] = time; + } + + Tithe = reader.ReadEncodedInt(); + Silver = reader.ReadEncodedInt(); + + var memberCount = reader.ReadEncodedInt(); + + Members = new List(); + + for (var i = 0; i < memberCount; ++i) + { + var pl = new PlayerState(reader, m_Faction, Members); + + if (pl.Mobile != null) + Members.Add(pl); + } + + m_Faction.State = this; + + m_Faction.ZeroRankOffset = Members.Count; + Members.Sort(); + + for (var i = Members.Count - 1; i >= 0; i--) + { + var player = Members[i]; + + if (player.KillPoints <= 0) + m_Faction.ZeroRankOffset = i; + else + player.RankIndex = i; + } + + FactionItems = new List(); + + if (version >= 2) + { + var factionItemCount = reader.ReadEncodedInt(); + + for (var i = 0; i < factionItemCount; ++i) + { + var factionItem = new FactionItem(reader, m_Faction); + + Timer.DelayCall(factionItem.CheckAttach); // sandbox attachment + } + } + + Traps = new List(); + + if (version >= 3) + { + var factionTrapCount = reader.ReadEncodedInt(); + + for (var i = 0; i < factionTrapCount; ++i) + if (reader.ReadItem() is BaseFactionTrap trap && !trap.CheckDecay()) + Traps.Add(trap); + } + + break; + } + } + + if (version < 1) + Election = new Election(m_Faction); + } + + public DateTime LastAtrophy { get; set; } + + public bool FactionMessageReady + { + get + { + for (var i = 0; i < m_LastBroadcasts.Length; ++i) + if (DateTime.UtcNow >= m_LastBroadcasts[i] + BroadcastPeriod) + return true; + + return false; + } + } + + public bool IsAtrophyReady => DateTime.UtcNow >= LastAtrophy + TimeSpan.FromHours(47.0); + + public List FactionItems { get; set; } + + public List Traps { get; set; } + + public Election Election { get; set; } + + public Mobile Commander + { + get => m_Commander; + set + { + m_Commander?.InvalidateProperties(); + + m_Commander = value; + + if (m_Commander != null) + { + m_Commander.SendLocalizedMessage(1042227); // You have been elected Commander of your faction + + m_Commander.InvalidateProperties(); + + var pl = PlayerState.Find(m_Commander); + + if (pl?.Finance != null) + pl.Finance.Finance = null; + + if (pl?.Sheriff != null) + pl.Sheriff.Sheriff = null; + } + } + } + + public int Tithe { get; set; } + + public int Silver { get; set; } + + public List Members { get; set; } + + public int CheckAtrophy() + { + if (DateTime.UtcNow < LastAtrophy + TimeSpan.FromHours(47.0)) + return 0; + + var distrib = 0; + LastAtrophy = DateTime.UtcNow; + + var members = new List(Members); + + for (var i = 0; i < members.Count; ++i) + { + var ps = members[i]; + + if (ps.IsActive) + { + ps.IsActive = false; + continue; + } + + if (ps.KillPoints > 0) + { + var atrophy = (ps.KillPoints + 9) / 10; + ps.KillPoints -= atrophy; + distrib += atrophy; + } + } + + return distrib; + } + + public void RegisterBroadcast() + { + for (var i = 0; i < m_LastBroadcasts.Length; ++i) + if (DateTime.UtcNow >= m_LastBroadcasts[i] + BroadcastPeriod) + { + m_LastBroadcasts[i] = DateTime.UtcNow; + break; + } + } + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(5); // version + + writer.Write(LastAtrophy); + + writer.WriteEncodedInt(m_LastBroadcasts.Length); + + for (var i = 0; i < m_LastBroadcasts.Length; ++i) + writer.Write(m_LastBroadcasts[i]); + + Election.Serialize(writer); + + Faction.WriteReference(writer, m_Faction); + + writer.Write(m_Commander); + + writer.WriteEncodedInt(Tithe); + writer.WriteEncodedInt(Silver); + + writer.WriteEncodedInt(Members.Count); + + for (var i = 0; i < Members.Count; ++i) + { + var pl = Members[i]; + + pl.Serialize(writer); + } + + writer.WriteEncodedInt(FactionItems.Count); + + for (var i = 0; i < FactionItems.Count; ++i) + FactionItems[i].Serialize(writer); + + writer.WriteEncodedInt(Traps.Count); + + for (var i = 0; i < Traps.Count; ++i) + writer.Write(Traps[i]); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Core/Generator.cs b/Projects/UOContent/Engines/Factions/Core/Generator.cs index 1e5a6c60c..cb637ddc5 100644 --- a/Projects/UOContent/Engines/Factions/Core/Generator.cs +++ b/Projects/UOContent/Engines/Factions/Core/Generator.cs @@ -1,71 +1,71 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Server.Factions -{ - public class Generator - { - public static void Initialize() - { - CommandSystem.Register("GenerateFactions", AccessLevel.Administrator, GenerateFactions_OnCommand); - } - - public static void GenerateFactions_OnCommand(CommandEventArgs e) - { - new FactionPersistance(); - - List factions = Faction.Factions; - - foreach (Faction faction in factions) - Generate(faction); - - List towns = Town.Towns; - - foreach (Town town in towns) - Generate(town); - } - - public static void Generate(Town town) - { - Map facet = Faction.Facet; - - TownDefinition def = town.Definition; - - if (!CheckExistance(def.Monolith, facet, typeof(TownMonolith))) - { - TownMonolith mono = new TownMonolith(town); - mono.MoveToWorld(def.Monolith, facet); - mono.Sigil = new Sigil(town); - } - - if (!CheckExistance(def.TownStone, facet, typeof(TownStone))) - new TownStone(town).MoveToWorld(def.TownStone, facet); - } - - public static void Generate(Faction faction) - { - Map facet = Faction.Facet; - - List towns = Town.Towns; - - StrongholdDefinition stronghold = faction.Definition.Stronghold; - - if (!CheckExistance(stronghold.JoinStone, facet, typeof(JoinStone))) - new JoinStone(faction).MoveToWorld(stronghold.JoinStone, facet); - - if (!CheckExistance(stronghold.FactionStone, facet, typeof(FactionStone))) - new FactionStone(faction).MoveToWorld(stronghold.FactionStone, facet); - - for (int i = 0; i < stronghold.Monoliths.Length; ++i) - { - Point3D monolith = stronghold.Monoliths[i]; - - if (!CheckExistance(monolith, facet, typeof(StrongholdMonolith))) - new StrongholdMonolith(towns[i], faction).MoveToWorld(monolith, facet); - } - } - - private static bool CheckExistance(Point3D loc, Map facet, Type type) => facet.GetItemsInRange(loc, 0).Any(type.IsInstanceOfType); - } -} \ No newline at end of file +using System; +using System.Linq; + +namespace Server.Factions +{ + public class Generator + { + public static void Initialize() + { + CommandSystem.Register("GenerateFactions", AccessLevel.Administrator, GenerateFactions_OnCommand); + } + + public static void GenerateFactions_OnCommand(CommandEventArgs e) + { + new FactionPersistance(); + + var factions = Faction.Factions; + + foreach (var faction in factions) + Generate(faction); + + var towns = Town.Towns; + + foreach (var town in towns) + Generate(town); + } + + public static void Generate(Town town) + { + var facet = Faction.Facet; + + var def = town.Definition; + + if (!CheckExistance(def.Monolith, facet, typeof(TownMonolith))) + { + var mono = new TownMonolith(town); + mono.MoveToWorld(def.Monolith, facet); + mono.Sigil = new Sigil(town); + } + + if (!CheckExistance(def.TownStone, facet, typeof(TownStone))) + new TownStone(town).MoveToWorld(def.TownStone, facet); + } + + public static void Generate(Faction faction) + { + var facet = Faction.Facet; + + var towns = Town.Towns; + + var stronghold = faction.Definition.Stronghold; + + if (!CheckExistance(stronghold.JoinStone, facet, typeof(JoinStone))) + new JoinStone(faction).MoveToWorld(stronghold.JoinStone, facet); + + if (!CheckExistance(stronghold.FactionStone, facet, typeof(FactionStone))) + new FactionStone(faction).MoveToWorld(stronghold.FactionStone, facet); + + for (var i = 0; i < stronghold.Monoliths.Length; ++i) + { + var monolith = stronghold.Monoliths[i]; + + if (!CheckExistance(monolith, facet, typeof(StrongholdMonolith))) + new StrongholdMonolith(towns[i], faction).MoveToWorld(monolith, facet); + } + } + + private static bool CheckExistance(Point3D loc, Map facet, Type type) => + facet.GetItemsInRange(loc, 0).Any(type.IsInstanceOfType); + } +} diff --git a/Projects/UOContent/Engines/Factions/Core/GuardList.cs b/Projects/UOContent/Engines/Factions/Core/GuardList.cs index eb899ea79..3ea41b8f4 100644 --- a/Projects/UOContent/Engines/Factions/Core/GuardList.cs +++ b/Projects/UOContent/Engines/Factions/Core/GuardList.cs @@ -1,30 +1,30 @@ -using System.Collections.Generic; -using Server.Utilities; - -namespace Server.Factions -{ - public class GuardList - { - public GuardList(GuardDefinition definition) - { - Definition = definition; - Guards = new List(); - } - - public GuardDefinition Definition { get; } - - public List Guards { get; } - - public BaseFactionGuard Construct() - { - try - { - return ActivatorUtil.CreateInstance(Definition.Type) as BaseFactionGuard; - } - catch - { - return null; - } - } - } -} +using System.Collections.Generic; +using Server.Utilities; + +namespace Server.Factions +{ + public class GuardList + { + public GuardList(GuardDefinition definition) + { + Definition = definition; + Guards = new List(); + } + + public GuardDefinition Definition { get; } + + public List Guards { get; } + + public BaseFactionGuard Construct() + { + try + { + return ActivatorUtil.CreateInstance(Definition.Type) as BaseFactionGuard; + } + catch + { + return null; + } + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Core/Keywords.cs b/Projects/UOContent/Engines/Factions/Core/Keywords.cs index de0c9adf1..21a6fb1c1 100644 --- a/Projects/UOContent/Engines/Factions/Core/Keywords.cs +++ b/Projects/UOContent/Engines/Factions/Core/Keywords.cs @@ -1,154 +1,164 @@ -using System; -using Server.Mobiles; -using Server.Network; - -namespace Server.Factions -{ - public static class Keywords - { - public static void Initialize() - { - EventSink.Speech += EventSink_Speech; - } - - private static void ShowScore_Sandbox(PlayerState pl) - { - pl?.Mobile.PublicOverheadMessage(MessageType.Regular, pl.Mobile.SpeechHue, true, - pl.KillPoints.ToString("N0")); // NOTE: Added 'N0' - } - - private static void EventSink_Speech(SpeechEventArgs e) - { - Mobile from = e.Mobile; - int[] keywords = e.Keywords; - - for (int i = 0; i < keywords.Length; ++i) - switch (keywords[i]) - { - case 0x00E4: // *i wish to access the city treasury* - { - Town town = Town.FromRegion(from.Region); - - if (town?.IsFinance(from) != true || !from.Alive) - break; - - if (FactionGump.Exists(from)) - from.SendLocalizedMessage(1042160); // You already have a faction menu open. - else if (town.Owner != null && from is PlayerMobile mobile) - mobile.SendGump(new FinanceGump(mobile, town.Owner, town)); - - break; - } - case 0x0ED: // *i am sheriff* - { - Town town = Town.FromRegion(from.Region); - - if (town?.IsSheriff(from) != true || !from.Alive) - break; - - if (FactionGump.Exists(from)) - from.SendLocalizedMessage(1042160); // You already have a faction menu open. - else if (town.Owner != null) - from.SendGump(new SheriffGump((PlayerMobile)from, town.Owner, town)); - - break; - } - case 0x00EF: // *you are fired* - { - Town town = Town.FromRegion(from.Region); - - if (town == null) - break; - - if (town.IsFinance(from) || town.IsSheriff(from)) - town.BeginOrderFiring(from); - - break; - } - case 0x00E5: // *i wish to resign as finance minister* - { - PlayerState pl = PlayerState.Find(from); - - if (pl?.Finance != null) - { - pl.Finance.Finance = null; - from.SendLocalizedMessage(1005081); // You have been fired as Finance Minister - } - - break; - } - case 0x00EE: // *i wish to resign as sheriff* - { - PlayerState pl = PlayerState.Find(from); - - if (pl?.Sheriff != null) - { - pl.Sheriff.Sheriff = null; - from.SendLocalizedMessage(1010270); // You have been fired as Sheriff - } - - break; - } - case 0x00E9: // *what is my faction term status* - { - PlayerState pl = PlayerState.Find(from); - - if (pl?.IsLeaving == true) - { - if (Faction.CheckLeaveTimer(from)) - break; - - TimeSpan remaining = pl.Leaving + Faction.LeavePeriod - DateTime.UtcNow; - - if (remaining.TotalDays >= 1) - from.SendLocalizedMessage(1042743, - remaining.TotalDays - .ToString("N0")); // Your term of service will come to an end in ~1_DAYS~ days. - else if (remaining.TotalHours >= 1) - from.SendLocalizedMessage(1042741, - remaining.TotalHours - .ToString("N0")); // Your term of service will come to an end in ~1_HOURS~ hours. - else - from.SendLocalizedMessage( - 1042742); // Your term of service will come to an end in less than one hour. - } - else if (pl != null) - { - from.SendLocalizedMessage(1042233); // You are not in the process of quitting the faction. - } - - break; - } - case 0x00EA: // *message faction* - { - Faction faction = Faction.Find(from); - - if (faction?.IsCommander(from) != true) - break; - - if (from.AccessLevel == AccessLevel.Player && !faction.FactionMessageReady) - from.SendLocalizedMessage( - 1010264); // The required time has not yet passed since the last message was sent - else - faction.BeginBroadcast(from); - - break; - } - case 0x00EC: // *showscore* - { - PlayerState pl = PlayerState.Find(from); - - if (pl != null) - Timer.DelayCall(ShowScore_Sandbox, pl); - - break; - } - case 0x0178: // i honor your leadership - { - Faction.Find(from)?.BeginHonorLeadership(from); - break; - } - } - } - } -} +using System; +using Server.Mobiles; +using Server.Network; + +namespace Server.Factions +{ + public static class Keywords + { + public static void Initialize() + { + EventSink.Speech += EventSink_Speech; + } + + private static void ShowScore_Sandbox(PlayerState pl) + { + pl?.Mobile.PublicOverheadMessage( + MessageType.Regular, + pl.Mobile.SpeechHue, + true, + pl.KillPoints.ToString("N0") + ); // NOTE: Added 'N0' + } + + private static void EventSink_Speech(SpeechEventArgs e) + { + var from = e.Mobile; + var keywords = e.Keywords; + + for (var i = 0; i < keywords.Length; ++i) + switch (keywords[i]) + { + case 0x00E4: // *i wish to access the city treasury* + { + var town = Town.FromRegion(from.Region); + + if (town?.IsFinance(from) != true || !from.Alive) + break; + + if (FactionGump.Exists(from)) + from.SendLocalizedMessage(1042160); // You already have a faction menu open. + else if (town.Owner != null && from is PlayerMobile mobile) + mobile.SendGump(new FinanceGump(mobile, town.Owner, town)); + + break; + } + case 0x0ED: // *i am sheriff* + { + var town = Town.FromRegion(from.Region); + + if (town?.IsSheriff(from) != true || !from.Alive) + break; + + if (FactionGump.Exists(from)) + from.SendLocalizedMessage(1042160); // You already have a faction menu open. + else if (town.Owner != null) + from.SendGump(new SheriffGump((PlayerMobile)from, town.Owner, town)); + + break; + } + case 0x00EF: // *you are fired* + { + var town = Town.FromRegion(from.Region); + + if (town == null) + break; + + if (town.IsFinance(from) || town.IsSheriff(from)) + town.BeginOrderFiring(from); + + break; + } + case 0x00E5: // *i wish to resign as finance minister* + { + var pl = PlayerState.Find(from); + + if (pl?.Finance != null) + { + pl.Finance.Finance = null; + from.SendLocalizedMessage(1005081); // You have been fired as Finance Minister + } + + break; + } + case 0x00EE: // *i wish to resign as sheriff* + { + var pl = PlayerState.Find(from); + + if (pl?.Sheriff != null) + { + pl.Sheriff.Sheriff = null; + from.SendLocalizedMessage(1010270); // You have been fired as Sheriff + } + + break; + } + case 0x00E9: // *what is my faction term status* + { + var pl = PlayerState.Find(from); + + if (pl?.IsLeaving == true) + { + if (Faction.CheckLeaveTimer(from)) + break; + + var remaining = pl.Leaving + Faction.LeavePeriod - DateTime.UtcNow; + + if (remaining.TotalDays >= 1) + from.SendLocalizedMessage( + 1042743, + remaining.TotalDays + .ToString("N0") + ); // Your term of service will come to an end in ~1_DAYS~ days. + else if (remaining.TotalHours >= 1) + from.SendLocalizedMessage( + 1042741, + remaining.TotalHours + .ToString("N0") + ); // Your term of service will come to an end in ~1_HOURS~ hours. + else + from.SendLocalizedMessage( + 1042742 + ); // Your term of service will come to an end in less than one hour. + } + else if (pl != null) + { + from.SendLocalizedMessage(1042233); // You are not in the process of quitting the faction. + } + + break; + } + case 0x00EA: // *message faction* + { + var faction = Faction.Find(from); + + if (faction?.IsCommander(from) != true) + break; + + if (from.AccessLevel == AccessLevel.Player && !faction.FactionMessageReady) + from.SendLocalizedMessage( + 1010264 + ); // The required time has not yet passed since the last message was sent + else + faction.BeginBroadcast(from); + + break; + } + case 0x00EC: // *showscore* + { + var pl = PlayerState.Find(from); + + if (pl != null) + Timer.DelayCall(ShowScore_Sandbox, pl); + + break; + } + case 0x0178: // i honor your leadership + { + Faction.Find(from)?.BeginHonorLeadership(from); + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Core/MerchantTitles.cs b/Projects/UOContent/Engines/Factions/Core/MerchantTitles.cs index c7195bd7b..f39e74ad7 100644 --- a/Projects/UOContent/Engines/Factions/Core/MerchantTitles.cs +++ b/Projects/UOContent/Engines/Factions/Core/MerchantTitles.cs @@ -1,89 +1,115 @@ -namespace Server.Factions -{ - public enum MerchantTitle - { - None, - Scribe, - Carpenter, - Blacksmith, - Bowyer, - Tialor - } - - public class MerchantTitleInfo - { - public MerchantTitleInfo(SkillName skill, double requirement, TextDefinition title, TextDefinition label, - TextDefinition assigned) - { - Skill = skill; - Requirement = requirement; - Title = title; - Label = label; - Assigned = assigned; - } - - public SkillName Skill { get; } - - public double Requirement { get; } - - public TextDefinition Title { get; } - - public TextDefinition Label { get; } - - public TextDefinition Assigned { get; } - } - - public class MerchantTitles - { - public static MerchantTitleInfo[] Info { get; } = - { - new MerchantTitleInfo(SkillName.Inscribe, 90.0, new TextDefinition(1060773, "Scribe"), - new TextDefinition(1011468, "SCRIBE"), - new TextDefinition(1010121, "You now have the faction title of scribe")), - new MerchantTitleInfo(SkillName.Carpentry, 90.0, new TextDefinition(1060774, "Carpenter"), - new TextDefinition(1011469, "CARPENTER"), - new TextDefinition(1010122, "You now have the faction title of carpenter")), - new MerchantTitleInfo(SkillName.Tinkering, 90.0, new TextDefinition(1022984, "Tinker"), - new TextDefinition(1011470, "TINKER"), - new TextDefinition(1010123, "You now have the faction title of tinker")), - new MerchantTitleInfo(SkillName.Blacksmith, 90.0, new TextDefinition(1023016, "Blacksmith"), - new TextDefinition(1011471, "BLACKSMITH"), - new TextDefinition(1010124, "You now have the faction title of blacksmith")), - new MerchantTitleInfo(SkillName.Fletching, 90.0, new TextDefinition(1023022, "Bowyer"), - new TextDefinition(1011472, "BOWYER"), - new TextDefinition(1010125, "You now have the faction title of Bowyer")), - new MerchantTitleInfo(SkillName.Tailoring, 90.0, new TextDefinition(1022982, "Tailor"), - new TextDefinition(1018300, "TAILOR"), - new TextDefinition(1042162, "You now have the faction title of Tailor")) - }; - - public static MerchantTitleInfo GetInfo(MerchantTitle title) - { - int idx = (int)title - 1; - - if (idx >= 0 && idx < Info.Length) - return Info[idx]; - - return null; - } - - public static bool HasMerchantQualifications(Mobile mob) - { - for (int i = 0; i < Info.Length; ++i) - if (IsQualified(mob, Info[i])) - return true; - - return false; - } - - public static bool IsQualified(Mobile mob, MerchantTitle title) => IsQualified(mob, GetInfo(title)); - - public static bool IsQualified(Mobile mob, MerchantTitleInfo info) - { - if (mob == null || info == null) - return false; - - return mob.Skills[info.Skill].Value >= info.Requirement; - } - } -} \ No newline at end of file +namespace Server.Factions +{ + public enum MerchantTitle + { + None, + Scribe, + Carpenter, + Blacksmith, + Bowyer, + Tialor + } + + public class MerchantTitleInfo + { + public MerchantTitleInfo( + SkillName skill, double requirement, TextDefinition title, TextDefinition label, + TextDefinition assigned + ) + { + Skill = skill; + Requirement = requirement; + Title = title; + Label = label; + Assigned = assigned; + } + + public SkillName Skill { get; } + + public double Requirement { get; } + + public TextDefinition Title { get; } + + public TextDefinition Label { get; } + + public TextDefinition Assigned { get; } + } + + public class MerchantTitles + { + public static MerchantTitleInfo[] Info { get; } = + { + new MerchantTitleInfo( + SkillName.Inscribe, + 90.0, + new TextDefinition(1060773, "Scribe"), + new TextDefinition(1011468, "SCRIBE"), + new TextDefinition(1010121, "You now have the faction title of scribe") + ), + new MerchantTitleInfo( + SkillName.Carpentry, + 90.0, + new TextDefinition(1060774, "Carpenter"), + new TextDefinition(1011469, "CARPENTER"), + new TextDefinition(1010122, "You now have the faction title of carpenter") + ), + new MerchantTitleInfo( + SkillName.Tinkering, + 90.0, + new TextDefinition(1022984, "Tinker"), + new TextDefinition(1011470, "TINKER"), + new TextDefinition(1010123, "You now have the faction title of tinker") + ), + new MerchantTitleInfo( + SkillName.Blacksmith, + 90.0, + new TextDefinition(1023016, "Blacksmith"), + new TextDefinition(1011471, "BLACKSMITH"), + new TextDefinition(1010124, "You now have the faction title of blacksmith") + ), + new MerchantTitleInfo( + SkillName.Fletching, + 90.0, + new TextDefinition(1023022, "Bowyer"), + new TextDefinition(1011472, "BOWYER"), + new TextDefinition(1010125, "You now have the faction title of Bowyer") + ), + new MerchantTitleInfo( + SkillName.Tailoring, + 90.0, + new TextDefinition(1022982, "Tailor"), + new TextDefinition(1018300, "TAILOR"), + new TextDefinition(1042162, "You now have the faction title of Tailor") + ) + }; + + public static MerchantTitleInfo GetInfo(MerchantTitle title) + { + var idx = (int)title - 1; + + if (idx >= 0 && idx < Info.Length) + return Info[idx]; + + return null; + } + + public static bool HasMerchantQualifications(Mobile mob) + { + for (var i = 0; i < Info.Length; ++i) + if (IsQualified(mob, Info[i])) + return true; + + return false; + } + + public static bool IsQualified(Mobile mob, MerchantTitle title) => IsQualified(mob, GetInfo(title)); + + public static bool IsQualified(Mobile mob, MerchantTitleInfo info) + { + if (mob == null || info == null) + return false; + + return mob.Skills[info.Skill].Value >= info.Requirement; + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Core/Persistance.cs b/Projects/UOContent/Engines/Factions/Core/Persistance.cs index a273a7e55..fd3c5b728 100644 --- a/Projects/UOContent/Engines/Factions/Core/Persistance.cs +++ b/Projects/UOContent/Engines/Factions/Core/Persistance.cs @@ -1,87 +1,85 @@ -using System.Collections.Generic; - -namespace Server.Factions -{ - public class FactionPersistance : Item - { - public FactionPersistance() : base(1) - { - Movable = false; - - if (Instance?.Deleted == true) - Instance = this; - else - base.Delete(); - } - - public FactionPersistance(Serial serial) : base(serial) => Instance = this; - - public static FactionPersistance Instance { get; private set; } - - public override string DefaultName => "Faction Persistance - Internal"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - List factions = Faction.Factions; - - for (int i = 0; i < factions.Count; ++i) - { - writer.WriteEncodedInt((int)PersistedType.Faction); - factions[i].State.Serialize(writer); - } - - List towns = Town.Towns; - - for (int i = 0; i < towns.Count; ++i) - { - writer.WriteEncodedInt((int)PersistedType.Town); - towns[i].State.Serialize(writer); - } - - writer.WriteEncodedInt((int)PersistedType.Terminator); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - PersistedType type; - - while ((type = (PersistedType)reader.ReadEncodedInt()) != PersistedType.Terminator) - switch (type) - { - case PersistedType.Faction: - new FactionState(reader); - break; - case PersistedType.Town: - new TownState(reader); - break; - } - - break; - } - } - } - - public override void Delete() - { - } - - private enum PersistedType - { - Terminator, - Faction, - Town - } - } -} +namespace Server.Factions +{ + public class FactionPersistance : Item + { + public FactionPersistance() : base(1) + { + Movable = false; + + if (Instance?.Deleted == true) + Instance = this; + else + base.Delete(); + } + + public FactionPersistance(Serial serial) : base(serial) => Instance = this; + + public static FactionPersistance Instance { get; private set; } + + public override string DefaultName => "Faction Persistance - Internal"; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + var factions = Faction.Factions; + + for (var i = 0; i < factions.Count; ++i) + { + writer.WriteEncodedInt((int)PersistedType.Faction); + factions[i].State.Serialize(writer); + } + + var towns = Town.Towns; + + for (var i = 0; i < towns.Count; ++i) + { + writer.WriteEncodedInt((int)PersistedType.Town); + towns[i].State.Serialize(writer); + } + + writer.WriteEncodedInt((int)PersistedType.Terminator); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + PersistedType type; + + while ((type = (PersistedType)reader.ReadEncodedInt()) != PersistedType.Terminator) + switch (type) + { + case PersistedType.Faction: + new FactionState(reader); + break; + case PersistedType.Town: + new TownState(reader); + break; + } + + break; + } + } + } + + public override void Delete() + { + } + + private enum PersistedType + { + Terminator, + Faction, + Town + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Core/PlayerState.cs b/Projects/UOContent/Engines/Factions/Core/PlayerState.cs index 0cafab3e2..04578c4a1 100644 --- a/Projects/UOContent/Engines/Factions/Core/PlayerState.cs +++ b/Projects/UOContent/Engines/Factions/Core/PlayerState.cs @@ -1,296 +1,296 @@ -using System; -using System.Collections.Generic; -using Server.Mobiles; - -namespace Server.Factions -{ - public class PlayerState : IComparable - { - private Town m_Finance; - - private bool m_InvalidateRank = true; - private int m_KillPoints; - private MerchantTitle m_MerchantTitle; - private RankDefinition m_Rank; - private int m_RankIndex = -1; - - private Town m_Sheriff; - - public PlayerState(Mobile mob, Faction faction, List owner) - { - Mobile = mob; - Faction = faction; - Owner = owner; - - Attach(); - Invalidate(); - } - - public PlayerState(IGenericReader reader, Faction faction, List owner) - { - Faction = faction; - Owner = owner; - - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 1: - { - IsActive = reader.ReadBool(); - LastHonorTime = reader.ReadDateTime(); - goto case 0; - } - case 0: - { - Mobile = reader.ReadMobile(); - - m_KillPoints = reader.ReadEncodedInt(); - m_MerchantTitle = (MerchantTitle)reader.ReadEncodedInt(); - - Leaving = reader.ReadDateTime(); - - break; - } - } - - Attach(); - } - - public Mobile Mobile { get; } - - public Faction Faction { get; } - - public List Owner { get; } - - public MerchantTitle MerchantTitle - { - get => m_MerchantTitle; - set - { - m_MerchantTitle = value; - Invalidate(); - } - } - - public Town Sheriff - { - get => m_Sheriff; - set - { - m_Sheriff = value; - Invalidate(); - } - } - - public Town Finance - { - get => m_Finance; - set - { - m_Finance = value; - Invalidate(); - } - } - - public List SilverGiven { get; private set; } - - public int KillPoints - { - get => m_KillPoints; - set - { - if (m_KillPoints != value) - { - if (value > m_KillPoints) - { - if (m_KillPoints <= 0) - { - if (value <= 0) - { - m_KillPoints = value; - Invalidate(); - return; - } - - Owner.Remove(this); - Owner.Insert(Faction.ZeroRankOffset, this); - - m_RankIndex = Faction.ZeroRankOffset; - Faction.ZeroRankOffset++; - } - - while (m_RankIndex - 1 >= 0) - { - PlayerState p = Owner[m_RankIndex - 1]; - if (value > p.KillPoints) - { - Owner[m_RankIndex] = p; - Owner[m_RankIndex - 1] = this; - RankIndex--; - p.RankIndex++; - } - else - { - break; - } - } - } - else - { - if (value <= 0) - { - if (m_KillPoints <= 0) - { - m_KillPoints = value; - Invalidate(); - return; - } - - while (m_RankIndex + 1 < Faction.ZeroRankOffset) - { - PlayerState p = Owner[m_RankIndex + 1]; - Owner[m_RankIndex + 1] = this; - Owner[m_RankIndex] = p; - RankIndex++; - p.RankIndex--; - } - - m_RankIndex = -1; - Faction.ZeroRankOffset--; - } - else - { - while (m_RankIndex + 1 < Faction.ZeroRankOffset) - { - PlayerState p = Owner[m_RankIndex + 1]; - if (value < p.KillPoints) - { - Owner[m_RankIndex + 1] = this; - Owner[m_RankIndex] = p; - RankIndex++; - p.RankIndex--; - } - else - { - break; - } - } - } - } - - m_KillPoints = value; - Invalidate(); - } - } - } - - public int RankIndex - { - get => m_RankIndex; - set - { - if (m_RankIndex != value) - { - m_RankIndex = value; - m_InvalidateRank = true; - } - } - } - - public RankDefinition Rank - { - get - { - if (m_InvalidateRank) - { - RankDefinition[] ranks = Faction.Definition.Ranks; - int percent; - - if (Owner.Count == 1) - percent = 1000; - else if (m_RankIndex == -1) - percent = 0; - else - percent = (Faction.ZeroRankOffset - m_RankIndex) * 1000 / Faction.ZeroRankOffset; - - for (int i = 0; i < ranks.Length; i++) - { - RankDefinition check = ranks[i]; - - if (percent >= check.Required) - { - m_Rank = check; - m_InvalidateRank = false; - break; - } - } - - Invalidate(); - } - - return m_Rank; - } - } - - public DateTime LastHonorTime { get; set; } - - public DateTime Leaving { get; set; } - - public bool IsLeaving => Leaving > DateTime.MinValue; - - public bool IsActive { get; set; } - - public int CompareTo(PlayerState ps) => (ps?.m_KillPoints ?? 0) - m_KillPoints; - - public bool CanGiveSilverTo(Mobile mob) - { - for (int i = 0; i < SilverGiven?.Count; ++i) - { - SilverGivenEntry sge = SilverGiven[i]; - - if (sge.IsExpired) - SilverGiven.RemoveAt(i--); - else if (sge.GivenTo == mob) - return false; - } - - return true; - } - - public void OnGivenSilverTo(Mobile mob) - { - SilverGiven ??= new List(); - - SilverGiven.Add(new SilverGivenEntry(mob)); - } - - public void Invalidate() - { - (Mobile as PlayerMobile)?.InvalidateProperties(); - } - - public void Attach() - { - if (Mobile is PlayerMobile mobile) - mobile.FactionPlayerState = this; - } - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(1); // version - - writer.Write(IsActive); - writer.Write(LastHonorTime); - - writer.Write(Mobile); - - writer.WriteEncodedInt(m_KillPoints); - writer.WriteEncodedInt((int)m_MerchantTitle); - - writer.Write(Leaving); - } - - public static PlayerState Find(Mobile mob) => mob is PlayerMobile mobile ? mobile.FactionPlayerState : null; - } -} +using System; +using System.Collections.Generic; +using Server.Mobiles; + +namespace Server.Factions +{ + public class PlayerState : IComparable + { + private Town m_Finance; + + private bool m_InvalidateRank = true; + private int m_KillPoints; + private MerchantTitle m_MerchantTitle; + private RankDefinition m_Rank; + private int m_RankIndex = -1; + + private Town m_Sheriff; + + public PlayerState(Mobile mob, Faction faction, List owner) + { + Mobile = mob; + Faction = faction; + Owner = owner; + + Attach(); + Invalidate(); + } + + public PlayerState(IGenericReader reader, Faction faction, List owner) + { + Faction = faction; + Owner = owner; + + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 1: + { + IsActive = reader.ReadBool(); + LastHonorTime = reader.ReadDateTime(); + goto case 0; + } + case 0: + { + Mobile = reader.ReadMobile(); + + m_KillPoints = reader.ReadEncodedInt(); + m_MerchantTitle = (MerchantTitle)reader.ReadEncodedInt(); + + Leaving = reader.ReadDateTime(); + + break; + } + } + + Attach(); + } + + public Mobile Mobile { get; } + + public Faction Faction { get; } + + public List Owner { get; } + + public MerchantTitle MerchantTitle + { + get => m_MerchantTitle; + set + { + m_MerchantTitle = value; + Invalidate(); + } + } + + public Town Sheriff + { + get => m_Sheriff; + set + { + m_Sheriff = value; + Invalidate(); + } + } + + public Town Finance + { + get => m_Finance; + set + { + m_Finance = value; + Invalidate(); + } + } + + public List SilverGiven { get; private set; } + + public int KillPoints + { + get => m_KillPoints; + set + { + if (m_KillPoints != value) + { + if (value > m_KillPoints) + { + if (m_KillPoints <= 0) + { + if (value <= 0) + { + m_KillPoints = value; + Invalidate(); + return; + } + + Owner.Remove(this); + Owner.Insert(Faction.ZeroRankOffset, this); + + m_RankIndex = Faction.ZeroRankOffset; + Faction.ZeroRankOffset++; + } + + while (m_RankIndex - 1 >= 0) + { + var p = Owner[m_RankIndex - 1]; + if (value > p.KillPoints) + { + Owner[m_RankIndex] = p; + Owner[m_RankIndex - 1] = this; + RankIndex--; + p.RankIndex++; + } + else + { + break; + } + } + } + else + { + if (value <= 0) + { + if (m_KillPoints <= 0) + { + m_KillPoints = value; + Invalidate(); + return; + } + + while (m_RankIndex + 1 < Faction.ZeroRankOffset) + { + var p = Owner[m_RankIndex + 1]; + Owner[m_RankIndex + 1] = this; + Owner[m_RankIndex] = p; + RankIndex++; + p.RankIndex--; + } + + m_RankIndex = -1; + Faction.ZeroRankOffset--; + } + else + { + while (m_RankIndex + 1 < Faction.ZeroRankOffset) + { + var p = Owner[m_RankIndex + 1]; + if (value < p.KillPoints) + { + Owner[m_RankIndex + 1] = this; + Owner[m_RankIndex] = p; + RankIndex++; + p.RankIndex--; + } + else + { + break; + } + } + } + } + + m_KillPoints = value; + Invalidate(); + } + } + } + + public int RankIndex + { + get => m_RankIndex; + set + { + if (m_RankIndex != value) + { + m_RankIndex = value; + m_InvalidateRank = true; + } + } + } + + public RankDefinition Rank + { + get + { + if (m_InvalidateRank) + { + var ranks = Faction.Definition.Ranks; + int percent; + + if (Owner.Count == 1) + percent = 1000; + else if (m_RankIndex == -1) + percent = 0; + else + percent = (Faction.ZeroRankOffset - m_RankIndex) * 1000 / Faction.ZeroRankOffset; + + for (var i = 0; i < ranks.Length; i++) + { + var check = ranks[i]; + + if (percent >= check.Required) + { + m_Rank = check; + m_InvalidateRank = false; + break; + } + } + + Invalidate(); + } + + return m_Rank; + } + } + + public DateTime LastHonorTime { get; set; } + + public DateTime Leaving { get; set; } + + public bool IsLeaving => Leaving > DateTime.MinValue; + + public bool IsActive { get; set; } + + public int CompareTo(PlayerState ps) => (ps?.m_KillPoints ?? 0) - m_KillPoints; + + public bool CanGiveSilverTo(Mobile mob) + { + for (var i = 0; i < SilverGiven?.Count; ++i) + { + var sge = SilverGiven[i]; + + if (sge.IsExpired) + SilverGiven.RemoveAt(i--); + else if (sge.GivenTo == mob) + return false; + } + + return true; + } + + public void OnGivenSilverTo(Mobile mob) + { + SilverGiven ??= new List(); + + SilverGiven.Add(new SilverGivenEntry(mob)); + } + + public void Invalidate() + { + (Mobile as PlayerMobile)?.InvalidateProperties(); + } + + public void Attach() + { + if (Mobile is PlayerMobile mobile) + mobile.FactionPlayerState = this; + } + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(1); // version + + writer.Write(IsActive); + writer.Write(LastHonorTime); + + writer.Write(Mobile); + + writer.WriteEncodedInt(m_KillPoints); + writer.WriteEncodedInt((int)m_MerchantTitle); + + writer.Write(Leaving); + } + + public static PlayerState Find(Mobile mob) => mob is PlayerMobile mobile ? mobile.FactionPlayerState : null; + } +} diff --git a/Projects/UOContent/Engines/Factions/Core/Reflector.cs b/Projects/UOContent/Engines/Factions/Core/Reflector.cs index 45e31e7ee..90e25cf74 100644 --- a/Projects/UOContent/Engines/Factions/Core/Reflector.cs +++ b/Projects/UOContent/Engines/Factions/Core/Reflector.cs @@ -1,80 +1,79 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using Server.Utilities; - -namespace Server.Factions -{ - public class Reflector - { - private static List m_Towns; - - private static List m_Factions; - - public static List Towns - { - get - { - if (m_Towns == null) - ProcessTypes(); - - return m_Towns; - } - } - - public static List Factions - { - get - { - if (m_Factions == null) - ProcessTypes(); - - return m_Factions; - } - } - - private static object Construct(Type type) - { - try - { - return ActivatorUtil.CreateInstance(type); - } - catch - { - return null; - } - } - - private static void ProcessTypes() - { - m_Factions = new List(); - m_Towns = new List(); - - Assembly[] asms = AssemblyHandler.Assemblies; - - for (int i = 0; i < asms.Length; ++i) - { - Assembly asm = asms[i]; - TypeCache tc = AssemblyHandler.GetTypeCache(asm); - Type[] types = tc.Types.ToArray(); - - for (int j = 0; j < types.Length; ++j) - { - Type type = types[j]; - - if (type.IsSubclassOf(typeof(Faction))) - { - if (Construct(type) is Faction faction) - Faction.Factions.Add(faction); - } - else if (type.IsSubclassOf(typeof(Town))) - { - if (Construct(type) is Town town) - Town.Towns.Add(town); - } - } - } - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using Server.Utilities; + +namespace Server.Factions +{ + public class Reflector + { + private static List m_Towns; + + private static List m_Factions; + + public static List Towns + { + get + { + if (m_Towns == null) + ProcessTypes(); + + return m_Towns; + } + } + + public static List Factions + { + get + { + if (m_Factions == null) + ProcessTypes(); + + return m_Factions; + } + } + + private static object Construct(Type type) + { + try + { + return ActivatorUtil.CreateInstance(type); + } + catch + { + return null; + } + } + + private static void ProcessTypes() + { + m_Factions = new List(); + m_Towns = new List(); + + var asms = AssemblyHandler.Assemblies; + + for (var i = 0; i < asms.Length; ++i) + { + var asm = asms[i]; + var tc = AssemblyHandler.GetTypeCache(asm); + var types = tc.Types.ToArray(); + + for (var j = 0; j < types.Length; ++j) + { + var type = types[j]; + + if (type.IsSubclassOf(typeof(Faction))) + { + if (Construct(type) is Faction faction) + Faction.Factions.Add(faction); + } + else if (type.IsSubclassOf(typeof(Town))) + { + if (Construct(type) is Town town) + Town.Towns.Add(town); + } + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Core/SilverGivenEntry.cs b/Projects/UOContent/Engines/Factions/Core/SilverGivenEntry.cs index acf77f189..2c24c5df0 100644 --- a/Projects/UOContent/Engines/Factions/Core/SilverGivenEntry.cs +++ b/Projects/UOContent/Engines/Factions/Core/SilverGivenEntry.cs @@ -1,21 +1,21 @@ -using System; - -namespace Server.Factions -{ - public class SilverGivenEntry - { - public static readonly TimeSpan ExpirePeriod = TimeSpan.FromHours(3.0); - - public SilverGivenEntry(Mobile givenTo) - { - GivenTo = givenTo; - TimeOfGift = DateTime.UtcNow; - } - - public Mobile GivenTo { get; } - - public DateTime TimeOfGift { get; } - - public bool IsExpired => TimeOfGift + ExpirePeriod < DateTime.UtcNow; - } -} \ No newline at end of file +using System; + +namespace Server.Factions +{ + public class SilverGivenEntry + { + public static readonly TimeSpan ExpirePeriod = TimeSpan.FromHours(3.0); + + public SilverGivenEntry(Mobile givenTo) + { + GivenTo = givenTo; + TimeOfGift = DateTime.UtcNow; + } + + public Mobile GivenTo { get; } + + public DateTime TimeOfGift { get; } + + public bool IsExpired => TimeOfGift + ExpirePeriod < DateTime.UtcNow; + } +} diff --git a/Projects/UOContent/Engines/Factions/Core/StrongholdRegion.cs b/Projects/UOContent/Engines/Factions/Core/StrongholdRegion.cs index 544c4f2d7..9eafcfc73 100644 --- a/Projects/UOContent/Engines/Factions/Core/StrongholdRegion.cs +++ b/Projects/UOContent/Engines/Factions/Core/StrongholdRegion.cs @@ -1,37 +1,41 @@ -using Server.Mobiles; -using Server.Regions; - -namespace Server.Factions -{ - public class StrongholdRegion : BaseRegion - { - public StrongholdRegion(Faction faction) : base(faction.Definition.FriendlyName, Faction.Facet, DefaultPriority, - faction.Definition.Stronghold.Area) - { - Faction = faction; - - Register(); - } - - public Faction Faction { get; set; } - - public override bool OnMoveInto(Mobile m, Direction d, Point3D newLocation, Point3D oldLocation) - { - if (!base.OnMoveInto(m, d, newLocation, oldLocation)) - return false; - - if (m.AccessLevel >= AccessLevel.Counselor || Contains(oldLocation)) - return true; - - if (m is PlayerMobile pm && pm.DuelContext != null) - { - pm.SendMessage("You may not enter this area while participating in a duel or a tournament."); - return false; - } - - return Faction.Find(m, true, true) != null; - } - - public override bool AllowHousing(Mobile from, Point3D p) => false; - } -} \ No newline at end of file +using Server.Mobiles; +using Server.Regions; + +namespace Server.Factions +{ + public class StrongholdRegion : BaseRegion + { + public StrongholdRegion(Faction faction) : base( + faction.Definition.FriendlyName, + Faction.Facet, + DefaultPriority, + faction.Definition.Stronghold.Area + ) + { + Faction = faction; + + Register(); + } + + public Faction Faction { get; set; } + + public override bool OnMoveInto(Mobile m, Direction d, Point3D newLocation, Point3D oldLocation) + { + if (!base.OnMoveInto(m, d, newLocation, oldLocation)) + return false; + + if (m.AccessLevel >= AccessLevel.Counselor || Contains(oldLocation)) + return true; + + if (m is PlayerMobile pm && pm.DuelContext != null) + { + pm.SendMessage("You may not enter this area while participating in a duel or a tournament."); + return false; + } + + return Faction.Find(m, true, true) != null; + } + + public override bool AllowHousing(Mobile from, Point3D p) => false; + } +} diff --git a/Projects/UOContent/Engines/Factions/Core/Town.cs b/Projects/UOContent/Engines/Factions/Core/Town.cs index af8871c4f..97a0abae5 100644 --- a/Projects/UOContent/Engines/Factions/Core/Town.cs +++ b/Projects/UOContent/Engines/Factions/Core/Town.cs @@ -1,492 +1,495 @@ -using System; -using System.Collections.Generic; -using Server.Targeting; - -namespace Server.Factions -{ - [CustomEnum(new[] { "Britain", "Magincia", "Minoc", "Moonglow", "Skara Brae", "Trinsic", "Vesper", "Yew" })] - public abstract class Town : IComparable - { - public const int SilverCaptureBonus = 10000; - - public static readonly TimeSpan TaxChangePeriod = TimeSpan.FromHours(12.0); - public static readonly TimeSpan IncomePeriod = TimeSpan.FromDays(1.0); - - private Timer m_IncomeTimer; - private TownState m_State; - - public Town() - { - m_State = new TownState(this); - ConstructVendorLists(); - ConstructGuardLists(); - StartIncomeTimer(); - } - - public TownDefinition Definition { get; set; } - - public TownState State - { - get => m_State; - set - { - m_State = value; - ConstructGuardLists(); - } - } - - public int Silver - { - get => m_State.Silver; - set => m_State.Silver = value; - } - - public Faction Owner - { - get => m_State.Owner; - set => Capture(value); - } - - public Mobile Sheriff - { - get => m_State.Sheriff; - set => m_State.Sheriff = value; - } - - public Mobile Finance - { - get => m_State.Finance; - set => m_State.Finance = value; - } - - public int Tax - { - get => m_State.Tax; - set => m_State.Tax = value; - } - - public DateTime LastTaxChange - { - get => m_State.LastTaxChange; - set => m_State.LastTaxChange = value; - } - - public bool TaxChangeReady => m_State.LastTaxChange + TaxChangePeriod < DateTime.UtcNow; - - public int FinanceUpkeep - { - get - { - List vendorLists = VendorLists; - int upkeep = 0; - - for (int i = 0; i < vendorLists.Count; ++i) - upkeep += vendorLists[i].Vendors.Count * vendorLists[i].Definition.Upkeep; - - return upkeep; - } - } - - public int SheriffUpkeep - { - get - { - List guardLists = GuardLists; - int upkeep = 0; - - for (int i = 0; i < guardLists.Count; ++i) - upkeep += guardLists[i].Guards.Count * guardLists[i].Definition.Upkeep; - - return upkeep; - } - } - - public int DailyIncome => 10000 * (100 + m_State.Tax) / 100; - - public int NetCashFlow => DailyIncome - FinanceUpkeep - SheriffUpkeep; - - public TownMonolith Monolith - { - get - { - List monoliths = BaseMonolith.Monoliths; - - foreach (BaseMonolith monolith in monoliths) - if (monolith is TownMonolith townMonolith && townMonolith.Town == this) - return townMonolith; - - return null; - } - } - - public DateTime LastIncome - { - get => m_State.LastIncome; - set => m_State.LastIncome = value; - } - - public List VendorLists { get; set; } - - public List GuardLists { get; set; } - - public static List Towns => Reflector.Towns; - - public int CompareTo(Town other) => Definition.Sort - (other?.Definition.Sort ?? 0); - - public static Town FromRegion(Region reg) - { - if (reg.Map != Faction.Facet) - return null; - - List towns = Towns; - - for (int i = 0; i < towns.Count; ++i) - { - Town town = towns[i]; - - if (reg.IsPartOf(town.Definition.Region)) - return town; - } - - return null; - } - - public void BeginOrderFiring(Mobile from) - { - bool isFinance = IsFinance(from); - bool isSheriff = IsSheriff(from); - string type = null; - - // NOTE: Messages not OSI-accurate, intentional - if (isFinance && isSheriff) // GM only - type = "vendor or guard"; - else if (isFinance) - type = "vendor"; - else if (isSheriff) - type = "guard"; - - from.SendMessage("Target the {0} you wish to dismiss.", type); - from.BeginTarget(12, false, TargetFlags.None, EndOrderFiring); - } - - public void EndOrderFiring(Mobile from, object obj) - { - bool isFinance = IsFinance(from); - bool isSheriff = IsSheriff(from); - string type = null; - - if (isFinance && isSheriff) // GM only - type = "vendor or guard"; - else if (isFinance) - type = "vendor"; - else if (isSheriff) - type = "guard"; - - if (obj is BaseFactionVendor vendor && vendor.Town == this && isFinance) - vendor.Delete(); - else if (obj is BaseFactionGuard guard && guard.Town == this && isSheriff) - guard.Delete(); - else - from.SendMessage("That is not a {0}!", type); - } - - public void StartIncomeTimer() - { - m_IncomeTimer?.Stop(); - - m_IncomeTimer = Timer.DelayCall(TimeSpan.FromMinutes(1.0), TimeSpan.FromMinutes(1.0), CheckIncome); - } - - public void StopIncomeTimer() - { - m_IncomeTimer?.Stop(); - - m_IncomeTimer = null; - } - - public void CheckIncome() - { - if (LastIncome + IncomePeriod > DateTime.UtcNow || Owner == null) - return; - - ProcessIncome(); - } - - public void ProcessIncome() - { - LastIncome = DateTime.UtcNow; - - int flow = NetCashFlow; - - if (Silver + flow < 0) - { - List toDelete = BuildFinanceList(); - - while (Silver + flow < 0 && toDelete.Count > 0) - { - Mobile mob = toDelete.RandomElement(); - mob.Delete(); - - toDelete.Remove(mob); - flow = NetCashFlow; - } - } - - Silver += flow; - } - - public List BuildFinanceList() - { - List list = new List(); - - for (int i = 0; i < VendorLists.Count; ++i) - list.AddRange(VendorLists[i].Vendors); - - for (int i = 0; i < GuardLists.Count; ++i) - list.AddRange(GuardLists[i].Guards); - - return list; - } - - public void ConstructGuardLists() - { - GuardDefinition[] defs = Owner?.Definition.Guards ?? new GuardDefinition[0]; - - GuardLists = new List(); - - for (int i = 0; i < defs.Length; ++i) - GuardLists.Add(new GuardList(defs[i])); - } - - public GuardList FindGuardList(Type type) - { - List guardLists = GuardLists; - - for (int i = 0; i < guardLists.Count; ++i) - { - GuardList guardList = guardLists[i]; - - if (guardList.Definition.Type == type) - return guardList; - } - - return null; - } - - public void ConstructVendorLists() - { - VendorDefinition[] defs = VendorDefinition.Definitions; - - VendorLists = new List(); - - for (int i = 0; i < defs.Length; ++i) - VendorLists.Add(new VendorList(defs[i])); - } - - public VendorList FindVendorList(Type type) - { - List vendorLists = VendorLists; - - for (int i = 0; i < vendorLists.Count; ++i) - { - VendorList vendorList = vendorLists[i]; - - if (vendorList.Definition.Type == type) - return vendorList; - } - - return null; - } - - public bool RegisterGuard(BaseFactionGuard guard) - { - if (guard == null) - return false; - - GuardList guardList = FindGuardList(guard.GetType()); - - if (guardList == null) - return false; - - guardList.Guards.Add(guard); - return true; - } - - public bool UnregisterGuard(BaseFactionGuard guard) - { - if (guard == null) - return false; - - GuardList guardList = FindGuardList(guard.GetType()); - - if (guardList == null) - return false; - - if (!guardList.Guards.Contains(guard)) - return false; - - guardList.Guards.Remove(guard); - return true; - } - - public bool RegisterVendor(BaseFactionVendor vendor) - { - if (vendor == null) - return false; - - VendorList vendorList = FindVendorList(vendor.GetType()); - - if (vendorList == null) - return false; - - vendorList.Vendors.Add(vendor); - return true; - } - - public bool UnregisterVendor(BaseFactionVendor vendor) - { - if (vendor == null) - return false; - - VendorList vendorList = FindVendorList(vendor.GetType()); - - if (vendorList == null) - return false; - - if (!vendorList.Vendors.Contains(vendor)) - return false; - - vendorList.Vendors.Remove(vendor); - return true; - } - - public static void Initialize() - { - List towns = Towns; - - for (int i = 0; i < towns.Count; ++i) - { - towns[i].Sheriff = towns[i].Sheriff; - towns[i].Finance = towns[i].Finance; - } - - CommandSystem.Register("GrantTownSilver", AccessLevel.Administrator, GrantTownSilver_OnCommand); - } - - public bool IsSheriff(Mobile mob) => - mob?.Deleted == false && - (mob.AccessLevel >= AccessLevel.GameMaster || mob == Sheriff); - - public bool IsFinance(Mobile mob) => - mob?.Deleted == false && - (mob.AccessLevel >= AccessLevel.GameMaster || mob == Finance); - - public void Capture(Faction f) - { - if (m_State.Owner == f) - return; - - if (m_State.Owner == null) // going from unowned to owned - { - LastIncome = DateTime.UtcNow; - f.Silver += SilverCaptureBonus; - } - else if (f == null) // going from owned to unowned - { - LastIncome = DateTime.MinValue; - } - else // otherwise changing hands, income timer doesn't change - { - f.Silver += SilverCaptureBonus; - } - - m_State.Owner = f; - - Sheriff = null; - Finance = null; - - TownMonolith monolith = Monolith; - - if (monolith != null) - monolith.Faction = f; - - List vendorLists = VendorLists; - - for (int i = 0; i < vendorLists.Count; ++i) - { - VendorList vendorList = vendorLists[i]; - List vendors = vendorList.Vendors; - - for (int j = vendors.Count - 1; j >= 0; --j) - vendors[j].Delete(); - } - - List guardLists = GuardLists; - - for (int i = 0; i < guardLists.Count; ++i) - { - GuardList guardList = guardLists[i]; - List guards = guardList.Guards; - - for (int j = guards.Count - 1; j >= 0; --j) - guards[j].Delete(); - } - - ConstructGuardLists(); - } - - public override string ToString() => Definition.FriendlyName; - - public static void WriteReference(IGenericWriter writer, Town town) - { - int idx = Towns.IndexOf(town); - - writer.WriteEncodedInt(idx + 1); - } - - public static Town ReadReference(IGenericReader reader) - { - int idx = reader.ReadEncodedInt() - 1; - - if (idx >= 0 && idx < Towns.Count) - return Towns[idx]; - - return null; - } - - public static Town Parse(string name) - { - List towns = Towns; - - for (int i = 0; i < towns.Count; ++i) - { - Town town = towns[i]; - - if (Insensitive.Equals(town.Definition.FriendlyName, name)) - return town; - } - - return null; - } - - public static void GrantTownSilver_OnCommand(CommandEventArgs e) - { - Town town = FromRegion(e.Mobile.Region); - - if (town == null) - { - e.Mobile.SendMessage("You are not in a faction town."); - } - else if (e.Length == 0) - { - e.Mobile.SendMessage("Format: GrantTownSilver "); - } - else - { - town.Silver += e.GetInt32(0); - e.Mobile.SendMessage("You have granted {0:N0} silver to the town. It now has {1:N0} silver.", e.GetInt32(0), - town.Silver); - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Targeting; + +namespace Server.Factions +{ + [CustomEnum(new[] { "Britain", "Magincia", "Minoc", "Moonglow", "Skara Brae", "Trinsic", "Vesper", "Yew" })] + public abstract class Town : IComparable + { + public const int SilverCaptureBonus = 10000; + + public static readonly TimeSpan TaxChangePeriod = TimeSpan.FromHours(12.0); + public static readonly TimeSpan IncomePeriod = TimeSpan.FromDays(1.0); + + private Timer m_IncomeTimer; + private TownState m_State; + + public Town() + { + m_State = new TownState(this); + ConstructVendorLists(); + ConstructGuardLists(); + StartIncomeTimer(); + } + + public TownDefinition Definition { get; set; } + + public TownState State + { + get => m_State; + set + { + m_State = value; + ConstructGuardLists(); + } + } + + public int Silver + { + get => m_State.Silver; + set => m_State.Silver = value; + } + + public Faction Owner + { + get => m_State.Owner; + set => Capture(value); + } + + public Mobile Sheriff + { + get => m_State.Sheriff; + set => m_State.Sheriff = value; + } + + public Mobile Finance + { + get => m_State.Finance; + set => m_State.Finance = value; + } + + public int Tax + { + get => m_State.Tax; + set => m_State.Tax = value; + } + + public DateTime LastTaxChange + { + get => m_State.LastTaxChange; + set => m_State.LastTaxChange = value; + } + + public bool TaxChangeReady => m_State.LastTaxChange + TaxChangePeriod < DateTime.UtcNow; + + public int FinanceUpkeep + { + get + { + var vendorLists = VendorLists; + var upkeep = 0; + + for (var i = 0; i < vendorLists.Count; ++i) + upkeep += vendorLists[i].Vendors.Count * vendorLists[i].Definition.Upkeep; + + return upkeep; + } + } + + public int SheriffUpkeep + { + get + { + var guardLists = GuardLists; + var upkeep = 0; + + for (var i = 0; i < guardLists.Count; ++i) + upkeep += guardLists[i].Guards.Count * guardLists[i].Definition.Upkeep; + + return upkeep; + } + } + + public int DailyIncome => 10000 * (100 + m_State.Tax) / 100; + + public int NetCashFlow => DailyIncome - FinanceUpkeep - SheriffUpkeep; + + public TownMonolith Monolith + { + get + { + var monoliths = BaseMonolith.Monoliths; + + foreach (var monolith in monoliths) + if (monolith is TownMonolith townMonolith && townMonolith.Town == this) + return townMonolith; + + return null; + } + } + + public DateTime LastIncome + { + get => m_State.LastIncome; + set => m_State.LastIncome = value; + } + + public List VendorLists { get; set; } + + public List GuardLists { get; set; } + + public static List Towns => Reflector.Towns; + + public int CompareTo(Town other) => Definition.Sort - (other?.Definition.Sort ?? 0); + + public static Town FromRegion(Region reg) + { + if (reg.Map != Faction.Facet) + return null; + + var towns = Towns; + + for (var i = 0; i < towns.Count; ++i) + { + var town = towns[i]; + + if (reg.IsPartOf(town.Definition.Region)) + return town; + } + + return null; + } + + public void BeginOrderFiring(Mobile from) + { + var isFinance = IsFinance(from); + var isSheriff = IsSheriff(from); + string type = null; + + // NOTE: Messages not OSI-accurate, intentional + if (isFinance && isSheriff) // GM only + type = "vendor or guard"; + else if (isFinance) + type = "vendor"; + else if (isSheriff) + type = "guard"; + + from.SendMessage("Target the {0} you wish to dismiss.", type); + from.BeginTarget(12, false, TargetFlags.None, EndOrderFiring); + } + + public void EndOrderFiring(Mobile from, object obj) + { + var isFinance = IsFinance(from); + var isSheriff = IsSheriff(from); + string type = null; + + if (isFinance && isSheriff) // GM only + type = "vendor or guard"; + else if (isFinance) + type = "vendor"; + else if (isSheriff) + type = "guard"; + + if (obj is BaseFactionVendor vendor && vendor.Town == this && isFinance) + vendor.Delete(); + else if (obj is BaseFactionGuard guard && guard.Town == this && isSheriff) + guard.Delete(); + else + from.SendMessage("That is not a {0}!", type); + } + + public void StartIncomeTimer() + { + m_IncomeTimer?.Stop(); + + m_IncomeTimer = Timer.DelayCall(TimeSpan.FromMinutes(1.0), TimeSpan.FromMinutes(1.0), CheckIncome); + } + + public void StopIncomeTimer() + { + m_IncomeTimer?.Stop(); + + m_IncomeTimer = null; + } + + public void CheckIncome() + { + if (LastIncome + IncomePeriod > DateTime.UtcNow || Owner == null) + return; + + ProcessIncome(); + } + + public void ProcessIncome() + { + LastIncome = DateTime.UtcNow; + + var flow = NetCashFlow; + + if (Silver + flow < 0) + { + var toDelete = BuildFinanceList(); + + while (Silver + flow < 0 && toDelete.Count > 0) + { + var mob = toDelete.RandomElement(); + mob.Delete(); + + toDelete.Remove(mob); + flow = NetCashFlow; + } + } + + Silver += flow; + } + + public List BuildFinanceList() + { + var list = new List(); + + for (var i = 0; i < VendorLists.Count; ++i) + list.AddRange(VendorLists[i].Vendors); + + for (var i = 0; i < GuardLists.Count; ++i) + list.AddRange(GuardLists[i].Guards); + + return list; + } + + public void ConstructGuardLists() + { + var defs = Owner?.Definition.Guards ?? new GuardDefinition[0]; + + GuardLists = new List(); + + for (var i = 0; i < defs.Length; ++i) + GuardLists.Add(new GuardList(defs[i])); + } + + public GuardList FindGuardList(Type type) + { + var guardLists = GuardLists; + + for (var i = 0; i < guardLists.Count; ++i) + { + var guardList = guardLists[i]; + + if (guardList.Definition.Type == type) + return guardList; + } + + return null; + } + + public void ConstructVendorLists() + { + var defs = VendorDefinition.Definitions; + + VendorLists = new List(); + + for (var i = 0; i < defs.Length; ++i) + VendorLists.Add(new VendorList(defs[i])); + } + + public VendorList FindVendorList(Type type) + { + var vendorLists = VendorLists; + + for (var i = 0; i < vendorLists.Count; ++i) + { + var vendorList = vendorLists[i]; + + if (vendorList.Definition.Type == type) + return vendorList; + } + + return null; + } + + public bool RegisterGuard(BaseFactionGuard guard) + { + if (guard == null) + return false; + + var guardList = FindGuardList(guard.GetType()); + + if (guardList == null) + return false; + + guardList.Guards.Add(guard); + return true; + } + + public bool UnregisterGuard(BaseFactionGuard guard) + { + if (guard == null) + return false; + + var guardList = FindGuardList(guard.GetType()); + + if (guardList == null) + return false; + + if (!guardList.Guards.Contains(guard)) + return false; + + guardList.Guards.Remove(guard); + return true; + } + + public bool RegisterVendor(BaseFactionVendor vendor) + { + if (vendor == null) + return false; + + var vendorList = FindVendorList(vendor.GetType()); + + if (vendorList == null) + return false; + + vendorList.Vendors.Add(vendor); + return true; + } + + public bool UnregisterVendor(BaseFactionVendor vendor) + { + if (vendor == null) + return false; + + var vendorList = FindVendorList(vendor.GetType()); + + if (vendorList == null) + return false; + + if (!vendorList.Vendors.Contains(vendor)) + return false; + + vendorList.Vendors.Remove(vendor); + return true; + } + + public static void Initialize() + { + var towns = Towns; + + for (var i = 0; i < towns.Count; ++i) + { + towns[i].Sheriff = towns[i].Sheriff; + towns[i].Finance = towns[i].Finance; + } + + CommandSystem.Register("GrantTownSilver", AccessLevel.Administrator, GrantTownSilver_OnCommand); + } + + public bool IsSheriff(Mobile mob) => + mob?.Deleted == false && + (mob.AccessLevel >= AccessLevel.GameMaster || mob == Sheriff); + + public bool IsFinance(Mobile mob) => + mob?.Deleted == false && + (mob.AccessLevel >= AccessLevel.GameMaster || mob == Finance); + + public void Capture(Faction f) + { + if (m_State.Owner == f) + return; + + if (m_State.Owner == null) // going from unowned to owned + { + LastIncome = DateTime.UtcNow; + f.Silver += SilverCaptureBonus; + } + else if (f == null) // going from owned to unowned + { + LastIncome = DateTime.MinValue; + } + else // otherwise changing hands, income timer doesn't change + { + f.Silver += SilverCaptureBonus; + } + + m_State.Owner = f; + + Sheriff = null; + Finance = null; + + var monolith = Monolith; + + if (monolith != null) + monolith.Faction = f; + + var vendorLists = VendorLists; + + for (var i = 0; i < vendorLists.Count; ++i) + { + var vendorList = vendorLists[i]; + var vendors = vendorList.Vendors; + + for (var j = vendors.Count - 1; j >= 0; --j) + vendors[j].Delete(); + } + + var guardLists = GuardLists; + + for (var i = 0; i < guardLists.Count; ++i) + { + var guardList = guardLists[i]; + var guards = guardList.Guards; + + for (var j = guards.Count - 1; j >= 0; --j) + guards[j].Delete(); + } + + ConstructGuardLists(); + } + + public override string ToString() => Definition.FriendlyName; + + public static void WriteReference(IGenericWriter writer, Town town) + { + var idx = Towns.IndexOf(town); + + writer.WriteEncodedInt(idx + 1); + } + + public static Town ReadReference(IGenericReader reader) + { + var idx = reader.ReadEncodedInt() - 1; + + if (idx >= 0 && idx < Towns.Count) + return Towns[idx]; + + return null; + } + + public static Town Parse(string name) + { + var towns = Towns; + + for (var i = 0; i < towns.Count; ++i) + { + var town = towns[i]; + + if (Insensitive.Equals(town.Definition.FriendlyName, name)) + return town; + } + + return null; + } + + public static void GrantTownSilver_OnCommand(CommandEventArgs e) + { + var town = FromRegion(e.Mobile.Region); + + if (town == null) + { + e.Mobile.SendMessage("You are not in a faction town."); + } + else if (e.Length == 0) + { + e.Mobile.SendMessage("Format: GrantTownSilver "); + } + else + { + town.Silver += e.GetInt32(0); + e.Mobile.SendMessage( + "You have granted {0:N0} silver to the town. It now has {1:N0} silver.", + e.GetInt32(0), + town.Silver + ); + } + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Core/TownState.cs b/Projects/UOContent/Engines/Factions/Core/TownState.cs index 883236a1a..128a2db3a 100644 --- a/Projects/UOContent/Engines/Factions/Core/TownState.cs +++ b/Projects/UOContent/Engines/Factions/Core/TownState.cs @@ -1,132 +1,132 @@ -using System; - -namespace Server.Factions -{ - public class TownState - { - private Mobile m_Finance; - private Mobile m_Sheriff; - - public TownState(Town town) => Town = town; - - public TownState(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 3: - { - LastIncome = reader.ReadDateTime(); - - goto case 2; - } - case 2: - { - Tax = reader.ReadEncodedInt(); - LastTaxChange = reader.ReadDateTime(); - - goto case 1; - } - case 1: - { - Silver = reader.ReadEncodedInt(); - - goto case 0; - } - case 0: - { - Town = Town.ReadReference(reader); - Owner = Faction.ReadReference(reader); - - m_Sheriff = reader.ReadMobile(); - m_Finance = reader.ReadMobile(); - - Town.State = this; - - break; - } - } - } - - public Town Town { get; set; } - - public Faction Owner { get; set; } - - public Mobile Sheriff - { - get => m_Sheriff; - set - { - if (m_Sheriff != null) - { - PlayerState pl = PlayerState.Find(m_Sheriff); - - if (pl != null) - pl.Sheriff = null; - } - - m_Sheriff = value; - - if (m_Sheriff != null) - { - PlayerState pl = PlayerState.Find(m_Sheriff); - - if (pl != null) - pl.Sheriff = Town; - } - } - } - - public Mobile Finance - { - get => m_Finance; - set - { - if (m_Finance != null) - { - PlayerState pl = PlayerState.Find(m_Finance); - - if (pl != null) - pl.Finance = null; - } - - m_Finance = value; - - if (m_Finance != null) - { - PlayerState pl = PlayerState.Find(m_Finance); - - if (pl != null) - pl.Finance = Town; - } - } - } - - public int Silver { get; set; } - - public int Tax { get; set; } - - public DateTime LastTaxChange { get; set; } - - public DateTime LastIncome { get; set; } - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(3); // version - - writer.Write(LastIncome); - - writer.WriteEncodedInt(Tax); - writer.Write(LastTaxChange); - - writer.WriteEncodedInt(Silver); - - Town.WriteReference(writer, Town); - Faction.WriteReference(writer, Owner); - - writer.Write(m_Sheriff); - writer.Write(m_Finance); - } - } -} \ No newline at end of file +using System; + +namespace Server.Factions +{ + public class TownState + { + private Mobile m_Finance; + private Mobile m_Sheriff; + + public TownState(Town town) => Town = town; + + public TownState(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 3: + { + LastIncome = reader.ReadDateTime(); + + goto case 2; + } + case 2: + { + Tax = reader.ReadEncodedInt(); + LastTaxChange = reader.ReadDateTime(); + + goto case 1; + } + case 1: + { + Silver = reader.ReadEncodedInt(); + + goto case 0; + } + case 0: + { + Town = Town.ReadReference(reader); + Owner = Faction.ReadReference(reader); + + m_Sheriff = reader.ReadMobile(); + m_Finance = reader.ReadMobile(); + + Town.State = this; + + break; + } + } + } + + public Town Town { get; set; } + + public Faction Owner { get; set; } + + public Mobile Sheriff + { + get => m_Sheriff; + set + { + if (m_Sheriff != null) + { + var pl = PlayerState.Find(m_Sheriff); + + if (pl != null) + pl.Sheriff = null; + } + + m_Sheriff = value; + + if (m_Sheriff != null) + { + var pl = PlayerState.Find(m_Sheriff); + + if (pl != null) + pl.Sheriff = Town; + } + } + } + + public Mobile Finance + { + get => m_Finance; + set + { + if (m_Finance != null) + { + var pl = PlayerState.Find(m_Finance); + + if (pl != null) + pl.Finance = null; + } + + m_Finance = value; + + if (m_Finance != null) + { + var pl = PlayerState.Find(m_Finance); + + if (pl != null) + pl.Finance = Town; + } + } + } + + public int Silver { get; set; } + + public int Tax { get; set; } + + public DateTime LastTaxChange { get; set; } + + public DateTime LastIncome { get; set; } + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(3); // version + + writer.Write(LastIncome); + + writer.WriteEncodedInt(Tax); + writer.Write(LastTaxChange); + + writer.WriteEncodedInt(Silver); + + Town.WriteReference(writer, Town); + Faction.WriteReference(writer, Owner); + + writer.Write(m_Sheriff); + writer.Write(m_Finance); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Core/VendorList.cs b/Projects/UOContent/Engines/Factions/Core/VendorList.cs index 87c66d0fd..b94e84e5d 100644 --- a/Projects/UOContent/Engines/Factions/Core/VendorList.cs +++ b/Projects/UOContent/Engines/Factions/Core/VendorList.cs @@ -1,30 +1,30 @@ -using System.Collections.Generic; -using Server.Utilities; - -namespace Server.Factions -{ - public class VendorList - { - public VendorList(VendorDefinition definition) - { - Definition = definition; - Vendors = new List(); - } - - public VendorDefinition Definition { get; } - - public List Vendors { get; } - - public BaseFactionVendor Construct(Town town, Faction faction) - { - try - { - return ActivatorUtil.CreateInstance(Definition.Type, town, faction) as BaseFactionVendor; - } - catch - { - return null; - } - } - } -} +using System.Collections.Generic; +using Server.Utilities; + +namespace Server.Factions +{ + public class VendorList + { + public VendorList(VendorDefinition definition) + { + Definition = definition; + Vendors = new List(); + } + + public VendorDefinition Definition { get; } + + public List Vendors { get; } + + public BaseFactionVendor Construct(Town town, Faction faction) + { + try + { + return ActivatorUtil.CreateInstance(Definition.Type, town, faction) as BaseFactionVendor; + } + catch + { + return null; + } + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Definitions/FactionDefinition.cs b/Projects/UOContent/Engines/Factions/Definitions/FactionDefinition.cs index 84d1846ad..68fd8af90 100644 --- a/Projects/UOContent/Engines/Factions/Definitions/FactionDefinition.cs +++ b/Projects/UOContent/Engines/Factions/Definitions/FactionDefinition.cs @@ -1,89 +1,91 @@ -namespace Server.Factions -{ - public class FactionDefinition - { - public FactionDefinition(int sort, int huePrimary, int hueSecondary, int hueJoin, int hueBroadcast, int warHorseBody, - int warHorseItem, string friendlyName, string keyword, string abbreviation, TextDefinition name, - TextDefinition propName, TextDefinition header, TextDefinition about, TextDefinition cityControl, - TextDefinition sigilControl, TextDefinition signupName, TextDefinition factionStoneName, - TextDefinition ownerLabel, TextDefinition guardIgnore, TextDefinition guardWarn, TextDefinition guardAttack, - StrongholdDefinition stronghold, RankDefinition[] ranks, GuardDefinition[] guards) - { - Sort = sort; - HuePrimary = huePrimary; - HueSecondary = hueSecondary; - HueJoin = hueJoin; - HueBroadcast = hueBroadcast; - WarHorseBody = warHorseBody; - WarHorseItem = warHorseItem; - FriendlyName = friendlyName; - Keyword = keyword; - Abbreviation = abbreviation; - Name = name; - PropName = propName; - Header = header; - About = about; - CityControl = cityControl; - SigilControl = sigilControl; - SignupName = signupName; - FactionStoneName = factionStoneName; - OwnerLabel = ownerLabel; - GuardIgnore = guardIgnore; - GuardWarn = guardWarn; - GuardAttack = guardAttack; - Stronghold = stronghold; - Ranks = ranks; - Guards = guards; - } - - public int Sort { get; } - - public int HuePrimary { get; } - - public int HueSecondary { get; } - - public int HueJoin { get; } - - public int HueBroadcast { get; } - - public int WarHorseBody { get; } - - public int WarHorseItem { get; } - - public string FriendlyName { get; } - - public string Keyword { get; } - - public string Abbreviation { get; } - - public TextDefinition Name { get; } - - public TextDefinition PropName { get; } - - public TextDefinition Header { get; } - - public TextDefinition About { get; } - - public TextDefinition CityControl { get; } - - public TextDefinition SigilControl { get; } - - public TextDefinition SignupName { get; } - - public TextDefinition FactionStoneName { get; } - - public TextDefinition OwnerLabel { get; } - - public TextDefinition GuardIgnore { get; } - - public TextDefinition GuardWarn { get; } - - public TextDefinition GuardAttack { get; } - - public StrongholdDefinition Stronghold { get; } - - public RankDefinition[] Ranks { get; } - - public GuardDefinition[] Guards { get; } - } -} \ No newline at end of file +namespace Server.Factions +{ + public class FactionDefinition + { + public FactionDefinition( + int sort, int huePrimary, int hueSecondary, int hueJoin, int hueBroadcast, int warHorseBody, + int warHorseItem, string friendlyName, string keyword, string abbreviation, TextDefinition name, + TextDefinition propName, TextDefinition header, TextDefinition about, TextDefinition cityControl, + TextDefinition sigilControl, TextDefinition signupName, TextDefinition factionStoneName, + TextDefinition ownerLabel, TextDefinition guardIgnore, TextDefinition guardWarn, TextDefinition guardAttack, + StrongholdDefinition stronghold, RankDefinition[] ranks, GuardDefinition[] guards + ) + { + Sort = sort; + HuePrimary = huePrimary; + HueSecondary = hueSecondary; + HueJoin = hueJoin; + HueBroadcast = hueBroadcast; + WarHorseBody = warHorseBody; + WarHorseItem = warHorseItem; + FriendlyName = friendlyName; + Keyword = keyword; + Abbreviation = abbreviation; + Name = name; + PropName = propName; + Header = header; + About = about; + CityControl = cityControl; + SigilControl = sigilControl; + SignupName = signupName; + FactionStoneName = factionStoneName; + OwnerLabel = ownerLabel; + GuardIgnore = guardIgnore; + GuardWarn = guardWarn; + GuardAttack = guardAttack; + Stronghold = stronghold; + Ranks = ranks; + Guards = guards; + } + + public int Sort { get; } + + public int HuePrimary { get; } + + public int HueSecondary { get; } + + public int HueJoin { get; } + + public int HueBroadcast { get; } + + public int WarHorseBody { get; } + + public int WarHorseItem { get; } + + public string FriendlyName { get; } + + public string Keyword { get; } + + public string Abbreviation { get; } + + public TextDefinition Name { get; } + + public TextDefinition PropName { get; } + + public TextDefinition Header { get; } + + public TextDefinition About { get; } + + public TextDefinition CityControl { get; } + + public TextDefinition SigilControl { get; } + + public TextDefinition SignupName { get; } + + public TextDefinition FactionStoneName { get; } + + public TextDefinition OwnerLabel { get; } + + public TextDefinition GuardIgnore { get; } + + public TextDefinition GuardWarn { get; } + + public TextDefinition GuardAttack { get; } + + public StrongholdDefinition Stronghold { get; } + + public RankDefinition[] Ranks { get; } + + public GuardDefinition[] Guards { get; } + } +} diff --git a/Projects/UOContent/Engines/Factions/Definitions/FactionItemDefinition.cs b/Projects/UOContent/Engines/Factions/Definitions/FactionItemDefinition.cs index 2daa61970..402dc2c9d 100644 --- a/Projects/UOContent/Engines/Factions/Definitions/FactionItemDefinition.cs +++ b/Projects/UOContent/Engines/Factions/Definitions/FactionItemDefinition.cs @@ -1,48 +1,48 @@ -using System; -using Server.Items; -using Server.Mobiles; - -namespace Server.Factions -{ - public class FactionItemDefinition - { - private static readonly FactionItemDefinition m_MetalArmor = new FactionItemDefinition(1000, typeof(Blacksmith)); - private static readonly FactionItemDefinition m_Weapon = new FactionItemDefinition(1000, typeof(Blacksmith)); - private static readonly FactionItemDefinition m_RangedWeapon = new FactionItemDefinition(1000, typeof(Bowyer)); - private static readonly FactionItemDefinition m_LeatherArmor = new FactionItemDefinition(750, typeof(Tailor)); - private static readonly FactionItemDefinition m_Clothing = new FactionItemDefinition(200, typeof(Tailor)); - private static readonly FactionItemDefinition m_Scroll = new FactionItemDefinition(500, typeof(Mage)); - - public FactionItemDefinition(int silverCost, Type vendorType) - { - SilverCost = silverCost; - VendorType = vendorType; - } - - public int SilverCost { get; } - - public Type VendorType { get; } - - public static FactionItemDefinition Identify(Item item) - { - if (item is BaseArmor armor) - { - if (CraftResources.GetType(armor.Resource) == CraftResourceType.Leather) - return m_LeatherArmor; - - return m_MetalArmor; - } - - if (item is BaseRanged) - return m_RangedWeapon; - if (item is BaseWeapon) - return m_Weapon; - if (item is BaseClothing) - return m_Clothing; - if (item is SpellScroll) - return m_Scroll; - - return null; - } - } -} \ No newline at end of file +using System; +using Server.Items; +using Server.Mobiles; + +namespace Server.Factions +{ + public class FactionItemDefinition + { + private static readonly FactionItemDefinition m_MetalArmor = new FactionItemDefinition(1000, typeof(Blacksmith)); + private static readonly FactionItemDefinition m_Weapon = new FactionItemDefinition(1000, typeof(Blacksmith)); + private static readonly FactionItemDefinition m_RangedWeapon = new FactionItemDefinition(1000, typeof(Bowyer)); + private static readonly FactionItemDefinition m_LeatherArmor = new FactionItemDefinition(750, typeof(Tailor)); + private static readonly FactionItemDefinition m_Clothing = new FactionItemDefinition(200, typeof(Tailor)); + private static readonly FactionItemDefinition m_Scroll = new FactionItemDefinition(500, typeof(Mage)); + + public FactionItemDefinition(int silverCost, Type vendorType) + { + SilverCost = silverCost; + VendorType = vendorType; + } + + public int SilverCost { get; } + + public Type VendorType { get; } + + public static FactionItemDefinition Identify(Item item) + { + if (item is BaseArmor armor) + { + if (CraftResources.GetType(armor.Resource) == CraftResourceType.Leather) + return m_LeatherArmor; + + return m_MetalArmor; + } + + if (item is BaseRanged) + return m_RangedWeapon; + if (item is BaseWeapon) + return m_Weapon; + if (item is BaseClothing) + return m_Clothing; + if (item is SpellScroll) + return m_Scroll; + + return null; + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Definitions/GuardDefinition.cs b/Projects/UOContent/Engines/Factions/Definitions/GuardDefinition.cs index 898587918..41de68a39 100644 --- a/Projects/UOContent/Engines/Factions/Definitions/GuardDefinition.cs +++ b/Projects/UOContent/Engines/Factions/Definitions/GuardDefinition.cs @@ -1,35 +1,37 @@ -using System; - -namespace Server.Factions -{ - public class GuardDefinition - { - public GuardDefinition(Type type, int itemID, int price, int upkeep, int maximum, TextDefinition header, - TextDefinition label) - { - Type = type; - - Price = price; - Upkeep = upkeep; - Maximum = maximum; - ItemID = itemID; - - Header = header; - Label = label; - } - - public Type Type { get; } - - public int Price { get; } - - public int Upkeep { get; } - - public int Maximum { get; } - - public int ItemID { get; } - - public TextDefinition Header { get; } - - public TextDefinition Label { get; } - } -} \ No newline at end of file +using System; + +namespace Server.Factions +{ + public class GuardDefinition + { + public GuardDefinition( + Type type, int itemID, int price, int upkeep, int maximum, TextDefinition header, + TextDefinition label + ) + { + Type = type; + + Price = price; + Upkeep = upkeep; + Maximum = maximum; + ItemID = itemID; + + Header = header; + Label = label; + } + + public Type Type { get; } + + public int Price { get; } + + public int Upkeep { get; } + + public int Maximum { get; } + + public int ItemID { get; } + + public TextDefinition Header { get; } + + public TextDefinition Label { get; } + } +} diff --git a/Projects/UOContent/Engines/Factions/Definitions/RankDefinition.cs b/Projects/UOContent/Engines/Factions/Definitions/RankDefinition.cs index fead57da9..cd61ab056 100644 --- a/Projects/UOContent/Engines/Factions/Definitions/RankDefinition.cs +++ b/Projects/UOContent/Engines/Factions/Definitions/RankDefinition.cs @@ -1,21 +1,21 @@ -namespace Server.Factions -{ - public class RankDefinition - { - public RankDefinition(int rank, int required, int maxWearables, TextDefinition title) - { - Rank = rank; - Required = required; - Title = title; - MaxWearables = maxWearables; - } - - public int Rank { get; } - - public int Required { get; } - - public int MaxWearables { get; } - - public TextDefinition Title { get; } - } -} \ No newline at end of file +namespace Server.Factions +{ + public class RankDefinition + { + public RankDefinition(int rank, int required, int maxWearables, TextDefinition title) + { + Rank = rank; + Required = required; + Title = title; + MaxWearables = maxWearables; + } + + public int Rank { get; } + + public int Required { get; } + + public int MaxWearables { get; } + + public TextDefinition Title { get; } + } +} diff --git a/Projects/UOContent/Engines/Factions/Definitions/StrongholdDefintion.cs b/Projects/UOContent/Engines/Factions/Definitions/StrongholdDefintion.cs index 3786265cb..e5dfc4d77 100644 --- a/Projects/UOContent/Engines/Factions/Definitions/StrongholdDefintion.cs +++ b/Projects/UOContent/Engines/Factions/Definitions/StrongholdDefintion.cs @@ -1,21 +1,21 @@ -namespace Server.Factions -{ - public class StrongholdDefinition - { - public StrongholdDefinition(Rectangle2D[] area, Point3D joinStone, Point3D factionStone, Point3D[] monoliths) - { - Area = area; - JoinStone = joinStone; - FactionStone = factionStone; - Monoliths = monoliths; - } - - public Rectangle2D[] Area { get; } - - public Point3D JoinStone { get; } - - public Point3D FactionStone { get; } - - public Point3D[] Monoliths { get; } - } -} \ No newline at end of file +namespace Server.Factions +{ + public class StrongholdDefinition + { + public StrongholdDefinition(Rectangle2D[] area, Point3D joinStone, Point3D factionStone, Point3D[] monoliths) + { + Area = area; + JoinStone = joinStone; + FactionStone = factionStone; + Monoliths = monoliths; + } + + public Rectangle2D[] Area { get; } + + public Point3D JoinStone { get; } + + public Point3D FactionStone { get; } + + public Point3D[] Monoliths { get; } + } +} diff --git a/Projects/UOContent/Engines/Factions/Definitions/TownDefinition.cs b/Projects/UOContent/Engines/Factions/Definitions/TownDefinition.cs index fa3076522..1cbc857c7 100644 --- a/Projects/UOContent/Engines/Factions/Definitions/TownDefinition.cs +++ b/Projects/UOContent/Engines/Factions/Definitions/TownDefinition.cs @@ -1,51 +1,53 @@ -namespace Server.Factions -{ - public class TownDefinition - { - public TownDefinition(int sort, int sigilID, string region, string friendlyName, TextDefinition townName, - TextDefinition townStoneHeader, TextDefinition strongholdMonolithName, TextDefinition townMonolithName, - TextDefinition townStoneName, TextDefinition sigilName, TextDefinition corruptedSigilName, Point3D monolith, - Point3D townStone) - { - Sort = sort; - SigilID = sigilID; - Region = region; - FriendlyName = friendlyName; - TownName = townName; - TownStoneHeader = townStoneHeader; - StrongholdMonolithName = strongholdMonolithName; - TownMonolithName = townMonolithName; - TownStoneName = townStoneName; - SigilName = sigilName; - CorruptedSigilName = corruptedSigilName; - Monolith = monolith; - TownStone = townStone; - } - - public int Sort { get; } - - public int SigilID { get; } - - public string Region { get; } - - public string FriendlyName { get; } - - public TextDefinition TownName { get; } - - public TextDefinition TownStoneHeader { get; } - - public TextDefinition StrongholdMonolithName { get; } - - public TextDefinition TownMonolithName { get; } - - public TextDefinition TownStoneName { get; } - - public TextDefinition SigilName { get; } - - public TextDefinition CorruptedSigilName { get; } - - public Point3D Monolith { get; } - - public Point3D TownStone { get; } - } -} \ No newline at end of file +namespace Server.Factions +{ + public class TownDefinition + { + public TownDefinition( + int sort, int sigilID, string region, string friendlyName, TextDefinition townName, + TextDefinition townStoneHeader, TextDefinition strongholdMonolithName, TextDefinition townMonolithName, + TextDefinition townStoneName, TextDefinition sigilName, TextDefinition corruptedSigilName, Point3D monolith, + Point3D townStone + ) + { + Sort = sort; + SigilID = sigilID; + Region = region; + FriendlyName = friendlyName; + TownName = townName; + TownStoneHeader = townStoneHeader; + StrongholdMonolithName = strongholdMonolithName; + TownMonolithName = townMonolithName; + TownStoneName = townStoneName; + SigilName = sigilName; + CorruptedSigilName = corruptedSigilName; + Monolith = monolith; + TownStone = townStone; + } + + public int Sort { get; } + + public int SigilID { get; } + + public string Region { get; } + + public string FriendlyName { get; } + + public TextDefinition TownName { get; } + + public TextDefinition TownStoneHeader { get; } + + public TextDefinition StrongholdMonolithName { get; } + + public TextDefinition TownMonolithName { get; } + + public TextDefinition TownStoneName { get; } + + public TextDefinition SigilName { get; } + + public TextDefinition CorruptedSigilName { get; } + + public Point3D Monolith { get; } + + public Point3D TownStone { get; } + } +} diff --git a/Projects/UOContent/Engines/Factions/Definitions/VendorDefinition.cs b/Projects/UOContent/Engines/Factions/Definitions/VendorDefinition.cs index a55f7acf0..9426dc8ac 100644 --- a/Projects/UOContent/Engines/Factions/Definitions/VendorDefinition.cs +++ b/Projects/UOContent/Engines/Factions/Definitions/VendorDefinition.cs @@ -1,69 +1,86 @@ -using System; - -namespace Server.Factions -{ - public class VendorDefinition - { - public VendorDefinition(Type type, int itemID, int price, int upkeep, int maximum, TextDefinition header, - TextDefinition label) - { - Type = type; - - Price = price; - Upkeep = upkeep; - Maximum = maximum; - ItemID = itemID; - - Header = header; - Label = label; - } - - public Type Type { get; } - - public int Price { get; } - - public int Upkeep { get; } - - public int Maximum { get; } - - public int ItemID { get; } - - public TextDefinition Header { get; } - - public TextDefinition Label { get; } - - public static VendorDefinition[] Definitions { get; } = - { - new VendorDefinition(typeof(FactionBottleVendor), 0xF0E, - 5000, - 1000, - 10, - new TextDefinition(1011549, "POTION BOTTLE VENDOR"), - new TextDefinition(1011544, "Buy Potion Bottle Vendor")), - new VendorDefinition(typeof(FactionBoardVendor), 0x1BD7, - 3000, - 500, - 10, - new TextDefinition(1011552, "WOOD VENDOR"), - new TextDefinition(1011545, "Buy Wooden Board Vendor")), - new VendorDefinition(typeof(FactionOreVendor), 0x19B8, - 3000, - 500, - 10, - new TextDefinition(1011553, "IRON ORE VENDOR"), - new TextDefinition(1011546, "Buy Iron Ore Vendor")), - new VendorDefinition(typeof(FactionReagentVendor), 0xF86, - 5000, - 1000, - 10, - new TextDefinition(1011554, "REAGENT VENDOR"), - new TextDefinition(1011547, "Buy Reagent Vendor")), - new VendorDefinition(typeof(FactionHorseVendor), 0x20DD, - 5000, - 1000, - 1, - new TextDefinition(1011556, "HORSE BREEDER"), - new TextDefinition(1011555, "Buy Horse Breeder")) - }; - } -} \ No newline at end of file +using System; + +namespace Server.Factions +{ + public class VendorDefinition + { + public VendorDefinition( + Type type, int itemID, int price, int upkeep, int maximum, TextDefinition header, + TextDefinition label + ) + { + Type = type; + + Price = price; + Upkeep = upkeep; + Maximum = maximum; + ItemID = itemID; + + Header = header; + Label = label; + } + + public Type Type { get; } + + public int Price { get; } + + public int Upkeep { get; } + + public int Maximum { get; } + + public int ItemID { get; } + + public TextDefinition Header { get; } + + public TextDefinition Label { get; } + + public static VendorDefinition[] Definitions { get; } = + { + new VendorDefinition( + typeof(FactionBottleVendor), + 0xF0E, + 5000, + 1000, + 10, + new TextDefinition(1011549, "POTION BOTTLE VENDOR"), + new TextDefinition(1011544, "Buy Potion Bottle Vendor") + ), + new VendorDefinition( + typeof(FactionBoardVendor), + 0x1BD7, + 3000, + 500, + 10, + new TextDefinition(1011552, "WOOD VENDOR"), + new TextDefinition(1011545, "Buy Wooden Board Vendor") + ), + new VendorDefinition( + typeof(FactionOreVendor), + 0x19B8, + 3000, + 500, + 10, + new TextDefinition(1011553, "IRON ORE VENDOR"), + new TextDefinition(1011546, "Buy Iron Ore Vendor") + ), + new VendorDefinition( + typeof(FactionReagentVendor), + 0xF86, + 5000, + 1000, + 10, + new TextDefinition(1011554, "REAGENT VENDOR"), + new TextDefinition(1011547, "Buy Reagent Vendor") + ), + new VendorDefinition( + typeof(FactionHorseVendor), + 0x20DD, + 5000, + 1000, + 1, + new TextDefinition(1011556, "HORSE BREEDER"), + new TextDefinition(1011555, "Buy Horse Breeder") + ) + }; + } +} diff --git a/Projects/UOContent/Engines/Factions/Gumps/ElectionGump.cs b/Projects/UOContent/Engines/Factions/Gumps/ElectionGump.cs index 6efcca991..f1045ec38 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/ElectionGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/ElectionGump.cs @@ -1,127 +1,127 @@ -using System; -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Factions -{ - public class ElectionGump : FactionGump - { - private readonly Election m_Election; - private readonly PlayerMobile m_From; - - public ElectionGump(PlayerMobile from, Election election) : base(50, 50) - { - m_From = from; - m_Election = election; - - AddPage(0); - - AddBackground(0, 0, 420, 180, 5054); - AddBackground(10, 10, 400, 160, 3000); - - AddHtmlText(20, 20, 380, 20, election.Faction.Definition.Header, false, false); - - // NOTE: Gump not entirely OSI-accurate, intentionally so - - switch (election.State) - { - case ElectionState.Pending: - { - TimeSpan toGo = election.LastStateTime + Election.PendingPeriod - DateTime.UtcNow; - int days = (int)(toGo.TotalDays + 0.5); - - AddHtmlLocalized(20, 40, 380, 20, 1038034); // A new election campaign is pending - - if (days > 0) - { - AddHtmlLocalized(20, 60, 280, 20, 1018062); // Days until next election : - AddLabel(300, 60, 0, days.ToString()); - } - else - { - AddHtmlLocalized(20, 60, 280, 20, 1018059); // Election campaigning begins tonight. - } - - break; - } - case ElectionState.Campaign: - { - TimeSpan toGo = election.LastStateTime + Election.CampaignPeriod - DateTime.UtcNow; - int days = (int)(toGo.TotalDays + 0.5); - - AddHtmlLocalized(20, 40, 380, 20, 1018058); // There is an election campaign in progress. - - if (days > 0) - { - AddHtmlLocalized(20, 60, 280, 20, 1038033); // Days to go: - AddLabel(300, 60, 0, days.ToString()); - } - else - { - AddHtmlLocalized(20, 60, 280, 20, 1018061); // Campaign in progress. Voting begins tonight. - } - - if (m_Election.CanBeCandidate(m_From)) - { - AddButton(20, 110, 4005, 4007, 2); - AddHtmlLocalized(55, 110, 350, 20, 1011427); // CAMPAIGN FOR LEADERSHIP - } - else - { - PlayerState pl = PlayerState.Find(m_From); - - if (pl == null || pl.Rank.Rank < Election.CandidateRank) - AddHtmlLocalized(20, 100, 380, 20, 1010118); // You must have a higher rank to run for office - } - - break; - } - case ElectionState.Election: - { - TimeSpan toGo = election.LastStateTime + Election.VotingPeriod - DateTime.UtcNow; - int days = (int)Math.Ceiling(toGo.TotalDays); - - AddHtmlLocalized(20, 40, 380, 20, 1018060); // There is an election vote in progress. - - AddHtmlLocalized(20, 60, 280, 20, 1038033); - AddLabel(300, 60, 0, days.ToString()); - - AddHtmlLocalized(55, 100, 380, 20, 1011428); // VOTE FOR LEADERSHIP - AddButton(20, 100, 4005, 4007, 1); - - break; - } - } - - AddButton(20, 140, 4005, 4007, 0); - AddHtmlLocalized(55, 140, 350, 20, 1011012); // CANCEL - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - switch (info.ButtonID) - { - case 0: // back - { - m_From.SendGump(new FactionStoneGump(m_From, m_Election.Faction)); - break; - } - case 1: // vote - { - if (m_Election.State == ElectionState.Election) - m_From.SendGump(new VoteGump(m_From, m_Election)); - - break; - } - case 2: // campaign - { - if (m_Election.CanBeCandidate(m_From)) - m_Election.AddCandidate(m_From); - - break; - } - } - } - } -} +using System; +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Factions +{ + public class ElectionGump : FactionGump + { + private readonly Election m_Election; + private readonly PlayerMobile m_From; + + public ElectionGump(PlayerMobile from, Election election) : base(50, 50) + { + m_From = from; + m_Election = election; + + AddPage(0); + + AddBackground(0, 0, 420, 180, 5054); + AddBackground(10, 10, 400, 160, 3000); + + AddHtmlText(20, 20, 380, 20, election.Faction.Definition.Header, false, false); + + // NOTE: Gump not entirely OSI-accurate, intentionally so + + switch (election.State) + { + case ElectionState.Pending: + { + var toGo = election.LastStateTime + Election.PendingPeriod - DateTime.UtcNow; + var days = (int)(toGo.TotalDays + 0.5); + + AddHtmlLocalized(20, 40, 380, 20, 1038034); // A new election campaign is pending + + if (days > 0) + { + AddHtmlLocalized(20, 60, 280, 20, 1018062); // Days until next election : + AddLabel(300, 60, 0, days.ToString()); + } + else + { + AddHtmlLocalized(20, 60, 280, 20, 1018059); // Election campaigning begins tonight. + } + + break; + } + case ElectionState.Campaign: + { + var toGo = election.LastStateTime + Election.CampaignPeriod - DateTime.UtcNow; + var days = (int)(toGo.TotalDays + 0.5); + + AddHtmlLocalized(20, 40, 380, 20, 1018058); // There is an election campaign in progress. + + if (days > 0) + { + AddHtmlLocalized(20, 60, 280, 20, 1038033); // Days to go: + AddLabel(300, 60, 0, days.ToString()); + } + else + { + AddHtmlLocalized(20, 60, 280, 20, 1018061); // Campaign in progress. Voting begins tonight. + } + + if (m_Election.CanBeCandidate(m_From)) + { + AddButton(20, 110, 4005, 4007, 2); + AddHtmlLocalized(55, 110, 350, 20, 1011427); // CAMPAIGN FOR LEADERSHIP + } + else + { + var pl = PlayerState.Find(m_From); + + if (pl == null || pl.Rank.Rank < Election.CandidateRank) + AddHtmlLocalized(20, 100, 380, 20, 1010118); // You must have a higher rank to run for office + } + + break; + } + case ElectionState.Election: + { + var toGo = election.LastStateTime + Election.VotingPeriod - DateTime.UtcNow; + var days = (int)Math.Ceiling(toGo.TotalDays); + + AddHtmlLocalized(20, 40, 380, 20, 1018060); // There is an election vote in progress. + + AddHtmlLocalized(20, 60, 280, 20, 1038033); + AddLabel(300, 60, 0, days.ToString()); + + AddHtmlLocalized(55, 100, 380, 20, 1011428); // VOTE FOR LEADERSHIP + AddButton(20, 100, 4005, 4007, 1); + + break; + } + } + + AddButton(20, 140, 4005, 4007, 0); + AddHtmlLocalized(55, 140, 350, 20, 1011012); // CANCEL + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + switch (info.ButtonID) + { + case 0: // back + { + m_From.SendGump(new FactionStoneGump(m_From, m_Election.Faction)); + break; + } + case 1: // vote + { + if (m_Election.State == ElectionState.Election) + m_From.SendGump(new VoteGump(m_From, m_Election)); + + break; + } + case 2: // campaign + { + if (m_Election.CanBeCandidate(m_From)) + m_Election.AddCandidate(m_From); + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Gumps/ElectionManagementGump.cs b/Projects/UOContent/Engines/Factions/Gumps/ElectionManagementGump.cs index 6a5fb1f69..4a25cde0c 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/ElectionManagementGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/ElectionManagementGump.cs @@ -1,201 +1,207 @@ -using System; -using System.Net; -using Server.Gumps; -using Server.Network; - -namespace Server.Factions -{ - public class ElectionManagementGump : Gump - { - public const int LabelColor = 0xFFFFFF; - private readonly Candidate m_Candidate; - - private readonly Election m_Election; - private readonly int m_Page; - - public ElectionManagementGump(Election election, Candidate candidate = null, int page = 0) : base(40, 40) - { - m_Election = election; - m_Candidate = candidate; - m_Page = page; - - AddPage(0); - - if (candidate != null) - { - AddBackground(0, 0, 448, 354, 9270); - AddAlphaRegion(10, 10, 428, 334); - - AddHtml(10, 10, 428, 20, Color(Center("Candidate Management"), LabelColor)); - - AddHtml(45, 35, 100, 20, Color("Player Name:", LabelColor)); - AddHtml(145, 35, 100, 20, Color(candidate.Mobile == null ? "null" : candidate.Mobile.Name, LabelColor)); - - AddHtml(45, 55, 100, 20, Color("Vote Count:", LabelColor)); - AddHtml(145, 55, 100, 20, Color(candidate.Votes.ToString(), LabelColor)); - - AddButton(12, 73, 4005, 4007, 1); - AddHtml(45, 75, 100, 20, Color("Drop Candidate", LabelColor)); - - AddImageTiled(13, 99, 422, 242, 9264); - AddImageTiled(14, 100, 420, 240, 9274); - AddAlphaRegion(14, 100, 420, 240); - - AddHtml(14, 100, 420, 20, Color(Center("Voters"), LabelColor)); - - if (page > 0) - AddButton(397, 104, 0x15E3, 0x15E7, 2); - else - AddImage(397, 104, 0x25EA); - - if ((page + 1) * 10 < candidate.Voters.Count) - AddButton(414, 104, 0x15E1, 0x15E5, 3); - else - AddImage(414, 104, 0x25E6); - - AddHtml(14, 120, 30, 20, Color(Center("DEL"), LabelColor)); - AddHtml(47, 120, 150, 20, Color("Name", LabelColor)); - AddHtml(195, 120, 100, 20, Color(Center("Address"), LabelColor)); - AddHtml(295, 120, 80, 20, Color(Center("Time"), LabelColor)); - AddHtml(355, 120, 60, 20, Color(Center("Legit"), LabelColor)); - - int idx = 0; - - for (int i = page * 10; i >= 0 && i < candidate.Voters.Count && i < (page + 1) * 10; ++i, ++idx) - { - Voter voter = candidate.Voters[i]; - - AddButton(13, 138 + idx * 20, 4002, 4004, 4 + i); - - object[] fields = voter.AcquireFields(); - - int x = 45; - - for (int j = 0; j < fields.Length; ++j) - { - object obj = fields[j]; - - if (obj is Mobile mobile) - { - AddHtml(x + 2, 140 + idx * 20, 150, 20, Color(mobile.Name, LabelColor)); - x += 150; - } - else if (obj is IPAddress) - { - AddHtml(x, 140 + idx * 20, 100, 20, Color(Center(obj.ToString()), LabelColor)); - x += 100; - } - else if (obj is DateTime time) - { - AddHtml(x, 140 + idx * 20, 80, 20, - Color(Center(FormatTimeSpan(time - election.LastStateTime)), LabelColor)); - x += 80; - } - else if (obj is int i1) - { - AddHtml(x, 140 + idx * 20, 60, 20, Color(Center($"{i1}%"), LabelColor)); - x += 60; - } - } - } - } - else - { - AddBackground(0, 0, 288, 334, 9270); - AddAlphaRegion(10, 10, 268, 314); - - AddHtml(10, 10, 268, 20, Color(Center("Election Management"), LabelColor)); - - AddHtml(45, 35, 100, 20, Color("Current State:", LabelColor)); - AddHtml(145, 35, 100, 20, Color(election.State.ToString(), LabelColor)); - - AddButton(12, 53, 4005, 4007, 1); - AddHtml(45, 55, 100, 20, Color("Transition Time:", LabelColor)); - AddHtml(145, 55, 100, 20, Color(FormatTimeSpan(election.NextStateTime), LabelColor)); - - AddImageTiled(13, 79, 262, 242, 9264); - AddImageTiled(14, 80, 260, 240, 9274); - AddAlphaRegion(14, 80, 260, 240); - - AddHtml(14, 80, 260, 20, Color(Center("Candidates"), LabelColor)); - AddHtml(14, 100, 30, 20, Color(Center("-->"), LabelColor)); - AddHtml(47, 100, 150, 20, Color("Name", LabelColor)); - AddHtml(195, 100, 80, 20, Color(Center("Votes"), LabelColor)); - - for (int i = 0; i < election.Candidates.Count; ++i) - { - Candidate cd = election.Candidates[i]; - Mobile mob = cd.Mobile; - - if (mob == null) - continue; - - AddButton(13, 118 + i * 20, 4005, 4007, 2 + i); - AddHtml(47, 120 + i * 20, 150, 20, Color(mob.Name, LabelColor)); - AddHtml(195, 120 + i * 20, 80, 20, Color(Center(cd.Votes.ToString()), LabelColor)); - } - } - } - - public string Right(string text) => $"
{text}
"; - - public string Center(string text) => $"
{text}
"; - - public string Color(string text, int color) => $"{text}"; - - public static string FormatTimeSpan(TimeSpan ts) => $"{ts.Days:D2}:{ts.Hours % 24:D2}:{ts.Minutes % 60:D2}:{ts.Seconds % 60:D2}"; - - public override void OnResponse(NetState sender, RelayInfo info) - { - Mobile from = sender.Mobile; - int bid = info.ButtonID; - - if (m_Candidate == null) - { - if (bid == 0) - { - } - else if (bid == 1) - { - } - else - { - bid -= 2; - - if (bid >= 0 && bid < m_Election.Candidates.Count) - from.SendGump(new ElectionManagementGump(m_Election, m_Election.Candidates[bid])); - } - } - else - { - if (bid == 0) - { - from.SendGump(new ElectionManagementGump(m_Election)); - } - else if (bid == 1) - { - m_Election.RemoveCandidate(m_Candidate.Mobile); - from.SendGump(new ElectionManagementGump(m_Election)); - } - else if (bid == 2 && m_Page > 0) - { - from.SendGump(new ElectionManagementGump(m_Election, m_Candidate, m_Page - 1)); - } - else if (bid == 3 && (m_Page + 1) * 10 < m_Candidate.Voters.Count) - { - from.SendGump(new ElectionManagementGump(m_Election, m_Candidate, m_Page + 1)); - } - else - { - bid -= 4; - - if (bid >= 0 && bid < m_Candidate.Voters.Count) - { - m_Candidate.Voters.RemoveAt(bid); - from.SendGump(new ElectionManagementGump(m_Election, m_Candidate, m_Page)); - } - } - } - } - } -} +using System; +using System.Net; +using Server.Gumps; +using Server.Network; + +namespace Server.Factions +{ + public class ElectionManagementGump : Gump + { + public const int LabelColor = 0xFFFFFF; + private readonly Candidate m_Candidate; + + private readonly Election m_Election; + private readonly int m_Page; + + public ElectionManagementGump(Election election, Candidate candidate = null, int page = 0) : base(40, 40) + { + m_Election = election; + m_Candidate = candidate; + m_Page = page; + + AddPage(0); + + if (candidate != null) + { + AddBackground(0, 0, 448, 354, 9270); + AddAlphaRegion(10, 10, 428, 334); + + AddHtml(10, 10, 428, 20, Color(Center("Candidate Management"), LabelColor)); + + AddHtml(45, 35, 100, 20, Color("Player Name:", LabelColor)); + AddHtml(145, 35, 100, 20, Color(candidate.Mobile == null ? "null" : candidate.Mobile.Name, LabelColor)); + + AddHtml(45, 55, 100, 20, Color("Vote Count:", LabelColor)); + AddHtml(145, 55, 100, 20, Color(candidate.Votes.ToString(), LabelColor)); + + AddButton(12, 73, 4005, 4007, 1); + AddHtml(45, 75, 100, 20, Color("Drop Candidate", LabelColor)); + + AddImageTiled(13, 99, 422, 242, 9264); + AddImageTiled(14, 100, 420, 240, 9274); + AddAlphaRegion(14, 100, 420, 240); + + AddHtml(14, 100, 420, 20, Color(Center("Voters"), LabelColor)); + + if (page > 0) + AddButton(397, 104, 0x15E3, 0x15E7, 2); + else + AddImage(397, 104, 0x25EA); + + if ((page + 1) * 10 < candidate.Voters.Count) + AddButton(414, 104, 0x15E1, 0x15E5, 3); + else + AddImage(414, 104, 0x25E6); + + AddHtml(14, 120, 30, 20, Color(Center("DEL"), LabelColor)); + AddHtml(47, 120, 150, 20, Color("Name", LabelColor)); + AddHtml(195, 120, 100, 20, Color(Center("Address"), LabelColor)); + AddHtml(295, 120, 80, 20, Color(Center("Time"), LabelColor)); + AddHtml(355, 120, 60, 20, Color(Center("Legit"), LabelColor)); + + var idx = 0; + + for (var i = page * 10; i >= 0 && i < candidate.Voters.Count && i < (page + 1) * 10; ++i, ++idx) + { + var voter = candidate.Voters[i]; + + AddButton(13, 138 + idx * 20, 4002, 4004, 4 + i); + + var fields = voter.AcquireFields(); + + var x = 45; + + for (var j = 0; j < fields.Length; ++j) + { + var obj = fields[j]; + + if (obj is Mobile mobile) + { + AddHtml(x + 2, 140 + idx * 20, 150, 20, Color(mobile.Name, LabelColor)); + x += 150; + } + else if (obj is IPAddress) + { + AddHtml(x, 140 + idx * 20, 100, 20, Color(Center(obj.ToString()), LabelColor)); + x += 100; + } + else if (obj is DateTime time) + { + AddHtml( + x, + 140 + idx * 20, + 80, + 20, + Color(Center(FormatTimeSpan(time - election.LastStateTime)), LabelColor) + ); + x += 80; + } + else if (obj is int i1) + { + AddHtml(x, 140 + idx * 20, 60, 20, Color(Center($"{i1}%"), LabelColor)); + x += 60; + } + } + } + } + else + { + AddBackground(0, 0, 288, 334, 9270); + AddAlphaRegion(10, 10, 268, 314); + + AddHtml(10, 10, 268, 20, Color(Center("Election Management"), LabelColor)); + + AddHtml(45, 35, 100, 20, Color("Current State:", LabelColor)); + AddHtml(145, 35, 100, 20, Color(election.State.ToString(), LabelColor)); + + AddButton(12, 53, 4005, 4007, 1); + AddHtml(45, 55, 100, 20, Color("Transition Time:", LabelColor)); + AddHtml(145, 55, 100, 20, Color(FormatTimeSpan(election.NextStateTime), LabelColor)); + + AddImageTiled(13, 79, 262, 242, 9264); + AddImageTiled(14, 80, 260, 240, 9274); + AddAlphaRegion(14, 80, 260, 240); + + AddHtml(14, 80, 260, 20, Color(Center("Candidates"), LabelColor)); + AddHtml(14, 100, 30, 20, Color(Center("-->"), LabelColor)); + AddHtml(47, 100, 150, 20, Color("Name", LabelColor)); + AddHtml(195, 100, 80, 20, Color(Center("Votes"), LabelColor)); + + for (var i = 0; i < election.Candidates.Count; ++i) + { + var cd = election.Candidates[i]; + var mob = cd.Mobile; + + if (mob == null) + continue; + + AddButton(13, 118 + i * 20, 4005, 4007, 2 + i); + AddHtml(47, 120 + i * 20, 150, 20, Color(mob.Name, LabelColor)); + AddHtml(195, 120 + i * 20, 80, 20, Color(Center(cd.Votes.ToString()), LabelColor)); + } + } + } + + public string Right(string text) => $"
{text}
"; + + public string Center(string text) => $"
{text}
"; + + public string Color(string text, int color) => $"{text}"; + + public static string FormatTimeSpan(TimeSpan ts) => + $"{ts.Days:D2}:{ts.Hours % 24:D2}:{ts.Minutes % 60:D2}:{ts.Seconds % 60:D2}"; + + public override void OnResponse(NetState sender, RelayInfo info) + { + var from = sender.Mobile; + var bid = info.ButtonID; + + if (m_Candidate == null) + { + if (bid == 0) + { + } + else if (bid == 1) + { + } + else + { + bid -= 2; + + if (bid >= 0 && bid < m_Election.Candidates.Count) + from.SendGump(new ElectionManagementGump(m_Election, m_Election.Candidates[bid])); + } + } + else + { + if (bid == 0) + { + from.SendGump(new ElectionManagementGump(m_Election)); + } + else if (bid == 1) + { + m_Election.RemoveCandidate(m_Candidate.Mobile); + from.SendGump(new ElectionManagementGump(m_Election)); + } + else if (bid == 2 && m_Page > 0) + { + from.SendGump(new ElectionManagementGump(m_Election, m_Candidate, m_Page - 1)); + } + else if (bid == 3 && (m_Page + 1) * 10 < m_Candidate.Voters.Count) + { + from.SendGump(new ElectionManagementGump(m_Election, m_Candidate, m_Page + 1)); + } + else + { + bid -= 4; + + if (bid >= 0 && bid < m_Candidate.Voters.Count) + { + m_Candidate.Voters.RemoveAt(bid); + from.SendGump(new ElectionManagementGump(m_Election, m_Candidate, m_Page)); + } + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Gumps/FactionGump.cs b/Projects/UOContent/Engines/Factions/Gumps/FactionGump.cs index 328bf5956..f8266e5a1 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/FactionGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/FactionGump.cs @@ -1,40 +1,40 @@ -using Server.Gumps; - -namespace Server.Factions -{ - public abstract class FactionGump : Gump - { - public FactionGump(int x, int y) : base(x, y) - { - } - - public virtual int ButtonTypes => 10; - - public int ToButtonID(int type, int index) => 1 + index * ButtonTypes + type; - - public bool FromButtonID(int buttonID, out int type, out int index) - { - int offset = buttonID - 1; - - if (offset >= 0) - { - type = offset % ButtonTypes; - index = offset / ButtonTypes; - return true; - } - - type = index = 0; - return false; - } - - public static bool Exists(Mobile mob) => mob.HasGump(); - - public void AddHtmlText(int x, int y, int width, int height, TextDefinition text, bool back, bool scroll) - { - if (text?.Number > 0) - AddHtmlLocalized(x, y, width, height, text.Number, back, scroll); - else if (text?.String != null) - AddHtml(x, y, width, height, text.String, back, scroll); - } - } -} +using Server.Gumps; + +namespace Server.Factions +{ + public abstract class FactionGump : Gump + { + public FactionGump(int x, int y) : base(x, y) + { + } + + public virtual int ButtonTypes => 10; + + public int ToButtonID(int type, int index) => 1 + index * ButtonTypes + type; + + public bool FromButtonID(int buttonID, out int type, out int index) + { + var offset = buttonID - 1; + + if (offset >= 0) + { + type = offset % ButtonTypes; + index = offset / ButtonTypes; + return true; + } + + type = index = 0; + return false; + } + + public static bool Exists(Mobile mob) => mob.HasGump(); + + public void AddHtmlText(int x, int y, int width, int height, TextDefinition text, bool back, bool scroll) + { + if (text?.Number > 0) + AddHtmlLocalized(x, y, width, height, text.Number, back, scroll); + else if (text?.String != null) + AddHtml(x, y, width, height, text.String, back, scroll); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Gumps/FactionImbueGump.cs b/Projects/UOContent/Engines/Factions/Gumps/FactionImbueGump.cs index 4afb17db1..10631f165 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/FactionImbueGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/FactionImbueGump.cs @@ -1,97 +1,99 @@ -using Server.Engines.Craft; -using Server.Gumps; -using Server.Items; -using Server.Network; - -namespace Server.Factions -{ - public class FactionImbueGump : FactionGump - { - private readonly CraftSystem m_CraftSystem; - - private readonly FactionItemDefinition m_Definition; - private readonly Faction m_Faction; - private readonly Item m_Item; - private readonly Mobile m_Mobile; - private readonly object m_Notice; - private readonly BaseTool m_Tool; - - public FactionImbueGump(int quality, Item item, Mobile from, CraftSystem craftSystem, BaseTool tool, object notice, - int availableSilver, Faction faction, FactionItemDefinition def) : base(100, 200) - { - m_Item = item; - m_Mobile = from; - m_Faction = faction; - m_CraftSystem = craftSystem; - m_Tool = tool; - m_Notice = notice; - m_Definition = def; - - AddPage(0); - - AddBackground(0, 0, 320, 270, 5054); - AddBackground(10, 10, 300, 250, 3000); - - AddHtmlLocalized(20, 20, 210, 25, 1011569); // Imbue with Faction properties? - - AddHtmlLocalized(20, 60, 170, 25, 1018302); // Item quality: - AddHtmlLocalized(175, 60, 100, 25, 1018305 - quality); // Exceptional, Average, Low - - AddHtmlLocalized(20, 80, 170, 25, 1011572); // Item Cost : - AddLabel(175, 80, 0x34, def.SilverCost.ToString("N0")); // NOTE: Added 'N0' - - AddHtmlLocalized(20, 100, 170, 25, 1011573); // Your Silver : - AddLabel(175, 100, 0x34, availableSilver.ToString("N0")); // NOTE: Added 'N0' - - AddRadio(20, 140, 210, 211, true, 1); - AddLabel(55, 140, m_Faction.Definition.HuePrimary - 1, "*****"); - AddHtmlLocalized(150, 140, 150, 25, 1011570); // Primary Color - - AddRadio(20, 160, 210, 211, false, 2); - AddLabel(55, 160, m_Faction.Definition.HueSecondary - 1, "*****"); - AddHtmlLocalized(150, 160, 150, 25, 1011571); // Secondary Color - - AddHtmlLocalized(55, 200, 200, 25, 1011011); // CONTINUE - AddButton(20, 200, 4005, 4007, 1); - - AddHtmlLocalized(55, 230, 200, 25, 1011012); // CANCEL - AddButton(20, 230, 4005, 4007, 0); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 1) - { - Container pack = m_Mobile.Backpack; - - if (pack != null && m_Item.IsChildOf(pack)) - { - if (pack.ConsumeTotal(typeof(Silver), m_Definition.SilverCost)) - { - int hue; - - if (m_Item is SpellScroll) - hue = 0; - else if (info.IsSwitched(1)) - hue = m_Faction.Definition.HuePrimary; - else - hue = m_Faction.Definition.HueSecondary; - - FactionItem.Imbue(m_Item, m_Faction, true, hue); - } - else - { - m_Mobile.SendLocalizedMessage(1042204); // You do not have enough silver. - } - } - } - - if (m_Tool?.Deleted == false && m_Tool.UsesRemaining > 0) - m_Mobile.SendGump(new CraftGump(m_Mobile, m_CraftSystem, m_Tool, m_Notice)); - else if (m_Notice is string s) - m_Mobile.SendMessage(s); - else if (m_Notice is int i && i > 0) - m_Mobile.SendLocalizedMessage(i); - } - } -} +using Server.Engines.Craft; +using Server.Gumps; +using Server.Items; +using Server.Network; + +namespace Server.Factions +{ + public class FactionImbueGump : FactionGump + { + private readonly CraftSystem m_CraftSystem; + + private readonly FactionItemDefinition m_Definition; + private readonly Faction m_Faction; + private readonly Item m_Item; + private readonly Mobile m_Mobile; + private readonly object m_Notice; + private readonly BaseTool m_Tool; + + public FactionImbueGump( + int quality, Item item, Mobile from, CraftSystem craftSystem, BaseTool tool, object notice, + int availableSilver, Faction faction, FactionItemDefinition def + ) : base(100, 200) + { + m_Item = item; + m_Mobile = from; + m_Faction = faction; + m_CraftSystem = craftSystem; + m_Tool = tool; + m_Notice = notice; + m_Definition = def; + + AddPage(0); + + AddBackground(0, 0, 320, 270, 5054); + AddBackground(10, 10, 300, 250, 3000); + + AddHtmlLocalized(20, 20, 210, 25, 1011569); // Imbue with Faction properties? + + AddHtmlLocalized(20, 60, 170, 25, 1018302); // Item quality: + AddHtmlLocalized(175, 60, 100, 25, 1018305 - quality); // Exceptional, Average, Low + + AddHtmlLocalized(20, 80, 170, 25, 1011572); // Item Cost : + AddLabel(175, 80, 0x34, def.SilverCost.ToString("N0")); // NOTE: Added 'N0' + + AddHtmlLocalized(20, 100, 170, 25, 1011573); // Your Silver : + AddLabel(175, 100, 0x34, availableSilver.ToString("N0")); // NOTE: Added 'N0' + + AddRadio(20, 140, 210, 211, true, 1); + AddLabel(55, 140, m_Faction.Definition.HuePrimary - 1, "*****"); + AddHtmlLocalized(150, 140, 150, 25, 1011570); // Primary Color + + AddRadio(20, 160, 210, 211, false, 2); + AddLabel(55, 160, m_Faction.Definition.HueSecondary - 1, "*****"); + AddHtmlLocalized(150, 160, 150, 25, 1011571); // Secondary Color + + AddHtmlLocalized(55, 200, 200, 25, 1011011); // CONTINUE + AddButton(20, 200, 4005, 4007, 1); + + AddHtmlLocalized(55, 230, 200, 25, 1011012); // CANCEL + AddButton(20, 230, 4005, 4007, 0); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 1) + { + var pack = m_Mobile.Backpack; + + if (pack != null && m_Item.IsChildOf(pack)) + { + if (pack.ConsumeTotal(typeof(Silver), m_Definition.SilverCost)) + { + int hue; + + if (m_Item is SpellScroll) + hue = 0; + else if (info.IsSwitched(1)) + hue = m_Faction.Definition.HuePrimary; + else + hue = m_Faction.Definition.HueSecondary; + + FactionItem.Imbue(m_Item, m_Faction, true, hue); + } + else + { + m_Mobile.SendLocalizedMessage(1042204); // You do not have enough silver. + } + } + } + + if (m_Tool?.Deleted == false && m_Tool.UsesRemaining > 0) + m_Mobile.SendGump(new CraftGump(m_Mobile, m_CraftSystem, m_Tool, m_Notice)); + else if (m_Notice is string s) + m_Mobile.SendMessage(s); + else if (m_Notice is int i && i > 0) + m_Mobile.SendLocalizedMessage(i); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Gumps/FactionStoneGump.cs b/Projects/UOContent/Engines/Factions/Gumps/FactionStoneGump.cs index d3268183d..70bdceb93 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/FactionStoneGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/FactionStoneGump.cs @@ -1,324 +1,323 @@ -using System.Collections.Generic; -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Factions -{ - public class FactionStoneGump : FactionGump - { - private readonly Faction m_Faction; - private readonly PlayerMobile m_From; - - public FactionStoneGump(PlayerMobile from, Faction faction) : base(20, 30) - { - m_From = from; - m_Faction = faction; - - AddPage(0); - - AddBackground(0, 0, 550, 440, 5054); - AddBackground(10, 10, 530, 420, 3000); - - AddPage(1); - - AddHtmlText(20, 30, 510, 20, faction.Definition.Header, false, false); - - AddHtmlLocalized(20, 60, 100, 20, 1011429); // Led By : - AddHtml(125, 60, 200, 20, faction.Commander != null ? faction.Commander.Name : "Nobody"); - - AddHtmlLocalized(20, 80, 100, 20, 1011457); // Tithe rate : - if (faction.Tithe >= 0 && faction.Tithe <= 100 && faction.Tithe % 10 == 0) - AddHtmlLocalized(125, 80, 350, 20, 1011480 + faction.Tithe / 10); - else - AddHtml(125, 80, 350, 20, $"{faction.Tithe}%"); - - AddHtmlLocalized(20, 100, 100, 20, 1011458); // Traps placed : - AddHtml(125, 100, 50, 20, faction.Traps.Count.ToString()); - - AddHtmlLocalized(55, 225, 200, 20, 1011428); // VOTE FOR LEADERSHIP - AddButton(20, 225, 4005, 4007, ToButtonID(0, 0)); - - AddHtmlLocalized(55, 150, 100, 20, 1011430); // CITY STATUS - AddButton(20, 150, 4005, 4007, 0, GumpButtonType.Page, 2); - - AddHtmlLocalized(55, 175, 100, 20, 1011444); // STATISTICS - AddButton(20, 175, 4005, 4007, 0, GumpButtonType.Page, 4); - - bool isMerchantQualified = MerchantTitles.HasMerchantQualifications(from); - - PlayerState pl = PlayerState.Find(from); - - if (pl != null && pl.MerchantTitle != MerchantTitle.None) - { - AddHtmlLocalized(55, 200, 250, 20, 1011460); // UNDECLARE FACTION MERCHANT - AddButton(20, 200, 4005, 4007, ToButtonID(1, 0)); - } - else if (isMerchantQualified) - { - AddHtmlLocalized(55, 200, 250, 20, 1011459); // DECLARE FACTION MERCHANT - AddButton(20, 200, 4005, 4007, 0, GumpButtonType.Page, 5); - } - else - { - AddHtmlLocalized(55, 200, 250, 20, 1011467); // MERCHANT OPTIONS - AddImage(20, 200, 4020); - } - - AddHtmlLocalized(55, 250, 300, 20, 1011461); // COMMANDER OPTIONS - if (faction.IsCommander(from)) - AddButton(20, 250, 4005, 4007, 0, GumpButtonType.Page, 6); - else - AddImage(20, 250, 4020); - - AddHtmlLocalized(55, 275, 300, 20, 1011426); // LEAVE THIS FACTION - AddButton(20, 275, 4005, 4007, ToButtonID(0, 1)); - - AddHtmlLocalized(55, 300, 200, 20, 1011441); // EXIT - AddButton(20, 300, 4005, 4007, 0); - - AddPage(2); - - AddHtmlLocalized(20, 30, 250, 20, 1011430); // CITY STATUS - - List towns = Town.Towns; - - for (int i = 0; i < towns.Count; ++i) - { - Town town = towns[i]; - - AddHtmlText(40, 55 + i * 30, 150, 20, town.Definition.TownName, false, false); - - if (town.Owner == null) - { - AddHtmlLocalized(200, 55 + i * 30, 150, 20, 1011462); // : Neutral - } - else - { - AddHtmlLocalized(200, 55 + i * 30, 150, 20, town.Owner.Definition.OwnerLabel); - - BaseMonolith monolith = town.Monolith; - - AddImage(20, 60 + i * 30, monolith?.Sigil?.IsPurifying == true ? 0x938 : 0x939); - } - } - - AddImage(20, 300, 2361); - AddHtmlLocalized(45, 295, 300, 20, 1011491); // sigil may be recaptured - - AddImage(20, 320, 2360); - AddHtmlLocalized(45, 315, 300, 20, 1011492); // sigil may not be recaptured - - AddHtmlLocalized(55, 350, 100, 20, 1011447); // BACK - AddButton(20, 350, 4005, 4007, 0, GumpButtonType.Page, 1); - - AddPage(4); - - AddHtmlLocalized(20, 30, 150, 20, 1011444); // STATISTICS - - AddHtmlLocalized(20, 100, 100, 20, 1011445); // Name : - AddHtml(120, 100, 150, 20, from.Name); - - AddHtmlLocalized(20, 130, 100, 20, 1018064); // score : - AddHtml(120, 130, 100, 20, (pl?.KillPoints ?? 0).ToString()); - - AddHtmlLocalized(20, 160, 100, 20, 1011446); // Rank : - AddHtml(120, 160, 100, 20, (pl?.Rank.Rank ?? 0).ToString()); - - AddHtmlLocalized(55, 250, 100, 20, 1011447); // BACK - AddButton(20, 250, 4005, 4007, 0, GumpButtonType.Page, 1); - - if ((pl == null || pl.MerchantTitle == MerchantTitle.None) && isMerchantQualified) - { - AddPage(5); - - AddHtmlLocalized(20, 30, 250, 20, 1011467); // MERCHANT OPTIONS - - AddHtmlLocalized(20, 80, 300, 20, 1011473); // Select the title you wish to display - - MerchantTitleInfo[] infos = MerchantTitles.Info; - - for (int i = 0; i < infos.Length; ++i) - { - MerchantTitleInfo info = infos[i]; - - if (MerchantTitles.IsQualified(from, info)) - AddButton(20, 100 + i * 30, 4005, 4007, ToButtonID(1, i + 1)); - else - AddImage(20, 100 + i * 30, 4020); - - AddHtmlText(55, 100 + i * 30, 200, 20, info.Label, false, false); - } - - AddHtmlLocalized(55, 340, 100, 20, 1011447); // BACK - AddButton(20, 340, 4005, 4007, 0, GumpButtonType.Page, 1); - } - - if (faction.IsCommander(from)) - { - AddPage(6); - - AddHtmlLocalized(20, 30, 200, 20, 1011461); // COMMANDER OPTIONS - - AddHtmlLocalized(20, 70, 120, 20, 1011457); // Tithe rate : - if (faction.Tithe >= 0 && faction.Tithe <= 100 && faction.Tithe % 10 == 0) - AddHtmlLocalized(140, 70, 250, 20, 1011480 + faction.Tithe / 10); - else - AddHtml(140, 70, 250, 20, $"{faction.Tithe}%"); - - AddHtmlLocalized(20, 100, 120, 20, 1011474); // Silver available : - AddHtml(140, 100, 50, 20, faction.Silver.ToString("N0")); // NOTE: Added 'N0' formatting - - AddHtmlLocalized(55, 130, 200, 20, 1011478); // CHANGE TITHE RATE - AddButton(20, 130, 4005, 4007, 0, GumpButtonType.Page, 8); - - AddHtmlLocalized(55, 160, 200, 20, 1018301); // TRANSFER SILVER - if (faction.Silver >= 10000) - AddButton(20, 160, 4005, 4007, 0, GumpButtonType.Page, 7); - else - AddImage(20, 160, 4020); - - AddHtmlLocalized(55, 310, 100, 20, 1011447); // BACK - AddButton(20, 310, 4005, 4007, 0, GumpButtonType.Page, 1); - - if (faction.Silver >= 10000) - { - AddPage(7); - - AddHtmlLocalized(20, 30, 250, 20, 1011476); // TOWN FINANCE - - AddHtmlLocalized(20, 50, 400, 20, 1011477); // Select a town to transfer 10000 silver to - - for (int i = 0; i < towns.Count; ++i) - { - Town town = towns[i]; - - AddHtmlText(55, 75 + i * 30, 200, 20, town.Definition.TownName, false, false); - - if (town.Owner == faction) - AddButton(20, 75 + i * 30, 4005, 4007, ToButtonID(2, i)); - else - AddImage(20, 75 + i * 30, 4020); - } - - AddHtmlLocalized(55, 310, 100, 20, 1011447); // BACK - AddButton(20, 310, 4005, 4007, 0, GumpButtonType.Page, 1); - } - - AddPage(8); - - AddHtmlLocalized(20, 30, 400, 20, 1011479); // Select the % for the new tithe rate - - int y = 55; - - for (int i = 0; i <= 10; ++i) - { - if (i == 5) - y += 5; - - AddHtmlLocalized(55, y, 300, 20, 1011480 + i); - AddButton(20, y, 4005, 4007, ToButtonID(3, i)); - - y += 20; - - if (i == 5) - y += 5; - } - - AddHtmlLocalized(55, 310, 300, 20, 1011447); // BACK - AddButton(20, 310, 4005, 4007, 0, GumpButtonType.Page, 1); - } - } - - public override int ButtonTypes => 4; - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (!FromButtonID(info.ButtonID, out int type, out int index)) - return; - - switch (type) - { - case 0: // general - { - switch (index) - { - case 0: // vote - { - m_From.SendGump(new ElectionGump(m_From, m_Faction.Election)); - break; - } - case 1: // leave - { - m_From.SendGump(new LeaveFactionGump(m_From, m_Faction)); - break; - } - } - - break; - } - case 1: // merchant title - { - if (index >= 0 && index <= MerchantTitles.Info.Length) - { - PlayerState pl = PlayerState.Find(m_From); - - MerchantTitle newTitle = (MerchantTitle)index; - MerchantTitleInfo mti = MerchantTitles.GetInfo(newTitle); - - if (mti == null) - { - m_From.SendLocalizedMessage(1010120); // Your merchant title has been removed - - if (pl != null) - pl.MerchantTitle = newTitle; - } - else if (MerchantTitles.IsQualified(m_From, mti)) - { - m_From.SendLocalizedMessage(mti.Assigned); - - if (pl != null) - pl.MerchantTitle = newTitle; - } - } - - break; - } - case 2: // transfer silver - { - if (!m_Faction.IsCommander(m_From)) - return; - - List towns = Town.Towns; - - if (index >= 0 && index < towns.Count) - { - Town town = towns[index]; - - if (town.Owner == m_Faction) - if (m_Faction.Silver >= 10000) - { - m_Faction.Silver -= 10000; - town.Silver += 10000; - - // 10k in silver has been received by: - m_From.SendLocalizedMessage(1042726, true, $" {town.Definition.FriendlyName}"); - } - } - - break; - } - case 3: // change tithe - { - if (!m_Faction.IsCommander(m_From)) - return; - - if (index >= 0 && index <= 10) - m_Faction.Tithe = index * 10; - - break; - } - } - } - } -} +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Factions +{ + public class FactionStoneGump : FactionGump + { + private readonly Faction m_Faction; + private readonly PlayerMobile m_From; + + public FactionStoneGump(PlayerMobile from, Faction faction) : base(20, 30) + { + m_From = from; + m_Faction = faction; + + AddPage(0); + + AddBackground(0, 0, 550, 440, 5054); + AddBackground(10, 10, 530, 420, 3000); + + AddPage(1); + + AddHtmlText(20, 30, 510, 20, faction.Definition.Header, false, false); + + AddHtmlLocalized(20, 60, 100, 20, 1011429); // Led By : + AddHtml(125, 60, 200, 20, faction.Commander != null ? faction.Commander.Name : "Nobody"); + + AddHtmlLocalized(20, 80, 100, 20, 1011457); // Tithe rate : + if (faction.Tithe >= 0 && faction.Tithe <= 100 && faction.Tithe % 10 == 0) + AddHtmlLocalized(125, 80, 350, 20, 1011480 + faction.Tithe / 10); + else + AddHtml(125, 80, 350, 20, $"{faction.Tithe}%"); + + AddHtmlLocalized(20, 100, 100, 20, 1011458); // Traps placed : + AddHtml(125, 100, 50, 20, faction.Traps.Count.ToString()); + + AddHtmlLocalized(55, 225, 200, 20, 1011428); // VOTE FOR LEADERSHIP + AddButton(20, 225, 4005, 4007, ToButtonID(0, 0)); + + AddHtmlLocalized(55, 150, 100, 20, 1011430); // CITY STATUS + AddButton(20, 150, 4005, 4007, 0, GumpButtonType.Page, 2); + + AddHtmlLocalized(55, 175, 100, 20, 1011444); // STATISTICS + AddButton(20, 175, 4005, 4007, 0, GumpButtonType.Page, 4); + + var isMerchantQualified = MerchantTitles.HasMerchantQualifications(from); + + var pl = PlayerState.Find(from); + + if (pl != null && pl.MerchantTitle != MerchantTitle.None) + { + AddHtmlLocalized(55, 200, 250, 20, 1011460); // UNDECLARE FACTION MERCHANT + AddButton(20, 200, 4005, 4007, ToButtonID(1, 0)); + } + else if (isMerchantQualified) + { + AddHtmlLocalized(55, 200, 250, 20, 1011459); // DECLARE FACTION MERCHANT + AddButton(20, 200, 4005, 4007, 0, GumpButtonType.Page, 5); + } + else + { + AddHtmlLocalized(55, 200, 250, 20, 1011467); // MERCHANT OPTIONS + AddImage(20, 200, 4020); + } + + AddHtmlLocalized(55, 250, 300, 20, 1011461); // COMMANDER OPTIONS + if (faction.IsCommander(from)) + AddButton(20, 250, 4005, 4007, 0, GumpButtonType.Page, 6); + else + AddImage(20, 250, 4020); + + AddHtmlLocalized(55, 275, 300, 20, 1011426); // LEAVE THIS FACTION + AddButton(20, 275, 4005, 4007, ToButtonID(0, 1)); + + AddHtmlLocalized(55, 300, 200, 20, 1011441); // EXIT + AddButton(20, 300, 4005, 4007, 0); + + AddPage(2); + + AddHtmlLocalized(20, 30, 250, 20, 1011430); // CITY STATUS + + var towns = Town.Towns; + + for (var i = 0; i < towns.Count; ++i) + { + var town = towns[i]; + + AddHtmlText(40, 55 + i * 30, 150, 20, town.Definition.TownName, false, false); + + if (town.Owner == null) + { + AddHtmlLocalized(200, 55 + i * 30, 150, 20, 1011462); // : Neutral + } + else + { + AddHtmlLocalized(200, 55 + i * 30, 150, 20, town.Owner.Definition.OwnerLabel); + + BaseMonolith monolith = town.Monolith; + + AddImage(20, 60 + i * 30, monolith?.Sigil?.IsPurifying == true ? 0x938 : 0x939); + } + } + + AddImage(20, 300, 2361); + AddHtmlLocalized(45, 295, 300, 20, 1011491); // sigil may be recaptured + + AddImage(20, 320, 2360); + AddHtmlLocalized(45, 315, 300, 20, 1011492); // sigil may not be recaptured + + AddHtmlLocalized(55, 350, 100, 20, 1011447); // BACK + AddButton(20, 350, 4005, 4007, 0, GumpButtonType.Page, 1); + + AddPage(4); + + AddHtmlLocalized(20, 30, 150, 20, 1011444); // STATISTICS + + AddHtmlLocalized(20, 100, 100, 20, 1011445); // Name : + AddHtml(120, 100, 150, 20, from.Name); + + AddHtmlLocalized(20, 130, 100, 20, 1018064); // score : + AddHtml(120, 130, 100, 20, (pl?.KillPoints ?? 0).ToString()); + + AddHtmlLocalized(20, 160, 100, 20, 1011446); // Rank : + AddHtml(120, 160, 100, 20, (pl?.Rank.Rank ?? 0).ToString()); + + AddHtmlLocalized(55, 250, 100, 20, 1011447); // BACK + AddButton(20, 250, 4005, 4007, 0, GumpButtonType.Page, 1); + + if ((pl == null || pl.MerchantTitle == MerchantTitle.None) && isMerchantQualified) + { + AddPage(5); + + AddHtmlLocalized(20, 30, 250, 20, 1011467); // MERCHANT OPTIONS + + AddHtmlLocalized(20, 80, 300, 20, 1011473); // Select the title you wish to display + + var infos = MerchantTitles.Info; + + for (var i = 0; i < infos.Length; ++i) + { + var info = infos[i]; + + if (MerchantTitles.IsQualified(from, info)) + AddButton(20, 100 + i * 30, 4005, 4007, ToButtonID(1, i + 1)); + else + AddImage(20, 100 + i * 30, 4020); + + AddHtmlText(55, 100 + i * 30, 200, 20, info.Label, false, false); + } + + AddHtmlLocalized(55, 340, 100, 20, 1011447); // BACK + AddButton(20, 340, 4005, 4007, 0, GumpButtonType.Page, 1); + } + + if (faction.IsCommander(from)) + { + AddPage(6); + + AddHtmlLocalized(20, 30, 200, 20, 1011461); // COMMANDER OPTIONS + + AddHtmlLocalized(20, 70, 120, 20, 1011457); // Tithe rate : + if (faction.Tithe >= 0 && faction.Tithe <= 100 && faction.Tithe % 10 == 0) + AddHtmlLocalized(140, 70, 250, 20, 1011480 + faction.Tithe / 10); + else + AddHtml(140, 70, 250, 20, $"{faction.Tithe}%"); + + AddHtmlLocalized(20, 100, 120, 20, 1011474); // Silver available : + AddHtml(140, 100, 50, 20, faction.Silver.ToString("N0")); // NOTE: Added 'N0' formatting + + AddHtmlLocalized(55, 130, 200, 20, 1011478); // CHANGE TITHE RATE + AddButton(20, 130, 4005, 4007, 0, GumpButtonType.Page, 8); + + AddHtmlLocalized(55, 160, 200, 20, 1018301); // TRANSFER SILVER + if (faction.Silver >= 10000) + AddButton(20, 160, 4005, 4007, 0, GumpButtonType.Page, 7); + else + AddImage(20, 160, 4020); + + AddHtmlLocalized(55, 310, 100, 20, 1011447); // BACK + AddButton(20, 310, 4005, 4007, 0, GumpButtonType.Page, 1); + + if (faction.Silver >= 10000) + { + AddPage(7); + + AddHtmlLocalized(20, 30, 250, 20, 1011476); // TOWN FINANCE + + AddHtmlLocalized(20, 50, 400, 20, 1011477); // Select a town to transfer 10000 silver to + + for (var i = 0; i < towns.Count; ++i) + { + var town = towns[i]; + + AddHtmlText(55, 75 + i * 30, 200, 20, town.Definition.TownName, false, false); + + if (town.Owner == faction) + AddButton(20, 75 + i * 30, 4005, 4007, ToButtonID(2, i)); + else + AddImage(20, 75 + i * 30, 4020); + } + + AddHtmlLocalized(55, 310, 100, 20, 1011447); // BACK + AddButton(20, 310, 4005, 4007, 0, GumpButtonType.Page, 1); + } + + AddPage(8); + + AddHtmlLocalized(20, 30, 400, 20, 1011479); // Select the % for the new tithe rate + + var y = 55; + + for (var i = 0; i <= 10; ++i) + { + if (i == 5) + y += 5; + + AddHtmlLocalized(55, y, 300, 20, 1011480 + i); + AddButton(20, y, 4005, 4007, ToButtonID(3, i)); + + y += 20; + + if (i == 5) + y += 5; + } + + AddHtmlLocalized(55, 310, 300, 20, 1011447); // BACK + AddButton(20, 310, 4005, 4007, 0, GumpButtonType.Page, 1); + } + } + + public override int ButtonTypes => 4; + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (!FromButtonID(info.ButtonID, out var type, out var index)) + return; + + switch (type) + { + case 0: // general + { + switch (index) + { + case 0: // vote + { + m_From.SendGump(new ElectionGump(m_From, m_Faction.Election)); + break; + } + case 1: // leave + { + m_From.SendGump(new LeaveFactionGump(m_From, m_Faction)); + break; + } + } + + break; + } + case 1: // merchant title + { + if (index >= 0 && index <= MerchantTitles.Info.Length) + { + var pl = PlayerState.Find(m_From); + + var newTitle = (MerchantTitle)index; + var mti = MerchantTitles.GetInfo(newTitle); + + if (mti == null) + { + m_From.SendLocalizedMessage(1010120); // Your merchant title has been removed + + if (pl != null) + pl.MerchantTitle = newTitle; + } + else if (MerchantTitles.IsQualified(m_From, mti)) + { + m_From.SendLocalizedMessage(mti.Assigned); + + if (pl != null) + pl.MerchantTitle = newTitle; + } + } + + break; + } + case 2: // transfer silver + { + if (!m_Faction.IsCommander(m_From)) + return; + + var towns = Town.Towns; + + if (index >= 0 && index < towns.Count) + { + var town = towns[index]; + + if (town.Owner == m_Faction) + if (m_Faction.Silver >= 10000) + { + m_Faction.Silver -= 10000; + town.Silver += 10000; + + // 10k in silver has been received by: + m_From.SendLocalizedMessage(1042726, true, $" {town.Definition.FriendlyName}"); + } + } + + break; + } + case 3: // change tithe + { + if (!m_Faction.IsCommander(m_From)) + return; + + if (index >= 0 && index <= 10) + m_Faction.Tithe = index * 10; + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Gumps/FinanceGump.cs b/Projects/UOContent/Engines/Factions/Gumps/FinanceGump.cs index 8597459f4..44fc8fea4 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/FinanceGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/FinanceGump.cs @@ -1,269 +1,274 @@ -using System; -using System.Collections.Generic; -using Server.Gumps; -using Server.Mobiles; -using Server.Multis; -using Server.Network; - -namespace Server.Factions -{ - public class FinanceGump : FactionGump - { - private static readonly int[] m_PriceOffsets = - { - -30, -25, -20, -15, -10, -5, - +50, +100, +150, +200, +250, +300 - }; - - private readonly Faction m_Faction; - private readonly PlayerMobile m_From; - private readonly Town m_Town; - - public FinanceGump(PlayerMobile from, Faction faction, Town town) : base(50, 50) - { - m_From = from; - m_Faction = faction; - m_Town = town; - - AddPage(0); - - AddBackground(0, 0, 320, 410, 5054); - AddBackground(10, 10, 300, 390, 3000); - - AddPage(1); - - AddHtmlLocalized(20, 30, 260, 25, 1011541); // FINANCE MINISTER - - AddHtmlLocalized(55, 90, 200, 25, 1011539); // CHANGE PRICES - AddButton(20, 90, 4005, 4007, 0, GumpButtonType.Page, 2); - - AddHtmlLocalized(55, 120, 200, 25, 1011540); // BUY SHOPKEEPERS - AddButton(20, 120, 4005, 4007, 0, GumpButtonType.Page, 3); - - AddHtmlLocalized(55, 150, 200, 25, 1011495); // VIEW FINANCES - AddButton(20, 150, 4005, 4007, 0, GumpButtonType.Page, 4); - - AddHtmlLocalized(55, 360, 200, 25, 1011441); // EXIT - AddButton(20, 360, 4005, 4007, 0); - - AddPage(2); - - AddHtmlLocalized(20, 30, 200, 25, 1011539); // CHANGE PRICES - - for (int i = 0; i < m_PriceOffsets.Length; ++i) - { - int ofs = m_PriceOffsets[i]; - - int x = 20 + i / 6 * 150; - int y = 90 + i % 6 * 30; - - AddRadio(x, y, 208, 209, town.Tax == ofs, i + 1); - - if (ofs < 0) - AddLabel(x + 35, y, 0x26, $"- {-ofs}%"); - else - AddLabel(x + 35, y, 0x12A, $"+ {ofs}%"); - } - - AddRadio(20, 270, 208, 209, town.Tax == 0, 0); - AddHtmlLocalized(55, 270, 90, 25, 1011542); // normal - - AddHtmlLocalized(55, 330, 200, 25, 1011509); // Set Prices - AddButton(20, 330, 4005, 4007, ToButtonID(0, 0)); - - AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page - AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 1); - - AddPage(3); - - AddHtmlLocalized(20, 30, 200, 25, 1011540); // BUY SHOPKEEPERS - - List vendorLists = town.VendorLists; - - for (int i = 0; i < vendorLists.Count; ++i) - { - VendorList list = vendorLists[i]; - - AddButton(20, 90 + i * 40, 4005, 4007, 0, GumpButtonType.Page, 5 + i); - AddItem(55, 90 + i * 40, list.Definition.ItemID); - AddHtmlText(100, 90 + i * 40, 200, 25, list.Definition.Label, false, false); - } - - AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page - AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 1); - - AddPage(4); - - int financeUpkeep = town.FinanceUpkeep; - int sheriffUpkeep = town.SheriffUpkeep; - int dailyIncome = town.DailyIncome; - int netCashFlow = town.NetCashFlow; - - AddHtmlLocalized(20, 30, 300, 25, 1011524); // FINANCE STATEMENT - - AddHtmlLocalized(20, 80, 300, 25, 1011538); // Current total money for town : - AddLabel(20, 100, 0x44, town.Silver.ToString()); - - AddHtmlLocalized(20, 130, 300, 25, 1011520); // Finance Minister Upkeep : - AddLabel(20, 150, 0x44, financeUpkeep.ToString("N0")); // NOTE: Added 'N0' - - AddHtmlLocalized(20, 180, 300, 25, 1011521); // Sheriff Upkeep : - AddLabel(20, 200, 0x44, sheriffUpkeep.ToString("N0")); // NOTE: Added 'N0' - - AddHtmlLocalized(20, 230, 300, 25, 1011522); // Town Income : - AddLabel(20, 250, 0x44, dailyIncome.ToString("N0")); // NOTE: Added 'N0' - - AddHtmlLocalized(20, 280, 300, 25, 1011523); // Net Cash flow per day : - AddLabel(20, 300, 0x44, netCashFlow.ToString("N0")); // NOTE: Added 'N0' - - AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page - AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 1); - - for (int i = 0; i < vendorLists.Count; ++i) - { - VendorList vendorList = vendorLists[i]; - - AddPage(5 + i); - - AddHtmlText(60, 30, 300, 25, vendorList.Definition.Header, false, false); - AddItem(20, 30, vendorList.Definition.ItemID); - - AddHtmlLocalized(20, 90, 200, 25, 1011514); // You have : - AddLabel(230, 90, 0x26, vendorList.Vendors.Count.ToString()); - - AddHtmlLocalized(20, 120, 200, 25, 1011515); // Maximum : - AddLabel(230, 120, 0x256, vendorList.Definition.Maximum.ToString()); - - AddHtmlLocalized(20, 150, 200, 25, 1011516); // Cost : - AddLabel(230, 150, 0x44, vendorList.Definition.Price.ToString("N0")); // NOTE: Added 'N0' - - AddHtmlLocalized(20, 180, 200, 25, 1011517); // Daily Pay : - AddLabel(230, 180, 0x37, vendorList.Definition.Upkeep.ToString("N0")); // NOTE: Added 'N0' - - AddHtmlLocalized(20, 210, 200, 25, 1011518); // Current Silver : - AddLabel(230, 210, 0x44, town.Silver.ToString("N0")); // NOTE: Added 'N0' - - AddHtmlLocalized(20, 240, 200, 25, 1011519); // Current Payroll : - AddLabel(230, 240, 0x44, financeUpkeep.ToString("N0")); // NOTE: Added 'N0' - - AddHtmlText(55, 300, 200, 25, vendorList.Definition.Label, false, false); - if (town.Silver >= vendorList.Definition.Price) - AddButton(20, 300, 4005, 4007, ToButtonID(1, i)); - else - AddImage(20, 300, 4020); - - AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page - AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 3); - } - } - - public override int ButtonTypes => 2; - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (!m_Town.IsFinance(m_From) || m_Town.Owner != m_Faction) - { - m_From.SendLocalizedMessage(1010339); // You no longer control this city - return; - } - - if (!FromButtonID(info.ButtonID, out int type, out int index)) - return; - - switch (type) - { - case 0: // general - { - switch (index) - { - case 0: // set price - { - int[] switches = info.Switches; - - if (switches.Length == 0) - break; - - int opt = switches[0]; - int newTax = 0; - - if (opt >= 1 && opt <= m_PriceOffsets.Length) - newTax = m_PriceOffsets[opt - 1]; - - if (m_Town.Tax == newTax) - break; - - if (m_From.AccessLevel == AccessLevel.Player && !m_Town.TaxChangeReady) - { - TimeSpan remaining = DateTime.UtcNow - (m_Town.LastTaxChange + Town.TaxChangePeriod); - - if (remaining.TotalMinutes < 4) - m_From.SendLocalizedMessage( - 1042165); // You must wait a short while before changing prices again. - else if (remaining.TotalMinutes < 10) - m_From.SendLocalizedMessage( - 1042166); // You must wait several minutes before changing prices again. - else if (remaining.TotalHours < 1) - m_From.SendLocalizedMessage( - 1042167); // You must wait up to an hour before changing prices again. - else if (remaining.TotalHours < 4) - m_From.SendLocalizedMessage( - 1042168); // You must wait a few hours before changing prices again. - else - m_From.SendLocalizedMessage( - 1042169); // You must wait several hours before changing prices again. - } - else - { - m_Town.Tax = newTax; - - if (m_From.AccessLevel == AccessLevel.Player) - m_Town.LastTaxChange = DateTime.UtcNow; - } - - break; - } - } - - break; - } - case 1: // make vendor - { - List vendorLists = m_Town.VendorLists; - - if (index >= 0 && index < vendorLists.Count) - { - VendorList vendorList = vendorLists[index]; - - if (Town.FromRegion(m_From.Region) != m_Town) - { - m_From.SendLocalizedMessage(1010305); // You must be in your controlled city to buy Items - } - else if (vendorList.Vendors.Count >= vendorList.Definition.Maximum) - { - m_From.SendLocalizedMessage( - 1010306); // You currently have too many of this enhancement type to place another - } - else if (BaseBoat.FindBoatAt(m_From.Location, m_From.Map) != null) - { - m_From.SendMessage("You cannot place a vendor here"); - } - else if (m_Town.Silver >= vendorList.Definition.Price) - { - BaseFactionVendor vendor = vendorList.Construct(m_Town, m_Faction); - - if (vendor != null) - { - m_Town.Silver -= vendorList.Definition.Price; - - vendor.MoveToWorld(m_From.Location, m_From.Map); - vendor.Home = vendor.Location; - } - } - } - - break; - } - } - } - } -} +using System; +using Server.Gumps; +using Server.Mobiles; +using Server.Multis; +using Server.Network; + +namespace Server.Factions +{ + public class FinanceGump : FactionGump + { + private static readonly int[] m_PriceOffsets = + { + -30, -25, -20, -15, -10, -5, + +50, +100, +150, +200, +250, +300 + }; + + private readonly Faction m_Faction; + private readonly PlayerMobile m_From; + private readonly Town m_Town; + + public FinanceGump(PlayerMobile from, Faction faction, Town town) : base(50, 50) + { + m_From = from; + m_Faction = faction; + m_Town = town; + + AddPage(0); + + AddBackground(0, 0, 320, 410, 5054); + AddBackground(10, 10, 300, 390, 3000); + + AddPage(1); + + AddHtmlLocalized(20, 30, 260, 25, 1011541); // FINANCE MINISTER + + AddHtmlLocalized(55, 90, 200, 25, 1011539); // CHANGE PRICES + AddButton(20, 90, 4005, 4007, 0, GumpButtonType.Page, 2); + + AddHtmlLocalized(55, 120, 200, 25, 1011540); // BUY SHOPKEEPERS + AddButton(20, 120, 4005, 4007, 0, GumpButtonType.Page, 3); + + AddHtmlLocalized(55, 150, 200, 25, 1011495); // VIEW FINANCES + AddButton(20, 150, 4005, 4007, 0, GumpButtonType.Page, 4); + + AddHtmlLocalized(55, 360, 200, 25, 1011441); // EXIT + AddButton(20, 360, 4005, 4007, 0); + + AddPage(2); + + AddHtmlLocalized(20, 30, 200, 25, 1011539); // CHANGE PRICES + + for (var i = 0; i < m_PriceOffsets.Length; ++i) + { + var ofs = m_PriceOffsets[i]; + + var x = 20 + i / 6 * 150; + var y = 90 + i % 6 * 30; + + AddRadio(x, y, 208, 209, town.Tax == ofs, i + 1); + + if (ofs < 0) + AddLabel(x + 35, y, 0x26, $"- {-ofs}%"); + else + AddLabel(x + 35, y, 0x12A, $"+ {ofs}%"); + } + + AddRadio(20, 270, 208, 209, town.Tax == 0, 0); + AddHtmlLocalized(55, 270, 90, 25, 1011542); // normal + + AddHtmlLocalized(55, 330, 200, 25, 1011509); // Set Prices + AddButton(20, 330, 4005, 4007, ToButtonID(0, 0)); + + AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page + AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 1); + + AddPage(3); + + AddHtmlLocalized(20, 30, 200, 25, 1011540); // BUY SHOPKEEPERS + + var vendorLists = town.VendorLists; + + for (var i = 0; i < vendorLists.Count; ++i) + { + var list = vendorLists[i]; + + AddButton(20, 90 + i * 40, 4005, 4007, 0, GumpButtonType.Page, 5 + i); + AddItem(55, 90 + i * 40, list.Definition.ItemID); + AddHtmlText(100, 90 + i * 40, 200, 25, list.Definition.Label, false, false); + } + + AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page + AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 1); + + AddPage(4); + + var financeUpkeep = town.FinanceUpkeep; + var sheriffUpkeep = town.SheriffUpkeep; + var dailyIncome = town.DailyIncome; + var netCashFlow = town.NetCashFlow; + + AddHtmlLocalized(20, 30, 300, 25, 1011524); // FINANCE STATEMENT + + AddHtmlLocalized(20, 80, 300, 25, 1011538); // Current total money for town : + AddLabel(20, 100, 0x44, town.Silver.ToString()); + + AddHtmlLocalized(20, 130, 300, 25, 1011520); // Finance Minister Upkeep : + AddLabel(20, 150, 0x44, financeUpkeep.ToString("N0")); // NOTE: Added 'N0' + + AddHtmlLocalized(20, 180, 300, 25, 1011521); // Sheriff Upkeep : + AddLabel(20, 200, 0x44, sheriffUpkeep.ToString("N0")); // NOTE: Added 'N0' + + AddHtmlLocalized(20, 230, 300, 25, 1011522); // Town Income : + AddLabel(20, 250, 0x44, dailyIncome.ToString("N0")); // NOTE: Added 'N0' + + AddHtmlLocalized(20, 280, 300, 25, 1011523); // Net Cash flow per day : + AddLabel(20, 300, 0x44, netCashFlow.ToString("N0")); // NOTE: Added 'N0' + + AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page + AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 1); + + for (var i = 0; i < vendorLists.Count; ++i) + { + var vendorList = vendorLists[i]; + + AddPage(5 + i); + + AddHtmlText(60, 30, 300, 25, vendorList.Definition.Header, false, false); + AddItem(20, 30, vendorList.Definition.ItemID); + + AddHtmlLocalized(20, 90, 200, 25, 1011514); // You have : + AddLabel(230, 90, 0x26, vendorList.Vendors.Count.ToString()); + + AddHtmlLocalized(20, 120, 200, 25, 1011515); // Maximum : + AddLabel(230, 120, 0x256, vendorList.Definition.Maximum.ToString()); + + AddHtmlLocalized(20, 150, 200, 25, 1011516); // Cost : + AddLabel(230, 150, 0x44, vendorList.Definition.Price.ToString("N0")); // NOTE: Added 'N0' + + AddHtmlLocalized(20, 180, 200, 25, 1011517); // Daily Pay : + AddLabel(230, 180, 0x37, vendorList.Definition.Upkeep.ToString("N0")); // NOTE: Added 'N0' + + AddHtmlLocalized(20, 210, 200, 25, 1011518); // Current Silver : + AddLabel(230, 210, 0x44, town.Silver.ToString("N0")); // NOTE: Added 'N0' + + AddHtmlLocalized(20, 240, 200, 25, 1011519); // Current Payroll : + AddLabel(230, 240, 0x44, financeUpkeep.ToString("N0")); // NOTE: Added 'N0' + + AddHtmlText(55, 300, 200, 25, vendorList.Definition.Label, false, false); + if (town.Silver >= vendorList.Definition.Price) + AddButton(20, 300, 4005, 4007, ToButtonID(1, i)); + else + AddImage(20, 300, 4020); + + AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page + AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 3); + } + } + + public override int ButtonTypes => 2; + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (!m_Town.IsFinance(m_From) || m_Town.Owner != m_Faction) + { + m_From.SendLocalizedMessage(1010339); // You no longer control this city + return; + } + + if (!FromButtonID(info.ButtonID, out var type, out var index)) + return; + + switch (type) + { + case 0: // general + { + switch (index) + { + case 0: // set price + { + var switches = info.Switches; + + if (switches.Length == 0) + break; + + var opt = switches[0]; + var newTax = 0; + + if (opt >= 1 && opt <= m_PriceOffsets.Length) + newTax = m_PriceOffsets[opt - 1]; + + if (m_Town.Tax == newTax) + break; + + if (m_From.AccessLevel == AccessLevel.Player && !m_Town.TaxChangeReady) + { + var remaining = DateTime.UtcNow - (m_Town.LastTaxChange + Town.TaxChangePeriod); + + if (remaining.TotalMinutes < 4) + m_From.SendLocalizedMessage( + 1042165 + ); // You must wait a short while before changing prices again. + else if (remaining.TotalMinutes < 10) + m_From.SendLocalizedMessage( + 1042166 + ); // You must wait several minutes before changing prices again. + else if (remaining.TotalHours < 1) + m_From.SendLocalizedMessage( + 1042167 + ); // You must wait up to an hour before changing prices again. + else if (remaining.TotalHours < 4) + m_From.SendLocalizedMessage( + 1042168 + ); // You must wait a few hours before changing prices again. + else + m_From.SendLocalizedMessage( + 1042169 + ); // You must wait several hours before changing prices again. + } + else + { + m_Town.Tax = newTax; + + if (m_From.AccessLevel == AccessLevel.Player) + m_Town.LastTaxChange = DateTime.UtcNow; + } + + break; + } + } + + break; + } + case 1: // make vendor + { + var vendorLists = m_Town.VendorLists; + + if (index >= 0 && index < vendorLists.Count) + { + var vendorList = vendorLists[index]; + + if (Town.FromRegion(m_From.Region) != m_Town) + { + m_From.SendLocalizedMessage(1010305); // You must be in your controlled city to buy Items + } + else if (vendorList.Vendors.Count >= vendorList.Definition.Maximum) + { + m_From.SendLocalizedMessage( + 1010306 + ); // You currently have too many of this enhancement type to place another + } + else if (BaseBoat.FindBoatAt(m_From.Location, m_From.Map) != null) + { + m_From.SendMessage("You cannot place a vendor here"); + } + else if (m_Town.Silver >= vendorList.Definition.Price) + { + var vendor = vendorList.Construct(m_Town, m_Faction); + + if (vendor != null) + { + m_Town.Silver -= vendorList.Definition.Price; + + vendor.MoveToWorld(m_From.Location, m_From.Map); + vendor.Home = vendor.Location; + } + } + } + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Gumps/HorseBreederGump.cs b/Projects/UOContent/Engines/Factions/Gumps/HorseBreederGump.cs index 37dd44b6a..d8ca466a2 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/HorseBreederGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/HorseBreederGump.cs @@ -1,91 +1,91 @@ -using Server.Gumps; -using Server.Items; -using Server.Mobiles; -using Server.Network; - -namespace Server.Factions -{ - public class HorseBreederGump : FactionGump - { - private readonly Faction m_Faction; - private readonly PlayerMobile m_From; - - public HorseBreederGump(PlayerMobile from, Faction faction) : base(20, 30) - { - m_From = from; - m_Faction = faction; - - AddPage(0); - - AddBackground(0, 0, 320, 280, 5054); - AddBackground(10, 10, 300, 260, 3000); - - AddHtmlText(20, 30, 300, 25, faction.Definition.Header, false, false); - - AddHtmlLocalized(20, 60, 300, 25, 1018306); // Purchase a Faction War Horse - AddItem(70, 120, 0x3FFE); - - AddItem(150, 120, 0xEF2); - AddLabel(190, 122, 0x3E3, FactionWarHorse.SilverPrice.ToString("N0")); // NOTE: Added 'N0' - - AddItem(150, 150, 0xEEF); - AddLabel(190, 152, 0x3E3, FactionWarHorse.GoldPrice.ToString("N0")); // NOTE: Added 'N0' - - AddHtmlLocalized(55, 210, 200, 25, 1011011); // CONTINUE - AddButton(20, 210, 4005, 4007, 1); - - AddHtmlLocalized(55, 240, 200, 25, 1011012); // CANCEL - AddButton(20, 240, 4005, 4007, 0); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID != 1) - return; - - if (Faction.Find(m_From) != m_Faction) - return; - - Container pack = m_From.Backpack; - - if (pack == null) - return; - - FactionWarHorse horse = new FactionWarHorse(m_Faction); - - if (m_From.Followers + horse.ControlSlots > m_From.FollowersMax) - { - // TODO: Message? - horse.Delete(); - } - else - { - if (pack.GetAmount(typeof(Silver)) < FactionWarHorse.SilverPrice) - { - sender.Mobile.SendLocalizedMessage(1042204); // You do not have enough silver. - horse.Delete(); - } - else if (pack.GetAmount(typeof(Gold)) < FactionWarHorse.GoldPrice) - { - sender.Mobile.SendLocalizedMessage(1042205); // You do not have enough gold. - horse.Delete(); - } - else if (pack.ConsumeTotal(typeof(Silver), FactionWarHorse.SilverPrice) && - pack.ConsumeTotal(typeof(Gold), FactionWarHorse.GoldPrice)) - { - horse.Controlled = true; - horse.ControlMaster = m_From; - - horse.ControlOrder = OrderType.Follow; - horse.ControlTarget = m_From; - - horse.MoveToWorld(m_From.Location, m_From.Map); - } - else - { - horse.Delete(); - } - } - } - } -} +using Server.Gumps; +using Server.Items; +using Server.Mobiles; +using Server.Network; + +namespace Server.Factions +{ + public class HorseBreederGump : FactionGump + { + private readonly Faction m_Faction; + private readonly PlayerMobile m_From; + + public HorseBreederGump(PlayerMobile from, Faction faction) : base(20, 30) + { + m_From = from; + m_Faction = faction; + + AddPage(0); + + AddBackground(0, 0, 320, 280, 5054); + AddBackground(10, 10, 300, 260, 3000); + + AddHtmlText(20, 30, 300, 25, faction.Definition.Header, false, false); + + AddHtmlLocalized(20, 60, 300, 25, 1018306); // Purchase a Faction War Horse + AddItem(70, 120, 0x3FFE); + + AddItem(150, 120, 0xEF2); + AddLabel(190, 122, 0x3E3, FactionWarHorse.SilverPrice.ToString("N0")); // NOTE: Added 'N0' + + AddItem(150, 150, 0xEEF); + AddLabel(190, 152, 0x3E3, FactionWarHorse.GoldPrice.ToString("N0")); // NOTE: Added 'N0' + + AddHtmlLocalized(55, 210, 200, 25, 1011011); // CONTINUE + AddButton(20, 210, 4005, 4007, 1); + + AddHtmlLocalized(55, 240, 200, 25, 1011012); // CANCEL + AddButton(20, 240, 4005, 4007, 0); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID != 1) + return; + + if (Faction.Find(m_From) != m_Faction) + return; + + var pack = m_From.Backpack; + + if (pack == null) + return; + + var horse = new FactionWarHorse(m_Faction); + + if (m_From.Followers + horse.ControlSlots > m_From.FollowersMax) + { + // TODO: Message? + horse.Delete(); + } + else + { + if (pack.GetAmount(typeof(Silver)) < FactionWarHorse.SilverPrice) + { + sender.Mobile.SendLocalizedMessage(1042204); // You do not have enough silver. + horse.Delete(); + } + else if (pack.GetAmount(typeof(Gold)) < FactionWarHorse.GoldPrice) + { + sender.Mobile.SendLocalizedMessage(1042205); // You do not have enough gold. + horse.Delete(); + } + else if (pack.ConsumeTotal(typeof(Silver), FactionWarHorse.SilverPrice) && + pack.ConsumeTotal(typeof(Gold), FactionWarHorse.GoldPrice)) + { + horse.Controlled = true; + horse.ControlMaster = m_From; + + horse.ControlOrder = OrderType.Follow; + horse.ControlTarget = m_From; + + horse.MoveToWorld(m_From.Location, m_From.Map); + } + else + { + horse.Delete(); + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Gumps/JoinStoneGump.cs b/Projects/UOContent/Engines/Factions/Gumps/JoinStoneGump.cs index 22fb4cdea..2dd24856b 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/JoinStoneGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/JoinStoneGump.cs @@ -1,47 +1,47 @@ -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Factions -{ - public class JoinStoneGump : FactionGump - { - private readonly Faction m_Faction; - private readonly PlayerMobile m_From; - - public JoinStoneGump(PlayerMobile from, Faction faction) : base(20, 30) - { - m_From = from; - m_Faction = faction; - - AddPage(0); - - AddBackground(0, 0, 550, 440, 5054); - AddBackground(10, 10, 530, 420, 3000); - - AddHtmlText(20, 30, 510, 20, faction.Definition.Header, false, false); - AddHtmlText(20, 130, 510, 100, faction.Definition.About, true, true); - - AddHtmlLocalized(20, 60, 100, 20, 1011429); // Led By : - AddHtml(125, 60, 200, 20, faction.Commander != null ? faction.Commander.Name : "Nobody"); - - AddHtmlLocalized(20, 80, 100, 20, 1011457); // Tithe rate : - if (faction.Tithe >= 0 && faction.Tithe <= 100 && faction.Tithe % 10 == 0) - AddHtmlLocalized(125, 80, 350, 20, 1011480 + faction.Tithe / 10); - else - AddHtml(125, 80, 350, 20, $"{faction.Tithe}%"); - - AddButton(20, 400, 4005, 4007, 1); - AddHtmlLocalized(55, 400, 200, 20, 1011425); // JOIN THIS FACTION - - AddButton(300, 400, 4005, 4007, 0); - AddHtmlLocalized(335, 400, 200, 20, 1011012); // CANCEL - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 1) - m_Faction.OnJoinAccepted(m_From); - } - } -} +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Factions +{ + public class JoinStoneGump : FactionGump + { + private readonly Faction m_Faction; + private readonly PlayerMobile m_From; + + public JoinStoneGump(PlayerMobile from, Faction faction) : base(20, 30) + { + m_From = from; + m_Faction = faction; + + AddPage(0); + + AddBackground(0, 0, 550, 440, 5054); + AddBackground(10, 10, 530, 420, 3000); + + AddHtmlText(20, 30, 510, 20, faction.Definition.Header, false, false); + AddHtmlText(20, 130, 510, 100, faction.Definition.About, true, true); + + AddHtmlLocalized(20, 60, 100, 20, 1011429); // Led By : + AddHtml(125, 60, 200, 20, faction.Commander != null ? faction.Commander.Name : "Nobody"); + + AddHtmlLocalized(20, 80, 100, 20, 1011457); // Tithe rate : + if (faction.Tithe >= 0 && faction.Tithe <= 100 && faction.Tithe % 10 == 0) + AddHtmlLocalized(125, 80, 350, 20, 1011480 + faction.Tithe / 10); + else + AddHtml(125, 80, 350, 20, $"{faction.Tithe}%"); + + AddButton(20, 400, 4005, 4007, 1); + AddHtmlLocalized(55, 400, 200, 20, 1011425); // JOIN THIS FACTION + + AddButton(300, 400, 4005, 4007, 0); + AddHtmlLocalized(335, 400, 200, 20, 1011012); // CANCEL + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 1) + m_Faction.OnJoinAccepted(m_From); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Gumps/LeaveFactionGump.cs b/Projects/UOContent/Engines/Factions/Gumps/LeaveFactionGump.cs index 38b5cfaf9..969299faa 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/LeaveFactionGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/LeaveFactionGump.cs @@ -1,93 +1,105 @@ -using System; -using Server.Guilds; -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Factions -{ - public class LeaveFactionGump : FactionGump - { - private Faction m_Faction; - private readonly PlayerMobile m_From; - - public LeaveFactionGump(PlayerMobile from, Faction faction) : base(20, 30) - { - m_From = from; - m_Faction = faction; - - AddBackground(0, 0, 270, 120, 5054); - AddBackground(10, 10, 250, 100, 3000); - - if (from.Guild is Guild guild && guild.Leader == from) - AddHtmlLocalized(20, 15, 230, 60, 1018057, true, - true); // Are you sure you want your entire guild to leave this faction? - else - AddHtmlLocalized(20, 15, 230, 60, 1018063, true, true); // Are you sure you want to leave this faction? - - AddHtmlLocalized(55, 80, 75, 20, 1011011); // CONTINUE - AddButton(20, 80, 4005, 4007, 1); - - AddHtmlLocalized(170, 80, 75, 20, 1011012); // CANCEL - AddButton(135, 80, 4005, 4007, 2); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - switch (info.ButtonID) - { - case 1: // continue - { - if (!(m_From.Guild is Guild guild)) - { - PlayerState pl = PlayerState.Find(m_From); - - if (pl != null) - { - pl.Leaving = DateTime.UtcNow; - - if (TimeSpan.FromDays(3.0) == Faction.LeavePeriod) - m_From.SendLocalizedMessage(1005065); // You will be removed from the faction in 3 days - else - m_From.SendMessage("You will be removed from the faction in {0} days.", - Faction.LeavePeriod.TotalDays); - } - } - else if (guild.Leader != m_From) - { - m_From.SendLocalizedMessage( - 1005061); // You cannot quit the faction because you are not the guild master - } - else - { - m_From.SendLocalizedMessage(1042285); // Your guild is now quitting the faction. - - for (int i = 0; i < guild.Members.Count; ++i) - { - Mobile mob = guild.Members[i]; - PlayerState pl = PlayerState.Find(mob); - - if (pl != null) - { - pl.Leaving = DateTime.UtcNow; - - if (TimeSpan.FromDays(3.0) == Faction.LeavePeriod) - mob.SendLocalizedMessage(1005060); // Your guild will quit the faction in 3 days - else - mob.SendMessage("Your guild will quit the faction in {0} days.", - Faction.LeavePeriod.TotalDays); - } - } - } - - break; - } - case 2: // cancel - { - m_From.SendLocalizedMessage(500737); // Canceled resignation. - break; - } - } - } - } -} +using System; +using Server.Guilds; +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Factions +{ + public class LeaveFactionGump : FactionGump + { + private readonly PlayerMobile m_From; + private Faction m_Faction; + + public LeaveFactionGump(PlayerMobile from, Faction faction) : base(20, 30) + { + m_From = from; + m_Faction = faction; + + AddBackground(0, 0, 270, 120, 5054); + AddBackground(10, 10, 250, 100, 3000); + + if (from.Guild is Guild guild && guild.Leader == from) + AddHtmlLocalized( + 20, + 15, + 230, + 60, + 1018057, + true, + true + ); // Are you sure you want your entire guild to leave this faction? + else + AddHtmlLocalized(20, 15, 230, 60, 1018063, true, true); // Are you sure you want to leave this faction? + + AddHtmlLocalized(55, 80, 75, 20, 1011011); // CONTINUE + AddButton(20, 80, 4005, 4007, 1); + + AddHtmlLocalized(170, 80, 75, 20, 1011012); // CANCEL + AddButton(135, 80, 4005, 4007, 2); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + switch (info.ButtonID) + { + case 1: // continue + { + if (!(m_From.Guild is Guild guild)) + { + var pl = PlayerState.Find(m_From); + + if (pl != null) + { + pl.Leaving = DateTime.UtcNow; + + if (TimeSpan.FromDays(3.0) == Faction.LeavePeriod) + m_From.SendLocalizedMessage(1005065); // You will be removed from the faction in 3 days + else + m_From.SendMessage( + "You will be removed from the faction in {0} days.", + Faction.LeavePeriod.TotalDays + ); + } + } + else if (guild.Leader != m_From) + { + m_From.SendLocalizedMessage( + 1005061 + ); // You cannot quit the faction because you are not the guild master + } + else + { + m_From.SendLocalizedMessage(1042285); // Your guild is now quitting the faction. + + for (var i = 0; i < guild.Members.Count; ++i) + { + var mob = guild.Members[i]; + var pl = PlayerState.Find(mob); + + if (pl != null) + { + pl.Leaving = DateTime.UtcNow; + + if (TimeSpan.FromDays(3.0) == Faction.LeavePeriod) + mob.SendLocalizedMessage(1005060); // Your guild will quit the faction in 3 days + else + mob.SendMessage( + "Your guild will quit the faction in {0} days.", + Faction.LeavePeriod.TotalDays + ); + } + } + } + + break; + } + case 2: // cancel + { + m_From.SendLocalizedMessage(500737); // Canceled resignation. + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Gumps/SheriffGump.cs b/Projects/UOContent/Engines/Factions/Gumps/SheriffGump.cs index 9481572ab..80e58e02c 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/SheriffGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/SheriffGump.cs @@ -1,171 +1,171 @@ -using System.Collections.Generic; -using Server.Gumps; -using Server.Mobiles; -using Server.Multis; -using Server.Network; - -namespace Server.Factions -{ - public class SheriffGump : FactionGump - { - private readonly Faction m_Faction; - private readonly PlayerMobile m_From; - private readonly Town m_Town; - - public SheriffGump(PlayerMobile from, Faction faction, Town town) : base(50, 50) - { - m_From = from; - m_Faction = faction; - m_Town = town; - - AddPage(0); - - AddBackground(0, 0, 320, 410, 5054); - AddBackground(10, 10, 300, 390, 3000); - - AddPage(1); - - AddHtmlLocalized(20, 30, 260, 25, 1011431); // Sheriff - - AddHtmlLocalized(55, 90, 200, 25, 1011494); // HIRE GUARDS - AddButton(20, 90, 4005, 4007, 0, GumpButtonType.Page, 3); - - AddHtmlLocalized(55, 120, 200, 25, 1011495); // VIEW FINANCES - AddButton(20, 120, 4005, 4007, 0, GumpButtonType.Page, 2); - - AddHtmlLocalized(55, 360, 200, 25, 1011441); // Exit - AddButton(20, 360, 4005, 4007, 0); - - AddPage(2); - - int financeUpkeep = town.FinanceUpkeep; - int sheriffUpkeep = town.SheriffUpkeep; - int dailyIncome = town.DailyIncome; - int netCashFlow = town.NetCashFlow; - - AddHtmlLocalized(20, 30, 300, 25, 1011524); // FINANCE STATEMENT - - AddHtmlLocalized(20, 80, 300, 25, 1011538); // Current total money for town : - AddLabel(20, 100, 0x44, town.Silver.ToString("N0")); // NOTE: Added 'N0' - - AddHtmlLocalized(20, 130, 300, 25, 1011520); // Finance Minister Upkeep : - AddLabel(20, 150, 0x44, financeUpkeep.ToString("N0")); // NOTE: Added 'N0' - - AddHtmlLocalized(20, 180, 300, 25, 1011521); // Sheriff Upkeep : - AddLabel(20, 200, 0x44, sheriffUpkeep.ToString("N0")); // NOTE: Added 'N0' - - AddHtmlLocalized(20, 230, 300, 25, 1011522); // Town Income : - AddLabel(20, 250, 0x44, dailyIncome.ToString("N0")); // NOTE: Added 'N0' - - AddHtmlLocalized(20, 280, 300, 25, 1011523); // Net Cash flow per day : - AddLabel(20, 300, 0x44, netCashFlow.ToString("N0")); // NOTE: Added 'N0' - - AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page - AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 1); - - AddPage(3); - - AddHtmlLocalized(20, 30, 300, 25, 1011494); // HIRE GUARDS - - List guardLists = town.GuardLists; - - for (int i = 0; i < guardLists.Count; ++i) - { - GuardList guardList = guardLists[i]; - int y = 90 + i * 60; - - AddButton(20, y, 4005, 4007, 0, GumpButtonType.Page, 4 + i); - CenterItem(guardList.Definition.ItemID, 50, y - 20, 70, 60); - AddHtmlText(120, y, 200, 25, guardList.Definition.Header, false, false); - } - - AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page - AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 1); - - for (int i = 0; i < guardLists.Count; ++i) - { - GuardList guardList = guardLists[i]; - - AddPage(4 + i); - - AddHtmlText(90, 30, 300, 25, guardList.Definition.Header, false, false); - CenterItem(guardList.Definition.ItemID, 10, 10, 80, 80); - - AddHtmlLocalized(20, 90, 200, 25, 1011514); // You have : - AddLabel(230, 90, 0x26, guardList.Guards.Count.ToString()); - - AddHtmlLocalized(20, 120, 200, 25, 1011515); // Maximum : - AddLabel(230, 120, 0x12A, guardList.Definition.Maximum.ToString()); - - AddHtmlLocalized(20, 150, 200, 25, 1011516); // Cost : - AddLabel(230, 150, 0x44, guardList.Definition.Price.ToString("N0")); // NOTE: Added 'N0' - - AddHtmlLocalized(20, 180, 200, 25, 1011517); // Daily Pay : - AddLabel(230, 180, 0x37, guardList.Definition.Upkeep.ToString("N0")); // NOTE: Added 'N0' - - AddHtmlLocalized(20, 210, 200, 25, 1011518); // Current Silver : - AddLabel(230, 210, 0x44, town.Silver.ToString("N0")); // NOTE: Added 'N0' - - AddHtmlLocalized(20, 240, 200, 25, 1011519); // Current Payroll : - AddLabel(230, 240, 0x44, sheriffUpkeep.ToString("N0")); // NOTE: Added 'N0' - - AddHtmlText(55, 300, 200, 25, guardList.Definition.Label, false, false); - AddButton(20, 300, 4005, 4007, 1 + i); - - AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page - AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 3); - } - } - - private void CenterItem(int itemID, int x, int y, int w, int h) - { - Rectangle2D rc = ItemBounds.Table[itemID]; - AddItem(x + (w - rc.Width) / 2 - rc.X, y + (h - rc.Height) / 2 - rc.Y, itemID); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (!m_Town.IsSheriff(m_From) || m_Town.Owner != m_Faction) - { - m_From.SendLocalizedMessage(1010339); // You no longer control this city - return; - } - - int index = info.ButtonID - 1; - - if (index >= 0 && index < m_Town.GuardLists.Count) - { - GuardList guardList = m_Town.GuardLists[index]; - - if (Town.FromRegion(m_From.Region) != m_Town) - { - m_From.SendLocalizedMessage(1010305); // You must be in your controlled city to buy Items - } - else if (guardList.Guards.Count >= guardList.Definition.Maximum) - { - m_From.SendLocalizedMessage( - 1010306); // You currently have too many of this enhancement type to place another - } - else if (BaseBoat.FindBoatAt(m_From.Location, m_From.Map) != null) - { - m_From.SendMessage("You cannot place a guard here"); - } - else if (m_Town.Silver >= guardList.Definition.Price) - { - BaseFactionGuard guard = guardList.Construct(); - - if (guard != null) - { - guard.Faction = m_Faction; - guard.Town = m_Town; - - m_Town.Silver -= guardList.Definition.Price; - - guard.MoveToWorld(m_From.Location, m_From.Map); - guard.Home = guard.Location; - } - } - } - } - } -} +using Server.Gumps; +using Server.Mobiles; +using Server.Multis; +using Server.Network; + +namespace Server.Factions +{ + public class SheriffGump : FactionGump + { + private readonly Faction m_Faction; + private readonly PlayerMobile m_From; + private readonly Town m_Town; + + public SheriffGump(PlayerMobile from, Faction faction, Town town) : base(50, 50) + { + m_From = from; + m_Faction = faction; + m_Town = town; + + AddPage(0); + + AddBackground(0, 0, 320, 410, 5054); + AddBackground(10, 10, 300, 390, 3000); + + AddPage(1); + + AddHtmlLocalized(20, 30, 260, 25, 1011431); // Sheriff + + AddHtmlLocalized(55, 90, 200, 25, 1011494); // HIRE GUARDS + AddButton(20, 90, 4005, 4007, 0, GumpButtonType.Page, 3); + + AddHtmlLocalized(55, 120, 200, 25, 1011495); // VIEW FINANCES + AddButton(20, 120, 4005, 4007, 0, GumpButtonType.Page, 2); + + AddHtmlLocalized(55, 360, 200, 25, 1011441); // Exit + AddButton(20, 360, 4005, 4007, 0); + + AddPage(2); + + var financeUpkeep = town.FinanceUpkeep; + var sheriffUpkeep = town.SheriffUpkeep; + var dailyIncome = town.DailyIncome; + var netCashFlow = town.NetCashFlow; + + AddHtmlLocalized(20, 30, 300, 25, 1011524); // FINANCE STATEMENT + + AddHtmlLocalized(20, 80, 300, 25, 1011538); // Current total money for town : + AddLabel(20, 100, 0x44, town.Silver.ToString("N0")); // NOTE: Added 'N0' + + AddHtmlLocalized(20, 130, 300, 25, 1011520); // Finance Minister Upkeep : + AddLabel(20, 150, 0x44, financeUpkeep.ToString("N0")); // NOTE: Added 'N0' + + AddHtmlLocalized(20, 180, 300, 25, 1011521); // Sheriff Upkeep : + AddLabel(20, 200, 0x44, sheriffUpkeep.ToString("N0")); // NOTE: Added 'N0' + + AddHtmlLocalized(20, 230, 300, 25, 1011522); // Town Income : + AddLabel(20, 250, 0x44, dailyIncome.ToString("N0")); // NOTE: Added 'N0' + + AddHtmlLocalized(20, 280, 300, 25, 1011523); // Net Cash flow per day : + AddLabel(20, 300, 0x44, netCashFlow.ToString("N0")); // NOTE: Added 'N0' + + AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page + AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 1); + + AddPage(3); + + AddHtmlLocalized(20, 30, 300, 25, 1011494); // HIRE GUARDS + + var guardLists = town.GuardLists; + + for (var i = 0; i < guardLists.Count; ++i) + { + var guardList = guardLists[i]; + var y = 90 + i * 60; + + AddButton(20, y, 4005, 4007, 0, GumpButtonType.Page, 4 + i); + CenterItem(guardList.Definition.ItemID, 50, y - 20, 70, 60); + AddHtmlText(120, y, 200, 25, guardList.Definition.Header, false, false); + } + + AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page + AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 1); + + for (var i = 0; i < guardLists.Count; ++i) + { + var guardList = guardLists[i]; + + AddPage(4 + i); + + AddHtmlText(90, 30, 300, 25, guardList.Definition.Header, false, false); + CenterItem(guardList.Definition.ItemID, 10, 10, 80, 80); + + AddHtmlLocalized(20, 90, 200, 25, 1011514); // You have : + AddLabel(230, 90, 0x26, guardList.Guards.Count.ToString()); + + AddHtmlLocalized(20, 120, 200, 25, 1011515); // Maximum : + AddLabel(230, 120, 0x12A, guardList.Definition.Maximum.ToString()); + + AddHtmlLocalized(20, 150, 200, 25, 1011516); // Cost : + AddLabel(230, 150, 0x44, guardList.Definition.Price.ToString("N0")); // NOTE: Added 'N0' + + AddHtmlLocalized(20, 180, 200, 25, 1011517); // Daily Pay : + AddLabel(230, 180, 0x37, guardList.Definition.Upkeep.ToString("N0")); // NOTE: Added 'N0' + + AddHtmlLocalized(20, 210, 200, 25, 1011518); // Current Silver : + AddLabel(230, 210, 0x44, town.Silver.ToString("N0")); // NOTE: Added 'N0' + + AddHtmlLocalized(20, 240, 200, 25, 1011519); // Current Payroll : + AddLabel(230, 240, 0x44, sheriffUpkeep.ToString("N0")); // NOTE: Added 'N0' + + AddHtmlText(55, 300, 200, 25, guardList.Definition.Label, false, false); + AddButton(20, 300, 4005, 4007, 1 + i); + + AddHtmlLocalized(55, 360, 200, 25, 1011067); // Previous page + AddButton(20, 360, 4005, 4007, 0, GumpButtonType.Page, 3); + } + } + + private void CenterItem(int itemID, int x, int y, int w, int h) + { + var rc = ItemBounds.Table[itemID]; + AddItem(x + (w - rc.Width) / 2 - rc.X, y + (h - rc.Height) / 2 - rc.Y, itemID); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (!m_Town.IsSheriff(m_From) || m_Town.Owner != m_Faction) + { + m_From.SendLocalizedMessage(1010339); // You no longer control this city + return; + } + + var index = info.ButtonID - 1; + + if (index >= 0 && index < m_Town.GuardLists.Count) + { + var guardList = m_Town.GuardLists[index]; + + if (Town.FromRegion(m_From.Region) != m_Town) + { + m_From.SendLocalizedMessage(1010305); // You must be in your controlled city to buy Items + } + else if (guardList.Guards.Count >= guardList.Definition.Maximum) + { + m_From.SendLocalizedMessage( + 1010306 + ); // You currently have too many of this enhancement type to place another + } + else if (BaseBoat.FindBoatAt(m_From.Location, m_From.Map) != null) + { + m_From.SendMessage("You cannot place a guard here"); + } + else if (m_Town.Silver >= guardList.Definition.Price) + { + var guard = guardList.Construct(); + + if (guard != null) + { + guard.Faction = m_Faction; + guard.Town = m_Town; + + m_Town.Silver -= guardList.Definition.Price; + + guard.MoveToWorld(m_From.Location, m_From.Map); + guard.Home = guard.Location; + } + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Gumps/TownStoneGump.cs b/Projects/UOContent/Engines/Factions/Gumps/TownStoneGump.cs index 083cad6cb..bbebeb79b 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/TownStoneGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/TownStoneGump.cs @@ -1,204 +1,208 @@ -using Server.Gumps; -using Server.Mobiles; -using Server.Network; -using Server.Targeting; - -namespace Server.Factions -{ - public class TownStoneGump : FactionGump - { - private readonly Faction m_Faction; - private readonly PlayerMobile m_From; - private readonly Town m_Town; - - public TownStoneGump(PlayerMobile from, Faction faction, Town town) : base(50, 50) - { - m_From = from; - m_Faction = faction; - m_Town = town; - - AddPage(0); - - AddBackground(0, 0, 320, 250, 5054); - AddBackground(10, 10, 300, 230, 3000); - - AddHtmlText(25, 30, 250, 25, town.Definition.TownStoneHeader, false, false); - - AddHtmlLocalized(55, 60, 150, 25, 1011557); // Hire Sheriff - AddButton(20, 60, 4005, 4007, 1); - - AddHtmlLocalized(55, 90, 150, 25, 1011559); // Hire Finance Minister - AddButton(20, 90, 4005, 4007, 2); - - AddHtmlLocalized(55, 120, 150, 25, 1011558); // Fire Sheriff - AddButton(20, 120, 4005, 4007, 3); - - AddHtmlLocalized(55, 150, 150, 25, 1011560); // Fire Finance Minister - AddButton(20, 150, 4005, 4007, 4); - - AddHtmlLocalized(55, 210, 150, 25, 1011441); // EXIT - AddButton(20, 210, 4005, 4007, 0); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Town.Owner != m_Faction || !m_Faction.IsCommander(m_From)) - { - m_From.SendLocalizedMessage(1010339); // You no longer control this city - return; - } - - switch (info.ButtonID) - { - case 1: // hire sheriff - { - if (m_Town.Sheriff != null) - { - m_From.SendLocalizedMessage(1010342); // You must fire your Sheriff before you can elect a new one - } - else - { - m_From.SendLocalizedMessage(1010347); // Who shall be your new sheriff - m_From.BeginTarget(12, false, TargetFlags.None, HireSheriff_OnTarget); - } - - break; - } - case 2: // hire finance minister - { - if (m_Town.Finance != null) - { - m_From.SendLocalizedMessage( - 1010345); // You must fire your finance minister before you can elect a new one - } - else - { - m_From.SendLocalizedMessage(1010348); // Who shall be your new Minister of Finances? - m_From.BeginTarget(12, false, TargetFlags.None, HireFinanceMinister_OnTarget); - } - - break; - } - case 3: // fire sheriff - { - if (m_Town.Sheriff == null) - { - m_From.SendLocalizedMessage(1010350); // You need to elect a sheriff before you can fire one - } - else - { - m_From.SendLocalizedMessage(1010349); // You have fired your sheriff - m_Town.Sheriff.SendLocalizedMessage(1010270); // You have been fired as Sheriff - m_Town.Sheriff = null; - } - - break; - } - case 4: // fire finance minister - { - if (m_Town.Finance == null) - { - m_From.SendLocalizedMessage( - 1010352); // You need to elect a financial minister before you can fire one - } - else - { - m_From.SendLocalizedMessage(1010351); // You have fired your financial Minister - m_Town.Finance.SendLocalizedMessage(1010151); // You have been fired as Finance Minister - m_Town.Finance = null; - } - - break; - } - } - } - - private void HireSheriff_OnTarget(Mobile from, object obj) - { - if (m_Town.Owner != m_Faction || !m_Faction.IsCommander(from)) - { - from.SendLocalizedMessage(1010339); // You no longer control this city - return; - } - - if (m_Town.Sheriff != null) - { - from.SendLocalizedMessage(1010342); // You must fire your Sheriff before you can elect a new one - } - else if (obj is Mobile targ) - { - PlayerState pl = PlayerState.Find(targ); - - if (pl == null) - { - from.SendLocalizedMessage(1010337); // You must pick someone in a faction - } - else if (pl.Faction != m_Faction) - { - from.SendLocalizedMessage(1010338); // You must pick someone in the correct faction - } - else if (m_Faction.Commander == targ) - { - from.SendLocalizedMessage(1010335); // You cannot elect a commander to a town position - } - else if (pl.Sheriff != null || pl.Finance != null) - { - from.SendLocalizedMessage(1005245); // You must pick someone who does not already hold a city post - } - else - { - m_Town.Sheriff = targ; - targ.SendLocalizedMessage(1010340); // You are now the Sheriff - from.SendLocalizedMessage(1010341); // You have elected a Sheriff - } - } - else - { - from.SendLocalizedMessage(1010334); // You must select a player to hold a city position! - } - } - - private void HireFinanceMinister_OnTarget(Mobile from, object obj) - { - if (m_Town.Owner != m_Faction || !m_Faction.IsCommander(from)) - { - from.SendLocalizedMessage(1010339); // You no longer control this city - } - else if (m_Town.Finance != null) - { - from.SendLocalizedMessage(1010342); // You must fire your Sheriff before you can elect a new one - } - else if (obj is Mobile targ) - { - PlayerState pl = PlayerState.Find(targ); - - if (pl == null) - { - from.SendLocalizedMessage(1010337); // You must pick someone in a faction - } - else if (pl.Faction != m_Faction) - { - from.SendLocalizedMessage(1010338); // You must pick someone in the correct faction - } - else if (m_Faction.Commander == targ) - { - from.SendLocalizedMessage(1010335); // You cannot elect a commander to a town position - } - else if (pl.Sheriff != null || pl.Finance != null) - { - from.SendLocalizedMessage(1005245); // You must pick someone who does not already hold a city post - } - else - { - m_Town.Finance = targ; - targ.SendLocalizedMessage(1010343); // You are now the Financial Minister - from.SendLocalizedMessage(1010344); // You have elected a Financial Minister - } - } - else - { - from.SendLocalizedMessage(1010334); // You must select a player to hold a city position! - } - } - } -} +using Server.Gumps; +using Server.Mobiles; +using Server.Network; +using Server.Targeting; + +namespace Server.Factions +{ + public class TownStoneGump : FactionGump + { + private readonly Faction m_Faction; + private readonly PlayerMobile m_From; + private readonly Town m_Town; + + public TownStoneGump(PlayerMobile from, Faction faction, Town town) : base(50, 50) + { + m_From = from; + m_Faction = faction; + m_Town = town; + + AddPage(0); + + AddBackground(0, 0, 320, 250, 5054); + AddBackground(10, 10, 300, 230, 3000); + + AddHtmlText(25, 30, 250, 25, town.Definition.TownStoneHeader, false, false); + + AddHtmlLocalized(55, 60, 150, 25, 1011557); // Hire Sheriff + AddButton(20, 60, 4005, 4007, 1); + + AddHtmlLocalized(55, 90, 150, 25, 1011559); // Hire Finance Minister + AddButton(20, 90, 4005, 4007, 2); + + AddHtmlLocalized(55, 120, 150, 25, 1011558); // Fire Sheriff + AddButton(20, 120, 4005, 4007, 3); + + AddHtmlLocalized(55, 150, 150, 25, 1011560); // Fire Finance Minister + AddButton(20, 150, 4005, 4007, 4); + + AddHtmlLocalized(55, 210, 150, 25, 1011441); // EXIT + AddButton(20, 210, 4005, 4007, 0); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Town.Owner != m_Faction || !m_Faction.IsCommander(m_From)) + { + m_From.SendLocalizedMessage(1010339); // You no longer control this city + return; + } + + switch (info.ButtonID) + { + case 1: // hire sheriff + { + if (m_Town.Sheriff != null) + { + m_From.SendLocalizedMessage( + 1010342 + ); // You must fire your Sheriff before you can elect a new one + } + else + { + m_From.SendLocalizedMessage(1010347); // Who shall be your new sheriff + m_From.BeginTarget(12, false, TargetFlags.None, HireSheriff_OnTarget); + } + + break; + } + case 2: // hire finance minister + { + if (m_Town.Finance != null) + { + m_From.SendLocalizedMessage( + 1010345 + ); // You must fire your finance minister before you can elect a new one + } + else + { + m_From.SendLocalizedMessage(1010348); // Who shall be your new Minister of Finances? + m_From.BeginTarget(12, false, TargetFlags.None, HireFinanceMinister_OnTarget); + } + + break; + } + case 3: // fire sheriff + { + if (m_Town.Sheriff == null) + { + m_From.SendLocalizedMessage(1010350); // You need to elect a sheriff before you can fire one + } + else + { + m_From.SendLocalizedMessage(1010349); // You have fired your sheriff + m_Town.Sheriff.SendLocalizedMessage(1010270); // You have been fired as Sheriff + m_Town.Sheriff = null; + } + + break; + } + case 4: // fire finance minister + { + if (m_Town.Finance == null) + { + m_From.SendLocalizedMessage( + 1010352 + ); // You need to elect a financial minister before you can fire one + } + else + { + m_From.SendLocalizedMessage(1010351); // You have fired your financial Minister + m_Town.Finance.SendLocalizedMessage(1010151); // You have been fired as Finance Minister + m_Town.Finance = null; + } + + break; + } + } + } + + private void HireSheriff_OnTarget(Mobile from, object obj) + { + if (m_Town.Owner != m_Faction || !m_Faction.IsCommander(from)) + { + from.SendLocalizedMessage(1010339); // You no longer control this city + return; + } + + if (m_Town.Sheriff != null) + { + from.SendLocalizedMessage(1010342); // You must fire your Sheriff before you can elect a new one + } + else if (obj is Mobile targ) + { + var pl = PlayerState.Find(targ); + + if (pl == null) + { + from.SendLocalizedMessage(1010337); // You must pick someone in a faction + } + else if (pl.Faction != m_Faction) + { + from.SendLocalizedMessage(1010338); // You must pick someone in the correct faction + } + else if (m_Faction.Commander == targ) + { + from.SendLocalizedMessage(1010335); // You cannot elect a commander to a town position + } + else if (pl.Sheriff != null || pl.Finance != null) + { + from.SendLocalizedMessage(1005245); // You must pick someone who does not already hold a city post + } + else + { + m_Town.Sheriff = targ; + targ.SendLocalizedMessage(1010340); // You are now the Sheriff + from.SendLocalizedMessage(1010341); // You have elected a Sheriff + } + } + else + { + from.SendLocalizedMessage(1010334); // You must select a player to hold a city position! + } + } + + private void HireFinanceMinister_OnTarget(Mobile from, object obj) + { + if (m_Town.Owner != m_Faction || !m_Faction.IsCommander(from)) + { + from.SendLocalizedMessage(1010339); // You no longer control this city + } + else if (m_Town.Finance != null) + { + from.SendLocalizedMessage(1010342); // You must fire your Sheriff before you can elect a new one + } + else if (obj is Mobile targ) + { + var pl = PlayerState.Find(targ); + + if (pl == null) + { + from.SendLocalizedMessage(1010337); // You must pick someone in a faction + } + else if (pl.Faction != m_Faction) + { + from.SendLocalizedMessage(1010338); // You must pick someone in the correct faction + } + else if (m_Faction.Commander == targ) + { + from.SendLocalizedMessage(1010335); // You cannot elect a commander to a town position + } + else if (pl.Sheriff != null || pl.Finance != null) + { + from.SendLocalizedMessage(1005245); // You must pick someone who does not already hold a city post + } + else + { + m_Town.Finance = targ; + targ.SendLocalizedMessage(1010343); // You are now the Financial Minister + from.SendLocalizedMessage(1010344); // You have elected a Financial Minister + } + } + else + { + from.SendLocalizedMessage(1010334); // You must select a player to hold a city position! + } + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Gumps/VoteGump.cs b/Projects/UOContent/Engines/Factions/Gumps/VoteGump.cs index 8d21dd21b..8ecbaebd9 100644 --- a/Projects/UOContent/Engines/Factions/Gumps/VoteGump.cs +++ b/Projects/UOContent/Engines/Factions/Gumps/VoteGump.cs @@ -1,66 +1,66 @@ -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Factions -{ - public class VoteGump : FactionGump - { - private readonly Election m_Election; - private readonly PlayerMobile m_From; - - public VoteGump(PlayerMobile from, Election election) : base(50, 50) - { - m_From = from; - m_Election = election; - - bool canVote = election.CanVote(from); - - AddPage(0); - - AddBackground(0, 0, 420, 350, 5054); - AddBackground(10, 10, 400, 330, 3000); - - AddHtmlText(20, 20, 380, 20, election.Faction.Definition.Header, false, false); - - if (canVote) - AddHtmlLocalized(20, 60, 380, 20, 1011428); // VOTE FOR LEADERSHIP - else - AddHtmlLocalized(20, 60, 380, 20, 1038032); // You have already voted in this election. - - for (int i = 0; i < election.Candidates.Count; ++i) - { - Candidate cd = election.Candidates[i]; - - if (canVote) - AddButton(20, 100 + i * 20, 4005, 4007, i + 1); - - AddLabel(55, 100 + i * 20, 0, cd.Mobile.Name); - AddLabel(300, 100 + i * 20, 0, cd.Votes.ToString()); - } - - AddButton(20, 310, 4005, 4007, 0); - AddHtmlLocalized(55, 310, 100, 20, 1011012); // CANCEL - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 0) - { - m_From.SendGump(new FactionStoneGump(m_From, m_Election.Faction)); - } - else - { - if (!m_Election.CanVote(m_From)) - return; - - int index = info.ButtonID - 1; - - if (index >= 0 && index < m_Election.Candidates.Count) - m_Election.Candidates[index].Voters.Add(new Voter(m_From, m_Election.Candidates[index].Mobile)); - - m_From.SendGump(new VoteGump(m_From, m_Election)); - } - } - } -} +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Factions +{ + public class VoteGump : FactionGump + { + private readonly Election m_Election; + private readonly PlayerMobile m_From; + + public VoteGump(PlayerMobile from, Election election) : base(50, 50) + { + m_From = from; + m_Election = election; + + var canVote = election.CanVote(from); + + AddPage(0); + + AddBackground(0, 0, 420, 350, 5054); + AddBackground(10, 10, 400, 330, 3000); + + AddHtmlText(20, 20, 380, 20, election.Faction.Definition.Header, false, false); + + if (canVote) + AddHtmlLocalized(20, 60, 380, 20, 1011428); // VOTE FOR LEADERSHIP + else + AddHtmlLocalized(20, 60, 380, 20, 1038032); // You have already voted in this election. + + for (var i = 0; i < election.Candidates.Count; ++i) + { + var cd = election.Candidates[i]; + + if (canVote) + AddButton(20, 100 + i * 20, 4005, 4007, i + 1); + + AddLabel(55, 100 + i * 20, 0, cd.Mobile.Name); + AddLabel(300, 100 + i * 20, 0, cd.Votes.ToString()); + } + + AddButton(20, 310, 4005, 4007, 0); + AddHtmlLocalized(55, 310, 100, 20, 1011012); // CANCEL + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 0) + { + m_From.SendGump(new FactionStoneGump(m_From, m_Election.Faction)); + } + else + { + if (!m_Election.CanVote(m_From)) + return; + + var index = info.ButtonID - 1; + + if (index >= 0 && index < m_Election.Candidates.Count) + m_Election.Candidates[index].Voters.Add(new Voter(m_From, m_Election.Candidates[index].Mobile)); + + m_From.SendGump(new VoteGump(m_From, m_Election)); + } + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Instances/Factions/CouncilOfMages.cs b/Projects/UOContent/Engines/Factions/Instances/Factions/CouncilOfMages.cs index 5fc4142bf..ddcc418b4 100644 --- a/Projects/UOContent/Engines/Factions/Instances/Factions/CouncilOfMages.cs +++ b/Projects/UOContent/Engines/Factions/Instances/Factions/CouncilOfMages.cs @@ -1,105 +1,140 @@ -namespace Server.Factions -{ - public class CouncilOfMages : Faction - { - public CouncilOfMages() - { - Instance = this; - - Definition = - new FactionDefinition( - 1, - 1325, // blue - 1310, // bluish white - 1325, // join stone : blue - 1325, // broadcast : blue - 0x77, 0x3EB1, // war horse - "Council of Mages", "council", "CoM", - new TextDefinition(1011535, "COUNCIL OF MAGES"), - new TextDefinition(1060770, "Council of Mages faction"), - new TextDefinition(1011422, "
COUNCIL OF MAGES
"), - new TextDefinition(1011449, - "The council of Mages have their roots in the city of Moonglow, where " + - "they once convened. They began as a small movement, dedicated to " + - "calling forth the Stranger, who saved the lands once before. A " + - "series of war and murders and misbegotten trials by those loyal to " + - "Lord British has caused the group to take up the banner of war."), - new TextDefinition(1011455, "This city is controlled by the Council of Mages."), - new TextDefinition(1042253, "This sigil has been corrupted by the Council of Mages"), - new TextDefinition(1041044, "The faction signup stone for the Council of Mages"), - new TextDefinition(1041382, "The Faction Stone of the Council of Mages"), - new TextDefinition(1011464, ": Council of Mages"), - new TextDefinition(1005187, "Members of the Council of Mages will now be ignored."), - new TextDefinition(1005188, "Members of the Council of Mages will now be warned to leave."), - new TextDefinition(1005189, "Members of the Council of Mages will now be beaten with a stick."), - // Moonglow - new StrongholdDefinition( - new[] - { - new Rectangle2D(4463, 1487, 15, 35), - new Rectangle2D(4450, 1522, 35, 48) - }, - new Point3D(4469, 1486, 0), - new Point3D(4457, 1544, 0), - new[] - { - new Point3D(4464, 1534, 21), - new Point3D(4470, 1536, 21), - new Point3D(4468, 1534, 21), - new Point3D(4470, 1534, 21), - new Point3D(4468, 1536, 21), - new Point3D(4466, 1534, 21), - new Point3D(4466, 1536, 21), - new Point3D(4464, 1536, 21) - }), - // Magincia - /* new StrongholdDefinition( - new Rectangle2D[] - { - new Rectangle2D( 3756, 2232, 4, 23 ), - new Rectangle2D( 3760, 2227, 60, 28 ), - new Rectangle2D( 3782, 2219, 18, 8 ), - new Rectangle2D( 3778, 2255, 35, 17 ) - }, - new Point3D( 3750, 2241, 20 ), - new Point3D( 3795, 2259, 20 ), - new Point3D[] - { - new Point3D( 3793, 2255, 20 ), - new Point3D( 3793, 2252, 20 ), - new Point3D( 3793, 2249, 20 ), - new Point3D( 3793, 2246, 20 ), - new Point3D( 3797, 2255, 20 ), - new Point3D( 3797, 2252, 20 ), - new Point3D( 3797, 2249, 20 ), - new Point3D( 3797, 2246, 20 ) - } ), */ - new[] - { - new RankDefinition(10, 991, 8, new TextDefinition(1060789, "Inquisitor of the Council")), - new RankDefinition(9, 950, 7, new TextDefinition(1060788, "Archon of Principle")), - new RankDefinition(8, 900, 6, new TextDefinition(1060787, "Luminary")), - new RankDefinition(7, 800, 6, new TextDefinition(1060787, "Luminary")), - new RankDefinition(6, 700, 5, new TextDefinition(1060786, "Diviner")), - new RankDefinition(5, 600, 5, new TextDefinition(1060786, "Diviner")), - new RankDefinition(4, 500, 5, new TextDefinition(1060786, "Diviner")), - new RankDefinition(3, 400, 4, new TextDefinition(1060785, "Mystic")), - new RankDefinition(2, 200, 4, new TextDefinition(1060785, "Mystic")), - new RankDefinition(1, 0, 4, new TextDefinition(1060785, "Mystic")) - }, - new[] - { - new GuardDefinition(typeof(FactionHenchman), 0x1403, 5000, 1000, 10, - new TextDefinition(1011526, "HENCHMAN"), new TextDefinition(1011510, "Hire Henchman")), - new GuardDefinition(typeof(FactionMercenary), 0x0F62, 6000, 2000, 10, - new TextDefinition(1011527, "MERCENARY"), new TextDefinition(1011511, "Hire Mercenary")), - new GuardDefinition(typeof(FactionSorceress), 0x0E89, 7000, 3000, 10, - new TextDefinition(1011507, "SORCERESS"), new TextDefinition(1011501, "Hire Sorceress")), - new GuardDefinition(typeof(FactionWizard), 0x13F8, 8000, 4000, 10, - new TextDefinition(1011508, "ELDER WIZARD"), new TextDefinition(1011502, "Hire Elder Wizard")) - }); - } - - public static Faction Instance { get; private set; } - } -} \ No newline at end of file +namespace Server.Factions +{ + public class CouncilOfMages : Faction + { + public CouncilOfMages() + { + Instance = this; + + Definition = + new FactionDefinition( + 1, + 1325, // blue + 1310, // bluish white + 1325, // join stone : blue + 1325, // broadcast : blue + 0x77, + 0x3EB1, // war horse + "Council of Mages", + "council", + "CoM", + new TextDefinition(1011535, "COUNCIL OF MAGES"), + new TextDefinition(1060770, "Council of Mages faction"), + new TextDefinition(1011422, "
COUNCIL OF MAGES
"), + new TextDefinition( + 1011449, + "The council of Mages have their roots in the city of Moonglow, where " + + "they once convened. They began as a small movement, dedicated to " + + "calling forth the Stranger, who saved the lands once before. A " + + "series of war and murders and misbegotten trials by those loyal to " + + "Lord British has caused the group to take up the banner of war." + ), + new TextDefinition(1011455, "This city is controlled by the Council of Mages."), + new TextDefinition(1042253, "This sigil has been corrupted by the Council of Mages"), + new TextDefinition(1041044, "The faction signup stone for the Council of Mages"), + new TextDefinition(1041382, "The Faction Stone of the Council of Mages"), + new TextDefinition(1011464, ": Council of Mages"), + new TextDefinition(1005187, "Members of the Council of Mages will now be ignored."), + new TextDefinition(1005188, "Members of the Council of Mages will now be warned to leave."), + new TextDefinition(1005189, "Members of the Council of Mages will now be beaten with a stick."), + // Moonglow + new StrongholdDefinition( + new[] + { + new Rectangle2D(4463, 1487, 15, 35), + new Rectangle2D(4450, 1522, 35, 48) + }, + new Point3D(4469, 1486, 0), + new Point3D(4457, 1544, 0), + new[] + { + new Point3D(4464, 1534, 21), + new Point3D(4470, 1536, 21), + new Point3D(4468, 1534, 21), + new Point3D(4470, 1534, 21), + new Point3D(4468, 1536, 21), + new Point3D(4466, 1534, 21), + new Point3D(4466, 1536, 21), + new Point3D(4464, 1536, 21) + } + ), + // Magincia + /* new StrongholdDefinition( + new Rectangle2D[] + { + new Rectangle2D( 3756, 2232, 4, 23 ), + new Rectangle2D( 3760, 2227, 60, 28 ), + new Rectangle2D( 3782, 2219, 18, 8 ), + new Rectangle2D( 3778, 2255, 35, 17 ) + }, + new Point3D( 3750, 2241, 20 ), + new Point3D( 3795, 2259, 20 ), + new Point3D[] + { + new Point3D( 3793, 2255, 20 ), + new Point3D( 3793, 2252, 20 ), + new Point3D( 3793, 2249, 20 ), + new Point3D( 3793, 2246, 20 ), + new Point3D( 3797, 2255, 20 ), + new Point3D( 3797, 2252, 20 ), + new Point3D( 3797, 2249, 20 ), + new Point3D( 3797, 2246, 20 ) + } ), */ + new[] + { + new RankDefinition(10, 991, 8, new TextDefinition(1060789, "Inquisitor of the Council")), + new RankDefinition(9, 950, 7, new TextDefinition(1060788, "Archon of Principle")), + new RankDefinition(8, 900, 6, new TextDefinition(1060787, "Luminary")), + new RankDefinition(7, 800, 6, new TextDefinition(1060787, "Luminary")), + new RankDefinition(6, 700, 5, new TextDefinition(1060786, "Diviner")), + new RankDefinition(5, 600, 5, new TextDefinition(1060786, "Diviner")), + new RankDefinition(4, 500, 5, new TextDefinition(1060786, "Diviner")), + new RankDefinition(3, 400, 4, new TextDefinition(1060785, "Mystic")), + new RankDefinition(2, 200, 4, new TextDefinition(1060785, "Mystic")), + new RankDefinition(1, 0, 4, new TextDefinition(1060785, "Mystic")) + }, + new[] + { + new GuardDefinition( + typeof(FactionHenchman), + 0x1403, + 5000, + 1000, + 10, + new TextDefinition(1011526, "HENCHMAN"), + new TextDefinition(1011510, "Hire Henchman") + ), + new GuardDefinition( + typeof(FactionMercenary), + 0x0F62, + 6000, + 2000, + 10, + new TextDefinition(1011527, "MERCENARY"), + new TextDefinition(1011511, "Hire Mercenary") + ), + new GuardDefinition( + typeof(FactionSorceress), + 0x0E89, + 7000, + 3000, + 10, + new TextDefinition(1011507, "SORCERESS"), + new TextDefinition(1011501, "Hire Sorceress") + ), + new GuardDefinition( + typeof(FactionWizard), + 0x13F8, + 8000, + 4000, + 10, + new TextDefinition(1011508, "ELDER WIZARD"), + new TextDefinition(1011502, "Hire Elder Wizard") + ) + } + ); + } + + public static Faction Instance { get; private set; } + } +} diff --git a/Projects/UOContent/Engines/Factions/Instances/Factions/Minax.cs b/Projects/UOContent/Engines/Factions/Instances/Factions/Minax.cs index a7fb613d1..b4807d84f 100644 --- a/Projects/UOContent/Engines/Factions/Instances/Factions/Minax.cs +++ b/Projects/UOContent/Engines/Factions/Instances/Factions/Minax.cs @@ -1,82 +1,117 @@ -namespace Server.Factions -{ - public class Minax : Faction - { - public Minax() - { - Instance = this; - - Definition = - new FactionDefinition( - 0, - 1645, // dark red - 1109, // shadow - 1645, // join stone : dark red - 1645, // broadcast : dark red - 0x78, 0x3EAF, // war horse - "Minax", "minax", "Min", - new TextDefinition(1011534, "MINAX"), - new TextDefinition(1060769, "Minax faction"), - new TextDefinition(1011421, "
FOLLOWERS OF MINAX
"), - new TextDefinition(1011448, - "The followers of Minax have taken control in the old lands, " + - "and intend to hold it for as long as they can. Allying themselves " + - "with orcs, headless, gazers, trolls, and other beasts, they seek " + - "revenge against Lord British, for slights both real and imagined, " + - "though some of the followers wish only to wreak havoc on the " + - "unsuspecting populace."), - new TextDefinition(1011453, "This city is controlled by Minax."), - new TextDefinition(1042252, "This sigil has been corrupted by the Followers of Minax"), - new TextDefinition(1041043, "The faction signup stone for the Followers of Minax"), - new TextDefinition(1041381, "The Faction Stone of Minax"), - new TextDefinition(1011463, ": Minax"), - new TextDefinition(1005190, "Followers of Minax will now be ignored."), - new TextDefinition(1005191, "Followers of Minax will now be told to go away."), - new TextDefinition(1005192, "Followers of Minax will now be hanged by their toes."), - new StrongholdDefinition( - new[] - { - new Rectangle2D(1097, 2570, 70, 50) - }, - new Point3D(1172, 2593, 0), - new Point3D(1117, 2587, 18), - new[] - { - new Point3D(1113, 2601, 18), - new Point3D(1113, 2598, 18), - new Point3D(1113, 2595, 18), - new Point3D(1113, 2592, 18), - new Point3D(1116, 2601, 18), - new Point3D(1116, 2598, 18), - new Point3D(1116, 2595, 18), - new Point3D(1116, 2592, 18) - }), - new[] - { - new RankDefinition(10, 991, 8, new TextDefinition(1060784, "Avenger of Mondain")), - new RankDefinition(9, 950, 7, new TextDefinition(1060783, "Dread Knight")), - new RankDefinition(8, 900, 6, new TextDefinition(1060782, "Warlord")), - new RankDefinition(7, 800, 6, new TextDefinition(1060782, "Warlord")), - new RankDefinition(6, 700, 5, new TextDefinition(1060781, "Executioner")), - new RankDefinition(5, 600, 5, new TextDefinition(1060781, "Executioner")), - new RankDefinition(4, 500, 5, new TextDefinition(1060781, "Executioner")), - new RankDefinition(3, 400, 4, new TextDefinition(1060780, "Defiler")), - new RankDefinition(2, 200, 4, new TextDefinition(1060780, "Defiler")), - new RankDefinition(1, 0, 4, new TextDefinition(1060780, "Defiler")) - }, - new[] - { - new GuardDefinition(typeof(FactionHenchman), 0x1403, 5000, 1000, 10, - new TextDefinition(1011526, "HENCHMAN"), new TextDefinition(1011510, "Hire Henchman")), - new GuardDefinition(typeof(FactionMercenary), 0x0F62, 6000, 2000, 10, - new TextDefinition(1011527, "MERCENARY"), new TextDefinition(1011511, "Hire Mercenary")), - new GuardDefinition(typeof(FactionBerserker), 0x0F4B, 7000, 3000, 10, - new TextDefinition(1011505, "BERSERKER"), new TextDefinition(1011499, "Hire Berserker")), - new GuardDefinition(typeof(FactionDragoon), 0x1439, 8000, 4000, 10, - new TextDefinition(1011506, "DRAGOON"), new TextDefinition(1011500, "Hire Dragoon")) - }); - } - - public static Faction Instance { get; private set; } - } -} \ No newline at end of file +namespace Server.Factions +{ + public class Minax : Faction + { + public Minax() + { + Instance = this; + + Definition = + new FactionDefinition( + 0, + 1645, // dark red + 1109, // shadow + 1645, // join stone : dark red + 1645, // broadcast : dark red + 0x78, + 0x3EAF, // war horse + "Minax", + "minax", + "Min", + new TextDefinition(1011534, "MINAX"), + new TextDefinition(1060769, "Minax faction"), + new TextDefinition(1011421, "
FOLLOWERS OF MINAX
"), + new TextDefinition( + 1011448, + "The followers of Minax have taken control in the old lands, " + + "and intend to hold it for as long as they can. Allying themselves " + + "with orcs, headless, gazers, trolls, and other beasts, they seek " + + "revenge against Lord British, for slights both real and imagined, " + + "though some of the followers wish only to wreak havoc on the " + + "unsuspecting populace." + ), + new TextDefinition(1011453, "This city is controlled by Minax."), + new TextDefinition(1042252, "This sigil has been corrupted by the Followers of Minax"), + new TextDefinition(1041043, "The faction signup stone for the Followers of Minax"), + new TextDefinition(1041381, "The Faction Stone of Minax"), + new TextDefinition(1011463, ": Minax"), + new TextDefinition(1005190, "Followers of Minax will now be ignored."), + new TextDefinition(1005191, "Followers of Minax will now be told to go away."), + new TextDefinition(1005192, "Followers of Minax will now be hanged by their toes."), + new StrongholdDefinition( + new[] + { + new Rectangle2D(1097, 2570, 70, 50) + }, + new Point3D(1172, 2593, 0), + new Point3D(1117, 2587, 18), + new[] + { + new Point3D(1113, 2601, 18), + new Point3D(1113, 2598, 18), + new Point3D(1113, 2595, 18), + new Point3D(1113, 2592, 18), + new Point3D(1116, 2601, 18), + new Point3D(1116, 2598, 18), + new Point3D(1116, 2595, 18), + new Point3D(1116, 2592, 18) + } + ), + new[] + { + new RankDefinition(10, 991, 8, new TextDefinition(1060784, "Avenger of Mondain")), + new RankDefinition(9, 950, 7, new TextDefinition(1060783, "Dread Knight")), + new RankDefinition(8, 900, 6, new TextDefinition(1060782, "Warlord")), + new RankDefinition(7, 800, 6, new TextDefinition(1060782, "Warlord")), + new RankDefinition(6, 700, 5, new TextDefinition(1060781, "Executioner")), + new RankDefinition(5, 600, 5, new TextDefinition(1060781, "Executioner")), + new RankDefinition(4, 500, 5, new TextDefinition(1060781, "Executioner")), + new RankDefinition(3, 400, 4, new TextDefinition(1060780, "Defiler")), + new RankDefinition(2, 200, 4, new TextDefinition(1060780, "Defiler")), + new RankDefinition(1, 0, 4, new TextDefinition(1060780, "Defiler")) + }, + new[] + { + new GuardDefinition( + typeof(FactionHenchman), + 0x1403, + 5000, + 1000, + 10, + new TextDefinition(1011526, "HENCHMAN"), + new TextDefinition(1011510, "Hire Henchman") + ), + new GuardDefinition( + typeof(FactionMercenary), + 0x0F62, + 6000, + 2000, + 10, + new TextDefinition(1011527, "MERCENARY"), + new TextDefinition(1011511, "Hire Mercenary") + ), + new GuardDefinition( + typeof(FactionBerserker), + 0x0F4B, + 7000, + 3000, + 10, + new TextDefinition(1011505, "BERSERKER"), + new TextDefinition(1011499, "Hire Berserker") + ), + new GuardDefinition( + typeof(FactionDragoon), + 0x1439, + 8000, + 4000, + 10, + new TextDefinition(1011506, "DRAGOON"), + new TextDefinition(1011500, "Hire Dragoon") + ) + } + ); + } + + public static Faction Instance { get; private set; } + } +} diff --git a/Projects/UOContent/Engines/Factions/Instances/Factions/Shadowlords.cs b/Projects/UOContent/Engines/Factions/Instances/Factions/Shadowlords.cs index 23c2f0292..c881420fb 100644 --- a/Projects/UOContent/Engines/Factions/Instances/Factions/Shadowlords.cs +++ b/Projects/UOContent/Engines/Factions/Instances/Factions/Shadowlords.cs @@ -1,82 +1,117 @@ -namespace Server.Factions -{ - public class Shadowlords : Faction - { - public Shadowlords() - { - Instance = this; - - Definition = - new FactionDefinition( - 3, - 1109, // shadow - 2211, // green - 1109, // join stone : shadow - 2211, // broadcast : green - 0x79, 0x3EB0, // war horse - "Shadowlords", "shadow", "SL", - new TextDefinition(1011537, "SHADOWLORDS"), - new TextDefinition(1060772, "Shadowlords faction"), - new TextDefinition(1011424, "
SHADES OF DARKNESS
"), - new TextDefinition(1011451, - "The Shadow Lords are a faction that has sprung up within the ranks of " + - "Minax. Comprised mostly of undead and those who would seek to be " + - "necromancers, they pose a threat to both the sides of good and evil. " + - "Their plans have disrupted the hold Minax has over Felucca, and their " + - "ultimate goal is to destroy all life."), - new TextDefinition(1011456, "This city is controlled by the Shadow Lords."), - new TextDefinition(1042255, "This sigil has been corrupted by the Shadowlords"), - new TextDefinition(1041046, "The faction signup stone for the Shadowlords"), - new TextDefinition(1041384, "The Faction Stone of the Shadowlords"), - new TextDefinition(1011466, ": Shadowlords"), - new TextDefinition(1005184, "Minions of the Shadowlords will now be ignored."), - new TextDefinition(1005185, "Minions of the Shadowlords will now be warned of their impending deaths."), - new TextDefinition(1005186, "Minions of the Shadowlords will now be attacked at will."), - new StrongholdDefinition( - new[] - { - new Rectangle2D(960, 688, 8, 9), - new Rectangle2D(944, 697, 24, 23) - }, - new Point3D(969, 768, 0), - new Point3D(947, 713, 0), - new[] - { - new Point3D(953, 713, 20), - new Point3D(953, 709, 20), - new Point3D(953, 705, 20), - new Point3D(953, 701, 20), - new Point3D(957, 713, 20), - new Point3D(957, 709, 20), - new Point3D(957, 705, 20), - new Point3D(957, 701, 20) - }), - new[] - { - new RankDefinition(10, 991, 8, new TextDefinition(1060799, "Purveyor of Darkness")), - new RankDefinition(9, 950, 7, new TextDefinition(1060798, "Agent of Evil")), - new RankDefinition(8, 900, 6, new TextDefinition(1060797, "Bringer of Sorrow")), - new RankDefinition(7, 800, 6, new TextDefinition(1060797, "Bringer of Sorrow")), - new RankDefinition(6, 700, 5, new TextDefinition(1060796, "Keeper of Lies")), - new RankDefinition(5, 600, 5, new TextDefinition(1060796, "Keeper of Lies")), - new RankDefinition(4, 500, 5, new TextDefinition(1060796, "Keeper of Lies")), - new RankDefinition(3, 400, 4, new TextDefinition(1060795, "Servant")), - new RankDefinition(2, 200, 4, new TextDefinition(1060795, "Servant")), - new RankDefinition(1, 0, 4, new TextDefinition(1060795, "Servant")) - }, - new[] - { - new GuardDefinition(typeof(FactionHenchman), 0x1403, 5000, 1000, 10, - new TextDefinition(1011526, "HENCHMAN"), new TextDefinition(1011510, "Hire Henchman")), - new GuardDefinition(typeof(FactionMercenary), 0x0F62, 6000, 2000, 10, - new TextDefinition(1011527, "MERCENARY"), new TextDefinition(1011511, "Hire Mercenary")), - new GuardDefinition(typeof(FactionDeathKnight), 0x0F45, 7000, 3000, 10, - new TextDefinition(1011512, "DEATH KNIGHT"), new TextDefinition(1011503, "Hire Death Knight")), - new GuardDefinition(typeof(FactionNecromancer), 0x13F8, 8000, 4000, 10, - new TextDefinition(1011513, "SHADOW MAGE"), new TextDefinition(1011504, "Hire Shadow Mage")) - }); - } - - public static Faction Instance { get; private set; } - } -} \ No newline at end of file +namespace Server.Factions +{ + public class Shadowlords : Faction + { + public Shadowlords() + { + Instance = this; + + Definition = + new FactionDefinition( + 3, + 1109, // shadow + 2211, // green + 1109, // join stone : shadow + 2211, // broadcast : green + 0x79, + 0x3EB0, // war horse + "Shadowlords", + "shadow", + "SL", + new TextDefinition(1011537, "SHADOWLORDS"), + new TextDefinition(1060772, "Shadowlords faction"), + new TextDefinition(1011424, "
SHADES OF DARKNESS
"), + new TextDefinition( + 1011451, + "The Shadow Lords are a faction that has sprung up within the ranks of " + + "Minax. Comprised mostly of undead and those who would seek to be " + + "necromancers, they pose a threat to both the sides of good and evil. " + + "Their plans have disrupted the hold Minax has over Felucca, and their " + + "ultimate goal is to destroy all life." + ), + new TextDefinition(1011456, "This city is controlled by the Shadow Lords."), + new TextDefinition(1042255, "This sigil has been corrupted by the Shadowlords"), + new TextDefinition(1041046, "The faction signup stone for the Shadowlords"), + new TextDefinition(1041384, "The Faction Stone of the Shadowlords"), + new TextDefinition(1011466, ": Shadowlords"), + new TextDefinition(1005184, "Minions of the Shadowlords will now be ignored."), + new TextDefinition(1005185, "Minions of the Shadowlords will now be warned of their impending deaths."), + new TextDefinition(1005186, "Minions of the Shadowlords will now be attacked at will."), + new StrongholdDefinition( + new[] + { + new Rectangle2D(960, 688, 8, 9), + new Rectangle2D(944, 697, 24, 23) + }, + new Point3D(969, 768, 0), + new Point3D(947, 713, 0), + new[] + { + new Point3D(953, 713, 20), + new Point3D(953, 709, 20), + new Point3D(953, 705, 20), + new Point3D(953, 701, 20), + new Point3D(957, 713, 20), + new Point3D(957, 709, 20), + new Point3D(957, 705, 20), + new Point3D(957, 701, 20) + } + ), + new[] + { + new RankDefinition(10, 991, 8, new TextDefinition(1060799, "Purveyor of Darkness")), + new RankDefinition(9, 950, 7, new TextDefinition(1060798, "Agent of Evil")), + new RankDefinition(8, 900, 6, new TextDefinition(1060797, "Bringer of Sorrow")), + new RankDefinition(7, 800, 6, new TextDefinition(1060797, "Bringer of Sorrow")), + new RankDefinition(6, 700, 5, new TextDefinition(1060796, "Keeper of Lies")), + new RankDefinition(5, 600, 5, new TextDefinition(1060796, "Keeper of Lies")), + new RankDefinition(4, 500, 5, new TextDefinition(1060796, "Keeper of Lies")), + new RankDefinition(3, 400, 4, new TextDefinition(1060795, "Servant")), + new RankDefinition(2, 200, 4, new TextDefinition(1060795, "Servant")), + new RankDefinition(1, 0, 4, new TextDefinition(1060795, "Servant")) + }, + new[] + { + new GuardDefinition( + typeof(FactionHenchman), + 0x1403, + 5000, + 1000, + 10, + new TextDefinition(1011526, "HENCHMAN"), + new TextDefinition(1011510, "Hire Henchman") + ), + new GuardDefinition( + typeof(FactionMercenary), + 0x0F62, + 6000, + 2000, + 10, + new TextDefinition(1011527, "MERCENARY"), + new TextDefinition(1011511, "Hire Mercenary") + ), + new GuardDefinition( + typeof(FactionDeathKnight), + 0x0F45, + 7000, + 3000, + 10, + new TextDefinition(1011512, "DEATH KNIGHT"), + new TextDefinition(1011503, "Hire Death Knight") + ), + new GuardDefinition( + typeof(FactionNecromancer), + 0x13F8, + 8000, + 4000, + 10, + new TextDefinition(1011513, "SHADOW MAGE"), + new TextDefinition(1011504, "Hire Shadow Mage") + ) + } + ); + } + + public static Faction Instance { get; private set; } + } +} diff --git a/Projects/UOContent/Engines/Factions/Instances/Factions/TrueBritannians.cs b/Projects/UOContent/Engines/Factions/Instances/Factions/TrueBritannians.cs index 8a531d6b8..50ae1560e 100644 --- a/Projects/UOContent/Engines/Factions/Instances/Factions/TrueBritannians.cs +++ b/Projects/UOContent/Engines/Factions/Instances/Factions/TrueBritannians.cs @@ -1,87 +1,122 @@ -namespace Server.Factions -{ - public class TrueBritannians : Faction - { - public TrueBritannians() - { - Instance = this; - - Definition = - new FactionDefinition( - 2, - 1254, // dark purple - 2125, // gold - 2214, // join stone : gold - 2125, // broadcast : gold - 0x76, 0x3EB2, // war horse - "True Britannians", "true", "TB", - new TextDefinition(1011536, "LORD BRITISH"), - new TextDefinition(1060771, "True Britannians faction"), - new TextDefinition(1011423, "
TRUE BRITANNIANS
"), - new TextDefinition(1011450, - "True Britannians are loyal to the throne of Lord British. They refuse " + - "to give up their homelands to the vile Minax, and detest the Shadowlords " + - "for their evil ways. In addition, the Council of Mages threatens the " + - "existence of their ruler, and as such they have armed themselves, and " + - "prepare for war with all."), - new TextDefinition(1011454, "This city is controlled by Lord British."), - new TextDefinition(1042254, "This sigil has been corrupted by the True Britannians"), - new TextDefinition(1041045, "The faction signup stone for the True Britannians"), - new TextDefinition(1041383, "The Faction Stone of the True Britannians"), - new TextDefinition(1011465, ": True Britannians"), - new TextDefinition(1005181, "Followers of Lord British will now be ignored."), - new TextDefinition(1005182, "Followers of Lord British will now be warned of their impending doom."), - new TextDefinition(1005183, "Followers of Lord British will now be attacked on sight."), - new StrongholdDefinition( - new[] - { - new Rectangle2D(1292, 1556, 25, 25), - new Rectangle2D(1292, 1676, 120, 25), - new Rectangle2D(1388, 1556, 25, 25), - new Rectangle2D(1317, 1563, 71, 18), - new Rectangle2D(1300, 1581, 105, 95), - new Rectangle2D(1405, 1612, 12, 21), - new Rectangle2D(1405, 1633, 11, 5) - }, - new Point3D(1419, 1622, 20), - new Point3D(1330, 1621, 50), - new[] - { - new Point3D(1328, 1627, 50), - new Point3D(1328, 1621, 50), - new Point3D(1334, 1627, 50), - new Point3D(1334, 1621, 50), - new Point3D(1340, 1627, 50), - new Point3D(1340, 1621, 50), - new Point3D(1345, 1621, 50), - new Point3D(1345, 1627, 50) - }), - new[] - { - new RankDefinition(10, 991, 8, new TextDefinition(1060794, "Knight of the Codex")), - new RankDefinition(9, 950, 7, new TextDefinition(1060793, "Knight of Virtue")), - new RankDefinition(8, 900, 6, new TextDefinition(1060792, "Crusader")), - new RankDefinition(7, 800, 6, new TextDefinition(1060792, "Crusader")), - new RankDefinition(6, 700, 5, new TextDefinition(1060791, "Sentinel")), - new RankDefinition(5, 600, 5, new TextDefinition(1060791, "Sentinel")), - new RankDefinition(4, 500, 5, new TextDefinition(1060791, "Sentinel")), - new RankDefinition(3, 400, 4, new TextDefinition(1060790, "Defender")), - new RankDefinition(2, 200, 4, new TextDefinition(1060790, "Defender")), - new RankDefinition(1, 0, 4, new TextDefinition(1060790, "Defender")) - }, - new[] - { - new GuardDefinition(typeof(FactionHenchman), 0x1403, 5000, 1000, 10, - new TextDefinition(1011526, "HENCHMAN"), new TextDefinition(1011510, "Hire Henchman")), - new GuardDefinition(typeof(FactionMercenary), 0x0F62, 6000, 2000, 10, - new TextDefinition(1011527, "MERCENARY"), new TextDefinition(1011511, "Hire Mercenary")), - new GuardDefinition(typeof(FactionKnight), 0x0F4D, 7000, 3000, 10, - new TextDefinition(1011528, "KNIGHT"), new TextDefinition(1011497, "Hire Knight")), - new GuardDefinition(typeof(FactionPaladin), 0x143F, 8000, 4000, 10, - new TextDefinition(1011529, "PALADIN"), new TextDefinition(1011498, "Hire Paladin")) - }); - } - - public static Faction Instance { get; private set; } - } -} \ No newline at end of file +namespace Server.Factions +{ + public class TrueBritannians : Faction + { + public TrueBritannians() + { + Instance = this; + + Definition = + new FactionDefinition( + 2, + 1254, // dark purple + 2125, // gold + 2214, // join stone : gold + 2125, // broadcast : gold + 0x76, + 0x3EB2, // war horse + "True Britannians", + "true", + "TB", + new TextDefinition(1011536, "LORD BRITISH"), + new TextDefinition(1060771, "True Britannians faction"), + new TextDefinition(1011423, "
TRUE BRITANNIANS
"), + new TextDefinition( + 1011450, + "True Britannians are loyal to the throne of Lord British. They refuse " + + "to give up their homelands to the vile Minax, and detest the Shadowlords " + + "for their evil ways. In addition, the Council of Mages threatens the " + + "existence of their ruler, and as such they have armed themselves, and " + + "prepare for war with all." + ), + new TextDefinition(1011454, "This city is controlled by Lord British."), + new TextDefinition(1042254, "This sigil has been corrupted by the True Britannians"), + new TextDefinition(1041045, "The faction signup stone for the True Britannians"), + new TextDefinition(1041383, "The Faction Stone of the True Britannians"), + new TextDefinition(1011465, ": True Britannians"), + new TextDefinition(1005181, "Followers of Lord British will now be ignored."), + new TextDefinition(1005182, "Followers of Lord British will now be warned of their impending doom."), + new TextDefinition(1005183, "Followers of Lord British will now be attacked on sight."), + new StrongholdDefinition( + new[] + { + new Rectangle2D(1292, 1556, 25, 25), + new Rectangle2D(1292, 1676, 120, 25), + new Rectangle2D(1388, 1556, 25, 25), + new Rectangle2D(1317, 1563, 71, 18), + new Rectangle2D(1300, 1581, 105, 95), + new Rectangle2D(1405, 1612, 12, 21), + new Rectangle2D(1405, 1633, 11, 5) + }, + new Point3D(1419, 1622, 20), + new Point3D(1330, 1621, 50), + new[] + { + new Point3D(1328, 1627, 50), + new Point3D(1328, 1621, 50), + new Point3D(1334, 1627, 50), + new Point3D(1334, 1621, 50), + new Point3D(1340, 1627, 50), + new Point3D(1340, 1621, 50), + new Point3D(1345, 1621, 50), + new Point3D(1345, 1627, 50) + } + ), + new[] + { + new RankDefinition(10, 991, 8, new TextDefinition(1060794, "Knight of the Codex")), + new RankDefinition(9, 950, 7, new TextDefinition(1060793, "Knight of Virtue")), + new RankDefinition(8, 900, 6, new TextDefinition(1060792, "Crusader")), + new RankDefinition(7, 800, 6, new TextDefinition(1060792, "Crusader")), + new RankDefinition(6, 700, 5, new TextDefinition(1060791, "Sentinel")), + new RankDefinition(5, 600, 5, new TextDefinition(1060791, "Sentinel")), + new RankDefinition(4, 500, 5, new TextDefinition(1060791, "Sentinel")), + new RankDefinition(3, 400, 4, new TextDefinition(1060790, "Defender")), + new RankDefinition(2, 200, 4, new TextDefinition(1060790, "Defender")), + new RankDefinition(1, 0, 4, new TextDefinition(1060790, "Defender")) + }, + new[] + { + new GuardDefinition( + typeof(FactionHenchman), + 0x1403, + 5000, + 1000, + 10, + new TextDefinition(1011526, "HENCHMAN"), + new TextDefinition(1011510, "Hire Henchman") + ), + new GuardDefinition( + typeof(FactionMercenary), + 0x0F62, + 6000, + 2000, + 10, + new TextDefinition(1011527, "MERCENARY"), + new TextDefinition(1011511, "Hire Mercenary") + ), + new GuardDefinition( + typeof(FactionKnight), + 0x0F4D, + 7000, + 3000, + 10, + new TextDefinition(1011528, "KNIGHT"), + new TextDefinition(1011497, "Hire Knight") + ), + new GuardDefinition( + typeof(FactionPaladin), + 0x143F, + 8000, + 4000, + 10, + new TextDefinition(1011529, "PALADIN"), + new TextDefinition(1011498, "Hire Paladin") + ) + } + ); + } + + public static Faction Instance { get; private set; } + } +} diff --git a/Projects/UOContent/Engines/Factions/Instances/Towns/Britain.cs b/Projects/UOContent/Engines/Factions/Instances/Towns/Britain.cs index e89ba2bca..7a072c294 100644 --- a/Projects/UOContent/Engines/Factions/Instances/Towns/Britain.cs +++ b/Projects/UOContent/Engines/Factions/Instances/Towns/Britain.cs @@ -1,22 +1,23 @@ -namespace Server.Factions -{ - public class Britain : Town - { - public Britain() => - Definition = - new TownDefinition( - 0, - 0x1869, - "Britain", - "Britain", - new TextDefinition(1011433, "BRITAIN"), - new TextDefinition(1011561, "TOWN STONE FOR BRITAIN"), - new TextDefinition(1041034, "The Faction Sigil Monolith of Britain"), - new TextDefinition(1041404, "The Faction Town Sigil Monolith of Britain"), - new TextDefinition(1041413, "Faction Town Stone of Britain"), - new TextDefinition(1041395, "Faction Town Sigil of Britain"), - new TextDefinition(1041386, "Corrupted Faction Town Sigil of Britain"), - new Point3D(1592, 1680, 10), - new Point3D(1588, 1676, 10)); - } -} \ No newline at end of file +namespace Server.Factions +{ + public class Britain : Town + { + public Britain() => + Definition = + new TownDefinition( + 0, + 0x1869, + "Britain", + "Britain", + new TextDefinition(1011433, "BRITAIN"), + new TextDefinition(1011561, "TOWN STONE FOR BRITAIN"), + new TextDefinition(1041034, "The Faction Sigil Monolith of Britain"), + new TextDefinition(1041404, "The Faction Town Sigil Monolith of Britain"), + new TextDefinition(1041413, "Faction Town Stone of Britain"), + new TextDefinition(1041395, "Faction Town Sigil of Britain"), + new TextDefinition(1041386, "Corrupted Faction Town Sigil of Britain"), + new Point3D(1592, 1680, 10), + new Point3D(1588, 1676, 10) + ); + } +} diff --git a/Projects/UOContent/Engines/Factions/Instances/Towns/Magincia.cs b/Projects/UOContent/Engines/Factions/Instances/Towns/Magincia.cs index 126d58021..feb1ae018 100644 --- a/Projects/UOContent/Engines/Factions/Instances/Towns/Magincia.cs +++ b/Projects/UOContent/Engines/Factions/Instances/Towns/Magincia.cs @@ -1,22 +1,23 @@ -namespace Server.Factions -{ - public class Magincia : Town - { - public Magincia() => - Definition = - new TownDefinition( - 7, - 0x1870, - "Magincia", - "Magincia", - new TextDefinition(1011440, "MAGINCIA"), - new TextDefinition(1011568, "TOWN STONE FOR MAGINCIA"), - new TextDefinition(1041041, "The Faction Sigil Monolith of Magincia"), - new TextDefinition(1041411, "The Faction Town Sigil Monolith of Magincia"), - new TextDefinition(1041420, "Faction Town Stone of Magincia"), - new TextDefinition(1041402, "Faction Town Sigil of Magincia"), - new TextDefinition(1041393, "Corrupted Faction Town Sigil of Magincia"), - new Point3D(3714, 2235, 20), - new Point3D(3712, 2230, 20)); - } -} \ No newline at end of file +namespace Server.Factions +{ + public class Magincia : Town + { + public Magincia() => + Definition = + new TownDefinition( + 7, + 0x1870, + "Magincia", + "Magincia", + new TextDefinition(1011440, "MAGINCIA"), + new TextDefinition(1011568, "TOWN STONE FOR MAGINCIA"), + new TextDefinition(1041041, "The Faction Sigil Monolith of Magincia"), + new TextDefinition(1041411, "The Faction Town Sigil Monolith of Magincia"), + new TextDefinition(1041420, "Faction Town Stone of Magincia"), + new TextDefinition(1041402, "Faction Town Sigil of Magincia"), + new TextDefinition(1041393, "Corrupted Faction Town Sigil of Magincia"), + new Point3D(3714, 2235, 20), + new Point3D(3712, 2230, 20) + ); + } +} diff --git a/Projects/UOContent/Engines/Factions/Instances/Towns/Minoc.cs b/Projects/UOContent/Engines/Factions/Instances/Towns/Minoc.cs index 82f659200..c93545f8f 100644 --- a/Projects/UOContent/Engines/Factions/Instances/Towns/Minoc.cs +++ b/Projects/UOContent/Engines/Factions/Instances/Towns/Minoc.cs @@ -1,22 +1,23 @@ -namespace Server.Factions -{ - public class Minoc : Town - { - public Minoc() => - Definition = - new TownDefinition( - 2, - 0x186B, - "Minoc", - "Minoc", - new TextDefinition(1011437, "MINOC"), - new TextDefinition(1011564, "TOWN STONE FOR MINOC"), - new TextDefinition(1041036, "The Faction Sigil Monolith of Minoc"), - new TextDefinition(1041406, "The Faction Town Sigil Monolith Minoc"), - new TextDefinition(1041415, "Faction Town Stone of Minoc"), - new TextDefinition(1041397, "Faction Town Sigil of Minoc"), - new TextDefinition(1041388, "Corrupted Faction Town Sigil of Minoc"), - new Point3D(2471, 439, 15), - new Point3D(2469, 445, 15)); - } -} \ No newline at end of file +namespace Server.Factions +{ + public class Minoc : Town + { + public Minoc() => + Definition = + new TownDefinition( + 2, + 0x186B, + "Minoc", + "Minoc", + new TextDefinition(1011437, "MINOC"), + new TextDefinition(1011564, "TOWN STONE FOR MINOC"), + new TextDefinition(1041036, "The Faction Sigil Monolith of Minoc"), + new TextDefinition(1041406, "The Faction Town Sigil Monolith Minoc"), + new TextDefinition(1041415, "Faction Town Stone of Minoc"), + new TextDefinition(1041397, "Faction Town Sigil of Minoc"), + new TextDefinition(1041388, "Corrupted Faction Town Sigil of Minoc"), + new Point3D(2471, 439, 15), + new Point3D(2469, 445, 15) + ); + } +} diff --git a/Projects/UOContent/Engines/Factions/Instances/Towns/Moonglow.cs b/Projects/UOContent/Engines/Factions/Instances/Towns/Moonglow.cs index bb4377652..ed5ec2897 100644 --- a/Projects/UOContent/Engines/Factions/Instances/Towns/Moonglow.cs +++ b/Projects/UOContent/Engines/Factions/Instances/Towns/Moonglow.cs @@ -1,22 +1,23 @@ -namespace Server.Factions -{ - public class Moonglow : Town - { - public Moonglow() => - Definition = - new TownDefinition( - 3, - 0x186C, - "Moonglow", - "Moonglow", - new TextDefinition(1011435, "MOONGLOW"), - new TextDefinition(1011563, "TOWN STONE FOR MOONGLOW"), - new TextDefinition(1041037, "The Faction Sigil Monolith of Moonglow"), - new TextDefinition(1041407, "The Faction Town Sigil Monolith of Moonglow"), - new TextDefinition(1041416, "Faction Town Stone of Moonglow"), - new TextDefinition(1041398, "Faction Town Sigil of Moonglow"), - new TextDefinition(1041389, "Corrupted Faction Town Sigil of Moonglow"), - new Point3D(4436, 1083, 0), - new Point3D(4432, 1086, 0)); - } -} \ No newline at end of file +namespace Server.Factions +{ + public class Moonglow : Town + { + public Moonglow() => + Definition = + new TownDefinition( + 3, + 0x186C, + "Moonglow", + "Moonglow", + new TextDefinition(1011435, "MOONGLOW"), + new TextDefinition(1011563, "TOWN STONE FOR MOONGLOW"), + new TextDefinition(1041037, "The Faction Sigil Monolith of Moonglow"), + new TextDefinition(1041407, "The Faction Town Sigil Monolith of Moonglow"), + new TextDefinition(1041416, "Faction Town Stone of Moonglow"), + new TextDefinition(1041398, "Faction Town Sigil of Moonglow"), + new TextDefinition(1041389, "Corrupted Faction Town Sigil of Moonglow"), + new Point3D(4436, 1083, 0), + new Point3D(4432, 1086, 0) + ); + } +} diff --git a/Projects/UOContent/Engines/Factions/Instances/Towns/SkaraBrae.cs b/Projects/UOContent/Engines/Factions/Instances/Towns/SkaraBrae.cs index 20243c3d9..60277833c 100644 --- a/Projects/UOContent/Engines/Factions/Instances/Towns/SkaraBrae.cs +++ b/Projects/UOContent/Engines/Factions/Instances/Towns/SkaraBrae.cs @@ -1,22 +1,23 @@ -namespace Server.Factions -{ - public class SkaraBrae : Town - { - public SkaraBrae() => - Definition = - new TownDefinition( - 6, - 0x186F, - "Skara Brae", - "Skara Brae", - new TextDefinition(1011439, "SKARA BRAE"), - new TextDefinition(1011567, "TOWN STONE FOR SKARA BRAE"), - new TextDefinition(1041040, "The Faction Sigil Monolith of Skara Brae"), - new TextDefinition(1041410, "The Faction Town Sigil Monolith of Skara Brae"), - new TextDefinition(1041419, "Faction Town Stone of Skara Brae"), - new TextDefinition(1041401, "Faction Town Sigil of Skara Brae"), - new TextDefinition(1041392, "Corrupted Faction Town Sigil of Skara Brae"), - new Point3D(576, 2200, 0), - new Point3D(572, 2196, 0)); - } -} \ No newline at end of file +namespace Server.Factions +{ + public class SkaraBrae : Town + { + public SkaraBrae() => + Definition = + new TownDefinition( + 6, + 0x186F, + "Skara Brae", + "Skara Brae", + new TextDefinition(1011439, "SKARA BRAE"), + new TextDefinition(1011567, "TOWN STONE FOR SKARA BRAE"), + new TextDefinition(1041040, "The Faction Sigil Monolith of Skara Brae"), + new TextDefinition(1041410, "The Faction Town Sigil Monolith of Skara Brae"), + new TextDefinition(1041419, "Faction Town Stone of Skara Brae"), + new TextDefinition(1041401, "Faction Town Sigil of Skara Brae"), + new TextDefinition(1041392, "Corrupted Faction Town Sigil of Skara Brae"), + new Point3D(576, 2200, 0), + new Point3D(572, 2196, 0) + ); + } +} diff --git a/Projects/UOContent/Engines/Factions/Instances/Towns/Trinsic.cs b/Projects/UOContent/Engines/Factions/Instances/Towns/Trinsic.cs index 1ae773f61..f53ef55a3 100644 --- a/Projects/UOContent/Engines/Factions/Instances/Towns/Trinsic.cs +++ b/Projects/UOContent/Engines/Factions/Instances/Towns/Trinsic.cs @@ -1,22 +1,23 @@ -namespace Server.Factions -{ - public class Trinsic : Town - { - public Trinsic() => - Definition = - new TownDefinition( - 1, - 0x186A, - "Trinsic", - "Trinsic", - new TextDefinition(1011434, "TRINSIC"), - new TextDefinition(1011562, "TOWN STONE FOR TRINSIC"), - new TextDefinition(1041035, "The Faction Sigil Monolith of Trinsic"), - new TextDefinition(1041405, "The Faction Town Sigil Monolith of Trinsic"), - new TextDefinition(1041414, "Faction Town Stone of Trinsic"), - new TextDefinition(1041396, "Faction Town Sigil of Trinsic"), - new TextDefinition(1041387, "Corrupted Faction Town Sigil of Trinsic"), - new Point3D(1914, 2717, 20), - new Point3D(1909, 2720, 20)); - } -} \ No newline at end of file +namespace Server.Factions +{ + public class Trinsic : Town + { + public Trinsic() => + Definition = + new TownDefinition( + 1, + 0x186A, + "Trinsic", + "Trinsic", + new TextDefinition(1011434, "TRINSIC"), + new TextDefinition(1011562, "TOWN STONE FOR TRINSIC"), + new TextDefinition(1041035, "The Faction Sigil Monolith of Trinsic"), + new TextDefinition(1041405, "The Faction Town Sigil Monolith of Trinsic"), + new TextDefinition(1041414, "Faction Town Stone of Trinsic"), + new TextDefinition(1041396, "Faction Town Sigil of Trinsic"), + new TextDefinition(1041387, "Corrupted Faction Town Sigil of Trinsic"), + new Point3D(1914, 2717, 20), + new Point3D(1909, 2720, 20) + ); + } +} diff --git a/Projects/UOContent/Engines/Factions/Instances/Towns/Vesper.cs b/Projects/UOContent/Engines/Factions/Instances/Towns/Vesper.cs index fd7e8e6a8..fbdf139cb 100644 --- a/Projects/UOContent/Engines/Factions/Instances/Towns/Vesper.cs +++ b/Projects/UOContent/Engines/Factions/Instances/Towns/Vesper.cs @@ -1,22 +1,23 @@ -namespace Server.Factions -{ - public class Vesper : Town - { - public Vesper() => - Definition = - new TownDefinition( - 5, - 0x186E, - "Vesper", - "Vesper", - new TextDefinition(1016413, "VESPER"), - new TextDefinition(1011566, "TOWN STONE FOR VESPER"), - new TextDefinition(1041039, "The Faction Sigil Monolith of Vesper"), - new TextDefinition(1041409, "The Faction Town Sigil Monolith of Vesper"), - new TextDefinition(1041418, "Faction Town Stone of Vesper"), - new TextDefinition(1041400, "Faction Town Sigil of Vesper"), - new TextDefinition(1041391, "Corrupted Faction Town Sigil of Vesper"), - new Point3D(2982, 818, 0), - new Point3D(2985, 821, 0)); - } -} \ No newline at end of file +namespace Server.Factions +{ + public class Vesper : Town + { + public Vesper() => + Definition = + new TownDefinition( + 5, + 0x186E, + "Vesper", + "Vesper", + new TextDefinition(1016413, "VESPER"), + new TextDefinition(1011566, "TOWN STONE FOR VESPER"), + new TextDefinition(1041039, "The Faction Sigil Monolith of Vesper"), + new TextDefinition(1041409, "The Faction Town Sigil Monolith of Vesper"), + new TextDefinition(1041418, "Faction Town Stone of Vesper"), + new TextDefinition(1041400, "Faction Town Sigil of Vesper"), + new TextDefinition(1041391, "Corrupted Faction Town Sigil of Vesper"), + new Point3D(2982, 818, 0), + new Point3D(2985, 821, 0) + ); + } +} diff --git a/Projects/UOContent/Engines/Factions/Instances/Towns/Yew.cs b/Projects/UOContent/Engines/Factions/Instances/Towns/Yew.cs index 9a21177a0..426867090 100644 --- a/Projects/UOContent/Engines/Factions/Instances/Towns/Yew.cs +++ b/Projects/UOContent/Engines/Factions/Instances/Towns/Yew.cs @@ -1,22 +1,23 @@ -namespace Server.Factions -{ - public class Yew : Town - { - public Yew() => - Definition = - new TownDefinition( - 4, - 0x186D, - "Yew", - "Yew", - new TextDefinition(1011438, "YEW"), - new TextDefinition(1011565, "TOWN STONE FOR YEW"), - new TextDefinition(1041038, "The Faction Sigil Monolith of Yew"), - new TextDefinition(1041408, "The Faction Town Sigil Monolith of Yew"), - new TextDefinition(1041417, "Faction Town Stone of Yew"), - new TextDefinition(1041399, "Faction Town Sigil of Yew"), - new TextDefinition(1041390, "Corrupted Faction Town Sigil of Yew"), - new Point3D(548, 979, 0), - new Point3D(542, 980, 0)); - } -} \ No newline at end of file +namespace Server.Factions +{ + public class Yew : Town + { + public Yew() => + Definition = + new TownDefinition( + 4, + 0x186D, + "Yew", + "Yew", + new TextDefinition(1011438, "YEW"), + new TextDefinition(1011565, "TOWN STONE FOR YEW"), + new TextDefinition(1041038, "The Faction Sigil Monolith of Yew"), + new TextDefinition(1041408, "The Faction Town Sigil Monolith of Yew"), + new TextDefinition(1041417, "Faction Town Stone of Yew"), + new TextDefinition(1041399, "Faction Town Sigil of Yew"), + new TextDefinition(1041390, "Corrupted Faction Town Sigil of Yew"), + new Point3D(548, 979, 0), + new Point3D(542, 980, 0) + ); + } +} diff --git a/Projects/UOContent/Engines/Factions/Items/BaseMonolith.cs b/Projects/UOContent/Engines/Factions/Items/BaseMonolith.cs index 2353d34d8..13117bc90 100644 --- a/Projects/UOContent/Engines/Factions/Items/BaseMonolith.cs +++ b/Projects/UOContent/Engines/Factions/Items/BaseMonolith.cs @@ -1,129 +1,129 @@ -using System.Collections.Generic; - -namespace Server.Factions -{ - public abstract class BaseMonolith : BaseSystemController - { - private Faction m_Faction; - private Sigil m_Sigil; - private Town m_Town; - - public BaseMonolith(Town town = null, Faction faction = null) : base(0x1183) - { - Movable = false; - Town = town; - Faction = faction; - Monoliths.Add(this); - } - - public BaseMonolith(Serial serial) : base(serial) - { - Monoliths.Add(this); - } - - [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] - public Sigil Sigil - { - get => m_Sigil; - set - { - if (m_Sigil == value) - return; - - m_Sigil = value; - - if (m_Sigil?.LastMonolith != null && m_Sigil.LastMonolith != this && m_Sigil.LastMonolith.Sigil == m_Sigil) - m_Sigil.LastMonolith.Sigil = null; - - if (m_Sigil != null) - m_Sigil.LastMonolith = this; - - UpdateSigil(); - } - } - - [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] - public Town Town - { - get => m_Town; - set - { - m_Town = value; - OnTownChanged(); - } - } - - [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] - public Faction Faction - { - get => m_Faction; - set - { - m_Faction = value; - Hue = m_Faction?.Definition.HuePrimary ?? 0; - } - } - - public static List Monoliths { get; set; } = new List(); - - public override void OnLocationChange(Point3D oldLocation) - { - base.OnLocationChange(oldLocation); - UpdateSigil(); - } - - public override void OnMapChange() - { - base.OnMapChange(); - UpdateSigil(); - } - - public virtual void UpdateSigil() - { - if (m_Sigil?.Deleted != false) - return; - - m_Sigil.MoveToWorld(new Point3D(X, Y, Z + 18), Map); - } - - public virtual void OnTownChanged() - { - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - Monoliths.Remove(this); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - Town.WriteReference(writer, m_Town); - Faction.WriteReference(writer, m_Faction); - - writer.Write(m_Sigil); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Town = Town.ReadReference(reader); - Faction = Faction.ReadReference(reader); - m_Sigil = reader.ReadItem() as Sigil; - break; - } - } - } - } -} +using System.Collections.Generic; + +namespace Server.Factions +{ + public abstract class BaseMonolith : BaseSystemController + { + private Faction m_Faction; + private Sigil m_Sigil; + private Town m_Town; + + public BaseMonolith(Town town = null, Faction faction = null) : base(0x1183) + { + Movable = false; + Town = town; + Faction = faction; + Monoliths.Add(this); + } + + public BaseMonolith(Serial serial) : base(serial) + { + Monoliths.Add(this); + } + + [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] + public Sigil Sigil + { + get => m_Sigil; + set + { + if (m_Sigil == value) + return; + + m_Sigil = value; + + if (m_Sigil?.LastMonolith != null && m_Sigil.LastMonolith != this && m_Sigil.LastMonolith.Sigil == m_Sigil) + m_Sigil.LastMonolith.Sigil = null; + + if (m_Sigil != null) + m_Sigil.LastMonolith = this; + + UpdateSigil(); + } + } + + [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] + public Town Town + { + get => m_Town; + set + { + m_Town = value; + OnTownChanged(); + } + } + + [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] + public Faction Faction + { + get => m_Faction; + set + { + m_Faction = value; + Hue = m_Faction?.Definition.HuePrimary ?? 0; + } + } + + public static List Monoliths { get; set; } = new List(); + + public override void OnLocationChange(Point3D oldLocation) + { + base.OnLocationChange(oldLocation); + UpdateSigil(); + } + + public override void OnMapChange() + { + base.OnMapChange(); + UpdateSigil(); + } + + public virtual void UpdateSigil() + { + if (m_Sigil?.Deleted != false) + return; + + m_Sigil.MoveToWorld(new Point3D(X, Y, Z + 18), Map); + } + + public virtual void OnTownChanged() + { + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + Monoliths.Remove(this); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + Town.WriteReference(writer, m_Town); + Faction.WriteReference(writer, m_Faction); + + writer.Write(m_Sigil); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Town = Town.ReadReference(reader); + Faction = Faction.ReadReference(reader); + m_Sigil = reader.ReadItem() as Sigil; + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Items/BaseSystemController.cs b/Projects/UOContent/Engines/Factions/Items/BaseSystemController.cs index 5343e5fa7..854fa8839 100644 --- a/Projects/UOContent/Engines/Factions/Items/BaseSystemController.cs +++ b/Projects/UOContent/Engines/Factions/Items/BaseSystemController.cs @@ -1,64 +1,64 @@ -namespace Server.Factions -{ - public abstract class BaseSystemController : Item - { - private int m_LabelNumber; - - public BaseSystemController(int itemID) : base(itemID) - { - } - - public BaseSystemController(Serial serial) : base(serial) - { - } - - public virtual int DefaultLabelNumber => base.LabelNumber; - public new virtual string DefaultName => null; - - public override int LabelNumber - { - get - { - if (m_LabelNumber > 0) - return m_LabelNumber; - - return DefaultLabelNumber; - } - } - - public virtual void AssignName(TextDefinition name) - { - if (name != null && name.Number > 0) - { - m_LabelNumber = name.Number; - Name = null; - } - else if (name?.String != null) - { - m_LabelNumber = 0; - Name = name.String; - } - else - { - m_LabelNumber = 0; - Name = DefaultName; - } - - InvalidateProperties(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Factions +{ + public abstract class BaseSystemController : Item + { + private int m_LabelNumber; + + public BaseSystemController(int itemID) : base(itemID) + { + } + + public BaseSystemController(Serial serial) : base(serial) + { + } + + public virtual int DefaultLabelNumber => base.LabelNumber; + public new virtual string DefaultName => null; + + public override int LabelNumber + { + get + { + if (m_LabelNumber > 0) + return m_LabelNumber; + + return DefaultLabelNumber; + } + } + + public virtual void AssignName(TextDefinition name) + { + if (name != null && name.Number > 0) + { + m_LabelNumber = name.Number; + Name = null; + } + else if (name?.String != null) + { + m_LabelNumber = 0; + Name = name.String; + } + else + { + m_LabelNumber = 0; + Name = DefaultName; + } + + InvalidateProperties(); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Items/FactionStone.cs b/Projects/UOContent/Engines/Factions/Items/FactionStone.cs index ff98a3617..147cf1147 100644 --- a/Projects/UOContent/Engines/Factions/Items/FactionStone.cs +++ b/Projects/UOContent/Engines/Factions/Items/FactionStone.cs @@ -1,99 +1,100 @@ -using Server.Mobiles; -using Server.Network; - -namespace Server.Factions -{ - public class FactionStone : BaseSystemController - { - private Faction m_Faction; - - [Constructible] - public FactionStone(Faction faction = null) : base(0xEDC) - { - Movable = false; - Faction = faction; - } - - public FactionStone(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] - public Faction Faction - { - get => m_Faction; - set - { - m_Faction = value; - - AssignName(m_Faction?.Definition.FactionStoneName); - } - } - - public override string DefaultName => "faction stone"; - - public override void OnDoubleClick(Mobile from) - { - if (m_Faction == null) - return; - - if (!from.InRange(GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - else if (FactionGump.Exists(from)) - { - from.SendLocalizedMessage(1042160); // You already have a faction menu open. - } - else if (from is PlayerMobile mobile) - { - Faction existingFaction = Faction.Find(mobile); - - if (existingFaction == m_Faction || mobile.AccessLevel >= AccessLevel.GameMaster) - { - PlayerState pl = PlayerState.Find(mobile); - - if (pl?.IsLeaving == true) - mobile.SendLocalizedMessage( - 1005051); // You cannot use the faction stone until you have finished quitting your current faction - else - mobile.SendGump(new FactionStoneGump(mobile, m_Faction)); - } - else if (existingFaction != null) - { - // TODO: Validate - mobile.SendLocalizedMessage(1005053); // This is not your faction stone! - } - else - { - mobile.SendGump(new JoinStoneGump(mobile, m_Faction)); - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - Faction.WriteReference(writer, m_Faction); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Faction = Faction.ReadReference(reader); - break; - } - } - } - } -} +using Server.Mobiles; +using Server.Network; + +namespace Server.Factions +{ + public class FactionStone : BaseSystemController + { + private Faction m_Faction; + + [Constructible] + public FactionStone(Faction faction = null) : base(0xEDC) + { + Movable = false; + Faction = faction; + } + + public FactionStone(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] + public Faction Faction + { + get => m_Faction; + set + { + m_Faction = value; + + AssignName(m_Faction?.Definition.FactionStoneName); + } + } + + public override string DefaultName => "faction stone"; + + public override void OnDoubleClick(Mobile from) + { + if (m_Faction == null) + return; + + if (!from.InRange(GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + else if (FactionGump.Exists(from)) + { + from.SendLocalizedMessage(1042160); // You already have a faction menu open. + } + else if (from is PlayerMobile mobile) + { + var existingFaction = Faction.Find(mobile); + + if (existingFaction == m_Faction || mobile.AccessLevel >= AccessLevel.GameMaster) + { + var pl = PlayerState.Find(mobile); + + if (pl?.IsLeaving == true) + mobile.SendLocalizedMessage( + 1005051 + ); // You cannot use the faction stone until you have finished quitting your current faction + else + mobile.SendGump(new FactionStoneGump(mobile, m_Faction)); + } + else if (existingFaction != null) + { + // TODO: Validate + mobile.SendLocalizedMessage(1005053); // This is not your faction stone! + } + else + { + mobile.SendGump(new JoinStoneGump(mobile, m_Faction)); + } + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + Faction.WriteReference(writer, m_Faction); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Faction = Faction.ReadReference(reader); + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Items/JoinStone.cs b/Projects/UOContent/Engines/Factions/Items/JoinStone.cs index a498a9d7b..b97f6b935 100644 --- a/Projects/UOContent/Engines/Factions/Items/JoinStone.cs +++ b/Projects/UOContent/Engines/Factions/Items/JoinStone.cs @@ -1,74 +1,74 @@ -using Server.Mobiles; -using Server.Network; - -namespace Server.Factions -{ - public class JoinStone : BaseSystemController - { - private Faction m_Faction; - - [Constructible] - public JoinStone(Faction faction = null) : base(0xEDC) - { - Movable = false; - Faction = faction; - } - - public JoinStone(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] - public Faction Faction - { - get => m_Faction; - set - { - m_Faction = value; - - Hue = m_Faction?.Definition.HueJoin ?? 0; - AssignName(m_Faction?.Definition.SignupName); - } - } - - public override string DefaultName => "faction signup stone"; - - public override void OnDoubleClick(Mobile from) - { - if (m_Faction == null) - return; - - if (!from.InRange(GetWorldLocation(), 2)) - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - else if (FactionGump.Exists(from)) - from.SendLocalizedMessage(1042160); // You already have a faction menu open. - else if (Faction.Find(from) == null && from is PlayerMobile mobile) - mobile.SendGump(new JoinStoneGump(mobile, m_Faction)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - Faction.WriteReference(writer, m_Faction); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Faction = Faction.ReadReference(reader); - break; - } - } - } - } -} +using Server.Mobiles; +using Server.Network; + +namespace Server.Factions +{ + public class JoinStone : BaseSystemController + { + private Faction m_Faction; + + [Constructible] + public JoinStone(Faction faction = null) : base(0xEDC) + { + Movable = false; + Faction = faction; + } + + public JoinStone(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] + public Faction Faction + { + get => m_Faction; + set + { + m_Faction = value; + + Hue = m_Faction?.Definition.HueJoin ?? 0; + AssignName(m_Faction?.Definition.SignupName); + } + } + + public override string DefaultName => "faction signup stone"; + + public override void OnDoubleClick(Mobile from) + { + if (m_Faction == null) + return; + + if (!from.InRange(GetWorldLocation(), 2)) + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + else if (FactionGump.Exists(from)) + from.SendLocalizedMessage(1042160); // You already have a faction menu open. + else if (Faction.Find(from) == null && from is PlayerMobile mobile) + mobile.SendGump(new JoinStoneGump(mobile, m_Faction)); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + Faction.WriteReference(writer, m_Faction); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Faction = Faction.ReadReference(reader); + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Items/Power Faction Items/BloodRose.cs b/Projects/UOContent/Engines/Factions/Items/Power Faction Items/BloodRose.cs index 5c04931b9..2c1d4b834 100644 --- a/Projects/UOContent/Engines/Factions/Items/Power Faction Items/BloodRose.cs +++ b/Projects/UOContent/Engines/Factions/Items/Power Faction Items/BloodRose.cs @@ -1,57 +1,58 @@ -using System; - -namespace Server -{ - public sealed class BloodRose : PowerFactionItem - { - public BloodRose() - : base(Utility.RandomList(6378, 9035)) => - Hue = 2118; - - public BloodRose(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "blood rose"; - - public override bool Use(Mobile from) - { - if (from.GetStatMod("blood-rose") == null) - { - from.PlaySound(Utility.Random(0x3A, 3)); - - if (from.Body.IsHuman && !from.Mounted) from.Animate(34, 5, 1, true, false, 0); - - int amount = Utility.Dice(3, 3, 3); - int time = Utility.RandomMinMax(5, 30); - - from.FixedParticles(0x373A, 10, 15, 5018, EffectLayer.Waist); - - from.PlaySound(0x1EE); - from.AddStatMod(new StatMod(StatType.All, "blood-rose", amount, TimeSpan.FromMinutes(time))); - - return true; - } - - from.SendLocalizedMessage( - 1062927); // You have eaten one of these recently and eating another would provide no benefit. - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server +{ + public sealed class BloodRose : PowerFactionItem + { + public BloodRose() + : base(Utility.RandomList(6378, 9035)) => + Hue = 2118; + + public BloodRose(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "blood rose"; + + public override bool Use(Mobile from) + { + if (from.GetStatMod("blood-rose") == null) + { + from.PlaySound(Utility.Random(0x3A, 3)); + + if (from.Body.IsHuman && !from.Mounted) from.Animate(34, 5, 1, true, false, 0); + + var amount = Utility.Dice(3, 3, 3); + var time = Utility.RandomMinMax(5, 30); + + from.FixedParticles(0x373A, 10, 15, 5018, EffectLayer.Waist); + + from.PlaySound(0x1EE); + from.AddStatMod(new StatMod(StatType.All, "blood-rose", amount, TimeSpan.FromMinutes(time))); + + return true; + } + + from.SendLocalizedMessage( + 1062927 + ); // You have eaten one of these recently and eating another would provide no benefit. + + return false; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Items/Power Faction Items/ClarityPotion.cs b/Projects/UOContent/Engines/Factions/Items/Power Faction Items/ClarityPotion.cs index 0f3565168..f43563b77 100644 --- a/Projects/UOContent/Engines/Factions/Items/Power Faction Items/ClarityPotion.cs +++ b/Projects/UOContent/Engines/Factions/Items/Power Faction Items/ClarityPotion.cs @@ -1,65 +1,65 @@ -using System; - -namespace Server -{ - public sealed class ClarityPotion : PowerFactionItem - { - public ClarityPotion() - : base(3628) => - Hue = 1154; - - public ClarityPotion(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "clarity potion"; - - public override bool Use(Mobile from) - { - if (from.BeginAction()) - { - int amount = Utility.Dice(3, 3, 3); - int time = Utility.RandomMinMax(5, 30); - - from.PlaySound(0x2D6); - - if (from.Body.IsHuman) from.Animate(34, 5, 1, true, false, 0); - - from.FixedParticles(0x375A, 10, 15, 5011, EffectLayer.Head); - from.PlaySound(0x1EB); - - StatMod mod = from.GetStatMod("Concussion"); - - if (mod != null) - { - from.RemoveStatMod("Concussion"); - from.Mana -= mod.Offset; - } - - from.PlaySound(0x1EE); - from.AddStatMod(new StatMod(StatType.Int, "clarity-potion", amount, TimeSpan.FromMinutes(time))); - - Timer.DelayCall(TimeSpan.FromMinutes(time), from.EndAction); - - return true; - } - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} +using System; + +namespace Server +{ + public sealed class ClarityPotion : PowerFactionItem + { + public ClarityPotion() + : base(3628) => + Hue = 1154; + + public ClarityPotion(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "clarity potion"; + + public override bool Use(Mobile from) + { + if (from.BeginAction()) + { + var amount = Utility.Dice(3, 3, 3); + var time = Utility.RandomMinMax(5, 30); + + from.PlaySound(0x2D6); + + if (from.Body.IsHuman) from.Animate(34, 5, 1, true, false, 0); + + from.FixedParticles(0x375A, 10, 15, 5011, EffectLayer.Head); + from.PlaySound(0x1EB); + + var mod = from.GetStatMod("Concussion"); + + if (mod != null) + { + from.RemoveStatMod("Concussion"); + from.Mana -= mod.Offset; + } + + from.PlaySound(0x1EE); + from.AddStatMod(new StatMod(StatType.Int, "clarity-potion", amount, TimeSpan.FromMinutes(time))); + + Timer.DelayCall(TimeSpan.FromMinutes(time), from.EndAction); + + return true; + } + + return false; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Items/Power Faction Items/GemOfEmpowerment.cs b/Projects/UOContent/Engines/Factions/Items/Power Faction Items/GemOfEmpowerment.cs index eaa4b74da..fb07d6b26 100644 --- a/Projects/UOContent/Engines/Factions/Items/Power Faction Items/GemOfEmpowerment.cs +++ b/Projects/UOContent/Engines/Factions/Items/Power Faction Items/GemOfEmpowerment.cs @@ -1,49 +1,49 @@ -using Server.Factions; -using Server.Network; - -namespace Server -{ - public sealed class GemOfEmpowerment : PowerFactionItem - { - public GemOfEmpowerment() - : base(7955) => - Hue = 1154; - - public GemOfEmpowerment(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "gem of empowerment"; - - public override bool Use(Mobile from) - { - if (Faction.ClearSkillLoss(from)) - { - from.LocalOverheadMessage(MessageType.Regular, 2219, false, "The gem shatters as you invoke its power."); - from.PlaySound(909); - - from.FixedEffect(0x373A, 10, 30); - from.PlaySound(0x209); - - return true; - } - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +using Server.Factions; +using Server.Network; + +namespace Server +{ + public sealed class GemOfEmpowerment : PowerFactionItem + { + public GemOfEmpowerment() + : base(7955) => + Hue = 1154; + + public GemOfEmpowerment(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "gem of empowerment"; + + public override bool Use(Mobile from) + { + if (Faction.ClearSkillLoss(from)) + { + from.LocalOverheadMessage(MessageType.Regular, 2219, false, "The gem shatters as you invoke its power."); + from.PlaySound(909); + + from.FixedEffect(0x373A, 10, 30); + from.PlaySound(0x209); + + return true; + } + + return false; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Items/Power Faction Items/PowerFactionItem.cs b/Projects/UOContent/Engines/Factions/Items/Power Faction Items/PowerFactionItem.cs index ec2806b44..12f7db779 100644 --- a/Projects/UOContent/Engines/Factions/Items/Power Faction Items/PowerFactionItem.cs +++ b/Projects/UOContent/Engines/Factions/Items/Power Faction Items/PowerFactionItem.cs @@ -1,177 +1,192 @@ -using System; -using System.IO; -using Server.Factions; -using Server.Mobiles; -using Server.Network; -using Server.Utilities; - -namespace Server -{ - public abstract class PowerFactionItem : Item - { - private static readonly WeightedItem[] _items = - { - new WeightedItem(30, typeof(GemOfEmpowerment)), - new WeightedItem(25, typeof(BloodRose)), - new WeightedItem(20, typeof(ClarityPotion)), - new WeightedItem(15, typeof(UrnOfAscension)), - new WeightedItem(10, typeof(StormsEye)) - }; - - public PowerFactionItem(int itemId) - : base(itemId) - { - } - - public PowerFactionItem(Serial serial) - : base(serial) - { - } - - public abstract bool Use(Mobile mob); - - public static void CheckSpawn(Mobile killer, Mobile victim) - { - if (killer != null && victim != null) - { - PlayerState ps = PlayerState.Find(victim); - - if (ps != null) - { - int chance = ps.Rank.Rank; - - if (chance > Utility.Random(100)) - { - int weight = 0; - - foreach (WeightedItem item in _items) weight += item.Weight; - - weight = Utility.Random(weight); - - foreach (WeightedItem item in _items) - { - if (weight < item.Weight) - { - Item obj = item.Construct(); - - if (obj != null) - { - killer.AddToBackpack(obj); - - killer.SendSound(1470); - killer.LocalOverheadMessage( - MessageType.Regular, 2119, false, - "You notice a strange item on the corpse, and decide to pick it up."); - - try - { - using StreamWriter op = new StreamWriter("faction-power-items.log", true); - op.WriteLine("{0}\t{1}\t{2}\t{3}", DateTime.UtcNow, killer, victim, obj); - } - catch - { - // ignored - } - } - - break; - } - - weight -= item.Weight; - } - } - } - } - } - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. - } - else if (from is PlayerMobile mobile && mobile.DuelContext != null) - { - mobile.SendMessage("You can't use that."); - } - else if (Faction.Find(from) == null) - { - from.LocalOverheadMessage(MessageType.Regular, 2119, false, - "The object vanishes from your hands as you touch it."); - - Timer.DelayCall(TimeSpan.FromSeconds(1.0), - () => from.LocalOverheadMessage(MessageType.Regular, 2118, false, - "You feel a strange tingling sensation throughout your body.")); - - Timer.DelayCall(TimeSpan.FromSeconds(4.0), - () => { from.LocalOverheadMessage(MessageType.Regular, 2118, false, "Your skin begins to burn."); }); - - new DestructionTimer(from).Start(); - Delete(); - - // from.SendMessage( "You must be in a faction to use this item." ); - } - else if (Use(from)) - { - from.RevealingAction(); - Consume(); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - private sealed class DestructionTimer : Timer - { - private readonly Mobile _mobile; - - private bool _screamed; - - public DestructionTimer(Mobile mob) - : base(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(0.1), 10) => - _mobile = mob; - - protected override void OnTick() - { - if (_mobile.Alive) - { - if (!_screamed) - { - _screamed = true; - - _mobile.PlaySound(_mobile.Female ? 814 : 1088); - _mobile.PublicOverheadMessage(MessageType.Regular, 2118, false, "Aaaaah!"); - } - - _mobile.Damage(Utility.Dice(2, 6, 0)); - } - } - } - - private sealed class WeightedItem - { - public WeightedItem(int weight, Type type) - { - Weight = weight; - Type = type; - } - - public int Weight { get; } - - public Type Type { get; } - - public Item Construct() => ActivatorUtil.CreateInstance(Type) as Item; - } - } -} +using System; +using System.IO; +using Server.Factions; +using Server.Mobiles; +using Server.Network; +using Server.Utilities; + +namespace Server +{ + public abstract class PowerFactionItem : Item + { + private static readonly WeightedItem[] _items = + { + new WeightedItem(30, typeof(GemOfEmpowerment)), + new WeightedItem(25, typeof(BloodRose)), + new WeightedItem(20, typeof(ClarityPotion)), + new WeightedItem(15, typeof(UrnOfAscension)), + new WeightedItem(10, typeof(StormsEye)) + }; + + public PowerFactionItem(int itemId) + : base(itemId) + { + } + + public PowerFactionItem(Serial serial) + : base(serial) + { + } + + public abstract bool Use(Mobile mob); + + public static void CheckSpawn(Mobile killer, Mobile victim) + { + if (killer != null && victim != null) + { + var ps = PlayerState.Find(victim); + + if (ps != null) + { + var chance = ps.Rank.Rank; + + if (chance > Utility.Random(100)) + { + var weight = 0; + + foreach (var item in _items) weight += item.Weight; + + weight = Utility.Random(weight); + + foreach (var item in _items) + { + if (weight < item.Weight) + { + var obj = item.Construct(); + + if (obj != null) + { + killer.AddToBackpack(obj); + + killer.SendSound(1470); + killer.LocalOverheadMessage( + MessageType.Regular, + 2119, + false, + "You notice a strange item on the corpse, and decide to pick it up." + ); + + try + { + using var op = new StreamWriter("faction-power-items.log", true); + op.WriteLine("{0}\t{1}\t{2}\t{3}", DateTime.UtcNow, killer, victim, obj); + } + catch + { + // ignored + } + } + + break; + } + + weight -= item.Weight; + } + } + } + } + } + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. + } + else if (from is PlayerMobile mobile && mobile.DuelContext != null) + { + mobile.SendMessage("You can't use that."); + } + else if (Faction.Find(from) == null) + { + from.LocalOverheadMessage( + MessageType.Regular, + 2119, + false, + "The object vanishes from your hands as you touch it." + ); + + Timer.DelayCall( + TimeSpan.FromSeconds(1.0), + () => from.LocalOverheadMessage( + MessageType.Regular, + 2118, + false, + "You feel a strange tingling sensation throughout your body." + ) + ); + + Timer.DelayCall( + TimeSpan.FromSeconds(4.0), + () => { from.LocalOverheadMessage(MessageType.Regular, 2118, false, "Your skin begins to burn."); } + ); + + new DestructionTimer(from).Start(); + Delete(); + + // from.SendMessage( "You must be in a faction to use this item." ); + } + else if (Use(from)) + { + from.RevealingAction(); + Consume(); + } + } + + 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(); + } + + private sealed class DestructionTimer : Timer + { + private readonly Mobile _mobile; + + private bool _screamed; + + public DestructionTimer(Mobile mob) + : base(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(0.1), 10) => + _mobile = mob; + + protected override void OnTick() + { + if (_mobile.Alive) + { + if (!_screamed) + { + _screamed = true; + + _mobile.PlaySound(_mobile.Female ? 814 : 1088); + _mobile.PublicOverheadMessage(MessageType.Regular, 2118, false, "Aaaaah!"); + } + + _mobile.Damage(Utility.Dice(2, 6, 0)); + } + } + } + + private sealed class WeightedItem + { + public WeightedItem(int weight, Type type) + { + Weight = weight; + Type = type; + } + + public int Weight { get; } + + public Type Type { get; } + + public Item Construct() => ActivatorUtil.CreateInstance(Type) as Item; + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Items/Power Faction Items/StormsEye.cs b/Projects/UOContent/Engines/Factions/Items/Power Faction Items/StormsEye.cs index 6edc4149e..0e5e63f99 100644 --- a/Projects/UOContent/Engines/Factions/Items/Power Faction Items/StormsEye.cs +++ b/Projects/UOContent/Engines/Factions/Items/Power Faction Items/StormsEye.cs @@ -1,111 +1,168 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Server.Factions; -using Server.Spells; -using Server.Targeting; - -namespace Server -{ - public sealed class StormsEye : PowerFactionItem - { - public StormsEye() - : base(3967) => - Hue = 1165; - - public StormsEye(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "storms eye"; - - public override bool Use(Mobile user) - { - if (!Movable) return false; - - user.BeginTarget(12, true, TargetFlags.None, (from, obj, stormsEye) => - { - if (!stormsEye.Movable || stormsEye.Deleted || !(obj is IPoint3D pt)) return; - - SpellHelper.GetSurfaceTop(ref pt); - - Point3D origin = new Point3D(pt); - Map facet = from.Map; - - if (facet?.CanFit(pt.X, pt.Y, pt.Z, 16, false, false) != true) - return; - - stormsEye.Movable = false; - - Effects.SendMovingEffect( - from, new Entity(Serial.Zero, origin, facet), - ItemID & 0x3FFF, 7, 0, false, false, Hue - 1); - - Timer.DelayCall(TimeSpan.FromSeconds(0.5), OnDelay, from, stormsEye, origin, facet); - }, this); - - return false; - } - - private static void OnDelay(Mobile from, StormsEye stormsEye, Point3D origin, Map facet) - { - stormsEye.Delete(); - - Effects.PlaySound(origin, facet, 530); - Effects.PlaySound(origin, facet, 263); - - Effects.SendLocationEffect( - origin, facet, - 14284, 96, 1, 0, 2); - - Timer.DelayCall(TimeSpan.FromSeconds(1.0), OnHit, from, origin, facet); - } - - private static void OnHit(Mobile from, Point3D origin, Map facet) - { - List targets = facet.GetMobilesInRange(origin, 12).Where(mob => - from.CanBeHarmful(mob, false) && mob.InLOS(new Point3D(origin, origin.Z + 1)) && - Faction.Find(mob) != null).ToList(); - - foreach (Mobile mob in targets) - { - int damage = mob.Hits * 6 / 10; - - if (!mob.Player && damage < 10) - damage = 10; - else if (damage > 75) - damage = 75; - - Effects.SendMovingEffect( - new Entity(Serial.Zero, new Point3D(origin, origin.Z + 4), facet), mob, - 14068, 1, 32, false, false, 1111, 2); - - from.DoHarmful(mob); - - SpellHelper.Damage(TimeSpan.FromSeconds(0.50), mob, from, damage / 3.0, 0, 0, 0, 0, - 100); - SpellHelper.Damage(TimeSpan.FromSeconds(0.70), mob, from, damage / 3.0, 0, 0, 0, 0, - 100); - SpellHelper.Damage(TimeSpan.FromSeconds(1.00), mob, from, damage / 3.0, 0, 0, 0, 0, - 100); - - Timer.DelayCall(TimeSpan.FromSeconds(0.50), mob.PlaySound, 0x1FB); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} +using System; +using System.Linq; +using Server.Factions; +using Server.Spells; +using Server.Targeting; + +namespace Server +{ + public sealed class StormsEye : PowerFactionItem + { + public StormsEye() + : base(3967) => + Hue = 1165; + + public StormsEye(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "storms eye"; + + public override bool Use(Mobile user) + { + if (!Movable) return false; + + user.BeginTarget( + 12, + true, + TargetFlags.None, + (from, obj, stormsEye) => + { + if (!stormsEye.Movable || stormsEye.Deleted || !(obj is IPoint3D pt)) return; + + SpellHelper.GetSurfaceTop(ref pt); + + var origin = new Point3D(pt); + var facet = from.Map; + + if (facet?.CanFit(pt.X, pt.Y, pt.Z, 16, false, false) != true) + return; + + stormsEye.Movable = false; + + Effects.SendMovingEffect( + from, + new Entity(Serial.Zero, origin, facet), + ItemID & 0x3FFF, + 7, + 0, + false, + false, + Hue - 1 + ); + + Timer.DelayCall(TimeSpan.FromSeconds(0.5), OnDelay, from, stormsEye, origin, facet); + }, + this + ); + + return false; + } + + private static void OnDelay(Mobile from, StormsEye stormsEye, Point3D origin, Map facet) + { + stormsEye.Delete(); + + Effects.PlaySound(origin, facet, 530); + Effects.PlaySound(origin, facet, 263); + + Effects.SendLocationEffect( + origin, + facet, + 14284, + 96, + 1, + 0, + 2 + ); + + Timer.DelayCall(TimeSpan.FromSeconds(1.0), OnHit, from, origin, facet); + } + + private static void OnHit(Mobile from, Point3D origin, Map facet) + { + var targets = facet.GetMobilesInRange(origin, 12) + .Where( + mob => + from.CanBeHarmful(mob, false) && mob.InLOS(new Point3D(origin, origin.Z + 1)) && + Faction.Find(mob) != null + ) + .ToList(); + + foreach (var mob in targets) + { + var damage = mob.Hits * 6 / 10; + + if (!mob.Player && damage < 10) + damage = 10; + else if (damage > 75) + damage = 75; + + Effects.SendMovingEffect( + new Entity(Serial.Zero, new Point3D(origin, origin.Z + 4), facet), + mob, + 14068, + 1, + 32, + false, + false, + 1111, + 2 + ); + + from.DoHarmful(mob); + + SpellHelper.Damage( + TimeSpan.FromSeconds(0.50), + mob, + from, + damage / 3.0, + 0, + 0, + 0, + 0, + 100 + ); + SpellHelper.Damage( + TimeSpan.FromSeconds(0.70), + mob, + from, + damage / 3.0, + 0, + 0, + 0, + 0, + 100 + ); + SpellHelper.Damage( + TimeSpan.FromSeconds(1.00), + mob, + from, + damage / 3.0, + 0, + 0, + 0, + 0, + 100 + ); + + Timer.DelayCall(TimeSpan.FromSeconds(0.50), mob.PlaySound, 0x1FB); + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Items/Power Faction Items/UrnOfAscension.cs b/Projects/UOContent/Engines/Factions/Items/Power Faction Items/UrnOfAscension.cs index 238817ddc..4397233f8 100644 --- a/Projects/UOContent/Engines/Factions/Items/Power Faction Items/UrnOfAscension.cs +++ b/Projects/UOContent/Engines/Factions/Items/Power Faction Items/UrnOfAscension.cs @@ -1,69 +1,69 @@ -using Server.Factions; -using Server.Gumps; -using Server.Multis; -using Server.Network; - -namespace Server -{ - public sealed class UrnOfAscension : PowerFactionItem - { - public UrnOfAscension() - : base(9246) - { - } - - public UrnOfAscension(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "urn of ascension"; - - public override bool Use(Mobile from) - { - Faction ourFaction = Faction.Find(from); - - bool used = false; - - foreach (Mobile mob in from.GetMobilesInRange(8)) - if (mob.Player && !mob.Alive && from.InLOS(mob)) - { - if (Faction.Find(mob) != ourFaction) continue; - - BaseHouse house = BaseHouse.FindHouseAt(mob); - - if (house?.IsFriend(from) != false || house.IsFriend(mob)) - { - Faction.ClearSkillLoss(mob); - - mob.SendGump(new ResurrectGump(mob, from)); - used = true; - } - } - - if (used) - { - from.LocalOverheadMessage(MessageType.Regular, 2219, false, "The urn shatters as you invoke its power."); - from.PlaySound(64); - - Effects.PlaySound(from.Location, from.Map, 1481); - } - - return used; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} +using Server.Factions; +using Server.Gumps; +using Server.Multis; +using Server.Network; + +namespace Server +{ + public sealed class UrnOfAscension : PowerFactionItem + { + public UrnOfAscension() + : base(9246) + { + } + + public UrnOfAscension(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "urn of ascension"; + + public override bool Use(Mobile from) + { + var ourFaction = Faction.Find(from); + + var used = false; + + foreach (var mob in from.GetMobilesInRange(8)) + if (mob.Player && !mob.Alive && from.InLOS(mob)) + { + if (Faction.Find(mob) != ourFaction) continue; + + var house = BaseHouse.FindHouseAt(mob); + + if (house?.IsFriend(from) != false || house.IsFriend(mob)) + { + Faction.ClearSkillLoss(mob); + + mob.SendGump(new ResurrectGump(mob, from)); + used = true; + } + } + + if (used) + { + from.LocalOverheadMessage(MessageType.Regular, 2219, false, "The urn shatters as you invoke its power."); + from.PlaySound(64); + + Effects.PlaySound(from.Location, from.Map, 1481); + } + + return used; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Items/Sigil.cs b/Projects/UOContent/Engines/Factions/Items/Sigil.cs index 2511353a2..5e4c9e5b6 100644 --- a/Projects/UOContent/Engines/Factions/Items/Sigil.cs +++ b/Projects/UOContent/Engines/Factions/Items/Sigil.cs @@ -1,439 +1,439 @@ -using System; -using System.Collections.Generic; -using Server.Items; -using Server.Mobiles; -using Server.Network; -using Server.Targeting; - -namespace Server.Factions -{ - public class Sigil : BaseSystemController - { - public const int OwnershipHue = 0xB; - - // ?? time corrupting faction has to return the sigil before corruption time resets ? - public static readonly TimeSpan CorruptionGrace = TimeSpan.FromMinutes(Core.SE ? 30.0 : 15.0); - - // Sigil must be held at a stronghold for this amount of time in order to become corrupted - public static readonly TimeSpan CorruptionPeriod = Core.SE ? TimeSpan.FromHours(10.0) : TimeSpan.FromHours(24.0); - - // After a sigil has been corrupted it must be returned to the town within this period of time - public static readonly TimeSpan ReturnPeriod = TimeSpan.FromHours(1.0); - - // Once it's been returned the corrupting faction owns the town for this period of time - public static readonly TimeSpan PurificationPeriod = TimeSpan.FromDays(3.0); - private Faction m_Corrupted; - private Faction m_Corrupting; - - private Town m_Town; - - public Sigil(Town town) : base(0x1869) - { - Movable = false; - Town = town; - - Sigils.Add(this); - } - - public Sigil(Serial serial) : base(serial) - { - Sigils.Add(this); - } - - [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] - public DateTime LastStolen { get; set; } - - [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] - public DateTime GraceStart { get; set; } - - [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] - public DateTime CorruptionStart { get; set; } - - [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] - public DateTime PurificationStart { get; set; } - - [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] - public Town Town - { - get => m_Town; - set - { - m_Town = value; - Update(); - } - } - - [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] - public Faction Corrupted - { - get => m_Corrupted; - set - { - m_Corrupted = value; - Update(); - } - } - - [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] - public Faction Corrupting - { - get => m_Corrupting; - set - { - m_Corrupting = value; - Update(); - } - } - - [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] - public BaseMonolith LastMonolith { get; set; } - - [CommandProperty(AccessLevel.Counselor)] - public bool IsBeingCorrupted => LastMonolith is StrongholdMonolith && LastMonolith.Faction == m_Corrupting && - m_Corrupting != null; - - [CommandProperty(AccessLevel.Counselor)] - public bool IsCorrupted => m_Corrupted != null; - - [CommandProperty(AccessLevel.Counselor)] - public bool IsPurifying => PurificationStart != DateTime.MinValue; - - [CommandProperty(AccessLevel.Counselor)] - public bool IsCorrupting => m_Corrupting != null && m_Corrupting != m_Corrupted; - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan TimeUntilCorruption - { - get - { - if (!IsBeingCorrupted) - return TimeSpan.Zero; - - TimeSpan ts = CorruptionStart + CorruptionPeriod - DateTime.UtcNow; - - if (ts < TimeSpan.Zero) - ts = TimeSpan.Zero; - - return ts; - } - } - - public static List Sigils { get; } = new List(); - - public void Update() - { - ItemID = m_Town?.Definition.SigilID ?? 0x1869; - - if (m_Town == null) - AssignName(null); - else if (IsCorrupted || IsPurifying) - AssignName(m_Town.Definition.CorruptedSigilName); - else - AssignName(m_Town.Definition.SigilName); - - InvalidateProperties(); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (IsCorrupted) - TextDefinition.AddTo(list, m_Corrupted.Definition.SigilControl); - else - list.Add(1042256); // This sigil is not corrupted. - - if (IsCorrupting) - list.Add(1042257); // This sigil is in the process of being corrupted. - else if (IsPurifying) - list.Add(1042258); // This sigil has recently been corrupted, and is undergoing purification. - else - list.Add(1042259); // This sigil is not in the process of being corrupted. - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - if (IsCorrupted) - { - if (m_Corrupted.Definition.SigilControl.Number > 0) - LabelTo(from, m_Corrupted.Definition.SigilControl.Number); - else if (m_Corrupted.Definition.SigilControl.String != null) - LabelTo(from, m_Corrupted.Definition.SigilControl.String); - } - else - { - LabelTo(from, 1042256); // This sigil is not corrupted. - } - - if (IsCorrupting) - LabelTo(from, 1042257); // This sigil is in the process of being corrupted. - else if (IsPurifying) - LabelTo(from, 1042258); // This sigil has been recently corrupted, and is undergoing purification. - else - LabelTo(from, 1042259); // This sigil is not in the process of being corrupted. - } - - public override bool CheckLift(Mobile from, Item item, ref LRReason reject) - { - from.SendLocalizedMessage(1005225); // You must use the stealing skill to pick up the sigil - return false; - } - - private Mobile FindOwner(IEntity parent) - { - if (parent is Item item) - return item.RootParent as Mobile; - - if (parent is Mobile mobile) - return mobile; - - return null; - } - - public override void OnAdded(IEntity parent) - { - base.OnAdded(parent); - - Mobile mob = FindOwner(parent); - - if (mob != null) - mob.SolidHueOverride = OwnershipHue; - } - - public override void OnRemoved(IEntity parent) - { - base.OnRemoved(parent); - - Mobile mob = FindOwner(parent); - - if (mob != null) - mob.SolidHueOverride = -1; - } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - from.BeginTarget(1, false, TargetFlags.None, Sigil_OnTarget); - from.SendLocalizedMessage(1042251); // Click on a sigil monolith or player - } - } - - public static bool ExistsOn(Mobile mob) => mob.Backpack?.FindItemByType() != null; - - private void BeginCorrupting(Faction faction) - { - m_Corrupting = faction; - CorruptionStart = DateTime.UtcNow; - } - - private void ClearCorrupting() - { - m_Corrupting = null; - CorruptionStart = DateTime.MinValue; - } - - private void Sigil_OnTarget(Mobile from, object obj) - { - if (Deleted || !IsChildOf(from.Backpack)) - return; - - if (obj is Mobile) - { - if (obj is PlayerMobile targ) - { - Faction toFaction = Faction.Find(targ); - Faction fromFaction = Faction.Find(from); - - if (toFaction == null) - { - from.SendLocalizedMessage(1005223); // You cannot give the sigil to someone not in a faction - } - else if (fromFaction != toFaction) - { - from.SendLocalizedMessage(1005222); // You cannot give the sigil to someone not in your faction - } - else if (ExistsOn(targ)) - { - from.SendLocalizedMessage(1005220); // You cannot give this sigil to someone who already has a sigil - } - else if (!targ.Alive) - { - from.SendLocalizedMessage(1042248); // You cannot give a sigil to a dead person. - } - else if (from.NetState != null && targ.NetState != null) - { - Container pack = targ.Backpack; - - pack?.DropItem(this); - } - } - else - { - from.SendLocalizedMessage(1005221); // You cannot give the sigil to them - } - } - else if (obj is BaseMonolith) - { - if (obj is StrongholdMonolith sm) - { - if (sm.Faction == null || sm.Faction != Faction.Find(from)) - { - from.SendLocalizedMessage(1042246); // You can't place that on an enemy monolith - } - else if (sm.Town == null || sm.Town != m_Town) - { - from.SendLocalizedMessage(1042247); // That is not the correct faction monolith - } - else - { - sm.Sigil = this; - - Faction newController = sm.Faction; - Faction oldController = m_Corrupting; - - if (oldController == null) - { - if (m_Corrupted != newController) - BeginCorrupting(newController); - } - else if (GraceStart > DateTime.MinValue && GraceStart + CorruptionGrace < DateTime.UtcNow) - { - if (m_Corrupted != newController) - BeginCorrupting(newController); // grace time over, reset period - else - ClearCorrupting(); - - GraceStart = DateTime.MinValue; - } - else if (newController == oldController) - { - GraceStart = DateTime.MinValue; // returned within grace period - } - else if (GraceStart == DateTime.MinValue) - { - GraceStart = DateTime.UtcNow; - } - - PurificationStart = DateTime.MinValue; - } - } - else if (obj is TownMonolith tm) - { - if (tm.Town == null || tm.Town != m_Town) - { - from.SendLocalizedMessage(1042245); // This is not the correct town sigil monolith - } - else if (m_Corrupted == null || m_Corrupted != Faction.Find(from)) - { - from.SendLocalizedMessage( - 1042244); // Your faction did not corrupt this sigil. Take it to your stronghold. - } - else - { - tm.Sigil = this; - - m_Corrupting = null; - PurificationStart = DateTime.UtcNow; - CorruptionStart = DateTime.MinValue; - - m_Town.Capture(m_Corrupted); - m_Corrupted = null; - } - } - } - else - { - from.SendLocalizedMessage(1005224); // You can't use the sigil on that - } - - Update(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - Town.WriteReference(writer, m_Town); - Faction.WriteReference(writer, m_Corrupted); - Faction.WriteReference(writer, m_Corrupting); - - writer.Write(LastMonolith); - - writer.Write(LastStolen); - writer.Write(GraceStart); - writer.Write(CorruptionStart); - writer.Write(PurificationStart); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Town = Town.ReadReference(reader); - m_Corrupted = Faction.ReadReference(reader); - m_Corrupting = Faction.ReadReference(reader); - - LastMonolith = reader.ReadItem() as BaseMonolith; - - LastStolen = reader.ReadDateTime(); - GraceStart = reader.ReadDateTime(); - CorruptionStart = reader.ReadDateTime(); - PurificationStart = reader.ReadDateTime(); - - Update(); - - if (RootParent is Mobile mob) - mob.SolidHueOverride = OwnershipHue; - - break; - } - } - } - - public bool ReturnHome() - { - BaseMonolith monolith = LastMonolith; - - if (monolith == null && m_Town != null) - monolith = m_Town.Monolith; - - if (monolith?.Deleted == false) - monolith.Sigil = this; - - return monolith?.Deleted == false; - } - - public override void OnParentDeleted(IEntity parent) - { - base.OnParentDeleted(parent); - - ReturnHome(); - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - Sigils.Remove(this); - } - - public override void Delete() - { - if (ReturnHome()) - return; - - base.Delete(); - } - } -} +using System; +using System.Collections.Generic; +using Server.Mobiles; +using Server.Network; +using Server.Targeting; + +namespace Server.Factions +{ + public class Sigil : BaseSystemController + { + public const int OwnershipHue = 0xB; + + // ?? time corrupting faction has to return the sigil before corruption time resets ? + public static readonly TimeSpan CorruptionGrace = TimeSpan.FromMinutes(Core.SE ? 30.0 : 15.0); + + // Sigil must be held at a stronghold for this amount of time in order to become corrupted + public static readonly TimeSpan CorruptionPeriod = Core.SE ? TimeSpan.FromHours(10.0) : TimeSpan.FromHours(24.0); + + // After a sigil has been corrupted it must be returned to the town within this period of time + public static readonly TimeSpan ReturnPeriod = TimeSpan.FromHours(1.0); + + // Once it's been returned the corrupting faction owns the town for this period of time + public static readonly TimeSpan PurificationPeriod = TimeSpan.FromDays(3.0); + private Faction m_Corrupted; + private Faction m_Corrupting; + + private Town m_Town; + + public Sigil(Town town) : base(0x1869) + { + Movable = false; + Town = town; + + Sigils.Add(this); + } + + public Sigil(Serial serial) : base(serial) + { + Sigils.Add(this); + } + + [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] + public DateTime LastStolen { get; set; } + + [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] + public DateTime GraceStart { get; set; } + + [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] + public DateTime CorruptionStart { get; set; } + + [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] + public DateTime PurificationStart { get; set; } + + [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] + public Town Town + { + get => m_Town; + set + { + m_Town = value; + Update(); + } + } + + [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] + public Faction Corrupted + { + get => m_Corrupted; + set + { + m_Corrupted = value; + Update(); + } + } + + [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] + public Faction Corrupting + { + get => m_Corrupting; + set + { + m_Corrupting = value; + Update(); + } + } + + [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] + public BaseMonolith LastMonolith { get; set; } + + [CommandProperty(AccessLevel.Counselor)] + public bool IsBeingCorrupted => LastMonolith is StrongholdMonolith && LastMonolith.Faction == m_Corrupting && + m_Corrupting != null; + + [CommandProperty(AccessLevel.Counselor)] + public bool IsCorrupted => m_Corrupted != null; + + [CommandProperty(AccessLevel.Counselor)] + public bool IsPurifying => PurificationStart != DateTime.MinValue; + + [CommandProperty(AccessLevel.Counselor)] + public bool IsCorrupting => m_Corrupting != null && m_Corrupting != m_Corrupted; + + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan TimeUntilCorruption + { + get + { + if (!IsBeingCorrupted) + return TimeSpan.Zero; + + var ts = CorruptionStart + CorruptionPeriod - DateTime.UtcNow; + + if (ts < TimeSpan.Zero) + ts = TimeSpan.Zero; + + return ts; + } + } + + public static List Sigils { get; } = new List(); + + public void Update() + { + ItemID = m_Town?.Definition.SigilID ?? 0x1869; + + if (m_Town == null) + AssignName(null); + else if (IsCorrupted || IsPurifying) + AssignName(m_Town.Definition.CorruptedSigilName); + else + AssignName(m_Town.Definition.SigilName); + + InvalidateProperties(); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (IsCorrupted) + TextDefinition.AddTo(list, m_Corrupted.Definition.SigilControl); + else + list.Add(1042256); // This sigil is not corrupted. + + if (IsCorrupting) + list.Add(1042257); // This sigil is in the process of being corrupted. + else if (IsPurifying) + list.Add(1042258); // This sigil has recently been corrupted, and is undergoing purification. + else + list.Add(1042259); // This sigil is not in the process of being corrupted. + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + if (IsCorrupted) + { + if (m_Corrupted.Definition.SigilControl.Number > 0) + LabelTo(from, m_Corrupted.Definition.SigilControl.Number); + else if (m_Corrupted.Definition.SigilControl.String != null) + LabelTo(from, m_Corrupted.Definition.SigilControl.String); + } + else + { + LabelTo(from, 1042256); // This sigil is not corrupted. + } + + if (IsCorrupting) + LabelTo(from, 1042257); // This sigil is in the process of being corrupted. + else if (IsPurifying) + LabelTo(from, 1042258); // This sigil has been recently corrupted, and is undergoing purification. + else + LabelTo(from, 1042259); // This sigil is not in the process of being corrupted. + } + + public override bool CheckLift(Mobile from, Item item, ref LRReason reject) + { + from.SendLocalizedMessage(1005225); // You must use the stealing skill to pick up the sigil + return false; + } + + private Mobile FindOwner(IEntity parent) + { + if (parent is Item item) + return item.RootParent as Mobile; + + if (parent is Mobile mobile) + return mobile; + + return null; + } + + public override void OnAdded(IEntity parent) + { + base.OnAdded(parent); + + var mob = FindOwner(parent); + + if (mob != null) + mob.SolidHueOverride = OwnershipHue; + } + + public override void OnRemoved(IEntity parent) + { + base.OnRemoved(parent); + + var mob = FindOwner(parent); + + if (mob != null) + mob.SolidHueOverride = -1; + } + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + from.BeginTarget(1, false, TargetFlags.None, Sigil_OnTarget); + from.SendLocalizedMessage(1042251); // Click on a sigil monolith or player + } + } + + public static bool ExistsOn(Mobile mob) => mob.Backpack?.FindItemByType() != null; + + private void BeginCorrupting(Faction faction) + { + m_Corrupting = faction; + CorruptionStart = DateTime.UtcNow; + } + + private void ClearCorrupting() + { + m_Corrupting = null; + CorruptionStart = DateTime.MinValue; + } + + private void Sigil_OnTarget(Mobile from, object obj) + { + if (Deleted || !IsChildOf(from.Backpack)) + return; + + if (obj is Mobile) + { + if (obj is PlayerMobile targ) + { + var toFaction = Faction.Find(targ); + var fromFaction = Faction.Find(from); + + if (toFaction == null) + { + from.SendLocalizedMessage(1005223); // You cannot give the sigil to someone not in a faction + } + else if (fromFaction != toFaction) + { + from.SendLocalizedMessage(1005222); // You cannot give the sigil to someone not in your faction + } + else if (ExistsOn(targ)) + { + from.SendLocalizedMessage(1005220); // You cannot give this sigil to someone who already has a sigil + } + else if (!targ.Alive) + { + from.SendLocalizedMessage(1042248); // You cannot give a sigil to a dead person. + } + else if (from.NetState != null && targ.NetState != null) + { + var pack = targ.Backpack; + + pack?.DropItem(this); + } + } + else + { + from.SendLocalizedMessage(1005221); // You cannot give the sigil to them + } + } + else if (obj is BaseMonolith) + { + if (obj is StrongholdMonolith sm) + { + if (sm.Faction == null || sm.Faction != Faction.Find(from)) + { + from.SendLocalizedMessage(1042246); // You can't place that on an enemy monolith + } + else if (sm.Town == null || sm.Town != m_Town) + { + from.SendLocalizedMessage(1042247); // That is not the correct faction monolith + } + else + { + sm.Sigil = this; + + var newController = sm.Faction; + var oldController = m_Corrupting; + + if (oldController == null) + { + if (m_Corrupted != newController) + BeginCorrupting(newController); + } + else if (GraceStart > DateTime.MinValue && GraceStart + CorruptionGrace < DateTime.UtcNow) + { + if (m_Corrupted != newController) + BeginCorrupting(newController); // grace time over, reset period + else + ClearCorrupting(); + + GraceStart = DateTime.MinValue; + } + else if (newController == oldController) + { + GraceStart = DateTime.MinValue; // returned within grace period + } + else if (GraceStart == DateTime.MinValue) + { + GraceStart = DateTime.UtcNow; + } + + PurificationStart = DateTime.MinValue; + } + } + else if (obj is TownMonolith tm) + { + if (tm.Town == null || tm.Town != m_Town) + { + from.SendLocalizedMessage(1042245); // This is not the correct town sigil monolith + } + else if (m_Corrupted == null || m_Corrupted != Faction.Find(from)) + { + from.SendLocalizedMessage( + 1042244 + ); // Your faction did not corrupt this sigil. Take it to your stronghold. + } + else + { + tm.Sigil = this; + + m_Corrupting = null; + PurificationStart = DateTime.UtcNow; + CorruptionStart = DateTime.MinValue; + + m_Town.Capture(m_Corrupted); + m_Corrupted = null; + } + } + } + else + { + from.SendLocalizedMessage(1005224); // You can't use the sigil on that + } + + Update(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + Town.WriteReference(writer, m_Town); + Faction.WriteReference(writer, m_Corrupted); + Faction.WriteReference(writer, m_Corrupting); + + writer.Write(LastMonolith); + + writer.Write(LastStolen); + writer.Write(GraceStart); + writer.Write(CorruptionStart); + writer.Write(PurificationStart); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Town = Town.ReadReference(reader); + m_Corrupted = Faction.ReadReference(reader); + m_Corrupting = Faction.ReadReference(reader); + + LastMonolith = reader.ReadItem() as BaseMonolith; + + LastStolen = reader.ReadDateTime(); + GraceStart = reader.ReadDateTime(); + CorruptionStart = reader.ReadDateTime(); + PurificationStart = reader.ReadDateTime(); + + Update(); + + if (RootParent is Mobile mob) + mob.SolidHueOverride = OwnershipHue; + + break; + } + } + } + + public bool ReturnHome() + { + var monolith = LastMonolith; + + if (monolith == null && m_Town != null) + monolith = m_Town.Monolith; + + if (monolith?.Deleted == false) + monolith.Sigil = this; + + return monolith?.Deleted == false; + } + + public override void OnParentDeleted(IEntity parent) + { + base.OnParentDeleted(parent); + + ReturnHome(); + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + Sigils.Remove(this); + } + + public override void Delete() + { + if (ReturnHome()) + return; + + base.Delete(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Items/Silver.cs b/Projects/UOContent/Engines/Factions/Items/Silver.cs index 8edcfedbe..684242207 100644 --- a/Projects/UOContent/Engines/Factions/Items/Silver.cs +++ b/Projects/UOContent/Engines/Factions/Items/Silver.cs @@ -1,51 +1,51 @@ -namespace Server.Factions -{ - public class Silver : Item - { - [Constructible] - public Silver() : this(1) - { - } - - [Constructible] - public Silver(int amountFrom, int amountTo) : this(Utility.RandomMinMax(amountFrom, amountTo)) - { - } - - [Constructible] - public Silver(int amount) : base(0xEF0) - { - Stackable = true; - Amount = amount; - } - - public Silver(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.02; - - public override int GetDropSound() - { - if (Amount <= 1) - return 0x2E4; - if (Amount <= 5) - return 0x2E5; - return 0x2E6; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Factions +{ + public class Silver : Item + { + [Constructible] + public Silver() : this(1) + { + } + + [Constructible] + public Silver(int amountFrom, int amountTo) : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } + + [Constructible] + public Silver(int amount) : base(0xEF0) + { + Stackable = true; + Amount = amount; + } + + public Silver(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0.02; + + public override int GetDropSound() + { + if (Amount <= 1) + return 0x2E4; + if (Amount <= 5) + return 0x2E5; + return 0x2E6; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Items/StrongholdMonolith.cs b/Projects/UOContent/Engines/Factions/Items/StrongholdMonolith.cs index fda116e90..3eab01878 100644 --- a/Projects/UOContent/Engines/Factions/Items/StrongholdMonolith.cs +++ b/Projects/UOContent/Engines/Factions/Items/StrongholdMonolith.cs @@ -1,34 +1,34 @@ -namespace Server.Factions -{ - public class StrongholdMonolith : BaseMonolith - { - public StrongholdMonolith(Town town = null, Faction faction = null) : base(town, faction) - { - } - - public StrongholdMonolith(Serial serial) : base(serial) - { - } - - public override int DefaultLabelNumber => 1041042; // A Faction Sigil Monolith - - public override void OnTownChanged() - { - AssignName(Town?.Definition.StrongholdMonolithName); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Factions +{ + public class StrongholdMonolith : BaseMonolith + { + public StrongholdMonolith(Town town = null, Faction faction = null) : base(town, faction) + { + } + + public StrongholdMonolith(Serial serial) : base(serial) + { + } + + public override int DefaultLabelNumber => 1041042; // A Faction Sigil Monolith + + public override void OnTownChanged() + { + AssignName(Town?.Definition.StrongholdMonolithName); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Items/TownMonolith.cs b/Projects/UOContent/Engines/Factions/Items/TownMonolith.cs index 40fd32ed1..264184f48 100644 --- a/Projects/UOContent/Engines/Factions/Items/TownMonolith.cs +++ b/Projects/UOContent/Engines/Factions/Items/TownMonolith.cs @@ -1,34 +1,34 @@ -namespace Server.Factions -{ - public class TownMonolith : BaseMonolith - { - public TownMonolith(Town town = null) : base(town) - { - } - - public TownMonolith(Serial serial) : base(serial) - { - } - - public override int DefaultLabelNumber => 1041403; // A Faction Town Sigil Monolith - - public override void OnTownChanged() - { - AssignName(Town?.Definition.TownMonolithName); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Factions +{ + public class TownMonolith : BaseMonolith + { + public TownMonolith(Town town = null) : base(town) + { + } + + public TownMonolith(Serial serial) : base(serial) + { + } + + public override int DefaultLabelNumber => 1041403; // A Faction Town Sigil Monolith + + public override void OnTownChanged() + { + AssignName(Town?.Definition.TownMonolithName); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Items/TownStone.cs b/Projects/UOContent/Engines/Factions/Items/TownStone.cs index f87d7b481..b452f4905 100644 --- a/Projects/UOContent/Engines/Factions/Items/TownStone.cs +++ b/Projects/UOContent/Engines/Factions/Items/TownStone.cs @@ -1,79 +1,79 @@ -using Server.Mobiles; - -namespace Server.Factions -{ - public class TownStone : BaseSystemController - { - private Town m_Town; - - [Constructible] - public TownStone(Town town = null) : base(0xEDE) - { - Movable = false; - Town = town; - } - - public TownStone(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] - public Town Town - { - get => m_Town; - set - { - m_Town = value; - - AssignName(m_Town?.Definition.TownStoneName); - } - } - - public override string DefaultName => "faction town stone"; - - public override void OnDoubleClick(Mobile from) - { - if (m_Town == null) - return; - - Faction faction = Faction.Find(from); - - if (faction == null && from.AccessLevel < AccessLevel.GameMaster) - return; // TODO: Message? - - if (m_Town.Owner == null || (from.AccessLevel < AccessLevel.GameMaster && faction != m_Town.Owner)) - from.SendLocalizedMessage(1010332); // Your faction does not control this town - else if (!m_Town.Owner.IsCommander(from)) - from.SendLocalizedMessage(1005242); // Only faction Leaders can use townstones - else if (FactionGump.Exists(from)) - from.SendLocalizedMessage(1042160); // You already have a faction menu open. - else if (from is PlayerMobile mobile) - mobile.SendGump(new TownStoneGump(mobile, m_Town.Owner, m_Town)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - Town.WriteReference(writer, m_Town); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Town = Town.ReadReference(reader); - break; - } - } - } - } -} +using Server.Mobiles; + +namespace Server.Factions +{ + public class TownStone : BaseSystemController + { + private Town m_Town; + + [Constructible] + public TownStone(Town town = null) : base(0xEDE) + { + Movable = false; + Town = town; + } + + public TownStone(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] + public Town Town + { + get => m_Town; + set + { + m_Town = value; + + AssignName(m_Town?.Definition.TownStoneName); + } + } + + public override string DefaultName => "faction town stone"; + + public override void OnDoubleClick(Mobile from) + { + if (m_Town == null) + return; + + var faction = Faction.Find(from); + + if (faction == null && from.AccessLevel < AccessLevel.GameMaster) + return; // TODO: Message? + + if (m_Town.Owner == null || @from.AccessLevel < AccessLevel.GameMaster && faction != m_Town.Owner) + from.SendLocalizedMessage(1010332); // Your faction does not control this town + else if (!m_Town.Owner.IsCommander(from)) + from.SendLocalizedMessage(1005242); // Only faction Leaders can use townstones + else if (FactionGump.Exists(from)) + from.SendLocalizedMessage(1042160); // You already have a faction menu open. + else if (from is PlayerMobile mobile) + mobile.SendGump(new TownStoneGump(mobile, m_Town.Owner, m_Town)); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + Town.WriteReference(writer, m_Town); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Town = Town.ReadReference(reader); + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Items/Traps/BaseFactionTrap.cs b/Projects/UOContent/Engines/Factions/Items/Traps/BaseFactionTrap.cs index e02c9fcd0..7ad03e92b 100644 --- a/Projects/UOContent/Engines/Factions/Items/Traps/BaseFactionTrap.cs +++ b/Projects/UOContent/Engines/Factions/Items/Traps/BaseFactionTrap.cs @@ -1,261 +1,266 @@ -using System; -using Server.Items; -using Server.Network; - -namespace Server.Factions -{ - public enum AllowedPlacing - { - Everywhere, - - AnyFactionTown, - ControlledFactionTown, - FactionStronghold - } - - public abstract class BaseFactionTrap : BaseTrap - { - private Timer m_Concealing; - - public BaseFactionTrap(Faction f, Mobile m, int itemID) : base(itemID) - { - Visible = false; - - Faction = f; - TimeOfPlacement = DateTime.UtcNow; - Placer = m; - } - - public BaseFactionTrap(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public Faction Faction { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Placer { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime TimeOfPlacement { get; set; } - - public virtual int EffectSound => 0; - - public virtual int SilverFromDisarm => 100; - - public virtual int MessageHue => 0; - - public virtual int AttackMessage => 0; - public virtual int DisarmMessage => 0; - - public virtual AllowedPlacing AllowedPlacing => AllowedPlacing.Everywhere; - - public virtual TimeSpan ConcealPeriod => TimeSpan.FromMinutes(1.0); - - public virtual TimeSpan DecayPeriod - { - get - { - if (Core.AOS) - return TimeSpan.FromDays(1.0); - - return TimeSpan.MaxValue; // no decay - } - } - - public override void OnTrigger(Mobile from) - { - if (!IsEnemy(from)) - return; - - Conceal(); - - DoVisibleEffect(); - Effects.PlaySound(Location, Map, EffectSound); - DoAttackEffect(from); - - int silverToAward = from.Alive ? 20 : 40; - - if (silverToAward > 0 && Placer != null && Faction != null) - { - PlayerState victimState = PlayerState.Find(from); - - if (victimState?.CanGiveSilverTo(Placer) == true && victimState.KillPoints > 0) - { - int silverGiven = Faction.AwardSilver(Placer, silverToAward); - - if (silverGiven > 0) - { - // TODO: Get real message - if (from.Alive) - Placer.SendMessage("You have earned {0} silver pieces because {1} fell for your trap.", - silverGiven, from.Name); - else - Placer.SendLocalizedMessage(1042736, - $"{silverGiven} silver\t{from.Name}"); // You have earned ~1_SILVER_AMOUNT~ pieces for vanquishing ~2_PLAYER_NAME~! - } - - victimState.OnGivenSilverTo(Placer); - } - } - - from.LocalOverheadMessage(MessageType.Regular, MessageHue, AttackMessage); - } - - public abstract void DoVisibleEffect(); - public abstract void DoAttackEffect(Mobile m); - - public virtual int IsValidLocation() => IsValidLocation(GetWorldLocation(), Map); - - public virtual int IsValidLocation(Point3D p, Map m) - { - if (m == null) - return 502956; // You cannot place a trap on that. - - if (Core.ML) - foreach (Item item in m.GetItemsInRange(p, 0)) - if (item is BaseFactionTrap trap && trap.Faction == Faction) - return 1075263; // There is already a trap belonging to your faction at this location.; - - switch (AllowedPlacing) - { - case AllowedPlacing.FactionStronghold: - { - StrongholdRegion region = Region.Find(p, m).GetRegion(); - - if (region != null && region.Faction == Faction) - return 0; - - return 1010355; // This trap can only be placed in your stronghold - } - case AllowedPlacing.AnyFactionTown: - { - Town town = Town.FromRegion(Region.Find(p, m)); - - if (town != null) - return 0; - - return 1010356; // This trap can only be placed in a faction town - } - case AllowedPlacing.ControlledFactionTown: - { - Town town = Town.FromRegion(Region.Find(p, m)); - - if (town != null && town.Owner == Faction) - return 0; - - return 1010357; // This trap can only be placed in a town your faction controls - } - } - - return 0; - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - base.OnMovement(m, oldLocation); - - if (!CheckDecay() && CheckRange(m.Location, oldLocation, 6)) - if (Faction.Find(m) != null && - (m.Skills.DetectHidden.Value - 80.0) / 20.0 > Utility.RandomDouble()) - PrivateOverheadLocalizedMessage(m, 1010154, MessageHue, "", ""); // [Faction Trap] - } - - public void PrivateOverheadLocalizedMessage(Mobile to, int number, int hue, string name, string args) - { - NetState ns = to?.NetState; - - ns?.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, hue, 3, number, name, args)); - } - - public virtual bool CheckDecay() - { - TimeSpan decayPeriod = DecayPeriod; - - if (decayPeriod == TimeSpan.MaxValue) - return false; - - if (TimeOfPlacement + decayPeriod < DateTime.UtcNow) - { - Timer.DelayCall(Delete); - return true; - } - - return false; - } - - public virtual void BeginConceal() - { - m_Concealing?.Stop(); - - m_Concealing = Timer.DelayCall(ConcealPeriod, Conceal); - } - - public virtual void Conceal() - { - m_Concealing?.Stop(); - - m_Concealing = null; - - if (!Deleted) - Visible = false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - Faction.WriteReference(writer, Faction); - writer.Write(Placer); - writer.Write(TimeOfPlacement); - - if (Visible) - BeginConceal(); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Faction = Faction.ReadReference(reader); - Placer = reader.ReadMobile(); - TimeOfPlacement = reader.ReadDateTime(); - - if (Visible) - BeginConceal(); - - CheckDecay(); - } - - public override void OnDelete() - { - if (Faction?.Traps.Contains(this) == true) - Faction.Traps.Remove(this); - - base.OnDelete(); - } - - public virtual bool IsEnemy(Mobile mob) - { - if (mob.Hidden && mob.AccessLevel > AccessLevel.Player) - return false; - - if (!mob.Alive || mob.IsDeadBondedPet) - return false; - - Faction faction = Faction.Find(mob, true); - - if (faction == null && mob is BaseFactionGuard guard) - faction = guard.Faction; - - if (faction == null) - return false; - - return faction != Faction; - } - } -} +using System; +using Server.Items; +using Server.Network; + +namespace Server.Factions +{ + public enum AllowedPlacing + { + Everywhere, + + AnyFactionTown, + ControlledFactionTown, + FactionStronghold + } + + public abstract class BaseFactionTrap : BaseTrap + { + private Timer m_Concealing; + + public BaseFactionTrap(Faction f, Mobile m, int itemID) : base(itemID) + { + Visible = false; + + Faction = f; + TimeOfPlacement = DateTime.UtcNow; + Placer = m; + } + + public BaseFactionTrap(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public Faction Faction { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Placer { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime TimeOfPlacement { get; set; } + + public virtual int EffectSound => 0; + + public virtual int SilverFromDisarm => 100; + + public virtual int MessageHue => 0; + + public virtual int AttackMessage => 0; + public virtual int DisarmMessage => 0; + + public virtual AllowedPlacing AllowedPlacing => AllowedPlacing.Everywhere; + + public virtual TimeSpan ConcealPeriod => TimeSpan.FromMinutes(1.0); + + public virtual TimeSpan DecayPeriod + { + get + { + if (Core.AOS) + return TimeSpan.FromDays(1.0); + + return TimeSpan.MaxValue; // no decay + } + } + + public override void OnTrigger(Mobile from) + { + if (!IsEnemy(from)) + return; + + Conceal(); + + DoVisibleEffect(); + Effects.PlaySound(Location, Map, EffectSound); + DoAttackEffect(from); + + var silverToAward = from.Alive ? 20 : 40; + + if (silverToAward > 0 && Placer != null && Faction != null) + { + var victimState = PlayerState.Find(from); + + if (victimState?.CanGiveSilverTo(Placer) == true && victimState.KillPoints > 0) + { + var silverGiven = Faction.AwardSilver(Placer, silverToAward); + + if (silverGiven > 0) + { + // TODO: Get real message + if (from.Alive) + Placer.SendMessage( + "You have earned {0} silver pieces because {1} fell for your trap.", + silverGiven, + from.Name + ); + else + Placer.SendLocalizedMessage( + 1042736, + $"{silverGiven} silver\t{from.Name}" + ); // You have earned ~1_SILVER_AMOUNT~ pieces for vanquishing ~2_PLAYER_NAME~! + } + + victimState.OnGivenSilverTo(Placer); + } + } + + from.LocalOverheadMessage(MessageType.Regular, MessageHue, AttackMessage); + } + + public abstract void DoVisibleEffect(); + public abstract void DoAttackEffect(Mobile m); + + public virtual int IsValidLocation() => IsValidLocation(GetWorldLocation(), Map); + + public virtual int IsValidLocation(Point3D p, Map m) + { + if (m == null) + return 502956; // You cannot place a trap on that. + + if (Core.ML) + foreach (var item in m.GetItemsInRange(p, 0)) + if (item is BaseFactionTrap trap && trap.Faction == Faction) + return 1075263; // There is already a trap belonging to your faction at this location.; + + switch (AllowedPlacing) + { + case AllowedPlacing.FactionStronghold: + { + var region = Region.Find(p, m).GetRegion(); + + if (region != null && region.Faction == Faction) + return 0; + + return 1010355; // This trap can only be placed in your stronghold + } + case AllowedPlacing.AnyFactionTown: + { + var town = Town.FromRegion(Region.Find(p, m)); + + if (town != null) + return 0; + + return 1010356; // This trap can only be placed in a faction town + } + case AllowedPlacing.ControlledFactionTown: + { + var town = Town.FromRegion(Region.Find(p, m)); + + if (town != null && town.Owner == Faction) + return 0; + + return 1010357; // This trap can only be placed in a town your faction controls + } + } + + return 0; + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + base.OnMovement(m, oldLocation); + + if (!CheckDecay() && CheckRange(m.Location, oldLocation, 6)) + if (Faction.Find(m) != null && + (m.Skills.DetectHidden.Value - 80.0) / 20.0 > Utility.RandomDouble()) + PrivateOverheadLocalizedMessage(m, 1010154, MessageHue, "", ""); // [Faction Trap] + } + + public void PrivateOverheadLocalizedMessage(Mobile to, int number, int hue, string name, string args) + { + var ns = to?.NetState; + + ns?.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, hue, 3, number, name, args)); + } + + public virtual bool CheckDecay() + { + var decayPeriod = DecayPeriod; + + if (decayPeriod == TimeSpan.MaxValue) + return false; + + if (TimeOfPlacement + decayPeriod < DateTime.UtcNow) + { + Timer.DelayCall(Delete); + return true; + } + + return false; + } + + public virtual void BeginConceal() + { + m_Concealing?.Stop(); + + m_Concealing = Timer.DelayCall(ConcealPeriod, Conceal); + } + + public virtual void Conceal() + { + m_Concealing?.Stop(); + + m_Concealing = null; + + if (!Deleted) + Visible = false; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + Faction.WriteReference(writer, Faction); + writer.Write(Placer); + writer.Write(TimeOfPlacement); + + if (Visible) + BeginConceal(); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + Faction = Faction.ReadReference(reader); + Placer = reader.ReadMobile(); + TimeOfPlacement = reader.ReadDateTime(); + + if (Visible) + BeginConceal(); + + CheckDecay(); + } + + public override void OnDelete() + { + if (Faction?.Traps.Contains(this) == true) + Faction.Traps.Remove(this); + + base.OnDelete(); + } + + public virtual bool IsEnemy(Mobile mob) + { + if (mob.Hidden && mob.AccessLevel > AccessLevel.Player) + return false; + + if (!mob.Alive || mob.IsDeadBondedPet) + return false; + + var faction = Faction.Find(mob, true); + + if (faction == null && mob is BaseFactionGuard guard) + faction = guard.Faction; + + if (faction == null) + return false; + + return faction != Faction; + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Items/Traps/BaseFactionTrapDeed.cs b/Projects/UOContent/Engines/Factions/Items/Traps/BaseFactionTrapDeed.cs index 817ab05c6..df030b988 100644 --- a/Projects/UOContent/Engines/Factions/Items/Traps/BaseFactionTrapDeed.cs +++ b/Projects/UOContent/Engines/Factions/Items/Traps/BaseFactionTrapDeed.cs @@ -1,116 +1,118 @@ -using System; -using Server.Engines.Craft; -using Server.Items; -using Server.Utilities; - -namespace Server.Factions -{ - public abstract class BaseFactionTrapDeed : Item, ICraftable - { - private Faction m_Faction; - - public BaseFactionTrapDeed(int itemID = 0x14F0) : base(itemID) - { - Weight = 1.0; - LootType = LootType.Blessed; - } - - public BaseFactionTrapDeed(Serial serial) : base(serial) - { - } - - public abstract Type TrapType { get; } - - [CommandProperty(AccessLevel.GameMaster)] - public Faction Faction - { - get => m_Faction; - set - { - m_Faction = value; - - if (m_Faction != null) - Hue = m_Faction.Definition.HuePrimary; - } - } - - public int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, - CraftItem craftItem, int resHue) - { - ItemID = 0x14F0; - Faction = Faction.Find(from); - - return 1; - } - - public virtual BaseFactionTrap Construct(Mobile from) - { - try - { - return ActivatorUtil.CreateInstance(TrapType, m_Faction, from) as BaseFactionTrap; - } - catch - { - return null; - } - } - - public override void OnDoubleClick(Mobile from) - { - Faction faction = Faction.Find(from); - - if (faction == null) - { - from.SendLocalizedMessage(1010353, "", 0x23); // Only faction members may place faction traps - } - else if (faction != m_Faction) - { - from.SendLocalizedMessage(1010354, "", 0x23); // You may only place faction traps created by your faction - } - else if (faction.Traps.Count >= faction.MaximumTraps) - { - from.SendLocalizedMessage(1010358, "", 0x23); // Your faction already has the maximum number of traps placed - } - else - { - BaseFactionTrap trap = Construct(from); - - if (trap == null) - return; - - int message = trap.IsValidLocation(from.Location, from.Map); - - if (message > 0) - { - from.SendLocalizedMessage(message, "", 0x23); - trap.Delete(); - } - else - { - from.SendLocalizedMessage(1010360); // You arm the trap and carefully hide it from view - trap.MoveToWorld(from.Location, from.Map); - faction.Traps.Add(trap); - Delete(); - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - Faction.WriteReference(writer, m_Faction); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Faction = Faction.ReadReference(reader); - } - } -} +using System; +using Server.Engines.Craft; +using Server.Items; +using Server.Utilities; + +namespace Server.Factions +{ + public abstract class BaseFactionTrapDeed : Item, ICraftable + { + private Faction m_Faction; + + public BaseFactionTrapDeed(int itemID = 0x14F0) : base(itemID) + { + Weight = 1.0; + LootType = LootType.Blessed; + } + + public BaseFactionTrapDeed(Serial serial) : base(serial) + { + } + + public abstract Type TrapType { get; } + + [CommandProperty(AccessLevel.GameMaster)] + public Faction Faction + { + get => m_Faction; + set + { + m_Faction = value; + + if (m_Faction != null) + Hue = m_Faction.Definition.HuePrimary; + } + } + + public int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, + CraftItem craftItem, int resHue + ) + { + ItemID = 0x14F0; + Faction = Faction.Find(from); + + return 1; + } + + public virtual BaseFactionTrap Construct(Mobile from) + { + try + { + return ActivatorUtil.CreateInstance(TrapType, m_Faction, from) as BaseFactionTrap; + } + catch + { + return null; + } + } + + public override void OnDoubleClick(Mobile from) + { + var faction = Faction.Find(from); + + if (faction == null) + { + from.SendLocalizedMessage(1010353, "", 0x23); // Only faction members may place faction traps + } + else if (faction != m_Faction) + { + from.SendLocalizedMessage(1010354, "", 0x23); // You may only place faction traps created by your faction + } + else if (faction.Traps.Count >= faction.MaximumTraps) + { + from.SendLocalizedMessage(1010358, "", 0x23); // Your faction already has the maximum number of traps placed + } + else + { + var trap = Construct(from); + + if (trap == null) + return; + + var message = trap.IsValidLocation(from.Location, from.Map); + + if (message > 0) + { + from.SendLocalizedMessage(message, "", 0x23); + trap.Delete(); + } + else + { + from.SendLocalizedMessage(1010360); // You arm the trap and carefully hide it from view + trap.MoveToWorld(from.Location, from.Map); + faction.Traps.Add(trap); + Delete(); + } + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + Faction.WriteReference(writer, m_Faction); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Faction = Faction.ReadReference(reader); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Items/Traps/FactionExplosionTrap.cs b/Projects/UOContent/Engines/Factions/Items/Traps/FactionExplosionTrap.cs index c7cf74841..ae822844d 100644 --- a/Projects/UOContent/Engines/Factions/Items/Traps/FactionExplosionTrap.cs +++ b/Projects/UOContent/Engines/Factions/Items/Traps/FactionExplosionTrap.cs @@ -1,76 +1,76 @@ -using System; - -namespace Server.Factions -{ - public class FactionExplosionTrap : BaseFactionTrap - { - [Constructible] - public FactionExplosionTrap(Faction f = null, Mobile m = null) : base(f, m, 0x11C1) - { - } - - public FactionExplosionTrap(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1044599; // faction explosion trap - - public override int AttackMessage => 1010543; // You are enveloped in an explosion of fire! - public override int DisarmMessage => 1010539; // You carefully remove the pressure trigger and disable the trap. - public override int EffectSound => 0x307; - public override int MessageHue => 0x78; - - public override AllowedPlacing AllowedPlacing => AllowedPlacing.AnyFactionTown; - - public override void DoVisibleEffect() - { - Effects.SendLocationEffect(GetWorldLocation(), Map, 0x36BD, 15, 10); - } - - public override void DoAttackEffect(Mobile m) - { - m.Damage(Utility.Dice(6, 10, 40), m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class FactionExplosionTrapDeed : BaseFactionTrapDeed - { - public FactionExplosionTrapDeed() : base(0x36D2) - { - } - - public FactionExplosionTrapDeed(Serial serial) : base(serial) - { - } - - public override Type TrapType => typeof(FactionExplosionTrap); - public override int LabelNumber => 1044603; // faction explosion trap deed - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} +using System; + +namespace Server.Factions +{ + public class FactionExplosionTrap : BaseFactionTrap + { + [Constructible] + public FactionExplosionTrap(Faction f = null, Mobile m = null) : base(f, m, 0x11C1) + { + } + + public FactionExplosionTrap(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1044599; // faction explosion trap + + public override int AttackMessage => 1010543; // You are enveloped in an explosion of fire! + public override int DisarmMessage => 1010539; // You carefully remove the pressure trigger and disable the trap. + public override int EffectSound => 0x307; + public override int MessageHue => 0x78; + + public override AllowedPlacing AllowedPlacing => AllowedPlacing.AnyFactionTown; + + public override void DoVisibleEffect() + { + Effects.SendLocationEffect(GetWorldLocation(), Map, 0x36BD, 15, 10); + } + + public override void DoAttackEffect(Mobile m) + { + m.Damage(Utility.Dice(6, 10, 40), m); + } + + 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 class FactionExplosionTrapDeed : BaseFactionTrapDeed + { + public FactionExplosionTrapDeed() : base(0x36D2) + { + } + + public FactionExplosionTrapDeed(Serial serial) : base(serial) + { + } + + public override Type TrapType => typeof(FactionExplosionTrap); + public override int LabelNumber => 1044603; // faction explosion trap deed + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Items/Traps/FactionGasTrap.cs b/Projects/UOContent/Engines/Factions/Items/Traps/FactionGasTrap.cs index f7f343f97..cc2e70fb0 100644 --- a/Projects/UOContent/Engines/Factions/Items/Traps/FactionGasTrap.cs +++ b/Projects/UOContent/Engines/Factions/Items/Traps/FactionGasTrap.cs @@ -1,76 +1,76 @@ -using System; - -namespace Server.Factions -{ - public class FactionGasTrap : BaseFactionTrap - { - [Constructible] - public FactionGasTrap(Faction f = null, Mobile m = null) : base(f, m, 0x113C) - { - } - - public FactionGasTrap(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1044598; // faction gas trap - - public override int AttackMessage => 1010542; // A noxious green cloud of poison gas envelops you! - public override int DisarmMessage => 502376; // The poison leaks harmlessly away due to your deft touch. - public override int EffectSound => 0x230; - public override int MessageHue => 0x44; - - public override AllowedPlacing AllowedPlacing => AllowedPlacing.FactionStronghold; - - public override void DoVisibleEffect() - { - Effects.SendLocationEffect(Location, Map, 0x3709, 28, 10, 0x1D3, 5); - } - - public override void DoAttackEffect(Mobile m) - { - m.ApplyPoison(m, Poison.Lethal); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class FactionGasTrapDeed : BaseFactionTrapDeed - { - public FactionGasTrapDeed() : base(0x11AB) - { - } - - public FactionGasTrapDeed(Serial serial) : base(serial) - { - } - - public override Type TrapType => typeof(FactionGasTrap); - public override int LabelNumber => 1044602; // faction gas trap deed - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} +using System; + +namespace Server.Factions +{ + public class FactionGasTrap : BaseFactionTrap + { + [Constructible] + public FactionGasTrap(Faction f = null, Mobile m = null) : base(f, m, 0x113C) + { + } + + public FactionGasTrap(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1044598; // faction gas trap + + public override int AttackMessage => 1010542; // A noxious green cloud of poison gas envelops you! + public override int DisarmMessage => 502376; // The poison leaks harmlessly away due to your deft touch. + public override int EffectSound => 0x230; + public override int MessageHue => 0x44; + + public override AllowedPlacing AllowedPlacing => AllowedPlacing.FactionStronghold; + + public override void DoVisibleEffect() + { + Effects.SendLocationEffect(Location, Map, 0x3709, 28, 10, 0x1D3, 5); + } + + public override void DoAttackEffect(Mobile m) + { + m.ApplyPoison(m, Poison.Lethal); + } + + 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 class FactionGasTrapDeed : BaseFactionTrapDeed + { + public FactionGasTrapDeed() : base(0x11AB) + { + } + + public FactionGasTrapDeed(Serial serial) : base(serial) + { + } + + public override Type TrapType => typeof(FactionGasTrap); + public override int LabelNumber => 1044602; // faction gas trap deed + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Items/Traps/FactionSawTrap.cs b/Projects/UOContent/Engines/Factions/Items/Traps/FactionSawTrap.cs index 472a9255d..6847d59f0 100644 --- a/Projects/UOContent/Engines/Factions/Items/Traps/FactionSawTrap.cs +++ b/Projects/UOContent/Engines/Factions/Items/Traps/FactionSawTrap.cs @@ -1,72 +1,72 @@ -using System; - -namespace Server.Factions -{ - public class FactionSawTrap : BaseFactionTrap - { - [Constructible] - public FactionSawTrap(Faction f = null, Mobile m = null) : base(f, m, 0x11AC) - { - } - - public override int LabelNumber => 1041047; // faction saw trap - - public override int AttackMessage => 1010544; // The blade cuts deep into your skin! - public override int DisarmMessage => 1010540; // You carefully dismantle the saw mechanism and disable the trap. - public override int EffectSound => 0x218; - public override int MessageHue => 0x5A; - - public override AllowedPlacing AllowedPlacing => AllowedPlacing.ControlledFactionTown; - - public override void DoVisibleEffect() - { - Effects.SendLocationEffect(Location, Map, 0x11AD, 25, 10); - } - - public override void DoAttackEffect(Mobile m) - { - m.Damage(Utility.Dice(6, 10, 40), m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class FactionSawTrapDeed : BaseFactionTrapDeed - { - public FactionSawTrapDeed() : base(0x1107) - { - } - - public FactionSawTrapDeed(Serial serial) : base(serial) - { - } - - public override Type TrapType => typeof(FactionSawTrap); - public override int LabelNumber => 1044604; // faction saw trap deed - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} +using System; + +namespace Server.Factions +{ + public class FactionSawTrap : BaseFactionTrap + { + [Constructible] + public FactionSawTrap(Faction f = null, Mobile m = null) : base(f, m, 0x11AC) + { + } + + public override int LabelNumber => 1041047; // faction saw trap + + public override int AttackMessage => 1010544; // The blade cuts deep into your skin! + public override int DisarmMessage => 1010540; // You carefully dismantle the saw mechanism and disable the trap. + public override int EffectSound => 0x218; + public override int MessageHue => 0x5A; + + public override AllowedPlacing AllowedPlacing => AllowedPlacing.ControlledFactionTown; + + public override void DoVisibleEffect() + { + Effects.SendLocationEffect(Location, Map, 0x11AD, 25, 10); + } + + public override void DoAttackEffect(Mobile m) + { + m.Damage(Utility.Dice(6, 10, 40), m); + } + + 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 class FactionSawTrapDeed : BaseFactionTrapDeed + { + public FactionSawTrapDeed() : base(0x1107) + { + } + + public FactionSawTrapDeed(Serial serial) : base(serial) + { + } + + public override Type TrapType => typeof(FactionSawTrap); + public override int LabelNumber => 1044604; // faction saw trap deed + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Items/Traps/FactionSpikeTrap.cs b/Projects/UOContent/Engines/Factions/Items/Traps/FactionSpikeTrap.cs index 90c7421b4..b861ee738 100644 --- a/Projects/UOContent/Engines/Factions/Items/Traps/FactionSpikeTrap.cs +++ b/Projects/UOContent/Engines/Factions/Items/Traps/FactionSpikeTrap.cs @@ -1,79 +1,79 @@ -using System; - -namespace Server.Factions -{ - public class FactionSpikeTrap : BaseFactionTrap - { - [Constructible] - public FactionSpikeTrap(Faction f = null, Mobile m = null) : base(f, m, 0x11A0) - { - } - - public FactionSpikeTrap(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1044601; // faction spike trap - - public override int AttackMessage => 1010545; // Large spikes in the ground spring up piercing your skin! - - public override int DisarmMessage => - 1010541; // You carefully dismantle the trigger on the spikes and disable the trap. - - public override int EffectSound => 0x22E; - public override int MessageHue => 0x5A; - - public override AllowedPlacing AllowedPlacing => AllowedPlacing.ControlledFactionTown; - - public override void DoVisibleEffect() - { - Effects.SendLocationEffect(Location, Map, 0x11A4, 12, 6); - } - - public override void DoAttackEffect(Mobile m) - { - m.Damage(Utility.Dice(6, 10, 40), m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class FactionSpikeTrapDeed : BaseFactionTrapDeed - { - public FactionSpikeTrapDeed() : base(0x11A5) - { - } - - public FactionSpikeTrapDeed(Serial serial) : base(serial) - { - } - - public override Type TrapType => typeof(FactionSpikeTrap); - public override int LabelNumber => 1044605; // faction spike trap deed - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} +using System; + +namespace Server.Factions +{ + public class FactionSpikeTrap : BaseFactionTrap + { + [Constructible] + public FactionSpikeTrap(Faction f = null, Mobile m = null) : base(f, m, 0x11A0) + { + } + + public FactionSpikeTrap(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1044601; // faction spike trap + + public override int AttackMessage => 1010545; // Large spikes in the ground spring up piercing your skin! + + public override int DisarmMessage => + 1010541; // You carefully dismantle the trigger on the spikes and disable the trap. + + public override int EffectSound => 0x22E; + public override int MessageHue => 0x5A; + + public override AllowedPlacing AllowedPlacing => AllowedPlacing.ControlledFactionTown; + + public override void DoVisibleEffect() + { + Effects.SendLocationEffect(Location, Map, 0x11A4, 12, 6); + } + + public override void DoAttackEffect(Mobile m) + { + m.Damage(Utility.Dice(6, 10, 40), m); + } + + 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 class FactionSpikeTrapDeed : BaseFactionTrapDeed + { + public FactionSpikeTrapDeed() : base(0x11A5) + { + } + + public FactionSpikeTrapDeed(Serial serial) : base(serial) + { + } + + public override Type TrapType => typeof(FactionSpikeTrap); + public override int LabelNumber => 1044605; // faction spike trap deed + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Items/Traps/FactionTrapRemovalKit.cs b/Projects/UOContent/Engines/Factions/Items/Traps/FactionTrapRemovalKit.cs index 89ef35787..78dd3c488 100644 --- a/Projects/UOContent/Engines/Factions/Items/Traps/FactionTrapRemovalKit.cs +++ b/Projects/UOContent/Engines/Factions/Items/Traps/FactionTrapRemovalKit.cs @@ -1,71 +1,71 @@ -namespace Server.Factions -{ - public class FactionTrapRemovalKit : Item - { - [Constructible] - public FactionTrapRemovalKit() : base(7867) - { - LootType = LootType.Blessed; - Charges = 25; - } - - public FactionTrapRemovalKit(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Charges { get; set; } - - public override int LabelNumber => 1041508; // a faction trap removal kit - - public void ConsumeCharge(Mobile consumer) - { - --Charges; - - if (Charges <= 0) - { - Delete(); - - consumer?.SendLocalizedMessage(1042531); // You have used all of the parts in your trap removal kit. - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - // NOTE: OSI does not list uses remaining; intentional difference - list.Add(1060584, Charges.ToString()); // uses remaining: ~1_val~ - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.WriteEncodedInt(Charges); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - Charges = reader.ReadEncodedInt(); - break; - } - case 0: - { - Charges = 25; - break; - } - } - } - } -} \ No newline at end of file +namespace Server.Factions +{ + public class FactionTrapRemovalKit : Item + { + [Constructible] + public FactionTrapRemovalKit() : base(7867) + { + LootType = LootType.Blessed; + Charges = 25; + } + + public FactionTrapRemovalKit(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Charges { get; set; } + + public override int LabelNumber => 1041508; // a faction trap removal kit + + public void ConsumeCharge(Mobile consumer) + { + --Charges; + + if (Charges <= 0) + { + Delete(); + + consumer?.SendLocalizedMessage(1042531); // You have used all of the parts in your trap removal kit. + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + // NOTE: OSI does not list uses remaining; intentional difference + list.Add(1060584, Charges.ToString()); // uses remaining: ~1_val~ + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.WriteEncodedInt(Charges); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + Charges = reader.ReadEncodedInt(); + break; + } + case 0: + { + Charges = 25; + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Mobiles/FactionWarHorse.cs b/Projects/UOContent/Engines/Factions/Mobiles/FactionWarHorse.cs index 33055cf1e..d32319ada 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/FactionWarHorse.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/FactionWarHorse.cs @@ -1,108 +1,109 @@ -using Server.Mobiles; - -namespace Server.Factions -{ - public class FactionWarHorse : BaseMount - { - public const int SilverPrice = 500; - public const int GoldPrice = 3000; - private Faction m_Faction; - - [Constructible] - public FactionWarHorse(Faction faction = null) - : base("a war horse", 0xE2, 0x3EA0, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) - { - BaseSoundID = 0xA8; - - SetStr(400); - SetDex(125); - SetInt(51, 55); - - SetHits(240); - SetMana(0); - - SetDamage(5, 8); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 40, 50); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 30, 40); - - SetSkill(SkillName.MagicResist, 25.1, 30.0); - SetSkill(SkillName.Tactics, 29.3, 44.0); - SetSkill(SkillName.Wrestling, 29.3, 44.0); - - Fame = 300; - Karma = 300; - - Tamable = true; - ControlSlots = 1; - - Faction = faction; - } - - public FactionWarHorse(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a war horse corpse"; - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public Faction Faction - { - get => m_Faction; - set - { - m_Faction = value; - - Body = m_Faction?.Definition.WarHorseBody ?? 0xE2; - ItemID = m_Faction?.Definition.WarHorseItem ?? 0x3EA0; - } - } - - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - - public override void OnDoubleClick(Mobile from) - { - PlayerState pl = PlayerState.Find(from); - - if (pl == null) - from.SendLocalizedMessage(1010366); // You cannot mount a faction war horse! - else if (pl.Faction != Faction) - from.SendLocalizedMessage(1010367); // You cannot ride an opposing faction's war horse! - else if (pl.Rank.Rank < 2) - from.SendLocalizedMessage( - 1010368); // You must achieve a faction rank of at least two before riding a war horse! - else - base.OnDoubleClick(from); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - Faction.WriteReference(writer, m_Faction); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Faction = Faction.ReadReference(reader); - break; - } - } - } - } -} +using Server.Mobiles; + +namespace Server.Factions +{ + public class FactionWarHorse : BaseMount + { + public const int SilverPrice = 500; + public const int GoldPrice = 3000; + private Faction m_Faction; + + [Constructible] + public FactionWarHorse(Faction faction = null) + : base("a war horse", 0xE2, 0x3EA0, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + BaseSoundID = 0xA8; + + SetStr(400); + SetDex(125); + SetInt(51, 55); + + SetHits(240); + SetMana(0); + + SetDamage(5, 8); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 40, 50); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 30, 40); + + SetSkill(SkillName.MagicResist, 25.1, 30.0); + SetSkill(SkillName.Tactics, 29.3, 44.0); + SetSkill(SkillName.Wrestling, 29.3, 44.0); + + Fame = 300; + Karma = 300; + + Tamable = true; + ControlSlots = 1; + + Faction = faction; + } + + public FactionWarHorse(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a war horse corpse"; + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public Faction Faction + { + get => m_Faction; + set + { + m_Faction = value; + + Body = m_Faction?.Definition.WarHorseBody ?? 0xE2; + ItemID = m_Faction?.Definition.WarHorseItem ?? 0x3EA0; + } + } + + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + + public override void OnDoubleClick(Mobile from) + { + var pl = PlayerState.Find(from); + + if (pl == null) + from.SendLocalizedMessage(1010366); // You cannot mount a faction war horse! + else if (pl.Faction != Faction) + from.SendLocalizedMessage(1010367); // You cannot ride an opposing faction's war horse! + else if (pl.Rank.Rank < 2) + from.SendLocalizedMessage( + 1010368 + ); // You must achieve a faction rank of at least two before riding a war horse! + else + base.OnDoubleClick(from); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + Faction.WriteReference(writer, m_Faction); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Faction = Faction.ReadReference(reader); + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Mobiles/Guards/BaseFactionGuard.cs b/Projects/UOContent/Engines/Factions/Mobiles/Guards/BaseFactionGuard.cs index 786cf52f6..9ae3e89e8 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/Guards/BaseFactionGuard.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/Guards/BaseFactionGuard.cs @@ -1,498 +1,497 @@ -using System; -using System.Collections.Generic; -using Server.Factions.AI; -using Server.Items; -using Server.Mobiles; -using Server.Network; - -namespace Server.Factions -{ - public abstract class BaseFactionGuard : BaseCreature - { - private const int ListenRange = 12; - - private static readonly Type[] m_StrongPotions = - { - typeof(GreaterHealPotion), typeof(GreaterHealPotion), typeof(GreaterHealPotion), - typeof(GreaterCurePotion), typeof(GreaterCurePotion), typeof(GreaterCurePotion), - typeof(GreaterStrengthPotion), typeof(GreaterStrengthPotion), - typeof(GreaterAgilityPotion), typeof(GreaterAgilityPotion), - typeof(TotalRefreshPotion), typeof(TotalRefreshPotion), - typeof(GreaterExplosionPotion) - }; - - private static readonly Type[] m_WeakPotions = - { - typeof(HealPotion), typeof(HealPotion), typeof(HealPotion), - typeof(CurePotion), typeof(CurePotion), typeof(CurePotion), - typeof(StrengthPotion), typeof(StrengthPotion), - typeof(AgilityPotion), typeof(AgilityPotion), - typeof(RefreshPotion), typeof(RefreshPotion), - typeof(ExplosionPotion) - }; - - private Faction m_Faction; - - private DateTime m_OrdersEnd; - private Town m_Town; - - public BaseFactionGuard(string title) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) - { - Orders = new Orders(this); - Title = title; - - RangeHome = 6; - } - - public BaseFactionGuard(Serial serial) : base(serial) - { - } - - public override bool BardImmune => true; - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public Faction Faction - { - get => m_Faction; - set - { - Unregister(); - m_Faction = value; - Register(); - } - } - - public Orders Orders { get; private set; } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public Town Town - { - get => m_Town; - set - { - Unregister(); - m_Town = value; - Register(); - } - } - - public abstract GuardAI GuardAI { get; } - - protected override BaseAI ForcedAI => new FactionGuardAI(this); - - public override TimeSpan ReacquireDelay => TimeSpan.FromSeconds(2.0); - - public override bool ClickTitle => false; - - public void Register() - { - if (m_Town != null && m_Faction != null) - m_Town.RegisterGuard(this); - } - - public void Unregister() - { - m_Town?.UnregisterGuard(this); - } - - public override bool IsEnemy(Mobile m) - { - Faction ourFaction = m_Faction; - Faction theirFaction = Faction.Find(m); - - if (theirFaction == null && m is BaseFactionGuard guard) - theirFaction = guard.Faction; - - if (ourFaction != null && theirFaction != null && ourFaction != theirFaction) - { - ReactionType reactionType = Orders.GetReaction(theirFaction).Type; - - if (reactionType == ReactionType.Attack) - return true; - - List list = m.Aggressed; - - for (int i = 0; i < list.Count; ++i) - { - AggressorInfo ai = list[i]; - - if (ai.Defender is BaseFactionGuard bf && bf.Faction == ourFaction) - return true; - } - } - - return false; - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (m.Player && m.Alive && InRange(m, 10) && !InRange(oldLocation, 10) && InLOS(m) && - Orders.GetReaction(Faction.Find(m)).Type == ReactionType.Warn) - { - Direction = GetDirectionTo(m); - - var warning = Utility.Random(6) switch - { - 0 => "I warn you, {0}, you would do well to leave this area before someone shows you the world of gray.", - 1 => "It would be wise to leave this area, {0}, lest your head become my commanders' trophy.", - 2 => "You are bold, {0}, for one of the meager {1}. Leave now, lest you be taught the taste of dirt.", - 3 => "Your presence here is an insult, {0}. Be gone now, knave.", - 4 => "Dost thou wish to be hung by your toes, {0}? Nay? Then come no closer.", - _ => "Hey, {0}. Yeah, you. Get out of here before I beat you with a stick." // 5 - }; - - Faction faction = Faction.Find(m); - - Say(warning, m.Name, faction == null ? "civilians" : faction.Definition.FriendlyName); - } - } - - public override bool HandlesOnSpeech(Mobile from) - { - if (InRange(from, ListenRange)) - return true; - - return base.HandlesOnSpeech(from); - } - - private void ChangeReaction(Faction faction, ReactionType type) - { - if (faction == null) - { - switch (type) - { - case ReactionType.Ignore: - Say(1005179); - break; // Civilians will now be ignored. - case ReactionType.Warn: - Say(1005180); - break; // Civilians will now be warned of their impending deaths. - case ReactionType.Attack: return; - } - } - else - { - var def = type switch - { - ReactionType.Ignore => faction.Definition.GuardIgnore, - ReactionType.Warn => faction.Definition.GuardWarn, - _ => faction.Definition.GuardAttack // ReactionType.Attack - }; - - if (def != null && def.Number > 0) - Say(def.Number); - else if (def?.String != null) - Say(def.String); - } - - Orders.SetReaction(faction, type); - } - - private bool WasNamed(string speech) - { - string name = Name; - - return name != null && Insensitive.StartsWith(speech, name); - } - - public override void OnSpeech(SpeechEventArgs e) - { - base.OnSpeech(e); - - Mobile from = e.Mobile; - - if (!e.Handled && InRange(from, ListenRange) && from.Alive) - { - if (e.HasKeyword(0xE6) && (Insensitive.Equals(e.Speech, "orders") || WasNamed(e.Speech))) // *orders* - { - if (m_Town?.IsSheriff(from) != true) - { - Say(1042189); // I don't work for you! - } - else if (Town.FromRegion(Region) == m_Town) - { - Say(1042180); // Your orders, sire? - m_OrdersEnd = DateTime.UtcNow + TimeSpan.FromSeconds(10.0); - } - } - else if (DateTime.UtcNow < m_OrdersEnd) - { - if (m_Town?.IsSheriff(from) != true || Town.FromRegion(Region) != m_Town) - return; - - m_OrdersEnd = DateTime.UtcNow + TimeSpan.FromSeconds(10.0); - - bool understood = true; - ReactionType newType = 0; - - if (Insensitive.Contains(e.Speech, "attack")) - newType = ReactionType.Attack; - else if (Insensitive.Contains(e.Speech, "warn")) - newType = ReactionType.Warn; - else if (Insensitive.Contains(e.Speech, "ignore")) - newType = ReactionType.Ignore; - else - understood = false; - - if (understood) - { - understood = false; - - if (Insensitive.Contains(e.Speech, "civil")) - { - ChangeReaction(null, newType); - understood = true; - } - - List factions = Faction.Factions; - - for (int i = 0; i < factions.Count; ++i) - { - Faction faction = factions[i]; - - if (faction != m_Faction && Insensitive.Contains(e.Speech, faction.Definition.Keyword)) - { - ChangeReaction(faction, newType); - understood = true; - } - } - } - else if (Insensitive.Contains(e.Speech, "patrol")) - { - Home = Location; - RangeHome = 6; - Combatant = null; - Orders.Movement = MovementType.Patrol; - Say(1005146); // This spot looks like it needs protection! I shall guard it with my life. - understood = true; - } - else if (Insensitive.Contains(e.Speech, "follow")) - { - Home = Location; - RangeHome = 6; - Combatant = null; - Orders.Follow = from; - Orders.Movement = MovementType.Follow; - Say(1005144); // Yes, Sire. - understood = true; - } - - if (!understood) - Say(1042183); // I'm sorry, I don't understand your orders... - } - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_Faction != null && Map == Faction.Facet) - list.Add(1060846, m_Faction.Definition.PropName); // Guard: ~1_val~ - } - - public override void OnSingleClick(Mobile from) - { - if (m_Faction != null && Map == Faction.Facet) - { - string text = $"(Guard, {m_Faction.Definition.FriendlyName})"; - - int hue = Faction.Find(from) == m_Faction ? 98 : 38; - - PrivateOverheadMessage(MessageType.Label, hue, true, text, from.NetState); - } - - base.OnSingleClick(from); - } - - public virtual void GenerateRandomHair() - { - Utility.AssignRandomHair(this); - Utility.AssignRandomFacialHair(this, HairHue); - } - - public void PackStrongPotions(int min, int max) - { - PackStrongPotions(Utility.RandomMinMax(min, max)); - } - - public void PackStrongPotions(int count) - { - for (int i = 0; i < count; ++i) - PackStrongPotion(); - } - - public void PackStrongPotion() - { - PackItem(Loot.Construct(m_StrongPotions)); - } - - public void PackWeakPotions(int min, int max) - { - PackWeakPotions(Utility.RandomMinMax(min, max)); - } - - public void PackWeakPotions(int count) - { - for (int i = 0; i < count; ++i) - PackWeakPotion(); - } - - public void PackWeakPotion() - { - PackItem(Loot.Construct(m_WeakPotions)); - } - - public Item Immovable(Item item) - { - item.Movable = false; - return item; - } - - public Item Newbied(Item item) - { - item.LootType = LootType.Newbied; - return item; - } - - public Item Rehued(Item item, int hue) - { - item.Hue = hue; - return item; - } - - public Item Layered(Item item, Layer layer) - { - item.Layer = layer; - return item; - } - - public Item Resourced(BaseWeapon weapon, CraftResource resource) - { - weapon.Resource = resource; - return weapon; - } - - public Item Resourced(BaseArmor armor, CraftResource resource) - { - armor.Resource = resource; - return armor; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - Unregister(); - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - c.Delete(); - } - - public virtual void GenerateBody(bool isFemale, bool randomHair) - { - Hue = Race.Human.RandomSkinHue(); - - if (isFemale) - { - Female = true; - Body = 401; - Name = NameList.RandomName("female"); - } - else - { - Female = false; - Body = 400; - Name = NameList.RandomName("male"); - } - - if (randomHair) - GenerateRandomHair(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - Faction.WriteReference(writer, m_Faction); - Town.WriteReference(writer, m_Town); - - Orders.Serialize(writer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Faction = Faction.ReadReference(reader); - m_Town = Town.ReadReference(reader); - Orders = new Orders(this, reader); - - Timer.DelayCall(Register); - } - } - - public class VirtualMount : IMount - { - private readonly VirtualMountItem m_Item; - - public VirtualMount(VirtualMountItem item) => m_Item = item; - - Mobile IMount.Rider - { - get => m_Item.Rider; - set { } - } - - public virtual void OnRiderDamaged(int amount, Mobile from, bool willKill) - { - } - } - - public class VirtualMountItem : Item, IMountItem - { - private readonly VirtualMount m_Mount; - - public VirtualMountItem(Mobile mob) : base(0x3EA0) - { - Layer = Layer.Mount; - - Rider = mob; - m_Mount = new VirtualMount(this); - } - - public VirtualMountItem(Serial serial) : base(serial) => m_Mount = new VirtualMount(this); - - public Mobile Rider { get; private set; } - - public IMount Mount => m_Mount; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(Rider); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Rider = reader.ReadMobile(); - - if (Rider == null) - Delete(); - } - } -} +using System; +using Server.Factions.AI; +using Server.Items; +using Server.Mobiles; +using Server.Network; + +namespace Server.Factions +{ + public abstract class BaseFactionGuard : BaseCreature + { + private const int ListenRange = 12; + + private static readonly Type[] m_StrongPotions = + { + typeof(GreaterHealPotion), typeof(GreaterHealPotion), typeof(GreaterHealPotion), + typeof(GreaterCurePotion), typeof(GreaterCurePotion), typeof(GreaterCurePotion), + typeof(GreaterStrengthPotion), typeof(GreaterStrengthPotion), + typeof(GreaterAgilityPotion), typeof(GreaterAgilityPotion), + typeof(TotalRefreshPotion), typeof(TotalRefreshPotion), + typeof(GreaterExplosionPotion) + }; + + private static readonly Type[] m_WeakPotions = + { + typeof(HealPotion), typeof(HealPotion), typeof(HealPotion), + typeof(CurePotion), typeof(CurePotion), typeof(CurePotion), + typeof(StrengthPotion), typeof(StrengthPotion), + typeof(AgilityPotion), typeof(AgilityPotion), + typeof(RefreshPotion), typeof(RefreshPotion), + typeof(ExplosionPotion) + }; + + private Faction m_Faction; + + private DateTime m_OrdersEnd; + private Town m_Town; + + public BaseFactionGuard(string title) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Orders = new Orders(this); + Title = title; + + RangeHome = 6; + } + + public BaseFactionGuard(Serial serial) : base(serial) + { + } + + public override bool BardImmune => true; + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public Faction Faction + { + get => m_Faction; + set + { + Unregister(); + m_Faction = value; + Register(); + } + } + + public Orders Orders { get; private set; } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public Town Town + { + get => m_Town; + set + { + Unregister(); + m_Town = value; + Register(); + } + } + + public abstract GuardAI GuardAI { get; } + + protected override BaseAI ForcedAI => new FactionGuardAI(this); + + public override TimeSpan ReacquireDelay => TimeSpan.FromSeconds(2.0); + + public override bool ClickTitle => false; + + public void Register() + { + if (m_Town != null && m_Faction != null) + m_Town.RegisterGuard(this); + } + + public void Unregister() + { + m_Town?.UnregisterGuard(this); + } + + public override bool IsEnemy(Mobile m) + { + var ourFaction = m_Faction; + var theirFaction = Faction.Find(m); + + if (theirFaction == null && m is BaseFactionGuard guard) + theirFaction = guard.Faction; + + if (ourFaction != null && theirFaction != null && ourFaction != theirFaction) + { + var reactionType = Orders.GetReaction(theirFaction).Type; + + if (reactionType == ReactionType.Attack) + return true; + + var list = m.Aggressed; + + for (var i = 0; i < list.Count; ++i) + { + var ai = list[i]; + + if (ai.Defender is BaseFactionGuard bf && bf.Faction == ourFaction) + return true; + } + } + + return false; + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (m.Player && m.Alive && InRange(m, 10) && !InRange(oldLocation, 10) && InLOS(m) && + Orders.GetReaction(Faction.Find(m)).Type == ReactionType.Warn) + { + Direction = GetDirectionTo(m); + + var warning = Utility.Random(6) switch + { + 0 => "I warn you, {0}, you would do well to leave this area before someone shows you the world of gray.", + 1 => "It would be wise to leave this area, {0}, lest your head become my commanders' trophy.", + 2 => "You are bold, {0}, for one of the meager {1}. Leave now, lest you be taught the taste of dirt.", + 3 => "Your presence here is an insult, {0}. Be gone now, knave.", + 4 => "Dost thou wish to be hung by your toes, {0}? Nay? Then come no closer.", + _ => "Hey, {0}. Yeah, you. Get out of here before I beat you with a stick." // 5 + }; + + var faction = Faction.Find(m); + + Say(warning, m.Name, faction == null ? "civilians" : faction.Definition.FriendlyName); + } + } + + public override bool HandlesOnSpeech(Mobile from) + { + if (InRange(from, ListenRange)) + return true; + + return base.HandlesOnSpeech(from); + } + + private void ChangeReaction(Faction faction, ReactionType type) + { + if (faction == null) + { + switch (type) + { + case ReactionType.Ignore: + Say(1005179); + break; // Civilians will now be ignored. + case ReactionType.Warn: + Say(1005180); + break; // Civilians will now be warned of their impending deaths. + case ReactionType.Attack: return; + } + } + else + { + var def = type switch + { + ReactionType.Ignore => faction.Definition.GuardIgnore, + ReactionType.Warn => faction.Definition.GuardWarn, + _ => faction.Definition.GuardAttack // ReactionType.Attack + }; + + if (def != null && def.Number > 0) + Say(def.Number); + else if (def?.String != null) + Say(def.String); + } + + Orders.SetReaction(faction, type); + } + + private bool WasNamed(string speech) + { + var name = Name; + + return name != null && Insensitive.StartsWith(speech, name); + } + + public override void OnSpeech(SpeechEventArgs e) + { + base.OnSpeech(e); + + var from = e.Mobile; + + if (!e.Handled && InRange(from, ListenRange) && from.Alive) + { + if (e.HasKeyword(0xE6) && (Insensitive.Equals(e.Speech, "orders") || WasNamed(e.Speech))) // *orders* + { + if (m_Town?.IsSheriff(from) != true) + { + Say(1042189); // I don't work for you! + } + else if (Town.FromRegion(Region) == m_Town) + { + Say(1042180); // Your orders, sire? + m_OrdersEnd = DateTime.UtcNow + TimeSpan.FromSeconds(10.0); + } + } + else if (DateTime.UtcNow < m_OrdersEnd) + { + if (m_Town?.IsSheriff(from) != true || Town.FromRegion(Region) != m_Town) + return; + + m_OrdersEnd = DateTime.UtcNow + TimeSpan.FromSeconds(10.0); + + var understood = true; + ReactionType newType = 0; + + if (Insensitive.Contains(e.Speech, "attack")) + newType = ReactionType.Attack; + else if (Insensitive.Contains(e.Speech, "warn")) + newType = ReactionType.Warn; + else if (Insensitive.Contains(e.Speech, "ignore")) + newType = ReactionType.Ignore; + else + understood = false; + + if (understood) + { + understood = false; + + if (Insensitive.Contains(e.Speech, "civil")) + { + ChangeReaction(null, newType); + understood = true; + } + + var factions = Faction.Factions; + + for (var i = 0; i < factions.Count; ++i) + { + var faction = factions[i]; + + if (faction != m_Faction && Insensitive.Contains(e.Speech, faction.Definition.Keyword)) + { + ChangeReaction(faction, newType); + understood = true; + } + } + } + else if (Insensitive.Contains(e.Speech, "patrol")) + { + Home = Location; + RangeHome = 6; + Combatant = null; + Orders.Movement = MovementType.Patrol; + Say(1005146); // This spot looks like it needs protection! I shall guard it with my life. + understood = true; + } + else if (Insensitive.Contains(e.Speech, "follow")) + { + Home = Location; + RangeHome = 6; + Combatant = null; + Orders.Follow = from; + Orders.Movement = MovementType.Follow; + Say(1005144); // Yes, Sire. + understood = true; + } + + if (!understood) + Say(1042183); // I'm sorry, I don't understand your orders... + } + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_Faction != null && Map == Faction.Facet) + list.Add(1060846, m_Faction.Definition.PropName); // Guard: ~1_val~ + } + + public override void OnSingleClick(Mobile from) + { + if (m_Faction != null && Map == Faction.Facet) + { + var text = $"(Guard, {m_Faction.Definition.FriendlyName})"; + + var hue = Faction.Find(from) == m_Faction ? 98 : 38; + + PrivateOverheadMessage(MessageType.Label, hue, true, text, from.NetState); + } + + base.OnSingleClick(from); + } + + public virtual void GenerateRandomHair() + { + Utility.AssignRandomHair(this); + Utility.AssignRandomFacialHair(this, HairHue); + } + + public void PackStrongPotions(int min, int max) + { + PackStrongPotions(Utility.RandomMinMax(min, max)); + } + + public void PackStrongPotions(int count) + { + for (var i = 0; i < count; ++i) + PackStrongPotion(); + } + + public void PackStrongPotion() + { + PackItem(Loot.Construct(m_StrongPotions)); + } + + public void PackWeakPotions(int min, int max) + { + PackWeakPotions(Utility.RandomMinMax(min, max)); + } + + public void PackWeakPotions(int count) + { + for (var i = 0; i < count; ++i) + PackWeakPotion(); + } + + public void PackWeakPotion() + { + PackItem(Loot.Construct(m_WeakPotions)); + } + + public Item Immovable(Item item) + { + item.Movable = false; + return item; + } + + public Item Newbied(Item item) + { + item.LootType = LootType.Newbied; + return item; + } + + public Item Rehued(Item item, int hue) + { + item.Hue = hue; + return item; + } + + public Item Layered(Item item, Layer layer) + { + item.Layer = layer; + return item; + } + + public Item Resourced(BaseWeapon weapon, CraftResource resource) + { + weapon.Resource = resource; + return weapon; + } + + public Item Resourced(BaseArmor armor, CraftResource resource) + { + armor.Resource = resource; + return armor; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + Unregister(); + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + c.Delete(); + } + + public virtual void GenerateBody(bool isFemale, bool randomHair) + { + Hue = Race.Human.RandomSkinHue(); + + if (isFemale) + { + Female = true; + Body = 401; + Name = NameList.RandomName("female"); + } + else + { + Female = false; + Body = 400; + Name = NameList.RandomName("male"); + } + + if (randomHair) + GenerateRandomHair(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + Faction.WriteReference(writer, m_Faction); + Town.WriteReference(writer, m_Town); + + Orders.Serialize(writer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Faction = Faction.ReadReference(reader); + m_Town = Town.ReadReference(reader); + Orders = new Orders(this, reader); + + Timer.DelayCall(Register); + } + } + + public class VirtualMount : IMount + { + private readonly VirtualMountItem m_Item; + + public VirtualMount(VirtualMountItem item) => m_Item = item; + + Mobile IMount.Rider + { + get => m_Item.Rider; + set { } + } + + public virtual void OnRiderDamaged(int amount, Mobile from, bool willKill) + { + } + } + + public class VirtualMountItem : Item, IMountItem + { + private readonly VirtualMount m_Mount; + + public VirtualMountItem(Mobile mob) : base(0x3EA0) + { + Layer = Layer.Mount; + + Rider = mob; + m_Mount = new VirtualMount(this); + } + + public VirtualMountItem(Serial serial) : base(serial) => m_Mount = new VirtualMount(this); + + public Mobile Rider { get; private set; } + + public IMount Mount => m_Mount; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(Rider); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + Rider = reader.ReadMobile(); + + if (Rider == null) + Delete(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Mobiles/Guards/GuardAI.cs b/Projects/UOContent/Engines/Factions/Mobiles/Guards/GuardAI.cs index 5c6e148eb..f40998be0 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/Guards/GuardAI.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/Guards/GuardAI.cs @@ -1,743 +1,750 @@ -using System; -using System.Collections.Generic; -using Server.Factions.AI; -using Server.Items; -using Server.Mobiles; -using Server.Spells; -using Server.Spells.Fifth; -using Server.Spells.First; -using Server.Spells.Fourth; -using Server.Spells.Second; -using Server.Spells.Seventh; -using Server.Spells.Sixth; -using Server.Spells.Third; -using Server.Targeting; -using Server.Utilities; - -namespace Server.Factions -{ - [Flags] - public enum GuardAI - { - Bless = 0x01, // heal, cure, +stats - Curse = 0x02, // poison, -stats - Melee = 0x04, // weapons - Magic = 0x08, // damage spells - Smart = 0x10 // smart weapons/damage spells - } - - public class ComboEntry - { - public ComboEntry(Type spell, int chance = 100) : this(spell, chance, TimeSpan.Zero) - { - } - - public ComboEntry(Type spell, int chance, TimeSpan hold) - { - Spell = spell; - Chance = chance; - Hold = hold; - } - - public Type Spell { get; } - - public TimeSpan Hold { get; } - - public int Chance { get; } - } - - public class SpellCombo - { - public static readonly SpellCombo Simple = new SpellCombo(50, - new ComboEntry(typeof(ParalyzeSpell), 20), - new ComboEntry(typeof(ExplosionSpell), 100, TimeSpan.FromSeconds(2.8)), - new ComboEntry(typeof(PoisonSpell), 30), - new ComboEntry(typeof(EnergyBoltSpell))); - - public static readonly SpellCombo Strong = new SpellCombo(90, - new ComboEntry(typeof(ParalyzeSpell), 20), - new ComboEntry(typeof(ExplosionSpell), 50, TimeSpan.FromSeconds(2.8)), - new ComboEntry(typeof(PoisonSpell), 30), - new ComboEntry(typeof(ExplosionSpell), 100, TimeSpan.FromSeconds(2.8)), - new ComboEntry(typeof(EnergyBoltSpell)), - new ComboEntry(typeof(PoisonSpell), 30), - new ComboEntry(typeof(EnergyBoltSpell))); - - public SpellCombo(int mana, params ComboEntry[] entries) - { - Mana = mana; - Entries = entries; - } - - public int Mana { get; } - - public ComboEntry[] Entries { get; } - - public static Spell Process(Mobile mob, Mobile targ, ref SpellCombo combo, ref int index, ref DateTime releaseTime) - { - while (++index < combo.Entries.Length) - { - ComboEntry entry = combo.Entries[index]; - - if (entry.Spell == typeof(PoisonSpell) && targ.Poisoned) - continue; - - if (entry.Chance > Utility.Random(100)) - { - releaseTime = DateTime.UtcNow + entry.Hold; - return (Spell)ActivatorUtil.CreateInstance(entry.Spell, mob, null); - } - } - - combo = null; - index = -1; - return null; - } - } - - public class FactionGuardAI : BaseAI - { - private const int ManaReserve = 30; - - private BandageContext m_Bandage; - private DateTime m_BandageStart; - - private SpellCombo m_Combo; - private int m_ComboIndex = -1; - private readonly BaseFactionGuard m_Guard; - private DateTime m_ReleaseTarget; - - public FactionGuardAI(BaseFactionGuard guard) : base(guard) => m_Guard = guard; - - public bool IsDamaged => m_Guard.Hits < m_Guard.HitsMax; - - public bool IsPoisoned => m_Guard.Poisoned; - - public TimeSpan TimeUntilBandage - { - get - { - if (m_Bandage != null && m_Bandage.Timer == null) - m_Bandage = null; - - if (m_Bandage == null) - return TimeSpan.MaxValue; - - TimeSpan ts = m_BandageStart + m_Bandage.Timer.Delay - DateTime.UtcNow; - - if (ts < TimeSpan.FromSeconds(-1.0)) - { - m_Bandage = null; - return TimeSpan.MaxValue; - } - - if (ts < TimeSpan.Zero) - ts = TimeSpan.Zero; - - return ts; - } - } - - public bool IsAllowed(GuardAI flag) => (m_Guard.GuardAI & flag) == flag; - - public bool DequipWeapon() - { - Container pack = m_Guard.Backpack; - - if (pack == null) - return false; - - if (m_Guard.Weapon is Item weapon && weapon.Parent == m_Guard && !(weapon is Fists)) - { - pack.DropItem(weapon); - return true; - } - - return false; - } - - public bool EquipWeapon() - { - Item weapon = m_Guard.Backpack?.FindItemByType(); - - return weapon != null && m_Guard.EquipItem(weapon); - } - - public bool StartBandage() - { - m_Bandage = null; - - if (m_Guard.Backpack?.FindItemByType() == null) - return false; - - m_Bandage = BandageContext.BeginHeal(m_Guard, m_Guard); - m_BandageStart = DateTime.UtcNow; - return m_Bandage != null; - } - - public bool UseItemByType(Type type) - { - Container pack = m_Guard.Backpack; - - Item item = pack?.FindItemByType(type); - - if (item == null) - return false; - - bool requip = DequipWeapon(); - - item.OnDoubleClick(m_Guard); - - if (requip) - EquipWeapon(); - - return true; - } - - public int GetStatMod(Mobile mob, StatType type) - { - StatMod mod = mob.GetStatMod($"[Magic] {type} Offset"); - - if (mod == null) - return 0; - - return mod.Offset; - } - - public Spell RandomOffenseSpell() - { - int maxCircle = Math.Max((int)((m_Guard.Skills.Magery.Value + 20.0) / (100.0 / 7.0)), 1); - - return Utility.Random(maxCircle * 2) switch - { - 0 => new MagicArrowSpell(m_Guard), - 1 => new MagicArrowSpell(m_Guard), - 2 => new HarmSpell(m_Guard), - 3 => new HarmSpell(m_Guard), - 4 => new FireballSpell(m_Guard), - 5 => new FireballSpell(m_Guard), - 6 => new LightningSpell(m_Guard), - 7 => new LightningSpell(m_Guard), - 8 => new MindBlastSpell(m_Guard), - 9 => new ParalyzeSpell(m_Guard), - 10 => new EnergyBoltSpell(m_Guard), - 11 => new ExplosionSpell(m_Guard), - _ => new FlameStrikeSpell(m_Guard) - }; - } - - public Mobile FindDispelTarget(bool activeOnly) - { - if (m_Mobile.Deleted || m_Mobile.Int < 95 || CanDispel(m_Mobile) || m_Mobile.AutoDispel) - return null; - - if (activeOnly) - { - List aggressed = m_Mobile.Aggressed; - List aggressors = m_Mobile.Aggressors; - - Mobile active = null; - double activePrio = 0.0; - - Mobile comb = m_Mobile.Combatant; - - if (comb?.Deleted == false && comb.Alive && !comb.IsDeadBondedPet && m_Mobile.InRange(comb, 12) && - CanDispel(comb)) - { - active = comb; - activePrio = m_Mobile.GetDistanceToSqrt(comb); - - if (activePrio <= 2) - return active; - } - - for (int i = 0; i < aggressed.Count; ++i) - { - AggressorInfo info = aggressed[i]; - Mobile m = info.Defender; - - if (m != comb && m.Combatant == m_Mobile && m_Mobile.InRange(m, 12) && CanDispel(m)) - { - double prio = m_Mobile.GetDistanceToSqrt(m); - - if (active == null || prio < activePrio) - { - active = m; - activePrio = prio; - - if (activePrio <= 2) - return active; - } - } - } - - for (int i = 0; i < aggressors.Count; ++i) - { - AggressorInfo info = aggressors[i]; - Mobile m = info.Attacker; - - if (m != comb && m.Combatant == m_Mobile && m_Mobile.InRange(m, 12) && CanDispel(m)) - { - double prio = m_Mobile.GetDistanceToSqrt(m); - - if (active == null || prio < activePrio) - { - active = m; - activePrio = prio; - - if (activePrio <= 2) - return active; - } - } - } - - return active; - } - - Map map = m_Mobile.Map; - - if (map != null) - { - Mobile active = null, inactive = null; - double actPrio = 0.0, inactPrio = 0.0; - - Mobile comb = m_Mobile.Combatant; - - if (comb?.Deleted == false && comb.Alive && !comb.IsDeadBondedPet && CanDispel(comb)) - { - active = inactive = comb; - actPrio = inactPrio = m_Mobile.GetDistanceToSqrt(comb); - } - - foreach (Mobile m in m_Mobile.GetMobilesInRange(12)) - if (m != m_Mobile && CanDispel(m)) - { - double prio = m_Mobile.GetDistanceToSqrt(m); - - if (inactive == null || prio < inactPrio) - { - inactive = m; - inactPrio = prio; - } - - if ((m_Mobile.Combatant == m || m.Combatant == m_Mobile) && (active == null || prio < actPrio)) - { - active = m; - actPrio = prio; - } - } - - return active ?? inactive; - } - - return null; - } - - public bool CanDispel(Mobile m) => - m is BaseCreature creature && creature.Summoned && m_Mobile.CanBeHarmful(creature, false) && - !creature.IsAnimatedDead; - - public void RunTo(Mobile m) - { - /*if (m.Paralyzed || m.Frozen) - { - if (m_Mobile.InRange( m, 1 )) - RunFrom( m ); - else if (!m_Mobile.InRange( m, m_Mobile.RangeFight > 2 ? m_Mobile.RangeFight : 2 ) && !MoveTo( m, true, 1 )) - OnFailedMove(); - } - else - {*/ - if (!m_Mobile.InRange(m, m_Mobile.RangeFight)) - { - if (!MoveTo(m, true, 1)) - OnFailedMove(); - } - else if (m_Mobile.InRange(m, m_Mobile.RangeFight - 1)) - { - RunFrom(m); - } - - /*}*/ - } - - public void RunFrom(Mobile m) - { - Run(m_Mobile.GetDirectionTo(m) - 4 & Direction.Mask); - } - - public void OnFailedMove() - { - /*if (!m_Mobile.DisallowAllMoves && 20 > Utility.Random( 100 ) && IsAllowed( GuardAI.Magic )) - { - if (m_Mobile.Target != null) - m_Mobile.Target.Cancel( m_Mobile, TargetCancelType.Canceled ); - - new TeleportSpell( m_Mobile, null ).Cast(); - - m_Mobile.DebugSay( "I am stuck, I'm going to try teleporting away" ); - } - else*/ - if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) - { - if (m_Mobile.Debug) - m_Mobile.DebugSay("My move is blocked, so I am going to attack {0}", m_Mobile.FocusMob.Name); - - m_Mobile.Combatant = m_Mobile.FocusMob; - Action = ActionType.Combat; - } - else - { - m_Mobile.DebugSay("I am stuck"); - } - } - - public void Run(Direction d) - { - if (m_Mobile.Spell?.IsCasting == true || m_Mobile.Paralyzed || m_Mobile.Frozen || - m_Mobile.DisallowAllMoves) - return; - - m_Mobile.Direction = d | Direction.Running; - - if (!DoMove(m_Mobile.Direction, true)) - OnFailedMove(); - } - - public override bool Think() - { - if (m_Mobile.Deleted) - return false; - - Mobile combatant = m_Guard.Combatant; - - if (combatant?.Deleted != false || !combatant.Alive || combatant.IsDeadBondedPet || - !m_Mobile.CanSee(combatant) || !m_Mobile.CanBeHarmful(combatant, false) || combatant.Map != m_Mobile.Map) - { - // Our combatant is deleted, dead, hidden, or we cannot hurt them - // Try to find another combatant - - if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) - { - m_Mobile.Combatant = combatant = m_Mobile.FocusMob; - m_Mobile.FocusMob = null; - } - else - { - m_Mobile.Combatant = combatant = null; - } - } - - if (combatant != null && (!m_Mobile.InLOS(combatant) || !m_Mobile.InRange(combatant, 12))) - { - if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) - { - m_Mobile.Combatant = combatant = m_Mobile.FocusMob; - m_Mobile.FocusMob = null; - } - else if (!m_Mobile.InRange(combatant, 36)) - { - m_Mobile.Combatant = combatant = null; - } - } - - Mobile dispelTarget = FindDispelTarget(true); - - if (m_Guard.Target != null && m_ReleaseTarget == DateTime.MinValue) - m_ReleaseTarget = DateTime.UtcNow + TimeSpan.FromSeconds(10.0); - - if (m_Guard.Target != null && DateTime.UtcNow > m_ReleaseTarget) - { - Target targ = m_Guard.Target; - - Mobile toHarm = dispelTarget ?? combatant; - - if ((targ.Flags & TargetFlags.Harmful) != 0 && toHarm != null) - { - if (m_Guard.Map == toHarm.Map && (targ.Range < 0 || m_Guard.InRange(toHarm, targ.Range)) && - m_Guard.CanSee(toHarm) && m_Guard.InLOS(toHarm)) - targ.Invoke(m_Guard, toHarm); - else if ((targ as ISpellTarget)?.Spell is DispelSpell) - targ.Cancel(m_Guard, TargetCancelType.Canceled); - } - else if ((targ.Flags & TargetFlags.Beneficial) != 0) - { - targ.Invoke(m_Guard, m_Guard); - } - else - { - targ.Cancel(m_Guard, TargetCancelType.Canceled); - } - - m_ReleaseTarget = DateTime.MinValue; - } - - if (dispelTarget != null) - { - if (Action != ActionType.Combat) - Action = ActionType.Combat; - - m_Guard.Warmode = true; - - RunFrom(dispelTarget); - } - else if (combatant != null) - { - if (Action != ActionType.Combat) - Action = ActionType.Combat; - - m_Guard.Warmode = true; - - RunTo(combatant); - } - else if (m_Guard.Orders.Movement != MovementType.Stand) - { - Mobile toFollow = null; - - if (m_Guard.Town != null && m_Guard.Orders.Movement == MovementType.Follow) toFollow = m_Guard.Orders.Follow ?? m_Guard.Town.Sheriff; - - if (toFollow != null && toFollow.Map == m_Guard.Map && - toFollow.InRange(m_Guard, m_Guard.RangePerception * 3) && - Town.FromRegion(toFollow.Region) == m_Guard.Town) - { - if (Action != ActionType.Combat) - Action = ActionType.Combat; - - if (m_Mobile.CurrentSpeed != m_Mobile.ActiveSpeed) - m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; - - m_Guard.Warmode = true; - - RunTo(toFollow); - } - else - { - if (Action != ActionType.Wander) - Action = ActionType.Wander; - - if (m_Mobile.CurrentSpeed != m_Mobile.PassiveSpeed) - m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; - - m_Guard.Warmode = false; - - WalkRandomInHome(2, 2, 1); - } - } - else - { - if (Action != ActionType.Wander) - Action = ActionType.Wander; - - m_Guard.Warmode = false; - } - - if ((IsDamaged || IsPoisoned) && m_Guard.Skills.Healing.Base > 20.0) - { - TimeSpan ts = TimeUntilBandage; - - if (ts == TimeSpan.MaxValue) - StartBandage(); - } - - Spell spell = m_Mobile.Spell as Spell; - - if (spell == null && Core.TickCount - m_Mobile.NextSpellTime >= 0) - { - DateTime toRelease = DateTime.MinValue; - - if (IsPoisoned) - { - Poison p = m_Guard.Poison; - - TimeSpan ts = TimeUntilBandage; - - if (p != Poison.Lesser || ts == TimeSpan.MaxValue || TimeUntilBandage < TimeSpan.FromSeconds(1.5) || - m_Guard.HitsMax - m_Guard.Hits > Utility.Random(250)) - { - if (IsAllowed(GuardAI.Bless)) - spell = new CureSpell(m_Guard); - else - UseItemByType(typeof(BaseCurePotion)); - } - } - else if (IsDamaged && m_Guard.HitsMax - m_Guard.Hits > Utility.Random(200)) - { - if (IsAllowed(GuardAI.Magic) && m_Guard.Hits * 100 / Math.Max(m_Guard.HitsMax, 1) < 10 && - m_Guard.Home != Point3D.Zero && !Utility.InRange(m_Guard.Location, m_Guard.Home, 15) && - m_Guard.Mana >= 11) - { - spell = new RecallSpell(m_Guard, - new RunebookEntry(m_Guard.Home, m_Guard.Map, "Guard's Home")); - } - else if (IsAllowed(GuardAI.Bless)) - { - if (m_Guard.Mana >= 11 && m_Guard.Hits + 30 < m_Guard.HitsMax) - spell = new GreaterHealSpell(m_Guard); - else if (m_Guard.Hits + 10 < m_Guard.HitsMax && - (m_Guard.Mana < 11 || m_Guard.NextCombatTime - Core.TickCount > 2000)) - spell = new HealSpell(m_Guard); - } - else if (m_Guard.CanBeginAction()) - { - UseItemByType(typeof(BaseHealPotion)); - } - } - else if (dispelTarget != null && - (IsAllowed(GuardAI.Magic) || IsAllowed(GuardAI.Bless) || IsAllowed(GuardAI.Curse))) - { - if (!dispelTarget.Paralyzed && m_Guard.Mana > ManaReserve + 20 && Utility.Random(100) < 40) - spell = new ParalyzeSpell(m_Guard); - else - spell = new DispelSpell(m_Guard); - } - - if (combatant != null) - { - if (m_Combo != null) - { - if (spell == null) - { - spell = SpellCombo.Process(m_Guard, combatant, ref m_Combo, ref m_ComboIndex, ref toRelease); - } - else - { - m_Combo = null; - m_ComboIndex = -1; - } - } - else if (Utility.Random(100) < 20 && IsAllowed(GuardAI.Magic)) - { - if (Utility.Random(100) < 80) - { - m_Combo = IsAllowed(GuardAI.Smart) ? SpellCombo.Simple : SpellCombo.Strong; - m_ComboIndex = -1; - - if (m_Guard.Mana >= ManaReserve + m_Combo.Mana) - { - spell = SpellCombo.Process(m_Guard, combatant, ref m_Combo, ref m_ComboIndex, ref toRelease); - } - else - { - m_Combo = null; - - if (m_Guard.Mana >= ManaReserve + 40) - spell = RandomOffenseSpell(); - } - } - else if (m_Guard.Mana >= ManaReserve + 40) - { - spell = RandomOffenseSpell(); - } - } - - if (spell == null && Utility.Random(100) < 2 && m_Guard.Mana >= ManaReserve + 10) - { - int strMod = GetStatMod(m_Guard, StatType.Str); - int dexMod = GetStatMod(m_Guard, StatType.Dex); - int intMod = GetStatMod(m_Guard, StatType.Int); - - List types = new List(); - - if (strMod <= 0) - types.Add(typeof(StrengthSpell)); - - if (dexMod <= 0 && IsAllowed(GuardAI.Melee)) - types.Add(typeof(AgilitySpell)); - - if (intMod <= 0 && IsAllowed(GuardAI.Magic)) - types.Add(typeof(CunningSpell)); - - if (IsAllowed(GuardAI.Bless)) - { - if (types.Count > 1) - spell = new BlessSpell(m_Guard); - else if (types.Count == 1) - spell = ActivatorUtil.CreateInstance(types[0], m_Guard, null) as Spell; - } - else if (types.Count > 0) - { - if (types[0] == typeof(StrengthSpell)) - UseItemByType(typeof(BaseStrengthPotion)); - else if (types[0] == typeof(AgilitySpell)) - UseItemByType(typeof(BaseAgilityPotion)); - } - } - - if (spell == null && Utility.Random(100) < 2 && m_Guard.Mana >= ManaReserve + 10 && - IsAllowed(GuardAI.Curse)) - { - if (!combatant.Poisoned && Utility.Random(100) < 40) - { - spell = new PoisonSpell(m_Guard); - } - else - { - int strMod = GetStatMod(combatant, StatType.Str); - int dexMod = GetStatMod(combatant, StatType.Dex); - int intMod = GetStatMod(combatant, StatType.Int); - - List types = new List(); - - if (strMod >= 0) - types.Add(typeof(WeakenSpell)); - - if (dexMod >= 0 && IsAllowed(GuardAI.Melee)) - types.Add(typeof(ClumsySpell)); - - if (intMod >= 0 && IsAllowed(GuardAI.Magic)) - types.Add(typeof(FeeblemindSpell)); - - if (types.Count > 1) - spell = new CurseSpell(m_Guard); - else if (types.Count == 1) - spell = (Spell)ActivatorUtil.CreateInstance(types[0], m_Guard, null); - } - } - } - - if (spell != null && m_Guard.HitsMax - m_Guard.Hits + 10 > Utility.Random(100)) - { - Type type = null; - - if (spell is GreaterHealSpell) - type = typeof(BaseHealPotion); - else if (spell is CureSpell) - type = typeof(BaseCurePotion); - else if (spell is StrengthSpell) - type = typeof(BaseStrengthPotion); - else if (spell is AgilitySpell) - type = typeof(BaseAgilityPotion); - - if (type == typeof(BaseHealPotion) && !m_Guard.CanBeginAction(type)) - type = null; - - if (type != null && m_Guard.Target == null && UseItemByType(type)) - { - if (spell is GreaterHealSpell) - { - if (m_Guard.Hits + 30 > m_Guard.HitsMax && m_Guard.Hits + 10 < m_Guard.HitsMax) - spell = new HealSpell(m_Guard); - } - else - { - spell = null; - } - } - } - else if (spell == null && m_Guard.Stam < m_Guard.StamMax / 3 && IsAllowed(GuardAI.Melee)) - { - UseItemByType(typeof(BaseRefreshPotion)); - } - - if (spell?.Cast() != true) - EquipWeapon(); - } - else if (spell?.State == SpellState.Sequencing) - { - EquipWeapon(); - } - - return true; - } - } -} +using System; +using System.Collections.Generic; +using Server.Factions.AI; +using Server.Items; +using Server.Mobiles; +using Server.Spells; +using Server.Spells.Fifth; +using Server.Spells.First; +using Server.Spells.Fourth; +using Server.Spells.Second; +using Server.Spells.Seventh; +using Server.Spells.Sixth; +using Server.Spells.Third; +using Server.Targeting; +using Server.Utilities; + +namespace Server.Factions +{ + [Flags] + public enum GuardAI + { + Bless = 0x01, // heal, cure, +stats + Curse = 0x02, // poison, -stats + Melee = 0x04, // weapons + Magic = 0x08, // damage spells + Smart = 0x10 // smart weapons/damage spells + } + + public class ComboEntry + { + public ComboEntry(Type spell, int chance = 100) : this(spell, chance, TimeSpan.Zero) + { + } + + public ComboEntry(Type spell, int chance, TimeSpan hold) + { + Spell = spell; + Chance = chance; + Hold = hold; + } + + public Type Spell { get; } + + public TimeSpan Hold { get; } + + public int Chance { get; } + } + + public class SpellCombo + { + public static readonly SpellCombo Simple = new SpellCombo( + 50, + new ComboEntry(typeof(ParalyzeSpell), 20), + new ComboEntry(typeof(ExplosionSpell), 100, TimeSpan.FromSeconds(2.8)), + new ComboEntry(typeof(PoisonSpell), 30), + new ComboEntry(typeof(EnergyBoltSpell)) + ); + + public static readonly SpellCombo Strong = new SpellCombo( + 90, + new ComboEntry(typeof(ParalyzeSpell), 20), + new ComboEntry(typeof(ExplosionSpell), 50, TimeSpan.FromSeconds(2.8)), + new ComboEntry(typeof(PoisonSpell), 30), + new ComboEntry(typeof(ExplosionSpell), 100, TimeSpan.FromSeconds(2.8)), + new ComboEntry(typeof(EnergyBoltSpell)), + new ComboEntry(typeof(PoisonSpell), 30), + new ComboEntry(typeof(EnergyBoltSpell)) + ); + + public SpellCombo(int mana, params ComboEntry[] entries) + { + Mana = mana; + Entries = entries; + } + + public int Mana { get; } + + public ComboEntry[] Entries { get; } + + public static Spell Process(Mobile mob, Mobile targ, ref SpellCombo combo, ref int index, ref DateTime releaseTime) + { + while (++index < combo.Entries.Length) + { + var entry = combo.Entries[index]; + + if (entry.Spell == typeof(PoisonSpell) && targ.Poisoned) + continue; + + if (entry.Chance > Utility.Random(100)) + { + releaseTime = DateTime.UtcNow + entry.Hold; + return (Spell)ActivatorUtil.CreateInstance(entry.Spell, mob, null); + } + } + + combo = null; + index = -1; + return null; + } + } + + public class FactionGuardAI : BaseAI + { + private const int ManaReserve = 30; + private readonly BaseFactionGuard m_Guard; + + private BandageContext m_Bandage; + private DateTime m_BandageStart; + + private SpellCombo m_Combo; + private int m_ComboIndex = -1; + private DateTime m_ReleaseTarget; + + public FactionGuardAI(BaseFactionGuard guard) : base(guard) => m_Guard = guard; + + public bool IsDamaged => m_Guard.Hits < m_Guard.HitsMax; + + public bool IsPoisoned => m_Guard.Poisoned; + + public TimeSpan TimeUntilBandage + { + get + { + if (m_Bandage != null && m_Bandage.Timer == null) + m_Bandage = null; + + if (m_Bandage == null) + return TimeSpan.MaxValue; + + var ts = m_BandageStart + m_Bandage.Timer.Delay - DateTime.UtcNow; + + if (ts < TimeSpan.FromSeconds(-1.0)) + { + m_Bandage = null; + return TimeSpan.MaxValue; + } + + if (ts < TimeSpan.Zero) + ts = TimeSpan.Zero; + + return ts; + } + } + + public bool IsAllowed(GuardAI flag) => (m_Guard.GuardAI & flag) == flag; + + public bool DequipWeapon() + { + var pack = m_Guard.Backpack; + + if (pack == null) + return false; + + if (m_Guard.Weapon is Item weapon && weapon.Parent == m_Guard && !(weapon is Fists)) + { + pack.DropItem(weapon); + return true; + } + + return false; + } + + public bool EquipWeapon() + { + Item weapon = m_Guard.Backpack?.FindItemByType(); + + return weapon != null && m_Guard.EquipItem(weapon); + } + + public bool StartBandage() + { + m_Bandage = null; + + if (m_Guard.Backpack?.FindItemByType() == null) + return false; + + m_Bandage = BandageContext.BeginHeal(m_Guard, m_Guard); + m_BandageStart = DateTime.UtcNow; + return m_Bandage != null; + } + + public bool UseItemByType(Type type) + { + var pack = m_Guard.Backpack; + + var item = pack?.FindItemByType(type); + + if (item == null) + return false; + + var requip = DequipWeapon(); + + item.OnDoubleClick(m_Guard); + + if (requip) + EquipWeapon(); + + return true; + } + + public int GetStatMod(Mobile mob, StatType type) + { + var mod = mob.GetStatMod($"[Magic] {type} Offset"); + + if (mod == null) + return 0; + + return mod.Offset; + } + + public Spell RandomOffenseSpell() + { + var maxCircle = Math.Max((int)((m_Guard.Skills.Magery.Value + 20.0) / (100.0 / 7.0)), 1); + + return Utility.Random(maxCircle * 2) switch + { + 0 => new MagicArrowSpell(m_Guard), + 1 => new MagicArrowSpell(m_Guard), + 2 => new HarmSpell(m_Guard), + 3 => new HarmSpell(m_Guard), + 4 => new FireballSpell(m_Guard), + 5 => new FireballSpell(m_Guard), + 6 => new LightningSpell(m_Guard), + 7 => new LightningSpell(m_Guard), + 8 => new MindBlastSpell(m_Guard), + 9 => new ParalyzeSpell(m_Guard), + 10 => new EnergyBoltSpell(m_Guard), + 11 => new ExplosionSpell(m_Guard), + _ => new FlameStrikeSpell(m_Guard) + }; + } + + public Mobile FindDispelTarget(bool activeOnly) + { + if (m_Mobile.Deleted || m_Mobile.Int < 95 || CanDispel(m_Mobile) || m_Mobile.AutoDispel) + return null; + + if (activeOnly) + { + var aggressed = m_Mobile.Aggressed; + var aggressors = m_Mobile.Aggressors; + + Mobile active = null; + var activePrio = 0.0; + + var comb = m_Mobile.Combatant; + + if (comb?.Deleted == false && comb.Alive && !comb.IsDeadBondedPet && m_Mobile.InRange(comb, 12) && + CanDispel(comb)) + { + active = comb; + activePrio = m_Mobile.GetDistanceToSqrt(comb); + + if (activePrio <= 2) + return active; + } + + for (var i = 0; i < aggressed.Count; ++i) + { + var info = aggressed[i]; + var m = info.Defender; + + if (m != comb && m.Combatant == m_Mobile && m_Mobile.InRange(m, 12) && CanDispel(m)) + { + var prio = m_Mobile.GetDistanceToSqrt(m); + + if (active == null || prio < activePrio) + { + active = m; + activePrio = prio; + + if (activePrio <= 2) + return active; + } + } + } + + for (var i = 0; i < aggressors.Count; ++i) + { + var info = aggressors[i]; + var m = info.Attacker; + + if (m != comb && m.Combatant == m_Mobile && m_Mobile.InRange(m, 12) && CanDispel(m)) + { + var prio = m_Mobile.GetDistanceToSqrt(m); + + if (active == null || prio < activePrio) + { + active = m; + activePrio = prio; + + if (activePrio <= 2) + return active; + } + } + } + + return active; + } + + var map = m_Mobile.Map; + + if (map != null) + { + Mobile active = null, inactive = null; + double actPrio = 0.0, inactPrio = 0.0; + + var comb = m_Mobile.Combatant; + + if (comb?.Deleted == false && comb.Alive && !comb.IsDeadBondedPet && CanDispel(comb)) + { + active = inactive = comb; + actPrio = inactPrio = m_Mobile.GetDistanceToSqrt(comb); + } + + foreach (var m in m_Mobile.GetMobilesInRange(12)) + if (m != m_Mobile && CanDispel(m)) + { + var prio = m_Mobile.GetDistanceToSqrt(m); + + if (inactive == null || prio < inactPrio) + { + inactive = m; + inactPrio = prio; + } + + if ((m_Mobile.Combatant == m || m.Combatant == m_Mobile) && (active == null || prio < actPrio)) + { + active = m; + actPrio = prio; + } + } + + return active ?? inactive; + } + + return null; + } + + public bool CanDispel(Mobile m) => + m is BaseCreature creature && creature.Summoned && m_Mobile.CanBeHarmful(creature, false) && + !creature.IsAnimatedDead; + + public void RunTo(Mobile m) + { + /*if (m.Paralyzed || m.Frozen) + { + if (m_Mobile.InRange( m, 1 )) + RunFrom( m ); + else if (!m_Mobile.InRange( m, m_Mobile.RangeFight > 2 ? m_Mobile.RangeFight : 2 ) && !MoveTo( m, true, 1 )) + OnFailedMove(); + } + else + {*/ + if (!m_Mobile.InRange(m, m_Mobile.RangeFight)) + { + if (!MoveTo(m, true, 1)) + OnFailedMove(); + } + else if (m_Mobile.InRange(m, m_Mobile.RangeFight - 1)) + { + RunFrom(m); + } + + /*}*/ + } + + public void RunFrom(Mobile m) + { + Run((m_Mobile.GetDirectionTo(m) - 4) & Direction.Mask); + } + + public void OnFailedMove() + { + /*if (!m_Mobile.DisallowAllMoves && 20 > Utility.Random( 100 ) && IsAllowed( GuardAI.Magic )) + { + if (m_Mobile.Target != null) + m_Mobile.Target.Cancel( m_Mobile, TargetCancelType.Canceled ); + + new TeleportSpell( m_Mobile, null ).Cast(); + + m_Mobile.DebugSay( "I am stuck, I'm going to try teleporting away" ); + } + else*/ + if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) + { + if (m_Mobile.Debug) + m_Mobile.DebugSay("My move is blocked, so I am going to attack {0}", m_Mobile.FocusMob.Name); + + m_Mobile.Combatant = m_Mobile.FocusMob; + Action = ActionType.Combat; + } + else + { + m_Mobile.DebugSay("I am stuck"); + } + } + + public void Run(Direction d) + { + if (m_Mobile.Spell?.IsCasting == true || m_Mobile.Paralyzed || m_Mobile.Frozen || + m_Mobile.DisallowAllMoves) + return; + + m_Mobile.Direction = d | Direction.Running; + + if (!DoMove(m_Mobile.Direction, true)) + OnFailedMove(); + } + + public override bool Think() + { + if (m_Mobile.Deleted) + return false; + + var combatant = m_Guard.Combatant; + + if (combatant?.Deleted != false || !combatant.Alive || combatant.IsDeadBondedPet || + !m_Mobile.CanSee(combatant) || !m_Mobile.CanBeHarmful(combatant, false) || combatant.Map != m_Mobile.Map) + { + // Our combatant is deleted, dead, hidden, or we cannot hurt them + // Try to find another combatant + + if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) + { + m_Mobile.Combatant = combatant = m_Mobile.FocusMob; + m_Mobile.FocusMob = null; + } + else + { + m_Mobile.Combatant = combatant = null; + } + } + + if (combatant != null && (!m_Mobile.InLOS(combatant) || !m_Mobile.InRange(combatant, 12))) + { + if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) + { + m_Mobile.Combatant = combatant = m_Mobile.FocusMob; + m_Mobile.FocusMob = null; + } + else if (!m_Mobile.InRange(combatant, 36)) + { + m_Mobile.Combatant = combatant = null; + } + } + + var dispelTarget = FindDispelTarget(true); + + if (m_Guard.Target != null && m_ReleaseTarget == DateTime.MinValue) + m_ReleaseTarget = DateTime.UtcNow + TimeSpan.FromSeconds(10.0); + + if (m_Guard.Target != null && DateTime.UtcNow > m_ReleaseTarget) + { + var targ = m_Guard.Target; + + var toHarm = dispelTarget ?? combatant; + + if ((targ.Flags & TargetFlags.Harmful) != 0 && toHarm != null) + { + if (m_Guard.Map == toHarm.Map && (targ.Range < 0 || m_Guard.InRange(toHarm, targ.Range)) && + m_Guard.CanSee(toHarm) && m_Guard.InLOS(toHarm)) + targ.Invoke(m_Guard, toHarm); + else if ((targ as ISpellTarget)?.Spell is DispelSpell) + targ.Cancel(m_Guard, TargetCancelType.Canceled); + } + else if ((targ.Flags & TargetFlags.Beneficial) != 0) + { + targ.Invoke(m_Guard, m_Guard); + } + else + { + targ.Cancel(m_Guard, TargetCancelType.Canceled); + } + + m_ReleaseTarget = DateTime.MinValue; + } + + if (dispelTarget != null) + { + if (Action != ActionType.Combat) + Action = ActionType.Combat; + + m_Guard.Warmode = true; + + RunFrom(dispelTarget); + } + else if (combatant != null) + { + if (Action != ActionType.Combat) + Action = ActionType.Combat; + + m_Guard.Warmode = true; + + RunTo(combatant); + } + else if (m_Guard.Orders.Movement != MovementType.Stand) + { + Mobile toFollow = null; + + if (m_Guard.Town != null && m_Guard.Orders.Movement == MovementType.Follow) + toFollow = m_Guard.Orders.Follow ?? m_Guard.Town.Sheriff; + + if (toFollow != null && toFollow.Map == m_Guard.Map && + toFollow.InRange(m_Guard, m_Guard.RangePerception * 3) && + Town.FromRegion(toFollow.Region) == m_Guard.Town) + { + if (Action != ActionType.Combat) + Action = ActionType.Combat; + + if (m_Mobile.CurrentSpeed != m_Mobile.ActiveSpeed) + m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; + + m_Guard.Warmode = true; + + RunTo(toFollow); + } + else + { + if (Action != ActionType.Wander) + Action = ActionType.Wander; + + if (m_Mobile.CurrentSpeed != m_Mobile.PassiveSpeed) + m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; + + m_Guard.Warmode = false; + + WalkRandomInHome(2, 2, 1); + } + } + else + { + if (Action != ActionType.Wander) + Action = ActionType.Wander; + + m_Guard.Warmode = false; + } + + if ((IsDamaged || IsPoisoned) && m_Guard.Skills.Healing.Base > 20.0) + { + var ts = TimeUntilBandage; + + if (ts == TimeSpan.MaxValue) + StartBandage(); + } + + var spell = m_Mobile.Spell as Spell; + + if (spell == null && Core.TickCount - m_Mobile.NextSpellTime >= 0) + { + var toRelease = DateTime.MinValue; + + if (IsPoisoned) + { + var p = m_Guard.Poison; + + var ts = TimeUntilBandage; + + if (p != Poison.Lesser || ts == TimeSpan.MaxValue || TimeUntilBandage < TimeSpan.FromSeconds(1.5) || + m_Guard.HitsMax - m_Guard.Hits > Utility.Random(250)) + { + if (IsAllowed(GuardAI.Bless)) + spell = new CureSpell(m_Guard); + else + UseItemByType(typeof(BaseCurePotion)); + } + } + else if (IsDamaged && m_Guard.HitsMax - m_Guard.Hits > Utility.Random(200)) + { + if (IsAllowed(GuardAI.Magic) && m_Guard.Hits * 100 / Math.Max(m_Guard.HitsMax, 1) < 10 && + m_Guard.Home != Point3D.Zero && !Utility.InRange(m_Guard.Location, m_Guard.Home, 15) && + m_Guard.Mana >= 11) + { + spell = new RecallSpell( + m_Guard, + new RunebookEntry(m_Guard.Home, m_Guard.Map, "Guard's Home") + ); + } + else if (IsAllowed(GuardAI.Bless)) + { + if (m_Guard.Mana >= 11 && m_Guard.Hits + 30 < m_Guard.HitsMax) + spell = new GreaterHealSpell(m_Guard); + else if (m_Guard.Hits + 10 < m_Guard.HitsMax && + (m_Guard.Mana < 11 || m_Guard.NextCombatTime - Core.TickCount > 2000)) + spell = new HealSpell(m_Guard); + } + else if (m_Guard.CanBeginAction()) + { + UseItemByType(typeof(BaseHealPotion)); + } + } + else if (dispelTarget != null && + (IsAllowed(GuardAI.Magic) || IsAllowed(GuardAI.Bless) || IsAllowed(GuardAI.Curse))) + { + if (!dispelTarget.Paralyzed && m_Guard.Mana > ManaReserve + 20 && Utility.Random(100) < 40) + spell = new ParalyzeSpell(m_Guard); + else + spell = new DispelSpell(m_Guard); + } + + if (combatant != null) + { + if (m_Combo != null) + { + if (spell == null) + { + spell = SpellCombo.Process(m_Guard, combatant, ref m_Combo, ref m_ComboIndex, ref toRelease); + } + else + { + m_Combo = null; + m_ComboIndex = -1; + } + } + else if (Utility.Random(100) < 20 && IsAllowed(GuardAI.Magic)) + { + if (Utility.Random(100) < 80) + { + m_Combo = IsAllowed(GuardAI.Smart) ? SpellCombo.Simple : SpellCombo.Strong; + m_ComboIndex = -1; + + if (m_Guard.Mana >= ManaReserve + m_Combo.Mana) + { + spell = SpellCombo.Process(m_Guard, combatant, ref m_Combo, ref m_ComboIndex, ref toRelease); + } + else + { + m_Combo = null; + + if (m_Guard.Mana >= ManaReserve + 40) + spell = RandomOffenseSpell(); + } + } + else if (m_Guard.Mana >= ManaReserve + 40) + { + spell = RandomOffenseSpell(); + } + } + + if (spell == null && Utility.Random(100) < 2 && m_Guard.Mana >= ManaReserve + 10) + { + var strMod = GetStatMod(m_Guard, StatType.Str); + var dexMod = GetStatMod(m_Guard, StatType.Dex); + var intMod = GetStatMod(m_Guard, StatType.Int); + + var types = new List(); + + if (strMod <= 0) + types.Add(typeof(StrengthSpell)); + + if (dexMod <= 0 && IsAllowed(GuardAI.Melee)) + types.Add(typeof(AgilitySpell)); + + if (intMod <= 0 && IsAllowed(GuardAI.Magic)) + types.Add(typeof(CunningSpell)); + + if (IsAllowed(GuardAI.Bless)) + { + if (types.Count > 1) + spell = new BlessSpell(m_Guard); + else if (types.Count == 1) + spell = ActivatorUtil.CreateInstance(types[0], m_Guard, null) as Spell; + } + else if (types.Count > 0) + { + if (types[0] == typeof(StrengthSpell)) + UseItemByType(typeof(BaseStrengthPotion)); + else if (types[0] == typeof(AgilitySpell)) + UseItemByType(typeof(BaseAgilityPotion)); + } + } + + if (spell == null && Utility.Random(100) < 2 && m_Guard.Mana >= ManaReserve + 10 && + IsAllowed(GuardAI.Curse)) + { + if (!combatant.Poisoned && Utility.Random(100) < 40) + { + spell = new PoisonSpell(m_Guard); + } + else + { + var strMod = GetStatMod(combatant, StatType.Str); + var dexMod = GetStatMod(combatant, StatType.Dex); + var intMod = GetStatMod(combatant, StatType.Int); + + var types = new List(); + + if (strMod >= 0) + types.Add(typeof(WeakenSpell)); + + if (dexMod >= 0 && IsAllowed(GuardAI.Melee)) + types.Add(typeof(ClumsySpell)); + + if (intMod >= 0 && IsAllowed(GuardAI.Magic)) + types.Add(typeof(FeeblemindSpell)); + + if (types.Count > 1) + spell = new CurseSpell(m_Guard); + else if (types.Count == 1) + spell = (Spell)ActivatorUtil.CreateInstance(types[0], m_Guard, null); + } + } + } + + if (spell != null && m_Guard.HitsMax - m_Guard.Hits + 10 > Utility.Random(100)) + { + Type type = null; + + if (spell is GreaterHealSpell) + type = typeof(BaseHealPotion); + else if (spell is CureSpell) + type = typeof(BaseCurePotion); + else if (spell is StrengthSpell) + type = typeof(BaseStrengthPotion); + else if (spell is AgilitySpell) + type = typeof(BaseAgilityPotion); + + if (type == typeof(BaseHealPotion) && !m_Guard.CanBeginAction(type)) + type = null; + + if (type != null && m_Guard.Target == null && UseItemByType(type)) + { + if (spell is GreaterHealSpell) + { + if (m_Guard.Hits + 30 > m_Guard.HitsMax && m_Guard.Hits + 10 < m_Guard.HitsMax) + spell = new HealSpell(m_Guard); + } + else + { + spell = null; + } + } + } + else if (spell == null && m_Guard.Stam < m_Guard.StamMax / 3 && IsAllowed(GuardAI.Melee)) + { + UseItemByType(typeof(BaseRefreshPotion)); + } + + if (spell?.Cast() != true) + EquipWeapon(); + } + else if (spell?.State == SpellState.Sequencing) + { + EquipWeapon(); + } + + return true; + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Mobiles/Guards/Orders.cs b/Projects/UOContent/Engines/Factions/Mobiles/Guards/Orders.cs index 336ed4aa5..0cd0c4051 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/Guards/Orders.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/Guards/Orders.cs @@ -1,141 +1,143 @@ -using System.Collections.Generic; - -namespace Server.Factions.AI -{ - public enum ReactionType - { - Ignore, - Warn, - Attack - } - - public enum MovementType - { - Stand, - Patrol, - Follow - } - - public class Reaction - { - public Reaction(Faction faction, ReactionType type) - { - Faction = faction; - Type = type; - } - - public Reaction(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 0: - { - Faction = Faction.ReadReference(reader); - Type = (ReactionType)reader.ReadEncodedInt(); - - break; - } - } - } - - public Faction Faction { get; } - - public ReactionType Type { get; set; } - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - Faction.WriteReference(writer, Faction); - writer.WriteEncodedInt((int)Type); - } - } - - public class Orders - { - private readonly List m_Reactions; - - public Orders(BaseFactionGuard guard) - { - Guard = guard; - m_Reactions = new List(); - Movement = MovementType.Patrol; - } - - public Orders(BaseFactionGuard guard, IGenericReader reader) - { - Guard = guard; - - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 1: - { - Follow = reader.ReadMobile(); - goto case 0; - } - case 0: - { - int count = reader.ReadEncodedInt(); - m_Reactions = new List(count); - - for (int i = 0; i < count; ++i) - m_Reactions.Add(new Reaction(reader)); - - Movement = (MovementType)reader.ReadEncodedInt(); - - break; - } - } - } - - public BaseFactionGuard Guard { get; } - - public MovementType Movement { get; set; } - - public Mobile Follow { get; set; } - - public Reaction GetReaction(Faction faction) - { - Reaction reaction; - - for (int i = 0; i < m_Reactions.Count; ++i) - { - reaction = m_Reactions[i]; - - if (reaction.Faction == faction) - return reaction; - } - - reaction = new Reaction(faction, - faction == null || faction == Guard.Faction ? ReactionType.Ignore : ReactionType.Attack); - m_Reactions.Add(reaction); - - return reaction; - } - - public void SetReaction(Faction faction, ReactionType type) - { - Reaction reaction = GetReaction(faction); - - reaction.Type = type; - } - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(1); // version - - writer.Write(Follow); - - writer.WriteEncodedInt(m_Reactions.Count); - - for (int i = 0; i < m_Reactions.Count; ++i) - m_Reactions[i].Serialize(writer); - - writer.WriteEncodedInt((int)Movement); - } - } -} \ No newline at end of file +using System.Collections.Generic; + +namespace Server.Factions.AI +{ + public enum ReactionType + { + Ignore, + Warn, + Attack + } + + public enum MovementType + { + Stand, + Patrol, + Follow + } + + public class Reaction + { + public Reaction(Faction faction, ReactionType type) + { + Faction = faction; + Type = type; + } + + public Reaction(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 0: + { + Faction = Faction.ReadReference(reader); + Type = (ReactionType)reader.ReadEncodedInt(); + + break; + } + } + } + + public Faction Faction { get; } + + public ReactionType Type { get; set; } + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + Faction.WriteReference(writer, Faction); + writer.WriteEncodedInt((int)Type); + } + } + + public class Orders + { + private readonly List m_Reactions; + + public Orders(BaseFactionGuard guard) + { + Guard = guard; + m_Reactions = new List(); + Movement = MovementType.Patrol; + } + + public Orders(BaseFactionGuard guard, IGenericReader reader) + { + Guard = guard; + + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 1: + { + Follow = reader.ReadMobile(); + goto case 0; + } + case 0: + { + var count = reader.ReadEncodedInt(); + m_Reactions = new List(count); + + for (var i = 0; i < count; ++i) + m_Reactions.Add(new Reaction(reader)); + + Movement = (MovementType)reader.ReadEncodedInt(); + + break; + } + } + } + + public BaseFactionGuard Guard { get; } + + public MovementType Movement { get; set; } + + public Mobile Follow { get; set; } + + public Reaction GetReaction(Faction faction) + { + Reaction reaction; + + for (var i = 0; i < m_Reactions.Count; ++i) + { + reaction = m_Reactions[i]; + + if (reaction.Faction == faction) + return reaction; + } + + reaction = new Reaction( + faction, + faction == null || faction == Guard.Faction ? ReactionType.Ignore : ReactionType.Attack + ); + m_Reactions.Add(reaction); + + return reaction; + } + + public void SetReaction(Faction faction, ReactionType type) + { + var reaction = GetReaction(faction); + + reaction.Type = type; + } + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(1); // version + + writer.Write(Follow); + + writer.WriteEncodedInt(m_Reactions.Count); + + for (var i = 0; i < m_Reactions.Count; ++i) + m_Reactions[i].Serialize(writer); + + writer.WriteEncodedInt((int)Movement); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionBerserker.cs b/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionBerserker.cs index 4b69fc7f4..e40d60a1a 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionBerserker.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionBerserker.cs @@ -1,72 +1,72 @@ -using Server.Items; - -namespace Server.Factions -{ - public class FactionBerserker : BaseFactionGuard - { - [Constructible] - public FactionBerserker() : base("the berserker") - { - GenerateBody(false, false); - - SetStr(126, 150); - SetDex(61, 85); - SetInt(81, 95); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 30, 50); - SetResistance(ResistanceType.Fire, 30, 50); - SetResistance(ResistanceType.Cold, 30, 50); - SetResistance(ResistanceType.Energy, 30, 50); - SetResistance(ResistanceType.Poison, 30, 50); - - VirtualArmor = 24; - - SetSkill(SkillName.Swords, 100.0, 110.0); - SetSkill(SkillName.Wrestling, 100.0, 110.0); - SetSkill(SkillName.Tactics, 100.0, 110.0); - SetSkill(SkillName.MagicResist, 100.0, 110.0); - SetSkill(SkillName.Healing, 100.0, 110.0); - SetSkill(SkillName.Anatomy, 100.0, 110.0); - - SetSkill(SkillName.Magery, 100.0, 110.0); - SetSkill(SkillName.EvalInt, 100.0, 110.0); - SetSkill(SkillName.Meditation, 100.0, 110.0); - - AddItem(Immovable(Rehued(new BodySash(), 1645))); - AddItem(Immovable(Rehued(new Kilt(), 1645))); - AddItem(Immovable(Rehued(new Sandals(), 1645))); - AddItem(Newbied(new DoubleAxe())); - - HairItemID = 0x2047; // Afro - HairHue = 0x29; - - FacialHairItemID = 0x204B; // Medium Short Beard - FacialHairHue = 0x29; - - PackItem(new Bandage(Utility.RandomMinMax(30, 40))); - PackStrongPotions(6, 12); - } - - public FactionBerserker(Serial serial) : base(serial) - { - } - - public override GuardAI GuardAI => GuardAI.Melee | GuardAI.Curse | GuardAI.Bless; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; + +namespace Server.Factions +{ + public class FactionBerserker : BaseFactionGuard + { + [Constructible] + public FactionBerserker() : base("the berserker") + { + GenerateBody(false, false); + + SetStr(126, 150); + SetDex(61, 85); + SetInt(81, 95); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 30, 50); + SetResistance(ResistanceType.Fire, 30, 50); + SetResistance(ResistanceType.Cold, 30, 50); + SetResistance(ResistanceType.Energy, 30, 50); + SetResistance(ResistanceType.Poison, 30, 50); + + VirtualArmor = 24; + + SetSkill(SkillName.Swords, 100.0, 110.0); + SetSkill(SkillName.Wrestling, 100.0, 110.0); + SetSkill(SkillName.Tactics, 100.0, 110.0); + SetSkill(SkillName.MagicResist, 100.0, 110.0); + SetSkill(SkillName.Healing, 100.0, 110.0); + SetSkill(SkillName.Anatomy, 100.0, 110.0); + + SetSkill(SkillName.Magery, 100.0, 110.0); + SetSkill(SkillName.EvalInt, 100.0, 110.0); + SetSkill(SkillName.Meditation, 100.0, 110.0); + + AddItem(Immovable(Rehued(new BodySash(), 1645))); + AddItem(Immovable(Rehued(new Kilt(), 1645))); + AddItem(Immovable(Rehued(new Sandals(), 1645))); + AddItem(Newbied(new DoubleAxe())); + + HairItemID = 0x2047; // Afro + HairHue = 0x29; + + FacialHairItemID = 0x204B; // Medium Short Beard + FacialHairHue = 0x29; + + PackItem(new Bandage(Utility.RandomMinMax(30, 40))); + PackStrongPotions(6, 12); + } + + public FactionBerserker(Serial serial) : base(serial) + { + } + + public override GuardAI GuardAI => GuardAI.Melee | GuardAI.Curse | GuardAI.Bless; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionDeathKnight.cs b/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionDeathKnight.cs index 7c9c42514..37b3b4e2e 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionDeathKnight.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionDeathKnight.cs @@ -1,68 +1,68 @@ -using Server.Items; - -namespace Server.Factions -{ - public class FactionDeathKnight : BaseFactionGuard - { - [Constructible] - public FactionDeathKnight() : base("the death knight") - { - GenerateBody(false, false); - Hue = 1; - - SetStr(126, 150); - SetDex(61, 85); - SetInt(81, 95); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 30, 50); - SetResistance(ResistanceType.Fire, 30, 50); - SetResistance(ResistanceType.Cold, 30, 50); - SetResistance(ResistanceType.Energy, 30, 50); - SetResistance(ResistanceType.Poison, 30, 50); - - VirtualArmor = 24; - - SetSkill(SkillName.Swords, 100.0, 110.0); - SetSkill(SkillName.Wrestling, 100.0, 110.0); - SetSkill(SkillName.Tactics, 100.0, 110.0); - SetSkill(SkillName.MagicResist, 100.0, 110.0); - SetSkill(SkillName.Healing, 100.0, 110.0); - SetSkill(SkillName.Anatomy, 100.0, 110.0); - - SetSkill(SkillName.Magery, 100.0, 110.0); - SetSkill(SkillName.EvalInt, 100.0, 110.0); - SetSkill(SkillName.Meditation, 100.0, 110.0); - - Item shroud = new Item(0x204E); - shroud.Layer = Layer.OuterTorso; - - AddItem(Immovable(Rehued(shroud, 1109))); - AddItem(Newbied(Rehued(new ExecutionersAxe(), 2211))); - - PackItem(new Bandage(Utility.RandomMinMax(30, 40))); - PackStrongPotions(6, 12); - } - - public FactionDeathKnight(Serial serial) : base(serial) - { - } - - public override GuardAI GuardAI => GuardAI.Melee | GuardAI.Curse | GuardAI.Bless; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; + +namespace Server.Factions +{ + public class FactionDeathKnight : BaseFactionGuard + { + [Constructible] + public FactionDeathKnight() : base("the death knight") + { + GenerateBody(false, false); + Hue = 1; + + SetStr(126, 150); + SetDex(61, 85); + SetInt(81, 95); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 30, 50); + SetResistance(ResistanceType.Fire, 30, 50); + SetResistance(ResistanceType.Cold, 30, 50); + SetResistance(ResistanceType.Energy, 30, 50); + SetResistance(ResistanceType.Poison, 30, 50); + + VirtualArmor = 24; + + SetSkill(SkillName.Swords, 100.0, 110.0); + SetSkill(SkillName.Wrestling, 100.0, 110.0); + SetSkill(SkillName.Tactics, 100.0, 110.0); + SetSkill(SkillName.MagicResist, 100.0, 110.0); + SetSkill(SkillName.Healing, 100.0, 110.0); + SetSkill(SkillName.Anatomy, 100.0, 110.0); + + SetSkill(SkillName.Magery, 100.0, 110.0); + SetSkill(SkillName.EvalInt, 100.0, 110.0); + SetSkill(SkillName.Meditation, 100.0, 110.0); + + var shroud = new Item(0x204E); + shroud.Layer = Layer.OuterTorso; + + AddItem(Immovable(Rehued(shroud, 1109))); + AddItem(Newbied(Rehued(new ExecutionersAxe(), 2211))); + + PackItem(new Bandage(Utility.RandomMinMax(30, 40))); + PackStrongPotions(6, 12); + } + + public FactionDeathKnight(Serial serial) : base(serial) + { + } + + public override GuardAI GuardAI => GuardAI.Melee | GuardAI.Curse | GuardAI.Bless; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionDragoon.cs b/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionDragoon.cs index b10015e69..3811c675f 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionDragoon.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionDragoon.cs @@ -1,72 +1,72 @@ -using Server.Items; - -namespace Server.Factions -{ - public class FactionDragoon : BaseFactionGuard - { - [Constructible] - public FactionDragoon() : base("the dragoon") - { - GenerateBody(false, false); - - SetStr(151, 175); - SetDex(61, 85); - SetInt(151, 175); - - SetResistance(ResistanceType.Physical, 40, 60); - SetResistance(ResistanceType.Fire, 40, 60); - SetResistance(ResistanceType.Cold, 40, 60); - SetResistance(ResistanceType.Energy, 40, 60); - SetResistance(ResistanceType.Poison, 40, 60); - - VirtualArmor = 32; - - SetSkill(SkillName.Macing, 110.0, 120.0); - SetSkill(SkillName.Wrestling, 110.0, 120.0); - SetSkill(SkillName.Tactics, 110.0, 120.0); - SetSkill(SkillName.MagicResist, 110.0, 120.0); - SetSkill(SkillName.Healing, 110.0, 120.0); - SetSkill(SkillName.Anatomy, 110.0, 120.0); - - SetSkill(SkillName.Magery, 110.0, 120.0); - SetSkill(SkillName.EvalInt, 110.0, 120.0); - SetSkill(SkillName.Meditation, 110.0, 120.0); - - AddItem(Immovable(Rehued(new Cloak(), 1645))); - - AddItem(Immovable(Rehued(new PlateChest(), 1645))); - AddItem(Immovable(Rehued(new PlateLegs(), 1109))); - AddItem(Immovable(Rehued(new PlateArms(), 1109))); - AddItem(Immovable(Rehued(new PlateGloves(), 1109))); - AddItem(Immovable(Rehued(new PlateGorget(), 1109))); - AddItem(Immovable(Rehued(new PlateHelm(), 1109))); - - AddItem(Newbied(new WarHammer())); - - AddItem(Immovable(Rehued(new VirtualMountItem(this), 1109))); - - PackItem(new Bandage(Utility.RandomMinMax(30, 40))); - PackStrongPotions(6, 12); - } - - public FactionDragoon(Serial serial) : base(serial) - { - } - - public override GuardAI GuardAI => GuardAI.Magic | GuardAI.Melee | GuardAI.Smart | GuardAI.Bless | GuardAI.Curse; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; + +namespace Server.Factions +{ + public class FactionDragoon : BaseFactionGuard + { + [Constructible] + public FactionDragoon() : base("the dragoon") + { + GenerateBody(false, false); + + SetStr(151, 175); + SetDex(61, 85); + SetInt(151, 175); + + SetResistance(ResistanceType.Physical, 40, 60); + SetResistance(ResistanceType.Fire, 40, 60); + SetResistance(ResistanceType.Cold, 40, 60); + SetResistance(ResistanceType.Energy, 40, 60); + SetResistance(ResistanceType.Poison, 40, 60); + + VirtualArmor = 32; + + SetSkill(SkillName.Macing, 110.0, 120.0); + SetSkill(SkillName.Wrestling, 110.0, 120.0); + SetSkill(SkillName.Tactics, 110.0, 120.0); + SetSkill(SkillName.MagicResist, 110.0, 120.0); + SetSkill(SkillName.Healing, 110.0, 120.0); + SetSkill(SkillName.Anatomy, 110.0, 120.0); + + SetSkill(SkillName.Magery, 110.0, 120.0); + SetSkill(SkillName.EvalInt, 110.0, 120.0); + SetSkill(SkillName.Meditation, 110.0, 120.0); + + AddItem(Immovable(Rehued(new Cloak(), 1645))); + + AddItem(Immovable(Rehued(new PlateChest(), 1645))); + AddItem(Immovable(Rehued(new PlateLegs(), 1109))); + AddItem(Immovable(Rehued(new PlateArms(), 1109))); + AddItem(Immovable(Rehued(new PlateGloves(), 1109))); + AddItem(Immovable(Rehued(new PlateGorget(), 1109))); + AddItem(Immovable(Rehued(new PlateHelm(), 1109))); + + AddItem(Newbied(new WarHammer())); + + AddItem(Immovable(Rehued(new VirtualMountItem(this), 1109))); + + PackItem(new Bandage(Utility.RandomMinMax(30, 40))); + PackStrongPotions(6, 12); + } + + public FactionDragoon(Serial serial) : base(serial) + { + } + + public override GuardAI GuardAI => GuardAI.Magic | GuardAI.Melee | GuardAI.Smart | GuardAI.Bless | GuardAI.Curse; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionHenchman.cs b/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionHenchman.cs index 77a1d87ef..aecaf84af 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionHenchman.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionHenchman.cs @@ -1,65 +1,65 @@ -using Server.Items; - -namespace Server.Factions -{ - public class FactionHenchman : BaseFactionGuard - { - [Constructible] - public FactionHenchman() : base("the henchman") - { - GenerateBody(false, true); - - SetStr(91, 115); - SetDex(61, 85); - SetInt(81, 95); - - SetDamage(10, 14); - - SetResistance(ResistanceType.Physical, 10, 30); - SetResistance(ResistanceType.Fire, 10, 30); - SetResistance(ResistanceType.Cold, 10, 30); - SetResistance(ResistanceType.Energy, 10, 30); - SetResistance(ResistanceType.Poison, 10, 30); - - VirtualArmor = 8; - - SetSkill(SkillName.Fencing, 80.0, 90.0); - SetSkill(SkillName.Wrestling, 80.0, 90.0); - SetSkill(SkillName.Tactics, 80.0, 90.0); - SetSkill(SkillName.MagicResist, 80.0, 90.0); - SetSkill(SkillName.Healing, 80.0, 90.0); - SetSkill(SkillName.Anatomy, 80.0, 90.0); - - AddItem(new StuddedChest()); - AddItem(new StuddedLegs()); - AddItem(new StuddedArms()); - AddItem(new StuddedGloves()); - AddItem(new StuddedGorget()); - AddItem(new Boots()); - AddItem(Newbied(new Spear())); - - PackItem(new Bandage(Utility.RandomMinMax(10, 20))); - PackWeakPotions(1, 4); - } - - public FactionHenchman(Serial serial) : base(serial) - { - } - - public override GuardAI GuardAI => GuardAI.Melee; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; + +namespace Server.Factions +{ + public class FactionHenchman : BaseFactionGuard + { + [Constructible] + public FactionHenchman() : base("the henchman") + { + GenerateBody(false, true); + + SetStr(91, 115); + SetDex(61, 85); + SetInt(81, 95); + + SetDamage(10, 14); + + SetResistance(ResistanceType.Physical, 10, 30); + SetResistance(ResistanceType.Fire, 10, 30); + SetResistance(ResistanceType.Cold, 10, 30); + SetResistance(ResistanceType.Energy, 10, 30); + SetResistance(ResistanceType.Poison, 10, 30); + + VirtualArmor = 8; + + SetSkill(SkillName.Fencing, 80.0, 90.0); + SetSkill(SkillName.Wrestling, 80.0, 90.0); + SetSkill(SkillName.Tactics, 80.0, 90.0); + SetSkill(SkillName.MagicResist, 80.0, 90.0); + SetSkill(SkillName.Healing, 80.0, 90.0); + SetSkill(SkillName.Anatomy, 80.0, 90.0); + + AddItem(new StuddedChest()); + AddItem(new StuddedLegs()); + AddItem(new StuddedArms()); + AddItem(new StuddedGloves()); + AddItem(new StuddedGorget()); + AddItem(new Boots()); + AddItem(Newbied(new Spear())); + + PackItem(new Bandage(Utility.RandomMinMax(10, 20))); + PackWeakPotions(1, 4); + } + + public FactionHenchman(Serial serial) : base(serial) + { + } + + public override GuardAI GuardAI => GuardAI.Melee; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionKnight.cs b/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionKnight.cs index 08e0d3bb2..e193bcb3d 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionKnight.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionKnight.cs @@ -1,73 +1,73 @@ -using Server.Items; - -namespace Server.Factions -{ - public class FactionKnight : BaseFactionGuard - { - [Constructible] - public FactionKnight() : base("the knight") - { - GenerateBody(false, false); - - SetStr(126, 150); - SetDex(61, 85); - SetInt(81, 95); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 30, 50); - SetResistance(ResistanceType.Fire, 30, 50); - SetResistance(ResistanceType.Cold, 30, 50); - SetResistance(ResistanceType.Energy, 30, 50); - SetResistance(ResistanceType.Poison, 30, 50); - - VirtualArmor = 24; - - SetSkill(SkillName.Swords, 100.0, 110.0); - SetSkill(SkillName.Wrestling, 100.0, 110.0); - SetSkill(SkillName.Tactics, 100.0, 110.0); - SetSkill(SkillName.MagicResist, 100.0, 110.0); - SetSkill(SkillName.Healing, 100.0, 110.0); - SetSkill(SkillName.Anatomy, 100.0, 110.0); - - SetSkill(SkillName.Magery, 100.0, 110.0); - SetSkill(SkillName.EvalInt, 100.0, 110.0); - SetSkill(SkillName.Meditation, 100.0, 110.0); - - AddItem(Immovable(Rehued(new ChainChest(), 2125))); - AddItem(Immovable(Rehued(new ChainLegs(), 2125))); - AddItem(Immovable(Rehued(new ChainCoif(), 2125))); - AddItem(Immovable(Rehued(new PlateArms(), 2125))); - AddItem(Immovable(Rehued(new PlateGloves(), 2125))); - - AddItem(Immovable(Rehued(new BodySash(), 1254))); - AddItem(Immovable(Rehued(new Kilt(), 1254))); - AddItem(Immovable(Rehued(new Sandals(), 1254))); - - AddItem(Newbied(new Bardiche())); - - PackItem(new Bandage(Utility.RandomMinMax(30, 40))); - PackStrongPotions(6, 12); - } - - public FactionKnight(Serial serial) : base(serial) - { - } - - public override GuardAI GuardAI => GuardAI.Magic | GuardAI.Melee | GuardAI.Smart | GuardAI.Curse | GuardAI.Bless; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; + +namespace Server.Factions +{ + public class FactionKnight : BaseFactionGuard + { + [Constructible] + public FactionKnight() : base("the knight") + { + GenerateBody(false, false); + + SetStr(126, 150); + SetDex(61, 85); + SetInt(81, 95); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 30, 50); + SetResistance(ResistanceType.Fire, 30, 50); + SetResistance(ResistanceType.Cold, 30, 50); + SetResistance(ResistanceType.Energy, 30, 50); + SetResistance(ResistanceType.Poison, 30, 50); + + VirtualArmor = 24; + + SetSkill(SkillName.Swords, 100.0, 110.0); + SetSkill(SkillName.Wrestling, 100.0, 110.0); + SetSkill(SkillName.Tactics, 100.0, 110.0); + SetSkill(SkillName.MagicResist, 100.0, 110.0); + SetSkill(SkillName.Healing, 100.0, 110.0); + SetSkill(SkillName.Anatomy, 100.0, 110.0); + + SetSkill(SkillName.Magery, 100.0, 110.0); + SetSkill(SkillName.EvalInt, 100.0, 110.0); + SetSkill(SkillName.Meditation, 100.0, 110.0); + + AddItem(Immovable(Rehued(new ChainChest(), 2125))); + AddItem(Immovable(Rehued(new ChainLegs(), 2125))); + AddItem(Immovable(Rehued(new ChainCoif(), 2125))); + AddItem(Immovable(Rehued(new PlateArms(), 2125))); + AddItem(Immovable(Rehued(new PlateGloves(), 2125))); + + AddItem(Immovable(Rehued(new BodySash(), 1254))); + AddItem(Immovable(Rehued(new Kilt(), 1254))); + AddItem(Immovable(Rehued(new Sandals(), 1254))); + + AddItem(Newbied(new Bardiche())); + + PackItem(new Bandage(Utility.RandomMinMax(30, 40))); + PackStrongPotions(6, 12); + } + + public FactionKnight(Serial serial) : base(serial) + { + } + + public override GuardAI GuardAI => GuardAI.Magic | GuardAI.Melee | GuardAI.Smart | GuardAI.Curse | GuardAI.Bless; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionMercenary.cs b/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionMercenary.cs index 51c2139aa..b48221677 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionMercenary.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionMercenary.cs @@ -1,63 +1,63 @@ -using Server.Items; - -namespace Server.Factions -{ - public class FactionMercenary : BaseFactionGuard - { - [Constructible] - public FactionMercenary() : base("the mercenary") - { - GenerateBody(false, true); - - SetStr(116, 125); - SetDex(61, 85); - SetInt(81, 95); - - SetResistance(ResistanceType.Physical, 20, 40); - SetResistance(ResistanceType.Fire, 20, 40); - SetResistance(ResistanceType.Cold, 20, 40); - SetResistance(ResistanceType.Energy, 20, 40); - SetResistance(ResistanceType.Poison, 20, 40); - - VirtualArmor = 16; - - SetSkill(SkillName.Fencing, 90.0, 100.0); - SetSkill(SkillName.Wrestling, 90.0, 100.0); - SetSkill(SkillName.Tactics, 90.0, 100.0); - SetSkill(SkillName.MagicResist, 90.0, 100.0); - SetSkill(SkillName.Healing, 90.0, 100.0); - SetSkill(SkillName.Anatomy, 90.0, 100.0); - - AddItem(new ChainChest()); - AddItem(new ChainLegs()); - AddItem(new RingmailArms()); - AddItem(new RingmailGloves()); - AddItem(new ChainCoif()); - AddItem(new Boots()); - AddItem(Newbied(new ShortSpear())); - - PackItem(new Bandage(Utility.RandomMinMax(20, 30))); - PackStrongPotions(3, 8); - } - - public FactionMercenary(Serial serial) : base(serial) - { - } - - public override GuardAI GuardAI => GuardAI.Melee | GuardAI.Smart; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; + +namespace Server.Factions +{ + public class FactionMercenary : BaseFactionGuard + { + [Constructible] + public FactionMercenary() : base("the mercenary") + { + GenerateBody(false, true); + + SetStr(116, 125); + SetDex(61, 85); + SetInt(81, 95); + + SetResistance(ResistanceType.Physical, 20, 40); + SetResistance(ResistanceType.Fire, 20, 40); + SetResistance(ResistanceType.Cold, 20, 40); + SetResistance(ResistanceType.Energy, 20, 40); + SetResistance(ResistanceType.Poison, 20, 40); + + VirtualArmor = 16; + + SetSkill(SkillName.Fencing, 90.0, 100.0); + SetSkill(SkillName.Wrestling, 90.0, 100.0); + SetSkill(SkillName.Tactics, 90.0, 100.0); + SetSkill(SkillName.MagicResist, 90.0, 100.0); + SetSkill(SkillName.Healing, 90.0, 100.0); + SetSkill(SkillName.Anatomy, 90.0, 100.0); + + AddItem(new ChainChest()); + AddItem(new ChainLegs()); + AddItem(new RingmailArms()); + AddItem(new RingmailGloves()); + AddItem(new ChainCoif()); + AddItem(new Boots()); + AddItem(Newbied(new ShortSpear())); + + PackItem(new Bandage(Utility.RandomMinMax(20, 30))); + PackStrongPotions(3, 8); + } + + public FactionMercenary(Serial serial) : base(serial) + { + } + + public override GuardAI GuardAI => GuardAI.Melee | GuardAI.Smart; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionNecromancer.cs b/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionNecromancer.cs index efc85a9b7..37d718e7e 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionNecromancer.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionNecromancer.cs @@ -1,66 +1,66 @@ -using Server.Items; - -namespace Server.Factions -{ - public class FactionNecromancer : BaseFactionGuard - { - [Constructible] - public FactionNecromancer() : base("the necromancer") - { - GenerateBody(false, false); - Hue = 1; - - SetStr(151, 175); - SetDex(61, 85); - SetInt(151, 175); - - SetResistance(ResistanceType.Physical, 40, 60); - SetResistance(ResistanceType.Fire, 40, 60); - SetResistance(ResistanceType.Cold, 40, 60); - SetResistance(ResistanceType.Energy, 40, 60); - SetResistance(ResistanceType.Poison, 40, 60); - - VirtualArmor = 32; - - SetSkill(SkillName.Macing, 110.0, 120.0); - SetSkill(SkillName.Wrestling, 110.0, 120.0); - SetSkill(SkillName.Tactics, 110.0, 120.0); - SetSkill(SkillName.MagicResist, 110.0, 120.0); - SetSkill(SkillName.Healing, 110.0, 120.0); - SetSkill(SkillName.Anatomy, 110.0, 120.0); - - SetSkill(SkillName.Magery, 110.0, 120.0); - SetSkill(SkillName.EvalInt, 110.0, 120.0); - SetSkill(SkillName.Meditation, 110.0, 120.0); - - Item shroud = new Item(0x204E); - shroud.Layer = Layer.OuterTorso; - - AddItem(Immovable(Rehued(shroud, 1109))); - AddItem(Newbied(Rehued(new GnarledStaff(), 2211))); - - PackItem(new Bandage(Utility.RandomMinMax(30, 40))); - PackStrongPotions(6, 12); - } - - public FactionNecromancer(Serial serial) : base(serial) - { - } - - public override GuardAI GuardAI => GuardAI.Magic | GuardAI.Smart | GuardAI.Bless | GuardAI.Curse; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; + +namespace Server.Factions +{ + public class FactionNecromancer : BaseFactionGuard + { + [Constructible] + public FactionNecromancer() : base("the necromancer") + { + GenerateBody(false, false); + Hue = 1; + + SetStr(151, 175); + SetDex(61, 85); + SetInt(151, 175); + + SetResistance(ResistanceType.Physical, 40, 60); + SetResistance(ResistanceType.Fire, 40, 60); + SetResistance(ResistanceType.Cold, 40, 60); + SetResistance(ResistanceType.Energy, 40, 60); + SetResistance(ResistanceType.Poison, 40, 60); + + VirtualArmor = 32; + + SetSkill(SkillName.Macing, 110.0, 120.0); + SetSkill(SkillName.Wrestling, 110.0, 120.0); + SetSkill(SkillName.Tactics, 110.0, 120.0); + SetSkill(SkillName.MagicResist, 110.0, 120.0); + SetSkill(SkillName.Healing, 110.0, 120.0); + SetSkill(SkillName.Anatomy, 110.0, 120.0); + + SetSkill(SkillName.Magery, 110.0, 120.0); + SetSkill(SkillName.EvalInt, 110.0, 120.0); + SetSkill(SkillName.Meditation, 110.0, 120.0); + + var shroud = new Item(0x204E); + shroud.Layer = Layer.OuterTorso; + + AddItem(Immovable(Rehued(shroud, 1109))); + AddItem(Newbied(Rehued(new GnarledStaff(), 2211))); + + PackItem(new Bandage(Utility.RandomMinMax(30, 40))); + PackStrongPotions(6, 12); + } + + public FactionNecromancer(Serial serial) : base(serial) + { + } + + public override GuardAI GuardAI => GuardAI.Magic | GuardAI.Smart | GuardAI.Bless | GuardAI.Curse; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionPaladin.cs b/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionPaladin.cs index 27f72aa1d..b74f74b7e 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionPaladin.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionPaladin.cs @@ -1,73 +1,73 @@ -using Server.Items; - -namespace Server.Factions -{ - public class FactionPaladin : BaseFactionGuard - { - [Constructible] - public FactionPaladin() : base("the paladin") - { - GenerateBody(false, false); - - SetStr(151, 175); - SetDex(61, 85); - SetInt(81, 95); - - SetResistance(ResistanceType.Physical, 40, 60); - SetResistance(ResistanceType.Fire, 40, 60); - SetResistance(ResistanceType.Cold, 40, 60); - SetResistance(ResistanceType.Energy, 40, 60); - SetResistance(ResistanceType.Poison, 40, 60); - - VirtualArmor = 32; - - SetSkill(SkillName.Swords, 110.0, 120.0); - SetSkill(SkillName.Wrestling, 110.0, 120.0); - SetSkill(SkillName.Tactics, 110.0, 120.0); - SetSkill(SkillName.MagicResist, 110.0, 120.0); - SetSkill(SkillName.Healing, 110.0, 120.0); - SetSkill(SkillName.Anatomy, 110.0, 120.0); - - SetSkill(SkillName.Magery, 110.0, 120.0); - SetSkill(SkillName.EvalInt, 110.0, 120.0); - SetSkill(SkillName.Meditation, 110.0, 120.0); - - AddItem(Immovable(Rehued(new PlateChest(), 2125))); - AddItem(Immovable(Rehued(new PlateLegs(), 2125))); - AddItem(Immovable(Rehued(new PlateHelm(), 2125))); - AddItem(Immovable(Rehued(new PlateGorget(), 2125))); - AddItem(Immovable(Rehued(new PlateArms(), 2125))); - AddItem(Immovable(Rehued(new PlateGloves(), 2125))); - - AddItem(Immovable(Rehued(new BodySash(), 1254))); - AddItem(Immovable(Rehued(new Cloak(), 1254))); - - AddItem(Newbied(new Halberd())); - - AddItem(Immovable(Rehued(new VirtualMountItem(this), 1254))); - - PackItem(new Bandage(Utility.RandomMinMax(30, 40))); - PackStrongPotions(6, 12); - } - - public FactionPaladin(Serial serial) : base(serial) - { - } - - public override GuardAI GuardAI => GuardAI.Magic | GuardAI.Melee | GuardAI.Smart | GuardAI.Curse | GuardAI.Bless; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; + +namespace Server.Factions +{ + public class FactionPaladin : BaseFactionGuard + { + [Constructible] + public FactionPaladin() : base("the paladin") + { + GenerateBody(false, false); + + SetStr(151, 175); + SetDex(61, 85); + SetInt(81, 95); + + SetResistance(ResistanceType.Physical, 40, 60); + SetResistance(ResistanceType.Fire, 40, 60); + SetResistance(ResistanceType.Cold, 40, 60); + SetResistance(ResistanceType.Energy, 40, 60); + SetResistance(ResistanceType.Poison, 40, 60); + + VirtualArmor = 32; + + SetSkill(SkillName.Swords, 110.0, 120.0); + SetSkill(SkillName.Wrestling, 110.0, 120.0); + SetSkill(SkillName.Tactics, 110.0, 120.0); + SetSkill(SkillName.MagicResist, 110.0, 120.0); + SetSkill(SkillName.Healing, 110.0, 120.0); + SetSkill(SkillName.Anatomy, 110.0, 120.0); + + SetSkill(SkillName.Magery, 110.0, 120.0); + SetSkill(SkillName.EvalInt, 110.0, 120.0); + SetSkill(SkillName.Meditation, 110.0, 120.0); + + AddItem(Immovable(Rehued(new PlateChest(), 2125))); + AddItem(Immovable(Rehued(new PlateLegs(), 2125))); + AddItem(Immovable(Rehued(new PlateHelm(), 2125))); + AddItem(Immovable(Rehued(new PlateGorget(), 2125))); + AddItem(Immovable(Rehued(new PlateArms(), 2125))); + AddItem(Immovable(Rehued(new PlateGloves(), 2125))); + + AddItem(Immovable(Rehued(new BodySash(), 1254))); + AddItem(Immovable(Rehued(new Cloak(), 1254))); + + AddItem(Newbied(new Halberd())); + + AddItem(Immovable(Rehued(new VirtualMountItem(this), 1254))); + + PackItem(new Bandage(Utility.RandomMinMax(30, 40))); + PackStrongPotions(6, 12); + } + + public FactionPaladin(Serial serial) : base(serial) + { + } + + public override GuardAI GuardAI => GuardAI.Magic | GuardAI.Melee | GuardAI.Smart | GuardAI.Curse | GuardAI.Bless; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionSorceress.cs b/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionSorceress.cs index 97fd86d28..ae80882a4 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionSorceress.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionSorceress.cs @@ -1,70 +1,70 @@ -using Server.Items; - -namespace Server.Factions -{ - public class FactionSorceress : BaseFactionGuard - { - [Constructible] - public FactionSorceress() : base("the sorceress") - { - GenerateBody(true, false); - - SetStr(126, 150); - SetDex(61, 85); - SetInt(126, 150); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 30, 50); - SetResistance(ResistanceType.Fire, 30, 50); - SetResistance(ResistanceType.Cold, 30, 50); - SetResistance(ResistanceType.Energy, 30, 50); - SetResistance(ResistanceType.Poison, 30, 50); - - VirtualArmor = 24; - - SetSkill(SkillName.Macing, 100.0, 110.0); - SetSkill(SkillName.Wrestling, 100.0, 110.0); - SetSkill(SkillName.Tactics, 100.0, 110.0); - SetSkill(SkillName.MagicResist, 100.0, 110.0); - SetSkill(SkillName.Healing, 100.0, 110.0); - SetSkill(SkillName.Anatomy, 100.0, 110.0); - - SetSkill(SkillName.Magery, 100.0, 110.0); - SetSkill(SkillName.EvalInt, 100.0, 110.0); - SetSkill(SkillName.Meditation, 100.0, 110.0); - - AddItem(Immovable(Rehued(new WizardsHat(), 1325))); - AddItem(Immovable(Rehued(new Sandals(), 1325))); - AddItem(Immovable(Rehued(new LeatherGorget(), 1325))); - AddItem(Immovable(Rehued(new LeatherGloves(), 1325))); - AddItem(Immovable(Rehued(new LeatherLegs(), 1325))); - AddItem(Immovable(Rehued(new Skirt(), 1325))); - AddItem(Immovable(Rehued(new FemaleLeatherChest(), 1325))); - AddItem(Newbied(Rehued(new QuarterStaff(), 1310))); - - PackItem(new Bandage(Utility.RandomMinMax(30, 40))); - PackStrongPotions(6, 12); - } - - public FactionSorceress(Serial serial) : base(serial) - { - } - - public override GuardAI GuardAI => GuardAI.Magic | GuardAI.Bless | GuardAI.Curse; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; + +namespace Server.Factions +{ + public class FactionSorceress : BaseFactionGuard + { + [Constructible] + public FactionSorceress() : base("the sorceress") + { + GenerateBody(true, false); + + SetStr(126, 150); + SetDex(61, 85); + SetInt(126, 150); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 30, 50); + SetResistance(ResistanceType.Fire, 30, 50); + SetResistance(ResistanceType.Cold, 30, 50); + SetResistance(ResistanceType.Energy, 30, 50); + SetResistance(ResistanceType.Poison, 30, 50); + + VirtualArmor = 24; + + SetSkill(SkillName.Macing, 100.0, 110.0); + SetSkill(SkillName.Wrestling, 100.0, 110.0); + SetSkill(SkillName.Tactics, 100.0, 110.0); + SetSkill(SkillName.MagicResist, 100.0, 110.0); + SetSkill(SkillName.Healing, 100.0, 110.0); + SetSkill(SkillName.Anatomy, 100.0, 110.0); + + SetSkill(SkillName.Magery, 100.0, 110.0); + SetSkill(SkillName.EvalInt, 100.0, 110.0); + SetSkill(SkillName.Meditation, 100.0, 110.0); + + AddItem(Immovable(Rehued(new WizardsHat(), 1325))); + AddItem(Immovable(Rehued(new Sandals(), 1325))); + AddItem(Immovable(Rehued(new LeatherGorget(), 1325))); + AddItem(Immovable(Rehued(new LeatherGloves(), 1325))); + AddItem(Immovable(Rehued(new LeatherLegs(), 1325))); + AddItem(Immovable(Rehued(new Skirt(), 1325))); + AddItem(Immovable(Rehued(new FemaleLeatherChest(), 1325))); + AddItem(Newbied(Rehued(new QuarterStaff(), 1310))); + + PackItem(new Bandage(Utility.RandomMinMax(30, 40))); + PackStrongPotions(6, 12); + } + + public FactionSorceress(Serial serial) : base(serial) + { + } + + public override GuardAI GuardAI => GuardAI.Magic | GuardAI.Bless | GuardAI.Curse; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionWizard.cs b/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionWizard.cs index e156f403d..21231dcca 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionWizard.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/Guards/Types/FactionWizard.cs @@ -1,67 +1,67 @@ -using Server.Items; - -namespace Server.Factions -{ - public class FactionWizard : BaseFactionGuard - { - [Constructible] - public FactionWizard() : base("the wizard") - { - GenerateBody(false, false); - - SetStr(151, 175); - SetDex(61, 85); - SetInt(151, 175); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 40, 60); - SetResistance(ResistanceType.Fire, 40, 60); - SetResistance(ResistanceType.Cold, 40, 60); - SetResistance(ResistanceType.Energy, 40, 60); - SetResistance(ResistanceType.Poison, 40, 60); - - VirtualArmor = 32; - - SetSkill(SkillName.Macing, 110.0, 120.0); - SetSkill(SkillName.Wrestling, 110.0, 120.0); - SetSkill(SkillName.Tactics, 110.0, 120.0); - SetSkill(SkillName.MagicResist, 110.0, 120.0); - SetSkill(SkillName.Healing, 110.0, 120.0); - SetSkill(SkillName.Anatomy, 110.0, 120.0); - - SetSkill(SkillName.Magery, 110.0, 120.0); - SetSkill(SkillName.EvalInt, 110.0, 120.0); - SetSkill(SkillName.Meditation, 110.0, 120.0); - - AddItem(Immovable(Rehued(new WizardsHat(), 1325))); - AddItem(Immovable(Rehued(new Sandals(), 1325))); - AddItem(Immovable(Rehued(new Robe(), 1310))); - AddItem(Immovable(Rehued(new LeatherGloves(), 1325))); - AddItem(Newbied(Rehued(new GnarledStaff(), 1310))); - - PackItem(new Bandage(Utility.RandomMinMax(30, 40))); - PackStrongPotions(6, 12); - } - - public FactionWizard(Serial serial) : base(serial) - { - } - - public override GuardAI GuardAI => GuardAI.Magic | GuardAI.Smart | GuardAI.Bless | GuardAI.Curse; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; + +namespace Server.Factions +{ + public class FactionWizard : BaseFactionGuard + { + [Constructible] + public FactionWizard() : base("the wizard") + { + GenerateBody(false, false); + + SetStr(151, 175); + SetDex(61, 85); + SetInt(151, 175); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 40, 60); + SetResistance(ResistanceType.Fire, 40, 60); + SetResistance(ResistanceType.Cold, 40, 60); + SetResistance(ResistanceType.Energy, 40, 60); + SetResistance(ResistanceType.Poison, 40, 60); + + VirtualArmor = 32; + + SetSkill(SkillName.Macing, 110.0, 120.0); + SetSkill(SkillName.Wrestling, 110.0, 120.0); + SetSkill(SkillName.Tactics, 110.0, 120.0); + SetSkill(SkillName.MagicResist, 110.0, 120.0); + SetSkill(SkillName.Healing, 110.0, 120.0); + SetSkill(SkillName.Anatomy, 110.0, 120.0); + + SetSkill(SkillName.Magery, 110.0, 120.0); + SetSkill(SkillName.EvalInt, 110.0, 120.0); + SetSkill(SkillName.Meditation, 110.0, 120.0); + + AddItem(Immovable(Rehued(new WizardsHat(), 1325))); + AddItem(Immovable(Rehued(new Sandals(), 1325))); + AddItem(Immovable(Rehued(new Robe(), 1310))); + AddItem(Immovable(Rehued(new LeatherGloves(), 1325))); + AddItem(Newbied(Rehued(new GnarledStaff(), 1310))); + + PackItem(new Bandage(Utility.RandomMinMax(30, 40))); + PackStrongPotions(6, 12); + } + + public FactionWizard(Serial serial) : base(serial) + { + } + + public override GuardAI GuardAI => GuardAI.Magic | GuardAI.Smart | GuardAI.Bless | GuardAI.Curse; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Mobiles/Vendors/BaseFactionVendor.cs b/Projects/UOContent/Engines/Factions/Mobiles/Vendors/BaseFactionVendor.cs index c3b157037..37d47264b 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/Vendors/BaseFactionVendor.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/Vendors/BaseFactionVendor.cs @@ -1,118 +1,118 @@ -using System.Collections.Generic; -using Server.Mobiles; - -namespace Server.Factions -{ - public abstract class BaseFactionVendor : BaseVendor - { - private Faction m_Faction; - private Town m_Town; - - public BaseFactionVendor(Town town, Faction faction, string title) : base(title) - { - Frozen = true; - CantWalk = true; - Female = false; - BodyValue = 400; - Name = NameList.RandomName("male"); - - RangeHome = 0; - - m_Town = town; - m_Faction = faction; - Register(); - } - - public BaseFactionVendor(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] - public Town Town - { - get => m_Town; - set - { - Unregister(); - m_Town = value; - Register(); - } - } - - [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] - public Faction Faction - { - get => m_Faction; - set - { - Unregister(); - m_Faction = value; - Register(); - } - } - - protected override List SBInfos { get; } = new List(); - - public void Register() - { - if (m_Town != null && m_Faction != null) - m_Town.RegisterVendor(this); - } - - public override bool OnMoveOver(Mobile m) - { - if (Core.ML) - return true; - - return base.OnMoveOver(m); - } - - public void Unregister() - { - m_Town?.UnregisterVendor(this); - } - - public override void InitSBInfo() - { - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - Unregister(); - } - - public override bool CheckVendorAccess(Mobile from) => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - Town.WriteReference(writer, m_Town); - Faction.WriteReference(writer, m_Faction); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Town = Town.ReadReference(reader); - m_Faction = Faction.ReadReference(reader); - Register(); - break; - } - } - - Frozen = true; - } - } -} \ No newline at end of file +using System.Collections.Generic; +using Server.Mobiles; + +namespace Server.Factions +{ + public abstract class BaseFactionVendor : BaseVendor + { + private Faction m_Faction; + private Town m_Town; + + public BaseFactionVendor(Town town, Faction faction, string title) : base(title) + { + Frozen = true; + CantWalk = true; + Female = false; + BodyValue = 400; + Name = NameList.RandomName("male"); + + RangeHome = 0; + + m_Town = town; + m_Faction = faction; + Register(); + } + + public BaseFactionVendor(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] + public Town Town + { + get => m_Town; + set + { + Unregister(); + m_Town = value; + Register(); + } + } + + [CommandProperty(AccessLevel.Counselor, AccessLevel.Administrator)] + public Faction Faction + { + get => m_Faction; + set + { + Unregister(); + m_Faction = value; + Register(); + } + } + + protected override List SBInfos { get; } = new List(); + + public void Register() + { + if (m_Town != null && m_Faction != null) + m_Town.RegisterVendor(this); + } + + public override bool OnMoveOver(Mobile m) + { + if (Core.ML) + return true; + + return base.OnMoveOver(m); + } + + public void Unregister() + { + m_Town?.UnregisterVendor(this); + } + + public override void InitSBInfo() + { + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + Unregister(); + } + + public override bool CheckVendorAccess(Mobile from) => true; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + Town.WriteReference(writer, m_Town); + Faction.WriteReference(writer, m_Faction); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Town = Town.ReadReference(reader); + m_Faction = Faction.ReadReference(reader); + Register(); + break; + } + } + + Frozen = true; + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionBoardVendor.cs b/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionBoardVendor.cs index 8e2722176..9af80bffe 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionBoardVendor.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionBoardVendor.cs @@ -1,65 +1,66 @@ -using System.Collections.Generic; -using Server.Items; -using Server.Mobiles; - -namespace Server.Factions -{ - public class FactionBoardVendor : BaseFactionVendor - { - public FactionBoardVendor(Town town, Faction faction) : base(town, faction, "the LumberMan") // NOTE: title inconsistant, as OSI - { - SetSkill(SkillName.Carpentry, 85.0, 100.0); - SetSkill(SkillName.Lumberjacking, 60.0, 83.0); - } - - public FactionBoardVendor(Serial serial) : base(serial) - { - } - - public override void InitSBInfo() - { - SBInfos.Add(new SBFactionBoard()); - } - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new HalfApron()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SBFactionBoard : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List - { - public InternalBuyInfo() - { - for (int i = 0; i < 5; ++i) - Add(new GenericBuyInfo(typeof(Board), 3, 20, 0x1BD7, 0)); - } - } - - public class InternalSellInfo : GenericSellInfo - { - } - } -} \ No newline at end of file +using System.Collections.Generic; +using Server.Items; +using Server.Mobiles; + +namespace Server.Factions +{ + public class FactionBoardVendor : BaseFactionVendor + { + public FactionBoardVendor(Town town, Faction faction) : + base(town, faction, "the LumberMan") // NOTE: title inconsistant, as OSI + { + SetSkill(SkillName.Carpentry, 85.0, 100.0); + SetSkill(SkillName.Lumberjacking, 60.0, 83.0); + } + + public FactionBoardVendor(Serial serial) : base(serial) + { + } + + public override void InitSBInfo() + { + SBInfos.Add(new SBFactionBoard()); + } + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new HalfApron()); + } + + 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 class SBFactionBoard : SBInfo + { + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); + + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + for (var i = 0; i < 5; ++i) + Add(new GenericBuyInfo(typeof(Board), 3, 20, 0x1BD7, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionBottleVendor.cs b/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionBottleVendor.cs index 315de7944..4dcb68b14 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionBottleVendor.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionBottleVendor.cs @@ -1,67 +1,67 @@ -using System.Collections.Generic; -using Server.Items; -using Server.Mobiles; - -namespace Server.Factions -{ - public class FactionBottleVendor : BaseFactionVendor - { - public FactionBottleVendor(Town town, Faction faction) : base(town, faction, "the Bottle Seller") - { - SetSkill(SkillName.Alchemy, 85.0, 100.0); - SetSkill(SkillName.TasteID, 65.0, 88.0); - } - - public FactionBottleVendor(Serial serial) : base(serial) - { - } - - public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Shoes : VendorShoeType.Sandals; - - public override void InitSBInfo() - { - SBInfos.Add(new SBFactionBottle()); - } - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new Robe(Utility.RandomPinkHue())); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SBFactionBottle : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List - { - public InternalBuyInfo() - { - for (int i = 0; i < 5; ++i) - Add(new GenericBuyInfo(typeof(Bottle), 5, 20, 0xF0E, 0)); - } - } - - public class InternalSellInfo : GenericSellInfo - { - } - } -} \ No newline at end of file +using System.Collections.Generic; +using Server.Items; +using Server.Mobiles; + +namespace Server.Factions +{ + public class FactionBottleVendor : BaseFactionVendor + { + public FactionBottleVendor(Town town, Faction faction) : base(town, faction, "the Bottle Seller") + { + SetSkill(SkillName.Alchemy, 85.0, 100.0); + SetSkill(SkillName.TasteID, 65.0, 88.0); + } + + public FactionBottleVendor(Serial serial) : base(serial) + { + } + + public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Shoes : VendorShoeType.Sandals; + + public override void InitSBInfo() + { + SBInfos.Add(new SBFactionBottle()); + } + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new Robe(Utility.RandomPinkHue())); + } + + 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 class SBFactionBottle : SBInfo + { + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); + + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + for (var i = 0; i < 5; ++i) + Add(new GenericBuyInfo(typeof(Bottle), 5, 20, 0xF0E, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionHorseVendor.cs b/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionHorseVendor.cs index f62366c83..feae0c653 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionHorseVendor.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionHorseVendor.cs @@ -1,69 +1,73 @@ -using System.Collections.Generic; -using Server.Items; -using Server.Mobiles; -using Server.Network; - -namespace Server.Factions -{ - public class FactionHorseVendor : BaseFactionVendor - { - public FactionHorseVendor(Town town, Faction faction) : base(town, faction, "the Horse Breeder") - { - SetSkill(SkillName.AnimalLore, 64.0, 100.0); - SetSkill(SkillName.AnimalTaming, 90.0, 100.0); - SetSkill(SkillName.Veterinary, 65.0, 88.0); - } - - public FactionHorseVendor(Serial serial) : base(serial) - { - } - - public override VendorShoeType ShoeType => Female ? VendorShoeType.ThighBoots : VendorShoeType.Boots; - - public override void InitSBInfo() - { - } - - public override int GetShoeHue() => 0; - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(Utility.RandomBool() ? new QuarterStaff() : (Item)new ShepherdsCrook()); - } - - public override void VendorBuy(Mobile from) - { - if (Faction == null || Faction.Find(from, true) != Faction) - PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1042201, - from.NetState); // You are not in my faction, I cannot sell you a horse! - else if (FactionGump.Exists(from)) - from.SendLocalizedMessage(1042160); // You already have a faction menu open. - else if (from is PlayerMobile mobile) - mobile.SendGump(new HorseBreederGump(mobile, Faction)); - } - - public override void VendorSell(Mobile from) - { - } - - public override bool OnBuyItems(Mobile buyer, List list) => false; - - public override bool OnSellItems(Mobile seller, List list) => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System.Collections.Generic; +using Server.Items; +using Server.Mobiles; +using Server.Network; + +namespace Server.Factions +{ + public class FactionHorseVendor : BaseFactionVendor + { + public FactionHorseVendor(Town town, Faction faction) : base(town, faction, "the Horse Breeder") + { + SetSkill(SkillName.AnimalLore, 64.0, 100.0); + SetSkill(SkillName.AnimalTaming, 90.0, 100.0); + SetSkill(SkillName.Veterinary, 65.0, 88.0); + } + + public FactionHorseVendor(Serial serial) : base(serial) + { + } + + public override VendorShoeType ShoeType => Female ? VendorShoeType.ThighBoots : VendorShoeType.Boots; + + public override void InitSBInfo() + { + } + + public override int GetShoeHue() => 0; + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(Utility.RandomBool() ? new QuarterStaff() : (Item)new ShepherdsCrook()); + } + + public override void VendorBuy(Mobile from) + { + if (Faction == null || Faction.Find(from, true) != Faction) + PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 1042201, + from.NetState + ); // You are not in my faction, I cannot sell you a horse! + else if (FactionGump.Exists(from)) + from.SendLocalizedMessage(1042160); // You already have a faction menu open. + else if (from is PlayerMobile mobile) + mobile.SendGump(new HorseBreederGump(mobile, Faction)); + } + + public override void VendorSell(Mobile from) + { + } + + public override bool OnBuyItems(Mobile buyer, List list) => false; + + public override bool OnSellItems(Mobile seller, List list) => 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionOreVendor.cs b/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionOreVendor.cs index bdaeac477..b2ffd9dd2 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionOreVendor.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionOreVendor.cs @@ -1,68 +1,68 @@ -using System.Collections.Generic; -using Server.Items; -using Server.Mobiles; - -namespace Server.Factions -{ - public class FactionOreVendor : BaseFactionVendor - { - public FactionOreVendor(Town town, Faction faction) : base(town, faction, "the Ore Man") - { - // NOTE: Skills verified - SetSkill(SkillName.Carpentry, 85.0, 100.0); - SetSkill(SkillName.Lumberjacking, 60.0, 83.0); - } - - public FactionOreVendor(Serial serial) : base(serial) - { - } - - public override void InitSBInfo() - { - SBInfos.Add(new SBFactionOre()); - } - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new HalfApron()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SBFactionOre : SBInfo - { - private static readonly object[] m_FixedSizeArgs = { true }; - - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List - { - public InternalBuyInfo() - { - for (int i = 0; i < 5; ++i) - Add(new GenericBuyInfo(typeof(IronOre), 16, 20, 0x19B8, 0, m_FixedSizeArgs)); - } - } - - public class InternalSellInfo : GenericSellInfo - { - } - } -} \ No newline at end of file +using System.Collections.Generic; +using Server.Items; +using Server.Mobiles; + +namespace Server.Factions +{ + public class FactionOreVendor : BaseFactionVendor + { + public FactionOreVendor(Town town, Faction faction) : base(town, faction, "the Ore Man") + { + // NOTE: Skills verified + SetSkill(SkillName.Carpentry, 85.0, 100.0); + SetSkill(SkillName.Lumberjacking, 60.0, 83.0); + } + + public FactionOreVendor(Serial serial) : base(serial) + { + } + + public override void InitSBInfo() + { + SBInfos.Add(new SBFactionOre()); + } + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new HalfApron()); + } + + 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 class SBFactionOre : SBInfo + { + private static readonly object[] m_FixedSizeArgs = { true }; + + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); + + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + for (var i = 0; i < 5; ++i) + Add(new GenericBuyInfo(typeof(IronOre), 16, 20, 0x19B8, 0, m_FixedSizeArgs)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + } + } +} diff --git a/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionReagentVendor.cs b/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionReagentVendor.cs index 0198a1f01..d593be05a 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionReagentVendor.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/Vendors/FactionReagentVendor.cs @@ -1,81 +1,81 @@ -using System.Collections.Generic; -using Server.Items; -using Server.Mobiles; - -namespace Server.Factions -{ - public class FactionReagentVendor : BaseFactionVendor - { - public FactionReagentVendor(Town town, Faction faction) : base(town, faction, "the Reagent Man") - { - SetSkill(SkillName.EvalInt, 65.0, 88.0); - SetSkill(SkillName.Inscribe, 60.0, 83.0); - SetSkill(SkillName.Magery, 64.0, 100.0); - SetSkill(SkillName.Meditation, 60.0, 83.0); - SetSkill(SkillName.MagicResist, 65.0, 88.0); - SetSkill(SkillName.Wrestling, 36.0, 68.0); - } - - public FactionReagentVendor(Serial serial) : base(serial) - { - } - - public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Shoes : VendorShoeType.Sandals; - - public override void InitSBInfo() - { - SBInfos.Add(new SBFactionReagent()); - } - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new Robe(Utility.RandomBlueHue())); - AddItem(new GnarledStaff()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SBFactionReagent : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List - { - public InternalBuyInfo() - { - for (int i = 0; i < 2; ++i) - { - Add(new GenericBuyInfo(typeof(BlackPearl), 5, 20, 0xF7A, 0)); - Add(new GenericBuyInfo(typeof(Bloodmoss), 5, 20, 0xF7B, 0)); - Add(new GenericBuyInfo(typeof(MandrakeRoot), 3, 20, 0xF86, 0)); - Add(new GenericBuyInfo(typeof(Garlic), 3, 20, 0xF84, 0)); - Add(new GenericBuyInfo(typeof(Ginseng), 3, 20, 0xF85, 0)); - Add(new GenericBuyInfo(typeof(Nightshade), 3, 20, 0xF88, 0)); - Add(new GenericBuyInfo(typeof(SpidersSilk), 3, 20, 0xF8D, 0)); - Add(new GenericBuyInfo(typeof(SulfurousAsh), 3, 20, 0xF8C, 0)); - } - } - } - - public class InternalSellInfo : GenericSellInfo - { - } - } -} \ No newline at end of file +using System.Collections.Generic; +using Server.Items; +using Server.Mobiles; + +namespace Server.Factions +{ + public class FactionReagentVendor : BaseFactionVendor + { + public FactionReagentVendor(Town town, Faction faction) : base(town, faction, "the Reagent Man") + { + SetSkill(SkillName.EvalInt, 65.0, 88.0); + SetSkill(SkillName.Inscribe, 60.0, 83.0); + SetSkill(SkillName.Magery, 64.0, 100.0); + SetSkill(SkillName.Meditation, 60.0, 83.0); + SetSkill(SkillName.MagicResist, 65.0, 88.0); + SetSkill(SkillName.Wrestling, 36.0, 68.0); + } + + public FactionReagentVendor(Serial serial) : base(serial) + { + } + + public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Shoes : VendorShoeType.Sandals; + + public override void InitSBInfo() + { + SBInfos.Add(new SBFactionReagent()); + } + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new Robe(Utility.RandomBlueHue())); + AddItem(new GnarledStaff()); + } + + 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 class SBFactionReagent : SBInfo + { + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); + + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + for (var i = 0; i < 2; ++i) + { + Add(new GenericBuyInfo(typeof(BlackPearl), 5, 20, 0xF7A, 0)); + Add(new GenericBuyInfo(typeof(Bloodmoss), 5, 20, 0xF7B, 0)); + Add(new GenericBuyInfo(typeof(MandrakeRoot), 3, 20, 0xF86, 0)); + Add(new GenericBuyInfo(typeof(Garlic), 3, 20, 0xF84, 0)); + Add(new GenericBuyInfo(typeof(Ginseng), 3, 20, 0xF85, 0)); + Add(new GenericBuyInfo(typeof(Nightshade), 3, 20, 0xF88, 0)); + Add(new GenericBuyInfo(typeof(SpidersSilk), 3, 20, 0xF8D, 0)); + Add(new GenericBuyInfo(typeof(SulfurousAsh), 3, 20, 0xF8C, 0)); + } + } + } + + public class InternalSellInfo : GenericSellInfo + { + } + } +} diff --git a/Projects/UOContent/Engines/Harvest/Core/BonusHarvestResource.cs b/Projects/UOContent/Engines/Harvest/Core/BonusHarvestResource.cs index ef92a20f9..ca7f95183 100644 --- a/Projects/UOContent/Engines/Harvest/Core/BonusHarvestResource.cs +++ b/Projects/UOContent/Engines/Harvest/Core/BonusHarvestResource.cs @@ -1,29 +1,29 @@ -using System; - -namespace Server.Engines.Harvest -{ - public class BonusHarvestResource - { - public BonusHarvestResource(double reqSkill, double chance, TextDefinition message, Type type) - { - ReqSkill = reqSkill; - - Chance = chance; - Type = type; - SuccessMessage = message; - } - - public Type Type { get; set; } - - public double ReqSkill { get; set; } - - public double Chance { get; set; } - - public TextDefinition SuccessMessage { get; } - - public void SendSuccessTo(Mobile m) - { - TextDefinition.SendMessageTo(m, SuccessMessage); - } - } -} \ No newline at end of file +using System; + +namespace Server.Engines.Harvest +{ + public class BonusHarvestResource + { + public BonusHarvestResource(double reqSkill, double chance, TextDefinition message, Type type) + { + ReqSkill = reqSkill; + + Chance = chance; + Type = type; + SuccessMessage = message; + } + + public Type Type { get; set; } + + public double ReqSkill { get; set; } + + public double Chance { get; set; } + + public TextDefinition SuccessMessage { get; } + + public void SendSuccessTo(Mobile m) + { + TextDefinition.SendMessageTo(m, SuccessMessage); + } + } +} diff --git a/Projects/UOContent/Engines/Harvest/Core/FurnitureAttribute.cs b/Projects/UOContent/Engines/Harvest/Core/FurnitureAttribute.cs index b421847bf..e37a4e5ae 100644 --- a/Projects/UOContent/Engines/Harvest/Core/FurnitureAttribute.cs +++ b/Projects/UOContent/Engines/Harvest/Core/FurnitureAttribute.cs @@ -1,10 +1,10 @@ -using System; - -namespace Server -{ - [AttributeUsage(AttributeTargets.Class)] - public class FurnitureAttribute : Attribute - { - public static bool Check(Item item) => item?.GetType().IsDefined(typeof(FurnitureAttribute), false) == true; - } -} +using System; + +namespace Server +{ + [AttributeUsage(AttributeTargets.Class)] + public class FurnitureAttribute : Attribute + { + public static bool Check(Item item) => item?.GetType().IsDefined(typeof(FurnitureAttribute), false) == true; + } +} diff --git a/Projects/UOContent/Engines/Harvest/Core/HarvestBank.cs b/Projects/UOContent/Engines/Harvest/Core/HarvestBank.cs index 7c80dff2f..1583c8955 100644 --- a/Projects/UOContent/Engines/Harvest/Core/HarvestBank.cs +++ b/Projects/UOContent/Engines/Harvest/Core/HarvestBank.cs @@ -1,91 +1,91 @@ -using System; - -namespace Server.Engines.Harvest -{ - public class HarvestBank - { - private int m_Current; - private readonly int m_Maximum; - private DateTime m_NextRespawn; - private HarvestVein m_Vein, m_DefaultVein; - - public HarvestBank(HarvestDefinition def, HarvestVein defaultVein) - { - m_Maximum = Utility.RandomMinMax(def.MinTotal, def.MaxTotal); - m_Current = m_Maximum; - m_DefaultVein = defaultVein; - m_Vein = m_DefaultVein; - - Definition = def; - } - - public HarvestDefinition Definition { get; } - - public int Current - { - get - { - CheckRespawn(); - return m_Current; - } - } - - public HarvestVein Vein - { - get - { - CheckRespawn(); - return m_Vein; - } - set => m_Vein = value; - } - - public HarvestVein DefaultVein - { - get - { - CheckRespawn(); - return m_DefaultVein; - } - } - - public void CheckRespawn() - { - if (m_Current == m_Maximum || m_NextRespawn > DateTime.UtcNow) - return; - - m_Current = m_Maximum; - - if (Definition.RandomizeVeins) m_DefaultVein = Definition.GetVeinFrom(Utility.Random(Definition.VeinWeights)); - - m_Vein = m_DefaultVein; - } - - public void Consume(int amount, Mobile from) - { - CheckRespawn(); - - if (m_Current == m_Maximum) - { - double min = Definition.MinRespawn.TotalMinutes; - double max = Definition.MaxRespawn.TotalMinutes; - double rnd = Utility.RandomDouble(); - - m_Current = m_Maximum - amount; - - double minutes = min + rnd * (max - min); - if (Definition.RaceBonus && from.Race == Race.Elf) // def.RaceBonus = Core.ML - minutes *= .75; // 25% off the time. - - m_NextRespawn = DateTime.UtcNow + TimeSpan.FromMinutes(minutes); - } - else - { - m_Current -= amount; - } - - if (m_Current < 0) - m_Current = 0; - } - } -} +using System; + +namespace Server.Engines.Harvest +{ + public class HarvestBank + { + private readonly int m_Maximum; + private int m_Current; + private DateTime m_NextRespawn; + private HarvestVein m_Vein, m_DefaultVein; + + public HarvestBank(HarvestDefinition def, HarvestVein defaultVein) + { + m_Maximum = Utility.RandomMinMax(def.MinTotal, def.MaxTotal); + m_Current = m_Maximum; + m_DefaultVein = defaultVein; + m_Vein = m_DefaultVein; + + Definition = def; + } + + public HarvestDefinition Definition { get; } + + public int Current + { + get + { + CheckRespawn(); + return m_Current; + } + } + + public HarvestVein Vein + { + get + { + CheckRespawn(); + return m_Vein; + } + set => m_Vein = value; + } + + public HarvestVein DefaultVein + { + get + { + CheckRespawn(); + return m_DefaultVein; + } + } + + public void CheckRespawn() + { + if (m_Current == m_Maximum || m_NextRespawn > DateTime.UtcNow) + return; + + m_Current = m_Maximum; + + if (Definition.RandomizeVeins) m_DefaultVein = Definition.GetVeinFrom(Utility.Random(Definition.VeinWeights)); + + m_Vein = m_DefaultVein; + } + + public void Consume(int amount, Mobile from) + { + CheckRespawn(); + + if (m_Current == m_Maximum) + { + var min = Definition.MinRespawn.TotalMinutes; + var max = Definition.MaxRespawn.TotalMinutes; + var rnd = Utility.RandomDouble(); + + m_Current = m_Maximum - amount; + + var minutes = min + rnd * (max - min); + if (Definition.RaceBonus && from.Race == Race.Elf) // def.RaceBonus = Core.ML + minutes *= .75; // 25% off the time. + + m_NextRespawn = DateTime.UtcNow + TimeSpan.FromMinutes(minutes); + } + else + { + m_Current -= amount; + } + + if (m_Current < 0) + m_Current = 0; + } + } +} diff --git a/Projects/UOContent/Engines/Harvest/Core/HarvestDefinition.cs b/Projects/UOContent/Engines/Harvest/Core/HarvestDefinition.cs index 559db0a85..bfe635d88 100644 --- a/Projects/UOContent/Engines/Harvest/Core/HarvestDefinition.cs +++ b/Projects/UOContent/Engines/Harvest/Core/HarvestDefinition.cs @@ -1,178 +1,177 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Server.Random; - -namespace Server.Engines.Harvest -{ - public class HarvestDefinition - { - public int BankWidth { get; set; } - - public int BankHeight { get; set; } - - public int MinTotal { get; set; } - - public int MaxTotal { get; set; } - - public int[] Tiles { get; set; } - - public bool RangedTiles { get; set; } - - public TimeSpan MinRespawn { get; set; } - - public TimeSpan MaxRespawn { get; set; } - - public int MaxRange { get; set; } - - public int ConsumedPerHarvest { get; set; } - - public int ConsumedPerFeluccaHarvest { get; set; } - - public bool PlaceAtFeetIfFull { get; set; } - - public SkillName Skill { get; set; } - - public int[] EffectActions { get; set; } - - public int[] EffectCounts { get; set; } - - public int[] EffectSounds { get; set; } - - public TimeSpan EffectSoundDelay { get; set; } - - public TimeSpan EffectDelay { get; set; } - - public TextDefinition NoResourcesMessage { get; set; } - - public TextDefinition OutOfRangeMessage { get; set; } - - public TextDefinition TimedOutOfRangeMessage { get; set; } - - public TextDefinition DoubleHarvestMessage { get; set; } - - public TextDefinition FailMessage { get; set; } - - public TextDefinition PackFullMessage { get; set; } - - public TextDefinition ToolBrokeMessage { get; set; } - - public HarvestResource[] Resources { get; set; } - - private HarvestVein[] m_Veins; - - public HarvestVein[] Veins - { - get => m_Veins; - set - { - m_Veins = value; - VeinWeights = m_Veins.Aggregate(0, (current, t) => current + t.VeinChance); - } - } - - public BonusHarvestResource[] BonusResources { get; set; } - - public bool RaceBonus { get; set; } - - public bool RandomizeVeins { get; set; } - - public uint VeinWeights { get; private set; } - - public Dictionary> Banks { get; } - = new Dictionary>(); - - public void SendMessageTo(Mobile from, TextDefinition message) - { - if (message.Number > 0) - from.SendLocalizedMessage(message.Number); - else - from.SendMessage(message); - } - - public HarvestBank GetBank(Map map, int x, int y) - { - if (map == null || map == Map.Internal) - return null; - - x /= BankWidth; - y /= BankHeight; - - if (!Banks.TryGetValue(map, out Dictionary banks)) - Banks[map] = banks = new Dictionary(); - - Point2D key = new Point2D(x, y); - - if (!banks.TryGetValue(key, out HarvestBank bank)) - banks[key] = bank = new HarvestBank(this, GetVeinAt(map, x, y)); - - return bank; - } - - public HarvestVein GetVeinAt(Map map, int x, int y) - { - if (Veins.Length == 1) - return Veins[0]; - - if (RandomizeVeins) return GetVeinFrom(Utility.Random(1000u)); - - // TODO: Introduce pulling primes from a config and writing them if they don't exist to the config - var random = new Xoshiro256PlusPlus((ulong)(x * 17 + y * 11 + map.MapID * 3)); - return GetVeinFrom(random.Next(VeinWeights)); - } - - public HarvestVein GetVeinFrom(uint randomValue) - { - if (Veins.Length == 1) - return Veins[0]; - - for (int i = 0; i < Veins.Length; ++i) - { - if (randomValue <= Veins[i].VeinChance) - return Veins[i]; - - randomValue -= Veins[i].VeinChance; - } - - return null; - } - - public BonusHarvestResource GetBonusResource() - { - if (BonusResources == null) - return null; - - double randomValue = Utility.RandomDouble() * 100; - - for (int i = 0; i < BonusResources.Length; ++i) - { - if (randomValue <= BonusResources[i].Chance) - return BonusResources[i]; - - randomValue -= BonusResources[i].Chance; - } - - return null; - } - - public bool Validate(int tileID) - { - if (RangedTiles) - { - bool contains = false; - - for (int i = 0; !contains && i < Tiles.Length; i += 2) - contains = tileID >= Tiles[i] && tileID <= Tiles[i + 1]; - - return contains; - } - - int dist = -1; - - for (int i = 0; dist < 0 && i < Tiles.Length; ++i) - dist = Tiles[i] - tileID; - - return dist == 0; - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using Server.Random; + +namespace Server.Engines.Harvest +{ + public class HarvestDefinition + { + private HarvestVein[] m_Veins; + public int BankWidth { get; set; } + + public int BankHeight { get; set; } + + public int MinTotal { get; set; } + + public int MaxTotal { get; set; } + + public int[] Tiles { get; set; } + + public bool RangedTiles { get; set; } + + public TimeSpan MinRespawn { get; set; } + + public TimeSpan MaxRespawn { get; set; } + + public int MaxRange { get; set; } + + public int ConsumedPerHarvest { get; set; } + + public int ConsumedPerFeluccaHarvest { get; set; } + + public bool PlaceAtFeetIfFull { get; set; } + + public SkillName Skill { get; set; } + + public int[] EffectActions { get; set; } + + public int[] EffectCounts { get; set; } + + public int[] EffectSounds { get; set; } + + public TimeSpan EffectSoundDelay { get; set; } + + public TimeSpan EffectDelay { get; set; } + + public TextDefinition NoResourcesMessage { get; set; } + + public TextDefinition OutOfRangeMessage { get; set; } + + public TextDefinition TimedOutOfRangeMessage { get; set; } + + public TextDefinition DoubleHarvestMessage { get; set; } + + public TextDefinition FailMessage { get; set; } + + public TextDefinition PackFullMessage { get; set; } + + public TextDefinition ToolBrokeMessage { get; set; } + + public HarvestResource[] Resources { get; set; } + + public HarvestVein[] Veins + { + get => m_Veins; + set + { + m_Veins = value; + VeinWeights = m_Veins.Aggregate(0, (current, t) => current + t.VeinChance); + } + } + + public BonusHarvestResource[] BonusResources { get; set; } + + public bool RaceBonus { get; set; } + + public bool RandomizeVeins { get; set; } + + public uint VeinWeights { get; private set; } + + public Dictionary> Banks { get; } + = new Dictionary>(); + + public void SendMessageTo(Mobile from, TextDefinition message) + { + if (message.Number > 0) + from.SendLocalizedMessage(message.Number); + else + from.SendMessage(message); + } + + public HarvestBank GetBank(Map map, int x, int y) + { + if (map == null || map == Map.Internal) + return null; + + x /= BankWidth; + y /= BankHeight; + + if (!Banks.TryGetValue(map, out var banks)) + Banks[map] = banks = new Dictionary(); + + var key = new Point2D(x, y); + + if (!banks.TryGetValue(key, out var bank)) + banks[key] = bank = new HarvestBank(this, GetVeinAt(map, x, y)); + + return bank; + } + + public HarvestVein GetVeinAt(Map map, int x, int y) + { + if (Veins.Length == 1) + return Veins[0]; + + if (RandomizeVeins) return GetVeinFrom(Utility.Random(1000u)); + + // TODO: Introduce pulling primes from a config and writing them if they don't exist to the config + var random = new Xoshiro256PlusPlus((ulong)(x * 17 + y * 11 + map.MapID * 3)); + return GetVeinFrom(random.Next(VeinWeights)); + } + + public HarvestVein GetVeinFrom(uint randomValue) + { + if (Veins.Length == 1) + return Veins[0]; + + for (var i = 0; i < Veins.Length; ++i) + { + if (randomValue <= Veins[i].VeinChance) + return Veins[i]; + + randomValue -= Veins[i].VeinChance; + } + + return null; + } + + public BonusHarvestResource GetBonusResource() + { + if (BonusResources == null) + return null; + + var randomValue = Utility.RandomDouble() * 100; + + for (var i = 0; i < BonusResources.Length; ++i) + { + if (randomValue <= BonusResources[i].Chance) + return BonusResources[i]; + + randomValue -= BonusResources[i].Chance; + } + + return null; + } + + public bool Validate(int tileID) + { + if (RangedTiles) + { + var contains = false; + + for (var i = 0; !contains && i < Tiles.Length; i += 2) + contains = tileID >= Tiles[i] && tileID <= Tiles[i + 1]; + + return contains; + } + + var dist = -1; + + for (var i = 0; dist < 0 && i < Tiles.Length; ++i) + dist = Tiles[i] - tileID; + + return dist == 0; + } + } +} diff --git a/Projects/UOContent/Engines/Harvest/Core/HarvestResource.cs b/Projects/UOContent/Engines/Harvest/Core/HarvestResource.cs index 014a7cc3f..96f5ef480 100644 --- a/Projects/UOContent/Engines/Harvest/Core/HarvestResource.cs +++ b/Projects/UOContent/Engines/Harvest/Core/HarvestResource.cs @@ -1,34 +1,34 @@ -using System; - -namespace Server.Engines.Harvest -{ - public class HarvestResource - { - public HarvestResource(double reqSkill, double minSkill, double maxSkill, object message, params Type[] types) - { - ReqSkill = reqSkill; - MinSkill = minSkill; - MaxSkill = maxSkill; - Types = types; - SuccessMessage = message; - } - - public Type[] Types { get; set; } - - public double ReqSkill { get; set; } - - public double MinSkill { get; set; } - - public double MaxSkill { get; set; } - - public object SuccessMessage { get; } - - public void SendSuccessTo(Mobile m) - { - if (SuccessMessage is int messageInt) - m.SendLocalizedMessage(messageInt); - else - m.SendMessage(SuccessMessage.ToString()); - } - } -} \ No newline at end of file +using System; + +namespace Server.Engines.Harvest +{ + public class HarvestResource + { + public HarvestResource(double reqSkill, double minSkill, double maxSkill, object message, params Type[] types) + { + ReqSkill = reqSkill; + MinSkill = minSkill; + MaxSkill = maxSkill; + Types = types; + SuccessMessage = message; + } + + public Type[] Types { get; set; } + + public double ReqSkill { get; set; } + + public double MinSkill { get; set; } + + public double MaxSkill { get; set; } + + public object SuccessMessage { get; } + + public void SendSuccessTo(Mobile m) + { + if (SuccessMessage is int messageInt) + m.SendLocalizedMessage(messageInt); + else + m.SendMessage(SuccessMessage.ToString()); + } + } +} diff --git a/Projects/UOContent/Engines/Harvest/Core/HarvestSoundTimer.cs b/Projects/UOContent/Engines/Harvest/Core/HarvestSoundTimer.cs index 885247b70..64806f72d 100644 --- a/Projects/UOContent/Engines/Harvest/Core/HarvestSoundTimer.cs +++ b/Projects/UOContent/Engines/Harvest/Core/HarvestSoundTimer.cs @@ -1,33 +1,35 @@ -namespace Server.Engines.Harvest -{ - public class HarvestSoundTimer : Timer - { - private readonly HarvestDefinition m_Definition; - private readonly Mobile m_From; - private readonly bool m_Last; - private readonly HarvestSystem m_System; - private readonly object m_ToHarvest; - private readonly object m_Locked; - private readonly Item m_Tool; - - public HarvestSoundTimer(Mobile from, Item tool, HarvestSystem system, HarvestDefinition def, object toHarvest, - object locked, bool last) : base(def.EffectSoundDelay) - { - m_From = from; - m_Tool = tool; - m_System = system; - m_Definition = def; - m_ToHarvest = toHarvest; - m_Locked = locked; - m_Last = last; - } - - protected override void OnTick() - { - m_System.DoHarvestingSound(m_From, m_Tool, m_Definition, m_ToHarvest); - - if (m_Last) - m_System.FinishHarvesting(m_From, m_Tool, m_Definition, m_ToHarvest, m_Locked); - } - } -} \ No newline at end of file +namespace Server.Engines.Harvest +{ + public class HarvestSoundTimer : Timer + { + private readonly HarvestDefinition m_Definition; + private readonly Mobile m_From; + private readonly bool m_Last; + private readonly object m_Locked; + private readonly HarvestSystem m_System; + private readonly object m_ToHarvest; + private readonly Item m_Tool; + + public HarvestSoundTimer( + Mobile from, Item tool, HarvestSystem system, HarvestDefinition def, object toHarvest, + object locked, bool last + ) : base(def.EffectSoundDelay) + { + m_From = from; + m_Tool = tool; + m_System = system; + m_Definition = def; + m_ToHarvest = toHarvest; + m_Locked = locked; + m_Last = last; + } + + protected override void OnTick() + { + m_System.DoHarvestingSound(m_From, m_Tool, m_Definition, m_ToHarvest); + + if (m_Last) + m_System.FinishHarvesting(m_From, m_Tool, m_Definition, m_ToHarvest, m_Locked); + } + } +} diff --git a/Projects/UOContent/Engines/Harvest/Core/HarvestSystem.cs b/Projects/UOContent/Engines/Harvest/Core/HarvestSystem.cs index 82661e851..0dc2c1337 100644 --- a/Projects/UOContent/Engines/Harvest/Core/HarvestSystem.cs +++ b/Projects/UOContent/Engines/Harvest/Core/HarvestSystem.cs @@ -1,424 +1,440 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Server.Items; -using Server.Targeting; -using Server.Utilities; - -namespace Server.Engines.Harvest -{ - public abstract class HarvestSystem - { - public HarvestSystem() => Definitions = new List(); - - public List Definitions { get; } - - public virtual bool CheckTool(Mobile from, Item tool) - { - bool wornOut = tool?.Deleted != false || (tool as IUsesRemaining)?.UsesRemaining <= 0; - - if (wornOut) - from.SendLocalizedMessage(1044038); // You have worn out your tool! - - return !wornOut; - } - - public virtual bool CheckHarvest(Mobile from, Item tool) => CheckTool(from, tool); - - public virtual bool CheckHarvest(Mobile from, Item tool, HarvestDefinition def, object toHarvest) => CheckTool(from, tool); - - public virtual bool CheckRange(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, bool timed) - { - bool inRange = from.Map == map && from.InRange(loc, def.MaxRange); - - if (!inRange) - def.SendMessageTo(from, timed ? def.TimedOutOfRangeMessage : def.OutOfRangeMessage); - - return inRange; - } - - public virtual bool CheckResources(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, bool timed) - { - HarvestBank bank = def.GetBank(map, loc.X, loc.Y); - bool available = bank?.Current >= def.ConsumedPerHarvest; - - if (!available) - def.SendMessageTo(from, timed ? def.DoubleHarvestMessage : def.NoResourcesMessage); - - return available; - } - - public virtual void OnBadHarvestTarget(Mobile from, Item tool, object toHarvest) - { - } - - public virtual object GetLock(Mobile from, Item tool, HarvestDefinition def, object toHarvest) => tool; - - public virtual void OnConcurrentHarvest(Mobile from, Item tool, HarvestDefinition def, object toHarvest) - { - } - - public virtual void OnHarvestStarted(Mobile from, Item tool, HarvestDefinition def, object toHarvest) - { - } - - public virtual bool BeginHarvesting(Mobile from, Item tool) - { - if (!CheckHarvest(from, tool)) - return false; - - from.Target = new HarvestTarget(tool, this); - return true; - } - - public virtual void FinishHarvesting(Mobile from, Item tool, HarvestDefinition def, object toHarvest, object locked) - { - from.EndAction(locked); - - if (!CheckHarvest(from, tool)) - return; - - if (!GetHarvestDetails(from, tool, toHarvest, out int tileID, out Map map, out Point3D loc)) - { - OnBadHarvestTarget(from, tool, toHarvest); - return; - } - - if (!def.Validate(tileID)) - { - OnBadHarvestTarget(from, tool, toHarvest); - return; - } - - if (!CheckRange(from, tool, def, map, loc, true)) - return; - if (!CheckResources(from, tool, def, map, loc, true)) - return; - if (!CheckHarvest(from, tool, def, toHarvest)) - return; - - if (SpecialHarvest(from, tool, def, map, loc)) - return; - - HarvestBank bank = def.GetBank(map, loc.X, loc.Y); - - if (bank == null) - return; - - HarvestVein vein = bank.Vein; - - if (vein != null) - vein = MutateVein(from, tool, def, bank, toHarvest, vein); - - if (vein == null) - return; - - HarvestResource primary = vein.PrimaryResource; - HarvestResource fallback = vein.FallbackResource; - HarvestResource resource = MutateResource(from, tool, def, map, loc, vein, primary, fallback); - - double skillBase = from.Skills[def.Skill].Base; - // double skillValue = from.Skills[def.Skill].Value; - - Type type = null; - - if (skillBase >= resource.ReqSkill && from.CheckSkill(def.Skill, resource.MinSkill, resource.MaxSkill)) - { - type = GetResourceType(from, tool, def, map, loc, resource); - - if (type != null) - type = MutateType(type, from, tool, def, map, loc, resource); - - if (type != null) - { - Item item = Construct(type, from); - - if (item == null) - { - type = null; - } - else - { - // The whole harvest system is kludgy and I'm sure this is just adding to it. - if (item.Stackable) - { - int amount = def.ConsumedPerHarvest; - int feluccaAmount = def.ConsumedPerFeluccaHarvest; - - int racialAmount = (int)Math.Ceiling(amount * 1.1); - int feluccaRacialAmount = (int)Math.Ceiling(feluccaAmount * 1.1); - - bool eligableForRacialBonus = def.RaceBonus && from.Race == Race.Human; - bool inFelucca = map == Map.Felucca; - - if (eligableForRacialBonus && inFelucca && bank.Current >= feluccaRacialAmount && - Utility.RandomDouble() < 0.1) - item.Amount = feluccaRacialAmount; - else if (inFelucca && bank.Current >= feluccaAmount) - item.Amount = feluccaAmount; - else if (eligableForRacialBonus && bank.Current >= racialAmount && Utility.RandomDouble() < 0.1) - item.Amount = racialAmount; - else - item.Amount = amount; - } - - bank.Consume(item.Amount, from); - - if (Give(from, item, def.PlaceAtFeetIfFull)) - { - SendSuccessTo(from, item, resource); - } - else - { - SendPackFullTo(from, item, def, resource); - item.Delete(); - } - - BonusHarvestResource bonus = def.GetBonusResource(); - - if (bonus?.Type != null && skillBase >= bonus.ReqSkill) - { - Item bonusItem = Construct(bonus.Type, from); - - if (Give(from, bonusItem, true)) // Bonuses always allow placing at feet, even if pack is full irregrdless of def - bonus.SendSuccessTo(from); - else - item.Delete(); - } - - if (tool is IUsesRemaining toolWithUses) - { - toolWithUses.ShowUsesRemaining = true; - - if (toolWithUses.UsesRemaining > 0) - --toolWithUses.UsesRemaining; - - if (toolWithUses.UsesRemaining < 1) - { - tool.Delete(); - def.SendMessageTo(from, def.ToolBrokeMessage); - } - } - } - } - } - - if (type == null) - def.SendMessageTo(from, def.FailMessage); - - OnHarvestFinished(from, tool, def, vein, bank, resource, toHarvest); - } - - public virtual void OnHarvestFinished(Mobile from, Item tool, HarvestDefinition def, HarvestVein vein, - HarvestBank bank, HarvestResource resource, object harvested) - { - } - - public virtual bool SpecialHarvest(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc) => false; - - public virtual Item Construct(Type type, Mobile from) - { - try - { - return ActivatorUtil.CreateInstance(type) as Item; - } - catch - { - return null; - } - } - - public virtual HarvestVein MutateVein(Mobile from, Item tool, HarvestDefinition def, HarvestBank bank, - object toHarvest, HarvestVein vein) => - vein; - - public virtual void SendSuccessTo(Mobile from, Item item, HarvestResource resource) - { - resource.SendSuccessTo(from); - } - - public virtual void SendPackFullTo(Mobile from, Item item, HarvestDefinition def, HarvestResource resource) - { - def.SendMessageTo(from, def.PackFullMessage); - } - - public virtual bool Give(Mobile m, Item item, bool placeAtFeet) - { - if (m.PlaceInBackpack(item)) - return true; - - if (!placeAtFeet) - return false; - - Map map = m.Map; - - if (map == null) - return false; - - if (m.GetItemsInRange(0).Any(t => t.StackWith(m, item, false))) - return true; - - item.MoveToWorld(m.Location, map); - return true; - } - - public virtual Type MutateType(Type type, Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, - HarvestResource resource) => - from.Region.GetResource(type); - - public virtual Type GetResourceType(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, - HarvestResource resource) => resource.Types.RandomElement(); - - public virtual HarvestResource MutateResource(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, - HarvestVein vein, HarvestResource primary, HarvestResource fallback) - { - bool racialBonus = def.RaceBonus && from.Race == Race.Elf; - - if (vein.ChanceToFallback > Utility.RandomDouble() + (racialBonus ? .20 : 0)) - return fallback; - - double skillValue = from.Skills[def.Skill].Value; - - if (fallback != null && (skillValue < primary.ReqSkill || skillValue < primary.MinSkill)) - return fallback; - - return primary; - } - - public virtual bool OnHarvesting(Mobile from, Item tool, HarvestDefinition def, object toHarvest, object locked, - bool last) - { - if (!CheckHarvest(from, tool)) - { - from.EndAction(locked); - return false; - } - - if (!GetHarvestDetails(from, tool, toHarvest, out int tileID, out Map map, out Point3D loc)) - { - from.EndAction(locked); - OnBadHarvestTarget(from, tool, toHarvest); - return false; - } - - if (!def.Validate(tileID)) - { - from.EndAction(locked); - OnBadHarvestTarget(from, tool, toHarvest); - return false; - } - - if (!CheckRange(from, tool, def, map, loc, true)) - { - from.EndAction(locked); - return false; - } - - if (!CheckResources(from, tool, def, map, loc, true)) - { - from.EndAction(locked); - return false; - } - - if (!CheckHarvest(from, tool, def, toHarvest)) - { - from.EndAction(locked); - return false; - } - - DoHarvestingEffect(from, tool, def, map, loc); - - new HarvestSoundTimer(from, tool, this, def, toHarvest, locked, last).Start(); - - return !last; - } - - public virtual void DoHarvestingSound(Mobile from, Item tool, HarvestDefinition def, object toHarvest) - { - from.PlaySound(def.EffectSounds.RandomElement(-1)); - } - - public virtual void DoHarvestingEffect(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc) - { - from.Direction = from.GetDirectionTo(loc); - - if (!from.Mounted) - from.Animate(def.EffectActions.RandomElement(), 5, 1, true, false, 0); - } - - public virtual HarvestDefinition GetDefinition() => Definitions.First(); - - public virtual HarvestDefinition GetDefinition(int tileID) => - Definitions.FirstOrDefault(check => check.Validate(tileID)); - - public virtual void StartHarvesting(Mobile from, Item tool, object toHarvest) - { - if (!CheckHarvest(from, tool)) - return; - - if (!GetHarvestDetails(from, tool, toHarvest, out int tileID, out Map map, out Point3D loc)) - { - OnBadHarvestTarget(from, tool, toHarvest); - return; - } - - HarvestDefinition def = GetDefinition(tileID); - - if (def == null) - { - OnBadHarvestTarget(from, tool, toHarvest); - return; - } - - if (!CheckRange(from, tool, def, map, loc, false)) - return; - if (!CheckResources(from, tool, def, map, loc, false)) - return; - if (!CheckHarvest(from, tool, def, toHarvest)) - return; - - object toLock = GetLock(from, tool, def, toHarvest); - - if (!from.BeginAction(toLock)) - { - OnConcurrentHarvest(from, tool, def, toHarvest); - return; - } - - new HarvestTimer(from, tool, this, def, toHarvest, toLock).Start(); - OnHarvestStarted(from, tool, def, toHarvest); - } - - public virtual bool GetHarvestDetails(Mobile from, Item tool, object toHarvest, out int tileID, out Map map, - out Point3D loc) - { - if (toHarvest is Static staticObj && !staticObj.Movable) - { - tileID = staticObj.ItemID & 0x3FFF | 0x4000; - map = staticObj.Map; - loc = staticObj.GetWorldLocation(); - } - else if (toHarvest is StaticTarget staticTarget) - { - tileID = staticTarget.ItemID & 0x3FFF | 0x4000; - map = from.Map; - loc = staticTarget.Location; - } - else if (toHarvest is LandTarget landTarget) - { - tileID = landTarget.TileID; - map = from.Map; - loc = landTarget.Location; - } - else - { - tileID = 0; - map = null; - loc = Point3D.Zero; - return false; - } - - return map != null && map != Map.Internal; - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using Server.Items; +using Server.Targeting; +using Server.Utilities; + +namespace Server.Engines.Harvest +{ + public abstract class HarvestSystem + { + public HarvestSystem() => Definitions = new List(); + + public List Definitions { get; } + + public virtual bool CheckTool(Mobile from, Item tool) + { + var wornOut = tool?.Deleted != false || (tool as IUsesRemaining)?.UsesRemaining <= 0; + + if (wornOut) + from.SendLocalizedMessage(1044038); // You have worn out your tool! + + return !wornOut; + } + + public virtual bool CheckHarvest(Mobile from, Item tool) => CheckTool(from, tool); + + public virtual bool CheckHarvest(Mobile from, Item tool, HarvestDefinition def, object toHarvest) => + CheckTool(from, tool); + + public virtual bool CheckRange(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, bool timed) + { + var inRange = from.Map == map && from.InRange(loc, def.MaxRange); + + if (!inRange) + def.SendMessageTo(from, timed ? def.TimedOutOfRangeMessage : def.OutOfRangeMessage); + + return inRange; + } + + public virtual bool CheckResources(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, bool timed) + { + var bank = def.GetBank(map, loc.X, loc.Y); + var available = bank?.Current >= def.ConsumedPerHarvest; + + if (!available) + def.SendMessageTo(from, timed ? def.DoubleHarvestMessage : def.NoResourcesMessage); + + return available; + } + + public virtual void OnBadHarvestTarget(Mobile from, Item tool, object toHarvest) + { + } + + public virtual object GetLock(Mobile from, Item tool, HarvestDefinition def, object toHarvest) => tool; + + public virtual void OnConcurrentHarvest(Mobile from, Item tool, HarvestDefinition def, object toHarvest) + { + } + + public virtual void OnHarvestStarted(Mobile from, Item tool, HarvestDefinition def, object toHarvest) + { + } + + public virtual bool BeginHarvesting(Mobile from, Item tool) + { + if (!CheckHarvest(from, tool)) + return false; + + from.Target = new HarvestTarget(tool, this); + return true; + } + + public virtual void FinishHarvesting(Mobile from, Item tool, HarvestDefinition def, object toHarvest, object locked) + { + from.EndAction(locked); + + if (!CheckHarvest(from, tool)) + return; + + if (!GetHarvestDetails(from, tool, toHarvest, out var tileID, out var map, out var loc)) + { + OnBadHarvestTarget(from, tool, toHarvest); + return; + } + + if (!def.Validate(tileID)) + { + OnBadHarvestTarget(from, tool, toHarvest); + return; + } + + if (!CheckRange(from, tool, def, map, loc, true)) + return; + if (!CheckResources(from, tool, def, map, loc, true)) + return; + if (!CheckHarvest(from, tool, def, toHarvest)) + return; + + if (SpecialHarvest(from, tool, def, map, loc)) + return; + + var bank = def.GetBank(map, loc.X, loc.Y); + + if (bank == null) + return; + + var vein = bank.Vein; + + if (vein != null) + vein = MutateVein(from, tool, def, bank, toHarvest, vein); + + if (vein == null) + return; + + var primary = vein.PrimaryResource; + var fallback = vein.FallbackResource; + var resource = MutateResource(from, tool, def, map, loc, vein, primary, fallback); + + var skillBase = from.Skills[def.Skill].Base; + // double skillValue = from.Skills[def.Skill].Value; + + Type type = null; + + if (skillBase >= resource.ReqSkill && from.CheckSkill(def.Skill, resource.MinSkill, resource.MaxSkill)) + { + type = GetResourceType(from, tool, def, map, loc, resource); + + if (type != null) + type = MutateType(type, from, tool, def, map, loc, resource); + + if (type != null) + { + var item = Construct(type, from); + + if (item == null) + { + type = null; + } + else + { + // The whole harvest system is kludgy and I'm sure this is just adding to it. + if (item.Stackable) + { + var amount = def.ConsumedPerHarvest; + var feluccaAmount = def.ConsumedPerFeluccaHarvest; + + var racialAmount = (int)Math.Ceiling(amount * 1.1); + var feluccaRacialAmount = (int)Math.Ceiling(feluccaAmount * 1.1); + + var eligableForRacialBonus = def.RaceBonus && from.Race == Race.Human; + var inFelucca = map == Map.Felucca; + + if (eligableForRacialBonus && inFelucca && bank.Current >= feluccaRacialAmount && + Utility.RandomDouble() < 0.1) + item.Amount = feluccaRacialAmount; + else if (inFelucca && bank.Current >= feluccaAmount) + item.Amount = feluccaAmount; + else if (eligableForRacialBonus && bank.Current >= racialAmount && Utility.RandomDouble() < 0.1) + item.Amount = racialAmount; + else + item.Amount = amount; + } + + bank.Consume(item.Amount, from); + + if (Give(from, item, def.PlaceAtFeetIfFull)) + { + SendSuccessTo(from, item, resource); + } + else + { + SendPackFullTo(from, item, def, resource); + item.Delete(); + } + + var bonus = def.GetBonusResource(); + + if (bonus?.Type != null && skillBase >= bonus.ReqSkill) + { + var bonusItem = Construct(bonus.Type, from); + + if (Give(from, bonusItem, true) + ) // Bonuses always allow placing at feet, even if pack is full irregrdless of def + bonus.SendSuccessTo(from); + else + item.Delete(); + } + + if (tool is IUsesRemaining toolWithUses) + { + toolWithUses.ShowUsesRemaining = true; + + if (toolWithUses.UsesRemaining > 0) + --toolWithUses.UsesRemaining; + + if (toolWithUses.UsesRemaining < 1) + { + tool.Delete(); + def.SendMessageTo(from, def.ToolBrokeMessage); + } + } + } + } + } + + if (type == null) + def.SendMessageTo(from, def.FailMessage); + + OnHarvestFinished(from, tool, def, vein, bank, resource, toHarvest); + } + + public virtual void OnHarvestFinished( + Mobile from, Item tool, HarvestDefinition def, HarvestVein vein, + HarvestBank bank, HarvestResource resource, object harvested + ) + { + } + + public virtual bool SpecialHarvest(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc) => false; + + public virtual Item Construct(Type type, Mobile from) + { + try + { + return ActivatorUtil.CreateInstance(type) as Item; + } + catch + { + return null; + } + } + + public virtual HarvestVein MutateVein( + Mobile from, Item tool, HarvestDefinition def, HarvestBank bank, + object toHarvest, HarvestVein vein + ) => + vein; + + public virtual void SendSuccessTo(Mobile from, Item item, HarvestResource resource) + { + resource.SendSuccessTo(from); + } + + public virtual void SendPackFullTo(Mobile from, Item item, HarvestDefinition def, HarvestResource resource) + { + def.SendMessageTo(from, def.PackFullMessage); + } + + public virtual bool Give(Mobile m, Item item, bool placeAtFeet) + { + if (m.PlaceInBackpack(item)) + return true; + + if (!placeAtFeet) + return false; + + var map = m.Map; + + if (map == null) + return false; + + if (m.GetItemsInRange(0).Any(t => t.StackWith(m, item, false))) + return true; + + item.MoveToWorld(m.Location, map); + return true; + } + + public virtual Type MutateType( + Type type, Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, + HarvestResource resource + ) => + from.Region.GetResource(type); + + public virtual Type GetResourceType( + Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, + HarvestResource resource + ) => resource.Types.RandomElement(); + + public virtual HarvestResource MutateResource( + Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, + HarvestVein vein, HarvestResource primary, HarvestResource fallback + ) + { + var racialBonus = def.RaceBonus && from.Race == Race.Elf; + + if (vein.ChanceToFallback > Utility.RandomDouble() + (racialBonus ? .20 : 0)) + return fallback; + + var skillValue = from.Skills[def.Skill].Value; + + if (fallback != null && (skillValue < primary.ReqSkill || skillValue < primary.MinSkill)) + return fallback; + + return primary; + } + + public virtual bool OnHarvesting( + Mobile from, Item tool, HarvestDefinition def, object toHarvest, object locked, + bool last + ) + { + if (!CheckHarvest(from, tool)) + { + from.EndAction(locked); + return false; + } + + if (!GetHarvestDetails(from, tool, toHarvest, out var tileID, out var map, out var loc)) + { + from.EndAction(locked); + OnBadHarvestTarget(from, tool, toHarvest); + return false; + } + + if (!def.Validate(tileID)) + { + from.EndAction(locked); + OnBadHarvestTarget(from, tool, toHarvest); + return false; + } + + if (!CheckRange(from, tool, def, map, loc, true)) + { + from.EndAction(locked); + return false; + } + + if (!CheckResources(from, tool, def, map, loc, true)) + { + from.EndAction(locked); + return false; + } + + if (!CheckHarvest(from, tool, def, toHarvest)) + { + from.EndAction(locked); + return false; + } + + DoHarvestingEffect(from, tool, def, map, loc); + + new HarvestSoundTimer(from, tool, this, def, toHarvest, locked, last).Start(); + + return !last; + } + + public virtual void DoHarvestingSound(Mobile from, Item tool, HarvestDefinition def, object toHarvest) + { + from.PlaySound(def.EffectSounds.RandomElement(-1)); + } + + public virtual void DoHarvestingEffect(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc) + { + from.Direction = from.GetDirectionTo(loc); + + if (!from.Mounted) + from.Animate(def.EffectActions.RandomElement(), 5, 1, true, false, 0); + } + + public virtual HarvestDefinition GetDefinition() => Definitions.First(); + + public virtual HarvestDefinition GetDefinition(int tileID) => + Definitions.FirstOrDefault(check => check.Validate(tileID)); + + public virtual void StartHarvesting(Mobile from, Item tool, object toHarvest) + { + if (!CheckHarvest(from, tool)) + return; + + if (!GetHarvestDetails(from, tool, toHarvest, out var tileID, out var map, out var loc)) + { + OnBadHarvestTarget(from, tool, toHarvest); + return; + } + + var def = GetDefinition(tileID); + + if (def == null) + { + OnBadHarvestTarget(from, tool, toHarvest); + return; + } + + if (!CheckRange(from, tool, def, map, loc, false)) + return; + if (!CheckResources(from, tool, def, map, loc, false)) + return; + if (!CheckHarvest(from, tool, def, toHarvest)) + return; + + var toLock = GetLock(from, tool, def, toHarvest); + + if (!from.BeginAction(toLock)) + { + OnConcurrentHarvest(from, tool, def, toHarvest); + return; + } + + new HarvestTimer(from, tool, this, def, toHarvest, toLock).Start(); + OnHarvestStarted(from, tool, def, toHarvest); + } + + public virtual bool GetHarvestDetails( + Mobile from, Item tool, object toHarvest, out int tileID, out Map map, + out Point3D loc + ) + { + if (toHarvest is Static staticObj && !staticObj.Movable) + { + tileID = (staticObj.ItemID & 0x3FFF) | 0x4000; + map = staticObj.Map; + loc = staticObj.GetWorldLocation(); + } + else if (toHarvest is StaticTarget staticTarget) + { + tileID = (staticTarget.ItemID & 0x3FFF) | 0x4000; + map = from.Map; + loc = staticTarget.Location; + } + else if (toHarvest is LandTarget landTarget) + { + tileID = landTarget.TileID; + map = from.Map; + loc = landTarget.Location; + } + else + { + tileID = 0; + map = null; + loc = Point3D.Zero; + return false; + } + + return map != null && map != Map.Internal; + } + } +} diff --git a/Projects/UOContent/Engines/Harvest/Core/HarvestTarget.cs b/Projects/UOContent/Engines/Harvest/Core/HarvestTarget.cs index 75c979280..0004e0612 100644 --- a/Projects/UOContent/Engines/Harvest/Core/HarvestTarget.cs +++ b/Projects/UOContent/Engines/Harvest/Core/HarvestTarget.cs @@ -1,111 +1,111 @@ -using Server.Engines.Quests; -using Server.Engines.Quests.Hag; -using Server.Items; -using Server.Mobiles; -using Server.Targeting; - -namespace Server.Engines.Harvest -{ - public class HarvestTarget : Target - { - private readonly HarvestSystem m_System; - private readonly Item m_Tool; - - public HarvestTarget(Item tool, HarvestSystem system) : base(-1, true, TargetFlags.None) - { - m_Tool = tool; - m_System = system; - - DisallowMultis = true; - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_System is Mining && targeted is StaticTarget target) - { - int itemID = target.ItemID; - - // grave - if (itemID == 0xED3 || itemID == 0xEDF || itemID == 0xEE0 || itemID == 0xEE1 || itemID == 0xEE2 || - itemID == 0xEE8) - if (from is PlayerMobile player) - { - QuestSystem qs = player.Quest; - if (!(qs is WitchApprenticeQuest)) - return; - - FindIngredientObjective obj = qs.FindObjective(); - - if (obj?.Completed == false && obj.Ingredient == Ingredient.Bones) - { - player.SendLocalizedMessage( - 1055037); // You finish your grim work, finding some of the specific bones listed in the Hag's recipe. - obj.Complete(); - - return; - } - } - } - - if (m_System is Lumberjacking && targeted is IChoppable chopable) - { - chopable.OnChop(from); - } - else if (m_System is Lumberjacking && targeted is IAxe obj && m_Tool is BaseAxe axe) - { - Item item = (Item)obj; - - if (!item.IsChildOf(from.Backpack)) - from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. - else if (obj.Axe(from, axe)) - from.PlaySound(0x13E); - } - else if (m_System is Lumberjacking && targeted is ICarvable carvable) - { - carvable.Carve(from, m_Tool); - } - else if (m_System is Lumberjacking && FurnitureAttribute.Check(targeted as Item)) - { - DestroyFurniture(from, (Item)targeted); - } - else if (m_System is Mining && targeted is TreasureMap map) - { - map.OnBeginDig(from); - } - else - { - m_System.StartHarvesting(from, m_Tool, targeted); - } - } - - private void DestroyFurniture(Mobile from, Item item) - { - if (!from.InRange(item.GetWorldLocation(), 3)) - { - from.SendLocalizedMessage(500446); // That is too far away. - return; - } - - if (!item.IsChildOf(from.Backpack) && !item.Movable) - { - from.SendLocalizedMessage(500462); // You can't destroy that while it is here. - return; - } - - from.SendLocalizedMessage(500461); // You destroy the item. - Effects.PlaySound(item.GetWorldLocation(), item.Map, 0x3B3); - - if (item is Container container) - { - if (container is TrappableContainer trappableContainer) - trappableContainer.ExecuteTrap(from); - - container.Destroy(); - } - else - { - item.Delete(); - } - } - } -} \ No newline at end of file +using Server.Engines.Quests.Hag; +using Server.Items; +using Server.Mobiles; +using Server.Targeting; + +namespace Server.Engines.Harvest +{ + public class HarvestTarget : Target + { + private readonly HarvestSystem m_System; + private readonly Item m_Tool; + + public HarvestTarget(Item tool, HarvestSystem system) : base(-1, true, TargetFlags.None) + { + m_Tool = tool; + m_System = system; + + DisallowMultis = true; + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_System is Mining && targeted is StaticTarget target) + { + var itemID = target.ItemID; + + // grave + if (itemID == 0xED3 || itemID == 0xEDF || itemID == 0xEE0 || itemID == 0xEE1 || itemID == 0xEE2 || + itemID == 0xEE8) + if (from is PlayerMobile player) + { + var qs = player.Quest; + if (!(qs is WitchApprenticeQuest)) + return; + + var obj = qs.FindObjective(); + + if (obj?.Completed == false && obj.Ingredient == Ingredient.Bones) + { + player.SendLocalizedMessage( + 1055037 + ); // You finish your grim work, finding some of the specific bones listed in the Hag's recipe. + obj.Complete(); + + return; + } + } + } + + if (m_System is Lumberjacking && targeted is IChoppable chopable) + { + chopable.OnChop(from); + } + else if (m_System is Lumberjacking && targeted is IAxe obj && m_Tool is BaseAxe axe) + { + var item = (Item)obj; + + if (!item.IsChildOf(from.Backpack)) + from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. + else if (obj.Axe(from, axe)) + from.PlaySound(0x13E); + } + else if (m_System is Lumberjacking && targeted is ICarvable carvable) + { + carvable.Carve(from, m_Tool); + } + else if (m_System is Lumberjacking && FurnitureAttribute.Check(targeted as Item)) + { + DestroyFurniture(from, (Item)targeted); + } + else if (m_System is Mining && targeted is TreasureMap map) + { + map.OnBeginDig(from); + } + else + { + m_System.StartHarvesting(from, m_Tool, targeted); + } + } + + private void DestroyFurniture(Mobile from, Item item) + { + if (!from.InRange(item.GetWorldLocation(), 3)) + { + from.SendLocalizedMessage(500446); // That is too far away. + return; + } + + if (!item.IsChildOf(from.Backpack) && !item.Movable) + { + from.SendLocalizedMessage(500462); // You can't destroy that while it is here. + return; + } + + from.SendLocalizedMessage(500461); // You destroy the item. + Effects.PlaySound(item.GetWorldLocation(), item.Map, 0x3B3); + + if (item is Container container) + { + if (container is TrappableContainer trappableContainer) + trappableContainer.ExecuteTrap(from); + + container.Destroy(); + } + else + { + item.Delete(); + } + } + } +} diff --git a/Projects/UOContent/Engines/Harvest/Core/HarvestTimer.cs b/Projects/UOContent/Engines/Harvest/Core/HarvestTimer.cs index 2486588cf..98ddf577a 100644 --- a/Projects/UOContent/Engines/Harvest/Core/HarvestTimer.cs +++ b/Projects/UOContent/Engines/Harvest/Core/HarvestTimer.cs @@ -1,34 +1,36 @@ -using System; - -namespace Server.Engines.Harvest -{ - public class HarvestTimer : Timer - { - private readonly HarvestDefinition m_Definition; - private readonly Mobile m_From; - private int m_Index; - private readonly int m_Count; - private readonly HarvestSystem m_System; - private readonly object m_ToHarvest; - private readonly object m_Locked; - private readonly Item m_Tool; - - public HarvestTimer(Mobile from, Item tool, HarvestSystem system, HarvestDefinition def, object toHarvest, - object locked) : base(TimeSpan.Zero, def.EffectDelay) - { - m_From = from; - m_Tool = tool; - m_System = system; - m_Definition = def; - m_ToHarvest = toHarvest; - m_Locked = locked; - m_Count = def.EffectCounts.RandomElement(); - } - - protected override void OnTick() - { - if (!m_System.OnHarvesting(m_From, m_Tool, m_Definition, m_ToHarvest, m_Locked, ++m_Index == m_Count)) - Stop(); - } - } -} +using System; + +namespace Server.Engines.Harvest +{ + public class HarvestTimer : Timer + { + private readonly int m_Count; + private readonly HarvestDefinition m_Definition; + private readonly Mobile m_From; + private readonly object m_Locked; + private readonly HarvestSystem m_System; + private readonly object m_ToHarvest; + private readonly Item m_Tool; + private int m_Index; + + public HarvestTimer( + Mobile from, Item tool, HarvestSystem system, HarvestDefinition def, object toHarvest, + object locked + ) : base(TimeSpan.Zero, def.EffectDelay) + { + m_From = from; + m_Tool = tool; + m_System = system; + m_Definition = def; + m_ToHarvest = toHarvest; + m_Locked = locked; + m_Count = def.EffectCounts.RandomElement(); + } + + protected override void OnTick() + { + if (!m_System.OnHarvesting(m_From, m_Tool, m_Definition, m_ToHarvest, m_Locked, ++m_Index == m_Count)) + Stop(); + } + } +} diff --git a/Projects/UOContent/Engines/Harvest/Core/HarvestVein.cs b/Projects/UOContent/Engines/Harvest/Core/HarvestVein.cs index 87a67ee43..bdc89816b 100644 --- a/Projects/UOContent/Engines/Harvest/Core/HarvestVein.cs +++ b/Projects/UOContent/Engines/Harvest/Core/HarvestVein.cs @@ -1,22 +1,24 @@ -namespace Server.Engines.Harvest -{ - public class HarvestVein - { - public HarvestVein(uint veinChance, double chanceToFallback, HarvestResource primaryResource, - HarvestResource fallbackResource) - { - VeinChance = veinChance; - ChanceToFallback = chanceToFallback; - PrimaryResource = primaryResource; - FallbackResource = fallbackResource; - } - - public uint VeinChance { get; set; } - - public double ChanceToFallback { get; set; } - - public HarvestResource PrimaryResource { get; set; } - - public HarvestResource FallbackResource { get; set; } - } -} +namespace Server.Engines.Harvest +{ + public class HarvestVein + { + public HarvestVein( + uint veinChance, double chanceToFallback, HarvestResource primaryResource, + HarvestResource fallbackResource + ) + { + VeinChance = veinChance; + ChanceToFallback = chanceToFallback; + PrimaryResource = primaryResource; + FallbackResource = fallbackResource; + } + + public uint VeinChance { get; set; } + + public double ChanceToFallback { get; set; } + + public HarvestResource PrimaryResource { get; set; } + + public HarvestResource FallbackResource { get; set; } + } +} diff --git a/Projects/UOContent/Engines/Harvest/Core/IChoppable..cs b/Projects/UOContent/Engines/Harvest/Core/IChoppable..cs index c9d71da89..96955d383 100644 --- a/Projects/UOContent/Engines/Harvest/Core/IChoppable..cs +++ b/Projects/UOContent/Engines/Harvest/Core/IChoppable..cs @@ -1,7 +1,7 @@ -namespace Server -{ - public interface IChoppable - { - void OnChop(Mobile from); - } -} +namespace Server +{ + public interface IChoppable + { + void OnChop(Mobile from); + } +} diff --git a/Projects/UOContent/Engines/Harvest/Fishing.cs b/Projects/UOContent/Engines/Harvest/Fishing.cs index 52f53df46..b5f63ffd7 100644 --- a/Projects/UOContent/Engines/Harvest/Fishing.cs +++ b/Projects/UOContent/Engines/Harvest/Fishing.cs @@ -1,501 +1,524 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Server.Engines.Quests; -using Server.Engines.Quests.Collector; -using Server.Items; -using Server.Mobiles; -using Server.Network; -using Server.Spells; - -namespace Server.Engines.Harvest -{ - public class Fishing : HarvestSystem - { - private static Fishing m_System; - - private static readonly MutateEntry[] m_MutateTable = - { - new MutateEntry(80.0, 80.0, 4080.0, true, typeof(SpecialFishingNet)), - new MutateEntry(80.0, 80.0, 4080.0, true, typeof(BigFish)), - new MutateEntry(90.0, 80.0, 4080.0, true, typeof(TreasureMap)), - new MutateEntry(100.0, 80.0, 4080.0, true, typeof(MessageInABottle)), - new MutateEntry(0.0, 125.0, -2375.0, false, typeof(PrizedFish), typeof(WondrousFish), typeof(TrulyRareFish), - typeof(PeculiarFish)), - new MutateEntry(0.0, 105.0, -420.0, false, typeof(Boots), typeof(Shoes), typeof(Sandals), typeof(ThighBoots)), - new MutateEntry(0.0, 200.0, -200.0, false, new Type[] { null }) - }; - - private static readonly int[] m_WaterTiles = - { - 0x00A8, 0x00AB, - 0x0136, 0x0137, - 0x5797, 0x579C, - 0x746E, 0x7485, - 0x7490, 0x74AB, - 0x74B5, 0x75D5 - }; - - private Fishing() - { - HarvestDefinition fish = new HarvestDefinition - { - BankWidth = 8, - BankHeight = 8, - MinTotal = 5, - MaxTotal = 15, - MinRespawn = TimeSpan.FromMinutes(10.0), - MaxRespawn = TimeSpan.FromMinutes(20.0), - Skill = SkillName.Fishing, - Tiles = m_WaterTiles, - RangedTiles = true, - MaxRange = 4, - ConsumedPerHarvest = 1, - ConsumedPerFeluccaHarvest = 1, - EffectActions = new[] { 12 }, - EffectSounds = Array.Empty(), - EffectCounts = new[] { 1 }, - EffectDelay = TimeSpan.Zero, - EffectSoundDelay = TimeSpan.FromSeconds(8.0), - NoResourcesMessage = 503172, // The fish don't seem to be biting here. - FailMessage = 503171, // You fish a while, but fail to catch anything. - TimedOutOfRangeMessage = 500976, // You need to be closer to the water to fish! - OutOfRangeMessage = 500976, // You need to be closer to the water to fish! - PackFullMessage = 503176, // You do not have room in your backpack for a fish. - ToolBrokeMessage = 503174 // You broke your fishing pole. - }; - - HarvestResource[] res = { - new HarvestResource(00.0, 00.0, 100.0, 1043297, typeof(Fish)) - }; - - HarvestVein[] veins = { - new HarvestVein(1000, 0.0, res[0], null) - }; - - fish.Resources = res; - fish.Veins = veins; - - if (Core.ML) - fish.BonusResources = new[] - { - new BonusHarvestResource(0, 99.4, null, null), // set to same chance as mining ml gems - new BonusHarvestResource(80.0, .6, 1072597, typeof(WhitePearl)) - }; - - Definitions.Add(fish); - } - - public static Fishing System => m_System ?? (m_System = new Fishing()); - - public override void OnConcurrentHarvest(Mobile from, Item tool, HarvestDefinition def, object toHarvest) - { - from.SendLocalizedMessage(500972); // You are already fishing. - } - - public override bool SpecialHarvest(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc) - { - if (from is PlayerMobile player) - { - QuestSystem qs = player.Quest; - - if (qs is CollectorQuest) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - if (Utility.RandomDouble() < 0.5) - { - player.SendLocalizedMessage(1055086, "", - 0x59); // You pull a shellfish out of the water, and find a rainbow pearl inside of it. - - obj.CurProgress++; - } - else - { - player.SendLocalizedMessage(1055087, "", - 0x2C); // You pull a shellfish out of the water, but it doesn't have a rainbow pearl. - } - - return true; - } - } - } - - return false; - } - - public override Type MutateType(Type type, Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, - HarvestResource resource) - { - bool deepWater = SpecialFishingNet.FullValidation(map, loc.X, loc.Y); - - double skillBase = from.Skills.Fishing.Base; - double skillValue = from.Skills.Fishing.Value; - - for (int i = 0; i < m_MutateTable.Length; ++i) - { - MutateEntry entry = m_MutateTable[i]; - - if (!deepWater && entry.m_DeepWater) - continue; - - if (skillBase >= entry.m_ReqSkill) - { - double chance = (skillValue - entry.m_MinSkill) / (entry.m_MaxSkill - entry.m_MinSkill); - - if (chance > Utility.RandomDouble()) - return entry.m_Types.RandomElement(); - } - } - - return type; - } - - private static Map SafeMap(Map map) => map == null || map == Map.Internal ? Map.Trammel : map; - - public override bool CheckResources(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, bool timed) - { - return from?.Backpack?.FindItemsByType().Any(sos => - (from.Map == Map.Felucca || from.Map == Map.Trammel) && from.InRange(sos.TargetLocation, 60)) ?? - base.CheckResources(from, tool, def, map, loc, timed); - } - - public override Item Construct(Type type, Mobile from) - { - if (type == typeof(TreasureMap)) - { - int level; - if (from is PlayerMobile mobile && mobile.Young && mobile.Map == Map.Trammel && - TreasureMap.IsInHavenIsland(from)) - level = 0; - else - level = 1; - - return new TreasureMap(level, from.Map == Map.Felucca ? Map.Felucca : Map.Trammel); - } - - if (type == typeof(MessageInABottle)) - return new MessageInABottle(from.Map == Map.Felucca ? Map.Felucca : Map.Trammel); - - Container pack = from.Backpack; - - if (pack != null) - { - List messages = pack.FindItemsByType(); - - for (int i = 0; i < messages.Count; ++i) - { - SOS sos = messages[i]; - - if ((from.Map == Map.Felucca || from.Map == Map.Trammel) && from.InRange(sos.TargetLocation, 60)) - { - Item preLoot = null; - - switch (Utility.Random(8)) - { - case 0: // Body parts - { - int[] list = - { - 0x1CDD, 0x1CE5, // arm - 0x1CE0, 0x1CE8, // torso - 0x1CE1, 0x1CE9, // head - 0x1CE2, 0x1CEC // leg - }; - - preLoot = new ShipwreckedItem(list.RandomElement()); - break; - } - case 1: // Bone parts - { - int[] list = - { - 0x1AE0, 0x1AE1, 0x1AE2, 0x1AE3, 0x1AE4, // skulls - 0x1B09, 0x1B0A, 0x1B0B, 0x1B0C, 0x1B0D, 0x1B0E, 0x1B0F, 0x1B10, // bone piles - 0x1B15, 0x1B16 // pelvis bones - }; - - preLoot = new ShipwreckedItem(list.RandomElement()); - break; - } - case 2: // Paintings and portraits - { - preLoot = new ShipwreckedItem(Utility.Random(0xE9F, 10)); - break; - } - case 3: // Pillows - { - preLoot = new ShipwreckedItem(Utility.Random(0x13A4, 11)); - break; - } - case 4: // Shells - { - preLoot = new ShipwreckedItem(Utility.Random(0xFC4, 9)); - break; - } - case 5: // Hats - { - if (Utility.RandomBool()) - preLoot = new SkullCap(); - else - preLoot = new TricorneHat(); - - break; - } - case 6: // Misc - { - int[] list = - { - 0x1EB5, // unfinished barrel - 0xA2A, // stool - 0xC1F, // broken clock - 0x1047, 0x1048, // globe - 0x1EB1, 0x1EB2, 0x1EB3, 0x1EB4 // barrel staves - }; - - if (Utility.Random(list.Length + 1) == 0) - preLoot = new Candelabra(); - else - preLoot = new ShipwreckedItem(list.RandomElement()); - - break; - } - } - - if (preLoot != null) - { - ((IShipwreckedItem)preLoot).IsShipwreckedItem = true; - return preLoot; - } - - LockableContainer chest; - - if (Utility.RandomBool()) - chest = new MetalGoldenChest(); - else - chest = new WoodenChest(); - - if (sos.IsAncient) - chest.Hue = 0x481; - - TreasureMapChest.Fill(chest, Math.Max(1, Math.Min(4, sos.Level))); - - chest.DropItem(sos.IsAncient ? new FabledFishingNet() : new SpecialFishingNet()); - - chest.Movable = true; - chest.Locked = false; - chest.TrapType = TrapType.None; - chest.TrapPower = 0; - chest.TrapLevel = 0; - - sos.Delete(); - - return chest; - } - } - } - - return base.Construct(type, from); - } - - public override bool Give(Mobile m, Item item, bool placeAtFeet) - { - if (item is TreasureMap || item is MessageInABottle || item is SpecialFishingNet) - { - BaseCreature serp; - - if (Utility.RandomDouble() < 0.25) - serp = new DeepSeaSerpent(); - else - serp = new SeaSerpent(); - - int x = m.X, y = m.Y; - - Map map = m.Map; - - for (int i = 0; map != null && i < 20; ++i) - { - int tx = m.X - 10 + Utility.Random(21); - int ty = m.Y - 10 + Utility.Random(21); - - LandTile t = map.Tiles.GetLandTile(tx, ty); - - if (t.Z == -5 && ((t.ID >= 0xA8 && t.ID <= 0xAB) || (t.ID >= 0x136 && t.ID <= 0x137)) && - !SpellHelper.CheckMulti(new Point3D(tx, ty, -5), map)) - { - x = tx; - y = ty; - break; - } - } - - serp.MoveToWorld(new Point3D(x, y, -5), map); - - serp.Home = serp.Location; - serp.RangeHome = 10; - - serp.PackItem(item); - - m.SendLocalizedMessage(503170); // Uh oh! That doesn't look like a fish! - - return true; // we don't want to give the item to the player, it's on the serpent - } - - return base.Give(m, item, placeAtFeet || item is BigFish || item is WoodenChest || item is MetalGoldenChest); - } - - public override void SendSuccessTo(Mobile from, Item item, HarvestResource resource) - { - if (item is BigFish fish) - { - from.SendLocalizedMessage(1042635); // Your fishing pole bends as you pull a big fish from the depths! - fish.Fisher = from; - } - else if (item is WoodenChest || item is MetalGoldenChest) - { - from.SendLocalizedMessage(503175); // You pull up a heavy chest from the depths of the ocean! - } - else - { - int number; - string name; - - if (item is BaseMagicFish) - { - number = 1008124; - name = "a mess of small fish"; - } - else if (item is Fish) - { - number = 1008124; - name = item.ItemData.Name; - } - else if (item is BaseShoes) - { - number = 1008124; - name = item.ItemData.Name; - } - else if (item is TreasureMap) - { - number = 1008125; - name = "a sodden piece of parchment"; - } - else if (item is MessageInABottle) - { - number = 1008125; - name = "a bottle, with a message in it"; - } - else if (item is SpecialFishingNet) - { - number = 1008125; - name = "a special fishing net"; // TODO: this is just a guess--what should it really be named? - } - else - { - number = 1043297; - - if ((item.ItemData.Flags & TileFlag.ArticleA) != 0) - name = $"a {item.ItemData.Name}"; - else if ((item.ItemData.Flags & TileFlag.ArticleAn) != 0) - name = $"an {item.ItemData.Name}"; - else - name = item.ItemData.Name; - } - - NetState ns = from.NetState; - - if (ns == null) - return; - - if (number == 1043297 || ns.HighSeas) - from.SendLocalizedMessage(number, name); - else - from.SendLocalizedMessage(number, true, name); - } - } - - public override void OnHarvestStarted(Mobile from, Item tool, HarvestDefinition def, object toHarvest) - { - base.OnHarvestStarted(from, tool, def, toHarvest); - - if (GetHarvestDetails(from, tool, toHarvest, out _, out Map map, out Point3D loc)) - Timer.DelayCall(TimeSpan.FromSeconds(1.5), - () => - { - if (Core.ML) - from.RevealingAction(); - - Effects.SendLocationEffect(loc, map, 0x352D, 16, 4); - Effects.PlaySound(loc, map, 0x364); - }); - } - - public override void OnHarvestFinished(Mobile from, Item tool, HarvestDefinition def, HarvestVein vein, - HarvestBank bank, HarvestResource resource, object harvested) - { - base.OnHarvestFinished(from, tool, def, vein, bank, resource, harvested); - - if (Core.ML) - from.RevealingAction(); - } - - public override object GetLock(Mobile from, Item tool, HarvestDefinition def, object toHarvest) => this; - - public override bool BeginHarvesting(Mobile from, Item tool) - { - if (!base.BeginHarvesting(from, tool)) - return false; - - from.SendLocalizedMessage(500974); // What water do you want to fish in? - return true; - } - - public override bool CheckHarvest(Mobile from, Item tool) - { - if (!base.CheckHarvest(from, tool)) - return false; - - if (from.Mounted) - { - from.SendLocalizedMessage(500971); // You can't fish while riding! - return false; - } - - return true; - } - - public override bool CheckHarvest(Mobile from, Item tool, HarvestDefinition def, object toHarvest) - { - if (!base.CheckHarvest(from, tool, def, toHarvest)) - return false; - - if (from.Mounted) - { - from.SendLocalizedMessage(500971); // You can't fish while riding! - return false; - } - - return true; - } - - private class MutateEntry - { - public readonly bool m_DeepWater; - public readonly double m_ReqSkill; - public readonly double m_MinSkill; - public readonly double m_MaxSkill; - public readonly Type[] m_Types; - - public MutateEntry(double reqSkill, double minSkill, double maxSkill, bool deepWater, params Type[] types) - { - m_ReqSkill = reqSkill; - m_MinSkill = minSkill; - m_MaxSkill = maxSkill; - m_DeepWater = deepWater; - m_Types = types; - } - } - } -} +using System; +using System.Linq; +using Server.Engines.Quests; +using Server.Engines.Quests.Collector; +using Server.Items; +using Server.Mobiles; +using Server.Spells; + +namespace Server.Engines.Harvest +{ + public class Fishing : HarvestSystem + { + private static Fishing m_System; + + private static readonly MutateEntry[] m_MutateTable = + { + new MutateEntry(80.0, 80.0, 4080.0, true, typeof(SpecialFishingNet)), + new MutateEntry(80.0, 80.0, 4080.0, true, typeof(BigFish)), + new MutateEntry(90.0, 80.0, 4080.0, true, typeof(TreasureMap)), + new MutateEntry(100.0, 80.0, 4080.0, true, typeof(MessageInABottle)), + new MutateEntry( + 0.0, + 125.0, + -2375.0, + false, + typeof(PrizedFish), + typeof(WondrousFish), + typeof(TrulyRareFish), + typeof(PeculiarFish) + ), + new MutateEntry(0.0, 105.0, -420.0, false, typeof(Boots), typeof(Shoes), typeof(Sandals), typeof(ThighBoots)), + new MutateEntry(0.0, 200.0, -200.0, false, new Type[] { null }) + }; + + private static readonly int[] m_WaterTiles = + { + 0x00A8, 0x00AB, + 0x0136, 0x0137, + 0x5797, 0x579C, + 0x746E, 0x7485, + 0x7490, 0x74AB, + 0x74B5, 0x75D5 + }; + + private Fishing() + { + var fish = new HarvestDefinition + { + BankWidth = 8, + BankHeight = 8, + MinTotal = 5, + MaxTotal = 15, + MinRespawn = TimeSpan.FromMinutes(10.0), + MaxRespawn = TimeSpan.FromMinutes(20.0), + Skill = SkillName.Fishing, + Tiles = m_WaterTiles, + RangedTiles = true, + MaxRange = 4, + ConsumedPerHarvest = 1, + ConsumedPerFeluccaHarvest = 1, + EffectActions = new[] { 12 }, + EffectSounds = Array.Empty(), + EffectCounts = new[] { 1 }, + EffectDelay = TimeSpan.Zero, + EffectSoundDelay = TimeSpan.FromSeconds(8.0), + NoResourcesMessage = 503172, // The fish don't seem to be biting here. + FailMessage = 503171, // You fish a while, but fail to catch anything. + TimedOutOfRangeMessage = 500976, // You need to be closer to the water to fish! + OutOfRangeMessage = 500976, // You need to be closer to the water to fish! + PackFullMessage = 503176, // You do not have room in your backpack for a fish. + ToolBrokeMessage = 503174 // You broke your fishing pole. + }; + + HarvestResource[] res = + { + new HarvestResource(00.0, 00.0, 100.0, 1043297, typeof(Fish)) + }; + + HarvestVein[] veins = + { + new HarvestVein(1000, 0.0, res[0], null) + }; + + fish.Resources = res; + fish.Veins = veins; + + if (Core.ML) + fish.BonusResources = new[] + { + new BonusHarvestResource(0, 99.4, null, null), // set to same chance as mining ml gems + new BonusHarvestResource(80.0, .6, 1072597, typeof(WhitePearl)) + }; + + Definitions.Add(fish); + } + + public static Fishing System => m_System ?? (m_System = new Fishing()); + + public override void OnConcurrentHarvest(Mobile from, Item tool, HarvestDefinition def, object toHarvest) + { + from.SendLocalizedMessage(500972); // You are already fishing. + } + + public override bool SpecialHarvest(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc) + { + if (from is PlayerMobile player) + { + var qs = player.Quest; + + if (qs is CollectorQuest) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + if (Utility.RandomDouble() < 0.5) + { + player.SendLocalizedMessage( + 1055086, + "", + 0x59 + ); // You pull a shellfish out of the water, and find a rainbow pearl inside of it. + + obj.CurProgress++; + } + else + { + player.SendLocalizedMessage( + 1055087, + "", + 0x2C + ); // You pull a shellfish out of the water, but it doesn't have a rainbow pearl. + } + + return true; + } + } + } + + return false; + } + + public override Type MutateType( + Type type, Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, + HarvestResource resource + ) + { + var deepWater = SpecialFishingNet.FullValidation(map, loc.X, loc.Y); + + var skillBase = from.Skills.Fishing.Base; + var skillValue = from.Skills.Fishing.Value; + + for (var i = 0; i < m_MutateTable.Length; ++i) + { + var entry = m_MutateTable[i]; + + if (!deepWater && entry.m_DeepWater) + continue; + + if (skillBase >= entry.m_ReqSkill) + { + var chance = (skillValue - entry.m_MinSkill) / (entry.m_MaxSkill - entry.m_MinSkill); + + if (chance > Utility.RandomDouble()) + return entry.m_Types.RandomElement(); + } + } + + return type; + } + + private static Map SafeMap(Map map) => map == null || map == Map.Internal ? Map.Trammel : map; + + public override bool CheckResources(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, bool timed) + { + return from?.Backpack?.FindItemsByType() + .Any( + sos => + (from.Map == Map.Felucca || from.Map == Map.Trammel) && from.InRange(sos.TargetLocation, 60) + ) ?? + base.CheckResources(from, tool, def, map, loc, timed); + } + + public override Item Construct(Type type, Mobile from) + { + if (type == typeof(TreasureMap)) + { + int level; + if (from is PlayerMobile mobile && mobile.Young && mobile.Map == Map.Trammel && + TreasureMap.IsInHavenIsland(from)) + level = 0; + else + level = 1; + + return new TreasureMap(level, from.Map == Map.Felucca ? Map.Felucca : Map.Trammel); + } + + if (type == typeof(MessageInABottle)) + return new MessageInABottle(from.Map == Map.Felucca ? Map.Felucca : Map.Trammel); + + var pack = from.Backpack; + + if (pack != null) + { + var messages = pack.FindItemsByType(); + + for (var i = 0; i < messages.Count; ++i) + { + var sos = messages[i]; + + if ((from.Map == Map.Felucca || from.Map == Map.Trammel) && from.InRange(sos.TargetLocation, 60)) + { + Item preLoot = null; + + switch (Utility.Random(8)) + { + case 0: // Body parts + { + int[] list = + { + 0x1CDD, 0x1CE5, // arm + 0x1CE0, 0x1CE8, // torso + 0x1CE1, 0x1CE9, // head + 0x1CE2, 0x1CEC // leg + }; + + preLoot = new ShipwreckedItem(list.RandomElement()); + break; + } + case 1: // Bone parts + { + int[] list = + { + 0x1AE0, 0x1AE1, 0x1AE2, 0x1AE3, 0x1AE4, // skulls + 0x1B09, 0x1B0A, 0x1B0B, 0x1B0C, 0x1B0D, 0x1B0E, 0x1B0F, 0x1B10, // bone piles + 0x1B15, 0x1B16 // pelvis bones + }; + + preLoot = new ShipwreckedItem(list.RandomElement()); + break; + } + case 2: // Paintings and portraits + { + preLoot = new ShipwreckedItem(Utility.Random(0xE9F, 10)); + break; + } + case 3: // Pillows + { + preLoot = new ShipwreckedItem(Utility.Random(0x13A4, 11)); + break; + } + case 4: // Shells + { + preLoot = new ShipwreckedItem(Utility.Random(0xFC4, 9)); + break; + } + case 5: // Hats + { + if (Utility.RandomBool()) + preLoot = new SkullCap(); + else + preLoot = new TricorneHat(); + + break; + } + case 6: // Misc + { + int[] list = + { + 0x1EB5, // unfinished barrel + 0xA2A, // stool + 0xC1F, // broken clock + 0x1047, 0x1048, // globe + 0x1EB1, 0x1EB2, 0x1EB3, 0x1EB4 // barrel staves + }; + + if (Utility.Random(list.Length + 1) == 0) + preLoot = new Candelabra(); + else + preLoot = new ShipwreckedItem(list.RandomElement()); + + break; + } + } + + if (preLoot != null) + { + ((IShipwreckedItem)preLoot).IsShipwreckedItem = true; + return preLoot; + } + + LockableContainer chest; + + if (Utility.RandomBool()) + chest = new MetalGoldenChest(); + else + chest = new WoodenChest(); + + if (sos.IsAncient) + chest.Hue = 0x481; + + TreasureMapChest.Fill(chest, Math.Max(1, Math.Min(4, sos.Level))); + + chest.DropItem(sos.IsAncient ? new FabledFishingNet() : new SpecialFishingNet()); + + chest.Movable = true; + chest.Locked = false; + chest.TrapType = TrapType.None; + chest.TrapPower = 0; + chest.TrapLevel = 0; + + sos.Delete(); + + return chest; + } + } + } + + return base.Construct(type, from); + } + + public override bool Give(Mobile m, Item item, bool placeAtFeet) + { + if (item is TreasureMap || item is MessageInABottle || item is SpecialFishingNet) + { + BaseCreature serp; + + if (Utility.RandomDouble() < 0.25) + serp = new DeepSeaSerpent(); + else + serp = new SeaSerpent(); + + int x = m.X, y = m.Y; + + var map = m.Map; + + for (var i = 0; map != null && i < 20; ++i) + { + var tx = m.X - 10 + Utility.Random(21); + var ty = m.Y - 10 + Utility.Random(21); + + var t = map.Tiles.GetLandTile(tx, ty); + + if (t.Z == -5 && (t.ID >= 0xA8 && t.ID <= 0xAB || t.ID >= 0x136 && t.ID <= 0x137) && + !SpellHelper.CheckMulti(new Point3D(tx, ty, -5), map)) + { + x = tx; + y = ty; + break; + } + } + + serp.MoveToWorld(new Point3D(x, y, -5), map); + + serp.Home = serp.Location; + serp.RangeHome = 10; + + serp.PackItem(item); + + m.SendLocalizedMessage(503170); // Uh oh! That doesn't look like a fish! + + return true; // we don't want to give the item to the player, it's on the serpent + } + + return base.Give(m, item, placeAtFeet || item is BigFish || item is WoodenChest || item is MetalGoldenChest); + } + + public override void SendSuccessTo(Mobile from, Item item, HarvestResource resource) + { + if (item is BigFish fish) + { + from.SendLocalizedMessage(1042635); // Your fishing pole bends as you pull a big fish from the depths! + fish.Fisher = from; + } + else if (item is WoodenChest || item is MetalGoldenChest) + { + from.SendLocalizedMessage(503175); // You pull up a heavy chest from the depths of the ocean! + } + else + { + int number; + string name; + + if (item is BaseMagicFish) + { + number = 1008124; + name = "a mess of small fish"; + } + else if (item is Fish) + { + number = 1008124; + name = item.ItemData.Name; + } + else if (item is BaseShoes) + { + number = 1008124; + name = item.ItemData.Name; + } + else if (item is TreasureMap) + { + number = 1008125; + name = "a sodden piece of parchment"; + } + else if (item is MessageInABottle) + { + number = 1008125; + name = "a bottle, with a message in it"; + } + else if (item is SpecialFishingNet) + { + number = 1008125; + name = "a special fishing net"; // TODO: this is just a guess--what should it really be named? + } + else + { + number = 1043297; + + if ((item.ItemData.Flags & TileFlag.ArticleA) != 0) + name = $"a {item.ItemData.Name}"; + else if ((item.ItemData.Flags & TileFlag.ArticleAn) != 0) + name = $"an {item.ItemData.Name}"; + else + name = item.ItemData.Name; + } + + var ns = from.NetState; + + if (ns == null) + return; + + if (number == 1043297 || ns.HighSeas) + from.SendLocalizedMessage(number, name); + else + from.SendLocalizedMessage(number, true, name); + } + } + + public override void OnHarvestStarted(Mobile from, Item tool, HarvestDefinition def, object toHarvest) + { + base.OnHarvestStarted(from, tool, def, toHarvest); + + if (GetHarvestDetails(from, tool, toHarvest, out _, out var map, out var loc)) + Timer.DelayCall( + TimeSpan.FromSeconds(1.5), + () => + { + if (Core.ML) + from.RevealingAction(); + + Effects.SendLocationEffect(loc, map, 0x352D, 16, 4); + Effects.PlaySound(loc, map, 0x364); + } + ); + } + + public override void OnHarvestFinished( + Mobile from, Item tool, HarvestDefinition def, HarvestVein vein, + HarvestBank bank, HarvestResource resource, object harvested + ) + { + base.OnHarvestFinished(from, tool, def, vein, bank, resource, harvested); + + if (Core.ML) + from.RevealingAction(); + } + + public override object GetLock(Mobile from, Item tool, HarvestDefinition def, object toHarvest) => this; + + public override bool BeginHarvesting(Mobile from, Item tool) + { + if (!base.BeginHarvesting(from, tool)) + return false; + + from.SendLocalizedMessage(500974); // What water do you want to fish in? + return true; + } + + public override bool CheckHarvest(Mobile from, Item tool) + { + if (!base.CheckHarvest(from, tool)) + return false; + + if (from.Mounted) + { + from.SendLocalizedMessage(500971); // You can't fish while riding! + return false; + } + + return true; + } + + public override bool CheckHarvest(Mobile from, Item tool, HarvestDefinition def, object toHarvest) + { + if (!base.CheckHarvest(from, tool, def, toHarvest)) + return false; + + if (from.Mounted) + { + from.SendLocalizedMessage(500971); // You can't fish while riding! + return false; + } + + return true; + } + + private class MutateEntry + { + public readonly bool m_DeepWater; + public readonly double m_MaxSkill; + public readonly double m_MinSkill; + public readonly double m_ReqSkill; + public readonly Type[] m_Types; + + public MutateEntry(double reqSkill, double minSkill, double maxSkill, bool deepWater, params Type[] types) + { + m_ReqSkill = reqSkill; + m_MinSkill = minSkill; + m_MaxSkill = maxSkill; + m_DeepWater = deepWater; + m_Types = types; + } + } + } +} diff --git a/Projects/UOContent/Engines/Harvest/Lumberjacking.cs b/Projects/UOContent/Engines/Harvest/Lumberjacking.cs index c13dd2240..1f98d9db8 100644 --- a/Projects/UOContent/Engines/Harvest/Lumberjacking.cs +++ b/Projects/UOContent/Engines/Harvest/Lumberjacking.cs @@ -1,179 +1,183 @@ -using System; -using Server.Items; -using Server.Network; -using Server.Targeting; - -namespace Server.Engines.Harvest -{ - public class Lumberjacking : HarvestSystem - { - private static Lumberjacking m_System; - - private static readonly int[] m_TreeTiles = - { - 0x4CCA, 0x4CCB, 0x4CCC, 0x4CCD, 0x4CD0, 0x4CD3, 0x4CD6, 0x4CD8, - 0x4CDA, 0x4CDD, 0x4CE0, 0x4CE3, 0x4CE6, 0x4CF8, 0x4CFB, 0x4CFE, - 0x4D01, 0x4D41, 0x4D42, 0x4D43, 0x4D44, 0x4D57, 0x4D58, 0x4D59, - 0x4D5A, 0x4D5B, 0x4D6E, 0x4D6F, 0x4D70, 0x4D71, 0x4D72, 0x4D84, - 0x4D85, 0x4D86, 0x52B5, 0x52B6, 0x52B7, 0x52B8, 0x52B9, 0x52BA, - 0x52BB, 0x52BC, 0x52BD, - - 0x4CCE, 0x4CCF, 0x4CD1, 0x4CD2, 0x4CD4, 0x4CD5, 0x4CD7, 0x4CD9, - 0x4CDB, 0x4CDC, 0x4CDE, 0x4CDF, 0x4CE1, 0x4CE2, 0x4CE4, 0x4CE5, - 0x4CE7, 0x4CE8, 0x4CF9, 0x4CFA, 0x4CFC, 0x4CFD, 0x4CFF, 0x4D00, - 0x4D02, 0x4D03, 0x4D45, 0x4D46, 0x4D47, 0x4D48, 0x4D49, 0x4D4A, - 0x4D4B, 0x4D4C, 0x4D4D, 0x4D4E, 0x4D4F, 0x4D50, 0x4D51, 0x4D52, - 0x4D53, 0x4D5C, 0x4D5D, 0x4D5E, 0x4D5F, 0x4D60, 0x4D61, 0x4D62, - 0x4D63, 0x4D64, 0x4D65, 0x4D66, 0x4D67, 0x4D68, 0x4D69, 0x4D73, - 0x4D74, 0x4D75, 0x4D76, 0x4D77, 0x4D78, 0x4D79, 0x4D7A, 0x4D7B, - 0x4D7C, 0x4D7D, 0x4D7E, 0x4D7F, 0x4D87, 0x4D88, 0x4D89, 0x4D8A, - 0x4D8B, 0x4D8C, 0x4D8D, 0x4D8E, 0x4D8F, 0x4D90, 0x4D95, 0x4D96, - 0x4D97, 0x4D99, 0x4D9A, 0x4D9B, 0x4D9D, 0x4D9E, 0x4D9F, 0x4DA1, - 0x4DA2, 0x4DA3, 0x4DA5, 0x4DA6, 0x4DA7, 0x4DA9, 0x4DAA, 0x4DAB, - 0x52BE, 0x52BF, 0x52C0, 0x52C1, 0x52C2, 0x52C3, 0x52C4, 0x52C5, - 0x52C6, 0x52C7 - }; - - private Lumberjacking() - { - HarvestResource[] res; - HarvestVein[] veins; - - HarvestDefinition lumber = new HarvestDefinition - { - BankWidth = 4, - BankHeight = 3, - MinTotal = 20, - MaxTotal = 45, - MinRespawn = TimeSpan.FromMinutes(20.0), - MaxRespawn = TimeSpan.FromMinutes(30.0), - Skill = SkillName.Lumberjacking, - Tiles = m_TreeTiles, - MaxRange = 2, - ConsumedPerHarvest = 10, - ConsumedPerFeluccaHarvest = 20, - EffectActions = new[] { 13 }, - EffectSounds = new[] { 0x13E }, - EffectCounts = Core.AOS ? new[] { 1 } : new[] { 1, 2, 2, 2, 3 }, - EffectDelay = TimeSpan.FromSeconds(1.6), - EffectSoundDelay = TimeSpan.FromSeconds(0.9), - NoResourcesMessage = 500493, // There's not enough wood here to harvest. - FailMessage = 500495, // You hack at the tree for a while, but fail to produce any useable wood. - OutOfRangeMessage = 500446, // That is too far away. - PackFullMessage = 500497, // You can't place any wood into your backpack! - ToolBrokeMessage = 500499 // You broke your axe. - }; - - if (Core.ML) - { - res = new[] - { - new HarvestResource(00.0, 00.0, 100.0, 1072540, typeof(Log)), - new HarvestResource(65.0, 25.0, 105.0, 1072541, typeof(OakLog)), - new HarvestResource(80.0, 40.0, 120.0, 1072542, typeof(AshLog)), - new HarvestResource(95.0, 55.0, 135.0, 1072543, typeof(YewLog)), - new HarvestResource(100.0, 60.0, 140.0, 1072544, typeof(HeartwoodLog)), - new HarvestResource(100.0, 60.0, 140.0, 1072545, typeof(BloodwoodLog)), - new HarvestResource(100.0, 60.0, 140.0, 1072546, typeof(FrostwoodLog)) - }; - - veins = new[] - { - new HarvestVein(490, 0.0, res[0], null), // Ordinary Logs - new HarvestVein(300, 0.5, res[1], res[0]), // Oak - new HarvestVein(100, 0.5, res[2], res[0]), // Ash - new HarvestVein(050, 0.5, res[3], res[0]), // Yew - new HarvestVein(030, 0.5, res[4], res[0]), // Heartwood - new HarvestVein(020, 0.5, res[5], res[0]), // Bloodwood - new HarvestVein(010, 0.5, res[6], res[0]) // Frostwood - }; - - lumber.BonusResources = new[] - { - new BonusHarvestResource(0, 83.9, null, null), // Nothing - new BonusHarvestResource(100, 10.0, 1072548, typeof(BarkFragment)), - new BonusHarvestResource(100, 03.0, 1072550, typeof(LuminescentFungi)), - new BonusHarvestResource(100, 02.0, 1072547, typeof(SwitchItem)), - new BonusHarvestResource(100, 01.0, 1072549, typeof(ParasiticPlant)), - new BonusHarvestResource(100, 00.1, 1072551, typeof(BrilliantAmber)) - }; - } - else - { - res = new[] - { - new HarvestResource(00.0, 00.0, 100.0, 500498, typeof(Log)) - }; - - veins = new[] - { - new HarvestVein(1000, 0.0, res[0], null) - }; - } - - lumber.Resources = res; - lumber.Veins = veins; - - lumber.RaceBonus = Core.ML; - lumber.RandomizeVeins = Core.ML; - - Definitions.Add(lumber); - } - - public static Lumberjacking System => m_System ?? (m_System = new Lumberjacking()); - - public override bool CheckHarvest(Mobile from, Item tool) - { - if (!base.CheckHarvest(from, tool)) - return false; - - if (tool.Parent != from) - { - from.SendLocalizedMessage(500487); // The axe must be equipped for any serious wood chopping. - return false; - } - - return true; - } - - public override bool CheckHarvest(Mobile from, Item tool, HarvestDefinition def, object toHarvest) - { - if (!base.CheckHarvest(from, tool, def, toHarvest)) - return false; - - if (tool.Parent != from) - { - from.SendLocalizedMessage(500487); // The axe must be equipped for any serious wood chopping. - return false; - } - - return true; - } - - public override void OnBadHarvestTarget(Mobile from, Item tool, object toHarvest) - { - if (toHarvest is Mobile mobile) - mobile.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 500450, - from.NetState); // You can only skin dead creatures. - else if (toHarvest is Item item) - item.LabelTo(from, 500464); // Use this on corpses to carve away meat and hide - else if (toHarvest is StaticTarget || toHarvest is LandTarget) - from.SendLocalizedMessage(500489); // You can't use an axe on that. - else - from.SendLocalizedMessage(1005213); // You can't do that - } - - public override void OnHarvestStarted(Mobile from, Item tool, HarvestDefinition def, object toHarvest) - { - base.OnHarvestStarted(from, tool, def, toHarvest); - - if (Core.ML) - from.RevealingAction(); - } - - public static void Initialize() - { - Array.Sort(m_TreeTiles); - } - } -} +using System; +using Server.Items; +using Server.Network; +using Server.Targeting; + +namespace Server.Engines.Harvest +{ + public class Lumberjacking : HarvestSystem + { + private static Lumberjacking m_System; + + private static readonly int[] m_TreeTiles = + { + 0x4CCA, 0x4CCB, 0x4CCC, 0x4CCD, 0x4CD0, 0x4CD3, 0x4CD6, 0x4CD8, + 0x4CDA, 0x4CDD, 0x4CE0, 0x4CE3, 0x4CE6, 0x4CF8, 0x4CFB, 0x4CFE, + 0x4D01, 0x4D41, 0x4D42, 0x4D43, 0x4D44, 0x4D57, 0x4D58, 0x4D59, + 0x4D5A, 0x4D5B, 0x4D6E, 0x4D6F, 0x4D70, 0x4D71, 0x4D72, 0x4D84, + 0x4D85, 0x4D86, 0x52B5, 0x52B6, 0x52B7, 0x52B8, 0x52B9, 0x52BA, + 0x52BB, 0x52BC, 0x52BD, + + 0x4CCE, 0x4CCF, 0x4CD1, 0x4CD2, 0x4CD4, 0x4CD5, 0x4CD7, 0x4CD9, + 0x4CDB, 0x4CDC, 0x4CDE, 0x4CDF, 0x4CE1, 0x4CE2, 0x4CE4, 0x4CE5, + 0x4CE7, 0x4CE8, 0x4CF9, 0x4CFA, 0x4CFC, 0x4CFD, 0x4CFF, 0x4D00, + 0x4D02, 0x4D03, 0x4D45, 0x4D46, 0x4D47, 0x4D48, 0x4D49, 0x4D4A, + 0x4D4B, 0x4D4C, 0x4D4D, 0x4D4E, 0x4D4F, 0x4D50, 0x4D51, 0x4D52, + 0x4D53, 0x4D5C, 0x4D5D, 0x4D5E, 0x4D5F, 0x4D60, 0x4D61, 0x4D62, + 0x4D63, 0x4D64, 0x4D65, 0x4D66, 0x4D67, 0x4D68, 0x4D69, 0x4D73, + 0x4D74, 0x4D75, 0x4D76, 0x4D77, 0x4D78, 0x4D79, 0x4D7A, 0x4D7B, + 0x4D7C, 0x4D7D, 0x4D7E, 0x4D7F, 0x4D87, 0x4D88, 0x4D89, 0x4D8A, + 0x4D8B, 0x4D8C, 0x4D8D, 0x4D8E, 0x4D8F, 0x4D90, 0x4D95, 0x4D96, + 0x4D97, 0x4D99, 0x4D9A, 0x4D9B, 0x4D9D, 0x4D9E, 0x4D9F, 0x4DA1, + 0x4DA2, 0x4DA3, 0x4DA5, 0x4DA6, 0x4DA7, 0x4DA9, 0x4DAA, 0x4DAB, + 0x52BE, 0x52BF, 0x52C0, 0x52C1, 0x52C2, 0x52C3, 0x52C4, 0x52C5, + 0x52C6, 0x52C7 + }; + + private Lumberjacking() + { + HarvestResource[] res; + HarvestVein[] veins; + + var lumber = new HarvestDefinition + { + BankWidth = 4, + BankHeight = 3, + MinTotal = 20, + MaxTotal = 45, + MinRespawn = TimeSpan.FromMinutes(20.0), + MaxRespawn = TimeSpan.FromMinutes(30.0), + Skill = SkillName.Lumberjacking, + Tiles = m_TreeTiles, + MaxRange = 2, + ConsumedPerHarvest = 10, + ConsumedPerFeluccaHarvest = 20, + EffectActions = new[] { 13 }, + EffectSounds = new[] { 0x13E }, + EffectCounts = Core.AOS ? new[] { 1 } : new[] { 1, 2, 2, 2, 3 }, + EffectDelay = TimeSpan.FromSeconds(1.6), + EffectSoundDelay = TimeSpan.FromSeconds(0.9), + NoResourcesMessage = 500493, // There's not enough wood here to harvest. + FailMessage = 500495, // You hack at the tree for a while, but fail to produce any useable wood. + OutOfRangeMessage = 500446, // That is too far away. + PackFullMessage = 500497, // You can't place any wood into your backpack! + ToolBrokeMessage = 500499 // You broke your axe. + }; + + if (Core.ML) + { + res = new[] + { + new HarvestResource(00.0, 00.0, 100.0, 1072540, typeof(Log)), + new HarvestResource(65.0, 25.0, 105.0, 1072541, typeof(OakLog)), + new HarvestResource(80.0, 40.0, 120.0, 1072542, typeof(AshLog)), + new HarvestResource(95.0, 55.0, 135.0, 1072543, typeof(YewLog)), + new HarvestResource(100.0, 60.0, 140.0, 1072544, typeof(HeartwoodLog)), + new HarvestResource(100.0, 60.0, 140.0, 1072545, typeof(BloodwoodLog)), + new HarvestResource(100.0, 60.0, 140.0, 1072546, typeof(FrostwoodLog)) + }; + + veins = new[] + { + new HarvestVein(490, 0.0, res[0], null), // Ordinary Logs + new HarvestVein(300, 0.5, res[1], res[0]), // Oak + new HarvestVein(100, 0.5, res[2], res[0]), // Ash + new HarvestVein(050, 0.5, res[3], res[0]), // Yew + new HarvestVein(030, 0.5, res[4], res[0]), // Heartwood + new HarvestVein(020, 0.5, res[5], res[0]), // Bloodwood + new HarvestVein(010, 0.5, res[6], res[0]) // Frostwood + }; + + lumber.BonusResources = new[] + { + new BonusHarvestResource(0, 83.9, null, null), // Nothing + new BonusHarvestResource(100, 10.0, 1072548, typeof(BarkFragment)), + new BonusHarvestResource(100, 03.0, 1072550, typeof(LuminescentFungi)), + new BonusHarvestResource(100, 02.0, 1072547, typeof(SwitchItem)), + new BonusHarvestResource(100, 01.0, 1072549, typeof(ParasiticPlant)), + new BonusHarvestResource(100, 00.1, 1072551, typeof(BrilliantAmber)) + }; + } + else + { + res = new[] + { + new HarvestResource(00.0, 00.0, 100.0, 500498, typeof(Log)) + }; + + veins = new[] + { + new HarvestVein(1000, 0.0, res[0], null) + }; + } + + lumber.Resources = res; + lumber.Veins = veins; + + lumber.RaceBonus = Core.ML; + lumber.RandomizeVeins = Core.ML; + + Definitions.Add(lumber); + } + + public static Lumberjacking System => m_System ?? (m_System = new Lumberjacking()); + + public override bool CheckHarvest(Mobile from, Item tool) + { + if (!base.CheckHarvest(from, tool)) + return false; + + if (tool.Parent != from) + { + from.SendLocalizedMessage(500487); // The axe must be equipped for any serious wood chopping. + return false; + } + + return true; + } + + public override bool CheckHarvest(Mobile from, Item tool, HarvestDefinition def, object toHarvest) + { + if (!base.CheckHarvest(from, tool, def, toHarvest)) + return false; + + if (tool.Parent != from) + { + from.SendLocalizedMessage(500487); // The axe must be equipped for any serious wood chopping. + return false; + } + + return true; + } + + public override void OnBadHarvestTarget(Mobile from, Item tool, object toHarvest) + { + if (toHarvest is Mobile mobile) + mobile.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 500450, + from.NetState + ); // You can only skin dead creatures. + else if (toHarvest is Item item) + item.LabelTo(from, 500464); // Use this on corpses to carve away meat and hide + else if (toHarvest is StaticTarget || toHarvest is LandTarget) + from.SendLocalizedMessage(500489); // You can't use an axe on that. + else + from.SendLocalizedMessage(1005213); // You can't do that + } + + public override void OnHarvestStarted(Mobile from, Item tool, HarvestDefinition def, object toHarvest) + { + base.OnHarvestStarted(from, tool, def, toHarvest); + + if (Core.ML) + from.RevealingAction(); + } + + public static void Initialize() + { + Array.Sort(m_TreeTiles); + } + } +} diff --git a/Projects/UOContent/Engines/Harvest/Mining.cs b/Projects/UOContent/Engines/Harvest/Mining.cs index 8242b4b00..679b3de97 100644 --- a/Projects/UOContent/Engines/Harvest/Mining.cs +++ b/Projects/UOContent/Engines/Harvest/Mining.cs @@ -1,381 +1,445 @@ -using System; -using Server.Items; -using Server.Mobiles; -using Server.Targeting; -using Server.Utilities; - -namespace Server.Engines.Harvest -{ - public class Mining : HarvestSystem - { - private static Mining m_System; - - private static readonly int[] m_Offsets = - { - -1, -1, - -1, 0, - -1, 1, - 0, -1, - 0, 1, - 1, -1, - 1, 0, - 1, 1 - }; - - private Mining() - { - OreAndStone = new HarvestDefinition - { - BankWidth = 8, - BankHeight = 8, - MinTotal = 10, - MaxTotal = 34, - MinRespawn = TimeSpan.FromMinutes(10.0), - MaxRespawn = TimeSpan.FromMinutes(20.0), - Skill = SkillName.Mining, - Tiles = m_MountainAndCaveTiles, - MaxRange = 2, - ConsumedPerHarvest = 1, - ConsumedPerFeluccaHarvest = 2, - EffectActions = new[] { 11 }, - EffectSounds = new[] { 0x125, 0x126 }, - EffectCounts = new[] { 1 }, - EffectDelay = TimeSpan.FromSeconds(1.6), - EffectSoundDelay = TimeSpan.FromSeconds(0.9), - NoResourcesMessage = 503040, // There is no metal here to mine. - DoubleHarvestMessage = 503042, // Someone has gotten to the metal before you. - TimedOutOfRangeMessage = 503041, // You have moved too far away to continue mining. - OutOfRangeMessage = 500446, // That is too far away. - FailMessage = 503043, // You loosen some rocks but fail to find any useable ore. - PackFullMessage = 1010481, // Your backpack is full, so the ore you mined is lost. - ToolBrokeMessage = 1044038 // You have worn out your tool! - }; - - HarvestResource[] res = { - new HarvestResource(00.0, 00.0, 100.0, 1007072, typeof(IronOre), typeof(Granite)), - new HarvestResource(65.0, 25.0, 105.0, 1007073, typeof(DullCopperOre), typeof(DullCopperGranite), - typeof(DullCopperElemental)), - new HarvestResource(70.0, 30.0, 110.0, 1007074, typeof(ShadowIronOre), typeof(ShadowIronGranite), - typeof(ShadowIronElemental)), - new HarvestResource(75.0, 35.0, 115.0, 1007075, typeof(CopperOre), typeof(CopperGranite), - typeof(CopperElemental)), - new HarvestResource(80.0, 40.0, 120.0, 1007076, typeof(BronzeOre), typeof(BronzeGranite), - typeof(BronzeElemental)), - new HarvestResource(85.0, 45.0, 125.0, 1007077, typeof(GoldOre), typeof(GoldGranite), - typeof(GoldenElemental)), - new HarvestResource(90.0, 50.0, 130.0, 1007078, typeof(AgapiteOre), typeof(AgapiteGranite), - typeof(AgapiteElemental)), - new HarvestResource(95.0, 55.0, 135.0, 1007079, typeof(VeriteOre), typeof(VeriteGranite), - typeof(VeriteElemental)), - new HarvestResource(99.0, 59.0, 139.0, 1007080, typeof(ValoriteOre), typeof(ValoriteGranite), - typeof(ValoriteElemental)) - }; - - HarvestVein[] veins = { - new HarvestVein(496, 0.0, res[0], null), // Iron - new HarvestVein(112, 0.5, res[1], res[0]), // Dull Copper - new HarvestVein(098, 0.5, res[2], res[0]), // Shadow Iron - new HarvestVein(084, 0.5, res[3], res[0]), // Copper - new HarvestVein(070, 0.5, res[4], res[0]), // Bronze - new HarvestVein(056, 0.5, res[5], res[0]), // Gold - new HarvestVein(042, 0.5, res[6], res[0]), // Agapite - new HarvestVein(028, 0.5, res[7], res[0]), // Verite - new HarvestVein(014, 0.5, res[8], res[0]) // Valorite - }; - - OreAndStone.Resources = res; - OreAndStone.Veins = veins; - - if (Core.ML) - OreAndStone.BonusResources = new[] - { - new BonusHarvestResource(0, 99.4, null, null), // Nothing - new BonusHarvestResource(100, .1, 1072562, typeof(BlueDiamond)), - new BonusHarvestResource(100, .1, 1072567, typeof(DarkSapphire)), - new BonusHarvestResource(100, .1, 1072570, typeof(EcruCitrine)), - new BonusHarvestResource(100, .1, 1072564, typeof(FireRuby)), - new BonusHarvestResource(100, .1, 1072566, typeof(PerfectEmerald)), - new BonusHarvestResource(100, .1, 1072568, typeof(Turquoise)) - }; - - OreAndStone.RaceBonus = Core.ML; - OreAndStone.RandomizeVeins = Core.ML; - - Definitions.Add(OreAndStone); - - Sand = new HarvestDefinition - { - BankWidth = 8, - BankHeight = 8, - MinTotal = 6, - MaxTotal = 12, - MinRespawn = TimeSpan.FromMinutes(10.0), - MaxRespawn = TimeSpan.FromMinutes(20.0), - Skill = SkillName.Mining, - Tiles = m_SandTiles, - MaxRange = 2, - ConsumedPerHarvest = 1, - ConsumedPerFeluccaHarvest = 1, - EffectActions = new[] { 11 }, - EffectSounds = new[] { 0x125, 0x126 }, - EffectCounts = new[] { 6 }, - EffectDelay = TimeSpan.FromSeconds(1.6), - EffectSoundDelay = TimeSpan.FromSeconds(0.9), - NoResourcesMessage = 1044629, // There is no sand here to mine. - DoubleHarvestMessage = 1044629, // There is no sand here to mine. - TimedOutOfRangeMessage = 503041, // You have moved too far away to continue mining. - OutOfRangeMessage = 500446, // That is too far away. - FailMessage = 1044630, // You dig for a while but fail to find any of sufficient quality for glassblowing. - PackFullMessage = 1044632, // Your backpack can't hold the sand, and it is lost! - ToolBrokeMessage = 1044038 // You have worn out your tool! - }; - - res = new[] - { - new HarvestResource(100.0, 70.0, 400.0, 1044631, typeof(Sand)) - }; - - veins = new[] - { - new HarvestVein(1000, 0.0, res[0], null) - }; - - Sand.Resources = res; - Sand.Veins = veins; - - Definitions.Add(Sand); - } - - public static Mining System => m_System ?? (m_System = new Mining()); - - public HarvestDefinition OreAndStone { get; } - - public HarvestDefinition Sand { get; } - - public override Type GetResourceType(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, - HarvestResource resource) - { - if (def != OreAndStone) - return base.GetResourceType(from, tool, def, map, loc, resource); - - if (from.Skills.Mining.Base >= 100.0 && from is PlayerMobile pm && pm.StoneMining && pm.ToggleMiningStone - && Utility.RandomDouble() < 0.1) - return resource.Types[1]; - - return resource.Types[0]; - } - - public override bool CheckHarvest(Mobile from, Item tool) - { - if (!base.CheckHarvest(from, tool)) - return false; - - if (from.Mounted) - { - from.SendLocalizedMessage(501864); // You can't mine while riding. - return false; - } - - if (from.IsBodyMod && !from.Body.IsHuman) - { - from.SendLocalizedMessage(501865); // You can't mine while polymorphed. - return false; - } - - return true; - } - - public override void SendSuccessTo(Mobile from, Item item, HarvestResource resource) - { - if (item is BaseGranite) - from.SendLocalizedMessage(1044606); // You carefully extract some workable stone from the ore vein! - else - base.SendSuccessTo(from, item, resource); - } - - public override bool CheckHarvest(Mobile from, Item tool, HarvestDefinition def, object toHarvest) - { - if (!base.CheckHarvest(from, tool, def, toHarvest)) - return false; - - if (def == Sand && !(from is PlayerMobile mobile && mobile.Skills.Mining.Base >= 100.0 && - mobile.SandMining)) - { - OnBadHarvestTarget(from, tool, toHarvest); - return false; - } - - if (from.Mounted) - { - from.SendLocalizedMessage(501864); // You can't mine while riding. - return false; - } - - if (from.IsBodyMod && !from.Body.IsHuman) - { - from.SendLocalizedMessage(501865); // You can't mine while polymorphed. - return false; - } - - return true; - } - - public override HarvestVein MutateVein(Mobile from, Item tool, HarvestDefinition def, HarvestBank bank, - object toHarvest, HarvestVein vein) - { - if (tool is GargoylesPickaxe && def == OreAndStone) - { - int veinIndex = Array.IndexOf(def.Veins, vein); - - if (veinIndex >= 0 && veinIndex < def.Veins.Length - 1) - return def.Veins[veinIndex + 1]; - } - - return base.MutateVein(from, tool, def, bank, toHarvest, vein); - } - - public override void OnHarvestFinished(Mobile from, Item tool, HarvestDefinition def, HarvestVein vein, - HarvestBank bank, HarvestResource resource, object harvested) - { - if (tool is GargoylesPickaxe && def == OreAndStone && Utility.RandomDouble() < 0.1) - { - HarvestResource res = vein.PrimaryResource; - - if (res == resource && res.Types.Length >= 3) - try - { - Map map = from.Map; - - if (map == null) - return; - - if (ActivatorUtil.CreateInstance(res.Types[2], 25) is BaseCreature spawned) - { - int offset = Utility.Random(8) * 2; - - for (int i = 0; i < m_Offsets.Length; i += 2) - { - int x = from.X + m_Offsets[(offset + i) % m_Offsets.Length]; - int y = from.Y + m_Offsets[(offset + i + 1) % m_Offsets.Length]; - - if (map.CanSpawnMobile(x, y, from.Z)) - { - spawned.OnBeforeSpawn(new Point3D(x, y, from.Z), map); - spawned.MoveToWorld(new Point3D(x, y, from.Z), map); - spawned.Combatant = from; - return; - } - - int z = map.GetAverageZ(x, y); - - if (Math.Abs(z - from.Z) < 10 && map.CanSpawnMobile(x, y, z)) - { - spawned.OnBeforeSpawn(new Point3D(x, y, z), map); - spawned.MoveToWorld(new Point3D(x, y, z), map); - spawned.Combatant = from; - return; - } - } - - spawned.OnBeforeSpawn(from.Location, from.Map); - spawned.MoveToWorld(from.Location, from.Map); - spawned.Combatant = from; - } - } - catch - { - // ignored - } - } - } - - public override bool BeginHarvesting(Mobile from, Item tool) - { - if (!base.BeginHarvesting(from, tool)) - return false; - - from.SendLocalizedMessage(503033); // Where do you wish to dig? - return true; - } - - public override void OnHarvestStarted(Mobile from, Item tool, HarvestDefinition def, object toHarvest) - { - base.OnHarvestStarted(from, tool, def, toHarvest); - - if (Core.ML) - from.RevealingAction(); - } - - public override void OnBadHarvestTarget(Mobile from, Item tool, object toHarvest) - { - if (toHarvest is LandTarget) - from.SendLocalizedMessage(501862); // You can't mine there. - else - from.SendLocalizedMessage(501863); // You can't mine that. - } - - private static readonly int[] m_MountainAndCaveTiles = - { - 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, - 230, 231, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, 286, 287, - 288, 289, 290, 291, 292, 293, 294, 296, 296, 297, - 321, 322, 323, 324, 467, 468, 469, 470, 471, 472, - 473, 474, 476, 477, 478, 479, 480, 481, 482, 483, - 484, 485, 486, 487, 492, 493, 494, 495, 543, 544, - 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, - 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, - 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, - 575, 576, 577, 578, 579, 581, 582, 583, 584, 585, - 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, - 596, 597, 598, 599, 600, 601, 610, 611, 612, 613, - - 1010, 1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, - 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1771, 1772, - 1773, 1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, 1782, - 1783, 1784, 1785, 1786, 1787, 1788, 1789, 1790, 1801, 1802, - 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1811, 1812, 1813, - 1814, 1815, 1816, 1817, 1818, 1819, 1820, 1821, 1822, 1823, - 1824, 1831, 1832, 1833, 1834, 1835, 1836, 1837, 1838, 1839, - 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, - 1850, 1851, 1852, 1853, 1854, 1861, 1862, 1863, 1864, 1865, - 1866, 1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875, - 1876, 1877, 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1981, - 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, - 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2028, 2029, 2030, 2031, 2032, 2033, 2100, - 2101, 2102, 2103, 2104, 2105, - - 0x453B, 0x453C, 0x453D, 0x453E, 0x453F, 0x4540, 0x4541, - 0x4542, 0x4543, 0x4544, 0x4545, 0x4546, 0x4547, 0x4548, - 0x4549, 0x454A, 0x454B, 0x454C, 0x454D, 0x454E, 0x454F - }; - - private static readonly int[] m_SandTiles = - { - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 68, 69, 70, 71, 72, 73, 74, 75, - - 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, - 296, 297, 298, 299, 300, 301, 402, 424, 425, 426, - 427, 441, 442, 443, 444, 445, 446, 447, 448, 449, - 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, - 460, 461, 462, 463, 464, 465, 642, 643, 644, 645, - 650, 651, 652, 653, 654, 655, 656, 657, 821, 822, - 823, 824, 825, 826, 827, 828, 833, 834, 835, 836, - 845, 846, 847, 848, 849, 850, 851, 852, 857, 858, - 859, 860, 951, 952, 953, 954, 955, 956, 957, 958, - 967, 968, 969, 970, - - 1447, 1448, 1449, 1450, 1451, 1452, 1453, 1454, 1455, - 1456, 1457, 1458, 1611, 1612, 1613, 1614, 1615, 1616, - 1617, 1618, 1623, 1624, 1625, 1626, 1635, 1636, 1637, - 1638, 1639, 1640, 1641, 1642, 1647, 1648, 1649, 1650 - }; - } -} +using System; +using Server.Items; +using Server.Mobiles; +using Server.Targeting; +using Server.Utilities; + +namespace Server.Engines.Harvest +{ + public class Mining : HarvestSystem + { + private static Mining m_System; + + private static readonly int[] m_Offsets = + { + -1, -1, + -1, 0, + -1, 1, + 0, -1, + 0, 1, + 1, -1, + 1, 0, + 1, 1 + }; + + private static readonly int[] m_MountainAndCaveTiles = + { + 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, + 230, 231, 236, 237, 238, 239, 240, 241, 242, 243, + 244, 245, 246, 247, 252, 253, 254, 255, 256, 257, + 258, 259, 260, 261, 262, 263, 268, 269, 270, 271, + 272, 273, 274, 275, 276, 277, 278, 279, 286, 287, + 288, 289, 290, 291, 292, 293, 294, 296, 296, 297, + 321, 322, 323, 324, 467, 468, 469, 470, 471, 472, + 473, 474, 476, 477, 478, 479, 480, 481, 482, 483, + 484, 485, 486, 487, 492, 493, 494, 495, 543, 544, + 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, + 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, + 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, + 575, 576, 577, 578, 579, 581, 582, 583, 584, 585, + 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, + 596, 597, 598, 599, 600, 601, 610, 611, 612, 613, + + 1010, 1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, + 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1771, 1772, + 1773, 1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, 1782, + 1783, 1784, 1785, 1786, 1787, 1788, 1789, 1790, 1801, 1802, + 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1811, 1812, 1813, + 1814, 1815, 1816, 1817, 1818, 1819, 1820, 1821, 1822, 1823, + 1824, 1831, 1832, 1833, 1834, 1835, 1836, 1837, 1838, 1839, + 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, + 1850, 1851, 1852, 1853, 1854, 1861, 1862, 1863, 1864, 1865, + 1866, 1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875, + 1876, 1877, 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1981, + 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, + 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, + 2002, 2003, 2004, 2028, 2029, 2030, 2031, 2032, 2033, 2100, + 2101, 2102, 2103, 2104, 2105, + + 0x453B, 0x453C, 0x453D, 0x453E, 0x453F, 0x4540, 0x4541, + 0x4542, 0x4543, 0x4544, 0x4545, 0x4546, 0x4547, 0x4548, + 0x4549, 0x454A, 0x454B, 0x454C, 0x454D, 0x454E, 0x454F + }; + + private static readonly int[] m_SandTiles = + { + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 68, 69, 70, 71, 72, 73, 74, 75, + + 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, + 296, 297, 298, 299, 300, 301, 402, 424, 425, 426, + 427, 441, 442, 443, 444, 445, 446, 447, 448, 449, + 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, + 460, 461, 462, 463, 464, 465, 642, 643, 644, 645, + 650, 651, 652, 653, 654, 655, 656, 657, 821, 822, + 823, 824, 825, 826, 827, 828, 833, 834, 835, 836, + 845, 846, 847, 848, 849, 850, 851, 852, 857, 858, + 859, 860, 951, 952, 953, 954, 955, 956, 957, 958, + 967, 968, 969, 970, + + 1447, 1448, 1449, 1450, 1451, 1452, 1453, 1454, 1455, + 1456, 1457, 1458, 1611, 1612, 1613, 1614, 1615, 1616, + 1617, 1618, 1623, 1624, 1625, 1626, 1635, 1636, 1637, + 1638, 1639, 1640, 1641, 1642, 1647, 1648, 1649, 1650 + }; + + private Mining() + { + OreAndStone = new HarvestDefinition + { + BankWidth = 8, + BankHeight = 8, + MinTotal = 10, + MaxTotal = 34, + MinRespawn = TimeSpan.FromMinutes(10.0), + MaxRespawn = TimeSpan.FromMinutes(20.0), + Skill = SkillName.Mining, + Tiles = m_MountainAndCaveTiles, + MaxRange = 2, + ConsumedPerHarvest = 1, + ConsumedPerFeluccaHarvest = 2, + EffectActions = new[] { 11 }, + EffectSounds = new[] { 0x125, 0x126 }, + EffectCounts = new[] { 1 }, + EffectDelay = TimeSpan.FromSeconds(1.6), + EffectSoundDelay = TimeSpan.FromSeconds(0.9), + NoResourcesMessage = 503040, // There is no metal here to mine. + DoubleHarvestMessage = 503042, // Someone has gotten to the metal before you. + TimedOutOfRangeMessage = 503041, // You have moved too far away to continue mining. + OutOfRangeMessage = 500446, // That is too far away. + FailMessage = 503043, // You loosen some rocks but fail to find any useable ore. + PackFullMessage = 1010481, // Your backpack is full, so the ore you mined is lost. + ToolBrokeMessage = 1044038 // You have worn out your tool! + }; + + HarvestResource[] res = + { + new HarvestResource(00.0, 00.0, 100.0, 1007072, typeof(IronOre), typeof(Granite)), + new HarvestResource( + 65.0, + 25.0, + 105.0, + 1007073, + typeof(DullCopperOre), + typeof(DullCopperGranite), + typeof(DullCopperElemental) + ), + new HarvestResource( + 70.0, + 30.0, + 110.0, + 1007074, + typeof(ShadowIronOre), + typeof(ShadowIronGranite), + typeof(ShadowIronElemental) + ), + new HarvestResource( + 75.0, + 35.0, + 115.0, + 1007075, + typeof(CopperOre), + typeof(CopperGranite), + typeof(CopperElemental) + ), + new HarvestResource( + 80.0, + 40.0, + 120.0, + 1007076, + typeof(BronzeOre), + typeof(BronzeGranite), + typeof(BronzeElemental) + ), + new HarvestResource( + 85.0, + 45.0, + 125.0, + 1007077, + typeof(GoldOre), + typeof(GoldGranite), + typeof(GoldenElemental) + ), + new HarvestResource( + 90.0, + 50.0, + 130.0, + 1007078, + typeof(AgapiteOre), + typeof(AgapiteGranite), + typeof(AgapiteElemental) + ), + new HarvestResource( + 95.0, + 55.0, + 135.0, + 1007079, + typeof(VeriteOre), + typeof(VeriteGranite), + typeof(VeriteElemental) + ), + new HarvestResource( + 99.0, + 59.0, + 139.0, + 1007080, + typeof(ValoriteOre), + typeof(ValoriteGranite), + typeof(ValoriteElemental) + ) + }; + + HarvestVein[] veins = + { + new HarvestVein(496, 0.0, res[0], null), // Iron + new HarvestVein(112, 0.5, res[1], res[0]), // Dull Copper + new HarvestVein(098, 0.5, res[2], res[0]), // Shadow Iron + new HarvestVein(084, 0.5, res[3], res[0]), // Copper + new HarvestVein(070, 0.5, res[4], res[0]), // Bronze + new HarvestVein(056, 0.5, res[5], res[0]), // Gold + new HarvestVein(042, 0.5, res[6], res[0]), // Agapite + new HarvestVein(028, 0.5, res[7], res[0]), // Verite + new HarvestVein(014, 0.5, res[8], res[0]) // Valorite + }; + + OreAndStone.Resources = res; + OreAndStone.Veins = veins; + + if (Core.ML) + OreAndStone.BonusResources = new[] + { + new BonusHarvestResource(0, 99.4, null, null), // Nothing + new BonusHarvestResource(100, .1, 1072562, typeof(BlueDiamond)), + new BonusHarvestResource(100, .1, 1072567, typeof(DarkSapphire)), + new BonusHarvestResource(100, .1, 1072570, typeof(EcruCitrine)), + new BonusHarvestResource(100, .1, 1072564, typeof(FireRuby)), + new BonusHarvestResource(100, .1, 1072566, typeof(PerfectEmerald)), + new BonusHarvestResource(100, .1, 1072568, typeof(Turquoise)) + }; + + OreAndStone.RaceBonus = Core.ML; + OreAndStone.RandomizeVeins = Core.ML; + + Definitions.Add(OreAndStone); + + Sand = new HarvestDefinition + { + BankWidth = 8, + BankHeight = 8, + MinTotal = 6, + MaxTotal = 12, + MinRespawn = TimeSpan.FromMinutes(10.0), + MaxRespawn = TimeSpan.FromMinutes(20.0), + Skill = SkillName.Mining, + Tiles = m_SandTiles, + MaxRange = 2, + ConsumedPerHarvest = 1, + ConsumedPerFeluccaHarvest = 1, + EffectActions = new[] { 11 }, + EffectSounds = new[] { 0x125, 0x126 }, + EffectCounts = new[] { 6 }, + EffectDelay = TimeSpan.FromSeconds(1.6), + EffectSoundDelay = TimeSpan.FromSeconds(0.9), + NoResourcesMessage = 1044629, // There is no sand here to mine. + DoubleHarvestMessage = 1044629, // There is no sand here to mine. + TimedOutOfRangeMessage = 503041, // You have moved too far away to continue mining. + OutOfRangeMessage = 500446, // That is too far away. + FailMessage = 1044630, // You dig for a while but fail to find any of sufficient quality for glassblowing. + PackFullMessage = 1044632, // Your backpack can't hold the sand, and it is lost! + ToolBrokeMessage = 1044038 // You have worn out your tool! + }; + + res = new[] + { + new HarvestResource(100.0, 70.0, 400.0, 1044631, typeof(Sand)) + }; + + veins = new[] + { + new HarvestVein(1000, 0.0, res[0], null) + }; + + Sand.Resources = res; + Sand.Veins = veins; + + Definitions.Add(Sand); + } + + public static Mining System => m_System ?? (m_System = new Mining()); + + public HarvestDefinition OreAndStone { get; } + + public HarvestDefinition Sand { get; } + + public override Type GetResourceType( + Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, + HarvestResource resource + ) + { + if (def != OreAndStone) + return base.GetResourceType(from, tool, def, map, loc, resource); + + if (from.Skills.Mining.Base >= 100.0 && from is PlayerMobile pm && pm.StoneMining && pm.ToggleMiningStone + && Utility.RandomDouble() < 0.1) + return resource.Types[1]; + + return resource.Types[0]; + } + + public override bool CheckHarvest(Mobile from, Item tool) + { + if (!base.CheckHarvest(from, tool)) + return false; + + if (from.Mounted) + { + from.SendLocalizedMessage(501864); // You can't mine while riding. + return false; + } + + if (from.IsBodyMod && !from.Body.IsHuman) + { + from.SendLocalizedMessage(501865); // You can't mine while polymorphed. + return false; + } + + return true; + } + + public override void SendSuccessTo(Mobile from, Item item, HarvestResource resource) + { + if (item is BaseGranite) + from.SendLocalizedMessage(1044606); // You carefully extract some workable stone from the ore vein! + else + base.SendSuccessTo(from, item, resource); + } + + public override bool CheckHarvest(Mobile from, Item tool, HarvestDefinition def, object toHarvest) + { + if (!base.CheckHarvest(from, tool, def, toHarvest)) + return false; + + if (def == Sand && !(from is PlayerMobile mobile && mobile.Skills.Mining.Base >= 100.0 && + mobile.SandMining)) + { + OnBadHarvestTarget(from, tool, toHarvest); + return false; + } + + if (from.Mounted) + { + from.SendLocalizedMessage(501864); // You can't mine while riding. + return false; + } + + if (from.IsBodyMod && !from.Body.IsHuman) + { + from.SendLocalizedMessage(501865); // You can't mine while polymorphed. + return false; + } + + return true; + } + + public override HarvestVein MutateVein( + Mobile from, Item tool, HarvestDefinition def, HarvestBank bank, + object toHarvest, HarvestVein vein + ) + { + if (tool is GargoylesPickaxe && def == OreAndStone) + { + var veinIndex = Array.IndexOf(def.Veins, vein); + + if (veinIndex >= 0 && veinIndex < def.Veins.Length - 1) + return def.Veins[veinIndex + 1]; + } + + return base.MutateVein(from, tool, def, bank, toHarvest, vein); + } + + public override void OnHarvestFinished( + Mobile from, Item tool, HarvestDefinition def, HarvestVein vein, + HarvestBank bank, HarvestResource resource, object harvested + ) + { + if (tool is GargoylesPickaxe && def == OreAndStone && Utility.RandomDouble() < 0.1) + { + var res = vein.PrimaryResource; + + if (res == resource && res.Types.Length >= 3) + try + { + var map = from.Map; + + if (map == null) + return; + + if (ActivatorUtil.CreateInstance(res.Types[2], 25) is BaseCreature spawned) + { + var offset = Utility.Random(8) * 2; + + for (var i = 0; i < m_Offsets.Length; i += 2) + { + var x = from.X + m_Offsets[(offset + i) % m_Offsets.Length]; + var y = from.Y + m_Offsets[(offset + i + 1) % m_Offsets.Length]; + + if (map.CanSpawnMobile(x, y, from.Z)) + { + spawned.OnBeforeSpawn(new Point3D(x, y, from.Z), map); + spawned.MoveToWorld(new Point3D(x, y, from.Z), map); + spawned.Combatant = from; + return; + } + + var z = map.GetAverageZ(x, y); + + if (Math.Abs(z - from.Z) < 10 && map.CanSpawnMobile(x, y, z)) + { + spawned.OnBeforeSpawn(new Point3D(x, y, z), map); + spawned.MoveToWorld(new Point3D(x, y, z), map); + spawned.Combatant = from; + return; + } + } + + spawned.OnBeforeSpawn(from.Location, from.Map); + spawned.MoveToWorld(from.Location, from.Map); + spawned.Combatant = from; + } + } + catch + { + // ignored + } + } + } + + public override bool BeginHarvesting(Mobile from, Item tool) + { + if (!base.BeginHarvesting(from, tool)) + return false; + + from.SendLocalizedMessage(503033); // Where do you wish to dig? + return true; + } + + public override void OnHarvestStarted(Mobile from, Item tool, HarvestDefinition def, object toHarvest) + { + base.OnHarvestStarted(from, tool, def, toHarvest); + + if (Core.ML) + from.RevealingAction(); + } + + public override void OnBadHarvestTarget(Mobile from, Item tool, object toHarvest) + { + if (toHarvest is LandTarget) + from.SendLocalizedMessage(501862); // You can't mine there. + else + from.SendLocalizedMessage(501863); // You can't mine that. + } + } +} diff --git a/Projects/UOContent/Engines/Help/HelpGump.cs b/Projects/UOContent/Engines/Help/HelpGump.cs index f15127260..8edd7da4c 100644 --- a/Projects/UOContent/Engines/Help/HelpGump.cs +++ b/Projects/UOContent/Engines/Help/HelpGump.cs @@ -1,332 +1,429 @@ -using System; -using System.Linq; -using Server.Engines.ConPVP; -using Server.Factions; -using Server.Gumps; -using Server.Menus.Questions; -using Server.Mobiles; -using Server.Multis; -using Server.Network; -using Server.Regions; - -namespace Server.Engines.Help -{ - public class ContainedMenu : QuestionMenu - { - private readonly Mobile m_From; - - public ContainedMenu(Mobile from) : base( - "You already have an open help request. We will have someone assist you as soon as possible. What would you like to do?", - new[] { "Leave my old help request like it is.", "Remove my help request from the queue." }) => - m_From = from; - - public override void OnCancel(NetState state) - { - m_From.SendLocalizedMessage(1005306, "", 0x35); // Help request unchanged. - } - - public override void OnResponse(NetState state, int index) - { - if (index == 0) - { - m_From.SendLocalizedMessage(1005306, "", 0x35); // Help request unchanged. - } - else if (index == 1) - { - PageEntry entry = PageQueue.GetEntry(m_From); - - if (entry != null && entry.Handler == null) - { - m_From.SendLocalizedMessage(1005307, "", 0x35); // Removed help request. - // entry.AddResponse(entry.Sender, "[Canceled]"); - PageQueue.Remove(entry); - } - else - { - m_From.SendLocalizedMessage(1005306, "", 0x35); // Help request unchanged. - } - } - } - } - - public class HelpGump : Gump - { - public HelpGump(Mobile from) : base(0, 0) - { - from.CloseGump(); - - bool isYoung = IsYoung(from); - - AddBackground(50, 25, 540, 430, 2600); - - AddPage(0); - - AddHtmlLocalized(150, 50, 360, 40, 1001002); //
Ultima Online Help Menu
- AddButton(425, 415, 2073, 2072, 0); // Close - - AddPage(1); - - if (isYoung) - { - AddButton(80, 75, 5540, 5541, 9, GumpButtonType.Reply, 2); - AddHtml(110, 75, 450, 58, - @"Young Player Haven Transport. Select this option if you want to be transported to Haven.", - true, true); - - AddButton(80, 140, 5540, 5541, 1, GumpButtonType.Reply, 2); - AddHtml(110, 140, 450, 58, - @"General question about Ultima Online. Select this option if you have a general gameplay question, need help learning to use a skill, or if you would like to search the UO Knowledge Base.", - true, true); - - AddButton(80, 205, 5540, 5541, 2); - AddHtml(110, 205, 450, 58, - @"My character is physically stuck in the game. This choice only covers cases where your character is physically stuck in a location they cannot move out of. This option will only work two times in 24 hours.", - true, true); - - AddButton(80, 270, 5540, 5541, 0, GumpButtonType.Page, 3); - AddHtml(110, 270, 450, 58, - @"Another player is harassing me. Another player is verbally harassing your character. When you select this option you will be sending a text log to Origin Systems. To see what constitutes harassment please visit http://support.uo.com/gm_9.html.", - true, true); - - AddButton(80, 335, 5540, 5541, 0, GumpButtonType.Page, 2); - AddHtml(110, 335, 450, 58, - @"Other. If you are experiencing a problem in the game that does not fall into one of the other categories or is not addressed on the Support web page (located at http://support.uo.com), please use this option.", - true, true); - } - else - { - AddButton(80, 90, 5540, 5541, 1, GumpButtonType.Reply, 2); - AddHtml(110, 90, 450, 74, - @"General question about Ultima Online. Select this option if you have a general gameplay question, need help learning to use a skill, or if you would like to search the UO Knowledge Base.", - true, true); - - AddButton(80, 170, 5540, 5541, 2); - AddHtml(110, 170, 450, 74, - @"My character is physically stuck in the game. This choice only covers cases where your character is physically stuck in a location they cannot move out of. This option will only work two times in 24 hours.", - true, true); - - AddButton(80, 250, 5540, 5541, 0, GumpButtonType.Page, 3); - AddHtml(110, 250, 450, 74, - @"Another player is harassing me. Another player is verbally harassing your character. When you select this option you will be sending a text log to Origin Systems. To see what constitutes harassment please visit http://support.uo.com/gm_9.html.", - true, true); - - AddButton(80, 330, 5540, 5541, 0, GumpButtonType.Page, 2); - AddHtml(110, 330, 450, 74, - @"Other. If you are experiencing a problem in the game that does not fall into one of the other categories or is not addressed on the Support web page (located at http://support.uo.com), please use this option.", - true, true); - } - - AddPage(2); - - AddButton(80, 90, 5540, 5541, 3); - AddHtml(110, 90, 450, 74, - @"Report a bug or contact Origin. Use this option to launch your web browser and mail in a bug report. Your report will be read by our Quality Assurance Staff. We apologize for not being able to reply to individual reports. ", - true, true); - - AddButton(80, 170, 5540, 5541, 4); - AddHtml(110, 170, 450, 74, - @"Suggestion for the Game. If you'd like to make a suggestion for the game, it should be directed to the Development Team Members who participate in the discussion forums on the UO.Com web site. Choosing this option will take you to the Discussion Forums. ", - true, true); - - AddButton(80, 250, 5540, 5541, 5); - AddHtml(110, 250, 450, 74, - @"Account Management For questions regarding your account such as forgotten passwords, payment options, account activation, and account transfer, please choose this option.", - true, true); - - AddButton(80, 330, 5540, 5541, 6); - AddHtml(110, 330, 450, 74, - @"Other. If you are experiencing a problem in the game that does not fall into one of the other categories or is not addressed on the Support web page (located at http://support.uo.com), and requires in-game assistance, use this option. ", - true, true); - - AddPage(3); - - AddButton(80, 90, 5540, 5541, 7); - - /*
Another player is harassing me (or Exploiting).

- * VERBAL HARASSMENT
- * Use this option when another player is verbally harassing your character. - * Verbal harassment behaviors include but are not limited to, using bad language, threats etc.. - * Before you submit a complaint be sure you understand what constitutes harassment - * � what is verbal harassment? - - * and that you have followed these steps:
- * 1. You have asked the player to stop and they have continued.
- * 2. You have tried to remove yourself from the situation.
- * 3. You have done nothing to instigate or further encourage the harassment.
- * 4. You have added the player to your ignore list. - * - How do I ignore a player?
- * 5. You have read and understand Origin�s definition of harassment.
- * 6. Your account information is up to date. (Including a current email address)
- * *If these steps have not been taken, GMs may be unable to take action against the offending player.
- * **A chat log will be review by a GM to assess the validity of this complaint. - * Abuse of this system is a violation of the Rules of Conduct.
- * EXPLOITING
- * Use this option to report someone who may be exploiting or cheating. - * � What constitutes an exploit? - */ - AddHtmlLocalized(110, 90, 450, 145, 1062572, true, - true); - - AddButton(80, 240, 5540, 5541, 8); - - /*
Another player is harassing me using game mechanics.

- *
- * PHYSICAL HARASSMENT
- * Use this option when another player is harassing your character using game mechanics. - * Physical harassment includes but is not limited to luring, Kill Stealing, and any act that causes a players death in Trammel. - * Before you submit a complaint be sure you understand what constitutes harassment - * � what is physical harassment? - * and that you have followed these steps:
- * 1. You have asked the player to stop and they have continued.
- * 2. You have tried to remove yourself from the situation.
- * 3. You have done nothing to instigate or further encourage the harassment.
- * 4. You have added the player to your ignore list. - * - how do I ignore a player?
- * 5. You have read and understand Origin�s definition of harassment.
- * 6. Your account information is up to date. (Including a current email address)
- * *If these steps have not been taken, GMs may be unable to take action against the offending player.
- * **This issue will be reviewed by a GM to assess the validity of this complaint. - * Abuse of this system is a violation of the Rules of Conduct. - */ - AddHtmlLocalized(110, 240, 450, 145, 1062573, true, - true); - - AddButton(150, 390, 5540, 5541, 0, GumpButtonType.Page, 1); - AddHtmlLocalized(180, 390, 335, 40, 1001015); // NO - I meant to ask for help with another matter. - } - - public static void Initialize() - { - EventSink.HelpRequest += EventSink_HelpRequest; - } - - private static void EventSink_HelpRequest(Mobile m) - { - if (m.NetState.Gumps.OfType().Any()) return; - - if (!PageQueue.CheckAllowedToPage(m)) - return; - - if (PageQueue.Contains(m)) - m.SendMenu(new ContainedMenu(m)); - else - m.SendGump(new HelpGump(m)); - } - - private static bool IsYoung(Mobile m) => m is PlayerMobile mobile && mobile.Young; - - public static bool CheckCombat(Mobile m) - { - for (int i = 0; i < m.Aggressed.Count; ++i) - { - AggressorInfo info = m.Aggressed[i]; - - if (DateTime.UtcNow - info.LastCombatTime < TimeSpan.FromSeconds(30.0)) - return true; - } - - return false; - } - - public override void OnResponse(NetState state, RelayInfo info) - { - Mobile from = state.Mobile; - - PageType type = (PageType)(-1); - - switch (info.ButtonID) - { - case 0: // Close/Cancel - { - from.SendLocalizedMessage(501235, "", 0x35); // Help request aborted. - - break; - } - case 1: // General question - { - type = PageType.Question; - break; - } - case 2: // Stuck - { - BaseHouse house = BaseHouse.FindHouseAt(from); - - if (house?.IsAosRules == true && !from.Region.IsPartOf()) // Dueling - { - from.Location = house.BanLocation; - } - else if (from.Region.IsPartOf()) - { - from.SendLocalizedMessage(1114345, "", 0x35); // You'll need a better jailbreak plan than that! - } - else if (Sigil.ExistsOn(from)) - { - from.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. - } - else if (from is PlayerMobile mobile && mobile.CanUseStuckMenu() && - mobile.Region.CanUseStuckMenu(mobile) && !CheckCombat(mobile) && !mobile.Frozen && - !mobile.Criminal && (Core.AOS || mobile.Kills < 5)) - { - StuckMenu menu = new StuckMenu(mobile, mobile, true); - - menu.BeginClose(); - - mobile.SendGump(menu); - } - else - { - type = PageType.Stuck; - } - - break; - } - case 3: // Report bug or contact Origin - { - type = PageType.Bug; - break; - } - case 4: // Game suggestion - { - type = PageType.Suggestion; - break; - } - case 5: // Account management - { - type = PageType.Account; - break; - } - case 6: // Other - { - type = PageType.Other; - break; - } - case 7: // Harassment: verbal/exploit - { - type = PageType.VerbalHarassment; - break; - } - case 8: // Harassment: physical - { - type = PageType.PhysicalHarassment; - break; - } - case 9: // Young player transport - { - if (IsYoung(from)) - { - if (from.Region.IsPartOf()) - from.SendLocalizedMessage(1114345, "", 0x35); // You'll need a better jailbreak plan than that! - else if (from.Region.IsPartOf("Haven Island")) - from.SendLocalizedMessage(1041529); // You're already in Haven - else - from.MoveToWorld(new Point3D(3503, 2574, 14), Map.Trammel); - } - - break; - } - } - - if (type != (PageType)(-1) && PageQueue.CheckAllowedToPage(from)) - from.SendGump(new PagePromptGump(from, type)); - } - } -} +using System; +using System.Linq; +using Server.Engines.ConPVP; +using Server.Factions; +using Server.Gumps; +using Server.Menus.Questions; +using Server.Mobiles; +using Server.Multis; +using Server.Network; +using Server.Regions; + +namespace Server.Engines.Help +{ + public class ContainedMenu : QuestionMenu + { + private readonly Mobile m_From; + + public ContainedMenu(Mobile from) : base( + "You already have an open help request. We will have someone assist you as soon as possible. What would you like to do?", + new[] { "Leave my old help request like it is.", "Remove my help request from the queue." } + ) => + m_From = from; + + public override void OnCancel(NetState state) + { + m_From.SendLocalizedMessage(1005306, "", 0x35); // Help request unchanged. + } + + public override void OnResponse(NetState state, int index) + { + if (index == 0) + { + m_From.SendLocalizedMessage(1005306, "", 0x35); // Help request unchanged. + } + else if (index == 1) + { + var entry = PageQueue.GetEntry(m_From); + + if (entry != null && entry.Handler == null) + { + m_From.SendLocalizedMessage(1005307, "", 0x35); // Removed help request. + // entry.AddResponse(entry.Sender, "[Canceled]"); + PageQueue.Remove(entry); + } + else + { + m_From.SendLocalizedMessage(1005306, "", 0x35); // Help request unchanged. + } + } + } + } + + public class HelpGump : Gump + { + public HelpGump(Mobile from) : base(0, 0) + { + from.CloseGump(); + + var isYoung = IsYoung(from); + + AddBackground(50, 25, 540, 430, 2600); + + AddPage(0); + + AddHtmlLocalized(150, 50, 360, 40, 1001002); //
Ultima Online Help Menu
+ AddButton(425, 415, 2073, 2072, 0); // Close + + AddPage(1); + + if (isYoung) + { + AddButton(80, 75, 5540, 5541, 9, GumpButtonType.Reply, 2); + AddHtml( + 110, + 75, + 450, + 58, + @"Young Player Haven Transport. Select this option if you want to be transported to Haven.", + true, + true + ); + + AddButton(80, 140, 5540, 5541, 1, GumpButtonType.Reply, 2); + AddHtml( + 110, + 140, + 450, + 58, + @"General question about Ultima Online. Select this option if you have a general gameplay question, need help learning to use a skill, or if you would like to search the UO Knowledge Base.", + true, + true + ); + + AddButton(80, 205, 5540, 5541, 2); + AddHtml( + 110, + 205, + 450, + 58, + @"My character is physically stuck in the game. This choice only covers cases where your character is physically stuck in a location they cannot move out of. This option will only work two times in 24 hours.", + true, + true + ); + + AddButton(80, 270, 5540, 5541, 0, GumpButtonType.Page, 3); + AddHtml( + 110, + 270, + 450, + 58, + @"Another player is harassing me. Another player is verbally harassing your character. When you select this option you will be sending a text log to Origin Systems. To see what constitutes harassment please visit http://support.uo.com/gm_9.html.", + true, + true + ); + + AddButton(80, 335, 5540, 5541, 0, GumpButtonType.Page, 2); + AddHtml( + 110, + 335, + 450, + 58, + @"Other. If you are experiencing a problem in the game that does not fall into one of the other categories or is not addressed on the Support web page (located at http://support.uo.com), please use this option.", + true, + true + ); + } + else + { + AddButton(80, 90, 5540, 5541, 1, GumpButtonType.Reply, 2); + AddHtml( + 110, + 90, + 450, + 74, + @"General question about Ultima Online. Select this option if you have a general gameplay question, need help learning to use a skill, or if you would like to search the UO Knowledge Base.", + true, + true + ); + + AddButton(80, 170, 5540, 5541, 2); + AddHtml( + 110, + 170, + 450, + 74, + @"My character is physically stuck in the game. This choice only covers cases where your character is physically stuck in a location they cannot move out of. This option will only work two times in 24 hours.", + true, + true + ); + + AddButton(80, 250, 5540, 5541, 0, GumpButtonType.Page, 3); + AddHtml( + 110, + 250, + 450, + 74, + @"Another player is harassing me. Another player is verbally harassing your character. When you select this option you will be sending a text log to Origin Systems. To see what constitutes harassment please visit http://support.uo.com/gm_9.html.", + true, + true + ); + + AddButton(80, 330, 5540, 5541, 0, GumpButtonType.Page, 2); + AddHtml( + 110, + 330, + 450, + 74, + @"Other. If you are experiencing a problem in the game that does not fall into one of the other categories or is not addressed on the Support web page (located at http://support.uo.com), please use this option.", + true, + true + ); + } + + AddPage(2); + + AddButton(80, 90, 5540, 5541, 3); + AddHtml( + 110, + 90, + 450, + 74, + @"Report a bug or contact Origin. Use this option to launch your web browser and mail in a bug report. Your report will be read by our Quality Assurance Staff. We apologize for not being able to reply to individual reports. ", + true, + true + ); + + AddButton(80, 170, 5540, 5541, 4); + AddHtml( + 110, + 170, + 450, + 74, + @"Suggestion for the Game. If you'd like to make a suggestion for the game, it should be directed to the Development Team Members who participate in the discussion forums on the UO.Com web site. Choosing this option will take you to the Discussion Forums. ", + true, + true + ); + + AddButton(80, 250, 5540, 5541, 5); + AddHtml( + 110, + 250, + 450, + 74, + @"Account Management For questions regarding your account such as forgotten passwords, payment options, account activation, and account transfer, please choose this option.", + true, + true + ); + + AddButton(80, 330, 5540, 5541, 6); + AddHtml( + 110, + 330, + 450, + 74, + @"Other. If you are experiencing a problem in the game that does not fall into one of the other categories or is not addressed on the Support web page (located at http://support.uo.com), and requires in-game assistance, use this option. ", + true, + true + ); + + AddPage(3); + + AddButton(80, 90, 5540, 5541, 7); + + /*
Another player is harassing me (or Exploiting).

+ * VERBAL HARASSMENT
+ * Use this option when another player is verbally harassing your character. + * Verbal harassment behaviors include but are not limited to, using bad language, threats etc.. + * Before you submit a complaint be sure you understand what constitutes harassment + * � what is verbal harassment? - + * and that you have followed these steps:
+ * 1. You have asked the player to stop and they have continued.
+ * 2. You have tried to remove yourself from the situation.
+ * 3. You have done nothing to instigate or further encourage the harassment.
+ * 4. You have added the player to your ignore list. + * - How do I ignore a player?
+ * 5. You have read and understand Origin�s definition of harassment.
+ * 6. Your account information is up to date. (Including a current email address)
+ * *If these steps have not been taken, GMs may be unable to take action against the offending player.
+ * **A chat log will be review by a GM to assess the validity of this complaint. + * Abuse of this system is a violation of the Rules of Conduct.
+ * EXPLOITING
+ * Use this option to report someone who may be exploiting or cheating. + * � What constitutes an exploit? + */ + AddHtmlLocalized( + 110, + 90, + 450, + 145, + 1062572, + true, + true + ); + + AddButton(80, 240, 5540, 5541, 8); + + /*
Another player is harassing me using game mechanics.

+ *
+ * PHYSICAL HARASSMENT
+ * Use this option when another player is harassing your character using game mechanics. + * Physical harassment includes but is not limited to luring, Kill Stealing, and any act that causes a players death in Trammel. + * Before you submit a complaint be sure you understand what constitutes harassment + * � what is physical harassment? + * and that you have followed these steps:
+ * 1. You have asked the player to stop and they have continued.
+ * 2. You have tried to remove yourself from the situation.
+ * 3. You have done nothing to instigate or further encourage the harassment.
+ * 4. You have added the player to your ignore list. + * - how do I ignore a player?
+ * 5. You have read and understand Origin�s definition of harassment.
+ * 6. Your account information is up to date. (Including a current email address)
+ * *If these steps have not been taken, GMs may be unable to take action against the offending player.
+ * **This issue will be reviewed by a GM to assess the validity of this complaint. + * Abuse of this system is a violation of the Rules of Conduct. + */ + AddHtmlLocalized( + 110, + 240, + 450, + 145, + 1062573, + true, + true + ); + + AddButton(150, 390, 5540, 5541, 0, GumpButtonType.Page, 1); + AddHtmlLocalized(180, 390, 335, 40, 1001015); // NO - I meant to ask for help with another matter. + } + + public static void Initialize() + { + EventSink.HelpRequest += EventSink_HelpRequest; + } + + private static void EventSink_HelpRequest(Mobile m) + { + if (m.NetState.Gumps.OfType().Any()) return; + + if (!PageQueue.CheckAllowedToPage(m)) + return; + + if (PageQueue.Contains(m)) + m.SendMenu(new ContainedMenu(m)); + else + m.SendGump(new HelpGump(m)); + } + + private static bool IsYoung(Mobile m) => m is PlayerMobile mobile && mobile.Young; + + public static bool CheckCombat(Mobile m) + { + for (var i = 0; i < m.Aggressed.Count; ++i) + { + var info = m.Aggressed[i]; + + if (DateTime.UtcNow - info.LastCombatTime < TimeSpan.FromSeconds(30.0)) + return true; + } + + return false; + } + + public override void OnResponse(NetState state, RelayInfo info) + { + var from = state.Mobile; + + var type = (PageType)(-1); + + switch (info.ButtonID) + { + case 0: // Close/Cancel + { + from.SendLocalizedMessage(501235, "", 0x35); // Help request aborted. + + break; + } + case 1: // General question + { + type = PageType.Question; + break; + } + case 2: // Stuck + { + var house = BaseHouse.FindHouseAt(from); + + if (house?.IsAosRules == true && !from.Region.IsPartOf()) // Dueling + { + from.Location = house.BanLocation; + } + else if (from.Region.IsPartOf()) + { + from.SendLocalizedMessage(1114345, "", 0x35); // You'll need a better jailbreak plan than that! + } + else if (Sigil.ExistsOn(from)) + { + from.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. + } + else if (from is PlayerMobile mobile && mobile.CanUseStuckMenu() && + mobile.Region.CanUseStuckMenu(mobile) && !CheckCombat(mobile) && !mobile.Frozen && + !mobile.Criminal && (Core.AOS || mobile.Kills < 5)) + { + var menu = new StuckMenu(mobile, mobile, true); + + menu.BeginClose(); + + mobile.SendGump(menu); + } + else + { + type = PageType.Stuck; + } + + break; + } + case 3: // Report bug or contact Origin + { + type = PageType.Bug; + break; + } + case 4: // Game suggestion + { + type = PageType.Suggestion; + break; + } + case 5: // Account management + { + type = PageType.Account; + break; + } + case 6: // Other + { + type = PageType.Other; + break; + } + case 7: // Harassment: verbal/exploit + { + type = PageType.VerbalHarassment; + break; + } + case 8: // Harassment: physical + { + type = PageType.PhysicalHarassment; + break; + } + case 9: // Young player transport + { + if (IsYoung(from)) + { + if (from.Region.IsPartOf()) + from.SendLocalizedMessage( + 1114345, + "", + 0x35 + ); // You'll need a better jailbreak plan than that! + else if (from.Region.IsPartOf("Haven Island")) + from.SendLocalizedMessage(1041529); // You're already in Haven + else + from.MoveToWorld(new Point3D(3503, 2574, 14), Map.Trammel); + } + + break; + } + } + + if (type != (PageType)(-1) && PageQueue.CheckAllowedToPage(from)) + from.SendGump(new PagePromptGump(from, type)); + } + } +} diff --git a/Projects/UOContent/Engines/Help/PagePrompt.cs b/Projects/UOContent/Engines/Help/PagePrompt.cs index a5e8e9717..1566d55fc 100644 --- a/Projects/UOContent/Engines/Help/PagePrompt.cs +++ b/Projects/UOContent/Engines/Help/PagePrompt.cs @@ -1,26 +1,26 @@ -using Server.Prompts; - -namespace Server.Engines.Help -{ - public class PagePrompt : Prompt - { - private readonly PageType m_Type; - - public PagePrompt(PageType type) => m_Type = type; - - public override void OnCancel(Mobile from) - { - from.SendLocalizedMessage(501235, "", 0x35); // Help request aborted. - } - - public override void OnResponse(Mobile from, string text) - { - /* The next available Counselor/Game Master will respond as soon as possible. - * Please check your Journal for messages every few minutes. - */ - from.SendLocalizedMessage(501234, "", 0x35); - - PageQueue.Enqueue(new PageEntry(from, text, m_Type)); - } - } -} +using Server.Prompts; + +namespace Server.Engines.Help +{ + public class PagePrompt : Prompt + { + private readonly PageType m_Type; + + public PagePrompt(PageType type) => m_Type = type; + + public override void OnCancel(Mobile from) + { + from.SendLocalizedMessage(501235, "", 0x35); // Help request aborted. + } + + public override void OnResponse(Mobile from, string text) + { + /* The next available Counselor/Game Master will respond as soon as possible. + * Please check your Journal for messages every few minutes. + */ + from.SendLocalizedMessage(501234, "", 0x35); + + PageQueue.Enqueue(new PageEntry(from, text, m_Type)); + } + } +} diff --git a/Projects/UOContent/Engines/Help/PagePromptGump.cs b/Projects/UOContent/Engines/Help/PagePromptGump.cs index 8c738fee5..5af5ad5d0 100644 --- a/Projects/UOContent/Engines/Help/PagePromptGump.cs +++ b/Projects/UOContent/Engines/Help/PagePromptGump.cs @@ -1,60 +1,66 @@ -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.Help -{ - public class PagePromptGump : Gump - { - private readonly Mobile m_From; - private readonly PageType m_Type; - - public PagePromptGump(Mobile from, PageType type) : base(0, 0) - { - m_From = from; - m_Type = type; - - from.CloseGump(); - - AddBackground(50, 50, 540, 350, 2600); - - AddPage(0); - - AddHtmlLocalized(264, 80, 200, 24, 1062524); // Enter Description - AddHtmlLocalized(120, 108, 420, 48, 1062638); // Please enter a brief description (up to 200 characters) of your problem: - - AddBackground(100, 148, 440, 200, 3500); - AddTextEntry(120, 168, 400, 200, 1153, 0, ""); - - AddButton(175, 355, 2074, 2075, 1); // Okay - AddButton(405, 355, 2073, 2072, 0); // Cancel - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 0) - { - m_From.SendLocalizedMessage(501235, "", 0x35); // Help request aborted. - } - else - { - TextRelay entry = info.GetTextEntry(0); - string text = entry?.Text.Trim() ?? ""; - - if (text.Length == 0) - { - m_From.SendMessage(0x35, "You must enter a description."); - m_From.SendGump(new PagePromptGump(m_From, m_Type)); - } - else - { - /* The next available Counselor/Game Master will respond as soon as possible. - * Please check your Journal for messages every few minutes. - */ - m_From.SendLocalizedMessage(501234, "", 0x35); - - PageQueue.Enqueue(new PageEntry(m_From, text, m_Type)); - } - } - } - } -} +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.Help +{ + public class PagePromptGump : Gump + { + private readonly Mobile m_From; + private readonly PageType m_Type; + + public PagePromptGump(Mobile from, PageType type) : base(0, 0) + { + m_From = from; + m_Type = type; + + from.CloseGump(); + + AddBackground(50, 50, 540, 350, 2600); + + AddPage(0); + + AddHtmlLocalized(264, 80, 200, 24, 1062524); // Enter Description + AddHtmlLocalized( + 120, + 108, + 420, + 48, + 1062638 + ); // Please enter a brief description (up to 200 characters) of your problem: + + AddBackground(100, 148, 440, 200, 3500); + AddTextEntry(120, 168, 400, 200, 1153, 0, ""); + + AddButton(175, 355, 2074, 2075, 1); // Okay + AddButton(405, 355, 2073, 2072, 0); // Cancel + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 0) + { + m_From.SendLocalizedMessage(501235, "", 0x35); // Help request aborted. + } + else + { + var entry = info.GetTextEntry(0); + var text = entry?.Text.Trim() ?? ""; + + if (text.Length == 0) + { + m_From.SendMessage(0x35, "You must enter a description."); + m_From.SendGump(new PagePromptGump(m_From, m_Type)); + } + else + { + /* The next available Counselor/Game Master will respond as soon as possible. + * Please check your Journal for messages every few minutes. + */ + m_From.SendLocalizedMessage(501234, "", 0x35); + + PageQueue.Enqueue(new PageEntry(m_From, text, m_Type)); + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Help/PageQueue.cs b/Projects/UOContent/Engines/Help/PageQueue.cs index d979aacdb..3a075e43b 100644 --- a/Projects/UOContent/Engines/Help/PageQueue.cs +++ b/Projects/UOContent/Engines/Help/PageQueue.cs @@ -1,234 +1,240 @@ -using System; -using System.Collections.Generic; -using Server.Misc; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.Help -{ - public enum PageType - { - Bug, - Stuck, - Account, - Question, - Suggestion, - Other, - VerbalHarassment, - PhysicalHarassment - } - - public class PageEntry - { - // What page types should have a speech log as attachment? - public static readonly PageType[] SpeechLogAttachment = - { - PageType.VerbalHarassment - }; - - private Mobile m_Handler; - - private Timer m_Timer; - - public PageEntry(Mobile sender, string message, PageType type) - { - Sender = sender; - Sent = DateTime.UtcNow; - Message = Utility.FixHtml(message); - Type = type; - PageLocation = sender.Location; - PageMap = sender.Map; - - if (sender is PlayerMobile pm && pm.SpeechLog != null && Array.IndexOf(SpeechLogAttachment, type) >= 0) - SpeechLog = new List(pm.SpeechLog); - - m_Timer = new InternalTimer(this); - m_Timer.Start(); - } - - public Mobile Sender { get; } - - public Mobile Handler - { - get => m_Handler; - set - { - PageQueue.OnHandlerChanged(m_Handler, value, this); - m_Handler = value; - } - } - - public DateTime Sent { get; } - - public string Message { get; } - - public PageType Type { get; } - - public Point3D PageLocation { get; } - - public Map PageMap { get; } - - public List SpeechLog { get; } - - public void Stop() - { - m_Timer?.Stop(); - - m_Timer = null; - } - - private class InternalTimer : Timer - { - private static readonly TimeSpan StatusDelay = TimeSpan.FromMinutes(2.0); - - private readonly PageEntry m_Entry; - - public InternalTimer(PageEntry entry) : base(TimeSpan.FromSeconds(1.0), StatusDelay) => m_Entry = entry; - - protected override void OnTick() - { - int index = PageQueue.IndexOf(m_Entry); - - if (m_Entry.Sender.NetState != null && index != -1) - { - m_Entry.Sender.SendLocalizedMessage(1008077, true, - (index + 1).ToString()); // Thank you for paging. Queue status : - m_Entry.Sender - .SendLocalizedMessage( - 1008084); // You can reference our website at www.uo.com or contact us at support@uo.com. To cancel your page, please select the help button again and select cancel. - - if (m_Entry.Handler != null && m_Entry.Handler.NetState == null) m_Entry.Handler = null; - } - else - { - if (index != -1) - // m_Entry.AddResponse(m_Entry.Sender, "[Logout]"); - - PageQueue.Remove(m_Entry); - } - } - } - } - - public class PageQueue - { - private static readonly Dictionary m_KeyedByHandler = new Dictionary(); - private static readonly Dictionary m_KeyedBySender = new Dictionary(); - - public static List List { get; } = new List(); - - public static void Initialize() - { - CommandSystem.Register("Pages", AccessLevel.Counselor, Pages_OnCommand); - } - - public static bool CheckAllowedToPage(Mobile from) - { - if (!(from is PlayerMobile pm)) - return true; - - if (pm.DesignContext != null) - { - from.SendLocalizedMessage( - 500182); // You cannot request help while customizing a house or transferring a character. - return false; - } - - if (pm.PagingSquelched) - { - from.SendMessage("You cannot request help, sorry."); - return false; - } - - return true; - } - - public static string GetPageTypeName(PageType type) - { - if (type == PageType.VerbalHarassment) - return "Verbal Harassment"; - if (type == PageType.PhysicalHarassment) - return "Physical Harassment"; - return type.ToString(); - } - - public static void OnHandlerChanged(Mobile old, Mobile value, PageEntry entry) - { - if (old != null) - m_KeyedByHandler.Remove(old); - - if (value != null) - m_KeyedByHandler[value] = entry; - } - - [Usage("Pages")] - [Description("Opens the page queue menu.")] - private static void Pages_OnCommand(CommandEventArgs e) - { - if (m_KeyedByHandler.TryGetValue(e.Mobile, out PageEntry entry)) - e.Mobile.SendGump(new PageEntryGump(e.Mobile, entry)); - else if (List.Count > 0) - e.Mobile.SendGump(new PageQueueGump()); - else - e.Mobile.SendMessage("The page queue is empty."); - } - - public static bool IsHandling(Mobile check) => m_KeyedByHandler.ContainsKey(check); - - public static bool Contains(Mobile sender) => m_KeyedBySender.ContainsKey(sender); - - public static int IndexOf(PageEntry e) => List.IndexOf(e); - - public static void Remove(PageEntry e) - { - if (e == null) - return; - - e.Stop(); - - List.Remove(e); - m_KeyedBySender.Remove(e.Sender); - - if (e.Handler != null) - m_KeyedByHandler.Remove(e.Handler); - } - - public static PageEntry GetEntry(Mobile sender) - { - m_KeyedBySender.TryGetValue(sender, out PageEntry entry); - return entry; - } - - public static void Remove(Mobile sender) - { - Remove(GetEntry(sender)); - } - - public static void Enqueue(PageEntry entry) - { - List.Add(entry); - m_KeyedBySender[entry.Sender] = entry; - - bool isStaffOnline = false; - - foreach (NetState ns in TcpServer.Instances) - { - Mobile m = ns.Mobile; - - if (m?.AccessLevel >= AccessLevel.Counselor && m.AutoPageNotify && !IsHandling(m)) - m.SendMessage("A new page has been placed in the queue."); - - if (m?.AccessLevel >= AccessLevel.Counselor && m.AutoPageNotify && - Core.TickCount - m.LastMoveTime < 600000) - isStaffOnline = true; - } - - if (!isStaffOnline) - entry.Sender.SendMessage( - "We are sorry, but no staff members are currently available to assist you. Your page will remain in the queue until one becomes available, or until you cancel it manually."); - - if (entry.SpeechLog != null) - Email.SendQueueEmail(entry, GetPageTypeName(entry.Type)); - } - } -} +using System; +using System.Collections.Generic; +using Server.Misc; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.Help +{ + public enum PageType + { + Bug, + Stuck, + Account, + Question, + Suggestion, + Other, + VerbalHarassment, + PhysicalHarassment + } + + public class PageEntry + { + // What page types should have a speech log as attachment? + public static readonly PageType[] SpeechLogAttachment = + { + PageType.VerbalHarassment + }; + + private Mobile m_Handler; + + private Timer m_Timer; + + public PageEntry(Mobile sender, string message, PageType type) + { + Sender = sender; + Sent = DateTime.UtcNow; + Message = Utility.FixHtml(message); + Type = type; + PageLocation = sender.Location; + PageMap = sender.Map; + + if (sender is PlayerMobile pm && pm.SpeechLog != null && Array.IndexOf(SpeechLogAttachment, type) >= 0) + SpeechLog = new List(pm.SpeechLog); + + m_Timer = new InternalTimer(this); + m_Timer.Start(); + } + + public Mobile Sender { get; } + + public Mobile Handler + { + get => m_Handler; + set + { + PageQueue.OnHandlerChanged(m_Handler, value, this); + m_Handler = value; + } + } + + public DateTime Sent { get; } + + public string Message { get; } + + public PageType Type { get; } + + public Point3D PageLocation { get; } + + public Map PageMap { get; } + + public List SpeechLog { get; } + + public void Stop() + { + m_Timer?.Stop(); + + m_Timer = null; + } + + private class InternalTimer : Timer + { + private static readonly TimeSpan StatusDelay = TimeSpan.FromMinutes(2.0); + + private readonly PageEntry m_Entry; + + public InternalTimer(PageEntry entry) : base(TimeSpan.FromSeconds(1.0), StatusDelay) => m_Entry = entry; + + protected override void OnTick() + { + var index = PageQueue.IndexOf(m_Entry); + + if (m_Entry.Sender.NetState != null && index != -1) + { + m_Entry.Sender.SendLocalizedMessage( + 1008077, + true, + (index + 1).ToString() + ); // Thank you for paging. Queue status : + m_Entry.Sender + .SendLocalizedMessage( + 1008084 + ); // You can reference our website at www.uo.com or contact us at support@uo.com. To cancel your page, please select the help button again and select cancel. + + if (m_Entry.Handler != null && m_Entry.Handler.NetState == null) m_Entry.Handler = null; + } + else + { + if (index != -1) + // m_Entry.AddResponse(m_Entry.Sender, "[Logout]"); + + PageQueue.Remove(m_Entry); + } + } + } + } + + public class PageQueue + { + private static readonly Dictionary m_KeyedByHandler = new Dictionary(); + private static readonly Dictionary m_KeyedBySender = new Dictionary(); + + public static List List { get; } = new List(); + + public static void Initialize() + { + CommandSystem.Register("Pages", AccessLevel.Counselor, Pages_OnCommand); + } + + public static bool CheckAllowedToPage(Mobile from) + { + if (!(from is PlayerMobile pm)) + return true; + + if (pm.DesignContext != null) + { + from.SendLocalizedMessage( + 500182 + ); // You cannot request help while customizing a house or transferring a character. + return false; + } + + if (pm.PagingSquelched) + { + from.SendMessage("You cannot request help, sorry."); + return false; + } + + return true; + } + + public static string GetPageTypeName(PageType type) + { + if (type == PageType.VerbalHarassment) + return "Verbal Harassment"; + if (type == PageType.PhysicalHarassment) + return "Physical Harassment"; + return type.ToString(); + } + + public static void OnHandlerChanged(Mobile old, Mobile value, PageEntry entry) + { + if (old != null) + m_KeyedByHandler.Remove(old); + + if (value != null) + m_KeyedByHandler[value] = entry; + } + + [Usage("Pages")] + [Description("Opens the page queue menu.")] + private static void Pages_OnCommand(CommandEventArgs e) + { + if (m_KeyedByHandler.TryGetValue(e.Mobile, out var entry)) + e.Mobile.SendGump(new PageEntryGump(e.Mobile, entry)); + else if (List.Count > 0) + e.Mobile.SendGump(new PageQueueGump()); + else + e.Mobile.SendMessage("The page queue is empty."); + } + + public static bool IsHandling(Mobile check) => m_KeyedByHandler.ContainsKey(check); + + public static bool Contains(Mobile sender) => m_KeyedBySender.ContainsKey(sender); + + public static int IndexOf(PageEntry e) => List.IndexOf(e); + + public static void Remove(PageEntry e) + { + if (e == null) + return; + + e.Stop(); + + List.Remove(e); + m_KeyedBySender.Remove(e.Sender); + + if (e.Handler != null) + m_KeyedByHandler.Remove(e.Handler); + } + + public static PageEntry GetEntry(Mobile sender) + { + m_KeyedBySender.TryGetValue(sender, out var entry); + return entry; + } + + public static void Remove(Mobile sender) + { + Remove(GetEntry(sender)); + } + + public static void Enqueue(PageEntry entry) + { + List.Add(entry); + m_KeyedBySender[entry.Sender] = entry; + + var isStaffOnline = false; + + foreach (var ns in TcpServer.Instances) + { + var m = ns.Mobile; + + if (m?.AccessLevel >= AccessLevel.Counselor && m.AutoPageNotify && !IsHandling(m)) + m.SendMessage("A new page has been placed in the queue."); + + if (m?.AccessLevel >= AccessLevel.Counselor && m.AutoPageNotify && + Core.TickCount - m.LastMoveTime < 600000) + isStaffOnline = true; + } + + if (!isStaffOnline) + entry.Sender.SendMessage( + "We are sorry, but no staff members are currently available to assist you. Your page will remain in the queue until one becomes available, or until you cancel it manually." + ); + + if (entry.SpeechLog != null) + Email.SendQueueEmail(entry, GetPageTypeName(entry.Type)); + } + } +} diff --git a/Projects/UOContent/Engines/Help/PageQueueGump.cs b/Projects/UOContent/Engines/Help/PageQueueGump.cs index 869551bf1..113817169 100644 --- a/Projects/UOContent/Engines/Help/PageQueueGump.cs +++ b/Projects/UOContent/Engines/Help/PageQueueGump.cs @@ -1,782 +1,794 @@ -using System; -using System.Collections.Generic; -using System.IO; -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.Help -{ - public class MessageSentGump : Gump - { - private readonly Mobile m_Mobile; - private readonly string m_Name; - private readonly string m_Text; - - public MessageSentGump(Mobile mobile, string name, string text) : base(30, 30) - { - m_Name = name; - m_Text = text; - m_Mobile = mobile; - - Closable = false; - - AddPage(0); - - AddBackground(0, 0, 92, 75, 0xA3C); - - AddImageTiled(5, 7, 82, 61, 0xA40); - AddAlphaRegion(5, 7, 82, 61); - - AddImageTiled(9, 11, 21, 53, 0xBBC); - - AddButton(10, 12, 0x7D2, 0x7D2, 0); - AddHtmlLocalized(34, 28, 65, 24, 3001002, 0xFFFFFF); // Message - } - - public override void OnResponse(NetState state, RelayInfo info) - { - m_Mobile.SendGump(new PageResponseGump(m_Mobile, m_Name, m_Text)); - - // m_Mobile.SendMessage( 0x482, "{0} tells you:", m_Name ); - // m_Mobile.SendMessage( 0x482, m_Text ); - } - } - - public class PageQueueGump : Gump - { - private readonly PageEntry[] m_List; - - public PageQueueGump() : base(30, 30) - { - Add(new GumpPage(0)); - // Add( new GumpBackground( 0, 0, 410, 448, 9200 ) ); - Add(new GumpImageTiled(0, 0, 410, 448, 0xA40)); - Add(new GumpAlphaRegion(1, 1, 408, 446)); - - Add(new GumpLabel(180, 12, 2100, "Page Queue")); - - List list = PageQueue.List; - - for (int i = 0; i < list.Count;) - { - PageEntry e = list[i]; - - if (e.Sender.Deleted || e.Sender.NetState == null) - // e.AddResponse(e.Sender, "[Logout]"); - PageQueue.Remove(e); - else - ++i; - } - - m_List = list.ToArray(); - - if (m_List.Length <= 0) - { - Add(new GumpLabel(12, 44, 2100, "The page queue is empty.")); - return; - } - - Add(new GumpPage(1)); - - for (int i = 0; i < m_List.Length; ++i) - { - PageEntry e = m_List[i]; - - if (i >= 5 && i % 5 == 0) - { - Add(new GumpButton(368, 12, 0xFA5, 0xFA7, 0, GumpButtonType.Page, i / 5 + 1)); - Add(new GumpLabel(298, 12, 2100, "Next Page")); - Add(new GumpPage(i / 5 + 1)); - Add(new GumpButton(12, 12, 0xFAE, 0xFB0, 0, GumpButtonType.Page, i / 5)); - Add(new GumpLabel(48, 12, 2100, "Previous Page")); - } - - string typeString = PageQueue.GetPageTypeName(e.Type); - - string html = - $"[{typeString}] {e.Message} [{(e.Handler == null ? "Unhandled" : "Handling")}]"; - - Add(new GumpHtml(12, 44 + i % 5 * 80, 350, 70, html, true, true)); - Add(new GumpButton(370, 44 + i % 5 * 80 + 24, 0xFA5, 0xFA7, i + 1)); - } - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (info.ButtonID >= 1 && info.ButtonID <= m_List.Length) - { - if (PageQueue.List.IndexOf(m_List[info.ButtonID - 1]) >= 0) - { - PageEntryGump g = new PageEntryGump(state.Mobile, m_List[info.ButtonID - 1]); - - g.SendTo(state); - } - else - { - state.Mobile.SendGump(new PageQueueGump()); - state.Mobile.SendMessage("That page has been removed."); - } - } - } - } - - public class PredefinedResponse - { - public PredefinedResponse(string title, string message) - { - Title = title; - Message = message; - } - - public string Title { get; set; } - - public string Message { get; set; } - - public static List List { get; private set; } = Load(); - - public static PredefinedResponse Add(string title, string message) - { - PredefinedResponse resp = new PredefinedResponse(title, message); - - List.Add(resp); - Save(); - - return resp; - } - - public static void Save() - { - List ??= Load(); - - try - { - string path = Path.Combine(Core.BaseDirectory, "Data/pageresponse.cfg"); - - using StreamWriter op = new StreamWriter(path); - for (int i = 0; i < List.Count; ++i) - { - PredefinedResponse resp = List[i]; - - op.WriteLine("{0}\t{1}", resp.Title, resp.Message); - } - } - catch (Exception e) - { - Console.WriteLine(e); - } - } - - public static List Load() - { - string path = Path.Combine(Core.BaseDirectory, "Data/pageresponse.cfg"); - - if (!File.Exists(path)) - return new List(); - - List list = new List(); - - try - { - using StreamReader ip = new StreamReader(path); - string line; - - while ((line = ip.ReadLine()?.Trim()) != null) - { - if (line.Length == 0 || line.StartsWith("#")) - continue; - - string[] split = line.Split('\t'); - - if (split.Length == 2) - list.Add(new PredefinedResponse(split[0], split[1])); - } - } - catch (Exception e) - { - Console.WriteLine(e); - } - - return list; - } - } - - public class PredefGump : Gump - { - private const int LabelColor32 = 0xFFFFFF; - - private readonly Mobile m_From; - private readonly PredefinedResponse m_Response; - - public PredefGump(Mobile from, PredefinedResponse response) : base(30, 30) - { - m_From = from; - m_Response = response; - - from.CloseGump(); - - bool canEdit = from.AccessLevel >= AccessLevel.GameMaster; - - AddPage(0); - - if (response == null) - { - AddImageTiled(0, 0, 410, 448, 0xA40); - AddAlphaRegion(1, 1, 408, 446); - - AddHtml(10, 10, 390, 20, Color(Center("Predefined Responses"), LabelColor32)); - - List list = PredefinedResponse.List; - - AddPage(1); - - int i; - - for (i = 0; i < list.Count; ++i) - { - if (i >= 5 && i % 5 == 0) - { - AddButton(368, 10, 0xFA5, 0xFA7, 0, GumpButtonType.Page, i / 5 + 1); - AddLabel(298, 10, 2100, "Next Page"); - AddPage(i / 5 + 1); - AddButton(12, 10, 0xFAE, 0xFB0, 0, GumpButtonType.Page, i / 5); - AddLabel(48, 10, 2100, "Previous Page"); - } - - PredefinedResponse resp = list[i]; - - string html = $"{resp.Title}
{resp.Message}"; - - AddHtml(12, 44 + i % 5 * 80, 350, 70, html, true, true); - - if (canEdit) - { - AddButton(370, 44 + i % 5 * 80 + 24, 0xFA5, 0xFA7, 2 + i * 3); - - if (i > 0) - AddButton(377, 44 + i % 5 * 80 + 2, 0x15E0, 0x15E4, 3 + i * 3); - else - AddImage(377, 44 + i % 5 * 80 + 2, 0x25E4); - - if (i < list.Count - 1) - AddButton(377, 44 + i % 5 * 80 + 70 - 2 - 16, 0x15E2, 0x15E6, 4 + i * 3); - else - AddImage(377, 44 + i % 5 * 80 + 70 - 2 - 16, 0x25E8); - } - } - - if (canEdit) - { - if (i >= 5 && i % 5 == 0) - { - AddButton(368, 10, 0xFA5, 0xFA7, 0, GumpButtonType.Page, i / 5 + 1); - AddLabel(298, 10, 2100, "Next Page"); - AddPage(i / 5 + 1); - AddButton(12, 10, 0xFAE, 0xFB0, 0, GumpButtonType.Page, i / 5); - AddLabel(48, 10, 2100, "Previous Page"); - } - - AddButton(12, 44 + i % 5 * 80, 0xFAB, 0xFAD, 1); - AddHtml(45, 44 + i % 5 * 80, 200, 20, Color("New Response", LabelColor32)); - } - } - else if (canEdit) - { - AddImageTiled(0, 0, 410, 250, 0xA40); - AddAlphaRegion(1, 1, 408, 248); - - AddHtml(10, 10, 390, 20, Color(Center("Predefined Response Editor"), LabelColor32)); - - AddButton(10, 40, 0xFB1, 0xFB3, 1); - AddHtml(45, 40, 200, 20, Color("Remove", LabelColor32)); - - AddButton(10, 70, 0xFA5, 0xFA7, 2); - AddHtml(45, 70, 200, 20, Color("Title:", LabelColor32)); - AddTextInput(10, 90, 300, 20, 0, response.Title); - - AddButton(10, 120, 0xFA5, 0xFA7, 3); - AddHtml(45, 120, 200, 20, Color("Message:", LabelColor32)); - AddTextInput(10, 140, 390, 100, 1, response.Message); - } - } - - public string Center(string text) => $"
{text}
"; - - public string Color(string text, int color) => $"{text}"; - - public void AddTextInput(int x, int y, int w, int h, int id, string def) - { - AddImageTiled(x, y, w, h, 0xA40); - AddImageTiled(x + 1, y + 1, w - 2, h - 2, 0xBBC); - AddTextEntry(x + 3, y + 1, w - 4, h - 2, 0x480, id, def); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_From.AccessLevel < AccessLevel.Administrator) - return; - - if (m_Response == null) - { - int index = info.ButtonID - 1; - - if (index == 0) - { - PredefinedResponse resp = new PredefinedResponse("", ""); - - List list = PredefinedResponse.List; - list.Add(resp); - - m_From.SendGump(new PredefGump(m_From, resp)); - } - else - { - --index; - - int type = index % 3; - index /= 3; - - List list = PredefinedResponse.List; - - if (index >= 0 && index < list.Count) - { - PredefinedResponse resp = list[index]; - - switch (type) - { - case 0: // edit - { - m_From.SendGump(new PredefGump(m_From, resp)); - break; - } - case 1: // move up - { - if (index > 0) - { - list.RemoveAt(index); - list.Insert(index - 1, resp); - - PredefinedResponse.Save(); - m_From.SendGump(new PredefGump(m_From, null)); - } - - break; - } - case 2: // move down - { - if (index < list.Count - 1) - { - list.RemoveAt(index); - list.Insert(index + 1, resp); - - PredefinedResponse.Save(); - m_From.SendGump(new PredefGump(m_From, null)); - } - - break; - } - } - } - } - } - else - { - List list = PredefinedResponse.List; - - switch (info.ButtonID) - { - case 1: - { - list.Remove(m_Response); - - PredefinedResponse.Save(); - m_From.SendGump(new PredefGump(m_From, null)); - break; - } - case 2: - { - TextRelay te = info.GetTextEntry(0); - - if (te != null) - m_Response.Title = te.Text; - - PredefinedResponse.Save(); - m_From.SendGump(new PredefGump(m_From, m_Response)); - - break; - } - case 3: - { - TextRelay te = info.GetTextEntry(1); - - if (te != null) - m_Response.Message = te.Text; - - PredefinedResponse.Save(); - m_From.SendGump(new PredefGump(m_From, m_Response)); - - break; - } - } - } - } - } - - public class PageEntryGump : Gump - { - private static readonly int[] m_AccessLevelHues = - { - 2100, - 2122, - 2117, - 2129, - 2415, - 2415, - 2415 - }; - - private readonly PageEntry m_Entry; - private readonly Mobile m_Mobile; - - public PageEntryGump(Mobile m, PageEntry entry) : base(30, 30) - { - m_Mobile = m; - m_Entry = entry; - - int buttons = 0; - - int bottom = 356; - - AddPage(0); - - AddImageTiled(0, 0, 410, 456, 0xA40); - AddAlphaRegion(1, 1, 408, 454); - - AddPage(1); - - AddLabel(18, 18, 2100, "Sent:"); - AddLabelCropped(128, 18, 264, 20, 2100, entry.Sent.ToString()); - - AddLabel(18, 38, 2100, "Sender:"); - AddLabelCropped(128, 38, 264, 20, 2100, - $"{entry.Sender.RawName} {entry.Sender.Location} [{entry.Sender.Map}]"); - - AddButton(18, bottom - buttons * 22, 0xFAB, 0xFAD, 8); - AddImageTiled(52, bottom - buttons * 22 + 1, 340, 80, 0xA40 /*0xBBC*/ /*0x2458*/); - AddImageTiled(53, bottom - buttons * 22 + 2, 338, 78, 0xBBC /*0x2426*/); - AddTextEntry(55, bottom - buttons++ * 22 + 2, 336, 78, 0x480, 0, ""); - - AddButton(18, bottom - buttons * 22, 0xFA5, 0xFA7, 0, GumpButtonType.Page, 2); - AddLabel(52, bottom - buttons++ * 22, 2100, "Predefined Response"); - - if (entry.Sender != m) - { - AddButton(18, bottom - buttons * 22, 0xFA5, 0xFA7, 1); - AddLabel(52, bottom - buttons++ * 22, 2100, "Go to Sender"); - } - - AddLabel(18, 58, 2100, "Handler:"); - - if (entry.Handler == null) - { - AddLabelCropped(128, 58, 264, 20, 2100, "Unhandled"); - - AddButton(18, bottom - buttons * 22, 0xFB1, 0xFB3, 5); - AddLabel(52, bottom - buttons++ * 22, 2100, "Delete Page"); - - AddButton(18, bottom - buttons * 22, 0xFB7, 0xFB9, 4); - AddLabel(52, bottom - buttons++ * 22, 2100, "Handle Page"); - } - else - { - AddLabelCropped(128, 58, 264, 20, m_AccessLevelHues[(int)entry.Handler.AccessLevel], entry.Handler.Name); - - if (entry.Handler != m) - { - AddButton(18, bottom - buttons * 22, 0xFA5, 0xFA7, 2); - AddLabel(52, bottom - buttons++ * 22, 2100, "Go to Handler"); - } - else - { - AddButton(18, bottom - buttons * 22, 0xFA2, 0xFA4, 6); - AddLabel(52, bottom - buttons++ * 22, 2100, "Abandon Page"); - - AddButton(18, bottom - buttons * 22, 0xFB7, 0xFB9, 7); - AddLabel(52, bottom - buttons++ * 22, 2100, "Page Handled"); - } - } - - AddLabel(18, 78, 2100, "Page Location:"); - AddLabelCropped(128, 78, 264, 20, 2100, $"{entry.PageLocation} [{entry.PageMap}]"); - - AddButton(18, bottom - buttons * 22, 0xFA5, 0xFA7, 3); - AddLabel(52, bottom - buttons++ * 22, 2100, "Go to Page Location"); - - if (entry.SpeechLog != null) - { - AddButton(18, bottom - buttons * 22, 0xFA5, 0xFA7, 10); - AddLabel(52, bottom - buttons * 22, 2100, "View Speech Log"); - } - - AddLabel(18, 98, 2100, "Page Type:"); - AddLabelCropped(128, 98, 264, 20, 2100, PageQueue.GetPageTypeName(entry.Type)); - - AddLabel(18, 118, 2100, "Message:"); - AddHtml(128, 118, 250, 100, entry.Message, true, true); - - AddPage(2); - - List preresp = PredefinedResponse.List; - - AddButton(18, 18, 0xFAE, 0xFB0, 0, GumpButtonType.Page, 1); - AddButton(410 - 18 - 32, 18, 0xFAB, 0xFAC, 9); - - if (preresp.Count == 0) - { - AddLabel(52, 18, 2100, "There are no predefined responses."); - } - else - { - AddLabel(52, 18, 2100, "Back"); - - for (int i = 0; i < preresp.Count; ++i) - { - AddButton(18, 40 + i * 22, 0xFA5, 0xFA7, 100 + i); - AddLabel(52, 40 + i * 22, 2100, preresp[i].Title); - } - } - } - - public void Resend(NetState state) - { - PageEntryGump g = new PageEntryGump(m_Mobile, m_Entry); - - g.SendTo(state); - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (info.ButtonID != 0 && PageQueue.List.IndexOf(m_Entry) < 0) - { - state.Mobile.SendGump(new PageQueueGump()); - state.Mobile.SendMessage("That page has been removed."); - return; - } - - switch (info.ButtonID) - { - case 0: // close - { - if (m_Entry.Handler != state.Mobile) - { - PageQueueGump g = new PageQueueGump(); - - g.SendTo(state); - } - - break; - } - case 1: // go to sender - { - Mobile m = state.Mobile; - - if (m_Entry.Sender.Deleted) - { - m.SendMessage("That character no longer exists."); - } - else if (m_Entry.Sender.Map == null || m_Entry.Sender.Map == Map.Internal) - { - m.SendMessage("That character is not in the world."); - } - else - { - // m_Entry.AddResponse(state.Mobile, "[Go Sender]"); - m.MoveToWorld(m_Entry.Sender.Location, m_Entry.Sender.Map); - - m.SendMessage("You have been teleported to that page's sender."); - - Resend(state); - } - - break; - } - case 2: // go to handler - { - Mobile m = state.Mobile; - Mobile h = m_Entry.Handler; - - if (h != null) - { - if (h.Deleted) - { - m.SendMessage("That character no longer exists."); - } - else if (h.Map == null || h.Map == Map.Internal) - { - m.SendMessage("That character is not in the world."); - } - else - { - // m_Entry.AddResponse(state.Mobile, "[Go Handler]"); - m.MoveToWorld(h.Location, h.Map); - - m.SendMessage("You have been teleported to that page's handler."); - Resend(state); - } - } - else - { - m.SendMessage("Nobody is handling that page."); - Resend(state); - } - - break; - } - case 3: // go to page location - { - Mobile m = state.Mobile; - - if (m_Entry.PageMap == null || m_Entry.PageMap == Map.Internal) - { - m.SendMessage("That location is not in the world."); - } - else - { - // m_Entry.AddResponse(state.Mobile, "[Go PageLoc]"); - m.MoveToWorld(m_Entry.PageLocation, m_Entry.PageMap); - - state.Mobile.SendMessage("You have been teleported to the original page location."); - - Resend(state); - } - - break; - } - case 4: // handle page - { - if (m_Entry.Handler == null) - { - // m_Entry.AddResponse(state.Mobile, "[Handling]"); - m_Entry.Handler = state.Mobile; - - state.Mobile.SendMessage("You are now handling the page."); - } - else - { - state.Mobile.SendMessage("Someone is already handling that page."); - } - - Resend(state); - - break; - } - case 5: // delete page - { - if (m_Entry.Handler == null) - { - // m_Entry.AddResponse(state.Mobile, "[Deleting]"); - PageQueue.Remove(m_Entry); - - state.Mobile.SendMessage("You delete the page."); - - PageQueueGump g = new PageQueueGump(); - - g.SendTo(state); - } - else - { - state.Mobile.SendMessage("Someone is handling that page, it can not be deleted."); - - Resend(state); - } - - break; - } - case 6: // abandon page - { - if (m_Entry.Handler == state.Mobile) - { - // m_Entry.AddResponse(state.Mobile, "[Abandoning]"); - state.Mobile.SendMessage("You abandon the page."); - - m_Entry.Handler = null; - } - else - { - state.Mobile.SendMessage("You are not handling that page."); - } - - Resend(state); - - break; - } - case 7: // page handled - { - if (m_Entry.Handler == state.Mobile) - { - // m_Entry.AddResponse(state.Mobile, "[Handled]"); - PageQueue.Remove(m_Entry); - - m_Entry.Handler = null; - - state.Mobile.SendMessage("You mark the page as handled, and remove it from the queue."); - - PageQueueGump g = new PageQueueGump(); - - g.SendTo(state); - } - else - { - state.Mobile.SendMessage("You are not handling that page."); - - Resend(state); - } - - break; - } - case 8: // Send message - { - TextRelay text = info.GetTextEntry(0); - - if (text != null) - // m_Entry.AddResponse(state.Mobile, "[Response] " + text.Text); - m_Entry.Sender.SendGump(new MessageSentGump(m_Entry.Sender, state.Mobile.Name, text.Text)); - // m_Entry.Sender.SendMessage( 0x482, "{0} tells you:", state.Mobile.Name ); - // m_Entry.Sender.SendMessage( 0x482, text.Text ); - - Resend(state); - - break; - } - case 9: // predef overview - { - Resend(state); - state.Mobile.SendGump(new PredefGump(state.Mobile, null)); - - break; - } - case 10: // View Speech Log - { - Resend(state); - - if (m_Entry.SpeechLog != null) state.Mobile.SendGump(new SpeechLogGump(m_Entry.Sender, m_Entry.SpeechLog)); - - break; - } - default: - { - int index = info.ButtonID - 100; - List preresp = PredefinedResponse.List; - - if (index >= 0 && index < preresp.Count) - // m_Entry.AddResponse(state.Mobile, "[PreDef] " + preresp[index].Title); - m_Entry.Sender.SendGump(new MessageSentGump(m_Entry.Sender, state.Mobile.Name, - preresp[index].Message)); - - Resend(state); - - break; - } - } - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.Help +{ + public class MessageSentGump : Gump + { + private readonly Mobile m_Mobile; + private readonly string m_Name; + private readonly string m_Text; + + public MessageSentGump(Mobile mobile, string name, string text) : base(30, 30) + { + m_Name = name; + m_Text = text; + m_Mobile = mobile; + + Closable = false; + + AddPage(0); + + AddBackground(0, 0, 92, 75, 0xA3C); + + AddImageTiled(5, 7, 82, 61, 0xA40); + AddAlphaRegion(5, 7, 82, 61); + + AddImageTiled(9, 11, 21, 53, 0xBBC); + + AddButton(10, 12, 0x7D2, 0x7D2, 0); + AddHtmlLocalized(34, 28, 65, 24, 3001002, 0xFFFFFF); // Message + } + + public override void OnResponse(NetState state, RelayInfo info) + { + m_Mobile.SendGump(new PageResponseGump(m_Mobile, m_Name, m_Text)); + + // m_Mobile.SendMessage( 0x482, "{0} tells you:", m_Name ); + // m_Mobile.SendMessage( 0x482, m_Text ); + } + } + + public class PageQueueGump : Gump + { + private readonly PageEntry[] m_List; + + public PageQueueGump() : base(30, 30) + { + Add(new GumpPage(0)); + // Add( new GumpBackground( 0, 0, 410, 448, 9200 ) ); + Add(new GumpImageTiled(0, 0, 410, 448, 0xA40)); + Add(new GumpAlphaRegion(1, 1, 408, 446)); + + Add(new GumpLabel(180, 12, 2100, "Page Queue")); + + var list = PageQueue.List; + + for (var i = 0; i < list.Count;) + { + var e = list[i]; + + if (e.Sender.Deleted || e.Sender.NetState == null) + // e.AddResponse(e.Sender, "[Logout]"); + PageQueue.Remove(e); + else + ++i; + } + + m_List = list.ToArray(); + + if (m_List.Length <= 0) + { + Add(new GumpLabel(12, 44, 2100, "The page queue is empty.")); + return; + } + + Add(new GumpPage(1)); + + for (var i = 0; i < m_List.Length; ++i) + { + var e = m_List[i]; + + if (i >= 5 && i % 5 == 0) + { + Add(new GumpButton(368, 12, 0xFA5, 0xFA7, 0, GumpButtonType.Page, i / 5 + 1)); + Add(new GumpLabel(298, 12, 2100, "Next Page")); + Add(new GumpPage(i / 5 + 1)); + Add(new GumpButton(12, 12, 0xFAE, 0xFB0, 0, GumpButtonType.Page, i / 5)); + Add(new GumpLabel(48, 12, 2100, "Previous Page")); + } + + var typeString = PageQueue.GetPageTypeName(e.Type); + + var html = + $"[{typeString}] {e.Message} [{(e.Handler == null ? "Unhandled" : "Handling")}]"; + + Add(new GumpHtml(12, 44 + i % 5 * 80, 350, 70, html, true, true)); + Add(new GumpButton(370, 44 + i % 5 * 80 + 24, 0xFA5, 0xFA7, i + 1)); + } + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (info.ButtonID >= 1 && info.ButtonID <= m_List.Length) + { + if (PageQueue.List.IndexOf(m_List[info.ButtonID - 1]) >= 0) + { + var g = new PageEntryGump(state.Mobile, m_List[info.ButtonID - 1]); + + g.SendTo(state); + } + else + { + state.Mobile.SendGump(new PageQueueGump()); + state.Mobile.SendMessage("That page has been removed."); + } + } + } + } + + public class PredefinedResponse + { + public PredefinedResponse(string title, string message) + { + Title = title; + Message = message; + } + + public string Title { get; set; } + + public string Message { get; set; } + + public static List List { get; private set; } = Load(); + + public static PredefinedResponse Add(string title, string message) + { + var resp = new PredefinedResponse(title, message); + + List.Add(resp); + Save(); + + return resp; + } + + public static void Save() + { + List ??= Load(); + + try + { + var path = Path.Combine(Core.BaseDirectory, "Data/pageresponse.cfg"); + + using var op = new StreamWriter(path); + for (var i = 0; i < List.Count; ++i) + { + var resp = List[i]; + + op.WriteLine("{0}\t{1}", resp.Title, resp.Message); + } + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + + public static List Load() + { + var path = Path.Combine(Core.BaseDirectory, "Data/pageresponse.cfg"); + + if (!File.Exists(path)) + return new List(); + + var list = new List(); + + try + { + using var ip = new StreamReader(path); + string line; + + while ((line = ip.ReadLine()?.Trim()) != null) + { + if (line.Length == 0 || line.StartsWith("#")) + continue; + + var split = line.Split('\t'); + + if (split.Length == 2) + list.Add(new PredefinedResponse(split[0], split[1])); + } + } + catch (Exception e) + { + Console.WriteLine(e); + } + + return list; + } + } + + public class PredefGump : Gump + { + private const int LabelColor32 = 0xFFFFFF; + + private readonly Mobile m_From; + private readonly PredefinedResponse m_Response; + + public PredefGump(Mobile from, PredefinedResponse response) : base(30, 30) + { + m_From = from; + m_Response = response; + + from.CloseGump(); + + var canEdit = from.AccessLevel >= AccessLevel.GameMaster; + + AddPage(0); + + if (response == null) + { + AddImageTiled(0, 0, 410, 448, 0xA40); + AddAlphaRegion(1, 1, 408, 446); + + AddHtml(10, 10, 390, 20, Color(Center("Predefined Responses"), LabelColor32)); + + var list = PredefinedResponse.List; + + AddPage(1); + + int i; + + for (i = 0; i < list.Count; ++i) + { + if (i >= 5 && i % 5 == 0) + { + AddButton(368, 10, 0xFA5, 0xFA7, 0, GumpButtonType.Page, i / 5 + 1); + AddLabel(298, 10, 2100, "Next Page"); + AddPage(i / 5 + 1); + AddButton(12, 10, 0xFAE, 0xFB0, 0, GumpButtonType.Page, i / 5); + AddLabel(48, 10, 2100, "Previous Page"); + } + + var resp = list[i]; + + var html = $"{resp.Title}
{resp.Message}"; + + AddHtml(12, 44 + i % 5 * 80, 350, 70, html, true, true); + + if (canEdit) + { + AddButton(370, 44 + i % 5 * 80 + 24, 0xFA5, 0xFA7, 2 + i * 3); + + if (i > 0) + AddButton(377, 44 + i % 5 * 80 + 2, 0x15E0, 0x15E4, 3 + i * 3); + else + AddImage(377, 44 + i % 5 * 80 + 2, 0x25E4); + + if (i < list.Count - 1) + AddButton(377, 44 + i % 5 * 80 + 70 - 2 - 16, 0x15E2, 0x15E6, 4 + i * 3); + else + AddImage(377, 44 + i % 5 * 80 + 70 - 2 - 16, 0x25E8); + } + } + + if (canEdit) + { + if (i >= 5 && i % 5 == 0) + { + AddButton(368, 10, 0xFA5, 0xFA7, 0, GumpButtonType.Page, i / 5 + 1); + AddLabel(298, 10, 2100, "Next Page"); + AddPage(i / 5 + 1); + AddButton(12, 10, 0xFAE, 0xFB0, 0, GumpButtonType.Page, i / 5); + AddLabel(48, 10, 2100, "Previous Page"); + } + + AddButton(12, 44 + i % 5 * 80, 0xFAB, 0xFAD, 1); + AddHtml(45, 44 + i % 5 * 80, 200, 20, Color("New Response", LabelColor32)); + } + } + else if (canEdit) + { + AddImageTiled(0, 0, 410, 250, 0xA40); + AddAlphaRegion(1, 1, 408, 248); + + AddHtml(10, 10, 390, 20, Color(Center("Predefined Response Editor"), LabelColor32)); + + AddButton(10, 40, 0xFB1, 0xFB3, 1); + AddHtml(45, 40, 200, 20, Color("Remove", LabelColor32)); + + AddButton(10, 70, 0xFA5, 0xFA7, 2); + AddHtml(45, 70, 200, 20, Color("Title:", LabelColor32)); + AddTextInput(10, 90, 300, 20, 0, response.Title); + + AddButton(10, 120, 0xFA5, 0xFA7, 3); + AddHtml(45, 120, 200, 20, Color("Message:", LabelColor32)); + AddTextInput(10, 140, 390, 100, 1, response.Message); + } + } + + public string Center(string text) => $"
{text}
"; + + public string Color(string text, int color) => $"{text}"; + + public void AddTextInput(int x, int y, int w, int h, int id, string def) + { + AddImageTiled(x, y, w, h, 0xA40); + AddImageTiled(x + 1, y + 1, w - 2, h - 2, 0xBBC); + AddTextEntry(x + 3, y + 1, w - 4, h - 2, 0x480, id, def); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_From.AccessLevel < AccessLevel.Administrator) + return; + + if (m_Response == null) + { + var index = info.ButtonID - 1; + + if (index == 0) + { + var resp = new PredefinedResponse("", ""); + + var list = PredefinedResponse.List; + list.Add(resp); + + m_From.SendGump(new PredefGump(m_From, resp)); + } + else + { + --index; + + var type = index % 3; + index /= 3; + + var list = PredefinedResponse.List; + + if (index >= 0 && index < list.Count) + { + var resp = list[index]; + + switch (type) + { + case 0: // edit + { + m_From.SendGump(new PredefGump(m_From, resp)); + break; + } + case 1: // move up + { + if (index > 0) + { + list.RemoveAt(index); + list.Insert(index - 1, resp); + + PredefinedResponse.Save(); + m_From.SendGump(new PredefGump(m_From, null)); + } + + break; + } + case 2: // move down + { + if (index < list.Count - 1) + { + list.RemoveAt(index); + list.Insert(index + 1, resp); + + PredefinedResponse.Save(); + m_From.SendGump(new PredefGump(m_From, null)); + } + + break; + } + } + } + } + } + else + { + var list = PredefinedResponse.List; + + switch (info.ButtonID) + { + case 1: + { + list.Remove(m_Response); + + PredefinedResponse.Save(); + m_From.SendGump(new PredefGump(m_From, null)); + break; + } + case 2: + { + var te = info.GetTextEntry(0); + + if (te != null) + m_Response.Title = te.Text; + + PredefinedResponse.Save(); + m_From.SendGump(new PredefGump(m_From, m_Response)); + + break; + } + case 3: + { + var te = info.GetTextEntry(1); + + if (te != null) + m_Response.Message = te.Text; + + PredefinedResponse.Save(); + m_From.SendGump(new PredefGump(m_From, m_Response)); + + break; + } + } + } + } + } + + public class PageEntryGump : Gump + { + private static readonly int[] m_AccessLevelHues = + { + 2100, + 2122, + 2117, + 2129, + 2415, + 2415, + 2415 + }; + + private readonly PageEntry m_Entry; + private readonly Mobile m_Mobile; + + public PageEntryGump(Mobile m, PageEntry entry) : base(30, 30) + { + m_Mobile = m; + m_Entry = entry; + + var buttons = 0; + + var bottom = 356; + + AddPage(0); + + AddImageTiled(0, 0, 410, 456, 0xA40); + AddAlphaRegion(1, 1, 408, 454); + + AddPage(1); + + AddLabel(18, 18, 2100, "Sent:"); + AddLabelCropped(128, 18, 264, 20, 2100, entry.Sent.ToString()); + + AddLabel(18, 38, 2100, "Sender:"); + AddLabelCropped( + 128, + 38, + 264, + 20, + 2100, + $"{entry.Sender.RawName} {entry.Sender.Location} [{entry.Sender.Map}]" + ); + + AddButton(18, bottom - buttons * 22, 0xFAB, 0xFAD, 8); + AddImageTiled(52, bottom - buttons * 22 + 1, 340, 80, 0xA40 /*0xBBC*/ /*0x2458*/); + AddImageTiled(53, bottom - buttons * 22 + 2, 338, 78, 0xBBC /*0x2426*/); + AddTextEntry(55, bottom - buttons++ * 22 + 2, 336, 78, 0x480, 0, ""); + + AddButton(18, bottom - buttons * 22, 0xFA5, 0xFA7, 0, GumpButtonType.Page, 2); + AddLabel(52, bottom - buttons++ * 22, 2100, "Predefined Response"); + + if (entry.Sender != m) + { + AddButton(18, bottom - buttons * 22, 0xFA5, 0xFA7, 1); + AddLabel(52, bottom - buttons++ * 22, 2100, "Go to Sender"); + } + + AddLabel(18, 58, 2100, "Handler:"); + + if (entry.Handler == null) + { + AddLabelCropped(128, 58, 264, 20, 2100, "Unhandled"); + + AddButton(18, bottom - buttons * 22, 0xFB1, 0xFB3, 5); + AddLabel(52, bottom - buttons++ * 22, 2100, "Delete Page"); + + AddButton(18, bottom - buttons * 22, 0xFB7, 0xFB9, 4); + AddLabel(52, bottom - buttons++ * 22, 2100, "Handle Page"); + } + else + { + AddLabelCropped(128, 58, 264, 20, m_AccessLevelHues[(int)entry.Handler.AccessLevel], entry.Handler.Name); + + if (entry.Handler != m) + { + AddButton(18, bottom - buttons * 22, 0xFA5, 0xFA7, 2); + AddLabel(52, bottom - buttons++ * 22, 2100, "Go to Handler"); + } + else + { + AddButton(18, bottom - buttons * 22, 0xFA2, 0xFA4, 6); + AddLabel(52, bottom - buttons++ * 22, 2100, "Abandon Page"); + + AddButton(18, bottom - buttons * 22, 0xFB7, 0xFB9, 7); + AddLabel(52, bottom - buttons++ * 22, 2100, "Page Handled"); + } + } + + AddLabel(18, 78, 2100, "Page Location:"); + AddLabelCropped(128, 78, 264, 20, 2100, $"{entry.PageLocation} [{entry.PageMap}]"); + + AddButton(18, bottom - buttons * 22, 0xFA5, 0xFA7, 3); + AddLabel(52, bottom - buttons++ * 22, 2100, "Go to Page Location"); + + if (entry.SpeechLog != null) + { + AddButton(18, bottom - buttons * 22, 0xFA5, 0xFA7, 10); + AddLabel(52, bottom - buttons * 22, 2100, "View Speech Log"); + } + + AddLabel(18, 98, 2100, "Page Type:"); + AddLabelCropped(128, 98, 264, 20, 2100, PageQueue.GetPageTypeName(entry.Type)); + + AddLabel(18, 118, 2100, "Message:"); + AddHtml(128, 118, 250, 100, entry.Message, true, true); + + AddPage(2); + + var preresp = PredefinedResponse.List; + + AddButton(18, 18, 0xFAE, 0xFB0, 0, GumpButtonType.Page, 1); + AddButton(410 - 18 - 32, 18, 0xFAB, 0xFAC, 9); + + if (preresp.Count == 0) + { + AddLabel(52, 18, 2100, "There are no predefined responses."); + } + else + { + AddLabel(52, 18, 2100, "Back"); + + for (var i = 0; i < preresp.Count; ++i) + { + AddButton(18, 40 + i * 22, 0xFA5, 0xFA7, 100 + i); + AddLabel(52, 40 + i * 22, 2100, preresp[i].Title); + } + } + } + + public void Resend(NetState state) + { + var g = new PageEntryGump(m_Mobile, m_Entry); + + g.SendTo(state); + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (info.ButtonID != 0 && PageQueue.List.IndexOf(m_Entry) < 0) + { + state.Mobile.SendGump(new PageQueueGump()); + state.Mobile.SendMessage("That page has been removed."); + return; + } + + switch (info.ButtonID) + { + case 0: // close + { + if (m_Entry.Handler != state.Mobile) + { + var g = new PageQueueGump(); + + g.SendTo(state); + } + + break; + } + case 1: // go to sender + { + var m = state.Mobile; + + if (m_Entry.Sender.Deleted) + { + m.SendMessage("That character no longer exists."); + } + else if (m_Entry.Sender.Map == null || m_Entry.Sender.Map == Map.Internal) + { + m.SendMessage("That character is not in the world."); + } + else + { + // m_Entry.AddResponse(state.Mobile, "[Go Sender]"); + m.MoveToWorld(m_Entry.Sender.Location, m_Entry.Sender.Map); + + m.SendMessage("You have been teleported to that page's sender."); + + Resend(state); + } + + break; + } + case 2: // go to handler + { + var m = state.Mobile; + var h = m_Entry.Handler; + + if (h != null) + { + if (h.Deleted) + { + m.SendMessage("That character no longer exists."); + } + else if (h.Map == null || h.Map == Map.Internal) + { + m.SendMessage("That character is not in the world."); + } + else + { + // m_Entry.AddResponse(state.Mobile, "[Go Handler]"); + m.MoveToWorld(h.Location, h.Map); + + m.SendMessage("You have been teleported to that page's handler."); + Resend(state); + } + } + else + { + m.SendMessage("Nobody is handling that page."); + Resend(state); + } + + break; + } + case 3: // go to page location + { + var m = state.Mobile; + + if (m_Entry.PageMap == null || m_Entry.PageMap == Map.Internal) + { + m.SendMessage("That location is not in the world."); + } + else + { + // m_Entry.AddResponse(state.Mobile, "[Go PageLoc]"); + m.MoveToWorld(m_Entry.PageLocation, m_Entry.PageMap); + + state.Mobile.SendMessage("You have been teleported to the original page location."); + + Resend(state); + } + + break; + } + case 4: // handle page + { + if (m_Entry.Handler == null) + { + // m_Entry.AddResponse(state.Mobile, "[Handling]"); + m_Entry.Handler = state.Mobile; + + state.Mobile.SendMessage("You are now handling the page."); + } + else + { + state.Mobile.SendMessage("Someone is already handling that page."); + } + + Resend(state); + + break; + } + case 5: // delete page + { + if (m_Entry.Handler == null) + { + // m_Entry.AddResponse(state.Mobile, "[Deleting]"); + PageQueue.Remove(m_Entry); + + state.Mobile.SendMessage("You delete the page."); + + var g = new PageQueueGump(); + + g.SendTo(state); + } + else + { + state.Mobile.SendMessage("Someone is handling that page, it can not be deleted."); + + Resend(state); + } + + break; + } + case 6: // abandon page + { + if (m_Entry.Handler == state.Mobile) + { + // m_Entry.AddResponse(state.Mobile, "[Abandoning]"); + state.Mobile.SendMessage("You abandon the page."); + + m_Entry.Handler = null; + } + else + { + state.Mobile.SendMessage("You are not handling that page."); + } + + Resend(state); + + break; + } + case 7: // page handled + { + if (m_Entry.Handler == state.Mobile) + { + // m_Entry.AddResponse(state.Mobile, "[Handled]"); + PageQueue.Remove(m_Entry); + + m_Entry.Handler = null; + + state.Mobile.SendMessage("You mark the page as handled, and remove it from the queue."); + + var g = new PageQueueGump(); + + g.SendTo(state); + } + else + { + state.Mobile.SendMessage("You are not handling that page."); + + Resend(state); + } + + break; + } + case 8: // Send message + { + var text = info.GetTextEntry(0); + + if (text != null) + // m_Entry.AddResponse(state.Mobile, "[Response] " + text.Text); + m_Entry.Sender.SendGump(new MessageSentGump(m_Entry.Sender, state.Mobile.Name, text.Text)); + // m_Entry.Sender.SendMessage( 0x482, "{0} tells you:", state.Mobile.Name ); + // m_Entry.Sender.SendMessage( 0x482, text.Text ); + + Resend(state); + + break; + } + case 9: // predef overview + { + Resend(state); + state.Mobile.SendGump(new PredefGump(state.Mobile, null)); + + break; + } + case 10: // View Speech Log + { + Resend(state); + + if (m_Entry.SpeechLog != null) + state.Mobile.SendGump(new SpeechLogGump(m_Entry.Sender, m_Entry.SpeechLog)); + + break; + } + default: + { + var index = info.ButtonID - 100; + var preresp = PredefinedResponse.List; + + if (index >= 0 && index < preresp.Count) + // m_Entry.AddResponse(state.Mobile, "[PreDef] " + preresp[index].Title); + m_Entry.Sender.SendGump( + new MessageSentGump( + m_Entry.Sender, + state.Mobile.Name, + preresp[index].Message + ) + ); + + Resend(state); + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Help/PageResponseGump.cs b/Projects/UOContent/Engines/Help/PageResponseGump.cs index 240d35024..255e06c82 100644 --- a/Projects/UOContent/Engines/Help/PageResponseGump.cs +++ b/Projects/UOContent/Engines/Help/PageResponseGump.cs @@ -1,38 +1,44 @@ -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.Help -{ - public class PageResponseGump : Gump - { - private readonly Mobile m_From; - private readonly string m_Name; - private readonly string m_Text; - - public PageResponseGump(Mobile from, string name, string text) : base(0, 0) - { - m_From = from; - m_Name = name; - m_Text = text; - - AddBackground(50, 25, 540, 430, 2600); - - AddPage(0); - - AddHtmlLocalized(150, 40, 360, 40, 1062610); //
Ultima Online Help Response
- - AddHtml(80, 90, 480, 290, $"{name} tells {from.Name}: {text}", true, true); - - AddHtmlLocalized(80, 390, 480, 40, 1062611); // Clicking the OKAY button will remove the reponse you have received. - AddButton(400, 417, 2074, 2075, 1); // OKAY - - AddButton(475, 417, 2073, 2072, 0); // CANCEL - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID != 1) - m_From.SendGump(new MessageSentGump(m_From, m_Name, m_Text)); - } - } -} +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.Help +{ + public class PageResponseGump : Gump + { + private readonly Mobile m_From; + private readonly string m_Name; + private readonly string m_Text; + + public PageResponseGump(Mobile from, string name, string text) : base(0, 0) + { + m_From = from; + m_Name = name; + m_Text = text; + + AddBackground(50, 25, 540, 430, 2600); + + AddPage(0); + + AddHtmlLocalized(150, 40, 360, 40, 1062610); //
Ultima Online Help Response
+ + AddHtml(80, 90, 480, 290, $"{name} tells {from.Name}: {text}", true, true); + + AddHtmlLocalized( + 80, + 390, + 480, + 40, + 1062611 + ); // Clicking the OKAY button will remove the reponse you have received. + AddButton(400, 417, 2074, 2075, 1); // OKAY + + AddButton(475, 417, 2073, 2072, 0); // CANCEL + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID != 1) + m_From.SendGump(new MessageSentGump(m_From, m_Name, m_Text)); + } + } +} diff --git a/Projects/UOContent/Engines/Help/SpeechLog.cs b/Projects/UOContent/Engines/Help/SpeechLog.cs index 941ddb727..8dd0d1d12 100644 --- a/Projects/UOContent/Engines/Help/SpeechLog.cs +++ b/Projects/UOContent/Engines/Help/SpeechLog.cs @@ -1,128 +1,135 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using Server.Commands; -using Server.Gumps; -using Server.Mobiles; -using Server.Targeting; - -namespace Server.Engines.Help -{ - public class SpeechLog : IEnumerable - { - // Are speech logs enabled? - public static readonly bool Enabled = true; - - // How long should we maintain each speech entry? - public static readonly TimeSpan EntryDuration = TimeSpan.FromMinutes(20.0); - - // What is the maximum number of entries a log can contain? (0 -> no limit) - public static readonly int MaxLength = 0; - - private readonly Queue m_Queue; - - public SpeechLog() => m_Queue = new Queue(); - - public int Count => m_Queue.Count; - - IEnumerator IEnumerable.GetEnumerator() => m_Queue.GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => m_Queue.GetEnumerator(); - - public static void Initialize() - { - CommandSystem.Register("SpeechLog", AccessLevel.Counselor, SpeechLog_OnCommand); - } - - [Usage("SpeechLog")] - [Description("Opens the speech log of a given target.")] - private static void SpeechLog_OnCommand(CommandEventArgs e) - { - Mobile from = e.Mobile; - - from.SendMessage("Target a player to view his speech log."); - e.Mobile.Target = new SpeechLogTarget(); - } - - public void Add(Mobile from, string speech) - { - Add(new SpeechLogEntry(from, speech)); - } - - public void Add(SpeechLogEntry entry) - { - if (MaxLength > 0 && m_Queue.Count >= MaxLength) - m_Queue.Dequeue(); - - Clean(); - - m_Queue.Enqueue(entry); - } - - public void Clean() - { - while (m_Queue.Count > 0) - { - SpeechLogEntry entry = m_Queue.Peek(); - - if (DateTime.UtcNow - entry.Created > EntryDuration) - m_Queue.Dequeue(); - else - break; - } - } - - public void CopyTo(SpeechLogEntry[] array, int index) - { - m_Queue.CopyTo(array, index); - } - - private class SpeechLogTarget : Target - { - public SpeechLogTarget() : base(-1, false, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (!(targeted is PlayerMobile pm)) - { - from.SendMessage("Speech logs aren't supported on that target."); - } - else if (from != targeted && from.AccessLevel <= pm.AccessLevel && from.AccessLevel != AccessLevel.Owner) - { - from.SendMessage("You don't have the required access level to view {0} speech log.", - pm.Female ? "her" : "his"); - } - else if (pm.SpeechLog == null) - { - from.SendMessage("{0} has no speech log.", pm.Female ? "She" : "He"); - } - else - { - CommandLogging.WriteLine(from, "{0} {1} viewing speech log of {2}", from.AccessLevel, - CommandLogging.Format(from), CommandLogging.Format(targeted)); - - Gump gump = new SpeechLogGump(pm, pm.SpeechLog); - from.SendGump(gump); - } - } - } - } - - public class SpeechLogEntry - { - public SpeechLogEntry(Mobile from, string speech) - { - From = from; - Speech = speech; - Created = DateTime.UtcNow; - } - - public Mobile From { get; } - - public string Speech { get; } - - public DateTime Created { get; } - } -} \ No newline at end of file +using System; +using System.Collections; +using System.Collections.Generic; +using Server.Commands; +using Server.Gumps; +using Server.Mobiles; +using Server.Targeting; + +namespace Server.Engines.Help +{ + public class SpeechLog : IEnumerable + { + // Are speech logs enabled? + public static readonly bool Enabled = true; + + // How long should we maintain each speech entry? + public static readonly TimeSpan EntryDuration = TimeSpan.FromMinutes(20.0); + + // What is the maximum number of entries a log can contain? (0 -> no limit) + public static readonly int MaxLength = 0; + + private readonly Queue m_Queue; + + public SpeechLog() => m_Queue = new Queue(); + + public int Count => m_Queue.Count; + + IEnumerator IEnumerable.GetEnumerator() => m_Queue.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => m_Queue.GetEnumerator(); + + public static void Initialize() + { + CommandSystem.Register("SpeechLog", AccessLevel.Counselor, SpeechLog_OnCommand); + } + + [Usage("SpeechLog")] + [Description("Opens the speech log of a given target.")] + private static void SpeechLog_OnCommand(CommandEventArgs e) + { + var from = e.Mobile; + + from.SendMessage("Target a player to view his speech log."); + e.Mobile.Target = new SpeechLogTarget(); + } + + public void Add(Mobile from, string speech) + { + Add(new SpeechLogEntry(from, speech)); + } + + public void Add(SpeechLogEntry entry) + { + if (MaxLength > 0 && m_Queue.Count >= MaxLength) + m_Queue.Dequeue(); + + Clean(); + + m_Queue.Enqueue(entry); + } + + public void Clean() + { + while (m_Queue.Count > 0) + { + var entry = m_Queue.Peek(); + + if (DateTime.UtcNow - entry.Created > EntryDuration) + m_Queue.Dequeue(); + else + break; + } + } + + public void CopyTo(SpeechLogEntry[] array, int index) + { + m_Queue.CopyTo(array, index); + } + + private class SpeechLogTarget : Target + { + public SpeechLogTarget() : base(-1, false, TargetFlags.None) + { + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (!(targeted is PlayerMobile pm)) + { + from.SendMessage("Speech logs aren't supported on that target."); + } + else if (from != targeted && from.AccessLevel <= pm.AccessLevel && from.AccessLevel != AccessLevel.Owner) + { + from.SendMessage( + "You don't have the required access level to view {0} speech log.", + pm.Female ? "her" : "his" + ); + } + else if (pm.SpeechLog == null) + { + from.SendMessage("{0} has no speech log.", pm.Female ? "She" : "He"); + } + else + { + CommandLogging.WriteLine( + from, + "{0} {1} viewing speech log of {2}", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(targeted) + ); + + Gump gump = new SpeechLogGump(pm, pm.SpeechLog); + from.SendGump(gump); + } + } + } + } + + public class SpeechLogEntry + { + public SpeechLogEntry(Mobile from, string speech) + { + From = from; + Speech = speech; + Created = DateTime.UtcNow; + } + + public Mobile From { get; } + + public string Speech { get; } + + public DateTime Created { get; } + } +} diff --git a/Projects/UOContent/Engines/Help/SpeechLogGump.cs b/Projects/UOContent/Engines/Help/SpeechLogGump.cs index a25eb1308..7ef0e32ff 100644 --- a/Projects/UOContent/Engines/Help/SpeechLogGump.cs +++ b/Projects/UOContent/Engines/Help/SpeechLogGump.cs @@ -1,113 +1,125 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Server.Accounting; -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.Help -{ - public class SpeechLogGump : Gump - { - public static readonly int MaxEntriesPerPage = 30; - private readonly List m_Log; - private readonly int m_Page; - - private readonly Mobile m_Player; - - public SpeechLogGump(Mobile player, SpeechLog log) - : this(player, new List(log)) - { - } - - public SpeechLogGump(Mobile player, List log) : this(player, log, - (log.Count - 1) / MaxEntriesPerPage) - { - } - - public SpeechLogGump(Mobile player, List log, int page) - : base(500, 30) - { - m_Player = player; - m_Log = log; - m_Page = page; - - AddImageTiled(0, 0, 300, 425, 0xA40); - AddAlphaRegion(1, 1, 298, 423); - - string playerName = player.Name; - string playerAccount = player.Account is Account ? player.Account.Username : "???"; - - AddHtml(10, 10, 280, 20, - $"
SPEECH LOG - {playerName} ({Utility.FixHtml(playerAccount)})
"); - - int lastPage = (log.Count - 1) / MaxEntriesPerPage; - - string sLog; - - if (page < 0 || page > lastPage) - { - sLog = ""; - } - else - { - int max = log.Count - (lastPage - page) * MaxEntriesPerPage; - int min = Math.Max(max - MaxEntriesPerPage, 0); - - StringBuilder builder = new StringBuilder(); - - for (int i = min; i < max; i++) - { - SpeechLogEntry entry = log[i]; - - Mobile m = entry.From; - - string name = m.Name; - string account = m.Account is Account ? m.Account.Username : "???"; - string speech = entry.Speech; - - if (i != min) - builder.Append("
"); - - builder.AppendFormat("{0} ({1}): {2}", name, Utility.FixHtml(account), - Utility.FixHtml(speech)); - } - - sLog = builder.ToString(); - } - - AddHtml(10, 40, 280, 350, sLog, false, true); - - if (page > 0) - AddButton(10, 395, 0xFAE, 0xFB0, 1); // Previous page - - AddLabel(45, 395, 0x481, $"Current page: {page + 1}/{lastPage + 1}"); - - if (page < lastPage) - AddButton(261, 395, 0xFA5, 0xFA7, 2); // Next page - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - Mobile from = sender.Mobile; - - switch (info.ButtonID) - { - case 1: // Previous page - { - if (m_Page - 1 >= 0) - from.SendGump(new SpeechLogGump(m_Player, m_Log, m_Page - 1)); - - break; - } - case 2: // Next page - { - if ((m_Page + 1) * MaxEntriesPerPage < m_Log.Count) - from.SendGump(new SpeechLogGump(m_Player, m_Log, m_Page + 1)); - - break; - } - } - } - } -} +using System; +using System.Collections.Generic; +using System.Text; +using Server.Accounting; +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.Help +{ + public class SpeechLogGump : Gump + { + public static readonly int MaxEntriesPerPage = 30; + private readonly List m_Log; + private readonly int m_Page; + + private readonly Mobile m_Player; + + public SpeechLogGump(Mobile player, SpeechLog log) + : this(player, new List(log)) + { + } + + public SpeechLogGump(Mobile player, List log) : this( + player, + log, + (log.Count - 1) / MaxEntriesPerPage + ) + { + } + + public SpeechLogGump(Mobile player, List log, int page) + : base(500, 30) + { + m_Player = player; + m_Log = log; + m_Page = page; + + AddImageTiled(0, 0, 300, 425, 0xA40); + AddAlphaRegion(1, 1, 298, 423); + + var playerName = player.Name; + var playerAccount = player.Account is Account ? player.Account.Username : "???"; + + AddHtml( + 10, + 10, + 280, + 20, + $"
SPEECH LOG - {playerName} ({Utility.FixHtml(playerAccount)})
" + ); + + var lastPage = (log.Count - 1) / MaxEntriesPerPage; + + string sLog; + + if (page < 0 || page > lastPage) + { + sLog = ""; + } + else + { + var max = log.Count - (lastPage - page) * MaxEntriesPerPage; + var min = Math.Max(max - MaxEntriesPerPage, 0); + + var builder = new StringBuilder(); + + for (var i = min; i < max; i++) + { + var entry = log[i]; + + var m = entry.From; + + var name = m.Name; + var account = m.Account is Account ? m.Account.Username : "???"; + var speech = entry.Speech; + + if (i != min) + builder.Append("
"); + + builder.AppendFormat( + "{0} ({1}): {2}", + name, + Utility.FixHtml(account), + Utility.FixHtml(speech) + ); + } + + sLog = builder.ToString(); + } + + AddHtml(10, 40, 280, 350, sLog, false, true); + + if (page > 0) + AddButton(10, 395, 0xFAE, 0xFB0, 1); // Previous page + + AddLabel(45, 395, 0x481, $"Current page: {page + 1}/{lastPage + 1}"); + + if (page < lastPage) + AddButton(261, 395, 0xFA5, 0xFA7, 2); // Next page + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var from = sender.Mobile; + + switch (info.ButtonID) + { + case 1: // Previous page + { + if (m_Page - 1 >= 0) + from.SendGump(new SpeechLogGump(m_Player, m_Log, m_Page - 1)); + + break; + } + case 2: // Next page + { + if ((m_Page + 1) * MaxEntriesPerPage < m_Log.Count) + from.SendGump(new SpeechLogGump(m_Player, m_Log, m_Page + 1)); + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Help/StuckMenu.cs b/Projects/UOContent/Engines/Help/StuckMenu.cs index cbb7349be..a3ec4f1bb 100644 --- a/Projects/UOContent/Engines/Help/StuckMenu.cs +++ b/Projects/UOContent/Engines/Help/StuckMenu.cs @@ -1,282 +1,308 @@ -using System; -using Server.Factions; -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Menus.Questions -{ - public class StuckMenuEntry - { - public StuckMenuEntry(int name, Point3D[] locations) - { - Name = name; - Locations = locations; - } - - public int Name { get; } - - public Point3D[] Locations { get; } - } - - public class StuckMenu : Gump - { - private static readonly StuckMenuEntry[] m_Entries = - { - // Britain - new StuckMenuEntry(1011028, new[] - { - new Point3D(1522, 1757, 28), - new Point3D(1519, 1619, 10), - new Point3D(1457, 1538, 30), - new Point3D(1607, 1568, 20), - new Point3D(1643, 1680, 18) - }), - - // Trinsic - new StuckMenuEntry(1011029, new[] - { - new Point3D(2005, 2754, 30), - new Point3D(1993, 2827, 0), - new Point3D(2044, 2883, 0), - new Point3D(1876, 2859, 20), - new Point3D(1865, 2687, 0) - }), - - // Vesper - new StuckMenuEntry(1011030, new[] - { - new Point3D(2973, 891, 0), - new Point3D(3003, 776, 0), - new Point3D(2910, 727, 0), - new Point3D(2865, 804, 0), - new Point3D(2832, 927, 0) - }), - - // Minoc - new StuckMenuEntry(1011031, new[] - { - new Point3D(2498, 392, 0), - new Point3D(2433, 541, 0), - new Point3D(2445, 501, 15), - new Point3D(2501, 469, 15), - new Point3D(2444, 420, 15) - }), - - // Yew - new StuckMenuEntry(1011032, new[] - { - new Point3D(490, 1166, 0), - new Point3D(652, 1098, 0), - new Point3D(650, 1013, 0), - new Point3D(536, 979, 0), - new Point3D(464, 970, 0) - }), - - // Cove - new StuckMenuEntry(1011033, new[] - { - new Point3D(2230, 1159, 0), - new Point3D(2218, 1203, 0), - new Point3D(2247, 1194, 0), - new Point3D(2236, 1224, 0), - new Point3D(2273, 1231, 0) - }) - }; - - private static readonly StuckMenuEntry[] m_T2AEntries = - { - // Papua - new StuckMenuEntry(1011057, new[] - { - new Point3D(5720, 3109, -1), - new Point3D(5677, 3176, -3), - new Point3D(5678, 3227, 0), - new Point3D(5769, 3206, -2), - new Point3D(5777, 3270, -1) - }), - - // Delucia - new StuckMenuEntry(1011058, new[] - { - new Point3D(5216, 4033, 37), - new Point3D(5262, 4049, 37), - new Point3D(5284, 4006, 37), - new Point3D(5189, 3971, 39), - new Point3D(5243, 3960, 37) - }) - }; - - private readonly bool m_MarkUse; - - private readonly Mobile m_Mobile; - private readonly Mobile m_Sender; - - private Timer m_Timer; - - public StuckMenu(Mobile beholder, Mobile beheld, bool markUse) : base(150, 50) - { - m_Sender = beholder; - m_Mobile = beheld; - m_MarkUse = markUse; - - Closable = false; - Draggable = false; - Disposable = false; - - AddBackground(0, 0, 270, 320, 2600); - - AddHtmlLocalized(50, 20, 250, 35, 1011027); // Chose a town: - - StuckMenuEntry[] entries = IsInSecondAgeArea(beheld) ? m_T2AEntries : m_Entries; - - for (int i = 0; i < entries.Length; i++) - { - StuckMenuEntry entry = entries[i]; - - AddButton(50, 55 + 35 * i, 208, 209, i + 1); - AddHtmlLocalized(75, 55 + 35 * i, 335, 40, entry.Name); - } - - AddButton(55, 263, 4005, 4007, 0); - AddHtmlLocalized(90, 265, 200, 35, 1011012); // CANCEL - } - - private static bool IsInSecondAgeArea(Mobile m) => - (m.Map == Map.Trammel || m.Map == Map.Felucca) && - ((m.X >= 5120 && m.Y >= 2304) || m.Region.IsPartOf("Terathan Keep")); - - public void BeginClose() - { - StopClose(); - - m_Timer = new CloseTimer(m_Mobile); - m_Timer.Start(); - - m_Mobile.Frozen = true; - } - - public void StopClose() - { - m_Timer?.Stop(); - - m_Mobile.Frozen = false; - } - - public override void OnResponse(NetState state, RelayInfo info) - { - StopClose(); - - if (Sigil.ExistsOn(m_Mobile)) - { - m_Mobile.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. - } - else if (info.ButtonID == 0) - { - if (m_Mobile == m_Sender) - m_Mobile.SendLocalizedMessage(1010588); // You choose not to go to any city. - } - else - { - int index = info.ButtonID - 1; - StuckMenuEntry[] entries = IsInSecondAgeArea(m_Mobile) ? m_T2AEntries : m_Entries; - - if (index >= 0 && index < entries.Length) - Teleport(entries[index]); - } - } - - private void Teleport(StuckMenuEntry entry) - { - if (m_MarkUse) - { - m_Mobile.SendLocalizedMessage(1010589); // You will be teleported within the next two minutes. - - new TeleportTimer(m_Mobile, entry, TimeSpan.FromSeconds(10.0 + Utility.RandomDouble() * 110.0)).Start(); - - if (m_Mobile is PlayerMobile mobile) - mobile.UsedStuckMenu(); - } - else - { - new TeleportTimer(m_Mobile, entry, TimeSpan.Zero).Start(); - } - } - - private class CloseTimer : Timer - { - private readonly DateTime m_End; - private readonly Mobile m_Mobile; - - public CloseTimer(Mobile m) : base(TimeSpan.Zero, TimeSpan.FromSeconds(1.0)) - { - m_Mobile = m; - m_End = DateTime.UtcNow + TimeSpan.FromMinutes(3.0); - } - - protected override void OnTick() - { - if (m_Mobile.NetState == null || DateTime.UtcNow > m_End) - { - m_Mobile.Frozen = false; - m_Mobile.CloseGump(); - - Stop(); - } - else - { - m_Mobile.Frozen = true; - } - } - } - - private class TeleportTimer : Timer - { - private readonly StuckMenuEntry m_Destination; - private readonly DateTime m_End; - private readonly Mobile m_Mobile; - - public TeleportTimer(Mobile mobile, StuckMenuEntry destination, TimeSpan delay) : base(TimeSpan.Zero, - TimeSpan.FromSeconds(1.0)) - { - Priority = TimerPriority.TwoFiftyMS; - - m_Mobile = mobile; - m_Destination = destination; - m_End = DateTime.UtcNow + delay; - } - - protected override void OnTick() - { - if (DateTime.UtcNow < m_End) - { - m_Mobile.Frozen = true; - } - else - { - m_Mobile.Frozen = false; - Stop(); - - if (Sigil.ExistsOn(m_Mobile)) - { - m_Mobile.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. - return; - } - - Point3D dest = m_Destination.Locations.RandomElement(); - - Map destMap; - if (m_Mobile.Map == Map.Trammel) - destMap = Map.Trammel; - else if (m_Mobile.Map == Map.Felucca) - destMap = Map.Felucca; - else - destMap = m_Mobile.Kills >= 5 ? Map.Felucca : Map.Trammel; - - BaseCreature.TeleportPets(m_Mobile, dest, destMap); - m_Mobile.MoveToWorld(dest, destMap); - } - } - } - } -} +using System; +using Server.Factions; +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Menus.Questions +{ + public class StuckMenuEntry + { + public StuckMenuEntry(int name, Point3D[] locations) + { + Name = name; + Locations = locations; + } + + public int Name { get; } + + public Point3D[] Locations { get; } + } + + public class StuckMenu : Gump + { + private static readonly StuckMenuEntry[] m_Entries = + { + // Britain + new StuckMenuEntry( + 1011028, + new[] + { + new Point3D(1522, 1757, 28), + new Point3D(1519, 1619, 10), + new Point3D(1457, 1538, 30), + new Point3D(1607, 1568, 20), + new Point3D(1643, 1680, 18) + } + ), + + // Trinsic + new StuckMenuEntry( + 1011029, + new[] + { + new Point3D(2005, 2754, 30), + new Point3D(1993, 2827, 0), + new Point3D(2044, 2883, 0), + new Point3D(1876, 2859, 20), + new Point3D(1865, 2687, 0) + } + ), + + // Vesper + new StuckMenuEntry( + 1011030, + new[] + { + new Point3D(2973, 891, 0), + new Point3D(3003, 776, 0), + new Point3D(2910, 727, 0), + new Point3D(2865, 804, 0), + new Point3D(2832, 927, 0) + } + ), + + // Minoc + new StuckMenuEntry( + 1011031, + new[] + { + new Point3D(2498, 392, 0), + new Point3D(2433, 541, 0), + new Point3D(2445, 501, 15), + new Point3D(2501, 469, 15), + new Point3D(2444, 420, 15) + } + ), + + // Yew + new StuckMenuEntry( + 1011032, + new[] + { + new Point3D(490, 1166, 0), + new Point3D(652, 1098, 0), + new Point3D(650, 1013, 0), + new Point3D(536, 979, 0), + new Point3D(464, 970, 0) + } + ), + + // Cove + new StuckMenuEntry( + 1011033, + new[] + { + new Point3D(2230, 1159, 0), + new Point3D(2218, 1203, 0), + new Point3D(2247, 1194, 0), + new Point3D(2236, 1224, 0), + new Point3D(2273, 1231, 0) + } + ) + }; + + private static readonly StuckMenuEntry[] m_T2AEntries = + { + // Papua + new StuckMenuEntry( + 1011057, + new[] + { + new Point3D(5720, 3109, -1), + new Point3D(5677, 3176, -3), + new Point3D(5678, 3227, 0), + new Point3D(5769, 3206, -2), + new Point3D(5777, 3270, -1) + } + ), + + // Delucia + new StuckMenuEntry( + 1011058, + new[] + { + new Point3D(5216, 4033, 37), + new Point3D(5262, 4049, 37), + new Point3D(5284, 4006, 37), + new Point3D(5189, 3971, 39), + new Point3D(5243, 3960, 37) + } + ) + }; + + private readonly bool m_MarkUse; + + private readonly Mobile m_Mobile; + private readonly Mobile m_Sender; + + private Timer m_Timer; + + public StuckMenu(Mobile beholder, Mobile beheld, bool markUse) : base(150, 50) + { + m_Sender = beholder; + m_Mobile = beheld; + m_MarkUse = markUse; + + Closable = false; + Draggable = false; + Disposable = false; + + AddBackground(0, 0, 270, 320, 2600); + + AddHtmlLocalized(50, 20, 250, 35, 1011027); // Chose a town: + + var entries = IsInSecondAgeArea(beheld) ? m_T2AEntries : m_Entries; + + for (var i = 0; i < entries.Length; i++) + { + var entry = entries[i]; + + AddButton(50, 55 + 35 * i, 208, 209, i + 1); + AddHtmlLocalized(75, 55 + 35 * i, 335, 40, entry.Name); + } + + AddButton(55, 263, 4005, 4007, 0); + AddHtmlLocalized(90, 265, 200, 35, 1011012); // CANCEL + } + + private static bool IsInSecondAgeArea(Mobile m) => + (m.Map == Map.Trammel || m.Map == Map.Felucca) && + (m.X >= 5120 && m.Y >= 2304 || m.Region.IsPartOf("Terathan Keep")); + + public void BeginClose() + { + StopClose(); + + m_Timer = new CloseTimer(m_Mobile); + m_Timer.Start(); + + m_Mobile.Frozen = true; + } + + public void StopClose() + { + m_Timer?.Stop(); + + m_Mobile.Frozen = false; + } + + public override void OnResponse(NetState state, RelayInfo info) + { + StopClose(); + + if (Sigil.ExistsOn(m_Mobile)) + { + m_Mobile.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. + } + else if (info.ButtonID == 0) + { + if (m_Mobile == m_Sender) + m_Mobile.SendLocalizedMessage(1010588); // You choose not to go to any city. + } + else + { + var index = info.ButtonID - 1; + var entries = IsInSecondAgeArea(m_Mobile) ? m_T2AEntries : m_Entries; + + if (index >= 0 && index < entries.Length) + Teleport(entries[index]); + } + } + + private void Teleport(StuckMenuEntry entry) + { + if (m_MarkUse) + { + m_Mobile.SendLocalizedMessage(1010589); // You will be teleported within the next two minutes. + + new TeleportTimer(m_Mobile, entry, TimeSpan.FromSeconds(10.0 + Utility.RandomDouble() * 110.0)).Start(); + + if (m_Mobile is PlayerMobile mobile) + mobile.UsedStuckMenu(); + } + else + { + new TeleportTimer(m_Mobile, entry, TimeSpan.Zero).Start(); + } + } + + private class CloseTimer : Timer + { + private readonly DateTime m_End; + private readonly Mobile m_Mobile; + + public CloseTimer(Mobile m) : base(TimeSpan.Zero, TimeSpan.FromSeconds(1.0)) + { + m_Mobile = m; + m_End = DateTime.UtcNow + TimeSpan.FromMinutes(3.0); + } + + protected override void OnTick() + { + if (m_Mobile.NetState == null || DateTime.UtcNow > m_End) + { + m_Mobile.Frozen = false; + m_Mobile.CloseGump(); + + Stop(); + } + else + { + m_Mobile.Frozen = true; + } + } + } + + private class TeleportTimer : Timer + { + private readonly StuckMenuEntry m_Destination; + private readonly DateTime m_End; + private readonly Mobile m_Mobile; + + public TeleportTimer(Mobile mobile, StuckMenuEntry destination, TimeSpan delay) : base( + TimeSpan.Zero, + TimeSpan.FromSeconds(1.0) + ) + { + Priority = TimerPriority.TwoFiftyMS; + + m_Mobile = mobile; + m_Destination = destination; + m_End = DateTime.UtcNow + delay; + } + + protected override void OnTick() + { + if (DateTime.UtcNow < m_End) + { + m_Mobile.Frozen = true; + } + else + { + m_Mobile.Frozen = false; + Stop(); + + if (Sigil.ExistsOn(m_Mobile)) + { + m_Mobile.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. + return; + } + + var dest = m_Destination.Locations.RandomElement(); + + Map destMap; + if (m_Mobile.Map == Map.Trammel) + destMap = Map.Trammel; + else if (m_Mobile.Map == Map.Felucca) + destMap = Map.Felucca; + else + destMap = m_Mobile.Kills >= 5 ? Map.Felucca : Map.Trammel; + + BaseCreature.TeleportPets(m_Mobile, dest, destMap); + m_Mobile.MoveToWorld(dest, destMap); + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Khaldun/Books/GrimmochJournal.cs b/Projects/UOContent/Engines/Khaldun/Books/GrimmochJournal.cs index ae117bd49..76c1fd0cf 100644 --- a/Projects/UOContent/Engines/Khaldun/Books/GrimmochJournal.cs +++ b/Projects/UOContent/Engines/Khaldun/Books/GrimmochJournal.cs @@ -1,666 +1,730 @@ -namespace Server.Items -{ - public class GrimmochJournal1 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "The daily journal of Grimmoch Drummel", "Grimmoch", - new BookPageInfo( - "Day One :", - "", - "'Tis a grand sight, this", - "primeval tomb, I agree", - "with Tavara on that.", - "And we've a good crew", - "here, they've strong", - "backs and a good"), - new BookPageInfo( - "attitude. I'm a bit", - "concerned by those", - "that worked as guides", - "for us, however. All", - "seemed well enough", - "until we revealed the", - "immense stone doors", - "of the tomb structure"), - new BookPageInfo( - "itself. Seemed to send", - "a shiver up their", - "spines and get them all", - "stirred up with", - "whispering. I'll", - "watch the lot of them", - "with a close eye, but", - "I'm confident we won't"), - new BookPageInfo( - "have any real", - "problems on the dig.", - "I'm especially proud to", - "see Thomas standing", - "out - he was a good", - "hire, despite the", - "warnings from his", - "previous employers."), - new BookPageInfo( - "He's drummed up the", - "workers into a", - "furious pace - we've", - "nearly halved the", - "estimate on the", - "timeline for", - "excavating the Tomb's", - "entrance.")); - - [Constructible] - public GrimmochJournal1() : base(Utility.Random(0xFF1, 2), false) - { - } - - public GrimmochJournal1(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class GrimmochJournal2 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "The daily journal of Grimmoch Drummel", "Grimmoch", - new BookPageInfo( - "Day Two :", - "", - "We managed to dig out", - "the last of the", - "remaining rubble", - "today, revealing the", - "entirety of the giant", - "stone doors that sealed"), - new BookPageInfo( - "ol' Khal Ankur and", - "his folk up ages ago.", - "Actually getting them", - "open was another", - "matter altogether,", - "however. As the", - "workers set to the", - "task with picks and"), - new BookPageInfo( - "crowbars, I could have", - "sworn I saw Lysander", - "Gathenwale fiddling", - "with something in that", - "musty old tome of his.", - " I've no great", - "knowledge of things", - "magical, but the way"), - new BookPageInfo( - "his hand moved over", - "that book, and the look", - "of concentration on his", - "face as he whispered", - "something to himself", - "looked like every", - "description of an", - "incantation I've ever"), - new BookPageInfo( - "heard. The strange", - "thing is, this set of", - "doors that an entire", - "crew of excavators", - "was laboring over for", - "hours, right when", - "Gathenwale finishes", - "with his mumbling..."), - new BookPageInfo( - "well, I swore the doors", - "just gave open at the", - "exact moment he", - "spoke his last bit of", - "whisper and shut the", - "tome tight in his", - "hands. When he", - "looked up, it was"), - new BookPageInfo( - "almost as if he was", - "expecting the doors to", - "be open, rather than", - "shocked that they'd", - "finally given way.")); - - [Constructible] - public GrimmochJournal2() : base(Utility.Random(0xFF1, 2), false) - { - } - - public GrimmochJournal2(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class GrimmochJournal3 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "The daily journal of Grimmoch Drummel", "Grimmoch", - new BookPageInfo( - "Day Three - Day Five:", - "", - "I might have", - "written too hastily in", - "my first entry - this", - "place doesn't seem too", - "bent on giving up any", - "secrets. Though the"), - new BookPageInfo( - "main antechamber is", - "open to us, the main", - "exit hall is blocked by", - "yet another pile of", - "rubble. Doesn't look a", - "bit like anything", - "caused by a quake or", - "instability in the"), - new BookPageInfo( - "stonework... I swear it", - "looks as if someone", - "actually piled the", - "stones up themselves,", - "some time after the", - "tomb was built. The", - "stones aren't of the", - "same set nor quality"), - new BookPageInfo( - "of the carved work", - "that surrounds them", - "- if anything, they", - "resemble the grade of", - "common rock we saw", - "in great quantities on", - "the trip here. Which", - "makes it feel all the"), - new BookPageInfo( - "more like someone", - "hauled them in and", - "deliberately covered", - "this passage. But then", - "why not decorate them", - "in the same ornate", - "manner as the rest of", - "the stone in this"), - new BookPageInfo( - "place? Lysander", - "wouldn't hear a word", - "of what I had to say -", - "to him, it was a quake", - "some time in the", - "history of the tomb,", - "and that was it, shut", - "up and move on. So I"), - new BookPageInfo( - "shut up, and got back", - "to work.")); - - [Constructible] - public GrimmochJournal3() : base(Utility.Random(0xFF1, 2), false) - { - } - - public GrimmochJournal3(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class GrimmochJournal6 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "The daily journal of Grimmoch Drummel", "Grimmoch", - new BookPageInfo( - "Day Six :", - "", - "The camp was", - "attacked last night by", - "a pack of, well, I don't", - "have a clue. I've never", - "seen the like of these", - "beasts anywhere."), - new BookPageInfo( - "Huge things, with", - "fangs the size of your", - "forefinger, covered in", - "hair and with the", - "strangest arched back", - "I've ever seen. And so", - "many of them. We", - "were forced back into"), - new BookPageInfo( - "the Tomb for the", - "night, just to keep our", - "hides on us. And", - "today Gathenwale", - "practically orders us", - "all to move the entire", - "exterior camp into the", - "Tomb. Now, I don't"), - new BookPageInfo( - "disagree that we'd be", - "well off to use the", - "place as a point of", - "fortification... but I", - "don't like it one bit, in", - "any case. I don't like", - "the look of this place,", - "nor the sound of it."), - new BookPageInfo( - "The way the wind", - "gets into the", - "passageways,", - "whistling up the", - "strangest noises.", - "Deep, sustained echoes", - "of the wind, not so", - "much flute-like as..."), - new BookPageInfo( - "well, it sounds", - "ridiculous. In any", - "case, we've set to work", - "moving the bulk of the", - "exterior camp into the", - "main antechamber, so", - "there's no use moaning", - "about it now.")); - - [Constructible] - public GrimmochJournal6() : base(Utility.Random(0xFF1, 2), false) - { - } - - public GrimmochJournal6(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class GrimmochJournal7 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "The daily journal of Grimmoch Drummel", "Grimmoch", - new BookPageInfo( - "Day Seven - Day Ten:", - "", - "I cannot stand this", - "place, I cannot bear it.", - "I've got to get out.", - "Something evil lurks", - "in this ancient place,", - "something best left"), - new BookPageInfo( - "alone. I hear them,", - "yet none of the others", - "do. And yet they", - "must. Hands, claws,", - "scratching at stone,", - "the awful scratching", - "and the piteous cries", - "that sound almost like"), - new BookPageInfo( - "laughter. I can hear", - "them above even the", - "cracks of the", - "workmen's picks, and", - "at night they are all I", - "can hear. And yet the", - "others hear nothing.", - "We must leave this"), - new BookPageInfo( - "place, we must.", - "Three workers have", - "gone missing - Tavara", - "expects they've", - "abandoned us - and I", - "count them lucky if", - "they have. I don't care", - "what the others say,"), - new BookPageInfo( - "we must leave this", - "place. We must do as", - "those before and pile", - "up the stones, block all", - "access to this primeval", - "crypt, seal it up again", - "for all eternity.")); - - [Constructible] - public GrimmochJournal7() : base(Utility.Random(0xFF1, 2), false) - { - } - - public GrimmochJournal7(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class GrimmochJournal11 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "The daily journal of Grimmoch Drummel", "Grimmoch", - new BookPageInfo( - "Day Eleven - Day", - "Thirteen :", - "", - "Lysander is gone, and", - "two more workers", - "with him. Good", - "riddance to the first.", - "He knows something."), - new BookPageInfo( - "He heard them too, I", - "know he did - and yet", - "he scowled at me", - "when I mentioned", - "them. I cannot stop", - "the noise in my head,", - "the scratching, the", - "clawing tears at my"), - new BookPageInfo( - "senses. What is it?", - "What does Lysander", - "seek that I can only", - "turn from? Where", - "has he gone? The", - "only answer to my", - "questions comes as", - "laughter from behind"), - new BookPageInfo( - "the stones.")); - - [Constructible] - public GrimmochJournal11() : base(Utility.Random(0xFF1, 2), false) - { - } - - public GrimmochJournal11(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class GrimmochJournal14 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "The daily journal of Grimmoch Drummel", "Grimmoch", - new BookPageInfo( - "Day Fourteen - Day", - "Sixteen :", - "", - "We are lost... we are", - "lost... all is lost. The", - "dead are piled up at", - "my feet. Bergen and I", - "somehow managed in"), - new BookPageInfo( - "the madness to piece", - "together a barricade,", - "barring access to the", - "camp antechamber.", - "He knows as well as I", - "that we cannot hold it", - "forever. The dead", - "come. They took"), - new BookPageInfo( - "Lysander before our", - "eyes. I pity the soul", - "of even such a", - "madman - no one", - "should die in such a", - "manner. And yet so", - "many have. We're", - "trapped here in this"), - new BookPageInfo( - "horror. So many have", - "died, and for what?", - "What curse have we", - "stumbled upon? I", - "cannot bear it, the", - "moaning, wailing cries", - "of the dead. Poor", - "Thomas, cut to pieces"), - new BookPageInfo( - "by their blades. We", - "had only an hour to", - "properly bury those", - "we could, before the", - "undead legions struck", - "again. I cannot go on...", - "I cannot go on.")); - - [Constructible] - public GrimmochJournal14() : base(Utility.Random(0xFF1, 2), false) - { - } - - public GrimmochJournal14(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class GrimmochJournal17 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "The daily journal of Grimmoch Drummel", "Grimmoch", - new BookPageInfo( - "Day Seventeen - Day", - "Twenty-Two :", - "", - "The fighting never", - "ceases... the blood", - "never stops flowing,", - "like a river through", - "the bloated corpses of"), - new BookPageInfo( - "the dead. And yet", - "there are still more.", - "Always more, with", - "the red fire gleaming", - "in their eyes. My", - "arm aches, I've taken", - "to the sword as my", - "bow seems to do little"), - new BookPageInfo( - "good... the dull ache in", - "my arm... so many", - "swings, cleaving a", - "mountain of decaying", - "flesh. And Thomas...", - "he was there, in the", - "thick of it... Thomas", - "was beside me..."), - new BookPageInfo( - "his face cleaved in", - "twain - and yet beside", - "me, fighting with us", - "against the horde until", - "he was cut down once", - "again. And I swear I", - "see him even now,", - "there in the dark"), - new BookPageInfo( - "corner of the", - "antechamber, his eyes", - "flickering in the last", - "dying embers of the", - "fire... and he stares at", - "me, and a scream fills", - "the vault - whether", - "his or mine, I can no"), - new BookPageInfo( - "longer tell.")); - - [Constructible] - public GrimmochJournal17() : base(Utility.Random(0xFF1, 2), false) - { - } - - public GrimmochJournal17(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class GrimmochJournal23 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "The daily journal of Grimmoch Drummel", "Grimmoch", - new BookPageInfo( - "Day Twenty-Three :", - "", - "We no longer bury the", - "dead.")); - - [Constructible] - public GrimmochJournal23() : base(Utility.Random(0xFF1, 2), false) - { - } - - public GrimmochJournal23(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} +namespace Server.Items +{ + public class GrimmochJournal1 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "The daily journal of Grimmoch Drummel", + "Grimmoch", + new BookPageInfo( + "Day One :", + "", + "'Tis a grand sight, this", + "primeval tomb, I agree", + "with Tavara on that.", + "And we've a good crew", + "here, they've strong", + "backs and a good" + ), + new BookPageInfo( + "attitude. I'm a bit", + "concerned by those", + "that worked as guides", + "for us, however. All", + "seemed well enough", + "until we revealed the", + "immense stone doors", + "of the tomb structure" + ), + new BookPageInfo( + "itself. Seemed to send", + "a shiver up their", + "spines and get them all", + "stirred up with", + "whispering. I'll", + "watch the lot of them", + "with a close eye, but", + "I'm confident we won't" + ), + new BookPageInfo( + "have any real", + "problems on the dig.", + "I'm especially proud to", + "see Thomas standing", + "out - he was a good", + "hire, despite the", + "warnings from his", + "previous employers." + ), + new BookPageInfo( + "He's drummed up the", + "workers into a", + "furious pace - we've", + "nearly halved the", + "estimate on the", + "timeline for", + "excavating the Tomb's", + "entrance." + ) + ); + + [Constructible] + public GrimmochJournal1() : base(Utility.Random(0xFF1, 2), false) + { + } + + public GrimmochJournal1(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class GrimmochJournal2 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "The daily journal of Grimmoch Drummel", + "Grimmoch", + new BookPageInfo( + "Day Two :", + "", + "We managed to dig out", + "the last of the", + "remaining rubble", + "today, revealing the", + "entirety of the giant", + "stone doors that sealed" + ), + new BookPageInfo( + "ol' Khal Ankur and", + "his folk up ages ago.", + "Actually getting them", + "open was another", + "matter altogether,", + "however. As the", + "workers set to the", + "task with picks and" + ), + new BookPageInfo( + "crowbars, I could have", + "sworn I saw Lysander", + "Gathenwale fiddling", + "with something in that", + "musty old tome of his.", + " I've no great", + "knowledge of things", + "magical, but the way" + ), + new BookPageInfo( + "his hand moved over", + "that book, and the look", + "of concentration on his", + "face as he whispered", + "something to himself", + "looked like every", + "description of an", + "incantation I've ever" + ), + new BookPageInfo( + "heard. The strange", + "thing is, this set of", + "doors that an entire", + "crew of excavators", + "was laboring over for", + "hours, right when", + "Gathenwale finishes", + "with his mumbling..." + ), + new BookPageInfo( + "well, I swore the doors", + "just gave open at the", + "exact moment he", + "spoke his last bit of", + "whisper and shut the", + "tome tight in his", + "hands. When he", + "looked up, it was" + ), + new BookPageInfo( + "almost as if he was", + "expecting the doors to", + "be open, rather than", + "shocked that they'd", + "finally given way." + ) + ); + + [Constructible] + public GrimmochJournal2() : base(Utility.Random(0xFF1, 2), false) + { + } + + public GrimmochJournal2(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class GrimmochJournal3 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "The daily journal of Grimmoch Drummel", + "Grimmoch", + new BookPageInfo( + "Day Three - Day Five:", + "", + "I might have", + "written too hastily in", + "my first entry - this", + "place doesn't seem too", + "bent on giving up any", + "secrets. Though the" + ), + new BookPageInfo( + "main antechamber is", + "open to us, the main", + "exit hall is blocked by", + "yet another pile of", + "rubble. Doesn't look a", + "bit like anything", + "caused by a quake or", + "instability in the" + ), + new BookPageInfo( + "stonework... I swear it", + "looks as if someone", + "actually piled the", + "stones up themselves,", + "some time after the", + "tomb was built. The", + "stones aren't of the", + "same set nor quality" + ), + new BookPageInfo( + "of the carved work", + "that surrounds them", + "- if anything, they", + "resemble the grade of", + "common rock we saw", + "in great quantities on", + "the trip here. Which", + "makes it feel all the" + ), + new BookPageInfo( + "more like someone", + "hauled them in and", + "deliberately covered", + "this passage. But then", + "why not decorate them", + "in the same ornate", + "manner as the rest of", + "the stone in this" + ), + new BookPageInfo( + "place? Lysander", + "wouldn't hear a word", + "of what I had to say -", + "to him, it was a quake", + "some time in the", + "history of the tomb,", + "and that was it, shut", + "up and move on. So I" + ), + new BookPageInfo( + "shut up, and got back", + "to work." + ) + ); + + [Constructible] + public GrimmochJournal3() : base(Utility.Random(0xFF1, 2), false) + { + } + + public GrimmochJournal3(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class GrimmochJournal6 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "The daily journal of Grimmoch Drummel", + "Grimmoch", + new BookPageInfo( + "Day Six :", + "", + "The camp was", + "attacked last night by", + "a pack of, well, I don't", + "have a clue. I've never", + "seen the like of these", + "beasts anywhere." + ), + new BookPageInfo( + "Huge things, with", + "fangs the size of your", + "forefinger, covered in", + "hair and with the", + "strangest arched back", + "I've ever seen. And so", + "many of them. We", + "were forced back into" + ), + new BookPageInfo( + "the Tomb for the", + "night, just to keep our", + "hides on us. And", + "today Gathenwale", + "practically orders us", + "all to move the entire", + "exterior camp into the", + "Tomb. Now, I don't" + ), + new BookPageInfo( + "disagree that we'd be", + "well off to use the", + "place as a point of", + "fortification... but I", + "don't like it one bit, in", + "any case. I don't like", + "the look of this place,", + "nor the sound of it." + ), + new BookPageInfo( + "The way the wind", + "gets into the", + "passageways,", + "whistling up the", + "strangest noises.", + "Deep, sustained echoes", + "of the wind, not so", + "much flute-like as..." + ), + new BookPageInfo( + "well, it sounds", + "ridiculous. In any", + "case, we've set to work", + "moving the bulk of the", + "exterior camp into the", + "main antechamber, so", + "there's no use moaning", + "about it now." + ) + ); + + [Constructible] + public GrimmochJournal6() : base(Utility.Random(0xFF1, 2), false) + { + } + + public GrimmochJournal6(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class GrimmochJournal7 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "The daily journal of Grimmoch Drummel", + "Grimmoch", + new BookPageInfo( + "Day Seven - Day Ten:", + "", + "I cannot stand this", + "place, I cannot bear it.", + "I've got to get out.", + "Something evil lurks", + "in this ancient place,", + "something best left" + ), + new BookPageInfo( + "alone. I hear them,", + "yet none of the others", + "do. And yet they", + "must. Hands, claws,", + "scratching at stone,", + "the awful scratching", + "and the piteous cries", + "that sound almost like" + ), + new BookPageInfo( + "laughter. I can hear", + "them above even the", + "cracks of the", + "workmen's picks, and", + "at night they are all I", + "can hear. And yet the", + "others hear nothing.", + "We must leave this" + ), + new BookPageInfo( + "place, we must.", + "Three workers have", + "gone missing - Tavara", + "expects they've", + "abandoned us - and I", + "count them lucky if", + "they have. I don't care", + "what the others say," + ), + new BookPageInfo( + "we must leave this", + "place. We must do as", + "those before and pile", + "up the stones, block all", + "access to this primeval", + "crypt, seal it up again", + "for all eternity." + ) + ); + + [Constructible] + public GrimmochJournal7() : base(Utility.Random(0xFF1, 2), false) + { + } + + public GrimmochJournal7(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class GrimmochJournal11 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "The daily journal of Grimmoch Drummel", + "Grimmoch", + new BookPageInfo( + "Day Eleven - Day", + "Thirteen :", + "", + "Lysander is gone, and", + "two more workers", + "with him. Good", + "riddance to the first.", + "He knows something." + ), + new BookPageInfo( + "He heard them too, I", + "know he did - and yet", + "he scowled at me", + "when I mentioned", + "them. I cannot stop", + "the noise in my head,", + "the scratching, the", + "clawing tears at my" + ), + new BookPageInfo( + "senses. What is it?", + "What does Lysander", + "seek that I can only", + "turn from? Where", + "has he gone? The", + "only answer to my", + "questions comes as", + "laughter from behind" + ), + new BookPageInfo( + "the stones." + ) + ); + + [Constructible] + public GrimmochJournal11() : base(Utility.Random(0xFF1, 2), false) + { + } + + public GrimmochJournal11(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class GrimmochJournal14 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "The daily journal of Grimmoch Drummel", + "Grimmoch", + new BookPageInfo( + "Day Fourteen - Day", + "Sixteen :", + "", + "We are lost... we are", + "lost... all is lost. The", + "dead are piled up at", + "my feet. Bergen and I", + "somehow managed in" + ), + new BookPageInfo( + "the madness to piece", + "together a barricade,", + "barring access to the", + "camp antechamber.", + "He knows as well as I", + "that we cannot hold it", + "forever. The dead", + "come. They took" + ), + new BookPageInfo( + "Lysander before our", + "eyes. I pity the soul", + "of even such a", + "madman - no one", + "should die in such a", + "manner. And yet so", + "many have. We're", + "trapped here in this" + ), + new BookPageInfo( + "horror. So many have", + "died, and for what?", + "What curse have we", + "stumbled upon? I", + "cannot bear it, the", + "moaning, wailing cries", + "of the dead. Poor", + "Thomas, cut to pieces" + ), + new BookPageInfo( + "by their blades. We", + "had only an hour to", + "properly bury those", + "we could, before the", + "undead legions struck", + "again. I cannot go on...", + "I cannot go on." + ) + ); + + [Constructible] + public GrimmochJournal14() : base(Utility.Random(0xFF1, 2), false) + { + } + + public GrimmochJournal14(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class GrimmochJournal17 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "The daily journal of Grimmoch Drummel", + "Grimmoch", + new BookPageInfo( + "Day Seventeen - Day", + "Twenty-Two :", + "", + "The fighting never", + "ceases... the blood", + "never stops flowing,", + "like a river through", + "the bloated corpses of" + ), + new BookPageInfo( + "the dead. And yet", + "there are still more.", + "Always more, with", + "the red fire gleaming", + "in their eyes. My", + "arm aches, I've taken", + "to the sword as my", + "bow seems to do little" + ), + new BookPageInfo( + "good... the dull ache in", + "my arm... so many", + "swings, cleaving a", + "mountain of decaying", + "flesh. And Thomas...", + "he was there, in the", + "thick of it... Thomas", + "was beside me..." + ), + new BookPageInfo( + "his face cleaved in", + "twain - and yet beside", + "me, fighting with us", + "against the horde until", + "he was cut down once", + "again. And I swear I", + "see him even now,", + "there in the dark" + ), + new BookPageInfo( + "corner of the", + "antechamber, his eyes", + "flickering in the last", + "dying embers of the", + "fire... and he stares at", + "me, and a scream fills", + "the vault - whether", + "his or mine, I can no" + ), + new BookPageInfo( + "longer tell." + ) + ); + + [Constructible] + public GrimmochJournal17() : base(Utility.Random(0xFF1, 2), false) + { + } + + public GrimmochJournal17(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class GrimmochJournal23 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "The daily journal of Grimmoch Drummel", + "Grimmoch", + new BookPageInfo( + "Day Twenty-Three :", + "", + "We no longer bury the", + "dead." + ) + ); + + [Constructible] + public GrimmochJournal23() : base(Utility.Random(0xFF1, 2), false) + { + } + + public GrimmochJournal23(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Khaldun/Books/LysanderNotebook.cs b/Projects/UOContent/Engines/Khaldun/Books/LysanderNotebook.cs index 8e5c62f7f..ca2daa001 100644 --- a/Projects/UOContent/Engines/Khaldun/Books/LysanderNotebook.cs +++ b/Projects/UOContent/Engines/Khaldun/Books/LysanderNotebook.cs @@ -1,458 +1,503 @@ -namespace Server.Items -{ - public class LysanderNotebook1 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Lysander's Notebook", "L. Gathenwale", - new BookPageInfo( - "Day One :", - "", - "At last, it stands", - "before me. The doors", - "of Thy Sanctum will", - "open to me now, after", - "all these years of", - "searching. I give"), - new BookPageInfo( - "myself unto Thee,", - "Khal Ankur, I have", - "come for Thy secrets", - "and I will kneel", - "prostrate before Thee.", - " Blessed are the", - "Keepers, praise unto", - "Thee, a thousand"), - new BookPageInfo( - "fortunes in the night.")); - - [Constructible] - public LysanderNotebook1() : base(Utility.Random(0xFF1, 2), false) - { - } - - public LysanderNotebook1(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class LysanderNotebook2 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Lysander's Notebook", "L. Gathenwale", - new BookPageInfo( - "Day Two:", - "", - "The woman, Tavara", - "Sewel, is unbearable.", - "Her entire demeanor", - "sickens me. I would", - "take her life for Thee", - "now, my Lord. But I"), - new BookPageInfo( - "cannot alert the", - "others. Progress is", - "made too slowly, I", - "cannot stand this", - "perpetual waiting.", - "Today I knelt down", - "with the workers,", - "tossing stones and dirt"), - new BookPageInfo( - "aside with my very", - "hands as they dug at", - "the last of the rubble", - "covering the entrance", - "to Thy Sanctum. The", - "Sewel woman was", - "shocked at my", - "demeanor, dirtying"), - new BookPageInfo( - "my robes, on my", - "knees in the muck as I", - "clawed at the rocks.", - "She thought I did this", - "for those sickly", - "scholars, or for her,", - "or for what she", - "laughably calls 'The"), - new BookPageInfo( - "Gift of Discovery', of", - "learning. As if I did", - "not know what I went", - "to find! I come for", - "Thee, Master. Soon", - "shall I receive Thy", - "gifts, Thy blessings.", - "Patience, eternal"), - new BookPageInfo( - "patience. I must take", - "my lessons well. I", - "have learned from", - "Thee, Master, I have.")); - - [Constructible] - public LysanderNotebook2() : base(Utility.Random(0xFF1, 2), false) - { - } - - public LysanderNotebook2(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class LysanderNotebook3 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Lysander's Notebook", "L. Gathenwale", - new BookPageInfo( - "Day Three - Day Six:", - "", - "What are these Beasts", - "that dare to defy our", - "presence here? Hast", - "Thou sent them,", - "Master? To tear", - "apart these foolish"), - new BookPageInfo( - "ones that accompany", - "me? That repugnant", - "pustule, Drummel, put", - "forth his absurd little", - "theories as to the", - "nature of the Beasts", - "that attacked our", - "camp, but I'll have"), - new BookPageInfo( - "none of his words. He", - "asks too many", - "questions. He is a", - "taint upon the grounds", - "of Thy Sanctum,", - "Master - I will deal", - "with him after the", - "Sewel woman."), - new BookPageInfo( - "Speaking of Sewel, I", - "have convinced that", - "empty-headed harlot", - "that we should move", - "our encampment", - "within the", - "antechamber. She", - "thinks I worry for"), - new BookPageInfo( - "her safety. I come", - "for thee, Master. I", - "make my camp in Thy", - "chambers. I sleep", - "under Thy roof. I can", - "feel Thine presence", - "even now. Soon,", - "Master. Soon.")); - - [Constructible] - public LysanderNotebook3() : base(Utility.Random(0xFF1, 2), false) - { - } - - public LysanderNotebook3(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class LysanderNotebook7 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Lysander's Notebook", "L. Gathenwale", - new BookPageInfo( - "Day Seven :", - "", - "The Sewel woman", - "pratters on endlessly.", - "And she dares to", - "speak Thy Name,", - "Master! I wish so", - "vehemently to take a"), - new BookPageInfo( - "knife to that little", - "neck of hers. She", - "struts around the", - "chambers of Thy", - "Sanctum with her", - "repugnant airs, her", - "scholarly conjecture", - "on this or that. That I"), - new BookPageInfo( - "could peel the skin", - "from her face and", - "show her how vile and", - "ugly she truly is, how", - "unworthy of entrance", - "to Thy Sanctum. I", - "must take her,", - "Master. I must rend"), - new BookPageInfo( - "that little wench to", - "pieces. I ask this gift", - "of Thee, that I might", - "cleanse Thy Sanctum", - "of her presence. Give", - "me the Sewel woman", - "and I shall show you", - "my mastery of Death,"), - new BookPageInfo( - "Master. I shall cut", - "her to bits and scatter", - "them before the", - "others as a warning.", - "I cannot stand her", - "presence, I cannot", - "abide it. And", - "Drummel! He is a"), - new BookPageInfo( - "pustule that must be", - "lanced, a sickness that", - "I must cure by blade", - "and fire. Not a trace", - "of him will be left", - "when I'm done with", - "him. Praises to Thee,", - "Master. I shall honor"), - new BookPageInfo( - "Thee with many", - "sacrifices, soon", - "enough.")); - - [Constructible] - public LysanderNotebook7() : base(Utility.Random(0xFF1, 2), false) - { - } - - public LysanderNotebook7(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class LysanderNotebook8 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Lysander's Notebook", "L. Gathenwale", - new BookPageInfo( - "Day Eight - Day Ten :", - "", - "Have you taken them,", - "Master? They could", - "not have found a way", - "past the stones that", - "block our path! The", - "three workers, My"), - new BookPageInfo( - "Master, where have", - "they gone? Curses", - "upon them! I'll cut", - "them all to pieces if", - "they show their faces", - "again, then burn the", - "rest alive upon a pyre,", - "for all to see, as a"), - new BookPageInfo( - "warning of Thy", - "Power. How could", - "they have gotten past", - "me? I sleep against", - "the very walls, to", - "hear Thy Words, to", - "feel Thy Breath. I", - "can find no egress"), - new BookPageInfo( - "from the chambers", - "that the Sewel woman", - "does not know of nor", - "have men working at", - "excavating. Where", - "have they gone,", - "Master? Have you", - "taken them, or do they"), - new BookPageInfo( - "truly flee from Thy", - "Presence? I will kill", - "them if they show", - "their faces again.", - "Give me Strength, my", - "Master, to let them", - "live a while longer,", - "until they have"), - new BookPageInfo( - "fulfilled their", - "purpose and I kneel", - "before Thee, covered", - "in their blood.")); - - [Constructible] - public LysanderNotebook8() : base(Utility.Random(0xFF1, 2), false) - { - } - - public LysanderNotebook8(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class LysanderNotebook11 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Lysander's Notebook", "L. Gathenwale", - new BookPageInfo( - "Day Eleven - Day", - "Thirteen:", - "", - "I come for Thee, my", - "Master. I come! The", - "way is clear, I have", - "found Thy path and", - "washed it in the blood"), - new BookPageInfo( - "of the two workers", - "that caught sight of", - "me. Ah, how sweet it", - "was to cut them open,", - "to see the blood pour", - "out in great torrents, to", - "stand in it, to revel in", - "it. If only I had time"), - new BookPageInfo( - "for the Sewel woman.", - "But there will be time", - "enough for her. I", - "have learned Thy", - "Patience, Master. I", - "come for Thee. I walk", - "Thy halls in penance,", - "my last steps in this"), - new BookPageInfo( - "repulsive living", - "frame. I come for", - "Thee and Thy Gifts,", - "my Master. Glory", - "Unto Thee, Khal", - "Ankur, Keeper of the", - "Seventh Death,", - "Master, Leader of the"), - new BookPageInfo( - "Chosen, the Khaldun.", - "Praises in Thy", - "Name, Master of Life", - "and Death, Lord of All.", - " Khal Ankur, Master,", - "Prophet, I join Thy", - "ranks this night, a", - "member of the"), - new BookPageInfo( - "Khaldun at last!")); - - [Constructible] - public LysanderNotebook11() : base(Utility.Random(0xFF1, 2), false) - { - } - - public LysanderNotebook11(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LysanderNotebook1 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Lysander's Notebook", + "L. Gathenwale", + new BookPageInfo( + "Day One :", + "", + "At last, it stands", + "before me. The doors", + "of Thy Sanctum will", + "open to me now, after", + "all these years of", + "searching. I give" + ), + new BookPageInfo( + "myself unto Thee,", + "Khal Ankur, I have", + "come for Thy secrets", + "and I will kneel", + "prostrate before Thee.", + " Blessed are the", + "Keepers, praise unto", + "Thee, a thousand" + ), + new BookPageInfo( + "fortunes in the night." + ) + ); + + [Constructible] + public LysanderNotebook1() : base(Utility.Random(0xFF1, 2), false) + { + } + + public LysanderNotebook1(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class LysanderNotebook2 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Lysander's Notebook", + "L. Gathenwale", + new BookPageInfo( + "Day Two:", + "", + "The woman, Tavara", + "Sewel, is unbearable.", + "Her entire demeanor", + "sickens me. I would", + "take her life for Thee", + "now, my Lord. But I" + ), + new BookPageInfo( + "cannot alert the", + "others. Progress is", + "made too slowly, I", + "cannot stand this", + "perpetual waiting.", + "Today I knelt down", + "with the workers,", + "tossing stones and dirt" + ), + new BookPageInfo( + "aside with my very", + "hands as they dug at", + "the last of the rubble", + "covering the entrance", + "to Thy Sanctum. The", + "Sewel woman was", + "shocked at my", + "demeanor, dirtying" + ), + new BookPageInfo( + "my robes, on my", + "knees in the muck as I", + "clawed at the rocks.", + "She thought I did this", + "for those sickly", + "scholars, or for her,", + "or for what she", + "laughably calls 'The" + ), + new BookPageInfo( + "Gift of Discovery', of", + "learning. As if I did", + "not know what I went", + "to find! I come for", + "Thee, Master. Soon", + "shall I receive Thy", + "gifts, Thy blessings.", + "Patience, eternal" + ), + new BookPageInfo( + "patience. I must take", + "my lessons well. I", + "have learned from", + "Thee, Master, I have." + ) + ); + + [Constructible] + public LysanderNotebook2() : base(Utility.Random(0xFF1, 2), false) + { + } + + public LysanderNotebook2(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class LysanderNotebook3 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Lysander's Notebook", + "L. Gathenwale", + new BookPageInfo( + "Day Three - Day Six:", + "", + "What are these Beasts", + "that dare to defy our", + "presence here? Hast", + "Thou sent them,", + "Master? To tear", + "apart these foolish" + ), + new BookPageInfo( + "ones that accompany", + "me? That repugnant", + "pustule, Drummel, put", + "forth his absurd little", + "theories as to the", + "nature of the Beasts", + "that attacked our", + "camp, but I'll have" + ), + new BookPageInfo( + "none of his words. He", + "asks too many", + "questions. He is a", + "taint upon the grounds", + "of Thy Sanctum,", + "Master - I will deal", + "with him after the", + "Sewel woman." + ), + new BookPageInfo( + "Speaking of Sewel, I", + "have convinced that", + "empty-headed harlot", + "that we should move", + "our encampment", + "within the", + "antechamber. She", + "thinks I worry for" + ), + new BookPageInfo( + "her safety. I come", + "for thee, Master. I", + "make my camp in Thy", + "chambers. I sleep", + "under Thy roof. I can", + "feel Thine presence", + "even now. Soon,", + "Master. Soon." + ) + ); + + [Constructible] + public LysanderNotebook3() : base(Utility.Random(0xFF1, 2), false) + { + } + + public LysanderNotebook3(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class LysanderNotebook7 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Lysander's Notebook", + "L. Gathenwale", + new BookPageInfo( + "Day Seven :", + "", + "The Sewel woman", + "pratters on endlessly.", + "And she dares to", + "speak Thy Name,", + "Master! I wish so", + "vehemently to take a" + ), + new BookPageInfo( + "knife to that little", + "neck of hers. She", + "struts around the", + "chambers of Thy", + "Sanctum with her", + "repugnant airs, her", + "scholarly conjecture", + "on this or that. That I" + ), + new BookPageInfo( + "could peel the skin", + "from her face and", + "show her how vile and", + "ugly she truly is, how", + "unworthy of entrance", + "to Thy Sanctum. I", + "must take her,", + "Master. I must rend" + ), + new BookPageInfo( + "that little wench to", + "pieces. I ask this gift", + "of Thee, that I might", + "cleanse Thy Sanctum", + "of her presence. Give", + "me the Sewel woman", + "and I shall show you", + "my mastery of Death," + ), + new BookPageInfo( + "Master. I shall cut", + "her to bits and scatter", + "them before the", + "others as a warning.", + "I cannot stand her", + "presence, I cannot", + "abide it. And", + "Drummel! He is a" + ), + new BookPageInfo( + "pustule that must be", + "lanced, a sickness that", + "I must cure by blade", + "and fire. Not a trace", + "of him will be left", + "when I'm done with", + "him. Praises to Thee,", + "Master. I shall honor" + ), + new BookPageInfo( + "Thee with many", + "sacrifices, soon", + "enough." + ) + ); + + [Constructible] + public LysanderNotebook7() : base(Utility.Random(0xFF1, 2), false) + { + } + + public LysanderNotebook7(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class LysanderNotebook8 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Lysander's Notebook", + "L. Gathenwale", + new BookPageInfo( + "Day Eight - Day Ten :", + "", + "Have you taken them,", + "Master? They could", + "not have found a way", + "past the stones that", + "block our path! The", + "three workers, My" + ), + new BookPageInfo( + "Master, where have", + "they gone? Curses", + "upon them! I'll cut", + "them all to pieces if", + "they show their faces", + "again, then burn the", + "rest alive upon a pyre,", + "for all to see, as a" + ), + new BookPageInfo( + "warning of Thy", + "Power. How could", + "they have gotten past", + "me? I sleep against", + "the very walls, to", + "hear Thy Words, to", + "feel Thy Breath. I", + "can find no egress" + ), + new BookPageInfo( + "from the chambers", + "that the Sewel woman", + "does not know of nor", + "have men working at", + "excavating. Where", + "have they gone,", + "Master? Have you", + "taken them, or do they" + ), + new BookPageInfo( + "truly flee from Thy", + "Presence? I will kill", + "them if they show", + "their faces again.", + "Give me Strength, my", + "Master, to let them", + "live a while longer,", + "until they have" + ), + new BookPageInfo( + "fulfilled their", + "purpose and I kneel", + "before Thee, covered", + "in their blood." + ) + ); + + [Constructible] + public LysanderNotebook8() : base(Utility.Random(0xFF1, 2), false) + { + } + + public LysanderNotebook8(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class LysanderNotebook11 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Lysander's Notebook", + "L. Gathenwale", + new BookPageInfo( + "Day Eleven - Day", + "Thirteen:", + "", + "I come for Thee, my", + "Master. I come! The", + "way is clear, I have", + "found Thy path and", + "washed it in the blood" + ), + new BookPageInfo( + "of the two workers", + "that caught sight of", + "me. Ah, how sweet it", + "was to cut them open,", + "to see the blood pour", + "out in great torrents, to", + "stand in it, to revel in", + "it. If only I had time" + ), + new BookPageInfo( + "for the Sewel woman.", + "But there will be time", + "enough for her. I", + "have learned Thy", + "Patience, Master. I", + "come for Thee. I walk", + "Thy halls in penance,", + "my last steps in this" + ), + new BookPageInfo( + "repulsive living", + "frame. I come for", + "Thee and Thy Gifts,", + "my Master. Glory", + "Unto Thee, Khal", + "Ankur, Keeper of the", + "Seventh Death,", + "Master, Leader of the" + ), + new BookPageInfo( + "Chosen, the Khaldun.", + "Praises in Thy", + "Name, Master of Life", + "and Death, Lord of All.", + " Khal Ankur, Master,", + "Prophet, I join Thy", + "ranks this night, a", + "member of the" + ), + new BookPageInfo( + "Khaldun at last!" + ) + ); + + [Constructible] + public LysanderNotebook11() : base(Utility.Random(0xFF1, 2), false) + { + } + + public LysanderNotebook11(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Khaldun/Books/TavarasJournal.cs b/Projects/UOContent/Engines/Khaldun/Books/TavarasJournal.cs index 38c7fb192..d59d182c8 100644 --- a/Projects/UOContent/Engines/Khaldun/Books/TavarasJournal.cs +++ b/Projects/UOContent/Engines/Khaldun/Books/TavarasJournal.cs @@ -1,1134 +1,1245 @@ -namespace Server.Items -{ - public class TavarasJournal1 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Journal: Discovery of the Tomb", "Tavara Sewel", - new BookPageInfo( - "Day One:", - "", - "The workers continue", - "tirelessly in their", - "efforts to unload our", - "supplies even as light", - "fades. I feel I should", - "lend a hand in the"), - new BookPageInfo( - "effort, and yet I", - "cannot bear to take my", - "attention away from", - "the magnificent stone", - "doors of the tomb.", - "Every inch of their", - "massive frame is", - "covered with"), - new BookPageInfo( - "intricately carved", - "design work - 'tis", - "truly a sight to see.", - "I've spent the day", - "sketching and", - "cataloging what I can", - "of them while my", - "companions set up our"), - new BookPageInfo( - "camp and make", - "preparations for", - "tomorrow's work.", - "Though the stonework", - "symbols inspire me to", - "new flights of fancy,", - "some of the workers", - "seem strangely"), - new BookPageInfo( - "fearful of them. I", - "cannot wait 'til the", - "morrow when those", - "ancient works of stone", - "shall swing open and", - "deliver unto me", - "everything I have", - "dreamed of for the"), - new BookPageInfo( - "last ten years of my", - "life.")); - - [Constructible] - public TavarasJournal1() : base(Utility.Random(0xFF1, 2), false) - { - } - - public TavarasJournal1(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TavarasJournal2 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Journal: Discovery of the Tomb", "Tavara Sewel", - new BookPageInfo( - "Day Two:", - "", - "Everything we'd", - "heard and read of the", - "tomb has proved", - "correct - and yet,", - "nothing could prepare", - "me for the sight of it"), - new BookPageInfo( - "with my own eyes.", - "The Tomb of Khal", - "Ankur has given up", - "its secrets at last! The", - "intricate stonework", - "that covered the tomb", - "doors seems to", - "continue throughout"), - new BookPageInfo( - "the entirety of the", - "catacombs, each", - "hallway and room", - "yielding a seemingly", - "endless amount of", - "information for my", - "companions and I to", - "record. It will take"), - new BookPageInfo( - "years to catalogue the", - "entirety of the Tomb,", - "if those legends of its", - "massive size prove", - "true. Sadly, a good", - "deal of the Tomb's", - "interior has been", - "damaged or utterly"), - new BookPageInfo( - "destroyed, whether", - "by seismic activity in", - "the surrounding", - "mountainside or", - "merely the slow", - "efforts of Time", - "itself, I do not know.", - "A good deal of the"), - new BookPageInfo( - "stonework has been", - "cracked or collapsed", - "entirely, especially", - "near the entrance", - "supports of the main", - "hall. Our passage has", - "indeed already been", - "entirely blocked in the"), - new BookPageInfo( - "first major room", - "we've discovered, a", - "massive pile of", - "boulders and stones", - "blocking any exit", - "from the", - "antechamber. What", - "could have caused"), - new BookPageInfo( - "such a localized", - "disruption of the", - "support structures,", - "one can only guess -", - "but it will surely take", - "an entire afternoon's", - "effort to remove even", - "a fraction of it. I look"), - new BookPageInfo( - "forward to more", - "progress tomorrow", - "once the workers have", - "set to excavating the", - "hall.")); - - [Constructible] - public TavarasJournal2() : base(Utility.Random(0xFF1, 2), false) - { - } - - public TavarasJournal2(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TavarasJournal3 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Journal: Discovery of the Tomb", "Tavara Sewel", - new BookPageInfo( - "Day Three - Day Five:", - "", - "I do not understand", - "this place... not as I", - "once thought I did.", - "Something palatable", - "seems to hinder our", - "every attempt to"), - new BookPageInfo( - "investigate this", - "ancient site.", - "Excavation work on", - "the first major", - "hallway finished only", - "yesterday - the", - "amount of stone and", - "rubble blocking the"), - new BookPageInfo( - "egress was", - "astounding, it stands", - "in immense piles", - "outside the Tomb's", - "entrance, as if we", - "were digging the", - "tunnels of this", - "abhorred place"), - new BookPageInfo( - "ourselves! The", - "satisfaction of", - "completing our efforts", - "was quickly thwarted,", - "however, as we", - "discovered the end of", - "the hallway we had", - "just revealed was"), - new BookPageInfo( - "blocked by yet another", - "colossal pile of stone.", - "I've had a few of the", - "workers set up", - "primitive scaffolding", - "in the main", - "antechamber so that I", - "can spend my time"), - new BookPageInfo( - "pouring over the detail", - "work on the stone", - "carvings while the", - "rest of our crew", - "continue excavating", - "the inner halls.")); - - [Constructible] - public TavarasJournal3() : base(Utility.Random(0xFF1, 2), false) - { - } - - public TavarasJournal3(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TavarasJournal6 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Journal: Discovery of the Tomb", "Tavara Sewel", - new BookPageInfo( - "Day Six:", - "", - "Late last night our", - "camp was set upon by", - "a pack of wild beasts", - "- behemoth creatures", - "with a speed and", - "viciousness I'd n'ere"), - new BookPageInfo( - "before seen. Even", - "Grimmoch, well", - "versed in all manner", - "of wildlife, was", - "unsure as to their", - "nature - though I lay", - "blame upon the", - "darkness covering"), - new BookPageInfo( - "their movements", - "rather than on his", - "skill as a huntsman.", - "The attacks did not let", - "up the entire night,", - "and we were", - "eventually forced to", - "flee into the Tomb"), - new BookPageInfo( - "itself to take refuge", - "from the ravenous", - "creatures - e'en", - "Lysander's spells", - "could not keep the foul", - "things from attacking", - "in great numbers.", - "The Tomb performed"), - new BookPageInfo( - "well as an impromptu", - "fortress, and we", - "managed to spend the", - "night unscathed.", - "Morning's light", - "seemed to have", - "scattered the beasts,", - "as not a single one of"), - new BookPageInfo( - "them was to be seen as", - "we exited the Tomb -", - "not even a carcass of", - "the few that were", - "slain a'fore we fled.", - "Lysander set the crew", - "to work, moving our", - "supplies and gear into"), - new BookPageInfo( - "the Tomb, in case the", - "creatures did opt to", - "return. Such savage", - "fury had the beasts -", - "and not a single one", - "ever turned to run,", - "even in the face of", - "certain death.")); - - [Constructible] - public TavarasJournal6() : base(Utility.Random(0xFF1, 2), false) - { - } - - public TavarasJournal6(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TavarasJournal7 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Journal: Discovery of the Tomb", "Tavara Sewel", - new BookPageInfo( - "Day Seven:", - "", - "T'was written that,", - "upon his death, Khal", - "Ankur's followers,", - "those known as the", - "Keepers of the", - "Seventh Death, sealed"), - new BookPageInfo( - "themselves within the", - "Sanctum they had", - "carved from the", - "mountains in his", - "honor. The Zealots of", - "his order entombed", - "the lesser followers", - "alive, then, when all"), - new BookPageInfo( - "but two remained, slit", - "their throats and", - "joined Khal Ankur in", - "death. Surely this is", - "not surprising for a", - "Cult that worshipped", - "death and sacrifice so", - "vehemently as it is"), - new BookPageInfo( - "said that the Keepers", - "did - and yet, to be in", - "this Tomb, to know", - "that somewhere in its", - "depths hundreds upon", - "hundreds of bodies", - "lay, sealed alive at", - "their own behest..."), - new BookPageInfo( - "I must confess that", - "the very thought of it", - "troubles my dreams at", - "night. I've asked", - "Lysander if we might", - "reestablish the camp", - "outside the Tomb,", - "setting up night"), - new BookPageInfo( - "watches and some sort", - "of fortification, but", - "he'll have none of it. I", - "did not press the", - "issue, as I suddenly", - "felt foolish even at", - "my askance.")); - - [Constructible] - public TavarasJournal7() : base(Utility.Random(0xFF1, 2), false) - { - } - - public TavarasJournal7(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TavarasJournal8 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Journal: Discovery of the Tomb", "Tavara Sewel", - new BookPageInfo( - "Day Eight :", - "", - "Astounding progress", - "was made today, and", - "my very head spins", - "with the excitement", - "of it. Upon full", - "excavation of the far"), - new BookPageInfo( - "western hall, another", - "large antechamber", - "was revealed. By the", - "larger, mosaic style of", - "the wall carvings and", - "their framing, as well", - "as the numerous", - "vellum scrolls and"), - new BookPageInfo( - "tomes held within, the", - "room appears to have", - "been a great museum", - "or library of sorts.", - "The sheer amount of", - "written information", - "encased within this", - "room would surely"), - new BookPageInfo( - "take me decades to", - "study e'en if I could", - "immediately decipher", - "the strange text with", - "which it was written.", - "My sheer joy at the", - "discovery was quickly", - "noted by the brute"), - new BookPageInfo( - "known as Morg", - "Bergen, who, even in", - "his simple way,", - "seemed just as", - "delighted as I that", - "some progress had", - "been made. I must", - "confess, upon his"), - new BookPageInfo( - "inclusion in our party", - "at the beginning of", - "this journey I was", - "somewhat suspect of", - "his nature, but he has", - "a startlingly quick wit", - "about him for such a", - "massive, calloused"), - new BookPageInfo( - "warrior. While", - "Lysander and e'en", - "Grimmoch always", - "seem to investigate the", - "tomb with a scowling", - "determination, Bergen", - "seems to feel the same", - "thrill of discovery as"), - new BookPageInfo( - "I. I am proud to now", - "count him as a friend,", - "and am thankful for", - "his laughter as well", - "as his strength.")); - - [Constructible] - public TavarasJournal8() : base(Utility.Random(0xFF1, 2), false) - { - } - - public TavarasJournal8(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TavarasJournal9 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Journal: Discovery of the Tomb", "Tavara Sewel", - new BookPageInfo( - "Day Nine - Day Ten:", - "", - "The excavation of the", - "next set of tunnels", - "has ceased, as three", - "of the workers have", - "gone missing in the", - "night. Bergen voiced"), - new BookPageInfo( - "the opinion that they", - "had most likely", - "abandoned our group", - "altogether and headed", - "back, as they were of", - "the number that", - "seemed especially", - "disturbed by the"), - new BookPageInfo( - "Tomb. Lysander had", - "other ideas, however.", - "In the middle of our", - "discussion on the", - "matter, he went into a", - "wild tirade on the", - "possibility that they", - "had somehow"), - new BookPageInfo( - "infiltrated the tomb's", - "interior without us.", - "The pure, hateful", - "venom in his voice", - "when he spoke of the", - "workers shocked me,", - "as I had always", - "thought him to be a"), - new BookPageInfo( - "levelheaded man of", - "great learning. As we", - "are still at work", - "digging out the rubble", - "that blocks all access", - "to the inner chambers,", - "I cannot help but", - "believe the workers"), - new BookPageInfo( - "must have fled the", - "site altogether, as", - "Bergen said.")); - - [Constructible] - public TavarasJournal9() : base(Utility.Random(0xFF1, 2), false) - { - } - - public TavarasJournal9(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TavarasJournal11 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Journal: Discovery of the Tomb", "Tavara Sewel", - new BookPageInfo( - "Day Eleven - Day", - "Thirteen:", - "", - "Two more workers", - "have gone missing.", - "Even more disturbing", - "is the fact that", - "Lysander has joined"), - new BookPageInfo( - "them. Late last night", - "the workers finished", - "excavating the next", - "main hall, and we", - "retired to the main", - "antechamber and our", - "camp to rest up for", - "exploration on the"), - new BookPageInfo( - "'morrow. In the", - "middle of the night we", - "woke to a strange", - "howling sound, and as", - "the men prepared", - "themselves for", - "another onslaught of", - "the beasts that had"), - new BookPageInfo( - "troubled our outer", - "camp, it was noticed", - "that Lysander was", - "nowhere in our", - "number. I cannot", - "fathom where he has", - "gone - the newly", - "revealed chamber"), - new BookPageInfo( - "holds no immediate", - "egress, blocked again", - "by piles of stone and", - "rubble, and I cannot", - "believe that Lysander,", - "of all people, would", - "have fled this site -", - "indeed, he had lately"), - new BookPageInfo( - "grown almost fanatical", - "in his work to", - "discover more of the", - "secrets barred to us", - "by the consistently", - "slow progress of", - "excavating each new", - "hallway. The men are"), - new BookPageInfo( - "at work even now, and", - "as the ceaseless", - "thumps and cracks of", - "their picks", - "reverberate", - "throughout the", - "entirety of the tomb,", - "the dust continues to"), - new BookPageInfo( - "pour down from the", - "ancient stonework", - "above us like some", - "horrible, eldritch", - "curse upon us all.")); - - [Constructible] - public TavarasJournal11() : base(Utility.Random(0xFF1, 2), false) - { - } - - public TavarasJournal11(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TavarasJournal14 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Journal: Discovery of the Tomb", "Tavara Sewel", - new BookPageInfo( - "Day Fourteen - Day", - "Fifteen:", - "", - "Lysander has", - "returned... and yet,", - "how can I describe the", - "horror of it? He", - "stands across the"), - new BookPageInfo( - "chamber from me", - "even now, a changed", - "man. His hair hangs", - "in grimy knots across", - "his face, his clothes", - "filthy and torn in", - "places... and the blood", - "- covered in blood, his"), - new BookPageInfo( - "skin shining in", - "scarlet reflections of", - "the torchlight. He", - "will let no one", - "approach; a thick,", - "rusted dagger in his", - "hand warding off any", - "attempts to overcome"), - new BookPageInfo( - "him. And the blood,", - "which runs down in", - "great rivulets from", - "his arms and hands -", - "it is not his own, and", - "this is enough to keep", - "us at a wary distance.", - "Morg Bergen wishes"), - new BookPageInfo( - "to subdue him", - "quickly, but there is", - "something in", - "Lysander's eyes - and", - "I remember the power", - "of his spells, even as", - "he swings the jagged", - "dagger back and forth"), - new BookPageInfo( - "in a wide swath", - "before him.", - "Something about the", - "sight of it makes my", - "stomach churn.", - "Something has", - "happened, something", - "that changes"), - new BookPageInfo( - "everything. Lysander", - "has lost his sanity to", - "this tomb... or to", - "something within it.", - "Do we dare approach?", - "We must make a", - "decision soon.")); - - [Constructible] - public TavarasJournal14() : base(Utility.Random(0xFF1, 2), false) - { - } - - public TavarasJournal14(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TavarasJournal16 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Journal: Discovery of the Tomb", "Tavara Sewel", - new BookPageInfo( - "Day Sixteen:", - "", - "Why do I write? I", - "must... not so much", - "because there must be", - "some record of", - "this... what's", - "happened here... as"), - new BookPageInfo( - "for my own sanity.", - "The act of putting pen", - "to paper calms me,", - "focuses me, even in", - "this madness.", - "Lysander is dead. So", - "many are dead. And", - "we're trapped here,"), - new BookPageInfo( - "trapped forever in", - "this nightmare. He", - "would not let us pass,", - "wild in his psychosis,", - "furious, spitting,", - "covered in blood, he", - "swung the ancient", - "dagger at any who"), - new BookPageInfo( - "approached. He", - "babbled incoherently,", - "cursed at us, the most", - "hateful curses,", - "prophecy, doom upon", - "us. Bergen would", - "have none of it.", - "Finally, he leapt at"), - new BookPageInfo( - "Lysander, his", - "massive axe at his", - "side. But he would not", - "be the end of the mad", - "mage... no... they", - "were... those hands,", - "covered in the dirt of", - "the grave, maggots,"), - new BookPageInfo( - "filth. They rose up", - "behind Lysander.", - "That look of curiosity", - "on the mage's face as", - "Bergen skidded to a", - "halt... t'was almost a", - "moment of sanity for", - "him, surely, to"), - new BookPageInfo( - "attempt to comprehend", - "what could have", - "stopped the warrior in", - "his tracks. And then", - "they were upon him.", - "Skeletal hands, arms", - "and faces with loose,", - "corrupted flesh"), - new BookPageInfo( - "hanging from yellow", - "bone. Inhuman, yet", - "once human,", - "staggering towards us", - "as their companions", - "tore at Lysander,", - "coming towards us in", - "droves.")); - - [Constructible] - public TavarasJournal16() : base(Utility.Random(0xFF1, 2), false) - { - } - - public TavarasJournal16(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TavarasJournal16b : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Journal: Discovery of the Tomb", "Tavara Sewel", - new BookPageInfo( - "Day Sixteen, Later :", - "", - "We ran. What could", - "we do? We ran back", - "towards the entrance,", - "cutting at them when", - "we could. T'was a", - "nightmare, and yet"), - new BookPageInfo( - "nothing to prepare us", - "for what would come.", - "We were almost there,", - "the entrance to this", - "abhorred crypt in", - "sight. Then the earth", - "shook with such a", - "force that we were"), - new BookPageInfo( - "dropped to our hands", - "and knees, stumbling", - "in the darkness with", - "those... those things", - "surely behind us.", - "The noise of falling", - "rock and crumbling", - "stone drowned out our"), - new BookPageInfo( - "piteous cries. No sign", - "of the entrance", - "remained.", - "We owe our lives to", - "Bergen, whose wits", - "returned quickly.", - "That he could make us", - "hurry back into the"), - new BookPageInfo( - "main antechamber...", - "actually run back", - "towards those eldritch", - "dead that stalked us.", - "But we did, the", - "strength of his", - "convictions enough for", - "us in the moment."), - new BookPageInfo( - "And at our campsite", - "we erected our last", - "defense, a pitiable", - "wall of wood and", - "stone, anything at", - "hand that might block", - "the tide of those", - "nightmare creatures."), - new BookPageInfo( - "And I sit against it", - "even now. I can hear", - "their moans, their", - "wailing cries in the", - "distance - they'll be", - "here soon, even at the", - "unhurried pace of the", - "shuffling dead.")); - - [Constructible] - public TavarasJournal16b() : base(Utility.Random(0xFF1, 2), false) - { - } - - public TavarasJournal16b(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TavarasJournal17 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Journal: Discovery of the Tomb", "Tavara Sewel", - new BookPageInfo( - "Day Seventeen - Day", - "Eighteen :", - "", - "I cannot go on much", - "longer. I know now", - "t'was no work of the", - "earth that trapped us", - "here - I can feel His"), - new BookPageInfo( - "force in it. It was His", - "will, His power that", - "has sealed us here in", - "this nightmare. The", - "barricade will not be", - "enough. So many of", - "them. They come like", - "unto the ocean's waves"), - new BookPageInfo( - "- ceaseless,", - "neverending. For", - "every five we strike", - "down, another ten rise", - "up against us. And", - "like the sands we", - "cannot help but be", - "brought down, wasted"), - new BookPageInfo( - "away in this ocean of", - "blood.")); - - [Constructible] - public TavarasJournal17() : base(Utility.Random(0xFF1, 2), false) - { - } - - public TavarasJournal17(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TavarasJournal19 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Journal: Discovery of the Tomb", "Tavara Sewel", - new BookPageInfo( - "Day Nineteen - Day", - "Twenty-One :", - "", - "The barricade won't", - "hold - never, and", - "they'll come, they", - "come even now. I", - "would tear the last of"), - new BookPageInfo( - "it down, let them in to", - "devour us all, if only", - "to stop the screaming", - "- the awful, wailing", - "cries that fill the tomb", - "with their presence.", - "May my ancestors", - "forgive me, but it"), - new BookPageInfo( - "must be done. I must", - "end this.")); - - [Constructible] - public TavarasJournal19() : base(Utility.Random(0xFF1, 2), false) - { - } - - public TavarasJournal19(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TavarasJournal1 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Journal: Discovery of the Tomb", + "Tavara Sewel", + new BookPageInfo( + "Day One:", + "", + "The workers continue", + "tirelessly in their", + "efforts to unload our", + "supplies even as light", + "fades. I feel I should", + "lend a hand in the" + ), + new BookPageInfo( + "effort, and yet I", + "cannot bear to take my", + "attention away from", + "the magnificent stone", + "doors of the tomb.", + "Every inch of their", + "massive frame is", + "covered with" + ), + new BookPageInfo( + "intricately carved", + "design work - 'tis", + "truly a sight to see.", + "I've spent the day", + "sketching and", + "cataloging what I can", + "of them while my", + "companions set up our" + ), + new BookPageInfo( + "camp and make", + "preparations for", + "tomorrow's work.", + "Though the stonework", + "symbols inspire me to", + "new flights of fancy,", + "some of the workers", + "seem strangely" + ), + new BookPageInfo( + "fearful of them. I", + "cannot wait 'til the", + "morrow when those", + "ancient works of stone", + "shall swing open and", + "deliver unto me", + "everything I have", + "dreamed of for the" + ), + new BookPageInfo( + "last ten years of my", + "life." + ) + ); + + [Constructible] + public TavarasJournal1() : base(Utility.Random(0xFF1, 2), false) + { + } + + public TavarasJournal1(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class TavarasJournal2 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Journal: Discovery of the Tomb", + "Tavara Sewel", + new BookPageInfo( + "Day Two:", + "", + "Everything we'd", + "heard and read of the", + "tomb has proved", + "correct - and yet,", + "nothing could prepare", + "me for the sight of it" + ), + new BookPageInfo( + "with my own eyes.", + "The Tomb of Khal", + "Ankur has given up", + "its secrets at last! The", + "intricate stonework", + "that covered the tomb", + "doors seems to", + "continue throughout" + ), + new BookPageInfo( + "the entirety of the", + "catacombs, each", + "hallway and room", + "yielding a seemingly", + "endless amount of", + "information for my", + "companions and I to", + "record. It will take" + ), + new BookPageInfo( + "years to catalogue the", + "entirety of the Tomb,", + "if those legends of its", + "massive size prove", + "true. Sadly, a good", + "deal of the Tomb's", + "interior has been", + "damaged or utterly" + ), + new BookPageInfo( + "destroyed, whether", + "by seismic activity in", + "the surrounding", + "mountainside or", + "merely the slow", + "efforts of Time", + "itself, I do not know.", + "A good deal of the" + ), + new BookPageInfo( + "stonework has been", + "cracked or collapsed", + "entirely, especially", + "near the entrance", + "supports of the main", + "hall. Our passage has", + "indeed already been", + "entirely blocked in the" + ), + new BookPageInfo( + "first major room", + "we've discovered, a", + "massive pile of", + "boulders and stones", + "blocking any exit", + "from the", + "antechamber. What", + "could have caused" + ), + new BookPageInfo( + "such a localized", + "disruption of the", + "support structures,", + "one can only guess -", + "but it will surely take", + "an entire afternoon's", + "effort to remove even", + "a fraction of it. I look" + ), + new BookPageInfo( + "forward to more", + "progress tomorrow", + "once the workers have", + "set to excavating the", + "hall." + ) + ); + + [Constructible] + public TavarasJournal2() : base(Utility.Random(0xFF1, 2), false) + { + } + + public TavarasJournal2(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class TavarasJournal3 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Journal: Discovery of the Tomb", + "Tavara Sewel", + new BookPageInfo( + "Day Three - Day Five:", + "", + "I do not understand", + "this place... not as I", + "once thought I did.", + "Something palatable", + "seems to hinder our", + "every attempt to" + ), + new BookPageInfo( + "investigate this", + "ancient site.", + "Excavation work on", + "the first major", + "hallway finished only", + "yesterday - the", + "amount of stone and", + "rubble blocking the" + ), + new BookPageInfo( + "egress was", + "astounding, it stands", + "in immense piles", + "outside the Tomb's", + "entrance, as if we", + "were digging the", + "tunnels of this", + "abhorred place" + ), + new BookPageInfo( + "ourselves! The", + "satisfaction of", + "completing our efforts", + "was quickly thwarted,", + "however, as we", + "discovered the end of", + "the hallway we had", + "just revealed was" + ), + new BookPageInfo( + "blocked by yet another", + "colossal pile of stone.", + "I've had a few of the", + "workers set up", + "primitive scaffolding", + "in the main", + "antechamber so that I", + "can spend my time" + ), + new BookPageInfo( + "pouring over the detail", + "work on the stone", + "carvings while the", + "rest of our crew", + "continue excavating", + "the inner halls." + ) + ); + + [Constructible] + public TavarasJournal3() : base(Utility.Random(0xFF1, 2), false) + { + } + + public TavarasJournal3(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class TavarasJournal6 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Journal: Discovery of the Tomb", + "Tavara Sewel", + new BookPageInfo( + "Day Six:", + "", + "Late last night our", + "camp was set upon by", + "a pack of wild beasts", + "- behemoth creatures", + "with a speed and", + "viciousness I'd n'ere" + ), + new BookPageInfo( + "before seen. Even", + "Grimmoch, well", + "versed in all manner", + "of wildlife, was", + "unsure as to their", + "nature - though I lay", + "blame upon the", + "darkness covering" + ), + new BookPageInfo( + "their movements", + "rather than on his", + "skill as a huntsman.", + "The attacks did not let", + "up the entire night,", + "and we were", + "eventually forced to", + "flee into the Tomb" + ), + new BookPageInfo( + "itself to take refuge", + "from the ravenous", + "creatures - e'en", + "Lysander's spells", + "could not keep the foul", + "things from attacking", + "in great numbers.", + "The Tomb performed" + ), + new BookPageInfo( + "well as an impromptu", + "fortress, and we", + "managed to spend the", + "night unscathed.", + "Morning's light", + "seemed to have", + "scattered the beasts,", + "as not a single one of" + ), + new BookPageInfo( + "them was to be seen as", + "we exited the Tomb -", + "not even a carcass of", + "the few that were", + "slain a'fore we fled.", + "Lysander set the crew", + "to work, moving our", + "supplies and gear into" + ), + new BookPageInfo( + "the Tomb, in case the", + "creatures did opt to", + "return. Such savage", + "fury had the beasts -", + "and not a single one", + "ever turned to run,", + "even in the face of", + "certain death." + ) + ); + + [Constructible] + public TavarasJournal6() : base(Utility.Random(0xFF1, 2), false) + { + } + + public TavarasJournal6(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class TavarasJournal7 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Journal: Discovery of the Tomb", + "Tavara Sewel", + new BookPageInfo( + "Day Seven:", + "", + "T'was written that,", + "upon his death, Khal", + "Ankur's followers,", + "those known as the", + "Keepers of the", + "Seventh Death, sealed" + ), + new BookPageInfo( + "themselves within the", + "Sanctum they had", + "carved from the", + "mountains in his", + "honor. The Zealots of", + "his order entombed", + "the lesser followers", + "alive, then, when all" + ), + new BookPageInfo( + "but two remained, slit", + "their throats and", + "joined Khal Ankur in", + "death. Surely this is", + "not surprising for a", + "Cult that worshipped", + "death and sacrifice so", + "vehemently as it is" + ), + new BookPageInfo( + "said that the Keepers", + "did - and yet, to be in", + "this Tomb, to know", + "that somewhere in its", + "depths hundreds upon", + "hundreds of bodies", + "lay, sealed alive at", + "their own behest..." + ), + new BookPageInfo( + "I must confess that", + "the very thought of it", + "troubles my dreams at", + "night. I've asked", + "Lysander if we might", + "reestablish the camp", + "outside the Tomb,", + "setting up night" + ), + new BookPageInfo( + "watches and some sort", + "of fortification, but", + "he'll have none of it. I", + "did not press the", + "issue, as I suddenly", + "felt foolish even at", + "my askance." + ) + ); + + [Constructible] + public TavarasJournal7() : base(Utility.Random(0xFF1, 2), false) + { + } + + public TavarasJournal7(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class TavarasJournal8 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Journal: Discovery of the Tomb", + "Tavara Sewel", + new BookPageInfo( + "Day Eight :", + "", + "Astounding progress", + "was made today, and", + "my very head spins", + "with the excitement", + "of it. Upon full", + "excavation of the far" + ), + new BookPageInfo( + "western hall, another", + "large antechamber", + "was revealed. By the", + "larger, mosaic style of", + "the wall carvings and", + "their framing, as well", + "as the numerous", + "vellum scrolls and" + ), + new BookPageInfo( + "tomes held within, the", + "room appears to have", + "been a great museum", + "or library of sorts.", + "The sheer amount of", + "written information", + "encased within this", + "room would surely" + ), + new BookPageInfo( + "take me decades to", + "study e'en if I could", + "immediately decipher", + "the strange text with", + "which it was written.", + "My sheer joy at the", + "discovery was quickly", + "noted by the brute" + ), + new BookPageInfo( + "known as Morg", + "Bergen, who, even in", + "his simple way,", + "seemed just as", + "delighted as I that", + "some progress had", + "been made. I must", + "confess, upon his" + ), + new BookPageInfo( + "inclusion in our party", + "at the beginning of", + "this journey I was", + "somewhat suspect of", + "his nature, but he has", + "a startlingly quick wit", + "about him for such a", + "massive, calloused" + ), + new BookPageInfo( + "warrior. While", + "Lysander and e'en", + "Grimmoch always", + "seem to investigate the", + "tomb with a scowling", + "determination, Bergen", + "seems to feel the same", + "thrill of discovery as" + ), + new BookPageInfo( + "I. I am proud to now", + "count him as a friend,", + "and am thankful for", + "his laughter as well", + "as his strength." + ) + ); + + [Constructible] + public TavarasJournal8() : base(Utility.Random(0xFF1, 2), false) + { + } + + public TavarasJournal8(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class TavarasJournal9 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Journal: Discovery of the Tomb", + "Tavara Sewel", + new BookPageInfo( + "Day Nine - Day Ten:", + "", + "The excavation of the", + "next set of tunnels", + "has ceased, as three", + "of the workers have", + "gone missing in the", + "night. Bergen voiced" + ), + new BookPageInfo( + "the opinion that they", + "had most likely", + "abandoned our group", + "altogether and headed", + "back, as they were of", + "the number that", + "seemed especially", + "disturbed by the" + ), + new BookPageInfo( + "Tomb. Lysander had", + "other ideas, however.", + "In the middle of our", + "discussion on the", + "matter, he went into a", + "wild tirade on the", + "possibility that they", + "had somehow" + ), + new BookPageInfo( + "infiltrated the tomb's", + "interior without us.", + "The pure, hateful", + "venom in his voice", + "when he spoke of the", + "workers shocked me,", + "as I had always", + "thought him to be a" + ), + new BookPageInfo( + "levelheaded man of", + "great learning. As we", + "are still at work", + "digging out the rubble", + "that blocks all access", + "to the inner chambers,", + "I cannot help but", + "believe the workers" + ), + new BookPageInfo( + "must have fled the", + "site altogether, as", + "Bergen said." + ) + ); + + [Constructible] + public TavarasJournal9() : base(Utility.Random(0xFF1, 2), false) + { + } + + public TavarasJournal9(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class TavarasJournal11 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Journal: Discovery of the Tomb", + "Tavara Sewel", + new BookPageInfo( + "Day Eleven - Day", + "Thirteen:", + "", + "Two more workers", + "have gone missing.", + "Even more disturbing", + "is the fact that", + "Lysander has joined" + ), + new BookPageInfo( + "them. Late last night", + "the workers finished", + "excavating the next", + "main hall, and we", + "retired to the main", + "antechamber and our", + "camp to rest up for", + "exploration on the" + ), + new BookPageInfo( + "'morrow. In the", + "middle of the night we", + "woke to a strange", + "howling sound, and as", + "the men prepared", + "themselves for", + "another onslaught of", + "the beasts that had" + ), + new BookPageInfo( + "troubled our outer", + "camp, it was noticed", + "that Lysander was", + "nowhere in our", + "number. I cannot", + "fathom where he has", + "gone - the newly", + "revealed chamber" + ), + new BookPageInfo( + "holds no immediate", + "egress, blocked again", + "by piles of stone and", + "rubble, and I cannot", + "believe that Lysander,", + "of all people, would", + "have fled this site -", + "indeed, he had lately" + ), + new BookPageInfo( + "grown almost fanatical", + "in his work to", + "discover more of the", + "secrets barred to us", + "by the consistently", + "slow progress of", + "excavating each new", + "hallway. The men are" + ), + new BookPageInfo( + "at work even now, and", + "as the ceaseless", + "thumps and cracks of", + "their picks", + "reverberate", + "throughout the", + "entirety of the tomb,", + "the dust continues to" + ), + new BookPageInfo( + "pour down from the", + "ancient stonework", + "above us like some", + "horrible, eldritch", + "curse upon us all." + ) + ); + + [Constructible] + public TavarasJournal11() : base(Utility.Random(0xFF1, 2), false) + { + } + + public TavarasJournal11(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class TavarasJournal14 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Journal: Discovery of the Tomb", + "Tavara Sewel", + new BookPageInfo( + "Day Fourteen - Day", + "Fifteen:", + "", + "Lysander has", + "returned... and yet,", + "how can I describe the", + "horror of it? He", + "stands across the" + ), + new BookPageInfo( + "chamber from me", + "even now, a changed", + "man. His hair hangs", + "in grimy knots across", + "his face, his clothes", + "filthy and torn in", + "places... and the blood", + "- covered in blood, his" + ), + new BookPageInfo( + "skin shining in", + "scarlet reflections of", + "the torchlight. He", + "will let no one", + "approach; a thick,", + "rusted dagger in his", + "hand warding off any", + "attempts to overcome" + ), + new BookPageInfo( + "him. And the blood,", + "which runs down in", + "great rivulets from", + "his arms and hands -", + "it is not his own, and", + "this is enough to keep", + "us at a wary distance.", + "Morg Bergen wishes" + ), + new BookPageInfo( + "to subdue him", + "quickly, but there is", + "something in", + "Lysander's eyes - and", + "I remember the power", + "of his spells, even as", + "he swings the jagged", + "dagger back and forth" + ), + new BookPageInfo( + "in a wide swath", + "before him.", + "Something about the", + "sight of it makes my", + "stomach churn.", + "Something has", + "happened, something", + "that changes" + ), + new BookPageInfo( + "everything. Lysander", + "has lost his sanity to", + "this tomb... or to", + "something within it.", + "Do we dare approach?", + "We must make a", + "decision soon." + ) + ); + + [Constructible] + public TavarasJournal14() : base(Utility.Random(0xFF1, 2), false) + { + } + + public TavarasJournal14(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class TavarasJournal16 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Journal: Discovery of the Tomb", + "Tavara Sewel", + new BookPageInfo( + "Day Sixteen:", + "", + "Why do I write? I", + "must... not so much", + "because there must be", + "some record of", + "this... what's", + "happened here... as" + ), + new BookPageInfo( + "for my own sanity.", + "The act of putting pen", + "to paper calms me,", + "focuses me, even in", + "this madness.", + "Lysander is dead. So", + "many are dead. And", + "we're trapped here," + ), + new BookPageInfo( + "trapped forever in", + "this nightmare. He", + "would not let us pass,", + "wild in his psychosis,", + "furious, spitting,", + "covered in blood, he", + "swung the ancient", + "dagger at any who" + ), + new BookPageInfo( + "approached. He", + "babbled incoherently,", + "cursed at us, the most", + "hateful curses,", + "prophecy, doom upon", + "us. Bergen would", + "have none of it.", + "Finally, he leapt at" + ), + new BookPageInfo( + "Lysander, his", + "massive axe at his", + "side. But he would not", + "be the end of the mad", + "mage... no... they", + "were... those hands,", + "covered in the dirt of", + "the grave, maggots," + ), + new BookPageInfo( + "filth. They rose up", + "behind Lysander.", + "That look of curiosity", + "on the mage's face as", + "Bergen skidded to a", + "halt... t'was almost a", + "moment of sanity for", + "him, surely, to" + ), + new BookPageInfo( + "attempt to comprehend", + "what could have", + "stopped the warrior in", + "his tracks. And then", + "they were upon him.", + "Skeletal hands, arms", + "and faces with loose,", + "corrupted flesh" + ), + new BookPageInfo( + "hanging from yellow", + "bone. Inhuman, yet", + "once human,", + "staggering towards us", + "as their companions", + "tore at Lysander,", + "coming towards us in", + "droves." + ) + ); + + [Constructible] + public TavarasJournal16() : base(Utility.Random(0xFF1, 2), false) + { + } + + public TavarasJournal16(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class TavarasJournal16b : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Journal: Discovery of the Tomb", + "Tavara Sewel", + new BookPageInfo( + "Day Sixteen, Later :", + "", + "We ran. What could", + "we do? We ran back", + "towards the entrance,", + "cutting at them when", + "we could. T'was a", + "nightmare, and yet" + ), + new BookPageInfo( + "nothing to prepare us", + "for what would come.", + "We were almost there,", + "the entrance to this", + "abhorred crypt in", + "sight. Then the earth", + "shook with such a", + "force that we were" + ), + new BookPageInfo( + "dropped to our hands", + "and knees, stumbling", + "in the darkness with", + "those... those things", + "surely behind us.", + "The noise of falling", + "rock and crumbling", + "stone drowned out our" + ), + new BookPageInfo( + "piteous cries. No sign", + "of the entrance", + "remained.", + "We owe our lives to", + "Bergen, whose wits", + "returned quickly.", + "That he could make us", + "hurry back into the" + ), + new BookPageInfo( + "main antechamber...", + "actually run back", + "towards those eldritch", + "dead that stalked us.", + "But we did, the", + "strength of his", + "convictions enough for", + "us in the moment." + ), + new BookPageInfo( + "And at our campsite", + "we erected our last", + "defense, a pitiable", + "wall of wood and", + "stone, anything at", + "hand that might block", + "the tide of those", + "nightmare creatures." + ), + new BookPageInfo( + "And I sit against it", + "even now. I can hear", + "their moans, their", + "wailing cries in the", + "distance - they'll be", + "here soon, even at the", + "unhurried pace of the", + "shuffling dead." + ) + ); + + [Constructible] + public TavarasJournal16b() : base(Utility.Random(0xFF1, 2), false) + { + } + + public TavarasJournal16b(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class TavarasJournal17 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Journal: Discovery of the Tomb", + "Tavara Sewel", + new BookPageInfo( + "Day Seventeen - Day", + "Eighteen :", + "", + "I cannot go on much", + "longer. I know now", + "t'was no work of the", + "earth that trapped us", + "here - I can feel His" + ), + new BookPageInfo( + "force in it. It was His", + "will, His power that", + "has sealed us here in", + "this nightmare. The", + "barricade will not be", + "enough. So many of", + "them. They come like", + "unto the ocean's waves" + ), + new BookPageInfo( + "- ceaseless,", + "neverending. For", + "every five we strike", + "down, another ten rise", + "up against us. And", + "like the sands we", + "cannot help but be", + "brought down, wasted" + ), + new BookPageInfo( + "away in this ocean of", + "blood." + ) + ); + + [Constructible] + public TavarasJournal17() : base(Utility.Random(0xFF1, 2), false) + { + } + + public TavarasJournal17(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class TavarasJournal19 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Journal: Discovery of the Tomb", + "Tavara Sewel", + new BookPageInfo( + "Day Nineteen - Day", + "Twenty-One :", + "", + "The barricade won't", + "hold - never, and", + "they'll come, they", + "come even now. I", + "would tear the last of" + ), + new BookPageInfo( + "it down, let them in to", + "devour us all, if only", + "to stop the screaming", + "- the awful, wailing", + "cries that fill the tomb", + "with their presence.", + "May my ancestors", + "forgive me, but it" + ), + new BookPageInfo( + "must be done. I must", + "end this." + ) + ); + + [Constructible] + public TavarasJournal19() : base(Utility.Random(0xFF1, 2), false) + { + } + + public TavarasJournal19(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Khaldun/KhaldunGen.cs b/Projects/UOContent/Engines/Khaldun/KhaldunGen.cs index 8370bfe64..b49ca87af 100644 --- a/Projects/UOContent/Engines/Khaldun/KhaldunGen.cs +++ b/Projects/UOContent/Engines/Khaldun/KhaldunGen.cs @@ -1,196 +1,198 @@ -using System; -using System.Linq; -using Server.Items; - -namespace Server.Commands -{ - public class GenKhaldun - { - private static int m_Count; - - public static void Initialize() - { - CommandSystem.Register("GenKhaldun", AccessLevel.Administrator, GenKhaldun_OnCommand); - } - - public static bool FindMorphItem(int x, int y, int z, int inactiveItemID, int activeItemID) - { - IPooledEnumerable eable = Map.Felucca.GetItemsInRange(new Point3D(x, y, z), 0); - - bool found = eable.Any(item => item is MorphItem morphItem && morphItem.Z == z && - morphItem.InactiveItemID == inactiveItemID && - morphItem.ActiveItemID == activeItemID); - eable.Free(); - return found; - } - - public static bool FindEffectController(int x, int y, int z) - { - IPooledEnumerable eable = Map.Felucca.GetItemsInRange(new Point3D(x, y, z), 0); - - bool found = eable.Any(item => item is EffectController && item.Z == z); - eable.Free(); - return found; - } - - public static T TryCreateItem(int x, int y, int z, T srcItem) where T : Item - { - IPooledEnumerable eable = Map.Felucca.GetItemsInBounds(new Rectangle2D(x, y, 1, 1)); - T t = eable.FirstOrDefault(item => item.GetType() == srcItem.GetType()); - eable.Free(); - if (t != null) - { - srcItem.Delete(); - return t; - } - - srcItem.MoveToWorld(new Point3D(x, y, z), Map.Felucca); - m_Count++; - - return srcItem; - } - - public static void CreateMorphItem(int x, int y, int z, int inactiveItemID, int activeItemID, int range) - { - if (FindMorphItem(x, y, z, inactiveItemID, activeItemID)) - return; - - MorphItem item = new MorphItem(inactiveItemID, activeItemID, range, 3); - - item.MoveToWorld(new Point3D(x, y, z), Map.Felucca); - m_Count++; - } - - public static void CreateApproachLight(int x, int y, int z, int off, int on, LightType light) - { - if (FindMorphItem(x, y, z, off, on)) - return; - - MorphItem item = new MorphItem(off, on, 2, 3); - item.Light = light; - - item.MoveToWorld(new Point3D(x, y, z), Map.Felucca); - m_Count++; - } - - public static void CreateSoundEffect(int x, int y, int z, int sound, int range) - { - if (FindEffectController(x, y, z)) - return; - - EffectController item = new EffectController(); - item.SoundID = sound; - item.TriggerType = EffectTriggerType.InRange; - item.TriggerRange = range; - - item.MoveToWorld(new Point3D(x, y, z), Map.Felucca); - m_Count++; - } - - public static void CreateBigTeleporterItem(int x, int y, bool reverse) - { - if (FindMorphItem(x, y, 0, reverse ? 0x17DC : 0x17EE, reverse ? 0x17EE : 0x17DC)) - return; - - MorphItem item = new MorphItem(reverse ? 0x17DC : 0x17EE, reverse ? 0x17EE : 0x17DC, 1, 3); - - item.MoveToWorld(new Point3D(x, y, 0), Map.Felucca); - m_Count++; - } - - public static void GenKhaldun_OnCommand(CommandEventArgs e) - { - m_Count = 0; - - // Generate Morph Items - CreateMorphItem(5459, 1416, 0, 0x1D0, 0x1, 1); - CreateMorphItem(5460, 1416, 0, 0x1D0, 0x1, 1); - CreateMorphItem(5459, 1416, 0, 0x1, 0x53D, 1); - CreateMorphItem(5460, 1416, 0, 0x1, 0x53B, 1); - - CreateMorphItem(5459, 1425, 0, 0x1, 0x53B, 2); - CreateMorphItem(5459, 1426, 0, 0x1, 0x53B, 2); - CreateMorphItem(5459, 1427, 0, 0x1, 0x53B, 2); - CreateMorphItem(5460, 1425, 0, 0x1, 0x53B, 2); - CreateMorphItem(5460, 1426, 0, 0x1, 0x53B, 2); - CreateMorphItem(5460, 1427, 0, 0x1, 0x53B, 2); - CreateMorphItem(5461, 1427, 0, 0x1, 0x53B, 2); - CreateMorphItem(5460, 1422, 0, 0x1, 0x544, 2); - CreateMorphItem(5460, 1419, 0, 0x1, 0x545, 2); - CreateMorphItem(5460, 1420, 0, 0x1, 0x545, 2); - CreateMorphItem(5460, 1423, 0, 0x1, 0x545, 2); - CreateMorphItem(5460, 1424, 0, 0x1, 0x545, 2); - CreateMorphItem(5461, 1426, 0, 0x1, 0x545, 2); - CreateMorphItem(5460, 1417, 0, 0x1, 0x546, 1); - CreateMorphItem(5460, 1418, 0, 0x1, 0x546, 2); - CreateMorphItem(5460, 1421, 0, 0x1, 0x546, 2); - CreateMorphItem(5461, 1425, 0, 0x1, 0x548, 2); - CreateMorphItem(5459, 1420, 0, 0x1, 0x54A, 2); - CreateMorphItem(5459, 1421, 0, 0x1, 0x54A, 2); - CreateMorphItem(5459, 1423, 0, 0x1, 0x54A, 2); - CreateMorphItem(5459, 1418, 0, 0x1, 0x54B, 2); - CreateMorphItem(5459, 1422, 0, 0x1, 0x54B, 2); - CreateMorphItem(5459, 1417, 0, 0x1, 0x54C, 1); - CreateMorphItem(5459, 1419, 0, 0x1, 0x54C, 2); - CreateMorphItem(5459, 1424, 0, 0x1, 0x54C, 2); - - CreateMorphItem(5458, 1426, 0, 0x1, 0x1D1, 2); - CreateMorphItem(5459, 1427, 0, 0x1, 0x1E3, 2); - CreateMorphItem(5458, 1425, 3, 0x1, 0x1E4, 2); - CreateMorphItem(5458, 1427, 6, 0x1, 0x1E5, 2); - CreateMorphItem(5461, 1427, 0, 0x1, 0x1E8, 2); - CreateMorphItem(5460, 1427, 0, 0x1, 0x1E9, 2); - CreateMorphItem(5458, 1425, 0, 0x1, 0x1EA, 2); - CreateMorphItem(5458, 1427, 0, 0x1, 0x1EA, 2); - CreateMorphItem(5458, 1427, 3, 0x1, 0x1EA, 2); - - // Generate Approach Lights - CreateApproachLight(5393, 1417, 0, 0x1857, 0x1858, LightType.Circle150); - CreateApproachLight(5393, 1420, 0, 0x1857, 0x1858, LightType.Circle150); - CreateApproachLight(5395, 1421, 0, 0x1857, 0x1858, LightType.Circle150); - CreateApproachLight(5396, 1417, 0, 0x1857, 0x1858, LightType.Circle150); - CreateApproachLight(5397, 1419, 0, 0x1857, 0x1858, LightType.Circle150); - - CreateApproachLight(5441, 1393, 5, 0x1F2B, 0x19BB, LightType.Circle225); - CreateApproachLight(5446, 1393, 5, 0x1F2B, 0x19BB, LightType.Circle225); - - // Generate Sound Effects - CreateSoundEffect(5425, 1489, 5, 0x102, 1); - CreateSoundEffect(5425, 1491, 5, 0x102, 1); - - CreateSoundEffect(5449, 1499, 10, 0xF5, 1); - CreateSoundEffect(5451, 1499, 10, 0xF5, 1); - CreateSoundEffect(5453, 1499, 10, 0xF5, 1); - - CreateSoundEffect(5524, 1367, 0, 0x102, 1); - - CreateSoundEffect(5450, 1370, 0, 0x220, 2); - CreateSoundEffect(5450, 1372, 0, 0x220, 2); - - CreateSoundEffect(5460, 1416, 0, 0x244, 2); - - CreateSoundEffect(5483, 1439, 5, 0x14, 3); - - // Generate Big Teleporter - CreateBigTeleporterItem(5387, 1325, true); - CreateBigTeleporterItem(5388, 1326, true); - CreateBigTeleporterItem(5388, 1325, false); - CreateBigTeleporterItem(5387, 1326, false); - - // Generate Central Khaldun entrance - DisappearingRaiseSwitch sw = - TryCreateItem(5459, 1426, 10, new DisappearingRaiseSwitch()); - RaiseSwitch lv = TryCreateItem(5403, 1359, 0, new RaiseSwitch()); - - RaisableItem stone = - TryCreateItem(5403, 1360, 0, new RaisableItem(0x788, 10, 0x477, 0x475, TimeSpan.FromMinutes(1.5))); - RaisableItem door = - TryCreateItem(5524, 1367, 0, new RaisableItem(0x1D0, 20, 0x477, 0x475, TimeSpan.FromMinutes(5.0))); - - sw.RaisableItem = stone; - lv.RaisableItem = door; - - e.Mobile.SendMessage($"{m_Count} dynamic Khaldun item{(m_Count == 1 ? "" : "s")} generated."); - } - } -} +using System; +using System.Linq; +using Server.Items; + +namespace Server.Commands +{ + public class GenKhaldun + { + private static int m_Count; + + public static void Initialize() + { + CommandSystem.Register("GenKhaldun", AccessLevel.Administrator, GenKhaldun_OnCommand); + } + + public static bool FindMorphItem(int x, int y, int z, int inactiveItemID, int activeItemID) + { + var eable = Map.Felucca.GetItemsInRange(new Point3D(x, y, z), 0); + + var found = eable.Any( + item => item is MorphItem morphItem && morphItem.Z == z && + morphItem.InactiveItemID == inactiveItemID && + morphItem.ActiveItemID == activeItemID + ); + eable.Free(); + return found; + } + + public static bool FindEffectController(int x, int y, int z) + { + var eable = Map.Felucca.GetItemsInRange(new Point3D(x, y, z), 0); + + var found = eable.Any(item => item is EffectController && item.Z == z); + eable.Free(); + return found; + } + + public static T TryCreateItem(int x, int y, int z, T srcItem) where T : Item + { + var eable = Map.Felucca.GetItemsInBounds(new Rectangle2D(x, y, 1, 1)); + var t = eable.FirstOrDefault(item => item.GetType() == srcItem.GetType()); + eable.Free(); + if (t != null) + { + srcItem.Delete(); + return t; + } + + srcItem.MoveToWorld(new Point3D(x, y, z), Map.Felucca); + m_Count++; + + return srcItem; + } + + public static void CreateMorphItem(int x, int y, int z, int inactiveItemID, int activeItemID, int range) + { + if (FindMorphItem(x, y, z, inactiveItemID, activeItemID)) + return; + + var item = new MorphItem(inactiveItemID, activeItemID, range, 3); + + item.MoveToWorld(new Point3D(x, y, z), Map.Felucca); + m_Count++; + } + + public static void CreateApproachLight(int x, int y, int z, int off, int on, LightType light) + { + if (FindMorphItem(x, y, z, off, on)) + return; + + var item = new MorphItem(off, on, 2, 3); + item.Light = light; + + item.MoveToWorld(new Point3D(x, y, z), Map.Felucca); + m_Count++; + } + + public static void CreateSoundEffect(int x, int y, int z, int sound, int range) + { + if (FindEffectController(x, y, z)) + return; + + var item = new EffectController(); + item.SoundID = sound; + item.TriggerType = EffectTriggerType.InRange; + item.TriggerRange = range; + + item.MoveToWorld(new Point3D(x, y, z), Map.Felucca); + m_Count++; + } + + public static void CreateBigTeleporterItem(int x, int y, bool reverse) + { + if (FindMorphItem(x, y, 0, reverse ? 0x17DC : 0x17EE, reverse ? 0x17EE : 0x17DC)) + return; + + var item = new MorphItem(reverse ? 0x17DC : 0x17EE, reverse ? 0x17EE : 0x17DC, 1, 3); + + item.MoveToWorld(new Point3D(x, y, 0), Map.Felucca); + m_Count++; + } + + public static void GenKhaldun_OnCommand(CommandEventArgs e) + { + m_Count = 0; + + // Generate Morph Items + CreateMorphItem(5459, 1416, 0, 0x1D0, 0x1, 1); + CreateMorphItem(5460, 1416, 0, 0x1D0, 0x1, 1); + CreateMorphItem(5459, 1416, 0, 0x1, 0x53D, 1); + CreateMorphItem(5460, 1416, 0, 0x1, 0x53B, 1); + + CreateMorphItem(5459, 1425, 0, 0x1, 0x53B, 2); + CreateMorphItem(5459, 1426, 0, 0x1, 0x53B, 2); + CreateMorphItem(5459, 1427, 0, 0x1, 0x53B, 2); + CreateMorphItem(5460, 1425, 0, 0x1, 0x53B, 2); + CreateMorphItem(5460, 1426, 0, 0x1, 0x53B, 2); + CreateMorphItem(5460, 1427, 0, 0x1, 0x53B, 2); + CreateMorphItem(5461, 1427, 0, 0x1, 0x53B, 2); + CreateMorphItem(5460, 1422, 0, 0x1, 0x544, 2); + CreateMorphItem(5460, 1419, 0, 0x1, 0x545, 2); + CreateMorphItem(5460, 1420, 0, 0x1, 0x545, 2); + CreateMorphItem(5460, 1423, 0, 0x1, 0x545, 2); + CreateMorphItem(5460, 1424, 0, 0x1, 0x545, 2); + CreateMorphItem(5461, 1426, 0, 0x1, 0x545, 2); + CreateMorphItem(5460, 1417, 0, 0x1, 0x546, 1); + CreateMorphItem(5460, 1418, 0, 0x1, 0x546, 2); + CreateMorphItem(5460, 1421, 0, 0x1, 0x546, 2); + CreateMorphItem(5461, 1425, 0, 0x1, 0x548, 2); + CreateMorphItem(5459, 1420, 0, 0x1, 0x54A, 2); + CreateMorphItem(5459, 1421, 0, 0x1, 0x54A, 2); + CreateMorphItem(5459, 1423, 0, 0x1, 0x54A, 2); + CreateMorphItem(5459, 1418, 0, 0x1, 0x54B, 2); + CreateMorphItem(5459, 1422, 0, 0x1, 0x54B, 2); + CreateMorphItem(5459, 1417, 0, 0x1, 0x54C, 1); + CreateMorphItem(5459, 1419, 0, 0x1, 0x54C, 2); + CreateMorphItem(5459, 1424, 0, 0x1, 0x54C, 2); + + CreateMorphItem(5458, 1426, 0, 0x1, 0x1D1, 2); + CreateMorphItem(5459, 1427, 0, 0x1, 0x1E3, 2); + CreateMorphItem(5458, 1425, 3, 0x1, 0x1E4, 2); + CreateMorphItem(5458, 1427, 6, 0x1, 0x1E5, 2); + CreateMorphItem(5461, 1427, 0, 0x1, 0x1E8, 2); + CreateMorphItem(5460, 1427, 0, 0x1, 0x1E9, 2); + CreateMorphItem(5458, 1425, 0, 0x1, 0x1EA, 2); + CreateMorphItem(5458, 1427, 0, 0x1, 0x1EA, 2); + CreateMorphItem(5458, 1427, 3, 0x1, 0x1EA, 2); + + // Generate Approach Lights + CreateApproachLight(5393, 1417, 0, 0x1857, 0x1858, LightType.Circle150); + CreateApproachLight(5393, 1420, 0, 0x1857, 0x1858, LightType.Circle150); + CreateApproachLight(5395, 1421, 0, 0x1857, 0x1858, LightType.Circle150); + CreateApproachLight(5396, 1417, 0, 0x1857, 0x1858, LightType.Circle150); + CreateApproachLight(5397, 1419, 0, 0x1857, 0x1858, LightType.Circle150); + + CreateApproachLight(5441, 1393, 5, 0x1F2B, 0x19BB, LightType.Circle225); + CreateApproachLight(5446, 1393, 5, 0x1F2B, 0x19BB, LightType.Circle225); + + // Generate Sound Effects + CreateSoundEffect(5425, 1489, 5, 0x102, 1); + CreateSoundEffect(5425, 1491, 5, 0x102, 1); + + CreateSoundEffect(5449, 1499, 10, 0xF5, 1); + CreateSoundEffect(5451, 1499, 10, 0xF5, 1); + CreateSoundEffect(5453, 1499, 10, 0xF5, 1); + + CreateSoundEffect(5524, 1367, 0, 0x102, 1); + + CreateSoundEffect(5450, 1370, 0, 0x220, 2); + CreateSoundEffect(5450, 1372, 0, 0x220, 2); + + CreateSoundEffect(5460, 1416, 0, 0x244, 2); + + CreateSoundEffect(5483, 1439, 5, 0x14, 3); + + // Generate Big Teleporter + CreateBigTeleporterItem(5387, 1325, true); + CreateBigTeleporterItem(5388, 1326, true); + CreateBigTeleporterItem(5388, 1325, false); + CreateBigTeleporterItem(5387, 1326, false); + + // Generate Central Khaldun entrance + var sw = + TryCreateItem(5459, 1426, 10, new DisappearingRaiseSwitch()); + var lv = TryCreateItem(5403, 1359, 0, new RaiseSwitch()); + + var stone = + TryCreateItem(5403, 1360, 0, new RaisableItem(0x788, 10, 0x477, 0x475, TimeSpan.FromMinutes(1.5))); + var door = + TryCreateItem(5524, 1367, 0, new RaisableItem(0x1D0, 20, 0x477, 0x475, TimeSpan.FromMinutes(5.0))); + + sw.RaisableItem = stone; + lv.RaisableItem = door; + + e.Mobile.SendMessage($"{m_Count} dynamic Khaldun item{(m_Count == 1 ? "" : "s")} generated."); + } + } +} diff --git a/Projects/UOContent/Engines/Khaldun/KhaldunPitTeleporter.cs b/Projects/UOContent/Engines/Khaldun/KhaldunPitTeleporter.cs index 98c1d0f96..7dc130e43 100644 --- a/Projects/UOContent/Engines/Khaldun/KhaldunPitTeleporter.cs +++ b/Projects/UOContent/Engines/Khaldun/KhaldunPitTeleporter.cs @@ -1,93 +1,93 @@ -using Server.Mobiles; - -namespace Server.Items -{ - public class KhaldunPitTeleporter : Item - { - [Constructible] - public KhaldunPitTeleporter() : this(new Point3D(5451, 1374, 0), Map.Felucca) - { - } - - [Constructible] - public KhaldunPitTeleporter(Point3D pointDest, Map mapDest) : base(0x053B) - { - Movable = false; - Hue = 1; - - Active = true; - PointDest = pointDest; - MapDest = mapDest; - } - - public KhaldunPitTeleporter(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Active { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D PointDest { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Map MapDest { get; set; } - - public override int LabelNumber => - 1016511; // the floor of the cavern seems to have collapsed here - a faint light is visible at the bottom of the pit - - public override void OnDoubleClick(Mobile m) - { - if (!Active) - return; - - Map map = MapDest; - - if (map == null || map == Map.Internal) - map = m.Map; - - Point3D p = PointDest; - - if (p == Point3D.Zero) - p = m.Location; - - if (m.InRange(this, 3)) - { - BaseCreature.TeleportPets(m, PointDest, MapDest); - - m.MoveToWorld(PointDest, MapDest); - } - else - { - m.SendLocalizedMessage(1019045); // I can't reach that. - } - } - - public override void OnDoubleClickDead(Mobile m) - { - OnDoubleClick(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(Active); - writer.Write(PointDest); - writer.Write(MapDest); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Active = reader.ReadBool(); - PointDest = reader.ReadPoint3D(); - MapDest = reader.ReadMap(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Items +{ + public class KhaldunPitTeleporter : Item + { + [Constructible] + public KhaldunPitTeleporter() : this(new Point3D(5451, 1374, 0), Map.Felucca) + { + } + + [Constructible] + public KhaldunPitTeleporter(Point3D pointDest, Map mapDest) : base(0x053B) + { + Movable = false; + Hue = 1; + + Active = true; + PointDest = pointDest; + MapDest = mapDest; + } + + public KhaldunPitTeleporter(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Active { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D PointDest { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Map MapDest { get; set; } + + public override int LabelNumber => + 1016511; // the floor of the cavern seems to have collapsed here - a faint light is visible at the bottom of the pit + + public override void OnDoubleClick(Mobile m) + { + if (!Active) + return; + + var map = MapDest; + + if (map == null || map == Map.Internal) + map = m.Map; + + var p = PointDest; + + if (p == Point3D.Zero) + p = m.Location; + + if (m.InRange(this, 3)) + { + BaseCreature.TeleportPets(m, PointDest, MapDest); + + m.MoveToWorld(PointDest, MapDest); + } + else + { + m.SendLocalizedMessage(1019045); // I can't reach that. + } + } + + public override void OnDoubleClickDead(Mobile m) + { + OnDoubleClick(m); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(Active); + writer.Write(PointDest); + writer.Write(MapDest); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + Active = reader.ReadBool(); + PointDest = reader.ReadPoint3D(); + MapDest = reader.ReadMap(); + } + } +} diff --git a/Projects/UOContent/Engines/Khaldun/Mobiles/GrimmochDrummel.cs b/Projects/UOContent/Engines/Khaldun/Mobiles/GrimmochDrummel.cs index bcfa4fec0..b442e0fd4 100644 --- a/Projects/UOContent/Engines/Khaldun/Mobiles/GrimmochDrummel.cs +++ b/Projects/UOContent/Engines/Khaldun/Mobiles/GrimmochDrummel.cs @@ -1,118 +1,118 @@ -using Server.Items; - -namespace Server.Mobiles -{ - public class GrimmochDrummel : BaseCreature - { - [Constructible] - public GrimmochDrummel() : base(AIType.AI_Archer, FightMode.Closest, 10, 1, 0.2, 0.4) - { - Title = "the Cursed"; - - Hue = 0x8596; - Body = 0x190; - - HairItemID = 0x204A; // Krisna - - Bow bow = new Bow(); - bow.Movable = false; - AddItem(bow); - - AddItem(new Boots(0x8A4)); - AddItem(new BodySash(0x8A4)); - - Backpack backpack = new Backpack(); - backpack.Movable = false; - AddItem(backpack); - - LeatherGloves gloves = new LeatherGloves(); - LeatherChest chest = new LeatherChest(); - gloves.Hue = 0x96F; - chest.Hue = 0x96F; - - AddItem(gloves); - AddItem(chest); - - SetStr(111, 120); - SetDex(151, 160); - SetInt(41, 50); - - SetHits(180, 207); - SetMana(0); - - SetDamage(13, 16); - - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 25, 30); - SetResistance(ResistanceType.Cold, 45, 55); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 20, 25); - - SetSkill(SkillName.Archery, 90.1, 110.0); - SetSkill(SkillName.Swords, 60.1, 70.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 60.1, 70.0); - SetSkill(SkillName.Anatomy, 90.1, 100.0); - - Fame = 5000; - Karma = -1000; - - PackItem(new Arrow(40)); - - if (Utility.Random(100) < 3) - PackItem(new FireHorn()); - - if (Utility.Random(3) < 1) - PackItem(Loot.RandomGrimmochJournal()); - } - - public GrimmochDrummel(Serial serial) : base(serial) - { - } - - public override bool ClickTitle => false; - public override bool ShowFameTitle => false; - public override bool DeleteCorpseOnDeath => true; - public override string DefaultName => "Grimmoch Drummel"; - - public override bool AlwaysMurderer => true; - - public override int GetIdleSound() => 0x178; - - public override int GetAngerSound() => 0x1AC; - - public override int GetDeathSound() => 0x27E; - - public override int GetHurtSound() => 0x177; - - public override bool OnBeforeDeath() - { - Gold gold = new Gold(Utility.RandomMinMax(190, 230)); - gold.MoveToWorld(Location, Map); - - Container pack = Backpack; - if (pack != null) - { - pack.Movable = true; - pack.MoveToWorld(Location, Map); - } - - Effects.SendLocationEffect(Location, Map, 0x376A, 10, 1); - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; + +namespace Server.Mobiles +{ + public class GrimmochDrummel : BaseCreature + { + [Constructible] + public GrimmochDrummel() : base(AIType.AI_Archer, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Title = "the Cursed"; + + Hue = 0x8596; + Body = 0x190; + + HairItemID = 0x204A; // Krisna + + var bow = new Bow(); + bow.Movable = false; + AddItem(bow); + + AddItem(new Boots(0x8A4)); + AddItem(new BodySash(0x8A4)); + + var backpack = new Backpack(); + backpack.Movable = false; + AddItem(backpack); + + var gloves = new LeatherGloves(); + var chest = new LeatherChest(); + gloves.Hue = 0x96F; + chest.Hue = 0x96F; + + AddItem(gloves); + AddItem(chest); + + SetStr(111, 120); + SetDex(151, 160); + SetInt(41, 50); + + SetHits(180, 207); + SetMana(0); + + SetDamage(13, 16); + + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 25, 30); + SetResistance(ResistanceType.Cold, 45, 55); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 20, 25); + + SetSkill(SkillName.Archery, 90.1, 110.0); + SetSkill(SkillName.Swords, 60.1, 70.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 60.1, 70.0); + SetSkill(SkillName.Anatomy, 90.1, 100.0); + + Fame = 5000; + Karma = -1000; + + PackItem(new Arrow(40)); + + if (Utility.Random(100) < 3) + PackItem(new FireHorn()); + + if (Utility.Random(3) < 1) + PackItem(Loot.RandomGrimmochJournal()); + } + + public GrimmochDrummel(Serial serial) : base(serial) + { + } + + public override bool ClickTitle => false; + public override bool ShowFameTitle => false; + public override bool DeleteCorpseOnDeath => true; + public override string DefaultName => "Grimmoch Drummel"; + + public override bool AlwaysMurderer => true; + + public override int GetIdleSound() => 0x178; + + public override int GetAngerSound() => 0x1AC; + + public override int GetDeathSound() => 0x27E; + + public override int GetHurtSound() => 0x177; + + public override bool OnBeforeDeath() + { + var gold = new Gold(Utility.RandomMinMax(190, 230)); + gold.MoveToWorld(Location, Map); + + var pack = Backpack; + if (pack != null) + { + pack.Movable = true; + pack.MoveToWorld(Location, Map); + } + + Effects.SendLocationEffect(Location, Map, 0x376A, 10, 1); + return true; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Khaldun/Mobiles/LysanderGathenwale.cs b/Projects/UOContent/Engines/Khaldun/Mobiles/LysanderGathenwale.cs index 14dcebfc1..5d56335b5 100644 --- a/Projects/UOContent/Engines/Khaldun/Mobiles/LysanderGathenwale.cs +++ b/Projects/UOContent/Engines/Khaldun/Mobiles/LysanderGathenwale.cs @@ -1,118 +1,118 @@ -using Server.Items; - -namespace Server.Mobiles -{ - public class LysanderGathenwale : BaseCreature - { - [Constructible] - public LysanderGathenwale() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) - { - Title = "the Cursed"; - - Hue = 0x8838; - Body = 0x190; - - AddItem(new Boots(0x599)); - AddItem(new Cloak(0x96F)); - - Spellbook spellbook = new Spellbook(); - RingmailGloves gloves = new RingmailGloves(); - StuddedChest chest = new StuddedChest(); - PlateArms arms = new PlateArms(); - - spellbook.Hue = 0x599; - gloves.Hue = 0x599; - chest.Hue = 0x96F; - arms.Hue = 0x599; - - AddItem(spellbook); - AddItem(gloves); - AddItem(chest); - AddItem(arms); - - SetStr(111, 120); - SetDex(71, 80); - SetInt(121, 130); - - SetHits(180, 207); - SetMana(227, 265); - - SetDamage(5, 13); - - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 25, 30); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 25, 35); - SetResistance(ResistanceType.Energy, 25, 35); - - SetSkill(SkillName.Wrestling, 80.1, 90.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 80.1, 90.0); - SetSkill(SkillName.Magery, 90.1, 100.0); - SetSkill(SkillName.EvalInt, 95.1, 100.0); - SetSkill(SkillName.Meditation, 90.1, 100.0); - - Fame = 5000; - Karma = -10000; - - Item reags = Loot.RandomReagent(); - reags.Amount = 30; - PackItem(reags); - } - - public LysanderGathenwale(Serial serial) : base(serial) - { - } - - public override bool ClickTitle => false; - public override bool ShowFameTitle => false; - public override bool DeleteCorpseOnDeath => true; - public override string DefaultName => "Lysander Gatherwale"; - - public override bool AlwaysMurderer => true; - - public override int GetIdleSound() => 0x1CE; - - public override int GetAngerSound() => 0x1AC; - - public override int GetDeathSound() => 0x182; - - public override int GetHurtSound() => 0x28D; - - public override void GenerateLoot() - { - AddLoot(LootPack.MedScrolls, 2); - } - - public override bool OnBeforeDeath() - { - if (!base.OnBeforeDeath()) - return false; - - Backpack?.Destroy(); - - if (Utility.Random(3) == 0) - { - BaseBook notebook = Loot.RandomLysanderNotebook(); - notebook.MoveToWorld(Location, Map); - } - - Effects.SendLocationEffect(Location, Map, 0x376A, 10, 1); - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; + +namespace Server.Mobiles +{ + public class LysanderGathenwale : BaseCreature + { + [Constructible] + public LysanderGathenwale() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Title = "the Cursed"; + + Hue = 0x8838; + Body = 0x190; + + AddItem(new Boots(0x599)); + AddItem(new Cloak(0x96F)); + + var spellbook = new Spellbook(); + var gloves = new RingmailGloves(); + var chest = new StuddedChest(); + var arms = new PlateArms(); + + spellbook.Hue = 0x599; + gloves.Hue = 0x599; + chest.Hue = 0x96F; + arms.Hue = 0x599; + + AddItem(spellbook); + AddItem(gloves); + AddItem(chest); + AddItem(arms); + + SetStr(111, 120); + SetDex(71, 80); + SetInt(121, 130); + + SetHits(180, 207); + SetMana(227, 265); + + SetDamage(5, 13); + + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 25, 30); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 25, 35); + SetResistance(ResistanceType.Energy, 25, 35); + + SetSkill(SkillName.Wrestling, 80.1, 90.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 80.1, 90.0); + SetSkill(SkillName.Magery, 90.1, 100.0); + SetSkill(SkillName.EvalInt, 95.1, 100.0); + SetSkill(SkillName.Meditation, 90.1, 100.0); + + Fame = 5000; + Karma = -10000; + + var reags = Loot.RandomReagent(); + reags.Amount = 30; + PackItem(reags); + } + + public LysanderGathenwale(Serial serial) : base(serial) + { + } + + public override bool ClickTitle => false; + public override bool ShowFameTitle => false; + public override bool DeleteCorpseOnDeath => true; + public override string DefaultName => "Lysander Gatherwale"; + + public override bool AlwaysMurderer => true; + + public override int GetIdleSound() => 0x1CE; + + public override int GetAngerSound() => 0x1AC; + + public override int GetDeathSound() => 0x182; + + public override int GetHurtSound() => 0x28D; + + public override void GenerateLoot() + { + AddLoot(LootPack.MedScrolls, 2); + } + + public override bool OnBeforeDeath() + { + if (!base.OnBeforeDeath()) + return false; + + Backpack?.Destroy(); + + if (Utility.Random(3) == 0) + { + var notebook = Loot.RandomLysanderNotebook(); + notebook.MoveToWorld(Location, Map); + } + + Effects.SendLocationEffect(Location, Map, 0x376A, 10, 1); + return true; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Khaldun/Mobiles/MorgBergen.cs b/Projects/UOContent/Engines/Khaldun/Mobiles/MorgBergen.cs index 438931ab6..6c6bf8f46 100644 --- a/Projects/UOContent/Engines/Khaldun/Mobiles/MorgBergen.cs +++ b/Projects/UOContent/Engines/Khaldun/Mobiles/MorgBergen.cs @@ -1,98 +1,98 @@ -using Server.Items; - -namespace Server.Mobiles -{ - public class MorgBergen : BaseCreature - { - [Constructible] - public MorgBergen() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) - { - Title = "the Cursed"; - - Hue = 0x8596; - Body = 0x190; - - AddItem(new ShortPants(0x59C)); - - Bardiche bardiche = new Bardiche(); - LeatherGloves gloves = new LeatherGloves(); - LeatherArms arms = new LeatherArms(); - - bardiche.Hue = 0x96F; - bardiche.Movable = false; - gloves.Hue = 0x96F; - arms.Hue = 0x96F; - - AddItem(bardiche); - AddItem(gloves); - AddItem(arms); - - SetStr(111, 120); - SetDex(111, 120); - SetInt(51, 60); - - SetHits(180, 207); - SetMana(0); - - SetDamage(9, 17); - - SetDamageType(ResistanceType.Physical, 40); - SetDamageType(ResistanceType.Cold, 60); - - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 25, 30); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 25, 35); - SetResistance(ResistanceType.Energy, 25, 35); - - SetSkill(SkillName.Swords, 90.1, 100.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 80.1, 90.0); - SetSkill(SkillName.Anatomy, 90.1, 100.0); - - Fame = 5000; - Karma = -1000; - } - - public MorgBergen(Serial serial) : base(serial) - { - } - - public override bool ShowFameTitle => false; - public override bool DeleteCorpseOnDeath => true; - public override string DefaultName => "Morg Bergen"; - - public override bool AlwaysMurderer => true; - - public override int GetIdleSound() => 0x1CE; - - public override int GetAngerSound() => 0x263; - - public override int GetDeathSound() => 0x1D1; - - public override int GetHurtSound() => 0x25E; - - public override bool OnBeforeDeath() - { - Gold gold = new Gold(Utility.RandomMinMax(190, 230)); - gold.MoveToWorld(Location, Map); - - Effects.SendLocationEffect(Location, Map, 0x376A, 10, 1); - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; + +namespace Server.Mobiles +{ + public class MorgBergen : BaseCreature + { + [Constructible] + public MorgBergen() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Title = "the Cursed"; + + Hue = 0x8596; + Body = 0x190; + + AddItem(new ShortPants(0x59C)); + + var bardiche = new Bardiche(); + var gloves = new LeatherGloves(); + var arms = new LeatherArms(); + + bardiche.Hue = 0x96F; + bardiche.Movable = false; + gloves.Hue = 0x96F; + arms.Hue = 0x96F; + + AddItem(bardiche); + AddItem(gloves); + AddItem(arms); + + SetStr(111, 120); + SetDex(111, 120); + SetInt(51, 60); + + SetHits(180, 207); + SetMana(0); + + SetDamage(9, 17); + + SetDamageType(ResistanceType.Physical, 40); + SetDamageType(ResistanceType.Cold, 60); + + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 25, 30); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 25, 35); + SetResistance(ResistanceType.Energy, 25, 35); + + SetSkill(SkillName.Swords, 90.1, 100.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 80.1, 90.0); + SetSkill(SkillName.Anatomy, 90.1, 100.0); + + Fame = 5000; + Karma = -1000; + } + + public MorgBergen(Serial serial) : base(serial) + { + } + + public override bool ShowFameTitle => false; + public override bool DeleteCorpseOnDeath => true; + public override string DefaultName => "Morg Bergen"; + + public override bool AlwaysMurderer => true; + + public override int GetIdleSound() => 0x1CE; + + public override int GetAngerSound() => 0x263; + + public override int GetDeathSound() => 0x1D1; + + public override int GetHurtSound() => 0x25E; + + public override bool OnBeforeDeath() + { + var gold = new Gold(Utility.RandomMinMax(190, 230)); + gold.MoveToWorld(Location, Map); + + Effects.SendLocationEffect(Location, Map, 0x376A, 10, 1); + return true; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Khaldun/Mobiles/TavaraSewel.cs b/Projects/UOContent/Engines/Khaldun/Mobiles/TavaraSewel.cs index 3bdf419af..c568c64f8 100644 --- a/Projects/UOContent/Engines/Khaldun/Mobiles/TavaraSewel.cs +++ b/Projects/UOContent/Engines/Khaldun/Mobiles/TavaraSewel.cs @@ -1,108 +1,108 @@ -using Server.Items; - -namespace Server.Mobiles -{ - public class TavaraSewel : BaseCreature - { - [Constructible] - public TavaraSewel() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) - { - Title = "the Cursed"; - - Hue = 0x8838; - Female = true; - Body = 0x191; - - AddItem(new Kilt(0x59C)); - AddItem(new Sandals(0x599)); - - Kryss kryss = new Kryss(); - Buckler buckler = new Buckler(); - RingmailGloves gloves = new RingmailGloves(); - FemalePlateChest chest = new FemalePlateChest(); - - kryss.Hue = 0x96F; - kryss.Movable = false; - buckler.Hue = 0x96F; - buckler.Movable = false; - gloves.Hue = 0x599; - chest.Hue = 0x96F; - - AddItem(kryss); - AddItem(buckler); - AddItem(gloves); - AddItem(chest); - - SetStr(111, 120); - SetDex(111, 120); - SetInt(111, 120); - - SetHits(180, 207); - SetStam(126, 150); - SetMana(0); - - SetDamage(13, 16); - - SetResistance(ResistanceType.Physical, 25, 30); - SetResistance(ResistanceType.Fire, 25, 30); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 25, 35); - SetResistance(ResistanceType.Energy, 25, 35); - - SetSkill(SkillName.Fencing, 90.1, 100.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 80.1, 90.0); - SetSkill(SkillName.Anatomy, 90.1, 100.0); - - Fame = 5000; - Karma = -1000; - } - - public TavaraSewel(Serial serial) : base(serial) - { - } - - public override bool ShowFameTitle => false; - public override bool DeleteCorpseOnDeath => true; - public override string DefaultName => "Tavara Sewel"; - - public override bool AlwaysMurderer => true; - - public override int GetIdleSound() => 0x27F; - - public override int GetAngerSound() => 0x258; - - public override int GetDeathSound() => 0x25B; - - public override int GetHurtSound() => 0x257; - - public override bool OnBeforeDeath() - { - Gold gold = new Gold(Utility.RandomMinMax(190, 230)); - gold.MoveToWorld(Location, Map); - - if (Utility.Random(3) == 0) - { - BaseBook journal = Loot.RandomTavarasJournal(); - journal.MoveToWorld(Location, Map); - } - - Effects.SendLocationEffect(Location, Map, 0x376A, 10, 1); - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; + +namespace Server.Mobiles +{ + public class TavaraSewel : BaseCreature + { + [Constructible] + public TavaraSewel() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Title = "the Cursed"; + + Hue = 0x8838; + Female = true; + Body = 0x191; + + AddItem(new Kilt(0x59C)); + AddItem(new Sandals(0x599)); + + var kryss = new Kryss(); + var buckler = new Buckler(); + var gloves = new RingmailGloves(); + var chest = new FemalePlateChest(); + + kryss.Hue = 0x96F; + kryss.Movable = false; + buckler.Hue = 0x96F; + buckler.Movable = false; + gloves.Hue = 0x599; + chest.Hue = 0x96F; + + AddItem(kryss); + AddItem(buckler); + AddItem(gloves); + AddItem(chest); + + SetStr(111, 120); + SetDex(111, 120); + SetInt(111, 120); + + SetHits(180, 207); + SetStam(126, 150); + SetMana(0); + + SetDamage(13, 16); + + SetResistance(ResistanceType.Physical, 25, 30); + SetResistance(ResistanceType.Fire, 25, 30); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 25, 35); + SetResistance(ResistanceType.Energy, 25, 35); + + SetSkill(SkillName.Fencing, 90.1, 100.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 80.1, 90.0); + SetSkill(SkillName.Anatomy, 90.1, 100.0); + + Fame = 5000; + Karma = -1000; + } + + public TavaraSewel(Serial serial) : base(serial) + { + } + + public override bool ShowFameTitle => false; + public override bool DeleteCorpseOnDeath => true; + public override string DefaultName => "Tavara Sewel"; + + public override bool AlwaysMurderer => true; + + public override int GetIdleSound() => 0x27F; + + public override int GetAngerSound() => 0x258; + + public override int GetDeathSound() => 0x25B; + + public override int GetHurtSound() => 0x257; + + public override bool OnBeforeDeath() + { + var gold = new Gold(Utility.RandomMinMax(190, 230)); + gold.MoveToWorld(Location, Map); + + if (Utility.Random(3) == 0) + { + var journal = Loot.RandomTavarasJournal(); + journal.MoveToWorld(Location, Map); + } + + Effects.SendLocationEffect(Location, Map, 0x376A, 10, 1); + return true; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Khaldun/PuzzleChest.cs b/Projects/UOContent/Engines/Khaldun/PuzzleChest.cs index 808eec029..553e57d4b 100644 --- a/Projects/UOContent/Engines/Khaldun/PuzzleChest.cs +++ b/Projects/UOContent/Engines/Khaldun/PuzzleChest.cs @@ -1,805 +1,815 @@ -using System; -using System.Collections.Generic; -using Server.Gumps; -using Server.Network; - -namespace Server.Items -{ - public enum PuzzleChestCylinder - { - None = 0xE73, - LightBlue = 0x186F, - Blue = 0x186A, - Green = 0x186B, - Orange = 0x186C, - Purple = 0x186D, - Red = 0x186E, - DarkBlue = 0x1869, - Yellow = 0x1870 - } - - public class PuzzleChestSolution - { - public const int Length = 5; - - public PuzzleChestSolution() - { - for (int i = 0; i < Cylinders.Length; i++) Cylinders[i] = RandomCylinder(); - } - - public PuzzleChestSolution(PuzzleChestCylinder first, PuzzleChestCylinder second, PuzzleChestCylinder third, - PuzzleChestCylinder fourth, PuzzleChestCylinder fifth) - { - First = first; - Second = second; - Third = third; - Fourth = fourth; - Fifth = fifth; - } - - public PuzzleChestSolution(PuzzleChestSolution solution) - { - for (int i = 0; i < Cylinders.Length; i++) Cylinders[i] = solution.Cylinders[i]; - } - - public PuzzleChestSolution(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - int length = reader.ReadEncodedInt(); - for (int i = 0; ; i++) - if (i < length) - { - PuzzleChestCylinder cylinder = (PuzzleChestCylinder)reader.ReadInt(); - - if (i < Cylinders.Length) - Cylinders[i] = cylinder; - } - else if (i < Cylinders.Length) - { - Cylinders[i] = RandomCylinder(); - } - else - { - break; - } - } - - public PuzzleChestCylinder[] Cylinders { get; } = new PuzzleChestCylinder[Length]; - - public PuzzleChestCylinder First - { - get => Cylinders[0]; - set => Cylinders[0] = value; - } - - public PuzzleChestCylinder Second - { - get => Cylinders[1]; - set => Cylinders[1] = value; - } - - public PuzzleChestCylinder Third - { - get => Cylinders[2]; - set => Cylinders[2] = value; - } - - public PuzzleChestCylinder Fourth - { - get => Cylinders[3]; - set => Cylinders[3] = value; - } - - public PuzzleChestCylinder Fifth - { - get => Cylinders[4]; - set => Cylinders[4] = value; - } - - public static PuzzleChestCylinder RandomCylinder() - { - return Utility.Random(8) switch - { - 0 => PuzzleChestCylinder.LightBlue, - 1 => PuzzleChestCylinder.Blue, - 2 => PuzzleChestCylinder.Green, - 3 => PuzzleChestCylinder.Orange, - 4 => PuzzleChestCylinder.Purple, - 5 => PuzzleChestCylinder.Red, - 6 => PuzzleChestCylinder.DarkBlue, - _ => PuzzleChestCylinder.Yellow - }; - } - - public bool Matches(PuzzleChestSolution solution, out int cylinders, out int colors) - { - cylinders = 0; - colors = 0; - - bool[] matchesSrc = new bool[solution.Cylinders.Length]; - bool[] matchesDst = new bool[solution.Cylinders.Length]; - - for (int i = 0; i < Cylinders.Length; i++) - if (Cylinders[i] == solution.Cylinders[i]) - { - cylinders++; - - matchesSrc[i] = true; - matchesDst[i] = true; - } - - for (int i = 0; i < Cylinders.Length; i++) - if (!matchesSrc[i]) - for (int j = 0; j < solution.Cylinders.Length; j++) - if (Cylinders[i] == solution.Cylinders[j] && !matchesDst[j]) - { - colors++; - - matchesDst[j] = true; - } - - return cylinders == Cylinders.Length; - } - - public virtual void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.WriteEncodedInt(Cylinders.Length); - for (int i = 0; i < Cylinders.Length; i++) writer.Write((int)Cylinders[i]); - } - } - - public class PuzzleChestSolutionAndTime : PuzzleChestSolution - { - public PuzzleChestSolutionAndTime(DateTime when, PuzzleChestSolution solution) : base(solution) => When = when; - - public PuzzleChestSolutionAndTime(IGenericReader reader) : base(reader) - { - int version = reader.ReadEncodedInt(); - - When = reader.ReadDeltaTime(); - } - - public DateTime When { get; } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.WriteDeltaTime(When); - } - } - - public abstract class PuzzleChest : BaseTreasureChest - { - public const int HintsCount = 3; - public readonly TimeSpan CleanupTime = TimeSpan.FromHours(1.0); - - private readonly Dictionary m_Guesses = - new Dictionary(); - - private PuzzleChestSolution m_Solution; - - public PuzzleChest(int itemID) : base(itemID) - { - } - - public PuzzleChest(Serial serial) : base(serial) - { - } - - public PuzzleChestSolution Solution - { - get => m_Solution; - set - { - m_Solution = value; - InitHints(); - } - } - - public PuzzleChestCylinder[] Hints { get; private set; } = new PuzzleChestCylinder[HintsCount]; - - public PuzzleChestCylinder FirstHint - { - get => Hints[0]; - set => Hints[0] = value; - } - - public PuzzleChestCylinder SecondHint - { - get => Hints[1]; - set => Hints[1] = value; - } - - public PuzzleChestCylinder ThirdHint - { - get => Hints[2]; - set => Hints[2] = value; - } - - public override string DefaultName => null; - - private void InitHints() - { - List list = new List(Solution.Cylinders.Length - 1); - for (int i = 1; i < Solution.Cylinders.Length; i++) - list.Add(Solution.Cylinders[i]); - - Hints = new PuzzleChestCylinder[HintsCount]; - - for (int i = 0; i < Hints.Length; i++) - { - var random = list.RandomElement(); - Hints[i] = random; - list.Remove(random); - } - } - - protected override void SetLockLevel() - { - LockLevel = 0; // Can't be unlocked - } - - public override bool CheckLocked(Mobile from) - { - if (Locked) - { - PuzzleChestSolution solution = GetLastGuess(from); - if (solution != null) - solution = new PuzzleChestSolution(solution); - else - solution = new PuzzleChestSolution(PuzzleChestCylinder.None, PuzzleChestCylinder.None, - PuzzleChestCylinder.None, PuzzleChestCylinder.None, PuzzleChestCylinder.None); - - from.CloseGump(); - from.CloseGump(); - from.SendGump(new PuzzleGump(from, this, solution, 0)); - - return true; - } - - return false; - } - - public PuzzleChestSolutionAndTime GetLastGuess(Mobile m) - { - m_Guesses.TryGetValue(m, out PuzzleChestSolutionAndTime pcst); - return pcst; - } - - public void SubmitSolution(Mobile m, PuzzleChestSolution solution) - { - if (solution.Matches(Solution, out int correctCylinders, out int correctColors)) - { - LockPick(m); - - DisplayTo(m); - } - else - { - m_Guesses[m] = new PuzzleChestSolutionAndTime(DateTime.UtcNow, solution); - - m.SendGump(new StatusGump(correctCylinders, correctColors)); - - DoDamage(m); - } - } - - public void DoDamage(Mobile to) - { - switch (Utility.Random(4)) - { - case 0: - { - Effects.SendLocationEffect(to, to.Map, 0x113A, 20, 10); - to.PlaySound(0x231); - to.LocalOverheadMessage(MessageType.Regular, 0x44, 1010523); // A toxic vapor envelops thee. - - to.ApplyPoison(to, Poison.Regular); - - break; - } - case 1: - { - Effects.SendLocationEffect(to, to.Map, 0x3709, 30); - to.PlaySound(0x54); - to.LocalOverheadMessage(MessageType.Regular, 0xEE, 1010524); // Searing heat scorches thy skin. - - AOS.Damage(to, to, Utility.RandomMinMax(10, 40), 0, 100, 0, 0, 0); - - break; - } - case 2: - { - to.PlaySound(0x223); - to.LocalOverheadMessage(MessageType.Regular, 0x62, - 1010525); // Pain lances through thee from a sharp metal blade. - - AOS.Damage(to, to, Utility.RandomMinMax(10, 40), 100, 0, 0, 0, 0); - - break; - } - default: - { - to.BoltEffect(0); - to.LocalOverheadMessage(MessageType.Regular, 0xDA, 1010526); // Lightning arcs through thy body. - - AOS.Damage(to, to, Utility.RandomMinMax(10, 40), 0, 0, 0, 0, 100); - - break; - } - } - } - - public override void LockPick(Mobile from) - { - base.LockPick(from); - - m_Guesses.Clear(); - } - - private static void GetRandomAOSStats(out int attributeCount, out int min, out int max) - { - int rnd = Utility.Random(15); - - if (rnd < 1) - { - attributeCount = Utility.RandomMinMax(2, 6); - min = 20; - max = 70; - } - else if (rnd < 3) - { - attributeCount = Utility.RandomMinMax(2, 4); - min = 20; - max = 50; - } - else if (rnd < 6) - { - attributeCount = Utility.RandomMinMax(2, 3); - min = 20; - max = 40; - } - else if (rnd < 10) - { - attributeCount = Utility.RandomMinMax(1, 2); - min = 10; - max = 30; - } - else - { - attributeCount = 1; - min = 10; - max = 20; - } - } - - protected override void GenerateTreasure() - { - DropItem(new Gold(600, 900)); - - List gems = new List(); - for (int i = 0; i < 9; i++) - { - Item gem = Loot.RandomGem(); - Type gemType = gem.GetType(); - - foreach (Item listGem in gems) - if (listGem.GetType() == gemType) - { - listGem.Amount++; - gem.Delete(); - break; - } - - if (!gem.Deleted) - gems.Add(gem); - } - - foreach (Item gem in gems) - DropItem(gem); - - if (Utility.RandomDouble() < 0.2) - DropItem(new BagOfReagents()); - - for (int i = 0; i < 2; i++) - { - Item item; - - if (Core.AOS) - item = Loot.RandomArmorOrShieldOrWeaponOrJewelry(); - else - item = Loot.RandomArmorOrShieldOrWeapon(); - - if (item is BaseWeapon weapon) - { - if (Core.AOS) - { - GetRandomAOSStats(out int attributeCount, out int min, out int max); - - BaseRunicTool.ApplyAttributesTo(weapon, attributeCount, min, max); - } - else - { - weapon.DamageLevel = (WeaponDamageLevel)Utility.Random(6); - weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random(6); - weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random(6); - } - - DropItem(weapon); - } - else if (item is BaseArmor armor) - { - if (Core.AOS) - { - GetRandomAOSStats(out int attributeCount, out int min, out int max); - - BaseRunicTool.ApplyAttributesTo(armor, attributeCount, min, max); - } - else - { - armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(6); - armor.Durability = (ArmorDurabilityLevel)Utility.Random(6); - } - - DropItem(armor); - } - else if (item is BaseHat hat) - { - if (Core.AOS) - { - GetRandomAOSStats(out int attributeCount, out int min, out int max); - - BaseRunicTool.ApplyAttributesTo(hat, attributeCount, min, max); - } - - DropItem(hat); - } - else if (item is BaseJewel jewel) - { - GetRandomAOSStats(out int attributeCount, out int min, out int max); - - BaseRunicTool.ApplyAttributesTo(jewel, attributeCount, min, max); - - DropItem(jewel); - } - } - - Solution = new PuzzleChestSolution(); - } - - public void CleanupGuesses() - { - List toDelete = new List(); - - foreach (KeyValuePair kvp in m_Guesses) - if (DateTime.UtcNow - kvp.Value.When > CleanupTime) - toDelete.Add(kvp.Key); - - foreach (Mobile m in toDelete) - m_Guesses.Remove(m); - } - - public override void Serialize(IGenericWriter writer) - { - CleanupGuesses(); - - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - m_Solution.Serialize(writer); - - writer.WriteEncodedInt(Hints.Length); - for (int i = 0; i < Hints.Length; i++) writer.Write((int)Hints[i]); - - writer.WriteEncodedInt(m_Guesses.Count); - foreach (KeyValuePair kvp in m_Guesses) - { - writer.Write(kvp.Key); - kvp.Value.Serialize(writer); - } - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_Solution = new PuzzleChestSolution(reader); - - int length = reader.ReadEncodedInt(); - for (int i = 0; i < length; i++) - { - PuzzleChestCylinder cylinder = (PuzzleChestCylinder)reader.ReadInt(); - - if (length == Hints.Length) - Hints[i] = cylinder; - } - - if (length != Hints.Length) - InitHints(); - - int guesses = reader.ReadEncodedInt(); - for (int i = 0; i < guesses; i++) - { - Mobile m = reader.ReadMobile(); - PuzzleChestSolutionAndTime sol = new PuzzleChestSolutionAndTime(reader); - - m_Guesses[m] = sol; - } - } - - private class PuzzleGump : Gump - { - private readonly PuzzleChest m_Chest; - private readonly Mobile m_From; - private readonly PuzzleChestSolution m_Solution; - - public PuzzleGump(Mobile from, PuzzleChest chest, PuzzleChestSolution solution, int check) : base(50, 50) - { - m_From = from; - m_Chest = chest; - m_Solution = solution; - - Draggable = false; - - AddBackground(25, 0, 500, 410, 0x53); - - AddImage(62, 20, 0x67); - - AddHtmlLocalized(80, 36, 110, 70, 1018309, true); // A Puzzle Lock - - /* Correctly choose the sequence of cylinders needed to open the latch. Each cylinder - * may potentially be used more than once. Beware! A false attempt could be deadly! - */ - AddHtmlLocalized(214, 26, 270, 90, 1018310, true, true); - - AddLeftCylinderButton(62, 130, PuzzleChestCylinder.LightBlue, 10); - AddLeftCylinderButton(62, 180, PuzzleChestCylinder.Blue, 11); - AddLeftCylinderButton(62, 230, PuzzleChestCylinder.Green, 12); - AddLeftCylinderButton(62, 280, PuzzleChestCylinder.Orange, 13); - - AddRightCylinderButton(451, 130, PuzzleChestCylinder.Purple, 14); - AddRightCylinderButton(451, 180, PuzzleChestCylinder.Red, 15); - AddRightCylinderButton(451, 230, PuzzleChestCylinder.DarkBlue, 16); - AddRightCylinderButton(451, 280, PuzzleChestCylinder.Yellow, 17); - - double lockpicking = from.Skills.Lockpicking.Base; - if (lockpicking >= 60.0) - { - AddHtmlLocalized(160, 125, 230, 24, 1018308); // Lockpicking hint: - - AddBackground(159, 150, 230, 95, 0x13EC); - - if (lockpicking >= 80.0) - { - AddHtmlLocalized(165, 157, 200, 40, 1018312); // In the first slot: - AddCylinder(350, 165, chest.Solution.First); - - AddHtmlLocalized(165, 197, 200, 40, 1018313); // Used in unknown slot: - AddCylinder(350, 200, chest.FirstHint); - - if (lockpicking >= 90.0) - AddCylinder(350, 212, chest.SecondHint); - - if (lockpicking >= 100.0) - AddCylinder(350, 224, chest.ThirdHint); - } - else - { - AddHtmlLocalized(165, 157, 200, 40, 1018313); // Used in unknown slot: - AddCylinder(350, 160, chest.FirstHint); - - if (lockpicking >= 70.0) - AddCylinder(350, 172, chest.SecondHint); - } - } - - PuzzleChestSolution lastGuess = chest.GetLastGuess(from); - if (lastGuess != null) - { - AddHtmlLocalized(127, 249, 170, 20, 1018311); // Thy previous guess: - - AddBackground(290, 247, 115, 25, 0x13EC); - - AddCylinder(281, 254, lastGuess.First); - AddCylinder(303, 254, lastGuess.Second); - AddCylinder(325, 254, lastGuess.Third); - AddCylinder(347, 254, lastGuess.Fourth); - AddCylinder(369, 254, lastGuess.Fifth); - } - - AddPedestal(140, 270, solution.First, 0, check == 0); - AddPedestal(195, 270, solution.Second, 1, check == 1); - AddPedestal(250, 270, solution.Third, 2, check == 2); - AddPedestal(305, 270, solution.Fourth, 3, check == 3); - AddPedestal(360, 270, solution.Fifth, 4, check == 4); - - AddButton(258, 370, 0xFA5, 0xFA7, 1); - } - - private void AddLeftCylinderButton(int x, int y, PuzzleChestCylinder cylinder, int buttonID) - { - AddBackground(x, y, 30, 30, 0x13EC); - AddCylinder(x - 7, y + 10, cylinder); - AddButton(x + 38, y + 9, 0x13A8, 0x4B9, buttonID); - } - - private void AddRightCylinderButton(int x, int y, PuzzleChestCylinder cylinder, int buttonID) - { - AddBackground(x, y, 30, 30, 0x13EC); - AddCylinder(x - 7, y + 10, cylinder); - AddButton(x - 26, y + 9, 0x13A8, 0x4B9, buttonID); - } - - private void AddPedestal(int x, int y, PuzzleChestCylinder cylinder, int switchID, bool initialState) - { - AddItem(x, y, 0xB10); - AddItem(x - 23, y + 12, 0xB12); - AddItem(x + 23, y + 12, 0xB13); - AddItem(x, y + 23, 0xB11); - - if (cylinder != PuzzleChestCylinder.None) - { - AddItem(x, y + 2, 0x51A); - AddCylinder(x - 1, y + 19, cylinder); - } - else - { - AddItem(x, y + 2, 0x521); - } - - AddRadio(x + 7, y + 65, 0x867, 0x86A, initialState, switchID); - } - - private void AddCylinder(int x, int y, PuzzleChestCylinder cylinder) - { - if (cylinder != PuzzleChestCylinder.None) - AddItem(x, y, (int)cylinder); - else - AddItem(x + 9, y, (int)cylinder); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Chest.Deleted || info.ButtonID == 0 || !m_From.CheckAlive()) - return; - - if (m_From.AccessLevel == AccessLevel.Player && - (m_From.Map != m_Chest.Map || !m_From.InRange(m_Chest.GetWorldLocation(), 2))) - { - m_From.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500446); // That is too far away. - return; - } - - if (info.ButtonID == 1) - { - m_Chest.SubmitSolution(m_From, m_Solution); - } - else - { - if (info.Switches.Length == 0) - return; - - int pedestal = info.Switches[0]; - if (pedestal < 0 || pedestal >= m_Solution.Cylinders.Length) - return; - - PuzzleChestCylinder cylinder; - switch (info.ButtonID) - { - case 10: - cylinder = PuzzleChestCylinder.LightBlue; - break; - case 11: - cylinder = PuzzleChestCylinder.Blue; - break; - case 12: - cylinder = PuzzleChestCylinder.Green; - break; - case 13: - cylinder = PuzzleChestCylinder.Orange; - break; - case 14: - cylinder = PuzzleChestCylinder.Purple; - break; - case 15: - cylinder = PuzzleChestCylinder.Red; - break; - case 16: - cylinder = PuzzleChestCylinder.DarkBlue; - break; - case 17: - cylinder = PuzzleChestCylinder.Yellow; - break; - default: return; - } - - m_Solution.Cylinders[pedestal] = cylinder; - - m_From.SendGump(new PuzzleGump(m_From, m_Chest, m_Solution, pedestal)); - } - } - } - - private class StatusGump : Gump - { - public StatusGump(int correctCylinders, int correctColors) : base(50, 50) - { - AddBackground(15, 250, 305, 163, 0x53); - AddBackground(28, 265, 280, 133, 0xBB8); - - AddHtmlLocalized(35, 271, 270, 24, 1018314); // Thou hast failed to solve the puzzle! - - AddHtmlLocalized(35, 297, 250, 24, 1018315); // Correctly placed colors: - AddLabel(285, 297, 0x44, correctCylinders.ToString()); - - AddHtmlLocalized(35, 323, 250, 24, 1018316); // Used colors in wrong slots: - AddLabel(285, 323, 0x44, correctColors.ToString()); - - AddButton(152, 369, 0xFA5, 0xFA7, 0); - } - } - } - - [Flippable(0xE41, 0xE40)] - public class MetalGoldenPuzzleChest : PuzzleChest - { - [Constructible] - public MetalGoldenPuzzleChest() : base(0xE41) - { - } - - public MetalGoldenPuzzleChest(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - [Flippable(0xE80, 0x9A8)] - public class StrongBoxPuzzle : PuzzleChest - { - [Constructible] - public StrongBoxPuzzle() : base(0xE80) - { - } - - public StrongBoxPuzzle(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} +using System; +using System.Collections.Generic; +using Server.Gumps; +using Server.Network; + +namespace Server.Items +{ + public enum PuzzleChestCylinder + { + None = 0xE73, + LightBlue = 0x186F, + Blue = 0x186A, + Green = 0x186B, + Orange = 0x186C, + Purple = 0x186D, + Red = 0x186E, + DarkBlue = 0x1869, + Yellow = 0x1870 + } + + public class PuzzleChestSolution + { + public const int Length = 5; + + public PuzzleChestSolution() + { + for (var i = 0; i < Cylinders.Length; i++) Cylinders[i] = RandomCylinder(); + } + + public PuzzleChestSolution( + PuzzleChestCylinder first, PuzzleChestCylinder second, PuzzleChestCylinder third, + PuzzleChestCylinder fourth, PuzzleChestCylinder fifth + ) + { + First = first; + Second = second; + Third = third; + Fourth = fourth; + Fifth = fifth; + } + + public PuzzleChestSolution(PuzzleChestSolution solution) + { + for (var i = 0; i < Cylinders.Length; i++) Cylinders[i] = solution.Cylinders[i]; + } + + public PuzzleChestSolution(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + var length = reader.ReadEncodedInt(); + for (var i = 0;; i++) + if (i < length) + { + var cylinder = (PuzzleChestCylinder)reader.ReadInt(); + + if (i < Cylinders.Length) + Cylinders[i] = cylinder; + } + else if (i < Cylinders.Length) + { + Cylinders[i] = RandomCylinder(); + } + else + { + break; + } + } + + public PuzzleChestCylinder[] Cylinders { get; } = new PuzzleChestCylinder[Length]; + + public PuzzleChestCylinder First + { + get => Cylinders[0]; + set => Cylinders[0] = value; + } + + public PuzzleChestCylinder Second + { + get => Cylinders[1]; + set => Cylinders[1] = value; + } + + public PuzzleChestCylinder Third + { + get => Cylinders[2]; + set => Cylinders[2] = value; + } + + public PuzzleChestCylinder Fourth + { + get => Cylinders[3]; + set => Cylinders[3] = value; + } + + public PuzzleChestCylinder Fifth + { + get => Cylinders[4]; + set => Cylinders[4] = value; + } + + public static PuzzleChestCylinder RandomCylinder() + { + return Utility.Random(8) switch + { + 0 => PuzzleChestCylinder.LightBlue, + 1 => PuzzleChestCylinder.Blue, + 2 => PuzzleChestCylinder.Green, + 3 => PuzzleChestCylinder.Orange, + 4 => PuzzleChestCylinder.Purple, + 5 => PuzzleChestCylinder.Red, + 6 => PuzzleChestCylinder.DarkBlue, + _ => PuzzleChestCylinder.Yellow + }; + } + + public bool Matches(PuzzleChestSolution solution, out int cylinders, out int colors) + { + cylinders = 0; + colors = 0; + + var matchesSrc = new bool[solution.Cylinders.Length]; + var matchesDst = new bool[solution.Cylinders.Length]; + + for (var i = 0; i < Cylinders.Length; i++) + if (Cylinders[i] == solution.Cylinders[i]) + { + cylinders++; + + matchesSrc[i] = true; + matchesDst[i] = true; + } + + for (var i = 0; i < Cylinders.Length; i++) + if (!matchesSrc[i]) + for (var j = 0; j < solution.Cylinders.Length; j++) + if (Cylinders[i] == solution.Cylinders[j] && !matchesDst[j]) + { + colors++; + + matchesDst[j] = true; + } + + return cylinders == Cylinders.Length; + } + + public virtual void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.WriteEncodedInt(Cylinders.Length); + for (var i = 0; i < Cylinders.Length; i++) writer.Write((int)Cylinders[i]); + } + } + + public class PuzzleChestSolutionAndTime : PuzzleChestSolution + { + public PuzzleChestSolutionAndTime(DateTime when, PuzzleChestSolution solution) : base(solution) => When = when; + + public PuzzleChestSolutionAndTime(IGenericReader reader) : base(reader) + { + var version = reader.ReadEncodedInt(); + + When = reader.ReadDeltaTime(); + } + + public DateTime When { get; } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.WriteDeltaTime(When); + } + } + + public abstract class PuzzleChest : BaseTreasureChest + { + public const int HintsCount = 3; + public readonly TimeSpan CleanupTime = TimeSpan.FromHours(1.0); + + private readonly Dictionary m_Guesses = + new Dictionary(); + + private PuzzleChestSolution m_Solution; + + public PuzzleChest(int itemID) : base(itemID) + { + } + + public PuzzleChest(Serial serial) : base(serial) + { + } + + public PuzzleChestSolution Solution + { + get => m_Solution; + set + { + m_Solution = value; + InitHints(); + } + } + + public PuzzleChestCylinder[] Hints { get; private set; } = new PuzzleChestCylinder[HintsCount]; + + public PuzzleChestCylinder FirstHint + { + get => Hints[0]; + set => Hints[0] = value; + } + + public PuzzleChestCylinder SecondHint + { + get => Hints[1]; + set => Hints[1] = value; + } + + public PuzzleChestCylinder ThirdHint + { + get => Hints[2]; + set => Hints[2] = value; + } + + public override string DefaultName => null; + + private void InitHints() + { + var list = new List(Solution.Cylinders.Length - 1); + for (var i = 1; i < Solution.Cylinders.Length; i++) + list.Add(Solution.Cylinders[i]); + + Hints = new PuzzleChestCylinder[HintsCount]; + + for (var i = 0; i < Hints.Length; i++) + { + var random = list.RandomElement(); + Hints[i] = random; + list.Remove(random); + } + } + + protected override void SetLockLevel() + { + LockLevel = 0; // Can't be unlocked + } + + public override bool CheckLocked(Mobile from) + { + if (Locked) + { + PuzzleChestSolution solution = GetLastGuess(from); + if (solution != null) + solution = new PuzzleChestSolution(solution); + else + solution = new PuzzleChestSolution( + PuzzleChestCylinder.None, + PuzzleChestCylinder.None, + PuzzleChestCylinder.None, + PuzzleChestCylinder.None, + PuzzleChestCylinder.None + ); + + from.CloseGump(); + from.CloseGump(); + from.SendGump(new PuzzleGump(from, this, solution, 0)); + + return true; + } + + return false; + } + + public PuzzleChestSolutionAndTime GetLastGuess(Mobile m) + { + m_Guesses.TryGetValue(m, out var pcst); + return pcst; + } + + public void SubmitSolution(Mobile m, PuzzleChestSolution solution) + { + if (solution.Matches(Solution, out var correctCylinders, out var correctColors)) + { + LockPick(m); + + DisplayTo(m); + } + else + { + m_Guesses[m] = new PuzzleChestSolutionAndTime(DateTime.UtcNow, solution); + + m.SendGump(new StatusGump(correctCylinders, correctColors)); + + DoDamage(m); + } + } + + public void DoDamage(Mobile to) + { + switch (Utility.Random(4)) + { + case 0: + { + Effects.SendLocationEffect(to, to.Map, 0x113A, 20, 10); + to.PlaySound(0x231); + to.LocalOverheadMessage(MessageType.Regular, 0x44, 1010523); // A toxic vapor envelops thee. + + to.ApplyPoison(to, Poison.Regular); + + break; + } + case 1: + { + Effects.SendLocationEffect(to, to.Map, 0x3709, 30); + to.PlaySound(0x54); + to.LocalOverheadMessage(MessageType.Regular, 0xEE, 1010524); // Searing heat scorches thy skin. + + AOS.Damage(to, to, Utility.RandomMinMax(10, 40), 0, 100, 0, 0, 0); + + break; + } + case 2: + { + to.PlaySound(0x223); + to.LocalOverheadMessage( + MessageType.Regular, + 0x62, + 1010525 + ); // Pain lances through thee from a sharp metal blade. + + AOS.Damage(to, to, Utility.RandomMinMax(10, 40), 100, 0, 0, 0, 0); + + break; + } + default: + { + to.BoltEffect(0); + to.LocalOverheadMessage(MessageType.Regular, 0xDA, 1010526); // Lightning arcs through thy body. + + AOS.Damage(to, to, Utility.RandomMinMax(10, 40), 0, 0, 0, 0, 100); + + break; + } + } + } + + public override void LockPick(Mobile from) + { + base.LockPick(from); + + m_Guesses.Clear(); + } + + private static void GetRandomAOSStats(out int attributeCount, out int min, out int max) + { + var rnd = Utility.Random(15); + + if (rnd < 1) + { + attributeCount = Utility.RandomMinMax(2, 6); + min = 20; + max = 70; + } + else if (rnd < 3) + { + attributeCount = Utility.RandomMinMax(2, 4); + min = 20; + max = 50; + } + else if (rnd < 6) + { + attributeCount = Utility.RandomMinMax(2, 3); + min = 20; + max = 40; + } + else if (rnd < 10) + { + attributeCount = Utility.RandomMinMax(1, 2); + min = 10; + max = 30; + } + else + { + attributeCount = 1; + min = 10; + max = 20; + } + } + + protected override void GenerateTreasure() + { + DropItem(new Gold(600, 900)); + + var gems = new List(); + for (var i = 0; i < 9; i++) + { + var gem = Loot.RandomGem(); + var gemType = gem.GetType(); + + foreach (var listGem in gems) + if (listGem.GetType() == gemType) + { + listGem.Amount++; + gem.Delete(); + break; + } + + if (!gem.Deleted) + gems.Add(gem); + } + + foreach (var gem in gems) + DropItem(gem); + + if (Utility.RandomDouble() < 0.2) + DropItem(new BagOfReagents()); + + for (var i = 0; i < 2; i++) + { + Item item; + + if (Core.AOS) + item = Loot.RandomArmorOrShieldOrWeaponOrJewelry(); + else + item = Loot.RandomArmorOrShieldOrWeapon(); + + if (item is BaseWeapon weapon) + { + if (Core.AOS) + { + GetRandomAOSStats(out var attributeCount, out var min, out var max); + + BaseRunicTool.ApplyAttributesTo(weapon, attributeCount, min, max); + } + else + { + weapon.DamageLevel = (WeaponDamageLevel)Utility.Random(6); + weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random(6); + weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random(6); + } + + DropItem(weapon); + } + else if (item is BaseArmor armor) + { + if (Core.AOS) + { + GetRandomAOSStats(out var attributeCount, out var min, out var max); + + BaseRunicTool.ApplyAttributesTo(armor, attributeCount, min, max); + } + else + { + armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(6); + armor.Durability = (ArmorDurabilityLevel)Utility.Random(6); + } + + DropItem(armor); + } + else if (item is BaseHat hat) + { + if (Core.AOS) + { + GetRandomAOSStats(out var attributeCount, out var min, out var max); + + BaseRunicTool.ApplyAttributesTo(hat, attributeCount, min, max); + } + + DropItem(hat); + } + else if (item is BaseJewel jewel) + { + GetRandomAOSStats(out var attributeCount, out var min, out var max); + + BaseRunicTool.ApplyAttributesTo(jewel, attributeCount, min, max); + + DropItem(jewel); + } + } + + Solution = new PuzzleChestSolution(); + } + + public void CleanupGuesses() + { + var toDelete = new List(); + + foreach (var kvp in m_Guesses) + if (DateTime.UtcNow - kvp.Value.When > CleanupTime) + toDelete.Add(kvp.Key); + + foreach (var m in toDelete) + m_Guesses.Remove(m); + } + + public override void Serialize(IGenericWriter writer) + { + CleanupGuesses(); + + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + m_Solution.Serialize(writer); + + writer.WriteEncodedInt(Hints.Length); + for (var i = 0; i < Hints.Length; i++) writer.Write((int)Hints[i]); + + writer.WriteEncodedInt(m_Guesses.Count); + foreach (var kvp in m_Guesses) + { + writer.Write(kvp.Key); + kvp.Value.Serialize(writer); + } + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_Solution = new PuzzleChestSolution(reader); + + var length = reader.ReadEncodedInt(); + for (var i = 0; i < length; i++) + { + var cylinder = (PuzzleChestCylinder)reader.ReadInt(); + + if (length == Hints.Length) + Hints[i] = cylinder; + } + + if (length != Hints.Length) + InitHints(); + + var guesses = reader.ReadEncodedInt(); + for (var i = 0; i < guesses; i++) + { + var m = reader.ReadMobile(); + var sol = new PuzzleChestSolutionAndTime(reader); + + m_Guesses[m] = sol; + } + } + + private class PuzzleGump : Gump + { + private readonly PuzzleChest m_Chest; + private readonly Mobile m_From; + private readonly PuzzleChestSolution m_Solution; + + public PuzzleGump(Mobile from, PuzzleChest chest, PuzzleChestSolution solution, int check) : base(50, 50) + { + m_From = from; + m_Chest = chest; + m_Solution = solution; + + Draggable = false; + + AddBackground(25, 0, 500, 410, 0x53); + + AddImage(62, 20, 0x67); + + AddHtmlLocalized(80, 36, 110, 70, 1018309, true); // A Puzzle Lock + + /* Correctly choose the sequence of cylinders needed to open the latch. Each cylinder + * may potentially be used more than once. Beware! A false attempt could be deadly! + */ + AddHtmlLocalized(214, 26, 270, 90, 1018310, true, true); + + AddLeftCylinderButton(62, 130, PuzzleChestCylinder.LightBlue, 10); + AddLeftCylinderButton(62, 180, PuzzleChestCylinder.Blue, 11); + AddLeftCylinderButton(62, 230, PuzzleChestCylinder.Green, 12); + AddLeftCylinderButton(62, 280, PuzzleChestCylinder.Orange, 13); + + AddRightCylinderButton(451, 130, PuzzleChestCylinder.Purple, 14); + AddRightCylinderButton(451, 180, PuzzleChestCylinder.Red, 15); + AddRightCylinderButton(451, 230, PuzzleChestCylinder.DarkBlue, 16); + AddRightCylinderButton(451, 280, PuzzleChestCylinder.Yellow, 17); + + var lockpicking = from.Skills.Lockpicking.Base; + if (lockpicking >= 60.0) + { + AddHtmlLocalized(160, 125, 230, 24, 1018308); // Lockpicking hint: + + AddBackground(159, 150, 230, 95, 0x13EC); + + if (lockpicking >= 80.0) + { + AddHtmlLocalized(165, 157, 200, 40, 1018312); // In the first slot: + AddCylinder(350, 165, chest.Solution.First); + + AddHtmlLocalized(165, 197, 200, 40, 1018313); // Used in unknown slot: + AddCylinder(350, 200, chest.FirstHint); + + if (lockpicking >= 90.0) + AddCylinder(350, 212, chest.SecondHint); + + if (lockpicking >= 100.0) + AddCylinder(350, 224, chest.ThirdHint); + } + else + { + AddHtmlLocalized(165, 157, 200, 40, 1018313); // Used in unknown slot: + AddCylinder(350, 160, chest.FirstHint); + + if (lockpicking >= 70.0) + AddCylinder(350, 172, chest.SecondHint); + } + } + + PuzzleChestSolution lastGuess = chest.GetLastGuess(from); + if (lastGuess != null) + { + AddHtmlLocalized(127, 249, 170, 20, 1018311); // Thy previous guess: + + AddBackground(290, 247, 115, 25, 0x13EC); + + AddCylinder(281, 254, lastGuess.First); + AddCylinder(303, 254, lastGuess.Second); + AddCylinder(325, 254, lastGuess.Third); + AddCylinder(347, 254, lastGuess.Fourth); + AddCylinder(369, 254, lastGuess.Fifth); + } + + AddPedestal(140, 270, solution.First, 0, check == 0); + AddPedestal(195, 270, solution.Second, 1, check == 1); + AddPedestal(250, 270, solution.Third, 2, check == 2); + AddPedestal(305, 270, solution.Fourth, 3, check == 3); + AddPedestal(360, 270, solution.Fifth, 4, check == 4); + + AddButton(258, 370, 0xFA5, 0xFA7, 1); + } + + private void AddLeftCylinderButton(int x, int y, PuzzleChestCylinder cylinder, int buttonID) + { + AddBackground(x, y, 30, 30, 0x13EC); + AddCylinder(x - 7, y + 10, cylinder); + AddButton(x + 38, y + 9, 0x13A8, 0x4B9, buttonID); + } + + private void AddRightCylinderButton(int x, int y, PuzzleChestCylinder cylinder, int buttonID) + { + AddBackground(x, y, 30, 30, 0x13EC); + AddCylinder(x - 7, y + 10, cylinder); + AddButton(x - 26, y + 9, 0x13A8, 0x4B9, buttonID); + } + + private void AddPedestal(int x, int y, PuzzleChestCylinder cylinder, int switchID, bool initialState) + { + AddItem(x, y, 0xB10); + AddItem(x - 23, y + 12, 0xB12); + AddItem(x + 23, y + 12, 0xB13); + AddItem(x, y + 23, 0xB11); + + if (cylinder != PuzzleChestCylinder.None) + { + AddItem(x, y + 2, 0x51A); + AddCylinder(x - 1, y + 19, cylinder); + } + else + { + AddItem(x, y + 2, 0x521); + } + + AddRadio(x + 7, y + 65, 0x867, 0x86A, initialState, switchID); + } + + private void AddCylinder(int x, int y, PuzzleChestCylinder cylinder) + { + if (cylinder != PuzzleChestCylinder.None) + AddItem(x, y, (int)cylinder); + else + AddItem(x + 9, y, (int)cylinder); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Chest.Deleted || info.ButtonID == 0 || !m_From.CheckAlive()) + return; + + if (m_From.AccessLevel == AccessLevel.Player && + (m_From.Map != m_Chest.Map || !m_From.InRange(m_Chest.GetWorldLocation(), 2))) + { + m_From.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500446); // That is too far away. + return; + } + + if (info.ButtonID == 1) + { + m_Chest.SubmitSolution(m_From, m_Solution); + } + else + { + if (info.Switches.Length == 0) + return; + + var pedestal = info.Switches[0]; + if (pedestal < 0 || pedestal >= m_Solution.Cylinders.Length) + return; + + PuzzleChestCylinder cylinder; + switch (info.ButtonID) + { + case 10: + cylinder = PuzzleChestCylinder.LightBlue; + break; + case 11: + cylinder = PuzzleChestCylinder.Blue; + break; + case 12: + cylinder = PuzzleChestCylinder.Green; + break; + case 13: + cylinder = PuzzleChestCylinder.Orange; + break; + case 14: + cylinder = PuzzleChestCylinder.Purple; + break; + case 15: + cylinder = PuzzleChestCylinder.Red; + break; + case 16: + cylinder = PuzzleChestCylinder.DarkBlue; + break; + case 17: + cylinder = PuzzleChestCylinder.Yellow; + break; + default: return; + } + + m_Solution.Cylinders[pedestal] = cylinder; + + m_From.SendGump(new PuzzleGump(m_From, m_Chest, m_Solution, pedestal)); + } + } + } + + private class StatusGump : Gump + { + public StatusGump(int correctCylinders, int correctColors) : base(50, 50) + { + AddBackground(15, 250, 305, 163, 0x53); + AddBackground(28, 265, 280, 133, 0xBB8); + + AddHtmlLocalized(35, 271, 270, 24, 1018314); // Thou hast failed to solve the puzzle! + + AddHtmlLocalized(35, 297, 250, 24, 1018315); // Correctly placed colors: + AddLabel(285, 297, 0x44, correctCylinders.ToString()); + + AddHtmlLocalized(35, 323, 250, 24, 1018316); // Used colors in wrong slots: + AddLabel(285, 323, 0x44, correctColors.ToString()); + + AddButton(152, 369, 0xFA5, 0xFA7, 0); + } + } + } + + [Flippable(0xE41, 0xE40)] + public class MetalGoldenPuzzleChest : PuzzleChest + { + [Constructible] + public MetalGoldenPuzzleChest() : base(0xE41) + { + } + + public MetalGoldenPuzzleChest(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0xE80, 0x9A8)] + public class StrongBoxPuzzle : PuzzleChest + { + [Constructible] + public StrongBoxPuzzle() : base(0xE80) + { + } + + public StrongBoxPuzzle(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Khaldun/RaisableItem.cs b/Projects/UOContent/Engines/Khaldun/RaisableItem.cs index 8ec46d3bb..72ab86502 100644 --- a/Projects/UOContent/Engines/Khaldun/RaisableItem.cs +++ b/Projects/UOContent/Engines/Khaldun/RaisableItem.cs @@ -1,170 +1,175 @@ -using System; - -namespace Server.Items -{ - public class RaisableItem : Item - { - private int m_Elevation; - private int m_MaxElevation; - private RaiseTimer m_RaiseTimer; - - [Constructible] - public RaisableItem(int itemID) : this(itemID, 20, -1, -1, TimeSpan.FromMinutes(1.0)) - { - } - - [Constructible] - public RaisableItem(int itemID, int maxElevation, TimeSpan closeDelay) : this(itemID, maxElevation, -1, -1, - closeDelay) - { - } - - [Constructible] - public RaisableItem(int itemID, int maxElevation, int moveSound, int stopSound, TimeSpan closeDelay) : base(itemID) - { - Movable = false; - - m_MaxElevation = maxElevation; - MoveSound = moveSound; - StopSound = stopSound; - CloseDelay = closeDelay; - } - - public RaisableItem(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxElevation - { - get => m_MaxElevation; - set - { - if (value <= 0) - m_MaxElevation = 0; - else if (value >= 60) - m_MaxElevation = 60; - else - m_MaxElevation = value; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int MoveSound { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int StopSound { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan CloseDelay { get; set; } - - public bool IsRaisable => m_RaiseTimer == null; - - public void Raise() - { - if (!IsRaisable) - return; - - m_RaiseTimer = new RaiseTimer(this); - m_RaiseTimer.Start(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.WriteEncodedInt(m_MaxElevation); - writer.WriteEncodedInt(MoveSound); - writer.WriteEncodedInt(StopSound); - writer.Write(CloseDelay); - - writer.WriteEncodedInt(m_Elevation); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_MaxElevation = reader.ReadEncodedInt(); - MoveSound = reader.ReadEncodedInt(); - StopSound = reader.ReadEncodedInt(); - CloseDelay = reader.ReadTimeSpan(); - - int elevation = reader.ReadEncodedInt(); - Z -= elevation; - } - - private class RaiseTimer : Timer - { - private readonly DateTime m_CloseTime; - private readonly RaisableItem m_Item; - private int m_Step; - private bool m_Up; - - public RaiseTimer(RaisableItem item) : base(TimeSpan.Zero, TimeSpan.FromSeconds(0.5)) - { - m_Item = item; - m_CloseTime = DateTime.UtcNow + item.CloseDelay; - m_Up = true; - - Priority = TimerPriority.TenMS; - } - - protected override void OnTick() - { - if (m_Item.Deleted) - { - Stop(); - return; - } - - if (m_Step++ % 3 == 0) - { - if (m_Up) - { - m_Item.Z++; - - if (++m_Item.m_Elevation >= m_Item.MaxElevation) - { - Stop(); - - if (m_Item.StopSound >= 0) - Effects.PlaySound(m_Item.Location, m_Item.Map, m_Item.StopSound); - - m_Up = false; - m_Step = 0; - - TimeSpan delay = m_CloseTime - DateTime.UtcNow; - DelayCall(delay > TimeSpan.Zero ? delay : TimeSpan.Zero, Start); - - return; - } - } - else - { - m_Item.Z--; - - if (--m_Item.m_Elevation <= 0) - { - Stop(); - - if (m_Item.StopSound >= 0) - Effects.PlaySound(m_Item.Location, m_Item.Map, m_Item.StopSound); - - m_Item.m_RaiseTimer = null; - - return; - } - } - } - - if (m_Item.MoveSound >= 0) - Effects.PlaySound(m_Item.Location, m_Item.Map, m_Item.MoveSound); - } - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class RaisableItem : Item + { + private int m_Elevation; + private int m_MaxElevation; + private RaiseTimer m_RaiseTimer; + + [Constructible] + public RaisableItem(int itemID) : this(itemID, 20, -1, -1, TimeSpan.FromMinutes(1.0)) + { + } + + [Constructible] + public RaisableItem(int itemID, int maxElevation, TimeSpan closeDelay) : this( + itemID, + maxElevation, + -1, + -1, + closeDelay + ) + { + } + + [Constructible] + public RaisableItem(int itemID, int maxElevation, int moveSound, int stopSound, TimeSpan closeDelay) : base(itemID) + { + Movable = false; + + m_MaxElevation = maxElevation; + MoveSound = moveSound; + StopSound = stopSound; + CloseDelay = closeDelay; + } + + public RaisableItem(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxElevation + { + get => m_MaxElevation; + set + { + if (value <= 0) + m_MaxElevation = 0; + else if (value >= 60) + m_MaxElevation = 60; + else + m_MaxElevation = value; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int MoveSound { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int StopSound { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan CloseDelay { get; set; } + + public bool IsRaisable => m_RaiseTimer == null; + + public void Raise() + { + if (!IsRaisable) + return; + + m_RaiseTimer = new RaiseTimer(this); + m_RaiseTimer.Start(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.WriteEncodedInt(m_MaxElevation); + writer.WriteEncodedInt(MoveSound); + writer.WriteEncodedInt(StopSound); + writer.Write(CloseDelay); + + writer.WriteEncodedInt(m_Elevation); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_MaxElevation = reader.ReadEncodedInt(); + MoveSound = reader.ReadEncodedInt(); + StopSound = reader.ReadEncodedInt(); + CloseDelay = reader.ReadTimeSpan(); + + var elevation = reader.ReadEncodedInt(); + Z -= elevation; + } + + private class RaiseTimer : Timer + { + private readonly DateTime m_CloseTime; + private readonly RaisableItem m_Item; + private int m_Step; + private bool m_Up; + + public RaiseTimer(RaisableItem item) : base(TimeSpan.Zero, TimeSpan.FromSeconds(0.5)) + { + m_Item = item; + m_CloseTime = DateTime.UtcNow + item.CloseDelay; + m_Up = true; + + Priority = TimerPriority.TenMS; + } + + protected override void OnTick() + { + if (m_Item.Deleted) + { + Stop(); + return; + } + + if (m_Step++ % 3 == 0) + { + if (m_Up) + { + m_Item.Z++; + + if (++m_Item.m_Elevation >= m_Item.MaxElevation) + { + Stop(); + + if (m_Item.StopSound >= 0) + Effects.PlaySound(m_Item.Location, m_Item.Map, m_Item.StopSound); + + m_Up = false; + m_Step = 0; + + var delay = m_CloseTime - DateTime.UtcNow; + DelayCall(delay > TimeSpan.Zero ? delay : TimeSpan.Zero, Start); + + return; + } + } + else + { + m_Item.Z--; + + if (--m_Item.m_Elevation <= 0) + { + Stop(); + + if (m_Item.StopSound >= 0) + Effects.PlaySound(m_Item.Location, m_Item.Map, m_Item.StopSound); + + m_Item.m_RaiseTimer = null; + + return; + } + } + } + + if (m_Item.MoveSound >= 0) + Effects.PlaySound(m_Item.Location, m_Item.Map, m_Item.MoveSound); + } + } + } +} diff --git a/Projects/UOContent/Engines/Khaldun/RaiseSwitch.cs b/Projects/UOContent/Engines/Khaldun/RaiseSwitch.cs index cb623fd7b..d4b9aab14 100644 --- a/Projects/UOContent/Engines/Khaldun/RaiseSwitch.cs +++ b/Projects/UOContent/Engines/Khaldun/RaiseSwitch.cs @@ -1,199 +1,209 @@ -using System; -using System.Linq; -using Server.Network; - -namespace Server.Items -{ - public class RaiseSwitch : Item - { - private ResetTimer m_ResetTimer; - - [Constructible] - public RaiseSwitch(int itemID = 0x1093) : base(itemID) => Movable = false; - - public RaiseSwitch(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public RaisableItem RaisableItem { get; set; } - - public override void OnDoubleClick(Mobile m) - { - if (!m.InRange(this, 2)) - { - m.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return; - } - - if (RaisableItem?.Deleted == true) - RaisableItem = null; - - Flip(); - - if (RaisableItem == null) - return; - - if (RaisableItem.IsRaisable) - { - RaisableItem.Raise(); - m.LocalOverheadMessage(MessageType.Regular, 0x5A, true, - "You hear a grinding noise echoing in the distance."); - } - else - { - m.LocalOverheadMessage(MessageType.Regular, 0x5A, true, - "You flip the switch again, but nothing happens."); - } - } - - protected virtual void Flip() - { - if (ItemID != 0x1093) - { - ItemID = 0x1093; - - StopResetTimer(); - } - else - { - ItemID = 0x1095; - - StartResetTimer(RaisableItem?.CloseDelay >= TimeSpan.Zero ? RaisableItem.CloseDelay : TimeSpan.FromMinutes(2.0)); - } - - Effects.PlaySound(Location, Map, 0x3E8); - } - - protected void StartResetTimer(TimeSpan delay) - { - StopResetTimer(); - - m_ResetTimer = new ResetTimer(this, delay); - m_ResetTimer.Start(); - } - - protected void StopResetTimer() - { - if (m_ResetTimer != null) - { - m_ResetTimer.Stop(); - m_ResetTimer = null; - } - } - - protected virtual void Reset() - { - if (ItemID != 0x1093) - Flip(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(RaisableItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - RaisableItem = (RaisableItem)reader.ReadItem(); - - Reset(); - } - - private class ResetTimer : Timer - { - private readonly RaiseSwitch m_RaiseSwitch; - - public ResetTimer(RaiseSwitch raiseSwitch, TimeSpan delay) : base(delay) - { - m_RaiseSwitch = raiseSwitch; - - Priority = ComputePriority(delay); - } - - protected override void OnTick() - { - if (m_RaiseSwitch.Deleted) - return; - - m_RaiseSwitch.m_ResetTimer = null; - - m_RaiseSwitch.Reset(); - } - } - } - - public class DisappearingRaiseSwitch : RaiseSwitch - { - [Constructible] - public DisappearingRaiseSwitch() : base(0x108F) - { - } - - public DisappearingRaiseSwitch(Serial serial) : base(serial) - { - } - - public int CurrentRange => Visible ? 3 : 2; - - public override bool HandlesOnMovement => true; - - protected override void Flip() - { - } - - protected override void Reset() - { - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (Utility.InRange(m.Location, Location, CurrentRange) || Utility.InRange(oldLocation, Location, CurrentRange)) - Refresh(); - } - - public override void OnMapChange() - { - if (!Deleted) - Refresh(); - } - - public override void OnLocationChange(Point3D oldLoc) - { - if (!Deleted) - Refresh(); - } - - public void Refresh() - { - Visible = GetMobilesInRange(CurrentRange).Any(mob => !mob.Hidden || mob.AccessLevel <= AccessLevel.Player); - } - - public override void Serialize(IGenericWriter writer) - { - if (RaisableItem?.Deleted == true) - RaisableItem = null; - - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - Timer.DelayCall(Refresh); - } - } -} +using System; +using System.Linq; +using Server.Network; + +namespace Server.Items +{ + public class RaiseSwitch : Item + { + private ResetTimer m_ResetTimer; + + [Constructible] + public RaiseSwitch(int itemID = 0x1093) : base(itemID) => Movable = false; + + public RaiseSwitch(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public RaisableItem RaisableItem { get; set; } + + public override void OnDoubleClick(Mobile m) + { + if (!m.InRange(this, 2)) + { + m.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return; + } + + if (RaisableItem?.Deleted == true) + RaisableItem = null; + + Flip(); + + if (RaisableItem == null) + return; + + if (RaisableItem.IsRaisable) + { + RaisableItem.Raise(); + m.LocalOverheadMessage( + MessageType.Regular, + 0x5A, + true, + "You hear a grinding noise echoing in the distance." + ); + } + else + { + m.LocalOverheadMessage( + MessageType.Regular, + 0x5A, + true, + "You flip the switch again, but nothing happens." + ); + } + } + + protected virtual void Flip() + { + if (ItemID != 0x1093) + { + ItemID = 0x1093; + + StopResetTimer(); + } + else + { + ItemID = 0x1095; + + StartResetTimer( + RaisableItem?.CloseDelay >= TimeSpan.Zero ? RaisableItem.CloseDelay : TimeSpan.FromMinutes(2.0) + ); + } + + Effects.PlaySound(Location, Map, 0x3E8); + } + + protected void StartResetTimer(TimeSpan delay) + { + StopResetTimer(); + + m_ResetTimer = new ResetTimer(this, delay); + m_ResetTimer.Start(); + } + + protected void StopResetTimer() + { + if (m_ResetTimer != null) + { + m_ResetTimer.Stop(); + m_ResetTimer = null; + } + } + + protected virtual void Reset() + { + if (ItemID != 0x1093) + Flip(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(RaisableItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + RaisableItem = (RaisableItem)reader.ReadItem(); + + Reset(); + } + + private class ResetTimer : Timer + { + private readonly RaiseSwitch m_RaiseSwitch; + + public ResetTimer(RaiseSwitch raiseSwitch, TimeSpan delay) : base(delay) + { + m_RaiseSwitch = raiseSwitch; + + Priority = ComputePriority(delay); + } + + protected override void OnTick() + { + if (m_RaiseSwitch.Deleted) + return; + + m_RaiseSwitch.m_ResetTimer = null; + + m_RaiseSwitch.Reset(); + } + } + } + + public class DisappearingRaiseSwitch : RaiseSwitch + { + [Constructible] + public DisappearingRaiseSwitch() : base(0x108F) + { + } + + public DisappearingRaiseSwitch(Serial serial) : base(serial) + { + } + + public int CurrentRange => Visible ? 3 : 2; + + public override bool HandlesOnMovement => true; + + protected override void Flip() + { + } + + protected override void Reset() + { + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (Utility.InRange(m.Location, Location, CurrentRange) || Utility.InRange(oldLocation, Location, CurrentRange)) + Refresh(); + } + + public override void OnMapChange() + { + if (!Deleted) + Refresh(); + } + + public override void OnLocationChange(Point3D oldLoc) + { + if (!Deleted) + Refresh(); + } + + public void Refresh() + { + Visible = GetMobilesInRange(CurrentRange).Any(mob => !mob.Hidden || mob.AccessLevel <= AccessLevel.Player); + } + + public override void Serialize(IGenericWriter writer) + { + if (RaisableItem?.Deleted == true) + RaisableItem = null; + + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + Timer.DelayCall(Refresh); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Definitions/AGhostOfCovetous.cs b/Projects/UOContent/Engines/MLQuests/Definitions/AGhostOfCovetous.cs index 4d890c703..f0d836ac0 100644 --- a/Projects/UOContent/Engines/MLQuests/Definitions/AGhostOfCovetous.cs +++ b/Projects/UOContent/Engines/MLQuests/Definitions/AGhostOfCovetous.cs @@ -1,282 +1,295 @@ -using System; -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; -using Server.Engines.Spawners; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Definitions -{ - public class AGhostOfCovetous : MLQuest - { - public AGhostOfCovetous() - { - Activated = true; - Title = 1075287; // A Ghost of Covetous - Description = - 1075286; // What? Oh, you startled me! Sorry, I'm a little jumpy. My master Griswolt learned that a ghost has recently taken up residence in the Covetous dungeon. He sent me to capture it, but I . . . well, it terrified me, to be perfectly honest. If you think yourself courageous enough, I'll give you my Spirit Bottle, and you can try to capture it yourself. I'm certain my master would reward you richly for such service. - RefusalMessage = - 1075288; // That's okay, I'm sure someone with more courage than either of us will come along eventually. - InProgressMessage = 1075290; // You'll find that ghost in the mountain pass above the Covetous dungeon. - CompletionMessage = - 1075291; // (As you try to use the Spirit Bottle, the ghost snatches it out of your hand and smashes it on the rocks) Please, don't be frightened. I need your help! - CompletionNotice = CompletionNoticeShort; - - Objectives.Add(new DeliverObjective(typeof(SpiritBottle), 1, "Spirit Bottle", typeof(Frederic))); - - Rewards.Add(new DummyReward( - 1075284)); // Return the filled Spirit Bottle to Griswolt the Master Necromancer to receive a reward. - } - - public override Type NextQuest => typeof(SaveHisDad); - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 3, "Ben"), new Point3D(2467, 402, 15), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 3, "Ben"), new Point3D(2467, 402, 15), Map.Felucca); - } - } - - public class SaveHisDad : MLQuest - { - public SaveHisDad() - { - Activated = true; - Title = 1075337; // Save His Dad - Description = - 1075338; // My father, Andros, is a smith in Minoc. Last week his forge overturned and he was splashed by molten steel. He was horribly burned, and we feared he would die. An alchemist in Vesper promised to make a bandage that could heal him, but he needed the silk of a dread spider. I came here to get some, but I was careless, and succumbed to their poison. Please, won�t you help my father? - RefusalMessage = 1075340; // Oh . . . that�s your decision . . . OooOoooOOoo . . . - InProgressMessage = - 1075341; // Thank you! Deliver it to Leon the Alchemist in Vesper. The silk crumbles easily, and much time has already passed since I died. Please! Hurry! - CompletionMessage = - 1075342; // How may I help thee? You have the silk of a dread spider? Of course I can make you a bandage, but what happened to Frederic? - CompletionNotice = CompletionNoticeShort; - - Objectives.Add(new TimedDeliverObjective(TimeSpan.FromSeconds(600), typeof(DreadSpiderSilk), 1, - "Dread Spider Silk", typeof(Leon))); - - Rewards.Add(new DummyReward( - 1075339)); // Hurry! You must get the silk to Leon the Alchemist quickly, or it will crumble and become useless! - } - - public override Type NextQuest => typeof(AFathersGratitude); - public override bool IsChainTriggered => true; - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Frederic"), new Point3D(2415, 887, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Frederic"), new Point3D(2415, 887, 0), Map.Felucca); - } - } - - public class AFathersGratitude : MLQuest - { - public AFathersGratitude() - { - Activated = true; - OneTimeOnly = true; - Title = 1075343; // A Father�s Gratitude - Description = - 1075344; // That is simply terrible. First Andros, and now his son. Well, let�s make sure Frederic�s sacrifice wasn�t in vain. Will you take the bandages to his father? You can probably deliver them faster than I can, can�t you? - RefusalMessage = - 1075346; // Well I�m sorry to hear you say that. Without your help, I don�t know if I can get these to Andros quickly enough to help him. - InProgressMessage = - 1075347; // I don�t know how much longer Andros will survive. You�d better get this to him as quick as you can. Every second counts! - CompletionMessage = - 1075348; // Sorry, I�m not accepting commissions at the moment. What? You have the bandage I need from Leon? Thank you so much! But why didn�t my son bring this to me himself? . . . Oh, no! You can't be serious! *sag* My Freddie, my son! Thank you for carrying out his last wish. Here -- I made this for my son, to give to him when he became a journeyman. I want you to have it. - CompletionNotice = CompletionNoticeShort; - - Objectives.Add(new DeliverObjective(typeof(AlchemistsBandage), 1, "Alchemist's Bandage", typeof(Andros))); - - Rewards.Add(new ItemReward(1075345, typeof(AndrosGratitude))); // Andros� Gratitude - } - - public override bool IsChainTriggered => true; - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 3, "Leon"), new Point3D(2918, 851, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 3, "Leon"), new Point3D(2918, 851, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 3, "Andros"), new Point3D(2531, 581, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 3, "Andros"), new Point3D(2531, 581, 0), Map.Felucca); - } - } - - public class Ben : BaseCreature - { - [Constructible] - public Ben() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Apprentice Necromancer"; - BodyValue = 0x190; - Hue = 0x83FD; - HairItemID = 0x2048; - HairHue = 0x463; - FacialHairItemID = 0x204C; - FacialHairHue = 0x463; - - InitStats(100, 100, 25); - - AddItem(new Backpack()); - AddItem(new Shoes(0x901)); - AddItem(new LongPants(0x1BB)); - AddItem(new FancyShirt(0x756)); - } - - public Ben(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Ben"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("The Ghost of Frederic Smithson")] - public class Frederic : BaseCreature - { - [Constructible] - public Frederic() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - BodyValue = 0x1A; - Hue = 0x455; - Frozen = true; - - InitStats(100, 100, 25); - } - - public Frederic(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "The Ghost of Frederic Smithson"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Leon : BaseCreature - { - [Constructible] - public Leon() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Alchemist"; - Race = Race.Human; - BodyValue = 0x190; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Backpack()); - AddItem(new Shoes(0x901)); - AddItem(new Robe(0x657)); - } - - public Leon(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Leon"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Andros : BaseCreature - { - [Constructible] - public Andros() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Blacksmith"; - BodyValue = 0x190; - Hue = 0x8409; - FacialHairItemID = 0x2041; - FacialHairHue = 0x45E; - HairItemID = 0x2049; - HairHue = 0x45E; - - InitStats(100, 100, 25); - - AddItem(new Backpack()); - AddItem(new Boots(0x901)); - AddItem(new FancyShirt(0x60B)); - AddItem(new LongPants(0x1BB)); - AddItem(new FullApron(0x901)); - AddItem(new SmithHammer()); - } - - public Andros(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Andros"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; +using Server.Engines.Spawners; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Definitions +{ + public class AGhostOfCovetous : MLQuest + { + public AGhostOfCovetous() + { + Activated = true; + Title = 1075287; // A Ghost of Covetous + Description = + 1075286; // What? Oh, you startled me! Sorry, I'm a little jumpy. My master Griswolt learned that a ghost has recently taken up residence in the Covetous dungeon. He sent me to capture it, but I . . . well, it terrified me, to be perfectly honest. If you think yourself courageous enough, I'll give you my Spirit Bottle, and you can try to capture it yourself. I'm certain my master would reward you richly for such service. + RefusalMessage = + 1075288; // That's okay, I'm sure someone with more courage than either of us will come along eventually. + InProgressMessage = 1075290; // You'll find that ghost in the mountain pass above the Covetous dungeon. + CompletionMessage = + 1075291; // (As you try to use the Spirit Bottle, the ghost snatches it out of your hand and smashes it on the rocks) Please, don't be frightened. I need your help! + CompletionNotice = CompletionNoticeShort; + + Objectives.Add(new DeliverObjective(typeof(SpiritBottle), 1, "Spirit Bottle", typeof(Frederic))); + + Rewards.Add( + new DummyReward( + 1075284 + ) + ); // Return the filled Spirit Bottle to Griswolt the Master Necromancer to receive a reward. + } + + public override Type NextQuest => typeof(SaveHisDad); + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 3, "Ben"), new Point3D(2467, 402, 15), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 3, "Ben"), new Point3D(2467, 402, 15), Map.Felucca); + } + } + + public class SaveHisDad : MLQuest + { + public SaveHisDad() + { + Activated = true; + Title = 1075337; // Save His Dad + Description = + 1075338; // My father, Andros, is a smith in Minoc. Last week his forge overturned and he was splashed by molten steel. He was horribly burned, and we feared he would die. An alchemist in Vesper promised to make a bandage that could heal him, but he needed the silk of a dread spider. I came here to get some, but I was careless, and succumbed to their poison. Please, won�t you help my father? + RefusalMessage = 1075340; // Oh . . . that�s your decision . . . OooOoooOOoo . . . + InProgressMessage = + 1075341; // Thank you! Deliver it to Leon the Alchemist in Vesper. The silk crumbles easily, and much time has already passed since I died. Please! Hurry! + CompletionMessage = + 1075342; // How may I help thee? You have the silk of a dread spider? Of course I can make you a bandage, but what happened to Frederic? + CompletionNotice = CompletionNoticeShort; + + Objectives.Add( + new TimedDeliverObjective( + TimeSpan.FromSeconds(600), + typeof(DreadSpiderSilk), + 1, + "Dread Spider Silk", + typeof(Leon) + ) + ); + + Rewards.Add( + new DummyReward( + 1075339 + ) + ); // Hurry! You must get the silk to Leon the Alchemist quickly, or it will crumble and become useless! + } + + public override Type NextQuest => typeof(AFathersGratitude); + public override bool IsChainTriggered => true; + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Frederic"), new Point3D(2415, 887, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Frederic"), new Point3D(2415, 887, 0), Map.Felucca); + } + } + + public class AFathersGratitude : MLQuest + { + public AFathersGratitude() + { + Activated = true; + OneTimeOnly = true; + Title = 1075343; // A Father�s Gratitude + Description = + 1075344; // That is simply terrible. First Andros, and now his son. Well, let�s make sure Frederic�s sacrifice wasn�t in vain. Will you take the bandages to his father? You can probably deliver them faster than I can, can�t you? + RefusalMessage = + 1075346; // Well I�m sorry to hear you say that. Without your help, I don�t know if I can get these to Andros quickly enough to help him. + InProgressMessage = + 1075347; // I don�t know how much longer Andros will survive. You�d better get this to him as quick as you can. Every second counts! + CompletionMessage = + 1075348; // Sorry, I�m not accepting commissions at the moment. What? You have the bandage I need from Leon? Thank you so much! But why didn�t my son bring this to me himself? . . . Oh, no! You can't be serious! *sag* My Freddie, my son! Thank you for carrying out his last wish. Here -- I made this for my son, to give to him when he became a journeyman. I want you to have it. + CompletionNotice = CompletionNoticeShort; + + Objectives.Add(new DeliverObjective(typeof(AlchemistsBandage), 1, "Alchemist's Bandage", typeof(Andros))); + + Rewards.Add(new ItemReward(1075345, typeof(AndrosGratitude))); // Andros� Gratitude + } + + public override bool IsChainTriggered => true; + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 3, "Leon"), new Point3D(2918, 851, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 3, "Leon"), new Point3D(2918, 851, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 3, "Andros"), new Point3D(2531, 581, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 3, "Andros"), new Point3D(2531, 581, 0), Map.Felucca); + } + } + + public class Ben : BaseCreature + { + [Constructible] + public Ben() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Apprentice Necromancer"; + BodyValue = 0x190; + Hue = 0x83FD; + HairItemID = 0x2048; + HairHue = 0x463; + FacialHairItemID = 0x204C; + FacialHairHue = 0x463; + + InitStats(100, 100, 25); + + AddItem(new Backpack()); + AddItem(new Shoes(0x901)); + AddItem(new LongPants(0x1BB)); + AddItem(new FancyShirt(0x756)); + } + + public Ben(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Ben"; + + 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(); + } + } + + [QuesterName("The Ghost of Frederic Smithson")] + public class Frederic : BaseCreature + { + [Constructible] + public Frederic() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + BodyValue = 0x1A; + Hue = 0x455; + Frozen = true; + + InitStats(100, 100, 25); + } + + public Frederic(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "The Ghost of Frederic Smithson"; + + 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 class Leon : BaseCreature + { + [Constructible] + public Leon() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Alchemist"; + Race = Race.Human; + BodyValue = 0x190; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Backpack()); + AddItem(new Shoes(0x901)); + AddItem(new Robe(0x657)); + } + + public Leon(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Leon"; + + 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 class Andros : BaseCreature + { + [Constructible] + public Andros() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Blacksmith"; + BodyValue = 0x190; + Hue = 0x8409; + FacialHairItemID = 0x2041; + FacialHairHue = 0x45E; + HairItemID = 0x2049; + HairHue = 0x45E; + + InitStats(100, 100, 25); + + AddItem(new Backpack()); + AddItem(new Boots(0x901)); + AddItem(new FancyShirt(0x60B)); + AddItem(new LongPants(0x1BB)); + AddItem(new FullApron(0x901)); + AddItem(new SmithHammer()); + } + + public Andros(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Andros"; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Definitions/BaseEscort.cs b/Projects/UOContent/Engines/MLQuests/Definitions/BaseEscort.cs index 6a505e897..733150718 100644 --- a/Projects/UOContent/Engines/MLQuests/Definitions/BaseEscort.cs +++ b/Projects/UOContent/Engines/MLQuests/Definitions/BaseEscort.cs @@ -1,18 +1,18 @@ -namespace Server.Engines.MLQuests.Definitions -{ - // Base class for escorts providing the AwardHumanInNeed option - public class BaseEscort : MLQuest - { - public BaseEscort() => CompletionNotice = CompletionNoticeShort; - - public virtual bool AwardHumanInNeed => true; - - public override void GetRewards(MLQuestInstance instance) - { - if (AwardHumanInNeed) - HumanInNeed.AwardTo(instance.Player); - - base.GetRewards(instance); - } - } -} \ No newline at end of file +namespace Server.Engines.MLQuests.Definitions +{ + // Base class for escorts providing the AwardHumanInNeed option + public class BaseEscort : MLQuest + { + public BaseEscort() => CompletionNotice = CompletionNoticeShort; + + public virtual bool AwardHumanInNeed => true; + + public override void GetRewards(MLQuestInstance instance) + { + if (AwardHumanInNeed) + HumanInNeed.AwardTo(instance.Player); + + base.GetRewards(instance); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Definitions/Bedlam.cs b/Projects/UOContent/Engines/MLQuests/Definitions/Bedlam.cs index 9e42f0c1d..1019b5d9a 100644 --- a/Projects/UOContent/Engines/MLQuests/Definitions/Bedlam.cs +++ b/Projects/UOContent/Engines/MLQuests/Definitions/Bedlam.cs @@ -1,223 +1,223 @@ -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; -using Server.Engines.Spawners; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Definitions -{ - public class Momento : MLQuest - { - public Momento() - { - Activated = true; - Title = 1074750; // Momento! - Description = - 1074751; // I was going to march right out there and get it myself, but no ... Master Gnosos won't let me. But you see, that bridle means so much to me. A momento of happier, less-dead ... well undead horseback riding. Could you fetch it for me? I think my horse, formerly known as 'Resolve', may still be wearing it. - RefusalMessage = 1074752; // Hrmph. - InProgressMessage = - 1074753; // The bridle would be hard to miss on him now ... since he's skeletal. Please do what you need to do to retrieve it for me. - CompletionMessage = 1074754; // I'd know that jingling sound anywhere! You have recovered my bridle. Thank you. - - Objectives.Add(new CollectObjective(1, typeof(ResolvesBridle), "Resolve's Bridle")); - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 3, "Kia"), new Point3D(87, 1640, 0), Map.Malas); - PutSpawner(new Spawner(1, 5, 10, 0, 3, "Nythalia"), new Point3D(91, 1639, 0), Map.Malas); - } - } - - public class CulinaryCrisis : MLQuest - { - public CulinaryCrisis() - { - Activated = true; - Title = 1074755; // Culinary Crisis - Description = - 1074756; // You have NO idea how impossible this is. Simply intolerable! How can one expect an artiste' like me to create masterpieces of culinary delight without the best, fresh ingredients? Ever since this whositwhatsit started this uproar, my thrice-daily produce deliveries have ended. I can't survive another hour without produce! - RefusalMessage = 1074757; // You have no artistry in your soul. - InProgressMessage = 1074758; // I must have fresh produce and cheese at once! - CompletionMessage = - 1074759; // Those dates look bruised! Oh no, and you fetched a soft cheese. *deep pained sigh* Well, even I can only do so much with inferior ingredients. BAM! - - Objectives.Add(new CollectObjective(20, typeof(Dates), 1025927)); // bunch of dates - Objectives.Add(new CollectObjective(5, typeof(CheeseWheel), 1022430)); // wheel of cheese - - Rewards.Add(ItemReward.BagOfTreasure); - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 3, "Emerillo"), new Point3D(90, 1639, 0), Map.Malas); - } - } - - public class GoneNative : MLQuest - { - public GoneNative() - { - Activated = true; - Title = 1074855; // Gone Native - Description = - 1074856; // Pathetic really. I must say, a senior instructor going native -- forgetting about his students and peers and engaging in such disgraceful behavior! I'm speaking, of course, of Theophilus. Master Theophilus to you. He may have gone native but he still holds a Mastery Degree from Bedlam College! But, well, that's neither here nor there. I need you to take care of my colleague. Convince him of the error of his ways. He may resist. In fact, assume he will and kill him. We'll get him resurrected and be ready to cure his folly. What do you say? - RefusalMessage = - 1074857; // I understand. A Master of Bedlam, even one entirely off his rocker, is too much for you to handle. - InProgressMessage = - 1074858; // You had better get going. Master Theophilus isn't likely to kill himself just to save me this embarrassment. - CompletionMessage = - 1074859; // You look a bit worse for wear! He put up a good fight did he? Hah! That's the spirit … a Master of Bedlam is a match for most. - - Objectives.Add(new KillObjective(1, new[] { typeof(MasterTheophilus) }, "Master Theophilus")); - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - } - - [QuesterName("Kia (Bedlam)")] - public class Kia : BaseCreature - { - [Constructible] - public Kia() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the student"; - Race = Race.Human; - BodyValue = 0x191; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Backpack()); - AddItem(new Sandals(0x709)); - AddItem(new Robe(0x497)); - } - - public Kia(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Kia"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Emerillo (Bedlam)")] - public class Emerillo : BaseCreature - { - [Constructible] - public Emerillo() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the cook"; - Race = Race.Human; - BodyValue = 0x190; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Backpack()); - AddItem(new Sandals(Utility.RandomNeutralHue())); - AddItem(new ShortPants(Utility.RandomPinkHue())); - AddItem(new Shirt()); - AddItem(new HalfApron(0x8FD)); - } - - public Emerillo(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Emerillo"; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1074222); // Could I trouble you for some assistance? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Nythalia : BaseCreature - { - [Constructible] - public Nythalia() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the student"; - Race = Race.Human; - BodyValue = 0x191; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Backpack()); - AddItem(new Shoes(Utility.RandomNeutralHue())); - AddItem(new Robe(Utility.RandomBool() ? 0x497 : 0x498)); - } - - public Nythalia(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Mythalia"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; +using Server.Engines.Spawners; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Definitions +{ + public class Momento : MLQuest + { + public Momento() + { + Activated = true; + Title = 1074750; // Momento! + Description = + 1074751; // I was going to march right out there and get it myself, but no ... Master Gnosos won't let me. But you see, that bridle means so much to me. A momento of happier, less-dead ... well undead horseback riding. Could you fetch it for me? I think my horse, formerly known as 'Resolve', may still be wearing it. + RefusalMessage = 1074752; // Hrmph. + InProgressMessage = + 1074753; // The bridle would be hard to miss on him now ... since he's skeletal. Please do what you need to do to retrieve it for me. + CompletionMessage = 1074754; // I'd know that jingling sound anywhere! You have recovered my bridle. Thank you. + + Objectives.Add(new CollectObjective(1, typeof(ResolvesBridle), "Resolve's Bridle")); + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 3, "Kia"), new Point3D(87, 1640, 0), Map.Malas); + PutSpawner(new Spawner(1, 5, 10, 0, 3, "Nythalia"), new Point3D(91, 1639, 0), Map.Malas); + } + } + + public class CulinaryCrisis : MLQuest + { + public CulinaryCrisis() + { + Activated = true; + Title = 1074755; // Culinary Crisis + Description = + 1074756; // You have NO idea how impossible this is. Simply intolerable! How can one expect an artiste' like me to create masterpieces of culinary delight without the best, fresh ingredients? Ever since this whositwhatsit started this uproar, my thrice-daily produce deliveries have ended. I can't survive another hour without produce! + RefusalMessage = 1074757; // You have no artistry in your soul. + InProgressMessage = 1074758; // I must have fresh produce and cheese at once! + CompletionMessage = + 1074759; // Those dates look bruised! Oh no, and you fetched a soft cheese. *deep pained sigh* Well, even I can only do so much with inferior ingredients. BAM! + + Objectives.Add(new CollectObjective(20, typeof(Dates), 1025927)); // bunch of dates + Objectives.Add(new CollectObjective(5, typeof(CheeseWheel), 1022430)); // wheel of cheese + + Rewards.Add(ItemReward.BagOfTreasure); + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 3, "Emerillo"), new Point3D(90, 1639, 0), Map.Malas); + } + } + + public class GoneNative : MLQuest + { + public GoneNative() + { + Activated = true; + Title = 1074855; // Gone Native + Description = + 1074856; // Pathetic really. I must say, a senior instructor going native -- forgetting about his students and peers and engaging in such disgraceful behavior! I'm speaking, of course, of Theophilus. Master Theophilus to you. He may have gone native but he still holds a Mastery Degree from Bedlam College! But, well, that's neither here nor there. I need you to take care of my colleague. Convince him of the error of his ways. He may resist. In fact, assume he will and kill him. We'll get him resurrected and be ready to cure his folly. What do you say? + RefusalMessage = + 1074857; // I understand. A Master of Bedlam, even one entirely off his rocker, is too much for you to handle. + InProgressMessage = + 1074858; // You had better get going. Master Theophilus isn't likely to kill himself just to save me this embarrassment. + CompletionMessage = + 1074859; // You look a bit worse for wear! He put up a good fight did he? Hah! That's the spirit … a Master of Bedlam is a match for most. + + Objectives.Add(new KillObjective(1, new[] { typeof(MasterTheophilus) }, "Master Theophilus")); + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + } + + [QuesterName("Kia (Bedlam)")] + public class Kia : BaseCreature + { + [Constructible] + public Kia() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the student"; + Race = Race.Human; + BodyValue = 0x191; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Backpack()); + AddItem(new Sandals(0x709)); + AddItem(new Robe(0x497)); + } + + public Kia(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Kia"; + + 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(); + } + } + + [QuesterName("Emerillo (Bedlam)")] + public class Emerillo : BaseCreature + { + [Constructible] + public Emerillo() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the cook"; + Race = Race.Human; + BodyValue = 0x190; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Backpack()); + AddItem(new Sandals(Utility.RandomNeutralHue())); + AddItem(new ShortPants(Utility.RandomPinkHue())); + AddItem(new Shirt()); + AddItem(new HalfApron(0x8FD)); + } + + public Emerillo(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Emerillo"; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1074222); // Could I trouble you for some assistance? + } + + 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 class Nythalia : BaseCreature + { + [Constructible] + public Nythalia() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the student"; + Race = Race.Human; + BodyValue = 0x191; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Backpack()); + AddItem(new Shoes(Utility.RandomNeutralHue())); + AddItem(new Robe(Utility.RandomBool() ? 0x497 : 0x498)); + } + + public Nythalia(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Mythalia"; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Definitions/BlightedGrove.cs b/Projects/UOContent/Engines/MLQuests/Definitions/BlightedGrove.cs index 30a33fcf6..d34999582 100644 --- a/Projects/UOContent/Engines/MLQuests/Definitions/BlightedGrove.cs +++ b/Projects/UOContent/Engines/MLQuests/Definitions/BlightedGrove.cs @@ -1,279 +1,290 @@ -using System; -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; -using Server.Engines.Spawners; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Definitions -{ - public class VilePoison : MLQuest - { - public VilePoison() - { - Activated = true; - Title = 1074950; // Vile Poison - Description = - 1074956; // Heya! I'm sure glad to see you. Listen I'm in a bit of a bind here. I'm supposed to be gathering poisoned water at the base of that corrupted tree there, but I can't get in under the roots to get a good sample. The branches and brush are so tainted that they can't be cut, burned or even magically passed. It's put my work at a real standstill. If you help me out, I'll help you get in there too. Whadda ya say? - RefusalMessage = 1074964; // Okay. If you change your mind, I'll probably still be stuck here trying to get in. - InProgressMessage = 1074968; // My friend, Iosep, is a weaponsmith in Jhelom. If anyone can help us, he can! - CompletionMessage = - 1074991; // Greetings. What have you there? Ah, a sample from a poisonous tree, you say? My friend Jamal sent you? Well, let me see that then, and we'll get to work. - - Objectives.Add(new DeliverObjective(typeof(TaintedTreeSample), 1, "tainted tree sample", typeof(Iosep))); - - Rewards.Add(new DummyReward(1074962)); // A step closer to entering Blighted Grove. - } - - public override Type NextQuest => typeof(ARockAndAHardPlace); - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Jamal"), new Point3D(559, 1651, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Jamal"), new Point3D(559, 1651, 0), Map.Trammel); - - PutSpawner(new Spawner(1, 5, 10, 0, 2, "Iosep"), new Point3D(1354, 3754, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 2, "Iosep"), new Point3D(1354, 3754, 0), Map.Trammel); - } - } - - public class ARockAndAHardPlace : MLQuest - { - public ARockAndAHardPlace() - { - Activated = true; - Title = 1074951; // A Rock and a Hard Place - Description = - 1074957; // This is some nasty stuff, that's for certain. I don't even want to think about what sort of blight caused this venomous reaction from that old tree. Let's get to work … we'll need to try something really hard but still workable as our base material. Nothing's harder than stone and diamond. Let's try them first. - RefusalMessage = 1074965; // Sure, no problem. I thought you were interested in figuring this out. - InProgressMessage = - 1074969; // If you're a miner, you should have no trouble getting that stuff. If not, you can probably buy some samples from a miner? - CompletionMessage = - 1074992; // Have you got the granite and diamonds? Great, let me see them and we'll see what effect this venom has upon them. - - // Any type of granite works - Objectives.Add(new CollectObjective(4, typeof(BaseGranite), 1026009)); // rock - Objectives.Add(new CollectObjective(2, typeof(BlueDiamond), 1032696)); // Blue Diamond - - Rewards.Add(new DummyReward(1074962)); // A step closer to entering Blighted Grove. - } - - public override Type NextQuest => typeof(SympatheticMagic); - public override bool IsChainTriggered => true; - } - - public class SympatheticMagic : MLQuest - { - public SympatheticMagic() - { - Activated = true; - Title = 1074952; // Sympathetic Magic - Description = - 1074958; // Hmm, I've never even heard of something that can damage diamond like that. I guess we'll have to go with plan B. Let's try something similar. Sometimes there's a natural immunity to be found when you use a substance that's like the one you're trying to cut. A sort of "sympathetic" thing. Y'know? - RefusalMessage = 1074965; // Sure, no problem. I thought you were interested in figuring this out. - InProgressMessage = 1074970; // I think a lumberjack can help supply bark. - CompletionMessage = 1074993; // You're back with the bark already? Terrific! I bet this will do the trick. - - Objectives.Add(new CollectObjective(10, typeof(BarkFragment), 1032687)); // Bark Fragment - - Rewards.Add(new DummyReward(1074962)); // A step closer to entering Blighted Grove. - } - - public override Type NextQuest => typeof(AlreadyDead); - public override bool IsChainTriggered => true; - } - - public class AlreadyDead : MLQuest - { - public AlreadyDead() - { - Activated = true; - Title = 1074953; // Already Dead - Description = - 1074959; // Amazing! The bark was reduced to ash in seconds. Whatever this taint is, it plays havok with living things. And of course, it took the edge off both diamonds and granite even faster. What we need is something workable but dead; something that can hold an edge without melting. See what you can come up with, please. - RefusalMessage = 1074965; // Sure, no problem. I thought you were interested in figuring this out. - InProgressMessage = - 1074971; // I'm thinking we need something fairly brittle or it won't hold an edge. And, it can't be alive, of course. - CompletionMessage = 1074994; // Great thought! Bone might just do the trick. - - Objectives.Add(new InternalObjective()); - - Rewards.Add(new DummyReward(1074962)); // A step closer to entering Blighted Grove. - } - - public override Type NextQuest => typeof(Eureka); - public override bool IsChainTriggered => true; - - private class InternalObjective : CollectObjective - { - public InternalObjective() - : base(10, typeof(Bone), 1074963) // (10) workable samples - { - } - - public override bool ShowDetailed => false; - } - } - - public class Eureka : MLQuest - { - public Eureka() - { - Activated = true; - Title = 1074954; // Eureka! - Description = - 1074960; // We're in business! I've put together the instructions for chopping sort of sword, in the style of one of those new-fangled elven machetes. Take those back to Jamal for me, if you would. - RefusalMessage = 1074966; // Well, okay. I guess I thought you'd want to see this through. - InProgressMessage = - 1074972; // I'm sure Jamal is eager to get this information. He's probably still hanging around near that big old blighted tree. - CompletionMessage = 1074995; // Heya! You're back. Was Iosep able to help? Let me see what he's sent. - - Objectives.Add(new DeliverObjective(typeof(SealedNotesForJamal), 1, "sealed note for Jamal", typeof(Jamal))); - - Rewards.Add(new DummyReward(1074962)); // A step closer to entering Blighted Grove. - } - - public override Type NextQuest => typeof(SubContracting); - public override bool IsChainTriggered => true; - - public override void GetRewards(MLQuestInstance instance) - { - PlayerMobile pm = instance.Player; - - if (!pm.HasRecipe(32)) - { - // The ability is awarded regardless of blacksmithy skill - pm.AcquireRecipe(32); - - if (pm.Skills.Blacksmith.Base < 45.0) // TODO: Verify threshold - pm.SendLocalizedMessage( - 1075005); // You observe carefully but you can't grasp the complexities of smithing a bone handled machete. - else - pm.SendLocalizedMessage(1075006); // You have learned how to smith a bone handled machete! - } - - base.GetRewards(instance); - } - } - - public class SubContracting : MLQuest - { - public SubContracting() - { - Activated = true; - Title = 1074955; // Sub Contracting - Description = - 1074961; // Wonderful! Now we can both get in there! Let me show you these instructions for making this machete. If you're not skilled in smithing, I'm not sure how much sense it will make though. Listen, if you're heading in there anyway … maybe you'd do me one more favor? I'm ah ... buried in work out here ... so if you'd go in and get me a few water samples, I'd be obliged. - RefusalMessage = 1074967; // Oh. Right, I guess you're really ... ah ... busy too. - InProgressMessage = - 1074973; // Once you're inside, look for places where the water has twisted and warped the natural creatures. - CompletionMessage = - 1074996; // I hear sloshing ... that must mean you've got my water samples. Whew, I'm so glad you braved the dangers in there ... I mean, I would have but I'm so busy out here. Here's your reward! - - Objectives.Add(new CollectObjective(3, typeof(SamplesOfCorruptedWater), - "samples of corrupted water")); // On OSI the label is "#1074999" - // TODO: "Return to" should say "Jamal (near Blighted Grove)" - // Maybe every quest NPC has directions as a property? - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - - public override bool IsChainTriggered => true; - } - - [QuesterName("Jamal (near Blighted Grove)")] - public class Jamal : BaseCreature - { - [Constructible] - public Jamal() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.2, 0.4) - { - Title = "the Fisherman"; - Body = 400; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - Utility.AssignRandomFacialHair(this, HairHue); - - AddItem(new Shirt(0x1BB)); - AddItem(new ShortPants(Utility.RandomNeutralHue())); - AddItem(new ThighBoots(Utility.RandomAnimalHue())); - AddItem(new Backpack()); - } - - public Jamal(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Jamal"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - reader.ReadInt(); - } - } - - [QuesterName("Iosep (Jhelom)")] - public class Iosep : BaseCreature - { - [Constructible] - public Iosep() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.2, 0.4) - { - Title = "the Exporter"; - Body = 400; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - AddItem(new FancyShirt(Utility.RandomBlueHue())); - AddItem(new LongPants(0x1BB)); - AddItem(new Shoes(Utility.RandomNeutralHue())); - AddItem(new Backpack()); - } - - public Iosep(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Iosep"; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074209, // Hey, could you help me out with something? - 1074215)); // Don’t test my patience you sniveling worm! - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - reader.ReadInt(); - } - } -} +using System; +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; +using Server.Engines.Spawners; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Definitions +{ + public class VilePoison : MLQuest + { + public VilePoison() + { + Activated = true; + Title = 1074950; // Vile Poison + Description = + 1074956; // Heya! I'm sure glad to see you. Listen I'm in a bit of a bind here. I'm supposed to be gathering poisoned water at the base of that corrupted tree there, but I can't get in under the roots to get a good sample. The branches and brush are so tainted that they can't be cut, burned or even magically passed. It's put my work at a real standstill. If you help me out, I'll help you get in there too. Whadda ya say? + RefusalMessage = 1074964; // Okay. If you change your mind, I'll probably still be stuck here trying to get in. + InProgressMessage = 1074968; // My friend, Iosep, is a weaponsmith in Jhelom. If anyone can help us, he can! + CompletionMessage = + 1074991; // Greetings. What have you there? Ah, a sample from a poisonous tree, you say? My friend Jamal sent you? Well, let me see that then, and we'll get to work. + + Objectives.Add(new DeliverObjective(typeof(TaintedTreeSample), 1, "tainted tree sample", typeof(Iosep))); + + Rewards.Add(new DummyReward(1074962)); // A step closer to entering Blighted Grove. + } + + public override Type NextQuest => typeof(ARockAndAHardPlace); + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Jamal"), new Point3D(559, 1651, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Jamal"), new Point3D(559, 1651, 0), Map.Trammel); + + PutSpawner(new Spawner(1, 5, 10, 0, 2, "Iosep"), new Point3D(1354, 3754, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 2, "Iosep"), new Point3D(1354, 3754, 0), Map.Trammel); + } + } + + public class ARockAndAHardPlace : MLQuest + { + public ARockAndAHardPlace() + { + Activated = true; + Title = 1074951; // A Rock and a Hard Place + Description = + 1074957; // This is some nasty stuff, that's for certain. I don't even want to think about what sort of blight caused this venomous reaction from that old tree. Let's get to work … we'll need to try something really hard but still workable as our base material. Nothing's harder than stone and diamond. Let's try them first. + RefusalMessage = 1074965; // Sure, no problem. I thought you were interested in figuring this out. + InProgressMessage = + 1074969; // If you're a miner, you should have no trouble getting that stuff. If not, you can probably buy some samples from a miner? + CompletionMessage = + 1074992; // Have you got the granite and diamonds? Great, let me see them and we'll see what effect this venom has upon them. + + // Any type of granite works + Objectives.Add(new CollectObjective(4, typeof(BaseGranite), 1026009)); // rock + Objectives.Add(new CollectObjective(2, typeof(BlueDiamond), 1032696)); // Blue Diamond + + Rewards.Add(new DummyReward(1074962)); // A step closer to entering Blighted Grove. + } + + public override Type NextQuest => typeof(SympatheticMagic); + public override bool IsChainTriggered => true; + } + + public class SympatheticMagic : MLQuest + { + public SympatheticMagic() + { + Activated = true; + Title = 1074952; // Sympathetic Magic + Description = + 1074958; // Hmm, I've never even heard of something that can damage diamond like that. I guess we'll have to go with plan B. Let's try something similar. Sometimes there's a natural immunity to be found when you use a substance that's like the one you're trying to cut. A sort of "sympathetic" thing. Y'know? + RefusalMessage = 1074965; // Sure, no problem. I thought you were interested in figuring this out. + InProgressMessage = 1074970; // I think a lumberjack can help supply bark. + CompletionMessage = 1074993; // You're back with the bark already? Terrific! I bet this will do the trick. + + Objectives.Add(new CollectObjective(10, typeof(BarkFragment), 1032687)); // Bark Fragment + + Rewards.Add(new DummyReward(1074962)); // A step closer to entering Blighted Grove. + } + + public override Type NextQuest => typeof(AlreadyDead); + public override bool IsChainTriggered => true; + } + + public class AlreadyDead : MLQuest + { + public AlreadyDead() + { + Activated = true; + Title = 1074953; // Already Dead + Description = + 1074959; // Amazing! The bark was reduced to ash in seconds. Whatever this taint is, it plays havok with living things. And of course, it took the edge off both diamonds and granite even faster. What we need is something workable but dead; something that can hold an edge without melting. See what you can come up with, please. + RefusalMessage = 1074965; // Sure, no problem. I thought you were interested in figuring this out. + InProgressMessage = + 1074971; // I'm thinking we need something fairly brittle or it won't hold an edge. And, it can't be alive, of course. + CompletionMessage = 1074994; // Great thought! Bone might just do the trick. + + Objectives.Add(new InternalObjective()); + + Rewards.Add(new DummyReward(1074962)); // A step closer to entering Blighted Grove. + } + + public override Type NextQuest => typeof(Eureka); + public override bool IsChainTriggered => true; + + private class InternalObjective : CollectObjective + { + public InternalObjective() + : base(10, typeof(Bone), 1074963) // (10) workable samples + { + } + + public override bool ShowDetailed => false; + } + } + + public class Eureka : MLQuest + { + public Eureka() + { + Activated = true; + Title = 1074954; // Eureka! + Description = + 1074960; // We're in business! I've put together the instructions for chopping sort of sword, in the style of one of those new-fangled elven machetes. Take those back to Jamal for me, if you would. + RefusalMessage = 1074966; // Well, okay. I guess I thought you'd want to see this through. + InProgressMessage = + 1074972; // I'm sure Jamal is eager to get this information. He's probably still hanging around near that big old blighted tree. + CompletionMessage = 1074995; // Heya! You're back. Was Iosep able to help? Let me see what he's sent. + + Objectives.Add(new DeliverObjective(typeof(SealedNotesForJamal), 1, "sealed note for Jamal", typeof(Jamal))); + + Rewards.Add(new DummyReward(1074962)); // A step closer to entering Blighted Grove. + } + + public override Type NextQuest => typeof(SubContracting); + public override bool IsChainTriggered => true; + + public override void GetRewards(MLQuestInstance instance) + { + var pm = instance.Player; + + if (!pm.HasRecipe(32)) + { + // The ability is awarded regardless of blacksmithy skill + pm.AcquireRecipe(32); + + if (pm.Skills.Blacksmith.Base < 45.0) // TODO: Verify threshold + pm.SendLocalizedMessage( + 1075005 + ); // You observe carefully but you can't grasp the complexities of smithing a bone handled machete. + else + pm.SendLocalizedMessage(1075006); // You have learned how to smith a bone handled machete! + } + + base.GetRewards(instance); + } + } + + public class SubContracting : MLQuest + { + public SubContracting() + { + Activated = true; + Title = 1074955; // Sub Contracting + Description = + 1074961; // Wonderful! Now we can both get in there! Let me show you these instructions for making this machete. If you're not skilled in smithing, I'm not sure how much sense it will make though. Listen, if you're heading in there anyway … maybe you'd do me one more favor? I'm ah ... buried in work out here ... so if you'd go in and get me a few water samples, I'd be obliged. + RefusalMessage = 1074967; // Oh. Right, I guess you're really ... ah ... busy too. + InProgressMessage = + 1074973; // Once you're inside, look for places where the water has twisted and warped the natural creatures. + CompletionMessage = + 1074996; // I hear sloshing ... that must mean you've got my water samples. Whew, I'm so glad you braved the dangers in there ... I mean, I would have but I'm so busy out here. Here's your reward! + + Objectives.Add( + new CollectObjective( + 3, + typeof(SamplesOfCorruptedWater), + "samples of corrupted water" + ) + ); // On OSI the label is "#1074999" + // TODO: "Return to" should say "Jamal (near Blighted Grove)" + // Maybe every quest NPC has directions as a property? + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + + public override bool IsChainTriggered => true; + } + + [QuesterName("Jamal (near Blighted Grove)")] + public class Jamal : BaseCreature + { + [Constructible] + public Jamal() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.2, 0.4) + { + Title = "the Fisherman"; + Body = 400; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + Utility.AssignRandomFacialHair(this, HairHue); + + AddItem(new Shirt(0x1BB)); + AddItem(new ShortPants(Utility.RandomNeutralHue())); + AddItem(new ThighBoots(Utility.RandomAnimalHue())); + AddItem(new Backpack()); + } + + public Jamal(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Jamal"; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + reader.ReadInt(); + } + } + + [QuesterName("Iosep (Jhelom)")] + public class Iosep : BaseCreature + { + [Constructible] + public Iosep() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.2, 0.4) + { + Title = "the Exporter"; + Body = 400; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + AddItem(new FancyShirt(Utility.RandomBlueHue())); + AddItem(new LongPants(0x1BB)); + AddItem(new Shoes(Utility.RandomNeutralHue())); + AddItem(new Backpack()); + } + + public Iosep(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Iosep"; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074209, // Hey, could you help me out with something? + 1074215 + ) + ); // Don’t test my patience you sniveling worm! + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + reader.ReadInt(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Definitions/Britannia.cs b/Projects/UOContent/Engines/MLQuests/Definitions/Britannia.cs index 2add7d8a5..551fc14e4 100644 --- a/Projects/UOContent/Engines/MLQuests/Definitions/Britannia.cs +++ b/Projects/UOContent/Engines/MLQuests/Definitions/Britannia.cs @@ -1,197 +1,209 @@ -using System; -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; -using Server.Engines.Spawners; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Definitions -{ - public class Aemaeth1 : MLQuest - { - public Aemaeth1() - { - Activated = true; - Title = 1075321; // Aemaeth - Description = - 1075322; // My father died in an accident some months ago. My mother refused to accept his death. We had a little money set by, and she took it to a necromancer, who promised to restore my father to life. Well, he revived my father, all right, the cheat! Now my father is a walking corpse, a travesty . . . a monster. My mother is beside herself -- she won't eat, she can't sleep. I prayed at the shrine of Spirituality for guidance, and I must have fallen asleep. When I awoke, there was this basin of clear water. I cannot leave my mother, for I fear what she might do to herself. Could you take this to the graveyard, and give it to what is left of my father? - RefusalMessage = - 1075324; // Oh! Alright then. I hope someone comes along soon who can help me, or I dont know what will become of us. - InProgressMessage = - 1075325; // My father - or what remains of him - can be found in the graveyard northwest of the city. - CompletionMessage = 1075326; // What is this you give me? A basin of water? - CompletionNotice = CompletionNoticeShort; - - Objectives.Add(new DeliverObjective(typeof(BasinOfCrystalClearWater), 1, "Basin of Crystal Clear Water", - typeof(SkeletonOfSzandor))); - - Rewards.Add(new DummyReward(1075323)); // Aurelia's gratitude. - } - - public override Type NextQuest => typeof(Aemaeth2); - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Aurelia"), new Point3D(1459, 3795, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Aurelia"), new Point3D(1459, 3795, 0), Map.Felucca); - } - } - - public class Aemaeth2 : MLQuest - { - public Aemaeth2() - { - Activated = true; - OneTimeOnly = true; - Title = 1075327; // Aemaeth - Description = - 1075328; // You tell me it is time to leave this flesh. I did not understand until now. I thought: I can see my wife and my daughter, I can speak. Is this not life? But now, as I regard my reflection, I see what I have become. This only a mockery of life. Thank you for having the courage to show me the truth. For the love I bear my wife and daughter, I know now that I must pass beyond the veil. Will you return this basin to Aurelia? She will know by this that I am at rest. - RefusalMessage = - 1075330; // You wont take this back to my daughter? Please, I cannot leave until she knows I am at peace. - InProgressMessage = 1075331; // My daughter will be at my home, on the east side of the city. - CompletionMessage = - 1075332; // Thank goodness! Now we can honor my father for the great man he was while he lived, rather than the horror he became. - CompletionNotice = CompletionNoticeShort; - - Objectives.Add(new DeliverObjective(typeof(BasinOfCrystalClearWater), 1, "Basin of Crystal Clear Water", - typeof(Aurelia))); - - Rewards.Add(new ItemReward(1075304, typeof(MirrorOfPurification))); // Mirror of Purification - } - - public override bool IsChainTriggered => true; - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 2, "SkeletonOfSzandor"), new Point3D(1277, 3731, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 2, "SkeletonOfSzandor"), new Point3D(1277, 3731, 0), Map.Felucca); - } - } - - public class OddsAndEnds : MLQuest - { - public OddsAndEnds() - { - Activated = true; - Title = 1074354; // Odds and Ends - Description = - 1074677; // I've always been fascinated by primitive cultures -- especially the artifacts. I'm a collector, you see. I'm working on building my troglodyte display and I'm saddened to say that I'm short on examples of religion and superstition amongst the creatures. If you come across any primitive fetishes, I'd be happy to trade you something interesting for them. - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = - 1074678; // I don't really want to know where you get the primitive fetishes, as I can't support the destruction of their lifestyle and culture. That would be wrong. - CompletionMessage = 1074679; // Bravo! These fetishes are just what I needed. You've earned this reward. - - Objectives.Add(new CollectObjective(12, typeof(PrimitiveFetish), "Primitive Fetishes")); - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - public class EmbracingHumanity : MLQuest - { - public EmbracingHumanity() - { - Activated = true; - OneTimeOnly = true; // OSI has no limit or delay, VERY exploitable - Title = 1074349; // Embracing Humanity - Description = - 1074357; // Well, I don't mind saying it -- I'm flabbergasted! Absolutely astonished. I just heard that some elves want to convert themselves to humans through some magical process. My cousin Nedrick does whatever needs doing. I guess you could check it out for yourself if you're curious. Anyway, I wonder if you'll bring my cousin, Drithen, this here treat my wife baked up for him special. - RefusalMessage = 1074459; // That's okay, I'll find someone else to make the delivery. - InProgressMessage = 1074460; // If I knew where my cousin was, I'd make the delivery myself. - CompletionMessage = 1074461; // Oh, hello there. What do you have for me? - - Objectives.Add(new DeliverObjective(typeof(SpecialTreatForDrithen), 1, "treat for Drithen", typeof(Drithen))); - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - public class Aurelia : BaseCreature - { - [Constructible] - public Aurelia() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Architect's Daughter"; - Race = Race.Human; - BodyValue = 0x191; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Backpack()); - AddItem(new Sandals(Utility.RandomPinkHue())); - - if (Utility.RandomBool()) - AddItem(new Kilt(Utility.RandomPinkHue())); - else - AddItem(new Skirt(Utility.RandomPinkHue())); - - AddItem(new FancyShirt(Utility.RandomRedHue())); - } - - public Aurelia(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Aurelia"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Szandor")] - public class SkeletonOfSzandor : BaseCreature - { - [Constructible] - public SkeletonOfSzandor() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Late Architect"; - Hue = 0x83F2; // TODO: Random human hue? Why??? - Body = 0x32; - InitStats(100, 100, 25); - } - - public SkeletonOfSzandor(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Skeleton of Szandor"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; +using Server.Engines.Spawners; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Definitions +{ + public class Aemaeth1 : MLQuest + { + public Aemaeth1() + { + Activated = true; + Title = 1075321; // Aemaeth + Description = + 1075322; // My father died in an accident some months ago. My mother refused to accept his death. We had a little money set by, and she took it to a necromancer, who promised to restore my father to life. Well, he revived my father, all right, the cheat! Now my father is a walking corpse, a travesty . . . a monster. My mother is beside herself -- she won't eat, she can't sleep. I prayed at the shrine of Spirituality for guidance, and I must have fallen asleep. When I awoke, there was this basin of clear water. I cannot leave my mother, for I fear what she might do to herself. Could you take this to the graveyard, and give it to what is left of my father? + RefusalMessage = + 1075324; // Oh! Alright then. I hope someone comes along soon who can help me, or I dont know what will become of us. + InProgressMessage = + 1075325; // My father - or what remains of him - can be found in the graveyard northwest of the city. + CompletionMessage = 1075326; // What is this you give me? A basin of water? + CompletionNotice = CompletionNoticeShort; + + Objectives.Add( + new DeliverObjective( + typeof(BasinOfCrystalClearWater), + 1, + "Basin of Crystal Clear Water", + typeof(SkeletonOfSzandor) + ) + ); + + Rewards.Add(new DummyReward(1075323)); // Aurelia's gratitude. + } + + public override Type NextQuest => typeof(Aemaeth2); + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Aurelia"), new Point3D(1459, 3795, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Aurelia"), new Point3D(1459, 3795, 0), Map.Felucca); + } + } + + public class Aemaeth2 : MLQuest + { + public Aemaeth2() + { + Activated = true; + OneTimeOnly = true; + Title = 1075327; // Aemaeth + Description = + 1075328; // You tell me it is time to leave this flesh. I did not understand until now. I thought: I can see my wife and my daughter, I can speak. Is this not life? But now, as I regard my reflection, I see what I have become. This only a mockery of life. Thank you for having the courage to show me the truth. For the love I bear my wife and daughter, I know now that I must pass beyond the veil. Will you return this basin to Aurelia? She will know by this that I am at rest. + RefusalMessage = + 1075330; // You wont take this back to my daughter? Please, I cannot leave until she knows I am at peace. + InProgressMessage = 1075331; // My daughter will be at my home, on the east side of the city. + CompletionMessage = + 1075332; // Thank goodness! Now we can honor my father for the great man he was while he lived, rather than the horror he became. + CompletionNotice = CompletionNoticeShort; + + Objectives.Add( + new DeliverObjective( + typeof(BasinOfCrystalClearWater), + 1, + "Basin of Crystal Clear Water", + typeof(Aurelia) + ) + ); + + Rewards.Add(new ItemReward(1075304, typeof(MirrorOfPurification))); // Mirror of Purification + } + + public override bool IsChainTriggered => true; + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 2, "SkeletonOfSzandor"), new Point3D(1277, 3731, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 2, "SkeletonOfSzandor"), new Point3D(1277, 3731, 0), Map.Felucca); + } + } + + public class OddsAndEnds : MLQuest + { + public OddsAndEnds() + { + Activated = true; + Title = 1074354; // Odds and Ends + Description = + 1074677; // I've always been fascinated by primitive cultures -- especially the artifacts. I'm a collector, you see. I'm working on building my troglodyte display and I'm saddened to say that I'm short on examples of religion and superstition amongst the creatures. If you come across any primitive fetishes, I'd be happy to trade you something interesting for them. + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = + 1074678; // I don't really want to know where you get the primitive fetishes, as I can't support the destruction of their lifestyle and culture. That would be wrong. + CompletionMessage = 1074679; // Bravo! These fetishes are just what I needed. You've earned this reward. + + Objectives.Add(new CollectObjective(12, typeof(PrimitiveFetish), "Primitive Fetishes")); + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + public class EmbracingHumanity : MLQuest + { + public EmbracingHumanity() + { + Activated = true; + OneTimeOnly = true; // OSI has no limit or delay, VERY exploitable + Title = 1074349; // Embracing Humanity + Description = + 1074357; // Well, I don't mind saying it -- I'm flabbergasted! Absolutely astonished. I just heard that some elves want to convert themselves to humans through some magical process. My cousin Nedrick does whatever needs doing. I guess you could check it out for yourself if you're curious. Anyway, I wonder if you'll bring my cousin, Drithen, this here treat my wife baked up for him special. + RefusalMessage = 1074459; // That's okay, I'll find someone else to make the delivery. + InProgressMessage = 1074460; // If I knew where my cousin was, I'd make the delivery myself. + CompletionMessage = 1074461; // Oh, hello there. What do you have for me? + + Objectives.Add(new DeliverObjective(typeof(SpecialTreatForDrithen), 1, "treat for Drithen", typeof(Drithen))); + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + public class Aurelia : BaseCreature + { + [Constructible] + public Aurelia() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Architect's Daughter"; + Race = Race.Human; + BodyValue = 0x191; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Backpack()); + AddItem(new Sandals(Utility.RandomPinkHue())); + + if (Utility.RandomBool()) + AddItem(new Kilt(Utility.RandomPinkHue())); + else + AddItem(new Skirt(Utility.RandomPinkHue())); + + AddItem(new FancyShirt(Utility.RandomRedHue())); + } + + public Aurelia(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Aurelia"; + + 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(); + } + } + + [QuesterName("Szandor")] + public class SkeletonOfSzandor : BaseCreature + { + [Constructible] + public SkeletonOfSzandor() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Late Architect"; + Hue = 0x83F2; // TODO: Random human hue? Why??? + Body = 0x32; + InitStats(100, 100, 25); + } + + public SkeletonOfSzandor(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Skeleton of Szandor"; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Definitions/Heartwood.cs b/Projects/UOContent/Engines/MLQuests/Definitions/Heartwood.cs index f17f9ce89..6b58c50d6 100644 --- a/Projects/UOContent/Engines/MLQuests/Definitions/Heartwood.cs +++ b/Projects/UOContent/Engines/MLQuests/Definitions/Heartwood.cs @@ -1,4647 +1,4875 @@ -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; -using Server.Engines.Spawners; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Definitions -{ - public class TheyreBreedingLikeRabbits : MLQuest - { - public TheyreBreedingLikeRabbits() - { - Activated = true; - Title = 1072244; // They're Breeding Like Rabbits - Description = - 1072259; // Aaaahhhh! They're everywhere! Aaaaahhh! Ahem. Actually, friend, how do you feel about rabbits? Well, we're being overrun by them. We're finding fuzzy bunnies everywhere. Aaaaahhh! - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(Rabbit) }, "rabbits")); - - Rewards.Add(ItemReward.SmallBagOfTrinkets); - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Saril"), new Point3D(7075, 376, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Saril"), new Point3D(7075, 376, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Cailla"), new Point3D(7075, 377, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Cailla"), new Point3D(7075, 377, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Tamm"), new Point3D(7075, 378, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Tamm"), new Point3D(7075, 378, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 3, "Landy"), new Point3D(7089, 390, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 3, "Landy"), new Point3D(7089, 390, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Alejaha"), new Point3D(7043, 387, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Alejaha"), new Point3D(7043, 387, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 3, "Mielan"), new Point3D(7063, 350, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 3, "Mielan"), new Point3D(7063, 350, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Ciala"), new Point3D(7031, 411, 7), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Ciala"), new Point3D(7031, 411, 7), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Aniel"), new Point3D(7034, 412, 6), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Aniel"), new Point3D(7034, 412, 6), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Aulan"), new Point3D(6986, 340, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Aulan"), new Point3D(6986, 340, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Brinnae"), new Point3D(6996, 351, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Brinnae"), new Point3D(6996, 351, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Caelas"), new Point3D(7039, 390, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Caelas"), new Point3D(7039, 390, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Clehin"), new Point3D(7092, 390, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Clehin"), new Point3D(7092, 390, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Cloorne"), new Point3D(7010, 364, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Cloorne"), new Point3D(7010, 364, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Salaenih"), new Point3D(7009, 362, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Salaenih"), new Point3D(7009, 362, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Vilo"), new Point3D(7029, 377, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Vilo"), new Point3D(7029, 377, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Tholef"), new Point3D(6986, 386, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Tholef"), new Point3D(6986, 386, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Tillanil"), new Point3D(6987, 388, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Tillanil"), new Point3D(6987, 388, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Waelian"), new Point3D(6996, 381, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Waelian"), new Point3D(6996, 381, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Sleen"), new Point3D(6997, 381, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Sleen"), new Point3D(6997, 381, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Unoelil"), new Point3D(7010, 388, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Unoelil"), new Point3D(7010, 388, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Anolly"), new Point3D(7009, 388, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Anolly"), new Point3D(7009, 388, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Jusae"), new Point3D(7042, 377, 2), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Jusae"), new Point3D(7042, 377, 2), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Cillitha"), new Point3D(7043, 377, 2), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Cillitha"), new Point3D(7043, 377, 2), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Lohn"), new Point3D(7062, 410, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Lohn"), new Point3D(7062, 410, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Olla"), new Point3D(7063, 410, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Olla"), new Point3D(7063, 410, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Thallary"), new Point3D(7032, 439, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Thallary"), new Point3D(7032, 439, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Ahie"), new Point3D(7033, 440, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Ahie"), new Point3D(7033, 440, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Tyeelor"), new Point3D(7010, 364, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Tyeelor"), new Point3D(7010, 364, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Athailon"), new Point3D(7011, 365, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Athailon"), new Point3D(7011, 365, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderTaellia"), new Point3D(7038, 387, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderTaellia"), new Point3D(7038, 387, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderMallew"), new Point3D(7047, 390, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderMallew"), new Point3D(7047, 390, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderAbbein"), new Point3D(7043, 390, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderAbbein"), new Point3D(7043, 390, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderVicaie"), new Point3D(7054, 390, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderVicaie"), new Point3D(7054, 390, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderJothan"), new Point3D(7056, 383, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderJothan"), new Point3D(7056, 383, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "ElderAlethanian"), new Point3D(7056, 380, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "ElderAlethanian"), new Point3D(7056, 380, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Rebinil"), new Point3D(7089, 380, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Rebinil"), new Point3D(7089, 380, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Aluniol"), new Point3D(7089, 383, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Aluniol"), new Point3D(7089, 383, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Olaeni"), new Point3D(7080, 363, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Olaeni"), new Point3D(7080, 363, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Bolaevin"), new Point3D(7066, 351, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Bolaevin"), new Point3D(7066, 351, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "LorekeeperAneen"), new Point3D(7053, 337, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "LorekeeperAneen"), new Point3D(7053, 337, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Daelas"), new Point3D(7036, 412, 7), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Daelas"), new Point3D(7036, 412, 7), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Alelle"), new Point3D(7028, 406, 7), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Alelle"), new Point3D(7028, 406, 7), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "LorekeeperNillaen"), new Point3D(7061, 370, 14), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "LorekeeperNillaen"), new Point3D(7061, 370, 14), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "LorekeeperRyal"), new Point3D(7009, 375, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "LorekeeperRyal"), new Point3D(7009, 375, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Braen"), new Point3D(7081, 366, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Braen"), new Point3D(7081, 366, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderAcob"), new Point3D(7037, 387, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderAcob"), new Point3D(7037, 387, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "LorekeeperCalendor"), new Point3D(7062, 370, 14), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "LorekeeperCalendor"), new Point3D(7062, 370, 14), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "LorekeeperSiarra"), new Point3D(7051, 339, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "LorekeeperSiarra"), new Point3D(7051, 339, 0), Map.Felucca); - } - } - - public class TheyllEatAnything : MLQuest - { - public TheyllEatAnything() - { - Activated = true; - Title = 1072248; // They'll Eat Anything - Description = - 1072262; // Pork is the fruit of the land! You can barbeque it, boil it, bake it, sautee it. There's pork kebabs, pork creole, pork gumbo, pan fried, deep fried, stir fried. There's apple pork, peppered pork, pork soup, pork salad, pork and potatoes, pork burger, pork sandwich, pork stew, pork chops, pork loins, shredded pork. So, lets get some piggies butchered! - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(Pig) }, "pigs")); - - Rewards.Add(ItemReward.SmallBagOfTrinkets); - } - } - - public class NoGoodFishStealing : MLQuest - { - public NoGoodFishStealing() - { - Activated = true; - Title = 1072251; // No Good, Fish Stealing ... - Description = - 1072265; // Mighty creatures they are, aye. Fierce and strong, can't blame 'em for wanting to feed themselves an' all. Blame or no, they're eating all the fish up, so they got to go. Lend a hand? - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(Walrus) }, "walruses")); - - Rewards.Add(ItemReward.SmallBagOfTrinkets); - } - } - - public class AHeroInTheMaking : MLQuest - { - public AHeroInTheMaking() - { - Activated = true; - Title = 1072246; // A Hero in the Making - Description = - 1072257; // Are you new around here? Well, nevermind that. You look ready for adventure, I can see the gleam of glory in your eyes! Nothing is more valiant, more noble, more praiseworthy than mongbat slaying. - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(Mongbat) }, "mongbats")); - - Rewards.Add(ItemReward.SmallBagOfTrinkets); - } - } - - public class BullfightingSortOf : MLQuest - { - public BullfightingSortOf() - { - Activated = true; - Title = 1072247; // Bullfighting ... Sort Of - Description = - 1072254; // You there! Yes, you. Listen, I've got a little problem on my hands, but a brave, bold hero like yourself should find it a snap to solve. Bottom line -- we need some of the bulls in the area culled. You're welcome to any meat or hides, and of course, I'll give you a nice reward. - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(Bull) }, "bulls")); - - Rewards.Add(ItemReward.SmallBagOfTrinkets); - } - } - - public class AFineFeast : MLQuest - { - public AFineFeast() - { - Activated = true; - Title = 1072243; // A Fine Feast. - Description = - 1072261; // Mmm, I do love mutton! It's slaughtering time again and my usual hirelings haven't turned up. I've arranged for a butcher to come by and cut everything up but the basic sheep killing part I haven't gotten worked out yet. Are you up for the task? - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(Sheep) }, "sheep")); - - Rewards.Add(ItemReward.SmallBagOfTrinkets); - } - } - - public class ForcedMigration : MLQuest - { - public ForcedMigration() - { - Activated = true; - Title = 1072250; // Forced Migration - Description = - 1072264; // Chirp chirp ... tweet chirp. Tra la la. Bloody birds and their blasted noise. I've tried everything but they just won't stop that infernal clamor. Return me to blessed silence and I'll make it worth your while. - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(Bird) }, "birds")); - - Rewards.Add(ItemReward.SmallBagOfTrinkets); - } - } - - public class FilthyPests : MLQuest - { - public FilthyPests() - { - Activated = true; - Title = 1072242; // Filthy Pests! - Description = - 1072253; // They're everywhere I tell you! They crawl in the walls, they scurry in the bushes. Disgusting critters. Say ... I don't suppose you're up for some sewer rat killing? Sewer rats now, not any other kind of squeaker will do. - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(SewerRat) }, "sewer rats")); - - Rewards.Add(ItemReward.SmallBagOfTrinkets); - } - } - - public class DeadManWalking : MLQuest - { - public DeadManWalking() - { - Activated = true; - Title = 1072983; // Dead Man Walking - Description = - 1073009; // Why? I ask you why? They walk around after they're put in the ground. It's just wrong in so many ways. Put them to proper rest, I beg you. I'll find some way to pay you for the kindness. Just kill five zombies and five skeletons. - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(5, new[] { typeof(Zombie) }, "zombies")); - Objectives.Add(new KillObjective(5, new[] { typeof(Skeleton) }, "skeletons")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class KingOfBears : MLQuest - { - public KingOfBears() - { - Activated = true; - Title = 1072996; // King of Bears - Description = - 1073030; // A pity really. With the balance of nature awry, we have no choice but to accept the responsibility of making it all right. It's all a part of the circle of life, after all. So, yes, the grizzly bears are running rampant. There are far too many in the region. Will you shoulder your obligations as a higher life form? - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(GrizzlyBear) }, "grizzly bears")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class Specimens : MLQuest - { - public Specimens() - { - Activated = true; - Title = 1072999; // Specimens - Description = - 1073032; // I admire them, you know. The solen have their place -- regimented, organized. They're fascinating to watch with their constant strife between red and black. I can't help but want to stir things up from time to time. And that's where you come in. Kill either twelve red or twelve black solen workers and let's see what happens next! - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - ObjectiveType = ObjectiveType.Any; - - Objectives.Add(new KillObjective(12, new[] { typeof(RedSolenWorker) }, "red solen workers")); - Objectives.Add(new KillObjective(12, new[] { typeof(BlackSolenWorker) }, "black solen workers")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class Spirits : MLQuest - { - public Spirits() - { - Activated = true; - Title = 1073076; // Spirits - Description = - 1073566; // It is a piteous thing when the dead continue to walk the earth. Restless spirits are known to inhabit these parts, taking the lives of unwary travelers. It is about time a hero put the dead back in their graves. I'm sure such a hero would be justly rewarded. - RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. - InProgressMessage = 1073586; // The restless spirts still walk -- you must kill 15 of them. - - Objectives.Add(new KillObjective(15, new[] { typeof(Spectre), typeof(Shade), typeof(Wraith) }, - "spectres or shades or wraiths")); - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - public class RollTheBones : MLQuest - { - public RollTheBones() - { - Activated = true; - Title = 1073002; // Roll the Bones - Description = - 1073011; // Why? I ask you why? They walk around after they're put in the ground. It's just wrong in so many ways. Put them to proper rest, I beg you. I'll find some way to pay you for the kindness. Just kill eight patchwork skeletons. - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(8, new[] { typeof(PatchworkSkeleton) }, "patchwork skeletons")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class ItsAGhastlyJob : MLQuest - { - public ItsAGhastlyJob() - { - Activated = true; - Title = 1073008; // It's a Ghastly Job - Description = - 1073012; // Why? I ask you why? They walk around after they're put in the ground. It's just wrong in so many ways. Put them to proper rest, I beg you. I'll find some way to pay you for the kindness. Just kill twelve ghouls. - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(12, new[] { typeof(Ghoul) }, "ghouls")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class Troglodytes : MLQuest - { - public Troglodytes() - { - Activated = true; - Title = 1074688; // Troglodytes! - Description = - 1074689; // Oh nevermind, you don't look capable of my task afterall. Haha! What was I thinking - you could never handle killing troglodytes. It'd be suicide. What? I don't know, I don't want to be responsible ... well okay if you're really sure? - RefusalMessage = 1074690; // Probably the wiser course of action. - InProgressMessage = 1074691; // You still need to kill those troglodytes, remember? - - Objectives.Add(new KillObjective(12, new[] { typeof(Troglodyte) }, "troglodytes")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class UnholyKnights : MLQuest - { - public UnholyKnights() - { - Activated = true; - Title = 1073075; // Unholy Knights - Description = - 1073565; // Please, hear me kind traveler. You know when a knight falls, sometimes they are cursed to roam the earth as undead mockeries of their former glory? That is too grim a fate for even any knight to suffer! Please, put them out of their misery. I will offer you what payment I can if you will end the torment of these undead wretches. - RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. - InProgressMessage = 1073585; // Your task is not done. Continue putting the Skeleton and Bone Knights to rest. - - Objectives.Add(new KillObjective(16, new[] { typeof(BoneKnight), typeof(SkeletalKnight) }, - "bone knights or skeletal knights")); - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - public class AFeatherInYerCap : MLQuest - { - public AFeatherInYerCap() - { - Activated = true; - Title = 1074738; // A Feather in Yer Cap - Description = - 1074737; // I've seen how you strut about, as if you were something special. I have some news for you, you don't impress me at all. It's not enough to have a fancy hat you know. That may impress people in the big city, but not here. If you want a reputation you have to climb a mountain, slay some great beast, and then write about it. Trust me, it's a long process. The first step is doing a great feat. If I were you, I'd go pluck a feather from the harpy Saliva, that would give you a good start. - RefusalMessage = 1074736; // The path to greatness isn't for everyone obviously. - InProgressMessage = - 1074735; // If you're going to get anywhere in the adventuring game, you have to take some risks. A harpy, well, it's bad, but it's not a dragon. - CompletionMessage = 1074734; // The hero returns from the glorious battle and - oh, such a small feather? - - Objectives.Add(new CollectObjective(1, typeof(SalivasFeather), "Saliva's Feather")); - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - public class ATaleOfTail : MLQuest - { - public ATaleOfTail() - { - Activated = true; - Title = 1074726; // A Tale of Tail - Description = - 1074727; // I've heard of you, adventurer. Your reputation is impressive, and now I'll put it to the test. This is not something I ask lightly, for this task is fraught with danger, but it is vital. Seek out the vile hydra Abscess, slay it, and return to me with it's tail. - RefusalMessage = 1074728; // Well, the beast will still be there when you are ready I suppose. - InProgressMessage = - 1074729; // Em, I thought I had explained already. Abscess, the hydra, you know? Lots of heads but just the one tail. I need the tail. I have my reasons. Go go go. - CompletionMessage = - 1074730; // Ah, the tail. You did it! You know the rumours about dried ground hydra tail powder are all true? Thank you so much! - - Objectives.Add(new CollectObjective(1, typeof(AbscessTail), "Abscess' Tail")); - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - public class ATrogAndHisDog : MLQuest - { - public ATrogAndHisDog() - { - Activated = true; - Title = 1074681; // A Trog and His Dog - Description = - 1074680; // I don't know if you can handle it, but I'll give you a go at it. Troglodyte chief - name of Lurg and his mangy wolf pet need killing. Do the deed and I'll reward you. - RefusalMessage = 1074655; // Perhaps I thought too highly of you. - InProgressMessage = - 1074682; // The trog chief and his mutt should be easy enough to find. Just kill them and report back. Easy enough. - CompletionMessage = 1074683; // Not half bad. Here's your prize. - - Objectives.Add(new KillObjective(1, new[] { typeof(Lurg) }, "Lurg")); - Objectives.Add(new KillObjective(1, new[] { typeof(Grobu) }, "Grobu")); - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - } - - public class Overpopulation : MLQuest - { - public Overpopulation() - { - Activated = true; - Title = 1072252; // Overpopulation - Description = - 1072267; // I just can't bear it any longer. Sure, it's my job to thin the deer out so they don't overeat the area and starve themselves come winter time. Sure, I know we killed off the predators that would do this naturally so now we have to make up for it. But they're so graceful and innocent. I just can't do it. Will you? - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(Hind) }, "hinds")); - - Rewards.Add(ItemReward.SmallBagOfTrinkets); - } - } - - public class WildBoarCull : MLQuest - { - public WildBoarCull() - { - Activated = true; - Title = 1072245; // Wild Boar Cull - Description = - 1072260; // A pity really. With the balance of nature awry, we have no choice but to accept the responsibility of making it all right. It's all a part of the circle of life, after all. So, yes, the boars are running rampant. There are far too many in the region. Will you shoulder your obligations as a higher life form? - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(Boar) }, "boars")); - - Rewards.Add(ItemReward.SmallBagOfTrinkets); - } - } - - public class ItsElemental : MLQuest - { - public ItsElemental() - { - Activated = true; - Title = 1073089; // It's Elemental - Description = - 1073579; // The universe is all about balance my friend. Tip one end, you must balance the other. That's why I must ask you to kill not just one kind of elemental, but three kinds. Snuff out some Fire, douse a few Water, and crush some Earth elementals and I'll pay you for your trouble. - RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. - InProgressMessage = 1073599; // Four of each, that's all I ask. Water, earth and fire. - - Objectives.Add(new KillObjective(4, new[] { typeof(FireElemental) }, "fire elementals")); - Objectives.Add(new KillObjective(4, new[] { typeof(WaterElemental) }, "water elementals")); - Objectives.Add(new KillObjective(4, new[] { typeof(EarthElemental) }, "earth elementals")); - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - public class CircleOfLife : MLQuest - { - public CircleOfLife() - { - Activated = true; - Title = 1073656; // Circle of Life - Description = - 1073695; // There's been a bumper crop of evil with the Bog Things in these parts, my friend. Though they are foul creatures, they are also most fecund. Slay one and you make the land more fertile. Even better, slay several and I will give you whatever coin I can spare. - RefusalMessage = 1073733; // Perhaps you'll change your mind and return at some point. - InProgressMessage = 1073736; // Continue to seek and kill the Bog Things. - - Objectives.Add(new KillObjective(8, new[] { typeof(BogThing) }, "bog things")); - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - } - - public class DustToDust : MLQuest - { - public DustToDust() - { - Activated = true; - Title = 1073074; // Dust to Dust - Description = - 1073564; // You want to hear about trouble? I got trouble. How's angry piles of granite walking around for trouble? Maybe they don't like the mining, maybe it's the farming. I don't know. All I know is someone's got to turn them back to potting soil. And it'd be worth a pretty penny to the soul that does it. - RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. - InProgressMessage = 1073584; // You got rocks in your head? I said to kill 12 earth elementals, okay? - - Objectives.Add(new KillObjective(12, new[] { typeof(EarthElemental) }, "earth elementals")); - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - public class CreepyCrawlies : MLQuest - { - public CreepyCrawlies() - { - Activated = true; - Title = 1072987; // Creepy Crawlies - Description = - 1073016; // Disgusting! The way they scuttle on those hairy legs just makes me want to gag. I hate spiders! Rid the world of twelve and I'll find something nice to give you in thanks. - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(12, new[] { typeof(GiantSpider) }, "giant spiders")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class VoraciousPlants : MLQuest - { - public VoraciousPlants() - { - Activated = true; - Title = 1073001; // Voracious Plants - Description = - 1073024; // I bet you can't tangle with those nasty plants ... say eight corpsers and two swamp tentacles! I bet they're too much for you. You may as well confess you can't ... - RefusalMessage = 1073019; // Hahahaha! I knew it! - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(8, new[] { typeof(Corpser) }, "corpsers")); - Objectives.Add(new KillObjective(2, new[] { typeof(SwampTentacle) }, "swamp tentacles")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class GibberJabber : MLQuest - { - public GibberJabber() - { - Activated = true; - Title = 1073004; // Gibber Jabber - Description = - 1073024; // I bet you can't kill ... ten gibberlings! I bet they're too much for you. You may as well confess you can't ... - RefusalMessage = 1073019; // Hahahaha! I knew it! - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(Gibberling) }, "gibberlings")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class AnimatedMonstrosity : MLQuest - { - public AnimatedMonstrosity() - { - Activated = true; - Title = 1072990; // Animated Monstrosity - Description = - 1073020; // I bet you can't kill ... say twelve ... flesh golems! I bet they're too much for you. You may as well confess you can't ... - RefusalMessage = 1073019; // Hahahaha! I knew it! - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(12, new[] { typeof(FleshGolem) }, "flesh golems")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class BirdsOfAFeather : MLQuest - { - public BirdsOfAFeather() - { - Activated = true; - Title = 1073007; // Birds of a Feather - Description = - 1073022; // I bet you can't kill ... ten harpies! I bet they're too much for you. You may as well confess you can't ... - RefusalMessage = 1073019; // Hahahaha! I knew it! - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(Harpy) }, "harpies")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class Frightmares : MLQuest - { - public Frightmares() - { - Activated = true; - Title = 1073000; // Frightmares - Description = - 1073036; // I bet you can't handle ten plague spawns! I bet they're too much for you. You may as well confess you can't ... - RefusalMessage = 1073019; // Hahahaha! I knew it! - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(PlagueSpawn) }, "plague spawns")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class MoltenReptiles : MLQuest - { - public MoltenReptiles() - { - Activated = true; - Title = 1072989; // Molten Reptiles - Description = - 1073018; // I bet you can't kill ... say ten ... lava lizards! I bet they're too much for you. You may as well confess you can't ... - RefusalMessage = 1073019; // Hahahaha! I knew it! - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(LavaLizard) }, "lava lizards")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class BloodyNuisance : MLQuest - { - public BloodyNuisance() - { - Activated = true; - Title = 1072992; // Bloody Nuisance - Description = - 1073021; // I bet you can't kill ... ten gore fiends! I bet they're too much for you. You may as well confess you can't ... - RefusalMessage = 1073019; // Hahahaha! I knew it! - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(GoreFiend) }, "gore fiends")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class BloodSuckers : MLQuest - { - public BloodSuckers() - { - Activated = true; - Title = 1072997; // Blood Suckers - Description = - 1073025; // I bet you can't tangle with those bloodsuckers ... say around ten vampire bats! I bet they're too much for you. You may as well confess you can't ... - RefusalMessage = 1073019; // Hahahaha! I knew it! - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(VampireBat) }, "vampire bats")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class TheAfterlife : MLQuest - { - public TheAfterlife() - { - Activated = true; - Title = 1073073; // The Afterlife - Description = - 1073563; // Nobody told me about the Mummy's Curse. How was I supposed to know you shouldn't disturb the tombs? Oh, sure, now all I hear about is the curse of the vengeful dead. I'll tell you what - make a few of these mummies go away and we'll keep this between you and me. - RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. - InProgressMessage = 1073583; // Uh, I don't think you're quite done killing Mummies yet. - - Objectives.Add(new KillObjective(15, new[] { typeof(Mummy) }, "mummies")); - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - public class ForkedTongue : MLQuest - { - public ForkedTongue() - { - Activated = true; - Title = 1073655; // Forked Tongue - Description = - 1073694; // I must implore you, brave traveler, to do battle with the vile reptiles which haunt these parts. Those hideous abominations, the Ophidians, are a blight across the land. If you were able to put down a host of the scaly warriors, the Knights or the Avengers, I would forever be in your debt. - RefusalMessage = 1073733; // Perhaps you'll change your mind and return at some point. - InProgressMessage = 1073735; // Have you killed the Ophidian Knights or Avengers? - - Objectives.Add(new KillObjective(10, new[] { typeof(OphidianKnight) }, - "ophidian avengers or ophidian knight-errants")); - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - } - - public class ImpishDelights : MLQuest - { - public ImpishDelights() - { - Activated = true; - Title = 1073077; // Impish Delights - Description = - 1073567; // Imps! Do you hear me? Imps! They're everywhere! They're in everything! Oh, don't be fooled by their size - they vicious little devils! Half-sized evil incarnate, they are! Somebody needs to send them back to where they came from, if you know what I mean. - RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. - InProgressMessage = - 1073587; // Don't let the little devils scare you! You kill 12 imps - then we'll talk reward. - - Objectives.Add(new KillObjective(12, new[] { typeof(Imp) }, "imps")); - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - public class ThreeWishes : MLQuest - { - public ThreeWishes() - { - Activated = true; - Title = 1073660; // Three Wishes - Description = - 1073699; // If I had but one wish, it would be to rid myself of these dread Efreet! Fire and ash, they are cunning and deadly! You look a brave soul - would you be interested in earning a rich reward for slaughtering a few of the smoky devils? - RefusalMessage = 1073733; // Perhaps you'll change your mind and return at some point. - InProgressMessage = 1073740; // Those smoky devils, the Efreets, are still about. - - Objectives.Add(new KillObjective(8, new[] { typeof(Efreet) }, "efreets")); - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - } - - public class EvilEye : MLQuest - { - public EvilEye() - { - Activated = true; - Title = 1073084; // Evil Eye - Description = - 1073574; // Kind traveler, hear my plea. You know of the evil orbs? The wrathful eyes? Some call them gazers? They must be a nest nearby, for they are tormenting us poor folk. We need to drive back their numbers. But we are not strong enough to face such horrors ourselves, we need a true hero. - RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. - InProgressMessage = 1073594; // Have you annihilated a dozen Gazers yet, kind traveler? - - Objectives.Add(new KillObjective(12, new[] { typeof(Gazer) }, "gazers")); - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - public class GargoylesWrath : MLQuest - { - public GargoylesWrath() - { - Activated = true; - Title = 1073658; // Gargoyle's Wrath - Description = - 1073697; // It is regretable that the Gargoyles insist upon warring with us. Their Enforcers attack men on sight, despite all efforts at reason. To help maintain order in this region, I have been authorized to encourage bounty hunters to reduce their numbers. Eradicate their number and I will reward you handsomely. - RefusalMessage = 1073733; // Perhaps you'll change your mind and return at some point. - InProgressMessage = 1073738; // I won't be able to pay you until you've gotten enough Gargoyle Enforcers. - - Objectives.Add(new KillObjective(6, new[] { typeof(GargoyleEnforcer) }, "gargoyle enforcers")); - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - } - - public class UndeadMages : MLQuest - { - public UndeadMages() - { - Activated = true; - Title = 1073080; // Undead Mages - Description = - 1073570; // Why must the dead plague the living? With their foul necromancy and dark sorceries, the undead menace the countryside. I fear what will happen if no one is strong enough to face these nightmare sorcerers and thin their numbers. - RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. - InProgressMessage = 1073590; // Surely, a brave soul like yourself can kill 10 Bone Magi and Skeletal Mages? - - Objectives.Add(new KillObjective(10, new[] { typeof(BoneMagi), typeof(SkeletalMage) }, - "bone mages or skeletal mages")); - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - public class FriendlyNeighborhoodSpiderkiller : MLQuest - { - public FriendlyNeighborhoodSpiderkiller() - { - Activated = true; - Title = 1073662; // Friendly Neighborhood Spider-killer - Description = - 1073701; // They aren't called Dread Spiders because they're fluffy and cuddly now, are they? No, there's nothing appealing about those wretches so I sure wouldn't lose any sleep if you were to exterminate a few. I'd even part with a generous amount of gold, I would. - RefusalMessage = 1073733; // Perhaps you'll change your mind and return at some point. - InProgressMessage = 1073742; // Dread Spiders? I say keep exterminating the arachnid vermin. - - Objectives.Add(new KillObjective(8, new[] { typeof(DreadSpider) }, "dread spiders")); - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - } - - public class MongbatMenace : MLQuest - { - public MongbatMenace() - { - Activated = true; - Title = 1073003; // Mongbat Menace! - Description = - 1073033; // I imagine you don't know about the mongbats. Well, you may think you do, but I know more than just about anyone. You see they come in two varieties ... the stronger and the weaker. Either way, they're a menace. Exterminate ten of the weaker ones and four of the stronger and I'll pay you an honest wage. - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(Mongbat) }, "mongbats")); - Objectives.Add(new KillObjective(4, new[] { typeof(GreaterMongbat) }, "greater mongbats")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class StirringTheNest : MLQuest - { - public StirringTheNest() - { - Activated = true; - Title = 1073087; // Stirring the Nest - Description = - 1073577; // Were you the sort of child that enjoyed knocking over anthills? Well, perhaps you'd like to try something a little bigger? There's a Solen nest nearby and I bet if you killed a queen or two, it would be quite the sight to behold. I'd even pay to see that - what do you say? - RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. - InProgressMessage = 1073597; // Dead Solen Queens isn't too much to ask, is it? - - ObjectiveType = ObjectiveType.Any; - - Objectives.Add(new KillObjective(3, new[] { typeof(RedSolenQueen) }, "red solen queens")); - Objectives.Add(new KillObjective(3, new[] { typeof(BlackSolenQueen) }, "black solen queens")); - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - public class WarriorCaste : MLQuest - { - public WarriorCaste() - { - Activated = true; - Title = 1073078; // Warrior Caste - Description = - 1073568; // The Terathan are an aggressive species. Left unchecked, they will swarm across our lands. And where will that leave us? Compost in the hive, that's what! Stop them, stop them cold my friend. Kill their warriors and you'll check their movement, that is certain. - RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. - InProgressMessage = - 1073588; // Unless you kill at least 10 Terathan Warriors, you won't have any impact on their hive. - - Objectives.Add(new KillObjective(10, new[] { typeof(TerathanWarrior) }, "terathan warriors")); - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - public class BigWorms : MLQuest - { - public BigWorms() - { - Activated = true; - Title = 1073088; // Big Worms - Description = - 1073578; // It makes no sense! Cold blooded serpents cannot live in the ice! It's a biological impossibility! They are an abomination against reason! Please, I beg you - kill them! Make them disappear for me! Do this and I will reward you. - RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. - InProgressMessage = 1073598; // You wouldn't try and just pretend you murdered 10 Giant Ice Worms, would you? - - Objectives.Add(new KillObjective(10, new[] { typeof(IceSerpent) }, "giant ice serpents")); - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - public class OrcishElite : MLQuest - { - public OrcishElite() - { - Activated = true; - Title = 1073081; // Orcish Elite - Description = - 1073571; // Foul brutes! No one loves an orc, but some of them are worse than the rest. Their Captains and their Bombers, for instance, they're the worst of the lot. Kill a few of those, and the rest are just a rabble. Exterminate a few of them and you'll make the world a sunnier place, don't you know. - RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. - InProgressMessage = - 1073591; // The only good orc is a dead orc - and 4 dead Captains and 6 dead Bombers is even better! - - Objectives.Add(new KillObjective(6, new[] { typeof(OrcBomber) }, "orc bombers")); - Objectives.Add(new KillObjective(4, new[] { typeof(OrcCaptain) }, "orc captain")); - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - public class ThinningTheHerd : MLQuest - { - public ThinningTheHerd() - { - Activated = true; - Title = 1072249; // Thinning the Herd - Description = - 1072263; // Psst! Hey ... psst! Listen, I need some help here but it's gotta be hush hush. I don't want THEM to know I'm onto them. They watch me. I've seen them, but they don't know that I know what I know. You know? Anyway, I need you to scare them off by killing a few of them. That'll send a clear message that I won't suffer goats watching me! - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(Goat) }, "goats")); - - Rewards.Add(ItemReward.SmallBagOfTrinkets); - } - } - - public class Squishy : MLQuest - { - public Squishy() - { - Activated = true; - Title = 1072998; // Squishy - Description = - 1073031; // Have you ever seen what a slime can do to good gear? Well, it's not pretty, let me tell you! If you take on my task to destroy twelve of them, bear that in mind. They'll corrode your equipment faster than anything. - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(12, new[] { typeof(Slime) }, "slimes")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class OrcSlaying : MLQuest - { - public OrcSlaying() - { - Activated = true; - Title = 1072986; // Orc Slaying - Description = - 1073015; // Those green-skinned freaks have run off with more of my livestock. I want an orc scout killed for each sheep I lost and an orc for each chicken. So that's four orc scouts and eight orcs I'll pay you to slay. - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(8, new[] { typeof(Orc) }, "orcs")); - // TODO: This needs to be orc scouts but they aren't in the SVN - Objectives.Add(new KillObjective(4, new[] { typeof(OrcishLord) }, "orcish lords")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class ABigJob : MLQuest - { - public ABigJob() - { - Activated = true; - Title = 1072988; // A Big Job - Description = - 1073017; // It's a big job but you look to be just the adventurer to do it! I'm so glad you came by ... I'm paying well for the death of five ogres and five ettins. - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(5, new[] { typeof(Ogre) }, "ogres")); - Objectives.Add(new KillObjective(5, new[] { typeof(Ettin) }, "ettins")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class TrollingForTrolls : MLQuest - { - public TrollingForTrolls() - { - Activated = true; - Title = 1072985; // Trolling for Trolls - Description = - 1073014; // They may not be bright, but they're incredibly destructive. Kill off ten trolls and I'll consider it a favor done for me. - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(Troll) }, "trolls")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class ColdHearted : MLQuest - { - public ColdHearted() - { - Activated = true; - Title = 1072991; // Cold Hearted - Description = - 1073027; // It's a big job but you look to be just the adventurer to do it! I'm so glad you came by ... I'm paying well for the death of six giant ice serpents and six frost spiders. Hop to it, if you're so inclined. - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(6, new[] { typeof(IceSerpent) }, "giant ice serpents")); - Objectives.Add(new KillObjective(6, new[] { typeof(FrostSpider) }, "frost spiders")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class ForkedTongues : MLQuest - { - public ForkedTongues() - { - Activated = true; - Title = 1072984; // Forked Tongues - Description = - 1073013; // You can't trust them, you know. Lizardmen I mean. They have forked tongues ... and you know what that means. Exterminate ten of them and I'll reward you. - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(Lizardman) }, "lizardmen")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class ShakingThingsUp : MLQuest - { - public ShakingThingsUp() - { - Activated = true; - Title = 1073083; // Shaking Things Up - Description = - 1073573; // A Solen hive is a fascinating piece of ecology. It's put together like a finely crafted clock. Who knows what happens if you remove something? So let's find out. Exterminate a few of the warriors and I'll make it worth your while. - RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. - InProgressMessage = - 1073593; // I don't think you've gotten their attention yet -- you need to kill at least 10 Solen Warriors. - - ObjectiveType = ObjectiveType.Any; - - Objectives.Add(new KillObjective(10, new[] { typeof(RedSolenWarrior) }, "red solen warriors")); - Objectives.Add(new KillObjective(10, new[] { typeof(BlackSolenWarrior) }, "black solen warriors")); - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - public class Arachnophobia : MLQuest - { - public Arachnophobia() - { - Activated = true; - Title = 1073079; // Arachnophobia - Description = - 1073569; // I've seen them hiding in their webs among the woods. Glassy eyes, spindly legs, poisonous fangs. Monsters, I say! Deadly horrors, these black widows. Someone must exterminate the abominations! If only I could find a worthy hero for such a task, then I could give them this considerable reward. - RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. - InProgressMessage = - 1073589; // You've got a good start, but to stop the black-eyed fiends, you need to kill a dozen. - - Objectives.Add(new KillObjective(12, new[] { typeof(GiantBlackWidow) }, "giant black widows")); - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - public class MiniSwampThing : MLQuest - { - public MiniSwampThing() - { - Activated = true; - Title = 1073072; // Mini Swamp Thing - Description = - 1073562; // Some say killing a boggling brings good luck. I don't place much stock in old wives' tales, but I can say a few dead bogglings would certainly be lucky for me! Help me out and I can reward you for your efforts. - RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. - InProgressMessage = 1073582; // Go back and kill all 20 bogglings! - - Objectives.Add(new KillObjective(12, new[] { typeof(Bogling) }, "boglings")); - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - public class ThePerilsOfFarming : MLQuest - { - public ThePerilsOfFarming() - { - Activated = true; - Title = 1073664; // The Perils of Farming - Description = - 1073703; // I should be trimming back the vegetation here, but something nasty has taken root. Viscious vines I can't go near. If there's any hope of getting things under control, some one's going to need to destroy a few of those Whipping Vines. Someone strong and fast and tough. - RefusalMessage = 1073733; // Perhaps you'll change your mind and return at some point. - InProgressMessage = 1073744; // How are farmers supposed to work with these Whipping Vines around? - - Objectives.Add(new KillObjective(15, new[] { typeof(WhippingVine) }, "whipping vines")); - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - } - - public class IndustriousAsAnAntLion : MLQuest - { - public IndustriousAsAnAntLion() - { - Activated = true; - Title = 1073665; // Industrious as an Ant Lion - Description = - 1073704; // Ants are industrious and Lions are noble so who'd think an Ant Lion would be such a problem? The Ant Lion's have been causing mindless destruction in these parts. I suppose it's just how ants are. But I need you to help eliminate the infestation. Would you be willing to help for a bit of reward? - RefusalMessage = 1073733; // Perhaps you'll change your mind and return at some point. - InProgressMessage = 1073745; // Please, rid us of the Ant Lion infestation. - - Objectives.Add(new KillObjective(12, new[] { typeof(AntLion) }, "ant lions")); - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - } - - public class UnholyConstruct : MLQuest - { - public UnholyConstruct() - { - Activated = true; - Title = 1073666; // Unholy Construct - Description = - 1073705; // They're unholy, I say. Golems, a walking mockery of all life, born of blackest magic. They're not truly alive, so destroying them isn't a crime, it's a service. A service I will gladly pay for. - RefusalMessage = 1073733; // Perhaps you'll change your mind and return at some point. - InProgressMessage = 1073746; // The unholy brutes, the Golems, must be smited! - CompletionMessage = 1073787; // Reduced those Golems to component parts? Good, then -- you deserve this reward! - - Objectives.Add(new KillObjective(10, new[] { typeof(Golem) }, "golems")); - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - } - - public class AChillInTheAir : MLQuest - { - public AChillInTheAir() - { - Activated = true; - Title = 1073663; // A Chill in the Air - Description = - 1073702; // Feel that chill in the air? It means an icy death for the unwary, for deadly Ice Elementals are about. Who knows what magic summoned them, what's important now is getting rid of them. I don't have much, but I'll give all I can if you'd only stop the cold-hearted monsters. - RefusalMessage = 1073733; // Perhaps you'll change your mind and return at some point. - InProgressMessage = 1073746; // The chill won't lift until you eradicate a few Ice Elemenals. - - Objectives.Add(new KillObjective(15, new[] { typeof(IceElemental) }, "ice elementals")); - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - } - - public class TheKingOfClothing : MLQuest - { - public TheKingOfClothing() - { - Activated = true; - HasRestartDelay = true; - Title = 1073902; // The King of Clothing - Description = - 1074092; // I have heard noble tales of a fine and proud human garment. An article of clothing fit for both man and god alike. It is called a "kilt" I believe? Could you fetch for me some of these kilts so I that I might revel in their majesty and glory? - RefusalMessage = 1073921; // I will patiently await your reconsideration. - InProgressMessage = 1073948; // I will be in your debt if you bring me kilts. - CompletionMessage = 1073974; // I say truly - that is a magnificent garment! You have more than earned a reward. - - Objectives.Add(new CollectObjective(10, typeof(Kilt), 1025431)); // kilt - - Rewards.Add(ItemReward.TailorSatchel); - } - } - - public class ThePuffyShirt : MLQuest - { - public ThePuffyShirt() - { - Activated = true; - HasRestartDelay = true; - Title = 1073903; // The Puffy Shirt - Description = - 1074093; // We elves believe that beauty is expressed in all things, including the garments we wear. I wish to understand more about human aesthetics, so please kind traveler - could you bring to me magnificent examples of human fancy shirts? For my thanks, I could teach you more about the beauty of elven vestements. - RefusalMessage = 1073921; // I will patiently await your reconsideration. - InProgressMessage = 1073949; // I will be in your debt if you bring me fancy shirts. - CompletionMessage = 1073973; // I appreciate your service. Now, see what elven hands can create. - - Objectives.Add(new CollectObjective(10, typeof(FancyShirt), 1027933)); // fancy shirt - - Rewards.Add(ItemReward.TailorSatchel); - } - } - - public class FromTheGaultierCollection : MLQuest - { - public FromTheGaultierCollection() - { - Activated = true; - HasRestartDelay = true; - Title = 1073905; // From the Gaultier Collection - Description = - 1074095; // It is my understanding, the females of humankind actually wear on certain occasions a studded bustier? This is not simply a fanciful tale? Remarkable! It sounds hideously uncomfortable as well as ludicrously impracticle. But perhaps, I simply do not understand the nuances of human clothing. Perhaps, I need to see such a studded bustier for myself? - RefusalMessage = 1073921; // I will patiently await your reconsideration. - InProgressMessage = 1073951; // I will be in your debt if you bring me studded bustiers. - CompletionMessage = 1073976; // Truly, it is worse than I feared. Still, I appreciate your efforts on my behalf. - - Objectives.Add(new CollectObjective(10, typeof(StuddedBustierArms), 1027180)); // studded bustier - - Rewards.Add(ItemReward.TailorSatchel); - } - } - - public class HauteCouture : MLQuest - { - public HauteCouture() - { - Activated = true; - HasRestartDelay = true; - Title = 1073901; // Hâute Couture - Description = - 1074091; // Most human apparel is interesting to elven eyes. But there is one garment - the flower garland - which sounds very elven indeed. Could I see how a human crafts such an object of beauty? In exchange, I could share with you the wonders of elven garments. - RefusalMessage = 1073921; // I will patiently await your reconsideration. - InProgressMessage = 1073947; // I will be in your debt if you bring me flower garlands. - CompletionMessage = 1073973; // I appreciate your service. Now, see what elven hands can create. - - Objectives.Add(new CollectObjective(10, typeof(FlowerGarland), 1028965)); // flower garland - - Rewards.Add(ItemReward.TailorSatchel); - } - } - - public class TheSongOfTheWind : MLQuest - { - public TheSongOfTheWind() - { - Activated = true; - HasRestartDelay = true; - Title = 1073910; // The Song of the Wind - Description = - 1074100; // To give voice to the passing wind, this is an idea worthy of an elf! Friend, bring me some of the amazing fancy wind chimes so that I may listen to the song of the passing breeze. Do this, and I will share with you treasured elven secrets. - RefusalMessage = 1073921; // I will patiently await your reconsideration. - InProgressMessage = 1073956; // I will be in your debt if you bring me fancy wind chimes. - CompletionMessage = 1073980; // Such a delightful sound, I think I shall never tire of it. - - Objectives.Add(new CollectObjective(10, typeof(FancyWindChimes), "fancy wind chimes")); - - Rewards.Add(ItemReward.TinkerSatchel); - } - } - - public class BeerGoggles : MLQuest - { - public BeerGoggles() - { - Activated = true; - HasRestartDelay = true; - Title = 1073895; // Beer Goggles - Description = - 1074085; // Oh, the deviltry! Why would humans lock their precious liquors inside a wooden coffin? I understand I need a "keg tap" to access the golden brew within such a wooden abomination. Perhaps, if you could bring me such a tap, we could share a drink and I could teach you. - RefusalMessage = 1073921; // I will patiently await your reconsideration. - InProgressMessage = 1073941; // I will be in your debt if you bring me barrel taps. - CompletionMessage = 1073971; // My thanks for your service. Here is something for you to enjoy. - - Objectives.Add(new CollectObjective(25, typeof(BarrelTap), 1024100)); // barrel tap - - Rewards.Add(ItemReward.TinkerSatchel); - } - } - - public class MessageInABottleQuest : MLQuest - { - public MessageInABottleQuest() - { - Activated = true; - HasRestartDelay = true; - Title = 1073894; // Message in a Bottle - Description = - 1074084; // We elves are interested in trading our wines with humans but we understand human usually trade such brew in strange transparent bottles. If you could provide some of these empty glass bottles, I might engage in a bit of elven winemaking. - RefusalMessage = 1073921; // I will patiently await your reconsideration. - InProgressMessage = 1073940; // I will be in your debt if you bring me empty bottles. - CompletionMessage = 1073971; // My thanks for your service. Here is something for you to enjoy. - - Objectives.Add(new CollectObjective(50, typeof(Bottle), 1023854)); // empty bottle - - Rewards.Add(ItemReward.TinkerSatchel); - } - } - - public class NecessitysMother : MLQuest - { - public NecessitysMother() - { - Activated = true; - HasRestartDelay = true; - Title = 1073906; // Necessity's Mother - Description = - 1074096; // What a thing, this human need to tinker. It seems there is no end to what might be produced with a set of Tinker's Tools. Who knows what an elf might build with some? Could you obtain some tinker's tools and bring them to me? In exchange, I offer you elven lore and knowledge. - RefusalMessage = 1073921; // I will patiently await your reconsideration. - InProgressMessage = 1073952; // I will be in your debt if you bring me tinker's tools. - CompletionMessage = 1073977; // Now, I shall see what an elf can invent! - - Objectives.Add(new CollectObjective(10, typeof(TinkerTools), 1027868)); // tinker's tools - - Rewards.Add(ItemReward.TinkerSatchel); - } - } - - public class TickTock : MLQuest - { - public TickTock() - { - Activated = true; - HasRestartDelay = true; - Title = 1073907; // Tick Tock - Description = - 1074097; // Elves find it remarkable the human preoccupation with the passage of time. To have built instruments to try and capture time -- it is a fascinating notion. I would like to see how a clock is put together. Maybe you could provide some clocks for my experimentation? - RefusalMessage = 1073921; // I will patiently await your reconsideration. - InProgressMessage = 1073953; // I will be in your debt if you bring me clocks. - CompletionMessage = 1073978; // Enjoy my thanks for your service. - - Objectives.Add(new CollectObjective(10, typeof(Clock), 1024171)); // clock - - Rewards.Add(ItemReward.TinkerSatchel); - } - } - - public class ReptilianDentist : MLQuest - { - public ReptilianDentist() - { - Activated = true; - Title = 1074280; // Reptilian Dentist - Description = - 1074710; // I'm working on a striking necklace -- something really unique -- and I know just what I need to finish it up. A huge fang! Won't that catch the eye? I would like to employ you to find me such an item, perhaps a snake would make the ideal donor. I'll make it worth your while, of course. - RefusalMessage = 1074723; // I understand. I don't like snakes much either. They're so creepy. - InProgressMessage = - 1074722; // Those really big snakes like swamps, I've heard. You might try the blighted grove. - CompletionMessage = 1074721; // Do you have it? *gasp* What a tooth! Here � I must get right to work. - - Objectives.Add(new CollectObjective(1, typeof(CoilsFang), "coil's fang")); - - Rewards.Add(ItemReward.TinkerSatchel); - } - } - - public class StopHarpingOnMe : MLQuest - { - public StopHarpingOnMe() - { - Activated = true; - HasRestartDelay = true; - Title = 1073881; // Stop Harping on Me - Description = - 1074071; // Humans artistry can be a remarkable thing. For instance, I have heard of a wonderful instrument which creates the most melodious of music. A lap harp. I would be ever so grateful if I could examine one in person. - RefusalMessage = 1073921; // I will patiently await your reconsideration. - InProgressMessage = 1073927; // I will be in your debt if you bring me lap harp. - CompletionMessage = 1073969; // My thanks for your service. Now, I will show you something of elven carpentry. - - Objectives.Add(new CollectObjective(20, typeof(LapHarp), 1023762)); // lap harp - - Rewards.Add(ItemReward.CarpentrySatchel); - } - } - - public class TheFarEye : MLQuest - { - public TheFarEye() - { - Activated = true; - HasRestartDelay = true; - Title = 1073908; // The Far Eye - Description = - 1074098; // The wonders of human invention! Turning sand and metal into a far-seeing eye! This is something I must experience for myself. Bring me some of these spyglasses friend human. - RefusalMessage = 1073921; // I will patiently await your reconsideration. - InProgressMessage = 1073954; // I will be in your debt if you bring me spyglasses. - CompletionMessage = 1073978; // Enjoy my thanks for your service. - - Objectives.Add(new CollectObjective(20, typeof(Spyglass), 1025365)); // spyglass - - Rewards.Add(ItemReward.TinkerSatchel); - } - } - - public class LethalDarts : MLQuest - { - public LethalDarts() - { - Activated = true; - HasRestartDelay = true; - Title = 1073876; // Lethal Darts - Description = - 1074066; // We elves are no strangers to archery but I would be interested in learning whether there is anything to learn from the human approach. I would gladly trade you something I have if you could teach me of the deadly crossbow bolt. - RefusalMessage = 1073921; // I will patiently await your reconsideration. - InProgressMessage = 1073922; // I will be in your debt if you bring me crossbow bolts. - CompletionMessage = 1073968; // My thanks for your service. Now, I shall teach you of elven archery. - CompletionNotice = CompletionNoticeCraft; - - Objectives.Add(new CollectObjective(10, typeof(Bolt), 1027163)); // crossbow bolt - - Rewards.Add(ItemReward.FletchingSatchel); - } - } - - public class ASimpleBow : MLQuest - { - public ASimpleBow() - { - Activated = true; - HasRestartDelay = true; - Title = 1073877; // A Simple Bow - Description = - 1074067; // I wish to try a bow crafted in the human style. Is it possible for you to bring me such a weapon? I would be happy to return this favor. - RefusalMessage = 1073921; // I will patiently await your reconsideration. - InProgressMessage = 1073923; // I will be in your debt if you bring me bows. - CompletionMessage = 1073968; // My thanks for your service. Now, I shall teach you of elven archery. - CompletionNotice = CompletionNoticeCraft; - - Objectives.Add(new CollectObjective(10, typeof(Bow), 1025041)); // bow - - Rewards.Add(ItemReward.FletchingSatchel); - } - } - - public class IngeniousArcheryPartOne : MLQuest - { - public IngeniousArcheryPartOne() - { - Activated = true; - HasRestartDelay = true; - Title = 1073878; // Ingenious Archery, Part I - Description = - 1074068; // I have heard of a curious type of bow, you call it a "crossbow". It sounds fascinating and I would very much like to examine one closely. Would you be able to obtain such an instrument for me? - RefusalMessage = 1073921; // I will patiently await your reconsideration. - InProgressMessage = 1073924; // I will be in your debt if you bring me crossbows. - CompletionMessage = 1073968; // My thanks for your service. Now, I shall teach you of elven archery. - CompletionNotice = CompletionNoticeCraft; - - Objectives.Add(new CollectObjective(10, typeof(Crossbow), 1023919)); // crossbow - - Rewards.Add(ItemReward.FletchingSatchel); - } - } - - public class IngeniousArcheryPartTwo : MLQuest - { - public IngeniousArcheryPartTwo() - { - Activated = true; - HasRestartDelay = true; - Title = 1073879; // Ingenious Archery, Part II - Description = - 1074069; // These human "crossbows" are complex and clever. The "heavy crossbow" is a remarkable instrument of war. I am interested in seeing one up close, if you could arrange for one to make its way to my hands. - RefusalMessage = 1073921; // I will patiently await your reconsideration. - InProgressMessage = 1073925; // I will be in your debt if you bring me heavy crossbows. - CompletionMessage = 1073968; // My thanks for your service. Now, I shall teach you of elven archery. - CompletionNotice = CompletionNoticeCraft; - - Objectives.Add(new CollectObjective(8, typeof(HeavyCrossbow), 1025116)); // heavy crossbow - - Rewards.Add(ItemReward.FletchingSatchel); - } - } - - public class IngeniousArcheryPartThree : MLQuest - { - public IngeniousArcheryPartThree() - { - Activated = true; - HasRestartDelay = true; - Title = 1073880; // Ingenious Archery, Part III - Description = - 1074070; // My friend, I am in search of a device, a instrument of remarkable human ingenuity. It is a repeating crossbow. If you were to obtain such a device, I would gladly reveal to you some of the secrets of elven craftsmanship. - RefusalMessage = 1073921; // I will patiently await your reconsideration. - InProgressMessage = 1073926; // I will be in your debt if you bring me repeating crossbows. - CompletionMessage = 1073968; // My thanks for your service. Now, I shall teach you of elven archery. - CompletionNotice = CompletionNoticeCraft; - - Objectives.Add(new CollectObjective(10, typeof(RepeatingCrossbow), 1029923)); // repeating crossbow - - Rewards.Add(ItemReward.FletchingSatchel); - } - } - - public class ScaleArmor : MLQuest - { - public ScaleArmor() - { - Activated = true; - Title = 1074711; // Scale Armor - Description = - 1074712; // Here's what I need ... there are some creatures called hydra, fearsome beasts, whose scales are especially suitable for a new sort of armor that I'm developing. I need a few such pieces and then some supple alligator skin for the backing. I'm going to need a really large piece that's shaped just right ... the tail I think would do nicely. I appreciate your help. - RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. - InProgressMessage = - 1074724; // Hydras have been spotted in the Blighted Grove. You won't get those scales without getting your feet wet, I'm afraid. - CompletionMessage = 1074725; // I can't wait to get to work now that you've returned with my scales. - - Objectives.Add(new CollectObjective(1, typeof(ThrashersTail), "Thrasher's Tail")); - Objectives.Add(new CollectObjective(10, typeof(HydraScale), "Hydra Scales")); - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - public class CutsBothWays : MLQuest - { - public CutsBothWays() - { - Activated = true; - HasRestartDelay = true; - Title = 1073913; // Cuts Both Ways - Description = - 1074103; // What would you say is a typical human instrument of war? Is a broadsword a typical example? I wish to see more of such human weapons, so I would gladly trade elven knowledge for human steel. - RefusalMessage = 1073921; // I will patiently await your reconsideration. - InProgressMessage = 1073959; // I will be in your debt if you bring me broadswords. - CompletionMessage = 1073978; // Enjoy my thanks for your service. - - Objectives.Add(new CollectObjective(12, typeof(Broadsword), 1023934)); // broadsword - - Rewards.Add(ItemReward.BlacksmithSatchel); - } - } - - public class DragonProtection : MLQuest - { - public DragonProtection() - { - Activated = true; - HasRestartDelay = true; - Title = 1073915; // Dragon Protection - Description = - 1074105; // Mankind, I am told, knows how to take the scales of a terrible dragon and forge them into powerful armor. Such a feat of craftsmanship! I would give anything to view such a creation - I would even teach some of the prize secrets of the elven people. - RefusalMessage = 1073921; // I will patiently await your reconsideration. - InProgressMessage = 1073961; // I will be in your debt if you bring me dragon armor. - CompletionMessage = 1073978; // Enjoy my thanks for your service. - - Objectives.Add(new CollectObjective(10, typeof(DragonHelm), 1029797)); // dragon helm - - Rewards.Add(ItemReward.BlacksmithSatchel); - } - } - - public class NothingFancy : MLQuest - { - public NothingFancy() - { - Activated = true; - HasRestartDelay = true; - Title = 1073911; // Nothing Fancy - Description = - 1074101; // I am curious to see the results of human blacksmithing. To examine the care and quality of a simple item. Perhaps, a simple bascinet helmet? Yes, indeed -- if you could bring to me some bascinet helmets, I would demonstrate my gratitude. - RefusalMessage = 1073921; // I will patiently await your reconsideration. - InProgressMessage = 1073957; // I will be in your debt if you bring me bascinets. - CompletionMessage = 1073978; // Enjoy my thanks for your service. - - Objectives.Add(new CollectObjective(15, typeof(Bascinet), 1025132)); // bascinet - - Rewards.Add(ItemReward.BlacksmithSatchel); - } - } - - public class TheBulwark : MLQuest - { - public TheBulwark() - { - Activated = true; - HasRestartDelay = true; - Title = 1073912; // The Bulwark - Description = - 1074102; // The clank of human iron and steel is strange to elven ears. For instance, the metallic heater shield which human warriors carry into battle. It is odd to an elf, but nevertheless intriguing. Tell me friend, could you bring me such an example of human smithing skill? - RefusalMessage = 1073921; // I will patiently await your reconsideration. - InProgressMessage = 1073958; // I will be in your debt if you bring me heater shields. - CompletionMessage = 1073978; // Enjoy my thanks for your service. - - Objectives.Add(new CollectObjective(10, typeof(HeaterShield), 1027030)); // heater shield - - Rewards.Add(ItemReward.BlacksmithSatchel); - } - } - - public class ArchSupport : MLQuest - { - public ArchSupport() - { - Activated = true; - HasRestartDelay = true; - Title = 1073882; // Arch Support - Description = - 1074072; // How clever humans are - to understand the need of feet to rest from time to time! Imagine creating a special stool just for weary toes. I would like to examine and learn the secret of their making. Would you bring me some foot stools to examine? - RefusalMessage = 1073921; // I will patiently await your reconsideration. - InProgressMessage = 1073928; // I will be in your debt if you bring me foot stools. - CompletionMessage = 1073969; // My thanks for your service. Now, I will show you something of elven carpentry. - - Objectives.Add(new CollectObjective(10, typeof(FootStool), 1022910)); // foot stool - - Rewards.Add(ItemReward.CarpentrySatchel); - } - } - - public class ParoxysmusSuccubi : MLQuest - { - public ParoxysmusSuccubi() - { - Activated = true; - Title = 1073067; // Paroxysmus' Succubi - Description = - 1074696; // The succubi that have congregated within the sinkhole to worship Paroxysmus pose a tremendous danger. Will you enter the lair and see to their destruction? - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(3, new[] { typeof(Succubus) }, "succubi", - new QuestArea(1074806, "The Palace of Paroxysmus"))); // The Palace of Paroxysmus - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - } - - public class ParoxysmusMoloch : MLQuest - { - public ParoxysmusMoloch() - { - Activated = true; - Title = 1073068; // Paroxysmus' Moloch - Description = - 1074695; // The moloch daemons that have congregated to worship Paroxysmus pose a tremendous danger. Will you enter the lair and see to their destruction? - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(3, new[] { typeof(Moloch) }, "molochs", - new QuestArea(1074806, "The Palace of Paroxysmus"))); // The Palace of Paroxysmus - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - } - - public class ParoxysmusDaemons : MLQuest - { - public ParoxysmusDaemons() - { - Activated = true; - Title = 1073069; // Paroxysmus' Daemons - Description = - 1074694; // The daemons that have congregated to worship Paroxysmus pose a tremendous danger. Will you enter the lair and see to their destruction? - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(Daemon) }, "daemons", - new QuestArea(1074806, "The Palace of Paroxysmus"))); // The Palace of Paroxysmus - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - } - - public class ParoxysmusArcaneDaemons : MLQuest - { - public ParoxysmusArcaneDaemons() - { - Activated = true; - Title = 1073070; // Paroxysmus' Arcane Daemons - Description = - 1074697; // The arcane daemons that worship Paroxysmus pose a tremendous danger. Will you enter the lair and see to their destruction? - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(ArcaneDaemon) }, "arcane daemons", - new QuestArea(1074806, "The Palace of Paroxysmus"))); // The Palace of Paroxysmus - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - } - - public class CausticCombo : MLQuest - { - public CausticCombo() - { - Activated = true; - Title = 1073062; // Caustic Combo - Description = - 1074693; // Vile creatures have exited the sinkhole and begun terrorizing the surrounding area. The demons are bad enough, but the elementals are an abomination, their poisons seeping into the fertile ground here. Will you enter the sinkhole and put a stop to their depredations? - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(3, new[] { typeof(PoisonElemental) }, "poison elementals", - new QuestArea(1074806, "The Palace of Paroxysmus"))); // The Palace of Paroxysmus - Objectives.Add(new KillObjective(6, new[] { typeof(AcidElemental) }, "acid elementals", - new QuestArea(1074806, "The Palace of Paroxysmus"))); // The Palace of Paroxysmus - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - } - - public class PlagueLord : MLQuest - { - public PlagueLord() - { - Activated = true; - Title = 1073061; // Plague Lord - Description = - 1074692; // Some of the most horrific creatures have slithered out of the sinkhole there and begun terrorizing the surrounding area. The plague creatures are one of the most destruction of the minions of Paroxysmus. Are you willing to do something about them? - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(PlagueSpawn) }, "plague spawns", - new QuestArea(1074806, "The Palace of Paroxysmus"))); // The Palace of Paroxysmus - Objectives.Add(new KillObjective(3, new[] { typeof(PlagueBeast) }, "plague beasts", - new QuestArea(1074806, "The Palace of Paroxysmus"))); // The Palace of Paroxysmus - Objectives.Add(new KillObjective(1, new[] { typeof(PlagueBeastLord) }, "plague beast lord", - new QuestArea(1074806, "The Palace of Paroxysmus"))); // The Palace of Paroxysmus - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - } - - public class GlassyFoe : MLQuest - { - public GlassyFoe() - { - Activated = true; - Title = 1073055; // Glassy Foe - Description = - 1074669; // Good, you're here. The presence of a twisted creature deep under the earth near Nu'Jelm has corrupted the natural growth of crystals in that region. They've become infused with the twisting energy - they've come to a sort of life. This is an abomination that festers within Sosaria. You must eradicate the crystal lattice seekers. - RefusalMessage = 1074671; // These abominations must not be permitted to fester! - InProgressMessage = 1074672; // You must not waste time. Do not suffer these crystalline abominations to live. - CompletionMessage = 1074673; // You have done well. Enjoy this reward. - - Objectives.Add(new KillObjective(5, new[] { typeof(CrystalLatticeSeeker) }, "crystal lattice seekers", - new QuestArea(1074805, "The Prism of Light"))); // The Prism of Light - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - } - - public class DaemonicPrism : MLQuest - { - public DaemonicPrism() - { - Activated = true; - Title = 1073053; // Daemonic Prism - Description = - 1074668; // Good, you're here. The presence of a twisted creature deep under the earth near Nu'Jelm has corrupted the natural growth of crystals in that region. They've become infused with the twisting energy - they've come to a sort of life. This is an abomination that festers within Sosaria. You must eradicate the crystal daemons. - RefusalMessage = 1074671; // These abominations must not be permitted to fester! - InProgressMessage = 1074672; // You must not waste time. Do not suffer these crystalline abominations to live. - CompletionMessage = 1074673; // You have done well. Enjoy this reward. - - Objectives.Add(new KillObjective(3, new[] { typeof(CrystalDaemon) }, "crystal daemons", - new QuestArea(1074805, "The Prism of Light"))); // The Prism of Light - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - } - - public class Hailstorm : MLQuest - { - public Hailstorm() - { - Activated = true; - Title = 1073057; // Hailstorm - Description = - 1074670; // Good, you're here. The presence of a twisted creature deep under the earth near Nu'Jelm has corrupted the natural growth of crystals in that region. They've become infused with the twisting energy - they've come to a sort of life. This is an abomination that festers within Sosaria. You must eradicate the crystal vortices. - RefusalMessage = 1074671; // These abominations must not be permitted to fester! - InProgressMessage = 1074672; // You must not waste time. Do not suffer these crystalline abominations to live. - CompletionMessage = 1074673; // You have done well. Enjoy this reward. - - Objectives.Add(new KillObjective(8, new[] { typeof(CrystalVortex) }, "crystal vortices", - new QuestArea(1074805, "The Prism of Light"))); // The Prism of Light - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - } - - /* TODO: Uncomment when Crystal Hydra is added - public class HowManyHeads : MLQuest - { - public HowManyHeads() - { - Activated = true; - Title = 1073050; // How Many Heads? - Description = 1074674; // Good, you're here. The presence of a twisted creature deep under the earth near Nu'Jelm has corrupted the natural growth of crystals in that region. They've become infused with the twisting energy - they've come to a sort of life. This is an abomination that festers within Sosaria. You must eradicate the crystal hydras. - RefusalMessage = 1074671; // These abominations must not be permitted to fester! - InProgressMessage = 1074672; // You must not waste time. Do not suffer these crystalline abominations to live. - CompletionMessage = 1074673; // You have done well. Enjoy this reward. - - Objectives.Add( new KillObjective( 3, new Type[] { typeof( CrystalHydra ) }, "crystal hydras", new QuestArea( 1074805, "The Prism of Light" ) ) ); // The Prism of Light - - Rewards.Add( ItemReward.LargeBagOfTreasure ); - } - } - */ - - /* TODO: Uncomment when Dreadhorn is added - public class DreadhornQuest : MLQuest - { - public DreadhornQuest() - { - Activated = true; - Title = 1074645; // Dreadhorn - Description = 1074646; // Can you comprehend it? I cannot, I confess. The most pristine and perfect Lord of Sosaria has fallen prey to the blight. From the depths of my heart I mourn his corruption; my thoughts are filled with pity for this glorious creature now tainted. And my blood boils with fury at those responsible for the innocent creature's undoing. Will you find Dread Horn, as he is now called, and free him from this misery? - RefusalMessage = 1074647; // How can you not feel as I do? - InProgressMessage = 1074648; // The lush and fertile land where Dread Horn now lives is twisted and tainted, a result of his corruption. The fey folk have sealed the land off through their magics, but you can enter through an enchanted mushroom fairy circle. - CompletionMessage = 1074649; // Thank you. I haven't the words to express my gratitude. - - Objectives.Add( new KillObjective( 1, new Type[] { typeof( DreadHorn ) }, "dread horn" ) ); - - Rewards.Add( ItemReward.RewardStrongbox ); - } - } - */ - - /* TODO: Uncomment when SerpentsFangHighExecutioner, TigersClawThief and DragonsFlameGrandMage are added - public class NewLeadership : MLQuest - { - public NewLeadership() - { - Activated = true; - Title = 1072905; // New Leadership - Description = 1072963; // I have a task for you ... adventurer. Will you risk all to win great renown? The Black Order is organized into three sects, each with their own speciality. The Dragon's Flame serves the will of the Grand Mage, the Tiger's Claw answers to the Master Thief, and the Serpent's Fang kills at the direction of the High Executioner. Slay all three and you will strike the order a devastating blow! - RefusalMessage = 1072973; // I do not fault your decision. - InProgressMessage = 1072974; // Once you gain entrance into The Citadel, you will need to move cautiously to find the sect leaders. - - Objectives.Add( new KillObjective( 1, new Type[] { typeof( SerpentsFangHighExecutioner ) }, "serpent's fang high executioner", new QuestArea( 1074804, "The Citadel" ) ) ); // The Citadel - Objectives.Add( new KillObjective( 1, new Type[] { typeof( TigersClawThief ) }, "tiger's claw thief", new QuestArea( 1074804, "The Citadel" ) ) ); // The Citadel - Objectives.Add( new KillObjective( 1, new Type[] { typeof( DragonsFlameGrandMage ) }, "dragon's flame mage", new QuestArea( 1074804, "The Citadel" ) ) ); // The Citadel - - Rewards.Add( ItemReward.RewardStrongbox ); - } - } - */ - - /* TODO: Uncomment when SerpentsFangAssassin is added - public class ExAssassins : MLQuest - { - public ExAssassins() - { - Activated = true; - Title = 1072917; // Ex-Assassins - Description = 1072969; // The Serpent's Fang sect members have gone too far! Express to them my displeasure by slaying ten of them. But remember, I do not condone war on women, so I will only accept the deaths of men, human and elf. - RefusalMessage = 1072979; // As you wish. - InProgressMessage = 1072980; // The Black Order's fortress home is well hidden. Legend has it that a humble fishing village disguises the magical portal. - - // TODO: This has to be MALES only! - Objectives.Add( new KillObjective( 10, new Type[] { typeof( SerpentsFangAssassin ) }, "male serpent's fang assassins", new QuestArea( 1074804, "The Citadel" ) ) ); // The Citadel - - Rewards.Add( ItemReward.BagOfTreasure ); - } - } - */ - - /* TODO: Uncomment when DragonsFlameMage is added - public class ExtinguishingTheFlame : MLQuest - { - public ExtinguishingTheFlame() - { - Activated = true; - Title = 1072911; // Extinguishing the Flame - Description = 1072966; // The Dragon's Flame sect members have gone too far! Express to them my displeasure by slaying ten of them. But remember, I do not condone war on women, so I will only accept the deaths of men, human or elf. Either race will do, I care not for the shape of their ears. Yes, this action will properly make clear my disapproval and has a pleasing harmony. - RefusalMessage = 1072979; // As you wish. - InProgressMessage = 1072980; // The Black Order's fortress home is well hidden. Legend has it that a humble fishing village disguises the magical portal. - - // TODO: This has to be MALES only! - Objectives.Add( new KillObjective( 10, new Type[] { typeof( DragonsFlameMage ) }, "male dragon's flame mages", new QuestArea( 1074804, "The Citadel" ) ) ); // The Citadel - - Rewards.Add( ItemReward.BagOfTreasure ); - } - } - */ - - public class DeathToTheNinja : MLQuest - { - public DeathToTheNinja() - { - Activated = true; - Title = 1072913; // Death to the Ninja! - Description = - 1072966; // I wish to make a statement of censure against the elite ninjas of the Black Order. Deliver, in the strongest manner, my disdain. But do not make war on women, even those that take arms against you. It is not ... fitting. - RefusalMessage = 1072979; // As you wish. - InProgressMessage = - 1072980; // The Black Order's fortress home is well hidden. Legend has it that a humble fishing village disguises the magical portal. - - // TODO: Verify that this has to be males only (as per the description) - Objectives.Add(new KillObjective(10, new[] { typeof(EliteNinja) }, "elite ninjas", - new QuestArea(1074804, "The Citadel"))); // The Citadel - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - /* TODO: Uncomment when TigersClawThief is added - public class CrimeAndPunishment : MLQuest - { - public CrimeAndPunishment() - { - Activated = true; - Title = 1072914; // Crime and Punishment - Description = 1072968; // The Tiger's Claw sect members have gone too far! Express to them my displeasure by slaying ten of them. But remember, I do not condone war on women, so I will only accept the deaths of men, human and elf. - RefusalMessage = 1072979; // As you wish. - InProgressMessage = 1072980; // The Black Order's fortress home is well hidden. Legend has it that a humble fishing village disguises the magical portal. - - // TODO: This has to be MALES only! - Objectives.Add( new KillObjective( 10, new Type[] { typeof( TigersClawThief ) }, "male tiger's claw thieves", new QuestArea( 1074804, "The Citadel" ) ) ); // The Citadel - - Rewards.Add( ItemReward.BagOfTreasure ); - } - } - */ - - /* TODO: Uncomment when ShimmeringEffusion is added - public class AllThatGlittersIsNotGood : MLQuest - { - public AllThatGlittersIsNotGood() - { - Activated = true; - Title = 1073048; // All That Glitters is Not Good - Description = 1074654; // The most incredible tale has reached my ears! Deep within the bowels of Sosaria, somewhere under the city of Nu'Jelm, a twisted creature feeds. What created this abomination, no one knows ... though there is some speculation that the fumbling initial efforts to open the portal to The Heartwood, brought it into existence. Regardless of it's origin, it must be destroyed before it damages Sosaria. Will you undertake this quest? - RefusalMessage = 1074655; // Perhaps I thought too highly of you. - InProgressMessage = 1074656; // An explorer discovered the cave system under Nu'Jelm. He made multiple trips into the place bringing back fascinating crystals and artifacts that suggested the hollow place in Sosaria was inhabited by other creatures at some point. You'll need to follow in his footsteps to find this abomination and destroy it. - CompletionMessage = 1074657; // I am overjoyed with your efforts! Your devotion to Sosaria is noted and appreciated. - - Objectives.Add( new KillObjective( 1, new Type[] { typeof( ShimmeringEffusion ) }, "shimmering effusion" ) ); - - Rewards.Add( ItemReward.RewardStrongbox ); - } - } - */ - - [QuesterName("Saril (The Heartwood)")] - public class Saril : BaseCreature - { - [Constructible] - public Saril() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the guard"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenBoots()); - AddItem(new WoodlandLegs()); - AddItem(new WoodlandArms()); - AddItem(new WoodlandBelt()); - AddItem(new WingedHelm()); - AddItem(new FemaleElvenPlateChest()); - AddItem(new RadiantScimitar()); - } - - public Saril(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Saril"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074186, // Come here, I have a task. - 1074183)); // You there! I have a job for you. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Cailla (The Heartwood)")] - public class Cailla : BaseCreature - { - [Constructible] - public Cailla() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the guard"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenBoots()); - AddItem(new HidePants()); - AddItem(new HidePauldrons()); - AddItem(new HideGloves()); - AddItem(new WoodlandBelt()); - AddItem(new RavenHelm()); - AddItem(new HideFemaleChest()); - AddItem(new MagicalShortbow()); - } - - public Cailla(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Cailla"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074187, // Want a job? - 1074210)); // Hi.� Looking for something to do? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Tamm (The Heartwood)")] - public class Tamm : BaseCreature - { - [Constructible] - public Tamm() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the guard"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenBoots()); - AddItem(new HidePants()); - AddItem(new HidePauldrons()); - AddItem(new WingedHelm()); - AddItem(new HideChest()); - AddItem(new ElvenCompositeLongbow()); - } - - public Tamm(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Tamm"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074213, // Hey buddy.� Looking for work? - 1074187)); // Want a job? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Landy (The Heartwood)")] - public class Landy : BaseCreature - { - [Constructible] - public Landy() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the soil nurturer"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new Sandals(Utility.RandomYellowHue())); - AddItem(new ShortPants(Utility.RandomYellowHue())); - AddItem(new Tunic(Utility.RandomYellowHue())); - - Item gloves = new LeafGloves(); - gloves.Hue = Utility.RandomYellowHue(); - AddItem(gloves); - } - - public Landy(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Landy"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074211, // I could use some help. - 1074218)); // Hey!� I want to talk to you, now. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Elder Alejaha (The Heartwood)")] - public class Alejaha : BaseCreature - { - [Constructible] - public Alejaha() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the wise"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new Sandals(Utility.RandomYellowHue())); - AddItem(new ElvenShirt(Utility.RandomYellowHue())); - AddItem(new GemmedCirclet()); - AddItem(new Cloak(Utility.RandomBrightHue())); - - if (Utility.RandomBool()) - AddItem(new Kilt(0x387)); - else - AddItem(new Skirt(0x387)); - } - - public Alejaha(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Elder Alejaha"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1074223); // Have you done it yet?� Oh, I haven�t told you, have I? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Mielan (The Heartwood)")] - public class Mielan : BaseCreature - { - [Constructible] - public Mielan() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the arcanist"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenBoots(0x901)); - AddItem(new ElvenShirt(0x56)); - AddItem(new GemmedCirclet()); - AddItem(new ElvenPants(0x901)); - } - - public Mielan(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Mielan"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074219, // Hello there, can I have a moment of your time? - 1074223)); // Have you done it yet?� Oh, I haven�t told you, have I? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Ciala (The Heartwood)")] - public class Ciala : BaseCreature - { - [Constructible] - public Ciala() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the arborist"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new Skirt(Utility.RandomBlueHue())); - AddItem(new ElvenShirt(Utility.RandomYellowHue())); - AddItem(new RoyalCirclet()); - - if (Utility.RandomBool()) - AddItem(new Boots(Utility.RandomYellowHue())); - else - AddItem(new ThighBoots(Utility.RandomYellowHue())); - } - - public Ciala(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Ciala"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074206, // Excuse me please traveler, might I have a little of your time? - 1074186)); // Come here, I have a task. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Aniel (The Heartwood)")] - public class Aniel : BaseCreature - { - [Constructible] - public Aniel() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the arborist"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenPants(0x901)); - AddItem(new LeafChest()); - AddItem(new HalfApron(Utility.RandomYellowHue())); - AddItem(new ElvenBoots(0x901)); - } - - public Aniel(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Aniel"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074220, // May I call you friend?� I have a favor to beg of you. - 1074222)); // Could I trouble you for some assistance? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Aulan (The Heartwood)")] - public class Aulan : BaseCreature - { - [Constructible] - public Aulan() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the expeditionist"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - Item item; - - item = new ElvenBoots(); - item.Hue = Utility.RandomYellowHue(); - AddItem(item); - - AddItem(new ElvenPants(Utility.RandomGreenHue())); - AddItem(new Cloak(Utility.RandomGreenHue())); - AddItem(new Circlet()); - - item = new HideChest(); - item.Hue = Utility.RandomYellowHue(); - AddItem(item); - - item = new HideGloves(); - item.Hue = Utility.RandomYellowHue(); - AddItem(item); - } - - public Aulan(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Aulan"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074188, // Weakling! You are not up to the task I have. - 1074191, // Just keep walking away!� I thought so. Coward!� I�ll bite your legs off! - 1074195)); // You there, in the stupid hat! Come here. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Brinnae (The Heartwood)")] - public class Brinnae : BaseCreature - { - [Constructible] - public Brinnae() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the wise"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new ElvenBoots()); - AddItem(new FemaleLeafChest()); - AddItem(new LeafArms()); - AddItem(new HidePants()); - AddItem(new ElvenCompositeLongbow()); - } - - public Brinnae(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Brinnae"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074212, // *yawn* You busy? - 1074210)); // Hi.� Looking for something to do? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Elder Caelas (The Heartwood)")] - public class Caelas : BaseCreature - { - [Constructible] - public Caelas() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the wise"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenBoots(0x1BB)); - AddItem(new MaleElvenRobe(0x489)); - AddItem(new Cloak(0x718)); - AddItem(new RoyalCirclet()); - } - - public Caelas(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Elder Caelas"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074204, // Greetings seeker.� I have an urgent matter for you, if you are willing. - 1074201)); // Waste not a minute! There�s work to be done. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Clehin (The Heartwood)")] - public class Clehin : BaseCreature - { - [Constructible] - public Clehin() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the soil nurturer"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenBoots()); - AddItem(new ElvenShirt()); - AddItem(new LeafTonlet()); - } - - public Clehin(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Clehin"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074211, // I could use some help. - 1074186)); // Come here, I have a task. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Cloorne : BaseCreature - { - [Constructible] - public Cloorne() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the expeditionist"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenBoots(0x3B2)); - AddItem(new RadiantScimitar()); - AddItem(new WingedHelm()); - - Item item; - - item = new WoodlandLegs(); - item.Hue = 0x74A; - AddItem(item); - - item = new HideChest(); - item.Hue = 0x726; - AddItem(item); - - item = new LeafArms(); - item.Hue = 0x73E; - AddItem(item); - } - - public Cloorne(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Cloorne"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074185, // Hey you! Want to help me out? - 1074186)); // Come here, I have a task. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Salaenih (The Heartwood)")] - public class Salaenih : BaseCreature - { - [Constructible] - public Salaenih() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the expeditionist"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenBoots()); - AddItem(new WarCleaver()); - - Item item; - - item = new WoodlandBelt(); - item.Hue = 0x597; - AddItem(item); - - item = new VultureHelm(); - item.Hue = 0x1BB; - AddItem(item); - - item = new WoodlandLegs(); - item.Hue = 0x1BB; - AddItem(item); - - item = new WoodlandChest(); - item.Hue = 0x1BB; - AddItem(item); - - item = new WoodlandArms(); - item.Hue = 0x1BB; - AddItem(item); - } - - public Salaenih(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Salaenih"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074207, // Good day to you friend! Allow me to offer you a fabulous opportunity!� Thrills and adventure await! - 1074209)); // Hey, could you help me out with something? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Vilo (The Heartwood)")] - public class Vilo : BaseCreature - { - [Constructible] - public Vilo() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the guard"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenBoots(0x901)); - AddItem(new OrnateAxe()); - AddItem(new WoodlandBelt(0x592)); - AddItem(new VultureHelm()); - AddItem(new WoodlandLegs()); - AddItem(new WoodlandChest()); - AddItem(new WoodlandArms()); - AddItem(new WoodlandGorget()); - } - - public Vilo(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Vilo"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074210, // Hi.� Looking for something to do? - 1074220)); // May I call you friend?� I have a favor to beg of you. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Tholef (The Heartwood)")] - public class Tholef : BaseCreature - { - [Constructible] - public Tholef() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the grape tender"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new Sandals(0x901)); - AddItem(new FullApron(0x756)); - AddItem(new ShortPants(0x28C)); - AddItem(new Shirt(0x28C)); - - Item item; - - item = new LeafArms(); - item.Hue = 0x28C; - AddItem(item); - } - - public Tholef(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Tholef"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074209, // Hey, could you help me out with something? - 1074184)); // Come here, I have work for you. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Tillanil (The Heartwood)")] - public class Tillanil : BaseCreature - { - [Constructible] - public Tillanil() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the grape tender"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new Sandals(0x1BB)); - AddItem(new Tunic(0x759)); - AddItem(new ShortPants(0x21)); - } - - public Tillanil(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Tillanil"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074187, // Want a job? - 1074222)); // Could I trouble you for some assistance? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Waelian (The Heartwood)")] - public class Waelian : BaseCreature - { - [Constructible] - public Waelian() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the trinket weaver"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new Shoes(0x901)); - AddItem(new SmithHammer()); - AddItem(new LongPants(0x340)); - AddItem(new GemmedCirclet()); - - Item item; - - item = new LeafChest(); - item.Hue = 0x344; - AddItem(item); - } - - public Waelian(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Waelian"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074221, // Greetings!� I have a small task for you good traveler. - 1074201)); // Waste not a minute! There�s work to be done. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Sleen (The Heartwood)")] - public class Sleen : BaseCreature - { - [Constructible] - public Sleen() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the trinket weaver"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenBoots(0x901)); - AddItem(new SmithHammer()); - AddItem(new Cloak(0x75A)); - AddItem(new ElvenShirt()); - } - - public Sleen(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Sleen"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074200, // Thank goodness you are here, there�s no time to lose. - 1074206)); // Excuse me please traveler, might I have a little of your time? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Unoelil (The Heartwood)")] - public class Unoelil : BaseCreature - { - [Constructible] - public Unoelil() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the bark weaver"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenBoots(0x1BB)); - AddItem(new ShortPants(0x1BB)); - AddItem(new Tunic(0x64D)); - } - - public Unoelil(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Unoelil"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074186, // Come here, I have a task. - 1074209)); // Hey, could you help me out with something? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Anolly (The Heartwood)")] - public class Anolly : BaseCreature - { - [Constructible] - public Anolly() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the bark weaver"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new Sandals(0x901)); - AddItem(new ShortPants(0x3B3)); - AddItem(new FullApron(0x1BB)); - AddItem(new SmithHammer()); - } - - public Anolly(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Anolly"; - public override bool CanTeach => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Jusae (The Heartwood)")] - public class Jusae : BaseCreature - { - [Constructible] - public Jusae() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the bowcrafter"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new Sandals(0x901)); - AddItem(new ShortPants(0x661)); - AddItem(new MagicalShortbow()); - - Item item; - - item = new HideChest(); - item.Hue = 0x27B; - AddItem(item); - - item = new HidePauldrons(); - item.Hue = 0x27E; - AddItem(item); - } - - public Jusae(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Jusae"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074210, // Hi.� Looking for something to do? - 1074213)); // Hey buddy.� Looking for work? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Cillitha (The Heartwood)")] - public class Cillitha : BaseCreature - { - [Constructible] - public Cillitha() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the bowcrafter"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenBoots(0x901)); - AddItem(new ElvenShirt(0x731)); - AddItem(new LeafLegs()); - } - - public Cillitha(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Cillitha"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074223, // Have you done it yet?� Oh, I haven�t told you, have I? - 1074213)); // Hey buddy.� Looking for work? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Lohn (The Heartwood)")] - public class Lohn : BaseCreature - { - [Constructible] - public Lohn() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the metal weaver"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new Shoes(0x901)); - AddItem(new LongPants(0x359)); - AddItem(new SmithHammer()); - AddItem(new GemmedCirclet()); - - Item item; - - item = new LeafChest(); - item.Hue = 0x359; - AddItem(item); - } - - public Lohn(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Lohn"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074187, // Want a job? - 1074209)); // Hey, could you help me out with something? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Olla (The Heartwood)")] - public class Olla : BaseCreature - { - [Constructible] - public Olla() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the metal weaver"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenBoots()); - AddItem(new LongPants(0x3B3)); - AddItem(new SmithHammer()); - AddItem(new FullApron(0x1BB)); - AddItem(new ElvenShirt()); - } - - public Olla(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Olla"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074187, // Want a job? - 1074185)); // Hey you! Want to help me out? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Thallary (The Heartwood)")] - public class Thallary : BaseCreature - { - [Constructible] - public Thallary() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the cloth weaver"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new Sandals(0x901)); - AddItem(new LongPants(0x72E)); - AddItem(new Cloak(0x3B3)); - AddItem(new FancyShirt(0x13)); - } - - public Thallary(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Thallary"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074221, // Greetings!� I have a small task for you good traveler. - 1074212)); // *yawn* You busy? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Ahie (The Heartwood)")] - public class Ahie : BaseCreature - { - [Constructible] - public Ahie() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the cloth weaver"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new Boots(0x901)); - AddItem(new Skirt(0x1C)); - AddItem(new Cloak(0x62)); - AddItem(new FancyShirt(0x738)); - } - - public Ahie(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Ahie"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074206, // Excuse me please traveler, might I have a little of your time? - 1074203)); // Hello friend. I realize you are busy but if you would be willing to render me a service I can assure you that you will be judiciously renumerated. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Tyeelor : BaseCreature - { - [Constructible] - public Tyeelor() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the expeditionist"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new ElvenBoots(0x1BB)); - - Item item; - - item = new WoodlandLegs(); - item.Hue = 0x236; - AddItem(item); - - item = new WoodlandChest(); - item.Hue = 0x236; - AddItem(item); - - item = new WoodlandArms(); - item.Hue = 0x236; - AddItem(item); - - item = new VultureHelm(); - item.Hue = 0x236; - AddItem(item); - - item = new WoodlandBelt(); - item.Hue = 0x236; - AddItem(item); - } - - public Tyeelor(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Tyeelor"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Athailon : BaseCreature - { - [Constructible] - public Athailon() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the expeditionist"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new ElvenBoots(0x901)); - AddItem(new WoodlandBelt()); - AddItem(new DiamondMace()); - - Item item; - - item = new WoodlandLegs(); - item.Hue = 0x3B2; - AddItem(item); - - item = new FemaleElvenPlateChest(); - item.Hue = 0x3B2; - AddItem(item); - - item = new WoodlandArms(); - item.Hue = 0x3B2; - AddItem(item); - - item = new WingedHelm(); - item.Hue = 0x3B2; - AddItem(item); - } - - public Athailon(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Athailon"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class ElderTaellia : BaseCreature - { - [Constructible] - public ElderTaellia() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the wise"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new ThighBoots(0x127)); - AddItem(new FemaleElvenRobe(Utility.RandomBrightHue())); - AddItem(new MagicWand()); - AddItem(new Circlet()); - } - - public ElderTaellia(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Elder Taellia"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class ElderMallew : BaseCreature - { - [Constructible] - public ElderMallew() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the wise"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new ElvenBoots(0x1BB)); - AddItem(new Cloak(0x3B2)); - AddItem(new Circlet()); - - Item item; - - item = new LeafTonlet(); - item.Hue = 0x544; - AddItem(item); - - item = new LeafChest(); - item.Hue = 0x538; - AddItem(item); - - item = new LeafArms(); - item.Hue = 0x528; - AddItem(item); - } - - public ElderMallew(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Elder Mallew"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class ElderAbbein : BaseCreature - { - [Constructible] - public ElderAbbein() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the wise"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new ElvenBoots(0x72C)); - AddItem(new FemaleElvenRobe(0x8B0)); - AddItem(new RoyalCirclet()); - } - - public ElderAbbein(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Elder Abbein"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class ElderVicaie : BaseCreature - { - [Constructible] - public ElderVicaie() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the wise"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new ElvenBoots()); - AddItem(new Tunic(0x732)); - - Item item; - - item = new LeafLegs(); - item.Hue = 0x3B2; - AddItem(item); - } - - public ElderVicaie(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Elder Vicaie"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class ElderJothan : BaseCreature - { - [Constructible] - public ElderJothan() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the wise"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new ThighBoots()); - AddItem(new ElvenPants(0x58D)); - AddItem(new ElvenShirt(Utility.RandomYellowHue())); - AddItem(new Cloak(Utility.RandomBrightHue())); - AddItem(new Circlet()); - } - - public ElderJothan(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Elder Jothan"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class ElderAlethanian : BaseCreature - { - [Constructible] - public ElderAlethanian() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the wise"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new ElvenBoots()); - AddItem(new HidePants()); - AddItem(new HideFemaleChest()); - AddItem(new HidePauldrons()); - AddItem(new GemmedCirclet()); - } - - public ElderAlethanian(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Elder Alethanian"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Rebinil : BaseCreature - { - [Constructible] - public Rebinil() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the healer"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Sandals(0x715)); - AddItem(new FemaleElvenRobe(0x742)); - AddItem(new RoyalCirclet()); - } - - public Rebinil(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Rebinil"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Aluniol : BaseCreature - { - [Constructible] - public Aluniol() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the healer"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new ElvenBoots(0x1BB)); - AddItem(new MaleElvenRobe(0x47E)); - AddItem(new WildStaff()); - } - - public Aluniol(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Aluniol"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Olaeni : BaseCreature - { - [Constructible] - public Olaeni() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the thaumaturgist"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Shoes(0x75A)); - AddItem(new FemaleElvenRobe(0x13)); - AddItem(new MagicWand()); - AddItem(new GemmedCirclet()); - } - - public Olaeni(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Olaeni"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Bolaevin : BaseCreature - { - [Constructible] - public Bolaevin() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the arcanist"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new ElvenBoots(0x3B2)); - AddItem(new RoyalCirclet()); - AddItem(new LeafChest()); - AddItem(new LeafArms()); - - Item item; - - item = new LeafLegs(); - item.Hue = 0x1BB; - AddItem(item); - } - - public Bolaevin(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Bolaevin"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LorekeeperAneen : BaseCreature - { - [Constructible] - public LorekeeperAneen() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the keeper of tradition"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Sandals(0x1BB)); - AddItem(new MaleElvenRobe(0x48F)); - AddItem(new MagicWand()); - } - - public LorekeeperAneen(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Lorekeeper Aneen"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Daelas : BaseCreature - { - [Constructible] - public Daelas() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the arborist"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new ElvenBoots(0x901)); - AddItem(new ElvenPants(0x8AB)); - - Item item; - - item = new LeafChest(); - item.Hue = 0x8B0; - AddItem(item); - - item = new LeafGloves(); - item.Hue = 0x1BB; - AddItem(item); - } - - public Daelas(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Daelas"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Alelle : BaseCreature - { - [Constructible] - public Alelle() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the arborist"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new ElvenBoots(0x1BB)); - - Item item; - - item = new FemaleLeafChest(); - item.Hue = 0x3A; - AddItem(item); - - item = new LeafLegs(); - item.Hue = 0x74C; - AddItem(item); - - item = new LeafGloves(); - item.Hue = 0x1BB; - AddItem(item); - } - - public Alelle(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Alelle"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Nillaen (The Heartwood)")] - public class LorekeeperNillaen : BaseCreature - { - [Constructible] - public LorekeeperNillaen() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the keeper of tradition"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new Shoes(0x1BB)); - AddItem(new LongPants(0x1FB)); - AddItem(new ElvenShirt()); - AddItem(new GemmedCirclet()); - AddItem(new BodySash(0x25)); - AddItem(new BlackStaff()); - } - - public LorekeeperNillaen(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Lorekeeper Nillaen"; - public override bool CanTeach => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Ryal (The Heartwood)")] - public class LorekeeperRyal : BaseCreature - { - [Constructible] - public LorekeeperRyal() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the keeper of tradition"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenBoots(0x1BB)); - AddItem(new LeafTonlet()); - AddItem(new ElvenShirt(0x2DD)); - AddItem(new Cloak(0x219)); - AddItem(new GnarledStaff()); - } - - public LorekeeperRyal(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Lorekeeper Ryal"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074204, // Greetings seeker.� I have an urgent matter for you, if you are willing. - 1074200)); // Thank goodness you are here, there�s no time to lose. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Braen (The Heartwood)")] - public class Braen : BaseCreature - { - [Constructible] - public Braen() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the thaumaturgist"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new Sandals(0x714)); - AddItem(new MaleElvenRobe(0x64A)); - AddItem(new MagicWand()); - } - - public Braen(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Braen"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1074187); // Want a job? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Elder Acob (The Heartwood)")] - public class ElderAcob : BaseCreature - { - [Constructible] - public ElderAcob() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the wise"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenBoots(0x714)); - AddItem(new ElvenShirt(Utility.RandomBrightHue())); - AddItem(new HidePants()); - } - - public ElderAcob(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Elder Acob"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1074197); // Pardon me, but if you could spare some time I�d greatly appreciate it. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LorekeeperCalendor : BaseCreature - { - [Constructible] - public LorekeeperCalendor() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the keeper of tradition"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenBoots(0x714)); - AddItem(new ElvenShirt(Utility.RandomOrangeHue())); - AddItem(new Kilt(Utility.RandomOrangeHue())); - AddItem(new RoyalCirclet()); - } - - public LorekeeperCalendor(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Lorekeeper Calendor"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1074204); // Greetings seeker.� I have an urgent matter for you, if you are willing. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LorekeeperSiarra : BaseCreature - { - [Constructible] - public LorekeeperSiarra() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the keeper of tradition"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new Sandals(0x1BB)); - AddItem(new ElvenShirt()); - AddItem(new LeafTonlet()); - AddItem(new GemmedCirclet()); - } - - public LorekeeperSiarra(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Lorekeeper Siarra"; - public override bool CanTeach => true; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1074206); // Excuse me please traveler, might I have a little of your time? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; +using Server.Engines.Spawners; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Definitions +{ + public class TheyreBreedingLikeRabbits : MLQuest + { + public TheyreBreedingLikeRabbits() + { + Activated = true; + Title = 1072244; // They're Breeding Like Rabbits + Description = + 1072259; // Aaaahhhh! They're everywhere! Aaaaahhh! Ahem. Actually, friend, how do you feel about rabbits? Well, we're being overrun by them. We're finding fuzzy bunnies everywhere. Aaaaahhh! + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(10, new[] { typeof(Rabbit) }, "rabbits")); + + Rewards.Add(ItemReward.SmallBagOfTrinkets); + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Saril"), new Point3D(7075, 376, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Saril"), new Point3D(7075, 376, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Cailla"), new Point3D(7075, 377, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Cailla"), new Point3D(7075, 377, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Tamm"), new Point3D(7075, 378, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Tamm"), new Point3D(7075, 378, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 3, "Landy"), new Point3D(7089, 390, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 3, "Landy"), new Point3D(7089, 390, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Alejaha"), new Point3D(7043, 387, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Alejaha"), new Point3D(7043, 387, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 3, "Mielan"), new Point3D(7063, 350, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 3, "Mielan"), new Point3D(7063, 350, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Ciala"), new Point3D(7031, 411, 7), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Ciala"), new Point3D(7031, 411, 7), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Aniel"), new Point3D(7034, 412, 6), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Aniel"), new Point3D(7034, 412, 6), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Aulan"), new Point3D(6986, 340, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Aulan"), new Point3D(6986, 340, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Brinnae"), new Point3D(6996, 351, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Brinnae"), new Point3D(6996, 351, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Caelas"), new Point3D(7039, 390, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Caelas"), new Point3D(7039, 390, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Clehin"), new Point3D(7092, 390, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Clehin"), new Point3D(7092, 390, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Cloorne"), new Point3D(7010, 364, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Cloorne"), new Point3D(7010, 364, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Salaenih"), new Point3D(7009, 362, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Salaenih"), new Point3D(7009, 362, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Vilo"), new Point3D(7029, 377, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Vilo"), new Point3D(7029, 377, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Tholef"), new Point3D(6986, 386, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Tholef"), new Point3D(6986, 386, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Tillanil"), new Point3D(6987, 388, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Tillanil"), new Point3D(6987, 388, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Waelian"), new Point3D(6996, 381, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Waelian"), new Point3D(6996, 381, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Sleen"), new Point3D(6997, 381, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Sleen"), new Point3D(6997, 381, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Unoelil"), new Point3D(7010, 388, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Unoelil"), new Point3D(7010, 388, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Anolly"), new Point3D(7009, 388, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Anolly"), new Point3D(7009, 388, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Jusae"), new Point3D(7042, 377, 2), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Jusae"), new Point3D(7042, 377, 2), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Cillitha"), new Point3D(7043, 377, 2), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Cillitha"), new Point3D(7043, 377, 2), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Lohn"), new Point3D(7062, 410, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Lohn"), new Point3D(7062, 410, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Olla"), new Point3D(7063, 410, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Olla"), new Point3D(7063, 410, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Thallary"), new Point3D(7032, 439, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Thallary"), new Point3D(7032, 439, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Ahie"), new Point3D(7033, 440, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Ahie"), new Point3D(7033, 440, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Tyeelor"), new Point3D(7010, 364, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Tyeelor"), new Point3D(7010, 364, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Athailon"), new Point3D(7011, 365, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Athailon"), new Point3D(7011, 365, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderTaellia"), new Point3D(7038, 387, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderTaellia"), new Point3D(7038, 387, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderMallew"), new Point3D(7047, 390, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderMallew"), new Point3D(7047, 390, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderAbbein"), new Point3D(7043, 390, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderAbbein"), new Point3D(7043, 390, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderVicaie"), new Point3D(7054, 390, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderVicaie"), new Point3D(7054, 390, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderJothan"), new Point3D(7056, 383, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderJothan"), new Point3D(7056, 383, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "ElderAlethanian"), new Point3D(7056, 380, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "ElderAlethanian"), new Point3D(7056, 380, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Rebinil"), new Point3D(7089, 380, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Rebinil"), new Point3D(7089, 380, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Aluniol"), new Point3D(7089, 383, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Aluniol"), new Point3D(7089, 383, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Olaeni"), new Point3D(7080, 363, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Olaeni"), new Point3D(7080, 363, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Bolaevin"), new Point3D(7066, 351, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Bolaevin"), new Point3D(7066, 351, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "LorekeeperAneen"), new Point3D(7053, 337, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "LorekeeperAneen"), new Point3D(7053, 337, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Daelas"), new Point3D(7036, 412, 7), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Daelas"), new Point3D(7036, 412, 7), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Alelle"), new Point3D(7028, 406, 7), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Alelle"), new Point3D(7028, 406, 7), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "LorekeeperNillaen"), new Point3D(7061, 370, 14), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "LorekeeperNillaen"), new Point3D(7061, 370, 14), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "LorekeeperRyal"), new Point3D(7009, 375, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "LorekeeperRyal"), new Point3D(7009, 375, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Braen"), new Point3D(7081, 366, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Braen"), new Point3D(7081, 366, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderAcob"), new Point3D(7037, 387, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "ElderAcob"), new Point3D(7037, 387, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "LorekeeperCalendor"), new Point3D(7062, 370, 14), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "LorekeeperCalendor"), new Point3D(7062, 370, 14), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "LorekeeperSiarra"), new Point3D(7051, 339, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "LorekeeperSiarra"), new Point3D(7051, 339, 0), Map.Felucca); + } + } + + public class TheyllEatAnything : MLQuest + { + public TheyllEatAnything() + { + Activated = true; + Title = 1072248; // They'll Eat Anything + Description = + 1072262; // Pork is the fruit of the land! You can barbeque it, boil it, bake it, sautee it. There's pork kebabs, pork creole, pork gumbo, pan fried, deep fried, stir fried. There's apple pork, peppered pork, pork soup, pork salad, pork and potatoes, pork burger, pork sandwich, pork stew, pork chops, pork loins, shredded pork. So, lets get some piggies butchered! + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(10, new[] { typeof(Pig) }, "pigs")); + + Rewards.Add(ItemReward.SmallBagOfTrinkets); + } + } + + public class NoGoodFishStealing : MLQuest + { + public NoGoodFishStealing() + { + Activated = true; + Title = 1072251; // No Good, Fish Stealing ... + Description = + 1072265; // Mighty creatures they are, aye. Fierce and strong, can't blame 'em for wanting to feed themselves an' all. Blame or no, they're eating all the fish up, so they got to go. Lend a hand? + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(10, new[] { typeof(Walrus) }, "walruses")); + + Rewards.Add(ItemReward.SmallBagOfTrinkets); + } + } + + public class AHeroInTheMaking : MLQuest + { + public AHeroInTheMaking() + { + Activated = true; + Title = 1072246; // A Hero in the Making + Description = + 1072257; // Are you new around here? Well, nevermind that. You look ready for adventure, I can see the gleam of glory in your eyes! Nothing is more valiant, more noble, more praiseworthy than mongbat slaying. + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(10, new[] { typeof(Mongbat) }, "mongbats")); + + Rewards.Add(ItemReward.SmallBagOfTrinkets); + } + } + + public class BullfightingSortOf : MLQuest + { + public BullfightingSortOf() + { + Activated = true; + Title = 1072247; // Bullfighting ... Sort Of + Description = + 1072254; // You there! Yes, you. Listen, I've got a little problem on my hands, but a brave, bold hero like yourself should find it a snap to solve. Bottom line -- we need some of the bulls in the area culled. You're welcome to any meat or hides, and of course, I'll give you a nice reward. + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(10, new[] { typeof(Bull) }, "bulls")); + + Rewards.Add(ItemReward.SmallBagOfTrinkets); + } + } + + public class AFineFeast : MLQuest + { + public AFineFeast() + { + Activated = true; + Title = 1072243; // A Fine Feast. + Description = + 1072261; // Mmm, I do love mutton! It's slaughtering time again and my usual hirelings haven't turned up. I've arranged for a butcher to come by and cut everything up but the basic sheep killing part I haven't gotten worked out yet. Are you up for the task? + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(10, new[] { typeof(Sheep) }, "sheep")); + + Rewards.Add(ItemReward.SmallBagOfTrinkets); + } + } + + public class ForcedMigration : MLQuest + { + public ForcedMigration() + { + Activated = true; + Title = 1072250; // Forced Migration + Description = + 1072264; // Chirp chirp ... tweet chirp. Tra la la. Bloody birds and their blasted noise. I've tried everything but they just won't stop that infernal clamor. Return me to blessed silence and I'll make it worth your while. + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(10, new[] { typeof(Bird) }, "birds")); + + Rewards.Add(ItemReward.SmallBagOfTrinkets); + } + } + + public class FilthyPests : MLQuest + { + public FilthyPests() + { + Activated = true; + Title = 1072242; // Filthy Pests! + Description = + 1072253; // They're everywhere I tell you! They crawl in the walls, they scurry in the bushes. Disgusting critters. Say ... I don't suppose you're up for some sewer rat killing? Sewer rats now, not any other kind of squeaker will do. + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(10, new[] { typeof(SewerRat) }, "sewer rats")); + + Rewards.Add(ItemReward.SmallBagOfTrinkets); + } + } + + public class DeadManWalking : MLQuest + { + public DeadManWalking() + { + Activated = true; + Title = 1072983; // Dead Man Walking + Description = + 1073009; // Why? I ask you why? They walk around after they're put in the ground. It's just wrong in so many ways. Put them to proper rest, I beg you. I'll find some way to pay you for the kindness. Just kill five zombies and five skeletons. + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(5, new[] { typeof(Zombie) }, "zombies")); + Objectives.Add(new KillObjective(5, new[] { typeof(Skeleton) }, "skeletons")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class KingOfBears : MLQuest + { + public KingOfBears() + { + Activated = true; + Title = 1072996; // King of Bears + Description = + 1073030; // A pity really. With the balance of nature awry, we have no choice but to accept the responsibility of making it all right. It's all a part of the circle of life, after all. So, yes, the grizzly bears are running rampant. There are far too many in the region. Will you shoulder your obligations as a higher life form? + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(10, new[] { typeof(GrizzlyBear) }, "grizzly bears")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class Specimens : MLQuest + { + public Specimens() + { + Activated = true; + Title = 1072999; // Specimens + Description = + 1073032; // I admire them, you know. The solen have their place -- regimented, organized. They're fascinating to watch with their constant strife between red and black. I can't help but want to stir things up from time to time. And that's where you come in. Kill either twelve red or twelve black solen workers and let's see what happens next! + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + ObjectiveType = ObjectiveType.Any; + + Objectives.Add(new KillObjective(12, new[] { typeof(RedSolenWorker) }, "red solen workers")); + Objectives.Add(new KillObjective(12, new[] { typeof(BlackSolenWorker) }, "black solen workers")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class Spirits : MLQuest + { + public Spirits() + { + Activated = true; + Title = 1073076; // Spirits + Description = + 1073566; // It is a piteous thing when the dead continue to walk the earth. Restless spirits are known to inhabit these parts, taking the lives of unwary travelers. It is about time a hero put the dead back in their graves. I'm sure such a hero would be justly rewarded. + RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. + InProgressMessage = 1073586; // The restless spirts still walk -- you must kill 15 of them. + + Objectives.Add( + new KillObjective( + 15, + new[] { typeof(Spectre), typeof(Shade), typeof(Wraith) }, + "spectres or shades or wraiths" + ) + ); + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + public class RollTheBones : MLQuest + { + public RollTheBones() + { + Activated = true; + Title = 1073002; // Roll the Bones + Description = + 1073011; // Why? I ask you why? They walk around after they're put in the ground. It's just wrong in so many ways. Put them to proper rest, I beg you. I'll find some way to pay you for the kindness. Just kill eight patchwork skeletons. + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(8, new[] { typeof(PatchworkSkeleton) }, "patchwork skeletons")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class ItsAGhastlyJob : MLQuest + { + public ItsAGhastlyJob() + { + Activated = true; + Title = 1073008; // It's a Ghastly Job + Description = + 1073012; // Why? I ask you why? They walk around after they're put in the ground. It's just wrong in so many ways. Put them to proper rest, I beg you. I'll find some way to pay you for the kindness. Just kill twelve ghouls. + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(12, new[] { typeof(Ghoul) }, "ghouls")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class Troglodytes : MLQuest + { + public Troglodytes() + { + Activated = true; + Title = 1074688; // Troglodytes! + Description = + 1074689; // Oh nevermind, you don't look capable of my task afterall. Haha! What was I thinking - you could never handle killing troglodytes. It'd be suicide. What? I don't know, I don't want to be responsible ... well okay if you're really sure? + RefusalMessage = 1074690; // Probably the wiser course of action. + InProgressMessage = 1074691; // You still need to kill those troglodytes, remember? + + Objectives.Add(new KillObjective(12, new[] { typeof(Troglodyte) }, "troglodytes")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class UnholyKnights : MLQuest + { + public UnholyKnights() + { + Activated = true; + Title = 1073075; // Unholy Knights + Description = + 1073565; // Please, hear me kind traveler. You know when a knight falls, sometimes they are cursed to roam the earth as undead mockeries of their former glory? That is too grim a fate for even any knight to suffer! Please, put them out of their misery. I will offer you what payment I can if you will end the torment of these undead wretches. + RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. + InProgressMessage = 1073585; // Your task is not done. Continue putting the Skeleton and Bone Knights to rest. + + Objectives.Add( + new KillObjective( + 16, + new[] { typeof(BoneKnight), typeof(SkeletalKnight) }, + "bone knights or skeletal knights" + ) + ); + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + public class AFeatherInYerCap : MLQuest + { + public AFeatherInYerCap() + { + Activated = true; + Title = 1074738; // A Feather in Yer Cap + Description = + 1074737; // I've seen how you strut about, as if you were something special. I have some news for you, you don't impress me at all. It's not enough to have a fancy hat you know. That may impress people in the big city, but not here. If you want a reputation you have to climb a mountain, slay some great beast, and then write about it. Trust me, it's a long process. The first step is doing a great feat. If I were you, I'd go pluck a feather from the harpy Saliva, that would give you a good start. + RefusalMessage = 1074736; // The path to greatness isn't for everyone obviously. + InProgressMessage = + 1074735; // If you're going to get anywhere in the adventuring game, you have to take some risks. A harpy, well, it's bad, but it's not a dragon. + CompletionMessage = 1074734; // The hero returns from the glorious battle and - oh, such a small feather? + + Objectives.Add(new CollectObjective(1, typeof(SalivasFeather), "Saliva's Feather")); + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + public class ATaleOfTail : MLQuest + { + public ATaleOfTail() + { + Activated = true; + Title = 1074726; // A Tale of Tail + Description = + 1074727; // I've heard of you, adventurer. Your reputation is impressive, and now I'll put it to the test. This is not something I ask lightly, for this task is fraught with danger, but it is vital. Seek out the vile hydra Abscess, slay it, and return to me with it's tail. + RefusalMessage = 1074728; // Well, the beast will still be there when you are ready I suppose. + InProgressMessage = + 1074729; // Em, I thought I had explained already. Abscess, the hydra, you know? Lots of heads but just the one tail. I need the tail. I have my reasons. Go go go. + CompletionMessage = + 1074730; // Ah, the tail. You did it! You know the rumours about dried ground hydra tail powder are all true? Thank you so much! + + Objectives.Add(new CollectObjective(1, typeof(AbscessTail), "Abscess' Tail")); + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + public class ATrogAndHisDog : MLQuest + { + public ATrogAndHisDog() + { + Activated = true; + Title = 1074681; // A Trog and His Dog + Description = + 1074680; // I don't know if you can handle it, but I'll give you a go at it. Troglodyte chief - name of Lurg and his mangy wolf pet need killing. Do the deed and I'll reward you. + RefusalMessage = 1074655; // Perhaps I thought too highly of you. + InProgressMessage = + 1074682; // The trog chief and his mutt should be easy enough to find. Just kill them and report back. Easy enough. + CompletionMessage = 1074683; // Not half bad. Here's your prize. + + Objectives.Add(new KillObjective(1, new[] { typeof(Lurg) }, "Lurg")); + Objectives.Add(new KillObjective(1, new[] { typeof(Grobu) }, "Grobu")); + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + } + + public class Overpopulation : MLQuest + { + public Overpopulation() + { + Activated = true; + Title = 1072252; // Overpopulation + Description = + 1072267; // I just can't bear it any longer. Sure, it's my job to thin the deer out so they don't overeat the area and starve themselves come winter time. Sure, I know we killed off the predators that would do this naturally so now we have to make up for it. But they're so graceful and innocent. I just can't do it. Will you? + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(10, new[] { typeof(Hind) }, "hinds")); + + Rewards.Add(ItemReward.SmallBagOfTrinkets); + } + } + + public class WildBoarCull : MLQuest + { + public WildBoarCull() + { + Activated = true; + Title = 1072245; // Wild Boar Cull + Description = + 1072260; // A pity really. With the balance of nature awry, we have no choice but to accept the responsibility of making it all right. It's all a part of the circle of life, after all. So, yes, the boars are running rampant. There are far too many in the region. Will you shoulder your obligations as a higher life form? + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(10, new[] { typeof(Boar) }, "boars")); + + Rewards.Add(ItemReward.SmallBagOfTrinkets); + } + } + + public class ItsElemental : MLQuest + { + public ItsElemental() + { + Activated = true; + Title = 1073089; // It's Elemental + Description = + 1073579; // The universe is all about balance my friend. Tip one end, you must balance the other. That's why I must ask you to kill not just one kind of elemental, but three kinds. Snuff out some Fire, douse a few Water, and crush some Earth elementals and I'll pay you for your trouble. + RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. + InProgressMessage = 1073599; // Four of each, that's all I ask. Water, earth and fire. + + Objectives.Add(new KillObjective(4, new[] { typeof(FireElemental) }, "fire elementals")); + Objectives.Add(new KillObjective(4, new[] { typeof(WaterElemental) }, "water elementals")); + Objectives.Add(new KillObjective(4, new[] { typeof(EarthElemental) }, "earth elementals")); + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + public class CircleOfLife : MLQuest + { + public CircleOfLife() + { + Activated = true; + Title = 1073656; // Circle of Life + Description = + 1073695; // There's been a bumper crop of evil with the Bog Things in these parts, my friend. Though they are foul creatures, they are also most fecund. Slay one and you make the land more fertile. Even better, slay several and I will give you whatever coin I can spare. + RefusalMessage = 1073733; // Perhaps you'll change your mind and return at some point. + InProgressMessage = 1073736; // Continue to seek and kill the Bog Things. + + Objectives.Add(new KillObjective(8, new[] { typeof(BogThing) }, "bog things")); + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + } + + public class DustToDust : MLQuest + { + public DustToDust() + { + Activated = true; + Title = 1073074; // Dust to Dust + Description = + 1073564; // You want to hear about trouble? I got trouble. How's angry piles of granite walking around for trouble? Maybe they don't like the mining, maybe it's the farming. I don't know. All I know is someone's got to turn them back to potting soil. And it'd be worth a pretty penny to the soul that does it. + RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. + InProgressMessage = 1073584; // You got rocks in your head? I said to kill 12 earth elementals, okay? + + Objectives.Add(new KillObjective(12, new[] { typeof(EarthElemental) }, "earth elementals")); + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + public class CreepyCrawlies : MLQuest + { + public CreepyCrawlies() + { + Activated = true; + Title = 1072987; // Creepy Crawlies + Description = + 1073016; // Disgusting! The way they scuttle on those hairy legs just makes me want to gag. I hate spiders! Rid the world of twelve and I'll find something nice to give you in thanks. + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(12, new[] { typeof(GiantSpider) }, "giant spiders")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class VoraciousPlants : MLQuest + { + public VoraciousPlants() + { + Activated = true; + Title = 1073001; // Voracious Plants + Description = + 1073024; // I bet you can't tangle with those nasty plants ... say eight corpsers and two swamp tentacles! I bet they're too much for you. You may as well confess you can't ... + RefusalMessage = 1073019; // Hahahaha! I knew it! + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(8, new[] { typeof(Corpser) }, "corpsers")); + Objectives.Add(new KillObjective(2, new[] { typeof(SwampTentacle) }, "swamp tentacles")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class GibberJabber : MLQuest + { + public GibberJabber() + { + Activated = true; + Title = 1073004; // Gibber Jabber + Description = + 1073024; // I bet you can't kill ... ten gibberlings! I bet they're too much for you. You may as well confess you can't ... + RefusalMessage = 1073019; // Hahahaha! I knew it! + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(10, new[] { typeof(Gibberling) }, "gibberlings")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class AnimatedMonstrosity : MLQuest + { + public AnimatedMonstrosity() + { + Activated = true; + Title = 1072990; // Animated Monstrosity + Description = + 1073020; // I bet you can't kill ... say twelve ... flesh golems! I bet they're too much for you. You may as well confess you can't ... + RefusalMessage = 1073019; // Hahahaha! I knew it! + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(12, new[] { typeof(FleshGolem) }, "flesh golems")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class BirdsOfAFeather : MLQuest + { + public BirdsOfAFeather() + { + Activated = true; + Title = 1073007; // Birds of a Feather + Description = + 1073022; // I bet you can't kill ... ten harpies! I bet they're too much for you. You may as well confess you can't ... + RefusalMessage = 1073019; // Hahahaha! I knew it! + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(10, new[] { typeof(Harpy) }, "harpies")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class Frightmares : MLQuest + { + public Frightmares() + { + Activated = true; + Title = 1073000; // Frightmares + Description = + 1073036; // I bet you can't handle ten plague spawns! I bet they're too much for you. You may as well confess you can't ... + RefusalMessage = 1073019; // Hahahaha! I knew it! + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(10, new[] { typeof(PlagueSpawn) }, "plague spawns")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class MoltenReptiles : MLQuest + { + public MoltenReptiles() + { + Activated = true; + Title = 1072989; // Molten Reptiles + Description = + 1073018; // I bet you can't kill ... say ten ... lava lizards! I bet they're too much for you. You may as well confess you can't ... + RefusalMessage = 1073019; // Hahahaha! I knew it! + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(10, new[] { typeof(LavaLizard) }, "lava lizards")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class BloodyNuisance : MLQuest + { + public BloodyNuisance() + { + Activated = true; + Title = 1072992; // Bloody Nuisance + Description = + 1073021; // I bet you can't kill ... ten gore fiends! I bet they're too much for you. You may as well confess you can't ... + RefusalMessage = 1073019; // Hahahaha! I knew it! + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(10, new[] { typeof(GoreFiend) }, "gore fiends")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class BloodSuckers : MLQuest + { + public BloodSuckers() + { + Activated = true; + Title = 1072997; // Blood Suckers + Description = + 1073025; // I bet you can't tangle with those bloodsuckers ... say around ten vampire bats! I bet they're too much for you. You may as well confess you can't ... + RefusalMessage = 1073019; // Hahahaha! I knew it! + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(10, new[] { typeof(VampireBat) }, "vampire bats")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class TheAfterlife : MLQuest + { + public TheAfterlife() + { + Activated = true; + Title = 1073073; // The Afterlife + Description = + 1073563; // Nobody told me about the Mummy's Curse. How was I supposed to know you shouldn't disturb the tombs? Oh, sure, now all I hear about is the curse of the vengeful dead. I'll tell you what - make a few of these mummies go away and we'll keep this between you and me. + RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. + InProgressMessage = 1073583; // Uh, I don't think you're quite done killing Mummies yet. + + Objectives.Add(new KillObjective(15, new[] { typeof(Mummy) }, "mummies")); + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + public class ForkedTongue : MLQuest + { + public ForkedTongue() + { + Activated = true; + Title = 1073655; // Forked Tongue + Description = + 1073694; // I must implore you, brave traveler, to do battle with the vile reptiles which haunt these parts. Those hideous abominations, the Ophidians, are a blight across the land. If you were able to put down a host of the scaly warriors, the Knights or the Avengers, I would forever be in your debt. + RefusalMessage = 1073733; // Perhaps you'll change your mind and return at some point. + InProgressMessage = 1073735; // Have you killed the Ophidian Knights or Avengers? + + Objectives.Add( + new KillObjective( + 10, + new[] { typeof(OphidianKnight) }, + "ophidian avengers or ophidian knight-errants" + ) + ); + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + } + + public class ImpishDelights : MLQuest + { + public ImpishDelights() + { + Activated = true; + Title = 1073077; // Impish Delights + Description = + 1073567; // Imps! Do you hear me? Imps! They're everywhere! They're in everything! Oh, don't be fooled by their size - they vicious little devils! Half-sized evil incarnate, they are! Somebody needs to send them back to where they came from, if you know what I mean. + RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. + InProgressMessage = + 1073587; // Don't let the little devils scare you! You kill 12 imps - then we'll talk reward. + + Objectives.Add(new KillObjective(12, new[] { typeof(Imp) }, "imps")); + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + public class ThreeWishes : MLQuest + { + public ThreeWishes() + { + Activated = true; + Title = 1073660; // Three Wishes + Description = + 1073699; // If I had but one wish, it would be to rid myself of these dread Efreet! Fire and ash, they are cunning and deadly! You look a brave soul - would you be interested in earning a rich reward for slaughtering a few of the smoky devils? + RefusalMessage = 1073733; // Perhaps you'll change your mind and return at some point. + InProgressMessage = 1073740; // Those smoky devils, the Efreets, are still about. + + Objectives.Add(new KillObjective(8, new[] { typeof(Efreet) }, "efreets")); + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + } + + public class EvilEye : MLQuest + { + public EvilEye() + { + Activated = true; + Title = 1073084; // Evil Eye + Description = + 1073574; // Kind traveler, hear my plea. You know of the evil orbs? The wrathful eyes? Some call them gazers? They must be a nest nearby, for they are tormenting us poor folk. We need to drive back their numbers. But we are not strong enough to face such horrors ourselves, we need a true hero. + RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. + InProgressMessage = 1073594; // Have you annihilated a dozen Gazers yet, kind traveler? + + Objectives.Add(new KillObjective(12, new[] { typeof(Gazer) }, "gazers")); + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + public class GargoylesWrath : MLQuest + { + public GargoylesWrath() + { + Activated = true; + Title = 1073658; // Gargoyle's Wrath + Description = + 1073697; // It is regretable that the Gargoyles insist upon warring with us. Their Enforcers attack men on sight, despite all efforts at reason. To help maintain order in this region, I have been authorized to encourage bounty hunters to reduce their numbers. Eradicate their number and I will reward you handsomely. + RefusalMessage = 1073733; // Perhaps you'll change your mind and return at some point. + InProgressMessage = 1073738; // I won't be able to pay you until you've gotten enough Gargoyle Enforcers. + + Objectives.Add(new KillObjective(6, new[] { typeof(GargoyleEnforcer) }, "gargoyle enforcers")); + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + } + + public class UndeadMages : MLQuest + { + public UndeadMages() + { + Activated = true; + Title = 1073080; // Undead Mages + Description = + 1073570; // Why must the dead plague the living? With their foul necromancy and dark sorceries, the undead menace the countryside. I fear what will happen if no one is strong enough to face these nightmare sorcerers and thin their numbers. + RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. + InProgressMessage = 1073590; // Surely, a brave soul like yourself can kill 10 Bone Magi and Skeletal Mages? + + Objectives.Add( + new KillObjective( + 10, + new[] { typeof(BoneMagi), typeof(SkeletalMage) }, + "bone mages or skeletal mages" + ) + ); + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + public class FriendlyNeighborhoodSpiderkiller : MLQuest + { + public FriendlyNeighborhoodSpiderkiller() + { + Activated = true; + Title = 1073662; // Friendly Neighborhood Spider-killer + Description = + 1073701; // They aren't called Dread Spiders because they're fluffy and cuddly now, are they? No, there's nothing appealing about those wretches so I sure wouldn't lose any sleep if you were to exterminate a few. I'd even part with a generous amount of gold, I would. + RefusalMessage = 1073733; // Perhaps you'll change your mind and return at some point. + InProgressMessage = 1073742; // Dread Spiders? I say keep exterminating the arachnid vermin. + + Objectives.Add(new KillObjective(8, new[] { typeof(DreadSpider) }, "dread spiders")); + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + } + + public class MongbatMenace : MLQuest + { + public MongbatMenace() + { + Activated = true; + Title = 1073003; // Mongbat Menace! + Description = + 1073033; // I imagine you don't know about the mongbats. Well, you may think you do, but I know more than just about anyone. You see they come in two varieties ... the stronger and the weaker. Either way, they're a menace. Exterminate ten of the weaker ones and four of the stronger and I'll pay you an honest wage. + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(10, new[] { typeof(Mongbat) }, "mongbats")); + Objectives.Add(new KillObjective(4, new[] { typeof(GreaterMongbat) }, "greater mongbats")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class StirringTheNest : MLQuest + { + public StirringTheNest() + { + Activated = true; + Title = 1073087; // Stirring the Nest + Description = + 1073577; // Were you the sort of child that enjoyed knocking over anthills? Well, perhaps you'd like to try something a little bigger? There's a Solen nest nearby and I bet if you killed a queen or two, it would be quite the sight to behold. I'd even pay to see that - what do you say? + RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. + InProgressMessage = 1073597; // Dead Solen Queens isn't too much to ask, is it? + + ObjectiveType = ObjectiveType.Any; + + Objectives.Add(new KillObjective(3, new[] { typeof(RedSolenQueen) }, "red solen queens")); + Objectives.Add(new KillObjective(3, new[] { typeof(BlackSolenQueen) }, "black solen queens")); + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + public class WarriorCaste : MLQuest + { + public WarriorCaste() + { + Activated = true; + Title = 1073078; // Warrior Caste + Description = + 1073568; // The Terathan are an aggressive species. Left unchecked, they will swarm across our lands. And where will that leave us? Compost in the hive, that's what! Stop them, stop them cold my friend. Kill their warriors and you'll check their movement, that is certain. + RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. + InProgressMessage = + 1073588; // Unless you kill at least 10 Terathan Warriors, you won't have any impact on their hive. + + Objectives.Add(new KillObjective(10, new[] { typeof(TerathanWarrior) }, "terathan warriors")); + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + public class BigWorms : MLQuest + { + public BigWorms() + { + Activated = true; + Title = 1073088; // Big Worms + Description = + 1073578; // It makes no sense! Cold blooded serpents cannot live in the ice! It's a biological impossibility! They are an abomination against reason! Please, I beg you - kill them! Make them disappear for me! Do this and I will reward you. + RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. + InProgressMessage = 1073598; // You wouldn't try and just pretend you murdered 10 Giant Ice Worms, would you? + + Objectives.Add(new KillObjective(10, new[] { typeof(IceSerpent) }, "giant ice serpents")); + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + public class OrcishElite : MLQuest + { + public OrcishElite() + { + Activated = true; + Title = 1073081; // Orcish Elite + Description = + 1073571; // Foul brutes! No one loves an orc, but some of them are worse than the rest. Their Captains and their Bombers, for instance, they're the worst of the lot. Kill a few of those, and the rest are just a rabble. Exterminate a few of them and you'll make the world a sunnier place, don't you know. + RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. + InProgressMessage = + 1073591; // The only good orc is a dead orc - and 4 dead Captains and 6 dead Bombers is even better! + + Objectives.Add(new KillObjective(6, new[] { typeof(OrcBomber) }, "orc bombers")); + Objectives.Add(new KillObjective(4, new[] { typeof(OrcCaptain) }, "orc captain")); + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + public class ThinningTheHerd : MLQuest + { + public ThinningTheHerd() + { + Activated = true; + Title = 1072249; // Thinning the Herd + Description = + 1072263; // Psst! Hey ... psst! Listen, I need some help here but it's gotta be hush hush. I don't want THEM to know I'm onto them. They watch me. I've seen them, but they don't know that I know what I know. You know? Anyway, I need you to scare them off by killing a few of them. That'll send a clear message that I won't suffer goats watching me! + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(10, new[] { typeof(Goat) }, "goats")); + + Rewards.Add(ItemReward.SmallBagOfTrinkets); + } + } + + public class Squishy : MLQuest + { + public Squishy() + { + Activated = true; + Title = 1072998; // Squishy + Description = + 1073031; // Have you ever seen what a slime can do to good gear? Well, it's not pretty, let me tell you! If you take on my task to destroy twelve of them, bear that in mind. They'll corrode your equipment faster than anything. + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(12, new[] { typeof(Slime) }, "slimes")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class OrcSlaying : MLQuest + { + public OrcSlaying() + { + Activated = true; + Title = 1072986; // Orc Slaying + Description = + 1073015; // Those green-skinned freaks have run off with more of my livestock. I want an orc scout killed for each sheep I lost and an orc for each chicken. So that's four orc scouts and eight orcs I'll pay you to slay. + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(8, new[] { typeof(Orc) }, "orcs")); + // TODO: This needs to be orc scouts but they aren't in the SVN + Objectives.Add(new KillObjective(4, new[] { typeof(OrcishLord) }, "orcish lords")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class ABigJob : MLQuest + { + public ABigJob() + { + Activated = true; + Title = 1072988; // A Big Job + Description = + 1073017; // It's a big job but you look to be just the adventurer to do it! I'm so glad you came by ... I'm paying well for the death of five ogres and five ettins. + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(5, new[] { typeof(Ogre) }, "ogres")); + Objectives.Add(new KillObjective(5, new[] { typeof(Ettin) }, "ettins")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class TrollingForTrolls : MLQuest + { + public TrollingForTrolls() + { + Activated = true; + Title = 1072985; // Trolling for Trolls + Description = + 1073014; // They may not be bright, but they're incredibly destructive. Kill off ten trolls and I'll consider it a favor done for me. + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(10, new[] { typeof(Troll) }, "trolls")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class ColdHearted : MLQuest + { + public ColdHearted() + { + Activated = true; + Title = 1072991; // Cold Hearted + Description = + 1073027; // It's a big job but you look to be just the adventurer to do it! I'm so glad you came by ... I'm paying well for the death of six giant ice serpents and six frost spiders. Hop to it, if you're so inclined. + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(6, new[] { typeof(IceSerpent) }, "giant ice serpents")); + Objectives.Add(new KillObjective(6, new[] { typeof(FrostSpider) }, "frost spiders")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class ForkedTongues : MLQuest + { + public ForkedTongues() + { + Activated = true; + Title = 1072984; // Forked Tongues + Description = + 1073013; // You can't trust them, you know. Lizardmen I mean. They have forked tongues ... and you know what that means. Exterminate ten of them and I'll reward you. + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(10, new[] { typeof(Lizardman) }, "lizardmen")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class ShakingThingsUp : MLQuest + { + public ShakingThingsUp() + { + Activated = true; + Title = 1073083; // Shaking Things Up + Description = + 1073573; // A Solen hive is a fascinating piece of ecology. It's put together like a finely crafted clock. Who knows what happens if you remove something? So let's find out. Exterminate a few of the warriors and I'll make it worth your while. + RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. + InProgressMessage = + 1073593; // I don't think you've gotten their attention yet -- you need to kill at least 10 Solen Warriors. + + ObjectiveType = ObjectiveType.Any; + + Objectives.Add(new KillObjective(10, new[] { typeof(RedSolenWarrior) }, "red solen warriors")); + Objectives.Add(new KillObjective(10, new[] { typeof(BlackSolenWarrior) }, "black solen warriors")); + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + public class Arachnophobia : MLQuest + { + public Arachnophobia() + { + Activated = true; + Title = 1073079; // Arachnophobia + Description = + 1073569; // I've seen them hiding in their webs among the woods. Glassy eyes, spindly legs, poisonous fangs. Monsters, I say! Deadly horrors, these black widows. Someone must exterminate the abominations! If only I could find a worthy hero for such a task, then I could give them this considerable reward. + RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. + InProgressMessage = + 1073589; // You've got a good start, but to stop the black-eyed fiends, you need to kill a dozen. + + Objectives.Add(new KillObjective(12, new[] { typeof(GiantBlackWidow) }, "giant black widows")); + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + public class MiniSwampThing : MLQuest + { + public MiniSwampThing() + { + Activated = true; + Title = 1073072; // Mini Swamp Thing + Description = + 1073562; // Some say killing a boggling brings good luck. I don't place much stock in old wives' tales, but I can say a few dead bogglings would certainly be lucky for me! Help me out and I can reward you for your efforts. + RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. + InProgressMessage = 1073582; // Go back and kill all 20 bogglings! + + Objectives.Add(new KillObjective(12, new[] { typeof(Bogling) }, "boglings")); + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + public class ThePerilsOfFarming : MLQuest + { + public ThePerilsOfFarming() + { + Activated = true; + Title = 1073664; // The Perils of Farming + Description = + 1073703; // I should be trimming back the vegetation here, but something nasty has taken root. Viscious vines I can't go near. If there's any hope of getting things under control, some one's going to need to destroy a few of those Whipping Vines. Someone strong and fast and tough. + RefusalMessage = 1073733; // Perhaps you'll change your mind and return at some point. + InProgressMessage = 1073744; // How are farmers supposed to work with these Whipping Vines around? + + Objectives.Add(new KillObjective(15, new[] { typeof(WhippingVine) }, "whipping vines")); + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + } + + public class IndustriousAsAnAntLion : MLQuest + { + public IndustriousAsAnAntLion() + { + Activated = true; + Title = 1073665; // Industrious as an Ant Lion + Description = + 1073704; // Ants are industrious and Lions are noble so who'd think an Ant Lion would be such a problem? The Ant Lion's have been causing mindless destruction in these parts. I suppose it's just how ants are. But I need you to help eliminate the infestation. Would you be willing to help for a bit of reward? + RefusalMessage = 1073733; // Perhaps you'll change your mind and return at some point. + InProgressMessage = 1073745; // Please, rid us of the Ant Lion infestation. + + Objectives.Add(new KillObjective(12, new[] { typeof(AntLion) }, "ant lions")); + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + } + + public class UnholyConstruct : MLQuest + { + public UnholyConstruct() + { + Activated = true; + Title = 1073666; // Unholy Construct + Description = + 1073705; // They're unholy, I say. Golems, a walking mockery of all life, born of blackest magic. They're not truly alive, so destroying them isn't a crime, it's a service. A service I will gladly pay for. + RefusalMessage = 1073733; // Perhaps you'll change your mind and return at some point. + InProgressMessage = 1073746; // The unholy brutes, the Golems, must be smited! + CompletionMessage = 1073787; // Reduced those Golems to component parts? Good, then -- you deserve this reward! + + Objectives.Add(new KillObjective(10, new[] { typeof(Golem) }, "golems")); + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + } + + public class AChillInTheAir : MLQuest + { + public AChillInTheAir() + { + Activated = true; + Title = 1073663; // A Chill in the Air + Description = + 1073702; // Feel that chill in the air? It means an icy death for the unwary, for deadly Ice Elementals are about. Who knows what magic summoned them, what's important now is getting rid of them. I don't have much, but I'll give all I can if you'd only stop the cold-hearted monsters. + RefusalMessage = 1073733; // Perhaps you'll change your mind and return at some point. + InProgressMessage = 1073746; // The chill won't lift until you eradicate a few Ice Elemenals. + + Objectives.Add(new KillObjective(15, new[] { typeof(IceElemental) }, "ice elementals")); + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + } + + public class TheKingOfClothing : MLQuest + { + public TheKingOfClothing() + { + Activated = true; + HasRestartDelay = true; + Title = 1073902; // The King of Clothing + Description = + 1074092; // I have heard noble tales of a fine and proud human garment. An article of clothing fit for both man and god alike. It is called a "kilt" I believe? Could you fetch for me some of these kilts so I that I might revel in their majesty and glory? + RefusalMessage = 1073921; // I will patiently await your reconsideration. + InProgressMessage = 1073948; // I will be in your debt if you bring me kilts. + CompletionMessage = 1073974; // I say truly - that is a magnificent garment! You have more than earned a reward. + + Objectives.Add(new CollectObjective(10, typeof(Kilt), 1025431)); // kilt + + Rewards.Add(ItemReward.TailorSatchel); + } + } + + public class ThePuffyShirt : MLQuest + { + public ThePuffyShirt() + { + Activated = true; + HasRestartDelay = true; + Title = 1073903; // The Puffy Shirt + Description = + 1074093; // We elves believe that beauty is expressed in all things, including the garments we wear. I wish to understand more about human aesthetics, so please kind traveler - could you bring to me magnificent examples of human fancy shirts? For my thanks, I could teach you more about the beauty of elven vestements. + RefusalMessage = 1073921; // I will patiently await your reconsideration. + InProgressMessage = 1073949; // I will be in your debt if you bring me fancy shirts. + CompletionMessage = 1073973; // I appreciate your service. Now, see what elven hands can create. + + Objectives.Add(new CollectObjective(10, typeof(FancyShirt), 1027933)); // fancy shirt + + Rewards.Add(ItemReward.TailorSatchel); + } + } + + public class FromTheGaultierCollection : MLQuest + { + public FromTheGaultierCollection() + { + Activated = true; + HasRestartDelay = true; + Title = 1073905; // From the Gaultier Collection + Description = + 1074095; // It is my understanding, the females of humankind actually wear on certain occasions a studded bustier? This is not simply a fanciful tale? Remarkable! It sounds hideously uncomfortable as well as ludicrously impracticle. But perhaps, I simply do not understand the nuances of human clothing. Perhaps, I need to see such a studded bustier for myself? + RefusalMessage = 1073921; // I will patiently await your reconsideration. + InProgressMessage = 1073951; // I will be in your debt if you bring me studded bustiers. + CompletionMessage = 1073976; // Truly, it is worse than I feared. Still, I appreciate your efforts on my behalf. + + Objectives.Add(new CollectObjective(10, typeof(StuddedBustierArms), 1027180)); // studded bustier + + Rewards.Add(ItemReward.TailorSatchel); + } + } + + public class HauteCouture : MLQuest + { + public HauteCouture() + { + Activated = true; + HasRestartDelay = true; + Title = 1073901; // Hâute Couture + Description = + 1074091; // Most human apparel is interesting to elven eyes. But there is one garment - the flower garland - which sounds very elven indeed. Could I see how a human crafts such an object of beauty? In exchange, I could share with you the wonders of elven garments. + RefusalMessage = 1073921; // I will patiently await your reconsideration. + InProgressMessage = 1073947; // I will be in your debt if you bring me flower garlands. + CompletionMessage = 1073973; // I appreciate your service. Now, see what elven hands can create. + + Objectives.Add(new CollectObjective(10, typeof(FlowerGarland), 1028965)); // flower garland + + Rewards.Add(ItemReward.TailorSatchel); + } + } + + public class TheSongOfTheWind : MLQuest + { + public TheSongOfTheWind() + { + Activated = true; + HasRestartDelay = true; + Title = 1073910; // The Song of the Wind + Description = + 1074100; // To give voice to the passing wind, this is an idea worthy of an elf! Friend, bring me some of the amazing fancy wind chimes so that I may listen to the song of the passing breeze. Do this, and I will share with you treasured elven secrets. + RefusalMessage = 1073921; // I will patiently await your reconsideration. + InProgressMessage = 1073956; // I will be in your debt if you bring me fancy wind chimes. + CompletionMessage = 1073980; // Such a delightful sound, I think I shall never tire of it. + + Objectives.Add(new CollectObjective(10, typeof(FancyWindChimes), "fancy wind chimes")); + + Rewards.Add(ItemReward.TinkerSatchel); + } + } + + public class BeerGoggles : MLQuest + { + public BeerGoggles() + { + Activated = true; + HasRestartDelay = true; + Title = 1073895; // Beer Goggles + Description = + 1074085; // Oh, the deviltry! Why would humans lock their precious liquors inside a wooden coffin? I understand I need a "keg tap" to access the golden brew within such a wooden abomination. Perhaps, if you could bring me such a tap, we could share a drink and I could teach you. + RefusalMessage = 1073921; // I will patiently await your reconsideration. + InProgressMessage = 1073941; // I will be in your debt if you bring me barrel taps. + CompletionMessage = 1073971; // My thanks for your service. Here is something for you to enjoy. + + Objectives.Add(new CollectObjective(25, typeof(BarrelTap), 1024100)); // barrel tap + + Rewards.Add(ItemReward.TinkerSatchel); + } + } + + public class MessageInABottleQuest : MLQuest + { + public MessageInABottleQuest() + { + Activated = true; + HasRestartDelay = true; + Title = 1073894; // Message in a Bottle + Description = + 1074084; // We elves are interested in trading our wines with humans but we understand human usually trade such brew in strange transparent bottles. If you could provide some of these empty glass bottles, I might engage in a bit of elven winemaking. + RefusalMessage = 1073921; // I will patiently await your reconsideration. + InProgressMessage = 1073940; // I will be in your debt if you bring me empty bottles. + CompletionMessage = 1073971; // My thanks for your service. Here is something for you to enjoy. + + Objectives.Add(new CollectObjective(50, typeof(Bottle), 1023854)); // empty bottle + + Rewards.Add(ItemReward.TinkerSatchel); + } + } + + public class NecessitysMother : MLQuest + { + public NecessitysMother() + { + Activated = true; + HasRestartDelay = true; + Title = 1073906; // Necessity's Mother + Description = + 1074096; // What a thing, this human need to tinker. It seems there is no end to what might be produced with a set of Tinker's Tools. Who knows what an elf might build with some? Could you obtain some tinker's tools and bring them to me? In exchange, I offer you elven lore and knowledge. + RefusalMessage = 1073921; // I will patiently await your reconsideration. + InProgressMessage = 1073952; // I will be in your debt if you bring me tinker's tools. + CompletionMessage = 1073977; // Now, I shall see what an elf can invent! + + Objectives.Add(new CollectObjective(10, typeof(TinkerTools), 1027868)); // tinker's tools + + Rewards.Add(ItemReward.TinkerSatchel); + } + } + + public class TickTock : MLQuest + { + public TickTock() + { + Activated = true; + HasRestartDelay = true; + Title = 1073907; // Tick Tock + Description = + 1074097; // Elves find it remarkable the human preoccupation with the passage of time. To have built instruments to try and capture time -- it is a fascinating notion. I would like to see how a clock is put together. Maybe you could provide some clocks for my experimentation? + RefusalMessage = 1073921; // I will patiently await your reconsideration. + InProgressMessage = 1073953; // I will be in your debt if you bring me clocks. + CompletionMessage = 1073978; // Enjoy my thanks for your service. + + Objectives.Add(new CollectObjective(10, typeof(Clock), 1024171)); // clock + + Rewards.Add(ItemReward.TinkerSatchel); + } + } + + public class ReptilianDentist : MLQuest + { + public ReptilianDentist() + { + Activated = true; + Title = 1074280; // Reptilian Dentist + Description = + 1074710; // I'm working on a striking necklace -- something really unique -- and I know just what I need to finish it up. A huge fang! Won't that catch the eye? I would like to employ you to find me such an item, perhaps a snake would make the ideal donor. I'll make it worth your while, of course. + RefusalMessage = 1074723; // I understand. I don't like snakes much either. They're so creepy. + InProgressMessage = + 1074722; // Those really big snakes like swamps, I've heard. You might try the blighted grove. + CompletionMessage = 1074721; // Do you have it? *gasp* What a tooth! Here � I must get right to work. + + Objectives.Add(new CollectObjective(1, typeof(CoilsFang), "coil's fang")); + + Rewards.Add(ItemReward.TinkerSatchel); + } + } + + public class StopHarpingOnMe : MLQuest + { + public StopHarpingOnMe() + { + Activated = true; + HasRestartDelay = true; + Title = 1073881; // Stop Harping on Me + Description = + 1074071; // Humans artistry can be a remarkable thing. For instance, I have heard of a wonderful instrument which creates the most melodious of music. A lap harp. I would be ever so grateful if I could examine one in person. + RefusalMessage = 1073921; // I will patiently await your reconsideration. + InProgressMessage = 1073927; // I will be in your debt if you bring me lap harp. + CompletionMessage = 1073969; // My thanks for your service. Now, I will show you something of elven carpentry. + + Objectives.Add(new CollectObjective(20, typeof(LapHarp), 1023762)); // lap harp + + Rewards.Add(ItemReward.CarpentrySatchel); + } + } + + public class TheFarEye : MLQuest + { + public TheFarEye() + { + Activated = true; + HasRestartDelay = true; + Title = 1073908; // The Far Eye + Description = + 1074098; // The wonders of human invention! Turning sand and metal into a far-seeing eye! This is something I must experience for myself. Bring me some of these spyglasses friend human. + RefusalMessage = 1073921; // I will patiently await your reconsideration. + InProgressMessage = 1073954; // I will be in your debt if you bring me spyglasses. + CompletionMessage = 1073978; // Enjoy my thanks for your service. + + Objectives.Add(new CollectObjective(20, typeof(Spyglass), 1025365)); // spyglass + + Rewards.Add(ItemReward.TinkerSatchel); + } + } + + public class LethalDarts : MLQuest + { + public LethalDarts() + { + Activated = true; + HasRestartDelay = true; + Title = 1073876; // Lethal Darts + Description = + 1074066; // We elves are no strangers to archery but I would be interested in learning whether there is anything to learn from the human approach. I would gladly trade you something I have if you could teach me of the deadly crossbow bolt. + RefusalMessage = 1073921; // I will patiently await your reconsideration. + InProgressMessage = 1073922; // I will be in your debt if you bring me crossbow bolts. + CompletionMessage = 1073968; // My thanks for your service. Now, I shall teach you of elven archery. + CompletionNotice = CompletionNoticeCraft; + + Objectives.Add(new CollectObjective(10, typeof(Bolt), 1027163)); // crossbow bolt + + Rewards.Add(ItemReward.FletchingSatchel); + } + } + + public class ASimpleBow : MLQuest + { + public ASimpleBow() + { + Activated = true; + HasRestartDelay = true; + Title = 1073877; // A Simple Bow + Description = + 1074067; // I wish to try a bow crafted in the human style. Is it possible for you to bring me such a weapon? I would be happy to return this favor. + RefusalMessage = 1073921; // I will patiently await your reconsideration. + InProgressMessage = 1073923; // I will be in your debt if you bring me bows. + CompletionMessage = 1073968; // My thanks for your service. Now, I shall teach you of elven archery. + CompletionNotice = CompletionNoticeCraft; + + Objectives.Add(new CollectObjective(10, typeof(Bow), 1025041)); // bow + + Rewards.Add(ItemReward.FletchingSatchel); + } + } + + public class IngeniousArcheryPartOne : MLQuest + { + public IngeniousArcheryPartOne() + { + Activated = true; + HasRestartDelay = true; + Title = 1073878; // Ingenious Archery, Part I + Description = + 1074068; // I have heard of a curious type of bow, you call it a "crossbow". It sounds fascinating and I would very much like to examine one closely. Would you be able to obtain such an instrument for me? + RefusalMessage = 1073921; // I will patiently await your reconsideration. + InProgressMessage = 1073924; // I will be in your debt if you bring me crossbows. + CompletionMessage = 1073968; // My thanks for your service. Now, I shall teach you of elven archery. + CompletionNotice = CompletionNoticeCraft; + + Objectives.Add(new CollectObjective(10, typeof(Crossbow), 1023919)); // crossbow + + Rewards.Add(ItemReward.FletchingSatchel); + } + } + + public class IngeniousArcheryPartTwo : MLQuest + { + public IngeniousArcheryPartTwo() + { + Activated = true; + HasRestartDelay = true; + Title = 1073879; // Ingenious Archery, Part II + Description = + 1074069; // These human "crossbows" are complex and clever. The "heavy crossbow" is a remarkable instrument of war. I am interested in seeing one up close, if you could arrange for one to make its way to my hands. + RefusalMessage = 1073921; // I will patiently await your reconsideration. + InProgressMessage = 1073925; // I will be in your debt if you bring me heavy crossbows. + CompletionMessage = 1073968; // My thanks for your service. Now, I shall teach you of elven archery. + CompletionNotice = CompletionNoticeCraft; + + Objectives.Add(new CollectObjective(8, typeof(HeavyCrossbow), 1025116)); // heavy crossbow + + Rewards.Add(ItemReward.FletchingSatchel); + } + } + + public class IngeniousArcheryPartThree : MLQuest + { + public IngeniousArcheryPartThree() + { + Activated = true; + HasRestartDelay = true; + Title = 1073880; // Ingenious Archery, Part III + Description = + 1074070; // My friend, I am in search of a device, a instrument of remarkable human ingenuity. It is a repeating crossbow. If you were to obtain such a device, I would gladly reveal to you some of the secrets of elven craftsmanship. + RefusalMessage = 1073921; // I will patiently await your reconsideration. + InProgressMessage = 1073926; // I will be in your debt if you bring me repeating crossbows. + CompletionMessage = 1073968; // My thanks for your service. Now, I shall teach you of elven archery. + CompletionNotice = CompletionNoticeCraft; + + Objectives.Add(new CollectObjective(10, typeof(RepeatingCrossbow), 1029923)); // repeating crossbow + + Rewards.Add(ItemReward.FletchingSatchel); + } + } + + public class ScaleArmor : MLQuest + { + public ScaleArmor() + { + Activated = true; + Title = 1074711; // Scale Armor + Description = + 1074712; // Here's what I need ... there are some creatures called hydra, fearsome beasts, whose scales are especially suitable for a new sort of armor that I'm developing. I need a few such pieces and then some supple alligator skin for the backing. I'm going to need a really large piece that's shaped just right ... the tail I think would do nicely. I appreciate your help. + RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. + InProgressMessage = + 1074724; // Hydras have been spotted in the Blighted Grove. You won't get those scales without getting your feet wet, I'm afraid. + CompletionMessage = 1074725; // I can't wait to get to work now that you've returned with my scales. + + Objectives.Add(new CollectObjective(1, typeof(ThrashersTail), "Thrasher's Tail")); + Objectives.Add(new CollectObjective(10, typeof(HydraScale), "Hydra Scales")); + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + public class CutsBothWays : MLQuest + { + public CutsBothWays() + { + Activated = true; + HasRestartDelay = true; + Title = 1073913; // Cuts Both Ways + Description = + 1074103; // What would you say is a typical human instrument of war? Is a broadsword a typical example? I wish to see more of such human weapons, so I would gladly trade elven knowledge for human steel. + RefusalMessage = 1073921; // I will patiently await your reconsideration. + InProgressMessage = 1073959; // I will be in your debt if you bring me broadswords. + CompletionMessage = 1073978; // Enjoy my thanks for your service. + + Objectives.Add(new CollectObjective(12, typeof(Broadsword), 1023934)); // broadsword + + Rewards.Add(ItemReward.BlacksmithSatchel); + } + } + + public class DragonProtection : MLQuest + { + public DragonProtection() + { + Activated = true; + HasRestartDelay = true; + Title = 1073915; // Dragon Protection + Description = + 1074105; // Mankind, I am told, knows how to take the scales of a terrible dragon and forge them into powerful armor. Such a feat of craftsmanship! I would give anything to view such a creation - I would even teach some of the prize secrets of the elven people. + RefusalMessage = 1073921; // I will patiently await your reconsideration. + InProgressMessage = 1073961; // I will be in your debt if you bring me dragon armor. + CompletionMessage = 1073978; // Enjoy my thanks for your service. + + Objectives.Add(new CollectObjective(10, typeof(DragonHelm), 1029797)); // dragon helm + + Rewards.Add(ItemReward.BlacksmithSatchel); + } + } + + public class NothingFancy : MLQuest + { + public NothingFancy() + { + Activated = true; + HasRestartDelay = true; + Title = 1073911; // Nothing Fancy + Description = + 1074101; // I am curious to see the results of human blacksmithing. To examine the care and quality of a simple item. Perhaps, a simple bascinet helmet? Yes, indeed -- if you could bring to me some bascinet helmets, I would demonstrate my gratitude. + RefusalMessage = 1073921; // I will patiently await your reconsideration. + InProgressMessage = 1073957; // I will be in your debt if you bring me bascinets. + CompletionMessage = 1073978; // Enjoy my thanks for your service. + + Objectives.Add(new CollectObjective(15, typeof(Bascinet), 1025132)); // bascinet + + Rewards.Add(ItemReward.BlacksmithSatchel); + } + } + + public class TheBulwark : MLQuest + { + public TheBulwark() + { + Activated = true; + HasRestartDelay = true; + Title = 1073912; // The Bulwark + Description = + 1074102; // The clank of human iron and steel is strange to elven ears. For instance, the metallic heater shield which human warriors carry into battle. It is odd to an elf, but nevertheless intriguing. Tell me friend, could you bring me such an example of human smithing skill? + RefusalMessage = 1073921; // I will patiently await your reconsideration. + InProgressMessage = 1073958; // I will be in your debt if you bring me heater shields. + CompletionMessage = 1073978; // Enjoy my thanks for your service. + + Objectives.Add(new CollectObjective(10, typeof(HeaterShield), 1027030)); // heater shield + + Rewards.Add(ItemReward.BlacksmithSatchel); + } + } + + public class ArchSupport : MLQuest + { + public ArchSupport() + { + Activated = true; + HasRestartDelay = true; + Title = 1073882; // Arch Support + Description = + 1074072; // How clever humans are - to understand the need of feet to rest from time to time! Imagine creating a special stool just for weary toes. I would like to examine and learn the secret of their making. Would you bring me some foot stools to examine? + RefusalMessage = 1073921; // I will patiently await your reconsideration. + InProgressMessage = 1073928; // I will be in your debt if you bring me foot stools. + CompletionMessage = 1073969; // My thanks for your service. Now, I will show you something of elven carpentry. + + Objectives.Add(new CollectObjective(10, typeof(FootStool), 1022910)); // foot stool + + Rewards.Add(ItemReward.CarpentrySatchel); + } + } + + public class ParoxysmusSuccubi : MLQuest + { + public ParoxysmusSuccubi() + { + Activated = true; + Title = 1073067; // Paroxysmus' Succubi + Description = + 1074696; // The succubi that have congregated within the sinkhole to worship Paroxysmus pose a tremendous danger. Will you enter the lair and see to their destruction? + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add( + new KillObjective( + 3, + new[] { typeof(Succubus) }, + "succubi", + new QuestArea(1074806, "The Palace of Paroxysmus") + ) + ); // The Palace of Paroxysmus + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + } + + public class ParoxysmusMoloch : MLQuest + { + public ParoxysmusMoloch() + { + Activated = true; + Title = 1073068; // Paroxysmus' Moloch + Description = + 1074695; // The moloch daemons that have congregated to worship Paroxysmus pose a tremendous danger. Will you enter the lair and see to their destruction? + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add( + new KillObjective( + 3, + new[] { typeof(Moloch) }, + "molochs", + new QuestArea(1074806, "The Palace of Paroxysmus") + ) + ); // The Palace of Paroxysmus + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + } + + public class ParoxysmusDaemons : MLQuest + { + public ParoxysmusDaemons() + { + Activated = true; + Title = 1073069; // Paroxysmus' Daemons + Description = + 1074694; // The daemons that have congregated to worship Paroxysmus pose a tremendous danger. Will you enter the lair and see to their destruction? + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add( + new KillObjective( + 10, + new[] { typeof(Daemon) }, + "daemons", + new QuestArea(1074806, "The Palace of Paroxysmus") + ) + ); // The Palace of Paroxysmus + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + } + + public class ParoxysmusArcaneDaemons : MLQuest + { + public ParoxysmusArcaneDaemons() + { + Activated = true; + Title = 1073070; // Paroxysmus' Arcane Daemons + Description = + 1074697; // The arcane daemons that worship Paroxysmus pose a tremendous danger. Will you enter the lair and see to their destruction? + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add( + new KillObjective( + 10, + new[] { typeof(ArcaneDaemon) }, + "arcane daemons", + new QuestArea(1074806, "The Palace of Paroxysmus") + ) + ); // The Palace of Paroxysmus + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + } + + public class CausticCombo : MLQuest + { + public CausticCombo() + { + Activated = true; + Title = 1073062; // Caustic Combo + Description = + 1074693; // Vile creatures have exited the sinkhole and begun terrorizing the surrounding area. The demons are bad enough, but the elementals are an abomination, their poisons seeping into the fertile ground here. Will you enter the sinkhole and put a stop to their depredations? + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add( + new KillObjective( + 3, + new[] { typeof(PoisonElemental) }, + "poison elementals", + new QuestArea(1074806, "The Palace of Paroxysmus") + ) + ); // The Palace of Paroxysmus + Objectives.Add( + new KillObjective( + 6, + new[] { typeof(AcidElemental) }, + "acid elementals", + new QuestArea(1074806, "The Palace of Paroxysmus") + ) + ); // The Palace of Paroxysmus + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + } + + public class PlagueLord : MLQuest + { + public PlagueLord() + { + Activated = true; + Title = 1073061; // Plague Lord + Description = + 1074692; // Some of the most horrific creatures have slithered out of the sinkhole there and begun terrorizing the surrounding area. The plague creatures are one of the most destruction of the minions of Paroxysmus. Are you willing to do something about them? + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add( + new KillObjective( + 10, + new[] { typeof(PlagueSpawn) }, + "plague spawns", + new QuestArea(1074806, "The Palace of Paroxysmus") + ) + ); // The Palace of Paroxysmus + Objectives.Add( + new KillObjective( + 3, + new[] { typeof(PlagueBeast) }, + "plague beasts", + new QuestArea(1074806, "The Palace of Paroxysmus") + ) + ); // The Palace of Paroxysmus + Objectives.Add( + new KillObjective( + 1, + new[] { typeof(PlagueBeastLord) }, + "plague beast lord", + new QuestArea(1074806, "The Palace of Paroxysmus") + ) + ); // The Palace of Paroxysmus + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + } + + public class GlassyFoe : MLQuest + { + public GlassyFoe() + { + Activated = true; + Title = 1073055; // Glassy Foe + Description = + 1074669; // Good, you're here. The presence of a twisted creature deep under the earth near Nu'Jelm has corrupted the natural growth of crystals in that region. They've become infused with the twisting energy - they've come to a sort of life. This is an abomination that festers within Sosaria. You must eradicate the crystal lattice seekers. + RefusalMessage = 1074671; // These abominations must not be permitted to fester! + InProgressMessage = 1074672; // You must not waste time. Do not suffer these crystalline abominations to live. + CompletionMessage = 1074673; // You have done well. Enjoy this reward. + + Objectives.Add( + new KillObjective( + 5, + new[] { typeof(CrystalLatticeSeeker) }, + "crystal lattice seekers", + new QuestArea(1074805, "The Prism of Light") + ) + ); // The Prism of Light + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + } + + public class DaemonicPrism : MLQuest + { + public DaemonicPrism() + { + Activated = true; + Title = 1073053; // Daemonic Prism + Description = + 1074668; // Good, you're here. The presence of a twisted creature deep under the earth near Nu'Jelm has corrupted the natural growth of crystals in that region. They've become infused with the twisting energy - they've come to a sort of life. This is an abomination that festers within Sosaria. You must eradicate the crystal daemons. + RefusalMessage = 1074671; // These abominations must not be permitted to fester! + InProgressMessage = 1074672; // You must not waste time. Do not suffer these crystalline abominations to live. + CompletionMessage = 1074673; // You have done well. Enjoy this reward. + + Objectives.Add( + new KillObjective( + 3, + new[] { typeof(CrystalDaemon) }, + "crystal daemons", + new QuestArea(1074805, "The Prism of Light") + ) + ); // The Prism of Light + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + } + + public class Hailstorm : MLQuest + { + public Hailstorm() + { + Activated = true; + Title = 1073057; // Hailstorm + Description = + 1074670; // Good, you're here. The presence of a twisted creature deep under the earth near Nu'Jelm has corrupted the natural growth of crystals in that region. They've become infused with the twisting energy - they've come to a sort of life. This is an abomination that festers within Sosaria. You must eradicate the crystal vortices. + RefusalMessage = 1074671; // These abominations must not be permitted to fester! + InProgressMessage = 1074672; // You must not waste time. Do not suffer these crystalline abominations to live. + CompletionMessage = 1074673; // You have done well. Enjoy this reward. + + Objectives.Add( + new KillObjective( + 8, + new[] { typeof(CrystalVortex) }, + "crystal vortices", + new QuestArea(1074805, "The Prism of Light") + ) + ); // The Prism of Light + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + } + + /* TODO: Uncomment when Crystal Hydra is added + public class HowManyHeads : MLQuest + { + public HowManyHeads() + { + Activated = true; + Title = 1073050; // How Many Heads? + Description = 1074674; // Good, you're here. The presence of a twisted creature deep under the earth near Nu'Jelm has corrupted the natural growth of crystals in that region. They've become infused with the twisting energy - they've come to a sort of life. This is an abomination that festers within Sosaria. You must eradicate the crystal hydras. + RefusalMessage = 1074671; // These abominations must not be permitted to fester! + InProgressMessage = 1074672; // You must not waste time. Do not suffer these crystalline abominations to live. + CompletionMessage = 1074673; // You have done well. Enjoy this reward. + + Objectives.Add( new KillObjective( 3, new Type[] { typeof( CrystalHydra ) }, "crystal hydras", new QuestArea( 1074805, "The Prism of Light" ) ) ); // The Prism of Light + + Rewards.Add( ItemReward.LargeBagOfTreasure ); + } + } + */ + + /* TODO: Uncomment when Dreadhorn is added + public class DreadhornQuest : MLQuest + { + public DreadhornQuest() + { + Activated = true; + Title = 1074645; // Dreadhorn + Description = 1074646; // Can you comprehend it? I cannot, I confess. The most pristine and perfect Lord of Sosaria has fallen prey to the blight. From the depths of my heart I mourn his corruption; my thoughts are filled with pity for this glorious creature now tainted. And my blood boils with fury at those responsible for the innocent creature's undoing. Will you find Dread Horn, as he is now called, and free him from this misery? + RefusalMessage = 1074647; // How can you not feel as I do? + InProgressMessage = 1074648; // The lush and fertile land where Dread Horn now lives is twisted and tainted, a result of his corruption. The fey folk have sealed the land off through their magics, but you can enter through an enchanted mushroom fairy circle. + CompletionMessage = 1074649; // Thank you. I haven't the words to express my gratitude. + + Objectives.Add( new KillObjective( 1, new Type[] { typeof( DreadHorn ) }, "dread horn" ) ); + + Rewards.Add( ItemReward.RewardStrongbox ); + } + } + */ + + /* TODO: Uncomment when SerpentsFangHighExecutioner, TigersClawThief and DragonsFlameGrandMage are added + public class NewLeadership : MLQuest + { + public NewLeadership() + { + Activated = true; + Title = 1072905; // New Leadership + Description = 1072963; // I have a task for you ... adventurer. Will you risk all to win great renown? The Black Order is organized into three sects, each with their own speciality. The Dragon's Flame serves the will of the Grand Mage, the Tiger's Claw answers to the Master Thief, and the Serpent's Fang kills at the direction of the High Executioner. Slay all three and you will strike the order a devastating blow! + RefusalMessage = 1072973; // I do not fault your decision. + InProgressMessage = 1072974; // Once you gain entrance into The Citadel, you will need to move cautiously to find the sect leaders. + + Objectives.Add( new KillObjective( 1, new Type[] { typeof( SerpentsFangHighExecutioner ) }, "serpent's fang high executioner", new QuestArea( 1074804, "The Citadel" ) ) ); // The Citadel + Objectives.Add( new KillObjective( 1, new Type[] { typeof( TigersClawThief ) }, "tiger's claw thief", new QuestArea( 1074804, "The Citadel" ) ) ); // The Citadel + Objectives.Add( new KillObjective( 1, new Type[] { typeof( DragonsFlameGrandMage ) }, "dragon's flame mage", new QuestArea( 1074804, "The Citadel" ) ) ); // The Citadel + + Rewards.Add( ItemReward.RewardStrongbox ); + } + } + */ + + /* TODO: Uncomment when SerpentsFangAssassin is added + public class ExAssassins : MLQuest + { + public ExAssassins() + { + Activated = true; + Title = 1072917; // Ex-Assassins + Description = 1072969; // The Serpent's Fang sect members have gone too far! Express to them my displeasure by slaying ten of them. But remember, I do not condone war on women, so I will only accept the deaths of men, human and elf. + RefusalMessage = 1072979; // As you wish. + InProgressMessage = 1072980; // The Black Order's fortress home is well hidden. Legend has it that a humble fishing village disguises the magical portal. + + // TODO: This has to be MALES only! + Objectives.Add( new KillObjective( 10, new Type[] { typeof( SerpentsFangAssassin ) }, "male serpent's fang assassins", new QuestArea( 1074804, "The Citadel" ) ) ); // The Citadel + + Rewards.Add( ItemReward.BagOfTreasure ); + } + } + */ + + /* TODO: Uncomment when DragonsFlameMage is added + public class ExtinguishingTheFlame : MLQuest + { + public ExtinguishingTheFlame() + { + Activated = true; + Title = 1072911; // Extinguishing the Flame + Description = 1072966; // The Dragon's Flame sect members have gone too far! Express to them my displeasure by slaying ten of them. But remember, I do not condone war on women, so I will only accept the deaths of men, human or elf. Either race will do, I care not for the shape of their ears. Yes, this action will properly make clear my disapproval and has a pleasing harmony. + RefusalMessage = 1072979; // As you wish. + InProgressMessage = 1072980; // The Black Order's fortress home is well hidden. Legend has it that a humble fishing village disguises the magical portal. + + // TODO: This has to be MALES only! + Objectives.Add( new KillObjective( 10, new Type[] { typeof( DragonsFlameMage ) }, "male dragon's flame mages", new QuestArea( 1074804, "The Citadel" ) ) ); // The Citadel + + Rewards.Add( ItemReward.BagOfTreasure ); + } + } + */ + + public class DeathToTheNinja : MLQuest + { + public DeathToTheNinja() + { + Activated = true; + Title = 1072913; // Death to the Ninja! + Description = + 1072966; // I wish to make a statement of censure against the elite ninjas of the Black Order. Deliver, in the strongest manner, my disdain. But do not make war on women, even those that take arms against you. It is not ... fitting. + RefusalMessage = 1072979; // As you wish. + InProgressMessage = + 1072980; // The Black Order's fortress home is well hidden. Legend has it that a humble fishing village disguises the magical portal. + + // TODO: Verify that this has to be males only (as per the description) + Objectives.Add( + new KillObjective( + 10, + new[] { typeof(EliteNinja) }, + "elite ninjas", + new QuestArea(1074804, "The Citadel") + ) + ); // The Citadel + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + /* TODO: Uncomment when TigersClawThief is added + public class CrimeAndPunishment : MLQuest + { + public CrimeAndPunishment() + { + Activated = true; + Title = 1072914; // Crime and Punishment + Description = 1072968; // The Tiger's Claw sect members have gone too far! Express to them my displeasure by slaying ten of them. But remember, I do not condone war on women, so I will only accept the deaths of men, human and elf. + RefusalMessage = 1072979; // As you wish. + InProgressMessage = 1072980; // The Black Order's fortress home is well hidden. Legend has it that a humble fishing village disguises the magical portal. + + // TODO: This has to be MALES only! + Objectives.Add( new KillObjective( 10, new Type[] { typeof( TigersClawThief ) }, "male tiger's claw thieves", new QuestArea( 1074804, "The Citadel" ) ) ); // The Citadel + + Rewards.Add( ItemReward.BagOfTreasure ); + } + } + */ + + /* TODO: Uncomment when ShimmeringEffusion is added + public class AllThatGlittersIsNotGood : MLQuest + { + public AllThatGlittersIsNotGood() + { + Activated = true; + Title = 1073048; // All That Glitters is Not Good + Description = 1074654; // The most incredible tale has reached my ears! Deep within the bowels of Sosaria, somewhere under the city of Nu'Jelm, a twisted creature feeds. What created this abomination, no one knows ... though there is some speculation that the fumbling initial efforts to open the portal to The Heartwood, brought it into existence. Regardless of it's origin, it must be destroyed before it damages Sosaria. Will you undertake this quest? + RefusalMessage = 1074655; // Perhaps I thought too highly of you. + InProgressMessage = 1074656; // An explorer discovered the cave system under Nu'Jelm. He made multiple trips into the place bringing back fascinating crystals and artifacts that suggested the hollow place in Sosaria was inhabited by other creatures at some point. You'll need to follow in his footsteps to find this abomination and destroy it. + CompletionMessage = 1074657; // I am overjoyed with your efforts! Your devotion to Sosaria is noted and appreciated. + + Objectives.Add( new KillObjective( 1, new Type[] { typeof( ShimmeringEffusion ) }, "shimmering effusion" ) ); + + Rewards.Add( ItemReward.RewardStrongbox ); + } + } + */ + + [QuesterName("Saril (The Heartwood)")] + public class Saril : BaseCreature + { + [Constructible] + public Saril() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the guard"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenBoots()); + AddItem(new WoodlandLegs()); + AddItem(new WoodlandArms()); + AddItem(new WoodlandBelt()); + AddItem(new WingedHelm()); + AddItem(new FemaleElvenPlateChest()); + AddItem(new RadiantScimitar()); + } + + public Saril(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Saril"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074186, // Come here, I have a task. + 1074183 + ) + ); // You there! I have a job for you. + } + + 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(); + } + } + + [QuesterName("Cailla (The Heartwood)")] + public class Cailla : BaseCreature + { + [Constructible] + public Cailla() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the guard"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenBoots()); + AddItem(new HidePants()); + AddItem(new HidePauldrons()); + AddItem(new HideGloves()); + AddItem(new WoodlandBelt()); + AddItem(new RavenHelm()); + AddItem(new HideFemaleChest()); + AddItem(new MagicalShortbow()); + } + + public Cailla(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Cailla"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074187, // Want a job? + 1074210 + ) + ); // Hi.� Looking for something to do? + } + + 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(); + } + } + + [QuesterName("Tamm (The Heartwood)")] + public class Tamm : BaseCreature + { + [Constructible] + public Tamm() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the guard"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenBoots()); + AddItem(new HidePants()); + AddItem(new HidePauldrons()); + AddItem(new WingedHelm()); + AddItem(new HideChest()); + AddItem(new ElvenCompositeLongbow()); + } + + public Tamm(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Tamm"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074213, // Hey buddy.� Looking for work? + 1074187 + ) + ); // Want a job? + } + + 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(); + } + } + + [QuesterName("Landy (The Heartwood)")] + public class Landy : BaseCreature + { + [Constructible] + public Landy() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the soil nurturer"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new Sandals(Utility.RandomYellowHue())); + AddItem(new ShortPants(Utility.RandomYellowHue())); + AddItem(new Tunic(Utility.RandomYellowHue())); + + Item gloves = new LeafGloves(); + gloves.Hue = Utility.RandomYellowHue(); + AddItem(gloves); + } + + public Landy(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Landy"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074211, // I could use some help. + 1074218 + ) + ); // Hey!� I want to talk to you, now. + } + + 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(); + } + } + + [QuesterName("Elder Alejaha (The Heartwood)")] + public class Alejaha : BaseCreature + { + [Constructible] + public Alejaha() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the wise"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new Sandals(Utility.RandomYellowHue())); + AddItem(new ElvenShirt(Utility.RandomYellowHue())); + AddItem(new GemmedCirclet()); + AddItem(new Cloak(Utility.RandomBrightHue())); + + if (Utility.RandomBool()) + AddItem(new Kilt(0x387)); + else + AddItem(new Skirt(0x387)); + } + + public Alejaha(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Elder Alejaha"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1074223); // Have you done it yet?� Oh, I haven�t told you, have I? + } + + 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(); + } + } + + [QuesterName("Mielan (The Heartwood)")] + public class Mielan : BaseCreature + { + [Constructible] + public Mielan() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the arcanist"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenBoots(0x901)); + AddItem(new ElvenShirt(0x56)); + AddItem(new GemmedCirclet()); + AddItem(new ElvenPants(0x901)); + } + + public Mielan(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Mielan"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074219, // Hello there, can I have a moment of your time? + 1074223 + ) + ); // Have you done it yet?� Oh, I haven�t told you, have I? + } + + 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(); + } + } + + [QuesterName("Ciala (The Heartwood)")] + public class Ciala : BaseCreature + { + [Constructible] + public Ciala() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the arborist"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new Skirt(Utility.RandomBlueHue())); + AddItem(new ElvenShirt(Utility.RandomYellowHue())); + AddItem(new RoyalCirclet()); + + if (Utility.RandomBool()) + AddItem(new Boots(Utility.RandomYellowHue())); + else + AddItem(new ThighBoots(Utility.RandomYellowHue())); + } + + public Ciala(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Ciala"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074206, // Excuse me please traveler, might I have a little of your time? + 1074186 + ) + ); // Come here, I have a task. + } + + 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(); + } + } + + [QuesterName("Aniel (The Heartwood)")] + public class Aniel : BaseCreature + { + [Constructible] + public Aniel() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the arborist"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenPants(0x901)); + AddItem(new LeafChest()); + AddItem(new HalfApron(Utility.RandomYellowHue())); + AddItem(new ElvenBoots(0x901)); + } + + public Aniel(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Aniel"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074220, // May I call you friend?� I have a favor to beg of you. + 1074222 + ) + ); // Could I trouble you for some assistance? + } + + 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(); + } + } + + [QuesterName("Aulan (The Heartwood)")] + public class Aulan : BaseCreature + { + [Constructible] + public Aulan() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the expeditionist"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + Item item; + + item = new ElvenBoots(); + item.Hue = Utility.RandomYellowHue(); + AddItem(item); + + AddItem(new ElvenPants(Utility.RandomGreenHue())); + AddItem(new Cloak(Utility.RandomGreenHue())); + AddItem(new Circlet()); + + item = new HideChest(); + item.Hue = Utility.RandomYellowHue(); + AddItem(item); + + item = new HideGloves(); + item.Hue = Utility.RandomYellowHue(); + AddItem(item); + } + + public Aulan(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Aulan"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074188, // Weakling! You are not up to the task I have. + 1074191, // Just keep walking away!� I thought so. Coward!� I�ll bite your legs off! + 1074195 + ) + ); // You there, in the stupid hat! Come here. + } + + 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(); + } + } + + [QuesterName("Brinnae (The Heartwood)")] + public class Brinnae : BaseCreature + { + [Constructible] + public Brinnae() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the wise"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new ElvenBoots()); + AddItem(new FemaleLeafChest()); + AddItem(new LeafArms()); + AddItem(new HidePants()); + AddItem(new ElvenCompositeLongbow()); + } + + public Brinnae(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Brinnae"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074212, // *yawn* You busy? + 1074210 + ) + ); // Hi.� Looking for something to do? + } + + 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(); + } + } + + [QuesterName("Elder Caelas (The Heartwood)")] + public class Caelas : BaseCreature + { + [Constructible] + public Caelas() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the wise"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenBoots(0x1BB)); + AddItem(new MaleElvenRobe(0x489)); + AddItem(new Cloak(0x718)); + AddItem(new RoyalCirclet()); + } + + public Caelas(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Elder Caelas"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074204, // Greetings seeker.� I have an urgent matter for you, if you are willing. + 1074201 + ) + ); // Waste not a minute! There�s work to be done. + } + + 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(); + } + } + + [QuesterName("Clehin (The Heartwood)")] + public class Clehin : BaseCreature + { + [Constructible] + public Clehin() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the soil nurturer"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenBoots()); + AddItem(new ElvenShirt()); + AddItem(new LeafTonlet()); + } + + public Clehin(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Clehin"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074211, // I could use some help. + 1074186 + ) + ); // Come here, I have a task. + } + + 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 class Cloorne : BaseCreature + { + [Constructible] + public Cloorne() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the expeditionist"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenBoots(0x3B2)); + AddItem(new RadiantScimitar()); + AddItem(new WingedHelm()); + + Item item; + + item = new WoodlandLegs(); + item.Hue = 0x74A; + AddItem(item); + + item = new HideChest(); + item.Hue = 0x726; + AddItem(item); + + item = new LeafArms(); + item.Hue = 0x73E; + AddItem(item); + } + + public Cloorne(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Cloorne"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074185, // Hey you! Want to help me out? + 1074186 + ) + ); // Come here, I have a task. + } + + 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(); + } + } + + [QuesterName("Salaenih (The Heartwood)")] + public class Salaenih : BaseCreature + { + [Constructible] + public Salaenih() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the expeditionist"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenBoots()); + AddItem(new WarCleaver()); + + Item item; + + item = new WoodlandBelt(); + item.Hue = 0x597; + AddItem(item); + + item = new VultureHelm(); + item.Hue = 0x1BB; + AddItem(item); + + item = new WoodlandLegs(); + item.Hue = 0x1BB; + AddItem(item); + + item = new WoodlandChest(); + item.Hue = 0x1BB; + AddItem(item); + + item = new WoodlandArms(); + item.Hue = 0x1BB; + AddItem(item); + } + + public Salaenih(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Salaenih"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074207, // Good day to you friend! Allow me to offer you a fabulous opportunity!� Thrills and adventure await! + 1074209 + ) + ); // Hey, could you help me out with something? + } + + 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(); + } + } + + [QuesterName("Vilo (The Heartwood)")] + public class Vilo : BaseCreature + { + [Constructible] + public Vilo() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the guard"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenBoots(0x901)); + AddItem(new OrnateAxe()); + AddItem(new WoodlandBelt(0x592)); + AddItem(new VultureHelm()); + AddItem(new WoodlandLegs()); + AddItem(new WoodlandChest()); + AddItem(new WoodlandArms()); + AddItem(new WoodlandGorget()); + } + + public Vilo(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Vilo"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074210, // Hi.� Looking for something to do? + 1074220 + ) + ); // May I call you friend?� I have a favor to beg of you. + } + + 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(); + } + } + + [QuesterName("Tholef (The Heartwood)")] + public class Tholef : BaseCreature + { + [Constructible] + public Tholef() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the grape tender"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new Sandals(0x901)); + AddItem(new FullApron(0x756)); + AddItem(new ShortPants(0x28C)); + AddItem(new Shirt(0x28C)); + + Item item; + + item = new LeafArms(); + item.Hue = 0x28C; + AddItem(item); + } + + public Tholef(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Tholef"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074209, // Hey, could you help me out with something? + 1074184 + ) + ); // Come here, I have work for you. + } + + 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(); + } + } + + [QuesterName("Tillanil (The Heartwood)")] + public class Tillanil : BaseCreature + { + [Constructible] + public Tillanil() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the grape tender"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new Sandals(0x1BB)); + AddItem(new Tunic(0x759)); + AddItem(new ShortPants(0x21)); + } + + public Tillanil(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Tillanil"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074187, // Want a job? + 1074222 + ) + ); // Could I trouble you for some assistance? + } + + 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(); + } + } + + [QuesterName("Waelian (The Heartwood)")] + public class Waelian : BaseCreature + { + [Constructible] + public Waelian() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the trinket weaver"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new Shoes(0x901)); + AddItem(new SmithHammer()); + AddItem(new LongPants(0x340)); + AddItem(new GemmedCirclet()); + + Item item; + + item = new LeafChest(); + item.Hue = 0x344; + AddItem(item); + } + + public Waelian(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Waelian"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074221, // Greetings!� I have a small task for you good traveler. + 1074201 + ) + ); // Waste not a minute! There�s work to be done. + } + + 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(); + } + } + + [QuesterName("Sleen (The Heartwood)")] + public class Sleen : BaseCreature + { + [Constructible] + public Sleen() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the trinket weaver"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenBoots(0x901)); + AddItem(new SmithHammer()); + AddItem(new Cloak(0x75A)); + AddItem(new ElvenShirt()); + } + + public Sleen(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Sleen"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074200, // Thank goodness you are here, there�s no time to lose. + 1074206 + ) + ); // Excuse me please traveler, might I have a little of your time? + } + + 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(); + } + } + + [QuesterName("Unoelil (The Heartwood)")] + public class Unoelil : BaseCreature + { + [Constructible] + public Unoelil() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the bark weaver"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenBoots(0x1BB)); + AddItem(new ShortPants(0x1BB)); + AddItem(new Tunic(0x64D)); + } + + public Unoelil(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Unoelil"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074186, // Come here, I have a task. + 1074209 + ) + ); // Hey, could you help me out with something? + } + + 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(); + } + } + + [QuesterName("Anolly (The Heartwood)")] + public class Anolly : BaseCreature + { + [Constructible] + public Anolly() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the bark weaver"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new Sandals(0x901)); + AddItem(new ShortPants(0x3B3)); + AddItem(new FullApron(0x1BB)); + AddItem(new SmithHammer()); + } + + public Anolly(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Anolly"; + public override bool CanTeach => true; + + 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(); + } + } + + [QuesterName("Jusae (The Heartwood)")] + public class Jusae : BaseCreature + { + [Constructible] + public Jusae() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the bowcrafter"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new Sandals(0x901)); + AddItem(new ShortPants(0x661)); + AddItem(new MagicalShortbow()); + + Item item; + + item = new HideChest(); + item.Hue = 0x27B; + AddItem(item); + + item = new HidePauldrons(); + item.Hue = 0x27E; + AddItem(item); + } + + public Jusae(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Jusae"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074210, // Hi.� Looking for something to do? + 1074213 + ) + ); // Hey buddy.� Looking for work? + } + + 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(); + } + } + + [QuesterName("Cillitha (The Heartwood)")] + public class Cillitha : BaseCreature + { + [Constructible] + public Cillitha() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the bowcrafter"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenBoots(0x901)); + AddItem(new ElvenShirt(0x731)); + AddItem(new LeafLegs()); + } + + public Cillitha(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Cillitha"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074223, // Have you done it yet?� Oh, I haven�t told you, have I? + 1074213 + ) + ); // Hey buddy.� Looking for work? + } + + 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(); + } + } + + [QuesterName("Lohn (The Heartwood)")] + public class Lohn : BaseCreature + { + [Constructible] + public Lohn() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the metal weaver"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new Shoes(0x901)); + AddItem(new LongPants(0x359)); + AddItem(new SmithHammer()); + AddItem(new GemmedCirclet()); + + Item item; + + item = new LeafChest(); + item.Hue = 0x359; + AddItem(item); + } + + public Lohn(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Lohn"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074187, // Want a job? + 1074209 + ) + ); // Hey, could you help me out with something? + } + + 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(); + } + } + + [QuesterName("Olla (The Heartwood)")] + public class Olla : BaseCreature + { + [Constructible] + public Olla() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the metal weaver"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenBoots()); + AddItem(new LongPants(0x3B3)); + AddItem(new SmithHammer()); + AddItem(new FullApron(0x1BB)); + AddItem(new ElvenShirt()); + } + + public Olla(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Olla"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074187, // Want a job? + 1074185 + ) + ); // Hey you! Want to help me out? + } + + 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(); + } + } + + [QuesterName("Thallary (The Heartwood)")] + public class Thallary : BaseCreature + { + [Constructible] + public Thallary() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the cloth weaver"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new Sandals(0x901)); + AddItem(new LongPants(0x72E)); + AddItem(new Cloak(0x3B3)); + AddItem(new FancyShirt(0x13)); + } + + public Thallary(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Thallary"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074221, // Greetings!� I have a small task for you good traveler. + 1074212 + ) + ); // *yawn* You busy? + } + + 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(); + } + } + + [QuesterName("Ahie (The Heartwood)")] + public class Ahie : BaseCreature + { + [Constructible] + public Ahie() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the cloth weaver"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new Boots(0x901)); + AddItem(new Skirt(0x1C)); + AddItem(new Cloak(0x62)); + AddItem(new FancyShirt(0x738)); + } + + public Ahie(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Ahie"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074206, // Excuse me please traveler, might I have a little of your time? + 1074203 + ) + ); // Hello friend. I realize you are busy but if you would be willing to render me a service I can assure you that you will be judiciously renumerated. + } + + 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 class Tyeelor : BaseCreature + { + [Constructible] + public Tyeelor() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the expeditionist"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new ElvenBoots(0x1BB)); + + Item item; + + item = new WoodlandLegs(); + item.Hue = 0x236; + AddItem(item); + + item = new WoodlandChest(); + item.Hue = 0x236; + AddItem(item); + + item = new WoodlandArms(); + item.Hue = 0x236; + AddItem(item); + + item = new VultureHelm(); + item.Hue = 0x236; + AddItem(item); + + item = new WoodlandBelt(); + item.Hue = 0x236; + AddItem(item); + } + + public Tyeelor(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Tyeelor"; + + 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 class Athailon : BaseCreature + { + [Constructible] + public Athailon() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the expeditionist"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new ElvenBoots(0x901)); + AddItem(new WoodlandBelt()); + AddItem(new DiamondMace()); + + Item item; + + item = new WoodlandLegs(); + item.Hue = 0x3B2; + AddItem(item); + + item = new FemaleElvenPlateChest(); + item.Hue = 0x3B2; + AddItem(item); + + item = new WoodlandArms(); + item.Hue = 0x3B2; + AddItem(item); + + item = new WingedHelm(); + item.Hue = 0x3B2; + AddItem(item); + } + + public Athailon(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Athailon"; + + 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 class ElderTaellia : BaseCreature + { + [Constructible] + public ElderTaellia() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the wise"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new ThighBoots(0x127)); + AddItem(new FemaleElvenRobe(Utility.RandomBrightHue())); + AddItem(new MagicWand()); + AddItem(new Circlet()); + } + + public ElderTaellia(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Elder Taellia"; + + 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 class ElderMallew : BaseCreature + { + [Constructible] + public ElderMallew() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the wise"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new ElvenBoots(0x1BB)); + AddItem(new Cloak(0x3B2)); + AddItem(new Circlet()); + + Item item; + + item = new LeafTonlet(); + item.Hue = 0x544; + AddItem(item); + + item = new LeafChest(); + item.Hue = 0x538; + AddItem(item); + + item = new LeafArms(); + item.Hue = 0x528; + AddItem(item); + } + + public ElderMallew(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Elder Mallew"; + + 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 class ElderAbbein : BaseCreature + { + [Constructible] + public ElderAbbein() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the wise"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new ElvenBoots(0x72C)); + AddItem(new FemaleElvenRobe(0x8B0)); + AddItem(new RoyalCirclet()); + } + + public ElderAbbein(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Elder Abbein"; + + 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 class ElderVicaie : BaseCreature + { + [Constructible] + public ElderVicaie() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the wise"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new ElvenBoots()); + AddItem(new Tunic(0x732)); + + Item item; + + item = new LeafLegs(); + item.Hue = 0x3B2; + AddItem(item); + } + + public ElderVicaie(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Elder Vicaie"; + + 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 class ElderJothan : BaseCreature + { + [Constructible] + public ElderJothan() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the wise"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new ThighBoots()); + AddItem(new ElvenPants(0x58D)); + AddItem(new ElvenShirt(Utility.RandomYellowHue())); + AddItem(new Cloak(Utility.RandomBrightHue())); + AddItem(new Circlet()); + } + + public ElderJothan(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Elder Jothan"; + + 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 class ElderAlethanian : BaseCreature + { + [Constructible] + public ElderAlethanian() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the wise"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new ElvenBoots()); + AddItem(new HidePants()); + AddItem(new HideFemaleChest()); + AddItem(new HidePauldrons()); + AddItem(new GemmedCirclet()); + } + + public ElderAlethanian(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Elder Alethanian"; + + 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 class Rebinil : BaseCreature + { + [Constructible] + public Rebinil() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the healer"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Sandals(0x715)); + AddItem(new FemaleElvenRobe(0x742)); + AddItem(new RoyalCirclet()); + } + + public Rebinil(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Rebinil"; + + 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 class Aluniol : BaseCreature + { + [Constructible] + public Aluniol() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the healer"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new ElvenBoots(0x1BB)); + AddItem(new MaleElvenRobe(0x47E)); + AddItem(new WildStaff()); + } + + public Aluniol(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Aluniol"; + + 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 class Olaeni : BaseCreature + { + [Constructible] + public Olaeni() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the thaumaturgist"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Shoes(0x75A)); + AddItem(new FemaleElvenRobe(0x13)); + AddItem(new MagicWand()); + AddItem(new GemmedCirclet()); + } + + public Olaeni(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Olaeni"; + + 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 class Bolaevin : BaseCreature + { + [Constructible] + public Bolaevin() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the arcanist"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new ElvenBoots(0x3B2)); + AddItem(new RoyalCirclet()); + AddItem(new LeafChest()); + AddItem(new LeafArms()); + + Item item; + + item = new LeafLegs(); + item.Hue = 0x1BB; + AddItem(item); + } + + public Bolaevin(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Bolaevin"; + + 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 class LorekeeperAneen : BaseCreature + { + [Constructible] + public LorekeeperAneen() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the keeper of tradition"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Sandals(0x1BB)); + AddItem(new MaleElvenRobe(0x48F)); + AddItem(new MagicWand()); + } + + public LorekeeperAneen(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Lorekeeper Aneen"; + + 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 class Daelas : BaseCreature + { + [Constructible] + public Daelas() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the arborist"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new ElvenBoots(0x901)); + AddItem(new ElvenPants(0x8AB)); + + Item item; + + item = new LeafChest(); + item.Hue = 0x8B0; + AddItem(item); + + item = new LeafGloves(); + item.Hue = 0x1BB; + AddItem(item); + } + + public Daelas(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Daelas"; + + 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 class Alelle : BaseCreature + { + [Constructible] + public Alelle() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the arborist"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new ElvenBoots(0x1BB)); + + Item item; + + item = new FemaleLeafChest(); + item.Hue = 0x3A; + AddItem(item); + + item = new LeafLegs(); + item.Hue = 0x74C; + AddItem(item); + + item = new LeafGloves(); + item.Hue = 0x1BB; + AddItem(item); + } + + public Alelle(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Alelle"; + + 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(); + } + } + + [QuesterName("Nillaen (The Heartwood)")] + public class LorekeeperNillaen : BaseCreature + { + [Constructible] + public LorekeeperNillaen() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the keeper of tradition"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new Shoes(0x1BB)); + AddItem(new LongPants(0x1FB)); + AddItem(new ElvenShirt()); + AddItem(new GemmedCirclet()); + AddItem(new BodySash(0x25)); + AddItem(new BlackStaff()); + } + + public LorekeeperNillaen(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Lorekeeper Nillaen"; + public override bool CanTeach => true; + + 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(); + } + } + + [QuesterName("Ryal (The Heartwood)")] + public class LorekeeperRyal : BaseCreature + { + [Constructible] + public LorekeeperRyal() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the keeper of tradition"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenBoots(0x1BB)); + AddItem(new LeafTonlet()); + AddItem(new ElvenShirt(0x2DD)); + AddItem(new Cloak(0x219)); + AddItem(new GnarledStaff()); + } + + public LorekeeperRyal(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Lorekeeper Ryal"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074204, // Greetings seeker.� I have an urgent matter for you, if you are willing. + 1074200 + ) + ); // Thank goodness you are here, there�s no time to lose. + } + + 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(); + } + } + + [QuesterName("Braen (The Heartwood)")] + public class Braen : BaseCreature + { + [Constructible] + public Braen() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the thaumaturgist"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new Sandals(0x714)); + AddItem(new MaleElvenRobe(0x64A)); + AddItem(new MagicWand()); + } + + public Braen(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Braen"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1074187); // Want a job? + } + + 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(); + } + } + + [QuesterName("Elder Acob (The Heartwood)")] + public class ElderAcob : BaseCreature + { + [Constructible] + public ElderAcob() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the wise"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenBoots(0x714)); + AddItem(new ElvenShirt(Utility.RandomBrightHue())); + AddItem(new HidePants()); + } + + public ElderAcob(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Elder Acob"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1074197); // Pardon me, but if you could spare some time I�d greatly appreciate it. + } + + 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 class LorekeeperCalendor : BaseCreature + { + [Constructible] + public LorekeeperCalendor() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the keeper of tradition"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenBoots(0x714)); + AddItem(new ElvenShirt(Utility.RandomOrangeHue())); + AddItem(new Kilt(Utility.RandomOrangeHue())); + AddItem(new RoyalCirclet()); + } + + public LorekeeperCalendor(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Lorekeeper Calendor"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1074204); // Greetings seeker.� I have an urgent matter for you, if you are willing. + } + + 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 class LorekeeperSiarra : BaseCreature + { + [Constructible] + public LorekeeperSiarra() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the keeper of tradition"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new Sandals(0x1BB)); + AddItem(new ElvenShirt()); + AddItem(new LeafTonlet()); + AddItem(new GemmedCirclet()); + } + + public LorekeeperSiarra(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Lorekeeper Siarra"; + public override bool CanTeach => true; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1074206); // Excuse me please traveler, might I have a little of your time? + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Definitions/Heritage.cs b/Projects/UOContent/Engines/MLQuests/Definitions/Heritage.cs index 7b59cd5d7..03e077ac6 100644 --- a/Projects/UOContent/Engines/MLQuests/Definitions/Heritage.cs +++ b/Projects/UOContent/Engines/MLQuests/Definitions/Heritage.cs @@ -1,802 +1,894 @@ -using System; -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; -using Server.Engines.Spawners; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Definitions -{ - public class Seasons : MLQuest - { - public Seasons() - { - Activated = true; - Title = 1072782; // Seasons - Description = - 1072802; // *rumbling growl* *sniff* ... not-smell ... seek-fight ... not-smell ... fear-stench ... *rumble* ... cold-soon-time comes ... hungry ... eat-fish ... sleep-soon-time ... *deep fang-filled yawn* ... much-fish. - RefusalMessage = 1072810; // *yawn* ... cold-soon-time ... *growl* - InProgressMessage = 1072811; // *sniff* *sniff* ... not-much-fish ... hungry ... *grumble* - CompletionMessage = 1074174; // *sniff* fish! much-fish! - - Objectives.Add(new CollectObjective(20, typeof(RawFishSteak), 1022426)); // raw fish steak - - Rewards.Add(new DummyReward(1072803)); // The boon of Maul. - } - - public override bool RecordCompletion => true; - - public override void GetRewards(MLQuestInstance instance) - { - instance.Player.SendLocalizedMessage(1074940, "", - 0x2A); // You have gained the boon of Maul! Your understanding of the seasons grows. You are one step closer to claiming your elven heritage. - instance.ClaimRewards(); // skip gump - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Darius"), new Point3D(4310, 954, 10), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Darius"), new Point3D(4310, 954, 10), Map.Trammel); - - PutSpawner(new Spawner(1, 5, 10, 0, 5, "MaulTheBear"), new Point3D(1730, 257, 16), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "MaulTheBear"), new Point3D(1730, 257, 16), Map.Trammel); - } - } - - public class CaretakerOfTheLand : MLQuest - { - public CaretakerOfTheLand() - { - Activated = true; - Title = 1072783; // Caretaker of the Land - Description = - 1072812; // Hrrrrr. Hurrrr. Huuuman. *creaking branches* Suuun on baaark, roooooots diiig deeeeeep, wiiind caaaresses leeeaves … Hrrrrr. Saaap of Sooosaria feeeeeeds us. Hrrrrr. Huuuman leeearn. Caaaretaker of plaaants … teeend … prooove.
- RefusalMessage = 1072813; // Hrrrrr. Hrrrrr. Huuuman. - InProgressMessage = - 1072814; // Hrrrr. Hrrrr. Roooooots neeeeeed saaap of Sooosaria. Hrrrrr. Roooooots tiiingle neeeaaar Yeeew. Seeeaaarch. Hrrrr! - CompletionMessage = 1074175; // Thiiirsty. Hurrr. Hurrr. - - Objectives.Add(new CollectObjective(1, typeof(SapOfSosaria), "sap of sosaria")); - - Rewards.Add(new DummyReward(1072804)); // The boon of Strongroot. - } - - public override bool RecordCompletion => true; - - public override void GetRewards(MLQuestInstance instance) - { - instance.Player.SendLocalizedMessage(1074941, "", - 0x2A); // You have gained the boon of Strongroot! You have been approved by one whose roots touch the bones of Sosaria. You are one step closer to claiming your elven heritage. - instance.ClaimRewards(); // skip gump - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Strongroot"), new Point3D(597, 1744, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Strongroot"), new Point3D(597, 1744, 0), Map.Trammel); - - PutSpawner(new Spawner(1, TimeSpan.FromSeconds(30), TimeSpan.FromMinutes(2), 0, 12, "SapOfSosaria"), - new Point3D(757, 1004, 0), Map.Felucca); - PutSpawner(new Spawner(1, TimeSpan.FromSeconds(30), TimeSpan.FromMinutes(2), 0, 12, "SapOfSosaria"), - new Point3D(757, 1004, 0), Map.Trammel); - } - } - - public class WisdomOfTheSphynx : MLQuest - { - public WisdomOfTheSphynx() - { - Activated = true; - Title = 1072784; // Wisdom of the Sphynx - Description = - 1072822; // I greet thee human and divine my boon thou seek. Convey hence the object of my riddle and I shall reward thee with thy desire.

Three lives have I.
Gentle enough to soothe the skin,
Light enough to caress the sky,
Hard enough to crack rocks
What am I? - RefusalMessage = 1072823; // As thou wish, human. - InProgressMessage = - 1072824; // I give thee a hint then human. The answer to my riddle must be held carefully or it cannot be contained at all. Bring this elusive item to me in a suitable container. - CompletionMessage = 1074176; // Ah, thus it ends. - - Objectives.Add(new InternalObjective()); - - Rewards.Add(new DummyReward(1072805)); // The boon of Enigma. - } - - public override bool RecordCompletion => true; - - public override void GetRewards(MLQuestInstance instance) - { - instance.Player.SendLocalizedMessage(1074945, "", - 0x2A); // You have gained the boon of Enigma! You are wise enough to know how little you know. You are one step closer to claiming your elven heritage. - instance.ClaimRewards(); // skip gump - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Enigma"), new Point3D(1828, 961, 7), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Enigma"), new Point3D(1828, 961, 7), Map.Trammel); - } - - private class InternalObjective : CollectObjective - { - public InternalObjective() - : base(1, typeof(Pitcher), 1074869) // The answer to the riddle. - { - } - - public override bool ShowDetailed => false; - - public override bool CheckItem(Item item) => item is Pitcher pitcher && pitcher.Content == BeverageType.Water && pitcher.Quantity > 0; - } - } - - public class DefendingTheHerd : MLQuest - { - public DefendingTheHerd() - { - Activated = true; - Title = 1072785; // Defending the Herd - Description = - 1072825; // *snort* ... guard-mates ... guard-herd *hoof stomp* ... defend-with-hoof-and-horn ... thirsty-drink. *proud head-toss* - RefusalMessage = 1072826; // *snort* - InProgressMessage = 1072827; // *impatient hoof stomp* ... thirsty herd ... water scent. - CompletionNotice = CompletionNoticeShort; - - Objectives.Add( - new EscortObjective(new QuestArea(1074779, "Bravehorn's drinking pool"))); // Bravehorn's drinking pool - - Rewards.Add(new DummyReward(1072806)); // The boon of Bravehorn. - } - - public override bool RecordCompletion => true; - - public override void GetRewards(MLQuestInstance instance) - { - instance.Player.SendLocalizedMessage(1074942, "", - 0x2A); // You have gained the boon of Bravehorn! You have glimpsed the nobility of those that sacrifice themselves for their people. You are one step closer to claiming your elven heritage. - instance.ClaimRewards(); // skip gump - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(90), 0, 5, "Bravehorn"), - new Point3D(1193, 2467, 0), Map.Felucca); - PutSpawner(new Spawner(1, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(90), 0, 5, "Bravehorn"), - new Point3D(1193, 2467, 0), Map.Trammel); - - PutSpawner(new Spawner(5, TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(30), 0, 8, "BravehornsMate"), - new Point3D(1192, 2467, 0), Map.Felucca); - PutSpawner(new Spawner(5, TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(30), 0, 8, "BravehornsMate"), - new Point3D(1192, 2467, 0), Map.Trammel); - } - } - - public class TheBalanceOfNature : MLQuest - { - public TheBalanceOfNature() - { - Activated = true; - Title = 1072786; // The Balance of Nature - Description = - 1072829; // Ho, there human. Why do you seek out the Huntsman? The hunter serves the land by culling both predators and prey. The hunter maintains the essential balance of life and does not kill for sport or glory. If you seek my favor, human, then demonstrate you are capable of the duty. Cull the wolves nearby. - RefusalMessage = 1072830; // Then begone. I have no time to waste on you, human. - InProgressMessage = 1072831; // The timber wolves are easily tracked, human. - - Objectives.Add(new KillObjective(15, new[] { typeof(TimberWolf) }, "timber wolves", - new QuestArea(1074833, "Huntsman's Forest"))); // Huntsman's Forest - - Rewards.Add(new DummyReward(1072807)); // The boon of the Huntsman. - } - - public override bool RecordCompletion => true; - - public override void GetRewards(MLQuestInstance instance) - { - instance.Player.SendLocalizedMessage(1074943, "", - 0x2A); // You have gained the boon of the Huntsman! You have been given a taste of the bittersweet duty of those who guard the balance. You are one step closer to claiming your elven heritage. - instance.ClaimRewards(); // skip gump - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Huntsman"), new Point3D(1676, 593, 16), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Huntsman"), new Point3D(1676, 593, 16), Map.Trammel); - - PutSpawner(new Spawner(5, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(15), 0, 10, "TimberWolf"), - new Point3D(1671, 592, 16), Map.Felucca); - PutSpawner(new Spawner(5, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(15), 0, 10, "TimberWolf"), - new Point3D(1671, 592, 16), Map.Trammel); - } - } - - public class TheJoysOfLife : MLQuest - { - public TheJoysOfLife() - { - Activated = true; - Title = 1072787; // The Joys of Life - Description = - 1072832; // *giggle* So serious, so grim! *tickle* Enjoy life! Have fun! Laugh! Be merry! *giggle* Find three of my baubles ... *giggle* I hid them! *giggles hysterically* Hid them! La la la! Bring them quickly! They are magical and will hide themselves again if you are too slow. - RefusalMessage = 1072833; // *giggle* Too serious. Too thinky! - InProgressMessage = 1072834; // Magical baubles hidden, find them as you're bidden! *giggle* - CompletionMessage = 1074177; // *giggle* So pretty! - - Objectives.Add(new CollectObjective(3, typeof(ABauble), "arielle's baubles")); - - Rewards.Add(new DummyReward(1072809)); // The boon of Arielle. - } - - public override bool RecordCompletion => true; - - public override void GetRewards(MLQuestInstance instance) - { - instance.Player.SendLocalizedMessage(1074944, "", - 0x2A); // You have gained the boon of Arielle! You have been taught the importance of laughter and light spirits. You are one step closer to claiming your elven heritage. - instance.ClaimRewards(); // skip gump - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Arielle"), new Point3D(1560, 1182, -27), Map.Ilshenar); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Arielle"), new Point3D(3366, 292, 9), - Map.Felucca); // Felucca spawn for reds - - PutSpawner(new Spawner(6, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(30), 0, 20, "ABauble"), - new Point3D(1585, 1212, -13), Map.Ilshenar); - } - } - - [QuesterName("Maul")] - public class MaulTheBear : GrizzlyBear - { - [Constructible] - public MaulTheBear() - { - AI = AIType.AI_Vendor; - FightMode = FightMode.None; - Tamable = false; - } - - public MaulTheBear(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Maul"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Strongroot : Treefellow - { - [Constructible] - public Strongroot() - { - AI = AIType.AI_Vendor; - FightMode = FightMode.None; - } - - public Strongroot(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Strongroot"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Enigma : BaseCreature - { - [Constructible] - public Enigma() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - BodyValue = 788; - BaseSoundID = 0x3EE; - - InitStats(100, 100, 25); - } - - public Enigma(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Enigma"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Bravehorn : BaseEscortable - { - [Constructible] - public Bravehorn() - { - } - - public Bravehorn(Serial serial) - : base(serial) - { - } - - public override bool StaticMLQuester => true; - public override bool InitialInnocent => true; - public override string DefaultName => "Bravehorn"; - - public override void InitBody() - { - Body = 0xEA; - - SetStr(41, 71); - SetDex(47, 77); - SetInt(27, 57); - - SetHits(27, 41); - SetMana(0); - - SetDamage(5, 9); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 20, 25); - SetResistance(ResistanceType.Cold, 5, 10); - - SetSkill(SkillName.MagicResist, 26.8, 44.5); - SetSkill(SkillName.Tactics, 29.8, 47.5); - SetSkill(SkillName.Wrestling, 29.8, 47.5); - - Fame = 300; - Karma = 0; - - VirtualArmor = 24; - } - - public override void InitOutfit() - { - } - - public override int GetAttackSound() => 0x82; - - public override int GetHurtSound() => 0x83; - - public override int GetDeathSound() => 0x84; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BravehornsMate : Hind - { - [Constructible] - public BravehornsMate() => Tamable = false; - - public BravehornsMate(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "bravehorn's mate"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Huntsman : Centaur - { - [Constructible] - public Huntsman() - { - AI = AIType.AI_Vendor; - FightMode = FightMode.None; - } - - public Huntsman(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Huntsman"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Arielle : Pixie - { - [Constructible] - public Arielle() - { - AI = AIType.AI_Vendor; - FightMode = FightMode.None; - } - - public Arielle(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Arielle"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Ingenuity : MLQuest - { - public Ingenuity() - { - Activated = true; - Title = 1074350; // Ingenuity - Description = - 1074462; // The best thing about my job is that I do a little bit of everything, every day. It's what we're good at really. Just picking up something and making it do something else. Listen, I'm really low on parts. Are you interested in fetching me some supplies? - RefusalMessage = 1074508; // Okay. Best of luck with your other endeavors. - InProgressMessage = - 1074509; // Lord overseers are the best source I know for power crystals of the type I need. Iron golems too, can have them but they're harder to find. - CompletionMessage = - 1074510; // Do you have those power crystals? I'm ready to put the finishing touches on my latest experiment. - CompletionNotice = CompletionNoticeShortReturn; - - Objectives.Add(new CollectObjective(10, typeof(PowerCrystal), "Power Crystals")); - - Rewards.Add(new DummyReward(1074875)); // Another step closer to becoming human. - } - - public override bool RecordCompletion => true; - - public override void GetRewards(MLQuestInstance instance) - { - instance.Player.SendLocalizedMessage(1074946, "", - 0x2A); // You have demonstrated your ingenuity! Humans are jacks of all trades and know a little about a lot of things. You are one step closer to achieving humanity. - instance.ClaimRewards(); // skip gump - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Nedrick"), new Point3D(2958, 3466, 15), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Nedrick"), new Point3D(2958, 3466, 15), Map.Trammel); - - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Sledge"), new Point3D(2673, 2129, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Sledge"), new Point3D(2673, 2129, 0), Map.Trammel); - } - } - - public class HeaveHo : MLQuest - { - public HeaveHo() - { - Activated = true; - Title = 1074351; // Heave Ho! - Description = - 1074519; // Ho there! There's nothing quite like a day's honest labor to make you appreciate being alive. Hey, maybe you'd like to help out with this project? These crates need to be delivered to Sledge. The only thing is -- it's a bit of a rush job and if you don't make it in time, he won't take them. Can I trust you to help out? - RefusalMessage = 1074521; // Oh yah, if you're too busy, no problem. - InProgressMessage = - 1074522; // Sledge can be found in Buc's Den. Better hurry, he won't take those crates if you take too long with them. - CompletionMessage = 1074523; // Hey, if you have cargo for me, you can start unloading over here. - CompletionNotice = CompletionNoticeShort; - - Objectives.Add(new TimedDeliverObjective(TimeSpan.FromHours(1), typeof(CrateForSledge), 5, "Crates for Sledge", - typeof(Sledge))); - - Rewards.Add(new DummyReward(1074875)); // Another step closer to becoming human. - } - - public override bool RecordCompletion => true; - - public override void GetRewards(MLQuestInstance instance) - { - instance.Player.SendLocalizedMessage(1074948, "", - 0x2A); // You have demonstrated your physical strength! Humans can carry vast loads without complaint. You are one step closer to achieving humanity. - instance.ClaimRewards(); // skip gump - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Patricus"), new Point3D(3007, 823, -2), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Patricus"), new Point3D(3007, 823, -2), Map.Trammel); - } - } - - // This is not a real quest, it is only used as a reference - public class HumanInNeed : MLQuest - { - public HumanInNeed() - { - Title = 1075011; // A quest that asks you to defend a human in need. - Description = 0; - RefusalMessage = 0; - InProgressMessage = 0; - } - - public override bool RecordCompletion => true; - - public static void AwardTo(PlayerMobile pm) - { - MLQuestSystem.GetOrCreateContext(pm).SetDoneQuest(MLQuestSystem.FindQuest(typeof(HumanInNeed))); - pm.SendLocalizedMessage(1074949, "", - 0x2A); // You have demonstrated your compassion! Your kind actions have been noted. - } - } - - public class AllSeasonAdventurer : MLQuest - { - public AllSeasonAdventurer() - { - Activated = true; - Title = 1074353; // All Season Adventurer - Description = - 1074527; // It's all about hardship, suffering, struggle and pain. Without challenges, you've got nothing to test yourself against -- and that's what life is all about. Self improvement! Honing your body and mind! Overcoming obstacles ... You'll see what I mean if you take on my challenge. - RefusalMessage = 1074528; // My way of life isn't for everyone, that's true enough. - InProgressMessage = 1074529; // You're not making much progress in the honing-mind-and-body department, are you? - CompletionNotice = CompletionNoticeShortReturn; - - Objectives.Add(new KillObjective(5, new[] { typeof(Efreet) }, "efreets", - new QuestArea(1074808, "Fire"))); // Fire - Objectives.Add(new KillObjective(5, new[] { typeof(IceFiend) }, "ice fiends", - new QuestArea(1074809, "Ice"))); // Ice - - Rewards.Add(new DummyReward(1074875)); // Another step closer to becoming human. - } - - public override bool RecordCompletion => true; - - public override void GetRewards(MLQuestInstance instance) - { - instance.Player.SendLocalizedMessage(1074947, "", - 0x2A); // You have demonstrated your toughness! Humans are able to endure unimaginable hardships in pursuit of their goals. You are one step closer to achieving humanity. - instance.ClaimRewards(); // skip gump - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Belulah"), new Point3D(3782, 1266, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Belulah"), new Point3D(3782, 1266, 0), Map.Trammel); - } - } - - [QuesterName("Sledge (Buc's Den)")] - public class Sledge : BaseCreature - { - [Constructible] - public Sledge() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Versatile"; - Body = 400; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - AddItem(new Tunic(Utility.RandomNeutralHue())); - AddItem(new LongPants(Utility.RandomBlueHue())); - AddItem(new Cloak(Utility.RandomBrightHue())); - AddItem(new ElvenBoots(Utility.RandomNeutralHue())); - AddItem(new Backpack()); - } - - public Sledge(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Sledge"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074188, // Weakling! You are not up to the task I have. - 1074195)); // You there, in the stupid hat! Come here. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Patricus (Vesper)")] - public class Patricus : BaseCreature - { - [Constructible] - public Patricus() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Trader"; - Body = 400; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - AddItem(new FancyShirt(Utility.RandomNeutralHue())); - AddItem(new LongPants(Utility.RandomBrightHue())); - AddItem(new Cloak(0x1BB)); - AddItem(new Shoes(Utility.RandomNeutralHue())); - AddItem(new Backpack()); - } - - public Patricus(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Patricus"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Belulah (Nujel'm)")] // On OSI it's "Belulah (Nu'Jelm)" (incorrect spelling) - public class Belulah : BaseCreature - { - [Constructible] - public Belulah() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the scorned"; - Female = true; - Body = 401; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new FancyShirt(Utility.RandomBlueHue())); - AddItem(new LongPants(Utility.RandomNondyedHue())); - AddItem(new Boots()); - } - - public Belulah(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Belulah"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - /* - * 1074205 - Oh great adventurer, would you please assist a weak soul in need of aid? - * 1074206 - Excuse me please traveler, might I have a little of your time? - */ - MLQuestSystem.Tell(this, pm, Utility.Random(1074205, 2)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; +using Server.Engines.Spawners; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Definitions +{ + public class Seasons : MLQuest + { + public Seasons() + { + Activated = true; + Title = 1072782; // Seasons + Description = + 1072802; // *rumbling growl* *sniff* ... not-smell ... seek-fight ... not-smell ... fear-stench ... *rumble* ... cold-soon-time comes ... hungry ... eat-fish ... sleep-soon-time ... *deep fang-filled yawn* ... much-fish. + RefusalMessage = 1072810; // *yawn* ... cold-soon-time ... *growl* + InProgressMessage = 1072811; // *sniff* *sniff* ... not-much-fish ... hungry ... *grumble* + CompletionMessage = 1074174; // *sniff* fish! much-fish! + + Objectives.Add(new CollectObjective(20, typeof(RawFishSteak), 1022426)); // raw fish steak + + Rewards.Add(new DummyReward(1072803)); // The boon of Maul. + } + + public override bool RecordCompletion => true; + + public override void GetRewards(MLQuestInstance instance) + { + instance.Player.SendLocalizedMessage( + 1074940, + "", + 0x2A + ); // You have gained the boon of Maul! Your understanding of the seasons grows. You are one step closer to claiming your elven heritage. + instance.ClaimRewards(); // skip gump + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Darius"), new Point3D(4310, 954, 10), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Darius"), new Point3D(4310, 954, 10), Map.Trammel); + + PutSpawner(new Spawner(1, 5, 10, 0, 5, "MaulTheBear"), new Point3D(1730, 257, 16), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "MaulTheBear"), new Point3D(1730, 257, 16), Map.Trammel); + } + } + + public class CaretakerOfTheLand : MLQuest + { + public CaretakerOfTheLand() + { + Activated = true; + Title = 1072783; // Caretaker of the Land + Description = + 1072812; // Hrrrrr. Hurrrr. Huuuman. *creaking branches* Suuun on baaark, roooooots diiig deeeeeep, wiiind caaaresses leeeaves … Hrrrrr. Saaap of Sooosaria feeeeeeds us. Hrrrrr. Huuuman leeearn. Caaaretaker of plaaants … teeend … prooove.
+ RefusalMessage = 1072813; // Hrrrrr. Hrrrrr. Huuuman. + InProgressMessage = + 1072814; // Hrrrr. Hrrrr. Roooooots neeeeeed saaap of Sooosaria. Hrrrrr. Roooooots tiiingle neeeaaar Yeeew. Seeeaaarch. Hrrrr! + CompletionMessage = 1074175; // Thiiirsty. Hurrr. Hurrr. + + Objectives.Add(new CollectObjective(1, typeof(SapOfSosaria), "sap of sosaria")); + + Rewards.Add(new DummyReward(1072804)); // The boon of Strongroot. + } + + public override bool RecordCompletion => true; + + public override void GetRewards(MLQuestInstance instance) + { + instance.Player.SendLocalizedMessage( + 1074941, + "", + 0x2A + ); // You have gained the boon of Strongroot! You have been approved by one whose roots touch the bones of Sosaria. You are one step closer to claiming your elven heritage. + instance.ClaimRewards(); // skip gump + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Strongroot"), new Point3D(597, 1744, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Strongroot"), new Point3D(597, 1744, 0), Map.Trammel); + + PutSpawner( + new Spawner(1, TimeSpan.FromSeconds(30), TimeSpan.FromMinutes(2), 0, 12, "SapOfSosaria"), + new Point3D(757, 1004, 0), + Map.Felucca + ); + PutSpawner( + new Spawner(1, TimeSpan.FromSeconds(30), TimeSpan.FromMinutes(2), 0, 12, "SapOfSosaria"), + new Point3D(757, 1004, 0), + Map.Trammel + ); + } + } + + public class WisdomOfTheSphynx : MLQuest + { + public WisdomOfTheSphynx() + { + Activated = true; + Title = 1072784; // Wisdom of the Sphynx + Description = + 1072822; // I greet thee human and divine my boon thou seek. Convey hence the object of my riddle and I shall reward thee with thy desire.

Three lives have I.
Gentle enough to soothe the skin,
Light enough to caress the sky,
Hard enough to crack rocks
What am I? + RefusalMessage = 1072823; // As thou wish, human. + InProgressMessage = + 1072824; // I give thee a hint then human. The answer to my riddle must be held carefully or it cannot be contained at all. Bring this elusive item to me in a suitable container. + CompletionMessage = 1074176; // Ah, thus it ends. + + Objectives.Add(new InternalObjective()); + + Rewards.Add(new DummyReward(1072805)); // The boon of Enigma. + } + + public override bool RecordCompletion => true; + + public override void GetRewards(MLQuestInstance instance) + { + instance.Player.SendLocalizedMessage( + 1074945, + "", + 0x2A + ); // You have gained the boon of Enigma! You are wise enough to know how little you know. You are one step closer to claiming your elven heritage. + instance.ClaimRewards(); // skip gump + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Enigma"), new Point3D(1828, 961, 7), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Enigma"), new Point3D(1828, 961, 7), Map.Trammel); + } + + private class InternalObjective : CollectObjective + { + public InternalObjective() + : base(1, typeof(Pitcher), 1074869) // The answer to the riddle. + { + } + + public override bool ShowDetailed => false; + + public override bool CheckItem(Item item) => + item is Pitcher pitcher && pitcher.Content == BeverageType.Water && pitcher.Quantity > 0; + } + } + + public class DefendingTheHerd : MLQuest + { + public DefendingTheHerd() + { + Activated = true; + Title = 1072785; // Defending the Herd + Description = + 1072825; // *snort* ... guard-mates ... guard-herd *hoof stomp* ... defend-with-hoof-and-horn ... thirsty-drink. *proud head-toss* + RefusalMessage = 1072826; // *snort* + InProgressMessage = 1072827; // *impatient hoof stomp* ... thirsty herd ... water scent. + CompletionNotice = CompletionNoticeShort; + + Objectives.Add( + new EscortObjective(new QuestArea(1074779, "Bravehorn's drinking pool")) + ); // Bravehorn's drinking pool + + Rewards.Add(new DummyReward(1072806)); // The boon of Bravehorn. + } + + public override bool RecordCompletion => true; + + public override void GetRewards(MLQuestInstance instance) + { + instance.Player.SendLocalizedMessage( + 1074942, + "", + 0x2A + ); // You have gained the boon of Bravehorn! You have glimpsed the nobility of those that sacrifice themselves for their people. You are one step closer to claiming your elven heritage. + instance.ClaimRewards(); // skip gump + } + + public override void Generate() + { + base.Generate(); + + PutSpawner( + new Spawner(1, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(90), 0, 5, "Bravehorn"), + new Point3D(1193, 2467, 0), + Map.Felucca + ); + PutSpawner( + new Spawner(1, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(90), 0, 5, "Bravehorn"), + new Point3D(1193, 2467, 0), + Map.Trammel + ); + + PutSpawner( + new Spawner(5, TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(30), 0, 8, "BravehornsMate"), + new Point3D(1192, 2467, 0), + Map.Felucca + ); + PutSpawner( + new Spawner(5, TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(30), 0, 8, "BravehornsMate"), + new Point3D(1192, 2467, 0), + Map.Trammel + ); + } + } + + public class TheBalanceOfNature : MLQuest + { + public TheBalanceOfNature() + { + Activated = true; + Title = 1072786; // The Balance of Nature + Description = + 1072829; // Ho, there human. Why do you seek out the Huntsman? The hunter serves the land by culling both predators and prey. The hunter maintains the essential balance of life and does not kill for sport or glory. If you seek my favor, human, then demonstrate you are capable of the duty. Cull the wolves nearby. + RefusalMessage = 1072830; // Then begone. I have no time to waste on you, human. + InProgressMessage = 1072831; // The timber wolves are easily tracked, human. + + Objectives.Add( + new KillObjective( + 15, + new[] { typeof(TimberWolf) }, + "timber wolves", + new QuestArea(1074833, "Huntsman's Forest") + ) + ); // Huntsman's Forest + + Rewards.Add(new DummyReward(1072807)); // The boon of the Huntsman. + } + + public override bool RecordCompletion => true; + + public override void GetRewards(MLQuestInstance instance) + { + instance.Player.SendLocalizedMessage( + 1074943, + "", + 0x2A + ); // You have gained the boon of the Huntsman! You have been given a taste of the bittersweet duty of those who guard the balance. You are one step closer to claiming your elven heritage. + instance.ClaimRewards(); // skip gump + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Huntsman"), new Point3D(1676, 593, 16), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Huntsman"), new Point3D(1676, 593, 16), Map.Trammel); + + PutSpawner( + new Spawner(5, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(15), 0, 10, "TimberWolf"), + new Point3D(1671, 592, 16), + Map.Felucca + ); + PutSpawner( + new Spawner(5, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(15), 0, 10, "TimberWolf"), + new Point3D(1671, 592, 16), + Map.Trammel + ); + } + } + + public class TheJoysOfLife : MLQuest + { + public TheJoysOfLife() + { + Activated = true; + Title = 1072787; // The Joys of Life + Description = + 1072832; // *giggle* So serious, so grim! *tickle* Enjoy life! Have fun! Laugh! Be merry! *giggle* Find three of my baubles ... *giggle* I hid them! *giggles hysterically* Hid them! La la la! Bring them quickly! They are magical and will hide themselves again if you are too slow. + RefusalMessage = 1072833; // *giggle* Too serious. Too thinky! + InProgressMessage = 1072834; // Magical baubles hidden, find them as you're bidden! *giggle* + CompletionMessage = 1074177; // *giggle* So pretty! + + Objectives.Add(new CollectObjective(3, typeof(ABauble), "arielle's baubles")); + + Rewards.Add(new DummyReward(1072809)); // The boon of Arielle. + } + + public override bool RecordCompletion => true; + + public override void GetRewards(MLQuestInstance instance) + { + instance.Player.SendLocalizedMessage( + 1074944, + "", + 0x2A + ); // You have gained the boon of Arielle! You have been taught the importance of laughter and light spirits. You are one step closer to claiming your elven heritage. + instance.ClaimRewards(); // skip gump + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Arielle"), new Point3D(1560, 1182, -27), Map.Ilshenar); + PutSpawner( + new Spawner(1, 5, 10, 0, 5, "Arielle"), + new Point3D(3366, 292, 9), + Map.Felucca + ); // Felucca spawn for reds + + PutSpawner( + new Spawner(6, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(30), 0, 20, "ABauble"), + new Point3D(1585, 1212, -13), + Map.Ilshenar + ); + } + } + + [QuesterName("Maul")] + public class MaulTheBear : GrizzlyBear + { + [Constructible] + public MaulTheBear() + { + AI = AIType.AI_Vendor; + FightMode = FightMode.None; + Tamable = false; + } + + public MaulTheBear(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Maul"; + + 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 class Strongroot : Treefellow + { + [Constructible] + public Strongroot() + { + AI = AIType.AI_Vendor; + FightMode = FightMode.None; + } + + public Strongroot(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Strongroot"; + + 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 class Enigma : BaseCreature + { + [Constructible] + public Enigma() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + BodyValue = 788; + BaseSoundID = 0x3EE; + + InitStats(100, 100, 25); + } + + public Enigma(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Enigma"; + + 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 class Bravehorn : BaseEscortable + { + [Constructible] + public Bravehorn() + { + } + + public Bravehorn(Serial serial) + : base(serial) + { + } + + public override bool StaticMLQuester => true; + public override bool InitialInnocent => true; + public override string DefaultName => "Bravehorn"; + + public override void InitBody() + { + Body = 0xEA; + + SetStr(41, 71); + SetDex(47, 77); + SetInt(27, 57); + + SetHits(27, 41); + SetMana(0); + + SetDamage(5, 9); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 20, 25); + SetResistance(ResistanceType.Cold, 5, 10); + + SetSkill(SkillName.MagicResist, 26.8, 44.5); + SetSkill(SkillName.Tactics, 29.8, 47.5); + SetSkill(SkillName.Wrestling, 29.8, 47.5); + + Fame = 300; + Karma = 0; + + VirtualArmor = 24; + } + + public override void InitOutfit() + { + } + + public override int GetAttackSound() => 0x82; + + public override int GetHurtSound() => 0x83; + + public override int GetDeathSound() => 0x84; + + 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 class BravehornsMate : Hind + { + [Constructible] + public BravehornsMate() => Tamable = false; + + public BravehornsMate(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "bravehorn's mate"; + + 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 class Huntsman : Centaur + { + [Constructible] + public Huntsman() + { + AI = AIType.AI_Vendor; + FightMode = FightMode.None; + } + + public Huntsman(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Huntsman"; + + 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 class Arielle : Pixie + { + [Constructible] + public Arielle() + { + AI = AIType.AI_Vendor; + FightMode = FightMode.None; + } + + public Arielle(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Arielle"; + + 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 class Ingenuity : MLQuest + { + public Ingenuity() + { + Activated = true; + Title = 1074350; // Ingenuity + Description = + 1074462; // The best thing about my job is that I do a little bit of everything, every day. It's what we're good at really. Just picking up something and making it do something else. Listen, I'm really low on parts. Are you interested in fetching me some supplies? + RefusalMessage = 1074508; // Okay. Best of luck with your other endeavors. + InProgressMessage = + 1074509; // Lord overseers are the best source I know for power crystals of the type I need. Iron golems too, can have them but they're harder to find. + CompletionMessage = + 1074510; // Do you have those power crystals? I'm ready to put the finishing touches on my latest experiment. + CompletionNotice = CompletionNoticeShortReturn; + + Objectives.Add(new CollectObjective(10, typeof(PowerCrystal), "Power Crystals")); + + Rewards.Add(new DummyReward(1074875)); // Another step closer to becoming human. + } + + public override bool RecordCompletion => true; + + public override void GetRewards(MLQuestInstance instance) + { + instance.Player.SendLocalizedMessage( + 1074946, + "", + 0x2A + ); // You have demonstrated your ingenuity! Humans are jacks of all trades and know a little about a lot of things. You are one step closer to achieving humanity. + instance.ClaimRewards(); // skip gump + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Nedrick"), new Point3D(2958, 3466, 15), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Nedrick"), new Point3D(2958, 3466, 15), Map.Trammel); + + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Sledge"), new Point3D(2673, 2129, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Sledge"), new Point3D(2673, 2129, 0), Map.Trammel); + } + } + + public class HeaveHo : MLQuest + { + public HeaveHo() + { + Activated = true; + Title = 1074351; // Heave Ho! + Description = + 1074519; // Ho there! There's nothing quite like a day's honest labor to make you appreciate being alive. Hey, maybe you'd like to help out with this project? These crates need to be delivered to Sledge. The only thing is -- it's a bit of a rush job and if you don't make it in time, he won't take them. Can I trust you to help out? + RefusalMessage = 1074521; // Oh yah, if you're too busy, no problem. + InProgressMessage = + 1074522; // Sledge can be found in Buc's Den. Better hurry, he won't take those crates if you take too long with them. + CompletionMessage = 1074523; // Hey, if you have cargo for me, you can start unloading over here. + CompletionNotice = CompletionNoticeShort; + + Objectives.Add( + new TimedDeliverObjective( + TimeSpan.FromHours(1), + typeof(CrateForSledge), + 5, + "Crates for Sledge", + typeof(Sledge) + ) + ); + + Rewards.Add(new DummyReward(1074875)); // Another step closer to becoming human. + } + + public override bool RecordCompletion => true; + + public override void GetRewards(MLQuestInstance instance) + { + instance.Player.SendLocalizedMessage( + 1074948, + "", + 0x2A + ); // You have demonstrated your physical strength! Humans can carry vast loads without complaint. You are one step closer to achieving humanity. + instance.ClaimRewards(); // skip gump + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Patricus"), new Point3D(3007, 823, -2), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Patricus"), new Point3D(3007, 823, -2), Map.Trammel); + } + } + + // This is not a real quest, it is only used as a reference + public class HumanInNeed : MLQuest + { + public HumanInNeed() + { + Title = 1075011; // A quest that asks you to defend a human in need. + Description = 0; + RefusalMessage = 0; + InProgressMessage = 0; + } + + public override bool RecordCompletion => true; + + public static void AwardTo(PlayerMobile pm) + { + MLQuestSystem.GetOrCreateContext(pm).SetDoneQuest(MLQuestSystem.FindQuest(typeof(HumanInNeed))); + pm.SendLocalizedMessage( + 1074949, + "", + 0x2A + ); // You have demonstrated your compassion! Your kind actions have been noted. + } + } + + public class AllSeasonAdventurer : MLQuest + { + public AllSeasonAdventurer() + { + Activated = true; + Title = 1074353; // All Season Adventurer + Description = + 1074527; // It's all about hardship, suffering, struggle and pain. Without challenges, you've got nothing to test yourself against -- and that's what life is all about. Self improvement! Honing your body and mind! Overcoming obstacles ... You'll see what I mean if you take on my challenge. + RefusalMessage = 1074528; // My way of life isn't for everyone, that's true enough. + InProgressMessage = 1074529; // You're not making much progress in the honing-mind-and-body department, are you? + CompletionNotice = CompletionNoticeShortReturn; + + Objectives.Add( + new KillObjective( + 5, + new[] { typeof(Efreet) }, + "efreets", + new QuestArea(1074808, "Fire") + ) + ); // Fire + Objectives.Add( + new KillObjective( + 5, + new[] { typeof(IceFiend) }, + "ice fiends", + new QuestArea(1074809, "Ice") + ) + ); // Ice + + Rewards.Add(new DummyReward(1074875)); // Another step closer to becoming human. + } + + public override bool RecordCompletion => true; + + public override void GetRewards(MLQuestInstance instance) + { + instance.Player.SendLocalizedMessage( + 1074947, + "", + 0x2A + ); // You have demonstrated your toughness! Humans are able to endure unimaginable hardships in pursuit of their goals. You are one step closer to achieving humanity. + instance.ClaimRewards(); // skip gump + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Belulah"), new Point3D(3782, 1266, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Belulah"), new Point3D(3782, 1266, 0), Map.Trammel); + } + } + + [QuesterName("Sledge (Buc's Den)")] + public class Sledge : BaseCreature + { + [Constructible] + public Sledge() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Versatile"; + Body = 400; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + AddItem(new Tunic(Utility.RandomNeutralHue())); + AddItem(new LongPants(Utility.RandomBlueHue())); + AddItem(new Cloak(Utility.RandomBrightHue())); + AddItem(new ElvenBoots(Utility.RandomNeutralHue())); + AddItem(new Backpack()); + } + + public Sledge(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Sledge"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074188, // Weakling! You are not up to the task I have. + 1074195 + ) + ); // You there, in the stupid hat! Come here. + } + + 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(); + } + } + + [QuesterName("Patricus (Vesper)")] + public class Patricus : BaseCreature + { + [Constructible] + public Patricus() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Trader"; + Body = 400; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + AddItem(new FancyShirt(Utility.RandomNeutralHue())); + AddItem(new LongPants(Utility.RandomBrightHue())); + AddItem(new Cloak(0x1BB)); + AddItem(new Shoes(Utility.RandomNeutralHue())); + AddItem(new Backpack()); + } + + public Patricus(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Patricus"; + + 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(); + } + } + + [QuesterName("Belulah (Nujel'm)")] // On OSI it's "Belulah (Nu'Jelm)" (incorrect spelling) + public class Belulah : BaseCreature + { + [Constructible] + public Belulah() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the scorned"; + Female = true; + Body = 401; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new FancyShirt(Utility.RandomBlueHue())); + AddItem(new LongPants(Utility.RandomNondyedHue())); + AddItem(new Boots()); + } + + public Belulah(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Belulah"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + /* + * 1074205 - Oh great adventurer, would you please assist a weak soul in need of aid? + * 1074206 - Excuse me please traveler, might I have a little of your time? + */ + MLQuestSystem.Tell(this, pm, Utility.Random(1074205, 2)); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Definitions/HonestBeggar.cs b/Projects/UOContent/Engines/MLQuests/Definitions/HonestBeggar.cs index 2bd255639..5fdba233c 100644 --- a/Projects/UOContent/Engines/MLQuests/Definitions/HonestBeggar.cs +++ b/Projects/UOContent/Engines/MLQuests/Definitions/HonestBeggar.cs @@ -1,157 +1,157 @@ -using System; -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; -using Server.Engines.Spawners; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Definitions -{ - public class HonestBeggar : MLQuest - { - public HonestBeggar() - { - Activated = true; - Title = 1075392; // Honest Beggar - Description = - 1075393; // Beg pardon, sir. I mean, madam. Uh, can I ask a favor of you? I found this jeweled ring. Most people would sell it and keep the money, but not me. I ain't never stole nothing, and I ain't about to start. I tried to take it over to Brit castle, figgerin' it must belong to some highborn lady, but the guards threw me out. You look like they might let you pass. Will you take the ring over there and see if you can find the owner? - RefusalMessage = 1075395; // I see. Too good to help an honest beggar like me, eh? - InProgressMessage = - 1075396; // A jewel like this must be worth a lot, so it must belong to some noble or another. I would show it around the castle. Someone�s bound to recognize it. - CompletionMessage = - 1075397; // Didst thou find my ring? I thank thee very much! It is an old ring, and a gift from my husband. I was most distraught when I realized it was missing. - CompletionNotice = CompletionNoticeShort; - - Objectives.Add(new DeliverObjective(typeof(ReginasRing), 1, "Regina's Ring", typeof(Regina))); - - Rewards.Add(new DummyReward(1075394)); // Find the ring�s owner. - } - - public override Type NextQuest => typeof(ReginasThanks); - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Evan"), new Point3D(1486, 1706, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Evan"), new Point3D(1486, 1706, 0), Map.Felucca); - } - } - - public class ReginasThanks : MLQuest - { - public ReginasThanks() - { - Activated = true; - OneTimeOnly = true; - Title = 1075398; // Regina�s Thanks - Description = - 1075399; // What�s that you say? It was a humble beggar that found my ring? Such honesty must be rewarded. Here, take this packet and return it to him, and I will be in your debt. - RefusalMessage = 1075401; // Hmph. Very well. What did you say his name was? - InProgressMessage = 1075402; // Take the packet and return it to the beggar who found my ring. - CompletionMessage = - 1075403; // What? For me? Let me see . . . these sapphire earrings are for you, it says. Oh, she wants to offer me a job! This is the most wonderful thing that ever happened to me! - CompletionNotice = CompletionNoticeShort; - - Objectives.Add(new DeliverObjective(typeof(ReginasLetter), 1, "Regina's Letter", typeof(Evan))); - - Rewards.Add(new ItemReward(1075400, typeof(TransparentHeart))); // Transparent Heart - } - - public override bool IsChainTriggered => true; - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Regina"), new Point3D(1362, 1622, 50), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 3, "Regina"), new Point3D(1422, 1621, 20), Map.Felucca); - } - } - - public class Evan : BaseCreature - { - [Constructible] - public Evan() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Beggar"; - Race = Race.Human; - BodyValue = 0x190; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Backpack()); - AddItem(new Doublet()); - AddItem(new ShortPants(0x755)); - } - - public Evan(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Evan"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Regina : BaseCreature - { - [Constructible] - public Regina() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Noble"; - Race = Race.Human; - BodyValue = 0x191; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Backpack()); - AddItem(new GildedDress()); - AddItem(new Boots()); - } - - public Regina(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Regina"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; +using Server.Engines.Spawners; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Definitions +{ + public class HonestBeggar : MLQuest + { + public HonestBeggar() + { + Activated = true; + Title = 1075392; // Honest Beggar + Description = + 1075393; // Beg pardon, sir. I mean, madam. Uh, can I ask a favor of you? I found this jeweled ring. Most people would sell it and keep the money, but not me. I ain't never stole nothing, and I ain't about to start. I tried to take it over to Brit castle, figgerin' it must belong to some highborn lady, but the guards threw me out. You look like they might let you pass. Will you take the ring over there and see if you can find the owner? + RefusalMessage = 1075395; // I see. Too good to help an honest beggar like me, eh? + InProgressMessage = + 1075396; // A jewel like this must be worth a lot, so it must belong to some noble or another. I would show it around the castle. Someone�s bound to recognize it. + CompletionMessage = + 1075397; // Didst thou find my ring? I thank thee very much! It is an old ring, and a gift from my husband. I was most distraught when I realized it was missing. + CompletionNotice = CompletionNoticeShort; + + Objectives.Add(new DeliverObjective(typeof(ReginasRing), 1, "Regina's Ring", typeof(Regina))); + + Rewards.Add(new DummyReward(1075394)); // Find the ring�s owner. + } + + public override Type NextQuest => typeof(ReginasThanks); + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Evan"), new Point3D(1486, 1706, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Evan"), new Point3D(1486, 1706, 0), Map.Felucca); + } + } + + public class ReginasThanks : MLQuest + { + public ReginasThanks() + { + Activated = true; + OneTimeOnly = true; + Title = 1075398; // Regina�s Thanks + Description = + 1075399; // What�s that you say? It was a humble beggar that found my ring? Such honesty must be rewarded. Here, take this packet and return it to him, and I will be in your debt. + RefusalMessage = 1075401; // Hmph. Very well. What did you say his name was? + InProgressMessage = 1075402; // Take the packet and return it to the beggar who found my ring. + CompletionMessage = + 1075403; // What? For me? Let me see . . . these sapphire earrings are for you, it says. Oh, she wants to offer me a job! This is the most wonderful thing that ever happened to me! + CompletionNotice = CompletionNoticeShort; + + Objectives.Add(new DeliverObjective(typeof(ReginasLetter), 1, "Regina's Letter", typeof(Evan))); + + Rewards.Add(new ItemReward(1075400, typeof(TransparentHeart))); // Transparent Heart + } + + public override bool IsChainTriggered => true; + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Regina"), new Point3D(1362, 1622, 50), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 3, "Regina"), new Point3D(1422, 1621, 20), Map.Felucca); + } + } + + public class Evan : BaseCreature + { + [Constructible] + public Evan() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Beggar"; + Race = Race.Human; + BodyValue = 0x190; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Backpack()); + AddItem(new Doublet()); + AddItem(new ShortPants(0x755)); + } + + public Evan(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Evan"; + + 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 class Regina : BaseCreature + { + [Constructible] + public Regina() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Noble"; + Race = Race.Human; + BodyValue = 0x191; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Backpack()); + AddItem(new GildedDress()); + AddItem(new Boots()); + } + + public Regina(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Regina"; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Definitions/Ilshenar.cs b/Projects/UOContent/Engines/MLQuests/Definitions/Ilshenar.cs index 5d5d41917..e28fda230 100644 --- a/Projects/UOContent/Engines/MLQuests/Definitions/Ilshenar.cs +++ b/Projects/UOContent/Engines/MLQuests/Definitions/Ilshenar.cs @@ -1,347 +1,358 @@ -using System; -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; -using Server.Engines.Spawners; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Definitions -{ - public class Responsibility : BaseEscort - { - public Responsibility() - { - Activated = true; - Title = 1074352; // Responsibility - Description = - 1074524; // Oh! I just don't know what to do. My mother is away and my father told me not to talk to strangers ... *worried frown* But my grandfather has sent word that he has been hurt and needs me to tend his wounds. He has a small farm southeast of here. Would you ... could you ... escort me there safely? - RefusalMessage = 1074525; // I hope my grandfather will be alright. - InProgressMessage = - 1074526; // Grandfather's farm is a ways west of the Shrine of Spirituality. So, we're not quite there yet. Thank you again for keeping me safe. - - Objectives.Add(new EscortObjective(new QuestArea(1074781, "Sheep Farm"))); // Sheep Farm - - Rewards.Add(ItemReward.BagOfTrinkets); - } - - // OSI sends this instead, but it doesn't make sense for an escortable - // public override void OnComplete( MLQuestInstance instance ) - // { - // instance.Player.SendLocalizedMessage( 1073775, "", 0x23 ); // Your quest is complete. Return for your reward. - // } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(30), 0, 5, "Lissbet"), - new Point3D(1568, 1040, -7), Map.Ilshenar); - PutSpawner(new Spawner(1, 5, 10, 0, 8, "GrandpaCharley"), new Point3D(1322, 1331, -14), Map.Ilshenar); - PutSpawner(new Spawner(1, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(30), 0, 3, "Sheep"), - new Point3D(1308, 1324, -14), Map.Ilshenar); - } - } - - public class SomethingToWailAbout : MLQuest - { - public SomethingToWailAbout() - { - Activated = true; - Title = 1073071; // Something to Wail About - Description = - 1073561; // Can you hear them? The never-ending howling? The incessant wailing? These banshees, they never cease! Never! They haunt my nights. Please, I beg you -- will you silence them? I would be ever so grateful. - RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. - InProgressMessage = 1073581; // Until you kill 12 Wailing Banshees, there will be no peace. - - Objectives.Add(new KillObjective(12, new[] { typeof(WailingBanshee) }, "wailing banshees")); - - Rewards.Add(ItemReward.BagOfTreasure); - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Jelrice"), new Point3D(1176, 1196, -25), Map.Ilshenar); - } - } - - public class Runaways : MLQuest - { - public Runaways() - { - Activated = true; - Title = 1072993; // Runaways! - Description = - 1073026; // You've got to help me out! Those wild ostards have been causing absolute havok around here. Kill them off before they destroy my land. There are around twelve of them. - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(12, new[] { typeof(FrenziedOstard) }, "frenzied ostards")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class ViciousPredator : MLQuest - { - public ViciousPredator() - { - Activated = true; - Title = 1072994; // Vicious Predator - Description = - 1073028; // You've got to help me out! Those dire wolves have been causing absolute havok around here. Kill them off before they destroy my land. They run around in a pack of around ten. - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(10, new[] { typeof(DireWolf) }, "dire wolves")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class GuileIrkAndSpite : MLQuest - { - public GuileIrkAndSpite() - { - Activated = true; - Title = 1074739; // Guile, Irk and Spite - Description = - 1074740; // You know them, don't you. The three? They look like you, you'll see. They looked like me, I remember, they looked like, well, you'll see. The three. They'll drive you mad too, if you let them. They are trouble, and they need to be slain. Seek them out. - RefusalMessage = - 1074745; // You just don't understand the gravity of the situation. If you did, you'd agree to my task. - InProgressMessage = - 1074746; // Perhaps I was unclear. You'll know them when you see them, because you'll see you, and you, and you. Hurry now. - CompletionMessage = - 1074747; // Are you one of THEM? Ahhhh! Oh, wait, if you were them, then you'd be me. So you're -- you. Good job! - - Objectives.Add(new KillObjective(1, new[] { typeof(Guile) }, "Guile")); - Objectives.Add(new KillObjective(1, new[] { typeof(Irk) }, "Irk")); - Objectives.Add(new KillObjective(1, new[] { typeof(Spite) }, "Spite")); - - Rewards.Add(ItemReward.Strongbox); - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 5, "Yorus"), new Point3D(1389, 423, -24), Map.Ilshenar); - } - } - - public class Lissbet : BaseEscortable - { - [Constructible] - public Lissbet() - { - } - - public Lissbet(Serial serial) - : base(serial) - { - } - - public override bool StaticMLQuester => true; - public override bool InitialInnocent => true; - public override string DefaultName => "Lissbet"; - - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074204, // Greetings seeker.  I have an urgent matter for you, if you are willing. - 1074222)); // Could I trouble you for some assistance? - } - - public override void InitBody() - { - SetStr(40, 50); - SetDex(70, 80); - SetInt(80, 90); - - Hue = Race.Human.RandomSkinHue(); - Female = true; - Body = 401; - - Title = "the flower girl"; - - HairItemID = 0x203D; - HairHue = 0x1BB; - } - - public override void InitOutfit() - { - AddItem(new Kilt(Utility.RandomYellowHue())); - AddItem(new FancyShirt(Utility.RandomYellowHue())); - AddItem(new Sandals()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GrandpaCharley : BaseCreature - { - [Constructible] - public GrandpaCharley() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the farmer"; - Body = 400; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - int hairHue = 0x3B2 + Utility.Random(2); - Utility.AssignRandomHair(this, hairHue); - - FacialHairItemID = 0x203E; // Long Beard - FacialHairHue = hairHue; - - SetSkill(SkillName.ItemID, 80, 90); - - AddItem(new WideBrimHat(Utility.RandomNondyedHue())); - AddItem(new FancyShirt(Utility.RandomNondyedHue())); - AddItem(new LongPants(Utility.RandomNondyedHue())); - AddItem(new Sandals(Utility.RandomNeutralHue())); - AddItem(new ShepherdsCrook()); - AddItem(new Backpack()); - } - - public GrandpaCharley(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Grandpa Charley"; - public override bool CanTeach => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Jelrice (Ilshenar)")] - public class Jelrice : BaseCreature - { - [Constructible] - public Jelrice() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the trader"; - Race = Race.Human; - BodyValue = 0x191; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Shoes(Utility.RandomNeutralHue())); - AddItem(new Skirt(Utility.RandomBlueHue())); - AddItem(new FancyShirt(Utility.RandomRedHue())); - } - - public Jelrice(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Jelrice"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1074221); // Greetings!  I have a small task for you good traveler. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Yorus (Ilshenar)")] - public class Yorus : BaseCreature - { - [Constructible] - public Yorus() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the tinker"; - Race = Race.Human; - BodyValue = 0x190; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Shoes(Utility.RandomNeutralHue())); - AddItem(new LongPants(Utility.RandomBlueHue())); - AddItem(new FancyShirt(Utility.RandomOrangeHue())); - AddItem(new Cloak(Utility.RandomBrightHue())); - } - - public Yorus(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Yorus"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1074218); // Hey!  I want to talk to you, now. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; +using Server.Engines.Spawners; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Definitions +{ + public class Responsibility : BaseEscort + { + public Responsibility() + { + Activated = true; + Title = 1074352; // Responsibility + Description = + 1074524; // Oh! I just don't know what to do. My mother is away and my father told me not to talk to strangers ... *worried frown* But my grandfather has sent word that he has been hurt and needs me to tend his wounds. He has a small farm southeast of here. Would you ... could you ... escort me there safely? + RefusalMessage = 1074525; // I hope my grandfather will be alright. + InProgressMessage = + 1074526; // Grandfather's farm is a ways west of the Shrine of Spirituality. So, we're not quite there yet. Thank you again for keeping me safe. + + Objectives.Add(new EscortObjective(new QuestArea(1074781, "Sheep Farm"))); // Sheep Farm + + Rewards.Add(ItemReward.BagOfTrinkets); + } + + // OSI sends this instead, but it doesn't make sense for an escortable + // public override void OnComplete( MLQuestInstance instance ) + // { + // instance.Player.SendLocalizedMessage( 1073775, "", 0x23 ); // Your quest is complete. Return for your reward. + // } + + public override void Generate() + { + base.Generate(); + + PutSpawner( + new Spawner(1, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(30), 0, 5, "Lissbet"), + new Point3D(1568, 1040, -7), + Map.Ilshenar + ); + PutSpawner(new Spawner(1, 5, 10, 0, 8, "GrandpaCharley"), new Point3D(1322, 1331, -14), Map.Ilshenar); + PutSpawner( + new Spawner(1, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(30), 0, 3, "Sheep"), + new Point3D(1308, 1324, -14), + Map.Ilshenar + ); + } + } + + public class SomethingToWailAbout : MLQuest + { + public SomethingToWailAbout() + { + Activated = true; + Title = 1073071; // Something to Wail About + Description = + 1073561; // Can you hear them? The never-ending howling? The incessant wailing? These banshees, they never cease! Never! They haunt my nights. Please, I beg you -- will you silence them? I would be ever so grateful. + RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. + InProgressMessage = 1073581; // Until you kill 12 Wailing Banshees, there will be no peace. + + Objectives.Add(new KillObjective(12, new[] { typeof(WailingBanshee) }, "wailing banshees")); + + Rewards.Add(ItemReward.BagOfTreasure); + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Jelrice"), new Point3D(1176, 1196, -25), Map.Ilshenar); + } + } + + public class Runaways : MLQuest + { + public Runaways() + { + Activated = true; + Title = 1072993; // Runaways! + Description = + 1073026; // You've got to help me out! Those wild ostards have been causing absolute havok around here. Kill them off before they destroy my land. There are around twelve of them. + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(12, new[] { typeof(FrenziedOstard) }, "frenzied ostards")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class ViciousPredator : MLQuest + { + public ViciousPredator() + { + Activated = true; + Title = 1072994; // Vicious Predator + Description = + 1073028; // You've got to help me out! Those dire wolves have been causing absolute havok around here. Kill them off before they destroy my land. They run around in a pack of around ten. + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(10, new[] { typeof(DireWolf) }, "dire wolves")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class GuileIrkAndSpite : MLQuest + { + public GuileIrkAndSpite() + { + Activated = true; + Title = 1074739; // Guile, Irk and Spite + Description = + 1074740; // You know them, don't you. The three? They look like you, you'll see. They looked like me, I remember, they looked like, well, you'll see. The three. They'll drive you mad too, if you let them. They are trouble, and they need to be slain. Seek them out. + RefusalMessage = + 1074745; // You just don't understand the gravity of the situation. If you did, you'd agree to my task. + InProgressMessage = + 1074746; // Perhaps I was unclear. You'll know them when you see them, because you'll see you, and you, and you. Hurry now. + CompletionMessage = + 1074747; // Are you one of THEM? Ahhhh! Oh, wait, if you were them, then you'd be me. So you're -- you. Good job! + + Objectives.Add(new KillObjective(1, new[] { typeof(Guile) }, "Guile")); + Objectives.Add(new KillObjective(1, new[] { typeof(Irk) }, "Irk")); + Objectives.Add(new KillObjective(1, new[] { typeof(Spite) }, "Spite")); + + Rewards.Add(ItemReward.Strongbox); + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 5, "Yorus"), new Point3D(1389, 423, -24), Map.Ilshenar); + } + } + + public class Lissbet : BaseEscortable + { + [Constructible] + public Lissbet() + { + } + + public Lissbet(Serial serial) + : base(serial) + { + } + + public override bool StaticMLQuester => true; + public override bool InitialInnocent => true; + public override string DefaultName => "Lissbet"; + + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074204, // Greetings seeker.  I have an urgent matter for you, if you are willing. + 1074222 + ) + ); // Could I trouble you for some assistance? + } + + public override void InitBody() + { + SetStr(40, 50); + SetDex(70, 80); + SetInt(80, 90); + + Hue = Race.Human.RandomSkinHue(); + Female = true; + Body = 401; + + Title = "the flower girl"; + + HairItemID = 0x203D; + HairHue = 0x1BB; + } + + public override void InitOutfit() + { + AddItem(new Kilt(Utility.RandomYellowHue())); + AddItem(new FancyShirt(Utility.RandomYellowHue())); + AddItem(new Sandals()); + } + + 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 class GrandpaCharley : BaseCreature + { + [Constructible] + public GrandpaCharley() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the farmer"; + Body = 400; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + var hairHue = 0x3B2 + Utility.Random(2); + Utility.AssignRandomHair(this, hairHue); + + FacialHairItemID = 0x203E; // Long Beard + FacialHairHue = hairHue; + + SetSkill(SkillName.ItemID, 80, 90); + + AddItem(new WideBrimHat(Utility.RandomNondyedHue())); + AddItem(new FancyShirt(Utility.RandomNondyedHue())); + AddItem(new LongPants(Utility.RandomNondyedHue())); + AddItem(new Sandals(Utility.RandomNeutralHue())); + AddItem(new ShepherdsCrook()); + AddItem(new Backpack()); + } + + public GrandpaCharley(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Grandpa Charley"; + public override bool CanTeach => true; + + 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(); + } + } + + [QuesterName("Jelrice (Ilshenar)")] + public class Jelrice : BaseCreature + { + [Constructible] + public Jelrice() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the trader"; + Race = Race.Human; + BodyValue = 0x191; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Shoes(Utility.RandomNeutralHue())); + AddItem(new Skirt(Utility.RandomBlueHue())); + AddItem(new FancyShirt(Utility.RandomRedHue())); + } + + public Jelrice(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Jelrice"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1074221); // Greetings!  I have a small task for you good traveler. + } + + 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(); + } + } + + [QuesterName("Yorus (Ilshenar)")] + public class Yorus : BaseCreature + { + [Constructible] + public Yorus() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the tinker"; + Race = Race.Human; + BodyValue = 0x190; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Shoes(Utility.RandomNeutralHue())); + AddItem(new LongPants(Utility.RandomBlueHue())); + AddItem(new FancyShirt(Utility.RandomOrangeHue())); + AddItem(new Cloak(Utility.RandomBrightHue())); + } + + public Yorus(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Yorus"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1074218); // Hey!  I want to talk to you, now. + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Definitions/LostItems.cs b/Projects/UOContent/Engines/MLQuests/Definitions/LostItems.cs index 4014ae12b..cfcee86f3 100644 --- a/Projects/UOContent/Engines/MLQuests/Definitions/LostItems.cs +++ b/Projects/UOContent/Engines/MLQuests/Definitions/LostItems.cs @@ -1,61 +1,69 @@ -using System; -using Server.Engines.MLQuests.Items; -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; - -namespace Server.Engines.MLQuests.Definitions -{ - // TODO: Assassination Contract, Evidence, Lost in Transit, Last Words - - public class LostAndFound : MLQuest - { - public LostAndFound() - { - Activated = true; - Title = 1072370; // Lost and Found - Description = - 1072589; // The battered, old bucket is inscribed with barely legible writing that indicates it belongs to someone named "Dallid". Maybe they'd pay for its return? - RefusalMessage = - 1072590; // You're right, who cares if Dallid might pay for his battered old bucket back. This way you can carry it around with you! - InProgressMessage = 1072591; // Whoever this "Dallid" might be, he's probably looking for his bucket. - CompletionMessage = - 1074580; // Is that my bucket? I had to ditch my favorite bucket when a group of ratmen jumped me! - - Objectives.Add(new TimedDeliverObjective(TimeSpan.FromSeconds(600), typeof(BatteredBucket), 1, "battered bucket", - typeof(Dallid), false)); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class BatteredBucket : TransientQuestGiverItem - { - [Constructible] - public BatteredBucket() - : base(0x2004, TimeSpan.FromMinutes(10)) => - LootType = LootType.Blessed; - - public BatteredBucket(Serial serial) - : base(serial) - { - } - // Original label, doesn't fit the expiration message well - // public override int LabelNumber => 1073129; // A battered bucket. - - public override string DefaultName => "battered bucket"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; +using Server.Engines.MLQuests.Items; +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; + +namespace Server.Engines.MLQuests.Definitions +{ + // TODO: Assassination Contract, Evidence, Lost in Transit, Last Words + + public class LostAndFound : MLQuest + { + public LostAndFound() + { + Activated = true; + Title = 1072370; // Lost and Found + Description = + 1072589; // The battered, old bucket is inscribed with barely legible writing that indicates it belongs to someone named "Dallid". Maybe they'd pay for its return? + RefusalMessage = + 1072590; // You're right, who cares if Dallid might pay for his battered old bucket back. This way you can carry it around with you! + InProgressMessage = 1072591; // Whoever this "Dallid" might be, he's probably looking for his bucket. + CompletionMessage = + 1074580; // Is that my bucket? I had to ditch my favorite bucket when a group of ratmen jumped me! + + Objectives.Add( + new TimedDeliverObjective( + TimeSpan.FromSeconds(600), + typeof(BatteredBucket), + 1, + "battered bucket", + typeof(Dallid), + false + ) + ); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class BatteredBucket : TransientQuestGiverItem + { + [Constructible] + public BatteredBucket() + : base(0x2004, TimeSpan.FromMinutes(10)) => + LootType = LootType.Blessed; + + public BatteredBucket(Serial serial) + : base(serial) + { + } + // Original label, doesn't fit the expiration message well + // public override int LabelNumber => 1073129; // A battered bucket. + + public override string DefaultName => "battered bucket"; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Definitions/Malas.cs b/Projects/UOContent/Engines/MLQuests/Definitions/Malas.cs index 553fa276b..43b968308 100644 --- a/Projects/UOContent/Engines/MLQuests/Definitions/Malas.cs +++ b/Projects/UOContent/Engines/MLQuests/Definitions/Malas.cs @@ -1,86 +1,86 @@ -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; -using Server.Engines.Spawners; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Definitions -{ - public class PointyEars : MLQuest - { - public PointyEars() - { - Activated = true; - Title = 1074640; // Pointy Ears - Description = - 1074641; // I've heard ... there's some that will pay a good bounty for pointed ears, much like we used to pay for each wolf skin. I've got nothing personal against these elves. It's just business. You want in on this? I'm not fussy who I work with. - RefusalMessage = 1074642; // Suit yourself. - InProgressMessage = 1074643; // I can't pay a bounty if you don't bring bag the ears. - CompletionMessage = 1074644; // Here to collect on a bounty? - - Objectives.Add(new CollectObjective(20, typeof(SeveredElfEars), 1032590)); // severed elf ears - - Rewards.Add(ItemReward.BagOfTrinkets); - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Drithen"), new Point3D(1983, 1364, -80), Map.Malas); - } - } - - [QuesterName("Drithen (Umbra)")] - public class Drithen : BaseCreature - { - [Constructible] - public Drithen() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Fierce"; - Race = Race.Human; - BodyValue = 0x190; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - AddItem(new Backpack()); - AddItem(new ElvenBoots(Utility.RandomNeutralHue())); - AddItem(new LongPants(Utility.RandomBlueHue())); - AddItem(new Tunic(Utility.RandomNeutralHue())); - AddItem(new Cloak(Utility.RandomBrightHue())); - - SetSkill(SkillName.Focus, 60.0, 80.0); - } - - public Drithen(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Drithen"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1074188); // Weakling! You are not up to the task I have. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; +using Server.Engines.Spawners; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Definitions +{ + public class PointyEars : MLQuest + { + public PointyEars() + { + Activated = true; + Title = 1074640; // Pointy Ears + Description = + 1074641; // I've heard ... there's some that will pay a good bounty for pointed ears, much like we used to pay for each wolf skin. I've got nothing personal against these elves. It's just business. You want in on this? I'm not fussy who I work with. + RefusalMessage = 1074642; // Suit yourself. + InProgressMessage = 1074643; // I can't pay a bounty if you don't bring bag the ears. + CompletionMessage = 1074644; // Here to collect on a bounty? + + Objectives.Add(new CollectObjective(20, typeof(SeveredElfEars), 1032590)); // severed elf ears + + Rewards.Add(ItemReward.BagOfTrinkets); + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Drithen"), new Point3D(1983, 1364, -80), Map.Malas); + } + } + + [QuesterName("Drithen (Umbra)")] + public class Drithen : BaseCreature + { + [Constructible] + public Drithen() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Fierce"; + Race = Race.Human; + BodyValue = 0x190; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + AddItem(new Backpack()); + AddItem(new ElvenBoots(Utility.RandomNeutralHue())); + AddItem(new LongPants(Utility.RandomBlueHue())); + AddItem(new Tunic(Utility.RandomNeutralHue())); + AddItem(new Cloak(Utility.RandomBrightHue())); + + SetSkill(SkillName.Focus, 60.0, 80.0); + } + + public Drithen(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Drithen"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1074188); // Weakling! You are not up to the task I have. + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Definitions/MistakenIdentity.cs b/Projects/UOContent/Engines/MLQuests/Definitions/MistakenIdentity.cs index 1060c946d..4c49c25eb 100644 --- a/Projects/UOContent/Engines/MLQuests/Definitions/MistakenIdentity.cs +++ b/Projects/UOContent/Engines/MLQuests/Definitions/MistakenIdentity.cs @@ -1,348 +1,377 @@ -using System; -using Server.Engines.MLQuests.Items; -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; -using Server.Engines.Spawners; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Definitions -{ - public class MistakenIdentity : MLQuest - { - public MistakenIdentity() - { - Activated = true; - Title = 1074573; // Mistaken Identity - Description = - 1074574; // What do you want? Wonderful, another whining request for a refund on tuition. You know, experiences like that are invaluable ... and infrequent. Having the opportunity to test yourself under such realistic situations isn't something the college offers all students. Fine. Fine. You'll need to submit a refund request form in triplicate before I can return your 1,000,000 gold tuition. You'll need to get some signatures and a few other odds and ends. - RefusalMessage = 1074606; // If you're not willing to follow the proper process then go away. - InProgressMessage = 1074605; // You're not getting a refund without the proper forms and signatures. - CompletionMessage = 1074607; // Oh blast! Not another of those forms. I'm so sick of this endless paperwork. - CompletionNotice = CompletionNoticeShort; - - Objectives.Add(new DeliverObjective(typeof(TuitionReimbursementForm), 1, "Tuition Reimbursement Form", - typeof(Gorrow))); - - Rewards.Add(new DummyReward(1074634)); // Tuition Reimbursement - } - - public override Type NextQuest => typeof(YouScratchMyBack); - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Aernya"), new Point3D(2095, 1380, -90), Map.Malas); - } - } - - public class YouScratchMyBack : MLQuest - { - public YouScratchMyBack() - { - Activated = true; - Title = 1074608; // You Scratch My Back - Description = - 1074609; // Heh. Heheheh. Good one. You're not a Bedlam student and you're definitely not eligible for a tuition refund. Heheheh. That old witch Aernya doesn't see as well as she used to you know. Otherwise, she would have ... hmmm, wait a minute. I sense a certain 'opportunity' here. I'll sign your forms in return for a little help with a project of my own. What do you say? - RefusalMessage = 1074615; // Hehehe. Your choice. - InProgressMessage = - 1074616; // I'm something of a gourmet, you see. It's tough getting some of the ingredients, though. Bring me back some pixie legs, unicorn ribs and ki-rin brains and I'll sign your form. - CompletionMessage = - 1074617; // Oh excellent, you're back. I'll get the oven going. That thing about pixie legs, you see, is that they burn and dry out if you're not really careful. Taste just like chicken too! - CompletionNotice = CompletionNoticeShortReturn; - - Objectives.Add(new CollectObjective(1, typeof(UnicornRibs), "Unicorn Ribs")); - Objectives.Add(new CollectObjective(2, typeof(KirinBrains), "Ki-Rin Brains")); - Objectives.Add(new CollectObjective(5, typeof(PixieLeg), "Pixie Leg")); - - Rewards.Add(new DummyReward(1074634)); // Tuition Reimbursement - } - - public override Type NextQuest => typeof(FoolingAernya); - public override bool IsChainTriggered => true; - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 4, "Gorrow"), new Point3D(993, 512, -50), Map.Malas); - } - } - - public class FoolingAernya : MLQuest - { - public FoolingAernya() - { - Activated = true; - Title = 1074618; // Fooling Aernya - Description = - 1074619; // Now that I've signed your papers you'd better get back to that witch Aernya. Mmmm mmm smell those ribs! - RefusalMessage = 1074620; // Giving up on your scheme eh? Suit yourself. - InProgressMessage = - 1074621; // You better hurry back to Mistress Aernya with that signed form. The college only has so much money and with enough claims you may find yourself unable to get your tuition refunded. *wink* - CompletionMessage = 1074622; // What? Hrmph. Gorrow signed your form did he? Let me see that. *squint* - CompletionNotice = CompletionNoticeShort; - - Objectives.Add(new DeliverObjective(typeof(SignedTuitionReimbursementForm), 1, - "Signed Tuition Reimbursement Form", typeof(Aernya))); - - Rewards.Add(new DummyReward(1074634)); // Tuition Reimbursement - } - - public override Type NextQuest => typeof(NotQuiteThatEasy); - public override bool IsChainTriggered => true; - } - - public class NotQuiteThatEasy : MLQuest - { - public NotQuiteThatEasy() - { - Activated = true; - Title = 1074623; // Not Quite That Easy - Description = - 1074624; // I wouldn't be too smug just yet, whiner. You still need Master Gnosos' signature before I can cut your refund. Last I heard, he's coordinating the recovery of the portions of the college that are currently overrun. *nasty smile* Off with you. - RefusalMessage = 1074626; // Coward. - InProgressMessage = 1074627; // What are you waiting for? The iron maiden is still the portal to Bedlam. - CompletionMessage = - 1074628; // Made it through did you? Did you happen to see Red Death out there? Big horse, skeletal ... burning eyes? No? What's this? Forms? FORMS? I'm up to my eyebrows in ravenous out-of-control undead and you want a signature? - CompletionNotice = CompletionNoticeShort; - - Objectives.Add(new DeliverObjective(typeof(SignedTuitionReimbursementForm), 1, - "Signed Tuition Reimbursement Form", typeof(MasterGnosos))); - - Rewards.Add(new DummyReward(1074634)); // Tuition Reimbursement - } - - public override Type NextQuest => typeof(ConvinceMe); - public override bool IsChainTriggered => true; - - public override void Generate() - { - base.Generate(); - - PutDeco(new BedlamTeleporter(), new Point3D(2067, 1371, -75), Map.Malas); - } - - public override void OnAccepted(MLQuestInstance instance) - { - instance.PlayerContext.BedlamAccess = true; // Permanent access - } - } - - public class ConvinceMe : MLQuest - { - public ConvinceMe() - { - Activated = true; - Title = 1074629; // Convince Me - Description = - 1074630; // I'm not signing any forms until the situation here is under control. So, you can either help out or you can forget getting your tuition refund. Which will it be? Help control the shambling dead? - RefusalMessage = 1074631; // No signature for you. - InProgressMessage = - 1074632; // No signature for you until you kill off some of the shambling dead out there and destroy that blasted horse. - CompletionMessage = 1074633; // Pulled it off huh? Well then you've earned this signature! - CompletionNotice = CompletionNoticeShortReturn; - - QuestArea bedlam = new QuestArea(1074835, "Bedlam"); // Bedlam - - Objectives.Add(new KillObjective(1, new[] { typeof(RedDeath) }, "Red Death", bedlam)); - Objectives.Add(new KillObjective(10, new[] { typeof(GoreFiend) }, "gore fiends", bedlam)); - Objectives.Add(new KillObjective(8, new[] { typeof(RottingCorpse) }, "rotting corpses", bedlam)); - - Rewards.Add(new DummyReward(1074634)); // Tuition Reimbursement - } - - public override Type NextQuest => typeof(TuitionReimbursement); - public override bool IsChainTriggered => true; - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 3, "MasterGnosos"), new Point3D(87, 1639, 0), Map.Malas); - } - } - - public class TuitionReimbursement : MLQuest - { - public TuitionReimbursement() - { - Activated = true; - Title = 1074634; // Tuition Reimbursement - Description = - 1074635; // Well, there you are. I've added my signature to that of Gorrow, so you should be set to return to Mistress Aernya and get your tuition refunded. - RefusalMessage = - 1074636; // Great! If you're going to stick around here, I know we have more tasks for you to perform. - InProgressMessage = - 1074637; // Just head out the main gates there and you'll find yourself embracing the iron maiden in the Bloodletter's Guild. - CompletionMessage = - 1074638; // *disinterested stare* What? Oh, you've gotten your form filled in. How nice. *glare* And I'd hoped you'd drop this charade before I was forced to rub your nose in it. *nasty smile* You're not even a student and as such, you're not eligible for a refund -- you've never paid tuition. For your services, Master Gnosos has recommended you receive pay. So here. Now go away. - CompletionNotice = CompletionNoticeShort; - - Objectives.Add(new DeliverObjective(typeof(CompletedTuitionReimbursementForm), 1, - "Completed Tuition Reimbursement Form", typeof(Aernya))); - - Rewards.Add(ItemReward.Strongbox); - } - - public override bool IsChainTriggered => true; - } - - [QuesterName("Aernya (Umbra)")] - public class Aernya : BaseCreature - { - [Constructible] - public Aernya() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Mistress of Admissions"; - Race = Race.Human; - BodyValue = 0x191; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Backpack()); - AddItem(new Sandals(Utility.RandomNeutralHue())); - AddItem(new Skirt(Utility.RandomBool() ? 0x1 : 0x0)); - AddItem(new Cloak(Utility.RandomBrightHue())); - AddItem(new FancyShirt(Utility.RandomBool() ? 0x3B2 : 0x3B3)); - } - - public Aernya(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Aernya"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Gorrow (Luna)")] - public class Gorrow : BaseCreature - { - [Constructible] - public Gorrow() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Mayor"; - Race = Race.Human; - BodyValue = 0x190; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - AddItem(new Backpack()); - AddItem(new Shoes(0x1BB)); - AddItem(new Tunic(Utility.RandomNeutralHue())); - AddItem(new LongPants(0x901)); - AddItem(new Cloak(Utility.RandomRedHue())); - } - - public Gorrow(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Gorrow"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074200, // Thank goodness you are here, there�s no time to lose. - 1074203)); // Hello friend. I realize you are busy but if you would be willing to render me a service I can assure you that you will be judiciously renumerated. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Master Gnosos (Bedlam)")] - public class MasterGnosos : BaseCreature - { - [Constructible] - public MasterGnosos() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the necromancer"; - Race = Race.Human; - BodyValue = 0x190; - Female = false; - Hue = 0x83E8; - InitStats(100, 100, 25); - - HairItemID = 0x2049; - FacialHairItemID = 0x204B; - - AddItem(new Backpack()); - AddItem(new Shoes(0x485)); - AddItem(new Robe(0x497)); - - SetSkill(SkillName.EvalInt, 60.0, 80.0); - SetSkill(SkillName.Inscribe, 60.0, 80.0); - SetSkill(SkillName.MagicResist, 60.0, 80.0); - SetSkill(SkillName.SpiritSpeak, 60.0, 80.0); - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Necromancy, 60.0, 80.0); - } - - public MasterGnosos(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Master Gnosos"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1074186); // Come here, I have a task. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using Server.Engines.MLQuests.Items; +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; +using Server.Engines.Spawners; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Definitions +{ + public class MistakenIdentity : MLQuest + { + public MistakenIdentity() + { + Activated = true; + Title = 1074573; // Mistaken Identity + Description = + 1074574; // What do you want? Wonderful, another whining request for a refund on tuition. You know, experiences like that are invaluable ... and infrequent. Having the opportunity to test yourself under such realistic situations isn't something the college offers all students. Fine. Fine. You'll need to submit a refund request form in triplicate before I can return your 1,000,000 gold tuition. You'll need to get some signatures and a few other odds and ends. + RefusalMessage = 1074606; // If you're not willing to follow the proper process then go away. + InProgressMessage = 1074605; // You're not getting a refund without the proper forms and signatures. + CompletionMessage = 1074607; // Oh blast! Not another of those forms. I'm so sick of this endless paperwork. + CompletionNotice = CompletionNoticeShort; + + Objectives.Add( + new DeliverObjective( + typeof(TuitionReimbursementForm), + 1, + "Tuition Reimbursement Form", + typeof(Gorrow) + ) + ); + + Rewards.Add(new DummyReward(1074634)); // Tuition Reimbursement + } + + public override Type NextQuest => typeof(YouScratchMyBack); + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Aernya"), new Point3D(2095, 1380, -90), Map.Malas); + } + } + + public class YouScratchMyBack : MLQuest + { + public YouScratchMyBack() + { + Activated = true; + Title = 1074608; // You Scratch My Back + Description = + 1074609; // Heh. Heheheh. Good one. You're not a Bedlam student and you're definitely not eligible for a tuition refund. Heheheh. That old witch Aernya doesn't see as well as she used to you know. Otherwise, she would have ... hmmm, wait a minute. I sense a certain 'opportunity' here. I'll sign your forms in return for a little help with a project of my own. What do you say? + RefusalMessage = 1074615; // Hehehe. Your choice. + InProgressMessage = + 1074616; // I'm something of a gourmet, you see. It's tough getting some of the ingredients, though. Bring me back some pixie legs, unicorn ribs and ki-rin brains and I'll sign your form. + CompletionMessage = + 1074617; // Oh excellent, you're back. I'll get the oven going. That thing about pixie legs, you see, is that they burn and dry out if you're not really careful. Taste just like chicken too! + CompletionNotice = CompletionNoticeShortReturn; + + Objectives.Add(new CollectObjective(1, typeof(UnicornRibs), "Unicorn Ribs")); + Objectives.Add(new CollectObjective(2, typeof(KirinBrains), "Ki-Rin Brains")); + Objectives.Add(new CollectObjective(5, typeof(PixieLeg), "Pixie Leg")); + + Rewards.Add(new DummyReward(1074634)); // Tuition Reimbursement + } + + public override Type NextQuest => typeof(FoolingAernya); + public override bool IsChainTriggered => true; + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 4, "Gorrow"), new Point3D(993, 512, -50), Map.Malas); + } + } + + public class FoolingAernya : MLQuest + { + public FoolingAernya() + { + Activated = true; + Title = 1074618; // Fooling Aernya + Description = + 1074619; // Now that I've signed your papers you'd better get back to that witch Aernya. Mmmm mmm smell those ribs! + RefusalMessage = 1074620; // Giving up on your scheme eh? Suit yourself. + InProgressMessage = + 1074621; // You better hurry back to Mistress Aernya with that signed form. The college only has so much money and with enough claims you may find yourself unable to get your tuition refunded. *wink* + CompletionMessage = 1074622; // What? Hrmph. Gorrow signed your form did he? Let me see that. *squint* + CompletionNotice = CompletionNoticeShort; + + Objectives.Add( + new DeliverObjective( + typeof(SignedTuitionReimbursementForm), + 1, + "Signed Tuition Reimbursement Form", + typeof(Aernya) + ) + ); + + Rewards.Add(new DummyReward(1074634)); // Tuition Reimbursement + } + + public override Type NextQuest => typeof(NotQuiteThatEasy); + public override bool IsChainTriggered => true; + } + + public class NotQuiteThatEasy : MLQuest + { + public NotQuiteThatEasy() + { + Activated = true; + Title = 1074623; // Not Quite That Easy + Description = + 1074624; // I wouldn't be too smug just yet, whiner. You still need Master Gnosos' signature before I can cut your refund. Last I heard, he's coordinating the recovery of the portions of the college that are currently overrun. *nasty smile* Off with you. + RefusalMessage = 1074626; // Coward. + InProgressMessage = 1074627; // What are you waiting for? The iron maiden is still the portal to Bedlam. + CompletionMessage = + 1074628; // Made it through did you? Did you happen to see Red Death out there? Big horse, skeletal ... burning eyes? No? What's this? Forms? FORMS? I'm up to my eyebrows in ravenous out-of-control undead and you want a signature? + CompletionNotice = CompletionNoticeShort; + + Objectives.Add( + new DeliverObjective( + typeof(SignedTuitionReimbursementForm), + 1, + "Signed Tuition Reimbursement Form", + typeof(MasterGnosos) + ) + ); + + Rewards.Add(new DummyReward(1074634)); // Tuition Reimbursement + } + + public override Type NextQuest => typeof(ConvinceMe); + public override bool IsChainTriggered => true; + + public override void Generate() + { + base.Generate(); + + PutDeco(new BedlamTeleporter(), new Point3D(2067, 1371, -75), Map.Malas); + } + + public override void OnAccepted(MLQuestInstance instance) + { + instance.PlayerContext.BedlamAccess = true; // Permanent access + } + } + + public class ConvinceMe : MLQuest + { + public ConvinceMe() + { + Activated = true; + Title = 1074629; // Convince Me + Description = + 1074630; // I'm not signing any forms until the situation here is under control. So, you can either help out or you can forget getting your tuition refund. Which will it be? Help control the shambling dead? + RefusalMessage = 1074631; // No signature for you. + InProgressMessage = + 1074632; // No signature for you until you kill off some of the shambling dead out there and destroy that blasted horse. + CompletionMessage = 1074633; // Pulled it off huh? Well then you've earned this signature! + CompletionNotice = CompletionNoticeShortReturn; + + var bedlam = new QuestArea(1074835, "Bedlam"); // Bedlam + + Objectives.Add(new KillObjective(1, new[] { typeof(RedDeath) }, "Red Death", bedlam)); + Objectives.Add(new KillObjective(10, new[] { typeof(GoreFiend) }, "gore fiends", bedlam)); + Objectives.Add(new KillObjective(8, new[] { typeof(RottingCorpse) }, "rotting corpses", bedlam)); + + Rewards.Add(new DummyReward(1074634)); // Tuition Reimbursement + } + + public override Type NextQuest => typeof(TuitionReimbursement); + public override bool IsChainTriggered => true; + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 3, "MasterGnosos"), new Point3D(87, 1639, 0), Map.Malas); + } + } + + public class TuitionReimbursement : MLQuest + { + public TuitionReimbursement() + { + Activated = true; + Title = 1074634; // Tuition Reimbursement + Description = + 1074635; // Well, there you are. I've added my signature to that of Gorrow, so you should be set to return to Mistress Aernya and get your tuition refunded. + RefusalMessage = + 1074636; // Great! If you're going to stick around here, I know we have more tasks for you to perform. + InProgressMessage = + 1074637; // Just head out the main gates there and you'll find yourself embracing the iron maiden in the Bloodletter's Guild. + CompletionMessage = + 1074638; // *disinterested stare* What? Oh, you've gotten your form filled in. How nice. *glare* And I'd hoped you'd drop this charade before I was forced to rub your nose in it. *nasty smile* You're not even a student and as such, you're not eligible for a refund -- you've never paid tuition. For your services, Master Gnosos has recommended you receive pay. So here. Now go away. + CompletionNotice = CompletionNoticeShort; + + Objectives.Add( + new DeliverObjective( + typeof(CompletedTuitionReimbursementForm), + 1, + "Completed Tuition Reimbursement Form", + typeof(Aernya) + ) + ); + + Rewards.Add(ItemReward.Strongbox); + } + + public override bool IsChainTriggered => true; + } + + [QuesterName("Aernya (Umbra)")] + public class Aernya : BaseCreature + { + [Constructible] + public Aernya() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Mistress of Admissions"; + Race = Race.Human; + BodyValue = 0x191; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Backpack()); + AddItem(new Sandals(Utility.RandomNeutralHue())); + AddItem(new Skirt(Utility.RandomBool() ? 0x1 : 0x0)); + AddItem(new Cloak(Utility.RandomBrightHue())); + AddItem(new FancyShirt(Utility.RandomBool() ? 0x3B2 : 0x3B3)); + } + + public Aernya(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Aernya"; + + 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(); + } + } + + [QuesterName("Gorrow (Luna)")] + public class Gorrow : BaseCreature + { + [Constructible] + public Gorrow() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Mayor"; + Race = Race.Human; + BodyValue = 0x190; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + AddItem(new Backpack()); + AddItem(new Shoes(0x1BB)); + AddItem(new Tunic(Utility.RandomNeutralHue())); + AddItem(new LongPants(0x901)); + AddItem(new Cloak(Utility.RandomRedHue())); + } + + public Gorrow(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Gorrow"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074200, // Thank goodness you are here, there�s no time to lose. + 1074203 + ) + ); // Hello friend. I realize you are busy but if you would be willing to render me a service I can assure you that you will be judiciously renumerated. + } + + 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(); + } + } + + [QuesterName("Master Gnosos (Bedlam)")] + public class MasterGnosos : BaseCreature + { + [Constructible] + public MasterGnosos() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the necromancer"; + Race = Race.Human; + BodyValue = 0x190; + Female = false; + Hue = 0x83E8; + InitStats(100, 100, 25); + + HairItemID = 0x2049; + FacialHairItemID = 0x204B; + + AddItem(new Backpack()); + AddItem(new Shoes(0x485)); + AddItem(new Robe(0x497)); + + SetSkill(SkillName.EvalInt, 60.0, 80.0); + SetSkill(SkillName.Inscribe, 60.0, 80.0); + SetSkill(SkillName.MagicResist, 60.0, 80.0); + SetSkill(SkillName.SpiritSpeak, 60.0, 80.0); + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Necromancy, 60.0, 80.0); + } + + public MasterGnosos(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Master Gnosos"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1074186); // Come here, I have a task. + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Definitions/NewHaven.cs b/Projects/UOContent/Engines/MLQuests/Definitions/NewHaven.cs index 71fcdac89..271009316 100644 --- a/Projects/UOContent/Engines/MLQuests/Definitions/NewHaven.cs +++ b/Projects/UOContent/Engines/MLQuests/Definitions/NewHaven.cs @@ -1,125 +1,125 @@ -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; -using Server.Items; - -namespace Server.Engines.MLQuests.Definitions -{ - public class NewHavenEscort : BaseEscort - { - // Escort reward - private static readonly BaseReward m_Reward = new ItemReward("Gold", typeof(Gold), 500); - - public NewHavenEscort(int title, int description, int progress, int destination, string region) - { - Activated = true; - Title = title; - Description = description; - RefusalMessage = - 1072288; // I wish you would reconsider my offer. I'll be waiting right here for someone brave enough to assist me. - InProgressMessage = progress; - - Objectives.Add(new EscortObjective(new QuestArea(destination, region))); - - Rewards.Add(m_Reward); - } - - // New Haven escorts do not count for 'helping a human in need' - public override bool AwardHumanInNeed => false; - } - - public class EscortToNHAlchemist : NewHavenEscort - { - public EscortToNHAlchemist() - : base(1072314, 1042769, 1072326, 1073864, "the New Haven Alchemist") - { - } - } - - public class EscortToNHBard : NewHavenEscort - { - public EscortToNHBard() - : base(1072315, 1042772, 1072327, 1073865, "the New Haven Bard") - { - } - } - - public class EscortToNHWarrior : NewHavenEscort - { - public EscortToNHWarrior() - : base(1072316, 1042787, 1072328, 1073866, "the New Haven Warrior") - { - } - } - - public class EscortToNHTailor : NewHavenEscort - { - public EscortToNHTailor() - : base(1072317, 1042781, 1072329, 1073867, "the New Haven Tailor") - { - } - } - - public class EscortToNHCarpenter : NewHavenEscort - { - public EscortToNHCarpenter() - : base(1072318, 1042775, 1072330, 1073868, "the New Haven Carpenter") - { - } - } - - public class EscortToNHMapmaker : NewHavenEscort - { - public EscortToNHMapmaker() - : base(1072319, 1042793, 1072331, 1073869, "the New Haven Mapmaker") - { - } - } - - public class EscortToNHMage : NewHavenEscort - { - public EscortToNHMage() - : base(1072320, 1042790, 1072332, 1073870, "the New Haven Mage") - { - } - } - - public class EscortToNHInn : NewHavenEscort - { - public EscortToNHInn() - : base(1072321, 1042796, 1072333, 1073871, "the New Haven Inn") - { - } - } - - public class EscortToNHFarm : NewHavenEscort - { - public EscortToNHFarm() - : base(1072322, 1042799, 1072334, 1073872, "the New Haven Farm") - { - } - } - - public class EscortToNHDocks : NewHavenEscort - { - public EscortToNHDocks() - : base(1072323, 1042802, 1072335, 1073873, "the New Haven Docks") - { - } - } - - public class EscortToNHBowyer : NewHavenEscort - { - public EscortToNHBowyer() - : base(1072324, 1042805, 1072336, 1073874, "the New Haven Bowyer") - { - } - } - - public class EscortToNHBank : NewHavenEscort - { - public EscortToNHBank() - : base(1072325, 1042784, 1072337, 1073875, "the New Haven Bank") - { - } - } -} \ No newline at end of file +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; +using Server.Items; + +namespace Server.Engines.MLQuests.Definitions +{ + public class NewHavenEscort : BaseEscort + { + // Escort reward + private static readonly BaseReward m_Reward = new ItemReward("Gold", typeof(Gold), 500); + + public NewHavenEscort(int title, int description, int progress, int destination, string region) + { + Activated = true; + Title = title; + Description = description; + RefusalMessage = + 1072288; // I wish you would reconsider my offer. I'll be waiting right here for someone brave enough to assist me. + InProgressMessage = progress; + + Objectives.Add(new EscortObjective(new QuestArea(destination, region))); + + Rewards.Add(m_Reward); + } + + // New Haven escorts do not count for 'helping a human in need' + public override bool AwardHumanInNeed => false; + } + + public class EscortToNHAlchemist : NewHavenEscort + { + public EscortToNHAlchemist() + : base(1072314, 1042769, 1072326, 1073864, "the New Haven Alchemist") + { + } + } + + public class EscortToNHBard : NewHavenEscort + { + public EscortToNHBard() + : base(1072315, 1042772, 1072327, 1073865, "the New Haven Bard") + { + } + } + + public class EscortToNHWarrior : NewHavenEscort + { + public EscortToNHWarrior() + : base(1072316, 1042787, 1072328, 1073866, "the New Haven Warrior") + { + } + } + + public class EscortToNHTailor : NewHavenEscort + { + public EscortToNHTailor() + : base(1072317, 1042781, 1072329, 1073867, "the New Haven Tailor") + { + } + } + + public class EscortToNHCarpenter : NewHavenEscort + { + public EscortToNHCarpenter() + : base(1072318, 1042775, 1072330, 1073868, "the New Haven Carpenter") + { + } + } + + public class EscortToNHMapmaker : NewHavenEscort + { + public EscortToNHMapmaker() + : base(1072319, 1042793, 1072331, 1073869, "the New Haven Mapmaker") + { + } + } + + public class EscortToNHMage : NewHavenEscort + { + public EscortToNHMage() + : base(1072320, 1042790, 1072332, 1073870, "the New Haven Mage") + { + } + } + + public class EscortToNHInn : NewHavenEscort + { + public EscortToNHInn() + : base(1072321, 1042796, 1072333, 1073871, "the New Haven Inn") + { + } + } + + public class EscortToNHFarm : NewHavenEscort + { + public EscortToNHFarm() + : base(1072322, 1042799, 1072334, 1073872, "the New Haven Farm") + { + } + } + + public class EscortToNHDocks : NewHavenEscort + { + public EscortToNHDocks() + : base(1072323, 1042802, 1072335, 1073873, "the New Haven Docks") + { + } + } + + public class EscortToNHBowyer : NewHavenEscort + { + public EscortToNHBowyer() + : base(1072324, 1042805, 1072336, 1073874, "the New Haven Bowyer") + { + } + } + + public class EscortToNHBank : NewHavenEscort + { + public EscortToNHBank() + : base(1072325, 1042784, 1072337, 1073875, "the New Haven Bank") + { + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Definitions/NewHavenSkillTraining.cs b/Projects/UOContent/Engines/MLQuests/Definitions/NewHavenSkillTraining.cs index 6c7b911d7..1b42bd86a 100644 --- a/Projects/UOContent/Engines/MLQuests/Definitions/NewHavenSkillTraining.cs +++ b/Projects/UOContent/Engines/MLQuests/Definitions/NewHavenSkillTraining.cs @@ -1,2522 +1,2533 @@ -using System.Collections.Generic; -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; -using Server.Engines.Spawners; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Definitions -{ - public class CleansingOldHaven : MLQuest - { - public CleansingOldHaven() - { - Activated = true; - OneTimeOnly = true; - Title = 1077719; // Cleansing Old Haven - Description = - 1077722; // Head East out of town to Old Haven. Consecrate your weapon, cast Divine Fury, and battle monsters there until you have raised your Chivalry skill to 50.
------

Hail, friend. The life of a Paladin is a life of much sacrifice, humility, bravery, and righteousness. If you wish to pursue such a life, I have an assignment for you. Adventure east to Old Haven, consecrate your weapon, and lay to rest the undead that inhabit there.

Each ability a Paladin wishes to invoke will require a certain amount of "tithing points" to use. A Paladin can earn these tithing points by donating gold at a shrine or holy place. You may tithe at this shrine.

Return to me once you feel that you are worthy of the rank of Apprentice Paladin. - RefusalMessage = 1077723; // Farewell to you my friend. Return to me if you wish to live the life of a Paladin. - InProgressMessage = - 1077724; // There are still more undead to lay to rest. You still have more to learn. Return to me once you have done so. - CompletionMessage = - 1077726; // Well done, friend. While I know you understand Chivalry is its own reward, I would like to reward you with something that will protect you in battle. It was passed down to me when I was a lad. Now, I am passing it on you. It is called the Bulwark Leggings. Thank you for your service. - CompletionNotice = - 1077725; // You have achieved the rank of Apprentice Paladin. Return to Aelorn in New Haven to report your progress. - - Objectives.Add(new GainSkillObjective(SkillName.Chivalry, 500, true, true)); - - Rewards.Add(new ItemReward(1077727, typeof(BulwarkLeggings))); // Bulwark Leggings - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Aelorn"), new Point3D(3527, 2516, 45), Map.Trammel); - } - } - - public class TheRudimentsOfSelfDefense : MLQuest - { - public TheRudimentsOfSelfDefense() - { - Activated = true; - OneTimeOnly = true; - Title = 1077609; // The Rudiments of Self Defense - Description = - 1077610; // Head East out of town and go to Old Haven. Battle monster there until you have raised your Wrestling skill to 50.Listen up! If you want to learn the rudiments of self-defense, you need toughening up, and there's no better way to toughen up than engaging in combat. Head East out of town to Old Haven and battle the undead there in hand to hand combat. Afraid of dying, you say? Well, you should be! Being an adventurer isn't a bed of posies, or roses, or however that saying goes. If you take a dirt nap, go to one of the nearby wandering healers and they'll get you back on your feet.Come back to me once you feel that you are worthy of the rank Apprentice Wrestler and i will reward you wit a prize. - RefusalMessage = - 1077611; // Ok, featherweight. come back to me if you want to learn the rudiments of self-defense. - InProgressMessage = - 1077630; // You have not achived the rank of Apprentice Wrestler. Come back to me once you feel that you are worthy of the rank Apprentice Wrestler and i will reward you with something useful. - CompletionMessage = - 1077613; // It's about time! Looks like you managed to make it through your self-defense training. As i promised, here's a little something for you. When worn, these Gloves of Safeguarding will increase your awareness and resistances to most elements except poison. Oh yeah, they also increase your natural health regeneration aswell. Pretty handy gloves, indeed. Oh, if you are wondering if your meditation will be hinered while wearing these gloves, it won't be. Mages can wear cloth and leather items without needing to worry about that. Now get out of here and make something of yourself. - CompletionNotice = - 1077612; // You have achieved the rank of Apprentice Wrestler. Return to Dimethro in New Haven to receive your prize. - - Objectives.Add(new GainSkillObjective(SkillName.Wrestling, 500, true, true)); - - Rewards.Add(new ItemReward(1077614, typeof(GlovesOfSafeguarding))); // Gloves Of Safeguarding - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Dimethro"), new Point3D(3528, 2520, 25), Map.Trammel); - } - } - - public class CrushingBonesAndTakingNames : MLQuest - { - public CrushingBonesAndTakingNames() - { - Activated = true; - OneTimeOnly = true; - Title = 1078070; // Crushing Bones and Taking Names - Description = - 1078065; // Head East out of town and go to Old Haven. While wielding your mace,battle monster there until you have raised your Mace Fighting skill to 50. I see you want to learn a real weapon skill and not that toothpick training Jockles hasto offer. Real warriors are called Armsmen, and they wield mace weapons. No doubt about it. Nothing is more satisfying than knocking the wind out of your enemies, smashing there armor, crushing their bones, and taking there names. Want to learn how to wield a mace? Well i have an assignment for you. Head East out of town and go to Old Haven. Undead have plagued the town, so there are plenty of bones for you to smash there. Come back to me after you have ahcived the rank of Apprentice Armsman, and i will reward you with a real weapon. - RefusalMessage = - 1078068; // I thought you wanted to be an Armsman and really make something of yourself. You have potential, kid, but if you want to play with toothpicks, run to Jockles and he will teach you how to clean your teeth with a sword. If you change your mind, come back to me, and i will show you how to wield a real weapon. - InProgressMessage = - 1078067; // Listen kid. There are a lot of undead in Old Haven, and you haven't smashed enough of them yet. So get back there and do some more cleansing. - CompletionMessage = - 1078069; // Now that's what I'm talking about! Well done! Don't you like crushing bones and taking names? As i promised, here is a war mace for you. It hits hard. It swings fast. It hits often. What more do you need? Now get out of here and crush some more enemies! - CompletionNotice = - 1078068; // You have achieved the rank of Apprentice Armsman. Return to Churchill in New Haven to claim your reward. - - Objectives.Add(new GainSkillObjective(SkillName.Macing, 500, true, true)); - - Rewards.Add(new ItemReward(1078062, typeof(ChurchillsWarMace))); // Churchill's War Mace - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Churchill"), new Point3D(3531, 2531, 20), Map.Trammel); - } - } - - public class SwiftAsAnArrow : MLQuest - { - public SwiftAsAnArrow() - { - Activated = true; - OneTimeOnly = true; - Title = 1078201; // Swift as an Arrow - Description = - 1078205; // Head East out of town and go to Old Haven. While wielding your bow or crossbow, battle monster there until you have raised your Archery skill to 50. Well met, friend. Imagine yourself in a distant grove of trees, You raise your bow, take slow, careful aim, and with the twitch of a finger, you impale your prey with a deadly arrow. You look like you would make a excellent archer, but you will need practice. There is no better way to practice Archery than when you life is on the line. I have a challenge for you. Head East out of town and go to Old Haven. While wielding your bow or crossbow, battle the undead that reside there. Make sure you bring a healthy supply of arrows (or bolts if you prefer a crossbow). If you wish to purchase a bow, crossbow, arrows, or bolts, you can purchase them from me or the Archery shop in town. You can also make your own arrows with the Bowcraft/Fletching skill. You will need fletcher's tools, wood to turn into sharft's, and feathers to make arrows or bolts. Come back to me after you have achived the rank of Apprentice Archer, and i will reward you with a fine Archery weapon. - RefusalMessage = - 1078206; // I understand that Archery may not be for you. Feel free to visit me in the future if you change your mind. - InProgressMessage = 1078207; // You're doing great as an Archer! however, you need more practice. - CompletionMessage = - 1078209; // Congratulation! I want to reward you for your accomplishment. Take this composite bow. It is called " Heartseeker". With it, you will shoot with swiftness, precision, and power. I hope "Heartseeker" serves you well. - CompletionNotice = - 1078208; // You have achieved the rank of Apprentice Archer. Return to Robyn in New Haven to claim your reward. - - Objectives.Add(new GainSkillObjective(SkillName.Archery, 500, true, true)); - - Rewards.Add(new ItemReward(1078210, typeof(Heartseeker))); // Heartseeker - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Robyn"), new Point3D(3535, 2531, 20), Map.Trammel); - } - } - - public class EnGuarde : MLQuest - { - public EnGuarde() - { - Activated = true; - OneTimeOnly = true; - Title = 1078186; // En Guarde! - Description = - 1078190; // Head East out of town to Old Haven. Battle monsters there until you have raised your Fencing skill to 50.
------

Well hello there, lad. Fighting with elegance and precision is far more enriching than slugging an enemy with a club or butchering an enemy with a sword. Learn the art of Fencing if you want to master combat and look good doing it!

The key to being a successful fencer is to be the complement and not the opposition to your opponent's strength. Watch for your opponent to become off balance. Then finish him off with finesse and flair.

There are some undead that need cleansing out in Old Haven towards the East. Head over there and slay them, but remember, do it with style!

Come back to me once you have achieved the rank of Apprentice Fencer, and I will reward you with a prize. - RefusalMessage = - 1078191; // I understand, lad. Being a hero isn't for everyone. Run along, then. Come back to me if you change your mind. - InProgressMessage = - 1078192; // You're doing well so far, but you're not quite ready yet. Head back to Old Haven, to the East, and kill some more undead. - CompletionMessage = - 1078194; // Excellent! You are beginning to appreciate the art of Fencing. I told you fighting with elegance and precision is more enriching than fighting like an ogre.

Since you have returned victorious, please take this war fork and use it well. The war fork is a finesse weapon, and this one is magical! I call it "Recaro's Riposte". With it, you will be able to parry and counterstrike with ease! Your enemies will bask in your greatness and glory! Good luck to you, lad, and keep practicing! - CompletionNotice = - 1078193; // You have achieved the rank of Apprentice Fencer. Return to Recaro in New Haven to claim your reward. - - Objectives.Add(new GainSkillObjective(SkillName.Fencing, 500, true, true)); - - Rewards.Add(new ItemReward(1078195, typeof(RecarosRiposte))); // Recaro's Riposte - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Recaro"), new Point3D(3536, 2534, 20), Map.Trammel); - } - } - - public class TheArtOfWar : MLQuest - { - public TheArtOfWar() - { - Activated = true; - OneTimeOnly = true; - Title = 1077667; // The Art of War - Description = - 1077670; // Head East out of town to Old Haven. Battle monsters there until you have raised your Tactics skill to 50.
------

Knowing how to hold a weapon is only half of the battle. The other half is knowing how to use it against an opponent. It's one thing to kill a few bunnies now and then for fun, but a true warrior knows that the right moves to use against a lich will pretty much get your arse fried by a dragon.

I'll help teach you how to fight so that when you do come up against that dragon, maybe you won't have to walk out of there "OooOOooOOOooOO'ing" and looking for a healer.

There are some undead that need cleaning out in Old Haven towards the east. Why don't you head on over there and practice killing things?

When you feel like you've got the basics down, come back to me and I'll see if I can scrounge up an item to help you in your adventures later on. - RefusalMessage = - 1077671; // That's too bad. I really thought you had it in you. Well, I'm sure those undead will still be there later, so if you change your mind, feel free to stop on by and I'll help you the best I can. - InProgressMessage = - 1077672; // You're making some progress, that i can tell, but you're not quite good enough to last for very long out there by yourself. Head back to Old Haven, to the east, and kill some more undead. - CompletionMessage = - 1077674; // Hey, good job killing those undead! Hopefully someone will come along and clean up the mess. All that blood and guts tends to stink after a few days, and when the wind blows in from the east, it can raise a mighty stink!

Since you performed valiantly, please take these arms and use them well. I've seen a few too many harvests to be running around out there myself, so you might as well take it.

There is a lot left for you to learn, but I think you'll do fine. Remember to keep your elbows in and stick'em where it hurts the most! - CompletionNotice = - 1077673; // You have achieved the rank of Apprentice Warrior. Return to Alden Armstrong in New Haven to claim your reward. - - Objectives.Add(new GainSkillObjective(SkillName.Tactics, 500, true, true)); - - Rewards.Add(new ItemReward(1077675, typeof(ArmsOfArmstrong))); // Arms of Armstrong - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "AldenArmstrong"), new Point3D(3535, 2538, 20), Map.Trammel); - } - } - - public class TheWayOfTheBlade : MLQuest - { - public TheWayOfTheBlade() - { - Activated = true; - OneTimeOnly = true; - Title = 1077658; // The way of The Blade - Description = - 1077661; // Head East out of town and go to Old Haven. While wielding your sword, battle monster there until you have raised your Swordsmanship skill to 50. *as you approach, you notice Jockles sizing you up with a skeptical look on his face* i can see you want to learn how to handle a blade. It's a lot harder than it looks, and you're going to have to put alot of time and effort if you ever want to be half as good as i am. I'll tell you what, kid, I'll help you get started, but you're going to have to do all the work if you want to learn something. East of here, outside of town, is Old Haven. It's been overrun with the nastiest of undead you've seen, which makes it a perfect place for you to turn that sloppy grin on your face into actual skill at handling a sword. Make sure you have a sturdy Swordsmanship weapon in good repair before you leave. 'tis no fun to travel all the way down there just to find out you forgot your blade! When you feel that you've cut down enough of those foul smelling things to learn how to handle a blade without hurting yourself, come back to me. If i think you've improved enough, I'll give you something suited for a real warrior. - RefusalMessage = - 1077662; // Ha! I had a feeling you were a lily-livered pansy. You might have potential, but you're scared by a few smelly undead, maybe it's better that you stay away from sharp objects. After all, you wouldn't want to hurt yourself swinging a sword. If you change your mind, I might give you another chance...maybe. - InProgressMessage = - 1077663; // *Jockles looks you up and down* Come on! You've got to work harder than that to get better. Now get out of here, go kill some more of those undead to the east in Old Haven, and don't come back till you've got real skill. - CompletionMessage = - 1077665; // Well, well, look at what we have here! You managed to do it after all. I have to say, I'm a little surprised that you came back in one piece, but since you did. I've got a little something for you. This is a fine blade that served me well in my younger days. Of course I've got much better swords at my disposal now, so I'll let you go ahead and use it under one condition. Take goodcare of it and treat it with the respect that a fine sword deserves. You're one of the quickers learners I've seen, but you still have a long way to go. Keep at it, and you'll get there someday. Happy hunting, kid. - CompletionNotice = - 1077664; // You have achieved the rank of Apprentice Swordsman. Return to Jockles in New Haven to see what kind of reward he has waiting for you. Hopefully he'll be a little nicer this time! - - Objectives.Add(new GainSkillObjective(SkillName.Swords, 500, true, true)); - - Rewards.Add(new ItemReward(1077666, typeof(JocklesQuicksword))); // Jockles' Quicksword - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Jockles"), new Point3D(3535, 2544, 20), Map.Trammel); - } - } - - public class ThouAndThineShield : MLQuest - { - public ThouAndThineShield() - { - Activated = true; - OneTimeOnly = true; - Title = 1077704; // Thou and Thine Shield - Description = - 1077707; // Head East out of town and go to Old Haven. Battle monsters, or simply let them hit you, while holding a shield or a weapon until you have raised your Parrying skill to 50. Oh, hello. You probably want me to teach you how to parry, don't you? Very Well. First, you'll need a weapon or a shield. Obviously shields work best of all, but you can parry with a 2-handed weapon. Or if you're feeling particularly brave, a 1-handed weapon will do in a pinch, I'd advise you to go to Old Haven, which you'll find to the East, and practice blocking incoming blows from the undead there. You'll learn quickly if you have more than one opponent attacking you at the same time to practice parrying lots of blows at once. That's the quickest way to master the art of parrying. If you manage to improve your skill enough, i have a shield that you might find useful. Come back to me when you've trained to an apprentice level. - RefusalMessage = - 1077708; // It's your choice, obviously, but I'd highly suggest that you learn to parry before adventuring out into the world. Come talk to me again when you get tired of being beat on by your opponents - InProgressMessage = - 1077709; // You're doing well, but in my opinion, I Don't think you really want to continue on without improving your parrying skill a bit more. Go to Old Haven, to the East, and practice blocking blows with a shield. - CompletionMessage = - 1077711; // Well done! You're much better at parrying blows than you were when we first met. You should be proud of your new ability and I bet your body is greatful to you aswell. *Tyl Ariadne laughs loudly at his ownn (mostly lame) joke* Oh yes, I did promise you a shield if I thought you were worthy of having it, so here you go. My father made these shields for the guards who served my father faithfully for many years, and I just happen to have obe that i can part with. You should find it useful as you explore the lands.Good luck, and may the Virtues be your guide. - CompletionNotice = - 1077710; // You have achieved the rank of Apprentice Warrior (for Parrying). Return to Tyl Ariadne in New Haven as soon as you can to claim your reward. - - Objectives.Add(new GainSkillObjective(SkillName.Parry, 500, true, true)); - - Rewards.Add(new ItemReward(1077694, typeof(EscutcheonDeAriadne))); // Escutcheon de Ariadne - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "TylAriadne"), new Point3D(3525, 2556, 20), Map.Trammel); - } - } - - public class DefyingTheArcane : MLQuest - { - public DefyingTheArcane() - { - Activated = true; - OneTimeOnly = true; - Title = 1077621; // Defying the Arcane - Description = - 1077623; // Head East out of town and go to Old Haven. Battle spell casting monsters there until you have raised your Resisting Spells skill to 50.
------

Hail and well met! To become a true master of the arcane art of Magery, I suggest learning the complementary skill known as Resisting Spells. While the name of this skill may suggest that it helps with resisting all spells, this is not the case. This skill helps you lessen the severity of spells that lower your stats or ones that last for a specific duration of time. It does not lessen damage from spells such as Energy Bolt or Flamestrike.

The Magery spells that can be resisted are Clumsy, Curse, Feeblemind, Mana Drain, Mana Vampire, Paralyze, Paralyze Field, Poison, Poison Field, and Weaken.

The Necromancy spells that can be resisted are Blood Oath, Corpse Skin, Mind Rot, and Pain Spike.

At higher ranks, the Resisting Spells skill also benefits you by adding a bonus to your minimum elemental resists. This bonus is only applied after all other resist modifications - such as from equipment - has been calculated. It's also not cumulative. It compares the number of your minimum resists to the calculated value of your modifications and uses the higher of the two values.

As you can see, Resisting Spells is a difficult skill to understand, and even more difficult to master. This is because in order to improve it, you will have to put yourself in harm's way - as in the path of one of the above spells.

Undead have plagued the town of Old Haven. We need your assistance in cleansing the town of this evil influence. Old Haven is located east of here. Battle the undead spell casters that inhabit there.

Comeback to me once you feel that you are worthy of the rank of Apprentice Mage and I will reward you with an arcane prize. - RefusalMessage = - 1077624; // The ability to resist powerful spells is a taxing experience. I understand your resistance in wanting to pursue it. If you wish to reconsider, feel free to return to me for Resisting Spells training. Good journey to you! - InProgressMessage = - 1077632; // You have not achieved the rank of Apprentice Mage. Come back to me once you feel that you are worthy of the rank of Apprentice Mage and I will reward you with an arcane prize. - CompletionMessage = - 1077626; // You have successfully begun your journey in becoming a true master of Magery. On behalf of the New Haven Mage Council I wish to present you with this bracelet. When worn, the Bracelet of Resilience will enhance your resistances vs. the elements, physical, and poison harm. The Bracelet of Resilience also magically enhances your ability fend off ranged and melee attacks. I hope it serves you well. - CompletionNotice = - 1077625; // You have achieved the rank of Apprentice Mage (for Resisting Spells). Return to Alefian in New Haven to receive your arcane prize. - - Objectives.Add(new GainSkillObjective(SkillName.MagicResist, 500, true, true)); - - Rewards.Add(new ItemReward(1077627, typeof(BraceletOfResilience))); // Bracelet of Resilience - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Alefian"), new Point3D(3473, 2497, 72), Map.Trammel); - } - } - - public class StoppingTheWorld : MLQuest - { - public StoppingTheWorld() - { - Activated = true; - OneTimeOnly = true; - Title = 1077597; // Stopping the World - Description = - 1077598; // Head East out of town and go to Old Haven. Use spells and abilities to deplete your mana and meditate there until you have raised your Meditation skill to 50. Well met! I can teach you how to 'Stop the World' around you and focus your inner energies on replenishing you mana. What is mana? Mana is the life force for everyone who practices arcane arts. When a practitioner of magic invokes a spell or scribes a scroll. It consumes mana. Having a abundant supply of mana is vital to excelling as a practitioner of the arcane. Those of us who study the art of Meditation are also known as stotics. The Meditation skill allows stoics to increase the rate at which they regenerate mana A Stoic needs to perform abilities or cast spells to deplete mana before he can meditate to replenish it. Meditation can occur passively or actively. Actively Meditation is more difficult to master but allows for the stoic to replenish mana at a significantly faster rate. Metal armor inerferes with the regenerative properties of Meditation. It is wise to wear leather or cloth protection when meditating. Head east out of town and go to Old Haven. Use spells and abilities to deplete your mana and actively meditate to replenish it. Come back once you feel you are at the worthy rank of Apprentice Stoic and i will reward you with a arcane prize. - RefusalMessage = 1077599; // Seek me out if you ever wish to study the art of Meditation. Good journey. - InProgressMessage = - 1077628; // You have not achieved the rank of Apprentice Stoic. Come back to me once you feel that you are worthy of the rank Apprentice Stoic and i will reward you with a arcane prize. - CompletionMessage = - 1077626; // You have successfully begun your journey in becoming a true master of Magery. On behalf of the New Haven Mage Council I wish to present you with this bracelet. When worn, the Bracelet of Resilience will enhance your resistances vs. the elements, physical, and poison harm. The Bracelet of Resilience also magically enhances your ability fend off ranged and melee attacks. I hope it serves you well. - CompletionNotice = - 1077600; // You have achieved the rank of Apprentice Stoic (for Meditation). Return to Gustar in New Haven to receive your arcane prize. - - Objectives.Add(new GainSkillObjective(SkillName.Meditation, 500, true, true)); - - Rewards.Add(new ItemReward(1077602, typeof(PhilosophersHat))); // Philosopher's Hat - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Gustar"), new Point3D(3474, 2492, 91), Map.Trammel); - } - } - - public class ScribingArcaneKnowledge : MLQuest - { - public ScribingArcaneKnowledge() - { - Activated = true; - OneTimeOnly = true; - Title = 1077615; // Scribing Arcane Knowledge - Description = - 1077616; // While here at the New Haven Magery Library, use a scribe's pen and scribe and 3rd and 4th circle Magery scrolls that you have in your spellbook. Remember, you will need blank scrolls as well. Do this until you have raised your Inscription skill to 50.
------

Greetings and welcome to the New Haven Magery Library! You wish to learn how to scribe spell scrolls? You have come to the right place! Inscribed in a steady hand and imbued with the power of reagents, a scroll can mean the difference between life and death in a perilous situation. Those knowledgeable in Inscription may transcribe spells to create useful and valuable magical scrolls.

Before you inscribe a spell, you must first be able to cast the spell without the aid of a scroll. This means that you need the appropriate level of proficiency as a mage, the required mana, and the required reagents. Second, you will need a blank scroll to write on and a scribe's pen. Then, you will need to decide which particular spell you wish to scribe. It may sound easy, but there is a bit more to it. As with the development of all skills, you need to practice Inscription of lower level spells before you can move onto the more difficult ones.

The most important aspect of Inscription is mana. Inscribing a scroll with a magic spell drains your mana. When inscribing 3rd circle or lower spells this will not be much of a problem for these spells consume a small amount of mana. However, when you are inscribing higher circle spells, you may see your mana drain rapidly. When this happens, pause or meditate before continuing.

I suggest you begin scribing any 3rd and 4th circle spells that you know. If you don't possess any, you can always barter with one of the local mage merchants or a fellow adventurer that is a seasoned Scribe.

Come back to me once you feel that you are worthy of the rank of Apprentice Scribe and I will reward you with an arcane prize. - RefusalMessage = - 1077617; // I understand. When you are ready, feel free to return to me for Inscription training. Thanks for stopping by! - InProgressMessage = - 1077631; // You have not achieved the rank of Apprentice Scribe. Come back to me once you feel that you are worthy of the rank Apprentice Scribe and i will reward you with a arcane prize. - CompletionMessage = - 1077619; // Scribing is a very fulfilling pursuit. I am pleased to see you embark on this journey. You sling a pen well! On behalf of the New Haven Mage Council I wish to present you with this spellbook. When equipped, the Hallowed Spellbook greatly enhances the potency of your offensive spells when used against Undead. Be mindful, though. While this book is equipped, when you invoke your powerful spells and abilities vs. Humanoids such as other humans, orcs, ettins, trolls, and the like, your offensive spells will diminish in effectiveness. I suggest unequipping the Hallowed Spellbook when battling Humanoids. I hope this spellbook serves you well. - CompletionNotice = - 1077618; // You have achieved the rank of Apprentice Scribe. Return to Jillian in New Haven to receive your arcane prize. - - Objectives.Add(new GainSkillObjective(SkillName.Inscribe, 500, true, true)); - - Rewards.Add(new ItemReward(1077620, typeof(HallowedSpellbook))); // Hallowed Spellbook - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Jillian"), new Point3D(3465, 2490, 71), Map.Trammel); - } - } - - public class TheMagesApprentice : MLQuest - { - public TheMagesApprentice() - { - Activated = true; - OneTimeOnly = true; - Title = 1077576; // The Mage's Apprentice - Description = - 1077577; // Head East out of town and go to Old Haven. Cast fireballs and lightning bolts against monsters there until you have raised your Magery skill to 50. Greetings. You seek to unlock the secrets of the arcane art of Magery. The New Haven Mage Council has an assignment for you. Undead have plagued the town of Old Haven. We need your assistance in cleansing the town of this evil influence. Old Haven is located east of here. I suggest using your offensive Magery spells such as Fireball and Lightning Bolt against the Undead that inhabit there. Make sure you have plenty of reagents before embarking on your journey. Reagents are required to cast Magery spells. You can purchase extra reagents at the nearby Reagent shop, or you can find reagents growing in the nearby wooded areas. You can see which reagents are required for each spell by looking in your spellbook. Come back to me once you feel that you are worthy of the rank of Apprentice Mage and I will reward you with an arcane prize. - RefusalMessage = - 1077578; // Very well, come back to me when you are ready to practice Magery. You have so much arcane potential. 'Tis a shame to see it go to waste. The New Haven Mage Council could really use your help. - InProgressMessage = - 1077579; // You have not achieved the rank of Apprentice Mage. Come back to me once you feel that you are worthy of the rank of Apprentice Mage and I will reward you with an arcane prize. - CompletionMessage = - 1077581; // Well done! On behalf of the New Haven Mage Council I wish to present you with this staff. Normally a mage must unequip weapons before spell casting. While wielding your new Ember Staff, however, you will be able to invoke your Magery spells. Even if you do not currently possess skill in Mace Fighting, the Ember Staff will allow you to fight as if you do. However, your Magery skill will be temporarily reduced while doing so. Finally, the Ember Staff occasionally smites a foe with a Fireball while wielding it in melee combat. I hope the Ember Staff serves you well. - CompletionNotice = - 1077580; // You have achieved the rank of Apprentice Mage. Return to Kaelynna in New Haven to receive your arcane prize. - - Objectives.Add(new GainSkillObjective(SkillName.Magery, 500, true, true)); - - Rewards.Add(new ItemReward(1077582, typeof(EmberStaff))); // Ember Staff - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Kaelynna"), new Point3D(3486, 2491, 52), Map.Trammel); - } - } - - public class ScholarlyTask : MLQuest - { - public ScholarlyTask() - { - Activated = true; - OneTimeOnly = true; - Title = 1077603; // A Scholarly Task - Description = - 1077604; // Head East out of town and go to Old Haven. Use Evaluating Intelligence on all creatures you see there. You can also cast Magery spells as well to raise Evaluating Intelligence. Do these activities until you have raised your Evaluating Intelligence skill to 50.
------

Hello. Truly knowing your opponent is essential for landing your offensive spells with precision. I can teach you how to enhance the effectiveness of your offensive spells, but first you must learn how to size up your opponents intellectually. I have a scholarly task for you. Head East out of town and go to Old Haven. Use Evaluating Intelligence on all creatures you see there. You can also cast Magery spells as well to raise Evaluating Intelligence.

Come back to me once you feel that you are worthy of the rank of Apprentice Scholar and I will reward you with an arcane prize. - RefusalMessage = 1077605; // Return to me if you reconsider and wish to become an Apprentice Scholar. - InProgressMessage = - 1077629; // You have not achieved the rank of Apprentice Scholar. Come back to me once you feel that you are worthy of the rank of Apprentice Scholar and I will reward you with an arcane prize. - CompletionMessage = - 1077607; // You have completed the task. Well done. On behalf of the New Haven Mage Council I wish to present you with this ring. When worn, the Ring of the Savant enhances your intellectual aptitude and increases your mana pool. Your spell casting abilities will take less time to invoke and recovering from such spell casting will be hastened. I hope the Ring of the Savant serves you well. - CompletionNotice = - 1077606; // You have achieved the rank of Apprentice Scholar. Return to Mithneral in New Haven to receive your arcane prize. - - Objectives.Add(new GainSkillObjective(SkillName.EvalInt, 500, true, true)); - - Rewards.Add(new ItemReward(1077608, typeof(RingOfTheSavant))); // Ring of the Savant - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Mithneral"), new Point3D(3485, 2491, 71), Map.Trammel); - } - } - - public class TheRightToolForTheJob : MLQuest - { - public TheRightToolForTheJob() - { - Activated = true; - OneTimeOnly = true; - Title = 1077741; // The Right Tool for the Job - Description = - 1077744; // Create new scissors and hammers while inside Amelia's workshop. Try making scissors up to 45 skill, the switch to making hammers until 50 skill.
-----

Hello! I guess you're here to learn something about Tinkering, eh? You've come to the right place, as Tinkering is what I've dedicated my life to.

You'll need two things to get started: a supply of ingots and the right tools for the job. You can either buy ingots from the market, or go mine them yourself. As for tools, you can try making your own set of Tinker's Tools, or if you'd prefer to buy them, I have some for sale.

Working here in my shop will let me give you pointers as you go, so you'll be able to learn faster than anywhere else. Start off making scissors until you reach 45 tinkering skill, then switch to hammers until you've achieved 50. Once you've done that, come talk to me and I'll give you something for your hard work. - RefusalMessage = - 1077745; // I’m disappointed that you aren’t interested in learning more about Tinkering. It’s really such a useful skill!

*Amelia smiles*

At least you know where to find me if you change your mind, since I rarely spend time outside of this shop. - InProgressMessage = - 1077746; // Nice going! You're not quite at Apprentice Tinkering yet, though, so you better get back to work. Remember that the quickest way to learn is to make scissors up until 45 skill, and then switch to hammers. Also, don't forget that working here in my shop will let me give you tips so you can learn faster. - CompletionMessage = - 1077748; // You've done it! Look at our brand new Apprentice Tinker! You've still got quite a lot to learn if you want to be a Grandmaster Tinker, but I believe you can do it! Just keep in mind that if you're tinkering just to practice and improve your skill, make items that are moderately difficult (60-80% success chance), and try to stick to ones that use less ingots.

Come here, my brand new Apprentice Tinker, I want to give you something special. I created this just for you, so I hope you like it. It's a set of Tinker's Tools that contains a bit of magic. These tools have more charges than any Tinker's Tools a Tinker can make. You can even use them to make a normal set of tools, so that way you won't ever find yourself stuck somewhere with no tools! - CompletionNotice = - 1077747; // You have achieved the rank of Apprentice Tinker. Talk to Amelia Youngstone in New Haven to see what kind of reward she has waiting for you. - - Objectives.Add(new GainSkillObjective(SkillName.Tinkering, 500, true, true)); - - Rewards.Add(new ItemReward(1077749, typeof(AmeliasToolbox))); // Amelia’s Toolbox - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "AmeliaYoungstone"), new Point3D(3459, 2529, 53), Map.Trammel); - } - } - - public class KnowThineEnemy : MLQuest - { - public KnowThineEnemy() - { - Activated = true; - OneTimeOnly = true; - Title = 1077685; // Know Thine Enemy - Description = - 1077688; // Head East out of town to Old Haven. Battle monsters there, or heal yourself and other players, until you have raised your Anatomy skill to 50.
------

Hail and well met. You must be here to improve your knowledge of Anatomy. Well, you've come to the right place because I can teach you what you need to know. At least all you'll need to know for now. Haha!

Knowing about how living things work inside can be a very useful skill. Not only can you learn where to strike an opponent to hurt him the most, but you can use what you learn to heal wounds better as well. Just walking around town, you can even tell if someone is strong or weak or if they happen to be particularly dexterous or not.

If you're interested in learning more, I'd advise you to head out to Old Haven, just to the east, and jump into the fray. You'll learn best by engaging in combat while keeping you and your fellow adventurers healed, or you can even try sizing up your opponents.

While you're gone, I'll dig up something you may find useful. - RefusalMessage = - 1077689; // It's your choice, but I wouldn't head out there without knowing what makes those things tick inside! If you change your mind, you can find me right here dissecting frogs, cats or even the occasional unlucky adventurer. - InProgressMessage = - 1077690; // I'm surprised to see you back so soon. You've still got a ways to go if you want to really understand the science of Anatomy. Head out to Old Haven and practice combat and healing yourself or other adventurers. - CompletionMessage = - 1077692; // By the Virtues, you've done it! Congratulations mate! You still have quite a ways to go if you want to perfect your knowledge of Anatomy, but I know you'll get there someday. Just keep at it.

In the meantime, here's a piece of armor that you might find useful. It's not fancy, but it'll serve you well if you choose to wear it.

Happy adventuring, and remember to keep your cranium separate from your clavicle! - CompletionNotice = - 1077691; // You have achieved the rank of Apprentice Healer (for Anatomy). Return to Andreas Vesalius in New Haven as soon as you can to claim your reward. - - Objectives.Add(new GainSkillObjective(SkillName.Anatomy, 500, true, true)); - - Rewards.Add(new ItemReward(1077693, typeof(TunicOfGuarding))); // Tunic of Guarding - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "AndreasVesalius"), new Point3D(3457, 2550, 35), Map.Trammel); - } - } - - public class BruisesBandagesAndBlood : MLQuest - { - public BruisesBandagesAndBlood() - { - Activated = true; - OneTimeOnly = true; - Title = 1077676; // Bruises, Bandages and Blood - Description = - 1077679; // Head East out of town and go to Old Haven. Heal yourself and other players until you have raised your Healing skill to 50.
------

Ah, welcome to my humble practice. I am Avicenna, New Haven's resident Healer. A lot of adventurers head out into the wild from here, so I keep rather busy when they come back bruised, bleeding, or worse.

I can teach you how to bandage a wound, sure, but it's not a job for the queasy! For some folks, the mere sight of blood is too much for them, but it's something you'll get used to over time. It is one thing to cut open a living thing, but it's quite another to sew it back up and save it from sure death. 'Tis noble work, healing.

Best way for you to practice fixing up wounds is to head east out to Old Haven and either practice binding up your own wounds, or practice on someone else. Surely they'll be grateful for the assistance.

Make sure to take enough bandages with you! You don't want to run out in the middle of a tough fight. - RefusalMessage = - 1077680; // No? Are you sure? Well, when you feel that you're ready to practice your healing, come back to me. I'll be right here, fixing up adventurers and curing the occasional cold! - InProgressMessage = - 1077681; // Hail! 'Tis good to see you again. Unfortunately, you're not quite ready to call yourself an Apprentice Healer quite yet. Head back out to Old Haven, due east from here, and bandage up some wounds. Yours or someone else's, it doesn't much matter. - CompletionMessage = - 1077683; // Hello there, friend. I see you've returned in one piece, and you're an Apprentice Healer to boot! You should be proud of your accomplishment, as not everyone has "the touch" when it comes to healing.

I can't stand to see such good work go unrewarded, so I have something I'd like you to have. It's not much, but it'll help you heal just a little faster, and maybe keep you alive.

Good luck out there, friend, and don't forget to help your fellow adventurer whenever possible! - CompletionNotice = - 1077682; // You have achieved the rank of Apprentice Healer. Return to Avicenna in New Haven as soon as you can to claim your reward. - - Objectives.Add(new GainSkillObjective(SkillName.Healing, 500, true, true)); - - Rewards.Add(new ItemReward(1077684, typeof(HealersTouch))); // Healer's Touch - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Avicenna"), new Point3D(3464, 2558, 35), Map.Trammel); - } - } - - public class TheInnerWarrior : MLQuest - { - public TheInnerWarrior() - { - Activated = true; - OneTimeOnly = true; - Title = 1077696; // The Inner Warrior - Description = - 1077699; // Head East out of town to Old Haven. Expend stamina and mana until you have raised your Focus skill to 50.
------

Well, hello there. Don't you look like quite the adventurer!

You want to learn more about Focus, do you? I can teach you something about that, but first you should know that not everyone can be disciplined enough to excel at it. Focus is the ability to achieve inner balance in both body and spirit, so that you recover from physical and mental exertion faster than you otherwise would.

If you want to practice Focus, the best place to do that is east of here, in Old Haven, where you'll find an undead infestation. Exert yourself physically by engaging in combat and moving quickly. For testing your mental balance, expend mana in whatever way you find most suitable to your abilities. Casting spells and using abilities work well for consuming your mana.

Go. Train hard, and you will find that your concentration will improve naturally. When you've improved your ability to focus yourself at an Apprentice level, come back to me and I shall give you something worthy of your new ability. - RefusalMessage = - 1077700; // I'm disappointed. You have a lot of inner potential, and it would pain me greatly to see you waste that. Oh well. If you change your mind, I'll be right here. - InProgressMessage = - 1077701; // Hello again. I see you've returned, but it seems that your Focus skill hasn't improved as much as it could have. Just head east, to Old Haven, and exert yourself physically and mentally as much as possible. To do this physically, engage in combat and move as quickly as you can. For exerting yourself mentally, expend mana in whatever way you find most suitable to your abilities. Casting spells and using abilities work well for consuming your mana.

Return to me when you have gained enough Focus skill to be considered an Apprentice Stoic. - CompletionMessage = - 1077703; // Look who it is! I knew you could do it if you just had the discipline to apply yourself. It feels good to recover from battle so quickly, doesn't it? Just wait until you become a Grandmaster, it's amazing!

Please take this gift, as you've more than earned it with your hard work. It will help you recover even faster during battle, and provides a bit of protection as well.

You have so much more potential, so don't stop trying to improve your Focus now! Safe travels! - CompletionNotice = - 1077702; // You have achieved the rank of Apprentice Stoic (for Focus). Return to Sarsmea Smythe in New Haven to see what kind of reward she has waiting for you. - - Objectives.Add(new GainSkillObjective(SkillName.Focus, 500, true, true)); - - Rewards.Add(new ItemReward(1077695, typeof(ClaspOfConcentration))); // Clasp of Concentration - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "SarsmeaSmythe"), new Point3D(3492, 2577, 15), Map.Trammel); - } - } - - public class TheArtOfStealth : MLQuest - { - public TheArtOfStealth() - { - Activated = true; - OneTimeOnly = true; - Title = 1078154; // The Art of Stealth - Description = - 1078158; // Head East out of town and go to Old Haven. While wielding your fencing weapon, battle monsters with focus attack and summon mirror images up to 40 Ninjitsu skill, and continue practicing focus attack on monsters until 50 Ninjitsu skill.
------

Welcome, young one. You seek to learn Ninjitsu. With it, and the book of Ninjitsu, a Ninja can evoke a number of special abilities including transforming into a variety of creatures that give unique bonuses, using stealth to attack unsuspecting opponents or just plain disappear into thin air! If you do not have a book of Ninjitsu, you can purchase one from me.

I have an assignment for you. Head East out of town and go to Old Haven. While wielding your fencing weapon, battle monsters with focus attack and summon mirror images up to Novice rank, and continue focusing your attacks for greater damage on monsters until you become an Apprentice Ninja. Each image will absorb one attack. The art of deception is a strong defense. Use it wisely.

Come back to me once you have achieved the rank of Apprentice Ninja, and I shall reward you with something useful. - RefusalMessage = 1078159; // Come back to me if you with to learn Ninjitsu in the future. - InProgressMessage = - 1078160; // You have not achieved the rank of Apprentice Ninja. Come back to me once you have done so. - CompletionMessage = - 1078162; // You have done well, young one. Please accept this kryss as a gift. It is called the "Silver Serpent Blade". With it, you will strike with precision and power. This should aid you in your journey as a Ninja. Farewell. - CompletionNotice = - 1078161; // You have achieved the rank of Apprentice Ninja. Return to Ryuichi in New Haven to see what kind of reward he has waiting for you. - - Objectives.Add(new GainSkillObjective(SkillName.Ninjitsu, 500, true, true)); - - Rewards.Add(new ItemReward(1078163, typeof(SilverSerpentBlade))); // Silver Serpent Blade - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Ryuichi"), new Point3D(3422, 2520, 21), Map.Trammel); - } - } - - public class BecomingOneWithTheShadows : MLQuest - { - public BecomingOneWithTheShadows() - { - Activated = true; - OneTimeOnly = true; - Title = 1078164; // Becoming One with the Shadows - Description = - 1078168; // Practice hiding in the Ninja Dojo until you reach 50 Hiding skill.
------

Come closer. Don't be afraid. The shadows will not harm you. To be a successful Ninja, you must learn to become one with the shadows. The Ninja Dojo is the ideal place to learn the art of concealment. Practice hiding here.

Talk to me once you have achieved the rank of Apprentice Rogue (for Hiding), and I shall reward you. - RefusalMessage = 1078169; // If you wish to become one with the shadows, come back and talk to me. - InProgressMessage = - 1078170; // You have not achieved the rank of Apprentice Rogue (for Hiding). Talk to me when you feel you have accomplished this. - CompletionMessage = - 1078172; // Not bad at all. You have learned to control your fear of the dark and you are becoming one with the shadows. If you haven't already talked to Jun, I advise you do so. Jun can teach you how to stealth undetected. Hiding and Stealth are essential skills to master when becoming a Ninja.

As promised, I have a reward for you. Here are some smokebombs. As long as you are an Apprentice Ninja and have mana available you will be able to use them. They will allow you to hide while in the middle of combat. I hope these serve you well. - CompletionNotice = - 1078171; // You have achieved the rank of Apprentice Rogue (for Hiding). Return to Chiyo in New Haven to claim your reward. - - Objectives.Add(new GainSkillObjective(SkillName.Hiding, 500, true, true)); - - Rewards.Add(new ItemReward(1078173, typeof(BagOfSmokeBombs))); // Bag of Smoke Bombs - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Chiyo"), new Point3D(3420, 2516, 21), Map.Trammel); - } - } - - public class WalkingSilently : MLQuest - { - public WalkingSilently() - { - Activated = true; - OneTimeOnly = true; - Title = 1078174; // Walking Silently - Description = - 1078178; // Head East out of town and go to Old Haven. While wearing normal clothes, practice Stealth there until you reach 50 Stealth skill.
------

You there. You're not very quiet in your movements. I can help you with that. Not only must you must learn to become one with the shadows, but also you must learn to quiet your movements. Old Haven is the ideal place to learn how to Stealth.

Head East out of town and go to Old Haven. While wearing normal clothes, practice Stealth there. Stealth becomes more difficult as you wear heavier pieces of armor, so for now, only wear clothes while practicing Stealth.

You can only Stealth once you are hidden. If you become visible, use your Hiding skill, and begin slowing walking.

Come back to me once you have achieved the rank of Apprentice Rogue (for Stealth), and I will reward you with something useful. - RefusalMessage = 1078179; // If you want to learn to quiet your movements, talk to me, and I will help you. - InProgressMessage = - 1078180; // You have not achieved the rank of Apprentice Rogue (for Stealth). Come back to me when you feel you have accomplished this. - CompletionMessage = - 1078182; // Good. You have learned to quiet your movements. If you haven't already talked to Chiyo, I advise you do so. Chiyo can teach you how to become one with the shadows. Hiding and Stealth are essential skills to master when becoming a Ninja.

Here is your reward. This leather Ninja jacket is called "Twilight Jacket". It will offer greater protection to you. I hope this serve you well. - CompletionNotice = - 1078181; // You have achieved the rank of Apprentice Rogue (for Stealth). Return to Jun in New Haven to claim your reward. - - Objectives.Add(new GainSkillObjective(SkillName.Stealth, 500, true, true)); - - Rewards.Add(new ItemReward(1078183, typeof(TwilightJacket))); // Twilight Jacket - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Jun"), new Point3D(3422, 2516, 21), Map.Trammel); - } - } - - public class EyesOfARanger : MLQuest - { - public EyesOfARanger() - { - Activated = true; - OneTimeOnly = true; - Title = 1078211; // Eyes of a Ranger - Description = - 1078217; // Track animals, monsters, and people on Haven Island until you have raised your Tracking skill to 50.
------

Hello friend. I am Walker, Grandmaster Ranger. An adventurer needs to keep alive in the wilderness. Being able to track those around you is essential to surviving in dangerous places. Certain Ninja abilities are more potent when the Ninja possesses Tracking knowledge. If you want to be a Ninja, or if you simply want to get a leg up on the creatures that habit these parts, I advise you learn how to track them.

You can track any animals, monsters, or people on Haven Island. Clear your mind, focus, and note any tracks in the ground or sounds in the air that can help you find your mark. You can do it, friend. I have faith in you.

Come back to me once you have achieved the rank of Apprentice Ranger (for Tracking), and I will give you something that may help you in your travels. Take care, friend. - RefusalMessage = - 1078218; // Farewell, friend. Be careful out here. If you change your mind and want to learn Tracking, come back and talk to me. - InProgressMessage = - 1078219; // So far so good, kid. You are still alive, and you are getting the hang of Tracking. There are many more animals, monsters, and people to track. Come back to me once you have tracked them. - CompletionMessage = - 1078221; // I knew you could do it! You have become a fine Ranger. Just keep practicing, and one day you will become a Grandmaster Ranger. Just like me.

I have a little something for you that will hopefully aid you in your journeys. These leggings offer some resistances that will hopefully protect you from harm. I hope these serve you well. Farewell, friend. - CompletionNotice = - 1078220; // You have achieved the rank of Apprentice Ranger (for Tracking). Return to Walker in New Haven to claim your reward. - - Objectives.Add(new GainSkillObjective(SkillName.Tracking, 500, true, true)); - - Rewards.Add(new ItemReward(1078222, typeof(WalkersLeggings))); // Walker's Leggings - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Walker"), new Point3D(3429, 2518, 19), Map.Trammel); - } - } - - public class TheWayOfTheSamurai : MLQuest - { - public TheWayOfTheSamurai() - { - Activated = true; - OneTimeOnly = true; - Title = 1078007; // The Way of the Samurai - Description = - 1078010; // Head East out of town and go to Old Haven. use the Confidence defensive stance and attempt to honorably execute monsters there until you have raised your Bushido skill to 50.
------

Greetings. I see you wish to learn the Way of the Samurai. Wielding a blade is easy. Anyone can grasp a sword's hilt. Learning how to fight properly and skillfully is to become an Armsman. Learning how to master weapons, and even more importantly when not to use them, is the Way of the Warrior. The Way of the Samurai. The Code of the Bushido. That is why you are here.

Adventure East to Old Haven. Use the Confidence defensive stance and attempt to honorably execute the undead that inhabit there. You will need a book of Bushido to perform these abilities. If you do not possess a book of Bushido, you can purchase one from me.

If you fail to honorably execute the undead, your defenses will be greatly weakened: Resistances will suffer and Resisting Spells will suffer. A successful parry instantly ends the weakness. If you succeed, however, you will be infused with strength and healing. Your swing speed will also be boosted for a short duration. With practice, you will learn how to master your Bushido abilities.

Return to me once you feel that you have become an Apprentice Samurai. - RefusalMessage = 1078011; // Good journey to you. Return to me if you wish to live the life of a Samurai. - InProgressMessage = - 1078012; // You are not ready to become an Apprentice Samurai. There are still more undead to lay to rest. Return to me once you have done so. - CompletionMessage = - 1078014; // You have proven yourself young one. You will continue to improve as your skills are honed with age. You are an honorable warrior, worthy of the rank of Apprentice Samurai. Please accept this no-dachi as a gift. It is called "The Dragon's Tail". Upon a successful strike in combat, there is a chance this mighty weapon will replenish your stamina equal to the damage of your attack. I hope "The Dragon's Tail" serves you well. You have earned it. Farewell for now. - CompletionNotice = - 1078013; // You have achieved the rank of Apprentice Samurai. Return to Hamato in New Haven to report your progress. - - Objectives.Add(new GainSkillObjective(SkillName.Bushido, 500, true, true)); - - Rewards.Add(new ItemReward(1078015, typeof(TheDragonsTail))); // The Dragon's Tail - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Hamato"), new Point3D(3493, 2414, 55), Map.Trammel); - } - } - - public class TheAllureOfDarkMagic : MLQuest - { - public TheAllureOfDarkMagic() - { - Activated = true; - OneTimeOnly = true; - Title = 1078036; // The Allure of Dark Magic - Description = - 1078039; // Head East out of town and go to Old Haven. Cast Evil Omen and Pain Spike against monsters there until you have raised your Necromancy skill to 50.
------

Welcome! I see you are allured by the dark magic of Necromancy. First, you must prove yourself worthy of such knowledge. Undead currently occupy the town of Old Haven. Practice your harmful Necromancy spells on them such as Evil Omen and Pain Spike.

Make sure you have plenty of reagents before embarking on your journey. Reagents are required to cast Necromancy spells. You can purchase extra reagents from me, or you can find reagents growing in the nearby wooded areas. You can see which reagents are required for each spell by looking in your spellbook.

Come back to me once you feel that you are worthy of the rank of Apprentice Necromancer and I will reward you with the knowledge you desire. - RefusalMessage = 1078040; // You are weak after all. Come back to me when you are ready to practice Necromancy. - InProgressMessage = - 1078041; // You have not achieved the rank of Apprentice Necromancer. Come back to me once you feel that you are worthy of the rank of Apprentice Necromancer and I will reward you with the knowledge you desire. - CompletionMessage = - 1078043; // You have done well, my young apprentice. Behold! I now present to you the knowledge you desire. This spellbook contains all the Necromancer spells. The power is intoxicating, isn't it? - CompletionNotice = - 1078042; // You have achieved the rank of Apprentice Necromancer. Return to Mulcivikh in New Haven to receive the knowledge you desire. - - Objectives.Add(new GainSkillObjective(SkillName.Necromancy, 500, true, true)); - - Rewards.Add(new InternalReward()); - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Mulcivikh"), new Point3D(3548, 2456, 15), Map.Trammel); - } - - private class InternalReward : ItemReward - { - public InternalReward() - : base(1078052, typeof(NecromancerSpellbook)) // Complete Necromancer Spellbook - { - } - - public override Item CreateItem() - { - Item item = base.CreateItem(); - - if (item is Spellbook book) - book.Content = (1ul << book.BookCount) - 1; - - return item; - } - } - } - - public class ChannelingTheSupernatural : MLQuest - { - public ChannelingTheSupernatural() - { - Activated = true; - OneTimeOnly = true; - Title = 1078044; // Channeling the Supernatural - Description = - 1078047; // Head East out of town and go to Old Haven. Use Spirit Speak and channel energy from either yourself or nearby corpses there. You can also cast Necromancy spells as well to raise Spirit Speak. Do these activities until you have raised your Spirit Speak skill to 50.
------

How do you do? Channeling the supernatural through Spirit Speak allows you heal your wounds. Such channeling expends your mana, so be mindful of this. Spirit Speak enhances the potency of your Necromancy spells. The channeling powers of a Medium are quite useful when practicing the dark magic of Necromancy.

It is best to practice Spirit Speak where there are a lot of corpses. Head East out of town and go to Old Haven. Undead currently reside there. Use Spirit Speak and channel energy from either yourself or nearby corpses. You can also cast Necromancy spells as well to raise Spirit Speak.

Come back to me once you feel that you are worthy of the rank of Apprentice Medium and I will reward you with something useful. - RefusalMessage = - 1078048; // Channeling the supernatural isn't for everyone. It is a dark art. See me if you ever wish to pursue the life of a Medium. - InProgressMessage = - 1078049; // Back so soon? You have not achieved the rank of Apprentice Medium. Come back to me once you feel that you are worthy of the rank of Apprentice Medium and I will reward you with something useful. - CompletionMessage = - 1078051; // Well done! Channeling the supernatural is taxing, indeed. As promised, I will reward you with this bag of Necromancer reagents. You will need these if you wish to also pursue the dark magic of Necromancy. Good journey to you. - CompletionNotice = - 1078050; // You have achieved the rank of Apprentice Medium. Return to Morganna in New Haven to receive your reward. - - Objectives.Add(new GainSkillObjective(SkillName.SpiritSpeak, 500, true, true)); - - Rewards.Add(new ItemReward(1078053, typeof(BagOfNecromancerReagents))); // Bag of Necromancer Reagents - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Morganna"), new Point3D(3547, 2463, 15), Map.Trammel); - } - } - - public class TheDeluciansLostMine : MLQuest - { - public TheDeluciansLostMine() - { - Activated = true; - OneTimeOnly = true; - Title = 1077750; // The Delucian’s Lost Mine - Description = - 1077753; // Find Jacob's Lost Mine and mine iron ore there, using a pickaxe or shovel. Bring it back to Jacob's forge and smelt the ore into ingots, until you have raised your Mining skill to 50. You may find a packhorse useful for hauling the ore around. The animal trainer in New Haven has packhorses for sale.
-----

Howdy! Welcome to my camp. It's not much, I know, but it's all I'll be needin' up here. I don't need them fancy things those townspeople have down there in New Haven. Nope, not one bit. Just me, Bessie, my pick and a thick vein 'o valorite.

Anyhows, I'm guessin' that you're up here to ask me about minin', aren't ya? Well, don't be expectin' me to tell you where the valorite's at, cause I ain't gonna tell the King of Britannia, much less the likes of you. But I will show ya how to mine and smelt iron, cause there certainly is a 'nough of up in these hills.

*Jacob looks around, with a perplexed look on his face*

Problem is, I can't remember where my iron mine's at, so you'll have to find it yourself. Once you're there, have at it with a pickaxe or shovel, then haul it back to camp and I'll show ya how to smelt it. Ya look a bit wimpy, so you might wanna go buy yourself a packhorse in town from the animal trainer to help you haul around all that ore.

When you're an Apprentice Miner, talk to me and I'll give ya a little somethin' I've got layin' around here... somewhere. - RefusalMessage = - 1077754; // Couldn’t find my iron mine, could ya? Well, neither can I!

*Jacob laughs*

Oh, ya don’t wanna find it? Well, allrighty then, ya might as well head on back down to town then and stop cluttering up my camp. Come back and talk to me if you’re interested in learnin’ ‘bout minin’. - InProgressMessage = - 1077755; // Where ya been off a gallivantin’ all day, pilgrim? You ain’t seen no hard work yet! Get yer arse back out there to my mine and dig up some more iron. Don’t forget to take a pickaxe or shovel, and if you’re so inclined, a packhorse too. - CompletionMessage = - 1077757; // Dang gun it! If that don't beat all! Ya went and did it, didn’t ya? What we got ourselves here is a mighty fine brand spankin’ new Apprentice Miner!

I can see ya put some meat on them bones too while you were at it!

Here’s that little somethin’ I told ya I had for ya. It’s a pickaxe with some high falutin’ magic inside that’ll help you find the good stuff when you’re off minin’. It wears out fast, though, so you can only use it a few times a day.

Welp, I’ve got some smeltin’ to do, so off with ya. Good luck, pilgrim! - CompletionNotice = - 1077756; // You have achieved the rank of Apprentice Miner. Return to Jacob Waltz in at his camp in the hills above New Haven as soon as you can to claim your reward. - - Objectives.Add(new GainSkillObjective(SkillName.Mining, 500, true, true)); - - Rewards.Add(new ItemReward(1077758, typeof(JacobsPickaxe))); // Jacob's Pickaxe - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "JacobWaltz"), new Point3D(3504, 2741, 0), Map.Trammel); - } - } - - public class ItsHammerTime : MLQuest - { - public ItsHammerTime() - { - Activated = true; - OneTimeOnly = true; - Title = 1077732; // It’s Hammer Time! - Description = - 1077735; // Create new daggers and maces using the forge and anvil in George's shop. Try making daggers up to 45 skill, the switch to making maces until 50 skill.
-----

Hail, and welcome to my humble shop. I'm George Hephaestus, New Haven's blacksmith. I assume that you're here to ask me to train you to be an Apprentice Blacksmith. I certainly can do that, but you're going to have to supply your own ingots.

You can always buy them at the market, but I highly suggest that you mine your own. That way, any items you sell will be pure profit!

So, once you have a supply of ingots, use my forge and anvil here to create items. You'll also need a supply of the proper tools; you can use a smith's hammer, a sledgehammer or tongs. You can either make them yourself if you have the tinkering skill, or buy them from a tinker at the market.

Since I'll be around to give you advice, you'll learn faster here than anywhere else. Start off making daggers until you reach 45 blacksmithing skill, then switch to maces until you've achieved 50. Once you've done that, come talk to me and I'll give you something for your hard work. - RefusalMessage = - 1077736; // You're not interested in learning to be a smith, eh? I thought for sure that's why you were here. Oh well, if you change your mind, you can always come back and talk to me. - InProgressMessage = - 1077737; // You’re doing well, but you’re not quite there yet. Remember that the quickest way to learn is to make daggers up until 45 skill, and then switch to maces. Also, don’t forget that using my forge and anvil will help you learn faster. - CompletionMessage = - 1077739; // I've been watching you get better and better as you've been smithing, and I have to say, you're a natural! It's a long road to being a Grandmaster Blacksmith, but I have no doubt that if you put your mind to it you'll get there someday. Let me give you one final piece of advice. If you're smithing just to practice and improve your skill, make items that are moderately difficult (60-80% success chance), and try to stick to ones that use less ingots.

Now that you're an Apprentice Blacksmith, I have something for you. While you were busy practicing, I was crafting this hammer for you. It's finely balanced, and has a bit of magic imbued within that will help you craft better items. However, that magic needs to restore itself over time, so you can only use it so many times per day. I hope you find it useful! - CompletionNotice = - 1077738; // You have achieved the rank of Apprentice Blacksmith. Return to George Hephaestus in New Haven to see what kind of reward he has waiting for you. - - Objectives.Add(new GainSkillObjective(SkillName.Blacksmith, 500, true, true)); - - Rewards.Add(new ItemReward(1077740, typeof(HammerOfHephaestus))); // Hammer of Hephaestus - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "GeorgeHephaestus"), new Point3D(3471, 2542, 36), Map.Trammel); - } - } - - public class Aelorn : KeeperOfChivalry - { - [Constructible] - public Aelorn() - { - Title = "the Chivalry Instructor"; - BodyValue = 0x190; - Hue = 0x83EA; - HairItemID = 0x203C; - HairHue = 0x47D; - FacialHairItemID = 0x204D; - FacialHairHue = 0x47D; - - InitStats(100, 100, 25); - - SetSkill(SkillName.Anatomy, 120.0); - SetSkill(SkillName.MagicResist, 120.0); - SetSkill(SkillName.Tactics, 120.0); - SetSkill(SkillName.Swords, 120.0); - SetSkill(SkillName.Meditation, 120.0); - SetSkill(SkillName.Focus, 120.0); - SetSkill(SkillName.Chivalry, 120.0); - } - - public Aelorn(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "Aelorn"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078133); // Hail, friend. Want to live the life of a paladin? - } - - public override void InitOutfit() - { - AddItem(new Backpack()); - AddItem(new VikingSword()); - AddItem(new PlateChest()); - AddItem(new PlateLegs()); - AddItem(new PlateGloves()); - AddItem(new PlateArms()); - AddItem(new PlateGorget()); - AddItem(new OrderShield()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Dimethro : BaseCreature - { - [Constructible] - public Dimethro() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Wrestling Instructor"; - BodyValue = 0x190; - Hue = 0x83EA; - HairItemID = 0x203D; - HairHue = 0x455; - FacialHairItemID = 0x204D; - FacialHairHue = 0x455; - - InitStats(100, 100, 25); - - SetSkill(SkillName.EvalInt, 120.0); - SetSkill(SkillName.Inscribe, 120.0); - SetSkill(SkillName.Magery, 120.0); - SetSkill(SkillName.MagicResist, 120.0); - SetSkill(SkillName.Wrestling, 120.0); - SetSkill(SkillName.Meditation, 120.0); - - AddItem(new Backpack()); - AddItem(new Sandals(0x455)); - AddItem(new BodySash(0x455)); - AddItem(new LongPants(0x455)); - } - - public Dimethro(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Dimethro"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078128); // You there! Wanna master hand to hand defense? Of course you do! - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Churchill : BaseCreature - { - [Constructible] - public Churchill() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Mace Fighting Instructor"; - BodyValue = 0x190; - Hue = 0x83EA; - HairItemID = 0x203C; - HairHue = 0x455; - - InitStats(100, 100, 25); - - SetSkill(SkillName.Anatomy, 120.0); - SetSkill(SkillName.Parry, 120.0); - SetSkill(SkillName.Healing, 120.0); - SetSkill(SkillName.Tactics, 120.0); - SetSkill(SkillName.Macing, 120.0); - SetSkill(SkillName.Focus, 120.0); - - AddItem(new Backpack()); - AddItem(new OrderShield()); - AddItem(new WarMace()); - - Item item; - - item = new PlateLegs(); - item.Hue = 0x966; - AddItem(item); - - item = new PlateGloves(); - item.Hue = 0x966; - AddItem(item); - - item = new PlateGorget(); - item.Hue = 0x966; - AddItem(item); - - item = new PlateChest(); - item.Hue = 0x966; - AddItem(item); - - item = new PlateArms(); - item.Hue = 0x966; - AddItem(item); - } - - public Churchill(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Churchill"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078141); // Don't listen to Jockles. Real warriors wield mace weapons! - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Robyn : Bowyer - { - [Constructible] - public Robyn() - { - Title = "the Archery Instructor"; - BodyValue = 0x191; - Hue = 0x83EA; - HairItemID = 0x203C; - HairHue = 0x47D; - Female = true; - - InitStats(100, 100, 25); - - SetSkill(SkillName.Anatomy, 120.0); - SetSkill(SkillName.Parry, 120.0); - SetSkill(SkillName.Fletching, 120.0); - SetSkill(SkillName.Healing, 120.0); - SetSkill(SkillName.Tactics, 120.0); - SetSkill(SkillName.Archery, 120.0); - SetSkill(SkillName.Focus, 120.0); - } - - public Robyn(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "Robyn"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078202); // Archery requires a steady aim and dexterous fingers. - } - - public override void InitOutfit() - { - AddItem(new Backpack()); - AddItem(new Boots(0x592)); - AddItem(new Cloak(0x592)); - AddItem(new Bandana(0x592)); - AddItem(new CompositeBow()); - - Item item; - - item = new StuddedLegs(); - item.Hue = 0x592; - AddItem(item); - - item = new StuddedGloves(); - item.Hue = 0x592; - AddItem(item); - - item = new StuddedGorget(); - item.Hue = 0x592; - AddItem(item); - - item = new StuddedChest(); - item.Hue = 0x592; - AddItem(item); - - item = new StuddedArms(); - item.Hue = 0x592; - AddItem(item); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Recaro : BaseCreature - { - [Constructible] - public Recaro() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Fencer Instructor"; - BodyValue = 0x190; - Hue = 0x83EA; - HairItemID = 0x203C; - HairHue = 0x455; - FacialHairItemID = 0x204D; - FacialHairHue = 0x455; - - InitStats(100, 100, 25); - - SetSkill(SkillName.Anatomy, 120.0); - SetSkill(SkillName.Parry, 120.0); - SetSkill(SkillName.Healing, 120.0); - SetSkill(SkillName.Tactics, 120.0); - SetSkill(SkillName.Fencing, 120.0); - SetSkill(SkillName.Focus, 120.0); - - AddItem(new Backpack()); - AddItem(new Shoes(0x455)); - AddItem(new WarFork()); - - Item item; - - item = new StuddedLegs(); - item.Hue = 0x455; - AddItem(item); - - item = new StuddedGloves(); - item.Hue = 0x455; - AddItem(item); - - item = new StuddedGorget(); - item.Hue = 0x455; - AddItem(item); - - item = new StuddedChest(); - item.Hue = 0x455; - AddItem(item); - - item = new StuddedArms(); - item.Hue = 0x455; - AddItem(item); - } - - public Recaro(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Recaro"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, - 1078187); // The art of fencing requires a dexterous hand, a quick wit and fleet feet. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class AldenArmstrong : BaseCreature - { - [Constructible] - public AldenArmstrong() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Tactics Instructor"; - BodyValue = 0x190; - Hue = 0x83EA; - HairItemID = 0x203B; - HairHue = 0x44E; - - InitStats(100, 100, 25); - - SetSkill(SkillName.Anatomy, 120.0); - SetSkill(SkillName.Parry, 120.0); - SetSkill(SkillName.Healing, 120.0); - SetSkill(SkillName.Tactics, 120.0); - SetSkill(SkillName.Swords, 120.0); - SetSkill(SkillName.Focus, 120.0); - - AddItem(new Backpack()); - AddItem(new Shoes()); - AddItem(new StuddedLegs()); - AddItem(new StuddedGloves()); - AddItem(new StuddedGorget()); - AddItem(new StuddedChest()); - AddItem(new StuddedArms()); - AddItem(new Katana()); - } - - public AldenArmstrong(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Alden Armstrong"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, - 1078136); // There is an art to slaying your enemies swiftly. It's called tactics, and I can teach it to you. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Jockles : BaseCreature - { - [Constructible] - public Jockles() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Swordsmanship Instructor"; - BodyValue = 0x190; - Hue = 0x83FA; - HairItemID = 0x203C; - HairHue = 0x8A7; - - InitStats(100, 100, 25); - - SetSkill(SkillName.Anatomy, 120.0); - SetSkill(SkillName.Parry, 120.0); - SetSkill(SkillName.Healing, 120.0); - SetSkill(SkillName.Tactics, 120.0); - SetSkill(SkillName.Swords, 120.0); - SetSkill(SkillName.Focus, 120.0); - - AddItem(new Backpack()); - AddItem(new Broadsword()); - AddItem(new PlateChest()); - AddItem(new PlateLegs()); - AddItem(new PlateGloves()); - AddItem(new PlateArms()); - AddItem(new PlateGorget()); - AddItem(new OrderShield()); - } - - public Jockles(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Jockles"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078135); // Talk to me to learn the way of the blade. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class TylAriadne : BaseCreature - { - [Constructible] - public TylAriadne() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Parrying Instructor"; - BodyValue = 0x190; - Hue = 0x8374; - HairItemID = 0; - - InitStats(100, 100, 25); - - SetSkill(SkillName.Anatomy, 120.0); - SetSkill(SkillName.Parry, 120.0); - SetSkill(SkillName.Healing, 120.0); - SetSkill(SkillName.Tactics, 120.0); - SetSkill(SkillName.Swords, 120.0); - SetSkill(SkillName.Meditation, 120.0); - SetSkill(SkillName.Focus, 120.0); - - AddItem(new Backpack()); - AddItem(new ElvenBoots(0x96D)); - - Item item; - - item = new StuddedLegs(); - item.Hue = 0x96D; - AddItem(item); - - item = new StuddedGloves(); - item.Hue = 0x96D; - AddItem(item); - - item = new StuddedGorget(); - item.Hue = 0x96D; - AddItem(item); - - item = new StuddedChest(); - item.Hue = 0x96D; - AddItem(item); - - item = new StuddedArms(); - item.Hue = 0x96D; - AddItem(item); - - item = new DiamondMace(); - item.Hue = 0x96D; - AddItem(item); - } - - public TylAriadne(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Tyl Ariadne"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078140); // Want to learn how to parry blows? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Alefian : BaseCreature - { - [Constructible] - public Alefian() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Resisting Spells Instructor"; - BodyValue = 0x190; - Hue = 0x83EA; - HairItemID = 0x203D; - HairHue = 0x457; - - InitStats(100, 100, 25); - - SetSkill(SkillName.EvalInt, 120.0); - SetSkill(SkillName.Inscribe, 120.0); - SetSkill(SkillName.Magery, 120.0); - SetSkill(SkillName.MagicResist, 120.0); - SetSkill(SkillName.Wrestling, 120.0); - SetSkill(SkillName.Meditation, 120.0); - - AddItem(new Backpack()); - AddItem(new Robe()); - AddItem(new Sandals()); - } - - public Alefian(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Alefian"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078130); // A mage should learn how to resist spells. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Gustar : BaseCreature - { - [Constructible] - public Gustar() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Meditation Instructor"; - BodyValue = 0x190; - Hue = 0x83F5; - HairItemID = 0x203B; - HairHue = 0x455; - - InitStats(100, 100, 25); - - SetSkill(SkillName.EvalInt, 120.0); - SetSkill(SkillName.Inscribe, 120.0); - SetSkill(SkillName.Magery, 120.0); - SetSkill(SkillName.MagicResist, 120.0); - SetSkill(SkillName.Wrestling, 120.0); - SetSkill(SkillName.Meditation, 120.0); - - AddItem(new Backpack()); - AddItem(new GustarShroud()); - AddItem(new Sandals()); - } - - public Gustar(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Gustar"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078126); // Meditation allows a mage to replenish mana quickly. I can teach you. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GustarShroud : BaseOuterTorso - { - [Constructible] - public GustarShroud() : base(0x2684) => Hue = 0x479; - - public GustarShroud(Serial serial) : base(serial) - { - } - - public override string DefaultName => " "; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Jillian : BaseCreature - { - [Constructible] - public Jillian() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Inscription Instructor"; - BodyValue = 0x191; - Female = true; - Hue = 0x83EA; - HairItemID = 0x203D; - HairHue = 0x455; - - InitStats(100, 100, 25); - - SetSkill(SkillName.EvalInt, 120.0); - SetSkill(SkillName.Inscribe, 120.0); - SetSkill(SkillName.Magery, 120.0); - SetSkill(SkillName.MagicResist, 120.0); - SetSkill(SkillName.Wrestling, 120.0); - SetSkill(SkillName.Meditation, 120.0); - - AddItem(new Backpack()); - AddItem(new Robe(0x479)); - AddItem(new Sandals()); - } - - public Jillian(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Jillian"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078129); // I can teach you how to scribe magic scrolls. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Kaelynna : BaseCreature - { - [Constructible] - public Kaelynna() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Magery Instructor"; - BodyValue = 0x191; - Female = true; - Hue = 0x83EA; - HairItemID = 0x203C; - HairHue = 0x47D; - - InitStats(100, 100, 25); - - SetSkill(SkillName.EvalInt, 120.0); - SetSkill(SkillName.Inscribe, 120.0); - SetSkill(SkillName.Magery, 120.0); - SetSkill(SkillName.MagicResist, 120.0); - SetSkill(SkillName.Wrestling, 120.0); - SetSkill(SkillName.Meditation, 120.0); - - AddItem(new Backpack()); - AddItem(new Robe(0x592)); - AddItem(new Sandals()); - } - - public Kaelynna(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Kaelynna"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078125); // Want to unlock the secrets of magery? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Mithneral : BaseCreature - { - [Constructible] - public Mithneral() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Evaluating Intelligence Instructor"; - BodyValue = 0x190; - Hue = 0x83EA; - HairItemID = 0x203C; - HairHue = 0x455; - - InitStats(100, 100, 25); - - SetSkill(SkillName.EvalInt, 120.0); - SetSkill(SkillName.Inscribe, 120.0); - SetSkill(SkillName.Magery, 120.0); - SetSkill(SkillName.MagicResist, 120.0); - SetSkill(SkillName.Wrestling, 120.0); - SetSkill(SkillName.Meditation, 120.0); - - AddItem(new Backpack()); - AddItem(new Sandals()); - - Item item; - - item = new GustarShroud(); - item.Hue = 0x51C; - AddItem(item); - } - - public Mithneral(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Mithneral"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078127); // Want to maximize your spell damage? I have a scholarly task for you! - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class AmeliaYoungstone : Tinker - { - [Constructible] - public AmeliaYoungstone() - { - Title = "the Tinkering Instructor"; - BodyValue = 0x191; - Female = true; - Hue = 0x83EA; - HairItemID = 0x203D; - HairHue = 0x46C; - - InitStats(100, 100, 25); - - SetSkill(SkillName.ArmsLore, 120.0); - SetSkill(SkillName.Blacksmith, 120.0); - SetSkill(SkillName.Magery, 120.0); - SetSkill(SkillName.Tactics, 120.0); - SetSkill(SkillName.Swords, 120.0); - SetSkill(SkillName.Tinkering, 120.0); - SetSkill(SkillName.Mining, 120.0); - } - - public AmeliaYoungstone(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "Amelia Youngstone"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078123); // Tinkering is very useful for a blacksmith. You can make your own tools. - } - - public override void InitOutfit() - { - AddItem(new Backpack()); - AddItem(new Sandals()); - AddItem(new Doublet()); - AddItem(new ShortPants()); - AddItem(new HalfApron(0x8AB)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class AndreasVesalius : BaseCreature - { - [Constructible] - public AndreasVesalius() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Anatomy Instructor"; - BodyValue = 0x190; - Hue = 0x83EC; - HairItemID = 0x203C; - HairHue = 0x477; - FacialHairItemID = 0x203E; - FacialHairHue = 0x477; - - InitStats(100, 100, 25); - - SetSkill(SkillName.Anatomy, 120.0); - SetSkill(SkillName.Parry, 120.0); - SetSkill(SkillName.Healing, 120.0); - SetSkill(SkillName.Tactics, 120.0); - SetSkill(SkillName.Swords, 120.0); - SetSkill(SkillName.Focus, 120.0); - - AddItem(new Backpack()); - AddItem(new Boots()); - AddItem(new BlackStaff()); - AddItem(new LongPants()); - AddItem(new Tunic(0x66D)); - } - - public AndreasVesalius(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Andreas Vesalius"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078138); // Learning of the body will allow you to excel in combat. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Avicenna : BaseCreature - { - [Constructible] - public Avicenna() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Healing Instructor"; - BodyValue = 0x190; - Hue = 0x83EA; - HairItemID = 0x203B; - HairHue = 0x477; - - InitStats(100, 100, 25); - - SetSkill(SkillName.Anatomy, 120.0); - SetSkill(SkillName.Parry, 120.0); - SetSkill(SkillName.Healing, 120.0); - SetSkill(SkillName.Tactics, 120.0); - SetSkill(SkillName.Swords, 120.0); - SetSkill(SkillName.Focus, 120.0); - - AddItem(new Backpack()); - AddItem(new Robe(0x66D)); - AddItem(new Boots()); - AddItem(new GnarledStaff()); - } - - public Avicenna(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Avicenna"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078137); // A warrior needs to learn how to apply bandages to wounds. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SarsmeaSmythe : BaseCreature - { - [Constructible] - public SarsmeaSmythe() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Focus Instructor"; - BodyValue = 0x191; - Female = true; - Hue = 0x83EA; - HairItemID = 0x203C; - HairHue = 0x456; - - InitStats(100, 100, 25); - - SetSkill(SkillName.Anatomy, 120.0); - SetSkill(SkillName.Parry, 120.0); - SetSkill(SkillName.Healing, 120.0); - SetSkill(SkillName.Tactics, 120.0); - SetSkill(SkillName.Swords, 120.0); - SetSkill(SkillName.Focus, 120.0); - - AddItem(new Backpack()); - AddItem(new ThighBoots()); - AddItem(new StuddedGorget()); - AddItem(new LeatherLegs()); - AddItem(new FemaleLeatherChest()); - AddItem(new StuddedGloves()); - AddItem(new LeatherNinjaBelt()); - AddItem(new LightPlateJingasa()); - } - - public SarsmeaSmythe(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Sarsmea Smythe"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078139); // Know yourself, and you will become a true warrior. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Ryuichi : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Ryuichi() - : base("the Ninjitsu Instructor") - { - Hue = 0x8403; - - SetSkill(SkillName.Hiding, 120.0); - SetSkill(SkillName.Tactics, 120.0); - SetSkill(SkillName.Tracking, 120.0); - SetSkill(SkillName.Fencing, 120.0); - SetSkill(SkillName.Stealth, 120.0); - SetSkill(SkillName.Ninjitsu, 120.0); - } - - public Ryuichi(Serial serial) - : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override string DefaultName => "Ryuichi"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078155); // I can teach you Ninjitsu. The Art of Stealth. - } - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBNinja()); - } - - public override bool GetGender() => false; - - public override void InitOutfit() - { - HairItemID = 0x203B; - HairHue = 0x455; - - AddItem(new SamuraiTabi()); - AddItem(new LeatherNinjaPants()); - AddItem(new LeatherNinjaMitts()); - AddItem(new LeatherNinjaHood()); - AddItem(new LeatherNinjaJacket()); - AddItem(new LeatherNinjaBelt()); - - PackGold(100, 200); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Chiyo : BaseCreature - { - [Constructible] - public Chiyo() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Hiding Instructor"; - BodyValue = 0xF7; - - InitStats(100, 100, 25); - - SetSkill(SkillName.Hiding, 120.0); - SetSkill(SkillName.Tactics, 120.0); - SetSkill(SkillName.Tracking, 120.0); - SetSkill(SkillName.Fencing, 120.0); - SetSkill(SkillName.Stealth, 120.0); - SetSkill(SkillName.Ninjitsu, 120.0); - } - - public Chiyo(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Chiyo"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078165); // To be undetected means you cannot be harmed. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Jun : BaseCreature - { - [Constructible] - public Jun() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Stealth Instructor"; - BodyValue = 0x190; - Hue = 0x8403; - HairItemID = 0x203B; - HairHue = 0x455; - - InitStats(100, 100, 25); - - SetSkill(SkillName.Hiding, 120.0); - SetSkill(SkillName.Tactics, 120.0); - SetSkill(SkillName.Tracking, 120.0); - SetSkill(SkillName.Fencing, 120.0); - SetSkill(SkillName.Stealth, 120.0); - SetSkill(SkillName.Ninjitsu, 120.0); - - AddItem(new Backpack()); - AddItem(new SamuraiTabi()); - AddItem(new LeatherNinjaPants()); - AddItem(new LeatherNinjaMitts()); - AddItem(new LeatherNinjaHood()); - AddItem(new LeatherNinjaJacket()); - AddItem(new LeatherNinjaBelt()); - } - - public Jun(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Jun"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078175); // Walk Silently. Remain unseen. I can teach you. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Walker : BaseCreature - { - [Constructible] - public Walker() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Tracking Instructor"; - BodyValue = 0x190; - Hue = 0x83EA; - HairItemID = 0x203B; - HairHue = 0x47D; - FacialHairItemID = 0x204B; - FacialHairHue = 0x47D; - - InitStats(100, 100, 25); - - SetSkill(SkillName.Hiding, 120.0); - SetSkill(SkillName.Tactics, 120.0); - SetSkill(SkillName.Tracking, 120.0); - SetSkill(SkillName.Fencing, 120.0); - SetSkill(SkillName.Wrestling, 120.0); - SetSkill(SkillName.Stealth, 120.0); - SetSkill(SkillName.Ninjitsu, 120.0); - - AddItem(new Backpack()); - AddItem(new Boots(0x455)); - AddItem(new LongPants(0x455)); - AddItem(new FancyShirt(0x47D)); - AddItem(new FloppyHat(0x455)); - } - - public Walker(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Walker"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1078213, // I don't sleep. I wait. - 1078212, // There is no theory of evolution. Just a list of creatures I allow to live. - 1078214)); // I can lead a horse to water and make it drink. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Hamato : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Hamato() - : base("the Bushido Instructor") - { - Hue = 0x8403; - - SetSkill(SkillName.Anatomy, 120.0); - SetSkill(SkillName.Parry, 120.0); - SetSkill(SkillName.Healing, 120.0); - SetSkill(SkillName.Tactics, 120.0); - SetSkill(SkillName.Swords, 120.0); - SetSkill(SkillName.Bushido, 120.0); - } - - public Hamato(Serial serial) - : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override string DefaultName => "Hamato"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078134); // Seek me to learn the way of the samurai. - } - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBSamurai()); - } - - public override bool GetGender() => false; - - public override void InitOutfit() - { - HairItemID = 0x203D; - HairHue = 0x497; - - AddItem(new Backpack()); - AddItem(new NoDachi()); - AddItem(new NinjaTabi()); - AddItem(new PlateSuneate()); - AddItem(new LightPlateJingasa()); - AddItem(new LeatherDo()); - AddItem(new LeatherHiroSode()); - - PackGold(100, 200); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Mulcivikh : Mage - { - [Constructible] - public Mulcivikh() - { - Title = "the Necromancy Instructor"; - BodyValue = 0x190; - Hue = 0x83EA; - HairItemID = 0x203D; - HairHue = 0x457; - - InitStats(100, 100, 25); - - SetSkill(SkillName.Magery, 120.0); - SetSkill(SkillName.MagicResist, 120.0); - SetSkill(SkillName.SpiritSpeak, 120.0); - SetSkill(SkillName.Swords, 120.0); - SetSkill(SkillName.Meditation, 120.0); - SetSkill(SkillName.Necromancy, 120.0); - } - - public Mulcivikh(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "Mulcivikh"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078131); // Allured by dark magic, aren't you? - } - - public override void InitOutfit() - { - AddItem(new Backpack()); - AddItem(new Sandals(0x8FD)); - AddItem(new BoneHelm()); - - Item item; - - item = new LeatherLegs(); - item.Hue = 0x2C3; - AddItem(item); - - item = new LeatherGloves(); - item.Hue = 0x2C3; - AddItem(item); - - item = new LeatherGorget(); - item.Hue = 0x2C3; - AddItem(item); - - item = new LeatherChest(); - item.Hue = 0x2C3; - AddItem(item); - - item = new LeatherArms(); - item.Hue = 0x2C3; - AddItem(item); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Morganna : Mage - { - [Constructible] - public Morganna() - { - Title = "the Spirit Speak Instructor"; - BodyValue = 0x191; - Female = true; - Hue = 0x83EA; - HairItemID = 0x203C; - HairHue = 0x455; - - InitStats(100, 100, 25); - - SetSkill(SkillName.Magery, 120.0); - SetSkill(SkillName.MagicResist, 120.0); - SetSkill(SkillName.SpiritSpeak, 120.0); - SetSkill(SkillName.Swords, 120.0); - SetSkill(SkillName.Meditation, 120.0); - SetSkill(SkillName.Necromancy, 120.0); - } - - public Morganna(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "Morganna"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078132); // Want to learn how to channel the supernatural? - } - - public override void InitOutfit() - { - AddItem(new Backpack()); - AddItem(new Sandals()); - AddItem(new Robe(0x47D)); - AddItem(new SkullCap(0x455)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class JacobWaltz : BaseCreature - { - [Constructible] - public JacobWaltz() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Miner Instructor"; - BodyValue = 0x190; - Hue = 0x83EA; - HairItemID = 0x2048; - HairHue = 0x44E; - FacialHairItemID = 0x204D; - FacialHairHue = 0x44E; - - InitStats(100, 100, 25); - - SetSkill(SkillName.ArmsLore, 120.0); - SetSkill(SkillName.Blacksmith, 120.0); - SetSkill(SkillName.Magery, 120.0); - SetSkill(SkillName.Tactics, 120.0); - SetSkill(SkillName.Tinkering, 120.0); - SetSkill(SkillName.Swords, 120.0); - SetSkill(SkillName.Mining, 120.0); - - AddItem(new Backpack()); - AddItem(new Pickaxe()); - AddItem(new Boots()); - AddItem(new WideBrimHat(0x966)); - AddItem(new ShortPants(0x370)); - AddItem(new Shirt(0x966)); - AddItem(new HalfApron(0x1BB)); - } - - public JacobWaltz(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Jacob Waltz"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078124); // You there! I can use some help mining these rocks! - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GeorgeHephaestus : Blacksmith - { - [Constructible] - public GeorgeHephaestus() - { - Title = "the Blacksmith Instructor"; - BodyValue = 0x190; - Hue = 0x83EA; - HairItemID = 0x203B; - HairHue = 0x47B; - - InitStats(100, 100, 25); - - SetSkill(SkillName.ArmsLore, 120.0); - SetSkill(SkillName.Blacksmith, 120.0); - SetSkill(SkillName.Magery, 120.0); - SetSkill(SkillName.Tactics, 120.0); - SetSkill(SkillName.Tinkering, 120.0); - SetSkill(SkillName.Swords, 120.0); - SetSkill(SkillName.Mining, 120.0); - } - - public GeorgeHephaestus(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "George Hephaestus"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1078122); // Wanna learn how to make powerful weapons and armor? Talk to me. - } - - public override void InitOutfit() - { - AddItem(new Backpack()); - AddItem(new Boots(0x973)); - AddItem(new LongPants()); - AddItem(new Bascinet()); - AddItem(new FullApron(0x8AB)); - - Item item; - - item = new SmithHammer(); - item.Hue = 0x8AB; - AddItem(item); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System.Collections.Generic; +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; +using Server.Engines.Spawners; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Definitions +{ + public class CleansingOldHaven : MLQuest + { + public CleansingOldHaven() + { + Activated = true; + OneTimeOnly = true; + Title = 1077719; // Cleansing Old Haven + Description = + 1077722; // Head East out of town to Old Haven. Consecrate your weapon, cast Divine Fury, and battle monsters there until you have raised your Chivalry skill to 50.
------

Hail, friend. The life of a Paladin is a life of much sacrifice, humility, bravery, and righteousness. If you wish to pursue such a life, I have an assignment for you. Adventure east to Old Haven, consecrate your weapon, and lay to rest the undead that inhabit there.

Each ability a Paladin wishes to invoke will require a certain amount of "tithing points" to use. A Paladin can earn these tithing points by donating gold at a shrine or holy place. You may tithe at this shrine.

Return to me once you feel that you are worthy of the rank of Apprentice Paladin. + RefusalMessage = 1077723; // Farewell to you my friend. Return to me if you wish to live the life of a Paladin. + InProgressMessage = + 1077724; // There are still more undead to lay to rest. You still have more to learn. Return to me once you have done so. + CompletionMessage = + 1077726; // Well done, friend. While I know you understand Chivalry is its own reward, I would like to reward you with something that will protect you in battle. It was passed down to me when I was a lad. Now, I am passing it on you. It is called the Bulwark Leggings. Thank you for your service. + CompletionNotice = + 1077725; // You have achieved the rank of Apprentice Paladin. Return to Aelorn in New Haven to report your progress. + + Objectives.Add(new GainSkillObjective(SkillName.Chivalry, 500, true, true)); + + Rewards.Add(new ItemReward(1077727, typeof(BulwarkLeggings))); // Bulwark Leggings + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Aelorn"), new Point3D(3527, 2516, 45), Map.Trammel); + } + } + + public class TheRudimentsOfSelfDefense : MLQuest + { + public TheRudimentsOfSelfDefense() + { + Activated = true; + OneTimeOnly = true; + Title = 1077609; // The Rudiments of Self Defense + Description = + 1077610; // Head East out of town and go to Old Haven. Battle monster there until you have raised your Wrestling skill to 50.Listen up! If you want to learn the rudiments of self-defense, you need toughening up, and there's no better way to toughen up than engaging in combat. Head East out of town to Old Haven and battle the undead there in hand to hand combat. Afraid of dying, you say? Well, you should be! Being an adventurer isn't a bed of posies, or roses, or however that saying goes. If you take a dirt nap, go to one of the nearby wandering healers and they'll get you back on your feet.Come back to me once you feel that you are worthy of the rank Apprentice Wrestler and i will reward you wit a prize. + RefusalMessage = + 1077611; // Ok, featherweight. come back to me if you want to learn the rudiments of self-defense. + InProgressMessage = + 1077630; // You have not achived the rank of Apprentice Wrestler. Come back to me once you feel that you are worthy of the rank Apprentice Wrestler and i will reward you with something useful. + CompletionMessage = + 1077613; // It's about time! Looks like you managed to make it through your self-defense training. As i promised, here's a little something for you. When worn, these Gloves of Safeguarding will increase your awareness and resistances to most elements except poison. Oh yeah, they also increase your natural health regeneration aswell. Pretty handy gloves, indeed. Oh, if you are wondering if your meditation will be hinered while wearing these gloves, it won't be. Mages can wear cloth and leather items without needing to worry about that. Now get out of here and make something of yourself. + CompletionNotice = + 1077612; // You have achieved the rank of Apprentice Wrestler. Return to Dimethro in New Haven to receive your prize. + + Objectives.Add(new GainSkillObjective(SkillName.Wrestling, 500, true, true)); + + Rewards.Add(new ItemReward(1077614, typeof(GlovesOfSafeguarding))); // Gloves Of Safeguarding + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Dimethro"), new Point3D(3528, 2520, 25), Map.Trammel); + } + } + + public class CrushingBonesAndTakingNames : MLQuest + { + public CrushingBonesAndTakingNames() + { + Activated = true; + OneTimeOnly = true; + Title = 1078070; // Crushing Bones and Taking Names + Description = + 1078065; // Head East out of town and go to Old Haven. While wielding your mace,battle monster there until you have raised your Mace Fighting skill to 50. I see you want to learn a real weapon skill and not that toothpick training Jockles hasto offer. Real warriors are called Armsmen, and they wield mace weapons. No doubt about it. Nothing is more satisfying than knocking the wind out of your enemies, smashing there armor, crushing their bones, and taking there names. Want to learn how to wield a mace? Well i have an assignment for you. Head East out of town and go to Old Haven. Undead have plagued the town, so there are plenty of bones for you to smash there. Come back to me after you have ahcived the rank of Apprentice Armsman, and i will reward you with a real weapon. + RefusalMessage = + 1078068; // I thought you wanted to be an Armsman and really make something of yourself. You have potential, kid, but if you want to play with toothpicks, run to Jockles and he will teach you how to clean your teeth with a sword. If you change your mind, come back to me, and i will show you how to wield a real weapon. + InProgressMessage = + 1078067; // Listen kid. There are a lot of undead in Old Haven, and you haven't smashed enough of them yet. So get back there and do some more cleansing. + CompletionMessage = + 1078069; // Now that's what I'm talking about! Well done! Don't you like crushing bones and taking names? As i promised, here is a war mace for you. It hits hard. It swings fast. It hits often. What more do you need? Now get out of here and crush some more enemies! + CompletionNotice = + 1078068; // You have achieved the rank of Apprentice Armsman. Return to Churchill in New Haven to claim your reward. + + Objectives.Add(new GainSkillObjective(SkillName.Macing, 500, true, true)); + + Rewards.Add(new ItemReward(1078062, typeof(ChurchillsWarMace))); // Churchill's War Mace + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Churchill"), new Point3D(3531, 2531, 20), Map.Trammel); + } + } + + public class SwiftAsAnArrow : MLQuest + { + public SwiftAsAnArrow() + { + Activated = true; + OneTimeOnly = true; + Title = 1078201; // Swift as an Arrow + Description = + 1078205; // Head East out of town and go to Old Haven. While wielding your bow or crossbow, battle monster there until you have raised your Archery skill to 50. Well met, friend. Imagine yourself in a distant grove of trees, You raise your bow, take slow, careful aim, and with the twitch of a finger, you impale your prey with a deadly arrow. You look like you would make a excellent archer, but you will need practice. There is no better way to practice Archery than when you life is on the line. I have a challenge for you. Head East out of town and go to Old Haven. While wielding your bow or crossbow, battle the undead that reside there. Make sure you bring a healthy supply of arrows (or bolts if you prefer a crossbow). If you wish to purchase a bow, crossbow, arrows, or bolts, you can purchase them from me or the Archery shop in town. You can also make your own arrows with the Bowcraft/Fletching skill. You will need fletcher's tools, wood to turn into sharft's, and feathers to make arrows or bolts. Come back to me after you have achived the rank of Apprentice Archer, and i will reward you with a fine Archery weapon. + RefusalMessage = + 1078206; // I understand that Archery may not be for you. Feel free to visit me in the future if you change your mind. + InProgressMessage = 1078207; // You're doing great as an Archer! however, you need more practice. + CompletionMessage = + 1078209; // Congratulation! I want to reward you for your accomplishment. Take this composite bow. It is called " Heartseeker". With it, you will shoot with swiftness, precision, and power. I hope "Heartseeker" serves you well. + CompletionNotice = + 1078208; // You have achieved the rank of Apprentice Archer. Return to Robyn in New Haven to claim your reward. + + Objectives.Add(new GainSkillObjective(SkillName.Archery, 500, true, true)); + + Rewards.Add(new ItemReward(1078210, typeof(Heartseeker))); // Heartseeker + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Robyn"), new Point3D(3535, 2531, 20), Map.Trammel); + } + } + + public class EnGuarde : MLQuest + { + public EnGuarde() + { + Activated = true; + OneTimeOnly = true; + Title = 1078186; // En Guarde! + Description = + 1078190; // Head East out of town to Old Haven. Battle monsters there until you have raised your Fencing skill to 50.
------

Well hello there, lad. Fighting with elegance and precision is far more enriching than slugging an enemy with a club or butchering an enemy with a sword. Learn the art of Fencing if you want to master combat and look good doing it!

The key to being a successful fencer is to be the complement and not the opposition to your opponent's strength. Watch for your opponent to become off balance. Then finish him off with finesse and flair.

There are some undead that need cleansing out in Old Haven towards the East. Head over there and slay them, but remember, do it with style!

Come back to me once you have achieved the rank of Apprentice Fencer, and I will reward you with a prize. + RefusalMessage = + 1078191; // I understand, lad. Being a hero isn't for everyone. Run along, then. Come back to me if you change your mind. + InProgressMessage = + 1078192; // You're doing well so far, but you're not quite ready yet. Head back to Old Haven, to the East, and kill some more undead. + CompletionMessage = + 1078194; // Excellent! You are beginning to appreciate the art of Fencing. I told you fighting with elegance and precision is more enriching than fighting like an ogre.

Since you have returned victorious, please take this war fork and use it well. The war fork is a finesse weapon, and this one is magical! I call it "Recaro's Riposte". With it, you will be able to parry and counterstrike with ease! Your enemies will bask in your greatness and glory! Good luck to you, lad, and keep practicing! + CompletionNotice = + 1078193; // You have achieved the rank of Apprentice Fencer. Return to Recaro in New Haven to claim your reward. + + Objectives.Add(new GainSkillObjective(SkillName.Fencing, 500, true, true)); + + Rewards.Add(new ItemReward(1078195, typeof(RecarosRiposte))); // Recaro's Riposte + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Recaro"), new Point3D(3536, 2534, 20), Map.Trammel); + } + } + + public class TheArtOfWar : MLQuest + { + public TheArtOfWar() + { + Activated = true; + OneTimeOnly = true; + Title = 1077667; // The Art of War + Description = + 1077670; // Head East out of town to Old Haven. Battle monsters there until you have raised your Tactics skill to 50.
------

Knowing how to hold a weapon is only half of the battle. The other half is knowing how to use it against an opponent. It's one thing to kill a few bunnies now and then for fun, but a true warrior knows that the right moves to use against a lich will pretty much get your arse fried by a dragon.

I'll help teach you how to fight so that when you do come up against that dragon, maybe you won't have to walk out of there "OooOOooOOOooOO'ing" and looking for a healer.

There are some undead that need cleaning out in Old Haven towards the east. Why don't you head on over there and practice killing things?

When you feel like you've got the basics down, come back to me and I'll see if I can scrounge up an item to help you in your adventures later on. + RefusalMessage = + 1077671; // That's too bad. I really thought you had it in you. Well, I'm sure those undead will still be there later, so if you change your mind, feel free to stop on by and I'll help you the best I can. + InProgressMessage = + 1077672; // You're making some progress, that i can tell, but you're not quite good enough to last for very long out there by yourself. Head back to Old Haven, to the east, and kill some more undead. + CompletionMessage = + 1077674; // Hey, good job killing those undead! Hopefully someone will come along and clean up the mess. All that blood and guts tends to stink after a few days, and when the wind blows in from the east, it can raise a mighty stink!

Since you performed valiantly, please take these arms and use them well. I've seen a few too many harvests to be running around out there myself, so you might as well take it.

There is a lot left for you to learn, but I think you'll do fine. Remember to keep your elbows in and stick'em where it hurts the most! + CompletionNotice = + 1077673; // You have achieved the rank of Apprentice Warrior. Return to Alden Armstrong in New Haven to claim your reward. + + Objectives.Add(new GainSkillObjective(SkillName.Tactics, 500, true, true)); + + Rewards.Add(new ItemReward(1077675, typeof(ArmsOfArmstrong))); // Arms of Armstrong + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "AldenArmstrong"), new Point3D(3535, 2538, 20), Map.Trammel); + } + } + + public class TheWayOfTheBlade : MLQuest + { + public TheWayOfTheBlade() + { + Activated = true; + OneTimeOnly = true; + Title = 1077658; // The way of The Blade + Description = + 1077661; // Head East out of town and go to Old Haven. While wielding your sword, battle monster there until you have raised your Swordsmanship skill to 50. *as you approach, you notice Jockles sizing you up with a skeptical look on his face* i can see you want to learn how to handle a blade. It's a lot harder than it looks, and you're going to have to put alot of time and effort if you ever want to be half as good as i am. I'll tell you what, kid, I'll help you get started, but you're going to have to do all the work if you want to learn something. East of here, outside of town, is Old Haven. It's been overrun with the nastiest of undead you've seen, which makes it a perfect place for you to turn that sloppy grin on your face into actual skill at handling a sword. Make sure you have a sturdy Swordsmanship weapon in good repair before you leave. 'tis no fun to travel all the way down there just to find out you forgot your blade! When you feel that you've cut down enough of those foul smelling things to learn how to handle a blade without hurting yourself, come back to me. If i think you've improved enough, I'll give you something suited for a real warrior. + RefusalMessage = + 1077662; // Ha! I had a feeling you were a lily-livered pansy. You might have potential, but you're scared by a few smelly undead, maybe it's better that you stay away from sharp objects. After all, you wouldn't want to hurt yourself swinging a sword. If you change your mind, I might give you another chance...maybe. + InProgressMessage = + 1077663; // *Jockles looks you up and down* Come on! You've got to work harder than that to get better. Now get out of here, go kill some more of those undead to the east in Old Haven, and don't come back till you've got real skill. + CompletionMessage = + 1077665; // Well, well, look at what we have here! You managed to do it after all. I have to say, I'm a little surprised that you came back in one piece, but since you did. I've got a little something for you. This is a fine blade that served me well in my younger days. Of course I've got much better swords at my disposal now, so I'll let you go ahead and use it under one condition. Take goodcare of it and treat it with the respect that a fine sword deserves. You're one of the quickers learners I've seen, but you still have a long way to go. Keep at it, and you'll get there someday. Happy hunting, kid. + CompletionNotice = + 1077664; // You have achieved the rank of Apprentice Swordsman. Return to Jockles in New Haven to see what kind of reward he has waiting for you. Hopefully he'll be a little nicer this time! + + Objectives.Add(new GainSkillObjective(SkillName.Swords, 500, true, true)); + + Rewards.Add(new ItemReward(1077666, typeof(JocklesQuicksword))); // Jockles' Quicksword + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Jockles"), new Point3D(3535, 2544, 20), Map.Trammel); + } + } + + public class ThouAndThineShield : MLQuest + { + public ThouAndThineShield() + { + Activated = true; + OneTimeOnly = true; + Title = 1077704; // Thou and Thine Shield + Description = + 1077707; // Head East out of town and go to Old Haven. Battle monsters, or simply let them hit you, while holding a shield or a weapon until you have raised your Parrying skill to 50. Oh, hello. You probably want me to teach you how to parry, don't you? Very Well. First, you'll need a weapon or a shield. Obviously shields work best of all, but you can parry with a 2-handed weapon. Or if you're feeling particularly brave, a 1-handed weapon will do in a pinch, I'd advise you to go to Old Haven, which you'll find to the East, and practice blocking incoming blows from the undead there. You'll learn quickly if you have more than one opponent attacking you at the same time to practice parrying lots of blows at once. That's the quickest way to master the art of parrying. If you manage to improve your skill enough, i have a shield that you might find useful. Come back to me when you've trained to an apprentice level. + RefusalMessage = + 1077708; // It's your choice, obviously, but I'd highly suggest that you learn to parry before adventuring out into the world. Come talk to me again when you get tired of being beat on by your opponents + InProgressMessage = + 1077709; // You're doing well, but in my opinion, I Don't think you really want to continue on without improving your parrying skill a bit more. Go to Old Haven, to the East, and practice blocking blows with a shield. + CompletionMessage = + 1077711; // Well done! You're much better at parrying blows than you were when we first met. You should be proud of your new ability and I bet your body is greatful to you aswell. *Tyl Ariadne laughs loudly at his ownn (mostly lame) joke* Oh yes, I did promise you a shield if I thought you were worthy of having it, so here you go. My father made these shields for the guards who served my father faithfully for many years, and I just happen to have obe that i can part with. You should find it useful as you explore the lands.Good luck, and may the Virtues be your guide. + CompletionNotice = + 1077710; // You have achieved the rank of Apprentice Warrior (for Parrying). Return to Tyl Ariadne in New Haven as soon as you can to claim your reward. + + Objectives.Add(new GainSkillObjective(SkillName.Parry, 500, true, true)); + + Rewards.Add(new ItemReward(1077694, typeof(EscutcheonDeAriadne))); // Escutcheon de Ariadne + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "TylAriadne"), new Point3D(3525, 2556, 20), Map.Trammel); + } + } + + public class DefyingTheArcane : MLQuest + { + public DefyingTheArcane() + { + Activated = true; + OneTimeOnly = true; + Title = 1077621; // Defying the Arcane + Description = + 1077623; // Head East out of town and go to Old Haven. Battle spell casting monsters there until you have raised your Resisting Spells skill to 50.
------

Hail and well met! To become a true master of the arcane art of Magery, I suggest learning the complementary skill known as Resisting Spells. While the name of this skill may suggest that it helps with resisting all spells, this is not the case. This skill helps you lessen the severity of spells that lower your stats or ones that last for a specific duration of time. It does not lessen damage from spells such as Energy Bolt or Flamestrike.

The Magery spells that can be resisted are Clumsy, Curse, Feeblemind, Mana Drain, Mana Vampire, Paralyze, Paralyze Field, Poison, Poison Field, and Weaken.

The Necromancy spells that can be resisted are Blood Oath, Corpse Skin, Mind Rot, and Pain Spike.

At higher ranks, the Resisting Spells skill also benefits you by adding a bonus to your minimum elemental resists. This bonus is only applied after all other resist modifications - such as from equipment - has been calculated. It's also not cumulative. It compares the number of your minimum resists to the calculated value of your modifications and uses the higher of the two values.

As you can see, Resisting Spells is a difficult skill to understand, and even more difficult to master. This is because in order to improve it, you will have to put yourself in harm's way - as in the path of one of the above spells.

Undead have plagued the town of Old Haven. We need your assistance in cleansing the town of this evil influence. Old Haven is located east of here. Battle the undead spell casters that inhabit there.

Comeback to me once you feel that you are worthy of the rank of Apprentice Mage and I will reward you with an arcane prize. + RefusalMessage = + 1077624; // The ability to resist powerful spells is a taxing experience. I understand your resistance in wanting to pursue it. If you wish to reconsider, feel free to return to me for Resisting Spells training. Good journey to you! + InProgressMessage = + 1077632; // You have not achieved the rank of Apprentice Mage. Come back to me once you feel that you are worthy of the rank of Apprentice Mage and I will reward you with an arcane prize. + CompletionMessage = + 1077626; // You have successfully begun your journey in becoming a true master of Magery. On behalf of the New Haven Mage Council I wish to present you with this bracelet. When worn, the Bracelet of Resilience will enhance your resistances vs. the elements, physical, and poison harm. The Bracelet of Resilience also magically enhances your ability fend off ranged and melee attacks. I hope it serves you well. + CompletionNotice = + 1077625; // You have achieved the rank of Apprentice Mage (for Resisting Spells). Return to Alefian in New Haven to receive your arcane prize. + + Objectives.Add(new GainSkillObjective(SkillName.MagicResist, 500, true, true)); + + Rewards.Add(new ItemReward(1077627, typeof(BraceletOfResilience))); // Bracelet of Resilience + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Alefian"), new Point3D(3473, 2497, 72), Map.Trammel); + } + } + + public class StoppingTheWorld : MLQuest + { + public StoppingTheWorld() + { + Activated = true; + OneTimeOnly = true; + Title = 1077597; // Stopping the World + Description = + 1077598; // Head East out of town and go to Old Haven. Use spells and abilities to deplete your mana and meditate there until you have raised your Meditation skill to 50. Well met! I can teach you how to 'Stop the World' around you and focus your inner energies on replenishing you mana. What is mana? Mana is the life force for everyone who practices arcane arts. When a practitioner of magic invokes a spell or scribes a scroll. It consumes mana. Having a abundant supply of mana is vital to excelling as a practitioner of the arcane. Those of us who study the art of Meditation are also known as stotics. The Meditation skill allows stoics to increase the rate at which they regenerate mana A Stoic needs to perform abilities or cast spells to deplete mana before he can meditate to replenish it. Meditation can occur passively or actively. Actively Meditation is more difficult to master but allows for the stoic to replenish mana at a significantly faster rate. Metal armor inerferes with the regenerative properties of Meditation. It is wise to wear leather or cloth protection when meditating. Head east out of town and go to Old Haven. Use spells and abilities to deplete your mana and actively meditate to replenish it. Come back once you feel you are at the worthy rank of Apprentice Stoic and i will reward you with a arcane prize. + RefusalMessage = 1077599; // Seek me out if you ever wish to study the art of Meditation. Good journey. + InProgressMessage = + 1077628; // You have not achieved the rank of Apprentice Stoic. Come back to me once you feel that you are worthy of the rank Apprentice Stoic and i will reward you with a arcane prize. + CompletionMessage = + 1077626; // You have successfully begun your journey in becoming a true master of Magery. On behalf of the New Haven Mage Council I wish to present you with this bracelet. When worn, the Bracelet of Resilience will enhance your resistances vs. the elements, physical, and poison harm. The Bracelet of Resilience also magically enhances your ability fend off ranged and melee attacks. I hope it serves you well. + CompletionNotice = + 1077600; // You have achieved the rank of Apprentice Stoic (for Meditation). Return to Gustar in New Haven to receive your arcane prize. + + Objectives.Add(new GainSkillObjective(SkillName.Meditation, 500, true, true)); + + Rewards.Add(new ItemReward(1077602, typeof(PhilosophersHat))); // Philosopher's Hat + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Gustar"), new Point3D(3474, 2492, 91), Map.Trammel); + } + } + + public class ScribingArcaneKnowledge : MLQuest + { + public ScribingArcaneKnowledge() + { + Activated = true; + OneTimeOnly = true; + Title = 1077615; // Scribing Arcane Knowledge + Description = + 1077616; // While here at the New Haven Magery Library, use a scribe's pen and scribe and 3rd and 4th circle Magery scrolls that you have in your spellbook. Remember, you will need blank scrolls as well. Do this until you have raised your Inscription skill to 50.
------

Greetings and welcome to the New Haven Magery Library! You wish to learn how to scribe spell scrolls? You have come to the right place! Inscribed in a steady hand and imbued with the power of reagents, a scroll can mean the difference between life and death in a perilous situation. Those knowledgeable in Inscription may transcribe spells to create useful and valuable magical scrolls.

Before you inscribe a spell, you must first be able to cast the spell without the aid of a scroll. This means that you need the appropriate level of proficiency as a mage, the required mana, and the required reagents. Second, you will need a blank scroll to write on and a scribe's pen. Then, you will need to decide which particular spell you wish to scribe. It may sound easy, but there is a bit more to it. As with the development of all skills, you need to practice Inscription of lower level spells before you can move onto the more difficult ones.

The most important aspect of Inscription is mana. Inscribing a scroll with a magic spell drains your mana. When inscribing 3rd circle or lower spells this will not be much of a problem for these spells consume a small amount of mana. However, when you are inscribing higher circle spells, you may see your mana drain rapidly. When this happens, pause or meditate before continuing.

I suggest you begin scribing any 3rd and 4th circle spells that you know. If you don't possess any, you can always barter with one of the local mage merchants or a fellow adventurer that is a seasoned Scribe.

Come back to me once you feel that you are worthy of the rank of Apprentice Scribe and I will reward you with an arcane prize. + RefusalMessage = + 1077617; // I understand. When you are ready, feel free to return to me for Inscription training. Thanks for stopping by! + InProgressMessage = + 1077631; // You have not achieved the rank of Apprentice Scribe. Come back to me once you feel that you are worthy of the rank Apprentice Scribe and i will reward you with a arcane prize. + CompletionMessage = + 1077619; // Scribing is a very fulfilling pursuit. I am pleased to see you embark on this journey. You sling a pen well! On behalf of the New Haven Mage Council I wish to present you with this spellbook. When equipped, the Hallowed Spellbook greatly enhances the potency of your offensive spells when used against Undead. Be mindful, though. While this book is equipped, when you invoke your powerful spells and abilities vs. Humanoids such as other humans, orcs, ettins, trolls, and the like, your offensive spells will diminish in effectiveness. I suggest unequipping the Hallowed Spellbook when battling Humanoids. I hope this spellbook serves you well. + CompletionNotice = + 1077618; // You have achieved the rank of Apprentice Scribe. Return to Jillian in New Haven to receive your arcane prize. + + Objectives.Add(new GainSkillObjective(SkillName.Inscribe, 500, true, true)); + + Rewards.Add(new ItemReward(1077620, typeof(HallowedSpellbook))); // Hallowed Spellbook + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Jillian"), new Point3D(3465, 2490, 71), Map.Trammel); + } + } + + public class TheMagesApprentice : MLQuest + { + public TheMagesApprentice() + { + Activated = true; + OneTimeOnly = true; + Title = 1077576; // The Mage's Apprentice + Description = + 1077577; // Head East out of town and go to Old Haven. Cast fireballs and lightning bolts against monsters there until you have raised your Magery skill to 50. Greetings. You seek to unlock the secrets of the arcane art of Magery. The New Haven Mage Council has an assignment for you. Undead have plagued the town of Old Haven. We need your assistance in cleansing the town of this evil influence. Old Haven is located east of here. I suggest using your offensive Magery spells such as Fireball and Lightning Bolt against the Undead that inhabit there. Make sure you have plenty of reagents before embarking on your journey. Reagents are required to cast Magery spells. You can purchase extra reagents at the nearby Reagent shop, or you can find reagents growing in the nearby wooded areas. You can see which reagents are required for each spell by looking in your spellbook. Come back to me once you feel that you are worthy of the rank of Apprentice Mage and I will reward you with an arcane prize. + RefusalMessage = + 1077578; // Very well, come back to me when you are ready to practice Magery. You have so much arcane potential. 'Tis a shame to see it go to waste. The New Haven Mage Council could really use your help. + InProgressMessage = + 1077579; // You have not achieved the rank of Apprentice Mage. Come back to me once you feel that you are worthy of the rank of Apprentice Mage and I will reward you with an arcane prize. + CompletionMessage = + 1077581; // Well done! On behalf of the New Haven Mage Council I wish to present you with this staff. Normally a mage must unequip weapons before spell casting. While wielding your new Ember Staff, however, you will be able to invoke your Magery spells. Even if you do not currently possess skill in Mace Fighting, the Ember Staff will allow you to fight as if you do. However, your Magery skill will be temporarily reduced while doing so. Finally, the Ember Staff occasionally smites a foe with a Fireball while wielding it in melee combat. I hope the Ember Staff serves you well. + CompletionNotice = + 1077580; // You have achieved the rank of Apprentice Mage. Return to Kaelynna in New Haven to receive your arcane prize. + + Objectives.Add(new GainSkillObjective(SkillName.Magery, 500, true, true)); + + Rewards.Add(new ItemReward(1077582, typeof(EmberStaff))); // Ember Staff + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Kaelynna"), new Point3D(3486, 2491, 52), Map.Trammel); + } + } + + public class ScholarlyTask : MLQuest + { + public ScholarlyTask() + { + Activated = true; + OneTimeOnly = true; + Title = 1077603; // A Scholarly Task + Description = + 1077604; // Head East out of town and go to Old Haven. Use Evaluating Intelligence on all creatures you see there. You can also cast Magery spells as well to raise Evaluating Intelligence. Do these activities until you have raised your Evaluating Intelligence skill to 50.
------

Hello. Truly knowing your opponent is essential for landing your offensive spells with precision. I can teach you how to enhance the effectiveness of your offensive spells, but first you must learn how to size up your opponents intellectually. I have a scholarly task for you. Head East out of town and go to Old Haven. Use Evaluating Intelligence on all creatures you see there. You can also cast Magery spells as well to raise Evaluating Intelligence.

Come back to me once you feel that you are worthy of the rank of Apprentice Scholar and I will reward you with an arcane prize. + RefusalMessage = 1077605; // Return to me if you reconsider and wish to become an Apprentice Scholar. + InProgressMessage = + 1077629; // You have not achieved the rank of Apprentice Scholar. Come back to me once you feel that you are worthy of the rank of Apprentice Scholar and I will reward you with an arcane prize. + CompletionMessage = + 1077607; // You have completed the task. Well done. On behalf of the New Haven Mage Council I wish to present you with this ring. When worn, the Ring of the Savant enhances your intellectual aptitude and increases your mana pool. Your spell casting abilities will take less time to invoke and recovering from such spell casting will be hastened. I hope the Ring of the Savant serves you well. + CompletionNotice = + 1077606; // You have achieved the rank of Apprentice Scholar. Return to Mithneral in New Haven to receive your arcane prize. + + Objectives.Add(new GainSkillObjective(SkillName.EvalInt, 500, true, true)); + + Rewards.Add(new ItemReward(1077608, typeof(RingOfTheSavant))); // Ring of the Savant + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Mithneral"), new Point3D(3485, 2491, 71), Map.Trammel); + } + } + + public class TheRightToolForTheJob : MLQuest + { + public TheRightToolForTheJob() + { + Activated = true; + OneTimeOnly = true; + Title = 1077741; // The Right Tool for the Job + Description = + 1077744; // Create new scissors and hammers while inside Amelia's workshop. Try making scissors up to 45 skill, the switch to making hammers until 50 skill.
-----

Hello! I guess you're here to learn something about Tinkering, eh? You've come to the right place, as Tinkering is what I've dedicated my life to.

You'll need two things to get started: a supply of ingots and the right tools for the job. You can either buy ingots from the market, or go mine them yourself. As for tools, you can try making your own set of Tinker's Tools, or if you'd prefer to buy them, I have some for sale.

Working here in my shop will let me give you pointers as you go, so you'll be able to learn faster than anywhere else. Start off making scissors until you reach 45 tinkering skill, then switch to hammers until you've achieved 50. Once you've done that, come talk to me and I'll give you something for your hard work. + RefusalMessage = + 1077745; // I’m disappointed that you aren’t interested in learning more about Tinkering. It’s really such a useful skill!

*Amelia smiles*

At least you know where to find me if you change your mind, since I rarely spend time outside of this shop. + InProgressMessage = + 1077746; // Nice going! You're not quite at Apprentice Tinkering yet, though, so you better get back to work. Remember that the quickest way to learn is to make scissors up until 45 skill, and then switch to hammers. Also, don't forget that working here in my shop will let me give you tips so you can learn faster. + CompletionMessage = + 1077748; // You've done it! Look at our brand new Apprentice Tinker! You've still got quite a lot to learn if you want to be a Grandmaster Tinker, but I believe you can do it! Just keep in mind that if you're tinkering just to practice and improve your skill, make items that are moderately difficult (60-80% success chance), and try to stick to ones that use less ingots.

Come here, my brand new Apprentice Tinker, I want to give you something special. I created this just for you, so I hope you like it. It's a set of Tinker's Tools that contains a bit of magic. These tools have more charges than any Tinker's Tools a Tinker can make. You can even use them to make a normal set of tools, so that way you won't ever find yourself stuck somewhere with no tools! + CompletionNotice = + 1077747; // You have achieved the rank of Apprentice Tinker. Talk to Amelia Youngstone in New Haven to see what kind of reward she has waiting for you. + + Objectives.Add(new GainSkillObjective(SkillName.Tinkering, 500, true, true)); + + Rewards.Add(new ItemReward(1077749, typeof(AmeliasToolbox))); // Amelia’s Toolbox + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "AmeliaYoungstone"), new Point3D(3459, 2529, 53), Map.Trammel); + } + } + + public class KnowThineEnemy : MLQuest + { + public KnowThineEnemy() + { + Activated = true; + OneTimeOnly = true; + Title = 1077685; // Know Thine Enemy + Description = + 1077688; // Head East out of town to Old Haven. Battle monsters there, or heal yourself and other players, until you have raised your Anatomy skill to 50.
------

Hail and well met. You must be here to improve your knowledge of Anatomy. Well, you've come to the right place because I can teach you what you need to know. At least all you'll need to know for now. Haha!

Knowing about how living things work inside can be a very useful skill. Not only can you learn where to strike an opponent to hurt him the most, but you can use what you learn to heal wounds better as well. Just walking around town, you can even tell if someone is strong or weak or if they happen to be particularly dexterous or not.

If you're interested in learning more, I'd advise you to head out to Old Haven, just to the east, and jump into the fray. You'll learn best by engaging in combat while keeping you and your fellow adventurers healed, or you can even try sizing up your opponents.

While you're gone, I'll dig up something you may find useful. + RefusalMessage = + 1077689; // It's your choice, but I wouldn't head out there without knowing what makes those things tick inside! If you change your mind, you can find me right here dissecting frogs, cats or even the occasional unlucky adventurer. + InProgressMessage = + 1077690; // I'm surprised to see you back so soon. You've still got a ways to go if you want to really understand the science of Anatomy. Head out to Old Haven and practice combat and healing yourself or other adventurers. + CompletionMessage = + 1077692; // By the Virtues, you've done it! Congratulations mate! You still have quite a ways to go if you want to perfect your knowledge of Anatomy, but I know you'll get there someday. Just keep at it.

In the meantime, here's a piece of armor that you might find useful. It's not fancy, but it'll serve you well if you choose to wear it.

Happy adventuring, and remember to keep your cranium separate from your clavicle! + CompletionNotice = + 1077691; // You have achieved the rank of Apprentice Healer (for Anatomy). Return to Andreas Vesalius in New Haven as soon as you can to claim your reward. + + Objectives.Add(new GainSkillObjective(SkillName.Anatomy, 500, true, true)); + + Rewards.Add(new ItemReward(1077693, typeof(TunicOfGuarding))); // Tunic of Guarding + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "AndreasVesalius"), new Point3D(3457, 2550, 35), Map.Trammel); + } + } + + public class BruisesBandagesAndBlood : MLQuest + { + public BruisesBandagesAndBlood() + { + Activated = true; + OneTimeOnly = true; + Title = 1077676; // Bruises, Bandages and Blood + Description = + 1077679; // Head East out of town and go to Old Haven. Heal yourself and other players until you have raised your Healing skill to 50.
------

Ah, welcome to my humble practice. I am Avicenna, New Haven's resident Healer. A lot of adventurers head out into the wild from here, so I keep rather busy when they come back bruised, bleeding, or worse.

I can teach you how to bandage a wound, sure, but it's not a job for the queasy! For some folks, the mere sight of blood is too much for them, but it's something you'll get used to over time. It is one thing to cut open a living thing, but it's quite another to sew it back up and save it from sure death. 'Tis noble work, healing.

Best way for you to practice fixing up wounds is to head east out to Old Haven and either practice binding up your own wounds, or practice on someone else. Surely they'll be grateful for the assistance.

Make sure to take enough bandages with you! You don't want to run out in the middle of a tough fight. + RefusalMessage = + 1077680; // No? Are you sure? Well, when you feel that you're ready to practice your healing, come back to me. I'll be right here, fixing up adventurers and curing the occasional cold! + InProgressMessage = + 1077681; // Hail! 'Tis good to see you again. Unfortunately, you're not quite ready to call yourself an Apprentice Healer quite yet. Head back out to Old Haven, due east from here, and bandage up some wounds. Yours or someone else's, it doesn't much matter. + CompletionMessage = + 1077683; // Hello there, friend. I see you've returned in one piece, and you're an Apprentice Healer to boot! You should be proud of your accomplishment, as not everyone has "the touch" when it comes to healing.

I can't stand to see such good work go unrewarded, so I have something I'd like you to have. It's not much, but it'll help you heal just a little faster, and maybe keep you alive.

Good luck out there, friend, and don't forget to help your fellow adventurer whenever possible! + CompletionNotice = + 1077682; // You have achieved the rank of Apprentice Healer. Return to Avicenna in New Haven as soon as you can to claim your reward. + + Objectives.Add(new GainSkillObjective(SkillName.Healing, 500, true, true)); + + Rewards.Add(new ItemReward(1077684, typeof(HealersTouch))); // Healer's Touch + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Avicenna"), new Point3D(3464, 2558, 35), Map.Trammel); + } + } + + public class TheInnerWarrior : MLQuest + { + public TheInnerWarrior() + { + Activated = true; + OneTimeOnly = true; + Title = 1077696; // The Inner Warrior + Description = + 1077699; // Head East out of town to Old Haven. Expend stamina and mana until you have raised your Focus skill to 50.
------

Well, hello there. Don't you look like quite the adventurer!

You want to learn more about Focus, do you? I can teach you something about that, but first you should know that not everyone can be disciplined enough to excel at it. Focus is the ability to achieve inner balance in both body and spirit, so that you recover from physical and mental exertion faster than you otherwise would.

If you want to practice Focus, the best place to do that is east of here, in Old Haven, where you'll find an undead infestation. Exert yourself physically by engaging in combat and moving quickly. For testing your mental balance, expend mana in whatever way you find most suitable to your abilities. Casting spells and using abilities work well for consuming your mana.

Go. Train hard, and you will find that your concentration will improve naturally. When you've improved your ability to focus yourself at an Apprentice level, come back to me and I shall give you something worthy of your new ability. + RefusalMessage = + 1077700; // I'm disappointed. You have a lot of inner potential, and it would pain me greatly to see you waste that. Oh well. If you change your mind, I'll be right here. + InProgressMessage = + 1077701; // Hello again. I see you've returned, but it seems that your Focus skill hasn't improved as much as it could have. Just head east, to Old Haven, and exert yourself physically and mentally as much as possible. To do this physically, engage in combat and move as quickly as you can. For exerting yourself mentally, expend mana in whatever way you find most suitable to your abilities. Casting spells and using abilities work well for consuming your mana.

Return to me when you have gained enough Focus skill to be considered an Apprentice Stoic. + CompletionMessage = + 1077703; // Look who it is! I knew you could do it if you just had the discipline to apply yourself. It feels good to recover from battle so quickly, doesn't it? Just wait until you become a Grandmaster, it's amazing!

Please take this gift, as you've more than earned it with your hard work. It will help you recover even faster during battle, and provides a bit of protection as well.

You have so much more potential, so don't stop trying to improve your Focus now! Safe travels! + CompletionNotice = + 1077702; // You have achieved the rank of Apprentice Stoic (for Focus). Return to Sarsmea Smythe in New Haven to see what kind of reward she has waiting for you. + + Objectives.Add(new GainSkillObjective(SkillName.Focus, 500, true, true)); + + Rewards.Add(new ItemReward(1077695, typeof(ClaspOfConcentration))); // Clasp of Concentration + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "SarsmeaSmythe"), new Point3D(3492, 2577, 15), Map.Trammel); + } + } + + public class TheArtOfStealth : MLQuest + { + public TheArtOfStealth() + { + Activated = true; + OneTimeOnly = true; + Title = 1078154; // The Art of Stealth + Description = + 1078158; // Head East out of town and go to Old Haven. While wielding your fencing weapon, battle monsters with focus attack and summon mirror images up to 40 Ninjitsu skill, and continue practicing focus attack on monsters until 50 Ninjitsu skill.
------

Welcome, young one. You seek to learn Ninjitsu. With it, and the book of Ninjitsu, a Ninja can evoke a number of special abilities including transforming into a variety of creatures that give unique bonuses, using stealth to attack unsuspecting opponents or just plain disappear into thin air! If you do not have a book of Ninjitsu, you can purchase one from me.

I have an assignment for you. Head East out of town and go to Old Haven. While wielding your fencing weapon, battle monsters with focus attack and summon mirror images up to Novice rank, and continue focusing your attacks for greater damage on monsters until you become an Apprentice Ninja. Each image will absorb one attack. The art of deception is a strong defense. Use it wisely.

Come back to me once you have achieved the rank of Apprentice Ninja, and I shall reward you with something useful. + RefusalMessage = 1078159; // Come back to me if you with to learn Ninjitsu in the future. + InProgressMessage = + 1078160; // You have not achieved the rank of Apprentice Ninja. Come back to me once you have done so. + CompletionMessage = + 1078162; // You have done well, young one. Please accept this kryss as a gift. It is called the "Silver Serpent Blade". With it, you will strike with precision and power. This should aid you in your journey as a Ninja. Farewell. + CompletionNotice = + 1078161; // You have achieved the rank of Apprentice Ninja. Return to Ryuichi in New Haven to see what kind of reward he has waiting for you. + + Objectives.Add(new GainSkillObjective(SkillName.Ninjitsu, 500, true, true)); + + Rewards.Add(new ItemReward(1078163, typeof(SilverSerpentBlade))); // Silver Serpent Blade + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Ryuichi"), new Point3D(3422, 2520, 21), Map.Trammel); + } + } + + public class BecomingOneWithTheShadows : MLQuest + { + public BecomingOneWithTheShadows() + { + Activated = true; + OneTimeOnly = true; + Title = 1078164; // Becoming One with the Shadows + Description = + 1078168; // Practice hiding in the Ninja Dojo until you reach 50 Hiding skill.
------

Come closer. Don't be afraid. The shadows will not harm you. To be a successful Ninja, you must learn to become one with the shadows. The Ninja Dojo is the ideal place to learn the art of concealment. Practice hiding here.

Talk to me once you have achieved the rank of Apprentice Rogue (for Hiding), and I shall reward you. + RefusalMessage = 1078169; // If you wish to become one with the shadows, come back and talk to me. + InProgressMessage = + 1078170; // You have not achieved the rank of Apprentice Rogue (for Hiding). Talk to me when you feel you have accomplished this. + CompletionMessage = + 1078172; // Not bad at all. You have learned to control your fear of the dark and you are becoming one with the shadows. If you haven't already talked to Jun, I advise you do so. Jun can teach you how to stealth undetected. Hiding and Stealth are essential skills to master when becoming a Ninja.

As promised, I have a reward for you. Here are some smokebombs. As long as you are an Apprentice Ninja and have mana available you will be able to use them. They will allow you to hide while in the middle of combat. I hope these serve you well. + CompletionNotice = + 1078171; // You have achieved the rank of Apprentice Rogue (for Hiding). Return to Chiyo in New Haven to claim your reward. + + Objectives.Add(new GainSkillObjective(SkillName.Hiding, 500, true, true)); + + Rewards.Add(new ItemReward(1078173, typeof(BagOfSmokeBombs))); // Bag of Smoke Bombs + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Chiyo"), new Point3D(3420, 2516, 21), Map.Trammel); + } + } + + public class WalkingSilently : MLQuest + { + public WalkingSilently() + { + Activated = true; + OneTimeOnly = true; + Title = 1078174; // Walking Silently + Description = + 1078178; // Head East out of town and go to Old Haven. While wearing normal clothes, practice Stealth there until you reach 50 Stealth skill.
------

You there. You're not very quiet in your movements. I can help you with that. Not only must you must learn to become one with the shadows, but also you must learn to quiet your movements. Old Haven is the ideal place to learn how to Stealth.

Head East out of town and go to Old Haven. While wearing normal clothes, practice Stealth there. Stealth becomes more difficult as you wear heavier pieces of armor, so for now, only wear clothes while practicing Stealth.

You can only Stealth once you are hidden. If you become visible, use your Hiding skill, and begin slowing walking.

Come back to me once you have achieved the rank of Apprentice Rogue (for Stealth), and I will reward you with something useful. + RefusalMessage = 1078179; // If you want to learn to quiet your movements, talk to me, and I will help you. + InProgressMessage = + 1078180; // You have not achieved the rank of Apprentice Rogue (for Stealth). Come back to me when you feel you have accomplished this. + CompletionMessage = + 1078182; // Good. You have learned to quiet your movements. If you haven't already talked to Chiyo, I advise you do so. Chiyo can teach you how to become one with the shadows. Hiding and Stealth are essential skills to master when becoming a Ninja.

Here is your reward. This leather Ninja jacket is called "Twilight Jacket". It will offer greater protection to you. I hope this serve you well. + CompletionNotice = + 1078181; // You have achieved the rank of Apprentice Rogue (for Stealth). Return to Jun in New Haven to claim your reward. + + Objectives.Add(new GainSkillObjective(SkillName.Stealth, 500, true, true)); + + Rewards.Add(new ItemReward(1078183, typeof(TwilightJacket))); // Twilight Jacket + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Jun"), new Point3D(3422, 2516, 21), Map.Trammel); + } + } + + public class EyesOfARanger : MLQuest + { + public EyesOfARanger() + { + Activated = true; + OneTimeOnly = true; + Title = 1078211; // Eyes of a Ranger + Description = + 1078217; // Track animals, monsters, and people on Haven Island until you have raised your Tracking skill to 50.
------

Hello friend. I am Walker, Grandmaster Ranger. An adventurer needs to keep alive in the wilderness. Being able to track those around you is essential to surviving in dangerous places. Certain Ninja abilities are more potent when the Ninja possesses Tracking knowledge. If you want to be a Ninja, or if you simply want to get a leg up on the creatures that habit these parts, I advise you learn how to track them.

You can track any animals, monsters, or people on Haven Island. Clear your mind, focus, and note any tracks in the ground or sounds in the air that can help you find your mark. You can do it, friend. I have faith in you.

Come back to me once you have achieved the rank of Apprentice Ranger (for Tracking), and I will give you something that may help you in your travels. Take care, friend. + RefusalMessage = + 1078218; // Farewell, friend. Be careful out here. If you change your mind and want to learn Tracking, come back and talk to me. + InProgressMessage = + 1078219; // So far so good, kid. You are still alive, and you are getting the hang of Tracking. There are many more animals, monsters, and people to track. Come back to me once you have tracked them. + CompletionMessage = + 1078221; // I knew you could do it! You have become a fine Ranger. Just keep practicing, and one day you will become a Grandmaster Ranger. Just like me.

I have a little something for you that will hopefully aid you in your journeys. These leggings offer some resistances that will hopefully protect you from harm. I hope these serve you well. Farewell, friend. + CompletionNotice = + 1078220; // You have achieved the rank of Apprentice Ranger (for Tracking). Return to Walker in New Haven to claim your reward. + + Objectives.Add(new GainSkillObjective(SkillName.Tracking, 500, true, true)); + + Rewards.Add(new ItemReward(1078222, typeof(WalkersLeggings))); // Walker's Leggings + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Walker"), new Point3D(3429, 2518, 19), Map.Trammel); + } + } + + public class TheWayOfTheSamurai : MLQuest + { + public TheWayOfTheSamurai() + { + Activated = true; + OneTimeOnly = true; + Title = 1078007; // The Way of the Samurai + Description = + 1078010; // Head East out of town and go to Old Haven. use the Confidence defensive stance and attempt to honorably execute monsters there until you have raised your Bushido skill to 50.
------

Greetings. I see you wish to learn the Way of the Samurai. Wielding a blade is easy. Anyone can grasp a sword's hilt. Learning how to fight properly and skillfully is to become an Armsman. Learning how to master weapons, and even more importantly when not to use them, is the Way of the Warrior. The Way of the Samurai. The Code of the Bushido. That is why you are here.

Adventure East to Old Haven. Use the Confidence defensive stance and attempt to honorably execute the undead that inhabit there. You will need a book of Bushido to perform these abilities. If you do not possess a book of Bushido, you can purchase one from me.

If you fail to honorably execute the undead, your defenses will be greatly weakened: Resistances will suffer and Resisting Spells will suffer. A successful parry instantly ends the weakness. If you succeed, however, you will be infused with strength and healing. Your swing speed will also be boosted for a short duration. With practice, you will learn how to master your Bushido abilities.

Return to me once you feel that you have become an Apprentice Samurai. + RefusalMessage = 1078011; // Good journey to you. Return to me if you wish to live the life of a Samurai. + InProgressMessage = + 1078012; // You are not ready to become an Apprentice Samurai. There are still more undead to lay to rest. Return to me once you have done so. + CompletionMessage = + 1078014; // You have proven yourself young one. You will continue to improve as your skills are honed with age. You are an honorable warrior, worthy of the rank of Apprentice Samurai. Please accept this no-dachi as a gift. It is called "The Dragon's Tail". Upon a successful strike in combat, there is a chance this mighty weapon will replenish your stamina equal to the damage of your attack. I hope "The Dragon's Tail" serves you well. You have earned it. Farewell for now. + CompletionNotice = + 1078013; // You have achieved the rank of Apprentice Samurai. Return to Hamato in New Haven to report your progress. + + Objectives.Add(new GainSkillObjective(SkillName.Bushido, 500, true, true)); + + Rewards.Add(new ItemReward(1078015, typeof(TheDragonsTail))); // The Dragon's Tail + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Hamato"), new Point3D(3493, 2414, 55), Map.Trammel); + } + } + + public class TheAllureOfDarkMagic : MLQuest + { + public TheAllureOfDarkMagic() + { + Activated = true; + OneTimeOnly = true; + Title = 1078036; // The Allure of Dark Magic + Description = + 1078039; // Head East out of town and go to Old Haven. Cast Evil Omen and Pain Spike against monsters there until you have raised your Necromancy skill to 50.
------

Welcome! I see you are allured by the dark magic of Necromancy. First, you must prove yourself worthy of such knowledge. Undead currently occupy the town of Old Haven. Practice your harmful Necromancy spells on them such as Evil Omen and Pain Spike.

Make sure you have plenty of reagents before embarking on your journey. Reagents are required to cast Necromancy spells. You can purchase extra reagents from me, or you can find reagents growing in the nearby wooded areas. You can see which reagents are required for each spell by looking in your spellbook.

Come back to me once you feel that you are worthy of the rank of Apprentice Necromancer and I will reward you with the knowledge you desire. + RefusalMessage = 1078040; // You are weak after all. Come back to me when you are ready to practice Necromancy. + InProgressMessage = + 1078041; // You have not achieved the rank of Apprentice Necromancer. Come back to me once you feel that you are worthy of the rank of Apprentice Necromancer and I will reward you with the knowledge you desire. + CompletionMessage = + 1078043; // You have done well, my young apprentice. Behold! I now present to you the knowledge you desire. This spellbook contains all the Necromancer spells. The power is intoxicating, isn't it? + CompletionNotice = + 1078042; // You have achieved the rank of Apprentice Necromancer. Return to Mulcivikh in New Haven to receive the knowledge you desire. + + Objectives.Add(new GainSkillObjective(SkillName.Necromancy, 500, true, true)); + + Rewards.Add(new InternalReward()); + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Mulcivikh"), new Point3D(3548, 2456, 15), Map.Trammel); + } + + private class InternalReward : ItemReward + { + public InternalReward() + : base(1078052, typeof(NecromancerSpellbook)) // Complete Necromancer Spellbook + { + } + + public override Item CreateItem() + { + var item = base.CreateItem(); + + if (item is Spellbook book) + book.Content = (1ul << book.BookCount) - 1; + + return item; + } + } + } + + public class ChannelingTheSupernatural : MLQuest + { + public ChannelingTheSupernatural() + { + Activated = true; + OneTimeOnly = true; + Title = 1078044; // Channeling the Supernatural + Description = + 1078047; // Head East out of town and go to Old Haven. Use Spirit Speak and channel energy from either yourself or nearby corpses there. You can also cast Necromancy spells as well to raise Spirit Speak. Do these activities until you have raised your Spirit Speak skill to 50.
------

How do you do? Channeling the supernatural through Spirit Speak allows you heal your wounds. Such channeling expends your mana, so be mindful of this. Spirit Speak enhances the potency of your Necromancy spells. The channeling powers of a Medium are quite useful when practicing the dark magic of Necromancy.

It is best to practice Spirit Speak where there are a lot of corpses. Head East out of town and go to Old Haven. Undead currently reside there. Use Spirit Speak and channel energy from either yourself or nearby corpses. You can also cast Necromancy spells as well to raise Spirit Speak.

Come back to me once you feel that you are worthy of the rank of Apprentice Medium and I will reward you with something useful. + RefusalMessage = + 1078048; // Channeling the supernatural isn't for everyone. It is a dark art. See me if you ever wish to pursue the life of a Medium. + InProgressMessage = + 1078049; // Back so soon? You have not achieved the rank of Apprentice Medium. Come back to me once you feel that you are worthy of the rank of Apprentice Medium and I will reward you with something useful. + CompletionMessage = + 1078051; // Well done! Channeling the supernatural is taxing, indeed. As promised, I will reward you with this bag of Necromancer reagents. You will need these if you wish to also pursue the dark magic of Necromancy. Good journey to you. + CompletionNotice = + 1078050; // You have achieved the rank of Apprentice Medium. Return to Morganna in New Haven to receive your reward. + + Objectives.Add(new GainSkillObjective(SkillName.SpiritSpeak, 500, true, true)); + + Rewards.Add(new ItemReward(1078053, typeof(BagOfNecromancerReagents))); // Bag of Necromancer Reagents + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Morganna"), new Point3D(3547, 2463, 15), Map.Trammel); + } + } + + public class TheDeluciansLostMine : MLQuest + { + public TheDeluciansLostMine() + { + Activated = true; + OneTimeOnly = true; + Title = 1077750; // The Delucian’s Lost Mine + Description = + 1077753; // Find Jacob's Lost Mine and mine iron ore there, using a pickaxe or shovel. Bring it back to Jacob's forge and smelt the ore into ingots, until you have raised your Mining skill to 50. You may find a packhorse useful for hauling the ore around. The animal trainer in New Haven has packhorses for sale.
-----

Howdy! Welcome to my camp. It's not much, I know, but it's all I'll be needin' up here. I don't need them fancy things those townspeople have down there in New Haven. Nope, not one bit. Just me, Bessie, my pick and a thick vein 'o valorite.

Anyhows, I'm guessin' that you're up here to ask me about minin', aren't ya? Well, don't be expectin' me to tell you where the valorite's at, cause I ain't gonna tell the King of Britannia, much less the likes of you. But I will show ya how to mine and smelt iron, cause there certainly is a 'nough of up in these hills.

*Jacob looks around, with a perplexed look on his face*

Problem is, I can't remember where my iron mine's at, so you'll have to find it yourself. Once you're there, have at it with a pickaxe or shovel, then haul it back to camp and I'll show ya how to smelt it. Ya look a bit wimpy, so you might wanna go buy yourself a packhorse in town from the animal trainer to help you haul around all that ore.

When you're an Apprentice Miner, talk to me and I'll give ya a little somethin' I've got layin' around here... somewhere. + RefusalMessage = + 1077754; // Couldn’t find my iron mine, could ya? Well, neither can I!

*Jacob laughs*

Oh, ya don’t wanna find it? Well, allrighty then, ya might as well head on back down to town then and stop cluttering up my camp. Come back and talk to me if you’re interested in learnin’ ‘bout minin’. + InProgressMessage = + 1077755; // Where ya been off a gallivantin’ all day, pilgrim? You ain’t seen no hard work yet! Get yer arse back out there to my mine and dig up some more iron. Don’t forget to take a pickaxe or shovel, and if you’re so inclined, a packhorse too. + CompletionMessage = + 1077757; // Dang gun it! If that don't beat all! Ya went and did it, didn’t ya? What we got ourselves here is a mighty fine brand spankin’ new Apprentice Miner!

I can see ya put some meat on them bones too while you were at it!

Here’s that little somethin’ I told ya I had for ya. It’s a pickaxe with some high falutin’ magic inside that’ll help you find the good stuff when you’re off minin’. It wears out fast, though, so you can only use it a few times a day.

Welp, I’ve got some smeltin’ to do, so off with ya. Good luck, pilgrim! + CompletionNotice = + 1077756; // You have achieved the rank of Apprentice Miner. Return to Jacob Waltz in at his camp in the hills above New Haven as soon as you can to claim your reward. + + Objectives.Add(new GainSkillObjective(SkillName.Mining, 500, true, true)); + + Rewards.Add(new ItemReward(1077758, typeof(JacobsPickaxe))); // Jacob's Pickaxe + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "JacobWaltz"), new Point3D(3504, 2741, 0), Map.Trammel); + } + } + + public class ItsHammerTime : MLQuest + { + public ItsHammerTime() + { + Activated = true; + OneTimeOnly = true; + Title = 1077732; // It’s Hammer Time! + Description = + 1077735; // Create new daggers and maces using the forge and anvil in George's shop. Try making daggers up to 45 skill, the switch to making maces until 50 skill.
-----

Hail, and welcome to my humble shop. I'm George Hephaestus, New Haven's blacksmith. I assume that you're here to ask me to train you to be an Apprentice Blacksmith. I certainly can do that, but you're going to have to supply your own ingots.

You can always buy them at the market, but I highly suggest that you mine your own. That way, any items you sell will be pure profit!

So, once you have a supply of ingots, use my forge and anvil here to create items. You'll also need a supply of the proper tools; you can use a smith's hammer, a sledgehammer or tongs. You can either make them yourself if you have the tinkering skill, or buy them from a tinker at the market.

Since I'll be around to give you advice, you'll learn faster here than anywhere else. Start off making daggers until you reach 45 blacksmithing skill, then switch to maces until you've achieved 50. Once you've done that, come talk to me and I'll give you something for your hard work. + RefusalMessage = + 1077736; // You're not interested in learning to be a smith, eh? I thought for sure that's why you were here. Oh well, if you change your mind, you can always come back and talk to me. + InProgressMessage = + 1077737; // You’re doing well, but you’re not quite there yet. Remember that the quickest way to learn is to make daggers up until 45 skill, and then switch to maces. Also, don’t forget that using my forge and anvil will help you learn faster. + CompletionMessage = + 1077739; // I've been watching you get better and better as you've been smithing, and I have to say, you're a natural! It's a long road to being a Grandmaster Blacksmith, but I have no doubt that if you put your mind to it you'll get there someday. Let me give you one final piece of advice. If you're smithing just to practice and improve your skill, make items that are moderately difficult (60-80% success chance), and try to stick to ones that use less ingots.

Now that you're an Apprentice Blacksmith, I have something for you. While you were busy practicing, I was crafting this hammer for you. It's finely balanced, and has a bit of magic imbued within that will help you craft better items. However, that magic needs to restore itself over time, so you can only use it so many times per day. I hope you find it useful! + CompletionNotice = + 1077738; // You have achieved the rank of Apprentice Blacksmith. Return to George Hephaestus in New Haven to see what kind of reward he has waiting for you. + + Objectives.Add(new GainSkillObjective(SkillName.Blacksmith, 500, true, true)); + + Rewards.Add(new ItemReward(1077740, typeof(HammerOfHephaestus))); // Hammer of Hephaestus + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "GeorgeHephaestus"), new Point3D(3471, 2542, 36), Map.Trammel); + } + } + + public class Aelorn : KeeperOfChivalry + { + [Constructible] + public Aelorn() + { + Title = "the Chivalry Instructor"; + BodyValue = 0x190; + Hue = 0x83EA; + HairItemID = 0x203C; + HairHue = 0x47D; + FacialHairItemID = 0x204D; + FacialHairHue = 0x47D; + + InitStats(100, 100, 25); + + SetSkill(SkillName.Anatomy, 120.0); + SetSkill(SkillName.MagicResist, 120.0); + SetSkill(SkillName.Tactics, 120.0); + SetSkill(SkillName.Swords, 120.0); + SetSkill(SkillName.Meditation, 120.0); + SetSkill(SkillName.Focus, 120.0); + SetSkill(SkillName.Chivalry, 120.0); + } + + public Aelorn(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "Aelorn"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078133); // Hail, friend. Want to live the life of a paladin? + } + + public override void InitOutfit() + { + AddItem(new Backpack()); + AddItem(new VikingSword()); + AddItem(new PlateChest()); + AddItem(new PlateLegs()); + AddItem(new PlateGloves()); + AddItem(new PlateArms()); + AddItem(new PlateGorget()); + AddItem(new OrderShield()); + } + + 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 class Dimethro : BaseCreature + { + [Constructible] + public Dimethro() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Wrestling Instructor"; + BodyValue = 0x190; + Hue = 0x83EA; + HairItemID = 0x203D; + HairHue = 0x455; + FacialHairItemID = 0x204D; + FacialHairHue = 0x455; + + InitStats(100, 100, 25); + + SetSkill(SkillName.EvalInt, 120.0); + SetSkill(SkillName.Inscribe, 120.0); + SetSkill(SkillName.Magery, 120.0); + SetSkill(SkillName.MagicResist, 120.0); + SetSkill(SkillName.Wrestling, 120.0); + SetSkill(SkillName.Meditation, 120.0); + + AddItem(new Backpack()); + AddItem(new Sandals(0x455)); + AddItem(new BodySash(0x455)); + AddItem(new LongPants(0x455)); + } + + public Dimethro(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Dimethro"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078128); // You there! Wanna master hand to hand defense? Of course you do! + } + + 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 class Churchill : BaseCreature + { + [Constructible] + public Churchill() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Mace Fighting Instructor"; + BodyValue = 0x190; + Hue = 0x83EA; + HairItemID = 0x203C; + HairHue = 0x455; + + InitStats(100, 100, 25); + + SetSkill(SkillName.Anatomy, 120.0); + SetSkill(SkillName.Parry, 120.0); + SetSkill(SkillName.Healing, 120.0); + SetSkill(SkillName.Tactics, 120.0); + SetSkill(SkillName.Macing, 120.0); + SetSkill(SkillName.Focus, 120.0); + + AddItem(new Backpack()); + AddItem(new OrderShield()); + AddItem(new WarMace()); + + Item item; + + item = new PlateLegs(); + item.Hue = 0x966; + AddItem(item); + + item = new PlateGloves(); + item.Hue = 0x966; + AddItem(item); + + item = new PlateGorget(); + item.Hue = 0x966; + AddItem(item); + + item = new PlateChest(); + item.Hue = 0x966; + AddItem(item); + + item = new PlateArms(); + item.Hue = 0x966; + AddItem(item); + } + + public Churchill(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Churchill"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078141); // Don't listen to Jockles. Real warriors wield mace weapons! + } + + 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 class Robyn : Bowyer + { + [Constructible] + public Robyn() + { + Title = "the Archery Instructor"; + BodyValue = 0x191; + Hue = 0x83EA; + HairItemID = 0x203C; + HairHue = 0x47D; + Female = true; + + InitStats(100, 100, 25); + + SetSkill(SkillName.Anatomy, 120.0); + SetSkill(SkillName.Parry, 120.0); + SetSkill(SkillName.Fletching, 120.0); + SetSkill(SkillName.Healing, 120.0); + SetSkill(SkillName.Tactics, 120.0); + SetSkill(SkillName.Archery, 120.0); + SetSkill(SkillName.Focus, 120.0); + } + + public Robyn(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "Robyn"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078202); // Archery requires a steady aim and dexterous fingers. + } + + public override void InitOutfit() + { + AddItem(new Backpack()); + AddItem(new Boots(0x592)); + AddItem(new Cloak(0x592)); + AddItem(new Bandana(0x592)); + AddItem(new CompositeBow()); + + Item item; + + item = new StuddedLegs(); + item.Hue = 0x592; + AddItem(item); + + item = new StuddedGloves(); + item.Hue = 0x592; + AddItem(item); + + item = new StuddedGorget(); + item.Hue = 0x592; + AddItem(item); + + item = new StuddedChest(); + item.Hue = 0x592; + AddItem(item); + + item = new StuddedArms(); + item.Hue = 0x592; + AddItem(item); + } + + 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 class Recaro : BaseCreature + { + [Constructible] + public Recaro() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Fencer Instructor"; + BodyValue = 0x190; + Hue = 0x83EA; + HairItemID = 0x203C; + HairHue = 0x455; + FacialHairItemID = 0x204D; + FacialHairHue = 0x455; + + InitStats(100, 100, 25); + + SetSkill(SkillName.Anatomy, 120.0); + SetSkill(SkillName.Parry, 120.0); + SetSkill(SkillName.Healing, 120.0); + SetSkill(SkillName.Tactics, 120.0); + SetSkill(SkillName.Fencing, 120.0); + SetSkill(SkillName.Focus, 120.0); + + AddItem(new Backpack()); + AddItem(new Shoes(0x455)); + AddItem(new WarFork()); + + Item item; + + item = new StuddedLegs(); + item.Hue = 0x455; + AddItem(item); + + item = new StuddedGloves(); + item.Hue = 0x455; + AddItem(item); + + item = new StuddedGorget(); + item.Hue = 0x455; + AddItem(item); + + item = new StuddedChest(); + item.Hue = 0x455; + AddItem(item); + + item = new StuddedArms(); + item.Hue = 0x455; + AddItem(item); + } + + public Recaro(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Recaro"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + 1078187 + ); // The art of fencing requires a dexterous hand, a quick wit and fleet feet. + } + + 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 class AldenArmstrong : BaseCreature + { + [Constructible] + public AldenArmstrong() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Tactics Instructor"; + BodyValue = 0x190; + Hue = 0x83EA; + HairItemID = 0x203B; + HairHue = 0x44E; + + InitStats(100, 100, 25); + + SetSkill(SkillName.Anatomy, 120.0); + SetSkill(SkillName.Parry, 120.0); + SetSkill(SkillName.Healing, 120.0); + SetSkill(SkillName.Tactics, 120.0); + SetSkill(SkillName.Swords, 120.0); + SetSkill(SkillName.Focus, 120.0); + + AddItem(new Backpack()); + AddItem(new Shoes()); + AddItem(new StuddedLegs()); + AddItem(new StuddedGloves()); + AddItem(new StuddedGorget()); + AddItem(new StuddedChest()); + AddItem(new StuddedArms()); + AddItem(new Katana()); + } + + public AldenArmstrong(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Alden Armstrong"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + 1078136 + ); // There is an art to slaying your enemies swiftly. It's called tactics, and I can teach it to you. + } + + 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 class Jockles : BaseCreature + { + [Constructible] + public Jockles() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Swordsmanship Instructor"; + BodyValue = 0x190; + Hue = 0x83FA; + HairItemID = 0x203C; + HairHue = 0x8A7; + + InitStats(100, 100, 25); + + SetSkill(SkillName.Anatomy, 120.0); + SetSkill(SkillName.Parry, 120.0); + SetSkill(SkillName.Healing, 120.0); + SetSkill(SkillName.Tactics, 120.0); + SetSkill(SkillName.Swords, 120.0); + SetSkill(SkillName.Focus, 120.0); + + AddItem(new Backpack()); + AddItem(new Broadsword()); + AddItem(new PlateChest()); + AddItem(new PlateLegs()); + AddItem(new PlateGloves()); + AddItem(new PlateArms()); + AddItem(new PlateGorget()); + AddItem(new OrderShield()); + } + + public Jockles(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Jockles"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078135); // Talk to me to learn the way of the blade. + } + + 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 class TylAriadne : BaseCreature + { + [Constructible] + public TylAriadne() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Parrying Instructor"; + BodyValue = 0x190; + Hue = 0x8374; + HairItemID = 0; + + InitStats(100, 100, 25); + + SetSkill(SkillName.Anatomy, 120.0); + SetSkill(SkillName.Parry, 120.0); + SetSkill(SkillName.Healing, 120.0); + SetSkill(SkillName.Tactics, 120.0); + SetSkill(SkillName.Swords, 120.0); + SetSkill(SkillName.Meditation, 120.0); + SetSkill(SkillName.Focus, 120.0); + + AddItem(new Backpack()); + AddItem(new ElvenBoots(0x96D)); + + Item item; + + item = new StuddedLegs(); + item.Hue = 0x96D; + AddItem(item); + + item = new StuddedGloves(); + item.Hue = 0x96D; + AddItem(item); + + item = new StuddedGorget(); + item.Hue = 0x96D; + AddItem(item); + + item = new StuddedChest(); + item.Hue = 0x96D; + AddItem(item); + + item = new StuddedArms(); + item.Hue = 0x96D; + AddItem(item); + + item = new DiamondMace(); + item.Hue = 0x96D; + AddItem(item); + } + + public TylAriadne(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Tyl Ariadne"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078140); // Want to learn how to parry blows? + } + + 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 class Alefian : BaseCreature + { + [Constructible] + public Alefian() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Resisting Spells Instructor"; + BodyValue = 0x190; + Hue = 0x83EA; + HairItemID = 0x203D; + HairHue = 0x457; + + InitStats(100, 100, 25); + + SetSkill(SkillName.EvalInt, 120.0); + SetSkill(SkillName.Inscribe, 120.0); + SetSkill(SkillName.Magery, 120.0); + SetSkill(SkillName.MagicResist, 120.0); + SetSkill(SkillName.Wrestling, 120.0); + SetSkill(SkillName.Meditation, 120.0); + + AddItem(new Backpack()); + AddItem(new Robe()); + AddItem(new Sandals()); + } + + public Alefian(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Alefian"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078130); // A mage should learn how to resist spells. + } + + 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 class Gustar : BaseCreature + { + [Constructible] + public Gustar() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Meditation Instructor"; + BodyValue = 0x190; + Hue = 0x83F5; + HairItemID = 0x203B; + HairHue = 0x455; + + InitStats(100, 100, 25); + + SetSkill(SkillName.EvalInt, 120.0); + SetSkill(SkillName.Inscribe, 120.0); + SetSkill(SkillName.Magery, 120.0); + SetSkill(SkillName.MagicResist, 120.0); + SetSkill(SkillName.Wrestling, 120.0); + SetSkill(SkillName.Meditation, 120.0); + + AddItem(new Backpack()); + AddItem(new GustarShroud()); + AddItem(new Sandals()); + } + + public Gustar(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Gustar"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078126); // Meditation allows a mage to replenish mana quickly. I can teach you. + } + + 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 class GustarShroud : BaseOuterTorso + { + [Constructible] + public GustarShroud() : base(0x2684) => Hue = 0x479; + + public GustarShroud(Serial serial) : base(serial) + { + } + + public override string DefaultName => " "; + + 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 class Jillian : BaseCreature + { + [Constructible] + public Jillian() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Inscription Instructor"; + BodyValue = 0x191; + Female = true; + Hue = 0x83EA; + HairItemID = 0x203D; + HairHue = 0x455; + + InitStats(100, 100, 25); + + SetSkill(SkillName.EvalInt, 120.0); + SetSkill(SkillName.Inscribe, 120.0); + SetSkill(SkillName.Magery, 120.0); + SetSkill(SkillName.MagicResist, 120.0); + SetSkill(SkillName.Wrestling, 120.0); + SetSkill(SkillName.Meditation, 120.0); + + AddItem(new Backpack()); + AddItem(new Robe(0x479)); + AddItem(new Sandals()); + } + + public Jillian(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Jillian"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078129); // I can teach you how to scribe magic scrolls. + } + + 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 class Kaelynna : BaseCreature + { + [Constructible] + public Kaelynna() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Magery Instructor"; + BodyValue = 0x191; + Female = true; + Hue = 0x83EA; + HairItemID = 0x203C; + HairHue = 0x47D; + + InitStats(100, 100, 25); + + SetSkill(SkillName.EvalInt, 120.0); + SetSkill(SkillName.Inscribe, 120.0); + SetSkill(SkillName.Magery, 120.0); + SetSkill(SkillName.MagicResist, 120.0); + SetSkill(SkillName.Wrestling, 120.0); + SetSkill(SkillName.Meditation, 120.0); + + AddItem(new Backpack()); + AddItem(new Robe(0x592)); + AddItem(new Sandals()); + } + + public Kaelynna(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Kaelynna"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078125); // Want to unlock the secrets of magery? + } + + 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 class Mithneral : BaseCreature + { + [Constructible] + public Mithneral() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Evaluating Intelligence Instructor"; + BodyValue = 0x190; + Hue = 0x83EA; + HairItemID = 0x203C; + HairHue = 0x455; + + InitStats(100, 100, 25); + + SetSkill(SkillName.EvalInt, 120.0); + SetSkill(SkillName.Inscribe, 120.0); + SetSkill(SkillName.Magery, 120.0); + SetSkill(SkillName.MagicResist, 120.0); + SetSkill(SkillName.Wrestling, 120.0); + SetSkill(SkillName.Meditation, 120.0); + + AddItem(new Backpack()); + AddItem(new Sandals()); + + Item item; + + item = new GustarShroud(); + item.Hue = 0x51C; + AddItem(item); + } + + public Mithneral(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Mithneral"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078127); // Want to maximize your spell damage? I have a scholarly task for you! + } + + 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 class AmeliaYoungstone : Tinker + { + [Constructible] + public AmeliaYoungstone() + { + Title = "the Tinkering Instructor"; + BodyValue = 0x191; + Female = true; + Hue = 0x83EA; + HairItemID = 0x203D; + HairHue = 0x46C; + + InitStats(100, 100, 25); + + SetSkill(SkillName.ArmsLore, 120.0); + SetSkill(SkillName.Blacksmith, 120.0); + SetSkill(SkillName.Magery, 120.0); + SetSkill(SkillName.Tactics, 120.0); + SetSkill(SkillName.Swords, 120.0); + SetSkill(SkillName.Tinkering, 120.0); + SetSkill(SkillName.Mining, 120.0); + } + + public AmeliaYoungstone(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "Amelia Youngstone"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078123); // Tinkering is very useful for a blacksmith. You can make your own tools. + } + + public override void InitOutfit() + { + AddItem(new Backpack()); + AddItem(new Sandals()); + AddItem(new Doublet()); + AddItem(new ShortPants()); + AddItem(new HalfApron(0x8AB)); + } + + 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 class AndreasVesalius : BaseCreature + { + [Constructible] + public AndreasVesalius() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Anatomy Instructor"; + BodyValue = 0x190; + Hue = 0x83EC; + HairItemID = 0x203C; + HairHue = 0x477; + FacialHairItemID = 0x203E; + FacialHairHue = 0x477; + + InitStats(100, 100, 25); + + SetSkill(SkillName.Anatomy, 120.0); + SetSkill(SkillName.Parry, 120.0); + SetSkill(SkillName.Healing, 120.0); + SetSkill(SkillName.Tactics, 120.0); + SetSkill(SkillName.Swords, 120.0); + SetSkill(SkillName.Focus, 120.0); + + AddItem(new Backpack()); + AddItem(new Boots()); + AddItem(new BlackStaff()); + AddItem(new LongPants()); + AddItem(new Tunic(0x66D)); + } + + public AndreasVesalius(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Andreas Vesalius"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078138); // Learning of the body will allow you to excel in combat. + } + + 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 class Avicenna : BaseCreature + { + [Constructible] + public Avicenna() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Healing Instructor"; + BodyValue = 0x190; + Hue = 0x83EA; + HairItemID = 0x203B; + HairHue = 0x477; + + InitStats(100, 100, 25); + + SetSkill(SkillName.Anatomy, 120.0); + SetSkill(SkillName.Parry, 120.0); + SetSkill(SkillName.Healing, 120.0); + SetSkill(SkillName.Tactics, 120.0); + SetSkill(SkillName.Swords, 120.0); + SetSkill(SkillName.Focus, 120.0); + + AddItem(new Backpack()); + AddItem(new Robe(0x66D)); + AddItem(new Boots()); + AddItem(new GnarledStaff()); + } + + public Avicenna(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Avicenna"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078137); // A warrior needs to learn how to apply bandages to wounds. + } + + 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 class SarsmeaSmythe : BaseCreature + { + [Constructible] + public SarsmeaSmythe() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Focus Instructor"; + BodyValue = 0x191; + Female = true; + Hue = 0x83EA; + HairItemID = 0x203C; + HairHue = 0x456; + + InitStats(100, 100, 25); + + SetSkill(SkillName.Anatomy, 120.0); + SetSkill(SkillName.Parry, 120.0); + SetSkill(SkillName.Healing, 120.0); + SetSkill(SkillName.Tactics, 120.0); + SetSkill(SkillName.Swords, 120.0); + SetSkill(SkillName.Focus, 120.0); + + AddItem(new Backpack()); + AddItem(new ThighBoots()); + AddItem(new StuddedGorget()); + AddItem(new LeatherLegs()); + AddItem(new FemaleLeatherChest()); + AddItem(new StuddedGloves()); + AddItem(new LeatherNinjaBelt()); + AddItem(new LightPlateJingasa()); + } + + public SarsmeaSmythe(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Sarsmea Smythe"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078139); // Know yourself, and you will become a true warrior. + } + + 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 class Ryuichi : BaseVendor + { + private readonly List m_SBInfos = new List(); + + [Constructible] + public Ryuichi() + : base("the Ninjitsu Instructor") + { + Hue = 0x8403; + + SetSkill(SkillName.Hiding, 120.0); + SetSkill(SkillName.Tactics, 120.0); + SetSkill(SkillName.Tracking, 120.0); + SetSkill(SkillName.Fencing, 120.0); + SetSkill(SkillName.Stealth, 120.0); + SetSkill(SkillName.Ninjitsu, 120.0); + } + + public Ryuichi(Serial serial) + : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override string DefaultName => "Ryuichi"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078155); // I can teach you Ninjitsu. The Art of Stealth. + } + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBNinja()); + } + + public override bool GetGender() => false; + + public override void InitOutfit() + { + HairItemID = 0x203B; + HairHue = 0x455; + + AddItem(new SamuraiTabi()); + AddItem(new LeatherNinjaPants()); + AddItem(new LeatherNinjaMitts()); + AddItem(new LeatherNinjaHood()); + AddItem(new LeatherNinjaJacket()); + AddItem(new LeatherNinjaBelt()); + + PackGold(100, 200); + } + + 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 class Chiyo : BaseCreature + { + [Constructible] + public Chiyo() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Hiding Instructor"; + BodyValue = 0xF7; + + InitStats(100, 100, 25); + + SetSkill(SkillName.Hiding, 120.0); + SetSkill(SkillName.Tactics, 120.0); + SetSkill(SkillName.Tracking, 120.0); + SetSkill(SkillName.Fencing, 120.0); + SetSkill(SkillName.Stealth, 120.0); + SetSkill(SkillName.Ninjitsu, 120.0); + } + + public Chiyo(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Chiyo"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078165); // To be undetected means you cannot be harmed. + } + + 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 class Jun : BaseCreature + { + [Constructible] + public Jun() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Stealth Instructor"; + BodyValue = 0x190; + Hue = 0x8403; + HairItemID = 0x203B; + HairHue = 0x455; + + InitStats(100, 100, 25); + + SetSkill(SkillName.Hiding, 120.0); + SetSkill(SkillName.Tactics, 120.0); + SetSkill(SkillName.Tracking, 120.0); + SetSkill(SkillName.Fencing, 120.0); + SetSkill(SkillName.Stealth, 120.0); + SetSkill(SkillName.Ninjitsu, 120.0); + + AddItem(new Backpack()); + AddItem(new SamuraiTabi()); + AddItem(new LeatherNinjaPants()); + AddItem(new LeatherNinjaMitts()); + AddItem(new LeatherNinjaHood()); + AddItem(new LeatherNinjaJacket()); + AddItem(new LeatherNinjaBelt()); + } + + public Jun(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Jun"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078175); // Walk Silently. Remain unseen. I can teach you. + } + + 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 class Walker : BaseCreature + { + [Constructible] + public Walker() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Tracking Instructor"; + BodyValue = 0x190; + Hue = 0x83EA; + HairItemID = 0x203B; + HairHue = 0x47D; + FacialHairItemID = 0x204B; + FacialHairHue = 0x47D; + + InitStats(100, 100, 25); + + SetSkill(SkillName.Hiding, 120.0); + SetSkill(SkillName.Tactics, 120.0); + SetSkill(SkillName.Tracking, 120.0); + SetSkill(SkillName.Fencing, 120.0); + SetSkill(SkillName.Wrestling, 120.0); + SetSkill(SkillName.Stealth, 120.0); + SetSkill(SkillName.Ninjitsu, 120.0); + + AddItem(new Backpack()); + AddItem(new Boots(0x455)); + AddItem(new LongPants(0x455)); + AddItem(new FancyShirt(0x47D)); + AddItem(new FloppyHat(0x455)); + } + + public Walker(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Walker"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1078213, // I don't sleep. I wait. + 1078212, // There is no theory of evolution. Just a list of creatures I allow to live. + 1078214 + ) + ); // I can lead a horse to water and make it drink. + } + + 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 class Hamato : BaseVendor + { + private readonly List m_SBInfos = new List(); + + [Constructible] + public Hamato() + : base("the Bushido Instructor") + { + Hue = 0x8403; + + SetSkill(SkillName.Anatomy, 120.0); + SetSkill(SkillName.Parry, 120.0); + SetSkill(SkillName.Healing, 120.0); + SetSkill(SkillName.Tactics, 120.0); + SetSkill(SkillName.Swords, 120.0); + SetSkill(SkillName.Bushido, 120.0); + } + + public Hamato(Serial serial) + : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override string DefaultName => "Hamato"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078134); // Seek me to learn the way of the samurai. + } + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBSamurai()); + } + + public override bool GetGender() => false; + + public override void InitOutfit() + { + HairItemID = 0x203D; + HairHue = 0x497; + + AddItem(new Backpack()); + AddItem(new NoDachi()); + AddItem(new NinjaTabi()); + AddItem(new PlateSuneate()); + AddItem(new LightPlateJingasa()); + AddItem(new LeatherDo()); + AddItem(new LeatherHiroSode()); + + PackGold(100, 200); + } + + 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 class Mulcivikh : Mage + { + [Constructible] + public Mulcivikh() + { + Title = "the Necromancy Instructor"; + BodyValue = 0x190; + Hue = 0x83EA; + HairItemID = 0x203D; + HairHue = 0x457; + + InitStats(100, 100, 25); + + SetSkill(SkillName.Magery, 120.0); + SetSkill(SkillName.MagicResist, 120.0); + SetSkill(SkillName.SpiritSpeak, 120.0); + SetSkill(SkillName.Swords, 120.0); + SetSkill(SkillName.Meditation, 120.0); + SetSkill(SkillName.Necromancy, 120.0); + } + + public Mulcivikh(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "Mulcivikh"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078131); // Allured by dark magic, aren't you? + } + + public override void InitOutfit() + { + AddItem(new Backpack()); + AddItem(new Sandals(0x8FD)); + AddItem(new BoneHelm()); + + Item item; + + item = new LeatherLegs(); + item.Hue = 0x2C3; + AddItem(item); + + item = new LeatherGloves(); + item.Hue = 0x2C3; + AddItem(item); + + item = new LeatherGorget(); + item.Hue = 0x2C3; + AddItem(item); + + item = new LeatherChest(); + item.Hue = 0x2C3; + AddItem(item); + + item = new LeatherArms(); + item.Hue = 0x2C3; + AddItem(item); + } + + 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 class Morganna : Mage + { + [Constructible] + public Morganna() + { + Title = "the Spirit Speak Instructor"; + BodyValue = 0x191; + Female = true; + Hue = 0x83EA; + HairItemID = 0x203C; + HairHue = 0x455; + + InitStats(100, 100, 25); + + SetSkill(SkillName.Magery, 120.0); + SetSkill(SkillName.MagicResist, 120.0); + SetSkill(SkillName.SpiritSpeak, 120.0); + SetSkill(SkillName.Swords, 120.0); + SetSkill(SkillName.Meditation, 120.0); + SetSkill(SkillName.Necromancy, 120.0); + } + + public Morganna(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "Morganna"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078132); // Want to learn how to channel the supernatural? + } + + public override void InitOutfit() + { + AddItem(new Backpack()); + AddItem(new Sandals()); + AddItem(new Robe(0x47D)); + AddItem(new SkullCap(0x455)); + } + + 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 class JacobWaltz : BaseCreature + { + [Constructible] + public JacobWaltz() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Miner Instructor"; + BodyValue = 0x190; + Hue = 0x83EA; + HairItemID = 0x2048; + HairHue = 0x44E; + FacialHairItemID = 0x204D; + FacialHairHue = 0x44E; + + InitStats(100, 100, 25); + + SetSkill(SkillName.ArmsLore, 120.0); + SetSkill(SkillName.Blacksmith, 120.0); + SetSkill(SkillName.Magery, 120.0); + SetSkill(SkillName.Tactics, 120.0); + SetSkill(SkillName.Tinkering, 120.0); + SetSkill(SkillName.Swords, 120.0); + SetSkill(SkillName.Mining, 120.0); + + AddItem(new Backpack()); + AddItem(new Pickaxe()); + AddItem(new Boots()); + AddItem(new WideBrimHat(0x966)); + AddItem(new ShortPants(0x370)); + AddItem(new Shirt(0x966)); + AddItem(new HalfApron(0x1BB)); + } + + public JacobWaltz(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Jacob Waltz"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078124); // You there! I can use some help mining these rocks! + } + + 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 class GeorgeHephaestus : Blacksmith + { + [Constructible] + public GeorgeHephaestus() + { + Title = "the Blacksmith Instructor"; + BodyValue = 0x190; + Hue = 0x83EA; + HairItemID = 0x203B; + HairHue = 0x47B; + + InitStats(100, 100, 25); + + SetSkill(SkillName.ArmsLore, 120.0); + SetSkill(SkillName.Blacksmith, 120.0); + SetSkill(SkillName.Magery, 120.0); + SetSkill(SkillName.Tactics, 120.0); + SetSkill(SkillName.Tinkering, 120.0); + SetSkill(SkillName.Swords, 120.0); + SetSkill(SkillName.Mining, 120.0); + } + + public GeorgeHephaestus(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "George Hephaestus"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1078122); // Wanna learn how to make powerful weapons and armor? Talk to me. + } + + public override void InitOutfit() + { + AddItem(new Backpack()); + AddItem(new Boots(0x973)); + AddItem(new LongPants()); + AddItem(new Bascinet()); + AddItem(new FullApron(0x8AB)); + + Item item; + + item = new SmithHammer(); + item.Hue = 0x8AB; + AddItem(item); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Definitions/NewHavenTraining.cs b/Projects/UOContent/Engines/MLQuests/Definitions/NewHavenTraining.cs index 518a8556d..6d8f3a6d6 100644 --- a/Projects/UOContent/Engines/MLQuests/Definitions/NewHavenTraining.cs +++ b/Projects/UOContent/Engines/MLQuests/Definitions/NewHavenTraining.cs @@ -1,1020 +1,1065 @@ -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; -using Server.Engines.Spawners; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Definitions -{ - public class SplitEnds : MLQuest - { - public SplitEnds() - { - Activated = true; - HasRestartDelay = true; - Title = 1075506; // Split Ends - Description = - 1075507; // *sighs* I think bowcrafting is a might beyond my talents. Say there, you look a bit more confident with tools. Can I persuade thee to make a few arrows? You could have my satchel in return... 'tis useless to me! You'll need a fletching kit to start, some feathers, and a few arrow shafts. Just use the fletching kit while you have the other things, and I'm sure you'll figure out the rest. - RefusalMessage = 1075508; // Oh. Well. I'll just keep trying alone, I suppose... - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - CompletionMessage = 1072272; // Thanks for helping me out. Here's the reward I promised you. - - Objectives.Add(new CollectObjective(20, typeof(Arrow), 1023902)); // arrow - - Rewards.Add(new ItemReward(1074282, typeof(AndricSatchel))); // Craftsmans's Satchel - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Andric"), new Point3D(3742, 2582, 40), Map.Trammel); - } - } - - public class IShotAnArrowIntoTheAir : MLQuest - { - public IShotAnArrowIntoTheAir() - { - Activated = true; - Title = 1075486; // I Shot an Arrow Into the Air... - Description = - 1075482; // Truth be told, the only way to get a feel for the bow is to shoot one and there's no better practice target than a sheep. If ye can shoot ten of them I think ye will have proven yer abilities. Just grab a bow and make sure to take enough ammunition. Bows tend to use arrows and crossbows use bolts. Ye can buy 'em or have someone craft 'em. How about it then? Come back here when ye are done. - RefusalMessage = 1075483; // Fair enough, the bow isn't for everyone. Good day then. - InProgressMessage = 1075484; // Return once ye have killed ten sheep with a bow and not a moment before. - - Objectives.Add(new KillObjective(10, new[] { typeof(Sheep) }, 1018270)); // sheep - - Rewards.Add(ItemReward.BagOfTrinkets); - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Kashiel"), new Point3D(3744, 2586, 40), Map.Trammel); - } - } - - public class BakersDozen : MLQuest - { - public BakersDozen() - { - Activated = true; - HasRestartDelay = true; - Title = 1075478; // Baker's Dozen - Description = - 1075479; // You there! Do you know much about the ways of cooking? If you help me out, I'll show you a thing or two about how it's done. Bring me some cookie mix, about 5 batches will do it, and I will reward you. Although, I don't think you can buy it, you can make some in a snap! First get a rolling pin or frying pan or even a flour sifter. Then you mix one pinch of flour with some water and you've got some dough! Take that dough and add one dollop of honey and you've got sweet dough. add one more drop of honey and you've got cookie mix. See? Nothing to it! Now get to work! - RefusalMessage = - 1075480; // Argh, I absolutely must have more of these 'cookies!' Come back if you change your mind. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - CompletionMessage = 1075481; // Thank you! I haven't been this excited about food in months! - - Objectives.Add(new CollectObjective(5, typeof(CookieMix), 1024159)); // cookie mix - - Rewards.Add(new ItemReward(1074282, typeof(AsandosSatchel))); // Craftsmans's Satchel - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Asandos"), new Point3D(3505, 2513, 27), Map.Trammel); - } - } - - public class AStitchInTime : MLQuest - { - public AStitchInTime() - { - Activated = true; - HasRestartDelay = true; - Title = 1075523; // A Stitch in Time - Description = - 1075522; // Oh how I wish I had a fancy dress like the noble ladies of Castle British! I don't have much... but I have a few trinkets I might trade for it. It would mean the world to me to go to a fancy ball and dance the night away. Oh, and I could tell you how to make one! You just need to use your sewing kit on enough cut cloth, that's all. - RefusalMessage = 1075526; // Won't you reconsider? It'd mean the world to me, it would! - InProgressMessage = - 1075527; // Hello again! Do you need anything? You may want to visit the tailor's shop for cloth and a sewing kit, if you don't already have them. - CompletionMessage = - 1075528; // It's gorgeous! I only have a few things to give you in return, but I can't thank you enough! Maybe I'll even catch Uzeraan's eye at the, er, *blushes* I mean, I can't wait to wear it to the next town dance! - - Objectives.Add(new CollectObjective(1, typeof(FancyDress), 1027935)); // fancy dress - - Rewards.Add(new ItemReward(1075524, typeof(AnOldRing))); // an old ring - Rewards.Add(new ItemReward(1075525, typeof(AnOldNecklace))); // an old necklace - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Clairesse"), new Point3D(3492, 2546, 20), Map.Trammel); - } - } - - public class BatteredBucklers : MLQuest - { - public BatteredBucklers() - { - Activated = true; - HasRestartDelay = true; - Title = 1075511; // Battered Bucklers - Description = - 1075512; // Hey there! Yeah... you! Ya' any good with a hammer? Tell ya what, if yer thinking about tryin' some metal work, and have a bit of skill, I can show ya how to bend it into shape. Just get some of those ingots there, and grab a hammer and use it over here at this forge. I need a few more bucklers hammered out to fill this here order with... hmmm about ten more. that'll give some taste of how to work the metal. - RefusalMessage = - 1075514; // Not enough muscle on yer bones to use it? hmph, probably afraid of the sparks markin' up yer loverly skin... to good for some honest labor... ha!... off with ya! - InProgressMessage = 1075515; // Come On! Whats that... a bucket? We need ten bucklers... not spitoons. - CompletionMessage = 1075516; // Thanks for the help. Here's something for ya to remember me by. - - Objectives.Add(new CollectObjective(10, typeof(Buckler), 1027027)); // buckler - - Rewards.Add(new ItemReward(1074282, typeof(GervisSatchel))); // Craftsmans's Satchel - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Gervis"), new Point3D(3505, 2749, 0), Map.Trammel); - } - } - - public class MoreOrePlease : MLQuest - { - public MoreOrePlease() - { - Activated = true; - HasRestartDelay = true; - Title = 1075530; // More Ore Please - Description = - 1075529; // Have a pickaxe? My supplier is late and I need some iron ore so I can complete a bulk order for another merchant. If you can get me some soon I'll pay you double what it's worth on the market. Just find a cave or mountainside and try to use your pickaxe there, maybe you'll strike a good vein! 5 large pieces should do it. - RefusalMessage = - 1075531; // Not feeling strong enough today? Its alright, I didn't need a bucket of rocks anyway. - InProgressMessage = 1075532; // Hmmm� we need some more Ore. Try finding a mountain or cave, and give it a whack. - CompletionMessage = - 1075533; // I see you found a good vien! Great! This will help get this order out on time. Good work! - - Objectives.Add(new InternalObjective()); - - Rewards.Add(new ItemReward(1074282, typeof(MuggSatchel))); // Craftsmans's Satchel - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Mugg"), new Point3D(3507, 2747, 0), Map.Trammel); - } - - private class InternalObjective : CollectObjective - { - // Any type of ore is allowed - public InternalObjective() - : base(5, typeof(BaseOre), 1026585) // ore - { - } - - public override bool CheckItem(Item item) => item.ItemID == 6585; - } - } - - public class ComfortableSeating : MLQuest - { - public ComfortableSeating() - { - Activated = true; - HasRestartDelay = true; - Title = 1075517; // Comfortable Seating - Description = - 1075518; // Hail friend, hast thou a moment? A mishap with a saw hath left me in a sorry state, for it shall be a while before I canst return to carpentry. In the meantime, I need a comfortable chair that I may rest. Could thou craft a straw chair? Only a tool, such as a dovetail saw, a few boards, and some skill as a carpenter is needed. Remember, this is a piece of furniture, so please pay attention to detail. - RefusalMessage = 1072687; // I quite understand your reluctance. If you reconsider, I'll be here. - InProgressMessage = 1075509; // Is all going well? I look forward to the simple comforts in my very own home. - CompletionMessage = 1074720; // This is perfect! - - Objectives.Add(new CollectObjective(1, typeof(BambooChair), "straw chair")); - - Rewards.Add(new ItemReward(1074282, typeof(LowelSatchel))); // Craftsmans's Satchel - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Lowel"), new Point3D(3440, 2645, 27), Map.Trammel); - } - } - - public class ThePenIsMightier : MLQuest - { - public ThePenIsMightier() - { - Activated = true; - HasRestartDelay = true; - Title = 1075542; // The Pen is Mightier - Description = - 1075543; // Do you know anything about 'Inscription?' I've been trying to get my hands on some hand crafted Recall scrolls for a while now, and I could really use some help. I don't have a scribe's pen, let alone a spellbook with Recall in it, or blank scrolls, so there's no way I can do it on my own. How about you though? I could trade you one of my old leather bound books for some. - RefusalMessage = - 1075546; // Hmm, thought I had your interest there for a moment. It's not everyday you see a book made from real daemon skin, after all! - InProgressMessage = - 1075547; // Inscribing... yes, you'll need a scribe's pen, some reagents, some blank scroll, and of course your own magery book. You might want to visit the magery shop if you're lacking some materials. - CompletionMessage = - 1075548; // Ha! Finally! I've had a rune to the waterfalls near Justice Isle that I've been wanting to use for the longest time, and now I can visit at last. Here's that book I promised you... glad to be rid of it, to be honest. - - Objectives.Add(new CollectObjective(5, typeof(RecallScroll), "recall scroll")); - - Rewards.Add(new ItemReward(1075545, typeof(RedLeatherBook))); // a book bound in red leather - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Lyle"), new Point3D(3503, 2584, 14), Map.Trammel); - } - } - - public class AClockworkPuzzle : MLQuest - { - public AClockworkPuzzle() - { - Activated = true; - HasRestartDelay = true; - Title = 1075535; // A clockwork puzzle - Description = - 1075534; // 'Tis a riddle, you see! "What kind of clock is only right twice per day? A broken one!" *laughs heartily* Ah, yes *wipes eye*, that's one of my favorites! Ah... to business. Could you fashion me some clock parts? I wish my own clocks to be right all the day long! You'll need some tinker's tools and some iron ingots, I think, but from there it should be just a matter of working the metal. - RefusalMessage = 1072981; // Or perhaps you'd rather not. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - CompletionMessage = 1075536; // Wonderful! Tick tock, tick tock, soon all shall be well with grandfather's clock! - - Objectives.Add(new CollectObjective(5, typeof(ClockParts), 1024175)); // clock parts - - Rewards.Add(new ItemReward(1074282, typeof(NibbetSatchel))); // Craftsmans's Satchel - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Nibbet"), new Point3D(3459, 2525, 53), Map.Trammel); - } - } - - public class DeliciousFishes : MLQuest - { - public DeliciousFishes() - { - Activated = true; - HasRestartDelay = true; - Title = 1075555; // Delicious Fishes - Description = - 1075556; // Ello there, looking for a good place on the dock to fish? I like the southeast corner meself. What's that? Oh, no, *sighs* me pole is broken and in for fixin'. My grandpappy gave me that pole, means a lot you see. Miss the taste of fish though... Oh say, since you're here, could you catch me a few fish? I can cook a mean fish steak, and I'll split 'em with you! But make sure it's one of the green kind, they're the best for seasoning! - RefusalMessage = - 1075558; // Ah, you're missin' out my friend, you're missing out. My peppercorn fishsteaks are famous on this little isle of ours! - InProgressMessage = - 1075559; // Eh? Find yerself a pole and get close to some water. Just toss the line on in and hopefully you won't snag someone's old boots! Remember, that's twenty of them green fish we'll be needin', so come back when you've got em, 'aight? - CompletionMessage = - 1075560; // Just a moment my friend, just a moment! *rummages in his pack* Here we are! My secret blend of peppers always does the trick, never fails, no not once. These'll fill you up much faster than that tripe they sell in the market! - - Objectives.Add(new CollectObjective(5, typeof(Fish), 1022508)); // fish - - Rewards.Add(new ItemReward(1075557, typeof(PeppercornFishsteak), 3)); // peppercorn fishsteak - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Norton"), new Point3D(3502, 2603, 1), Map.Trammel); - } - } - - public class FleeAndFatigue : MLQuest - { - public FleeAndFatigue() - { - Activated = true; - HasRestartDelay = true; - Title = 1075487; // Flee and Fatigue - Description = - 1075488; // I was just *coughs* ambushed near the moongate. *wheeze* Why do I pay my taxes? Where were the guards? You then, you an Alchemist? If you can make me a few Refresh potions, I will be back on my feet and can give those lizards the what for! Find a mortar and pestle, a good amount of black pearl, and ten empty bottles to store the finished potions in. Just use the mortar and pestle and the rest will surely come to you. When you return, the favor will be repaid. - RefusalMessage = - 1075489; // Fine fine, off with *cough* thee then! The next time you see a lizardman though, give him a whallop for me, eh? - InProgressMessage = - 1075490; // Just remember you need to use your mortar and pestle while you have empty bottles and some black pearl. Refresh potions are what I need. - CompletionMessage = - 1075491; // *glug* *glug* Ahh... Yes! Yes! That feels great! Those lizardmen will never know what hit 'em! Here, take this, I can get more from the lizards. - - Objectives.Add(new CollectObjective(10, typeof(RefreshPotion), "refresh potions")); - - Rewards.Add(new ItemReward(1074282, typeof(SadrahSatchel))); // Craftsmans's Satchel - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Sadrah"), new Point3D(3742, 2731, 7), Map.Trammel); - } - } - - public class ChopChopOnTheDouble : MLQuest - { - public ChopChopOnTheDouble() - { - Activated = true; - HasRestartDelay = true; - Title = 1075537; // Chop Chop, On The Double! - Description = - 1075538; // That's right, move it! I need sixty logs on the double, and they need to be freshly cut! If you can get them to me fast I'll have your payment in your hands before you have the scent of pine out from beneath your nostrils. Just get a sharp axe and hack away at some of the trees in the land and your lumberjacking skill will rise in no time. - RefusalMessage = 1072981; // Or perhaps you'd rather not. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - CompletionMessage = - 1075539; // Ahhh! The smell of fresh cut lumber. And look at you, all strong and proud, as if you had done an honest days work! - - Objectives.Add(new CollectObjective(60, typeof(Log), 1027133)); // log - - Rewards.Add(new ItemReward(1074282, typeof(HargroveSatchel))); // Craftsmans's Satchel - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Hargrove"), new Point3D(3445, 2633, 28), Map.Trammel); - } - } - - public class Andric : BaseCreature - { - [Constructible] - public Andric() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the archer trainer"; - Race = Race.Human; - BodyValue = 0x190; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Archery, 60.0, 80.0); - - AddItem(new Backpack()); - - Item item; - - item = new LeatherChest(); - item.Hue = 0x1BB; - AddItem(item); - - item = new LeatherLegs(); - item.Hue = 0x6AD; - AddItem(item); - - item = new LeatherArms(); - item.Hue = 0x6AD; - AddItem(item); - - item = new LeatherGloves(); - item.Hue = 0x1BB; - AddItem(item); - - AddItem(new Boots(0x1BB)); - AddItem(new CompositeBow()); - } - - public Andric(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Andric"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074205, // Oh great adventurer, would you please assist a weak soul in need of aid? - 1074213)); // Hey buddy.� Looking for work? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Kashiel : BaseCreature - { - [Constructible] - public Kashiel() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the archer"; - Race = Race.Human; - BodyValue = 0x191; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Backpack()); - - Item item; - - item = new LeatherChest(); - item.Hue = 0x1BB; - AddItem(item); - - item = new LeatherLegs(); - item.Hue = 0x901; - AddItem(item); - - item = new LeatherArms(); - item.Hue = 0x901; - AddItem(item); - - item = new LeatherGloves(); - item.Hue = 0x1BB; - AddItem(item); - - AddItem(new Boots(0x1BB)); - AddItem(new CompositeBow()); - } - - public Kashiel(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "Kashiel"; - public override bool IsInvulnerable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Asandos : BaseCreature - { - [Constructible] - public Asandos() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the chef"; - Race = Race.Human; - BodyValue = 0x190; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Backpack()); - AddItem(new Boots(0x901)); - AddItem(new ShortPants()); - AddItem(new Shirt()); - AddItem(new Cap()); - AddItem(new HalfApron(0x28)); - } - - public Asandos(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Asandos"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074205, // Oh great adventurer, would you please assist a weak soul in need of aid? - 1074213)); // Hey buddy.� Looking for work? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - // [QuesterName( "Clarisse" )] // On OSI the gumps refer to her as this, different from actual name - public class Clairesse : BaseCreature - { - [Constructible] - public Clairesse() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the servant"; - Race = Race.Human; - BodyValue = 0x191; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Backpack()); - AddItem(new Shoes(Utility.RandomNeutralHue())); - AddItem(new PlainDress(0x3C9)); - } - - public Clairesse(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Clairesse"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074205, // Oh great adventurer, would you please assist a weak soul in need of aid? - 1074213)); // Hey buddy.� Looking for work? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Gervis : BaseCreature - { - [Constructible] - public Gervis() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the blacksmith trainer"; - Race = Race.Human; - BodyValue = 0x190; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Blacksmith, 60.0, 80.0); - - AddItem(new Backpack()); - AddItem(new Boots(0x3B3)); - AddItem(new ShortPants(0x1BB)); - AddItem(new Doublet(0x652)); - AddItem(new SmithHammer()); - - Item item; - - item = new LeatherGloves(); - item.Hue = 0x3B2; - AddItem(item); - } - - public Gervis(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Gervis"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074205, // Oh great adventurer, would you please assist a weak soul in need of aid? - 1074213, // Hey buddy.� Looking for work? - 1074211)); // I could use some help. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Mugg : BaseCreature - { - [Constructible] - public Mugg() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the miner"; - Race = Race.Human; - BodyValue = 0x190; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Backpack()); - AddItem(new Boots(0x901)); - AddItem(new ShortPants(0x3B3)); - AddItem(new Shirt(0x22B)); - AddItem(new HalfApron(0x5F1)); - AddItem(new SkullCap(0x177)); - AddItem(new Pickaxe()); - } - - public Mugg(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Mugg"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1074211); // I could use some help. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Lowel : BaseCreature - { - [Constructible] - public Lowel() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the carpenter"; - Race = Race.Human; - BodyValue = 0x190; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Backpack()); - AddItem(new Boots(0x543)); - AddItem(new ShortPants(0x758)); - AddItem(new FancyShirt(0x53A)); - AddItem(new HalfApron(0x6D2)); - } - - public Lowel(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Lowel"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074205, // Oh great adventurer, would you please assist a weak soul in need of aid? - 1074213)); // Hey buddy.� Looking for work? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Lyle : BaseCreature - { - [Constructible] - public Lyle() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the mage"; - Race = Race.Human; - BodyValue = 0x190; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Backpack()); - AddItem(new Robe(0x2FD)); - AddItem(new ThighBoots()); - } - - public Lyle(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Lyle"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074205, // Oh great adventurer, would you please assist a weak soul in need of aid? - 1074213)); // Hey buddy.� Looking for work? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Nibbet : BaseCreature - { - [Constructible] - public Nibbet() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the tinker"; - Race = Race.Human; - BodyValue = 0x190; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Backpack()); - AddItem(new Boots(0x591)); - AddItem(new ShortPants(0xF8)); - AddItem(new Shirt(0x2D)); - AddItem(new FullApron(0x288)); - } - - public Nibbet(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "Nibbet"; - public override bool IsInvulnerable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Norton : BaseCreature - { - [Constructible] - public Norton() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the fisher"; - Race = Race.Human; - BodyValue = 0x190; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Backpack()); - AddItem(new ThighBoots()); - AddItem(new LongPants(0x6C2)); - AddItem(new Shirt(0x11D)); - } - - public Norton(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Norton"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074205, // Oh great adventurer, would you please assist a weak soul in need of aid? - 1074213, // Hey buddy.� Looking for work? - 1074211)); // I could use some help. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Sadrah : BaseCreature - { - [Constructible] - public Sadrah() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the courier"; - Race = Race.Human; - BodyValue = 0x191; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Backpack()); - AddItem(new Boots(0x901)); - AddItem(new Skirt(0x52)); - AddItem(new Shirt(0x127)); - AddItem(new Cloak(0x65)); - AddItem(new Longsword()); - } - - public Sadrah(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Sadrah"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074205, // Oh great adventurer, would you please assist a weak soul in need of aid? - 1074213, // Hey buddy.� Looking for work? - 1074211)); // I could use some help. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Hargrove : BaseCreature - { - [Constructible] - public Hargrove() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Lumberjack"; - Race = Race.Human; - BodyValue = 0x190; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Backpack()); - AddItem(new Boots(0x901)); - AddItem(new StuddedLegs()); - AddItem(new Shirt(0x288)); - AddItem(new Bandana(0x20)); - AddItem(new BattleAxe()); - - Item item; - - item = new PlateGloves(); - item.Hue = 0x21E; - AddItem(item); - } - - public Hargrove(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override string DefaultName => "Hargrove"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074213, // Hey buddy.� Looking for work? - 1074211)); // I could use some help. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; +using Server.Engines.Spawners; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Definitions +{ + public class SplitEnds : MLQuest + { + public SplitEnds() + { + Activated = true; + HasRestartDelay = true; + Title = 1075506; // Split Ends + Description = + 1075507; // *sighs* I think bowcrafting is a might beyond my talents. Say there, you look a bit more confident with tools. Can I persuade thee to make a few arrows? You could have my satchel in return... 'tis useless to me! You'll need a fletching kit to start, some feathers, and a few arrow shafts. Just use the fletching kit while you have the other things, and I'm sure you'll figure out the rest. + RefusalMessage = 1075508; // Oh. Well. I'll just keep trying alone, I suppose... + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + CompletionMessage = 1072272; // Thanks for helping me out. Here's the reward I promised you. + + Objectives.Add(new CollectObjective(20, typeof(Arrow), 1023902)); // arrow + + Rewards.Add(new ItemReward(1074282, typeof(AndricSatchel))); // Craftsmans's Satchel + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Andric"), new Point3D(3742, 2582, 40), Map.Trammel); + } + } + + public class IShotAnArrowIntoTheAir : MLQuest + { + public IShotAnArrowIntoTheAir() + { + Activated = true; + Title = 1075486; // I Shot an Arrow Into the Air... + Description = + 1075482; // Truth be told, the only way to get a feel for the bow is to shoot one and there's no better practice target than a sheep. If ye can shoot ten of them I think ye will have proven yer abilities. Just grab a bow and make sure to take enough ammunition. Bows tend to use arrows and crossbows use bolts. Ye can buy 'em or have someone craft 'em. How about it then? Come back here when ye are done. + RefusalMessage = 1075483; // Fair enough, the bow isn't for everyone. Good day then. + InProgressMessage = 1075484; // Return once ye have killed ten sheep with a bow and not a moment before. + + Objectives.Add(new KillObjective(10, new[] { typeof(Sheep) }, 1018270)); // sheep + + Rewards.Add(ItemReward.BagOfTrinkets); + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Kashiel"), new Point3D(3744, 2586, 40), Map.Trammel); + } + } + + public class BakersDozen : MLQuest + { + public BakersDozen() + { + Activated = true; + HasRestartDelay = true; + Title = 1075478; // Baker's Dozen + Description = + 1075479; // You there! Do you know much about the ways of cooking? If you help me out, I'll show you a thing or two about how it's done. Bring me some cookie mix, about 5 batches will do it, and I will reward you. Although, I don't think you can buy it, you can make some in a snap! First get a rolling pin or frying pan or even a flour sifter. Then you mix one pinch of flour with some water and you've got some dough! Take that dough and add one dollop of honey and you've got sweet dough. add one more drop of honey and you've got cookie mix. See? Nothing to it! Now get to work! + RefusalMessage = + 1075480; // Argh, I absolutely must have more of these 'cookies!' Come back if you change your mind. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + CompletionMessage = 1075481; // Thank you! I haven't been this excited about food in months! + + Objectives.Add(new CollectObjective(5, typeof(CookieMix), 1024159)); // cookie mix + + Rewards.Add(new ItemReward(1074282, typeof(AsandosSatchel))); // Craftsmans's Satchel + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Asandos"), new Point3D(3505, 2513, 27), Map.Trammel); + } + } + + public class AStitchInTime : MLQuest + { + public AStitchInTime() + { + Activated = true; + HasRestartDelay = true; + Title = 1075523; // A Stitch in Time + Description = + 1075522; // Oh how I wish I had a fancy dress like the noble ladies of Castle British! I don't have much... but I have a few trinkets I might trade for it. It would mean the world to me to go to a fancy ball and dance the night away. Oh, and I could tell you how to make one! You just need to use your sewing kit on enough cut cloth, that's all. + RefusalMessage = 1075526; // Won't you reconsider? It'd mean the world to me, it would! + InProgressMessage = + 1075527; // Hello again! Do you need anything? You may want to visit the tailor's shop for cloth and a sewing kit, if you don't already have them. + CompletionMessage = + 1075528; // It's gorgeous! I only have a few things to give you in return, but I can't thank you enough! Maybe I'll even catch Uzeraan's eye at the, er, *blushes* I mean, I can't wait to wear it to the next town dance! + + Objectives.Add(new CollectObjective(1, typeof(FancyDress), 1027935)); // fancy dress + + Rewards.Add(new ItemReward(1075524, typeof(AnOldRing))); // an old ring + Rewards.Add(new ItemReward(1075525, typeof(AnOldNecklace))); // an old necklace + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Clairesse"), new Point3D(3492, 2546, 20), Map.Trammel); + } + } + + public class BatteredBucklers : MLQuest + { + public BatteredBucklers() + { + Activated = true; + HasRestartDelay = true; + Title = 1075511; // Battered Bucklers + Description = + 1075512; // Hey there! Yeah... you! Ya' any good with a hammer? Tell ya what, if yer thinking about tryin' some metal work, and have a bit of skill, I can show ya how to bend it into shape. Just get some of those ingots there, and grab a hammer and use it over here at this forge. I need a few more bucklers hammered out to fill this here order with... hmmm about ten more. that'll give some taste of how to work the metal. + RefusalMessage = + 1075514; // Not enough muscle on yer bones to use it? hmph, probably afraid of the sparks markin' up yer loverly skin... to good for some honest labor... ha!... off with ya! + InProgressMessage = 1075515; // Come On! Whats that... a bucket? We need ten bucklers... not spitoons. + CompletionMessage = 1075516; // Thanks for the help. Here's something for ya to remember me by. + + Objectives.Add(new CollectObjective(10, typeof(Buckler), 1027027)); // buckler + + Rewards.Add(new ItemReward(1074282, typeof(GervisSatchel))); // Craftsmans's Satchel + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Gervis"), new Point3D(3505, 2749, 0), Map.Trammel); + } + } + + public class MoreOrePlease : MLQuest + { + public MoreOrePlease() + { + Activated = true; + HasRestartDelay = true; + Title = 1075530; // More Ore Please + Description = + 1075529; // Have a pickaxe? My supplier is late and I need some iron ore so I can complete a bulk order for another merchant. If you can get me some soon I'll pay you double what it's worth on the market. Just find a cave or mountainside and try to use your pickaxe there, maybe you'll strike a good vein! 5 large pieces should do it. + RefusalMessage = + 1075531; // Not feeling strong enough today? Its alright, I didn't need a bucket of rocks anyway. + InProgressMessage = 1075532; // Hmmm� we need some more Ore. Try finding a mountain or cave, and give it a whack. + CompletionMessage = + 1075533; // I see you found a good vien! Great! This will help get this order out on time. Good work! + + Objectives.Add(new InternalObjective()); + + Rewards.Add(new ItemReward(1074282, typeof(MuggSatchel))); // Craftsmans's Satchel + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Mugg"), new Point3D(3507, 2747, 0), Map.Trammel); + } + + private class InternalObjective : CollectObjective + { + // Any type of ore is allowed + public InternalObjective() + : base(5, typeof(BaseOre), 1026585) // ore + { + } + + public override bool CheckItem(Item item) => item.ItemID == 6585; + } + } + + public class ComfortableSeating : MLQuest + { + public ComfortableSeating() + { + Activated = true; + HasRestartDelay = true; + Title = 1075517; // Comfortable Seating + Description = + 1075518; // Hail friend, hast thou a moment? A mishap with a saw hath left me in a sorry state, for it shall be a while before I canst return to carpentry. In the meantime, I need a comfortable chair that I may rest. Could thou craft a straw chair? Only a tool, such as a dovetail saw, a few boards, and some skill as a carpenter is needed. Remember, this is a piece of furniture, so please pay attention to detail. + RefusalMessage = 1072687; // I quite understand your reluctance. If you reconsider, I'll be here. + InProgressMessage = 1075509; // Is all going well? I look forward to the simple comforts in my very own home. + CompletionMessage = 1074720; // This is perfect! + + Objectives.Add(new CollectObjective(1, typeof(BambooChair), "straw chair")); + + Rewards.Add(new ItemReward(1074282, typeof(LowelSatchel))); // Craftsmans's Satchel + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Lowel"), new Point3D(3440, 2645, 27), Map.Trammel); + } + } + + public class ThePenIsMightier : MLQuest + { + public ThePenIsMightier() + { + Activated = true; + HasRestartDelay = true; + Title = 1075542; // The Pen is Mightier + Description = + 1075543; // Do you know anything about 'Inscription?' I've been trying to get my hands on some hand crafted Recall scrolls for a while now, and I could really use some help. I don't have a scribe's pen, let alone a spellbook with Recall in it, or blank scrolls, so there's no way I can do it on my own. How about you though? I could trade you one of my old leather bound books for some. + RefusalMessage = + 1075546; // Hmm, thought I had your interest there for a moment. It's not everyday you see a book made from real daemon skin, after all! + InProgressMessage = + 1075547; // Inscribing... yes, you'll need a scribe's pen, some reagents, some blank scroll, and of course your own magery book. You might want to visit the magery shop if you're lacking some materials. + CompletionMessage = + 1075548; // Ha! Finally! I've had a rune to the waterfalls near Justice Isle that I've been wanting to use for the longest time, and now I can visit at last. Here's that book I promised you... glad to be rid of it, to be honest. + + Objectives.Add(new CollectObjective(5, typeof(RecallScroll), "recall scroll")); + + Rewards.Add(new ItemReward(1075545, typeof(RedLeatherBook))); // a book bound in red leather + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Lyle"), new Point3D(3503, 2584, 14), Map.Trammel); + } + } + + public class AClockworkPuzzle : MLQuest + { + public AClockworkPuzzle() + { + Activated = true; + HasRestartDelay = true; + Title = 1075535; // A clockwork puzzle + Description = + 1075534; // 'Tis a riddle, you see! "What kind of clock is only right twice per day? A broken one!" *laughs heartily* Ah, yes *wipes eye*, that's one of my favorites! Ah... to business. Could you fashion me some clock parts? I wish my own clocks to be right all the day long! You'll need some tinker's tools and some iron ingots, I think, but from there it should be just a matter of working the metal. + RefusalMessage = 1072981; // Or perhaps you'd rather not. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + CompletionMessage = 1075536; // Wonderful! Tick tock, tick tock, soon all shall be well with grandfather's clock! + + Objectives.Add(new CollectObjective(5, typeof(ClockParts), 1024175)); // clock parts + + Rewards.Add(new ItemReward(1074282, typeof(NibbetSatchel))); // Craftsmans's Satchel + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Nibbet"), new Point3D(3459, 2525, 53), Map.Trammel); + } + } + + public class DeliciousFishes : MLQuest + { + public DeliciousFishes() + { + Activated = true; + HasRestartDelay = true; + Title = 1075555; // Delicious Fishes + Description = + 1075556; // Ello there, looking for a good place on the dock to fish? I like the southeast corner meself. What's that? Oh, no, *sighs* me pole is broken and in for fixin'. My grandpappy gave me that pole, means a lot you see. Miss the taste of fish though... Oh say, since you're here, could you catch me a few fish? I can cook a mean fish steak, and I'll split 'em with you! But make sure it's one of the green kind, they're the best for seasoning! + RefusalMessage = + 1075558; // Ah, you're missin' out my friend, you're missing out. My peppercorn fishsteaks are famous on this little isle of ours! + InProgressMessage = + 1075559; // Eh? Find yerself a pole and get close to some water. Just toss the line on in and hopefully you won't snag someone's old boots! Remember, that's twenty of them green fish we'll be needin', so come back when you've got em, 'aight? + CompletionMessage = + 1075560; // Just a moment my friend, just a moment! *rummages in his pack* Here we are! My secret blend of peppers always does the trick, never fails, no not once. These'll fill you up much faster than that tripe they sell in the market! + + Objectives.Add(new CollectObjective(5, typeof(Fish), 1022508)); // fish + + Rewards.Add(new ItemReward(1075557, typeof(PeppercornFishsteak), 3)); // peppercorn fishsteak + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Norton"), new Point3D(3502, 2603, 1), Map.Trammel); + } + } + + public class FleeAndFatigue : MLQuest + { + public FleeAndFatigue() + { + Activated = true; + HasRestartDelay = true; + Title = 1075487; // Flee and Fatigue + Description = + 1075488; // I was just *coughs* ambushed near the moongate. *wheeze* Why do I pay my taxes? Where were the guards? You then, you an Alchemist? If you can make me a few Refresh potions, I will be back on my feet and can give those lizards the what for! Find a mortar and pestle, a good amount of black pearl, and ten empty bottles to store the finished potions in. Just use the mortar and pestle and the rest will surely come to you. When you return, the favor will be repaid. + RefusalMessage = + 1075489; // Fine fine, off with *cough* thee then! The next time you see a lizardman though, give him a whallop for me, eh? + InProgressMessage = + 1075490; // Just remember you need to use your mortar and pestle while you have empty bottles and some black pearl. Refresh potions are what I need. + CompletionMessage = + 1075491; // *glug* *glug* Ahh... Yes! Yes! That feels great! Those lizardmen will never know what hit 'em! Here, take this, I can get more from the lizards. + + Objectives.Add(new CollectObjective(10, typeof(RefreshPotion), "refresh potions")); + + Rewards.Add(new ItemReward(1074282, typeof(SadrahSatchel))); // Craftsmans's Satchel + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Sadrah"), new Point3D(3742, 2731, 7), Map.Trammel); + } + } + + public class ChopChopOnTheDouble : MLQuest + { + public ChopChopOnTheDouble() + { + Activated = true; + HasRestartDelay = true; + Title = 1075537; // Chop Chop, On The Double! + Description = + 1075538; // That's right, move it! I need sixty logs on the double, and they need to be freshly cut! If you can get them to me fast I'll have your payment in your hands before you have the scent of pine out from beneath your nostrils. Just get a sharp axe and hack away at some of the trees in the land and your lumberjacking skill will rise in no time. + RefusalMessage = 1072981; // Or perhaps you'd rather not. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + CompletionMessage = + 1075539; // Ahhh! The smell of fresh cut lumber. And look at you, all strong and proud, as if you had done an honest days work! + + Objectives.Add(new CollectObjective(60, typeof(Log), 1027133)); // log + + Rewards.Add(new ItemReward(1074282, typeof(HargroveSatchel))); // Craftsmans's Satchel + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Hargrove"), new Point3D(3445, 2633, 28), Map.Trammel); + } + } + + public class Andric : BaseCreature + { + [Constructible] + public Andric() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the archer trainer"; + Race = Race.Human; + BodyValue = 0x190; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Archery, 60.0, 80.0); + + AddItem(new Backpack()); + + Item item; + + item = new LeatherChest(); + item.Hue = 0x1BB; + AddItem(item); + + item = new LeatherLegs(); + item.Hue = 0x6AD; + AddItem(item); + + item = new LeatherArms(); + item.Hue = 0x6AD; + AddItem(item); + + item = new LeatherGloves(); + item.Hue = 0x1BB; + AddItem(item); + + AddItem(new Boots(0x1BB)); + AddItem(new CompositeBow()); + } + + public Andric(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Andric"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074205, // Oh great adventurer, would you please assist a weak soul in need of aid? + 1074213 + ) + ); // Hey buddy.� Looking for work? + } + + 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 class Kashiel : BaseCreature + { + [Constructible] + public Kashiel() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the archer"; + Race = Race.Human; + BodyValue = 0x191; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Backpack()); + + Item item; + + item = new LeatherChest(); + item.Hue = 0x1BB; + AddItem(item); + + item = new LeatherLegs(); + item.Hue = 0x901; + AddItem(item); + + item = new LeatherArms(); + item.Hue = 0x901; + AddItem(item); + + item = new LeatherGloves(); + item.Hue = 0x1BB; + AddItem(item); + + AddItem(new Boots(0x1BB)); + AddItem(new CompositeBow()); + } + + public Kashiel(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "Kashiel"; + public override bool IsInvulnerable => true; + + 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 class Asandos : BaseCreature + { + [Constructible] + public Asandos() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the chef"; + Race = Race.Human; + BodyValue = 0x190; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Backpack()); + AddItem(new Boots(0x901)); + AddItem(new ShortPants()); + AddItem(new Shirt()); + AddItem(new Cap()); + AddItem(new HalfApron(0x28)); + } + + public Asandos(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Asandos"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074205, // Oh great adventurer, would you please assist a weak soul in need of aid? + 1074213 + ) + ); // Hey buddy.� Looking for work? + } + + 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(); + } + } + + // [QuesterName( "Clarisse" )] // On OSI the gumps refer to her as this, different from actual name + public class Clairesse : BaseCreature + { + [Constructible] + public Clairesse() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the servant"; + Race = Race.Human; + BodyValue = 0x191; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Backpack()); + AddItem(new Shoes(Utility.RandomNeutralHue())); + AddItem(new PlainDress(0x3C9)); + } + + public Clairesse(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Clairesse"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074205, // Oh great adventurer, would you please assist a weak soul in need of aid? + 1074213 + ) + ); // Hey buddy.� Looking for work? + } + + 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 class Gervis : BaseCreature + { + [Constructible] + public Gervis() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the blacksmith trainer"; + Race = Race.Human; + BodyValue = 0x190; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Blacksmith, 60.0, 80.0); + + AddItem(new Backpack()); + AddItem(new Boots(0x3B3)); + AddItem(new ShortPants(0x1BB)); + AddItem(new Doublet(0x652)); + AddItem(new SmithHammer()); + + Item item; + + item = new LeatherGloves(); + item.Hue = 0x3B2; + AddItem(item); + } + + public Gervis(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Gervis"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074205, // Oh great adventurer, would you please assist a weak soul in need of aid? + 1074213, // Hey buddy.� Looking for work? + 1074211 + ) + ); // I could use some help. + } + + 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 class Mugg : BaseCreature + { + [Constructible] + public Mugg() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the miner"; + Race = Race.Human; + BodyValue = 0x190; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Backpack()); + AddItem(new Boots(0x901)); + AddItem(new ShortPants(0x3B3)); + AddItem(new Shirt(0x22B)); + AddItem(new HalfApron(0x5F1)); + AddItem(new SkullCap(0x177)); + AddItem(new Pickaxe()); + } + + public Mugg(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Mugg"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1074211); // I could use some help. + } + + 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 class Lowel : BaseCreature + { + [Constructible] + public Lowel() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the carpenter"; + Race = Race.Human; + BodyValue = 0x190; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Backpack()); + AddItem(new Boots(0x543)); + AddItem(new ShortPants(0x758)); + AddItem(new FancyShirt(0x53A)); + AddItem(new HalfApron(0x6D2)); + } + + public Lowel(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Lowel"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074205, // Oh great adventurer, would you please assist a weak soul in need of aid? + 1074213 + ) + ); // Hey buddy.� Looking for work? + } + + 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 class Lyle : BaseCreature + { + [Constructible] + public Lyle() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the mage"; + Race = Race.Human; + BodyValue = 0x190; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Backpack()); + AddItem(new Robe(0x2FD)); + AddItem(new ThighBoots()); + } + + public Lyle(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Lyle"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074205, // Oh great adventurer, would you please assist a weak soul in need of aid? + 1074213 + ) + ); // Hey buddy.� Looking for work? + } + + 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 class Nibbet : BaseCreature + { + [Constructible] + public Nibbet() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the tinker"; + Race = Race.Human; + BodyValue = 0x190; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Backpack()); + AddItem(new Boots(0x591)); + AddItem(new ShortPants(0xF8)); + AddItem(new Shirt(0x2D)); + AddItem(new FullApron(0x288)); + } + + public Nibbet(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "Nibbet"; + public override bool IsInvulnerable => true; + + 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 class Norton : BaseCreature + { + [Constructible] + public Norton() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the fisher"; + Race = Race.Human; + BodyValue = 0x190; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Backpack()); + AddItem(new ThighBoots()); + AddItem(new LongPants(0x6C2)); + AddItem(new Shirt(0x11D)); + } + + public Norton(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Norton"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074205, // Oh great adventurer, would you please assist a weak soul in need of aid? + 1074213, // Hey buddy.� Looking for work? + 1074211 + ) + ); // I could use some help. + } + + 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 class Sadrah : BaseCreature + { + [Constructible] + public Sadrah() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the courier"; + Race = Race.Human; + BodyValue = 0x191; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Backpack()); + AddItem(new Boots(0x901)); + AddItem(new Skirt(0x52)); + AddItem(new Shirt(0x127)); + AddItem(new Cloak(0x65)); + AddItem(new Longsword()); + } + + public Sadrah(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Sadrah"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074205, // Oh great adventurer, would you please assist a weak soul in need of aid? + 1074213, // Hey buddy.� Looking for work? + 1074211 + ) + ); // I could use some help. + } + + 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 class Hargrove : BaseCreature + { + [Constructible] + public Hargrove() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Lumberjack"; + Race = Race.Human; + BodyValue = 0x190; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Backpack()); + AddItem(new Boots(0x901)); + AddItem(new StuddedLegs()); + AddItem(new Shirt(0x288)); + AddItem(new Bandana(0x20)); + AddItem(new BattleAxe()); + + Item item; + + item = new PlateGloves(); + item.Hue = 0x21E; + AddItem(item); + } + + public Hargrove(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Hargrove"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074213, // Hey buddy.� Looking for work? + 1074211 + ) + ); // I could use some help. + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Definitions/Sanctuary.cs b/Projects/UOContent/Engines/MLQuests/Definitions/Sanctuary.cs index 3198a35a5..6444d5c94 100644 --- a/Projects/UOContent/Engines/MLQuests/Definitions/Sanctuary.cs +++ b/Projects/UOContent/Engines/MLQuests/Definitions/Sanctuary.cs @@ -1,1300 +1,1400 @@ -using System; -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; -using Server.Engines.Spawners; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Definitions -{ - public class BrokenShaft : MLQuest - { - public BrokenShaft() - { - Activated = true; - HasRestartDelay = true; - Title = 1074018; // Broken Shaft - Description = - 1074112; // What do humans know of archery? Humans can barely shoot straight. Why, your efforts are absurd. In fact, I will make a wager - if these so called human arrows I've heard about are really as effective and innovative as human braggarts would have me believe, then I'll trade you something useful. I might even teach you something of elven craftsmanship. - RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. - InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! - CompletionMessage = - 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! - - Objectives.Add(new CollectObjective(10, typeof(Arrow), 1023902)); // arrow - - Rewards.Add(ItemReward.FletchingSatchel); - } - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Beotham"), new Point3D(6285, 114, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Beotham"), new Point3D(6285, 114, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Danoel"), new Point3D(6282, 116, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Danoel"), new Point3D(6282, 116, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Tallinin"), new Point3D(6279, 122, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Tallinin"), new Point3D(6279, 122, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Tiana"), new Point3D(6257, 112, -10), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Tiana"), new Point3D(6257, 112, -10), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 0, "LorekeeperOolua"), new Point3D(6250, 124, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 0, "LorekeeperOolua"), new Point3D(6250, 124, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 0, "LorekeeperRollarn"), new Point3D(6244, 110, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 0, "LorekeeperRollarn"), new Point3D(6244, 110, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Dallid"), new Point3D(6277, 104, -10), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Dallid"), new Point3D(6277, 104, -10), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Canir"), new Point3D(6274, 130, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Canir"), new Point3D(6274, 130, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Yellienir"), new Point3D(6257, 126, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Yellienir"), new Point3D(6257, 126, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 0, "ElderOnallan"), new Point3D(6258, 108, -10), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 0, "ElderOnallan"), new Point3D(6258, 108, -10), Map.Felucca); - } - } - - public class BendingTheBow : MLQuest - { - public BendingTheBow() - { - Activated = true; - HasRestartDelay = true; - Title = 1074019; // Bending the Bow - Description = - 1074113; // Human craftsmanship! Ha! Why, take an elven bow. It will last for a lifetime, never break and always shoot an arrow straight and true. Can't say the same for a human, can you? Bring me some of these human made bows, and I will show you. - RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. - InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! - CompletionMessage = - 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! - - Objectives.Add(new CollectObjective(10, typeof(Bow), 1025041)); // bow - - Rewards.Add(ItemReward.FletchingSatchel); - } - } - - public class ArmsRace : MLQuest - { - public ArmsRace() - { - Activated = true; - HasRestartDelay = true; - Title = 1074020; // Arms Race - Description = - 1074114; // Leave it to a human to try and improve upon perfection. To take a bow and turn it into a mechanical contraption like a crossbow. I wish to see more of this sort of "invention". Fetch for me a crossbow, human. - RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. - InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! - CompletionMessage = - 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! - - Objectives.Add(new CollectObjective(10, typeof(Crossbow), 1023919)); // crossbow - - Rewards.Add(ItemReward.FletchingSatchel); - } - } - - public class ImprovedCrossbows : MLQuest - { - public ImprovedCrossbows() - { - Activated = true; - HasRestartDelay = true; - Title = 1074021; // Improved Crossbows - Description = - 1074115; // How lazy is man! You cannot even be bothered to pull your own drawstring and hold an arrow ready? You must invent a device to do it for you? I cannot understand, but perhaps if I examine a heavy crossbow for myself, I will see their appeal. Go and bring me such a device and I will repay your meager favor. - RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. - InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! - CompletionMessage = - 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! - - Objectives.Add(new CollectObjective(10, typeof(HeavyCrossbow), 1025116)); // heavy crossbow - - Rewards.Add(ItemReward.FletchingSatchel); - } - } - - public class BuildingTheBetterCrossbow : MLQuest - { - public BuildingTheBetterCrossbow() - { - Activated = true; - HasRestartDelay = true; - Title = 1074022; // Building the Better Crossbow - Description = - 1074116; // More is always better for a human, eh? Take these repeating crossbows. What sort of mind invents such a thing? I must look at it more closely. Bring such a contraption to me and you'll receive a token for your efforts. - RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. - InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! - CompletionMessage = - 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! - - Objectives.Add(new CollectObjective(10, typeof(RepeatingCrossbow), 1029923)); // repeating crossbow - - Rewards.Add(ItemReward.FletchingSatchel); - } - } - - public class InstrumentOfWar : MLQuest - { - public InstrumentOfWar() - { - Activated = true; - HasRestartDelay = true; - Title = 1074055; // Instrument of War - Description = - 1074149; // Pathetic, this human craftsmanship! Take their broadswords - overgrown butter knives, in reality. No, I cannot do them justice - you must see for yourself. Bring me broadswords and I will demonstrate their feebleness. - RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. - InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! - CompletionMessage = - 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! - - Objectives.Add(new CollectObjective(12, typeof(Broadsword), 1023934)); // broadsword - - Rewards.Add(ItemReward.BlacksmithSatchel); - } - } - - public class TheShield : MLQuest - { - public TheShield() - { - Activated = true; - HasRestartDelay = true; - Title = 1074054; // The Shield - Description = - 1074148; // I doubt very much a human shield would stop a good stout elven arrow. You doubt me? I will show you - get me some of these heater shields and I will piece them with sharp elven arrows! - RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. - InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! - CompletionMessage = - 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! - - Objectives.Add(new CollectObjective(10, typeof(HeaterShield), 1027030)); // heater shield - - Rewards.Add(ItemReward.BlacksmithSatchel); - } - } - - public class MusicToMyEars : MLQuest - { - public MusicToMyEars() - { - Activated = true; - HasRestartDelay = true; - Title = 1074023; // Music to my Ears - Description = - 1074117; // You think you know something of music? Laughable! Take your lap harp. Crude, indelicate instruments that make a noise not unlike the wailing of a choleric child or a dying cat. I will show you - bring lap harps, and I will demonstrate. - RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. - InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! - CompletionMessage = - 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! - - Objectives.Add(new CollectObjective(10, typeof(LapHarp), 1023762)); // lap harp - - Rewards.Add(ItemReward.CarpentrySatchel); - } - } - - public class TheGlassEye : MLQuest - { - public TheGlassEye() - { - Activated = true; - HasRestartDelay = true; - Title = 1074050; // The Glass Eye - Description = - 1074144; // Humans are so pathetically weak, they must be augmented by glass and metal! Imagine such a thing! I must see one of these spyglasses for myself, to understand the pathetic limits of human sight! - RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. - InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! - CompletionMessage = - 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! - - Objectives.Add(new CollectObjective(10, typeof(Spyglass), 1025365)); // spyglass - - Rewards.Add(ItemReward.TinkerSatchel); - } - } - - public class LazyHumans : MLQuest - { - public LazyHumans() - { - Activated = true; - HasRestartDelay = true; - Title = 1074024; // Lazy Humans - Description = - 1074118; // Human fancy knows no bounds! It's pathetic that they are so weak that they must create a special stool upon which to rest their feet when they recline! Humans don't have any clue how to live. Bring me some of these foot stools to examine and I may teach you something worthwhile. - RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. - InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! - CompletionMessage = - 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! - - Objectives.Add(new CollectObjective(10, typeof(FootStool), 1022910)); // foot stool - - Rewards.Add(ItemReward.CarpentrySatchel); - } - } - - public class InventiveTools : MLQuest - { - public InventiveTools() - { - Activated = true; - HasRestartDelay = true; - Title = 1074048; // Inventive Tools - Description = - 1074142; // Bring me some of these tinker's tools! I am certain, in the hands of an elf, they will fashion objects of ingenuity and delight that will shame all human invention! Hurry, do this quickly and I might deign to show you my skill. - RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. - InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! - CompletionMessage = - 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! - - Objectives.Add(new CollectObjective(10, typeof(TinkerTools), 1027868)); // tinker's tools - - Rewards.Add(ItemReward.TinkerSatchel); - } - } - - public class PixieDustToDust : MLQuest - { - public PixieDustToDust() - { - Activated = true; - Title = 1073661; // Pixie dust to dust - Description = - 1073700; // Is there anything more foul than a pixie? They have cruel eyes and a mind for mischief, I say. I don't care if some think they're cute -- I say kill them and let the Avatar sort them out. In fact, if you were to kill a few pixies, I'd make sure you had a few coins to rub together, if you get my meaning. - RefusalMessage = 1073733; // Perhaps you'll change your mind and return at some point. - InProgressMessage = 1073741; // There's too much cuteness in the world -- kill those pixies! - - Objectives.Add(new KillObjective(10, new[] { typeof(Pixie) }, "pixies")); - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - } - - public class AnImpressivePlaid : MLQuest - { - public AnImpressivePlaid() - { - Activated = true; - HasRestartDelay = true; - Title = 1074044; // An Impressive Plaid - Description = - 1074138; // I do not believe humans are so ridiculous as to wear something called a "kilt". Bring for me some of these kilts, if they truly exist, and I will offer you meager reward. - RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. - InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! - CompletionMessage = - 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! - - Objectives.Add(new CollectObjective(10, typeof(Kilt), 1025431)); // kilt - - Rewards.Add(ItemReward.TailorSatchel); - } - } - - public class ANiceShirt : MLQuest - { - public ANiceShirt() - { - Activated = true; - HasRestartDelay = true; - Title = 1074045; // A Nice Shirt - Description = - 1074139; // Humans call that a fancy shirt? I would wager the ends are frayed, the collar worn, the buttons loosely stitched. Bring me fancy shirts and I will demonstrate the many ways in which they are inferior. - RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. - InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! - CompletionMessage = - 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! - - Objectives.Add(new CollectObjective(10, typeof(FancyShirt), 1027933)); // fancy shirt - - Rewards.Add(ItemReward.TailorSatchel); - } - } - - public class LeatherAndLace : MLQuest - { - public LeatherAndLace() - { - Activated = true; - HasRestartDelay = true; - Title = 1074047; // Leather and Lace - Description = - 1074141; // No self respecting elf female would ever wear a studded bustier! I will prove it - bring me such clothing and I will show you how ridiculous they are! - RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. - InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! - CompletionMessage = - 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! - - Objectives.Add(new CollectObjective(10, typeof(StuddedBustierArms), 1027180)); // studded bustier - - Rewards.Add(ItemReward.TailorSatchel); - } - } - - public class FeyHeadgear : MLQuest - { - public FeyHeadgear() - { - Activated = true; - HasRestartDelay = true; - Title = 1074043; // Fey Headgear - Description = - 1074137; // Humans do not deserve to wear a thing such as a flower garland. Help me prevent such things from falling into the clumsy hands of humans -- bring me flower garlands! - RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. - InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! - CompletionMessage = - 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! - - Objectives.Add(new CollectObjective(10, typeof(FlowerGarland), 1028965)); // flower garland - - Rewards.Add(ItemReward.TailorSatchel); - } - } - - public class NewCloak : MLQuest - { - public NewCloak() - { - Activated = true; - Title = 1074684; // New Cloak - Description = - 1074685; // I have created a masterpiece! And all I need to finish it off is the soft fur of a wolf. But not just ANY wolf -- oh no, no, that wouldn't do. I've heard tales of a mighty beast, Grobu, who is bonded to the leader of the troglodytes. Only Grobu's fur will do. Will you retrieve it for me? - RefusalMessage = 1074655; // Perhaps I thought too highly of you. - InProgressMessage = - 1074686; // I've told you all I know of the creature. Until you return with Grobu's fur I can't finish my cloak. - CompletionMessage = 1074687; // Ah! So soft, so supple. What a wonderful texture. Here you are ... my thanks. - - Objectives.Add(new CollectObjective(1, typeof(GrobusFur), "Grobu's Fur")); - - Rewards.Add(ItemReward.TailorSatchel); - } - } - - public class ADishBestServedCold : MLQuest - { - public ADishBestServedCold() - { - Activated = true; - Title = 1072372; // A Dish Best Served Cold - Description = - 1072657; // *mutter* I'll have my revenge. Oh! You there. Fancy some orc extermination? I despise them all. Bombers, brutes -- you name it, if it's orcish I want it killed. - RefusalMessage = 1072667; // Hrmph. Well maybe another time then. - InProgressMessage = 1072668; // Shouldn't you be slaying orcs? - - Objectives.Add(new KillObjective(10, new[] { typeof(Orc) }, "orcs", - new QuestArea(1074807, "Sanctuary"))); // Sanctuary - Objectives.Add(new KillObjective(5, new[] { typeof(OrcBomber) }, "orc bombers", - new QuestArea(1074807, "Sanctuary"))); // Sanctuary - Objectives.Add(new KillObjective(3, new[] { typeof(OrcBrute) }, "orc brutes", - new QuestArea(1074807, "Sanctuary"))); // Sanctuary - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - public class ArchEnemies : MLQuest - { - public ArchEnemies() - { - Activated = true; - Title = 1073085; // Arch Enemies - Description = - 1073575; // Vermin! They get into everything! I told the boy to leave out some poisoned cheese -- and they shot him. What else can I do? Unless�these ratmen are skilled with a bow, but I'd lay a wager you're better, eh? Could you skin a few of the wretches for me? - RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. - InProgressMessage = - 1073595; // I don't see 10 tails from Ratman Archers on your belt -- and until I do, no reward for you. - - Objectives.Add(new KillObjective(10, new[] { typeof(RatmanArcher) }, "ratman archers")); - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - public class Vermin : MLQuest - { - public Vermin() - { - Activated = true; - Title = 1072995; // Vermin - Description = - 1073029; // You've got to help me out! Those ratmen have been causing absolute havok around here. Kill them off before they destroy my land. I'll pay you if you kill off twelve of those dirty rats. - RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. - InProgressMessage = 1072271; // You're not quite done yet. Get back to work! - - Objectives.Add(new KillObjective(12, new[] { typeof(Ratman) }, "ratmen")); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class MougGuurMustDie : MLQuest - { - public MougGuurMustDie() - { - Activated = true; - Title = 1072368; // Moug-Guur Must Die - Description = - 1072561; // You there! Yes, you. Kill Moug-Guur, the leader of the orcs in this depressing place, and I'll make it worth your while. - RefusalMessage = 1072571; // Fine. It's no skin off my teeth. - InProgressMessage = 1072572; // Small words. Kill Moug-Guur. Go. Now! - CompletionMessage = - 1072573; // You're better than I thought you'd be. Not particularly bad, but not entirely inept. - - Objectives.Add( - new KillObjective(1, new[] { typeof(MougGuur) }, "Moug-Guur", - new QuestArea(1074807, "Sanctuary"))); // Sanctuary - - Rewards.Add(ItemReward.BagOfTreasure); - } - - public override Type NextQuest => typeof(LeaderOfThePack); - } - - public class LeaderOfThePack : MLQuest - { - public LeaderOfThePack() - { - Activated = true; - Title = 1072560; // Leader of the Pack - Description = - 1072574; // Well now that Moug-Guur is no more -- and I can't say I'm weeping for his demise -- it's time for the ratmen to experience a similar loss of leadership. Slay Chiikkaha. In return, I'll satisfy your greed temporarily. - RefusalMessage = - 1072575; // Alright, if you'd rather not, then run along and do whatever worthless things you do when I'm not giving you direction. - InProgressMessage = - 1072576; // How difficult is this? The rats live in the tunnels. Go into the tunnels and find the biggest, meanest rat and execute him. Loitering around here won't get the task done. - CompletionMessage = 1072577; // It's about time! Could you have taken longer? - - Objectives.Add(new KillObjective(1, new[] { typeof(Chiikkaha) }, "Chiikkaha", - new QuestArea(1074807, "Sanctuary"))); // Sanctuary - - Rewards.Add(ItemReward.BagOfTreasure); - } - - public override Type NextQuest => typeof(SayonaraSzavetra); - public override bool IsChainTriggered => true; - } - - public class SayonaraSzavetra : MLQuest - { - public SayonaraSzavetra() - { - Activated = true; - Title = 1072375; // Sayonara, Szavetra - Description = - 1072578; // Hmm, maybe you aren't entirely worthless. I suspect a demoness of Szavetra's calibre will tear you apart ... We might as well find out. Kill the succubus, yada yada, and you'll be richly rewarded. - RefusalMessage = 1072579; // Hah! I knew you couldn't handle it. - InProgressMessage = - 1072581; // Hahahaha! I can see the fear in your eyes. Pathetic. Szavetra is waiting for you. - CompletionMessage = - 1072582; // Amazing! Simply astonishing ... you survived. Well, I supposed I should indulge your avarice with a reward. - - Objectives.Add(new KillObjective(1, new[] { typeof(Szavetra) }, "Szavetra", - new QuestArea(1074807, "Sanctuary"))); // Sanctuary - - Rewards.Add(ItemReward.Strongbox); - } - - public override bool IsChainTriggered => true; - } - - public class TappingTheKeg : MLQuest - { - public TappingTheKeg() - { - Activated = true; - HasRestartDelay = true; - Title = 1074037; // Tapping the Keg - Description = - 1074131; // I have acquired a barrel of human brewed beer. I am loathe to drink it, but how else to prove how inferior it is? I suppose I shall need a barrel tap to drink. Go, bring me a barrel tap quickly, so I might get this over with. - RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. - InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! - CompletionMessage = - 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! - - Objectives.Add(new CollectObjective(10, typeof(BarrelTap), 1024100)); // barrel tap - - Rewards.Add(ItemReward.TinkerSatchel); - } - } - - public class WaitingToBeFilled : MLQuest - { - public WaitingToBeFilled() - { - Activated = true; - HasRestartDelay = true; - Title = 1074036; // Waiting to be Filled - Description = - 1074130; // The only good thing I can say about human made bottles is that they are empty and may yet still be filled with elven wine. Go now, fetch a number of empty bottles so that I might save them from the fate of carrying human-made wine. - RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. - InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! - CompletionMessage = - 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! - - Objectives.Add(new CollectObjective(20, typeof(Bottle), 1023854)); // empty bottle - - Rewards.Add(ItemReward.TinkerSatchel); - } - } - - public class BreezesSong : MLQuest - { - public BreezesSong() - { - Activated = true; - HasRestartDelay = true; - Title = 1074052; // Breeze's Song - Description = - 1074146; // I understand humans cruely enslave the very wind to their selfish whims! Fancy wind chimes, what a monstrous idea! You must bring me proof of this terrible depredation - hurry, bring me wind chimes! - RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. - InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! - CompletionMessage = - 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! - - Objectives.Add(new CollectObjective(10, typeof(FancyWindChimes), 1030291)); // fancy wind chimes - - Rewards.Add(ItemReward.TinkerSatchel); - } - } - - public class ProofOfTheDeed : MLQuest - { - public ProofOfTheDeed() - { - Activated = true; - Title = 1072339; // Proof of the Deed - Description = - 1072340; // These human vermin must be erradicated! They despoil fair Sosaria with their every footfall upon her soil, every exhalation of breath upon her pristine air. Prove yourself an ally of Sosaria and bring me 20 human ears as proof of your devotion to our cause. - RefusalMessage = - 1072342; // Do you find the task distasteful? Are you too weak to shoulder the duty of cleansing Sosaria? So be it. - InProgressMessage = - 1072343; // Well, where is the proof of your deed? I will honor your actions when you have brought me the ears of the human scum. - CompletionMessage = - 1072344; // Ah, well done. You have chosen the path of duty and fulfilled your task with honor. - - Objectives.Add(new CollectObjective(20, typeof(SeveredHumanEars), 1032591)); // severed human ears - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class Marauders : MLQuest - { - public Marauders() - { - Activated = true; - Title = 1072374; // Marauders - Description = - 1072686; // What a miserable place we live in. Look around you at the changes we've wrought. The trees are sprouting leaves once more and the grass is reclaiming the blood-soaked soil. Who would have imagined we'd find ourselves here? Our "neighbors" are anything but friendly and those ogres are the worst of the lot. Maybe you'd be interested in helping our community by disposing of some of our least amiable neighbors? - RefusalMessage = 1072687; // I quite understand your reluctance. If you reconsider, I'll be here. - InProgressMessage = 1072688; // You can't miss those ogres, they're huge and just outside the gates here. - - Objectives.Add(new KillObjective(10, new[] { typeof(Ogre) }, "ogres", - new QuestArea(1074807, "Sanctuary"))); // Sanctuary - - Rewards.Add(ItemReward.BagOfTreasure); - } - - public override Type NextQuest => typeof(TheBrainsOfTheOperation); - } - - public class TheBrainsOfTheOperation : MLQuest - { - public TheBrainsOfTheOperation() - { - Activated = true; - Title = 1072692; // The Brains of the Operation - Description = - 1072707; // *sigh* We have so much to do to clean this area up. Even the fine work you did on those ogres didn't have much of an impact on the community. It's the ogre lords that direct the actions of the other ogres, let's strike at the leaders and perhaps that will thwart the miserable curs. - RefusalMessage = 1072708; // Reluctance doesn't become a hero like you. But, as you wish. - InProgressMessage = - 1072709; // Ogre Lords are pretty easy to recognize. They're the ones ordering the other ogres about in a lordly manner. Striking down their leadership will throw the ogres into confusion and dismay! - - Objectives.Add(new KillObjective(10, new[] { typeof(OgreLord) }, "ogre lords", - new QuestArea(1074807, "Sanctuary"))); // Sanctuary - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - - public override Type NextQuest => typeof(TheBrawn); - public override bool IsChainTriggered => true; - } - - public class TheBrawn : MLQuest - { - public TheBrawn() - { - Activated = true; - Title = 1072693; // The Brawn - Description = - 1072710; // Inconceiveable! We've learned that the ogre leadership has recruited some heavy-duty guards to their cause. I've never personally fought a cyclopian warrior, but I'm sure you could easily best a few and report back how much trouble they'll cause to our growing community? - RefusalMessage = 1072711; // Oh, I see. *sigh* Perhaps I overestimated your abilities. - InProgressMessage = 1072712; // Make sure you fully assess all of the cyclopian tactical abilities! - - Objectives.Add(new KillObjective(6, new[] { typeof(Cyclops) }, "cyclops", - new QuestArea(1074807, "Sanctuary"))); // Sanctuary - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - - public override Type NextQuest => typeof(TheBiggerTheyAre); - public override bool IsChainTriggered => true; - } - - public class TheBiggerTheyAre : MLQuest - { - public TheBiggerTheyAre() - { - Activated = true; - Title = 1072694; // The Bigger They Are ... - Description = - 1072713; // The ogre insurgency has taken a turn for the worse! I've just been advised that the titans have concluded their discussions with the ogres and they've allied. We have virtually no information about titans. Engage them and appraise their mettle. - RefusalMessage = - 1072714; // Certainly. You've done enough to merit a breather. When you're ready for more, report back to me. - InProgressMessage = - 1072715; // Those titans don't skulk very well. You should be able to track them easily ... their footsteps are easily the largest around. - - Objectives.Add(new KillObjective(3, new[] { typeof(Titan) }, "titans", - new QuestArea(1074807, "Sanctuary"))); // Sanctuary - - Rewards.Add(ItemReward.LargeBagOfTreasure); - } - - public override bool IsChainTriggered => true; - } - - public class TroubleOnTheWing : MLQuest - { - public TroubleOnTheWing() - { - Activated = true; - Title = 1072371; // Trouble on the Wing - Description = - 1072593; // Those gargoyles need to get knocked down a peg or two, if you ask me. They're always flying over here and lobbing things at us. What a nuisance. Drop a dozen of them for me, would you? - RefusalMessage = 1072594; // Don't tell me you're a gargoyle sympathizer? *spits* - InProgressMessage = - 1072595; // Those blasted gargoyles hang around the old tower. That's the best place to hunt them down. - - Objectives.Add(new KillObjective(12, new[] { typeof(Gargoyle) }, "gargoyles", - new QuestArea(1074807, "Sanctuary"))); // Sanctuary - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class BrotherlyLove : MLQuest - { - public BrotherlyLove() - { - Activated = true; - OneTimeOnly = true; - Title = 1072369; // Brotherly Love - Description = - 1072585; // *looks around nervously* Do you travel to The Heartwood? I have an urgent letter that must be delivered there in the next 30 minutes -- to Ahie the Cloth Weaver. Will you undertake this journey? - RefusalMessage = 1072587; // *looks disappointed* Let me know if you change your mind. - InProgressMessage = - 1072588; // You haven't lost the letter have you? It must be delivered to Ahie directly. Give it into no other hands. - CompletionMessage = 1074579; // Yes, can I help you? - CompletionNotice = CompletionNoticeShort; - - Objectives.Add(new DeliverObjective(typeof(APersonalLetterAddressedToAhie), 1, "letter", typeof(Ahie))); - - Rewards.Add(ItemReward.BagOfTrinkets); - } - } - - public class CommonBrigands : MLQuest - { - public CommonBrigands() - { - Activated = true; - Title = 1073082; // Common Brigands - Description = - 1073572; // Thank goodness, a hero like you has arrived! Brigands have descended upon this area like locusts, stealing and looting where ever they go. We need someone to put these vile curs where they belong -- in their graves. Are you up to the task? - RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. - InProgressMessage = 1073592; // The Brigands still plague us. Have you killed 20 of their number?
- - Objectives.Add(new KillObjective(20, new[] { typeof(Brigand) }, 1074894)); // Common brigands - - Rewards.Add(ItemReward.BagOfTreasure); - } - } - - [QuesterName("Beotham (Sanctuary)")] - public class Beotham : BaseCreature - { - [Constructible] - public Beotham() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the bowcrafter"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new Sandals(0x901)); - AddItem(new ShortPants(0x522)); - AddItem(new FancyShirt(0x515)); - - Item item; - - item = new LeafGloves(); - item.Hue = 0x901; - AddItem(item); - } - - public Beotham(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Beotham"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074187, // Want a job? - 1074184)); // Come here, I have work for you. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Danoel (Sanctuary)")] - public class Danoel : BaseCreature - { - [Constructible] - public Danoel() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the metal weaver"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenBoots(0x901)); - AddItem(new ElvenPants(0x386)); - AddItem(new ElvenShirt(0x75F)); - AddItem(new FullApron(0x1BB)); - AddItem(new RoyalCirclet()); - AddItem(new SmithHammer()); - } - - public Danoel(Serial serial) - : base(serial) - { - } - // TODO: Add quests: Spring Cleaning - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Danoel"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1074197); // Pardon me, but if you could spare some time I�d greatly appreciate it. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Tallinin (Sanctuary)")] - public class Tallinin : BaseCreature - { - [Constructible] - public Tallinin() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the cloth weaver"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenBoots(0x901)); - AddItem(new Tunic(0x37)); - AddItem(new Cloak(0x735)); - } - - public Tallinin(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Tallinin"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074188, // Weakling! You are not up to the task I have. - 1074211)); // I could use some help. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Tiana (Sanctuary)")] - public class Tiana : BaseCreature - { - [Constructible] - public Tiana() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the guard"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenBoots()); - AddItem(new HidePants()); - AddItem(new HideFemaleChest()); - AddItem(new HidePauldrons()); - - Item item; - - item = new WoodlandBelt(); - item.Hue = 0x673; - AddItem(item); - - item = new RavenHelm(); - item.Hue = 0x443; - AddItem(item); - } - - public Tiana(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Tiana"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074214, // Knave! Come here right now! - 1074218)); // Hey!� I want to talk to you, now. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Oolua (Sanctuary)")] - public class LorekeeperOolua : BaseCreature - { - [Constructible] - public LorekeeperOolua() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the keeper of tradition"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenBoots(0x75A)); - AddItem(new Skirt(Utility.RandomBrightHue())); - AddItem(new FancyShirt(0x742)); - AddItem(new Cloak(0x1BB)); - AddItem(new WildStaff()); - } - - public LorekeeperOolua(Serial serial) - : base(serial) - { - } - // TODO: Add quest Dreadhorn - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Lorekeeper Oolua"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1074187); // Want a job? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Rollarn (Sanctuary)")] - public class LorekeeperRollarn : BaseCreature - { - [Constructible] - public LorekeeperRollarn() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the keeper of tradition"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new Sandals(0x1BB)); - AddItem(new Cloak(0x296)); - AddItem(new Circlet()); - AddItem(new LeafChest()); - - Item item; - - item = new LeafLegs(); - item.Hue = 0x71A; - AddItem(item); - } - - public LorekeeperRollarn(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Lorekeeper Rollarn"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074196, // Excuse me! I�m sorry to interrupt but I urgently need some assistance. - 1074197)); // Pardon me, but if you could spare some time I�d greatly appreciate it. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Dallid (Sanctuary)")] - public class Dallid : BaseCreature - { - [Constructible] - public Dallid() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the cook"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new Boots(0x901)); - AddItem(new ShortPants(0x73C)); - AddItem(new Shirt(0x744)); - AddItem(new FullApron(0x1BE)); - AddItem(new Cleaver()); - } - - public Dallid(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Dallid"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074185, // Hey you! Want to help me out? - 1074195)); // You there, in the stupid hat! Come here. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Canir (Sanctuary)")] - public class Canir : BaseCreature - { - [Constructible] - public Canir() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the thaumaturgist"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new Sandals(0x1BB)); - AddItem(new FemaleElvenRobe(0x5A7)); - AddItem(new GemmedCirclet()); - AddItem(new MagicWand()); - } - - public Canir(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Canir"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074193, // You there! Yes you. Stop looking about like a toadie and come here. - 1074186)); // Come here, I have a task. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Yellienir : BaseCreature - { - [Constructible] - public Yellienir() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the bark weaver"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new ElvenBoots()); - AddItem(new LeafTonlet()); - AddItem(new FemaleLeafChest()); - AddItem(new LeafArms()); - AddItem(new Cloak(0x3B2)); - } - - public Yellienir(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "Yellienir"; - public override bool IsInvulnerable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Elder Onallan (Sanctuary)")] - public class ElderOnallan : BaseCreature - { - [Constructible] - public ElderOnallan() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the wise"; - Race = Race.Elf; - BodyValue = 0x25D; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new Shoes(0x729)); - AddItem(new WildStaff()); - AddItem(new Cloak(0x64E)); - } - - public ElderOnallan(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Elder Onallan"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074217, // I want to make you an offer you�d be a fool to �refuse. - 1074218)); // Hey!� I want to talk to you, now. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; +using Server.Engines.Spawners; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Definitions +{ + public class BrokenShaft : MLQuest + { + public BrokenShaft() + { + Activated = true; + HasRestartDelay = true; + Title = 1074018; // Broken Shaft + Description = + 1074112; // What do humans know of archery? Humans can barely shoot straight. Why, your efforts are absurd. In fact, I will make a wager - if these so called human arrows I've heard about are really as effective and innovative as human braggarts would have me believe, then I'll trade you something useful. I might even teach you something of elven craftsmanship. + RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. + InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! + CompletionMessage = + 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! + + Objectives.Add(new CollectObjective(10, typeof(Arrow), 1023902)); // arrow + + Rewards.Add(ItemReward.FletchingSatchel); + } + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Beotham"), new Point3D(6285, 114, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Beotham"), new Point3D(6285, 114, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Danoel"), new Point3D(6282, 116, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Danoel"), new Point3D(6282, 116, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Tallinin"), new Point3D(6279, 122, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Tallinin"), new Point3D(6279, 122, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Tiana"), new Point3D(6257, 112, -10), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Tiana"), new Point3D(6257, 112, -10), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 0, "LorekeeperOolua"), new Point3D(6250, 124, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 0, "LorekeeperOolua"), new Point3D(6250, 124, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 0, "LorekeeperRollarn"), new Point3D(6244, 110, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 0, "LorekeeperRollarn"), new Point3D(6244, 110, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Dallid"), new Point3D(6277, 104, -10), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Dallid"), new Point3D(6277, 104, -10), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Canir"), new Point3D(6274, 130, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Canir"), new Point3D(6274, 130, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Yellienir"), new Point3D(6257, 126, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Yellienir"), new Point3D(6257, 126, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 0, "ElderOnallan"), new Point3D(6258, 108, -10), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 0, "ElderOnallan"), new Point3D(6258, 108, -10), Map.Felucca); + } + } + + public class BendingTheBow : MLQuest + { + public BendingTheBow() + { + Activated = true; + HasRestartDelay = true; + Title = 1074019; // Bending the Bow + Description = + 1074113; // Human craftsmanship! Ha! Why, take an elven bow. It will last for a lifetime, never break and always shoot an arrow straight and true. Can't say the same for a human, can you? Bring me some of these human made bows, and I will show you. + RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. + InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! + CompletionMessage = + 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! + + Objectives.Add(new CollectObjective(10, typeof(Bow), 1025041)); // bow + + Rewards.Add(ItemReward.FletchingSatchel); + } + } + + public class ArmsRace : MLQuest + { + public ArmsRace() + { + Activated = true; + HasRestartDelay = true; + Title = 1074020; // Arms Race + Description = + 1074114; // Leave it to a human to try and improve upon perfection. To take a bow and turn it into a mechanical contraption like a crossbow. I wish to see more of this sort of "invention". Fetch for me a crossbow, human. + RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. + InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! + CompletionMessage = + 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! + + Objectives.Add(new CollectObjective(10, typeof(Crossbow), 1023919)); // crossbow + + Rewards.Add(ItemReward.FletchingSatchel); + } + } + + public class ImprovedCrossbows : MLQuest + { + public ImprovedCrossbows() + { + Activated = true; + HasRestartDelay = true; + Title = 1074021; // Improved Crossbows + Description = + 1074115; // How lazy is man! You cannot even be bothered to pull your own drawstring and hold an arrow ready? You must invent a device to do it for you? I cannot understand, but perhaps if I examine a heavy crossbow for myself, I will see their appeal. Go and bring me such a device and I will repay your meager favor. + RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. + InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! + CompletionMessage = + 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! + + Objectives.Add(new CollectObjective(10, typeof(HeavyCrossbow), 1025116)); // heavy crossbow + + Rewards.Add(ItemReward.FletchingSatchel); + } + } + + public class BuildingTheBetterCrossbow : MLQuest + { + public BuildingTheBetterCrossbow() + { + Activated = true; + HasRestartDelay = true; + Title = 1074022; // Building the Better Crossbow + Description = + 1074116; // More is always better for a human, eh? Take these repeating crossbows. What sort of mind invents such a thing? I must look at it more closely. Bring such a contraption to me and you'll receive a token for your efforts. + RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. + InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! + CompletionMessage = + 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! + + Objectives.Add(new CollectObjective(10, typeof(RepeatingCrossbow), 1029923)); // repeating crossbow + + Rewards.Add(ItemReward.FletchingSatchel); + } + } + + public class InstrumentOfWar : MLQuest + { + public InstrumentOfWar() + { + Activated = true; + HasRestartDelay = true; + Title = 1074055; // Instrument of War + Description = + 1074149; // Pathetic, this human craftsmanship! Take their broadswords - overgrown butter knives, in reality. No, I cannot do them justice - you must see for yourself. Bring me broadswords and I will demonstrate their feebleness. + RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. + InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! + CompletionMessage = + 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! + + Objectives.Add(new CollectObjective(12, typeof(Broadsword), 1023934)); // broadsword + + Rewards.Add(ItemReward.BlacksmithSatchel); + } + } + + public class TheShield : MLQuest + { + public TheShield() + { + Activated = true; + HasRestartDelay = true; + Title = 1074054; // The Shield + Description = + 1074148; // I doubt very much a human shield would stop a good stout elven arrow. You doubt me? I will show you - get me some of these heater shields and I will piece them with sharp elven arrows! + RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. + InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! + CompletionMessage = + 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! + + Objectives.Add(new CollectObjective(10, typeof(HeaterShield), 1027030)); // heater shield + + Rewards.Add(ItemReward.BlacksmithSatchel); + } + } + + public class MusicToMyEars : MLQuest + { + public MusicToMyEars() + { + Activated = true; + HasRestartDelay = true; + Title = 1074023; // Music to my Ears + Description = + 1074117; // You think you know something of music? Laughable! Take your lap harp. Crude, indelicate instruments that make a noise not unlike the wailing of a choleric child or a dying cat. I will show you - bring lap harps, and I will demonstrate. + RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. + InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! + CompletionMessage = + 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! + + Objectives.Add(new CollectObjective(10, typeof(LapHarp), 1023762)); // lap harp + + Rewards.Add(ItemReward.CarpentrySatchel); + } + } + + public class TheGlassEye : MLQuest + { + public TheGlassEye() + { + Activated = true; + HasRestartDelay = true; + Title = 1074050; // The Glass Eye + Description = + 1074144; // Humans are so pathetically weak, they must be augmented by glass and metal! Imagine such a thing! I must see one of these spyglasses for myself, to understand the pathetic limits of human sight! + RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. + InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! + CompletionMessage = + 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! + + Objectives.Add(new CollectObjective(10, typeof(Spyglass), 1025365)); // spyglass + + Rewards.Add(ItemReward.TinkerSatchel); + } + } + + public class LazyHumans : MLQuest + { + public LazyHumans() + { + Activated = true; + HasRestartDelay = true; + Title = 1074024; // Lazy Humans + Description = + 1074118; // Human fancy knows no bounds! It's pathetic that they are so weak that they must create a special stool upon which to rest their feet when they recline! Humans don't have any clue how to live. Bring me some of these foot stools to examine and I may teach you something worthwhile. + RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. + InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! + CompletionMessage = + 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! + + Objectives.Add(new CollectObjective(10, typeof(FootStool), 1022910)); // foot stool + + Rewards.Add(ItemReward.CarpentrySatchel); + } + } + + public class InventiveTools : MLQuest + { + public InventiveTools() + { + Activated = true; + HasRestartDelay = true; + Title = 1074048; // Inventive Tools + Description = + 1074142; // Bring me some of these tinker's tools! I am certain, in the hands of an elf, they will fashion objects of ingenuity and delight that will shame all human invention! Hurry, do this quickly and I might deign to show you my skill. + RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. + InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! + CompletionMessage = + 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! + + Objectives.Add(new CollectObjective(10, typeof(TinkerTools), 1027868)); // tinker's tools + + Rewards.Add(ItemReward.TinkerSatchel); + } + } + + public class PixieDustToDust : MLQuest + { + public PixieDustToDust() + { + Activated = true; + Title = 1073661; // Pixie dust to dust + Description = + 1073700; // Is there anything more foul than a pixie? They have cruel eyes and a mind for mischief, I say. I don't care if some think they're cute -- I say kill them and let the Avatar sort them out. In fact, if you were to kill a few pixies, I'd make sure you had a few coins to rub together, if you get my meaning. + RefusalMessage = 1073733; // Perhaps you'll change your mind and return at some point. + InProgressMessage = 1073741; // There's too much cuteness in the world -- kill those pixies! + + Objectives.Add(new KillObjective(10, new[] { typeof(Pixie) }, "pixies")); + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + } + + public class AnImpressivePlaid : MLQuest + { + public AnImpressivePlaid() + { + Activated = true; + HasRestartDelay = true; + Title = 1074044; // An Impressive Plaid + Description = + 1074138; // I do not believe humans are so ridiculous as to wear something called a "kilt". Bring for me some of these kilts, if they truly exist, and I will offer you meager reward. + RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. + InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! + CompletionMessage = + 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! + + Objectives.Add(new CollectObjective(10, typeof(Kilt), 1025431)); // kilt + + Rewards.Add(ItemReward.TailorSatchel); + } + } + + public class ANiceShirt : MLQuest + { + public ANiceShirt() + { + Activated = true; + HasRestartDelay = true; + Title = 1074045; // A Nice Shirt + Description = + 1074139; // Humans call that a fancy shirt? I would wager the ends are frayed, the collar worn, the buttons loosely stitched. Bring me fancy shirts and I will demonstrate the many ways in which they are inferior. + RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. + InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! + CompletionMessage = + 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! + + Objectives.Add(new CollectObjective(10, typeof(FancyShirt), 1027933)); // fancy shirt + + Rewards.Add(ItemReward.TailorSatchel); + } + } + + public class LeatherAndLace : MLQuest + { + public LeatherAndLace() + { + Activated = true; + HasRestartDelay = true; + Title = 1074047; // Leather and Lace + Description = + 1074141; // No self respecting elf female would ever wear a studded bustier! I will prove it - bring me such clothing and I will show you how ridiculous they are! + RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. + InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! + CompletionMessage = + 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! + + Objectives.Add(new CollectObjective(10, typeof(StuddedBustierArms), 1027180)); // studded bustier + + Rewards.Add(ItemReward.TailorSatchel); + } + } + + public class FeyHeadgear : MLQuest + { + public FeyHeadgear() + { + Activated = true; + HasRestartDelay = true; + Title = 1074043; // Fey Headgear + Description = + 1074137; // Humans do not deserve to wear a thing such as a flower garland. Help me prevent such things from falling into the clumsy hands of humans -- bring me flower garlands! + RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. + InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! + CompletionMessage = + 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! + + Objectives.Add(new CollectObjective(10, typeof(FlowerGarland), 1028965)); // flower garland + + Rewards.Add(ItemReward.TailorSatchel); + } + } + + public class NewCloak : MLQuest + { + public NewCloak() + { + Activated = true; + Title = 1074684; // New Cloak + Description = + 1074685; // I have created a masterpiece! And all I need to finish it off is the soft fur of a wolf. But not just ANY wolf -- oh no, no, that wouldn't do. I've heard tales of a mighty beast, Grobu, who is bonded to the leader of the troglodytes. Only Grobu's fur will do. Will you retrieve it for me? + RefusalMessage = 1074655; // Perhaps I thought too highly of you. + InProgressMessage = + 1074686; // I've told you all I know of the creature. Until you return with Grobu's fur I can't finish my cloak. + CompletionMessage = 1074687; // Ah! So soft, so supple. What a wonderful texture. Here you are ... my thanks. + + Objectives.Add(new CollectObjective(1, typeof(GrobusFur), "Grobu's Fur")); + + Rewards.Add(ItemReward.TailorSatchel); + } + } + + public class ADishBestServedCold : MLQuest + { + public ADishBestServedCold() + { + Activated = true; + Title = 1072372; // A Dish Best Served Cold + Description = + 1072657; // *mutter* I'll have my revenge. Oh! You there. Fancy some orc extermination? I despise them all. Bombers, brutes -- you name it, if it's orcish I want it killed. + RefusalMessage = 1072667; // Hrmph. Well maybe another time then. + InProgressMessage = 1072668; // Shouldn't you be slaying orcs? + + Objectives.Add( + new KillObjective( + 10, + new[] { typeof(Orc) }, + "orcs", + new QuestArea(1074807, "Sanctuary") + ) + ); // Sanctuary + Objectives.Add( + new KillObjective( + 5, + new[] { typeof(OrcBomber) }, + "orc bombers", + new QuestArea(1074807, "Sanctuary") + ) + ); // Sanctuary + Objectives.Add( + new KillObjective( + 3, + new[] { typeof(OrcBrute) }, + "orc brutes", + new QuestArea(1074807, "Sanctuary") + ) + ); // Sanctuary + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + public class ArchEnemies : MLQuest + { + public ArchEnemies() + { + Activated = true; + Title = 1073085; // Arch Enemies + Description = + 1073575; // Vermin! They get into everything! I told the boy to leave out some poisoned cheese -- and they shot him. What else can I do? Unless�these ratmen are skilled with a bow, but I'd lay a wager you're better, eh? Could you skin a few of the wretches for me? + RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. + InProgressMessage = + 1073595; // I don't see 10 tails from Ratman Archers on your belt -- and until I do, no reward for you. + + Objectives.Add(new KillObjective(10, new[] { typeof(RatmanArcher) }, "ratman archers")); + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + public class Vermin : MLQuest + { + public Vermin() + { + Activated = true; + Title = 1072995; // Vermin + Description = + 1073029; // You've got to help me out! Those ratmen have been causing absolute havok around here. Kill them off before they destroy my land. I'll pay you if you kill off twelve of those dirty rats. + RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me. + InProgressMessage = 1072271; // You're not quite done yet. Get back to work! + + Objectives.Add(new KillObjective(12, new[] { typeof(Ratman) }, "ratmen")); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class MougGuurMustDie : MLQuest + { + public MougGuurMustDie() + { + Activated = true; + Title = 1072368; // Moug-Guur Must Die + Description = + 1072561; // You there! Yes, you. Kill Moug-Guur, the leader of the orcs in this depressing place, and I'll make it worth your while. + RefusalMessage = 1072571; // Fine. It's no skin off my teeth. + InProgressMessage = 1072572; // Small words. Kill Moug-Guur. Go. Now! + CompletionMessage = + 1072573; // You're better than I thought you'd be. Not particularly bad, but not entirely inept. + + Objectives.Add( + new KillObjective( + 1, + new[] { typeof(MougGuur) }, + "Moug-Guur", + new QuestArea(1074807, "Sanctuary") + ) + ); // Sanctuary + + Rewards.Add(ItemReward.BagOfTreasure); + } + + public override Type NextQuest => typeof(LeaderOfThePack); + } + + public class LeaderOfThePack : MLQuest + { + public LeaderOfThePack() + { + Activated = true; + Title = 1072560; // Leader of the Pack + Description = + 1072574; // Well now that Moug-Guur is no more -- and I can't say I'm weeping for his demise -- it's time for the ratmen to experience a similar loss of leadership. Slay Chiikkaha. In return, I'll satisfy your greed temporarily. + RefusalMessage = + 1072575; // Alright, if you'd rather not, then run along and do whatever worthless things you do when I'm not giving you direction. + InProgressMessage = + 1072576; // How difficult is this? The rats live in the tunnels. Go into the tunnels and find the biggest, meanest rat and execute him. Loitering around here won't get the task done. + CompletionMessage = 1072577; // It's about time! Could you have taken longer? + + Objectives.Add( + new KillObjective( + 1, + new[] { typeof(Chiikkaha) }, + "Chiikkaha", + new QuestArea(1074807, "Sanctuary") + ) + ); // Sanctuary + + Rewards.Add(ItemReward.BagOfTreasure); + } + + public override Type NextQuest => typeof(SayonaraSzavetra); + public override bool IsChainTriggered => true; + } + + public class SayonaraSzavetra : MLQuest + { + public SayonaraSzavetra() + { + Activated = true; + Title = 1072375; // Sayonara, Szavetra + Description = + 1072578; // Hmm, maybe you aren't entirely worthless. I suspect a demoness of Szavetra's calibre will tear you apart ... We might as well find out. Kill the succubus, yada yada, and you'll be richly rewarded. + RefusalMessage = 1072579; // Hah! I knew you couldn't handle it. + InProgressMessage = + 1072581; // Hahahaha! I can see the fear in your eyes. Pathetic. Szavetra is waiting for you. + CompletionMessage = + 1072582; // Amazing! Simply astonishing ... you survived. Well, I supposed I should indulge your avarice with a reward. + + Objectives.Add( + new KillObjective( + 1, + new[] { typeof(Szavetra) }, + "Szavetra", + new QuestArea(1074807, "Sanctuary") + ) + ); // Sanctuary + + Rewards.Add(ItemReward.Strongbox); + } + + public override bool IsChainTriggered => true; + } + + public class TappingTheKeg : MLQuest + { + public TappingTheKeg() + { + Activated = true; + HasRestartDelay = true; + Title = 1074037; // Tapping the Keg + Description = + 1074131; // I have acquired a barrel of human brewed beer. I am loathe to drink it, but how else to prove how inferior it is? I suppose I shall need a barrel tap to drink. Go, bring me a barrel tap quickly, so I might get this over with. + RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. + InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! + CompletionMessage = + 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! + + Objectives.Add(new CollectObjective(10, typeof(BarrelTap), 1024100)); // barrel tap + + Rewards.Add(ItemReward.TinkerSatchel); + } + } + + public class WaitingToBeFilled : MLQuest + { + public WaitingToBeFilled() + { + Activated = true; + HasRestartDelay = true; + Title = 1074036; // Waiting to be Filled + Description = + 1074130; // The only good thing I can say about human made bottles is that they are empty and may yet still be filled with elven wine. Go now, fetch a number of empty bottles so that I might save them from the fate of carrying human-made wine. + RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. + InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! + CompletionMessage = + 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! + + Objectives.Add(new CollectObjective(20, typeof(Bottle), 1023854)); // empty bottle + + Rewards.Add(ItemReward.TinkerSatchel); + } + } + + public class BreezesSong : MLQuest + { + public BreezesSong() + { + Activated = true; + HasRestartDelay = true; + Title = 1074052; // Breeze's Song + Description = + 1074146; // I understand humans cruely enslave the very wind to their selfish whims! Fancy wind chimes, what a monstrous idea! You must bring me proof of this terrible depredation - hurry, bring me wind chimes! + RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. + InProgressMessage = 1074064; // Hurry up! I don't have all day to wait for you to bring what I desire! + CompletionMessage = + 1074065; // These human made goods are laughable! It offends so -- I must show you what elven skill is capable of! + + Objectives.Add(new CollectObjective(10, typeof(FancyWindChimes), 1030291)); // fancy wind chimes + + Rewards.Add(ItemReward.TinkerSatchel); + } + } + + public class ProofOfTheDeed : MLQuest + { + public ProofOfTheDeed() + { + Activated = true; + Title = 1072339; // Proof of the Deed + Description = + 1072340; // These human vermin must be erradicated! They despoil fair Sosaria with their every footfall upon her soil, every exhalation of breath upon her pristine air. Prove yourself an ally of Sosaria and bring me 20 human ears as proof of your devotion to our cause. + RefusalMessage = + 1072342; // Do you find the task distasteful? Are you too weak to shoulder the duty of cleansing Sosaria? So be it. + InProgressMessage = + 1072343; // Well, where is the proof of your deed? I will honor your actions when you have brought me the ears of the human scum. + CompletionMessage = + 1072344; // Ah, well done. You have chosen the path of duty and fulfilled your task with honor. + + Objectives.Add(new CollectObjective(20, typeof(SeveredHumanEars), 1032591)); // severed human ears + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class Marauders : MLQuest + { + public Marauders() + { + Activated = true; + Title = 1072374; // Marauders + Description = + 1072686; // What a miserable place we live in. Look around you at the changes we've wrought. The trees are sprouting leaves once more and the grass is reclaiming the blood-soaked soil. Who would have imagined we'd find ourselves here? Our "neighbors" are anything but friendly and those ogres are the worst of the lot. Maybe you'd be interested in helping our community by disposing of some of our least amiable neighbors? + RefusalMessage = 1072687; // I quite understand your reluctance. If you reconsider, I'll be here. + InProgressMessage = 1072688; // You can't miss those ogres, they're huge and just outside the gates here. + + Objectives.Add( + new KillObjective( + 10, + new[] { typeof(Ogre) }, + "ogres", + new QuestArea(1074807, "Sanctuary") + ) + ); // Sanctuary + + Rewards.Add(ItemReward.BagOfTreasure); + } + + public override Type NextQuest => typeof(TheBrainsOfTheOperation); + } + + public class TheBrainsOfTheOperation : MLQuest + { + public TheBrainsOfTheOperation() + { + Activated = true; + Title = 1072692; // The Brains of the Operation + Description = + 1072707; // *sigh* We have so much to do to clean this area up. Even the fine work you did on those ogres didn't have much of an impact on the community. It's the ogre lords that direct the actions of the other ogres, let's strike at the leaders and perhaps that will thwart the miserable curs. + RefusalMessage = 1072708; // Reluctance doesn't become a hero like you. But, as you wish. + InProgressMessage = + 1072709; // Ogre Lords are pretty easy to recognize. They're the ones ordering the other ogres about in a lordly manner. Striking down their leadership will throw the ogres into confusion and dismay! + + Objectives.Add( + new KillObjective( + 10, + new[] { typeof(OgreLord) }, + "ogre lords", + new QuestArea(1074807, "Sanctuary") + ) + ); // Sanctuary + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + + public override Type NextQuest => typeof(TheBrawn); + public override bool IsChainTriggered => true; + } + + public class TheBrawn : MLQuest + { + public TheBrawn() + { + Activated = true; + Title = 1072693; // The Brawn + Description = + 1072710; // Inconceiveable! We've learned that the ogre leadership has recruited some heavy-duty guards to their cause. I've never personally fought a cyclopian warrior, but I'm sure you could easily best a few and report back how much trouble they'll cause to our growing community? + RefusalMessage = 1072711; // Oh, I see. *sigh* Perhaps I overestimated your abilities. + InProgressMessage = 1072712; // Make sure you fully assess all of the cyclopian tactical abilities! + + Objectives.Add( + new KillObjective( + 6, + new[] { typeof(Cyclops) }, + "cyclops", + new QuestArea(1074807, "Sanctuary") + ) + ); // Sanctuary + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + + public override Type NextQuest => typeof(TheBiggerTheyAre); + public override bool IsChainTriggered => true; + } + + public class TheBiggerTheyAre : MLQuest + { + public TheBiggerTheyAre() + { + Activated = true; + Title = 1072694; // The Bigger They Are ... + Description = + 1072713; // The ogre insurgency has taken a turn for the worse! I've just been advised that the titans have concluded their discussions with the ogres and they've allied. We have virtually no information about titans. Engage them and appraise their mettle. + RefusalMessage = + 1072714; // Certainly. You've done enough to merit a breather. When you're ready for more, report back to me. + InProgressMessage = + 1072715; // Those titans don't skulk very well. You should be able to track them easily ... their footsteps are easily the largest around. + + Objectives.Add( + new KillObjective( + 3, + new[] { typeof(Titan) }, + "titans", + new QuestArea(1074807, "Sanctuary") + ) + ); // Sanctuary + + Rewards.Add(ItemReward.LargeBagOfTreasure); + } + + public override bool IsChainTriggered => true; + } + + public class TroubleOnTheWing : MLQuest + { + public TroubleOnTheWing() + { + Activated = true; + Title = 1072371; // Trouble on the Wing + Description = + 1072593; // Those gargoyles need to get knocked down a peg or two, if you ask me. They're always flying over here and lobbing things at us. What a nuisance. Drop a dozen of them for me, would you? + RefusalMessage = 1072594; // Don't tell me you're a gargoyle sympathizer? *spits* + InProgressMessage = + 1072595; // Those blasted gargoyles hang around the old tower. That's the best place to hunt them down. + + Objectives.Add( + new KillObjective( + 12, + new[] { typeof(Gargoyle) }, + "gargoyles", + new QuestArea(1074807, "Sanctuary") + ) + ); // Sanctuary + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class BrotherlyLove : MLQuest + { + public BrotherlyLove() + { + Activated = true; + OneTimeOnly = true; + Title = 1072369; // Brotherly Love + Description = + 1072585; // *looks around nervously* Do you travel to The Heartwood? I have an urgent letter that must be delivered there in the next 30 minutes -- to Ahie the Cloth Weaver. Will you undertake this journey? + RefusalMessage = 1072587; // *looks disappointed* Let me know if you change your mind. + InProgressMessage = + 1072588; // You haven't lost the letter have you? It must be delivered to Ahie directly. Give it into no other hands. + CompletionMessage = 1074579; // Yes, can I help you? + CompletionNotice = CompletionNoticeShort; + + Objectives.Add(new DeliverObjective(typeof(APersonalLetterAddressedToAhie), 1, "letter", typeof(Ahie))); + + Rewards.Add(ItemReward.BagOfTrinkets); + } + } + + public class CommonBrigands : MLQuest + { + public CommonBrigands() + { + Activated = true; + Title = 1073082; // Common Brigands + Description = + 1073572; // Thank goodness, a hero like you has arrived! Brigands have descended upon this area like locusts, stealing and looting where ever they go. We need someone to put these vile curs where they belong -- in their graves. Are you up to the task? + RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell. + InProgressMessage = 1073592; // The Brigands still plague us. Have you killed 20 of their number?
+ + Objectives.Add(new KillObjective(20, new[] { typeof(Brigand) }, 1074894)); // Common brigands + + Rewards.Add(ItemReward.BagOfTreasure); + } + } + + [QuesterName("Beotham (Sanctuary)")] + public class Beotham : BaseCreature + { + [Constructible] + public Beotham() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the bowcrafter"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new Sandals(0x901)); + AddItem(new ShortPants(0x522)); + AddItem(new FancyShirt(0x515)); + + Item item; + + item = new LeafGloves(); + item.Hue = 0x901; + AddItem(item); + } + + public Beotham(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Beotham"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074187, // Want a job? + 1074184 + ) + ); // Come here, I have work for you. + } + + 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(); + } + } + + [QuesterName("Danoel (Sanctuary)")] + public class Danoel : BaseCreature + { + [Constructible] + public Danoel() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the metal weaver"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenBoots(0x901)); + AddItem(new ElvenPants(0x386)); + AddItem(new ElvenShirt(0x75F)); + AddItem(new FullApron(0x1BB)); + AddItem(new RoyalCirclet()); + AddItem(new SmithHammer()); + } + + public Danoel(Serial serial) + : base(serial) + { + } + // TODO: Add quests: Spring Cleaning + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Danoel"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1074197); // Pardon me, but if you could spare some time I�d greatly appreciate it. + } + + 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(); + } + } + + [QuesterName("Tallinin (Sanctuary)")] + public class Tallinin : BaseCreature + { + [Constructible] + public Tallinin() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the cloth weaver"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenBoots(0x901)); + AddItem(new Tunic(0x37)); + AddItem(new Cloak(0x735)); + } + + public Tallinin(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Tallinin"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074188, // Weakling! You are not up to the task I have. + 1074211 + ) + ); // I could use some help. + } + + 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(); + } + } + + [QuesterName("Tiana (Sanctuary)")] + public class Tiana : BaseCreature + { + [Constructible] + public Tiana() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the guard"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenBoots()); + AddItem(new HidePants()); + AddItem(new HideFemaleChest()); + AddItem(new HidePauldrons()); + + Item item; + + item = new WoodlandBelt(); + item.Hue = 0x673; + AddItem(item); + + item = new RavenHelm(); + item.Hue = 0x443; + AddItem(item); + } + + public Tiana(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Tiana"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074214, // Knave! Come here right now! + 1074218 + ) + ); // Hey!� I want to talk to you, now. + } + + 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(); + } + } + + [QuesterName("Oolua (Sanctuary)")] + public class LorekeeperOolua : BaseCreature + { + [Constructible] + public LorekeeperOolua() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the keeper of tradition"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenBoots(0x75A)); + AddItem(new Skirt(Utility.RandomBrightHue())); + AddItem(new FancyShirt(0x742)); + AddItem(new Cloak(0x1BB)); + AddItem(new WildStaff()); + } + + public LorekeeperOolua(Serial serial) + : base(serial) + { + } + // TODO: Add quest Dreadhorn + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Lorekeeper Oolua"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1074187); // Want a job? + } + + 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(); + } + } + + [QuesterName("Rollarn (Sanctuary)")] + public class LorekeeperRollarn : BaseCreature + { + [Constructible] + public LorekeeperRollarn() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the keeper of tradition"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new Sandals(0x1BB)); + AddItem(new Cloak(0x296)); + AddItem(new Circlet()); + AddItem(new LeafChest()); + + Item item; + + item = new LeafLegs(); + item.Hue = 0x71A; + AddItem(item); + } + + public LorekeeperRollarn(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Lorekeeper Rollarn"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074196, // Excuse me! I�m sorry to interrupt but I urgently need some assistance. + 1074197 + ) + ); // Pardon me, but if you could spare some time I�d greatly appreciate it. + } + + 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(); + } + } + + [QuesterName("Dallid (Sanctuary)")] + public class Dallid : BaseCreature + { + [Constructible] + public Dallid() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the cook"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new Boots(0x901)); + AddItem(new ShortPants(0x73C)); + AddItem(new Shirt(0x744)); + AddItem(new FullApron(0x1BE)); + AddItem(new Cleaver()); + } + + public Dallid(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Dallid"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074185, // Hey you! Want to help me out? + 1074195 + ) + ); // You there, in the stupid hat! Come here. + } + + 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(); + } + } + + [QuesterName("Canir (Sanctuary)")] + public class Canir : BaseCreature + { + [Constructible] + public Canir() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the thaumaturgist"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new Sandals(0x1BB)); + AddItem(new FemaleElvenRobe(0x5A7)); + AddItem(new GemmedCirclet()); + AddItem(new MagicWand()); + } + + public Canir(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Canir"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074193, // You there! Yes you. Stop looking about like a toadie and come here. + 1074186 + ) + ); // Come here, I have a task. + } + + 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 class Yellienir : BaseCreature + { + [Constructible] + public Yellienir() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the bark weaver"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new ElvenBoots()); + AddItem(new LeafTonlet()); + AddItem(new FemaleLeafChest()); + AddItem(new LeafArms()); + AddItem(new Cloak(0x3B2)); + } + + public Yellienir(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "Yellienir"; + public override bool IsInvulnerable => true; + + 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(); + } + } + + [QuesterName("Elder Onallan (Sanctuary)")] + public class ElderOnallan : BaseCreature + { + [Constructible] + public ElderOnallan() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the wise"; + Race = Race.Elf; + BodyValue = 0x25D; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new Shoes(0x729)); + AddItem(new WildStaff()); + AddItem(new Cloak(0x64E)); + } + + public ElderOnallan(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Elder Onallan"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074217, // I want to make you an offer you�d be a fool to �refuse. + 1074218 + ) + ); // Hey!� I want to talk to you, now. + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Definitions/Spellweaving.cs b/Projects/UOContent/Engines/MLQuests/Definitions/Spellweaving.cs index 202f91651..732ac5720 100644 --- a/Projects/UOContent/Engines/MLQuests/Definitions/Spellweaving.cs +++ b/Projects/UOContent/Engines/MLQuests/Definitions/Spellweaving.cs @@ -1,706 +1,815 @@ -using System; -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; -using Server.Engines.Spawners; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Definitions -{ - public static class Spellweaving - { - public static void AwardTo(PlayerMobile pm) - { - if (pm == null) - return; - - MLQuestContext context = MLQuestSystem.GetOrCreateContext(pm); - - if (!context.Spellweaving) - { - context.Spellweaving = true; - - Effects.SendLocationParticles(EffectItem.Create(pm.Location, pm.Map, EffectItem.DefaultDuration), 0, 0, 0, 0, - 0, 5060, 0); - Effects.PlaySound(pm.Location, pm.Map, 0x243); - - Effects.SendMovingParticles(new Entity(Serial.Zero, new Point3D(pm.X - 6, pm.Y - 6, pm.Z + 15), pm.Map), pm, - 0x36D4, 7, 0, false, true, 0x497, 0, 9502, 1, 0, (EffectLayer)255, 0x100); - Effects.SendMovingParticles(new Entity(Serial.Zero, new Point3D(pm.X - 4, pm.Y - 6, pm.Z + 15), pm.Map), pm, - 0x36D4, 7, 0, false, true, 0x497, 0, 9502, 1, 0, (EffectLayer)255, 0x100); - Effects.SendMovingParticles(new Entity(Serial.Zero, new Point3D(pm.X - 6, pm.Y - 4, pm.Z + 15), pm.Map), pm, - 0x36D4, 7, 0, false, true, 0x497, 0, 9502, 1, 0, (EffectLayer)255, 0x100); - - Effects.SendTargetParticles(pm, 0x375A, 35, 90, 0x00, 0x00, 9502, (EffectLayer)255, 0x100); - } - } - } - - public class Patience : MLQuest - { - public Patience() - { - Activated = true; - Title = 1072753; // Patience - Description = - 1072762; // Learning to weave spells and control the forces of nature requires sacrifice, discipline, focus, and an unwavering dedication to Sosaria herself. We do not teach the unworthy. They do not comprehend the lessons nor the dedication required. If you would walk the path of the Arcanist, then you must do as I require without hesitation or question. Your first task is to gather miniature mushrooms ... 20 of them from the branches of our mighty home. I give you one hour to complete the task. - RefusalMessage = 1072767; // *nods* Not everyone has the temperment to undertake the way of the Arcanist. - InProgressMessage = - 1072774; // The mushrooms I seek can be found growing here in The Heartwood. Seek them out and gather them. You are running out of time. - CompletionMessage = 1074166; // Have you gathered the mushrooms? - - Objectives.Add(new TimedCollectObjective(TimeSpan.FromHours(1), 20, typeof(MiniatureMushroom), - "miniature mushrooms")); - - Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist. - } - - public override Type NextQuest => typeof(NeedsOfTheManyHeartwood1); - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 3, "Aeluva"), new Point3D(7064, 349, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 3, "Aeluva"), new Point3D(7064, 349, 0), Map.Trammel); - - // Split up to prevent stacking on the spawner - PutSpawner(new Spawner(20, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), 0, 30, "MiniatureMushroom"), - new Point3D(7015, 366, 0), Map.Felucca); - PutSpawner(new Spawner(20, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), 0, 30, "MiniatureMushroom"), - new Point3D(7015, 366, 0), Map.Trammel); - - PutSpawner(new Spawner(5, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), 0, 20, "MiniatureMushroom"), - new Point3D(7081, 373, 0), Map.Felucca); - PutSpawner(new Spawner(5, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), 0, 20, "MiniatureMushroom"), - new Point3D(7081, 373, 0), Map.Trammel); - - PutSpawner(new Spawner(15, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), 0, 20, "MiniatureMushroom"), - new Point3D(7052, 414, 0), Map.Felucca); - PutSpawner(new Spawner(15, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), 0, 20, "MiniatureMushroom"), - new Point3D(7052, 414, 0), Map.Trammel); - } - } - - public class NeedsOfTheManyHeartwood1 : MLQuest - { - public NeedsOfTheManyHeartwood1() - { - Activated = true; - Title = 1072797; // Needs of the Many - The Heartwood - Description = - 1072763; // The way of the Arcanist involves cooperation with others and a strong commitment to the community of your people. We have run low on the cotton we use to pack wounds and our people have need. Bring 10 bales of cotton to me. - RefusalMessage = 1072768; // You endanger your progress along the path with your unwillingness. - InProgressMessage = 1072775; // I care not where you acquire the cotton, merely that you provide it. - CompletionMessage = 1074110; // Well, where are the cotton bales? - - Objectives.Add(new CollectObjective(10, typeof(Cotton), 1023577)); // bale of cotton - - Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist. - } - - public override Type NextQuest => typeof(NeedsOfTheManyHeartwood2); - public override bool IsChainTriggered => true; - } - - public class NeedsOfTheManyHeartwood2 : MLQuest - { - public NeedsOfTheManyHeartwood2() - { - Activated = true; - Title = 1072797; // Needs of the Many - The Heartwood - Description = 1072764; // We must look to the defense of our people! Bring boards for new arrows. - RefusalMessage = - 1072769; // The people have need of these items. You are proving yourself inadequate to the demands of a member of this community. - InProgressMessage = 1072776; // The requirements are simple -- 250 boards. - CompletionMessage = 1074152; // Well, where are the boards? - - Objectives.Add(new CollectObjective(250, typeof(Board), 1027127)); // board - - Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist. - } - - public override Type NextQuest => typeof(MakingAContributionHeartwood); - public override bool IsChainTriggered => true; - } - - public class MakingAContributionHeartwood : MLQuest - { - public MakingAContributionHeartwood() - { - Activated = true; - Title = 1072798; // Making a Contribution - The Heartwood - Description = - 1072765; // With health and defense assured, we need look to the need of the community for food and drink. We will feast on fish steaks, sweets, and wine. You will supply the ingredients, the cooks will prepare the meal. As a Arcanist relies upon others to build focus and lend their power to her workings, the community needs the effort of all to survive. - RefusalMessage = 1072770; // Do not falter now. You have begun to show promise. - InProgressMessage = 1072777; // Where are the items you've been tasked to supply for the feast? - CompletionMessage = 1074158; // Ah good, you're back. We're eager for the feast. - - Objectives.Add(new CollectObjective(1, typeof(SackFlour), 1024153)); // sack of flour - Objectives.Add(new CollectObjective(10, typeof(JarHoney), 1022540)); // jar of honey - Objectives.Add(new CollectObjective(20, typeof(FishSteak), 1022427)); // fish steak - - Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist. - } - - public override Type NextQuest => typeof(UnnaturalCreations); - public override bool IsChainTriggered => true; - } - - public class UnnaturalCreations : MLQuest - { - public UnnaturalCreations() - { - Activated = true; - Title = 1072758; // Unnatural Creations - Description = - 1072780; // You have proven your desire to contribute to the community and serve the people. Now you must demonstrate your willingness to defend Sosaria from the greatest blight that plagues her. Unnatural creatures, brought to a sort of perverted life, despoil our fair world. Destroy them -- 5 Exodus Overseers and 2 Exodus Minions. - RefusalMessage = - 1072771; // You must serve Sosaria with all your heart and strength. Your unwillingness does not reflect favorably upon you. - InProgressMessage = 1072779; // Every moment you procrastinate, these unnatural creatures damage Sosaria. - CompletionMessage = 1074167; // Well done! Well done, indeed. You are worthy to become an arcanist! - - Objectives.Add(new KillObjective(5, new[] { typeof(ExodusOverseer) }, "Exodus Overseers")); - Objectives.Add(new KillObjective(2, new[] { typeof(ExodusMinion) }, "Exodus Minions")); - - Rewards.Add(new ItemReward(1031601, typeof(ArcaneCircleScroll))); // Arcane Circle - Rewards.Add(new ItemReward(1031600, typeof(SpellweavingBook))); // Spellweaving Spellbook - Rewards.Add(new ItemReward(1031602, typeof(GiftOfRenewalScroll))); // Gift of Renewal - } - - public override bool IsChainTriggered => true; - - public override void GetRewards(MLQuestInstance instance) - { - Spellweaving.AwardTo(instance.Player); - base.GetRewards(instance); - } - } - - public class Discipline : MLQuest - { - public Discipline() - { - Activated = true; - Title = 1072752; // Discipline - Description = - 1072761; // Learning to weave spells and control the forces of nature requires sacrifice, discipline, focus, and an unwavering dedication to Sosaria herself. We do not teach the unworthy. They do not comprehend the lessons nor the dedication required. If you would walk the path of the Arcanist, then you must do as I require without hesitation or question. Your first task is to rid our home of rats ... 50 of them in the next hour. - RefusalMessage = 1072767; // *nods* Not everyone has the temperament to undertake the way of the Arcanist. - InProgressMessage = 1072773; // You waste my time. The task is simple. Kill 50 rats in an hour. - // No completion message - - Objectives.Add(new TimedKillObjective(TimeSpan.FromHours(1), 50, new[] { typeof(Rat) }, "rats", - new QuestArea(1074807, "Sanctuary"))); // Sanctuary - - Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist. - } - - public override Type NextQuest => typeof(NeedsOfTheManySanctuary); - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Koole"), new Point3D(6257, 110, -10), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 0, "Koole"), new Point3D(6257, 110, -10), Map.Trammel); - } - } - - public class NeedsOfTheManySanctuary : MLQuest - { - public NeedsOfTheManySanctuary() - { - Activated = true; - Title = 1072754; // Needs of the Many - Sanctuary - Description = - 1072763; // The way of the Arcanist involves cooperation with others and a strong commitment to the community of your people. We have run low on the cotton we use to pack wounds and our people have need. Bring 10 bales of cotton to me. - RefusalMessage = 1072768; // You endanger your progress along the path with your unwillingness. - InProgressMessage = 1072775; // I care not where you acquire the cotton, merely that you provide it. - CompletionMessage = 1074110; // Well, where are the cotton bales? - - Objectives.Add(new CollectObjective(10, typeof(Cotton), 1023577)); // bale of cotton - - Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist. - } - - public override Type NextQuest => typeof(MakingAContributionSanctuary); - public override bool IsChainTriggered => true; - } - - public class MakingAContributionSanctuary : MLQuest - { - public MakingAContributionSanctuary() - { - Activated = true; - Title = 1072755; // Making a Contribution - Sanctuary - Description = 1072764; // We must look to the defense of our people! Bring boards for new arrows. - RefusalMessage = - 1072769; // The people have need of these items. You are proving yourself inadequate to the demands of a member of this community. - InProgressMessage = 1072776; // The requirements are simple -- 250 boards. - CompletionMessage = 1074152; // Well, where are the boards? - - Objectives.Add(new CollectObjective(250, typeof(Board), 1027127)); // board - - Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist. - } - - public override Type NextQuest => typeof(SuppliesForSanctuary); - public override bool IsChainTriggered => true; - } - - public class SuppliesForSanctuary : MLQuest - { - public SuppliesForSanctuary() - { - Activated = true; - Title = 1072756; // Supplies for Sanctuary - Description = - 1072765; // With health and defense assured, we need look to the need of the community for food and drink. We will feast on fish steaks, sweets, and wine. You will supply the ingredients, the cooks will prepare the meal. As a Arcanist relies upon others to build focus and lend their power to her workings, the community needs the effort of all to survive. - RefusalMessage = 1072770; // Do not falter now. You have begun to show promise. - InProgressMessage = 1072777; // Where are the items you've been tasked to supply for the feast? - CompletionMessage = 1074158; // Ah good, you're back. We're eager for the feast. - - Objectives.Add(new CollectObjective(1, typeof(SackFlour), 1024153)); // sack of flour - Objectives.Add(new CollectObjective(10, typeof(JarHoney), 1022540)); // jar of honey - Objectives.Add(new CollectObjective(20, typeof(FishSteak), 1022427)); // fish steak - - Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist. - } - - public override Type NextQuest => typeof(TheHumanBlight); - public override bool IsChainTriggered => true; - } - - public class TheHumanBlight : MLQuest - { - public TheHumanBlight() - { - Activated = true; - Title = 1072757; // The Human Blight - Description = - 1072766; // You have proven your desire to contribute to the community and serve the people. Now you must demonstrate your willingness to defend Sosaria from the greatest blight that plagues her. The human vermin that have spread as a disease, despoiling the land are the greatest blight we face. Kill humans and return to me the proof of your actions. Bring me 30 human ears. - RefusalMessage = - 1072771; // You must serve Sosaria with all your heart and strength. Your unwillingness does not reflect favorably upon you. - InProgressMessage = 1072778; // Why do you delay? The human blight must be averted. - CompletionMessage = 1074160; // I will take the ears you have collected now. Hand them here. - - Objectives.Add(new CollectObjective(30, typeof(SeveredHumanEars), 1032591)); // severed human ears - - Rewards.Add(new ItemReward(1031601, typeof(ArcaneCircleScroll))); // Arcane Circle - Rewards.Add(new ItemReward(1031600, typeof(SpellweavingBook))); // Spellweaving Spellbook - Rewards.Add(new ItemReward(1031602, typeof(GiftOfRenewalScroll))); // Gift of Renewal - } - - public override bool IsChainTriggered => true; - - public override void GetRewards(MLQuestInstance instance) - { - Spellweaving.AwardTo(instance.Player); - base.GetRewards(instance); - } - } - - public class FriendOfTheFey : MLQuest - { - public FriendOfTheFey() - { - Activated = true; - Title = 1074284; // Friend of the Fey - Description = - 1074286; // The children of Sosaria understand the dedication and committment of an arcanist -- and will, from time to time offer their friendship. If you would forge such a bond, first seek out a goodwill offering to present. Pixies enjoy sweets and pretty things. - RefusalMessage = 1074288; // There's always time to make new friends. - InProgressMessage = 1074290; // I think honey and some sparkly beads would please a pixie. - CompletionMessage = 1074292; // What have we here? Oh yes, gifts for a pixie. - - Objectives.Add(new CollectObjective(1, typeof(Beads), 1024235)); // beads - Objectives.Add(new CollectObjective(1, typeof(JarHoney), 1022540)); // jar of honey - - Rewards.Add(new DummyReward( - 1074874)); // The opportunity to prove yourself worthy of learning to Summon Fey. (Sufficient spellweaving skill is required to cast the spell) - } - - public override Type NextQuest => typeof(TokenOfFriendship); - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 3, "Synaeva"), new Point3D(7064, 350, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 3, "Synaeva"), new Point3D(7064, 350, 0), Map.Trammel); - } - } - - public class TokenOfFriendship : MLQuest - { - public TokenOfFriendship() - { - Activated = true; - Title = 1074293; // Token of Friendship - Description = - 1074297; // I've wrapped your gift suitably to present to a pixie of discriminating taste. Seek out Arielle and give her your offering. - RefusalMessage = 1074310; // I'll hold onto this gift in case you change your mind. - InProgressMessage = - 1074315; // Arielle wanders quite a bit, so I'm not sure exactly where to find her. I'm sure she's going to love your gift. - CompletionMessage = 1074319; // *giggle* Oooh! For me? - - Objectives.Add(new DeliverObjective(typeof(GiftForArielle), 1, "gift for Arielle", typeof(Arielle))); - - Rewards.Add(new DummyReward( - 1074874)); // The opportunity to prove yourself worthy of learning to Summon Fey. (Sufficient spellweaving skill is required to cast the spell) - } - - public override Type NextQuest => typeof(Alliance); - public override bool IsChainTriggered => true; - } - - public class Alliance : MLQuest - { - public Alliance() - { - Activated = true; - Title = 1074294; // Alliance - Description = 1074298; // *giggle* Mean reapers make pixies unhappy. *light-hearted giggle* You could fix them! - RefusalMessage = 1074311; // *giggle* Okies! - InProgressMessage = 1074316; // Mean reapers are all around trees! *giggle* You fix them up, please. - CompletionNotice = CompletionNoticeShortReturn; - - Objectives.Add(new KillObjective(20, new[] { typeof(Reaper) }, "reapers")); - - Rewards.Add(new ItemReward(1031607, typeof(SummonFeyScroll))); // Summon Fey - } - - public override bool IsChainTriggered => true; - - public override void GetRewards(MLQuestInstance instance) - { - instance.PlayerContext.SummonFey = true; - instance.Player.SendLocalizedMessage(1074320, "", - 0x2A); // *giggle* Mean reapers got fixed! Pixie friend now! *giggle* When mean thingies bother you, a brave pixie will help. - - base.GetRewards(instance); - } - } - - public class FiendishFriends : MLQuest - { - public FiendishFriends() - { - Activated = true; - Title = 1074283; // Fiendish Friends - Description = - 1074285; // It is true that a skilled arcanist can summon and dominate an imp to serve at their pleasure. To do such at thing though, you must master the miserable little fiends utterly by demonstrating your superiority. Rough them up some -- kill a few. That will do the trick. - RefusalMessage = 1074287; // You're probably right. They're not worth the effort. - InProgressMessage = 1074289; // Surely you're not having difficulties swatting down those annoying pests? - // TODO: Verify - CompletionMessage = 1074291; // Hah! You showed them! - - Objectives.Add(new KillObjective(50, new[] { typeof(Imp) }, "imps")); - - Rewards.Add(new DummyReward( - 1074873)); // The opportunity to prove yourself worthy of learning to Summon Fiends. (Sufficient spellweaving skill is required to cast the spell) - } - - public override Type NextQuest => typeof(CrackingTheWhipI); - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 0, "ElderBrae"), new Point3D(6266, 124, 0), Map.Felucca); - PutSpawner(new Spawner(1, 5, 10, 0, 0, "ElderBrae"), new Point3D(6266, 124, 0), Map.Trammel); - } - } - - // TODO: Verify - public class CrackingTheWhipI : MLQuest - { - public CrackingTheWhipI() - { - Activated = true; - Title = 1074295; // Cracking the Whip - Description = - 1074300; // Now that you've shown those mini pests your might, you should collect suitable implements to use to train your summoned pet. I suggest a stout whip. - RefusalMessage = 1074313; // Heh. Changed your mind, eh? - InProgressMessage = - 1074317; // Well, hurry up. If you don't get a whip how do you expect to control the little devil? - CompletionMessage = 1074321; // That's a well-made whip. No imp will ignore the sting of that lash. - - Objectives.Add(new CollectObjective(1, typeof(StoutWhip), "Stout Whip")); - - Rewards.Add(new DummyReward( - 1074873)); // The opportunity to prove yourself worthy of learning to Summon Fiends. (Sufficient spellweaving skill is required to cast the spell) - } - - public override Type NextQuest => typeof(CrackingTheWhipII); - public override bool IsChainTriggered => true; - } - - // TODO: Verify - public class CrackingTheWhipII : MLQuest - { - public CrackingTheWhipII() - { - Activated = true; - Title = 1074295; // Cracking the Whip - Description = - 1074302; // Now you just need to make the little buggers fear you -- if you can slay an arcane daemon, you'll earn their subservience. - RefusalMessage = 1074314; // If you're not up for it, so be it. - InProgressMessage = 1074318; // You need to vanquish an arcane daemon before the imps will fear you properly. - - Objectives.Add(new KillObjective(1, new[] { typeof(ArcaneDaemon) }, 1029733)); // arcane demon - - Rewards.Add(new ItemReward(1031608, typeof(SummonFiendScroll))); // Summon Fiend - } - - public override bool IsChainTriggered => true; - - public override void GetRewards(MLQuestInstance instance) - { - instance.PlayerContext.SummonFiend = true; - instance.Player.SendLocalizedMessage(1074322, "", - 0x2A); // You've demonstrated your strength, got a means of control, and taught the imps to fear you. You're ready now to summon them. - - base.GetRewards(instance); - } - } - - [QuesterName("Aeluva (The Heartwood)")] - public class Aeluva : BaseCreature - { - [Constructible] - public Aeluva() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2.0) - { - Title = "the arcanist"; - Race = Race.Elf; - Female = true; - Body = 606; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenShirt()); - AddItem(new Kilt(Utility.RandomNondyedHue())); // Note: OSI hue = 0x1516, typo? - AddItem(new ElvenBoots()); - AddItem(new Circlet()); - } - - public Aeluva(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Aeluva"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - /* - * 1074206 - Excuse me please traveler, might I have a little of your time? - * 1074207 - Good day to you friend! Allow me to offer you a fabulous opportunity!  Thrills and adventure await! - */ - MLQuestSystem.Tell(this, pm, Utility.Random(1074206, 2)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Koole (Sanctuary)")] - public class Koole : BaseCreature - { - [Constructible] - public Koole() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2.0) - { - Title = "the arcanist"; - Race = Race.Elf; - Body = 605; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - Item item; - - item = new LeafChest(); - item.Hue = 443; - AddItem(item); - - item = new LeafArms(); - item.Hue = 443; - AddItem(item); - - AddItem(new LeafTonlet()); - AddItem(new ThighBoots(Utility.RandomAnimalHue())); - AddItem(new RoyalCirclet()); - } - - public Koole(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Koole"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074186, // Come here, I have a task. - 1074218)); // Hey! I want to talk to you, now. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Synaeva (The Heartwood)")] - public class Synaeva : BaseCreature - { - [Constructible] - public Synaeva() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2.0) - { - Title = "the arcanist"; - Race = Race.Elf; - Female = true; - Body = 606; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - Item item = new RavenHelm(); - item.Hue = Utility.RandomGreenHue(); - AddItem(item); - - AddItem(new FemaleLeafChest()); - AddItem(new LeafArms()); - AddItem(new LeafTonlet()); - AddItem(new ElvenBoots()); - AddItem(new WildStaff()); - } - - public Synaeva(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Synaeva"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1074223); // Have you done it yet?  Oh, I haven’t told you, have I? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Elder Brae (Sanctuary)")] - public class ElderBrae : BaseCreature - { - [Constructible] - public ElderBrae() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2.0) - { - Title = "the wise"; - Race = Race.Elf; - Female = true; - Body = 606; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new GemmedCirclet()); - AddItem(new FemaleElvenRobe(Utility.RandomBrightHue())); - AddItem(new ElvenBoots(Utility.RandomAnimalHue())); - } - - public ElderBrae(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Elder Brae"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, Utility.RandomList( - 1074215, // Don’t test my patience you sniveling worm! - 1074218)); // Hey!  I want to talk to you, now. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; +using Server.Engines.Spawners; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Definitions +{ + public static class Spellweaving + { + public static void AwardTo(PlayerMobile pm) + { + if (pm == null) + return; + + var context = MLQuestSystem.GetOrCreateContext(pm); + + if (!context.Spellweaving) + { + context.Spellweaving = true; + + Effects.SendLocationParticles( + EffectItem.Create(pm.Location, pm.Map, EffectItem.DefaultDuration), + 0, + 0, + 0, + 0, + 0, + 5060, + 0 + ); + Effects.PlaySound(pm.Location, pm.Map, 0x243); + + Effects.SendMovingParticles( + new Entity(Serial.Zero, new Point3D(pm.X - 6, pm.Y - 6, pm.Z + 15), pm.Map), + pm, + 0x36D4, + 7, + 0, + false, + true, + 0x497, + 0, + 9502, + 1, + 0, + (EffectLayer)255, + 0x100 + ); + Effects.SendMovingParticles( + new Entity(Serial.Zero, new Point3D(pm.X - 4, pm.Y - 6, pm.Z + 15), pm.Map), + pm, + 0x36D4, + 7, + 0, + false, + true, + 0x497, + 0, + 9502, + 1, + 0, + (EffectLayer)255, + 0x100 + ); + Effects.SendMovingParticles( + new Entity(Serial.Zero, new Point3D(pm.X - 6, pm.Y - 4, pm.Z + 15), pm.Map), + pm, + 0x36D4, + 7, + 0, + false, + true, + 0x497, + 0, + 9502, + 1, + 0, + (EffectLayer)255, + 0x100 + ); + + Effects.SendTargetParticles(pm, 0x375A, 35, 90, 0x00, 0x00, 9502, (EffectLayer)255, 0x100); + } + } + } + + public class Patience : MLQuest + { + public Patience() + { + Activated = true; + Title = 1072753; // Patience + Description = + 1072762; // Learning to weave spells and control the forces of nature requires sacrifice, discipline, focus, and an unwavering dedication to Sosaria herself. We do not teach the unworthy. They do not comprehend the lessons nor the dedication required. If you would walk the path of the Arcanist, then you must do as I require without hesitation or question. Your first task is to gather miniature mushrooms ... 20 of them from the branches of our mighty home. I give you one hour to complete the task. + RefusalMessage = 1072767; // *nods* Not everyone has the temperment to undertake the way of the Arcanist. + InProgressMessage = + 1072774; // The mushrooms I seek can be found growing here in The Heartwood. Seek them out and gather them. You are running out of time. + CompletionMessage = 1074166; // Have you gathered the mushrooms? + + Objectives.Add( + new TimedCollectObjective( + TimeSpan.FromHours(1), + 20, + typeof(MiniatureMushroom), + "miniature mushrooms" + ) + ); + + Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist. + } + + public override Type NextQuest => typeof(NeedsOfTheManyHeartwood1); + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 3, "Aeluva"), new Point3D(7064, 349, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 3, "Aeluva"), new Point3D(7064, 349, 0), Map.Trammel); + + // Split up to prevent stacking on the spawner + PutSpawner( + new Spawner(20, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), 0, 30, "MiniatureMushroom"), + new Point3D(7015, 366, 0), + Map.Felucca + ); + PutSpawner( + new Spawner(20, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), 0, 30, "MiniatureMushroom"), + new Point3D(7015, 366, 0), + Map.Trammel + ); + + PutSpawner( + new Spawner(5, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), 0, 20, "MiniatureMushroom"), + new Point3D(7081, 373, 0), + Map.Felucca + ); + PutSpawner( + new Spawner(5, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), 0, 20, "MiniatureMushroom"), + new Point3D(7081, 373, 0), + Map.Trammel + ); + + PutSpawner( + new Spawner(15, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), 0, 20, "MiniatureMushroom"), + new Point3D(7052, 414, 0), + Map.Felucca + ); + PutSpawner( + new Spawner(15, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), 0, 20, "MiniatureMushroom"), + new Point3D(7052, 414, 0), + Map.Trammel + ); + } + } + + public class NeedsOfTheManyHeartwood1 : MLQuest + { + public NeedsOfTheManyHeartwood1() + { + Activated = true; + Title = 1072797; // Needs of the Many - The Heartwood + Description = + 1072763; // The way of the Arcanist involves cooperation with others and a strong commitment to the community of your people. We have run low on the cotton we use to pack wounds and our people have need. Bring 10 bales of cotton to me. + RefusalMessage = 1072768; // You endanger your progress along the path with your unwillingness. + InProgressMessage = 1072775; // I care not where you acquire the cotton, merely that you provide it. + CompletionMessage = 1074110; // Well, where are the cotton bales? + + Objectives.Add(new CollectObjective(10, typeof(Cotton), 1023577)); // bale of cotton + + Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist. + } + + public override Type NextQuest => typeof(NeedsOfTheManyHeartwood2); + public override bool IsChainTriggered => true; + } + + public class NeedsOfTheManyHeartwood2 : MLQuest + { + public NeedsOfTheManyHeartwood2() + { + Activated = true; + Title = 1072797; // Needs of the Many - The Heartwood + Description = 1072764; // We must look to the defense of our people! Bring boards for new arrows. + RefusalMessage = + 1072769; // The people have need of these items. You are proving yourself inadequate to the demands of a member of this community. + InProgressMessage = 1072776; // The requirements are simple -- 250 boards. + CompletionMessage = 1074152; // Well, where are the boards? + + Objectives.Add(new CollectObjective(250, typeof(Board), 1027127)); // board + + Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist. + } + + public override Type NextQuest => typeof(MakingAContributionHeartwood); + public override bool IsChainTriggered => true; + } + + public class MakingAContributionHeartwood : MLQuest + { + public MakingAContributionHeartwood() + { + Activated = true; + Title = 1072798; // Making a Contribution - The Heartwood + Description = + 1072765; // With health and defense assured, we need look to the need of the community for food and drink. We will feast on fish steaks, sweets, and wine. You will supply the ingredients, the cooks will prepare the meal. As a Arcanist relies upon others to build focus and lend their power to her workings, the community needs the effort of all to survive. + RefusalMessage = 1072770; // Do not falter now. You have begun to show promise. + InProgressMessage = 1072777; // Where are the items you've been tasked to supply for the feast? + CompletionMessage = 1074158; // Ah good, you're back. We're eager for the feast. + + Objectives.Add(new CollectObjective(1, typeof(SackFlour), 1024153)); // sack of flour + Objectives.Add(new CollectObjective(10, typeof(JarHoney), 1022540)); // jar of honey + Objectives.Add(new CollectObjective(20, typeof(FishSteak), 1022427)); // fish steak + + Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist. + } + + public override Type NextQuest => typeof(UnnaturalCreations); + public override bool IsChainTriggered => true; + } + + public class UnnaturalCreations : MLQuest + { + public UnnaturalCreations() + { + Activated = true; + Title = 1072758; // Unnatural Creations + Description = + 1072780; // You have proven your desire to contribute to the community and serve the people. Now you must demonstrate your willingness to defend Sosaria from the greatest blight that plagues her. Unnatural creatures, brought to a sort of perverted life, despoil our fair world. Destroy them -- 5 Exodus Overseers and 2 Exodus Minions. + RefusalMessage = + 1072771; // You must serve Sosaria with all your heart and strength. Your unwillingness does not reflect favorably upon you. + InProgressMessage = 1072779; // Every moment you procrastinate, these unnatural creatures damage Sosaria. + CompletionMessage = 1074167; // Well done! Well done, indeed. You are worthy to become an arcanist! + + Objectives.Add(new KillObjective(5, new[] { typeof(ExodusOverseer) }, "Exodus Overseers")); + Objectives.Add(new KillObjective(2, new[] { typeof(ExodusMinion) }, "Exodus Minions")); + + Rewards.Add(new ItemReward(1031601, typeof(ArcaneCircleScroll))); // Arcane Circle + Rewards.Add(new ItemReward(1031600, typeof(SpellweavingBook))); // Spellweaving Spellbook + Rewards.Add(new ItemReward(1031602, typeof(GiftOfRenewalScroll))); // Gift of Renewal + } + + public override bool IsChainTriggered => true; + + public override void GetRewards(MLQuestInstance instance) + { + Spellweaving.AwardTo(instance.Player); + base.GetRewards(instance); + } + } + + public class Discipline : MLQuest + { + public Discipline() + { + Activated = true; + Title = 1072752; // Discipline + Description = + 1072761; // Learning to weave spells and control the forces of nature requires sacrifice, discipline, focus, and an unwavering dedication to Sosaria herself. We do not teach the unworthy. They do not comprehend the lessons nor the dedication required. If you would walk the path of the Arcanist, then you must do as I require without hesitation or question. Your first task is to rid our home of rats ... 50 of them in the next hour. + RefusalMessage = 1072767; // *nods* Not everyone has the temperament to undertake the way of the Arcanist. + InProgressMessage = 1072773; // You waste my time. The task is simple. Kill 50 rats in an hour. + // No completion message + + Objectives.Add( + new TimedKillObjective( + TimeSpan.FromHours(1), + 50, + new[] { typeof(Rat) }, + "rats", + new QuestArea(1074807, "Sanctuary") + ) + ); // Sanctuary + + Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist. + } + + public override Type NextQuest => typeof(NeedsOfTheManySanctuary); + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Koole"), new Point3D(6257, 110, -10), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 0, "Koole"), new Point3D(6257, 110, -10), Map.Trammel); + } + } + + public class NeedsOfTheManySanctuary : MLQuest + { + public NeedsOfTheManySanctuary() + { + Activated = true; + Title = 1072754; // Needs of the Many - Sanctuary + Description = + 1072763; // The way of the Arcanist involves cooperation with others and a strong commitment to the community of your people. We have run low on the cotton we use to pack wounds and our people have need. Bring 10 bales of cotton to me. + RefusalMessage = 1072768; // You endanger your progress along the path with your unwillingness. + InProgressMessage = 1072775; // I care not where you acquire the cotton, merely that you provide it. + CompletionMessage = 1074110; // Well, where are the cotton bales? + + Objectives.Add(new CollectObjective(10, typeof(Cotton), 1023577)); // bale of cotton + + Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist. + } + + public override Type NextQuest => typeof(MakingAContributionSanctuary); + public override bool IsChainTriggered => true; + } + + public class MakingAContributionSanctuary : MLQuest + { + public MakingAContributionSanctuary() + { + Activated = true; + Title = 1072755; // Making a Contribution - Sanctuary + Description = 1072764; // We must look to the defense of our people! Bring boards for new arrows. + RefusalMessage = + 1072769; // The people have need of these items. You are proving yourself inadequate to the demands of a member of this community. + InProgressMessage = 1072776; // The requirements are simple -- 250 boards. + CompletionMessage = 1074152; // Well, where are the boards? + + Objectives.Add(new CollectObjective(250, typeof(Board), 1027127)); // board + + Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist. + } + + public override Type NextQuest => typeof(SuppliesForSanctuary); + public override bool IsChainTriggered => true; + } + + public class SuppliesForSanctuary : MLQuest + { + public SuppliesForSanctuary() + { + Activated = true; + Title = 1072756; // Supplies for Sanctuary + Description = + 1072765; // With health and defense assured, we need look to the need of the community for food and drink. We will feast on fish steaks, sweets, and wine. You will supply the ingredients, the cooks will prepare the meal. As a Arcanist relies upon others to build focus and lend their power to her workings, the community needs the effort of all to survive. + RefusalMessage = 1072770; // Do not falter now. You have begun to show promise. + InProgressMessage = 1072777; // Where are the items you've been tasked to supply for the feast? + CompletionMessage = 1074158; // Ah good, you're back. We're eager for the feast. + + Objectives.Add(new CollectObjective(1, typeof(SackFlour), 1024153)); // sack of flour + Objectives.Add(new CollectObjective(10, typeof(JarHoney), 1022540)); // jar of honey + Objectives.Add(new CollectObjective(20, typeof(FishSteak), 1022427)); // fish steak + + Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist. + } + + public override Type NextQuest => typeof(TheHumanBlight); + public override bool IsChainTriggered => true; + } + + public class TheHumanBlight : MLQuest + { + public TheHumanBlight() + { + Activated = true; + Title = 1072757; // The Human Blight + Description = + 1072766; // You have proven your desire to contribute to the community and serve the people. Now you must demonstrate your willingness to defend Sosaria from the greatest blight that plagues her. The human vermin that have spread as a disease, despoiling the land are the greatest blight we face. Kill humans and return to me the proof of your actions. Bring me 30 human ears. + RefusalMessage = + 1072771; // You must serve Sosaria with all your heart and strength. Your unwillingness does not reflect favorably upon you. + InProgressMessage = 1072778; // Why do you delay? The human blight must be averted. + CompletionMessage = 1074160; // I will take the ears you have collected now. Hand them here. + + Objectives.Add(new CollectObjective(30, typeof(SeveredHumanEars), 1032591)); // severed human ears + + Rewards.Add(new ItemReward(1031601, typeof(ArcaneCircleScroll))); // Arcane Circle + Rewards.Add(new ItemReward(1031600, typeof(SpellweavingBook))); // Spellweaving Spellbook + Rewards.Add(new ItemReward(1031602, typeof(GiftOfRenewalScroll))); // Gift of Renewal + } + + public override bool IsChainTriggered => true; + + public override void GetRewards(MLQuestInstance instance) + { + Spellweaving.AwardTo(instance.Player); + base.GetRewards(instance); + } + } + + public class FriendOfTheFey : MLQuest + { + public FriendOfTheFey() + { + Activated = true; + Title = 1074284; // Friend of the Fey + Description = + 1074286; // The children of Sosaria understand the dedication and committment of an arcanist -- and will, from time to time offer their friendship. If you would forge such a bond, first seek out a goodwill offering to present. Pixies enjoy sweets and pretty things. + RefusalMessage = 1074288; // There's always time to make new friends. + InProgressMessage = 1074290; // I think honey and some sparkly beads would please a pixie. + CompletionMessage = 1074292; // What have we here? Oh yes, gifts for a pixie. + + Objectives.Add(new CollectObjective(1, typeof(Beads), 1024235)); // beads + Objectives.Add(new CollectObjective(1, typeof(JarHoney), 1022540)); // jar of honey + + Rewards.Add( + new DummyReward( + 1074874 + ) + ); // The opportunity to prove yourself worthy of learning to Summon Fey. (Sufficient spellweaving skill is required to cast the spell) + } + + public override Type NextQuest => typeof(TokenOfFriendship); + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 3, "Synaeva"), new Point3D(7064, 350, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 3, "Synaeva"), new Point3D(7064, 350, 0), Map.Trammel); + } + } + + public class TokenOfFriendship : MLQuest + { + public TokenOfFriendship() + { + Activated = true; + Title = 1074293; // Token of Friendship + Description = + 1074297; // I've wrapped your gift suitably to present to a pixie of discriminating taste. Seek out Arielle and give her your offering. + RefusalMessage = 1074310; // I'll hold onto this gift in case you change your mind. + InProgressMessage = + 1074315; // Arielle wanders quite a bit, so I'm not sure exactly where to find her. I'm sure she's going to love your gift. + CompletionMessage = 1074319; // *giggle* Oooh! For me? + + Objectives.Add(new DeliverObjective(typeof(GiftForArielle), 1, "gift for Arielle", typeof(Arielle))); + + Rewards.Add( + new DummyReward( + 1074874 + ) + ); // The opportunity to prove yourself worthy of learning to Summon Fey. (Sufficient spellweaving skill is required to cast the spell) + } + + public override Type NextQuest => typeof(Alliance); + public override bool IsChainTriggered => true; + } + + public class Alliance : MLQuest + { + public Alliance() + { + Activated = true; + Title = 1074294; // Alliance + Description = 1074298; // *giggle* Mean reapers make pixies unhappy. *light-hearted giggle* You could fix them! + RefusalMessage = 1074311; // *giggle* Okies! + InProgressMessage = 1074316; // Mean reapers are all around trees! *giggle* You fix them up, please. + CompletionNotice = CompletionNoticeShortReturn; + + Objectives.Add(new KillObjective(20, new[] { typeof(Reaper) }, "reapers")); + + Rewards.Add(new ItemReward(1031607, typeof(SummonFeyScroll))); // Summon Fey + } + + public override bool IsChainTriggered => true; + + public override void GetRewards(MLQuestInstance instance) + { + instance.PlayerContext.SummonFey = true; + instance.Player.SendLocalizedMessage( + 1074320, + "", + 0x2A + ); // *giggle* Mean reapers got fixed! Pixie friend now! *giggle* When mean thingies bother you, a brave pixie will help. + + base.GetRewards(instance); + } + } + + public class FiendishFriends : MLQuest + { + public FiendishFriends() + { + Activated = true; + Title = 1074283; // Fiendish Friends + Description = + 1074285; // It is true that a skilled arcanist can summon and dominate an imp to serve at their pleasure. To do such at thing though, you must master the miserable little fiends utterly by demonstrating your superiority. Rough them up some -- kill a few. That will do the trick. + RefusalMessage = 1074287; // You're probably right. They're not worth the effort. + InProgressMessage = 1074289; // Surely you're not having difficulties swatting down those annoying pests? + // TODO: Verify + CompletionMessage = 1074291; // Hah! You showed them! + + Objectives.Add(new KillObjective(50, new[] { typeof(Imp) }, "imps")); + + Rewards.Add( + new DummyReward( + 1074873 + ) + ); // The opportunity to prove yourself worthy of learning to Summon Fiends. (Sufficient spellweaving skill is required to cast the spell) + } + + public override Type NextQuest => typeof(CrackingTheWhipI); + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 0, "ElderBrae"), new Point3D(6266, 124, 0), Map.Felucca); + PutSpawner(new Spawner(1, 5, 10, 0, 0, "ElderBrae"), new Point3D(6266, 124, 0), Map.Trammel); + } + } + + // TODO: Verify + public class CrackingTheWhipI : MLQuest + { + public CrackingTheWhipI() + { + Activated = true; + Title = 1074295; // Cracking the Whip + Description = + 1074300; // Now that you've shown those mini pests your might, you should collect suitable implements to use to train your summoned pet. I suggest a stout whip. + RefusalMessage = 1074313; // Heh. Changed your mind, eh? + InProgressMessage = + 1074317; // Well, hurry up. If you don't get a whip how do you expect to control the little devil? + CompletionMessage = 1074321; // That's a well-made whip. No imp will ignore the sting of that lash. + + Objectives.Add(new CollectObjective(1, typeof(StoutWhip), "Stout Whip")); + + Rewards.Add( + new DummyReward( + 1074873 + ) + ); // The opportunity to prove yourself worthy of learning to Summon Fiends. (Sufficient spellweaving skill is required to cast the spell) + } + + public override Type NextQuest => typeof(CrackingTheWhipII); + public override bool IsChainTriggered => true; + } + + // TODO: Verify + public class CrackingTheWhipII : MLQuest + { + public CrackingTheWhipII() + { + Activated = true; + Title = 1074295; // Cracking the Whip + Description = + 1074302; // Now you just need to make the little buggers fear you -- if you can slay an arcane daemon, you'll earn their subservience. + RefusalMessage = 1074314; // If you're not up for it, so be it. + InProgressMessage = 1074318; // You need to vanquish an arcane daemon before the imps will fear you properly. + + Objectives.Add(new KillObjective(1, new[] { typeof(ArcaneDaemon) }, 1029733)); // arcane demon + + Rewards.Add(new ItemReward(1031608, typeof(SummonFiendScroll))); // Summon Fiend + } + + public override bool IsChainTriggered => true; + + public override void GetRewards(MLQuestInstance instance) + { + instance.PlayerContext.SummonFiend = true; + instance.Player.SendLocalizedMessage( + 1074322, + "", + 0x2A + ); // You've demonstrated your strength, got a means of control, and taught the imps to fear you. You're ready now to summon them. + + base.GetRewards(instance); + } + } + + [QuesterName("Aeluva (The Heartwood)")] + public class Aeluva : BaseCreature + { + [Constructible] + public Aeluva() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2.0) + { + Title = "the arcanist"; + Race = Race.Elf; + Female = true; + Body = 606; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenShirt()); + AddItem(new Kilt(Utility.RandomNondyedHue())); // Note: OSI hue = 0x1516, typo? + AddItem(new ElvenBoots()); + AddItem(new Circlet()); + } + + public Aeluva(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Aeluva"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + /* + * 1074206 - Excuse me please traveler, might I have a little of your time? + * 1074207 - Good day to you friend! Allow me to offer you a fabulous opportunity!  Thrills and adventure await! + */ + MLQuestSystem.Tell(this, pm, Utility.Random(1074206, 2)); + } + + 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(); + } + } + + [QuesterName("Koole (Sanctuary)")] + public class Koole : BaseCreature + { + [Constructible] + public Koole() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2.0) + { + Title = "the arcanist"; + Race = Race.Elf; + Body = 605; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + Item item; + + item = new LeafChest(); + item.Hue = 443; + AddItem(item); + + item = new LeafArms(); + item.Hue = 443; + AddItem(item); + + AddItem(new LeafTonlet()); + AddItem(new ThighBoots(Utility.RandomAnimalHue())); + AddItem(new RoyalCirclet()); + } + + public Koole(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Koole"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074186, // Come here, I have a task. + 1074218 + ) + ); // Hey! I want to talk to you, now. + } + + 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(); + } + } + + [QuesterName("Synaeva (The Heartwood)")] + public class Synaeva : BaseCreature + { + [Constructible] + public Synaeva() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2.0) + { + Title = "the arcanist"; + Race = Race.Elf; + Female = true; + Body = 606; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + Item item = new RavenHelm(); + item.Hue = Utility.RandomGreenHue(); + AddItem(item); + + AddItem(new FemaleLeafChest()); + AddItem(new LeafArms()); + AddItem(new LeafTonlet()); + AddItem(new ElvenBoots()); + AddItem(new WildStaff()); + } + + public Synaeva(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Synaeva"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1074223); // Have you done it yet?  Oh, I haven’t told you, have I? + } + + 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(); + } + } + + [QuesterName("Elder Brae (Sanctuary)")] + public class ElderBrae : BaseCreature + { + [Constructible] + public ElderBrae() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2.0) + { + Title = "the wise"; + Race = Race.Elf; + Female = true; + Body = 606; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new GemmedCirclet()); + AddItem(new FemaleElvenRobe(Utility.RandomBrightHue())); + AddItem(new ElvenBoots(Utility.RandomAnimalHue())); + } + + public ElderBrae(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Elder Brae"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell( + this, + pm, + Utility.RandomList( + 1074215, // Don’t test my patience you sniveling worm! + 1074218 + ) + ); // Hey!  I want to talk to you, now. + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Definitions/TheAncientWorld.cs b/Projects/UOContent/Engines/MLQuests/Definitions/TheAncientWorld.cs index 93a217a8f..401754346 100644 --- a/Projects/UOContent/Engines/MLQuests/Definitions/TheAncientWorld.cs +++ b/Projects/UOContent/Engines/MLQuests/Definitions/TheAncientWorld.cs @@ -1,159 +1,159 @@ -using System; -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; -using Server.Engines.Spawners; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Definitions -{ - public class TheAncientWorld : MLQuest - { - public TheAncientWorld() - { - Activated = true; - Title = 1074534; // The Ancient World - Description = - 1074535; // The lore of my people mentions Mondain many times. In one tale, it is revealed that he created and enslaved a race -- a sort of man bull, known as a 'minotaur'. The tales speak of mighty warriors who charged with blood-soaked horns into the heat of battle. But, alas, the fate of the bull-men is unknown after the rupture. Will you seek information about their civilization? - RefusalMessage = 1074538; // I am disappointed, but I respect your decision. - InProgressMessage = - 1074539; // A traveler has told me that worshippers of Mondain still exist and wander the land. Perhaps their lore speaks of whether the bull-men survived. I do not think they share their secrets gladly. You may need to be 'persuasive'. - CompletionMessage = 1074542; // What have you found? - - Objectives.Add(new CollectObjective(1, typeof(FragmentOfAMap), "fragment of a map")); - - Rewards.Add(new DummyReward(1074876)); // Knowledge of the legendary minotaur. - } - - public override Type NextQuest => typeof(TheGoldenHorn); - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 5, "LorekeeperBroolol"), new Point3D(7011, 375, 0), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 5, "LorekeeperBroolol"), new Point3D(7011, 375, 0), Map.Felucca); - } - } - - public class TheGoldenHorn : MLQuest - { - public TheGoldenHorn() - { - Activated = true; - Title = 1074543; // The Golden Horn - Description = - 1074545; // Ah ha! You see here ... and over here ... The map fragment places the city of the bull-men, Labyrinth, on that piece of Sosaria that was thrown into the sky. Hmmm, I would have you go there and find any artifacts that remain that help tell the story. But, legend speaks of a mighty barrier to prevent invasion of the city. Take this map to Braen and explain the problem. Perhaps he can devise a solution. - RefusalMessage = 1074538; // I am disappointed, but I respect your decision. - InProgressMessage = 1074547; // Braen is nearby, run and speak with him. - CompletionMessage = 1074549; // Yes? What do you want? I'm very busy. - - Objectives.Add(new DeliverObjective(typeof(FragmentOfAMapDelivery), 1, "fragment of a map", typeof(Braen))); - - Rewards.Add(new DummyReward(1074876)); // Knowledge of the legendary minotaur. - } - - public override Type NextQuest => typeof(Bullish); - public override bool IsChainTriggered => true; - } - - public class Bullish : MLQuest - { - public Bullish() - { - Activated = true; - Title = 1074550; // Bullish - Description = - 1074552; // Oh, I see. I will need some materials to infuse you with the essence of a bull-man, so you can fool their defenses. The most similar beast to the original Baratarian bull that the minotaur were bred from is undoubtedly the mighty Gaman, native to the Lands of the Feudal Lords. I need horns, in great quantity to undertake this magic. - RefusalMessage = 1074554; // Oh come now, don't be afraid. The magic won't harm you. - InProgressMessage = - 1074555; // I cannot grant you the ability to pass through the bull-men's defenses without the gaman horns. - CompletionMessage = - 1074556; // You've returned at last! Give me just a moment to examine what you've brought and I can perform the magic that will allow you enter the Labyrinth. - - Objectives.Add(new CollectObjective(20, typeof(GamanHorns), "gaman horns")); - - Rewards.Add(new DummyReward(1074876)); // Knowledge of the legendary minotaur. - } - - public override Type NextQuest => typeof(LostCivilization); - public override bool IsChainTriggered => true; - } - - public class LostCivilization : MLQuest - { - public LostCivilization() - { - Activated = true; - Title = 1074823; // Lost Civilization - Description = - 1074825; // *whew* It is done! The fierce essence of the bull has been infused into your aura. You are able now to breach the ancient defenses of the city. Go forth and seek the minotaur -- and then return with wonderous tales and evidence of your visit to the Labyrinth. - RefusalMessage = - 1074827; // As you wish. I can't understand why you'd pass up such a remarkable opportunity. Think of the adventures you would have. - InProgressMessage = - 1074828; // You won't reach the minotaur city by loitering around here! What are you waiting for? You need to get to Malas and find the access point for the island. You'll be renowned for your discovery! - CompletionMessage = - 1074829; // Oh! You've returned at last! I can't wait to hear the tales ... but first, let me see those artifacts. You've certainly earned this reward. - - Objectives.Add(new CollectObjective(3, typeof(MinotaurArtifact), "minotaur artifacts")); - - Rewards.Add(ItemReward.Strongbox); - } - - public override bool IsChainTriggered => true; - } - - [QuesterName("Broolol (The Heartwood)")] - public class LorekeeperBroolol : BaseCreature - { - [Constructible] - public LorekeeperBroolol() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the keeper of tradition"; - Race = Race.Elf; - BodyValue = 0x25E; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - SetSkill(SkillName.Meditation, 60.0, 80.0); - SetSkill(SkillName.Focus, 60.0, 80.0); - - AddItem(new ElvenBoots(0x70D)); - AddItem(new FemaleElvenRobe(0x3A)); - AddItem(new WildStaff()); - } - - public LorekeeperBroolol(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - public override bool CanTeach => true; - public override string DefaultName => "Lorekeeper Broolol"; - public override bool CanShout => true; - - public override void Shout(PlayerMobile pm) - { - MLQuestSystem.Tell(this, pm, 1074200); // Thank goodness you are here, there�s no time to lose. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; +using Server.Engines.Spawners; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Definitions +{ + public class TheAncientWorld : MLQuest + { + public TheAncientWorld() + { + Activated = true; + Title = 1074534; // The Ancient World + Description = + 1074535; // The lore of my people mentions Mondain many times. In one tale, it is revealed that he created and enslaved a race -- a sort of man bull, known as a 'minotaur'. The tales speak of mighty warriors who charged with blood-soaked horns into the heat of battle. But, alas, the fate of the bull-men is unknown after the rupture. Will you seek information about their civilization? + RefusalMessage = 1074538; // I am disappointed, but I respect your decision. + InProgressMessage = + 1074539; // A traveler has told me that worshippers of Mondain still exist and wander the land. Perhaps their lore speaks of whether the bull-men survived. I do not think they share their secrets gladly. You may need to be 'persuasive'. + CompletionMessage = 1074542; // What have you found? + + Objectives.Add(new CollectObjective(1, typeof(FragmentOfAMap), "fragment of a map")); + + Rewards.Add(new DummyReward(1074876)); // Knowledge of the legendary minotaur. + } + + public override Type NextQuest => typeof(TheGoldenHorn); + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 5, "LorekeeperBroolol"), new Point3D(7011, 375, 0), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 5, "LorekeeperBroolol"), new Point3D(7011, 375, 0), Map.Felucca); + } + } + + public class TheGoldenHorn : MLQuest + { + public TheGoldenHorn() + { + Activated = true; + Title = 1074543; // The Golden Horn + Description = + 1074545; // Ah ha! You see here ... and over here ... The map fragment places the city of the bull-men, Labyrinth, on that piece of Sosaria that was thrown into the sky. Hmmm, I would have you go there and find any artifacts that remain that help tell the story. But, legend speaks of a mighty barrier to prevent invasion of the city. Take this map to Braen and explain the problem. Perhaps he can devise a solution. + RefusalMessage = 1074538; // I am disappointed, but I respect your decision. + InProgressMessage = 1074547; // Braen is nearby, run and speak with him. + CompletionMessage = 1074549; // Yes? What do you want? I'm very busy. + + Objectives.Add(new DeliverObjective(typeof(FragmentOfAMapDelivery), 1, "fragment of a map", typeof(Braen))); + + Rewards.Add(new DummyReward(1074876)); // Knowledge of the legendary minotaur. + } + + public override Type NextQuest => typeof(Bullish); + public override bool IsChainTriggered => true; + } + + public class Bullish : MLQuest + { + public Bullish() + { + Activated = true; + Title = 1074550; // Bullish + Description = + 1074552; // Oh, I see. I will need some materials to infuse you with the essence of a bull-man, so you can fool their defenses. The most similar beast to the original Baratarian bull that the minotaur were bred from is undoubtedly the mighty Gaman, native to the Lands of the Feudal Lords. I need horns, in great quantity to undertake this magic. + RefusalMessage = 1074554; // Oh come now, don't be afraid. The magic won't harm you. + InProgressMessage = + 1074555; // I cannot grant you the ability to pass through the bull-men's defenses without the gaman horns. + CompletionMessage = + 1074556; // You've returned at last! Give me just a moment to examine what you've brought and I can perform the magic that will allow you enter the Labyrinth. + + Objectives.Add(new CollectObjective(20, typeof(GamanHorns), "gaman horns")); + + Rewards.Add(new DummyReward(1074876)); // Knowledge of the legendary minotaur. + } + + public override Type NextQuest => typeof(LostCivilization); + public override bool IsChainTriggered => true; + } + + public class LostCivilization : MLQuest + { + public LostCivilization() + { + Activated = true; + Title = 1074823; // Lost Civilization + Description = + 1074825; // *whew* It is done! The fierce essence of the bull has been infused into your aura. You are able now to breach the ancient defenses of the city. Go forth and seek the minotaur -- and then return with wonderous tales and evidence of your visit to the Labyrinth. + RefusalMessage = + 1074827; // As you wish. I can't understand why you'd pass up such a remarkable opportunity. Think of the adventures you would have. + InProgressMessage = + 1074828; // You won't reach the minotaur city by loitering around here! What are you waiting for? You need to get to Malas and find the access point for the island. You'll be renowned for your discovery! + CompletionMessage = + 1074829; // Oh! You've returned at last! I can't wait to hear the tales ... but first, let me see those artifacts. You've certainly earned this reward. + + Objectives.Add(new CollectObjective(3, typeof(MinotaurArtifact), "minotaur artifacts")); + + Rewards.Add(ItemReward.Strongbox); + } + + public override bool IsChainTriggered => true; + } + + [QuesterName("Broolol (The Heartwood)")] + public class LorekeeperBroolol : BaseCreature + { + [Constructible] + public LorekeeperBroolol() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the keeper of tradition"; + Race = Race.Elf; + BodyValue = 0x25E; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + SetSkill(SkillName.Meditation, 60.0, 80.0); + SetSkill(SkillName.Focus, 60.0, 80.0); + + AddItem(new ElvenBoots(0x70D)); + AddItem(new FemaleElvenRobe(0x3A)); + AddItem(new WildStaff()); + } + + public LorekeeperBroolol(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + public override bool CanTeach => true; + public override string DefaultName => "Lorekeeper Broolol"; + public override bool CanShout => true; + + public override void Shout(PlayerMobile pm) + { + MLQuestSystem.Tell(this, pm, 1074200); // Thank goodness you are here, there�s no time to lose. + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Definitions/TownEscorts.cs b/Projects/UOContent/Engines/MLQuests/Definitions/TownEscorts.cs index 57330f5eb..612b0b3ed 100644 --- a/Projects/UOContent/Engines/MLQuests/Definitions/TownEscorts.cs +++ b/Projects/UOContent/Engines/MLQuests/Definitions/TownEscorts.cs @@ -1,131 +1,131 @@ -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; -using Server.Items; - -namespace Server.Engines.MLQuests.Definitions -{ - public class TownEscort : BaseEscort - { - // Escort reward - private static readonly BaseReward m_Reward = new ItemReward("Gold", typeof(Gold), 500); - - public TownEscort(int title, int progress, int destination, string region) - { - Activated = true; - Title = title; - Description = - 1072287; // I seek a worthy escort. I can offer some small pay to any able bodied adventurer who can assist me. It is imperative that I reach my destination. - RefusalMessage = - 1072288; // I wish you would reconsider my offer. I'll be waiting right here for someone brave enough to assist me. - InProgressMessage = progress; - - Objectives.Add(new EscortObjective(new QuestArea(destination, region))); - - Rewards.Add(m_Reward); - } - } - - public class EscortToYew : TownEscort - { - public EscortToYew() - : base(1072275, 1072289, 1072227, "Yew") - { - } - } - - public class EscortToVesper : TownEscort - { - public EscortToVesper() - : base(1072276, 1072290, 1072229, "Vesper") - { - } - } - - public class EscortToTrinsic : TownEscort - { - public EscortToTrinsic() - : base(1072277, 1072291, 1072236, "Trinsic") - { - } - } - - public class EscortToSkaraBrae : TownEscort - { - public EscortToSkaraBrae() - : base(1072278, 1072292, 1072235, "Skara Brae") - { - } - } - - public class EscortToSerpentsHold : TownEscort - { - public EscortToSerpentsHold() - : base(1072279, 1072293, 1072238, "Serpent's Hold") - { - } - } - - public class EscortToNujelm : TownEscort - { - public EscortToNujelm() - : base(1072280, 1072294, 1072237, "Nujel'm") - { - } - } - - public class EscortToMoonglow : TownEscort - { - public EscortToMoonglow() - : base(1072281, 1072295, 1072232, "Moonglow") - { - } - } - - public class EscortToMinoc : TownEscort - { - public EscortToMinoc() - : base(1072282, 1072296, 1072228, "Minoc") - { - } - } - - public class EscortToMagincia : TownEscort - { - public EscortToMagincia() - : base(1072283, 1072297, 1072233, "Magincia") - { - } - } - - public class EscortToJhelom : TownEscort - { - public EscortToJhelom() - : base(1072284, 1072298, 1072239, "Jhelom") - { - } - } - - public class EscortToCove : TownEscort - { - public EscortToCove() - : base(1072285, 1072299, 1072230, "Cove") - { - } - } - - public class EscortToBritain : TownEscort - { - public EscortToBritain() - : base(1072286, 1072300, 1072231, "Britain") - { - } - } - - public class EscortToOcllo : TownEscort - { - public EscortToOcllo() - : base(1072312, 1072313, 1072234, "Ocllo") - { - } - } -} \ No newline at end of file +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; +using Server.Items; + +namespace Server.Engines.MLQuests.Definitions +{ + public class TownEscort : BaseEscort + { + // Escort reward + private static readonly BaseReward m_Reward = new ItemReward("Gold", typeof(Gold), 500); + + public TownEscort(int title, int progress, int destination, string region) + { + Activated = true; + Title = title; + Description = + 1072287; // I seek a worthy escort. I can offer some small pay to any able bodied adventurer who can assist me. It is imperative that I reach my destination. + RefusalMessage = + 1072288; // I wish you would reconsider my offer. I'll be waiting right here for someone brave enough to assist me. + InProgressMessage = progress; + + Objectives.Add(new EscortObjective(new QuestArea(destination, region))); + + Rewards.Add(m_Reward); + } + } + + public class EscortToYew : TownEscort + { + public EscortToYew() + : base(1072275, 1072289, 1072227, "Yew") + { + } + } + + public class EscortToVesper : TownEscort + { + public EscortToVesper() + : base(1072276, 1072290, 1072229, "Vesper") + { + } + } + + public class EscortToTrinsic : TownEscort + { + public EscortToTrinsic() + : base(1072277, 1072291, 1072236, "Trinsic") + { + } + } + + public class EscortToSkaraBrae : TownEscort + { + public EscortToSkaraBrae() + : base(1072278, 1072292, 1072235, "Skara Brae") + { + } + } + + public class EscortToSerpentsHold : TownEscort + { + public EscortToSerpentsHold() + : base(1072279, 1072293, 1072238, "Serpent's Hold") + { + } + } + + public class EscortToNujelm : TownEscort + { + public EscortToNujelm() + : base(1072280, 1072294, 1072237, "Nujel'm") + { + } + } + + public class EscortToMoonglow : TownEscort + { + public EscortToMoonglow() + : base(1072281, 1072295, 1072232, "Moonglow") + { + } + } + + public class EscortToMinoc : TownEscort + { + public EscortToMinoc() + : base(1072282, 1072296, 1072228, "Minoc") + { + } + } + + public class EscortToMagincia : TownEscort + { + public EscortToMagincia() + : base(1072283, 1072297, 1072233, "Magincia") + { + } + } + + public class EscortToJhelom : TownEscort + { + public EscortToJhelom() + : base(1072284, 1072298, 1072239, "Jhelom") + { + } + } + + public class EscortToCove : TownEscort + { + public EscortToCove() + : base(1072285, 1072299, 1072230, "Cove") + { + } + } + + public class EscortToBritain : TownEscort + { + public EscortToBritain() + : base(1072286, 1072300, 1072231, "Britain") + { + } + } + + public class EscortToOcllo : TownEscort + { + public EscortToOcllo() + : base(1072312, 1072313, 1072234, "Ocllo") + { + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Definitions/UnfadingMemories.cs b/Projects/UOContent/Engines/MLQuests/Definitions/UnfadingMemories.cs index d9ae08f89..57f208231 100644 --- a/Projects/UOContent/Engines/MLQuests/Definitions/UnfadingMemories.cs +++ b/Projects/UOContent/Engines/MLQuests/Definitions/UnfadingMemories.cs @@ -1,189 +1,192 @@ -using System; -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; -using Server.Engines.Spawners; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Definitions -{ - public class UnfadingMemoriesPartOne : MLQuest - { - public UnfadingMemoriesPartOne() - { - Activated = true; - Title = 1075355; // Unfading Memories - Description = - 1075356; // Aargh! It�s just not right! It doesn�t capture the unique color of her hair at all! If only I had some Prismatic Amber. That would be perfect. They used to mine it in Malas, but alas, those veins ran dry some time ago. I hear it may have been found in the Prism of Light. Oh, if only there were a bold adventurer within earshot who would go to the Prism of Light and retrieve some for me! - RefusalMessage = 1075358; // Is there no one who can help a humble artist pursue his Muse? - InProgressMessage = - 1075359; // You can find Prismatic Amber in the Prism of Light, located just north of the city of Nujel'm. - CompletionMessage = - 1075360; // I knew it! See, it�s just the color I needed! Look how it brings out the highlights of her wheaten tresses! - CompletionNotice = CompletionNoticeShort; - - Objectives.Add(new CollectObjective(1, typeof(PrismaticAmber), "Prismatic Amber")); - - Rewards.Add(new DummyReward( - 1075357)); // The joy of contributing to a noble artistic effort, however paltry the end product. - } - - public override Type NextQuest => typeof(UnfadingMemoriesPartTwo); - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 3, "Emilio"), new Point3D(1447, 1664, 10), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 3, "Emilio"), new Point3D(1447, 1664, 10), Map.Felucca); - } - } - - public class UnfadingMemoriesPartTwo : MLQuest - { - public UnfadingMemoriesPartTwo() - { - Activated = true; - Title = 1075367; // Unfading Memories - Description = - 1075368; // Finished! With the pigment I was able to create from the Prismatic Amber you brought me, I was able to complete my humble work. I should explain. Once, I loved a noble lady of gentleness and refinement, who possessed such beauty that I have found myself unable to love another to this day. But it was from afar that I admired her, for it is not for one so lowly as I to pay court to the likes of her. You have heard of the fair Thalia, Lady of Nujel'm? No? Well, she was my Muse, my inspiration, and when I heard she was to be married, I lost whatever pitiful talent I possessed. I felt I must compose a portrait of her, my masterpiece, or I would never be able to paint again. You, my friend, have helped me complete my work. Now I ask another favor of you. Will you take it to her as a wedding gift? She will probably reject it, but I must make the offer. - RefusalMessage = - 1075370; // Alright then, you have already helped me more than I deserved. I shall find someone else to undertake this task. - InProgressMessage = - 1075371; // The wedding is taking place in the palace in Nujel'm. You will likely find her there. - CompletionMessage = - 1075372; // I�m sorry, I�m getting ready to be married. I don�t have time to . . . what�s that you say? - CompletionNotice = CompletionNoticeShort; - - Objectives.Add(new DeliverObjective(typeof(PortraitOfTheBride), 1, "Portrait of the Bride", typeof(Thalia))); - - Rewards.Add(new DummyReward(1075369)); // The Artist�s gratitude. - } - - public override Type NextQuest => typeof(UnfadingMemoriesPartThree); - public override bool IsChainTriggered => true; - } - - public class UnfadingMemoriesPartThree : MLQuest - { - public UnfadingMemoriesPartThree() - { - Activated = true; - OneTimeOnly = true; - Title = 1075373; // Unfading Memories - Description = - 1075374; // Emilio painted this? It is absolutely wonderful! I used to love looking at his paintings, but I don�t remember him creating anything like this before. Would you be so kind as to carry a letter to him? Fate may have it that I am to marry another, yet I am compelled to reveal to him that his love was not entirely unrequited. - RefusalMessage = 1075376; // Very well, then. If you will excuse me, I need to get ready. - InProgressMessage = - 1075377; // Take the letter back to the Artist�s Guild in Britain, if you would do me this kindness. - CompletionMessage = - 1075378; // She said what? She thinks what of me? I . . . I can�t believe it! All this time, I never knew how she truly felt. Thank you, my friend. I believe now I will be able to paint once again. Here, take this bleach. I was going to use it to destroy all of my works. Perhaps you can find a better use for it now. - CompletionNotice = CompletionNoticeShort; - - Objectives.Add(new DeliverObjective(typeof(BridesLetter), 1, "Bride's Letter", typeof(Emilio))); - - Rewards.Add(new ItemReward(1075375, typeof(Bleach))); // Bleach - } - - public override bool IsChainTriggered => true; - - public override void Generate() - { - base.Generate(); - - PutSpawner(new Spawner(1, 5, 10, 0, 3, "Thalia"), new Point3D(3675, 1322, 20), Map.Trammel); - PutSpawner(new Spawner(1, 5, 10, 0, 3, "Thalia"), new Point3D(3675, 1322, 20), Map.Felucca); - } - } - - [QuesterName("Emilio (Britain)")] // OSI's description is "Artist", not very helpful - public class Emilio : BaseCreature - { - [Constructible] - public Emilio() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Tortured Artist"; - Race = Race.Human; - BodyValue = 0x190; - Female = false; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Backpack()); - AddItem(new Sandals(0x72B)); - AddItem(new LongPants(0x525)); - AddItem(new FancyShirt(0x53F)); - AddItem(new FloppyHat(0x58C)); - AddItem(new BodySash(0x1C)); - } - - public Emilio(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "Emilio"; - public override bool IsInvulnerable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [QuesterName("Thalia (Nujel'm)")] // OSI's description is "Bride", not very helpful - public class Thalia : BaseCreature - { - [Constructible] - public Thalia() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - Title = "the Bride"; - Race = Race.Human; - BodyValue = 0x191; - Female = true; - Hue = Race.RandomSkinHue(); - InitStats(100, 100, 25); - - Utility.AssignRandomHair(this); - - AddItem(new Backpack()); - AddItem(new Sandals(0x8FD)); - AddItem(new FancyDress(0x8FD)); - } - - public Thalia(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "Thalia"; - public override bool IsInvulnerable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; +using Server.Engines.Spawners; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Definitions +{ + public class UnfadingMemoriesPartOne : MLQuest + { + public UnfadingMemoriesPartOne() + { + Activated = true; + Title = 1075355; // Unfading Memories + Description = + 1075356; // Aargh! It�s just not right! It doesn�t capture the unique color of her hair at all! If only I had some Prismatic Amber. That would be perfect. They used to mine it in Malas, but alas, those veins ran dry some time ago. I hear it may have been found in the Prism of Light. Oh, if only there were a bold adventurer within earshot who would go to the Prism of Light and retrieve some for me! + RefusalMessage = 1075358; // Is there no one who can help a humble artist pursue his Muse? + InProgressMessage = + 1075359; // You can find Prismatic Amber in the Prism of Light, located just north of the city of Nujel'm. + CompletionMessage = + 1075360; // I knew it! See, it�s just the color I needed! Look how it brings out the highlights of her wheaten tresses! + CompletionNotice = CompletionNoticeShort; + + Objectives.Add(new CollectObjective(1, typeof(PrismaticAmber), "Prismatic Amber")); + + Rewards.Add( + new DummyReward( + 1075357 + ) + ); // The joy of contributing to a noble artistic effort, however paltry the end product. + } + + public override Type NextQuest => typeof(UnfadingMemoriesPartTwo); + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 3, "Emilio"), new Point3D(1447, 1664, 10), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 3, "Emilio"), new Point3D(1447, 1664, 10), Map.Felucca); + } + } + + public class UnfadingMemoriesPartTwo : MLQuest + { + public UnfadingMemoriesPartTwo() + { + Activated = true; + Title = 1075367; // Unfading Memories + Description = + 1075368; // Finished! With the pigment I was able to create from the Prismatic Amber you brought me, I was able to complete my humble work. I should explain. Once, I loved a noble lady of gentleness and refinement, who possessed such beauty that I have found myself unable to love another to this day. But it was from afar that I admired her, for it is not for one so lowly as I to pay court to the likes of her. You have heard of the fair Thalia, Lady of Nujel'm? No? Well, she was my Muse, my inspiration, and when I heard she was to be married, I lost whatever pitiful talent I possessed. I felt I must compose a portrait of her, my masterpiece, or I would never be able to paint again. You, my friend, have helped me complete my work. Now I ask another favor of you. Will you take it to her as a wedding gift? She will probably reject it, but I must make the offer. + RefusalMessage = + 1075370; // Alright then, you have already helped me more than I deserved. I shall find someone else to undertake this task. + InProgressMessage = + 1075371; // The wedding is taking place in the palace in Nujel'm. You will likely find her there. + CompletionMessage = + 1075372; // I�m sorry, I�m getting ready to be married. I don�t have time to . . . what�s that you say? + CompletionNotice = CompletionNoticeShort; + + Objectives.Add(new DeliverObjective(typeof(PortraitOfTheBride), 1, "Portrait of the Bride", typeof(Thalia))); + + Rewards.Add(new DummyReward(1075369)); // The Artist�s gratitude. + } + + public override Type NextQuest => typeof(UnfadingMemoriesPartThree); + public override bool IsChainTriggered => true; + } + + public class UnfadingMemoriesPartThree : MLQuest + { + public UnfadingMemoriesPartThree() + { + Activated = true; + OneTimeOnly = true; + Title = 1075373; // Unfading Memories + Description = + 1075374; // Emilio painted this? It is absolutely wonderful! I used to love looking at his paintings, but I don�t remember him creating anything like this before. Would you be so kind as to carry a letter to him? Fate may have it that I am to marry another, yet I am compelled to reveal to him that his love was not entirely unrequited. + RefusalMessage = 1075376; // Very well, then. If you will excuse me, I need to get ready. + InProgressMessage = + 1075377; // Take the letter back to the Artist�s Guild in Britain, if you would do me this kindness. + CompletionMessage = + 1075378; // She said what? She thinks what of me? I . . . I can�t believe it! All this time, I never knew how she truly felt. Thank you, my friend. I believe now I will be able to paint once again. Here, take this bleach. I was going to use it to destroy all of my works. Perhaps you can find a better use for it now. + CompletionNotice = CompletionNoticeShort; + + Objectives.Add(new DeliverObjective(typeof(BridesLetter), 1, "Bride's Letter", typeof(Emilio))); + + Rewards.Add(new ItemReward(1075375, typeof(Bleach))); // Bleach + } + + public override bool IsChainTriggered => true; + + public override void Generate() + { + base.Generate(); + + PutSpawner(new Spawner(1, 5, 10, 0, 3, "Thalia"), new Point3D(3675, 1322, 20), Map.Trammel); + PutSpawner(new Spawner(1, 5, 10, 0, 3, "Thalia"), new Point3D(3675, 1322, 20), Map.Felucca); + } + } + + [QuesterName("Emilio (Britain)")] // OSI's description is "Artist", not very helpful + public class Emilio : BaseCreature + { + [Constructible] + public Emilio() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Tortured Artist"; + Race = Race.Human; + BodyValue = 0x190; + Female = false; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Backpack()); + AddItem(new Sandals(0x72B)); + AddItem(new LongPants(0x525)); + AddItem(new FancyShirt(0x53F)); + AddItem(new FloppyHat(0x58C)); + AddItem(new BodySash(0x1C)); + } + + public Emilio(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "Emilio"; + public override bool IsInvulnerable => true; + + 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(); + } + } + + [QuesterName("Thalia (Nujel'm)")] // OSI's description is "Bride", not very helpful + public class Thalia : BaseCreature + { + [Constructible] + public Thalia() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + Title = "the Bride"; + Race = Race.Human; + BodyValue = 0x191; + Female = true; + Hue = Race.RandomSkinHue(); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Backpack()); + AddItem(new Sandals(0x8FD)); + AddItem(new FancyDress(0x8FD)); + } + + public Thalia(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "Thalia"; + public override bool IsInvulnerable => true; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Definitions/WarriorsOfTheGemKeeper.cs b/Projects/UOContent/Engines/MLQuests/Definitions/WarriorsOfTheGemKeeper.cs index 8b4662682..a03d3e0f1 100644 --- a/Projects/UOContent/Engines/MLQuests/Definitions/WarriorsOfTheGemKeeper.cs +++ b/Projects/UOContent/Engines/MLQuests/Definitions/WarriorsOfTheGemKeeper.cs @@ -1,95 +1,95 @@ -using System; -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; -using Server.Items; - -namespace Server.Engines.MLQuests.Definitions -{ - public class WarriorsOfTheGemkeeper : MLQuest - { - public WarriorsOfTheGemkeeper() - { - Activated = true; - Title = 1074536; // Warriors of the Gemkeeper - Description = - 1074537; // Here we honor the Gemkeeper's Apprentice and seek to aid her efforts against the humans responsible for the death of her teacher - and the destruction of the elven way of life. Our tales speak of a fierce race of servants of the Gemkeeper, the men-bulls whose battle-skill was renowned. It is desireable to discover the fate of these noble creatures after the Rupture. Will you seek information? - RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. - InProgressMessage = - 1074540; // I care not how you get the information. Kill as many humans as you must ... but find the fate of the minotaurs. Perhaps another of the Gemkeeper's servants has the knowledge we seek. - CompletionMessage = 1074542; // What have you found? - - Objectives.Add(new CollectObjective(1, typeof(FragmentOfAMap), "fragment of a map")); - - Rewards.Add(new DummyReward(1074876)); // Knowledge of the legendary minotaur. - } - - public override Type NextQuest => typeof(CloseEnough); - } - - public class CloseEnough : MLQuest - { - public CloseEnough() - { - Activated = true; - Title = 1074544; // Close Enough - Description = - 1074546; // Ah ha! You see here ... and over here ... The map fragment places the city of the bull-men, Labyrinth, on that piece of Sosaria that was thrown into the sky. Hmmm, I would have you go there and seek out these warriors to see if they might join our cause. But, legend speaks of a mighty barrier to prevent invasion of the city. Take this map to Canir and explain the problem. Perhaps she can devise a solution. - RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. - InProgressMessage = 1074548; // Canir is nearby, run and speak with her. - CompletionMessage = 1074549; // Yes? What do you want? I'm very busy. - - Objectives.Add(new DeliverObjective(typeof(FragmentOfAMapDelivery), 1, "fragment of a map", typeof(Canir))); - - Rewards.Add(new DummyReward(1074876)); // Knowledge of the legendary minotaur. - } - - public override Type NextQuest => typeof(TakingTheBullByTheHorns); - public override bool IsChainTriggered => true; - } - - public class TakingTheBullByTheHorns : MLQuest - { - public TakingTheBullByTheHorns() - { - Activated = true; - Title = 1074551; // Taking the Bull by the Horns - Description = - 1074553; // Interesting. I believe I have a way. I will need some materials to infuse you with the essence of a bull-man, so you can fool their defenses. The most similar beast to the original Baratarian bull that the minotaur were bred from is undoubtedly the mighty Gaman, native to the Lands of the Feudal Lords. I need horns, in great quantity to undertake this magic. - RefusalMessage = 1074554; // Oh come now, don't be afraid. The magic won't harm you. - InProgressMessage = - 1074555; // I cannot grant you the ability to pass through the bull-men's defenses without the gaman horns. - CompletionMessage = - 1074556; // You've returned at last! Give me just a moment to examine what you've brought and I can perform the magic that will allow you enter the Labyrinth. - - Objectives.Add(new CollectObjective(20, typeof(GamanHorns), "gaman horns")); - - Rewards.Add(new DummyReward(1074876)); // Knowledge of the legendary minotaur. - } - - public override Type NextQuest => typeof(EmissaryToTheMinotaur); - public override bool IsChainTriggered => true; - } - - public class EmissaryToTheMinotaur : MLQuest - { - public EmissaryToTheMinotaur() - { - Activated = true; - Title = 1074824; // Emissary to the Minotaur - Description = - 1074825; // *whew* It is done! The fierce essence of the bull has been infused into your aura. You are able now to breach the ancient defenses of the city. Go forth and seek the minotaur -- and then return with wonderous tales and evidence of your visit to the Labyrinth. - RefusalMessage = - 1074827; // As you wish. I can't understand why you'd pass up such a remarkable opportunity. Think of the adventures you would have. - InProgressMessage = - 1074828; // You won't reach the minotaur city by loitering around here! What are you waiting for? You need to get to Malas and find the access point for the island. You'll be renowned for your discovery! - CompletionMessage = - 1074829; // Oh! You've returned at last! I can't wait to hear the tales ... but first, let me see those artifacts. You've certainly earned this reward. - - Objectives.Add(new CollectObjective(3, typeof(MinotaurArtifact), "minotaur artifacts")); - - Rewards.Add(ItemReward.Strongbox); - } - - public override bool IsChainTriggered => true; - } -} \ No newline at end of file +using System; +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; +using Server.Items; + +namespace Server.Engines.MLQuests.Definitions +{ + public class WarriorsOfTheGemkeeper : MLQuest + { + public WarriorsOfTheGemkeeper() + { + Activated = true; + Title = 1074536; // Warriors of the Gemkeeper + Description = + 1074537; // Here we honor the Gemkeeper's Apprentice and seek to aid her efforts against the humans responsible for the death of her teacher - and the destruction of the elven way of life. Our tales speak of a fierce race of servants of the Gemkeeper, the men-bulls whose battle-skill was renowned. It is desireable to discover the fate of these noble creatures after the Rupture. Will you seek information? + RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. + InProgressMessage = + 1074540; // I care not how you get the information. Kill as many humans as you must ... but find the fate of the minotaurs. Perhaps another of the Gemkeeper's servants has the knowledge we seek. + CompletionMessage = 1074542; // What have you found? + + Objectives.Add(new CollectObjective(1, typeof(FragmentOfAMap), "fragment of a map")); + + Rewards.Add(new DummyReward(1074876)); // Knowledge of the legendary minotaur. + } + + public override Type NextQuest => typeof(CloseEnough); + } + + public class CloseEnough : MLQuest + { + public CloseEnough() + { + Activated = true; + Title = 1074544; // Close Enough + Description = + 1074546; // Ah ha! You see here ... and over here ... The map fragment places the city of the bull-men, Labyrinth, on that piece of Sosaria that was thrown into the sky. Hmmm, I would have you go there and seek out these warriors to see if they might join our cause. But, legend speaks of a mighty barrier to prevent invasion of the city. Take this map to Canir and explain the problem. Perhaps she can devise a solution. + RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then. + InProgressMessage = 1074548; // Canir is nearby, run and speak with her. + CompletionMessage = 1074549; // Yes? What do you want? I'm very busy. + + Objectives.Add(new DeliverObjective(typeof(FragmentOfAMapDelivery), 1, "fragment of a map", typeof(Canir))); + + Rewards.Add(new DummyReward(1074876)); // Knowledge of the legendary minotaur. + } + + public override Type NextQuest => typeof(TakingTheBullByTheHorns); + public override bool IsChainTriggered => true; + } + + public class TakingTheBullByTheHorns : MLQuest + { + public TakingTheBullByTheHorns() + { + Activated = true; + Title = 1074551; // Taking the Bull by the Horns + Description = + 1074553; // Interesting. I believe I have a way. I will need some materials to infuse you with the essence of a bull-man, so you can fool their defenses. The most similar beast to the original Baratarian bull that the minotaur were bred from is undoubtedly the mighty Gaman, native to the Lands of the Feudal Lords. I need horns, in great quantity to undertake this magic. + RefusalMessage = 1074554; // Oh come now, don't be afraid. The magic won't harm you. + InProgressMessage = + 1074555; // I cannot grant you the ability to pass through the bull-men's defenses without the gaman horns. + CompletionMessage = + 1074556; // You've returned at last! Give me just a moment to examine what you've brought and I can perform the magic that will allow you enter the Labyrinth. + + Objectives.Add(new CollectObjective(20, typeof(GamanHorns), "gaman horns")); + + Rewards.Add(new DummyReward(1074876)); // Knowledge of the legendary minotaur. + } + + public override Type NextQuest => typeof(EmissaryToTheMinotaur); + public override bool IsChainTriggered => true; + } + + public class EmissaryToTheMinotaur : MLQuest + { + public EmissaryToTheMinotaur() + { + Activated = true; + Title = 1074824; // Emissary to the Minotaur + Description = + 1074825; // *whew* It is done! The fierce essence of the bull has been infused into your aura. You are able now to breach the ancient defenses of the city. Go forth and seek the minotaur -- and then return with wonderous tales and evidence of your visit to the Labyrinth. + RefusalMessage = + 1074827; // As you wish. I can't understand why you'd pass up such a remarkable opportunity. Think of the adventures you would have. + InProgressMessage = + 1074828; // You won't reach the minotaur city by loitering around here! What are you waiting for? You need to get to Malas and find the access point for the island. You'll be renowned for your discovery! + CompletionMessage = + 1074829; // Oh! You've returned at last! I can't wait to hear the tales ... but first, let me see those artifacts. You've certainly earned this reward. + + Objectives.Add(new CollectObjective(3, typeof(MinotaurArtifact), "minotaur artifacts")); + + Rewards.Add(ItemReward.Strongbox); + } + + public override bool IsChainTriggered => true; + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Gumps/BaseQuestGump.cs b/Projects/UOContent/Engines/MLQuests/Gumps/BaseQuestGump.cs index 2fe75f8aa..1dda2b787 100644 --- a/Projects/UOContent/Engines/MLQuests/Gumps/BaseQuestGump.cs +++ b/Projects/UOContent/Engines/MLQuests/Gumps/BaseQuestGump.cs @@ -1,236 +1,276 @@ -using System.Collections.Generic; -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; -using Server.Gumps; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Gumps -{ - public enum ButtonPosition : byte - { - Left, - Right - } - - public enum ButtonGraphic : ushort - { - Invalid, - Accept = 0x2EE0, - Clear = 0x2EE3, - Close = 0x2EE6, - Continue = 0x2EE9, - Okay = 0x2EEC, - Previous = 0x2EEF, - Refuse = 0x2EF2, - Resign = 0x2EF5 - } - - public abstract class BaseQuestGump : Gump - { - private struct ButtonInfo - { - public ButtonPosition Position { get; } - - public ButtonGraphic Graphic { get; } - - public int ButtonID { get; } - - public ButtonInfo(ButtonPosition position, ButtonGraphic graphic, int buttonID) - { - Position = position; - Graphic = graphic; - ButtonID = buttonID; - } - } - - private int m_Page; - private int m_MaxPages; - private int m_Label; - private string m_Title; - private readonly List m_Buttons; - - // RunUO optimized version - public BaseQuestGump(int label) - : base(75, 25) - { - m_Page = 0; - m_MaxPages = 0; - m_Label = label; - m_Title = null; - m_Buttons = new List(2); - - Closable = false; - - AddPage(0); - - AddImageTiled(50, 20, 400, 460, 0x1404); - AddImageTiled(50, 29, 30, 450, 0x28DC); - AddImageTiled(34, 140, 17, 339, 0x242F); - AddImage(48, 135, 0x28AB); - AddImage(-16, 285, 0x28A2); - AddImage(0, 10, 0x28B5); - AddImage(25, 0, 0x28B4); - AddImageTiled(83, 15, 350, 15, 0x280A); - AddImage(34, 479, 0x2842); - AddImage(442, 479, 0x2840); - AddImageTiled(51, 479, 392, 17, 0x2775); - AddImageTiled(415, 29, 44, 450, 0xA2D); - AddImageTiled(415, 29, 30, 450, 0x28DC); - // AddLabel( 100, 50, 0x481, "" ); - AddImage(370, 50, 0x589); - AddImage(379, 60, 0x15A9); - AddImage(425, 0, 0x28C9); - AddImage(90, 33, 0x232D); - AddHtmlLocalized(130, 45, 270, 16, label, 0xFFFFFF); - AddImageTiled(130, 65, 175, 1, 0x238D); - } - - public void BuildPage() - { - AddPage(++m_Page); - - if (m_Page > 1) - AddButton(130, 430, (int)ButtonGraphic.Previous, (int)ButtonGraphic.Previous + 2, 0, GumpButtonType.Page, - m_Page - 1); - - if (m_Page < m_MaxPages) - AddButton(275, 430, (int)ButtonGraphic.Continue, (int)ButtonGraphic.Continue + 2, 0, GumpButtonType.Page, - m_Page + 1); - - foreach (ButtonInfo button in m_Buttons) - AddButton(button.Position == ButtonPosition.Left ? 95 : 313, 455, (int)button.Graphic, - (int)button.Graphic + 2, button.ButtonID); - - if (m_Title != null) - AddHtmlLocalized(130, 68, 220, 48, 1114513, m_Title, 0x2710); //
~1_TOKEN~
- } - - public void SetPageCount(int maxPages) - { - m_MaxPages = maxPages; - } - - public void SetTitle(TextDefinition def) - { - if (def.Number > 0) - m_Title = $"#{def.Number}"; // OSI does "@@#{0}" instead, why? KR client related? - else - m_Title = def.String; - } - - public void RegisterButton(ButtonPosition position, ButtonGraphic graphic, int buttonID) - { - m_Buttons.Add(new ButtonInfo(position, graphic, buttonID)); - } - - public void AddDescription(MLQuest quest) - { - AddHtmlLocalized(98, 140, 312, 16, quest.IsChainTriggered || quest.NextQuest != null ? 1075024 : 1072202, 0x2710); // Description [(quest chain)] - TextDefinition.AddHtmlText(this, 98, 156, 312, 240, quest.Description, false, true, 0x15F90, 0xBDE784); - } - - public void AddObjectives(MLQuest quest) - { - AddHtmlLocalized(98, 140, 312, 16, 1049073, 0x2710); // Objective: - AddHtmlLocalized(98, 156, 312, 16, quest.ObjectiveType == ObjectiveType.All ? 1072208 : 1072209, 0x2710); // All of the following / Only one of the following - - int y = 172; - - foreach (BaseObjective objective in quest.Objectives) - { - objective.WriteToGump(this, ref y); - - if (objective.IsTimed) - { - if (objective is CollectObjective) - y -= 16; - - BaseObjectiveInstance.WriteTimeRemaining(this, ref y, objective.Duration); - } - } - } - - public void AddObjectivesProgress(MLQuestInstance instance) - { - MLQuest quest = instance.Quest; - - AddHtmlLocalized(98, 140, 312, 16, 1049073, 0x2710); // Objective: - AddHtmlLocalized(98, 156, 312, 16, quest.ObjectiveType == ObjectiveType.All ? 1072208 : 1072209, 0x2710); // All of the following / Only one of the following - - int y = 172; - - foreach (BaseObjectiveInstance objInstance in instance.Objectives) - objInstance.WriteToGump(this, ref y); - } - - public void AddRewardsPage(MLQuest quest) // For the quest log/offer gumps - { - AddHtmlLocalized(98, 140, 312, 16, 1072201, 0x2710); // Reward - - int y = 162; - - if (quest.Rewards.Count > 1) - { - // TODO: Is this what this is for? Does "Only one of the following" occur? - AddHtmlLocalized(98, 156, 312, 16, 1072208, 0x2710); // All of the following - y += 16; - } - - AddRewards(quest, 105, y, 16); - } - - public void AddRewards(MLQuest quest) // For the claim rewards gump - { - int y = 146; - - if (quest.Rewards.Count > 1) - { - // TODO: Is this what this is for? Does "Only one of the following" occur? - AddHtmlLocalized(100, 140, 312, 16, 1072208, 0x2710); // All of the following - y += 16; - } - - AddRewards(quest, 107, y, 26); - } - - public void AddRewards(MLQuest quest, int x, int y, int spacing) - { - int xReward = x + 28; - - foreach (BaseReward reward in quest.Rewards) - { - AddImage(x, y + 1, 0x4B9); - reward.WriteToGump(this, xReward, ref y); - y += spacing; - } - } - - public void AddConversation(TextDefinition text) - { - TextDefinition.AddHtmlText(this, 98, 140, 312, 180, text, false, true, 0x15F90, 0xBDE784); - } - - /* OSI gump IDs: - * 800 - QuestOfferGump - * 801 - QuestCancelConfirmGump - * 802 - ?? (gets closed by Toggle Quest Item) - * 803 - QuestRewardGump - * 804 - ?? (gets closed by Toggle Quest Item) - * 805 - QuestLogGump - * 806 - QuestConversationGump (refuse / in progress) - * 807 - ?? (gets closed by Toggle Quest Item and most quest gumps) - * 808 - InfoNPCGump - * 809 - QuestLogDetailedGump - * 810 - QuestReportBackGump - */ - public static void CloseOtherGumps(PlayerMobile pm) - { - pm.CloseGump(); - pm.CloseGump(); - pm.CloseGump(); - pm.CloseGump(); - // pm.CloseGump( typeof( UnknownGump807 ) ); - pm.CloseGump(); - } - } -} +using System.Collections.Generic; +using Server.Engines.MLQuests.Objectives; +using Server.Gumps; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Gumps +{ + public enum ButtonPosition : byte + { + Left, + Right + } + + public enum ButtonGraphic : ushort + { + Invalid, + Accept = 0x2EE0, + Clear = 0x2EE3, + Close = 0x2EE6, + Continue = 0x2EE9, + Okay = 0x2EEC, + Previous = 0x2EEF, + Refuse = 0x2EF2, + Resign = 0x2EF5 + } + + public abstract class BaseQuestGump : Gump + { + private readonly List m_Buttons; + private int m_Label; + private int m_MaxPages; + + private int m_Page; + private string m_Title; + + // RunUO optimized version + public BaseQuestGump(int label) + : base(75, 25) + { + m_Page = 0; + m_MaxPages = 0; + m_Label = label; + m_Title = null; + m_Buttons = new List(2); + + Closable = false; + + AddPage(0); + + AddImageTiled(50, 20, 400, 460, 0x1404); + AddImageTiled(50, 29, 30, 450, 0x28DC); + AddImageTiled(34, 140, 17, 339, 0x242F); + AddImage(48, 135, 0x28AB); + AddImage(-16, 285, 0x28A2); + AddImage(0, 10, 0x28B5); + AddImage(25, 0, 0x28B4); + AddImageTiled(83, 15, 350, 15, 0x280A); + AddImage(34, 479, 0x2842); + AddImage(442, 479, 0x2840); + AddImageTiled(51, 479, 392, 17, 0x2775); + AddImageTiled(415, 29, 44, 450, 0xA2D); + AddImageTiled(415, 29, 30, 450, 0x28DC); + // AddLabel( 100, 50, 0x481, "" ); + AddImage(370, 50, 0x589); + AddImage(379, 60, 0x15A9); + AddImage(425, 0, 0x28C9); + AddImage(90, 33, 0x232D); + AddHtmlLocalized(130, 45, 270, 16, label, 0xFFFFFF); + AddImageTiled(130, 65, 175, 1, 0x238D); + } + + public void BuildPage() + { + AddPage(++m_Page); + + if (m_Page > 1) + AddButton( + 130, + 430, + (int)ButtonGraphic.Previous, + (int)ButtonGraphic.Previous + 2, + 0, + GumpButtonType.Page, + m_Page - 1 + ); + + if (m_Page < m_MaxPages) + AddButton( + 275, + 430, + (int)ButtonGraphic.Continue, + (int)ButtonGraphic.Continue + 2, + 0, + GumpButtonType.Page, + m_Page + 1 + ); + + foreach (var button in m_Buttons) + AddButton( + button.Position == ButtonPosition.Left ? 95 : 313, + 455, + (int)button.Graphic, + (int)button.Graphic + 2, + button.ButtonID + ); + + if (m_Title != null) + AddHtmlLocalized(130, 68, 220, 48, 1114513, m_Title, 0x2710); //
~1_TOKEN~
+ } + + public void SetPageCount(int maxPages) + { + m_MaxPages = maxPages; + } + + public void SetTitle(TextDefinition def) + { + if (def.Number > 0) + m_Title = $"#{def.Number}"; // OSI does "@@#{0}" instead, why? KR client related? + else + m_Title = def.String; + } + + public void RegisterButton(ButtonPosition position, ButtonGraphic graphic, int buttonID) + { + m_Buttons.Add(new ButtonInfo(position, graphic, buttonID)); + } + + public void AddDescription(MLQuest quest) + { + AddHtmlLocalized( + 98, + 140, + 312, + 16, + quest.IsChainTriggered || quest.NextQuest != null ? 1075024 : 1072202, + 0x2710 + ); // Description [(quest chain)] + TextDefinition.AddHtmlText(this, 98, 156, 312, 240, quest.Description, false, true, 0x15F90, 0xBDE784); + } + + public void AddObjectives(MLQuest quest) + { + AddHtmlLocalized(98, 140, 312, 16, 1049073, 0x2710); // Objective: + AddHtmlLocalized( + 98, + 156, + 312, + 16, + quest.ObjectiveType == ObjectiveType.All ? 1072208 : 1072209, + 0x2710 + ); // All of the following / Only one of the following + + var y = 172; + + foreach (var objective in quest.Objectives) + { + objective.WriteToGump(this, ref y); + + if (objective.IsTimed) + { + if (objective is CollectObjective) + y -= 16; + + BaseObjectiveInstance.WriteTimeRemaining(this, ref y, objective.Duration); + } + } + } + + public void AddObjectivesProgress(MLQuestInstance instance) + { + var quest = instance.Quest; + + AddHtmlLocalized(98, 140, 312, 16, 1049073, 0x2710); // Objective: + AddHtmlLocalized( + 98, + 156, + 312, + 16, + quest.ObjectiveType == ObjectiveType.All ? 1072208 : 1072209, + 0x2710 + ); // All of the following / Only one of the following + + var y = 172; + + foreach (var objInstance in instance.Objectives) + objInstance.WriteToGump(this, ref y); + } + + public void AddRewardsPage(MLQuest quest) // For the quest log/offer gumps + { + AddHtmlLocalized(98, 140, 312, 16, 1072201, 0x2710); // Reward + + var y = 162; + + if (quest.Rewards.Count > 1) + { + // TODO: Is this what this is for? Does "Only one of the following" occur? + AddHtmlLocalized(98, 156, 312, 16, 1072208, 0x2710); // All of the following + y += 16; + } + + AddRewards(quest, 105, y, 16); + } + + public void AddRewards(MLQuest quest) // For the claim rewards gump + { + var y = 146; + + if (quest.Rewards.Count > 1) + { + // TODO: Is this what this is for? Does "Only one of the following" occur? + AddHtmlLocalized(100, 140, 312, 16, 1072208, 0x2710); // All of the following + y += 16; + } + + AddRewards(quest, 107, y, 26); + } + + public void AddRewards(MLQuest quest, int x, int y, int spacing) + { + var xReward = x + 28; + + foreach (var reward in quest.Rewards) + { + AddImage(x, y + 1, 0x4B9); + reward.WriteToGump(this, xReward, ref y); + y += spacing; + } + } + + public void AddConversation(TextDefinition text) + { + TextDefinition.AddHtmlText(this, 98, 140, 312, 180, text, false, true, 0x15F90, 0xBDE784); + } + + /* OSI gump IDs: + * 800 - QuestOfferGump + * 801 - QuestCancelConfirmGump + * 802 - ?? (gets closed by Toggle Quest Item) + * 803 - QuestRewardGump + * 804 - ?? (gets closed by Toggle Quest Item) + * 805 - QuestLogGump + * 806 - QuestConversationGump (refuse / in progress) + * 807 - ?? (gets closed by Toggle Quest Item and most quest gumps) + * 808 - InfoNPCGump + * 809 - QuestLogDetailedGump + * 810 - QuestReportBackGump + */ + public static void CloseOtherGumps(PlayerMobile pm) + { + pm.CloseGump(); + pm.CloseGump(); + pm.CloseGump(); + pm.CloseGump(); + // pm.CloseGump( typeof( UnknownGump807 ) ); + pm.CloseGump(); + } + + private struct ButtonInfo + { + public ButtonPosition Position { get; } + + public ButtonGraphic Graphic { get; } + + public int ButtonID { get; } + + public ButtonInfo(ButtonPosition position, ButtonGraphic graphic, int buttonID) + { + Position = position; + Graphic = graphic; + ButtonID = buttonID; + } + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Gumps/InfoNPCGump.cs b/Projects/UOContent/Engines/MLQuests/Gumps/InfoNPCGump.cs index 7e9a3a379..8aa04b5a4 100644 --- a/Projects/UOContent/Engines/MLQuests/Gumps/InfoNPCGump.cs +++ b/Projects/UOContent/Engines/MLQuests/Gumps/InfoNPCGump.cs @@ -1,17 +1,17 @@ -namespace Server.Engines.MLQuests.Gumps -{ - public class InfoNPCGump : BaseQuestGump - { - public InfoNPCGump(TextDefinition title, TextDefinition message) - : base(1060668) // INFORMATION - { - RegisterButton(ButtonPosition.Left, ButtonGraphic.Close, 3); - - SetPageCount(1); - - BuildPage(); - TextDefinition.AddHtmlText(this, 160, 108, 250, 16, title, false, false, 0x2710, 0x4AC684); - TextDefinition.AddHtmlText(this, 98, 156, 312, 180, message, false, true, 0x15F90, 0xBDE784); - } - } -} \ No newline at end of file +namespace Server.Engines.MLQuests.Gumps +{ + public class InfoNPCGump : BaseQuestGump + { + public InfoNPCGump(TextDefinition title, TextDefinition message) + : base(1060668) // INFORMATION + { + RegisterButton(ButtonPosition.Left, ButtonGraphic.Close, 3); + + SetPageCount(1); + + BuildPage(); + TextDefinition.AddHtmlText(this, 160, 108, 250, 16, title, false, false, 0x2710, 0x4AC684); + TextDefinition.AddHtmlText(this, 98, 156, 312, 180, message, false, true, 0x15F90, 0xBDE784); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Gumps/QuestCancelConfirmGump.cs b/Projects/UOContent/Engines/MLQuests/Gumps/QuestCancelConfirmGump.cs index 382606493..45414f0e8 100644 --- a/Projects/UOContent/Engines/MLQuests/Gumps/QuestCancelConfirmGump.cs +++ b/Projects/UOContent/Engines/MLQuests/Gumps/QuestCancelConfirmGump.cs @@ -1,97 +1,97 @@ -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.MLQuests.Gumps -{ - public class QuestCancelConfirmGump : Gump - { - private readonly bool m_CloseGumps; - private readonly MLQuestInstance m_Instance; - - public QuestCancelConfirmGump(MLQuestInstance instance, bool closeGumps = true) - : base(120, 50) - { - m_Instance = instance; - m_CloseGumps = closeGumps; - - if (closeGumps) - BaseQuestGump.CloseOtherGumps(instance.Player); - - AddPage(0); - - Closable = false; - - AddImageTiled(0, 0, 348, 262, 0xA8E); - AddAlphaRegion(0, 0, 348, 262); - - AddImage(0, 15, 0x27A8); - AddImageTiled(0, 30, 17, 200, 0x27A7); - AddImage(0, 230, 0x27AA); - - AddImage(15, 0, 0x280C); - AddImageTiled(30, 0, 300, 17, 0x280A); - AddImage(315, 0, 0x280E); - - AddImage(15, 244, 0x280C); - AddImageTiled(30, 244, 300, 17, 0x280A); - AddImage(315, 244, 0x280E); - - AddImage(330, 15, 0x27A8); - AddImageTiled(330, 30, 17, 200, 0x27A7); - AddImage(330, 230, 0x27AA); - - AddImage(333, 2, 0x2716); - AddImage(333, 248, 0x2716); - AddImage(2, 248, 0x2716); - AddImage(2, 2, 0x2716); - - AddHtmlLocalized(25, 22, 200, 20, 1049000, 0x7D00); // Confirm Quest Cancellation - AddImage(25, 40, 0xBBF); - - /* - * This quest will give you valuable information, skills - * and equipment that will help you advance in the - * game at a quicker pace.
- *
- * Are you certain you wish to cancel at this time? - */ - AddHtmlLocalized(25, 55, 300, 120, 1060836, 0xFFFFFF); - - MLQuest quest = instance.Quest; - - if (quest.IsChainTriggered || quest.NextQuest != null) - { - AddRadio(25, 145, 0x25F8, 0x25FB, false, 2); - AddHtmlLocalized(60, 150, 280, 20, 1075023, 0xFFFFFF); // Yes, I want to quit this entire chain! - } - - AddRadio(25, 180, 0x25F8, 0x25FB, true, 1); - AddHtmlLocalized(60, 185, 280, 20, 1049005, 0xFFFFFF); // Yes, I really want to quit this quest! - - AddRadio(25, 215, 0x25F8, 0x25FB, false, 0); - AddHtmlLocalized(60, 220, 280, 20, 1049006, 0xFFFFFF); // No, I don't want to quit. - - AddButton(265, 220, 0xF7, 0xF8, 7); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Instance.Removed) - return; - - switch (info.ButtonID) - { - case 7: // Okay - { - if (info.IsSwitched(2)) - m_Instance.Cancel(true); - else if (info.IsSwitched(1)) - m_Instance.Cancel(false); - - sender.Mobile.SendGump(new QuestLogGump(m_Instance.Player, m_CloseGumps)); - break; - } - } - } - } -} +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.MLQuests.Gumps +{ + public class QuestCancelConfirmGump : Gump + { + private readonly bool m_CloseGumps; + private readonly MLQuestInstance m_Instance; + + public QuestCancelConfirmGump(MLQuestInstance instance, bool closeGumps = true) + : base(120, 50) + { + m_Instance = instance; + m_CloseGumps = closeGumps; + + if (closeGumps) + BaseQuestGump.CloseOtherGumps(instance.Player); + + AddPage(0); + + Closable = false; + + AddImageTiled(0, 0, 348, 262, 0xA8E); + AddAlphaRegion(0, 0, 348, 262); + + AddImage(0, 15, 0x27A8); + AddImageTiled(0, 30, 17, 200, 0x27A7); + AddImage(0, 230, 0x27AA); + + AddImage(15, 0, 0x280C); + AddImageTiled(30, 0, 300, 17, 0x280A); + AddImage(315, 0, 0x280E); + + AddImage(15, 244, 0x280C); + AddImageTiled(30, 244, 300, 17, 0x280A); + AddImage(315, 244, 0x280E); + + AddImage(330, 15, 0x27A8); + AddImageTiled(330, 30, 17, 200, 0x27A7); + AddImage(330, 230, 0x27AA); + + AddImage(333, 2, 0x2716); + AddImage(333, 248, 0x2716); + AddImage(2, 248, 0x2716); + AddImage(2, 2, 0x2716); + + AddHtmlLocalized(25, 22, 200, 20, 1049000, 0x7D00); // Confirm Quest Cancellation + AddImage(25, 40, 0xBBF); + + /* + * This quest will give you valuable information, skills + * and equipment that will help you advance in the + * game at a quicker pace.
+ *
+ * Are you certain you wish to cancel at this time? + */ + AddHtmlLocalized(25, 55, 300, 120, 1060836, 0xFFFFFF); + + var quest = instance.Quest; + + if (quest.IsChainTriggered || quest.NextQuest != null) + { + AddRadio(25, 145, 0x25F8, 0x25FB, false, 2); + AddHtmlLocalized(60, 150, 280, 20, 1075023, 0xFFFFFF); // Yes, I want to quit this entire chain! + } + + AddRadio(25, 180, 0x25F8, 0x25FB, true, 1); + AddHtmlLocalized(60, 185, 280, 20, 1049005, 0xFFFFFF); // Yes, I really want to quit this quest! + + AddRadio(25, 215, 0x25F8, 0x25FB, false, 0); + AddHtmlLocalized(60, 220, 280, 20, 1049006, 0xFFFFFF); // No, I don't want to quit. + + AddButton(265, 220, 0xF7, 0xF8, 7); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Instance.Removed) + return; + + switch (info.ButtonID) + { + case 7: // Okay + { + if (info.IsSwitched(2)) + m_Instance.Cancel(true); + else if (info.IsSwitched(1)) + m_Instance.Cancel(false); + + sender.Mobile.SendGump(new QuestLogGump(m_Instance.Player, m_CloseGumps)); + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Gumps/QuestConversationGump.cs b/Projects/UOContent/Engines/MLQuests/Gumps/QuestConversationGump.cs index 5dd13de67..9004264a3 100644 --- a/Projects/UOContent/Engines/MLQuests/Gumps/QuestConversationGump.cs +++ b/Projects/UOContent/Engines/MLQuests/Gumps/QuestConversationGump.cs @@ -1,21 +1,21 @@ -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Gumps -{ - public class QuestConversationGump : BaseQuestGump - { - public QuestConversationGump(MLQuest quest, PlayerMobile pm, TextDefinition text) - : base(3006156) // Quest Conversation - { - CloseOtherGumps(pm); - - SetTitle(quest.Title); - RegisterButton(ButtonPosition.Right, ButtonGraphic.Close, 3); - - SetPageCount(1); - - BuildPage(); - AddConversation(text); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Gumps +{ + public class QuestConversationGump : BaseQuestGump + { + public QuestConversationGump(MLQuest quest, PlayerMobile pm, TextDefinition text) + : base(3006156) // Quest Conversation + { + CloseOtherGumps(pm); + + SetTitle(quest.Title); + RegisterButton(ButtonPosition.Right, ButtonGraphic.Close, 3); + + SetPageCount(1); + + BuildPage(); + AddConversation(text); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Gumps/QuestLogDetailedGump.cs b/Projects/UOContent/Engines/MLQuests/Gumps/QuestLogDetailedGump.cs index b837e7b80..f78c92556 100644 --- a/Projects/UOContent/Engines/MLQuests/Gumps/QuestLogDetailedGump.cs +++ b/Projects/UOContent/Engines/MLQuests/Gumps/QuestLogDetailedGump.cs @@ -1,73 +1,72 @@ -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.MLQuests.Gumps -{ - public class QuestLogDetailedGump : BaseQuestGump - { - private readonly bool m_CloseGumps; - private readonly MLQuestInstance m_Instance; - - public QuestLogDetailedGump(MLQuestInstance instance, bool closeGumps = true) - : base(1046026) // Quest Log - { - m_Instance = instance; - m_CloseGumps = closeGumps; - - PlayerMobile pm = instance.Player; - MLQuest quest = instance.Quest; - - if (closeGumps) - { - CloseOtherGumps(pm); - pm.CloseGump(); - } - - SetTitle(quest.Title); - RegisterButton(ButtonPosition.Left, ButtonGraphic.Resign, 1); - RegisterButton(ButtonPosition.Right, ButtonGraphic.Okay, 2); - - SetPageCount(3); - - BuildPage(); - AddDescription(quest); - - if (instance.Failed) // only displayed on the first page - AddHtmlLocalized(160, 80, 250, 16, 500039, 0x3C00); // Failed! - - BuildPage(); - AddObjectivesProgress(instance); - - BuildPage(); - AddRewardsPage(quest); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Instance.Removed) - return; - - switch (info.ButtonID) - { - case 1: // Resign - { - // TODO: Custom reward loss protection? OSI doesn't have this - // if (m_Instance.ClaimReward) - // pm.SendMessage( "You cannot cancel a quest with rewards pending." ); - // else - - sender.Mobile.SendGump(new QuestCancelConfirmGump(m_Instance, m_CloseGumps)); - - break; - } - case 2: // Okay - { - sender.Mobile.SendGump(new QuestLogGump(m_Instance.Player, m_CloseGumps)); - - break; - } - } - } - } -} +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.MLQuests.Gumps +{ + public class QuestLogDetailedGump : BaseQuestGump + { + private readonly bool m_CloseGumps; + private readonly MLQuestInstance m_Instance; + + public QuestLogDetailedGump(MLQuestInstance instance, bool closeGumps = true) + : base(1046026) // Quest Log + { + m_Instance = instance; + m_CloseGumps = closeGumps; + + var pm = instance.Player; + var quest = instance.Quest; + + if (closeGumps) + { + CloseOtherGumps(pm); + pm.CloseGump(); + } + + SetTitle(quest.Title); + RegisterButton(ButtonPosition.Left, ButtonGraphic.Resign, 1); + RegisterButton(ButtonPosition.Right, ButtonGraphic.Okay, 2); + + SetPageCount(3); + + BuildPage(); + AddDescription(quest); + + if (instance.Failed) // only displayed on the first page + AddHtmlLocalized(160, 80, 250, 16, 500039, 0x3C00); // Failed! + + BuildPage(); + AddObjectivesProgress(instance); + + BuildPage(); + AddRewardsPage(quest); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Instance.Removed) + return; + + switch (info.ButtonID) + { + case 1: // Resign + { + // TODO: Custom reward loss protection? OSI doesn't have this + // if (m_Instance.ClaimReward) + // pm.SendMessage( "You cannot cancel a quest with rewards pending." ); + // else + + sender.Mobile.SendGump(new QuestCancelConfirmGump(m_Instance, m_CloseGumps)); + + break; + } + case 2: // Okay + { + sender.Mobile.SendGump(new QuestLogGump(m_Instance.Player, m_CloseGumps)); + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Gumps/QuestLogGump.cs b/Projects/UOContent/Engines/MLQuests/Gumps/QuestLogGump.cs index 3ee72b3c0..5826cd2ee 100644 --- a/Projects/UOContent/Engines/MLQuests/Gumps/QuestLogGump.cs +++ b/Projects/UOContent/Engines/MLQuests/Gumps/QuestLogGump.cs @@ -1,77 +1,86 @@ -using System.Collections.Generic; -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.MLQuests.Gumps -{ - public class QuestLogGump : BaseQuestGump - { - private readonly bool m_CloseGumps; - private readonly PlayerMobile m_Owner; - - public QuestLogGump(PlayerMobile pm, bool closeGumps = true) - : base(1046026) // Quest Log - { - m_Owner = pm; - m_CloseGumps = closeGumps; - - if (closeGumps) - { - pm.CloseGump(); - pm.CloseGump(); - } - - RegisterButton(ButtonPosition.Right, ButtonGraphic.Okay, 3); - - SetPageCount(1); - - BuildPage(); - - int numberColor, stringColor; - - MLQuestContext context = MLQuestSystem.GetContext(pm); - - if (context != null) - { - List instances = context.QuestInstances; - - for (int i = 0; i < instances.Count; ++i) - { - if (instances[i].Failed) - { - numberColor = 0x3C00; - stringColor = 0x7B0000; - } - else - { - numberColor = stringColor = 0xFFFFFF; - } - - TextDefinition.AddHtmlText(this, 98, 140 + 21 * i, 270, 21, instances[i].Quest.Title, false, false, - numberColor, stringColor); - AddButton(368, 140 + 21 * i, 0x26B0, 0x26B1, 6 + i, GumpButtonType.Reply, 1); - } - } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID < 6) - return; - - MLQuestContext context = MLQuestSystem.GetContext(m_Owner); - - if (context == null) - return; - - List instances = context.QuestInstances; - int index = info.ButtonID - 6; - - if (index >= instances.Count) - return; - - sender.Mobile.SendGump(new QuestLogDetailedGump(instances[index], m_CloseGumps)); - } - } -} \ No newline at end of file +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.MLQuests.Gumps +{ + public class QuestLogGump : BaseQuestGump + { + private readonly bool m_CloseGumps; + private readonly PlayerMobile m_Owner; + + public QuestLogGump(PlayerMobile pm, bool closeGumps = true) + : base(1046026) // Quest Log + { + m_Owner = pm; + m_CloseGumps = closeGumps; + + if (closeGumps) + { + pm.CloseGump(); + pm.CloseGump(); + } + + RegisterButton(ButtonPosition.Right, ButtonGraphic.Okay, 3); + + SetPageCount(1); + + BuildPage(); + + int numberColor, stringColor; + + var context = MLQuestSystem.GetContext(pm); + + if (context != null) + { + var instances = context.QuestInstances; + + for (var i = 0; i < instances.Count; ++i) + { + if (instances[i].Failed) + { + numberColor = 0x3C00; + stringColor = 0x7B0000; + } + else + { + numberColor = stringColor = 0xFFFFFF; + } + + TextDefinition.AddHtmlText( + this, + 98, + 140 + 21 * i, + 270, + 21, + instances[i].Quest.Title, + false, + false, + numberColor, + stringColor + ); + AddButton(368, 140 + 21 * i, 0x26B0, 0x26B1, 6 + i, GumpButtonType.Reply, 1); + } + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID < 6) + return; + + var context = MLQuestSystem.GetContext(m_Owner); + + if (context == null) + return; + + var instances = context.QuestInstances; + var index = info.ButtonID - 6; + + if (index >= instances.Count) + return; + + sender.Mobile.SendGump(new QuestLogDetailedGump(instances[index], m_CloseGumps)); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Gumps/QuestOfferGump.cs b/Projects/UOContent/Engines/MLQuests/Gumps/QuestOfferGump.cs index 92872d979..f39a4f5fb 100644 --- a/Projects/UOContent/Engines/MLQuests/Gumps/QuestOfferGump.cs +++ b/Projects/UOContent/Engines/MLQuests/Gumps/QuestOfferGump.cs @@ -1,57 +1,57 @@ -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.MLQuests.Gumps -{ - public class QuestOfferGump : BaseQuestGump - { - private readonly MLQuest m_Quest; - private readonly IQuestGiver m_Quester; - - public QuestOfferGump(MLQuest quest, IQuestGiver quester, PlayerMobile pm) - : base(1049010) // Quest Offer - { - m_Quest = quest; - m_Quester = quester; - - CloseOtherGumps(pm); - pm.CloseGump(); - - SetTitle(quest.Title); - RegisterButton(ButtonPosition.Left, ButtonGraphic.Accept, 1); - RegisterButton(ButtonPosition.Right, ButtonGraphic.Refuse, 2); - - SetPageCount(3); - - BuildPage(); - AddDescription(quest); - - BuildPage(); - AddObjectives(quest); - - BuildPage(); - AddRewardsPage(quest); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (!(sender.Mobile is PlayerMobile pm)) - return; - - switch (info.ButtonID) - { - case 1: // Accept - { - m_Quest.OnAccept(m_Quester, pm); - break; - } - case 2: // Refuse - { - m_Quest.OnRefuse(m_Quester, pm); - break; - } - } - } - } -} \ No newline at end of file +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.MLQuests.Gumps +{ + public class QuestOfferGump : BaseQuestGump + { + private readonly MLQuest m_Quest; + private readonly IQuestGiver m_Quester; + + public QuestOfferGump(MLQuest quest, IQuestGiver quester, PlayerMobile pm) + : base(1049010) // Quest Offer + { + m_Quest = quest; + m_Quester = quester; + + CloseOtherGumps(pm); + pm.CloseGump(); + + SetTitle(quest.Title); + RegisterButton(ButtonPosition.Left, ButtonGraphic.Accept, 1); + RegisterButton(ButtonPosition.Right, ButtonGraphic.Refuse, 2); + + SetPageCount(3); + + BuildPage(); + AddDescription(quest); + + BuildPage(); + AddObjectives(quest); + + BuildPage(); + AddRewardsPage(quest); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (!(sender.Mobile is PlayerMobile pm)) + return; + + switch (info.ButtonID) + { + case 1: // Accept + { + m_Quest.OnAccept(m_Quester, pm); + break; + } + case 2: // Refuse + { + m_Quest.OnRefuse(m_Quester, pm); + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Gumps/QuestReportBackGump.cs b/Projects/UOContent/Engines/MLQuests/Gumps/QuestReportBackGump.cs index 58c4c29eb..773256dfa 100644 --- a/Projects/UOContent/Engines/MLQuests/Gumps/QuestReportBackGump.cs +++ b/Projects/UOContent/Engines/MLQuests/Gumps/QuestReportBackGump.cs @@ -1,38 +1,37 @@ -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.MLQuests.Gumps -{ - public class QuestReportBackGump : BaseQuestGump - { - private readonly MLQuestInstance m_Instance; - - public QuestReportBackGump(MLQuestInstance instance) - : base(3006156) // Quest Conversation - { - m_Instance = instance; - - MLQuest quest = instance.Quest; - PlayerMobile pm = instance.Player; - - // TODO: Check close sequence - CloseOtherGumps(pm); - - SetTitle(quest.Title); - RegisterButton(ButtonPosition.Left, ButtonGraphic.Continue, 4); - RegisterButton(ButtonPosition.Right, ButtonGraphic.Close, 3); - - SetPageCount(1); - - BuildPage(); - AddConversation(quest.CompletionMessage); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 4) - m_Instance.ContinueReportBack(true); - } - } -} \ No newline at end of file +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.MLQuests.Gumps +{ + public class QuestReportBackGump : BaseQuestGump + { + private readonly MLQuestInstance m_Instance; + + public QuestReportBackGump(MLQuestInstance instance) + : base(3006156) // Quest Conversation + { + m_Instance = instance; + + var quest = instance.Quest; + var pm = instance.Player; + + // TODO: Check close sequence + CloseOtherGumps(pm); + + SetTitle(quest.Title); + RegisterButton(ButtonPosition.Left, ButtonGraphic.Continue, 4); + RegisterButton(ButtonPosition.Right, ButtonGraphic.Close, 3); + + SetPageCount(1); + + BuildPage(); + AddConversation(quest.CompletionMessage); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 4) + m_Instance.ContinueReportBack(true); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Gumps/QuestRewardGump.cs b/Projects/UOContent/Engines/MLQuests/Gumps/QuestRewardGump.cs index 660ed7a40..d1fee0e51 100644 --- a/Projects/UOContent/Engines/MLQuests/Gumps/QuestRewardGump.cs +++ b/Projects/UOContent/Engines/MLQuests/Gumps/QuestRewardGump.cs @@ -1,36 +1,35 @@ -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.MLQuests.Gumps -{ - public class QuestRewardGump : BaseQuestGump - { - private readonly MLQuestInstance m_Instance; - - public QuestRewardGump(MLQuestInstance instance) - : base(1072201) // Reward - { - m_Instance = instance; - - MLQuest quest = instance.Quest; - PlayerMobile pm = instance.Player; - - CloseOtherGumps(pm); - - SetTitle(quest.Title); - RegisterButton(ButtonPosition.Left, ButtonGraphic.Accept, 1); - - SetPageCount(1); - - BuildPage(); - AddRewards(quest); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 1) - m_Instance.ClaimRewards(); - } - } -} \ No newline at end of file +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.MLQuests.Gumps +{ + public class QuestRewardGump : BaseQuestGump + { + private readonly MLQuestInstance m_Instance; + + public QuestRewardGump(MLQuestInstance instance) + : base(1072201) // Reward + { + m_Instance = instance; + + var quest = instance.Quest; + var pm = instance.Player; + + CloseOtherGumps(pm); + + SetTitle(quest.Title); + RegisterButton(ButtonPosition.Left, ButtonGraphic.Accept, 1); + + SetPageCount(1); + + BuildPage(); + AddRewards(quest); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 1) + m_Instance.ClaimRewards(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Gumps/RaceChangeGump.cs b/Projects/UOContent/Engines/MLQuests/Gumps/RaceChangeGump.cs index 603095f8c..77d9a11f8 100644 --- a/Projects/UOContent/Engines/MLQuests/Gumps/RaceChangeGump.cs +++ b/Projects/UOContent/Engines/MLQuests/Gumps/RaceChangeGump.cs @@ -1,331 +1,331 @@ -using System; -using System.Collections.Generic; -using Server.Gumps; -using Server.Items; -using Server.Mobiles; -using Server.Network; -using Server.Spells.Fifth; -using Server.Spells.Ninjitsu; -using Server.Spells.Seventh; - -namespace Server.Engines.MLQuests.Gumps -{ - public interface IRaceChanger - { - bool CheckComplete(PlayerMobile from); - void ConsumeNeeded(PlayerMobile from); - void OnCancel(PlayerMobile from); - } - - public class RaceChangeConfirmGump : Gump - { - private static Dictionary m_Pending; - private readonly PlayerMobile m_From; - - private readonly IRaceChanger m_Owner; - private readonly Race m_Race; - - public RaceChangeConfirmGump(IRaceChanger owner, PlayerMobile from, Race targetRace) - : base(50, 50) - { - from.CloseGump(); - - m_Owner = owner; - m_From = from; - m_Race = targetRace; - - AddPage(0); - AddBackground(0, 0, 240, 135, 0x2422); - - if (targetRace == Race.Human) - AddHtmlLocalized(15, 15, 210, 75, 1073643, 0); // Are you sure you wish to embrace your humanity? - else if (targetRace == Race.Elf) - AddHtmlLocalized(15, 15, 210, 75, 1073642, 0); // Are you sure you want to follow the elven ways? - else - AddHtml(15, 15, 210, 75, $"Are you sure you want to change your race to {targetRace.Name}?"); - - AddButton(160, 95, 0xF7, 0xF8, 1); - AddButton(90, 95, 0xF2, 0xF1, 0); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - switch (info.ButtonID) - { - case 0: // Cancel - { - m_Owner?.OnCancel(m_From); - - break; - } - case 1: // Okay - { - if (m_Owner?.CheckComplete(m_From) != false) - Offer(m_Owner, m_From, m_Race); - - break; - } - } - } - - public static void Initialize() - { - m_Pending = new Dictionary(); - - PacketHandlers.RegisterExtended(0x2A, true, RaceChangeReply); - } - - public static bool IsPending(NetState state) => state != null && m_Pending.ContainsKey(state); - - private static void Offer(IRaceChanger owner, PlayerMobile from, Race targetRace) - { - NetState ns = from.NetState; - - if (ns == null || !CanChange(from, targetRace)) - return; - - CloseCurrent(ns); - - m_Pending[ns] = new RaceChangeState(owner, ns, targetRace); - ns.Send(new RaceChanger(from.Female, targetRace)); - } - - private static void CloseCurrent(NetState ns) - { - if (m_Pending.TryGetValue(ns, out RaceChangeState state)) - { - state.m_Timeout.Stop(); - m_Pending.Remove(ns); - } - - ns.Send(CloseRaceChanger.Instance); - } - - private static void Timeout(NetState ns) - { - if (IsPending(ns)) - { - m_Pending.Remove(ns); - ns.Send(CloseRaceChanger.Instance); - } - } - - public static bool IsWearingEquipment(Mobile from) - { - foreach (Item item in from.Items) - switch (item.Layer) - { - case Layer.Hair: - case Layer.FacialHair: - case Layer.Backpack: - case Layer.Mount: - case Layer.Bank: - { - continue; // ignore - } - default: - { - return true; - } - } - - return false; - } - - private static bool CanChange(PlayerMobile from, Race targetRace) - { - if (from.Deleted) - return false; - - if (from.Race == targetRace) - from.SendLocalizedMessage(1111918); // You are already that race. - else if (!MondainsLegacy.CheckML(from, false)) - from.SendLocalizedMessage(1073651); // You must have Mondain's Legacy before proceeding... - else if (!from.Alive) - from.SendLocalizedMessage(1073646); // Only the living may proceed... - else if (from.Mounted) - from.SendLocalizedMessage(1073647); // You may not continue while mounted... - else if (!from.CanBeginAction() || DisguiseTimers.IsDisguised(from) || - AnimalForm.UnderTransformation(from) || !from.CanBeginAction() || - from.IsBodyMod) // TODO: Does this cover everything? - from.SendLocalizedMessage(1073648); // You may only proceed while in your original state... - else if (from.Spell?.IsCasting == true) - from.SendLocalizedMessage(1073649); // One may not proceed while embracing magic... - else if (from.Poisoned) - from.SendLocalizedMessage(1073652); // You must be healthy to proceed... - else if (IsWearingEquipment(from)) - from.SendLocalizedMessage(1073650); // To proceed you must be unburdened by equipment... - else - return true; - - return false; - } - - private static void RaceChangeReply(NetState state, PacketReader pvSrc) - { - if (!m_Pending.TryGetValue(state, out RaceChangeState raceChangeState)) - return; - - CloseCurrent(state); - - if (!(state.Mobile is PlayerMobile pm)) - return; - - IRaceChanger owner = raceChangeState.m_Owner; - Race targetRace = raceChangeState.m_TargetRace; - - if (pvSrc.Length == 5) - { - owner?.OnCancel(pm); - - return; - } - - if (!CanChange(pm, targetRace) || owner?.CheckComplete(pm) == false) - return; - - int hue = pvSrc.ReadUInt16(); - int hairItemId = pvSrc.ReadUInt16(); - int hairHue = pvSrc.ReadUInt16(); - int facialHairItemId = pvSrc.ReadUInt16(); - int facialHairHue = pvSrc.ReadUInt16(); - - pm.Race = targetRace; - pm.Hue = targetRace.ClipSkinHue(hue) | 0x8000; - - if (targetRace.ValidateHair(pm, hairItemId)) - { - pm.HairItemID = hairItemId; - pm.HairHue = targetRace.ClipHairHue(hairHue); - } - else - { - pm.HairItemID = 0; - } - - if (targetRace.ValidateFacialHair(pm, facialHairItemId)) - { - pm.FacialHairItemID = facialHairItemId; - pm.FacialHairHue = targetRace.ClipHairHue(facialHairHue); - } - else - { - pm.FacialHairItemID = 0; - } - - if (targetRace == Race.Human) - pm.SendLocalizedMessage(1073654); // You are now fully human. - else if (targetRace == Race.Elf) - pm.SendLocalizedMessage(1073653); // You are now fully initiated into the Elven culture. - else - pm.SendMessage("You have fully changed your race to {0}.", targetRace.Name); - - owner?.ConsumeNeeded(pm); - } - - private class RaceChangeState - { - private static readonly TimeSpan m_TimeoutDelay = TimeSpan.FromMinutes(1); - - public readonly IRaceChanger m_Owner; - public readonly Race m_TargetRace; - public readonly Timer m_Timeout; - - public RaceChangeState(IRaceChanger owner, NetState ns, Race targetRace) - { - m_Owner = owner; - m_TargetRace = targetRace; - m_Timeout = Timer.DelayCall(m_TimeoutDelay, Timeout, ns); - } - } - } - - public sealed class RaceChanger : Packet - { - public RaceChanger(bool female, Race targetRace) - : base(0xBF) - { - EnsureCapacity(7); - - Stream.Write((short)0x2A); - Stream.Write((byte)(female ? 1 : 0)); - Stream.Write((byte)(targetRace.RaceID + 1)); - } - } - - public sealed class CloseRaceChanger : Packet - { - public static readonly Packet Instance = SetStatic(new CloseRaceChanger()); - - private CloseRaceChanger() - : base(0xBF) - { - EnsureCapacity(7); - - Stream.Write((short)0x2A); - Stream.Write((byte)0); - Stream.Write((byte)0xFF); - } - } - - public class RaceChangeDeed : Item, IRaceChanger - { - [Constructible] - public RaceChangeDeed() - : base(0x14F0) => - LootType = LootType.Blessed; - - public RaceChangeDeed(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "a race change deed"; - - public bool CheckComplete(PlayerMobile pm) - { - if (Deleted) - return false; - - if (!IsChildOf(pm.Backpack)) - { - pm.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - return false; - } - - return true; - } - - public void ConsumeNeeded(PlayerMobile pm) - { - Consume(); - } - - public void OnCancel(PlayerMobile pm) - { - } - - public override void OnDoubleClick(Mobile from) - { - if (!(from is PlayerMobile pm)) - return; - - if (CheckComplete(pm)) - pm.SendGump(new RaceChangeConfirmGump(this, pm, pm.Race == Race.Human ? Race.Elf : Race.Human)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using System.Collections.Generic; +using Server.Gumps; +using Server.Items; +using Server.Mobiles; +using Server.Network; +using Server.Spells.Fifth; +using Server.Spells.Ninjitsu; +using Server.Spells.Seventh; + +namespace Server.Engines.MLQuests.Gumps +{ + public interface IRaceChanger + { + bool CheckComplete(PlayerMobile from); + void ConsumeNeeded(PlayerMobile from); + void OnCancel(PlayerMobile from); + } + + public class RaceChangeConfirmGump : Gump + { + private static Dictionary m_Pending; + private readonly PlayerMobile m_From; + + private readonly IRaceChanger m_Owner; + private readonly Race m_Race; + + public RaceChangeConfirmGump(IRaceChanger owner, PlayerMobile from, Race targetRace) + : base(50, 50) + { + from.CloseGump(); + + m_Owner = owner; + m_From = from; + m_Race = targetRace; + + AddPage(0); + AddBackground(0, 0, 240, 135, 0x2422); + + if (targetRace == Race.Human) + AddHtmlLocalized(15, 15, 210, 75, 1073643, 0); // Are you sure you wish to embrace your humanity? + else if (targetRace == Race.Elf) + AddHtmlLocalized(15, 15, 210, 75, 1073642, 0); // Are you sure you want to follow the elven ways? + else + AddHtml(15, 15, 210, 75, $"Are you sure you want to change your race to {targetRace.Name}?"); + + AddButton(160, 95, 0xF7, 0xF8, 1); + AddButton(90, 95, 0xF2, 0xF1, 0); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + switch (info.ButtonID) + { + case 0: // Cancel + { + m_Owner?.OnCancel(m_From); + + break; + } + case 1: // Okay + { + if (m_Owner?.CheckComplete(m_From) != false) + Offer(m_Owner, m_From, m_Race); + + break; + } + } + } + + public static void Initialize() + { + m_Pending = new Dictionary(); + + PacketHandlers.RegisterExtended(0x2A, true, RaceChangeReply); + } + + public static bool IsPending(NetState state) => state != null && m_Pending.ContainsKey(state); + + private static void Offer(IRaceChanger owner, PlayerMobile from, Race targetRace) + { + var ns = from.NetState; + + if (ns == null || !CanChange(from, targetRace)) + return; + + CloseCurrent(ns); + + m_Pending[ns] = new RaceChangeState(owner, ns, targetRace); + ns.Send(new RaceChanger(from.Female, targetRace)); + } + + private static void CloseCurrent(NetState ns) + { + if (m_Pending.TryGetValue(ns, out var state)) + { + state.m_Timeout.Stop(); + m_Pending.Remove(ns); + } + + ns.Send(CloseRaceChanger.Instance); + } + + private static void Timeout(NetState ns) + { + if (IsPending(ns)) + { + m_Pending.Remove(ns); + ns.Send(CloseRaceChanger.Instance); + } + } + + public static bool IsWearingEquipment(Mobile from) + { + foreach (var item in from.Items) + switch (item.Layer) + { + case Layer.Hair: + case Layer.FacialHair: + case Layer.Backpack: + case Layer.Mount: + case Layer.Bank: + { + continue; // ignore + } + default: + { + return true; + } + } + + return false; + } + + private static bool CanChange(PlayerMobile from, Race targetRace) + { + if (from.Deleted) + return false; + + if (from.Race == targetRace) + from.SendLocalizedMessage(1111918); // You are already that race. + else if (!MondainsLegacy.CheckML(from, false)) + from.SendLocalizedMessage(1073651); // You must have Mondain's Legacy before proceeding... + else if (!from.Alive) + from.SendLocalizedMessage(1073646); // Only the living may proceed... + else if (from.Mounted) + from.SendLocalizedMessage(1073647); // You may not continue while mounted... + else if (!from.CanBeginAction() || DisguiseTimers.IsDisguised(from) || + AnimalForm.UnderTransformation(from) || !from.CanBeginAction() || + from.IsBodyMod) // TODO: Does this cover everything? + from.SendLocalizedMessage(1073648); // You may only proceed while in your original state... + else if (from.Spell?.IsCasting == true) + from.SendLocalizedMessage(1073649); // One may not proceed while embracing magic... + else if (from.Poisoned) + from.SendLocalizedMessage(1073652); // You must be healthy to proceed... + else if (IsWearingEquipment(from)) + from.SendLocalizedMessage(1073650); // To proceed you must be unburdened by equipment... + else + return true; + + return false; + } + + private static void RaceChangeReply(NetState state, PacketReader pvSrc) + { + if (!m_Pending.TryGetValue(state, out var raceChangeState)) + return; + + CloseCurrent(state); + + if (!(state.Mobile is PlayerMobile pm)) + return; + + var owner = raceChangeState.m_Owner; + var targetRace = raceChangeState.m_TargetRace; + + if (pvSrc.Length == 5) + { + owner?.OnCancel(pm); + + return; + } + + if (!CanChange(pm, targetRace) || owner?.CheckComplete(pm) == false) + return; + + int hue = pvSrc.ReadUInt16(); + int hairItemId = pvSrc.ReadUInt16(); + int hairHue = pvSrc.ReadUInt16(); + int facialHairItemId = pvSrc.ReadUInt16(); + int facialHairHue = pvSrc.ReadUInt16(); + + pm.Race = targetRace; + pm.Hue = targetRace.ClipSkinHue(hue) | 0x8000; + + if (targetRace.ValidateHair(pm, hairItemId)) + { + pm.HairItemID = hairItemId; + pm.HairHue = targetRace.ClipHairHue(hairHue); + } + else + { + pm.HairItemID = 0; + } + + if (targetRace.ValidateFacialHair(pm, facialHairItemId)) + { + pm.FacialHairItemID = facialHairItemId; + pm.FacialHairHue = targetRace.ClipHairHue(facialHairHue); + } + else + { + pm.FacialHairItemID = 0; + } + + if (targetRace == Race.Human) + pm.SendLocalizedMessage(1073654); // You are now fully human. + else if (targetRace == Race.Elf) + pm.SendLocalizedMessage(1073653); // You are now fully initiated into the Elven culture. + else + pm.SendMessage("You have fully changed your race to {0}.", targetRace.Name); + + owner?.ConsumeNeeded(pm); + } + + private class RaceChangeState + { + private static readonly TimeSpan m_TimeoutDelay = TimeSpan.FromMinutes(1); + + public readonly IRaceChanger m_Owner; + public readonly Race m_TargetRace; + public readonly Timer m_Timeout; + + public RaceChangeState(IRaceChanger owner, NetState ns, Race targetRace) + { + m_Owner = owner; + m_TargetRace = targetRace; + m_Timeout = Timer.DelayCall(m_TimeoutDelay, Timeout, ns); + } + } + } + + public sealed class RaceChanger : Packet + { + public RaceChanger(bool female, Race targetRace) + : base(0xBF) + { + EnsureCapacity(7); + + Stream.Write((short)0x2A); + Stream.Write((byte)(female ? 1 : 0)); + Stream.Write((byte)(targetRace.RaceID + 1)); + } + } + + public sealed class CloseRaceChanger : Packet + { + public static readonly Packet Instance = SetStatic(new CloseRaceChanger()); + + private CloseRaceChanger() + : base(0xBF) + { + EnsureCapacity(7); + + Stream.Write((short)0x2A); + Stream.Write((byte)0); + Stream.Write((byte)0xFF); + } + } + + public class RaceChangeDeed : Item, IRaceChanger + { + [Constructible] + public RaceChangeDeed() + : base(0x14F0) => + LootType = LootType.Blessed; + + public RaceChangeDeed(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "a race change deed"; + + public bool CheckComplete(PlayerMobile pm) + { + if (Deleted) + return false; + + if (!IsChildOf(pm.Backpack)) + { + pm.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + return false; + } + + return true; + } + + public void ConsumeNeeded(PlayerMobile pm) + { + Consume(); + } + + public void OnCancel(PlayerMobile pm) + { + } + + public override void OnDoubleClick(Mobile from) + { + if (!(from is PlayerMobile pm)) + return; + + if (CheckComplete(pm)) + pm.SendGump(new RaceChangeConfirmGump(this, pm, pm.Race == Race.Human ? Race.Elf : Race.Human)); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/IQuestGiver.cs b/Projects/UOContent/Engines/MLQuests/IQuestGiver.cs index 59bd6b5a6..63312e757 100644 --- a/Projects/UOContent/Engines/MLQuests/IQuestGiver.cs +++ b/Projects/UOContent/Engines/MLQuests/IQuestGiver.cs @@ -1,15 +1,15 @@ -using System; -using System.Collections.Generic; - -namespace Server.Engines.MLQuests -{ - public interface IQuestGiver - { - List MLQuests { get; } - - Serial Serial { get; } - bool Deleted { get; } - - Type GetType(); - } -} \ No newline at end of file +using System; +using System.Collections.Generic; + +namespace Server.Engines.MLQuests +{ + public interface IQuestGiver + { + List MLQuests { get; } + + Serial Serial { get; } + bool Deleted { get; } + + Type GetType(); + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/ABauble.cs b/Projects/UOContent/Engines/MLQuests/Items/ABauble.cs index 26cac4624..4f9cbc9a9 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/ABauble.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/ABauble.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class ABauble : Item - { - [Constructible] - public ABauble() : base(0x23B) => LootType = LootType.Blessed; - - public ABauble(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073137; // A bauble - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ABauble : Item + { + [Constructible] + public ABauble() : base(0x23B) => LootType = LootType.Blessed; + + public ABauble(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073137; // A bauble + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/APersonalLetterAddressedToAhie.cs b/Projects/UOContent/Engines/MLQuests/Items/APersonalLetterAddressedToAhie.cs index 9676709f3..5dccf5f17 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/APersonalLetterAddressedToAhie.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/APersonalLetterAddressedToAhie.cs @@ -1,38 +1,38 @@ -using System; - -namespace Server.Items -{ - public class APersonalLetterAddressedToAhie : TransientItem - { - [Constructible] - public APersonalLetterAddressedToAhie() : base(0x14ED, TimeSpan.FromMinutes(30)) => LootType = LootType.Blessed; - - public APersonalLetterAddressedToAhie(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073128; // A personal letter addressed to: Ahie - - public override bool Nontransferable => true; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - AddQuestItemProperty(list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class APersonalLetterAddressedToAhie : TransientItem + { + [Constructible] + public APersonalLetterAddressedToAhie() : base(0x14ED, TimeSpan.FromMinutes(30)) => LootType = LootType.Blessed; + + public APersonalLetterAddressedToAhie(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073128; // A personal letter addressed to: Ahie + + public override bool Nontransferable => true; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + AddQuestItemProperty(list); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/AlchemistsBandage.cs b/Projects/UOContent/Engines/MLQuests/Items/AlchemistsBandage.cs index 59221d04a..116550434 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/AlchemistsBandage.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/AlchemistsBandage.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class AlchemistsBandage : Item - { - [Constructible] - public AlchemistsBandage() : base(0xE21) - { - LootType = LootType.Blessed; - Hue = 0x482; - } - - public AlchemistsBandage(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075452; // Alchemist's Bandage - - public override bool Nontransferable => true; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - AddQuestItemProperty(list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AlchemistsBandage : Item + { + [Constructible] + public AlchemistsBandage() : base(0xE21) + { + LootType = LootType.Blessed; + Hue = 0x482; + } + + public AlchemistsBandage(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075452; // Alchemist's Bandage + + public override bool Nontransferable => true; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + AddQuestItemProperty(list); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/AnOldNecklace.cs b/Projects/UOContent/Engines/MLQuests/Items/AnOldNecklace.cs index ebebb6f13..f7e0db1ce 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/AnOldNecklace.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/AnOldNecklace.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class AnOldNecklace : Necklace - { - [Constructible] - public AnOldNecklace() => Hue = 0x222; - - public AnOldNecklace(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075525; // an old necklace - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AnOldNecklace : Necklace + { + [Constructible] + public AnOldNecklace() => Hue = 0x222; + + public AnOldNecklace(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075525; // an old necklace + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/AnOldRing.cs b/Projects/UOContent/Engines/MLQuests/Items/AnOldRing.cs index ad6173647..95f379db8 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/AnOldRing.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/AnOldRing.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class AnOldRing : GoldRing - { - [Constructible] - public AnOldRing() => Hue = 0x222; - - public AnOldRing(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075524; // an old ring - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AnOldRing : GoldRing + { + [Constructible] + public AnOldRing() => Hue = 0x222; + + public AnOldRing(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075524; // an old ring + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/AndricSatchel.cs b/Projects/UOContent/Engines/MLQuests/Items/AndricSatchel.cs index f7644db1d..1f48616b9 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/AndricSatchel.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/AndricSatchel.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class AndricSatchel : Backpack - { - [Constructible] - public AndricSatchel() - { - Hue = Utility.RandomBrightHue(); - DropItem(new Feather(10)); - DropItem(new FletcherTools()); - } - - public AndricSatchel(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AndricSatchel : Backpack + { + [Constructible] + public AndricSatchel() + { + Hue = Utility.RandomBrightHue(); + DropItem(new Feather(10)); + DropItem(new FletcherTools()); + } + + public AndricSatchel(Serial serial) + : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/AndrosGratitude.cs b/Projects/UOContent/Engines/MLQuests/Items/AndrosGratitude.cs index a3aa8d9b0..4a453c306 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/AndrosGratitude.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/AndrosGratitude.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class AndrosGratitude : SmithHammer - { - [Constructible] - public AndrosGratitude() : base(10) => LootType = LootType.Blessed; - - public AndrosGratitude(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075345; // Andros Gratitude - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AndrosGratitude : SmithHammer + { + [Constructible] + public AndrosGratitude() : base(10) => LootType = LootType.Blessed; + + public AndrosGratitude(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075345; // Andros Gratitude + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/AsandosSatchel.cs b/Projects/UOContent/Engines/MLQuests/Items/AsandosSatchel.cs index a84129313..626234430 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/AsandosSatchel.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/AsandosSatchel.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class AsandosSatchel : Backpack - { - [Constructible] - public AsandosSatchel() - { - Hue = Utility.RandomBrightHue(); - DropItem(new SackFlour()); - DropItem(new Skillet()); - } - - public AsandosSatchel(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AsandosSatchel : Backpack + { + [Constructible] + public AsandosSatchel() + { + Hue = Utility.RandomBrightHue(); + DropItem(new SackFlour()); + DropItem(new Skillet()); + } + + public AsandosSatchel(Serial serial) + : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/BasinOfCrystalClearWater.cs b/Projects/UOContent/Engines/MLQuests/Items/BasinOfCrystalClearWater.cs index 824069d5a..b4f725563 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/BasinOfCrystalClearWater.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/BasinOfCrystalClearWater.cs @@ -1,36 +1,36 @@ -namespace Server.Items -{ - public class BasinOfCrystalClearWater : Item - { - [Constructible] - public BasinOfCrystalClearWater() : base(0x1008) => LootType = LootType.Blessed; - - public BasinOfCrystalClearWater(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075303; // Basin of Crystal-Clear Water - - public override bool Nontransferable => true; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - AddQuestItemProperty(list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class BasinOfCrystalClearWater : Item + { + [Constructible] + public BasinOfCrystalClearWater() : base(0x1008) => LootType = LootType.Blessed; + + public BasinOfCrystalClearWater(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075303; // Basin of Crystal-Clear Water + + public override bool Nontransferable => true; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + AddQuestItemProperty(list); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/BedlamTeleporter.cs b/Projects/UOContent/Engines/MLQuests/Items/BedlamTeleporter.cs index ebff833a0..27ede2185 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/BedlamTeleporter.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/BedlamTeleporter.cs @@ -1,55 +1,55 @@ -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.MLQuests.Items -{ - public class BedlamTeleporter : Item - { - private static readonly Point3D PointDest = new Point3D(120, 1682, 0); - private static readonly Map MapDest = Map.Malas; - - public BedlamTeleporter() - : base(0x124D) => - Movable = false; - - public BedlamTeleporter(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1074161; // Access to Bedlam by invitation only - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return; - } - - if (from is PlayerMobile mobile && MLQuestSystem.GetContext(mobile)?.BedlamAccess == true) - { - BaseCreature.TeleportPets(mobile, PointDest, MapDest); - mobile.MoveToWorld(PointDest, MapDest); - } - else - { - from.SendLocalizedMessage(1074276); // You press and push on the iron maiden, but nothing happens. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.MLQuests.Items +{ + public class BedlamTeleporter : Item + { + private static readonly Point3D PointDest = new Point3D(120, 1682, 0); + private static readonly Map MapDest = Map.Malas; + + public BedlamTeleporter() + : base(0x124D) => + Movable = false; + + public BedlamTeleporter(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1074161; // Access to Bedlam by invitation only + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return; + } + + if (from is PlayerMobile mobile && MLQuestSystem.GetContext(mobile)?.BedlamAccess == true) + { + BaseCreature.TeleportPets(mobile, PointDest, MapDest); + mobile.MoveToWorld(PointDest, MapDest); + } + else + { + from.SendLocalizedMessage(1074276); // You press and push on the iron maiden, but nothing happens. + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/Bleach.cs b/Projects/UOContent/Engines/MLQuests/Items/Bleach.cs index 5b71b71b9..ac6607c6e 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/Bleach.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/Bleach.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class Bleach : PigmentsOfTokuno - { - [Constructible] - public Bleach() => LootType = LootType.Blessed; - - public Bleach(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075375; // Bleach - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Bleach : PigmentsOfTokuno + { + [Constructible] + public Bleach() => LootType = LootType.Blessed; + + public Bleach(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075375; // Bleach + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/BridesLetter.cs b/Projects/UOContent/Engines/MLQuests/Items/BridesLetter.cs index 11eae1d1b..83f043636 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/BridesLetter.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/BridesLetter.cs @@ -1,36 +1,36 @@ -namespace Server.Items -{ - public class BridesLetter : Item - { - [Constructible] - public BridesLetter() : base(0x14ED) => LootType = LootType.Blessed; - - public BridesLetter(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075301; // Bride's Letter - - public override bool Nontransferable => true; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - AddQuestItemProperty(list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class BridesLetter : Item + { + [Constructible] + public BridesLetter() : base(0x14ED) => LootType = LootType.Blessed; + + public BridesLetter(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075301; // Bride's Letter + + public override bool Nontransferable => true; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + AddQuestItemProperty(list); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/CompletedTuitionReimbursementForm.cs b/Projects/UOContent/Engines/MLQuests/Items/CompletedTuitionReimbursementForm.cs index 1d6f9b63f..04f706bf7 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/CompletedTuitionReimbursementForm.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/CompletedTuitionReimbursementForm.cs @@ -1,36 +1,36 @@ -namespace Server.Items -{ - public class CompletedTuitionReimbursementForm : Item - { - [Constructible] - public CompletedTuitionReimbursementForm() : base(0x14F0) => LootType = LootType.Blessed; - - public CompletedTuitionReimbursementForm(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074625; // Completed Tuition Reimbursement Form - - public override bool Nontransferable => true; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - AddQuestItemProperty(list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class CompletedTuitionReimbursementForm : Item + { + [Constructible] + public CompletedTuitionReimbursementForm() : base(0x14F0) => LootType = LootType.Blessed; + + public CompletedTuitionReimbursementForm(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074625; // Completed Tuition Reimbursement Form + + public override bool Nontransferable => true; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + AddQuestItemProperty(list); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/CraftmansSatchel.cs b/Projects/UOContent/Engines/MLQuests/Items/CraftmansSatchel.cs index c928daf4e..bb4c81ae0 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/CraftmansSatchel.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/CraftmansSatchel.cs @@ -1,224 +1,224 @@ -using System; -using Server.Engines.Craft; -using Server.Items; - -namespace Server.Engines.MLQuests.Items -{ - public abstract class BaseCraftmansSatchel : Backpack - { - protected static readonly Type[] m_TalismanType = { typeof(RandomTalisman) }; - - public BaseCraftmansSatchel() => Hue = Utility.RandomBrightHue(); - - public BaseCraftmansSatchel(Serial serial) - : base(serial) - { - } - - protected void AddBaseLoot(params Type[][] lootSets) - { - Item loot = Loot.Construct(lootSets.RandomElement()); - - if (loot == null) - return; - - RewardBag.Enhance(loot); - DropItem(loot); - } - - protected void AddRecipe(CraftSystem system) - { - // TODO: change craftable artifact recipes to a rarer drop - int recipeID = system.RandomRecipe(); - - if (recipeID != -1) - DropItem(new RecipeScroll(recipeID)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class TailorSatchel : BaseCraftmansSatchel - { - [Constructible] - public TailorSatchel() - { - AddBaseLoot(Loot.MLArmorTypes, Loot.JewelryTypes, m_TalismanType); - - if (Utility.RandomDouble() < 0.50) - AddRecipe(DefTailoring.CraftSystem); - } - - public TailorSatchel(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BlacksmithSatchel : BaseCraftmansSatchel - { - [Constructible] - public BlacksmithSatchel() - { - AddBaseLoot(Loot.MLWeaponTypes, Loot.JewelryTypes, m_TalismanType); - - if (Utility.RandomDouble() < 0.50) - AddRecipe(DefBlacksmithy.CraftSystem); - } - - public BlacksmithSatchel(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class TinkerSatchel : BaseCraftmansSatchel - { - [Constructible] - public TinkerSatchel() - { - AddBaseLoot(Loot.MLArmorTypes, Loot.MLWeaponTypes, Loot.MLRangedWeaponTypes, Loot.JewelryTypes, m_TalismanType); - - if (Utility.RandomDouble() < 0.50) - switch (Utility.Random(6)) - { - case 0: - AddRecipe(DefInscription.CraftSystem); - break; - case 1: - AddRecipe(DefAlchemy.CraftSystem); - break; - // TODO - // case 2: AddNonArtifactRecipe( DefTailoring.CraftSystem ); break; - // case 3: AddNonArtifactRecipe( DefBlacksmithy.CraftSystem ); break; - // case 4: AddNonArtifactRecipe( DefCarpentry.CraftSystem ); break; - // case 5: AddNonArtifactRecipe( DefBowFletching.CraftSystem ); break; - } - } - - public TinkerSatchel(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class FletchingSatchel : BaseCraftmansSatchel - { - [Constructible] - public FletchingSatchel() - { - AddBaseLoot(Loot.MLRangedWeaponTypes, Loot.JewelryTypes, m_TalismanType); - - if (Utility.RandomDouble() < 0.50) - AddRecipe(DefBowFletching.CraftSystem); - - // TODO: runic fletching kit - } - - public FletchingSatchel(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class CarpentrySatchel : BaseCraftmansSatchel - { - [Constructible] - public CarpentrySatchel() - { - AddBaseLoot(Loot.MLArmorTypes, Loot.MLWeaponTypes, Loot.MLRangedWeaponTypes, Loot.JewelryTypes, m_TalismanType); - - if (Utility.RandomDouble() < 0.50) - AddRecipe(DefCarpentry.CraftSystem); - - // TODO: Add runic dovetail saw - } - - public CarpentrySatchel(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using Server.Engines.Craft; +using Server.Items; + +namespace Server.Engines.MLQuests.Items +{ + public abstract class BaseCraftmansSatchel : Backpack + { + protected static readonly Type[] m_TalismanType = { typeof(RandomTalisman) }; + + public BaseCraftmansSatchel() => Hue = Utility.RandomBrightHue(); + + public BaseCraftmansSatchel(Serial serial) + : base(serial) + { + } + + protected void AddBaseLoot(params Type[][] lootSets) + { + var loot = Loot.Construct(lootSets.RandomElement()); + + if (loot == null) + return; + + RewardBag.Enhance(loot); + DropItem(loot); + } + + protected void AddRecipe(CraftSystem system) + { + // TODO: change craftable artifact recipes to a rarer drop + var recipeID = system.RandomRecipe(); + + if (recipeID != -1) + DropItem(new RecipeScroll(recipeID)); + } + + 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 class TailorSatchel : BaseCraftmansSatchel + { + [Constructible] + public TailorSatchel() + { + AddBaseLoot(Loot.MLArmorTypes, Loot.JewelryTypes, m_TalismanType); + + if (Utility.RandomDouble() < 0.50) + AddRecipe(DefTailoring.CraftSystem); + } + + public TailorSatchel(Serial serial) + : base(serial) + { + } + + 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 class BlacksmithSatchel : BaseCraftmansSatchel + { + [Constructible] + public BlacksmithSatchel() + { + AddBaseLoot(Loot.MLWeaponTypes, Loot.JewelryTypes, m_TalismanType); + + if (Utility.RandomDouble() < 0.50) + AddRecipe(DefBlacksmithy.CraftSystem); + } + + public BlacksmithSatchel(Serial serial) + : base(serial) + { + } + + 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 class TinkerSatchel : BaseCraftmansSatchel + { + [Constructible] + public TinkerSatchel() + { + AddBaseLoot(Loot.MLArmorTypes, Loot.MLWeaponTypes, Loot.MLRangedWeaponTypes, Loot.JewelryTypes, m_TalismanType); + + if (Utility.RandomDouble() < 0.50) + switch (Utility.Random(6)) + { + case 0: + AddRecipe(DefInscription.CraftSystem); + break; + case 1: + AddRecipe(DefAlchemy.CraftSystem); + break; + // TODO + // case 2: AddNonArtifactRecipe( DefTailoring.CraftSystem ); break; + // case 3: AddNonArtifactRecipe( DefBlacksmithy.CraftSystem ); break; + // case 4: AddNonArtifactRecipe( DefCarpentry.CraftSystem ); break; + // case 5: AddNonArtifactRecipe( DefBowFletching.CraftSystem ); break; + } + } + + public TinkerSatchel(Serial serial) + : base(serial) + { + } + + 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 class FletchingSatchel : BaseCraftmansSatchel + { + [Constructible] + public FletchingSatchel() + { + AddBaseLoot(Loot.MLRangedWeaponTypes, Loot.JewelryTypes, m_TalismanType); + + if (Utility.RandomDouble() < 0.50) + AddRecipe(DefBowFletching.CraftSystem); + + // TODO: runic fletching kit + } + + public FletchingSatchel(Serial serial) + : base(serial) + { + } + + 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 class CarpentrySatchel : BaseCraftmansSatchel + { + [Constructible] + public CarpentrySatchel() + { + AddBaseLoot(Loot.MLArmorTypes, Loot.MLWeaponTypes, Loot.MLRangedWeaponTypes, Loot.JewelryTypes, m_TalismanType); + + if (Utility.RandomDouble() < 0.50) + AddRecipe(DefCarpentry.CraftSystem); + + // TODO: Add runic dovetail saw + } + + public CarpentrySatchel(Serial serial) + : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/CrateForSledge.cs b/Projects/UOContent/Engines/MLQuests/Items/CrateForSledge.cs index bef9ccea4..033da30ef 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/CrateForSledge.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/CrateForSledge.cs @@ -1,38 +1,38 @@ -using System; - -namespace Server.Items -{ - public class CrateForSledge : TransientItem - { - [Constructible] - public CrateForSledge() : base(0x1FFF, TimeSpan.FromHours(1)) => LootType = LootType.Blessed; - - public CrateForSledge(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074520; // Crate for Sledge - - public override bool Nontransferable => true; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - AddQuestItemProperty(list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class CrateForSledge : TransientItem + { + [Constructible] + public CrateForSledge() : base(0x1FFF, TimeSpan.FromHours(1)) => LootType = LootType.Blessed; + + public CrateForSledge(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074520; // Crate for Sledge + + public override bool Nontransferable => true; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + AddQuestItemProperty(list); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/DreadSpiderSilk.cs b/Projects/UOContent/Engines/MLQuests/Items/DreadSpiderSilk.cs index 847a14158..8583a7ce3 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/DreadSpiderSilk.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/DreadSpiderSilk.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class DreadSpiderSilk : Item - { - [Constructible] - public DreadSpiderSilk() : base(0xDF8) - { - LootType = LootType.Blessed; - Hue = 0x481; - } - - public DreadSpiderSilk(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075319; // Dread Spider Silk - - public override bool Nontransferable => true; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - AddQuestItemProperty(list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class DreadSpiderSilk : Item + { + [Constructible] + public DreadSpiderSilk() : base(0xDF8) + { + LootType = LootType.Blessed; + Hue = 0x481; + } + + public DreadSpiderSilk(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075319; // Dread Spider Silk + + public override bool Nontransferable => true; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + AddQuestItemProperty(list); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/FragmentOfAMap.cs b/Projects/UOContent/Engines/MLQuests/Items/FragmentOfAMap.cs index 6567e4172..663abf385 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/FragmentOfAMap.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/FragmentOfAMap.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class FragmentOfAMap : Item - { - [Constructible] - public FragmentOfAMap() : base(0x14ED) => LootType = LootType.Blessed; - - public FragmentOfAMap(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074533; // Fragment of a Map - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FragmentOfAMap : Item + { + [Constructible] + public FragmentOfAMap() : base(0x14ED) => LootType = LootType.Blessed; + + public FragmentOfAMap(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074533; // Fragment of a Map + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/FragmentOfAMapDelivery.cs b/Projects/UOContent/Engines/MLQuests/Items/FragmentOfAMapDelivery.cs index 2374526f0..18b52b92f 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/FragmentOfAMapDelivery.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/FragmentOfAMapDelivery.cs @@ -1,36 +1,36 @@ -namespace Server.Items -{ - public class FragmentOfAMapDelivery : Item - { - [Constructible] - public FragmentOfAMapDelivery() : base(0x14ED) => LootType = LootType.Blessed; - - public FragmentOfAMapDelivery(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074533; // Fragment of a Map - - public override bool Nontransferable => true; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - AddQuestItemProperty(list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FragmentOfAMapDelivery : Item + { + [Constructible] + public FragmentOfAMapDelivery() : base(0x14ED) => LootType = LootType.Blessed; + + public FragmentOfAMapDelivery(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074533; // Fragment of a Map + + public override bool Nontransferable => true; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + AddQuestItemProperty(list); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/FriendOfTheLibraryToken.cs b/Projects/UOContent/Engines/MLQuests/Items/FriendOfTheLibraryToken.cs index b6d8bfe16..0df3fa944 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/FriendOfTheLibraryToken.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/FriendOfTheLibraryToken.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class FriendOfTheLibraryToken : Item - { - [Constructible] - public FriendOfTheLibraryToken() : base(0x2F58) - { - Layer = Layer.Talisman; - Hue = 0x28A; - } - - public FriendOfTheLibraryToken(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073136; // Friend of the Library Token (allows donations to be made) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FriendOfTheLibraryToken : Item + { + [Constructible] + public FriendOfTheLibraryToken() : base(0x2F58) + { + Layer = Layer.Talisman; + Hue = 0x28A; + } + + public FriendOfTheLibraryToken(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073136; // Friend of the Library Token (allows donations to be made) + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/FriendsOfTheLibraryApplication.cs b/Projects/UOContent/Engines/MLQuests/Items/FriendsOfTheLibraryApplication.cs index dc08e2b6f..8bde0ff1f 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/FriendsOfTheLibraryApplication.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/FriendsOfTheLibraryApplication.cs @@ -1,36 +1,36 @@ -namespace Server.Items -{ - public class FriendsOfTheLibraryApplication : Item - { - [Constructible] - public FriendsOfTheLibraryApplication() : base(0xEC0) => LootType = LootType.Blessed; - - public FriendsOfTheLibraryApplication(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073131; // Friends of the Library Application - - public override bool Nontransferable => true; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - AddQuestItemProperty(list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FriendsOfTheLibraryApplication : Item + { + [Constructible] + public FriendsOfTheLibraryApplication() : base(0xEC0) => LootType = LootType.Blessed; + + public FriendsOfTheLibraryApplication(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073131; // Friends of the Library Application + + public override bool Nontransferable => true; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + AddQuestItemProperty(list); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/GamanHorns.cs b/Projects/UOContent/Engines/MLQuests/Items/GamanHorns.cs index fbe389442..fa9736dfb 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/GamanHorns.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/GamanHorns.cs @@ -1,34 +1,34 @@ -namespace Server.Items -{ - public class GamanHorns : Item - { - [Constructible] - public GamanHorns(int amount = 1) : base(0x1084) - { - LootType = LootType.Blessed; - Stackable = true; - Amount = amount; - Hue = 0x395; - } - - public GamanHorns(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074557; // Gaman Horns - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class GamanHorns : Item + { + [Constructible] + public GamanHorns(int amount = 1) : base(0x1084) + { + LootType = LootType.Blessed; + Stackable = true; + Amount = amount; + Hue = 0x395; + } + + public GamanHorns(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074557; // Gaman Horns + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/GervisSatchel.cs b/Projects/UOContent/Engines/MLQuests/Items/GervisSatchel.cs index cb38c504a..b0c6feb31 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/GervisSatchel.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/GervisSatchel.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class GervisSatchel : Backpack - { - [Constructible] - public GervisSatchel() - { - Hue = Utility.RandomBrightHue(); - DropItem(new IronIngot(10)); - DropItem(new SmithHammer()); - } - - public GervisSatchel(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class GervisSatchel : Backpack + { + [Constructible] + public GervisSatchel() + { + Hue = Utility.RandomBrightHue(); + DropItem(new IronIngot(10)); + DropItem(new SmithHammer()); + } + + public GervisSatchel(Serial serial) + : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/GiftForArielle.cs b/Projects/UOContent/Engines/MLQuests/Items/GiftForArielle.cs index 12589ae87..a3fe7a704 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/GiftForArielle.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/GiftForArielle.cs @@ -1,37 +1,37 @@ -namespace Server.Items -{ - public class GiftForArielle : BaseContainer - { - [Constructible] - public GiftForArielle() : base(0x1882) => Hue = 0x2C4; - - public GiftForArielle(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074356; // gift for arielle - public override int DefaultGumpID => 0x41; - - public override bool Nontransferable => true; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - AddQuestItemProperty(list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class GiftForArielle : BaseContainer + { + [Constructible] + public GiftForArielle() : base(0x1882) => Hue = 0x2C4; + + public GiftForArielle(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074356; // gift for arielle + public override int DefaultGumpID => 0x41; + + public override bool Nontransferable => true; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + AddQuestItemProperty(list); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/HargroveSatchel.cs b/Projects/UOContent/Engines/MLQuests/Items/HargroveSatchel.cs index 43302f085..7c8716a48 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/HargroveSatchel.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/HargroveSatchel.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class HargroveSatchel : Backpack - { - [Constructible] - public HargroveSatchel() - { - Hue = Utility.RandomBrightHue(); - DropItem(new Gold(15)); - DropItem(new Hatchet()); - } - - public HargroveSatchel(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class HargroveSatchel : Backpack + { + [Constructible] + public HargroveSatchel() + { + Hue = Utility.RandomBrightHue(); + DropItem(new Gold(15)); + DropItem(new Hatchet()); + } + + public HargroveSatchel(Serial serial) + : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/KirinBrains.cs b/Projects/UOContent/Engines/MLQuests/Items/KirinBrains.cs index 614670608..f34dd3e20 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/KirinBrains.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/KirinBrains.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class KirinBrains : Item - { - [Constructible] - public KirinBrains() : base(0x1CF0) - { - LootType = LootType.Blessed; - Hue = 0xD7; - } - - public KirinBrains(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074612; // Ki-Rin Brains - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class KirinBrains : Item + { + [Constructible] + public KirinBrains() : base(0x1CF0) + { + LootType = LootType.Blessed; + Hue = 0xD7; + } + + public KirinBrains(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074612; // Ki-Rin Brains + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/LowelSatchel.cs b/Projects/UOContent/Engines/MLQuests/Items/LowelSatchel.cs index 064f041aa..92848b8a3 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/LowelSatchel.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/LowelSatchel.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class LowelSatchel : Backpack - { - [Constructible] - public LowelSatchel() - { - Hue = Utility.RandomBrightHue(); - DropItem(new Board(10)); - DropItem(new DovetailSaw()); - } - - public LowelSatchel(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LowelSatchel : Backpack + { + [Constructible] + public LowelSatchel() + { + Hue = Utility.RandomBrightHue(); + DropItem(new Board(10)); + DropItem(new DovetailSaw()); + } + + public LowelSatchel(Serial serial) + : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/MiniatureMushroom.cs b/Projects/UOContent/Engines/MLQuests/Items/MiniatureMushroom.cs index 49c164a0a..9e4baced0 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/MiniatureMushroom.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/MiniatureMushroom.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class MiniatureMushroom : Food - { - [Constructible] - public MiniatureMushroom() : base(0xD16) => LootType = LootType.Blessed; - - public MiniatureMushroom(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073138; // Miniature mushroom - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class MiniatureMushroom : Food + { + [Constructible] + public MiniatureMushroom() : base(0xD16) => LootType = LootType.Blessed; + + public MiniatureMushroom(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073138; // Miniature mushroom + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/MirrorOfPurification.cs b/Projects/UOContent/Engines/MLQuests/Items/MirrorOfPurification.cs index f49338329..6c1255e0f 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/MirrorOfPurification.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/MirrorOfPurification.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class MirrorOfPurification : Item - { - [Constructible] - public MirrorOfPurification() : base(0x1008) - { - LootType = LootType.Blessed; - Hue = 0x530; - } - - public MirrorOfPurification(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075304; // Mirror of Purification - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class MirrorOfPurification : Item + { + [Constructible] + public MirrorOfPurification() : base(0x1008) + { + LootType = LootType.Blessed; + Hue = 0x530; + } + + public MirrorOfPurification(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075304; // Mirror of Purification + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/MuggSatchel.cs b/Projects/UOContent/Engines/MLQuests/Items/MuggSatchel.cs index f08f008cd..478e719b5 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/MuggSatchel.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/MuggSatchel.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class MuggSatchel : Backpack - { - [Constructible] - public MuggSatchel() - { - Hue = Utility.RandomBrightHue(); - DropItem(new Pickaxe()); - DropItem(new Pickaxe()); - } - - public MuggSatchel(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class MuggSatchel : Backpack + { + [Constructible] + public MuggSatchel() + { + Hue = Utility.RandomBrightHue(); + DropItem(new Pickaxe()); + DropItem(new Pickaxe()); + } + + public MuggSatchel(Serial serial) + : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/NibbetSatchel.cs b/Projects/UOContent/Engines/MLQuests/Items/NibbetSatchel.cs index f035a96b9..a6d8275d4 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/NibbetSatchel.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/NibbetSatchel.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - public class NibbetSatchel : Backpack - { - [Constructible] - public NibbetSatchel() - { - Hue = Utility.RandomBrightHue(); - DropItem(new TinkerTools()); - - DropItem( - Utility.Random(10) switch - { - 0 => new Springs(3), - 1 => new Axle(3), - 2 => new Hinge(3), - 3 => new Key(), - 4 => new Scissors(), - 5 => new BarrelTap(3), - 6 => new BarrelHoops(), - 7 => new Gears(3), - 8 => new Lockpick(3), - _ => new ClockFrame(3) // 9 - } - ); - } - - public NibbetSatchel(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class NibbetSatchel : Backpack + { + [Constructible] + public NibbetSatchel() + { + Hue = Utility.RandomBrightHue(); + DropItem(new TinkerTools()); + + DropItem( + Utility.Random(10) switch + { + 0 => new Springs(3), + 1 => new Axle(3), + 2 => new Hinge(3), + 3 => new Key(), + 4 => new Scissors(), + 5 => new BarrelTap(3), + 6 => new BarrelHoops(), + 7 => new Gears(3), + 8 => new Lockpick(3), + _ => new ClockFrame(3) // 9 + } + ); + } + + public NibbetSatchel(Serial serial) + : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/NotarizedApplication.cs b/Projects/UOContent/Engines/MLQuests/Items/NotarizedApplication.cs index 59da4e667..06d7d5b6e 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/NotarizedApplication.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/NotarizedApplication.cs @@ -1,36 +1,36 @@ -namespace Server.Items -{ - public class NotarizedApplication : Item - { - [Constructible] - public NotarizedApplication() : base(0x14EF) => LootType = LootType.Blessed; - - public NotarizedApplication(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073135; // Notarized Application - - public override bool Nontransferable => true; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - AddQuestItemProperty(list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class NotarizedApplication : Item + { + [Constructible] + public NotarizedApplication() : base(0x14EF) => LootType = LootType.Blessed; + + public NotarizedApplication(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073135; // Notarized Application + + public override bool Nontransferable => true; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + AddQuestItemProperty(list); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/OfficialSealingWax.cs b/Projects/UOContent/Engines/MLQuests/Items/OfficialSealingWax.cs index 9f701c268..e540a50d5 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/OfficialSealingWax.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/OfficialSealingWax.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class OfficialSealingWax : Item - { - [Constructible] - public OfficialSealingWax() : base(0x1426) - { - LootType = LootType.Blessed; - Hue = 0x84; - } - - public OfficialSealingWax(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072744; // Official Sealing Wax - - public override bool Nontransferable => true; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - AddQuestItemProperty(list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class OfficialSealingWax : Item + { + [Constructible] + public OfficialSealingWax() : base(0x1426) + { + LootType = LootType.Blessed; + Hue = 0x84; + } + + public OfficialSealingWax(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072744; // Official Sealing Wax + + public override bool Nontransferable => true; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + AddQuestItemProperty(list); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/PeppercornFishsteak.cs b/Projects/UOContent/Engines/MLQuests/Items/PeppercornFishsteak.cs index 0ecc21223..6aa74dd23 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/PeppercornFishsteak.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/PeppercornFishsteak.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class PeppercornFishsteak : FishSteak - { - [Constructible] - public PeppercornFishsteak() => Hue = 0x222; - - public PeppercornFishsteak(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075557; // peppercorn fishsteak - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PeppercornFishsteak : FishSteak + { + [Constructible] + public PeppercornFishsteak() => Hue = 0x222; + + public PeppercornFishsteak(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075557; // peppercorn fishsteak + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/PixieLeg.cs b/Projects/UOContent/Engines/MLQuests/Items/PixieLeg.cs index 9843740c4..eb141f398 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/PixieLeg.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/PixieLeg.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class PixieLeg : ChickenLeg - { - [Constructible] - public PixieLeg(int amount = 1) : base(amount) - { - LootType = LootType.Blessed; - Hue = 0x1C2; - } - - public PixieLeg(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074613; // Pixie Leg - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class PixieLeg : ChickenLeg + { + [Constructible] + public PixieLeg(int amount = 1) : base(amount) + { + LootType = LootType.Blessed; + Hue = 0x1C2; + } + + public PixieLeg(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074613; // Pixie Leg + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/PortraitOfTheBride.cs b/Projects/UOContent/Engines/MLQuests/Items/PortraitOfTheBride.cs index ffaf7d524..9f2ca6e75 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/PortraitOfTheBride.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/PortraitOfTheBride.cs @@ -1,36 +1,36 @@ -namespace Server.Items -{ - public class PortraitOfTheBride : Item - { - [Constructible] - public PortraitOfTheBride() : base(0xE9F) => LootType = LootType.Blessed; - - public PortraitOfTheBride(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075300; // Portrait of the Bride - - public override bool Nontransferable => true; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - AddQuestItemProperty(list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PortraitOfTheBride : Item + { + [Constructible] + public PortraitOfTheBride() : base(0xE9F) => LootType = LootType.Blessed; + + public PortraitOfTheBride(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075300; // Portrait of the Bride + + public override bool Nontransferable => true; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + AddQuestItemProperty(list); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/PrismaticAmber.cs b/Projects/UOContent/Engines/MLQuests/Items/PrismaticAmber.cs index 83cab4924..e4e2fc468 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/PrismaticAmber.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/PrismaticAmber.cs @@ -1,73 +1,73 @@ -namespace Server.Items -{ - public class PrismaticAmber : Amber - { - [Constructible] - public PrismaticAmber() - { - } - - public PrismaticAmber(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075299; // Prismatic Amber - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - list.Add(1075269); // Destroyed when dropped - } - - public override bool DropToWorld(Mobile from, Point3D p) - { - bool ret = base.DropToWorld(from, p); - - if (ret) - DestroyItem(from); - - return ret; - } - - public override bool DropToMobile(Mobile from, Mobile target, Point3D p) - { - bool ret = base.DropToMobile(from, target, p); - - if (ret) - DestroyItem(from); - - return ret; - } - - public override bool DropToItem(Mobile from, Item target, Point3D p) - { - bool ret = base.DropToItem(from, target, p); - - if (ret && Parent != from.Backpack) - DestroyItem(from); - - return ret; - } - - public virtual void DestroyItem(Mobile from) - { - from.SendLocalizedMessage(500424); // You destroyed the item. - Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PrismaticAmber : Amber + { + [Constructible] + public PrismaticAmber() + { + } + + public PrismaticAmber(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075299; // Prismatic Amber + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + list.Add(1075269); // Destroyed when dropped + } + + public override bool DropToWorld(Mobile from, Point3D p) + { + var ret = base.DropToWorld(from, p); + + if (ret) + DestroyItem(from); + + return ret; + } + + public override bool DropToMobile(Mobile from, Mobile target, Point3D p) + { + var ret = base.DropToMobile(from, target, p); + + if (ret) + DestroyItem(from); + + return ret; + } + + public override bool DropToItem(Mobile from, Item target, Point3D p) + { + var ret = base.DropToItem(from, target, p); + + if (ret && Parent != from.Backpack) + DestroyItem(from); + + return ret; + } + + public virtual void DestroyItem(Mobile from) + { + from.SendLocalizedMessage(500424); // You destroyed the item. + Delete(); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/PrismaticCrystal.cs b/Projects/UOContent/Engines/MLQuests/Items/PrismaticCrystal.cs index d837066ca..f23750f98 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/PrismaticCrystal.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/PrismaticCrystal.cs @@ -1,71 +1,71 @@ -using Server.Engines.MLQuests; -using Server.Engines.MLQuests.Definitions; -using Server.Mobiles; -using Server.Network; - -namespace Server.Items -{ - public class PrismaticCrystal : Item - { - [Constructible] - public PrismaticCrystal() : base(0x2DA) - { - Movable = false; - Hue = 0x32; - } - - public PrismaticCrystal(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074269; // prismatic crystal - - public override void OnDoubleClick(Mobile from) - { - if (!(from is PlayerMobile pm) || pm.Backpack == null) - return; - - if (pm.InRange(GetWorldLocation(), 2)) - { - if (MLQuestSystem.GetContext(pm)?.IsDoingQuest(typeof(UnfadingMemoriesPartOne)) == true && - pm.Backpack.FindItemByType(false) == null) - { - Item amber = new PrismaticAmber(); - - if (pm.PlaceInBackpack(amber)) - { - MLQuestSystem.MarkQuestItem(pm, amber); - Delete(); - } - else - { - pm.SendLocalizedMessage(502385); // Your pack cannot hold this item. - amber.Delete(); - } - } - else - { - pm.SendLocalizedMessage(1075464); // You already have as many of those as you need. - } - } - else - { - pm.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Engines.MLQuests; +using Server.Engines.MLQuests.Definitions; +using Server.Mobiles; +using Server.Network; + +namespace Server.Items +{ + public class PrismaticCrystal : Item + { + [Constructible] + public PrismaticCrystal() : base(0x2DA) + { + Movable = false; + Hue = 0x32; + } + + public PrismaticCrystal(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074269; // prismatic crystal + + public override void OnDoubleClick(Mobile from) + { + if (!(from is PlayerMobile pm) || pm.Backpack == null) + return; + + if (pm.InRange(GetWorldLocation(), 2)) + { + if (MLQuestSystem.GetContext(pm)?.IsDoingQuest(typeof(UnfadingMemoriesPartOne)) == true && + pm.Backpack.FindItemByType(false) == null) + { + Item amber = new PrismaticAmber(); + + if (pm.PlaceInBackpack(amber)) + { + MLQuestSystem.MarkQuestItem(pm, amber); + Delete(); + } + else + { + pm.SendLocalizedMessage(502385); // Your pack cannot hold this item. + amber.Delete(); + } + } + else + { + pm.SendLocalizedMessage(1075464); // You already have as many of those as you need. + } + } + else + { + pm.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/QuestGiverItem.cs b/Projects/UOContent/Engines/MLQuests/Items/QuestGiverItem.cs index e48f8c5ae..2b0bc9bd0 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/QuestGiverItem.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/QuestGiverItem.cs @@ -1,140 +1,140 @@ -using System; -using System.Collections.Generic; -using Server.Items; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.MLQuests.Items -{ - public abstract class QuestGiverItem : Item, IQuestGiver - { - private List m_MLQuests; - - public QuestGiverItem(int itemId) - : base(itemId) - { - } - - public QuestGiverItem(Serial serial) - : base(serial) - { - } - - public bool CanGiveMLQuest => MLQuests.Count != 0; - - public override bool Nontransferable => true; - - public List MLQuests => m_MLQuests ?? - (m_MLQuests = MLQuestSystem.FindQuestList(GetType()) ?? MLQuestSystem.EmptyList); - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - AddQuestItemProperty(list); - - if (CanGiveMLQuest) - list.Add(1072269); // Quest Giver - } - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 2)) - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - else if (!IsChildOf(from.Backpack)) - from.SendLocalizedMessage(1042593); // That is not in your backpack. - else if (MLQuestSystem.Enabled && CanGiveMLQuest && from is PlayerMobile mobile) - MLQuestSystem.OnDoubleClick(this, mobile); - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - if (MLQuestSystem.Enabled) - MLQuestSystem.HandleDeletion(this); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public abstract class TransientQuestGiverItem : TransientItem, IQuestGiver - { - private List m_MLQuests; - - public TransientQuestGiverItem(int itemId, TimeSpan lifeSpan) - : base(itemId, lifeSpan) - { - } - - public TransientQuestGiverItem(Serial serial) - : base(serial) - { - } - - public bool CanGiveMLQuest => MLQuests.Count != 0; - - public override bool Nontransferable => true; - - public List MLQuests => m_MLQuests ?? - (m_MLQuests = MLQuestSystem.FindQuestList(GetType()) ?? MLQuestSystem.EmptyList); - - public override void HandleInvalidTransfer(Mobile from) - { - } - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - AddQuestItemProperty(list); - - if (CanGiveMLQuest) - list.Add(1072269); // Quest Giver - } - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 2)) - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - else if (!IsChildOf(from.Backpack)) - from.SendLocalizedMessage(1042593); // That is not in your backpack. - else if (MLQuestSystem.Enabled && CanGiveMLQuest && from is PlayerMobile mobile) - MLQuestSystem.OnDoubleClick(this, mobile); - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - if (MLQuestSystem.Enabled) - MLQuestSystem.HandleDeletion(this); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using System.Collections.Generic; +using Server.Items; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.MLQuests.Items +{ + public abstract class QuestGiverItem : Item, IQuestGiver + { + private List m_MLQuests; + + public QuestGiverItem(int itemId) + : base(itemId) + { + } + + public QuestGiverItem(Serial serial) + : base(serial) + { + } + + public bool CanGiveMLQuest => MLQuests.Count != 0; + + public override bool Nontransferable => true; + + public List MLQuests => m_MLQuests ?? + (m_MLQuests = MLQuestSystem.FindQuestList(GetType()) ?? MLQuestSystem.EmptyList); + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + AddQuestItemProperty(list); + + if (CanGiveMLQuest) + list.Add(1072269); // Quest Giver + } + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 2)) + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + else if (!IsChildOf(from.Backpack)) + from.SendLocalizedMessage(1042593); // That is not in your backpack. + else if (MLQuestSystem.Enabled && CanGiveMLQuest && from is PlayerMobile mobile) + MLQuestSystem.OnDoubleClick(this, mobile); + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + if (MLQuestSystem.Enabled) + MLQuestSystem.HandleDeletion(this); + } + + 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 abstract class TransientQuestGiverItem : TransientItem, IQuestGiver + { + private List m_MLQuests; + + public TransientQuestGiverItem(int itemId, TimeSpan lifeSpan) + : base(itemId, lifeSpan) + { + } + + public TransientQuestGiverItem(Serial serial) + : base(serial) + { + } + + public bool CanGiveMLQuest => MLQuests.Count != 0; + + public override bool Nontransferable => true; + + public List MLQuests => m_MLQuests ?? + (m_MLQuests = MLQuestSystem.FindQuestList(GetType()) ?? MLQuestSystem.EmptyList); + + public override void HandleInvalidTransfer(Mobile from) + { + } + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + AddQuestItemProperty(list); + + if (CanGiveMLQuest) + list.Add(1072269); // Quest Giver + } + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 2)) + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + else if (!IsChildOf(from.Backpack)) + from.SendLocalizedMessage(1042593); // That is not in your backpack. + else if (MLQuestSystem.Enabled && CanGiveMLQuest && from is PlayerMobile mobile) + MLQuestSystem.OnDoubleClick(this, mobile); + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + if (MLQuestSystem.Enabled) + MLQuestSystem.HandleDeletion(this); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/RedLeatherBook.cs b/Projects/UOContent/Engines/MLQuests/Items/RedLeatherBook.cs index f207808a3..f4f229e4b 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/RedLeatherBook.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/RedLeatherBook.cs @@ -1,27 +1,27 @@ -namespace Server.Items -{ - public class RedLeatherBook : BlueBook - { - [Constructible] - public RedLeatherBook() => Hue = 0x485; - - public RedLeatherBook(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class RedLeatherBook : BlueBook + { + [Constructible] + public RedLeatherBook() => Hue = 0x485; + + public RedLeatherBook(Serial serial) + : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/ReginasLetter.cs b/Projects/UOContent/Engines/MLQuests/Items/ReginasLetter.cs index a8ac0e115..aaf62201b 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/ReginasLetter.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/ReginasLetter.cs @@ -1,36 +1,36 @@ -namespace Server.Items -{ - public class ReginasLetter : Item - { - [Constructible] - public ReginasLetter() : base(0x14ED) => LootType = LootType.Blessed; - - public ReginasLetter(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075306; // Regina's Letter - - public override bool Nontransferable => true; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - AddQuestItemProperty(list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ReginasLetter : Item + { + [Constructible] + public ReginasLetter() : base(0x14ED) => LootType = LootType.Blessed; + + public ReginasLetter(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075306; // Regina's Letter + + public override bool Nontransferable => true; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + AddQuestItemProperty(list); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/ReginasRing.cs b/Projects/UOContent/Engines/MLQuests/Items/ReginasRing.cs index cd30c00c1..d7a40fb3c 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/ReginasRing.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/ReginasRing.cs @@ -1,36 +1,36 @@ -namespace Server.Items -{ - public class ReginasRing : SilverRing - { - [Constructible] - public ReginasRing() => LootType = LootType.Blessed; - - public ReginasRing(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075305; // Regina's Ring - - public override bool Nontransferable => true; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - AddQuestItemProperty(list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ReginasRing : SilverRing + { + [Constructible] + public ReginasRing() => LootType = LootType.Blessed; + + public ReginasRing(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075305; // Regina's Ring + + public override bool Nontransferable => true; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + AddQuestItemProperty(list); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/RewardBags.cs b/Projects/UOContent/Engines/MLQuests/Items/RewardBags.cs index dec7ed682..c1cff5005 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/RewardBags.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/RewardBags.cs @@ -1,191 +1,191 @@ -using Server.Items; - -namespace Server.Engines.MLQuests.Items -{ - public static class RewardBag - { - public static void Fill(Container c, int itemCount, double talismanChance) - { - c.Hue = Utility.RandomNondyedHue(); - - int done = 0; - - if (Utility.RandomDouble() < talismanChance) - { - c.DropItem(new RandomTalisman()); - ++done; - } - - for (; done < itemCount; ++done) - { - var loot = Utility.Random(5) switch - { - 0 => (Item)Loot.RandomWeapon(false, true), - 1 => Loot.RandomArmor(false, true), - 2 => Loot.RandomRangedWeapon(false, true), - 3 => Loot.RandomJewelry(), - _ => Loot.RandomHat(false) // 4 - }; - - if (loot == null) - continue; - - Enhance(loot); - c.DropItem(loot); - } - } - - public static void Enhance(Item loot) - { - if (loot is BaseWeapon weapon) - { - BaseRunicTool.ApplyAttributesTo(weapon, Utility.RandomMinMax(1, 5), 10, 80); - return; - } - - if (loot is BaseArmor armor) BaseRunicTool.ApplyAttributesTo(armor, Utility.RandomMinMax(1, 5), 10, 80); - - if (loot is BaseJewel jewel) BaseRunicTool.ApplyAttributesTo(jewel, Utility.RandomMinMax(1, 5), 10, 80); - } - } - - public class SmallBagOfTrinkets : Bag - { - [Constructible] - public SmallBagOfTrinkets() - { - RewardBag.Fill(this, 1, 0.0); - } - - public SmallBagOfTrinkets(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BagOfTrinkets : Bag - { - [Constructible] - public BagOfTrinkets() - { - RewardBag.Fill(this, 2, 0.05); - } - - public BagOfTrinkets(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BagOfTreasure : Bag - { - [Constructible] - public BagOfTreasure() - { - RewardBag.Fill(this, 3, 0.20); - } - - public BagOfTreasure(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LargeBagOfTreasure : Bag - { - [Constructible] - public LargeBagOfTreasure() - { - RewardBag.Fill(this, 4, 0.50); - } - - public LargeBagOfTreasure(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class RewardStrongbox : WoodenBox - { - [Constructible] - public RewardStrongbox() - { - RewardBag.Fill(this, 5, 1.0); - } - - public RewardStrongbox(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using Server.Items; + +namespace Server.Engines.MLQuests.Items +{ + public static class RewardBag + { + public static void Fill(Container c, int itemCount, double talismanChance) + { + c.Hue = Utility.RandomNondyedHue(); + + var done = 0; + + if (Utility.RandomDouble() < talismanChance) + { + c.DropItem(new RandomTalisman()); + ++done; + } + + for (; done < itemCount; ++done) + { + var loot = Utility.Random(5) switch + { + 0 => (Item)Loot.RandomWeapon(false, true), + 1 => Loot.RandomArmor(false, true), + 2 => Loot.RandomRangedWeapon(false, true), + 3 => Loot.RandomJewelry(), + _ => Loot.RandomHat(false) // 4 + }; + + if (loot == null) + continue; + + Enhance(loot); + c.DropItem(loot); + } + } + + public static void Enhance(Item loot) + { + if (loot is BaseWeapon weapon) + { + BaseRunicTool.ApplyAttributesTo(weapon, Utility.RandomMinMax(1, 5), 10, 80); + return; + } + + if (loot is BaseArmor armor) BaseRunicTool.ApplyAttributesTo(armor, Utility.RandomMinMax(1, 5), 10, 80); + + if (loot is BaseJewel jewel) BaseRunicTool.ApplyAttributesTo(jewel, Utility.RandomMinMax(1, 5), 10, 80); + } + } + + public class SmallBagOfTrinkets : Bag + { + [Constructible] + public SmallBagOfTrinkets() + { + RewardBag.Fill(this, 1, 0.0); + } + + public SmallBagOfTrinkets(Serial serial) + : base(serial) + { + } + + 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 class BagOfTrinkets : Bag + { + [Constructible] + public BagOfTrinkets() + { + RewardBag.Fill(this, 2, 0.05); + } + + public BagOfTrinkets(Serial serial) + : base(serial) + { + } + + 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 class BagOfTreasure : Bag + { + [Constructible] + public BagOfTreasure() + { + RewardBag.Fill(this, 3, 0.20); + } + + public BagOfTreasure(Serial serial) + : base(serial) + { + } + + 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 class LargeBagOfTreasure : Bag + { + [Constructible] + public LargeBagOfTreasure() + { + RewardBag.Fill(this, 4, 0.50); + } + + public LargeBagOfTreasure(Serial serial) + : base(serial) + { + } + + 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 class RewardStrongbox : WoodenBox + { + [Constructible] + public RewardStrongbox() + { + RewardBag.Fill(this, 5, 1.0); + } + + public RewardStrongbox(Serial serial) + : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/SadrahSatchel.cs b/Projects/UOContent/Engines/MLQuests/Items/SadrahSatchel.cs index d4d0e72ea..9f44999bf 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/SadrahSatchel.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/SadrahSatchel.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class SadrahSatchel : Backpack - { - [Constructible] - public SadrahSatchel() - { - Hue = Utility.RandomBrightHue(); - DropItem(new Bloodmoss(10)); - DropItem(new MortarPestle()); - } - - public SadrahSatchel(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SadrahSatchel : Backpack + { + [Constructible] + public SadrahSatchel() + { + Hue = Utility.RandomBrightHue(); + DropItem(new Bloodmoss(10)); + DropItem(new MortarPestle()); + } + + public SadrahSatchel(Serial serial) + : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/SapOfSosaria.cs b/Projects/UOContent/Engines/MLQuests/Items/SapOfSosaria.cs index 4b328e590..de82f9d30 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/SapOfSosaria.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/SapOfSosaria.cs @@ -1,33 +1,33 @@ -namespace Server.Items -{ - public class SapOfSosaria : Item - { - [Constructible] - public SapOfSosaria(int amount = 1) : base(0x1848) - { - LootType = LootType.Blessed; - Stackable = true; - Amount = amount; - } - - public SapOfSosaria(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074178; // Sap of Sosaria - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class SapOfSosaria : Item + { + [Constructible] + public SapOfSosaria(int amount = 1) : base(0x1848) + { + LootType = LootType.Blessed; + Stackable = true; + Amount = amount; + } + + public SapOfSosaria(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074178; // Sap of Sosaria + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/SealedNotesForJamal.cs b/Projects/UOContent/Engines/MLQuests/Items/SealedNotesForJamal.cs index 5ef8d730c..6cdf61405 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/SealedNotesForJamal.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/SealedNotesForJamal.cs @@ -1,37 +1,37 @@ -namespace Server.Items -{ - public class SealedNotesForJamal : Item - { - [Constructible] - public SealedNotesForJamal() : base(0xEF9) => LootType = LootType.Blessed; - - public SealedNotesForJamal(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074998; // Sealed Notes For Jamal - public override double DefaultWeight => 1.0; - - public override bool Nontransferable => true; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - AddQuestItemProperty(list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SealedNotesForJamal : Item + { + [Constructible] + public SealedNotesForJamal() : base(0xEF9) => LootType = LootType.Blessed; + + public SealedNotesForJamal(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074998; // Sealed Notes For Jamal + public override double DefaultWeight => 1.0; + + public override bool Nontransferable => true; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + AddQuestItemProperty(list); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/SealingWaxOrderAddressedToPetrus.cs b/Projects/UOContent/Engines/MLQuests/Items/SealingWaxOrderAddressedToPetrus.cs index 6f3ec9088..59b4eb59a 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/SealingWaxOrderAddressedToPetrus.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/SealingWaxOrderAddressedToPetrus.cs @@ -1,36 +1,36 @@ -namespace Server.Items -{ - public class SealingWaxOrderAddressedToPetrus : Item - { - [Constructible] - public SealingWaxOrderAddressedToPetrus() : base(0xEBF) => LootType = LootType.Blessed; - - public SealingWaxOrderAddressedToPetrus(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073132; // Sealing Wax Order addressed to Petrus - - public override bool Nontransferable => true; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - AddQuestItemProperty(list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SealingWaxOrderAddressedToPetrus : Item + { + [Constructible] + public SealingWaxOrderAddressedToPetrus() : base(0xEBF) => LootType = LootType.Blessed; + + public SealingWaxOrderAddressedToPetrus(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073132; // Sealing Wax Order addressed to Petrus + + public override bool Nontransferable => true; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + AddQuestItemProperty(list); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/SeveredElfEars.cs b/Projects/UOContent/Engines/MLQuests/Items/SeveredElfEars.cs index daa1137ef..b058eddf0 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/SeveredElfEars.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/SeveredElfEars.cs @@ -1,31 +1,31 @@ -namespace Server.Items -{ - [Flippable(0x312D, 0x312E)] - public class SeveredElfEars : Item - { - [Constructible] - public SeveredElfEars(int amount = 1) : base(Utility.RandomList(0x312D, 0x312E)) - { - Stackable = true; - Amount = amount; - } - - public SeveredElfEars(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + [Flippable(0x312D, 0x312E)] + public class SeveredElfEars : Item + { + [Constructible] + public SeveredElfEars(int amount = 1) : base(Utility.RandomList(0x312D, 0x312E)) + { + Stackable = true; + Amount = amount; + } + + public SeveredElfEars(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/SeveredHumanEars.cs b/Projects/UOContent/Engines/MLQuests/Items/SeveredHumanEars.cs index f2fe0bf8f..0751c82d8 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/SeveredHumanEars.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/SeveredHumanEars.cs @@ -1,31 +1,31 @@ -namespace Server.Items -{ - [Flippable(0x312F, 0x3130)] - public class SeveredHumanEars : Item - { - [Constructible] - public SeveredHumanEars(int amount = 1) : base(Utility.RandomList(0x312F, 0x3130)) - { - Stackable = true; - Amount = amount; - } - - public SeveredHumanEars(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + [Flippable(0x312F, 0x3130)] + public class SeveredHumanEars : Item + { + [Constructible] + public SeveredHumanEars(int amount = 1) : base(Utility.RandomList(0x312F, 0x3130)) + { + Stackable = true; + Amount = amount; + } + + public SeveredHumanEars(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/SignedTuitionReimbursementForm.cs b/Projects/UOContent/Engines/MLQuests/Items/SignedTuitionReimbursementForm.cs index e0984426a..3094e5769 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/SignedTuitionReimbursementForm.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/SignedTuitionReimbursementForm.cs @@ -1,36 +1,36 @@ -namespace Server.Items -{ - public class SignedTuitionReimbursementForm : Item - { - [Constructible] - public SignedTuitionReimbursementForm() : base(0x14F0) => LootType = LootType.Blessed; - - public SignedTuitionReimbursementForm(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074614; // Signed Tuition Reimbursement Form - - public override bool Nontransferable => true; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - AddQuestItemProperty(list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SignedTuitionReimbursementForm : Item + { + [Constructible] + public SignedTuitionReimbursementForm() : base(0x14F0) => LootType = LootType.Blessed; + + public SignedTuitionReimbursementForm(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074614; // Signed Tuition Reimbursement Form + + public override bool Nontransferable => true; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + AddQuestItemProperty(list); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/SpecialTreatForDrithen.cs b/Projects/UOContent/Engines/MLQuests/Items/SpecialTreatForDrithen.cs index 100642388..e4264b700 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/SpecialTreatForDrithen.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/SpecialTreatForDrithen.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class SpecialTreatForDrithen : Item - { - [Constructible] - public SpecialTreatForDrithen() : base(0x21B) - { - LootType = LootType.Blessed; - Hue = 0x489; - } - - public SpecialTreatForDrithen(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074517; // Special Treat for Drithen - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SpecialTreatForDrithen : Item + { + [Constructible] + public SpecialTreatForDrithen() : base(0x21B) + { + LootType = LootType.Blessed; + Hue = 0x489; + } + + public SpecialTreatForDrithen(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074517; // Special Treat for Drithen + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/SpeckledPoisonSac.cs b/Projects/UOContent/Engines/MLQuests/Items/SpeckledPoisonSac.cs index 49c4a5626..7f2879aed 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/SpeckledPoisonSac.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/SpeckledPoisonSac.cs @@ -1,30 +1,30 @@ -using System; - -namespace Server.Items -{ - public class SpeckledPoisonSac : TransientItem - { - [Constructible] - public SpeckledPoisonSac() : base(0x23A, TimeSpan.FromHours(1)) => LootType = LootType.Blessed; - - public SpeckledPoisonSac(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073133; // Speckled Poison Sac - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class SpeckledPoisonSac : TransientItem + { + [Constructible] + public SpeckledPoisonSac() : base(0x23A, TimeSpan.FromHours(1)) => LootType = LootType.Blessed; + + public SpeckledPoisonSac(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073133; // Speckled Poison Sac + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/SpiritBottle.cs b/Projects/UOContent/Engines/MLQuests/Items/SpiritBottle.cs index d80008883..86767928b 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/SpiritBottle.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/SpiritBottle.cs @@ -1,36 +1,36 @@ -namespace Server.Items -{ - public class SpiritBottle : Item - { - [Constructible] - public SpiritBottle() : base(0xEFB) => LootType = LootType.Blessed; - - public SpiritBottle(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075283; // Spirit bottle - - public override bool Nontransferable => true; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - AddQuestItemProperty(list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SpiritBottle : Item + { + [Constructible] + public SpiritBottle() : base(0xEFB) => LootType = LootType.Blessed; + + public SpiritBottle(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075283; // Spirit bottle + + public override bool Nontransferable => true; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + AddQuestItemProperty(list); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/StoutWhip.cs b/Projects/UOContent/Engines/MLQuests/Items/StoutWhip.cs index d44f3b73a..2b898f579 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/StoutWhip.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/StoutWhip.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class StoutWhip : Item - { - [Constructible] - public StoutWhip() : base(0x166F) => LootType = LootType.Blessed; - - public StoutWhip(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074812; // Stout Whip - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class StoutWhip : Item + { + [Constructible] + public StoutWhip() : base(0x166F) => LootType = LootType.Blessed; + + public StoutWhip(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074812; // Stout Whip + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/TaintedTreeSample.cs b/Projects/UOContent/Engines/MLQuests/Items/TaintedTreeSample.cs index 8c8a8ccc5..545aa65ff 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/TaintedTreeSample.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/TaintedTreeSample.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class TaintedTreeSample : Item // On OSI the base class is Kindling, and it's ignitable... - { - [Constructible] - public TaintedTreeSample() : base(0xDE2) - { - LootType = LootType.Blessed; - Hue = 0x9D; - } - - public TaintedTreeSample(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074997; // Tainted Tree Sample - - public override bool Nontransferable => true; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - AddQuestItemProperty(list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TaintedTreeSample : Item // On OSI the base class is Kindling, and it's ignitable... + { + [Constructible] + public TaintedTreeSample() : base(0xDE2) + { + LootType = LootType.Blessed; + Hue = 0x9D; + } + + public TaintedTreeSample(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074997; // Tainted Tree Sample + + public override bool Nontransferable => true; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + AddQuestItemProperty(list); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/Teleporters.cs b/Projects/UOContent/Engines/MLQuests/Items/Teleporters.cs index 9baa4986f..143eb306c 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/Teleporters.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/Teleporters.cs @@ -1,194 +1,197 @@ -using System; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Items -{ - public class MLQuestTeleporter : Teleporter - { - private Type m_QuestType; - - [Constructible] - public MLQuestTeleporter() - : this(Point3D.Zero) - { - } - - [Constructible] - public MLQuestTeleporter( - Point3D pointDest, Map mapDest = null, Type questType = null, TextDefinition message = null) - : base(pointDest, mapDest) - { - m_QuestType = questType; - Message = message; - } - - public MLQuestTeleporter(Serial serial) - : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public Type QuestType - { - get => m_QuestType; - set - { - m_QuestType = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public TextDefinition Message { get; set; } - - public override bool CanTeleport(Mobile m) - { - if (!base.CanTeleport(m)) - return false; - - if (m_QuestType == null) - return true; - if (!(m is PlayerMobile pm)) - return false; - - MLQuestContext context = MLQuestSystem.GetContext(pm); - - if (context?.IsDoingQuest(m_QuestType) == true || context?.HasDoneQuest(m_QuestType) == true) - return true; - - TextDefinition.SendMessageTo(m, Message); - return false; - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_QuestType != null) - list.Add($"Required quest: {m_QuestType.Name}"); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_QuestType != null ? m_QuestType.FullName : null); - TextDefinition.Serialize(writer, Message); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - string typeName = reader.ReadString(); - - if (typeName != null) - m_QuestType = AssemblyHandler.FindFirstTypeForName(typeName, false); - - Message = TextDefinition.Deserialize(reader); - } - } - - public interface ITicket - { - void OnTicketUsed(Mobile from); - } - - public class TicketTeleporter : Teleporter - { - private Type m_TicketType; - - [Constructible] - public TicketTeleporter() - : this(Point3D.Zero) - { - } - - [Constructible] - public TicketTeleporter( - Point3D pointDest, Map mapDest = null, Type ticketType = null, TextDefinition message = null) - : base(pointDest, mapDest) - { - m_TicketType = ticketType; - Message = message; - } - - public TicketTeleporter(Serial serial) - : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public Type TicketType - { - get => m_TicketType; - set - { - m_TicketType = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public TextDefinition Message { get; set; } - - public override bool CanTeleport(Mobile m) - { - if (!base.CanTeleport(m)) - return false; - - if (m_TicketType == null) - return true; - - Container pack = m.Backpack; - Item ticket = pack?.FindItemByType(m_TicketType, false) ?? m.Items.Find(item => m_TicketType.IsInstanceOfType(item)); - - if (ticket == null) - { - TextDefinition.SendMessageTo(m, Message); - return false; - } - - (ticket as ITicket)?.OnTicketUsed(m); - - return true; - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_TicketType != null) - list.Add($"Required ticket: {m_TicketType.Name}"); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_TicketType != null ? m_TicketType.FullName : null); - TextDefinition.Serialize(writer, Message); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - string typeName = reader.ReadString(); - - if (typeName != null) - m_TicketType = AssemblyHandler.FindFirstTypeForName(typeName, false); - - Message = TextDefinition.Deserialize(reader); - } - } -} +using System; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Items +{ + public class MLQuestTeleporter : Teleporter + { + private Type m_QuestType; + + [Constructible] + public MLQuestTeleporter() + : this(Point3D.Zero) + { + } + + [Constructible] + public MLQuestTeleporter( + Point3D pointDest, Map mapDest = null, Type questType = null, TextDefinition message = null + ) + : base(pointDest, mapDest) + { + m_QuestType = questType; + Message = message; + } + + public MLQuestTeleporter(Serial serial) + : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public Type QuestType + { + get => m_QuestType; + set + { + m_QuestType = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public TextDefinition Message { get; set; } + + public override bool CanTeleport(Mobile m) + { + if (!base.CanTeleport(m)) + return false; + + if (m_QuestType == null) + return true; + if (!(m is PlayerMobile pm)) + return false; + + var context = MLQuestSystem.GetContext(pm); + + if (context?.IsDoingQuest(m_QuestType) == true || context?.HasDoneQuest(m_QuestType) == true) + return true; + + TextDefinition.SendMessageTo(m, Message); + return false; + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_QuestType != null) + list.Add($"Required quest: {m_QuestType.Name}"); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_QuestType != null ? m_QuestType.FullName : null); + TextDefinition.Serialize(writer, Message); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + var typeName = reader.ReadString(); + + if (typeName != null) + m_QuestType = AssemblyHandler.FindFirstTypeForName(typeName); + + Message = TextDefinition.Deserialize(reader); + } + } + + public interface ITicket + { + void OnTicketUsed(Mobile from); + } + + public class TicketTeleporter : Teleporter + { + private Type m_TicketType; + + [Constructible] + public TicketTeleporter() + : this(Point3D.Zero) + { + } + + [Constructible] + public TicketTeleporter( + Point3D pointDest, Map mapDest = null, Type ticketType = null, TextDefinition message = null + ) + : base(pointDest, mapDest) + { + m_TicketType = ticketType; + Message = message; + } + + public TicketTeleporter(Serial serial) + : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public Type TicketType + { + get => m_TicketType; + set + { + m_TicketType = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public TextDefinition Message { get; set; } + + public override bool CanTeleport(Mobile m) + { + if (!base.CanTeleport(m)) + return false; + + if (m_TicketType == null) + return true; + + var pack = m.Backpack; + var ticket = pack?.FindItemByType(m_TicketType, false) ?? + m.Items.Find(item => m_TicketType.IsInstanceOfType(item)); + + if (ticket == null) + { + TextDefinition.SendMessageTo(m, Message); + return false; + } + + (ticket as ITicket)?.OnTicketUsed(m); + + return true; + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_TicketType != null) + list.Add($"Required ticket: {m_TicketType.Name}"); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_TicketType != null ? m_TicketType.FullName : null); + TextDefinition.Serialize(writer, Message); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + var typeName = reader.ReadString(); + + if (typeName != null) + m_TicketType = AssemblyHandler.FindFirstTypeForName(typeName); + + Message = TextDefinition.Deserialize(reader); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/TransparentHeart.cs b/Projects/UOContent/Engines/MLQuests/Items/TransparentHeart.cs index db283755e..0db1acb9a 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/TransparentHeart.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/TransparentHeart.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class TransparentHeart : GoldEarrings - { - [Constructible] - public TransparentHeart() - { - LootType = LootType.Blessed; - Hue = 0x4AB; - } - - public TransparentHeart(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075400; // Transparent Heart - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TransparentHeart : GoldEarrings + { + [Constructible] + public TransparentHeart() + { + LootType = LootType.Blessed; + Hue = 0x4AB; + } + + public TransparentHeart(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075400; // Transparent Heart + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/TuitionReimbursementForm.cs b/Projects/UOContent/Engines/MLQuests/Items/TuitionReimbursementForm.cs index f7a82faa8..7daaa8b72 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/TuitionReimbursementForm.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/TuitionReimbursementForm.cs @@ -1,36 +1,36 @@ -namespace Server.Items -{ - public class TuitionReimbursementForm : Item - { - [Constructible] - public TuitionReimbursementForm() : base(0xE3A) => LootType = LootType.Blessed; - - public TuitionReimbursementForm(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074610; // Tuition Reimbursement Form (in triplicate) - - public override bool Nontransferable => true; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - AddQuestItemProperty(list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TuitionReimbursementForm : Item + { + [Constructible] + public TuitionReimbursementForm() : base(0xE3A) => LootType = LootType.Blessed; + + public TuitionReimbursementForm(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074610; // Tuition Reimbursement Form (in triplicate) + + public override bool Nontransferable => true; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + AddQuestItemProperty(list); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Items/UnicornRibs.cs b/Projects/UOContent/Engines/MLQuests/Items/UnicornRibs.cs index 0cbe53820..befc4be5c 100644 --- a/Projects/UOContent/Engines/MLQuests/Items/UnicornRibs.cs +++ b/Projects/UOContent/Engines/MLQuests/Items/UnicornRibs.cs @@ -1,34 +1,34 @@ -namespace Server.Items -{ - public class UnicornRibs : Item - { - [Constructible] - public UnicornRibs(int amount = 1) : base(0x9F1) - { - LootType = LootType.Blessed; - Hue = 0x14B; - Stackable = true; - Amount = amount; - } - - public UnicornRibs(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074611; // Unicorn Ribs - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class UnicornRibs : Item + { + [Constructible] + public UnicornRibs(int amount = 1) : base(0x9F1) + { + LootType = LootType.Blessed; + Hue = 0x14B; + Stackable = true; + Amount = amount; + } + + public UnicornRibs(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074611; // Unicorn Ribs + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/MLQuest.cs b/Projects/UOContent/Engines/MLQuests/MLQuest.cs index d89198fb6..ef982cba2 100644 --- a/Projects/UOContent/Engines/MLQuests/MLQuest.cs +++ b/Projects/UOContent/Engines/MLQuests/MLQuest.cs @@ -1,261 +1,266 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Server.Engines.MLQuests.Gumps; -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; -using Server.Engines.Spawners; -using Server.Mobiles; - -namespace Server.Engines.MLQuests -{ - public enum ObjectiveType - { - All, - Any - } - - public class MLQuest - { - public static readonly TextDefinition - CompletionNoticeDefault = - new TextDefinition(1072273); // You've completed a quest! Don't forget to collect your reward. - - public static readonly TextDefinition CompletionNoticeShort = new TextDefinition(1046258); // Your quest is complete. - - public static readonly TextDefinition - CompletionNoticeShortReturn = new TextDefinition(1073775); // Your quest is complete. Return for your reward. - - public static readonly TextDefinition - CompletionNoticeCraft = new TextDefinition(1073967); // You obtained what you seek, now receive your reward. - - public MLQuest() - { - Activated = false; - Objectives = new List(); - ObjectiveType = ObjectiveType.All; - Rewards = new List(); - CompletionNotice = CompletionNoticeDefault; - - Instances = new List(); - - SaveEnabled = true; - } - - public bool Deserialized { get; set; } - - public bool SaveEnabled { get; set; } - - // TODO: Flags? (Deserialized, SaveEnabled, Activated) - - public bool Activated { get; set; } - - public List Objectives { get; set; } - - public ObjectiveType ObjectiveType { get; set; } - - public List Rewards { get; set; } - - public List Instances { get; set; } - - public bool OneTimeOnly { get; set; } - - public bool HasRestartDelay { get; set; } - - public bool IsEscort => HasObjective(); - - public bool IsSkillTrainer => HasObjective(); - - public bool RequiresCollection => HasObjective() || HasObjective(); - - public virtual bool RecordCompletion => OneTimeOnly || HasRestartDelay; - - public virtual bool IsChainTriggered => false; - public virtual Type NextQuest => null; - - public TextDefinition Title { get; set; } - - public TextDefinition Description { get; set; } - - public TextDefinition RefusalMessage { get; set; } - - public TextDefinition InProgressMessage { get; set; } - - public TextDefinition CompletionMessage { get; set; } - - public TextDefinition CompletionNotice { get; set; } - - public virtual int Version => 0; - - public bool HasObjective() where T : BaseObjective - { - foreach (BaseObjective obj in Objectives) - if (obj is T) - return true; - - return false; - } - - public virtual void Generate() - { - if (MLQuestSystem.Debug) - Console.WriteLine("INFO: Generating quest: {0}", GetType()); - } - - public MLQuestInstance CreateInstance(IQuestGiver quester, PlayerMobile pm) => new MLQuestInstance(this, quester, pm); - - public bool CanOffer(IQuestGiver quester, PlayerMobile pm, bool message) => CanOffer(quester, pm, MLQuestSystem.GetContext(pm), message); - - public virtual bool CanOffer(IQuestGiver quester, PlayerMobile pm, MLQuestContext context, bool message) - { - if (!Activated || quester.Deleted) - return false; - - if (context != null) - { - if (context.IsFull) - { - if (message) - MLQuestSystem.Tell(quester, pm, 1080107); // I'm sorry, I have nothing for you at this time. - - return false; - } - - MLQuest checkQuest = this; - - while (checkQuest != null) - { - if (context.HasDoneQuest(checkQuest, out DateTime nextAvailable)) - { - if (checkQuest.OneTimeOnly) - { - if (message) - MLQuestSystem.Tell(quester, pm, 1075454); // I cannot offer you the quest again. - - return false; - } - - if (nextAvailable > DateTime.UtcNow) - { - if (message) - MLQuestSystem.Tell(quester, pm, - 1075575); // I'm sorry, but I don't have anything else for you right now. Could you check back with me in a few minutes? - - return false; - } - } - - if (checkQuest.NextQuest == null) - break; - - checkQuest = MLQuestSystem.FindQuest(checkQuest.NextQuest); - } - } - - foreach (BaseObjective obj in Objectives) - if (!obj.CanOffer(quester, pm, message)) - return false; - - return true; - } - - public virtual void SendOffer(IQuestGiver quester, PlayerMobile pm) - { - pm.SendGump(new QuestOfferGump(this, quester, pm)); - } - - public virtual void OnAccept(IQuestGiver quester, PlayerMobile pm) - { - if (!CanOffer(quester, pm, true)) - return; - - MLQuestInstance instance = CreateInstance(quester, pm); - - pm.SendLocalizedMessage(1049019); // You have accepted the Quest. - pm.SendSound(0x2E7); // private sound - - OnAccepted(instance); - - foreach (BaseObjectiveInstance obj in instance.Objectives) - obj.OnQuestAccepted(); - } - - public virtual void OnAccepted(MLQuestInstance instance) - { - } - - public virtual void OnRefuse(IQuestGiver quester, PlayerMobile pm) - { - pm.SendGump(new QuestConversationGump(this, pm, RefusalMessage)); - } - - public virtual void GetRewards(MLQuestInstance instance) - { - instance.SendRewardGump(); - } - - public virtual void OnRewardClaimed(MLQuestInstance instance) - { - } - - public virtual void OnCancel(MLQuestInstance instance) - { - } - - public virtual void OnQuesterDeleted(MLQuestInstance instance) - { - } - - public virtual void OnPlayerDeath(MLQuestInstance instance) - { - } - - public virtual TimeSpan GetRestartDelay() => TimeSpan.FromSeconds(Utility.Random(1, 5) * 30); - - public static void Serialize(IGenericWriter writer, MLQuest quest) - { - MLQuestSystem.WriteQuestRef(writer, quest); - writer.Write(quest.Version); - } - - public static void Deserialize(IGenericReader reader, int version) - { - MLQuest quest = MLQuestSystem.ReadQuestRef(reader); - int oldVersion = reader.ReadInt(); - - if (quest == null) - return; // not saved or no longer exists - - quest.Refresh(oldVersion); - quest.Deserialized = true; - } - - public virtual void Refresh(int oldVersion) - { - } - - public void PutSpawner(Spawner s, Point3D loc, Map map) - { - string name = $"MLQS-{GetType().Name}"; - - IEnumerable toDelete = map.GetItemsInRange(loc, 0).Where(item => item is Spawner && item.Name == name); - - foreach (Item item in toDelete) - item.Delete(); - - s.Name = name; - s.MoveToWorld(loc, map); - } - - public void PutDeco(Item deco, Point3D loc, Map map) - { - // Auto cleanup on regeneration - IEnumerable toDelete = map.GetItemsInRange(loc, 0).Where(item => item.ItemID == deco.ItemID && item.Z == loc.Z); - - foreach (Item item in toDelete) - item.Delete(); - - deco.MoveToWorld(loc, map); - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using Server.Engines.MLQuests.Gumps; +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; +using Server.Engines.Spawners; +using Server.Mobiles; + +namespace Server.Engines.MLQuests +{ + public enum ObjectiveType + { + All, + Any + } + + public class MLQuest + { + public static readonly TextDefinition + CompletionNoticeDefault = + new TextDefinition(1072273); // You've completed a quest! Don't forget to collect your reward. + + public static readonly TextDefinition CompletionNoticeShort = new TextDefinition(1046258); // Your quest is complete. + + public static readonly TextDefinition + CompletionNoticeShortReturn = new TextDefinition(1073775); // Your quest is complete. Return for your reward. + + public static readonly TextDefinition + CompletionNoticeCraft = new TextDefinition(1073967); // You obtained what you seek, now receive your reward. + + public MLQuest() + { + Activated = false; + Objectives = new List(); + ObjectiveType = ObjectiveType.All; + Rewards = new List(); + CompletionNotice = CompletionNoticeDefault; + + Instances = new List(); + + SaveEnabled = true; + } + + public bool Deserialized { get; set; } + + public bool SaveEnabled { get; set; } + + // TODO: Flags? (Deserialized, SaveEnabled, Activated) + + public bool Activated { get; set; } + + public List Objectives { get; set; } + + public ObjectiveType ObjectiveType { get; set; } + + public List Rewards { get; set; } + + public List Instances { get; set; } + + public bool OneTimeOnly { get; set; } + + public bool HasRestartDelay { get; set; } + + public bool IsEscort => HasObjective(); + + public bool IsSkillTrainer => HasObjective(); + + public bool RequiresCollection => HasObjective() || HasObjective(); + + public virtual bool RecordCompletion => OneTimeOnly || HasRestartDelay; + + public virtual bool IsChainTriggered => false; + public virtual Type NextQuest => null; + + public TextDefinition Title { get; set; } + + public TextDefinition Description { get; set; } + + public TextDefinition RefusalMessage { get; set; } + + public TextDefinition InProgressMessage { get; set; } + + public TextDefinition CompletionMessage { get; set; } + + public TextDefinition CompletionNotice { get; set; } + + public virtual int Version => 0; + + public bool HasObjective() where T : BaseObjective + { + foreach (var obj in Objectives) + if (obj is T) + return true; + + return false; + } + + public virtual void Generate() + { + if (MLQuestSystem.Debug) + Console.WriteLine("INFO: Generating quest: {0}", GetType()); + } + + public MLQuestInstance CreateInstance(IQuestGiver quester, PlayerMobile pm) => + new MLQuestInstance(this, quester, pm); + + public bool CanOffer(IQuestGiver quester, PlayerMobile pm, bool message) => + CanOffer(quester, pm, MLQuestSystem.GetContext(pm), message); + + public virtual bool CanOffer(IQuestGiver quester, PlayerMobile pm, MLQuestContext context, bool message) + { + if (!Activated || quester.Deleted) + return false; + + if (context != null) + { + if (context.IsFull) + { + if (message) + MLQuestSystem.Tell(quester, pm, 1080107); // I'm sorry, I have nothing for you at this time. + + return false; + } + + var checkQuest = this; + + while (checkQuest != null) + { + if (context.HasDoneQuest(checkQuest, out var nextAvailable)) + { + if (checkQuest.OneTimeOnly) + { + if (message) + MLQuestSystem.Tell(quester, pm, 1075454); // I cannot offer you the quest again. + + return false; + } + + if (nextAvailable > DateTime.UtcNow) + { + if (message) + MLQuestSystem.Tell( + quester, + pm, + 1075575 + ); // I'm sorry, but I don't have anything else for you right now. Could you check back with me in a few minutes? + + return false; + } + } + + if (checkQuest.NextQuest == null) + break; + + checkQuest = MLQuestSystem.FindQuest(checkQuest.NextQuest); + } + } + + foreach (var obj in Objectives) + if (!obj.CanOffer(quester, pm, message)) + return false; + + return true; + } + + public virtual void SendOffer(IQuestGiver quester, PlayerMobile pm) + { + pm.SendGump(new QuestOfferGump(this, quester, pm)); + } + + public virtual void OnAccept(IQuestGiver quester, PlayerMobile pm) + { + if (!CanOffer(quester, pm, true)) + return; + + var instance = CreateInstance(quester, pm); + + pm.SendLocalizedMessage(1049019); // You have accepted the Quest. + pm.SendSound(0x2E7); // private sound + + OnAccepted(instance); + + foreach (var obj in instance.Objectives) + obj.OnQuestAccepted(); + } + + public virtual void OnAccepted(MLQuestInstance instance) + { + } + + public virtual void OnRefuse(IQuestGiver quester, PlayerMobile pm) + { + pm.SendGump(new QuestConversationGump(this, pm, RefusalMessage)); + } + + public virtual void GetRewards(MLQuestInstance instance) + { + instance.SendRewardGump(); + } + + public virtual void OnRewardClaimed(MLQuestInstance instance) + { + } + + public virtual void OnCancel(MLQuestInstance instance) + { + } + + public virtual void OnQuesterDeleted(MLQuestInstance instance) + { + } + + public virtual void OnPlayerDeath(MLQuestInstance instance) + { + } + + public virtual TimeSpan GetRestartDelay() => TimeSpan.FromSeconds(Utility.Random(1, 5) * 30); + + public static void Serialize(IGenericWriter writer, MLQuest quest) + { + MLQuestSystem.WriteQuestRef(writer, quest); + writer.Write(quest.Version); + } + + public static void Deserialize(IGenericReader reader, int version) + { + var quest = MLQuestSystem.ReadQuestRef(reader); + var oldVersion = reader.ReadInt(); + + if (quest == null) + return; // not saved or no longer exists + + quest.Refresh(oldVersion); + quest.Deserialized = true; + } + + public virtual void Refresh(int oldVersion) + { + } + + public void PutSpawner(Spawner s, Point3D loc, Map map) + { + var name = $"MLQS-{GetType().Name}"; + + var toDelete = map.GetItemsInRange(loc, 0).Where(item => item is Spawner && item.Name == name); + + foreach (var item in toDelete) + item.Delete(); + + s.Name = name; + s.MoveToWorld(loc, map); + } + + public void PutDeco(Item deco, Point3D loc, Map map) + { + // Auto cleanup on regeneration + var toDelete = map.GetItemsInRange(loc, 0).Where(item => item.ItemID == deco.ItemID && item.Z == loc.Z); + + foreach (var item in toDelete) + item.Delete(); + + deco.MoveToWorld(loc, map); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/MLQuestContext.cs b/Projects/UOContent/Engines/MLQuests/MLQuestContext.cs index e131ec531..50c113ea4 100644 --- a/Projects/UOContent/Engines/MLQuests/MLQuestContext.cs +++ b/Projects/UOContent/Engines/MLQuests/MLQuestContext.cs @@ -1,269 +1,269 @@ -using System; -using System.Collections.Generic; -using Server.Mobiles; - -namespace Server.Engines.MLQuests -{ - [Flags] - public enum MLQuestFlag - { - None = 0x00, - Spellweaving = 0x01, - SummonFey = 0x02, - SummonFiend = 0x04, - BedlamAccess = 0x08 - } - - [PropertyObject] - public class MLQuestContext - { - private readonly List m_DoneQuests; - private MLQuestFlag m_Flags; - - public MLQuestContext(PlayerMobile owner) - { - Owner = owner; - QuestInstances = new List(); - m_DoneQuests = new List(); - ChainOffers = new List(); - m_Flags = MLQuestFlag.None; - } - - public MLQuestContext(IGenericReader reader, int version) - { - Owner = reader.ReadMobile(); - QuestInstances = new List(); - m_DoneQuests = new List(); - ChainOffers = new List(); - - int instances = reader.ReadInt(); - - for (int i = 0; i < instances; ++i) - { - MLQuestInstance instance = MLQuestInstance.Deserialize(reader, version, Owner); - - if (instance != null) - QuestInstances.Add(instance); - } - - int doneQuests = reader.ReadInt(); - - for (int i = 0; i < doneQuests; ++i) - { - MLDoneQuestInfo info = MLDoneQuestInfo.Deserialize(reader, version); - - if (info != null) - m_DoneQuests.Add(info); - } - - int chainOffers = reader.ReadInt(); - - for (int i = 0; i < chainOffers; ++i) - { - MLQuest quest = MLQuestSystem.ReadQuestRef(reader); - - if (quest?.IsChainTriggered == true) - ChainOffers.Add(quest); - } - - m_Flags = (MLQuestFlag)reader.ReadEncodedInt(); - } - - public PlayerMobile Owner { get; } - - public List QuestInstances { get; } - - public List ChainOffers { get; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsFull => QuestInstances.Count >= MLQuestSystem.MaxConcurrentQuests; - - [CommandProperty(AccessLevel.GameMaster)] - public bool Spellweaving - { - get => GetFlag(MLQuestFlag.Spellweaving); - set => SetFlag(MLQuestFlag.Spellweaving, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool SummonFey - { - get => GetFlag(MLQuestFlag.SummonFey); - set => SetFlag(MLQuestFlag.SummonFey, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool SummonFiend - { - get => GetFlag(MLQuestFlag.SummonFiend); - set => SetFlag(MLQuestFlag.SummonFiend, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool BedlamAccess - { - get => GetFlag(MLQuestFlag.BedlamAccess); - set => SetFlag(MLQuestFlag.BedlamAccess, value); - } - - public bool HasDoneQuest(Type questType) - { - MLQuest quest = MLQuestSystem.FindQuest(questType); - - return quest != null && HasDoneQuest(quest); - } - - public bool HasDoneQuest(MLQuest quest) - { - foreach (MLDoneQuestInfo info in m_DoneQuests) - if (info.m_Quest == quest) - return true; - - return false; - } - - public bool HasDoneQuest(MLQuest quest, out DateTime nextAvailable) - { - nextAvailable = DateTime.MinValue; - - foreach (MLDoneQuestInfo info in m_DoneQuests) - if (info.m_Quest == quest) - { - nextAvailable = info.m_NextAvailable; - return true; - } - - return false; - } - - public void SetDoneQuest(MLQuest quest) - { - SetDoneQuest(quest, DateTime.MinValue); - } - - public void SetDoneQuest(MLQuest quest, DateTime nextAvailable) - { - foreach (MLDoneQuestInfo info in m_DoneQuests) - if (info.m_Quest == quest) - { - info.m_NextAvailable = nextAvailable; - return; - } - - m_DoneQuests.Add(new MLDoneQuestInfo(quest, nextAvailable)); - } - - public void RemoveDoneQuest(MLQuest quest) - { - for (int i = m_DoneQuests.Count - 1; i >= 0; --i) - { - MLDoneQuestInfo info = m_DoneQuests[i]; - - if (info.m_Quest == quest) - m_DoneQuests.RemoveAt(i); - } - } - - public void HandleDeath() - { - for (int i = QuestInstances.Count - 1; i >= 0; --i) - QuestInstances[i].OnPlayerDeath(); - } - - public void HandleDeletion() - { - for (int i = QuestInstances.Count - 1; i >= 0; --i) - QuestInstances[i].Remove(); - } - - public MLQuestInstance FindInstance(Type questType) - { - MLQuest quest = MLQuestSystem.FindQuest(questType); - - if (quest == null) - return null; - - return FindInstance(quest); - } - - public MLQuestInstance FindInstance(MLQuest quest) - { - foreach (MLQuestInstance instance in QuestInstances) - if (instance.Quest == quest) - return instance; - - return null; - } - - public bool IsDoingQuest(Type questType) - { - MLQuest quest = MLQuestSystem.FindQuest(questType); - - return quest != null && IsDoingQuest(quest); - } - - public bool IsDoingQuest(MLQuest quest) => FindInstance(quest) != null; - - public void Serialize(IGenericWriter writer) - { - // Version info is written in MLQuestPersistence.Serialize - - writer.WriteMobile(Owner); - writer.Write(QuestInstances.Count); - - foreach (MLQuestInstance instance in QuestInstances) - instance.Serialize(writer); - - writer.Write(m_DoneQuests.Count); - - foreach (MLDoneQuestInfo info in m_DoneQuests) - info.Serialize(writer); - - writer.Write(ChainOffers.Count); - - foreach (MLQuest quest in ChainOffers) - MLQuestSystem.WriteQuestRef(writer, quest); - - writer.WriteEncodedInt((int)m_Flags); - } - - public bool GetFlag(MLQuestFlag flag) => (m_Flags & flag) != 0; - - public void SetFlag(MLQuestFlag flag, bool value) - { - if (value) - m_Flags |= flag; - else - m_Flags &= ~flag; - } - - private class MLDoneQuestInfo - { - public DateTime m_NextAvailable; - public readonly MLQuest m_Quest; - - public MLDoneQuestInfo(MLQuest quest, DateTime nextAvailable) - { - m_Quest = quest; - m_NextAvailable = nextAvailable; - } - - public void Serialize(IGenericWriter writer) - { - MLQuestSystem.WriteQuestRef(writer, m_Quest); - writer.Write(m_NextAvailable); - } - - public static MLDoneQuestInfo Deserialize(IGenericReader reader, int version) - { - MLQuest quest = MLQuestSystem.ReadQuestRef(reader); - DateTime nextAvailable = reader.ReadDateTime(); - - if (quest?.RecordCompletion != true) - return null; // forget about this record - - return new MLDoneQuestInfo(quest, nextAvailable); - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Mobiles; + +namespace Server.Engines.MLQuests +{ + [Flags] + public enum MLQuestFlag + { + None = 0x00, + Spellweaving = 0x01, + SummonFey = 0x02, + SummonFiend = 0x04, + BedlamAccess = 0x08 + } + + [PropertyObject] + public class MLQuestContext + { + private readonly List m_DoneQuests; + private MLQuestFlag m_Flags; + + public MLQuestContext(PlayerMobile owner) + { + Owner = owner; + QuestInstances = new List(); + m_DoneQuests = new List(); + ChainOffers = new List(); + m_Flags = MLQuestFlag.None; + } + + public MLQuestContext(IGenericReader reader, int version) + { + Owner = reader.ReadMobile(); + QuestInstances = new List(); + m_DoneQuests = new List(); + ChainOffers = new List(); + + var instances = reader.ReadInt(); + + for (var i = 0; i < instances; ++i) + { + var instance = MLQuestInstance.Deserialize(reader, version, Owner); + + if (instance != null) + QuestInstances.Add(instance); + } + + var doneQuests = reader.ReadInt(); + + for (var i = 0; i < doneQuests; ++i) + { + var info = MLDoneQuestInfo.Deserialize(reader, version); + + if (info != null) + m_DoneQuests.Add(info); + } + + var chainOffers = reader.ReadInt(); + + for (var i = 0; i < chainOffers; ++i) + { + var quest = MLQuestSystem.ReadQuestRef(reader); + + if (quest?.IsChainTriggered == true) + ChainOffers.Add(quest); + } + + m_Flags = (MLQuestFlag)reader.ReadEncodedInt(); + } + + public PlayerMobile Owner { get; } + + public List QuestInstances { get; } + + public List ChainOffers { get; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsFull => QuestInstances.Count >= MLQuestSystem.MaxConcurrentQuests; + + [CommandProperty(AccessLevel.GameMaster)] + public bool Spellweaving + { + get => GetFlag(MLQuestFlag.Spellweaving); + set => SetFlag(MLQuestFlag.Spellweaving, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool SummonFey + { + get => GetFlag(MLQuestFlag.SummonFey); + set => SetFlag(MLQuestFlag.SummonFey, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool SummonFiend + { + get => GetFlag(MLQuestFlag.SummonFiend); + set => SetFlag(MLQuestFlag.SummonFiend, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool BedlamAccess + { + get => GetFlag(MLQuestFlag.BedlamAccess); + set => SetFlag(MLQuestFlag.BedlamAccess, value); + } + + public bool HasDoneQuest(Type questType) + { + var quest = MLQuestSystem.FindQuest(questType); + + return quest != null && HasDoneQuest(quest); + } + + public bool HasDoneQuest(MLQuest quest) + { + foreach (var info in m_DoneQuests) + if (info.m_Quest == quest) + return true; + + return false; + } + + public bool HasDoneQuest(MLQuest quest, out DateTime nextAvailable) + { + nextAvailable = DateTime.MinValue; + + foreach (var info in m_DoneQuests) + if (info.m_Quest == quest) + { + nextAvailable = info.m_NextAvailable; + return true; + } + + return false; + } + + public void SetDoneQuest(MLQuest quest) + { + SetDoneQuest(quest, DateTime.MinValue); + } + + public void SetDoneQuest(MLQuest quest, DateTime nextAvailable) + { + foreach (var info in m_DoneQuests) + if (info.m_Quest == quest) + { + info.m_NextAvailable = nextAvailable; + return; + } + + m_DoneQuests.Add(new MLDoneQuestInfo(quest, nextAvailable)); + } + + public void RemoveDoneQuest(MLQuest quest) + { + for (var i = m_DoneQuests.Count - 1; i >= 0; --i) + { + var info = m_DoneQuests[i]; + + if (info.m_Quest == quest) + m_DoneQuests.RemoveAt(i); + } + } + + public void HandleDeath() + { + for (var i = QuestInstances.Count - 1; i >= 0; --i) + QuestInstances[i].OnPlayerDeath(); + } + + public void HandleDeletion() + { + for (var i = QuestInstances.Count - 1; i >= 0; --i) + QuestInstances[i].Remove(); + } + + public MLQuestInstance FindInstance(Type questType) + { + var quest = MLQuestSystem.FindQuest(questType); + + if (quest == null) + return null; + + return FindInstance(quest); + } + + public MLQuestInstance FindInstance(MLQuest quest) + { + foreach (var instance in QuestInstances) + if (instance.Quest == quest) + return instance; + + return null; + } + + public bool IsDoingQuest(Type questType) + { + var quest = MLQuestSystem.FindQuest(questType); + + return quest != null && IsDoingQuest(quest); + } + + public bool IsDoingQuest(MLQuest quest) => FindInstance(quest) != null; + + public void Serialize(IGenericWriter writer) + { + // Version info is written in MLQuestPersistence.Serialize + + writer.WriteMobile(Owner); + writer.Write(QuestInstances.Count); + + foreach (var instance in QuestInstances) + instance.Serialize(writer); + + writer.Write(m_DoneQuests.Count); + + foreach (var info in m_DoneQuests) + info.Serialize(writer); + + writer.Write(ChainOffers.Count); + + foreach (var quest in ChainOffers) + MLQuestSystem.WriteQuestRef(writer, quest); + + writer.WriteEncodedInt((int)m_Flags); + } + + public bool GetFlag(MLQuestFlag flag) => (m_Flags & flag) != 0; + + public void SetFlag(MLQuestFlag flag, bool value) + { + if (value) + m_Flags |= flag; + else + m_Flags &= ~flag; + } + + private class MLDoneQuestInfo + { + public readonly MLQuest m_Quest; + public DateTime m_NextAvailable; + + public MLDoneQuestInfo(MLQuest quest, DateTime nextAvailable) + { + m_Quest = quest; + m_NextAvailable = nextAvailable; + } + + public void Serialize(IGenericWriter writer) + { + MLQuestSystem.WriteQuestRef(writer, m_Quest); + writer.Write(m_NextAvailable); + } + + public static MLDoneQuestInfo Deserialize(IGenericReader reader, int version) + { + var quest = MLQuestSystem.ReadQuestRef(reader); + var nextAvailable = reader.ReadDateTime(); + + if (quest?.RecordCompletion != true) + return null; // forget about this record + + return new MLDoneQuestInfo(quest, nextAvailable); + } + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/MLQuestEntry.cs b/Projects/UOContent/Engines/MLQuests/MLQuestEntry.cs index 37d6f75f0..f5ae7d632 100644 --- a/Projects/UOContent/Engines/MLQuests/MLQuestEntry.cs +++ b/Projects/UOContent/Engines/MLQuests/MLQuestEntry.cs @@ -1,479 +1,485 @@ -using System; -using System.Collections.Generic; -using Server.Engines.MLQuests.Gumps; -using Server.Engines.MLQuests.Objectives; -using Server.Engines.MLQuests.Rewards; -using Server.Mobiles; - -namespace Server.Engines.MLQuests -{ - [Flags] - public enum MLQuestInstanceFlags : byte - { - None = 0x00, - ClaimReward = 0x01, - Removed = 0x02, - Failed = 0x04 - } - - public class MLQuestInstance - { - private MLQuestInstanceFlags m_Flags; - private IQuestGiver m_Quester; - - private Timer m_Timer; - - public MLQuestInstance(MLQuest quest, IQuestGiver quester, PlayerMobile player) - { - Quest = quest; - - m_Quester = quester; - QuesterType = quester?.GetType(); - Player = player; - - Accepted = DateTime.UtcNow; - m_Flags = MLQuestInstanceFlags.None; - - Objectives = new BaseObjectiveInstance[quest.Objectives.Count]; - - BaseObjectiveInstance obj; - bool timed = false; - - for (int i = 0; i < quest.Objectives.Count; ++i) - { - Objectives[i] = obj = quest.Objectives[i].CreateInstance(this); - - if (obj.IsTimed) - timed = true; - } - - Register(); - - if (timed) - m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5), Slice); - } - - public MLQuest Quest { get; set; } - - public IQuestGiver Quester - { - get => m_Quester; - set - { - m_Quester = value; - QuesterType = value?.GetType(); - } - } - - public Type QuesterType { get; private set; } - - public PlayerMobile Player { get; set; } - - public MLQuestContext PlayerContext => MLQuestSystem.GetOrCreateContext(Player); - - public DateTime Accepted { get; set; } - - public bool ClaimReward - { - get => GetFlag(MLQuestInstanceFlags.ClaimReward); - set => SetFlag(MLQuestInstanceFlags.ClaimReward, value); - } - - public bool Removed - { - get => GetFlag(MLQuestInstanceFlags.Removed); - set => SetFlag(MLQuestInstanceFlags.Removed, value); - } - - public bool Failed - { - get => GetFlag(MLQuestInstanceFlags.Failed); - set => SetFlag(MLQuestInstanceFlags.Failed, value); - } - - public BaseObjectiveInstance[] Objectives { get; set; } - - public bool SkipReportBack => TextDefinition.IsNullOrEmpty(Quest.CompletionMessage); - - private void Register() - { - Quest?.Instances?.Add(this); - - if (Player != null) - PlayerContext.QuestInstances.Add(this); - } - - private void Unregister() - { - Quest?.Instances?.Remove(this); - - if (Player != null) - PlayerContext.QuestInstances.Remove(this); - - Removed = true; - } - - public bool AllowsQuestItem(Item item, Type type) - { - foreach (BaseObjectiveInstance objective in Objectives) - if (!objective.Expired && objective.AllowsQuestItem(item, type)) - return true; - - return false; - } - - public bool IsCompleted() - { - bool requiresAll = Quest.ObjectiveType == ObjectiveType.All; - - foreach (BaseObjectiveInstance obj in Objectives) - { - bool complete = obj.IsCompleted(); - - if (complete && !requiresAll) - return true; - if (!complete && requiresAll) - return false; - } - - return requiresAll; - } - - public void CheckComplete() - { - if (IsCompleted()) - { - Player.PlaySound(0x5B5); // public sound - - foreach (BaseObjectiveInstance obj in Objectives) - obj.OnQuestCompleted(); - - TextDefinition.SendMessageTo(Player, Quest.CompletionNotice, 0x23); - - /* - * Advance to the ClaimReward=true stage if this quest has no - * completion message to show anyway. This suppresses further - * triggers of CheckComplete. - * - * For quests that require collections, this is done later when - * the player double clicks the quester. - */ - if (!Removed && SkipReportBack && !Quest.RequiresCollection) // An OnQuestCompleted can potentially have removed this instance already - ContinueReportBack(false); - } - } - - public void Fail() - { - Failed = true; - } - - private void Slice() - { - if (ClaimReward || Removed) - { - StopTimer(); - return; - } - - bool hasAnyFails = false; - bool hasAnyLeft = false; - - foreach (BaseObjectiveInstance obj in Objectives) - if (!obj.Expired) - { - if (obj.IsTimed && obj.EndTime <= DateTime.UtcNow) - { - Player.SendLocalizedMessage(1072258); // You failed to complete an objective in time! - - obj.Expired = true; - obj.OnExpire(); - - hasAnyFails = true; - } - else - { - hasAnyLeft = true; - } - } - - if ((Quest.ObjectiveType == ObjectiveType.All && hasAnyFails) || !hasAnyLeft) - Fail(); - - if (!hasAnyLeft) - StopTimer(); - } - - public void SendProgressGump() - { - Player.SendGump(new QuestConversationGump(Quest, Player, Quest.InProgressMessage)); - } - - public void SendRewardOffer() - { - Quest.GetRewards(this); - } - - // TODO: Split next quest stuff from SendRewardGump stuff? - public void SendRewardGump() - { - Type nextQuestType = Quest.NextQuest; - - if (nextQuestType != null) - { - ClaimRewards(); // skip reward gump - - if (Removed) // rewards were claimed successfully - { - MLQuest nextQuest = MLQuestSystem.FindQuest(nextQuestType); - - nextQuest?.SendOffer(m_Quester, Player); - } - } - else - { - Player.SendGump(new QuestRewardGump(this)); - } - } - - public void SendReportBackGump() - { - if (SkipReportBack) - ContinueReportBack(true); // skip ahead - else - Player.SendGump(new QuestReportBackGump(this)); - } - - public void ContinueReportBack(bool sendRewardGump) - { - // There is a backpack check here on OSI for the rewards as well (even though it's not needed...) - - if (Quest.ObjectiveType == ObjectiveType.All) - { - // TODO: 1115877 - You no longer have the required items to complete this quest. - foreach (BaseObjectiveInstance objective in Objectives) - if (!objective.IsCompleted()) - return; - - foreach (BaseObjectiveInstance objective in Objectives) - if (!objective.OnBeforeClaimReward()) - return; - - foreach (BaseObjectiveInstance objective in Objectives) - objective.OnClaimReward(); - } - else - { - /* The following behavior is unverified, as OSI (currently) has no collect quest requiring - * only one objective to be completed. It is assumed that only one objective is claimed - * (the first completed one), even when multiple are complete. - */ - bool complete = false; - - foreach (BaseObjectiveInstance objective in Objectives) - if (objective.IsCompleted()) - { - if (objective.OnBeforeClaimReward()) - { - complete = true; - objective.OnClaimReward(); - } - - break; - } - - if (!complete) - return; - } - - ClaimReward = true; - - if (Quest.HasRestartDelay) - PlayerContext.SetDoneQuest(Quest, DateTime.UtcNow + Quest.GetRestartDelay()); - - // This is correct for ObjectiveType.Any as well - foreach (BaseObjectiveInstance objective in Objectives) - objective.OnAfterClaimReward(); - - if (sendRewardGump) - SendRewardOffer(); - } - - public void ClaimRewards() - { - if (Quest == null || Player?.Deleted != false || !ClaimReward || Removed) - return; - - List rewards = new List(); - - foreach (BaseReward reward in Quest.Rewards) - reward.AddRewardItems(Player, rewards); - - if (rewards.Count != 0) - { - // On OSI a more naive method of checking is used. - // For containers, only the actual container item counts. - bool canFit = true; - - foreach (Item rewardItem in rewards) - if (!Player.AddToBackpack(rewardItem)) - { - canFit = false; - break; - } - - if (!canFit) - { - foreach (Item rewardItem in rewards) - rewardItem.Delete(); - - Player.SendLocalizedMessage( - 1078524); // Your backpack is full. You cannot complete the quest and receive your reward. - return; - } - - foreach (Item rewardItem in rewards) - { - string rewardName = rewardItem.Name ?? $"#{rewardItem.LabelNumber}"; - - if (rewardItem.Stackable) - Player.SendLocalizedMessage(1115917, - $"{rewardItem.Amount}\t{rewardName}"); // You receive a reward: ~1_QUANTITY~ ~2_ITEM~ - else - Player.SendLocalizedMessage(1074360, rewardName); // You receive a reward: ~1_REWARD~ - } - } - - foreach (BaseObjectiveInstance objective in Objectives) - objective.OnRewardClaimed(); - - Quest.OnRewardClaimed(this); - - MLQuestContext context = PlayerContext; - - if (Quest.RecordCompletion && !Quest.HasRestartDelay) // Quests with restart delays are logged earlier as per OSI - context.SetDoneQuest(Quest); - - if (Quest.IsChainTriggered) - context.ChainOffers.Remove(Quest); - - Type nextQuestType = Quest.NextQuest; - - if (nextQuestType != null) - { - MLQuest nextQuest = MLQuestSystem.FindQuest(nextQuestType); - - if (nextQuest != null && !context.ChainOffers.Contains(nextQuest)) - context.ChainOffers.Add(nextQuest); - } - - Remove(); - } - - public void Cancel() - { - Cancel(false); - } - - public void Cancel(bool removeChain) - { - Remove(); - - Player.SendSound(0x5B3); // private sound - - foreach (BaseObjectiveInstance obj in Objectives) - obj.OnQuestCancelled(); - - Quest.OnCancel(this); - - if (removeChain) - PlayerContext.ChainOffers.Remove(Quest); - } - - public void Remove() - { - Unregister(); - StopTimer(); - } - - private void StopTimer() - { - if (m_Timer == null) - return; - m_Timer.Stop(); - m_Timer = null; - } - - public void OnQuesterDeleted() - { - foreach (BaseObjectiveInstance obj in Objectives) - obj.OnQuesterDeleted(); - - Quest.OnQuesterDeleted(this); - } - - public void OnPlayerDeath() - { - foreach (BaseObjectiveInstance obj in Objectives) - obj.OnPlayerDeath(); - - Quest.OnPlayerDeath(this); - } - - private bool GetFlag(MLQuestInstanceFlags flag) => (m_Flags & flag) != 0; - - private void SetFlag(MLQuestInstanceFlags flag, bool value) - { - if (value) - m_Flags |= flag; - else - m_Flags &= ~flag; - } - - public void Serialize(IGenericWriter writer) - { - // Version info is written in MLQuestPersistence.Serialize - - MLQuestSystem.WriteQuestRef(writer, Quest); - - writer.Write(m_Quester?.Deleted != false ? Serial.MinusOne : m_Quester.Serial); - - writer.Write(ClaimReward); - writer.Write(Objectives.Length); - - foreach (BaseObjectiveInstance objInstance in Objectives) - objInstance.Serialize(writer); - } - - public static MLQuestInstance Deserialize(IGenericReader reader, int version, PlayerMobile pm) - { - MLQuest quest = MLQuestSystem.ReadQuestRef(reader); - - // TODO: Serialize quester TYPE too, the quest giver reference then becomes optional (only for escorts) - IQuestGiver quester = World.FindEntity(reader.ReadUInt()) as IQuestGiver; - - bool claimReward = reader.ReadBool(); - int objectives = reader.ReadInt(); - - MLQuestInstance instance; - - if (quest != null && quester != null && pm != null) - { - instance = quest.CreateInstance(quester, pm); - instance.ClaimReward = claimReward; - } - else - { - instance = null; - } - - for (int i = 0; i < objectives; ++i) - BaseObjectiveInstance.Deserialize(reader, version, - instance != null && i < instance.Objectives.Length ? instance.Objectives[i] : null); - - instance?.Slice(); - - return instance; - } - } -} +using System; +using System.Collections.Generic; +using Server.Engines.MLQuests.Gumps; +using Server.Engines.MLQuests.Objectives; +using Server.Mobiles; + +namespace Server.Engines.MLQuests +{ + [Flags] + public enum MLQuestInstanceFlags : byte + { + None = 0x00, + ClaimReward = 0x01, + Removed = 0x02, + Failed = 0x04 + } + + public class MLQuestInstance + { + private MLQuestInstanceFlags m_Flags; + private IQuestGiver m_Quester; + + private Timer m_Timer; + + public MLQuestInstance(MLQuest quest, IQuestGiver quester, PlayerMobile player) + { + Quest = quest; + + m_Quester = quester; + QuesterType = quester?.GetType(); + Player = player; + + Accepted = DateTime.UtcNow; + m_Flags = MLQuestInstanceFlags.None; + + Objectives = new BaseObjectiveInstance[quest.Objectives.Count]; + + BaseObjectiveInstance obj; + var timed = false; + + for (var i = 0; i < quest.Objectives.Count; ++i) + { + Objectives[i] = obj = quest.Objectives[i].CreateInstance(this); + + if (obj.IsTimed) + timed = true; + } + + Register(); + + if (timed) + m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5), Slice); + } + + public MLQuest Quest { get; set; } + + public IQuestGiver Quester + { + get => m_Quester; + set + { + m_Quester = value; + QuesterType = value?.GetType(); + } + } + + public Type QuesterType { get; private set; } + + public PlayerMobile Player { get; set; } + + public MLQuestContext PlayerContext => MLQuestSystem.GetOrCreateContext(Player); + + public DateTime Accepted { get; set; } + + public bool ClaimReward + { + get => GetFlag(MLQuestInstanceFlags.ClaimReward); + set => SetFlag(MLQuestInstanceFlags.ClaimReward, value); + } + + public bool Removed + { + get => GetFlag(MLQuestInstanceFlags.Removed); + set => SetFlag(MLQuestInstanceFlags.Removed, value); + } + + public bool Failed + { + get => GetFlag(MLQuestInstanceFlags.Failed); + set => SetFlag(MLQuestInstanceFlags.Failed, value); + } + + public BaseObjectiveInstance[] Objectives { get; set; } + + public bool SkipReportBack => TextDefinition.IsNullOrEmpty(Quest.CompletionMessage); + + private void Register() + { + Quest?.Instances?.Add(this); + + if (Player != null) + PlayerContext.QuestInstances.Add(this); + } + + private void Unregister() + { + Quest?.Instances?.Remove(this); + + if (Player != null) + PlayerContext.QuestInstances.Remove(this); + + Removed = true; + } + + public bool AllowsQuestItem(Item item, Type type) + { + foreach (var objective in Objectives) + if (!objective.Expired && objective.AllowsQuestItem(item, type)) + return true; + + return false; + } + + public bool IsCompleted() + { + var requiresAll = Quest.ObjectiveType == ObjectiveType.All; + + foreach (var obj in Objectives) + { + var complete = obj.IsCompleted(); + + if (complete && !requiresAll) + return true; + if (!complete && requiresAll) + return false; + } + + return requiresAll; + } + + public void CheckComplete() + { + if (IsCompleted()) + { + Player.PlaySound(0x5B5); // public sound + + foreach (var obj in Objectives) + obj.OnQuestCompleted(); + + TextDefinition.SendMessageTo(Player, Quest.CompletionNotice, 0x23); + + /* + * Advance to the ClaimReward=true stage if this quest has no + * completion message to show anyway. This suppresses further + * triggers of CheckComplete. + * + * For quests that require collections, this is done later when + * the player double clicks the quester. + */ + if (!Removed && SkipReportBack && !Quest.RequiresCollection + ) // An OnQuestCompleted can potentially have removed this instance already + ContinueReportBack(false); + } + } + + public void Fail() + { + Failed = true; + } + + private void Slice() + { + if (ClaimReward || Removed) + { + StopTimer(); + return; + } + + var hasAnyFails = false; + var hasAnyLeft = false; + + foreach (var obj in Objectives) + if (!obj.Expired) + { + if (obj.IsTimed && obj.EndTime <= DateTime.UtcNow) + { + Player.SendLocalizedMessage(1072258); // You failed to complete an objective in time! + + obj.Expired = true; + obj.OnExpire(); + + hasAnyFails = true; + } + else + { + hasAnyLeft = true; + } + } + + if (Quest.ObjectiveType == ObjectiveType.All && hasAnyFails || !hasAnyLeft) + Fail(); + + if (!hasAnyLeft) + StopTimer(); + } + + public void SendProgressGump() + { + Player.SendGump(new QuestConversationGump(Quest, Player, Quest.InProgressMessage)); + } + + public void SendRewardOffer() + { + Quest.GetRewards(this); + } + + // TODO: Split next quest stuff from SendRewardGump stuff? + public void SendRewardGump() + { + var nextQuestType = Quest.NextQuest; + + if (nextQuestType != null) + { + ClaimRewards(); // skip reward gump + + if (Removed) // rewards were claimed successfully + { + var nextQuest = MLQuestSystem.FindQuest(nextQuestType); + + nextQuest?.SendOffer(m_Quester, Player); + } + } + else + { + Player.SendGump(new QuestRewardGump(this)); + } + } + + public void SendReportBackGump() + { + if (SkipReportBack) + ContinueReportBack(true); // skip ahead + else + Player.SendGump(new QuestReportBackGump(this)); + } + + public void ContinueReportBack(bool sendRewardGump) + { + // There is a backpack check here on OSI for the rewards as well (even though it's not needed...) + + if (Quest.ObjectiveType == ObjectiveType.All) + { + // TODO: 1115877 - You no longer have the required items to complete this quest. + foreach (var objective in Objectives) + if (!objective.IsCompleted()) + return; + + foreach (var objective in Objectives) + if (!objective.OnBeforeClaimReward()) + return; + + foreach (var objective in Objectives) + objective.OnClaimReward(); + } + else + { + /* The following behavior is unverified, as OSI (currently) has no collect quest requiring + * only one objective to be completed. It is assumed that only one objective is claimed + * (the first completed one), even when multiple are complete. + */ + var complete = false; + + foreach (var objective in Objectives) + if (objective.IsCompleted()) + { + if (objective.OnBeforeClaimReward()) + { + complete = true; + objective.OnClaimReward(); + } + + break; + } + + if (!complete) + return; + } + + ClaimReward = true; + + if (Quest.HasRestartDelay) + PlayerContext.SetDoneQuest(Quest, DateTime.UtcNow + Quest.GetRestartDelay()); + + // This is correct for ObjectiveType.Any as well + foreach (var objective in Objectives) + objective.OnAfterClaimReward(); + + if (sendRewardGump) + SendRewardOffer(); + } + + public void ClaimRewards() + { + if (Quest == null || Player?.Deleted != false || !ClaimReward || Removed) + return; + + var rewards = new List(); + + foreach (var reward in Quest.Rewards) + reward.AddRewardItems(Player, rewards); + + if (rewards.Count != 0) + { + // On OSI a more naive method of checking is used. + // For containers, only the actual container item counts. + var canFit = true; + + foreach (var rewardItem in rewards) + if (!Player.AddToBackpack(rewardItem)) + { + canFit = false; + break; + } + + if (!canFit) + { + foreach (var rewardItem in rewards) + rewardItem.Delete(); + + Player.SendLocalizedMessage( + 1078524 + ); // Your backpack is full. You cannot complete the quest and receive your reward. + return; + } + + foreach (var rewardItem in rewards) + { + var rewardName = rewardItem.Name ?? $"#{rewardItem.LabelNumber}"; + + if (rewardItem.Stackable) + Player.SendLocalizedMessage( + 1115917, + $"{rewardItem.Amount}\t{rewardName}" + ); // You receive a reward: ~1_QUANTITY~ ~2_ITEM~ + else + Player.SendLocalizedMessage(1074360, rewardName); // You receive a reward: ~1_REWARD~ + } + } + + foreach (var objective in Objectives) + objective.OnRewardClaimed(); + + Quest.OnRewardClaimed(this); + + var context = PlayerContext; + + if (Quest.RecordCompletion && !Quest.HasRestartDelay) // Quests with restart delays are logged earlier as per OSI + context.SetDoneQuest(Quest); + + if (Quest.IsChainTriggered) + context.ChainOffers.Remove(Quest); + + var nextQuestType = Quest.NextQuest; + + if (nextQuestType != null) + { + var nextQuest = MLQuestSystem.FindQuest(nextQuestType); + + if (nextQuest != null && !context.ChainOffers.Contains(nextQuest)) + context.ChainOffers.Add(nextQuest); + } + + Remove(); + } + + public void Cancel() + { + Cancel(false); + } + + public void Cancel(bool removeChain) + { + Remove(); + + Player.SendSound(0x5B3); // private sound + + foreach (var obj in Objectives) + obj.OnQuestCancelled(); + + Quest.OnCancel(this); + + if (removeChain) + PlayerContext.ChainOffers.Remove(Quest); + } + + public void Remove() + { + Unregister(); + StopTimer(); + } + + private void StopTimer() + { + if (m_Timer == null) + return; + m_Timer.Stop(); + m_Timer = null; + } + + public void OnQuesterDeleted() + { + foreach (var obj in Objectives) + obj.OnQuesterDeleted(); + + Quest.OnQuesterDeleted(this); + } + + public void OnPlayerDeath() + { + foreach (var obj in Objectives) + obj.OnPlayerDeath(); + + Quest.OnPlayerDeath(this); + } + + private bool GetFlag(MLQuestInstanceFlags flag) => (m_Flags & flag) != 0; + + private void SetFlag(MLQuestInstanceFlags flag, bool value) + { + if (value) + m_Flags |= flag; + else + m_Flags &= ~flag; + } + + public void Serialize(IGenericWriter writer) + { + // Version info is written in MLQuestPersistence.Serialize + + MLQuestSystem.WriteQuestRef(writer, Quest); + + writer.Write(m_Quester?.Deleted != false ? Serial.MinusOne : m_Quester.Serial); + + writer.Write(ClaimReward); + writer.Write(Objectives.Length); + + foreach (var objInstance in Objectives) + objInstance.Serialize(writer); + } + + public static MLQuestInstance Deserialize(IGenericReader reader, int version, PlayerMobile pm) + { + var quest = MLQuestSystem.ReadQuestRef(reader); + + // TODO: Serialize quester TYPE too, the quest giver reference then becomes optional (only for escorts) + var quester = World.FindEntity(reader.ReadUInt()) as IQuestGiver; + + var claimReward = reader.ReadBool(); + var objectives = reader.ReadInt(); + + MLQuestInstance instance; + + if (quest != null && quester != null && pm != null) + { + instance = quest.CreateInstance(quester, pm); + instance.ClaimReward = claimReward; + } + else + { + instance = null; + } + + for (var i = 0; i < objectives; ++i) + BaseObjectiveInstance.Deserialize( + reader, + version, + instance != null && i < instance.Objectives.Length ? instance.Objectives[i] : null + ); + + instance?.Slice(); + + return instance; + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/MLQuestPersistence.cs b/Projects/UOContent/Engines/MLQuests/MLQuestPersistence.cs index cd7ece20e..17455a3ec 100644 --- a/Projects/UOContent/Engines/MLQuests/MLQuestPersistence.cs +++ b/Projects/UOContent/Engines/MLQuests/MLQuestPersistence.cs @@ -1,57 +1,57 @@ -namespace Server.Engines.MLQuests -{ - public class MLQuestPersistence : Item - { - private static MLQuestPersistence m_Instance; - - private MLQuestPersistence() - : base(1) => - Movable = false; - - public MLQuestPersistence(Serial serial) : base(serial) => m_Instance = this; - - public override string DefaultName => "ML quests persistence - Internal"; - - public static void EnsureExistence() - { - m_Instance ??= new MLQuestPersistence(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(2); // version - writer.Write(MLQuestSystem.Contexts.Count); - - foreach (MLQuestContext context in MLQuestSystem.Contexts.Values) - context.Serialize(writer); - - writer.Write(MLQuestSystem.Quests.Count); - - foreach (MLQuest quest in MLQuestSystem.Quests.Values) - MLQuest.Serialize(writer, quest); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - int contexts = reader.ReadInt(); - - for (int i = 0; i < contexts; ++i) - { - MLQuestContext context = new MLQuestContext(reader, version); - - if (context.Owner != null) - MLQuestSystem.Contexts[context.Owner] = context; - } - - int quests = reader.ReadInt(); - - for (int i = 0; i < quests; ++i) - MLQuest.Deserialize(reader, version); - } - } -} +namespace Server.Engines.MLQuests +{ + public class MLQuestPersistence : Item + { + private static MLQuestPersistence m_Instance; + + private MLQuestPersistence() + : base(1) => + Movable = false; + + public MLQuestPersistence(Serial serial) : base(serial) => m_Instance = this; + + public override string DefaultName => "ML quests persistence - Internal"; + + public static void EnsureExistence() + { + m_Instance ??= new MLQuestPersistence(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(2); // version + writer.Write(MLQuestSystem.Contexts.Count); + + foreach (var context in MLQuestSystem.Contexts.Values) + context.Serialize(writer); + + writer.Write(MLQuestSystem.Quests.Count); + + foreach (var quest in MLQuestSystem.Quests.Values) + MLQuest.Serialize(writer, quest); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + var contexts = reader.ReadInt(); + + for (var i = 0; i < contexts; ++i) + { + var context = new MLQuestContext(reader, version); + + if (context.Owner != null) + MLQuestSystem.Contexts[context.Owner] = context; + } + + var quests = reader.ReadInt(); + + for (var i = 0; i < quests; ++i) + MLQuest.Deserialize(reader, version); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/MLQuestSystem.cs b/Projects/UOContent/Engines/MLQuests/MLQuestSystem.cs index 9072ad23d..862c8ae6c 100644 --- a/Projects/UOContent/Engines/MLQuests/MLQuestSystem.cs +++ b/Projects/UOContent/Engines/MLQuests/MLQuestSystem.cs @@ -1,706 +1,722 @@ -using System; -using System.Collections.Generic; -using System.IO; -using Server.Commands; -using Server.Commands.Generic; -using Server.Engines.MLQuests.Gumps; -using Server.Engines.MLQuests.Objectives; -using Server.Gumps; -using Server.Items; -using Server.Mobiles; -using Server.Network; -using Server.Utilities; - -namespace Server.Engines.MLQuests -{ - public static class MLQuestSystem - { - public const int MaxConcurrentQuests = 10; - public const int SpeechColor = 0x3B2; - - public static readonly bool AutoGenerateNew = true; - public static readonly bool Debug = false; - - public static readonly List EmptyList = new List(); - private static readonly List m_EligiblePool = new List(); - - public static bool Enabled { get; private set; } - - static MLQuestSystem() - { - Quests = new Dictionary(); - QuestGivers = new Dictionary>(); - Contexts = new Dictionary(); - - string cfgPath = Path.Combine(Core.BaseDirectory, Path.Combine("Data", "MLQuests.cfg")); - - Type baseQuestType = typeof(MLQuest); - Type baseQuesterType = typeof(IQuestGiver); - - if (File.Exists(cfgPath)) - { - using StreamReader sr = new StreamReader(cfgPath); - string line; - - while ((line = sr.ReadLine()) != null) - { - if (line.Length == 0 || line.StartsWith("#")) - continue; - - string[] split = line.Split('\t'); - - Type type = AssemblyHandler.FindFirstTypeForName(split[0]); - - if (type == null || !baseQuestType.IsAssignableFrom(type)) - { - if (Debug) - Console.WriteLine("Warning: {1} quest type '{0}'", split[0], - type == null ? "Unknown" : "Invalid"); - - continue; - } - - MLQuest quest = null; - - try - { - quest = ActivatorUtil.CreateInstance(type) as MLQuest; - } - catch - { - // ignored - } - - if (quest == null) - continue; - - Register(type, quest); - - for (int i = 1; i < split.Length; ++i) - { - Type questerType = AssemblyHandler.FindFirstTypeForName(split[i]); - - if (questerType == null || !baseQuesterType.IsAssignableFrom(questerType)) - { - if (Debug) - Console.WriteLine("Warning: {1} quester type '{0}'", split[i], - questerType == null ? "Unknown" : "Invalid"); - - continue; - } - - RegisterQuestGiver(quest, questerType); - } - } - } - } - - public static Dictionary Quests { get; } - - public static Dictionary> QuestGivers { get; } - - public static Dictionary Contexts { get; } - - private static void Register(Type type, MLQuest quest) - { - Quests[type] = quest; - } - - private static void RegisterQuestGiver(MLQuest quest, Type questerType) - { - if (!QuestGivers.TryGetValue(questerType, out List questList)) - QuestGivers[questerType] = questList = new List(); - - questList.Add(quest); - } - - public static void Register(MLQuest quest, params Type[] questerTypes) - { - Register(quest.GetType(), quest); - - foreach (Type questerType in questerTypes) - RegisterQuestGiver(quest, questerType); - } - - public static void Initialize() - { - Enabled = ServerConfiguration.GetOrUpdateSetting("questSystem.enableMLQuests", Core.ML); - - if (!Enabled) - return; - - if (AutoGenerateNew) - foreach (MLQuest quest in Quests.Values) - if (quest?.Deserialized == false) - quest.Generate(); - - MLQuestPersistence.EnsureExistence(); - - CommandSystem.Register("MLQuestsInfo", AccessLevel.Administrator, MLQuestsInfo_OnCommand); - CommandSystem.Register("SaveQuest", AccessLevel.Administrator, SaveQuest_OnCommand); - CommandSystem.Register("SaveAllQuests", AccessLevel.Administrator, SaveAllQuests_OnCommand); - CommandSystem.Register("InvalidQuestItems", AccessLevel.Administrator, InvalidQuestItems_OnCommand); - - TargetCommands.Register(new ViewQuestsCommand()); - TargetCommands.Register(new ViewContextCommand()); - - EventSink.QuestGumpRequest += EventSink_QuestGumpRequest; - } - - [Usage("MLQuestsInfo")] - [Description("Displays general information about the ML quest system, or a quest by type name.")] - public static void MLQuestsInfo_OnCommand(CommandEventArgs e) - { - Mobile m = e.Mobile; - - if (e.Length == 0) - { - m.SendMessage("Quest table length: {0}", Quests.Count); - return; - } - - Type index = AssemblyHandler.FindFirstTypeForName(e.GetString(0)); - - if (index == null || !Quests.TryGetValue(index, out MLQuest quest)) - { - m.SendMessage("Invalid quest type name."); - return; - } - - m.SendMessage("Activated: {0}", quest.Activated); - m.SendMessage("Number of objectives: {0}", quest.Objectives.Count); - m.SendMessage("Objective type: {0}", quest.ObjectiveType); - m.SendMessage("Number of active instances: {0}", quest.Instances.Count); - } - - [Usage("SaveQuest [saveEnabled=true]")] - [Description("Allows serialization for a specific quest to be turned on or off.")] - public static void SaveQuest_OnCommand(CommandEventArgs e) - { - Mobile m = e.Mobile; - - if (e.Length == 0 || e.Length > 2) - { - m.SendMessage("Syntax: SaveQuest [saveEnabled=true]"); - return; - } - - Type index = AssemblyHandler.FindFirstTypeForName(e.GetString(0)); - - if (index == null || !Quests.TryGetValue(index, out MLQuest quest)) - { - m.SendMessage("Invalid quest type name."); - return; - } - - bool enable = e.Length == 2 ? e.GetBoolean(1) : true; - - quest.SaveEnabled = enable; - m.SendMessage("Serialization for quest {0} is now {1}.", quest.GetType().Name, enable ? "enabled" : "disabled"); - - if (AutoGenerateNew && !enable) - m.SendMessage( - "Please note that automatic generation of new quests is ON. This quest will be regenerated on the next server start."); - } - - [Usage("SaveAllQuests [saveEnabled=true]")] - [Description("Allows serialization for all quests to be turned on or off.")] - public static void SaveAllQuests_OnCommand(CommandEventArgs e) - { - Mobile m = e.Mobile; - - if (e.Length > 1) - { - m.SendMessage("Syntax: SaveAllQuests [saveEnabled=true]"); - return; - } - - bool enable = e.Length == 1 ? e.GetBoolean(0) : true; - - foreach (MLQuest quest in Quests.Values) - quest.SaveEnabled = enable; - - m.SendMessage("Serialization for all quests is now {0}.", enable ? "enabled" : "disabled"); - - if (AutoGenerateNew && !enable) - m.SendMessage( - "Please note that automatic generation of new quests is ON. All quests will be regenerated on the next server start."); - } - - [Usage("InvalidQuestItems")] - [Description("Provides an overview of all quest items not located in the top-level of a player's backpack.")] - public static void InvalidQuestItems_OnCommand(CommandEventArgs e) - { - Mobile m = e.Mobile; - - List found = new List(); - - foreach (Item item in World.Items.Values) - if (item.QuestItem) - { - if (item.Parent is Backpack pack) - if (pack.Parent is PlayerMobile player && player.Backpack == pack) - continue; - - found.Add(item); - } - - if (found.Count == 0) - m.SendMessage("No matching objects found."); - else - m.SendGump(new InterfaceGump(m, new[] { "Object" }, found, 0, null)); - } - - private static bool FindQuest(IQuestGiver quester, PlayerMobile pm, MLQuestContext context, out MLQuest quest, - out MLQuestInstance entry) - { - quest = null; - entry = null; - - List quests = quester.MLQuests; - Type questerType = quester.GetType(); - - // 1. Check quests in progress with this NPC (overriding deliveries is intended) - if (context != null) - foreach (MLQuest questEntry in quests) - { - MLQuestInstance instance = context.FindInstance(questEntry); - - if (instance != null && (instance.Quester == quester || - (!questEntry.IsEscort && instance.QuesterType == questerType))) - { - entry = instance; - quest = questEntry; - return true; - } - } - - // 2. Check deliveries (overriding chain offers is intended) - if ((entry = HandleDelivery(pm, quester, questerType)) != null) - { - quest = entry.Quest; - return true; - } - - // 3. Check chain quest offers - if (context != null) - foreach (MLQuest questEntry in quests) - if (questEntry.IsChainTriggered && context.ChainOffers.Contains(questEntry)) - { - quest = questEntry; - return true; - } - - // 4. Random quest - quest = RandomStarterQuest(quester, pm, context); - - return quest != null; - } - - public static void OnDoubleClick(IQuestGiver quester, PlayerMobile pm) - { - if (quester.Deleted || !pm.Alive) - return; - - MLQuestContext context = GetContext(pm); - - if (!FindQuest(quester, pm, context, out MLQuest quest, out MLQuestInstance entry)) - { - Tell(quester, pm, 1080107); // I'm sorry, I have nothing for you at this time. - return; - } - - if (entry != null) - { - TurnToFace(quester, pm); - - if (entry.Failed) - return; // Note: OSI sends no gump at all for failed quests, they have to be cancelled in the quest overview - if (entry.ClaimReward) - entry.SendRewardOffer(); - else if (entry.IsCompleted()) - entry.SendReportBackGump(); - else - entry.SendProgressGump(); - } - else if (quest.CanOffer(quester, pm, context, true)) - { - TurnToFace(quester, pm); - - quest.SendOffer(quester, pm); - } - } - - public static bool CanMarkQuestItem(PlayerMobile pm, Item item, Type type) - { - MLQuestContext context = GetContext(pm); - - if (context != null) - foreach (MLQuestInstance quest in context.QuestInstances) - if (!quest.ClaimReward && quest.AllowsQuestItem(item, type)) - return true; - - return false; - } - - private static void OnMarkQuestItem(PlayerMobile pm, Item item, Type type) - { - MLQuestContext context = GetContext(pm); - - if (context == null) - return; - - List instances = context.QuestInstances; - - // We don't foreach because CheckComplete() can potentially modify the MLQuests list - for (int i = instances.Count - 1; i >= 0; --i) - { - MLQuestInstance instance = instances[i]; - - if (instance.ClaimReward) - continue; - - foreach (BaseObjectiveInstance objective in instance.Objectives) - if (!objective.Expired && objective.AllowsQuestItem(item, type)) - { - objective.CheckComplete(); // yes, this can happen multiple times (for multiple quests) - break; - } - } - } - - public static bool MarkQuestItem(PlayerMobile pm, Item item) - { - Type type = item.GetType(); - - if (CanMarkQuestItem(pm, item, type)) - { - item.QuestItem = true; - OnMarkQuestItem(pm, item, type); - - return true; - } - - return false; - } - - public static void HandleSkillGain(PlayerMobile pm, SkillName skill) - { - MLQuestContext context = GetContext(pm); - - if (context == null) - return; - - List instances = context.QuestInstances; - - for (int i = instances.Count - 1; i >= 0; --i) - { - MLQuestInstance instance = instances[i]; - - if (instance.ClaimReward) - continue; - - foreach (BaseObjectiveInstance objective in instance.Objectives) - if (!objective.Expired && objective is GainSkillObjectiveInstance objectiveInstance && - objectiveInstance.Handles(skill)) - { - objectiveInstance.CheckComplete(); - break; - } - } - } - - public static void HandleKill(PlayerMobile pm, Mobile mob) - { - MLQuestContext context = GetContext(pm); - - if (context == null) - return; - - List instances = context.QuestInstances; - - Type type = null; - - for (int i = instances.Count - 1; i >= 0; --i) - { - MLQuestInstance instance = instances[i]; - - if (instance.ClaimReward) - continue; - - /* A kill only counts for a single objective within a quest, - * but it can count for multiple quests. This is something not - * currently observable on OSI, so it is assumed behavior. - */ - foreach (BaseObjectiveInstance objective in instance.Objectives) - if (!objective.Expired && objective is KillObjectiveInstance kill) - { - type ??= mob.GetType(); - - if (kill.AddKill(mob, type)) - { - kill.CheckComplete(); - break; - } - } - } - } - - public static MLQuestInstance HandleDelivery(PlayerMobile pm, IQuestGiver quester, Type questerType) - { - MLQuestContext context = GetContext(pm); - - if (context == null) - return null; - - List instances = context.QuestInstances; - MLQuestInstance deliverInstance = null; - - for (int i = instances.Count - 1; i >= 0; --i) - { - MLQuestInstance instance = instances[i]; - - // Do NOT skip quests on ClaimReward, because the quester still needs the quest ref! - // if (instance.ClaimReward) - // continue; - - foreach (BaseObjectiveInstance objective in instance.Objectives) - // Note: On OSI, expired deliveries can still be completed. Bug? - if (!objective.Expired && objective is DeliverObjectiveInstance deliver && - deliver.IsDestination(quester, questerType)) - { - if (!deliver.HasCompleted) // objective completes only once - { - deliver.HasCompleted = true; - deliver.CheckComplete(); - - // The quest is continued with this NPC (important for chains) - instance.Quester = quester; - } - - deliverInstance ??= instance; - - break; // don't return, we may have to complete more deliveries - } - } - - return deliverInstance; - } - - public static MLQuestContext GetContext(PlayerMobile pm) - { - Contexts.TryGetValue(pm, out MLQuestContext context); - - return context; - } - - public static MLQuestContext GetOrCreateContext(PlayerMobile pm) - { - if (!Contexts.TryGetValue(pm, out MLQuestContext context)) - Contexts[pm] = context = new MLQuestContext(pm); - - return context; - } - - public static void HandleDeath(PlayerMobile pm) - { - MLQuestContext context = GetContext(pm); - - context?.HandleDeath(); - } - - public static void HandleDeletion(PlayerMobile pm) - { - MLQuestContext context = GetContext(pm); - - if (context != null) - { - context.HandleDeletion(); - Contexts.Remove(pm); - } - } - - public static void HandleDeletion(IQuestGiver quester) - { - foreach (MLQuest quest in quester.MLQuests) - { - List instances = quest.Instances; - - for (int i = instances.Count - 1; i >= 0; --i) - { - MLQuestInstance instance = instances[i]; - - if (instance.Quester == quester) - instance.OnQuesterDeleted(); - } - } - } - - public static void EventSink_QuestGumpRequest(Mobile m) - { - if (!Enabled || !(m is PlayerMobile pm)) - return; - - pm.SendGump(new QuestLogGump(pm)); - } - - public static MLQuest RandomStarterQuest(IQuestGiver quester, PlayerMobile pm, MLQuestContext context) - { - List quests = quester.MLQuests; - - if (quests.Count == 0) - return null; - - m_EligiblePool.Clear(); - MLQuest fallback = null; - - foreach (MLQuest quest in quests) - { - if (quest.IsChainTriggered || context?.IsDoingQuest(quest) == true) - continue; - - /* - * Save first quest that reaches the CanOffer call. - * If no quests are valid at all, return this quest for displaying the CanOffer error message. - */ - fallback ??= quest; - - if (quest.CanOffer(quester, pm, context, false)) - m_EligiblePool.Add(quest); - } - - return m_EligiblePool.Count == 0 ? fallback : m_EligiblePool.RandomElement(); - } - - public static void TurnToFace(IQuestGiver quester, Mobile mob) - { - if (quester is Mobile m) - m.Direction = m.GetDirectionTo(mob); - } - - public static void Tell(IQuestGiver quester, PlayerMobile pm, int cliloc) - { - TurnToFace(quester, pm); - - if (quester is Mobile mobile) - mobile.PrivateOverheadMessage(MessageType.Regular, SpeechColor, cliloc, pm.NetState); - else if (quester is Item item) - MessageHelper.SendLocalizedMessageTo(item, pm, cliloc, SpeechColor); - else - pm.SendLocalizedMessage(cliloc); - } - - public static void Tell(IQuestGiver quester, PlayerMobile pm, int cliloc, string args) - { - TurnToFace(quester, pm); - - if (quester is Mobile mobile) - mobile.PrivateOverheadMessage(MessageType.Regular, SpeechColor, cliloc, args, pm.NetState); - else if (quester is Item item) - MessageHelper.SendLocalizedMessageTo(item, pm, cliloc, args, SpeechColor); - else - pm.SendLocalizedMessage(cliloc, args); - } - - public static void Tell(IQuestGiver quester, PlayerMobile pm, string message) - { - TurnToFace(quester, pm); - - if (quester is Mobile mobile) - mobile.PrivateOverheadMessage(MessageType.Regular, SpeechColor, false, message, pm.NetState); - else if (quester is Item item) - MessageHelper.SendMessageTo(item, pm, message, SpeechColor); - else - pm.SendMessage(SpeechColor, message); - } - - public static void TellDef(IQuestGiver quester, PlayerMobile pm, TextDefinition def) - { - if (def == null) - return; - - if (def.Number > 0) - Tell(quester, pm, def.Number); - else if (def.String != null) - Tell(quester, pm, def.String); - } - - public static void WriteQuestRef(IGenericWriter writer, MLQuest quest) - { - writer.Write(quest?.SaveEnabled == true ? quest.GetType().FullName : null); - } - - public static MLQuest ReadQuestRef(IGenericReader reader) - { - string typeName = reader.ReadString(); - - if (typeName == null) - return null; // not serialized - - Type questType = AssemblyHandler.FindFirstTypeForName(typeName); - - if (questType == null) - return null; // no longer a type - - return FindQuest(questType); - } - - public static MLQuest FindQuest(Type questType) - { - Quests.TryGetValue(questType, out MLQuest result); - - return result; - } - - public static List FindQuestList(Type questerType) => QuestGivers.TryGetValue(questerType, out List result) ? result : EmptyList; - - public class ViewQuestsCommand : BaseCommand - { - public ViewQuestsCommand() - { - AccessLevel = AccessLevel.GameMaster; - Supports = CommandSupport.Simple; - Commands = new[] { "ViewQuests" }; - ObjectTypes = ObjectTypes.Mobiles; - Usage = "ViewQuests"; - Description = "Displays a targeted mobile's quest overview."; - } - - public override void Execute(CommandEventArgs e, object obj) - { - Mobile from = e.Mobile; - - if (!(obj is PlayerMobile pm)) - { - LogFailure("That is not a player."); - return; - } - - CommandLogging.WriteLine(from, "{0} {1} viewing quest overview of {2}", from.AccessLevel, - CommandLogging.Format(from), CommandLogging.Format(pm)); - from.SendGump(new QuestLogGump(pm, false)); - } - } - - private class ViewContextCommand : BaseCommand - { - public ViewContextCommand() - { - AccessLevel = AccessLevel.GameMaster; - Supports = CommandSupport.Simple; - Commands = new[] { "ViewMLContext" }; - ObjectTypes = ObjectTypes.Mobiles; - Usage = "ViewMLContext"; - Description = "Opens the ML quest context for a targeted mobile."; - } - - public override void Execute(CommandEventArgs e, object obj) - { - if (!(obj is PlayerMobile pm)) - LogFailure("They have no ML quest context."); - else - e.Mobile.SendGump(new PropertiesGump(e.Mobile, GetOrCreateContext(pm))); - } - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using Server.Commands; +using Server.Commands.Generic; +using Server.Engines.MLQuests.Gumps; +using Server.Engines.MLQuests.Objectives; +using Server.Gumps; +using Server.Items; +using Server.Mobiles; +using Server.Network; +using Server.Utilities; + +namespace Server.Engines.MLQuests +{ + public static class MLQuestSystem + { + public const int MaxConcurrentQuests = 10; + public const int SpeechColor = 0x3B2; + + public static readonly bool AutoGenerateNew = true; + public static readonly bool Debug = false; + + public static readonly List EmptyList = new List(); + private static readonly List m_EligiblePool = new List(); + + static MLQuestSystem() + { + Quests = new Dictionary(); + QuestGivers = new Dictionary>(); + Contexts = new Dictionary(); + + var cfgPath = Path.Combine(Core.BaseDirectory, Path.Combine("Data", "MLQuests.cfg")); + + var baseQuestType = typeof(MLQuest); + var baseQuesterType = typeof(IQuestGiver); + + if (File.Exists(cfgPath)) + { + using var sr = new StreamReader(cfgPath); + string line; + + while ((line = sr.ReadLine()) != null) + { + if (line.Length == 0 || line.StartsWith("#")) + continue; + + var split = line.Split('\t'); + + var type = AssemblyHandler.FindFirstTypeForName(split[0]); + + if (type == null || !baseQuestType.IsAssignableFrom(type)) + { + if (Debug) + Console.WriteLine( + "Warning: {1} quest type '{0}'", + split[0], + type == null ? "Unknown" : "Invalid" + ); + + continue; + } + + MLQuest quest = null; + + try + { + quest = ActivatorUtil.CreateInstance(type) as MLQuest; + } + catch + { + // ignored + } + + if (quest == null) + continue; + + Register(type, quest); + + for (var i = 1; i < split.Length; ++i) + { + var questerType = AssemblyHandler.FindFirstTypeForName(split[i]); + + if (questerType == null || !baseQuesterType.IsAssignableFrom(questerType)) + { + if (Debug) + Console.WriteLine( + "Warning: {1} quester type '{0}'", + split[i], + questerType == null ? "Unknown" : "Invalid" + ); + + continue; + } + + RegisterQuestGiver(quest, questerType); + } + } + } + } + + public static bool Enabled { get; private set; } + + public static Dictionary Quests { get; } + + public static Dictionary> QuestGivers { get; } + + public static Dictionary Contexts { get; } + + private static void Register(Type type, MLQuest quest) + { + Quests[type] = quest; + } + + private static void RegisterQuestGiver(MLQuest quest, Type questerType) + { + if (!QuestGivers.TryGetValue(questerType, out var questList)) + QuestGivers[questerType] = questList = new List(); + + questList.Add(quest); + } + + public static void Register(MLQuest quest, params Type[] questerTypes) + { + Register(quest.GetType(), quest); + + foreach (var questerType in questerTypes) + RegisterQuestGiver(quest, questerType); + } + + public static void Initialize() + { + Enabled = ServerConfiguration.GetOrUpdateSetting("questSystem.enableMLQuests", Core.ML); + + if (!Enabled) + return; + + if (AutoGenerateNew) + foreach (var quest in Quests.Values) + if (quest?.Deserialized == false) + quest.Generate(); + + MLQuestPersistence.EnsureExistence(); + + CommandSystem.Register("MLQuestsInfo", AccessLevel.Administrator, MLQuestsInfo_OnCommand); + CommandSystem.Register("SaveQuest", AccessLevel.Administrator, SaveQuest_OnCommand); + CommandSystem.Register("SaveAllQuests", AccessLevel.Administrator, SaveAllQuests_OnCommand); + CommandSystem.Register("InvalidQuestItems", AccessLevel.Administrator, InvalidQuestItems_OnCommand); + + TargetCommands.Register(new ViewQuestsCommand()); + TargetCommands.Register(new ViewContextCommand()); + + EventSink.QuestGumpRequest += EventSink_QuestGumpRequest; + } + + [Usage("MLQuestsInfo")] + [Description("Displays general information about the ML quest system, or a quest by type name.")] + public static void MLQuestsInfo_OnCommand(CommandEventArgs e) + { + var m = e.Mobile; + + if (e.Length == 0) + { + m.SendMessage("Quest table length: {0}", Quests.Count); + return; + } + + var index = AssemblyHandler.FindFirstTypeForName(e.GetString(0)); + + if (index == null || !Quests.TryGetValue(index, out var quest)) + { + m.SendMessage("Invalid quest type name."); + return; + } + + m.SendMessage("Activated: {0}", quest.Activated); + m.SendMessage("Number of objectives: {0}", quest.Objectives.Count); + m.SendMessage("Objective type: {0}", quest.ObjectiveType); + m.SendMessage("Number of active instances: {0}", quest.Instances.Count); + } + + [Usage("SaveQuest [saveEnabled=true]")] + [Description("Allows serialization for a specific quest to be turned on or off.")] + public static void SaveQuest_OnCommand(CommandEventArgs e) + { + var m = e.Mobile; + + if (e.Length == 0 || e.Length > 2) + { + m.SendMessage("Syntax: SaveQuest [saveEnabled=true]"); + return; + } + + var index = AssemblyHandler.FindFirstTypeForName(e.GetString(0)); + + if (index == null || !Quests.TryGetValue(index, out var quest)) + { + m.SendMessage("Invalid quest type name."); + return; + } + + var enable = e.Length == 2 ? e.GetBoolean(1) : true; + + quest.SaveEnabled = enable; + m.SendMessage("Serialization for quest {0} is now {1}.", quest.GetType().Name, enable ? "enabled" : "disabled"); + + if (AutoGenerateNew && !enable) + m.SendMessage( + "Please note that automatic generation of new quests is ON. This quest will be regenerated on the next server start." + ); + } + + [Usage("SaveAllQuests [saveEnabled=true]")] + [Description("Allows serialization for all quests to be turned on or off.")] + public static void SaveAllQuests_OnCommand(CommandEventArgs e) + { + var m = e.Mobile; + + if (e.Length > 1) + { + m.SendMessage("Syntax: SaveAllQuests [saveEnabled=true]"); + return; + } + + var enable = e.Length == 1 ? e.GetBoolean(0) : true; + + foreach (var quest in Quests.Values) + quest.SaveEnabled = enable; + + m.SendMessage("Serialization for all quests is now {0}.", enable ? "enabled" : "disabled"); + + if (AutoGenerateNew && !enable) + m.SendMessage( + "Please note that automatic generation of new quests is ON. All quests will be regenerated on the next server start." + ); + } + + [Usage("InvalidQuestItems")] + [Description("Provides an overview of all quest items not located in the top-level of a player's backpack.")] + public static void InvalidQuestItems_OnCommand(CommandEventArgs e) + { + var m = e.Mobile; + + var found = new List(); + + foreach (var item in World.Items.Values) + if (item.QuestItem) + { + if (item.Parent is Backpack pack) + if (pack.Parent is PlayerMobile player && player.Backpack == pack) + continue; + + found.Add(item); + } + + if (found.Count == 0) + m.SendMessage("No matching objects found."); + else + m.SendGump(new InterfaceGump(m, new[] { "Object" }, found, 0, null)); + } + + private static bool FindQuest( + IQuestGiver quester, PlayerMobile pm, MLQuestContext context, out MLQuest quest, + out MLQuestInstance entry + ) + { + quest = null; + entry = null; + + var quests = quester.MLQuests; + var questerType = quester.GetType(); + + // 1. Check quests in progress with this NPC (overriding deliveries is intended) + if (context != null) + foreach (var questEntry in quests) + { + var instance = context.FindInstance(questEntry); + + if (instance != null && (instance.Quester == quester || + !questEntry.IsEscort && instance.QuesterType == questerType)) + { + entry = instance; + quest = questEntry; + return true; + } + } + + // 2. Check deliveries (overriding chain offers is intended) + if ((entry = HandleDelivery(pm, quester, questerType)) != null) + { + quest = entry.Quest; + return true; + } + + // 3. Check chain quest offers + if (context != null) + foreach (var questEntry in quests) + if (questEntry.IsChainTriggered && context.ChainOffers.Contains(questEntry)) + { + quest = questEntry; + return true; + } + + // 4. Random quest + quest = RandomStarterQuest(quester, pm, context); + + return quest != null; + } + + public static void OnDoubleClick(IQuestGiver quester, PlayerMobile pm) + { + if (quester.Deleted || !pm.Alive) + return; + + var context = GetContext(pm); + + if (!FindQuest(quester, pm, context, out var quest, out var entry)) + { + Tell(quester, pm, 1080107); // I'm sorry, I have nothing for you at this time. + return; + } + + if (entry != null) + { + TurnToFace(quester, pm); + + if (entry.Failed) + return; // Note: OSI sends no gump at all for failed quests, they have to be cancelled in the quest overview + if (entry.ClaimReward) + entry.SendRewardOffer(); + else if (entry.IsCompleted()) + entry.SendReportBackGump(); + else + entry.SendProgressGump(); + } + else if (quest.CanOffer(quester, pm, context, true)) + { + TurnToFace(quester, pm); + + quest.SendOffer(quester, pm); + } + } + + public static bool CanMarkQuestItem(PlayerMobile pm, Item item, Type type) + { + var context = GetContext(pm); + + if (context != null) + foreach (var quest in context.QuestInstances) + if (!quest.ClaimReward && quest.AllowsQuestItem(item, type)) + return true; + + return false; + } + + private static void OnMarkQuestItem(PlayerMobile pm, Item item, Type type) + { + var context = GetContext(pm); + + if (context == null) + return; + + var instances = context.QuestInstances; + + // We don't foreach because CheckComplete() can potentially modify the MLQuests list + for (var i = instances.Count - 1; i >= 0; --i) + { + var instance = instances[i]; + + if (instance.ClaimReward) + continue; + + foreach (var objective in instance.Objectives) + if (!objective.Expired && objective.AllowsQuestItem(item, type)) + { + objective.CheckComplete(); // yes, this can happen multiple times (for multiple quests) + break; + } + } + } + + public static bool MarkQuestItem(PlayerMobile pm, Item item) + { + var type = item.GetType(); + + if (CanMarkQuestItem(pm, item, type)) + { + item.QuestItem = true; + OnMarkQuestItem(pm, item, type); + + return true; + } + + return false; + } + + public static void HandleSkillGain(PlayerMobile pm, SkillName skill) + { + var context = GetContext(pm); + + if (context == null) + return; + + var instances = context.QuestInstances; + + for (var i = instances.Count - 1; i >= 0; --i) + { + var instance = instances[i]; + + if (instance.ClaimReward) + continue; + + foreach (var objective in instance.Objectives) + if (!objective.Expired && objective is GainSkillObjectiveInstance objectiveInstance && + objectiveInstance.Handles(skill)) + { + objectiveInstance.CheckComplete(); + break; + } + } + } + + public static void HandleKill(PlayerMobile pm, Mobile mob) + { + var context = GetContext(pm); + + if (context == null) + return; + + var instances = context.QuestInstances; + + Type type = null; + + for (var i = instances.Count - 1; i >= 0; --i) + { + var instance = instances[i]; + + if (instance.ClaimReward) + continue; + + /* A kill only counts for a single objective within a quest, + * but it can count for multiple quests. This is something not + * currently observable on OSI, so it is assumed behavior. + */ + foreach (var objective in instance.Objectives) + if (!objective.Expired && objective is KillObjectiveInstance kill) + { + type ??= mob.GetType(); + + if (kill.AddKill(mob, type)) + { + kill.CheckComplete(); + break; + } + } + } + } + + public static MLQuestInstance HandleDelivery(PlayerMobile pm, IQuestGiver quester, Type questerType) + { + var context = GetContext(pm); + + if (context == null) + return null; + + var instances = context.QuestInstances; + MLQuestInstance deliverInstance = null; + + for (var i = instances.Count - 1; i >= 0; --i) + { + var instance = instances[i]; + + // Do NOT skip quests on ClaimReward, because the quester still needs the quest ref! + // if (instance.ClaimReward) + // continue; + + foreach (var objective in instance.Objectives) + // Note: On OSI, expired deliveries can still be completed. Bug? + if (!objective.Expired && objective is DeliverObjectiveInstance deliver && + deliver.IsDestination(quester, questerType)) + { + if (!deliver.HasCompleted) // objective completes only once + { + deliver.HasCompleted = true; + deliver.CheckComplete(); + + // The quest is continued with this NPC (important for chains) + instance.Quester = quester; + } + + deliverInstance ??= instance; + + break; // don't return, we may have to complete more deliveries + } + } + + return deliverInstance; + } + + public static MLQuestContext GetContext(PlayerMobile pm) + { + Contexts.TryGetValue(pm, out var context); + + return context; + } + + public static MLQuestContext GetOrCreateContext(PlayerMobile pm) + { + if (!Contexts.TryGetValue(pm, out var context)) + Contexts[pm] = context = new MLQuestContext(pm); + + return context; + } + + public static void HandleDeath(PlayerMobile pm) + { + var context = GetContext(pm); + + context?.HandleDeath(); + } + + public static void HandleDeletion(PlayerMobile pm) + { + var context = GetContext(pm); + + if (context != null) + { + context.HandleDeletion(); + Contexts.Remove(pm); + } + } + + public static void HandleDeletion(IQuestGiver quester) + { + foreach (var quest in quester.MLQuests) + { + var instances = quest.Instances; + + for (var i = instances.Count - 1; i >= 0; --i) + { + var instance = instances[i]; + + if (instance.Quester == quester) + instance.OnQuesterDeleted(); + } + } + } + + public static void EventSink_QuestGumpRequest(Mobile m) + { + if (!Enabled || !(m is PlayerMobile pm)) + return; + + pm.SendGump(new QuestLogGump(pm)); + } + + public static MLQuest RandomStarterQuest(IQuestGiver quester, PlayerMobile pm, MLQuestContext context) + { + var quests = quester.MLQuests; + + if (quests.Count == 0) + return null; + + m_EligiblePool.Clear(); + MLQuest fallback = null; + + foreach (var quest in quests) + { + if (quest.IsChainTriggered || context?.IsDoingQuest(quest) == true) + continue; + + /* + * Save first quest that reaches the CanOffer call. + * If no quests are valid at all, return this quest for displaying the CanOffer error message. + */ + fallback ??= quest; + + if (quest.CanOffer(quester, pm, context, false)) + m_EligiblePool.Add(quest); + } + + return m_EligiblePool.Count == 0 ? fallback : m_EligiblePool.RandomElement(); + } + + public static void TurnToFace(IQuestGiver quester, Mobile mob) + { + if (quester is Mobile m) + m.Direction = m.GetDirectionTo(mob); + } + + public static void Tell(IQuestGiver quester, PlayerMobile pm, int cliloc) + { + TurnToFace(quester, pm); + + if (quester is Mobile mobile) + mobile.PrivateOverheadMessage(MessageType.Regular, SpeechColor, cliloc, pm.NetState); + else if (quester is Item item) + MessageHelper.SendLocalizedMessageTo(item, pm, cliloc, SpeechColor); + else + pm.SendLocalizedMessage(cliloc); + } + + public static void Tell(IQuestGiver quester, PlayerMobile pm, int cliloc, string args) + { + TurnToFace(quester, pm); + + if (quester is Mobile mobile) + mobile.PrivateOverheadMessage(MessageType.Regular, SpeechColor, cliloc, args, pm.NetState); + else if (quester is Item item) + MessageHelper.SendLocalizedMessageTo(item, pm, cliloc, args, SpeechColor); + else + pm.SendLocalizedMessage(cliloc, args); + } + + public static void Tell(IQuestGiver quester, PlayerMobile pm, string message) + { + TurnToFace(quester, pm); + + if (quester is Mobile mobile) + mobile.PrivateOverheadMessage(MessageType.Regular, SpeechColor, false, message, pm.NetState); + else if (quester is Item item) + MessageHelper.SendMessageTo(item, pm, message, SpeechColor); + else + pm.SendMessage(SpeechColor, message); + } + + public static void TellDef(IQuestGiver quester, PlayerMobile pm, TextDefinition def) + { + if (def == null) + return; + + if (def.Number > 0) + Tell(quester, pm, def.Number); + else if (def.String != null) + Tell(quester, pm, def.String); + } + + public static void WriteQuestRef(IGenericWriter writer, MLQuest quest) + { + writer.Write(quest?.SaveEnabled == true ? quest.GetType().FullName : null); + } + + public static MLQuest ReadQuestRef(IGenericReader reader) + { + var typeName = reader.ReadString(); + + if (typeName == null) + return null; // not serialized + + var questType = AssemblyHandler.FindFirstTypeForName(typeName); + + if (questType == null) + return null; // no longer a type + + return FindQuest(questType); + } + + public static MLQuest FindQuest(Type questType) + { + Quests.TryGetValue(questType, out var result); + + return result; + } + + public static List FindQuestList(Type questerType) => + QuestGivers.TryGetValue(questerType, out var result) ? result : EmptyList; + + public class ViewQuestsCommand : BaseCommand + { + public ViewQuestsCommand() + { + AccessLevel = AccessLevel.GameMaster; + Supports = CommandSupport.Simple; + Commands = new[] { "ViewQuests" }; + ObjectTypes = ObjectTypes.Mobiles; + Usage = "ViewQuests"; + Description = "Displays a targeted mobile's quest overview."; + } + + public override void Execute(CommandEventArgs e, object obj) + { + var from = e.Mobile; + + if (!(obj is PlayerMobile pm)) + { + LogFailure("That is not a player."); + return; + } + + CommandLogging.WriteLine( + from, + "{0} {1} viewing quest overview of {2}", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(pm) + ); + from.SendGump(new QuestLogGump(pm, false)); + } + } + + private class ViewContextCommand : BaseCommand + { + public ViewContextCommand() + { + AccessLevel = AccessLevel.GameMaster; + Supports = CommandSupport.Simple; + Commands = new[] { "ViewMLContext" }; + ObjectTypes = ObjectTypes.Mobiles; + Usage = "ViewMLContext"; + Description = "Opens the ML quest context for a targeted mobile."; + } + + public override void Execute(CommandEventArgs e, object obj) + { + if (!(obj is PlayerMobile pm)) + LogFailure("They have no ML quest context."); + else + e.Mobile.SendGump(new PropertiesGump(e.Mobile, GetOrCreateContext(pm))); + } + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Mobiles/BoonCollector.cs b/Projects/UOContent/Engines/MLQuests/Mobiles/BoonCollector.cs index dce888f06..64f447934 100644 --- a/Projects/UOContent/Engines/MLQuests/Mobiles/BoonCollector.cs +++ b/Projects/UOContent/Engines/MLQuests/Mobiles/BoonCollector.cs @@ -1,414 +1,416 @@ -using System; -using System.Collections.Generic; -using Server.Engines.MLQuests.Definitions; -using Server.Engines.MLQuests.Gumps; -using Server.Items; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.MLQuests.Mobiles -{ - public abstract class DoneQuestCollector : BaseCreature, IRaceChanger - { - private static Type typeOfRaceChangeConfirmGump = typeof(RaceChangeConfirmGump); - - private InternalTimer m_Timer; - - public DoneQuestCollector() - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) - { - } - - public DoneQuestCollector(Serial serial) - : base(serial) - { - } - - public override bool IsInvulnerable => true; - - public abstract TextDefinition[] Offer { get; } - public abstract TextDefinition[] Incomplete { get; } - public abstract TextDefinition[] Complete { get; } - public abstract Type[] Needed { get; } - - public bool CheckComplete(PlayerMobile pm) - { - if (CompletedCount(pm) == Needed.Length) - return true; - - pm.SendLocalizedMessage(1073644); // You must complete all the tasks before proceeding... - return false; - } - - public void ConsumeNeeded(PlayerMobile pm) - { - MLQuestContext context = MLQuestSystem.GetContext(pm); - - if (context != null) - foreach (Type type in Needed) - { - MLQuest quest = MLQuestSystem.FindQuest(type); - - if (quest != null) - context.RemoveDoneQuest(quest); - } - } - - public void OnCancel(PlayerMobile pm) - { - pm.SendLocalizedMessage(1073645); // You may try this again later... - } - - public override void OnDoubleClick(Mobile from) - { - TryTalkTo(from, true); - } - - public override void OnDoubleClickDead(Mobile from) - { - TryTalkTo(from, true); - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (m.Player && InRange(m, 6) && !InRange(oldLocation, 6)) - TryTalkTo(m, false); - - base.OnMovement(m, oldLocation); - } - - public void TryTalkTo(Mobile from, bool fromClick) - { - if (!from.Hidden && !from.HasGump() && - !RaceChangeConfirmGump.IsPending(from.NetState) && CanTalkTo(from)) - TalkTo(from as PlayerMobile); - else if (fromClick) - DenyTalk(from); - } - - public virtual bool CanTalkTo(Mobile from) => true; - - public virtual void DenyTalk(Mobile from) - { - } - - public void TalkTo(PlayerMobile pm) - { - if (pm == null || m_Timer?.Running == true) - return; - - int completed = CompletedCount(pm); - - if (completed == Needed.Length) - { - m_Timer = new InternalTimer(this, pm, Complete, true); - } - else if (completed == 0) - { - m_Timer = new InternalTimer(this, pm, Offer, false); - } - else - { - List conversation = new List(); - conversation.AddRange(Incomplete); - - MLQuestContext context = MLQuestSystem.GetContext(pm); - - if (context != null) - foreach (Type type in Needed) - { - MLQuest quest = MLQuestSystem.FindQuest(type); - - if (quest == null || context.HasDoneQuest(quest)) - continue; - - conversation.Add(quest.Title); - } - - m_Timer = new InternalTimer(this, pm, conversation, false); - } - - m_Timer.Start(); - } - - private int CompletedCount(PlayerMobile pm) - { - MLQuestContext context = MLQuestSystem.GetContext(pm); - - if (context == null) - return 0; - - int result = 0; - - foreach (Type type in Needed) - { - MLQuest quest = MLQuestSystem.FindQuest(type); - - if (quest == null || context.HasDoneQuest(quest)) - ++result; - } - - return result; - } - - public virtual void OnComplete(PlayerMobile pm) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private class InternalTimer : Timer - { - private readonly IList m_Conversation; - private int m_Index; - private readonly bool m_IsComplete; - private readonly DoneQuestCollector m_Owner; - private readonly PlayerMobile m_Target; - - public InternalTimer(DoneQuestCollector owner, PlayerMobile target, IList conversation, - bool isComplete) - : base(TimeSpan.Zero, GetDelay()) - { - m_Owner = owner; - m_Target = target; - m_Conversation = conversation; - m_IsComplete = isComplete; - m_Index = 0; - } - - private static TimeSpan GetDelay() => TimeSpan.FromSeconds(Utility.RandomBool() ? 3 : 4); - - protected override void OnTick() - { - if (m_Owner.Deleted) - { - Stop(); - return; - } - - if (m_Index >= m_Conversation.Count) - { - if (m_IsComplete) - m_Owner.OnComplete(m_Target); - - Stop(); - } - else - { - if (m_Index == 0) - { - if (m_Target.ShowFameTitle && m_Target.Fame >= 10000) - m_Owner.Say(true, $"{(m_Target.Female ? "Lady" : "Lord")} {m_Target.Name}"); - else - m_Owner.Say(true, m_Target.Name); - } - - TextDefinition.PublicOverheadMessage(m_Owner, MessageType.Regular, 0x3B2, m_Conversation[m_Index++]); - Interval = GetDelay(); - } - } - } - } - - public class Darius : DoneQuestCollector - { - private static readonly TextDefinition[] m_Offer = - { - 1073998, // Blessings of Sosaria to you and merry met, friend. - 1073999, // I am glad for your company and wonder if you seek the heritage of your people? I sense within you an elven bloodline -- the purity of which was lost when our brothers and sisters were exiled here in the Rupture. - 1074000, // If it is your desire to reclaim your place amongst the people, you must demonstrate that you understand and embrace the responsibilities expected of you as an elf. - 1074001, // The most basic lessons of our Sosaria are taught by her humblest children. Seek Maul, the great bear, who understands instictively the seasons. - 1074398, // Seek Strongroot, the great treefellow, whose very roots reach to the heart of the world. Seek Enigma, whose wisdom can only be conveyed in riddles and rhymes. Seek Bravehorn, the great hart, who exemplifies the fierce dedication of a protector of his people. - 1074399, // Seek the Huntsman, the centuar tasked with maintaining the balance. And lastly seek Arielle, the pixie, who has perhaps the most important lesson -- not to take yourself too seriously. - 1074400 // Or do none of these things. You must choose your own path in the world, and what use you'll make of your existence. - }; - - private static readonly TextDefinition[] m_Incomplete = - { - 1074002, // You have begun to walk the path of reclaiming your heritage, but you have not learned all the lessons before you. - 1074003 // You yet must perform these services: - }; - - private static readonly TextDefinition[] m_Complete = - { - 1074004, // You have carved a path in history, sought to understand the way from our sage companions. - 1074005, // And now you have returned full circle to the place of your origin within the arms of Mother Sosaria. There is but one thing left to do if you truly wish to embrace your elven heritage. - 1074006, // To be born once more an elf, you must strip of all worldly possessions. Nothing of man or beast much touch your skin. - 1074007 // Then you may step forth into history. - }; - - private static readonly Type[] m_Needed = - { - typeof(Seasons), - typeof(CaretakerOfTheLand), - typeof(WisdomOfTheSphynx), - typeof(DefendingTheHerd), - typeof(TheBalanceOfNature), - typeof(TheJoysOfLife) - }; - - [Constructible] - public Darius() - { - Title = "the wise"; - Race = Race.Elf; - Hue = Race.RandomSkinHue(); - SpeechHue = Utility.RandomDyedHue(); - - AddItem(new WildStaff()); - AddItem(new Sandals(0x1BB)); - AddItem(new GemmedCirclet()); - AddItem(new Tunic(Utility.RandomBrightHue())); - - Utility.AssignRandomHair(this); - - SetStr(40, 50); - SetDex(60, 70); - SetInt(90, 100); // Verified int - } - - public Darius(Serial serial) - : base(serial) - { - } - - public override TextDefinition[] Offer => m_Offer; - public override TextDefinition[] Incomplete => m_Incomplete; - public override TextDefinition[] Complete => m_Complete; - public override Type[] Needed => m_Needed; - - public override string DefaultName => "Darius"; - - public override bool CanTalkTo(Mobile from) => from.Race == Race.Human; - - public override void DenyTalk(Mobile from) - { - from.SendLocalizedMessage(1074017); // He's too busy right now, so he ignores you. - } - - public override void OnComplete(PlayerMobile from) - { - from.SendGump(new RaceChangeConfirmGump(this, from, Race.Elf)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Nedrick : DoneQuestCollector - { - private static readonly TextDefinition[] m_Offer = - { - 1074403, // Greetings, traveler and welcome. - 1074404, // Perhaps you have heard of the service I offer? Perhaps you wish to avail yourself of the opportunity I lay before you. - 1074405, // Elves and humans; we lived together once in peace. Mighty relics that attest to our friendship remain, of course. Yet, memories faded when the Gem was shattered and the world torn asunder. Alone in The Heartwood, our elven brothers and sisters wondered what terrible evil had befallen Sosaria. - 1074406, // Violent change marked the sundering of our ties. We are different -- elves and humans. And yet we are much alike. I can give an elf the chance to walk as a human upon Sosaria. I can undertake the transformation. - 1074407, // But you must prove yourself to me. Humans possess a strength of character and back. Humans are quick-witted and able to pick up a smattering of nearly any talent. Humans are tough both mentally and physically. And of course, humans defend their own -- sometimes with their own lives. - 1074408, // Seek Sledge the Versatile and learn about human ingenuity and creativity. Seek Patricus and demonstrate your integrity and strength. - 1074409, // Seek out a human in need and prove your worth as a defender of humanity. Seek Belulah in Nu'Jelm and heartily challenge the elements in a display of toughness to rival any human. - 1074411 // Or turn away and embrace your heritage. It matters not to me. - }; - - private static readonly TextDefinition[] m_Incomplete = - { - 1074412, // You have made a good start but have more yet to do. - 1074413 // You must yet perform these deeds: - }; - - private static readonly TextDefinition[] m_Complete = - { - 1074410, // You have proven yourself capable and commited and so I will grant you the transformation you seek. - 1074531, // The first time you were born, you entered the world bare of all possessions and concerns. So too as you transform to your new life as a human, you must remove all worldly goods from the touch of your flesh. - 1074532 // I call upon all nearby to witness your rebirth! - }; - - private static readonly Type[] m_Needed = - { - typeof(Ingenuity), - typeof(HeaveHo), - typeof(HumanInNeed), - typeof(AllSeasonAdventurer) - }; - - [Constructible] - public Nedrick() - { - Title = "the iron worker"; - Race = Race.Human; - Hue = Race.RandomSkinHue(); - SpeechHue = Utility.RandomDyedHue(); - - AddItem(new Boots()); - AddItem(new LongPants(Utility.RandomNondyedHue())); - AddItem(new FancyShirt(Utility.RandomNondyedHue())); - - Utility.AssignRandomHair(this); - Utility.AssignRandomFacialHair(this, HairHue); - - SetStr(70, 80); - SetDex(50, 60); - SetInt(60, 70); // Verified int - } - - public Nedrick(Serial serial) - : base(serial) - { - } - - public override TextDefinition[] Offer => m_Offer; - public override TextDefinition[] Incomplete => m_Incomplete; - public override TextDefinition[] Complete => m_Complete; - public override Type[] Needed => m_Needed; - - public override string DefaultName => "Nedrick"; - - public override bool CanTalkTo(Mobile from) => from.Race == Race.Elf; - - public override void DenyTalk(Mobile from) - { - from.SendLocalizedMessage(1074017); // He's too busy right now, so he ignores you. - } - - public override void OnComplete(PlayerMobile from) - { - from.SendGump(new RaceChangeConfirmGump(this, from, Race.Human)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using System.Collections.Generic; +using Server.Engines.MLQuests.Definitions; +using Server.Engines.MLQuests.Gumps; +using Server.Items; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.MLQuests.Mobiles +{ + public abstract class DoneQuestCollector : BaseCreature, IRaceChanger + { + private static Type typeOfRaceChangeConfirmGump = typeof(RaceChangeConfirmGump); + + private InternalTimer m_Timer; + + public DoneQuestCollector() + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + { + } + + public DoneQuestCollector(Serial serial) + : base(serial) + { + } + + public override bool IsInvulnerable => true; + + public abstract TextDefinition[] Offer { get; } + public abstract TextDefinition[] Incomplete { get; } + public abstract TextDefinition[] Complete { get; } + public abstract Type[] Needed { get; } + + public bool CheckComplete(PlayerMobile pm) + { + if (CompletedCount(pm) == Needed.Length) + return true; + + pm.SendLocalizedMessage(1073644); // You must complete all the tasks before proceeding... + return false; + } + + public void ConsumeNeeded(PlayerMobile pm) + { + var context = MLQuestSystem.GetContext(pm); + + if (context != null) + foreach (var type in Needed) + { + var quest = MLQuestSystem.FindQuest(type); + + if (quest != null) + context.RemoveDoneQuest(quest); + } + } + + public void OnCancel(PlayerMobile pm) + { + pm.SendLocalizedMessage(1073645); // You may try this again later... + } + + public override void OnDoubleClick(Mobile from) + { + TryTalkTo(from, true); + } + + public override void OnDoubleClickDead(Mobile from) + { + TryTalkTo(from, true); + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (m.Player && InRange(m, 6) && !InRange(oldLocation, 6)) + TryTalkTo(m, false); + + base.OnMovement(m, oldLocation); + } + + public void TryTalkTo(Mobile from, bool fromClick) + { + if (!from.Hidden && !from.HasGump() && + !RaceChangeConfirmGump.IsPending(from.NetState) && CanTalkTo(from)) + TalkTo(from as PlayerMobile); + else if (fromClick) + DenyTalk(from); + } + + public virtual bool CanTalkTo(Mobile from) => true; + + public virtual void DenyTalk(Mobile from) + { + } + + public void TalkTo(PlayerMobile pm) + { + if (pm == null || m_Timer?.Running == true) + return; + + var completed = CompletedCount(pm); + + if (completed == Needed.Length) + { + m_Timer = new InternalTimer(this, pm, Complete, true); + } + else if (completed == 0) + { + m_Timer = new InternalTimer(this, pm, Offer, false); + } + else + { + var conversation = new List(); + conversation.AddRange(Incomplete); + + var context = MLQuestSystem.GetContext(pm); + + if (context != null) + foreach (var type in Needed) + { + var quest = MLQuestSystem.FindQuest(type); + + if (quest == null || context.HasDoneQuest(quest)) + continue; + + conversation.Add(quest.Title); + } + + m_Timer = new InternalTimer(this, pm, conversation, false); + } + + m_Timer.Start(); + } + + private int CompletedCount(PlayerMobile pm) + { + var context = MLQuestSystem.GetContext(pm); + + if (context == null) + return 0; + + var result = 0; + + foreach (var type in Needed) + { + var quest = MLQuestSystem.FindQuest(type); + + if (quest == null || context.HasDoneQuest(quest)) + ++result; + } + + return result; + } + + public virtual void OnComplete(PlayerMobile pm) + { + } + + 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(); + } + + private class InternalTimer : Timer + { + private readonly IList m_Conversation; + private readonly bool m_IsComplete; + private readonly DoneQuestCollector m_Owner; + private readonly PlayerMobile m_Target; + private int m_Index; + + public InternalTimer( + DoneQuestCollector owner, PlayerMobile target, IList conversation, + bool isComplete + ) + : base(TimeSpan.Zero, GetDelay()) + { + m_Owner = owner; + m_Target = target; + m_Conversation = conversation; + m_IsComplete = isComplete; + m_Index = 0; + } + + private static TimeSpan GetDelay() => TimeSpan.FromSeconds(Utility.RandomBool() ? 3 : 4); + + protected override void OnTick() + { + if (m_Owner.Deleted) + { + Stop(); + return; + } + + if (m_Index >= m_Conversation.Count) + { + if (m_IsComplete) + m_Owner.OnComplete(m_Target); + + Stop(); + } + else + { + if (m_Index == 0) + { + if (m_Target.ShowFameTitle && m_Target.Fame >= 10000) + m_Owner.Say(true, $"{(m_Target.Female ? "Lady" : "Lord")} {m_Target.Name}"); + else + m_Owner.Say(true, m_Target.Name); + } + + TextDefinition.PublicOverheadMessage(m_Owner, MessageType.Regular, 0x3B2, m_Conversation[m_Index++]); + Interval = GetDelay(); + } + } + } + } + + public class Darius : DoneQuestCollector + { + private static readonly TextDefinition[] m_Offer = + { + 1073998, // Blessings of Sosaria to you and merry met, friend. + 1073999, // I am glad for your company and wonder if you seek the heritage of your people? I sense within you an elven bloodline -- the purity of which was lost when our brothers and sisters were exiled here in the Rupture. + 1074000, // If it is your desire to reclaim your place amongst the people, you must demonstrate that you understand and embrace the responsibilities expected of you as an elf. + 1074001, // The most basic lessons of our Sosaria are taught by her humblest children. Seek Maul, the great bear, who understands instictively the seasons. + 1074398, // Seek Strongroot, the great treefellow, whose very roots reach to the heart of the world. Seek Enigma, whose wisdom can only be conveyed in riddles and rhymes. Seek Bravehorn, the great hart, who exemplifies the fierce dedication of a protector of his people. + 1074399, // Seek the Huntsman, the centuar tasked with maintaining the balance. And lastly seek Arielle, the pixie, who has perhaps the most important lesson -- not to take yourself too seriously. + 1074400 // Or do none of these things. You must choose your own path in the world, and what use you'll make of your existence. + }; + + private static readonly TextDefinition[] m_Incomplete = + { + 1074002, // You have begun to walk the path of reclaiming your heritage, but you have not learned all the lessons before you. + 1074003 // You yet must perform these services: + }; + + private static readonly TextDefinition[] m_Complete = + { + 1074004, // You have carved a path in history, sought to understand the way from our sage companions. + 1074005, // And now you have returned full circle to the place of your origin within the arms of Mother Sosaria. There is but one thing left to do if you truly wish to embrace your elven heritage. + 1074006, // To be born once more an elf, you must strip of all worldly possessions. Nothing of man or beast much touch your skin. + 1074007 // Then you may step forth into history. + }; + + private static readonly Type[] m_Needed = + { + typeof(Seasons), + typeof(CaretakerOfTheLand), + typeof(WisdomOfTheSphynx), + typeof(DefendingTheHerd), + typeof(TheBalanceOfNature), + typeof(TheJoysOfLife) + }; + + [Constructible] + public Darius() + { + Title = "the wise"; + Race = Race.Elf; + Hue = Race.RandomSkinHue(); + SpeechHue = Utility.RandomDyedHue(); + + AddItem(new WildStaff()); + AddItem(new Sandals(0x1BB)); + AddItem(new GemmedCirclet()); + AddItem(new Tunic(Utility.RandomBrightHue())); + + Utility.AssignRandomHair(this); + + SetStr(40, 50); + SetDex(60, 70); + SetInt(90, 100); // Verified int + } + + public Darius(Serial serial) + : base(serial) + { + } + + public override TextDefinition[] Offer => m_Offer; + public override TextDefinition[] Incomplete => m_Incomplete; + public override TextDefinition[] Complete => m_Complete; + public override Type[] Needed => m_Needed; + + public override string DefaultName => "Darius"; + + public override bool CanTalkTo(Mobile from) => from.Race == Race.Human; + + public override void DenyTalk(Mobile from) + { + from.SendLocalizedMessage(1074017); // He's too busy right now, so he ignores you. + } + + public override void OnComplete(PlayerMobile from) + { + from.SendGump(new RaceChangeConfirmGump(this, from, Race.Elf)); + } + + 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 class Nedrick : DoneQuestCollector + { + private static readonly TextDefinition[] m_Offer = + { + 1074403, // Greetings, traveler and welcome. + 1074404, // Perhaps you have heard of the service I offer? Perhaps you wish to avail yourself of the opportunity I lay before you. + 1074405, // Elves and humans; we lived together once in peace. Mighty relics that attest to our friendship remain, of course. Yet, memories faded when the Gem was shattered and the world torn asunder. Alone in The Heartwood, our elven brothers and sisters wondered what terrible evil had befallen Sosaria. + 1074406, // Violent change marked the sundering of our ties. We are different -- elves and humans. And yet we are much alike. I can give an elf the chance to walk as a human upon Sosaria. I can undertake the transformation. + 1074407, // But you must prove yourself to me. Humans possess a strength of character and back. Humans are quick-witted and able to pick up a smattering of nearly any talent. Humans are tough both mentally and physically. And of course, humans defend their own -- sometimes with their own lives. + 1074408, // Seek Sledge the Versatile and learn about human ingenuity and creativity. Seek Patricus and demonstrate your integrity and strength. + 1074409, // Seek out a human in need and prove your worth as a defender of humanity. Seek Belulah in Nu'Jelm and heartily challenge the elements in a display of toughness to rival any human. + 1074411 // Or turn away and embrace your heritage. It matters not to me. + }; + + private static readonly TextDefinition[] m_Incomplete = + { + 1074412, // You have made a good start but have more yet to do. + 1074413 // You must yet perform these deeds: + }; + + private static readonly TextDefinition[] m_Complete = + { + 1074410, // You have proven yourself capable and commited and so I will grant you the transformation you seek. + 1074531, // The first time you were born, you entered the world bare of all possessions and concerns. So too as you transform to your new life as a human, you must remove all worldly goods from the touch of your flesh. + 1074532 // I call upon all nearby to witness your rebirth! + }; + + private static readonly Type[] m_Needed = + { + typeof(Ingenuity), + typeof(HeaveHo), + typeof(HumanInNeed), + typeof(AllSeasonAdventurer) + }; + + [Constructible] + public Nedrick() + { + Title = "the iron worker"; + Race = Race.Human; + Hue = Race.RandomSkinHue(); + SpeechHue = Utility.RandomDyedHue(); + + AddItem(new Boots()); + AddItem(new LongPants(Utility.RandomNondyedHue())); + AddItem(new FancyShirt(Utility.RandomNondyedHue())); + + Utility.AssignRandomHair(this); + Utility.AssignRandomFacialHair(this, HairHue); + + SetStr(70, 80); + SetDex(50, 60); + SetInt(60, 70); // Verified int + } + + public Nedrick(Serial serial) + : base(serial) + { + } + + public override TextDefinition[] Offer => m_Offer; + public override TextDefinition[] Incomplete => m_Incomplete; + public override TextDefinition[] Complete => m_Complete; + public override Type[] Needed => m_Needed; + + public override string DefaultName => "Nedrick"; + + public override bool CanTalkTo(Mobile from) => from.Race == Race.Elf; + + public override void DenyTalk(Mobile from) + { + from.SendLocalizedMessage(1074017); // He's too busy right now, so he ignores you. + } + + public override void OnComplete(PlayerMobile from) + { + from.SendGump(new RaceChangeConfirmGump(this, from, Race.Human)); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Mobiles/SirHelper.cs b/Projects/UOContent/Engines/MLQuests/Mobiles/SirHelper.cs index 0d26ba21e..518f5a71a 100644 --- a/Projects/UOContent/Engines/MLQuests/Mobiles/SirHelper.cs +++ b/Projects/UOContent/Engines/MLQuests/Mobiles/SirHelper.cs @@ -1,137 +1,147 @@ -using System; -using Server.Engines.MLQuests.Gumps; -using Server.Gumps; -using Server.Items; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.MLQuests.Mobiles -{ - public class SirHelper : Mage - { - private static readonly Gump m_Gump = new InfoNPCGump(1078029, 1078028); - private static readonly TimeSpan m_ShoutDelay = TimeSpan.FromSeconds(20); - - private static readonly TimeSpan - m_ShoutCooldown = TimeSpan.FromDays(1); // TODO: Verify, could be a lot longer... or until a restart even - - private DateTime m_NextShout; - - [Constructible] - public SirHelper() - { - Title = "the Profession Guide"; // TODO: Don't display in paperdoll - - Hue = 0x83EA; - - Direction = Direction.South; - Frozen = true; - } - - public SirHelper(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "Sir Helper"; - public override bool IsActiveVendor => false; - - public override void InitSBInfo() - { - } - - public override bool GetGender() => false; - - public override void CheckMorph() - { - } - - public override void InitOutfit() - { - HairItemID = 0x203C; - FacialHairItemID = 0x204D; - HairHue = FacialHairHue = 0x8A7; - - AddItem(new Sandals()); - - Item item; - - item = new Cloak(); - item.ItemID = 0x26AD; - item.Hue = 0x455; - AddItem(item); - - item = new Robe(); - item.ItemID = 0x26AE; - item.Hue = 0x4AB; - AddItem(item); - - item = new Backpack(); - item.Movable = false; - AddItem(item); - } - - public override void OnDoubleClick(Mobile from) - { - if (from.CanBeginAction(this)) - { - from.BeginAction(this); - Timer.DelayCall(m_ShoutCooldown, EndLock, from); - } - - MLQuestSystem.TurnToFace(this, from); - from.SendGump(m_Gump); - - // Paperdoll doesn't open - // base.OnDoubleClick( from ); - } - - public override void OnThink() - { - base.OnThink(); - - if (m_NextShout <= DateTime.UtcNow) - { - Packet shoutPacket = null; - - foreach (NetState state in GetClientsInRange(12)) - { - Mobile m = state.Mobile; - - if (m.CanSee(this) && m.InLOS(this) && m.CanBeginAction(this)) - { - shoutPacket ??= Packet.Acquire(new MessageLocalized(Serial, Body, MessageType.Regular, 946, 3, - 1078099, Name, "")); // Double Click On Me For Help! - - state.Send(shoutPacket); - } - } - - Packet.Release(shoutPacket); - - m_NextShout = DateTime.UtcNow + m_ShoutDelay; - } - } - - private void EndLock(Mobile m) - { - m.EndAction(this); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Frozen = true; - } - } -} +using System; +using Server.Engines.MLQuests.Gumps; +using Server.Gumps; +using Server.Items; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.MLQuests.Mobiles +{ + public class SirHelper : Mage + { + private static readonly Gump m_Gump = new InfoNPCGump(1078029, 1078028); + private static readonly TimeSpan m_ShoutDelay = TimeSpan.FromSeconds(20); + + private static readonly TimeSpan + m_ShoutCooldown = TimeSpan.FromDays(1); // TODO: Verify, could be a lot longer... or until a restart even + + private DateTime m_NextShout; + + [Constructible] + public SirHelper() + { + Title = "the Profession Guide"; // TODO: Don't display in paperdoll + + Hue = 0x83EA; + + Direction = Direction.South; + Frozen = true; + } + + public SirHelper(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "Sir Helper"; + public override bool IsActiveVendor => false; + + public override void InitSBInfo() + { + } + + public override bool GetGender() => false; + + public override void CheckMorph() + { + } + + public override void InitOutfit() + { + HairItemID = 0x203C; + FacialHairItemID = 0x204D; + HairHue = FacialHairHue = 0x8A7; + + AddItem(new Sandals()); + + Item item; + + item = new Cloak(); + item.ItemID = 0x26AD; + item.Hue = 0x455; + AddItem(item); + + item = new Robe(); + item.ItemID = 0x26AE; + item.Hue = 0x4AB; + AddItem(item); + + item = new Backpack(); + item.Movable = false; + AddItem(item); + } + + public override void OnDoubleClick(Mobile from) + { + if (from.CanBeginAction(this)) + { + from.BeginAction(this); + Timer.DelayCall(m_ShoutCooldown, EndLock, from); + } + + MLQuestSystem.TurnToFace(this, from); + from.SendGump(m_Gump); + + // Paperdoll doesn't open + // base.OnDoubleClick( from ); + } + + public override void OnThink() + { + base.OnThink(); + + if (m_NextShout <= DateTime.UtcNow) + { + Packet shoutPacket = null; + + foreach (var state in GetClientsInRange(12)) + { + var m = state.Mobile; + + if (m.CanSee(this) && m.InLOS(this) && m.CanBeginAction(this)) + { + shoutPacket ??= Packet.Acquire( + new MessageLocalized( + Serial, + Body, + MessageType.Regular, + 946, + 3, + 1078099, + Name, + "" + ) + ); // Double Click On Me For Help! + + state.Send(shoutPacket); + } + } + + Packet.Release(shoutPacket); + + m_NextShout = DateTime.UtcNow + m_ShoutDelay; + } + } + + private void EndLock(Mobile m) + { + m.EndAction(this); + } + + 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(); + + Frozen = true; + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Objectives/BaseObjective.cs b/Projects/UOContent/Engines/MLQuests/Objectives/BaseObjective.cs index 581afc23b..498236a56 100644 --- a/Projects/UOContent/Engines/MLQuests/Objectives/BaseObjective.cs +++ b/Projects/UOContent/Engines/MLQuests/Objectives/BaseObjective.cs @@ -1,174 +1,174 @@ -using System; -using Server.Gumps; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Objectives -{ - public abstract class BaseObjective - { - public virtual bool IsTimed => false; - public virtual TimeSpan Duration => TimeSpan.Zero; - - public virtual bool CanOffer(IQuestGiver quester, PlayerMobile pm, bool message) => true; - - public abstract void WriteToGump(Gump g, ref int y); - - public virtual BaseObjectiveInstance CreateInstance(MLQuestInstance instance) => null; - } - - public abstract class BaseObjectiveInstance - { - public enum DataType : byte - { - None, - EscortObjective, - KillObjective, - DeliverObjective - } - - public BaseObjectiveInstance(MLQuestInstance instance, BaseObjective obj) - { - Instance = instance; - - if (obj.IsTimed) - EndTime = DateTime.UtcNow + obj.Duration; - } - - public MLQuestInstance Instance { get; } - - public bool IsTimed => EndTime != DateTime.MinValue; - - public DateTime EndTime { get; set; } - - public bool Expired { get; set; } - - public virtual DataType ExtraDataType => DataType.None; - - public virtual void WriteToGump(Gump g, ref int y) - { - if (IsTimed) - WriteTimeRemaining(g, ref y, EndTime > DateTime.UtcNow ? EndTime - DateTime.UtcNow : TimeSpan.Zero); - } - - public static void WriteTimeRemaining(Gump g, ref int y, TimeSpan timeRemaining) - { - g.AddHtmlLocalized(103, y, 120, 16, 1062379, 0x15F90); // Est. time remaining: - g.AddLabel(223, y, 0x481, timeRemaining.TotalSeconds.ToString("F0")); - y += 16; - } - - public virtual bool AllowsQuestItem(Item item, Type type) => false; - - public virtual bool IsCompleted() => false; - - public virtual void CheckComplete() - { - if (IsCompleted()) - { - Instance.Player.PlaySound(0x5B6); // public sound - Instance.CheckComplete(); - } - } - - public virtual void OnQuestAccepted() - { - } - - public virtual void OnQuestCancelled() - { - } - - public virtual void OnQuestCompleted() - { - } - - public virtual bool OnBeforeClaimReward() => true; - - public virtual void OnClaimReward() - { - } - - public virtual void OnAfterClaimReward() - { - } - - public virtual void OnRewardClaimed() - { - } - - public virtual void OnQuesterDeleted() - { - } - - public virtual void OnPlayerDeath() - { - } - - public virtual void OnExpire() - { - } - - public virtual void Serialize(IGenericWriter writer) - { - // Version info is written in MLQuestPersistence.Serialize - - if (IsTimed) - { - writer.Write(true); - writer.WriteDeltaTime(EndTime); - } - else - { - writer.Write(false); - } - - // For type checks on deserialization - // (This way quest objectives can be changed without breaking serialization) - writer.Write((byte)ExtraDataType); - } - - public static void Deserialize(IGenericReader reader, int version, BaseObjectiveInstance objInstance) - { - if (reader.ReadBool()) - { - DateTime endTime = reader.ReadDeltaTime(); - - if (objInstance != null) - objInstance.EndTime = endTime; - } - - DataType extraDataType = (DataType)reader.ReadByte(); - - switch (extraDataType) - { - case DataType.EscortObjective: - { - bool completed = reader.ReadBool(); - - if (objInstance is EscortObjectiveInstance instance) - instance.HasCompleted = completed; - - break; - } - case DataType.KillObjective: - { - int slain = reader.ReadInt(); - - if (objInstance is KillObjectiveInstance instance) - instance.Slain = slain; - - break; - } - case DataType.DeliverObjective: - { - bool completed = reader.ReadBool(); - - if (objInstance is DeliverObjectiveInstance instance) - instance.HasCompleted = completed; - - break; - } - } - } - } -} \ No newline at end of file +using System; +using Server.Gumps; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Objectives +{ + public abstract class BaseObjective + { + public virtual bool IsTimed => false; + public virtual TimeSpan Duration => TimeSpan.Zero; + + public virtual bool CanOffer(IQuestGiver quester, PlayerMobile pm, bool message) => true; + + public abstract void WriteToGump(Gump g, ref int y); + + public virtual BaseObjectiveInstance CreateInstance(MLQuestInstance instance) => null; + } + + public abstract class BaseObjectiveInstance + { + public enum DataType : byte + { + None, + EscortObjective, + KillObjective, + DeliverObjective + } + + public BaseObjectiveInstance(MLQuestInstance instance, BaseObjective obj) + { + Instance = instance; + + if (obj.IsTimed) + EndTime = DateTime.UtcNow + obj.Duration; + } + + public MLQuestInstance Instance { get; } + + public bool IsTimed => EndTime != DateTime.MinValue; + + public DateTime EndTime { get; set; } + + public bool Expired { get; set; } + + public virtual DataType ExtraDataType => DataType.None; + + public virtual void WriteToGump(Gump g, ref int y) + { + if (IsTimed) + WriteTimeRemaining(g, ref y, EndTime > DateTime.UtcNow ? EndTime - DateTime.UtcNow : TimeSpan.Zero); + } + + public static void WriteTimeRemaining(Gump g, ref int y, TimeSpan timeRemaining) + { + g.AddHtmlLocalized(103, y, 120, 16, 1062379, 0x15F90); // Est. time remaining: + g.AddLabel(223, y, 0x481, timeRemaining.TotalSeconds.ToString("F0")); + y += 16; + } + + public virtual bool AllowsQuestItem(Item item, Type type) => false; + + public virtual bool IsCompleted() => false; + + public virtual void CheckComplete() + { + if (IsCompleted()) + { + Instance.Player.PlaySound(0x5B6); // public sound + Instance.CheckComplete(); + } + } + + public virtual void OnQuestAccepted() + { + } + + public virtual void OnQuestCancelled() + { + } + + public virtual void OnQuestCompleted() + { + } + + public virtual bool OnBeforeClaimReward() => true; + + public virtual void OnClaimReward() + { + } + + public virtual void OnAfterClaimReward() + { + } + + public virtual void OnRewardClaimed() + { + } + + public virtual void OnQuesterDeleted() + { + } + + public virtual void OnPlayerDeath() + { + } + + public virtual void OnExpire() + { + } + + public virtual void Serialize(IGenericWriter writer) + { + // Version info is written in MLQuestPersistence.Serialize + + if (IsTimed) + { + writer.Write(true); + writer.WriteDeltaTime(EndTime); + } + else + { + writer.Write(false); + } + + // For type checks on deserialization + // (This way quest objectives can be changed without breaking serialization) + writer.Write((byte)ExtraDataType); + } + + public static void Deserialize(IGenericReader reader, int version, BaseObjectiveInstance objInstance) + { + if (reader.ReadBool()) + { + var endTime = reader.ReadDeltaTime(); + + if (objInstance != null) + objInstance.EndTime = endTime; + } + + var extraDataType = (DataType)reader.ReadByte(); + + switch (extraDataType) + { + case DataType.EscortObjective: + { + var completed = reader.ReadBool(); + + if (objInstance is EscortObjectiveInstance instance) + instance.HasCompleted = completed; + + break; + } + case DataType.KillObjective: + { + var slain = reader.ReadInt(); + + if (objInstance is KillObjectiveInstance instance) + instance.Slain = slain; + + break; + } + case DataType.DeliverObjective: + { + var completed = reader.ReadBool(); + + if (objInstance is DeliverObjectiveInstance instance) + instance.HasCompleted = completed; + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Objectives/CollectObjective.cs b/Projects/UOContent/Engines/MLQuests/Objectives/CollectObjective.cs index 9e9d56162..91b6fff1b 100644 --- a/Projects/UOContent/Engines/MLQuests/Objectives/CollectObjective.cs +++ b/Projects/UOContent/Engines/MLQuests/Objectives/CollectObjective.cs @@ -1,190 +1,190 @@ -using System; -using System.Linq; -using Server.Gumps; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Objectives -{ - public class CollectObjective : BaseObjective - { - public CollectObjective(int amount = 0, Type type = null, TextDefinition name = null) - { - DesiredAmount = amount; - AcceptedType = type; - Name = name; - - if (MLQuestSystem.Debug && ShowDetailed && name?.Number > 0) - { - int itemid = LabelToItemID(name.Number); - - if (itemid <= 0 || itemid > 0x4000) - Console.WriteLine("Warning: cliloc {0} is likely giving the wrong item ID", name.Number); - } - } - - public int DesiredAmount { get; set; } - - public Type AcceptedType { get; set; } - - public TextDefinition Name { get; set; } - - public virtual bool ShowDetailed => true; - - public bool CheckType(Type type) => AcceptedType?.IsAssignableFrom(type) == true; - - public virtual bool CheckItem(Item item) => true; - - public static int LabelToItemID(int label) - { - if (label < 1078872) - return label - 1020000; - return label - 1078872; - } - - public override void WriteToGump(Gump g, ref int y) - { - if (ShowDetailed) - { - string amount = DesiredAmount.ToString(); - - g.AddHtmlLocalized(98, y, 350, 16, 1072205, 0x15F90); // Obtain - g.AddLabel(143, y, 0x481, amount); - - if (Name.Number > 0) - { - g.AddHtmlLocalized(143 + amount.Length * 15, y, 190, 18, Name.Number, 0x77BF); - g.AddItem(350, y, LabelToItemID(Name.Number)); - } - else if (Name.String != null) - { - g.AddLabel(143 + amount.Length * 15, y, 0x481, Name.String); - } - } - else - { - if (Name.Number > 0) - g.AddHtmlLocalized(98, y, 312, 32, Name.Number, 0x15F90); - else if (Name.String != null) - g.AddLabel(98, y, 0x481, Name.String); - } - - y += 32; - } - - public override BaseObjectiveInstance CreateInstance(MLQuestInstance instance) => new CollectObjectiveInstance(this, instance); - } - - public class TimedCollectObjective : CollectObjective - { - public TimedCollectObjective(TimeSpan duration, int amount, Type type, TextDefinition name) - : base(amount, type, name) => - Duration = duration; - - public override bool IsTimed => true; - public override TimeSpan Duration { get; } - } - - public class CollectObjectiveInstance : BaseObjectiveInstance - { - public CollectObjectiveInstance(CollectObjective objective, MLQuestInstance instance) - : base(instance, objective) => - Objective = objective; - - public CollectObjective Objective { get; set; } - - private int GetCurrentTotal() - { - Container pack = Instance.Player.Backpack; - - if (pack == null) - return 0; - - Item[] items = pack.FindItemsByType(Objective.AcceptedType, false); // Note: subclasses are included - return items.Where(item => item.QuestItem && Objective.CheckItem(item)).Sum(item => item.Amount); - } - - public override bool AllowsQuestItem(Item item, Type type) => Objective.CheckType(type) && Objective.CheckItem(item); - - public override bool IsCompleted() => GetCurrentTotal() >= Objective.DesiredAmount; - - public override void OnQuestCancelled() - { - PlayerMobile pm = Instance.Player; - Container pack = pm.Backpack; - - if (pack == null) - return; - - Type checkType = Objective.AcceptedType; - Item[] items = pack.FindItemsByType(checkType, false); - - foreach (Item item in items) - if (item.QuestItem && !MLQuestSystem.CanMarkQuestItem(pm, item, checkType)) // does another quest still need this item? (OSI just unmarks everything) - item.QuestItem = false; - } - - // Should only be called after IsComplete() is checked to be true - public override void OnClaimReward() - { - Container pack = Instance.Player.Backpack; - - if (pack == null) - return; - - // TODO: OSI also counts the item in the cursor? - - Item[] items = pack.FindItemsByType(Objective.AcceptedType, false); - int left = Objective.DesiredAmount; - - foreach (Item item in items) - if (item.QuestItem && Objective.CheckItem(item)) - { - if (left == 0) - return; - - if (item.Amount > left) - { - item.Consume(left); - left = 0; - } - else - { - item.Delete(); - left -= item.Amount; - } - } - } - - public override void OnAfterClaimReward() - { - OnQuestCancelled(); // same thing, clear other quest items - } - - public override void OnExpire() - { - OnQuestCancelled(); - - // No message - } - - public override void WriteToGump(Gump g, ref int y) - { - Objective.WriteToGump(g, ref y); - y -= 16; - - if (Objective.ShowDetailed) - { - base.WriteToGump(g, ref y); - - g.AddHtmlLocalized(103, y, 120, 16, 3000087, 0x15F90); // Total - g.AddLabel(223, y, 0x481, GetCurrentTotal().ToString()); - y += 16; - - g.AddHtmlLocalized(103, y, 120, 16, 1074782, 0x15F90); // Return to - g.AddLabel(223, y, 0x481, QuesterNameAttribute.GetQuesterNameFor(Instance.QuesterType)); - y += 16; - } - } - } -} +using System; +using System.Linq; +using Server.Gumps; + +namespace Server.Engines.MLQuests.Objectives +{ + public class CollectObjective : BaseObjective + { + public CollectObjective(int amount = 0, Type type = null, TextDefinition name = null) + { + DesiredAmount = amount; + AcceptedType = type; + Name = name; + + if (MLQuestSystem.Debug && ShowDetailed && name?.Number > 0) + { + var itemid = LabelToItemID(name.Number); + + if (itemid <= 0 || itemid > 0x4000) + Console.WriteLine("Warning: cliloc {0} is likely giving the wrong item ID", name.Number); + } + } + + public int DesiredAmount { get; set; } + + public Type AcceptedType { get; set; } + + public TextDefinition Name { get; set; } + + public virtual bool ShowDetailed => true; + + public bool CheckType(Type type) => AcceptedType?.IsAssignableFrom(type) == true; + + public virtual bool CheckItem(Item item) => true; + + public static int LabelToItemID(int label) + { + if (label < 1078872) + return label - 1020000; + return label - 1078872; + } + + public override void WriteToGump(Gump g, ref int y) + { + if (ShowDetailed) + { + var amount = DesiredAmount.ToString(); + + g.AddHtmlLocalized(98, y, 350, 16, 1072205, 0x15F90); // Obtain + g.AddLabel(143, y, 0x481, amount); + + if (Name.Number > 0) + { + g.AddHtmlLocalized(143 + amount.Length * 15, y, 190, 18, Name.Number, 0x77BF); + g.AddItem(350, y, LabelToItemID(Name.Number)); + } + else if (Name.String != null) + { + g.AddLabel(143 + amount.Length * 15, y, 0x481, Name.String); + } + } + else + { + if (Name.Number > 0) + g.AddHtmlLocalized(98, y, 312, 32, Name.Number, 0x15F90); + else if (Name.String != null) + g.AddLabel(98, y, 0x481, Name.String); + } + + y += 32; + } + + public override BaseObjectiveInstance CreateInstance(MLQuestInstance instance) => + new CollectObjectiveInstance(this, instance); + } + + public class TimedCollectObjective : CollectObjective + { + public TimedCollectObjective(TimeSpan duration, int amount, Type type, TextDefinition name) + : base(amount, type, name) => + Duration = duration; + + public override bool IsTimed => true; + public override TimeSpan Duration { get; } + } + + public class CollectObjectiveInstance : BaseObjectiveInstance + { + public CollectObjectiveInstance(CollectObjective objective, MLQuestInstance instance) + : base(instance, objective) => + Objective = objective; + + public CollectObjective Objective { get; set; } + + private int GetCurrentTotal() + { + var pack = Instance.Player.Backpack; + + if (pack == null) + return 0; + + var items = pack.FindItemsByType(Objective.AcceptedType, false); // Note: subclasses are included + return items.Where(item => item.QuestItem && Objective.CheckItem(item)).Sum(item => item.Amount); + } + + public override bool AllowsQuestItem(Item item, Type type) => Objective.CheckType(type) && Objective.CheckItem(item); + + public override bool IsCompleted() => GetCurrentTotal() >= Objective.DesiredAmount; + + public override void OnQuestCancelled() + { + var pm = Instance.Player; + var pack = pm.Backpack; + + if (pack == null) + return; + + var checkType = Objective.AcceptedType; + var items = pack.FindItemsByType(checkType, false); + + foreach (var item in items) + if (item.QuestItem && !MLQuestSystem.CanMarkQuestItem(pm, item, checkType) + ) // does another quest still need this item? (OSI just unmarks everything) + item.QuestItem = false; + } + + // Should only be called after IsComplete() is checked to be true + public override void OnClaimReward() + { + var pack = Instance.Player.Backpack; + + if (pack == null) + return; + + // TODO: OSI also counts the item in the cursor? + + var items = pack.FindItemsByType(Objective.AcceptedType, false); + var left = Objective.DesiredAmount; + + foreach (var item in items) + if (item.QuestItem && Objective.CheckItem(item)) + { + if (left == 0) + return; + + if (item.Amount > left) + { + item.Consume(left); + left = 0; + } + else + { + item.Delete(); + left -= item.Amount; + } + } + } + + public override void OnAfterClaimReward() + { + OnQuestCancelled(); // same thing, clear other quest items + } + + public override void OnExpire() + { + OnQuestCancelled(); + + // No message + } + + public override void WriteToGump(Gump g, ref int y) + { + Objective.WriteToGump(g, ref y); + y -= 16; + + if (Objective.ShowDetailed) + { + base.WriteToGump(g, ref y); + + g.AddHtmlLocalized(103, y, 120, 16, 3000087, 0x15F90); // Total + g.AddLabel(223, y, 0x481, GetCurrentTotal().ToString()); + y += 16; + + g.AddHtmlLocalized(103, y, 120, 16, 1074782, 0x15F90); // Return to + g.AddLabel(223, y, 0x481, QuesterNameAttribute.GetQuesterNameFor(Instance.QuesterType)); + y += 16; + } + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Objectives/DeliverObjective.cs b/Projects/UOContent/Engines/MLQuests/Objectives/DeliverObjective.cs index 2d6b7ec31..00c00c44a 100644 --- a/Projects/UOContent/Engines/MLQuests/Objectives/DeliverObjective.cs +++ b/Projects/UOContent/Engines/MLQuests/Objectives/DeliverObjective.cs @@ -1,216 +1,218 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Server.Gumps; -using Server.Items; -using Server.Mobiles; -using Server.Utilities; - -namespace Server.Engines.MLQuests.Objectives -{ - public class DeliverObjective : BaseObjective - { - public DeliverObjective(Type delivery, int amount, TextDefinition name, Type destination, bool spawnsDelivery = true) - { - Delivery = delivery; - Amount = amount; - Name = name; - Destination = destination; - SpawnsDelivery = spawnsDelivery; - - if (MLQuestSystem.Debug && name.Number > 0) - { - int itemid = CollectObjective.LabelToItemID(name.Number); - - if (itemid <= 0 || itemid > 0x4000) - Console.WriteLine("Warning: cliloc {0} is likely giving the wrong item ID", name.Number); - } - } - - public Type Delivery { get; set; } - - public int Amount { get; set; } - - public TextDefinition Name { get; set; } - - public Type Destination { get; set; } - - public bool SpawnsDelivery { get; set; } - - public virtual void SpawnDelivery(Container pack) - { - if (!SpawnsDelivery || pack == null) - return; - - List delivery = new List(); - - for (int i = 0; i < Amount; ++i) - { - if (!(ActivatorUtil.CreateInstance(Delivery) is Item item)) - continue; - - delivery.Add(item); - - if (item.Stackable && Amount > 1) - { - item.Amount = Amount; - break; - } - } - - foreach (Item item in delivery) - pack.DropItem(item); // Confirmed: on OSI items are added even if your pack is full - } - - public override void WriteToGump(Gump g, ref int y) - { - string amount = Amount.ToString(); - - g.AddHtmlLocalized(98, y, 312, 16, 1072207, 0x15F90); // Deliver - g.AddLabel(143, y, 0x481, amount); - - if (Name.Number > 0) - { - g.AddHtmlLocalized(143 + amount.Length * 15, y, 190, 18, Name.Number, 0x77BF); - g.AddItem(350, y, CollectObjective.LabelToItemID(Name.Number)); - } - else if (Name.String != null) - { - g.AddLabel(143 + amount.Length * 15, y, 0x481, Name.String); - } - - y += 32; - - g.AddHtmlLocalized(103, y, 120, 16, 1072379, 0x15F90); // Deliver to - g.AddLabel(223, y, 0x481, QuesterNameAttribute.GetQuesterNameFor(Destination)); - - y += 16; - } - - public override BaseObjectiveInstance CreateInstance(MLQuestInstance instance) => new DeliverObjectiveInstance(this, instance); - } - - public class TimedDeliverObjective : DeliverObjective - { - public TimedDeliverObjective(TimeSpan duration, Type delivery, int amount, TextDefinition name, Type destination, - bool spawnsDelivery = true) - : base(delivery, amount, name, destination, spawnsDelivery) => - Duration = duration; - - public override bool IsTimed => true; - public override TimeSpan Duration { get; } - } - - public class DeliverObjectiveInstance : BaseObjectiveInstance - { - public DeliverObjectiveInstance(DeliverObjective objective, MLQuestInstance instance) - : base(instance, objective) => - Objective = objective; - - public DeliverObjective Objective { get; set; } - - public bool HasCompleted { get; set; } - - public override DataType ExtraDataType => DataType.DeliverObjective; - - public virtual bool IsDestination(IQuestGiver quester, Type type) - { - Type destType = Objective.Destination; - - return destType?.IsAssignableFrom(type) == true; - } - - public override bool IsCompleted() => HasCompleted; - - public override void OnQuestAccepted() - { - Objective.SpawnDelivery(Instance.Player.Backpack); - } - - // This is VERY similar to CollectObjective.GetCurrentTotal - private int GetCurrentTotal() - { - Container pack = Instance.Player.Backpack; - - if (pack == null) - return 0; - - Item[] items = pack.FindItemsByType(Objective.Delivery, false); // Note: subclasses are included - return items.Sum(item => item.Amount); - } - - public override bool OnBeforeClaimReward() - { - PlayerMobile pm = Instance.Player; - - int total = GetCurrentTotal(); - int desired = Objective.Amount; - - if (total < desired) - { - pm.SendLocalizedMessage(1074861); // You do not have everything you need! - pm.SendLocalizedMessage(1074885, $"{total}\t{desired}"); // You have ~1_val~ item(s) but require ~2_val~ - return false; - } - - return true; - } - - // TODO: This is VERY similar to CollectObjective.OnClaimReward - public override void OnClaimReward() - { - Container pack = Instance.Player.Backpack; - - if (pack == null) - return; - - Item[] items = pack.FindItemsByType(Objective.Delivery, false); - int left = Objective.Amount; - - foreach (Item item in items) - { - if (left == 0) - break; - - if (item.Amount > left) - { - item.Consume(left); - left = 0; - } - else - { - item.Delete(); - left -= item.Amount; - } - } - } - - public override void OnQuestCancelled() - { - OnClaimReward(); // same effect - } - - public override void OnExpire() - { - OnQuestCancelled(); - - Instance.Player.SendLocalizedMessage(1074813); // You have failed to complete your delivery. - } - - public override void WriteToGump(Gump g, ref int y) - { - Objective.WriteToGump(g, ref y); - - base.WriteToGump(g, ref y); - - // No extra instance stuff printed for this objective - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(HasCompleted); - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using Server.Gumps; +using Server.Items; +using Server.Utilities; + +namespace Server.Engines.MLQuests.Objectives +{ + public class DeliverObjective : BaseObjective + { + public DeliverObjective(Type delivery, int amount, TextDefinition name, Type destination, bool spawnsDelivery = true) + { + Delivery = delivery; + Amount = amount; + Name = name; + Destination = destination; + SpawnsDelivery = spawnsDelivery; + + if (MLQuestSystem.Debug && name.Number > 0) + { + var itemid = CollectObjective.LabelToItemID(name.Number); + + if (itemid <= 0 || itemid > 0x4000) + Console.WriteLine("Warning: cliloc {0} is likely giving the wrong item ID", name.Number); + } + } + + public Type Delivery { get; set; } + + public int Amount { get; set; } + + public TextDefinition Name { get; set; } + + public Type Destination { get; set; } + + public bool SpawnsDelivery { get; set; } + + public virtual void SpawnDelivery(Container pack) + { + if (!SpawnsDelivery || pack == null) + return; + + var delivery = new List(); + + for (var i = 0; i < Amount; ++i) + { + if (!(ActivatorUtil.CreateInstance(Delivery) is Item item)) + continue; + + delivery.Add(item); + + if (item.Stackable && Amount > 1) + { + item.Amount = Amount; + break; + } + } + + foreach (var item in delivery) + pack.DropItem(item); // Confirmed: on OSI items are added even if your pack is full + } + + public override void WriteToGump(Gump g, ref int y) + { + var amount = Amount.ToString(); + + g.AddHtmlLocalized(98, y, 312, 16, 1072207, 0x15F90); // Deliver + g.AddLabel(143, y, 0x481, amount); + + if (Name.Number > 0) + { + g.AddHtmlLocalized(143 + amount.Length * 15, y, 190, 18, Name.Number, 0x77BF); + g.AddItem(350, y, CollectObjective.LabelToItemID(Name.Number)); + } + else if (Name.String != null) + { + g.AddLabel(143 + amount.Length * 15, y, 0x481, Name.String); + } + + y += 32; + + g.AddHtmlLocalized(103, y, 120, 16, 1072379, 0x15F90); // Deliver to + g.AddLabel(223, y, 0x481, QuesterNameAttribute.GetQuesterNameFor(Destination)); + + y += 16; + } + + public override BaseObjectiveInstance CreateInstance(MLQuestInstance instance) => + new DeliverObjectiveInstance(this, instance); + } + + public class TimedDeliverObjective : DeliverObjective + { + public TimedDeliverObjective( + TimeSpan duration, Type delivery, int amount, TextDefinition name, Type destination, + bool spawnsDelivery = true + ) + : base(delivery, amount, name, destination, spawnsDelivery) => + Duration = duration; + + public override bool IsTimed => true; + public override TimeSpan Duration { get; } + } + + public class DeliverObjectiveInstance : BaseObjectiveInstance + { + public DeliverObjectiveInstance(DeliverObjective objective, MLQuestInstance instance) + : base(instance, objective) => + Objective = objective; + + public DeliverObjective Objective { get; set; } + + public bool HasCompleted { get; set; } + + public override DataType ExtraDataType => DataType.DeliverObjective; + + public virtual bool IsDestination(IQuestGiver quester, Type type) + { + var destType = Objective.Destination; + + return destType?.IsAssignableFrom(type) == true; + } + + public override bool IsCompleted() => HasCompleted; + + public override void OnQuestAccepted() + { + Objective.SpawnDelivery(Instance.Player.Backpack); + } + + // This is VERY similar to CollectObjective.GetCurrentTotal + private int GetCurrentTotal() + { + var pack = Instance.Player.Backpack; + + if (pack == null) + return 0; + + var items = pack.FindItemsByType(Objective.Delivery, false); // Note: subclasses are included + return items.Sum(item => item.Amount); + } + + public override bool OnBeforeClaimReward() + { + var pm = Instance.Player; + + var total = GetCurrentTotal(); + var desired = Objective.Amount; + + if (total < desired) + { + pm.SendLocalizedMessage(1074861); // You do not have everything you need! + pm.SendLocalizedMessage(1074885, $"{total}\t{desired}"); // You have ~1_val~ item(s) but require ~2_val~ + return false; + } + + return true; + } + + // TODO: This is VERY similar to CollectObjective.OnClaimReward + public override void OnClaimReward() + { + var pack = Instance.Player.Backpack; + + if (pack == null) + return; + + var items = pack.FindItemsByType(Objective.Delivery, false); + var left = Objective.Amount; + + foreach (var item in items) + { + if (left == 0) + break; + + if (item.Amount > left) + { + item.Consume(left); + left = 0; + } + else + { + item.Delete(); + left -= item.Amount; + } + } + } + + public override void OnQuestCancelled() + { + OnClaimReward(); // same effect + } + + public override void OnExpire() + { + OnQuestCancelled(); + + Instance.Player.SendLocalizedMessage(1074813); // You have failed to complete your delivery. + } + + public override void WriteToGump(Gump g, ref int y) + { + Objective.WriteToGump(g, ref y); + + base.WriteToGump(g, ref y); + + // No extra instance stuff printed for this objective + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(HasCompleted); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Objectives/EscortObjective.cs b/Projects/UOContent/Engines/MLQuests/Objectives/EscortObjective.cs index 58ff9b3b4..c066d0c1c 100644 --- a/Projects/UOContent/Engines/MLQuests/Objectives/EscortObjective.cs +++ b/Projects/UOContent/Engines/MLQuests/Objectives/EscortObjective.cs @@ -1,260 +1,271 @@ -using System; -using Server.Gumps; -using Server.Misc; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Objectives -{ - public class EscortObjective : BaseObjective - { - public EscortObjective(QuestArea destination = null) => Destination = destination; - - public QuestArea Destination { get; set; } - - public override bool CanOffer(IQuestGiver quester, PlayerMobile pm, bool message) - { - if ((quester is BaseCreature creature && creature.Controlled) || - (quester is BaseEscortable escortable && escortable.IsBeingDeleted)) - return false; - - MLQuestContext context = MLQuestSystem.GetContext(pm); - - if (context != null) - foreach (MLQuestInstance instance in context.QuestInstances) - if (instance.Quest.IsEscort) - { - if (message) - MLQuestSystem.Tell(quester, pm, 500896); // I see you already have an escort. - - return false; - } - - DateTime nextEscort = pm.LastEscortTime + BaseEscortable.EscortDelay; - - if (nextEscort > DateTime.UtcNow) - { - if (message) - { - int minutes = (int)Math.Ceiling((nextEscort - DateTime.UtcNow).TotalMinutes); - - if (minutes == 1) - MLQuestSystem.Tell(quester, pm, "You must rest 1 minute before we set out on this journey."); - else - MLQuestSystem.Tell(quester, pm, 1071195, - minutes.ToString()); // You must rest ~1_minsleft~ minutes before we set out on this journey. - } - - return false; - } - - return true; - } - - public override void WriteToGump(Gump g, ref int y) - { - g.AddHtmlLocalized(98, y, 312, 16, 1072206, 0x15F90); // Escort to - - if (Destination.Name.Number > 0) - g.AddHtmlLocalized(173, y, 312, 20, Destination.Name.Number, 0xFFFFFF); - else if (Destination.Name.String != null) - g.AddLabel(173, y, 0x481, Destination.Name.String); - - y += 16; - } - - public override BaseObjectiveInstance CreateInstance(MLQuestInstance instance) - { - if (instance == null || Destination == null) - return null; - - return new EscortObjectiveInstance(this, instance); - } - } - - public class EscortObjectiveInstance : BaseObjectiveInstance - { - private readonly BaseCreature m_Escort; - private DateTime m_LastSeenEscorter; - private readonly EscortObjective m_Objective; - private Timer m_Timer; - - public EscortObjectiveInstance(EscortObjective objective, MLQuestInstance instance) - : base(instance, objective) - { - m_Objective = objective; - HasCompleted = false; - m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5), CheckDestination); - m_LastSeenEscorter = DateTime.UtcNow; - m_Escort = instance.Quester as BaseCreature; - - if (MLQuestSystem.Debug && m_Escort == null && instance.Quester != null) - Console.WriteLine("Warning: EscortObjective is not supported for type '{0}'", - instance.Quester.GetType().Name); - } - - public bool HasCompleted { get; set; } - - public override DataType ExtraDataType => DataType.EscortObjective; - - public override bool IsCompleted() => HasCompleted; - - private void CheckDestination() - { - if (m_Escort == null || HasCompleted) // Completed by deserialization - { - StopTimer(); - return; - } - - MLQuestInstance instance = Instance; - PlayerMobile pm = instance.Player; - - if (instance.Removed) - { - Abandon(); - } - else if (m_Objective.Destination.Contains(m_Escort)) - { - m_Escort.Say(1042809, - pm.Name); // We have arrived! I thank thee, ~1_PLAYER_NAME~! I have no further need of thy services. Here is thy pay. - - if (pm.Young || m_Escort.Region.IsPartOf("Haven Island")) - Titles.AwardFame(pm, 10, true); - else - VirtueHelper.AwardVirtue(pm, VirtueName.Compassion, - m_Escort is BaseEscortable escortable && escortable.IsPrisoner ? 400 : 200); - - EndFollow(m_Escort); - StopTimer(); - - HasCompleted = true; - CheckComplete(); - - // Auto claim reward - MLQuestSystem.OnDoubleClick(m_Escort, pm); - } - else if (pm.Map != m_Escort.Map || !pm.InRange(m_Escort, 30)) // TODO: verify range - { - if (m_LastSeenEscorter + BaseEscortable.AbandonDelay <= DateTime.UtcNow) - Abandon(); - } - else - { - m_LastSeenEscorter = DateTime.UtcNow; - } - } - - private void StopTimer() - { - if (m_Timer != null) - { - m_Timer.Stop(); - m_Timer = null; - } - } - - public static void BeginFollow(BaseCreature quester, PlayerMobile pm) - { - quester.ControlSlots = 0; - quester.SetControlMaster(pm); - - quester.ActiveSpeed = 0.1; - quester.PassiveSpeed = 0.2; - - quester.ControlOrder = OrderType.Follow; - quester.ControlTarget = pm; - - quester.CantWalk = false; - quester.CurrentSpeed = 0.1; - } - - public static void EndFollow(BaseCreature quester) - { - quester.ActiveSpeed = 0.2; - quester.PassiveSpeed = 1.0; - - quester.ControlOrder = OrderType.None; - quester.ControlTarget = null; - - quester.CurrentSpeed = 1.0; - - quester.SetControlMaster(null); - - (quester as BaseEscortable)?.BeginDelete(); - } - - public override void OnQuestAccepted() - { - MLQuestInstance instance = Instance; - PlayerMobile pm = instance.Player; - - pm.LastEscortTime = DateTime.UtcNow; - - if (m_Escort != null) - BeginFollow(m_Escort, pm); - } - - public void Abandon() - { - StopTimer(); - - MLQuestInstance instance = Instance; - PlayerMobile pm = instance.Player; - - if (m_Escort?.Deleted == false) - { - if (!pm.Alive) - m_Escort.Say(500901); // Ack! My escort has come to haunt me! - else - m_Escort.Say(500902); // My escort seems to have abandoned me! - - EndFollow(m_Escort); - } - - // Note: this sound is sent twice on OSI (once here and once in Cancel()) - // m_Player.SendSound( 0x5B3 ); // private sound - pm.SendLocalizedMessage(1071194); // You have failed your escort quest... - - if (!instance.Removed) - instance.Cancel(); - } - - public override void OnQuesterDeleted() - { - if (IsCompleted() || Instance.Removed) - return; - - Abandon(); - } - - public override void OnPlayerDeath() - { - // Note: OSI also cancels it when the quest is already complete - if (/*IsCompleted() ||*/ Instance.Removed) - return; - - Instance.Cancel(); - } - - public override void OnExpire() - { - Abandon(); - } - - public override void WriteToGump(Gump g, ref int y) - { - m_Objective.WriteToGump(g, ref y); - - base.WriteToGump(g, ref y); - - // No extra instance stuff printed for this objective - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(HasCompleted); - } - } -} +using System; +using Server.Gumps; +using Server.Misc; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Objectives +{ + public class EscortObjective : BaseObjective + { + public EscortObjective(QuestArea destination = null) => Destination = destination; + + public QuestArea Destination { get; set; } + + public override bool CanOffer(IQuestGiver quester, PlayerMobile pm, bool message) + { + if (quester is BaseCreature creature && creature.Controlled || + quester is BaseEscortable escortable && escortable.IsBeingDeleted) + return false; + + var context = MLQuestSystem.GetContext(pm); + + if (context != null) + foreach (var instance in context.QuestInstances) + if (instance.Quest.IsEscort) + { + if (message) + MLQuestSystem.Tell(quester, pm, 500896); // I see you already have an escort. + + return false; + } + + var nextEscort = pm.LastEscortTime + BaseEscortable.EscortDelay; + + if (nextEscort > DateTime.UtcNow) + { + if (message) + { + var minutes = (int)Math.Ceiling((nextEscort - DateTime.UtcNow).TotalMinutes); + + if (minutes == 1) + MLQuestSystem.Tell(quester, pm, "You must rest 1 minute before we set out on this journey."); + else + MLQuestSystem.Tell( + quester, + pm, + 1071195, + minutes.ToString() + ); // You must rest ~1_minsleft~ minutes before we set out on this journey. + } + + return false; + } + + return true; + } + + public override void WriteToGump(Gump g, ref int y) + { + g.AddHtmlLocalized(98, y, 312, 16, 1072206, 0x15F90); // Escort to + + if (Destination.Name.Number > 0) + g.AddHtmlLocalized(173, y, 312, 20, Destination.Name.Number, 0xFFFFFF); + else if (Destination.Name.String != null) + g.AddLabel(173, y, 0x481, Destination.Name.String); + + y += 16; + } + + public override BaseObjectiveInstance CreateInstance(MLQuestInstance instance) + { + if (instance == null || Destination == null) + return null; + + return new EscortObjectiveInstance(this, instance); + } + } + + public class EscortObjectiveInstance : BaseObjectiveInstance + { + private readonly BaseCreature m_Escort; + private readonly EscortObjective m_Objective; + private DateTime m_LastSeenEscorter; + private Timer m_Timer; + + public EscortObjectiveInstance(EscortObjective objective, MLQuestInstance instance) + : base(instance, objective) + { + m_Objective = objective; + HasCompleted = false; + m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5), CheckDestination); + m_LastSeenEscorter = DateTime.UtcNow; + m_Escort = instance.Quester as BaseCreature; + + if (MLQuestSystem.Debug && m_Escort == null && instance.Quester != null) + Console.WriteLine( + "Warning: EscortObjective is not supported for type '{0}'", + instance.Quester.GetType().Name + ); + } + + public bool HasCompleted { get; set; } + + public override DataType ExtraDataType => DataType.EscortObjective; + + public override bool IsCompleted() => HasCompleted; + + private void CheckDestination() + { + if (m_Escort == null || HasCompleted) // Completed by deserialization + { + StopTimer(); + return; + } + + var instance = Instance; + var pm = instance.Player; + + if (instance.Removed) + { + Abandon(); + } + else if (m_Objective.Destination.Contains(m_Escort)) + { + m_Escort.Say( + 1042809, + pm.Name + ); // We have arrived! I thank thee, ~1_PLAYER_NAME~! I have no further need of thy services. Here is thy pay. + + if (pm.Young || m_Escort.Region.IsPartOf("Haven Island")) + Titles.AwardFame(pm, 10, true); + else + VirtueHelper.AwardVirtue( + pm, + VirtueName.Compassion, + m_Escort is BaseEscortable escortable && escortable.IsPrisoner ? 400 : 200 + ); + + EndFollow(m_Escort); + StopTimer(); + + HasCompleted = true; + CheckComplete(); + + // Auto claim reward + MLQuestSystem.OnDoubleClick(m_Escort, pm); + } + else if (pm.Map != m_Escort.Map || !pm.InRange(m_Escort, 30)) // TODO: verify range + { + if (m_LastSeenEscorter + BaseEscortable.AbandonDelay <= DateTime.UtcNow) + Abandon(); + } + else + { + m_LastSeenEscorter = DateTime.UtcNow; + } + } + + private void StopTimer() + { + if (m_Timer != null) + { + m_Timer.Stop(); + m_Timer = null; + } + } + + public static void BeginFollow(BaseCreature quester, PlayerMobile pm) + { + quester.ControlSlots = 0; + quester.SetControlMaster(pm); + + quester.ActiveSpeed = 0.1; + quester.PassiveSpeed = 0.2; + + quester.ControlOrder = OrderType.Follow; + quester.ControlTarget = pm; + + quester.CantWalk = false; + quester.CurrentSpeed = 0.1; + } + + public static void EndFollow(BaseCreature quester) + { + quester.ActiveSpeed = 0.2; + quester.PassiveSpeed = 1.0; + + quester.ControlOrder = OrderType.None; + quester.ControlTarget = null; + + quester.CurrentSpeed = 1.0; + + quester.SetControlMaster(null); + + (quester as BaseEscortable)?.BeginDelete(); + } + + public override void OnQuestAccepted() + { + var instance = Instance; + var pm = instance.Player; + + pm.LastEscortTime = DateTime.UtcNow; + + if (m_Escort != null) + BeginFollow(m_Escort, pm); + } + + public void Abandon() + { + StopTimer(); + + var instance = Instance; + var pm = instance.Player; + + if (m_Escort?.Deleted == false) + { + if (!pm.Alive) + m_Escort.Say(500901); // Ack! My escort has come to haunt me! + else + m_Escort.Say(500902); // My escort seems to have abandoned me! + + EndFollow(m_Escort); + } + + // Note: this sound is sent twice on OSI (once here and once in Cancel()) + // m_Player.SendSound( 0x5B3 ); // private sound + pm.SendLocalizedMessage(1071194); // You have failed your escort quest... + + if (!instance.Removed) + instance.Cancel(); + } + + public override void OnQuesterDeleted() + { + if (IsCompleted() || Instance.Removed) + return; + + Abandon(); + } + + public override void OnPlayerDeath() + { + // Note: OSI also cancels it when the quest is already complete + if ( /*IsCompleted() ||*/ Instance.Removed) + return; + + Instance.Cancel(); + } + + public override void OnExpire() + { + Abandon(); + } + + public override void WriteToGump(Gump g, ref int y) + { + m_Objective.WriteToGump(g, ref y); + + base.WriteToGump(g, ref y); + + // No extra instance stuff printed for this objective + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(HasCompleted); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Objectives/GainSkillObjective.cs b/Projects/UOContent/Engines/MLQuests/Objectives/GainSkillObjective.cs index 4ff6a9e6a..7bae273c0 100644 --- a/Projects/UOContent/Engines/MLQuests/Objectives/GainSkillObjective.cs +++ b/Projects/UOContent/Engines/MLQuests/Objectives/GainSkillObjective.cs @@ -1,151 +1,156 @@ -using System; -using Server.Gumps; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Objectives -{ - [Flags] - public enum GainSkillObjectiveFlags : byte - { - None = 0x00, - UseReal = 0x01, - Accelerate = 0x02 - } - - public class GainSkillObjective : BaseObjective - { - private GainSkillObjectiveFlags m_Flags; - - public GainSkillObjective(SkillName skill = SkillName.Alchemy, int thresholdFixed = 0, bool useReal = false, bool accelerate = false) - { - Skill = skill; - ThresholdFixed = thresholdFixed; - m_Flags = GainSkillObjectiveFlags.None; - - if (useReal) - m_Flags |= GainSkillObjectiveFlags.UseReal; - - if (accelerate) - m_Flags |= GainSkillObjectiveFlags.Accelerate; - } - - public SkillName Skill { get; set; } - - public int ThresholdFixed { get; set; } - - public bool UseReal - { - get => GetFlag(GainSkillObjectiveFlags.UseReal); - set => SetFlag(GainSkillObjectiveFlags.UseReal, value); - } - - public bool Accelerate - { - get => GetFlag(GainSkillObjectiveFlags.Accelerate); - set => SetFlag(GainSkillObjectiveFlags.Accelerate, value); - } - - public override bool CanOffer(IQuestGiver quester, PlayerMobile pm, bool message) - { - Skill skill = pm.Skills[Skill]; - - if ((UseReal ? skill.Fixed : skill.BaseFixedPoint) >= ThresholdFixed) - { - if (message) - MLQuestSystem.Tell(quester, pm, 1077772); // I cannot teach you, for you know all I can teach! - - return false; - } - - return true; - } - - public override void WriteToGump(Gump g, ref int y) - { - int skillLabel = AosSkillBonuses.GetLabel(Skill); - string args; - - args = ThresholdFixed % 10 == 0 ? $"#{skillLabel}\t{ThresholdFixed / 10}" : $"#{skillLabel}\t{(double)ThresholdFixed / 10:0.0}"; - - g.AddHtmlLocalized(98, y, 312, 16, 1077485, args, 0x15F90); // Increase ~1_SKILL~ to ~2_VALUE~ - y += 16; - } - - public override BaseObjectiveInstance CreateInstance(MLQuestInstance instance) => new GainSkillObjectiveInstance(this, instance); - - private bool GetFlag(GainSkillObjectiveFlags flag) => (m_Flags & flag) != 0; - - private void SetFlag(GainSkillObjectiveFlags flag, bool value) - { - if (value) - m_Flags |= flag; - else - m_Flags &= ~flag; - } - } - - // On OSI, once this is complete, it will *stay* complete, even if you lower your skill again - public class GainSkillObjectiveInstance : BaseObjectiveInstance - { - public GainSkillObjectiveInstance(GainSkillObjective objective, MLQuestInstance instance) - : base(instance, objective) => - Objective = objective; - - public GainSkillObjective Objective { get; set; } - - public bool Handles(SkillName skill) => Objective.Skill == skill; - - public override bool IsCompleted() - { - PlayerMobile pm = Instance.Player; - - int valueFixed = Objective.UseReal - ? pm.Skills[Objective.Skill].Fixed - : pm.Skills[Objective.Skill].BaseFixedPoint; - - return valueFixed >= Objective.ThresholdFixed; - } - - // TODO: This may interfere with scrolls, or even quests among each other - // How does OSI deal with this? - public override void OnQuestAccepted() - { - if (!Objective.Accelerate) - return; - - PlayerMobile pm = Instance.Player; - - pm.AcceleratedSkill = Objective.Skill; - pm.AcceleratedStart = DateTime.UtcNow + TimeSpan.FromMinutes(15); // TODO: Is there a max duration? - } - - public override void OnQuestCancelled() - { - if (!Objective.Accelerate) - return; - - PlayerMobile pm = Instance.Player; - - pm.AcceleratedStart = DateTime.UtcNow; - pm.PlaySound(0x100); - } - - public override void OnQuestCompleted() - { - OnQuestCancelled(); - } - - public override void WriteToGump(Gump g, ref int y) - { - Objective.WriteToGump(g, ref y); - - base.WriteToGump(g, ref y); - - if (IsCompleted()) - { - g.AddHtmlLocalized(113, y, 312, 20, 1055121, 0xFFFFFF); // Complete - y += 16; - } - } - } -} +using System; +using Server.Gumps; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Objectives +{ + [Flags] + public enum GainSkillObjectiveFlags : byte + { + None = 0x00, + UseReal = 0x01, + Accelerate = 0x02 + } + + public class GainSkillObjective : BaseObjective + { + private GainSkillObjectiveFlags m_Flags; + + public GainSkillObjective( + SkillName skill = SkillName.Alchemy, int thresholdFixed = 0, bool useReal = false, bool accelerate = false + ) + { + Skill = skill; + ThresholdFixed = thresholdFixed; + m_Flags = GainSkillObjectiveFlags.None; + + if (useReal) + m_Flags |= GainSkillObjectiveFlags.UseReal; + + if (accelerate) + m_Flags |= GainSkillObjectiveFlags.Accelerate; + } + + public SkillName Skill { get; set; } + + public int ThresholdFixed { get; set; } + + public bool UseReal + { + get => GetFlag(GainSkillObjectiveFlags.UseReal); + set => SetFlag(GainSkillObjectiveFlags.UseReal, value); + } + + public bool Accelerate + { + get => GetFlag(GainSkillObjectiveFlags.Accelerate); + set => SetFlag(GainSkillObjectiveFlags.Accelerate, value); + } + + public override bool CanOffer(IQuestGiver quester, PlayerMobile pm, bool message) + { + var skill = pm.Skills[Skill]; + + if ((UseReal ? skill.Fixed : skill.BaseFixedPoint) >= ThresholdFixed) + { + if (message) + MLQuestSystem.Tell(quester, pm, 1077772); // I cannot teach you, for you know all I can teach! + + return false; + } + + return true; + } + + public override void WriteToGump(Gump g, ref int y) + { + var skillLabel = AosSkillBonuses.GetLabel(Skill); + string args; + + args = ThresholdFixed % 10 == 0 + ? $"#{skillLabel}\t{ThresholdFixed / 10}" + : $"#{skillLabel}\t{(double)ThresholdFixed / 10:0.0}"; + + g.AddHtmlLocalized(98, y, 312, 16, 1077485, args, 0x15F90); // Increase ~1_SKILL~ to ~2_VALUE~ + y += 16; + } + + public override BaseObjectiveInstance CreateInstance(MLQuestInstance instance) => + new GainSkillObjectiveInstance(this, instance); + + private bool GetFlag(GainSkillObjectiveFlags flag) => (m_Flags & flag) != 0; + + private void SetFlag(GainSkillObjectiveFlags flag, bool value) + { + if (value) + m_Flags |= flag; + else + m_Flags &= ~flag; + } + } + + // On OSI, once this is complete, it will *stay* complete, even if you lower your skill again + public class GainSkillObjectiveInstance : BaseObjectiveInstance + { + public GainSkillObjectiveInstance(GainSkillObjective objective, MLQuestInstance instance) + : base(instance, objective) => + Objective = objective; + + public GainSkillObjective Objective { get; set; } + + public bool Handles(SkillName skill) => Objective.Skill == skill; + + public override bool IsCompleted() + { + var pm = Instance.Player; + + var valueFixed = Objective.UseReal + ? pm.Skills[Objective.Skill].Fixed + : pm.Skills[Objective.Skill].BaseFixedPoint; + + return valueFixed >= Objective.ThresholdFixed; + } + + // TODO: This may interfere with scrolls, or even quests among each other + // How does OSI deal with this? + public override void OnQuestAccepted() + { + if (!Objective.Accelerate) + return; + + var pm = Instance.Player; + + pm.AcceleratedSkill = Objective.Skill; + pm.AcceleratedStart = DateTime.UtcNow + TimeSpan.FromMinutes(15); // TODO: Is there a max duration? + } + + public override void OnQuestCancelled() + { + if (!Objective.Accelerate) + return; + + var pm = Instance.Player; + + pm.AcceleratedStart = DateTime.UtcNow; + pm.PlaySound(0x100); + } + + public override void OnQuestCompleted() + { + OnQuestCancelled(); + } + + public override void WriteToGump(Gump g, ref int y) + { + Objective.WriteToGump(g, ref y); + + base.WriteToGump(g, ref y); + + if (IsCompleted()) + { + g.AddHtmlLocalized(113, y, 312, 20, 1055121, 0xFFFFFF); // Complete + y += 16; + } + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Objectives/KillObjective.cs b/Projects/UOContent/Engines/MLQuests/Objectives/KillObjective.cs index 78cc1e010..1d3cfcafa 100644 --- a/Projects/UOContent/Engines/MLQuests/Objectives/KillObjective.cs +++ b/Projects/UOContent/Engines/MLQuests/Objectives/KillObjective.cs @@ -1,129 +1,132 @@ -using System; -using Server.Gumps; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Objectives -{ - public class KillObjective : BaseObjective - { -public KillObjective( - int amount = 0, Type[] types = null, TextDefinition name = null, QuestArea area = null) - { - DesiredAmount = amount; - AcceptedTypes = types; - Name = name; - Area = area; - } - - public int DesiredAmount { get; set; } - - public Type[] AcceptedTypes { get; set; } - - public TextDefinition Name { get; set; } - - public QuestArea Area { get; set; } - - public override void WriteToGump(Gump g, ref int y) - { - string amount = DesiredAmount.ToString(); - - g.AddHtmlLocalized(98, y, 312, 16, 1072204, 0x15F90); // Slay - g.AddLabel(133, y, 0x481, amount); - - if (Name.Number > 0) - g.AddHtmlLocalized(133 + amount.Length * 15, y, 190, 18, Name.Number, 0x77BF); - else if (Name.String != null) - g.AddLabel(133 + amount.Length * 15, y, 0x481, Name.String); - - y += 16; - - if (Area != null) - { - g.AddHtmlLocalized(103, y, 312, 20, 1018327, 0x15F90); // Location - - if (Area.Name.Number > 0) - g.AddHtmlLocalized(223, y, 312, 20, Area.Name.Number, 0xFFFFFF); - else if (Area.Name.String != null) - g.AddLabel(223, y, 0x481, Area.Name.String); - - y += 16; - } - } - - public override BaseObjectiveInstance CreateInstance(MLQuestInstance instance) => new KillObjectiveInstance(this, instance); - } - - public class TimedKillObjective : KillObjective - { - public TimedKillObjective(TimeSpan duration, int amount, Type[] types, TextDefinition name, QuestArea area = null) - : base(amount, types, name, area) => - Duration = duration; - - public override bool IsTimed => true; - public override TimeSpan Duration { get; } - } - - public class KillObjectiveInstance : BaseObjectiveInstance - { - public KillObjectiveInstance(KillObjective objective, MLQuestInstance instance) - : base(instance, objective) - { - Objective = objective; - Slain = 0; - } - - public KillObjective Objective { get; set; } - - public int Slain { get; set; } - - public override DataType ExtraDataType => DataType.KillObjective; - - public bool AddKill(Mobile mob, Type type) - { - int desired = Objective.DesiredAmount; - - foreach (Type acceptedType in Objective.AcceptedTypes) - if (acceptedType.IsAssignableFrom(type)) - { - if (Objective.Area?.Contains(mob) == false) - return false; - - PlayerMobile pm = Instance.Player; - - if (++Slain >= desired) - pm.SendLocalizedMessage(1075050); // You have killed all the required quest creatures of this type. - else - pm.SendLocalizedMessage(1075051, - (desired - Slain).ToString()); // You have killed a quest creature. ~1_val~ more left. - - return true; - } - - return false; - } - - public override bool IsCompleted() => Slain >= Objective.DesiredAmount; - - public override void WriteToGump(Gump g, ref int y) - { - Objective.WriteToGump(g, ref y); - - base.WriteToGump(g, ref y); - - g.AddHtmlLocalized(103, y, 120, 16, 3000087, 0x15F90); // Total - g.AddLabel(223, y, 0x481, Slain.ToString()); - y += 16; - - g.AddHtmlLocalized(103, y, 120, 16, 1074782, 0x15F90); // Return to - g.AddLabel(223, y, 0x481, QuesterNameAttribute.GetQuesterNameFor(Instance.QuesterType)); - y += 16; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(Slain); - } - } -} +using System; +using Server.Gumps; + +namespace Server.Engines.MLQuests.Objectives +{ + public class KillObjective : BaseObjective + { + public KillObjective( + int amount = 0, Type[] types = null, TextDefinition name = null, QuestArea area = null + ) + { + DesiredAmount = amount; + AcceptedTypes = types; + Name = name; + Area = area; + } + + public int DesiredAmount { get; set; } + + public Type[] AcceptedTypes { get; set; } + + public TextDefinition Name { get; set; } + + public QuestArea Area { get; set; } + + public override void WriteToGump(Gump g, ref int y) + { + var amount = DesiredAmount.ToString(); + + g.AddHtmlLocalized(98, y, 312, 16, 1072204, 0x15F90); // Slay + g.AddLabel(133, y, 0x481, amount); + + if (Name.Number > 0) + g.AddHtmlLocalized(133 + amount.Length * 15, y, 190, 18, Name.Number, 0x77BF); + else if (Name.String != null) + g.AddLabel(133 + amount.Length * 15, y, 0x481, Name.String); + + y += 16; + + if (Area != null) + { + g.AddHtmlLocalized(103, y, 312, 20, 1018327, 0x15F90); // Location + + if (Area.Name.Number > 0) + g.AddHtmlLocalized(223, y, 312, 20, Area.Name.Number, 0xFFFFFF); + else if (Area.Name.String != null) + g.AddLabel(223, y, 0x481, Area.Name.String); + + y += 16; + } + } + + public override BaseObjectiveInstance CreateInstance(MLQuestInstance instance) => + new KillObjectiveInstance(this, instance); + } + + public class TimedKillObjective : KillObjective + { + public TimedKillObjective(TimeSpan duration, int amount, Type[] types, TextDefinition name, QuestArea area = null) + : base(amount, types, name, area) => + Duration = duration; + + public override bool IsTimed => true; + public override TimeSpan Duration { get; } + } + + public class KillObjectiveInstance : BaseObjectiveInstance + { + public KillObjectiveInstance(KillObjective objective, MLQuestInstance instance) + : base(instance, objective) + { + Objective = objective; + Slain = 0; + } + + public KillObjective Objective { get; set; } + + public int Slain { get; set; } + + public override DataType ExtraDataType => DataType.KillObjective; + + public bool AddKill(Mobile mob, Type type) + { + var desired = Objective.DesiredAmount; + + foreach (var acceptedType in Objective.AcceptedTypes) + if (acceptedType.IsAssignableFrom(type)) + { + if (Objective.Area?.Contains(mob) == false) + return false; + + var pm = Instance.Player; + + if (++Slain >= desired) + pm.SendLocalizedMessage(1075050); // You have killed all the required quest creatures of this type. + else + pm.SendLocalizedMessage( + 1075051, + (desired - Slain).ToString() + ); // You have killed a quest creature. ~1_val~ more left. + + return true; + } + + return false; + } + + public override bool IsCompleted() => Slain >= Objective.DesiredAmount; + + public override void WriteToGump(Gump g, ref int y) + { + Objective.WriteToGump(g, ref y); + + base.WriteToGump(g, ref y); + + g.AddHtmlLocalized(103, y, 120, 16, 3000087, 0x15F90); // Total + g.AddLabel(223, y, 0x481, Slain.ToString()); + y += 16; + + g.AddHtmlLocalized(103, y, 120, 16, 1074782, 0x15F90); // Return to + g.AddLabel(223, y, 0x481, QuesterNameAttribute.GetQuesterNameFor(Instance.QuesterType)); + y += 16; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(Slain); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/QuestArea.cs b/Projects/UOContent/Engines/MLQuests/QuestArea.cs index 0066b0998..5f214da4d 100644 --- a/Projects/UOContent/Engines/MLQuests/QuestArea.cs +++ b/Projects/UOContent/Engines/MLQuests/QuestArea.cs @@ -1,50 +1,53 @@ -using System; - -namespace Server.Engines.MLQuests -{ - public class QuestArea - { - public QuestArea(TextDefinition name, string region, Map forceMap = null) - { - Name = name; - RegionName = region; - ForceMap = forceMap; - - if (MLQuestSystem.Debug) - ValidationQueue.Add(this); - } - - public TextDefinition Name { get; set; } - - public string RegionName { get; set; } - - public Map ForceMap { get; set; } - - public bool Contains(Mobile mob) => Contains(mob.Region); - - public bool Contains(Region reg) - { - if (reg == null || (ForceMap != null && reg.Map != ForceMap)) - return false; - - return reg.IsPartOf(RegionName); - } - - // Debug method - public void Validate() - { - bool found = false; - - foreach (Region r in Region.Regions) - if (r.Name == RegionName && (ForceMap == null || r.Map == ForceMap)) - { - found = true; - break; - } - - if (!found) - Console.WriteLine("Warning: QuestArea region '{0}' does not exist (ForceMap = {1})", RegionName, - ForceMap?.ToString() ?? "-null-"); - } - } -} +using System; + +namespace Server.Engines.MLQuests +{ + public class QuestArea + { + public QuestArea(TextDefinition name, string region, Map forceMap = null) + { + Name = name; + RegionName = region; + ForceMap = forceMap; + + if (MLQuestSystem.Debug) + ValidationQueue.Add(this); + } + + public TextDefinition Name { get; set; } + + public string RegionName { get; set; } + + public Map ForceMap { get; set; } + + public bool Contains(Mobile mob) => Contains(mob.Region); + + public bool Contains(Region reg) + { + if (reg == null || ForceMap != null && reg.Map != ForceMap) + return false; + + return reg.IsPartOf(RegionName); + } + + // Debug method + public void Validate() + { + var found = false; + + foreach (var r in Region.Regions) + if (r.Name == RegionName && (ForceMap == null || r.Map == ForceMap)) + { + found = true; + break; + } + + if (!found) + Console.WriteLine( + "Warning: QuestArea region '{0}' does not exist (ForceMap = {1})", + RegionName, + ForceMap?.ToString() ?? "-null-" + ); + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/QuesterNameAttribute.cs b/Projects/UOContent/Engines/MLQuests/QuesterNameAttribute.cs index 16758a375..4e9aea039 100644 --- a/Projects/UOContent/Engines/MLQuests/QuesterNameAttribute.cs +++ b/Projects/UOContent/Engines/MLQuests/QuesterNameAttribute.cs @@ -1,29 +1,29 @@ -using System; -using System.Collections.Generic; - -namespace Server.Engines.MLQuests -{ - [AttributeUsage(AttributeTargets.Class)] - public class QuesterNameAttribute : Attribute - { - private static readonly Type m_Type = typeof(QuesterNameAttribute); - private static readonly Dictionary m_Cache = new Dictionary(); - - public QuesterNameAttribute(string questerName) => QuesterName = questerName; - - public string QuesterName { get; } - - public static string GetQuesterNameFor(Type t) - { - if (t == null) - return ""; - - if (m_Cache.TryGetValue(t, out string result)) - return result; - - object[] attributes = t.GetCustomAttributes(m_Type, false); - - return m_Cache[t] = attributes.Length != 0 ? ((QuesterNameAttribute)attributes[0]).QuesterName : t.Name; - } - } -} +using System; +using System.Collections.Generic; + +namespace Server.Engines.MLQuests +{ + [AttributeUsage(AttributeTargets.Class)] + public class QuesterNameAttribute : Attribute + { + private static readonly Type m_Type = typeof(QuesterNameAttribute); + private static readonly Dictionary m_Cache = new Dictionary(); + + public QuesterNameAttribute(string questerName) => QuesterName = questerName; + + public string QuesterName { get; } + + public static string GetQuesterNameFor(Type t) + { + if (t == null) + return ""; + + if (m_Cache.TryGetValue(t, out var result)) + return result; + + var attributes = t.GetCustomAttributes(m_Type, false); + + return m_Cache[t] = attributes.Length != 0 ? ((QuesterNameAttribute)attributes[0]).QuesterName : t.Name; + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Rewards/BaseReward.cs b/Projects/UOContent/Engines/MLQuests/Rewards/BaseReward.cs index 0cee80628..7825ceebd 100644 --- a/Projects/UOContent/Engines/MLQuests/Rewards/BaseReward.cs +++ b/Projects/UOContent/Engines/MLQuests/Rewards/BaseReward.cs @@ -1,22 +1,22 @@ -using System.Collections.Generic; -using Server.Gumps; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Rewards -{ - public abstract class BaseReward - { - public BaseReward(TextDefinition name) => Name = name; - - public TextDefinition Name { get; set; } - - protected virtual int LabelHeight => 16; - - public void WriteToGump(Gump g, int x, ref int y) - { - TextDefinition.AddHtmlText(g, x, y, 280, LabelHeight, Name, false, false, 0x15F90, 0xBDE784); - } - - public abstract void AddRewardItems(PlayerMobile pm, List rewards); - } -} \ No newline at end of file +using System.Collections.Generic; +using Server.Gumps; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Rewards +{ + public abstract class BaseReward + { + public BaseReward(TextDefinition name) => Name = name; + + public TextDefinition Name { get; set; } + + protected virtual int LabelHeight => 16; + + public void WriteToGump(Gump g, int x, ref int y) + { + TextDefinition.AddHtmlText(g, x, y, 280, LabelHeight, Name, false, false, 0x15F90, 0xBDE784); + } + + public abstract void AddRewardItems(PlayerMobile pm, List rewards); + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Rewards/DummyReward.cs b/Projects/UOContent/Engines/MLQuests/Rewards/DummyReward.cs index b60df6f0f..9fc38c8df 100644 --- a/Projects/UOContent/Engines/MLQuests/Rewards/DummyReward.cs +++ b/Projects/UOContent/Engines/MLQuests/Rewards/DummyReward.cs @@ -1,19 +1,19 @@ -using System.Collections.Generic; -using Server.Mobiles; - -namespace Server.Engines.MLQuests.Rewards -{ - public class DummyReward : BaseReward - { - public DummyReward(TextDefinition name) - : base(name) - { - } - - protected override int LabelHeight => 180; - - public override void AddRewardItems(PlayerMobile pm, List rewards) - { - } - } -} \ No newline at end of file +using System.Collections.Generic; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Rewards +{ + public class DummyReward : BaseReward + { + public DummyReward(TextDefinition name) + : base(name) + { + } + + protected override int LabelHeight => 180; + + public override void AddRewardItems(PlayerMobile pm, List rewards) + { + } + } +} diff --git a/Projects/UOContent/Engines/MLQuests/Rewards/ItemReward.cs b/Projects/UOContent/Engines/MLQuests/Rewards/ItemReward.cs index 0886b1f51..34e26ad43 100644 --- a/Projects/UOContent/Engines/MLQuests/Rewards/ItemReward.cs +++ b/Projects/UOContent/Engines/MLQuests/Rewards/ItemReward.cs @@ -1,99 +1,99 @@ -using System; -using System.Collections.Generic; -using Server.Engines.MLQuests.Items; -using Server.Mobiles; -using Server.Utilities; - -namespace Server.Engines.MLQuests.Rewards -{ - public class ItemReward : BaseReward - { - public static readonly ItemReward - SmallBagOfTrinkets = new ItemReward(1072268, typeof(SmallBagOfTrinkets)); // A small bag of trinkets. - - public static readonly ItemReward - BagOfTrinkets = new ItemReward(1072341, typeof(BagOfTrinkets)); // A bag of trinkets. - - public static readonly ItemReward - BagOfTreasure = new ItemReward(1072583, typeof(BagOfTreasure)); // A bag of treasure. - - public static readonly ItemReward - LargeBagOfTreasure = new ItemReward(1072706, typeof(LargeBagOfTreasure)); // A large bag of treasure. - - public static readonly ItemReward Strongbox = new ItemReward(1072584, typeof(RewardStrongbox)); // A strongbox. - - public static readonly ItemReward - TailorSatchel = new ItemReward(1074282, typeof(TailorSatchel)); // Craftsman's Satchel - - public static readonly ItemReward - BlacksmithSatchel = new ItemReward(1074282, typeof(BlacksmithSatchel)); // Craftsman's Satchel - - public static readonly ItemReward - FletchingSatchel = new ItemReward(1074282, typeof(FletchingSatchel)); // Craftsman's Satchel - - public static readonly ItemReward - CarpentrySatchel = new ItemReward(1074282, typeof(CarpentrySatchel)); // Craftsman's Satchel - - public static readonly ItemReward - TinkerSatchel = new ItemReward(1074282, typeof(TinkerSatchel)); // Craftsman's Satchel - - private readonly int m_Amount; - - private readonly Type m_Type; - - public ItemReward(TextDefinition name = null, Type type = null, int amount = 1) - : base(name) - { - m_Type = type; - m_Amount = amount; - } - - public virtual Item CreateItem() - { - Item spawnedItem = null; - - try - { - spawnedItem = ActivatorUtil.CreateInstance(m_Type) as Item; - } - catch (Exception e) - { - if (MLQuestSystem.Debug) - Console.WriteLine("WARNING: ItemReward.CreateItem failed for {0}: {1}", m_Type, e); - } - - return spawnedItem; - } - - public override void AddRewardItems(PlayerMobile pm, List rewards) - { - Item reward = CreateItem(); - - if (reward == null) - return; - - if (reward.Stackable) - { - if (m_Amount > 1) - reward.Amount = m_Amount; - - rewards.Add(reward); - } - else - { - for (int i = 0; i < m_Amount; ++i) - { - rewards.Add(reward); - - if (i < m_Amount - 1) - { - reward = CreateItem(); - - if (reward == null) - return; - } - } - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Engines.MLQuests.Items; +using Server.Mobiles; +using Server.Utilities; + +namespace Server.Engines.MLQuests.Rewards +{ + public class ItemReward : BaseReward + { + public static readonly ItemReward + SmallBagOfTrinkets = new ItemReward(1072268, typeof(SmallBagOfTrinkets)); // A small bag of trinkets. + + public static readonly ItemReward + BagOfTrinkets = new ItemReward(1072341, typeof(BagOfTrinkets)); // A bag of trinkets. + + public static readonly ItemReward + BagOfTreasure = new ItemReward(1072583, typeof(BagOfTreasure)); // A bag of treasure. + + public static readonly ItemReward + LargeBagOfTreasure = new ItemReward(1072706, typeof(LargeBagOfTreasure)); // A large bag of treasure. + + public static readonly ItemReward Strongbox = new ItemReward(1072584, typeof(RewardStrongbox)); // A strongbox. + + public static readonly ItemReward + TailorSatchel = new ItemReward(1074282, typeof(TailorSatchel)); // Craftsman's Satchel + + public static readonly ItemReward + BlacksmithSatchel = new ItemReward(1074282, typeof(BlacksmithSatchel)); // Craftsman's Satchel + + public static readonly ItemReward + FletchingSatchel = new ItemReward(1074282, typeof(FletchingSatchel)); // Craftsman's Satchel + + public static readonly ItemReward + CarpentrySatchel = new ItemReward(1074282, typeof(CarpentrySatchel)); // Craftsman's Satchel + + public static readonly ItemReward + TinkerSatchel = new ItemReward(1074282, typeof(TinkerSatchel)); // Craftsman's Satchel + + private readonly int m_Amount; + + private readonly Type m_Type; + + public ItemReward(TextDefinition name = null, Type type = null, int amount = 1) + : base(name) + { + m_Type = type; + m_Amount = amount; + } + + public virtual Item CreateItem() + { + Item spawnedItem = null; + + try + { + spawnedItem = ActivatorUtil.CreateInstance(m_Type) as Item; + } + catch (Exception e) + { + if (MLQuestSystem.Debug) + Console.WriteLine("WARNING: ItemReward.CreateItem failed for {0}: {1}", m_Type, e); + } + + return spawnedItem; + } + + public override void AddRewardItems(PlayerMobile pm, List rewards) + { + var reward = CreateItem(); + + if (reward == null) + return; + + if (reward.Stackable) + { + if (m_Amount > 1) + reward.Amount = m_Amount; + + rewards.Add(reward); + } + else + { + for (var i = 0; i < m_Amount; ++i) + { + rewards.Add(reward); + + if (i < m_Amount - 1) + { + reward = CreateItem(); + + if (reward == null) + return; + } + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Party/AddPartyTarget.cs b/Projects/UOContent/Engines/Party/AddPartyTarget.cs index b54f92379..e267c46c3 100644 --- a/Projects/UOContent/Engines/Party/AddPartyTarget.cs +++ b/Projects/UOContent/Engines/Party/AddPartyTarget.cs @@ -1,45 +1,61 @@ -using Server.Targeting; - -namespace Server.Engines.PartySystem -{ - public class AddPartyTarget : Target - { - public AddPartyTarget(Mobile from) : base(8, false, TargetFlags.None) - { - from.SendLocalizedMessage(1005454); // Who would you like to add to your party? - } - - protected override void OnTarget(Mobile from, object o) - { - if (o is Mobile m) - { - Party p = Party.Get(from); - Party mp = Party.Get(m); - - if (from == m) - from.SendLocalizedMessage(1005439); // You cannot add yourself to a party. - else if (p != null && p.Leader != from) - from.SendLocalizedMessage(1005453); // You may only add members to the party if you are the leader. - else if (m.Party is Mobile) - { - } - else if (p != null && p.Members.Count + p.Candidates.Count >= Party.Capacity) - from.SendLocalizedMessage(1008095); // You may only have 10 in your party (this includes candidates). - else if (!m.Player && m.Body.IsHuman) - m.SayTo(from, 1005443); // Nay, I would rather stay here and watch a nail rust. - else if (!m.Player) - from.SendLocalizedMessage(1005444); // The creature ignores your offer. - else if (mp != null && mp == p) - from.SendLocalizedMessage(1005440); // This person is already in your party! - else if (mp != null) - from.SendLocalizedMessage(1005441); // This person is already in a party! - else - Party.Invite(from, m); - } - else - { - from.SendLocalizedMessage(1005442); // You may only add living things to your party! - } - } - } -} \ No newline at end of file +using Server.Targeting; + +namespace Server.Engines.PartySystem +{ + public class AddPartyTarget : Target + { + public AddPartyTarget(Mobile from) : base(8, false, TargetFlags.None) + { + from.SendLocalizedMessage(1005454); // Who would you like to add to your party? + } + + protected override void OnTarget(Mobile from, object o) + { + if (o is Mobile m) + { + var p = Party.Get(from); + var mp = Party.Get(m); + + if (from == m) + { + @from.SendLocalizedMessage(1005439); // You cannot add yourself to a party. + } + else if (p != null && p.Leader != from) + { + @from.SendLocalizedMessage(1005453); // You may only add members to the party if you are the leader. + } + else if (m.Party is Mobile) + { + } + else if (p != null && p.Members.Count + p.Candidates.Count >= Party.Capacity) + { + @from.SendLocalizedMessage(1008095); // You may only have 10 in your party (this includes candidates). + } + else if (!m.Player && m.Body.IsHuman) + { + m.SayTo(@from, 1005443); // Nay, I would rather stay here and watch a nail rust. + } + else if (!m.Player) + { + @from.SendLocalizedMessage(1005444); // The creature ignores your offer. + } + else if (mp != null && mp == p) + { + @from.SendLocalizedMessage(1005440); // This person is already in your party! + } + else if (mp != null) + { + @from.SendLocalizedMessage(1005441); // This person is already in a party! + } + else + { + Party.Invite(@from, m); + } + } + else + { + from.SendLocalizedMessage(1005442); // You may only add living things to your party! + } + } + } +} diff --git a/Projects/UOContent/Engines/Party/DeclineTimer.cs b/Projects/UOContent/Engines/Party/DeclineTimer.cs index d3c18db49..d65900849 100644 --- a/Projects/UOContent/Engines/Party/DeclineTimer.cs +++ b/Projects/UOContent/Engines/Party/DeclineTimer.cs @@ -1,35 +1,35 @@ -using System; -using System.Collections.Generic; - -namespace Server.Engines.PartySystem -{ - public class DeclineTimer : Timer - { - private static readonly Dictionary m_Table = new Dictionary(); - private readonly Mobile m_Mobile; - private readonly Mobile m_Leader; - - private DeclineTimer(Mobile m, Mobile leader) : base(TimeSpan.FromSeconds(30.0)) - { - m_Mobile = m; - m_Leader = leader; - } - - public static void Start(Mobile m, Mobile leader) - { - m_Table.TryGetValue(m, out DeclineTimer t); - t?.Stop(); - - m_Table[m] = t = new DeclineTimer(m, leader); - t.Start(); - } - - protected override void OnTick() - { - m_Table.Remove(m_Mobile); - - if (m_Mobile.Party == m_Leader && PartyCommands.Handler != null) - PartyCommands.Handler.OnDecline(m_Mobile, m_Leader); - } - } -} +using System; +using System.Collections.Generic; + +namespace Server.Engines.PartySystem +{ + public class DeclineTimer : Timer + { + private static readonly Dictionary m_Table = new Dictionary(); + private readonly Mobile m_Leader; + private readonly Mobile m_Mobile; + + private DeclineTimer(Mobile m, Mobile leader) : base(TimeSpan.FromSeconds(30.0)) + { + m_Mobile = m; + m_Leader = leader; + } + + public static void Start(Mobile m, Mobile leader) + { + m_Table.TryGetValue(m, out var t); + t?.Stop(); + + m_Table[m] = t = new DeclineTimer(m, leader); + t.Start(); + } + + protected override void OnTick() + { + m_Table.Remove(m_Mobile); + + if (m_Mobile.Party == m_Leader && PartyCommands.Handler != null) + PartyCommands.Handler.OnDecline(m_Mobile, m_Leader); + } + } +} diff --git a/Projects/UOContent/Engines/Party/Packets.cs b/Projects/UOContent/Engines/Party/Packets.cs index 47b7ce3e1..b9f4b580f 100644 --- a/Projects/UOContent/Engines/Party/Packets.cs +++ b/Projects/UOContent/Engines/Party/Packets.cs @@ -1,77 +1,77 @@ -using Server.Network; - -namespace Server.Engines.PartySystem -{ - public sealed class PartyEmptyList : Packet - { - public PartyEmptyList(Mobile m) : base(0xBF) - { - EnsureCapacity(7); - - Stream.Write((short)0x0006); - Stream.Write((byte)0x02); - Stream.Write((byte)0); - Stream.Write(m.Serial); - } - } - - public sealed class PartyMemberList : Packet - { - public PartyMemberList(Party p) : base(0xBF) - { - EnsureCapacity(7 + p.Count * 4); - - Stream.Write((short)0x0006); - Stream.Write((byte)0x01); - Stream.Write((byte)p.Count); - - for (int i = 0; i < p.Count; ++i) - Stream.Write(p[i].Mobile.Serial); - } - } - - public sealed class PartyRemoveMember : Packet - { - public PartyRemoveMember(Mobile removed, Party p) : base(0xBF) - { - EnsureCapacity(11 + p.Count * 4); - - Stream.Write((short)0x0006); - Stream.Write((byte)0x02); - Stream.Write((byte)p.Count); - - Stream.Write(removed.Serial); - - for (int i = 0; i < p.Count; ++i) - Stream.Write(p[i].Mobile.Serial); - } - } - - public sealed class PartyTextMessage : Packet - { - public PartyTextMessage(bool toAll, Mobile from, string text) : base(0xBF) - { - if (text == null) - text = ""; - - EnsureCapacity(12 + text.Length * 2); - - Stream.Write((short)0x0006); - Stream.Write((byte)(toAll ? 0x04 : 0x03)); - Stream.Write(from.Serial); - Stream.WriteBigUniNull(text); - } - } - - public sealed class PartyInvitation : Packet - { - public PartyInvitation(Mobile leader) : base(0xBF) - { - EnsureCapacity(10); - - Stream.Write((short)0x0006); - Stream.Write((byte)0x07); - Stream.Write(leader.Serial); - } - } -} \ No newline at end of file +using Server.Network; + +namespace Server.Engines.PartySystem +{ + public sealed class PartyEmptyList : Packet + { + public PartyEmptyList(Mobile m) : base(0xBF) + { + EnsureCapacity(7); + + Stream.Write((short)0x0006); + Stream.Write((byte)0x02); + Stream.Write((byte)0); + Stream.Write(m.Serial); + } + } + + public sealed class PartyMemberList : Packet + { + public PartyMemberList(Party p) : base(0xBF) + { + EnsureCapacity(7 + p.Count * 4); + + Stream.Write((short)0x0006); + Stream.Write((byte)0x01); + Stream.Write((byte)p.Count); + + for (var i = 0; i < p.Count; ++i) + Stream.Write(p[i].Mobile.Serial); + } + } + + public sealed class PartyRemoveMember : Packet + { + public PartyRemoveMember(Mobile removed, Party p) : base(0xBF) + { + EnsureCapacity(11 + p.Count * 4); + + Stream.Write((short)0x0006); + Stream.Write((byte)0x02); + Stream.Write((byte)p.Count); + + Stream.Write(removed.Serial); + + for (var i = 0; i < p.Count; ++i) + Stream.Write(p[i].Mobile.Serial); + } + } + + public sealed class PartyTextMessage : Packet + { + public PartyTextMessage(bool toAll, Mobile from, string text) : base(0xBF) + { + if (text == null) + text = ""; + + EnsureCapacity(12 + text.Length * 2); + + Stream.Write((short)0x0006); + Stream.Write((byte)(toAll ? 0x04 : 0x03)); + Stream.Write(from.Serial); + Stream.WriteBigUniNull(text); + } + } + + public sealed class PartyInvitation : Packet + { + public PartyInvitation(Mobile leader) : base(0xBF) + { + EnsureCapacity(10); + + Stream.Write((short)0x0006); + Stream.Write((byte)0x07); + Stream.Write(leader.Serial); + } + } +} diff --git a/Projects/UOContent/Engines/Party/Party.cs b/Projects/UOContent/Engines/Party/Party.cs index 6d2c7bfb8..60fe67c4e 100644 --- a/Projects/UOContent/Engines/Party/Party.cs +++ b/Projects/UOContent/Engines/Party/Party.cs @@ -1,461 +1,507 @@ -using System; -using System.Collections.Generic; -using Server.Factions; -using Server.Network; -using Server.Targeting; - -namespace Server.Engines.PartySystem -{ - public class Party : IParty - { - public const int Capacity = 10; - private readonly List m_Listeners; // staff listening - - public Party(Mobile leader) - { - Leader = leader; - - Members = new List(); - Candidates = new List(); - m_Listeners = new List(); - - Members.Add(new PartyMemberInfo(leader)); - } - - public int Count => Members.Count; - public bool Active => Members.Count > 1; - public Mobile Leader { get; } - - public List Members { get; } - - public List Candidates { get; } - - public PartyMemberInfo this[int index] => Members[index]; - - public PartyMemberInfo this[Mobile m] - { - get - { - for (int i = 0; i < Members.Count; ++i) - if (Members[i].Mobile == m) - return Members[i]; - - return null; - } - } - - public void OnStamChanged(Mobile m) - { - Packet p = null; - - for (int i = 0; i < Members.Count; ++i) - { - Mobile c = Members[i].Mobile; - - if (c != m && m.Map == c.Map && Utility.InUpdateRange(c, m) && c.CanSee(m)) - { - if (p == null) - p = Packet.Acquire(new MobileStamN(m)); - - c.Send(p); - } - } - - Packet.Release(p); - } - - public void OnManaChanged(Mobile m) - { - Packet p = null; - - for (int i = 0; i < Members.Count; ++i) - { - Mobile c = Members[i].Mobile; - - if (c != m && m.Map == c.Map && Utility.InUpdateRange(c, m) && c.CanSee(m)) - { - if (p == null) - p = Packet.Acquire(new MobileManaN(m)); - - c.Send(p); - } - } - - Packet.Release(p); - } - - public void OnStatsQuery(Mobile beholder, Mobile beheld) - { - if (beholder != beheld && Contains(beholder) && beholder.Map == beheld.Map && - Utility.InUpdateRange(beholder, beheld)) - { - if (!beholder.CanSee(beheld)) - beholder.Send(new MobileStatusCompact(beheld.CanBeRenamedBy(beholder), beheld)); - - beholder.Send(new MobileAttributesN(beheld)); - } - } - - public static void Initialize() - { - EventSink.Logout += EventSink_Logout; - EventSink.Login += EventSink_Login; - EventSink.PlayerDeath += EventSink_PlayerDeath; - - CommandSystem.Register("ListenToParty", AccessLevel.GameMaster, ListenToParty_OnCommand); - } - - public static void ListenToParty_OnCommand(CommandEventArgs e) - { - e.Mobile.BeginTarget(-1, false, TargetFlags.None, ListenToParty_OnTarget); - e.Mobile.SendMessage("Target a partied player."); - } - - public static void ListenToParty_OnTarget(Mobile from, object obj) - { - if (obj is Mobile mobile) - { - Party p = Get(mobile); - - if (p == null) - { - from.SendMessage("They are not in a party."); - } - else if (p.m_Listeners.Contains(from)) - { - p.m_Listeners.Remove(from); - from.SendMessage("You are no longer listening to that party."); - } - else - { - p.m_Listeners.Add(from); - from.SendMessage("You are now listening to that party."); - } - } - } - - public static void EventSink_PlayerDeath(Mobile from) - { - Party p = Get(from); - - if (p != null) - { - Mobile m = from.LastKiller; - - if (m == from) - p.SendPublicMessage(from, "I killed myself !!"); - else if (m == null) - p.SendPublicMessage(from, "I was killed !!"); - else - p.SendPublicMessage(from, $"I was killed by {m.Name} !!"); - } - } - - public static void EventSink_Login(Mobile from) - { - Party p = Get(from); - - if (p != null) - new RejoinTimer(from).Start(); - else - from.Party = null; - } - - public static void EventSink_Logout(Mobile from) - { - Party p = Get(from); - - p?.Remove(from); - - from.Party = null; - } - - public static Party Get(Mobile m) => m?.Party as Party; - - public void Add(Mobile m) - { - PartyMemberInfo mi = this[m]; - - if (mi == null) - { - Members.Add(new PartyMemberInfo(m)); - m.Party = this; - - Packet memberList = Packet.Acquire(new PartyMemberList(this)); - Packet attrs = Packet.Acquire(new MobileAttributesN(m)); - - for (int i = 0; i < Members.Count; ++i) - { - Mobile f = Members[i].Mobile; - - f.Send(memberList); - - if (f != m) - { - f.Send(new MobileStatusCompact(m.CanBeRenamedBy(f), m)); - f.Send(attrs); - m.Send(new MobileStatusCompact(f.CanBeRenamedBy(m), f)); - m.Send(new MobileAttributesN(f)); - } - } - - Packet.Release(memberList); - Packet.Release(attrs); - } - } - - public void OnAccept(Mobile from) - { - OnAccept(from, false); - } - - public void OnAccept(Mobile from, bool force) - { - Faction ourFaction = Faction.Find(Leader); - Faction theirFaction = Faction.Find(from); - - if (!force && ourFaction != null && theirFaction != null && ourFaction != theirFaction) - return; - - // : joined the party. - SendToAll(new MessageLocalizedAffix(Serial.MinusOne, -1, MessageType.Label, 0x3B2, 3, 1008094, "", - AffixType.Prepend | AffixType.System, from.Name, "")); - - from.SendLocalizedMessage(1005445); // You have been added to the party. - - Candidates.Remove(from); - Add(from); - } - - public void OnDecline(Mobile from, Mobile leader) - { - // : Does not wish to join the party. - leader.SendLocalizedMessage(1008091, false, from.Name); - - from.SendLocalizedMessage(1008092); // You notify them that you do not wish to join the party. - - Candidates.Remove(from); - from.Send(new PartyEmptyList(from)); - - if (Candidates.Count == 0 && Members.Count <= 1) - { - for (int i = 0; i < Members.Count; ++i) - { - this[i].Mobile.Send(new PartyEmptyList(this[i].Mobile)); - this[i].Mobile.Party = null; - } - - Members.Clear(); - } - } - - public void Remove(Mobile m) - { - if (m == Leader) - { - Disband(); - } - else - { - for (int i = 0; i < Members.Count; ++i) - if (Members[i].Mobile == m) - { - Members.RemoveAt(i); - - m.Party = null; - m.Send(new PartyEmptyList(m)); - - m.SendLocalizedMessage(1005451); // You have been removed from the party. - - SendToAll(new PartyRemoveMember(m, this)); - SendToAll(1005452); // A player has been removed from your party. - - break; - } - - if (Members.Count == 1) - { - SendToAll(1005450); // The last person has left the party... - Disband(); - } - } - } - - public bool Contains(Mobile m) => this[m] != null; - - public void Disband() - { - SendToAll(1005449); // Your party has disbanded. - - for (int i = 0; i < Members.Count; ++i) - { - this[i].Mobile.Send(new PartyEmptyList(this[i].Mobile)); - this[i].Mobile.Party = null; - } - - Members.Clear(); - } - - public static void Invite(Mobile from, Mobile target) - { - Faction ourFaction = Faction.Find(from); - Faction theirFaction = Faction.Find(target); - - if (ourFaction != null && theirFaction != null && ourFaction != theirFaction) - { - from.SendLocalizedMessage(1008088); // You cannot have players from opposing factions in the same party! - target.SendLocalizedMessage(1008093); // The party cannot have members from opposing factions. - return; - } - - Party p = Get(from); - - if (p == null) - from.Party = p = new Party(from); - - if (!p.Candidates.Contains(target)) - p.Candidates.Add(target); - - // : You are invited to join the party. Type /accept to join or /decline to decline the offer. - target.Send(new MessageLocalizedAffix(Serial.MinusOne, -1, MessageType.Label, 0x3B2, 3, 1008089, "", - AffixType.Prepend | AffixType.System, from.Name, "")); - - from.SendLocalizedMessage(1008090); // You have invited them to join the party. - - target.Send(new PartyInvitation(from)); - target.Party = from; - - DeclineTimer.Start(target, from); - } - - public void SendToAll(int number) - { - SendToAll(number, "", 0x3B2); - } - - public void SendToAll(int number, string args) - { - SendToAll(number, args, 0x3B2); - } - - public void SendToAll(int number, string args, int hue) - { - SendToAll(new MessageLocalized(Serial.MinusOne, -1, MessageType.Regular, hue, 3, number, "System", args)); - } - - public void SendPublicMessage(Mobile from, string text) - { - SendToAll(new PartyTextMessage(true, from, text)); - - for (int i = 0; i < m_Listeners.Count; ++i) - { - Mobile mob = m_Listeners[i]; - - if (mob.Party != this) - m_Listeners[i].SendMessage("[{0}]: {1}", from.Name, text); - } - - SendToStaffMessage(from, "[Party]: {0}", text); - } - - public void SendPrivateMessage(Mobile from, Mobile to, string text) - { - to.Send(new PartyTextMessage(false, from, text)); - - for (int i = 0; i < m_Listeners.Count; ++i) - { - Mobile mob = m_Listeners[i]; - - if (mob.Party != this) - m_Listeners[i].SendMessage("[{0}]->[{1}]: {2}", from.Name, to.Name, text); - } - - SendToStaffMessage(from, "[Party]->[{0}]: {1}", to.Name, text); - } - - private void SendToStaffMessage(Mobile from, string text) - { - Packet p = null; - - foreach (NetState ns in from.GetClientsInRange(8)) - { - Mobile mob = ns.Mobile; - - if (mob?.AccessLevel >= AccessLevel.GameMaster && mob.AccessLevel > from.AccessLevel && - mob.Party != this && !m_Listeners.Contains(mob)) - { - if (p == null) - p = Packet.Acquire(new UnicodeMessage(from.Serial, from.Body, MessageType.Regular, from.SpeechHue, 3, - from.Language, from.Name, text)); - - ns.Send(p); - } - } - - Packet.Release(p); - } - - private void SendToStaffMessage(Mobile from, string format, params object[] args) - { - SendToStaffMessage(from, string.Format(format, args)); - } - - public void SendToAll(Packet p) - { - p.Acquire(); - - for (int i = 0; i < Members.Count; ++i) - Members[i].Mobile.Send(p); - - if (p is MessageLocalized || p is MessageLocalizedAffix || p is UnicodeMessage || p is AsciiMessage) - for (int i = 0; i < m_Listeners.Count; ++i) - { - Mobile mob = m_Listeners[i]; - - if (mob.Party != this) - mob.Send(p); - } - - p.Release(); - } - - private class RejoinTimer : Timer - { - private readonly Mobile m_Mobile; - - public RejoinTimer(Mobile m) : base(TimeSpan.FromSeconds(1.0)) => m_Mobile = m; - - protected override void OnTick() - { - Party p = Get(m_Mobile); - - if (p == null) - return; - - m_Mobile.SendLocalizedMessage(1005437); // You have rejoined the party. - m_Mobile.Send(new PartyMemberList(p)); - - Packet message = Packet.Acquire(new MessageLocalizedAffix(Serial.MinusOne, -1, MessageType.Label, 0x3B2, 3, - 1008087, "", AffixType.Prepend | AffixType.System, m_Mobile.Name, "")); - Packet attrs = Packet.Acquire(new MobileAttributesN(m_Mobile)); - - foreach (PartyMemberInfo mi in p.Members) - { - Mobile m = mi.Mobile; - - if (m != m_Mobile) - { - m.Send(message); - m.Send(new MobileStatusCompact(m_Mobile.CanBeRenamedBy(m), m_Mobile)); - m.Send(attrs); - m_Mobile.Send(new MobileStatusCompact(m.CanBeRenamedBy(m_Mobile), m)); - m_Mobile.Send(new MobileAttributesN(m)); - } - } - - Packet.Release(message); - Packet.Release(attrs); - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Factions; +using Server.Network; +using Server.Targeting; + +namespace Server.Engines.PartySystem +{ + public class Party : IParty + { + public const int Capacity = 10; + private readonly List m_Listeners; // staff listening + + public Party(Mobile leader) + { + Leader = leader; + + Members = new List(); + Candidates = new List(); + m_Listeners = new List(); + + Members.Add(new PartyMemberInfo(leader)); + } + + public int Count => Members.Count; + public bool Active => Members.Count > 1; + public Mobile Leader { get; } + + public List Members { get; } + + public List Candidates { get; } + + public PartyMemberInfo this[int index] => Members[index]; + + public PartyMemberInfo this[Mobile m] + { + get + { + for (var i = 0; i < Members.Count; ++i) + if (Members[i].Mobile == m) + return Members[i]; + + return null; + } + } + + public void OnStamChanged(Mobile m) + { + Packet p = null; + + for (var i = 0; i < Members.Count; ++i) + { + var c = Members[i].Mobile; + + if (c != m && m.Map == c.Map && Utility.InUpdateRange(c, m) && c.CanSee(m)) + { + if (p == null) + p = Packet.Acquire(new MobileStamN(m)); + + c.Send(p); + } + } + + Packet.Release(p); + } + + public void OnManaChanged(Mobile m) + { + Packet p = null; + + for (var i = 0; i < Members.Count; ++i) + { + var c = Members[i].Mobile; + + if (c != m && m.Map == c.Map && Utility.InUpdateRange(c, m) && c.CanSee(m)) + { + if (p == null) + p = Packet.Acquire(new MobileManaN(m)); + + c.Send(p); + } + } + + Packet.Release(p); + } + + public void OnStatsQuery(Mobile beholder, Mobile beheld) + { + if (beholder != beheld && Contains(beholder) && beholder.Map == beheld.Map && + Utility.InUpdateRange(beholder, beheld)) + { + if (!beholder.CanSee(beheld)) + beholder.Send(new MobileStatusCompact(beheld.CanBeRenamedBy(beholder), beheld)); + + beholder.Send(new MobileAttributesN(beheld)); + } + } + + public static void Initialize() + { + EventSink.Logout += EventSink_Logout; + EventSink.Login += EventSink_Login; + EventSink.PlayerDeath += EventSink_PlayerDeath; + + CommandSystem.Register("ListenToParty", AccessLevel.GameMaster, ListenToParty_OnCommand); + } + + public static void ListenToParty_OnCommand(CommandEventArgs e) + { + e.Mobile.BeginTarget(-1, false, TargetFlags.None, ListenToParty_OnTarget); + e.Mobile.SendMessage("Target a partied player."); + } + + public static void ListenToParty_OnTarget(Mobile from, object obj) + { + if (obj is Mobile mobile) + { + var p = Get(mobile); + + if (p == null) + { + from.SendMessage("They are not in a party."); + } + else if (p.m_Listeners.Contains(from)) + { + p.m_Listeners.Remove(from); + from.SendMessage("You are no longer listening to that party."); + } + else + { + p.m_Listeners.Add(from); + from.SendMessage("You are now listening to that party."); + } + } + } + + public static void EventSink_PlayerDeath(Mobile from) + { + var p = Get(from); + + if (p != null) + { + var m = from.LastKiller; + + if (m == from) + p.SendPublicMessage(from, "I killed myself !!"); + else if (m == null) + p.SendPublicMessage(from, "I was killed !!"); + else + p.SendPublicMessage(from, $"I was killed by {m.Name} !!"); + } + } + + public static void EventSink_Login(Mobile from) + { + var p = Get(from); + + if (p != null) + new RejoinTimer(from).Start(); + else + from.Party = null; + } + + public static void EventSink_Logout(Mobile from) + { + var p = Get(from); + + p?.Remove(from); + + from.Party = null; + } + + public static Party Get(Mobile m) => m?.Party as Party; + + public void Add(Mobile m) + { + var mi = this[m]; + + if (mi == null) + { + Members.Add(new PartyMemberInfo(m)); + m.Party = this; + + var memberList = Packet.Acquire(new PartyMemberList(this)); + var attrs = Packet.Acquire(new MobileAttributesN(m)); + + for (var i = 0; i < Members.Count; ++i) + { + var f = Members[i].Mobile; + + f.Send(memberList); + + if (f != m) + { + f.Send(new MobileStatusCompact(m.CanBeRenamedBy(f), m)); + f.Send(attrs); + m.Send(new MobileStatusCompact(f.CanBeRenamedBy(m), f)); + m.Send(new MobileAttributesN(f)); + } + } + + Packet.Release(memberList); + Packet.Release(attrs); + } + } + + public void OnAccept(Mobile from) + { + OnAccept(from, false); + } + + public void OnAccept(Mobile from, bool force) + { + var ourFaction = Faction.Find(Leader); + var theirFaction = Faction.Find(from); + + if (!force && ourFaction != null && theirFaction != null && ourFaction != theirFaction) + return; + + // : joined the party. + SendToAll( + new MessageLocalizedAffix( + Serial.MinusOne, + -1, + MessageType.Label, + 0x3B2, + 3, + 1008094, + "", + AffixType.Prepend | AffixType.System, + from.Name, + "" + ) + ); + + from.SendLocalizedMessage(1005445); // You have been added to the party. + + Candidates.Remove(from); + Add(from); + } + + public void OnDecline(Mobile from, Mobile leader) + { + // : Does not wish to join the party. + leader.SendLocalizedMessage(1008091, false, from.Name); + + from.SendLocalizedMessage(1008092); // You notify them that you do not wish to join the party. + + Candidates.Remove(from); + from.Send(new PartyEmptyList(from)); + + if (Candidates.Count == 0 && Members.Count <= 1) + { + for (var i = 0; i < Members.Count; ++i) + { + this[i].Mobile.Send(new PartyEmptyList(this[i].Mobile)); + this[i].Mobile.Party = null; + } + + Members.Clear(); + } + } + + public void Remove(Mobile m) + { + if (m == Leader) + { + Disband(); + } + else + { + for (var i = 0; i < Members.Count; ++i) + if (Members[i].Mobile == m) + { + Members.RemoveAt(i); + + m.Party = null; + m.Send(new PartyEmptyList(m)); + + m.SendLocalizedMessage(1005451); // You have been removed from the party. + + SendToAll(new PartyRemoveMember(m, this)); + SendToAll(1005452); // A player has been removed from your party. + + break; + } + + if (Members.Count == 1) + { + SendToAll(1005450); // The last person has left the party... + Disband(); + } + } + } + + public bool Contains(Mobile m) => this[m] != null; + + public void Disband() + { + SendToAll(1005449); // Your party has disbanded. + + for (var i = 0; i < Members.Count; ++i) + { + this[i].Mobile.Send(new PartyEmptyList(this[i].Mobile)); + this[i].Mobile.Party = null; + } + + Members.Clear(); + } + + public static void Invite(Mobile from, Mobile target) + { + var ourFaction = Faction.Find(from); + var theirFaction = Faction.Find(target); + + if (ourFaction != null && theirFaction != null && ourFaction != theirFaction) + { + from.SendLocalizedMessage(1008088); // You cannot have players from opposing factions in the same party! + target.SendLocalizedMessage(1008093); // The party cannot have members from opposing factions. + return; + } + + var p = Get(from); + + if (p == null) + from.Party = p = new Party(from); + + if (!p.Candidates.Contains(target)) + p.Candidates.Add(target); + + // : You are invited to join the party. Type /accept to join or /decline to decline the offer. + target.Send( + new MessageLocalizedAffix( + Serial.MinusOne, + -1, + MessageType.Label, + 0x3B2, + 3, + 1008089, + "", + AffixType.Prepend | AffixType.System, + from.Name, + "" + ) + ); + + from.SendLocalizedMessage(1008090); // You have invited them to join the party. + + target.Send(new PartyInvitation(from)); + target.Party = from; + + DeclineTimer.Start(target, from); + } + + public void SendToAll(int number) + { + SendToAll(number, "", 0x3B2); + } + + public void SendToAll(int number, string args) + { + SendToAll(number, args, 0x3B2); + } + + public void SendToAll(int number, string args, int hue) + { + SendToAll(new MessageLocalized(Serial.MinusOne, -1, MessageType.Regular, hue, 3, number, "System", args)); + } + + public void SendPublicMessage(Mobile from, string text) + { + SendToAll(new PartyTextMessage(true, from, text)); + + for (var i = 0; i < m_Listeners.Count; ++i) + { + var mob = m_Listeners[i]; + + if (mob.Party != this) + m_Listeners[i].SendMessage("[{0}]: {1}", from.Name, text); + } + + SendToStaffMessage(from, "[Party]: {0}", text); + } + + public void SendPrivateMessage(Mobile from, Mobile to, string text) + { + to.Send(new PartyTextMessage(false, from, text)); + + for (var i = 0; i < m_Listeners.Count; ++i) + { + var mob = m_Listeners[i]; + + if (mob.Party != this) + m_Listeners[i].SendMessage("[{0}]->[{1}]: {2}", from.Name, to.Name, text); + } + + SendToStaffMessage(from, "[Party]->[{0}]: {1}", to.Name, text); + } + + private void SendToStaffMessage(Mobile from, string text) + { + Packet p = null; + + foreach (var ns in from.GetClientsInRange(8)) + { + var mob = ns.Mobile; + + if (mob?.AccessLevel >= AccessLevel.GameMaster && mob.AccessLevel > from.AccessLevel && + mob.Party != this && !m_Listeners.Contains(mob)) + { + if (p == null) + p = Packet.Acquire( + new UnicodeMessage( + from.Serial, + from.Body, + MessageType.Regular, + from.SpeechHue, + 3, + from.Language, + from.Name, + text + ) + ); + + ns.Send(p); + } + } + + Packet.Release(p); + } + + private void SendToStaffMessage(Mobile from, string format, params object[] args) + { + SendToStaffMessage(from, string.Format(format, args)); + } + + public void SendToAll(Packet p) + { + p.Acquire(); + + for (var i = 0; i < Members.Count; ++i) + Members[i].Mobile.Send(p); + + if (p is MessageLocalized || p is MessageLocalizedAffix || p is UnicodeMessage || p is AsciiMessage) + for (var i = 0; i < m_Listeners.Count; ++i) + { + var mob = m_Listeners[i]; + + if (mob.Party != this) + mob.Send(p); + } + + p.Release(); + } + + private class RejoinTimer : Timer + { + private readonly Mobile m_Mobile; + + public RejoinTimer(Mobile m) : base(TimeSpan.FromSeconds(1.0)) => m_Mobile = m; + + protected override void OnTick() + { + var p = Get(m_Mobile); + + if (p == null) + return; + + m_Mobile.SendLocalizedMessage(1005437); // You have rejoined the party. + m_Mobile.Send(new PartyMemberList(p)); + + var message = Packet.Acquire( + new MessageLocalizedAffix( + Serial.MinusOne, + -1, + MessageType.Label, + 0x3B2, + 3, + 1008087, + "", + AffixType.Prepend | AffixType.System, + m_Mobile.Name, + "" + ) + ); + var attrs = Packet.Acquire(new MobileAttributesN(m_Mobile)); + + foreach (var mi in p.Members) + { + var m = mi.Mobile; + + if (m != m_Mobile) + { + m.Send(message); + m.Send(new MobileStatusCompact(m_Mobile.CanBeRenamedBy(m), m_Mobile)); + m.Send(attrs); + m_Mobile.Send(new MobileStatusCompact(m.CanBeRenamedBy(m_Mobile), m)); + m_Mobile.Send(new MobileAttributesN(m)); + } + } + + Packet.Release(message); + Packet.Release(attrs); + } + } + } +} diff --git a/Projects/UOContent/Engines/Party/PartyCommands.cs b/Projects/UOContent/Engines/Party/PartyCommands.cs index 431d5d3e9..6b9fbad22 100644 --- a/Projects/UOContent/Engines/Party/PartyCommands.cs +++ b/Projects/UOContent/Engines/Party/PartyCommands.cs @@ -1,120 +1,121 @@ -namespace Server.Engines.PartySystem -{ - public class PartyCommandHandlers : PartyCommands - { - public static void Initialize() - { - Handler = new PartyCommandHandlers(); - } - - public override void OnAdd(Mobile from) - { - Party p = Party.Get(from); - - if (p != null && p.Leader != from) - from.SendLocalizedMessage(1005453); // You may only add members to the party if you are the leader. - else if (p != null && p.Members.Count + p.Candidates.Count >= Party.Capacity) - from.SendLocalizedMessage(1008095); // You may only have 10 in your party (this includes candidates). - else - from.Target = new AddPartyTarget(from); - } - - public override void OnRemove(Mobile from, Mobile target) - { - Party p = Party.Get(from); - - if (p == null) - { - from.SendLocalizedMessage(3000211); // You are not in a party. - return; - } - - if (p.Leader == from && target == null) - { - from.SendLocalizedMessage(1005455); // Who would you like to remove from your party? - from.Target = new RemovePartyTarget(); - } - else if ((p.Leader == from || from == target) && p.Contains(target)) - { - p.Remove(target); - } - } - - public override void OnPrivateMessage(Mobile from, Mobile target, string text) - { - if (text.Length > 128 || (text = text.Trim()).Length == 0) - return; - - Party p = Party.Get(from); - - if (p?.Contains(target) == true) - p.SendPrivateMessage(from, target, text); - else - from.SendLocalizedMessage(3000211); // You are not in a party. - } - - public override void OnPublicMessage(Mobile from, string text) - { - if (text.Length > 128 || (text = text.Trim()).Length == 0) - return; - - Party p = Party.Get(from); - - if (p != null) - p.SendPublicMessage(from, text); - else - from.SendLocalizedMessage(3000211); // You are not in a party. - } - - public override void OnSetCanLoot(Mobile from, bool canLoot) - { - Party p = Party.Get(from); - - if (p == null) - { - from.SendLocalizedMessage(3000211); // You are not in a party. - } - else - { - PartyMemberInfo mi = p[from]; - - if (mi != null) - { - mi.CanLoot = canLoot; - - if (canLoot) - from.SendLocalizedMessage(1005447); // You have chosen to allow your party to loot your corpse. - else - from.SendLocalizedMessage( - 1005448); // You have chosen to prevent your party from looting your corpse. - } - } - } - - public override void OnAccept(Mobile from, Mobile sentLeader) - { - Mobile leader = from.Party as Mobile; - from.Party = null; - - Party p = Party.Get(leader); - - if (leader == null || p?.Candidates.Contains(from) != true) - from.SendLocalizedMessage(3000222); // No one has invited you to be in a party. - else if (p.Members.Count + p.Candidates.Count <= Party.Capacity) - p.OnAccept(from); - } - - public override void OnDecline(Mobile from, Mobile sentLeader) - { - Mobile leader = from.Party as Mobile; - from.Party = null; - - Party p = Party.Get(leader); - - if (leader == null || p?.Candidates.Contains(from) != true) - from.SendLocalizedMessage(3000222); // No one has invited you to be in a party. - else - p.OnDecline(from, leader); - } - } -} +namespace Server.Engines.PartySystem +{ + public class PartyCommandHandlers : PartyCommands + { + public static void Initialize() + { + Handler = new PartyCommandHandlers(); + } + + public override void OnAdd(Mobile from) + { + var p = Party.Get(from); + + if (p != null && p.Leader != from) + from.SendLocalizedMessage(1005453); // You may only add members to the party if you are the leader. + else if (p != null && p.Members.Count + p.Candidates.Count >= Party.Capacity) + from.SendLocalizedMessage(1008095); // You may only have 10 in your party (this includes candidates). + else + from.Target = new AddPartyTarget(from); + } + + public override void OnRemove(Mobile from, Mobile target) + { + var p = Party.Get(from); + + if (p == null) + { + from.SendLocalizedMessage(3000211); // You are not in a party. + return; + } + + if (p.Leader == from && target == null) + { + from.SendLocalizedMessage(1005455); // Who would you like to remove from your party? + from.Target = new RemovePartyTarget(); + } + else if ((p.Leader == from || from == target) && p.Contains(target)) + { + p.Remove(target); + } + } + + public override void OnPrivateMessage(Mobile from, Mobile target, string text) + { + if (text.Length > 128 || (text = text.Trim()).Length == 0) + return; + + var p = Party.Get(from); + + if (p?.Contains(target) == true) + p.SendPrivateMessage(from, target, text); + else + from.SendLocalizedMessage(3000211); // You are not in a party. + } + + public override void OnPublicMessage(Mobile from, string text) + { + if (text.Length > 128 || (text = text.Trim()).Length == 0) + return; + + var p = Party.Get(from); + + if (p != null) + p.SendPublicMessage(from, text); + else + from.SendLocalizedMessage(3000211); // You are not in a party. + } + + public override void OnSetCanLoot(Mobile from, bool canLoot) + { + var p = Party.Get(from); + + if (p == null) + { + from.SendLocalizedMessage(3000211); // You are not in a party. + } + else + { + var mi = p[from]; + + if (mi != null) + { + mi.CanLoot = canLoot; + + if (canLoot) + from.SendLocalizedMessage(1005447); // You have chosen to allow your party to loot your corpse. + else + from.SendLocalizedMessage( + 1005448 + ); // You have chosen to prevent your party from looting your corpse. + } + } + } + + public override void OnAccept(Mobile from, Mobile sentLeader) + { + var leader = from.Party as Mobile; + from.Party = null; + + var p = Party.Get(leader); + + if (leader == null || p?.Candidates.Contains(from) != true) + from.SendLocalizedMessage(3000222); // No one has invited you to be in a party. + else if (p.Members.Count + p.Candidates.Count <= Party.Capacity) + p.OnAccept(from); + } + + public override void OnDecline(Mobile from, Mobile sentLeader) + { + var leader = from.Party as Mobile; + from.Party = null; + + var p = Party.Get(leader); + + if (leader == null || p?.Candidates.Contains(from) != true) + from.SendLocalizedMessage(3000222); // No one has invited you to be in a party. + else + p.OnDecline(from, leader); + } + } +} diff --git a/Projects/UOContent/Engines/Party/PartyMemberInfo.cs b/Projects/UOContent/Engines/Party/PartyMemberInfo.cs index 8992cbf20..a821a450a 100644 --- a/Projects/UOContent/Engines/Party/PartyMemberInfo.cs +++ b/Projects/UOContent/Engines/Party/PartyMemberInfo.cs @@ -1,15 +1,15 @@ -namespace Server.Engines.PartySystem -{ - public class PartyMemberInfo - { - public PartyMemberInfo(Mobile m) - { - Mobile = m; - CanLoot = !Core.ML; - } - - public Mobile Mobile { get; } - - public bool CanLoot { get; set; } - } -} \ No newline at end of file +namespace Server.Engines.PartySystem +{ + public class PartyMemberInfo + { + public PartyMemberInfo(Mobile m) + { + Mobile = m; + CanLoot = !Core.ML; + } + + public Mobile Mobile { get; } + + public bool CanLoot { get; set; } + } +} diff --git a/Projects/UOContent/Engines/Party/RemoveFromParty.cs b/Projects/UOContent/Engines/Party/RemoveFromParty.cs index 105ec3d93..ff032b12d 100644 --- a/Projects/UOContent/Engines/Party/RemoveFromParty.cs +++ b/Projects/UOContent/Engines/Party/RemoveFromParty.cs @@ -1,29 +1,29 @@ -using Server.Engines.PartySystem; - -namespace Server.ContextMenus -{ - public class RemoveFromPartyEntry : ContextMenuEntry - { - private readonly Mobile m_From; - private readonly Mobile m_Target; - - public RemoveFromPartyEntry(Mobile from, Mobile target) : base(0198, 12) - { - m_From = from; - m_Target = target; - } - - public override void OnClick() - { - Party p = Party.Get(m_From); - - if (p == null || p.Leader != m_From || !p.Contains(m_Target)) - return; - - if (m_From == m_Target) - m_From.SendLocalizedMessage(1005446); // You may only remove yourself from a party if you are not the leader. - else - p.Remove(m_Target); - } - } -} \ No newline at end of file +using Server.Engines.PartySystem; + +namespace Server.ContextMenus +{ + public class RemoveFromPartyEntry : ContextMenuEntry + { + private readonly Mobile m_From; + private readonly Mobile m_Target; + + public RemoveFromPartyEntry(Mobile from, Mobile target) : base(0198, 12) + { + m_From = from; + m_Target = target; + } + + public override void OnClick() + { + var p = Party.Get(m_From); + + if (p == null || p.Leader != m_From || !p.Contains(m_Target)) + return; + + if (m_From == m_Target) + m_From.SendLocalizedMessage(1005446); // You may only remove yourself from a party if you are not the leader. + else + p.Remove(m_Target); + } + } +} diff --git a/Projects/UOContent/Engines/Party/RemovePartyTarget.cs b/Projects/UOContent/Engines/Party/RemovePartyTarget.cs index 819b99cf1..de2c20e17 100644 --- a/Projects/UOContent/Engines/Party/RemovePartyTarget.cs +++ b/Projects/UOContent/Engines/Party/RemovePartyTarget.cs @@ -1,28 +1,29 @@ -using Server.Targeting; - -namespace Server.Engines.PartySystem -{ - public class RemovePartyTarget : Target - { - public RemovePartyTarget() : base(8, false, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object o) - { - if (o is Mobile m) - { - Party p = Party.Get(from); - - if (p == null || p.Leader != from || !p.Contains(m)) - return; - - if (from == m) - from.SendLocalizedMessage( - 1005446); // You may only remove yourself from a party if you are not the leader. - else - p.Remove(m); - } - } - } -} \ No newline at end of file +using Server.Targeting; + +namespace Server.Engines.PartySystem +{ + public class RemovePartyTarget : Target + { + public RemovePartyTarget() : base(8, false, TargetFlags.None) + { + } + + protected override void OnTarget(Mobile from, object o) + { + if (o is Mobile m) + { + var p = Party.Get(from); + + if (p == null || p.Leader != from || !p.Contains(m)) + return; + + if (from == m) + from.SendLocalizedMessage( + 1005446 + ); // You may only remove yourself from a party if you are not the leader. + else + p.Remove(m); + } + } + } +} diff --git a/Projects/UOContent/Engines/Pathing/FastAStarAlgorithm.cs b/Projects/UOContent/Engines/Pathing/FastAStarAlgorithm.cs index 36573e5b1..221381603 100644 --- a/Projects/UOContent/Engines/Pathing/FastAStarAlgorithm.cs +++ b/Projects/UOContent/Engines/Pathing/FastAStarAlgorithm.cs @@ -1,314 +1,322 @@ -using System.Collections; -using Server.Mobiles; -using CalcMoves = Server.Movement.Movement; -using MoveImpl = Server.Movement.MovementImpl; - -namespace Server.PathAlgorithms.FastAStar -{ - public struct PathNode - { - public int cost, total; - public int parent, next, prev; - public int z; - } - - public class FastAStarAlgorithm : PathAlgorithm - { - private const int MaxDepth = 300; - private const int AreaSize = 38; - - private const int NodeCount = AreaSize * AreaSize * PlaneCount; - - private const int PlaneOffset = 128; - private const int PlaneCount = 13; - private const int PlaneHeight = 20; - public static PathAlgorithm Instance = new FastAStarAlgorithm(); - - private static readonly Direction[] m_Path = new Direction[AreaSize * AreaSize]; - private static readonly PathNode[] m_Nodes = new PathNode[NodeCount]; - private static readonly BitArray m_Touched = new BitArray(NodeCount); - private static readonly BitArray m_OnOpen = new BitArray(NodeCount); - private static readonly int[] m_Successors = new int[8]; - - private static int m_xOffset, m_yOffset; - private static int m_OpenList; - - private Point3D m_Goal; - - public int Heuristic(int x, int y, int z) - { - x -= m_Goal.X - m_xOffset; - y -= m_Goal.Y - m_yOffset; - z -= m_Goal.Z; - - x *= 11; - y *= 11; - - return x * x + y * y + z * z; - } - - public override bool CheckCondition(Mobile m, Map map, Point3D start, Point3D goal) => Utility.InRange(start, goal, AreaSize); - - private void RemoveFromChain(int node) - { - if (node < 0 || node >= NodeCount) - return; - - if (!m_Touched[node] || !m_OnOpen[node]) - return; - - int prev = m_Nodes[node].prev; - int next = m_Nodes[node].next; - - if (m_OpenList == node) - m_OpenList = next; - - if (prev != -1) - m_Nodes[prev].next = next; - - if (next != -1) - m_Nodes[next].prev = prev; - - m_Nodes[node].prev = -1; - m_Nodes[node].next = -1; - } - - private void AddToChain(int node) - { - if (node < 0 || node >= NodeCount) - return; - - RemoveFromChain(node); - - if (m_OpenList != -1) - m_Nodes[m_OpenList].prev = node; - - m_Nodes[node].next = m_OpenList; - m_Nodes[node].prev = -1; - - m_OpenList = node; - - m_Touched[node] = true; - m_OnOpen[node] = true; - } - - public override Direction[] Find(Mobile m, Map map, Point3D start, Point3D goal) - { - if (!Utility.InRange(start, goal, AreaSize)) - return null; - - m_Touched.SetAll(false); - - m_Goal = goal; - - m_xOffset = (start.X + goal.X - AreaSize) / 2; - m_yOffset = (start.Y + goal.Y - AreaSize) / 2; - - int fromNode = GetIndex(start.X, start.Y, start.Z); - int destNode = GetIndex(goal.X, goal.Y, goal.Z); - - m_OpenList = fromNode; - - m_Nodes[m_OpenList].cost = 0; - m_Nodes[m_OpenList].total = Heuristic(start.X - m_xOffset, start.Y - m_yOffset, start.Z); - m_Nodes[m_OpenList].parent = -1; - m_Nodes[m_OpenList].next = -1; - m_Nodes[m_OpenList].prev = -1; - m_Nodes[m_OpenList].z = start.Z; - - m_OnOpen[m_OpenList] = true; - m_Touched[m_OpenList] = true; - - BaseCreature bc = m as BaseCreature; - - int backtrack = 0, depth = 0; - - Direction[] path = m_Path; - - while (m_OpenList != -1) - { - int bestNode = FindBest(m_OpenList); - - if (++depth > MaxDepth) - break; - - if (bc != null) - { - MoveImpl.AlwaysIgnoreDoors = bc.CanOpenDoors; - MoveImpl.IgnoreMovableImpassables = bc.CanMoveOverObstacles; - } - - MoveImpl.Goal = goal; - - int[] vals = m_Successors; - int count = GetSuccessors(bestNode, m, map); - - MoveImpl.AlwaysIgnoreDoors = false; - MoveImpl.IgnoreMovableImpassables = false; - MoveImpl.Goal = Point3D.Zero; - - if (count == 0) - break; - - for (int i = 0; i < count; ++i) - { - int newNode = vals[i]; - - bool wasTouched = m_Touched[newNode]; - - if (wasTouched) - continue; - - int newCost = m_Nodes[bestNode].cost + 1; - int newTotal = newCost + Heuristic(newNode % AreaSize, newNode / AreaSize % AreaSize, - m_Nodes[newNode].z); - - if (m_Nodes[newNode].total <= newTotal) - continue; - - m_Nodes[newNode].parent = bestNode; - m_Nodes[newNode].cost = newCost; - m_Nodes[newNode].total = newTotal; - - if (m_OnOpen[newNode]) - continue; - - AddToChain(newNode); - - if (newNode != destNode) - continue; - - int pathCount = 0; - int parent = m_Nodes[newNode].parent; - - while (parent != -1) - { - path[pathCount++] = GetDirection(parent % AreaSize, parent / AreaSize % AreaSize, - newNode % AreaSize, newNode / AreaSize % AreaSize); - newNode = parent; - parent = m_Nodes[newNode].parent; - - if (newNode == fromNode) - break; - } - - Direction[] dirs = new Direction[pathCount]; - - while (pathCount > 0) - dirs[backtrack++] = path[--pathCount]; - - return dirs; - } - } - - return null; - } - - private int GetIndex(int x, int y, int z) - { - x -= m_xOffset; - y -= m_yOffset; - z += PlaneOffset; - z /= PlaneHeight; - - return x + y * AreaSize + z * AreaSize * AreaSize; - } - - private int FindBest(int node) - { - int least = m_Nodes[node].total; - int leastNode = node; - - while (node != -1) - { - if (m_Nodes[node].total < least) - { - least = m_Nodes[node].total; - leastNode = node; - } - - node = m_Nodes[node].next; - } - - RemoveFromChain(leastNode); - - m_Touched[leastNode] = true; - m_OnOpen[leastNode] = false; - - return leastNode; - } - - public int GetSuccessors(int p, Mobile m, Map map) - { - int px = p % AreaSize; - int py = p / AreaSize % AreaSize; - int pz = m_Nodes[p].z; - - Point3D p3D = new Point3D(px + m_xOffset, py + m_yOffset, pz); - - int[] vals = m_Successors; - int count = 0; - - for (int i = 0; i < 8; ++i) - { - int x; - int y; - switch (i) - { - default: - case 0: - x = 0; - y = -1; - break; - case 1: - x = 1; - y = -1; - break; - case 2: - x = 1; - y = 0; - break; - case 3: - x = 1; - y = 1; - break; - case 4: - x = 0; - y = 1; - break; - case 5: - x = -1; - y = 1; - break; - case 6: - x = -1; - y = 0; - break; - case 7: - x = -1; - y = -1; - break; - } - - x += px; - y += py; - - if (x < 0 || x >= AreaSize || y < 0 || y >= AreaSize) - continue; - - if (CalcMoves.CheckMovement(m, map, p3D, (Direction)i, out int z)) - { - int idx = GetIndex(x + m_xOffset, y + m_yOffset, z); - - if (idx >= 0 && idx < NodeCount) - { - m_Nodes[idx].z = z; - vals[count++] = idx; - } - } - } - - return count; - } - } -} +using System.Collections; +using Server.Mobiles; +using CalcMoves = Server.Movement.Movement; +using MoveImpl = Server.Movement.MovementImpl; + +namespace Server.PathAlgorithms.FastAStar +{ + public struct PathNode + { + public int cost, total; + public int parent, next, prev; + public int z; + } + + public class FastAStarAlgorithm : PathAlgorithm + { + private const int MaxDepth = 300; + private const int AreaSize = 38; + + private const int NodeCount = AreaSize * AreaSize * PlaneCount; + + private const int PlaneOffset = 128; + private const int PlaneCount = 13; + private const int PlaneHeight = 20; + public static PathAlgorithm Instance = new FastAStarAlgorithm(); + + private static readonly Direction[] m_Path = new Direction[AreaSize * AreaSize]; + private static readonly PathNode[] m_Nodes = new PathNode[NodeCount]; + private static readonly BitArray m_Touched = new BitArray(NodeCount); + private static readonly BitArray m_OnOpen = new BitArray(NodeCount); + private static readonly int[] m_Successors = new int[8]; + + private static int m_xOffset, m_yOffset; + private static int m_OpenList; + + private Point3D m_Goal; + + public int Heuristic(int x, int y, int z) + { + x -= m_Goal.X - m_xOffset; + y -= m_Goal.Y - m_yOffset; + z -= m_Goal.Z; + + x *= 11; + y *= 11; + + return x * x + y * y + z * z; + } + + public override bool CheckCondition(Mobile m, Map map, Point3D start, Point3D goal) => + Utility.InRange(start, goal, AreaSize); + + private void RemoveFromChain(int node) + { + if (node < 0 || node >= NodeCount) + return; + + if (!m_Touched[node] || !m_OnOpen[node]) + return; + + var prev = m_Nodes[node].prev; + var next = m_Nodes[node].next; + + if (m_OpenList == node) + m_OpenList = next; + + if (prev != -1) + m_Nodes[prev].next = next; + + if (next != -1) + m_Nodes[next].prev = prev; + + m_Nodes[node].prev = -1; + m_Nodes[node].next = -1; + } + + private void AddToChain(int node) + { + if (node < 0 || node >= NodeCount) + return; + + RemoveFromChain(node); + + if (m_OpenList != -1) + m_Nodes[m_OpenList].prev = node; + + m_Nodes[node].next = m_OpenList; + m_Nodes[node].prev = -1; + + m_OpenList = node; + + m_Touched[node] = true; + m_OnOpen[node] = true; + } + + public override Direction[] Find(Mobile m, Map map, Point3D start, Point3D goal) + { + if (!Utility.InRange(start, goal, AreaSize)) + return null; + + m_Touched.SetAll(false); + + m_Goal = goal; + + m_xOffset = (start.X + goal.X - AreaSize) / 2; + m_yOffset = (start.Y + goal.Y - AreaSize) / 2; + + var fromNode = GetIndex(start.X, start.Y, start.Z); + var destNode = GetIndex(goal.X, goal.Y, goal.Z); + + m_OpenList = fromNode; + + m_Nodes[m_OpenList].cost = 0; + m_Nodes[m_OpenList].total = Heuristic(start.X - m_xOffset, start.Y - m_yOffset, start.Z); + m_Nodes[m_OpenList].parent = -1; + m_Nodes[m_OpenList].next = -1; + m_Nodes[m_OpenList].prev = -1; + m_Nodes[m_OpenList].z = start.Z; + + m_OnOpen[m_OpenList] = true; + m_Touched[m_OpenList] = true; + + var bc = m as BaseCreature; + + int backtrack = 0, depth = 0; + + var path = m_Path; + + while (m_OpenList != -1) + { + var bestNode = FindBest(m_OpenList); + + if (++depth > MaxDepth) + break; + + if (bc != null) + { + MoveImpl.AlwaysIgnoreDoors = bc.CanOpenDoors; + MoveImpl.IgnoreMovableImpassables = bc.CanMoveOverObstacles; + } + + MoveImpl.Goal = goal; + + var vals = m_Successors; + var count = GetSuccessors(bestNode, m, map); + + MoveImpl.AlwaysIgnoreDoors = false; + MoveImpl.IgnoreMovableImpassables = false; + MoveImpl.Goal = Point3D.Zero; + + if (count == 0) + break; + + for (var i = 0; i < count; ++i) + { + var newNode = vals[i]; + + var wasTouched = m_Touched[newNode]; + + if (wasTouched) + continue; + + var newCost = m_Nodes[bestNode].cost + 1; + var newTotal = newCost + Heuristic( + newNode % AreaSize, + newNode / AreaSize % AreaSize, + m_Nodes[newNode].z + ); + + if (m_Nodes[newNode].total <= newTotal) + continue; + + m_Nodes[newNode].parent = bestNode; + m_Nodes[newNode].cost = newCost; + m_Nodes[newNode].total = newTotal; + + if (m_OnOpen[newNode]) + continue; + + AddToChain(newNode); + + if (newNode != destNode) + continue; + + var pathCount = 0; + var parent = m_Nodes[newNode].parent; + + while (parent != -1) + { + path[pathCount++] = GetDirection( + parent % AreaSize, + parent / AreaSize % AreaSize, + newNode % AreaSize, + newNode / AreaSize % AreaSize + ); + newNode = parent; + parent = m_Nodes[newNode].parent; + + if (newNode == fromNode) + break; + } + + var dirs = new Direction[pathCount]; + + while (pathCount > 0) + dirs[backtrack++] = path[--pathCount]; + + return dirs; + } + } + + return null; + } + + private int GetIndex(int x, int y, int z) + { + x -= m_xOffset; + y -= m_yOffset; + z += PlaneOffset; + z /= PlaneHeight; + + return x + y * AreaSize + z * AreaSize * AreaSize; + } + + private int FindBest(int node) + { + var least = m_Nodes[node].total; + var leastNode = node; + + while (node != -1) + { + if (m_Nodes[node].total < least) + { + least = m_Nodes[node].total; + leastNode = node; + } + + node = m_Nodes[node].next; + } + + RemoveFromChain(leastNode); + + m_Touched[leastNode] = true; + m_OnOpen[leastNode] = false; + + return leastNode; + } + + public int GetSuccessors(int p, Mobile m, Map map) + { + var px = p % AreaSize; + var py = p / AreaSize % AreaSize; + var pz = m_Nodes[p].z; + + var p3D = new Point3D(px + m_xOffset, py + m_yOffset, pz); + + var vals = m_Successors; + var count = 0; + + for (var i = 0; i < 8; ++i) + { + int x; + int y; + switch (i) + { + default: + case 0: + x = 0; + y = -1; + break; + case 1: + x = 1; + y = -1; + break; + case 2: + x = 1; + y = 0; + break; + case 3: + x = 1; + y = 1; + break; + case 4: + x = 0; + y = 1; + break; + case 5: + x = -1; + y = 1; + break; + case 6: + x = -1; + y = 0; + break; + case 7: + x = -1; + y = -1; + break; + } + + x += px; + y += py; + + if (x < 0 || x >= AreaSize || y < 0 || y >= AreaSize) + continue; + + if (CalcMoves.CheckMovement(m, map, p3D, (Direction)i, out var z)) + { + var idx = GetIndex(x + m_xOffset, y + m_yOffset, z); + + if (idx >= 0 && idx < NodeCount) + { + m_Nodes[idx].z = z; + vals[count++] = idx; + } + } + } + + return count; + } + } +} diff --git a/Projects/UOContent/Engines/Pathing/FastMovement.cs b/Projects/UOContent/Engines/Pathing/FastMovement.cs index 74cffe328..d7fb73a1f 100644 --- a/Projects/UOContent/Engines/Pathing/FastMovement.cs +++ b/Projects/UOContent/Engines/Pathing/FastMovement.cs @@ -1,524 +1,527 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Server.Items; -using Server.Mobiles; - -namespace Server.Movement -{ - public class FastMovementImpl : IMovementImpl - { - private const int PersonHeight = 16; - private const int StepHeight = 2; - - private const TileFlag ImpassableSurface = TileFlag.Impassable | TileFlag.Surface; - public static bool Enabled = false; - - private static IMovementImpl _Successor; - - private FastMovementImpl() - { - } - - public bool CheckMovement(Mobile m, Map map, Point3D loc, Direction d, out int newZ) - { - if (!Enabled && _Successor != null) return _Successor.CheckMovement(m, map, loc, d, out newZ); - - if (map == null || map == Map.Internal) - { - newZ = 0; - return false; - } - - int xStart = loc.X; - int yStart = loc.Y; - - int xForward = xStart, yForward = yStart; - int xRight = xStart, yRight = yStart; - int xLeft = xStart, yLeft = yStart; - - bool checkDiagonals = ((int)d & 0x1) == 0x1; - - Offset(d, ref xForward, ref yForward); - Offset((Direction)((int)d - 1 & 0x7), ref xLeft, ref yLeft); - Offset((Direction)((int)d + 1 & 0x7), ref xRight, ref yRight); - - if (xForward < 0 || yForward < 0 || xForward >= map.Width || yForward >= map.Height) - { - newZ = 0; - return false; - } - - IEnumerable itemsStart, itemsForward, itemsLeft, itemsRight; - - bool ignoreMovableImpassables = MovementImpl.IgnoreMovableImpassables; - TileFlag reqFlags = ImpassableSurface; - - if (m.CanSwim) reqFlags |= TileFlag.Wet; - - if (checkDiagonals) - { - Sector sStart = map.GetSector(xStart, yStart); - Sector sForward = map.GetSector(xForward, yForward); - Sector sLeft = map.GetSector(xLeft, yLeft); - Sector sRight = map.GetSector(xRight, yRight); - - itemsStart = sStart.Items.Where(i => Verify(i, reqFlags, ignoreMovableImpassables, xStart, yStart)); - itemsForward = sForward.Items.Where(i => Verify(i, reqFlags, ignoreMovableImpassables, xForward, yForward)); - itemsLeft = sLeft.Items.Where(i => Verify(i, reqFlags, ignoreMovableImpassables, xLeft, yLeft)); - itemsRight = sRight.Items.Where(i => Verify(i, reqFlags, ignoreMovableImpassables, xRight, yRight)); - } - else - { - Sector sStart = map.GetSector(xStart, yStart); - Sector sForward = map.GetSector(xForward, yForward); - - itemsStart = sStart.Items.Where(i => Verify(i, reqFlags, ignoreMovableImpassables, xStart, yStart)); - itemsForward = sForward.Items.Where(i => Verify(i, reqFlags, ignoreMovableImpassables, xForward, yForward)); - itemsLeft = Enumerable.Empty(); - itemsRight = Enumerable.Empty(); - } - - GetStartZ(m, map, loc, itemsStart, out int startZ, out int startTop); - - List list = null; - - MovementPool.AcquireMoveCache(ref list, itemsForward); - - bool moveIsOk = Check(map, m, list, xForward, yForward, startTop, startZ, m.CanSwim, m.CantWalk, out newZ); - - if (moveIsOk && checkDiagonals) - { - if (m.Player && m.AccessLevel < AccessLevel.GameMaster) - { - MovementPool.AcquireMoveCache(ref list, itemsLeft); - - if (!Check(map, m, list, xLeft, yLeft, startTop, startZ, m.CanSwim, m.CantWalk, out _)) - { - moveIsOk = false; - } - else - { - MovementPool.AcquireMoveCache(ref list, itemsRight); - - if (!Check(map, m, list, xRight, yRight, startTop, startZ, m.CanSwim, m.CantWalk, out _)) - moveIsOk = false; - } - } - else - { - MovementPool.AcquireMoveCache(ref list, itemsLeft); - - if (!Check(map, m, list, xLeft, yLeft, startTop, startZ, m.CanSwim, m.CantWalk, out _)) - { - MovementPool.AcquireMoveCache(ref list, itemsRight); - - if (!Check(map, m, list, xRight, yRight, startTop, startZ, m.CanSwim, m.CantWalk, out _)) - moveIsOk = false; - } - } - } - - MovementPool.ClearMoveCache(ref list, true); - - if (!moveIsOk) newZ = startZ; - - return moveIsOk; - } - - public bool CheckMovement(Mobile m, Direction d, out int newZ) => - !Enabled && _Successor != null - ? _Successor.CheckMovement(m, d, out newZ) - : CheckMovement(m, m.Map, m.Location, d, out newZ); - - public static void Initialize() - { - _Successor = Movement.Impl; - Movement.Impl = new FastMovementImpl(); - } - - private static bool IsOk(StaticTile tile, int ourZ, int ourTop) - { - ItemData itemData = TileData.ItemTable[tile.ID & TileData.MaxItemValue]; - - return tile.Z + itemData.CalcHeight <= ourZ || ourTop <= tile.Z || (itemData.Flags & ImpassableSurface) == 0; - } - - private static bool IsOk(Item item, int ourZ, int ourTop, bool ignoreDoors, bool ignoreSpellFields) - { - int itemID = item.ItemID & TileData.MaxItemValue; - ItemData itemData = TileData.ItemTable[itemID]; - - if ((itemData.Flags & ImpassableSurface) == 0) return true; - - if (((itemData.Flags & TileFlag.Door) != 0 || itemID == 0x692 || itemID == 0x846 || itemID == 0x873 || - (itemID >= 0x6F5 && itemID <= 0x6F6)) && ignoreDoors) - return true; - - if ((itemID == 0x82 || itemID == 0x3946 || itemID == 0x3956) && ignoreSpellFields) return true; - - return item.Z + itemData.CalcHeight <= ourZ || ourTop <= item.Z; - } - - private static bool IsOk( - bool ignoreDoors, - bool ignoreSpellFields, - int ourZ, - int ourTop, - IEnumerable tiles, - IEnumerable items) - { - return tiles.All(t => IsOk(t, ourZ, ourTop)) && - items.All(i => IsOk(i, ourZ, ourTop, ignoreDoors, ignoreSpellFields)); - } - - private static bool Check( - Map map, - Mobile m, - List items, - int x, - int y, - int startTop, - int startZ, - bool canSwim, - bool cantWalk, - out int newZ) - { - newZ = 0; - - StaticTile[] tiles = map.Tiles.GetStaticTiles(x, y, true); - LandTile landTile = map.Tiles.GetLandTile(x, y); - LandData landData = TileData.LandTable[landTile.ID & TileData.MaxLandValue]; - bool landBlocks = (landData.Flags & TileFlag.Impassable) != 0; - bool considerLand = !landTile.Ignored; - - if (landBlocks && canSwim && (landData.Flags & TileFlag.Wet) != 0) - landBlocks = false; - else if (cantWalk && (landData.Flags & TileFlag.Wet) == 0) landBlocks = true; - - int landZ = 0, landCenter = 0, landTop = 0; - - map.GetAverageZ(x, y, ref landZ, ref landCenter, ref landTop); - - bool moveIsOk = false; - - int stepTop = startTop + StepHeight; - int checkTop = startZ + PersonHeight; - - bool ignoreDoors = MovementImpl.AlwaysIgnoreDoors || !m.Alive || m.IsDeadBondedPet || m.Body.IsGhost || - m.Body.BodyID == 987; - bool ignoreSpellFields = m is PlayerMobile && map.MapID != 0; - - int itemZ, itemTop, ourZ, ourTop, testTop; - ItemData itemData; - TileFlag flags; - - foreach (StaticTile tile in tiles) - { - itemData = TileData.ItemTable[tile.ID & TileData.MaxItemValue]; - - if (m.Flying && Insensitive.Equals(itemData.Name, "hover over")) - { - newZ = tile.Z; - return true; - } - - // Stygian Dragon - if (m.Body == 826 && map?.MapID == 5) - { - if (x >= 307 && x <= 354 && y >= 126 && y <= 192) - { - if (tile.Z > newZ) newZ = tile.Z; - - moveIsOk = true; - } - else if (x >= 42 && x <= 89) - { - if ((y >= 333 && y <= 399) || (y >= 531 && y <= 597) || (y >= 739 && y <= 805)) - { - if (tile.Z > newZ) newZ = tile.Z; - - moveIsOk = true; - } - } - } - - flags = itemData.Flags; - - if ((flags & ImpassableSurface) != TileFlag.Surface && (!canSwim || (flags & TileFlag.Wet) == 0)) continue; - - if (cantWalk && (flags & TileFlag.Wet) == 0) continue; - - itemZ = tile.Z; - itemTop = itemZ; - ourZ = itemZ + itemData.CalcHeight; - ourTop = ourZ + PersonHeight; - testTop = checkTop; - - if (moveIsOk) - { - int cmp = Math.Abs(ourZ - m.Z) - Math.Abs(newZ - m.Z); - - if (cmp > 0 || (cmp == 0 && ourZ > newZ)) continue; - } - - if (ourTop > testTop) testTop = ourTop; - - if (!itemData.Bridge) itemTop += itemData.Height; - - if (stepTop < itemTop) continue; - - int landCheck = itemZ; - - if (itemData.Height >= StepHeight) - landCheck += StepHeight; - else - landCheck += itemData.Height; - - if (considerLand && landCheck < landCenter && landCenter > ourZ && testTop > landZ) continue; - - if (!IsOk(ignoreDoors, ignoreSpellFields, ourZ, testTop, tiles, items)) continue; - - newZ = ourZ; - moveIsOk = true; - } - - foreach (Item item in items) - { - itemData = item.ItemData; - flags = itemData.Flags; - - if (m.Flying && Insensitive.Equals(itemData.Name, "hover over")) - { - newZ = item.Z; - return true; - } - - if (item.Movable) continue; - - if ((flags & ImpassableSurface) != TileFlag.Surface && (!m.CanSwim || (flags & TileFlag.Wet) == 0)) continue; - - if (cantWalk && (flags & TileFlag.Wet) == 0) continue; - - itemZ = item.Z; - itemTop = itemZ; - ourZ = itemZ + itemData.CalcHeight; - ourTop = ourZ + PersonHeight; - testTop = checkTop; - - if (moveIsOk) - { - int cmp = Math.Abs(ourZ - m.Z) - Math.Abs(newZ - m.Z); - - if (cmp > 0 || (cmp == 0 && ourZ > newZ)) continue; - } - - if (ourTop > testTop) testTop = ourTop; - - if (!itemData.Bridge) itemTop += itemData.Height; - - if (stepTop < itemTop) continue; - - int landCheck = itemZ; - - if (itemData.Height >= StepHeight) - landCheck += StepHeight; - else - landCheck += itemData.Height; - - if (considerLand && landCheck < landCenter && landCenter > ourZ && testTop > landZ) continue; - - if (!IsOk(ignoreDoors, ignoreSpellFields, ourZ, testTop, tiles, items)) continue; - - newZ = ourZ; - moveIsOk = true; - } - - if (!considerLand || landBlocks || stepTop < landZ) return moveIsOk; - - ourZ = landCenter; - ourTop = ourZ + PersonHeight; - testTop = checkTop; - - if (ourTop > testTop) testTop = ourTop; - - bool shouldCheck = true; - - if (moveIsOk) - { - int cmp = Math.Abs(ourZ - m.Z) - Math.Abs(newZ - m.Z); - - if (cmp > 0 || (cmp == 0 && ourZ > newZ)) shouldCheck = false; - } - - if (!shouldCheck || !IsOk(ignoreDoors, ignoreSpellFields, ourZ, testTop, tiles, items)) return moveIsOk; - - newZ = ourZ; - moveIsOk = true; - - return moveIsOk; - } - - private static bool Verify(Item item, int x, int y) => item.AtWorldPoint(x, y); - - private static bool Verify(Item item, TileFlag reqFlags, bool ignoreMovableImpassables) => - item != null && (!ignoreMovableImpassables || !item.Movable || !item.ItemData.Impassable) && - (item.ItemData.Flags & reqFlags) != 0 && !(item is BaseMulti) && item.ItemID <= TileData.MaxItemValue; - - private static bool Verify(Item item, TileFlag reqFlags, bool ignoreMovableImpassables, int x, int y) => Verify(item, reqFlags, ignoreMovableImpassables) && Verify(item, x, y); - - private static void GetStartZ(Mobile m, Map map, Point3D loc, IEnumerable itemList, out int zLow, out int zTop) - { - int xCheck = loc.X, yCheck = loc.Y; - - LandTile landTile = map.Tiles.GetLandTile(xCheck, yCheck); - LandData landData = TileData.LandTable[landTile.ID & TileData.MaxLandValue]; - bool landBlocks = (landData.Flags & TileFlag.Impassable) != 0; - - if (landBlocks && m.CanSwim && (landData.Flags & TileFlag.Wet) != 0) - landBlocks = false; - else if (m.CantWalk && (landData.Flags & TileFlag.Wet) == 0) landBlocks = true; - - int landZ = 0, landCenter = 0, landTop = 0; - - map.GetAverageZ(xCheck, yCheck, ref landZ, ref landCenter, ref landTop); - - bool considerLand = !landTile.Ignored; - - int zCenter = zLow = zTop = 0; - bool isSet = false; - - if (considerLand && !landBlocks && loc.Z >= landCenter) - { - zLow = landZ; - zCenter = landCenter; - zTop = landTop; - isSet = true; - } - - StaticTile[] staticTiles = map.Tiles.GetStaticTiles(xCheck, yCheck, true); - - foreach (StaticTile tile in staticTiles) - { - ItemData tileData = TileData.ItemTable[tile.ID & TileData.MaxItemValue]; - int calcTop = tile.Z + tileData.CalcHeight; - - if (isSet && calcTop < zCenter) continue; - - if ((tileData.Flags & TileFlag.Surface) == 0 && - (!m.CanSwim || (tileData.Flags & TileFlag.Wet) == 0)) continue; - - if (loc.Z < calcTop) continue; - - if (m.CantWalk && (tileData.Flags & TileFlag.Wet) == 0) continue; - - zLow = tile.Z; - zCenter = calcTop; - - int top = tile.Z + tileData.Height; - - if (!isSet || top > zTop) zTop = top; - - isSet = true; - } - - foreach (Item item in itemList) - { - ItemData itemData = item.ItemData; - - int calcTop = item.Z + itemData.CalcHeight; - - if (isSet && calcTop < zCenter) continue; - - if ((itemData.Flags & TileFlag.Surface) == 0 && - (!m.CanSwim || (itemData.Flags & TileFlag.Wet) == 0)) continue; - - if (loc.Z < calcTop) continue; - - if (m.CantWalk && (itemData.Flags & TileFlag.Wet) == 0) continue; - - zLow = item.Z; - zCenter = calcTop; - - int top = item.Z + itemData.Height; - - if (!isSet || top > zTop) zTop = top; - - isSet = true; - } - - if (!isSet) - zLow = zTop = loc.Z; - else if (loc.Z > zTop) - zTop = loc.Z; - } - - public void Offset(Direction d, ref int x, ref int y) - { - switch (d & Direction.Mask) - { - case Direction.North: - --y; - break; - case Direction.South: - ++y; - break; - case Direction.West: - --x; - break; - case Direction.East: - ++x; - break; - case Direction.Right: - ++x; - --y; - break; - case Direction.Left: - --x; - ++y; - break; - case Direction.Down: - ++x; - ++y; - break; - case Direction.Up: - --x; - --y; - break; - } - } - - private static class MovementPool - { - private static readonly object _MovePoolLock = new object(); - private static readonly Queue> _MoveCachePool = new Queue>(0x400); - - public static void AcquireMoveCache(ref List cache, IEnumerable items) - { - if (cache == null) - lock (_MovePoolLock) - { - cache = _MoveCachePool.Count > 0 ? _MoveCachePool.Dequeue() : new List(0x10); - } - else - cache.Clear(); - - cache.AddRange(items); - } - - public static void ClearMoveCache(ref List cache, bool free) - { - cache?.Clear(); - - if (!free) return; - - lock (_MovePoolLock) - { - if (_MoveCachePool.Count < 0x400) _MoveCachePool.Enqueue(cache); - } - - cache = null; - } - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using Server.Items; +using Server.Mobiles; + +namespace Server.Movement +{ + public class FastMovementImpl : IMovementImpl + { + private const int PersonHeight = 16; + private const int StepHeight = 2; + + private const TileFlag ImpassableSurface = TileFlag.Impassable | TileFlag.Surface; + public static bool Enabled = false; + + private static IMovementImpl _Successor; + + private FastMovementImpl() + { + } + + public bool CheckMovement(Mobile m, Map map, Point3D loc, Direction d, out int newZ) + { + if (!Enabled && _Successor != null) return _Successor.CheckMovement(m, map, loc, d, out newZ); + + if (map == null || map == Map.Internal) + { + newZ = 0; + return false; + } + + var xStart = loc.X; + var yStart = loc.Y; + + int xForward = xStart, yForward = yStart; + int xRight = xStart, yRight = yStart; + int xLeft = xStart, yLeft = yStart; + + var checkDiagonals = ((int)d & 0x1) == 0x1; + + Offset(d, ref xForward, ref yForward); + Offset((Direction)(((int)d - 1) & 0x7), ref xLeft, ref yLeft); + Offset((Direction)(((int)d + 1) & 0x7), ref xRight, ref yRight); + + if (xForward < 0 || yForward < 0 || xForward >= map.Width || yForward >= map.Height) + { + newZ = 0; + return false; + } + + IEnumerable itemsStart, itemsForward, itemsLeft, itemsRight; + + var ignoreMovableImpassables = MovementImpl.IgnoreMovableImpassables; + var reqFlags = ImpassableSurface; + + if (m.CanSwim) reqFlags |= TileFlag.Wet; + + if (checkDiagonals) + { + var sStart = map.GetSector(xStart, yStart); + var sForward = map.GetSector(xForward, yForward); + var sLeft = map.GetSector(xLeft, yLeft); + var sRight = map.GetSector(xRight, yRight); + + itemsStart = sStart.Items.Where(i => Verify(i, reqFlags, ignoreMovableImpassables, xStart, yStart)); + itemsForward = sForward.Items.Where(i => Verify(i, reqFlags, ignoreMovableImpassables, xForward, yForward)); + itemsLeft = sLeft.Items.Where(i => Verify(i, reqFlags, ignoreMovableImpassables, xLeft, yLeft)); + itemsRight = sRight.Items.Where(i => Verify(i, reqFlags, ignoreMovableImpassables, xRight, yRight)); + } + else + { + var sStart = map.GetSector(xStart, yStart); + var sForward = map.GetSector(xForward, yForward); + + itemsStart = sStart.Items.Where(i => Verify(i, reqFlags, ignoreMovableImpassables, xStart, yStart)); + itemsForward = sForward.Items.Where(i => Verify(i, reqFlags, ignoreMovableImpassables, xForward, yForward)); + itemsLeft = Enumerable.Empty(); + itemsRight = Enumerable.Empty(); + } + + GetStartZ(m, map, loc, itemsStart, out var startZ, out var startTop); + + List list = null; + + MovementPool.AcquireMoveCache(ref list, itemsForward); + + var moveIsOk = Check(map, m, list, xForward, yForward, startTop, startZ, m.CanSwim, m.CantWalk, out newZ); + + if (moveIsOk && checkDiagonals) + { + if (m.Player && m.AccessLevel < AccessLevel.GameMaster) + { + MovementPool.AcquireMoveCache(ref list, itemsLeft); + + if (!Check(map, m, list, xLeft, yLeft, startTop, startZ, m.CanSwim, m.CantWalk, out _)) + { + moveIsOk = false; + } + else + { + MovementPool.AcquireMoveCache(ref list, itemsRight); + + if (!Check(map, m, list, xRight, yRight, startTop, startZ, m.CanSwim, m.CantWalk, out _)) + moveIsOk = false; + } + } + else + { + MovementPool.AcquireMoveCache(ref list, itemsLeft); + + if (!Check(map, m, list, xLeft, yLeft, startTop, startZ, m.CanSwim, m.CantWalk, out _)) + { + MovementPool.AcquireMoveCache(ref list, itemsRight); + + if (!Check(map, m, list, xRight, yRight, startTop, startZ, m.CanSwim, m.CantWalk, out _)) + moveIsOk = false; + } + } + } + + MovementPool.ClearMoveCache(ref list, true); + + if (!moveIsOk) newZ = startZ; + + return moveIsOk; + } + + public bool CheckMovement(Mobile m, Direction d, out int newZ) => + !Enabled && _Successor != null + ? _Successor.CheckMovement(m, d, out newZ) + : CheckMovement(m, m.Map, m.Location, d, out newZ); + + public static void Initialize() + { + _Successor = Movement.Impl; + Movement.Impl = new FastMovementImpl(); + } + + private static bool IsOk(StaticTile tile, int ourZ, int ourTop) + { + var itemData = TileData.ItemTable[tile.ID & TileData.MaxItemValue]; + + return tile.Z + itemData.CalcHeight <= ourZ || ourTop <= tile.Z || (itemData.Flags & ImpassableSurface) == 0; + } + + private static bool IsOk(Item item, int ourZ, int ourTop, bool ignoreDoors, bool ignoreSpellFields) + { + var itemID = item.ItemID & TileData.MaxItemValue; + var itemData = TileData.ItemTable[itemID]; + + if ((itemData.Flags & ImpassableSurface) == 0) return true; + + if (((itemData.Flags & TileFlag.Door) != 0 || itemID == 0x692 || itemID == 0x846 || itemID == 0x873 || + itemID >= 0x6F5 && itemID <= 0x6F6) && ignoreDoors) + return true; + + if ((itemID == 0x82 || itemID == 0x3946 || itemID == 0x3956) && ignoreSpellFields) return true; + + return item.Z + itemData.CalcHeight <= ourZ || ourTop <= item.Z; + } + + private static bool IsOk( + bool ignoreDoors, + bool ignoreSpellFields, + int ourZ, + int ourTop, + IEnumerable tiles, + IEnumerable items + ) + { + return tiles.All(t => IsOk(t, ourZ, ourTop)) && + items.All(i => IsOk(i, ourZ, ourTop, ignoreDoors, ignoreSpellFields)); + } + + private static bool Check( + Map map, + Mobile m, + List items, + int x, + int y, + int startTop, + int startZ, + bool canSwim, + bool cantWalk, + out int newZ + ) + { + newZ = 0; + + var tiles = map.Tiles.GetStaticTiles(x, y, true); + var landTile = map.Tiles.GetLandTile(x, y); + var landData = TileData.LandTable[landTile.ID & TileData.MaxLandValue]; + var landBlocks = (landData.Flags & TileFlag.Impassable) != 0; + var considerLand = !landTile.Ignored; + + if (landBlocks && canSwim && (landData.Flags & TileFlag.Wet) != 0) + landBlocks = false; + else if (cantWalk && (landData.Flags & TileFlag.Wet) == 0) landBlocks = true; + + int landZ = 0, landCenter = 0, landTop = 0; + + map.GetAverageZ(x, y, ref landZ, ref landCenter, ref landTop); + + var moveIsOk = false; + + var stepTop = startTop + StepHeight; + var checkTop = startZ + PersonHeight; + + var ignoreDoors = MovementImpl.AlwaysIgnoreDoors || !m.Alive || m.IsDeadBondedPet || m.Body.IsGhost || + m.Body.BodyID == 987; + var ignoreSpellFields = m is PlayerMobile && map.MapID != 0; + + int itemZ, itemTop, ourZ, ourTop, testTop; + ItemData itemData; + TileFlag flags; + + foreach (var tile in tiles) + { + itemData = TileData.ItemTable[tile.ID & TileData.MaxItemValue]; + + if (m.Flying && Insensitive.Equals(itemData.Name, "hover over")) + { + newZ = tile.Z; + return true; + } + + // Stygian Dragon + if (m.Body == 826 && map?.MapID == 5) + { + if (x >= 307 && x <= 354 && y >= 126 && y <= 192) + { + if (tile.Z > newZ) newZ = tile.Z; + + moveIsOk = true; + } + else if (x >= 42 && x <= 89) + { + if (y >= 333 && y <= 399 || y >= 531 && y <= 597 || y >= 739 && y <= 805) + { + if (tile.Z > newZ) newZ = tile.Z; + + moveIsOk = true; + } + } + } + + flags = itemData.Flags; + + if ((flags & ImpassableSurface) != TileFlag.Surface && (!canSwim || (flags & TileFlag.Wet) == 0)) continue; + + if (cantWalk && (flags & TileFlag.Wet) == 0) continue; + + itemZ = tile.Z; + itemTop = itemZ; + ourZ = itemZ + itemData.CalcHeight; + ourTop = ourZ + PersonHeight; + testTop = checkTop; + + if (moveIsOk) + { + var cmp = Math.Abs(ourZ - m.Z) - Math.Abs(newZ - m.Z); + + if (cmp > 0 || cmp == 0 && ourZ > newZ) continue; + } + + if (ourTop > testTop) testTop = ourTop; + + if (!itemData.Bridge) itemTop += itemData.Height; + + if (stepTop < itemTop) continue; + + var landCheck = itemZ; + + if (itemData.Height >= StepHeight) + landCheck += StepHeight; + else + landCheck += itemData.Height; + + if (considerLand && landCheck < landCenter && landCenter > ourZ && testTop > landZ) continue; + + if (!IsOk(ignoreDoors, ignoreSpellFields, ourZ, testTop, tiles, items)) continue; + + newZ = ourZ; + moveIsOk = true; + } + + foreach (var item in items) + { + itemData = item.ItemData; + flags = itemData.Flags; + + if (m.Flying && Insensitive.Equals(itemData.Name, "hover over")) + { + newZ = item.Z; + return true; + } + + if (item.Movable) continue; + + if ((flags & ImpassableSurface) != TileFlag.Surface && (!m.CanSwim || (flags & TileFlag.Wet) == 0)) continue; + + if (cantWalk && (flags & TileFlag.Wet) == 0) continue; + + itemZ = item.Z; + itemTop = itemZ; + ourZ = itemZ + itemData.CalcHeight; + ourTop = ourZ + PersonHeight; + testTop = checkTop; + + if (moveIsOk) + { + var cmp = Math.Abs(ourZ - m.Z) - Math.Abs(newZ - m.Z); + + if (cmp > 0 || cmp == 0 && ourZ > newZ) continue; + } + + if (ourTop > testTop) testTop = ourTop; + + if (!itemData.Bridge) itemTop += itemData.Height; + + if (stepTop < itemTop) continue; + + var landCheck = itemZ; + + if (itemData.Height >= StepHeight) + landCheck += StepHeight; + else + landCheck += itemData.Height; + + if (considerLand && landCheck < landCenter && landCenter > ourZ && testTop > landZ) continue; + + if (!IsOk(ignoreDoors, ignoreSpellFields, ourZ, testTop, tiles, items)) continue; + + newZ = ourZ; + moveIsOk = true; + } + + if (!considerLand || landBlocks || stepTop < landZ) return moveIsOk; + + ourZ = landCenter; + ourTop = ourZ + PersonHeight; + testTop = checkTop; + + if (ourTop > testTop) testTop = ourTop; + + var shouldCheck = true; + + if (moveIsOk) + { + var cmp = Math.Abs(ourZ - m.Z) - Math.Abs(newZ - m.Z); + + if (cmp > 0 || cmp == 0 && ourZ > newZ) shouldCheck = false; + } + + if (!shouldCheck || !IsOk(ignoreDoors, ignoreSpellFields, ourZ, testTop, tiles, items)) return moveIsOk; + + newZ = ourZ; + moveIsOk = true; + + return moveIsOk; + } + + private static bool Verify(Item item, int x, int y) => item.AtWorldPoint(x, y); + + private static bool Verify(Item item, TileFlag reqFlags, bool ignoreMovableImpassables) => + item != null && (!ignoreMovableImpassables || !item.Movable || !item.ItemData.Impassable) && + (item.ItemData.Flags & reqFlags) != 0 && !(item is BaseMulti) && item.ItemID <= TileData.MaxItemValue; + + private static bool Verify(Item item, TileFlag reqFlags, bool ignoreMovableImpassables, int x, int y) => + Verify(item, reqFlags, ignoreMovableImpassables) && Verify(item, x, y); + + private static void GetStartZ(Mobile m, Map map, Point3D loc, IEnumerable itemList, out int zLow, out int zTop) + { + int xCheck = loc.X, yCheck = loc.Y; + + var landTile = map.Tiles.GetLandTile(xCheck, yCheck); + var landData = TileData.LandTable[landTile.ID & TileData.MaxLandValue]; + var landBlocks = (landData.Flags & TileFlag.Impassable) != 0; + + if (landBlocks && m.CanSwim && (landData.Flags & TileFlag.Wet) != 0) + landBlocks = false; + else if (m.CantWalk && (landData.Flags & TileFlag.Wet) == 0) landBlocks = true; + + int landZ = 0, landCenter = 0, landTop = 0; + + map.GetAverageZ(xCheck, yCheck, ref landZ, ref landCenter, ref landTop); + + var considerLand = !landTile.Ignored; + + var zCenter = zLow = zTop = 0; + var isSet = false; + + if (considerLand && !landBlocks && loc.Z >= landCenter) + { + zLow = landZ; + zCenter = landCenter; + zTop = landTop; + isSet = true; + } + + var staticTiles = map.Tiles.GetStaticTiles(xCheck, yCheck, true); + + foreach (var tile in staticTiles) + { + var tileData = TileData.ItemTable[tile.ID & TileData.MaxItemValue]; + var calcTop = tile.Z + tileData.CalcHeight; + + if (isSet && calcTop < zCenter) continue; + + if ((tileData.Flags & TileFlag.Surface) == 0 && + (!m.CanSwim || (tileData.Flags & TileFlag.Wet) == 0)) continue; + + if (loc.Z < calcTop) continue; + + if (m.CantWalk && (tileData.Flags & TileFlag.Wet) == 0) continue; + + zLow = tile.Z; + zCenter = calcTop; + + var top = tile.Z + tileData.Height; + + if (!isSet || top > zTop) zTop = top; + + isSet = true; + } + + foreach (var item in itemList) + { + var itemData = item.ItemData; + + var calcTop = item.Z + itemData.CalcHeight; + + if (isSet && calcTop < zCenter) continue; + + if ((itemData.Flags & TileFlag.Surface) == 0 && + (!m.CanSwim || (itemData.Flags & TileFlag.Wet) == 0)) continue; + + if (loc.Z < calcTop) continue; + + if (m.CantWalk && (itemData.Flags & TileFlag.Wet) == 0) continue; + + zLow = item.Z; + zCenter = calcTop; + + var top = item.Z + itemData.Height; + + if (!isSet || top > zTop) zTop = top; + + isSet = true; + } + + if (!isSet) + zLow = zTop = loc.Z; + else if (loc.Z > zTop) + zTop = loc.Z; + } + + public void Offset(Direction d, ref int x, ref int y) + { + switch (d & Direction.Mask) + { + case Direction.North: + --y; + break; + case Direction.South: + ++y; + break; + case Direction.West: + --x; + break; + case Direction.East: + ++x; + break; + case Direction.Right: + ++x; + --y; + break; + case Direction.Left: + --x; + ++y; + break; + case Direction.Down: + ++x; + ++y; + break; + case Direction.Up: + --x; + --y; + break; + } + } + + private static class MovementPool + { + private static readonly object _MovePoolLock = new object(); + private static readonly Queue> _MoveCachePool = new Queue>(0x400); + + public static void AcquireMoveCache(ref List cache, IEnumerable items) + { + if (cache == null) + lock (_MovePoolLock) + { + cache = _MoveCachePool.Count > 0 ? _MoveCachePool.Dequeue() : new List(0x10); + } + else + cache.Clear(); + + cache.AddRange(items); + } + + public static void ClearMoveCache(ref List cache, bool free) + { + cache?.Clear(); + + if (!free) return; + + lock (_MovePoolLock) + { + if (_MoveCachePool.Count < 0x400) _MoveCachePool.Enqueue(cache); + } + + cache = null; + } + } + } +} diff --git a/Projects/UOContent/Engines/Pathing/MoveResult.cs b/Projects/UOContent/Engines/Pathing/MoveResult.cs index 954c1825d..643f4f19b 100644 --- a/Projects/UOContent/Engines/Pathing/MoveResult.cs +++ b/Projects/UOContent/Engines/Pathing/MoveResult.cs @@ -1,12 +1,12 @@ -namespace Server -{ - public delegate MoveResult MoveMethod(Direction d); - - public enum MoveResult - { - BadState, - Blocked, - Success, - SuccessAutoTurn - } -} \ No newline at end of file +namespace Server +{ + public delegate MoveResult MoveMethod(Direction d); + + public enum MoveResult + { + BadState, + Blocked, + Success, + SuccessAutoTurn + } +} diff --git a/Projects/UOContent/Engines/Pathing/Movement.cs b/Projects/UOContent/Engines/Pathing/Movement.cs index e4d48e7a6..eaad778af 100644 --- a/Projects/UOContent/Engines/Pathing/Movement.cs +++ b/Projects/UOContent/Engines/Pathing/Movement.cs @@ -1,551 +1,598 @@ -using System; -using System.Collections.Generic; -using Server.Items; -using Server.Mobiles; - -namespace Server.Movement -{ - public class MovementImpl : IMovementImpl - { - private const int PersonHeight = 16; - private const int StepHeight = 2; - - private const TileFlag ImpassableSurface = TileFlag.Impassable | TileFlag.Surface; - - private static Point3D m_Goal; - - public static bool AlwaysIgnoreDoors { get; set; } - public static bool IgnoreMovableImpassables { get; set; } - public static bool IgnoreSpellFields { get; set; } - - public static Point3D Goal - { - get => m_Goal; - set => m_Goal = value; - } - - public static void Configure() - { - Movement.Impl = new MovementImpl(); - } - - private MovementImpl() - { - } - - private bool IsOk(bool ignoreDoors, bool ignoreSpellFields, int ourZ, int ourTop, StaticTile[] tiles, List items) - { - for (var i = 0; i < tiles.Length; ++i) - { - var check = tiles[i]; - var itemData = TileData.ItemTable[check.ID & TileData.MaxItemValue]; - - if ((itemData.Flags & ImpassableSurface) != 0) // Impassable || Surface - { - var checkZ = check.Z; - var checkTop = checkZ + itemData.CalcHeight; - - if (checkTop > ourZ && ourTop > checkZ) return false; - } - } - - for (var i = 0; i < items.Count; ++i) - { - var item = items[i]; - var itemID = item.ItemID & TileData.MaxItemValue; - var itemData = TileData.ItemTable[itemID]; - var flags = itemData.Flags; - - if ((flags & ImpassableSurface) != 0) // Impassable || Surface - { - if (ignoreDoors && ((flags & TileFlag.Door) != 0 || itemID == 0x692 || itemID == 0x846 || itemID == 0x873 || - itemID >= 0x6F5 && itemID <= 0x6F6)) - continue; - - if (ignoreSpellFields && (itemID == 0x82 || itemID == 0x3946 || itemID == 0x3956)) continue; - - var checkZ = item.Z; - var checkTop = checkZ + itemData.CalcHeight; - - if (checkTop > ourZ && ourTop > checkZ) return false; - } - } - - return true; - } - - private List[] m_Pools = { new List(), new List(), new List(), new List() }; - - private List[] m_MobPools = { new List(), new List(), new List() }; - - private List m_Sectors = new List(); - - private bool Check(Map map, Mobile m, List items, List mobiles, int x, int y, int startTop, int startZ, - bool canSwim, bool cantWalk, out int newZ) - { - newZ = 0; - - var tiles = map.Tiles.GetStaticTiles(x, y, true); - var landTile = map.Tiles.GetLandTile(x, y); - var flags = TileData.LandTable[landTile.ID & TileData.MaxLandValue].Flags; - var impassable = (flags & TileFlag.Impassable) != 0; - - // Impassable + swim on water is ok, otherwise block if cannot walk or impassable - var landBlocks = (cantWalk || impassable) && !(impassable && canSwim && (flags & TileFlag.Wet) != 0); - - var considerLand = !landTile.Ignored; - - int landZ = 0, landCenter = 0, landTop = 0; - - map.GetAverageZ(x, y, ref landZ, ref landCenter, ref landTop); - - var moveIsOk = false; - - var stepTop = startTop + StepHeight; - var checkTop = startZ + PersonHeight; - - var ignoreDoors = AlwaysIgnoreDoors || !m.Alive || m.Body.BodyID == 0x3DB || m.IsDeadBondedPet; - var ignoreSpellFields = m is PlayerMobile && map != Map.Felucca; - - for (var i = 0; i < tiles.Length; ++i) - { - var tile = tiles[i]; - var itemData = TileData.ItemTable[tile.ID & TileData.MaxItemValue]; - flags = itemData.Flags; - - var notWater = (flags & TileFlag.Wet) == 0; - - // Surface && !Impassable - if ((flags & ImpassableSurface) != TileFlag.Surface && (!canSwim || notWater) || cantWalk && notWater) continue; - - var itemZ = tile.Z; - var itemTop = itemZ; - var ourZ = itemZ + itemData.CalcHeight; - // int ourTop = ourZ + PersonHeight; - var testTop = checkTop; - - if (moveIsOk) - { - var cmp = Math.Abs(ourZ - m.Z) - Math.Abs(newZ - m.Z); - - if (cmp > 0 || cmp == 0 && ourZ > newZ) continue; - } - - if (ourZ + PersonHeight > testTop) testTop = ourZ + PersonHeight; - - if (!itemData.Bridge) itemTop += itemData.Height; - - if (stepTop >= itemTop) - { - var landCheck = itemZ; - - if (itemData.Height >= StepHeight) - landCheck += StepHeight; - else - landCheck += itemData.Height; - - if (considerLand && landCheck < landCenter && landCenter > ourZ && testTop > landZ) continue; - - if (IsOk(ignoreDoors, ignoreSpellFields, ourZ, testTop, tiles, items)) - { - newZ = ourZ; - moveIsOk = true; - } - } - } - - for (var i = 0; i < items.Count; ++i) - { - var item = items[i]; - var itemData = item.ItemData; - flags = itemData.Flags; - - var notWater = (flags & TileFlag.Wet) == 0; - - // Surface && !Impassable && !Movable - if (item.Movable || - (flags & ImpassableSurface) != TileFlag.Surface && (!m.CanSwim || notWater) || - cantWalk && notWater) continue; - - var itemZ = item.Z; - var itemTop = itemZ; - var ourZ = itemZ + itemData.CalcHeight; - // int ourTop = ourZ + PersonHeight; - var testTop = checkTop; - - if (moveIsOk) - { - var cmp = Math.Abs(ourZ - m.Z) - Math.Abs(newZ - m.Z); - - if (cmp > 0 || cmp == 0 && ourZ > newZ) continue; - } - - if (ourZ + PersonHeight > testTop) testTop = ourZ + PersonHeight; - - if (!itemData.Bridge) itemTop += itemData.Height; - - if (stepTop >= itemTop) - { - var landCheck = itemZ; - - if (itemData.Height >= StepHeight) - landCheck += StepHeight; - else - landCheck += itemData.Height; - - if (considerLand && landCheck < landCenter && landCenter > ourZ && testTop > landZ) continue; - - if (IsOk(ignoreDoors, ignoreSpellFields, ourZ, testTop, tiles, items)) - { - newZ = ourZ; - moveIsOk = true; - } - } - } - - if (considerLand && !landBlocks && stepTop >= landZ) - { - var ourZ = landCenter; - // int ourTop = ourZ + PersonHeight; - var testTop = checkTop; - - if (ourZ + PersonHeight > testTop) testTop = ourZ + PersonHeight; - - var shouldCheck = true; - - if (moveIsOk) - { - var cmp = Math.Abs(ourZ - m.Z) - Math.Abs(newZ - m.Z); - - if (cmp > 0 || cmp == 0 && ourZ > newZ) shouldCheck = false; - } - - if (shouldCheck && IsOk(ignoreDoors, ignoreSpellFields, ourZ, testTop, tiles, items)) - { - newZ = ourZ; - moveIsOk = true; - } - } - - if (moveIsOk) - for (var i = 0; moveIsOk && i < mobiles.Count; ++i) - { - var mob = mobiles[i]; - - if (mob != m && mob.Z + 15 > newZ && newZ + 15 > mob.Z && !CanMoveOver(m, mob)) moveIsOk = false; - } - - return moveIsOk; - } - - private bool CanMoveOver(Mobile m, Mobile t) => - !t.Alive || !m.Alive || t.IsDeadBondedPet || m.IsDeadBondedPet || t.Hidden && t.AccessLevel > AccessLevel.Player; - - public bool CheckMovement(Mobile m, Map map, Point3D loc, Direction d, out int newZ) - { - if (map == null || map == Map.Internal) - { - newZ = 0; - return false; - } - - var xStart = loc.X; - var yStart = loc.Y; - int xForward = xStart, yForward = yStart; - int xRight = xStart, yRight = yStart; - int xLeft = xStart, yLeft = yStart; - - var checkDiagonals = ((int)d & 0x1) == 0x1; - - Offset(d, ref xForward, ref yForward); - Offset((Direction)(((int)d - 1) & 0x7), ref xLeft, ref yLeft); - Offset((Direction)(((int)d + 1) & 0x7), ref xRight, ref yRight); - - if (xForward < 0 || yForward < 0 || xForward >= map.Width || yForward >= map.Height) - { - newZ = 0; - return false; - } - - var itemsStart = m_Pools[0]; - var itemsForward = m_Pools[1]; - var itemsLeft = m_Pools[2]; - var itemsRight = m_Pools[3]; - - var ignoreMovableImpassables = IgnoreMovableImpassables; - var reqFlags = ImpassableSurface; - - if (m.CanSwim) reqFlags |= TileFlag.Wet; - - var mobsForward = m_MobPools[0]; - var mobsLeft = m_MobPools[1]; - var mobsRight = m_MobPools[2]; - - var checkMobs = (m as BaseCreature)?.Controlled == false && (xForward != m_Goal.X || yForward != m_Goal.Y); - - if (checkDiagonals) - { - var sectorStart = map.GetSector(xStart, yStart); - var sectorForward = map.GetSector(xForward, yForward); - var sectorLeft = map.GetSector(xLeft, yLeft); - var sectorRight = map.GetSector(xRight, yRight); - - var sectors = m_Sectors; - - sectors.Add(sectorStart); - - if (!sectors.Contains(sectorForward)) sectors.Add(sectorForward); - if (!sectors.Contains(sectorLeft)) sectors.Add(sectorLeft); - if (!sectors.Contains(sectorRight)) sectors.Add(sectorRight); - - for (var i = 0; i < sectors.Count; ++i) - { - var sector = sectors[i]; - - for (var j = 0; j < sector.Items.Count; ++j) - { - var item = sector.Items[j]; - - if (ignoreMovableImpassables && item.Movable && (item.ItemData.Flags & ImpassableSurface) != 0) continue; - - if ((item.ItemData.Flags & reqFlags) == 0) continue; - - if (item is BaseMulti || item.ItemID > TileData.MaxItemValue) continue; - - if (sector == sectorStart && item.AtWorldPoint(xStart, yStart)) - itemsStart.Add(item); - else if (sector == sectorForward && item.AtWorldPoint(xForward, yForward)) - itemsForward.Add(item); - else if (sector == sectorLeft && item.AtWorldPoint(xLeft, yLeft)) - itemsLeft.Add(item); - else if (sector == sectorRight && item.AtWorldPoint(xRight, yRight)) - itemsRight.Add(item); - } - - if (checkMobs) - for (var j = 0; j < sector.Mobiles.Count; ++j) - { - var mob = sector.Mobiles[j]; - - if (sector == sectorForward && mob.X == xForward && mob.Y == yForward) - mobsForward.Add(mob); - else if (sector == sectorLeft && mob.X == xLeft && mob.Y == yLeft) - mobsLeft.Add(mob); - else if (sector == sectorRight && mob.X == xRight && mob.Y == yRight) mobsRight.Add(mob); - } - } - - if (m_Sectors.Count > 0) m_Sectors.Clear(); - } - else - { - var sectorStart = map.GetSector(xStart, yStart); - var sectorForward = map.GetSector(xForward, yForward); - - if (sectorStart == sectorForward) - { - for (var i = 0; i < sectorStart.Items.Count; ++i) - { - var item = sectorStart.Items[i]; - - if (ignoreMovableImpassables && item.Movable && (item.ItemData.Flags & ImpassableSurface) != 0) continue; - - if ((item.ItemData.Flags & reqFlags) == 0) continue; - - if (item is BaseMulti || item.ItemID > TileData.MaxItemValue) continue; - - if (item.AtWorldPoint(xStart, yStart)) - itemsStart.Add(item); - else if (item.AtWorldPoint(xForward, yForward)) - itemsForward.Add(item); - } - } - else - { - for (var i = 0; i < sectorForward.Items.Count; ++i) - { - var item = sectorForward.Items[i]; - - if (ignoreMovableImpassables && item.Movable && (item.ItemData.Flags & ImpassableSurface) != 0) continue; - - if ((item.ItemData.Flags & reqFlags) == 0) continue; - - if (item.AtWorldPoint(xForward, yForward) && !(item is BaseMulti) && item.ItemID <= TileData.MaxItemValue) - itemsForward.Add(item); - } - - for (var i = 0; i < sectorStart.Items.Count; ++i) - { - var item = sectorStart.Items[i]; - - if (ignoreMovableImpassables && item.Movable && (item.ItemData.Flags & ImpassableSurface) != 0) continue; - - if ((item.ItemData.Flags & reqFlags) == 0) continue; - - if (item.AtWorldPoint(xStart, yStart) && !(item is BaseMulti) && item.ItemID <= TileData.MaxItemValue) - itemsStart.Add(item); - } - } - - if (checkMobs) - for (var i = 0; i < sectorForward.Mobiles.Count; ++i) - { - var mob = sectorForward.Mobiles[i]; - - if (mob.X == xForward && mob.Y == yForward) mobsForward.Add(mob); - } - } - - GetStartZ(m, map, loc, itemsStart, out var startZ, out var startTop); - - var moveIsOk = Check(map, m, itemsForward, mobsForward, xForward, yForward, startTop, startZ, m.CanSwim, m.CantWalk, - out newZ); - - if (moveIsOk && checkDiagonals) - { - if (m.Player && m.AccessLevel < AccessLevel.GameMaster) - { - if (!Check(map, m, itemsLeft, mobsLeft, xLeft, yLeft, startTop, startZ, m.CanSwim, m.CantWalk, out _) || - !Check(map, m, itemsRight, mobsRight, xRight, yRight, startTop, startZ, m.CanSwim, m.CantWalk, out _)) - moveIsOk = false; - } - else - { - if (!Check(map, m, itemsLeft, mobsLeft, xLeft, yLeft, startTop, startZ, m.CanSwim, m.CantWalk, out _) && - !Check(map, m, itemsRight, mobsRight, xRight, yRight, startTop, startZ, m.CanSwim, m.CantWalk, out _)) - moveIsOk = false; - } - } - - for (int i = 0, c = checkDiagonals ? 4 : 2; i < c; ++i) - m_Pools[i].Clear(); - - for (int i = 0, c = checkDiagonals ? 3 : 1; i < c; ++i) - m_MobPools[i].Clear(); - - if (!moveIsOk) newZ = startZ; - - return moveIsOk; - } - - public bool CheckMovement(Mobile m, Direction d, out int newZ) => CheckMovement(m, m.Map, m.Location, d, out newZ); - - private void GetStartZ(Mobile m, Map map, Point3D loc, List itemList, out int zLow, out int zTop) - { - int xCheck = loc.X, yCheck = loc.Y; - - var landTile = map.Tiles.GetLandTile(xCheck, yCheck); - int landZ = 0, landCenter = 0, landTop = 0; - var flags = TileData.LandTable[landTile.ID & TileData.MaxLandValue].Flags; - var impassable = (flags & TileFlag.Impassable) != 0; - - // Impassable + swim on water is ok, otherwise block if cannot walk or impassable - var landBlocks = (m.CantWalk || impassable) && !(impassable && m.CanSwim && (flags & TileFlag.Wet) != 0); - - map.GetAverageZ(xCheck, yCheck, ref landZ, ref landCenter, ref landTop); - - var considerLand = !landTile.Ignored; - - var zCenter = zLow = zTop = 0; - var isSet = false; - - if (considerLand && !landBlocks && loc.Z >= landCenter) - { - zLow = landZ; - zCenter = landCenter; - - zTop = landTop; - - isSet = true; - } - - var staticTiles = map.Tiles.GetStaticTiles(xCheck, yCheck, true); - - for (var i = 0; i < staticTiles.Length; ++i) - { - var tile = staticTiles[i]; - var id = TileData.ItemTable[tile.ID & TileData.MaxItemValue]; - - var calcTop = tile.Z + id.CalcHeight; - - if ((!isSet || calcTop >= zCenter) && - ((id.Flags & TileFlag.Surface) != 0 || m.CanSwim && (id.Flags & TileFlag.Wet) != 0) && loc.Z >= calcTop) - { - if (m.CantWalk && (id.Flags & TileFlag.Wet) == 0) continue; - - zLow = tile.Z; - zCenter = calcTop; - - var top = tile.Z + id.Height; - - if (!isSet || top > zTop) zTop = top; - - isSet = true; - } - } - - for (var i = 0; i < itemList.Count; ++i) - { - var item = itemList[i]; - - var id = item.ItemData; - - var calcTop = item.Z + id.CalcHeight; - - if ((!isSet || calcTop >= zCenter) && - ((id.Flags & TileFlag.Surface) != 0 || m.CanSwim && (id.Flags & TileFlag.Wet) != 0) && loc.Z >= calcTop) - { - if (m.CantWalk && (id.Flags & TileFlag.Wet) == 0) continue; - - zLow = item.Z; - zCenter = calcTop; - - var top = item.Z + id.Height; - - if (!isSet || top > zTop) zTop = top; - - isSet = true; - } - } - - if (!isSet) - zLow = zTop = loc.Z; - else if (loc.Z > zTop) zTop = loc.Z; - } - - public void Offset(Direction d, ref int x, ref int y) - { - switch (d & Direction.Mask) - { - case Direction.North: - --y; - break; - case Direction.South: - ++y; - break; - case Direction.West: - --x; - break; - case Direction.East: - ++x; - break; - case Direction.Right: - ++x; - --y; - break; - case Direction.Left: - --x; - ++y; - break; - case Direction.Down: - ++x; - ++y; - break; - case Direction.Up: - --x; - --y; - break; - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Items; +using Server.Mobiles; + +namespace Server.Movement +{ + public class MovementImpl : IMovementImpl + { + private const int PersonHeight = 16; + private const int StepHeight = 2; + + private const TileFlag ImpassableSurface = TileFlag.Impassable | TileFlag.Surface; + + private static Point3D m_Goal; + + private readonly List[] m_MobPools = { new List(), new List(), new List() }; + + private readonly List[] m_Pools = { new List(), new List(), new List(), new List() }; + + private readonly List m_Sectors = new List(); + + private MovementImpl() + { + } + + public static bool AlwaysIgnoreDoors { get; set; } + public static bool IgnoreMovableImpassables { get; set; } + public static bool IgnoreSpellFields { get; set; } + + public static Point3D Goal + { + get => m_Goal; + set => m_Goal = value; + } + + public bool CheckMovement(Mobile m, Map map, Point3D loc, Direction d, out int newZ) + { + if (map == null || map == Map.Internal) + { + newZ = 0; + return false; + } + + var xStart = loc.X; + var yStart = loc.Y; + int xForward = xStart, yForward = yStart; + int xRight = xStart, yRight = yStart; + int xLeft = xStart, yLeft = yStart; + + var checkDiagonals = ((int)d & 0x1) == 0x1; + + Offset(d, ref xForward, ref yForward); + Offset((Direction)(((int)d - 1) & 0x7), ref xLeft, ref yLeft); + Offset((Direction)(((int)d + 1) & 0x7), ref xRight, ref yRight); + + if (xForward < 0 || yForward < 0 || xForward >= map.Width || yForward >= map.Height) + { + newZ = 0; + return false; + } + + var itemsStart = m_Pools[0]; + var itemsForward = m_Pools[1]; + var itemsLeft = m_Pools[2]; + var itemsRight = m_Pools[3]; + + var ignoreMovableImpassables = IgnoreMovableImpassables; + var reqFlags = ImpassableSurface; + + if (m.CanSwim) reqFlags |= TileFlag.Wet; + + var mobsForward = m_MobPools[0]; + var mobsLeft = m_MobPools[1]; + var mobsRight = m_MobPools[2]; + + var checkMobs = (m as BaseCreature)?.Controlled == false && (xForward != m_Goal.X || yForward != m_Goal.Y); + + if (checkDiagonals) + { + var sectorStart = map.GetSector(xStart, yStart); + var sectorForward = map.GetSector(xForward, yForward); + var sectorLeft = map.GetSector(xLeft, yLeft); + var sectorRight = map.GetSector(xRight, yRight); + + var sectors = m_Sectors; + + sectors.Add(sectorStart); + + if (!sectors.Contains(sectorForward)) sectors.Add(sectorForward); + if (!sectors.Contains(sectorLeft)) sectors.Add(sectorLeft); + if (!sectors.Contains(sectorRight)) sectors.Add(sectorRight); + + for (var i = 0; i < sectors.Count; ++i) + { + var sector = sectors[i]; + + for (var j = 0; j < sector.Items.Count; ++j) + { + var item = sector.Items[j]; + + if (ignoreMovableImpassables && item.Movable && + (item.ItemData.Flags & ImpassableSurface) != 0) continue; + + if ((item.ItemData.Flags & reqFlags) == 0) continue; + + if (item is BaseMulti || item.ItemID > TileData.MaxItemValue) continue; + + if (sector == sectorStart && item.AtWorldPoint(xStart, yStart)) + itemsStart.Add(item); + else if (sector == sectorForward && item.AtWorldPoint(xForward, yForward)) + itemsForward.Add(item); + else if (sector == sectorLeft && item.AtWorldPoint(xLeft, yLeft)) + itemsLeft.Add(item); + else if (sector == sectorRight && item.AtWorldPoint(xRight, yRight)) + itemsRight.Add(item); + } + + if (checkMobs) + for (var j = 0; j < sector.Mobiles.Count; ++j) + { + var mob = sector.Mobiles[j]; + + if (sector == sectorForward && mob.X == xForward && mob.Y == yForward) + mobsForward.Add(mob); + else if (sector == sectorLeft && mob.X == xLeft && mob.Y == yLeft) + mobsLeft.Add(mob); + else if (sector == sectorRight && mob.X == xRight && mob.Y == yRight) mobsRight.Add(mob); + } + } + + if (m_Sectors.Count > 0) m_Sectors.Clear(); + } + else + { + var sectorStart = map.GetSector(xStart, yStart); + var sectorForward = map.GetSector(xForward, yForward); + + if (sectorStart == sectorForward) + { + for (var i = 0; i < sectorStart.Items.Count; ++i) + { + var item = sectorStart.Items[i]; + + if (ignoreMovableImpassables && item.Movable && + (item.ItemData.Flags & ImpassableSurface) != 0) continue; + + if ((item.ItemData.Flags & reqFlags) == 0) continue; + + if (item is BaseMulti || item.ItemID > TileData.MaxItemValue) continue; + + if (item.AtWorldPoint(xStart, yStart)) + itemsStart.Add(item); + else if (item.AtWorldPoint(xForward, yForward)) + itemsForward.Add(item); + } + } + else + { + for (var i = 0; i < sectorForward.Items.Count; ++i) + { + var item = sectorForward.Items[i]; + + if (ignoreMovableImpassables && item.Movable && + (item.ItemData.Flags & ImpassableSurface) != 0) continue; + + if ((item.ItemData.Flags & reqFlags) == 0) continue; + + if (item.AtWorldPoint(xForward, yForward) && !(item is BaseMulti) && + item.ItemID <= TileData.MaxItemValue) + itemsForward.Add(item); + } + + for (var i = 0; i < sectorStart.Items.Count; ++i) + { + var item = sectorStart.Items[i]; + + if (ignoreMovableImpassables && item.Movable && + (item.ItemData.Flags & ImpassableSurface) != 0) continue; + + if ((item.ItemData.Flags & reqFlags) == 0) continue; + + if (item.AtWorldPoint(xStart, yStart) && !(item is BaseMulti) && + item.ItemID <= TileData.MaxItemValue) + itemsStart.Add(item); + } + } + + if (checkMobs) + for (var i = 0; i < sectorForward.Mobiles.Count; ++i) + { + var mob = sectorForward.Mobiles[i]; + + if (mob.X == xForward && mob.Y == yForward) mobsForward.Add(mob); + } + } + + GetStartZ(m, map, loc, itemsStart, out var startZ, out var startTop); + + var moveIsOk = Check( + map, + m, + itemsForward, + mobsForward, + xForward, + yForward, + startTop, + startZ, + m.CanSwim, + m.CantWalk, + out newZ + ); + + if (moveIsOk && checkDiagonals) + { + if (m.Player && m.AccessLevel < AccessLevel.GameMaster) + { + if (!Check(map, m, itemsLeft, mobsLeft, xLeft, yLeft, startTop, startZ, m.CanSwim, m.CantWalk, out _) || + !Check( + map, + m, + itemsRight, + mobsRight, + xRight, + yRight, + startTop, + startZ, + m.CanSwim, + m.CantWalk, + out _ + )) + moveIsOk = false; + } + else + { + if (!Check(map, m, itemsLeft, mobsLeft, xLeft, yLeft, startTop, startZ, m.CanSwim, m.CantWalk, out _) && + !Check( + map, + m, + itemsRight, + mobsRight, + xRight, + yRight, + startTop, + startZ, + m.CanSwim, + m.CantWalk, + out _ + )) + moveIsOk = false; + } + } + + for (int i = 0, c = checkDiagonals ? 4 : 2; i < c; ++i) + m_Pools[i].Clear(); + + for (int i = 0, c = checkDiagonals ? 3 : 1; i < c; ++i) + m_MobPools[i].Clear(); + + if (!moveIsOk) newZ = startZ; + + return moveIsOk; + } + + public bool CheckMovement(Mobile m, Direction d, out int newZ) => CheckMovement(m, m.Map, m.Location, d, out newZ); + + public static void Configure() + { + Movement.Impl = new MovementImpl(); + } + + private bool IsOk( + bool ignoreDoors, bool ignoreSpellFields, int ourZ, int ourTop, StaticTile[] tiles, List items + ) + { + for (var i = 0; i < tiles.Length; ++i) + { + var check = tiles[i]; + var itemData = TileData.ItemTable[check.ID & TileData.MaxItemValue]; + + if ((itemData.Flags & ImpassableSurface) != 0) // Impassable || Surface + { + var checkZ = check.Z; + var checkTop = checkZ + itemData.CalcHeight; + + if (checkTop > ourZ && ourTop > checkZ) return false; + } + } + + for (var i = 0; i < items.Count; ++i) + { + var item = items[i]; + var itemID = item.ItemID & TileData.MaxItemValue; + var itemData = TileData.ItemTable[itemID]; + var flags = itemData.Flags; + + if ((flags & ImpassableSurface) != 0) // Impassable || Surface + { + if (ignoreDoors && ((flags & TileFlag.Door) != 0 || itemID == 0x692 || itemID == 0x846 || + itemID == 0x873 || + itemID >= 0x6F5 && itemID <= 0x6F6)) + continue; + + if (ignoreSpellFields && (itemID == 0x82 || itemID == 0x3946 || itemID == 0x3956)) continue; + + var checkZ = item.Z; + var checkTop = checkZ + itemData.CalcHeight; + + if (checkTop > ourZ && ourTop > checkZ) return false; + } + } + + return true; + } + + private bool Check( + Map map, Mobile m, List items, List mobiles, int x, int y, int startTop, int startZ, + bool canSwim, bool cantWalk, out int newZ + ) + { + newZ = 0; + + var tiles = map.Tiles.GetStaticTiles(x, y, true); + var landTile = map.Tiles.GetLandTile(x, y); + var flags = TileData.LandTable[landTile.ID & TileData.MaxLandValue].Flags; + var impassable = (flags & TileFlag.Impassable) != 0; + + // Impassable + swim on water is ok, otherwise block if cannot walk or impassable + var landBlocks = (cantWalk || impassable) && !(impassable && canSwim && (flags & TileFlag.Wet) != 0); + + var considerLand = !landTile.Ignored; + + int landZ = 0, landCenter = 0, landTop = 0; + + map.GetAverageZ(x, y, ref landZ, ref landCenter, ref landTop); + + var moveIsOk = false; + + var stepTop = startTop + StepHeight; + var checkTop = startZ + PersonHeight; + + var ignoreDoors = AlwaysIgnoreDoors || !m.Alive || m.Body.BodyID == 0x3DB || m.IsDeadBondedPet; + var ignoreSpellFields = m is PlayerMobile && map != Map.Felucca; + + for (var i = 0; i < tiles.Length; ++i) + { + var tile = tiles[i]; + var itemData = TileData.ItemTable[tile.ID & TileData.MaxItemValue]; + flags = itemData.Flags; + + var notWater = (flags & TileFlag.Wet) == 0; + + // Surface && !Impassable + if ((flags & ImpassableSurface) != TileFlag.Surface && (!canSwim || notWater) || + cantWalk && notWater) continue; + + var itemZ = tile.Z; + var itemTop = itemZ; + var ourZ = itemZ + itemData.CalcHeight; + // int ourTop = ourZ + PersonHeight; + var testTop = checkTop; + + if (moveIsOk) + { + var cmp = Math.Abs(ourZ - m.Z) - Math.Abs(newZ - m.Z); + + if (cmp > 0 || cmp == 0 && ourZ > newZ) continue; + } + + if (ourZ + PersonHeight > testTop) testTop = ourZ + PersonHeight; + + if (!itemData.Bridge) itemTop += itemData.Height; + + if (stepTop >= itemTop) + { + var landCheck = itemZ; + + if (itemData.Height >= StepHeight) + landCheck += StepHeight; + else + landCheck += itemData.Height; + + if (considerLand && landCheck < landCenter && landCenter > ourZ && testTop > landZ) continue; + + if (IsOk(ignoreDoors, ignoreSpellFields, ourZ, testTop, tiles, items)) + { + newZ = ourZ; + moveIsOk = true; + } + } + } + + for (var i = 0; i < items.Count; ++i) + { + var item = items[i]; + var itemData = item.ItemData; + flags = itemData.Flags; + + var notWater = (flags & TileFlag.Wet) == 0; + + // Surface && !Impassable && !Movable + if (item.Movable || + (flags & ImpassableSurface) != TileFlag.Surface && (!m.CanSwim || notWater) || + cantWalk && notWater) continue; + + var itemZ = item.Z; + var itemTop = itemZ; + var ourZ = itemZ + itemData.CalcHeight; + // int ourTop = ourZ + PersonHeight; + var testTop = checkTop; + + if (moveIsOk) + { + var cmp = Math.Abs(ourZ - m.Z) - Math.Abs(newZ - m.Z); + + if (cmp > 0 || cmp == 0 && ourZ > newZ) continue; + } + + if (ourZ + PersonHeight > testTop) testTop = ourZ + PersonHeight; + + if (!itemData.Bridge) itemTop += itemData.Height; + + if (stepTop >= itemTop) + { + var landCheck = itemZ; + + if (itemData.Height >= StepHeight) + landCheck += StepHeight; + else + landCheck += itemData.Height; + + if (considerLand && landCheck < landCenter && landCenter > ourZ && testTop > landZ) continue; + + if (IsOk(ignoreDoors, ignoreSpellFields, ourZ, testTop, tiles, items)) + { + newZ = ourZ; + moveIsOk = true; + } + } + } + + if (considerLand && !landBlocks && stepTop >= landZ) + { + var ourZ = landCenter; + // int ourTop = ourZ + PersonHeight; + var testTop = checkTop; + + if (ourZ + PersonHeight > testTop) testTop = ourZ + PersonHeight; + + var shouldCheck = true; + + if (moveIsOk) + { + var cmp = Math.Abs(ourZ - m.Z) - Math.Abs(newZ - m.Z); + + if (cmp > 0 || cmp == 0 && ourZ > newZ) shouldCheck = false; + } + + if (shouldCheck && IsOk(ignoreDoors, ignoreSpellFields, ourZ, testTop, tiles, items)) + { + newZ = ourZ; + moveIsOk = true; + } + } + + if (moveIsOk) + for (var i = 0; moveIsOk && i < mobiles.Count; ++i) + { + var mob = mobiles[i]; + + if (mob != m && mob.Z + 15 > newZ && newZ + 15 > mob.Z && !CanMoveOver(m, mob)) moveIsOk = false; + } + + return moveIsOk; + } + + private bool CanMoveOver(Mobile m, Mobile t) => + !t.Alive || !m.Alive || t.IsDeadBondedPet || m.IsDeadBondedPet || t.Hidden && t.AccessLevel > AccessLevel.Player; + + private void GetStartZ(Mobile m, Map map, Point3D loc, List itemList, out int zLow, out int zTop) + { + int xCheck = loc.X, yCheck = loc.Y; + + var landTile = map.Tiles.GetLandTile(xCheck, yCheck); + int landZ = 0, landCenter = 0, landTop = 0; + var flags = TileData.LandTable[landTile.ID & TileData.MaxLandValue].Flags; + var impassable = (flags & TileFlag.Impassable) != 0; + + // Impassable + swim on water is ok, otherwise block if cannot walk or impassable + var landBlocks = (m.CantWalk || impassable) && !(impassable && m.CanSwim && (flags & TileFlag.Wet) != 0); + + map.GetAverageZ(xCheck, yCheck, ref landZ, ref landCenter, ref landTop); + + var considerLand = !landTile.Ignored; + + var zCenter = zLow = zTop = 0; + var isSet = false; + + if (considerLand && !landBlocks && loc.Z >= landCenter) + { + zLow = landZ; + zCenter = landCenter; + + zTop = landTop; + + isSet = true; + } + + var staticTiles = map.Tiles.GetStaticTiles(xCheck, yCheck, true); + + for (var i = 0; i < staticTiles.Length; ++i) + { + var tile = staticTiles[i]; + var id = TileData.ItemTable[tile.ID & TileData.MaxItemValue]; + + var calcTop = tile.Z + id.CalcHeight; + + if ((!isSet || calcTop >= zCenter) && + ((id.Flags & TileFlag.Surface) != 0 || m.CanSwim && (id.Flags & TileFlag.Wet) != 0) && loc.Z >= calcTop) + { + if (m.CantWalk && (id.Flags & TileFlag.Wet) == 0) continue; + + zLow = tile.Z; + zCenter = calcTop; + + var top = tile.Z + id.Height; + + if (!isSet || top > zTop) zTop = top; + + isSet = true; + } + } + + for (var i = 0; i < itemList.Count; ++i) + { + var item = itemList[i]; + + var id = item.ItemData; + + var calcTop = item.Z + id.CalcHeight; + + if ((!isSet || calcTop >= zCenter) && + ((id.Flags & TileFlag.Surface) != 0 || m.CanSwim && (id.Flags & TileFlag.Wet) != 0) && loc.Z >= calcTop) + { + if (m.CantWalk && (id.Flags & TileFlag.Wet) == 0) continue; + + zLow = item.Z; + zCenter = calcTop; + + var top = item.Z + id.Height; + + if (!isSet || top > zTop) zTop = top; + + isSet = true; + } + } + + if (!isSet) + zLow = zTop = loc.Z; + else if (loc.Z > zTop) zTop = loc.Z; + } + + public void Offset(Direction d, ref int x, ref int y) + { + switch (d & Direction.Mask) + { + case Direction.North: + --y; + break; + case Direction.South: + ++y; + break; + case Direction.West: + --x; + break; + case Direction.East: + ++x; + break; + case Direction.Right: + ++x; + --y; + break; + case Direction.Left: + --x; + ++y; + break; + case Direction.Down: + ++x; + ++y; + break; + case Direction.Up: + --x; + --y; + break; + } + } + } +} diff --git a/Projects/UOContent/Engines/Pathing/MovementPath.cs b/Projects/UOContent/Engines/Pathing/MovementPath.cs index ff54bbbd3..300601426 100644 --- a/Projects/UOContent/Engines/Pathing/MovementPath.cs +++ b/Projects/UOContent/Engines/Pathing/MovementPath.cs @@ -1,106 +1,106 @@ -using System; -using Server.Items; -using Server.PathAlgorithms; -using Server.PathAlgorithms.FastAStar; -using Server.PathAlgorithms.SlowAStar; -using Server.Spells; -using Server.Targeting; - -namespace Server -{ - public sealed class MovementPath - { - public MovementPath(Mobile m, Point3D goal) - { - Point3D start = m.Location; - Map map = m.Map; - - Map = map; - Start = start; - Goal = goal; - - if (map == null || map == Map.Internal) - return; - - if (Utility.InRange(start, goal, 1)) - return; - - try - { - PathAlgorithm alg = OverrideAlgorithm ?? FastAStarAlgorithm.Instance; - - if (alg?.CheckCondition(m, map, start, goal) == true) - Directions = alg.Find(m, map, start, goal); - } - catch (Exception e) - { - Console.WriteLine("Warning: {0}: Pathing error from {1} to {2}", e.GetType().Name, start, goal); - } - } - - public Map Map { get; } - - public Point3D Start { get; } - - public Point3D Goal { get; } - - public Direction[] Directions { get; } - - public bool Success => Directions?.Length > 0; - - public static PathAlgorithm OverrideAlgorithm { get; set; } - - public static void Initialize() - { - CommandSystem.Register("Path", AccessLevel.GameMaster, Path_OnCommand); - } - - public static void Path_OnCommand(CommandEventArgs e) - { - e.Mobile.BeginTarget(-1, true, TargetFlags.None, Path_OnTarget); - e.Mobile.SendMessage("Target a location and a path will be drawn there."); - } - - private static void Path(Mobile from, IPoint3D p, PathAlgorithm alg, string name, int zOffset) - { - OverrideAlgorithm = alg; - - long start = DateTime.UtcNow.Ticks; - MovementPath path = new MovementPath(from, new Point3D(p)); - long end = DateTime.UtcNow.Ticks; - double len = Math.Round((end - start) / 10000.0, 2); - - if (!path.Success) - { - from.SendMessage("{0} path failed: {1}ms", name, len); - } - else - { - from.SendMessage("{0} path success: {1}ms", name, len); - - int x = from.X; - int y = from.Y; - int z = from.Z; - - for (int i = 0; i < path.Directions.Length; ++i) - { - Movement.Movement.Offset(path.Directions[i], ref x, ref y); - - new RecallRune().MoveToWorld(new Point3D(x, y, z + zOffset), from.Map); - } - } - } - - public static void Path_OnTarget(Mobile from, object targeted) - { - if (!(targeted is IPoint3D p)) - return; - - SpellHelper.GetSurfaceTop(ref p); - - Path(from, p, FastAStarAlgorithm.Instance, "Fast", 0); - Path(from, p, SlowAStarAlgorithm.Instance, "Slow", 2); - OverrideAlgorithm = null; - } - } -} +using System; +using Server.Items; +using Server.PathAlgorithms; +using Server.PathAlgorithms.FastAStar; +using Server.PathAlgorithms.SlowAStar; +using Server.Spells; +using Server.Targeting; + +namespace Server +{ + public sealed class MovementPath + { + public MovementPath(Mobile m, Point3D goal) + { + var start = m.Location; + var map = m.Map; + + Map = map; + Start = start; + Goal = goal; + + if (map == null || map == Map.Internal) + return; + + if (Utility.InRange(start, goal, 1)) + return; + + try + { + var alg = OverrideAlgorithm ?? FastAStarAlgorithm.Instance; + + if (alg?.CheckCondition(m, map, start, goal) == true) + Directions = alg.Find(m, map, start, goal); + } + catch (Exception e) + { + Console.WriteLine("Warning: {0}: Pathing error from {1} to {2}", e.GetType().Name, start, goal); + } + } + + public Map Map { get; } + + public Point3D Start { get; } + + public Point3D Goal { get; } + + public Direction[] Directions { get; } + + public bool Success => Directions?.Length > 0; + + public static PathAlgorithm OverrideAlgorithm { get; set; } + + public static void Initialize() + { + CommandSystem.Register("Path", AccessLevel.GameMaster, Path_OnCommand); + } + + public static void Path_OnCommand(CommandEventArgs e) + { + e.Mobile.BeginTarget(-1, true, TargetFlags.None, Path_OnTarget); + e.Mobile.SendMessage("Target a location and a path will be drawn there."); + } + + private static void Path(Mobile from, IPoint3D p, PathAlgorithm alg, string name, int zOffset) + { + OverrideAlgorithm = alg; + + var start = DateTime.UtcNow.Ticks; + var path = new MovementPath(from, new Point3D(p)); + var end = DateTime.UtcNow.Ticks; + var len = Math.Round((end - start) / 10000.0, 2); + + if (!path.Success) + { + from.SendMessage("{0} path failed: {1}ms", name, len); + } + else + { + from.SendMessage("{0} path success: {1}ms", name, len); + + var x = from.X; + var y = from.Y; + var z = from.Z; + + for (var i = 0; i < path.Directions.Length; ++i) + { + Movement.Movement.Offset(path.Directions[i], ref x, ref y); + + new RecallRune().MoveToWorld(new Point3D(x, y, z + zOffset), from.Map); + } + } + } + + public static void Path_OnTarget(Mobile from, object targeted) + { + if (!(targeted is IPoint3D p)) + return; + + SpellHelper.GetSurfaceTop(ref p); + + Path(from, p, FastAStarAlgorithm.Instance, "Fast", 0); + Path(from, p, SlowAStarAlgorithm.Instance, "Slow", 2); + OverrideAlgorithm = null; + } + } +} diff --git a/Projects/UOContent/Engines/Pathing/PathAlgorithm.cs b/Projects/UOContent/Engines/Pathing/PathAlgorithm.cs index a2fdb8455..cd4c199db 100644 --- a/Projects/UOContent/Engines/Pathing/PathAlgorithm.cs +++ b/Projects/UOContent/Engines/Pathing/PathAlgorithm.cs @@ -1,32 +1,33 @@ -namespace Server.PathAlgorithms -{ - public abstract class PathAlgorithm - { - private static readonly Direction[] m_CalcDirections = { - Direction.Up, - Direction.North, - Direction.Right, - Direction.West, - Direction.North, - Direction.East, - Direction.Left, - Direction.South, - Direction.Down - }; - - public abstract bool CheckCondition(Mobile m, Map map, Point3D start, Point3D goal); - public abstract Direction[] Find(Mobile m, Map map, Point3D start, Point3D goal); - - public Direction GetDirection(int xSource, int ySource, int xDest, int yDest) - { - int x = xDest + 1 - xSource; - int y = yDest + 1 - ySource; - int v = y * 3 + x; - - if (v < 0 || v >= 9) - return Direction.North; - - return m_CalcDirections[v]; - } - } -} \ No newline at end of file +namespace Server.PathAlgorithms +{ + public abstract class PathAlgorithm + { + private static readonly Direction[] m_CalcDirections = + { + Direction.Up, + Direction.North, + Direction.Right, + Direction.West, + Direction.North, + Direction.East, + Direction.Left, + Direction.South, + Direction.Down + }; + + public abstract bool CheckCondition(Mobile m, Map map, Point3D start, Point3D goal); + public abstract Direction[] Find(Mobile m, Map map, Point3D start, Point3D goal); + + public Direction GetDirection(int xSource, int ySource, int xDest, int yDest) + { + var x = xDest + 1 - xSource; + var y = yDest + 1 - ySource; + var v = y * 3 + x; + + if (v < 0 || v >= 9) + return Direction.North; + + return m_CalcDirections[v]; + } + } +} diff --git a/Projects/UOContent/Engines/Pathing/PathFollower.cs b/Projects/UOContent/Engines/Pathing/PathFollower.cs index 84f8b572d..3414970d3 100644 --- a/Projects/UOContent/Engines/Pathing/PathFollower.cs +++ b/Projects/UOContent/Engines/Pathing/PathFollower.cs @@ -1,179 +1,180 @@ -using System; -using CalcMoves = Server.Movement.Movement; - -namespace Server -{ - public class PathFollower - { - private static bool Enabled; - private static readonly TimeSpan RepathDelay = TimeSpan.FromSeconds(2.0); - - private readonly Mobile m_From; - private int m_Index; - private DateTime m_LastPathTime; - private Point3D m_Next, m_LastGoalLoc; - private MovementPath m_Path; - - public static void Initialize() - { - Enabled = ServerConfiguration.GetOrUpdateSetting("pathfinding.enable", true); - } - - public PathFollower(Mobile from, IPoint3D goal) - { - m_From = from; - Goal = goal; - } - - public MoveMethod Mover { get; set; } - - public IPoint3D Goal { get; } - - public MoveResult Move(Direction d) - { - if (Mover == null) - return m_From.Move(d) ? MoveResult.Success : MoveResult.Blocked; - - return Mover(d); - } - - public Point3D GetGoalLocation() - { - if (Goal is Item item) - return item.GetWorldLocation(); - - return new Point3D(Goal); - } - - public void Advance(ref Point3D p, int index) - { - if (m_Path?.Success == true) - { - Direction[] dirs = m_Path.Directions; - - if (index >= 0 && index < dirs.Length) - { - int x = p.X, y = p.Y; - - CalcMoves.Offset(dirs[index], ref x, ref y); - - p.X = x; - p.Y = y; - } - } - } - - public void ForceRepath() - { - m_Path = null; - } - - public bool CheckPath() - { - if (!Enabled) - return false; - - Point3D goal = GetGoalLocation(); - - if (m_Path != null && ((m_Path.Success && goal == m_LastGoalLoc) || m_LastPathTime + RepathDelay > DateTime.Now) && - !(m_Path.Success && Check(m_From.Location, m_LastGoalLoc, 0))) - return false; - - m_LastPathTime = DateTime.UtcNow; - m_LastGoalLoc = goal; - - m_Path = new MovementPath(m_From, goal); - - m_Index = 0; - m_Next = m_From.Location; - - Advance(ref m_Next, m_Index); - - return true; - } - - public bool Check(Point3D loc, Point3D goal, int range) => Utility.InRange(loc, goal, range) && (range > 1 || Math.Abs(loc.Z - goal.Z) < 16); - - public bool Follow(bool run, int range) - { - Point3D goal = GetGoalLocation(); - Direction d; - - if (Check(m_From.Location, goal, range)) - return true; - - bool repathed = CheckPath(); - - if (!(Enabled && m_Path.Success)) - { - d = m_From.GetDirectionTo(goal); - - if (run) - d |= Direction.Running; - - m_From.SetDirection(d); - Move(d); - - return Check(m_From.Location, goal, range); - } - - d = m_From.GetDirectionTo(m_Next); - - if (run) - d |= Direction.Running; - - m_From.SetDirection(d); - - MoveResult res = Move(d); - - if (res == MoveResult.Blocked) - { - if (repathed) - return false; - - m_Path = null; - CheckPath(); - - if (!m_Path.Success) - { - d = m_From.GetDirectionTo(goal); - - if (run) - d |= Direction.Running; - - m_From.SetDirection(d); - Move(d); - - return Check(m_From.Location, goal, range); - } - - d = m_From.GetDirectionTo(m_Next); - - if (run) - d |= Direction.Running; - - m_From.SetDirection(d); - - res = Move(d); - - if (res == MoveResult.Blocked) - return false; - } - - if (m_From.X == m_Next.X && m_From.Y == m_Next.Y) - { - if (m_From.Z == m_Next.Z) - { - ++m_Index; - Advance(ref m_Next, m_Index); - } - else - { - m_Path = null; - } - } - - return Check(m_From.Location, goal, range); - } - } -} +using System; +using CalcMoves = Server.Movement.Movement; + +namespace Server +{ + public class PathFollower + { + private static bool Enabled; + private static readonly TimeSpan RepathDelay = TimeSpan.FromSeconds(2.0); + + private readonly Mobile m_From; + private int m_Index; + private DateTime m_LastPathTime; + private Point3D m_Next, m_LastGoalLoc; + private MovementPath m_Path; + + public PathFollower(Mobile from, IPoint3D goal) + { + m_From = from; + Goal = goal; + } + + public MoveMethod Mover { get; set; } + + public IPoint3D Goal { get; } + + public static void Initialize() + { + Enabled = ServerConfiguration.GetOrUpdateSetting("pathfinding.enable", true); + } + + public MoveResult Move(Direction d) + { + if (Mover == null) + return m_From.Move(d) ? MoveResult.Success : MoveResult.Blocked; + + return Mover(d); + } + + public Point3D GetGoalLocation() + { + if (Goal is Item item) + return item.GetWorldLocation(); + + return new Point3D(Goal); + } + + public void Advance(ref Point3D p, int index) + { + if (m_Path?.Success == true) + { + var dirs = m_Path.Directions; + + if (index >= 0 && index < dirs.Length) + { + int x = p.X, y = p.Y; + + CalcMoves.Offset(dirs[index], ref x, ref y); + + p.X = x; + p.Y = y; + } + } + } + + public void ForceRepath() + { + m_Path = null; + } + + public bool CheckPath() + { + if (!Enabled) + return false; + + var goal = GetGoalLocation(); + + if (m_Path != null && (m_Path.Success && goal == m_LastGoalLoc || m_LastPathTime + RepathDelay > DateTime.Now) && + !(m_Path.Success && Check(m_From.Location, m_LastGoalLoc, 0))) + return false; + + m_LastPathTime = DateTime.UtcNow; + m_LastGoalLoc = goal; + + m_Path = new MovementPath(m_From, goal); + + m_Index = 0; + m_Next = m_From.Location; + + Advance(ref m_Next, m_Index); + + return true; + } + + public bool Check(Point3D loc, Point3D goal, int range) => + Utility.InRange(loc, goal, range) && (range > 1 || Math.Abs(loc.Z - goal.Z) < 16); + + public bool Follow(bool run, int range) + { + var goal = GetGoalLocation(); + Direction d; + + if (Check(m_From.Location, goal, range)) + return true; + + var repathed = CheckPath(); + + if (!(Enabled && m_Path.Success)) + { + d = m_From.GetDirectionTo(goal); + + if (run) + d |= Direction.Running; + + m_From.SetDirection(d); + Move(d); + + return Check(m_From.Location, goal, range); + } + + d = m_From.GetDirectionTo(m_Next); + + if (run) + d |= Direction.Running; + + m_From.SetDirection(d); + + var res = Move(d); + + if (res == MoveResult.Blocked) + { + if (repathed) + return false; + + m_Path = null; + CheckPath(); + + if (!m_Path.Success) + { + d = m_From.GetDirectionTo(goal); + + if (run) + d |= Direction.Running; + + m_From.SetDirection(d); + Move(d); + + return Check(m_From.Location, goal, range); + } + + d = m_From.GetDirectionTo(m_Next); + + if (run) + d |= Direction.Running; + + m_From.SetDirection(d); + + res = Move(d); + + if (res == MoveResult.Blocked) + return false; + } + + if (m_From.X == m_Next.X && m_From.Y == m_Next.Y) + { + if (m_From.Z == m_Next.Z) + { + ++m_Index; + Advance(ref m_Next, m_Index); + } + else + { + m_Path = null; + } + } + + return Check(m_From.Location, goal, range); + } + } +} diff --git a/Projects/UOContent/Engines/Pathing/SlowAStarAlgorithm.cs b/Projects/UOContent/Engines/Pathing/SlowAStarAlgorithm.cs index 45c5a1520..fff1fe5da 100644 --- a/Projects/UOContent/Engines/Pathing/SlowAStarAlgorithm.cs +++ b/Projects/UOContent/Engines/Pathing/SlowAStarAlgorithm.cs @@ -1,274 +1,274 @@ -using System; -using Server.Mobiles; -using CalcMoves = Server.Movement.Movement; -using MoveImpl = Server.Movement.MovementImpl; - -namespace Server.PathAlgorithms.SlowAStar -{ - public struct PathNode - { - public int x, y, z; - public int g, h; - public int px, py, pz; - public int dir; - } - - public class SlowAStarAlgorithm : PathAlgorithm - { - private const int MaxDepth = 300; - private const int MaxNodes = MaxDepth * 16; - public static PathAlgorithm Instance = new SlowAStarAlgorithm(); - - private static readonly PathNode[] m_Closed = new PathNode[MaxNodes]; - private static readonly PathNode[] m_Open = new PathNode[MaxNodes]; - private static readonly PathNode[] m_Successors = new PathNode[8]; - private static readonly Direction[] m_Path = new Direction[MaxNodes]; - - private Point3D m_Goal; - - public int Heuristic(int x, int y, int z) - { - x -= m_Goal.X; - y -= m_Goal.Y; - z -= m_Goal.Z; - - x *= 11; - y *= 11; - - return x * x + y * y + z * z; - } - - public override bool CheckCondition(Mobile m, Map map, Point3D start, Point3D goal) => false; - - public override Direction[] Find(Mobile m, Map map, Point3D start, Point3D goal) - { - m_Goal = goal; - - BaseCreature bc = m as BaseCreature; - - PathNode curNode; - - PathNode goalNode = new PathNode(); - goalNode.x = goal.X; - goalNode.y = goal.Y; - goalNode.z = goal.Z; - - PathNode startNode = new PathNode(); - startNode.x = start.X; - startNode.y = start.Y; - startNode.z = start.Z; - startNode.h = Heuristic(startNode.x, startNode.y, startNode.z); - - PathNode[] closed = m_Closed, open = m_Open, successors = m_Successors; - Direction[] path = m_Path; - - int closedCount = 0, openCount = 0; - int pathCount = 0; - int depth = 0; - - int iBacktrack = 0; - - open[openCount++] = startNode; - - while (openCount > 0) - { - curNode = open[0]; - int curF = curNode.g + curNode.h; - int popIndex = 0; - - for (int i = 1; i < openCount; ++i) - if (open[i].g + open[i].h < curF) - { - curNode = open[i]; - curF = curNode.g + curNode.h; - popIndex = i; - } - - if (curNode.x == goalNode.x && curNode.y == goalNode.y && Math.Abs(curNode.z - goalNode.z) < 16) - { - if (closedCount == MaxNodes) - break; - - closed[closedCount++] = curNode; - - int xBacktrack = curNode.px; - int yBacktrack = curNode.py; - int zBacktrack = curNode.pz; - - if (pathCount == MaxNodes) - break; - - path[pathCount++] = (Direction)curNode.dir; - - while (xBacktrack != startNode.x || yBacktrack != startNode.y || zBacktrack != startNode.z) - { - bool found = false; - - for (int j = 0; !found && j < closedCount; ++j) - if (closed[j].x == xBacktrack && closed[j].y == yBacktrack && closed[j].z == zBacktrack) - { - if (pathCount == MaxNodes) - break; - - curNode = closed[j]; - path[pathCount++] = (Direction)curNode.dir; - xBacktrack = curNode.px; - yBacktrack = curNode.py; - zBacktrack = curNode.pz; - found = true; - } - - if (!found) - { - Console.WriteLine("bugaboo.."); - return null; - } - - if (pathCount == MaxNodes) - break; - } - - if (pathCount == MaxNodes) - break; - - Direction[] dirs = new Direction[pathCount]; - - while (pathCount > 0) - dirs[iBacktrack++] = path[--pathCount]; - - return dirs; - } - - --openCount; - - for (int i = popIndex; i < openCount; ++i) - open[i] = open[i + 1]; - - int sucCount = 0; - - if (bc != null) - { - MoveImpl.AlwaysIgnoreDoors = bc.CanOpenDoors; - MoveImpl.IgnoreMovableImpassables = bc.CanMoveOverObstacles; - } - - MoveImpl.Goal = goal; - - int x; - int y; - int z; - for (int i = 0; i < 8; ++i) - { - switch (i) - { - default: - x = 0; - y = -1; - break; - case 1: - x = 1; - y = -1; - break; - case 2: - x = 1; - y = 0; - break; - case 3: - x = 1; - y = 1; - break; - case 4: - x = 0; - y = 1; - break; - case 5: - x = -1; - y = 1; - break; - case 6: - x = -1; - y = 0; - break; - case 7: - x = -1; - y = -1; - break; - } - - if (CalcMoves.CheckMovement(m, map, new Point3D(curNode.x, curNode.y, curNode.z), (Direction)i, out z)) - { - successors[sucCount].x = x + curNode.x; - successors[sucCount].y = y + curNode.y; - successors[sucCount++].z = z; - } - } - - MoveImpl.AlwaysIgnoreDoors = false; - MoveImpl.IgnoreMovableImpassables = false; - MoveImpl.Goal = Point3D.Zero; - - if (sucCount == 0 || ++depth > MaxDepth) - break; - - for (int i = 0; i < sucCount; ++i) - { - x = successors[i].x; - y = successors[i].y; - z = successors[i].z; - - successors[i].g = curNode.g + 1; - - int openIndex = -1, closedIndex = -1; - - for (int j = 0; openIndex == -1 && j < openCount; ++j) - if (open[j].x == x && open[j].y == y && open[j].z == z) - openIndex = j; - - if (openIndex >= 0 && open[openIndex].g < successors[i].g) - continue; - - for (int j = 0; closedIndex == -1 && j < closedCount; ++j) - if (closed[j].x == x && closed[j].y == y && closed[j].z == z) - closedIndex = j; - - if (closedIndex >= 0 && closed[closedIndex].g < successors[i].g) - continue; - - if (openIndex >= 0) - { - --openCount; - - for (int j = openIndex; j < openCount; ++j) - open[j] = open[j + 1]; - } - - if (closedIndex >= 0) - { - --closedCount; - - for (int j = closedIndex; j < closedCount; ++j) - closed[j] = closed[j + 1]; - } - - successors[i].px = curNode.x; - successors[i].py = curNode.y; - successors[i].pz = curNode.z; - successors[i].dir = (int)GetDirection(curNode.x, curNode.y, x, y); - successors[i].h = Heuristic(x, y, z); - - if (openCount == MaxNodes) - break; - - open[openCount++] = successors[i]; - } - - if (openCount == MaxNodes || closedCount == MaxNodes) - break; - - closed[closedCount++] = curNode; - } - - return null; - } - } -} +using System; +using Server.Mobiles; +using CalcMoves = Server.Movement.Movement; +using MoveImpl = Server.Movement.MovementImpl; + +namespace Server.PathAlgorithms.SlowAStar +{ + public struct PathNode + { + public int x, y, z; + public int g, h; + public int px, py, pz; + public int dir; + } + + public class SlowAStarAlgorithm : PathAlgorithm + { + private const int MaxDepth = 300; + private const int MaxNodes = MaxDepth * 16; + public static PathAlgorithm Instance = new SlowAStarAlgorithm(); + + private static readonly PathNode[] m_Closed = new PathNode[MaxNodes]; + private static readonly PathNode[] m_Open = new PathNode[MaxNodes]; + private static readonly PathNode[] m_Successors = new PathNode[8]; + private static readonly Direction[] m_Path = new Direction[MaxNodes]; + + private Point3D m_Goal; + + public int Heuristic(int x, int y, int z) + { + x -= m_Goal.X; + y -= m_Goal.Y; + z -= m_Goal.Z; + + x *= 11; + y *= 11; + + return x * x + y * y + z * z; + } + + public override bool CheckCondition(Mobile m, Map map, Point3D start, Point3D goal) => false; + + public override Direction[] Find(Mobile m, Map map, Point3D start, Point3D goal) + { + m_Goal = goal; + + var bc = m as BaseCreature; + + PathNode curNode; + + var goalNode = new PathNode(); + goalNode.x = goal.X; + goalNode.y = goal.Y; + goalNode.z = goal.Z; + + var startNode = new PathNode(); + startNode.x = start.X; + startNode.y = start.Y; + startNode.z = start.Z; + startNode.h = Heuristic(startNode.x, startNode.y, startNode.z); + + PathNode[] closed = m_Closed, open = m_Open, successors = m_Successors; + var path = m_Path; + + int closedCount = 0, openCount = 0; + var pathCount = 0; + var depth = 0; + + var iBacktrack = 0; + + open[openCount++] = startNode; + + while (openCount > 0) + { + curNode = open[0]; + var curF = curNode.g + curNode.h; + var popIndex = 0; + + for (var i = 1; i < openCount; ++i) + if (open[i].g + open[i].h < curF) + { + curNode = open[i]; + curF = curNode.g + curNode.h; + popIndex = i; + } + + if (curNode.x == goalNode.x && curNode.y == goalNode.y && Math.Abs(curNode.z - goalNode.z) < 16) + { + if (closedCount == MaxNodes) + break; + + closed[closedCount++] = curNode; + + var xBacktrack = curNode.px; + var yBacktrack = curNode.py; + var zBacktrack = curNode.pz; + + if (pathCount == MaxNodes) + break; + + path[pathCount++] = (Direction)curNode.dir; + + while (xBacktrack != startNode.x || yBacktrack != startNode.y || zBacktrack != startNode.z) + { + var found = false; + + for (var j = 0; !found && j < closedCount; ++j) + if (closed[j].x == xBacktrack && closed[j].y == yBacktrack && closed[j].z == zBacktrack) + { + if (pathCount == MaxNodes) + break; + + curNode = closed[j]; + path[pathCount++] = (Direction)curNode.dir; + xBacktrack = curNode.px; + yBacktrack = curNode.py; + zBacktrack = curNode.pz; + found = true; + } + + if (!found) + { + Console.WriteLine("bugaboo.."); + return null; + } + + if (pathCount == MaxNodes) + break; + } + + if (pathCount == MaxNodes) + break; + + var dirs = new Direction[pathCount]; + + while (pathCount > 0) + dirs[iBacktrack++] = path[--pathCount]; + + return dirs; + } + + --openCount; + + for (var i = popIndex; i < openCount; ++i) + open[i] = open[i + 1]; + + var sucCount = 0; + + if (bc != null) + { + MoveImpl.AlwaysIgnoreDoors = bc.CanOpenDoors; + MoveImpl.IgnoreMovableImpassables = bc.CanMoveOverObstacles; + } + + MoveImpl.Goal = goal; + + int x; + int y; + int z; + for (var i = 0; i < 8; ++i) + { + switch (i) + { + default: + x = 0; + y = -1; + break; + case 1: + x = 1; + y = -1; + break; + case 2: + x = 1; + y = 0; + break; + case 3: + x = 1; + y = 1; + break; + case 4: + x = 0; + y = 1; + break; + case 5: + x = -1; + y = 1; + break; + case 6: + x = -1; + y = 0; + break; + case 7: + x = -1; + y = -1; + break; + } + + if (CalcMoves.CheckMovement(m, map, new Point3D(curNode.x, curNode.y, curNode.z), (Direction)i, out z)) + { + successors[sucCount].x = x + curNode.x; + successors[sucCount].y = y + curNode.y; + successors[sucCount++].z = z; + } + } + + MoveImpl.AlwaysIgnoreDoors = false; + MoveImpl.IgnoreMovableImpassables = false; + MoveImpl.Goal = Point3D.Zero; + + if (sucCount == 0 || ++depth > MaxDepth) + break; + + for (var i = 0; i < sucCount; ++i) + { + x = successors[i].x; + y = successors[i].y; + z = successors[i].z; + + successors[i].g = curNode.g + 1; + + int openIndex = -1, closedIndex = -1; + + for (var j = 0; openIndex == -1 && j < openCount; ++j) + if (open[j].x == x && open[j].y == y && open[j].z == z) + openIndex = j; + + if (openIndex >= 0 && open[openIndex].g < successors[i].g) + continue; + + for (var j = 0; closedIndex == -1 && j < closedCount; ++j) + if (closed[j].x == x && closed[j].y == y && closed[j].z == z) + closedIndex = j; + + if (closedIndex >= 0 && closed[closedIndex].g < successors[i].g) + continue; + + if (openIndex >= 0) + { + --openCount; + + for (var j = openIndex; j < openCount; ++j) + open[j] = open[j + 1]; + } + + if (closedIndex >= 0) + { + --closedCount; + + for (var j = closedIndex; j < closedCount; ++j) + closed[j] = closed[j + 1]; + } + + successors[i].px = curNode.x; + successors[i].py = curNode.y; + successors[i].pz = curNode.z; + successors[i].dir = (int)GetDirection(curNode.x, curNode.y, x, y); + successors[i].h = Heuristic(x, y, z); + + if (openCount == MaxNodes) + break; + + open[openCount++] = successors[i]; + } + + if (openCount == MaxNodes || closedCount == MaxNodes) + break; + + closed[closedCount++] = curNode; + } + + return null; + } + } +} diff --git a/Projects/UOContent/Engines/Plants/EmptyTheBowlGump.cs b/Projects/UOContent/Engines/Plants/EmptyTheBowlGump.cs index a67237003..4e6b01d3a 100644 --- a/Projects/UOContent/Engines/Plants/EmptyTheBowlGump.cs +++ b/Projects/UOContent/Engines/Plants/EmptyTheBowlGump.cs @@ -1,121 +1,121 @@ -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.Plants -{ - public class EmptyTheBowlGump : Gump - { - private readonly PlantItem m_Plant; - - public EmptyTheBowlGump(PlantItem plant) : base(20, 20) - { - m_Plant = plant; - - DrawBackground(); - - AddLabel(90, 70, 0x44, "Empty the bowl?"); - - DrawPicture(); - - AddButton(98, 150, 0x47E, 0x480, 1); // Cancel - - AddButton(138, 151, 0xD2, 0xD2, 2); // Help - AddLabel(143, 151, 0x835, "?"); - - AddButton(168, 150, 0x481, 0x483, 3); // Ok - } - - private void DrawBackground() - { - AddBackground(50, 50, 200, 150, 0xE10); - - AddItem(45, 45, 0xCEF); - AddItem(45, 118, 0xCF0); - - AddItem(211, 45, 0xCEB); - AddItem(211, 118, 0xCEC); - } - - private void DrawPicture() - { - AddItem(90, 100, 0x1602); - AddImage(140, 102, 0x15E1); - AddItem(160, 100, 0x15FD); - - if (m_Plant.PlantStatus != PlantStatus.BowlOfDirt && m_Plant.PlantStatus < PlantStatus.Plant) - AddItem(156, 130, 0xDCF); // Seed - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - Mobile from = sender.Mobile; - - if (info.ButtonID == 0 || m_Plant.Deleted || m_Plant.PlantStatus >= PlantStatus.DecorativePlant) - return; - - if (info.ButtonID == 3 && !from.InRange(m_Plant.GetWorldLocation(), 3)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 500446); // That is too far away. - return; - } - - if (!m_Plant.IsUsableBy(from)) - { - m_Plant.LabelTo(from, 1061856); // You must have the item in your backpack or locked down in order to use it. - return; - } - - switch (info.ButtonID) - { - case 1: // Cancel - { - from.SendGump(new MainPlantGump(m_Plant)); - - break; - } - case 2: // Help - { - from.Send(new DisplayHelpTopic(71, true)); // EMPTYING THE BOWL - - from.SendGump(new EmptyTheBowlGump(m_Plant)); - - break; - } - case 3: // Ok - { - PlantBowl bowl = new PlantBowl(); - - if (!from.PlaceInBackpack(bowl)) - { - bowl.Delete(); - - m_Plant.LabelTo(from, 1053047); // You cannot empty a bowl with a full pack! - from.SendGump(new MainPlantGump(m_Plant)); - - break; - } - - if (m_Plant.PlantStatus != PlantStatus.BowlOfDirt && m_Plant.PlantStatus < PlantStatus.Plant) - { - Seed seed = new Seed(m_Plant.PlantType, m_Plant.PlantHue, m_Plant.ShowType); - - if (!from.PlaceInBackpack(seed)) - { - bowl.Delete(); - seed.Delete(); - - m_Plant.LabelTo(from, 1053047); // You cannot empty a bowl with a full pack! - from.SendGump(new MainPlantGump(m_Plant)); - - break; - } - } - - m_Plant.Delete(); - - break; - } - } - } - } -} +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.Plants +{ + public class EmptyTheBowlGump : Gump + { + private readonly PlantItem m_Plant; + + public EmptyTheBowlGump(PlantItem plant) : base(20, 20) + { + m_Plant = plant; + + DrawBackground(); + + AddLabel(90, 70, 0x44, "Empty the bowl?"); + + DrawPicture(); + + AddButton(98, 150, 0x47E, 0x480, 1); // Cancel + + AddButton(138, 151, 0xD2, 0xD2, 2); // Help + AddLabel(143, 151, 0x835, "?"); + + AddButton(168, 150, 0x481, 0x483, 3); // Ok + } + + private void DrawBackground() + { + AddBackground(50, 50, 200, 150, 0xE10); + + AddItem(45, 45, 0xCEF); + AddItem(45, 118, 0xCF0); + + AddItem(211, 45, 0xCEB); + AddItem(211, 118, 0xCEC); + } + + private void DrawPicture() + { + AddItem(90, 100, 0x1602); + AddImage(140, 102, 0x15E1); + AddItem(160, 100, 0x15FD); + + if (m_Plant.PlantStatus != PlantStatus.BowlOfDirt && m_Plant.PlantStatus < PlantStatus.Plant) + AddItem(156, 130, 0xDCF); // Seed + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var from = sender.Mobile; + + if (info.ButtonID == 0 || m_Plant.Deleted || m_Plant.PlantStatus >= PlantStatus.DecorativePlant) + return; + + if (info.ButtonID == 3 && !from.InRange(m_Plant.GetWorldLocation(), 3)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 500446); // That is too far away. + return; + } + + if (!m_Plant.IsUsableBy(from)) + { + m_Plant.LabelTo(from, 1061856); // You must have the item in your backpack or locked down in order to use it. + return; + } + + switch (info.ButtonID) + { + case 1: // Cancel + { + from.SendGump(new MainPlantGump(m_Plant)); + + break; + } + case 2: // Help + { + from.Send(new DisplayHelpTopic(71, true)); // EMPTYING THE BOWL + + from.SendGump(new EmptyTheBowlGump(m_Plant)); + + break; + } + case 3: // Ok + { + var bowl = new PlantBowl(); + + if (!from.PlaceInBackpack(bowl)) + { + bowl.Delete(); + + m_Plant.LabelTo(from, 1053047); // You cannot empty a bowl with a full pack! + from.SendGump(new MainPlantGump(m_Plant)); + + break; + } + + if (m_Plant.PlantStatus != PlantStatus.BowlOfDirt && m_Plant.PlantStatus < PlantStatus.Plant) + { + var seed = new Seed(m_Plant.PlantType, m_Plant.PlantHue, m_Plant.ShowType); + + if (!from.PlaceInBackpack(seed)) + { + bowl.Delete(); + seed.Delete(); + + m_Plant.LabelTo(from, 1053047); // You cannot empty a bowl with a full pack! + from.SendGump(new MainPlantGump(m_Plant)); + + break; + } + } + + m_Plant.Delete(); + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Plants/MainPlantGump.cs b/Projects/UOContent/Engines/Plants/MainPlantGump.cs index e2dacc43d..43dfa97f1 100644 --- a/Projects/UOContent/Engines/Plants/MainPlantGump.cs +++ b/Projects/UOContent/Engines/Plants/MainPlantGump.cs @@ -1,423 +1,430 @@ -using System; -using Server.Gumps; -using Server.Items; -using Server.Network; - -namespace Server.Engines.Plants -{ - public class MainPlantGump : Gump - { - private readonly PlantItem m_Plant; - - public MainPlantGump(PlantItem plant) : base(20, 20) - { - m_Plant = plant; - - DrawBackground(); - - DrawPlant(); - - AddButton(71, 67, 0xD4, 0xD4, 1); // Reproduction menu - AddItem(59, 68, 0xD08); - - PlantSystem system = plant.PlantSystem; - - AddButton(71, 91, 0xD4, 0xD4, 2); // Infestation - AddItem(8, 96, 0x372); - AddPlus(95, 92, system.Infestation); - - AddButton(71, 115, 0xD4, 0xD4, 3); // Fungus - AddItem(58, 115, 0xD16); - AddPlus(95, 116, system.Fungus); - - AddButton(71, 139, 0xD4, 0xD4, 4); // Poison - AddItem(59, 143, 0x1AE4); - AddPlus(95, 140, system.Poison); - - AddButton(71, 163, 0xD4, 0xD4, 5); // Disease - AddItem(55, 167, 0x1727); - AddPlus(95, 164, system.Disease); - - AddButton(209, 67, 0xD2, 0xD2, 6); // Water - AddItem(193, 67, 0x1F9D); - AddPlusMinus(196, 67, system.Water); - - AddButton(209, 91, 0xD4, 0xD4, 7); // Poison potion - AddItem(201, 91, 0xF0A); - AddLevel(196, 91, system.PoisonPotion); - - AddButton(209, 115, 0xD4, 0xD4, 8); // Cure potion - AddItem(201, 115, 0xF07); - AddLevel(196, 115, system.CurePotion); - - AddButton(209, 139, 0xD4, 0xD4, 9); // Heal potion - AddItem(201, 139, 0xF0C); - AddLevel(196, 139, system.HealPotion); - - AddButton(209, 163, 0xD4, 0xD4, 10); // Strength potion - AddItem(201, 163, 0xF09); - AddLevel(196, 163, system.StrengthPotion); - - AddImage(48, 47, 0xD2); - AddLevel(54, 47, (int)m_Plant.PlantStatus); - - AddImage(232, 47, 0xD2); - AddGrowthIndicator(239, 47); - - AddButton(48, 183, 0xD2, 0xD2, 11); // Help - AddLabel(54, 183, 0x835, "?"); - - AddButton(232, 183, 0xD4, 0xD4, 12); // Empty the bowl - AddItem(219, 180, 0x15FD); - } - - private void DrawBackground() - { - AddBackground(50, 50, 200, 150, 0xE10); - - AddItem(45, 45, 0xCEF); - AddItem(45, 118, 0xCF0); - - AddItem(211, 45, 0xCEB); - AddItem(211, 118, 0xCEC); - } - - private void DrawPlant() - { - PlantStatus status = m_Plant.PlantStatus; - - if (status < PlantStatus.FullGrownPlant) - { - AddImage(110, 85, 0x589); - - AddItem(122, 94, 0x914); - AddItem(135, 94, 0x914); - AddItem(120, 112, 0x914); - AddItem(135, 112, 0x914); - - if (status >= PlantStatus.Stage2) AddItem(127, 112, 0xC62); - if (status == PlantStatus.Stage3 || status == PlantStatus.Stage4) AddItem(129, 85, 0xC7E); - if (status >= PlantStatus.Stage4) - { - AddItem(121, 117, 0xC62); - AddItem(133, 117, 0xC62); - } - - if (status >= PlantStatus.Stage5) - { - AddItem(110, 100, 0xC62); - AddItem(140, 100, 0xC62); - AddItem(110, 130, 0xC62); - AddItem(140, 130, 0xC62); - } - - if (status >= PlantStatus.Stage6) - { - AddItem(105, 115, 0xC62); - AddItem(145, 115, 0xC62); - AddItem(125, 90, 0xC62); - AddItem(125, 135, 0xC62); - } - } - else - { - PlantTypeInfo typeInfo = PlantTypeInfo.GetInfo(m_Plant.PlantType); - PlantHueInfo hueInfo = PlantHueInfo.GetInfo(m_Plant.PlantHue); - - // The large images for these trees trigger a client crash, so use a smaller, generic tree. - if (m_Plant.PlantType == PlantType.CypressTwisted || m_Plant.PlantType == PlantType.CypressStraight) - AddItem(130 + typeInfo.OffsetX, 96 + typeInfo.OffsetY, 0x0CCA, hueInfo.Hue); - else - AddItem(130 + typeInfo.OffsetX, 96 + typeInfo.OffsetY, typeInfo.ItemID, hueInfo.Hue); - } - - if (status != PlantStatus.BowlOfDirt) - { - int message = m_Plant.PlantSystem.GetLocalizedHealth(); - - switch (m_Plant.PlantSystem.Health) - { - case PlantHealth.Dying: - { - AddItem(92, 167, 0x1B9D); - AddItem(161, 167, 0x1B9D); - - AddHtmlLocalized(136, 167, 42, 20, message, 0x00FC00); - - break; - } - case PlantHealth.Wilted: - { - AddItem(91, 164, 0x18E6); - AddItem(161, 164, 0x18E6); - - AddHtmlLocalized(132, 167, 42, 20, message, 0x00C207); - - break; - } - case PlantHealth.Healthy: - { - AddItem(96, 168, 0xC61); - AddItem(162, 168, 0xC61); - - AddHtmlLocalized(129, 167, 42, 20, message, 0x008200); - - break; - } - case PlantHealth.Vibrant: - { - AddItem(93, 162, 0x1A99); - AddItem(162, 162, 0x1A99); - - AddHtmlLocalized(129, 167, 42, 20, message, 0x0083E0); - - break; - } - } - } - } - - private void AddPlus(int x, int y, int value) - { - switch (value) - { - case 1: - AddLabel(x, y, 0x35, "+"); - break; - case 2: - AddLabel(x, y, 0x21, "+"); - break; - } - } - - private void AddPlusMinus(int x, int y, int value) - { - switch (value) - { - case 0: - AddLabel(x, y, 0x21, "-"); - break; - case 1: - AddLabel(x, y, 0x35, "-"); - break; - case 3: - AddLabel(x, y, 0x35, "+"); - break; - case 4: - AddLabel(x, y, 0x21, "+"); - break; - } - } - - private void AddLevel(int x, int y, int value) - { - AddLabel(x, y, 0x835, value.ToString()); - } - - private void AddGrowthIndicator(int x, int y) - { - if (!m_Plant.IsGrowable) - return; - - switch (m_Plant.PlantSystem.GrowthIndicator) - { - case PlantGrowthIndicator.InvalidLocation: - AddLabel(x, y, 0x21, "!"); - break; - case PlantGrowthIndicator.NotHealthy: - AddLabel(x, y, 0x21, "-"); - break; - case PlantGrowthIndicator.Delay: - AddLabel(x, y, 0x35, "-"); - break; - case PlantGrowthIndicator.Grown: - AddLabel(x, y, 0x3, "+"); - break; - case PlantGrowthIndicator.DoubleGrown: - AddLabel(x, y, 0x3F, "+"); - break; - } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - Mobile from = sender.Mobile; - - if (info.ButtonID == 0 || m_Plant.Deleted || m_Plant.PlantStatus >= PlantStatus.DecorativePlant) - return; - - if (((info.ButtonID >= 6 && info.ButtonID <= 10) || info.ButtonID == 12) && - !from.InRange(m_Plant.GetWorldLocation(), 3)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 500446); // That is too far away. - return; - } - - if (!m_Plant.IsUsableBy(from)) - { - m_Plant.LabelTo(from, 1061856); // You must have the item in your backpack or locked down in order to use it. - return; - } - - switch (info.ButtonID) - { - case 1: // Reproduction menu - { - if (m_Plant.PlantStatus > PlantStatus.BowlOfDirt) - { - from.SendGump(new ReproductionGump(m_Plant)); - } - else - { - from.SendLocalizedMessage(1061885); // You need to plant a seed in the bowl first. - - from.SendGump(new MainPlantGump(m_Plant)); - } - - break; - } - case 2: // Infestation - { - from.Send(new DisplayHelpTopic(54, true)); // INFESTATION LEVEL - - from.SendGump(new MainPlantGump(m_Plant)); - - break; - } - case 3: // Fungus - { - from.Send(new DisplayHelpTopic(56, true)); // FUNGUS LEVEL - - from.SendGump(new MainPlantGump(m_Plant)); - - break; - } - case 4: // Poison - { - from.Send(new DisplayHelpTopic(58, true)); // POISON LEVEL - - from.SendGump(new MainPlantGump(m_Plant)); - - break; - } - case 5: // Disease - { - from.Send(new DisplayHelpTopic(60, true)); // DISEASE LEVEL - - from.SendGump(new MainPlantGump(m_Plant)); - - break; - } - case 6: // Water - { - BaseBeverage bev = from.Backpack.FindItemsByType().Find(beverage => - beverage.IsEmpty && beverage.Pourable && beverage.Content == BeverageType.Water); - - if (bev == null) - { - from.Target = new PlantPourTarget(m_Plant); - from.SendLocalizedMessage(1060808, - $"#{m_Plant.GetLocalizedPlantStatus()}"); // Target the container you wish to use to water the ~1_val~. - } - else - { - m_Plant.Pour(from, bev); - } - - from.SendGump(new MainPlantGump(m_Plant)); - - break; - } - case 7: // Poison potion - { - AddPotion(from, PotionEffect.PoisonGreater, PotionEffect.PoisonDeadly); - - break; - } - case 8: // Cure potion - { - AddPotion(from, PotionEffect.CureGreater); - - break; - } - case 9: // Heal potion - { - AddPotion(from, PotionEffect.HealGreater); - - break; - } - case 10: // Strength potion - { - AddPotion(from, PotionEffect.StrengthGreater); - - break; - } - case 11: // Help - { - from.Send(new DisplayHelpTopic(48, true)); // PLANT GROWING - - from.SendGump(new MainPlantGump(m_Plant)); - - break; - } - case 12: // Empty the bowl - { - from.SendGump(new EmptyTheBowlGump(m_Plant)); - - break; - } - } - } - - private void AddPotion(Mobile from, params PotionEffect[] effects) - { - Item item = GetPotion(from, effects); - - if (item != null) - { - m_Plant.Pour(from, item); - } - else - { - if (m_Plant.ApplyPotion(effects[0], true, out int message)) - { - from.SendLocalizedMessage(1061884); // You don't have any strong potions of that type in your pack. - - from.Target = new PlantPourTarget(m_Plant); - from.SendLocalizedMessage(1060808, - $"#{m_Plant.GetLocalizedPlantStatus()}"); // Target the container you wish to use to water the ~1_val~. - - return; - } - - m_Plant.LabelTo(from, message); - } - - from.SendGump(new MainPlantGump(m_Plant)); - } - - public static Item GetPotion(Mobile from, PotionEffect[] effects) - { - if (from.Backpack == null) - return null; - - Item[] items = from.Backpack.FindItemsByType(new[] { typeof(BasePotion), typeof(PotionKeg) }); - - foreach (Item item in items) - if (item is BasePotion potion) - { - if (Array.IndexOf(effects, potion.PotionEffect) >= 0) - return potion; - } - else - { - PotionKeg keg = (PotionKeg)item; - - if (keg.Held > 0 && Array.IndexOf(effects, keg.Type) >= 0) - return keg; - } - - return null; - } - } -} +using System; +using Server.Gumps; +using Server.Items; +using Server.Network; + +namespace Server.Engines.Plants +{ + public class MainPlantGump : Gump + { + private readonly PlantItem m_Plant; + + public MainPlantGump(PlantItem plant) : base(20, 20) + { + m_Plant = plant; + + DrawBackground(); + + DrawPlant(); + + AddButton(71, 67, 0xD4, 0xD4, 1); // Reproduction menu + AddItem(59, 68, 0xD08); + + var system = plant.PlantSystem; + + AddButton(71, 91, 0xD4, 0xD4, 2); // Infestation + AddItem(8, 96, 0x372); + AddPlus(95, 92, system.Infestation); + + AddButton(71, 115, 0xD4, 0xD4, 3); // Fungus + AddItem(58, 115, 0xD16); + AddPlus(95, 116, system.Fungus); + + AddButton(71, 139, 0xD4, 0xD4, 4); // Poison + AddItem(59, 143, 0x1AE4); + AddPlus(95, 140, system.Poison); + + AddButton(71, 163, 0xD4, 0xD4, 5); // Disease + AddItem(55, 167, 0x1727); + AddPlus(95, 164, system.Disease); + + AddButton(209, 67, 0xD2, 0xD2, 6); // Water + AddItem(193, 67, 0x1F9D); + AddPlusMinus(196, 67, system.Water); + + AddButton(209, 91, 0xD4, 0xD4, 7); // Poison potion + AddItem(201, 91, 0xF0A); + AddLevel(196, 91, system.PoisonPotion); + + AddButton(209, 115, 0xD4, 0xD4, 8); // Cure potion + AddItem(201, 115, 0xF07); + AddLevel(196, 115, system.CurePotion); + + AddButton(209, 139, 0xD4, 0xD4, 9); // Heal potion + AddItem(201, 139, 0xF0C); + AddLevel(196, 139, system.HealPotion); + + AddButton(209, 163, 0xD4, 0xD4, 10); // Strength potion + AddItem(201, 163, 0xF09); + AddLevel(196, 163, system.StrengthPotion); + + AddImage(48, 47, 0xD2); + AddLevel(54, 47, (int)m_Plant.PlantStatus); + + AddImage(232, 47, 0xD2); + AddGrowthIndicator(239, 47); + + AddButton(48, 183, 0xD2, 0xD2, 11); // Help + AddLabel(54, 183, 0x835, "?"); + + AddButton(232, 183, 0xD4, 0xD4, 12); // Empty the bowl + AddItem(219, 180, 0x15FD); + } + + private void DrawBackground() + { + AddBackground(50, 50, 200, 150, 0xE10); + + AddItem(45, 45, 0xCEF); + AddItem(45, 118, 0xCF0); + + AddItem(211, 45, 0xCEB); + AddItem(211, 118, 0xCEC); + } + + private void DrawPlant() + { + var status = m_Plant.PlantStatus; + + if (status < PlantStatus.FullGrownPlant) + { + AddImage(110, 85, 0x589); + + AddItem(122, 94, 0x914); + AddItem(135, 94, 0x914); + AddItem(120, 112, 0x914); + AddItem(135, 112, 0x914); + + if (status >= PlantStatus.Stage2) AddItem(127, 112, 0xC62); + if (status == PlantStatus.Stage3 || status == PlantStatus.Stage4) AddItem(129, 85, 0xC7E); + if (status >= PlantStatus.Stage4) + { + AddItem(121, 117, 0xC62); + AddItem(133, 117, 0xC62); + } + + if (status >= PlantStatus.Stage5) + { + AddItem(110, 100, 0xC62); + AddItem(140, 100, 0xC62); + AddItem(110, 130, 0xC62); + AddItem(140, 130, 0xC62); + } + + if (status >= PlantStatus.Stage6) + { + AddItem(105, 115, 0xC62); + AddItem(145, 115, 0xC62); + AddItem(125, 90, 0xC62); + AddItem(125, 135, 0xC62); + } + } + else + { + var typeInfo = PlantTypeInfo.GetInfo(m_Plant.PlantType); + var hueInfo = PlantHueInfo.GetInfo(m_Plant.PlantHue); + + // The large images for these trees trigger a client crash, so use a smaller, generic tree. + if (m_Plant.PlantType == PlantType.CypressTwisted || m_Plant.PlantType == PlantType.CypressStraight) + AddItem(130 + typeInfo.OffsetX, 96 + typeInfo.OffsetY, 0x0CCA, hueInfo.Hue); + else + AddItem(130 + typeInfo.OffsetX, 96 + typeInfo.OffsetY, typeInfo.ItemID, hueInfo.Hue); + } + + if (status != PlantStatus.BowlOfDirt) + { + var message = m_Plant.PlantSystem.GetLocalizedHealth(); + + switch (m_Plant.PlantSystem.Health) + { + case PlantHealth.Dying: + { + AddItem(92, 167, 0x1B9D); + AddItem(161, 167, 0x1B9D); + + AddHtmlLocalized(136, 167, 42, 20, message, 0x00FC00); + + break; + } + case PlantHealth.Wilted: + { + AddItem(91, 164, 0x18E6); + AddItem(161, 164, 0x18E6); + + AddHtmlLocalized(132, 167, 42, 20, message, 0x00C207); + + break; + } + case PlantHealth.Healthy: + { + AddItem(96, 168, 0xC61); + AddItem(162, 168, 0xC61); + + AddHtmlLocalized(129, 167, 42, 20, message, 0x008200); + + break; + } + case PlantHealth.Vibrant: + { + AddItem(93, 162, 0x1A99); + AddItem(162, 162, 0x1A99); + + AddHtmlLocalized(129, 167, 42, 20, message, 0x0083E0); + + break; + } + } + } + } + + private void AddPlus(int x, int y, int value) + { + switch (value) + { + case 1: + AddLabel(x, y, 0x35, "+"); + break; + case 2: + AddLabel(x, y, 0x21, "+"); + break; + } + } + + private void AddPlusMinus(int x, int y, int value) + { + switch (value) + { + case 0: + AddLabel(x, y, 0x21, "-"); + break; + case 1: + AddLabel(x, y, 0x35, "-"); + break; + case 3: + AddLabel(x, y, 0x35, "+"); + break; + case 4: + AddLabel(x, y, 0x21, "+"); + break; + } + } + + private void AddLevel(int x, int y, int value) + { + AddLabel(x, y, 0x835, value.ToString()); + } + + private void AddGrowthIndicator(int x, int y) + { + if (!m_Plant.IsGrowable) + return; + + switch (m_Plant.PlantSystem.GrowthIndicator) + { + case PlantGrowthIndicator.InvalidLocation: + AddLabel(x, y, 0x21, "!"); + break; + case PlantGrowthIndicator.NotHealthy: + AddLabel(x, y, 0x21, "-"); + break; + case PlantGrowthIndicator.Delay: + AddLabel(x, y, 0x35, "-"); + break; + case PlantGrowthIndicator.Grown: + AddLabel(x, y, 0x3, "+"); + break; + case PlantGrowthIndicator.DoubleGrown: + AddLabel(x, y, 0x3F, "+"); + break; + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var from = sender.Mobile; + + if (info.ButtonID == 0 || m_Plant.Deleted || m_Plant.PlantStatus >= PlantStatus.DecorativePlant) + return; + + if ((info.ButtonID >= 6 && info.ButtonID <= 10 || info.ButtonID == 12) && + !from.InRange(m_Plant.GetWorldLocation(), 3)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 500446); // That is too far away. + return; + } + + if (!m_Plant.IsUsableBy(from)) + { + m_Plant.LabelTo(from, 1061856); // You must have the item in your backpack or locked down in order to use it. + return; + } + + switch (info.ButtonID) + { + case 1: // Reproduction menu + { + if (m_Plant.PlantStatus > PlantStatus.BowlOfDirt) + { + from.SendGump(new ReproductionGump(m_Plant)); + } + else + { + from.SendLocalizedMessage(1061885); // You need to plant a seed in the bowl first. + + from.SendGump(new MainPlantGump(m_Plant)); + } + + break; + } + case 2: // Infestation + { + from.Send(new DisplayHelpTopic(54, true)); // INFESTATION LEVEL + + from.SendGump(new MainPlantGump(m_Plant)); + + break; + } + case 3: // Fungus + { + from.Send(new DisplayHelpTopic(56, true)); // FUNGUS LEVEL + + from.SendGump(new MainPlantGump(m_Plant)); + + break; + } + case 4: // Poison + { + from.Send(new DisplayHelpTopic(58, true)); // POISON LEVEL + + from.SendGump(new MainPlantGump(m_Plant)); + + break; + } + case 5: // Disease + { + from.Send(new DisplayHelpTopic(60, true)); // DISEASE LEVEL + + from.SendGump(new MainPlantGump(m_Plant)); + + break; + } + case 6: // Water + { + var bev = from.Backpack.FindItemsByType() + .Find( + beverage => + beverage.IsEmpty && beverage.Pourable && beverage.Content == BeverageType.Water + ); + + if (bev == null) + { + from.Target = new PlantPourTarget(m_Plant); + from.SendLocalizedMessage( + 1060808, + $"#{m_Plant.GetLocalizedPlantStatus()}" + ); // Target the container you wish to use to water the ~1_val~. + } + else + { + m_Plant.Pour(from, bev); + } + + from.SendGump(new MainPlantGump(m_Plant)); + + break; + } + case 7: // Poison potion + { + AddPotion(from, PotionEffect.PoisonGreater, PotionEffect.PoisonDeadly); + + break; + } + case 8: // Cure potion + { + AddPotion(from, PotionEffect.CureGreater); + + break; + } + case 9: // Heal potion + { + AddPotion(from, PotionEffect.HealGreater); + + break; + } + case 10: // Strength potion + { + AddPotion(from, PotionEffect.StrengthGreater); + + break; + } + case 11: // Help + { + from.Send(new DisplayHelpTopic(48, true)); // PLANT GROWING + + from.SendGump(new MainPlantGump(m_Plant)); + + break; + } + case 12: // Empty the bowl + { + from.SendGump(new EmptyTheBowlGump(m_Plant)); + + break; + } + } + } + + private void AddPotion(Mobile from, params PotionEffect[] effects) + { + var item = GetPotion(from, effects); + + if (item != null) + { + m_Plant.Pour(from, item); + } + else + { + if (m_Plant.ApplyPotion(effects[0], true, out var message)) + { + from.SendLocalizedMessage(1061884); // You don't have any strong potions of that type in your pack. + + from.Target = new PlantPourTarget(m_Plant); + from.SendLocalizedMessage( + 1060808, + $"#{m_Plant.GetLocalizedPlantStatus()}" + ); // Target the container you wish to use to water the ~1_val~. + + return; + } + + m_Plant.LabelTo(from, message); + } + + from.SendGump(new MainPlantGump(m_Plant)); + } + + public static Item GetPotion(Mobile from, PotionEffect[] effects) + { + if (from.Backpack == null) + return null; + + var items = from.Backpack.FindItemsByType(new[] { typeof(BasePotion), typeof(PotionKeg) }); + + foreach (var item in items) + if (item is BasePotion potion) + { + if (Array.IndexOf(effects, potion.PotionEffect) >= 0) + return potion; + } + else + { + var keg = (PotionKeg)item; + + if (keg.Held > 0 && Array.IndexOf(effects, keg.Type) >= 0) + return keg; + } + + return null; + } + } +} diff --git a/Projects/UOContent/Engines/Plants/MiscItems/FertileDirt.cs b/Projects/UOContent/Engines/Plants/MiscItems/FertileDirt.cs index 514d7dc74..b3d6d1580 100644 --- a/Projects/UOContent/Engines/Plants/MiscItems/FertileDirt.cs +++ b/Projects/UOContent/Engines/Plants/MiscItems/FertileDirt.cs @@ -1,31 +1,31 @@ -namespace Server.Items -{ - public class FertileDirt : Item - { - [Constructible] - public FertileDirt(int amount = 1) : base(0xF81) - { - Stackable = true; - Weight = 1.0; - Amount = amount; - } - - public FertileDirt(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class FertileDirt : Item + { + [Constructible] + public FertileDirt(int amount = 1) : base(0xF81) + { + Stackable = true; + Weight = 1.0; + Amount = amount; + } + + public FertileDirt(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Plants/MiscItems/GreenThorns.cs b/Projects/UOContent/Engines/Plants/MiscItems/GreenThorns.cs index 13d77f51e..98180ab28 100644 --- a/Projects/UOContent/Engines/Plants/MiscItems/GreenThorns.cs +++ b/Projects/UOContent/Engines/Plants/MiscItems/GreenThorns.cs @@ -1,730 +1,808 @@ -using System; -using Server.Mobiles; -using Server.Network; -using Server.Targeting; -using Server.Utilities; - -namespace Server.Items -{ - public class GreenThorns : Item - { - [Constructible] - public GreenThorns(int amount = 1) : base(0xF42) - { - Stackable = true; - Weight = 1.0; - Hue = 0x42; - Amount = amount; - } - - public GreenThorns(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1060837; // green thorns - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - return; - } - - if (!from.CanBeginAction()) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1061908); // * You must wait a while before planting another thorn. * - return; - } - - from.Target = new InternalTarget(this); - from.SendLocalizedMessage(1061906); // Choose a spot to plant the thorn. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private class InternalTarget : Target - { - private readonly GreenThorns m_Thorn; - - public InternalTarget(GreenThorns thorn) : base(3, true, TargetFlags.None) => m_Thorn = thorn; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Thorn.Deleted) - return; - - if (!m_Thorn.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - return; - } - - if (!from.CanBeginAction()) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1061908); // * You must wait a while before planting another thorn. * - return; - } - - if (from.Map != Map.Trammel && from.Map != Map.Felucca) - { - from.LocalOverheadMessage(MessageType.Regular, 0x2B2, true, - "No solen lairs exist on this facet. Try again in Trammel or Felucca."); - return; - } - - if (!(targeted is LandTarget land)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1061912); // * You cannot plant a green thorn there! * - } - else - { - GreenThornsEffect effect = GreenThornsEffect.Create(from, land); - - if (effect == null) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1061913); // * You sense it would be useless to plant a green thorn there. * - } - else - { - m_Thorn.Consume(); - - from.LocalOverheadMessage(MessageType.Emote, 0x961, - 1061914); // * You push the strange green thorn into the ground * - from.NonlocalOverheadMessage(MessageType.Emote, 0x961, 1061915, - from.Name); // * ~1_PLAYER_NAME~ pushes a strange green thorn into the ground. * - - from.BeginAction(); - new EndActionTimer(from).Start(); - - effect.Start(); - } - } - } - - protected override void OnTargetOutOfRange(Mobile from, object targeted) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502825); // That location is too far away - } - } - - private class EndActionTimer : Timer - { - private readonly Mobile m_From; - - public EndActionTimer(Mobile from) : base(TimeSpan.FromMinutes(3.0)) - { - m_From = from; - Priority = TimerPriority.FiveSeconds; - } - - protected override void OnTick() - { - m_From.EndAction(); - } - } - } - - public abstract class GreenThornsEffect : Timer - { - private static readonly TilesAndEffect[] m_Table = - { - new TilesAndEffect(new[] - { - 0x71, 0x7C, - 0x82, 0xA7, - 0xDC, 0xE3, - 0xE8, 0xEB, - 0x141, 0x144, - 0x14C, 0x14F, - 0x169, 0x174, - 0x1DC, 0x1E7, - 0x1EC, 0x1EF, - 0x272, 0x275, - 0x27E, 0x281, - 0x2D0, 0x2D7, - 0x2E5, 0x2FF, - 0x303, 0x31F, - 0x32C, 0x32F, - 0x33D, 0x340, - 0x345, 0x34C, - 0x355, 0x358, - 0x367, 0x36E, - 0x377, 0x37A, - 0x38D, 0x390, - 0x395, 0x39C, - 0x3A5, 0x3A8, - 0x3F6, 0x405, - 0x547, 0x54E, - 0x553, 0x556, - 0x597, 0x59E, - 0x623, 0x63A, - 0x6F3, 0x6FA, - 0x777, 0x791, - 0x79A, 0x7A9, - 0x7AE, 0x7B1 - }, - typeof(DirtGreenThornsEffect)), - - new TilesAndEffect(new[] - { - 0x9, 0x15, - 0x150, 0x15C - }, - typeof(FurrowsGreenThornsEffect)), - - new TilesAndEffect(new[] - { - 0x9C4, 0x9EB, - 0x3D65, 0x3D65, - 0x3DC0, 0x3DD9, - 0x3DDB, 0x3DDC, - 0x3DDE, 0x3EF0, - 0x3FF6, 0x3FF6, - 0x3FFC, 0x3FFE - }, - typeof(SwampGreenThornsEffect)), - - new TilesAndEffect(new[] - { - 0x10C, 0x10F, - 0x114, 0x117, - 0x119, 0x11D, - 0x179, 0x18A, - 0x385, 0x38C, - 0x391, 0x394, - 0x39D, 0x3A4, - 0x3A9, 0x3AC, - 0x5BF, 0x5D6, - 0x5DF, 0x5E2, - 0x745, 0x748, - 0x751, 0x758, - 0x75D, 0x760, - 0x76D, 0x773 - }, - typeof(SnowGreenThornsEffect)), - - new TilesAndEffect(new[] - { - 0x16, 0x3A, - 0x44, 0x4B, - 0x11E, 0x121, - 0x126, 0x12D, - 0x192, 0x192, - 0x1A8, 0x1AB, - 0x1B9, 0x1D1, - 0x282, 0x285, - 0x28A, 0x291, - 0x335, 0x33C, - 0x341, 0x344, - 0x34D, 0x354, - 0x359, 0x35C, - 0x3B7, 0x3BE, - 0x3C7, 0x3CA, - 0x5A7, 0x5B2, - 0x64B, 0x652, - 0x657, 0x65A, - 0x663, 0x66A, - 0x66F, 0x672, - 0x7BD, 0x7D0 - }, - typeof(SandGreenThornsEffect)) - }; - - private int m_Step; - - public GreenThornsEffect(Point3D location, Map map, Mobile from) : base(TimeSpan.FromSeconds(2.5)) - { - Location = location; - Map = map; - From = from; - - Priority = TimerPriority.TwoFiftyMS; - } - - public Point3D Location { get; } - - public Map Map { get; } - - public Mobile From { get; } - - public static GreenThornsEffect Create(Mobile from, LandTarget land) - { - if (!from.Map.CanSpawnMobile(land.Location)) - return null; - - int tileID = land.TileID; - - foreach (TilesAndEffect taep in m_Table) - { - bool contains = false; - - for (int i = 0; !contains && i < taep.Tiles.Length; i += 2) - contains = tileID >= taep.Tiles[i] && tileID <= taep.Tiles[i + 1]; - - if (contains) - { - GreenThornsEffect effect = - (GreenThornsEffect)ActivatorUtil.CreateInstance(taep.Effect, land.Location, from.Map, from); - return effect; - } - } - - return null; - } - - protected override void OnTick() - { - TimeSpan nextDelay = Play(m_Step++); - - if (nextDelay > TimeSpan.Zero) - { - Delay = nextDelay; - - Start(); - } - } - - protected abstract TimeSpan Play(int step); - - protected bool SpawnItem(Item item) - { - for (int i = 0; i < 5; i++) // Try 5 times - { - int x = Location.X + Utility.RandomMinMax(-1, 1); - int y = Location.Y + Utility.RandomMinMax(-1, 1); - int z = Map.GetAverageZ(x, y); - - if (Map.CanFit(x, y, Location.Z, 1)) - { - item.MoveToWorld(new Point3D(x, y, Location.Z), Map); - return true; - } - - if (Map.CanFit(x, y, z, 1)) - { - item.MoveToWorld(new Point3D(x, y, z), Map); - return true; - } - } - - return false; - } - - protected bool SpawnCreature(BaseCreature creature) - { - for (int i = 0; i < 5; i++) // Try 5 times - { - int x = Location.X + Utility.RandomMinMax(-1, 1); - int y = Location.Y + Utility.RandomMinMax(-1, 1); - int z = Map.GetAverageZ(x, y); - - if (Map.CanSpawnMobile(x, y, Location.Z)) - { - creature.MoveToWorld(new Point3D(x, y, Location.Z), Map); - creature.Combatant = From; - return true; - } - - if (Map.CanSpawnMobile(x, y, z)) - { - creature.MoveToWorld(new Point3D(x, y, z), Map); - creature.Combatant = From; - return true; - } - } - - return false; - } - - private class TilesAndEffect - { - public TilesAndEffect(int[] tiles, Type effect) - { - Tiles = tiles; - Effect = effect; - } - - public int[] Tiles { get; } - - public Type Effect { get; } - } - } - - public class DirtGreenThornsEffect : GreenThornsEffect - { - public DirtGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from) - { - } - - protected override TimeSpan Play(int step) - { - switch (step) - { - case 0: - { - Effects.PlaySound(Location, Map, 0x106); - Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x3735, 1, - 182, 0xBE3); - - return TimeSpan.FromSeconds(4.0); - } - case 1: - { - Effects.PlaySound(Location, Map, 0x222); - - return TimeSpan.FromSeconds(4.0); - } - case 2: - { - Effects.PlaySound(Location, Map, 0x21F); - - return TimeSpan.FromSeconds(5.0); - } - case 3: - { - EffectItem dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0)); - dummy.PublicOverheadMessage(MessageType.Regular, 0x3B2, true, - "* The ground erupts with chaotic growth! *"); - - Effects.PlaySound(Location, Map, 0x12D); - - SpawnReagents(); - SpawnReagents(); - - return TimeSpan.FromSeconds(2.0); - } - case 4: - { - Effects.PlaySound(Location, Map, 0x12D); - - SpawnReagents(); - SpawnReagents(); - - return TimeSpan.FromSeconds(2.0); - } - case 5: - { - Effects.PlaySound(Location, Map, 0x12D); - - SpawnReagents(); - SpawnReagents(); - - return TimeSpan.FromSeconds(3.0); - } - default: - { - Effects.PlaySound(Location, Map, 0x12D); - - SpawnReagents(); - SpawnReagents(); - - return TimeSpan.Zero; - } - } - } - - private void SpawnReagents() - { - Item reagents; - int amount = Utility.RandomMinMax(10, 25); - - reagents = Utility.Random(9) switch - { - 0 => (Item)new BlackPearl(amount), - 1 => new Bloodmoss(amount), - 2 => new Garlic(amount), - 3 => new Ginseng(amount), - 4 => new MandrakeRoot(amount), - 5 => new Nightshade(amount), - 6 => new SulfurousAsh(amount), - 7 => new SpidersSilk(amount), - _ => new FertileDirt(amount) - }; - - if (!SpawnItem(reagents)) - reagents.Delete(); - } - } - - public class FurrowsGreenThornsEffect : GreenThornsEffect - { - public FurrowsGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from) - { - } - - protected override TimeSpan Play(int step) - { - switch (step) - { - case 0: - { - Effects.PlaySound(Location, Map, 0x106); - Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x3735, 1, - 182, 0xBE3); - - return TimeSpan.FromSeconds(4.0); - } - case 1: - { - EffectItem hole = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(10.0)); - hole.ItemID = 0x913; - - Effects.PlaySound(Location, Map, 0x222); - - return TimeSpan.FromSeconds(4.0); - } - case 2: - { - Effects.PlaySound(Location, Map, 0x21F); - - return TimeSpan.FromSeconds(4.0); - } - default: - { - EffectItem dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0)); - dummy.PublicOverheadMessage(MessageType.Regular, 0x3B2, true, - "* A magical bunny leaps out of its hole, disturbed by the thorn's effect! *"); - - BaseCreature spawn = new VorpalBunny(); - if (!SpawnCreature(spawn)) - spawn.Delete(); - - return TimeSpan.Zero; - } - } - } - } - - public class SwampGreenThornsEffect : GreenThornsEffect - { - public SwampGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from) - { - } - - protected override TimeSpan Play(int step) - { - switch (step) - { - case 0: - { - Effects.PlaySound(Location, Map, 0x106); - Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x3735, 1, - 182, 0xBE3); - - return TimeSpan.FromSeconds(4.0); - } - case 1: - { - Effects.PlaySound(Location, Map, 0x222); - - return TimeSpan.FromSeconds(4.0); - } - case 2: - { - Effects.PlaySound(Location, Map, 0x21F); - - return TimeSpan.FromSeconds(1.0); - } - default: - { - EffectItem dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0)); - dummy.PublicOverheadMessage(MessageType.Regular, 0x3B2, true, - "* Strange green tendrils rise from the ground, whipping wildly! *"); - Effects.PlaySound(Location, Map, 0x2B0); - - BaseCreature spawn = new WhippingVine(); - if (!SpawnCreature(spawn)) - spawn.Delete(); - - return TimeSpan.Zero; - } - } - } - } - - public class SnowGreenThornsEffect : GreenThornsEffect - { - public SnowGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from) - { - } - - protected override TimeSpan Play(int step) - { - switch (step) - { - case 0: - { - Effects.PlaySound(Location, Map, 0x106); - Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x3735, 1, - 182, 0xBE3); - - return TimeSpan.FromSeconds(4.0); - } - case 1: - { - Effects.PlaySound(Location, Map, 0x222); - - return TimeSpan.FromSeconds(4.0); - } - case 2: - { - Effects.PlaySound(Location, Map, 0x21F); - - return TimeSpan.FromSeconds(4.0); - } - default: - { - EffectItem dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0)); - dummy.PublicOverheadMessage(MessageType.Regular, 0x3B2, true, - "* Slithering ice serpents rise to the surface to investigate the disturbance! *"); - - BaseCreature spawn = new GiantIceWorm(); - if (!SpawnCreature(spawn)) - spawn.Delete(); - - for (int i = 0; i < 3; i++) - { - BaseCreature snake = new IceSnake(); - if (!SpawnCreature(snake)) - snake.Delete(); - } - - return TimeSpan.Zero; - } - } - } - } - - public class SandGreenThornsEffect : GreenThornsEffect - { - public SandGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from) - { - } - - protected override TimeSpan Play(int step) - { - switch (step) - { - case 0: - { - Effects.PlaySound(Location, Map, 0x106); - Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x3735, 1, - 182, 0xBE3); - - return TimeSpan.FromSeconds(4.0); - } - case 1: - { - Effects.PlaySound(Location, Map, 0x222); - - return TimeSpan.FromSeconds(4.0); - } - case 2: - { - Effects.PlaySound(Location, Map, 0x21F); - - return TimeSpan.FromSeconds(5.0); - } - default: - { - EffectItem dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0)); - dummy.PublicOverheadMessage(MessageType.Regular, 0x3B2, true, - "* The sand collapses, revealing a dark hole. *"); - - GreenThornsSHTeleporter.Create(Location, Map); - - return TimeSpan.Zero; - } - } - } - } - - public class GreenThornsSHTeleporter : Item - { - public static readonly Point3D Destination = new Point3D(5738, 1856, 0); - - private GreenThornsSHTeleporter() : base(0x913) - { - Movable = false; - Hue = 0x1; - } - - public GreenThornsSHTeleporter(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a hole"; - - public static void Create(Point3D location, Map map) - { - GreenThornsSHTeleporter tele = new GreenThornsSHTeleporter(); - - tele.MoveToWorld(location, map); - - new InternalTimer(tele).Start(); - } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(this, 3)) - { - BaseCreature.TeleportPets(from, Destination, Map); - - from.Location = Destination; - } - else - { - from.SendLocalizedMessage(1019045); // I can't reach that. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Delete(); - } - - private class InternalTimer : Timer - { - private readonly GreenThornsSHTeleporter m_Teleporter; - - public InternalTimer(GreenThornsSHTeleporter teleporter) : base(TimeSpan.FromMinutes(1.0)) - { - m_Teleporter = teleporter; - Priority = TimerPriority.FiveSeconds; - } - - protected override void OnTick() - { - m_Teleporter.Delete(); - } - } - } -} +using System; +using Server.Mobiles; +using Server.Network; +using Server.Targeting; +using Server.Utilities; + +namespace Server.Items +{ + public class GreenThorns : Item + { + [Constructible] + public GreenThorns(int amount = 1) : base(0xF42) + { + Stackable = true; + Weight = 1.0; + Hue = 0x42; + Amount = amount; + } + + public GreenThorns(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1060837; // green thorns + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. + return; + } + + if (!from.CanBeginAction()) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1061908 + ); // * You must wait a while before planting another thorn. * + return; + } + + from.Target = new InternalTarget(this); + from.SendLocalizedMessage(1061906); // Choose a spot to plant the thorn. + } + + 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(); + } + + private class InternalTarget : Target + { + private readonly GreenThorns m_Thorn; + + public InternalTarget(GreenThorns thorn) : base(3, true, TargetFlags.None) => m_Thorn = thorn; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Thorn.Deleted) + return; + + if (!m_Thorn.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. + return; + } + + if (!from.CanBeginAction()) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1061908 + ); // * You must wait a while before planting another thorn. * + return; + } + + if (from.Map != Map.Trammel && from.Map != Map.Felucca) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x2B2, + true, + "No solen lairs exist on this facet. Try again in Trammel or Felucca." + ); + return; + } + + if (!(targeted is LandTarget land)) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1061912 + ); // * You cannot plant a green thorn there! * + } + else + { + var effect = GreenThornsEffect.Create(from, land); + + if (effect == null) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1061913 + ); // * You sense it would be useless to plant a green thorn there. * + } + else + { + m_Thorn.Consume(); + + from.LocalOverheadMessage( + MessageType.Emote, + 0x961, + 1061914 + ); // * You push the strange green thorn into the ground * + from.NonlocalOverheadMessage( + MessageType.Emote, + 0x961, + 1061915, + from.Name + ); // * ~1_PLAYER_NAME~ pushes a strange green thorn into the ground. * + + from.BeginAction(); + new EndActionTimer(from).Start(); + + effect.Start(); + } + } + } + + protected override void OnTargetOutOfRange(Mobile from, object targeted) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502825); // That location is too far away + } + } + + private class EndActionTimer : Timer + { + private readonly Mobile m_From; + + public EndActionTimer(Mobile from) : base(TimeSpan.FromMinutes(3.0)) + { + m_From = from; + Priority = TimerPriority.FiveSeconds; + } + + protected override void OnTick() + { + m_From.EndAction(); + } + } + } + + public abstract class GreenThornsEffect : Timer + { + private static readonly TilesAndEffect[] m_Table = + { + new TilesAndEffect( + new[] + { + 0x71, 0x7C, + 0x82, 0xA7, + 0xDC, 0xE3, + 0xE8, 0xEB, + 0x141, 0x144, + 0x14C, 0x14F, + 0x169, 0x174, + 0x1DC, 0x1E7, + 0x1EC, 0x1EF, + 0x272, 0x275, + 0x27E, 0x281, + 0x2D0, 0x2D7, + 0x2E5, 0x2FF, + 0x303, 0x31F, + 0x32C, 0x32F, + 0x33D, 0x340, + 0x345, 0x34C, + 0x355, 0x358, + 0x367, 0x36E, + 0x377, 0x37A, + 0x38D, 0x390, + 0x395, 0x39C, + 0x3A5, 0x3A8, + 0x3F6, 0x405, + 0x547, 0x54E, + 0x553, 0x556, + 0x597, 0x59E, + 0x623, 0x63A, + 0x6F3, 0x6FA, + 0x777, 0x791, + 0x79A, 0x7A9, + 0x7AE, 0x7B1 + }, + typeof(DirtGreenThornsEffect) + ), + + new TilesAndEffect( + new[] + { + 0x9, 0x15, + 0x150, 0x15C + }, + typeof(FurrowsGreenThornsEffect) + ), + + new TilesAndEffect( + new[] + { + 0x9C4, 0x9EB, + 0x3D65, 0x3D65, + 0x3DC0, 0x3DD9, + 0x3DDB, 0x3DDC, + 0x3DDE, 0x3EF0, + 0x3FF6, 0x3FF6, + 0x3FFC, 0x3FFE + }, + typeof(SwampGreenThornsEffect) + ), + + new TilesAndEffect( + new[] + { + 0x10C, 0x10F, + 0x114, 0x117, + 0x119, 0x11D, + 0x179, 0x18A, + 0x385, 0x38C, + 0x391, 0x394, + 0x39D, 0x3A4, + 0x3A9, 0x3AC, + 0x5BF, 0x5D6, + 0x5DF, 0x5E2, + 0x745, 0x748, + 0x751, 0x758, + 0x75D, 0x760, + 0x76D, 0x773 + }, + typeof(SnowGreenThornsEffect) + ), + + new TilesAndEffect( + new[] + { + 0x16, 0x3A, + 0x44, 0x4B, + 0x11E, 0x121, + 0x126, 0x12D, + 0x192, 0x192, + 0x1A8, 0x1AB, + 0x1B9, 0x1D1, + 0x282, 0x285, + 0x28A, 0x291, + 0x335, 0x33C, + 0x341, 0x344, + 0x34D, 0x354, + 0x359, 0x35C, + 0x3B7, 0x3BE, + 0x3C7, 0x3CA, + 0x5A7, 0x5B2, + 0x64B, 0x652, + 0x657, 0x65A, + 0x663, 0x66A, + 0x66F, 0x672, + 0x7BD, 0x7D0 + }, + typeof(SandGreenThornsEffect) + ) + }; + + private int m_Step; + + public GreenThornsEffect(Point3D location, Map map, Mobile from) : base(TimeSpan.FromSeconds(2.5)) + { + Location = location; + Map = map; + From = from; + + Priority = TimerPriority.TwoFiftyMS; + } + + public Point3D Location { get; } + + public Map Map { get; } + + public Mobile From { get; } + + public static GreenThornsEffect Create(Mobile from, LandTarget land) + { + if (!from.Map.CanSpawnMobile(land.Location)) + return null; + + var tileID = land.TileID; + + foreach (var taep in m_Table) + { + var contains = false; + + for (var i = 0; !contains && i < taep.Tiles.Length; i += 2) + contains = tileID >= taep.Tiles[i] && tileID <= taep.Tiles[i + 1]; + + if (contains) + { + var effect = + (GreenThornsEffect)ActivatorUtil.CreateInstance(taep.Effect, land.Location, from.Map, from); + return effect; + } + } + + return null; + } + + protected override void OnTick() + { + var nextDelay = Play(m_Step++); + + if (nextDelay > TimeSpan.Zero) + { + Delay = nextDelay; + + Start(); + } + } + + protected abstract TimeSpan Play(int step); + + protected bool SpawnItem(Item item) + { + for (var i = 0; i < 5; i++) // Try 5 times + { + var x = Location.X + Utility.RandomMinMax(-1, 1); + var y = Location.Y + Utility.RandomMinMax(-1, 1); + var z = Map.GetAverageZ(x, y); + + if (Map.CanFit(x, y, Location.Z, 1)) + { + item.MoveToWorld(new Point3D(x, y, Location.Z), Map); + return true; + } + + if (Map.CanFit(x, y, z, 1)) + { + item.MoveToWorld(new Point3D(x, y, z), Map); + return true; + } + } + + return false; + } + + protected bool SpawnCreature(BaseCreature creature) + { + for (var i = 0; i < 5; i++) // Try 5 times + { + var x = Location.X + Utility.RandomMinMax(-1, 1); + var y = Location.Y + Utility.RandomMinMax(-1, 1); + var z = Map.GetAverageZ(x, y); + + if (Map.CanSpawnMobile(x, y, Location.Z)) + { + creature.MoveToWorld(new Point3D(x, y, Location.Z), Map); + creature.Combatant = From; + return true; + } + + if (Map.CanSpawnMobile(x, y, z)) + { + creature.MoveToWorld(new Point3D(x, y, z), Map); + creature.Combatant = From; + return true; + } + } + + return false; + } + + private class TilesAndEffect + { + public TilesAndEffect(int[] tiles, Type effect) + { + Tiles = tiles; + Effect = effect; + } + + public int[] Tiles { get; } + + public Type Effect { get; } + } + } + + public class DirtGreenThornsEffect : GreenThornsEffect + { + public DirtGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from) + { + } + + protected override TimeSpan Play(int step) + { + switch (step) + { + case 0: + { + Effects.PlaySound(Location, Map, 0x106); + Effects.SendLocationParticles( + EffectItem.Create(Location, Map, EffectItem.DefaultDuration), + 0x3735, + 1, + 182, + 0xBE3 + ); + + return TimeSpan.FromSeconds(4.0); + } + case 1: + { + Effects.PlaySound(Location, Map, 0x222); + + return TimeSpan.FromSeconds(4.0); + } + case 2: + { + Effects.PlaySound(Location, Map, 0x21F); + + return TimeSpan.FromSeconds(5.0); + } + case 3: + { + var dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0)); + dummy.PublicOverheadMessage( + MessageType.Regular, + 0x3B2, + true, + "* The ground erupts with chaotic growth! *" + ); + + Effects.PlaySound(Location, Map, 0x12D); + + SpawnReagents(); + SpawnReagents(); + + return TimeSpan.FromSeconds(2.0); + } + case 4: + { + Effects.PlaySound(Location, Map, 0x12D); + + SpawnReagents(); + SpawnReagents(); + + return TimeSpan.FromSeconds(2.0); + } + case 5: + { + Effects.PlaySound(Location, Map, 0x12D); + + SpawnReagents(); + SpawnReagents(); + + return TimeSpan.FromSeconds(3.0); + } + default: + { + Effects.PlaySound(Location, Map, 0x12D); + + SpawnReagents(); + SpawnReagents(); + + return TimeSpan.Zero; + } + } + } + + private void SpawnReagents() + { + Item reagents; + var amount = Utility.RandomMinMax(10, 25); + + reagents = Utility.Random(9) switch + { + 0 => new BlackPearl(amount), + 1 => new Bloodmoss(amount), + 2 => new Garlic(amount), + 3 => new Ginseng(amount), + 4 => new MandrakeRoot(amount), + 5 => new Nightshade(amount), + 6 => new SulfurousAsh(amount), + 7 => new SpidersSilk(amount), + _ => new FertileDirt(amount) + }; + + if (!SpawnItem(reagents)) + reagents.Delete(); + } + } + + public class FurrowsGreenThornsEffect : GreenThornsEffect + { + public FurrowsGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from) + { + } + + protected override TimeSpan Play(int step) + { + switch (step) + { + case 0: + { + Effects.PlaySound(Location, Map, 0x106); + Effects.SendLocationParticles( + EffectItem.Create(Location, Map, EffectItem.DefaultDuration), + 0x3735, + 1, + 182, + 0xBE3 + ); + + return TimeSpan.FromSeconds(4.0); + } + case 1: + { + var hole = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(10.0)); + hole.ItemID = 0x913; + + Effects.PlaySound(Location, Map, 0x222); + + return TimeSpan.FromSeconds(4.0); + } + case 2: + { + Effects.PlaySound(Location, Map, 0x21F); + + return TimeSpan.FromSeconds(4.0); + } + default: + { + var dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0)); + dummy.PublicOverheadMessage( + MessageType.Regular, + 0x3B2, + true, + "* A magical bunny leaps out of its hole, disturbed by the thorn's effect! *" + ); + + BaseCreature spawn = new VorpalBunny(); + if (!SpawnCreature(spawn)) + spawn.Delete(); + + return TimeSpan.Zero; + } + } + } + } + + public class SwampGreenThornsEffect : GreenThornsEffect + { + public SwampGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from) + { + } + + protected override TimeSpan Play(int step) + { + switch (step) + { + case 0: + { + Effects.PlaySound(Location, Map, 0x106); + Effects.SendLocationParticles( + EffectItem.Create(Location, Map, EffectItem.DefaultDuration), + 0x3735, + 1, + 182, + 0xBE3 + ); + + return TimeSpan.FromSeconds(4.0); + } + case 1: + { + Effects.PlaySound(Location, Map, 0x222); + + return TimeSpan.FromSeconds(4.0); + } + case 2: + { + Effects.PlaySound(Location, Map, 0x21F); + + return TimeSpan.FromSeconds(1.0); + } + default: + { + var dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0)); + dummy.PublicOverheadMessage( + MessageType.Regular, + 0x3B2, + true, + "* Strange green tendrils rise from the ground, whipping wildly! *" + ); + Effects.PlaySound(Location, Map, 0x2B0); + + BaseCreature spawn = new WhippingVine(); + if (!SpawnCreature(spawn)) + spawn.Delete(); + + return TimeSpan.Zero; + } + } + } + } + + public class SnowGreenThornsEffect : GreenThornsEffect + { + public SnowGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from) + { + } + + protected override TimeSpan Play(int step) + { + switch (step) + { + case 0: + { + Effects.PlaySound(Location, Map, 0x106); + Effects.SendLocationParticles( + EffectItem.Create(Location, Map, EffectItem.DefaultDuration), + 0x3735, + 1, + 182, + 0xBE3 + ); + + return TimeSpan.FromSeconds(4.0); + } + case 1: + { + Effects.PlaySound(Location, Map, 0x222); + + return TimeSpan.FromSeconds(4.0); + } + case 2: + { + Effects.PlaySound(Location, Map, 0x21F); + + return TimeSpan.FromSeconds(4.0); + } + default: + { + var dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0)); + dummy.PublicOverheadMessage( + MessageType.Regular, + 0x3B2, + true, + "* Slithering ice serpents rise to the surface to investigate the disturbance! *" + ); + + BaseCreature spawn = new GiantIceWorm(); + if (!SpawnCreature(spawn)) + spawn.Delete(); + + for (var i = 0; i < 3; i++) + { + BaseCreature snake = new IceSnake(); + if (!SpawnCreature(snake)) + snake.Delete(); + } + + return TimeSpan.Zero; + } + } + } + } + + public class SandGreenThornsEffect : GreenThornsEffect + { + public SandGreenThornsEffect(Point3D location, Map map, Mobile from) : base(location, map, from) + { + } + + protected override TimeSpan Play(int step) + { + switch (step) + { + case 0: + { + Effects.PlaySound(Location, Map, 0x106); + Effects.SendLocationParticles( + EffectItem.Create(Location, Map, EffectItem.DefaultDuration), + 0x3735, + 1, + 182, + 0xBE3 + ); + + return TimeSpan.FromSeconds(4.0); + } + case 1: + { + Effects.PlaySound(Location, Map, 0x222); + + return TimeSpan.FromSeconds(4.0); + } + case 2: + { + Effects.PlaySound(Location, Map, 0x21F); + + return TimeSpan.FromSeconds(5.0); + } + default: + { + var dummy = EffectItem.Create(Location, Map, TimeSpan.FromSeconds(20.0)); + dummy.PublicOverheadMessage( + MessageType.Regular, + 0x3B2, + true, + "* The sand collapses, revealing a dark hole. *" + ); + + GreenThornsSHTeleporter.Create(Location, Map); + + return TimeSpan.Zero; + } + } + } + } + + public class GreenThornsSHTeleporter : Item + { + public static readonly Point3D Destination = new Point3D(5738, 1856, 0); + + private GreenThornsSHTeleporter() : base(0x913) + { + Movable = false; + Hue = 0x1; + } + + public GreenThornsSHTeleporter(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a hole"; + + public static void Create(Point3D location, Map map) + { + var tele = new GreenThornsSHTeleporter(); + + tele.MoveToWorld(location, map); + + new InternalTimer(tele).Start(); + } + + public override void OnDoubleClick(Mobile from) + { + if (from.InRange(this, 3)) + { + BaseCreature.TeleportPets(from, Destination, Map); + + from.Location = Destination; + } + else + { + from.SendLocalizedMessage(1019045); // I can't reach that. + } + } + + 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(); + + Delete(); + } + + private class InternalTimer : Timer + { + private readonly GreenThornsSHTeleporter m_Teleporter; + + public InternalTimer(GreenThornsSHTeleporter teleporter) : base(TimeSpan.FromMinutes(1.0)) + { + m_Teleporter = teleporter; + Priority = TimerPriority.FiveSeconds; + } + + protected override void OnTick() + { + m_Teleporter.Delete(); + } + } + } +} diff --git a/Projects/UOContent/Engines/Plants/MiscItems/OrangePetals.cs b/Projects/UOContent/Engines/Plants/MiscItems/OrangePetals.cs index 3ae595cf1..12b4e062d 100644 --- a/Projects/UOContent/Engines/Plants/MiscItems/OrangePetals.cs +++ b/Projects/UOContent/Engines/Plants/MiscItems/OrangePetals.cs @@ -1,127 +1,132 @@ -using System; -using System.Collections.Generic; -using Server.Network; - -namespace Server.Items -{ - public class OrangePetals : Item - { - private static readonly Dictionary m_Table = new Dictionary(); - - [Constructible] - public OrangePetals(int amount = 1) : base(0x1021) - { - Stackable = true; - Hue = 0x2B; - Amount = amount; - } - - public OrangePetals(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1053122; // orange petals - - public override double DefaultWeight => 0.1; - - public override bool CheckItemUse(Mobile from, Item item) - { - if (item != this) - return base.CheckItemUse(from, item); - - if (from != RootParent) - { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. - return false; - } - - return base.CheckItemUse(from, item); - } - - public override void OnDoubleClick(Mobile from) - { - OrangePetalsContext context = GetContext(from); - - if (context != null) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061904); - return; - } - - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061905); - from.PlaySound(0x3B); - - Timer timer = new OrangePetalsTimer(from); - timer.Start(); - - AddContext(from, new OrangePetalsContext(timer)); - - Consume(); - } - - private static void AddContext(Mobile m, OrangePetalsContext context) - { - m_Table[m] = context; - } - - public static void RemoveContext(Mobile m) - { - OrangePetalsContext context = GetContext(m); - - if (context != null) - RemoveContext(m, context); - } - - private static void RemoveContext(Mobile m, OrangePetalsContext context) - { - m_Table.Remove(m); - - context.Timer.Stop(); - } - - private static OrangePetalsContext GetContext(Mobile m) - { - m_Table.TryGetValue(m, out OrangePetalsContext context); - return context; - } - - public static bool UnderEffect(Mobile m) => m_Table.ContainsKey(m); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private class OrangePetalsTimer : Timer - { - private readonly Mobile m_Mobile; - - public OrangePetalsTimer(Mobile from) : base(TimeSpan.FromMinutes(5.0)) => m_Mobile = from; - - protected override void OnTick() - { - if (!m_Mobile.Deleted) - m_Mobile.LocalOverheadMessage(MessageType.Regular, 0x3F, true, - "* You feel the effects of your poison resistance wearing off *"); - - RemoveContext(m_Mobile); - } - } - - private class OrangePetalsContext - { - public OrangePetalsContext(Timer timer) => Timer = timer; - - public Timer Timer { get; } - } - } -} +using System; +using System.Collections.Generic; +using Server.Network; + +namespace Server.Items +{ + public class OrangePetals : Item + { + private static readonly Dictionary m_Table = + new Dictionary(); + + [Constructible] + public OrangePetals(int amount = 1) : base(0x1021) + { + Stackable = true; + Hue = 0x2B; + Amount = amount; + } + + public OrangePetals(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1053122; // orange petals + + public override double DefaultWeight => 0.1; + + public override bool CheckItemUse(Mobile from, Item item) + { + if (item != this) + return base.CheckItemUse(from, item); + + if (from != RootParent) + { + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. + return false; + } + + return base.CheckItemUse(from, item); + } + + public override void OnDoubleClick(Mobile from) + { + var context = GetContext(from); + + if (context != null) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061904); + return; + } + + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061905); + from.PlaySound(0x3B); + + Timer timer = new OrangePetalsTimer(from); + timer.Start(); + + AddContext(from, new OrangePetalsContext(timer)); + + Consume(); + } + + private static void AddContext(Mobile m, OrangePetalsContext context) + { + m_Table[m] = context; + } + + public static void RemoveContext(Mobile m) + { + var context = GetContext(m); + + if (context != null) + RemoveContext(m, context); + } + + private static void RemoveContext(Mobile m, OrangePetalsContext context) + { + m_Table.Remove(m); + + context.Timer.Stop(); + } + + private static OrangePetalsContext GetContext(Mobile m) + { + m_Table.TryGetValue(m, out var context); + return context; + } + + public static bool UnderEffect(Mobile m) => m_Table.ContainsKey(m); + + 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(); + } + + private class OrangePetalsTimer : Timer + { + private readonly Mobile m_Mobile; + + public OrangePetalsTimer(Mobile from) : base(TimeSpan.FromMinutes(5.0)) => m_Mobile = from; + + protected override void OnTick() + { + if (!m_Mobile.Deleted) + m_Mobile.LocalOverheadMessage( + MessageType.Regular, + 0x3F, + true, + "* You feel the effects of your poison resistance wearing off *" + ); + + RemoveContext(m_Mobile); + } + } + + private class OrangePetalsContext + { + public OrangePetalsContext(Timer timer) => Timer = timer; + + public Timer Timer { get; } + } + } +} diff --git a/Projects/UOContent/Engines/Plants/MiscItems/RedLeaves.cs b/Projects/UOContent/Engines/Plants/MiscItems/RedLeaves.cs index 4acffc221..a94acceab 100644 --- a/Projects/UOContent/Engines/Plants/MiscItems/RedLeaves.cs +++ b/Projects/UOContent/Engines/Plants/MiscItems/RedLeaves.cs @@ -1,93 +1,93 @@ -using Server.Targeting; - -namespace Server.Items -{ - public class RedLeaves : Item - { - [Constructible] - public RedLeaves(int amount = 1) : base(0x1E85) - { - Stackable = true; - Hue = 0x21; - Amount = amount; - } - - public RedLeaves(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1053123; // red leaves - - public override double DefaultWeight => 0.1; - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - return; - } - - from.Target = new InternalTarget(this); - from.SendLocalizedMessage(1061907); // Choose a book you wish to seal with the wax from the red leaf. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private class InternalTarget : Target - { - private readonly RedLeaves m_RedLeaves; - - public InternalTarget(RedLeaves redLeaves) : base(3, false, TargetFlags.None) => m_RedLeaves = redLeaves; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_RedLeaves.Deleted) - return; - - if (!m_RedLeaves.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - return; - } - - if (!(targeted is Item item) || !item.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - } - else if (!(item is BaseBook)) - { - item.LabelTo(from, 1061911); // You can only use red leaves to seal the ink into book pages! - } - else - { - BaseBook book = (BaseBook)item; - - if (!book.Writable) - { - book.LabelTo(from, 1061909); // The ink in this book has already been sealed. - } - else - { - m_RedLeaves.Consume(); - book.Writable = false; - - book.LabelTo(from, 1061910); // You seal the ink to the page using wax from the red leaf. - } - } - } - } - } -} +using Server.Targeting; + +namespace Server.Items +{ + public class RedLeaves : Item + { + [Constructible] + public RedLeaves(int amount = 1) : base(0x1E85) + { + Stackable = true; + Hue = 0x21; + Amount = amount; + } + + public RedLeaves(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1053123; // red leaves + + public override double DefaultWeight => 0.1; + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. + return; + } + + from.Target = new InternalTarget(this); + from.SendLocalizedMessage(1061907); // Choose a book you wish to seal with the wax from the red leaf. + } + + 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(); + } + + private class InternalTarget : Target + { + private readonly RedLeaves m_RedLeaves; + + public InternalTarget(RedLeaves redLeaves) : base(3, false, TargetFlags.None) => m_RedLeaves = redLeaves; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_RedLeaves.Deleted) + return; + + if (!m_RedLeaves.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. + return; + } + + if (!(targeted is Item item) || !item.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. + } + else if (!(item is BaseBook)) + { + item.LabelTo(from, 1061911); // You can only use red leaves to seal the ink into book pages! + } + else + { + var book = (BaseBook)item; + + if (!book.Writable) + { + book.LabelTo(from, 1061909); // The ink in this book has already been sealed. + } + else + { + m_RedLeaves.Consume(); + book.Writable = false; + + book.LabelTo(from, 1061910); // You seal the ink to the page using wax from the red leaf. + } + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Plants/MiscMobiles/GiantIceWorm.cs b/Projects/UOContent/Engines/Plants/MiscMobiles/GiantIceWorm.cs index bf723c367..a882b772a 100644 --- a/Projects/UOContent/Engines/Plants/MiscMobiles/GiantIceWorm.cs +++ b/Projects/UOContent/Engines/Plants/MiscMobiles/GiantIceWorm.cs @@ -1,71 +1,71 @@ -namespace Server.Mobiles -{ - public class GiantIceWorm : BaseCreature - { - [Constructible] - public GiantIceWorm() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) - { - Body = 89; - BaseSoundID = 0xDC; - - SetStr(216, 245); - SetDex(76, 100); - SetInt(66, 85); - - SetHits(130, 147); - - SetDamage(7, 17); - - SetDamageType(ResistanceType.Physical, 10); - SetDamageType(ResistanceType.Cold, 90); - - SetResistance(ResistanceType.Physical, 30, 35); - SetResistance(ResistanceType.Fire, 0); - SetResistance(ResistanceType.Cold, 80, 90); - SetResistance(ResistanceType.Poison, 15, 25); - SetResistance(ResistanceType.Energy, 10, 20); - - SetSkill(SkillName.Poisoning, 75.1, 95.0); - SetSkill(SkillName.MagicResist, 45.1, 60.0); - SetSkill(SkillName.Tactics, 75.1, 80.0); - SetSkill(SkillName.Wrestling, 60.1, 80.0); - - Fame = 4500; - Karma = -4500; - - VirtualArmor = 40; - - Tamable = true; - ControlSlots = 1; - MinTameSkill = 71.1; - } - - public GiantIceWorm(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a giant ice worm corpse"; - public override bool SubdueBeforeTame => true; - public override string DefaultName => "a giant ice worm"; - - public override Poison PoisonImmune => Poison.Greater; - - public override Poison HitPoison => Poison.Greater; - - public override FoodType FavoriteFood => FoodType.Meat; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Mobiles +{ + public class GiantIceWorm : BaseCreature + { + [Constructible] + public GiantIceWorm() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 89; + BaseSoundID = 0xDC; + + SetStr(216, 245); + SetDex(76, 100); + SetInt(66, 85); + + SetHits(130, 147); + + SetDamage(7, 17); + + SetDamageType(ResistanceType.Physical, 10); + SetDamageType(ResistanceType.Cold, 90); + + SetResistance(ResistanceType.Physical, 30, 35); + SetResistance(ResistanceType.Fire, 0); + SetResistance(ResistanceType.Cold, 80, 90); + SetResistance(ResistanceType.Poison, 15, 25); + SetResistance(ResistanceType.Energy, 10, 20); + + SetSkill(SkillName.Poisoning, 75.1, 95.0); + SetSkill(SkillName.MagicResist, 45.1, 60.0); + SetSkill(SkillName.Tactics, 75.1, 80.0); + SetSkill(SkillName.Wrestling, 60.1, 80.0); + + Fame = 4500; + Karma = -4500; + + VirtualArmor = 40; + + Tamable = true; + ControlSlots = 1; + MinTameSkill = 71.1; + } + + public GiantIceWorm(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a giant ice worm corpse"; + public override bool SubdueBeforeTame => true; + public override string DefaultName => "a giant ice worm"; + + public override Poison PoisonImmune => Poison.Greater; + + public override Poison HitPoison => Poison.Greater; + + public override FoodType FavoriteFood => FoodType.Meat; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Plants/Network/DisplayHelpTopic.cs b/Projects/UOContent/Engines/Plants/Network/DisplayHelpTopic.cs index 9a7f0060a..0e571838c 100644 --- a/Projects/UOContent/Engines/Plants/Network/DisplayHelpTopic.cs +++ b/Projects/UOContent/Engines/Plants/Network/DisplayHelpTopic.cs @@ -1,15 +1,15 @@ -namespace Server.Network -{ - public class DisplayHelpTopic : Packet - { - public DisplayHelpTopic(int topicID, bool display) : base(0xBF) - { - EnsureCapacity(11); - - Stream.Write((short)0x17); - Stream.Write((byte)1); - Stream.Write(topicID); - Stream.Write(display); - } - } -} \ No newline at end of file +namespace Server.Network +{ + public class DisplayHelpTopic : Packet + { + public DisplayHelpTopic(int topicID, bool display) : base(0xBF) + { + EnsureCapacity(11); + + Stream.Write((short)0x17); + Stream.Write((byte)1); + Stream.Write(topicID); + Stream.Write(display); + } + } +} diff --git a/Projects/UOContent/Engines/Plants/PlantBowl.cs b/Projects/UOContent/Engines/Plants/PlantBowl.cs index c19a52563..cab30cd32 100644 --- a/Projects/UOContent/Engines/Plants/PlantBowl.cs +++ b/Projects/UOContent/Engines/Plants/PlantBowl.cs @@ -1,188 +1,203 @@ -using Server.Items; -using Server.Network; -using Server.Targeting; - -namespace Server.Engines.Plants -{ - public class PlantBowl : Item - { - private static readonly int[] m_DirtPatchTiles = - { - 0x9, 0x15, - 0x71, 0x7C, - 0x82, 0xA7, - 0xDC, 0xE3, - 0xE8, 0xEB, - 0x141, 0x144, - 0x14C, 0x15C, - 0x169, 0x174, - 0x1DC, 0x1EF, - 0x272, 0x275, - 0x27E, 0x281, - 0x2D0, 0x2D7, - 0x2E5, 0x2FF, - 0x303, 0x31F, - 0x32C, 0x32F, - 0x33D, 0x340, - 0x345, 0x34C, - 0x355, 0x358, - 0x367, 0x36E, - 0x377, 0x37A, - 0x38D, 0x390, - 0x395, 0x39C, - 0x3A5, 0x3A8, - 0x3F6, 0x405, - 0x547, 0x54E, - 0x553, 0x556, - 0x597, 0x59E, - 0x623, 0x63A, - 0x6F3, 0x6FA, - 0x777, 0x791, - 0x79A, 0x7A9, - 0x7AE, 0x7B1, - 0x98C, 0x99F, - 0x9AC, 0x9BF, - 0x5B27, 0x5B3E, - 0x71F4, 0x71FB, - 0x72C9, 0x72CA - }; - - [Constructible] - public PlantBowl() : base(0x15FD) => Weight = 1.0; - - public PlantBowl(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1060834; // a plant bowl - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - return; - } - - from.Target = new InternalTarget(this); - from.SendLocalizedMessage(1061897); // Choose a patch of dirt to scoop up. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public static bool IsDirtPatch(object obj) - { - int tileID; - - if (obj is Static staticObj && !staticObj.Movable) - tileID = staticObj.ItemID & 0x3FFF | 0x4000; - else if (obj is StaticTarget staticTarget) - tileID = staticTarget.ItemID & 0x3FFF | 0x4000; - else if (obj is LandTarget landTarget) - tileID = landTarget.TileID; - else - return false; - - bool contains = false; - - for (int i = 0; !contains && i < m_DirtPatchTiles.Length; i += 2) - contains = tileID >= m_DirtPatchTiles[i] && tileID <= m_DirtPatchTiles[i + 1]; - - return contains; - } - - private class InternalTarget : Target - { - private readonly PlantBowl m_PlantBowl; - - public InternalTarget(PlantBowl plantBowl) : base(3, true, TargetFlags.None) => m_PlantBowl = plantBowl; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_PlantBowl.Deleted) - return; - - if (!m_PlantBowl.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - return; - } - - if (targeted is FertileDirt dirt) - { - int _dirtNeeded = Core.ML ? 20 : 40; - - if (!dirt.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - } - else if (dirt.Amount < _dirtNeeded) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1061896); // You need more dirt to fill a plant bowl! - } - else - { - PlantItem fullBowl = new PlantItem(true); - - if (from.PlaceInBackpack(fullBowl)) - { - dirt.Consume(_dirtNeeded); - m_PlantBowl.Delete(); - - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1061895); // You fill the bowl with fresh dirt. - } - else - { - fullBowl.Delete(); - - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1061894); // There is no room in your backpack for a bowl full of dirt! - } - } - } - else if (IsDirtPatch(targeted)) - { - PlantItem fullBowl = new PlantItem(); - - if (from.PlaceInBackpack(fullBowl)) - { - m_PlantBowl.Delete(); - - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061895); // You fill the bowl with fresh dirt. - } - else - { - fullBowl.Delete(); - - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1061894); // There is no room in your backpack for a bowl full of dirt! - } - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1061893); // You'll want to gather fresh dirt in order to raise a healthy plant! - } - } - - protected override void OnTargetOutOfRange(Mobile from, object targeted) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502825); // That location is too far away - } - } - } -} \ No newline at end of file +using Server.Items; +using Server.Network; +using Server.Targeting; + +namespace Server.Engines.Plants +{ + public class PlantBowl : Item + { + private static readonly int[] m_DirtPatchTiles = + { + 0x9, 0x15, + 0x71, 0x7C, + 0x82, 0xA7, + 0xDC, 0xE3, + 0xE8, 0xEB, + 0x141, 0x144, + 0x14C, 0x15C, + 0x169, 0x174, + 0x1DC, 0x1EF, + 0x272, 0x275, + 0x27E, 0x281, + 0x2D0, 0x2D7, + 0x2E5, 0x2FF, + 0x303, 0x31F, + 0x32C, 0x32F, + 0x33D, 0x340, + 0x345, 0x34C, + 0x355, 0x358, + 0x367, 0x36E, + 0x377, 0x37A, + 0x38D, 0x390, + 0x395, 0x39C, + 0x3A5, 0x3A8, + 0x3F6, 0x405, + 0x547, 0x54E, + 0x553, 0x556, + 0x597, 0x59E, + 0x623, 0x63A, + 0x6F3, 0x6FA, + 0x777, 0x791, + 0x79A, 0x7A9, + 0x7AE, 0x7B1, + 0x98C, 0x99F, + 0x9AC, 0x9BF, + 0x5B27, 0x5B3E, + 0x71F4, 0x71FB, + 0x72C9, 0x72CA + }; + + [Constructible] + public PlantBowl() : base(0x15FD) => Weight = 1.0; + + public PlantBowl(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1060834; // a plant bowl + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. + return; + } + + from.Target = new InternalTarget(this); + from.SendLocalizedMessage(1061897); // Choose a patch of dirt to scoop up. + } + + 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 static bool IsDirtPatch(object obj) + { + int tileID; + + if (obj is Static staticObj && !staticObj.Movable) + tileID = (staticObj.ItemID & 0x3FFF) | 0x4000; + else if (obj is StaticTarget staticTarget) + tileID = (staticTarget.ItemID & 0x3FFF) | 0x4000; + else if (obj is LandTarget landTarget) + tileID = landTarget.TileID; + else + return false; + + var contains = false; + + for (var i = 0; !contains && i < m_DirtPatchTiles.Length; i += 2) + contains = tileID >= m_DirtPatchTiles[i] && tileID <= m_DirtPatchTiles[i + 1]; + + return contains; + } + + private class InternalTarget : Target + { + private readonly PlantBowl m_PlantBowl; + + public InternalTarget(PlantBowl plantBowl) : base(3, true, TargetFlags.None) => m_PlantBowl = plantBowl; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_PlantBowl.Deleted) + return; + + if (!m_PlantBowl.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. + return; + } + + if (targeted is FertileDirt dirt) + { + var _dirtNeeded = Core.ML ? 20 : 40; + + if (!dirt.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. + } + else if (dirt.Amount < _dirtNeeded) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1061896 + ); // You need more dirt to fill a plant bowl! + } + else + { + var fullBowl = new PlantItem(true); + + if (from.PlaceInBackpack(fullBowl)) + { + dirt.Consume(_dirtNeeded); + m_PlantBowl.Delete(); + + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1061895 + ); // You fill the bowl with fresh dirt. + } + else + { + fullBowl.Delete(); + + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1061894 + ); // There is no room in your backpack for a bowl full of dirt! + } + } + } + else if (IsDirtPatch(targeted)) + { + var fullBowl = new PlantItem(); + + if (from.PlaceInBackpack(fullBowl)) + { + m_PlantBowl.Delete(); + + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061895); // You fill the bowl with fresh dirt. + } + else + { + fullBowl.Delete(); + + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1061894 + ); // There is no room in your backpack for a bowl full of dirt! + } + } + else + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1061893 + ); // You'll want to gather fresh dirt in order to raise a healthy plant! + } + } + + protected override void OnTargetOutOfRange(Mobile from, object targeted) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502825); // That location is too far away + } + } + } +} diff --git a/Projects/UOContent/Engines/Plants/PlantHue.cs b/Projects/UOContent/Engines/Plants/PlantHue.cs index 384a157b5..4c28b50e8 100644 --- a/Projects/UOContent/Engines/Plants/PlantHue.cs +++ b/Projects/UOContent/Engines/Plants/PlantHue.cs @@ -1,151 +1,153 @@ -using System; -using System.Collections.Generic; - -namespace Server.Engines.Plants -{ - [Flags] - public enum PlantHue - { - Plain = 0x1 | Crossable | Reproduces, - - Red = 0x2 | Crossable | Reproduces, - Blue = 0x4 | Crossable | Reproduces, - Yellow = 0x8 | Crossable | Reproduces, - - BrightRed = Red | Bright, - BrightBlue = Blue | Bright, - BrightYellow = Yellow | Bright, - - Purple = Red | Blue, - Green = Blue | Yellow, - Orange = Red | Yellow, - - BrightPurple = Purple | Bright, - BrightGreen = Green | Bright, - BrightOrange = Orange | Bright, - - Black = 0x10, - White = 0x20, - Pink = 0x40, - Magenta = 0x80, - Aqua = 0x100, - FireRed = 0x200, - - None = 0, - Reproduces = 0x2000000, - Crossable = 0x4000000, - Bright = 0x8000000 - } - - public class PlantHueInfo - { - private static readonly Dictionary m_Table; - - static PlantHueInfo() => - m_Table = new Dictionary - { - [PlantHue.Plain] = new PlantHueInfo(0, 1060813, PlantHue.Plain, 0x835), - [PlantHue.Red] = new PlantHueInfo(0x66D, 1060814, PlantHue.Red, 0x24), - [PlantHue.Blue] = new PlantHueInfo(0x53D, 1060815, PlantHue.Blue, 0x6), - [PlantHue.Yellow] = new PlantHueInfo(0x8A5, 1060818, PlantHue.Yellow, 0x38), - [PlantHue.BrightRed] = new PlantHueInfo(0x21, 1060814, PlantHue.BrightRed, 0x21), - [PlantHue.BrightBlue] = new PlantHueInfo(0x5, 1060815, PlantHue.BrightBlue, 0x6), - [PlantHue.BrightYellow] = new PlantHueInfo(0x38, 1060818, PlantHue.BrightYellow, 0x35), - [PlantHue.Purple] = new PlantHueInfo(0xD, 1060816, PlantHue.Purple, 0x10), - [PlantHue.Green] = new PlantHueInfo(0x59B, 1060819, PlantHue.Green, 0x42), - [PlantHue.Orange] = new PlantHueInfo(0x46F, 1060817, PlantHue.Orange, 0x2E), - [PlantHue.BrightPurple] = new PlantHueInfo(0x10, 1060816, PlantHue.BrightPurple, 0xD), - [PlantHue.BrightGreen] = new PlantHueInfo(0x42, 1060819, PlantHue.BrightGreen, 0x3F), - [PlantHue.BrightOrange] = new PlantHueInfo(0x2B, 1060817, PlantHue.BrightOrange, 0x2B), - [PlantHue.Black] = new PlantHueInfo(0x455, 1060820, PlantHue.Black, 0), - [PlantHue.White] = new PlantHueInfo(0x481, 1060821, PlantHue.White, 0x481), - [PlantHue.Pink] = new PlantHueInfo(0x48E, 1061854, PlantHue.Pink), - [PlantHue.Magenta] = new PlantHueInfo(0x486, 1061852, PlantHue.Magenta), - [PlantHue.Aqua] = new PlantHueInfo(0x495, 1061853, PlantHue.Aqua), - [PlantHue.FireRed] = new PlantHueInfo(0x489, 1061855, PlantHue.FireRed) - }; - - private PlantHueInfo(int hue, int name, PlantHue plantHue) : this(hue, name, plantHue, hue) - { - } - - private PlantHueInfo(int hue, int name, PlantHue plantHue, int gumpHue) - { - Hue = hue; - Name = name; - PlantHue = plantHue; - GumpHue = gumpHue; - } - - public int Hue { get; } - - public int Name { get; } - - public PlantHue PlantHue { get; } - - public int GumpHue { get; } - - public static PlantHueInfo GetInfo(PlantHue plantHue) => m_Table.TryGetValue(plantHue, out PlantHueInfo info) ? info : m_Table[PlantHue.Plain]; - - public static PlantHue RandomFirstGeneration() - { - return Utility.Random(4) switch - { - 0 => PlantHue.Plain, - 1 => PlantHue.Red, - 2 => PlantHue.Blue, - _ => PlantHue.Yellow - }; - } - - public static bool CanReproduce(PlantHue plantHue) => (plantHue & PlantHue.Reproduces) != PlantHue.None; - - public static bool IsCrossable(PlantHue plantHue) => (plantHue & PlantHue.Crossable) != PlantHue.None; - - public static bool IsBright(PlantHue plantHue) => (plantHue & PlantHue.Bright) != PlantHue.None; - - public static PlantHue GetNotBright(PlantHue plantHue) => plantHue & ~PlantHue.Bright; - - public static bool IsPrimary(PlantHue plantHue) => plantHue == PlantHue.Red || plantHue == PlantHue.Blue || plantHue == PlantHue.Yellow; - - public static PlantHue Cross(PlantHue first, PlantHue second) - { - if (!IsCrossable(first) || !IsCrossable(second)) - return PlantHue.None; - - if (Utility.RandomDouble() < 0.01) - return Utility.RandomBool() ? PlantHue.Black : PlantHue.White; - - if (first == PlantHue.Plain || second == PlantHue.Plain) - return PlantHue.Plain; - - PlantHue notBrightFirst = GetNotBright(first); - PlantHue notBrightSecond = GetNotBright(second); - - if (notBrightFirst == notBrightSecond) - return first | PlantHue.Bright; - - bool firstPrimary = IsPrimary(notBrightFirst); - bool secondPrimary = IsPrimary(notBrightSecond); - - if (firstPrimary && secondPrimary) - return notBrightFirst | notBrightSecond; - - if (firstPrimary) - return notBrightFirst; - - if (secondPrimary) - return notBrightSecond; - - return notBrightFirst & notBrightSecond; - } - - public bool IsCrossable() => IsCrossable(PlantHue); - - public bool IsBright() => IsBright(PlantHue); - - public PlantHue GetNotBright() => GetNotBright(PlantHue); - - public bool IsPrimary() => IsPrimary(PlantHue); - } -} +using System; +using System.Collections.Generic; + +namespace Server.Engines.Plants +{ + [Flags] + public enum PlantHue + { + Plain = 0x1 | Crossable | Reproduces, + + Red = 0x2 | Crossable | Reproduces, + Blue = 0x4 | Crossable | Reproduces, + Yellow = 0x8 | Crossable | Reproduces, + + BrightRed = Red | Bright, + BrightBlue = Blue | Bright, + BrightYellow = Yellow | Bright, + + Purple = Red | Blue, + Green = Blue | Yellow, + Orange = Red | Yellow, + + BrightPurple = Purple | Bright, + BrightGreen = Green | Bright, + BrightOrange = Orange | Bright, + + Black = 0x10, + White = 0x20, + Pink = 0x40, + Magenta = 0x80, + Aqua = 0x100, + FireRed = 0x200, + + None = 0, + Reproduces = 0x2000000, + Crossable = 0x4000000, + Bright = 0x8000000 + } + + public class PlantHueInfo + { + private static readonly Dictionary m_Table; + + static PlantHueInfo() => + m_Table = new Dictionary + { + [PlantHue.Plain] = new PlantHueInfo(0, 1060813, PlantHue.Plain, 0x835), + [PlantHue.Red] = new PlantHueInfo(0x66D, 1060814, PlantHue.Red, 0x24), + [PlantHue.Blue] = new PlantHueInfo(0x53D, 1060815, PlantHue.Blue, 0x6), + [PlantHue.Yellow] = new PlantHueInfo(0x8A5, 1060818, PlantHue.Yellow, 0x38), + [PlantHue.BrightRed] = new PlantHueInfo(0x21, 1060814, PlantHue.BrightRed, 0x21), + [PlantHue.BrightBlue] = new PlantHueInfo(0x5, 1060815, PlantHue.BrightBlue, 0x6), + [PlantHue.BrightYellow] = new PlantHueInfo(0x38, 1060818, PlantHue.BrightYellow, 0x35), + [PlantHue.Purple] = new PlantHueInfo(0xD, 1060816, PlantHue.Purple, 0x10), + [PlantHue.Green] = new PlantHueInfo(0x59B, 1060819, PlantHue.Green, 0x42), + [PlantHue.Orange] = new PlantHueInfo(0x46F, 1060817, PlantHue.Orange, 0x2E), + [PlantHue.BrightPurple] = new PlantHueInfo(0x10, 1060816, PlantHue.BrightPurple, 0xD), + [PlantHue.BrightGreen] = new PlantHueInfo(0x42, 1060819, PlantHue.BrightGreen, 0x3F), + [PlantHue.BrightOrange] = new PlantHueInfo(0x2B, 1060817, PlantHue.BrightOrange, 0x2B), + [PlantHue.Black] = new PlantHueInfo(0x455, 1060820, PlantHue.Black, 0), + [PlantHue.White] = new PlantHueInfo(0x481, 1060821, PlantHue.White, 0x481), + [PlantHue.Pink] = new PlantHueInfo(0x48E, 1061854, PlantHue.Pink), + [PlantHue.Magenta] = new PlantHueInfo(0x486, 1061852, PlantHue.Magenta), + [PlantHue.Aqua] = new PlantHueInfo(0x495, 1061853, PlantHue.Aqua), + [PlantHue.FireRed] = new PlantHueInfo(0x489, 1061855, PlantHue.FireRed) + }; + + private PlantHueInfo(int hue, int name, PlantHue plantHue) : this(hue, name, plantHue, hue) + { + } + + private PlantHueInfo(int hue, int name, PlantHue plantHue, int gumpHue) + { + Hue = hue; + Name = name; + PlantHue = plantHue; + GumpHue = gumpHue; + } + + public int Hue { get; } + + public int Name { get; } + + public PlantHue PlantHue { get; } + + public int GumpHue { get; } + + public static PlantHueInfo GetInfo(PlantHue plantHue) => + m_Table.TryGetValue(plantHue, out var info) ? info : m_Table[PlantHue.Plain]; + + public static PlantHue RandomFirstGeneration() + { + return Utility.Random(4) switch + { + 0 => PlantHue.Plain, + 1 => PlantHue.Red, + 2 => PlantHue.Blue, + _ => PlantHue.Yellow + }; + } + + public static bool CanReproduce(PlantHue plantHue) => (plantHue & PlantHue.Reproduces) != PlantHue.None; + + public static bool IsCrossable(PlantHue plantHue) => (plantHue & PlantHue.Crossable) != PlantHue.None; + + public static bool IsBright(PlantHue plantHue) => (plantHue & PlantHue.Bright) != PlantHue.None; + + public static PlantHue GetNotBright(PlantHue plantHue) => plantHue & ~PlantHue.Bright; + + public static bool IsPrimary(PlantHue plantHue) => + plantHue == PlantHue.Red || plantHue == PlantHue.Blue || plantHue == PlantHue.Yellow; + + public static PlantHue Cross(PlantHue first, PlantHue second) + { + if (!IsCrossable(first) || !IsCrossable(second)) + return PlantHue.None; + + if (Utility.RandomDouble() < 0.01) + return Utility.RandomBool() ? PlantHue.Black : PlantHue.White; + + if (first == PlantHue.Plain || second == PlantHue.Plain) + return PlantHue.Plain; + + var notBrightFirst = GetNotBright(first); + var notBrightSecond = GetNotBright(second); + + if (notBrightFirst == notBrightSecond) + return first | PlantHue.Bright; + + var firstPrimary = IsPrimary(notBrightFirst); + var secondPrimary = IsPrimary(notBrightSecond); + + if (firstPrimary && secondPrimary) + return notBrightFirst | notBrightSecond; + + if (firstPrimary) + return notBrightFirst; + + if (secondPrimary) + return notBrightSecond; + + return notBrightFirst & notBrightSecond; + } + + public bool IsCrossable() => IsCrossable(PlantHue); + + public bool IsBright() => IsBright(PlantHue); + + public PlantHue GetNotBright() => GetNotBright(PlantHue); + + public bool IsPrimary() => IsPrimary(PlantHue); + } +} diff --git a/Projects/UOContent/Engines/Plants/PlantItem.cs b/Projects/UOContent/Engines/Plants/PlantItem.cs index 297db5ee4..a63dc73ec 100644 --- a/Projects/UOContent/Engines/Plants/PlantItem.cs +++ b/Projects/UOContent/Engines/Plants/PlantItem.cs @@ -1,551 +1,557 @@ -using System.Collections.Generic; -using Server.ContextMenus; -using Server.Gumps; -using Server.Items; -using Server.Multis; -using Server.Network; - -namespace Server.Engines.Plants -{ - public enum PlantStatus - { - BowlOfDirt = 0, - Seed = 1, - Sapling = 2, - Plant = 4, - FullGrownPlant = 7, - DecorativePlant = 10, - DeadTwigs = 11, - - Stage1 = 1, - Stage2 = 2, - Stage3 = 3, - Stage4 = 4, - Stage5 = 5, - Stage6 = 6, - Stage7 = 7, - Stage8 = 8, - Stage9 = 9 - } - - public class PlantItem : Item, ISecurable - { - /* - * Clients 7.0.12.0+ expect a container type in the plant label. - * To support older (and only older) clients, change this to false. - */ - private static readonly bool ShowContainerType = true; - private PlantHue m_PlantHue; - - private PlantStatus m_PlantStatus; - private PlantType m_PlantType; - private bool m_ShowType; - - [Constructible] - public PlantItem(bool fertileDirt = false) : base(0x1602) - { - Weight = 1.0; - - m_PlantStatus = PlantStatus.BowlOfDirt; - PlantSystem = new PlantSystem(this, fertileDirt); - Level = SecureLevel.Owner; - - Plants.Add(this); - } - - public PlantItem(Serial serial) : base(serial) - { - } - - public PlantSystem PlantSystem { get; private set; } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - [CommandProperty(AccessLevel.GameMaster)] - public PlantStatus PlantStatus - { - get => m_PlantStatus; - set - { - if (m_PlantStatus == value || value < PlantStatus.BowlOfDirt || value > PlantStatus.DeadTwigs) - return; - - double ratio; - if (PlantSystem != null) - ratio = (double)PlantSystem.Hits / PlantSystem.MaxHits; - else - ratio = 1.0; - - m_PlantStatus = value; - - if (m_PlantStatus >= PlantStatus.DecorativePlant) - { - PlantSystem = null; - } - else - { - PlantSystem ??= new PlantSystem(this, false); - - int hits = (int)(PlantSystem.MaxHits * ratio); - - if (hits == 0 && m_PlantStatus > PlantStatus.BowlOfDirt) - PlantSystem.Hits = hits + 1; - else - PlantSystem.Hits = hits; - } - - Update(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public PlantType PlantType - { - get => m_PlantType; - set - { - m_PlantType = value; - Update(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public PlantHue PlantHue - { - get => m_PlantHue; - set - { - m_PlantHue = value; - Update(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool ShowType - { - get => m_ShowType; - set - { - m_ShowType = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool ValidGrowthLocation - { - get - { - if (IsLockedDown && RootParent == null) - return true; - - if (!(RootParent is Mobile owner)) - return false; - - return IsChildOf(owner.Backpack) || IsChildOf(owner.FindBankNoCreate()); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsGrowable => m_PlantStatus >= PlantStatus.BowlOfDirt && m_PlantStatus <= PlantStatus.Stage9; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsCrossable => PlantHueInfo.IsCrossable(PlantHue) && PlantTypeInfo.IsCrossable(PlantType); - - [CommandProperty(AccessLevel.GameMaster)] - public bool Reproduces => PlantHueInfo.CanReproduce(PlantHue) && PlantTypeInfo.CanReproduce(PlantType); - - public static List Plants { get; } = new List(); - - [CommandProperty(AccessLevel.GameMaster)] - public SecureLevel Level { get; set; } - - public override void OnSingleClick(Mobile from) - { - if (m_PlantStatus >= PlantStatus.DeadTwigs) - LabelTo(from, LabelNumber); - else if (m_PlantStatus >= PlantStatus.DecorativePlant) - LabelTo(from, 1061924); // a decorative plant - else if (m_PlantStatus >= PlantStatus.FullGrownPlant) - LabelTo(from, PlantTypeInfo.GetInfo(m_PlantType).Name); - else - LabelTo(from, 1029913); // plant bowl - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - SetSecureLevelEntry.AddTo(from, this, list); - } - - public int GetLocalizedPlantStatus() - { - if (m_PlantStatus >= PlantStatus.Plant) - return 1060812; // plant - if (m_PlantStatus >= PlantStatus.Sapling) - return 1023305; // sapling - if (m_PlantStatus >= PlantStatus.Seed) - return 1060810; // seed - return 1026951; // dirt - } - - public int GetLocalizedContainerType() => 1150435; - - private void Update() - { - if (m_PlantStatus >= PlantStatus.DeadTwigs) - { - ItemID = 0x1B9D; - Hue = PlantHueInfo.GetInfo(m_PlantHue).Hue; - } - else if (m_PlantStatus >= PlantStatus.FullGrownPlant) - { - ItemID = PlantTypeInfo.GetInfo(m_PlantType).ItemID; - Hue = PlantHueInfo.GetInfo(m_PlantHue).Hue; - } - else if (m_PlantStatus >= PlantStatus.Plant) - { - ItemID = 0x1600; - Hue = 0; - } - else - { - ItemID = 0x1602; - Hue = 0; - } - - InvalidateProperties(); - } - - public override void AddNameProperty(ObjectPropertyList list) - { - if (m_PlantStatus >= PlantStatus.DeadTwigs) - { - base.AddNameProperty(list); - } - else if (m_PlantStatus < PlantStatus.Seed) - { - string args; - - if (ShowContainerType) - args = $"#{GetLocalizedContainerType()}\t#{PlantSystem.GetLocalizedDirtStatus()}"; - else - args = $"#{PlantSystem.GetLocalizedDirtStatus()}"; - - list.Add(1060830, args); // a ~1_val~ of ~2_val~ dirt - } - else - { - PlantTypeInfo typeInfo = PlantTypeInfo.GetInfo(m_PlantType); - PlantHueInfo hueInfo = PlantHueInfo.GetInfo(m_PlantHue); - - if (m_PlantStatus >= PlantStatus.DecorativePlant) - { - list.Add(typeInfo.GetPlantLabelDecorative(hueInfo), $"#{hueInfo.Name}\t#{typeInfo.Name}"); - } - else if (m_PlantStatus >= PlantStatus.FullGrownPlant) - { - list.Add(typeInfo.GetPlantLabelFullGrown(hueInfo), - $"#{PlantSystem.GetLocalizedHealth()}\t#{hueInfo.Name}\t#{typeInfo.Name}"); - } - else - { - string args; - - if (ShowContainerType) - args = - $"#{GetLocalizedContainerType()}\t#{PlantSystem.GetLocalizedDirtStatus()}\t#{PlantSystem.GetLocalizedHealth()}"; - else - args = $"#{PlantSystem.GetLocalizedDirtStatus()}\t#{PlantSystem.GetLocalizedHealth()}"; - - if (m_ShowType) - { - args += $"\t#{hueInfo.Name}\t#{typeInfo.Name}\t#{GetLocalizedPlantStatus()}"; - - if (m_PlantStatus == PlantStatus.Plant) - list.Add(typeInfo.GetPlantLabelPlant(hueInfo), args); - else - list.Add(typeInfo.GetPlantLabelSeed(hueInfo), args); - } - else - { - args += - $"\t#{(typeInfo.PlantCategory == PlantCategory.Default ? hueInfo.Name : (int)typeInfo.PlantCategory)}\t#{GetLocalizedPlantStatus()}"; - - list.Add(hueInfo.IsBright() ? 1060832 : 1060831, - args); // a ~1_val~ of ~2_val~ dirt with a ~3_val~ [bright] ~4_val~ ~5_val~ - } - } - } - } - - public bool IsUsableBy(Mobile from) => - IsChildOf(from.Backpack) || IsChildOf(from.FindBankNoCreate()) || (IsLockedDown && IsAccessibleTo(from)) || - (RootParent is Item root && root.IsSecure && root.IsAccessibleTo(from)); - - public override void OnDoubleClick(Mobile from) - { - if (m_PlantStatus >= PlantStatus.DecorativePlant) - return; - - Point3D loc = GetWorldLocation(); - - if (!from.InLOS(loc) || !from.InRange(loc, 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 1019045); // I can't reach that. - return; - } - - if (!IsUsableBy(from)) - { - LabelTo(from, 1061856); // You must have the item in your backpack or locked down in order to use it. - return; - } - - from.SendGump(new MainPlantGump(this)); - } - - public void PlantSeed(Mobile from, Seed seed) - { - if (m_PlantStatus >= PlantStatus.FullGrownPlant) - { - LabelTo(from, 1061919); // You must use a seed on some prepared soil! - } - else if (!IsUsableBy(from)) - { - LabelTo(from, 1061921); // The bowl of dirt must be in your pack, or you must lock it down. - } - else if (m_PlantStatus != PlantStatus.BowlOfDirt) - { - from.SendLocalizedMessage(1080389, - $"#{GetLocalizedPlantStatus()}"); // This bowl of dirt already has a ~1_val~ in it! - } - else if (PlantSystem.Water < 2) - { - LabelTo(from, 1061920); // The dirt needs to be softened first. - } - else - { - m_PlantType = seed.PlantType; - m_PlantHue = seed.PlantHue; - m_ShowType = seed.ShowType; - - seed.Consume(); - - PlantStatus = PlantStatus.Seed; - - PlantSystem.Reset(false); - - LabelTo(from, 1061922); // You plant the seed in the bowl of dirt. - } - } - - public void Die() - { - if (m_PlantStatus >= PlantStatus.FullGrownPlant) - { - PlantStatus = PlantStatus.DeadTwigs; - } - else - { - PlantStatus = PlantStatus.BowlOfDirt; - PlantSystem.Reset(true); - } - } - - public void Pour(Mobile from, Item item) - { - if (m_PlantStatus >= PlantStatus.DeadTwigs) - return; - - if (m_PlantStatus == PlantStatus.DecorativePlant) - { - LabelTo(from, 1053049); // This is a decorative plant, it does not need watering! - return; - } - - if (!IsUsableBy(from)) - { - LabelTo(from, 1061856); // You must have the item in your backpack or locked down in order to use it. - return; - } - - if (item is BaseBeverage beverage) - { - if (beverage.IsEmpty || !beverage.Pourable || beverage.Content != BeverageType.Water) - { - LabelTo(from, 1053069); // You can't use that on a plant! - return; - } - - if (!beverage.ValidateUse(from, true)) - return; - - beverage.Quantity--; - PlantSystem.Water++; - - from.PlaySound(0x4E); - LabelTo(from, 1061858); // You soften the dirt with water. - } - else if (item is BasePotion potion) - { - if (ApplyPotion(potion.PotionEffect, false, out int message)) - { - potion.Consume(); - from.PlaySound(0x240); - from.AddToBackpack(new Bottle()); - } - - LabelTo(from, message); - } - else if (item is PotionKeg keg) - { - if (keg.Held <= 0) - { - LabelTo(from, 1053069); // You can't use that on a plant! - return; - } - - if (ApplyPotion(keg.Type, false, out int message)) - { - keg.Held--; - from.PlaySound(0x240); - } - - LabelTo(from, message); - } - else - { - LabelTo(from, 1053069); // You can't use that on a plant! - } - } - - public bool ApplyPotion(PotionEffect effect, bool testOnly, out int message) - { - if (m_PlantStatus >= PlantStatus.DecorativePlant) - { - message = 1053049; // This is a decorative plant, it does not need watering! - return false; - } - - if (m_PlantStatus == PlantStatus.BowlOfDirt) - { - message = 1053066; // You should only pour potions on a plant or seed! - return false; - } - - bool full = false; - - if (effect == PotionEffect.PoisonGreater || effect == PotionEffect.PoisonDeadly) - { - if (PlantSystem.IsFullPoisonPotion) - full = true; - else if (!testOnly) - PlantSystem.PoisonPotion++; - } - else if (effect == PotionEffect.CureGreater) - { - if (PlantSystem.IsFullCurePotion) - full = true; - else if (!testOnly) - PlantSystem.CurePotion++; - } - else if (effect == PotionEffect.HealGreater) - { - if (PlantSystem.IsFullHealPotion) - full = true; - else if (!testOnly) - PlantSystem.HealPotion++; - } - else if (effect == PotionEffect.StrengthGreater) - { - if (PlantSystem.IsFullStrengthPotion) - full = true; - else if (!testOnly) - PlantSystem.StrengthPotion++; - } - else if (effect == PotionEffect.PoisonLesser || effect == PotionEffect.Poison || - effect == PotionEffect.CureLesser || effect == PotionEffect.Cure || - effect == PotionEffect.HealLesser || effect == PotionEffect.Heal || effect == PotionEffect.Strength) - { - message = 1053068; // This potion is not powerful enough to use on a plant! - return false; - } - else - { - message = 1053069; // You can't use that on a plant! - return false; - } - - if (full) - { - message = 1053065; // The plant is already soaked with this type of potion! - return false; - } - - message = 1053067; // You pour the potion over the plant. - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(2); // version - - writer.Write((int)Level); - - writer.Write((int)m_PlantStatus); - writer.Write((int)m_PlantType); - writer.Write((int)m_PlantHue); - writer.Write(m_ShowType); - - if (m_PlantStatus < PlantStatus.DecorativePlant) - PlantSystem.Save(writer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 2: - case 1: - { - Level = (SecureLevel)reader.ReadInt(); - goto case 0; - } - case 0: - { - if (version < 1) - Level = SecureLevel.CoOwners; - - m_PlantStatus = (PlantStatus)reader.ReadInt(); - m_PlantType = (PlantType)reader.ReadInt(); - m_PlantHue = (PlantHue)reader.ReadInt(); - m_ShowType = reader.ReadBool(); - - if (m_PlantStatus < PlantStatus.DecorativePlant) - PlantSystem = new PlantSystem(this, reader); - - if (version < 2 && PlantHueInfo.IsCrossable(m_PlantHue)) - m_PlantHue |= PlantHue.Reproduces; - - break; - } - } - - Plants.Add(this); - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - Plants.Remove(this); - } - } -} +using System.Collections.Generic; +using Server.ContextMenus; +using Server.Gumps; +using Server.Items; +using Server.Multis; +using Server.Network; + +namespace Server.Engines.Plants +{ + public enum PlantStatus + { + BowlOfDirt = 0, + Seed = 1, + Sapling = 2, + Plant = 4, + FullGrownPlant = 7, + DecorativePlant = 10, + DeadTwigs = 11, + + Stage1 = 1, + Stage2 = 2, + Stage3 = 3, + Stage4 = 4, + Stage5 = 5, + Stage6 = 6, + Stage7 = 7, + Stage8 = 8, + Stage9 = 9 + } + + public class PlantItem : Item, ISecurable + { + /* + * Clients 7.0.12.0+ expect a container type in the plant label. + * To support older (and only older) clients, change this to false. + */ + private static readonly bool ShowContainerType = true; + private PlantHue m_PlantHue; + + private PlantStatus m_PlantStatus; + private PlantType m_PlantType; + private bool m_ShowType; + + [Constructible] + public PlantItem(bool fertileDirt = false) : base(0x1602) + { + Weight = 1.0; + + m_PlantStatus = PlantStatus.BowlOfDirt; + PlantSystem = new PlantSystem(this, fertileDirt); + Level = SecureLevel.Owner; + + Plants.Add(this); + } + + public PlantItem(Serial serial) : base(serial) + { + } + + public PlantSystem PlantSystem { get; private set; } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + [CommandProperty(AccessLevel.GameMaster)] + public PlantStatus PlantStatus + { + get => m_PlantStatus; + set + { + if (m_PlantStatus == value || value < PlantStatus.BowlOfDirt || value > PlantStatus.DeadTwigs) + return; + + double ratio; + if (PlantSystem != null) + ratio = (double)PlantSystem.Hits / PlantSystem.MaxHits; + else + ratio = 1.0; + + m_PlantStatus = value; + + if (m_PlantStatus >= PlantStatus.DecorativePlant) + { + PlantSystem = null; + } + else + { + PlantSystem ??= new PlantSystem(this, false); + + var hits = (int)(PlantSystem.MaxHits * ratio); + + if (hits == 0 && m_PlantStatus > PlantStatus.BowlOfDirt) + PlantSystem.Hits = hits + 1; + else + PlantSystem.Hits = hits; + } + + Update(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public PlantType PlantType + { + get => m_PlantType; + set + { + m_PlantType = value; + Update(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public PlantHue PlantHue + { + get => m_PlantHue; + set + { + m_PlantHue = value; + Update(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool ShowType + { + get => m_ShowType; + set + { + m_ShowType = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool ValidGrowthLocation + { + get + { + if (IsLockedDown && RootParent == null) + return true; + + if (!(RootParent is Mobile owner)) + return false; + + return IsChildOf(owner.Backpack) || IsChildOf(owner.FindBankNoCreate()); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsGrowable => m_PlantStatus >= PlantStatus.BowlOfDirt && m_PlantStatus <= PlantStatus.Stage9; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsCrossable => PlantHueInfo.IsCrossable(PlantHue) && PlantTypeInfo.IsCrossable(PlantType); + + [CommandProperty(AccessLevel.GameMaster)] + public bool Reproduces => PlantHueInfo.CanReproduce(PlantHue) && PlantTypeInfo.CanReproduce(PlantType); + + public static List Plants { get; } = new List(); + + [CommandProperty(AccessLevel.GameMaster)] + public SecureLevel Level { get; set; } + + public override void OnSingleClick(Mobile from) + { + if (m_PlantStatus >= PlantStatus.DeadTwigs) + LabelTo(from, LabelNumber); + else if (m_PlantStatus >= PlantStatus.DecorativePlant) + LabelTo(from, 1061924); // a decorative plant + else if (m_PlantStatus >= PlantStatus.FullGrownPlant) + LabelTo(from, PlantTypeInfo.GetInfo(m_PlantType).Name); + else + LabelTo(from, 1029913); // plant bowl + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + SetSecureLevelEntry.AddTo(from, this, list); + } + + public int GetLocalizedPlantStatus() + { + if (m_PlantStatus >= PlantStatus.Plant) + return 1060812; // plant + if (m_PlantStatus >= PlantStatus.Sapling) + return 1023305; // sapling + if (m_PlantStatus >= PlantStatus.Seed) + return 1060810; // seed + return 1026951; // dirt + } + + public int GetLocalizedContainerType() => 1150435; + + private void Update() + { + if (m_PlantStatus >= PlantStatus.DeadTwigs) + { + ItemID = 0x1B9D; + Hue = PlantHueInfo.GetInfo(m_PlantHue).Hue; + } + else if (m_PlantStatus >= PlantStatus.FullGrownPlant) + { + ItemID = PlantTypeInfo.GetInfo(m_PlantType).ItemID; + Hue = PlantHueInfo.GetInfo(m_PlantHue).Hue; + } + else if (m_PlantStatus >= PlantStatus.Plant) + { + ItemID = 0x1600; + Hue = 0; + } + else + { + ItemID = 0x1602; + Hue = 0; + } + + InvalidateProperties(); + } + + public override void AddNameProperty(ObjectPropertyList list) + { + if (m_PlantStatus >= PlantStatus.DeadTwigs) + { + base.AddNameProperty(list); + } + else if (m_PlantStatus < PlantStatus.Seed) + { + string args; + + if (ShowContainerType) + args = $"#{GetLocalizedContainerType()}\t#{PlantSystem.GetLocalizedDirtStatus()}"; + else + args = $"#{PlantSystem.GetLocalizedDirtStatus()}"; + + list.Add(1060830, args); // a ~1_val~ of ~2_val~ dirt + } + else + { + var typeInfo = PlantTypeInfo.GetInfo(m_PlantType); + var hueInfo = PlantHueInfo.GetInfo(m_PlantHue); + + if (m_PlantStatus >= PlantStatus.DecorativePlant) + { + list.Add(typeInfo.GetPlantLabelDecorative(hueInfo), $"#{hueInfo.Name}\t#{typeInfo.Name}"); + } + else if (m_PlantStatus >= PlantStatus.FullGrownPlant) + { + list.Add( + typeInfo.GetPlantLabelFullGrown(hueInfo), + $"#{PlantSystem.GetLocalizedHealth()}\t#{hueInfo.Name}\t#{typeInfo.Name}" + ); + } + else + { + string args; + + if (ShowContainerType) + args = + $"#{GetLocalizedContainerType()}\t#{PlantSystem.GetLocalizedDirtStatus()}\t#{PlantSystem.GetLocalizedHealth()}"; + else + args = $"#{PlantSystem.GetLocalizedDirtStatus()}\t#{PlantSystem.GetLocalizedHealth()}"; + + if (m_ShowType) + { + args += $"\t#{hueInfo.Name}\t#{typeInfo.Name}\t#{GetLocalizedPlantStatus()}"; + + if (m_PlantStatus == PlantStatus.Plant) + list.Add(typeInfo.GetPlantLabelPlant(hueInfo), args); + else + list.Add(typeInfo.GetPlantLabelSeed(hueInfo), args); + } + else + { + args += + $"\t#{(typeInfo.PlantCategory == PlantCategory.Default ? hueInfo.Name : (int)typeInfo.PlantCategory)}\t#{GetLocalizedPlantStatus()}"; + + list.Add( + hueInfo.IsBright() ? 1060832 : 1060831, + args + ); // a ~1_val~ of ~2_val~ dirt with a ~3_val~ [bright] ~4_val~ ~5_val~ + } + } + } + } + + public bool IsUsableBy(Mobile from) => + IsChildOf(from.Backpack) || IsChildOf(from.FindBankNoCreate()) || IsLockedDown && IsAccessibleTo(@from) || + RootParent is Item root && root.IsSecure && root.IsAccessibleTo(@from); + + public override void OnDoubleClick(Mobile from) + { + if (m_PlantStatus >= PlantStatus.DecorativePlant) + return; + + var loc = GetWorldLocation(); + + if (!from.InLOS(loc) || !from.InRange(loc, 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 1019045); // I can't reach that. + return; + } + + if (!IsUsableBy(from)) + { + LabelTo(from, 1061856); // You must have the item in your backpack or locked down in order to use it. + return; + } + + from.SendGump(new MainPlantGump(this)); + } + + public void PlantSeed(Mobile from, Seed seed) + { + if (m_PlantStatus >= PlantStatus.FullGrownPlant) + { + LabelTo(from, 1061919); // You must use a seed on some prepared soil! + } + else if (!IsUsableBy(from)) + { + LabelTo(from, 1061921); // The bowl of dirt must be in your pack, or you must lock it down. + } + else if (m_PlantStatus != PlantStatus.BowlOfDirt) + { + from.SendLocalizedMessage( + 1080389, + $"#{GetLocalizedPlantStatus()}" + ); // This bowl of dirt already has a ~1_val~ in it! + } + else if (PlantSystem.Water < 2) + { + LabelTo(from, 1061920); // The dirt needs to be softened first. + } + else + { + m_PlantType = seed.PlantType; + m_PlantHue = seed.PlantHue; + m_ShowType = seed.ShowType; + + seed.Consume(); + + PlantStatus = PlantStatus.Seed; + + PlantSystem.Reset(false); + + LabelTo(from, 1061922); // You plant the seed in the bowl of dirt. + } + } + + public void Die() + { + if (m_PlantStatus >= PlantStatus.FullGrownPlant) + { + PlantStatus = PlantStatus.DeadTwigs; + } + else + { + PlantStatus = PlantStatus.BowlOfDirt; + PlantSystem.Reset(true); + } + } + + public void Pour(Mobile from, Item item) + { + if (m_PlantStatus >= PlantStatus.DeadTwigs) + return; + + if (m_PlantStatus == PlantStatus.DecorativePlant) + { + LabelTo(from, 1053049); // This is a decorative plant, it does not need watering! + return; + } + + if (!IsUsableBy(from)) + { + LabelTo(from, 1061856); // You must have the item in your backpack or locked down in order to use it. + return; + } + + if (item is BaseBeverage beverage) + { + if (beverage.IsEmpty || !beverage.Pourable || beverage.Content != BeverageType.Water) + { + LabelTo(from, 1053069); // You can't use that on a plant! + return; + } + + if (!beverage.ValidateUse(from, true)) + return; + + beverage.Quantity--; + PlantSystem.Water++; + + from.PlaySound(0x4E); + LabelTo(from, 1061858); // You soften the dirt with water. + } + else if (item is BasePotion potion) + { + if (ApplyPotion(potion.PotionEffect, false, out var message)) + { + potion.Consume(); + from.PlaySound(0x240); + from.AddToBackpack(new Bottle()); + } + + LabelTo(from, message); + } + else if (item is PotionKeg keg) + { + if (keg.Held <= 0) + { + LabelTo(from, 1053069); // You can't use that on a plant! + return; + } + + if (ApplyPotion(keg.Type, false, out var message)) + { + keg.Held--; + from.PlaySound(0x240); + } + + LabelTo(from, message); + } + else + { + LabelTo(from, 1053069); // You can't use that on a plant! + } + } + + public bool ApplyPotion(PotionEffect effect, bool testOnly, out int message) + { + if (m_PlantStatus >= PlantStatus.DecorativePlant) + { + message = 1053049; // This is a decorative plant, it does not need watering! + return false; + } + + if (m_PlantStatus == PlantStatus.BowlOfDirt) + { + message = 1053066; // You should only pour potions on a plant or seed! + return false; + } + + var full = false; + + if (effect == PotionEffect.PoisonGreater || effect == PotionEffect.PoisonDeadly) + { + if (PlantSystem.IsFullPoisonPotion) + full = true; + else if (!testOnly) + PlantSystem.PoisonPotion++; + } + else if (effect == PotionEffect.CureGreater) + { + if (PlantSystem.IsFullCurePotion) + full = true; + else if (!testOnly) + PlantSystem.CurePotion++; + } + else if (effect == PotionEffect.HealGreater) + { + if (PlantSystem.IsFullHealPotion) + full = true; + else if (!testOnly) + PlantSystem.HealPotion++; + } + else if (effect == PotionEffect.StrengthGreater) + { + if (PlantSystem.IsFullStrengthPotion) + full = true; + else if (!testOnly) + PlantSystem.StrengthPotion++; + } + else if (effect == PotionEffect.PoisonLesser || effect == PotionEffect.Poison || + effect == PotionEffect.CureLesser || effect == PotionEffect.Cure || + effect == PotionEffect.HealLesser || effect == PotionEffect.Heal || effect == PotionEffect.Strength) + { + message = 1053068; // This potion is not powerful enough to use on a plant! + return false; + } + else + { + message = 1053069; // You can't use that on a plant! + return false; + } + + if (full) + { + message = 1053065; // The plant is already soaked with this type of potion! + return false; + } + + message = 1053067; // You pour the potion over the plant. + return true; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(2); // version + + writer.Write((int)Level); + + writer.Write((int)m_PlantStatus); + writer.Write((int)m_PlantType); + writer.Write((int)m_PlantHue); + writer.Write(m_ShowType); + + if (m_PlantStatus < PlantStatus.DecorativePlant) + PlantSystem.Save(writer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 2: + case 1: + { + Level = (SecureLevel)reader.ReadInt(); + goto case 0; + } + case 0: + { + if (version < 1) + Level = SecureLevel.CoOwners; + + m_PlantStatus = (PlantStatus)reader.ReadInt(); + m_PlantType = (PlantType)reader.ReadInt(); + m_PlantHue = (PlantHue)reader.ReadInt(); + m_ShowType = reader.ReadBool(); + + if (m_PlantStatus < PlantStatus.DecorativePlant) + PlantSystem = new PlantSystem(this, reader); + + if (version < 2 && PlantHueInfo.IsCrossable(m_PlantHue)) + m_PlantHue |= PlantHue.Reproduces; + + break; + } + } + + Plants.Add(this); + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + Plants.Remove(this); + } + } +} diff --git a/Projects/UOContent/Engines/Plants/PlantPourTarget.cs b/Projects/UOContent/Engines/Plants/PlantPourTarget.cs index be0507a7a..9c081bb3b 100644 --- a/Projects/UOContent/Engines/Plants/PlantPourTarget.cs +++ b/Projects/UOContent/Engines/Plants/PlantPourTarget.cs @@ -1,29 +1,29 @@ -using Server.Targeting; - -namespace Server.Engines.Plants -{ - public class PlantPourTarget : Target - { - private readonly PlantItem m_Plant; - - public PlantPourTarget(PlantItem plant) : base(3, true, TargetFlags.None) => m_Plant = plant; - - protected override void OnTarget(Mobile from, object targeted) - { - if (!m_Plant.Deleted && from.InRange(m_Plant.GetWorldLocation(), 3) && targeted is Item item) - m_Plant.Pour(from, item); - } - - protected override void OnTargetFinish(Mobile from) - { - if (!m_Plant.Deleted && m_Plant.PlantStatus < PlantStatus.DecorativePlant && - from.InRange(m_Plant.GetWorldLocation(), 3) && m_Plant.IsUsableBy(from)) - { - if (from.HasGump()) - from.CloseGump(); - - from.SendGump(new MainPlantGump(m_Plant)); - } - } - } -} \ No newline at end of file +using Server.Targeting; + +namespace Server.Engines.Plants +{ + public class PlantPourTarget : Target + { + private readonly PlantItem m_Plant; + + public PlantPourTarget(PlantItem plant) : base(3, true, TargetFlags.None) => m_Plant = plant; + + protected override void OnTarget(Mobile from, object targeted) + { + if (!m_Plant.Deleted && from.InRange(m_Plant.GetWorldLocation(), 3) && targeted is Item item) + m_Plant.Pour(from, item); + } + + protected override void OnTargetFinish(Mobile from) + { + if (!m_Plant.Deleted && m_Plant.PlantStatus < PlantStatus.DecorativePlant && + from.InRange(m_Plant.GetWorldLocation(), 3) && m_Plant.IsUsableBy(from)) + { + if (from.HasGump()) + from.CloseGump(); + + from.SendGump(new MainPlantGump(m_Plant)); + } + } + } +} diff --git a/Projects/UOContent/Engines/Plants/PlantResources.cs b/Projects/UOContent/Engines/Plants/PlantResources.cs index 8e9b0e6b3..f8a555072 100644 --- a/Projects/UOContent/Engines/Plants/PlantResources.cs +++ b/Projects/UOContent/Engines/Plants/PlantResources.cs @@ -1,46 +1,46 @@ -using System; -using Server.Items; -using Server.Utilities; - -namespace Server.Engines.Plants -{ - public class PlantResourceInfo - { - private static readonly PlantResourceInfo[] m_ResourceList = - { - new PlantResourceInfo(PlantType.ElephantEarPlant, PlantHue.BrightRed, typeof(RedLeaves)), - new PlantResourceInfo(PlantType.PonytailPalm, PlantHue.BrightRed, typeof(RedLeaves)), - new PlantResourceInfo(PlantType.CenturyPlant, PlantHue.BrightRed, typeof(RedLeaves)), - new PlantResourceInfo(PlantType.Poppies, PlantHue.BrightOrange, typeof(OrangePetals)), - new PlantResourceInfo(PlantType.Bulrushes, PlantHue.BrightOrange, typeof(OrangePetals)), - new PlantResourceInfo(PlantType.PampasGrass, PlantHue.BrightOrange, typeof(OrangePetals)), - new PlantResourceInfo(PlantType.SnakePlant, PlantHue.BrightGreen, typeof(GreenThorns)), - new PlantResourceInfo(PlantType.BarrelCactus, PlantHue.BrightGreen, typeof(GreenThorns)), - new PlantResourceInfo(PlantType.CocoaTree, PlantHue.Plain, typeof(CocoaPulp)) - }; - - private PlantResourceInfo(PlantType plantType, PlantHue plantHue, Type resourceType) - { - PlantType = plantType; - PlantHue = plantHue; - ResourceType = resourceType; - } - - public PlantType PlantType { get; } - - public PlantHue PlantHue { get; } - - public Type ResourceType { get; } - - public static PlantResourceInfo GetInfo(PlantType plantType, PlantHue plantHue) - { - foreach (PlantResourceInfo info in m_ResourceList) - if (info.PlantType == plantType && info.PlantHue == plantHue) - return info; - - return null; - } - - public Item CreateResource() => (Item)ActivatorUtil.CreateInstance(ResourceType); - } -} +using System; +using Server.Items; +using Server.Utilities; + +namespace Server.Engines.Plants +{ + public class PlantResourceInfo + { + private static readonly PlantResourceInfo[] m_ResourceList = + { + new PlantResourceInfo(PlantType.ElephantEarPlant, PlantHue.BrightRed, typeof(RedLeaves)), + new PlantResourceInfo(PlantType.PonytailPalm, PlantHue.BrightRed, typeof(RedLeaves)), + new PlantResourceInfo(PlantType.CenturyPlant, PlantHue.BrightRed, typeof(RedLeaves)), + new PlantResourceInfo(PlantType.Poppies, PlantHue.BrightOrange, typeof(OrangePetals)), + new PlantResourceInfo(PlantType.Bulrushes, PlantHue.BrightOrange, typeof(OrangePetals)), + new PlantResourceInfo(PlantType.PampasGrass, PlantHue.BrightOrange, typeof(OrangePetals)), + new PlantResourceInfo(PlantType.SnakePlant, PlantHue.BrightGreen, typeof(GreenThorns)), + new PlantResourceInfo(PlantType.BarrelCactus, PlantHue.BrightGreen, typeof(GreenThorns)), + new PlantResourceInfo(PlantType.CocoaTree, PlantHue.Plain, typeof(CocoaPulp)) + }; + + private PlantResourceInfo(PlantType plantType, PlantHue plantHue, Type resourceType) + { + PlantType = plantType; + PlantHue = plantHue; + ResourceType = resourceType; + } + + public PlantType PlantType { get; } + + public PlantHue PlantHue { get; } + + public Type ResourceType { get; } + + public static PlantResourceInfo GetInfo(PlantType plantType, PlantHue plantHue) + { + foreach (var info in m_ResourceList) + if (info.PlantType == plantType && info.PlantHue == plantHue) + return info; + + return null; + } + + public Item CreateResource() => (Item)ActivatorUtil.CreateInstance(ResourceType); + } +} diff --git a/Projects/UOContent/Engines/Plants/PlantSystem.cs b/Projects/UOContent/Engines/Plants/PlantSystem.cs index 7418541f5..9fd7abd88 100644 --- a/Projects/UOContent/Engines/Plants/PlantSystem.cs +++ b/Projects/UOContent/Engines/Plants/PlantSystem.cs @@ -1,594 +1,600 @@ -using System; -using System.Collections.Generic; -using Server.Misc; - -namespace Server.Engines.Plants -{ - public enum PlantHealth - { - Dying, - Wilted, - Healthy, - Vibrant - } - - public enum PlantGrowthIndicator - { - None, - InvalidLocation, - NotHealthy, - Delay, - Grown, - DoubleGrown - } - - public class PlantSystem - { - public static readonly TimeSpan CheckDelay = TimeSpan.FromHours(23.0); - - private int m_AvailableResources; - private int m_AvailableSeeds; - private int m_CurePotion; - private int m_Disease; - private int m_Fungus; - private int m_HealPotion; - - private int m_Hits; - private int m_Infestation; - private int m_LeftResources; - private int m_LeftSeeds; - private int m_Poison; - private int m_PoisonPotion; - private PlantHue m_SeedHue; - - private PlantType m_SeedType; - private int m_StrengthPotion; - - private int m_Water; - - public PlantSystem(PlantItem plant, bool fertileDirt) - { - Plant = plant; - FertileDirt = fertileDirt; - - NextGrowth = DateTime.UtcNow + CheckDelay; - GrowthIndicator = PlantGrowthIndicator.None; - m_Hits = MaxHits; - m_LeftSeeds = 8; - m_LeftResources = 8; - } - - public PlantSystem(PlantItem plant, IGenericReader reader) - { - Plant = plant; - - int version = reader.ReadInt(); - - FertileDirt = reader.ReadBool(); - - if (version >= 1) - NextGrowth = reader.ReadDateTime(); - else - NextGrowth = reader.ReadDeltaTime(); - - GrowthIndicator = (PlantGrowthIndicator)reader.ReadInt(); - - m_Water = reader.ReadInt(); - - m_Hits = reader.ReadInt(); - m_Infestation = reader.ReadInt(); - m_Fungus = reader.ReadInt(); - m_Poison = reader.ReadInt(); - m_Disease = reader.ReadInt(); - m_PoisonPotion = reader.ReadInt(); - m_CurePotion = reader.ReadInt(); - m_HealPotion = reader.ReadInt(); - m_StrengthPotion = reader.ReadInt(); - - Pollinated = reader.ReadBool(); - m_SeedType = (PlantType)reader.ReadInt(); - m_SeedHue = (PlantHue)reader.ReadInt(); - m_AvailableSeeds = reader.ReadInt(); - m_LeftSeeds = reader.ReadInt(); - - m_AvailableResources = reader.ReadInt(); - m_LeftResources = reader.ReadInt(); - - if (version < 2 && PlantHueInfo.IsCrossable(m_SeedHue)) - m_SeedHue |= PlantHue.Reproduces; - } - - public PlantItem Plant { get; } - - public bool FertileDirt { get; set; } - - public DateTime NextGrowth { get; private set; } - - public PlantGrowthIndicator GrowthIndicator { get; private set; } - - public bool IsFullWater => m_Water >= 4; - - public int Water - { - get => m_Water; - set - { - m_Water = Math.Clamp(value, 0, 4); - Plant.InvalidateProperties(); - } - } - - public int Hits - { - get => m_Hits; - set - { - if (m_Hits == value) - return; - - m_Hits = Math.Clamp(value, 0, MaxHits); - - if (m_Hits == 0) - Plant.Die(); - - Plant.InvalidateProperties(); - } - } - - public int MaxHits => 10 + (int)Plant.PlantStatus * 2; - - public PlantHealth Health - { - get - { - int perc = m_Hits * 100 / MaxHits; - - if (perc < 33) - return PlantHealth.Dying; - if (perc < 66) - return PlantHealth.Wilted; - return perc < 100 ? PlantHealth.Healthy : PlantHealth.Vibrant; - } - } - - public int Infestation - { - get => m_Infestation; - set => m_Infestation = Math.Clamp(value, 0, 2); - } - - public int Fungus - { - get => m_Fungus; - set => m_Fungus = Math.Clamp(value, 0, 2); - } - - public int Poison - { - get => m_Poison; - set => m_Poison = Math.Clamp(value, 0, 2); - } - - public int Disease - { - get => m_Disease; - set => m_Disease = Math.Clamp(value, 0, 2); - } - - public bool IsFullPoisonPotion => m_PoisonPotion >= 2; - - public int PoisonPotion - { - get => m_PoisonPotion; - set => m_PoisonPotion = Math.Clamp(value, 0, 2); - } - - public bool IsFullCurePotion => m_CurePotion >= 2; - - public int CurePotion - { - get => m_CurePotion; - set => m_CurePotion = Math.Clamp(value, 0, 2); - } - - public bool IsFullHealPotion => m_HealPotion >= 2; - - public int HealPotion - { - get => m_HealPotion; - set => m_HealPotion = Math.Clamp(value, 0, 2); - } - - public bool IsFullStrengthPotion => m_StrengthPotion >= 2; - - public int StrengthPotion - { - get => m_StrengthPotion; - set => m_StrengthPotion = Math.Clamp(value, 0, 2); - } - - public bool HasMaladies => Infestation > 0 || Fungus > 0 || Poison > 0 || Disease > 0 || Water != 2; - - public bool PollenProducing => Plant.IsCrossable && Plant.PlantStatus >= PlantStatus.FullGrownPlant; - - public bool Pollinated { get; set; } - - public PlantType SeedType - { - get => Pollinated ? m_SeedType : Plant.PlantType; - set => m_SeedType = value; - } - - public PlantHue SeedHue - { - get => Pollinated ? m_SeedHue : Plant.PlantHue; - set => m_SeedHue = value; - } - - public int AvailableSeeds - { - get => m_AvailableSeeds; - set - { - if (value >= 0) m_AvailableSeeds = value; - } - } - - public int LeftSeeds - { - get => m_LeftSeeds; - set - { - if (value >= 0) m_LeftSeeds = value; - } - } - - public int AvailableResources - { - get => m_AvailableResources; - set - { - if (value >= 0) m_AvailableResources = value; - } - } - - public int LeftResources - { - get => m_LeftResources; - set - { - if (value >= 0) m_LeftResources = value; - } - } - - public void Reset(bool potions) - { - NextGrowth = DateTime.UtcNow + CheckDelay; - GrowthIndicator = PlantGrowthIndicator.None; - - Hits = MaxHits; - m_Infestation = 0; - m_Fungus = 0; - m_Poison = 0; - m_Disease = 0; - - if (potions) - { - m_PoisonPotion = 0; - m_CurePotion = 0; - m_HealPotion = 0; - m_StrengthPotion = 0; - } - - Pollinated = false; - m_AvailableSeeds = 0; - m_LeftSeeds = 8; - - m_AvailableResources = 0; - m_LeftResources = 8; - } - - public int GetLocalizedDirtStatus() - { - if (Water <= 1) - return 1060826; // hard - if (Water <= 2) - return 1060827; // soft - if (Water <= 3) - return 1060828; // squishy - return 1060829; // sopping wet - } - - public int GetLocalizedHealth() - { - return Health switch - { - PlantHealth.Dying => 1060825, // dying - PlantHealth.Wilted => 1060824, // wilted - PlantHealth.Healthy => 1060823, // healthy - _ => 1060822 - }; - } - - public static void Configure() - { - EventSink.WorldLoad += EventSink_WorldLoad; - - if (!AutoRestart.Enabled) - EventSink.WorldSave += EventSink_WorldSave; - - EventSink.Login += EventSink_Login; - } - - private static void EventSink_Login(Mobile from) - { - from.Backpack?.FindItemsByType().ForEach(plant => - { - if (plant.IsGrowable) - plant.PlantSystem.DoGrowthCheck(); - }); - - from.FindBankNoCreate()?.FindItemsByType().ForEach(plant => - { - if (plant.IsGrowable) - plant.PlantSystem.DoGrowthCheck(); - }); - } - - public static void GrowAll() - { - List plants = PlantItem.Plants; - DateTime now = DateTime.UtcNow; - - for (int i = plants.Count - 1; i >= 0; --i) - { - PlantItem plant = plants[i]; - - if (plant.IsGrowable && !(plant.RootParent is Mobile) && now >= plant.PlantSystem.NextGrowth) - plant.PlantSystem.DoGrowthCheck(); - } - } - - private static void EventSink_WorldLoad() - { - GrowAll(); - } - - private static void EventSink_WorldSave(bool message) - { - GrowAll(); - } - - public void DoGrowthCheck() - { - if (!Plant.IsGrowable) - return; - - if (DateTime.UtcNow < NextGrowth) - { - GrowthIndicator = PlantGrowthIndicator.Delay; - return; - } - - NextGrowth = DateTime.UtcNow + CheckDelay; - - if (!Plant.ValidGrowthLocation) - { - GrowthIndicator = PlantGrowthIndicator.InvalidLocation; - return; - } - - if (Plant.PlantStatus == PlantStatus.BowlOfDirt) - { - if (Water > 2 || Utility.RandomDouble() < 0.9) - Water--; - return; - } - - ApplyBeneficialEffects(); - - if (!ApplyMaladiesEffects()) // Dead - return; - - Grow(); - - UpdateMaladies(); - } - - private void ApplyBeneficialEffects() - { - if (PoisonPotion >= Infestation) - { - PoisonPotion -= Infestation; - Infestation = 0; - } - else - { - Infestation -= PoisonPotion; - PoisonPotion = 0; - } - - if (CurePotion >= Fungus) - { - CurePotion -= Fungus; - Fungus = 0; - } - else - { - Fungus -= CurePotion; - CurePotion = 0; - } - - if (HealPotion >= Poison) - { - HealPotion -= Poison; - Poison = 0; - } - else - { - Poison -= HealPotion; - HealPotion = 0; - } - - if (HealPotion >= Disease) - { - HealPotion -= Disease; - Disease = 0; - } - else - { - Disease -= HealPotion; - HealPotion = 0; - } - - if (!HasMaladies) - { - if (HealPotion > 0) - Hits += HealPotion * 7; - else - Hits += 2; - } - - HealPotion = 0; - } - - private bool ApplyMaladiesEffects() - { - int damage = 0; - - if (Infestation > 0) - damage += Infestation * Utility.RandomMinMax(3, 6); - - if (Fungus > 0) - damage += Fungus * Utility.RandomMinMax(3, 6); - - if (Poison > 0) - damage += Poison * Utility.RandomMinMax(3, 6); - - if (Disease > 0) - damage += Disease * Utility.RandomMinMax(3, 6); - - if (Water > 2) - damage += (Water - 2) * Utility.RandomMinMax(3, 6); - else if (Water < 2) - damage += (2 - Water) * Utility.RandomMinMax(3, 6); - - Hits -= damage; - - return Plant.IsGrowable && Plant.PlantStatus != PlantStatus.BowlOfDirt; - } - - private void Grow() - { - if (Health < PlantHealth.Healthy) - { - GrowthIndicator = PlantGrowthIndicator.NotHealthy; - } - else if (FertileDirt && Plant.PlantStatus <= PlantStatus.Stage5 && Utility.RandomDouble() < 0.1) - { - int curStage = (int)Plant.PlantStatus; - Plant.PlantStatus = (PlantStatus)(curStage + 2); - - GrowthIndicator = PlantGrowthIndicator.DoubleGrown; - } - else if (Plant.PlantStatus < PlantStatus.Stage9) - { - int curStage = (int)Plant.PlantStatus; - Plant.PlantStatus = (PlantStatus)(curStage + 1); - - GrowthIndicator = PlantGrowthIndicator.Grown; - } - else - { - if (Pollinated && LeftSeeds > 0 && Plant.Reproduces) - { - LeftSeeds--; - AvailableSeeds++; - } - - if (LeftResources > 0 && PlantResourceInfo.GetInfo(Plant.PlantType, Plant.PlantHue) != null) - { - LeftResources--; - AvailableResources++; - } - - GrowthIndicator = PlantGrowthIndicator.Grown; - } - - if (Plant.PlantStatus >= PlantStatus.Stage9 && !Pollinated) - { - Pollinated = true; - SeedType = Plant.PlantType; - SeedHue = Plant.PlantHue; - } - } - - private void UpdateMaladies() - { - double infestationChance = 0.30 - StrengthPotion * 0.075 + (Water - 2) * 0.10; - - PlantTypeInfo typeInfo = PlantTypeInfo.GetInfo(Plant.PlantType); - if (typeInfo.Flowery) - infestationChance += 0.10; - - if (PlantHueInfo.IsBright(Plant.PlantHue)) - infestationChance += 0.10; - - if (Utility.RandomDouble() < infestationChance) - Infestation++; - - double fungusChance = 0.15 - StrengthPotion * 0.075 + (Water - 2) * 0.10; - - if (Utility.RandomDouble() < fungusChance) - Fungus++; - - if (Water > 2 || Utility.RandomDouble() < 0.9) - Water--; - - if (PoisonPotion > 0) - { - Poison += PoisonPotion; - PoisonPotion = 0; - } - - if (CurePotion > 0) - { - Disease += CurePotion; - CurePotion = 0; - } - - StrengthPotion = 0; - } - - public void Save(IGenericWriter writer) - { - writer.Write(2); // version - - writer.Write(FertileDirt); - - writer.Write(NextGrowth); - writer.Write((int)GrowthIndicator); - - writer.Write(m_Water); - - writer.Write(m_Hits); - writer.Write(m_Infestation); - writer.Write(m_Fungus); - writer.Write(m_Poison); - writer.Write(m_Disease); - writer.Write(m_PoisonPotion); - writer.Write(m_CurePotion); - writer.Write(m_HealPotion); - writer.Write(m_StrengthPotion); - - writer.Write(Pollinated); - writer.Write((int)m_SeedType); - writer.Write((int)m_SeedHue); - writer.Write(m_AvailableSeeds); - writer.Write(m_LeftSeeds); - - writer.Write(m_AvailableResources); - writer.Write(m_LeftResources); - } - } -} +using System; +using Server.Misc; + +namespace Server.Engines.Plants +{ + public enum PlantHealth + { + Dying, + Wilted, + Healthy, + Vibrant + } + + public enum PlantGrowthIndicator + { + None, + InvalidLocation, + NotHealthy, + Delay, + Grown, + DoubleGrown + } + + public class PlantSystem + { + public static readonly TimeSpan CheckDelay = TimeSpan.FromHours(23.0); + + private int m_AvailableResources; + private int m_AvailableSeeds; + private int m_CurePotion; + private int m_Disease; + private int m_Fungus; + private int m_HealPotion; + + private int m_Hits; + private int m_Infestation; + private int m_LeftResources; + private int m_LeftSeeds; + private int m_Poison; + private int m_PoisonPotion; + private PlantHue m_SeedHue; + + private PlantType m_SeedType; + private int m_StrengthPotion; + + private int m_Water; + + public PlantSystem(PlantItem plant, bool fertileDirt) + { + Plant = plant; + FertileDirt = fertileDirt; + + NextGrowth = DateTime.UtcNow + CheckDelay; + GrowthIndicator = PlantGrowthIndicator.None; + m_Hits = MaxHits; + m_LeftSeeds = 8; + m_LeftResources = 8; + } + + public PlantSystem(PlantItem plant, IGenericReader reader) + { + Plant = plant; + + var version = reader.ReadInt(); + + FertileDirt = reader.ReadBool(); + + if (version >= 1) + NextGrowth = reader.ReadDateTime(); + else + NextGrowth = reader.ReadDeltaTime(); + + GrowthIndicator = (PlantGrowthIndicator)reader.ReadInt(); + + m_Water = reader.ReadInt(); + + m_Hits = reader.ReadInt(); + m_Infestation = reader.ReadInt(); + m_Fungus = reader.ReadInt(); + m_Poison = reader.ReadInt(); + m_Disease = reader.ReadInt(); + m_PoisonPotion = reader.ReadInt(); + m_CurePotion = reader.ReadInt(); + m_HealPotion = reader.ReadInt(); + m_StrengthPotion = reader.ReadInt(); + + Pollinated = reader.ReadBool(); + m_SeedType = (PlantType)reader.ReadInt(); + m_SeedHue = (PlantHue)reader.ReadInt(); + m_AvailableSeeds = reader.ReadInt(); + m_LeftSeeds = reader.ReadInt(); + + m_AvailableResources = reader.ReadInt(); + m_LeftResources = reader.ReadInt(); + + if (version < 2 && PlantHueInfo.IsCrossable(m_SeedHue)) + m_SeedHue |= PlantHue.Reproduces; + } + + public PlantItem Plant { get; } + + public bool FertileDirt { get; set; } + + public DateTime NextGrowth { get; private set; } + + public PlantGrowthIndicator GrowthIndicator { get; private set; } + + public bool IsFullWater => m_Water >= 4; + + public int Water + { + get => m_Water; + set + { + m_Water = Math.Clamp(value, 0, 4); + Plant.InvalidateProperties(); + } + } + + public int Hits + { + get => m_Hits; + set + { + if (m_Hits == value) + return; + + m_Hits = Math.Clamp(value, 0, MaxHits); + + if (m_Hits == 0) + Plant.Die(); + + Plant.InvalidateProperties(); + } + } + + public int MaxHits => 10 + (int)Plant.PlantStatus * 2; + + public PlantHealth Health + { + get + { + var perc = m_Hits * 100 / MaxHits; + + if (perc < 33) + return PlantHealth.Dying; + if (perc < 66) + return PlantHealth.Wilted; + return perc < 100 ? PlantHealth.Healthy : PlantHealth.Vibrant; + } + } + + public int Infestation + { + get => m_Infestation; + set => m_Infestation = Math.Clamp(value, 0, 2); + } + + public int Fungus + { + get => m_Fungus; + set => m_Fungus = Math.Clamp(value, 0, 2); + } + + public int Poison + { + get => m_Poison; + set => m_Poison = Math.Clamp(value, 0, 2); + } + + public int Disease + { + get => m_Disease; + set => m_Disease = Math.Clamp(value, 0, 2); + } + + public bool IsFullPoisonPotion => m_PoisonPotion >= 2; + + public int PoisonPotion + { + get => m_PoisonPotion; + set => m_PoisonPotion = Math.Clamp(value, 0, 2); + } + + public bool IsFullCurePotion => m_CurePotion >= 2; + + public int CurePotion + { + get => m_CurePotion; + set => m_CurePotion = Math.Clamp(value, 0, 2); + } + + public bool IsFullHealPotion => m_HealPotion >= 2; + + public int HealPotion + { + get => m_HealPotion; + set => m_HealPotion = Math.Clamp(value, 0, 2); + } + + public bool IsFullStrengthPotion => m_StrengthPotion >= 2; + + public int StrengthPotion + { + get => m_StrengthPotion; + set => m_StrengthPotion = Math.Clamp(value, 0, 2); + } + + public bool HasMaladies => Infestation > 0 || Fungus > 0 || Poison > 0 || Disease > 0 || Water != 2; + + public bool PollenProducing => Plant.IsCrossable && Plant.PlantStatus >= PlantStatus.FullGrownPlant; + + public bool Pollinated { get; set; } + + public PlantType SeedType + { + get => Pollinated ? m_SeedType : Plant.PlantType; + set => m_SeedType = value; + } + + public PlantHue SeedHue + { + get => Pollinated ? m_SeedHue : Plant.PlantHue; + set => m_SeedHue = value; + } + + public int AvailableSeeds + { + get => m_AvailableSeeds; + set + { + if (value >= 0) m_AvailableSeeds = value; + } + } + + public int LeftSeeds + { + get => m_LeftSeeds; + set + { + if (value >= 0) m_LeftSeeds = value; + } + } + + public int AvailableResources + { + get => m_AvailableResources; + set + { + if (value >= 0) m_AvailableResources = value; + } + } + + public int LeftResources + { + get => m_LeftResources; + set + { + if (value >= 0) m_LeftResources = value; + } + } + + public void Reset(bool potions) + { + NextGrowth = DateTime.UtcNow + CheckDelay; + GrowthIndicator = PlantGrowthIndicator.None; + + Hits = MaxHits; + m_Infestation = 0; + m_Fungus = 0; + m_Poison = 0; + m_Disease = 0; + + if (potions) + { + m_PoisonPotion = 0; + m_CurePotion = 0; + m_HealPotion = 0; + m_StrengthPotion = 0; + } + + Pollinated = false; + m_AvailableSeeds = 0; + m_LeftSeeds = 8; + + m_AvailableResources = 0; + m_LeftResources = 8; + } + + public int GetLocalizedDirtStatus() + { + if (Water <= 1) + return 1060826; // hard + if (Water <= 2) + return 1060827; // soft + if (Water <= 3) + return 1060828; // squishy + return 1060829; // sopping wet + } + + public int GetLocalizedHealth() + { + return Health switch + { + PlantHealth.Dying => 1060825, // dying + PlantHealth.Wilted => 1060824, // wilted + PlantHealth.Healthy => 1060823, // healthy + _ => 1060822 + }; + } + + public static void Configure() + { + EventSink.WorldLoad += EventSink_WorldLoad; + + if (!AutoRestart.Enabled) + EventSink.WorldSave += EventSink_WorldSave; + + EventSink.Login += EventSink_Login; + } + + private static void EventSink_Login(Mobile from) + { + from.Backpack?.FindItemsByType() + .ForEach( + plant => + { + if (plant.IsGrowable) + plant.PlantSystem.DoGrowthCheck(); + } + ); + + from.FindBankNoCreate() + ?.FindItemsByType() + .ForEach( + plant => + { + if (plant.IsGrowable) + plant.PlantSystem.DoGrowthCheck(); + } + ); + } + + public static void GrowAll() + { + var plants = PlantItem.Plants; + var now = DateTime.UtcNow; + + for (var i = plants.Count - 1; i >= 0; --i) + { + var plant = plants[i]; + + if (plant.IsGrowable && !(plant.RootParent is Mobile) && now >= plant.PlantSystem.NextGrowth) + plant.PlantSystem.DoGrowthCheck(); + } + } + + private static void EventSink_WorldLoad() + { + GrowAll(); + } + + private static void EventSink_WorldSave(bool message) + { + GrowAll(); + } + + public void DoGrowthCheck() + { + if (!Plant.IsGrowable) + return; + + if (DateTime.UtcNow < NextGrowth) + { + GrowthIndicator = PlantGrowthIndicator.Delay; + return; + } + + NextGrowth = DateTime.UtcNow + CheckDelay; + + if (!Plant.ValidGrowthLocation) + { + GrowthIndicator = PlantGrowthIndicator.InvalidLocation; + return; + } + + if (Plant.PlantStatus == PlantStatus.BowlOfDirt) + { + if (Water > 2 || Utility.RandomDouble() < 0.9) + Water--; + return; + } + + ApplyBeneficialEffects(); + + if (!ApplyMaladiesEffects()) // Dead + return; + + Grow(); + + UpdateMaladies(); + } + + private void ApplyBeneficialEffects() + { + if (PoisonPotion >= Infestation) + { + PoisonPotion -= Infestation; + Infestation = 0; + } + else + { + Infestation -= PoisonPotion; + PoisonPotion = 0; + } + + if (CurePotion >= Fungus) + { + CurePotion -= Fungus; + Fungus = 0; + } + else + { + Fungus -= CurePotion; + CurePotion = 0; + } + + if (HealPotion >= Poison) + { + HealPotion -= Poison; + Poison = 0; + } + else + { + Poison -= HealPotion; + HealPotion = 0; + } + + if (HealPotion >= Disease) + { + HealPotion -= Disease; + Disease = 0; + } + else + { + Disease -= HealPotion; + HealPotion = 0; + } + + if (!HasMaladies) + { + if (HealPotion > 0) + Hits += HealPotion * 7; + else + Hits += 2; + } + + HealPotion = 0; + } + + private bool ApplyMaladiesEffects() + { + var damage = 0; + + if (Infestation > 0) + damage += Infestation * Utility.RandomMinMax(3, 6); + + if (Fungus > 0) + damage += Fungus * Utility.RandomMinMax(3, 6); + + if (Poison > 0) + damage += Poison * Utility.RandomMinMax(3, 6); + + if (Disease > 0) + damage += Disease * Utility.RandomMinMax(3, 6); + + if (Water > 2) + damage += (Water - 2) * Utility.RandomMinMax(3, 6); + else if (Water < 2) + damage += (2 - Water) * Utility.RandomMinMax(3, 6); + + Hits -= damage; + + return Plant.IsGrowable && Plant.PlantStatus != PlantStatus.BowlOfDirt; + } + + private void Grow() + { + if (Health < PlantHealth.Healthy) + { + GrowthIndicator = PlantGrowthIndicator.NotHealthy; + } + else if (FertileDirt && Plant.PlantStatus <= PlantStatus.Stage5 && Utility.RandomDouble() < 0.1) + { + var curStage = (int)Plant.PlantStatus; + Plant.PlantStatus = (PlantStatus)(curStage + 2); + + GrowthIndicator = PlantGrowthIndicator.DoubleGrown; + } + else if (Plant.PlantStatus < PlantStatus.Stage9) + { + var curStage = (int)Plant.PlantStatus; + Plant.PlantStatus = (PlantStatus)(curStage + 1); + + GrowthIndicator = PlantGrowthIndicator.Grown; + } + else + { + if (Pollinated && LeftSeeds > 0 && Plant.Reproduces) + { + LeftSeeds--; + AvailableSeeds++; + } + + if (LeftResources > 0 && PlantResourceInfo.GetInfo(Plant.PlantType, Plant.PlantHue) != null) + { + LeftResources--; + AvailableResources++; + } + + GrowthIndicator = PlantGrowthIndicator.Grown; + } + + if (Plant.PlantStatus >= PlantStatus.Stage9 && !Pollinated) + { + Pollinated = true; + SeedType = Plant.PlantType; + SeedHue = Plant.PlantHue; + } + } + + private void UpdateMaladies() + { + var infestationChance = 0.30 - StrengthPotion * 0.075 + (Water - 2) * 0.10; + + var typeInfo = PlantTypeInfo.GetInfo(Plant.PlantType); + if (typeInfo.Flowery) + infestationChance += 0.10; + + if (PlantHueInfo.IsBright(Plant.PlantHue)) + infestationChance += 0.10; + + if (Utility.RandomDouble() < infestationChance) + Infestation++; + + var fungusChance = 0.15 - StrengthPotion * 0.075 + (Water - 2) * 0.10; + + if (Utility.RandomDouble() < fungusChance) + Fungus++; + + if (Water > 2 || Utility.RandomDouble() < 0.9) + Water--; + + if (PoisonPotion > 0) + { + Poison += PoisonPotion; + PoisonPotion = 0; + } + + if (CurePotion > 0) + { + Disease += CurePotion; + CurePotion = 0; + } + + StrengthPotion = 0; + } + + public void Save(IGenericWriter writer) + { + writer.Write(2); // version + + writer.Write(FertileDirt); + + writer.Write(NextGrowth); + writer.Write((int)GrowthIndicator); + + writer.Write(m_Water); + + writer.Write(m_Hits); + writer.Write(m_Infestation); + writer.Write(m_Fungus); + writer.Write(m_Poison); + writer.Write(m_Disease); + writer.Write(m_PoisonPotion); + writer.Write(m_CurePotion); + writer.Write(m_HealPotion); + writer.Write(m_StrengthPotion); + + writer.Write(Pollinated); + writer.Write((int)m_SeedType); + writer.Write((int)m_SeedHue); + writer.Write(m_AvailableSeeds); + writer.Write(m_LeftSeeds); + + writer.Write(m_AvailableResources); + writer.Write(m_LeftResources); + } + } +} diff --git a/Projects/UOContent/Engines/Plants/PlantType.cs b/Projects/UOContent/Engines/Plants/PlantType.cs index 089ed4353..7aec8f538 100644 --- a/Projects/UOContent/Engines/Plants/PlantType.cs +++ b/Projects/UOContent/Engines/Plants/PlantType.cs @@ -1,359 +1,436 @@ -namespace Server.Engines.Plants -{ - public enum PlantType - { - CampionFlowers, - Poppies, - Snowdrops, - Bulrushes, - Lilies, - PampasGrass, - Rushes, - ElephantEarPlant, - Fern, - PonytailPalm, - SmallPalm, - CenturyPlant, - WaterPlant, - SnakePlant, - PricklyPearCactus, - BarrelCactus, - TribarrelCactus, - CommonGreenBonsai, - CommonPinkBonsai, - UncommonGreenBonsai, - UncommonPinkBonsai, - RareGreenBonsai, - RarePinkBonsai, - ExceptionalBonsai, - ExoticBonsai, - Cactus, - FlaxFlowers, - FoxgloveFlowers, - HopsEast, - OrfluerFlowers, - CypressTwisted, - HedgeShort, - JuniperBush, - SnowdropPatch, - Cattails, - PoppyPatch, - SpiderTree, - WaterLily, - CypressStraight, - HedgeTall, - HopsSouth, - SugarCanes, - CocoaTree - } - - public enum PlantCategory - { - Default, - Common = 1063335, // - Uncommon = 1063336, // - Rare = 1063337, // Bonsai - Exceptional = 1063341, // - Exotic = 1063342, // - Peculiar = 1080528, - Fragrant = 1080529 - } - - public class PlantTypeInfo - { - private static readonly PlantTypeInfo[] m_Table = - { - new PlantTypeInfo(0xC83, 0, 0, PlantType.CampionFlowers, false, true, true, true, PlantCategory.Default), - new PlantTypeInfo(0xC86, 0, 0, PlantType.Poppies, false, true, true, true, PlantCategory.Default), - new PlantTypeInfo(0xC88, 0, 10, PlantType.Snowdrops, false, true, true, true, PlantCategory.Default), - new PlantTypeInfo(0xC94, -15, 0, PlantType.Bulrushes, false, true, true, true, PlantCategory.Default), - new PlantTypeInfo(0xC8B, 0, 0, PlantType.Lilies, false, true, true, true, PlantCategory.Default), - new PlantTypeInfo(0xCA5, -8, 0, PlantType.PampasGrass, false, true, true, true, PlantCategory.Default), - new PlantTypeInfo(0xCA7, -10, 0, PlantType.Rushes, false, true, true, true, PlantCategory.Default), - new PlantTypeInfo(0xC97, -20, 0, PlantType.ElephantEarPlant, true, false, true, true, PlantCategory.Default), - new PlantTypeInfo(0xC9F, -20, 0, PlantType.Fern, false, false, true, true, PlantCategory.Default), - new PlantTypeInfo(0xCA6, -16, -5, PlantType.PonytailPalm, false, false, true, true, PlantCategory.Default), - new PlantTypeInfo(0xC9C, -5, -10, PlantType.SmallPalm, false, false, true, true, PlantCategory.Default), - new PlantTypeInfo(0xD31, 0, -27, PlantType.CenturyPlant, true, false, true, true, PlantCategory.Default), - new PlantTypeInfo(0xD04, 0, 10, PlantType.WaterPlant, true, false, true, true, PlantCategory.Default), - new PlantTypeInfo(0xCA9, 0, 0, PlantType.SnakePlant, true, false, true, true, PlantCategory.Default), - new PlantTypeInfo(0xD2C, 0, 10, PlantType.PricklyPearCactus, false, false, true, true, PlantCategory.Default), - new PlantTypeInfo(0xD26, 0, 10, PlantType.BarrelCactus, false, false, true, true, PlantCategory.Default), - new PlantTypeInfo(0xD27, 0, 10, PlantType.TribarrelCactus, false, false, true, true, PlantCategory.Default), - new PlantTypeInfo(0x28DC, -5, 5, PlantType.CommonGreenBonsai, true, false, false, false, PlantCategory.Common), - new PlantTypeInfo(0x28DF, -5, 5, PlantType.CommonPinkBonsai, true, false, false, false, PlantCategory.Common), - new PlantTypeInfo(0x28DD, -5, 5, PlantType.UncommonGreenBonsai, true, false, false, false, - PlantCategory.Uncommon), - new PlantTypeInfo(0x28E0, -5, 5, PlantType.UncommonPinkBonsai, true, false, false, false, - PlantCategory.Uncommon), - new PlantTypeInfo(0x28DE, -5, 5, PlantType.RareGreenBonsai, true, false, false, false, PlantCategory.Rare), - new PlantTypeInfo(0x28E1, -5, 5, PlantType.RarePinkBonsai, true, false, false, false, PlantCategory.Rare), - new PlantTypeInfo(0x28E2, -5, 5, PlantType.ExceptionalBonsai, true, false, false, false, - PlantCategory.Exceptional), - new PlantTypeInfo(0x28E3, -5, 5, PlantType.ExoticBonsai, true, false, false, false, PlantCategory.Exotic), - new PlantTypeInfo(0x0D25, 0, 0, PlantType.Cactus, false, false, false, false, PlantCategory.Peculiar), - new PlantTypeInfo(0x1A9A, 5, 10, PlantType.FlaxFlowers, false, true, false, false, PlantCategory.Peculiar), - new PlantTypeInfo(0x0C84, 0, 0, PlantType.FoxgloveFlowers, false, true, false, false, PlantCategory.Peculiar), - new PlantTypeInfo(0x1A9F, 5, -25, PlantType.HopsEast, false, false, false, false, PlantCategory.Peculiar), - new PlantTypeInfo(0x0CC1, 0, 0, PlantType.OrfluerFlowers, false, true, false, false, PlantCategory.Peculiar), - new PlantTypeInfo(0x0CFE, -45, -30, PlantType.CypressTwisted, false, false, false, false, - PlantCategory.Peculiar), - new PlantTypeInfo(0x0C8F, 0, 0, PlantType.HedgeShort, false, false, false, false, PlantCategory.Peculiar), - new PlantTypeInfo(0x0CC8, 0, 0, PlantType.JuniperBush, true, false, false, false, PlantCategory.Peculiar), - new PlantTypeInfo(0x0C8E, -20, 0, PlantType.SnowdropPatch, false, true, false, false, PlantCategory.Peculiar), - new PlantTypeInfo(0x0CB7, 0, 0, PlantType.Cattails, false, false, false, false, PlantCategory.Peculiar), - new PlantTypeInfo(0x0CBE, -20, 0, PlantType.PoppyPatch, false, true, false, false, PlantCategory.Peculiar), - new PlantTypeInfo(0x0CC9, 0, 0, PlantType.SpiderTree, false, false, false, false, PlantCategory.Peculiar), - new PlantTypeInfo(0x0DC1, -5, 15, PlantType.WaterLily, false, true, false, false, PlantCategory.Peculiar), - new PlantTypeInfo(0x0CFB, -45, -30, PlantType.CypressStraight, false, false, false, false, - PlantCategory.Peculiar), - new PlantTypeInfo(0x0DB8, 0, -20, PlantType.HedgeTall, false, false, false, false, PlantCategory.Peculiar), - new PlantTypeInfo(0x1AA1, 10, -25, PlantType.HopsSouth, false, false, false, false, PlantCategory.Peculiar), - new PlantTypeInfo(0x246C, -25, -20, PlantType.SugarCanes, false, false, false, false, PlantCategory.Peculiar, - 1114898, 1114898, 1094702, 1094703, 1095221, 1113715), - new PlantTypeInfo(0xC9E, -40, -30, PlantType.CocoaTree, false, false, false, true, PlantCategory.Fragrant, - 1080536, 1080536, 1080534, 1080531, 1080533, 1113716) - }; - - private readonly int m_PlantLabelDecorative; - private readonly int m_PlantLabelFullGrown; - private readonly int m_PlantLabelPlant; - - // Cliloc overrides - private readonly int m_PlantLabelSeed; - private readonly int m_SeedLabel; - private readonly int m_SeedLabelPlural; - - private PlantTypeInfo(int itemID, int offsetX, int offsetY, PlantType plantType, bool containsPlant, bool flowery, - bool crossable, bool reproduces, PlantCategory plantCategory, int plantLabelSeed = -1, int plantLabelPlant = -1, - int plantLabelFullGrown = -1, int plantLabelDecorative = -1, int seedLabel = -1, int seedLabelPlural = -1) - { - ItemID = itemID; - OffsetX = offsetX; - OffsetY = offsetY; - PlantType = plantType; - ContainsPlant = containsPlant; - Flowery = flowery; - Crossable = crossable; - Reproduces = reproduces; - PlantCategory = plantCategory; - m_PlantLabelSeed = plantLabelSeed; - m_PlantLabelPlant = plantLabelPlant; - m_PlantLabelFullGrown = plantLabelFullGrown; - m_PlantLabelDecorative = plantLabelDecorative; - m_SeedLabel = seedLabel; - m_SeedLabelPlural = seedLabelPlural; - } - - public int ItemID { get; } - - public int OffsetX { get; } - - public int OffsetY { get; } - - public PlantType PlantType { get; } - - public PlantCategory PlantCategory { get; } - - public int Name => ItemID < 0x4000 ? 1020000 + ItemID : 1078872 + ItemID; - - public bool ContainsPlant { get; } - - public bool Flowery { get; } - - public bool Crossable { get; } - - public bool Reproduces { get; } - - public static PlantTypeInfo GetInfo(PlantType plantType) - { - int index = (int)plantType; - - if (index >= 0 && index < m_Table.Length) - return m_Table[index]; - return m_Table[0]; - } - - public static PlantType RandomFirstGeneration() - { - return Utility.Random(3) switch - { - 0 => PlantType.CampionFlowers, - 1 => PlantType.Fern, - _ => PlantType.TribarrelCactus - }; - } - - public static PlantType RandomPeculiarGroupOne() - { - return Utility.Random(6) switch - { - 0 => PlantType.Cactus, - 1 => PlantType.FlaxFlowers, - 2 => PlantType.FoxgloveFlowers, - 3 => PlantType.HopsEast, - 4 => PlantType.CocoaTree, - _ => PlantType.OrfluerFlowers - }; - } - - public static PlantType RandomPeculiarGroupTwo() - { - return Utility.Random(5) switch - { - 0 => PlantType.CypressTwisted, - 1 => PlantType.HedgeShort, - 2 => PlantType.JuniperBush, - 3 => PlantType.CocoaTree, - _ => PlantType.SnowdropPatch - }; - } - - public static PlantType RandomPeculiarGroupThree() - { - return Utility.Random(5) switch - { - 0 => PlantType.Cattails, - 1 => PlantType.PoppyPatch, - 2 => PlantType.SpiderTree, - 3 => PlantType.CocoaTree, - _ => PlantType.WaterLily - }; - } - - public static PlantType RandomPeculiarGroupFour() - { - return Utility.Random(5) switch - { - 0 => PlantType.CypressStraight, - 1 => PlantType.HedgeTall, - 2 => PlantType.HopsSouth, - 3 => PlantType.CocoaTree, - _ => PlantType.SugarCanes - }; - } - - public static PlantType RandomBonsai(double increaseRatio) - { - /* Chances of each plant type are equal to the chances of the previous plant type * increaseRatio: - * E.g.: - * chances_of_uncommon = chances_of_common * increaseRatio - * chances_of_rare = chances_of_uncommon * increaseRatio - * ... - * - * If increaseRatio < 1 -> rare plants are actually rarer than the others - * If increaseRatio > 1 -> rare plants are actually more common than the others (it might be the case with certain monsters) - * - * If a plant type (common, uncommon, ...) has 2 different colors, they have the same chances: - * chances_of_green_common = chances_of_pink_common = chances_of_common / 2 - * ... - */ - - double k1 = increaseRatio >= 0.0 ? increaseRatio : 0.0; - double k2 = k1 * k1; - double k3 = k2 * k1; - double k4 = k3 * k1; - - double exp1 = k1 + 1.0; - double exp2 = k2 + exp1; - double exp3 = k3 + exp2; - double exp4 = k4 + exp3; - - double rand = Utility.RandomDouble(); - - if (rand < 0.5 / exp4) - return PlantType.CommonGreenBonsai; - if (rand < 1.0 / exp4) - return PlantType.CommonPinkBonsai; - if (rand < (k1 * 0.5 + 1.0) / exp4) - return PlantType.UncommonGreenBonsai; - if (rand < exp1 / exp4) - return PlantType.UncommonPinkBonsai; - if (rand < (k2 * 0.5 + exp1) / exp4) - return PlantType.RareGreenBonsai; - if (rand < exp2 / exp4) - return PlantType.RarePinkBonsai; - if (rand < exp3 / exp4) - return PlantType.ExceptionalBonsai; - return PlantType.ExoticBonsai; - } - - public static bool IsCrossable(PlantType plantType) => GetInfo(plantType).Crossable; - - public static PlantType Cross(PlantType first, PlantType second) - { - if (!IsCrossable(first) || !IsCrossable(second)) - return PlantType.CampionFlowers; - - int firstIndex = (int)first; - int secondIndex = (int)second; - - if (firstIndex + 1 == secondIndex || firstIndex == secondIndex + 1) - return Utility.RandomBool() ? first : second; - return (PlantType)((firstIndex + secondIndex) / 2); - } - - public static bool CanReproduce(PlantType plantType) => GetInfo(plantType).Reproduces; - - public int GetPlantLabelSeed(PlantHueInfo hueInfo) - { - if (m_PlantLabelSeed != -1) - return m_PlantLabelSeed; - - return - hueInfo.IsBright() - ? 1061887 - : 1061888; // a ~1_val~ of ~2_val~ dirt with a ~3_val~ [bright] ~4_val~ ~5_val~ ~6_val~ - } - - public int GetPlantLabelPlant(PlantHueInfo hueInfo) - { - if (m_PlantLabelPlant != -1) - return m_PlantLabelPlant; - - if (ContainsPlant) - return - hueInfo.IsBright() - ? 1060832 - : 1060831; // a ~1_val~ of ~2_val~ dirt with a ~3_val~ [bright] ~4_val~ ~5_val~ - return - hueInfo.IsBright() - ? 1061887 - : 1061888; // a ~1_val~ of ~2_val~ dirt with a ~3_val~ [bright] ~4_val~ ~5_val~ ~6_val~ - } - - public int GetPlantLabelFullGrown(PlantHueInfo hueInfo) - { - if (m_PlantLabelFullGrown != -1) - return m_PlantLabelFullGrown; - - if (ContainsPlant) - return hueInfo.IsBright() ? 1061891 : 1061889; // a ~1_HEALTH~ [bright] ~2_COLOR~ ~3_NAME~ - return hueInfo.IsBright() ? 1061892 : 1061890; // a ~1_HEALTH~ [bright] ~2_COLOR~ ~3_NAME~ plant - } - - public int GetPlantLabelDecorative(PlantHueInfo hueInfo) - { - if (m_PlantLabelDecorative != -1) - return m_PlantLabelDecorative; - - return hueInfo.IsBright() ? 1074267 : 1070973; // a decorative [bright] ~1_COLOR~ ~2_TYPE~ - } - - public int GetSeedLabel(PlantHueInfo hueInfo) - { - if (m_SeedLabel != -1) - return m_SeedLabel; - - return hueInfo.IsBright() ? 1061918 : 1061917; // [bright] ~1_COLOR~ ~2_TYPE~ seed - } - - public int GetSeedLabelPlural(PlantHueInfo hueInfo) - { - if (m_SeedLabelPlural != -1) - return m_SeedLabelPlural; - - return hueInfo.IsBright() ? 1113493 : 1113492; // ~1_amount~ [bright] ~2_color~ ~3_type~ seeds - } - } -} \ No newline at end of file +namespace Server.Engines.Plants +{ + public enum PlantType + { + CampionFlowers, + Poppies, + Snowdrops, + Bulrushes, + Lilies, + PampasGrass, + Rushes, + ElephantEarPlant, + Fern, + PonytailPalm, + SmallPalm, + CenturyPlant, + WaterPlant, + SnakePlant, + PricklyPearCactus, + BarrelCactus, + TribarrelCactus, + CommonGreenBonsai, + CommonPinkBonsai, + UncommonGreenBonsai, + UncommonPinkBonsai, + RareGreenBonsai, + RarePinkBonsai, + ExceptionalBonsai, + ExoticBonsai, + Cactus, + FlaxFlowers, + FoxgloveFlowers, + HopsEast, + OrfluerFlowers, + CypressTwisted, + HedgeShort, + JuniperBush, + SnowdropPatch, + Cattails, + PoppyPatch, + SpiderTree, + WaterLily, + CypressStraight, + HedgeTall, + HopsSouth, + SugarCanes, + CocoaTree + } + + public enum PlantCategory + { + Default, + Common = 1063335, // + Uncommon = 1063336, // + Rare = 1063337, // Bonsai + Exceptional = 1063341, // + Exotic = 1063342, // + Peculiar = 1080528, + Fragrant = 1080529 + } + + public class PlantTypeInfo + { + private static readonly PlantTypeInfo[] m_Table = + { + new PlantTypeInfo(0xC83, 0, 0, PlantType.CampionFlowers, false, true, true, true, PlantCategory.Default), + new PlantTypeInfo(0xC86, 0, 0, PlantType.Poppies, false, true, true, true, PlantCategory.Default), + new PlantTypeInfo(0xC88, 0, 10, PlantType.Snowdrops, false, true, true, true, PlantCategory.Default), + new PlantTypeInfo(0xC94, -15, 0, PlantType.Bulrushes, false, true, true, true, PlantCategory.Default), + new PlantTypeInfo(0xC8B, 0, 0, PlantType.Lilies, false, true, true, true, PlantCategory.Default), + new PlantTypeInfo(0xCA5, -8, 0, PlantType.PampasGrass, false, true, true, true, PlantCategory.Default), + new PlantTypeInfo(0xCA7, -10, 0, PlantType.Rushes, false, true, true, true, PlantCategory.Default), + new PlantTypeInfo(0xC97, -20, 0, PlantType.ElephantEarPlant, true, false, true, true, PlantCategory.Default), + new PlantTypeInfo(0xC9F, -20, 0, PlantType.Fern, false, false, true, true, PlantCategory.Default), + new PlantTypeInfo(0xCA6, -16, -5, PlantType.PonytailPalm, false, false, true, true, PlantCategory.Default), + new PlantTypeInfo(0xC9C, -5, -10, PlantType.SmallPalm, false, false, true, true, PlantCategory.Default), + new PlantTypeInfo(0xD31, 0, -27, PlantType.CenturyPlant, true, false, true, true, PlantCategory.Default), + new PlantTypeInfo(0xD04, 0, 10, PlantType.WaterPlant, true, false, true, true, PlantCategory.Default), + new PlantTypeInfo(0xCA9, 0, 0, PlantType.SnakePlant, true, false, true, true, PlantCategory.Default), + new PlantTypeInfo(0xD2C, 0, 10, PlantType.PricklyPearCactus, false, false, true, true, PlantCategory.Default), + new PlantTypeInfo(0xD26, 0, 10, PlantType.BarrelCactus, false, false, true, true, PlantCategory.Default), + new PlantTypeInfo(0xD27, 0, 10, PlantType.TribarrelCactus, false, false, true, true, PlantCategory.Default), + new PlantTypeInfo(0x28DC, -5, 5, PlantType.CommonGreenBonsai, true, false, false, false, PlantCategory.Common), + new PlantTypeInfo(0x28DF, -5, 5, PlantType.CommonPinkBonsai, true, false, false, false, PlantCategory.Common), + new PlantTypeInfo( + 0x28DD, + -5, + 5, + PlantType.UncommonGreenBonsai, + true, + false, + false, + false, + PlantCategory.Uncommon + ), + new PlantTypeInfo( + 0x28E0, + -5, + 5, + PlantType.UncommonPinkBonsai, + true, + false, + false, + false, + PlantCategory.Uncommon + ), + new PlantTypeInfo(0x28DE, -5, 5, PlantType.RareGreenBonsai, true, false, false, false, PlantCategory.Rare), + new PlantTypeInfo(0x28E1, -5, 5, PlantType.RarePinkBonsai, true, false, false, false, PlantCategory.Rare), + new PlantTypeInfo( + 0x28E2, + -5, + 5, + PlantType.ExceptionalBonsai, + true, + false, + false, + false, + PlantCategory.Exceptional + ), + new PlantTypeInfo(0x28E3, -5, 5, PlantType.ExoticBonsai, true, false, false, false, PlantCategory.Exotic), + new PlantTypeInfo(0x0D25, 0, 0, PlantType.Cactus, false, false, false, false, PlantCategory.Peculiar), + new PlantTypeInfo(0x1A9A, 5, 10, PlantType.FlaxFlowers, false, true, false, false, PlantCategory.Peculiar), + new PlantTypeInfo(0x0C84, 0, 0, PlantType.FoxgloveFlowers, false, true, false, false, PlantCategory.Peculiar), + new PlantTypeInfo(0x1A9F, 5, -25, PlantType.HopsEast, false, false, false, false, PlantCategory.Peculiar), + new PlantTypeInfo(0x0CC1, 0, 0, PlantType.OrfluerFlowers, false, true, false, false, PlantCategory.Peculiar), + new PlantTypeInfo( + 0x0CFE, + -45, + -30, + PlantType.CypressTwisted, + false, + false, + false, + false, + PlantCategory.Peculiar + ), + new PlantTypeInfo(0x0C8F, 0, 0, PlantType.HedgeShort, false, false, false, false, PlantCategory.Peculiar), + new PlantTypeInfo(0x0CC8, 0, 0, PlantType.JuniperBush, true, false, false, false, PlantCategory.Peculiar), + new PlantTypeInfo(0x0C8E, -20, 0, PlantType.SnowdropPatch, false, true, false, false, PlantCategory.Peculiar), + new PlantTypeInfo(0x0CB7, 0, 0, PlantType.Cattails, false, false, false, false, PlantCategory.Peculiar), + new PlantTypeInfo(0x0CBE, -20, 0, PlantType.PoppyPatch, false, true, false, false, PlantCategory.Peculiar), + new PlantTypeInfo(0x0CC9, 0, 0, PlantType.SpiderTree, false, false, false, false, PlantCategory.Peculiar), + new PlantTypeInfo(0x0DC1, -5, 15, PlantType.WaterLily, false, true, false, false, PlantCategory.Peculiar), + new PlantTypeInfo( + 0x0CFB, + -45, + -30, + PlantType.CypressStraight, + false, + false, + false, + false, + PlantCategory.Peculiar + ), + new PlantTypeInfo(0x0DB8, 0, -20, PlantType.HedgeTall, false, false, false, false, PlantCategory.Peculiar), + new PlantTypeInfo(0x1AA1, 10, -25, PlantType.HopsSouth, false, false, false, false, PlantCategory.Peculiar), + new PlantTypeInfo( + 0x246C, + -25, + -20, + PlantType.SugarCanes, + false, + false, + false, + false, + PlantCategory.Peculiar, + 1114898, + 1114898, + 1094702, + 1094703, + 1095221, + 1113715 + ), + new PlantTypeInfo( + 0xC9E, + -40, + -30, + PlantType.CocoaTree, + false, + false, + false, + true, + PlantCategory.Fragrant, + 1080536, + 1080536, + 1080534, + 1080531, + 1080533, + 1113716 + ) + }; + + private readonly int m_PlantLabelDecorative; + private readonly int m_PlantLabelFullGrown; + private readonly int m_PlantLabelPlant; + + // Cliloc overrides + private readonly int m_PlantLabelSeed; + private readonly int m_SeedLabel; + private readonly int m_SeedLabelPlural; + + private PlantTypeInfo( + int itemID, int offsetX, int offsetY, PlantType plantType, bool containsPlant, bool flowery, + bool crossable, bool reproduces, PlantCategory plantCategory, int plantLabelSeed = -1, int plantLabelPlant = -1, + int plantLabelFullGrown = -1, int plantLabelDecorative = -1, int seedLabel = -1, int seedLabelPlural = -1 + ) + { + ItemID = itemID; + OffsetX = offsetX; + OffsetY = offsetY; + PlantType = plantType; + ContainsPlant = containsPlant; + Flowery = flowery; + Crossable = crossable; + Reproduces = reproduces; + PlantCategory = plantCategory; + m_PlantLabelSeed = plantLabelSeed; + m_PlantLabelPlant = plantLabelPlant; + m_PlantLabelFullGrown = plantLabelFullGrown; + m_PlantLabelDecorative = plantLabelDecorative; + m_SeedLabel = seedLabel; + m_SeedLabelPlural = seedLabelPlural; + } + + public int ItemID { get; } + + public int OffsetX { get; } + + public int OffsetY { get; } + + public PlantType PlantType { get; } + + public PlantCategory PlantCategory { get; } + + public int Name => ItemID < 0x4000 ? 1020000 + ItemID : 1078872 + ItemID; + + public bool ContainsPlant { get; } + + public bool Flowery { get; } + + public bool Crossable { get; } + + public bool Reproduces { get; } + + public static PlantTypeInfo GetInfo(PlantType plantType) + { + var index = (int)plantType; + + if (index >= 0 && index < m_Table.Length) + return m_Table[index]; + return m_Table[0]; + } + + public static PlantType RandomFirstGeneration() + { + return Utility.Random(3) switch + { + 0 => PlantType.CampionFlowers, + 1 => PlantType.Fern, + _ => PlantType.TribarrelCactus + }; + } + + public static PlantType RandomPeculiarGroupOne() + { + return Utility.Random(6) switch + { + 0 => PlantType.Cactus, + 1 => PlantType.FlaxFlowers, + 2 => PlantType.FoxgloveFlowers, + 3 => PlantType.HopsEast, + 4 => PlantType.CocoaTree, + _ => PlantType.OrfluerFlowers + }; + } + + public static PlantType RandomPeculiarGroupTwo() + { + return Utility.Random(5) switch + { + 0 => PlantType.CypressTwisted, + 1 => PlantType.HedgeShort, + 2 => PlantType.JuniperBush, + 3 => PlantType.CocoaTree, + _ => PlantType.SnowdropPatch + }; + } + + public static PlantType RandomPeculiarGroupThree() + { + return Utility.Random(5) switch + { + 0 => PlantType.Cattails, + 1 => PlantType.PoppyPatch, + 2 => PlantType.SpiderTree, + 3 => PlantType.CocoaTree, + _ => PlantType.WaterLily + }; + } + + public static PlantType RandomPeculiarGroupFour() + { + return Utility.Random(5) switch + { + 0 => PlantType.CypressStraight, + 1 => PlantType.HedgeTall, + 2 => PlantType.HopsSouth, + 3 => PlantType.CocoaTree, + _ => PlantType.SugarCanes + }; + } + + public static PlantType RandomBonsai(double increaseRatio) + { + /* Chances of each plant type are equal to the chances of the previous plant type * increaseRatio: + * E.g.: + * chances_of_uncommon = chances_of_common * increaseRatio + * chances_of_rare = chances_of_uncommon * increaseRatio + * ... + * + * If increaseRatio < 1 -> rare plants are actually rarer than the others + * If increaseRatio > 1 -> rare plants are actually more common than the others (it might be the case with certain monsters) + * + * If a plant type (common, uncommon, ...) has 2 different colors, they have the same chances: + * chances_of_green_common = chances_of_pink_common = chances_of_common / 2 + * ... + */ + + var k1 = increaseRatio >= 0.0 ? increaseRatio : 0.0; + var k2 = k1 * k1; + var k3 = k2 * k1; + var k4 = k3 * k1; + + var exp1 = k1 + 1.0; + var exp2 = k2 + exp1; + var exp3 = k3 + exp2; + var exp4 = k4 + exp3; + + var rand = Utility.RandomDouble(); + + if (rand < 0.5 / exp4) + return PlantType.CommonGreenBonsai; + if (rand < 1.0 / exp4) + return PlantType.CommonPinkBonsai; + if (rand < (k1 * 0.5 + 1.0) / exp4) + return PlantType.UncommonGreenBonsai; + if (rand < exp1 / exp4) + return PlantType.UncommonPinkBonsai; + if (rand < (k2 * 0.5 + exp1) / exp4) + return PlantType.RareGreenBonsai; + if (rand < exp2 / exp4) + return PlantType.RarePinkBonsai; + if (rand < exp3 / exp4) + return PlantType.ExceptionalBonsai; + return PlantType.ExoticBonsai; + } + + public static bool IsCrossable(PlantType plantType) => GetInfo(plantType).Crossable; + + public static PlantType Cross(PlantType first, PlantType second) + { + if (!IsCrossable(first) || !IsCrossable(second)) + return PlantType.CampionFlowers; + + var firstIndex = (int)first; + var secondIndex = (int)second; + + if (firstIndex + 1 == secondIndex || firstIndex == secondIndex + 1) + return Utility.RandomBool() ? first : second; + return (PlantType)((firstIndex + secondIndex) / 2); + } + + public static bool CanReproduce(PlantType plantType) => GetInfo(plantType).Reproduces; + + public int GetPlantLabelSeed(PlantHueInfo hueInfo) + { + if (m_PlantLabelSeed != -1) + return m_PlantLabelSeed; + + return + hueInfo.IsBright() + ? 1061887 + : 1061888; // a ~1_val~ of ~2_val~ dirt with a ~3_val~ [bright] ~4_val~ ~5_val~ ~6_val~ + } + + public int GetPlantLabelPlant(PlantHueInfo hueInfo) + { + if (m_PlantLabelPlant != -1) + return m_PlantLabelPlant; + + if (ContainsPlant) + return + hueInfo.IsBright() + ? 1060832 + : 1060831; // a ~1_val~ of ~2_val~ dirt with a ~3_val~ [bright] ~4_val~ ~5_val~ + return + hueInfo.IsBright() + ? 1061887 + : 1061888; // a ~1_val~ of ~2_val~ dirt with a ~3_val~ [bright] ~4_val~ ~5_val~ ~6_val~ + } + + public int GetPlantLabelFullGrown(PlantHueInfo hueInfo) + { + if (m_PlantLabelFullGrown != -1) + return m_PlantLabelFullGrown; + + if (ContainsPlant) + return hueInfo.IsBright() ? 1061891 : 1061889; // a ~1_HEALTH~ [bright] ~2_COLOR~ ~3_NAME~ + return hueInfo.IsBright() ? 1061892 : 1061890; // a ~1_HEALTH~ [bright] ~2_COLOR~ ~3_NAME~ plant + } + + public int GetPlantLabelDecorative(PlantHueInfo hueInfo) + { + if (m_PlantLabelDecorative != -1) + return m_PlantLabelDecorative; + + return hueInfo.IsBright() ? 1074267 : 1070973; // a decorative [bright] ~1_COLOR~ ~2_TYPE~ + } + + public int GetSeedLabel(PlantHueInfo hueInfo) + { + if (m_SeedLabel != -1) + return m_SeedLabel; + + return hueInfo.IsBright() ? 1061918 : 1061917; // [bright] ~1_COLOR~ ~2_TYPE~ seed + } + + public int GetSeedLabelPlural(PlantHueInfo hueInfo) + { + if (m_SeedLabelPlural != -1) + return m_SeedLabelPlural; + + return hueInfo.IsBright() ? 1113493 : 1113492; // ~1_amount~ [bright] ~2_color~ ~3_type~ seeds + } + } +} diff --git a/Projects/UOContent/Engines/Plants/PollinateTarget.cs b/Projects/UOContent/Engines/Plants/PollinateTarget.cs index 43b5ce371..026aeb8b9 100644 --- a/Projects/UOContent/Engines/Plants/PollinateTarget.cs +++ b/Projects/UOContent/Engines/Plants/PollinateTarget.cs @@ -1,88 +1,92 @@ -using Server.Targeting; - -namespace Server.Engines.Plants -{ - public class PollinateTarget : Target - { - private readonly PlantItem m_Plant; - - public PollinateTarget(PlantItem plant) : base(3, true, TargetFlags.None) => m_Plant = plant; - - protected override void OnTarget(Mobile from, object targeted) - { - if (!m_Plant.Deleted && m_Plant.PlantStatus < PlantStatus.DecorativePlant && - from.InRange(m_Plant.GetWorldLocation(), 3)) - { - if (!m_Plant.IsUsableBy(from)) - { - m_Plant.LabelTo(from, - 1061856); // You must have the item in your backpack or locked down in order to use it. - } - else if (!m_Plant.IsCrossable) - { - m_Plant.LabelTo(from, 1053050); // You cannot gather pollen from a mutated plant! - } - else if (!m_Plant.PlantSystem.PollenProducing) - { - m_Plant.LabelTo(from, 1053051); // You cannot gather pollen from a plant in this stage of development! - } - else if (m_Plant.PlantSystem.Health < PlantHealth.Healthy) - { - m_Plant.LabelTo(from, 1053052); // You cannot gather pollen from an unhealthy plant! - } - else - { - if (!(targeted is PlantItem targ) || targ.PlantStatus >= PlantStatus.DecorativePlant || - targ.PlantStatus <= PlantStatus.BowlOfDirt) - { - m_Plant.LabelTo(from, 1053070); // You can only pollinate other specially grown plants! - } - else if (!targ.IsUsableBy(from)) - { - targ.LabelTo(from, - 1061856); // You must have the item in your backpack or locked down in order to use it. - } - else if (!targ.IsCrossable) - { - targ.LabelTo(from, 1053073); // You cannot cross-pollinate with a mutated plant! - } - else if (!targ.PlantSystem.PollenProducing) - { - targ.LabelTo(from, 1053074); // This plant is not in the flowering stage. You cannot pollinate it! - } - else if (targ.PlantSystem.Health < PlantHealth.Healthy) - { - targ.LabelTo(from, 1053075); // You cannot pollinate an unhealthy plant! - } - else if (targ.PlantSystem.Pollinated) - { - targ.LabelTo(from, 1053072); // This plant has already been pollinated! - } - else if (targ == m_Plant) - { - targ.PlantSystem.Pollinated = true; - targ.PlantSystem.SeedType = m_Plant.PlantType; - targ.PlantSystem.SeedHue = m_Plant.PlantHue; - - targ.LabelTo(from, 1053071); // You pollinate the plant with its own pollen. - } - else - { - targ.PlantSystem.Pollinated = true; - targ.PlantSystem.SeedType = PlantTypeInfo.Cross(m_Plant.PlantType, targ.PlantType); - targ.PlantSystem.SeedHue = PlantHueInfo.Cross(m_Plant.PlantHue, targ.PlantHue); - - targ.LabelTo(from, 1053076); // You successfully cross-pollinate the plant. - } - } - } - } - - protected override void OnTargetFinish(Mobile from) - { - if (!m_Plant.Deleted && m_Plant.PlantStatus < PlantStatus.DecorativePlant && - m_Plant.PlantStatus != PlantStatus.BowlOfDirt && from.InRange(m_Plant.GetWorldLocation(), 3) && - m_Plant.IsUsableBy(from)) from.SendGump(new ReproductionGump(m_Plant)); - } - } -} \ No newline at end of file +using Server.Targeting; + +namespace Server.Engines.Plants +{ + public class PollinateTarget : Target + { + private readonly PlantItem m_Plant; + + public PollinateTarget(PlantItem plant) : base(3, true, TargetFlags.None) => m_Plant = plant; + + protected override void OnTarget(Mobile from, object targeted) + { + if (!m_Plant.Deleted && m_Plant.PlantStatus < PlantStatus.DecorativePlant && + from.InRange(m_Plant.GetWorldLocation(), 3)) + { + if (!m_Plant.IsUsableBy(from)) + { + m_Plant.LabelTo( + from, + 1061856 + ); // You must have the item in your backpack or locked down in order to use it. + } + else if (!m_Plant.IsCrossable) + { + m_Plant.LabelTo(from, 1053050); // You cannot gather pollen from a mutated plant! + } + else if (!m_Plant.PlantSystem.PollenProducing) + { + m_Plant.LabelTo(from, 1053051); // You cannot gather pollen from a plant in this stage of development! + } + else if (m_Plant.PlantSystem.Health < PlantHealth.Healthy) + { + m_Plant.LabelTo(from, 1053052); // You cannot gather pollen from an unhealthy plant! + } + else + { + if (!(targeted is PlantItem targ) || targ.PlantStatus >= PlantStatus.DecorativePlant || + targ.PlantStatus <= PlantStatus.BowlOfDirt) + { + m_Plant.LabelTo(from, 1053070); // You can only pollinate other specially grown plants! + } + else if (!targ.IsUsableBy(from)) + { + targ.LabelTo( + from, + 1061856 + ); // You must have the item in your backpack or locked down in order to use it. + } + else if (!targ.IsCrossable) + { + targ.LabelTo(from, 1053073); // You cannot cross-pollinate with a mutated plant! + } + else if (!targ.PlantSystem.PollenProducing) + { + targ.LabelTo(from, 1053074); // This plant is not in the flowering stage. You cannot pollinate it! + } + else if (targ.PlantSystem.Health < PlantHealth.Healthy) + { + targ.LabelTo(from, 1053075); // You cannot pollinate an unhealthy plant! + } + else if (targ.PlantSystem.Pollinated) + { + targ.LabelTo(from, 1053072); // This plant has already been pollinated! + } + else if (targ == m_Plant) + { + targ.PlantSystem.Pollinated = true; + targ.PlantSystem.SeedType = m_Plant.PlantType; + targ.PlantSystem.SeedHue = m_Plant.PlantHue; + + targ.LabelTo(from, 1053071); // You pollinate the plant with its own pollen. + } + else + { + targ.PlantSystem.Pollinated = true; + targ.PlantSystem.SeedType = PlantTypeInfo.Cross(m_Plant.PlantType, targ.PlantType); + targ.PlantSystem.SeedHue = PlantHueInfo.Cross(m_Plant.PlantHue, targ.PlantHue); + + targ.LabelTo(from, 1053076); // You successfully cross-pollinate the plant. + } + } + } + } + + protected override void OnTargetFinish(Mobile from) + { + if (!m_Plant.Deleted && m_Plant.PlantStatus < PlantStatus.DecorativePlant && + m_Plant.PlantStatus != PlantStatus.BowlOfDirt && from.InRange(m_Plant.GetWorldLocation(), 3) && + m_Plant.IsUsableBy(from)) from.SendGump(new ReproductionGump(m_Plant)); + } + } +} diff --git a/Projects/UOContent/Engines/Plants/ReproductionGump.cs b/Projects/UOContent/Engines/Plants/ReproductionGump.cs index 717eb07e3..ac3a0710e 100644 --- a/Projects/UOContent/Engines/Plants/ReproductionGump.cs +++ b/Projects/UOContent/Engines/Plants/ReproductionGump.cs @@ -1,263 +1,277 @@ -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.Plants -{ - public class ReproductionGump : Gump - { - private readonly PlantItem m_Plant; - - public ReproductionGump(PlantItem plant) : base(20, 20) - { - m_Plant = plant; - - DrawBackground(); - - AddButton(70, 67, 0xD4, 0xD4, 1); // Main menu - AddItem(57, 65, 0x1600); - - AddLabel(108, 67, 0x835, "Reproduction"); - - if (m_Plant.PlantStatus == PlantStatus.Stage9) - { - AddButton(212, 67, 0xD4, 0xD4, 2); // Set to decorative - AddItem(202, 68, 0xC61); - AddLabel(216, 66, 0x21, "/"); - } - - AddButton(80, 116, 0xD4, 0xD4, 3); // Pollination - AddItem(66, 117, 0x1AA2); - AddPollinationState(106, 116); - - AddButton(128, 116, 0xD4, 0xD4, 4); // Resources - AddItem(113, 120, 0x1021); - AddResourcesState(149, 116); - - AddButton(177, 116, 0xD4, 0xD4, 5); // Seeds - AddItem(160, 121, 0xDCF); - AddSeedsState(199, 116); - - AddButton(70, 163, 0xD2, 0xD2, 6); // Gather pollen - AddItem(56, 164, 0x1AA2); - - AddButton(138, 163, 0xD2, 0xD2, 7); // Gather resources - AddItem(123, 167, 0x1021); - - AddButton(212, 163, 0xD2, 0xD2, 8); // Gather seeds - AddItem(195, 168, 0xDCF); - } - - private void DrawBackground() - { - AddBackground(50, 50, 200, 150, 0xE10); - - AddImage(60, 90, 0xE17); - AddImage(120, 90, 0xE17); - - AddImage(60, 145, 0xE17); - AddImage(120, 145, 0xE17); - - AddItem(45, 45, 0xCEF); - AddItem(45, 118, 0xCF0); - - AddItem(211, 45, 0xCEB); - AddItem(211, 118, 0xCEC); - } - - private void AddPollinationState(int x, int y) - { - PlantSystem system = m_Plant.PlantSystem; - - if (!system.PollenProducing) - AddLabel(x, y, 0x35, "-"); - else if (!system.Pollinated) - AddLabel(x, y, 0x21, "!"); - else - AddLabel(x, y, 0x3F, "+"); - } - - private void AddResourcesState(int x, int y) - { - PlantResourceInfo resInfo = PlantResourceInfo.GetInfo(m_Plant.PlantType, m_Plant.PlantHue); - - PlantSystem system = m_Plant.PlantSystem; - int totalResources = system.AvailableResources + system.LeftResources; - - if (resInfo == null || totalResources == 0) - AddLabel(x + 5, y, 0x21, "X"); - else - AddLabel(x, y, PlantHueInfo.GetInfo(m_Plant.PlantHue).GumpHue, - $"{system.AvailableResources}/{totalResources}"); - } - - private void AddSeedsState(int x, int y) - { - PlantSystem system = m_Plant.PlantSystem; - int totalSeeds = system.AvailableSeeds + system.LeftSeeds; - - if (!m_Plant.Reproduces || totalSeeds == 0) - AddLabel(x + 5, y, 0x21, "X"); - else - AddLabel(x, y, PlantHueInfo.GetInfo(system.SeedHue).GumpHue, - $"{system.AvailableSeeds}/{totalSeeds}"); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - Mobile from = sender.Mobile; - - if (info.ButtonID == 0 || m_Plant.Deleted || m_Plant.PlantStatus >= PlantStatus.DecorativePlant || - m_Plant.PlantStatus == PlantStatus.BowlOfDirt) - return; - - if (info.ButtonID >= 6 && info.ButtonID <= 8 && !from.InRange(m_Plant.GetWorldLocation(), 3)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 500446); // That is too far away. - return; - } - - if (!m_Plant.IsUsableBy(from)) - { - m_Plant.LabelTo(from, 1061856); // You must have the item in your backpack or locked down in order to use it. - return; - } - - switch (info.ButtonID) - { - case 1: // Main menu - { - from.SendGump(new MainPlantGump(m_Plant)); - - break; - } - case 2: // Set to decorative - { - if (m_Plant.PlantStatus == PlantStatus.Stage9) from.SendGump(new SetToDecorativeGump(m_Plant)); - - break; - } - case 3: // Pollination - { - from.Send(new DisplayHelpTopic(67, true)); // POLLINATION STATE - - from.SendGump(new ReproductionGump(m_Plant)); - - break; - } - case 4: // Resources - { - from.Send(new DisplayHelpTopic(69, true)); // RESOURCE PRODUCTION - - from.SendGump(new ReproductionGump(m_Plant)); - - break; - } - case 5: // Seeds - { - from.Send(new DisplayHelpTopic(68, true)); // SEED PRODUCTION - - from.SendGump(new ReproductionGump(m_Plant)); - - break; - } - case 6: // Gather pollen - { - if (!m_Plant.IsCrossable) - { - m_Plant.LabelTo(from, 1053050); // You cannot gather pollen from a mutated plant! - } - else if (!m_Plant.PlantSystem.PollenProducing) - { - m_Plant.LabelTo(from, - 1053051); // You cannot gather pollen from a plant in this stage of development! - } - else if (m_Plant.PlantSystem.Health < PlantHealth.Healthy) - { - m_Plant.LabelTo(from, 1053052); // You cannot gather pollen from an unhealthy plant! - } - else - { - from.Target = new PollinateTarget(m_Plant); - from.SendLocalizedMessage(1053054); // Target the plant you wish to cross-pollinate to. - - break; - } - - from.SendGump(new ReproductionGump(m_Plant)); - - break; - } - case 7: // Gather resources - { - PlantResourceInfo resInfo = PlantResourceInfo.GetInfo(m_Plant.PlantType, m_Plant.PlantHue); - PlantSystem system = m_Plant.PlantSystem; - - if (resInfo == null) - { - if (m_Plant.IsCrossable) - m_Plant.LabelTo(from, 1053056); // This plant has no resources to gather! - else - m_Plant.LabelTo(from, 1053055); // Mutated plants do not produce resources! - } - else if (system.AvailableResources == 0) - { - m_Plant.LabelTo(from, 1053056); // This plant has no resources to gather! - } - else - { - Item resource = resInfo.CreateResource(); - - if (from.PlaceInBackpack(resource)) - { - system.AvailableResources--; - m_Plant.LabelTo(from, 1053059); // You gather resources from the plant. - } - else - { - resource.Delete(); - m_Plant.LabelTo(from, - 1053058); // You attempt to gather as many resources as you can hold, but your backpack is full. - } - } - - from.SendGump(new ReproductionGump(m_Plant)); - - break; - } - case 8: // Gather seeds - { - PlantSystem system = m_Plant.PlantSystem; - - if (!m_Plant.Reproduces) - { - m_Plant.LabelTo(from, 1053060); // Mutated plants do not produce seeds! - } - else if (system.AvailableSeeds == 0) - { - m_Plant.LabelTo(from, 1053061); // This plant has no seeds to gather! - } - else - { - Seed seed = new Seed(system.SeedType, system.SeedHue, true); - - if (from.PlaceInBackpack(seed)) - { - system.AvailableSeeds--; - m_Plant.LabelTo(from, 1053063); // You gather seeds from the plant. - } - else - { - seed.Delete(); - m_Plant.LabelTo(from, - 1053062); // You attempt to gather as many seeds as you can hold, but your backpack is full. - } - } - - from.SendGump(new ReproductionGump(m_Plant)); - - break; - } - } - } - } -} +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.Plants +{ + public class ReproductionGump : Gump + { + private readonly PlantItem m_Plant; + + public ReproductionGump(PlantItem plant) : base(20, 20) + { + m_Plant = plant; + + DrawBackground(); + + AddButton(70, 67, 0xD4, 0xD4, 1); // Main menu + AddItem(57, 65, 0x1600); + + AddLabel(108, 67, 0x835, "Reproduction"); + + if (m_Plant.PlantStatus == PlantStatus.Stage9) + { + AddButton(212, 67, 0xD4, 0xD4, 2); // Set to decorative + AddItem(202, 68, 0xC61); + AddLabel(216, 66, 0x21, "/"); + } + + AddButton(80, 116, 0xD4, 0xD4, 3); // Pollination + AddItem(66, 117, 0x1AA2); + AddPollinationState(106, 116); + + AddButton(128, 116, 0xD4, 0xD4, 4); // Resources + AddItem(113, 120, 0x1021); + AddResourcesState(149, 116); + + AddButton(177, 116, 0xD4, 0xD4, 5); // Seeds + AddItem(160, 121, 0xDCF); + AddSeedsState(199, 116); + + AddButton(70, 163, 0xD2, 0xD2, 6); // Gather pollen + AddItem(56, 164, 0x1AA2); + + AddButton(138, 163, 0xD2, 0xD2, 7); // Gather resources + AddItem(123, 167, 0x1021); + + AddButton(212, 163, 0xD2, 0xD2, 8); // Gather seeds + AddItem(195, 168, 0xDCF); + } + + private void DrawBackground() + { + AddBackground(50, 50, 200, 150, 0xE10); + + AddImage(60, 90, 0xE17); + AddImage(120, 90, 0xE17); + + AddImage(60, 145, 0xE17); + AddImage(120, 145, 0xE17); + + AddItem(45, 45, 0xCEF); + AddItem(45, 118, 0xCF0); + + AddItem(211, 45, 0xCEB); + AddItem(211, 118, 0xCEC); + } + + private void AddPollinationState(int x, int y) + { + var system = m_Plant.PlantSystem; + + if (!system.PollenProducing) + AddLabel(x, y, 0x35, "-"); + else if (!system.Pollinated) + AddLabel(x, y, 0x21, "!"); + else + AddLabel(x, y, 0x3F, "+"); + } + + private void AddResourcesState(int x, int y) + { + var resInfo = PlantResourceInfo.GetInfo(m_Plant.PlantType, m_Plant.PlantHue); + + var system = m_Plant.PlantSystem; + var totalResources = system.AvailableResources + system.LeftResources; + + if (resInfo == null || totalResources == 0) + AddLabel(x + 5, y, 0x21, "X"); + else + AddLabel( + x, + y, + PlantHueInfo.GetInfo(m_Plant.PlantHue).GumpHue, + $"{system.AvailableResources}/{totalResources}" + ); + } + + private void AddSeedsState(int x, int y) + { + var system = m_Plant.PlantSystem; + var totalSeeds = system.AvailableSeeds + system.LeftSeeds; + + if (!m_Plant.Reproduces || totalSeeds == 0) + AddLabel(x + 5, y, 0x21, "X"); + else + AddLabel( + x, + y, + PlantHueInfo.GetInfo(system.SeedHue).GumpHue, + $"{system.AvailableSeeds}/{totalSeeds}" + ); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var from = sender.Mobile; + + if (info.ButtonID == 0 || m_Plant.Deleted || m_Plant.PlantStatus >= PlantStatus.DecorativePlant || + m_Plant.PlantStatus == PlantStatus.BowlOfDirt) + return; + + if (info.ButtonID >= 6 && info.ButtonID <= 8 && !from.InRange(m_Plant.GetWorldLocation(), 3)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 500446); // That is too far away. + return; + } + + if (!m_Plant.IsUsableBy(from)) + { + m_Plant.LabelTo(from, 1061856); // You must have the item in your backpack or locked down in order to use it. + return; + } + + switch (info.ButtonID) + { + case 1: // Main menu + { + from.SendGump(new MainPlantGump(m_Plant)); + + break; + } + case 2: // Set to decorative + { + if (m_Plant.PlantStatus == PlantStatus.Stage9) from.SendGump(new SetToDecorativeGump(m_Plant)); + + break; + } + case 3: // Pollination + { + from.Send(new DisplayHelpTopic(67, true)); // POLLINATION STATE + + from.SendGump(new ReproductionGump(m_Plant)); + + break; + } + case 4: // Resources + { + from.Send(new DisplayHelpTopic(69, true)); // RESOURCE PRODUCTION + + from.SendGump(new ReproductionGump(m_Plant)); + + break; + } + case 5: // Seeds + { + from.Send(new DisplayHelpTopic(68, true)); // SEED PRODUCTION + + from.SendGump(new ReproductionGump(m_Plant)); + + break; + } + case 6: // Gather pollen + { + if (!m_Plant.IsCrossable) + { + m_Plant.LabelTo(from, 1053050); // You cannot gather pollen from a mutated plant! + } + else if (!m_Plant.PlantSystem.PollenProducing) + { + m_Plant.LabelTo( + from, + 1053051 + ); // You cannot gather pollen from a plant in this stage of development! + } + else if (m_Plant.PlantSystem.Health < PlantHealth.Healthy) + { + m_Plant.LabelTo(from, 1053052); // You cannot gather pollen from an unhealthy plant! + } + else + { + from.Target = new PollinateTarget(m_Plant); + from.SendLocalizedMessage(1053054); // Target the plant you wish to cross-pollinate to. + + break; + } + + from.SendGump(new ReproductionGump(m_Plant)); + + break; + } + case 7: // Gather resources + { + var resInfo = PlantResourceInfo.GetInfo(m_Plant.PlantType, m_Plant.PlantHue); + var system = m_Plant.PlantSystem; + + if (resInfo == null) + { + if (m_Plant.IsCrossable) + m_Plant.LabelTo(from, 1053056); // This plant has no resources to gather! + else + m_Plant.LabelTo(from, 1053055); // Mutated plants do not produce resources! + } + else if (system.AvailableResources == 0) + { + m_Plant.LabelTo(from, 1053056); // This plant has no resources to gather! + } + else + { + var resource = resInfo.CreateResource(); + + if (from.PlaceInBackpack(resource)) + { + system.AvailableResources--; + m_Plant.LabelTo(from, 1053059); // You gather resources from the plant. + } + else + { + resource.Delete(); + m_Plant.LabelTo( + from, + 1053058 + ); // You attempt to gather as many resources as you can hold, but your backpack is full. + } + } + + from.SendGump(new ReproductionGump(m_Plant)); + + break; + } + case 8: // Gather seeds + { + var system = m_Plant.PlantSystem; + + if (!m_Plant.Reproduces) + { + m_Plant.LabelTo(from, 1053060); // Mutated plants do not produce seeds! + } + else if (system.AvailableSeeds == 0) + { + m_Plant.LabelTo(from, 1053061); // This plant has no seeds to gather! + } + else + { + var seed = new Seed(system.SeedType, system.SeedHue, true); + + if (from.PlaceInBackpack(seed)) + { + system.AvailableSeeds--; + m_Plant.LabelTo(from, 1053063); // You gather seeds from the plant. + } + else + { + seed.Delete(); + m_Plant.LabelTo( + from, + 1053062 + ); // You attempt to gather as many seeds as you can hold, but your backpack is full. + } + } + + from.SendGump(new ReproductionGump(m_Plant)); + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Plants/Seed.cs b/Projects/UOContent/Engines/Plants/Seed.cs index 78b26c22e..1b79e43b1 100644 --- a/Projects/UOContent/Engines/Plants/Seed.cs +++ b/Projects/UOContent/Engines/Plants/Seed.cs @@ -1,217 +1,220 @@ -using Server.Targeting; - -namespace Server.Engines.Plants -{ - public class Seed : Item - { - private PlantHue m_PlantHue; - private PlantType m_PlantType; - private bool m_ShowType; - - [Constructible] - public Seed() : this(PlantTypeInfo.RandomFirstGeneration(), PlantHueInfo.RandomFirstGeneration()) - { - } - - [Constructible] - public Seed(PlantType plantType, PlantHue plantHue, bool showType = false) : base(0xDCF) - { - Weight = 1.0; - Stackable = Core.SA; - - m_PlantType = plantType; - m_PlantHue = plantHue; - m_ShowType = showType; - - Hue = PlantHueInfo.GetInfo(plantHue).Hue; - } - - public Seed(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public PlantType PlantType - { - get => m_PlantType; - set - { - m_PlantType = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public PlantHue PlantHue - { - get => m_PlantHue; - set - { - m_PlantHue = value; - Hue = PlantHueInfo.GetInfo(value).Hue; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool ShowType - { - get => m_ShowType; - set - { - m_ShowType = value; - InvalidateProperties(); - } - } - - public override int LabelNumber => 1060810; // seed - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public static Seed RandomBonsaiSeed() => RandomBonsaiSeed(0.5); - - public static Seed RandomBonsaiSeed(double increaseRatio) => new Seed(PlantTypeInfo.RandomBonsai(increaseRatio), PlantHue.Plain); - - public static Seed RandomPeculiarSeed(int group) - { - return @group switch - { - 1 => new Seed(PlantTypeInfo.RandomPeculiarGroupOne(), PlantHue.Plain), - 2 => new Seed(PlantTypeInfo.RandomPeculiarGroupTwo(), PlantHue.Plain), - 3 => new Seed(PlantTypeInfo.RandomPeculiarGroupThree(), PlantHue.Plain), - _ => new Seed(PlantTypeInfo.RandomPeculiarGroupFour(), PlantHue.Plain) - }; - } - - private int GetLabel(out string args) - { - PlantTypeInfo typeInfo = PlantTypeInfo.GetInfo(m_PlantType); - PlantHueInfo hueInfo = PlantHueInfo.GetInfo(m_PlantHue); - - int title; - - if (m_ShowType || typeInfo.PlantCategory == PlantCategory.Default) - title = hueInfo.Name; - else - title = (int)typeInfo.PlantCategory; - - if (Amount == 1) - { - if (m_ShowType) - { - args = $"#{title}\t#{typeInfo.Name}"; - return typeInfo.GetSeedLabel(hueInfo); - } - - args = $"#{title}"; - return hueInfo.IsBright() ? 1060839 : 1060838; // [bright] ~1_val~ seed - } - - if (m_ShowType) - { - args = $"{Amount}\t#{title}\t#{typeInfo.Name}"; - return typeInfo.GetSeedLabelPlural(hueInfo); - } - - args = $"{Amount}\t#{title}"; - return hueInfo.IsBright() ? 1113491 : 1113490; // ~1_amount~ [bright] ~2_val~ seeds - } - - public override void AddNameProperty(ObjectPropertyList list) - { - list.Add(GetLabel(out string args), args); - } - - public override void OnSingleClick(Mobile from) - { - LabelTo(from, GetLabel(out string args), args); - } - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - return; - } - - from.Target = new InternalTarget(this); - LabelTo(from, 1061916); // Choose a bowl of dirt to plant this seed in. - } - - public override bool StackWith(Mobile from, Item dropped, bool playSound) => - dropped is Seed other && other.PlantType == m_PlantType && other.PlantHue == m_PlantHue && - other.ShowType == m_ShowType && base.StackWith(from, other, playSound); - - public override void OnAfterDuped(Item newItem) - { - if (!(newItem is Seed newSeed)) - return; - - newSeed.PlantType = m_PlantType; - newSeed.PlantHue = m_PlantHue; - newSeed.ShowType = m_ShowType; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(2); // version - - writer.Write((int)m_PlantType); - writer.Write((int)m_PlantHue); - writer.Write(m_ShowType); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_PlantType = (PlantType)reader.ReadInt(); - m_PlantHue = (PlantHue)reader.ReadInt(); - m_ShowType = reader.ReadBool(); - - if (Weight != 1.0) - Weight = 1.0; - - if (version < 1) - Stackable = Core.SA; - - if (version < 2 && PlantHueInfo.IsCrossable(m_PlantHue)) - m_PlantHue |= PlantHue.Reproduces; - } - - private class InternalTarget : Target - { - private readonly Seed m_Seed; - - public InternalTarget(Seed seed) : base(-1, false, TargetFlags.None) - { - m_Seed = seed; - CheckLOS = false; - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Seed.Deleted) - return; - - if (!m_Seed.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - return; - } - - if (targeted is PlantItem plant) - plant.PlantSeed(from, m_Seed); - else if (targeted is Item item) - item.LabelTo(from, 1061919); // You must use a seed on a bowl of dirt! - else - from.SendLocalizedMessage(1061919); // You must use a seed on a bowl of dirt! - } - } - } -} +using Server.Targeting; + +namespace Server.Engines.Plants +{ + public class Seed : Item + { + private PlantHue m_PlantHue; + private PlantType m_PlantType; + private bool m_ShowType; + + [Constructible] + public Seed() : this(PlantTypeInfo.RandomFirstGeneration(), PlantHueInfo.RandomFirstGeneration()) + { + } + + [Constructible] + public Seed(PlantType plantType, PlantHue plantHue, bool showType = false) : base(0xDCF) + { + Weight = 1.0; + Stackable = Core.SA; + + m_PlantType = plantType; + m_PlantHue = plantHue; + m_ShowType = showType; + + Hue = PlantHueInfo.GetInfo(plantHue).Hue; + } + + public Seed(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public PlantType PlantType + { + get => m_PlantType; + set + { + m_PlantType = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public PlantHue PlantHue + { + get => m_PlantHue; + set + { + m_PlantHue = value; + Hue = PlantHueInfo.GetInfo(value).Hue; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool ShowType + { + get => m_ShowType; + set + { + m_ShowType = value; + InvalidateProperties(); + } + } + + public override int LabelNumber => 1060810; // seed + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + public static Seed RandomBonsaiSeed() => RandomBonsaiSeed(0.5); + + public static Seed RandomBonsaiSeed(double increaseRatio) => new Seed( + PlantTypeInfo.RandomBonsai(increaseRatio), + PlantHue.Plain + ); + + public static Seed RandomPeculiarSeed(int group) + { + return group switch + { + 1 => new Seed(PlantTypeInfo.RandomPeculiarGroupOne(), PlantHue.Plain), + 2 => new Seed(PlantTypeInfo.RandomPeculiarGroupTwo(), PlantHue.Plain), + 3 => new Seed(PlantTypeInfo.RandomPeculiarGroupThree(), PlantHue.Plain), + _ => new Seed(PlantTypeInfo.RandomPeculiarGroupFour(), PlantHue.Plain) + }; + } + + private int GetLabel(out string args) + { + var typeInfo = PlantTypeInfo.GetInfo(m_PlantType); + var hueInfo = PlantHueInfo.GetInfo(m_PlantHue); + + int title; + + if (m_ShowType || typeInfo.PlantCategory == PlantCategory.Default) + title = hueInfo.Name; + else + title = (int)typeInfo.PlantCategory; + + if (Amount == 1) + { + if (m_ShowType) + { + args = $"#{title}\t#{typeInfo.Name}"; + return typeInfo.GetSeedLabel(hueInfo); + } + + args = $"#{title}"; + return hueInfo.IsBright() ? 1060839 : 1060838; // [bright] ~1_val~ seed + } + + if (m_ShowType) + { + args = $"{Amount}\t#{title}\t#{typeInfo.Name}"; + return typeInfo.GetSeedLabelPlural(hueInfo); + } + + args = $"{Amount}\t#{title}"; + return hueInfo.IsBright() ? 1113491 : 1113490; // ~1_amount~ [bright] ~2_val~ seeds + } + + public override void AddNameProperty(ObjectPropertyList list) + { + list.Add(GetLabel(out var args), args); + } + + public override void OnSingleClick(Mobile from) + { + LabelTo(from, GetLabel(out var args), args); + } + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. + return; + } + + from.Target = new InternalTarget(this); + LabelTo(from, 1061916); // Choose a bowl of dirt to plant this seed in. + } + + public override bool StackWith(Mobile from, Item dropped, bool playSound) => + dropped is Seed other && other.PlantType == m_PlantType && other.PlantHue == m_PlantHue && + other.ShowType == m_ShowType && base.StackWith(from, other, playSound); + + public override void OnAfterDuped(Item newItem) + { + if (!(newItem is Seed newSeed)) + return; + + newSeed.PlantType = m_PlantType; + newSeed.PlantHue = m_PlantHue; + newSeed.ShowType = m_ShowType; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(2); // version + + writer.Write((int)m_PlantType); + writer.Write((int)m_PlantHue); + writer.Write(m_ShowType); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_PlantType = (PlantType)reader.ReadInt(); + m_PlantHue = (PlantHue)reader.ReadInt(); + m_ShowType = reader.ReadBool(); + + if (Weight != 1.0) + Weight = 1.0; + + if (version < 1) + Stackable = Core.SA; + + if (version < 2 && PlantHueInfo.IsCrossable(m_PlantHue)) + m_PlantHue |= PlantHue.Reproduces; + } + + private class InternalTarget : Target + { + private readonly Seed m_Seed; + + public InternalTarget(Seed seed) : base(-1, false, TargetFlags.None) + { + m_Seed = seed; + CheckLOS = false; + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Seed.Deleted) + return; + + if (!m_Seed.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. + return; + } + + if (targeted is PlantItem plant) + plant.PlantSeed(from, m_Seed); + else if (targeted is Item item) + item.LabelTo(from, 1061919); // You must use a seed on a bowl of dirt! + else + from.SendLocalizedMessage(1061919); // You must use a seed on a bowl of dirt! + } + } + } +} diff --git a/Projects/UOContent/Engines/Plants/SetToDecorativeGump.cs b/Projects/UOContent/Engines/Plants/SetToDecorativeGump.cs index 8e1317bd2..71335597e 100644 --- a/Projects/UOContent/Engines/Plants/SetToDecorativeGump.cs +++ b/Projects/UOContent/Engines/Plants/SetToDecorativeGump.cs @@ -1,84 +1,86 @@ -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.Plants -{ - public class SetToDecorativeGump : Gump - { - private readonly PlantItem m_Plant; - - public SetToDecorativeGump(PlantItem plant) : base(20, 20) - { - m_Plant = plant; - - DrawBackground(); - - AddLabel(115, 85, 0x44, "Set plant"); - AddLabel(82, 105, 0x44, "to decorative mode?"); - - AddButton(98, 140, 0x47E, 0x480, 1); // Cancel - - AddButton(138, 141, 0xD2, 0xD2, 2); // Help - AddLabel(143, 141, 0x835, "?"); - - AddButton(168, 140, 0x481, 0x483, 3); // Ok - } - - private void DrawBackground() - { - AddBackground(50, 50, 200, 150, 0xE10); - - AddItem(25, 45, 0xCEB); - AddItem(25, 118, 0xCEC); - - AddItem(227, 45, 0xCEF); - AddItem(227, 118, 0xCF0); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - Mobile from = sender.Mobile; - - if (info.ButtonID == 0 || m_Plant.Deleted || m_Plant.PlantStatus != PlantStatus.Stage9) - return; - - if (info.ButtonID == 3 && !from.InRange(m_Plant.GetWorldLocation(), 3)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 500446); // That is too far away. - return; - } - - if (!m_Plant.IsUsableBy(from)) - { - m_Plant.LabelTo(from, 1061856); // You must have the item in your backpack or locked down in order to use it. - return; - } - - switch (info.ButtonID) - { - case 1: // Cancel - { - from.SendGump(new ReproductionGump(m_Plant)); - - break; - } - case 2: // Help - { - from.Send(new DisplayHelpTopic(70, true)); // DECORATIVE MODE - - from.SendGump(new SetToDecorativeGump(m_Plant)); - - break; - } - case 3: // Ok - { - m_Plant.PlantStatus = PlantStatus.DecorativePlant; - m_Plant.LabelTo(from, - 1053077); // You prune the plant. This plant will no longer produce resources or seeds, but will require no upkeep. - - break; - } - } - } - } -} +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.Plants +{ + public class SetToDecorativeGump : Gump + { + private readonly PlantItem m_Plant; + + public SetToDecorativeGump(PlantItem plant) : base(20, 20) + { + m_Plant = plant; + + DrawBackground(); + + AddLabel(115, 85, 0x44, "Set plant"); + AddLabel(82, 105, 0x44, "to decorative mode?"); + + AddButton(98, 140, 0x47E, 0x480, 1); // Cancel + + AddButton(138, 141, 0xD2, 0xD2, 2); // Help + AddLabel(143, 141, 0x835, "?"); + + AddButton(168, 140, 0x481, 0x483, 3); // Ok + } + + private void DrawBackground() + { + AddBackground(50, 50, 200, 150, 0xE10); + + AddItem(25, 45, 0xCEB); + AddItem(25, 118, 0xCEC); + + AddItem(227, 45, 0xCEF); + AddItem(227, 118, 0xCF0); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var from = sender.Mobile; + + if (info.ButtonID == 0 || m_Plant.Deleted || m_Plant.PlantStatus != PlantStatus.Stage9) + return; + + if (info.ButtonID == 3 && !from.InRange(m_Plant.GetWorldLocation(), 3)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 500446); // That is too far away. + return; + } + + if (!m_Plant.IsUsableBy(from)) + { + m_Plant.LabelTo(from, 1061856); // You must have the item in your backpack or locked down in order to use it. + return; + } + + switch (info.ButtonID) + { + case 1: // Cancel + { + from.SendGump(new ReproductionGump(m_Plant)); + + break; + } + case 2: // Help + { + from.Send(new DisplayHelpTopic(70, true)); // DECORATIVE MODE + + from.SendGump(new SetToDecorativeGump(m_Plant)); + + break; + } + case 3: // Ok + { + m_Plant.PlantStatus = PlantStatus.DecorativePlant; + m_Plant.LabelTo( + from, + 1053077 + ); // You prune the plant. This plant will no longer produce resources or seeds, but will require no upkeep. + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Ambitious Solen Queen/AmbitiousQueenQuest.cs b/Projects/UOContent/Engines/Quests/Ambitious Solen Queen/AmbitiousQueenQuest.cs index b06f65c3c..fff90c899 100644 --- a/Projects/UOContent/Engines/Quests/Ambitious Solen Queen/AmbitiousQueenQuest.cs +++ b/Projects/UOContent/Engines/Quests/Ambitious Solen Queen/AmbitiousQueenQuest.cs @@ -1,115 +1,117 @@ -using System; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Ambitious -{ - public class AmbitiousQueenQuest : QuestSystem - { - private static readonly Type[] m_TypeReferenceTable = - { - typeof(DontOfferConversation), - typeof(AcceptConversation), - typeof(DuringKillQueensConversation), - typeof(GatherFungiConversation), - typeof(DuringFungiGatheringConversation), - typeof(EndConversation), - typeof(FullBackpackConversation), - typeof(End2Conversation), - typeof(KillQueensObjective), - typeof(ReturnAfterKillsObjective), - typeof(GatherFungiObjective), - typeof(GetRewardObjective) - }; - - public AmbitiousQueenQuest(PlayerMobile from, bool redSolen) : base(from) => RedSolen = redSolen; - - // Serialization - public AmbitiousQueenQuest() - { - } - - public override Type[] TypeReferenceTable => m_TypeReferenceTable; - - public override object Name => 1054146; - - public override object OfferMessage => 1054060; - - public override TimeSpan RestartDelay => TimeSpan.Zero; - public override bool IsTutorial => false; - - public override int Picture => 0x15C9; - - public bool RedSolen { get; private set; } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - RedSolen = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(RedSolen); - } - - public override void Accept() - { - base.Accept(); - - AddConversation(new AcceptConversation()); - } - - public static void GiveRewardTo(PlayerMobile player, ref bool bagOfSending, ref bool powderOfTranslocation, - ref bool gold) - { - if (bagOfSending) - { - Item reward = new BagOfSending(); - - if (player.PlaceInBackpack(reward)) - { - player.SendLocalizedMessage(1054074, "", 0x59); // You have been given a bag of sending. - bagOfSending = false; - } - else - { - reward.Delete(); - } - } - - if (powderOfTranslocation) - { - Item reward = new PowderOfTranslocation(Utility.RandomMinMax(10, 12)); - - if (player.PlaceInBackpack(reward)) - { - player.SendLocalizedMessage(1054075, "", 0x59); // You have been given some powder of translocation. - powderOfTranslocation = false; - } - else - { - reward.Delete(); - } - } - - if (gold) - { - Item reward = new Gold(Utility.RandomMinMax(250, 350)); - - if (player.PlaceInBackpack(reward)) - { - player.SendLocalizedMessage(1054076, "", 0x59); // You have been given some gold. - gold = false; - } - else - { - reward.Delete(); - } - } - } - } -} \ No newline at end of file +using System; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Ambitious +{ + public class AmbitiousQueenQuest : QuestSystem + { + private static readonly Type[] m_TypeReferenceTable = + { + typeof(DontOfferConversation), + typeof(AcceptConversation), + typeof(DuringKillQueensConversation), + typeof(GatherFungiConversation), + typeof(DuringFungiGatheringConversation), + typeof(EndConversation), + typeof(FullBackpackConversation), + typeof(End2Conversation), + typeof(KillQueensObjective), + typeof(ReturnAfterKillsObjective), + typeof(GatherFungiObjective), + typeof(GetRewardObjective) + }; + + public AmbitiousQueenQuest(PlayerMobile from, bool redSolen) : base(from) => RedSolen = redSolen; + + // Serialization + public AmbitiousQueenQuest() + { + } + + public override Type[] TypeReferenceTable => m_TypeReferenceTable; + + public override object Name => 1054146; + + public override object OfferMessage => 1054060; + + public override TimeSpan RestartDelay => TimeSpan.Zero; + public override bool IsTutorial => false; + + public override int Picture => 0x15C9; + + public bool RedSolen { get; private set; } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + RedSolen = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(RedSolen); + } + + public override void Accept() + { + base.Accept(); + + AddConversation(new AcceptConversation()); + } + + public static void GiveRewardTo( + PlayerMobile player, ref bool bagOfSending, ref bool powderOfTranslocation, + ref bool gold + ) + { + if (bagOfSending) + { + Item reward = new BagOfSending(); + + if (player.PlaceInBackpack(reward)) + { + player.SendLocalizedMessage(1054074, "", 0x59); // You have been given a bag of sending. + bagOfSending = false; + } + else + { + reward.Delete(); + } + } + + if (powderOfTranslocation) + { + Item reward = new PowderOfTranslocation(Utility.RandomMinMax(10, 12)); + + if (player.PlaceInBackpack(reward)) + { + player.SendLocalizedMessage(1054075, "", 0x59); // You have been given some powder of translocation. + powderOfTranslocation = false; + } + else + { + reward.Delete(); + } + } + + if (gold) + { + Item reward = new Gold(Utility.RandomMinMax(250, 350)); + + if (player.PlaceInBackpack(reward)) + { + player.SendLocalizedMessage(1054076, "", 0x59); // You have been given some gold. + gold = false; + } + else + { + reward.Delete(); + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Ambitious Solen Queen/Conversations.cs b/Projects/UOContent/Engines/Quests/Ambitious Solen Queen/Conversations.cs index 81827773d..5ef475ac7 100644 --- a/Projects/UOContent/Engines/Quests/Ambitious Solen Queen/Conversations.cs +++ b/Projects/UOContent/Engines/Quests/Ambitious Solen Queen/Conversations.cs @@ -1,120 +1,119 @@ -namespace Server.Engines.Quests.Ambitious -{ - public class DontOfferConversation : QuestConversation - { - public override object Message => 1054059; - - public override bool Logged => false; - } - - public class AcceptConversation : QuestConversation - { - public override object Message => 1054061; - - public override void OnRead() - { - System.AddObjective(new KillQueensObjective()); - } - } - - public class DuringKillQueensConversation : QuestConversation - { - public override object Message => 1054066; - - public override bool Logged => false; - } - - public class GatherFungiConversation : QuestConversation - { - public override object Message => 1054068; - - public override void OnRead() - { - System.AddObjective(new GatherFungiObjective()); - } - } - - public class DuringFungiGatheringConversation : QuestConversation - { - public override object Message => 1054070; - - public override bool Logged => false; - } - - public class EndConversation : QuestConversation - { - public override object Message => 1054073; - - public override void OnRead() - { - bool bagOfSending = true; - bool powderOfTranslocation = true; - bool gold = true; - - AmbitiousQueenQuest.GiveRewardTo(System.From, ref bagOfSending, ref powderOfTranslocation, ref gold); - - if (!bagOfSending && !powderOfTranslocation && !gold) - System.Complete(); - else - System.AddConversation(new FullBackpackConversation(true, bagOfSending, powderOfTranslocation, gold)); - } - } - - public class FullBackpackConversation : QuestConversation - { - private bool m_BagOfSending; - private bool m_Gold; - - private readonly bool m_Logged; - private bool m_PowderOfTranslocation; - - public FullBackpackConversation(bool logged, bool bagOfSending, bool powderOfTranslocation, bool gold) - { - m_Logged = logged; - - m_BagOfSending = bagOfSending; - m_PowderOfTranslocation = powderOfTranslocation; - m_Gold = gold; - } - - public FullBackpackConversation() => m_Logged = true; - - public override object Message => 1054077; - - public override bool Logged => m_Logged; - - public override void OnRead() - { - if (m_Logged) - System.AddObjective(new GetRewardObjective(m_BagOfSending, m_PowderOfTranslocation, m_Gold)); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_BagOfSending = reader.ReadBool(); - m_PowderOfTranslocation = reader.ReadBool(); - m_Gold = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(m_BagOfSending); - writer.Write(m_PowderOfTranslocation); - writer.Write(m_Gold); - } - } - - public class End2Conversation : QuestConversation - { - public override object Message => 1054078; - - public override void OnRead() - { - System.Complete(); - } - } -} \ No newline at end of file +namespace Server.Engines.Quests.Ambitious +{ + public class DontOfferConversation : QuestConversation + { + public override object Message => 1054059; + + public override bool Logged => false; + } + + public class AcceptConversation : QuestConversation + { + public override object Message => 1054061; + + public override void OnRead() + { + System.AddObjective(new KillQueensObjective()); + } + } + + public class DuringKillQueensConversation : QuestConversation + { + public override object Message => 1054066; + + public override bool Logged => false; + } + + public class GatherFungiConversation : QuestConversation + { + public override object Message => 1054068; + + public override void OnRead() + { + System.AddObjective(new GatherFungiObjective()); + } + } + + public class DuringFungiGatheringConversation : QuestConversation + { + public override object Message => 1054070; + + public override bool Logged => false; + } + + public class EndConversation : QuestConversation + { + public override object Message => 1054073; + + public override void OnRead() + { + var bagOfSending = true; + var powderOfTranslocation = true; + var gold = true; + + AmbitiousQueenQuest.GiveRewardTo(System.From, ref bagOfSending, ref powderOfTranslocation, ref gold); + + if (!bagOfSending && !powderOfTranslocation && !gold) + System.Complete(); + else + System.AddConversation(new FullBackpackConversation(true, bagOfSending, powderOfTranslocation, gold)); + } + } + + public class FullBackpackConversation : QuestConversation + { + private readonly bool m_Logged; + private bool m_BagOfSending; + private bool m_Gold; + private bool m_PowderOfTranslocation; + + public FullBackpackConversation(bool logged, bool bagOfSending, bool powderOfTranslocation, bool gold) + { + m_Logged = logged; + + m_BagOfSending = bagOfSending; + m_PowderOfTranslocation = powderOfTranslocation; + m_Gold = gold; + } + + public FullBackpackConversation() => m_Logged = true; + + public override object Message => 1054077; + + public override bool Logged => m_Logged; + + public override void OnRead() + { + if (m_Logged) + System.AddObjective(new GetRewardObjective(m_BagOfSending, m_PowderOfTranslocation, m_Gold)); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_BagOfSending = reader.ReadBool(); + m_PowderOfTranslocation = reader.ReadBool(); + m_Gold = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(m_BagOfSending); + writer.Write(m_PowderOfTranslocation); + writer.Write(m_Gold); + } + } + + public class End2Conversation : QuestConversation + { + public override object Message => 1054078; + + public override void OnRead() + { + System.Complete(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Ambitious Solen Queen/Mobiles/AmbitiousSolenQueen.cs b/Projects/UOContent/Engines/Quests/Ambitious Solen Queen/Mobiles/AmbitiousSolenQueen.cs index 2c9b57f1d..b171a2dcd 100644 --- a/Projects/UOContent/Engines/Quests/Ambitious Solen Queen/Mobiles/AmbitiousSolenQueen.cs +++ b/Projects/UOContent/Engines/Quests/Ambitious Solen Queen/Mobiles/AmbitiousSolenQueen.cs @@ -1,196 +1,204 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Ambitious -{ - public abstract class BaseAmbitiousSolenQueen : BaseQuester - { - public BaseAmbitiousSolenQueen() - { - } - - public BaseAmbitiousSolenQueen(Serial serial) : base(serial) - { - } - - public abstract bool RedSolen { get; } - public override string DefaultName => "an ambitious solen queen"; - public override bool DisallowAllMoves => false; - - public override void InitBody() - { - Body = 0x30F; - - if (!RedSolen) - Hue = 0x453; - - SpeechHue = 0; - } - - public override int GetIdleSound() => 0x10D; - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - Direction = GetDirectionTo(player); - - if (player.Quest is AmbitiousQueenQuest qs && qs.RedSolen == RedSolen) - { - if (qs.IsObjectiveInProgress(typeof(KillQueensObjective))) - { - qs.AddConversation(new DuringKillQueensConversation()); - } - else - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - obj.Complete(); - } - else if (qs.IsObjectiveInProgress(typeof(GatherFungiObjective))) - { - qs.AddConversation(new DuringFungiGatheringConversation()); - } - else - { - GetRewardObjective lastObj = qs.FindObjective(); - - if (lastObj?.Completed == false) - { - bool bagOfSending = lastObj.BagOfSending; - bool powderOfTranslocation = lastObj.PowderOfTranslocation; - bool gold = lastObj.Gold; - - AmbitiousQueenQuest.GiveRewardTo(player, ref bagOfSending, ref powderOfTranslocation, ref gold); - - lastObj.BagOfSending = bagOfSending; - lastObj.PowderOfTranslocation = powderOfTranslocation; - lastObj.Gold = gold; - - if (!bagOfSending && !powderOfTranslocation && !gold) - lastObj.Complete(); - else - qs.AddConversation(new FullBackpackConversation(false, lastObj.BagOfSending, - lastObj.PowderOfTranslocation, lastObj.Gold)); - } - } - } - } - else - { - QuestSystem newQuest = new AmbitiousQueenQuest(player, RedSolen); - - if (player.Quest == null && QuestSystem.CanOfferQuest(player, typeof(AmbitiousQueenQuest))) - newQuest.SendOffer(); - else - newQuest.AddConversation(new DontOfferConversation()); - } - } - - public override bool OnDragDrop(Mobile from, Item dropped) - { - Direction = GetDirectionTo(from); - - if (from is PlayerMobile player) - if (player.Quest is AmbitiousQueenQuest qs && qs.RedSolen == RedSolen) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - if (dropped is ZoogiFungus fungi) - { - if (fungi.Amount >= 50) - { - obj.Complete(); - - fungi.Amount -= 50; - - if (fungi.Amount == 0) - { - fungi.Delete(); - return true; - } - - return false; - } - - SayTo(player, - 1054072); // Our arrangement was for 50 of the zoogi fungus. Please return to me when you have that amount. - return false; - } - } - - return base.OnDragDrop(from, dropped); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class RedAmbitiousSolenQueen : BaseAmbitiousSolenQueen - { - [Constructible] - public RedAmbitiousSolenQueen() - { - } - - public RedAmbitiousSolenQueen(Serial serial) : base(serial) - { - } - - public override bool RedSolen => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BlackAmbitiousSolenQueen : BaseAmbitiousSolenQueen - { - [Constructible] - public BlackAmbitiousSolenQueen() - { - } - - public BlackAmbitiousSolenQueen(Serial serial) : base(serial) - { - } - - public override bool RedSolen => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Ambitious +{ + public abstract class BaseAmbitiousSolenQueen : BaseQuester + { + public BaseAmbitiousSolenQueen() + { + } + + public BaseAmbitiousSolenQueen(Serial serial) : base(serial) + { + } + + public abstract bool RedSolen { get; } + public override string DefaultName => "an ambitious solen queen"; + public override bool DisallowAllMoves => false; + + public override void InitBody() + { + Body = 0x30F; + + if (!RedSolen) + Hue = 0x453; + + SpeechHue = 0; + } + + public override int GetIdleSound() => 0x10D; + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + Direction = GetDirectionTo(player); + + if (player.Quest is AmbitiousQueenQuest qs && qs.RedSolen == RedSolen) + { + if (qs.IsObjectiveInProgress(typeof(KillQueensObjective))) + { + qs.AddConversation(new DuringKillQueensConversation()); + } + else + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + obj.Complete(); + } + else if (qs.IsObjectiveInProgress(typeof(GatherFungiObjective))) + { + qs.AddConversation(new DuringFungiGatheringConversation()); + } + else + { + var lastObj = qs.FindObjective(); + + if (lastObj?.Completed == false) + { + var bagOfSending = lastObj.BagOfSending; + var powderOfTranslocation = lastObj.PowderOfTranslocation; + var gold = lastObj.Gold; + + AmbitiousQueenQuest.GiveRewardTo(player, ref bagOfSending, ref powderOfTranslocation, ref gold); + + lastObj.BagOfSending = bagOfSending; + lastObj.PowderOfTranslocation = powderOfTranslocation; + lastObj.Gold = gold; + + if (!bagOfSending && !powderOfTranslocation && !gold) + lastObj.Complete(); + else + qs.AddConversation( + new FullBackpackConversation( + false, + lastObj.BagOfSending, + lastObj.PowderOfTranslocation, + lastObj.Gold + ) + ); + } + } + } + } + else + { + QuestSystem newQuest = new AmbitiousQueenQuest(player, RedSolen); + + if (player.Quest == null && QuestSystem.CanOfferQuest(player, typeof(AmbitiousQueenQuest))) + newQuest.SendOffer(); + else + newQuest.AddConversation(new DontOfferConversation()); + } + } + + public override bool OnDragDrop(Mobile from, Item dropped) + { + Direction = GetDirectionTo(from); + + if (from is PlayerMobile player) + if (player.Quest is AmbitiousQueenQuest qs && qs.RedSolen == RedSolen) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + if (dropped is ZoogiFungus fungi) + { + if (fungi.Amount >= 50) + { + obj.Complete(); + + fungi.Amount -= 50; + + if (fungi.Amount == 0) + { + fungi.Delete(); + return true; + } + + return false; + } + + SayTo( + player, + 1054072 + ); // Our arrangement was for 50 of the zoogi fungus. Please return to me when you have that amount. + return false; + } + } + + return base.OnDragDrop(from, dropped); + } + + 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(); + } + } + + public class RedAmbitiousSolenQueen : BaseAmbitiousSolenQueen + { + [Constructible] + public RedAmbitiousSolenQueen() + { + } + + public RedAmbitiousSolenQueen(Serial serial) : base(serial) + { + } + + public override bool RedSolen => true; + + 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(); + } + } + + public class BlackAmbitiousSolenQueen : BaseAmbitiousSolenQueen + { + [Constructible] + public BlackAmbitiousSolenQueen() + { + } + + public BlackAmbitiousSolenQueen(Serial serial) : base(serial) + { + } + + public override bool RedSolen => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Ambitious Solen Queen/Objectives.cs b/Projects/UOContent/Engines/Quests/Ambitious Solen Queen/Objectives.cs index b651cbe54..6cb9b5cf6 100644 --- a/Projects/UOContent/Engines/Quests/Ambitious Solen Queen/Objectives.cs +++ b/Projects/UOContent/Engines/Quests/Ambitious Solen Queen/Objectives.cs @@ -1,127 +1,133 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Ambitious -{ - public class KillQueensObjective : QuestObjective - { - public override object Message => ((AmbitiousQueenQuest)System).RedSolen ? 1054062 : 1054063; - - public override int MaxProgress => 5; - - public override void RenderProgress(BaseQuestGump gump) - { - if (!Completed) - { - // Red/Black Solen Queens killed: - gump.AddHtmlLocalized(70, 260, 270, 100, ((AmbitiousQueenQuest)System).RedSolen ? 1054064 : 1054065, - BaseQuestGump.Blue); - gump.AddLabel(70, 280, 0x64, CurProgress.ToString()); - gump.AddLabel(100, 280, 0x64, "/"); - gump.AddLabel(130, 280, 0x64, MaxProgress.ToString()); - } - else - { - base.RenderProgress(gump); - } - } - - public override bool IgnoreYoungProtection(Mobile from) - { - if (Completed) - return false; - - bool redSolen = ((AmbitiousQueenQuest)System).RedSolen; - - if (redSolen) - return from is RedSolenQueen; - return from is BlackSolenQueen; - } - - public override void OnKill(BaseCreature creature, Container corpse) - { - bool redSolen = ((AmbitiousQueenQuest)System).RedSolen; - - if (redSolen) - { - if (creature is RedSolenQueen) - CurProgress++; - } - else - { - if (creature is BlackSolenQueen) - CurProgress++; - } - } - - public override void OnComplete() - { - System.AddObjective(new ReturnAfterKillsObjective()); - } - } - - public class ReturnAfterKillsObjective : QuestObjective - { - public override object Message => 1054067; - - public override void OnComplete() - { - System.AddConversation(new GatherFungiConversation()); - } - } - - public class GatherFungiObjective : QuestObjective - { - public override object Message => 1054069; - - public override void OnComplete() - { - System.AddConversation(new EndConversation()); - } - } - - public class GetRewardObjective : QuestObjective - { - public GetRewardObjective(bool bagOfSending, bool powderOfTranslocation, bool gold) - { - BagOfSending = bagOfSending; - PowderOfTranslocation = powderOfTranslocation; - Gold = gold; - } - - public GetRewardObjective() - { - } - - public override object Message => 1054148; - - public bool BagOfSending { get; set; } - - public bool PowderOfTranslocation { get; set; } - - public bool Gold { get; set; } - - public override void OnComplete() - { - System.AddConversation(new End2Conversation()); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - BagOfSending = reader.ReadBool(); - PowderOfTranslocation = reader.ReadBool(); - Gold = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(BagOfSending); - writer.Write(PowderOfTranslocation); - writer.Write(Gold); - } - } -} \ No newline at end of file +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Ambitious +{ + public class KillQueensObjective : QuestObjective + { + public override object Message => ((AmbitiousQueenQuest)System).RedSolen ? 1054062 : 1054063; + + public override int MaxProgress => 5; + + public override void RenderProgress(BaseQuestGump gump) + { + if (!Completed) + { + // Red/Black Solen Queens killed: + gump.AddHtmlLocalized( + 70, + 260, + 270, + 100, + ((AmbitiousQueenQuest)System).RedSolen ? 1054064 : 1054065, + BaseQuestGump.Blue + ); + gump.AddLabel(70, 280, 0x64, CurProgress.ToString()); + gump.AddLabel(100, 280, 0x64, "/"); + gump.AddLabel(130, 280, 0x64, MaxProgress.ToString()); + } + else + { + base.RenderProgress(gump); + } + } + + public override bool IgnoreYoungProtection(Mobile from) + { + if (Completed) + return false; + + var redSolen = ((AmbitiousQueenQuest)System).RedSolen; + + if (redSolen) + return from is RedSolenQueen; + return from is BlackSolenQueen; + } + + public override void OnKill(BaseCreature creature, Container corpse) + { + var redSolen = ((AmbitiousQueenQuest)System).RedSolen; + + if (redSolen) + { + if (creature is RedSolenQueen) + CurProgress++; + } + else + { + if (creature is BlackSolenQueen) + CurProgress++; + } + } + + public override void OnComplete() + { + System.AddObjective(new ReturnAfterKillsObjective()); + } + } + + public class ReturnAfterKillsObjective : QuestObjective + { + public override object Message => 1054067; + + public override void OnComplete() + { + System.AddConversation(new GatherFungiConversation()); + } + } + + public class GatherFungiObjective : QuestObjective + { + public override object Message => 1054069; + + public override void OnComplete() + { + System.AddConversation(new EndConversation()); + } + } + + public class GetRewardObjective : QuestObjective + { + public GetRewardObjective(bool bagOfSending, bool powderOfTranslocation, bool gold) + { + BagOfSending = bagOfSending; + PowderOfTranslocation = powderOfTranslocation; + Gold = gold; + } + + public GetRewardObjective() + { + } + + public override object Message => 1054148; + + public bool BagOfSending { get; set; } + + public bool PowderOfTranslocation { get; set; } + + public bool Gold { get; set; } + + public override void OnComplete() + { + System.AddConversation(new End2Conversation()); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + BagOfSending = reader.ReadBool(); + PowderOfTranslocation = reader.ReadBool(); + Gold = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(BagOfSending); + writer.Write(PowderOfTranslocation); + writer.Write(Gold); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Collector/CollectorQuest.cs b/Projects/UOContent/Engines/Quests/Collector/CollectorQuest.cs index 5b0563ec7..2f6ff3c83 100644 --- a/Projects/UOContent/Engines/Quests/Collector/CollectorQuest.cs +++ b/Projects/UOContent/Engines/Quests/Collector/CollectorQuest.cs @@ -1,89 +1,89 @@ -using System; -using Server.Mobiles; - -namespace Server.Engines.Quests.Collector -{ - public class CollectorQuest : QuestSystem - { - private static readonly Type[] m_TypeReferenceTable = - { - typeof(DontOfferConversation), - typeof(DeclineConversation), - typeof(AcceptConversation), - typeof(ElwoodDuringFishConversation), - typeof(ReturnPearlsConversation), - typeof(AlbertaPaintingConversation), - typeof(AlbertaStoolConversation), - typeof(AlbertaEndPaintingConversation), - typeof(AlbertaAfterPaintingConversation), - typeof(ElwoodDuringPainting1Conversation), - typeof(ElwoodDuringPainting2Conversation), - typeof(ReturnPaintingConversation), - typeof(GabrielAutographConversation), - typeof(GabrielNoSheetMusicConversation), - typeof(NoSheetMusicConversation), - typeof(GetSheetMusicConversation), - typeof(GabrielSheetMusicConversation), - typeof(GabrielIgnoreConversation), - typeof(ElwoodDuringAutograph1Conversation), - typeof(ElwoodDuringAutograph2Conversation), - typeof(ElwoodDuringAutograph3Conversation), - typeof(ReturnAutographConversation), - typeof(TomasToysConversation), - typeof(TomasDuringCollectingConversation), - typeof(ReturnImagesConversation), - typeof(ElwoodDuringToys1Conversation), - typeof(ElwoodDuringToys2Conversation), - typeof(ElwoodDuringToys3Conversation), - typeof(FullEndConversation), - typeof(FishPearlsObjective), - typeof(ReturnPearlsObjective), - typeof(FindAlbertaObjective), - typeof(SitOnTheStoolObjective), - typeof(ReturnPaintingObjective), - typeof(FindGabrielObjective), - typeof(FindSheetMusicObjective), - typeof(ReturnSheetMusicObjective), - typeof(ReturnAutographObjective), - typeof(FindTomasObjective), - typeof(CaptureImagesObjective), - typeof(ReturnImagesObjective), - typeof(ReturnToysObjective), - typeof(MakeRoomObjective) - }; - - public CollectorQuest(PlayerMobile from) : base(from) - { - } - - // Serialization - public CollectorQuest() - { - } - - public override Type[] TypeReferenceTable => m_TypeReferenceTable; - - public override object Name => "Collector's Quest"; - - public override object OfferMessage => 1055081; - - public override TimeSpan RestartDelay => TimeSpan.Zero; - public override bool IsTutorial => false; - - public override int Picture => 0x15A9; - - public override void Accept() - { - base.Accept(); - - AddConversation(new AcceptConversation()); - } - - public override void Decline() - { - base.Decline(); - - AddConversation(new DeclineConversation()); - } - } -} \ No newline at end of file +using System; +using Server.Mobiles; + +namespace Server.Engines.Quests.Collector +{ + public class CollectorQuest : QuestSystem + { + private static readonly Type[] m_TypeReferenceTable = + { + typeof(DontOfferConversation), + typeof(DeclineConversation), + typeof(AcceptConversation), + typeof(ElwoodDuringFishConversation), + typeof(ReturnPearlsConversation), + typeof(AlbertaPaintingConversation), + typeof(AlbertaStoolConversation), + typeof(AlbertaEndPaintingConversation), + typeof(AlbertaAfterPaintingConversation), + typeof(ElwoodDuringPainting1Conversation), + typeof(ElwoodDuringPainting2Conversation), + typeof(ReturnPaintingConversation), + typeof(GabrielAutographConversation), + typeof(GabrielNoSheetMusicConversation), + typeof(NoSheetMusicConversation), + typeof(GetSheetMusicConversation), + typeof(GabrielSheetMusicConversation), + typeof(GabrielIgnoreConversation), + typeof(ElwoodDuringAutograph1Conversation), + typeof(ElwoodDuringAutograph2Conversation), + typeof(ElwoodDuringAutograph3Conversation), + typeof(ReturnAutographConversation), + typeof(TomasToysConversation), + typeof(TomasDuringCollectingConversation), + typeof(ReturnImagesConversation), + typeof(ElwoodDuringToys1Conversation), + typeof(ElwoodDuringToys2Conversation), + typeof(ElwoodDuringToys3Conversation), + typeof(FullEndConversation), + typeof(FishPearlsObjective), + typeof(ReturnPearlsObjective), + typeof(FindAlbertaObjective), + typeof(SitOnTheStoolObjective), + typeof(ReturnPaintingObjective), + typeof(FindGabrielObjective), + typeof(FindSheetMusicObjective), + typeof(ReturnSheetMusicObjective), + typeof(ReturnAutographObjective), + typeof(FindTomasObjective), + typeof(CaptureImagesObjective), + typeof(ReturnImagesObjective), + typeof(ReturnToysObjective), + typeof(MakeRoomObjective) + }; + + public CollectorQuest(PlayerMobile from) : base(from) + { + } + + // Serialization + public CollectorQuest() + { + } + + public override Type[] TypeReferenceTable => m_TypeReferenceTable; + + public override object Name => "Collector's Quest"; + + public override object OfferMessage => 1055081; + + public override TimeSpan RestartDelay => TimeSpan.Zero; + public override bool IsTutorial => false; + + public override int Picture => 0x15A9; + + public override void Accept() + { + base.Accept(); + + AddConversation(new AcceptConversation()); + } + + public override void Decline() + { + base.Decline(); + + AddConversation(new DeclineConversation()); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Collector/Conversations.cs b/Projects/UOContent/Engines/Quests/Collector/Conversations.cs index f5a8cc334..d090d44c3 100644 --- a/Projects/UOContent/Engines/Quests/Collector/Conversations.cs +++ b/Projects/UOContent/Engines/Quests/Collector/Conversations.cs @@ -1,260 +1,260 @@ -namespace Server.Engines.Quests.Collector -{ - public class DontOfferConversation : QuestConversation - { - public override object Message => 1055080; - - public override bool Logged => false; - } - - public class DeclineConversation : QuestConversation - { - public override object Message => 1055082; - - public override bool Logged => false; - } - - public class AcceptConversation : QuestConversation - { - public override object Message => 1055083; - - public override void OnRead() - { - System.AddObjective(new FishPearlsObjective()); - } - } - - public class ElwoodDuringFishConversation : QuestConversation - { - public override object Message => 1055089; - - public override bool Logged => false; - } - - public class ReturnPearlsConversation : QuestConversation - { - public override object Message => 1055090; - - public override void OnRead() - { - System.AddObjective(new FindAlbertaObjective()); - } - } - - public class AlbertaPaintingConversation : QuestConversation - { - public override object Message => 1055092; - - public override void OnRead() - { - System.AddObjective(new SitOnTheStoolObjective()); - } - } - - public class AlbertaStoolConversation : QuestConversation - { - public override object Message => 1055096; - - public override bool Logged => false; - } - - public class AlbertaEndPaintingConversation : QuestConversation - { - public override object Message => 1055098; - - public override void OnRead() - { - System.AddObjective(new ReturnPaintingObjective()); - } - } - - public class AlbertaAfterPaintingConversation : QuestConversation - { - public override object Message => 1055102; - - public override bool Logged => false; - } - - public class ElwoodDuringPainting1Conversation : QuestConversation - { - public override object Message => 1055094; - - public override bool Logged => false; - } - - public class ElwoodDuringPainting2Conversation : QuestConversation - { - public override object Message => 1055097; - - public override bool Logged => false; - } - - public class ReturnPaintingConversation : QuestConversation - { - public override object Message => 1055100; - - public override void OnRead() - { - System.AddObjective(new FindGabrielObjective()); - } - } - - public class GabrielAutographConversation : QuestConversation - { - public override object Message => 1055103; - - public override void OnRead() - { - System.AddObjective(new FindSheetMusicObjective(true)); - } - } - - public class GabrielNoSheetMusicConversation : QuestConversation - { - public override object Message => 1055111; - - public override bool Logged => false; - } - - public class NoSheetMusicConversation : QuestConversation - { - public override object Message => 1055106; - - public override bool Logged => false; - } - - public class GetSheetMusicConversation : QuestConversation - { - public override object Message => 1055109; - - public override void OnRead() - { - System.AddObjective(new ReturnSheetMusicObjective()); - } - } - - public class GabrielSheetMusicConversation : QuestConversation - { - public override object Message => 1055113; - - public override void OnRead() - { - System.AddObjective(new ReturnAutographObjective()); - } - } - - public class GabrielIgnoreConversation : QuestConversation - { - public override object Message => 1055118; - - public override bool Logged => false; - } - - public class ElwoodDuringAutograph1Conversation : QuestConversation - { - public override object Message => 1055105; - - public override bool Logged => false; - } - - public class ElwoodDuringAutograph2Conversation : QuestConversation - { - public override object Message => 1055112; - - public override bool Logged => false; - } - - public class ElwoodDuringAutograph3Conversation : QuestConversation - { - public override object Message => 1055115; - - public override bool Logged => false; - } - - public class ReturnAutographConversation : QuestConversation - { - public override object Message => 1055116; - - public override void OnRead() - { - System.AddObjective(new FindTomasObjective()); - } - } - - public class TomasToysConversation : QuestConversation - { - public override object Message => 1055119; - - public override void OnRead() - { - System.AddObjective(new CaptureImagesObjective(true)); - } - } - - public class TomasDuringCollectingConversation : QuestConversation - { - public override object Message => 1055129; - - public override bool Logged => false; - } - - public class ReturnImagesConversation : QuestConversation - { - public override object Message => 1055131; - - public override void OnRead() - { - System.AddObjective(new ReturnToysObjective()); - } - } - - public class ElwoodDuringToys1Conversation : QuestConversation - { - public override object Message => 1055123; - - public override bool Logged => false; - } - - public class ElwoodDuringToys2Conversation : QuestConversation - { - public override object Message => 1055130; - - public override bool Logged => false; - } - - public class ElwoodDuringToys3Conversation : QuestConversation - { - public override object Message => 1055133; - - public override bool Logged => false; - } - - public class EndConversation : QuestConversation - { - public override object Message => 1055134; - - public override void OnRead() - { - System.Complete(); - } - } - - public class FullEndConversation : QuestConversation - { - private readonly bool m_Logged; - - public FullEndConversation(bool logged) => m_Logged = logged; - - public FullEndConversation() => m_Logged = true; - - public override object Message => 1055135; - - public override bool Logged => m_Logged; - - public override void OnRead() - { - if (m_Logged) - System.AddObjective(new MakeRoomObjective()); - } - } -} \ No newline at end of file +namespace Server.Engines.Quests.Collector +{ + public class DontOfferConversation : QuestConversation + { + public override object Message => 1055080; + + public override bool Logged => false; + } + + public class DeclineConversation : QuestConversation + { + public override object Message => 1055082; + + public override bool Logged => false; + } + + public class AcceptConversation : QuestConversation + { + public override object Message => 1055083; + + public override void OnRead() + { + System.AddObjective(new FishPearlsObjective()); + } + } + + public class ElwoodDuringFishConversation : QuestConversation + { + public override object Message => 1055089; + + public override bool Logged => false; + } + + public class ReturnPearlsConversation : QuestConversation + { + public override object Message => 1055090; + + public override void OnRead() + { + System.AddObjective(new FindAlbertaObjective()); + } + } + + public class AlbertaPaintingConversation : QuestConversation + { + public override object Message => 1055092; + + public override void OnRead() + { + System.AddObjective(new SitOnTheStoolObjective()); + } + } + + public class AlbertaStoolConversation : QuestConversation + { + public override object Message => 1055096; + + public override bool Logged => false; + } + + public class AlbertaEndPaintingConversation : QuestConversation + { + public override object Message => 1055098; + + public override void OnRead() + { + System.AddObjective(new ReturnPaintingObjective()); + } + } + + public class AlbertaAfterPaintingConversation : QuestConversation + { + public override object Message => 1055102; + + public override bool Logged => false; + } + + public class ElwoodDuringPainting1Conversation : QuestConversation + { + public override object Message => 1055094; + + public override bool Logged => false; + } + + public class ElwoodDuringPainting2Conversation : QuestConversation + { + public override object Message => 1055097; + + public override bool Logged => false; + } + + public class ReturnPaintingConversation : QuestConversation + { + public override object Message => 1055100; + + public override void OnRead() + { + System.AddObjective(new FindGabrielObjective()); + } + } + + public class GabrielAutographConversation : QuestConversation + { + public override object Message => 1055103; + + public override void OnRead() + { + System.AddObjective(new FindSheetMusicObjective(true)); + } + } + + public class GabrielNoSheetMusicConversation : QuestConversation + { + public override object Message => 1055111; + + public override bool Logged => false; + } + + public class NoSheetMusicConversation : QuestConversation + { + public override object Message => 1055106; + + public override bool Logged => false; + } + + public class GetSheetMusicConversation : QuestConversation + { + public override object Message => 1055109; + + public override void OnRead() + { + System.AddObjective(new ReturnSheetMusicObjective()); + } + } + + public class GabrielSheetMusicConversation : QuestConversation + { + public override object Message => 1055113; + + public override void OnRead() + { + System.AddObjective(new ReturnAutographObjective()); + } + } + + public class GabrielIgnoreConversation : QuestConversation + { + public override object Message => 1055118; + + public override bool Logged => false; + } + + public class ElwoodDuringAutograph1Conversation : QuestConversation + { + public override object Message => 1055105; + + public override bool Logged => false; + } + + public class ElwoodDuringAutograph2Conversation : QuestConversation + { + public override object Message => 1055112; + + public override bool Logged => false; + } + + public class ElwoodDuringAutograph3Conversation : QuestConversation + { + public override object Message => 1055115; + + public override bool Logged => false; + } + + public class ReturnAutographConversation : QuestConversation + { + public override object Message => 1055116; + + public override void OnRead() + { + System.AddObjective(new FindTomasObjective()); + } + } + + public class TomasToysConversation : QuestConversation + { + public override object Message => 1055119; + + public override void OnRead() + { + System.AddObjective(new CaptureImagesObjective(true)); + } + } + + public class TomasDuringCollectingConversation : QuestConversation + { + public override object Message => 1055129; + + public override bool Logged => false; + } + + public class ReturnImagesConversation : QuestConversation + { + public override object Message => 1055131; + + public override void OnRead() + { + System.AddObjective(new ReturnToysObjective()); + } + } + + public class ElwoodDuringToys1Conversation : QuestConversation + { + public override object Message => 1055123; + + public override bool Logged => false; + } + + public class ElwoodDuringToys2Conversation : QuestConversation + { + public override object Message => 1055130; + + public override bool Logged => false; + } + + public class ElwoodDuringToys3Conversation : QuestConversation + { + public override object Message => 1055133; + + public override bool Logged => false; + } + + public class EndConversation : QuestConversation + { + public override object Message => 1055134; + + public override void OnRead() + { + System.Complete(); + } + } + + public class FullEndConversation : QuestConversation + { + private readonly bool m_Logged; + + public FullEndConversation(bool logged) => m_Logged = logged; + + public FullEndConversation() => m_Logged = true; + + public override object Message => 1055135; + + public override bool Logged => m_Logged; + + public override void OnRead() + { + if (m_Logged) + System.AddObjective(new MakeRoomObjective()); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Collector/Items/EnchantedPaints.cs b/Projects/UOContent/Engines/Quests/Collector/Items/EnchantedPaints.cs index 7c8477c71..7389c3760 100644 --- a/Projects/UOContent/Engines/Quests/Collector/Items/EnchantedPaints.cs +++ b/Projects/UOContent/Engines/Quests/Collector/Items/EnchantedPaints.cs @@ -1,127 +1,133 @@ -using Server.Mobiles; -using Server.Targeting; - -namespace Server.Engines.Quests.Collector -{ - public class EnchantedPaints : QuestItem - { - [Constructible] - public EnchantedPaints() : base(0xFC1) - { - LootType = LootType.Blessed; - - Weight = 1.0; - } - - public EnchantedPaints(Serial serial) : base(serial) - { - } - - public override bool CanDrop(PlayerMobile player) => !(player.Quest is CollectorQuest); - - public override void OnDoubleClick(Mobile from) - { - if (from is PlayerMobile player) - { - QuestSystem qs = player.Quest; - - if (qs is CollectorQuest) - if (qs.IsObjectiveInProgress(typeof(CaptureImagesObjective))) - { - player.SendAsciiMessage(0x59, "Target the creature whose image you wish to create."); - player.Target = new InternalTarget(this); - - return; - } - } - - from.SendLocalizedMessage(1010085); // You cannot use this. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private class InternalTarget : Target - { - private readonly EnchantedPaints m_Paints; - - public InternalTarget(EnchantedPaints paints) : base(-1, false, TargetFlags.None) - { - CheckLOS = false; - m_Paints = paints; - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Paints.Deleted || !m_Paints.IsChildOf(from.Backpack)) - return; - - if (from is PlayerMobile player) - { - QuestSystem qs = player.Quest; - - if (!(qs is CollectorQuest)) - return; - - CaptureImagesObjective obj = qs.FindObjective(); - - if (obj?.Completed != false) - return; - - if (targeted is Mobile) - { - CaptureResponse response = obj.CaptureImage( - targeted.GetType().Name == "GreaterMongbat" - ? new Mongbat().GetType() - : targeted.GetType(), out ImageType image); - - switch (response) - { - case CaptureResponse.Valid: - { - player.SendLocalizedMessage( - 1055125); // The enchanted paints swirl for a moment then an image begins to take shape. *Click* - player.AddToBackpack(new PaintedImage(image)); - - break; - } - case CaptureResponse.AlreadyDone: - { - player.SendAsciiMessage(0x2C, - "You have already captured the image of this creature"); - - break; - } - case CaptureResponse.Invalid: - { - player.SendLocalizedMessage( - 1055124); // You have no interest in capturing the image of this creature. - - break; - } - } - } - else - { - player.SendAsciiMessage(0x35, "You have no interest in that."); - } - - return; - } - - from.SendLocalizedMessage(1010085); // You cannot use this. - } - } - } -} \ No newline at end of file +using Server.Mobiles; +using Server.Targeting; + +namespace Server.Engines.Quests.Collector +{ + public class EnchantedPaints : QuestItem + { + [Constructible] + public EnchantedPaints() : base(0xFC1) + { + LootType = LootType.Blessed; + + Weight = 1.0; + } + + public EnchantedPaints(Serial serial) : base(serial) + { + } + + public override bool CanDrop(PlayerMobile player) => !(player.Quest is CollectorQuest); + + public override void OnDoubleClick(Mobile from) + { + if (from is PlayerMobile player) + { + var qs = player.Quest; + + if (qs is CollectorQuest) + if (qs.IsObjectiveInProgress(typeof(CaptureImagesObjective))) + { + player.SendAsciiMessage(0x59, "Target the creature whose image you wish to create."); + player.Target = new InternalTarget(this); + + return; + } + } + + from.SendLocalizedMessage(1010085); // You cannot use this. + } + + 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(); + } + + private class InternalTarget : Target + { + private readonly EnchantedPaints m_Paints; + + public InternalTarget(EnchantedPaints paints) : base(-1, false, TargetFlags.None) + { + CheckLOS = false; + m_Paints = paints; + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Paints.Deleted || !m_Paints.IsChildOf(from.Backpack)) + return; + + if (from is PlayerMobile player) + { + var qs = player.Quest; + + if (!(qs is CollectorQuest)) + return; + + var obj = qs.FindObjective(); + + if (obj?.Completed != false) + return; + + if (targeted is Mobile) + { + var response = obj.CaptureImage( + targeted.GetType().Name == "GreaterMongbat" + ? new Mongbat().GetType() + : targeted.GetType(), + out var image + ); + + switch (response) + { + case CaptureResponse.Valid: + { + player.SendLocalizedMessage( + 1055125 + ); // The enchanted paints swirl for a moment then an image begins to take shape. *Click* + player.AddToBackpack(new PaintedImage(image)); + + break; + } + case CaptureResponse.AlreadyDone: + { + player.SendAsciiMessage( + 0x2C, + "You have already captured the image of this creature" + ); + + break; + } + case CaptureResponse.Invalid: + { + player.SendLocalizedMessage( + 1055124 + ); // You have no interest in capturing the image of this creature. + + break; + } + } + } + else + { + player.SendAsciiMessage(0x35, "You have no interest in that."); + } + + return; + } + + from.SendLocalizedMessage(1010085); // You cannot use this. + } + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Collector/Items/ImageTypeInfo.cs b/Projects/UOContent/Engines/Quests/Collector/Items/ImageTypeInfo.cs index 48ef5c891..4b3dd13ce 100644 --- a/Projects/UOContent/Engines/Quests/Collector/Items/ImageTypeInfo.cs +++ b/Projects/UOContent/Engines/Quests/Collector/Items/ImageTypeInfo.cs @@ -1,101 +1,101 @@ -using System; -using Server.Mobiles; - -namespace Server.Engines.Quests.Collector -{ - public enum ImageType - { - Betrayer, - Bogling, - BogThing, - Gazer, - Beetle, - GiantBlackWidow, - Scorpion, - JukaMage, - JukaWarrior, - Lich, - MeerMage, - MeerWarrior, - Mongbat, - Mummy, - Pixie, - PlagueBeast, - SandVortex, - StoneGargoyle, - SwampDragon, - Wisp, - Juggernaut - } - - public class ImageTypeInfo - { - private static readonly ImageTypeInfo[] m_Table = - { - new ImageTypeInfo(9734, typeof(Betrayer), 75, 45), - new ImageTypeInfo(9735, typeof(Bogling), 75, 45), - new ImageTypeInfo(9736, typeof(BogThing), 60, 47), - new ImageTypeInfo(9615, typeof(Gazer), 75, 45), - new ImageTypeInfo(9743, typeof(Beetle), 60, 55), - new ImageTypeInfo(9667, typeof(GiantBlackWidow), 55, 52), - new ImageTypeInfo(9657, typeof(Scorpion), 65, 47), - new ImageTypeInfo(9758, typeof(JukaMage), 75, 45), - new ImageTypeInfo(9759, typeof(JukaWarrior), 75, 45), - new ImageTypeInfo(9636, typeof(Lich), 75, 45), - new ImageTypeInfo(9756, typeof(MeerMage), 75, 45), - new ImageTypeInfo(9757, typeof(MeerWarrior), 75, 45), - new ImageTypeInfo(9638, typeof(Mongbat), 70, 50), - new ImageTypeInfo(9639, typeof(Mummy), 75, 45), - new ImageTypeInfo(9654, typeof(Pixie), 75, 45), - new ImageTypeInfo(9747, typeof(PlagueBeast), 60, 45), - new ImageTypeInfo(9750, typeof(SandVortex), 60, 43), - new ImageTypeInfo(9614, typeof(StoneGargoyle), 75, 45), - new ImageTypeInfo(9753, typeof(SwampDragon), 50, 55), - new ImageTypeInfo(8448, typeof(Wisp), 75, 45), - new ImageTypeInfo(9746, typeof(Juggernaut), 55, 38) - }; - - public ImageTypeInfo(int figurine, Type type, int x, int y) - { - Figurine = figurine; - Type = type; - X = x; - Y = y; - } - - public ImageType Image { get; } - - public int Figurine { get; } - - public Type Type { get; } - - public int Name => Figurine < 0x4000 ? 1020000 + Figurine : 1078872 + Figurine; - public int X { get; } - public int Y { get; } - - public static ImageTypeInfo Get(ImageType image) - { - int index = (int)image; - return m_Table[index >= 0 && index < m_Table.Length ? index : 0]; - } - - public static ImageType[] RandomList(int count) - { - if (count <= 0) return Array.Empty(); - - var length = m_Table.Length; - Span list = stackalloc bool[length]; - var imageTypes = new ImageType[count]; - - int i = 0; - do - { - var rand = Utility.Random(length); - if (!(list[rand] && (list[rand] = true))) - imageTypes[i++] = (ImageType)rand; - } while (i < count); - - return imageTypes; - } - } -} +using System; +using Server.Mobiles; + +namespace Server.Engines.Quests.Collector +{ + public enum ImageType + { + Betrayer, + Bogling, + BogThing, + Gazer, + Beetle, + GiantBlackWidow, + Scorpion, + JukaMage, + JukaWarrior, + Lich, + MeerMage, + MeerWarrior, + Mongbat, + Mummy, + Pixie, + PlagueBeast, + SandVortex, + StoneGargoyle, + SwampDragon, + Wisp, + Juggernaut + } + + public class ImageTypeInfo + { + private static readonly ImageTypeInfo[] m_Table = + { + new ImageTypeInfo(9734, typeof(Betrayer), 75, 45), + new ImageTypeInfo(9735, typeof(Bogling), 75, 45), + new ImageTypeInfo(9736, typeof(BogThing), 60, 47), + new ImageTypeInfo(9615, typeof(Gazer), 75, 45), + new ImageTypeInfo(9743, typeof(Beetle), 60, 55), + new ImageTypeInfo(9667, typeof(GiantBlackWidow), 55, 52), + new ImageTypeInfo(9657, typeof(Scorpion), 65, 47), + new ImageTypeInfo(9758, typeof(JukaMage), 75, 45), + new ImageTypeInfo(9759, typeof(JukaWarrior), 75, 45), + new ImageTypeInfo(9636, typeof(Lich), 75, 45), + new ImageTypeInfo(9756, typeof(MeerMage), 75, 45), + new ImageTypeInfo(9757, typeof(MeerWarrior), 75, 45), + new ImageTypeInfo(9638, typeof(Mongbat), 70, 50), + new ImageTypeInfo(9639, typeof(Mummy), 75, 45), + new ImageTypeInfo(9654, typeof(Pixie), 75, 45), + new ImageTypeInfo(9747, typeof(PlagueBeast), 60, 45), + new ImageTypeInfo(9750, typeof(SandVortex), 60, 43), + new ImageTypeInfo(9614, typeof(StoneGargoyle), 75, 45), + new ImageTypeInfo(9753, typeof(SwampDragon), 50, 55), + new ImageTypeInfo(8448, typeof(Wisp), 75, 45), + new ImageTypeInfo(9746, typeof(Juggernaut), 55, 38) + }; + + public ImageTypeInfo(int figurine, Type type, int x, int y) + { + Figurine = figurine; + Type = type; + X = x; + Y = y; + } + + public ImageType Image { get; } + + public int Figurine { get; } + + public Type Type { get; } + + public int Name => Figurine < 0x4000 ? 1020000 + Figurine : 1078872 + Figurine; + public int X { get; } + public int Y { get; } + + public static ImageTypeInfo Get(ImageType image) + { + var index = (int)image; + return m_Table[index >= 0 && index < m_Table.Length ? index : 0]; + } + + public static ImageType[] RandomList(int count) + { + if (count <= 0) return Array.Empty(); + + var length = m_Table.Length; + Span list = stackalloc bool[length]; + var imageTypes = new ImageType[count]; + + var i = 0; + do + { + var rand = Utility.Random(length); + if (!(list[rand] && (list[rand] = true))) + imageTypes[i++] = (ImageType)rand; + } while (i < count); + + return imageTypes; + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Collector/Items/Obsidian.cs b/Projects/UOContent/Engines/Quests/Collector/Items/Obsidian.cs index 015364af3..db29aff84 100644 --- a/Projects/UOContent/Engines/Quests/Collector/Items/Obsidian.cs +++ b/Projects/UOContent/Engines/Quests/Collector/Items/Obsidian.cs @@ -1,253 +1,282 @@ -using System.Collections.Generic; -using Server.ContextMenus; -using Server.Network; -using Server.Targeting; - -namespace Server.Engines.Quests.Collector -{ - public class Obsidian : Item - { - private const int m_Partial = 2; - private const int m_Completed = 10; - - private static readonly string[] m_Names = - { - null, - "an aggressive cavalier", - "a beguiling rogue", - "a benevolent physician", - "a brilliant artisan", - "a capricious adventurer", - "a clever beggar", - "a convincing charlatan", - "a creative inventor", - "a creative tinker", - "a cunning knave", - "a dauntless explorer", - "a despicable ruffian", - "an earnest malcontent", - "an exultant animal tamer", - "a famed adventurer", - "a fanatical crusader", - "a fastidious clerk", - "a fearless hunter", - "a festive harlequin", - "a fidgety assassin", - "a fierce soldier", - "a fierce warrior", - "a frugal magnate", - "a glib pundit", - "a gnomic shaman", - "a graceful noblewoman", - "a idiotic madman", - "a imaginative designer", - "an inept conjurer", - "an innovative architect", - "an inventive blacksmith", - "a judicious mayor", - "a masterful chef", - "a masterful woodworker", - "a melancholy clown", - "a melodic bard", - "a merciful guard", - "a mirthful jester", - "a nervous surgeon", - "a peaceful scholar", - "a prolific gardener", - "a quixotic knight", - "a regal aristocrat", - "a resourceful smith", - "a reticent alchemist", - "a sanctified priest", - "a scheming patrician", - "a shrewd mage", - "a singing minstrel", - "a skilled tailor", - "a squeamish assassin", - "a stoic swordsman", - "a studious scribe", - "a thought provoking writer", - "a treacherous scoundrel", - "a troubled poet", - "an unflappable wizard", - "a valiant warrior", - "a wayward fool" - }; - - private int m_Quantity; - private string m_StatueName; - - [Constructible] - public Obsidian() : base(0x1EA7) - { - Hue = 0x497; - - m_Quantity = 1; - m_StatueName = ""; - } - - public Obsidian(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Quantity - { - get => m_Quantity; - set - { - if (value <= 1) - m_Quantity = 1; - else if (value >= m_Completed) - m_Quantity = m_Completed; - else - m_Quantity = value; - - if (m_Quantity < m_Partial) - ItemID = 0x1EA7; - else if (m_Quantity < m_Completed) - ItemID = 0x1F13; - else - ItemID = 0x12CB; - - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public string StatueName - { - get => m_StatueName; - set - { - m_StatueName = value; - InvalidateProperties(); - } - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public static string RandomName(Mobile from) => m_Names.RandomElement() ?? from.Name; - - public override void AddNameProperty(ObjectPropertyList list) - { - if (m_Quantity < m_Partial) - list.Add(1055137); // a section of an obsidian statue - else if (m_Quantity < m_Completed) - list.Add(1055138); // a partially reconstructed obsidian statue - else - list.Add(1055139, m_StatueName); // an obsidian statue of ~1_STATUE_NAME~ - } - - public override void OnSingleClick(Mobile from) - { - if (m_Quantity < m_Partial) - LabelTo(from, 1055137); // a section of an obsidian statue - else if (m_Quantity < m_Completed) - LabelTo(from, 1055138); // a partially reconstructed obsidian statue - else - LabelTo(from, 1055139, m_StatueName); // an obsidian statue of ~1_STATUE_NAME~ - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (from.Alive && m_Quantity >= m_Partial && m_Quantity < m_Completed && IsChildOf(from.Backpack)) - list.Add(new DisassembleEntry(this)); - } - - public override void OnDoubleClick(Mobile from) - { - if (m_Quantity < m_Completed) - { - if (!IsChildOf(from.Backpack)) - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, 0x2C, 3, 500309, "", - "")); // Nothing Happens. - else - from.Target = new InternalTarget(this); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.WriteEncodedInt(m_Quantity); - writer.Write(m_StatueName); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Quantity = reader.ReadEncodedInt(); - m_StatueName = Utility.Intern(reader.ReadString()); - } - - private class DisassembleEntry : ContextMenuEntry - { - private readonly Obsidian m_Obsidian; - - public DisassembleEntry(Obsidian obsidian) : base(6142) => m_Obsidian = obsidian; - - public override void OnClick() - { - Mobile from = Owner.From; - if (!m_Obsidian.Deleted && m_Obsidian.Quantity >= m_Partial && m_Obsidian.Quantity < m_Completed && - m_Obsidian.IsChildOf(from.Backpack) && from.CheckAlive()) - { - for (int i = 0; i < m_Obsidian.Quantity - 1; i++) - from.AddToBackpack(new Obsidian()); - - m_Obsidian.Quantity = 1; - } - } - } - - private class InternalTarget : Target - { - private readonly Obsidian m_Obsidian; - - public InternalTarget(Obsidian obsidian) : base(-1, false, TargetFlags.None) => m_Obsidian = obsidian; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Obsidian.Deleted || m_Obsidian.Quantity >= m_Completed || !(targeted is Item targ)) - return; - - if (m_Obsidian.IsChildOf(from.Backpack) && targ.IsChildOf(from.Backpack) && targ is Obsidian targObsidian && - targ != m_Obsidian) - if (targObsidian.Quantity < m_Completed) - { - if (targObsidian.Quantity + m_Obsidian.Quantity <= m_Completed) - { - targObsidian.Quantity += m_Obsidian.Quantity; - m_Obsidian.Delete(); - } - else - { - int delta = m_Completed - targObsidian.Quantity; - targObsidian.Quantity += delta; - m_Obsidian.Quantity -= delta; - } - - if (targObsidian.Quantity >= m_Completed) - targObsidian.StatueName = RandomName(from); - - from.Send(new AsciiMessage(targObsidian.Serial, targObsidian.ItemID, MessageType.Regular, 0x59, 3, - m_Obsidian.Name, "Something Happened.")); - - return; - } - - from.Send(new MessageLocalized(m_Obsidian.Serial, m_Obsidian.ItemID, MessageType.Regular, 0x2C, 3, 500309, - m_Obsidian.Name, "")); // Nothing Happens. - } - } - } -} +using System.Collections.Generic; +using Server.ContextMenus; +using Server.Network; +using Server.Targeting; + +namespace Server.Engines.Quests.Collector +{ + public class Obsidian : Item + { + private const int m_Partial = 2; + private const int m_Completed = 10; + + private static readonly string[] m_Names = + { + null, + "an aggressive cavalier", + "a beguiling rogue", + "a benevolent physician", + "a brilliant artisan", + "a capricious adventurer", + "a clever beggar", + "a convincing charlatan", + "a creative inventor", + "a creative tinker", + "a cunning knave", + "a dauntless explorer", + "a despicable ruffian", + "an earnest malcontent", + "an exultant animal tamer", + "a famed adventurer", + "a fanatical crusader", + "a fastidious clerk", + "a fearless hunter", + "a festive harlequin", + "a fidgety assassin", + "a fierce soldier", + "a fierce warrior", + "a frugal magnate", + "a glib pundit", + "a gnomic shaman", + "a graceful noblewoman", + "a idiotic madman", + "a imaginative designer", + "an inept conjurer", + "an innovative architect", + "an inventive blacksmith", + "a judicious mayor", + "a masterful chef", + "a masterful woodworker", + "a melancholy clown", + "a melodic bard", + "a merciful guard", + "a mirthful jester", + "a nervous surgeon", + "a peaceful scholar", + "a prolific gardener", + "a quixotic knight", + "a regal aristocrat", + "a resourceful smith", + "a reticent alchemist", + "a sanctified priest", + "a scheming patrician", + "a shrewd mage", + "a singing minstrel", + "a skilled tailor", + "a squeamish assassin", + "a stoic swordsman", + "a studious scribe", + "a thought provoking writer", + "a treacherous scoundrel", + "a troubled poet", + "an unflappable wizard", + "a valiant warrior", + "a wayward fool" + }; + + private int m_Quantity; + private string m_StatueName; + + [Constructible] + public Obsidian() : base(0x1EA7) + { + Hue = 0x497; + + m_Quantity = 1; + m_StatueName = ""; + } + + public Obsidian(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Quantity + { + get => m_Quantity; + set + { + if (value <= 1) + m_Quantity = 1; + else if (value >= m_Completed) + m_Quantity = m_Completed; + else + m_Quantity = value; + + if (m_Quantity < m_Partial) + ItemID = 0x1EA7; + else if (m_Quantity < m_Completed) + ItemID = 0x1F13; + else + ItemID = 0x12CB; + + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public string StatueName + { + get => m_StatueName; + set + { + m_StatueName = value; + InvalidateProperties(); + } + } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + public static string RandomName(Mobile from) => m_Names.RandomElement() ?? from.Name; + + public override void AddNameProperty(ObjectPropertyList list) + { + if (m_Quantity < m_Partial) + list.Add(1055137); // a section of an obsidian statue + else if (m_Quantity < m_Completed) + list.Add(1055138); // a partially reconstructed obsidian statue + else + list.Add(1055139, m_StatueName); // an obsidian statue of ~1_STATUE_NAME~ + } + + public override void OnSingleClick(Mobile from) + { + if (m_Quantity < m_Partial) + LabelTo(from, 1055137); // a section of an obsidian statue + else if (m_Quantity < m_Completed) + LabelTo(from, 1055138); // a partially reconstructed obsidian statue + else + LabelTo(from, 1055139, m_StatueName); // an obsidian statue of ~1_STATUE_NAME~ + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (from.Alive && m_Quantity >= m_Partial && m_Quantity < m_Completed && IsChildOf(from.Backpack)) + list.Add(new DisassembleEntry(this)); + } + + public override void OnDoubleClick(Mobile from) + { + if (m_Quantity < m_Completed) + { + if (!IsChildOf(from.Backpack)) + from.Send( + new MessageLocalized( + Serial, + ItemID, + MessageType.Regular, + 0x2C, + 3, + 500309, + "", + "" + ) + ); // Nothing Happens. + else + from.Target = new InternalTarget(this); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.WriteEncodedInt(m_Quantity); + writer.Write(m_StatueName); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Quantity = reader.ReadEncodedInt(); + m_StatueName = Utility.Intern(reader.ReadString()); + } + + private class DisassembleEntry : ContextMenuEntry + { + private readonly Obsidian m_Obsidian; + + public DisassembleEntry(Obsidian obsidian) : base(6142) => m_Obsidian = obsidian; + + public override void OnClick() + { + var from = Owner.From; + if (!m_Obsidian.Deleted && m_Obsidian.Quantity >= m_Partial && m_Obsidian.Quantity < m_Completed && + m_Obsidian.IsChildOf(from.Backpack) && from.CheckAlive()) + { + for (var i = 0; i < m_Obsidian.Quantity - 1; i++) + from.AddToBackpack(new Obsidian()); + + m_Obsidian.Quantity = 1; + } + } + } + + private class InternalTarget : Target + { + private readonly Obsidian m_Obsidian; + + public InternalTarget(Obsidian obsidian) : base(-1, false, TargetFlags.None) => m_Obsidian = obsidian; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Obsidian.Deleted || m_Obsidian.Quantity >= m_Completed || !(targeted is Item targ)) + return; + + if (m_Obsidian.IsChildOf(from.Backpack) && targ.IsChildOf(from.Backpack) && targ is Obsidian targObsidian && + targ != m_Obsidian) + if (targObsidian.Quantity < m_Completed) + { + if (targObsidian.Quantity + m_Obsidian.Quantity <= m_Completed) + { + targObsidian.Quantity += m_Obsidian.Quantity; + m_Obsidian.Delete(); + } + else + { + var delta = m_Completed - targObsidian.Quantity; + targObsidian.Quantity += delta; + m_Obsidian.Quantity -= delta; + } + + if (targObsidian.Quantity >= m_Completed) + targObsidian.StatueName = RandomName(from); + + from.Send( + new AsciiMessage( + targObsidian.Serial, + targObsidian.ItemID, + MessageType.Regular, + 0x59, + 3, + m_Obsidian.Name, + "Something Happened." + ) + ); + + return; + } + + from.Send( + new MessageLocalized( + m_Obsidian.Serial, + m_Obsidian.ItemID, + MessageType.Regular, + 0x2C, + 3, + 500309, + m_Obsidian.Name, + "" + ) + ); // Nothing Happens. + } + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Collector/Items/PaintedImage.cs b/Projects/UOContent/Engines/Quests/Collector/Items/PaintedImage.cs index 1a8366ff0..afd44311f 100644 --- a/Projects/UOContent/Engines/Quests/Collector/Items/PaintedImage.cs +++ b/Projects/UOContent/Engines/Quests/Collector/Items/PaintedImage.cs @@ -1,88 +1,88 @@ -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.Quests.Collector -{ - public class PaintedImage : Item - { - private ImageType m_Image; - - [Constructible] - public PaintedImage(ImageType image) : base(0xFF3) - { - Weight = 1.0; - Hue = 0x8FD; - - m_Image = image; - } - - public PaintedImage(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public ImageType Image - { - get => m_Image; - set - { - m_Image = value; - InvalidateProperties(); - } - } - - public override void AddNameProperty(ObjectPropertyList list) - { - ImageTypeInfo info = ImageTypeInfo.Get(m_Image); - list.Add(1060847, $"#1055126\t#{info.Name}"); // a painted image of: - } - - public override void OnSingleClick(Mobile from) - { - ImageTypeInfo info = ImageTypeInfo.Get(m_Image); - LabelTo(from, 1060847, $"#1055126\t#{info.Name}"); // a painted image of: - } - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return; - } - - from.SendGump(new InternalGump(m_Image)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.WriteEncodedInt((int)m_Image); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Image = (ImageType)reader.ReadEncodedInt(); - } - - private class InternalGump : Gump - { - public InternalGump(ImageType image) : base(75, 25) - { - ImageTypeInfo info = ImageTypeInfo.Get(image); - - AddBackground(45, 20, 100, 100, 0xA3C); - AddBackground(52, 29, 86, 82, 0xBB8); - - AddItem(info.X, info.Y, info.Figurine); - } - } - } -} \ No newline at end of file +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.Quests.Collector +{ + public class PaintedImage : Item + { + private ImageType m_Image; + + [Constructible] + public PaintedImage(ImageType image) : base(0xFF3) + { + Weight = 1.0; + Hue = 0x8FD; + + m_Image = image; + } + + public PaintedImage(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public ImageType Image + { + get => m_Image; + set + { + m_Image = value; + InvalidateProperties(); + } + } + + public override void AddNameProperty(ObjectPropertyList list) + { + var info = ImageTypeInfo.Get(m_Image); + list.Add(1060847, $"#1055126\t#{info.Name}"); // a painted image of: + } + + public override void OnSingleClick(Mobile from) + { + var info = ImageTypeInfo.Get(m_Image); + LabelTo(from, 1060847, $"#1055126\t#{info.Name}"); // a painted image of: + } + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return; + } + + from.SendGump(new InternalGump(m_Image)); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.WriteEncodedInt((int)m_Image); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Image = (ImageType)reader.ReadEncodedInt(); + } + + private class InternalGump : Gump + { + public InternalGump(ImageType image) : base(75, 25) + { + var info = ImageTypeInfo.Get(image); + + AddBackground(45, 20, 100, 100, 0xA3C); + AddBackground(52, 29, 86, 82, 0xBB8); + + AddItem(info.X, info.Y, info.Figurine); + } + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Collector/Mobiles/AlbertaGiacco.cs b/Projects/UOContent/Engines/Quests/Collector/Mobiles/AlbertaGiacco.cs index a5cb369fe..f45ac44cf 100644 --- a/Projects/UOContent/Engines/Quests/Collector/Mobiles/AlbertaGiacco.cs +++ b/Projects/UOContent/Engines/Quests/Collector/Mobiles/AlbertaGiacco.cs @@ -1,86 +1,86 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Collector -{ - public class AlbertaGiacco : BaseQuester - { - [Constructible] - public AlbertaGiacco() : base("the respected painter") - { - } - - public AlbertaGiacco(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Alberta Giacco"; - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = 0x83F2; - - Female = true; - Body = 0x191; - } - - public override void InitOutfit() - { - AddItem(new FancyShirt()); - AddItem(new Skirt(0x59B)); - AddItem(new Boots()); - AddItem(new FeatheredHat(0x59B)); - AddItem(new FullApron(0x59B)); - - HairItemID = 0x203D; // Pony Tail - HairHue = 0x457; - } - - public override bool CanTalkTo(PlayerMobile to) - { - QuestSystem qs = to.Quest as CollectorQuest; - - if (qs == null) - return false; - - return qs.IsObjectiveInProgress(typeof(FindAlbertaObjective)) - || qs.IsObjectiveInProgress(typeof(SitOnTheStoolObjective)) - || qs.IsObjectiveInProgress(typeof(ReturnPaintingObjective)); - } - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - QuestSystem qs = player.Quest; - - if (qs is CollectorQuest) - { - Direction = GetDirectionTo(player); - - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - obj.Complete(); - else if (qs.IsObjectiveInProgress(typeof(SitOnTheStoolObjective))) - qs.AddConversation(new AlbertaStoolConversation()); - else if (qs.IsObjectiveInProgress(typeof(ReturnPaintingObjective))) - qs.AddConversation(new AlbertaAfterPaintingConversation()); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Collector +{ + public class AlbertaGiacco : BaseQuester + { + [Constructible] + public AlbertaGiacco() : base("the respected painter") + { + } + + public AlbertaGiacco(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Alberta Giacco"; + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = 0x83F2; + + Female = true; + Body = 0x191; + } + + public override void InitOutfit() + { + AddItem(new FancyShirt()); + AddItem(new Skirt(0x59B)); + AddItem(new Boots()); + AddItem(new FeatheredHat(0x59B)); + AddItem(new FullApron(0x59B)); + + HairItemID = 0x203D; // Pony Tail + HairHue = 0x457; + } + + public override bool CanTalkTo(PlayerMobile to) + { + QuestSystem qs = to.Quest as CollectorQuest; + + if (qs == null) + return false; + + return qs.IsObjectiveInProgress(typeof(FindAlbertaObjective)) + || qs.IsObjectiveInProgress(typeof(SitOnTheStoolObjective)) + || qs.IsObjectiveInProgress(typeof(ReturnPaintingObjective)); + } + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + var qs = player.Quest; + + if (qs is CollectorQuest) + { + Direction = GetDirectionTo(player); + + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + obj.Complete(); + else if (qs.IsObjectiveInProgress(typeof(SitOnTheStoolObjective))) + qs.AddConversation(new AlbertaStoolConversation()); + else if (qs.IsObjectiveInProgress(typeof(ReturnPaintingObjective))) + qs.AddConversation(new AlbertaAfterPaintingConversation()); + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Collector/Mobiles/ElwoodMcCarrin.cs b/Projects/UOContent/Engines/Quests/Collector/Mobiles/ElwoodMcCarrin.cs index 0976685d8..2120d0f7c 100644 --- a/Projects/UOContent/Engines/Quests/Collector/Mobiles/ElwoodMcCarrin.cs +++ b/Projects/UOContent/Engines/Quests/Collector/Mobiles/ElwoodMcCarrin.cs @@ -1,228 +1,228 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Collector -{ - public class ElwoodMcCarrin : BaseQuester - { - [Constructible] - public ElwoodMcCarrin() : base("the well-known collector") - { - } - - public ElwoodMcCarrin(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Elwood McCarrin"; - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = 0x83ED; - - Female = false; - Body = 0x190; - } - - public override void InitOutfit() - { - AddItem(new FancyShirt()); - AddItem(new LongPants(0x544)); - AddItem(new Shoes(0x454)); - AddItem(new JesterHat(0x4D2)); - AddItem(new FullApron(0x4D2)); - - HairItemID = 0x203D; // Pony Tail - HairHue = 0x47D; - - FacialHairItemID = 0x2040; // Goatee - FacialHairHue = 0x47D; - } - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - Direction = GetDirectionTo(player); - - QuestSystem qs = player.Quest; - - if (qs is CollectorQuest) - { - if (qs.IsObjectiveInProgress(typeof(FishPearlsObjective))) - { - qs.AddConversation(new ElwoodDuringFishConversation()); - } - else - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - obj.Complete(); - } - else if (qs.IsObjectiveInProgress(typeof(FindAlbertaObjective))) - { - qs.AddConversation(new ElwoodDuringPainting1Conversation()); - } - else if (qs.IsObjectiveInProgress(typeof(SitOnTheStoolObjective))) - { - qs.AddConversation(new ElwoodDuringPainting2Conversation()); - } - else - { - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - obj.Complete(); - } - else if (qs.IsObjectiveInProgress(typeof(FindGabrielObjective))) - { - qs.AddConversation(new ElwoodDuringAutograph1Conversation()); - } - else if (qs.IsObjectiveInProgress(typeof(FindSheetMusicObjective))) - { - qs.AddConversation(new ElwoodDuringAutograph2Conversation()); - } - else if (qs.IsObjectiveInProgress(typeof(ReturnSheetMusicObjective))) - { - qs.AddConversation(new ElwoodDuringAutograph3Conversation()); - } - else - { - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - obj.Complete(); - } - else if (qs.IsObjectiveInProgress(typeof(FindTomasObjective))) - { - qs.AddConversation(new ElwoodDuringToys1Conversation()); - } - else if (qs.IsObjectiveInProgress(typeof(CaptureImagesObjective))) - { - qs.AddConversation(new ElwoodDuringToys2Conversation()); - } - else if (qs.IsObjectiveInProgress(typeof(ReturnImagesObjective))) - { - qs.AddConversation(new ElwoodDuringToys3Conversation()); - } - else - { - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - obj.Complete(); - - if (GiveReward(player)) - qs.AddConversation(new EndConversation()); - else - qs.AddConversation(new FullEndConversation(true)); - } - else - { - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - if (GiveReward(player)) - { - obj.Complete(); - qs.AddConversation(new EndConversation()); - } - else - { - qs.AddConversation(new FullEndConversation(false)); - } - } - } - } - } - } - } - } - else - { - QuestSystem newQuest = new CollectorQuest(player); - - if (qs == null && QuestSystem.CanOfferQuest(player, typeof(CollectorQuest))) - newQuest.SendOffer(); - else - newQuest.AddConversation(new DontOfferConversation()); - } - } - - public bool GiveReward(Mobile to) - { - Bag bag = new Bag(); - - bag.DropItem(new Gold(Utility.RandomMinMax(500, 1000))); - - if (Utility.RandomBool()) - { - BaseWeapon weapon = Loot.RandomWeapon(); - - if (Core.AOS) - { - BaseRunicTool.ApplyAttributesTo(weapon, 2, 20, 30); - } - else - { - weapon.DamageLevel = (WeaponDamageLevel)RandomMinMaxScaled(2, 3); - weapon.AccuracyLevel = (WeaponAccuracyLevel)RandomMinMaxScaled(2, 3); - weapon.DurabilityLevel = (WeaponDurabilityLevel)RandomMinMaxScaled(2, 3); - } - - bag.DropItem(weapon); - } - else - { - Item item; - - if (Core.AOS) - { - item = Loot.RandomArmorOrShieldOrJewelry(); - - if (item is BaseArmor armor) - BaseRunicTool.ApplyAttributesTo(armor, 2, 20, 30); - else if (item is BaseJewel jewel) - BaseRunicTool.ApplyAttributesTo(jewel, 2, 20, 30); - } - else - { - BaseArmor armor = Loot.RandomArmorOrShield(); - item = armor; - - armor.ProtectionLevel = (ArmorProtectionLevel)RandomMinMaxScaled(2, 3); - armor.Durability = (ArmorDurabilityLevel)RandomMinMaxScaled(2, 3); - } - - bag.DropItem(item); - } - - bag.DropItem(new Obsidian()); - - if (to.PlaceInBackpack(bag)) return true; - - bag.Delete(); - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Collector +{ + public class ElwoodMcCarrin : BaseQuester + { + [Constructible] + public ElwoodMcCarrin() : base("the well-known collector") + { + } + + public ElwoodMcCarrin(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Elwood McCarrin"; + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = 0x83ED; + + Female = false; + Body = 0x190; + } + + public override void InitOutfit() + { + AddItem(new FancyShirt()); + AddItem(new LongPants(0x544)); + AddItem(new Shoes(0x454)); + AddItem(new JesterHat(0x4D2)); + AddItem(new FullApron(0x4D2)); + + HairItemID = 0x203D; // Pony Tail + HairHue = 0x47D; + + FacialHairItemID = 0x2040; // Goatee + FacialHairHue = 0x47D; + } + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + Direction = GetDirectionTo(player); + + var qs = player.Quest; + + if (qs is CollectorQuest) + { + if (qs.IsObjectiveInProgress(typeof(FishPearlsObjective))) + { + qs.AddConversation(new ElwoodDuringFishConversation()); + } + else + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + obj.Complete(); + } + else if (qs.IsObjectiveInProgress(typeof(FindAlbertaObjective))) + { + qs.AddConversation(new ElwoodDuringPainting1Conversation()); + } + else if (qs.IsObjectiveInProgress(typeof(SitOnTheStoolObjective))) + { + qs.AddConversation(new ElwoodDuringPainting2Conversation()); + } + else + { + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + obj.Complete(); + } + else if (qs.IsObjectiveInProgress(typeof(FindGabrielObjective))) + { + qs.AddConversation(new ElwoodDuringAutograph1Conversation()); + } + else if (qs.IsObjectiveInProgress(typeof(FindSheetMusicObjective))) + { + qs.AddConversation(new ElwoodDuringAutograph2Conversation()); + } + else if (qs.IsObjectiveInProgress(typeof(ReturnSheetMusicObjective))) + { + qs.AddConversation(new ElwoodDuringAutograph3Conversation()); + } + else + { + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + obj.Complete(); + } + else if (qs.IsObjectiveInProgress(typeof(FindTomasObjective))) + { + qs.AddConversation(new ElwoodDuringToys1Conversation()); + } + else if (qs.IsObjectiveInProgress(typeof(CaptureImagesObjective))) + { + qs.AddConversation(new ElwoodDuringToys2Conversation()); + } + else if (qs.IsObjectiveInProgress(typeof(ReturnImagesObjective))) + { + qs.AddConversation(new ElwoodDuringToys3Conversation()); + } + else + { + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + obj.Complete(); + + if (GiveReward(player)) + qs.AddConversation(new EndConversation()); + else + qs.AddConversation(new FullEndConversation(true)); + } + else + { + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + if (GiveReward(player)) + { + obj.Complete(); + qs.AddConversation(new EndConversation()); + } + else + { + qs.AddConversation(new FullEndConversation(false)); + } + } + } + } + } + } + } + } + else + { + QuestSystem newQuest = new CollectorQuest(player); + + if (qs == null && QuestSystem.CanOfferQuest(player, typeof(CollectorQuest))) + newQuest.SendOffer(); + else + newQuest.AddConversation(new DontOfferConversation()); + } + } + + public bool GiveReward(Mobile to) + { + var bag = new Bag(); + + bag.DropItem(new Gold(Utility.RandomMinMax(500, 1000))); + + if (Utility.RandomBool()) + { + var weapon = Loot.RandomWeapon(); + + if (Core.AOS) + { + BaseRunicTool.ApplyAttributesTo(weapon, 2, 20, 30); + } + else + { + weapon.DamageLevel = (WeaponDamageLevel)RandomMinMaxScaled(2, 3); + weapon.AccuracyLevel = (WeaponAccuracyLevel)RandomMinMaxScaled(2, 3); + weapon.DurabilityLevel = (WeaponDurabilityLevel)RandomMinMaxScaled(2, 3); + } + + bag.DropItem(weapon); + } + else + { + Item item; + + if (Core.AOS) + { + item = Loot.RandomArmorOrShieldOrJewelry(); + + if (item is BaseArmor armor) + BaseRunicTool.ApplyAttributesTo(armor, 2, 20, 30); + else if (item is BaseJewel jewel) + BaseRunicTool.ApplyAttributesTo(jewel, 2, 20, 30); + } + else + { + var armor = Loot.RandomArmorOrShield(); + item = armor; + + armor.ProtectionLevel = (ArmorProtectionLevel)RandomMinMaxScaled(2, 3); + armor.Durability = (ArmorDurabilityLevel)RandomMinMaxScaled(2, 3); + } + + bag.DropItem(item); + } + + bag.DropItem(new Obsidian()); + + if (to.PlaceInBackpack(bag)) return true; + + bag.Delete(); + return 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Collector/Mobiles/GabrielPiete.cs b/Projects/UOContent/Engines/Quests/Collector/Mobiles/GabrielPiete.cs index 3a475ef9f..75e7cf5ed 100644 --- a/Projects/UOContent/Engines/Quests/Collector/Mobiles/GabrielPiete.cs +++ b/Projects/UOContent/Engines/Quests/Collector/Mobiles/GabrielPiete.cs @@ -1,99 +1,99 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Collector -{ - public class GabrielPiete : BaseQuester - { - [Constructible] - public GabrielPiete() : base("the renowned minstrel") - { - } - - public GabrielPiete(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Gabriel Piete"; - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = 0x83EF; - - Female = false; - Body = 0x190; - } - - public override void InitOutfit() - { - AddItem(new FancyShirt()); - AddItem(new LongPants(0x5F7)); - AddItem(new Shoes(0x5F7)); - - HairItemID = 0x2049; // Pig Tails - HairHue = 0x460; - - FacialHairItemID = 0x2041; // Mustache - FacialHairHue = 0x460; - } - - public override bool CanTalkTo(PlayerMobile to) - { - QuestSystem qs = to.Quest as CollectorQuest; - - if (qs == null) - return false; - - return qs.IsObjectiveInProgress(typeof(FindGabrielObjective)) - || qs.IsObjectiveInProgress(typeof(FindSheetMusicObjective)) - || qs.IsObjectiveInProgress(typeof(ReturnSheetMusicObjective)) - || qs.IsObjectiveInProgress(typeof(ReturnAutographObjective)); - } - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - QuestSystem qs = player.Quest; - - if (qs is CollectorQuest) - { - Direction = GetDirectionTo(player); - - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - obj.Complete(); - } - else if (qs.IsObjectiveInProgress(typeof(FindSheetMusicObjective))) - { - qs.AddConversation(new GabrielNoSheetMusicConversation()); - } - else - { - obj = qs.FindObjective(); - - if (obj?.Completed == false) - obj.Complete(); - else if (qs.IsObjectiveInProgress(typeof(ReturnAutographObjective))) - qs.AddConversation(new GabrielIgnoreConversation()); - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Collector +{ + public class GabrielPiete : BaseQuester + { + [Constructible] + public GabrielPiete() : base("the renowned minstrel") + { + } + + public GabrielPiete(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Gabriel Piete"; + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = 0x83EF; + + Female = false; + Body = 0x190; + } + + public override void InitOutfit() + { + AddItem(new FancyShirt()); + AddItem(new LongPants(0x5F7)); + AddItem(new Shoes(0x5F7)); + + HairItemID = 0x2049; // Pig Tails + HairHue = 0x460; + + FacialHairItemID = 0x2041; // Mustache + FacialHairHue = 0x460; + } + + public override bool CanTalkTo(PlayerMobile to) + { + QuestSystem qs = to.Quest as CollectorQuest; + + if (qs == null) + return false; + + return qs.IsObjectiveInProgress(typeof(FindGabrielObjective)) + || qs.IsObjectiveInProgress(typeof(FindSheetMusicObjective)) + || qs.IsObjectiveInProgress(typeof(ReturnSheetMusicObjective)) + || qs.IsObjectiveInProgress(typeof(ReturnAutographObjective)); + } + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + var qs = player.Quest; + + if (qs is CollectorQuest) + { + Direction = GetDirectionTo(player); + + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + obj.Complete(); + } + else if (qs.IsObjectiveInProgress(typeof(FindSheetMusicObjective))) + { + qs.AddConversation(new GabrielNoSheetMusicConversation()); + } + else + { + obj = qs.FindObjective(); + + if (obj?.Completed == false) + obj.Complete(); + else if (qs.IsObjectiveInProgress(typeof(ReturnAutographObjective))) + qs.AddConversation(new GabrielIgnoreConversation()); + } + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Collector/Mobiles/Impresario.cs b/Projects/UOContent/Engines/Quests/Collector/Mobiles/Impresario.cs index c3f0c8c8a..5d5d39d9c 100644 --- a/Projects/UOContent/Engines/Quests/Collector/Mobiles/Impresario.cs +++ b/Projects/UOContent/Engines/Quests/Collector/Mobiles/Impresario.cs @@ -1,162 +1,171 @@ -using Server.Gumps; -using Server.Items; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.Quests.Collector -{ - public class Impresario : BaseQuester - { - [Constructible] - public Impresario() : base("the impresario") - { - } - - public Impresario(Serial serial) : base(serial) - { - } - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = Race.Human.RandomSkinHue(); - - Female = false; - Body = 0x190; - Name = NameList.RandomName("male"); - } - - public override void InitOutfit() - { - AddItem(new FancyShirt(Utility.RandomDyedHue())); - AddItem(new LongPants(Utility.RandomNondyedHue())); - AddItem(new Shoes(Utility.RandomNeutralHue())); - - Utility.AssignRandomHair(this); - Utility.AssignRandomFacialHair(this); - } - - public override bool CanTalkTo(PlayerMobile to) - { - QuestSystem qs = to.Quest as CollectorQuest; - - if (qs == null) - return false; - - return qs.IsObjectiveInProgress(typeof(FindSheetMusicObjective)); - } - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - QuestSystem qs = player.Quest; - - if (!(qs is CollectorQuest)) - return; - - FindSheetMusicObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - Direction = GetDirectionTo(player); - - if (obj.IsInRightTheater()) - { - player.CloseGump(); - player.SendGump(new SheetMusicOfferGump()); - } - else - { - qs.AddConversation(new NoSheetMusicConversation()); - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SheetMusicOfferGump : BaseQuestGump - { - public SheetMusicOfferGump() : base(75, 25) - { - Closable = false; - - AddImage(349, 10, 0x24B0); - AddImageTiled(349, 130, 100, 120, 0x24B3); - AddImageTiled(149, 10, 200, 140, 0x24AF); - AddImageTiled(149, 300, 200, 140, 0x24B5); - AddImage(349, 300, 0x24B6); - AddImage(35, 10, 0x24AE); - AddImageTiled(35, 150, 120, 100, 0x24B1); - AddImage(35, 300, 0x24B4); - - AddHtmlLocalized(110, 60, 200, 20, 1049069, White); // Conversation Event - - AddImage(65, 14, 0x2776); - AddImageTiled(81, 14, 349, 17, 0x2775); - AddImage(426, 14, 0x2778); - - AddImageTiled(50, 37, 400, 376, 0xA40); - AddAlphaRegion(50, 37, 400, 376); - - AddImage(0, 0, 0x28C8); - - AddImageTiled(75, 90, 200, 1, 0x238D); - AddImage(75, 58, 0x2635); - AddImage(380, 45, 0xDF); - - AddHtmlLocalized(98, 140, 312, 200, 1055107, LightGreen, false, - true); // Sure, I have some sheet music for a Gabriel Piete song. I'd be happy to sell you a copy for 10 gold. - - AddRadio(85, 350, 0x25F8, 0x25FB, true, 1); - AddHtmlLocalized(120, 356, 280, 20, 1014088, White); // I accept. - - AddRadio(85, 385, 0x25F8, 0x25FB, false, 0); - AddHtmlLocalized(120, 391, 280, 20, 1049012, White); // No thanks, I decline. - - AddButton(340, 390, 0xF7, 0xF8, 1); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 1 && info.IsSwitched(1)) - if (sender.Mobile is PlayerMobile player) - { - QuestSystem qs = player.Quest; - - if (!(qs is CollectorQuest)) - return; - - FindSheetMusicObjective obj = qs.FindObjective(); - - if (obj?.Completed != false) - return; - - if (player.Backpack?.ConsumeTotal(typeof(Gold), 10) == true) - { - obj.Complete(); - } - else - { - if (player.FindBankNoCreate()?.ConsumeTotal(typeof(Gold), 10) == true) - obj.Complete(); - else - player.SendLocalizedMessage( - 1055108); // You don't have enough gold to buy the sheet music. - } - } - } - } -} +using Server.Gumps; +using Server.Items; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.Quests.Collector +{ + public class Impresario : BaseQuester + { + [Constructible] + public Impresario() : base("the impresario") + { + } + + public Impresario(Serial serial) : base(serial) + { + } + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = Race.Human.RandomSkinHue(); + + Female = false; + Body = 0x190; + Name = NameList.RandomName("male"); + } + + public override void InitOutfit() + { + AddItem(new FancyShirt(Utility.RandomDyedHue())); + AddItem(new LongPants(Utility.RandomNondyedHue())); + AddItem(new Shoes(Utility.RandomNeutralHue())); + + Utility.AssignRandomHair(this); + Utility.AssignRandomFacialHair(this); + } + + public override bool CanTalkTo(PlayerMobile to) + { + QuestSystem qs = to.Quest as CollectorQuest; + + if (qs == null) + return false; + + return qs.IsObjectiveInProgress(typeof(FindSheetMusicObjective)); + } + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + var qs = player.Quest; + + if (!(qs is CollectorQuest)) + return; + + var obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + Direction = GetDirectionTo(player); + + if (obj.IsInRightTheater()) + { + player.CloseGump(); + player.SendGump(new SheetMusicOfferGump()); + } + else + { + qs.AddConversation(new NoSheetMusicConversation()); + } + } + } + + 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 class SheetMusicOfferGump : BaseQuestGump + { + public SheetMusicOfferGump() : base(75, 25) + { + Closable = false; + + AddImage(349, 10, 0x24B0); + AddImageTiled(349, 130, 100, 120, 0x24B3); + AddImageTiled(149, 10, 200, 140, 0x24AF); + AddImageTiled(149, 300, 200, 140, 0x24B5); + AddImage(349, 300, 0x24B6); + AddImage(35, 10, 0x24AE); + AddImageTiled(35, 150, 120, 100, 0x24B1); + AddImage(35, 300, 0x24B4); + + AddHtmlLocalized(110, 60, 200, 20, 1049069, White); // Conversation Event + + AddImage(65, 14, 0x2776); + AddImageTiled(81, 14, 349, 17, 0x2775); + AddImage(426, 14, 0x2778); + + AddImageTiled(50, 37, 400, 376, 0xA40); + AddAlphaRegion(50, 37, 400, 376); + + AddImage(0, 0, 0x28C8); + + AddImageTiled(75, 90, 200, 1, 0x238D); + AddImage(75, 58, 0x2635); + AddImage(380, 45, 0xDF); + + AddHtmlLocalized( + 98, + 140, + 312, + 200, + 1055107, + LightGreen, + false, + true + ); // Sure, I have some sheet music for a Gabriel Piete song. I'd be happy to sell you a copy for 10 gold. + + AddRadio(85, 350, 0x25F8, 0x25FB, true, 1); + AddHtmlLocalized(120, 356, 280, 20, 1014088, White); // I accept. + + AddRadio(85, 385, 0x25F8, 0x25FB, false, 0); + AddHtmlLocalized(120, 391, 280, 20, 1049012, White); // No thanks, I decline. + + AddButton(340, 390, 0xF7, 0xF8, 1); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 1 && info.IsSwitched(1)) + if (sender.Mobile is PlayerMobile player) + { + var qs = player.Quest; + + if (!(qs is CollectorQuest)) + return; + + var obj = qs.FindObjective(); + + if (obj?.Completed != false) + return; + + if (player.Backpack?.ConsumeTotal(typeof(Gold), 10) == true) + { + obj.Complete(); + } + else + { + if (player.FindBankNoCreate()?.ConsumeTotal(typeof(Gold), 10) == true) + obj.Complete(); + else + player.SendLocalizedMessage( + 1055108 + ); // You don't have enough gold to buy the sheet music. + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Collector/Mobiles/TomasONeerlan.cs b/Projects/UOContent/Engines/Quests/Collector/Mobiles/TomasONeerlan.cs index af0d859cf..2091f7125 100644 --- a/Projects/UOContent/Engines/Quests/Collector/Mobiles/TomasONeerlan.cs +++ b/Projects/UOContent/Engines/Quests/Collector/Mobiles/TomasONeerlan.cs @@ -1,109 +1,110 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Collector -{ - public class TomasONeerlan : BaseQuester - { - [Constructible] - public TomasONeerlan() : base("the famed toymaker") - { - } - - public TomasONeerlan(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Tomas O'Neerlan"; - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = 0x83F8; - - Female = false; - Body = 0x190; - } - - public override void InitOutfit() - { - AddItem(new FancyShirt()); - AddItem(new LongPants(0x546)); - AddItem(new Boots(0x452)); - AddItem(new FullApron(0x455)); - - HairItemID = 0x203B; // ShortHair - HairHue = 0x455; - } - - public override bool CanTalkTo(PlayerMobile to) - { - QuestSystem qs = to.Quest as CollectorQuest; - - if (qs == null) - return false; - - return qs.IsObjectiveInProgress(typeof(FindTomasObjective)) - || qs.IsObjectiveInProgress(typeof(CaptureImagesObjective)) - || qs.IsObjectiveInProgress(typeof(ReturnImagesObjective)); - } - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - QuestSystem qs = player.Quest; - - if (qs is CollectorQuest) - { - Direction = GetDirectionTo(player); - - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - Item paints = new EnchantedPaints(); - - if (!player.PlaceInBackpack(paints)) - { - paints.Delete(); - player.SendLocalizedMessage( - 1046260); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. - } - else - { - obj.Complete(); - } - } - else if (qs.IsObjectiveInProgress(typeof(CaptureImagesObjective))) - { - qs.AddConversation(new TomasDuringCollectingConversation()); - } - else - { - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - player.Backpack?.ConsumeUpTo(typeof(EnchantedPaints), 1); - - obj.Complete(); - } - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Collector +{ + public class TomasONeerlan : BaseQuester + { + [Constructible] + public TomasONeerlan() : base("the famed toymaker") + { + } + + public TomasONeerlan(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Tomas O'Neerlan"; + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = 0x83F8; + + Female = false; + Body = 0x190; + } + + public override void InitOutfit() + { + AddItem(new FancyShirt()); + AddItem(new LongPants(0x546)); + AddItem(new Boots(0x452)); + AddItem(new FullApron(0x455)); + + HairItemID = 0x203B; // ShortHair + HairHue = 0x455; + } + + public override bool CanTalkTo(PlayerMobile to) + { + QuestSystem qs = to.Quest as CollectorQuest; + + if (qs == null) + return false; + + return qs.IsObjectiveInProgress(typeof(FindTomasObjective)) + || qs.IsObjectiveInProgress(typeof(CaptureImagesObjective)) + || qs.IsObjectiveInProgress(typeof(ReturnImagesObjective)); + } + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + var qs = player.Quest; + + if (qs is CollectorQuest) + { + Direction = GetDirectionTo(player); + + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + Item paints = new EnchantedPaints(); + + if (!player.PlaceInBackpack(paints)) + { + paints.Delete(); + player.SendLocalizedMessage( + 1046260 + ); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. + } + else + { + obj.Complete(); + } + } + else if (qs.IsObjectiveInProgress(typeof(CaptureImagesObjective))) + { + qs.AddConversation(new TomasDuringCollectingConversation()); + } + else + { + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + player.Backpack?.ConsumeUpTo(typeof(EnchantedPaints), 1); + + obj.Complete(); + } + } + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Collector/Objectives.cs b/Projects/UOContent/Engines/Quests/Collector/Objectives.cs index 250eef9a3..e3d149abc 100644 --- a/Projects/UOContent/Engines/Quests/Collector/Objectives.cs +++ b/Projects/UOContent/Engines/Quests/Collector/Objectives.cs @@ -1,362 +1,372 @@ -using System; -using Server.Mobiles; - -namespace Server.Engines.Quests.Collector -{ - public class FishPearlsObjective : QuestObjective - { - public override object Message => 1055084; - - public override int MaxProgress => 6; - - public override void RenderProgress(BaseQuestGump gump) - { - if (!Completed) - { - // Rainbow pearls collected: - gump.AddHtmlObject(70, 260, 270, 100, 1055085, BaseQuestGump.Blue, false, false); - - gump.AddLabel(70, 280, 0x64, CurProgress.ToString()); - gump.AddLabel(100, 280, 0x64, "/"); - gump.AddLabel(130, 280, 0x64, MaxProgress.ToString()); - } - else - { - base.RenderProgress(gump); - } - } - - public override void OnComplete() - { - System.AddObjective(new ReturnPearlsObjective()); - } - } - - public class ReturnPearlsObjective : QuestObjective - { - public override object Message => 1055088; - - public override void OnComplete() - { - System.AddConversation(new ReturnPearlsConversation()); - } - } - - public class FindAlbertaObjective : QuestObjective - { - public override object Message => 1055091; - - public override void OnComplete() - { - System.AddConversation(new AlbertaPaintingConversation()); - } - } - - public class SitOnTheStoolObjective : QuestObjective - { - private static readonly Point3D m_StoolLocation = new Point3D(2899, 706, 0); - private static readonly Map m_StoolMap = Map.Trammel; - - private DateTime m_Begin; - - public SitOnTheStoolObjective() => m_Begin = DateTime.MaxValue; - - public override object Message => 1055093; - - public override void CheckProgress() - { - PlayerMobile pm = System.From; - - if (pm.Map == m_StoolMap && pm.Location == m_StoolLocation) - { - if (m_Begin == DateTime.MaxValue) - m_Begin = DateTime.UtcNow; - else if (DateTime.UtcNow - m_Begin > TimeSpan.FromSeconds(30.0)) Complete(); - } - else if (m_Begin != DateTime.MaxValue) - { - m_Begin = DateTime.MaxValue; - pm.SendLocalizedMessage(1055095, "", - 0x26); // You must remain seated on the stool until the portrait is complete. Alberta will now have to start again with a fresh canvas. - } - } - - public override void OnComplete() - { - System.AddConversation(new AlbertaEndPaintingConversation()); - } - } - - public class ReturnPaintingObjective : QuestObjective - { - public override object Message => 1055099; - - public override void OnComplete() - { - System.AddConversation(new ReturnPaintingConversation()); - } - } - - public class FindGabrielObjective : QuestObjective - { - public override object Message => 1055101; - - public override void OnComplete() - { - System.AddConversation(new GabrielAutographConversation()); - } - } - - public enum Theater - { - Britain, - Nujelm, - Jhelom - } - - public class FindSheetMusicObjective : QuestObjective - { - private Theater m_Theater; - - public FindSheetMusicObjective(bool init) - { - if (init) - InitTheater(); - } - - public FindSheetMusicObjective() - { - } - - public override object Message => 1055104; - - public void InitTheater() - { - m_Theater = Utility.Random(3) switch - { - 1 => Theater.Britain, - 2 => Theater.Nujelm, - _ => Theater.Jhelom - }; - } - - public bool IsInRightTheater() - { - PlayerMobile player = System.From; - - Region region = Region.Find(player.Location, player.Map); - - if (region == null) - return false; - - return m_Theater switch - { - Theater.Britain => region.IsPartOf("Britain"), - Theater.Nujelm => region.IsPartOf("Nujel'm"), - Theater.Jhelom => region.IsPartOf("Jhelom"), - _ => false - }; - } - - public override void OnComplete() - { - System.AddConversation(new GetSheetMusicConversation()); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_Theater = (Theater)reader.ReadEncodedInt(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.WriteEncodedInt((int)m_Theater); - } - } - - public class ReturnSheetMusicObjective : QuestObjective - { - public override object Message => 1055110; - - public override void OnComplete() - { - System.AddConversation(new GabrielSheetMusicConversation()); - } - } - - public class ReturnAutographObjective : QuestObjective - { - public override object Message => 1055114; - - public override void OnComplete() - { - System.AddConversation(new ReturnAutographConversation()); - } - } - - public class FindTomasObjective : QuestObjective - { - public override object Message => 1055117; - - public override void OnComplete() - { - System.AddConversation(new TomasToysConversation()); - } - } - - public enum CaptureResponse - { - Valid, - AlreadyDone, - Invalid - } - - public class CaptureImagesObjective : QuestObjective - { - private bool[] m_Done; - private ImageType[] m_Images; - - public CaptureImagesObjective(bool init) - { - if (init) - { - m_Images = ImageTypeInfo.RandomList(4); - m_Done = new bool[4]; - } - } - - public CaptureImagesObjective() - { - } - - public override object Message => 1055120; - - public override bool Completed - { - get - { - for (int i = 0; i < m_Done.Length; i++) - if (!m_Done[i]) - return false; - - return true; - } - } - - public override bool IgnoreYoungProtection(Mobile from) - { - if (Completed) - return false; - - Type fromType = from.GetType(); - - for (int i = 0; i < m_Images.Length; i++) - { - ImageTypeInfo info = ImageTypeInfo.Get(m_Images[i]); - - if (info.Type == fromType) - return true; - } - - return false; - } - - public CaptureResponse CaptureImage(Type type, out ImageType image) - { - for (int i = 0; i < m_Images.Length; i++) - { - ImageTypeInfo info = ImageTypeInfo.Get(m_Images[i]); - - if (info.Type == type) - { - image = m_Images[i]; - - if (m_Done[i]) return CaptureResponse.AlreadyDone; - - m_Done[i] = true; - - CheckCompletionStatus(); - - return CaptureResponse.Valid; - } - } - - image = 0; - return CaptureResponse.Invalid; - } - - public override void RenderProgress(BaseQuestGump gump) - { - if (!Completed) - for (int i = 0; i < m_Images.Length; i++) - { - ImageTypeInfo info = ImageTypeInfo.Get(m_Images[i]); - - gump.AddHtmlObject(70, 260 + 20 * i, 200, 100, info.Name, BaseQuestGump.Blue, false, false); - gump.AddLabel(200, 260 + 20 * i, 0x64, " : "); - gump.AddHtmlObject(220, 260 + 20 * i, 100, 100, m_Done[i] ? 1055121 : 1055122, BaseQuestGump.Blue, false, - false); - } - else - base.RenderProgress(gump); - } - - public override void OnComplete() - { - System.AddObjective(new ReturnImagesObjective()); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - int count = reader.ReadEncodedInt(); - - m_Images = new ImageType[count]; - m_Done = new bool[count]; - - for (int i = 0; i < count; i++) - { - m_Images[i] = (ImageType)reader.ReadEncodedInt(); - m_Done[i] = reader.ReadBool(); - } - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.WriteEncodedInt(m_Images.Length); - - for (int i = 0; i < m_Images.Length; i++) - { - writer.WriteEncodedInt((int)m_Images[i]); - writer.Write(m_Done[i]); - } - } - } - - public class ReturnImagesObjective : QuestObjective - { - public override object Message => 1055128; - - public override void OnComplete() - { - System.AddConversation(new ReturnImagesConversation()); - } - } - - public class ReturnToysObjective : QuestObjective - { - public override object Message => 1055132; - } - - public class MakeRoomObjective : QuestObjective - { - public override object Message => 1055136; - } -} \ No newline at end of file +using System; + +namespace Server.Engines.Quests.Collector +{ + public class FishPearlsObjective : QuestObjective + { + public override object Message => 1055084; + + public override int MaxProgress => 6; + + public override void RenderProgress(BaseQuestGump gump) + { + if (!Completed) + { + // Rainbow pearls collected: + gump.AddHtmlObject(70, 260, 270, 100, 1055085, BaseQuestGump.Blue, false, false); + + gump.AddLabel(70, 280, 0x64, CurProgress.ToString()); + gump.AddLabel(100, 280, 0x64, "/"); + gump.AddLabel(130, 280, 0x64, MaxProgress.ToString()); + } + else + { + base.RenderProgress(gump); + } + } + + public override void OnComplete() + { + System.AddObjective(new ReturnPearlsObjective()); + } + } + + public class ReturnPearlsObjective : QuestObjective + { + public override object Message => 1055088; + + public override void OnComplete() + { + System.AddConversation(new ReturnPearlsConversation()); + } + } + + public class FindAlbertaObjective : QuestObjective + { + public override object Message => 1055091; + + public override void OnComplete() + { + System.AddConversation(new AlbertaPaintingConversation()); + } + } + + public class SitOnTheStoolObjective : QuestObjective + { + private static readonly Point3D m_StoolLocation = new Point3D(2899, 706, 0); + private static readonly Map m_StoolMap = Map.Trammel; + + private DateTime m_Begin; + + public SitOnTheStoolObjective() => m_Begin = DateTime.MaxValue; + + public override object Message => 1055093; + + public override void CheckProgress() + { + var pm = System.From; + + if (pm.Map == m_StoolMap && pm.Location == m_StoolLocation) + { + if (m_Begin == DateTime.MaxValue) + m_Begin = DateTime.UtcNow; + else if (DateTime.UtcNow - m_Begin > TimeSpan.FromSeconds(30.0)) Complete(); + } + else if (m_Begin != DateTime.MaxValue) + { + m_Begin = DateTime.MaxValue; + pm.SendLocalizedMessage( + 1055095, + "", + 0x26 + ); // You must remain seated on the stool until the portrait is complete. Alberta will now have to start again with a fresh canvas. + } + } + + public override void OnComplete() + { + System.AddConversation(new AlbertaEndPaintingConversation()); + } + } + + public class ReturnPaintingObjective : QuestObjective + { + public override object Message => 1055099; + + public override void OnComplete() + { + System.AddConversation(new ReturnPaintingConversation()); + } + } + + public class FindGabrielObjective : QuestObjective + { + public override object Message => 1055101; + + public override void OnComplete() + { + System.AddConversation(new GabrielAutographConversation()); + } + } + + public enum Theater + { + Britain, + Nujelm, + Jhelom + } + + public class FindSheetMusicObjective : QuestObjective + { + private Theater m_Theater; + + public FindSheetMusicObjective(bool init) + { + if (init) + InitTheater(); + } + + public FindSheetMusicObjective() + { + } + + public override object Message => 1055104; + + public void InitTheater() + { + m_Theater = Utility.Random(3) switch + { + 1 => Theater.Britain, + 2 => Theater.Nujelm, + _ => Theater.Jhelom + }; + } + + public bool IsInRightTheater() + { + var player = System.From; + + var region = Region.Find(player.Location, player.Map); + + if (region == null) + return false; + + return m_Theater switch + { + Theater.Britain => region.IsPartOf("Britain"), + Theater.Nujelm => region.IsPartOf("Nujel'm"), + Theater.Jhelom => region.IsPartOf("Jhelom"), + _ => false + }; + } + + public override void OnComplete() + { + System.AddConversation(new GetSheetMusicConversation()); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_Theater = (Theater)reader.ReadEncodedInt(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.WriteEncodedInt((int)m_Theater); + } + } + + public class ReturnSheetMusicObjective : QuestObjective + { + public override object Message => 1055110; + + public override void OnComplete() + { + System.AddConversation(new GabrielSheetMusicConversation()); + } + } + + public class ReturnAutographObjective : QuestObjective + { + public override object Message => 1055114; + + public override void OnComplete() + { + System.AddConversation(new ReturnAutographConversation()); + } + } + + public class FindTomasObjective : QuestObjective + { + public override object Message => 1055117; + + public override void OnComplete() + { + System.AddConversation(new TomasToysConversation()); + } + } + + public enum CaptureResponse + { + Valid, + AlreadyDone, + Invalid + } + + public class CaptureImagesObjective : QuestObjective + { + private bool[] m_Done; + private ImageType[] m_Images; + + public CaptureImagesObjective(bool init) + { + if (init) + { + m_Images = ImageTypeInfo.RandomList(4); + m_Done = new bool[4]; + } + } + + public CaptureImagesObjective() + { + } + + public override object Message => 1055120; + + public override bool Completed + { + get + { + for (var i = 0; i < m_Done.Length; i++) + if (!m_Done[i]) + return false; + + return true; + } + } + + public override bool IgnoreYoungProtection(Mobile from) + { + if (Completed) + return false; + + var fromType = from.GetType(); + + for (var i = 0; i < m_Images.Length; i++) + { + var info = ImageTypeInfo.Get(m_Images[i]); + + if (info.Type == fromType) + return true; + } + + return false; + } + + public CaptureResponse CaptureImage(Type type, out ImageType image) + { + for (var i = 0; i < m_Images.Length; i++) + { + var info = ImageTypeInfo.Get(m_Images[i]); + + if (info.Type == type) + { + image = m_Images[i]; + + if (m_Done[i]) return CaptureResponse.AlreadyDone; + + m_Done[i] = true; + + CheckCompletionStatus(); + + return CaptureResponse.Valid; + } + } + + image = 0; + return CaptureResponse.Invalid; + } + + public override void RenderProgress(BaseQuestGump gump) + { + if (!Completed) + for (var i = 0; i < m_Images.Length; i++) + { + var info = ImageTypeInfo.Get(m_Images[i]); + + gump.AddHtmlObject(70, 260 + 20 * i, 200, 100, info.Name, BaseQuestGump.Blue, false, false); + gump.AddLabel(200, 260 + 20 * i, 0x64, " : "); + gump.AddHtmlObject( + 220, + 260 + 20 * i, + 100, + 100, + m_Done[i] ? 1055121 : 1055122, + BaseQuestGump.Blue, + false, + false + ); + } + else + base.RenderProgress(gump); + } + + public override void OnComplete() + { + System.AddObjective(new ReturnImagesObjective()); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + var count = reader.ReadEncodedInt(); + + m_Images = new ImageType[count]; + m_Done = new bool[count]; + + for (var i = 0; i < count; i++) + { + m_Images[i] = (ImageType)reader.ReadEncodedInt(); + m_Done[i] = reader.ReadBool(); + } + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.WriteEncodedInt(m_Images.Length); + + for (var i = 0; i < m_Images.Length; i++) + { + writer.WriteEncodedInt((int)m_Images[i]); + writer.Write(m_Done[i]); + } + } + } + + public class ReturnImagesObjective : QuestObjective + { + public override object Message => 1055128; + + public override void OnComplete() + { + System.AddConversation(new ReturnImagesConversation()); + } + } + + public class ReturnToysObjective : QuestObjective + { + public override object Message => 1055132; + } + + public class MakeRoomObjective : QuestObjective + { + public override object Message => 1055136; + } +} diff --git a/Projects/UOContent/Engines/Quests/Core/BaseQuester.cs b/Projects/UOContent/Engines/Quests/Core/BaseQuester.cs index a0f0f621c..8bc0c0d8f 100644 --- a/Projects/UOContent/Engines/Quests/Core/BaseQuester.cs +++ b/Projects/UOContent/Engines/Quests/Core/BaseQuester.cs @@ -1,109 +1,109 @@ -using System.Collections.Generic; -using Server.ContextMenus; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests -{ - public class TalkEntry : ContextMenuEntry - { - private readonly BaseQuester m_Quester; - - public TalkEntry(BaseQuester quester) : base(quester.TalkNumber) => m_Quester = quester; - - public override void OnClick() - { - Mobile from = Owner.From; - - if (from.CheckAlive() && from is PlayerMobile mobile && m_Quester.CanTalkTo(mobile)) - m_Quester.OnTalk(mobile, true); - } - } - - public abstract class BaseQuester : BaseVendor - { - protected List m_SBInfos = new List(); - - public BaseQuester(string title = null) : base(title) - { - } - - public BaseQuester(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override bool IsActiveVendor => false; - public override bool IsInvulnerable => true; - public override bool DisallowAllMoves => true; - public override bool ClickTitle => false; - public override bool CanTeach => false; - - public virtual int TalkNumber // Talk - => 6146; - - public override void InitSBInfo() - { - } - - public abstract void OnTalk(PlayerMobile player, bool contextMenu); - - public virtual bool CanTalkTo(PlayerMobile to) => true; - - public virtual int GetAutoTalkRange(PlayerMobile m) => -1; - - public override bool CanBeDamaged() => false; - - protected Item SetHue(Item item, int hue) - { - item.Hue = hue; - return item; - } - - public override void AddCustomContextEntries(Mobile from, List list) - { - base.AddCustomContextEntries(from, list); - - if (from.Alive && from is PlayerMobile mobile && TalkNumber > 0 && CanTalkTo(mobile)) - list.Add(new TalkEntry(this)); - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (m.Alive && m is PlayerMobile pm) - { - int range = GetAutoTalkRange(pm); - - if (pm.Alive && range >= 0 && InRange(m, range) && !InRange(oldLocation, range) && CanTalkTo(pm)) - OnTalk(pm, false); - } - } - - public void FocusTo(Mobile to) - { - QuestSystem.FocusTo(this, to); - } - - public static Container GetNewContainer() - { - Bag bag = new Bag(); - bag.Hue = QuestSystem.RandomBrightHue(); - return bag; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System.Collections.Generic; +using Server.ContextMenus; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests +{ + public class TalkEntry : ContextMenuEntry + { + private readonly BaseQuester m_Quester; + + public TalkEntry(BaseQuester quester) : base(quester.TalkNumber) => m_Quester = quester; + + public override void OnClick() + { + var from = Owner.From; + + if (from.CheckAlive() && from is PlayerMobile mobile && m_Quester.CanTalkTo(mobile)) + m_Quester.OnTalk(mobile, true); + } + } + + public abstract class BaseQuester : BaseVendor + { + protected List m_SBInfos = new List(); + + public BaseQuester(string title = null) : base(title) + { + } + + public BaseQuester(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override bool IsActiveVendor => false; + public override bool IsInvulnerable => true; + public override bool DisallowAllMoves => true; + public override bool ClickTitle => false; + public override bool CanTeach => false; + + public virtual int TalkNumber // Talk + => 6146; + + public override void InitSBInfo() + { + } + + public abstract void OnTalk(PlayerMobile player, bool contextMenu); + + public virtual bool CanTalkTo(PlayerMobile to) => true; + + public virtual int GetAutoTalkRange(PlayerMobile m) => -1; + + public override bool CanBeDamaged() => false; + + protected Item SetHue(Item item, int hue) + { + item.Hue = hue; + return item; + } + + public override void AddCustomContextEntries(Mobile from, List list) + { + base.AddCustomContextEntries(from, list); + + if (from.Alive && from is PlayerMobile mobile && TalkNumber > 0 && CanTalkTo(mobile)) + list.Add(new TalkEntry(this)); + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (m.Alive && m is PlayerMobile pm) + { + var range = GetAutoTalkRange(pm); + + if (pm.Alive && range >= 0 && InRange(m, range) && !InRange(oldLocation, range) && CanTalkTo(pm)) + OnTalk(pm, false); + } + } + + public void FocusTo(Mobile to) + { + QuestSystem.FocusTo(this, to); + } + + public static Container GetNewContainer() + { + var bag = new Bag(); + bag.Hue = QuestSystem.RandomBrightHue(); + return bag; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Core/Items/DynamicTeleporter.cs b/Projects/UOContent/Engines/Quests/Core/Items/DynamicTeleporter.cs index 1f210de2e..a36a14bee 100644 --- a/Projects/UOContent/Engines/Quests/Core/Items/DynamicTeleporter.cs +++ b/Projects/UOContent/Engines/Quests/Core/Items/DynamicTeleporter.cs @@ -1,61 +1,61 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests -{ - public abstract class DynamicTeleporter : Item - { - public DynamicTeleporter(int itemID = 0x1822, int hue = 0x482) : base(itemID) - { - Movable = false; - Hue = hue; - } - - public DynamicTeleporter(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1049382; // a magical teleporter - - public virtual int NotWorkingMessage // Nothing Happens. - => 500309; - - public abstract bool GetDestination(PlayerMobile player, ref Point3D loc, ref Map map); - - public override bool OnMoveOver(Mobile m) - { - if (m is PlayerMobile pm) - { - Point3D loc = Point3D.Zero; - Map map = null; - - if (GetDestination(pm, ref loc, ref map)) - { - BaseCreature.TeleportPets(pm, loc, map); - - pm.PlaySound(0x1FE); - pm.MoveToWorld(loc, map); - - return false; - } - - pm.SendLocalizedMessage(NotWorkingMessage); - } - - return base.OnMoveOver(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using Server.Mobiles; + +namespace Server.Engines.Quests +{ + public abstract class DynamicTeleporter : Item + { + public DynamicTeleporter(int itemID = 0x1822, int hue = 0x482) : base(itemID) + { + Movable = false; + Hue = hue; + } + + public DynamicTeleporter(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1049382; // a magical teleporter + + public virtual int NotWorkingMessage // Nothing Happens. + => 500309; + + public abstract bool GetDestination(PlayerMobile player, ref Point3D loc, ref Map map); + + public override bool OnMoveOver(Mobile m) + { + if (m is PlayerMobile pm) + { + var loc = Point3D.Zero; + Map map = null; + + if (GetDestination(pm, ref loc, ref map)) + { + BaseCreature.TeleportPets(pm, loc, map); + + pm.PlaySound(0x1FE); + pm.MoveToWorld(loc, map); + + return false; + } + + pm.SendLocalizedMessage(NotWorkingMessage); + } + + return base.OnMoveOver(m); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Core/Items/EnchantedSextant.cs b/Projects/UOContent/Engines/Quests/Core/Items/EnchantedSextant.cs index d671bb7d1..bad191c35 100644 --- a/Projects/UOContent/Engines/Quests/Core/Items/EnchantedSextant.cs +++ b/Projects/UOContent/Engines/Quests/Core/Items/EnchantedSextant.cs @@ -1,186 +1,196 @@ -using Server.Network; - -namespace Server.Items -{ - public class EnchantedSextant : Item - { - private const double m_LongDistance = 300.0; - - private const double m_ShortDistance = 5.0; - - // TODO: Trammel/Haven - private static readonly Point2D[] m_TrammelBanks = - { - new Point2D(652, 820), - new Point2D(1813, 2825), - new Point2D(3734, 2149), - new Point2D(2503, 552), - new Point2D(3764, 1317), - new Point2D(587, 2146), - new Point2D(1655, 1606), - new Point2D(1425, 1690), - new Point2D(4471, 1156), - new Point2D(1317, 3773), - new Point2D(2881, 684), - new Point2D(2731, 2192), - new Point2D(3620, 2617), - new Point2D(2880, 3472), - new Point2D(1897, 2684), - new Point2D(5346, 74), - new Point2D(5275, 3977), - new Point2D(5669, 3131) - }; - - private static readonly Point2D[] m_FeluccaBanks = - { - new Point2D(652, 820), - new Point2D(1813, 2825), - new Point2D(3734, 2149), - new Point2D(2503, 552), - new Point2D(3764, 1317), - new Point2D(3695, 2511), - new Point2D(587, 2146), - new Point2D(1655, 1606), - new Point2D(1425, 1690), - new Point2D(4471, 1156), - new Point2D(1317, 3773), - new Point2D(2881, 684), - new Point2D(2731, 2192), - new Point2D(2880, 3472), - new Point2D(1897, 2684), - new Point2D(5346, 74), - new Point2D(5275, 3977), - new Point2D(5669, 3131) - }; - - private static readonly Point2D[] m_IlshenarBanks = - { - new Point2D(854, 680), - new Point2D(855, 603), - new Point2D(1226, 554), - new Point2D(1610, 556) - }; - - private static readonly Point2D[] m_MalasBanks = - { - new Point2D(996, 519), - new Point2D(2048, 1345) - }; - - [Constructible] - public EnchantedSextant() : base(0x1058) => Weight = 2.0; - - public EnchantedSextant(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1046226; // an enchanted sextant - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return; - } - - Point2D[] banks; - PMList moongates; - if (from.Map == Map.Trammel) - { - banks = m_TrammelBanks; - moongates = PMList.Trammel; - } - else if (from.Map == Map.Felucca) - { - banks = m_FeluccaBanks; - moongates = PMList.Felucca; - } - else if (from.Map == Map.Ilshenar) - { -#if false - banks = m_IlshenarBanks; - moongates = PMList.Ilshenar; -#else - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, 0x482, 3, 1061684, "", - "")); // The magic of the sextant fails... - return; -#endif - } - else if (from.Map == Map.Malas) - { - banks = m_MalasBanks; - moongates = PMList.Malas; - } - else - { - banks = null; - moongates = null; - } - - Point3D closestMoongate = Point3D.Zero; - double moongateDistance = double.MaxValue; - if (moongates != null) - foreach (PMEntry entry in moongates.Entries) - { - double dist = from.GetDistanceToSqrt(entry.Location); - if (moongateDistance > dist) - { - closestMoongate = entry.Location; - moongateDistance = dist; - } - } - - Point2D closestBank = Point2D.Zero; - double bankDistance = double.MaxValue; - if (banks != null) - foreach (Point2D p in banks) - { - double dist = from.GetDistanceToSqrt(p); - if (bankDistance > dist) - { - closestBank = p; - bankDistance = dist; - } - } - - int moonMsg; - if (moongateDistance == double.MaxValue) - moonMsg = 1048021; // The sextant fails to find a Moongate nearby. - else if (moongateDistance > m_LongDistance) - moonMsg = 1046449 + (int)from.GetDirectionTo(closestMoongate); // A moongate is * from here - else if (moongateDistance > m_ShortDistance) - moonMsg = 1048010 + (int)from.GetDirectionTo(closestMoongate); // There is a Moongate * of here. - else - moonMsg = 1048018; // You are next to a Moongate at the moment. - - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, 0x482, 3, moonMsg, "", "")); - - int bankMsg; - if (bankDistance == double.MaxValue) - bankMsg = 1048020; // The sextant fails to find a Bank nearby. - else if (bankDistance > m_LongDistance) - bankMsg = 1046462 + (int)from.GetDirectionTo(closestBank); // A town is * from here - else if (bankDistance > m_ShortDistance) - bankMsg = 1048002 + (int)from.GetDirectionTo(closestBank); // There is a city Bank * of here. - else - bankMsg = 1048019; // You are next to a Bank at the moment. - - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, 0x5AA, 3, bankMsg, "", "")); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using Server.Network; + +namespace Server.Items +{ + public class EnchantedSextant : Item + { + private const double m_LongDistance = 300.0; + + private const double m_ShortDistance = 5.0; + + // TODO: Trammel/Haven + private static readonly Point2D[] m_TrammelBanks = + { + new Point2D(652, 820), + new Point2D(1813, 2825), + new Point2D(3734, 2149), + new Point2D(2503, 552), + new Point2D(3764, 1317), + new Point2D(587, 2146), + new Point2D(1655, 1606), + new Point2D(1425, 1690), + new Point2D(4471, 1156), + new Point2D(1317, 3773), + new Point2D(2881, 684), + new Point2D(2731, 2192), + new Point2D(3620, 2617), + new Point2D(2880, 3472), + new Point2D(1897, 2684), + new Point2D(5346, 74), + new Point2D(5275, 3977), + new Point2D(5669, 3131) + }; + + private static readonly Point2D[] m_FeluccaBanks = + { + new Point2D(652, 820), + new Point2D(1813, 2825), + new Point2D(3734, 2149), + new Point2D(2503, 552), + new Point2D(3764, 1317), + new Point2D(3695, 2511), + new Point2D(587, 2146), + new Point2D(1655, 1606), + new Point2D(1425, 1690), + new Point2D(4471, 1156), + new Point2D(1317, 3773), + new Point2D(2881, 684), + new Point2D(2731, 2192), + new Point2D(2880, 3472), + new Point2D(1897, 2684), + new Point2D(5346, 74), + new Point2D(5275, 3977), + new Point2D(5669, 3131) + }; + + private static readonly Point2D[] m_IlshenarBanks = + { + new Point2D(854, 680), + new Point2D(855, 603), + new Point2D(1226, 554), + new Point2D(1610, 556) + }; + + private static readonly Point2D[] m_MalasBanks = + { + new Point2D(996, 519), + new Point2D(2048, 1345) + }; + + [Constructible] + public EnchantedSextant() : base(0x1058) => Weight = 2.0; + + public EnchantedSextant(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1046226; // an enchanted sextant + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return; + } + + Point2D[] banks; + PMList moongates; + if (from.Map == Map.Trammel) + { + banks = m_TrammelBanks; + moongates = PMList.Trammel; + } + else if (from.Map == Map.Felucca) + { + banks = m_FeluccaBanks; + moongates = PMList.Felucca; + } + else if (from.Map == Map.Ilshenar) + { +#if false + banks = m_IlshenarBanks; + moongates = PMList.Ilshenar; +#else + from.Send( + new MessageLocalized( + Serial, + ItemID, + MessageType.Label, + 0x482, + 3, + 1061684, + "", + "" + ) + ); // The magic of the sextant fails... + return; +#endif + } + else if (from.Map == Map.Malas) + { + banks = m_MalasBanks; + moongates = PMList.Malas; + } + else + { + banks = null; + moongates = null; + } + + var closestMoongate = Point3D.Zero; + var moongateDistance = double.MaxValue; + if (moongates != null) + foreach (var entry in moongates.Entries) + { + var dist = from.GetDistanceToSqrt(entry.Location); + if (moongateDistance > dist) + { + closestMoongate = entry.Location; + moongateDistance = dist; + } + } + + var closestBank = Point2D.Zero; + var bankDistance = double.MaxValue; + if (banks != null) + foreach (var p in banks) + { + var dist = from.GetDistanceToSqrt(p); + if (bankDistance > dist) + { + closestBank = p; + bankDistance = dist; + } + } + + int moonMsg; + if (moongateDistance == double.MaxValue) + moonMsg = 1048021; // The sextant fails to find a Moongate nearby. + else if (moongateDistance > m_LongDistance) + moonMsg = 1046449 + (int)from.GetDirectionTo(closestMoongate); // A moongate is * from here + else if (moongateDistance > m_ShortDistance) + moonMsg = 1048010 + (int)from.GetDirectionTo(closestMoongate); // There is a Moongate * of here. + else + moonMsg = 1048018; // You are next to a Moongate at the moment. + + from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, 0x482, 3, moonMsg, "", "")); + + int bankMsg; + if (bankDistance == double.MaxValue) + bankMsg = 1048020; // The sextant fails to find a Bank nearby. + else if (bankDistance > m_LongDistance) + bankMsg = 1046462 + (int)from.GetDirectionTo(closestBank); // A town is * from here + else if (bankDistance > m_ShortDistance) + bankMsg = 1048002 + (int)from.GetDirectionTo(closestBank); // There is a city Bank * of here. + else + bankMsg = 1048019; // You are next to a Bank at the moment. + + from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, 0x5AA, 3, bankMsg, "", "")); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Core/Items/HornOfRetreat.cs b/Projects/UOContent/Engines/Quests/Core/Items/HornOfRetreat.cs index ce7b74f80..d1ff86b0d 100644 --- a/Projects/UOContent/Engines/Quests/Core/Items/HornOfRetreat.cs +++ b/Projects/UOContent/Engines/Quests/Core/Items/HornOfRetreat.cs @@ -1,192 +1,192 @@ -using System; -using Server.Items; -using Server.Regions; - -namespace Server.Engines.Quests -{ - public class HornOfRetreat : Item - { - private int m_Charges; - - private Timer m_PlayTimer; - - [Constructible] - public HornOfRetreat() : base(0xFC4) - { - Hue = 0x482; - Weight = 1.0; - Charges = 10; - } - - public HornOfRetreat(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D DestLoc { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Map DestMap { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Charges - { - get => m_Charges; - set - { - m_Charges = value; - InvalidateProperties(); - } - } - - public override int LabelNumber => 1049117; // Horn of Retreat - - public virtual bool ValidateUse(Mobile from) => true; - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1060741, m_Charges.ToString()); // charges: ~1_val~ - } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - if (!ValidateUse(from)) - { - SendLocalizedMessageTo(from, 500309); // Nothing Happens. - } - else if (Core.ML && from.Map != Map.Trammel && from.Map != Map.Malas) - { - from.SendLocalizedMessage(1076154); // You can only use this in Trammel and Malas. - } - else if (m_PlayTimer != null) - { - SendLocalizedMessageTo(from, 1042144); // This is currently in use. - } - else if (Charges > 0) - { - from.Animate(34, 7, 1, true, false, 0); - from.PlaySound(0xFF); - from.SendLocalizedMessage(1049115); // You play the horn and a sense of peace overcomes you... - - --Charges; - - m_PlayTimer = Timer.DelayCall(TimeSpan.FromSeconds(5.0), PlayTimer_Callback, from); - } - else - { - SendLocalizedMessageTo(from, 1042544); // This item is out of charges. - } - } - else - { - SendLocalizedMessageTo(from, 1042001); // That must be in your pack for you to use it. - } - } - - public virtual void PlayTimer_Callback(Mobile from) - { - m_PlayTimer = null; - - HornOfRetreatMoongate gate = new HornOfRetreatMoongate(DestLoc, DestMap, from, Hue); - - gate.MoveToWorld(from.Location, from.Map); - - from.PlaySound(0x20E); - - gate.SendLocalizedMessageTo(from, 1049102, from.Name); // Quickly ~1_NAME~! Onward through the gate! - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(DestLoc); - writer.Write(DestMap); - writer.Write(m_Charges); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - DestLoc = reader.ReadPoint3D(); - DestMap = reader.ReadMap(); - m_Charges = reader.ReadInt(); - break; - } - } - } - } - - public class HornOfRetreatMoongate : Moongate - { - private readonly Mobile m_Caster; - - public HornOfRetreatMoongate(Point3D destLoc, Map destMap, Mobile caster, int hue) - { - m_Caster = caster; - - Target = destLoc; - TargetMap = destMap; - - Hue = hue; - Light = LightType.Circle300; - - Dispellable = false; - - Timer.DelayCall(TimeSpan.FromSeconds(10.0), Delete); - } - - public HornOfRetreatMoongate(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1049114; // Sanctuary Gate - - public override void BeginConfirmation(Mobile from) - { - EndConfirmation(from); - } - - public override void UseGate(Mobile m) - { - if (m.Region.IsPartOf()) - { - m.SendLocalizedMessage(1114345); // You'll need a better jailbreak plan than that! - } - else if (m == m_Caster) - { - base.UseGate(m); - Delete(); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Delete(); - } - } -} +using System; +using Server.Items; +using Server.Regions; + +namespace Server.Engines.Quests +{ + public class HornOfRetreat : Item + { + private int m_Charges; + + private Timer m_PlayTimer; + + [Constructible] + public HornOfRetreat() : base(0xFC4) + { + Hue = 0x482; + Weight = 1.0; + Charges = 10; + } + + public HornOfRetreat(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D DestLoc { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Map DestMap { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Charges + { + get => m_Charges; + set + { + m_Charges = value; + InvalidateProperties(); + } + } + + public override int LabelNumber => 1049117; // Horn of Retreat + + public virtual bool ValidateUse(Mobile from) => true; + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1060741, m_Charges.ToString()); // charges: ~1_val~ + } + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + if (!ValidateUse(from)) + { + SendLocalizedMessageTo(from, 500309); // Nothing Happens. + } + else if (Core.ML && from.Map != Map.Trammel && from.Map != Map.Malas) + { + from.SendLocalizedMessage(1076154); // You can only use this in Trammel and Malas. + } + else if (m_PlayTimer != null) + { + SendLocalizedMessageTo(from, 1042144); // This is currently in use. + } + else if (Charges > 0) + { + from.Animate(34, 7, 1, true, false, 0); + from.PlaySound(0xFF); + from.SendLocalizedMessage(1049115); // You play the horn and a sense of peace overcomes you... + + --Charges; + + m_PlayTimer = Timer.DelayCall(TimeSpan.FromSeconds(5.0), PlayTimer_Callback, from); + } + else + { + SendLocalizedMessageTo(from, 1042544); // This item is out of charges. + } + } + else + { + SendLocalizedMessageTo(from, 1042001); // That must be in your pack for you to use it. + } + } + + public virtual void PlayTimer_Callback(Mobile from) + { + m_PlayTimer = null; + + var gate = new HornOfRetreatMoongate(DestLoc, DestMap, from, Hue); + + gate.MoveToWorld(from.Location, from.Map); + + from.PlaySound(0x20E); + + gate.SendLocalizedMessageTo(from, 1049102, from.Name); // Quickly ~1_NAME~! Onward through the gate! + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(DestLoc); + writer.Write(DestMap); + writer.Write(m_Charges); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + DestLoc = reader.ReadPoint3D(); + DestMap = reader.ReadMap(); + m_Charges = reader.ReadInt(); + break; + } + } + } + } + + public class HornOfRetreatMoongate : Moongate + { + private readonly Mobile m_Caster; + + public HornOfRetreatMoongate(Point3D destLoc, Map destMap, Mobile caster, int hue) + { + m_Caster = caster; + + Target = destLoc; + TargetMap = destMap; + + Hue = hue; + Light = LightType.Circle300; + + Dispellable = false; + + Timer.DelayCall(TimeSpan.FromSeconds(10.0), Delete); + } + + public HornOfRetreatMoongate(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1049114; // Sanctuary Gate + + public override void BeginConfirmation(Mobile from) + { + EndConfirmation(from); + } + + public override void UseGate(Mobile m) + { + if (m.Region.IsPartOf()) + { + m.SendLocalizedMessage(1114345); // You'll need a better jailbreak plan than that! + } + else if (m == m_Caster) + { + base.UseGate(m); + Delete(); + } + } + + 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(); + + Delete(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Core/Items/QuestItem.cs b/Projects/UOContent/Engines/Quests/Core/Items/QuestItem.cs index 1f0967b4b..61da83dab 100644 --- a/Projects/UOContent/Engines/Quests/Core/Items/QuestItem.cs +++ b/Projects/UOContent/Engines/Quests/Core/Items/QuestItem.cs @@ -1,92 +1,95 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests -{ - public abstract class QuestItem : Item - { - public QuestItem(int itemID) : base(itemID) - { - } - - public QuestItem(Serial serial) : base(serial) - { - } - - public virtual bool Accepted => Deleted; - - public abstract bool CanDrop(PlayerMobile pm); - - public override bool DropToWorld(Mobile from, Point3D p) - { - bool ret = base.DropToWorld(from, p); - - if (ret && !Accepted && Parent != from.Backpack) - { - if (from.AccessLevel > AccessLevel.Player) return true; - - if (!(from is PlayerMobile) || CanDrop((PlayerMobile)from)) return true; - from.SendLocalizedMessage( - 1049343); // You can only drop quest items into the top-most level of your backpack while you still need them for your quest. - return false; - } - - return ret; - } - - public override bool DropToMobile(Mobile from, Mobile target, Point3D p) - { - bool ret = base.DropToMobile(from, target, p); - - if (ret && !Accepted && Parent != from.Backpack) - { - if (from.AccessLevel > AccessLevel.Player) return true; - - if (!(from is PlayerMobile) || CanDrop((PlayerMobile)from)) return true; - from.SendLocalizedMessage( - 1049344); // You decide against trading the item. You still need it for your quest. - return false; - } - - return ret; - } - - public override bool DropToItem(Mobile from, Item target, Point3D p) - { - bool ret = base.DropToItem(from, target, p); - - if (ret && !Accepted && Parent != from.Backpack) - { - if (from.AccessLevel > AccessLevel.Player) return true; - - if (!(from is PlayerMobile) || CanDrop((PlayerMobile)from)) return true; - from.SendLocalizedMessage( - 1049343); // You can only drop quest items into the top-most level of your backpack while you still need them for your quest. - return false; - } - - return ret; - } - - public override DeathMoveResult OnParentDeath(Mobile parent) - { - if (parent is PlayerMobile mobile && !CanDrop(mobile)) - return DeathMoveResult.MoveToBackpack; - - return base.OnParentDeath(parent); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests +{ + public abstract class QuestItem : Item + { + public QuestItem(int itemID) : base(itemID) + { + } + + public QuestItem(Serial serial) : base(serial) + { + } + + public virtual bool Accepted => Deleted; + + public abstract bool CanDrop(PlayerMobile pm); + + public override bool DropToWorld(Mobile from, Point3D p) + { + var ret = base.DropToWorld(from, p); + + if (ret && !Accepted && Parent != from.Backpack) + { + if (from.AccessLevel > AccessLevel.Player) return true; + + if (!(from is PlayerMobile) || CanDrop((PlayerMobile)from)) return true; + from.SendLocalizedMessage( + 1049343 + ); // You can only drop quest items into the top-most level of your backpack while you still need them for your quest. + return false; + } + + return ret; + } + + public override bool DropToMobile(Mobile from, Mobile target, Point3D p) + { + var ret = base.DropToMobile(from, target, p); + + if (ret && !Accepted && Parent != from.Backpack) + { + if (from.AccessLevel > AccessLevel.Player) return true; + + if (!(from is PlayerMobile) || CanDrop((PlayerMobile)from)) return true; + from.SendLocalizedMessage( + 1049344 + ); // You decide against trading the item. You still need it for your quest. + return false; + } + + return ret; + } + + public override bool DropToItem(Mobile from, Item target, Point3D p) + { + var ret = base.DropToItem(from, target, p); + + if (ret && !Accepted && Parent != from.Backpack) + { + if (from.AccessLevel > AccessLevel.Player) return true; + + if (!(from is PlayerMobile) || CanDrop((PlayerMobile)from)) return true; + from.SendLocalizedMessage( + 1049343 + ); // You can only drop quest items into the top-most level of your backpack while you still need them for your quest. + return false; + } + + return ret; + } + + public override DeathMoveResult OnParentDeath(Mobile parent) + { + if (parent is PlayerMobile mobile && !CanDrop(mobile)) + return DeathMoveResult.MoveToBackpack; + + return base.OnParentDeath(parent); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Core/QuestCallbackEntry.cs b/Projects/UOContent/Engines/Quests/Core/QuestCallbackEntry.cs index 42c3cdc78..98706f103 100644 --- a/Projects/UOContent/Engines/Quests/Core/QuestCallbackEntry.cs +++ b/Projects/UOContent/Engines/Quests/Core/QuestCallbackEntry.cs @@ -1,20 +1,21 @@ -using Server.ContextMenus; - -namespace Server.Engines.Quests -{ - public class QuestCallbackEntry : ContextMenuEntry - { - private readonly QuestCallback m_Callback; - - public QuestCallbackEntry(int number, QuestCallback callback) : this(number, -1, callback) - { - } - - public QuestCallbackEntry(int number, int range, QuestCallback callback) : base(number, range) => m_Callback = callback; - - public override void OnClick() - { - m_Callback?.Invoke(); - } - } -} \ No newline at end of file +using Server.ContextMenus; + +namespace Server.Engines.Quests +{ + public class QuestCallbackEntry : ContextMenuEntry + { + private readonly QuestCallback m_Callback; + + public QuestCallbackEntry(int number, QuestCallback callback) : this(number, -1, callback) + { + } + + public QuestCallbackEntry(int number, int range, QuestCallback callback) : base(number, range) => + m_Callback = callback; + + public override void OnClick() + { + m_Callback?.Invoke(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Core/QuestConversation.cs b/Projects/UOContent/Engines/Quests/Core/QuestConversation.cs index 37ea14ac5..27b03814d 100644 --- a/Projects/UOContent/Engines/Quests/Core/QuestConversation.cs +++ b/Projects/UOContent/Engines/Quests/Core/QuestConversation.cs @@ -1,138 +1,138 @@ -using System.Collections.Generic; -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.Quests -{ - public abstract class QuestConversation - { - public abstract object Message { get; } - - public virtual QuestItemInfo[] Info => null; - public virtual bool Logged => true; - - public QuestSystem System { get; set; } - - public bool HasBeenRead { get; set; } - - public virtual void BaseDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 0: - { - HasBeenRead = reader.ReadBool(); - - break; - } - } - - ChildDeserialize(reader); - } - - public virtual void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - } - - public virtual void BaseSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(HasBeenRead); - - ChildSerialize(writer); - } - - public virtual void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - } - - public virtual void OnRead() - { - } - } - - public class QuestConversationsGump : BaseQuestGump - { - private readonly List m_Conversations; - - public QuestConversationsGump(QuestConversation conv) : this(new List { conv }) - { - } - - public QuestConversationsGump(List conversations) : base(30, 50) - { - m_Conversations = conversations; - - Closable = false; - - AddPage(0); - - AddImage(349, 10, 9392); - AddImageTiled(349, 130, 100, 120, 9395); - AddImageTiled(149, 10, 200, 140, 9391); - AddImageTiled(149, 250, 200, 140, 9397); - AddImage(349, 250, 9398); - AddImage(35, 10, 9390); - AddImageTiled(35, 150, 120, 100, 9393); - AddImage(35, 250, 9396); - - AddHtmlLocalized(110, 60, 200, 20, 1049069, White); // Conversation Event - - AddImage(65, 14, 10102); - AddImageTiled(81, 14, 349, 17, 10101); - AddImage(426, 14, 10104); - - AddImageTiled(55, 40, 388, 323, 2624); - AddAlphaRegion(55, 40, 388, 323); - - AddImageTiled(75, 90, 200, 1, 9101); - AddImage(75, 58, 9781); - AddImage(380, 45, 223); - - AddButton(220, 335, 2313, 2312, 1); - AddImage(0, 0, 10440); - - AddPage(1); - - for (int i = 0; i < conversations.Count; ++i) - { - QuestConversation conv = conversations[conversations.Count - 1 - i]; - - if (i > 0) - { - AddButton(65, 366, 9909, 9911, 0, GumpButtonType.Page, 1 + i); - AddHtmlLocalized(90, 367, 50, 20, 1043354, Black); // Previous - - AddPage(1 + i); - } - - AddHtmlObject(70, 110, 365, 220, conv.Message, LightGreen, false, true); - - if (i > 0) - { - AddButton(420, 366, 9903, 9905, 0, GumpButtonType.Page, i); - AddHtmlLocalized(370, 367, 50, 20, 1043353, Black); // Next - } - } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - for (int i = m_Conversations.Count - 1; i >= 0; --i) - { - QuestConversation qc = m_Conversations[i]; - - if (!qc.HasBeenRead) - { - qc.HasBeenRead = true; - qc.OnRead(); - } - } - } - } -} +using System.Collections.Generic; +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.Quests +{ + public abstract class QuestConversation + { + public abstract object Message { get; } + + public virtual QuestItemInfo[] Info => null; + public virtual bool Logged => true; + + public QuestSystem System { get; set; } + + public bool HasBeenRead { get; set; } + + public virtual void BaseDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 0: + { + HasBeenRead = reader.ReadBool(); + + break; + } + } + + ChildDeserialize(reader); + } + + public virtual void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + } + + public virtual void BaseSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(HasBeenRead); + + ChildSerialize(writer); + } + + public virtual void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + } + + public virtual void OnRead() + { + } + } + + public class QuestConversationsGump : BaseQuestGump + { + private readonly List m_Conversations; + + public QuestConversationsGump(QuestConversation conv) : this(new List { conv }) + { + } + + public QuestConversationsGump(List conversations) : base(30, 50) + { + m_Conversations = conversations; + + Closable = false; + + AddPage(0); + + AddImage(349, 10, 9392); + AddImageTiled(349, 130, 100, 120, 9395); + AddImageTiled(149, 10, 200, 140, 9391); + AddImageTiled(149, 250, 200, 140, 9397); + AddImage(349, 250, 9398); + AddImage(35, 10, 9390); + AddImageTiled(35, 150, 120, 100, 9393); + AddImage(35, 250, 9396); + + AddHtmlLocalized(110, 60, 200, 20, 1049069, White); // Conversation Event + + AddImage(65, 14, 10102); + AddImageTiled(81, 14, 349, 17, 10101); + AddImage(426, 14, 10104); + + AddImageTiled(55, 40, 388, 323, 2624); + AddAlphaRegion(55, 40, 388, 323); + + AddImageTiled(75, 90, 200, 1, 9101); + AddImage(75, 58, 9781); + AddImage(380, 45, 223); + + AddButton(220, 335, 2313, 2312, 1); + AddImage(0, 0, 10440); + + AddPage(1); + + for (var i = 0; i < conversations.Count; ++i) + { + var conv = conversations[conversations.Count - 1 - i]; + + if (i > 0) + { + AddButton(65, 366, 9909, 9911, 0, GumpButtonType.Page, 1 + i); + AddHtmlLocalized(90, 367, 50, 20, 1043354, Black); // Previous + + AddPage(1 + i); + } + + AddHtmlObject(70, 110, 365, 220, conv.Message, LightGreen, false, true); + + if (i > 0) + { + AddButton(420, 366, 9903, 9905, 0, GumpButtonType.Page, i); + AddHtmlLocalized(370, 367, 50, 20, 1043353, Black); // Next + } + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + for (var i = m_Conversations.Count - 1; i >= 0; --i) + { + var qc = m_Conversations[i]; + + if (!qc.HasBeenRead) + { + qc.HasBeenRead = true; + qc.OnRead(); + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Core/QuestItemInfo.cs b/Projects/UOContent/Engines/Quests/Core/QuestItemInfo.cs index 1529bd954..d26d51d6c 100644 --- a/Projects/UOContent/Engines/Quests/Core/QuestItemInfo.cs +++ b/Projects/UOContent/Engines/Quests/Core/QuestItemInfo.cs @@ -1,57 +1,57 @@ -namespace Server.Engines.Quests -{ - public class QuestItemInfo - { - public QuestItemInfo(object name, int itemID) - { - Name = name; - ItemID = itemID; - } - - public object Name { get; set; } - - public int ItemID { get; set; } - } - - public class QuestItemInfoGump : BaseQuestGump - { - public QuestItemInfoGump(QuestItemInfo[] info) : base(485, 75) - { - int height = 100 + info.Length * 75; - - AddPage(0); - - AddBackground(5, 10, 145, height, 5054); - - AddImageTiled(13, 20, 125, 10, 2624); - AddAlphaRegion(13, 20, 125, 10); - - AddImageTiled(13, height - 10, 128, 10, 2624); - AddAlphaRegion(13, height - 10, 128, 10); - - AddImageTiled(13, 20, 10, height - 30, 2624); - AddAlphaRegion(13, 20, 10, height - 30); - - AddImageTiled(131, 20, 10, height - 30, 2624); - AddAlphaRegion(131, 20, 10, height - 30); - - AddHtmlLocalized(67, 35, 120, 20, 1011233, White); // INFO - - AddImage(62, 52, 9157); - AddImage(72, 52, 9157); - AddImage(82, 52, 9157); - - AddButton(25, 31, 1209, 1210, 777); - - AddPage(1); - - for (int i = 0; i < info.Length; ++i) - { - QuestItemInfo cur = info[i]; - - AddHtmlObject(25, 65 + i * 75, 110, 20, cur.Name, 1153, false, false); - AddItem(45, 85 + i * 75, cur.ItemID); - } - } - } -} +namespace Server.Engines.Quests +{ + public class QuestItemInfo + { + public QuestItemInfo(object name, int itemID) + { + Name = name; + ItemID = itemID; + } + + public object Name { get; set; } + + public int ItemID { get; set; } + } + + public class QuestItemInfoGump : BaseQuestGump + { + public QuestItemInfoGump(QuestItemInfo[] info) : base(485, 75) + { + var height = 100 + info.Length * 75; + + AddPage(0); + + AddBackground(5, 10, 145, height, 5054); + + AddImageTiled(13, 20, 125, 10, 2624); + AddAlphaRegion(13, 20, 125, 10); + + AddImageTiled(13, height - 10, 128, 10, 2624); + AddAlphaRegion(13, height - 10, 128, 10); + + AddImageTiled(13, 20, 10, height - 30, 2624); + AddAlphaRegion(13, 20, 10, height - 30); + + AddImageTiled(131, 20, 10, height - 30, 2624); + AddAlphaRegion(131, 20, 10, height - 30); + + AddHtmlLocalized(67, 35, 120, 20, 1011233, White); // INFO + + AddImage(62, 52, 9157); + AddImage(72, 52, 9157); + AddImage(82, 52, 9157); + + AddButton(25, 31, 1209, 1210, 777); + + AddPage(1); + + for (var i = 0; i < info.Length; ++i) + { + var cur = info[i]; + + AddHtmlObject(25, 65 + i * 75, 110, 20, cur.Name, 1153, false, false); + AddItem(45, 85 + i * 75, cur.ItemID); + } + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Core/QuestObjective.cs b/Projects/UOContent/Engines/Quests/Core/QuestObjective.cs index a06baedb2..0c7156e50 100644 --- a/Projects/UOContent/Engines/Quests/Core/QuestObjective.cs +++ b/Projects/UOContent/Engines/Quests/Core/QuestObjective.cs @@ -1,246 +1,246 @@ -using System.Collections.Generic; -using Server.Gumps; -using Server.Items; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.Quests -{ - public abstract class QuestObjective - { - private int m_CurProgress; - - public abstract object Message { get; } - - public virtual int MaxProgress => 1; - public virtual QuestItemInfo[] Info => null; - - public QuestSystem System { get; set; } - - public bool HasBeenRead { get; set; } - - public int CurProgress - { - get => m_CurProgress; - set - { - m_CurProgress = value; - CheckCompletionStatus(); - } - } - - public bool HasCompleted { get; set; } - - public virtual bool Completed => m_CurProgress >= MaxProgress; - - public bool IsSingleObjective => MaxProgress == 1; - - public virtual void BaseDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 1: - { - HasBeenRead = reader.ReadBool(); - goto case 0; - } - case 0: - { - m_CurProgress = reader.ReadEncodedInt(); - HasCompleted = reader.ReadBool(); - - break; - } - } - - ChildDeserialize(reader); - } - - public virtual void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - } - - public virtual void BaseSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(1); // version - - writer.Write(HasBeenRead); - writer.WriteEncodedInt(m_CurProgress); - writer.Write(HasCompleted); - - ChildSerialize(writer); - } - - public virtual void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - } - - public virtual void Complete() - { - CurProgress = MaxProgress; - } - - public virtual void RenderMessage(BaseQuestGump gump) - { - gump.AddHtmlObject(70, 130, 300, 100, Message, BaseQuestGump.Blue, false, false); - } - - public virtual void RenderProgress(BaseQuestGump gump) - { - gump.AddHtmlObject(70, 260, 270, 100, Completed ? 1049077 : 1049078, BaseQuestGump.Blue, false, false); - } - - public virtual void CheckCompletionStatus() - { - if (Completed && !HasCompleted) - { - HasCompleted = true; - OnComplete(); - } - } - - public virtual void OnRead() - { - } - - public virtual bool GetTimerEvent() => !Completed; - - public virtual void CheckProgress() - { - } - - public virtual void OnComplete() - { - } - - public virtual bool GetKillEvent(BaseCreature creature, Container corpse) => !Completed; - - public virtual void OnKill(BaseCreature creature, Container corpse) - { - } - - public virtual bool IgnoreYoungProtection(Mobile from) => false; - } - - public class QuestLogUpdatedGump : BaseQuestGump - { - private readonly QuestSystem m_System; - - public QuestLogUpdatedGump(QuestSystem system) : base(3, 30) - { - m_System = system; - - AddPage(0); - - AddImage(20, 5, 1417); - - AddHtmlLocalized(0, 78, 120, 40, 1049079, White); // Quest Log Updated - - AddImageTiled(0, 78, 120, 40, 2624); - AddAlphaRegion(0, 78, 120, 40); - - AddButton(30, 15, 5575, 5576, 1); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 1) - m_System.ShowQuestLog(); - } - } - - public class QuestObjectivesGump : BaseQuestGump - { - private readonly List m_Objectives; - - public QuestObjectivesGump(QuestObjective obj) : this(new List { obj }) - { - } - - public QuestObjectivesGump(List objectives) : base(90, 50) - { - m_Objectives = objectives; - - Closable = false; - - AddPage(0); - - AddImage(0, 0, 3600); - AddImageTiled(0, 14, 15, 375, 3603); - AddImageTiled(380, 14, 14, 375, 3605); - AddImage(0, 376, 3606); - AddImageTiled(15, 376, 370, 16, 3607); - AddImageTiled(15, 0, 370, 16, 3601); - AddImage(380, 0, 3602); - AddImage(380, 376, 3608); - - AddImageTiled(15, 15, 365, 365, 2624); - AddAlphaRegion(15, 15, 365, 365); - - AddImage(20, 87, 1231); - AddImage(75, 62, 9307); - - AddHtmlLocalized(117, 35, 230, 20, 1046026, Blue); // Quest Log - - AddImage(77, 33, 9781); - AddImage(65, 110, 2104); - - AddHtmlLocalized(79, 106, 230, 20, 1049073, Blue); // Objective: - - AddImageTiled(68, 125, 120, 1, 9101); - AddImage(65, 240, 2104); - - AddHtmlLocalized(79, 237, 230, 20, 1049076, Blue); // Progress details: - - AddImageTiled(68, 255, 120, 1, 9101); - AddButton(175, 355, 2313, 2312, 1); - - AddImage(341, 15, 10450); - AddImage(341, 330, 10450); - AddImage(15, 330, 10450); - AddImage(15, 15, 10450); - - AddPage(1); - - for (int i = 0; i < objectives.Count; ++i) - { - QuestObjective obj = objectives[objectives.Count - 1 - i]; - - if (i > 0) - { - AddButton(55, 346, 9909, 9911, 0, GumpButtonType.Page, 1 + i); - AddHtmlLocalized(82, 347, 50, 20, 1043354, White); // Previous - - AddPage(1 + i); - } - - obj.RenderMessage(this); - obj.RenderProgress(this); - - if (i > 0) - { - AddButton(317, 346, 9903, 9905, 0, GumpButtonType.Page, i); - AddHtmlLocalized(278, 347, 50, 20, 1043353, White); // Next - } - } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - for (int i = m_Objectives.Count - 1; i >= 0; --i) - { - QuestObjective obj = m_Objectives[i]; - - if (!obj.HasBeenRead) - { - obj.HasBeenRead = true; - obj.OnRead(); - } - } - } - } -} +using System.Collections.Generic; +using Server.Gumps; +using Server.Items; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.Quests +{ + public abstract class QuestObjective + { + private int m_CurProgress; + + public abstract object Message { get; } + + public virtual int MaxProgress => 1; + public virtual QuestItemInfo[] Info => null; + + public QuestSystem System { get; set; } + + public bool HasBeenRead { get; set; } + + public int CurProgress + { + get => m_CurProgress; + set + { + m_CurProgress = value; + CheckCompletionStatus(); + } + } + + public bool HasCompleted { get; set; } + + public virtual bool Completed => m_CurProgress >= MaxProgress; + + public bool IsSingleObjective => MaxProgress == 1; + + public virtual void BaseDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 1: + { + HasBeenRead = reader.ReadBool(); + goto case 0; + } + case 0: + { + m_CurProgress = reader.ReadEncodedInt(); + HasCompleted = reader.ReadBool(); + + break; + } + } + + ChildDeserialize(reader); + } + + public virtual void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + } + + public virtual void BaseSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(1); // version + + writer.Write(HasBeenRead); + writer.WriteEncodedInt(m_CurProgress); + writer.Write(HasCompleted); + + ChildSerialize(writer); + } + + public virtual void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + } + + public virtual void Complete() + { + CurProgress = MaxProgress; + } + + public virtual void RenderMessage(BaseQuestGump gump) + { + gump.AddHtmlObject(70, 130, 300, 100, Message, BaseQuestGump.Blue, false, false); + } + + public virtual void RenderProgress(BaseQuestGump gump) + { + gump.AddHtmlObject(70, 260, 270, 100, Completed ? 1049077 : 1049078, BaseQuestGump.Blue, false, false); + } + + public virtual void CheckCompletionStatus() + { + if (Completed && !HasCompleted) + { + HasCompleted = true; + OnComplete(); + } + } + + public virtual void OnRead() + { + } + + public virtual bool GetTimerEvent() => !Completed; + + public virtual void CheckProgress() + { + } + + public virtual void OnComplete() + { + } + + public virtual bool GetKillEvent(BaseCreature creature, Container corpse) => !Completed; + + public virtual void OnKill(BaseCreature creature, Container corpse) + { + } + + public virtual bool IgnoreYoungProtection(Mobile from) => false; + } + + public class QuestLogUpdatedGump : BaseQuestGump + { + private readonly QuestSystem m_System; + + public QuestLogUpdatedGump(QuestSystem system) : base(3, 30) + { + m_System = system; + + AddPage(0); + + AddImage(20, 5, 1417); + + AddHtmlLocalized(0, 78, 120, 40, 1049079, White); // Quest Log Updated + + AddImageTiled(0, 78, 120, 40, 2624); + AddAlphaRegion(0, 78, 120, 40); + + AddButton(30, 15, 5575, 5576, 1); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 1) + m_System.ShowQuestLog(); + } + } + + public class QuestObjectivesGump : BaseQuestGump + { + private readonly List m_Objectives; + + public QuestObjectivesGump(QuestObjective obj) : this(new List { obj }) + { + } + + public QuestObjectivesGump(List objectives) : base(90, 50) + { + m_Objectives = objectives; + + Closable = false; + + AddPage(0); + + AddImage(0, 0, 3600); + AddImageTiled(0, 14, 15, 375, 3603); + AddImageTiled(380, 14, 14, 375, 3605); + AddImage(0, 376, 3606); + AddImageTiled(15, 376, 370, 16, 3607); + AddImageTiled(15, 0, 370, 16, 3601); + AddImage(380, 0, 3602); + AddImage(380, 376, 3608); + + AddImageTiled(15, 15, 365, 365, 2624); + AddAlphaRegion(15, 15, 365, 365); + + AddImage(20, 87, 1231); + AddImage(75, 62, 9307); + + AddHtmlLocalized(117, 35, 230, 20, 1046026, Blue); // Quest Log + + AddImage(77, 33, 9781); + AddImage(65, 110, 2104); + + AddHtmlLocalized(79, 106, 230, 20, 1049073, Blue); // Objective: + + AddImageTiled(68, 125, 120, 1, 9101); + AddImage(65, 240, 2104); + + AddHtmlLocalized(79, 237, 230, 20, 1049076, Blue); // Progress details: + + AddImageTiled(68, 255, 120, 1, 9101); + AddButton(175, 355, 2313, 2312, 1); + + AddImage(341, 15, 10450); + AddImage(341, 330, 10450); + AddImage(15, 330, 10450); + AddImage(15, 15, 10450); + + AddPage(1); + + for (var i = 0; i < objectives.Count; ++i) + { + var obj = objectives[objectives.Count - 1 - i]; + + if (i > 0) + { + AddButton(55, 346, 9909, 9911, 0, GumpButtonType.Page, 1 + i); + AddHtmlLocalized(82, 347, 50, 20, 1043354, White); // Previous + + AddPage(1 + i); + } + + obj.RenderMessage(this); + obj.RenderProgress(this); + + if (i > 0) + { + AddButton(317, 346, 9903, 9905, 0, GumpButtonType.Page, i); + AddHtmlLocalized(278, 347, 50, 20, 1043353, White); // Next + } + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + for (var i = m_Objectives.Count - 1; i >= 0; --i) + { + var obj = m_Objectives[i]; + + if (!obj.HasBeenRead) + { + obj.HasBeenRead = true; + obj.OnRead(); + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Core/QuestRestartInfo.cs b/Projects/UOContent/Engines/Quests/Core/QuestRestartInfo.cs index 8764271d3..6eb8a80ea 100644 --- a/Projects/UOContent/Engines/Quests/Core/QuestRestartInfo.cs +++ b/Projects/UOContent/Engines/Quests/Core/QuestRestartInfo.cs @@ -1,31 +1,31 @@ -using System; - -namespace Server.Engines.Quests -{ - public class QuestRestartInfo - { - public QuestRestartInfo(Type questType, TimeSpan restartDelay) - { - QuestType = questType; - Reset(restartDelay); - } - - public QuestRestartInfo(Type questType, DateTime restartTime) - { - QuestType = questType; - RestartTime = restartTime; - } - - public Type QuestType { get; set; } - - public DateTime RestartTime { get; set; } - - public void Reset(TimeSpan restartDelay) - { - if (restartDelay < TimeSpan.MaxValue) - RestartTime = DateTime.UtcNow + restartDelay; - else - RestartTime = DateTime.MaxValue; - } - } -} \ No newline at end of file +using System; + +namespace Server.Engines.Quests +{ + public class QuestRestartInfo + { + public QuestRestartInfo(Type questType, TimeSpan restartDelay) + { + QuestType = questType; + Reset(restartDelay); + } + + public QuestRestartInfo(Type questType, DateTime restartTime) + { + QuestType = questType; + RestartTime = restartTime; + } + + public Type QuestType { get; set; } + + public DateTime RestartTime { get; set; } + + public void Reset(TimeSpan restartDelay) + { + if (restartDelay < TimeSpan.MaxValue) + RestartTime = DateTime.UtcNow + restartDelay; + else + RestartTime = DateTime.MaxValue; + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Core/QuestSerializer.cs b/Projects/UOContent/Engines/Quests/Core/QuestSerializer.cs index a9b347ff0..2b285bec5 100644 --- a/Projects/UOContent/Engines/Quests/Core/QuestSerializer.cs +++ b/Projects/UOContent/Engines/Quests/Core/QuestSerializer.cs @@ -1,189 +1,189 @@ -using System; -using Server.Utilities; - -namespace Server.Engines.Quests -{ - public class QuestSerializer - { - public static object Construct(Type type) - { - try - { - return ActivatorUtil.CreateInstance(type); - } - catch - { - return null; - } - } - - public static void Write(Type type, Type[] referenceTable, IGenericWriter writer) - { - if (type == null) - { - writer.WriteEncodedInt(0x00); - } - else - { - for (int i = 0; i < referenceTable.Length; ++i) - if (referenceTable[i] == type) - { - writer.WriteEncodedInt(0x01); - writer.WriteEncodedInt(i); - return; - } - - writer.WriteEncodedInt(0x02); - writer.Write(type.FullName); - } - } - - public static Type ReadType(Type[] referenceTable, IGenericReader reader) - { - int encoding = reader.ReadEncodedInt(); - - switch (encoding) - { - default: - { - return null; - } - case 0x01: // indexed - { - int index = reader.ReadEncodedInt(); - - if (index >= 0 && index < referenceTable.Length) - return referenceTable[index]; - - return null; - } - case 0x02: // by name - { - string fullName = reader.ReadString(); - - if (fullName == null) - return null; - - return AssemblyHandler.FindFirstTypeForName(fullName, false); - } - } - } - - public static QuestSystem DeserializeQuest(IGenericReader reader) - { - int encoding = reader.ReadEncodedInt(); - - switch (encoding) - { - default: - { - return null; - } - case 0x01: - { - Type type = ReadType(QuestSystem.QuestTypes, reader); - - QuestSystem qs = Construct(type) as QuestSystem; - - qs?.BaseDeserialize(reader); - - return qs; - } - } - } - - public static void Serialize(QuestSystem qs, IGenericWriter writer) - { - if (qs == null) - { - writer.WriteEncodedInt(0x00); - } - else - { - writer.WriteEncodedInt(0x01); - - Write(qs.GetType(), QuestSystem.QuestTypes, writer); - - qs.BaseSerialize(writer); - } - } - - public static QuestObjective DeserializeObjective(Type[] referenceTable, IGenericReader reader) - { - int encoding = reader.ReadEncodedInt(); - - switch (encoding) - { - default: - { - return null; - } - case 0x01: - { - Type type = ReadType(referenceTable, reader); - - QuestObjective obj = Construct(type) as QuestObjective; - - obj?.BaseDeserialize(reader); - - return obj; - } - } - } - - public static void Serialize(Type[] referenceTable, QuestObjective obj, IGenericWriter writer) - { - if (obj == null) - { - writer.WriteEncodedInt(0x00); - } - else - { - writer.WriteEncodedInt(0x01); - - Write(obj.GetType(), referenceTable, writer); - - obj.BaseSerialize(writer); - } - } - - public static QuestConversation DeserializeConversation(Type[] referenceTable, IGenericReader reader) - { - int encoding = reader.ReadEncodedInt(); - - switch (encoding) - { - default: - { - return null; - } - case 0x01: - { - Type type = ReadType(referenceTable, reader); - - QuestConversation conv = Construct(type) as QuestConversation; - - conv?.BaseDeserialize(reader); - - return conv; - } - } - } - - public static void Serialize(Type[] referenceTable, QuestConversation conv, IGenericWriter writer) - { - if (conv == null) - { - writer.WriteEncodedInt(0x00); - } - else - { - writer.WriteEncodedInt(0x01); - - Write(conv.GetType(), referenceTable, writer); - - conv.BaseSerialize(writer); - } - } - } -} +using System; +using Server.Utilities; + +namespace Server.Engines.Quests +{ + public class QuestSerializer + { + public static object Construct(Type type) + { + try + { + return ActivatorUtil.CreateInstance(type); + } + catch + { + return null; + } + } + + public static void Write(Type type, Type[] referenceTable, IGenericWriter writer) + { + if (type == null) + { + writer.WriteEncodedInt(0x00); + } + else + { + for (var i = 0; i < referenceTable.Length; ++i) + if (referenceTable[i] == type) + { + writer.WriteEncodedInt(0x01); + writer.WriteEncodedInt(i); + return; + } + + writer.WriteEncodedInt(0x02); + writer.Write(type.FullName); + } + } + + public static Type ReadType(Type[] referenceTable, IGenericReader reader) + { + var encoding = reader.ReadEncodedInt(); + + switch (encoding) + { + default: + { + return null; + } + case 0x01: // indexed + { + var index = reader.ReadEncodedInt(); + + if (index >= 0 && index < referenceTable.Length) + return referenceTable[index]; + + return null; + } + case 0x02: // by name + { + var fullName = reader.ReadString(); + + if (fullName == null) + return null; + + return AssemblyHandler.FindFirstTypeForName(fullName); + } + } + } + + public static QuestSystem DeserializeQuest(IGenericReader reader) + { + var encoding = reader.ReadEncodedInt(); + + switch (encoding) + { + default: + { + return null; + } + case 0x01: + { + var type = ReadType(QuestSystem.QuestTypes, reader); + + var qs = Construct(type) as QuestSystem; + + qs?.BaseDeserialize(reader); + + return qs; + } + } + } + + public static void Serialize(QuestSystem qs, IGenericWriter writer) + { + if (qs == null) + { + writer.WriteEncodedInt(0x00); + } + else + { + writer.WriteEncodedInt(0x01); + + Write(qs.GetType(), QuestSystem.QuestTypes, writer); + + qs.BaseSerialize(writer); + } + } + + public static QuestObjective DeserializeObjective(Type[] referenceTable, IGenericReader reader) + { + var encoding = reader.ReadEncodedInt(); + + switch (encoding) + { + default: + { + return null; + } + case 0x01: + { + var type = ReadType(referenceTable, reader); + + var obj = Construct(type) as QuestObjective; + + obj?.BaseDeserialize(reader); + + return obj; + } + } + } + + public static void Serialize(Type[] referenceTable, QuestObjective obj, IGenericWriter writer) + { + if (obj == null) + { + writer.WriteEncodedInt(0x00); + } + else + { + writer.WriteEncodedInt(0x01); + + Write(obj.GetType(), referenceTable, writer); + + obj.BaseSerialize(writer); + } + } + + public static QuestConversation DeserializeConversation(Type[] referenceTable, IGenericReader reader) + { + var encoding = reader.ReadEncodedInt(); + + switch (encoding) + { + default: + { + return null; + } + case 0x01: + { + var type = ReadType(referenceTable, reader); + + var conv = Construct(type) as QuestConversation; + + conv?.BaseDeserialize(reader); + + return conv; + } + } + } + + public static void Serialize(Type[] referenceTable, QuestConversation conv, IGenericWriter writer) + { + if (conv == null) + { + writer.WriteEncodedInt(0x00); + } + else + { + writer.WriteEncodedInt(0x01); + + Write(conv.GetType(), referenceTable, writer); + + conv.BaseSerialize(writer); + } + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Core/QuestSystem.cs b/Projects/UOContent/Engines/Quests/Core/QuestSystem.cs index 88871667c..22fdb287e 100644 --- a/Projects/UOContent/Engines/Quests/Core/QuestSystem.cs +++ b/Projects/UOContent/Engines/Quests/Core/QuestSystem.cs @@ -1,643 +1,658 @@ -using System; -using System.Collections.Generic; -using Server.ContextMenus; -using Server.Engines.Quests.Ambitious; -using Server.Engines.Quests.Collector; -using Server.Engines.Quests.Doom; -using Server.Engines.Quests.Hag; -using Server.Engines.Quests.Haven; -using Server.Engines.Quests.Matriarch; -using Server.Engines.Quests.Naturalist; -using Server.Engines.Quests.Necro; -using Server.Engines.Quests.Ninja; -using Server.Engines.Quests.Samurai; -using Server.Engines.Quests.Zento; -using Server.Gumps; -using Server.Items; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.Quests -{ - public delegate void QuestCallback(); - - public abstract class QuestSystem - { - public static readonly Type[] QuestTypes = - { - typeof(TheSummoningQuest), - typeof(DarkTidesQuest), - typeof(UzeraanTurmoilQuest), - typeof(CollectorQuest), - typeof(WitchApprenticeQuest), - typeof(StudyOfSolenQuest), - typeof(SolenMatriarchQuest), - typeof(AmbitiousQueenQuest), - typeof(EminosUndertakingQuest), - typeof(HaochisTrialsQuest), - typeof(TerribleHatchlingsQuest) - }; - - private Timer m_Timer; - - public QuestSystem(PlayerMobile from) - { - From = from; - Objectives = new List(); - Conversations = new List(); - } - - public QuestSystem() - { - } - - public abstract object Name { get; } - public abstract object OfferMessage { get; } - - public abstract int Picture { get; } - - public abstract bool IsTutorial { get; } - public abstract TimeSpan RestartDelay { get; } - - public abstract Type[] TypeReferenceTable { get; } - - public PlayerMobile From { get; set; } - - public List Objectives { get; set; } - - public List Conversations { get; set; } - - public virtual void StartTimer() - { - if (m_Timer != null) - return; - - m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(0.5), TimeSpan.FromSeconds(0.5), Slice); - } - - public virtual void StopTimer() - { - m_Timer?.Stop(); - - m_Timer = null; - } - - public virtual void Slice() - { - for (int i = Objectives.Count - 1; i >= 0; --i) - { - QuestObjective obj = Objectives[i]; - - if (obj.GetTimerEvent()) - obj.CheckProgress(); - } - } - - public virtual void OnKill(BaseCreature creature, Container corpse) - { - for (int i = Objectives.Count - 1; i >= 0; --i) - { - QuestObjective obj = Objectives[i]; - - if (obj.GetKillEvent(creature, corpse)) - obj.OnKill(creature, corpse); - } - } - - public virtual bool IgnoreYoungProtection(Mobile from) - { - for (int i = Objectives.Count - 1; i >= 0; --i) - { - QuestObjective obj = Objectives[i]; - - if (obj.IgnoreYoungProtection(from)) - return true; - } - - return false; - } - - public virtual void BaseDeserialize(IGenericReader reader) - { - Type[] referenceTable = TypeReferenceTable; - - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 0: - { - int count = reader.ReadEncodedInt(); - - Objectives = new List(count); - - for (int i = 0; i < count; ++i) - { - QuestObjective obj = QuestSerializer.DeserializeObjective(referenceTable, reader); - - if (obj != null) - { - obj.System = this; - Objectives.Add(obj); - } - } - - count = reader.ReadEncodedInt(); - - Conversations = new List(count); - - for (int i = 0; i < count; ++i) - { - QuestConversation conv = QuestSerializer.DeserializeConversation(referenceTable, reader); - - if (conv != null) - { - conv.System = this; - Conversations.Add(conv); - } - } - - break; - } - } - - ChildDeserialize(reader); - } - - public virtual void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - } - - public virtual void BaseSerialize(IGenericWriter writer) - { - Type[] referenceTable = TypeReferenceTable; - - writer.WriteEncodedInt(0); // version - - writer.WriteEncodedInt(Objectives.Count); - - for (int i = 0; i < Objectives.Count; ++i) - QuestSerializer.Serialize(referenceTable, Objectives[i], writer); - - writer.WriteEncodedInt(Conversations.Count); - - for (int i = 0; i < Conversations.Count; ++i) - QuestSerializer.Serialize(referenceTable, Conversations[i], writer); - - ChildSerialize(writer); - } - - public virtual void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - } - - public bool IsObjectiveInProgress(Type type) - { - QuestObjective obj = FindObjective(type); - - return obj?.Completed == false; - } - - public T FindObjective() where T : QuestObjective - { - for (int i = Objectives.Count - 1; i >= 0; --i) - { - QuestObjective obj = Objectives[i]; - - if (obj is T t) - return t; - } - - return null; - } - - public QuestObjective FindObjective(Type type) - { - for (int i = Objectives.Count - 1; i >= 0; --i) - { - QuestObjective obj = Objectives[i]; - - if (obj.GetType() == type) - return obj; - } - - return null; - } - - public virtual void SendOffer() - { - From.SendGump(new QuestOfferGump(this)); - } - - public virtual void GetContextMenuEntries(List list) - { - if (Objectives.Count > 0) - list.Add(new QuestCallbackEntry(6154, ShowQuestLog)); // View Quest Log - - if (Conversations.Count > 0) - list.Add(new QuestCallbackEntry(6156, ShowQuestConversation)); // Quest Conversation - - list.Add(new QuestCallbackEntry(6155, BeginCancelQuest)); // Cancel Quest - } - - public virtual void ShowQuestLogUpdated() - { - From.CloseGump(); - From.SendGump(new QuestLogUpdatedGump(this)); - } - - public virtual void ShowQuestLog() - { - if (Objectives.Count > 0) - { - From.CloseGump(); - From.CloseGump(); - From.CloseGump(); - From.CloseGump(); - - From.SendGump(new QuestObjectivesGump(Objectives)); - - QuestObjective last = Objectives[^1]; - - if (last.Info != null) - From.SendGump(new QuestItemInfoGump(last.Info)); - } - } - - public virtual void ShowQuestConversation() - { - if (Conversations.Count > 0) - { - From.CloseGump(); - From.CloseGump(); - From.CloseGump(); - - From.SendGump(new QuestConversationsGump(Conversations)); - - QuestConversation last = Conversations[^1]; - - if (last.Info != null) - From.SendGump(new QuestItemInfoGump(last.Info)); - } - } - - public virtual void BeginCancelQuest() - { - From.SendGump(new QuestCancelGump(this)); - } - - public virtual void EndCancelQuest(bool shouldCancel) - { - if (From.Quest != this) - return; - - if (shouldCancel) - { - From.SendLocalizedMessage(1049015); // You have canceled your quest. - Cancel(); - } - else - { - From.SendLocalizedMessage(1049014); // You have chosen not to cancel your quest. - } - } - - public virtual void Cancel() - { - ClearQuest(false); - } - - public virtual void Complete() - { - ClearQuest(true); - } - - public virtual void ClearQuest(bool completed) - { - StopTimer(); - - if (From.Quest == this) - { - From.Quest = null; - - TimeSpan restartDelay = RestartDelay; - - if ((completed && restartDelay > TimeSpan.Zero) || (!completed && restartDelay == TimeSpan.MaxValue)) - { - From.DoneQuests ??= new List(); - - bool found = false; - - Type ourQuestType = GetType(); - - for (int i = 0; i < From.DoneQuests.Count; ++i) - { - QuestRestartInfo restartInfo = From.DoneQuests[i]; - - if (restartInfo.QuestType == ourQuestType) - { - restartInfo.Reset(restartDelay); - found = true; - break; - } - } - - if (!found) - From.DoneQuests.Add(new QuestRestartInfo(ourQuestType, restartDelay)); - } - } - } - - public virtual void AddConversation(QuestConversation conv) - { - conv.System = this; - - if (conv.Logged) - Conversations.Add(conv); - - From.CloseGump(); - From.CloseGump(); - From.CloseGump(); - From.SendGump(conv.Logged ? new QuestConversationsGump(Conversations) : new QuestConversationsGump(conv)); - - if (conv.Info != null) - From.SendGump(new QuestItemInfoGump(conv.Info)); - } - - public virtual void AddObjective(QuestObjective obj) - { - obj.System = this; - Objectives.Add(obj); - - ShowQuestLogUpdated(); - } - - public virtual void Accept() - { - if (From.Quest != null) - return; - - From.Quest = this; - From.SendLocalizedMessage(1049019); // You have accepted the Quest. - - StartTimer(); - } - - public virtual void Decline() - { - From.SendLocalizedMessage(1049018); // You have declined the Quest. - } - - public static bool CanOfferQuest(Mobile check, Type questType) => CanOfferQuest(check, questType, out _); - - public static bool CanOfferQuest(Mobile check, Type questType, out bool inRestartPeriod) - { - inRestartPeriod = false; - - if (!(check is PlayerMobile pm)) - return false; - - if (pm.HasGump()) - return false; - - if (questType == typeof(DarkTidesQuest) && pm.Profession != 4) // necromancer - return false; - - if (questType == typeof(UzeraanTurmoilQuest) && pm.Profession != 1 && pm.Profession != 2 && pm.Profession != 5) // warrior / magician / paladin - return false; - - if (questType == typeof(HaochisTrialsQuest) && pm.Profession != 6) // samurai - return false; - - if (questType == typeof(EminosUndertakingQuest) && pm.Profession != 7) // ninja - return false; - - List doneQuests = pm.DoneQuests; - - if (doneQuests != null) - for (int i = 0; i < doneQuests.Count; ++i) - { - QuestRestartInfo restartInfo = doneQuests[i]; - - if (restartInfo.QuestType == questType) - { - DateTime endTime = restartInfo.RestartTime; - - if (DateTime.UtcNow < endTime) - { - inRestartPeriod = true; - return false; - } - - doneQuests.RemoveAt(i); - return true; - } - } - - return true; - } - - public static void FocusTo(Mobile who, Mobile to) - { - if (Utility.RandomBool()) - who.Animate(17, 7, 1, true, false, 0); - else - who.Animate(32 + Utility.Random(3), 7, 1, true, false, 0); - - who.Direction = who.GetDirectionTo(to); - } - - public static int RandomBrightHue() - { - if (Utility.RandomDouble() < 0.1) - return Utility.RandomList(0x62, 0x71); - - return Utility.RandomList(0x03, 0x0D, 0x13, 0x1C, 0x21, 0x30, 0x37, 0x3A, 0x44, 0x59); - } - } - - public class QuestCancelGump : BaseQuestGump - { - private readonly QuestSystem m_System; - - public QuestCancelGump(QuestSystem system) : base(120, 50) - { - m_System = system; - - Closable = false; - - AddPage(0); - - AddImageTiled(0, 0, 348, 262, 2702); - AddAlphaRegion(0, 0, 348, 262); - - AddImage(0, 15, 10152); - AddImageTiled(0, 30, 17, 200, 10151); - AddImage(0, 230, 10154); - - AddImage(15, 0, 10252); - AddImageTiled(30, 0, 300, 17, 10250); - AddImage(315, 0, 10254); - - AddImage(15, 244, 10252); - AddImageTiled(30, 244, 300, 17, 10250); - AddImage(315, 244, 10254); - - AddImage(330, 15, 10152); - AddImageTiled(330, 30, 17, 200, 10151); - AddImage(330, 230, 10154); - - AddImage(333, 2, 10006); - AddImage(333, 248, 10006); - AddImage(2, 248, 10006); - AddImage(2, 2, 10006); - - AddHtmlLocalized(25, 22, 200, 20, 1049000, 32000); // Confirm Quest Cancellation - AddImage(25, 40, 3007); - - if (system.IsTutorial) - { - AddHtmlLocalized(25, 55, 300, 120, 1060836, White); // This quest will give you valuable information, skills and equipment that will help you advance in the game at a quicker pace.

Are you certain you wish to cancel at this time? - } - else - { - AddHtmlLocalized(25, 60, 300, 20, 1049001, White); // You have chosen to abort your quest: - AddImage(25, 81, 0x25E7); - AddHtmlObject(48, 80, 280, 20, system.Name, DarkGreen, false, false); - - AddHtmlLocalized(25, 120, 280, 20, 1049002, White); // Can this quest be restarted after quitting? - AddImage(25, 141, 0x25E7); - AddHtmlLocalized(48, 140, 280, 20, system.RestartDelay < TimeSpan.MaxValue ? 1049016 : 1049017, DarkGreen); // Yes/No - } - - AddRadio(25, 175, 9720, 9723, true, 1); - AddHtmlLocalized(60, 180, 280, 20, 1049005, White); // Yes, I really want to quit! - - AddRadio(25, 210, 9720, 9723, false, 0); - AddHtmlLocalized(60, 215, 280, 20, 1049006, White); // No, I don't want to quit. - - AddButton(265, 220, 247, 248, 1); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 1) - m_System.EndCancelQuest(info.IsSwitched(1)); - } - } - - public class QuestOfferGump : BaseQuestGump - { - private readonly QuestSystem m_System; - - public QuestOfferGump(QuestSystem system) : base(75, 25) - { - m_System = system; - - Closable = false; - - AddPage(0); - - AddImageTiled(50, 20, 400, 400, 2624); - AddAlphaRegion(50, 20, 400, 400); - - AddImage(90, 33, 9005); - AddHtmlLocalized(130, 45, 270, 20, 1049010, White); // Quest Offer - AddImageTiled(130, 65, 175, 1, 9101); - - AddImage(140, 110, 1209); - AddHtmlObject(160, 108, 250, 20, system.Name, DarkGreen, false, false); - - AddHtmlObject(98, 140, 312, 200, system.OfferMessage, LightGreen, false, true); - - AddRadio(85, 350, 9720, 9723, true, 1); - AddHtmlLocalized(120, 356, 280, 20, 1049011, White); // I accept! - - AddRadio(85, 385, 9720, 9723, false, 0); - AddHtmlLocalized(120, 391, 280, 20, 1049012, White); // No thanks, I decline. - - AddButton(340, 390, 247, 248, 1); - - AddImageTiled(50, 29, 30, 390, 10460); - AddImageTiled(34, 140, 17, 279, 9263); - - AddImage(48, 135, 10411); - AddImage(-16, 285, 10402); - AddImage(0, 10, 10421); - AddImage(25, 0, 10420); - - AddImageTiled(83, 15, 350, 15, 10250); - - AddImage(34, 419, 10306); - AddImage(442, 419, 10304); - AddImageTiled(51, 419, 392, 17, 10101); - - AddImageTiled(415, 29, 44, 390, 2605); - AddImageTiled(415, 29, 30, 390, 10460); - AddImage(425, 0, 10441); - - AddImage(370, 50, 1417); - AddImage(379, 60, system.Picture); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 1) - { - if (info.IsSwitched(1)) - m_System.Accept(); - else - m_System.Decline(); - } - } - } - - public abstract class BaseQuestGump : Gump - { - public const int Black = 0x0000; - public const int White = 0x7FFF; - public const int DarkGreen = 10000; - public const int LightGreen = 90000; - public const int Blue = 19777215; - - public BaseQuestGump(int x, int y) : base(x, y) - { - } - - public static int C16232(int c16) - { - c16 &= 0x7FFF; - - int r = (c16 >> 10 & 0x1F) << 3; - int g = (c16 >> 05 & 0x1F) << 3; - int b = (c16 & 0x1F) << 3; - - return r << 16 | g << 8 | b; - } - - public static int C16216(int c16) => c16 & 0x7FFF; - - public static int C32216(int c32) - { - c32 &= 0xFFFFFF; - - int r = (c32 >> 16 & 0xFF) >> 3; - int g = (c32 >> 08 & 0xFF) >> 3; - int b = (c32 & 0xFF) >> 3; - - return r << 10 | g << 5 | b; - } - - public static string Color(string text, int color) => $"{text}"; - - public void AddHtmlObject(int x, int y, int width, int height, object message, int color, bool back, bool scroll) - { - if (message is int html) - AddHtmlLocalized(x, y, width, height, html, C16216(color), back, scroll); - else - AddHtml(x, y, width, height, Color(message.ToString(), C16232(color)), back, scroll); - } - } -} +using System; +using System.Collections.Generic; +using Server.ContextMenus; +using Server.Engines.Quests.Ambitious; +using Server.Engines.Quests.Collector; +using Server.Engines.Quests.Doom; +using Server.Engines.Quests.Hag; +using Server.Engines.Quests.Haven; +using Server.Engines.Quests.Matriarch; +using Server.Engines.Quests.Naturalist; +using Server.Engines.Quests.Necro; +using Server.Engines.Quests.Ninja; +using Server.Engines.Quests.Samurai; +using Server.Engines.Quests.Zento; +using Server.Gumps; +using Server.Items; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.Quests +{ + public delegate void QuestCallback(); + + public abstract class QuestSystem + { + public static readonly Type[] QuestTypes = + { + typeof(TheSummoningQuest), + typeof(DarkTidesQuest), + typeof(UzeraanTurmoilQuest), + typeof(CollectorQuest), + typeof(WitchApprenticeQuest), + typeof(StudyOfSolenQuest), + typeof(SolenMatriarchQuest), + typeof(AmbitiousQueenQuest), + typeof(EminosUndertakingQuest), + typeof(HaochisTrialsQuest), + typeof(TerribleHatchlingsQuest) + }; + + private Timer m_Timer; + + public QuestSystem(PlayerMobile from) + { + From = from; + Objectives = new List(); + Conversations = new List(); + } + + public QuestSystem() + { + } + + public abstract object Name { get; } + public abstract object OfferMessage { get; } + + public abstract int Picture { get; } + + public abstract bool IsTutorial { get; } + public abstract TimeSpan RestartDelay { get; } + + public abstract Type[] TypeReferenceTable { get; } + + public PlayerMobile From { get; set; } + + public List Objectives { get; set; } + + public List Conversations { get; set; } + + public virtual void StartTimer() + { + if (m_Timer != null) + return; + + m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(0.5), TimeSpan.FromSeconds(0.5), Slice); + } + + public virtual void StopTimer() + { + m_Timer?.Stop(); + + m_Timer = null; + } + + public virtual void Slice() + { + for (var i = Objectives.Count - 1; i >= 0; --i) + { + var obj = Objectives[i]; + + if (obj.GetTimerEvent()) + obj.CheckProgress(); + } + } + + public virtual void OnKill(BaseCreature creature, Container corpse) + { + for (var i = Objectives.Count - 1; i >= 0; --i) + { + var obj = Objectives[i]; + + if (obj.GetKillEvent(creature, corpse)) + obj.OnKill(creature, corpse); + } + } + + public virtual bool IgnoreYoungProtection(Mobile from) + { + for (var i = Objectives.Count - 1; i >= 0; --i) + { + var obj = Objectives[i]; + + if (obj.IgnoreYoungProtection(from)) + return true; + } + + return false; + } + + public virtual void BaseDeserialize(IGenericReader reader) + { + var referenceTable = TypeReferenceTable; + + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 0: + { + var count = reader.ReadEncodedInt(); + + Objectives = new List(count); + + for (var i = 0; i < count; ++i) + { + var obj = QuestSerializer.DeserializeObjective(referenceTable, reader); + + if (obj != null) + { + obj.System = this; + Objectives.Add(obj); + } + } + + count = reader.ReadEncodedInt(); + + Conversations = new List(count); + + for (var i = 0; i < count; ++i) + { + var conv = QuestSerializer.DeserializeConversation(referenceTable, reader); + + if (conv != null) + { + conv.System = this; + Conversations.Add(conv); + } + } + + break; + } + } + + ChildDeserialize(reader); + } + + public virtual void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + } + + public virtual void BaseSerialize(IGenericWriter writer) + { + var referenceTable = TypeReferenceTable; + + writer.WriteEncodedInt(0); // version + + writer.WriteEncodedInt(Objectives.Count); + + for (var i = 0; i < Objectives.Count; ++i) + QuestSerializer.Serialize(referenceTable, Objectives[i], writer); + + writer.WriteEncodedInt(Conversations.Count); + + for (var i = 0; i < Conversations.Count; ++i) + QuestSerializer.Serialize(referenceTable, Conversations[i], writer); + + ChildSerialize(writer); + } + + public virtual void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + } + + public bool IsObjectiveInProgress(Type type) + { + var obj = FindObjective(type); + + return obj?.Completed == false; + } + + public T FindObjective() where T : QuestObjective + { + for (var i = Objectives.Count - 1; i >= 0; --i) + { + var obj = Objectives[i]; + + if (obj is T t) + return t; + } + + return null; + } + + public QuestObjective FindObjective(Type type) + { + for (var i = Objectives.Count - 1; i >= 0; --i) + { + var obj = Objectives[i]; + + if (obj.GetType() == type) + return obj; + } + + return null; + } + + public virtual void SendOffer() + { + From.SendGump(new QuestOfferGump(this)); + } + + public virtual void GetContextMenuEntries(List list) + { + if (Objectives.Count > 0) + list.Add(new QuestCallbackEntry(6154, ShowQuestLog)); // View Quest Log + + if (Conversations.Count > 0) + list.Add(new QuestCallbackEntry(6156, ShowQuestConversation)); // Quest Conversation + + list.Add(new QuestCallbackEntry(6155, BeginCancelQuest)); // Cancel Quest + } + + public virtual void ShowQuestLogUpdated() + { + From.CloseGump(); + From.SendGump(new QuestLogUpdatedGump(this)); + } + + public virtual void ShowQuestLog() + { + if (Objectives.Count > 0) + { + From.CloseGump(); + From.CloseGump(); + From.CloseGump(); + From.CloseGump(); + + From.SendGump(new QuestObjectivesGump(Objectives)); + + var last = Objectives[^1]; + + if (last.Info != null) + From.SendGump(new QuestItemInfoGump(last.Info)); + } + } + + public virtual void ShowQuestConversation() + { + if (Conversations.Count > 0) + { + From.CloseGump(); + From.CloseGump(); + From.CloseGump(); + + From.SendGump(new QuestConversationsGump(Conversations)); + + var last = Conversations[^1]; + + if (last.Info != null) + From.SendGump(new QuestItemInfoGump(last.Info)); + } + } + + public virtual void BeginCancelQuest() + { + From.SendGump(new QuestCancelGump(this)); + } + + public virtual void EndCancelQuest(bool shouldCancel) + { + if (From.Quest != this) + return; + + if (shouldCancel) + { + From.SendLocalizedMessage(1049015); // You have canceled your quest. + Cancel(); + } + else + { + From.SendLocalizedMessage(1049014); // You have chosen not to cancel your quest. + } + } + + public virtual void Cancel() + { + ClearQuest(false); + } + + public virtual void Complete() + { + ClearQuest(true); + } + + public virtual void ClearQuest(bool completed) + { + StopTimer(); + + if (From.Quest == this) + { + From.Quest = null; + + var restartDelay = RestartDelay; + + if (completed && restartDelay > TimeSpan.Zero || !completed && restartDelay == TimeSpan.MaxValue) + { + From.DoneQuests ??= new List(); + + var found = false; + + var ourQuestType = GetType(); + + for (var i = 0; i < From.DoneQuests.Count; ++i) + { + var restartInfo = From.DoneQuests[i]; + + if (restartInfo.QuestType == ourQuestType) + { + restartInfo.Reset(restartDelay); + found = true; + break; + } + } + + if (!found) + From.DoneQuests.Add(new QuestRestartInfo(ourQuestType, restartDelay)); + } + } + } + + public virtual void AddConversation(QuestConversation conv) + { + conv.System = this; + + if (conv.Logged) + Conversations.Add(conv); + + From.CloseGump(); + From.CloseGump(); + From.CloseGump(); + From.SendGump(conv.Logged ? new QuestConversationsGump(Conversations) : new QuestConversationsGump(conv)); + + if (conv.Info != null) + From.SendGump(new QuestItemInfoGump(conv.Info)); + } + + public virtual void AddObjective(QuestObjective obj) + { + obj.System = this; + Objectives.Add(obj); + + ShowQuestLogUpdated(); + } + + public virtual void Accept() + { + if (From.Quest != null) + return; + + From.Quest = this; + From.SendLocalizedMessage(1049019); // You have accepted the Quest. + + StartTimer(); + } + + public virtual void Decline() + { + From.SendLocalizedMessage(1049018); // You have declined the Quest. + } + + public static bool CanOfferQuest(Mobile check, Type questType) => CanOfferQuest(check, questType, out _); + + public static bool CanOfferQuest(Mobile check, Type questType, out bool inRestartPeriod) + { + inRestartPeriod = false; + + if (!(check is PlayerMobile pm)) + return false; + + if (pm.HasGump()) + return false; + + if (questType == typeof(DarkTidesQuest) && pm.Profession != 4) // necromancer + return false; + + if (questType == typeof(UzeraanTurmoilQuest) && pm.Profession != 1 && pm.Profession != 2 && pm.Profession != 5 + ) // warrior / magician / paladin + return false; + + if (questType == typeof(HaochisTrialsQuest) && pm.Profession != 6) // samurai + return false; + + if (questType == typeof(EminosUndertakingQuest) && pm.Profession != 7) // ninja + return false; + + var doneQuests = pm.DoneQuests; + + if (doneQuests != null) + for (var i = 0; i < doneQuests.Count; ++i) + { + var restartInfo = doneQuests[i]; + + if (restartInfo.QuestType == questType) + { + var endTime = restartInfo.RestartTime; + + if (DateTime.UtcNow < endTime) + { + inRestartPeriod = true; + return false; + } + + doneQuests.RemoveAt(i); + return true; + } + } + + return true; + } + + public static void FocusTo(Mobile who, Mobile to) + { + if (Utility.RandomBool()) + who.Animate(17, 7, 1, true, false, 0); + else + who.Animate(32 + Utility.Random(3), 7, 1, true, false, 0); + + who.Direction = who.GetDirectionTo(to); + } + + public static int RandomBrightHue() + { + if (Utility.RandomDouble() < 0.1) + return Utility.RandomList(0x62, 0x71); + + return Utility.RandomList(0x03, 0x0D, 0x13, 0x1C, 0x21, 0x30, 0x37, 0x3A, 0x44, 0x59); + } + } + + public class QuestCancelGump : BaseQuestGump + { + private readonly QuestSystem m_System; + + public QuestCancelGump(QuestSystem system) : base(120, 50) + { + m_System = system; + + Closable = false; + + AddPage(0); + + AddImageTiled(0, 0, 348, 262, 2702); + AddAlphaRegion(0, 0, 348, 262); + + AddImage(0, 15, 10152); + AddImageTiled(0, 30, 17, 200, 10151); + AddImage(0, 230, 10154); + + AddImage(15, 0, 10252); + AddImageTiled(30, 0, 300, 17, 10250); + AddImage(315, 0, 10254); + + AddImage(15, 244, 10252); + AddImageTiled(30, 244, 300, 17, 10250); + AddImage(315, 244, 10254); + + AddImage(330, 15, 10152); + AddImageTiled(330, 30, 17, 200, 10151); + AddImage(330, 230, 10154); + + AddImage(333, 2, 10006); + AddImage(333, 248, 10006); + AddImage(2, 248, 10006); + AddImage(2, 2, 10006); + + AddHtmlLocalized(25, 22, 200, 20, 1049000, 32000); // Confirm Quest Cancellation + AddImage(25, 40, 3007); + + if (system.IsTutorial) + { + AddHtmlLocalized( + 25, + 55, + 300, + 120, + 1060836, + White + ); // This quest will give you valuable information, skills and equipment that will help you advance in the game at a quicker pace.

Are you certain you wish to cancel at this time? + } + else + { + AddHtmlLocalized(25, 60, 300, 20, 1049001, White); // You have chosen to abort your quest: + AddImage(25, 81, 0x25E7); + AddHtmlObject(48, 80, 280, 20, system.Name, DarkGreen, false, false); + + AddHtmlLocalized(25, 120, 280, 20, 1049002, White); // Can this quest be restarted after quitting? + AddImage(25, 141, 0x25E7); + AddHtmlLocalized( + 48, + 140, + 280, + 20, + system.RestartDelay < TimeSpan.MaxValue ? 1049016 : 1049017, + DarkGreen + ); // Yes/No + } + + AddRadio(25, 175, 9720, 9723, true, 1); + AddHtmlLocalized(60, 180, 280, 20, 1049005, White); // Yes, I really want to quit! + + AddRadio(25, 210, 9720, 9723, false, 0); + AddHtmlLocalized(60, 215, 280, 20, 1049006, White); // No, I don't want to quit. + + AddButton(265, 220, 247, 248, 1); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 1) + m_System.EndCancelQuest(info.IsSwitched(1)); + } + } + + public class QuestOfferGump : BaseQuestGump + { + private readonly QuestSystem m_System; + + public QuestOfferGump(QuestSystem system) : base(75, 25) + { + m_System = system; + + Closable = false; + + AddPage(0); + + AddImageTiled(50, 20, 400, 400, 2624); + AddAlphaRegion(50, 20, 400, 400); + + AddImage(90, 33, 9005); + AddHtmlLocalized(130, 45, 270, 20, 1049010, White); // Quest Offer + AddImageTiled(130, 65, 175, 1, 9101); + + AddImage(140, 110, 1209); + AddHtmlObject(160, 108, 250, 20, system.Name, DarkGreen, false, false); + + AddHtmlObject(98, 140, 312, 200, system.OfferMessage, LightGreen, false, true); + + AddRadio(85, 350, 9720, 9723, true, 1); + AddHtmlLocalized(120, 356, 280, 20, 1049011, White); // I accept! + + AddRadio(85, 385, 9720, 9723, false, 0); + AddHtmlLocalized(120, 391, 280, 20, 1049012, White); // No thanks, I decline. + + AddButton(340, 390, 247, 248, 1); + + AddImageTiled(50, 29, 30, 390, 10460); + AddImageTiled(34, 140, 17, 279, 9263); + + AddImage(48, 135, 10411); + AddImage(-16, 285, 10402); + AddImage(0, 10, 10421); + AddImage(25, 0, 10420); + + AddImageTiled(83, 15, 350, 15, 10250); + + AddImage(34, 419, 10306); + AddImage(442, 419, 10304); + AddImageTiled(51, 419, 392, 17, 10101); + + AddImageTiled(415, 29, 44, 390, 2605); + AddImageTiled(415, 29, 30, 390, 10460); + AddImage(425, 0, 10441); + + AddImage(370, 50, 1417); + AddImage(379, 60, system.Picture); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 1) + { + if (info.IsSwitched(1)) + m_System.Accept(); + else + m_System.Decline(); + } + } + } + + public abstract class BaseQuestGump : Gump + { + public const int Black = 0x0000; + public const int White = 0x7FFF; + public const int DarkGreen = 10000; + public const int LightGreen = 90000; + public const int Blue = 19777215; + + public BaseQuestGump(int x, int y) : base(x, y) + { + } + + public static int C16232(int c16) + { + c16 &= 0x7FFF; + + var r = ((c16 >> 10) & 0x1F) << 3; + var g = ((c16 >> 05) & 0x1F) << 3; + var b = (c16 & 0x1F) << 3; + + return (r << 16) | (g << 8) | b; + } + + public static int C16216(int c16) => c16 & 0x7FFF; + + public static int C32216(int c32) + { + c32 &= 0xFFFFFF; + + var r = ((c32 >> 16) & 0xFF) >> 3; + var g = ((c32 >> 08) & 0xFF) >> 3; + var b = (c32 & 0xFF) >> 3; + + return (r << 10) | (g << 5) | b; + } + + public static string Color(string text, int color) => $"{text}"; + + public void AddHtmlObject(int x, int y, int width, int height, object message, int color, bool back, bool scroll) + { + if (message is int html) + AddHtmlLocalized(x, y, width, height, html, C16216(color), back, scroll); + else + AddHtml(x, y, width, height, Color(message.ToString(), C16232(color)), back, scroll); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Dark Tides/Conversations.cs b/Projects/UOContent/Engines/Quests/Dark Tides/Conversations.cs index 0837a8483..ed25845a2 100644 --- a/Projects/UOContent/Engines/Quests/Dark Tides/Conversations.cs +++ b/Projects/UOContent/Engines/Quests/Dark Tides/Conversations.cs @@ -1,204 +1,202 @@ -using Server.Items; - -namespace Server.Engines.Quests.Necro -{ - public class AcceptConversation : QuestConversation - { - public override object Message => 1049092; - - public override void OnRead() - { - Container bag = BaseQuester.GetNewContainer(); - - bag.DropItem(new DarkTidesHorn()); - - System.From.AddToBackpack(bag); - - System.AddConversation(new ReanimateMaabusConversation()); - } - } - - public class ReanimateMaabusConversation : QuestConversation - { - private static readonly QuestItemInfo[] m_Info = - { - new QuestItemInfo(1026153, 6178), // teleporter - new QuestItemInfo(1049117, 4036), // Horn of Retreat - new QuestItemInfo(1048032, 3702) // a bag - }; - - public override object Message => 1060099; - - public override QuestItemInfo[] Info => m_Info; - - public override void OnRead() - { - System.AddObjective(new FindMaabusTombObjective()); - } - } - - public class MaabasConversation : QuestConversation - { - private static readonly QuestItemInfo[] m_Info = - { - new QuestItemInfo(1026153, 6178) // teleporter - }; - - public override object Message => 1060103; - - public override QuestItemInfo[] Info => m_Info; - - public override void OnRead() - { - System.AddObjective(new FindCrystalCaveObjective()); - } - } - - public class HorusConversation : QuestConversation - { - public override object Message => 1060105; - - public override void OnRead() - { - System.AddObjective(new FindMardothAboutVaultObjective()); - } - } - - public class MardothVaultConversation : QuestConversation - { - public override object Message => 1060107; - - public override void OnRead() - { - System.AddObjective(new FindCityOfLightObjective()); - } - } - - public class VaultOfSecretsConversation : QuestConversation - { - private static readonly QuestItemInfo[] m_Info = - { - new QuestItemInfo(1023643, 8787) // spellbook - }; - - public override object Message => 1060110; - - public override QuestItemInfo[] Info => m_Info; - - public override void OnRead() - { - System.AddObjective(new FetchAbraxusScrollObjective()); - } - } - - public class ReadAbraxusScrollConversation : QuestConversation - { - public override object Message => 1060114; - - public override void OnRead() - { - System.AddObjective(new ReadAbraxusScrollObjective()); - } - } - - public class SecondHorusConversation : QuestConversation - { - public override object Message => 1060118; - - public override void OnRead() - { - System.AddObjective(new FindCallingScrollObjective()); - } - } - - public class HealConversation : QuestConversation - { - public override object Message => 1061610; - } - - public class HorusRewardConversation : QuestConversation - { - public override object Message => 1060717; - - public override bool Logged => false; - } - - public class LostCallingScrollConversation : QuestConversation - { - private bool m_FromMardoth; - - public LostCallingScrollConversation(bool fromMardoth) => m_FromMardoth = fromMardoth; - - // Serialization - public LostCallingScrollConversation() - { - } - - public override object Message - { - get - { - if (m_FromMardoth) return 1062058; - - /* You have arrived at the well, but no longer have the scroll - * of calling. Use Mardoth's teleporter to return to the - * Crystal Cave and fetch another scroll from the box. - */ - return 1060129; - } - } - - public override bool Logged => false; - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_FromMardoth = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(m_FromMardoth); - } - } - - public class MardothKronusConversation : QuestConversation - { - public override object Message => 1060121; - - public override void OnRead() - { - System.AddObjective(new FindWellOfTearsObjective()); - } - } - - public class MardothEndConversation : QuestConversation - { - public override object Message => 1060133; - - public override void OnRead() - { - System.AddObjective(new FindBankObjective()); - } - } - - public class BankerConversation : QuestConversation - { - public override object Message => 1060137; - - public override void OnRead() - { - System.Complete(); - } - } - - public class RadarConversation : QuestConversation - { - public override object Message => 1061692; - - public override bool Logged => false; - } -} \ No newline at end of file +namespace Server.Engines.Quests.Necro +{ + public class AcceptConversation : QuestConversation + { + public override object Message => 1049092; + + public override void OnRead() + { + var bag = BaseQuester.GetNewContainer(); + + bag.DropItem(new DarkTidesHorn()); + + System.From.AddToBackpack(bag); + + System.AddConversation(new ReanimateMaabusConversation()); + } + } + + public class ReanimateMaabusConversation : QuestConversation + { + private static readonly QuestItemInfo[] m_Info = + { + new QuestItemInfo(1026153, 6178), // teleporter + new QuestItemInfo(1049117, 4036), // Horn of Retreat + new QuestItemInfo(1048032, 3702) // a bag + }; + + public override object Message => 1060099; + + public override QuestItemInfo[] Info => m_Info; + + public override void OnRead() + { + System.AddObjective(new FindMaabusTombObjective()); + } + } + + public class MaabasConversation : QuestConversation + { + private static readonly QuestItemInfo[] m_Info = + { + new QuestItemInfo(1026153, 6178) // teleporter + }; + + public override object Message => 1060103; + + public override QuestItemInfo[] Info => m_Info; + + public override void OnRead() + { + System.AddObjective(new FindCrystalCaveObjective()); + } + } + + public class HorusConversation : QuestConversation + { + public override object Message => 1060105; + + public override void OnRead() + { + System.AddObjective(new FindMardothAboutVaultObjective()); + } + } + + public class MardothVaultConversation : QuestConversation + { + public override object Message => 1060107; + + public override void OnRead() + { + System.AddObjective(new FindCityOfLightObjective()); + } + } + + public class VaultOfSecretsConversation : QuestConversation + { + private static readonly QuestItemInfo[] m_Info = + { + new QuestItemInfo(1023643, 8787) // spellbook + }; + + public override object Message => 1060110; + + public override QuestItemInfo[] Info => m_Info; + + public override void OnRead() + { + System.AddObjective(new FetchAbraxusScrollObjective()); + } + } + + public class ReadAbraxusScrollConversation : QuestConversation + { + public override object Message => 1060114; + + public override void OnRead() + { + System.AddObjective(new ReadAbraxusScrollObjective()); + } + } + + public class SecondHorusConversation : QuestConversation + { + public override object Message => 1060118; + + public override void OnRead() + { + System.AddObjective(new FindCallingScrollObjective()); + } + } + + public class HealConversation : QuestConversation + { + public override object Message => 1061610; + } + + public class HorusRewardConversation : QuestConversation + { + public override object Message => 1060717; + + public override bool Logged => false; + } + + public class LostCallingScrollConversation : QuestConversation + { + private bool m_FromMardoth; + + public LostCallingScrollConversation(bool fromMardoth) => m_FromMardoth = fromMardoth; + + // Serialization + public LostCallingScrollConversation() + { + } + + public override object Message + { + get + { + if (m_FromMardoth) return 1062058; + + /* You have arrived at the well, but no longer have the scroll + * of calling. Use Mardoth's teleporter to return to the + * Crystal Cave and fetch another scroll from the box. + */ + return 1060129; + } + } + + public override bool Logged => false; + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_FromMardoth = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(m_FromMardoth); + } + } + + public class MardothKronusConversation : QuestConversation + { + public override object Message => 1060121; + + public override void OnRead() + { + System.AddObjective(new FindWellOfTearsObjective()); + } + } + + public class MardothEndConversation : QuestConversation + { + public override object Message => 1060133; + + public override void OnRead() + { + System.AddObjective(new FindBankObjective()); + } + } + + public class BankerConversation : QuestConversation + { + public override object Message => 1060137; + + public override void OnRead() + { + System.Complete(); + } + } + + public class RadarConversation : QuestConversation + { + public override object Message => 1061692; + + public override bool Logged => false; + } +} diff --git a/Projects/UOContent/Engines/Quests/Dark Tides/DarkTidesQuest.cs b/Projects/UOContent/Engines/Quests/Dark Tides/DarkTidesQuest.cs index c0bc30dad..0b589780d 100644 --- a/Projects/UOContent/Engines/Quests/Dark Tides/DarkTidesQuest.cs +++ b/Projects/UOContent/Engines/Quests/Dark Tides/DarkTidesQuest.cs @@ -1,98 +1,98 @@ -using System; -using Server.Mobiles; - -namespace Server.Engines.Quests.Necro -{ - public class DarkTidesQuest : QuestSystem - { - private static readonly Type[] m_TypeReferenceTable = - { - typeof(AcceptConversation), - typeof(AnimateMaabusCorpseObjective), - typeof(BankerConversation), - typeof(CashBankCheckObjective), - typeof(FetchAbraxusScrollObjective), - typeof(FindBankObjective), - typeof(FindCallingScrollObjective), - typeof(FindCityOfLightObjective), - typeof(FindCrystalCaveObjective), - typeof(FindMaabusCorpseObjective), - typeof(FindMaabusTombObjective), - typeof(FindMardothAboutKronusObjective), - typeof(FindMardothAboutVaultObjective), - typeof(FindMardothEndObjective), - typeof(FindVaultOfSecretsObjective), - typeof(FindWellOfTearsObjective), - typeof(HorusConversation), - typeof(LostCallingScrollConversation), - typeof(MaabasConversation), - typeof(MardothEndConversation), - typeof(MardothKronusConversation), - typeof(MardothVaultConversation), - typeof(RadarConversation), - typeof(ReadAbraxusScrollConversation), - typeof(ReadAbraxusScrollObjective), - typeof(ReanimateMaabusConversation), - typeof(RetrieveAbraxusScrollObjective), - typeof(ReturnToCrystalCaveObjective), - typeof(SecondHorusConversation), - typeof(SpeakCavePasswordObjective), - typeof(UseCallingScrollObjective), - typeof(VaultOfSecretsConversation), - typeof(FindHorusAboutRewardObjective), - typeof(HealConversation), - typeof(HorusRewardConversation) - }; - - public DarkTidesQuest(PlayerMobile from) : base(from) - { - } - - // Serialization - public DarkTidesQuest() - { - } - - public override Type[] TypeReferenceTable => m_TypeReferenceTable; - - public override object Name => 1060095; - - public override object OfferMessage => 1060094; - - public override TimeSpan RestartDelay => TimeSpan.MaxValue; - public override bool IsTutorial => true; - - public override int Picture => 0x15B5; - - public override void Accept() - { - base.Accept(); - - AddConversation(new AcceptConversation()); - } - - public override bool IgnoreYoungProtection(Mobile from) - { - if (from is SummonedPaladin) - return true; - - return base.IgnoreYoungProtection(from); - } - - public static bool HasLostCallingScroll(Mobile from) - { - if (!(from is PlayerMobile pm)) - return false; - - QuestSystem qs = pm.Quest; - - if (qs is DarkTidesQuest) - if (qs.IsObjectiveInProgress(typeof(FindMardothAboutKronusObjective)) || - qs.IsObjectiveInProgress(typeof(FindWellOfTearsObjective)) || - qs.IsObjectiveInProgress(typeof(UseCallingScrollObjective))) - return from.Backpack?.FindItemByType() == null; - - return false; - } - } -} \ No newline at end of file +using System; +using Server.Mobiles; + +namespace Server.Engines.Quests.Necro +{ + public class DarkTidesQuest : QuestSystem + { + private static readonly Type[] m_TypeReferenceTable = + { + typeof(AcceptConversation), + typeof(AnimateMaabusCorpseObjective), + typeof(BankerConversation), + typeof(CashBankCheckObjective), + typeof(FetchAbraxusScrollObjective), + typeof(FindBankObjective), + typeof(FindCallingScrollObjective), + typeof(FindCityOfLightObjective), + typeof(FindCrystalCaveObjective), + typeof(FindMaabusCorpseObjective), + typeof(FindMaabusTombObjective), + typeof(FindMardothAboutKronusObjective), + typeof(FindMardothAboutVaultObjective), + typeof(FindMardothEndObjective), + typeof(FindVaultOfSecretsObjective), + typeof(FindWellOfTearsObjective), + typeof(HorusConversation), + typeof(LostCallingScrollConversation), + typeof(MaabasConversation), + typeof(MardothEndConversation), + typeof(MardothKronusConversation), + typeof(MardothVaultConversation), + typeof(RadarConversation), + typeof(ReadAbraxusScrollConversation), + typeof(ReadAbraxusScrollObjective), + typeof(ReanimateMaabusConversation), + typeof(RetrieveAbraxusScrollObjective), + typeof(ReturnToCrystalCaveObjective), + typeof(SecondHorusConversation), + typeof(SpeakCavePasswordObjective), + typeof(UseCallingScrollObjective), + typeof(VaultOfSecretsConversation), + typeof(FindHorusAboutRewardObjective), + typeof(HealConversation), + typeof(HorusRewardConversation) + }; + + public DarkTidesQuest(PlayerMobile from) : base(from) + { + } + + // Serialization + public DarkTidesQuest() + { + } + + public override Type[] TypeReferenceTable => m_TypeReferenceTable; + + public override object Name => 1060095; + + public override object OfferMessage => 1060094; + + public override TimeSpan RestartDelay => TimeSpan.MaxValue; + public override bool IsTutorial => true; + + public override int Picture => 0x15B5; + + public override void Accept() + { + base.Accept(); + + AddConversation(new AcceptConversation()); + } + + public override bool IgnoreYoungProtection(Mobile from) + { + if (from is SummonedPaladin) + return true; + + return base.IgnoreYoungProtection(from); + } + + public static bool HasLostCallingScroll(Mobile from) + { + if (!(from is PlayerMobile pm)) + return false; + + var qs = pm.Quest; + + if (qs is DarkTidesQuest) + if (qs.IsObjectiveInProgress(typeof(FindMardothAboutKronusObjective)) || + qs.IsObjectiveInProgress(typeof(FindWellOfTearsObjective)) || + qs.IsObjectiveInProgress(typeof(UseCallingScrollObjective))) + return from.Backpack?.FindItemByType() == null; + + return false; + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Dark Tides/Items/CrystalCaveBarrier.cs b/Projects/UOContent/Engines/Quests/Dark Tides/Items/CrystalCaveBarrier.cs index e4f2fd12a..7df17ff4d 100644 --- a/Projects/UOContent/Engines/Quests/Dark Tides/Items/CrystalCaveBarrier.cs +++ b/Projects/UOContent/Engines/Quests/Dark Tides/Items/CrystalCaveBarrier.cs @@ -1,62 +1,66 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Necro -{ - public class CrystalCaveBarrier : Item - { - [Constructible] - public CrystalCaveBarrier() : base(0x3967) => Movable = false; - - public CrystalCaveBarrier(Serial serial) : base(serial) - { - } - - public override bool OnMoveOver(Mobile m) - { - if (m.AccessLevel > AccessLevel.Player) - return true; - - Mobile mob = m; - - if (m is BaseCreature creature) - mob = creature.ControlMaster; - - if (!(mob is PlayerMobile pm)) - return false; - - QuestSystem qs = pm.Quest; - - if (qs is DarkTidesQuest) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == true) - { - m.SendLocalizedMessage( - 1060648); // With Horus' permission, you are able to pass through the barrier. - - return true; - } - } - - m.SendLocalizedMessage(1060649, "", - 0x66D); // Without the permission of the guardian Horus, the magic of the barrier prevents your passage. - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using Server.Mobiles; + +namespace Server.Engines.Quests.Necro +{ + public class CrystalCaveBarrier : Item + { + [Constructible] + public CrystalCaveBarrier() : base(0x3967) => Movable = false; + + public CrystalCaveBarrier(Serial serial) : base(serial) + { + } + + public override bool OnMoveOver(Mobile m) + { + if (m.AccessLevel > AccessLevel.Player) + return true; + + var mob = m; + + if (m is BaseCreature creature) + mob = creature.ControlMaster; + + if (!(mob is PlayerMobile pm)) + return false; + + var qs = pm.Quest; + + if (qs is DarkTidesQuest) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == true) + { + m.SendLocalizedMessage( + 1060648 + ); // With Horus' permission, you are able to pass through the barrier. + + return true; + } + } + + m.SendLocalizedMessage( + 1060649, + "", + 0x66D + ); // Without the permission of the guardian Horus, the magic of the barrier prevents your passage. + + return 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Dark Tides/Items/DarkTidesHorn.cs b/Projects/UOContent/Engines/Quests/Dark Tides/Items/DarkTidesHorn.cs index 90a8a7eef..3ebd9b9ff 100644 --- a/Projects/UOContent/Engines/Quests/Dark Tides/Items/DarkTidesHorn.cs +++ b/Projects/UOContent/Engines/Quests/Dark Tides/Items/DarkTidesHorn.cs @@ -1,34 +1,34 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Necro -{ - public class DarkTidesHorn : HornOfRetreat - { - [Constructible] - public DarkTidesHorn() - { - DestLoc = new Point3D(2103, 1319, -68); - DestMap = Map.Malas; - } - - public DarkTidesHorn(Serial serial) : base(serial) - { - } - - public override bool ValidateUse(Mobile from) => from is PlayerMobile pm && pm.Quest is DarkTidesQuest; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Necro +{ + public class DarkTidesHorn : HornOfRetreat + { + [Constructible] + public DarkTidesHorn() + { + DestLoc = new Point3D(2103, 1319, -68); + DestMap = Map.Malas; + } + + public DarkTidesHorn(Serial serial) : base(serial) + { + } + + public override bool ValidateUse(Mobile from) => from is PlayerMobile pm && pm.Quest is DarkTidesQuest; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Dark Tides/Items/DarkTidesTeleporter.cs b/Projects/UOContent/Engines/Quests/Dark Tides/Items/DarkTidesTeleporter.cs index f0066afc2..e8cbd59d5 100644 --- a/Projects/UOContent/Engines/Quests/Dark Tides/Items/DarkTidesTeleporter.cs +++ b/Projects/UOContent/Engines/Quests/Dark Tides/Items/DarkTidesTeleporter.cs @@ -1,76 +1,76 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Necro -{ - public class DarkTidesTeleporter : DynamicTeleporter - { - [Constructible] - public DarkTidesTeleporter() - { - } - - public DarkTidesTeleporter(Serial serial) : base(serial) - { - } - - public override bool GetDestination(PlayerMobile player, ref Point3D loc, ref Map map) - { - QuestSystem qs = player.Quest; - - if (qs is DarkTidesQuest) - { - if (qs.IsObjectiveInProgress(typeof(FindMaabusTombObjective))) - { - loc = new Point3D(2038, 1263, -90); - map = Map.Malas; - qs.AddConversation(new RadarConversation()); - return true; - } - - if (qs.IsObjectiveInProgress(typeof(FindCrystalCaveObjective))) - { - loc = new Point3D(1194, 521, -90); - map = Map.Malas; - return true; - } - - if (qs.IsObjectiveInProgress(typeof(FindCityOfLightObjective))) - { - loc = new Point3D(1091, 519, -90); - map = Map.Malas; - return true; - } - - if (qs.IsObjectiveInProgress(typeof(ReturnToCrystalCaveObjective))) - { - loc = new Point3D(1194, 521, -90); - map = Map.Malas; - return true; - } - - if (DarkTidesQuest.HasLostCallingScroll(player)) - { - loc = new Point3D(1194, 521, -90); - map = Map.Malas; - return true; - } - } - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Necro +{ + public class DarkTidesTeleporter : DynamicTeleporter + { + [Constructible] + public DarkTidesTeleporter() + { + } + + public DarkTidesTeleporter(Serial serial) : base(serial) + { + } + + public override bool GetDestination(PlayerMobile player, ref Point3D loc, ref Map map) + { + var qs = player.Quest; + + if (qs is DarkTidesQuest) + { + if (qs.IsObjectiveInProgress(typeof(FindMaabusTombObjective))) + { + loc = new Point3D(2038, 1263, -90); + map = Map.Malas; + qs.AddConversation(new RadarConversation()); + return true; + } + + if (qs.IsObjectiveInProgress(typeof(FindCrystalCaveObjective))) + { + loc = new Point3D(1194, 521, -90); + map = Map.Malas; + return true; + } + + if (qs.IsObjectiveInProgress(typeof(FindCityOfLightObjective))) + { + loc = new Point3D(1091, 519, -90); + map = Map.Malas; + return true; + } + + if (qs.IsObjectiveInProgress(typeof(ReturnToCrystalCaveObjective))) + { + loc = new Point3D(1194, 521, -90); + map = Map.Malas; + return true; + } + + if (DarkTidesQuest.HasLostCallingScroll(player)) + { + loc = new Point3D(1194, 521, -90); + map = Map.Malas; + return true; + } + } + + return 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Dark Tides/Items/KronusScroll.cs b/Projects/UOContent/Engines/Quests/Dark Tides/Items/KronusScroll.cs index ecf6b808e..c1a6e97a7 100644 --- a/Projects/UOContent/Engines/Quests/Dark Tides/Items/KronusScroll.cs +++ b/Projects/UOContent/Engines/Quests/Dark Tides/Items/KronusScroll.cs @@ -1,158 +1,190 @@ -using System; -using Server.Items; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.Quests.Necro -{ - public class KronusScroll : QuestItem - { - private static readonly Rectangle2D m_WellOfTearsArea = new Rectangle2D(2080, 1346, 10, 10); - private static readonly Map m_WellOfTearsMap = Map.Malas; - - [Constructible] - public KronusScroll() : base(0x227A) - { - Weight = 1.0; - Hue = 0x44E; - } - - public KronusScroll(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1060149; // Calling of Kronus - - public override bool CanDrop(PlayerMobile player) => !(player.Quest is DarkTidesQuest); - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from)) - return; - - if (from is PlayerMobile pm) - { - QuestSystem qs = pm.Quest; - - if (qs is DarkTidesQuest) - { - if (qs.IsObjectiveInProgress(typeof(FindMardothAboutKronusObjective))) - { - pm.SendLocalizedMessage(1060151, "", - 0x41); // You read the scroll, but decide against performing the calling until you are instructed to do so by Mardoth. - } - else if (qs.IsObjectiveInProgress(typeof(FindWellOfTearsObjective))) - { - pm.SendLocalizedMessage(1060152, "", - 0x41); // You must be at the Well of Tears in the city of Necromancers to use this scroll. - } - else if (qs.IsObjectiveInProgress(typeof(UseCallingScrollObjective))) - { - if (pm.Map == m_WellOfTearsMap && m_WellOfTearsArea.Contains(pm)) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - obj.Complete(); - - Delete(); - new CallingTimer(pm).Start(); - } - else - { - pm.SendLocalizedMessage(1060152, "", - 0x41); // You must be at the Well of Tears in the city of Necromancers to use this scroll. - } - } - else - { - pm.SendLocalizedMessage(1060150, "", - 0x41); // A strange terror grips your heart as you attempt to read the scroll. You decide it would be a bad idea to read it out loud. - } - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private class CallingTimer : Timer - { - private readonly PlayerMobile m_Player; - private int m_Step; - - public CallingTimer(PlayerMobile player) : base(TimeSpan.Zero, TimeSpan.FromSeconds(1.0), 6) - { - Priority = TimerPriority.TwentyFiveMS; - - m_Player = player; - m_Step = 0; - } - - protected override void OnTick() - { - if (m_Player.Deleted) - { - Stop(); - return; - } - - if (!m_Player.Mounted) - m_Player.Animate(Utility.RandomBool() ? 16 : 17, 7, 1, true, false, 0); - - if (m_Step == 4) - { - int baseX = m_WellOfTearsArea.X; - int baseY = m_WellOfTearsArea.Y; - int width = m_WellOfTearsArea.Width; - int height = m_WellOfTearsArea.Height; - Map map = m_WellOfTearsMap; - - Effects.SendLocationParticles( - EffectItem.Create(m_Player.Location, m_Player.Map, TimeSpan.FromSeconds(1.0)), 0, 0, 0, 0x13C4); - Effects.PlaySound(m_Player.Location, m_Player.Map, 0x243); - - for (int i = 0; i < 15; i++) - { - int x = baseX + Utility.Random(width); - int y = baseY + Utility.Random(height); - int z = map.GetAverageZ(x, y); - - Point3D from = new Point3D(x, y, z + Utility.RandomMinMax(5, 20)); - Point3D to = new Point3D(x, y, z); - - int hue = Utility.RandomList(0x481, 0x482, 0x489, 0x497, 0x66D); - - Effects.SendPacket(from, map, - new HuedEffect(EffectType.Moving, Serial.Zero, Serial.Zero, 0x36D4, from, to, 0, 0, false, true, - hue, 0)); - } - } - - if (m_Step < 5) - { - m_Player.Frozen = true; - } - else // Cast completed - { - m_Player.Frozen = false; - - SummonedPaladin.BeginSummon(m_Player); - } - - m_Step++; - } - } - } -} \ No newline at end of file +using System; +using Server.Items; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.Quests.Necro +{ + public class KronusScroll : QuestItem + { + private static readonly Rectangle2D m_WellOfTearsArea = new Rectangle2D(2080, 1346, 10, 10); + private static readonly Map m_WellOfTearsMap = Map.Malas; + + [Constructible] + public KronusScroll() : base(0x227A) + { + Weight = 1.0; + Hue = 0x44E; + } + + public KronusScroll(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1060149; // Calling of Kronus + + public override bool CanDrop(PlayerMobile player) => !(player.Quest is DarkTidesQuest); + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from)) + return; + + if (from is PlayerMobile pm) + { + var qs = pm.Quest; + + if (qs is DarkTidesQuest) + { + if (qs.IsObjectiveInProgress(typeof(FindMardothAboutKronusObjective))) + { + pm.SendLocalizedMessage( + 1060151, + "", + 0x41 + ); // You read the scroll, but decide against performing the calling until you are instructed to do so by Mardoth. + } + else if (qs.IsObjectiveInProgress(typeof(FindWellOfTearsObjective))) + { + pm.SendLocalizedMessage( + 1060152, + "", + 0x41 + ); // You must be at the Well of Tears in the city of Necromancers to use this scroll. + } + else if (qs.IsObjectiveInProgress(typeof(UseCallingScrollObjective))) + { + if (pm.Map == m_WellOfTearsMap && m_WellOfTearsArea.Contains(pm)) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + obj.Complete(); + + Delete(); + new CallingTimer(pm).Start(); + } + else + { + pm.SendLocalizedMessage( + 1060152, + "", + 0x41 + ); // You must be at the Well of Tears in the city of Necromancers to use this scroll. + } + } + else + { + pm.SendLocalizedMessage( + 1060150, + "", + 0x41 + ); // A strange terror grips your heart as you attempt to read the scroll. You decide it would be a bad idea to read it out loud. + } + } + } + } + + 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(); + } + + private class CallingTimer : Timer + { + private readonly PlayerMobile m_Player; + private int m_Step; + + public CallingTimer(PlayerMobile player) : base(TimeSpan.Zero, TimeSpan.FromSeconds(1.0), 6) + { + Priority = TimerPriority.TwentyFiveMS; + + m_Player = player; + m_Step = 0; + } + + protected override void OnTick() + { + if (m_Player.Deleted) + { + Stop(); + return; + } + + if (!m_Player.Mounted) + m_Player.Animate(Utility.RandomBool() ? 16 : 17, 7, 1, true, false, 0); + + if (m_Step == 4) + { + var baseX = m_WellOfTearsArea.X; + var baseY = m_WellOfTearsArea.Y; + var width = m_WellOfTearsArea.Width; + var height = m_WellOfTearsArea.Height; + var map = m_WellOfTearsMap; + + Effects.SendLocationParticles( + EffectItem.Create(m_Player.Location, m_Player.Map, TimeSpan.FromSeconds(1.0)), + 0, + 0, + 0, + 0x13C4 + ); + Effects.PlaySound(m_Player.Location, m_Player.Map, 0x243); + + for (var i = 0; i < 15; i++) + { + var x = baseX + Utility.Random(width); + var y = baseY + Utility.Random(height); + var z = map.GetAverageZ(x, y); + + var from = new Point3D(x, y, z + Utility.RandomMinMax(5, 20)); + var to = new Point3D(x, y, z); + + var hue = Utility.RandomList(0x481, 0x482, 0x489, 0x497, 0x66D); + + Effects.SendPacket( + from, + map, + new HuedEffect( + EffectType.Moving, + Serial.Zero, + Serial.Zero, + 0x36D4, + from, + to, + 0, + 0, + false, + true, + hue, + 0 + ) + ); + } + } + + if (m_Step < 5) + { + m_Player.Frozen = true; + } + else // Cast completed + { + m_Player.Frozen = false; + + SummonedPaladin.BeginSummon(m_Player); + } + + m_Step++; + } + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Dark Tides/Items/KronusScrollBox.cs b/Projects/UOContent/Engines/Quests/Dark Tides/Items/KronusScrollBox.cs index 71d8eac67..b781affbb 100644 --- a/Projects/UOContent/Engines/Quests/Dark Tides/Items/KronusScrollBox.cs +++ b/Projects/UOContent/Engines/Quests/Dark Tides/Items/KronusScrollBox.cs @@ -1,74 +1,77 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Necro -{ - public class KronusScrollBox : MetalBox - { - [Constructible] - public KronusScrollBox() - { - ItemID = 0xE80; - Movable = false; - - for (int i = 0; i < 40; i++) - { - Item scroll = Loot.RandomScroll(0, 15, SpellbookType.Necromancer); - scroll.Movable = false; - DropItem(scroll); - } - } - - public KronusScrollBox(Serial serial) : base(serial) - { - } - - public override void OnDoubleClick(Mobile from) - { - if (from is PlayerMobile pm && pm.InRange(GetWorldLocation(), 2)) - { - QuestSystem qs = pm.Quest; - - if (qs is DarkTidesQuest) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false || DarkTidesQuest.HasLostCallingScroll(from)) - { - Item scroll = new KronusScroll(); - - if (pm.PlaceInBackpack(scroll)) - { - pm.SendLocalizedMessage(1060120, "", - 0x41); // You rummage through the scrolls until you find the Scroll of Calling. You quickly put it in your pack. - - if (obj?.Completed == false) - obj.Complete(); - } - else - { - pm.SendLocalizedMessage(1060148, "", 0x41); // You were unable to take the scroll. - scroll.Delete(); - } - } - } - } - - base.OnDoubleClick(from); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Necro +{ + public class KronusScrollBox : MetalBox + { + [Constructible] + public KronusScrollBox() + { + ItemID = 0xE80; + Movable = false; + + for (var i = 0; i < 40; i++) + { + Item scroll = Loot.RandomScroll(0, 15, SpellbookType.Necromancer); + scroll.Movable = false; + DropItem(scroll); + } + } + + public KronusScrollBox(Serial serial) : base(serial) + { + } + + public override void OnDoubleClick(Mobile from) + { + if (from is PlayerMobile pm && pm.InRange(GetWorldLocation(), 2)) + { + var qs = pm.Quest; + + if (qs is DarkTidesQuest) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false || DarkTidesQuest.HasLostCallingScroll(from)) + { + Item scroll = new KronusScroll(); + + if (pm.PlaceInBackpack(scroll)) + { + pm.SendLocalizedMessage( + 1060120, + "", + 0x41 + ); // You rummage through the scrolls until you find the Scroll of Calling. You quickly put it in your pack. + + if (obj?.Completed == false) + obj.Complete(); + } + else + { + pm.SendLocalizedMessage(1060148, "", 0x41); // You were unable to take the scroll. + scroll.Delete(); + } + } + } + } + + base.OnDoubleClick(from); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Dark Tides/Items/MaabusCoffin.cs b/Projects/UOContent/Engines/Quests/Dark Tides/Items/MaabusCoffin.cs index 3c2049a63..0fda629fe 100644 --- a/Projects/UOContent/Engines/Quests/Dark Tides/Items/MaabusCoffin.cs +++ b/Projects/UOContent/Engines/Quests/Dark Tides/Items/MaabusCoffin.cs @@ -1,154 +1,159 @@ -using System; -using Server.Items; - -namespace Server.Engines.Quests.Necro -{ - public class MaabusCoffin : BaseAddon - { - [Constructible] - public MaabusCoffin() - { - AddComponent(new MaabusCoffinComponent(0x1C2B, 0x1C2B), -1, -1, 0); - - AddComponent(new MaabusCoffinComponent(0x1D16, 0x1C2C), 0, -1, 0); - AddComponent(new MaabusCoffinComponent(0x1D17, 0x1C2D), 1, -1, 0); - AddComponent(new MaabusCoffinComponent(0x1D51, 0x1C2E), 2, -1, 0); - - AddComponent(new MaabusCoffinComponent(0x1D4E, 0x1C2A), 0, 0, 0); - AddComponent(new MaabusCoffinComponent(0x1D4D, 0x1C29), 1, 0, 0); - AddComponent(new MaabusCoffinComponent(0x1D4C, 0x1C28), 2, 0, 0); - } - - public MaabusCoffin(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public Maabus Maabus { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D SpawnLocation { get; set; } - - public void Awake(Mobile caller) - { - if (Maabus != null || SpawnLocation == Point3D.Zero) - return; - - foreach (AddonComponent c in Components) - (c as MaabusCoffinComponent)?.TurnToEmpty(); - - Maabus = new Maabus { Location = SpawnLocation, Map = Map }; - Maabus.Direction = Maabus.GetDirectionTo(caller); - - Timer.DelayCall(TimeSpan.FromSeconds(7.5), BeginSleep); - } - - public void BeginSleep() - { - if (Maabus == null) - return; - - Effects.PlaySound(Maabus.Location, Maabus.Map, 0x48E); - - Timer.DelayCall(TimeSpan.FromSeconds(2.5), Sleep); - } - - public void Sleep() - { - if (Maabus == null) - return; - - Effects.SendLocationParticles(EffectItem.Create(Maabus.Location, Maabus.Map, EffectItem.DefaultDuration), 0x3728, - 10, 10, 0x7E7); - Effects.PlaySound(Maabus.Location, Maabus.Map, 0x1FE); - - Maabus.Delete(); - Maabus = null; - - foreach (MaabusCoffinComponent c in Components) - c.TurnToFull(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(Maabus); - writer.Write(SpawnLocation); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Maabus = reader.ReadMobile() as Maabus; - SpawnLocation = reader.ReadPoint3D(); - - Sleep(); - } - } - - public class MaabusCoffinComponent : AddonComponent - { - private int m_EmptyItemID; - private int m_FullItemID; - - public MaabusCoffinComponent(int itemID) : this(itemID, itemID) - { - } - - public MaabusCoffinComponent(int fullItemID, int emptyItemID) : base(fullItemID) - { - m_FullItemID = fullItemID; - m_EmptyItemID = emptyItemID; - } - - public MaabusCoffinComponent(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D SpawnLocation - { - get => Addon is MaabusCoffin coffin ? coffin.SpawnLocation : Point3D.Zero; - set - { - if (Addon is MaabusCoffin coffin) coffin.SpawnLocation = value; - } - } - - public void TurnToEmpty() - { - ItemID = m_EmptyItemID; - } - - public void TurnToFull() - { - ItemID = m_FullItemID; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_FullItemID); - writer.Write(m_EmptyItemID); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_FullItemID = reader.ReadInt(); - m_EmptyItemID = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; +using Server.Items; + +namespace Server.Engines.Quests.Necro +{ + public class MaabusCoffin : BaseAddon + { + [Constructible] + public MaabusCoffin() + { + AddComponent(new MaabusCoffinComponent(0x1C2B, 0x1C2B), -1, -1, 0); + + AddComponent(new MaabusCoffinComponent(0x1D16, 0x1C2C), 0, -1, 0); + AddComponent(new MaabusCoffinComponent(0x1D17, 0x1C2D), 1, -1, 0); + AddComponent(new MaabusCoffinComponent(0x1D51, 0x1C2E), 2, -1, 0); + + AddComponent(new MaabusCoffinComponent(0x1D4E, 0x1C2A), 0, 0, 0); + AddComponent(new MaabusCoffinComponent(0x1D4D, 0x1C29), 1, 0, 0); + AddComponent(new MaabusCoffinComponent(0x1D4C, 0x1C28), 2, 0, 0); + } + + public MaabusCoffin(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public Maabus Maabus { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D SpawnLocation { get; set; } + + public void Awake(Mobile caller) + { + if (Maabus != null || SpawnLocation == Point3D.Zero) + return; + + foreach (var c in Components) + (c as MaabusCoffinComponent)?.TurnToEmpty(); + + Maabus = new Maabus { Location = SpawnLocation, Map = Map }; + Maabus.Direction = Maabus.GetDirectionTo(caller); + + Timer.DelayCall(TimeSpan.FromSeconds(7.5), BeginSleep); + } + + public void BeginSleep() + { + if (Maabus == null) + return; + + Effects.PlaySound(Maabus.Location, Maabus.Map, 0x48E); + + Timer.DelayCall(TimeSpan.FromSeconds(2.5), Sleep); + } + + public void Sleep() + { + if (Maabus == null) + return; + + Effects.SendLocationParticles( + EffectItem.Create(Maabus.Location, Maabus.Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 0x7E7 + ); + Effects.PlaySound(Maabus.Location, Maabus.Map, 0x1FE); + + Maabus.Delete(); + Maabus = null; + + foreach (MaabusCoffinComponent c in Components) + c.TurnToFull(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(Maabus); + writer.Write(SpawnLocation); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + Maabus = reader.ReadMobile() as Maabus; + SpawnLocation = reader.ReadPoint3D(); + + Sleep(); + } + } + + public class MaabusCoffinComponent : AddonComponent + { + private int m_EmptyItemID; + private int m_FullItemID; + + public MaabusCoffinComponent(int itemID) : this(itemID, itemID) + { + } + + public MaabusCoffinComponent(int fullItemID, int emptyItemID) : base(fullItemID) + { + m_FullItemID = fullItemID; + m_EmptyItemID = emptyItemID; + } + + public MaabusCoffinComponent(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D SpawnLocation + { + get => Addon is MaabusCoffin coffin ? coffin.SpawnLocation : Point3D.Zero; + set + { + if (Addon is MaabusCoffin coffin) coffin.SpawnLocation = value; + } + } + + public void TurnToEmpty() + { + ItemID = m_EmptyItemID; + } + + public void TurnToFull() + { + ItemID = m_FullItemID; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_FullItemID); + writer.Write(m_EmptyItemID); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_FullItemID = reader.ReadInt(); + m_EmptyItemID = reader.ReadInt(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Dark Tides/Items/ScrollOfAbraxus.cs b/Projects/UOContent/Engines/Quests/Dark Tides/Items/ScrollOfAbraxus.cs index cfab36807..0e83beeac 100644 --- a/Projects/UOContent/Engines/Quests/Dark Tides/Items/ScrollOfAbraxus.cs +++ b/Projects/UOContent/Engines/Quests/Dark Tides/Items/ScrollOfAbraxus.cs @@ -1,125 +1,125 @@ -using Server.Gumps; -using Server.Mobiles; - -namespace Server.Engines.Quests.Necro -{ - public class ScrollOfAbraxus : QuestItem - { - [Constructible] - public ScrollOfAbraxus() : base(0x227B) => Weight = 1.0; - - public ScrollOfAbraxus(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1028827; // Scroll of Abraxus - - public override bool CanDrop(PlayerMobile player) => !(player.Quest is DarkTidesQuest); - - public override void OnAdded(IEntity parent) - { - base.OnAdded(parent); - - if (RootParent is PlayerMobile pm) - { - QuestSystem qs = pm.Quest; - - if (qs is DarkTidesQuest) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - obj.Complete(); - } - } - } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - from.SendGump(new ScrollOfAbraxusGump()); - - if (from is PlayerMobile pm) - { - QuestSystem qs = pm.Quest; - - if (qs is DarkTidesQuest) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - obj.Complete(); - } - } - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class ScrollOfAbraxusGump : Gump - { - public ScrollOfAbraxusGump() : base(150, 50) - { - AddPage(0); - - AddImage(0, 0, 1228); - AddImage(340, 255, 9005); - - /* Security at the Crystal Cave

- * - * We have taken great measuresto ensure the safety of the - * Scroll of Calling, which we have so valiantly taken from - * the Necromancer Maabus during the battle of the wood - * nearly 200 years ago.

- * - * The scroll must never fall into the hands of the - * Necromancers again, lest they use it to summon the ancient - * daemon Kronus. The scroll of calling is a necessity in the - * series of dark rites the Necromancers must perform to once again - * re-awaken Kronus.

- * - * Should Kronus ever rise again, the days of the Paladins, and - * indeed humanity as we know it will be numbered.

- * - * For this reason, we have posted the honorable Horus, former - * General of the Northern Legions to guard the entrance of the - * Crystal Cave where we keep the Scroll of Calling. Horus was - * infused with magical life from the tree Urywen during his last - * battle. The power gave him eternal life, but it also, - * unfortunately, took his eye sight.

- * - * Since Horus cannot see those he admits to the Crystal Cave, - * he will only allow those that know the secret password to enter. - * Speak the following word to Horus and he shall grant you passage - * to the Crystal Cave:

- * - * Urywen

- * - * Do not speak this password anywhere except when seeking passage - * into the Crystal Cave, as our adversaries are lurking in the - * shadows � they are everywhere.

Go with the light, friend.

- * - * - Frater Melkeer - */ - AddHtmlLocalized(25, 36, 350, 210, 1060116, 1, false, true); - } - } -} \ No newline at end of file +using Server.Gumps; +using Server.Mobiles; + +namespace Server.Engines.Quests.Necro +{ + public class ScrollOfAbraxus : QuestItem + { + [Constructible] + public ScrollOfAbraxus() : base(0x227B) => Weight = 1.0; + + public ScrollOfAbraxus(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1028827; // Scroll of Abraxus + + public override bool CanDrop(PlayerMobile player) => !(player.Quest is DarkTidesQuest); + + public override void OnAdded(IEntity parent) + { + base.OnAdded(parent); + + if (RootParent is PlayerMobile pm) + { + var qs = pm.Quest; + + if (qs is DarkTidesQuest) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + obj.Complete(); + } + } + } + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + from.SendGump(new ScrollOfAbraxusGump()); + + if (from is PlayerMobile pm) + { + var qs = pm.Quest; + + if (qs is DarkTidesQuest) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + obj.Complete(); + } + } + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + + 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 class ScrollOfAbraxusGump : Gump + { + public ScrollOfAbraxusGump() : base(150, 50) + { + AddPage(0); + + AddImage(0, 0, 1228); + AddImage(340, 255, 9005); + + /* Security at the Crystal Cave

+ * + * We have taken great measuresto ensure the safety of the + * Scroll of Calling, which we have so valiantly taken from + * the Necromancer Maabus during the battle of the wood + * nearly 200 years ago.

+ * + * The scroll must never fall into the hands of the + * Necromancers again, lest they use it to summon the ancient + * daemon Kronus. The scroll of calling is a necessity in the + * series of dark rites the Necromancers must perform to once again + * re-awaken Kronus.

+ * + * Should Kronus ever rise again, the days of the Paladins, and + * indeed humanity as we know it will be numbered.

+ * + * For this reason, we have posted the honorable Horus, former + * General of the Northern Legions to guard the entrance of the + * Crystal Cave where we keep the Scroll of Calling. Horus was + * infused with magical life from the tree Urywen during his last + * battle. The power gave him eternal life, but it also, + * unfortunately, took his eye sight.

+ * + * Since Horus cannot see those he admits to the Crystal Cave, + * he will only allow those that know the secret password to enter. + * Speak the following word to Horus and he shall grant you passage + * to the Crystal Cave:

+ * + * Urywen

+ * + * Do not speak this password anywhere except when seeking passage + * into the Crystal Cave, as our adversaries are lurking in the + * shadows � they are everywhere.

Go with the light, friend.

+ * + * - Frater Melkeer + */ + AddHtmlLocalized(25, 36, 350, 210, 1060116, 1, false, true); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Dark Tides/Items/VaultOfSecretsBarrier.cs b/Projects/UOContent/Engines/Quests/Dark Tides/Items/VaultOfSecretsBarrier.cs index 81cbfd912..5d068719c 100644 --- a/Projects/UOContent/Engines/Quests/Dark Tides/Items/VaultOfSecretsBarrier.cs +++ b/Projects/UOContent/Engines/Quests/Dark Tides/Items/VaultOfSecretsBarrier.cs @@ -1,46 +1,46 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Necro -{ - public class VaultOfSecretsBarrier : Item - { - [Constructible] - public VaultOfSecretsBarrier() : base(0x49E) - { - Movable = false; - Visible = false; - } - - public VaultOfSecretsBarrier(Serial serial) : base(serial) - { - } - - public override bool OnMoveOver(Mobile m) - { - if (m.AccessLevel > AccessLevel.Player) - return true; - - if (m is PlayerMobile pm && pm.Profession == 4) - { - m.SendLocalizedMessage(1060188, "", 0x24); // The wicked may not enter! - return false; - } - - return base.OnMoveOver(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Necro +{ + public class VaultOfSecretsBarrier : Item + { + [Constructible] + public VaultOfSecretsBarrier() : base(0x49E) + { + Movable = false; + Visible = false; + } + + public VaultOfSecretsBarrier(Serial serial) : base(serial) + { + } + + public override bool OnMoveOver(Mobile m) + { + if (m.AccessLevel > AccessLevel.Player) + return true; + + if (m is PlayerMobile pm && pm.Profession == 4) + { + m.SendLocalizedMessage(1060188, "", 0x24); // The wicked may not enter! + return false; + } + + return base.OnMoveOver(m); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Dark Tides/Mobiles/Horus.cs b/Projects/UOContent/Engines/Quests/Dark Tides/Mobiles/Horus.cs index 978587747..4602e7acd 100644 --- a/Projects/UOContent/Engines/Quests/Dark Tides/Mobiles/Horus.cs +++ b/Projects/UOContent/Engines/Quests/Dark Tides/Mobiles/Horus.cs @@ -1,188 +1,189 @@ -using System.Collections.Generic; -using Server.ContextMenus; -using Server.Items; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.Quests.Necro -{ - public class Horus : BaseQuester - { - [Constructible] - public Horus() : base("the Guardian") - { - } - - public Horus(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Horus"; - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = 0x83F3; - Body = 0x190; - } - - public override void InitOutfit() - { - AddItem(SetHue(new PlateLegs(), 0x849)); - AddItem(SetHue(new PlateChest(), 0x849)); - AddItem(SetHue(new PlateArms(), 0x849)); - AddItem(SetHue(new PlateGloves(), 0x849)); - AddItem(SetHue(new PlateGorget(), 0x849)); - - AddItem(SetHue(new Bardiche(), 0x482)); - - AddItem(SetHue(new Boots(), 0x001)); - AddItem(SetHue(new Cloak(), 0x482)); - - Utility.AssignRandomHair(this, false); - Utility.AssignRandomFacialHair(this, false); - } - - public override int GetAutoTalkRange(PlayerMobile m) => 3; - - public override bool CanTalkTo(PlayerMobile to) - { - QuestSystem qs = to.Quest; - - return qs is DarkTidesQuest && qs.IsObjectiveInProgress(typeof(FindCrystalCaveObjective)); - } - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - QuestSystem qs = player.Quest; - - if (qs is DarkTidesQuest) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - obj.Complete(); - } - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - base.OnMovement(m, oldLocation); - - if (InRange(m.Location, 2) && !InRange(oldLocation, 2) && m is PlayerMobile pm) - { - QuestSystem qs = pm.Quest; - - if (qs is DarkTidesQuest) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - obj.Complete(); - } - else - { - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - Container cont = GetNewContainer(); - - cont.DropItem(new Gold(500)); - - BaseJewel jewel = new GoldBracelet(); - if (Core.AOS) - BaseRunicTool.ApplyAttributesTo(jewel, 3, 20, 40); - cont.DropItem(jewel); - - if (!pm.PlaceInBackpack(cont)) - { - cont.Delete(); - pm.SendLocalizedMessage( - 1046260); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. - } - else - { - obj.Complete(); - } - } - } - } - } - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (from.Alive) - if (from is PlayerMobile pm) - { - QuestSystem qs = pm.Quest; - - if (qs is DarkTidesQuest) - { - QuestObjective obj = qs.FindObjective(); - bool enabled = obj?.Completed == false; - - list.Add(new SpeakPasswordEntry(this, pm, enabled)); - } - } - } - - public virtual void OnPasswordSpoken(PlayerMobile from) - { - QuestSystem qs = from.Quest; - - if (qs is DarkTidesQuest) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - obj.Complete(); - return; - } - } - - from.SendLocalizedMessage(1060185); // Horus ignores you. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private class SpeakPasswordEntry : ContextMenuEntry - { - private readonly PlayerMobile m_From; - private readonly Horus m_Horus; - - public SpeakPasswordEntry(Horus horus, PlayerMobile from, bool enabled) : base(6193, 3) - { - m_Horus = horus; - m_From = from; - - if (!enabled) - Flags |= CMEFlags.Disabled; - } - - public override void OnClick() - { - if (m_From.Alive) - m_Horus.OnPasswordSpoken(m_From); - } - } - } -} \ No newline at end of file +using System.Collections.Generic; +using Server.ContextMenus; +using Server.Items; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.Quests.Necro +{ + public class Horus : BaseQuester + { + [Constructible] + public Horus() : base("the Guardian") + { + } + + public Horus(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Horus"; + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = 0x83F3; + Body = 0x190; + } + + public override void InitOutfit() + { + AddItem(SetHue(new PlateLegs(), 0x849)); + AddItem(SetHue(new PlateChest(), 0x849)); + AddItem(SetHue(new PlateArms(), 0x849)); + AddItem(SetHue(new PlateGloves(), 0x849)); + AddItem(SetHue(new PlateGorget(), 0x849)); + + AddItem(SetHue(new Bardiche(), 0x482)); + + AddItem(SetHue(new Boots(), 0x001)); + AddItem(SetHue(new Cloak(), 0x482)); + + Utility.AssignRandomHair(this, false); + Utility.AssignRandomFacialHair(this, false); + } + + public override int GetAutoTalkRange(PlayerMobile m) => 3; + + public override bool CanTalkTo(PlayerMobile to) + { + var qs = to.Quest; + + return qs is DarkTidesQuest && qs.IsObjectiveInProgress(typeof(FindCrystalCaveObjective)); + } + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + var qs = player.Quest; + + if (qs is DarkTidesQuest) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + obj.Complete(); + } + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + base.OnMovement(m, oldLocation); + + if (InRange(m.Location, 2) && !InRange(oldLocation, 2) && m is PlayerMobile pm) + { + var qs = pm.Quest; + + if (qs is DarkTidesQuest) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + obj.Complete(); + } + else + { + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + var cont = GetNewContainer(); + + cont.DropItem(new Gold(500)); + + BaseJewel jewel = new GoldBracelet(); + if (Core.AOS) + BaseRunicTool.ApplyAttributesTo(jewel, 3, 20, 40); + cont.DropItem(jewel); + + if (!pm.PlaceInBackpack(cont)) + { + cont.Delete(); + pm.SendLocalizedMessage( + 1046260 + ); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. + } + else + { + obj.Complete(); + } + } + } + } + } + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (from.Alive) + if (from is PlayerMobile pm) + { + var qs = pm.Quest; + + if (qs is DarkTidesQuest) + { + QuestObjective obj = qs.FindObjective(); + var enabled = obj?.Completed == false; + + list.Add(new SpeakPasswordEntry(this, pm, enabled)); + } + } + } + + public virtual void OnPasswordSpoken(PlayerMobile from) + { + var qs = from.Quest; + + if (qs is DarkTidesQuest) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + obj.Complete(); + return; + } + } + + from.SendLocalizedMessage(1060185); // Horus ignores you. + } + + 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(); + } + + private class SpeakPasswordEntry : ContextMenuEntry + { + private readonly PlayerMobile m_From; + private readonly Horus m_Horus; + + public SpeakPasswordEntry(Horus horus, PlayerMobile from, bool enabled) : base(6193, 3) + { + m_Horus = horus; + m_From = from; + + if (!enabled) + Flags |= CMEFlags.Disabled; + } + + public override void OnClick() + { + if (m_From.Alive) + m_Horus.OnPasswordSpoken(m_From); + } + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Dark Tides/Mobiles/Maabus.cs b/Projects/UOContent/Engines/Quests/Dark Tides/Mobiles/Maabus.cs index ee30bfa78..170ff5894 100644 --- a/Projects/UOContent/Engines/Quests/Dark Tides/Mobiles/Maabus.cs +++ b/Projects/UOContent/Engines/Quests/Dark Tides/Mobiles/Maabus.cs @@ -1,42 +1,42 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Necro -{ - public class Maabus : BaseQuester - { - public Maabus() - { - } - - public Maabus(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Maabus"; - - public override void InitBody() - { - Body = 0x94; - } - - public override bool CanTalkTo(PlayerMobile to) => false; - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Necro +{ + public class Maabus : BaseQuester + { + public Maabus() + { + } + + public Maabus(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Maabus"; + + public override void InitBody() + { + Body = 0x94; + } + + public override bool CanTalkTo(PlayerMobile to) => false; + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Dark Tides/Mobiles/Mardoth.cs b/Projects/UOContent/Engines/Quests/Dark Tides/Mobiles/Mardoth.cs index 70a945c75..9c90a6d93 100644 --- a/Projects/UOContent/Engines/Quests/Dark Tides/Mobiles/Mardoth.cs +++ b/Projects/UOContent/Engines/Quests/Dark Tides/Mobiles/Mardoth.cs @@ -1,216 +1,217 @@ -using Server.Gumps; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Necro -{ - public class Mardoth : BaseQuester - { - [Constructible] - public Mardoth() : base("the Ancient Necromancer") - { - } - - public Mardoth(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Mardoth"; - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = 0x8849; - Body = 0x190; - } - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (from is PlayerMobile player) - { - QuestSystem qs = player.Quest; - - if (qs is DarkTidesQuest) - if (dropped is DarkTidesHorn horn) - { - if (player.Young) - { - if (horn.Charges < 10) - { - SayTo(from, 1049384); // I have recharged the item for you. - horn.Charges = 10; - } - else - { - SayTo(from, 1049385); // That doesn't need recharging yet. - } - } - else - { - player.SendLocalizedMessage(1114333); // You must be young to have this item recharged. - } - - return false; - } - } - - return base.OnDragDrop(from, dropped); - } - - public override void InitOutfit() - { - AddItem(new Sandals(0x1)); - AddItem(new Robe(0x66D)); - AddItem(new BlackStaff()); - AddItem(new WizardsHat(0x1)); - - FacialHairItemID = 0x2041; - FacialHairHue = 0x482; - - HairItemID = 0x203C; - HairHue = 0x482; - - Item gloves = new BoneGloves(); - gloves.Hue = 0x66D; - AddItem(gloves); - - Item gorget = new PlateGorget(); - gorget.Hue = 0x1; - AddItem(gorget); - } - - public override int GetAutoTalkRange(PlayerMobile m) => 3; - - public override bool CanTalkTo(PlayerMobile to) - { - if (!(to.Quest is DarkTidesQuest qs)) - return to.Quest == null && QuestSystem.CanOfferQuest(to, typeof(DarkTidesQuest)); - - return qs.FindObjective() != null; - } - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - QuestSystem qs = player.Quest; - - if (qs is DarkTidesQuest) - { - if (DarkTidesQuest.HasLostCallingScroll(player)) - { - qs.AddConversation(new LostCallingScrollConversation(true)); - } - else - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - obj.Complete(); - } - else - { - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - obj.Complete(); - } - else - { - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - Container cont = GetNewContainer(); - - cont.DropItem(new PigIron(20)); - cont.DropItem(new NoxCrystal(20)); - cont.DropItem(new BatWing(25)); - cont.DropItem(new DaemonBlood(20)); - cont.DropItem(new GraveDust(20)); - - BaseWeapon weapon = new BoneHarvester(); - - weapon.Slayer = SlayerName.OrcSlaying; - - if (Core.AOS) - { - BaseRunicTool.ApplyAttributesTo(weapon, 3, 20, 40); - } - else - { - weapon.DamageLevel = (WeaponDamageLevel)RandomMinMaxScaled(2, 4); - weapon.AccuracyLevel = (WeaponAccuracyLevel)RandomMinMaxScaled(2, 4); - weapon.DurabilityLevel = (WeaponDurabilityLevel)RandomMinMaxScaled(2, 4); - } - - cont.DropItem(weapon); - - cont.DropItem(new BankCheck(2000)); - cont.DropItem(new EnchantedSextant()); - - if (!player.PlaceInBackpack(cont)) - { - cont.Delete(); - player.SendLocalizedMessage( - 1046260); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. - } - else - { - obj.Complete(); - } - } - else if (contextMenu) - { - FocusTo(player); - player.SendLocalizedMessage(1061821); // Mardoth has nothing more for you at this time. - } - } - } - } - } - else if (qs == null && QuestSystem.CanOfferQuest(player, typeof(DarkTidesQuest))) - { - new DarkTidesQuest(player).SendOffer(); - } - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - base.OnMovement(m, oldLocation); - - if (m is PlayerMobile && !m.Frozen && !m.Alive && InRange(m, 4) && !InRange(oldLocation, 4) && InLOS(m)) - { - if (m.Map?.CanFit(m.Location, 16, false, false) != true) - { - m.SendLocalizedMessage(502391); // Thou can not be resurrected there! - } - else - { - Direction = GetDirectionTo(m); - - m.PlaySound(0x214); - m.FixedEffect(0x376A, 10, 16); - - m.CloseGump(); - m.SendGump(new ResurrectGump(m, ResurrectMessage.Healer)); - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Gumps; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Necro +{ + public class Mardoth : BaseQuester + { + [Constructible] + public Mardoth() : base("the Ancient Necromancer") + { + } + + public Mardoth(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Mardoth"; + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = 0x8849; + Body = 0x190; + } + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (from is PlayerMobile player) + { + var qs = player.Quest; + + if (qs is DarkTidesQuest) + if (dropped is DarkTidesHorn horn) + { + if (player.Young) + { + if (horn.Charges < 10) + { + SayTo(from, 1049384); // I have recharged the item for you. + horn.Charges = 10; + } + else + { + SayTo(from, 1049385); // That doesn't need recharging yet. + } + } + else + { + player.SendLocalizedMessage(1114333); // You must be young to have this item recharged. + } + + return false; + } + } + + return base.OnDragDrop(from, dropped); + } + + public override void InitOutfit() + { + AddItem(new Sandals(0x1)); + AddItem(new Robe(0x66D)); + AddItem(new BlackStaff()); + AddItem(new WizardsHat(0x1)); + + FacialHairItemID = 0x2041; + FacialHairHue = 0x482; + + HairItemID = 0x203C; + HairHue = 0x482; + + Item gloves = new BoneGloves(); + gloves.Hue = 0x66D; + AddItem(gloves); + + Item gorget = new PlateGorget(); + gorget.Hue = 0x1; + AddItem(gorget); + } + + public override int GetAutoTalkRange(PlayerMobile m) => 3; + + public override bool CanTalkTo(PlayerMobile to) + { + if (!(to.Quest is DarkTidesQuest qs)) + return to.Quest == null && QuestSystem.CanOfferQuest(to, typeof(DarkTidesQuest)); + + return qs.FindObjective() != null; + } + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + var qs = player.Quest; + + if (qs is DarkTidesQuest) + { + if (DarkTidesQuest.HasLostCallingScroll(player)) + { + qs.AddConversation(new LostCallingScrollConversation(true)); + } + else + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + obj.Complete(); + } + else + { + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + obj.Complete(); + } + else + { + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + var cont = GetNewContainer(); + + cont.DropItem(new PigIron(20)); + cont.DropItem(new NoxCrystal(20)); + cont.DropItem(new BatWing(25)); + cont.DropItem(new DaemonBlood(20)); + cont.DropItem(new GraveDust(20)); + + BaseWeapon weapon = new BoneHarvester(); + + weapon.Slayer = SlayerName.OrcSlaying; + + if (Core.AOS) + { + BaseRunicTool.ApplyAttributesTo(weapon, 3, 20, 40); + } + else + { + weapon.DamageLevel = (WeaponDamageLevel)RandomMinMaxScaled(2, 4); + weapon.AccuracyLevel = (WeaponAccuracyLevel)RandomMinMaxScaled(2, 4); + weapon.DurabilityLevel = (WeaponDurabilityLevel)RandomMinMaxScaled(2, 4); + } + + cont.DropItem(weapon); + + cont.DropItem(new BankCheck(2000)); + cont.DropItem(new EnchantedSextant()); + + if (!player.PlaceInBackpack(cont)) + { + cont.Delete(); + player.SendLocalizedMessage( + 1046260 + ); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. + } + else + { + obj.Complete(); + } + } + else if (contextMenu) + { + FocusTo(player); + player.SendLocalizedMessage(1061821); // Mardoth has nothing more for you at this time. + } + } + } + } + } + else if (qs == null && QuestSystem.CanOfferQuest(player, typeof(DarkTidesQuest))) + { + new DarkTidesQuest(player).SendOffer(); + } + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + base.OnMovement(m, oldLocation); + + if (m is PlayerMobile && !m.Frozen && !m.Alive && InRange(m, 4) && !InRange(oldLocation, 4) && InLOS(m)) + { + if (m.Map?.CanFit(m.Location, 16, false, false) != true) + { + m.SendLocalizedMessage(502391); // Thou can not be resurrected there! + } + else + { + Direction = GetDirectionTo(m); + + m.PlaySound(0x214); + m.FixedEffect(0x376A, 10, 16); + + m.CloseGump(); + m.SendGump(new ResurrectGump(m, ResurrectMessage.Healer)); + } + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Dark Tides/Mobiles/SummonedPaladin.cs b/Projects/UOContent/Engines/Quests/Dark Tides/Mobiles/SummonedPaladin.cs index 8f0de24a2..cabc0e380 100644 --- a/Projects/UOContent/Engines/Quests/Dark Tides/Mobiles/SummonedPaladin.cs +++ b/Projects/UOContent/Engines/Quests/Dark Tides/Mobiles/SummonedPaladin.cs @@ -1,243 +1,252 @@ -using System; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Necro -{ - public class SummonedPaladin : BaseCreature - { - private PlayerMobile m_Necromancer; - private bool m_ToDelete; - - public SummonedPaladin(PlayerMobile necromancer) : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) - { - m_Necromancer = necromancer; - - InitStats(45, 30, 5); - Title = "the Paladin"; - - Hue = 0x83F3; - - Female = false; - Body = 0x190; - Name = NameList.RandomName("male"); - - Utility.AssignRandomHair(this); - Utility.AssignRandomFacialHair(this, false); - - FacialHairHue = HairHue; - - AddItem(new Boots(0x1)); - AddItem(new ChainChest()); - AddItem(new ChainLegs()); - AddItem(new RingmailArms()); - AddItem(new PlateHelm()); - AddItem(new PlateGloves()); - AddItem(new PlateGorget()); - - AddItem(new Cloak(0xCF)); - - AddItem(new ThinLongsword()); - - SetSkill(SkillName.Swords, 50.0); - SetSkill(SkillName.Tactics, 50.0); - - PackGold(500); - } - - public SummonedPaladin(Serial serial) : base(serial) - { - } - - public override bool ClickTitle => false; - - public override bool PlayerRangeSensitive => false; - - public override bool IsHarmfulCriminal(Mobile target) - { - if (target == m_Necromancer) - return false; - - return base.IsHarmfulCriminal(target); - } - - public override void OnThink() - { - if (!m_ToDelete && !Frozen) - { - if (m_Necromancer?.Deleted != false || m_Necromancer.Map == Map.Internal) - { - Delete(); - return; - } - - if (Combatant != m_Necromancer) - Combatant = m_Necromancer; - - if (!m_Necromancer.Alive) - { - QuestSystem qs = m_Necromancer.Quest; - - if (qs is DarkTidesQuest && qs.FindObjective() == null) - qs.AddObjective(new FindMardothEndObjective(false)); - - Say(1060139, m_Necromancer.Name); // You have made my work easy for me, ~1_NAME~. My task here is done. - - m_ToDelete = true; - - Timer.DelayCall(TimeSpan.FromSeconds(5.0), Delete); - } - else if (m_Necromancer.Map != Map || GetDistanceToSqrt(m_Necromancer) > RangePerception + 1) - { - Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x3728, 10, - 10, 2023); - Effects.SendLocationParticles( - EffectItem.Create(m_Necromancer.Location, m_Necromancer.Map, EffectItem.DefaultDuration), 0x3728, 10, - 10, 5023); - - Map = m_Necromancer.Map; - Location = m_Necromancer.Location; - - PlaySound(0x1FE); - - Say(1060140); // You cannot escape me, knave of evil! - } - } - - base.OnThink(); - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - QuestSystem qs = m_Necromancer.Quest; - - if (qs is DarkTidesQuest && qs.FindObjective() == null) - qs.AddObjective(new FindMardothEndObjective(true)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Necromancer); - writer.Write(m_ToDelete); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Necromancer = reader.ReadMobile() as PlayerMobile; - m_ToDelete = reader.ReadBool(); - - if (m_ToDelete) - Delete(); - } - - public static void BeginSummon(PlayerMobile player) - { - new SummonTimer(player).Start(); - } - - private class SummonTimer : Timer - { - private SummonedPaladin m_Paladin; - private readonly PlayerMobile m_Player; - private int m_Step; - - public SummonTimer(PlayerMobile player) : base(TimeSpan.FromSeconds(4.0)) - { - Priority = TimerPriority.FiftyMS; - - m_Player = player; - } - - protected override void OnTick() - { - if (m_Player.Deleted) - { - if (m_Step > 0) - m_Paladin.Delete(); - - return; - } - - if (m_Step > 0 && m_Paladin.Deleted) - return; - - if (m_Step == 0) - { - SummonedPaladinMoongate moongate = new SummonedPaladinMoongate(); - moongate.MoveToWorld(new Point3D(2091, 1348, -90), Map.Malas); - - Effects.PlaySound(moongate.Location, moongate.Map, 0x20E); - - m_Paladin = new SummonedPaladin(m_Player); - m_Paladin.Frozen = true; - - m_Paladin.Location = moongate.Location; - m_Paladin.Map = moongate.Map; - - Delay = TimeSpan.FromSeconds(2.0); - Start(); - } - else if (m_Step == 1) - { - m_Paladin.Direction = m_Paladin.GetDirectionTo(m_Player); - m_Paladin.Say(1060122); // STOP WICKED ONE! - - Delay = TimeSpan.FromSeconds(3.0); - Start(); - } - else - { - m_Paladin.Frozen = false; - - m_Paladin.Say(1060123); // I will slay you before I allow you to complete your evil rites! - - m_Paladin.Combatant = m_Player; - } - - m_Step++; - } - } - } - - public class SummonedPaladinMoongate : Item - { - public SummonedPaladinMoongate() : base(0xF6C) - { - Movable = false; - Hue = 0x482; - Light = LightType.Circle300; - - Timer.DelayCall(TimeSpan.FromSeconds(10.0), Delete); - } - - public SummonedPaladinMoongate(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Delete(); - } - } -} +using System; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Necro +{ + public class SummonedPaladin : BaseCreature + { + private PlayerMobile m_Necromancer; + private bool m_ToDelete; + + public SummonedPaladin(PlayerMobile necromancer) : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + m_Necromancer = necromancer; + + InitStats(45, 30, 5); + Title = "the Paladin"; + + Hue = 0x83F3; + + Female = false; + Body = 0x190; + Name = NameList.RandomName("male"); + + Utility.AssignRandomHair(this); + Utility.AssignRandomFacialHair(this, false); + + FacialHairHue = HairHue; + + AddItem(new Boots(0x1)); + AddItem(new ChainChest()); + AddItem(new ChainLegs()); + AddItem(new RingmailArms()); + AddItem(new PlateHelm()); + AddItem(new PlateGloves()); + AddItem(new PlateGorget()); + + AddItem(new Cloak(0xCF)); + + AddItem(new ThinLongsword()); + + SetSkill(SkillName.Swords, 50.0); + SetSkill(SkillName.Tactics, 50.0); + + PackGold(500); + } + + public SummonedPaladin(Serial serial) : base(serial) + { + } + + public override bool ClickTitle => false; + + public override bool PlayerRangeSensitive => false; + + public override bool IsHarmfulCriminal(Mobile target) + { + if (target == m_Necromancer) + return false; + + return base.IsHarmfulCriminal(target); + } + + public override void OnThink() + { + if (!m_ToDelete && !Frozen) + { + if (m_Necromancer?.Deleted != false || m_Necromancer.Map == Map.Internal) + { + Delete(); + return; + } + + if (Combatant != m_Necromancer) + Combatant = m_Necromancer; + + if (!m_Necromancer.Alive) + { + var qs = m_Necromancer.Quest; + + if (qs is DarkTidesQuest && qs.FindObjective() == null) + qs.AddObjective(new FindMardothEndObjective(false)); + + Say(1060139, m_Necromancer.Name); // You have made my work easy for me, ~1_NAME~. My task here is done. + + m_ToDelete = true; + + Timer.DelayCall(TimeSpan.FromSeconds(5.0), Delete); + } + else if (m_Necromancer.Map != Map || GetDistanceToSqrt(m_Necromancer) > RangePerception + 1) + { + Effects.SendLocationParticles( + EffectItem.Create(Location, Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 2023 + ); + Effects.SendLocationParticles( + EffectItem.Create(m_Necromancer.Location, m_Necromancer.Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 5023 + ); + + Map = m_Necromancer.Map; + Location = m_Necromancer.Location; + + PlaySound(0x1FE); + + Say(1060140); // You cannot escape me, knave of evil! + } + } + + base.OnThink(); + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + var qs = m_Necromancer.Quest; + + if (qs is DarkTidesQuest && qs.FindObjective() == null) + qs.AddObjective(new FindMardothEndObjective(true)); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Necromancer); + writer.Write(m_ToDelete); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Necromancer = reader.ReadMobile() as PlayerMobile; + m_ToDelete = reader.ReadBool(); + + if (m_ToDelete) + Delete(); + } + + public static void BeginSummon(PlayerMobile player) + { + new SummonTimer(player).Start(); + } + + private class SummonTimer : Timer + { + private readonly PlayerMobile m_Player; + private SummonedPaladin m_Paladin; + private int m_Step; + + public SummonTimer(PlayerMobile player) : base(TimeSpan.FromSeconds(4.0)) + { + Priority = TimerPriority.FiftyMS; + + m_Player = player; + } + + protected override void OnTick() + { + if (m_Player.Deleted) + { + if (m_Step > 0) + m_Paladin.Delete(); + + return; + } + + if (m_Step > 0 && m_Paladin.Deleted) + return; + + if (m_Step == 0) + { + var moongate = new SummonedPaladinMoongate(); + moongate.MoveToWorld(new Point3D(2091, 1348, -90), Map.Malas); + + Effects.PlaySound(moongate.Location, moongate.Map, 0x20E); + + m_Paladin = new SummonedPaladin(m_Player); + m_Paladin.Frozen = true; + + m_Paladin.Location = moongate.Location; + m_Paladin.Map = moongate.Map; + + Delay = TimeSpan.FromSeconds(2.0); + Start(); + } + else if (m_Step == 1) + { + m_Paladin.Direction = m_Paladin.GetDirectionTo(m_Player); + m_Paladin.Say(1060122); // STOP WICKED ONE! + + Delay = TimeSpan.FromSeconds(3.0); + Start(); + } + else + { + m_Paladin.Frozen = false; + + m_Paladin.Say(1060123); // I will slay you before I allow you to complete your evil rites! + + m_Paladin.Combatant = m_Player; + } + + m_Step++; + } + } + } + + public class SummonedPaladinMoongate : Item + { + public SummonedPaladinMoongate() : base(0xF6C) + { + Movable = false; + Hue = 0x482; + Light = LightType.Circle300; + + Timer.DelayCall(TimeSpan.FromSeconds(10.0), Delete); + } + + public SummonedPaladinMoongate(Serial serial) : base(serial) + { + } + + 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(); + + Delete(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Dark Tides/Objectives.cs b/Projects/UOContent/Engines/Quests/Dark Tides/Objectives.cs index a11a6820b..41167c2ef 100644 --- a/Projects/UOContent/Engines/Quests/Dark Tides/Objectives.cs +++ b/Projects/UOContent/Engines/Quests/Dark Tides/Objectives.cs @@ -1,370 +1,371 @@ -using Server.Items; -using Server.Mobiles; -using Server.Spells.Necromancy; - -namespace Server.Engines.Quests.Necro -{ - public class AnimateMaabusCorpseObjective : QuestObjective - { - private static readonly QuestItemInfo[] m_Info = - { - new QuestItemInfo(1023643, 8787) // spellbook - }; - - public override object Message => 1060102; - - public override QuestItemInfo[] Info => m_Info; - - public override void OnComplete() - { - System.AddConversation(new MaabasConversation()); - } - } - - public class FindCrystalCaveObjective : QuestObjective - { - public override object Message => 1060104; - - public override void OnComplete() - { - System.AddConversation(new HorusConversation()); - } - } - - public class FindMardothAboutVaultObjective : QuestObjective - { - public override object Message => 1060106; - - public override void OnComplete() - { - System.AddConversation(new MardothVaultConversation()); - } - } - - public class FindMaabusTombObjective : QuestObjective - { - public override object Message => 1060124; - - public override void CheckProgress() - { - if (System.From.Map == Map.Malas && System.From.InRange(new Point3D(2024, 1240, -90), 3)) - Complete(); - } - - public override void OnComplete() - { - System.AddObjective(new FindMaabusCorpseObjective()); - } - } - - public class FindMaabusCorpseObjective : QuestObjective - { - public override object Message => 1061142; - - public override void CheckProgress() - { - if (System.From.Map == Map.Malas && System.From.InRange(new Point3D(2024, 1223, -90), 3)) - Complete(); - } - - public override void OnComplete() - { - System.AddObjective(new AnimateMaabusCorpseObjective()); - } - } - - public class FindCityOfLightObjective : QuestObjective - { - public override object Message => 1060108; - - public override void CheckProgress() - { - if (System.From.Map == Map.Malas && System.From.InRange(new Point3D(1076, 519, -90), 5)) - Complete(); - } - - public override void OnComplete() - { - System.AddObjective(new FindVaultOfSecretsObjective()); - } - } - - public class FindVaultOfSecretsObjective : QuestObjective - { - private static readonly QuestItemInfo[] m_Info = - { - new QuestItemInfo(1023676, 3679) // glowing rune - }; - - public override object Message => 1060109; - - public override QuestItemInfo[] Info => m_Info; - - public override void CheckProgress() - { - if (System.From.Map == Map.Malas && System.From.InRange(new Point3D(1072, 455, -90), 1)) - Complete(); - } - - public override void OnComplete() - { - System.AddConversation(new VaultOfSecretsConversation()); - } - } - - public class FetchAbraxusScrollObjective : QuestObjective - { - public override object Message => 1060196; - - public override void CheckProgress() - { - if (System.From.Map != Map.Malas || !System.From.InRange(new Point3D(1076, 450, -84), 5) || - !SummonFamiliarSpell.Table.TryGetValue(System.From, out BaseCreature bc) || !(bc is HordeMinionFamiliar hmf) || - !hmf.InRange(System.From, 5) || hmf.TargetLocation != null) - return; - - System.From.SendLocalizedMessage( - 1060113); // You instinctively will your familiar to fetch the scroll for you. - hmf.TargetLocation = new Point2D(1076, 450); - } - - public override void OnComplete() - { - System.AddObjective(new RetrieveAbraxusScrollObjective()); - } - } - - public class RetrieveAbraxusScrollObjective : QuestObjective - { - public override object Message => 1060199; - - public override void OnComplete() - { - System.AddConversation(new ReadAbraxusScrollConversation()); - } - } - - public class ReadAbraxusScrollObjective : QuestObjective - { - public override object Message => 1060125; - - public override void OnComplete() - { - System.AddObjective(new ReturnToCrystalCaveObjective()); - } - } - - public class ReturnToCrystalCaveObjective : QuestObjective - { - private static readonly QuestItemInfo[] m_Info = - { - new QuestItemInfo(1026153, 6178) // teleporter - }; - - public override object Message => 1060115; - - public override QuestItemInfo[] Info => m_Info; - - public override void OnComplete() - { - System.AddObjective(new SpeakCavePasswordObjective()); - } - } - - public class SpeakCavePasswordObjective : QuestObjective - { - public override object Message => 1060117; - - public override void OnComplete() - { - System.AddConversation(new SecondHorusConversation()); - } - } - - public class FindCallingScrollObjective : QuestObjective - { - private bool m_HealConversationShown; - private bool m_SkitteringHoppersDisposed; - - private int m_SkitteringHoppersKilled; - - public override object Message => 1060119; - - public override bool IgnoreYoungProtection(Mobile from) => !m_SkitteringHoppersDisposed && from is SkitteringHopper; - - public override bool GetKillEvent(BaseCreature creature, Container corpse) => !m_SkitteringHoppersDisposed; - - public override void OnKill(BaseCreature creature, Container corpse) - { - if (creature is SkitteringHopper) - { - if (!m_HealConversationShown) - { - m_HealConversationShown = true; - System.AddConversation(new HealConversation()); - } - - if (++m_SkitteringHoppersKilled >= 5) - { - m_SkitteringHoppersDisposed = true; - System.AddObjective(new FindHorusAboutRewardObjective()); - } - } - } - - public override void OnComplete() - { - System.AddObjective(new FindMardothAboutKronusObjective()); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_SkitteringHoppersKilled = reader.ReadEncodedInt(); - m_HealConversationShown = reader.ReadBool(); - m_SkitteringHoppersDisposed = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.WriteEncodedInt(m_SkitteringHoppersKilled); - writer.Write(m_HealConversationShown); - writer.Write(m_SkitteringHoppersDisposed); - } - } - - public class FindHorusAboutRewardObjective : QuestObjective - { - public override object Message => 1060126; - - public override void OnComplete() - { - System.AddConversation(new HorusRewardConversation()); - } - } - - public class FindMardothAboutKronusObjective : QuestObjective - { - public override object Message => 1060127; - - public override void OnComplete() - { - System.AddConversation(new MardothKronusConversation()); - } - } - - public class FindWellOfTearsObjective : QuestObjective - { - private static readonly Rectangle2D m_WellOfTearsArea = new Rectangle2D(2080, 1346, 10, 10); - - private bool m_Inside; - - public override object Message => 1060128; - - public override void CheckProgress() - { - if (System.From.Map == Map.Malas && m_WellOfTearsArea.Contains(System.From.Location)) - { - if (DarkTidesQuest.HasLostCallingScroll(System.From)) - { - if (!m_Inside) - System.AddConversation(new LostCallingScrollConversation(false)); - } - else - { - Complete(); - } - - m_Inside = true; - } - else - { - m_Inside = false; - } - } - - public override void OnComplete() - { - System.AddObjective(new UseCallingScrollObjective()); - } - } - - public class UseCallingScrollObjective : QuestObjective - { - public override object Message => 1060130; - } - - public class FindMardothEndObjective : QuestObjective - { - private bool m_Victory; - - public FindMardothEndObjective(bool victory) => m_Victory = victory; - - // Serialization - public FindMardothEndObjective() - { - } - - public override object Message - { - get - { - if (m_Victory) return 1060131; - - /* Although you were slain by the cowardly paladin, - * you managed to complete the rite of calling as - * instructed. Return to Mardoth. - */ - return 1060132; - } - } - - public override void OnComplete() - { - System.AddConversation(new MardothEndConversation()); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_Victory = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(m_Victory); - } - } - - public class FindBankObjective : QuestObjective - { - public override object Message => 1060134; - - public override void CheckProgress() - { - if (System.From.Map == Map.Malas && System.From.InRange(new Point3D(2048, 1345, -84), 5)) - Complete(); - } - - public override void OnComplete() - { - System.AddObjective(new CashBankCheckObjective()); - } - } - - public class CashBankCheckObjective : QuestObjective - { - public override object Message => 1060644; - - public override void OnComplete() - { - System.AddConversation(new BankerConversation()); - } - } -} +using Server.Items; +using Server.Mobiles; +using Server.Spells.Necromancy; + +namespace Server.Engines.Quests.Necro +{ + public class AnimateMaabusCorpseObjective : QuestObjective + { + private static readonly QuestItemInfo[] m_Info = + { + new QuestItemInfo(1023643, 8787) // spellbook + }; + + public override object Message => 1060102; + + public override QuestItemInfo[] Info => m_Info; + + public override void OnComplete() + { + System.AddConversation(new MaabasConversation()); + } + } + + public class FindCrystalCaveObjective : QuestObjective + { + public override object Message => 1060104; + + public override void OnComplete() + { + System.AddConversation(new HorusConversation()); + } + } + + public class FindMardothAboutVaultObjective : QuestObjective + { + public override object Message => 1060106; + + public override void OnComplete() + { + System.AddConversation(new MardothVaultConversation()); + } + } + + public class FindMaabusTombObjective : QuestObjective + { + public override object Message => 1060124; + + public override void CheckProgress() + { + if (System.From.Map == Map.Malas && System.From.InRange(new Point3D(2024, 1240, -90), 3)) + Complete(); + } + + public override void OnComplete() + { + System.AddObjective(new FindMaabusCorpseObjective()); + } + } + + public class FindMaabusCorpseObjective : QuestObjective + { + public override object Message => 1061142; + + public override void CheckProgress() + { + if (System.From.Map == Map.Malas && System.From.InRange(new Point3D(2024, 1223, -90), 3)) + Complete(); + } + + public override void OnComplete() + { + System.AddObjective(new AnimateMaabusCorpseObjective()); + } + } + + public class FindCityOfLightObjective : QuestObjective + { + public override object Message => 1060108; + + public override void CheckProgress() + { + if (System.From.Map == Map.Malas && System.From.InRange(new Point3D(1076, 519, -90), 5)) + Complete(); + } + + public override void OnComplete() + { + System.AddObjective(new FindVaultOfSecretsObjective()); + } + } + + public class FindVaultOfSecretsObjective : QuestObjective + { + private static readonly QuestItemInfo[] m_Info = + { + new QuestItemInfo(1023676, 3679) // glowing rune + }; + + public override object Message => 1060109; + + public override QuestItemInfo[] Info => m_Info; + + public override void CheckProgress() + { + if (System.From.Map == Map.Malas && System.From.InRange(new Point3D(1072, 455, -90), 1)) + Complete(); + } + + public override void OnComplete() + { + System.AddConversation(new VaultOfSecretsConversation()); + } + } + + public class FetchAbraxusScrollObjective : QuestObjective + { + public override object Message => 1060196; + + public override void CheckProgress() + { + if (System.From.Map != Map.Malas || !System.From.InRange(new Point3D(1076, 450, -84), 5) || + !SummonFamiliarSpell.Table.TryGetValue(System.From, out var bc) || !(bc is HordeMinionFamiliar hmf) || + !hmf.InRange(System.From, 5) || hmf.TargetLocation != null) + return; + + System.From.SendLocalizedMessage( + 1060113 + ); // You instinctively will your familiar to fetch the scroll for you. + hmf.TargetLocation = new Point2D(1076, 450); + } + + public override void OnComplete() + { + System.AddObjective(new RetrieveAbraxusScrollObjective()); + } + } + + public class RetrieveAbraxusScrollObjective : QuestObjective + { + public override object Message => 1060199; + + public override void OnComplete() + { + System.AddConversation(new ReadAbraxusScrollConversation()); + } + } + + public class ReadAbraxusScrollObjective : QuestObjective + { + public override object Message => 1060125; + + public override void OnComplete() + { + System.AddObjective(new ReturnToCrystalCaveObjective()); + } + } + + public class ReturnToCrystalCaveObjective : QuestObjective + { + private static readonly QuestItemInfo[] m_Info = + { + new QuestItemInfo(1026153, 6178) // teleporter + }; + + public override object Message => 1060115; + + public override QuestItemInfo[] Info => m_Info; + + public override void OnComplete() + { + System.AddObjective(new SpeakCavePasswordObjective()); + } + } + + public class SpeakCavePasswordObjective : QuestObjective + { + public override object Message => 1060117; + + public override void OnComplete() + { + System.AddConversation(new SecondHorusConversation()); + } + } + + public class FindCallingScrollObjective : QuestObjective + { + private bool m_HealConversationShown; + private bool m_SkitteringHoppersDisposed; + + private int m_SkitteringHoppersKilled; + + public override object Message => 1060119; + + public override bool IgnoreYoungProtection(Mobile from) => !m_SkitteringHoppersDisposed && from is SkitteringHopper; + + public override bool GetKillEvent(BaseCreature creature, Container corpse) => !m_SkitteringHoppersDisposed; + + public override void OnKill(BaseCreature creature, Container corpse) + { + if (creature is SkitteringHopper) + { + if (!m_HealConversationShown) + { + m_HealConversationShown = true; + System.AddConversation(new HealConversation()); + } + + if (++m_SkitteringHoppersKilled >= 5) + { + m_SkitteringHoppersDisposed = true; + System.AddObjective(new FindHorusAboutRewardObjective()); + } + } + } + + public override void OnComplete() + { + System.AddObjective(new FindMardothAboutKronusObjective()); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_SkitteringHoppersKilled = reader.ReadEncodedInt(); + m_HealConversationShown = reader.ReadBool(); + m_SkitteringHoppersDisposed = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.WriteEncodedInt(m_SkitteringHoppersKilled); + writer.Write(m_HealConversationShown); + writer.Write(m_SkitteringHoppersDisposed); + } + } + + public class FindHorusAboutRewardObjective : QuestObjective + { + public override object Message => 1060126; + + public override void OnComplete() + { + System.AddConversation(new HorusRewardConversation()); + } + } + + public class FindMardothAboutKronusObjective : QuestObjective + { + public override object Message => 1060127; + + public override void OnComplete() + { + System.AddConversation(new MardothKronusConversation()); + } + } + + public class FindWellOfTearsObjective : QuestObjective + { + private static readonly Rectangle2D m_WellOfTearsArea = new Rectangle2D(2080, 1346, 10, 10); + + private bool m_Inside; + + public override object Message => 1060128; + + public override void CheckProgress() + { + if (System.From.Map == Map.Malas && m_WellOfTearsArea.Contains(System.From.Location)) + { + if (DarkTidesQuest.HasLostCallingScroll(System.From)) + { + if (!m_Inside) + System.AddConversation(new LostCallingScrollConversation(false)); + } + else + { + Complete(); + } + + m_Inside = true; + } + else + { + m_Inside = false; + } + } + + public override void OnComplete() + { + System.AddObjective(new UseCallingScrollObjective()); + } + } + + public class UseCallingScrollObjective : QuestObjective + { + public override object Message => 1060130; + } + + public class FindMardothEndObjective : QuestObjective + { + private bool m_Victory; + + public FindMardothEndObjective(bool victory) => m_Victory = victory; + + // Serialization + public FindMardothEndObjective() + { + } + + public override object Message + { + get + { + if (m_Victory) return 1060131; + + /* Although you were slain by the cowardly paladin, + * you managed to complete the rite of calling as + * instructed. Return to Mardoth. + */ + return 1060132; + } + } + + public override void OnComplete() + { + System.AddConversation(new MardothEndConversation()); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_Victory = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(m_Victory); + } + } + + public class FindBankObjective : QuestObjective + { + public override object Message => 1060134; + + public override void CheckProgress() + { + if (System.From.Map == Map.Malas && System.From.InRange(new Point3D(2048, 1345, -84), 5)) + Complete(); + } + + public override void OnComplete() + { + System.AddObjective(new CashBankCheckObjective()); + } + } + + public class CashBankCheckObjective : QuestObjective + { + public override object Message => 1060644; + + public override void OnComplete() + { + System.AddConversation(new BankerConversation()); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Conversations.cs b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Conversations.cs index 536d5d5c3..b97c730e3 100644 --- a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Conversations.cs +++ b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Conversations.cs @@ -1,185 +1,185 @@ -namespace Server.Engines.Quests.Ninja -{ - public class AcceptConversation : QuestConversation - { - public override object Message => 1049092; - - public override void OnRead() - { - System.AddObjective(new FindEminoBeginObjective()); - } - } - - public class FindZoelConversation : QuestConversation - { - public override object Message => 1063175; - - public override void OnRead() - { - System.AddObjective(new FindZoelObjective()); - } - } - - public class RadarConversation : QuestConversation - { - public override object Message => 1063033; - - public override bool Logged => false; - } - - public class EnterCaveConversation : QuestConversation - { - public override object Message => 1063177; - - public override void OnRead() - { - System.AddObjective(new EnterCaveObjective()); - } - } - - public class SneakPastGuardiansConversation : QuestConversation - { - public override object Message => 1063180; - - public override void OnRead() - { - System.AddObjective(new SneakPastGuardiansObjective()); - } - } - - public class NeedToHideConversation : QuestConversation - { - public override object Message => 1063181; - } - - public class UseTeleporterConversation : QuestConversation - { - public override object Message => 1063182; - - public override void OnRead() - { - System.AddObjective(new UseTeleporterObjective()); - } - } - - public class GiveZoelNoteConversation : QuestConversation - { - public override object Message => 1063184; - - public override void OnRead() - { - System.AddObjective(new GiveZoelNoteObjective()); - } - } - - public class LostNoteConversation : QuestConversation - { - public override object Message => 1063187; - - public override bool Logged => false; - } - - public class GainInnInformationConversation : QuestConversation - { - public override object Message => 1063189; - - public override void OnRead() - { - System.AddObjective(new GainInnInformationObjective()); - } - } - - public class ReturnFromInnConversation : QuestConversation - { - public override object Message => 1063196; - - public override void OnRead() - { - System.AddObjective(new ReturnFromInnObjective()); - } - } - - public class SearchForSwordConversation : QuestConversation - { - public override object Message => 1063199; - - public override void OnRead() - { - System.AddObjective(new SearchForSwordObjective()); - } - } - - public class HallwayWalkConversation : QuestConversation - { - public override object Message => 1063201; - - public override void OnRead() - { - System.AddObjective(new HallwayWalkObjective()); - } - } - - public class ReturnSwordConversation : QuestConversation - { - public override object Message => 1063203; - - public override void OnRead() - { - System.AddObjective(new ReturnSwordObjective()); - } - } - - public class SlayHenchmenConversation : QuestConversation - { - public override object Message => 1063205; - - public override void OnRead() - { - System.AddObjective(new SlayHenchmenObjective()); - } - } - - public class ContinueSlayHenchmenConversation : QuestConversation - { - public override object Message => 1063208; - - public override bool Logged => false; - } - - public class GiveEminoSwordConversation : QuestConversation - { - public override object Message => 1063211; - - public override void OnRead() - { - System.AddObjective(new GiveEminoSwordObjective()); - } - } - - public class LostSwordConversation : QuestConversation - { - public override object Message => 1063212; - - public override bool Logged => false; - } - - public class EarnGiftsConversation : QuestConversation - { - public override object Message => 1063216; - - public override void OnRead() - { - System.Complete(); - } - } - - public class EarnLessGiftsConversation : QuestConversation - { - public override object Message => 1063217; - - public override void OnRead() - { - System.Complete(); - } - } -} \ No newline at end of file +namespace Server.Engines.Quests.Ninja +{ + public class AcceptConversation : QuestConversation + { + public override object Message => 1049092; + + public override void OnRead() + { + System.AddObjective(new FindEminoBeginObjective()); + } + } + + public class FindZoelConversation : QuestConversation + { + public override object Message => 1063175; + + public override void OnRead() + { + System.AddObjective(new FindZoelObjective()); + } + } + + public class RadarConversation : QuestConversation + { + public override object Message => 1063033; + + public override bool Logged => false; + } + + public class EnterCaveConversation : QuestConversation + { + public override object Message => 1063177; + + public override void OnRead() + { + System.AddObjective(new EnterCaveObjective()); + } + } + + public class SneakPastGuardiansConversation : QuestConversation + { + public override object Message => 1063180; + + public override void OnRead() + { + System.AddObjective(new SneakPastGuardiansObjective()); + } + } + + public class NeedToHideConversation : QuestConversation + { + public override object Message => 1063181; + } + + public class UseTeleporterConversation : QuestConversation + { + public override object Message => 1063182; + + public override void OnRead() + { + System.AddObjective(new UseTeleporterObjective()); + } + } + + public class GiveZoelNoteConversation : QuestConversation + { + public override object Message => 1063184; + + public override void OnRead() + { + System.AddObjective(new GiveZoelNoteObjective()); + } + } + + public class LostNoteConversation : QuestConversation + { + public override object Message => 1063187; + + public override bool Logged => false; + } + + public class GainInnInformationConversation : QuestConversation + { + public override object Message => 1063189; + + public override void OnRead() + { + System.AddObjective(new GainInnInformationObjective()); + } + } + + public class ReturnFromInnConversation : QuestConversation + { + public override object Message => 1063196; + + public override void OnRead() + { + System.AddObjective(new ReturnFromInnObjective()); + } + } + + public class SearchForSwordConversation : QuestConversation + { + public override object Message => 1063199; + + public override void OnRead() + { + System.AddObjective(new SearchForSwordObjective()); + } + } + + public class HallwayWalkConversation : QuestConversation + { + public override object Message => 1063201; + + public override void OnRead() + { + System.AddObjective(new HallwayWalkObjective()); + } + } + + public class ReturnSwordConversation : QuestConversation + { + public override object Message => 1063203; + + public override void OnRead() + { + System.AddObjective(new ReturnSwordObjective()); + } + } + + public class SlayHenchmenConversation : QuestConversation + { + public override object Message => 1063205; + + public override void OnRead() + { + System.AddObjective(new SlayHenchmenObjective()); + } + } + + public class ContinueSlayHenchmenConversation : QuestConversation + { + public override object Message => 1063208; + + public override bool Logged => false; + } + + public class GiveEminoSwordConversation : QuestConversation + { + public override object Message => 1063211; + + public override void OnRead() + { + System.AddObjective(new GiveEminoSwordObjective()); + } + } + + public class LostSwordConversation : QuestConversation + { + public override object Message => 1063212; + + public override bool Logged => false; + } + + public class EarnGiftsConversation : QuestConversation + { + public override object Message => 1063216; + + public override void OnRead() + { + System.Complete(); + } + } + + public class EarnLessGiftsConversation : QuestConversation + { + public override object Message => 1063217; + + public override void OnRead() + { + System.Complete(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Emino's Undertaking/EminosUndertakingQuest.cs b/Projects/UOContent/Engines/Quests/Emino's Undertaking/EminosUndertakingQuest.cs index 79bdc6be6..724817cf8 100644 --- a/Projects/UOContent/Engines/Quests/Emino's Undertaking/EminosUndertakingQuest.cs +++ b/Projects/UOContent/Engines/Quests/Emino's Undertaking/EminosUndertakingQuest.cs @@ -1,128 +1,128 @@ -using System; -using Server.Mobiles; - -namespace Server.Engines.Quests.Ninja -{ - public class EminosUndertakingQuest : QuestSystem - { - private static readonly Type[] m_TypeReferenceTable = - { - typeof(AcceptConversation), - typeof(FindZoelConversation), - typeof(RadarConversation), - typeof(EnterCaveConversation), - typeof(SneakPastGuardiansConversation), - typeof(NeedToHideConversation), - typeof(UseTeleporterConversation), - typeof(GiveZoelNoteConversation), - typeof(LostNoteConversation), - typeof(GainInnInformationConversation), - typeof(ReturnFromInnConversation), - typeof(SearchForSwordConversation), - typeof(HallwayWalkConversation), - typeof(ReturnSwordConversation), - typeof(SlayHenchmenConversation), - typeof(ContinueSlayHenchmenConversation), - typeof(GiveEminoSwordConversation), - typeof(LostSwordConversation), - typeof(EarnGiftsConversation), - typeof(EarnLessGiftsConversation), - typeof(FindEminoBeginObjective), - typeof(FindZoelObjective), - typeof(EnterCaveObjective), - typeof(SneakPastGuardiansObjective), - typeof(UseTeleporterObjective), - typeof(GiveZoelNoteObjective), - typeof(GainInnInformationObjective), - typeof(ReturnFromInnObjective), - typeof(SearchForSwordObjective), - typeof(HallwayWalkObjective), - typeof(ReturnSwordObjective), - typeof(SlayHenchmenObjective), - typeof(GiveEminoSwordObjective) - }; - - private bool m_SentRadarConversion; - - public EminosUndertakingQuest(PlayerMobile from) : base(from) - { - } - - // Serialization - public EminosUndertakingQuest() - { - } - - public override Type[] TypeReferenceTable => m_TypeReferenceTable; - - public override object Name => 1063173; - - public override object OfferMessage => 1063174; - - public override TimeSpan RestartDelay => TimeSpan.MaxValue; - public override bool IsTutorial => true; - - public override int Picture => 0x15D5; - - public override void Accept() - { - base.Accept(); - - AddConversation(new AcceptConversation()); - } - - public override void Slice() - { - if (!m_SentRadarConversion && - (From.Map != Map.Malas || From.X < 407 || From.X > 431 || From.Y < 801 || From.Y > 830)) - { - m_SentRadarConversion = true; - AddConversation(new RadarConversation()); - } - - base.Slice(); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_SentRadarConversion = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(m_SentRadarConversion); - } - - public static bool HasLostNoteForZoel(Mobile from) - { - if (!(from is PlayerMobile pm)) - return false; - - QuestSystem qs = pm.Quest; - - if (qs is EminosUndertakingQuest) - if (qs.IsObjectiveInProgress(typeof(GiveZoelNoteObjective))) - return from.Backpack?.FindItemByType() == null; - - return false; - } - - public static bool HasLostEminosKatana(Mobile from) - { - if (!(from is PlayerMobile pm)) - return false; - - QuestSystem qs = pm.Quest; - - if (qs is EminosUndertakingQuest) - if (qs.IsObjectiveInProgress(typeof(GiveEminoSwordObjective))) - return from.Backpack?.FindItemByType() == null; - - return false; - } - } -} \ No newline at end of file +using System; +using Server.Mobiles; + +namespace Server.Engines.Quests.Ninja +{ + public class EminosUndertakingQuest : QuestSystem + { + private static readonly Type[] m_TypeReferenceTable = + { + typeof(AcceptConversation), + typeof(FindZoelConversation), + typeof(RadarConversation), + typeof(EnterCaveConversation), + typeof(SneakPastGuardiansConversation), + typeof(NeedToHideConversation), + typeof(UseTeleporterConversation), + typeof(GiveZoelNoteConversation), + typeof(LostNoteConversation), + typeof(GainInnInformationConversation), + typeof(ReturnFromInnConversation), + typeof(SearchForSwordConversation), + typeof(HallwayWalkConversation), + typeof(ReturnSwordConversation), + typeof(SlayHenchmenConversation), + typeof(ContinueSlayHenchmenConversation), + typeof(GiveEminoSwordConversation), + typeof(LostSwordConversation), + typeof(EarnGiftsConversation), + typeof(EarnLessGiftsConversation), + typeof(FindEminoBeginObjective), + typeof(FindZoelObjective), + typeof(EnterCaveObjective), + typeof(SneakPastGuardiansObjective), + typeof(UseTeleporterObjective), + typeof(GiveZoelNoteObjective), + typeof(GainInnInformationObjective), + typeof(ReturnFromInnObjective), + typeof(SearchForSwordObjective), + typeof(HallwayWalkObjective), + typeof(ReturnSwordObjective), + typeof(SlayHenchmenObjective), + typeof(GiveEminoSwordObjective) + }; + + private bool m_SentRadarConversion; + + public EminosUndertakingQuest(PlayerMobile from) : base(from) + { + } + + // Serialization + public EminosUndertakingQuest() + { + } + + public override Type[] TypeReferenceTable => m_TypeReferenceTable; + + public override object Name => 1063173; + + public override object OfferMessage => 1063174; + + public override TimeSpan RestartDelay => TimeSpan.MaxValue; + public override bool IsTutorial => true; + + public override int Picture => 0x15D5; + + public override void Accept() + { + base.Accept(); + + AddConversation(new AcceptConversation()); + } + + public override void Slice() + { + if (!m_SentRadarConversion && + (From.Map != Map.Malas || From.X < 407 || From.X > 431 || From.Y < 801 || From.Y > 830)) + { + m_SentRadarConversion = true; + AddConversation(new RadarConversation()); + } + + base.Slice(); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_SentRadarConversion = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(m_SentRadarConversion); + } + + public static bool HasLostNoteForZoel(Mobile from) + { + if (!(from is PlayerMobile pm)) + return false; + + var qs = pm.Quest; + + if (qs is EminosUndertakingQuest) + if (qs.IsObjectiveInProgress(typeof(GiveZoelNoteObjective))) + return from.Backpack?.FindItemByType() == null; + + return false; + } + + public static bool HasLostEminosKatana(Mobile from) + { + if (!(from is PlayerMobile pm)) + return false; + + var qs = pm.Quest; + + if (qs is EminosUndertakingQuest) + if (qs.IsObjectiveInProgress(typeof(GiveEminoSwordObjective))) + return from.Backpack?.FindItemByType() == null; + + return false; + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/BlueNinjaQuestTeleporter.cs b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/BlueNinjaQuestTeleporter.cs index 5137bfefa..7ccf1602f 100644 --- a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/BlueNinjaQuestTeleporter.cs +++ b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/BlueNinjaQuestTeleporter.cs @@ -1,49 +1,49 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Ninja -{ - public class BlueNinjaQuestTeleporter : DynamicTeleporter - { - [Constructible] - public BlueNinjaQuestTeleporter() : base(0x51C, 0x2) - { - } - - public BlueNinjaQuestTeleporter(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1026157; // teleporter - - public override int NotWorkingMessage => 1063198; // You stand on the strange floor tile but nothing happens. - - public override bool GetDestination(PlayerMobile player, ref Point3D loc, ref Map map) - { - QuestSystem qs = player.Quest; - - if (qs is EminosUndertakingQuest && qs.FindObjective() != null) - { - loc = new Point3D(411, 1116, 0); - map = Map.Malas; - - return true; - } - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Ninja +{ + public class BlueNinjaQuestTeleporter : DynamicTeleporter + { + [Constructible] + public BlueNinjaQuestTeleporter() : base(0x51C, 0x2) + { + } + + public BlueNinjaQuestTeleporter(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1026157; // teleporter + + public override int NotWorkingMessage => 1063198; // You stand on the strange floor tile but nothing happens. + + public override bool GetDestination(PlayerMobile player, ref Point3D loc, ref Map map) + { + var qs = player.Quest; + + if (qs is EminosUndertakingQuest && qs.FindObjective() != null) + { + loc = new Point3D(411, 1116, 0); + map = Map.Malas; + + return true; + } + + return 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/EminosKatana.cs b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/EminosKatana.cs index f837ac923..b3ae1d647 100644 --- a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/EminosKatana.cs +++ b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/EminosKatana.cs @@ -1,32 +1,32 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Ninja -{ - public class EminosKatana : QuestItem - { - [Constructible] - public EminosKatana() : base(0x13FF) => Weight = 1.0; - - public EminosKatana(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1063214; // Daimyo Emino's Katana - - public override bool CanDrop(PlayerMobile player) => !(player.Quest is EminosUndertakingQuest); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Ninja +{ + public class EminosKatana : QuestItem + { + [Constructible] + public EminosKatana() : base(0x13FF) => Weight = 1.0; + + public EminosKatana(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1063214; // Daimyo Emino's Katana + + public override bool CanDrop(PlayerMobile player) => !(player.Quest is EminosUndertakingQuest); + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/EminosKatanaChest.cs b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/EminosKatanaChest.cs index 83a3bd913..322343cbe 100644 --- a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/EminosKatanaChest.cs +++ b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/EminosKatanaChest.cs @@ -1,132 +1,136 @@ -using Server.Items; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.Quests.Ninja -{ - public class EminosKatanaChest : WoodenChest - { - [Constructible] - public EminosKatanaChest() - { - Movable = false; - ItemID = 0xE42; - - GenerateTreasure(); - } - - public EminosKatanaChest(Serial serial) : base(serial) - { - } - - public override bool IsDecoContainer => false; - - private void GenerateTreasure() - { - for (int i = Items.Count - 1; i >= 0; i--) - Items[i].Delete(); - - for (int i = 0; i < 75; i++) - DropItem( - Utility.Random(10) switch - { - 0 => new GoldBracelet(), - 1 => new GoldRing(), - _ => Loot.RandomGem() // 2 - } - ); - } - - public override void OnDoubleClick(Mobile from) - { - if (from is PlayerMobile player && player.InRange(GetWorldLocation(), 2)) - { - QuestSystem qs = player.Quest; - - if (qs is EminosUndertakingQuest) - { - if (EminosUndertakingQuest.HasLostEminosKatana(from)) - { - Item katana = new EminosKatana(); - - if (!player.PlaceInBackpack(katana)) - { - katana.Delete(); - player.SendLocalizedMessage( - 1046260); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. - } - } - else - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - Item katana = new EminosKatana(); - - if (player.PlaceInBackpack(katana)) - { - GenerateTreasure(); - obj.Complete(); - } - else - { - katana.Delete(); - player.SendLocalizedMessage( - 1046260); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. - } - } - } - } - } - - base.OnDoubleClick(from); - } - - public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight) => false; - - public override bool CheckItemUse(Mobile from, Item item) => item == this; - - public override bool CheckLift(Mobile from, Item item, ref LRReason reject) - { - if (from.AccessLevel >= AccessLevel.GameMaster) - return true; - - if (from is PlayerMobile player && player.Quest is EminosUndertakingQuest) - { - HallwayWalkObjective obj = player.Quest.FindObjective(); - if (obj?.StolenTreasure == true) - from.SendLocalizedMessage( - 1063247); // The guard is watching you carefully! It would be unwise to remove another item from here. - else - return true; - } - - return false; - } - - public override void OnItemLifted(Mobile from, Item item) - { - if (from is PlayerMobile player && player.Quest is EminosUndertakingQuest) - { - HallwayWalkObjective obj = player.Quest.FindObjective(); - if (obj != null) - obj.StolenTreasure = true; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} +using Server.Items; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.Quests.Ninja +{ + public class EminosKatanaChest : WoodenChest + { + [Constructible] + public EminosKatanaChest() + { + Movable = false; + ItemID = 0xE42; + + GenerateTreasure(); + } + + public EminosKatanaChest(Serial serial) : base(serial) + { + } + + public override bool IsDecoContainer => false; + + private void GenerateTreasure() + { + for (var i = Items.Count - 1; i >= 0; i--) + Items[i].Delete(); + + for (var i = 0; i < 75; i++) + DropItem( + Utility.Random(10) switch + { + 0 => new GoldBracelet(), + 1 => new GoldRing(), + _ => Loot.RandomGem() // 2 + } + ); + } + + public override void OnDoubleClick(Mobile from) + { + if (from is PlayerMobile player && player.InRange(GetWorldLocation(), 2)) + { + var qs = player.Quest; + + if (qs is EminosUndertakingQuest) + { + if (EminosUndertakingQuest.HasLostEminosKatana(from)) + { + Item katana = new EminosKatana(); + + if (!player.PlaceInBackpack(katana)) + { + katana.Delete(); + player.SendLocalizedMessage( + 1046260 + ); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. + } + } + else + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + Item katana = new EminosKatana(); + + if (player.PlaceInBackpack(katana)) + { + GenerateTreasure(); + obj.Complete(); + } + else + { + katana.Delete(); + player.SendLocalizedMessage( + 1046260 + ); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. + } + } + } + } + } + + base.OnDoubleClick(from); + } + + public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight) => + false; + + public override bool CheckItemUse(Mobile from, Item item) => item == this; + + public override bool CheckLift(Mobile from, Item item, ref LRReason reject) + { + if (from.AccessLevel >= AccessLevel.GameMaster) + return true; + + if (from is PlayerMobile player && player.Quest is EminosUndertakingQuest) + { + var obj = player.Quest.FindObjective(); + if (obj?.StolenTreasure == true) + from.SendLocalizedMessage( + 1063247 + ); // The guard is watching you carefully! It would be unwise to remove another item from here. + else + return true; + } + + return false; + } + + public override void OnItemLifted(Mobile from, Item item) + { + if (from is PlayerMobile player && player.Quest is EminosUndertakingQuest) + { + var obj = player.Quest.FindObjective(); + if (obj != null) + obj.StolenTreasure = true; + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/GreenNinjaQuestTeleporter.cs b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/GreenNinjaQuestTeleporter.cs index 7afd27eda..b6d002cd2 100644 --- a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/GreenNinjaQuestTeleporter.cs +++ b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/GreenNinjaQuestTeleporter.cs @@ -1,49 +1,49 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Ninja -{ - public class GreenNinjaQuestTeleporter : DynamicTeleporter - { - [Constructible] - public GreenNinjaQuestTeleporter() : base(0x51C, 0x17E) - { - } - - public GreenNinjaQuestTeleporter(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1026157; // teleporter - - public override int NotWorkingMessage => 1063198; // You stand on the strange floor tile but nothing happens. - - public override bool GetDestination(PlayerMobile player, ref Point3D loc, ref Map map) - { - QuestSystem qs = player.Quest; - - if (qs is EminosUndertakingQuest && qs.FindObjective() != null) - { - loc = new Point3D(410, 1125, 0); - map = Map.Malas; - - return true; - } - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Ninja +{ + public class GreenNinjaQuestTeleporter : DynamicTeleporter + { + [Constructible] + public GreenNinjaQuestTeleporter() : base(0x51C, 0x17E) + { + } + + public GreenNinjaQuestTeleporter(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1026157; // teleporter + + public override int NotWorkingMessage => 1063198; // You stand on the strange floor tile but nothing happens. + + public override bool GetDestination(PlayerMobile player, ref Point3D loc, ref Map map) + { + var qs = player.Quest; + + if (qs is EminosUndertakingQuest && qs.FindObjective() != null) + { + loc = new Point3D(410, 1125, 0); + map = Map.Malas; + + return true; + } + + return 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/GuardianBarrier.cs b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/GuardianBarrier.cs index 4569fcafd..4115f9632 100644 --- a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/GuardianBarrier.cs +++ b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/GuardianBarrier.cs @@ -1,68 +1,68 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Ninja -{ - public class GuardianBarrier : Item - { - [Constructible] - public GuardianBarrier() : base(0x3967) - { - Movable = false; - Visible = false; - } - - public GuardianBarrier(Serial serial) : base(serial) - { - } - - public override bool OnMoveOver(Mobile m) - { - if (m.AccessLevel > AccessLevel.Player) - return true; - - // If the mobile is to the north of the barrier, allow him to pass - if (Y >= m.Y) - return true; - - if (m is BaseCreature creature) - { - Mobile master = creature.GetMaster(); - - // Allow creatures to cross from the south to the north only if their master is near to the north - return master != null && Y >= master.Y && master.InRange(this, 4); - } - - if (m is PlayerMobile pm && pm.Quest is EminosUndertakingQuest qs) - { - SneakPastGuardiansObjective obj = qs.FindObjective(); - if (obj != null) - { - if (m.Hidden) - return true; // Hidden ninjas can pass - - if (!obj.TaughtHowToUseSkills) - { - obj.TaughtHowToUseSkills = true; - qs.AddConversation(new NeedToHideConversation()); - } - } - } - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Ninja +{ + public class GuardianBarrier : Item + { + [Constructible] + public GuardianBarrier() : base(0x3967) + { + Movable = false; + Visible = false; + } + + public GuardianBarrier(Serial serial) : base(serial) + { + } + + public override bool OnMoveOver(Mobile m) + { + if (m.AccessLevel > AccessLevel.Player) + return true; + + // If the mobile is to the north of the barrier, allow him to pass + if (Y >= m.Y) + return true; + + if (m is BaseCreature creature) + { + var master = creature.GetMaster(); + + // Allow creatures to cross from the south to the north only if their master is near to the north + return master != null && Y >= master.Y && master.InRange(this, 4); + } + + if (m is PlayerMobile pm && pm.Quest is EminosUndertakingQuest qs) + { + var obj = qs.FindObjective(); + if (obj != null) + { + if (m.Hidden) + return true; // Hidden ninjas can pass + + if (!obj.TaughtHowToUseSkills) + { + obj.TaughtHowToUseSkills = true; + qs.AddConversation(new NeedToHideConversation()); + } + } + } + + return 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/NoteForZoel.cs b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/NoteForZoel.cs index 71707f20f..cd1d0dc6e 100644 --- a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/NoteForZoel.cs +++ b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/NoteForZoel.cs @@ -1,36 +1,36 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Ninja -{ - public class NoteForZoel : QuestItem - { - [Constructible] - public NoteForZoel() : base(0x14EF) - { - Weight = 1.0; - Hue = 0x6B9; - } - - public NoteForZoel(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1063186; // A Note for Zoel - - public override bool CanDrop(PlayerMobile player) => !(player.Quest is EminosUndertakingQuest); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Ninja +{ + public class NoteForZoel : QuestItem + { + [Constructible] + public NoteForZoel() : base(0x14EF) + { + Weight = 1.0; + Hue = 0x6B9; + } + + public NoteForZoel(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1063186; // A Note for Zoel + + public override bool CanDrop(PlayerMobile player) => !(player.Quest is EminosUndertakingQuest); + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/WhiteNinjaQuestTeleporter.cs b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/WhiteNinjaQuestTeleporter.cs index fde82601a..a822b0678 100644 --- a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/WhiteNinjaQuestTeleporter.cs +++ b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Items/WhiteNinjaQuestTeleporter.cs @@ -1,57 +1,57 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Ninja -{ - public class WhiteNinjaQuestTeleporter : DynamicTeleporter - { - [Constructible] - public WhiteNinjaQuestTeleporter() : base(0x51C, 0x47E) - { - } - - public WhiteNinjaQuestTeleporter(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1026157; // teleporter - - public override int NotWorkingMessage => 1063198; // You stand on the strange floor tile but nothing happens. - - public override bool GetDestination(PlayerMobile player, ref Point3D loc, ref Map map) - { - QuestSystem qs = player.Quest; - - if (qs is EminosUndertakingQuest) - { - QuestObjective obj = qs.FindObjective(); - - if (obj != null) - { - if (!obj.Completed) - obj.Complete(); - - loc = new Point3D(411, 1085, 0); - map = Map.Malas; - - return true; - } - } - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Ninja +{ + public class WhiteNinjaQuestTeleporter : DynamicTeleporter + { + [Constructible] + public WhiteNinjaQuestTeleporter() : base(0x51C, 0x47E) + { + } + + public WhiteNinjaQuestTeleporter(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1026157; // teleporter + + public override int NotWorkingMessage => 1063198; // You stand on the strange floor tile but nothing happens. + + public override bool GetDestination(PlayerMobile player, ref Point3D loc, ref Map map) + { + var qs = player.Quest; + + if (qs is EminosUndertakingQuest) + { + QuestObjective obj = qs.FindObjective(); + + if (obj != null) + { + if (!obj.Completed) + obj.Complete(); + + loc = new Point3D(411, 1085, 0); + map = Map.Malas; + + return true; + } + } + + return 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/Emino.cs b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/Emino.cs index ceb27bd63..ec3c23afd 100644 --- a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/Emino.cs +++ b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/Emino.cs @@ -1,228 +1,232 @@ -using Server.Gumps; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Ninja -{ - public class Emino : BaseQuester - { - [Constructible] - public Emino() : base("the Notorious") - { - } - - public Emino(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Daimyo Emino"; - - public override int TalkNumber => -1; - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = 0x83FE; - - Female = false; - Body = 0x190; - } - - public override void InitOutfit() - { - HairItemID = 0x203B; - HairHue = 0x901; - - AddItem(new MaleKimono()); - AddItem(new SamuraiTabi()); - AddItem(new Bandana()); - - AddItem(new PlateHaidate()); - AddItem(new PlateDo()); - AddItem(new PlateHiroSode()); - - Nunchaku nunchaku = new Nunchaku(); - nunchaku.Movable = false; - AddItem(nunchaku); - } - - public override int GetAutoTalkRange(PlayerMobile pm) => 2; - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - QuestSystem qs = player.Quest; - - if (qs is EminosUndertakingQuest) - { - if (EminosUndertakingQuest.HasLostNoteForZoel(player)) - { - Item note = new NoteForZoel(); - - if (player.PlaceInBackpack(note)) - { - qs.AddConversation(new LostNoteConversation()); - } - else - { - note.Delete(); - player.SendLocalizedMessage( - 1046260); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. - } - } - else if (EminosUndertakingQuest.HasLostEminosKatana(player)) - { - qs.AddConversation(new LostSwordConversation()); - } - else - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - obj.Complete(); - } - else - { - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - Item note = new NoteForZoel(); - - if (player.PlaceInBackpack(note)) - { - obj.Complete(); - - player.AddToBackpack(new LeatherNinjaPants()); - player.AddToBackpack(new LeatherNinjaMitts()); - } - else - { - note.Delete(); - player.SendLocalizedMessage( - 1046260); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. - } - } - else - { - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - Container cont = GetNewContainer(); - - for (int i = 0; i < 10; i++) - cont.DropItem(new LesserHealPotion()); - - cont.DropItem(new LeatherNinjaHood()); - cont.DropItem(new LeatherNinjaJacket()); - - if (player.PlaceInBackpack(cont)) - { - obj.Complete(); - } - else - { - cont.Delete(); - player.SendLocalizedMessage( - 1046260); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. - } - } - else - { - if (qs.IsObjectiveInProgress(typeof(SlayHenchmenObjective))) - { - qs.AddConversation(new ContinueSlayHenchmenConversation()); - } - else - { - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - Item katana = null; - - if (player.Backpack != null) - katana = player.Backpack.FindItemByType(); - - if (katana != null) - { - bool stolenTreasure = false; - - HallwayWalkObjective walk = qs.FindObjective(); - - if (walk != null) - stolenTreasure = walk.StolenTreasure; - - Kama kama = new Kama(); - - if (stolenTreasure) - BaseRunicTool.ApplyAttributesTo(kama, 1, 10, 20); - else - BaseRunicTool.ApplyAttributesTo(kama, 1, 10, 30); - - if (player.PlaceInBackpack(kama)) - { - katana.Delete(); - obj.Complete(); - - if (stolenTreasure) - qs.AddConversation(new EarnLessGiftsConversation()); - else - qs.AddConversation(new EarnGiftsConversation()); - } - else - { - kama.Delete(); - player.SendLocalizedMessage( - 1046260); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. - } - } - } - } - } - } - } - } - } - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - base.OnMovement(m, oldLocation); - - if (!m.Frozen && !m.Alive && InRange(m, 4) && !InRange(oldLocation, 4) && InLOS(m)) - { - if (m.Map?.CanFit(m.Location, 16, false, false) != true) - { - m.SendLocalizedMessage(502391); // Thou can not be resurrected there! - } - else - { - Direction = GetDirectionTo(m); - - m.PlaySound(0x214); - m.FixedEffect(0x376A, 10, 16); - - m.CloseGump(); - m.SendGump(new ResurrectGump(m, ResurrectMessage.Healer)); - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Gumps; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Ninja +{ + public class Emino : BaseQuester + { + [Constructible] + public Emino() : base("the Notorious") + { + } + + public Emino(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Daimyo Emino"; + + public override int TalkNumber => -1; + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = 0x83FE; + + Female = false; + Body = 0x190; + } + + public override void InitOutfit() + { + HairItemID = 0x203B; + HairHue = 0x901; + + AddItem(new MaleKimono()); + AddItem(new SamuraiTabi()); + AddItem(new Bandana()); + + AddItem(new PlateHaidate()); + AddItem(new PlateDo()); + AddItem(new PlateHiroSode()); + + var nunchaku = new Nunchaku(); + nunchaku.Movable = false; + AddItem(nunchaku); + } + + public override int GetAutoTalkRange(PlayerMobile pm) => 2; + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + var qs = player.Quest; + + if (qs is EminosUndertakingQuest) + { + if (EminosUndertakingQuest.HasLostNoteForZoel(player)) + { + Item note = new NoteForZoel(); + + if (player.PlaceInBackpack(note)) + { + qs.AddConversation(new LostNoteConversation()); + } + else + { + note.Delete(); + player.SendLocalizedMessage( + 1046260 + ); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. + } + } + else if (EminosUndertakingQuest.HasLostEminosKatana(player)) + { + qs.AddConversation(new LostSwordConversation()); + } + else + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + obj.Complete(); + } + else + { + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + Item note = new NoteForZoel(); + + if (player.PlaceInBackpack(note)) + { + obj.Complete(); + + player.AddToBackpack(new LeatherNinjaPants()); + player.AddToBackpack(new LeatherNinjaMitts()); + } + else + { + note.Delete(); + player.SendLocalizedMessage( + 1046260 + ); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. + } + } + else + { + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + var cont = GetNewContainer(); + + for (var i = 0; i < 10; i++) + cont.DropItem(new LesserHealPotion()); + + cont.DropItem(new LeatherNinjaHood()); + cont.DropItem(new LeatherNinjaJacket()); + + if (player.PlaceInBackpack(cont)) + { + obj.Complete(); + } + else + { + cont.Delete(); + player.SendLocalizedMessage( + 1046260 + ); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. + } + } + else + { + if (qs.IsObjectiveInProgress(typeof(SlayHenchmenObjective))) + { + qs.AddConversation(new ContinueSlayHenchmenConversation()); + } + else + { + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + Item katana = null; + + if (player.Backpack != null) + katana = player.Backpack.FindItemByType(); + + if (katana != null) + { + var stolenTreasure = false; + + var walk = qs.FindObjective(); + + if (walk != null) + stolenTreasure = walk.StolenTreasure; + + var kama = new Kama(); + + if (stolenTreasure) + BaseRunicTool.ApplyAttributesTo(kama, 1, 10, 20); + else + BaseRunicTool.ApplyAttributesTo(kama, 1, 10, 30); + + if (player.PlaceInBackpack(kama)) + { + katana.Delete(); + obj.Complete(); + + if (stolenTreasure) + qs.AddConversation(new EarnLessGiftsConversation()); + else + qs.AddConversation(new EarnGiftsConversation()); + } + else + { + kama.Delete(); + player.SendLocalizedMessage( + 1046260 + ); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. + } + } + } + } + } + } + } + } + } + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + base.OnMovement(m, oldLocation); + + if (!m.Frozen && !m.Alive && InRange(m, 4) && !InRange(oldLocation, 4) && InLOS(m)) + { + if (m.Map?.CanFit(m.Location, 16, false, false) != true) + { + m.SendLocalizedMessage(502391); // Thou can not be resurrected there! + } + else + { + Direction = GetDirectionTo(m); + + m.PlaySound(0x214); + m.FixedEffect(0x376A, 10, 16); + + m.CloseGump(); + m.SendGump(new ResurrectGump(m, ResurrectMessage.Healer)); + } + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/EnshroudedFigure.cs b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/EnshroudedFigure.cs index 4bffd30f9..1a838e16c 100644 --- a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/EnshroudedFigure.cs +++ b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/EnshroudedFigure.cs @@ -1,54 +1,54 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Ninja -{ - public class EnshroudedFigure : BaseQuester - { - [Constructible] - public EnshroudedFigure() - { - } - - public EnshroudedFigure(Serial serial) : base(serial) - { - } - - public override string DefaultName => "an enshrouded figure"; - - public override int TalkNumber => -1; - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = 0x8401; - Female = false; - Body = 0x190; - } - - public override void InitOutfit() - { - AddItem(new DeathShroud()); - AddItem(new ThighBoots()); - } - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Ninja +{ + public class EnshroudedFigure : BaseQuester + { + [Constructible] + public EnshroudedFigure() + { + } + + public EnshroudedFigure(Serial serial) : base(serial) + { + } + + public override string DefaultName => "an enshrouded figure"; + + public override int TalkNumber => -1; + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = 0x8401; + Female = false; + Body = 0x190; + } + + public override void InitOutfit() + { + AddItem(new DeathShroud()); + AddItem(new ThighBoots()); + } + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/Henchman.cs b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/Henchman.cs index 6f15e8bd6..e62ad31e5 100644 --- a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/Henchman.cs +++ b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/Henchman.cs @@ -1,54 +1,54 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Ninja -{ - public class Henchman : BaseCreature - { - [Constructible] - public Henchman() : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) - { - InitStats(45, 30, 5); - - Hue = Race.Human.RandomSkinHue(); - Body = 0x190; - - Utility.AssignRandomHair(this); - Utility.AssignRandomFacialHair(this); - - AddItem(new LeatherNinjaJacket()); - AddItem(new LeatherNinjaPants()); - AddItem(new NinjaTabi()); - - if (Utility.RandomBool()) - AddItem(new Kama()); - else - AddItem(new Tessen()); - - SetSkill(SkillName.Swords, 50.0); - SetSkill(SkillName.Tactics, 50.0); - } - - public Henchman(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a henchman"; - - public override bool AlwaysMurderer => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Ninja +{ + public class Henchman : BaseCreature + { + [Constructible] + public Henchman() : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + InitStats(45, 30, 5); + + Hue = Race.Human.RandomSkinHue(); + Body = 0x190; + + Utility.AssignRandomHair(this); + Utility.AssignRandomFacialHair(this); + + AddItem(new LeatherNinjaJacket()); + AddItem(new LeatherNinjaPants()); + AddItem(new NinjaTabi()); + + if (Utility.RandomBool()) + AddItem(new Kama()); + else + AddItem(new Tessen()); + + SetSkill(SkillName.Swords, 50.0); + SetSkill(SkillName.Tactics, 50.0); + } + + public Henchman(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a henchman"; + + public override bool AlwaysMurderer => true; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/HiddenFigure.cs b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/HiddenFigure.cs index 0de8a29c6..013fc7346 100644 --- a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/HiddenFigure.cs +++ b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/HiddenFigure.cs @@ -1,86 +1,86 @@ -using Server.Items; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.Quests.Ninja -{ - public class HiddenFigure : BaseQuester - { - public static int[] Messages = - { - 1063191, // They won�t find me here. - 1063192 // Ah, a quiet hideout. - }; - - [Constructible] - public HiddenFigure() => Message = Messages.RandomElement(); - - public HiddenFigure(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Message { get; set; } - - public override int TalkNumber => -1; - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = Race.Human.RandomSkinHue(); - - Female = Utility.RandomBool(); - - if (Female) - { - Body = 0x191; - Name = NameList.RandomName("female"); - } - else - { - Body = 0x190; - Name = NameList.RandomName("male"); - } - } - - public override void InitOutfit() - { - Utility.AssignRandomHair(this); - - AddItem(new TattsukeHakama(GetRandomHue())); - AddItem(new Kasa()); - AddItem(new HakamaShita(GetRandomHue())); - - if (Utility.RandomBool()) - AddItem(new Shoes(GetShoeHue())); - else - AddItem(new Sandals(GetShoeHue())); - } - - public override int GetAutoTalkRange(PlayerMobile pm) => 3; - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - PrivateOverheadMessage(MessageType.Regular, 0x3B2, Message, player.NetState); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(Message); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - Message = reader.ReadInt(); - } - } -} +using Server.Items; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.Quests.Ninja +{ + public class HiddenFigure : BaseQuester + { + public static int[] Messages = + { + 1063191, // They won�t find me here. + 1063192 // Ah, a quiet hideout. + }; + + [Constructible] + public HiddenFigure() => Message = Messages.RandomElement(); + + public HiddenFigure(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Message { get; set; } + + public override int TalkNumber => -1; + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = Race.Human.RandomSkinHue(); + + Female = Utility.RandomBool(); + + if (Female) + { + Body = 0x191; + Name = NameList.RandomName("female"); + } + else + { + Body = 0x190; + Name = NameList.RandomName("male"); + } + } + + public override void InitOutfit() + { + Utility.AssignRandomHair(this); + + AddItem(new TattsukeHakama(GetRandomHue())); + AddItem(new Kasa()); + AddItem(new HakamaShita(GetRandomHue())); + + if (Utility.RandomBool()) + AddItem(new Shoes(GetShoeHue())); + else + AddItem(new Sandals(GetShoeHue())); + } + + public override int GetAutoTalkRange(PlayerMobile pm) => 3; + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + PrivateOverheadMessage(MessageType.Regular, 0x3B2, Message, player.NetState); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(Message); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + Message = reader.ReadInt(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/JedahEntille.cs b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/JedahEntille.cs index 58db9f0a3..60b4b891f 100644 --- a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/JedahEntille.cs +++ b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/JedahEntille.cs @@ -1,58 +1,58 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Ninja -{ - public class JedahEntille : BaseQuester - { - [Constructible] - public JedahEntille() : base("the Silent") - { - } - - public JedahEntille(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Jedah Entille"; - - public override int TalkNumber => -1; - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = 0x83FE; - Female = true; - Body = 0x191; - } - - public override void InitOutfit() - { - HairItemID = 0x203C; - HairHue = 0x6BE; - - AddItem(new PlainDress(0x528)); - AddItem(new ThighBoots()); - AddItem(new FloppyHat()); - } - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Ninja +{ + public class JedahEntille : BaseQuester + { + [Constructible] + public JedahEntille() : base("the Silent") + { + } + + public JedahEntille(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Jedah Entille"; + + public override int TalkNumber => -1; + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = 0x83FE; + Female = true; + Body = 0x191; + } + + public override void InitOutfit() + { + HairItemID = 0x203C; + HairHue = 0x6BE; + + AddItem(new PlainDress(0x528)); + AddItem(new ThighBoots()); + AddItem(new FloppyHat()); + } + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/Zoel.cs b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/Zoel.cs index 95fe7aea2..cc5bf06f0 100644 --- a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/Zoel.cs +++ b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Mobiles/Zoel.cs @@ -1,126 +1,126 @@ -using Server.Gumps; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Ninja -{ - public class Zoel : BaseQuester - { - [Constructible] - public Zoel() : base("the Masterful Tactician") - { - } - - public Zoel(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Elite Ninja Zoel"; - - public override int TalkNumber => -1; - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = 0x83FE; - - Female = false; - Body = 0x190; - } - - public override void InitOutfit() - { - HairItemID = 0x203B; - HairHue = 0x901; - - AddItem(new HakamaShita(0x1)); - AddItem(new NinjaTabi()); - AddItem(new TattsukeHakama()); - AddItem(new Bandana()); - - AddItem(new LeatherNinjaBelt()); - - Tekagi tekagi = new Tekagi(); - tekagi.Movable = false; - AddItem(tekagi); - } - - public override int GetAutoTalkRange(PlayerMobile pm) => 2; - - public override bool CanTalkTo(PlayerMobile to) => to.Quest is EminosUndertakingQuest; - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - QuestSystem qs = player.Quest; - - if (qs is EminosUndertakingQuest) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - obj.Complete(); - } - } - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (from is PlayerMobile player) - { - QuestSystem qs = player.Quest; - - if (qs is EminosUndertakingQuest) - if (dropped is NoteForZoel) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - dropped.Delete(); - obj.Complete(); - return true; - } - } - } - - return base.OnDragDrop(from, dropped); - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - base.OnMovement(m, oldLocation); - - if (!m.Frozen && !m.Alive && InRange(m, 4) && !InRange(oldLocation, 4) && InLOS(m)) - { - if (m.Map?.CanFit(m.Location, 16, false, false) != true) - { - m.SendLocalizedMessage(502391); // Thou can not be resurrected there! - } - else - { - Direction = GetDirectionTo(m); - - m.PlaySound(0x214); - m.FixedEffect(0x376A, 10, 16); - - m.CloseGump(); - m.SendGump(new ResurrectGump(m, ResurrectMessage.Healer)); - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Gumps; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Ninja +{ + public class Zoel : BaseQuester + { + [Constructible] + public Zoel() : base("the Masterful Tactician") + { + } + + public Zoel(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Elite Ninja Zoel"; + + public override int TalkNumber => -1; + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = 0x83FE; + + Female = false; + Body = 0x190; + } + + public override void InitOutfit() + { + HairItemID = 0x203B; + HairHue = 0x901; + + AddItem(new HakamaShita(0x1)); + AddItem(new NinjaTabi()); + AddItem(new TattsukeHakama()); + AddItem(new Bandana()); + + AddItem(new LeatherNinjaBelt()); + + var tekagi = new Tekagi(); + tekagi.Movable = false; + AddItem(tekagi); + } + + public override int GetAutoTalkRange(PlayerMobile pm) => 2; + + public override bool CanTalkTo(PlayerMobile to) => to.Quest is EminosUndertakingQuest; + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + var qs = player.Quest; + + if (qs is EminosUndertakingQuest) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + obj.Complete(); + } + } + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (from is PlayerMobile player) + { + var qs = player.Quest; + + if (qs is EminosUndertakingQuest) + if (dropped is NoteForZoel) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + dropped.Delete(); + obj.Complete(); + return true; + } + } + } + + return base.OnDragDrop(from, dropped); + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + base.OnMovement(m, oldLocation); + + if (!m.Frozen && !m.Alive && InRange(m, 4) && !InRange(oldLocation, 4) && InLOS(m)) + { + if (m.Map?.CanFit(m.Location, 16, false, false) != true) + { + m.SendLocalizedMessage(502391); // Thou can not be resurrected there! + } + else + { + Direction = GetDirectionTo(m); + + m.PlaySound(0x214); + m.FixedEffect(0x376A, 10, 16); + + m.CloseGump(); + m.SendGump(new ResurrectGump(m, ResurrectMessage.Healer)); + } + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Objectives.cs b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Objectives.cs index 769618ce0..980c1061c 100644 --- a/Projects/UOContent/Engines/Quests/Emino's Undertaking/Objectives.cs +++ b/Projects/UOContent/Engines/Quests/Emino's Undertaking/Objectives.cs @@ -1,218 +1,218 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Ninja -{ - public class FindEminoBeginObjective : QuestObjective - { - public override object Message => 1063174; - - public override void OnComplete() - { - System.AddConversation(new FindZoelConversation()); - } - } - - public class FindZoelObjective : QuestObjective - { - public override object Message => 1063176; - - public override void OnComplete() - { - System.AddConversation(new EnterCaveConversation()); - } - } - - public class EnterCaveObjective : QuestObjective - { - public override object Message => 1063179; - - public override void CheckProgress() - { - if (System.From.Map == Map.Malas && System.From.InRange(new Point3D(406, 1141, 0), 2)) - Complete(); - } - - public override void OnComplete() - { - System.AddConversation(new SneakPastGuardiansConversation()); - } - } - - public class SneakPastGuardiansObjective : QuestObjective - { - public bool TaughtHowToUseSkills { get; set; } - - public override object Message => 1063261; - - public override void CheckProgress() - { - if (System.From.Map == Map.Malas && System.From.InRange(new Point3D(412, 1123, 0), 3)) - Complete(); - } - - public override void OnComplete() - { - System.AddConversation(new UseTeleporterConversation()); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - TaughtHowToUseSkills = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(TaughtHowToUseSkills); - } - } - - public class UseTeleporterObjective : QuestObjective - { - public override object Message => 1063183; - - public override void OnComplete() - { - System.AddConversation(new GiveZoelNoteConversation()); - } - } - - public class GiveZoelNoteObjective : QuestObjective - { - public override object Message => 1063185; - - public override void OnComplete() - { - System.AddConversation(new GainInnInformationConversation()); - } - } - - public class GainInnInformationObjective : QuestObjective - { - public override object Message => 1063190; - - public override void CheckProgress() - { - Mobile from = System.From; - - if (from.Map == Map.Malas && from.X > 399 && from.X < 408 && from.Y > 1091 && from.Y < 1099) - Complete(); - } - - public override void OnComplete() - { - System.AddConversation(new ReturnFromInnConversation()); - } - } - - public class ReturnFromInnObjective : QuestObjective - { - public override object Message => 1063197; - - public override void OnComplete() - { - System.AddConversation(new SearchForSwordConversation()); - } - } - - public class SearchForSwordObjective : QuestObjective - { - public override object Message => 1063200; - - public override void OnComplete() - { - System.AddConversation(new HallwayWalkConversation()); - } - } - - public class HallwayWalkObjective : QuestObjective - { - public bool StolenTreasure { get; set; } - - public override object Message => 1063202; - - public override void OnComplete() - { - System.AddConversation(new ReturnSwordConversation()); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - StolenTreasure = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(StolenTreasure); - } - } - - public class ReturnSwordObjective : QuestObjective - { - public override object Message => 1063204; - - public override void CheckProgress() - { - Mobile from = System.From; - - if (from.Map != Map.Malas || from.Y > 992) - Complete(); - } - - public override void OnComplete() - { - System.AddConversation(new SlayHenchmenConversation()); - } - } - - public class SlayHenchmenObjective : QuestObjective - { - public override object Message => 1063206; - - public override int MaxProgress => 3; - - public override void RenderProgress(BaseQuestGump gump) - { - if (!Completed) - { - // Henchmen killed: - gump.AddHtmlLocalized(70, 260, 270, 100, 1063207, BaseQuestGump.Blue); - gump.AddLabel(70, 280, 0x64, CurProgress.ToString()); - gump.AddLabel(100, 280, 0x64, "/"); - gump.AddLabel(130, 280, 0x64, MaxProgress.ToString()); - } - else - { - base.RenderProgress(gump); - } - } - - public override void OnKill(BaseCreature creature, Container corpse) - { - if (creature is Henchman) - CurProgress++; - } - - public override void OnComplete() - { - System.AddConversation(new GiveEminoSwordConversation()); - } - } - - public class GiveEminoSwordObjective : QuestObjective - { - public override object Message => 1063210; - - public override void OnComplete() - { - } - } -} \ No newline at end of file +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Ninja +{ + public class FindEminoBeginObjective : QuestObjective + { + public override object Message => 1063174; + + public override void OnComplete() + { + System.AddConversation(new FindZoelConversation()); + } + } + + public class FindZoelObjective : QuestObjective + { + public override object Message => 1063176; + + public override void OnComplete() + { + System.AddConversation(new EnterCaveConversation()); + } + } + + public class EnterCaveObjective : QuestObjective + { + public override object Message => 1063179; + + public override void CheckProgress() + { + if (System.From.Map == Map.Malas && System.From.InRange(new Point3D(406, 1141, 0), 2)) + Complete(); + } + + public override void OnComplete() + { + System.AddConversation(new SneakPastGuardiansConversation()); + } + } + + public class SneakPastGuardiansObjective : QuestObjective + { + public bool TaughtHowToUseSkills { get; set; } + + public override object Message => 1063261; + + public override void CheckProgress() + { + if (System.From.Map == Map.Malas && System.From.InRange(new Point3D(412, 1123, 0), 3)) + Complete(); + } + + public override void OnComplete() + { + System.AddConversation(new UseTeleporterConversation()); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + TaughtHowToUseSkills = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(TaughtHowToUseSkills); + } + } + + public class UseTeleporterObjective : QuestObjective + { + public override object Message => 1063183; + + public override void OnComplete() + { + System.AddConversation(new GiveZoelNoteConversation()); + } + } + + public class GiveZoelNoteObjective : QuestObjective + { + public override object Message => 1063185; + + public override void OnComplete() + { + System.AddConversation(new GainInnInformationConversation()); + } + } + + public class GainInnInformationObjective : QuestObjective + { + public override object Message => 1063190; + + public override void CheckProgress() + { + Mobile from = System.From; + + if (from.Map == Map.Malas && from.X > 399 && from.X < 408 && from.Y > 1091 && from.Y < 1099) + Complete(); + } + + public override void OnComplete() + { + System.AddConversation(new ReturnFromInnConversation()); + } + } + + public class ReturnFromInnObjective : QuestObjective + { + public override object Message => 1063197; + + public override void OnComplete() + { + System.AddConversation(new SearchForSwordConversation()); + } + } + + public class SearchForSwordObjective : QuestObjective + { + public override object Message => 1063200; + + public override void OnComplete() + { + System.AddConversation(new HallwayWalkConversation()); + } + } + + public class HallwayWalkObjective : QuestObjective + { + public bool StolenTreasure { get; set; } + + public override object Message => 1063202; + + public override void OnComplete() + { + System.AddConversation(new ReturnSwordConversation()); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + StolenTreasure = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(StolenTreasure); + } + } + + public class ReturnSwordObjective : QuestObjective + { + public override object Message => 1063204; + + public override void CheckProgress() + { + Mobile from = System.From; + + if (from.Map != Map.Malas || from.Y > 992) + Complete(); + } + + public override void OnComplete() + { + System.AddConversation(new SlayHenchmenConversation()); + } + } + + public class SlayHenchmenObjective : QuestObjective + { + public override object Message => 1063206; + + public override int MaxProgress => 3; + + public override void RenderProgress(BaseQuestGump gump) + { + if (!Completed) + { + // Henchmen killed: + gump.AddHtmlLocalized(70, 260, 270, 100, 1063207, BaseQuestGump.Blue); + gump.AddLabel(70, 280, 0x64, CurProgress.ToString()); + gump.AddLabel(100, 280, 0x64, "/"); + gump.AddLabel(130, 280, 0x64, MaxProgress.ToString()); + } + else + { + base.RenderProgress(gump); + } + } + + public override void OnKill(BaseCreature creature, Container corpse) + { + if (creature is Henchman) + CurProgress++; + } + + public override void OnComplete() + { + System.AddConversation(new GiveEminoSwordConversation()); + } + } + + public class GiveEminoSwordObjective : QuestObjective + { + public override object Message => 1063210; + + public override void OnComplete() + { + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Haochi's Trials/Conversations.cs b/Projects/UOContent/Engines/Quests/Haochi's Trials/Conversations.cs index 5e7d0010e..e3abd7792 100644 --- a/Projects/UOContent/Engines/Quests/Haochi's Trials/Conversations.cs +++ b/Projects/UOContent/Engines/Quests/Haochi's Trials/Conversations.cs @@ -1,359 +1,359 @@ -namespace Server.Engines.Quests.Samurai -{ - public class AcceptConversation : QuestConversation - { - public override object Message => 1049092; - - public override void OnRead() - { - System.AddObjective(new FindHaochiObjective()); - } - } - - public class RadarConversation : QuestConversation - { - public override object Message => 1063033; - - public override bool Logged => false; - } - - public class FirstTrialIntroConversation : QuestConversation - { - public override object Message => 1063029; - - public override void OnRead() - { - System.AddObjective(new FirstTrialIntroObjective()); - } - } - - public class FirstTrialKillConversation : QuestConversation - { - public override object Message => 1063031; - - public override void OnRead() - { - System.AddObjective(new FirstTrialKillObjective()); - } - } - - public class GainKarmaConversation : QuestConversation - { - private bool m_CursedSoul; - - public GainKarmaConversation(bool cursedSoul) => m_CursedSoul = cursedSoul; - - public GainKarmaConversation() - { - } - - public override object Message - { - get - { - if (m_CursedSoul) return 1063040; - - // You have just gained some Karma for killing a Young Ronin. - return 1063041; - } - } - - public override bool Logged => false; - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_CursedSoul = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(m_CursedSoul); - } - } - - public class SecondTrialIntroConversation : QuestConversation - { - private bool m_CursedSoul; - - public SecondTrialIntroConversation(bool cursedSoul) => m_CursedSoul = cursedSoul; - - public SecondTrialIntroConversation() - { - } - - public override object Message - { - get - { - if (m_CursedSoul) return 1063045; - - /* It is good that you rid the land of those dishonorable Samurai. - * Perhaps they will learn a greater lesson in death.

- * - * I have placed a reward in your pack.

- * - * The second trial will test your courage. You only have to follow - * the yellow path to see what awaits you. - */ - return 1063046; - } - } - - public override void OnRead() - { - System.AddObjective(new SecondTrialIntroObjective()); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_CursedSoul = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(m_CursedSoul); - } - } - - public class SecondTrialAttackConversation : QuestConversation - { - public override object Message => 1063057; - - public override void OnRead() - { - System.AddObjective(new SecondTrialAttackObjective()); - } - } - - public class ThirdTrialIntroConversation : QuestConversation - { - private bool m_Dragon; - - public ThirdTrialIntroConversation(bool dragon) => m_Dragon = dragon; - - public ThirdTrialIntroConversation() - { - } - - public override object Message - { - get - { - if (m_Dragon) return 1063060; - - /* Fear remains in your eyes but you have learned that not all is - * what it appears to be.

- * - * You must have known the dragon would slay you instantly. - * You elected the weaker opponent though the imp did not come - * here to destroy. You have much to learn.

- * - * In these lands, death is not forever. The shrines can make you whole - * again as can a helpful mage or healer.

- * - * Seek them out when you have been mortally wounded.

- * - * The next trial will test your benevolence. You only have to walk the blue path. - */ - return 1063059; - } - } - - public override void OnRead() - { - System.AddObjective(new ThirdTrialIntroObjective()); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_Dragon = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(m_Dragon); - } - } - - public class ThirdTrialKillConversation : QuestConversation - { - public override object Message => 1063062; - - public override void OnRead() - { - System.AddObjective(new ThirdTrialKillObjective()); - } - } - - public class FourthTrialIntroConversation : QuestConversation - { - public override object Message => 1063065; - - public override void OnRead() - { - System.AddObjective(new FourthTrialIntroObjective()); - } - } - - public class FourthTrialCatsConversation : QuestConversation - { - public override object Message => 1063067; - - public override void OnRead() - { - System.AddObjective(new FourthTrialCatsObjective()); - } - } - - public class FifthTrialIntroConversation : QuestConversation - { - private bool m_KilledCat; - - public FifthTrialIntroConversation(bool killedCat) => m_KilledCat = killedCat; - - public FifthTrialIntroConversation() - { - } - - public override object Message - { - get - { - if (m_KilledCat) return 1063071; - - /* You showed respect by helping another out while allowing the gypsy - * what little dignity she has left.

- * - * Now she will be able to feed herself and gain enough energy to walk - * to her camp.

- * - * The cats are her family members� cursed by an evil mage.

- * - * Once she has enough strength to walk back to the camp, she will be - * able to undo the spell.

- * - * You have been rewarded for completing your trial. And now you must - * prove yourself again.

Please retrieve my katana from the - * treasure room and return it to me. - */ - return 1063070; - } - } - - public override void OnRead() - { - System.AddObjective(new FifthTrialIntroObjective()); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_KilledCat = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(m_KilledCat); - } - } - - public class FifthTrialReturnConversation : QuestConversation - { - public override object Message => 1063248; - - public override void OnRead() - { - System.AddObjective(new FifthTrialReturnObjective()); - } - } - - public class LostSwordConversation : QuestConversation - { - public override object Message => 1063074; - - public override bool Logged => false; - } - - public class SixthTrialIntroConversation : QuestConversation - { - private bool m_StolenTreasure; - - public SixthTrialIntroConversation(bool stolenTreasure) => m_StolenTreasure = stolenTreasure; - - public SixthTrialIntroConversation() - { - } - - public override object Message - { - get - { - if (m_StolenTreasure) return 1063077; - - /* Thank you for returning this sword to me and leaving the remaining - * treasure alone.

- * - * Your training is nearly complete. Before you have your final trial, - * you should pay homage to Samurai who came before you.

- * - * Go into the Altar Room and light a candle for them. Afterwards, return to me. - */ - return 1063076; - } - } - - public override void OnRead() - { - System.AddObjective(new SixthTrialIntroObjective()); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_StolenTreasure = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(m_StolenTreasure); - } - } - - public class SeventhTrialIntroConversation : QuestConversation - { - public override object Message => 1063079; - - public override void OnRead() - { - System.AddObjective(new SeventhTrialIntroObjective()); - } - } - - public class EndConversation : QuestConversation - { - public override object Message => 1063125; - - public override void OnRead() - { - System.Complete(); - } - } -} \ No newline at end of file +namespace Server.Engines.Quests.Samurai +{ + public class AcceptConversation : QuestConversation + { + public override object Message => 1049092; + + public override void OnRead() + { + System.AddObjective(new FindHaochiObjective()); + } + } + + public class RadarConversation : QuestConversation + { + public override object Message => 1063033; + + public override bool Logged => false; + } + + public class FirstTrialIntroConversation : QuestConversation + { + public override object Message => 1063029; + + public override void OnRead() + { + System.AddObjective(new FirstTrialIntroObjective()); + } + } + + public class FirstTrialKillConversation : QuestConversation + { + public override object Message => 1063031; + + public override void OnRead() + { + System.AddObjective(new FirstTrialKillObjective()); + } + } + + public class GainKarmaConversation : QuestConversation + { + private bool m_CursedSoul; + + public GainKarmaConversation(bool cursedSoul) => m_CursedSoul = cursedSoul; + + public GainKarmaConversation() + { + } + + public override object Message + { + get + { + if (m_CursedSoul) return 1063040; + + // You have just gained some Karma for killing a Young Ronin. + return 1063041; + } + } + + public override bool Logged => false; + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_CursedSoul = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(m_CursedSoul); + } + } + + public class SecondTrialIntroConversation : QuestConversation + { + private bool m_CursedSoul; + + public SecondTrialIntroConversation(bool cursedSoul) => m_CursedSoul = cursedSoul; + + public SecondTrialIntroConversation() + { + } + + public override object Message + { + get + { + if (m_CursedSoul) return 1063045; + + /* It is good that you rid the land of those dishonorable Samurai. + * Perhaps they will learn a greater lesson in death.

+ * + * I have placed a reward in your pack.

+ * + * The second trial will test your courage. You only have to follow + * the yellow path to see what awaits you. + */ + return 1063046; + } + } + + public override void OnRead() + { + System.AddObjective(new SecondTrialIntroObjective()); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_CursedSoul = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(m_CursedSoul); + } + } + + public class SecondTrialAttackConversation : QuestConversation + { + public override object Message => 1063057; + + public override void OnRead() + { + System.AddObjective(new SecondTrialAttackObjective()); + } + } + + public class ThirdTrialIntroConversation : QuestConversation + { + private bool m_Dragon; + + public ThirdTrialIntroConversation(bool dragon) => m_Dragon = dragon; + + public ThirdTrialIntroConversation() + { + } + + public override object Message + { + get + { + if (m_Dragon) return 1063060; + + /* Fear remains in your eyes but you have learned that not all is + * what it appears to be.

+ * + * You must have known the dragon would slay you instantly. + * You elected the weaker opponent though the imp did not come + * here to destroy. You have much to learn.

+ * + * In these lands, death is not forever. The shrines can make you whole + * again as can a helpful mage or healer.

+ * + * Seek them out when you have been mortally wounded.

+ * + * The next trial will test your benevolence. You only have to walk the blue path. + */ + return 1063059; + } + } + + public override void OnRead() + { + System.AddObjective(new ThirdTrialIntroObjective()); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_Dragon = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(m_Dragon); + } + } + + public class ThirdTrialKillConversation : QuestConversation + { + public override object Message => 1063062; + + public override void OnRead() + { + System.AddObjective(new ThirdTrialKillObjective()); + } + } + + public class FourthTrialIntroConversation : QuestConversation + { + public override object Message => 1063065; + + public override void OnRead() + { + System.AddObjective(new FourthTrialIntroObjective()); + } + } + + public class FourthTrialCatsConversation : QuestConversation + { + public override object Message => 1063067; + + public override void OnRead() + { + System.AddObjective(new FourthTrialCatsObjective()); + } + } + + public class FifthTrialIntroConversation : QuestConversation + { + private bool m_KilledCat; + + public FifthTrialIntroConversation(bool killedCat) => m_KilledCat = killedCat; + + public FifthTrialIntroConversation() + { + } + + public override object Message + { + get + { + if (m_KilledCat) return 1063071; + + /* You showed respect by helping another out while allowing the gypsy + * what little dignity she has left.

+ * + * Now she will be able to feed herself and gain enough energy to walk + * to her camp.

+ * + * The cats are her family members� cursed by an evil mage.

+ * + * Once she has enough strength to walk back to the camp, she will be + * able to undo the spell.

+ * + * You have been rewarded for completing your trial. And now you must + * prove yourself again.

Please retrieve my katana from the + * treasure room and return it to me. + */ + return 1063070; + } + } + + public override void OnRead() + { + System.AddObjective(new FifthTrialIntroObjective()); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_KilledCat = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(m_KilledCat); + } + } + + public class FifthTrialReturnConversation : QuestConversation + { + public override object Message => 1063248; + + public override void OnRead() + { + System.AddObjective(new FifthTrialReturnObjective()); + } + } + + public class LostSwordConversation : QuestConversation + { + public override object Message => 1063074; + + public override bool Logged => false; + } + + public class SixthTrialIntroConversation : QuestConversation + { + private bool m_StolenTreasure; + + public SixthTrialIntroConversation(bool stolenTreasure) => m_StolenTreasure = stolenTreasure; + + public SixthTrialIntroConversation() + { + } + + public override object Message + { + get + { + if (m_StolenTreasure) return 1063077; + + /* Thank you for returning this sword to me and leaving the remaining + * treasure alone.

+ * + * Your training is nearly complete. Before you have your final trial, + * you should pay homage to Samurai who came before you.

+ * + * Go into the Altar Room and light a candle for them. Afterwards, return to me. + */ + return 1063076; + } + } + + public override void OnRead() + { + System.AddObjective(new SixthTrialIntroObjective()); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_StolenTreasure = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(m_StolenTreasure); + } + } + + public class SeventhTrialIntroConversation : QuestConversation + { + public override object Message => 1063079; + + public override void OnRead() + { + System.AddObjective(new SeventhTrialIntroObjective()); + } + } + + public class EndConversation : QuestConversation + { + public override object Message => 1063125; + + public override void OnRead() + { + System.Complete(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Haochi's Trials/HaochisTrialsQuest.cs b/Projects/UOContent/Engines/Quests/Haochi's Trials/HaochisTrialsQuest.cs index b833106af..bb43950ff 100644 --- a/Projects/UOContent/Engines/Quests/Haochi's Trials/HaochisTrialsQuest.cs +++ b/Projects/UOContent/Engines/Quests/Haochi's Trials/HaochisTrialsQuest.cs @@ -1,117 +1,117 @@ -using System; -using Server.Mobiles; - -namespace Server.Engines.Quests.Samurai -{ - public class HaochisTrialsQuest : QuestSystem - { - private static readonly Type[] m_TypeReferenceTable = - { - typeof(AcceptConversation), - typeof(RadarConversation), - typeof(FirstTrialIntroConversation), - typeof(FirstTrialKillConversation), - typeof(GainKarmaConversation), - typeof(SecondTrialIntroConversation), - typeof(SecondTrialAttackConversation), - typeof(ThirdTrialIntroConversation), - typeof(ThirdTrialKillConversation), - typeof(FourthTrialIntroConversation), - typeof(FourthTrialCatsConversation), - typeof(FifthTrialIntroConversation), - typeof(FifthTrialReturnConversation), - typeof(LostSwordConversation), - typeof(SixthTrialIntroConversation), - typeof(SeventhTrialIntroConversation), - typeof(EndConversation), - typeof(FindHaochiObjective), - typeof(FirstTrialIntroObjective), - typeof(FirstTrialKillObjective), - typeof(FirstTrialReturnObjective), - typeof(SecondTrialIntroObjective), - typeof(SecondTrialAttackObjective), - typeof(SecondTrialReturnObjective), - typeof(ThirdTrialIntroObjective), - typeof(ThirdTrialKillObjective), - typeof(ThirdTrialReturnObjective), - typeof(FourthTrialIntroObjective), - typeof(FourthTrialCatsObjective), - typeof(FourthTrialReturnObjective), - typeof(FifthTrialIntroObjective), - typeof(FifthTrialReturnObjective), - typeof(SixthTrialIntroObjective), - typeof(SixthTrialReturnObjective), - typeof(SeventhTrialIntroObjective), - typeof(SeventhTrialReturnObjective) - }; - - private bool m_SentRadarConversion; - - public HaochisTrialsQuest(PlayerMobile from) : base(from) - { - } - - // Serialization - public HaochisTrialsQuest() - { - } - - public override Type[] TypeReferenceTable => m_TypeReferenceTable; - - public override object Name => 1063022; - - public override object OfferMessage => 1063023; - - public override TimeSpan RestartDelay => TimeSpan.MaxValue; - public override bool IsTutorial => true; - - public override int Picture => 0x15D7; - - public override void Accept() - { - base.Accept(); - - AddConversation(new AcceptConversation()); - } - - public override void Slice() - { - if (!m_SentRadarConversion && - (From.Map != Map.Malas || From.X < 360 || From.X > 400 || From.Y < 760 || From.Y > 780)) - { - m_SentRadarConversion = true; - AddConversation(new RadarConversation()); - } - - base.Slice(); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_SentRadarConversion = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(m_SentRadarConversion); - } - - public static bool HasLostHaochisKatana(Mobile from) - { - if (!(from is PlayerMobile pm)) - return false; - - QuestSystem qs = pm.Quest; - - if (qs is HaochisTrialsQuest) - if (qs.IsObjectiveInProgress(typeof(FifthTrialReturnObjective))) - return from.Backpack?.FindItemByType() == null; - - return false; - } - } -} \ No newline at end of file +using System; +using Server.Mobiles; + +namespace Server.Engines.Quests.Samurai +{ + public class HaochisTrialsQuest : QuestSystem + { + private static readonly Type[] m_TypeReferenceTable = + { + typeof(AcceptConversation), + typeof(RadarConversation), + typeof(FirstTrialIntroConversation), + typeof(FirstTrialKillConversation), + typeof(GainKarmaConversation), + typeof(SecondTrialIntroConversation), + typeof(SecondTrialAttackConversation), + typeof(ThirdTrialIntroConversation), + typeof(ThirdTrialKillConversation), + typeof(FourthTrialIntroConversation), + typeof(FourthTrialCatsConversation), + typeof(FifthTrialIntroConversation), + typeof(FifthTrialReturnConversation), + typeof(LostSwordConversation), + typeof(SixthTrialIntroConversation), + typeof(SeventhTrialIntroConversation), + typeof(EndConversation), + typeof(FindHaochiObjective), + typeof(FirstTrialIntroObjective), + typeof(FirstTrialKillObjective), + typeof(FirstTrialReturnObjective), + typeof(SecondTrialIntroObjective), + typeof(SecondTrialAttackObjective), + typeof(SecondTrialReturnObjective), + typeof(ThirdTrialIntroObjective), + typeof(ThirdTrialKillObjective), + typeof(ThirdTrialReturnObjective), + typeof(FourthTrialIntroObjective), + typeof(FourthTrialCatsObjective), + typeof(FourthTrialReturnObjective), + typeof(FifthTrialIntroObjective), + typeof(FifthTrialReturnObjective), + typeof(SixthTrialIntroObjective), + typeof(SixthTrialReturnObjective), + typeof(SeventhTrialIntroObjective), + typeof(SeventhTrialReturnObjective) + }; + + private bool m_SentRadarConversion; + + public HaochisTrialsQuest(PlayerMobile from) : base(from) + { + } + + // Serialization + public HaochisTrialsQuest() + { + } + + public override Type[] TypeReferenceTable => m_TypeReferenceTable; + + public override object Name => 1063022; + + public override object OfferMessage => 1063023; + + public override TimeSpan RestartDelay => TimeSpan.MaxValue; + public override bool IsTutorial => true; + + public override int Picture => 0x15D7; + + public override void Accept() + { + base.Accept(); + + AddConversation(new AcceptConversation()); + } + + public override void Slice() + { + if (!m_SentRadarConversion && + (From.Map != Map.Malas || From.X < 360 || From.X > 400 || From.Y < 760 || From.Y > 780)) + { + m_SentRadarConversion = true; + AddConversation(new RadarConversation()); + } + + base.Slice(); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_SentRadarConversion = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(m_SentRadarConversion); + } + + public static bool HasLostHaochisKatana(Mobile from) + { + if (!(from is PlayerMobile pm)) + return false; + + var qs = pm.Quest; + + if (qs is HaochisTrialsQuest) + if (qs.IsObjectiveInProgress(typeof(FifthTrialReturnObjective))) + return from.Backpack?.FindItemByType() == null; + + return false; + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Haochi's Trials/Items/HaochisKatana.cs b/Projects/UOContent/Engines/Quests/Haochi's Trials/Items/HaochisKatana.cs index 2f8d4cba8..b9992bcde 100644 --- a/Projects/UOContent/Engines/Quests/Haochi's Trials/Items/HaochisKatana.cs +++ b/Projects/UOContent/Engines/Quests/Haochi's Trials/Items/HaochisKatana.cs @@ -1,32 +1,32 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Samurai -{ - public class HaochisKatana : QuestItem - { - [Constructible] - public HaochisKatana() : base(0x13FF) => Weight = 1.0; - - public HaochisKatana(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1063165; // Daimyo Haochi's Katana - - public override bool CanDrop(PlayerMobile player) => !(player.Quest is HaochisTrialsQuest); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Samurai +{ + public class HaochisKatana : QuestItem + { + [Constructible] + public HaochisKatana() : base(0x13FF) => Weight = 1.0; + + public HaochisKatana(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1063165; // Daimyo Haochi's Katana + + public override bool CanDrop(PlayerMobile player) => !(player.Quest is HaochisTrialsQuest); + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Haochi's Trials/Items/HaochisKatanaGenerator.cs b/Projects/UOContent/Engines/Quests/Haochi's Trials/Items/HaochisKatanaGenerator.cs index 219f957e0..1ca2d2c9d 100644 --- a/Projects/UOContent/Engines/Quests/Haochi's Trials/Items/HaochisKatanaGenerator.cs +++ b/Projects/UOContent/Engines/Quests/Haochi's Trials/Items/HaochisKatanaGenerator.cs @@ -1,79 +1,81 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Samurai -{ - public class HaochisKatanaGenerator : Item - { - [Constructible] - public HaochisKatanaGenerator() : base(0x1B7B) - { - Visible = false; - Movable = false; - } - - public HaochisKatanaGenerator(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Haochi's katana generator"; - - public override bool OnMoveOver(Mobile m) - { - if (m is PlayerMobile player) - { - QuestSystem qs = player.Quest; - - if (qs is HaochisTrialsQuest) - { - if (HaochisTrialsQuest.HasLostHaochisKatana(player)) - { - Item katana = new HaochisKatana(); - - if (!player.PlaceInBackpack(katana)) - { - katana.Delete(); - player.SendLocalizedMessage( - 1046260); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. - } - } - else - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - Item katana = new HaochisKatana(); - - if (player.PlaceInBackpack(katana)) - { - obj.Complete(); - } - else - { - katana.Delete(); - player.SendLocalizedMessage( - 1046260); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. - } - } - } - } - } - - return base.OnMoveOver(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Samurai +{ + public class HaochisKatanaGenerator : Item + { + [Constructible] + public HaochisKatanaGenerator() : base(0x1B7B) + { + Visible = false; + Movable = false; + } + + public HaochisKatanaGenerator(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Haochi's katana generator"; + + public override bool OnMoveOver(Mobile m) + { + if (m is PlayerMobile player) + { + var qs = player.Quest; + + if (qs is HaochisTrialsQuest) + { + if (HaochisTrialsQuest.HasLostHaochisKatana(player)) + { + Item katana = new HaochisKatana(); + + if (!player.PlaceInBackpack(katana)) + { + katana.Delete(); + player.SendLocalizedMessage( + 1046260 + ); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. + } + } + else + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + Item katana = new HaochisKatana(); + + if (player.PlaceInBackpack(katana)) + { + obj.Complete(); + } + else + { + katana.Delete(); + player.SendLocalizedMessage( + 1046260 + ); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. + } + } + } + } + } + + return base.OnMoveOver(m); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Haochi's Trials/Items/HaochisTreasureChest.cs b/Projects/UOContent/Engines/Quests/Haochi's Trials/Items/HaochisTreasureChest.cs index a632ed999..38d95fbc5 100644 --- a/Projects/UOContent/Engines/Quests/Haochi's Trials/Items/HaochisTreasureChest.cs +++ b/Projects/UOContent/Engines/Quests/Haochi's Trials/Items/HaochisTreasureChest.cs @@ -1,90 +1,92 @@ -using System; -using Server.Items; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.Quests.Samurai -{ - public class HaochisTreasureChest : WoodenFootLocker - { - [Constructible] - public HaochisTreasureChest() - { - Movable = false; - - GenerateTreasure(); - } - - public HaochisTreasureChest(Serial serial) : base(serial) - { - } - - public override bool IsDecoContainer => false; - - private void GenerateTreasure() - { - for (int i = Items.Count - 1; i >= 0; i--) - Items[i].Delete(); - - for (int i = 0; i < 75; i++) - DropItem( - Utility.Random(10) switch - { - 0 => new GoldBracelet(), - 1 => new GoldRing(), - _ => Loot.RandomGem() // 2 - } - ); - } - - public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight) => false; - - public override bool CheckItemUse(Mobile from, Item item) => item == this; - - public override bool CheckLift(Mobile from, Item item, ref LRReason reject) - { - if (from.AccessLevel >= AccessLevel.GameMaster) - return true; - - if (from is PlayerMobile player && player.Quest is HaochisTrialsQuest) - { - FifthTrialIntroObjective obj = player.Quest.FindObjective(); - if (obj?.StolenTreasure == true) - from.SendLocalizedMessage( - 1063247); // The guard is watching you carefully! It would be unwise to remove another item from here. - else - return true; - } - - return false; - } - - public override void OnItemLifted(Mobile from, Item item) - { - if (from is PlayerMobile player && player.Quest is HaochisTrialsQuest) - { - FifthTrialIntroObjective obj = player.Quest.FindObjective(); - if (obj != null) - obj.StolenTreasure = true; - } - - Timer.DelayCall(TimeSpan.FromMinutes(2.0), GenerateTreasure); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - Timer.DelayCall(GenerateTreasure); - } - } -} +using System; +using Server.Items; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.Quests.Samurai +{ + public class HaochisTreasureChest : WoodenFootLocker + { + [Constructible] + public HaochisTreasureChest() + { + Movable = false; + + GenerateTreasure(); + } + + public HaochisTreasureChest(Serial serial) : base(serial) + { + } + + public override bool IsDecoContainer => false; + + private void GenerateTreasure() + { + for (var i = Items.Count - 1; i >= 0; i--) + Items[i].Delete(); + + for (var i = 0; i < 75; i++) + DropItem( + Utility.Random(10) switch + { + 0 => new GoldBracelet(), + 1 => new GoldRing(), + _ => Loot.RandomGem() // 2 + } + ); + } + + public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight) => + false; + + public override bool CheckItemUse(Mobile from, Item item) => item == this; + + public override bool CheckLift(Mobile from, Item item, ref LRReason reject) + { + if (from.AccessLevel >= AccessLevel.GameMaster) + return true; + + if (from is PlayerMobile player && player.Quest is HaochisTrialsQuest) + { + var obj = player.Quest.FindObjective(); + if (obj?.StolenTreasure == true) + from.SendLocalizedMessage( + 1063247 + ); // The guard is watching you carefully! It would be unwise to remove another item from here. + else + return true; + } + + return false; + } + + public override void OnItemLifted(Mobile from, Item item) + { + if (from is PlayerMobile player && player.Quest is HaochisTrialsQuest) + { + var obj = player.Quest.FindObjective(); + if (obj != null) + obj.StolenTreasure = true; + } + + Timer.DelayCall(TimeSpan.FromMinutes(2.0), GenerateTreasure); + } + + 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(); + + Timer.DelayCall(GenerateTreasure); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Haochi's Trials/Items/HonorCandle.cs b/Projects/UOContent/Engines/Quests/Haochi's Trials/Items/HonorCandle.cs index 8d3afe2b2..68fb86454 100644 --- a/Projects/UOContent/Engines/Quests/Haochi's Trials/Items/HonorCandle.cs +++ b/Projects/UOContent/Engines/Quests/Haochi's Trials/Items/HonorCandle.cs @@ -1,76 +1,76 @@ -using System; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Samurai -{ - public class HonorCandle : CandleLong - { - private static readonly TimeSpan LitDuration = TimeSpan.FromSeconds(20.0); - - [Constructible] - public HonorCandle() - { - Movable = false; - Duration = LitDuration; - } - - public HonorCandle(Serial serial) : base(serial) - { - } - - public override int LitSound => 0; - public override int UnlitSound => 0; - - public override void OnDoubleClick(Mobile from) - { - bool wasBurning = Burning; - - base.OnDoubleClick(from); - - if (!wasBurning && Burning) - { - if (!(from is PlayerMobile player)) - return; - - QuestSystem qs = player.Quest; - - if (qs is HaochisTrialsQuest) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - obj.Complete(); - - SendLocalizedMessageTo(from, 1063251); // You light a candle in honor. - } - } - } - - public override void Burn() - { - Douse(); - } - - public override void Douse() - { - base.Douse(); - - Duration = LitDuration; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +using System; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Samurai +{ + public class HonorCandle : CandleLong + { + private static readonly TimeSpan LitDuration = TimeSpan.FromSeconds(20.0); + + [Constructible] + public HonorCandle() + { + Movable = false; + Duration = LitDuration; + } + + public HonorCandle(Serial serial) : base(serial) + { + } + + public override int LitSound => 0; + public override int UnlitSound => 0; + + public override void OnDoubleClick(Mobile from) + { + var wasBurning = Burning; + + base.OnDoubleClick(from); + + if (!wasBurning && Burning) + { + if (!(from is PlayerMobile player)) + return; + + var qs = player.Quest; + + if (qs is HaochisTrialsQuest) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + obj.Complete(); + + SendLocalizedMessageTo(from, 1063251); // You light a candle in honor. + } + } + } + + public override void Burn() + { + Douse(); + } + + public override void Douse() + { + base.Douse(); + + Duration = LitDuration; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/CursedSoul.cs b/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/CursedSoul.cs index e3283c9e5..5defbf092 100644 --- a/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/CursedSoul.cs +++ b/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/CursedSoul.cs @@ -1,69 +1,69 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Samurai -{ - public class CursedSoul : BaseCreature - { - [Constructible] - public CursedSoul() : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) - { - Body = 3; - BaseSoundID = 471; - - SetStr(20, 40); - SetDex(40, 60); - SetInt(15, 25); - - SetHits(10, 20); - - SetDamage(3, 7); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 15, 20); - SetResistance(ResistanceType.Fire, 8, 12); - - SetSkill(SkillName.Wrestling, 35.0, 39.0); - SetSkill(SkillName.Tactics, 5.0, 15.0); - SetSkill(SkillName.MagicResist, 10.0); - - Fame = 200; - Karma = -200; - - PackItem( - Utility.Random(10) switch - { - 0 => new LeftArm(), - 1 => new RightArm(), - 2 => new Torso(), - 3 => new Bone(), - 4 => new RibCage(), - 5 => new RibCage(), - _ => new BonePile() // 6-9 - } - ); - } - - public CursedSoul(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a cursed soul corpse"; - public override string DefaultName => "a cursed soul"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Samurai +{ + public class CursedSoul : BaseCreature + { + [Constructible] + public CursedSoul() : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 3; + BaseSoundID = 471; + + SetStr(20, 40); + SetDex(40, 60); + SetInt(15, 25); + + SetHits(10, 20); + + SetDamage(3, 7); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 15, 20); + SetResistance(ResistanceType.Fire, 8, 12); + + SetSkill(SkillName.Wrestling, 35.0, 39.0); + SetSkill(SkillName.Tactics, 5.0, 15.0); + SetSkill(SkillName.MagicResist, 10.0); + + Fame = 200; + Karma = -200; + + PackItem( + Utility.Random(10) switch + { + 0 => new LeftArm(), + 1 => new RightArm(), + 2 => new Torso(), + 3 => new Bone(), + 4 => new RibCage(), + 5 => new RibCage(), + _ => new BonePile() // 6-9 + } + ); + } + + public CursedSoul(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a cursed soul corpse"; + public override string DefaultName => "a cursed soul"; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/DeadlyImp.cs b/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/DeadlyImp.cs index b3af42884..bc5cd2092 100644 --- a/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/DeadlyImp.cs +++ b/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/DeadlyImp.cs @@ -1,79 +1,79 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Samurai -{ - public class DeadlyImp : BaseCreature - { - [Constructible] - public DeadlyImp() : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) - { - Body = 74; - BaseSoundID = 422; - Hue = 0x66A; - - SetStr(91, 115); - SetDex(61, 80); - SetInt(86, 105); - - SetHits(1000); - - SetDamage(50, 80); - - SetDamageType(ResistanceType.Fire, 100); - - SetResistance(ResistanceType.Physical, 95, 98); - SetResistance(ResistanceType.Fire, 95, 98); - SetResistance(ResistanceType.Cold, 95, 98); - SetResistance(ResistanceType.Poison, 95, 98); - SetResistance(ResistanceType.Energy, 95, 98); - - SetSkill(SkillName.Magery, 120.0); - SetSkill(SkillName.Tactics, 120.0); - SetSkill(SkillName.Wrestling, 120.0); - - Fame = 2500; - Karma = -2500; - - CantWalk = true; - } - - public DeadlyImp(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a deadly imp"; - - public override void AggressiveAction(Mobile aggressor, bool criminal) - { - base.AggressiveAction(aggressor, criminal); - - if (aggressor is PlayerMobile player) - { - QuestSystem qs = player.Quest; - if (qs is HaochisTrialsQuest) - { - QuestObjective obj = qs.FindObjective(); - if (obj?.Completed == false) - { - obj.Complete(); - qs.AddObjective(new SecondTrialReturnObjective(false)); - } - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Samurai +{ + public class DeadlyImp : BaseCreature + { + [Constructible] + public DeadlyImp() : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 74; + BaseSoundID = 422; + Hue = 0x66A; + + SetStr(91, 115); + SetDex(61, 80); + SetInt(86, 105); + + SetHits(1000); + + SetDamage(50, 80); + + SetDamageType(ResistanceType.Fire, 100); + + SetResistance(ResistanceType.Physical, 95, 98); + SetResistance(ResistanceType.Fire, 95, 98); + SetResistance(ResistanceType.Cold, 95, 98); + SetResistance(ResistanceType.Poison, 95, 98); + SetResistance(ResistanceType.Energy, 95, 98); + + SetSkill(SkillName.Magery, 120.0); + SetSkill(SkillName.Tactics, 120.0); + SetSkill(SkillName.Wrestling, 120.0); + + Fame = 2500; + Karma = -2500; + + CantWalk = true; + } + + public DeadlyImp(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a deadly imp"; + + public override void AggressiveAction(Mobile aggressor, bool criminal) + { + base.AggressiveAction(aggressor, criminal); + + if (aggressor is PlayerMobile player) + { + var qs = player.Quest; + if (qs is HaochisTrialsQuest) + { + QuestObjective obj = qs.FindObjective(); + if (obj?.Completed == false) + { + obj.Complete(); + qs.AddObjective(new SecondTrialReturnObjective(false)); + } + } + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/DiseasedCat.cs b/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/DiseasedCat.cs index 8f929d979..3b135a242 100644 --- a/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/DiseasedCat.cs +++ b/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/DiseasedCat.cs @@ -1,56 +1,56 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Samurai -{ - public class DiseasedCat : BaseCreature - { - [Constructible] - public DiseasedCat() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) - { - Body = 0xC9; - Hue = Utility.RandomAnimalHue(); - BaseSoundID = 0x69; - - SetStr(9); - SetDex(35); - SetInt(5); - - SetHits(6); - SetMana(0); - - SetDamage(1); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 5, 10); - - SetSkill(SkillName.MagicResist, 5.0); - SetSkill(SkillName.Tactics, 4.0); - SetSkill(SkillName.Wrestling, 5.0); - - VirtualArmor = 8; - } - - public DiseasedCat(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a diseased cat"; - - public override bool AlwaysMurderer => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Samurai +{ + public class DiseasedCat : BaseCreature + { + [Constructible] + public DiseasedCat() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 0xC9; + Hue = Utility.RandomAnimalHue(); + BaseSoundID = 0x69; + + SetStr(9); + SetDex(35); + SetInt(5); + + SetHits(6); + SetMana(0); + + SetDamage(1); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 5, 10); + + SetSkill(SkillName.MagicResist, 5.0); + SetSkill(SkillName.Tactics, 4.0); + SetSkill(SkillName.Wrestling, 5.0); + + VirtualArmor = 8; + } + + public DiseasedCat(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a diseased cat"; + + public override bool AlwaysMurderer => true; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/FierceDragon.cs b/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/FierceDragon.cs index c6a2cbf55..8e2016a15 100644 --- a/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/FierceDragon.cs +++ b/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/FierceDragon.cs @@ -1,86 +1,86 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Samurai -{ - public class FierceDragon : BaseCreature - { - [Constructible] - public FierceDragon() : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) - { - Body = 103; - BaseSoundID = 362; - - SetStr(6000, 6020); - SetDex(0); - SetInt(850, 870); - - SetDamage(50, 80); - - SetDamageType(ResistanceType.Fire, 100); - - SetResistance(ResistanceType.Physical, 95, 98); - SetResistance(ResistanceType.Fire, 95, 98); - SetResistance(ResistanceType.Cold, 95, 98); - SetResistance(ResistanceType.Poison, 95, 98); - SetResistance(ResistanceType.Energy, 95, 98); - - SetSkill(SkillName.Tactics, 120.0); - SetSkill(SkillName.Wrestling, 120.0); - SetSkill(SkillName.Magery, 120.0); - - Fame = 15000; - Karma = 15000; - - CantWalk = true; - } - - public FierceDragon(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a fierce dragon"; - - public override int GetIdleSound() => 0x2C4; - - public override int GetAttackSound() => 0x2C0; - - public override int GetDeathSound() => 0x2C1; - - public override int GetAngerSound() => 0x2C4; - - public override int GetHurtSound() => 0x2C3; - - public override void AggressiveAction(Mobile aggressor, bool criminal) - { - base.AggressiveAction(aggressor, criminal); - - if (aggressor is PlayerMobile player) - { - QuestSystem qs = player.Quest; - if (qs is HaochisTrialsQuest) - { - QuestObjective obj = qs.FindObjective(); - if (obj?.Completed == false) - { - obj.Complete(); - qs.AddObjective(new SecondTrialReturnObjective(true)); - } - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Samurai +{ + public class FierceDragon : BaseCreature + { + [Constructible] + public FierceDragon() : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 103; + BaseSoundID = 362; + + SetStr(6000, 6020); + SetDex(0); + SetInt(850, 870); + + SetDamage(50, 80); + + SetDamageType(ResistanceType.Fire, 100); + + SetResistance(ResistanceType.Physical, 95, 98); + SetResistance(ResistanceType.Fire, 95, 98); + SetResistance(ResistanceType.Cold, 95, 98); + SetResistance(ResistanceType.Poison, 95, 98); + SetResistance(ResistanceType.Energy, 95, 98); + + SetSkill(SkillName.Tactics, 120.0); + SetSkill(SkillName.Wrestling, 120.0); + SetSkill(SkillName.Magery, 120.0); + + Fame = 15000; + Karma = 15000; + + CantWalk = true; + } + + public FierceDragon(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a fierce dragon"; + + public override int GetIdleSound() => 0x2C4; + + public override int GetAttackSound() => 0x2C0; + + public override int GetDeathSound() => 0x2C1; + + public override int GetAngerSound() => 0x2C4; + + public override int GetHurtSound() => 0x2C3; + + public override void AggressiveAction(Mobile aggressor, bool criminal) + { + base.AggressiveAction(aggressor, criminal); + + if (aggressor is PlayerMobile player) + { + var qs = player.Quest; + if (qs is HaochisTrialsQuest) + { + QuestObjective obj = qs.FindObjective(); + if (obj?.Completed == false) + { + obj.Complete(); + qs.AddObjective(new SecondTrialReturnObjective(true)); + } + } + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/Haochi.cs b/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/Haochi.cs index bf45e6148..4f5de01dd 100644 --- a/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/Haochi.cs +++ b/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/Haochi.cs @@ -1,170 +1,170 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Samurai -{ - public class Haochi : BaseQuester - { - [Constructible] - public Haochi() : base("the Honorable Samurai Legend") - { - } - - public Haochi(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Daimyo Haochi"; - - public override int TalkNumber => -1; - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = 0x8403; - - Female = false; - Body = 0x190; - } - - public override void InitOutfit() - { - HairItemID = 0x204A; - HairHue = 0x901; - - AddItem(new SamuraiTabi()); - AddItem(new JinBaori()); - - AddItem(new PlateHaidate()); - AddItem(new StandardPlateKabuto()); - AddItem(new PlateMempo()); - AddItem(new PlateDo()); - AddItem(new PlateHiroSode()); - } - - public override int GetAutoTalkRange(PlayerMobile pm) => 2; - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - QuestSystem qs = player.Quest; - - if (qs is HaochisTrialsQuest) - { - if (HaochisTrialsQuest.HasLostHaochisKatana(player)) - { - qs.AddConversation(new LostSwordConversation()); - return; - } - - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - obj.Complete(); - return; - } - - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - player.AddToBackpack(new LeatherDo()); - obj.Complete(); - return; - } - - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - if (((SecondTrialReturnObjective)obj).Dragon) - player.AddToBackpack(new LeatherSuneate()); - - obj.Complete(); - return; - } - - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - player.AddToBackpack(new LeatherHiroSode()); - obj.Complete(); - return; - } - - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - if (!((FourthTrialReturnObjective)obj).KilledCat) - { - Container cont = GetNewContainer(); - cont.DropItem(new LeatherHiroSode()); - cont.DropItem(new JinBaori()); - player.AddToBackpack(cont); - } - - obj.Complete(); - return; - } - - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - HaochisKatana katana = player.Backpack?.FindItemByType(); - if (katana == null) - return; - - katana.Delete(); - obj.Complete(); - - obj = qs.FindObjective(); - if (((FifthTrialIntroObjective)obj)?.StolenTreasure == true) - qs.AddConversation(new SixthTrialIntroConversation(true)); - else - qs.AddConversation(new SixthTrialIntroConversation(false)); - } - - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - obj.Complete(); - return; - } - - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - BaseWeapon weapon = new Daisho(); - BaseRunicTool.ApplyAttributesTo(weapon, Utility.Random(1, 3), 10, 30); - player.AddToBackpack(weapon); - - BaseArmor armor = new LeatherDo(); - BaseRunicTool.ApplyAttributesTo(armor, Utility.Random(1, 3), 10, 20); - player.AddToBackpack(armor); - - obj.Complete(); - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Samurai +{ + public class Haochi : BaseQuester + { + [Constructible] + public Haochi() : base("the Honorable Samurai Legend") + { + } + + public Haochi(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Daimyo Haochi"; + + public override int TalkNumber => -1; + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = 0x8403; + + Female = false; + Body = 0x190; + } + + public override void InitOutfit() + { + HairItemID = 0x204A; + HairHue = 0x901; + + AddItem(new SamuraiTabi()); + AddItem(new JinBaori()); + + AddItem(new PlateHaidate()); + AddItem(new StandardPlateKabuto()); + AddItem(new PlateMempo()); + AddItem(new PlateDo()); + AddItem(new PlateHiroSode()); + } + + public override int GetAutoTalkRange(PlayerMobile pm) => 2; + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + var qs = player.Quest; + + if (qs is HaochisTrialsQuest) + { + if (HaochisTrialsQuest.HasLostHaochisKatana(player)) + { + qs.AddConversation(new LostSwordConversation()); + return; + } + + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + obj.Complete(); + return; + } + + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + player.AddToBackpack(new LeatherDo()); + obj.Complete(); + return; + } + + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + if (((SecondTrialReturnObjective)obj).Dragon) + player.AddToBackpack(new LeatherSuneate()); + + obj.Complete(); + return; + } + + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + player.AddToBackpack(new LeatherHiroSode()); + obj.Complete(); + return; + } + + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + if (!((FourthTrialReturnObjective)obj).KilledCat) + { + var cont = GetNewContainer(); + cont.DropItem(new LeatherHiroSode()); + cont.DropItem(new JinBaori()); + player.AddToBackpack(cont); + } + + obj.Complete(); + return; + } + + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + var katana = player.Backpack?.FindItemByType(); + if (katana == null) + return; + + katana.Delete(); + obj.Complete(); + + obj = qs.FindObjective(); + if (((FifthTrialIntroObjective)obj)?.StolenTreasure == true) + qs.AddConversation(new SixthTrialIntroConversation(true)); + else + qs.AddConversation(new SixthTrialIntroConversation(false)); + } + + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + obj.Complete(); + return; + } + + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + BaseWeapon weapon = new Daisho(); + BaseRunicTool.ApplyAttributesTo(weapon, Utility.Random(1, 3), 10, 30); + player.AddToBackpack(weapon); + + BaseArmor armor = new LeatherDo(); + BaseRunicTool.ApplyAttributesTo(armor, Utility.Random(1, 3), 10, 20); + player.AddToBackpack(armor); + + obj.Complete(); + } + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/HaochisGuardsman.cs b/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/HaochisGuardsman.cs index 2b83deb39..5c2687c31 100644 --- a/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/HaochisGuardsman.cs +++ b/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/HaochisGuardsman.cs @@ -1,85 +1,85 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Samurai -{ - public class HaochisGuardsman : BaseQuester - { - [Constructible] - public HaochisGuardsman() : base("the Guardsman of Daimyo Haochi") - { - } - - public HaochisGuardsman(Serial serial) : base(serial) - { - } - - public override int TalkNumber => -1; - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = Race.Human.RandomSkinHue(); - - Female = false; - Body = 0x190; - Name = NameList.RandomName("male"); - } - - public override void InitOutfit() - { - Utility.AssignRandomHair(this); - - AddItem(new LeatherDo()); - AddItem(new LeatherHiroSode()); - AddItem(new SamuraiTabi(Utility.RandomNondyedHue())); - - AddItem( - Utility.Random(3) switch - { - 0 => new StuddedHaidate(), - 1 => new PlateSuneate(), - _ => new LeatherSuneate() - } - ); - - AddItem( - Utility.Random(4) switch - { - 0 => new DecorativePlateKabuto(), - 1 => new ChainHatsuburi(), - 2 => new LightPlateJingasa(), - _ => new LeatherJingasa() - } - ); - - AddItem( - Utility.Random(3) switch - { - 0 => new NoDachi{Movable = false}, - 1 => new Lajatang{Movable = false}, - _ => new Wakizashi{Movable = false} - } - ); - } - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Samurai +{ + public class HaochisGuardsman : BaseQuester + { + [Constructible] + public HaochisGuardsman() : base("the Guardsman of Daimyo Haochi") + { + } + + public HaochisGuardsman(Serial serial) : base(serial) + { + } + + public override int TalkNumber => -1; + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = Race.Human.RandomSkinHue(); + + Female = false; + Body = 0x190; + Name = NameList.RandomName("male"); + } + + public override void InitOutfit() + { + Utility.AssignRandomHair(this); + + AddItem(new LeatherDo()); + AddItem(new LeatherHiroSode()); + AddItem(new SamuraiTabi(Utility.RandomNondyedHue())); + + AddItem( + Utility.Random(3) switch + { + 0 => new StuddedHaidate(), + 1 => new PlateSuneate(), + _ => new LeatherSuneate() + } + ); + + AddItem( + Utility.Random(4) switch + { + 0 => new DecorativePlateKabuto(), + 1 => new ChainHatsuburi(), + 2 => new LightPlateJingasa(), + _ => new LeatherJingasa() + } + ); + + AddItem( + Utility.Random(3) switch + { + 0 => new NoDachi { Movable = false }, + 1 => new Lajatang { Movable = false }, + _ => new Wakizashi { Movable = false } + } + ); + } + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/InjuredWolf.cs b/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/InjuredWolf.cs index 97589e719..5bcf2fedf 100644 --- a/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/InjuredWolf.cs +++ b/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/InjuredWolf.cs @@ -1,56 +1,56 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Samurai -{ - public class InjuredWolf : BaseCreature - { - [Constructible] - public InjuredWolf() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) - { - Body = 0xE1; - BaseSoundID = 0xE5; - - Hue = Utility.RandomAnimalHue(); - - SetStr(10, 20); - SetDex(45, 65); - SetInt(10, 15); - - SetHits(1); - - SetDamage(1, 3); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 15); - SetResistance(ResistanceType.Fire, 5, 10); - - SetSkill(SkillName.MagicResist, 10.0); - SetSkill(SkillName.Tactics, 0.0, 5.0); - SetSkill(SkillName.Wrestling, 20.0, 30.0); - } - - public InjuredWolf(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an injured wolf corpse"; - public override string DefaultName => "an injured wolf"; - - public override int GetIdleSound() => 0xE9; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Samurai +{ + public class InjuredWolf : BaseCreature + { + [Constructible] + public InjuredWolf() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 0xE1; + BaseSoundID = 0xE5; + + Hue = Utility.RandomAnimalHue(); + + SetStr(10, 20); + SetDex(45, 65); + SetInt(10, 15); + + SetHits(1); + + SetDamage(1, 3); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 15); + SetResistance(ResistanceType.Fire, 5, 10); + + SetSkill(SkillName.MagicResist, 10.0); + SetSkill(SkillName.Tactics, 0.0, 5.0); + SetSkill(SkillName.Wrestling, 20.0, 30.0); + } + + public InjuredWolf(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an injured wolf corpse"; + public override string DefaultName => "an injured wolf"; + + public override int GetIdleSound() => 0xE9; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/Relnia.cs b/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/Relnia.cs index d4627a45e..0a879c95e 100644 --- a/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/Relnia.cs +++ b/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/Relnia.cs @@ -1,87 +1,87 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Samurai -{ - public class Relnia : BaseQuester - { - [Constructible] - public Relnia() : base("the Gypsy") - { - } - - public Relnia(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Disheveled Relnia"; - - public override int TalkNumber => -1; - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = 0x83FF; - - Female = true; - Body = 0x191; - } - - public override void InitOutfit() - { - HairItemID = 0x203C; - HairHue = 0x654; - - AddItem(new ThighBoots(0x901)); - AddItem(new FancyShirt(0x5F3)); - AddItem(new SkullCap(0x6A7)); - AddItem(new Skirt(0x544)); - } - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - } - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (from is PlayerMobile player) - { - QuestSystem qs = player.Quest; - - if (qs is HaochisTrialsQuest) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - if (dropped is Gold gold) - { - obj.Complete(); - qs.AddObjective(new FourthTrialReturnObjective(false)); - - SayTo(from, 1063241); // I thank thee. This gold will be a great help to me and mine! - - gold.Consume(); // Intentional difference from OSI: don't take all the gold of poor newbies! - return gold.Deleted; - } - } - } - - return base.OnDragDrop(from, dropped); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Samurai +{ + public class Relnia : BaseQuester + { + [Constructible] + public Relnia() : base("the Gypsy") + { + } + + public Relnia(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Disheveled Relnia"; + + public override int TalkNumber => -1; + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = 0x83FF; + + Female = true; + Body = 0x191; + } + + public override void InitOutfit() + { + HairItemID = 0x203C; + HairHue = 0x654; + + AddItem(new ThighBoots(0x901)); + AddItem(new FancyShirt(0x5F3)); + AddItem(new SkullCap(0x6A7)); + AddItem(new Skirt(0x544)); + } + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + } + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (from is PlayerMobile player) + { + var qs = player.Quest; + + if (qs is HaochisTrialsQuest) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + if (dropped is Gold gold) + { + obj.Complete(); + qs.AddObjective(new FourthTrialReturnObjective(false)); + + SayTo(from, 1063241); // I thank thee. This gold will be a great help to me and mine! + + gold.Consume(); // Intentional difference from OSI: don't take all the gold of poor newbies! + return gold.Deleted; + } + } + } + + return base.OnDragDrop(from, dropped); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/YoungNinja.cs b/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/YoungNinja.cs index d5f85cb72..130567bd9 100644 --- a/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/YoungNinja.cs +++ b/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/YoungNinja.cs @@ -1,63 +1,63 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Samurai -{ - public class YoungNinja : BaseCreature - { - [Constructible] - public YoungNinja() : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) - { - InitStats(45, 30, 5); - SetHits(20, 30); - - Hue = Race.Human.RandomSkinHue(); - Body = 0x190; - - Utility.AssignRandomHair(this); - Utility.AssignRandomFacialHair(this); - - AddItem(new NinjaTabi()); - AddItem(new LeatherNinjaPants()); - AddItem(new LeatherNinjaJacket()); - AddItem(new LeatherNinjaBelt()); - - AddItem(new Bandana(Utility.RandomNondyedHue())); - - AddItem( - Utility.Random(3) switch - { - 0 => new Tessen(), - 1 => new Kama(), - _ => new Lajatang() - } - ); - - SetSkill(SkillName.Swords, 50.0); - SetSkill(SkillName.Tactics, 50.0); - } - - public YoungNinja(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a young ninja's corpse"; - public override string DefaultName => "a young ninja"; - - public override bool AlwaysMurderer => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Samurai +{ + public class YoungNinja : BaseCreature + { + [Constructible] + public YoungNinja() : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + InitStats(45, 30, 5); + SetHits(20, 30); + + Hue = Race.Human.RandomSkinHue(); + Body = 0x190; + + Utility.AssignRandomHair(this); + Utility.AssignRandomFacialHair(this); + + AddItem(new NinjaTabi()); + AddItem(new LeatherNinjaPants()); + AddItem(new LeatherNinjaJacket()); + AddItem(new LeatherNinjaBelt()); + + AddItem(new Bandana(Utility.RandomNondyedHue())); + + AddItem( + Utility.Random(3) switch + { + 0 => new Tessen(), + 1 => new Kama(), + _ => new Lajatang() + } + ); + + SetSkill(SkillName.Swords, 50.0); + SetSkill(SkillName.Tactics, 50.0); + } + + public YoungNinja(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a young ninja's corpse"; + public override string DefaultName => "a young ninja"; + + public override bool AlwaysMurderer => true; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/YoungRonin.cs b/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/YoungRonin.cs index fd290954a..98ddf1f45 100644 --- a/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/YoungRonin.cs +++ b/Projects/UOContent/Engines/Quests/Haochi's Trials/Mobiles/YoungRonin.cs @@ -1,71 +1,71 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Samurai -{ - public class YoungRonin : BaseCreature - { - [Constructible] - public YoungRonin() : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) - { - InitStats(45, 30, 5); - SetHits(10, 20); - - Hue = Race.Human.RandomSkinHue(); - Body = 0x190; - - Utility.AssignRandomHair(this); - Utility.AssignRandomFacialHair(this); - - AddItem(new LeatherDo()); - AddItem(new LeatherHiroSode()); - AddItem(new SamuraiTabi()); - - AddItem( - Utility.Random(3) switch - { - 0 => new StuddedHaidate(), - 1 => new PlateSuneate(), - _ => new LeatherSuneate() - } - ); - - AddItem(new Bandana(Utility.RandomNondyedHue())); - - AddItem( - Utility.Random(3) switch - { - 0 => new NoDachi(), - 1 => new Lajatang(), - _ => new Wakizashi() - } - ); - - SetSkill(SkillName.Swords, 50.0); - SetSkill(SkillName.Tactics, 50.0); - } - - public YoungRonin(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a young ronin's corpse"; - public override string DefaultName => "a young ronin"; - - public override bool AlwaysMurderer => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Samurai +{ + public class YoungRonin : BaseCreature + { + [Constructible] + public YoungRonin() : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + InitStats(45, 30, 5); + SetHits(10, 20); + + Hue = Race.Human.RandomSkinHue(); + Body = 0x190; + + Utility.AssignRandomHair(this); + Utility.AssignRandomFacialHair(this); + + AddItem(new LeatherDo()); + AddItem(new LeatherHiroSode()); + AddItem(new SamuraiTabi()); + + AddItem( + Utility.Random(3) switch + { + 0 => new StuddedHaidate(), + 1 => new PlateSuneate(), + _ => new LeatherSuneate() + } + ); + + AddItem(new Bandana(Utility.RandomNondyedHue())); + + AddItem( + Utility.Random(3) switch + { + 0 => new NoDachi(), + 1 => new Lajatang(), + _ => new Wakizashi() + } + ); + + SetSkill(SkillName.Swords, 50.0); + SetSkill(SkillName.Tactics, 50.0); + } + + public YoungRonin(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a young ronin's corpse"; + public override string DefaultName => "a young ronin"; + + public override bool AlwaysMurderer => true; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Haochi's Trials/Objectives.cs b/Projects/UOContent/Engines/Quests/Haochi's Trials/Objectives.cs index 0d7c426f3..da8215ad5 100644 --- a/Projects/UOContent/Engines/Quests/Haochi's Trials/Objectives.cs +++ b/Projects/UOContent/Engines/Quests/Haochi's Trials/Objectives.cs @@ -1,333 +1,333 @@ -using System; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Samurai -{ - public class FindHaochiObjective : QuestObjective - { - public override object Message => 1063026; - - public override void OnComplete() - { - System.AddConversation(new FirstTrialIntroConversation()); - } - } - - public class FirstTrialIntroObjective : QuestObjective - { - public override object Message => 1063030; - - public override void OnComplete() - { - System.AddConversation(new FirstTrialKillConversation()); - } - } - - public class FirstTrialKillObjective : QuestObjective - { - private int m_CursedSoulsKilled; - private int m_YoungRoninKilled; - - public override object Message => 1063032; - - public override int MaxProgress => 3; - - public override void OnKill(BaseCreature creature, Container corpse) - { - if (creature is CursedSoul) - { - if (m_CursedSoulsKilled == 0) - System.AddConversation(new GainKarmaConversation(true)); - - m_CursedSoulsKilled++; - - // Cursed Souls killed: ~1_COUNT~ - System.From.SendLocalizedMessage(1063038, m_CursedSoulsKilled.ToString()); - } - else if (creature is YoungRonin) - { - if (m_YoungRoninKilled == 0) - System.AddConversation(new GainKarmaConversation(false)); - - m_YoungRoninKilled++; - - // Young Ronin killed: ~1_COUNT~ - System.From.SendLocalizedMessage(1063039, m_YoungRoninKilled.ToString()); - } - - CurProgress = Math.Max(m_CursedSoulsKilled, m_YoungRoninKilled); - } - - public override void OnComplete() - { - System.AddObjective(new FirstTrialReturnObjective(m_CursedSoulsKilled > m_YoungRoninKilled)); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_CursedSoulsKilled = reader.ReadEncodedInt(); - m_YoungRoninKilled = reader.ReadEncodedInt(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.WriteEncodedInt(m_CursedSoulsKilled); - writer.WriteEncodedInt(m_YoungRoninKilled); - } - } - - public class FirstTrialReturnObjective : QuestObjective - { - private bool m_CursedSoul; - - public FirstTrialReturnObjective(bool cursedSoul) => m_CursedSoul = cursedSoul; - - public FirstTrialReturnObjective() - { - } - - public override object Message => 1063044; - - public override void OnComplete() - { - System.AddConversation(new SecondTrialIntroConversation(m_CursedSoul)); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_CursedSoul = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(m_CursedSoul); - } - } - - public class SecondTrialIntroObjective : QuestObjective - { - public override object Message => 1063047; - - public override void OnComplete() - { - System.AddConversation(new SecondTrialAttackConversation()); - } - } - - public class SecondTrialAttackObjective : QuestObjective - { - public override object Message => 1063058; - } - - public class SecondTrialReturnObjective : QuestObjective - { - public SecondTrialReturnObjective(bool dragon) => Dragon = dragon; - - public SecondTrialReturnObjective() - { - } - - public override object Message => 1063229; - - public bool Dragon { get; private set; } - - public override void OnComplete() - { - System.AddConversation(new ThirdTrialIntroConversation(Dragon)); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - Dragon = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(Dragon); - } - } - - public class ThirdTrialIntroObjective : QuestObjective - { - public override object Message => 1063061; - - public override void OnComplete() - { - System.AddConversation(new ThirdTrialKillConversation()); - } - } - - public class ThirdTrialKillObjective : QuestObjective - { - public override object Message => 1063063; - - public override void OnKill(BaseCreature creature, Container corpse) - { - if (creature is InjuredWolf) - Complete(); - } - - public override void OnComplete() - { - System.AddObjective(new ThirdTrialReturnObjective()); - } - } - - public class ThirdTrialReturnObjective : QuestObjective - { - public override object Message => 1063064; - - public override void OnComplete() - { - System.AddConversation(new FourthTrialIntroConversation()); - } - } - - public class FourthTrialIntroObjective : QuestObjective - { - public override object Message => 1063066; - - public override void OnComplete() - { - System.AddConversation(new FourthTrialCatsConversation()); - } - } - - public class FourthTrialCatsObjective : QuestObjective - { - public override object Message => 1063068; - - public override void OnKill(BaseCreature creature, Container corpse) - { - if (creature is DiseasedCat) - { - Complete(); - System.AddObjective(new FourthTrialReturnObjective(true)); - } - } - } - - public class FourthTrialReturnObjective : QuestObjective - { - public FourthTrialReturnObjective(bool killedCat) => KilledCat = killedCat; - - public FourthTrialReturnObjective() - { - } - - public override object Message => 1063242; - - public bool KilledCat { get; private set; } - - public override void OnComplete() - { - System.AddConversation(new FifthTrialIntroConversation(KilledCat)); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - KilledCat = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(KilledCat); - } - } - - public class FifthTrialIntroObjective : QuestObjective - { - public override object Message => 1063072; - - public bool StolenTreasure { get; set; } - - public override void OnComplete() - { - System.AddConversation(new FifthTrialReturnConversation()); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - StolenTreasure = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(StolenTreasure); - } - } - - public class FifthTrialReturnObjective : QuestObjective - { - public override object Message => 1063073; - } - - public class SixthTrialIntroObjective : QuestObjective - { - public override object Message => 1063078; - - public override void OnComplete() - { - System.AddObjective(new SixthTrialReturnObjective()); - } - } - - public class SixthTrialReturnObjective : QuestObjective - { - public override object Message => 1063252; - - public override void OnComplete() - { - System.AddConversation(new SeventhTrialIntroConversation()); - } - } - - public class SeventhTrialIntroObjective : QuestObjective - { - public override object Message => 1063080; - - public override int MaxProgress => 3; - - public override void OnKill(BaseCreature creature, Container corpse) - { - if (creature is YoungNinja) - CurProgress++; - } - - public override void OnComplete() - { - System.AddObjective(new SeventhTrialReturnObjective()); - } - } - - public class SeventhTrialReturnObjective : QuestObjective - { - public override object Message => 1063253; - - public override void OnComplete() - { - System.AddConversation(new EndConversation()); - } - } -} \ No newline at end of file +using System; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Samurai +{ + public class FindHaochiObjective : QuestObjective + { + public override object Message => 1063026; + + public override void OnComplete() + { + System.AddConversation(new FirstTrialIntroConversation()); + } + } + + public class FirstTrialIntroObjective : QuestObjective + { + public override object Message => 1063030; + + public override void OnComplete() + { + System.AddConversation(new FirstTrialKillConversation()); + } + } + + public class FirstTrialKillObjective : QuestObjective + { + private int m_CursedSoulsKilled; + private int m_YoungRoninKilled; + + public override object Message => 1063032; + + public override int MaxProgress => 3; + + public override void OnKill(BaseCreature creature, Container corpse) + { + if (creature is CursedSoul) + { + if (m_CursedSoulsKilled == 0) + System.AddConversation(new GainKarmaConversation(true)); + + m_CursedSoulsKilled++; + + // Cursed Souls killed: ~1_COUNT~ + System.From.SendLocalizedMessage(1063038, m_CursedSoulsKilled.ToString()); + } + else if (creature is YoungRonin) + { + if (m_YoungRoninKilled == 0) + System.AddConversation(new GainKarmaConversation(false)); + + m_YoungRoninKilled++; + + // Young Ronin killed: ~1_COUNT~ + System.From.SendLocalizedMessage(1063039, m_YoungRoninKilled.ToString()); + } + + CurProgress = Math.Max(m_CursedSoulsKilled, m_YoungRoninKilled); + } + + public override void OnComplete() + { + System.AddObjective(new FirstTrialReturnObjective(m_CursedSoulsKilled > m_YoungRoninKilled)); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_CursedSoulsKilled = reader.ReadEncodedInt(); + m_YoungRoninKilled = reader.ReadEncodedInt(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.WriteEncodedInt(m_CursedSoulsKilled); + writer.WriteEncodedInt(m_YoungRoninKilled); + } + } + + public class FirstTrialReturnObjective : QuestObjective + { + private bool m_CursedSoul; + + public FirstTrialReturnObjective(bool cursedSoul) => m_CursedSoul = cursedSoul; + + public FirstTrialReturnObjective() + { + } + + public override object Message => 1063044; + + public override void OnComplete() + { + System.AddConversation(new SecondTrialIntroConversation(m_CursedSoul)); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_CursedSoul = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(m_CursedSoul); + } + } + + public class SecondTrialIntroObjective : QuestObjective + { + public override object Message => 1063047; + + public override void OnComplete() + { + System.AddConversation(new SecondTrialAttackConversation()); + } + } + + public class SecondTrialAttackObjective : QuestObjective + { + public override object Message => 1063058; + } + + public class SecondTrialReturnObjective : QuestObjective + { + public SecondTrialReturnObjective(bool dragon) => Dragon = dragon; + + public SecondTrialReturnObjective() + { + } + + public override object Message => 1063229; + + public bool Dragon { get; private set; } + + public override void OnComplete() + { + System.AddConversation(new ThirdTrialIntroConversation(Dragon)); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + Dragon = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(Dragon); + } + } + + public class ThirdTrialIntroObjective : QuestObjective + { + public override object Message => 1063061; + + public override void OnComplete() + { + System.AddConversation(new ThirdTrialKillConversation()); + } + } + + public class ThirdTrialKillObjective : QuestObjective + { + public override object Message => 1063063; + + public override void OnKill(BaseCreature creature, Container corpse) + { + if (creature is InjuredWolf) + Complete(); + } + + public override void OnComplete() + { + System.AddObjective(new ThirdTrialReturnObjective()); + } + } + + public class ThirdTrialReturnObjective : QuestObjective + { + public override object Message => 1063064; + + public override void OnComplete() + { + System.AddConversation(new FourthTrialIntroConversation()); + } + } + + public class FourthTrialIntroObjective : QuestObjective + { + public override object Message => 1063066; + + public override void OnComplete() + { + System.AddConversation(new FourthTrialCatsConversation()); + } + } + + public class FourthTrialCatsObjective : QuestObjective + { + public override object Message => 1063068; + + public override void OnKill(BaseCreature creature, Container corpse) + { + if (creature is DiseasedCat) + { + Complete(); + System.AddObjective(new FourthTrialReturnObjective(true)); + } + } + } + + public class FourthTrialReturnObjective : QuestObjective + { + public FourthTrialReturnObjective(bool killedCat) => KilledCat = killedCat; + + public FourthTrialReturnObjective() + { + } + + public override object Message => 1063242; + + public bool KilledCat { get; private set; } + + public override void OnComplete() + { + System.AddConversation(new FifthTrialIntroConversation(KilledCat)); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + KilledCat = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(KilledCat); + } + } + + public class FifthTrialIntroObjective : QuestObjective + { + public override object Message => 1063072; + + public bool StolenTreasure { get; set; } + + public override void OnComplete() + { + System.AddConversation(new FifthTrialReturnConversation()); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + StolenTreasure = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(StolenTreasure); + } + } + + public class FifthTrialReturnObjective : QuestObjective + { + public override object Message => 1063073; + } + + public class SixthTrialIntroObjective : QuestObjective + { + public override object Message => 1063078; + + public override void OnComplete() + { + System.AddObjective(new SixthTrialReturnObjective()); + } + } + + public class SixthTrialReturnObjective : QuestObjective + { + public override object Message => 1063252; + + public override void OnComplete() + { + System.AddConversation(new SeventhTrialIntroConversation()); + } + } + + public class SeventhTrialIntroObjective : QuestObjective + { + public override object Message => 1063080; + + public override int MaxProgress => 3; + + public override void OnKill(BaseCreature creature, Container corpse) + { + if (creature is YoungNinja) + CurProgress++; + } + + public override void OnComplete() + { + System.AddObjective(new SeventhTrialReturnObjective()); + } + } + + public class SeventhTrialReturnObjective : QuestObjective + { + public override object Message => 1063253; + + public override void OnComplete() + { + System.AddConversation(new EndConversation()); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Solen Matriarch/Conversations.cs b/Projects/UOContent/Engines/Quests/Solen Matriarch/Conversations.cs index a61d3ab88..aba0bcdb7 100644 --- a/Projects/UOContent/Engines/Quests/Solen Matriarch/Conversations.cs +++ b/Projects/UOContent/Engines/Quests/Solen Matriarch/Conversations.cs @@ -1,171 +1,171 @@ -namespace Server.Engines.Quests.Matriarch -{ - public class DontOfferConversation : QuestConversation - { - private bool m_Friend; - - public DontOfferConversation(bool friend) => m_Friend = friend; - - public DontOfferConversation() - { - } - - public override object Message - { - get - { - if (m_Friend) return 1054081; - - /* The Solen Matriarch smiles as she eats the seed you offered.

- * - * Thank you for that seed. It was quite delicious.

- * - * I would offer to make you a friend of my colony, but you seem to be busy with - * another task at the moment. Perhaps you should finish whatever is occupying - * your attention at the moment and return to me once you're done. - */ - return 1054079; - } - } - - public override bool Logged => false; - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_Friend = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(m_Friend); - } - } - - public class AcceptConversation : QuestConversation - { - public override object Message => 1054084; - - public override void OnRead() - { - System.AddObjective(new KillInfiltratorsObjective()); - } - } - - public class DuringKillInfiltratorsConversation : QuestConversation - { - public override object Message => 1054089; - - public override bool Logged => false; - } - - public class GatherWaterConversation : QuestConversation - { - public override object Message => 1054091; - - public override void OnRead() - { - System.AddObjective(new GatherWaterObjective()); - } - } - - public class DuringWaterGatheringConversation : QuestConversation - { - public override object Message => 1054094; - - public override bool Logged => false; - } - - public class ProcessFungiConversation : QuestConversation - { - private bool m_Friend; - - public ProcessFungiConversation(bool friend) => m_Friend = friend; - - public ProcessFungiConversation() - { - } - - public override object Message - { - get - { - if (m_Friend) return 1054097; - - /* The Solen Matriarch listens as you report the completion of your - * tasks to her.

- * - * I give you my thanks for your help, and I will gladly make you a friend of my - * solen colony. My warriors, workers, and queens will not longer look at you - * as an intruder and attack you when you enter our lair.

- * - * I will also process some zoogi fungus into powder of translocation for you. - * Two of the zoogi fungi are required for each measure of the powder. I will - * process up to 200 zoogi fungi into 100 measures of powder of translocation.

- * - * I will also give you some gold for assisting me and my colony, but first let's - * take care of your zoogi fungus. - */ - return 1054096; - } - } - - public override void OnRead() - { - System.AddObjective(new ProcessFungiObjective()); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_Friend = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(m_Friend); - } - } - - public class DuringFungiProcessConversation : QuestConversation - { - public override object Message => 1054099; - - public override bool Logged => false; - } - - public class FullBackpackConversation : QuestConversation - { - private readonly bool m_Logged; - - public FullBackpackConversation(bool logged) => m_Logged = logged; - - public FullBackpackConversation() => m_Logged = true; - - public override object Message => 1054102; - - public override bool Logged => m_Logged; - - public override void OnRead() - { - if (m_Logged) - System.AddObjective(new GetRewardObjective()); - } - } - - public class EndConversation : QuestConversation - { - public override object Message => 1054101; - - public override void OnRead() - { - System.Complete(); - } - } -} \ No newline at end of file +namespace Server.Engines.Quests.Matriarch +{ + public class DontOfferConversation : QuestConversation + { + private bool m_Friend; + + public DontOfferConversation(bool friend) => m_Friend = friend; + + public DontOfferConversation() + { + } + + public override object Message + { + get + { + if (m_Friend) return 1054081; + + /* The Solen Matriarch smiles as she eats the seed you offered.

+ * + * Thank you for that seed. It was quite delicious.

+ * + * I would offer to make you a friend of my colony, but you seem to be busy with + * another task at the moment. Perhaps you should finish whatever is occupying + * your attention at the moment and return to me once you're done. + */ + return 1054079; + } + } + + public override bool Logged => false; + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_Friend = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(m_Friend); + } + } + + public class AcceptConversation : QuestConversation + { + public override object Message => 1054084; + + public override void OnRead() + { + System.AddObjective(new KillInfiltratorsObjective()); + } + } + + public class DuringKillInfiltratorsConversation : QuestConversation + { + public override object Message => 1054089; + + public override bool Logged => false; + } + + public class GatherWaterConversation : QuestConversation + { + public override object Message => 1054091; + + public override void OnRead() + { + System.AddObjective(new GatherWaterObjective()); + } + } + + public class DuringWaterGatheringConversation : QuestConversation + { + public override object Message => 1054094; + + public override bool Logged => false; + } + + public class ProcessFungiConversation : QuestConversation + { + private bool m_Friend; + + public ProcessFungiConversation(bool friend) => m_Friend = friend; + + public ProcessFungiConversation() + { + } + + public override object Message + { + get + { + if (m_Friend) return 1054097; + + /* The Solen Matriarch listens as you report the completion of your + * tasks to her.

+ * + * I give you my thanks for your help, and I will gladly make you a friend of my + * solen colony. My warriors, workers, and queens will not longer look at you + * as an intruder and attack you when you enter our lair.

+ * + * I will also process some zoogi fungus into powder of translocation for you. + * Two of the zoogi fungi are required for each measure of the powder. I will + * process up to 200 zoogi fungi into 100 measures of powder of translocation.

+ * + * I will also give you some gold for assisting me and my colony, but first let's + * take care of your zoogi fungus. + */ + return 1054096; + } + } + + public override void OnRead() + { + System.AddObjective(new ProcessFungiObjective()); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_Friend = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(m_Friend); + } + } + + public class DuringFungiProcessConversation : QuestConversation + { + public override object Message => 1054099; + + public override bool Logged => false; + } + + public class FullBackpackConversation : QuestConversation + { + private readonly bool m_Logged; + + public FullBackpackConversation(bool logged) => m_Logged = logged; + + public FullBackpackConversation() => m_Logged = true; + + public override object Message => 1054102; + + public override bool Logged => m_Logged; + + public override void OnRead() + { + if (m_Logged) + System.AddObjective(new GetRewardObjective()); + } + } + + public class EndConversation : QuestConversation + { + public override object Message => 1054101; + + public override void OnRead() + { + System.Complete(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Solen Matriarch/Mobiles/SolenMatriarch.cs b/Projects/UOContent/Engines/Quests/Solen Matriarch/Mobiles/SolenMatriarch.cs index afd1a2950..b7ebe4b2e 100644 --- a/Projects/UOContent/Engines/Quests/Solen Matriarch/Mobiles/SolenMatriarch.cs +++ b/Projects/UOContent/Engines/Quests/Solen Matriarch/Mobiles/SolenMatriarch.cs @@ -1,296 +1,297 @@ -using System.Collections.Generic; -using Server.ContextMenus; -using Server.Engines.Plants; -using Server.Items; -using Server.Mobiles; -using Server.Targeting; - -namespace Server.Engines.Quests.Matriarch -{ - public abstract class BaseSolenMatriarch : BaseQuester - { - public BaseSolenMatriarch() - { - Body = 0x328; - - if (!RedSolen) - Hue = 0x44E; - - SpeechHue = 0; - } - - public BaseSolenMatriarch(Serial serial) : base(serial) - { - } - - public abstract bool RedSolen { get; } - public override string DefaultName => "the solen matriarch"; - public override bool DisallowAllMoves => false; - - public override int GetIdleSound() => 0x10D; - - public override bool CanTalkTo(PlayerMobile to) - { - if (SolenMatriarchQuest.IsFriend(to, RedSolen)) - return true; - - return to.Quest is SolenMatriarchQuest qs && qs.RedSolen == RedSolen; - } - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - Direction = GetDirectionTo(player); - - if (player.Quest is SolenMatriarchQuest qs && qs.RedSolen == RedSolen) - { - if (qs.IsObjectiveInProgress(typeof(KillInfiltratorsObjective))) - { - qs.AddConversation(new DuringKillInfiltratorsConversation()); - } - else - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - obj.Complete(); - } - else if (qs.IsObjectiveInProgress(typeof(GatherWaterObjective))) - { - qs.AddConversation(new DuringWaterGatheringConversation()); - } - else - { - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - obj.Complete(); - } - else if (qs.IsObjectiveInProgress(typeof(ProcessFungiObjective))) - { - qs.AddConversation(new DuringFungiProcessConversation()); - } - else - { - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - if (SolenMatriarchQuest.GiveRewardTo(player)) - obj.Complete(); - else - qs.AddConversation(new FullBackpackConversation(false)); - } - } - } - } - } - else if (SolenMatriarchQuest.IsFriend(player, RedSolen)) - { - QuestSystem newQuest = new SolenMatriarchQuest(player, RedSolen); - - if (player.Quest == null && QuestSystem.CanOfferQuest(player, typeof(SolenMatriarchQuest))) - newQuest.SendOffer(); - else - newQuest.AddConversation(new DontOfferConversation(true)); - } - } - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (from is PlayerMobile player) - { - if (dropped is Seed) - { - if (player.Quest is SolenMatriarchQuest qs && qs.RedSolen == RedSolen) - { - SayTo(player, 1054080); // Thank you for that plant seed. Those have such wonderful flavor. - } - else - { - QuestSystem newQuest = new SolenMatriarchQuest(player, RedSolen); - - if (player.Quest == null && QuestSystem.CanOfferQuest(player, typeof(SolenMatriarchQuest))) - newQuest.SendOffer(); - else - newQuest.AddConversation( - new DontOfferConversation(SolenMatriarchQuest.IsFriend(player, RedSolen))); - } - - dropped.Delete(); - return true; - } - - if (dropped is ZoogiFungus fungus) - { - OnGivenFungi(player, fungus); - - return fungus.Deleted; - } - } - - return base.OnDragDrop(from, dropped); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (from.Alive) - if (from is PlayerMobile pm) - if (pm.Quest is SolenMatriarchQuest qs && qs.RedSolen == RedSolen) - if (qs.IsObjectiveInProgress(typeof(ProcessFungiObjective))) - list.Add(new ProcessZoogiFungusEntry(this, pm)); - } - - public void OnGivenFungi(PlayerMobile player, ZoogiFungus fungi) - { - Direction = GetDirectionTo(player); - - if (player.Quest is SolenMatriarchQuest qs && qs.RedSolen == RedSolen) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - int amount = fungi.Amount / 2; - - if (amount > 100) - amount = 100; - - if (amount > 0) - { - if (amount * 2 >= fungi.Amount) - fungi.Delete(); - else - fungi.Amount -= amount * 2; - - PowderOfTranslocation powder = new PowderOfTranslocation(amount); - player.AddToBackpack(powder); - - player.SendLocalizedMessage(1054100); // You receive some powder of translocation. - - obj.Complete(); - } - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - private class ProcessZoogiFungusEntry : ContextMenuEntry - { - private readonly PlayerMobile m_From; - private readonly BaseSolenMatriarch m_Matriarch; - - public ProcessZoogiFungusEntry(BaseSolenMatriarch matriarch, PlayerMobile from) : base(6184) - { - m_Matriarch = matriarch; - m_From = from; - } - - public override void OnClick() - { - if (m_From.Alive) - m_From.Target = new ProcessFungiTarget(m_Matriarch, m_From); - } - } - - private class ProcessFungiTarget : Target - { - private readonly PlayerMobile m_From; - private readonly BaseSolenMatriarch m_Matriarch; - - public ProcessFungiTarget(BaseSolenMatriarch matriarch, PlayerMobile from) : base(-1, false, TargetFlags.None) - { - m_Matriarch = matriarch; - m_From = from; - } - - protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType) - { - from.SendLocalizedMessage(1042021, "", 0x59); // Cancelled. - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is ZoogiFungus fungus) - { - if (fungus.IsChildOf(m_From.Backpack)) - m_Matriarch.OnGivenFungi(m_From, fungus); - else - m_From.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - } - } - - public class RedSolenMatriarch : BaseSolenMatriarch - { - [Constructible] - public RedSolenMatriarch() - { - } - - public RedSolenMatriarch(Serial serial) : base(serial) - { - } - - public override bool RedSolen => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BlackSolenMatriarch : BaseSolenMatriarch - { - [Constructible] - public BlackSolenMatriarch() - { - } - - public BlackSolenMatriarch(Serial serial) : base(serial) - { - } - - public override bool RedSolen => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +using System.Collections.Generic; +using Server.ContextMenus; +using Server.Engines.Plants; +using Server.Items; +using Server.Mobiles; +using Server.Targeting; + +namespace Server.Engines.Quests.Matriarch +{ + public abstract class BaseSolenMatriarch : BaseQuester + { + public BaseSolenMatriarch() + { + Body = 0x328; + + if (!RedSolen) + Hue = 0x44E; + + SpeechHue = 0; + } + + public BaseSolenMatriarch(Serial serial) : base(serial) + { + } + + public abstract bool RedSolen { get; } + public override string DefaultName => "the solen matriarch"; + public override bool DisallowAllMoves => false; + + public override int GetIdleSound() => 0x10D; + + public override bool CanTalkTo(PlayerMobile to) + { + if (SolenMatriarchQuest.IsFriend(to, RedSolen)) + return true; + + return to.Quest is SolenMatriarchQuest qs && qs.RedSolen == RedSolen; + } + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + Direction = GetDirectionTo(player); + + if (player.Quest is SolenMatriarchQuest qs && qs.RedSolen == RedSolen) + { + if (qs.IsObjectiveInProgress(typeof(KillInfiltratorsObjective))) + { + qs.AddConversation(new DuringKillInfiltratorsConversation()); + } + else + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + obj.Complete(); + } + else if (qs.IsObjectiveInProgress(typeof(GatherWaterObjective))) + { + qs.AddConversation(new DuringWaterGatheringConversation()); + } + else + { + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + obj.Complete(); + } + else if (qs.IsObjectiveInProgress(typeof(ProcessFungiObjective))) + { + qs.AddConversation(new DuringFungiProcessConversation()); + } + else + { + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + if (SolenMatriarchQuest.GiveRewardTo(player)) + obj.Complete(); + else + qs.AddConversation(new FullBackpackConversation(false)); + } + } + } + } + } + else if (SolenMatriarchQuest.IsFriend(player, RedSolen)) + { + QuestSystem newQuest = new SolenMatriarchQuest(player, RedSolen); + + if (player.Quest == null && QuestSystem.CanOfferQuest(player, typeof(SolenMatriarchQuest))) + newQuest.SendOffer(); + else + newQuest.AddConversation(new DontOfferConversation(true)); + } + } + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (from is PlayerMobile player) + { + if (dropped is Seed) + { + if (player.Quest is SolenMatriarchQuest qs && qs.RedSolen == RedSolen) + { + SayTo(player, 1054080); // Thank you for that plant seed. Those have such wonderful flavor. + } + else + { + QuestSystem newQuest = new SolenMatriarchQuest(player, RedSolen); + + if (player.Quest == null && QuestSystem.CanOfferQuest(player, typeof(SolenMatriarchQuest))) + newQuest.SendOffer(); + else + newQuest.AddConversation( + new DontOfferConversation(SolenMatriarchQuest.IsFriend(player, RedSolen)) + ); + } + + dropped.Delete(); + return true; + } + + if (dropped is ZoogiFungus fungus) + { + OnGivenFungi(player, fungus); + + return fungus.Deleted; + } + } + + return base.OnDragDrop(from, dropped); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (from.Alive) + if (from is PlayerMobile pm) + if (pm.Quest is SolenMatriarchQuest qs && qs.RedSolen == RedSolen) + if (qs.IsObjectiveInProgress(typeof(ProcessFungiObjective))) + list.Add(new ProcessZoogiFungusEntry(this, pm)); + } + + public void OnGivenFungi(PlayerMobile player, ZoogiFungus fungi) + { + Direction = GetDirectionTo(player); + + if (player.Quest is SolenMatriarchQuest qs && qs.RedSolen == RedSolen) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + var amount = fungi.Amount / 2; + + if (amount > 100) + amount = 100; + + if (amount > 0) + { + if (amount * 2 >= fungi.Amount) + fungi.Delete(); + else + fungi.Amount -= amount * 2; + + var powder = new PowderOfTranslocation(amount); + player.AddToBackpack(powder); + + player.SendLocalizedMessage(1054100); // You receive some powder of translocation. + + obj.Complete(); + } + } + } + } + + 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(); + } + + private class ProcessZoogiFungusEntry : ContextMenuEntry + { + private readonly PlayerMobile m_From; + private readonly BaseSolenMatriarch m_Matriarch; + + public ProcessZoogiFungusEntry(BaseSolenMatriarch matriarch, PlayerMobile from) : base(6184) + { + m_Matriarch = matriarch; + m_From = from; + } + + public override void OnClick() + { + if (m_From.Alive) + m_From.Target = new ProcessFungiTarget(m_Matriarch, m_From); + } + } + + private class ProcessFungiTarget : Target + { + private readonly PlayerMobile m_From; + private readonly BaseSolenMatriarch m_Matriarch; + + public ProcessFungiTarget(BaseSolenMatriarch matriarch, PlayerMobile from) : base(-1, false, TargetFlags.None) + { + m_Matriarch = matriarch; + m_From = from; + } + + protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType) + { + from.SendLocalizedMessage(1042021, "", 0x59); // Cancelled. + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted is ZoogiFungus fungus) + { + if (fungus.IsChildOf(m_From.Backpack)) + m_Matriarch.OnGivenFungi(m_From, fungus); + else + m_From.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + } + } + + public class RedSolenMatriarch : BaseSolenMatriarch + { + [Constructible] + public RedSolenMatriarch() + { + } + + public RedSolenMatriarch(Serial serial) : base(serial) + { + } + + public override bool RedSolen => true; + + 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(); + } + } + + public class BlackSolenMatriarch : BaseSolenMatriarch + { + [Constructible] + public BlackSolenMatriarch() + { + } + + public BlackSolenMatriarch(Serial serial) : base(serial) + { + } + + public override bool RedSolen => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Solen Matriarch/Objectives.cs b/Projects/UOContent/Engines/Quests/Solen Matriarch/Objectives.cs index e1a81eb52..09bcc3eeb 100644 --- a/Projects/UOContent/Engines/Quests/Solen Matriarch/Objectives.cs +++ b/Projects/UOContent/Engines/Quests/Solen Matriarch/Objectives.cs @@ -1,142 +1,148 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Matriarch -{ - public class KillInfiltratorsObjective : QuestObjective - { - public override object Message => ((SolenMatriarchQuest)System).RedSolen ? 1054086 : 1054085; - - public override int MaxProgress => 7; - - public override void RenderProgress(BaseQuestGump gump) - { - if (!Completed) - { - // Black/Red Solen Infiltrators killed: - gump.AddHtmlLocalized(70, 260, 270, 100, ((SolenMatriarchQuest)System).RedSolen ? 1054088 : 1054087, - BaseQuestGump.Blue); - gump.AddLabel(70, 280, 0x64, CurProgress.ToString()); - gump.AddLabel(100, 280, 0x64, "/"); - gump.AddLabel(130, 280, 0x64, MaxProgress.ToString()); - } - else - { - base.RenderProgress(gump); - } - } - - public override bool IgnoreYoungProtection(Mobile from) - { - if (Completed) - return false; - - bool redSolen = ((SolenMatriarchQuest)System).RedSolen; - - if (redSolen) - return from is BlackSolenInfiltratorWarrior || from is BlackSolenInfiltratorQueen; - return from is RedSolenInfiltratorWarrior || from is RedSolenInfiltratorQueen; - } - - public override void OnKill(BaseCreature creature, Container corpse) - { - bool redSolen = ((SolenMatriarchQuest)System).RedSolen; - - if (redSolen) - { - if (creature is BlackSolenInfiltratorWarrior || creature is BlackSolenInfiltratorQueen) - CurProgress++; - } - else - { - if (creature is RedSolenInfiltratorWarrior || creature is RedSolenInfiltratorQueen) - CurProgress++; - } - } - - public override void OnComplete() - { - System.AddObjective(new ReturnAfterKillsObjective()); - } - } - - public class ReturnAfterKillsObjective : QuestObjective - { - public override object Message => 1054090; - - public override void OnComplete() - { - System.AddConversation(new GatherWaterConversation()); - } - } - - public class GatherWaterObjective : QuestObjective - { - public override object Message => 1054092; - - public override int MaxProgress => 40; - - public override void RenderProgress(BaseQuestGump gump) - { - if (!Completed) - { - gump.AddHtmlLocalized(70, 260, 270, 100, 1054093, BaseQuestGump.Blue); // Gallons of Water gathered: - gump.AddLabel(70, 280, 0x64, (CurProgress / 5).ToString()); - gump.AddLabel(100, 280, 0x64, "/"); - gump.AddLabel(130, 280, 0x64, (MaxProgress / 5).ToString()); - } - else - { - base.RenderProgress(gump); - } - } - - public override void OnComplete() - { - System.AddObjective(new ReturnAfterWaterObjective()); - } - } - - public class ReturnAfterWaterObjective : QuestObjective - { - public override object Message => 1054095; - - public override void OnComplete() - { - PlayerMobile player = System.From; - bool redSolen = ((SolenMatriarchQuest)System).RedSolen; - - bool friend = SolenMatriarchQuest.IsFriend(player, redSolen); - - System.AddConversation(new ProcessFungiConversation(friend)); - - if (redSolen) - player.SolenFriendship = SolenFriendship.Red; - else - player.SolenFriendship = SolenFriendship.Black; - } - } - - public class ProcessFungiObjective : QuestObjective - { - public override object Message => 1054098; - - public override void OnComplete() - { - if (SolenMatriarchQuest.GiveRewardTo(System.From)) - System.Complete(); - else - System.AddConversation(new FullBackpackConversation(true)); - } - } - - public class GetRewardObjective : QuestObjective - { - public override object Message => 1054149; - - public override void OnComplete() - { - System.AddConversation(new EndConversation()); - } - } -} \ No newline at end of file +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Matriarch +{ + public class KillInfiltratorsObjective : QuestObjective + { + public override object Message => ((SolenMatriarchQuest)System).RedSolen ? 1054086 : 1054085; + + public override int MaxProgress => 7; + + public override void RenderProgress(BaseQuestGump gump) + { + if (!Completed) + { + // Black/Red Solen Infiltrators killed: + gump.AddHtmlLocalized( + 70, + 260, + 270, + 100, + ((SolenMatriarchQuest)System).RedSolen ? 1054088 : 1054087, + BaseQuestGump.Blue + ); + gump.AddLabel(70, 280, 0x64, CurProgress.ToString()); + gump.AddLabel(100, 280, 0x64, "/"); + gump.AddLabel(130, 280, 0x64, MaxProgress.ToString()); + } + else + { + base.RenderProgress(gump); + } + } + + public override bool IgnoreYoungProtection(Mobile from) + { + if (Completed) + return false; + + var redSolen = ((SolenMatriarchQuest)System).RedSolen; + + if (redSolen) + return from is BlackSolenInfiltratorWarrior || from is BlackSolenInfiltratorQueen; + return from is RedSolenInfiltratorWarrior || from is RedSolenInfiltratorQueen; + } + + public override void OnKill(BaseCreature creature, Container corpse) + { + var redSolen = ((SolenMatriarchQuest)System).RedSolen; + + if (redSolen) + { + if (creature is BlackSolenInfiltratorWarrior || creature is BlackSolenInfiltratorQueen) + CurProgress++; + } + else + { + if (creature is RedSolenInfiltratorWarrior || creature is RedSolenInfiltratorQueen) + CurProgress++; + } + } + + public override void OnComplete() + { + System.AddObjective(new ReturnAfterKillsObjective()); + } + } + + public class ReturnAfterKillsObjective : QuestObjective + { + public override object Message => 1054090; + + public override void OnComplete() + { + System.AddConversation(new GatherWaterConversation()); + } + } + + public class GatherWaterObjective : QuestObjective + { + public override object Message => 1054092; + + public override int MaxProgress => 40; + + public override void RenderProgress(BaseQuestGump gump) + { + if (!Completed) + { + gump.AddHtmlLocalized(70, 260, 270, 100, 1054093, BaseQuestGump.Blue); // Gallons of Water gathered: + gump.AddLabel(70, 280, 0x64, (CurProgress / 5).ToString()); + gump.AddLabel(100, 280, 0x64, "/"); + gump.AddLabel(130, 280, 0x64, (MaxProgress / 5).ToString()); + } + else + { + base.RenderProgress(gump); + } + } + + public override void OnComplete() + { + System.AddObjective(new ReturnAfterWaterObjective()); + } + } + + public class ReturnAfterWaterObjective : QuestObjective + { + public override object Message => 1054095; + + public override void OnComplete() + { + var player = System.From; + var redSolen = ((SolenMatriarchQuest)System).RedSolen; + + var friend = SolenMatriarchQuest.IsFriend(player, redSolen); + + System.AddConversation(new ProcessFungiConversation(friend)); + + if (redSolen) + player.SolenFriendship = SolenFriendship.Red; + else + player.SolenFriendship = SolenFriendship.Black; + } + } + + public class ProcessFungiObjective : QuestObjective + { + public override object Message => 1054098; + + public override void OnComplete() + { + if (SolenMatriarchQuest.GiveRewardTo(System.From)) + System.Complete(); + else + System.AddConversation(new FullBackpackConversation(true)); + } + } + + public class GetRewardObjective : QuestObjective + { + public override object Message => 1054149; + + public override void OnComplete() + { + System.AddConversation(new EndConversation()); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Solen Matriarch/SolenMatriarchQuest.cs b/Projects/UOContent/Engines/Quests/Solen Matriarch/SolenMatriarchQuest.cs index e727e047f..c0c9ac9c0 100644 --- a/Projects/UOContent/Engines/Quests/Solen Matriarch/SolenMatriarchQuest.cs +++ b/Projects/UOContent/Engines/Quests/Solen Matriarch/SolenMatriarchQuest.cs @@ -1,121 +1,121 @@ -using System; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Matriarch -{ - public class SolenMatriarchQuest : QuestSystem - { - private static readonly Type[] m_TypeReferenceTable = - { - typeof(DontOfferConversation), - typeof(AcceptConversation), - typeof(DuringKillInfiltratorsConversation), - typeof(GatherWaterConversation), - typeof(DuringWaterGatheringConversation), - typeof(ProcessFungiConversation), - typeof(DuringFungiProcessConversation), - typeof(FullBackpackConversation), - typeof(EndConversation), - typeof(KillInfiltratorsObjective), - typeof(ReturnAfterKillsObjective), - typeof(GatherWaterObjective), - typeof(ReturnAfterWaterObjective), - typeof(ProcessFungiObjective), - typeof(GetRewardObjective) - }; - - public SolenMatriarchQuest(PlayerMobile from, bool redSolen) : base(from) => RedSolen = redSolen; - - // Serialization - public SolenMatriarchQuest() - { - } - - public override Type[] TypeReferenceTable => m_TypeReferenceTable; - - public override object Name => 1054147; - - public override object OfferMessage - { - get - { - if (IsFriend(From, RedSolen)) return 1054083; - - /* The Solen Matriarch smiles happily as she eats the seed you offered.

- * - * I think you for that seed. I was quite delicious. So full of flavor.

- * - * Hmm... if you would like, I could make you a friend of my colony. This would stop - * the warriors, workers, and queens of my colony from thinking you are an intruder, - * thus they would not attack you. In addition, as a friend of my colony I will process - * zoogi fungus into powder of translocation for you.

- * - * To become a friend of my colony, I ask that you complete a couple tasks for me. These - * are the same tasks I will ask of you when you wish me to process zoogi fungus, - * by the way.

- * - * First, I would like for you to eliminate some infiltrators from the other solen colony. - * They are spying on my colony, and I fear for the safety of my people. They must - * be slain.

- * - * After that, I must ask that you gather some water for me. Our water supplies are - * inadequate, so we must try to supplement our reserve using water vats here in our - * lair.

- * - * Will you accept my offer? - */ - return 1054082; - } - } - - public override TimeSpan RestartDelay => TimeSpan.Zero; - public override bool IsTutorial => false; - - public override int Picture => 0x15C9; - - public bool RedSolen { get; private set; } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - RedSolen = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(RedSolen); - } - - public override void Accept() - { - base.Accept(); - - AddConversation(new AcceptConversation()); - } - - public static bool IsFriend(PlayerMobile player, bool redSolen) - { - if (redSolen) - return player.SolenFriendship == SolenFriendship.Red; - return player.SolenFriendship == SolenFriendship.Black; - } - - public static bool GiveRewardTo(PlayerMobile player) - { - Gold gold = new Gold(Utility.RandomMinMax(250, 350)); - - if (player.PlaceInBackpack(gold)) - { - player.SendLocalizedMessage(1054076); // You have been given some gold. - return true; - } - - gold.Delete(); - return false; - } - } -} \ No newline at end of file +using System; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Matriarch +{ + public class SolenMatriarchQuest : QuestSystem + { + private static readonly Type[] m_TypeReferenceTable = + { + typeof(DontOfferConversation), + typeof(AcceptConversation), + typeof(DuringKillInfiltratorsConversation), + typeof(GatherWaterConversation), + typeof(DuringWaterGatheringConversation), + typeof(ProcessFungiConversation), + typeof(DuringFungiProcessConversation), + typeof(FullBackpackConversation), + typeof(EndConversation), + typeof(KillInfiltratorsObjective), + typeof(ReturnAfterKillsObjective), + typeof(GatherWaterObjective), + typeof(ReturnAfterWaterObjective), + typeof(ProcessFungiObjective), + typeof(GetRewardObjective) + }; + + public SolenMatriarchQuest(PlayerMobile from, bool redSolen) : base(from) => RedSolen = redSolen; + + // Serialization + public SolenMatriarchQuest() + { + } + + public override Type[] TypeReferenceTable => m_TypeReferenceTable; + + public override object Name => 1054147; + + public override object OfferMessage + { + get + { + if (IsFriend(From, RedSolen)) return 1054083; + + /* The Solen Matriarch smiles happily as she eats the seed you offered.

+ * + * I think you for that seed. I was quite delicious. So full of flavor.

+ * + * Hmm... if you would like, I could make you a friend of my colony. This would stop + * the warriors, workers, and queens of my colony from thinking you are an intruder, + * thus they would not attack you. In addition, as a friend of my colony I will process + * zoogi fungus into powder of translocation for you.

+ * + * To become a friend of my colony, I ask that you complete a couple tasks for me. These + * are the same tasks I will ask of you when you wish me to process zoogi fungus, + * by the way.

+ * + * First, I would like for you to eliminate some infiltrators from the other solen colony. + * They are spying on my colony, and I fear for the safety of my people. They must + * be slain.

+ * + * After that, I must ask that you gather some water for me. Our water supplies are + * inadequate, so we must try to supplement our reserve using water vats here in our + * lair.

+ * + * Will you accept my offer? + */ + return 1054082; + } + } + + public override TimeSpan RestartDelay => TimeSpan.Zero; + public override bool IsTutorial => false; + + public override int Picture => 0x15C9; + + public bool RedSolen { get; private set; } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + RedSolen = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(RedSolen); + } + + public override void Accept() + { + base.Accept(); + + AddConversation(new AcceptConversation()); + } + + public static bool IsFriend(PlayerMobile player, bool redSolen) + { + if (redSolen) + return player.SolenFriendship == SolenFriendship.Red; + return player.SolenFriendship == SolenFriendship.Black; + } + + public static bool GiveRewardTo(PlayerMobile player) + { + var gold = new Gold(Utility.RandomMinMax(250, 350)); + + if (player.PlaceInBackpack(gold)) + { + player.SendLocalizedMessage(1054076); // You have been given some gold. + return true; + } + + gold.Delete(); + return false; + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Study of the Solen Hive/Conversations.cs b/Projects/UOContent/Engines/Quests/Study of the Solen Hive/Conversations.cs index db4a33c65..318096d5e 100644 --- a/Projects/UOContent/Engines/Quests/Study of the Solen Hive/Conversations.cs +++ b/Projects/UOContent/Engines/Quests/Study of the Solen Hive/Conversations.cs @@ -1,53 +1,53 @@ -namespace Server.Engines.Quests.Naturalist -{ - public class DontOfferConversation : QuestConversation - { - public override object Message => 1054052; - - public override bool Logged => false; - } - - public class AcceptConversation : QuestConversation - { - public override object Message => 1054043; - - public override void OnRead() - { - System.AddObjective(new StudyNestsObjective()); - } - } - - public class NaturalistDuringStudyConversation : QuestConversation - { - public override object Message => 1054049; - - public override bool Logged => false; - } - - public class EndConversation : QuestConversation - { - public override object Message => 1054050; - - public override void OnRead() - { - System.Complete(); - } - } - - public class SpecialEndConversation : QuestConversation - { - public override object Message => 1054051; - - public override void OnRead() - { - System.Complete(); - } - } - - public class FullBackpackConversation : QuestConversation - { - public override object Message => 1054053; - - public override bool Logged => false; - } -} \ No newline at end of file +namespace Server.Engines.Quests.Naturalist +{ + public class DontOfferConversation : QuestConversation + { + public override object Message => 1054052; + + public override bool Logged => false; + } + + public class AcceptConversation : QuestConversation + { + public override object Message => 1054043; + + public override void OnRead() + { + System.AddObjective(new StudyNestsObjective()); + } + } + + public class NaturalistDuringStudyConversation : QuestConversation + { + public override object Message => 1054049; + + public override bool Logged => false; + } + + public class EndConversation : QuestConversation + { + public override object Message => 1054050; + + public override void OnRead() + { + System.Complete(); + } + } + + public class SpecialEndConversation : QuestConversation + { + public override object Message => 1054051; + + public override void OnRead() + { + System.Complete(); + } + } + + public class FullBackpackConversation : QuestConversation + { + public override object Message => 1054053; + + public override bool Logged => false; + } +} diff --git a/Projects/UOContent/Engines/Quests/Study of the Solen Hive/Mobiles/Naturalist.cs b/Projects/UOContent/Engines/Quests/Study of the Solen Hive/Mobiles/Naturalist.cs index 6282577fc..9c00a198c 100644 --- a/Projects/UOContent/Engines/Quests/Study of the Solen Hive/Mobiles/Naturalist.cs +++ b/Projects/UOContent/Engines/Quests/Study of the Solen Hive/Mobiles/Naturalist.cs @@ -1,148 +1,148 @@ -using Server.Engines.Plants; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Naturalist -{ - public class Naturalist : BaseQuester - { - [Constructible] - public Naturalist() : base("the Naturalist") - { - } - - public Naturalist(Serial serial) : base(serial) - { - } - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = Race.Human.RandomSkinHue(); - - Female = false; - Body = 0x190; - Name = NameList.RandomName("male"); - } - - public override void InitOutfit() - { - AddItem(new Tunic(0x598)); - AddItem(new LongPants(0x59B)); - AddItem(new Boots()); - - Utility.AssignRandomHair(this); - Utility.AssignRandomFacialHair(this, HairHue); - } - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - if (player.Quest is StudyOfSolenQuest qs && qs.Naturalist == this) - { - StudyNestsObjective study = qs.FindObjective(); - if (study == null) - return; - - if (!study.Completed) - { - PlaySound(0x41F); - qs.AddConversation(new NaturalistDuringStudyConversation()); - return; - } - - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - Seed reward; - - var type = Utility.Random(17) switch - { - 0 => PlantType.CampionFlowers, - 1 => PlantType.Poppies, - 2 => PlantType.Snowdrops, - 3 => PlantType.Bulrushes, - 4 => PlantType.Lilies, - 5 => PlantType.PampasGrass, - 6 => PlantType.Rushes, - 7 => PlantType.ElephantEarPlant, - 8 => PlantType.Fern, - 9 => PlantType.PonytailPalm, - 10 => PlantType.SmallPalm, - 11 => PlantType.CenturyPlant, - 12 => PlantType.WaterPlant, - 13 => PlantType.SnakePlant, - 14 => PlantType.PricklyPearCactus, - 15 => PlantType.BarrelCactus, - _ => PlantType.TribarrelCactus - }; - - if (study.StudiedSpecialNest) - { - reward = new Seed(type, PlantHue.FireRed); - } - else - { - var hue = Utility.Random(3) switch - { - 0 => PlantHue.Pink, - 1 => PlantHue.Magenta, - _ => PlantHue.Aqua - }; - - reward = new Seed(type, hue); - } - - if (player.PlaceInBackpack(reward)) - { - obj.Complete(); - - PlaySound(0x449); - PlaySound(0x41B); - - if (study.StudiedSpecialNest) - qs.AddConversation(new SpecialEndConversation()); - else - qs.AddConversation(new EndConversation()); - } - else - { - reward.Delete(); - - qs.AddConversation(new FullBackpackConversation()); - } - } - } - else - { - QuestSystem newQuest = new StudyOfSolenQuest(player, this); - - if (player.Quest == null && QuestSystem.CanOfferQuest(player, typeof(StudyOfSolenQuest))) - { - PlaySound(0x42F); - newQuest.SendOffer(); - } - else - { - PlaySound(0x448); - newQuest.AddConversation(new DontOfferConversation()); - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +using Server.Engines.Plants; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Naturalist +{ + public class Naturalist : BaseQuester + { + [Constructible] + public Naturalist() : base("the Naturalist") + { + } + + public Naturalist(Serial serial) : base(serial) + { + } + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = Race.Human.RandomSkinHue(); + + Female = false; + Body = 0x190; + Name = NameList.RandomName("male"); + } + + public override void InitOutfit() + { + AddItem(new Tunic(0x598)); + AddItem(new LongPants(0x59B)); + AddItem(new Boots()); + + Utility.AssignRandomHair(this); + Utility.AssignRandomFacialHair(this, HairHue); + } + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + if (player.Quest is StudyOfSolenQuest qs && qs.Naturalist == this) + { + var study = qs.FindObjective(); + if (study == null) + return; + + if (!study.Completed) + { + PlaySound(0x41F); + qs.AddConversation(new NaturalistDuringStudyConversation()); + return; + } + + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + Seed reward; + + var type = Utility.Random(17) switch + { + 0 => PlantType.CampionFlowers, + 1 => PlantType.Poppies, + 2 => PlantType.Snowdrops, + 3 => PlantType.Bulrushes, + 4 => PlantType.Lilies, + 5 => PlantType.PampasGrass, + 6 => PlantType.Rushes, + 7 => PlantType.ElephantEarPlant, + 8 => PlantType.Fern, + 9 => PlantType.PonytailPalm, + 10 => PlantType.SmallPalm, + 11 => PlantType.CenturyPlant, + 12 => PlantType.WaterPlant, + 13 => PlantType.SnakePlant, + 14 => PlantType.PricklyPearCactus, + 15 => PlantType.BarrelCactus, + _ => PlantType.TribarrelCactus + }; + + if (study.StudiedSpecialNest) + { + reward = new Seed(type, PlantHue.FireRed); + } + else + { + var hue = Utility.Random(3) switch + { + 0 => PlantHue.Pink, + 1 => PlantHue.Magenta, + _ => PlantHue.Aqua + }; + + reward = new Seed(type, hue); + } + + if (player.PlaceInBackpack(reward)) + { + obj.Complete(); + + PlaySound(0x449); + PlaySound(0x41B); + + if (study.StudiedSpecialNest) + qs.AddConversation(new SpecialEndConversation()); + else + qs.AddConversation(new EndConversation()); + } + else + { + reward.Delete(); + + qs.AddConversation(new FullBackpackConversation()); + } + } + } + else + { + QuestSystem newQuest = new StudyOfSolenQuest(player, this); + + if (player.Quest == null && QuestSystem.CanOfferQuest(player, typeof(StudyOfSolenQuest))) + { + PlaySound(0x42F); + newQuest.SendOffer(); + } + else + { + PlaySound(0x448); + newQuest.AddConversation(new DontOfferConversation()); + } + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Study of the Solen Hive/NestArea.cs b/Projects/UOContent/Engines/Quests/Study of the Solen Hive/NestArea.cs index 0287483e8..4ee10df47 100644 --- a/Projects/UOContent/Engines/Quests/Study of the Solen Hive/NestArea.cs +++ b/Projects/UOContent/Engines/Quests/Study of the Solen Hive/NestArea.cs @@ -1,64 +1,73 @@ -using System.Linq; - -namespace Server.Engines.Quests.Naturalist -{ - public class NestArea - { - private static readonly NestArea[] m_Areas = - { - new NestArea(false, new Rectangle2D(5861, 1787, 26, 25)), - - new NestArea(false, new Rectangle2D(5734, 1788, 14, 50), - new Rectangle2D(5748, 1800, 3, 34), - new Rectangle2D(5751, 1808, 2, 20)), - - new NestArea(false, new Rectangle2D(5907, 1908, 19, 43)), - - new NestArea(false, new Rectangle2D(5721, 1926, 24, 29), - new Rectangle2D(5745, 1935, 7, 22)), - - new NestArea(true, new Rectangle2D(5651, 1853, 21, 32), - new Rectangle2D(5672, 1857, 6, 20)) - }; - - private readonly Rectangle2D[] m_Rects; - - private NestArea(bool special, params Rectangle2D[] rects) - { - Special = special; - m_Rects = rects; - } - - public static int NonSpecialCount => m_Areas.Count(area => !area.Special); - - public bool Special { get; } - - public int ID - { - get - { - for (int i = 0; i < m_Areas.Length; i++) - if (m_Areas[i] == this) - return i; - return 0; - } - } - - public static NestArea Find(IPoint2D p) - { - return m_Areas.FirstOrDefault(area => area.Contains(p)); - } - - public static NestArea GetByID(int id) - { - if (id >= 0 && id < m_Areas.Length) - return m_Areas[id]; - return null; - } - - public bool Contains(IPoint2D p) - { - return m_Rects.Any(rect => rect.Contains(p)); - } - } -} \ No newline at end of file +using System.Linq; + +namespace Server.Engines.Quests.Naturalist +{ + public class NestArea + { + private static readonly NestArea[] m_Areas = + { + new NestArea(false, new Rectangle2D(5861, 1787, 26, 25)), + + new NestArea( + false, + new Rectangle2D(5734, 1788, 14, 50), + new Rectangle2D(5748, 1800, 3, 34), + new Rectangle2D(5751, 1808, 2, 20) + ), + + new NestArea(false, new Rectangle2D(5907, 1908, 19, 43)), + + new NestArea( + false, + new Rectangle2D(5721, 1926, 24, 29), + new Rectangle2D(5745, 1935, 7, 22) + ), + + new NestArea( + true, + new Rectangle2D(5651, 1853, 21, 32), + new Rectangle2D(5672, 1857, 6, 20) + ) + }; + + private readonly Rectangle2D[] m_Rects; + + private NestArea(bool special, params Rectangle2D[] rects) + { + Special = special; + m_Rects = rects; + } + + public static int NonSpecialCount => m_Areas.Count(area => !area.Special); + + public bool Special { get; } + + public int ID + { + get + { + for (var i = 0; i < m_Areas.Length; i++) + if (m_Areas[i] == this) + return i; + return 0; + } + } + + public static NestArea Find(IPoint2D p) + { + return m_Areas.FirstOrDefault(area => area.Contains(p)); + } + + public static NestArea GetByID(int id) + { + if (id >= 0 && id < m_Areas.Length) + return m_Areas[id]; + return null; + } + + public bool Contains(IPoint2D p) + { + return m_Rects.Any(rect => rect.Contains(p)); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Study of the Solen Hive/Objectives.cs b/Projects/UOContent/Engines/Quests/Study of the Solen Hive/Objectives.cs index 677f678b7..86f4dddc3 100644 --- a/Projects/UOContent/Engines/Quests/Study of the Solen Hive/Objectives.cs +++ b/Projects/UOContent/Engines/Quests/Study of the Solen Hive/Objectives.cs @@ -1,177 +1,182 @@ -using System; -using System.Collections.Generic; -using Server.Mobiles; - -namespace Server.Engines.Quests.Naturalist -{ - public class StudyNestsObjective : QuestObjective - { - private NestArea m_CurrentNest; - - private readonly List m_StudiedNests = new List(); - private DateTime m_StudyBegin; - private StudyState m_StudyState; - - public override object Message => 1054044; - - public override int MaxProgress => NestArea.NonSpecialCount; - - public bool StudiedSpecialNest { get; private set; } - - public override bool GetTimerEvent() => true; - - public override void CheckProgress() - { - PlayerMobile from = System.From; - - if (m_CurrentNest != null) - { - NestArea nest = m_CurrentNest; - - if ((from.Map == Map.Trammel || from.Map == Map.Felucca) && nest.Contains(from)) - { - if (m_StudyState != StudyState.Inactive) - { - TimeSpan time = DateTime.UtcNow - m_StudyBegin; - - if (time > TimeSpan.FromSeconds(30.0)) - { - m_StudiedNests.Add(nest); - m_StudyState = StudyState.Inactive; - - if (m_CurrentNest.Special) - { - from.SendLocalizedMessage( - 1054057); // You complete your examination of this bizarre Egg Nest. The Naturalist will undoubtedly be quite interested in these notes! - StudiedSpecialNest = true; - } - else - { - from.SendLocalizedMessage( - 1054054); // You have completed your study of this Solen Egg Nest. You put your notes away. - CurProgress++; - } - } - else if (m_StudyState == StudyState.FirstStep && time > TimeSpan.FromSeconds(15.0)) - { - if (!nest.Special) - from.SendLocalizedMessage( - 1054058); // You begin recording your completed notes on a bit of parchment. - - m_StudyState = StudyState.SecondStep; - } - } - } - else - { - if (m_StudyState != StudyState.Inactive) - from.SendLocalizedMessage( - 1054046); // You abandon your study of the Solen Egg Nest without gathering the needed information. - - m_CurrentNest = null; - } - } - else if (from.Map == Map.Trammel || from.Map == Map.Felucca) - { - NestArea nest = NestArea.Find(from); - - if (nest != null) - { - m_CurrentNest = nest; - m_StudyBegin = DateTime.UtcNow; - - if (m_StudiedNests.Contains(nest)) - { - m_StudyState = StudyState.Inactive; - - from.SendLocalizedMessage( - 1054047); // You glance at the Egg Nest, realizing you've already studied this one. - } - else - { - m_StudyState = StudyState.FirstStep; - - if (nest.Special) - from.SendLocalizedMessage( - 1054056); // You notice something very odd about this Solen Egg Nest. You begin taking notes. - else - from.SendLocalizedMessage( - 1054045); // You begin studying the Solen Egg Nest to gather information. - - if (from.Female) - from.PlaySound(0x30B); - else - from.PlaySound(0x419); - } - } - } - } - - public override void RenderProgress(BaseQuestGump gump) - { - if (!Completed) - { - gump.AddHtmlLocalized(70, 260, 270, 100, 1054055, BaseQuestGump.Blue); // Solen Nests Studied : - gump.AddLabel(70, 280, 0x64, CurProgress.ToString()); - gump.AddLabel(100, 280, 0x64, "/"); - gump.AddLabel(130, 280, 0x64, MaxProgress.ToString()); - } - else - { - base.RenderProgress(gump); - } - } - - public override void OnComplete() - { - System.AddObjective(new ReturnToNaturalistObjective()); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - int count = reader.ReadEncodedInt(); - for (int i = 0; i < count; i++) - { - NestArea nest = NestArea.GetByID(reader.ReadEncodedInt()); - m_StudiedNests.Add(nest); - } - - StudiedSpecialNest = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.WriteEncodedInt(m_StudiedNests.Count); - foreach (NestArea nest in m_StudiedNests) - writer.WriteEncodedInt(nest.ID); - - writer.Write(StudiedSpecialNest); - } - - private enum StudyState - { - Inactive, - FirstStep, - SecondStep - } - } - - public class ReturnToNaturalistObjective : QuestObjective - { - public override object Message => 1054048; - - public override void RenderProgress(BaseQuestGump gump) - { - string count = NestArea.NonSpecialCount.ToString(); - - gump.AddHtmlLocalized(70, 260, 270, 100, 1054055, BaseQuestGump.Blue); // Solen Nests Studied : - gump.AddLabel(70, 280, 0x64, count); - gump.AddLabel(100, 280, 0x64, "/"); - gump.AddLabel(130, 280, 0x64, count); - } - } -} \ No newline at end of file +using System; +using System.Collections.Generic; + +namespace Server.Engines.Quests.Naturalist +{ + public class StudyNestsObjective : QuestObjective + { + private readonly List m_StudiedNests = new List(); + private NestArea m_CurrentNest; + private DateTime m_StudyBegin; + private StudyState m_StudyState; + + public override object Message => 1054044; + + public override int MaxProgress => NestArea.NonSpecialCount; + + public bool StudiedSpecialNest { get; private set; } + + public override bool GetTimerEvent() => true; + + public override void CheckProgress() + { + var from = System.From; + + if (m_CurrentNest != null) + { + var nest = m_CurrentNest; + + if ((from.Map == Map.Trammel || from.Map == Map.Felucca) && nest.Contains(from)) + { + if (m_StudyState != StudyState.Inactive) + { + var time = DateTime.UtcNow - m_StudyBegin; + + if (time > TimeSpan.FromSeconds(30.0)) + { + m_StudiedNests.Add(nest); + m_StudyState = StudyState.Inactive; + + if (m_CurrentNest.Special) + { + from.SendLocalizedMessage( + 1054057 + ); // You complete your examination of this bizarre Egg Nest. The Naturalist will undoubtedly be quite interested in these notes! + StudiedSpecialNest = true; + } + else + { + from.SendLocalizedMessage( + 1054054 + ); // You have completed your study of this Solen Egg Nest. You put your notes away. + CurProgress++; + } + } + else if (m_StudyState == StudyState.FirstStep && time > TimeSpan.FromSeconds(15.0)) + { + if (!nest.Special) + from.SendLocalizedMessage( + 1054058 + ); // You begin recording your completed notes on a bit of parchment. + + m_StudyState = StudyState.SecondStep; + } + } + } + else + { + if (m_StudyState != StudyState.Inactive) + from.SendLocalizedMessage( + 1054046 + ); // You abandon your study of the Solen Egg Nest without gathering the needed information. + + m_CurrentNest = null; + } + } + else if (from.Map == Map.Trammel || from.Map == Map.Felucca) + { + var nest = NestArea.Find(from); + + if (nest != null) + { + m_CurrentNest = nest; + m_StudyBegin = DateTime.UtcNow; + + if (m_StudiedNests.Contains(nest)) + { + m_StudyState = StudyState.Inactive; + + from.SendLocalizedMessage( + 1054047 + ); // You glance at the Egg Nest, realizing you've already studied this one. + } + else + { + m_StudyState = StudyState.FirstStep; + + if (nest.Special) + from.SendLocalizedMessage( + 1054056 + ); // You notice something very odd about this Solen Egg Nest. You begin taking notes. + else + from.SendLocalizedMessage( + 1054045 + ); // You begin studying the Solen Egg Nest to gather information. + + if (from.Female) + from.PlaySound(0x30B); + else + from.PlaySound(0x419); + } + } + } + } + + public override void RenderProgress(BaseQuestGump gump) + { + if (!Completed) + { + gump.AddHtmlLocalized(70, 260, 270, 100, 1054055, BaseQuestGump.Blue); // Solen Nests Studied : + gump.AddLabel(70, 280, 0x64, CurProgress.ToString()); + gump.AddLabel(100, 280, 0x64, "/"); + gump.AddLabel(130, 280, 0x64, MaxProgress.ToString()); + } + else + { + base.RenderProgress(gump); + } + } + + public override void OnComplete() + { + System.AddObjective(new ReturnToNaturalistObjective()); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + var count = reader.ReadEncodedInt(); + for (var i = 0; i < count; i++) + { + var nest = NestArea.GetByID(reader.ReadEncodedInt()); + m_StudiedNests.Add(nest); + } + + StudiedSpecialNest = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.WriteEncodedInt(m_StudiedNests.Count); + foreach (var nest in m_StudiedNests) + writer.WriteEncodedInt(nest.ID); + + writer.Write(StudiedSpecialNest); + } + + private enum StudyState + { + Inactive, + FirstStep, + SecondStep + } + } + + public class ReturnToNaturalistObjective : QuestObjective + { + public override object Message => 1054048; + + public override void RenderProgress(BaseQuestGump gump) + { + var count = NestArea.NonSpecialCount.ToString(); + + gump.AddHtmlLocalized(70, 260, 270, 100, 1054055, BaseQuestGump.Blue); // Solen Nests Studied : + gump.AddLabel(70, 280, 0x64, count); + gump.AddLabel(100, 280, 0x64, "/"); + gump.AddLabel(130, 280, 0x64, count); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Study of the Solen Hive/StudyOfSolenQuest.cs b/Projects/UOContent/Engines/Quests/Study of the Solen Hive/StudyOfSolenQuest.cs index cd057ce0c..fadba3651 100644 --- a/Projects/UOContent/Engines/Quests/Study of the Solen Hive/StudyOfSolenQuest.cs +++ b/Projects/UOContent/Engines/Quests/Study of the Solen Hive/StudyOfSolenQuest.cs @@ -1,63 +1,63 @@ -using System; -using Server.Mobiles; - -namespace Server.Engines.Quests.Naturalist -{ - public class StudyOfSolenQuest : QuestSystem - { - private static readonly Type[] m_TypeReferenceTable = - { - typeof(StudyNestsObjective), - typeof(ReturnToNaturalistObjective), - typeof(DontOfferConversation), - typeof(AcceptConversation), - typeof(NaturalistDuringStudyConversation), - typeof(EndConversation), - typeof(SpecialEndConversation), - typeof(FullBackpackConversation) - }; - - public StudyOfSolenQuest(PlayerMobile from, Naturalist naturalist) : base(from) => Naturalist = naturalist; - - // Serialization - public StudyOfSolenQuest() - { - } - - public override Type[] TypeReferenceTable => m_TypeReferenceTable; - - public override object Name => 1054041; - - public override object OfferMessage => 1054042; - - public override TimeSpan RestartDelay => TimeSpan.Zero; - public override bool IsTutorial => false; - - public override int Picture => 0x15C7; - - public Naturalist Naturalist { get; private set; } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - Naturalist = (Naturalist)reader.ReadMobile(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(Naturalist); - } - - public override void Accept() - { - base.Accept(); - - Naturalist?.PlaySound(0x431); - - AddConversation(new AcceptConversation()); - } - } -} \ No newline at end of file +using System; +using Server.Mobiles; + +namespace Server.Engines.Quests.Naturalist +{ + public class StudyOfSolenQuest : QuestSystem + { + private static readonly Type[] m_TypeReferenceTable = + { + typeof(StudyNestsObjective), + typeof(ReturnToNaturalistObjective), + typeof(DontOfferConversation), + typeof(AcceptConversation), + typeof(NaturalistDuringStudyConversation), + typeof(EndConversation), + typeof(SpecialEndConversation), + typeof(FullBackpackConversation) + }; + + public StudyOfSolenQuest(PlayerMobile from, Naturalist naturalist) : base(from) => Naturalist = naturalist; + + // Serialization + public StudyOfSolenQuest() + { + } + + public override Type[] TypeReferenceTable => m_TypeReferenceTable; + + public override object Name => 1054041; + + public override object OfferMessage => 1054042; + + public override TimeSpan RestartDelay => TimeSpan.Zero; + public override bool IsTutorial => false; + + public override int Picture => 0x15C7; + + public Naturalist Naturalist { get; private set; } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + Naturalist = (Naturalist)reader.ReadMobile(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(Naturalist); + } + + public override void Accept() + { + base.Accept(); + + Naturalist?.PlaySound(0x431); + + AddConversation(new AcceptConversation()); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Terrible Hatchlings/Conversations.cs b/Projects/UOContent/Engines/Quests/Terrible Hatchlings/Conversations.cs index f3c3623a3..ae8a44c64 100644 --- a/Projects/UOContent/Engines/Quests/Terrible Hatchlings/Conversations.cs +++ b/Projects/UOContent/Engines/Quests/Terrible Hatchlings/Conversations.cs @@ -1,36 +1,36 @@ -namespace Server.Engines.Quests.Zento -{ - public class AcceptConversation : QuestConversation - { - public override object Message => 1049092; - - public override void OnRead() - { - System.AddObjective(new FirstKillObjective()); - } - } - - public class DirectionConversation : QuestConversation - { - public override object Message => 1063323; - - public override bool Logged => false; - } - - public class TakeCareConversation : QuestConversation - { - public override object Message => 1063324; - - public override bool Logged => false; - } - - public class EndConversation : QuestConversation - { - public override object Message => 1063321; - - public override void OnRead() - { - System.Complete(); - } - } -} \ No newline at end of file +namespace Server.Engines.Quests.Zento +{ + public class AcceptConversation : QuestConversation + { + public override object Message => 1049092; + + public override void OnRead() + { + System.AddObjective(new FirstKillObjective()); + } + } + + public class DirectionConversation : QuestConversation + { + public override object Message => 1063323; + + public override bool Logged => false; + } + + public class TakeCareConversation : QuestConversation + { + public override object Message => 1063324; + + public override bool Logged => false; + } + + public class EndConversation : QuestConversation + { + public override object Message => 1063321; + + public override void OnRead() + { + System.Complete(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Terrible Hatchlings/Mobiles/AnsellaGryen.cs b/Projects/UOContent/Engines/Quests/Terrible Hatchlings/Mobiles/AnsellaGryen.cs index f55679176..d637eedbd 100644 --- a/Projects/UOContent/Engines/Quests/Terrible Hatchlings/Mobiles/AnsellaGryen.cs +++ b/Projects/UOContent/Engines/Quests/Terrible Hatchlings/Mobiles/AnsellaGryen.cs @@ -1,142 +1,145 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Zento -{ - public class AnsellaGryen : BaseQuester - { - [Constructible] - public AnsellaGryen() - { - } - - public AnsellaGryen(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Ansella Gryen"; - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = 0x83EA; - - Female = true; - Body = 0x191; - } - - public override void InitOutfit() - { - HairItemID = 0x203B; - HairHue = 0x1BB; - - AddItem(new SamuraiTabi(0x8FD)); - AddItem(new FemaleKimono(0x4B6)); - AddItem(new Obi(0x526)); - - AddItem(new GoldBracelet()); - } - - public override int GetAutoTalkRange(PlayerMobile m) - { - if (m.Quest == null) - return 3; - return -1; - } - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - QuestSystem qs = player.Quest; - - if (qs is TerribleHatchlingsQuest) - { - if (qs.IsObjectiveInProgress(typeof(FirstKillObjective))) - { - qs.AddConversation(new DirectionConversation()); - } - else if (qs.IsObjectiveInProgress(typeof(SecondKillObjective)) - || qs.IsObjectiveInProgress(typeof(ThirdKillObjective))) - { - qs.AddConversation(new TakeCareConversation()); - } - else - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - Container cont = GetNewContainer(); - - cont.DropItem(new Gold(Utility.RandomMinMax(100, 200))); - - if (Utility.RandomBool()) - { - if (Loot.Construct(Loot.SEWeaponTypes) is BaseWeapon weapon) - { - BaseRunicTool.ApplyAttributesTo(weapon, 3, 10, 30); - cont.DropItem(weapon); - } - } - else - { - if (Loot.Construct(Loot.SEArmorTypes) is BaseArmor armor) - { - BaseRunicTool.ApplyAttributesTo(armor, 1, 10, 20); - cont.DropItem(armor); - } - } - - if (player.PlaceInBackpack(cont)) - { - obj.Complete(); - } - else - { - cont.Delete(); - player.SendLocalizedMessage( - 1046260); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. - } - } - } - } - else - { - TerribleHatchlingsQuest newQuest = new TerribleHatchlingsQuest(player); - - if (qs != null) - { - if (contextMenu) - SayTo(player, - 1063322); // Before you can help me with the Terrible Hatchlings, you'll need to finish the quest you've already taken! - } - else if (QuestSystem.CanOfferQuest(player, typeof(TerribleHatchlingsQuest), out bool inRestartPeriod)) - { - newQuest.SendOffer(); - } - else if (inRestartPeriod && contextMenu) - { - SayTo(player, 1049357); // I have nothing more for you at this time. - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - public override void TurnToTokuno() - { - } - } -} \ No newline at end of file +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Zento +{ + public class AnsellaGryen : BaseQuester + { + [Constructible] + public AnsellaGryen() + { + } + + public AnsellaGryen(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Ansella Gryen"; + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = 0x83EA; + + Female = true; + Body = 0x191; + } + + public override void InitOutfit() + { + HairItemID = 0x203B; + HairHue = 0x1BB; + + AddItem(new SamuraiTabi(0x8FD)); + AddItem(new FemaleKimono(0x4B6)); + AddItem(new Obi(0x526)); + + AddItem(new GoldBracelet()); + } + + public override int GetAutoTalkRange(PlayerMobile m) + { + if (m.Quest == null) + return 3; + return -1; + } + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + var qs = player.Quest; + + if (qs is TerribleHatchlingsQuest) + { + if (qs.IsObjectiveInProgress(typeof(FirstKillObjective))) + { + qs.AddConversation(new DirectionConversation()); + } + else if (qs.IsObjectiveInProgress(typeof(SecondKillObjective)) + || qs.IsObjectiveInProgress(typeof(ThirdKillObjective))) + { + qs.AddConversation(new TakeCareConversation()); + } + else + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + var cont = GetNewContainer(); + + cont.DropItem(new Gold(Utility.RandomMinMax(100, 200))); + + if (Utility.RandomBool()) + { + if (Loot.Construct(Loot.SEWeaponTypes) is BaseWeapon weapon) + { + BaseRunicTool.ApplyAttributesTo(weapon, 3, 10, 30); + cont.DropItem(weapon); + } + } + else + { + if (Loot.Construct(Loot.SEArmorTypes) is BaseArmor armor) + { + BaseRunicTool.ApplyAttributesTo(armor, 1, 10, 20); + cont.DropItem(armor); + } + } + + if (player.PlaceInBackpack(cont)) + { + obj.Complete(); + } + else + { + cont.Delete(); + player.SendLocalizedMessage( + 1046260 + ); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. + } + } + } + } + else + { + var newQuest = new TerribleHatchlingsQuest(player); + + if (qs != null) + { + if (contextMenu) + SayTo( + player, + 1063322 + ); // Before you can help me with the Terrible Hatchlings, you'll need to finish the quest you've already taken! + } + else if (QuestSystem.CanOfferQuest(player, typeof(TerribleHatchlingsQuest), out var inRestartPeriod)) + { + newQuest.SendOffer(); + } + else if (inRestartPeriod && contextMenu) + { + SayTo(player, 1049357); // I have nothing more for you at this time. + } + } + } + + 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(); + } + + public override void TurnToTokuno() + { + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Terrible Hatchlings/Objectives.cs b/Projects/UOContent/Engines/Quests/Terrible Hatchlings/Objectives.cs index e4ffa64e8..fa6627f7b 100644 --- a/Projects/UOContent/Engines/Quests/Terrible Hatchlings/Objectives.cs +++ b/Projects/UOContent/Engines/Quests/Terrible Hatchlings/Objectives.cs @@ -1,129 +1,129 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Zento -{ - public class FirstKillObjective : QuestObjective - { - public override object Message => 1063316; - - public override void RenderProgress(BaseQuestGump gump) - { - if (!Completed) - { - // Deathwatch Beetle Hatchlings killed: - gump.AddHtmlLocalized(70, 260, 270, 100, 1063318, 0x12DC6BF); - - gump.AddLabel(70, 280, 0x64, "0"); - gump.AddLabel(100, 280, 0x64, "/"); - gump.AddLabel(130, 280, 0x64, "10"); - } - else - { - base.RenderProgress(gump); - } - } - - public override void OnKill(BaseCreature creature, Container corpse) - { - if (creature is DeathwatchBeetleHatchling) - Complete(); - } - - public override void OnComplete() - { - System.AddObjective(new SecondKillObjective()); - } - } - - public class SecondKillObjective : QuestObjective - { - public override object Message => 1063320; - - public override void RenderProgress(BaseQuestGump gump) - { - if (!Completed) - { - // Deathwatch Beetle Hatchlings killed: - gump.AddHtmlLocalized(70, 260, 270, 100, 1063318, 0x12DC6BF); - - gump.AddLabel(70, 280, 0x64, "1"); - gump.AddLabel(100, 280, 0x64, "/"); - gump.AddLabel(130, 280, 0x64, "10"); - } - else - { - base.RenderProgress(gump); - } - } - - public override void OnKill(BaseCreature creature, Container corpse) - { - if (creature is DeathwatchBeetleHatchling) - { - Complete(); - System.AddObjective(new ThirdKillObjective(2)); - } - } - - public override void OnRead() - { - if (!Completed) - { - Complete(); - System.AddObjective(new ThirdKillObjective(1)); - } - } - } - - public class ThirdKillObjective : QuestObjective - { - public ThirdKillObjective(int startingProgress) => CurProgress = startingProgress; - - public ThirdKillObjective() - { - } - - public override object Message => 1063319; - - public override int MaxProgress => 10; - - public override void RenderProgress(BaseQuestGump gump) - { - if (!Completed) - { - // Deathwatch Beetle Hatchlings killed: - gump.AddHtmlLocalized(70, 260, 270, 100, 1063318, 0x12DC6BF); - - gump.AddLabel(70, 280, 0x64, CurProgress.ToString()); - gump.AddLabel(100, 280, 0x64, "/"); - gump.AddLabel(130, 280, 0x64, "10"); - } - else - { - base.RenderProgress(gump); - } - } - - public override void OnKill(BaseCreature creature, Container corpse) - { - if (creature is DeathwatchBeetleHatchling) - CurProgress++; - } - - public override void OnComplete() - { - System.AddObjective(new ReturnObjective()); - } - } - - public class ReturnObjective : QuestObjective - { - public override object Message => 1063313; - - public override void OnComplete() - { - System.AddConversation(new EndConversation()); - } - } -} \ No newline at end of file +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Zento +{ + public class FirstKillObjective : QuestObjective + { + public override object Message => 1063316; + + public override void RenderProgress(BaseQuestGump gump) + { + if (!Completed) + { + // Deathwatch Beetle Hatchlings killed: + gump.AddHtmlLocalized(70, 260, 270, 100, 1063318, 0x12DC6BF); + + gump.AddLabel(70, 280, 0x64, "0"); + gump.AddLabel(100, 280, 0x64, "/"); + gump.AddLabel(130, 280, 0x64, "10"); + } + else + { + base.RenderProgress(gump); + } + } + + public override void OnKill(BaseCreature creature, Container corpse) + { + if (creature is DeathwatchBeetleHatchling) + Complete(); + } + + public override void OnComplete() + { + System.AddObjective(new SecondKillObjective()); + } + } + + public class SecondKillObjective : QuestObjective + { + public override object Message => 1063320; + + public override void RenderProgress(BaseQuestGump gump) + { + if (!Completed) + { + // Deathwatch Beetle Hatchlings killed: + gump.AddHtmlLocalized(70, 260, 270, 100, 1063318, 0x12DC6BF); + + gump.AddLabel(70, 280, 0x64, "1"); + gump.AddLabel(100, 280, 0x64, "/"); + gump.AddLabel(130, 280, 0x64, "10"); + } + else + { + base.RenderProgress(gump); + } + } + + public override void OnKill(BaseCreature creature, Container corpse) + { + if (creature is DeathwatchBeetleHatchling) + { + Complete(); + System.AddObjective(new ThirdKillObjective(2)); + } + } + + public override void OnRead() + { + if (!Completed) + { + Complete(); + System.AddObjective(new ThirdKillObjective(1)); + } + } + } + + public class ThirdKillObjective : QuestObjective + { + public ThirdKillObjective(int startingProgress) => CurProgress = startingProgress; + + public ThirdKillObjective() + { + } + + public override object Message => 1063319; + + public override int MaxProgress => 10; + + public override void RenderProgress(BaseQuestGump gump) + { + if (!Completed) + { + // Deathwatch Beetle Hatchlings killed: + gump.AddHtmlLocalized(70, 260, 270, 100, 1063318, 0x12DC6BF); + + gump.AddLabel(70, 280, 0x64, CurProgress.ToString()); + gump.AddLabel(100, 280, 0x64, "/"); + gump.AddLabel(130, 280, 0x64, "10"); + } + else + { + base.RenderProgress(gump); + } + } + + public override void OnKill(BaseCreature creature, Container corpse) + { + if (creature is DeathwatchBeetleHatchling) + CurProgress++; + } + + public override void OnComplete() + { + System.AddObjective(new ReturnObjective()); + } + } + + public class ReturnObjective : QuestObjective + { + public override object Message => 1063313; + + public override void OnComplete() + { + System.AddConversation(new EndConversation()); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Terrible Hatchlings/TerribleHatchlingsQuest.cs b/Projects/UOContent/Engines/Quests/Terrible Hatchlings/TerribleHatchlingsQuest.cs index e7c724e69..07ba36d75 100644 --- a/Projects/UOContent/Engines/Quests/Terrible Hatchlings/TerribleHatchlingsQuest.cs +++ b/Projects/UOContent/Engines/Quests/Terrible Hatchlings/TerribleHatchlingsQuest.cs @@ -1,47 +1,47 @@ -using System; -using Server.Mobiles; - -namespace Server.Engines.Quests.Zento -{ - public class TerribleHatchlingsQuest : QuestSystem - { - private static readonly Type[] m_TypeReferenceTable = - { - typeof(AcceptConversation), - typeof(DirectionConversation), - typeof(TakeCareConversation), - typeof(EndConversation), - typeof(FirstKillObjective), - typeof(SecondKillObjective), - typeof(ThirdKillObjective), - typeof(ReturnObjective) - }; - - public TerribleHatchlingsQuest(PlayerMobile from) : base(from) - { - } - - // Serialization - public TerribleHatchlingsQuest() - { - } - - public override Type[] TypeReferenceTable => m_TypeReferenceTable; - - public override object Name => 1063314; - - public override object OfferMessage => 1063315; - - public override TimeSpan RestartDelay => TimeSpan.MaxValue; - public override bool IsTutorial => true; - - public override int Picture => 0x15CF; - - public override void Accept() - { - base.Accept(); - - AddConversation(new AcceptConversation()); - } - } -} \ No newline at end of file +using System; +using Server.Mobiles; + +namespace Server.Engines.Quests.Zento +{ + public class TerribleHatchlingsQuest : QuestSystem + { + private static readonly Type[] m_TypeReferenceTable = + { + typeof(AcceptConversation), + typeof(DirectionConversation), + typeof(TakeCareConversation), + typeof(EndConversation), + typeof(FirstKillObjective), + typeof(SecondKillObjective), + typeof(ThirdKillObjective), + typeof(ReturnObjective) + }; + + public TerribleHatchlingsQuest(PlayerMobile from) : base(from) + { + } + + // Serialization + public TerribleHatchlingsQuest() + { + } + + public override Type[] TypeReferenceTable => m_TypeReferenceTable; + + public override object Name => 1063314; + + public override object OfferMessage => 1063315; + + public override TimeSpan RestartDelay => TimeSpan.MaxValue; + public override bool IsTutorial => true; + + public override int Picture => 0x15CF; + + public override void Accept() + { + base.Accept(); + + AddConversation(new AcceptConversation()); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/The Summoning/Conversations.cs b/Projects/UOContent/Engines/Quests/The Summoning/Conversations.cs index 77ce26b56..5d830010d 100644 --- a/Projects/UOContent/Engines/Quests/The Summoning/Conversations.cs +++ b/Projects/UOContent/Engines/Quests/The Summoning/Conversations.cs @@ -1,55 +1,55 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Doom -{ - public class AcceptConversation : QuestConversation - { - public override object Message => 1050027; - - public override void OnRead() - { - System.AddObjective(new CollectBonesObjective()); - } - } - - public class VanquishDaemonConversation : QuestConversation - { - public override object Message => 1050021; - - public override void OnRead() - { - Victoria victoria = ((TheSummoningQuest)System).Victoria; - - if (victoria == null) - { - System.From.SendMessage("Internal error: unable to find Victoria. Quest unable to continue."); - System.Cancel(); - } - else - { - SummoningAltar altar = victoria.Altar; - - if (altar == null) - { - System.From.SendMessage("Internal error: unable to find summoning altar. Quest unable to continue."); - System.Cancel(); - } - else if (altar.Daemon?.Alive != true) - { - BoneDemon daemon = new BoneDemon(); - - daemon.MoveToWorld(altar.Location, altar.Map); - altar.Daemon = daemon; - - System.AddObjective(new VanquishDaemonObjective(daemon)); - } - else - { - victoria.SayTo(System.From, "The devourer has already been summoned."); - - ((TheSummoningQuest)System).WaitForSummon = true; - } - } - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Doom +{ + public class AcceptConversation : QuestConversation + { + public override object Message => 1050027; + + public override void OnRead() + { + System.AddObjective(new CollectBonesObjective()); + } + } + + public class VanquishDaemonConversation : QuestConversation + { + public override object Message => 1050021; + + public override void OnRead() + { + var victoria = ((TheSummoningQuest)System).Victoria; + + if (victoria == null) + { + System.From.SendMessage("Internal error: unable to find Victoria. Quest unable to continue."); + System.Cancel(); + } + else + { + var altar = victoria.Altar; + + if (altar == null) + { + System.From.SendMessage("Internal error: unable to find summoning altar. Quest unable to continue."); + System.Cancel(); + } + else if (altar.Daemon?.Alive != true) + { + var daemon = new BoneDemon(); + + daemon.MoveToWorld(altar.Location, altar.Map); + altar.Daemon = daemon; + + System.AddObjective(new VanquishDaemonObjective(daemon)); + } + else + { + victoria.SayTo(System.From, "The devourer has already been summoned."); + + ((TheSummoningQuest)System).WaitForSummon = true; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Quests/The Summoning/Items/BellOfTheDead.cs b/Projects/UOContent/Engines/Quests/The Summoning/Items/BellOfTheDead.cs index 57f73a7bf..30b42578a 100644 --- a/Projects/UOContent/Engines/Quests/The Summoning/Items/BellOfTheDead.cs +++ b/Projects/UOContent/Engines/Quests/The Summoning/Items/BellOfTheDead.cs @@ -1,119 +1,131 @@ -using System; -using Server.Items; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.Quests.Doom -{ - public class BellOfTheDead : Item - { - [Constructible] - public BellOfTheDead() : base(0x91A) - { - Hue = 0x835; - Movable = false; - } - - public BellOfTheDead(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1050018; // bell of the dead - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public Chyloth Chyloth { get; set; } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public SkeletalDragon Dragon { get; set; } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public bool Summoning { get; set; } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(GetWorldLocation(), 2)) - BeginSummon(from); - else - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - - public virtual void BeginSummon(Mobile from) - { - if (Chyloth?.Deleted == false) - { - from.SendLocalizedMessage( - 1050010); // The ferry man has already been summoned. There is no need to ring for him again. - } - else if (Dragon?.Deleted == false) - { - from.SendLocalizedMessage( - 1050017); // The ferryman has recently been summoned already. You decide against ringing the bell again so soon. - } - else if (!Summoning) - { - Summoning = true; - - Effects.PlaySound(GetWorldLocation(), Map, 0x100); - - Timer.DelayCall(TimeSpan.FromSeconds(8.0), EndSummon, from); - } - } - - public virtual void EndSummon(Mobile from) - { - if (Chyloth?.Deleted == false) - { - from.SendLocalizedMessage( - 1050010); // The ferry man has already been summoned. There is no need to ring for him again. - } - else if (Dragon?.Deleted == false) - { - from.SendLocalizedMessage( - 1050017); // The ferryman has recently been summoned already. You decide against ringing the bell again so soon. - } - else if (Summoning) - { - Summoning = false; - - Point3D loc = GetWorldLocation(); - - loc.Z -= 16; - - Effects.SendLocationParticles(EffectItem.Create(loc, Map, EffectItem.DefaultDuration), 0x3728, 10, 10, 0, 0, - 2023, 0); - Effects.PlaySound(loc, Map, 0x1FE); - - Chyloth = new Chyloth { Direction = (Direction)(7 & 4 + (int)from.GetDirectionTo(loc)) }; - - Chyloth.MoveToWorld(loc, Map); - - Chyloth.Bell = this; - Chyloth.AngryAt = from; - Chyloth.BeginGiveWarning(); - Chyloth.BeginRemove(TimeSpan.FromSeconds(40.0)); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(Chyloth); - writer.Write(Dragon); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Chyloth = reader.ReadMobile() as Chyloth; - Dragon = reader.ReadMobile() as SkeletalDragon; - - Chyloth?.Delete(); - } - } -} +using System; +using Server.Items; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.Quests.Doom +{ + public class BellOfTheDead : Item + { + [Constructible] + public BellOfTheDead() : base(0x91A) + { + Hue = 0x835; + Movable = false; + } + + public BellOfTheDead(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1050018; // bell of the dead + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public Chyloth Chyloth { get; set; } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public SkeletalDragon Dragon { get; set; } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public bool Summoning { get; set; } + + public override void OnDoubleClick(Mobile from) + { + if (from.InRange(GetWorldLocation(), 2)) + BeginSummon(from); + else + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + + public virtual void BeginSummon(Mobile from) + { + if (Chyloth?.Deleted == false) + { + from.SendLocalizedMessage( + 1050010 + ); // The ferry man has already been summoned. There is no need to ring for him again. + } + else if (Dragon?.Deleted == false) + { + from.SendLocalizedMessage( + 1050017 + ); // The ferryman has recently been summoned already. You decide against ringing the bell again so soon. + } + else if (!Summoning) + { + Summoning = true; + + Effects.PlaySound(GetWorldLocation(), Map, 0x100); + + Timer.DelayCall(TimeSpan.FromSeconds(8.0), EndSummon, from); + } + } + + public virtual void EndSummon(Mobile from) + { + if (Chyloth?.Deleted == false) + { + from.SendLocalizedMessage( + 1050010 + ); // The ferry man has already been summoned. There is no need to ring for him again. + } + else if (Dragon?.Deleted == false) + { + from.SendLocalizedMessage( + 1050017 + ); // The ferryman has recently been summoned already. You decide against ringing the bell again so soon. + } + else if (Summoning) + { + Summoning = false; + + var loc = GetWorldLocation(); + + loc.Z -= 16; + + Effects.SendLocationParticles( + EffectItem.Create(loc, Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 0, + 0, + 2023, + 0 + ); + Effects.PlaySound(loc, Map, 0x1FE); + + Chyloth = new Chyloth { Direction = (Direction)(7 & (4 + (int)@from.GetDirectionTo(loc))) }; + + Chyloth.MoveToWorld(loc, Map); + + Chyloth.Bell = this; + Chyloth.AngryAt = from; + Chyloth.BeginGiveWarning(); + Chyloth.BeginRemove(TimeSpan.FromSeconds(40.0)); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(Chyloth); + writer.Write(Dragon); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + Chyloth = reader.ReadMobile() as Chyloth; + Dragon = reader.ReadMobile() as SkeletalDragon; + + Chyloth?.Delete(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/The Summoning/Items/ChylothShroud.cs b/Projects/UOContent/Engines/Quests/The Summoning/Items/ChylothShroud.cs index 2d0e78622..2dfcd8a7b 100644 --- a/Projects/UOContent/Engines/Quests/The Summoning/Items/ChylothShroud.cs +++ b/Projects/UOContent/Engines/Quests/The Summoning/Items/ChylothShroud.cs @@ -1,30 +1,30 @@ -namespace Server.Engines.Quests.Doom -{ - public class ChylothShroud : Item - { - [Constructible] - public ChylothShroud() : base(0x204E) - { - Hue = 0x846; - Layer = Layer.OuterTorso; - } - - public ChylothShroud(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Engines.Quests.Doom +{ + public class ChylothShroud : Item + { + [Constructible] + public ChylothShroud() : base(0x204E) + { + Hue = 0x846; + Layer = Layer.OuterTorso; + } + + public ChylothShroud(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/The Summoning/Items/ChylothStaff.cs b/Projects/UOContent/Engines/Quests/The Summoning/Items/ChylothStaff.cs index 7ba6ddeac..f42d3dce8 100644 --- a/Projects/UOContent/Engines/Quests/The Summoning/Items/ChylothStaff.cs +++ b/Projects/UOContent/Engines/Quests/The Summoning/Items/ChylothStaff.cs @@ -1,30 +1,30 @@ -using Server.Items; - -namespace Server.Engines.Quests.Doom -{ - public class ChylothStaff : BlackStaff - { - [Constructible] - public ChylothStaff() => Hue = 0x482; - - public ChylothStaff(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041111; // a magic staff - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; + +namespace Server.Engines.Quests.Doom +{ + public class ChylothStaff : BlackStaff + { + [Constructible] + public ChylothStaff() => Hue = 0x482; + + public ChylothStaff(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041111; // a magic staff + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/The Summoning/Items/GoldenSkull.cs b/Projects/UOContent/Engines/Quests/The Summoning/Items/GoldenSkull.cs index 6a059872a..17d9f0527 100644 --- a/Projects/UOContent/Engines/Quests/The Summoning/Items/GoldenSkull.cs +++ b/Projects/UOContent/Engines/Quests/The Summoning/Items/GoldenSkull.cs @@ -1,33 +1,33 @@ -namespace Server.Engines.Quests.Doom -{ - public class GoldenSkull : Item - { - [Constructible] - public GoldenSkull() : base(Utility.Random(0x1AE2, 3)) - { - Weight = 1.0; - Hue = 0x8A5; - LootType = LootType.Blessed; - } - - public GoldenSkull(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061619; // a golden skull - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Engines.Quests.Doom +{ + public class GoldenSkull : Item + { + [Constructible] + public GoldenSkull() : base(Utility.Random(0x1AE2, 3)) + { + Weight = 1.0; + Hue = 0x8A5; + LootType = LootType.Blessed; + } + + public GoldenSkull(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061619; // a golden skull + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/The Summoning/Items/GrandGrimoire.cs b/Projects/UOContent/Engines/Quests/The Summoning/Items/GrandGrimoire.cs index d750111b7..a5e5c8836 100644 --- a/Projects/UOContent/Engines/Quests/The Summoning/Items/GrandGrimoire.cs +++ b/Projects/UOContent/Engines/Quests/The Summoning/Items/GrandGrimoire.cs @@ -1,34 +1,34 @@ -namespace Server.Engines.Quests.Doom -{ - public class GrandGrimoire : Item - { - [Constructible] - public GrandGrimoire() : base(0xEFA) - { - Weight = 1.0; - Hue = 0x835; - Layer = Layer.OneHanded; - LootType = LootType.Blessed; - } - - public GrandGrimoire(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1060801; // The Grand Grimoire - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Engines.Quests.Doom +{ + public class GrandGrimoire : Item + { + [Constructible] + public GrandGrimoire() : base(0xEFA) + { + Weight = 1.0; + Hue = 0x835; + Layer = Layer.OneHanded; + LootType = LootType.Blessed; + } + + public GrandGrimoire(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1060801; // The Grand Grimoire + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/The Summoning/Items/SummoningAltar.cs b/Projects/UOContent/Engines/Quests/The Summoning/Items/SummoningAltar.cs index c8dfcebdb..851875a17 100644 --- a/Projects/UOContent/Engines/Quests/The Summoning/Items/SummoningAltar.cs +++ b/Projects/UOContent/Engines/Quests/The Summoning/Items/SummoningAltar.cs @@ -1,62 +1,62 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Doom -{ - public class SummoningAltar : AbbatoirAddon - { - private BoneDemon m_Daemon; - - [Constructible] - public SummoningAltar() - { - } - - public SummoningAltar(Serial serial) : base(serial) - { - } - - public BoneDemon Daemon - { - get => m_Daemon; - set - { - m_Daemon = value; - CheckDaemon(); - } - } - - public void CheckDaemon() - { - if (m_Daemon?.Alive != true) - { - m_Daemon = null; - Hue = 0; - } - else - { - Hue = 0x66D; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Daemon); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Daemon = reader.ReadMobile() as BoneDemon; - - CheckDaemon(); - } - } -} \ No newline at end of file +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Doom +{ + public class SummoningAltar : AbbatoirAddon + { + private BoneDemon m_Daemon; + + [Constructible] + public SummoningAltar() + { + } + + public SummoningAltar(Serial serial) : base(serial) + { + } + + public BoneDemon Daemon + { + get => m_Daemon; + set + { + m_Daemon = value; + CheckDaemon(); + } + } + + public void CheckDaemon() + { + if (m_Daemon?.Alive != true) + { + m_Daemon = null; + Hue = 0; + } + else + { + Hue = 0x66D; + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Daemon); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Daemon = reader.ReadMobile() as BoneDemon; + + CheckDaemon(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/The Summoning/Mobiles/Chyloth.cs b/Projects/UOContent/Engines/Quests/The Summoning/Mobiles/Chyloth.cs index 8ef295114..4e976a4a8 100644 --- a/Projects/UOContent/Engines/Quests/The Summoning/Mobiles/Chyloth.cs +++ b/Projects/UOContent/Engines/Quests/The Summoning/Mobiles/Chyloth.cs @@ -1,305 +1,339 @@ -using System; -using Server.Engines.PartySystem; -using Server.Gumps; -using Server.Items; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.Quests.Doom -{ - public class Chyloth : BaseQuester - { - private static readonly int[] m_Offsets = - { - -1, -1, - -1, 0, - -1, 1, - 0, -1, - 0, 1, - 1, -1, - 1, 0, - 1, 1 - }; - - [Constructible] - public Chyloth() : base("the Ferryman") - { - } - - public Chyloth(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Chyloth"; - - public BellOfTheDead Bell { get; set; } - - public Mobile AngryAt { get; set; } - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = 0x8455; - Body = 0x190; - } - - public override void InitOutfit() - { - EquipItem(new ChylothShroud()); - EquipItem(new ChylothStaff()); - } - - public virtual void BeginGiveWarning() - { - if (Deleted || AngryAt == null) - return; - - Timer.DelayCall(TimeSpan.FromSeconds(4.0), EndGiveWarning); - } - - public virtual void EndGiveWarning() - { - if (Deleted || AngryAt == null) - return; - - PublicOverheadMessage(MessageType.Regular, 0x3B2, 1050013, - AngryAt.Name); // You have summoned me in vain ~1_NAME~! Only the dead may cross! - PublicOverheadMessage(MessageType.Regular, 0x3B2, 1050014); // Why have you disturbed me, mortal?!? - - BeginSummonDragon(); - } - - public virtual void BeginSummonDragon() - { - if (Deleted || AngryAt == null) - return; - - Timer.DelayCall(TimeSpan.FromSeconds(30.0), EndSummonDragon); - } - - public virtual void BeginRemove(TimeSpan delay) - { - Timer.DelayCall(delay, EndRemove); - } - - public virtual void EndRemove() - { - if (Deleted) - return; - - Point3D loc = Location; - Map map = Map; - - Effects.SendLocationParticles(EffectItem.Create(loc, map, EffectItem.DefaultDuration), 0x3728, 10, 10, 0, 0, - 2023, 0); - Effects.PlaySound(loc, map, 0x1FE); - - Delete(); - } - - public virtual void EndSummonDragon() - { - if (Deleted || AngryAt == null) - return; - - Map map = AngryAt.Map; - - if (map == null) - return; - - if (!AngryAt.Region.IsPartOf("Doom")) - return; - - PublicOverheadMessage(MessageType.Regular, 0x3B2, 1050015); // Feel the wrath of my legions!!! - PublicOverheadMessage(MessageType.Regular, 0x3B2, false, "MUHAHAHAHA HAHAH HAHA"); // A wee bit crazy, aren't we? - - SkeletalDragon dragon = new SkeletalDragon(); - - int offset = Utility.Random(8) * 2; - - bool foundLoc = false; - - for (int i = 0; i < m_Offsets.Length; i += 2) - { - int x = AngryAt.X + m_Offsets[(offset + i) % m_Offsets.Length]; - int y = AngryAt.Y + m_Offsets[(offset + i + 1) % m_Offsets.Length]; - - if (map.CanSpawnMobile(x, y, AngryAt.Z)) - { - dragon.MoveToWorld(new Point3D(x, y, AngryAt.Z), map); - foundLoc = true; - break; - } - - int z = map.GetAverageZ(x, y); - - if (map.CanSpawnMobile(x, y, z)) - { - dragon.MoveToWorld(new Point3D(x, y, z), map); - foundLoc = true; - break; - } - } - - if (!foundLoc) - dragon.MoveToWorld(AngryAt.Location, map); - - dragon.Combatant = AngryAt; - - if (Bell != null) - Bell.Dragon = dragon; - } - - public static void TeleportToFerry(Mobile from) - { - Point3D loc = new Point3D(408, 251, 2); - Map map = Map.Malas; - - Effects.SendLocationParticles(EffectItem.Create(loc, map, EffectItem.DefaultDuration), 0x3728, 10, 10, 0, 0, - 2023, 0); - Effects.PlaySound(loc, map, 0x1FE); - - TeleportPets(from, loc, map); - - from.MoveToWorld(loc, map); - } - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (dropped is GoldenSkull) - { - dropped.Delete(); - - PublicOverheadMessage(MessageType.Regular, 0x3B2, 1050046, - from.Name); // Very well, ~1_NAME~, I accept your token. You may cross. - BeginRemove(TimeSpan.FromSeconds(4.0)); - - Party p = PartySystem.Party.Get(from); - - for (int i = 0; i < p?.Members.Count; ++i) - { - PartyMemberInfo pmi = p.Members[i]; - Mobile member = pmi.Mobile; - - if (member != from && member.Map == Map.Malas && member.Region.IsPartOf("Doom")) - { - if (AngryAt == member) - AngryAt = null; - - member.CloseGump(); - member.SendGump(new ChylothPartyGump(from, member)); - } - } - - if (AngryAt == from) - AngryAt = null; - - TeleportToFerry(from); - - return false; - } - - return base.OnDragDrop(from, dropped); - } - - public override bool CanTalkTo(PlayerMobile to) => false; - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class ChylothPartyGump : Gump - { - private readonly Mobile m_Leader; - private readonly Mobile m_Member; - - public ChylothPartyGump(Mobile leader, Mobile member) : base(150, 50) - { - m_Leader = leader; - m_Member = member; - - Closable = false; - - AddPage(0); - - AddImage(0, 0, 3600); - - AddImageTiled(0, 14, 15, 200, 3603); - AddImageTiled(380, 14, 14, 200, 3605); - AddImage(0, 201, 3606); - AddImageTiled(15, 201, 370, 16, 3607); - AddImageTiled(15, 0, 370, 16, 3601); - AddImage(380, 0, 3602); - AddImage(380, 201, 3608); - AddImageTiled(15, 15, 365, 190, 2624); - - AddRadio(30, 140, 9727, 9730, true, 1); - AddHtmlLocalized(65, 145, 300, 25, 1050050, 0x7FFF); // Yes, let's go! - - AddRadio(30, 175, 9727, 9730, false, 0); - AddHtmlLocalized(65, 178, 300, 25, 1050049, 0x7FFF); // No thanks, I'd rather stay here. - - AddHtmlLocalized(30, 20, 360, 35, 1050047, 0x7FFF); // Another player has paid Chyloth for your passage across lake Mortis: - - AddHtmlLocalized(30, 105, 345, 40, 1050048, 0x5B2D); // Do you wish to accept their invitation at this time? - - AddImage(65, 72, 5605); - - AddImageTiled(80, 90, 200, 1, 9107); - AddImageTiled(95, 92, 200, 1, 9157); - - AddLabel(90, 70, 1645, leader.Name); - - AddButton(290, 175, 247, 248, 2); - - AddImageTiled(15, 14, 365, 1, 9107); - AddImageTiled(380, 14, 1, 190, 9105); - AddImageTiled(15, 205, 365, 1, 9107); - AddImageTiled(15, 14, 1, 190, 9105); - AddImageTiled(0, 0, 395, 1, 9157); - AddImageTiled(394, 0, 1, 217, 9155); - AddImageTiled(0, 216, 395, 1, 9157); - AddImageTiled(0, 0, 1, 217, 9155); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 2 && info.IsSwitched(1)) - { - if (m_Member.Region.IsPartOf("Doom")) - { - m_Leader.SendLocalizedMessage(1050054, - m_Member.Name); // ~1_NAME~ has accepted your invitation to cross lake Mortis. - - Chyloth.TeleportToFerry(m_Member); - } - else - { - m_Member.SendLocalizedMessage(1050051); // The invitation has been revoked. - } - } - else - { - m_Member.SendLocalizedMessage(1050052); // You have declined their invitation. - m_Leader.SendLocalizedMessage(1050053, - m_Member.Name); // ~1_NAME~ has declined your invitation to cross lake Mortis. - } - } - } -} +using System; +using Server.Gumps; +using Server.Items; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.Quests.Doom +{ + public class Chyloth : BaseQuester + { + private static readonly int[] m_Offsets = + { + -1, -1, + -1, 0, + -1, 1, + 0, -1, + 0, 1, + 1, -1, + 1, 0, + 1, 1 + }; + + [Constructible] + public Chyloth() : base("the Ferryman") + { + } + + public Chyloth(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Chyloth"; + + public BellOfTheDead Bell { get; set; } + + public Mobile AngryAt { get; set; } + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = 0x8455; + Body = 0x190; + } + + public override void InitOutfit() + { + EquipItem(new ChylothShroud()); + EquipItem(new ChylothStaff()); + } + + public virtual void BeginGiveWarning() + { + if (Deleted || AngryAt == null) + return; + + Timer.DelayCall(TimeSpan.FromSeconds(4.0), EndGiveWarning); + } + + public virtual void EndGiveWarning() + { + if (Deleted || AngryAt == null) + return; + + PublicOverheadMessage( + MessageType.Regular, + 0x3B2, + 1050013, + AngryAt.Name + ); // You have summoned me in vain ~1_NAME~! Only the dead may cross! + PublicOverheadMessage(MessageType.Regular, 0x3B2, 1050014); // Why have you disturbed me, mortal?!? + + BeginSummonDragon(); + } + + public virtual void BeginSummonDragon() + { + if (Deleted || AngryAt == null) + return; + + Timer.DelayCall(TimeSpan.FromSeconds(30.0), EndSummonDragon); + } + + public virtual void BeginRemove(TimeSpan delay) + { + Timer.DelayCall(delay, EndRemove); + } + + public virtual void EndRemove() + { + if (Deleted) + return; + + var loc = Location; + var map = Map; + + Effects.SendLocationParticles( + EffectItem.Create(loc, map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 0, + 0, + 2023, + 0 + ); + Effects.PlaySound(loc, map, 0x1FE); + + Delete(); + } + + public virtual void EndSummonDragon() + { + if (Deleted || AngryAt == null) + return; + + var map = AngryAt.Map; + + if (map == null) + return; + + if (!AngryAt.Region.IsPartOf("Doom")) + return; + + PublicOverheadMessage(MessageType.Regular, 0x3B2, 1050015); // Feel the wrath of my legions!!! + PublicOverheadMessage(MessageType.Regular, 0x3B2, false, "MUHAHAHAHA HAHAH HAHA"); // A wee bit crazy, aren't we? + + var dragon = new SkeletalDragon(); + + var offset = Utility.Random(8) * 2; + + var foundLoc = false; + + for (var i = 0; i < m_Offsets.Length; i += 2) + { + var x = AngryAt.X + m_Offsets[(offset + i) % m_Offsets.Length]; + var y = AngryAt.Y + m_Offsets[(offset + i + 1) % m_Offsets.Length]; + + if (map.CanSpawnMobile(x, y, AngryAt.Z)) + { + dragon.MoveToWorld(new Point3D(x, y, AngryAt.Z), map); + foundLoc = true; + break; + } + + var z = map.GetAverageZ(x, y); + + if (map.CanSpawnMobile(x, y, z)) + { + dragon.MoveToWorld(new Point3D(x, y, z), map); + foundLoc = true; + break; + } + } + + if (!foundLoc) + dragon.MoveToWorld(AngryAt.Location, map); + + dragon.Combatant = AngryAt; + + if (Bell != null) + Bell.Dragon = dragon; + } + + public static void TeleportToFerry(Mobile from) + { + var loc = new Point3D(408, 251, 2); + var map = Map.Malas; + + Effects.SendLocationParticles( + EffectItem.Create(loc, map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 0, + 0, + 2023, + 0 + ); + Effects.PlaySound(loc, map, 0x1FE); + + TeleportPets(from, loc, map); + + from.MoveToWorld(loc, map); + } + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (dropped is GoldenSkull) + { + dropped.Delete(); + + PublicOverheadMessage( + MessageType.Regular, + 0x3B2, + 1050046, + from.Name + ); // Very well, ~1_NAME~, I accept your token. You may cross. + BeginRemove(TimeSpan.FromSeconds(4.0)); + + var p = PartySystem.Party.Get(from); + + for (var i = 0; i < p?.Members.Count; ++i) + { + var pmi = p.Members[i]; + var member = pmi.Mobile; + + if (member != from && member.Map == Map.Malas && member.Region.IsPartOf("Doom")) + { + if (AngryAt == member) + AngryAt = null; + + member.CloseGump(); + member.SendGump(new ChylothPartyGump(from, member)); + } + } + + if (AngryAt == from) + AngryAt = null; + + TeleportToFerry(from); + + return false; + } + + return base.OnDragDrop(from, dropped); + } + + public override bool CanTalkTo(PlayerMobile to) => false; + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + } + + 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 class ChylothPartyGump : Gump + { + private readonly Mobile m_Leader; + private readonly Mobile m_Member; + + public ChylothPartyGump(Mobile leader, Mobile member) : base(150, 50) + { + m_Leader = leader; + m_Member = member; + + Closable = false; + + AddPage(0); + + AddImage(0, 0, 3600); + + AddImageTiled(0, 14, 15, 200, 3603); + AddImageTiled(380, 14, 14, 200, 3605); + AddImage(0, 201, 3606); + AddImageTiled(15, 201, 370, 16, 3607); + AddImageTiled(15, 0, 370, 16, 3601); + AddImage(380, 0, 3602); + AddImage(380, 201, 3608); + AddImageTiled(15, 15, 365, 190, 2624); + + AddRadio(30, 140, 9727, 9730, true, 1); + AddHtmlLocalized(65, 145, 300, 25, 1050050, 0x7FFF); // Yes, let's go! + + AddRadio(30, 175, 9727, 9730, false, 0); + AddHtmlLocalized(65, 178, 300, 25, 1050049, 0x7FFF); // No thanks, I'd rather stay here. + + AddHtmlLocalized( + 30, + 20, + 360, + 35, + 1050047, + 0x7FFF + ); // Another player has paid Chyloth for your passage across lake Mortis: + + AddHtmlLocalized(30, 105, 345, 40, 1050048, 0x5B2D); // Do you wish to accept their invitation at this time? + + AddImage(65, 72, 5605); + + AddImageTiled(80, 90, 200, 1, 9107); + AddImageTiled(95, 92, 200, 1, 9157); + + AddLabel(90, 70, 1645, leader.Name); + + AddButton(290, 175, 247, 248, 2); + + AddImageTiled(15, 14, 365, 1, 9107); + AddImageTiled(380, 14, 1, 190, 9105); + AddImageTiled(15, 205, 365, 1, 9107); + AddImageTiled(15, 14, 1, 190, 9105); + AddImageTiled(0, 0, 395, 1, 9157); + AddImageTiled(394, 0, 1, 217, 9155); + AddImageTiled(0, 216, 395, 1, 9157); + AddImageTiled(0, 0, 1, 217, 9155); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 2 && info.IsSwitched(1)) + { + if (m_Member.Region.IsPartOf("Doom")) + { + m_Leader.SendLocalizedMessage( + 1050054, + m_Member.Name + ); // ~1_NAME~ has accepted your invitation to cross lake Mortis. + + Chyloth.TeleportToFerry(m_Member); + } + else + { + m_Member.SendLocalizedMessage(1050051); // The invitation has been revoked. + } + } + else + { + m_Member.SendLocalizedMessage(1050052); // You have declined their invitation. + m_Leader.SendLocalizedMessage( + 1050053, + m_Member.Name + ); // ~1_NAME~ has declined your invitation to cross lake Mortis. + } + } + } +} diff --git a/Projects/UOContent/Engines/Quests/The Summoning/Mobiles/Victoria.cs b/Projects/UOContent/Engines/Quests/The Summoning/Mobiles/Victoria.cs index 3e4d717f4..42fa4a2aa 100644 --- a/Projects/UOContent/Engines/Quests/The Summoning/Mobiles/Victoria.cs +++ b/Projects/UOContent/Engines/Quests/The Summoning/Mobiles/Victoria.cs @@ -1,143 +1,148 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Doom -{ - public class Victoria : BaseQuester - { - private const int AltarRange = 24; - - private SummoningAltar m_Altar; - - [Constructible] - public Victoria() : base("the Sorceress") - { - } - - public Victoria(Serial serial) : base(serial) - { - } - - public override int TalkNumber => 6159; // Ask about Chyloth - public override string DefaultName => "Victoria"; - public override bool ClickTitle => true; - public override bool IsActiveVendor => true; - public override bool DisallowAllMoves => false; - - public SummoningAltar Altar - { - get - { - if (m_Altar?.Deleted != false || m_Altar.Map != Map || - !Utility.InRange(m_Altar.Location, Location, AltarRange)) - foreach (Item item in GetItemsInRange(AltarRange)) - if (item is SummoningAltar altar) - { - m_Altar = altar; - break; - } - - return m_Altar; - } - } - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBMage()); - } - - public override void InitBody() - { - InitStats(100, 100, 25); - - Female = true; - Hue = 0x8835; - Body = 0x191; - } - - public override void InitOutfit() - { - EquipItem(new GrandGrimoire()); - - EquipItem(SetHue(new Sandals(), 0x455)); - EquipItem(SetHue(new SkullCap(), 0x455)); - EquipItem(SetHue(new PlainDress(), 0x455)); - - HairItemID = 0x203C; - HairHue = 0x482; - } - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (from is PlayerMobile player) - { - QuestSystem qs = player.Quest; - - if (qs is TheSummoningQuest) - if (dropped is DaemonBone bones) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - int need = obj.MaxProgress - obj.CurProgress; - - if (bones.Amount < need) - { - obj.CurProgress += bones.Amount; - bones.Delete(); - - qs.ShowQuestLogUpdated(); - } - else - { - obj.Complete(); - bones.Consume(need); - - if (!bones.Deleted) - SayTo(from, - 1050038); // You have already given me all the Daemon bones necessary to weave the spell. Keep these for a later time. - } - } - else - { - // TODO: Accurate? - SayTo(from, - 1050038); // You have already given me all the Daemon bones necessary to weave the spell. Keep these for a later time. - } - - return false; - } - } - - return base.OnDragDrop(from, dropped); - } - - public override bool CanTalkTo(PlayerMobile to) => to.Quest == null && QuestSystem.CanOfferQuest(to, typeof(TheSummoningQuest)); - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - QuestSystem qs = player.Quest; - - if (qs == null && QuestSystem.CanOfferQuest(player, typeof(TheSummoningQuest))) - { - Direction = GetDirectionTo(player); - new TheSummoningQuest(this, player).SendOffer(); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Doom +{ + public class Victoria : BaseQuester + { + private const int AltarRange = 24; + + private SummoningAltar m_Altar; + + [Constructible] + public Victoria() : base("the Sorceress") + { + } + + public Victoria(Serial serial) : base(serial) + { + } + + public override int TalkNumber => 6159; // Ask about Chyloth + public override string DefaultName => "Victoria"; + public override bool ClickTitle => true; + public override bool IsActiveVendor => true; + public override bool DisallowAllMoves => false; + + public SummoningAltar Altar + { + get + { + if (m_Altar?.Deleted != false || m_Altar.Map != Map || + !Utility.InRange(m_Altar.Location, Location, AltarRange)) + foreach (var item in GetItemsInRange(AltarRange)) + if (item is SummoningAltar altar) + { + m_Altar = altar; + break; + } + + return m_Altar; + } + } + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBMage()); + } + + public override void InitBody() + { + InitStats(100, 100, 25); + + Female = true; + Hue = 0x8835; + Body = 0x191; + } + + public override void InitOutfit() + { + EquipItem(new GrandGrimoire()); + + EquipItem(SetHue(new Sandals(), 0x455)); + EquipItem(SetHue(new SkullCap(), 0x455)); + EquipItem(SetHue(new PlainDress(), 0x455)); + + HairItemID = 0x203C; + HairHue = 0x482; + } + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (from is PlayerMobile player) + { + var qs = player.Quest; + + if (qs is TheSummoningQuest) + if (dropped is DaemonBone bones) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + var need = obj.MaxProgress - obj.CurProgress; + + if (bones.Amount < need) + { + obj.CurProgress += bones.Amount; + bones.Delete(); + + qs.ShowQuestLogUpdated(); + } + else + { + obj.Complete(); + bones.Consume(need); + + if (!bones.Deleted) + SayTo( + from, + 1050038 + ); // You have already given me all the Daemon bones necessary to weave the spell. Keep these for a later time. + } + } + else + { + // TODO: Accurate? + SayTo( + from, + 1050038 + ); // You have already given me all the Daemon bones necessary to weave the spell. Keep these for a later time. + } + + return false; + } + } + + return base.OnDragDrop(from, dropped); + } + + public override bool CanTalkTo(PlayerMobile to) => + to.Quest == null && QuestSystem.CanOfferQuest(to, typeof(TheSummoningQuest)); + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + var qs = player.Quest; + + if (qs == null && QuestSystem.CanOfferQuest(player, typeof(TheSummoningQuest))) + { + Direction = GetDirectionTo(player); + new TheSummoningQuest(this, player).SendOffer(); + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/The Summoning/Objectives.cs b/Projects/UOContent/Engines/Quests/The Summoning/Objectives.cs index a4555f46e..880875b16 100644 --- a/Projects/UOContent/Engines/Quests/The Summoning/Objectives.cs +++ b/Projects/UOContent/Engines/Quests/The Summoning/Objectives.cs @@ -1,161 +1,180 @@ -using System.Collections.Generic; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Doom -{ - public class CollectBonesObjective : QuestObjective - { - public override object Message => 1050026; - - public override int MaxProgress => 1000; - - public override void OnComplete() - { - Victoria victoria = ((TheSummoningQuest)System).Victoria; - - if (victoria == null) - { - System.From.SendMessage("Internal error: unable to find Victoria. Quest unable to continue."); - System.Cancel(); - } - else - { - SummoningAltar altar = victoria.Altar; - - if (altar == null) - { - System.From.SendMessage("Internal error: unable to find summoning altar. Quest unable to continue."); - System.Cancel(); - } - else if (altar.Daemon?.Alive != true) - { - System.AddConversation(new VanquishDaemonConversation()); - } - else - { - victoria.SayTo(System.From, - "The devourer has already been summoned. Return when the devourer has been slain and I will summon it for you."); - ((TheSummoningQuest)System).WaitForSummon = true; - } - } - } - - public override void RenderMessage(BaseQuestGump gump) - { - if (CurProgress > 0 && CurProgress < MaxProgress) - gump.AddHtmlObject(70, 130, 300, 100, 1050028, BaseQuestGump.Blue, false, - false); // Victoria has accepted the Daemon bones, but the requirement is not yet met. - else - base.RenderMessage(gump); - } - - public override void RenderProgress(BaseQuestGump gump) - { - if (CurProgress > 0 && CurProgress < MaxProgress) - { - gump.AddHtmlObject(70, 260, 270, 100, 1050019, BaseQuestGump.Blue, false, - false); // Number of bones collected: - - gump.AddLabel(70, 280, 100, CurProgress.ToString()); - gump.AddLabel(100, 280, 100, "/"); - gump.AddLabel(130, 280, 100, MaxProgress.ToString()); - } - else - { - base.RenderProgress(gump); - } - } - } - - public class VanquishDaemonObjective : QuestObjective - { - private BoneDemon m_Daemon; - - public VanquishDaemonObjective(BoneDemon daemon) => m_Daemon = daemon; - - // Serialization - public VanquishDaemonObjective() - { - } - - public Corpse CorpseWithSkull { get; set; } - - public override object Message => 1050037; - - public override void CheckProgress() - { - if (m_Daemon?.Alive != true) - Complete(); - } - - public override void OnComplete() - { - Victoria victoria = ((TheSummoningQuest)System).Victoria; - - SummoningAltar altar = victoria?.Altar; - - altar?.CheckDaemon(); - - PlayerMobile from = System.From; - - if (!from.Alive) - { - from.SendLocalizedMessage( - 1050033); // The devourer lies dead, unfortunately so do you. You cannot claim your reward while dead. You will need to face him again. - ((TheSummoningQuest)System).WaitForSummon = true; - } - else - { - bool hasRights = false; - - if (m_Daemon != null) - { - List lootingRights = - BaseCreature.GetLootingRights(m_Daemon.DamageEntries, m_Daemon.HitsMax); - - for (int i = 0; i < lootingRights.Count; ++i) - { - DamageStore ds = lootingRights[i]; - - if (ds.m_HasRight && ds.m_Mobile == from) - { - hasRights = true; - break; - } - } - } - - if (!hasRights) - { - from.SendLocalizedMessage( - 1050034); // The devourer lies dead. Unfortunately you did not sufficiently prove your worth in combating the devourer. Victoria shall summon another incarnation of the devourer to the circle of stones. Try again noble adventurer. - ((TheSummoningQuest)System).WaitForSummon = true; - } - else - { - from.SendLocalizedMessage(1050035); // The devourer lies dead. Search his corpse to claim your prize! - - if (m_Daemon != null) - CorpseWithSkull = m_Daemon.Corpse as Corpse; - } - } - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_Daemon = reader.ReadMobile() as BoneDemon; - CorpseWithSkull = reader.ReadItem() as Corpse; - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(m_Daemon); - writer.Write(CorpseWithSkull); - } - } -} \ No newline at end of file +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Doom +{ + public class CollectBonesObjective : QuestObjective + { + public override object Message => 1050026; + + public override int MaxProgress => 1000; + + public override void OnComplete() + { + var victoria = ((TheSummoningQuest)System).Victoria; + + if (victoria == null) + { + System.From.SendMessage("Internal error: unable to find Victoria. Quest unable to continue."); + System.Cancel(); + } + else + { + var altar = victoria.Altar; + + if (altar == null) + { + System.From.SendMessage("Internal error: unable to find summoning altar. Quest unable to continue."); + System.Cancel(); + } + else if (altar.Daemon?.Alive != true) + { + System.AddConversation(new VanquishDaemonConversation()); + } + else + { + victoria.SayTo( + System.From, + "The devourer has already been summoned. Return when the devourer has been slain and I will summon it for you." + ); + ((TheSummoningQuest)System).WaitForSummon = true; + } + } + } + + public override void RenderMessage(BaseQuestGump gump) + { + if (CurProgress > 0 && CurProgress < MaxProgress) + gump.AddHtmlObject( + 70, + 130, + 300, + 100, + 1050028, + BaseQuestGump.Blue, + false, + false + ); // Victoria has accepted the Daemon bones, but the requirement is not yet met. + else + base.RenderMessage(gump); + } + + public override void RenderProgress(BaseQuestGump gump) + { + if (CurProgress > 0 && CurProgress < MaxProgress) + { + gump.AddHtmlObject( + 70, + 260, + 270, + 100, + 1050019, + BaseQuestGump.Blue, + false, + false + ); // Number of bones collected: + + gump.AddLabel(70, 280, 100, CurProgress.ToString()); + gump.AddLabel(100, 280, 100, "/"); + gump.AddLabel(130, 280, 100, MaxProgress.ToString()); + } + else + { + base.RenderProgress(gump); + } + } + } + + public class VanquishDaemonObjective : QuestObjective + { + private BoneDemon m_Daemon; + + public VanquishDaemonObjective(BoneDemon daemon) => m_Daemon = daemon; + + // Serialization + public VanquishDaemonObjective() + { + } + + public Corpse CorpseWithSkull { get; set; } + + public override object Message => 1050037; + + public override void CheckProgress() + { + if (m_Daemon?.Alive != true) + Complete(); + } + + public override void OnComplete() + { + var victoria = ((TheSummoningQuest)System).Victoria; + + var altar = victoria?.Altar; + + altar?.CheckDaemon(); + + var from = System.From; + + if (!from.Alive) + { + from.SendLocalizedMessage( + 1050033 + ); // The devourer lies dead, unfortunately so do you. You cannot claim your reward while dead. You will need to face him again. + ((TheSummoningQuest)System).WaitForSummon = true; + } + else + { + var hasRights = false; + + if (m_Daemon != null) + { + var lootingRights = + BaseCreature.GetLootingRights(m_Daemon.DamageEntries, m_Daemon.HitsMax); + + for (var i = 0; i < lootingRights.Count; ++i) + { + var ds = lootingRights[i]; + + if (ds.m_HasRight && ds.m_Mobile == from) + { + hasRights = true; + break; + } + } + } + + if (!hasRights) + { + from.SendLocalizedMessage( + 1050034 + ); // The devourer lies dead. Unfortunately you did not sufficiently prove your worth in combating the devourer. Victoria shall summon another incarnation of the devourer to the circle of stones. Try again noble adventurer. + ((TheSummoningQuest)System).WaitForSummon = true; + } + else + { + from.SendLocalizedMessage(1050035); // The devourer lies dead. Search his corpse to claim your prize! + + if (m_Daemon != null) + CorpseWithSkull = m_Daemon.Corpse as Corpse; + } + } + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_Daemon = reader.ReadMobile() as BoneDemon; + CorpseWithSkull = reader.ReadItem() as Corpse; + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(m_Daemon); + writer.Write(CorpseWithSkull); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/The Summoning/TheSummoningQuest.cs b/Projects/UOContent/Engines/Quests/The Summoning/TheSummoningQuest.cs index 3421ed1ab..fe2167ece 100644 --- a/Projects/UOContent/Engines/Quests/The Summoning/TheSummoningQuest.cs +++ b/Projects/UOContent/Engines/Quests/The Summoning/TheSummoningQuest.cs @@ -1,109 +1,110 @@ -using System; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Doom -{ - public class TheSummoningQuest : QuestSystem - { - private static readonly Type[] m_TypeReferenceTable = - { - typeof(AcceptConversation), - typeof(CollectBonesObjective), - typeof(VanquishDaemonConversation), - typeof(VanquishDaemonObjective) - }; - - public TheSummoningQuest(Victoria victoria, PlayerMobile from) : base(from) => Victoria = victoria; - - public TheSummoningQuest() - { - } - - public override Type[] TypeReferenceTable => m_TypeReferenceTable; - - public Victoria Victoria { get; private set; } - - public bool WaitForSummon { get; set; } - - public override object Name => 1050025; - - public override object OfferMessage => 1050020; - - public override bool IsTutorial => false; - public override TimeSpan RestartDelay => TimeSpan.Zero; - public override int Picture => 0x15B5; - - // NOTE: Quest not entirely OSI-accurate: some changes made to prevent numerous OSI bugs - - public override void Slice() - { - if (WaitForSummon && Victoria != null) - { - SummoningAltar altar = Victoria.Altar; - - if (altar != null && altar.Daemon?.Alive != true) - if (From.Map == Victoria.Map && From.InRange(Victoria, 8)) - { - WaitForSummon = false; - - AddConversation(new VanquishDaemonConversation()); - } - } - - base.Slice(); - } - - public static int GetDaemonBonesFor(BaseCreature creature) - { - if (creature?.Controlled != false || creature.Summoned) - return 0; - - int fame = creature.Fame; - - if (fame < 1500) - return Utility.Dice(2, 5, -1); - if (fame < 20000) - return Utility.Dice(2, 4, 8); - return 50; - } - - public override void Cancel() - { - base.Cancel(); - - QuestObjective obj = FindObjective(); - - if (obj?.CurProgress > 0) - { - From.BankBox.DropItem(new DaemonBone(obj.CurProgress)); - - From.SendLocalizedMessage( - 1050030); // The Daemon bones that you have thus far given to Victoria have been returned to you. - } - } - - public override void Accept() - { - base.Accept(); - - AddConversation(new AcceptConversation()); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - Victoria = reader.ReadMobile() as Victoria; - WaitForSummon = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(Victoria); - writer.Write(WaitForSummon); - } - } -} +using System; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Doom +{ + public class TheSummoningQuest : QuestSystem + { + private static readonly Type[] m_TypeReferenceTable = + { + typeof(AcceptConversation), + typeof(CollectBonesObjective), + typeof(VanquishDaemonConversation), + typeof(VanquishDaemonObjective) + }; + + public TheSummoningQuest(Victoria victoria, PlayerMobile from) : base(from) => Victoria = victoria; + + public TheSummoningQuest() + { + } + + public override Type[] TypeReferenceTable => m_TypeReferenceTable; + + public Victoria Victoria { get; private set; } + + public bool WaitForSummon { get; set; } + + public override object Name => 1050025; + + public override object OfferMessage => 1050020; + + public override bool IsTutorial => false; + public override TimeSpan RestartDelay => TimeSpan.Zero; + public override int Picture => 0x15B5; + + // NOTE: Quest not entirely OSI-accurate: some changes made to prevent numerous OSI bugs + + public override void Slice() + { + if (WaitForSummon && Victoria != null) + { + var altar = Victoria.Altar; + + if (altar != null && altar.Daemon?.Alive != true) + if (From.Map == Victoria.Map && From.InRange(Victoria, 8)) + { + WaitForSummon = false; + + AddConversation(new VanquishDaemonConversation()); + } + } + + base.Slice(); + } + + public static int GetDaemonBonesFor(BaseCreature creature) + { + if (creature?.Controlled != false || creature.Summoned) + return 0; + + var fame = creature.Fame; + + if (fame < 1500) + return Utility.Dice(2, 5, -1); + if (fame < 20000) + return Utility.Dice(2, 4, 8); + return 50; + } + + public override void Cancel() + { + base.Cancel(); + + QuestObjective obj = FindObjective(); + + if (obj?.CurProgress > 0) + { + From.BankBox.DropItem(new DaemonBone(obj.CurProgress)); + + From.SendLocalizedMessage( + 1050030 + ); // The Daemon bones that you have thus far given to Victoria have been returned to you. + } + } + + public override void Accept() + { + base.Accept(); + + AddConversation(new AcceptConversation()); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + Victoria = reader.ReadMobile() as Victoria; + WaitForSummon = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(Victoria); + writer.Write(WaitForSummon); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Conversations.cs b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Conversations.cs index 64bdb1f4d..07d93e2f1 100644 --- a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Conversations.cs +++ b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Conversations.cs @@ -1,472 +1,472 @@ -namespace Server.Engines.Quests.Haven -{ - public class AcceptConversation : QuestConversation - { - public override object Message => 1049092; - - public override void OnRead() - { - System.AddObjective(new FindUzeraanBeginObjective()); - } - } - - public class UzeraanTitheConversation : QuestConversation - { - public override object Message => 1060209; - - public override void OnRead() - { - System.AddObjective(new TitheGoldObjective()); - } - } - - public class UzeraanFirstTaskConversation : QuestConversation - { - private static readonly QuestItemInfo[] m_Info = - { - new QuestItemInfo(1023676, 0xE68) // glowing rune - }; - - public override object Message - { - get - { - if (System.From.Profession == 1) // warrior - return 1049088; - - if (System.From.Profession == 2) // magician - return 1049386; - /* Uzeraan nods at you with approval and begins to speak...

- * - * Now that you are ready, let me give you your first task.

- * - * As I mentioned earlier, we have been trying to fight back the wicked - * Horde Minions which have recently begun attacking our cities - * - but to no avail. Our need is great!

- * - * Your first task will be to assess the situation in the mountain pass, - * and help our troops defeat the Horde Minions there.

- * - * Take the road marked with glowing runes, that starts just outside of this mansion. - * Before you go into battle, it would be prudent to - * review combat techniques as well as - * information on healing yourself, - * using your Paladin ability 'Close Wounds'.

- * - * To aid you in your fight, you may also wish to - * purchase equipment from Frank the Blacksmith, - * who is standing just South of here.

- * - * Good luck young Paladin! - */ - return 1060388; - } - } - - public override QuestItemInfo[] Info => m_Info; - - public override void OnRead() - { - System.AddObjective(new KillHordeMinionsObjective()); - } - } - - public class UzeraanReportConversation : QuestConversation - { - private static readonly QuestItemInfo[] m_Info = - { - new QuestItemInfo(1026153, 0x1822), // teleporter - new QuestItemInfo(1048032, 0xE76) // a bag - }; - - public override object Message - { - get - { - if (System.From.Profession == 2) // magician - return 1049387; - - /* You give your report to Uzeraan and after a while, - * he begins to speak...

- * - * Your report is grim, but all hope is not lost! It has become apparent - * that our swords and spells will not drive the evil from Haven.

- * - * The head of my order, the High Mage Schmendrick, arrived here shortly after - * you went into battle with the Horde Minions. He has brought with him a - * scroll of great power, that should aid us greatly in our battle.

- * - * Unfortunately, the entrance to one of our mining caves collapsed recently, - * trapping our miners inside.

- * - * Schmendrick went to install magical teleporters inside the mines so that - * the miners would have a way out. The miners have since returned, but Schmendrick has not. - * Those who have returned, all seem to have lost their minds to madness; - * mumbling strange things of "the souls of the dead seeking revenge".

- * - * No matter. We must find Schmendrick.

- * - * Step onto the teleporter, located against the wall, and seek Schmendrick in the mines.

- * - * I've given you a bag with some Night Sight - * and Healing potions - * to help you out along the way. Good luck. - */ - return 1049119; - } - } - - public override QuestItemInfo[] Info => m_Info; - - public override void OnRead() - { - System.AddObjective(new FindSchmendrickObjective()); - } - } - - public class SchmendrickConversation : QuestConversation - { - private static readonly QuestItemInfo[] m_Info = - { - new QuestItemInfo(1023637, 0xE34) // scroll - }; - - public override object Message - { - get - { - if (System.From.Profession == 5) // paladin - return 1060749; - - /* Schmendrick barely pays you any attention as you approach him. His - * mind seems to be occupied with something else. You explain to him that - * you came for the scroll of power and after a long while he begins to speak, - * but apparently still not giving you his full attention...

- * - * Hmmm.. peculiar indeed. Very strange activity here indeed... I wonder...

- * - * Hmmm. Oh yes! Scroll, you say? I don't have it, sorry. My apprentice was - * carrying it, and he ran off to somewhere in this cave. Find him and you will - * find the scroll.

Be sure to bring the scroll to Uzeraan once you - * have it. He's the only person aside from myself who can read the ancient - * markings on the scroll. I need to figure out what's going on down here before - * I can leave. Strange activity indeed...

- * - * Schmendrick goes back to his work and you seem to completely fade from his - * awareness... - */ - return 1049322; - } - } - - public override QuestItemInfo[] Info => m_Info; - - public override void OnRead() - { - System.AddObjective(new FindApprenticeObjective()); - } - } - - public class UzeraanScrollOfPowerConversation : QuestConversation - { - private static readonly QuestItemInfo[] m_Info = - { - new QuestItemInfo(1048030, 0x14EB), // a Treasure Map - new QuestItemInfo(1023969, 0xF81), // Fertile Dirt - new QuestItemInfo(1049117, 0xFC4) // Horn of Retreat - }; - - public override object Message => 1049325; - - public override QuestItemInfo[] Info => m_Info; - - public override void OnRead() - { - System.AddObjective(new FindDryadObjective()); - } - } - - public class DryadConversation : QuestConversation - { - public override object Message => 1049326; - - public override void OnRead() - { - System.AddObjective(new ReturnFertileDirtObjective()); - } - } - - public class UzeraanFertileDirtConversation : QuestConversation - { - private static readonly QuestItemInfo[] m_Info = - { - new QuestItemInfo(1023965, 0xF7D), // Daemon Blood - new QuestItemInfo(1022581, 0xA22) // lantern - }; - - public override object Message - { - get - { - if (System.From.Profession == 2) // magician - return 1049388; - - /* Uzeraan takes the dirt from you and smiles...

- * - * Wonderful! I knew I could count on you. As a token of my appreciation - * I've given you a bag with some bandages as well as some healing potions. - * They should help out a bit.

- * - * The next item I need is a Vial of Blood. I know it seems strange, - * but that's what the formula asks for. I have some locked away in a chest - * not far from here. It's only a short distance from the mansion. Let me give - * you directions...

- * - * Exit the front door to the East. Then follow the path to the North. - * You will pass by several pedestals with lanterns on them. Continue on this - * path until you run into a small hut. Walk up the stairs and through the door. - * Inside you will find a chest. Open it and bring me a Vial of Blood - * from inside the chest. It's very easy to find. Just follow the road and you - * can't miss it.

- * - * Good luck! - */ - return 1049329; - } - } - - public override QuestItemInfo[] Info => m_Info; - - public override void OnRead() - { - System.AddObjective(new GetDaemonBloodObjective()); - } - } - - public class UzeraanDaemonBloodConversation : QuestConversation - { - private static readonly QuestItemInfo[] m_Info = - { - new QuestItemInfo(1017412, 0xF80) // Daemon Bone - }; - - private static readonly QuestItemInfo[] m_InfoPaladin = - { - new QuestItemInfo(1017412, 0xF80), // Daemon Bone - new QuestItemInfo(1060577, 0x1F14) // Recall Rune - }; - - public override object Message - { - get - { - if (System.From.Profession == 2) // magician - return "You hand Uzeraan the Vial of Blood, which he hastily accepts...
" - + "
" - + "Excellent work! Only one reagent remains and the spell is complete! The final " - + "requirement is a Daemon Bone, which will not be as easily acquired as the " - + "previous two components.
" - + "
" - + "There is a haunted graveyard on this island, which is the home to many undead " - + "creatures. Dispose of the undead as you see fit. Be sure to search their remains " - + "after you have smitten them, to check for a Daemon Bone. I'm quite sure " - + "that you will find what we seek, if you are thorough enough with your " - + "extermination.
" - + "
" - + "Take these explosion spell scrolls and magical wizard's hat to aid you in your " - + "battle. The scrolls should help you make short work of the undead.
" - + "
" - + "Return here when you have found a Daemon Bone."; - - /* You hand Uzeraan the Vial of Blood, which he hastily accepts...

- * - * Excellent work! Only one reagent remains and the spell is complete! - * The final requirement is a Daemon Bone, which will not be as easily - * acquired as the previous two components.

- * - * There is a haunted graveyard on this island, which is the home to many - * undead creatures. Dispose of the undead as you see fit. Be sure to search - * their remains after you have smitten them, to check for a Daemon Bone. - * I'm quite sure that you will find what we seek, if you are thorough enough - * with your extermination.

- * - * Take this magical silver sword to aid you in your battle. Silver weapons - * will damage the undead twice as much as your regular weapon.

- * - * Return here when you have found a Daemon Bone. - */ - return 1049333; - } - } - - public override QuestItemInfo[] Info - { - get - { - if (System.From.Profession == 5) // paladin - return m_InfoPaladin; - return m_Info; - } - } - - public override void OnRead() - { - System.AddObjective(new GetDaemonBoneObjective()); - } - } - - public class UzeraanDaemonBoneConversation : QuestConversation - { - public override object Message => 1049335; - - public override void OnRead() - { - System.AddObjective(new CashBankCheckObjective()); - } - } - - public class BankerConversation : QuestConversation - { - public override object Message => 1060137; - - public override void OnRead() - { - System.Complete(); - } - } - - public class RadarConversation : QuestConversation - { - public override object Message => 1049660; - - public override bool Logged => false; - } - - public class LostScrollOfPowerConversation : QuestConversation - { - private bool m_FromUzeraan; - - public LostScrollOfPowerConversation(bool fromUzeraan) => m_FromUzeraan = fromUzeraan; - - public LostScrollOfPowerConversation() - { - } - - public override object Message - { - get - { - if (m_FromUzeraan) return 1049377; - - /* You've lost the scroll? Argh! I will have to try and re-construct - * the scroll from memory. Bring me a blank scroll, which you can - * purchase from the mage shop just - * East of Uzeraan's mansion in Haven.

- * - * Return the scroll to me and I will try to make another scroll for you.

- * - * When you return, be sure to hand me the scroll (drag and drop). - */ - return 1049345; - } - } - - public override bool Logged => false; - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_FromUzeraan = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(m_FromUzeraan); - } - } - - public class LostFertileDirtConversation : QuestConversation - { - private bool m_FromUzeraan; - - public LostFertileDirtConversation(bool fromUzeraan) => m_FromUzeraan = fromUzeraan; - - public LostFertileDirtConversation() - { - } - - public override object Message - { - get - { - if (m_FromUzeraan) return 1049374; - - /* You've lost the dirt I gave you?

- * - * My, my, my... What ever shall we do now?

- * - * I can try to make you some more, but I will need something - * that I can transform. Bring me an apple, and I shall - * see what I can do.

- * - * You can buy apples from the - * Provisioner's Shop, which is located a ways East - * of Uzeraan's mansion.

- * - * Hand me the apple when you have it, and I shall see about transforming - * it for you.

- * - * Good luck.

- */ - return 1049359; - } - } - - public override bool Logged => false; - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_FromUzeraan = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(m_FromUzeraan); - } - } - - public class DryadAppleConversation : QuestConversation - { - public override object Message => 1049360; - - public override bool Logged => false; - } - - public class LostDaemonBloodConversation : QuestConversation - { - public override object Message => 1049375; - - public override bool Logged => false; - } - - public class LostDaemonBoneConversation : QuestConversation - { - public override object Message => 1049376; - - public override bool Logged => false; - } - - public class FewReagentsConversation : QuestConversation - { - public override object Message => 1049390; - - public override bool Logged => false; - } -} \ No newline at end of file +namespace Server.Engines.Quests.Haven +{ + public class AcceptConversation : QuestConversation + { + public override object Message => 1049092; + + public override void OnRead() + { + System.AddObjective(new FindUzeraanBeginObjective()); + } + } + + public class UzeraanTitheConversation : QuestConversation + { + public override object Message => 1060209; + + public override void OnRead() + { + System.AddObjective(new TitheGoldObjective()); + } + } + + public class UzeraanFirstTaskConversation : QuestConversation + { + private static readonly QuestItemInfo[] m_Info = + { + new QuestItemInfo(1023676, 0xE68) // glowing rune + }; + + public override object Message + { + get + { + if (System.From.Profession == 1) // warrior + return 1049088; + + if (System.From.Profession == 2) // magician + return 1049386; + /* Uzeraan nods at you with approval and begins to speak...

+ * + * Now that you are ready, let me give you your first task.

+ * + * As I mentioned earlier, we have been trying to fight back the wicked + * Horde Minions which have recently begun attacking our cities + * - but to no avail. Our need is great!

+ * + * Your first task will be to assess the situation in the mountain pass, + * and help our troops defeat the Horde Minions there.

+ * + * Take the road marked with glowing runes, that starts just outside of this mansion. + * Before you go into battle, it would be prudent to + * review combat techniques as well as + * information on healing yourself, + * using your Paladin ability 'Close Wounds'.

+ * + * To aid you in your fight, you may also wish to + * purchase equipment from Frank the Blacksmith, + * who is standing just South of here.

+ * + * Good luck young Paladin! + */ + return 1060388; + } + } + + public override QuestItemInfo[] Info => m_Info; + + public override void OnRead() + { + System.AddObjective(new KillHordeMinionsObjective()); + } + } + + public class UzeraanReportConversation : QuestConversation + { + private static readonly QuestItemInfo[] m_Info = + { + new QuestItemInfo(1026153, 0x1822), // teleporter + new QuestItemInfo(1048032, 0xE76) // a bag + }; + + public override object Message + { + get + { + if (System.From.Profession == 2) // magician + return 1049387; + + /* You give your report to Uzeraan and after a while, + * he begins to speak...

+ * + * Your report is grim, but all hope is not lost! It has become apparent + * that our swords and spells will not drive the evil from Haven.

+ * + * The head of my order, the High Mage Schmendrick, arrived here shortly after + * you went into battle with the Horde Minions. He has brought with him a + * scroll of great power, that should aid us greatly in our battle.

+ * + * Unfortunately, the entrance to one of our mining caves collapsed recently, + * trapping our miners inside.

+ * + * Schmendrick went to install magical teleporters inside the mines so that + * the miners would have a way out. The miners have since returned, but Schmendrick has not. + * Those who have returned, all seem to have lost their minds to madness; + * mumbling strange things of "the souls of the dead seeking revenge".

+ * + * No matter. We must find Schmendrick.

+ * + * Step onto the teleporter, located against the wall, and seek Schmendrick in the mines.

+ * + * I've given you a bag with some Night Sight + * and Healing potions + * to help you out along the way. Good luck. + */ + return 1049119; + } + } + + public override QuestItemInfo[] Info => m_Info; + + public override void OnRead() + { + System.AddObjective(new FindSchmendrickObjective()); + } + } + + public class SchmendrickConversation : QuestConversation + { + private static readonly QuestItemInfo[] m_Info = + { + new QuestItemInfo(1023637, 0xE34) // scroll + }; + + public override object Message + { + get + { + if (System.From.Profession == 5) // paladin + return 1060749; + + /* Schmendrick barely pays you any attention as you approach him. His + * mind seems to be occupied with something else. You explain to him that + * you came for the scroll of power and after a long while he begins to speak, + * but apparently still not giving you his full attention...

+ * + * Hmmm.. peculiar indeed. Very strange activity here indeed... I wonder...

+ * + * Hmmm. Oh yes! Scroll, you say? I don't have it, sorry. My apprentice was + * carrying it, and he ran off to somewhere in this cave. Find him and you will + * find the scroll.

Be sure to bring the scroll to Uzeraan once you + * have it. He's the only person aside from myself who can read the ancient + * markings on the scroll. I need to figure out what's going on down here before + * I can leave. Strange activity indeed...

+ * + * Schmendrick goes back to his work and you seem to completely fade from his + * awareness... + */ + return 1049322; + } + } + + public override QuestItemInfo[] Info => m_Info; + + public override void OnRead() + { + System.AddObjective(new FindApprenticeObjective()); + } + } + + public class UzeraanScrollOfPowerConversation : QuestConversation + { + private static readonly QuestItemInfo[] m_Info = + { + new QuestItemInfo(1048030, 0x14EB), // a Treasure Map + new QuestItemInfo(1023969, 0xF81), // Fertile Dirt + new QuestItemInfo(1049117, 0xFC4) // Horn of Retreat + }; + + public override object Message => 1049325; + + public override QuestItemInfo[] Info => m_Info; + + public override void OnRead() + { + System.AddObjective(new FindDryadObjective()); + } + } + + public class DryadConversation : QuestConversation + { + public override object Message => 1049326; + + public override void OnRead() + { + System.AddObjective(new ReturnFertileDirtObjective()); + } + } + + public class UzeraanFertileDirtConversation : QuestConversation + { + private static readonly QuestItemInfo[] m_Info = + { + new QuestItemInfo(1023965, 0xF7D), // Daemon Blood + new QuestItemInfo(1022581, 0xA22) // lantern + }; + + public override object Message + { + get + { + if (System.From.Profession == 2) // magician + return 1049388; + + /* Uzeraan takes the dirt from you and smiles...

+ * + * Wonderful! I knew I could count on you. As a token of my appreciation + * I've given you a bag with some bandages as well as some healing potions. + * They should help out a bit.

+ * + * The next item I need is a Vial of Blood. I know it seems strange, + * but that's what the formula asks for. I have some locked away in a chest + * not far from here. It's only a short distance from the mansion. Let me give + * you directions...

+ * + * Exit the front door to the East. Then follow the path to the North. + * You will pass by several pedestals with lanterns on them. Continue on this + * path until you run into a small hut. Walk up the stairs and through the door. + * Inside you will find a chest. Open it and bring me a Vial of Blood + * from inside the chest. It's very easy to find. Just follow the road and you + * can't miss it.

+ * + * Good luck! + */ + return 1049329; + } + } + + public override QuestItemInfo[] Info => m_Info; + + public override void OnRead() + { + System.AddObjective(new GetDaemonBloodObjective()); + } + } + + public class UzeraanDaemonBloodConversation : QuestConversation + { + private static readonly QuestItemInfo[] m_Info = + { + new QuestItemInfo(1017412, 0xF80) // Daemon Bone + }; + + private static readonly QuestItemInfo[] m_InfoPaladin = + { + new QuestItemInfo(1017412, 0xF80), // Daemon Bone + new QuestItemInfo(1060577, 0x1F14) // Recall Rune + }; + + public override object Message + { + get + { + if (System.From.Profession == 2) // magician + return "You hand Uzeraan the Vial of Blood, which he hastily accepts...
" + + "
" + + "Excellent work! Only one reagent remains and the spell is complete! The final " + + "requirement is a Daemon Bone, which will not be as easily acquired as the " + + "previous two components.
" + + "
" + + "There is a haunted graveyard on this island, which is the home to many undead " + + "creatures. Dispose of the undead as you see fit. Be sure to search their remains " + + "after you have smitten them, to check for a Daemon Bone. I'm quite sure " + + "that you will find what we seek, if you are thorough enough with your " + + "extermination.
" + + "
" + + "Take these explosion spell scrolls and magical wizard's hat to aid you in your " + + "battle. The scrolls should help you make short work of the undead.
" + + "
" + + "Return here when you have found a Daemon Bone."; + + /* You hand Uzeraan the Vial of Blood, which he hastily accepts...

+ * + * Excellent work! Only one reagent remains and the spell is complete! + * The final requirement is a Daemon Bone, which will not be as easily + * acquired as the previous two components.

+ * + * There is a haunted graveyard on this island, which is the home to many + * undead creatures. Dispose of the undead as you see fit. Be sure to search + * their remains after you have smitten them, to check for a Daemon Bone. + * I'm quite sure that you will find what we seek, if you are thorough enough + * with your extermination.

+ * + * Take this magical silver sword to aid you in your battle. Silver weapons + * will damage the undead twice as much as your regular weapon.

+ * + * Return here when you have found a Daemon Bone. + */ + return 1049333; + } + } + + public override QuestItemInfo[] Info + { + get + { + if (System.From.Profession == 5) // paladin + return m_InfoPaladin; + return m_Info; + } + } + + public override void OnRead() + { + System.AddObjective(new GetDaemonBoneObjective()); + } + } + + public class UzeraanDaemonBoneConversation : QuestConversation + { + public override object Message => 1049335; + + public override void OnRead() + { + System.AddObjective(new CashBankCheckObjective()); + } + } + + public class BankerConversation : QuestConversation + { + public override object Message => 1060137; + + public override void OnRead() + { + System.Complete(); + } + } + + public class RadarConversation : QuestConversation + { + public override object Message => 1049660; + + public override bool Logged => false; + } + + public class LostScrollOfPowerConversation : QuestConversation + { + private bool m_FromUzeraan; + + public LostScrollOfPowerConversation(bool fromUzeraan) => m_FromUzeraan = fromUzeraan; + + public LostScrollOfPowerConversation() + { + } + + public override object Message + { + get + { + if (m_FromUzeraan) return 1049377; + + /* You've lost the scroll? Argh! I will have to try and re-construct + * the scroll from memory. Bring me a blank scroll, which you can + * purchase from the mage shop just + * East of Uzeraan's mansion in Haven.

+ * + * Return the scroll to me and I will try to make another scroll for you.

+ * + * When you return, be sure to hand me the scroll (drag and drop). + */ + return 1049345; + } + } + + public override bool Logged => false; + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_FromUzeraan = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(m_FromUzeraan); + } + } + + public class LostFertileDirtConversation : QuestConversation + { + private bool m_FromUzeraan; + + public LostFertileDirtConversation(bool fromUzeraan) => m_FromUzeraan = fromUzeraan; + + public LostFertileDirtConversation() + { + } + + public override object Message + { + get + { + if (m_FromUzeraan) return 1049374; + + /* You've lost the dirt I gave you?

+ * + * My, my, my... What ever shall we do now?

+ * + * I can try to make you some more, but I will need something + * that I can transform. Bring me an apple, and I shall + * see what I can do.

+ * + * You can buy apples from the + * Provisioner's Shop, which is located a ways East + * of Uzeraan's mansion.

+ * + * Hand me the apple when you have it, and I shall see about transforming + * it for you.

+ * + * Good luck.

+ */ + return 1049359; + } + } + + public override bool Logged => false; + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_FromUzeraan = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(m_FromUzeraan); + } + } + + public class DryadAppleConversation : QuestConversation + { + public override object Message => 1049360; + + public override bool Logged => false; + } + + public class LostDaemonBloodConversation : QuestConversation + { + public override object Message => 1049375; + + public override bool Logged => false; + } + + public class LostDaemonBoneConversation : QuestConversation + { + public override object Message => 1049376; + + public override bool Logged => false; + } + + public class FewReagentsConversation : QuestConversation + { + public override object Message => 1049390; + + public override bool Logged => false; + } +} diff --git a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/Cannon.cs b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/Cannon.cs index 2ea01a7ff..312e97c67 100644 --- a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/Cannon.cs +++ b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/Cannon.cs @@ -1,168 +1,168 @@ -using Server.Items; - -namespace Server.Engines.Quests.Haven -{ - public enum CannonDirection - { - North, - East, - South, - West - } - - public class Cannon : BaseAddon - { - [Constructible] - public Cannon(CannonDirection direction) - { - CannonDirection = direction; - - switch (direction) - { - case CannonDirection.North: - { - AddComponent(new CannonComponent(0xE8D), 0, 0, 0); - AddComponent(new CannonComponent(0xE8C), 0, 1, 0); - AddComponent(new CannonComponent(0xE8B), 0, 2, 0); - - break; - } - case CannonDirection.East: - { - AddComponent(new CannonComponent(0xE96), 0, 0, 0); - AddComponent(new CannonComponent(0xE95), -1, 0, 0); - AddComponent(new CannonComponent(0xE94), -2, 0, 0); - - break; - } - case CannonDirection.South: - { - AddComponent(new CannonComponent(0xE91), 0, 0, 0); - AddComponent(new CannonComponent(0xE92), 0, -1, 0); - AddComponent(new CannonComponent(0xE93), 0, -2, 0); - - break; - } - default: - { - AddComponent(new CannonComponent(0xE8E), 0, 0, 0); - AddComponent(new CannonComponent(0xE8F), 1, 0, 0); - AddComponent(new CannonComponent(0xE90), 2, 0, 0); - - break; - } - } - } - - public Cannon(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public CannonDirection CannonDirection { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public MilitiaCanoneer Canoneer { get; set; } - - public override bool HandlesOnMovement => Canoneer?.Deleted == false && Canoneer.Active; - - public void DoFireEffect(IPoint3D target) - { - var from = CannonDirection switch - { - CannonDirection.North => new Point3D(X, Y - 1, Z), - CannonDirection.East => new Point3D(X + 1, Y, Z), - CannonDirection.South => new Point3D(X, Y + 1, Z), - _ => new Point3D(X - 1, Y, Z) - }; - - Effects.SendLocationEffect(from, Map, 0x36B0, 16, 1); - Effects.PlaySound(from, Map, 0x11D); - - Effects.SendLocationEffect(target, Map, 0x36B0, 16, 1); - Effects.PlaySound(target, Map, 0x11D); - } - - public void Fire(Mobile from, Mobile target) - { - DoFireEffect(target); - - target.Damage(9999, from); - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (!(Canoneer?.Deleted == false && Canoneer.Active)) - return; - - var canFire = CannonDirection switch - { - CannonDirection.North => m.X >= X - 7 && m.X <= X + 7 && m.Y == Y - 7 && oldLocation.Y < Y - 7, - CannonDirection.East => m.Y >= Y - 7 && m.Y <= Y + 7 && m.X == X + 7 && oldLocation.X > X + 7, - CannonDirection.South => m.X >= X - 7 && m.X <= X + 7 && m.Y == Y + 7 && oldLocation.Y > Y + 7, - _ => m.Y >= Y - 7 && m.Y <= Y + 7 && m.X == X - 7 && oldLocation.X < X - 7 - }; - - if (canFire && Canoneer.WillFire(this, m)) - Fire(Canoneer, m); - } - - public override void Serialize(IGenericWriter writer) - { - if (Canoneer?.Deleted == true) - Canoneer = null; - - base.Serialize(writer); - - writer.Write(0); // version - - writer.WriteEncodedInt((int)CannonDirection); - writer.Write(Canoneer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - CannonDirection = (CannonDirection)reader.ReadEncodedInt(); - Canoneer = (MilitiaCanoneer)reader.ReadMobile(); - } - } - - public class CannonComponent : AddonComponent - { - public CannonComponent(int itemID) : base(itemID) - { - } - - public CannonComponent(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public MilitiaCanoneer Canoneer - { - get => Addon is Cannon cannon ? cannon.Canoneer : null; - set - { - if (Addon is Cannon cannon) cannon.Canoneer = value; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using Server.Items; + +namespace Server.Engines.Quests.Haven +{ + public enum CannonDirection + { + North, + East, + South, + West + } + + public class Cannon : BaseAddon + { + [Constructible] + public Cannon(CannonDirection direction) + { + CannonDirection = direction; + + switch (direction) + { + case CannonDirection.North: + { + AddComponent(new CannonComponent(0xE8D), 0, 0, 0); + AddComponent(new CannonComponent(0xE8C), 0, 1, 0); + AddComponent(new CannonComponent(0xE8B), 0, 2, 0); + + break; + } + case CannonDirection.East: + { + AddComponent(new CannonComponent(0xE96), 0, 0, 0); + AddComponent(new CannonComponent(0xE95), -1, 0, 0); + AddComponent(new CannonComponent(0xE94), -2, 0, 0); + + break; + } + case CannonDirection.South: + { + AddComponent(new CannonComponent(0xE91), 0, 0, 0); + AddComponent(new CannonComponent(0xE92), 0, -1, 0); + AddComponent(new CannonComponent(0xE93), 0, -2, 0); + + break; + } + default: + { + AddComponent(new CannonComponent(0xE8E), 0, 0, 0); + AddComponent(new CannonComponent(0xE8F), 1, 0, 0); + AddComponent(new CannonComponent(0xE90), 2, 0, 0); + + break; + } + } + } + + public Cannon(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public CannonDirection CannonDirection { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public MilitiaCanoneer Canoneer { get; set; } + + public override bool HandlesOnMovement => Canoneer?.Deleted == false && Canoneer.Active; + + public void DoFireEffect(IPoint3D target) + { + var from = CannonDirection switch + { + CannonDirection.North => new Point3D(X, Y - 1, Z), + CannonDirection.East => new Point3D(X + 1, Y, Z), + CannonDirection.South => new Point3D(X, Y + 1, Z), + _ => new Point3D(X - 1, Y, Z) + }; + + Effects.SendLocationEffect(from, Map, 0x36B0, 16, 1); + Effects.PlaySound(from, Map, 0x11D); + + Effects.SendLocationEffect(target, Map, 0x36B0, 16, 1); + Effects.PlaySound(target, Map, 0x11D); + } + + public void Fire(Mobile from, Mobile target) + { + DoFireEffect(target); + + target.Damage(9999, from); + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (!(Canoneer?.Deleted == false && Canoneer.Active)) + return; + + var canFire = CannonDirection switch + { + CannonDirection.North => m.X >= X - 7 && m.X <= X + 7 && m.Y == Y - 7 && oldLocation.Y < Y - 7, + CannonDirection.East => m.Y >= Y - 7 && m.Y <= Y + 7 && m.X == X + 7 && oldLocation.X > X + 7, + CannonDirection.South => m.X >= X - 7 && m.X <= X + 7 && m.Y == Y + 7 && oldLocation.Y > Y + 7, + _ => m.Y >= Y - 7 && m.Y <= Y + 7 && m.X == X - 7 && oldLocation.X < X - 7 + }; + + if (canFire && Canoneer.WillFire(this, m)) + Fire(Canoneer, m); + } + + public override void Serialize(IGenericWriter writer) + { + if (Canoneer?.Deleted == true) + Canoneer = null; + + base.Serialize(writer); + + writer.Write(0); // version + + writer.WriteEncodedInt((int)CannonDirection); + writer.Write(Canoneer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + CannonDirection = (CannonDirection)reader.ReadEncodedInt(); + Canoneer = (MilitiaCanoneer)reader.ReadMobile(); + } + } + + public class CannonComponent : AddonComponent + { + public CannonComponent(int itemID) : base(itemID) + { + } + + public CannonComponent(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public MilitiaCanoneer Canoneer + { + get => Addon is Cannon cannon ? cannon.Canoneer : null; + set + { + if (Addon is Cannon cannon) cannon.Canoneer = value; + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/DaemonBloodChest.cs b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/DaemonBloodChest.cs index c74810669..c81db5fe2 100644 --- a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/DaemonBloodChest.cs +++ b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/DaemonBloodChest.cs @@ -1,66 +1,72 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Haven -{ - public class DaemonBloodChest : MetalChest - { - [Constructible] - public DaemonBloodChest() => Movable = false; - - public DaemonBloodChest(Serial serial) : base(serial) - { - } - - public override void OnDoubleClick(Mobile from) - { - if (from is PlayerMobile player && player.InRange(GetWorldLocation(), 2)) - { - QuestSystem qs = player.Quest; - - if (qs is UzeraanTurmoilQuest) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false || UzeraanTurmoilQuest.HasLostDaemonBlood(player)) - { - Item vial = new QuestDaemonBlood(); - - if (player.PlaceInBackpack(vial)) - { - player.SendLocalizedMessage(1049331, "", - 0x22); // You take a vial of blood from the chest and put it in your pack. - - if (obj?.Completed == false) - obj.Complete(); - } - else - { - player.SendLocalizedMessage(1049338, "", - 0x22); // You find a vial of blood, but can't pick it up because your pack is too full. Come back when you have more room in your pack. - vial.Delete(); - } - - return; - } - } - } - - base.OnDoubleClick(from); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Haven +{ + public class DaemonBloodChest : MetalChest + { + [Constructible] + public DaemonBloodChest() => Movable = false; + + public DaemonBloodChest(Serial serial) : base(serial) + { + } + + public override void OnDoubleClick(Mobile from) + { + if (from is PlayerMobile player && player.InRange(GetWorldLocation(), 2)) + { + var qs = player.Quest; + + if (qs is UzeraanTurmoilQuest) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false || UzeraanTurmoilQuest.HasLostDaemonBlood(player)) + { + Item vial = new QuestDaemonBlood(); + + if (player.PlaceInBackpack(vial)) + { + player.SendLocalizedMessage( + 1049331, + "", + 0x22 + ); // You take a vial of blood from the chest and put it in your pack. + + if (obj?.Completed == false) + obj.Complete(); + } + else + { + player.SendLocalizedMessage( + 1049338, + "", + 0x22 + ); // You find a vial of blood, but can't pick it up because your pack is too full. Come back when you have more room in your pack. + vial.Delete(); + } + + return; + } + } + } + + base.OnDoubleClick(from); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/QuestDaemonBlood.cs b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/QuestDaemonBlood.cs index aa9a98862..a1e7faaa7 100644 --- a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/QuestDaemonBlood.cs +++ b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/QuestDaemonBlood.cs @@ -1,30 +1,30 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Haven -{ - public class QuestDaemonBlood : QuestItem - { - [Constructible] - public QuestDaemonBlood() : base(0xF7D) => Weight = 1.0; - - public QuestDaemonBlood(Serial serial) : base(serial) - { - } - - public override bool CanDrop(PlayerMobile player) => !(player.Quest is UzeraanTurmoilQuest); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Haven +{ + public class QuestDaemonBlood : QuestItem + { + [Constructible] + public QuestDaemonBlood() : base(0xF7D) => Weight = 1.0; + + public QuestDaemonBlood(Serial serial) : base(serial) + { + } + + public override bool CanDrop(PlayerMobile player) => !(player.Quest is UzeraanTurmoilQuest); + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/QuestDaemonBone.cs b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/QuestDaemonBone.cs index 43c77c4cf..d1da95128 100644 --- a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/QuestDaemonBone.cs +++ b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/QuestDaemonBone.cs @@ -1,30 +1,30 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Haven -{ - public class QuestDaemonBone : QuestItem - { - [Constructible] - public QuestDaemonBone() : base(0xF80) => Weight = 1.0; - - public QuestDaemonBone(Serial serial) : base(serial) - { - } - - public override bool CanDrop(PlayerMobile player) => !(player.Quest is UzeraanTurmoilQuest); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Haven +{ + public class QuestDaemonBone : QuestItem + { + [Constructible] + public QuestDaemonBone() : base(0xF80) => Weight = 1.0; + + public QuestDaemonBone(Serial serial) : base(serial) + { + } + + public override bool CanDrop(PlayerMobile player) => !(player.Quest is UzeraanTurmoilQuest); + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/QuestFertileDirt.cs b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/QuestFertileDirt.cs index 9dde67ff4..c596f15cb 100644 --- a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/QuestFertileDirt.cs +++ b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/QuestFertileDirt.cs @@ -1,30 +1,30 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Haven -{ - public class QuestFertileDirt : QuestItem - { - [Constructible] - public QuestFertileDirt() : base(0xF81) => Weight = 1.0; - - public QuestFertileDirt(Serial serial) : base(serial) - { - } - - public override bool CanDrop(PlayerMobile player) => !(player.Quest is UzeraanTurmoilQuest); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Haven +{ + public class QuestFertileDirt : QuestItem + { + [Constructible] + public QuestFertileDirt() : base(0xF81) => Weight = 1.0; + + public QuestFertileDirt(Serial serial) : base(serial) + { + } + + public override bool CanDrop(PlayerMobile player) => !(player.Quest is UzeraanTurmoilQuest); + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/SchmendrickApprenticeCorpse.cs b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/SchmendrickApprenticeCorpse.cs index 79893af17..b5a358e11 100644 --- a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/SchmendrickApprenticeCorpse.cs +++ b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/SchmendrickApprenticeCorpse.cs @@ -1,175 +1,201 @@ -using System.Collections.Generic; -using Server.Items; -using Server.Misc; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.Quests.Haven -{ - public class SchmendrickApprenticeCorpse : Corpse - { - private static int m_HairHue; - - private Lantern m_Lantern; - - [Constructible] - public SchmendrickApprenticeCorpse() : base(GetOwner(), GetHair(), GetFacialHair(), GetEquipment()) - { - Direction = Direction.West; - - foreach (Item item in EquipItems) - DropItem(item); - - m_Lantern = new Lantern { Movable = false, Protected = true }; - m_Lantern.Ignite(); - } - - public SchmendrickApprenticeCorpse(Serial serial) : base(serial) - { - } - - // TODO: What is this? Why are we creating and deleting a mobile? - private static Mobile GetOwner() - { - Mobile apprentice = new Mobile(); - - apprentice.Hue = Race.Human.RandomSkinHue(); - apprentice.Female = false; - apprentice.Body = 0x190; - apprentice.Name = NameList.RandomName("male"); - - apprentice.Delete(); - - return apprentice; - } - - private static List GetEquipment() - { - List list = new List(); - - list.Add(new Robe(QuestSystem.RandomBrightHue())); - list.Add(new WizardsHat(Utility.RandomNeutralHue())); - list.Add(new Shoes(Utility.RandomNeutralHue())); - list.Add(new Spellbook()); - - return list; - } - - private static HairInfo GetHair() - { - m_HairHue = Race.Human.RandomHairHue(); - return new HairInfo(Race.Human.RandomHair(false), m_HairHue); - } - - private static FacialHairInfo GetFacialHair() - { - m_HairHue = Race.Human.RandomHairHue(); - - return new FacialHairInfo(Race.Human.RandomFacialHair(false), m_HairHue); - } - - public override void AddNameProperty(ObjectPropertyList list) - { - if (ItemID == 0x2006) // Corpse form - { - list.Add("a human corpse"); - list.Add(1049144, Name); // the remains of ~1_NAME~ the apprentice - } - else - { - list.Add(1049145); // the remains of a wizard's apprentice - } - } - - public override void OnSingleClick(Mobile from) - { - int hue = Notoriety.GetHue(NotorietyHandlers.CorpseNotoriety(from, this)); - - if (ItemID == 0x2006) // Corpse form - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, hue, 3, 1049144, "", - Name)); // the remains of ~1_NAME~ the apprentice - else - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, hue, 3, 1049145, "", - "")); // the remains of a wizard's apprentice - } - - public override void Open(Mobile from, bool checkSelfLoot) - { - if (!from.InRange(GetWorldLocation(), 2)) - return; - - if (from is PlayerMobile player) - { - QuestSystem qs = player.Quest; - - if (qs is UzeraanTurmoilQuest) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - Item scroll = new SchmendrickScrollOfPower(); - - if (player.PlaceInBackpack(scroll)) - { - player.SendLocalizedMessage(1049147, "", 0x22); // You find the scroll and put it in your pack. - obj.Complete(); - } - else - { - player.SendLocalizedMessage(1049146, "", - 0x22); // You find the scroll, but can't pick it up because your pack is too full. Come back when you have more room in your pack. - scroll.Delete(); - } - - return; - } - } - } - - from.SendLocalizedMessage(1049143, "", - 0x22); // This is the corpse of a wizard's apprentice. You can't bring yourself to search it without a good reason. - } - - public override void OnLocationChange(Point3D oldLoc) - { - if (m_Lantern?.Deleted == false) - m_Lantern.Location = new Point3D(X, Y + 1, Z); - } - - public override void OnMapChange() - { - if (m_Lantern?.Deleted == false) - m_Lantern.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - if (m_Lantern?.Deleted == false) - m_Lantern.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - if (m_Lantern?.Deleted == true) - m_Lantern = null; - - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Lantern); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Lantern = (Lantern)reader.ReadItem(); - } - } -} +using System.Collections.Generic; +using Server.Items; +using Server.Misc; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.Quests.Haven +{ + public class SchmendrickApprenticeCorpse : Corpse + { + private static int m_HairHue; + + private Lantern m_Lantern; + + [Constructible] + public SchmendrickApprenticeCorpse() : base(GetOwner(), GetHair(), GetFacialHair(), GetEquipment()) + { + Direction = Direction.West; + + foreach (var item in EquipItems) + DropItem(item); + + m_Lantern = new Lantern { Movable = false, Protected = true }; + m_Lantern.Ignite(); + } + + public SchmendrickApprenticeCorpse(Serial serial) : base(serial) + { + } + + // TODO: What is this? Why are we creating and deleting a mobile? + private static Mobile GetOwner() + { + var apprentice = new Mobile(); + + apprentice.Hue = Race.Human.RandomSkinHue(); + apprentice.Female = false; + apprentice.Body = 0x190; + apprentice.Name = NameList.RandomName("male"); + + apprentice.Delete(); + + return apprentice; + } + + private static List GetEquipment() + { + var list = new List(); + + list.Add(new Robe(QuestSystem.RandomBrightHue())); + list.Add(new WizardsHat(Utility.RandomNeutralHue())); + list.Add(new Shoes(Utility.RandomNeutralHue())); + list.Add(new Spellbook()); + + return list; + } + + private static HairInfo GetHair() + { + m_HairHue = Race.Human.RandomHairHue(); + return new HairInfo(Race.Human.RandomHair(false), m_HairHue); + } + + private static FacialHairInfo GetFacialHair() + { + m_HairHue = Race.Human.RandomHairHue(); + + return new FacialHairInfo(Race.Human.RandomFacialHair(false), m_HairHue); + } + + public override void AddNameProperty(ObjectPropertyList list) + { + if (ItemID == 0x2006) // Corpse form + { + list.Add("a human corpse"); + list.Add(1049144, Name); // the remains of ~1_NAME~ the apprentice + } + else + { + list.Add(1049145); // the remains of a wizard's apprentice + } + } + + public override void OnSingleClick(Mobile from) + { + var hue = Notoriety.GetHue(NotorietyHandlers.CorpseNotoriety(from, this)); + + if (ItemID == 0x2006) // Corpse form + from.Send( + new MessageLocalized( + Serial, + ItemID, + MessageType.Label, + hue, + 3, + 1049144, + "", + Name + ) + ); // the remains of ~1_NAME~ the apprentice + else + from.Send( + new MessageLocalized( + Serial, + ItemID, + MessageType.Label, + hue, + 3, + 1049145, + "", + "" + ) + ); // the remains of a wizard's apprentice + } + + public override void Open(Mobile from, bool checkSelfLoot) + { + if (!from.InRange(GetWorldLocation(), 2)) + return; + + if (from is PlayerMobile player) + { + var qs = player.Quest; + + if (qs is UzeraanTurmoilQuest) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + Item scroll = new SchmendrickScrollOfPower(); + + if (player.PlaceInBackpack(scroll)) + { + player.SendLocalizedMessage(1049147, "", 0x22); // You find the scroll and put it in your pack. + obj.Complete(); + } + else + { + player.SendLocalizedMessage( + 1049146, + "", + 0x22 + ); // You find the scroll, but can't pick it up because your pack is too full. Come back when you have more room in your pack. + scroll.Delete(); + } + + return; + } + } + } + + from.SendLocalizedMessage( + 1049143, + "", + 0x22 + ); // This is the corpse of a wizard's apprentice. You can't bring yourself to search it without a good reason. + } + + public override void OnLocationChange(Point3D oldLoc) + { + if (m_Lantern?.Deleted == false) + m_Lantern.Location = new Point3D(X, Y + 1, Z); + } + + public override void OnMapChange() + { + if (m_Lantern?.Deleted == false) + m_Lantern.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + if (m_Lantern?.Deleted == false) + m_Lantern.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + if (m_Lantern?.Deleted == true) + m_Lantern = null; + + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Lantern); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Lantern = (Lantern)reader.ReadItem(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/SchmendrickScrollOfPower.cs b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/SchmendrickScrollOfPower.cs index 1fd9a7afd..d744c50be 100644 --- a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/SchmendrickScrollOfPower.cs +++ b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/SchmendrickScrollOfPower.cs @@ -1,37 +1,37 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Haven -{ - public class SchmendrickScrollOfPower : QuestItem - { - public SchmendrickScrollOfPower() : base(0xE34) - { - Weight = 1.0; - Hue = 0x34D; - } - - public SchmendrickScrollOfPower(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1049118; // a scroll with ancient markings - - public override bool CanDrop(PlayerMobile player) => - !(player.Quest is UzeraanTurmoilQuest qs && - qs.IsObjectiveInProgress(typeof(ReturnScrollOfPowerObjective))); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Haven +{ + public class SchmendrickScrollOfPower : QuestItem + { + public SchmendrickScrollOfPower() : base(0xE34) + { + Weight = 1.0; + Hue = 0x34D; + } + + public SchmendrickScrollOfPower(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1049118; // a scroll with ancient markings + + public override bool CanDrop(PlayerMobile player) => + !(player.Quest is UzeraanTurmoilQuest qs && + qs.IsObjectiveInProgress(typeof(ReturnScrollOfPowerObjective))); + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/UzeraanTurmoilHorn.cs b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/UzeraanTurmoilHorn.cs index fc41ebb4f..cdc20fc80 100644 --- a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/UzeraanTurmoilHorn.cs +++ b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/UzeraanTurmoilHorn.cs @@ -1,34 +1,34 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Haven -{ - public class UzeraanTurmoilHorn : HornOfRetreat - { - [Constructible] - public UzeraanTurmoilHorn() - { - DestLoc = new Point3D(3597, 2582, 0); - DestMap = Map.Trammel; - } - - public UzeraanTurmoilHorn(Serial serial) : base(serial) - { - } - - public override bool ValidateUse(Mobile from) => from is PlayerMobile pm && pm.Quest is UzeraanTurmoilQuest; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Haven +{ + public class UzeraanTurmoilHorn : HornOfRetreat + { + [Constructible] + public UzeraanTurmoilHorn() + { + DestLoc = new Point3D(3597, 2582, 0); + DestMap = Map.Trammel; + } + + public UzeraanTurmoilHorn(Serial serial) : base(serial) + { + } + + public override bool ValidateUse(Mobile from) => from is PlayerMobile pm && pm.Quest is UzeraanTurmoilQuest; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/UzeraanTurmoilTeleporter.cs b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/UzeraanTurmoilTeleporter.cs index 12e87c198..65739ee07 100644 --- a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/UzeraanTurmoilTeleporter.cs +++ b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/UzeraanTurmoilTeleporter.cs @@ -1,73 +1,73 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Haven -{ - public class UzeraanTurmoilTeleporter : DynamicTeleporter - { - [Constructible] - public UzeraanTurmoilTeleporter() - { - } - - public UzeraanTurmoilTeleporter(Serial serial) : base(serial) - { - } - - public override bool GetDestination(PlayerMobile player, ref Point3D loc, ref Map map) - { - QuestSystem qs = player.Quest; - - if (qs is UzeraanTurmoilQuest) - { - if (qs.IsObjectiveInProgress(typeof(FindSchmendrickObjective)) - || qs.IsObjectiveInProgress(typeof(FindApprenticeObjective)) - || UzeraanTurmoilQuest.HasLostScrollOfPower(player)) - { - loc = new Point3D(5222, 1858, 0); - map = Map.Trammel; - return true; - } - - if (qs.IsObjectiveInProgress(typeof(FindDryadObjective)) - || UzeraanTurmoilQuest.HasLostFertileDirt(player)) - { - loc = new Point3D(3557, 2690, 2); - map = Map.Trammel; - return true; - } - - if (player.Profession != 5 // paladin - && (qs.IsObjectiveInProgress(typeof(GetDaemonBoneObjective)) - || UzeraanTurmoilQuest.HasLostDaemonBone(player))) - { - loc = new Point3D(3422, 2653, 48); - map = Map.Trammel; - return true; - } - - if (qs.IsObjectiveInProgress(typeof(CashBankCheckObjective))) - { - loc = new Point3D(3624, 2610, 0); - map = Map.Trammel; - return true; - } - } - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Haven +{ + public class UzeraanTurmoilTeleporter : DynamicTeleporter + { + [Constructible] + public UzeraanTurmoilTeleporter() + { + } + + public UzeraanTurmoilTeleporter(Serial serial) : base(serial) + { + } + + public override bool GetDestination(PlayerMobile player, ref Point3D loc, ref Map map) + { + var qs = player.Quest; + + if (qs is UzeraanTurmoilQuest) + { + if (qs.IsObjectiveInProgress(typeof(FindSchmendrickObjective)) + || qs.IsObjectiveInProgress(typeof(FindApprenticeObjective)) + || UzeraanTurmoilQuest.HasLostScrollOfPower(player)) + { + loc = new Point3D(5222, 1858, 0); + map = Map.Trammel; + return true; + } + + if (qs.IsObjectiveInProgress(typeof(FindDryadObjective)) + || UzeraanTurmoilQuest.HasLostFertileDirt(player)) + { + loc = new Point3D(3557, 2690, 2); + map = Map.Trammel; + return true; + } + + if (player.Profession != 5 // paladin + && (qs.IsObjectiveInProgress(typeof(GetDaemonBoneObjective)) + || UzeraanTurmoilQuest.HasLostDaemonBone(player))) + { + loc = new Point3D(3422, 2653, 48); + map = Map.Trammel; + return true; + } + + if (qs.IsObjectiveInProgress(typeof(CashBankCheckObjective))) + { + loc = new Point3D(3624, 2610, 0); + map = Map.Trammel; + return true; + } + } + + return 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/Dryad.cs b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/Dryad.cs index ec675b0a8..75e077c04 100644 --- a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/Dryad.cs +++ b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/Dryad.cs @@ -1,179 +1,182 @@ -using System.Collections.Generic; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Haven -{ - public class Dryad : BaseQuester - { - [Constructible] - public Dryad() : base("the Dryad") - { - SetSkill(SkillName.Peacemaking, 80.0, 100.0); - SetSkill(SkillName.Cooking, 80.0, 100.0); - SetSkill(SkillName.Provocation, 80.0, 100.0); - SetSkill(SkillName.Musicianship, 80.0, 100.0); - SetSkill(SkillName.Poisoning, 80.0, 100.0); - SetSkill(SkillName.Archery, 80.0, 100.0); - SetSkill(SkillName.Tailoring, 80.0, 100.0); - } - - public Dryad(Serial serial) : base(serial) - { - } - - public override bool IsActiveVendor => true; - public override bool DisallowAllMoves => false; - public override bool ClickTitle => true; - public override bool CanTeach => true; - public override string DefaultName => "Anwin Brenna"; - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = 0x85A7; - - Female = true; - Body = 0x191; - } - - public override void InitOutfit() - { - AddItem(new Kilt(0x301)); - AddItem(new FancyShirt(0x300)); - - HairItemID = 0x203D; // Pony Tail - HairHue = 0x22; - - Bow bow = new Bow(); - bow.Movable = false; - AddItem(bow); - } - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBDryad()); - } - - public override int GetAutoTalkRange(PlayerMobile pm) => 4; - - public override bool CanTalkTo(PlayerMobile to) => to.Quest is UzeraanTurmoilQuest qs && qs.FindObjective() != null; - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - QuestSystem qs = player.Quest; - - if (qs is UzeraanTurmoilQuest) - { - if (UzeraanTurmoilQuest.HasLostFertileDirt(player)) - { - FocusTo(player); - qs.AddConversation(new LostFertileDirtConversation(false)); - } - else - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - FocusTo(player); - - Item fertileDirt = new QuestFertileDirt(); - - if (!player.PlaceInBackpack(fertileDirt)) - { - fertileDirt.Delete(); - player.SendLocalizedMessage( - 1046260); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. - } - else - { - obj.Complete(); - } - } - else if (contextMenu) - { - FocusTo(player); - SayTo(player, 1049357); // I have nothing more for you at this time. - } - } - } - } - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (from is PlayerMobile player) - if (player.Quest is UzeraanTurmoilQuest qs && dropped is Apple && - UzeraanTurmoilQuest.HasLostFertileDirt(from)) - { - FocusTo(from); - - Item fertileDirt = new QuestFertileDirt(); - - if (!player.PlaceInBackpack(fertileDirt)) - { - fertileDirt.Delete(); - player.SendLocalizedMessage( - 1046260); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. - return false; - } - - dropped.Consume(); - qs.AddConversation(new DryadAppleConversation()); - return dropped.Deleted; - } - - return base.OnDragDrop(from, dropped); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SBDryad : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List - { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Bandage), 5, 20, 0xE21, 0)); - Add(new GenericBuyInfo(typeof(Ginseng), 3, 20, 0xF85, 0)); - Add(new GenericBuyInfo(typeof(Garlic), 3, 20, 0xF84, 0)); - Add(new GenericBuyInfo(typeof(Bloodmoss), 5, 20, 0xF7B, 0)); - Add(new GenericBuyInfo(typeof(Nightshade), 3, 20, 0xF88, 0)); - Add(new GenericBuyInfo(typeof(SpidersSilk), 3, 20, 0xF8D, 0)); - Add(new GenericBuyInfo(typeof(MandrakeRoot), 3, 20, 0xF86, 0)); - } - } - - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Bandage), 2); - Add(typeof(Garlic), 2); - Add(typeof(Ginseng), 2); - Add(typeof(Bloodmoss), 3); - Add(typeof(Nightshade), 2); - Add(typeof(SpidersSilk), 2); - Add(typeof(MandrakeRoot), 2); - } - } - } -} \ No newline at end of file +using System.Collections.Generic; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Haven +{ + public class Dryad : BaseQuester + { + [Constructible] + public Dryad() : base("the Dryad") + { + SetSkill(SkillName.Peacemaking, 80.0, 100.0); + SetSkill(SkillName.Cooking, 80.0, 100.0); + SetSkill(SkillName.Provocation, 80.0, 100.0); + SetSkill(SkillName.Musicianship, 80.0, 100.0); + SetSkill(SkillName.Poisoning, 80.0, 100.0); + SetSkill(SkillName.Archery, 80.0, 100.0); + SetSkill(SkillName.Tailoring, 80.0, 100.0); + } + + public Dryad(Serial serial) : base(serial) + { + } + + public override bool IsActiveVendor => true; + public override bool DisallowAllMoves => false; + public override bool ClickTitle => true; + public override bool CanTeach => true; + public override string DefaultName => "Anwin Brenna"; + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = 0x85A7; + + Female = true; + Body = 0x191; + } + + public override void InitOutfit() + { + AddItem(new Kilt(0x301)); + AddItem(new FancyShirt(0x300)); + + HairItemID = 0x203D; // Pony Tail + HairHue = 0x22; + + var bow = new Bow(); + bow.Movable = false; + AddItem(bow); + } + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBDryad()); + } + + public override int GetAutoTalkRange(PlayerMobile pm) => 4; + + public override bool CanTalkTo(PlayerMobile to) => + to.Quest is UzeraanTurmoilQuest qs && qs.FindObjective() != null; + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + var qs = player.Quest; + + if (qs is UzeraanTurmoilQuest) + { + if (UzeraanTurmoilQuest.HasLostFertileDirt(player)) + { + FocusTo(player); + qs.AddConversation(new LostFertileDirtConversation(false)); + } + else + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + FocusTo(player); + + Item fertileDirt = new QuestFertileDirt(); + + if (!player.PlaceInBackpack(fertileDirt)) + { + fertileDirt.Delete(); + player.SendLocalizedMessage( + 1046260 + ); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. + } + else + { + obj.Complete(); + } + } + else if (contextMenu) + { + FocusTo(player); + SayTo(player, 1049357); // I have nothing more for you at this time. + } + } + } + } + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (from is PlayerMobile player) + if (player.Quest is UzeraanTurmoilQuest qs && dropped is Apple && + UzeraanTurmoilQuest.HasLostFertileDirt(from)) + { + FocusTo(from); + + Item fertileDirt = new QuestFertileDirt(); + + if (!player.PlaceInBackpack(fertileDirt)) + { + fertileDirt.Delete(); + player.SendLocalizedMessage( + 1046260 + ); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. + return false; + } + + dropped.Consume(); + qs.AddConversation(new DryadAppleConversation()); + return dropped.Deleted; + } + + return base.OnDragDrop(from, dropped); + } + + 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 class SBDryad : SBInfo + { + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); + + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Bandage), 5, 20, 0xE21, 0)); + Add(new GenericBuyInfo(typeof(Ginseng), 3, 20, 0xF85, 0)); + Add(new GenericBuyInfo(typeof(Garlic), 3, 20, 0xF84, 0)); + Add(new GenericBuyInfo(typeof(Bloodmoss), 5, 20, 0xF7B, 0)); + Add(new GenericBuyInfo(typeof(Nightshade), 3, 20, 0xF88, 0)); + Add(new GenericBuyInfo(typeof(SpidersSilk), 3, 20, 0xF8D, 0)); + Add(new GenericBuyInfo(typeof(MandrakeRoot), 3, 20, 0xF86, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Bandage), 2); + Add(typeof(Garlic), 2); + Add(typeof(Ginseng), 2); + Add(typeof(Bloodmoss), 3); + Add(typeof(Nightshade), 2); + Add(typeof(SpidersSilk), 2); + Add(typeof(MandrakeRoot), 2); + } + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/MansionGuard.cs b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/MansionGuard.cs index f4df0f404..a0b978464 100644 --- a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/MansionGuard.cs +++ b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/MansionGuard.cs @@ -1,71 +1,72 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Haven -{ - public class MansionGuard : BaseQuester - { - [Constructible] - public MansionGuard() : base("the Mansion Guard") - { - } - - public MansionGuard(Serial serial) : base(serial) - { - } - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = Race.Human.RandomSkinHue(); - - Female = false; - Body = 0x190; - Name = NameList.RandomName("male"); - } - - public override void InitOutfit() - { - AddItem(new PlateChest()); - AddItem(new PlateArms()); - AddItem(new PlateGloves()); - AddItem(new PlateLegs()); - - Utility.AssignRandomHair(this); - Utility.AssignRandomFacialHair(this, HairHue); - - Bardiche weapon = new Bardiche(); - weapon.Movable = false; - AddItem(weapon); - } - - public override int GetAutoTalkRange(PlayerMobile pm) => 3; - - public override bool CanTalkTo(PlayerMobile to) => to.Quest == null && QuestSystem.CanOfferQuest(to, typeof(UzeraanTurmoilQuest)); - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - if (player.Quest == null && QuestSystem.CanOfferQuest(player, typeof(UzeraanTurmoilQuest))) - { - Direction = GetDirectionTo(player); - - new UzeraanTurmoilQuest(player).SendOffer(); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Haven +{ + public class MansionGuard : BaseQuester + { + [Constructible] + public MansionGuard() : base("the Mansion Guard") + { + } + + public MansionGuard(Serial serial) : base(serial) + { + } + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = Race.Human.RandomSkinHue(); + + Female = false; + Body = 0x190; + Name = NameList.RandomName("male"); + } + + public override void InitOutfit() + { + AddItem(new PlateChest()); + AddItem(new PlateArms()); + AddItem(new PlateGloves()); + AddItem(new PlateLegs()); + + Utility.AssignRandomHair(this); + Utility.AssignRandomFacialHair(this, HairHue); + + var weapon = new Bardiche(); + weapon.Movable = false; + AddItem(weapon); + } + + public override int GetAutoTalkRange(PlayerMobile pm) => 3; + + public override bool CanTalkTo(PlayerMobile to) => + to.Quest == null && QuestSystem.CanOfferQuest(to, typeof(UzeraanTurmoilQuest)); + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + if (player.Quest == null && QuestSystem.CanOfferQuest(player, typeof(UzeraanTurmoilQuest))) + { + Direction = GetDirectionTo(player); + + new UzeraanTurmoilQuest(player).SendOffer(); + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/MilitiaCanoneer.cs b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/MilitiaCanoneer.cs index 14d9bcdb5..04cc87aee 100644 --- a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/MilitiaCanoneer.cs +++ b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/MilitiaCanoneer.cs @@ -1,96 +1,96 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Haven -{ - public class MilitiaCanoneer : BaseQuester - { - [Constructible] - public MilitiaCanoneer() : base("the Militia Canoneer") => Active = true; - - public MilitiaCanoneer(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Active { get; set; } - - public override void InitBody() - { - InitStats(100, 125, 25); - - Hue = Race.Human.RandomSkinHue(); - - Female = false; - Body = 0x190; - Name = NameList.RandomName("male"); - } - - public override void InitOutfit() - { - Utility.AssignRandomHair(this); - Utility.AssignRandomFacialHair(this, HairHue); - - AddItem(new PlateChest()); - AddItem(new PlateArms()); - AddItem(new PlateGloves()); - AddItem(new PlateLegs()); - - Torch torch = new Torch(); - torch.Movable = false; - AddItem(torch); - torch.Ignite(); - } - - public override bool CanTalkTo(PlayerMobile to) => false; - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - } - - public override bool IsEnemy(Mobile m) - { - if (m.Player || m is BaseVendor) - return false; - - if (m is BaseCreature bc) - { - Mobile master = bc.GetMaster(); - if (master != null) - return IsEnemy(master); - } - - return m.Karma < 0; - } - - public bool WillFire(Cannon cannon, Mobile target) - { - if (Active && IsEnemy(target)) - { - Direction = GetDirectionTo(target); - Say(Utility.RandomList(500651, 1049098, 1049320, 1043149)); - return true; - } - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(Active); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Active = reader.ReadBool(); - } - } -} \ No newline at end of file +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Haven +{ + public class MilitiaCanoneer : BaseQuester + { + [Constructible] + public MilitiaCanoneer() : base("the Militia Canoneer") => Active = true; + + public MilitiaCanoneer(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Active { get; set; } + + public override void InitBody() + { + InitStats(100, 125, 25); + + Hue = Race.Human.RandomSkinHue(); + + Female = false; + Body = 0x190; + Name = NameList.RandomName("male"); + } + + public override void InitOutfit() + { + Utility.AssignRandomHair(this); + Utility.AssignRandomFacialHair(this, HairHue); + + AddItem(new PlateChest()); + AddItem(new PlateArms()); + AddItem(new PlateGloves()); + AddItem(new PlateLegs()); + + var torch = new Torch(); + torch.Movable = false; + AddItem(torch); + torch.Ignite(); + } + + public override bool CanTalkTo(PlayerMobile to) => false; + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + } + + public override bool IsEnemy(Mobile m) + { + if (m.Player || m is BaseVendor) + return false; + + if (m is BaseCreature bc) + { + var master = bc.GetMaster(); + if (master != null) + return IsEnemy(master); + } + + return m.Karma < 0; + } + + public bool WillFire(Cannon cannon, Mobile target) + { + if (Active && IsEnemy(target)) + { + Direction = GetDirectionTo(target); + Say(Utility.RandomList(500651, 1049098, 1049320, 1043149)); + return true; + } + + return false; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(Active); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + Active = reader.ReadBool(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/MilitiaFighter.cs b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/MilitiaFighter.cs index c3632285c..10e5896f0 100644 --- a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/MilitiaFighter.cs +++ b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/MilitiaFighter.cs @@ -1,149 +1,176 @@ -using System.Collections.Generic; -using Server.Items; -using Server.Misc; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.Quests.Haven -{ - public class MilitiaFighter : BaseCreature - { - [Constructible] - public MilitiaFighter() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) - { - InitStats(40, 30, 5); - Title = "the Militia Fighter"; - - SpeechHue = Utility.RandomDyedHue(); - - Hue = Race.Human.RandomSkinHue(); - - Female = false; - Body = 0x190; - Name = NameList.RandomName("male"); - - Utility.AssignRandomHair(this); - Utility.AssignRandomFacialHair(this, HairHue); - - AddItem(new ThighBoots(0x1BB)); - AddItem(new LeatherChest()); - AddItem(new LeatherArms()); - AddItem(new LeatherLegs()); - AddItem(new LeatherCap()); - AddItem(new LeatherGloves()); - AddItem(new LeatherGorget()); - - var weapon = Utility.Random(6) switch - { - 0 => (Item)new Broadsword(), - 1 => new Cutlass(), - 2 => new Katana(), - 3 => new Longsword(), - 4 => new Scimitar(), - _ => new VikingSword() - }; - - weapon.Movable = false; - AddItem(weapon); - - Item shield = new BronzeShield(); - shield.Movable = false; - AddItem(shield); - - SetSkill(SkillName.Swords, 20.0); - } - - public MilitiaFighter(Serial serial) : base(serial) - { - } - - public override bool ClickTitle => false; - - public override bool IsEnemy(Mobile m) - { - if (m.Player || m is BaseVendor) - return false; - - if (m is BaseCreature bc) - { - Mobile master = bc.GetMaster(); - if (master != null) - return IsEnemy(master); - } - - return m.Karma < 0; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class MilitiaFighterCorpse : Corpse - { - public MilitiaFighterCorpse(Mobile owner, HairInfo hair, FacialHairInfo facialhair, List equipItems) : base( - owner, hair, facialhair, equipItems) - { - } - - public MilitiaFighterCorpse(Serial serial) : base(serial) - { - } - - public override void AddNameProperty(ObjectPropertyList list) - { - if (ItemID == 0x2006) // Corpse form - { - list.Add("a human corpse"); - list.Add(1049318, Name); // the remains of ~1_NAME~ the militia fighter - } - else - { - list.Add(1049319); // the remains of a militia fighter - } - } - - public override void OnSingleClick(Mobile from) - { - int hue = Notoriety.GetHue(NotorietyHandlers.CorpseNotoriety(from, this)); - - if (ItemID == 0x2006) // Corpse form - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, hue, 3, 1049318, "", - Name)); // the remains of ~1_NAME~ the militia fighter - else - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, hue, 3, 1049319, "", - "")); // the remains of a militia fighter - } - - public override void Open(Mobile from, bool checkSelfLoot) - { - if (from.InRange(GetWorldLocation(), 2)) - from.SendLocalizedMessage(1049661, "", - 0x22); // Thinking about his sacrifice, you can't bring yourself to loot the body of this militia fighter. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System.Collections.Generic; +using Server.Items; +using Server.Misc; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.Quests.Haven +{ + public class MilitiaFighter : BaseCreature + { + [Constructible] + public MilitiaFighter() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + InitStats(40, 30, 5); + Title = "the Militia Fighter"; + + SpeechHue = Utility.RandomDyedHue(); + + Hue = Race.Human.RandomSkinHue(); + + Female = false; + Body = 0x190; + Name = NameList.RandomName("male"); + + Utility.AssignRandomHair(this); + Utility.AssignRandomFacialHair(this, HairHue); + + AddItem(new ThighBoots(0x1BB)); + AddItem(new LeatherChest()); + AddItem(new LeatherArms()); + AddItem(new LeatherLegs()); + AddItem(new LeatherCap()); + AddItem(new LeatherGloves()); + AddItem(new LeatherGorget()); + + var weapon = Utility.Random(6) switch + { + 0 => (Item)new Broadsword(), + 1 => new Cutlass(), + 2 => new Katana(), + 3 => new Longsword(), + 4 => new Scimitar(), + _ => new VikingSword() + }; + + weapon.Movable = false; + AddItem(weapon); + + Item shield = new BronzeShield(); + shield.Movable = false; + AddItem(shield); + + SetSkill(SkillName.Swords, 20.0); + } + + public MilitiaFighter(Serial serial) : base(serial) + { + } + + public override bool ClickTitle => false; + + public override bool IsEnemy(Mobile m) + { + if (m.Player || m is BaseVendor) + return false; + + if (m is BaseCreature bc) + { + var master = bc.GetMaster(); + if (master != null) + return IsEnemy(master); + } + + return m.Karma < 0; + } + + 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 class MilitiaFighterCorpse : Corpse + { + public MilitiaFighterCorpse(Mobile owner, HairInfo hair, FacialHairInfo facialhair, List equipItems) : base( + owner, + hair, + facialhair, + equipItems + ) + { + } + + public MilitiaFighterCorpse(Serial serial) : base(serial) + { + } + + public override void AddNameProperty(ObjectPropertyList list) + { + if (ItemID == 0x2006) // Corpse form + { + list.Add("a human corpse"); + list.Add(1049318, Name); // the remains of ~1_NAME~ the militia fighter + } + else + { + list.Add(1049319); // the remains of a militia fighter + } + } + + public override void OnSingleClick(Mobile from) + { + var hue = Notoriety.GetHue(NotorietyHandlers.CorpseNotoriety(from, this)); + + if (ItemID == 0x2006) // Corpse form + from.Send( + new MessageLocalized( + Serial, + ItemID, + MessageType.Label, + hue, + 3, + 1049318, + "", + Name + ) + ); // the remains of ~1_NAME~ the militia fighter + else + from.Send( + new MessageLocalized( + Serial, + ItemID, + MessageType.Label, + hue, + 3, + 1049319, + "", + "" + ) + ); // the remains of a militia fighter + } + + public override void Open(Mobile from, bool checkSelfLoot) + { + if (from.InRange(GetWorldLocation(), 2)) + from.SendLocalizedMessage( + 1049661, + "", + 0x22 + ); // Thinking about his sacrifice, you can't bring yourself to loot the body of this militia fighter. + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/Schmendrick.cs b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/Schmendrick.cs index 15311b33a..38f75ff24 100644 --- a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/Schmendrick.cs +++ b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/Schmendrick.cs @@ -1,146 +1,149 @@ -using Server.Gumps; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Haven -{ - public class Schmendrick : BaseQuester - { - [Constructible] - public Schmendrick() : base("the High Mage") - { - } - - public Schmendrick(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Schmendrick"; - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = 0x83F3; - - Female = false; - Body = 0x190; - } - - public override void InitOutfit() - { - AddItem(new Robe(0x4DD)); - AddItem(new WizardsHat(0x482)); - AddItem(new Shoes(0x482)); - - HairItemID = 0x203C; - HairHue = 0x455; - - FacialHairItemID = 0x203E; - FacialHairHue = 0x455; - - GlacialStaff staff = new GlacialStaff(); - staff.Movable = false; - AddItem(staff); - - Backpack pack = new Backpack(); - pack.Movable = false; - AddItem(pack); - } - - public override int GetAutoTalkRange(PlayerMobile pm) => 7; - - public override bool CanTalkTo(PlayerMobile to) => to.Quest is UzeraanTurmoilQuest qs && qs.FindObjective() != null; - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - QuestSystem qs = player.Quest; - - if (qs is UzeraanTurmoilQuest) - { - if (UzeraanTurmoilQuest.HasLostScrollOfPower(player)) - { - FocusTo(player); - qs.AddConversation(new LostScrollOfPowerConversation(false)); - } - else - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - FocusTo(player); - obj.Complete(); - } - else if (contextMenu) - { - FocusTo(player); - SayTo(player, 1049357); // I have nothing more for you at this time. - } - } - } - } - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (dropped is BlankScroll && UzeraanTurmoilQuest.HasLostScrollOfPower(from)) - { - FocusTo(from); - - Item scroll = new SchmendrickScrollOfPower(); - - if (!from.PlaceInBackpack(scroll)) - { - scroll.Delete(); - from.SendLocalizedMessage( - 1046260); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. - return false; - } - - dropped.Consume(); - from.SendLocalizedMessage( - 1049346); // Schmendrick scribbles on the scroll for a few moments and hands you the finished product. - return dropped.Deleted; - } - - return base.OnDragDrop(from, dropped); - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - base.OnMovement(m, oldLocation); - - if (m is PlayerMobile && !m.Frozen && !m.Alive && InRange(m, 4) && !InRange(oldLocation, 4) && InLOS(m)) - { - if (m.Map?.CanFit(m.Location, 16, false, false) != true) - { - m.SendLocalizedMessage(502391); // Thou can not be resurrected there! - } - else - { - Direction = GetDirectionTo(m); - - m.PlaySound(0x214); - m.FixedEffect(0x376A, 10, 16); - - m.CloseGump(); - m.SendGump(new ResurrectGump(m, ResurrectMessage.Healer)); - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Gumps; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Haven +{ + public class Schmendrick : BaseQuester + { + [Constructible] + public Schmendrick() : base("the High Mage") + { + } + + public Schmendrick(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Schmendrick"; + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = 0x83F3; + + Female = false; + Body = 0x190; + } + + public override void InitOutfit() + { + AddItem(new Robe(0x4DD)); + AddItem(new WizardsHat(0x482)); + AddItem(new Shoes(0x482)); + + HairItemID = 0x203C; + HairHue = 0x455; + + FacialHairItemID = 0x203E; + FacialHairHue = 0x455; + + var staff = new GlacialStaff(); + staff.Movable = false; + AddItem(staff); + + var pack = new Backpack(); + pack.Movable = false; + AddItem(pack); + } + + public override int GetAutoTalkRange(PlayerMobile pm) => 7; + + public override bool CanTalkTo(PlayerMobile to) => + to.Quest is UzeraanTurmoilQuest qs && qs.FindObjective() != null; + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + var qs = player.Quest; + + if (qs is UzeraanTurmoilQuest) + { + if (UzeraanTurmoilQuest.HasLostScrollOfPower(player)) + { + FocusTo(player); + qs.AddConversation(new LostScrollOfPowerConversation(false)); + } + else + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + FocusTo(player); + obj.Complete(); + } + else if (contextMenu) + { + FocusTo(player); + SayTo(player, 1049357); // I have nothing more for you at this time. + } + } + } + } + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (dropped is BlankScroll && UzeraanTurmoilQuest.HasLostScrollOfPower(from)) + { + FocusTo(from); + + Item scroll = new SchmendrickScrollOfPower(); + + if (!from.PlaceInBackpack(scroll)) + { + scroll.Delete(); + from.SendLocalizedMessage( + 1046260 + ); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. + return false; + } + + dropped.Consume(); + from.SendLocalizedMessage( + 1049346 + ); // Schmendrick scribbles on the scroll for a few moments and hands you the finished product. + return dropped.Deleted; + } + + return base.OnDragDrop(from, dropped); + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + base.OnMovement(m, oldLocation); + + if (m is PlayerMobile && !m.Frozen && !m.Alive && InRange(m, 4) && !InRange(oldLocation, 4) && InLOS(m)) + { + if (m.Map?.CanFit(m.Location, 16, false, false) != true) + { + m.SendLocalizedMessage(502391); // Thou can not be resurrected there! + } + else + { + Direction = GetDirectionTo(m); + + m.PlaySound(0x214); + m.FixedEffect(0x376A, 10, 16); + + m.CloseGump(); + m.SendGump(new ResurrectGump(m, ResurrectMessage.Healer)); + } + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/Uzeraan.cs b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/Uzeraan.cs index 681e0e824..f5816da6b 100644 --- a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/Uzeraan.cs +++ b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/Uzeraan.cs @@ -1,413 +1,418 @@ -using Server.Gumps; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Haven -{ - public class Uzeraan : BaseQuester - { - [Constructible] - public Uzeraan() : base("the Conjurer") - { - } - - public Uzeraan(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Uzeraan"; - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = 0x83F3; - - Female = false; - Body = 0x190; - } - - public override void InitOutfit() - { - AddItem(new Robe(0x4DD)); - AddItem(new WizardsHat(0x8A5)); - AddItem(new Shoes(0x8A5)); - - HairItemID = 0x203C; - HairHue = 0x455; - - FacialHairItemID = 0x203E; - FacialHairHue = 0x455; - - BlackStaff staff = new BlackStaff(); - staff.Movable = false; - AddItem(staff); - } - - public override int GetAutoTalkRange(PlayerMobile pm) => 3; - - public override bool CanTalkTo(PlayerMobile to) => to.Quest is UzeraanTurmoilQuest; - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - QuestSystem qs = player.Quest; - - if (qs is UzeraanTurmoilQuest) - { - if (UzeraanTurmoilQuest.HasLostScrollOfPower(player)) - { - qs.AddConversation(new LostScrollOfPowerConversation(true)); - } - else if (UzeraanTurmoilQuest.HasLostFertileDirt(player)) - { - qs.AddConversation(new LostFertileDirtConversation(true)); - } - else if (UzeraanTurmoilQuest.HasLostDaemonBlood(player)) - { - qs.AddConversation(new LostDaemonBloodConversation()); - } - else if (UzeraanTurmoilQuest.HasLostDaemonBone(player)) - { - qs.AddConversation(new LostDaemonBoneConversation()); - } - else - { - if (player.Profession == 2) // magician - { - Container backpack = player.Backpack; - - if (backpack == null - || backpack.GetAmount(typeof(BlackPearl)) < 30 - || backpack.GetAmount(typeof(Bloodmoss)) < 30 - || backpack.GetAmount(typeof(Garlic)) < 30 - || backpack.GetAmount(typeof(Ginseng)) < 30 - || backpack.GetAmount(typeof(MandrakeRoot)) < 30 - || backpack.GetAmount(typeof(Nightshade)) < 30 - || backpack.GetAmount(typeof(SulfurousAsh)) < 30 - || backpack.GetAmount(typeof(SpidersSilk)) < 30) - qs.AddConversation(new FewReagentsConversation()); - } - - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - obj.Complete(); - } - else - { - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - obj.Complete(); - } - else - { - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - Container cont = GetNewContainer(); - - if (player.Profession == 2) // magician - { - cont.DropItem(new MarkScroll(5)); - cont.DropItem(new RecallScroll(5)); - for (int i = 0; i < 5; i++) cont.DropItem(new RecallRune()); - } - else - { - cont.DropItem(new Gold(300)); - for (int i = 0; i < 6; i++) - { - cont.DropItem(new NightSightPotion()); - cont.DropItem(new LesserHealPotion()); - } - } - - if (!player.PlaceInBackpack(cont)) - { - cont.Delete(); - player.SendLocalizedMessage( - 1046260); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. - } - else - { - obj.Complete(); - } - } - else - { - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - FocusTo(player); - SayTo(player, 1049378); // Hand me the scroll, if you have it. - } - else - { - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - FocusTo(player); - SayTo(player, 1049381); // Hand me the Fertile Dirt, if you have it. - } - else - { - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - FocusTo(player); - SayTo(player, 1049379); // Hand me the Vial of Blood, if you have it. - } - else - { - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - FocusTo(player); - SayTo(player, 1049380); // Hand me the Daemon Bone, if you have it. - } - else - { - SayTo(player, 1049357); // I have nothing more for you at this time. - } - } - } - } - } - } - } - } - } - } - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (from is PlayerMobile player) - { - QuestSystem qs = player.Quest; - - if (qs is UzeraanTurmoilQuest) - { - if (dropped is UzeraanTurmoilHorn horn) - { - if (player.Young) - { - if (horn.Charges < 10) - { - SayTo(from, 1049384); // I have recharged the item for you. - horn.Charges = 10; - } - else - { - SayTo(from, 1049385); // That doesn't need recharging yet. - } - } - else - { - player.SendLocalizedMessage(1114333); // You must be young to have this item recharged. - } - - return false; - } - - if (dropped is SchmendrickScrollOfPower) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - Container cont = GetNewContainer(); - - cont.DropItem(new TreasureMap(player.Young ? 0 : 1, Map.Trammel)); - cont.DropItem(new Shovel()); - cont.DropItem(new UzeraanTurmoilHorn()); - - if (!player.PlaceInBackpack(cont)) - { - cont.Delete(); - player.SendLocalizedMessage( - 1046260); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. - return false; - } - - dropped.Delete(); - obj.Complete(); - return true; - } - } - else if (dropped is QuestFertileDirt) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - Container cont = GetNewContainer(); - - if (player.Profession == 2) // magician - { - cont.DropItem(new BlackPearl(20)); - cont.DropItem(new Bloodmoss(20)); - cont.DropItem(new Garlic(20)); - cont.DropItem(new Ginseng(20)); - cont.DropItem(new MandrakeRoot(20)); - cont.DropItem(new Nightshade(20)); - cont.DropItem(new SulfurousAsh(20)); - cont.DropItem(new SpidersSilk(20)); - - for (int i = 0; i < 3; i++) - cont.DropItem(Loot.RandomScroll(0, 23, SpellbookType.Regular)); - } - else - { - cont.DropItem(new Gold(300)); - cont.DropItem(new Bandage(25)); - - for (int i = 0; i < 5; i++) - cont.DropItem(new LesserHealPotion()); - } - - if (!player.PlaceInBackpack(cont)) - { - cont.Delete(); - player.SendLocalizedMessage( - 1046260); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. - return false; - } - - dropped.Delete(); - obj.Complete(); - return true; - } - } - else if (dropped is QuestDaemonBlood) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - Item reward; - - if (player.Profession == 2) // magician - { - Container cont = GetNewContainer(); - - cont.DropItem(new ExplosionScroll(4)); - cont.DropItem(new MagicWizardsHat()); - - reward = cont; - } - else - { - var weapon = Utility.Random(6) switch - { - 0 => (BaseWeapon)new Broadsword(), - 1 => new Cutlass(), - 2 => new Katana(), - 3 => new Longsword(), - 4 => new Scimitar(), - _ => new VikingSword() - }; - - if (Core.AOS) - { - BaseRunicTool.ApplyAttributesTo(weapon, 3, 20, 40); - } - else - { - weapon.DamageLevel = (WeaponDamageLevel)RandomMinMaxScaled(2, 4); - weapon.AccuracyLevel = (WeaponAccuracyLevel)RandomMinMaxScaled(2, 4); - weapon.DurabilityLevel = (WeaponDurabilityLevel)RandomMinMaxScaled(2, 4); - } - - weapon.Slayer = SlayerName.Silver; - - reward = weapon; - } - - if (!player.PlaceInBackpack(reward)) - { - reward.Delete(); - player.SendLocalizedMessage( - 1046260); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. - return false; - } - - dropped.Delete(); - obj.Complete(); - return true; - } - } - else if (dropped is QuestDaemonBone) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - Container cont = GetNewContainer(); - cont.DropItem(new BankCheck(2000)); - cont.DropItem(new EnchantedSextant()); - - if (!player.PlaceInBackpack(cont)) - { - cont.Delete(); - player.SendLocalizedMessage( - 1046260); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. - return false; - } - - dropped.Delete(); - obj.Complete(); - return true; - } - } - } - } - - return base.OnDragDrop(from, dropped); - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - base.OnMovement(m, oldLocation); - - if (m is PlayerMobile && !m.Frozen && !m.Alive && InRange(m, 4) && !InRange(oldLocation, 4) && InLOS(m)) - { - if (m.Map?.CanFit(m.Location, 16, false, false) != true) - { - m.SendLocalizedMessage(502391); // Thou can not be resurrected there! - } - else - { - Direction = GetDirectionTo(m); - - m.PlaySound(0x214); - m.FixedEffect(0x376A, 10, 16); - - m.CloseGump(); - m.SendGump(new ResurrectGump(m, ResurrectMessage.Healer)); - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Gumps; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Haven +{ + public class Uzeraan : BaseQuester + { + [Constructible] + public Uzeraan() : base("the Conjurer") + { + } + + public Uzeraan(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Uzeraan"; + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = 0x83F3; + + Female = false; + Body = 0x190; + } + + public override void InitOutfit() + { + AddItem(new Robe(0x4DD)); + AddItem(new WizardsHat(0x8A5)); + AddItem(new Shoes(0x8A5)); + + HairItemID = 0x203C; + HairHue = 0x455; + + FacialHairItemID = 0x203E; + FacialHairHue = 0x455; + + var staff = new BlackStaff(); + staff.Movable = false; + AddItem(staff); + } + + public override int GetAutoTalkRange(PlayerMobile pm) => 3; + + public override bool CanTalkTo(PlayerMobile to) => to.Quest is UzeraanTurmoilQuest; + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + var qs = player.Quest; + + if (qs is UzeraanTurmoilQuest) + { + if (UzeraanTurmoilQuest.HasLostScrollOfPower(player)) + { + qs.AddConversation(new LostScrollOfPowerConversation(true)); + } + else if (UzeraanTurmoilQuest.HasLostFertileDirt(player)) + { + qs.AddConversation(new LostFertileDirtConversation(true)); + } + else if (UzeraanTurmoilQuest.HasLostDaemonBlood(player)) + { + qs.AddConversation(new LostDaemonBloodConversation()); + } + else if (UzeraanTurmoilQuest.HasLostDaemonBone(player)) + { + qs.AddConversation(new LostDaemonBoneConversation()); + } + else + { + if (player.Profession == 2) // magician + { + var backpack = player.Backpack; + + if (backpack == null + || backpack.GetAmount(typeof(BlackPearl)) < 30 + || backpack.GetAmount(typeof(Bloodmoss)) < 30 + || backpack.GetAmount(typeof(Garlic)) < 30 + || backpack.GetAmount(typeof(Ginseng)) < 30 + || backpack.GetAmount(typeof(MandrakeRoot)) < 30 + || backpack.GetAmount(typeof(Nightshade)) < 30 + || backpack.GetAmount(typeof(SulfurousAsh)) < 30 + || backpack.GetAmount(typeof(SpidersSilk)) < 30) + qs.AddConversation(new FewReagentsConversation()); + } + + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + obj.Complete(); + } + else + { + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + obj.Complete(); + } + else + { + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + var cont = GetNewContainer(); + + if (player.Profession == 2) // magician + { + cont.DropItem(new MarkScroll(5)); + cont.DropItem(new RecallScroll(5)); + for (var i = 0; i < 5; i++) cont.DropItem(new RecallRune()); + } + else + { + cont.DropItem(new Gold(300)); + for (var i = 0; i < 6; i++) + { + cont.DropItem(new NightSightPotion()); + cont.DropItem(new LesserHealPotion()); + } + } + + if (!player.PlaceInBackpack(cont)) + { + cont.Delete(); + player.SendLocalizedMessage( + 1046260 + ); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. + } + else + { + obj.Complete(); + } + } + else + { + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + FocusTo(player); + SayTo(player, 1049378); // Hand me the scroll, if you have it. + } + else + { + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + FocusTo(player); + SayTo(player, 1049381); // Hand me the Fertile Dirt, if you have it. + } + else + { + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + FocusTo(player); + SayTo(player, 1049379); // Hand me the Vial of Blood, if you have it. + } + else + { + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + FocusTo(player); + SayTo(player, 1049380); // Hand me the Daemon Bone, if you have it. + } + else + { + SayTo(player, 1049357); // I have nothing more for you at this time. + } + } + } + } + } + } + } + } + } + } + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (from is PlayerMobile player) + { + var qs = player.Quest; + + if (qs is UzeraanTurmoilQuest) + { + if (dropped is UzeraanTurmoilHorn horn) + { + if (player.Young) + { + if (horn.Charges < 10) + { + SayTo(from, 1049384); // I have recharged the item for you. + horn.Charges = 10; + } + else + { + SayTo(from, 1049385); // That doesn't need recharging yet. + } + } + else + { + player.SendLocalizedMessage(1114333); // You must be young to have this item recharged. + } + + return false; + } + + if (dropped is SchmendrickScrollOfPower) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + var cont = GetNewContainer(); + + cont.DropItem(new TreasureMap(player.Young ? 0 : 1, Map.Trammel)); + cont.DropItem(new Shovel()); + cont.DropItem(new UzeraanTurmoilHorn()); + + if (!player.PlaceInBackpack(cont)) + { + cont.Delete(); + player.SendLocalizedMessage( + 1046260 + ); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. + return false; + } + + dropped.Delete(); + obj.Complete(); + return true; + } + } + else if (dropped is QuestFertileDirt) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + var cont = GetNewContainer(); + + if (player.Profession == 2) // magician + { + cont.DropItem(new BlackPearl(20)); + cont.DropItem(new Bloodmoss(20)); + cont.DropItem(new Garlic(20)); + cont.DropItem(new Ginseng(20)); + cont.DropItem(new MandrakeRoot(20)); + cont.DropItem(new Nightshade(20)); + cont.DropItem(new SulfurousAsh(20)); + cont.DropItem(new SpidersSilk(20)); + + for (var i = 0; i < 3; i++) + cont.DropItem(Loot.RandomScroll(0, 23, SpellbookType.Regular)); + } + else + { + cont.DropItem(new Gold(300)); + cont.DropItem(new Bandage(25)); + + for (var i = 0; i < 5; i++) + cont.DropItem(new LesserHealPotion()); + } + + if (!player.PlaceInBackpack(cont)) + { + cont.Delete(); + player.SendLocalizedMessage( + 1046260 + ); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. + return false; + } + + dropped.Delete(); + obj.Complete(); + return true; + } + } + else if (dropped is QuestDaemonBlood) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + Item reward; + + if (player.Profession == 2) // magician + { + var cont = GetNewContainer(); + + cont.DropItem(new ExplosionScroll(4)); + cont.DropItem(new MagicWizardsHat()); + + reward = cont; + } + else + { + var weapon = Utility.Random(6) switch + { + 0 => (BaseWeapon)new Broadsword(), + 1 => new Cutlass(), + 2 => new Katana(), + 3 => new Longsword(), + 4 => new Scimitar(), + _ => new VikingSword() + }; + + if (Core.AOS) + { + BaseRunicTool.ApplyAttributesTo(weapon, 3, 20, 40); + } + else + { + weapon.DamageLevel = (WeaponDamageLevel)RandomMinMaxScaled(2, 4); + weapon.AccuracyLevel = (WeaponAccuracyLevel)RandomMinMaxScaled(2, 4); + weapon.DurabilityLevel = (WeaponDurabilityLevel)RandomMinMaxScaled(2, 4); + } + + weapon.Slayer = SlayerName.Silver; + + reward = weapon; + } + + if (!player.PlaceInBackpack(reward)) + { + reward.Delete(); + player.SendLocalizedMessage( + 1046260 + ); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. + return false; + } + + dropped.Delete(); + obj.Complete(); + return true; + } + } + else if (dropped is QuestDaemonBone) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + var cont = GetNewContainer(); + cont.DropItem(new BankCheck(2000)); + cont.DropItem(new EnchantedSextant()); + + if (!player.PlaceInBackpack(cont)) + { + cont.Delete(); + player.SendLocalizedMessage( + 1046260 + ); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. + return false; + } + + dropped.Delete(); + obj.Complete(); + return true; + } + } + } + } + + return base.OnDragDrop(from, dropped); + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + base.OnMovement(m, oldLocation); + + if (m is PlayerMobile && !m.Frozen && !m.Alive && InRange(m, 4) && !InRange(oldLocation, 4) && InLOS(m)) + { + if (m.Map?.CanFit(m.Location, 16, false, false) != true) + { + m.SendLocalizedMessage(502391); // Thou can not be resurrected there! + } + else + { + Direction = GetDirectionTo(m); + + m.PlaySound(0x214); + m.FixedEffect(0x376A, 10, 16); + + m.CloseGump(); + m.SendGump(new ResurrectGump(m, ResurrectMessage.Healer)); + } + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Objectives.cs b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Objectives.cs index c55b1bf81..29f621670 100644 --- a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Objectives.cs +++ b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Objectives.cs @@ -1,425 +1,431 @@ -using Server.Items; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.Quests.Haven -{ - public class FindUzeraanBeginObjective : QuestObjective - { - public override object Message => 1046039; - - public override void OnComplete() - { - if (System.From.Profession == 5) // paladin - System.AddConversation(new UzeraanTitheConversation()); - else - System.AddConversation(new UzeraanFirstTaskConversation()); - } - } - - public class TitheGoldObjective : QuestObjective - { - private int m_OldTithingPoints; - - public TitheGoldObjective() => m_OldTithingPoints = -1; - - public override object Message => 1060386; - - public override void CheckProgress() - { - PlayerMobile pm = System.From; - int curTithingPoints = pm.TithingPoints; - - if (curTithingPoints >= 500) - Complete(); - else if (curTithingPoints > m_OldTithingPoints && m_OldTithingPoints >= 0) - pm.SendLocalizedMessage(1060240, "", - 0x41); // You must have at least 500 tithing points before you can continue in your quest. - - m_OldTithingPoints = curTithingPoints; - } - - public override void OnComplete() - { - System.AddObjective(new FindUzeraanFirstTaskObjective()); - } - } - - public class FindUzeraanFirstTaskObjective : QuestObjective - { - public override object Message => 1060387; - - public override void OnComplete() - { - System.AddConversation(new UzeraanFirstTaskConversation()); - } - } - - public enum KillHordeMinionsStep - { - First, - LearnKarma, - Others - } - - public class KillHordeMinionsObjective : QuestObjective - { - public KillHordeMinionsObjective() - { - } - - public KillHordeMinionsObjective(KillHordeMinionsStep step) => Step = step; - - public KillHordeMinionsStep Step { get; private set; } - - public override object Message - { - get - { - return Step switch - { - KillHordeMinionsStep.First => - /* Find the mountain pass beyond the house which lies at the - * end of the runic road.

- * - * Assist the city Militia by slaying Horde Minions - */ - 1049089, - KillHordeMinionsStep.LearnKarma => - /* You have just gained some Karma - * for killing the horde minion. Learn - * how this affects your Paladin abilities. - */ - 1060389, - _ => 1060507 - }; - } - } - - public override int MaxProgress - { - get - { - if (System.From.Profession == 5) // paladin - return Step switch - { - KillHordeMinionsStep.First => 1, - KillHordeMinionsStep.LearnKarma => 2, - _ => 5 - }; - - return 5; - } - } - - public override bool Completed - { - get - { - if (Step == KillHordeMinionsStep.LearnKarma && HasBeenRead) - return true; - return base.Completed; - } - } - - public override void RenderProgress(BaseQuestGump gump) - { - if (!Completed) - { - gump.AddHtmlObject(70, 260, 270, 100, 1049090, BaseQuestGump.Blue, false, false); // Horde Minions killed: - gump.AddLabel(70, 280, 0x64, CurProgress.ToString()); - } - else - { - base.RenderProgress(gump); - } - } - - public override void OnRead() - { - CheckCompletionStatus(); - } - - public override bool IgnoreYoungProtection(Mobile from) - { - // This restriction continues until the quest is ended - if (from is HordeMinion && from.Map == Map.Trammel && from.X >= 3314 && from.X <= 3814 && from.Y >= 2345 && - from.Y <= 3095) // Haven island - return true; - - return false; - } - - public override void OnKill(BaseCreature creature, Container corpse) - { - if (creature is HordeMinion && corpse.Map == Map.Trammel && corpse.X >= 3314 && corpse.X <= 3814 && - corpse.Y >= 2345 && corpse.Y <= 3095) // Haven island - { - if (CurProgress == 0) - System.From.Send(new DisplayHelpTopic(29, false)); // HEALING - - CurProgress++; - } - } - - public override void OnComplete() - { - if (System.From.Profession == 5) - switch (Step) - { - case KillHordeMinionsStep.First: - { - QuestObjective obj = new KillHordeMinionsObjective(KillHordeMinionsStep.LearnKarma); - System.AddObjective(obj); - obj.CurProgress = CurProgress; - break; - } - case KillHordeMinionsStep.LearnKarma: - { - QuestObjective obj = new KillHordeMinionsObjective(KillHordeMinionsStep.Others); - System.AddObjective(obj); - obj.CurProgress = CurProgress; - break; - } - default: - { - System.AddObjective(new FindUzeraanAboutReportObjective()); - break; - } - } - else - System.AddObjective(new FindUzeraanAboutReportObjective()); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - Step = (KillHordeMinionsStep)reader.ReadEncodedInt(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.WriteEncodedInt((int)Step); - } - } - - public class FindUzeraanAboutReportObjective : QuestObjective - { - public override object Message => 1049091; - - public override void OnComplete() - { - System.AddConversation(new UzeraanReportConversation()); - } - } - - public class FindSchmendrickObjective : QuestObjective - { - public override object Message => 1049120; - - public override bool IgnoreYoungProtection(Mobile from) - { - // This restriction begins when this objective is completed, and continues until the quest is ended - if (Completed && from is RestlessSoul && from.Map == Map.Trammel && from.X >= 5199 && from.X <= 5271 && - from.Y >= 1812 && from.Y <= 1865) // Schmendrick's cave - return true; - - return false; - } - - public override void OnComplete() - { - System.AddConversation(new SchmendrickConversation()); - } - } - - public class FindApprenticeObjective : QuestObjective - { - public override object Message => 1049323; - - public override void OnComplete() - { - System.AddObjective(new ReturnScrollOfPowerObjective()); - } - } - - public class ReturnScrollOfPowerObjective : QuestObjective - { - public override object Message => 1049324; - - public override void OnComplete() - { - System.AddConversation(new UzeraanScrollOfPowerConversation()); - } - } - - public class FindDryadObjective : QuestObjective - { - public override object Message => 1049358; - - public override void OnComplete() - { - System.AddConversation(new DryadConversation()); - } - } - - public class ReturnFertileDirtObjective : QuestObjective - { - public override object Message => 1049327; - - public override void OnComplete() - { - System.AddConversation(new UzeraanFertileDirtConversation()); - } - } - - public class GetDaemonBloodObjective : QuestObjective - { - private bool m_Ambushed; - - public override object Message => 1049361; - - public override void CheckProgress() - { - PlayerMobile player = System.From; - - if (!m_Ambushed && player.Map == Map.Trammel && player.InRange(new Point3D(3456, 2558, 50), 30)) - { - int x = player.X - 1; - int y = player.Y - 2; - int z = Map.Trammel.GetAverageZ(x, y); - - if (Map.Trammel.CanSpawnMobile(x, y, z)) - { - m_Ambushed = true; - - player.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1049330); // You have been ambushed! Fight for your honor!!! - - BaseCreature creature = new HordeMinion(); - creature.MoveToWorld(new Point3D(x, y, z), Map.Trammel); - creature.Combatant = player; - } - } - } - - public override void OnComplete() - { - System.AddObjective(new ReturnDaemonBloodObjective()); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_Ambushed = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(m_Ambushed); - } - } - - public class ReturnDaemonBloodObjective : QuestObjective - { - public override object Message => 1049332; - - public override void OnComplete() - { - System.AddConversation(new UzeraanDaemonBloodConversation()); - } - } - - public class GetDaemonBoneObjective : QuestObjective - { - public Container CorpseWithBone { get; set; } - - public override object Message - { - get - { - if (System.From.Profession == 5) return 1060755; - - /* Use Uzeraan's teleporter to get to the Haunted graveyard.

- * - * Slay the undead until you find a Daemon Bone. - */ - return 1049362; - } - } - - public override void OnComplete() - { - System.AddObjective(new ReturnDaemonBoneObjective()); - } - - public override bool IgnoreYoungProtection(Mobile from) - { - // This restriction continues until the end of the quest - if ((from is Zombie || from is Skeleton) && from.Map == Map.Trammel && from.X >= 3391 && from.X <= 3424 && - from.Y >= 2639 && from.Y <= 2664) // Haven graveyard - return true; - - return false; - } - - public override bool GetKillEvent(BaseCreature creature, Container corpse) - { - if (base.GetKillEvent(creature, corpse)) - return true; - - return UzeraanTurmoilQuest.HasLostDaemonBone(System.From); - } - - public override void OnKill(BaseCreature creature, Container corpse) - { - if ((creature is Zombie || creature is Skeleton) && corpse.Map == Map.Trammel && corpse.X >= 3391 && - corpse.X <= 3424 && corpse.Y >= 2639 && corpse.Y <= 2664) // Haven graveyard - if (Utility.RandomDouble() < 0.25) - CorpseWithBone = corpse; - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - CorpseWithBone = (Container)reader.ReadItem(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - if (CorpseWithBone?.Deleted == true) - CorpseWithBone = null; - - writer.WriteEncodedInt(0); // version - - writer.Write(CorpseWithBone); - } - } - - public class ReturnDaemonBoneObjective : QuestObjective - { - public override object Message => 1049334; - - public override void OnComplete() - { - System.AddConversation(new UzeraanDaemonBoneConversation()); - } - } - - public class CashBankCheckObjective : QuestObjective - { - public override object Message => 1049336; - - public override void OnComplete() - { - System.AddConversation(new BankerConversation()); - } - } -} +using Server.Items; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.Quests.Haven +{ + public class FindUzeraanBeginObjective : QuestObjective + { + public override object Message => 1046039; + + public override void OnComplete() + { + if (System.From.Profession == 5) // paladin + System.AddConversation(new UzeraanTitheConversation()); + else + System.AddConversation(new UzeraanFirstTaskConversation()); + } + } + + public class TitheGoldObjective : QuestObjective + { + private int m_OldTithingPoints; + + public TitheGoldObjective() => m_OldTithingPoints = -1; + + public override object Message => 1060386; + + public override void CheckProgress() + { + var pm = System.From; + var curTithingPoints = pm.TithingPoints; + + if (curTithingPoints >= 500) + Complete(); + else if (curTithingPoints > m_OldTithingPoints && m_OldTithingPoints >= 0) + pm.SendLocalizedMessage( + 1060240, + "", + 0x41 + ); // You must have at least 500 tithing points before you can continue in your quest. + + m_OldTithingPoints = curTithingPoints; + } + + public override void OnComplete() + { + System.AddObjective(new FindUzeraanFirstTaskObjective()); + } + } + + public class FindUzeraanFirstTaskObjective : QuestObjective + { + public override object Message => 1060387; + + public override void OnComplete() + { + System.AddConversation(new UzeraanFirstTaskConversation()); + } + } + + public enum KillHordeMinionsStep + { + First, + LearnKarma, + Others + } + + public class KillHordeMinionsObjective : QuestObjective + { + public KillHordeMinionsObjective() + { + } + + public KillHordeMinionsObjective(KillHordeMinionsStep step) => Step = step; + + public KillHordeMinionsStep Step { get; private set; } + + public override object Message + { + get + { + return Step switch + { + KillHordeMinionsStep.First => + /* Find the mountain pass beyond the house which lies at the + * end of the runic road.

+ * + * Assist the city Militia by slaying Horde Minions + */ + 1049089, + KillHordeMinionsStep.LearnKarma => + /* You have just gained some Karma + * for killing the horde minion. Learn + * how this affects your Paladin abilities. + */ + 1060389, + _ => 1060507 + }; + } + } + + public override int MaxProgress + { + get + { + if (System.From.Profession == 5) // paladin + return Step switch + { + KillHordeMinionsStep.First => 1, + KillHordeMinionsStep.LearnKarma => 2, + _ => 5 + }; + + return 5; + } + } + + public override bool Completed + { + get + { + if (Step == KillHordeMinionsStep.LearnKarma && HasBeenRead) + return true; + return base.Completed; + } + } + + public override void RenderProgress(BaseQuestGump gump) + { + if (!Completed) + { + gump.AddHtmlObject(70, 260, 270, 100, 1049090, BaseQuestGump.Blue, false, false); // Horde Minions killed: + gump.AddLabel(70, 280, 0x64, CurProgress.ToString()); + } + else + { + base.RenderProgress(gump); + } + } + + public override void OnRead() + { + CheckCompletionStatus(); + } + + public override bool IgnoreYoungProtection(Mobile from) + { + // This restriction continues until the quest is ended + if (from is HordeMinion && from.Map == Map.Trammel && from.X >= 3314 && from.X <= 3814 && from.Y >= 2345 && + from.Y <= 3095) // Haven island + return true; + + return false; + } + + public override void OnKill(BaseCreature creature, Container corpse) + { + if (creature is HordeMinion && corpse.Map == Map.Trammel && corpse.X >= 3314 && corpse.X <= 3814 && + corpse.Y >= 2345 && corpse.Y <= 3095) // Haven island + { + if (CurProgress == 0) + System.From.Send(new DisplayHelpTopic(29, false)); // HEALING + + CurProgress++; + } + } + + public override void OnComplete() + { + if (System.From.Profession == 5) + switch (Step) + { + case KillHordeMinionsStep.First: + { + QuestObjective obj = new KillHordeMinionsObjective(KillHordeMinionsStep.LearnKarma); + System.AddObjective(obj); + obj.CurProgress = CurProgress; + break; + } + case KillHordeMinionsStep.LearnKarma: + { + QuestObjective obj = new KillHordeMinionsObjective(KillHordeMinionsStep.Others); + System.AddObjective(obj); + obj.CurProgress = CurProgress; + break; + } + default: + { + System.AddObjective(new FindUzeraanAboutReportObjective()); + break; + } + } + else + System.AddObjective(new FindUzeraanAboutReportObjective()); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + Step = (KillHordeMinionsStep)reader.ReadEncodedInt(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.WriteEncodedInt((int)Step); + } + } + + public class FindUzeraanAboutReportObjective : QuestObjective + { + public override object Message => 1049091; + + public override void OnComplete() + { + System.AddConversation(new UzeraanReportConversation()); + } + } + + public class FindSchmendrickObjective : QuestObjective + { + public override object Message => 1049120; + + public override bool IgnoreYoungProtection(Mobile from) + { + // This restriction begins when this objective is completed, and continues until the quest is ended + if (Completed && from is RestlessSoul && from.Map == Map.Trammel && from.X >= 5199 && from.X <= 5271 && + from.Y >= 1812 && from.Y <= 1865) // Schmendrick's cave + return true; + + return false; + } + + public override void OnComplete() + { + System.AddConversation(new SchmendrickConversation()); + } + } + + public class FindApprenticeObjective : QuestObjective + { + public override object Message => 1049323; + + public override void OnComplete() + { + System.AddObjective(new ReturnScrollOfPowerObjective()); + } + } + + public class ReturnScrollOfPowerObjective : QuestObjective + { + public override object Message => 1049324; + + public override void OnComplete() + { + System.AddConversation(new UzeraanScrollOfPowerConversation()); + } + } + + public class FindDryadObjective : QuestObjective + { + public override object Message => 1049358; + + public override void OnComplete() + { + System.AddConversation(new DryadConversation()); + } + } + + public class ReturnFertileDirtObjective : QuestObjective + { + public override object Message => 1049327; + + public override void OnComplete() + { + System.AddConversation(new UzeraanFertileDirtConversation()); + } + } + + public class GetDaemonBloodObjective : QuestObjective + { + private bool m_Ambushed; + + public override object Message => 1049361; + + public override void CheckProgress() + { + var player = System.From; + + if (!m_Ambushed && player.Map == Map.Trammel && player.InRange(new Point3D(3456, 2558, 50), 30)) + { + var x = player.X - 1; + var y = player.Y - 2; + var z = Map.Trammel.GetAverageZ(x, y); + + if (Map.Trammel.CanSpawnMobile(x, y, z)) + { + m_Ambushed = true; + + player.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1049330 + ); // You have been ambushed! Fight for your honor!!! + + BaseCreature creature = new HordeMinion(); + creature.MoveToWorld(new Point3D(x, y, z), Map.Trammel); + creature.Combatant = player; + } + } + } + + public override void OnComplete() + { + System.AddObjective(new ReturnDaemonBloodObjective()); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_Ambushed = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(m_Ambushed); + } + } + + public class ReturnDaemonBloodObjective : QuestObjective + { + public override object Message => 1049332; + + public override void OnComplete() + { + System.AddConversation(new UzeraanDaemonBloodConversation()); + } + } + + public class GetDaemonBoneObjective : QuestObjective + { + public Container CorpseWithBone { get; set; } + + public override object Message + { + get + { + if (System.From.Profession == 5) return 1060755; + + /* Use Uzeraan's teleporter to get to the Haunted graveyard.

+ * + * Slay the undead until you find a Daemon Bone. + */ + return 1049362; + } + } + + public override void OnComplete() + { + System.AddObjective(new ReturnDaemonBoneObjective()); + } + + public override bool IgnoreYoungProtection(Mobile from) + { + // This restriction continues until the end of the quest + if ((from is Zombie || from is Skeleton) && from.Map == Map.Trammel && from.X >= 3391 && from.X <= 3424 && + from.Y >= 2639 && from.Y <= 2664) // Haven graveyard + return true; + + return false; + } + + public override bool GetKillEvent(BaseCreature creature, Container corpse) + { + if (base.GetKillEvent(creature, corpse)) + return true; + + return UzeraanTurmoilQuest.HasLostDaemonBone(System.From); + } + + public override void OnKill(BaseCreature creature, Container corpse) + { + if ((creature is Zombie || creature is Skeleton) && corpse.Map == Map.Trammel && corpse.X >= 3391 && + corpse.X <= 3424 && corpse.Y >= 2639 && corpse.Y <= 2664) // Haven graveyard + if (Utility.RandomDouble() < 0.25) + CorpseWithBone = corpse; + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + CorpseWithBone = (Container)reader.ReadItem(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + if (CorpseWithBone?.Deleted == true) + CorpseWithBone = null; + + writer.WriteEncodedInt(0); // version + + writer.Write(CorpseWithBone); + } + } + + public class ReturnDaemonBoneObjective : QuestObjective + { + public override object Message => 1049334; + + public override void OnComplete() + { + System.AddConversation(new UzeraanDaemonBoneConversation()); + } + } + + public class CashBankCheckObjective : QuestObjective + { + public override object Message => 1049336; + + public override void OnComplete() + { + System.AddConversation(new BankerConversation()); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/UzeraanTurmoilQuest.cs b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/UzeraanTurmoilQuest.cs index 3a25ccb9f..26d6eda25 100644 --- a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/UzeraanTurmoilQuest.cs +++ b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/UzeraanTurmoilQuest.cs @@ -1,167 +1,167 @@ -using System; -using Server.Mobiles; - -namespace Server.Engines.Quests.Haven -{ - public class UzeraanTurmoilQuest : QuestSystem - { - private static readonly Type[] m_TypeReferenceTable = - { - typeof(AcceptConversation), - typeof(UzeraanTitheConversation), - typeof(UzeraanFirstTaskConversation), - typeof(UzeraanReportConversation), - typeof(SchmendrickConversation), - typeof(UzeraanScrollOfPowerConversation), - typeof(DryadConversation), - typeof(UzeraanFertileDirtConversation), - typeof(UzeraanDaemonBloodConversation), - typeof(UzeraanDaemonBoneConversation), - typeof(BankerConversation), - typeof(RadarConversation), - typeof(LostScrollOfPowerConversation), - typeof(LostFertileDirtConversation), - typeof(DryadAppleConversation), - typeof(LostDaemonBloodConversation), - typeof(LostDaemonBoneConversation), - typeof(FindUzeraanBeginObjective), - typeof(TitheGoldObjective), - typeof(FindUzeraanFirstTaskObjective), - typeof(KillHordeMinionsObjective), - typeof(FindUzeraanAboutReportObjective), - typeof(FindSchmendrickObjective), - typeof(FindApprenticeObjective), - typeof(ReturnScrollOfPowerObjective), - typeof(FindDryadObjective), - typeof(ReturnFertileDirtObjective), - typeof(GetDaemonBloodObjective), - typeof(ReturnDaemonBloodObjective), - typeof(GetDaemonBoneObjective), - typeof(ReturnDaemonBoneObjective), - typeof(CashBankCheckObjective), - typeof(FewReagentsConversation) - }; - - private bool m_HasLeftTheMansion; - - public UzeraanTurmoilQuest(PlayerMobile from) : base(from) - { - } - - // Serialization - public UzeraanTurmoilQuest() - { - } - - public override Type[] TypeReferenceTable => m_TypeReferenceTable; - - public override object Name => 1049007; - - public override object OfferMessage => 1049008; - - public override TimeSpan RestartDelay => TimeSpan.MaxValue; - public override bool IsTutorial => true; - - public override int Picture - { - get - { - return From.Profession switch - { - 1 => 0x15C9, // warrior - 2 => 0x15C1, // magician - _ => 0x15D3 - }; - } - } - - public override void Slice() - { - if (!m_HasLeftTheMansion && - (From.Map != Map.Trammel || From.X < 3573 || From.X > 3611 || From.Y < 2568 || From.Y > 2606)) - { - m_HasLeftTheMansion = true; - AddConversation(new RadarConversation()); - } - - base.Slice(); - } - - public override void Accept() - { - base.Accept(); - - AddConversation(new AcceptConversation()); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_HasLeftTheMansion = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(m_HasLeftTheMansion); - } - - public static bool HasLostScrollOfPower(Mobile from) - { - if (!(from is PlayerMobile pm)) - return false; - - QuestSystem qs = pm.Quest; - - if (qs is UzeraanTurmoilQuest) - if (qs.IsObjectiveInProgress(typeof(ReturnScrollOfPowerObjective))) - return from.Backpack?.FindItemByType() == null; - - return false; - } - - public static bool HasLostFertileDirt(Mobile from) - { - if (!(from is PlayerMobile pm)) - return false; - - QuestSystem qs = pm.Quest; - - if (qs is UzeraanTurmoilQuest) - if (qs.IsObjectiveInProgress(typeof(ReturnFertileDirtObjective))) - return from.Backpack?.FindItemByType() == null; - - return false; - } - - public static bool HasLostDaemonBlood(Mobile from) - { - if (!(from is PlayerMobile pm)) - return false; - - QuestSystem qs = pm.Quest; - - if (qs is UzeraanTurmoilQuest) - if (qs.IsObjectiveInProgress(typeof(ReturnDaemonBloodObjective))) - return from.Backpack?.FindItemByType() == null; - - return false; - } - - public static bool HasLostDaemonBone(Mobile from) - { - if (!(from is PlayerMobile pm)) - return false; - - QuestSystem qs = pm.Quest; - - if (qs is UzeraanTurmoilQuest) - if (qs.IsObjectiveInProgress(typeof(ReturnDaemonBoneObjective))) - return from.Backpack?.FindItemByType() == null; - - return false; - } - } -} +using System; +using Server.Mobiles; + +namespace Server.Engines.Quests.Haven +{ + public class UzeraanTurmoilQuest : QuestSystem + { + private static readonly Type[] m_TypeReferenceTable = + { + typeof(AcceptConversation), + typeof(UzeraanTitheConversation), + typeof(UzeraanFirstTaskConversation), + typeof(UzeraanReportConversation), + typeof(SchmendrickConversation), + typeof(UzeraanScrollOfPowerConversation), + typeof(DryadConversation), + typeof(UzeraanFertileDirtConversation), + typeof(UzeraanDaemonBloodConversation), + typeof(UzeraanDaemonBoneConversation), + typeof(BankerConversation), + typeof(RadarConversation), + typeof(LostScrollOfPowerConversation), + typeof(LostFertileDirtConversation), + typeof(DryadAppleConversation), + typeof(LostDaemonBloodConversation), + typeof(LostDaemonBoneConversation), + typeof(FindUzeraanBeginObjective), + typeof(TitheGoldObjective), + typeof(FindUzeraanFirstTaskObjective), + typeof(KillHordeMinionsObjective), + typeof(FindUzeraanAboutReportObjective), + typeof(FindSchmendrickObjective), + typeof(FindApprenticeObjective), + typeof(ReturnScrollOfPowerObjective), + typeof(FindDryadObjective), + typeof(ReturnFertileDirtObjective), + typeof(GetDaemonBloodObjective), + typeof(ReturnDaemonBloodObjective), + typeof(GetDaemonBoneObjective), + typeof(ReturnDaemonBoneObjective), + typeof(CashBankCheckObjective), + typeof(FewReagentsConversation) + }; + + private bool m_HasLeftTheMansion; + + public UzeraanTurmoilQuest(PlayerMobile from) : base(from) + { + } + + // Serialization + public UzeraanTurmoilQuest() + { + } + + public override Type[] TypeReferenceTable => m_TypeReferenceTable; + + public override object Name => 1049007; + + public override object OfferMessage => 1049008; + + public override TimeSpan RestartDelay => TimeSpan.MaxValue; + public override bool IsTutorial => true; + + public override int Picture + { + get + { + return From.Profession switch + { + 1 => 0x15C9, // warrior + 2 => 0x15C1, // magician + _ => 0x15D3 + }; + } + } + + public override void Slice() + { + if (!m_HasLeftTheMansion && + (From.Map != Map.Trammel || From.X < 3573 || From.X > 3611 || From.Y < 2568 || From.Y > 2606)) + { + m_HasLeftTheMansion = true; + AddConversation(new RadarConversation()); + } + + base.Slice(); + } + + public override void Accept() + { + base.Accept(); + + AddConversation(new AcceptConversation()); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_HasLeftTheMansion = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(m_HasLeftTheMansion); + } + + public static bool HasLostScrollOfPower(Mobile from) + { + if (!(from is PlayerMobile pm)) + return false; + + var qs = pm.Quest; + + if (qs is UzeraanTurmoilQuest) + if (qs.IsObjectiveInProgress(typeof(ReturnScrollOfPowerObjective))) + return from.Backpack?.FindItemByType() == null; + + return false; + } + + public static bool HasLostFertileDirt(Mobile from) + { + if (!(from is PlayerMobile pm)) + return false; + + var qs = pm.Quest; + + if (qs is UzeraanTurmoilQuest) + if (qs.IsObjectiveInProgress(typeof(ReturnFertileDirtObjective))) + return from.Backpack?.FindItemByType() == null; + + return false; + } + + public static bool HasLostDaemonBlood(Mobile from) + { + if (!(from is PlayerMobile pm)) + return false; + + var qs = pm.Quest; + + if (qs is UzeraanTurmoilQuest) + if (qs.IsObjectiveInProgress(typeof(ReturnDaemonBloodObjective))) + return from.Backpack?.FindItemByType() == null; + + return false; + } + + public static bool HasLostDaemonBone(Mobile from) + { + if (!(from is PlayerMobile pm)) + return false; + + var qs = pm.Quest; + + if (qs is UzeraanTurmoilQuest) + if (qs.IsObjectiveInProgress(typeof(ReturnDaemonBoneObjective))) + return from.Backpack?.FindItemByType() == null; + + return false; + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Witch Apprentice/Conversations.cs b/Projects/UOContent/Engines/Quests/Witch Apprentice/Conversations.cs index bbcc1b1f1..bb9f2dff4 100644 --- a/Projects/UOContent/Engines/Quests/Witch Apprentice/Conversations.cs +++ b/Projects/UOContent/Engines/Quests/Witch Apprentice/Conversations.cs @@ -1,285 +1,287 @@ -namespace Server.Engines.Quests.Hag -{ - public class DontOfferConversation : QuestConversation - { - public override object Message => 1055000; - - public override bool Logged => false; - } - - public class AcceptConversation : QuestConversation - { - public override object Message => 1055002; - - public override void OnRead() - { - System.AddObjective(new FindApprenticeObjective(true)); - } - } - - public class HagDuringCorpseSearchConversation : QuestConversation - { - public override object Message => 1055003; - - public override bool Logged => false; - } - - public class ApprenticeCorpseConversation : QuestConversation - { - public override object Message => 1055004; - - public override void OnRead() - { - System.AddObjective(new FindGrizeldaAboutMurderObjective()); - } - } - - public class MurderConversation : QuestConversation - { - public override object Message => 1055005; - - public override void OnRead() - { - System.AddObjective(new KillImpsObjective(true)); - } - } - - public class HagDuringImpSearchConversation : QuestConversation - { - public override object Message => 1055006; - - public override bool Logged => false; - } - - public class ImpDeathConversation : QuestConversation - { - private Point3D m_ImpLocation; - - public ImpDeathConversation(Point3D impLocation) => m_ImpLocation = impLocation; - - public ImpDeathConversation() - { - } - - public override object Message => 1055007; - - public override void OnRead() - { - System.AddObjective(new FindZeefzorpulObjective(m_ImpLocation)); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_ImpLocation = reader.ReadPoint3D(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(m_ImpLocation); - } - } - - public class ZeefzorpulConversation : QuestConversation - { - public override object Message => 1055008; - - public override void OnRead() - { - System.AddObjective(new ReturnRecipeObjective()); - } - } - - public class RecipeConversation : QuestConversation - { - public override object Message => 1055009; - - public override void OnRead() - { - System.AddObjective(new FindIngredientObjective(global::System.Array.Empty())); - } - } - - public class HagDuringIngredientsConversation : QuestConversation - { - public override object Message => 1055012; - - public override bool Logged => false; - } - - public class BlackheartFirstConversation : QuestConversation - { - public override object Message => 1055010; - - public override void OnRead() - { - FindIngredientObjective obj = System.FindObjective(); - if (obj != null) - System.AddObjective(new FindIngredientObjective(obj.Ingredients, true)); - } - } - - public class BlackheartNoPirateConversation : QuestConversation - { - private bool m_Drunken; - private bool m_Tricorne; - - public BlackheartNoPirateConversation(bool tricorne, bool drunken) - { - m_Tricorne = tricorne; - m_Drunken = drunken; - } - - public BlackheartNoPirateConversation() - { - } - - public override object Message - { - get - { - if (m_Tricorne) - { - if (m_Drunken) return 1055059; - - /* Captain Blackheart looks up from polishing his cutlass, glaring at - * you with red-rimmed eyes.

- * - * Well, well. Lookit the wee little deck swabby. Aren't ye a cute lil' - * lassy? Don't ye look just fancy? Ye think yer ready te join me pirate - * crew? Ye think I should offer ye some've me special Blackheart brew?

- * - * I'll make ye walk the plank, I will! We'll see how sweet n' darlin' ye - * look when the sea serpents get at ye and rip ye te threads! Won't that be - * a pretty picture, eh?

- * - * Ye don't have the stomach fer the pirate life, that's plain enough te me. Ye - * prance around here like a wee lil' princess, ye do. If ye want to join my - * crew ye can't just look tha part - ye have to have the stomach fer it, filled - * up with rotgut until ye can't see straight. I don't drink with just any ol' - * landlubber! Ye'd best prove yer mettle before ye talk te me again!

- * - * The drunken pirate captain leans back in his chair, taking another gulp of - * his drink before he starts in on another bawdy pirate song. - */ - return 1055057; - } - - if (m_Drunken) return 1055056; - - /* Captain Blackheart looks up from his drink, almost tipping over - * his chair as he looks you up and down.

- * - * You again? I thought I told ye te get lost? Go on with ye! Ye ain't - * no pirate - yer not even fit te clean the barnacles off me rear end! - * Don't ye come back babbling te me for any of me Blackheart Whiskey until - * ye look and act like a true pirate!

- * - * Now shove off, sewer rat - I've got drinkin' te do!

- * - * The inebriated pirate bolts back another mug of ale and brushes you - * off with a wave of his hand. - */ - return 1055058; - } - } - - public override bool Logged => false; - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_Tricorne = reader.ReadBool(); - m_Drunken = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(m_Tricorne); - writer.Write(m_Drunken); - } - } - - public class BlackheartPirateConversation : QuestConversation - { - private bool m_FirstMet; - - public BlackheartPirateConversation(bool firstMet) => m_FirstMet = firstMet; - - public BlackheartPirateConversation() - { - } - - public override object Message - { - get - { - if (m_FirstMet) return 1055054; - - /* The drunken pirate, Captain Blackheart, looks up from his bottle - * of whiskey with a pleased expression.

- * - * Well looky here! I didn't think a landlubber like yourself had the pirate - * blood in ye! But look at that! You certainly look the part now! Sure - * you can still keep on your feet? Har!

- * - * Avast ye, ye loveable pirate! Ye deserve a belt of better brew than the slop - * ye've been drinking, and I've just the thing.

- * - * I call it Captain Blackheart's Whiskey, and it'll give ye hairs on yer chest, - * that's for sure. Why, a keg of this stuff once spilled on my ship, and it ate - * a hole right through the deck!

- * - * Go on, drink up, or use it to clean the rust off your cutlass - it's the best - * brew, either way!

- * - * Captain Blackheart hands you a jug of his famous Whiskey. You think it best - * to return it to the Hag, rather than drink any of the noxious swill. - */ - return 1055011; - } - } - - public override void OnRead() - { - System.FindObjective()?.NextStep(); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_FirstMet = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(m_FirstMet); - } - } - - public class EndConversation : QuestConversation - { - public override object Message => 1055013; - - public override void OnRead() - { - System.Complete(); - } - } - - public class RecentlyFinishedConversation : QuestConversation - { - public override object Message => 1055064; - - public override bool Logged => false; - } -} +using System; + +namespace Server.Engines.Quests.Hag +{ + public class DontOfferConversation : QuestConversation + { + public override object Message => 1055000; + + public override bool Logged => false; + } + + public class AcceptConversation : QuestConversation + { + public override object Message => 1055002; + + public override void OnRead() + { + System.AddObjective(new FindApprenticeObjective(true)); + } + } + + public class HagDuringCorpseSearchConversation : QuestConversation + { + public override object Message => 1055003; + + public override bool Logged => false; + } + + public class ApprenticeCorpseConversation : QuestConversation + { + public override object Message => 1055004; + + public override void OnRead() + { + System.AddObjective(new FindGrizeldaAboutMurderObjective()); + } + } + + public class MurderConversation : QuestConversation + { + public override object Message => 1055005; + + public override void OnRead() + { + System.AddObjective(new KillImpsObjective(true)); + } + } + + public class HagDuringImpSearchConversation : QuestConversation + { + public override object Message => 1055006; + + public override bool Logged => false; + } + + public class ImpDeathConversation : QuestConversation + { + private Point3D m_ImpLocation; + + public ImpDeathConversation(Point3D impLocation) => m_ImpLocation = impLocation; + + public ImpDeathConversation() + { + } + + public override object Message => 1055007; + + public override void OnRead() + { + System.AddObjective(new FindZeefzorpulObjective(m_ImpLocation)); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_ImpLocation = reader.ReadPoint3D(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(m_ImpLocation); + } + } + + public class ZeefzorpulConversation : QuestConversation + { + public override object Message => 1055008; + + public override void OnRead() + { + System.AddObjective(new ReturnRecipeObjective()); + } + } + + public class RecipeConversation : QuestConversation + { + public override object Message => 1055009; + + public override void OnRead() + { + System.AddObjective(new FindIngredientObjective(Array.Empty())); + } + } + + public class HagDuringIngredientsConversation : QuestConversation + { + public override object Message => 1055012; + + public override bool Logged => false; + } + + public class BlackheartFirstConversation : QuestConversation + { + public override object Message => 1055010; + + public override void OnRead() + { + var obj = System.FindObjective(); + if (obj != null) + System.AddObjective(new FindIngredientObjective(obj.Ingredients, true)); + } + } + + public class BlackheartNoPirateConversation : QuestConversation + { + private bool m_Drunken; + private bool m_Tricorne; + + public BlackheartNoPirateConversation(bool tricorne, bool drunken) + { + m_Tricorne = tricorne; + m_Drunken = drunken; + } + + public BlackheartNoPirateConversation() + { + } + + public override object Message + { + get + { + if (m_Tricorne) + { + if (m_Drunken) return 1055059; + + /* Captain Blackheart looks up from polishing his cutlass, glaring at + * you with red-rimmed eyes.

+ * + * Well, well. Lookit the wee little deck swabby. Aren't ye a cute lil' + * lassy? Don't ye look just fancy? Ye think yer ready te join me pirate + * crew? Ye think I should offer ye some've me special Blackheart brew?

+ * + * I'll make ye walk the plank, I will! We'll see how sweet n' darlin' ye + * look when the sea serpents get at ye and rip ye te threads! Won't that be + * a pretty picture, eh?

+ * + * Ye don't have the stomach fer the pirate life, that's plain enough te me. Ye + * prance around here like a wee lil' princess, ye do. If ye want to join my + * crew ye can't just look tha part - ye have to have the stomach fer it, filled + * up with rotgut until ye can't see straight. I don't drink with just any ol' + * landlubber! Ye'd best prove yer mettle before ye talk te me again!

+ * + * The drunken pirate captain leans back in his chair, taking another gulp of + * his drink before he starts in on another bawdy pirate song. + */ + return 1055057; + } + + if (m_Drunken) return 1055056; + + /* Captain Blackheart looks up from his drink, almost tipping over + * his chair as he looks you up and down.

+ * + * You again? I thought I told ye te get lost? Go on with ye! Ye ain't + * no pirate - yer not even fit te clean the barnacles off me rear end! + * Don't ye come back babbling te me for any of me Blackheart Whiskey until + * ye look and act like a true pirate!

+ * + * Now shove off, sewer rat - I've got drinkin' te do!

+ * + * The inebriated pirate bolts back another mug of ale and brushes you + * off with a wave of his hand. + */ + return 1055058; + } + } + + public override bool Logged => false; + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_Tricorne = reader.ReadBool(); + m_Drunken = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(m_Tricorne); + writer.Write(m_Drunken); + } + } + + public class BlackheartPirateConversation : QuestConversation + { + private bool m_FirstMet; + + public BlackheartPirateConversation(bool firstMet) => m_FirstMet = firstMet; + + public BlackheartPirateConversation() + { + } + + public override object Message + { + get + { + if (m_FirstMet) return 1055054; + + /* The drunken pirate, Captain Blackheart, looks up from his bottle + * of whiskey with a pleased expression.

+ * + * Well looky here! I didn't think a landlubber like yourself had the pirate + * blood in ye! But look at that! You certainly look the part now! Sure + * you can still keep on your feet? Har!

+ * + * Avast ye, ye loveable pirate! Ye deserve a belt of better brew than the slop + * ye've been drinking, and I've just the thing.

+ * + * I call it Captain Blackheart's Whiskey, and it'll give ye hairs on yer chest, + * that's for sure. Why, a keg of this stuff once spilled on my ship, and it ate + * a hole right through the deck!

+ * + * Go on, drink up, or use it to clean the rust off your cutlass - it's the best + * brew, either way!

+ * + * Captain Blackheart hands you a jug of his famous Whiskey. You think it best + * to return it to the Hag, rather than drink any of the noxious swill. + */ + return 1055011; + } + } + + public override void OnRead() + { + System.FindObjective()?.NextStep(); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_FirstMet = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(m_FirstMet); + } + } + + public class EndConversation : QuestConversation + { + public override object Message => 1055013; + + public override void OnRead() + { + System.Complete(); + } + } + + public class RecentlyFinishedConversation : QuestConversation + { + public override object Message => 1055064; + + public override bool Logged => false; + } +} diff --git a/Projects/UOContent/Engines/Quests/Witch Apprentice/Ingredient.cs b/Projects/UOContent/Engines/Quests/Witch Apprentice/Ingredient.cs index 9b2582993..e431cab6e 100644 --- a/Projects/UOContent/Engines/Quests/Witch Apprentice/Ingredient.cs +++ b/Projects/UOContent/Engines/Quests/Witch Apprentice/Ingredient.cs @@ -1,104 +1,104 @@ -using System; -using Server.Mobiles; - -namespace Server.Engines.Quests.Hag -{ - public enum Ingredient - { - SheepLiver, - RabbitsFoot, - MongbatWing, - ChickenGizzard, - RatTail, - FrogsLeg, - DeerHeart, - LizardTongue, - SlimeOoze, - SpiritEssence, - SwampWater, - RedMushrooms, - Bones, - StarChart, - Whiskey - } - - public class IngredientInfo - { - private static readonly IngredientInfo[] m_Table = - { - // sheep liver - new IngredientInfo(1055020, 5, typeof(Sheep)), - // rabbit's foot - new IngredientInfo(1055021, 5, typeof(Rabbit), typeof(JackRabbit)), - // mongbat wing - new IngredientInfo(1055022, 5, typeof(Mongbat), typeof(GreaterMongbat)), - // chicken gizzard - new IngredientInfo(1055023, 5, typeof(Chicken)), - // rat tail - new IngredientInfo(1055024, 5, typeof(Rat), typeof(GiantRat), typeof(SewerRat)), - // frog's leg - new IngredientInfo(1055025, 5, typeof(BullFrog)), - // deer heart - new IngredientInfo(1055026, 5, typeof(Hind), typeof(GreatHart)), - // lizard tongue - new IngredientInfo(1055027, 5, typeof(LavaLizard), typeof(Lizardman)), - // slime ooze - new IngredientInfo(1055028, 5, typeof(Slime)), - // spirit essence - new IngredientInfo(1055029, 5, typeof(Ghoul), typeof(Spectre), typeof(Shade), typeof(Wraith), typeof(Bogle)), - // Swamp Water - new IngredientInfo(1055030, 1), - // Freshly Cut Red Mushrooms - new IngredientInfo(1055031, 1), - // Bones Buried In Hallowed Ground - new IngredientInfo(1055032, 1), - // Star Chart - new IngredientInfo(1055033, 1), - // Captain Blackheart's Whiskey - new IngredientInfo(1055034, 1) - }; - - private IngredientInfo(int name, int quantity, params Type[] creatures) - { - Name = name; - Creatures = creatures; - Quantity = quantity; - } - - public int Name { get; } - - public Type[] Creatures { get; } - - public int Quantity { get; } - - public static IngredientInfo Get(Ingredient ingredient) - { - int index = (int)ingredient; - - if (index >= 0 && index < m_Table.Length) - return m_Table[index]; - return m_Table[0]; - } - - public static Ingredient RandomIngredient(Ingredient[] oldIngredients) - { - int length = m_Table.Length - oldIngredients.Length; - Ingredient[] ingredients = new Ingredient[length]; - - for (int i = 0, n = 0; i < m_Table.Length && n < ingredients.Length; i++) - { - Ingredient currIngredient = (Ingredient)i; - - bool found = false; - for (int j = 0; !found && j < oldIngredients.Length; j++) - if (oldIngredients[j] == currIngredient) - found = true; - - if (!found) - ingredients[n++] = currIngredient; - } - - return ingredients.RandomElement(); - } - } -} +using System; +using Server.Mobiles; + +namespace Server.Engines.Quests.Hag +{ + public enum Ingredient + { + SheepLiver, + RabbitsFoot, + MongbatWing, + ChickenGizzard, + RatTail, + FrogsLeg, + DeerHeart, + LizardTongue, + SlimeOoze, + SpiritEssence, + SwampWater, + RedMushrooms, + Bones, + StarChart, + Whiskey + } + + public class IngredientInfo + { + private static readonly IngredientInfo[] m_Table = + { + // sheep liver + new IngredientInfo(1055020, 5, typeof(Sheep)), + // rabbit's foot + new IngredientInfo(1055021, 5, typeof(Rabbit), typeof(JackRabbit)), + // mongbat wing + new IngredientInfo(1055022, 5, typeof(Mongbat), typeof(GreaterMongbat)), + // chicken gizzard + new IngredientInfo(1055023, 5, typeof(Chicken)), + // rat tail + new IngredientInfo(1055024, 5, typeof(Rat), typeof(GiantRat), typeof(SewerRat)), + // frog's leg + new IngredientInfo(1055025, 5, typeof(BullFrog)), + // deer heart + new IngredientInfo(1055026, 5, typeof(Hind), typeof(GreatHart)), + // lizard tongue + new IngredientInfo(1055027, 5, typeof(LavaLizard), typeof(Lizardman)), + // slime ooze + new IngredientInfo(1055028, 5, typeof(Slime)), + // spirit essence + new IngredientInfo(1055029, 5, typeof(Ghoul), typeof(Spectre), typeof(Shade), typeof(Wraith), typeof(Bogle)), + // Swamp Water + new IngredientInfo(1055030, 1), + // Freshly Cut Red Mushrooms + new IngredientInfo(1055031, 1), + // Bones Buried In Hallowed Ground + new IngredientInfo(1055032, 1), + // Star Chart + new IngredientInfo(1055033, 1), + // Captain Blackheart's Whiskey + new IngredientInfo(1055034, 1) + }; + + private IngredientInfo(int name, int quantity, params Type[] creatures) + { + Name = name; + Creatures = creatures; + Quantity = quantity; + } + + public int Name { get; } + + public Type[] Creatures { get; } + + public int Quantity { get; } + + public static IngredientInfo Get(Ingredient ingredient) + { + var index = (int)ingredient; + + if (index >= 0 && index < m_Table.Length) + return m_Table[index]; + return m_Table[0]; + } + + public static Ingredient RandomIngredient(Ingredient[] oldIngredients) + { + var length = m_Table.Length - oldIngredients.Length; + var ingredients = new Ingredient[length]; + + for (int i = 0, n = 0; i < m_Table.Length && n < ingredients.Length; i++) + { + var currIngredient = (Ingredient)i; + + var found = false; + for (var j = 0; !found && j < oldIngredients.Length; j++) + if (oldIngredients[j] == currIngredient) + found = true; + + if (!found) + ingredients[n++] = currIngredient; + } + + return ingredients.RandomElement(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/Cauldron.cs b/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/Cauldron.cs index ff80891f5..03f5bb1c5 100644 --- a/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/Cauldron.cs +++ b/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/Cauldron.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class Cauldron : Item - { - [Constructible] - public Cauldron() : base(0x9ED) => Weight = 1.0; - - public Cauldron(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a cauldron"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Cauldron : Item + { + [Constructible] + public Cauldron() : base(0x9ED) => Weight = 1.0; + + public Cauldron(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a cauldron"; + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/HagApprenticeCorpse.cs b/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/HagApprenticeCorpse.cs index 72b0a1928..ade91e45d 100644 --- a/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/HagApprenticeCorpse.cs +++ b/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/HagApprenticeCorpse.cs @@ -1,99 +1,101 @@ -using System.Collections.Generic; -using Server.Items; -using Server.Misc; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.Quests.Hag -{ - public class HagApprenticeCorpse : Corpse - { - [Constructible] - public HagApprenticeCorpse() : base(GetOwner(), GetEquipment()) - { - Direction = Direction.South; - - foreach (Item item in EquipItems) - DropItem(item); - } - - public HagApprenticeCorpse(Serial serial) : base(serial) - { - } - - // TODO: What is this? Why are we creating a mobile and deleting it? - private static Mobile GetOwner() - { - Mobile apprentice = new Mobile(); - - apprentice.Hue = Race.Human.RandomSkinHue(); - apprentice.Female = false; - apprentice.Body = 0x190; - - apprentice.Delete(); - - return apprentice; - } - - private static List GetEquipment() => new List(); - - public override void AddNameProperty(ObjectPropertyList list) - { - list.Add("a charred corpse"); - } - - public override void OnSingleClick(Mobile from) - { - int hue = Notoriety.GetHue(NotorietyHandlers.CorpseNotoriety(from, this)); - - from.Send(new AsciiMessage(Serial, ItemID, MessageType.Label, hue, 3, "", "a charred corpse")); - } - - public override void Open(Mobile from, bool checkSelfLoot) - { - if (!from.InRange(GetWorldLocation(), 2)) - return; - - if (from is PlayerMobile player) - { - QuestSystem qs = player.Quest; - - if (qs is WitchApprenticeQuest) - { - FindApprenticeObjective obj = qs.FindObjective(); - if (obj?.Completed == false) - { - if (obj.Corpse == this) - { - obj.Complete(); - Delete(); - } - else - { - SendLocalizedMessageTo(from, - 1055047); // You examine the corpse, but it doesn't fit the description of the particular apprentice the Hag tasked you with finding. - } - - return; - } - } - } - - SendLocalizedMessageTo(from, 1055048); // You examine the corpse, but find nothing of interest. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System.Collections.Generic; +using Server.Items; +using Server.Misc; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.Quests.Hag +{ + public class HagApprenticeCorpse : Corpse + { + [Constructible] + public HagApprenticeCorpse() : base(GetOwner(), GetEquipment()) + { + Direction = Direction.South; + + foreach (var item in EquipItems) + DropItem(item); + } + + public HagApprenticeCorpse(Serial serial) : base(serial) + { + } + + // TODO: What is this? Why are we creating a mobile and deleting it? + private static Mobile GetOwner() + { + var apprentice = new Mobile(); + + apprentice.Hue = Race.Human.RandomSkinHue(); + apprentice.Female = false; + apprentice.Body = 0x190; + + apprentice.Delete(); + + return apprentice; + } + + private static List GetEquipment() => new List(); + + public override void AddNameProperty(ObjectPropertyList list) + { + list.Add("a charred corpse"); + } + + public override void OnSingleClick(Mobile from) + { + var hue = Notoriety.GetHue(NotorietyHandlers.CorpseNotoriety(from, this)); + + from.Send(new AsciiMessage(Serial, ItemID, MessageType.Label, hue, 3, "", "a charred corpse")); + } + + public override void Open(Mobile from, bool checkSelfLoot) + { + if (!from.InRange(GetWorldLocation(), 2)) + return; + + if (from is PlayerMobile player) + { + var qs = player.Quest; + + if (qs is WitchApprenticeQuest) + { + var obj = qs.FindObjective(); + if (obj?.Completed == false) + { + if (obj.Corpse == this) + { + obj.Complete(); + Delete(); + } + else + { + SendLocalizedMessageTo( + from, + 1055047 + ); // You examine the corpse, but it doesn't fit the description of the particular apprentice the Hag tasked you with finding. + } + + return; + } + } + } + + SendLocalizedMessageTo(from, 1055048); // You examine the corpse, but find nothing of interest. + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/HagCauldron.cs b/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/HagCauldron.cs index 058d47fa5..bb1fce1ff 100644 --- a/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/HagCauldron.cs +++ b/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/HagCauldron.cs @@ -1,36 +1,36 @@ -namespace Server.Items -{ - public class HagCauldron : BaseAddon - { - [Constructible] - public HagCauldron() - { - AddonComponent pot; - pot = new AddonComponent(2420); - AddComponent(pot, 0, 0, 0); // pot w/ support - - AddonComponent fire; - fire = new AddonComponent(4012); // fire pit - fire.Light = LightType.Circle150; - AddComponent(fire, 0, 0, 0); - } - - public HagCauldron(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class HagCauldron : BaseAddon + { + [Constructible] + public HagCauldron() + { + AddonComponent pot; + pot = new AddonComponent(2420); + AddComponent(pot, 0, 0, 0); // pot w/ support + + AddonComponent fire; + fire = new AddonComponent(4012); // fire pit + fire.Light = LightType.Circle150; + AddComponent(fire, 0, 0, 0); + } + + public HagCauldron(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/HagStew.cs b/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/HagStew.cs index de5b43bc8..5ca45af4a 100644 --- a/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/HagStew.cs +++ b/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/HagStew.cs @@ -1,73 +1,73 @@ -using System; - -namespace Server.Items -{ - public class HagStew : BaseAddon - { - [Constructible] - public HagStew() - { - AddonComponent stew; - stew = new AddonComponent(2416); - stew.Name = "stew"; - stew.Visible = true; - AddComponent(stew, 0, 0, -7); // stew - } - - public HagStew(Serial serial) : base(serial) - { - } - - public override void OnComponentUsed(AddonComponent stew, Mobile from) - { - if (!from.InRange(GetWorldLocation(), 2)) - { - from.SendMessage("You are too far away."); - } - else - { - stew.Visible = false; - - BreadLoaf hagstew = new BreadLoaf(); // this decides your fillrate - hagstew.Eat(from); - - Timer m_timer = new ShowStew(stew); - m_timer.Start(); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public class ShowStew : Timer - { - private readonly AddonComponent stew; - - public ShowStew(AddonComponent ac) : base(TimeSpan.FromSeconds(30)) - { - stew = ac; - Priority = TimerPriority.OneSecond; - } - - protected override void OnTick() - { - if (stew.Visible == false) - { - Stop(); - stew.Visible = true; - } - } - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class HagStew : BaseAddon + { + [Constructible] + public HagStew() + { + AddonComponent stew; + stew = new AddonComponent(2416); + stew.Name = "stew"; + stew.Visible = true; + AddComponent(stew, 0, 0, -7); // stew + } + + public HagStew(Serial serial) : base(serial) + { + } + + public override void OnComponentUsed(AddonComponent stew, Mobile from) + { + if (!from.InRange(GetWorldLocation(), 2)) + { + from.SendMessage("You are too far away."); + } + else + { + stew.Visible = false; + + var hagstew = new BreadLoaf(); // this decides your fillrate + hagstew.Eat(from); + + Timer m_timer = new ShowStew(stew); + m_timer.Start(); + } + } + + 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 class ShowStew : Timer + { + private readonly AddonComponent stew; + + public ShowStew(AddonComponent ac) : base(TimeSpan.FromSeconds(30)) + { + stew = ac; + Priority = TimerPriority.OneSecond; + } + + protected override void OnTick() + { + if (stew.Visible == false) + { + Stop(); + stew.Visible = true; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/HangoverCure.cs b/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/HangoverCure.cs index 5fcff0340..335a26f90 100644 --- a/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/HangoverCure.cs +++ b/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/HangoverCure.cs @@ -1,81 +1,81 @@ -namespace Server.Engines.Quests.Hag -{ - public class HangoverCure : Item - { - [Constructible] - public HangoverCure() : base(0xE2B) - { - Weight = 1.0; - Hue = 0x2D; - - Uses = 20; - } - - public HangoverCure(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1055060; // Grizelda's Extra Strength Hangover Cure - - [CommandProperty(AccessLevel.GameMaster)] - public int Uses { get; set; } - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - SendLocalizedMessageTo(from, 1042038); // You must have the object in your backpack to use it. - return; - } - - if (Uses > 0) - { - from.PlaySound(0x2D6); - from.SendLocalizedMessage(501206); // An awful taste fills your mouth. - - if (from.BAC > 0) - { - from.BAC = 0; - from.SendLocalizedMessage(501204); // You are now sober! - } - - Uses--; - } - else - { - Delete(); - from.SendLocalizedMessage(501201); // There wasn't enough left to have any effect. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.WriteEncodedInt(Uses); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - Uses = reader.ReadEncodedInt(); - break; - } - case 0: - { - Uses = 20; - break; - } - } - } - } -} \ No newline at end of file +namespace Server.Engines.Quests.Hag +{ + public class HangoverCure : Item + { + [Constructible] + public HangoverCure() : base(0xE2B) + { + Weight = 1.0; + Hue = 0x2D; + + Uses = 20; + } + + public HangoverCure(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1055060; // Grizelda's Extra Strength Hangover Cure + + [CommandProperty(AccessLevel.GameMaster)] + public int Uses { get; set; } + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + SendLocalizedMessageTo(from, 1042038); // You must have the object in your backpack to use it. + return; + } + + if (Uses > 0) + { + from.PlaySound(0x2D6); + from.SendLocalizedMessage(501206); // An awful taste fills your mouth. + + if (from.BAC > 0) + { + from.BAC = 0; + from.SendLocalizedMessage(501204); // You are now sober! + } + + Uses--; + } + else + { + Delete(); + from.SendLocalizedMessage(501201); // There wasn't enough left to have any effect. + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.WriteEncodedInt(Uses); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + Uses = reader.ReadEncodedInt(); + break; + } + case 0: + { + Uses = 20; + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/MagicFlute.cs b/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/MagicFlute.cs index ec29a37b3..dbcb64ce7 100644 --- a/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/MagicFlute.cs +++ b/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/MagicFlute.cs @@ -1,70 +1,72 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Hag -{ - public class MagicFlute : Item - { - [Constructible] - public MagicFlute() : base(0x1421) => Hue = 0x8AB; - - public MagicFlute(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1055051; // magic flute - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - SendLocalizedMessageTo(from, 1042292); // You must have the object in your backpack to use it. - return; - } - - from.PlaySound(0x3D); - - if (from is PlayerMobile player) - { - QuestSystem qs = player.Quest; - - if (qs is WitchApprenticeQuest) - { - FindZeefzorpulObjective obj = qs.FindObjective(); - if (obj?.Completed == false) - { - if ((player.Map != Map.Trammel && player.Map != Map.Felucca) || !player.InRange(obj.ImpLocation, 8)) - { - player.SendLocalizedMessage( - 1055053); // Nothing happens. Zeefzorpul must not be hiding in this area. - } - else if (player.InRange(obj.ImpLocation, 4)) - { - Delete(); - - obj.Complete(); - } - else - { - player.SendLocalizedMessage( - 1055052); // The flute sparkles. Zeefzorpul must be in a good hiding place nearby. - } - } - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Hag +{ + public class MagicFlute : Item + { + [Constructible] + public MagicFlute() : base(0x1421) => Hue = 0x8AB; + + public MagicFlute(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1055051; // magic flute + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + SendLocalizedMessageTo(from, 1042292); // You must have the object in your backpack to use it. + return; + } + + from.PlaySound(0x3D); + + if (from is PlayerMobile player) + { + var qs = player.Quest; + + if (qs is WitchApprenticeQuest) + { + var obj = qs.FindObjective(); + if (obj?.Completed == false) + { + if (player.Map != Map.Trammel && player.Map != Map.Felucca || !player.InRange(obj.ImpLocation, 8)) + { + player.SendLocalizedMessage( + 1055053 + ); // Nothing happens. Zeefzorpul must not be hiding in this area. + } + else if (player.InRange(obj.ImpLocation, 4)) + { + Delete(); + + obj.Complete(); + } + else + { + player.SendLocalizedMessage( + 1055052 + ); // The flute sparkles. Zeefzorpul must be in a good hiding place nearby. + } + } + } + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/MoonfireBrew.cs b/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/MoonfireBrew.cs index f065881d8..11b3f53b5 100644 --- a/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/MoonfireBrew.cs +++ b/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/MoonfireBrew.cs @@ -1,28 +1,28 @@ -namespace Server.Engines.Quests.Hag -{ - public class MoonfireBrew : Item - { - [Constructible] - public MoonfireBrew() : base(0xF04) => Weight = 1.0; - - public MoonfireBrew(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1055065; // a bottle of magical moonfire brew - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Engines.Quests.Hag +{ + public class MoonfireBrew : Item + { + [Constructible] + public MoonfireBrew() : base(0xF04) => Weight = 1.0; + + public MoonfireBrew(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1055065; // a bottle of magical moonfire brew + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Witch Apprentice/Mobiles/Blackheart.cs b/Projects/UOContent/Engines/Quests/Witch Apprentice/Mobiles/Blackheart.cs index 377328672..6be2a30d1 100644 --- a/Projects/UOContent/Engines/Quests/Witch Apprentice/Mobiles/Blackheart.cs +++ b/Projects/UOContent/Engines/Quests/Witch Apprentice/Mobiles/Blackheart.cs @@ -1,116 +1,116 @@ -using System; -using Server.Items; -using Server.Mobiles; -using Server.Network; - -namespace Server.Engines.Quests.Hag -{ - public class Blackheart : BaseQuester - { - [Constructible] - public Blackheart() : base("the Drunken Pirate") - { - } - - public Blackheart(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Captain Blackheart"; - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = 0x83EF; - - Female = false; - Body = 0x190; - } - - public override void InitOutfit() - { - AddItem(new FancyShirt()); - AddItem(new LongPants(0x66D)); - AddItem(new ThighBoots()); - AddItem(new TricorneHat(0x1)); - AddItem(new BodySash(0x66D)); - - LeatherGloves gloves = new LeatherGloves(); - gloves.Hue = 0x66D; - AddItem(gloves); - - FacialHairItemID = 0x203E; // Long Beard - FacialHairHue = 0x455; - - Item sword = new Cutlass(); - sword.Movable = false; - AddItem(sword); - } - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - Direction = GetDirectionTo(player); - Animate(33, 20, 1, true, false, 0); - - QuestSystem qs = player.Quest; - - if (qs is WitchApprenticeQuest) - { - FindIngredientObjective obj = qs.FindObjective(); - if (obj?.Completed == false && obj.Ingredient == Ingredient.Whiskey) - { - PlaySound(Utility.RandomBool() ? 0x42E : 0x43F); - - Item hat = player.FindItemOnLayer(Layer.Helm); - bool tricorne = hat is TricorneHat; - - if (tricorne && player.BAC >= 20) - { - obj.Complete(); - - qs.AddConversation(new BlackheartPirateConversation(!obj.BlackheartMet)); - } - else if (!obj.BlackheartMet) - { - obj.Complete(); - - qs.AddConversation(new BlackheartFirstConversation()); - } - else - { - qs.AddConversation(new BlackheartNoPirateConversation(tricorne, player.BAC > 0)); - } - - return; - } - } - - PlaySound(0x42C); - SayTo(player, 1055041); // The drunken pirate shakes his fist at you and goes back to drinking. - } - - private void Heave() - { - PublicOverheadMessage(MessageType.Regular, 0x3B2, 500849); // *hic* - - Timer.DelayCall(TimeSpan.FromSeconds(Utility.RandomMinMax(60, 180)), Heave); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Heave(); - } - } -} \ No newline at end of file +using System; +using Server.Items; +using Server.Mobiles; +using Server.Network; + +namespace Server.Engines.Quests.Hag +{ + public class Blackheart : BaseQuester + { + [Constructible] + public Blackheart() : base("the Drunken Pirate") + { + } + + public Blackheart(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Captain Blackheart"; + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = 0x83EF; + + Female = false; + Body = 0x190; + } + + public override void InitOutfit() + { + AddItem(new FancyShirt()); + AddItem(new LongPants(0x66D)); + AddItem(new ThighBoots()); + AddItem(new TricorneHat(0x1)); + AddItem(new BodySash(0x66D)); + + var gloves = new LeatherGloves(); + gloves.Hue = 0x66D; + AddItem(gloves); + + FacialHairItemID = 0x203E; // Long Beard + FacialHairHue = 0x455; + + Item sword = new Cutlass(); + sword.Movable = false; + AddItem(sword); + } + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + Direction = GetDirectionTo(player); + Animate(33, 20, 1, true, false, 0); + + var qs = player.Quest; + + if (qs is WitchApprenticeQuest) + { + var obj = qs.FindObjective(); + if (obj?.Completed == false && obj.Ingredient == Ingredient.Whiskey) + { + PlaySound(Utility.RandomBool() ? 0x42E : 0x43F); + + var hat = player.FindItemOnLayer(Layer.Helm); + var tricorne = hat is TricorneHat; + + if (tricorne && player.BAC >= 20) + { + obj.Complete(); + + qs.AddConversation(new BlackheartPirateConversation(!obj.BlackheartMet)); + } + else if (!obj.BlackheartMet) + { + obj.Complete(); + + qs.AddConversation(new BlackheartFirstConversation()); + } + else + { + qs.AddConversation(new BlackheartNoPirateConversation(tricorne, player.BAC > 0)); + } + + return; + } + } + + PlaySound(0x42C); + SayTo(player, 1055041); // The drunken pirate shakes his fist at you and goes back to drinking. + } + + private void Heave() + { + PublicOverheadMessage(MessageType.Regular, 0x3B2, 500849); // *hic* + + Timer.DelayCall(TimeSpan.FromSeconds(Utility.RandomMinMax(60, 180)), Heave); + } + + 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(); + + Heave(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Witch Apprentice/Mobiles/Grizelda.cs b/Projects/UOContent/Engines/Quests/Witch Apprentice/Mobiles/Grizelda.cs index 3b0ba89a4..fc721a261 100644 --- a/Projects/UOContent/Engines/Quests/Witch Apprentice/Mobiles/Grizelda.cs +++ b/Projects/UOContent/Engines/Quests/Witch Apprentice/Mobiles/Grizelda.cs @@ -1,217 +1,223 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Hag -{ - public class Grizelda : BaseQuester - { - [Constructible] - public Grizelda() : base("the Hag") - { - } - - public Grizelda(Serial serial) : base(serial) - { - } - - public override bool ClickTitle => true; - public override string DefaultName => "Grizelda"; - - public override void InitBody() - { - InitStats(100, 100, 25); - - Hue = 0x83EA; - - Female = true; - Body = 0x191; - } - - public override void InitOutfit() - { - AddItem(new Robe(0x1)); - AddItem(new Sandals()); - AddItem(new WizardsHat(0x1)); - AddItem(new GoldBracelet()); - - HairItemID = 0x203C; - - Item staff = new GnarledStaff(); - staff.Movable = false; - AddItem(staff); - } - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - Direction = GetDirectionTo(player); - - QuestSystem qs = player.Quest; - - if (qs is WitchApprenticeQuest) - { - if (qs.IsObjectiveInProgress(typeof(FindApprenticeObjective))) - { - PlaySound(0x259); - PlaySound(0x206); - qs.AddConversation(new HagDuringCorpseSearchConversation()); - } - else - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - PlaySound(0x420); - PlaySound(0x20); - obj.Complete(); - } - else if (qs.IsObjectiveInProgress(typeof(KillImpsObjective)) - || qs.IsObjectiveInProgress(typeof(FindZeefzorpulObjective))) - { - PlaySound(0x259); - PlaySound(0x206); - qs.AddConversation(new HagDuringImpSearchConversation()); - } - else - { - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - PlaySound(0x258); - PlaySound(0x41B); - obj.Complete(); - } - else if (qs.IsObjectiveInProgress(typeof(FindIngredientObjective))) - { - PlaySound(0x259); - PlaySound(0x206); - qs.AddConversation(new HagDuringIngredientsConversation()); - } - else - { - obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - Container cont = GetNewContainer(); - - cont.DropItem(new BlackPearl(30)); - cont.DropItem(new Bloodmoss(30)); - cont.DropItem(new Garlic(30)); - cont.DropItem(new Ginseng(30)); - cont.DropItem(new MandrakeRoot(30)); - cont.DropItem(new Nightshade(30)); - cont.DropItem(new SulfurousAsh(30)); - cont.DropItem(new SpidersSilk(30)); - - cont.DropItem(new Cauldron()); - cont.DropItem(new MoonfireBrew()); - cont.DropItem(new TreasureMap(Utility.RandomMinMax(1, 4), Map)); - cont.DropItem(new Gold(2000, 2200)); - - if (Utility.RandomBool()) - { - BaseWeapon weapon = Loot.RandomWeapon(); - - if (Core.AOS) - { - BaseRunicTool.ApplyAttributesTo(weapon, 2, 20, 30); - } - else - { - weapon.DamageLevel = (WeaponDamageLevel)RandomMinMaxScaled(2, 3); - weapon.AccuracyLevel = (WeaponAccuracyLevel)RandomMinMaxScaled(2, 3); - weapon.DurabilityLevel = (WeaponDurabilityLevel)RandomMinMaxScaled(2, 3); - } - - cont.DropItem(weapon); - } - else - { - Item item; - - if (Core.AOS) - { - item = Loot.RandomArmorOrShieldOrJewelry(); - - if (item is BaseArmor armor) - BaseRunicTool.ApplyAttributesTo(armor, 2, 20, 30); - else if (item is BaseJewel jewel) - BaseRunicTool.ApplyAttributesTo(jewel, 2, 20, 30); - } - else - { - BaseArmor armor = Loot.RandomArmorOrShield(); - item = armor; - - armor.ProtectionLevel = (ArmorProtectionLevel)RandomMinMaxScaled(2, 3); - armor.Durability = (ArmorDurabilityLevel)RandomMinMaxScaled(2, 3); - } - - cont.DropItem(item); - } - - if (player.BAC > 0) - cont.DropItem(new HangoverCure()); - - if (player.PlaceInBackpack(cont)) - { - bool gainedPath = false; - - if (VirtueHelper.Award(player, VirtueName.Sacrifice, 250, ref gainedPath)) // TODO: Check amount on OSI. - player.SendLocalizedMessage(1054160); // You have gained in sacrifice. - - PlaySound(0x253); - PlaySound(0x20); - obj.Complete(); - } - else - { - cont.Delete(); - player.SendLocalizedMessage( - 1046260); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. - } - } - } - } - } - } - else - { - QuestSystem newQuest = new WitchApprenticeQuest(player); - - if (qs != null) - { - newQuest.AddConversation(new DontOfferConversation()); - } - else if (QuestSystem.CanOfferQuest(player, typeof(WitchApprenticeQuest), out bool inRestartPeriod)) - { - PlaySound(0x20); - PlaySound(0x206); - newQuest.SendOffer(); - } - else if (inRestartPeriod) - { - PlaySound(0x259); - PlaySound(0x206); - newQuest.AddConversation(new RecentlyFinishedConversation()); - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Hag +{ + public class Grizelda : BaseQuester + { + [Constructible] + public Grizelda() : base("the Hag") + { + } + + public Grizelda(Serial serial) : base(serial) + { + } + + public override bool ClickTitle => true; + public override string DefaultName => "Grizelda"; + + public override void InitBody() + { + InitStats(100, 100, 25); + + Hue = 0x83EA; + + Female = true; + Body = 0x191; + } + + public override void InitOutfit() + { + AddItem(new Robe(0x1)); + AddItem(new Sandals()); + AddItem(new WizardsHat(0x1)); + AddItem(new GoldBracelet()); + + HairItemID = 0x203C; + + Item staff = new GnarledStaff(); + staff.Movable = false; + AddItem(staff); + } + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + Direction = GetDirectionTo(player); + + var qs = player.Quest; + + if (qs is WitchApprenticeQuest) + { + if (qs.IsObjectiveInProgress(typeof(FindApprenticeObjective))) + { + PlaySound(0x259); + PlaySound(0x206); + qs.AddConversation(new HagDuringCorpseSearchConversation()); + } + else + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + PlaySound(0x420); + PlaySound(0x20); + obj.Complete(); + } + else if (qs.IsObjectiveInProgress(typeof(KillImpsObjective)) + || qs.IsObjectiveInProgress(typeof(FindZeefzorpulObjective))) + { + PlaySound(0x259); + PlaySound(0x206); + qs.AddConversation(new HagDuringImpSearchConversation()); + } + else + { + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + PlaySound(0x258); + PlaySound(0x41B); + obj.Complete(); + } + else if (qs.IsObjectiveInProgress(typeof(FindIngredientObjective))) + { + PlaySound(0x259); + PlaySound(0x206); + qs.AddConversation(new HagDuringIngredientsConversation()); + } + else + { + obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + var cont = GetNewContainer(); + + cont.DropItem(new BlackPearl(30)); + cont.DropItem(new Bloodmoss(30)); + cont.DropItem(new Garlic(30)); + cont.DropItem(new Ginseng(30)); + cont.DropItem(new MandrakeRoot(30)); + cont.DropItem(new Nightshade(30)); + cont.DropItem(new SulfurousAsh(30)); + cont.DropItem(new SpidersSilk(30)); + + cont.DropItem(new Cauldron()); + cont.DropItem(new MoonfireBrew()); + cont.DropItem(new TreasureMap(Utility.RandomMinMax(1, 4), Map)); + cont.DropItem(new Gold(2000, 2200)); + + if (Utility.RandomBool()) + { + var weapon = Loot.RandomWeapon(); + + if (Core.AOS) + { + BaseRunicTool.ApplyAttributesTo(weapon, 2, 20, 30); + } + else + { + weapon.DamageLevel = (WeaponDamageLevel)RandomMinMaxScaled(2, 3); + weapon.AccuracyLevel = (WeaponAccuracyLevel)RandomMinMaxScaled(2, 3); + weapon.DurabilityLevel = (WeaponDurabilityLevel)RandomMinMaxScaled(2, 3); + } + + cont.DropItem(weapon); + } + else + { + Item item; + + if (Core.AOS) + { + item = Loot.RandomArmorOrShieldOrJewelry(); + + if (item is BaseArmor armor) + BaseRunicTool.ApplyAttributesTo(armor, 2, 20, 30); + else if (item is BaseJewel jewel) + BaseRunicTool.ApplyAttributesTo(jewel, 2, 20, 30); + } + else + { + var armor = Loot.RandomArmorOrShield(); + item = armor; + + armor.ProtectionLevel = (ArmorProtectionLevel)RandomMinMaxScaled(2, 3); + armor.Durability = (ArmorDurabilityLevel)RandomMinMaxScaled(2, 3); + } + + cont.DropItem(item); + } + + if (player.BAC > 0) + cont.DropItem(new HangoverCure()); + + if (player.PlaceInBackpack(cont)) + { + var gainedPath = false; + + if (VirtueHelper.Award( + player, + VirtueName.Sacrifice, + 250, + ref gainedPath + )) // TODO: Check amount on OSI. + player.SendLocalizedMessage(1054160); // You have gained in sacrifice. + + PlaySound(0x253); + PlaySound(0x20); + obj.Complete(); + } + else + { + cont.Delete(); + player.SendLocalizedMessage( + 1046260 + ); // You need to clear some space in your inventory to continue with the quest. Come back here when you have more space in your inventory. + } + } + } + } + } + } + else + { + QuestSystem newQuest = new WitchApprenticeQuest(player); + + if (qs != null) + { + newQuest.AddConversation(new DontOfferConversation()); + } + else if (QuestSystem.CanOfferQuest(player, typeof(WitchApprenticeQuest), out var inRestartPeriod)) + { + PlaySound(0x20); + PlaySound(0x206); + newQuest.SendOffer(); + } + else if (inRestartPeriod) + { + PlaySound(0x259); + PlaySound(0x206); + newQuest.AddConversation(new RecentlyFinishedConversation()); + } + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Witch Apprentice/Mobiles/Zeefzorpul.cs b/Projects/UOContent/Engines/Quests/Witch Apprentice/Mobiles/Zeefzorpul.cs index 17cbca6d8..cfed4c031 100644 --- a/Projects/UOContent/Engines/Quests/Witch Apprentice/Mobiles/Zeefzorpul.cs +++ b/Projects/UOContent/Engines/Quests/Witch Apprentice/Mobiles/Zeefzorpul.cs @@ -1,44 +1,44 @@ -using Server.Mobiles; - -namespace Server.Engines.Quests.Hag -{ - public class Zeefzorpul : BaseQuester - { - public Zeefzorpul() - { - } - - public Zeefzorpul(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Zeefzorpul"; - - public override void InitBody() - { - Body = 0x4A; - } - - public override bool CanTalkTo(PlayerMobile to) => false; - - public override void OnTalk(PlayerMobile player, bool contextMenu) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Delete(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Engines.Quests.Hag +{ + public class Zeefzorpul : BaseQuester + { + public Zeefzorpul() + { + } + + public Zeefzorpul(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Zeefzorpul"; + + public override void InitBody() + { + Body = 0x4A; + } + + public override bool CanTalkTo(PlayerMobile to) => false; + + public override void OnTalk(PlayerMobile player, bool contextMenu) + { + } + + 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(); + + Delete(); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Witch Apprentice/Objectives.cs b/Projects/UOContent/Engines/Quests/Witch Apprentice/Objectives.cs index d4ed6ad1d..00e17d60d 100644 --- a/Projects/UOContent/Engines/Quests/Witch Apprentice/Objectives.cs +++ b/Projects/UOContent/Engines/Quests/Witch Apprentice/Objectives.cs @@ -1,426 +1,429 @@ -using System; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Quests.Hag -{ - public class FindApprenticeObjective : QuestObjective - { - private static readonly Point3D[] m_CorpseLocations = - { - new Point3D(778, 1158, 0), - new Point3D(698, 1443, 0), - new Point3D(785, 1548, 0), - new Point3D(734, 1504, 0), - new Point3D(819, 1266, 0) - }; - - private Point3D m_CorpseLocation; - - public FindApprenticeObjective(bool init) - { - if (init) - m_CorpseLocation = RandomCorpseLocation(); - } - - public FindApprenticeObjective() - { - } - - public override object Message => 1055014; - - public Corpse Corpse { get; private set; } - - private static Point3D RandomCorpseLocation() => m_CorpseLocations.RandomElement(); - - public override void CheckProgress() - { - PlayerMobile player = System.From; - Map map = player.Map; - - if (Corpse?.Deleted == false || (map != Map.Trammel && map != Map.Felucca) || - !player.InRange(m_CorpseLocation, 8)) - return; - - Corpse = new HagApprenticeCorpse(); - Corpse.MoveToWorld(m_CorpseLocation, map); - - Effects.SendLocationEffect(m_CorpseLocation, map, 0x3728, 10, 10); - Effects.PlaySound(m_CorpseLocation, map, 0x1FE); - - Mobile imp = new Zeefzorpul(); - imp.MoveToWorld(m_CorpseLocation, map); - - // * You see a strange imp stealing a scrap of paper from the bloodied corpse * - Corpse.SendLocalizedMessageTo(player, 1055049); - - Timer.DelayCall(TimeSpan.FromSeconds(3.0), DeleteImp, imp); - } - - private void DeleteImp(Mobile m) - { - if (m?.Deleted == false) - { - Effects.SendLocationEffect(m.Location, m.Map, 0x3728, 10, 10); - Effects.PlaySound(m.Location, m.Map, 0x1FE); - - m.Delete(); - } - } - - public override void OnComplete() - { - System.AddConversation(new ApprenticeCorpseConversation()); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 1: - { - m_CorpseLocation = reader.ReadPoint3D(); - goto case 0; - } - case 0: - { - Corpse = (Corpse)reader.ReadItem(); - break; - } - } - - if (version == 0) - m_CorpseLocation = RandomCorpseLocation(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - if (Corpse?.Deleted == true) - Corpse = null; - - writer.WriteEncodedInt(1); // version - - writer.Write(m_CorpseLocation); - writer.Write(Corpse); - } - } - - public class FindGrizeldaAboutMurderObjective : QuestObjective - { - public override object Message => 1055015; - - public override void OnComplete() - { - System.AddConversation(new MurderConversation()); - } - } - - public class KillImpsObjective : QuestObjective - { - private int m_MaxProgress; - - public KillImpsObjective(bool init) - { - if (init) - m_MaxProgress = Utility.RandomMinMax(1, 4); - } - - public KillImpsObjective() - { - } - - public override object Message => 1055016; - - public override int MaxProgress => m_MaxProgress; - - public override bool IgnoreYoungProtection(Mobile from) - { - if (!Completed && from is Imp) - return true; - - return false; - } - - public override void OnKill(BaseCreature creature, Container corpse) - { - if (creature is Imp) - CurProgress++; - } - - public override void OnComplete() - { - PlayerMobile from = System.From; - - Point3D loc = WitchApprenticeQuest.RandomZeefzorpulLocation(); - - MapItem mapItem = new MapItem(); - mapItem.SetDisplay(loc.X - 200, loc.Y - 200, loc.X + 200, loc.Y + 200, 200, 200); - mapItem.AddWorldPin(loc.X, loc.Y); - from.AddToBackpack(mapItem); - - from.AddToBackpack(new MagicFlute()); - - from.SendLocalizedMessage(1055061); // You have received a map and a magic flute. - - System.AddConversation(new ImpDeathConversation(loc)); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - m_MaxProgress = reader.ReadInt(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(m_MaxProgress); - } - } - - public class FindZeefzorpulObjective : QuestObjective - { - public FindZeefzorpulObjective(Point3D impLocation) => ImpLocation = impLocation; - - public FindZeefzorpulObjective() - { - } - - public override object Message => 1055017; - - public Point3D ImpLocation { get; private set; } - - public override void OnComplete() - { - Mobile from = System.From; - Map map = from.Map; - - Effects.SendLocationEffect(ImpLocation, map, 0x3728, 10, 10); - Effects.PlaySound(ImpLocation, map, 0x1FE); - - Mobile imp = new Zeefzorpul(); - imp.MoveToWorld(ImpLocation, map); - - imp.Direction = imp.GetDirectionTo(from); - - Timer.DelayCall(TimeSpan.FromSeconds(3.0), DeleteImp, imp); - } - - private void DeleteImp(object imp) - { - if (imp is Mobile m && !m.Deleted) - { - Effects.SendLocationEffect(m.Location, m.Map, 0x3728, 10, 10); - Effects.PlaySound(m.Location, m.Map, 0x1FE); - - m.Delete(); - } - - System.From.SendLocalizedMessage(1055062); // You have received the Magic Brew Recipe. - - System.AddConversation(new ZeefzorpulConversation()); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - ImpLocation = reader.ReadPoint3D(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(ImpLocation); - } - } - - public class ReturnRecipeObjective : QuestObjective - { - public override object Message => 1055018; - - public override void OnComplete() - { - System.AddConversation(new RecipeConversation()); - } - } - - public class FindIngredientObjective : QuestObjective - { - public FindIngredientObjective(Ingredient[] oldIngredients, bool blackheartMet = false) - { - if (!blackheartMet) - { - Ingredients = new Ingredient[oldIngredients.Length + 1]; - - for (int i = 0; i < oldIngredients.Length; i++) - Ingredients[i] = oldIngredients[i]; - - Ingredients[^1] = IngredientInfo.RandomIngredient(oldIngredients); - } - else - { - Ingredients = new Ingredient[oldIngredients.Length]; - - for (int i = 0; i < oldIngredients.Length; i++) - Ingredients[i] = oldIngredients[i]; - } - - BlackheartMet = blackheartMet; - } - - public FindIngredientObjective() - { - } - - public override object Message - { - get - { - if (!BlackheartMet) - return Step switch - { - 1 => - /* You must gather each ingredient on the Hag's list so that she can cook - * up her vile Magic Brew. The first ingredient is : - */ - 1055019, - 2 => - /* You must gather each ingredient on the Hag's list so that she can cook - * up her vile Magic Brew. The second ingredient is : - */ - 1055044, - _ => 1055045 - }; - - /* You are still attempting to obtain a jug of Captain Blackheart's - * Whiskey, but the drunkard Captain refuses to share his unique brew. - * You must prove your worthiness as a pirate to Blackheart before he'll - * offer you a jug. - */ - return 1055055; - } - } - - public override int MaxProgress - { - get - { - IngredientInfo info = IngredientInfo.Get(Ingredient); - - return info.Quantity; - } - } - - public Ingredient[] Ingredients { get; private set; } - - public Ingredient Ingredient => Ingredients[^1]; - public int Step => Ingredients.Length; - public bool BlackheartMet { get; private set; } - - public override void RenderProgress(BaseQuestGump gump) - { - if (!Completed) - { - IngredientInfo info = IngredientInfo.Get(Ingredient); - - gump.AddHtmlLocalized(70, 260, 270, 100, info.Name, BaseQuestGump.Blue); - gump.AddLabel(70, 280, 0x64, CurProgress.ToString()); - gump.AddLabel(100, 280, 0x64, "/"); - gump.AddLabel(130, 280, 0x64, info.Quantity.ToString()); - } - else - { - base.RenderProgress(gump); - } - } - - public override bool IgnoreYoungProtection(Mobile from) - { - if (Completed) - return false; - - IngredientInfo info = IngredientInfo.Get(Ingredient); - Type fromType = from.GetType(); - - for (int i = 0; i < info.Creatures.Length; i++) - if (fromType == info.Creatures[i]) - return true; - - return false; - } - - public override void OnKill(BaseCreature creature, Container corpse) - { - IngredientInfo info = IngredientInfo.Get(Ingredient); - - for (int i = 0; i < info.Creatures.Length; i++) - { - Type type = info.Creatures[i]; - - if (creature.GetType() == type) - { - System.From.SendLocalizedMessage(1055043, - $"#{info.Name}"); // You gather a ~1_INGREDIENT_NAME~ from the corpse. - - CurProgress++; - - break; - } - } - } - - public override void OnComplete() - { - if (Ingredient != Ingredient.Whiskey) NextStep(); - } - - public void NextStep() - { - System.From.SendLocalizedMessage( - 1055046); // You have completed your current task on the Hag's Magic Brew Recipe list. - - if (Step < 3) - System.AddObjective(new FindIngredientObjective(Ingredients)); - else - System.AddObjective(new ReturnIngredientsObjective()); - } - - public override void ChildDeserialize(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - Ingredients = new Ingredient[reader.ReadEncodedInt()]; - for (int i = 0; i < Ingredients.Length; i++) - Ingredients[i] = (Ingredient)reader.ReadEncodedInt(); - - BlackheartMet = reader.ReadBool(); - } - - public override void ChildSerialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.WriteEncodedInt(Ingredients.Length); - for (int i = 0; i < Ingredients.Length; i++) - writer.WriteEncodedInt((int)Ingredients[i]); - - writer.Write(BlackheartMet); - } - } - - public class ReturnIngredientsObjective : QuestObjective - { - public override object Message => 1055050; - - public override void OnComplete() - { - System.AddConversation(new EndConversation()); - } - } -} +using System; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Quests.Hag +{ + public class FindApprenticeObjective : QuestObjective + { + private static readonly Point3D[] m_CorpseLocations = + { + new Point3D(778, 1158, 0), + new Point3D(698, 1443, 0), + new Point3D(785, 1548, 0), + new Point3D(734, 1504, 0), + new Point3D(819, 1266, 0) + }; + + private Point3D m_CorpseLocation; + + public FindApprenticeObjective(bool init) + { + if (init) + m_CorpseLocation = RandomCorpseLocation(); + } + + public FindApprenticeObjective() + { + } + + public override object Message => 1055014; + + public Corpse Corpse { get; private set; } + + private static Point3D RandomCorpseLocation() => m_CorpseLocations.RandomElement(); + + public override void CheckProgress() + { + var player = System.From; + var map = player.Map; + + if (Corpse?.Deleted == false || map != Map.Trammel && map != Map.Felucca || + !player.InRange(m_CorpseLocation, 8)) + return; + + Corpse = new HagApprenticeCorpse(); + Corpse.MoveToWorld(m_CorpseLocation, map); + + Effects.SendLocationEffect(m_CorpseLocation, map, 0x3728, 10, 10); + Effects.PlaySound(m_CorpseLocation, map, 0x1FE); + + Mobile imp = new Zeefzorpul(); + imp.MoveToWorld(m_CorpseLocation, map); + + // * You see a strange imp stealing a scrap of paper from the bloodied corpse * + Corpse.SendLocalizedMessageTo(player, 1055049); + + Timer.DelayCall(TimeSpan.FromSeconds(3.0), DeleteImp, imp); + } + + private void DeleteImp(Mobile m) + { + if (m?.Deleted == false) + { + Effects.SendLocationEffect(m.Location, m.Map, 0x3728, 10, 10); + Effects.PlaySound(m.Location, m.Map, 0x1FE); + + m.Delete(); + } + } + + public override void OnComplete() + { + System.AddConversation(new ApprenticeCorpseConversation()); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 1: + { + m_CorpseLocation = reader.ReadPoint3D(); + goto case 0; + } + case 0: + { + Corpse = (Corpse)reader.ReadItem(); + break; + } + } + + if (version == 0) + m_CorpseLocation = RandomCorpseLocation(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + if (Corpse?.Deleted == true) + Corpse = null; + + writer.WriteEncodedInt(1); // version + + writer.Write(m_CorpseLocation); + writer.Write(Corpse); + } + } + + public class FindGrizeldaAboutMurderObjective : QuestObjective + { + public override object Message => 1055015; + + public override void OnComplete() + { + System.AddConversation(new MurderConversation()); + } + } + + public class KillImpsObjective : QuestObjective + { + private int m_MaxProgress; + + public KillImpsObjective(bool init) + { + if (init) + m_MaxProgress = Utility.RandomMinMax(1, 4); + } + + public KillImpsObjective() + { + } + + public override object Message => 1055016; + + public override int MaxProgress => m_MaxProgress; + + public override bool IgnoreYoungProtection(Mobile from) + { + if (!Completed && from is Imp) + return true; + + return false; + } + + public override void OnKill(BaseCreature creature, Container corpse) + { + if (creature is Imp) + CurProgress++; + } + + public override void OnComplete() + { + var from = System.From; + + var loc = WitchApprenticeQuest.RandomZeefzorpulLocation(); + + var mapItem = new MapItem(); + mapItem.SetDisplay(loc.X - 200, loc.Y - 200, loc.X + 200, loc.Y + 200, 200, 200); + mapItem.AddWorldPin(loc.X, loc.Y); + from.AddToBackpack(mapItem); + + from.AddToBackpack(new MagicFlute()); + + from.SendLocalizedMessage(1055061); // You have received a map and a magic flute. + + System.AddConversation(new ImpDeathConversation(loc)); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + m_MaxProgress = reader.ReadInt(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(m_MaxProgress); + } + } + + public class FindZeefzorpulObjective : QuestObjective + { + public FindZeefzorpulObjective(Point3D impLocation) => ImpLocation = impLocation; + + public FindZeefzorpulObjective() + { + } + + public override object Message => 1055017; + + public Point3D ImpLocation { get; private set; } + + public override void OnComplete() + { + Mobile from = System.From; + var map = from.Map; + + Effects.SendLocationEffect(ImpLocation, map, 0x3728, 10, 10); + Effects.PlaySound(ImpLocation, map, 0x1FE); + + Mobile imp = new Zeefzorpul(); + imp.MoveToWorld(ImpLocation, map); + + imp.Direction = imp.GetDirectionTo(from); + + Timer.DelayCall(TimeSpan.FromSeconds(3.0), DeleteImp, imp); + } + + private void DeleteImp(object imp) + { + if (imp is Mobile m && !m.Deleted) + { + Effects.SendLocationEffect(m.Location, m.Map, 0x3728, 10, 10); + Effects.PlaySound(m.Location, m.Map, 0x1FE); + + m.Delete(); + } + + System.From.SendLocalizedMessage(1055062); // You have received the Magic Brew Recipe. + + System.AddConversation(new ZeefzorpulConversation()); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + ImpLocation = reader.ReadPoint3D(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(ImpLocation); + } + } + + public class ReturnRecipeObjective : QuestObjective + { + public override object Message => 1055018; + + public override void OnComplete() + { + System.AddConversation(new RecipeConversation()); + } + } + + public class FindIngredientObjective : QuestObjective + { + public FindIngredientObjective(Ingredient[] oldIngredients, bool blackheartMet = false) + { + if (!blackheartMet) + { + Ingredients = new Ingredient[oldIngredients.Length + 1]; + + for (var i = 0; i < oldIngredients.Length; i++) + Ingredients[i] = oldIngredients[i]; + + Ingredients[^1] = IngredientInfo.RandomIngredient(oldIngredients); + } + else + { + Ingredients = new Ingredient[oldIngredients.Length]; + + for (var i = 0; i < oldIngredients.Length; i++) + Ingredients[i] = oldIngredients[i]; + } + + BlackheartMet = blackheartMet; + } + + public FindIngredientObjective() + { + } + + public override object Message + { + get + { + if (!BlackheartMet) + return Step switch + { + 1 => + /* You must gather each ingredient on the Hag's list so that she can cook + * up her vile Magic Brew. The first ingredient is : + */ + 1055019, + 2 => + /* You must gather each ingredient on the Hag's list so that she can cook + * up her vile Magic Brew. The second ingredient is : + */ + 1055044, + _ => 1055045 + }; + + /* You are still attempting to obtain a jug of Captain Blackheart's + * Whiskey, but the drunkard Captain refuses to share his unique brew. + * You must prove your worthiness as a pirate to Blackheart before he'll + * offer you a jug. + */ + return 1055055; + } + } + + public override int MaxProgress + { + get + { + var info = IngredientInfo.Get(Ingredient); + + return info.Quantity; + } + } + + public Ingredient[] Ingredients { get; private set; } + + public Ingredient Ingredient => Ingredients[^1]; + public int Step => Ingredients.Length; + public bool BlackheartMet { get; private set; } + + public override void RenderProgress(BaseQuestGump gump) + { + if (!Completed) + { + var info = IngredientInfo.Get(Ingredient); + + gump.AddHtmlLocalized(70, 260, 270, 100, info.Name, BaseQuestGump.Blue); + gump.AddLabel(70, 280, 0x64, CurProgress.ToString()); + gump.AddLabel(100, 280, 0x64, "/"); + gump.AddLabel(130, 280, 0x64, info.Quantity.ToString()); + } + else + { + base.RenderProgress(gump); + } + } + + public override bool IgnoreYoungProtection(Mobile from) + { + if (Completed) + return false; + + var info = IngredientInfo.Get(Ingredient); + var fromType = from.GetType(); + + for (var i = 0; i < info.Creatures.Length; i++) + if (fromType == info.Creatures[i]) + return true; + + return false; + } + + public override void OnKill(BaseCreature creature, Container corpse) + { + var info = IngredientInfo.Get(Ingredient); + + for (var i = 0; i < info.Creatures.Length; i++) + { + var type = info.Creatures[i]; + + if (creature.GetType() == type) + { + System.From.SendLocalizedMessage( + 1055043, + $"#{info.Name}" + ); // You gather a ~1_INGREDIENT_NAME~ from the corpse. + + CurProgress++; + + break; + } + } + } + + public override void OnComplete() + { + if (Ingredient != Ingredient.Whiskey) NextStep(); + } + + public void NextStep() + { + System.From.SendLocalizedMessage( + 1055046 + ); // You have completed your current task on the Hag's Magic Brew Recipe list. + + if (Step < 3) + System.AddObjective(new FindIngredientObjective(Ingredients)); + else + System.AddObjective(new ReturnIngredientsObjective()); + } + + public override void ChildDeserialize(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + Ingredients = new Ingredient[reader.ReadEncodedInt()]; + for (var i = 0; i < Ingredients.Length; i++) + Ingredients[i] = (Ingredient)reader.ReadEncodedInt(); + + BlackheartMet = reader.ReadBool(); + } + + public override void ChildSerialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.WriteEncodedInt(Ingredients.Length); + for (var i = 0; i < Ingredients.Length; i++) + writer.WriteEncodedInt((int)Ingredients[i]); + + writer.Write(BlackheartMet); + } + } + + public class ReturnIngredientsObjective : QuestObjective + { + public override object Message => 1055050; + + public override void OnComplete() + { + System.AddConversation(new EndConversation()); + } + } +} diff --git a/Projects/UOContent/Engines/Quests/Witch Apprentice/WitchApprenticeQuest.cs b/Projects/UOContent/Engines/Quests/Witch Apprentice/WitchApprenticeQuest.cs index 45555f516..4077c9860 100644 --- a/Projects/UOContent/Engines/Quests/Witch Apprentice/WitchApprenticeQuest.cs +++ b/Projects/UOContent/Engines/Quests/Witch Apprentice/WitchApprenticeQuest.cs @@ -1,87 +1,87 @@ -using System; -using Server.Mobiles; - -namespace Server.Engines.Quests.Hag -{ - public class WitchApprenticeQuest : QuestSystem - { - private static readonly Type[] m_TypeReferenceTable = - { - typeof(FindApprenticeObjective), - typeof(FindGrizeldaAboutMurderObjective), - typeof(KillImpsObjective), - typeof(FindZeefzorpulObjective), - typeof(ReturnRecipeObjective), - typeof(FindIngredientObjective), - typeof(ReturnIngredientsObjective), - typeof(DontOfferConversation), - typeof(AcceptConversation), - typeof(HagDuringCorpseSearchConversation), - typeof(ApprenticeCorpseConversation), - typeof(MurderConversation), - typeof(HagDuringImpSearchConversation), - typeof(ImpDeathConversation), - typeof(ZeefzorpulConversation), - typeof(RecipeConversation), - typeof(HagDuringIngredientsConversation), - typeof(BlackheartFirstConversation), - typeof(BlackheartNoPirateConversation), - typeof(BlackheartPirateConversation), - typeof(EndConversation), - typeof(RecentlyFinishedConversation) - }; - - private static readonly Point3D[] m_ZeefzorpulLocations = - { - new Point3D(1226, 1573, 0), - new Point3D(1929, 1148, 0), - new Point3D(1366, 2723, 0), - new Point3D(1675, 2984, 0), - new Point3D(2177, 3367, 10), - new Point3D(1171, 3594, 0), - new Point3D(1010, 2667, 5), - new Point3D(1591, 2156, 5), - new Point3D(2592, 464, 60), - new Point3D(474, 1654, 0), - new Point3D(897, 2411, 0), - new Point3D(1471, 2505, 5), - new Point3D(1257, 872, 16), - new Point3D(2581, 1118, 0), - new Point3D(2513, 1102, 0), - new Point3D(1608, 3371, 0), - new Point3D(4687, 1179, 0), - new Point3D(3704, 2196, 20), - new Point3D(3346, 572, 0), - new Point3D(569, 1309, 0) - }; - - public WitchApprenticeQuest(PlayerMobile from) : base(from) - { - } - - // Serialization - public WitchApprenticeQuest() - { - } - - public override Type[] TypeReferenceTable => m_TypeReferenceTable; - - public override object Name => 1055042; - - public override object OfferMessage => 1055001; - - public override TimeSpan RestartDelay => TimeSpan.FromMinutes(5.0); - public override bool IsTutorial => false; - - public override int Picture => 0x15D3; - - public override void Accept() - { - base.Accept(); - - AddConversation(new AcceptConversation()); - } - - public static Point3D RandomZeefzorpulLocation() => m_ZeefzorpulLocations.RandomElement(); - } -} +using System; +using Server.Mobiles; + +namespace Server.Engines.Quests.Hag +{ + public class WitchApprenticeQuest : QuestSystem + { + private static readonly Type[] m_TypeReferenceTable = + { + typeof(FindApprenticeObjective), + typeof(FindGrizeldaAboutMurderObjective), + typeof(KillImpsObjective), + typeof(FindZeefzorpulObjective), + typeof(ReturnRecipeObjective), + typeof(FindIngredientObjective), + typeof(ReturnIngredientsObjective), + typeof(DontOfferConversation), + typeof(AcceptConversation), + typeof(HagDuringCorpseSearchConversation), + typeof(ApprenticeCorpseConversation), + typeof(MurderConversation), + typeof(HagDuringImpSearchConversation), + typeof(ImpDeathConversation), + typeof(ZeefzorpulConversation), + typeof(RecipeConversation), + typeof(HagDuringIngredientsConversation), + typeof(BlackheartFirstConversation), + typeof(BlackheartNoPirateConversation), + typeof(BlackheartPirateConversation), + typeof(EndConversation), + typeof(RecentlyFinishedConversation) + }; + + private static readonly Point3D[] m_ZeefzorpulLocations = + { + new Point3D(1226, 1573, 0), + new Point3D(1929, 1148, 0), + new Point3D(1366, 2723, 0), + new Point3D(1675, 2984, 0), + new Point3D(2177, 3367, 10), + new Point3D(1171, 3594, 0), + new Point3D(1010, 2667, 5), + new Point3D(1591, 2156, 5), + new Point3D(2592, 464, 60), + new Point3D(474, 1654, 0), + new Point3D(897, 2411, 0), + new Point3D(1471, 2505, 5), + new Point3D(1257, 872, 16), + new Point3D(2581, 1118, 0), + new Point3D(2513, 1102, 0), + new Point3D(1608, 3371, 0), + new Point3D(4687, 1179, 0), + new Point3D(3704, 2196, 20), + new Point3D(3346, 572, 0), + new Point3D(569, 1309, 0) + }; + + public WitchApprenticeQuest(PlayerMobile from) : base(from) + { + } + + // Serialization + public WitchApprenticeQuest() + { + } + + public override Type[] TypeReferenceTable => m_TypeReferenceTable; + + public override object Name => 1055042; + + public override object OfferMessage => 1055001; + + public override TimeSpan RestartDelay => TimeSpan.FromMinutes(5.0); + public override bool IsTutorial => false; + + public override int Picture => 0x15D3; + + public override void Accept() + { + base.Accept(); + + AddConversation(new AcceptConversation()); + } + + public static Point3D RandomZeefzorpulLocation() => m_ZeefzorpulLocations.RandomElement(); + } +} diff --git a/Projects/UOContent/Engines/Spawners/BaseSpawner.cs b/Projects/UOContent/Engines/Spawners/BaseSpawner.cs index 779c11308..c2022084c 100644 --- a/Projects/UOContent/Engines/Spawners/BaseSpawner.cs +++ b/Projects/UOContent/Engines/Spawners/BaseSpawner.cs @@ -1,1005 +1,1039 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text.Json; -using Server.Commands; -using Server.Items; -using Server.Json; -using Server.Mobiles; -using Server.Utilities; -using CPA = Server.CommandPropertyAttribute; - -namespace Server.Engines.Spawners -{ - public abstract class BaseSpawner : Item, ISpawner - { - private static WarnTimer m_WarnTimer; - private int m_Count; - private bool m_Group; - private int m_HomeRange; - private int m_Team; - private TimeSpan m_MaxDelay; - private TimeSpan m_MinDelay; - private bool m_Running; - - private InternalTimer m_Timer; - private int m_WalkingRange = -1; - - public BaseSpawner() : this(1, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(10), 0, 4) - { - } - - public BaseSpawner(string spawnedName) : this(1, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(10), 0, 4, spawnedName) - { - } - - public BaseSpawner(int amount, int minDelay, int maxDelay, int team, int homeRange, - params string[] spawnedNames) : this(amount, TimeSpan.FromMinutes(minDelay), TimeSpan.FromMinutes(maxDelay), - team, homeRange, spawnedNames) - { - } - - public BaseSpawner(int amount, TimeSpan minDelay, TimeSpan maxDelay, int team, int homeRange, - params string[] spawnedNames) : base(0x1f13) - { - InitSpawn(amount, minDelay, maxDelay, team, homeRange); - for (int i = 0; i < spawnedNames.Length; i++) - AddEntry(spawnedNames[i], 100, amount, false); - } - - public BaseSpawner(DynamicJson json, JsonSerializerOptions options) : base(0x1f13) - { - json.GetProperty("count", options, out int amount); - json.GetProperty("minDelay", options, out TimeSpan minDelay); - json.GetProperty("maxDelay", options, out TimeSpan maxDelay); - json.GetProperty("team", options, out int team); - json.GetProperty("homeRange", options, out int homeRange); - json.GetProperty("walkingRange", options, out int walkingRange); - m_WalkingRange = walkingRange; - - InitSpawn(amount, minDelay, maxDelay, team, homeRange); - - json.GetProperty("entries", options, out List entries); - - foreach (var entry in entries) - AddEntry(entry.SpawnedName, entry.SpawnedProbability, entry.SpawnedMaxCount, false); - } - - public BaseSpawner(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Spawner"; - public bool IsFull => Spawned?.Count >= m_Count; - public bool IsEmpty => Spawned?.Count == 0; - public DateTime End { get; set; } - - public List Entries { get; private set; } - - public Dictionary Spawned { get; private set; } - - [CommandProperty(AccessLevel.Developer)] - public bool ReturnOnDeactivate { get; set; } - - [CommandProperty(AccessLevel.Developer)] - public int Count - { - get => m_Count; - set - { - m_Count = value; - - if (m_Timer != null && (!IsFull && !m_Timer.Running || IsFull && m_Timer.Running)) - DoTimer(); - - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.Developer)] - public virtual WayPoint WayPoint { get; set; } - - [CommandProperty(AccessLevel.Developer)] - public bool Running - { - get => m_Running; - set - { - if (value) - Start(); - else - Stop(); - - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.Developer)] - public int WalkingRange - { - get => m_WalkingRange; - set - { - m_WalkingRange = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.Developer)] - public int Team - { - get => m_Team; - set - { - m_Team = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.Developer)] - public TimeSpan MinDelay - { - get => m_MinDelay; - set - { - m_MinDelay = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.Developer)] - public TimeSpan MaxDelay - { - get => m_MaxDelay; - set - { - m_MaxDelay = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.Developer)] - public TimeSpan NextSpawn - { - get => m_Running && m_Timer?.Running == true ? End - DateTime.UtcNow : TimeSpan.FromSeconds(0); - set - { - Start(); - DoTimer(value); - } - } - - [CommandProperty(AccessLevel.Developer)] - public bool Group - { - get => m_Group; - set - { - m_Group = value; - InvalidateProperties(); - } - } - - public virtual Point3D HomeLocation => Location; - public bool UnlinkOnTaming => true; - - [CommandProperty(AccessLevel.Developer)] - public int HomeRange - { - get => m_HomeRange; - set - { - m_HomeRange = value; - InvalidateProperties(); - } - } - - Region ISpawner.Region => Region.Find(Location, Map); - - public void Remove(ISpawnable spawn) - { - Defrag(); - - if (spawn != null) - { - Spawned.TryGetValue(spawn, out SpawnerEntry entry); - - entry?.Spawned.Remove(spawn); - - Spawned.Remove(spawn); - } - - if (m_Running && !IsFull && m_Timer?.Running == false) - DoTimer(); - } - - public override void OnAfterDuped(Item newItem) - { - if (newItem is BaseSpawner newSpawner) - for (int i = 0; i < Entries.Count; i++) - newSpawner.AddEntry(Entries[i].SpawnedName, Entries[i].SpawnedProbability, Entries[i].SpawnedMaxCount, - false); - } - - public SpawnerEntry AddEntry(string creaturename, int probability = 100, int amount = 1, bool dotimer = true) - { - SpawnerEntry entry = new SpawnerEntry(creaturename, probability, amount); - Entries.Add(entry); - if (dotimer) - DoTimer(TimeSpan.FromSeconds(1)); - - return entry; - } - - public void InitSpawn(int amount, TimeSpan minDelay, TimeSpan maxDelay, int team, int homeRange) - { - Visible = false; - Movable = false; - m_Running = true; - m_Group = false; - m_MinDelay = minDelay; - m_MaxDelay = maxDelay; - m_Count = amount; - m_Team = team; - m_HomeRange = homeRange; - Entries = new List(); - Spawned = new Dictionary(); - - DoTimer(TimeSpan.FromSeconds(1)); - } - - public override void OnDoubleClick(Mobile from) - { - if (from.AccessLevel >= AccessLevel.Developer) - from.SendGump(new SpawnerGump(this)); - } - - public virtual void GetSpawnerProperties(ObjectPropertyList list) - { - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_Running) - { - list.Add(1060742); // active - - list.Add(1060656, m_Count.ToString()); // amount to make: ~1_val~ - list.Add(1061169, m_HomeRange.ToString()); // range ~1_val~ - list.Add(1050039, "walking range:\t{0}", m_WalkingRange); // ~1_NUMBER~ ~2_ITEMNAME~ - - list.Add(1053099, "group:\t{0}", m_Group); // ~1_oretype~: ~2_armortype~ - list.Add(1060847, "team:\t{0}", m_Team); // ~1_val~ ~2_val~ - list.Add(1063483, "delay:\t{0} to {1}", m_MinDelay, m_MaxDelay); // ~1_MATERIAL~: ~2_ITEMNAME~ - - GetSpawnerProperties(list); - - for (int i = 0; i < 6 && i < Entries.Count; ++i) - list.Add(1060658 + i, "\t{0}\t{1}", Entries[i].SpawnedName, CountSpawns(Entries[i])); - } - else - { - list.Add(1060743); // inactive - } - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - if (m_Running) - LabelTo(from, "[Running]"); - else - LabelTo(from, "[Off]"); - } - - public void Start() - { - if (!m_Running) - if (Entries.Count > 0) - { - m_Running = true; - DoTimer(); - } - } - - public void Stop() - { - if (m_Running) - { - m_Timer?.Stop(); - m_Running = false; - } - } - - public void Defrag() - { - Entries ??= new List(); - - for (int i = 0; i < Entries.Count; ++i) - Entries[i].Defrag(this); - } - - public virtual bool OnDefragSpawn(ISpawnable spawned, bool remove) - { - if (!remove) // Override could have set it to true already - remove = spawned.Deleted || spawned.Spawner == null || spawned switch - { - Item item => item.RootParent is Mobile || item.IsLockedDown || item.IsSecure, - Mobile m => m is BaseCreature c && (c.Controlled || c.IsStabled), - _ => true - }; - - if (remove) - Spawned.Remove(spawned); - - return remove; - } - - public void OnTick() - { - if (m_Group) - { - Defrag(); - - if (Spawned.Count > 0) - return; - - Respawn(); - } - else - { - Spawn(); - } - - DoTimer(); - } - - public virtual void Respawn() - { - RemoveSpawns(); - - for (int i = 0; i < m_Count; i++) - Spawn(); - - DoTimer(); // Turn off the timer! - } - - public virtual void Spawn() - { - Defrag(); - - if (Entries.Count <= 0 || IsFull) - return; - - int probsum = Entries.Where(t => !t.IsFull).Sum(t => t.SpawnedProbability); - - if (probsum <= 0) - return; - - int rand = Utility.RandomMinMax(1, probsum); - - for (int i = 0; i < Entries.Count; i++) - { - SpawnerEntry entry = Entries[i]; - if (entry.IsFull) - continue; - - if (rand <= entry.SpawnedProbability) - { - Spawn(entry, out EntryFlags flags); - entry.Valid = flags; - return; - } - - rand -= entry.SpawnedProbability; - } - } - - private static string[,] FormatProperties(string[] args) - { - string[,] props; - - int remains = args.Length; - - if (remains >= 2) - { - props = new string[remains / 2, 2]; - - remains /= 2; - - for (int j = 0; j < remains; ++j) - { - props[j, 0] = args[j * 2]; - props[j, 1] = args[j * 2 + 1]; - } - } - else - { - props = new string[0, 0]; - } - - return props; - } - - private static PropertyInfo[] GetTypeProperties(Type type, string[,] props) - { - PropertyInfo[] realProps = null; - - if (props != null) - { - realProps = new PropertyInfo[props.GetLength(0)]; - - PropertyInfo[] allProps = - type.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public); - - for (int i = 0; i < realProps.Length; ++i) - { - PropertyInfo thisProp = null; - - string propName = props[i, 0]; - - for (int j = 0; thisProp == null && j < allProps.Length; ++j) - if (Insensitive.Equals(propName, allProps[j].Name)) - thisProp = allProps[j]; - - if (thisProp == null) - return null; - CPA attr = Properties.GetCPA(thisProp); - - if (attr == null || attr.WriteLevel > AccessLevel.Developer || !thisProp.CanWrite || attr.ReadOnly) - return null; - realProps[i] = thisProp; - } - } - - return realProps; - } - - public bool Spawn(int index, out EntryFlags flags) - { - if (index >= 0 && index < Entries.Count) - return Spawn(Entries[index], out flags); - flags = EntryFlags.InvalidEntry; - return false; - } - - public bool Spawn(SpawnerEntry entry, out EntryFlags flags) - { - Map map = GetSpawnMap(); - flags = EntryFlags.None; - - if (map == null || map == Map.Internal || Parent != null) - return false; - - // Defrag taken care of in Spawn(), beforehand - // Count check taken care of in Spawn(), beforehand - - Type type = AssemblyHandler.FindFirstTypeForName(entry.SpawnedName); - - if (type != null) - { - try - { - object o = null; - string[] paramargs; - string[] propargs; - - propargs = string.IsNullOrEmpty(entry.Properties) ? - Array.Empty() : CommandSystem.Split(entry.Properties.Trim()); - - string[,] props = FormatProperties(propargs); - - PropertyInfo[] realProps = GetTypeProperties(type, props); - - if (realProps == null) - { - flags = EntryFlags.InvalidProps; - return false; - } - - paramargs = string.IsNullOrEmpty(entry.Parameters) ? - Array.Empty() : entry.Parameters.Trim().Split(' '); - - if (paramargs.Length == 0) - { - o = ActivatorUtil.CreateInstance(type, ci => Add.IsConstructible(ci, AccessLevel.Developer)); - } - else - { - ConstructorInfo[] ctors = type.GetConstructors(); - - for (int i = 0; i < ctors.Length; ++i) - { - ConstructorInfo ctor = ctors[i]; - - if (Add.IsConstructible(ctor, AccessLevel.Developer)) - { - ParameterInfo[] paramList = ctor.GetParameters(); - - if (paramargs.Length == paramList.Length) - { - object[] paramValues = Add.ParseValues(paramList, paramargs); - - if (paramValues != null) - { - o = ctor.Invoke(paramValues); - break; - } - } - } - } - } - - for (int i = 0; i < realProps.Length; i++) - if (realProps[i] != null) - { - object toSet = null; - string result = Properties.ConstructFromString(realProps[i].PropertyType, o, props[i, 1], ref toSet); - - if (result == null) - { - realProps[i].SetValue(o, toSet, null); - } - else - { - flags = EntryFlags.InvalidProps; - - (o as ISpawnable)?.Delete(); - - return false; - } - } - - if (o is Mobile m) - { - Spawned.Add(m, entry); - entry.Spawned.Add(m); - - Point3D loc = m is BaseVendor ? Location : GetSpawnPosition(m, map); - - m.OnBeforeSpawn(loc, map); - InvalidateProperties(); - - m.MoveToWorld(loc, map); - - if (m is BaseCreature c) - { - int walkrange = GetWalkingRange(); - - c.RangeHome = walkrange >= 0 ? walkrange : m_HomeRange; - c.CurrentWayPoint = WayPoint; - - if (m_Team > 0) - c.Team = m_Team; - - c.Home = Location; - c.HomeMap = Map; - } - - m.Spawner = this; - m.OnAfterSpawn(); - } - else if (o is Item item) - { - Spawned.Add(item, entry); - entry.Spawned.Add(item); - - Point3D loc = GetSpawnPosition(item, map); - - item.OnBeforeSpawn(loc, map); - - item.MoveToWorld(loc, map); - - item.Spawner = this; - item.OnAfterSpawn(); - } - else - { - flags = EntryFlags.InvalidType | EntryFlags.InvalidParams; - return false; - } - } - catch (Exception e) - { - Console.WriteLine($"EXCEPTION CAUGHT: {Serial}"); - Console.WriteLine(e); - return false; - } - - InvalidateProperties(); - return true; - } - - flags = EntryFlags.InvalidType; - return false; - } - - public virtual int GetWalkingRange() => m_WalkingRange; - - public abstract Point3D GetSpawnPosition(ISpawnable spawned, Map map); - - public virtual Map GetSpawnMap() => Map; - - public void DoTimer() - { - if (!m_Running) - return; - - int minSeconds = (int)m_MinDelay.TotalSeconds; - int maxSeconds = (int)m_MaxDelay.TotalSeconds; - - TimeSpan delay = TimeSpan.FromSeconds(Utility.RandomMinMax(minSeconds, maxSeconds)); - DoTimer(delay); - } - - public virtual void DoTimer(TimeSpan delay) - { - if (!m_Running) - return; - - End = DateTime.UtcNow + delay; - - m_Timer?.Stop(); - - m_Timer = new InternalTimer(this, delay); - if (!IsFull) - m_Timer.Start(); - } - - public int CountSpawns(SpawnerEntry entry) - { - Defrag(); - - return entry.Spawned.Count; - } - - public void RemoveEntry(SpawnerEntry entry) - { - Defrag(); - - for (int i = entry.Spawned.Count - 1; i >= 0; i--) - { - ISpawnable e = entry.Spawned[i]; - entry.Spawned.RemoveAt(i); - e?.Delete(); - } - - Entries.Remove(entry); - - if (m_Running && !IsFull && m_Timer?.Running == false) - DoTimer(); - - InvalidateProperties(); - } - - public void RemoveSpawn(int index) // Entry - { - if (index >= 0 && index < Entries.Count) - RemoveSpawn(Entries[index]); - } - - public void RemoveSpawn(SpawnerEntry entry) - { - for (int i = entry.Spawned.Count - 1; i >= 0; i--) - { - ISpawnable e = entry.Spawned[i]; - - if (e != null) - { - entry.Spawned.RemoveAt(i); - Spawned.Remove(e); - - e.Delete(); - } - } - } - - public void RemoveSpawns() - { - Defrag(); - - for (int i = 0; i < Entries.Count; i++) - { - SpawnerEntry entry = Entries[i]; - - for (int j = entry.Spawned.Count - 1; j >= 0; j--) - { - ISpawnable e = entry.Spawned[j]; - - if (e != null) - { - Spawned.Remove(e); - entry.Spawned.RemoveAt(j); - e.Delete(); - } - } - } - - if (m_Running && !IsFull && m_Timer?.Running == false) - DoTimer(); - - InvalidateProperties(); - } - - public void BringToHome() - { - Defrag(); - - foreach (ISpawnable e in Spawned.Keys) e?.MoveToWorld(Location, Map); - } - - public override void OnDelete() - { - base.OnDelete(); - - Stop(); - RemoveSpawns(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(8); // version - - writer.Write(ReturnOnDeactivate); - - writer.Write(Entries.Count); - - for (int i = 0; i < Entries.Count; ++i) - Entries[i].Serialize(writer); - - writer.Write(m_WalkingRange); - - writer.Write(WayPoint); - - writer.Write(m_Group); - - writer.Write(m_MinDelay); - writer.Write(m_MaxDelay); - writer.Write(m_Count); - writer.Write(m_Team); - writer.Write(m_HomeRange); - writer.Write(m_Running); - - if (m_Running) - writer.WriteDeltaTime(End); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Spawned = new Dictionary(); - - if (version < 7) - Entries = new List(); - - switch (version) - { - case 8: - { - ReturnOnDeactivate = reader.ReadBool(); - goto case 7; - } - case 7: - { - int size = reader.ReadInt(); - - Entries = new List(size); - - for (int i = 0; i < size; ++i) - Entries.Add(new SpawnerEntry(this, reader)); - - goto case 4; // Skip the other crap - } - case 6: - { - int size = reader.ReadInt(); - - bool addentries = Entries.Count == 0; - - for (int i = 0; i < size; ++i) - if (addentries) - Entries.Add(new SpawnerEntry(string.Empty, 100, reader.ReadInt())); - else - Entries[i].SpawnedMaxCount = reader.ReadInt(); - - goto case 5; - } - case 5: - { - int size = reader.ReadInt(); - - bool addentries = Entries.Count == 0; - - for (int i = 0; i < size; ++i) - if (addentries) - Entries.Add(new SpawnerEntry(string.Empty, reader.ReadInt(), 1)); - else - Entries[i].SpawnedProbability = reader.ReadInt(); - - goto case 4; - } - case 4: - { - m_WalkingRange = reader.ReadInt(); - - goto case 3; - } - case 3: - case 2: - { - WayPoint = reader.ReadItem() as WayPoint; - - goto case 1; - } - - case 1: - { - m_Group = reader.ReadBool(); - - goto case 0; - } - - case 0: - { - m_MinDelay = reader.ReadTimeSpan(); - m_MaxDelay = reader.ReadTimeSpan(); - m_Count = reader.ReadInt(); - m_Team = reader.ReadInt(); - m_HomeRange = reader.ReadInt(); - m_Running = reader.ReadBool(); - - TimeSpan ts = TimeSpan.Zero; - - if (m_Running) - ts = reader.ReadDeltaTime() - DateTime.UtcNow; - - if (version < 7) - { - int size = reader.ReadInt(); - - bool addentries = Entries.Count == 0; - - for (int i = 0; i < size; ++i) - { - string typeName = reader.ReadString(); - - if (addentries) - Entries.Add(new SpawnerEntry(typeName, 100, 1)); - else - Entries[i].SpawnedName = typeName; - - if (AssemblyHandler.FindFirstTypeForName(typeName) == null) - { - m_WarnTimer ??= new WarnTimer(); - - m_WarnTimer.Add(Location, Map, typeName); - } - } - - int count = reader.ReadInt(); - - for (int i = 0; i < count; ++i) - if (reader.ReadEntity() is ISpawnable e) - { - if (e is BaseCreature creature) - creature.RemoveIfUntamed = true; - - e.Spawner = this; - - for (int j = 0; j < Entries.Count; j++) - if (AssemblyHandler.FindFirstTypeForName(Entries[j].SpawnedName) == e.GetType()) - { - Entries[j].Spawned.Add(e); - Spawned.Add(e, Entries[j]); - break; - } - } - } - - DoTimer(ts); - - break; - } - } - - if (version < 4) - m_WalkingRange = m_HomeRange; - } - - private class InternalTimer : Timer - { - private readonly BaseSpawner m_Spawner; - - public InternalTimer(BaseSpawner spawner, TimeSpan delay) : base(delay) - { - if (spawner.IsFull) - Priority = TimerPriority.FiveSeconds; - else - Priority = TimerPriority.OneSecond; - - m_Spawner = spawner; - } - - protected override void OnTick() - { - if (m_Spawner != null) - if (!m_Spawner.Deleted) - m_Spawner.OnTick(); - } - } - - private class WarnTimer : Timer - { - private readonly List m_List; - - public WarnTimer() : base(TimeSpan.FromSeconds(1.0)) - { - m_List = new List(); - Start(); - } - - public void Add(Point3D p, Map map, string name) - { - m_List.Add(new WarnEntry(p, map, name)); - } - - protected override void OnTick() - { - try - { - Console.WriteLine("Warning: {0} bad spawns detected, logged: 'badspawn.log'", m_List.Count); - - using StreamWriter op = new StreamWriter("badspawn.log", true); - op.WriteLine("# Bad spawns : {0}", DateTime.Now); - op.WriteLine("# Format: X Y Z F Name"); - op.WriteLine(); - - foreach (WarnEntry e in m_List) - op.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}", e.m_Point.X, e.m_Point.Y, e.m_Point.Z, e.m_Map, - e.m_Name); - - op.WriteLine(); - op.WriteLine(); - } - catch - { - // ignored - } - } - - private class WarnEntry - { - public readonly Map m_Map; - public readonly string m_Name; - public Point3D m_Point; - - public WarnEntry(Point3D p, Map map, string name) - { - m_Point = p; - m_Map = map; - m_Name = name; - } - } - } - } - - [Flags] - public enum EntryFlags - { - None = 0x000, - InvalidType = 0x001, - InvalidParams = 0x002, - InvalidProps = 0x004, - InvalidEntry = 0x008 - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text.Json; +using Server.Commands; +using Server.Items; +using Server.Json; +using Server.Mobiles; +using Server.Utilities; +using CPA = Server.CommandPropertyAttribute; + +namespace Server.Engines.Spawners +{ + public abstract class BaseSpawner : Item, ISpawner + { + private static WarnTimer m_WarnTimer; + private int m_Count; + private bool m_Group; + private int m_HomeRange; + private TimeSpan m_MaxDelay; + private TimeSpan m_MinDelay; + private bool m_Running; + private int m_Team; + + private InternalTimer m_Timer; + private int m_WalkingRange = -1; + + public BaseSpawner() : this(1, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(10), 0, 4) + { + } + + public BaseSpawner(string spawnedName) : this( + 1, + TimeSpan.FromMinutes(5), + TimeSpan.FromMinutes(10), + 0, + 4, + spawnedName + ) + { + } + + public BaseSpawner( + int amount, int minDelay, int maxDelay, int team, int homeRange, + params string[] spawnedNames + ) : this( + amount, + TimeSpan.FromMinutes(minDelay), + TimeSpan.FromMinutes(maxDelay), + team, + homeRange, + spawnedNames + ) + { + } + + public BaseSpawner( + int amount, TimeSpan minDelay, TimeSpan maxDelay, int team, int homeRange, + params string[] spawnedNames + ) : base(0x1f13) + { + InitSpawn(amount, minDelay, maxDelay, team, homeRange); + for (var i = 0; i < spawnedNames.Length; i++) + AddEntry(spawnedNames[i], 100, amount, false); + } + + public BaseSpawner(DynamicJson json, JsonSerializerOptions options) : base(0x1f13) + { + json.GetProperty("count", options, out int amount); + json.GetProperty("minDelay", options, out TimeSpan minDelay); + json.GetProperty("maxDelay", options, out TimeSpan maxDelay); + json.GetProperty("team", options, out int team); + json.GetProperty("homeRange", options, out int homeRange); + json.GetProperty("walkingRange", options, out int walkingRange); + m_WalkingRange = walkingRange; + + InitSpawn(amount, minDelay, maxDelay, team, homeRange); + + json.GetProperty("entries", options, out List entries); + + foreach (var entry in entries) + AddEntry(entry.SpawnedName, entry.SpawnedProbability, entry.SpawnedMaxCount, false); + } + + public BaseSpawner(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Spawner"; + public bool IsFull => Spawned?.Count >= m_Count; + public bool IsEmpty => Spawned?.Count == 0; + public DateTime End { get; set; } + + public List Entries { get; private set; } + + public Dictionary Spawned { get; private set; } + + [CommandProperty(AccessLevel.Developer)] + public int Count + { + get => m_Count; + set + { + m_Count = value; + + if (m_Timer != null && (!IsFull && !m_Timer.Running || IsFull && m_Timer.Running)) + DoTimer(); + + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.Developer)] + public virtual WayPoint WayPoint { get; set; } + + [CommandProperty(AccessLevel.Developer)] + public bool Running + { + get => m_Running; + set + { + if (value) + Start(); + else + Stop(); + + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.Developer)] + public int WalkingRange + { + get => m_WalkingRange; + set + { + m_WalkingRange = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.Developer)] + public int Team + { + get => m_Team; + set + { + m_Team = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.Developer)] + public TimeSpan MinDelay + { + get => m_MinDelay; + set + { + m_MinDelay = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.Developer)] + public TimeSpan MaxDelay + { + get => m_MaxDelay; + set + { + m_MaxDelay = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.Developer)] + public TimeSpan NextSpawn + { + get => m_Running && m_Timer?.Running == true ? End - DateTime.UtcNow : TimeSpan.FromSeconds(0); + set + { + Start(); + DoTimer(value); + } + } + + [CommandProperty(AccessLevel.Developer)] + public bool Group + { + get => m_Group; + set + { + m_Group = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.Developer)] + public bool ReturnOnDeactivate { get; set; } + + public virtual Point3D HomeLocation => Location; + public bool UnlinkOnTaming => true; + + [CommandProperty(AccessLevel.Developer)] + public int HomeRange + { + get => m_HomeRange; + set + { + m_HomeRange = value; + InvalidateProperties(); + } + } + + Region ISpawner.Region => Region.Find(Location, Map); + + public void Remove(ISpawnable spawn) + { + Defrag(); + + if (spawn != null) + { + Spawned.TryGetValue(spawn, out var entry); + + entry?.Spawned.Remove(spawn); + + Spawned.Remove(spawn); + } + + if (m_Running && !IsFull && m_Timer?.Running == false) + DoTimer(); + } + + public virtual void Respawn() + { + RemoveSpawns(); + + for (var i = 0; i < m_Count; i++) + Spawn(); + + DoTimer(); // Turn off the timer! + } + + public abstract Point3D GetSpawnPosition(ISpawnable spawned, Map map); + + public override void OnAfterDuped(Item newItem) + { + if (newItem is BaseSpawner newSpawner) + for (var i = 0; i < Entries.Count; i++) + newSpawner.AddEntry( + Entries[i].SpawnedName, + Entries[i].SpawnedProbability, + Entries[i].SpawnedMaxCount, + false + ); + } + + public SpawnerEntry AddEntry(string creaturename, int probability = 100, int amount = 1, bool dotimer = true) + { + var entry = new SpawnerEntry(creaturename, probability, amount); + Entries.Add(entry); + if (dotimer) + DoTimer(TimeSpan.FromSeconds(1)); + + return entry; + } + + public void InitSpawn(int amount, TimeSpan minDelay, TimeSpan maxDelay, int team, int homeRange) + { + Visible = false; + Movable = false; + m_Running = true; + m_Group = false; + m_MinDelay = minDelay; + m_MaxDelay = maxDelay; + m_Count = amount; + m_Team = team; + m_HomeRange = homeRange; + Entries = new List(); + Spawned = new Dictionary(); + + DoTimer(TimeSpan.FromSeconds(1)); + } + + public override void OnDoubleClick(Mobile from) + { + if (from.AccessLevel >= AccessLevel.Developer) + from.SendGump(new SpawnerGump(this)); + } + + public virtual void GetSpawnerProperties(ObjectPropertyList list) + { + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_Running) + { + list.Add(1060742); // active + + list.Add(1060656, m_Count.ToString()); // amount to make: ~1_val~ + list.Add(1061169, m_HomeRange.ToString()); // range ~1_val~ + list.Add(1050039, "walking range:\t{0}", m_WalkingRange); // ~1_NUMBER~ ~2_ITEMNAME~ + + list.Add(1053099, "group:\t{0}", m_Group); // ~1_oretype~: ~2_armortype~ + list.Add(1060847, "team:\t{0}", m_Team); // ~1_val~ ~2_val~ + list.Add(1063483, "delay:\t{0} to {1}", m_MinDelay, m_MaxDelay); // ~1_MATERIAL~: ~2_ITEMNAME~ + + GetSpawnerProperties(list); + + for (var i = 0; i < 6 && i < Entries.Count; ++i) + list.Add(1060658 + i, "\t{0}\t{1}", Entries[i].SpawnedName, CountSpawns(Entries[i])); + } + else + { + list.Add(1060743); // inactive + } + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + if (m_Running) + LabelTo(from, "[Running]"); + else + LabelTo(from, "[Off]"); + } + + public void Start() + { + if (!m_Running) + if (Entries.Count > 0) + { + m_Running = true; + DoTimer(); + } + } + + public void Stop() + { + if (m_Running) + { + m_Timer?.Stop(); + m_Running = false; + } + } + + public void Defrag() + { + Entries ??= new List(); + + for (var i = 0; i < Entries.Count; ++i) + Entries[i].Defrag(this); + } + + public virtual bool OnDefragSpawn(ISpawnable spawned, bool remove) + { + if (!remove) // Override could have set it to true already + remove = spawned.Deleted || spawned.Spawner == null || spawned switch + { + Item item => item.RootParent is Mobile || item.IsLockedDown || item.IsSecure, + Mobile m => m is BaseCreature c && (c.Controlled || c.IsStabled), + _ => true + }; + + if (remove) + Spawned.Remove(spawned); + + return remove; + } + + public void OnTick() + { + if (m_Group) + { + Defrag(); + + if (Spawned.Count > 0) + return; + + Respawn(); + } + else + { + Spawn(); + } + + DoTimer(); + } + + public virtual void Spawn() + { + Defrag(); + + if (Entries.Count <= 0 || IsFull) + return; + + var probsum = Entries.Where(t => !t.IsFull).Sum(t => t.SpawnedProbability); + + if (probsum <= 0) + return; + + var rand = Utility.RandomMinMax(1, probsum); + + for (var i = 0; i < Entries.Count; i++) + { + var entry = Entries[i]; + if (entry.IsFull) + continue; + + if (rand <= entry.SpawnedProbability) + { + Spawn(entry, out var flags); + entry.Valid = flags; + return; + } + + rand -= entry.SpawnedProbability; + } + } + + private static string[,] FormatProperties(string[] args) + { + string[,] props; + + var remains = args.Length; + + if (remains >= 2) + { + props = new string[remains / 2, 2]; + + remains /= 2; + + for (var j = 0; j < remains; ++j) + { + props[j, 0] = args[j * 2]; + props[j, 1] = args[j * 2 + 1]; + } + } + else + { + props = new string[0, 0]; + } + + return props; + } + + private static PropertyInfo[] GetTypeProperties(Type type, string[,] props) + { + PropertyInfo[] realProps = null; + + if (props != null) + { + realProps = new PropertyInfo[props.GetLength(0)]; + + var allProps = + type.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public); + + for (var i = 0; i < realProps.Length; ++i) + { + PropertyInfo thisProp = null; + + var propName = props[i, 0]; + + for (var j = 0; thisProp == null && j < allProps.Length; ++j) + if (Insensitive.Equals(propName, allProps[j].Name)) + thisProp = allProps[j]; + + if (thisProp == null) + return null; + var attr = Properties.GetCPA(thisProp); + + if (attr == null || attr.WriteLevel > AccessLevel.Developer || !thisProp.CanWrite || attr.ReadOnly) + return null; + realProps[i] = thisProp; + } + } + + return realProps; + } + + public bool Spawn(int index, out EntryFlags flags) + { + if (index >= 0 && index < Entries.Count) + return Spawn(Entries[index], out flags); + flags = EntryFlags.InvalidEntry; + return false; + } + + public bool Spawn(SpawnerEntry entry, out EntryFlags flags) + { + var map = GetSpawnMap(); + flags = EntryFlags.None; + + if (map == null || map == Map.Internal || Parent != null) + return false; + + // Defrag taken care of in Spawn(), beforehand + // Count check taken care of in Spawn(), beforehand + + var type = AssemblyHandler.FindFirstTypeForName(entry.SpawnedName); + + if (type != null) + { + try + { + object o = null; + string[] paramargs; + string[] propargs; + + propargs = string.IsNullOrEmpty(entry.Properties) + ? Array.Empty() + : CommandSystem.Split(entry.Properties.Trim()); + + var props = FormatProperties(propargs); + + var realProps = GetTypeProperties(type, props); + + if (realProps == null) + { + flags = EntryFlags.InvalidProps; + return false; + } + + paramargs = string.IsNullOrEmpty(entry.Parameters) + ? Array.Empty() + : entry.Parameters.Trim().Split(' '); + + if (paramargs.Length == 0) + { + o = ActivatorUtil.CreateInstance(type, ci => Add.IsConstructible(ci, AccessLevel.Developer)); + } + else + { + var ctors = type.GetConstructors(); + + for (var i = 0; i < ctors.Length; ++i) + { + var ctor = ctors[i]; + + if (Add.IsConstructible(ctor, AccessLevel.Developer)) + { + var paramList = ctor.GetParameters(); + + if (paramargs.Length == paramList.Length) + { + var paramValues = Add.ParseValues(paramList, paramargs); + + if (paramValues != null) + { + o = ctor.Invoke(paramValues); + break; + } + } + } + } + } + + for (var i = 0; i < realProps.Length; i++) + if (realProps[i] != null) + { + object toSet = null; + var result = Properties.ConstructFromString( + realProps[i].PropertyType, + o, + props[i, 1], + ref toSet + ); + + if (result == null) + { + realProps[i].SetValue(o, toSet, null); + } + else + { + flags = EntryFlags.InvalidProps; + + (o as ISpawnable)?.Delete(); + + return false; + } + } + + if (o is Mobile m) + { + Spawned.Add(m, entry); + entry.Spawned.Add(m); + + var loc = m is BaseVendor ? Location : GetSpawnPosition(m, map); + + m.OnBeforeSpawn(loc, map); + InvalidateProperties(); + + m.MoveToWorld(loc, map); + + if (m is BaseCreature c) + { + var walkrange = GetWalkingRange(); + + c.RangeHome = walkrange >= 0 ? walkrange : m_HomeRange; + c.CurrentWayPoint = WayPoint; + + if (m_Team > 0) + c.Team = m_Team; + + c.Home = Location; + c.HomeMap = Map; + } + + m.Spawner = this; + m.OnAfterSpawn(); + } + else if (o is Item item) + { + Spawned.Add(item, entry); + entry.Spawned.Add(item); + + var loc = GetSpawnPosition(item, map); + + item.OnBeforeSpawn(loc, map); + + item.MoveToWorld(loc, map); + + item.Spawner = this; + item.OnAfterSpawn(); + } + else + { + flags = EntryFlags.InvalidType | EntryFlags.InvalidParams; + return false; + } + } + catch (Exception e) + { + Console.WriteLine($"EXCEPTION CAUGHT: {Serial}"); + Console.WriteLine(e); + return false; + } + + InvalidateProperties(); + return true; + } + + flags = EntryFlags.InvalidType; + return false; + } + + public virtual int GetWalkingRange() => m_WalkingRange; + + public virtual Map GetSpawnMap() => Map; + + public void DoTimer() + { + if (!m_Running) + return; + + var minSeconds = (int)m_MinDelay.TotalSeconds; + var maxSeconds = (int)m_MaxDelay.TotalSeconds; + + var delay = TimeSpan.FromSeconds(Utility.RandomMinMax(minSeconds, maxSeconds)); + DoTimer(delay); + } + + public virtual void DoTimer(TimeSpan delay) + { + if (!m_Running) + return; + + End = DateTime.UtcNow + delay; + + m_Timer?.Stop(); + + m_Timer = new InternalTimer(this, delay); + if (!IsFull) + m_Timer.Start(); + } + + public int CountSpawns(SpawnerEntry entry) + { + Defrag(); + + return entry.Spawned.Count; + } + + public void RemoveEntry(SpawnerEntry entry) + { + Defrag(); + + for (var i = entry.Spawned.Count - 1; i >= 0; i--) + { + var e = entry.Spawned[i]; + entry.Spawned.RemoveAt(i); + e?.Delete(); + } + + Entries.Remove(entry); + + if (m_Running && !IsFull && m_Timer?.Running == false) + DoTimer(); + + InvalidateProperties(); + } + + public void RemoveSpawn(int index) // Entry + { + if (index >= 0 && index < Entries.Count) + RemoveSpawn(Entries[index]); + } + + public void RemoveSpawn(SpawnerEntry entry) + { + for (var i = entry.Spawned.Count - 1; i >= 0; i--) + { + var e = entry.Spawned[i]; + + if (e != null) + { + entry.Spawned.RemoveAt(i); + Spawned.Remove(e); + + e.Delete(); + } + } + } + + public void RemoveSpawns() + { + Defrag(); + + for (var i = 0; i < Entries.Count; i++) + { + var entry = Entries[i]; + + for (var j = entry.Spawned.Count - 1; j >= 0; j--) + { + var e = entry.Spawned[j]; + + if (e != null) + { + Spawned.Remove(e); + entry.Spawned.RemoveAt(j); + e.Delete(); + } + } + } + + if (m_Running && !IsFull && m_Timer?.Running == false) + DoTimer(); + + InvalidateProperties(); + } + + public void BringToHome() + { + Defrag(); + + foreach (var e in Spawned.Keys) e?.MoveToWorld(Location, Map); + } + + public override void OnDelete() + { + base.OnDelete(); + + Stop(); + RemoveSpawns(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(8); // version + + writer.Write(ReturnOnDeactivate); + + writer.Write(Entries.Count); + + for (var i = 0; i < Entries.Count; ++i) + Entries[i].Serialize(writer); + + writer.Write(m_WalkingRange); + + writer.Write(WayPoint); + + writer.Write(m_Group); + + writer.Write(m_MinDelay); + writer.Write(m_MaxDelay); + writer.Write(m_Count); + writer.Write(m_Team); + writer.Write(m_HomeRange); + writer.Write(m_Running); + + if (m_Running) + writer.WriteDeltaTime(End); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + Spawned = new Dictionary(); + + if (version < 7) + Entries = new List(); + + switch (version) + { + case 8: + { + ReturnOnDeactivate = reader.ReadBool(); + goto case 7; + } + case 7: + { + var size = reader.ReadInt(); + + Entries = new List(size); + + for (var i = 0; i < size; ++i) + Entries.Add(new SpawnerEntry(this, reader)); + + goto case 4; // Skip the other crap + } + case 6: + { + var size = reader.ReadInt(); + + var addentries = Entries.Count == 0; + + for (var i = 0; i < size; ++i) + if (addentries) + Entries.Add(new SpawnerEntry(string.Empty, 100, reader.ReadInt())); + else + Entries[i].SpawnedMaxCount = reader.ReadInt(); + + goto case 5; + } + case 5: + { + var size = reader.ReadInt(); + + var addentries = Entries.Count == 0; + + for (var i = 0; i < size; ++i) + if (addentries) + Entries.Add(new SpawnerEntry(string.Empty, reader.ReadInt(), 1)); + else + Entries[i].SpawnedProbability = reader.ReadInt(); + + goto case 4; + } + case 4: + { + m_WalkingRange = reader.ReadInt(); + + goto case 3; + } + case 3: + case 2: + { + WayPoint = reader.ReadItem() as WayPoint; + + goto case 1; + } + + case 1: + { + m_Group = reader.ReadBool(); + + goto case 0; + } + + case 0: + { + m_MinDelay = reader.ReadTimeSpan(); + m_MaxDelay = reader.ReadTimeSpan(); + m_Count = reader.ReadInt(); + m_Team = reader.ReadInt(); + m_HomeRange = reader.ReadInt(); + m_Running = reader.ReadBool(); + + var ts = TimeSpan.Zero; + + if (m_Running) + ts = reader.ReadDeltaTime() - DateTime.UtcNow; + + if (version < 7) + { + var size = reader.ReadInt(); + + var addentries = Entries.Count == 0; + + for (var i = 0; i < size; ++i) + { + var typeName = reader.ReadString(); + + if (addentries) + Entries.Add(new SpawnerEntry(typeName, 100, 1)); + else + Entries[i].SpawnedName = typeName; + + if (AssemblyHandler.FindFirstTypeForName(typeName) == null) + { + m_WarnTimer ??= new WarnTimer(); + + m_WarnTimer.Add(Location, Map, typeName); + } + } + + var count = reader.ReadInt(); + + for (var i = 0; i < count; ++i) + if (reader.ReadEntity() is ISpawnable e) + { + if (e is BaseCreature creature) + creature.RemoveIfUntamed = true; + + e.Spawner = this; + + for (var j = 0; j < Entries.Count; j++) + if (AssemblyHandler.FindFirstTypeForName(Entries[j].SpawnedName) == e.GetType()) + { + Entries[j].Spawned.Add(e); + Spawned.Add(e, Entries[j]); + break; + } + } + } + + DoTimer(ts); + + break; + } + } + + if (version < 4) + m_WalkingRange = m_HomeRange; + } + + private class InternalTimer : Timer + { + private readonly BaseSpawner m_Spawner; + + public InternalTimer(BaseSpawner spawner, TimeSpan delay) : base(delay) + { + if (spawner.IsFull) + Priority = TimerPriority.FiveSeconds; + else + Priority = TimerPriority.OneSecond; + + m_Spawner = spawner; + } + + protected override void OnTick() + { + if (m_Spawner != null) + if (!m_Spawner.Deleted) + m_Spawner.OnTick(); + } + } + + private class WarnTimer : Timer + { + private readonly List m_List; + + public WarnTimer() : base(TimeSpan.FromSeconds(1.0)) + { + m_List = new List(); + Start(); + } + + public void Add(Point3D p, Map map, string name) + { + m_List.Add(new WarnEntry(p, map, name)); + } + + protected override void OnTick() + { + try + { + Console.WriteLine("Warning: {0} bad spawns detected, logged: 'badspawn.log'", m_List.Count); + + using var op = new StreamWriter("badspawn.log", true); + op.WriteLine("# Bad spawns : {0}", DateTime.Now); + op.WriteLine("# Format: X Y Z F Name"); + op.WriteLine(); + + foreach (var e in m_List) + op.WriteLine( + "{0}\t{1}\t{2}\t{3}\t{4}", + e.m_Point.X, + e.m_Point.Y, + e.m_Point.Z, + e.m_Map, + e.m_Name + ); + + op.WriteLine(); + op.WriteLine(); + } + catch + { + // ignored + } + } + + private class WarnEntry + { + public readonly Map m_Map; + public readonly string m_Name; + public Point3D m_Point; + + public WarnEntry(Point3D p, Map map, string name) + { + m_Point = p; + m_Map = map; + m_Name = name; + } + } + } + } + + [Flags] + public enum EntryFlags + { + None = 0x000, + InvalidType = 0x001, + InvalidParams = 0x002, + InvalidProps = 0x004, + InvalidEntry = 0x008 + } +} diff --git a/Projects/UOContent/Engines/Spawners/GenerateSpawners.cs b/Projects/UOContent/Engines/Spawners/GenerateSpawners.cs index 17e16b908..538b92961 100644 --- a/Projects/UOContent/Engines/Spawners/GenerateSpawners.cs +++ b/Projects/UOContent/Engines/Spawners/GenerateSpawners.cs @@ -1,120 +1,128 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text.Json; -using Server.Json; -using Server.Utilities; - -namespace Server.Engines.Spawners -{ - public static class GenerateSpawners - { - public static void Initialize() - { - CommandSystem.Register("GenerateSpawners", AccessLevel.Developer, GenerateSpawners_OnCommand); - } - - private static void GenerateSpawners_OnCommand(CommandEventArgs e) - { - Mobile from = e.Mobile; - - if (e.Arguments.Length == 0) - { - from.SendMessage("Usage: [GenerateSpawners "); - return; - } - - var di = new DirectoryInfo(Core.BaseDirectory); - - var files = di.GetFiles(e.Arguments[0], SearchOption.AllDirectories); - - if (files.Length == 0) - { - from.SendMessage("GenerateSpawners: No files found matching the pattern"); - return; - } - - JsonSerializerOptions options = JsonConfig.GetOptions(new TextDefinitionConverterFactory()); - - for (int i = 0; i < files.Length; i++) - { - var file = files[i]; - from.SendMessage("GenerateSpawners: Generating spawners for {0}...", file.Name); - - try - { - var spawners = JsonConfig.Deserialize>(file.FullName); - ParseSpawnerList(from, spawners, options); - } - catch (JsonException) - { - from.SendMessage("GenerateSpawners: Exception parsing {0}, file may not be in the correct format.", file.FullName); - } - } - } - - private static void ParseSpawnerList(Mobile from, List spawners, JsonSerializerOptions options) - { - Stopwatch watch = Stopwatch.StartNew(); - List failures = new List(); - int count = 0; - - for (var i = 0; i < spawners.Count; i++) - { - var json = spawners[i]; - Type type = AssemblyHandler.FindFirstTypeForName(json.Type); - - if (type == null || !typeof(BaseSpawner).IsAssignableFrom(type)) - { - string failure = $"GenerateSpawners: Invalid spawner type {json.Type ?? "(-null-)"} ({i})"; - if (!failures.Contains(failure)) - { - failures.Add(failure); - from.SendMessage(failure); - } - - continue; - } - - json.GetProperty("location", options, out Point3D location); - json.GetProperty("map", options, out Map map); - - var eable = map.GetItemsInRange(location, 0); - - if (eable.Any(sp => sp.GetType() == type)) - { - eable.Free(); - continue; - } - - eable.Free(); - - try - { - var spawner = ActivatorUtil.CreateInstance(type, json, options) as ISpawner; - - spawner!.MoveToWorld(location, map); - spawner!.Respawn(); - } - catch (Exception) - { - string failure = $"GenerateSpawners: Spawner {type} failed to construct"; - if (!failures.Contains(failure)) - { - failures.Add(failure); - from.SendMessage(failure); - } - - continue; - } - - count++; - } - - watch.Stop(); - from.SendMessage("GenerateSpawners: Generated {0} spawners ({1:F2} seconds, {2} failures)", count, watch.Elapsed.TotalSeconds, failures.Count); - } - } -} +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text.Json; +using Server.Json; +using Server.Utilities; + +namespace Server.Engines.Spawners +{ + public static class GenerateSpawners + { + public static void Initialize() + { + CommandSystem.Register("GenerateSpawners", AccessLevel.Developer, GenerateSpawners_OnCommand); + } + + private static void GenerateSpawners_OnCommand(CommandEventArgs e) + { + var from = e.Mobile; + + if (e.Arguments.Length == 0) + { + from.SendMessage("Usage: [GenerateSpawners "); + return; + } + + var di = new DirectoryInfo(Core.BaseDirectory); + + var files = di.GetFiles(e.Arguments[0], SearchOption.AllDirectories); + + if (files.Length == 0) + { + from.SendMessage("GenerateSpawners: No files found matching the pattern"); + return; + } + + var options = JsonConfig.GetOptions(new TextDefinitionConverterFactory()); + + for (var i = 0; i < files.Length; i++) + { + var file = files[i]; + from.SendMessage("GenerateSpawners: Generating spawners for {0}...", file.Name); + + try + { + var spawners = JsonConfig.Deserialize>(file.FullName); + ParseSpawnerList(from, spawners, options); + } + catch (JsonException) + { + from.SendMessage( + "GenerateSpawners: Exception parsing {0}, file may not be in the correct format.", + file.FullName + ); + } + } + } + + private static void ParseSpawnerList(Mobile from, List spawners, JsonSerializerOptions options) + { + var watch = Stopwatch.StartNew(); + var failures = new List(); + var count = 0; + + for (var i = 0; i < spawners.Count; i++) + { + var json = spawners[i]; + var type = AssemblyHandler.FindFirstTypeForName(json.Type); + + if (type == null || !typeof(BaseSpawner).IsAssignableFrom(type)) + { + var failure = $"GenerateSpawners: Invalid spawner type {json.Type ?? "(-null-)"} ({i})"; + if (!failures.Contains(failure)) + { + failures.Add(failure); + from.SendMessage(failure); + } + + continue; + } + + json.GetProperty("location", options, out Point3D location); + json.GetProperty("map", options, out Map map); + + var eable = map.GetItemsInRange(location, 0); + + if (eable.Any(sp => sp.GetType() == type)) + { + eable.Free(); + continue; + } + + eable.Free(); + + try + { + var spawner = ActivatorUtil.CreateInstance(type, json, options) as ISpawner; + + spawner!.MoveToWorld(location, map); + spawner!.Respawn(); + } + catch (Exception) + { + var failure = $"GenerateSpawners: Spawner {type} failed to construct"; + if (!failures.Contains(failure)) + { + failures.Add(failure); + from.SendMessage(failure); + } + + continue; + } + + count++; + } + + watch.Stop(); + from.SendMessage( + "GenerateSpawners: Generated {0} spawners ({1:F2} seconds, {2} failures)", + count, + watch.Elapsed.TotalSeconds, + failures.Count + ); + } + } +} diff --git a/Projects/UOContent/Engines/Spawners/ProximitySpawner.cs b/Projects/UOContent/Engines/Spawners/ProximitySpawner.cs index f1652cf98..2adf2ebe8 100644 --- a/Projects/UOContent/Engines/Spawners/ProximitySpawner.cs +++ b/Projects/UOContent/Engines/Spawners/ProximitySpawner.cs @@ -1,148 +1,154 @@ -using System; -using System.Text.Json; -using Server.Json; -using Server.Mobiles; - -namespace Server.Engines.Spawners -{ - public class ProximitySpawner : Spawner - { - [Constructible(AccessLevel.Developer)] - public ProximitySpawner() - { - } - - [Constructible(AccessLevel.Developer)] - public ProximitySpawner(string spawnName) - : base(spawnName) - { - } - - [Constructible(AccessLevel.Developer)] - public ProximitySpawner(int amount, int minDelay, int maxDelay, int team, int homeRange, string spawnName) - : base(amount, minDelay, maxDelay, team, homeRange, spawnName) - { - } - - [Constructible(AccessLevel.Developer)] - public ProximitySpawner(int amount, int minDelay, int maxDelay, int team, int homeRange, int triggerRange, - string spawnMessage, bool instantFlag, string spawnName) - : base(amount, minDelay, maxDelay, team, homeRange, spawnName) - { - TriggerRange = triggerRange; - SpawnMessage = TextDefinition.Parse(spawnMessage); - InstantFlag = instantFlag; - } - - [Constructible(AccessLevel.Developer)] - public ProximitySpawner(int amount, TimeSpan minDelay, TimeSpan maxDelay, int team, int homeRange, - params string[] spawnedNames) - : base(amount, minDelay, maxDelay, team, homeRange, spawnedNames) - { - } - - [Constructible(AccessLevel.Developer)] - public ProximitySpawner(int amount, TimeSpan minDelay, TimeSpan maxDelay, int team, int homeRange, int triggerRange, - TextDefinition spawnMessage, bool instantFlag, params string[] spawnedNames) - : base(amount, minDelay, maxDelay, team, homeRange, spawnedNames) - { - TriggerRange = triggerRange; - SpawnMessage = spawnMessage; - InstantFlag = instantFlag; - } - - public ProximitySpawner(DynamicJson json, JsonSerializerOptions options) : base(json, options) - { - json.GetProperty("triggerRange", options, out int triggerRange); - json.GetProperty("spawnMessage", options, out TextDefinition spawnMessage); - json.GetProperty("instant", options, out bool instant); - - TriggerRange = triggerRange; - SpawnMessage = spawnMessage; - InstantFlag = instant; - } - - public ProximitySpawner(Serial serial) - : base(serial) - { - } - - [CommandProperty(AccessLevel.Developer)] - public int TriggerRange { get; set; } - - [CommandProperty(AccessLevel.Developer)] - public TextDefinition SpawnMessage { get; set; } - - [CommandProperty(AccessLevel.Developer)] - public bool InstantFlag { get; set; } - - public override string DefaultName => "Proximity Spawner"; - - public override bool HandlesOnMovement => true; - - public override void DoTimer(TimeSpan delay) - { - if (!Running) - return; - - End = DateTime.UtcNow + delay; - } - - public override void Respawn() - { - RemoveSpawns(); - - End = DateTime.UtcNow; - } - - public virtual bool ValidTrigger(Mobile m) - { - if (m is BaseCreature bc && (bc.IsDeadBondedPet || !(bc.Controlled || bc.Summoned))) - return false; - - return m.AccessLevel == AccessLevel.Player && (m.Player || (m.Alive && !m.Hidden && m.CanBeDamaged())); - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (!Running) - return; - - if (IsEmpty && End <= DateTime.UtcNow && m.InRange(GetWorldLocation(), TriggerRange) && - m.Location != oldLocation && ValidTrigger(m)) - { - TextDefinition.SendMessageTo(m, SpawnMessage); - - DoTimer(); - Spawn(); - - if (InstantFlag) - foreach (ISpawnable spawned in Spawned.Keys) - if (spawned is Mobile mobile) - mobile.Combatant = m; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(TriggerRange); - TextDefinition.Serialize(writer, SpawnMessage); - writer.Write(InstantFlag); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - TriggerRange = reader.ReadInt(); - SpawnMessage = TextDefinition.Deserialize(reader); - InstantFlag = reader.ReadBool(); - } - } -} +using System; +using System.Text.Json; +using Server.Json; +using Server.Mobiles; + +namespace Server.Engines.Spawners +{ + public class ProximitySpawner : Spawner + { + [Constructible(AccessLevel.Developer)] + public ProximitySpawner() + { + } + + [Constructible(AccessLevel.Developer)] + public ProximitySpawner(string spawnName) + : base(spawnName) + { + } + + [Constructible(AccessLevel.Developer)] + public ProximitySpawner(int amount, int minDelay, int maxDelay, int team, int homeRange, string spawnName) + : base(amount, minDelay, maxDelay, team, homeRange, spawnName) + { + } + + [Constructible(AccessLevel.Developer)] + public ProximitySpawner( + int amount, int minDelay, int maxDelay, int team, int homeRange, int triggerRange, + string spawnMessage, bool instantFlag, string spawnName + ) + : base(amount, minDelay, maxDelay, team, homeRange, spawnName) + { + TriggerRange = triggerRange; + SpawnMessage = TextDefinition.Parse(spawnMessage); + InstantFlag = instantFlag; + } + + [Constructible(AccessLevel.Developer)] + public ProximitySpawner( + int amount, TimeSpan minDelay, TimeSpan maxDelay, int team, int homeRange, + params string[] spawnedNames + ) + : base(amount, minDelay, maxDelay, team, homeRange, spawnedNames) + { + } + + [Constructible(AccessLevel.Developer)] + public ProximitySpawner( + int amount, TimeSpan minDelay, TimeSpan maxDelay, int team, int homeRange, int triggerRange, + TextDefinition spawnMessage, bool instantFlag, params string[] spawnedNames + ) + : base(amount, minDelay, maxDelay, team, homeRange, spawnedNames) + { + TriggerRange = triggerRange; + SpawnMessage = spawnMessage; + InstantFlag = instantFlag; + } + + public ProximitySpawner(DynamicJson json, JsonSerializerOptions options) : base(json, options) + { + json.GetProperty("triggerRange", options, out int triggerRange); + json.GetProperty("spawnMessage", options, out TextDefinition spawnMessage); + json.GetProperty("instant", options, out bool instant); + + TriggerRange = triggerRange; + SpawnMessage = spawnMessage; + InstantFlag = instant; + } + + public ProximitySpawner(Serial serial) + : base(serial) + { + } + + [CommandProperty(AccessLevel.Developer)] + public int TriggerRange { get; set; } + + [CommandProperty(AccessLevel.Developer)] + public TextDefinition SpawnMessage { get; set; } + + [CommandProperty(AccessLevel.Developer)] + public bool InstantFlag { get; set; } + + public override string DefaultName => "Proximity Spawner"; + + public override bool HandlesOnMovement => true; + + public override void DoTimer(TimeSpan delay) + { + if (!Running) + return; + + End = DateTime.UtcNow + delay; + } + + public override void Respawn() + { + RemoveSpawns(); + + End = DateTime.UtcNow; + } + + public virtual bool ValidTrigger(Mobile m) + { + if (m is BaseCreature bc && (bc.IsDeadBondedPet || !(bc.Controlled || bc.Summoned))) + return false; + + return m.AccessLevel == AccessLevel.Player && (m.Player || m.Alive && !m.Hidden && m.CanBeDamaged()); + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (!Running) + return; + + if (IsEmpty && End <= DateTime.UtcNow && m.InRange(GetWorldLocation(), TriggerRange) && + m.Location != oldLocation && ValidTrigger(m)) + { + TextDefinition.SendMessageTo(m, SpawnMessage); + + DoTimer(); + Spawn(); + + if (InstantFlag) + foreach (var spawned in Spawned.Keys) + if (spawned is Mobile mobile) + mobile.Combatant = m; + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(TriggerRange); + TextDefinition.Serialize(writer, SpawnMessage); + writer.Write(InstantFlag); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + TriggerRange = reader.ReadInt(); + SpawnMessage = TextDefinition.Deserialize(reader); + InstantFlag = reader.ReadBool(); + } + } +} diff --git a/Projects/UOContent/Engines/Spawners/RegionSpawner.cs b/Projects/UOContent/Engines/Spawners/RegionSpawner.cs index d07e59019..83bf2f714 100644 --- a/Projects/UOContent/Engines/Spawners/RegionSpawner.cs +++ b/Projects/UOContent/Engines/Spawners/RegionSpawner.cs @@ -1,152 +1,164 @@ -using System; -using System.Text.Json; -using Server.Json; -using Server.Regions; - -namespace Server.Engines.Spawners -{ - public class RegionSpawner : Spawner - { - private BaseRegion m_SpawnRegion; - - [CommandProperty(AccessLevel.Developer)] - public BaseRegion SpawnRegion - { - get => m_SpawnRegion; - set - { - m_SpawnRegion = value; - m_SpawnRegion?.InitRectangles(); - - InvalidateProperties(); - } - } - - [Constructible(AccessLevel.Developer)] - public RegionSpawner() - { - } - - [Constructible(AccessLevel.Developer)] - public RegionSpawner(string spawnedName) : base(spawnedName) - { - } - - [Constructible(AccessLevel.Developer)] - public RegionSpawner(int amount, int minDelay, int maxDelay, int team, int homeRange, - params string[] spawnedNames) : this(amount, TimeSpan.FromMinutes(minDelay), TimeSpan.FromMinutes(maxDelay), - team, homeRange, spawnedNames) - { - } - - [Constructible(AccessLevel.Developer)] - public RegionSpawner(int amount, TimeSpan minDelay, TimeSpan maxDelay, int team, int homeRange, - params string[] spawnedNames) : base(amount, minDelay, maxDelay, team, homeRange, spawnedNames) - { - } - - public RegionSpawner(DynamicJson json, JsonSerializerOptions options) : base(json, options) - { - json.GetProperty("map", options, out Map map); - json.GetProperty("region", options, out string spawnRegion); - - m_SpawnRegion = Region.Find(spawnRegion, map) as BaseRegion; - m_SpawnRegion?.InitRectangles(); - } - - public RegionSpawner(Serial serial) : base(serial) - { - } - - public override void GetSpawnerProperties(ObjectPropertyList list) - { - base.GetSpawnerProperties(list); - - if (Running && m_SpawnRegion != null) list.Add(1076228, "region:\t{0}", m_SpawnRegion.Name); // ~1_DUMMY~ ~2_DUMMY~ - } - - public override Point3D GetSpawnPosition(ISpawnable spawned, Map map) - { - if (m_SpawnRegion == null || map == null || map == Map.Internal || map != m_SpawnRegion.Map || m_SpawnRegion.TotalWeight <= 0) - return Location; - - bool waterMob, waterOnlyMob; - - if (spawned is Mobile mob) - { - waterMob = mob.CanSwim; - waterOnlyMob = mob.CanSwim && mob.CantWalk; - } - else - { - waterMob = false; - waterOnlyMob = false; - } - - // Try 10 times to find a valid location. - for (int i = 0; i < 10; i++) - { - int rand = Utility.Random(m_SpawnRegion.TotalWeight); - - int x = int.MinValue; - int y = int.MinValue; - - for (int j = 0; j < m_SpawnRegion.RectangleWeights.Length; j++) - { - int curWeight = m_SpawnRegion.RectangleWeights[j]; - - if (rand < curWeight) - { - Rectangle3D rect = m_SpawnRegion.Rectangles[j]; - - x = rect.Start.X + rand % rect.Width; - y = rect.Start.Y + rand / rect.Width; - - break; - } - - rand -= curWeight; - } - - int mapZ = map.GetAverageZ(x, y); - - if (waterMob) - { - if (IsValidWater(map, x, y, Z)) - return new Point3D(x, y, Z); - if (IsValidWater(map, x, y, mapZ)) - return new Point3D(x, y, mapZ); - } - - if (!waterOnlyMob) - { - if (map.CanSpawnMobile(x, y, Z)) - return new Point3D(x, y, Z); - if (map.CanSpawnMobile(x, y, mapZ)) - return new Point3D(x, y, mapZ); - } - } - - return HomeLocation; - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_SpawnRegion = Region.Find(reader.ReadString(), Map) as BaseRegion; - m_SpawnRegion?.InitRectangles(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_SpawnRegion?.Name); - } - } -} +using System; +using System.Text.Json; +using Server.Json; +using Server.Regions; + +namespace Server.Engines.Spawners +{ + public class RegionSpawner : Spawner + { + private BaseRegion m_SpawnRegion; + + [Constructible(AccessLevel.Developer)] + public RegionSpawner() + { + } + + [Constructible(AccessLevel.Developer)] + public RegionSpawner(string spawnedName) : base(spawnedName) + { + } + + [Constructible(AccessLevel.Developer)] + public RegionSpawner( + int amount, int minDelay, int maxDelay, int team, int homeRange, + params string[] spawnedNames + ) : this( + amount, + TimeSpan.FromMinutes(minDelay), + TimeSpan.FromMinutes(maxDelay), + team, + homeRange, + spawnedNames + ) + { + } + + [Constructible(AccessLevel.Developer)] + public RegionSpawner( + int amount, TimeSpan minDelay, TimeSpan maxDelay, int team, int homeRange, + params string[] spawnedNames + ) : base(amount, minDelay, maxDelay, team, homeRange, spawnedNames) + { + } + + public RegionSpawner(DynamicJson json, JsonSerializerOptions options) : base(json, options) + { + json.GetProperty("map", options, out Map map); + json.GetProperty("region", options, out string spawnRegion); + + m_SpawnRegion = Region.Find(spawnRegion, map) as BaseRegion; + m_SpawnRegion?.InitRectangles(); + } + + public RegionSpawner(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.Developer)] + public BaseRegion SpawnRegion + { + get => m_SpawnRegion; + set + { + m_SpawnRegion = value; + m_SpawnRegion?.InitRectangles(); + + InvalidateProperties(); + } + } + + public override void GetSpawnerProperties(ObjectPropertyList list) + { + base.GetSpawnerProperties(list); + + if (Running && m_SpawnRegion != null) + list.Add(1076228, "region:\t{0}", m_SpawnRegion.Name); // ~1_DUMMY~ ~2_DUMMY~ + } + + public override Point3D GetSpawnPosition(ISpawnable spawned, Map map) + { + if (m_SpawnRegion == null || map == null || map == Map.Internal || map != m_SpawnRegion.Map || + m_SpawnRegion.TotalWeight <= 0) + return Location; + + bool waterMob, waterOnlyMob; + + if (spawned is Mobile mob) + { + waterMob = mob.CanSwim; + waterOnlyMob = mob.CanSwim && mob.CantWalk; + } + else + { + waterMob = false; + waterOnlyMob = false; + } + + // Try 10 times to find a valid location. + for (var i = 0; i < 10; i++) + { + var rand = Utility.Random(m_SpawnRegion.TotalWeight); + + var x = int.MinValue; + var y = int.MinValue; + + for (var j = 0; j < m_SpawnRegion.RectangleWeights.Length; j++) + { + var curWeight = m_SpawnRegion.RectangleWeights[j]; + + if (rand < curWeight) + { + var rect = m_SpawnRegion.Rectangles[j]; + + x = rect.Start.X + rand % rect.Width; + y = rect.Start.Y + rand / rect.Width; + + break; + } + + rand -= curWeight; + } + + var mapZ = map.GetAverageZ(x, y); + + if (waterMob) + { + if (IsValidWater(map, x, y, Z)) + return new Point3D(x, y, Z); + if (IsValidWater(map, x, y, mapZ)) + return new Point3D(x, y, mapZ); + } + + if (!waterOnlyMob) + { + if (map.CanSpawnMobile(x, y, Z)) + return new Point3D(x, y, Z); + if (map.CanSpawnMobile(x, y, mapZ)) + return new Point3D(x, y, mapZ); + } + } + + return HomeLocation; + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_SpawnRegion = Region.Find(reader.ReadString(), Map) as BaseRegion; + m_SpawnRegion?.InitRectangles(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_SpawnRegion?.Name); + } + } +} diff --git a/Projects/UOContent/Engines/Spawners/Spawner.cs b/Projects/UOContent/Engines/Spawners/Spawner.cs index eee0a8e54..13671f567 100644 --- a/Projects/UOContent/Engines/Spawners/Spawner.cs +++ b/Projects/UOContent/Engines/Spawners/Spawner.cs @@ -1,139 +1,149 @@ -using System; -using System.Text.Json; -using Server.Json; - -namespace Server.Engines.Spawners -{ - public class Spawner : BaseSpawner - { - public static bool IsValidWater(Map map, int x, int y, int z) - { - if (!Region.Find(new Point3D(x, y, z), map).AllowSpawn() || !map.CanFit(x, y, z, 16, false, true, false)) - return false; - - LandTile landTile = map.Tiles.GetLandTile(x, y); - - if (landTile.Z == z && (TileData.LandTable[landTile.ID & TileData.MaxLandValue].Flags & TileFlag.Wet) != 0) - return true; - - StaticTile[] staticTiles = map.Tiles.GetStaticTiles(x, y, true); - - for (int i = 0; i < staticTiles.Length; ++i) - { - StaticTile staticTile = staticTiles[i]; - - if (staticTile.Z == z && - (TileData.ItemTable[staticTile.ID & TileData.MaxItemValue].Flags & TileFlag.Wet) != 0) - return true; - } - - return false; - } - - [Constructible(AccessLevel.Developer)] - public Spawner() - { - } - - [Constructible(AccessLevel.Developer)] - public Spawner(string spawnedName) : base(spawnedName) - { - } - - [Constructible(AccessLevel.Developer)] - public Spawner(int amount, int minDelay, int maxDelay, int team, int homeRange, - params string[] spawnedNames) : this(amount, TimeSpan.FromMinutes(minDelay), TimeSpan.FromMinutes(maxDelay), - team, homeRange, spawnedNames) - { - } - - [Constructible(AccessLevel.Developer)] - public Spawner(int amount, TimeSpan minDelay, TimeSpan maxDelay, int team, int homeRange, - params string[] spawnedNames) : base(amount, minDelay, maxDelay, team, homeRange, spawnedNames) - { - } - - public Spawner(DynamicJson json, JsonSerializerOptions options) : base(json, options) - { - } - - public Spawner(Serial serial) : base(serial) - { - } - - /* - public override bool OnDefragSpawn(ISpawnable spawned, bool remove) - { - // To despawn a mob that was lured 4x away from its spawner - // TODO: Move this to a config - if (spawned is BaseCreature c && c.Combatant == null && c.GetDistanceToSqrt( Location ) > c.RangeHome * 4) - { - c.Delete(); - remove = true; - } - - return base.OnDefragSpawn(entry, spawned, remove); - } - */ - - public override Point3D GetSpawnPosition(ISpawnable spawned, Map map) - { - if (map == null || map == Map.Internal) - return Location; - - bool waterMob, waterOnlyMob; - - if (spawned is Mobile mob) - { - waterMob = mob.CanSwim; - waterOnlyMob = mob.CanSwim && mob.CantWalk; - } - else - { - waterMob = false; - waterOnlyMob = false; - } - - // Try 10 times to find a valid location. - for (int i = 0; i < 10; i++) - { - int x = Location.X + (Utility.Random(HomeRange * 2 + 1) - HomeRange); - int y = Location.Y + (Utility.Random(HomeRange * 2 + 1) - HomeRange); - - int mapZ = map.GetAverageZ(x, y); - - if (waterMob) - { - if (IsValidWater(map, x, y, Z)) - return new Point3D(x, y, Z); - if (IsValidWater(map, x, y, mapZ)) - return new Point3D(x, y, mapZ); - } - - if (!waterOnlyMob) - { - if (map.CanSpawnMobile(x, y, Z)) - return new Point3D(x, y, Z); - if (map.CanSpawnMobile(x, y, mapZ)) - return new Point3D(x, y, mapZ); - } - } - - return HomeLocation; - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - } -} +using System; +using System.Text.Json; +using Server.Json; + +namespace Server.Engines.Spawners +{ + public class Spawner : BaseSpawner + { + [Constructible(AccessLevel.Developer)] + public Spawner() + { + } + + [Constructible(AccessLevel.Developer)] + public Spawner(string spawnedName) : base(spawnedName) + { + } + + [Constructible(AccessLevel.Developer)] + public Spawner( + int amount, int minDelay, int maxDelay, int team, int homeRange, + params string[] spawnedNames + ) : this( + amount, + TimeSpan.FromMinutes(minDelay), + TimeSpan.FromMinutes(maxDelay), + team, + homeRange, + spawnedNames + ) + { + } + + [Constructible(AccessLevel.Developer)] + public Spawner( + int amount, TimeSpan minDelay, TimeSpan maxDelay, int team, int homeRange, + params string[] spawnedNames + ) : base(amount, minDelay, maxDelay, team, homeRange, spawnedNames) + { + } + + public Spawner(DynamicJson json, JsonSerializerOptions options) : base(json, options) + { + } + + public Spawner(Serial serial) : base(serial) + { + } + + public static bool IsValidWater(Map map, int x, int y, int z) + { + if (!Region.Find(new Point3D(x, y, z), map).AllowSpawn() || !map.CanFit(x, y, z, 16, false, true, false)) + return false; + + var landTile = map.Tiles.GetLandTile(x, y); + + if (landTile.Z == z && (TileData.LandTable[landTile.ID & TileData.MaxLandValue].Flags & TileFlag.Wet) != 0) + return true; + + var staticTiles = map.Tiles.GetStaticTiles(x, y, true); + + for (var i = 0; i < staticTiles.Length; ++i) + { + var staticTile = staticTiles[i]; + + if (staticTile.Z == z && + (TileData.ItemTable[staticTile.ID & TileData.MaxItemValue].Flags & TileFlag.Wet) != 0) + return true; + } + + return false; + } + + /* + public override bool OnDefragSpawn(ISpawnable spawned, bool remove) + { + // To despawn a mob that was lured 4x away from its spawner + // TODO: Move this to a config + if (spawned is BaseCreature c && c.Combatant == null && c.GetDistanceToSqrt( Location ) > c.RangeHome * 4) + { + c.Delete(); + remove = true; + } + + return base.OnDefragSpawn(entry, spawned, remove); + } + */ + + public override Point3D GetSpawnPosition(ISpawnable spawned, Map map) + { + if (map == null || map == Map.Internal) + return Location; + + bool waterMob, waterOnlyMob; + + if (spawned is Mobile mob) + { + waterMob = mob.CanSwim; + waterOnlyMob = mob.CanSwim && mob.CantWalk; + } + else + { + waterMob = false; + waterOnlyMob = false; + } + + // Try 10 times to find a valid location. + for (var i = 0; i < 10; i++) + { + var x = Location.X + (Utility.Random(HomeRange * 2 + 1) - HomeRange); + var y = Location.Y + (Utility.Random(HomeRange * 2 + 1) - HomeRange); + + var mapZ = map.GetAverageZ(x, y); + + if (waterMob) + { + if (IsValidWater(map, x, y, Z)) + return new Point3D(x, y, Z); + if (IsValidWater(map, x, y, mapZ)) + return new Point3D(x, y, mapZ); + } + + if (!waterOnlyMob) + { + if (map.CanSpawnMobile(x, y, Z)) + return new Point3D(x, y, Z); + if (map.CanSpawnMobile(x, y, mapZ)) + return new Point3D(x, y, mapZ); + } + } + + return HomeLocation; + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + } + } +} diff --git a/Projects/UOContent/Engines/Spawners/SpawnerEntry.cs b/Projects/UOContent/Engines/Spawners/SpawnerEntry.cs index 28c0532e2..683ae7686 100644 --- a/Projects/UOContent/Engines/Spawners/SpawnerEntry.cs +++ b/Projects/UOContent/Engines/Spawners/SpawnerEntry.cs @@ -1,113 +1,106 @@ -using System.Collections.Generic; -using System.Text.Json.Serialization; -using Server.Mobiles; - -namespace Server.Engines.Spawners -{ - public class SpawnerEntry - { - public SpawnerEntry() => Spawned = new List(); - - public SpawnerEntry(string name, int probability, int maxcount) : this() - { - SpawnedName = name; - SpawnedProbability = probability; - SpawnedMaxCount = maxcount; - } - - public SpawnerEntry(BaseSpawner parent, IGenericReader reader) - { - int version = reader.ReadInt(); - - SpawnedName = reader.ReadString(); - SpawnedProbability = reader.ReadInt(); - SpawnedMaxCount = reader.ReadInt(); - - Properties = reader.ReadString(); - Parameters = reader.ReadString(); - - int count = reader.ReadInt(); - - Spawned = new List(count); - - for (int i = 0; i < count; ++i) - // IEntity e = World.FindEntity( reader.ReadInt() ); - - if (reader.ReadEntity() is ISpawnable e) - { - e.Spawner = parent; - - if (e is BaseCreature creature) - creature.RemoveIfUntamed = true; - - Spawned.Add(e); - - if (!parent.Spawned.ContainsKey(e)) - parent.Spawned.Add(e, this); - } - } - - [JsonPropertyName("probability")] - public int SpawnedProbability { get; set; } - - [JsonPropertyName("maxCount")] - public int SpawnedMaxCount { get; set; } - - [JsonPropertyName("name")] - public string SpawnedName { get; set; } - - [JsonPropertyName("properties")] - public string Properties { get; set; } - - [JsonPropertyName("parameters")] - public string Parameters { get; set; } - - [JsonIgnore] - public EntryFlags Valid { get; set; } - - [JsonIgnore] - public List Spawned { get; } - - public bool IsFull => Spawned.Count >= SpawnedMaxCount; - - public void Serialize(IGenericWriter writer) - { - writer.Write(0); // version - - writer.Write(SpawnedName); - writer.Write(SpawnedProbability); - writer.Write(SpawnedMaxCount); - - writer.Write(Properties); - writer.Write(Parameters); - - writer.Write(Spawned.Count); - - for (int i = 0; i < Spawned.Count; ++i) - { - object o = Spawned[i]; - - if (o is Item item) - writer.Write(item); - else if (o is Mobile mobile) - writer.Write(mobile); - else - writer.Write(Serial.MinusOne); - } - } - - public void Defrag(BaseSpawner parent) - { - for (int i = 0; i < Spawned.Count; ++i) - { - ISpawnable spawned = Spawned[i]; - - if (parent.OnDefragSpawn(spawned, false)) - { - Spawned.RemoveAt(i--); - parent.Spawned.Remove(spawned); - } - } - } - } -} +using System.Collections.Generic; +using System.Text.Json.Serialization; +using Server.Mobiles; + +namespace Server.Engines.Spawners +{ + public class SpawnerEntry + { + public SpawnerEntry() => Spawned = new List(); + + public SpawnerEntry(string name, int probability, int maxcount) : this() + { + SpawnedName = name; + SpawnedProbability = probability; + SpawnedMaxCount = maxcount; + } + + public SpawnerEntry(BaseSpawner parent, IGenericReader reader) + { + var version = reader.ReadInt(); + + SpawnedName = reader.ReadString(); + SpawnedProbability = reader.ReadInt(); + SpawnedMaxCount = reader.ReadInt(); + + Properties = reader.ReadString(); + Parameters = reader.ReadString(); + + var count = reader.ReadInt(); + + Spawned = new List(count); + + for (var i = 0; i < count; ++i) + // IEntity e = World.FindEntity( reader.ReadInt() ); + + if (reader.ReadEntity() is ISpawnable e) + { + e.Spawner = parent; + + if (e is BaseCreature creature) + creature.RemoveIfUntamed = true; + + Spawned.Add(e); + + if (!parent.Spawned.ContainsKey(e)) + parent.Spawned.Add(e, this); + } + } + + [JsonPropertyName("probability")] public int SpawnedProbability { get; set; } + + [JsonPropertyName("maxCount")] public int SpawnedMaxCount { get; set; } + + [JsonPropertyName("name")] public string SpawnedName { get; set; } + + [JsonPropertyName("properties")] public string Properties { get; set; } + + [JsonPropertyName("parameters")] public string Parameters { get; set; } + + [JsonIgnore] public EntryFlags Valid { get; set; } + + [JsonIgnore] public List Spawned { get; } + + public bool IsFull => Spawned.Count >= SpawnedMaxCount; + + public void Serialize(IGenericWriter writer) + { + writer.Write(0); // version + + writer.Write(SpawnedName); + writer.Write(SpawnedProbability); + writer.Write(SpawnedMaxCount); + + writer.Write(Properties); + writer.Write(Parameters); + + writer.Write(Spawned.Count); + + for (var i = 0; i < Spawned.Count; ++i) + { + object o = Spawned[i]; + + if (o is Item item) + writer.Write(item); + else if (o is Mobile mobile) + writer.Write(mobile); + else + writer.Write(Serial.MinusOne); + } + } + + public void Defrag(BaseSpawner parent) + { + for (var i = 0; i < Spawned.Count; ++i) + { + var spawned = Spawned[i]; + + if (parent.OnDefragSpawn(spawned, false)) + { + Spawned.RemoveAt(i--); + parent.Spawned.Remove(spawned); + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Spawners/SpawnerGump.cs b/Projects/UOContent/Engines/Spawners/SpawnerGump.cs index 258dd3c68..b16dabe23 100644 --- a/Projects/UOContent/Engines/Spawners/SpawnerGump.cs +++ b/Projects/UOContent/Engines/Spawners/SpawnerGump.cs @@ -1,295 +1,325 @@ -using System; -using System.Collections.Generic; -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.Spawners -{ - public class SpawnerGump : Gump - { - private SpawnerEntry m_Entry; - private int m_Page; - private readonly BaseSpawner m_Spawner; - - public SpawnerGump(BaseSpawner spawner, SpawnerEntry focusentry = null, int page = 0) : base(50, 50) - { - m_Spawner = spawner; - m_Entry = focusentry; - m_Page = page; - - AddPage(0); - - AddBackground(0, 0, 343, 371 + (m_Entry != null ? 44 : 0), 5054); - - AddHtml(95, 1, 250, 20, "Creatures List"); - AddHtml(245, 1, 250, 20, "#"); - AddHtml(282, 1, 250, 20, "Prb"); - - // AddLabel( 95, 1, 0, "Creatures List" ); - - int offset = 0; - - for (int i = 0; i < 13; i++) - { - int textindex = i * 5; - int entryindex = m_Page * 13 + i; - - SpawnerEntry entry = null; - - if (entryindex < spawner.Entries.Count) - entry = m_Spawner.Entries[entryindex]; - - if (entry == null || m_Entry != entry) - AddButton(5, 22 * i + 21 + offset, entry != null ? 0xFBA : 0xFA5, entry != null ? 0xFBC : 0xFA7, - GetButtonID(2, i * 2)); // Expand - else - AddButton(5, 22 * i + 21 + offset, 0xFBB, 0xFBC, - GetButtonID(2, i * 2)); // Unexpand - - AddButton(38, 22 * i + 21 + offset, 0xFA2, 0xFA4, GetButtonID(2, 1 + i * 2)); // Delete - - AddImageTiled(71, 22 * i + 20 + offset, 161, 23, 0xA40); // creature text box - AddImageTiled(72, 22 * i + 21 + offset, 159, 21, 0xBBC); // creature text box - - AddImageTiled(235, 22 * i + 20 + offset, 35, 23, 0xA40); // maxcount text box - AddImageTiled(236, 22 * i + 21 + offset, 33, 21, 0xBBC); // maxcount text box - - AddImageTiled(273, 22 * i + 20 + offset, 35, 23, 0xA40); // probability text box - AddImageTiled(274, 22 * i + 21 + offset, 33, 21, 0xBBC); // probability text box - - string name = ""; - string probability = ""; - string maxcount = ""; - EntryFlags flags = EntryFlags.None; - - if (entry != null) - { - name = entry.SpawnedName; - probability = entry.SpawnedProbability.ToString(); - maxcount = entry.SpawnedMaxCount.ToString(); - flags = entry.Valid; - - AddLabel(315, 22 * i + 20 + offset, 0, spawner.CountSpawns(entry).ToString()); - } - - AddTextEntry(75, 22 * i + 21 + offset, 156, 21, (flags & EntryFlags.InvalidType) != 0 ? 33 : 0, textindex, - name); // creature - AddTextEntry(239, 22 * i + 21 + offset, 30, 21, 0, textindex + 1, maxcount); // max count - AddTextEntry(277, 22 * i + 21 + offset, 30, 21, 0, textindex + 2, probability); // probability - - if (entry != null && m_Entry == entry) - { - AddLabel(5, 22 * i + 42, 0x384, "Params"); - AddImageTiled(55, 22 * i + 42, 253, 23, 0xA40); // Parameters - AddImageTiled(56, 22 * i + 43, 251, 21, 0xBBC); // Parameters - - AddLabel(5, 22 * i + 64, 0x384, "Props"); - AddImageTiled(55, 22 * i + 64, 253, 23, 0xA40); // Properties - AddImageTiled(56, 22 * i + 65, 251, 21, 0xBBC); // Properties - - AddTextEntry(59, 22 * i + 42, 248, 21, (flags & EntryFlags.InvalidParams) != 0 ? 33 : 0, textindex + 3, - entry.Parameters); // parameters - AddTextEntry(59, 22 * i + 62, 248, 21, (flags & EntryFlags.InvalidProps) != 0 ? 33 : 0, textindex + 4, - entry.Properties); // properties - - offset += 44; - } - } - - AddButton(5, 347 + offset, 0xFB1, 0xFB3, 0); - AddLabel(38, 347 + offset, 0x384, "Cancel"); - - AddButton(5, 325 + offset, 0xFB7, 0xFB9, GetButtonID(1, 2)); - AddLabel(38, 325 + offset, 0x384, "Okay"); - - AddButton(110, 325 + offset, 0xFB4, 0xFB6, GetButtonID(1, 3)); - AddLabel(143, 325 + offset, 0x384, "Bring to Home"); - - AddButton(110, 347 + offset, 0xFA8, 0xFAA, GetButtonID(1, 4)); - AddLabel(143, 347 + offset, 0x384, "Total Respawn"); - - AddButton(253, 325 + offset, 0xFB7, 0xFB9, GetButtonID(1, 5)); - AddLabel(286, 325 + offset, 0x384, "Apply"); - - if (m_Page > 0) - AddButton(276, 308 + offset, 0x15E3, 0x15E7, GetButtonID(1, 0)); - else - AddImage(276, 308 + offset, 0x25EA); - - if ((m_Page + 1) * 13 <= m_Spawner.Entries.Count) - AddButton(293, 308 + offset, 0x15E1, 0x15E5, GetButtonID(1, 1)); - else - AddImage(293, 308 + offset, 0x25E6); - } - - public int GetButtonID(int type, int index) => 1 + index * 10 + type; - - public void CreateArray(RelayInfo info, Mobile from, BaseSpawner spawner) - { - int ocount = spawner.Entries.Count; - - List rementries = new List(); - - for (int i = 0; i < 13; i++) - { - int index = i * 5; - int entryindex = m_Page * 13 + i; - - TextRelay cte = info.GetTextEntry(index); - TextRelay mte = info.GetTextEntry(index + 1); - TextRelay poste = info.GetTextEntry(index + 2); - TextRelay parmte = info.GetTextEntry(index + 3); - TextRelay propte = info.GetTextEntry(index + 4); - - if (cte == null) - continue; - - string str = cte.Text.Trim().ToLower(); - - if (str.Length > 0) - { - Type type = AssemblyHandler.FindFirstTypeForName(str); - - if (type == null) - { - from.SendMessage("{0} is not a valid type name for entry #{1}.", str, i); - return; - } - - SpawnerEntry entry; - - if (entryindex < ocount) - { - entry = spawner.Entries[entryindex]; - entry.SpawnedName = str; - - if (mte != null) - entry.SpawnedMaxCount = Utility.ToInt32(mte.Text.Trim()); - - if (poste != null) - entry.SpawnedProbability = Utility.ToInt32(poste.Text.Trim()); - } - else - { - int maxcount = 1; - int probcount = 100; - - if (mte != null) - maxcount = Utility.ToInt32(mte.Text.Trim()); - - if (poste != null) - probcount = Utility.ToInt32(poste.Text.Trim()); - - entry = spawner.AddEntry(str, probcount, maxcount); - } - - if (parmte != null) - entry.Parameters = parmte.Text.Trim(); - - if (propte != null) - entry.Properties = propte.Text.Trim(); - } - else if (entryindex < ocount && spawner.Entries[entryindex] != null) - { - rementries.Add(spawner.Entries[entryindex]); - } - } - - for (int i = 0; i < rementries.Count; i++) - spawner.RemoveEntry(rementries[i]); - - if (ocount == 0 && spawner.Entries.Count > 0) - spawner.Start(); - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (m_Spawner.Deleted) - return; - - int val = info.ButtonID - 1; - - if (val < 0) - return; - - int type = val % 10; - int index = val / 10; - - switch (type) - { - case 0: // Cancel - return; - case 1: - { - switch (index) - { - case 0: - { - if (m_Spawner.Entries != null && m_Page > 0) - { - m_Page--; - m_Entry = null; - } - - break; - } - case 1: - { - if ((m_Page + 1) * 13 <= m_Spawner.Entries?.Count) - { - m_Page++; - m_Entry = null; - } - - break; - } - case 2: // Okay - { - CreateArray(info, state.Mobile, m_Spawner); - return; - } - case 3: - { - m_Spawner.BringToHome(); - break; - } - case 4: // Complete respawn - { - m_Spawner.Respawn(); - break; - } - case 5: - { - CreateArray(info, state.Mobile, m_Spawner); - break; - } - } - - break; - } - case 2: - { - int entryindex = index / 2 + m_Page * 13; - int buttontype = index % 2; - - if (entryindex >= 0 && entryindex < m_Spawner.Entries.Count) - { - SpawnerEntry entry = m_Spawner.Entries[entryindex]; - if (buttontype == 0) // Spawn creature - m_Entry = m_Entry != entry ? entry : null; - else // Remove creatures - m_Spawner.RemoveSpawn(entryindex); - } - - CreateArray(info, state.Mobile, m_Spawner); - break; - } - } - - if (m_Entry != null && m_Spawner.Entries?.Contains(m_Entry) == true) - state.Mobile.SendGump(new SpawnerGump(m_Spawner, m_Entry, m_Page)); - else - state.Mobile.SendGump(new SpawnerGump(m_Spawner, null, m_Page)); - } - } -} +using System.Collections.Generic; +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.Spawners +{ + public class SpawnerGump : Gump + { + private readonly BaseSpawner m_Spawner; + private SpawnerEntry m_Entry; + private int m_Page; + + public SpawnerGump(BaseSpawner spawner, SpawnerEntry focusentry = null, int page = 0) : base(50, 50) + { + m_Spawner = spawner; + m_Entry = focusentry; + m_Page = page; + + AddPage(0); + + AddBackground(0, 0, 343, 371 + (m_Entry != null ? 44 : 0), 5054); + + AddHtml(95, 1, 250, 20, "Creatures List"); + AddHtml(245, 1, 250, 20, "#"); + AddHtml(282, 1, 250, 20, "Prb"); + + // AddLabel( 95, 1, 0, "Creatures List" ); + + var offset = 0; + + for (var i = 0; i < 13; i++) + { + var textindex = i * 5; + var entryindex = m_Page * 13 + i; + + SpawnerEntry entry = null; + + if (entryindex < spawner.Entries.Count) + entry = m_Spawner.Entries[entryindex]; + + if (entry == null || m_Entry != entry) + AddButton( + 5, + 22 * i + 21 + offset, + entry != null ? 0xFBA : 0xFA5, + entry != null ? 0xFBC : 0xFA7, + GetButtonID(2, i * 2) + ); // Expand + else + AddButton( + 5, + 22 * i + 21 + offset, + 0xFBB, + 0xFBC, + GetButtonID(2, i * 2) + ); // Unexpand + + AddButton(38, 22 * i + 21 + offset, 0xFA2, 0xFA4, GetButtonID(2, 1 + i * 2)); // Delete + + AddImageTiled(71, 22 * i + 20 + offset, 161, 23, 0xA40); // creature text box + AddImageTiled(72, 22 * i + 21 + offset, 159, 21, 0xBBC); // creature text box + + AddImageTiled(235, 22 * i + 20 + offset, 35, 23, 0xA40); // maxcount text box + AddImageTiled(236, 22 * i + 21 + offset, 33, 21, 0xBBC); // maxcount text box + + AddImageTiled(273, 22 * i + 20 + offset, 35, 23, 0xA40); // probability text box + AddImageTiled(274, 22 * i + 21 + offset, 33, 21, 0xBBC); // probability text box + + var name = ""; + var probability = ""; + var maxcount = ""; + var flags = EntryFlags.None; + + if (entry != null) + { + name = entry.SpawnedName; + probability = entry.SpawnedProbability.ToString(); + maxcount = entry.SpawnedMaxCount.ToString(); + flags = entry.Valid; + + AddLabel(315, 22 * i + 20 + offset, 0, spawner.CountSpawns(entry).ToString()); + } + + AddTextEntry( + 75, + 22 * i + 21 + offset, + 156, + 21, + (flags & EntryFlags.InvalidType) != 0 ? 33 : 0, + textindex, + name + ); // creature + AddTextEntry(239, 22 * i + 21 + offset, 30, 21, 0, textindex + 1, maxcount); // max count + AddTextEntry(277, 22 * i + 21 + offset, 30, 21, 0, textindex + 2, probability); // probability + + if (entry != null && m_Entry == entry) + { + AddLabel(5, 22 * i + 42, 0x384, "Params"); + AddImageTiled(55, 22 * i + 42, 253, 23, 0xA40); // Parameters + AddImageTiled(56, 22 * i + 43, 251, 21, 0xBBC); // Parameters + + AddLabel(5, 22 * i + 64, 0x384, "Props"); + AddImageTiled(55, 22 * i + 64, 253, 23, 0xA40); // Properties + AddImageTiled(56, 22 * i + 65, 251, 21, 0xBBC); // Properties + + AddTextEntry( + 59, + 22 * i + 42, + 248, + 21, + (flags & EntryFlags.InvalidParams) != 0 ? 33 : 0, + textindex + 3, + entry.Parameters + ); // parameters + AddTextEntry( + 59, + 22 * i + 62, + 248, + 21, + (flags & EntryFlags.InvalidProps) != 0 ? 33 : 0, + textindex + 4, + entry.Properties + ); // properties + + offset += 44; + } + } + + AddButton(5, 347 + offset, 0xFB1, 0xFB3, 0); + AddLabel(38, 347 + offset, 0x384, "Cancel"); + + AddButton(5, 325 + offset, 0xFB7, 0xFB9, GetButtonID(1, 2)); + AddLabel(38, 325 + offset, 0x384, "Okay"); + + AddButton(110, 325 + offset, 0xFB4, 0xFB6, GetButtonID(1, 3)); + AddLabel(143, 325 + offset, 0x384, "Bring to Home"); + + AddButton(110, 347 + offset, 0xFA8, 0xFAA, GetButtonID(1, 4)); + AddLabel(143, 347 + offset, 0x384, "Total Respawn"); + + AddButton(253, 325 + offset, 0xFB7, 0xFB9, GetButtonID(1, 5)); + AddLabel(286, 325 + offset, 0x384, "Apply"); + + if (m_Page > 0) + AddButton(276, 308 + offset, 0x15E3, 0x15E7, GetButtonID(1, 0)); + else + AddImage(276, 308 + offset, 0x25EA); + + if ((m_Page + 1) * 13 <= m_Spawner.Entries.Count) + AddButton(293, 308 + offset, 0x15E1, 0x15E5, GetButtonID(1, 1)); + else + AddImage(293, 308 + offset, 0x25E6); + } + + public int GetButtonID(int type, int index) => 1 + index * 10 + type; + + public void CreateArray(RelayInfo info, Mobile from, BaseSpawner spawner) + { + var ocount = spawner.Entries.Count; + + var rementries = new List(); + + for (var i = 0; i < 13; i++) + { + var index = i * 5; + var entryindex = m_Page * 13 + i; + + var cte = info.GetTextEntry(index); + var mte = info.GetTextEntry(index + 1); + var poste = info.GetTextEntry(index + 2); + var parmte = info.GetTextEntry(index + 3); + var propte = info.GetTextEntry(index + 4); + + if (cte == null) + continue; + + var str = cte.Text.Trim().ToLower(); + + if (str.Length > 0) + { + var type = AssemblyHandler.FindFirstTypeForName(str); + + if (type == null) + { + from.SendMessage("{0} is not a valid type name for entry #{1}.", str, i); + return; + } + + SpawnerEntry entry; + + if (entryindex < ocount) + { + entry = spawner.Entries[entryindex]; + entry.SpawnedName = str; + + if (mte != null) + entry.SpawnedMaxCount = Utility.ToInt32(mte.Text.Trim()); + + if (poste != null) + entry.SpawnedProbability = Utility.ToInt32(poste.Text.Trim()); + } + else + { + var maxcount = 1; + var probcount = 100; + + if (mte != null) + maxcount = Utility.ToInt32(mte.Text.Trim()); + + if (poste != null) + probcount = Utility.ToInt32(poste.Text.Trim()); + + entry = spawner.AddEntry(str, probcount, maxcount); + } + + if (parmte != null) + entry.Parameters = parmte.Text.Trim(); + + if (propte != null) + entry.Properties = propte.Text.Trim(); + } + else if (entryindex < ocount && spawner.Entries[entryindex] != null) + { + rementries.Add(spawner.Entries[entryindex]); + } + } + + for (var i = 0; i < rementries.Count; i++) + spawner.RemoveEntry(rementries[i]); + + if (ocount == 0 && spawner.Entries.Count > 0) + spawner.Start(); + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (m_Spawner.Deleted) + return; + + var val = info.ButtonID - 1; + + if (val < 0) + return; + + var type = val % 10; + var index = val / 10; + + switch (type) + { + case 0: // Cancel + return; + case 1: + { + switch (index) + { + case 0: + { + if (m_Spawner.Entries != null && m_Page > 0) + { + m_Page--; + m_Entry = null; + } + + break; + } + case 1: + { + if ((m_Page + 1) * 13 <= m_Spawner.Entries?.Count) + { + m_Page++; + m_Entry = null; + } + + break; + } + case 2: // Okay + { + CreateArray(info, state.Mobile, m_Spawner); + return; + } + case 3: + { + m_Spawner.BringToHome(); + break; + } + case 4: // Complete respawn + { + m_Spawner.Respawn(); + break; + } + case 5: + { + CreateArray(info, state.Mobile, m_Spawner); + break; + } + } + + break; + } + case 2: + { + var entryindex = index / 2 + m_Page * 13; + var buttontype = index % 2; + + if (entryindex >= 0 && entryindex < m_Spawner.Entries.Count) + { + var entry = m_Spawner.Entries[entryindex]; + if (buttontype == 0) // Spawn creature + m_Entry = m_Entry != entry ? entry : null; + else // Remove creatures + m_Spawner.RemoveSpawn(entryindex); + } + + CreateArray(info, state.Mobile, m_Spawner); + break; + } + } + + if (m_Entry != null && m_Spawner.Entries?.Contains(m_Entry) == true) + state.Mobile.SendGump(new SpawnerGump(m_Spawner, m_Entry, m_Page)); + else + state.Mobile.SendGump(new SpawnerGump(m_Spawner, null, m_Page)); + } + } +} diff --git a/Projects/UOContent/Engines/Treasures of Tokuno/BasePigmentsOfTokuno.cs b/Projects/UOContent/Engines/Treasures of Tokuno/BasePigmentsOfTokuno.cs index 84cc4cb27..c8ef4d6ae 100644 --- a/Projects/UOContent/Engines/Treasures of Tokuno/BasePigmentsOfTokuno.cs +++ b/Projects/UOContent/Engines/Treasures of Tokuno/BasePigmentsOfTokuno.cs @@ -1,279 +1,281 @@ -using System; -using Server.Misc; -using Server.Mobiles; -using Server.Targeting; - -namespace Server.Items -{ - public abstract class BasePigmentsOfTokuno : Item, IUsesRemaining - { - private static readonly Type[] m_Glasses = - { - typeof(MaritimeGlasses), - typeof(WizardsGlasses), - typeof(TradeGlasses), - typeof(LyricalGlasses), - typeof(NecromanticGlasses), - typeof(LightOfWayGlasses), - typeof(FoldedSteelGlasses), - typeof(PoisonedGlasses), - typeof(TreasureTrinketGlasses), - typeof(MaceShieldGlasses), - typeof(ArtsGlasses), - typeof(AnthropomorphistGlasses) - }; - - private static readonly Type[] m_Replicas = - { - typeof(ANecromancerShroud), - typeof(BraveKnightOfTheBritannia), - typeof(CaptainJohnsHat), - typeof(DetectiveBoots), - typeof(DjinnisRing), - typeof(EmbroideredOakLeafCloak), - typeof(GuantletsOfAnger), - typeof(LieutenantOfTheBritannianRoyalGuard), - typeof(OblivionsNeedle), - typeof(RoyalGuardSurvivalKnife), - typeof(SamaritanRobe), - typeof(TheMostKnowledgePerson), - typeof(TheRobeOfBritanniaAri), - typeof(AcidProofRobe), - typeof(Calm), - typeof(CrownOfTalKeesh), - typeof(FangOfRactus), - typeof(GladiatorsCollar), - typeof(OrcChieftainHelm), - typeof(Pacify), - typeof(Quell), - typeof(ShroudOfDeciet), - typeof(Subdue) - }; - - private static readonly Type[] m_DyableHeritageItems = - { - typeof(ChargerOfTheFallen), - typeof(SamuraiHelm), - typeof(HolySword), - typeof(LeggingsOfEmbers), - typeof(ShaminoCrossbow) - }; - - private TextDefinition m_Label; - - private int m_UsesRemaining; - - public BasePigmentsOfTokuno() : base(0xEFF) - { - Weight = 1.0; - m_UsesRemaining = 1; - } - - public BasePigmentsOfTokuno(int uses) : base(0xEFF) - { - Weight = 1.0; - m_UsesRemaining = uses; - } - - public BasePigmentsOfTokuno(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070933; // Pigments of Tokuno - - protected TextDefinition Label - { - get => m_Label; - set - { - m_Label = value; - InvalidateProperties(); - } - } - - /* DO NOT USE! Only used in serialization of pigments that originally derived from Item */ - - protected bool InheritsItem { get; private set; } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_Label != null && m_Label > 0) - TextDefinition.AddTo(list, m_Label); - - list.Add(1060584, m_UsesRemaining.ToString()); // uses remaining: ~1_val~ - } - - public override void OnDoubleClick(Mobile from) - { - if (IsAccessibleTo(from) && from.InRange(GetWorldLocation(), 3)) - { - from.SendLocalizedMessage(1070929); // Select the artifact or enhanced magic item to dye. - from.BeginTarget(3, false, TargetFlags.None, InternalCallback); - } - else - { - from.SendLocalizedMessage(502436); // That is not accessible. - } - } - - private void InternalCallback(Mobile from, object targeted) - { - if (Deleted || UsesRemaining <= 0 || !from.InRange(GetWorldLocation(), 3) || - !IsAccessibleTo(from)) - return; - - if (!(targeted is Item i)) - { - from.SendLocalizedMessage(1070931); // You can only dye artifacts and enhanced magic items with this tub. - } - else if (!from.InRange(i.GetWorldLocation(), 3) || !IsAccessibleTo(from)) - { - from.SendLocalizedMessage(502436); // That is not accessible. - } - else if (from.Items.Contains(i)) - { - from.SendLocalizedMessage(1070930); // Can't dye artifacts or enhanced magic items that are being worn. - } - else if (i.IsLockedDown) - { - from.SendLocalizedMessage( - 1070932); // You may not dye artifacts and enhanced magic items which are locked down. - } - else if (i.QuestItem) - { - from.SendLocalizedMessage(1151836); // You may not dye toggled quest items. - } - else if (i is MetalPigmentsOfTokuno) - { - from.SendLocalizedMessage(1042417); // You cannot dye that. - } - else if (i is LesserPigmentsOfTokuno) - { - from.SendLocalizedMessage(1042417); // You cannot dye that. - } - else if (i is PigmentsOfTokuno) - { - from.SendLocalizedMessage(1042417); // You cannot dye that. - } - else if (!IsValidItem(i)) - { - from.SendLocalizedMessage( - 1070931); // You can only dye artifacts and enhanced magic items with this tub. //Yes, it says tub on OSI. Don't ask me why ;p - } - else - { - // Notes: on OSI there IS no hue check to see if it's already hued. and no messages on successful hue either - i.Hue = Hue; - - if (--UsesRemaining <= 0) - Delete(); - - from.PlaySound(0x23E); // As per OSI TC1 - } - } - - public static bool IsValidItem(Item i) - { - if (i is BasePigmentsOfTokuno) - return false; - - Type t = i.GetType(); - - CraftResource resource = CraftResource.None; - - if (i is BaseWeapon weapon) - resource = weapon.Resource; - else if (i is BaseArmor armor) - resource = armor.Resource; - else if (i is BaseClothing clothing) - resource = clothing.Resource; - - if (!CraftResources.IsStandard(resource)) - return true; - - if (i is ITokunoDyable) - return true; - - return IsInTypeList(t, TreasuresOfTokuno.LesserArtifactsTotal) - || IsInTypeList(t, TreasuresOfTokuno.GreaterArtifacts) - || IsInTypeList(t, DemonKnight.ArtifactRarity10) - || IsInTypeList(t, DemonKnight.ArtifactRarity11) - || IsInTypeList(t, MondainsLegacy.Artifacts) - || IsInTypeList(t, StealableArtifactsSpawner.TypesOfEntires) - || IsInTypeList(t, Paragon.Artifacts) - || IsInTypeList(t, Leviathan.Artifacts) - || IsInTypeList(t, TreasureMapChest.Artifacts) - || IsInTypeList(t, m_Replicas) - || IsInTypeList(t, m_DyableHeritageItems) - || IsInTypeList(t, m_Glasses); - } - - private static bool IsInTypeList(Type t, Type[] list) - { - for (int i = 0; i < list.Length; i++) - if (list[i] == t) - return true; - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - - writer.WriteEncodedInt(m_UsesRemaining); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_UsesRemaining = reader.ReadEncodedInt(); - break; - } - case 0: // Old pigments that inherited from item - { - InheritsItem = true; - - if (this is LesserPigmentsOfTokuno) - ((LesserPigmentsOfTokuno)this).Type = (LesserPigmentType)reader.ReadEncodedInt(); - else if (this is PigmentsOfTokuno) - ((PigmentsOfTokuno)this).Type = (PigmentType)reader.ReadEncodedInt(); - else if (this is MetalPigmentsOfTokuno) - reader.ReadEncodedInt(); - - m_UsesRemaining = reader.ReadEncodedInt(); - - break; - } - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int UsesRemaining - { - get => m_UsesRemaining; - set - { - m_UsesRemaining = value; - InvalidateProperties(); - } - } - - bool IUsesRemaining.ShowUsesRemaining - { - get => true; - set { } - } - } -} +using System; +using Server.Misc; +using Server.Mobiles; +using Server.Targeting; + +namespace Server.Items +{ + public abstract class BasePigmentsOfTokuno : Item, IUsesRemaining + { + private static readonly Type[] m_Glasses = + { + typeof(MaritimeGlasses), + typeof(WizardsGlasses), + typeof(TradeGlasses), + typeof(LyricalGlasses), + typeof(NecromanticGlasses), + typeof(LightOfWayGlasses), + typeof(FoldedSteelGlasses), + typeof(PoisonedGlasses), + typeof(TreasureTrinketGlasses), + typeof(MaceShieldGlasses), + typeof(ArtsGlasses), + typeof(AnthropomorphistGlasses) + }; + + private static readonly Type[] m_Replicas = + { + typeof(ANecromancerShroud), + typeof(BraveKnightOfTheBritannia), + typeof(CaptainJohnsHat), + typeof(DetectiveBoots), + typeof(DjinnisRing), + typeof(EmbroideredOakLeafCloak), + typeof(GuantletsOfAnger), + typeof(LieutenantOfTheBritannianRoyalGuard), + typeof(OblivionsNeedle), + typeof(RoyalGuardSurvivalKnife), + typeof(SamaritanRobe), + typeof(TheMostKnowledgePerson), + typeof(TheRobeOfBritanniaAri), + typeof(AcidProofRobe), + typeof(Calm), + typeof(CrownOfTalKeesh), + typeof(FangOfRactus), + typeof(GladiatorsCollar), + typeof(OrcChieftainHelm), + typeof(Pacify), + typeof(Quell), + typeof(ShroudOfDeciet), + typeof(Subdue) + }; + + private static readonly Type[] m_DyableHeritageItems = + { + typeof(ChargerOfTheFallen), + typeof(SamuraiHelm), + typeof(HolySword), + typeof(LeggingsOfEmbers), + typeof(ShaminoCrossbow) + }; + + private TextDefinition m_Label; + + private int m_UsesRemaining; + + public BasePigmentsOfTokuno() : base(0xEFF) + { + Weight = 1.0; + m_UsesRemaining = 1; + } + + public BasePigmentsOfTokuno(int uses) : base(0xEFF) + { + Weight = 1.0; + m_UsesRemaining = uses; + } + + public BasePigmentsOfTokuno(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070933; // Pigments of Tokuno + + protected TextDefinition Label + { + get => m_Label; + set + { + m_Label = value; + InvalidateProperties(); + } + } + + /* DO NOT USE! Only used in serialization of pigments that originally derived from Item */ + + protected bool InheritsItem { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int UsesRemaining + { + get => m_UsesRemaining; + set + { + m_UsesRemaining = value; + InvalidateProperties(); + } + } + + bool IUsesRemaining.ShowUsesRemaining + { + get => true; + set { } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_Label != null && m_Label > 0) + TextDefinition.AddTo(list, m_Label); + + list.Add(1060584, m_UsesRemaining.ToString()); // uses remaining: ~1_val~ + } + + public override void OnDoubleClick(Mobile from) + { + if (IsAccessibleTo(from) && from.InRange(GetWorldLocation(), 3)) + { + from.SendLocalizedMessage(1070929); // Select the artifact or enhanced magic item to dye. + from.BeginTarget(3, false, TargetFlags.None, InternalCallback); + } + else + { + from.SendLocalizedMessage(502436); // That is not accessible. + } + } + + private void InternalCallback(Mobile from, object targeted) + { + if (Deleted || UsesRemaining <= 0 || !from.InRange(GetWorldLocation(), 3) || + !IsAccessibleTo(from)) + return; + + if (!(targeted is Item i)) + { + from.SendLocalizedMessage(1070931); // You can only dye artifacts and enhanced magic items with this tub. + } + else if (!from.InRange(i.GetWorldLocation(), 3) || !IsAccessibleTo(from)) + { + from.SendLocalizedMessage(502436); // That is not accessible. + } + else if (from.Items.Contains(i)) + { + from.SendLocalizedMessage(1070930); // Can't dye artifacts or enhanced magic items that are being worn. + } + else if (i.IsLockedDown) + { + from.SendLocalizedMessage( + 1070932 + ); // You may not dye artifacts and enhanced magic items which are locked down. + } + else if (i.QuestItem) + { + from.SendLocalizedMessage(1151836); // You may not dye toggled quest items. + } + else if (i is MetalPigmentsOfTokuno) + { + from.SendLocalizedMessage(1042417); // You cannot dye that. + } + else if (i is LesserPigmentsOfTokuno) + { + from.SendLocalizedMessage(1042417); // You cannot dye that. + } + else if (i is PigmentsOfTokuno) + { + from.SendLocalizedMessage(1042417); // You cannot dye that. + } + else if (!IsValidItem(i)) + { + from.SendLocalizedMessage( + 1070931 + ); // You can only dye artifacts and enhanced magic items with this tub. //Yes, it says tub on OSI. Don't ask me why ;p + } + else + { + // Notes: on OSI there IS no hue check to see if it's already hued. and no messages on successful hue either + i.Hue = Hue; + + if (--UsesRemaining <= 0) + Delete(); + + from.PlaySound(0x23E); // As per OSI TC1 + } + } + + public static bool IsValidItem(Item i) + { + if (i is BasePigmentsOfTokuno) + return false; + + var t = i.GetType(); + + var resource = CraftResource.None; + + if (i is BaseWeapon weapon) + resource = weapon.Resource; + else if (i is BaseArmor armor) + resource = armor.Resource; + else if (i is BaseClothing clothing) + resource = clothing.Resource; + + if (!CraftResources.IsStandard(resource)) + return true; + + if (i is ITokunoDyable) + return true; + + return IsInTypeList(t, TreasuresOfTokuno.LesserArtifactsTotal) + || IsInTypeList(t, TreasuresOfTokuno.GreaterArtifacts) + || IsInTypeList(t, DemonKnight.ArtifactRarity10) + || IsInTypeList(t, DemonKnight.ArtifactRarity11) + || IsInTypeList(t, MondainsLegacy.Artifacts) + || IsInTypeList(t, StealableArtifactsSpawner.TypesOfEntires) + || IsInTypeList(t, Paragon.Artifacts) + || IsInTypeList(t, Leviathan.Artifacts) + || IsInTypeList(t, TreasureMapChest.Artifacts) + || IsInTypeList(t, m_Replicas) + || IsInTypeList(t, m_DyableHeritageItems) + || IsInTypeList(t, m_Glasses); + } + + private static bool IsInTypeList(Type t, Type[] list) + { + for (var i = 0; i < list.Length; i++) + if (list[i] == t) + return true; + + return false; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + + writer.WriteEncodedInt(m_UsesRemaining); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_UsesRemaining = reader.ReadEncodedInt(); + break; + } + case 0: // Old pigments that inherited from item + { + InheritsItem = true; + + if (this is LesserPigmentsOfTokuno) + ((LesserPigmentsOfTokuno)this).Type = (LesserPigmentType)reader.ReadEncodedInt(); + else if (this is PigmentsOfTokuno) + ((PigmentsOfTokuno)this).Type = (PigmentType)reader.ReadEncodedInt(); + else if (this is MetalPigmentsOfTokuno) + reader.ReadEncodedInt(); + + m_UsesRemaining = reader.ReadEncodedInt(); + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Treasures of Tokuno/GreaterArtifacts.cs b/Projects/UOContent/Engines/Treasures of Tokuno/GreaterArtifacts.cs index ce0a82bf7..00101d4fe 100644 --- a/Projects/UOContent/Engines/Treasures of Tokuno/GreaterArtifacts.cs +++ b/Projects/UOContent/Engines/Treasures of Tokuno/GreaterArtifacts.cs @@ -1,553 +1,563 @@ -namespace Server.Items -{ - public class DarkenedSky : Kama - { - [Constructible] - public DarkenedSky() - { - WeaponAttributes.HitLightning = 60; - Attributes.WeaponSpeed = 25; - Attributes.WeaponDamage = 50; - } - - public DarkenedSky(Serial serial) : base(serial) - { - } - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override int LabelNumber => 1070966; // Darkened Sky - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - phys = fire = pois = chaos = direct = 0; - cold = nrgy = 50; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class KasaOfTheRajin : Kasa - { - [Constructible] - public KasaOfTheRajin() => Attributes.SpellDamage = 12; - - public KasaOfTheRajin(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070969; // Kasa of the Raj-in - - public override int BasePhysicalResistance => 12; - public override int BaseFireResistance => 17; - public override int BaseColdResistance => 21; - public override int BasePoisonResistance => 17; - public override int BaseEnergyResistance => 17; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(2); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version <= 1) - { - MaxHitPoints = 255; - HitPoints = 255; - } - - if (version == 0) - LootType = LootType.Regular; - } - } - - public class RuneBeetleCarapace : PlateDo - { - [Constructible] - public RuneBeetleCarapace() - { - Attributes.BonusMana = 10; - Attributes.RegenMana = 3; - Attributes.LowerManaCost = 15; - ArmorAttributes.LowerStatReq = 100; - ArmorAttributes.MageArmor = 1; - } - - public RuneBeetleCarapace(Serial serial) : base(serial) - { - } - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override int LabelNumber => 1070968; // Rune Beetle Carapace - - public override int BaseColdResistance => 14; - public override int BaseEnergyResistance => 14; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Stormgrip : LeatherNinjaMitts - { - [Constructible] - public Stormgrip() - { - Attributes.BonusInt = 8; - Attributes.Luck = 125; - Attributes.WeaponDamage = 25; - } - - public Stormgrip(Serial serial) : base(serial) - { - } - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override int LabelNumber => 1070970; // Stormgrip - - public override int BasePhysicalResistance => 10; - public override int BaseColdResistance => 18; - public override int BaseEnergyResistance => 18; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SwordOfTheStampede : NoDachi - { - [Constructible] - public SwordOfTheStampede() - { - WeaponAttributes.HitHarm = 100; - Attributes.AttackChance = 10; - Attributes.WeaponDamage = 60; - } - - public SwordOfTheStampede(Serial serial) : base(serial) - { - } - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override int LabelNumber => 1070964; // Sword of the Stampede - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - phys = fire = pois = nrgy = chaos = direct = 0; - cold = 100; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SwordsOfProsperity : Daisho - { - [Constructible] - public SwordsOfProsperity() - { - WeaponAttributes.MageWeapon = 30; - Attributes.SpellChanneling = 1; - Attributes.CastSpeed = 1; - Attributes.Luck = 200; - } - - public SwordsOfProsperity(Serial serial) : base(serial) - { - } - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override int LabelNumber => 1070963; // Swords of Prosperity - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - phys = cold = pois = nrgy = chaos = direct = 0; - fire = 100; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class TheHorselord : Yumi - { - [Constructible] - public TheHorselord() - { - Attributes.BonusDex = 5; - Attributes.RegenMana = 1; - Attributes.Luck = 125; - Attributes.WeaponDamage = 50; - - Slayer = SlayerName.ElementalBan; - Slayer2 = SlayerName.ReptilianDeath; - } - - public TheHorselord(Serial serial) : base(serial) - { - } - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override int LabelNumber => 1070967; // The Horselord - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class TomeOfLostKnowledge : Spellbook - { - [Constructible] - public TomeOfLostKnowledge() - { - LootType = LootType.Regular; - Hue = 0x530; - - SkillBonuses.SetValues(0, SkillName.Magery, 15.0); - Attributes.BonusInt = 8; - Attributes.LowerManaCost = 15; - Attributes.SpellDamage = 15; - } - - public TomeOfLostKnowledge(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070971; // Tome of Lost Knowledge - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class WindsEdge : Tessen - { - [Constructible] - public WindsEdge() - { - WeaponAttributes.HitLeechMana = 40; - - Attributes.WeaponDamage = 50; - Attributes.WeaponSpeed = 50; - Attributes.DefendChance = 10; - } - - public WindsEdge(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070965; // Wind's Edge - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - phys = fire = cold = pois = chaos = direct = 0; - nrgy = 100; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public enum PigmentType - { - None, - ParagonGold, - VioletCouragePurple, - InvulnerabilityBlue, - LunaWhite, - DryadGreen, - ShadowDancerBlack, - BerserkerRed, - NoxGreen, - RumRed, - FireOrange, - FadedCoal, - Coal, - FadedGold, - StormBronze, - Rose, - MidnightCoal, - FadedBronze, - FadedRose, - DeepRose - } - - public class PigmentsOfTokuno : BasePigmentsOfTokuno - { - private static readonly int[][] m_Table = - { - // Hue, Label - new[] - { - /*PigmentType.None,*/ 0, -1 - }, - new[] - { - /*PigmentType.ParagonGold,*/ 0x501, 1070987 - }, - new[] - { - /*PigmentType.VioletCouragePurple,*/ 0x486, 1070988 - }, - new[] - { - /*PigmentType.InvulnerabilityBlue,*/ 0x4F2, 1070989 - }, - new[] - { - /*PigmentType.LunaWhite,*/ 0x47E, 1070990 - }, - new[] - { - /*PigmentType.DryadGreen,*/ 0x48F, 1070991 - }, - new[] - { - /*PigmentType.ShadowDancerBlack,*/ 0x455, 1070992 - }, - new[] - { - /*PigmentType.BerserkerRed,*/ 0x21, 1070993 - }, - new[] - { - /*PigmentType.NoxGreen,*/ 0x58C, 1070994 - }, - new[] - { - /*PigmentType.RumRed,*/ 0x66C, 1070995 - }, - new[] - { - /*PigmentType.FireOrange,*/ 0x54F, 1070996 - }, - new[] - { - /*PigmentType.Fadedcoal,*/ 0x96A, 1079579 - }, - new[] - { - /*PigmentType.Coal,*/ 0x96B, 1079580 - }, - new[] - { - /*PigmentType.FadedGold,*/ 0x972, 1079581 - }, - new[] - { - /*PigmentType.StormBronze,*/ 0x977, 1079582 - }, - new[] - { - /*PigmentType.Rose,*/ 0x97C, 1079583 - }, - new[] - { - /*PigmentType.MidnightCoal,*/ 0x96C, 1079584 - }, - new[] - { - /*PigmentType.FadedBronze,*/ 0x975, 1079585 - }, - new[] - { - /*PigmentType.FadedRose,*/ 0x97B, 1079586 - }, - new[] - { - /*PigmentType.DeepRose,*/ 0x97E, 1079587 - } - }; - - private PigmentType m_Type; - - [Constructible] - public PigmentsOfTokuno(PigmentType type = PigmentType.None) : this(type, - type == PigmentType.None || type >= PigmentType.FadedCoal ? 10 : 50) - { - } - - [Constructible] - public PigmentsOfTokuno(PigmentType type, int uses) : base(uses) - { - Weight = 1.0; - Type = type; - } - - public PigmentsOfTokuno(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public PigmentType Type - { - get => m_Type; - set - { - m_Type = value; - - int v = (int)m_Type; - - if (v >= 0 && v < m_Table.Length) - { - Hue = m_Table[v][0]; - Label = m_Table[v][1]; - } - else - { - Hue = 0; - Label = -1; - } - } - } - - public override int LabelNumber => 1070933; // Pigments of Tokuno - - public static int[] GetInfo(PigmentType type) - { - int v = (int)type; - - if (v < 0 || v >= m_Table.Length) - v = 0; - - return m_Table[v]; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - - writer.WriteEncodedInt((int)m_Type); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = InheritsItem ? 0 : reader.ReadInt(); // Required for BasePigmentsOfTokuno insertion - - switch (version) - { - case 1: - Type = (PigmentType)reader.ReadEncodedInt(); - break; - case 0: break; - } - } - } -} +namespace Server.Items +{ + public class DarkenedSky : Kama + { + [Constructible] + public DarkenedSky() + { + WeaponAttributes.HitLightning = 60; + Attributes.WeaponSpeed = 25; + Attributes.WeaponDamage = 50; + } + + public DarkenedSky(Serial serial) : base(serial) + { + } + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override int LabelNumber => 1070966; // Darkened Sky + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + phys = fire = pois = chaos = direct = 0; + cold = nrgy = 50; + } + + 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(); + } + } + + public class KasaOfTheRajin : Kasa + { + [Constructible] + public KasaOfTheRajin() => Attributes.SpellDamage = 12; + + public KasaOfTheRajin(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070969; // Kasa of the Raj-in + + public override int BasePhysicalResistance => 12; + public override int BaseFireResistance => 17; + public override int BaseColdResistance => 21; + public override int BasePoisonResistance => 17; + public override int BaseEnergyResistance => 17; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(2); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version <= 1) + { + MaxHitPoints = 255; + HitPoints = 255; + } + + if (version == 0) + LootType = LootType.Regular; + } + } + + public class RuneBeetleCarapace : PlateDo + { + [Constructible] + public RuneBeetleCarapace() + { + Attributes.BonusMana = 10; + Attributes.RegenMana = 3; + Attributes.LowerManaCost = 15; + ArmorAttributes.LowerStatReq = 100; + ArmorAttributes.MageArmor = 1; + } + + public RuneBeetleCarapace(Serial serial) : base(serial) + { + } + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override int LabelNumber => 1070968; // Rune Beetle Carapace + + public override int BaseColdResistance => 14; + public override int BaseEnergyResistance => 14; + + 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(); + } + } + + public class Stormgrip : LeatherNinjaMitts + { + [Constructible] + public Stormgrip() + { + Attributes.BonusInt = 8; + Attributes.Luck = 125; + Attributes.WeaponDamage = 25; + } + + public Stormgrip(Serial serial) : base(serial) + { + } + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override int LabelNumber => 1070970; // Stormgrip + + public override int BasePhysicalResistance => 10; + public override int BaseColdResistance => 18; + public override int BaseEnergyResistance => 18; + + 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(); + } + } + + public class SwordOfTheStampede : NoDachi + { + [Constructible] + public SwordOfTheStampede() + { + WeaponAttributes.HitHarm = 100; + Attributes.AttackChance = 10; + Attributes.WeaponDamage = 60; + } + + public SwordOfTheStampede(Serial serial) : base(serial) + { + } + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override int LabelNumber => 1070964; // Sword of the Stampede + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + phys = fire = pois = nrgy = chaos = direct = 0; + cold = 100; + } + + 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(); + } + } + + public class SwordsOfProsperity : Daisho + { + [Constructible] + public SwordsOfProsperity() + { + WeaponAttributes.MageWeapon = 30; + Attributes.SpellChanneling = 1; + Attributes.CastSpeed = 1; + Attributes.Luck = 200; + } + + public SwordsOfProsperity(Serial serial) : base(serial) + { + } + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override int LabelNumber => 1070963; // Swords of Prosperity + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + phys = cold = pois = nrgy = chaos = direct = 0; + fire = 100; + } + + 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(); + } + } + + public class TheHorselord : Yumi + { + [Constructible] + public TheHorselord() + { + Attributes.BonusDex = 5; + Attributes.RegenMana = 1; + Attributes.Luck = 125; + Attributes.WeaponDamage = 50; + + Slayer = SlayerName.ElementalBan; + Slayer2 = SlayerName.ReptilianDeath; + } + + public TheHorselord(Serial serial) : base(serial) + { + } + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override int LabelNumber => 1070967; // The Horselord + + 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(); + } + } + + public class TomeOfLostKnowledge : Spellbook + { + [Constructible] + public TomeOfLostKnowledge() + { + LootType = LootType.Regular; + Hue = 0x530; + + SkillBonuses.SetValues(0, SkillName.Magery, 15.0); + Attributes.BonusInt = 8; + Attributes.LowerManaCost = 15; + Attributes.SpellDamage = 15; + } + + public TomeOfLostKnowledge(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070971; // Tome of Lost Knowledge + + 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(); + } + } + + public class WindsEdge : Tessen + { + [Constructible] + public WindsEdge() + { + WeaponAttributes.HitLeechMana = 40; + + Attributes.WeaponDamage = 50; + Attributes.WeaponSpeed = 50; + Attributes.DefendChance = 10; + } + + public WindsEdge(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070965; // Wind's Edge + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + phys = fire = cold = pois = chaos = direct = 0; + nrgy = 100; + } + + 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(); + } + } + + public enum PigmentType + { + None, + ParagonGold, + VioletCouragePurple, + InvulnerabilityBlue, + LunaWhite, + DryadGreen, + ShadowDancerBlack, + BerserkerRed, + NoxGreen, + RumRed, + FireOrange, + FadedCoal, + Coal, + FadedGold, + StormBronze, + Rose, + MidnightCoal, + FadedBronze, + FadedRose, + DeepRose + } + + public class PigmentsOfTokuno : BasePigmentsOfTokuno + { + private static readonly int[][] m_Table = + { + // Hue, Label + new[] + { + /*PigmentType.None,*/ 0, -1 + }, + new[] + { + /*PigmentType.ParagonGold,*/ 0x501, 1070987 + }, + new[] + { + /*PigmentType.VioletCouragePurple,*/ 0x486, 1070988 + }, + new[] + { + /*PigmentType.InvulnerabilityBlue,*/ 0x4F2, 1070989 + }, + new[] + { + /*PigmentType.LunaWhite,*/ 0x47E, 1070990 + }, + new[] + { + /*PigmentType.DryadGreen,*/ 0x48F, 1070991 + }, + new[] + { + /*PigmentType.ShadowDancerBlack,*/ 0x455, 1070992 + }, + new[] + { + /*PigmentType.BerserkerRed,*/ 0x21, 1070993 + }, + new[] + { + /*PigmentType.NoxGreen,*/ 0x58C, 1070994 + }, + new[] + { + /*PigmentType.RumRed,*/ 0x66C, 1070995 + }, + new[] + { + /*PigmentType.FireOrange,*/ 0x54F, 1070996 + }, + new[] + { + /*PigmentType.Fadedcoal,*/ 0x96A, 1079579 + }, + new[] + { + /*PigmentType.Coal,*/ 0x96B, 1079580 + }, + new[] + { + /*PigmentType.FadedGold,*/ 0x972, 1079581 + }, + new[] + { + /*PigmentType.StormBronze,*/ 0x977, 1079582 + }, + new[] + { + /*PigmentType.Rose,*/ 0x97C, 1079583 + }, + new[] + { + /*PigmentType.MidnightCoal,*/ 0x96C, 1079584 + }, + new[] + { + /*PigmentType.FadedBronze,*/ 0x975, 1079585 + }, + new[] + { + /*PigmentType.FadedRose,*/ 0x97B, 1079586 + }, + new[] + { + /*PigmentType.DeepRose,*/ 0x97E, 1079587 + } + }; + + private PigmentType m_Type; + + [Constructible] + public PigmentsOfTokuno(PigmentType type = PigmentType.None) : this( + type, + type == PigmentType.None || type >= PigmentType.FadedCoal ? 10 : 50 + ) + { + } + + [Constructible] + public PigmentsOfTokuno(PigmentType type, int uses) : base(uses) + { + Weight = 1.0; + Type = type; + } + + public PigmentsOfTokuno(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public PigmentType Type + { + get => m_Type; + set + { + m_Type = value; + + var v = (int)m_Type; + + if (v >= 0 && v < m_Table.Length) + { + Hue = m_Table[v][0]; + Label = m_Table[v][1]; + } + else + { + Hue = 0; + Label = -1; + } + } + } + + public override int LabelNumber => 1070933; // Pigments of Tokuno + + public static int[] GetInfo(PigmentType type) + { + var v = (int)type; + + if (v < 0 || v >= m_Table.Length) + v = 0; + + return m_Table[v]; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + + writer.WriteEncodedInt((int)m_Type); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = InheritsItem ? 0 : reader.ReadInt(); // Required for BasePigmentsOfTokuno insertion + + switch (version) + { + case 1: + Type = (PigmentType)reader.ReadEncodedInt(); + break; + case 0: break; + } + } + } +} diff --git a/Projects/UOContent/Engines/Treasures of Tokuno/LesserArtifacts.cs b/Projects/UOContent/Engines/Treasures of Tokuno/LesserArtifacts.cs index f780fbff8..b9c02c682 100644 --- a/Projects/UOContent/Engines/Treasures of Tokuno/LesserArtifacts.cs +++ b/Projects/UOContent/Engines/Treasures of Tokuno/LesserArtifacts.cs @@ -1,1082 +1,1085 @@ -namespace Server.Items -{ - public class AncientFarmersKasa : Kasa - { - [Constructible] - public AncientFarmersKasa() - { - Attributes.BonusStr = 5; - Attributes.BonusStam = 5; - Attributes.RegenStam = 5; - - SkillBonuses.SetValues(0, SkillName.AnimalLore, 5.0); - } - - public AncientFarmersKasa(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070922; // Ancient Farmer's Kasa - public override int BaseColdResistance => 19; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(2); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version <= 1) - { - MaxHitPoints = 255; - HitPoints = 255; - } - - if (version == 0) - SkillBonuses.SetValues(0, SkillName.AnimalLore, 5.0); - } - } - - public class AncientSamuraiDo : PlateDo - { - [Constructible] - public AncientSamuraiDo() - { - ArmorAttributes.LowerStatReq = 100; - ArmorAttributes.MageArmor = 1; - SkillBonuses.SetValues(0, SkillName.Parry, 10.0); - } - - public AncientSamuraiDo(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070926; // Ancient Samurai Do - - public override int BasePhysicalResistance => 15; - public override int BaseFireResistance => 12; - public override int BaseColdResistance => 10; - public override int BasePoisonResistance => 11; - public override int BaseEnergyResistance => 8; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class ArmsOfTacticalExcellence : LeatherHiroSode - { - [Constructible] - public ArmsOfTacticalExcellence() - { - Attributes.BonusDex = 5; - SkillBonuses.SetValues(0, SkillName.Tactics, 12.0); - } - - public ArmsOfTacticalExcellence(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070921; // Arms of Tactical Excellence - - public override int BaseFireResistance => 9; - public override int BaseColdResistance => 13; - public override int BasePoisonResistance => 8; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BlackLotusHood : ClothNinjaHood - { - [Constructible] - public BlackLotusHood() - { - Attributes.LowerManaCost = 6; - Attributes.AttackChance = 6; - ClothingAttributes.SelfRepair = 5; - } - - public BlackLotusHood(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070919; // Black Lotus Hood - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 11; - public override int BaseColdResistance => 15; - public override int BasePoisonResistance => 11; - public override int BaseEnergyResistance => 11; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version == 0) - { - MaxHitPoints = 255; - HitPoints = 255; - } - } - } - - public class DaimyosHelm : PlateBattleKabuto - { - [Constructible] - public DaimyosHelm() - { - ArmorAttributes.LowerStatReq = 100; - ArmorAttributes.MageArmor = 1; - ArmorAttributes.SelfRepair = 3; - Attributes.WeaponSpeed = 10; - } - - public DaimyosHelm(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070920; // Daimyo's Helm - - public override int BaseColdResistance => 10; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DemonForks : Sai - { - [Constructible] - public DemonForks() - { - WeaponAttributes.ResistFireBonus = 10; - WeaponAttributes.ResistPoisonBonus = 10; - - Attributes.ReflectPhysical = 10; - Attributes.WeaponDamage = 35; - Attributes.DefendChance = 10; - } - - public DemonForks(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070917; // Demon Forks - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DragonNunchaku : Nunchaku - { - [Constructible] - public DragonNunchaku() - { - WeaponAttributes.ResistFireBonus = 5; - WeaponAttributes.SelfRepair = 3; - WeaponAttributes.HitFireball = 50; - - Attributes.WeaponDamage = 40; - Attributes.WeaponSpeed = 20; - } - - public DragonNunchaku(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070914; // Dragon Nunchaku - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Exiler : Tetsubo - { - [Constructible] - public Exiler() - { - WeaponAttributes.HitDispel = 33; - Slayer = SlayerName.Exorcism; - - Attributes.WeaponDamage = 40; - Attributes.WeaponSpeed = 20; - } - - public Exiler(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070913; // Exiler - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - phys = fire = cold = pois = chaos = direct = 0; - - nrgy = 100; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GlovesOfTheSun : LeatherNinjaMitts - { - [Constructible] - public GlovesOfTheSun() - { - Attributes.RegenHits = 2; - Attributes.NightSight = 1; - Attributes.LowerManaCost = 5; - Attributes.LowerRegCost = 18; - } - - public GlovesOfTheSun(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070924; // Gloves of the Sun - - public override int BaseFireResistance => 24; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class HanzosBow : Yumi - { - [Constructible] - public HanzosBow() - { - WeaponAttributes.HitLeechHits = 40; - WeaponAttributes.SelfRepair = 3; - - Attributes.WeaponDamage = 50; - - SkillBonuses.SetValues(0, SkillName.Ninjitsu, 10); - } - - public HanzosBow(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070918; // Hanzo's Bow - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LegsOfStability : PlateSuneate - { - [Constructible] - public LegsOfStability() - { - Attributes.BonusStam = 5; - - ArmorAttributes.SelfRepair = 3; - ArmorAttributes.LowerStatReq = 100; - ArmorAttributes.MageArmor = 1; - } - - public LegsOfStability(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070925; // Legs of Stability - - public override int BasePhysicalResistance => 20; - public override int BasePoisonResistance => 18; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PeasantsBokuto : Bokuto - { - [Constructible] - public PeasantsBokuto() - { - WeaponAttributes.SelfRepair = 3; - WeaponAttributes.HitLowerDefend = 30; - - Attributes.WeaponDamage = 35; - Attributes.WeaponSpeed = 10; - Slayer = SlayerName.SnakesBane; - } - - public PeasantsBokuto(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070912; // Peasant's Bokuto - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PilferedDancerFans : Tessen - { - [Constructible] - public PilferedDancerFans() - { - Attributes.WeaponDamage = 20; - Attributes.WeaponSpeed = 20; - Attributes.CastRecovery = 2; - Attributes.DefendChance = 5; - Attributes.SpellChanneling = 1; - } - - public PilferedDancerFans(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070916; // Pilfered Dancer Fans - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class TheDestroyer : NoDachi - { - [Constructible] - public TheDestroyer() - { - WeaponAttributes.HitLeechStam = 40; - - Attributes.BonusStr = 6; - Attributes.AttackChance = 10; - Attributes.WeaponDamage = 50; - } - - public TheDestroyer(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070915; // The Destroyer - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class TomeOfEnlightenment : Spellbook - { - [Constructible] - public TomeOfEnlightenment() - { - LootType = LootType.Regular; - Hue = 0x455; - - Attributes.BonusInt = 5; - Attributes.SpellDamage = 10; - Attributes.CastSpeed = 1; - } - - public TomeOfEnlightenment(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070934; // Tome of Enlightenment - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LeurociansMempoOfFortune : LeatherMempo - { - [Constructible] - public LeurociansMempoOfFortune() - { - LootType = LootType.Regular; - Hue = 0x501; - - Attributes.Luck = 300; - Attributes.RegenMana = 1; - } - - public LeurociansMempoOfFortune(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1071460; // Leurocian's mempo of fortune - - public override int BasePhysicalResistance => 15; - public override int BaseFireResistance => 10; - public override int BaseColdResistance => 10; - public override int BasePoisonResistance => 10; - public override int BaseEnergyResistance => 15; - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - // Non weapon/armor ones: - - public class AncientUrn : Item - { - private string m_UrnName; - - [Constructible] - public AncientUrn() : this(Names.RandomElement()) - { - } - - [Constructible] - public AncientUrn(string urnName) : base(0x241D) - { - m_UrnName = urnName; - Weight = 1.0; - } - - public AncientUrn(Serial serial) : base(serial) - { - } - - public static string[] Names { get; } = - { - "Akira", - "Avaniaga", - "Aya", - "Chie", - "Emiko", - "Fumiyo", - "Gennai", - "Gennosuke", - "Genjo", - "Hamato", - "Harumi", - "Ikuyo", - "Juri", - "Kaori", - "Kaoru", - "Kiyomori", - "Mayako", - "Motoki", - "Musashi", - "Nami", - "Nobukazu", - "Roku", - "Romi", - "Ryo", - "Sanzo", - "Sakamae", - "Satoshi", - "Takamori", - "Takuro", - "Teruyo", - "Toshiro", - "Yago", - "Yeijiro", - "Yoshi", - "Zeshin" - }; - - [CommandProperty(AccessLevel.GameMaster)] - public string UrnName - { - get => m_UrnName; - set => m_UrnName = value; - } - - public override int LabelNumber => 1071014; // Ancient Urn - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - writer.Write(m_UrnName); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - m_UrnName = reader.ReadString(); - - Utility.Intern(ref m_UrnName); - } - - public override void AddNameProperty(ObjectPropertyList list) - { - list.Add(1070935, m_UrnName); // Ancient Urn of ~1_name~ - } - - public override void OnSingleClick(Mobile from) - { - LabelTo(from, 1070935, m_UrnName); // Ancient Urn of ~1_name~ - } - } - - public class HonorableSwords : Item - { - private string m_SwordsName; - - [Constructible] - public HonorableSwords() : this(AncientUrn.Names.RandomElement()) - { - } - - [Constructible] - public HonorableSwords(string swordsName) : base(0x2853) - { - m_SwordsName = swordsName; - - Weight = 5.0; - } - - public HonorableSwords(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public string SwordsName - { - get => m_SwordsName; - set => m_SwordsName = value; - } - - public override int LabelNumber => 1071015; // Honorable Swords - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - writer.Write(m_SwordsName); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - m_SwordsName = reader.ReadString(); - - Utility.Intern(ref m_SwordsName); - } - - public override void AddNameProperty(ObjectPropertyList list) - { - list.Add(1070936, m_SwordsName); // Honorable Swords of ~1_name~ - } - - public override void OnSingleClick(Mobile from) - { - LabelTo(from, 1070936, m_SwordsName); // Honorable Swords of ~1_name~ - } - } - - [Furniture] - [Flippable(0x2811, 0x2812)] - public class ChestOfHeirlooms : LockableContainer - { - [Constructible] - public ChestOfHeirlooms() : base(0x2811) - { - Locked = true; - LockLevel = 95; - MaxLockLevel = 140; - RequiredSkill = 95; - - TrapType = TrapType.ExplosionTrap; - TrapLevel = 10; - TrapPower = 100; - - GumpID = 0x10B; - - for (int i = 0; i < 10; ++i) - { - Item item = Loot.ChestOfHeirloomsContains(); - - int attributeCount = Utility.RandomMinMax(1, 5); - int min = 20; - int max = 80; - - if (item is BaseWeapon weapon) - { - if (Core.AOS) - { - BaseRunicTool.ApplyAttributesTo(weapon, attributeCount, min, max); - } - else - { - weapon.DamageLevel = (WeaponDamageLevel)Utility.Random(6); - weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random(6); - weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random(6); - } - } - else if (item is BaseArmor armor) - { - if (Core.AOS) - { - BaseRunicTool.ApplyAttributesTo(armor, attributeCount, min, max); - } - else - { - armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(6); - armor.Durability = (ArmorDurabilityLevel)Utility.Random(6); - } - } - else if (Core.AOS) - { - if (item is BaseHat hat) - BaseRunicTool.ApplyAttributesTo(hat, attributeCount, min, max); - else if (item is BaseJewel jewel) - BaseRunicTool.ApplyAttributesTo(jewel, attributeCount, min, max); - } - - DropItem(item); - } - } - - public ChestOfHeirlooms(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070937; // Chest of heirlooms - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class FluteOfRenewal : BambooFlute - { - [Constructible] - public FluteOfRenewal() - { - Slayer = SlayerGroup.Groups[Utility.Random(SlayerGroup.Groups.Length - 1)].Super - .Name; // -1 to exclude Fey slayer. Try to confirm no fey slayer on this on OSI - - ReplenishesCharges = true; - } - - public FluteOfRenewal(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070927; // Flute of Renewal - - public override int InitMinUses => 300; - public override int InitMaxUses => 300; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version == 0 && Slayer == SlayerName.Fey) - Slayer = SlayerGroup.Groups[Utility.Random(SlayerGroup.Groups.Length - 1)].Super.Name; - } - } - - public enum LesserPigmentType - { - None, - PaleOrange, - FreshRose, - ChaosBlue, - Silver, - NobleGold, - LightGreen, - PaleBlue, - FreshPlum, - DeepBrown, - BurntBrown - } - - public class LesserPigmentsOfTokuno : BasePigmentsOfTokuno - { - private static readonly int[][] m_Table = - { - // Hue, Label - new[] - { - /*PigmentType.None,*/ 0, -1 - }, - new[] - { - /*PigmentType.PaleOrange,*/ 0x02E, 1071458 - }, - new[] - { - /*PigmentType.FreshRose,*/ 0x4B9, 1071455 - }, - new[] - { - /*PigmentType.ChaosBlue,*/ 0x005, 1071459 - }, - new[] - { - /*PigmentType.Silver,*/ 0x3E9, 1071451 - }, - new[] - { - /*PigmentType.NobleGold,*/ 0x227, 1071457 - }, - new[] - { - /*PigmentType.LightGreen,*/ 0x1C8, 1071454 - }, - new[] - { - /*PigmentType.PaleBlue,*/ 0x24F, 1071456 - }, - new[] - { - /*PigmentType.FreshPlum,*/ 0x145, 1071450 - }, - new[] - { - /*PigmentType.DeepBrown,*/ 0x3F0, 1071452 - }, - new[] - { - /*PigmentType.BurntBrown,*/ 0x41A, 1071453 - } - }; - - private LesserPigmentType m_Type; - - [Constructible] - public LesserPigmentsOfTokuno() : this((LesserPigmentType)Utility.Random(0, 11)) - { - } - - [Constructible] - public LesserPigmentsOfTokuno(LesserPigmentType type) : base(1) - { - Weight = 1.0; - Type = type; - } - - public LesserPigmentsOfTokuno(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public LesserPigmentType Type - { - get => m_Type; - set - { - m_Type = value; - - int v = (int)m_Type; - - if (v >= 0 && v < m_Table.Length) - { - Hue = m_Table[v][0]; - Label = m_Table[v][1]; - } - else - { - Hue = 0; - Label = -1; - } - } - } - - public static int[] GetInfo(LesserPigmentType type) - { - int v = (int)type; - - if (v < 0 || v >= m_Table.Length) - v = 0; - - return m_Table[v]; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - - writer.WriteEncodedInt((int)m_Type); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = InheritsItem ? 0 : reader.ReadInt(); // Required for BasePigmentsOfTokuno insertion - - switch (version) - { - case 1: - Type = (LesserPigmentType)reader.ReadEncodedInt(); - break; - case 0: break; - } - } - } - - public class MetalPigmentsOfTokuno : BasePigmentsOfTokuno - { - [Constructible] - public MetalPigmentsOfTokuno() : base(1) - { - RandomHue(); - Label = -1; - } - - public MetalPigmentsOfTokuno(Serial serial) : base(serial) - { - } - - public void RandomHue() - { - int a = Utility.Random(0, 30); - if (a != 0) - Hue = a + 0x960; - else - Hue = 0; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = InheritsItem ? 0 : reader.ReadInt(); // Required for BasePigmentsOfTokuno insertion - } - } -} +namespace Server.Items +{ + public class AncientFarmersKasa : Kasa + { + [Constructible] + public AncientFarmersKasa() + { + Attributes.BonusStr = 5; + Attributes.BonusStam = 5; + Attributes.RegenStam = 5; + + SkillBonuses.SetValues(0, SkillName.AnimalLore, 5.0); + } + + public AncientFarmersKasa(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070922; // Ancient Farmer's Kasa + public override int BaseColdResistance => 19; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(2); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version <= 1) + { + MaxHitPoints = 255; + HitPoints = 255; + } + + if (version == 0) + SkillBonuses.SetValues(0, SkillName.AnimalLore, 5.0); + } + } + + public class AncientSamuraiDo : PlateDo + { + [Constructible] + public AncientSamuraiDo() + { + ArmorAttributes.LowerStatReq = 100; + ArmorAttributes.MageArmor = 1; + SkillBonuses.SetValues(0, SkillName.Parry, 10.0); + } + + public AncientSamuraiDo(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070926; // Ancient Samurai Do + + public override int BasePhysicalResistance => 15; + public override int BaseFireResistance => 12; + public override int BaseColdResistance => 10; + public override int BasePoisonResistance => 11; + public override int BaseEnergyResistance => 8; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } + + public class ArmsOfTacticalExcellence : LeatherHiroSode + { + [Constructible] + public ArmsOfTacticalExcellence() + { + Attributes.BonusDex = 5; + SkillBonuses.SetValues(0, SkillName.Tactics, 12.0); + } + + public ArmsOfTacticalExcellence(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070921; // Arms of Tactical Excellence + + public override int BaseFireResistance => 9; + public override int BaseColdResistance => 13; + public override int BasePoisonResistance => 8; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } + + public class BlackLotusHood : ClothNinjaHood + { + [Constructible] + public BlackLotusHood() + { + Attributes.LowerManaCost = 6; + Attributes.AttackChance = 6; + ClothingAttributes.SelfRepair = 5; + } + + public BlackLotusHood(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070919; // Black Lotus Hood + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 11; + public override int BaseColdResistance => 15; + public override int BasePoisonResistance => 11; + public override int BaseEnergyResistance => 11; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version == 0) + { + MaxHitPoints = 255; + HitPoints = 255; + } + } + } + + public class DaimyosHelm : PlateBattleKabuto + { + [Constructible] + public DaimyosHelm() + { + ArmorAttributes.LowerStatReq = 100; + ArmorAttributes.MageArmor = 1; + ArmorAttributes.SelfRepair = 3; + Attributes.WeaponSpeed = 10; + } + + public DaimyosHelm(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070920; // Daimyo's Helm + + public override int BaseColdResistance => 10; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } + + public class DemonForks : Sai + { + [Constructible] + public DemonForks() + { + WeaponAttributes.ResistFireBonus = 10; + WeaponAttributes.ResistPoisonBonus = 10; + + Attributes.ReflectPhysical = 10; + Attributes.WeaponDamage = 35; + Attributes.DefendChance = 10; + } + + public DemonForks(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070917; // Demon Forks + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } + + public class DragonNunchaku : Nunchaku + { + [Constructible] + public DragonNunchaku() + { + WeaponAttributes.ResistFireBonus = 5; + WeaponAttributes.SelfRepair = 3; + WeaponAttributes.HitFireball = 50; + + Attributes.WeaponDamage = 40; + Attributes.WeaponSpeed = 20; + } + + public DragonNunchaku(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070914; // Dragon Nunchaku + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } + + public class Exiler : Tetsubo + { + [Constructible] + public Exiler() + { + WeaponAttributes.HitDispel = 33; + Slayer = SlayerName.Exorcism; + + Attributes.WeaponDamage = 40; + Attributes.WeaponSpeed = 20; + } + + public Exiler(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070913; // Exiler + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + phys = fire = cold = pois = chaos = direct = 0; + + nrgy = 100; + } + + 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(); + } + } + + public class GlovesOfTheSun : LeatherNinjaMitts + { + [Constructible] + public GlovesOfTheSun() + { + Attributes.RegenHits = 2; + Attributes.NightSight = 1; + Attributes.LowerManaCost = 5; + Attributes.LowerRegCost = 18; + } + + public GlovesOfTheSun(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070924; // Gloves of the Sun + + public override int BaseFireResistance => 24; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } + + public class HanzosBow : Yumi + { + [Constructible] + public HanzosBow() + { + WeaponAttributes.HitLeechHits = 40; + WeaponAttributes.SelfRepair = 3; + + Attributes.WeaponDamage = 50; + + SkillBonuses.SetValues(0, SkillName.Ninjitsu, 10); + } + + public HanzosBow(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070918; // Hanzo's Bow + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } + + public class LegsOfStability : PlateSuneate + { + [Constructible] + public LegsOfStability() + { + Attributes.BonusStam = 5; + + ArmorAttributes.SelfRepair = 3; + ArmorAttributes.LowerStatReq = 100; + ArmorAttributes.MageArmor = 1; + } + + public LegsOfStability(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070925; // Legs of Stability + + public override int BasePhysicalResistance => 20; + public override int BasePoisonResistance => 18; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } + + public class PeasantsBokuto : Bokuto + { + [Constructible] + public PeasantsBokuto() + { + WeaponAttributes.SelfRepair = 3; + WeaponAttributes.HitLowerDefend = 30; + + Attributes.WeaponDamage = 35; + Attributes.WeaponSpeed = 10; + Slayer = SlayerName.SnakesBane; + } + + public PeasantsBokuto(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070912; // Peasant's Bokuto + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } + + public class PilferedDancerFans : Tessen + { + [Constructible] + public PilferedDancerFans() + { + Attributes.WeaponDamage = 20; + Attributes.WeaponSpeed = 20; + Attributes.CastRecovery = 2; + Attributes.DefendChance = 5; + Attributes.SpellChanneling = 1; + } + + public PilferedDancerFans(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070916; // Pilfered Dancer Fans + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } + + public class TheDestroyer : NoDachi + { + [Constructible] + public TheDestroyer() + { + WeaponAttributes.HitLeechStam = 40; + + Attributes.BonusStr = 6; + Attributes.AttackChance = 10; + Attributes.WeaponDamage = 50; + } + + public TheDestroyer(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070915; // The Destroyer + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } + + public class TomeOfEnlightenment : Spellbook + { + [Constructible] + public TomeOfEnlightenment() + { + LootType = LootType.Regular; + Hue = 0x455; + + Attributes.BonusInt = 5; + Attributes.SpellDamage = 10; + Attributes.CastSpeed = 1; + } + + public TomeOfEnlightenment(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070934; // Tome of Enlightenment + + 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(); + } + } + + public class LeurociansMempoOfFortune : LeatherMempo + { + [Constructible] + public LeurociansMempoOfFortune() + { + LootType = LootType.Regular; + Hue = 0x501; + + Attributes.Luck = 300; + Attributes.RegenMana = 1; + } + + public LeurociansMempoOfFortune(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1071460; // Leurocian's mempo of fortune + + public override int BasePhysicalResistance => 15; + public override int BaseFireResistance => 10; + public override int BaseColdResistance => 10; + public override int BasePoisonResistance => 10; + public override int BaseEnergyResistance => 15; + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } + + // Non weapon/armor ones: + + public class AncientUrn : Item + { + private string m_UrnName; + + [Constructible] + public AncientUrn() : this(Names.RandomElement()) + { + } + + [Constructible] + public AncientUrn(string urnName) : base(0x241D) + { + m_UrnName = urnName; + Weight = 1.0; + } + + public AncientUrn(Serial serial) : base(serial) + { + } + + public static string[] Names { get; } = + { + "Akira", + "Avaniaga", + "Aya", + "Chie", + "Emiko", + "Fumiyo", + "Gennai", + "Gennosuke", + "Genjo", + "Hamato", + "Harumi", + "Ikuyo", + "Juri", + "Kaori", + "Kaoru", + "Kiyomori", + "Mayako", + "Motoki", + "Musashi", + "Nami", + "Nobukazu", + "Roku", + "Romi", + "Ryo", + "Sanzo", + "Sakamae", + "Satoshi", + "Takamori", + "Takuro", + "Teruyo", + "Toshiro", + "Yago", + "Yeijiro", + "Yoshi", + "Zeshin" + }; + + [CommandProperty(AccessLevel.GameMaster)] + public string UrnName + { + get => m_UrnName; + set => m_UrnName = value; + } + + public override int LabelNumber => 1071014; // Ancient Urn + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + writer.Write(m_UrnName); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + m_UrnName = reader.ReadString(); + + Utility.Intern(ref m_UrnName); + } + + public override void AddNameProperty(ObjectPropertyList list) + { + list.Add(1070935, m_UrnName); // Ancient Urn of ~1_name~ + } + + public override void OnSingleClick(Mobile from) + { + LabelTo(from, 1070935, m_UrnName); // Ancient Urn of ~1_name~ + } + } + + public class HonorableSwords : Item + { + private string m_SwordsName; + + [Constructible] + public HonorableSwords() : this(AncientUrn.Names.RandomElement()) + { + } + + [Constructible] + public HonorableSwords(string swordsName) : base(0x2853) + { + m_SwordsName = swordsName; + + Weight = 5.0; + } + + public HonorableSwords(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public string SwordsName + { + get => m_SwordsName; + set => m_SwordsName = value; + } + + public override int LabelNumber => 1071015; // Honorable Swords + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + writer.Write(m_SwordsName); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + m_SwordsName = reader.ReadString(); + + Utility.Intern(ref m_SwordsName); + } + + public override void AddNameProperty(ObjectPropertyList list) + { + list.Add(1070936, m_SwordsName); // Honorable Swords of ~1_name~ + } + + public override void OnSingleClick(Mobile from) + { + LabelTo(from, 1070936, m_SwordsName); // Honorable Swords of ~1_name~ + } + } + + [Furniture] + [Flippable(0x2811, 0x2812)] + public class ChestOfHeirlooms : LockableContainer + { + [Constructible] + public ChestOfHeirlooms() : base(0x2811) + { + Locked = true; + LockLevel = 95; + MaxLockLevel = 140; + RequiredSkill = 95; + + TrapType = TrapType.ExplosionTrap; + TrapLevel = 10; + TrapPower = 100; + + GumpID = 0x10B; + + for (var i = 0; i < 10; ++i) + { + var item = Loot.ChestOfHeirloomsContains(); + + var attributeCount = Utility.RandomMinMax(1, 5); + var min = 20; + var max = 80; + + if (item is BaseWeapon weapon) + { + if (Core.AOS) + { + BaseRunicTool.ApplyAttributesTo(weapon, attributeCount, min, max); + } + else + { + weapon.DamageLevel = (WeaponDamageLevel)Utility.Random(6); + weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random(6); + weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random(6); + } + } + else if (item is BaseArmor armor) + { + if (Core.AOS) + { + BaseRunicTool.ApplyAttributesTo(armor, attributeCount, min, max); + } + else + { + armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(6); + armor.Durability = (ArmorDurabilityLevel)Utility.Random(6); + } + } + else if (Core.AOS) + { + if (item is BaseHat hat) + BaseRunicTool.ApplyAttributesTo(hat, attributeCount, min, max); + else if (item is BaseJewel jewel) + BaseRunicTool.ApplyAttributesTo(jewel, attributeCount, min, max); + } + + DropItem(item); + } + } + + public ChestOfHeirlooms(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070937; // Chest of heirlooms + + 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 class FluteOfRenewal : BambooFlute + { + [Constructible] + public FluteOfRenewal() + { + Slayer = SlayerGroup.Groups[Utility.Random(SlayerGroup.Groups.Length - 1)] + .Super + .Name; // -1 to exclude Fey slayer. Try to confirm no fey slayer on this on OSI + + ReplenishesCharges = true; + } + + public FluteOfRenewal(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070927; // Flute of Renewal + + public override int InitMinUses => 300; + public override int InitMaxUses => 300; + + 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 && Slayer == SlayerName.Fey) + Slayer = SlayerGroup.Groups[Utility.Random(SlayerGroup.Groups.Length - 1)].Super.Name; + } + } + + public enum LesserPigmentType + { + None, + PaleOrange, + FreshRose, + ChaosBlue, + Silver, + NobleGold, + LightGreen, + PaleBlue, + FreshPlum, + DeepBrown, + BurntBrown + } + + public class LesserPigmentsOfTokuno : BasePigmentsOfTokuno + { + private static readonly int[][] m_Table = + { + // Hue, Label + new[] + { + /*PigmentType.None,*/ 0, -1 + }, + new[] + { + /*PigmentType.PaleOrange,*/ 0x02E, 1071458 + }, + new[] + { + /*PigmentType.FreshRose,*/ 0x4B9, 1071455 + }, + new[] + { + /*PigmentType.ChaosBlue,*/ 0x005, 1071459 + }, + new[] + { + /*PigmentType.Silver,*/ 0x3E9, 1071451 + }, + new[] + { + /*PigmentType.NobleGold,*/ 0x227, 1071457 + }, + new[] + { + /*PigmentType.LightGreen,*/ 0x1C8, 1071454 + }, + new[] + { + /*PigmentType.PaleBlue,*/ 0x24F, 1071456 + }, + new[] + { + /*PigmentType.FreshPlum,*/ 0x145, 1071450 + }, + new[] + { + /*PigmentType.DeepBrown,*/ 0x3F0, 1071452 + }, + new[] + { + /*PigmentType.BurntBrown,*/ 0x41A, 1071453 + } + }; + + private LesserPigmentType m_Type; + + [Constructible] + public LesserPigmentsOfTokuno() : this((LesserPigmentType)Utility.Random(0, 11)) + { + } + + [Constructible] + public LesserPigmentsOfTokuno(LesserPigmentType type) : base(1) + { + Weight = 1.0; + Type = type; + } + + public LesserPigmentsOfTokuno(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public LesserPigmentType Type + { + get => m_Type; + set + { + m_Type = value; + + var v = (int)m_Type; + + if (v >= 0 && v < m_Table.Length) + { + Hue = m_Table[v][0]; + Label = m_Table[v][1]; + } + else + { + Hue = 0; + Label = -1; + } + } + } + + public static int[] GetInfo(LesserPigmentType type) + { + var v = (int)type; + + if (v < 0 || v >= m_Table.Length) + v = 0; + + return m_Table[v]; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + + writer.WriteEncodedInt((int)m_Type); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = InheritsItem ? 0 : reader.ReadInt(); // Required for BasePigmentsOfTokuno insertion + + switch (version) + { + case 1: + Type = (LesserPigmentType)reader.ReadEncodedInt(); + break; + case 0: break; + } + } + } + + public class MetalPigmentsOfTokuno : BasePigmentsOfTokuno + { + [Constructible] + public MetalPigmentsOfTokuno() : base(1) + { + RandomHue(); + Label = -1; + } + + public MetalPigmentsOfTokuno(Serial serial) : base(serial) + { + } + + public void RandomHue() + { + var a = Utility.Random(0, 30); + if (a != 0) + Hue = a + 0x960; + else + Hue = 0; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = InheritsItem ? 0 : reader.ReadInt(); // Required for BasePigmentsOfTokuno insertion + } + } +} diff --git a/Projects/UOContent/Engines/Treasures of Tokuno/TreasuresOfTokuno.cs b/Projects/UOContent/Engines/Treasures of Tokuno/TreasuresOfTokuno.cs index ae4eab4ca..20f173812 100644 --- a/Projects/UOContent/Engines/Treasures of Tokuno/TreasuresOfTokuno.cs +++ b/Projects/UOContent/Engines/Treasures of Tokuno/TreasuresOfTokuno.cs @@ -1,600 +1,652 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Server.Gumps; -using Server.Items; -using Server.Misc; -using Server.Mobiles; -using Server.Multis; -using Server.Network; -using Server.Regions; -using Server.Utilities; - -namespace Server.Misc -{ - public enum TreasuresOfTokunoEra - { - None, - ToTOne, - ToTTwo, - ToTThree - } - - public class TreasuresOfTokuno - { - public const int ItemsPerReward = 10; - - private static readonly Type[][] m_LesserArtifacts = - { - // ToT One Rewards - new[] - { - typeof(AncientFarmersKasa), typeof(AncientSamuraiDo), typeof(ArmsOfTacticalExcellence), - typeof(BlackLotusHood), - typeof(DaimyosHelm), typeof(DemonForks), typeof(DragonNunchaku), typeof(Exiler), typeof(GlovesOfTheSun), - typeof(HanzosBow), typeof(LegsOfStability), typeof(PeasantsBokuto), typeof(PilferedDancerFans), - typeof(TheDestroyer), - typeof(TomeOfEnlightenment), typeof(AncientUrn), typeof(HonorableSwords), typeof(PigmentsOfTokuno), - typeof(FluteOfRenewal), typeof(ChestOfHeirlooms) - }, - // ToT Two Rewards - new[] - { - typeof(MetalPigmentsOfTokuno), typeof(AncientFarmersKasa), typeof(AncientSamuraiDo), - typeof(ArmsOfTacticalExcellence), - typeof(MetalPigmentsOfTokuno), typeof(BlackLotusHood), typeof(DaimyosHelm), typeof(DemonForks), - typeof(MetalPigmentsOfTokuno), typeof(DragonNunchaku), typeof(Exiler), typeof(GlovesOfTheSun), - typeof(HanzosBow), - typeof(MetalPigmentsOfTokuno), typeof(LegsOfStability), typeof(PeasantsBokuto), typeof(PilferedDancerFans), - typeof(TheDestroyer), - typeof(MetalPigmentsOfTokuno), typeof(TomeOfEnlightenment), typeof(AncientUrn), typeof(HonorableSwords), - typeof(MetalPigmentsOfTokuno), typeof(FluteOfRenewal), typeof(ChestOfHeirlooms) - }, - // ToT Three Rewards - new[] - { - typeof(LesserPigmentsOfTokuno), typeof(AncientFarmersKasa), typeof(AncientSamuraiDo), - typeof(ArmsOfTacticalExcellence), - typeof(LesserPigmentsOfTokuno), typeof(BlackLotusHood), typeof(DaimyosHelm), typeof(HanzosBow), - typeof(LesserPigmentsOfTokuno), typeof(DemonForks), typeof(DragonNunchaku), typeof(Exiler), - typeof(GlovesOfTheSun), - typeof(LesserPigmentsOfTokuno), typeof(LegsOfStability), typeof(PeasantsBokuto), typeof(PilferedDancerFans), - typeof(TheDestroyer), - typeof(LesserPigmentsOfTokuno), typeof(TomeOfEnlightenment), typeof(AncientUrn), typeof(HonorableSwords), - typeof(FluteOfRenewal), - typeof(LesserPigmentsOfTokuno), typeof(LeurociansMempoOfFortune), typeof(ChestOfHeirlooms) - } - }; - - private static Type[][] m_GreaterArtifacts; - - public static Type[] LesserArtifactsTotal { get; } = - { - typeof(AncientFarmersKasa), typeof(AncientSamuraiDo), typeof(ArmsOfTacticalExcellence), typeof(BlackLotusHood), - typeof(DaimyosHelm), typeof(DemonForks), typeof(DragonNunchaku), typeof(Exiler), typeof(GlovesOfTheSun), - typeof(HanzosBow), typeof(LegsOfStability), typeof(PeasantsBokuto), typeof(PilferedDancerFans), - typeof(TheDestroyer), - typeof(TomeOfEnlightenment), typeof(AncientUrn), typeof(HonorableSwords), typeof(PigmentsOfTokuno), - typeof(FluteOfRenewal), - typeof(LeurociansMempoOfFortune), typeof(LesserPigmentsOfTokuno), typeof(MetalPigmentsOfTokuno), - typeof(ChestOfHeirlooms) - }; - - public static TreasuresOfTokunoEra DropEra { get; set; } = TreasuresOfTokunoEra.None; - - public static TreasuresOfTokunoEra RewardEra { get; set; } = TreasuresOfTokunoEra.ToTOne; - - public static Type[] LesserArtifacts => m_LesserArtifacts[(int)RewardEra - 1]; - - public static Type[] GreaterArtifacts - { - get - { - if (m_GreaterArtifacts == null) - { - m_GreaterArtifacts = new Type[ToTRedeemGump.NormalRewards.Length][]; - - for (int i = 0; i < m_GreaterArtifacts.Length; i++) - { - m_GreaterArtifacts[i] = new Type[ToTRedeemGump.NormalRewards[i].Length]; - - for (int j = 0; j < m_GreaterArtifacts[i].Length; j++) - m_GreaterArtifacts[i][j] = ToTRedeemGump.NormalRewards[i][j].Type; - } - } - - return m_GreaterArtifacts[(int)RewardEra - 1]; - } - } - - private static bool CheckLocation(Mobile m) - { - Region r = m.Region; - - if (r.IsPartOf() || BaseBoat.FindBoatAt(m, m.Map) != null) - return false; - // TODO: a CanReach of something check as opposed to above? - - if (r.IsPartOf("Yomotsu Mines") || r.IsPartOf("Fan Dancer's Dojo")) - return true; - - return m.Map == Map.Tokuno; - } - - public static void HandleKill(Mobile victim, Mobile killer) - { - if (DropEra == TreasuresOfTokunoEra.None || !(killer is PlayerMobile pm) || !(victim is BaseCreature bc) || - !CheckLocation(bc) || !CheckLocation(pm) || !killer.InRange(victim, 18)) - return; - - if (bc.Controlled || bc.Owners.Count > 0 || bc.Fame <= 0) - return; - - // 25000 for 1/100 chance, 10 hyrus - // 1500, 1/1000 chance, 20 lizard men for that chance. - - pm.ToTTotalMonsterFame += (int)(bc.Fame * (1 + Math.Sqrt(pm.Luck) / 100)); - - // This is the Exponentional regression with only 2 datapoints. - // A log. func would also work, but it didn't make as much sense. - // This function isn't OSI exact being that I don't know OSI's func they used ;p - int x = pm.ToTTotalMonsterFame; - - // const double A = 8.63316841 * Math.Pow( 10, -4 ); - const double A = 0.000863316841; - // const double B = 4.25531915 * Math.Pow( 10, -6 ); - const double B = 0.00000425531915; - - double chance = A * Math.Pow(10, B * x); - - if (chance > Utility.RandomDouble()) - { - Item i = null; - - try - { - i = ActivatorUtil.CreateInstance( - m_LesserArtifacts[(int)DropEra - 1].RandomElement()) - as - Item; - } - catch - { - // ignored - } - - if (i != null) - { - pm.SendLocalizedMessage( - 1062317); // For your valor in combating the fallen beast, a special artifact has been bestowed on you. - - if (!pm.PlaceInBackpack(i)) - { - if (pm.BankBox?.TryDropItem(killer, i, false) == true) - { - pm.SendLocalizedMessage(1079730); // The item has been placed into your bank box. - } - else - { - pm.SendLocalizedMessage( - 1072523); // You find an artifact, but your backpack and bank are too full to hold it. - i.MoveToWorld(pm.Location, pm.Map); - } - } - - pm.ToTTotalMonsterFame = 0; - } - } - } - } -} - -namespace Server.Mobiles -{ - public class IharaSoko : BaseVendor - { - protected List m_SBInfos = new List(); - - [Constructible] - public IharaSoko() : base("the Imperial Minister of Trade") - { - Female = false; - Body = 0x190; - Hue = 0x8403; - } - - public IharaSoko(Serial serial) : base(serial) - { - } - - public override bool IsActiveVendor => false; - public override bool IsInvulnerable => true; - public override bool DisallowAllMoves => true; - public override bool ClickTitle => true; - public override bool CanTeach => false; - public override string DefaultName => "Ihara Soko"; - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - } - - public override void InitOutfit() - { - AddItem(new Waraji(0x711)); - AddItem(new Backpack()); - AddItem(new Kamishimo(0x483)); - - Item item = new LightPlateJingasa(); - item.Hue = 0x711; - - AddItem(item); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override bool CanBeDamaged() => false; - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (m.Alive && m is PlayerMobile pm) - { - int range = 3; - - if (pm.Alive && Math.Abs(Z - pm.Z) < 16 && InRange(m, range) && !InRange(oldLocation, range)) - { - if (pm.ToTItemsTurnedIn >= TreasuresOfTokuno.ItemsPerReward) - { - SayTo(pm, - 1070980); // Congratulations! You have turned in enough minor treasures to earn a greater reward. - - pm.CloseGump(); // Sanity - - if (!pm.HasGump()) - pm.SendGump(new ToTRedeemGump(this, false)); - } - else - { - if (pm.ToTItemsTurnedIn == 0) - SayTo(pm, - 1071013); // Bring me 10 of the lost treasures of Tokuno and I will reward you with a valuable item. - else - SayTo(pm, 1070981, - $"{pm.ToTItemsTurnedIn}\t{TreasuresOfTokuno.ItemsPerReward}"); // You have turned in ~1_COUNT~ minor artifacts. Turn in ~2_NUM~ to receive a reward. - - List buttons = ToTTurnInGump.FindRedeemableItems(pm); - - if (buttons.Count > 0 && !pm.HasGump()) - pm.SendGump(new ToTTurnInGump(this, buttons)); - } - } - - int leaveRange = 7; - - if (!InRange(m, leaveRange) && InRange(oldLocation, leaveRange)) - { - pm.CloseGump(); - pm.CloseGump(); - } - } - } - - public override void TurnToTokuno() - { - } - } -} - -namespace Server.Gumps -{ - public class ItemTileButtonInfo : ImageTileButtonInfo - { - public ItemTileButtonInfo(Item i) : base(i.ItemID, i.Hue, - i.Name == null || i.Name.Length <= 0 ? (TextDefinition)i.LabelNumber : (TextDefinition)i.Name) => - Item = i; - - public Item Item { get; set; } - } - - public class ToTTurnInGump : BaseImageTileButtonsGump - { - private readonly Mobile m_Collector; - - public ToTTurnInGump(Mobile collector, List buttons) : base(1071012, Utility.CastListContravariant(buttons)) // Click a minor artifact to give it to Ihara Soko. - => - m_Collector = collector; - - public static List FindRedeemableItems(Mobile m) - { - Container pack = m.Backpack; - if (pack == null) - return new List(); - - List buttons = new List(); - - Item[] items = pack.FindItemsByType(TreasuresOfTokuno.LesserArtifactsTotal); - - for (int i = 0; i < items.Length; i++) - { - Item item = items[i]; - if (item is ChestOfHeirlooms heirlooms && !heirlooms.Locked) - continue; - - if (item is ChestOfHeirlooms ofHeirlooms && ofHeirlooms.TrapLevel != 10) - continue; - - if (item is PigmentsOfTokuno tokuno && tokuno.Type != PigmentType.None) - continue; - - buttons.Add(new ItemTileButtonInfo(item)); - } - - return buttons; - } - - public override void HandleButtonResponse(NetState sender, int adjustedButton, ImageTileButtonInfo buttonInfo) - { - PlayerMobile pm = sender.Mobile as PlayerMobile; - - Item item = ((ItemTileButtonInfo)buttonInfo).Item; - - if (!(pm != null && item.IsChildOf(pm.Backpack) && pm.InRange(m_Collector.Location, 7))) - return; - - item.Delete(); - - if (++pm.ToTItemsTurnedIn >= TreasuresOfTokuno.ItemsPerReward) - { - m_Collector.SayTo(pm, - 1070980); // Congratulations! You have turned in enough minor treasures to earn a greater reward. - - pm.CloseGump(); // Sanity - - if (!pm.HasGump()) - pm.SendGump(new ToTRedeemGump(m_Collector, false)); - } - else - { - m_Collector.SayTo(pm, 1070981, - $"{pm.ToTItemsTurnedIn}\t{TreasuresOfTokuno.ItemsPerReward}"); // You have turned in ~1_COUNT~ minor artifacts. Turn in ~2_NUM~ to receive a reward. - - List buttons = FindRedeemableItems(pm); - - pm.CloseGump(); // Sanity - - if (buttons.Count > 0) - pm.SendGump(new ToTTurnInGump(m_Collector, buttons)); - } - } - - public override void HandleCancel(NetState sender) - { - if (!(sender.Mobile is PlayerMobile pm) || !pm.InRange(m_Collector.Location, 7)) - return; - - if (pm.ToTItemsTurnedIn == 0) - m_Collector.SayTo(pm, - 1071013); // Bring me 10 of the lost treasures of Tokuno and I will reward you with a valuable item. - else if (pm.ToTItemsTurnedIn < TreasuresOfTokuno.ItemsPerReward) // This case should ALWAYS be true with this gump, jsut a sanity check - m_Collector.SayTo(pm, 1070981, - $"{pm.ToTItemsTurnedIn}\t{TreasuresOfTokuno.ItemsPerReward}"); // You have turned in ~1_COUNT~ minor artifacts. Turn in ~2_NUM~ to receive a reward. - else - m_Collector.SayTo(pm, 1070982); // When you wish to choose your reward, you have but to approach me again. - } - } - - public class ToTRedeemGump : BaseImageTileButtonsGump - { - private readonly Mobile m_Collector; - - public ToTRedeemGump(Mobile collector, bool pigments) : base(pigments ? 1070986 : 1070985, - pigments - ? PigmentRewards[(int)TreasuresOfTokuno.RewardEra - 1].ToArray() - : NormalRewards[(int)TreasuresOfTokuno.RewardEra - 1].ToArray()) => - m_Collector = collector; - - public static TypeTileButtonInfo[][] NormalRewards { get; } = - { - // ToT One Rewards - new[] - { - new TypeTileButtonInfo(typeof(SwordsOfProsperity), 0x27A9, 1070963, 1071002), - new TypeTileButtonInfo(typeof(SwordOfTheStampede), 0x27A2, 1070964, 1070978), - new TypeTileButtonInfo(typeof(WindsEdge), 0x27A3, 1070965, 1071003), - new TypeTileButtonInfo(typeof(DarkenedSky), 0x27AD, 1070966, 1071004), - new TypeTileButtonInfo(typeof(TheHorselord), 0x27A5, 1070967, 1071005), - new TypeTileButtonInfo(typeof(RuneBeetleCarapace), 0x277D, 1070968, 1071006), - new TypeTileButtonInfo(typeof(KasaOfTheRajin), 0x2798, 1070969, 1071007), - new TypeTileButtonInfo(typeof(Stormgrip), 0x2792, 1070970, 1071008), - new TypeTileButtonInfo(typeof(TomeOfLostKnowledge), 0x0EFA, 0x530, 1070971, 1071009), - new TypeTileButtonInfo(typeof(PigmentsOfTokuno), 0x0EFF, 1070933, 1071011) - }, - // ToT Two Rewards - new[] - { - new TypeTileButtonInfo(typeof(SwordsOfProsperity), 0x27A9, 1070963, 1071002), - new TypeTileButtonInfo(typeof(SwordOfTheStampede), 0x27A2, 1070964, 1070978), - new TypeTileButtonInfo(typeof(WindsEdge), 0x27A3, 1070965, 1071003), - new TypeTileButtonInfo(typeof(DarkenedSky), 0x27AD, 1070966, 1071004), - new TypeTileButtonInfo(typeof(TheHorselord), 0x27A5, 1070967, 1071005), - new TypeTileButtonInfo(typeof(RuneBeetleCarapace), 0x277D, 1070968, 1071006), - new TypeTileButtonInfo(typeof(KasaOfTheRajin), 0x2798, 1070969, 1071007), - new TypeTileButtonInfo(typeof(Stormgrip), 0x2792, 1070970, 1071008), - new TypeTileButtonInfo(typeof(TomeOfLostKnowledge), 0x0EFA, 0x530, 1070971, 1071009), - new TypeTileButtonInfo(typeof(PigmentsOfTokuno), 0x0EFF, 1070933, 1071011) - }, - // ToT Three Rewards - new[] - { - new TypeTileButtonInfo(typeof(SwordsOfProsperity), 0x27A9, 1070963, 1071002), - new TypeTileButtonInfo(typeof(SwordOfTheStampede), 0x27A2, 1070964, 1070978), - new TypeTileButtonInfo(typeof(WindsEdge), 0x27A3, 1070965, 1071003), - new TypeTileButtonInfo(typeof(DarkenedSky), 0x27AD, 1070966, 1071004), - new TypeTileButtonInfo(typeof(TheHorselord), 0x27A5, 1070967, 1071005), - new TypeTileButtonInfo(typeof(RuneBeetleCarapace), 0x277D, 1070968, 1071006), - new TypeTileButtonInfo(typeof(KasaOfTheRajin), 0x2798, 1070969, 1071007), - new TypeTileButtonInfo(typeof(Stormgrip), 0x2792, 1070970, 1071008), - new TypeTileButtonInfo(typeof(TomeOfLostKnowledge), 0x0EFA, 0x530, 1070971, 1071009) - } - }; - - public static PigmentsTileButtonInfo[][] PigmentRewards { get; } = - { - // ToT One Pigment Rewards - new[] - { - new PigmentsTileButtonInfo(PigmentType.ParagonGold), - new PigmentsTileButtonInfo(PigmentType.VioletCouragePurple), - new PigmentsTileButtonInfo(PigmentType.InvulnerabilityBlue), - new PigmentsTileButtonInfo(PigmentType.LunaWhite), - new PigmentsTileButtonInfo(PigmentType.DryadGreen), - new PigmentsTileButtonInfo(PigmentType.ShadowDancerBlack), - new PigmentsTileButtonInfo(PigmentType.BerserkerRed), - new PigmentsTileButtonInfo(PigmentType.NoxGreen), - new PigmentsTileButtonInfo(PigmentType.RumRed), - new PigmentsTileButtonInfo(PigmentType.FireOrange) - }, - // ToT Two Pigment Rewards - new[] - { - new PigmentsTileButtonInfo(PigmentType.FadedCoal), - new PigmentsTileButtonInfo(PigmentType.Coal), - new PigmentsTileButtonInfo(PigmentType.FadedGold), - new PigmentsTileButtonInfo(PigmentType.StormBronze), - new PigmentsTileButtonInfo(PigmentType.Rose), - new PigmentsTileButtonInfo(PigmentType.MidnightCoal), - new PigmentsTileButtonInfo(PigmentType.FadedBronze), - new PigmentsTileButtonInfo(PigmentType.FadedRose), - new PigmentsTileButtonInfo(PigmentType.DeepRose) - }, - // ToT Three Pigment Rewards - new[] - { - new PigmentsTileButtonInfo(PigmentType.ParagonGold), - new PigmentsTileButtonInfo(PigmentType.VioletCouragePurple), - new PigmentsTileButtonInfo(PigmentType.InvulnerabilityBlue), - new PigmentsTileButtonInfo(PigmentType.LunaWhite), - new PigmentsTileButtonInfo(PigmentType.DryadGreen), - new PigmentsTileButtonInfo(PigmentType.ShadowDancerBlack), - new PigmentsTileButtonInfo(PigmentType.BerserkerRed), - new PigmentsTileButtonInfo(PigmentType.NoxGreen), - new PigmentsTileButtonInfo(PigmentType.RumRed), - new PigmentsTileButtonInfo(PigmentType.FireOrange) - } - }; - - public override void HandleButtonResponse(NetState sender, int adjustedButton, ImageTileButtonInfo buttonInfo) - { - if (!(sender.Mobile is PlayerMobile pm) || !pm.InRange(m_Collector.Location, 7) || - !(pm.ToTItemsTurnedIn >= TreasuresOfTokuno.ItemsPerReward)) - return; - - Item item = null; - - if (buttonInfo is PigmentsTileButtonInfo p) - { - item = new PigmentsOfTokuno(p.Pigment); - } - else - { - TypeTileButtonInfo t = (TypeTileButtonInfo)buttonInfo; - - if (t.Type == typeof(PigmentsOfTokuno)) // Special case of course. - { - pm.CloseGump(); // Sanity - pm.CloseGump(); - - pm.SendGump(new ToTRedeemGump(m_Collector, true)); - - return; - } - - try - { - item = (Item)ActivatorUtil.CreateInstance(t.Type); - } - catch - { - // ignored - } - } - - if (item == null) - return; // Sanity - - if (pm.AddToBackpack(item)) - { - pm.ToTItemsTurnedIn -= TreasuresOfTokuno.ItemsPerReward; - m_Collector.SayTo(pm, 1070984, - item.Name == null || item.Name.Length <= 0 - ? $"#{item.LabelNumber}" - : item.Name); // You have earned the gratitude of the Empire. I have placed the ~1_OBJTYPE~ in your backpack. - } - else - { - item.Delete(); - m_Collector.SayTo(pm, 500722); // You don't have enough room in your backpack! - m_Collector.SayTo(pm, 1070982); // When you wish to choose your reward, you have but to approach me again. - } - } - - public override void HandleCancel(NetState sender) - { - if (!(sender.Mobile is PlayerMobile pm) || !pm.InRange(m_Collector.Location, 7)) - return; - - if (pm.ToTItemsTurnedIn == 0) - m_Collector.SayTo(pm, - 1071013); // Bring me 10 of the lost treasures of Tokuno and I will reward you with a valuable item. - else if (pm.ToTItemsTurnedIn < TreasuresOfTokuno.ItemsPerReward) // This and above case should ALWAYS be FALSE with this gump, jsut a sanity check - m_Collector.SayTo(pm, 1070981, - $"{pm.ToTItemsTurnedIn}\t{TreasuresOfTokuno.ItemsPerReward}"); // You have turned in ~1_COUNT~ minor artifacts. Turn in ~2_NUM~ to receive a reward. - else - m_Collector.SayTo(pm, 1070982); // When you wish to choose your reward, you have but to approach me again. - } - - public class TypeTileButtonInfo : ImageTileButtonInfo - { - public TypeTileButtonInfo(Type type, int itemID, TextDefinition label, int localizedToolTip = -1) : this(type, itemID, - 0, label, localizedToolTip) - { - } - - public TypeTileButtonInfo(Type type, int itemID, int hue, TextDefinition label, int localizedToolTip = -1) : base( - itemID, hue, label, localizedToolTip) => - Type = type; - - public Type Type { get; } - } - - public class PigmentsTileButtonInfo : ImageTileButtonInfo - { - public PigmentsTileButtonInfo(PigmentType p) : base(0xEFF, PigmentsOfTokuno.GetInfo(p)[0], - PigmentsOfTokuno.GetInfo(p)[1]) => - Pigment = p; - - public PigmentType Pigment { get; set; } - } - } -} - -/* Notes - -Pigments of tokuno do NOT check for if item is already hued 0; APPARENTLY he still accepts it if it's < 10 charges. - -Chest of Heirlooms don't show if unlocked. - -Chest of heirlooms, locked, HARD to pick at 100 lock picking but not impossible. had 95 health to 0, cause it's trapped >< (explosion i think) -*/ +using System; +using System.Collections.Generic; +using System.Linq; +using Server.Gumps; +using Server.Items; +using Server.Misc; +using Server.Mobiles; +using Server.Multis; +using Server.Network; +using Server.Regions; +using Server.Utilities; + +namespace Server.Misc +{ + public enum TreasuresOfTokunoEra + { + None, + ToTOne, + ToTTwo, + ToTThree + } + + public class TreasuresOfTokuno + { + public const int ItemsPerReward = 10; + + private static readonly Type[][] m_LesserArtifacts = + { + // ToT One Rewards + new[] + { + typeof(AncientFarmersKasa), typeof(AncientSamuraiDo), typeof(ArmsOfTacticalExcellence), + typeof(BlackLotusHood), + typeof(DaimyosHelm), typeof(DemonForks), typeof(DragonNunchaku), typeof(Exiler), typeof(GlovesOfTheSun), + typeof(HanzosBow), typeof(LegsOfStability), typeof(PeasantsBokuto), typeof(PilferedDancerFans), + typeof(TheDestroyer), + typeof(TomeOfEnlightenment), typeof(AncientUrn), typeof(HonorableSwords), typeof(PigmentsOfTokuno), + typeof(FluteOfRenewal), typeof(ChestOfHeirlooms) + }, + // ToT Two Rewards + new[] + { + typeof(MetalPigmentsOfTokuno), typeof(AncientFarmersKasa), typeof(AncientSamuraiDo), + typeof(ArmsOfTacticalExcellence), + typeof(MetalPigmentsOfTokuno), typeof(BlackLotusHood), typeof(DaimyosHelm), typeof(DemonForks), + typeof(MetalPigmentsOfTokuno), typeof(DragonNunchaku), typeof(Exiler), typeof(GlovesOfTheSun), + typeof(HanzosBow), + typeof(MetalPigmentsOfTokuno), typeof(LegsOfStability), typeof(PeasantsBokuto), typeof(PilferedDancerFans), + typeof(TheDestroyer), + typeof(MetalPigmentsOfTokuno), typeof(TomeOfEnlightenment), typeof(AncientUrn), typeof(HonorableSwords), + typeof(MetalPigmentsOfTokuno), typeof(FluteOfRenewal), typeof(ChestOfHeirlooms) + }, + // ToT Three Rewards + new[] + { + typeof(LesserPigmentsOfTokuno), typeof(AncientFarmersKasa), typeof(AncientSamuraiDo), + typeof(ArmsOfTacticalExcellence), + typeof(LesserPigmentsOfTokuno), typeof(BlackLotusHood), typeof(DaimyosHelm), typeof(HanzosBow), + typeof(LesserPigmentsOfTokuno), typeof(DemonForks), typeof(DragonNunchaku), typeof(Exiler), + typeof(GlovesOfTheSun), + typeof(LesserPigmentsOfTokuno), typeof(LegsOfStability), typeof(PeasantsBokuto), typeof(PilferedDancerFans), + typeof(TheDestroyer), + typeof(LesserPigmentsOfTokuno), typeof(TomeOfEnlightenment), typeof(AncientUrn), typeof(HonorableSwords), + typeof(FluteOfRenewal), + typeof(LesserPigmentsOfTokuno), typeof(LeurociansMempoOfFortune), typeof(ChestOfHeirlooms) + } + }; + + private static Type[][] m_GreaterArtifacts; + + public static Type[] LesserArtifactsTotal { get; } = + { + typeof(AncientFarmersKasa), typeof(AncientSamuraiDo), typeof(ArmsOfTacticalExcellence), typeof(BlackLotusHood), + typeof(DaimyosHelm), typeof(DemonForks), typeof(DragonNunchaku), typeof(Exiler), typeof(GlovesOfTheSun), + typeof(HanzosBow), typeof(LegsOfStability), typeof(PeasantsBokuto), typeof(PilferedDancerFans), + typeof(TheDestroyer), + typeof(TomeOfEnlightenment), typeof(AncientUrn), typeof(HonorableSwords), typeof(PigmentsOfTokuno), + typeof(FluteOfRenewal), + typeof(LeurociansMempoOfFortune), typeof(LesserPigmentsOfTokuno), typeof(MetalPigmentsOfTokuno), + typeof(ChestOfHeirlooms) + }; + + public static TreasuresOfTokunoEra DropEra { get; set; } = TreasuresOfTokunoEra.None; + + public static TreasuresOfTokunoEra RewardEra { get; set; } = TreasuresOfTokunoEra.ToTOne; + + public static Type[] LesserArtifacts => m_LesserArtifacts[(int)RewardEra - 1]; + + public static Type[] GreaterArtifacts + { + get + { + if (m_GreaterArtifacts == null) + { + m_GreaterArtifacts = new Type[ToTRedeemGump.NormalRewards.Length][]; + + for (var i = 0; i < m_GreaterArtifacts.Length; i++) + { + m_GreaterArtifacts[i] = new Type[ToTRedeemGump.NormalRewards[i].Length]; + + for (var j = 0; j < m_GreaterArtifacts[i].Length; j++) + m_GreaterArtifacts[i][j] = ToTRedeemGump.NormalRewards[i][j].Type; + } + } + + return m_GreaterArtifacts[(int)RewardEra - 1]; + } + } + + private static bool CheckLocation(Mobile m) + { + var r = m.Region; + + if (r.IsPartOf() || BaseBoat.FindBoatAt(m, m.Map) != null) + return false; + // TODO: a CanReach of something check as opposed to above? + + if (r.IsPartOf("Yomotsu Mines") || r.IsPartOf("Fan Dancer's Dojo")) + return true; + + return m.Map == Map.Tokuno; + } + + public static void HandleKill(Mobile victim, Mobile killer) + { + if (DropEra == TreasuresOfTokunoEra.None || !(killer is PlayerMobile pm) || !(victim is BaseCreature bc) || + !CheckLocation(bc) || !CheckLocation(pm) || !killer.InRange(victim, 18)) + return; + + if (bc.Controlled || bc.Owners.Count > 0 || bc.Fame <= 0) + return; + + // 25000 for 1/100 chance, 10 hyrus + // 1500, 1/1000 chance, 20 lizard men for that chance. + + pm.ToTTotalMonsterFame += (int)(bc.Fame * (1 + Math.Sqrt(pm.Luck) / 100)); + + // This is the Exponentional regression with only 2 datapoints. + // A log. func would also work, but it didn't make as much sense. + // This function isn't OSI exact being that I don't know OSI's func they used ;p + var x = pm.ToTTotalMonsterFame; + + // const double A = 8.63316841 * Math.Pow( 10, -4 ); + const double A = 0.000863316841; + // const double B = 4.25531915 * Math.Pow( 10, -6 ); + const double B = 0.00000425531915; + + var chance = A * Math.Pow(10, B * x); + + if (chance > Utility.RandomDouble()) + { + Item i = null; + + try + { + i = ActivatorUtil.CreateInstance( + m_LesserArtifacts[(int)DropEra - 1].RandomElement() + ) + as + Item; + } + catch + { + // ignored + } + + if (i != null) + { + pm.SendLocalizedMessage( + 1062317 + ); // For your valor in combating the fallen beast, a special artifact has been bestowed on you. + + if (!pm.PlaceInBackpack(i)) + { + if (pm.BankBox?.TryDropItem(killer, i, false) == true) + { + pm.SendLocalizedMessage(1079730); // The item has been placed into your bank box. + } + else + { + pm.SendLocalizedMessage( + 1072523 + ); // You find an artifact, but your backpack and bank are too full to hold it. + i.MoveToWorld(pm.Location, pm.Map); + } + } + + pm.ToTTotalMonsterFame = 0; + } + } + } + } +} + +namespace Server.Mobiles +{ + public class IharaSoko : BaseVendor + { + protected List m_SBInfos = new List(); + + [Constructible] + public IharaSoko() : base("the Imperial Minister of Trade") + { + Female = false; + Body = 0x190; + Hue = 0x8403; + } + + public IharaSoko(Serial serial) : base(serial) + { + } + + public override bool IsActiveVendor => false; + public override bool IsInvulnerable => true; + public override bool DisallowAllMoves => true; + public override bool ClickTitle => true; + public override bool CanTeach => false; + public override string DefaultName => "Ihara Soko"; + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + } + + public override void InitOutfit() + { + AddItem(new Waraji(0x711)); + AddItem(new Backpack()); + AddItem(new Kamishimo(0x483)); + + Item item = new LightPlateJingasa(); + item.Hue = 0x711; + + AddItem(item); + } + + 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(); + } + + public override bool CanBeDamaged() => false; + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (m.Alive && m is PlayerMobile pm) + { + var range = 3; + + if (pm.Alive && Math.Abs(Z - pm.Z) < 16 && InRange(m, range) && !InRange(oldLocation, range)) + { + if (pm.ToTItemsTurnedIn >= TreasuresOfTokuno.ItemsPerReward) + { + SayTo( + pm, + 1070980 + ); // Congratulations! You have turned in enough minor treasures to earn a greater reward. + + pm.CloseGump(); // Sanity + + if (!pm.HasGump()) + pm.SendGump(new ToTRedeemGump(this, false)); + } + else + { + if (pm.ToTItemsTurnedIn == 0) + SayTo( + pm, + 1071013 + ); // Bring me 10 of the lost treasures of Tokuno and I will reward you with a valuable item. + else + SayTo( + pm, + 1070981, + $"{pm.ToTItemsTurnedIn}\t{TreasuresOfTokuno.ItemsPerReward}" + ); // You have turned in ~1_COUNT~ minor artifacts. Turn in ~2_NUM~ to receive a reward. + + var buttons = ToTTurnInGump.FindRedeemableItems(pm); + + if (buttons.Count > 0 && !pm.HasGump()) + pm.SendGump(new ToTTurnInGump(this, buttons)); + } + } + + var leaveRange = 7; + + if (!InRange(m, leaveRange) && InRange(oldLocation, leaveRange)) + { + pm.CloseGump(); + pm.CloseGump(); + } + } + } + + public override void TurnToTokuno() + { + } + } +} + +namespace Server.Gumps +{ + public class ItemTileButtonInfo : ImageTileButtonInfo + { + public ItemTileButtonInfo(Item i) : base( + i.ItemID, + i.Hue, + i.Name == null || i.Name.Length <= 0 ? (TextDefinition)i.LabelNumber : (TextDefinition)i.Name + ) => + Item = i; + + public Item Item { get; set; } + } + + public class ToTTurnInGump : BaseImageTileButtonsGump + { + private readonly Mobile m_Collector; + + public ToTTurnInGump(Mobile collector, List buttons) : base( + 1071012, + Utility.CastListContravariant(buttons) + ) // Click a minor artifact to give it to Ihara Soko. + => + m_Collector = collector; + + public static List FindRedeemableItems(Mobile m) + { + var pack = m.Backpack; + if (pack == null) + return new List(); + + var buttons = new List(); + + var items = pack.FindItemsByType(TreasuresOfTokuno.LesserArtifactsTotal); + + for (var i = 0; i < items.Length; i++) + { + var item = items[i]; + if (item is ChestOfHeirlooms heirlooms && !heirlooms.Locked) + continue; + + if (item is ChestOfHeirlooms ofHeirlooms && ofHeirlooms.TrapLevel != 10) + continue; + + if (item is PigmentsOfTokuno tokuno && tokuno.Type != PigmentType.None) + continue; + + buttons.Add(new ItemTileButtonInfo(item)); + } + + return buttons; + } + + public override void HandleButtonResponse(NetState sender, int adjustedButton, ImageTileButtonInfo buttonInfo) + { + var pm = sender.Mobile as PlayerMobile; + + var item = ((ItemTileButtonInfo)buttonInfo).Item; + + if (!(pm != null && item.IsChildOf(pm.Backpack) && pm.InRange(m_Collector.Location, 7))) + return; + + item.Delete(); + + if (++pm.ToTItemsTurnedIn >= TreasuresOfTokuno.ItemsPerReward) + { + m_Collector.SayTo( + pm, + 1070980 + ); // Congratulations! You have turned in enough minor treasures to earn a greater reward. + + pm.CloseGump(); // Sanity + + if (!pm.HasGump()) + pm.SendGump(new ToTRedeemGump(m_Collector, false)); + } + else + { + m_Collector.SayTo( + pm, + 1070981, + $"{pm.ToTItemsTurnedIn}\t{TreasuresOfTokuno.ItemsPerReward}" + ); // You have turned in ~1_COUNT~ minor artifacts. Turn in ~2_NUM~ to receive a reward. + + var buttons = FindRedeemableItems(pm); + + pm.CloseGump(); // Sanity + + if (buttons.Count > 0) + pm.SendGump(new ToTTurnInGump(m_Collector, buttons)); + } + } + + public override void HandleCancel(NetState sender) + { + if (!(sender.Mobile is PlayerMobile pm) || !pm.InRange(m_Collector.Location, 7)) + return; + + if (pm.ToTItemsTurnedIn == 0) + m_Collector.SayTo( + pm, + 1071013 + ); // Bring me 10 of the lost treasures of Tokuno and I will reward you with a valuable item. + else if (pm.ToTItemsTurnedIn < TreasuresOfTokuno.ItemsPerReward + ) // This case should ALWAYS be true with this gump, jsut a sanity check + m_Collector.SayTo( + pm, + 1070981, + $"{pm.ToTItemsTurnedIn}\t{TreasuresOfTokuno.ItemsPerReward}" + ); // You have turned in ~1_COUNT~ minor artifacts. Turn in ~2_NUM~ to receive a reward. + else + m_Collector.SayTo(pm, 1070982); // When you wish to choose your reward, you have but to approach me again. + } + } + + public class ToTRedeemGump : BaseImageTileButtonsGump + { + private readonly Mobile m_Collector; + + public ToTRedeemGump(Mobile collector, bool pigments) : base( + pigments ? 1070986 : 1070985, + pigments + ? PigmentRewards[(int)TreasuresOfTokuno.RewardEra - 1].ToArray() + : NormalRewards[(int)TreasuresOfTokuno.RewardEra - 1].ToArray() + ) => + m_Collector = collector; + + public static TypeTileButtonInfo[][] NormalRewards { get; } = + { + // ToT One Rewards + new[] + { + new TypeTileButtonInfo(typeof(SwordsOfProsperity), 0x27A9, 1070963, 1071002), + new TypeTileButtonInfo(typeof(SwordOfTheStampede), 0x27A2, 1070964, 1070978), + new TypeTileButtonInfo(typeof(WindsEdge), 0x27A3, 1070965, 1071003), + new TypeTileButtonInfo(typeof(DarkenedSky), 0x27AD, 1070966, 1071004), + new TypeTileButtonInfo(typeof(TheHorselord), 0x27A5, 1070967, 1071005), + new TypeTileButtonInfo(typeof(RuneBeetleCarapace), 0x277D, 1070968, 1071006), + new TypeTileButtonInfo(typeof(KasaOfTheRajin), 0x2798, 1070969, 1071007), + new TypeTileButtonInfo(typeof(Stormgrip), 0x2792, 1070970, 1071008), + new TypeTileButtonInfo(typeof(TomeOfLostKnowledge), 0x0EFA, 0x530, 1070971, 1071009), + new TypeTileButtonInfo(typeof(PigmentsOfTokuno), 0x0EFF, 1070933, 1071011) + }, + // ToT Two Rewards + new[] + { + new TypeTileButtonInfo(typeof(SwordsOfProsperity), 0x27A9, 1070963, 1071002), + new TypeTileButtonInfo(typeof(SwordOfTheStampede), 0x27A2, 1070964, 1070978), + new TypeTileButtonInfo(typeof(WindsEdge), 0x27A3, 1070965, 1071003), + new TypeTileButtonInfo(typeof(DarkenedSky), 0x27AD, 1070966, 1071004), + new TypeTileButtonInfo(typeof(TheHorselord), 0x27A5, 1070967, 1071005), + new TypeTileButtonInfo(typeof(RuneBeetleCarapace), 0x277D, 1070968, 1071006), + new TypeTileButtonInfo(typeof(KasaOfTheRajin), 0x2798, 1070969, 1071007), + new TypeTileButtonInfo(typeof(Stormgrip), 0x2792, 1070970, 1071008), + new TypeTileButtonInfo(typeof(TomeOfLostKnowledge), 0x0EFA, 0x530, 1070971, 1071009), + new TypeTileButtonInfo(typeof(PigmentsOfTokuno), 0x0EFF, 1070933, 1071011) + }, + // ToT Three Rewards + new[] + { + new TypeTileButtonInfo(typeof(SwordsOfProsperity), 0x27A9, 1070963, 1071002), + new TypeTileButtonInfo(typeof(SwordOfTheStampede), 0x27A2, 1070964, 1070978), + new TypeTileButtonInfo(typeof(WindsEdge), 0x27A3, 1070965, 1071003), + new TypeTileButtonInfo(typeof(DarkenedSky), 0x27AD, 1070966, 1071004), + new TypeTileButtonInfo(typeof(TheHorselord), 0x27A5, 1070967, 1071005), + new TypeTileButtonInfo(typeof(RuneBeetleCarapace), 0x277D, 1070968, 1071006), + new TypeTileButtonInfo(typeof(KasaOfTheRajin), 0x2798, 1070969, 1071007), + new TypeTileButtonInfo(typeof(Stormgrip), 0x2792, 1070970, 1071008), + new TypeTileButtonInfo(typeof(TomeOfLostKnowledge), 0x0EFA, 0x530, 1070971, 1071009) + } + }; + + public static PigmentsTileButtonInfo[][] PigmentRewards { get; } = + { + // ToT One Pigment Rewards + new[] + { + new PigmentsTileButtonInfo(PigmentType.ParagonGold), + new PigmentsTileButtonInfo(PigmentType.VioletCouragePurple), + new PigmentsTileButtonInfo(PigmentType.InvulnerabilityBlue), + new PigmentsTileButtonInfo(PigmentType.LunaWhite), + new PigmentsTileButtonInfo(PigmentType.DryadGreen), + new PigmentsTileButtonInfo(PigmentType.ShadowDancerBlack), + new PigmentsTileButtonInfo(PigmentType.BerserkerRed), + new PigmentsTileButtonInfo(PigmentType.NoxGreen), + new PigmentsTileButtonInfo(PigmentType.RumRed), + new PigmentsTileButtonInfo(PigmentType.FireOrange) + }, + // ToT Two Pigment Rewards + new[] + { + new PigmentsTileButtonInfo(PigmentType.FadedCoal), + new PigmentsTileButtonInfo(PigmentType.Coal), + new PigmentsTileButtonInfo(PigmentType.FadedGold), + new PigmentsTileButtonInfo(PigmentType.StormBronze), + new PigmentsTileButtonInfo(PigmentType.Rose), + new PigmentsTileButtonInfo(PigmentType.MidnightCoal), + new PigmentsTileButtonInfo(PigmentType.FadedBronze), + new PigmentsTileButtonInfo(PigmentType.FadedRose), + new PigmentsTileButtonInfo(PigmentType.DeepRose) + }, + // ToT Three Pigment Rewards + new[] + { + new PigmentsTileButtonInfo(PigmentType.ParagonGold), + new PigmentsTileButtonInfo(PigmentType.VioletCouragePurple), + new PigmentsTileButtonInfo(PigmentType.InvulnerabilityBlue), + new PigmentsTileButtonInfo(PigmentType.LunaWhite), + new PigmentsTileButtonInfo(PigmentType.DryadGreen), + new PigmentsTileButtonInfo(PigmentType.ShadowDancerBlack), + new PigmentsTileButtonInfo(PigmentType.BerserkerRed), + new PigmentsTileButtonInfo(PigmentType.NoxGreen), + new PigmentsTileButtonInfo(PigmentType.RumRed), + new PigmentsTileButtonInfo(PigmentType.FireOrange) + } + }; + + public override void HandleButtonResponse(NetState sender, int adjustedButton, ImageTileButtonInfo buttonInfo) + { + if (!(sender.Mobile is PlayerMobile pm) || !pm.InRange(m_Collector.Location, 7) || + !(pm.ToTItemsTurnedIn >= TreasuresOfTokuno.ItemsPerReward)) + return; + + Item item = null; + + if (buttonInfo is PigmentsTileButtonInfo p) + { + item = new PigmentsOfTokuno(p.Pigment); + } + else + { + var t = (TypeTileButtonInfo)buttonInfo; + + if (t.Type == typeof(PigmentsOfTokuno)) // Special case of course. + { + pm.CloseGump(); // Sanity + pm.CloseGump(); + + pm.SendGump(new ToTRedeemGump(m_Collector, true)); + + return; + } + + try + { + item = (Item)ActivatorUtil.CreateInstance(t.Type); + } + catch + { + // ignored + } + } + + if (item == null) + return; // Sanity + + if (pm.AddToBackpack(item)) + { + pm.ToTItemsTurnedIn -= TreasuresOfTokuno.ItemsPerReward; + m_Collector.SayTo( + pm, + 1070984, + item.Name == null || item.Name.Length <= 0 + ? $"#{item.LabelNumber}" + : item.Name + ); // You have earned the gratitude of the Empire. I have placed the ~1_OBJTYPE~ in your backpack. + } + else + { + item.Delete(); + m_Collector.SayTo(pm, 500722); // You don't have enough room in your backpack! + m_Collector.SayTo(pm, 1070982); // When you wish to choose your reward, you have but to approach me again. + } + } + + public override void HandleCancel(NetState sender) + { + if (!(sender.Mobile is PlayerMobile pm) || !pm.InRange(m_Collector.Location, 7)) + return; + + if (pm.ToTItemsTurnedIn == 0) + m_Collector.SayTo( + pm, + 1071013 + ); // Bring me 10 of the lost treasures of Tokuno and I will reward you with a valuable item. + else if (pm.ToTItemsTurnedIn < TreasuresOfTokuno.ItemsPerReward + ) // This and above case should ALWAYS be FALSE with this gump, jsut a sanity check + m_Collector.SayTo( + pm, + 1070981, + $"{pm.ToTItemsTurnedIn}\t{TreasuresOfTokuno.ItemsPerReward}" + ); // You have turned in ~1_COUNT~ minor artifacts. Turn in ~2_NUM~ to receive a reward. + else + m_Collector.SayTo(pm, 1070982); // When you wish to choose your reward, you have but to approach me again. + } + + public class TypeTileButtonInfo : ImageTileButtonInfo + { + public TypeTileButtonInfo(Type type, int itemID, TextDefinition label, int localizedToolTip = -1) : this( + type, + itemID, + 0, + label, + localizedToolTip + ) + { + } + + public TypeTileButtonInfo( + Type type, int itemID, int hue, TextDefinition label, int localizedToolTip = -1 + ) : base( + itemID, + hue, + label, + localizedToolTip + ) => + Type = type; + + public Type Type { get; } + } + + public class PigmentsTileButtonInfo : ImageTileButtonInfo + { + public PigmentsTileButtonInfo(PigmentType p) : base( + 0xEFF, + PigmentsOfTokuno.GetInfo(p)[0], + PigmentsOfTokuno.GetInfo(p)[1] + ) => + Pigment = p; + + public PigmentType Pigment { get; set; } + } + } +} + +/* Notes + +Pigments of tokuno do NOT check for if item is already hued 0; APPARENTLY he still accepts it if it's < 10 charges. + +Chest of Heirlooms don't show if unlocked. + +Chest of heirlooms, locked, HARD to pick at 100 lock picking but not impossible. had 95 health to 0, cause it's trapped >< (explosion i think) +*/ diff --git a/Projects/UOContent/Engines/Treasures of Tokuno/TreasuresOfTokunoPersistance.cs b/Projects/UOContent/Engines/Treasures of Tokuno/TreasuresOfTokunoPersistance.cs index 368c0bc3c..08c01b964 100644 --- a/Projects/UOContent/Engines/Treasures of Tokuno/TreasuresOfTokunoPersistance.cs +++ b/Projects/UOContent/Engines/Treasures of Tokuno/TreasuresOfTokunoPersistance.cs @@ -1,59 +1,59 @@ -namespace Server.Misc -{ - public class TreasuresOfTokunoPersistance : Item - { - public TreasuresOfTokunoPersistance() : base(1) - { - Movable = false; - - if (Instance?.Deleted != false) - Instance = this; - else - base.Delete(); - } - - public TreasuresOfTokunoPersistance(Serial serial) : base(serial) => Instance = this; - - public static TreasuresOfTokunoPersistance Instance { get; private set; } - - public override string DefaultName => "TreasuresOfTokuno Persistance - Internal"; - - public static void Initialize() - { - if (Instance == null) - new TreasuresOfTokunoPersistance(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.WriteEncodedInt((int)TreasuresOfTokuno.RewardEra); - writer.WriteEncodedInt((int)TreasuresOfTokuno.DropEra); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - TreasuresOfTokuno.RewardEra = (TreasuresOfTokunoEra)reader.ReadEncodedInt(); - TreasuresOfTokuno.DropEra = (TreasuresOfTokunoEra)reader.ReadEncodedInt(); - - break; - } - } - } - - public override void Delete() - { - } - } -} +namespace Server.Misc +{ + public class TreasuresOfTokunoPersistance : Item + { + public TreasuresOfTokunoPersistance() : base(1) + { + Movable = false; + + if (Instance?.Deleted != false) + Instance = this; + else + base.Delete(); + } + + public TreasuresOfTokunoPersistance(Serial serial) : base(serial) => Instance = this; + + public static TreasuresOfTokunoPersistance Instance { get; private set; } + + public override string DefaultName => "TreasuresOfTokuno Persistance - Internal"; + + public static void Initialize() + { + if (Instance == null) + new TreasuresOfTokunoPersistance(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.WriteEncodedInt((int)TreasuresOfTokuno.RewardEra); + writer.WriteEncodedInt((int)TreasuresOfTokuno.DropEra); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + TreasuresOfTokuno.RewardEra = (TreasuresOfTokunoEra)reader.ReadEncodedInt(); + TreasuresOfTokuno.DropEra = (TreasuresOfTokunoEra)reader.ReadEncodedInt(); + + break; + } + } + } + + public override void Delete() + { + } + } +} diff --git a/Projects/UOContent/Engines/VeteranRewards/Character Statue Maker/CharacterStatue.cs b/Projects/UOContent/Engines/VeteranRewards/Character Statue Maker/CharacterStatue.cs index e49b386a2..2a118abee 100644 --- a/Projects/UOContent/Engines/VeteranRewards/Character Statue Maker/CharacterStatue.cs +++ b/Projects/UOContent/Engines/VeteranRewards/Character Statue Maker/CharacterStatue.cs @@ -1,661 +1,667 @@ -using System; -using System.Collections.Generic; -using Server.Accounting; -using Server.ContextMenus; -using Server.Engines.VeteranRewards; -using Server.Gumps; -using Server.Items; -using Server.Multis; -using Server.Network; -using Server.Spells; -using Server.Targeting; - -namespace Server.Mobiles -{ - public enum StatueType - { - Marble, - Jade, - Bronze - } - - public enum StatuePose - { - Ready, - Casting, - Salute, - AllPraiseMe, - Fighting, - HandsOnHips - } - - public enum StatueMaterial - { - Antique, - Dark, - Medium, - Light - } - - public class CharacterStatue : Mobile, IRewardItem - { - private int m_Animation; - private int m_Frames; - private StatueMaterial m_Material; - private StatuePose m_Pose; - - private Mobile m_SculptedBy; - private StatueType m_Type; - - public CharacterStatue(Mobile from, StatueType type) - { - m_Type = type; - m_Pose = StatuePose.Ready; - m_Material = StatueMaterial.Antique; - - Direction = Direction.South; - AccessLevel = AccessLevel.Counselor; - Hits = HitsMax; - Blessed = true; - Frozen = true; - - CloneBody(from); - CloneClothes(from); - InvalidateHues(); - } - - public CharacterStatue(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public StatueType StatueType - { - get => m_Type; - set - { - m_Type = value; - InvalidateHues(); - InvalidatePose(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public StatuePose Pose - { - get => m_Pose; - set - { - m_Pose = value; - InvalidatePose(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public StatueMaterial Material - { - get => m_Material; - set - { - m_Material = value; - InvalidateHues(); - InvalidatePose(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile SculptedBy - { - get => m_SculptedBy; - set - { - m_SculptedBy = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime SculptedOn { get; set; } - - public CharacterStatuePlinth Plinth { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem { get; set; } - - public override void OnDoubleClick(Mobile from) - { - DisplayPaperdollTo(from); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_SculptedBy != null) - { - if (m_SculptedBy.ShowFameTitle && (m_SculptedBy.Player || m_SculptedBy.Body.IsHuman) && - m_SculptedBy.Fame >= 10000) - list.Add(1076202, - $"{(m_SculptedBy.Female ? "Lady" : "Lord")} {m_SculptedBy.Name}"); // Sculpted by ~1_Name~ - else - list.Add(1076202, m_SculptedBy.Name); // Sculpted by ~1_Name~ - } - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (from.Alive && m_SculptedBy != null) - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (house?.IsCoOwner(from) == true || from.AccessLevel > AccessLevel.Counselor) - list.Add(new DemolishEntry(this)); - } - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - if (Plinth?.Deleted == false) - Plinth.Delete(); - } - - protected override void OnMapChange(Map oldMap) - { - InvalidatePose(); - - if (Plinth != null) - Plinth.Map = Map; - } - - protected override void OnLocationChange(Point3D oldLocation) - { - InvalidatePose(); - - if (Plinth != null) - Plinth.Location = new Point3D(X, Y, Z - 5); - } - - public override bool CanBeRenamedBy(Mobile from) => false; - - public override bool CanBeDamaged() => false; - - public void OnRequestedAnimation(Mobile from) - { - from.Send(new UpdateStatueAnimation(this, 1, m_Animation, m_Frames)); - } - - public override void OnAosSingleClick(Mobile from) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write((int)m_Type); - writer.Write((int)m_Pose); - writer.Write((int)m_Material); - - writer.Write(m_SculptedBy); - writer.Write(SculptedOn); - - writer.Write(Plinth); - writer.Write(IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_Type = (StatueType)reader.ReadInt(); - m_Pose = (StatuePose)reader.ReadInt(); - m_Material = (StatueMaterial)reader.ReadInt(); - - m_SculptedBy = reader.ReadMobile(); - SculptedOn = reader.ReadDateTime(); - - Plinth = reader.ReadItem() as CharacterStatuePlinth; - IsRewardItem = reader.ReadBool(); - - InvalidatePose(); - - Frozen = true; - - if (m_SculptedBy == null || Map == Map.Internal) // Remove preview statues - Timer.DelayCall(Delete); - } - - public void Sculpt(Mobile by) - { - m_SculptedBy = by; - SculptedOn = DateTime.UtcNow; - - InvalidateProperties(); - } - - public bool Demolish(Mobile by) - { - CharacterStatueDeed deed = new CharacterStatueDeed(null); - - if (by.PlaceInBackpack(deed)) - { - Delete(); - - deed.Statue = this; - deed.StatueType = m_Type; - deed.IsRewardItem = IsRewardItem; - - Plinth?.Delete(); - - return true; - } - - by.SendLocalizedMessage(500720); // You don't have enough room in your backpack! - deed.Delete(); - - return false; - } - - public void Restore(CharacterStatue from) - { - m_Material = from.Material; - m_Pose = from.Pose; - - Direction = from.Direction; - - CloneBody(from); - CloneClothes(from); - - InvalidateHues(); - InvalidatePose(); - } - - public void CloneBody(Mobile from) - { - Name = from.Name; - BodyValue = from.BodyValue; - Female = from.Female; - HairItemID = from.HairItemID; - FacialHairItemID = from.FacialHairItemID; - } - - public void CloneClothes(Mobile from) - { - for (int i = Items.Count - 1; i >= 0; i--) - Items[i].Delete(); - - for (int i = from.Items.Count - 1; i >= 0; i--) - { - Item item = from.Items[i]; - - if (item.Layer != Layer.Backpack && item.Layer != Layer.Mount && item.Layer != Layer.Bank) - AddItem(CloneItem(item)); - } - } - - public Item CloneItem(Item item) - { - Item cloned = new Item(item.ItemID) - { - Layer = item.Layer, - Name = item.Name, - Hue = item.Hue, - Weight = item.Weight, - Movable = false - }; - - return cloned; - } - - public void InvalidateHues() - { - Hue = 0xB8F + (int)m_Type * 4 + (int)m_Material; - - HairHue = Hue; - - if (FacialHairItemID > 0) - FacialHairHue = Hue; - - for (int i = Items.Count - 1; i >= 0; i--) - Items[i].Hue = Hue; - - Plinth?.InvalidateHue(); - } - - public void InvalidatePose() - { - switch (m_Pose) - { - case StatuePose.Ready: - m_Animation = 4; - m_Frames = 0; - break; - case StatuePose.Casting: - m_Animation = 16; - m_Frames = 2; - break; - case StatuePose.Salute: - m_Animation = 33; - m_Frames = 1; - break; - case StatuePose.AllPraiseMe: - m_Animation = 17; - m_Frames = 4; - break; - case StatuePose.Fighting: - m_Animation = 31; - m_Frames = 5; - break; - case StatuePose.HandsOnHips: - m_Animation = 6; - m_Frames = 1; - break; - } - - if (Map != null) - { - ProcessDelta(); - - Packet p = null; - - IPooledEnumerable eable = Map.GetClientsInRange(Location); - - foreach (NetState state in eable) - { - state.Mobile.ProcessDelta(); - - p ??= Packet.Acquire(new UpdateStatueAnimation(this, 1, m_Animation, m_Frames)); - - state.Send(p); - } - - Packet.Release(p); - - eable.Free(); - } - } - - private class DemolishEntry : ContextMenuEntry - { - private readonly CharacterStatue m_Statue; - - public DemolishEntry(CharacterStatue statue) : base(6275, 2) => m_Statue = statue; - - public override void OnClick() - { - if (m_Statue.Deleted) - return; - - m_Statue.Demolish(Owner.From); - } - } - } - - public class CharacterStatueDeed : Item, IRewardItem - { - private bool m_IsRewardItem; - - private StatueType m_Type; - - public CharacterStatueDeed(CharacterStatue statue) : base(0x14F0) - { - Statue = statue; - - if (statue != null) - { - m_Type = statue.StatueType; - m_IsRewardItem = statue.IsRewardItem; - } - - LootType = LootType.Blessed; - Weight = 1.0; - } - - public CharacterStatueDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber - { - get - { - StatueType t = m_Type; - - if (Statue != null) t = Statue.StatueType; - - return t switch - { - StatueType.Marble => 1076189, - StatueType.Jade => 1076188, - StatueType.Bronze => 1076190, - _ => 1076173 - }; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public CharacterStatue Statue { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public StatueType StatueType - { - get - { - if (Statue != null) - return Statue.StatueType; - - return m_Type; - } - set => m_Type = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_IsRewardItem) - list.Add(1076222); // 6th Year Veteran Reward - - if (Statue != null) - list.Add(1076231, Statue.Name); // Statue of ~1_Name~ - } - - public override void OnDoubleClick(Mobile from) - { - if (from.Account is Account acct && from.AccessLevel == AccessLevel.Player) - { - TimeSpan time = TimeSpan.FromDays(RewardSystem.RewardInterval.TotalDays * 6) - - (DateTime.UtcNow - acct.Created); - - if (time > TimeSpan.Zero) - { - from.SendLocalizedMessage(1008126, true, - Math.Ceiling(time.TotalDays / RewardSystem.RewardInterval.TotalDays) - .ToString()); // Your account is not old enough to use this item. Months until you can use this item : - return; - } - } - - if (IsChildOf(from.Backpack)) - { - if (!from.IsBodyMod) - { - from.SendLocalizedMessage(1076194); // Select a place where you would like to put your statue. - from.Target = new CharacterStatueTarget(this, StatueType); - } - else - { - from.SendLocalizedMessage(1073648); // You may only proceed while in your original state... - } - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - - public override void OnDelete() - { - base.OnDelete(); - - Statue?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(1); // version - - writer.Write((int)m_Type); - - writer.Write(Statue); - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - if (version >= 1) m_Type = (StatueType)reader.ReadInt(); - - Statue = reader.ReadMobile() as CharacterStatue; - m_IsRewardItem = reader.ReadBool(); - } - } - - public class CharacterStatueTarget : Target - { - private readonly Item m_Maker; - private readonly StatueType m_Type; - - public CharacterStatueTarget(Item maker, StatueType type) : base(-1, true, TargetFlags.None) - { - m_Maker = maker; - m_Type = type; - } - - protected override void OnTarget(Mobile from, object targeted) - { - IPoint3D p = targeted as IPoint3D; - Map map = from.Map; - - if (p == null || map == null || m_Maker?.Deleted != false) - return; - - if (m_Maker.IsChildOf(from.Backpack)) - { - SpellHelper.GetSurfaceTop(ref p); - BaseHouse house = null; - Point3D loc = new Point3D(p); - - if (targeted is Item item && !item.IsLockedDown && !item.IsSecure && !(item is AddonComponent)) - { - from.SendLocalizedMessage(1076191); // Statues can only be placed in houses. - return; - } - - if (from.IsBodyMod) - { - from.SendLocalizedMessage(1073648); // You may only proceed while in your original state... - return; - } - - AddonFitResult result = CouldFit(loc, map, from, ref house); - - if (result == AddonFitResult.Valid) - { - CharacterStatue statue = new CharacterStatue(from, m_Type); - CharacterStatuePlinth plinth = new CharacterStatuePlinth(statue); - - house.Addons.Add(plinth); - - if (m_Maker is IRewardItem rewardItem) - statue.IsRewardItem = rewardItem.IsRewardItem; - - statue.Plinth = plinth; - plinth.MoveToWorld(loc, map); - statue.InvalidatePose(); - - /* - * TODO: Previously the maker wasn't deleted until after statue - * customization, leading to redeeding issues. Exact OSI behavior - * needs looking into. - */ - m_Maker.Delete(); - statue.Sculpt(from); - - from.CloseGump(); - from.SendGump(new CharacterStatueGump(m_Maker, statue, from)); - } - else if (result == AddonFitResult.Blocked) - { - from.SendLocalizedMessage(500269); // You cannot build that there. - } - else if (result == AddonFitResult.NotInHouse) - { - from.SendLocalizedMessage( - 1076192); // Statues can only be placed in houses where you are the owner or co-owner. - } - else if (result == AddonFitResult.DoorTooClose) - { - from.SendLocalizedMessage(500271); // You cannot build near the door. - } - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - - public static AddonFitResult CouldFit(Point3D p, Map map, Mobile from, ref BaseHouse house) - { - if (!map.CanFit(p.X, p.Y, p.Z, 20, true)) - return AddonFitResult.Blocked; - if (!BaseAddon.CheckHouse(from, p, map, 20, ref house)) - return AddonFitResult.NotInHouse; - - return CheckDoors(p, 20, house); - } - - public static AddonFitResult CheckDoors(Point3D p, int height, BaseHouse house) - { - List doors = house.Doors; - - for (int i = 0; i < doors.Count; i++) - { - BaseDoor door = doors[i]; - - Point3D doorLoc = door.GetWorldLocation(); - int doorHeight = door.ItemData.CalcHeight; - - if (Utility.InRange(doorLoc, p, 1) && - (p.Z == doorLoc.Z || (p.Z + height > doorLoc.Z && doorLoc.Z + doorHeight > p.Z))) - return AddonFitResult.DoorTooClose; - } - - return AddonFitResult.Valid; - } - } -} +using System; +using System.Collections.Generic; +using Server.Accounting; +using Server.ContextMenus; +using Server.Engines.VeteranRewards; +using Server.Gumps; +using Server.Items; +using Server.Multis; +using Server.Network; +using Server.Spells; +using Server.Targeting; + +namespace Server.Mobiles +{ + public enum StatueType + { + Marble, + Jade, + Bronze + } + + public enum StatuePose + { + Ready, + Casting, + Salute, + AllPraiseMe, + Fighting, + HandsOnHips + } + + public enum StatueMaterial + { + Antique, + Dark, + Medium, + Light + } + + public class CharacterStatue : Mobile, IRewardItem + { + private int m_Animation; + private int m_Frames; + private StatueMaterial m_Material; + private StatuePose m_Pose; + + private Mobile m_SculptedBy; + private StatueType m_Type; + + public CharacterStatue(Mobile from, StatueType type) + { + m_Type = type; + m_Pose = StatuePose.Ready; + m_Material = StatueMaterial.Antique; + + Direction = Direction.South; + AccessLevel = AccessLevel.Counselor; + Hits = HitsMax; + Blessed = true; + Frozen = true; + + CloneBody(from); + CloneClothes(from); + InvalidateHues(); + } + + public CharacterStatue(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public StatueType StatueType + { + get => m_Type; + set + { + m_Type = value; + InvalidateHues(); + InvalidatePose(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public StatuePose Pose + { + get => m_Pose; + set + { + m_Pose = value; + InvalidatePose(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public StatueMaterial Material + { + get => m_Material; + set + { + m_Material = value; + InvalidateHues(); + InvalidatePose(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile SculptedBy + { + get => m_SculptedBy; + set + { + m_SculptedBy = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime SculptedOn { get; set; } + + public CharacterStatuePlinth Plinth { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem { get; set; } + + public override void OnDoubleClick(Mobile from) + { + DisplayPaperdollTo(from); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_SculptedBy != null) + { + if (m_SculptedBy.ShowFameTitle && (m_SculptedBy.Player || m_SculptedBy.Body.IsHuman) && + m_SculptedBy.Fame >= 10000) + list.Add( + 1076202, + $"{(m_SculptedBy.Female ? "Lady" : "Lord")} {m_SculptedBy.Name}" + ); // Sculpted by ~1_Name~ + else + list.Add(1076202, m_SculptedBy.Name); // Sculpted by ~1_Name~ + } + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (from.Alive && m_SculptedBy != null) + { + var house = BaseHouse.FindHouseAt(this); + + if (house?.IsCoOwner(from) == true || from.AccessLevel > AccessLevel.Counselor) + list.Add(new DemolishEntry(this)); + } + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + if (Plinth?.Deleted == false) + Plinth.Delete(); + } + + protected override void OnMapChange(Map oldMap) + { + InvalidatePose(); + + if (Plinth != null) + Plinth.Map = Map; + } + + protected override void OnLocationChange(Point3D oldLocation) + { + InvalidatePose(); + + if (Plinth != null) + Plinth.Location = new Point3D(X, Y, Z - 5); + } + + public override bool CanBeRenamedBy(Mobile from) => false; + + public override bool CanBeDamaged() => false; + + public void OnRequestedAnimation(Mobile from) + { + from.Send(new UpdateStatueAnimation(this, 1, m_Animation, m_Frames)); + } + + public override void OnAosSingleClick(Mobile from) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write((int)m_Type); + writer.Write((int)m_Pose); + writer.Write((int)m_Material); + + writer.Write(m_SculptedBy); + writer.Write(SculptedOn); + + writer.Write(Plinth); + writer.Write(IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_Type = (StatueType)reader.ReadInt(); + m_Pose = (StatuePose)reader.ReadInt(); + m_Material = (StatueMaterial)reader.ReadInt(); + + m_SculptedBy = reader.ReadMobile(); + SculptedOn = reader.ReadDateTime(); + + Plinth = reader.ReadItem() as CharacterStatuePlinth; + IsRewardItem = reader.ReadBool(); + + InvalidatePose(); + + Frozen = true; + + if (m_SculptedBy == null || Map == Map.Internal) // Remove preview statues + Timer.DelayCall(Delete); + } + + public void Sculpt(Mobile by) + { + m_SculptedBy = by; + SculptedOn = DateTime.UtcNow; + + InvalidateProperties(); + } + + public bool Demolish(Mobile by) + { + var deed = new CharacterStatueDeed(null); + + if (by.PlaceInBackpack(deed)) + { + Delete(); + + deed.Statue = this; + deed.StatueType = m_Type; + deed.IsRewardItem = IsRewardItem; + + Plinth?.Delete(); + + return true; + } + + by.SendLocalizedMessage(500720); // You don't have enough room in your backpack! + deed.Delete(); + + return false; + } + + public void Restore(CharacterStatue from) + { + m_Material = from.Material; + m_Pose = from.Pose; + + Direction = from.Direction; + + CloneBody(from); + CloneClothes(from); + + InvalidateHues(); + InvalidatePose(); + } + + public void CloneBody(Mobile from) + { + Name = from.Name; + BodyValue = from.BodyValue; + Female = from.Female; + HairItemID = from.HairItemID; + FacialHairItemID = from.FacialHairItemID; + } + + public void CloneClothes(Mobile from) + { + for (var i = Items.Count - 1; i >= 0; i--) + Items[i].Delete(); + + for (var i = from.Items.Count - 1; i >= 0; i--) + { + var item = from.Items[i]; + + if (item.Layer != Layer.Backpack && item.Layer != Layer.Mount && item.Layer != Layer.Bank) + AddItem(CloneItem(item)); + } + } + + public Item CloneItem(Item item) + { + var cloned = new Item(item.ItemID) + { + Layer = item.Layer, + Name = item.Name, + Hue = item.Hue, + Weight = item.Weight, + Movable = false + }; + + return cloned; + } + + public void InvalidateHues() + { + Hue = 0xB8F + (int)m_Type * 4 + (int)m_Material; + + HairHue = Hue; + + if (FacialHairItemID > 0) + FacialHairHue = Hue; + + for (var i = Items.Count - 1; i >= 0; i--) + Items[i].Hue = Hue; + + Plinth?.InvalidateHue(); + } + + public void InvalidatePose() + { + switch (m_Pose) + { + case StatuePose.Ready: + m_Animation = 4; + m_Frames = 0; + break; + case StatuePose.Casting: + m_Animation = 16; + m_Frames = 2; + break; + case StatuePose.Salute: + m_Animation = 33; + m_Frames = 1; + break; + case StatuePose.AllPraiseMe: + m_Animation = 17; + m_Frames = 4; + break; + case StatuePose.Fighting: + m_Animation = 31; + m_Frames = 5; + break; + case StatuePose.HandsOnHips: + m_Animation = 6; + m_Frames = 1; + break; + } + + if (Map != null) + { + ProcessDelta(); + + Packet p = null; + + var eable = Map.GetClientsInRange(Location); + + foreach (var state in eable) + { + state.Mobile.ProcessDelta(); + + p ??= Packet.Acquire(new UpdateStatueAnimation(this, 1, m_Animation, m_Frames)); + + state.Send(p); + } + + Packet.Release(p); + + eable.Free(); + } + } + + private class DemolishEntry : ContextMenuEntry + { + private readonly CharacterStatue m_Statue; + + public DemolishEntry(CharacterStatue statue) : base(6275, 2) => m_Statue = statue; + + public override void OnClick() + { + if (m_Statue.Deleted) + return; + + m_Statue.Demolish(Owner.From); + } + } + } + + public class CharacterStatueDeed : Item, IRewardItem + { + private bool m_IsRewardItem; + + private StatueType m_Type; + + public CharacterStatueDeed(CharacterStatue statue) : base(0x14F0) + { + Statue = statue; + + if (statue != null) + { + m_Type = statue.StatueType; + m_IsRewardItem = statue.IsRewardItem; + } + + LootType = LootType.Blessed; + Weight = 1.0; + } + + public CharacterStatueDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber + { + get + { + var t = m_Type; + + if (Statue != null) t = Statue.StatueType; + + return t switch + { + StatueType.Marble => 1076189, + StatueType.Jade => 1076188, + StatueType.Bronze => 1076190, + _ => 1076173 + }; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public CharacterStatue Statue { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public StatueType StatueType + { + get + { + if (Statue != null) + return Statue.StatueType; + + return m_Type; + } + set => m_Type = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_IsRewardItem) + list.Add(1076222); // 6th Year Veteran Reward + + if (Statue != null) + list.Add(1076231, Statue.Name); // Statue of ~1_Name~ + } + + public override void OnDoubleClick(Mobile from) + { + if (from.Account is Account acct && from.AccessLevel == AccessLevel.Player) + { + var time = TimeSpan.FromDays(RewardSystem.RewardInterval.TotalDays * 6) - + (DateTime.UtcNow - acct.Created); + + if (time > TimeSpan.Zero) + { + from.SendLocalizedMessage( + 1008126, + true, + Math.Ceiling(time.TotalDays / RewardSystem.RewardInterval.TotalDays) + .ToString() + ); // Your account is not old enough to use this item. Months until you can use this item : + return; + } + } + + if (IsChildOf(from.Backpack)) + { + if (!from.IsBodyMod) + { + from.SendLocalizedMessage(1076194); // Select a place where you would like to put your statue. + from.Target = new CharacterStatueTarget(this, StatueType); + } + else + { + from.SendLocalizedMessage(1073648); // You may only proceed while in your original state... + } + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + + public override void OnDelete() + { + base.OnDelete(); + + Statue?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(1); // version + + writer.Write((int)m_Type); + + writer.Write(Statue); + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + if (version >= 1) m_Type = (StatueType)reader.ReadInt(); + + Statue = reader.ReadMobile() as CharacterStatue; + m_IsRewardItem = reader.ReadBool(); + } + } + + public class CharacterStatueTarget : Target + { + private readonly Item m_Maker; + private readonly StatueType m_Type; + + public CharacterStatueTarget(Item maker, StatueType type) : base(-1, true, TargetFlags.None) + { + m_Maker = maker; + m_Type = type; + } + + protected override void OnTarget(Mobile from, object targeted) + { + var p = targeted as IPoint3D; + var map = from.Map; + + if (p == null || map == null || m_Maker?.Deleted != false) + return; + + if (m_Maker.IsChildOf(from.Backpack)) + { + SpellHelper.GetSurfaceTop(ref p); + BaseHouse house = null; + var loc = new Point3D(p); + + if (targeted is Item item && !item.IsLockedDown && !item.IsSecure && !(item is AddonComponent)) + { + from.SendLocalizedMessage(1076191); // Statues can only be placed in houses. + return; + } + + if (from.IsBodyMod) + { + from.SendLocalizedMessage(1073648); // You may only proceed while in your original state... + return; + } + + var result = CouldFit(loc, map, from, ref house); + + if (result == AddonFitResult.Valid) + { + var statue = new CharacterStatue(from, m_Type); + var plinth = new CharacterStatuePlinth(statue); + + house.Addons.Add(plinth); + + if (m_Maker is IRewardItem rewardItem) + statue.IsRewardItem = rewardItem.IsRewardItem; + + statue.Plinth = plinth; + plinth.MoveToWorld(loc, map); + statue.InvalidatePose(); + + /* + * TODO: Previously the maker wasn't deleted until after statue + * customization, leading to redeeding issues. Exact OSI behavior + * needs looking into. + */ + m_Maker.Delete(); + statue.Sculpt(from); + + from.CloseGump(); + from.SendGump(new CharacterStatueGump(m_Maker, statue, from)); + } + else if (result == AddonFitResult.Blocked) + { + from.SendLocalizedMessage(500269); // You cannot build that there. + } + else if (result == AddonFitResult.NotInHouse) + { + from.SendLocalizedMessage( + 1076192 + ); // Statues can only be placed in houses where you are the owner or co-owner. + } + else if (result == AddonFitResult.DoorTooClose) + { + from.SendLocalizedMessage(500271); // You cannot build near the door. + } + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + + public static AddonFitResult CouldFit(Point3D p, Map map, Mobile from, ref BaseHouse house) + { + if (!map.CanFit(p.X, p.Y, p.Z, 20, true)) + return AddonFitResult.Blocked; + if (!BaseAddon.CheckHouse(from, p, map, 20, ref house)) + return AddonFitResult.NotInHouse; + + return CheckDoors(p, 20, house); + } + + public static AddonFitResult CheckDoors(Point3D p, int height, BaseHouse house) + { + var doors = house.Doors; + + for (var i = 0; i < doors.Count; i++) + { + var door = doors[i]; + + var doorLoc = door.GetWorldLocation(); + var doorHeight = door.ItemData.CalcHeight; + + if (Utility.InRange(doorLoc, p, 1) && + (p.Z == doorLoc.Z || p.Z + height > doorLoc.Z && doorLoc.Z + doorHeight > p.Z)) + return AddonFitResult.DoorTooClose; + } + + return AddonFitResult.Valid; + } + } +} diff --git a/Projects/UOContent/Engines/VeteranRewards/Character Statue Maker/CharacterStatueMaker.cs b/Projects/UOContent/Engines/VeteranRewards/Character Statue Maker/CharacterStatueMaker.cs index 30833bc91..db85c035b 100644 --- a/Projects/UOContent/Engines/VeteranRewards/Character Statue Maker/CharacterStatueMaker.cs +++ b/Projects/UOContent/Engines/VeteranRewards/Character Statue Maker/CharacterStatueMaker.cs @@ -1,183 +1,183 @@ -using Server.Engines.VeteranRewards; -using Server.Mobiles; - -namespace Server.Items -{ - public class CharacterStatueMaker : Item, IRewardItem - { - private bool m_IsRewardItem; - private StatueType m_Type; - - public CharacterStatueMaker(StatueType type) : base(0x32F0) - { - m_Type = type; - - InvalidateHue(); - - LootType = LootType.Blessed; - Weight = 5.0; - } - - public CharacterStatueMaker(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1076173; // Character Statue Maker - - [CommandProperty(AccessLevel.GameMaster)] - public StatueType StatueType - { - get => m_Type; - set - { - m_Type = value; - InvalidateHue(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void OnDoubleClick(Mobile from) - { - if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this, new object[] { m_Type })) - return; - - if (IsChildOf(from.Backpack)) - { - if (!from.IsBodyMod) - { - from.SendLocalizedMessage(1076194); // Select a place where you would like to put your statue. - from.Target = new CharacterStatueTarget(this, m_Type); - } - else - { - from.SendLocalizedMessage(1073648); // You may only proceed while in your original state... - } - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_IsRewardItem) - list.Add(1076222); // 6th Year Veteran Reward - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - writer.Write((int)m_Type); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - m_Type = (StatueType)reader.ReadInt(); - } - - public void InvalidateHue() - { - Hue = 0xB8F + (int)m_Type * 4; - } - } - - public class MarbleStatueMaker : CharacterStatueMaker - { - [Constructible] - public MarbleStatueMaker() : base(StatueType.Marble) - { - } - - public MarbleStatueMaker(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class JadeStatueMaker : CharacterStatueMaker - { - [Constructible] - public JadeStatueMaker() : base(StatueType.Jade) - { - } - - public JadeStatueMaker(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BronzeStatueMaker : CharacterStatueMaker - { - [Constructible] - public BronzeStatueMaker() : base(StatueType.Bronze) - { - } - - public BronzeStatueMaker(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +using Server.Engines.VeteranRewards; +using Server.Mobiles; + +namespace Server.Items +{ + public class CharacterStatueMaker : Item, IRewardItem + { + private bool m_IsRewardItem; + private StatueType m_Type; + + public CharacterStatueMaker(StatueType type) : base(0x32F0) + { + m_Type = type; + + InvalidateHue(); + + LootType = LootType.Blessed; + Weight = 5.0; + } + + public CharacterStatueMaker(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1076173; // Character Statue Maker + + [CommandProperty(AccessLevel.GameMaster)] + public StatueType StatueType + { + get => m_Type; + set + { + m_Type = value; + InvalidateHue(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void OnDoubleClick(Mobile from) + { + if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this, new object[] { m_Type })) + return; + + if (IsChildOf(from.Backpack)) + { + if (!from.IsBodyMod) + { + from.SendLocalizedMessage(1076194); // Select a place where you would like to put your statue. + from.Target = new CharacterStatueTarget(this, m_Type); + } + else + { + from.SendLocalizedMessage(1073648); // You may only proceed while in your original state... + } + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_IsRewardItem) + list.Add(1076222); // 6th Year Veteran Reward + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + writer.Write((int)m_Type); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + m_Type = (StatueType)reader.ReadInt(); + } + + public void InvalidateHue() + { + Hue = 0xB8F + (int)m_Type * 4; + } + } + + public class MarbleStatueMaker : CharacterStatueMaker + { + [Constructible] + public MarbleStatueMaker() : base(StatueType.Marble) + { + } + + public MarbleStatueMaker(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class JadeStatueMaker : CharacterStatueMaker + { + [Constructible] + public JadeStatueMaker() : base(StatueType.Jade) + { + } + + public JadeStatueMaker(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class BronzeStatueMaker : CharacterStatueMaker + { + [Constructible] + public BronzeStatueMaker() : base(StatueType.Bronze) + { + } + + public BronzeStatueMaker(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Engines/VeteranRewards/Character Statue Maker/CharacterStatuePlinth.cs b/Projects/UOContent/Engines/VeteranRewards/Character Statue Maker/CharacterStatuePlinth.cs index 408eb24af..14fe325ce 100644 --- a/Projects/UOContent/Engines/VeteranRewards/Character Statue Maker/CharacterStatuePlinth.cs +++ b/Projects/UOContent/Engines/VeteranRewards/Character Statue Maker/CharacterStatuePlinth.cs @@ -1,126 +1,126 @@ -using Server.Gumps; -using Server.Mobiles; -using Server.Multis; - -namespace Server.Items -{ - public class CharacterStatuePlinth : Static, IAddon - { - private CharacterStatue m_Statue; - - public CharacterStatuePlinth(CharacterStatue statue) : base(0x32F2) - { - m_Statue = statue; - - InvalidateHue(); - } - - public CharacterStatuePlinth(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1076201; // Character Statue - public Item Deed => new CharacterStatueDeed(m_Statue); - - public virtual bool CouldFit(IPoint3D p, Map map) - { - Point3D point = new Point3D(p.X, p.Y, p.Z); - - if (map?.CanFit(point, 20) != true) - return false; - - BaseHouse house = BaseHouse.FindHouseAt(point, map, 20); - - if (house == null) - return false; - - AddonFitResult result = CharacterStatueTarget.CheckDoors(point, 20, house); - - if (result == AddonFitResult.Valid) - return true; - - return false; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - if (m_Statue?.Deleted == false) - m_Statue.Delete(); - } - - public override void OnMapChange() - { - if (m_Statue != null) - m_Statue.Map = Map; - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Statue != null) - m_Statue.Location = new Point3D(X, Y, Z + 5); - } - - public override void OnDoubleClick(Mobile from) - { - if (m_Statue != null) - from.SendGump(new CharacterPlinthGump(m_Statue)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_Statue); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_Statue = reader.ReadMobile() as CharacterStatue; - - if (m_Statue?.SculptedBy == null || Map == Map.Internal) - Timer.DelayCall(Delete); - } - - public void InvalidateHue() - { - if (m_Statue != null) - Hue = 0xB8F + (int)m_Statue.StatueType * 4 + (int)m_Statue.Material; - } - - private class CharacterPlinthGump : Gump - { - public CharacterPlinthGump(CharacterStatue statue) : base(60, 30) - { - Closable = true; - Disposable = true; - Draggable = true; - Resizable = false; - - AddPage(0); - AddImage(0, 0, 0x24F4); - AddHtml(55, 50, 150, 20, statue.Name); - AddHtml(55, 75, 150, 20, statue.SculptedOn.ToString()); - AddHtmlLocalized(55, 100, 150, 20, GetTypeNumber(statue.StatueType), 0); - } - - public int GetTypeNumber(StatueType type) - { - return type switch - { - StatueType.Marble => 1076181, - StatueType.Jade => 1076180, - StatueType.Bronze => 1076230, - _ => 1076181 - }; - } - } - } -} +using Server.Gumps; +using Server.Mobiles; +using Server.Multis; + +namespace Server.Items +{ + public class CharacterStatuePlinth : Static, IAddon + { + private CharacterStatue m_Statue; + + public CharacterStatuePlinth(CharacterStatue statue) : base(0x32F2) + { + m_Statue = statue; + + InvalidateHue(); + } + + public CharacterStatuePlinth(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1076201; // Character Statue + public Item Deed => new CharacterStatueDeed(m_Statue); + + public virtual bool CouldFit(IPoint3D p, Map map) + { + var point = new Point3D(p.X, p.Y, p.Z); + + if (map?.CanFit(point, 20) != true) + return false; + + var house = BaseHouse.FindHouseAt(point, map, 20); + + if (house == null) + return false; + + var result = CharacterStatueTarget.CheckDoors(point, 20, house); + + if (result == AddonFitResult.Valid) + return true; + + return false; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + if (m_Statue?.Deleted == false) + m_Statue.Delete(); + } + + public override void OnMapChange() + { + if (m_Statue != null) + m_Statue.Map = Map; + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Statue != null) + m_Statue.Location = new Point3D(X, Y, Z + 5); + } + + public override void OnDoubleClick(Mobile from) + { + if (m_Statue != null) + from.SendGump(new CharacterPlinthGump(m_Statue)); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_Statue); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_Statue = reader.ReadMobile() as CharacterStatue; + + if (m_Statue?.SculptedBy == null || Map == Map.Internal) + Timer.DelayCall(Delete); + } + + public void InvalidateHue() + { + if (m_Statue != null) + Hue = 0xB8F + (int)m_Statue.StatueType * 4 + (int)m_Statue.Material; + } + + private class CharacterPlinthGump : Gump + { + public CharacterPlinthGump(CharacterStatue statue) : base(60, 30) + { + Closable = true; + Disposable = true; + Draggable = true; + Resizable = false; + + AddPage(0); + AddImage(0, 0, 0x24F4); + AddHtml(55, 50, 150, 20, statue.Name); + AddHtml(55, 75, 150, 20, statue.SculptedOn.ToString()); + AddHtmlLocalized(55, 100, 150, 20, GetTypeNumber(statue.StatueType), 0); + } + + public int GetTypeNumber(StatueType type) + { + return type switch + { + StatueType.Marble => 1076181, + StatueType.Jade => 1076180, + StatueType.Bronze => 1076230, + _ => 1076181 + }; + } + } + } +} diff --git a/Projects/UOContent/Engines/VeteranRewards/Character Statue Maker/Gumps/CharacterStatueGump.cs b/Projects/UOContent/Engines/VeteranRewards/Character Statue Maker/Gumps/CharacterStatueGump.cs index ae6011e85..a61922071 100644 --- a/Projects/UOContent/Engines/VeteranRewards/Character Statue Maker/Gumps/CharacterStatueGump.cs +++ b/Projects/UOContent/Engines/VeteranRewards/Character Statue Maker/Gumps/CharacterStatueGump.cs @@ -1,197 +1,197 @@ -using Server.Mobiles; -using Server.Network; - -namespace Server.Gumps -{ - public class CharacterStatueGump : Gump - { - private readonly Item m_Maker; - private readonly Mobile m_Owner; - private readonly CharacterStatue m_Statue; - - public CharacterStatueGump(Item maker, CharacterStatue statue, Mobile owner) : base(60, 36) - { - m_Maker = maker; - m_Statue = statue; - m_Owner = owner; - - if (m_Statue == null) - return; - - Closable = true; - Disposable = true; - Draggable = true; - Resizable = false; - - AddPage(0); - - AddBackground(0, 0, 327, 324, 0x13BE); - AddImageTiled(10, 10, 307, 20, 0xA40); - AddImageTiled(10, 40, 307, 244, 0xA40); - AddImageTiled(10, 294, 307, 20, 0xA40); - AddAlphaRegion(10, 10, 307, 304); - AddHtmlLocalized(14, 12, 327, 20, 1076156, 0x7FFF); // Character Statue Maker - - // pose - AddHtmlLocalized(133, 41, 120, 20, 1076168, 0x7FFF); // Choose Pose - AddHtmlLocalized(133, 61, 120, 20, 1076208 + (int)m_Statue.Pose, 0x77E); - AddButton(163, 81, 0xFA5, 0xFA7, (int)Buttons.PoseNext); - AddButton(133, 81, 0xFAE, 0xFB0, (int)Buttons.PosePrev); - - // direction - AddHtmlLocalized(133, 126, 120, 20, 1076170, 0x7FFF); // Choose Direction - AddHtmlLocalized(133, 146, 120, 20, GetDirectionNumber(m_Statue.Direction), 0x77E); - AddButton(163, 167, 0xFA5, 0xFA7, (int)Buttons.DirNext); - AddButton(133, 167, 0xFAE, 0xFB0, (int)Buttons.DirPrev); - - // material - AddHtmlLocalized(133, 211, 120, 20, 1076171, 0x7FFF); // Choose Material - AddHtmlLocalized(133, 231, 120, 20, GetMaterialNumber(m_Statue.StatueType, m_Statue.Material), 0x77E); - AddButton(163, 253, 0xFA5, 0xFA7, (int)Buttons.MatNext); - AddButton(133, 253, 0xFAE, 0xFB0, (int)Buttons.MatPrev); - - // cancel - AddButton(10, 294, 0xFB1, 0xFB2, (int)Buttons.Close); - AddHtmlLocalized(45, 294, 80, 20, 1006045, 0x7FFF); // Cancel - - // sculpt - AddButton(234, 294, 0xFB7, 0xFB9, (int)Buttons.Sculpt); - AddHtmlLocalized(269, 294, 80, 20, 1076174, 0x7FFF); // Sculpt - - // restore - if (m_Maker is CharacterStatueDeed) - { - AddButton(107, 294, 0xFAB, 0xFAD, (int)Buttons.Restore); - AddHtmlLocalized(142, 294, 80, 20, 1076193, 0x7FFF); // Restore - } - } - - private int GetMaterialNumber(StatueType type, StatueMaterial material) - { - switch (material) - { - case StatueMaterial.Antique: - - return type switch - { - StatueType.Bronze => 1076187, - StatueType.Jade => 1076186, - StatueType.Marble => 1076182, - _ => 1076187 - }; - - case StatueMaterial.Dark: - - if (type == StatueType.Marble) - return 1076183; - - return 1076182; - case StatueMaterial.Medium: return 1076184; - case StatueMaterial.Light: return 1076185; - default: return 1076187; - } - } - - private int GetDirectionNumber(Direction direction) - { - return direction switch - { - Direction.North => 1075389, - Direction.Right => 1075388, - Direction.East => 1075387, - Direction.Down => 1076204, - Direction.South => 1075386, - Direction.Left => 1075391, - Direction.West => 1075390, - Direction.Up => 1076205, - _ => 1075386 - }; - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (m_Statue?.Deleted != false) - return; - - bool sendGump = false; - - if (info.ButtonID == (int)Buttons.Sculpt) - { - if (m_Maker is CharacterStatueDeed deed) - { - CharacterStatue backup = deed.Statue; - - backup?.Delete(); - } - - m_Maker?.Delete(); - - m_Statue.Sculpt(state.Mobile); - } - else if (info.ButtonID == (int)Buttons.PosePrev) - { - m_Statue.Pose = (StatuePose)(((int)m_Statue.Pose + 5) % 6); - sendGump = true; - } - else if (info.ButtonID == (int)Buttons.PoseNext) - { - m_Statue.Pose = (StatuePose)(((int)m_Statue.Pose + 1) % 6); - sendGump = true; - } - else if (info.ButtonID == (int)Buttons.DirPrev) - { - m_Statue.Direction = (Direction)(((int)m_Statue.Direction + 7) % 8); - m_Statue.InvalidatePose(); - sendGump = true; - } - else if (info.ButtonID == (int)Buttons.DirNext) - { - m_Statue.Direction = (Direction)(((int)m_Statue.Direction + 1) % 8); - m_Statue.InvalidatePose(); - sendGump = true; - } - else if (info.ButtonID == (int)Buttons.MatPrev) - { - m_Statue.Material = (StatueMaterial)(((int)m_Statue.Material + 3) % 4); - sendGump = true; - } - else if (info.ButtonID == (int)Buttons.MatNext) - { - m_Statue.Material = (StatueMaterial)(((int)m_Statue.Material + 1) % 4); - sendGump = true; - } - else if (info.ButtonID == (int)Buttons.Restore) - { - if (m_Maker is CharacterStatueDeed deed) - { - CharacterStatue backup = deed.Statue; - - if (backup != null) - m_Statue.Restore(backup); - } - - sendGump = true; - } - else // Close - { - sendGump = !m_Statue.Demolish(state.Mobile); - } - - if (sendGump) - state.Mobile.SendGump(new CharacterStatueGump(m_Maker, m_Statue, m_Owner)); - } - - private enum Buttons - { - Close, - Sculpt, - PosePrev, - PoseNext, - DirPrev, - DirNext, - MatPrev, - MatNext, - Restore - } - } -} +using Server.Mobiles; +using Server.Network; + +namespace Server.Gumps +{ + public class CharacterStatueGump : Gump + { + private readonly Item m_Maker; + private readonly Mobile m_Owner; + private readonly CharacterStatue m_Statue; + + public CharacterStatueGump(Item maker, CharacterStatue statue, Mobile owner) : base(60, 36) + { + m_Maker = maker; + m_Statue = statue; + m_Owner = owner; + + if (m_Statue == null) + return; + + Closable = true; + Disposable = true; + Draggable = true; + Resizable = false; + + AddPage(0); + + AddBackground(0, 0, 327, 324, 0x13BE); + AddImageTiled(10, 10, 307, 20, 0xA40); + AddImageTiled(10, 40, 307, 244, 0xA40); + AddImageTiled(10, 294, 307, 20, 0xA40); + AddAlphaRegion(10, 10, 307, 304); + AddHtmlLocalized(14, 12, 327, 20, 1076156, 0x7FFF); // Character Statue Maker + + // pose + AddHtmlLocalized(133, 41, 120, 20, 1076168, 0x7FFF); // Choose Pose + AddHtmlLocalized(133, 61, 120, 20, 1076208 + (int)m_Statue.Pose, 0x77E); + AddButton(163, 81, 0xFA5, 0xFA7, (int)Buttons.PoseNext); + AddButton(133, 81, 0xFAE, 0xFB0, (int)Buttons.PosePrev); + + // direction + AddHtmlLocalized(133, 126, 120, 20, 1076170, 0x7FFF); // Choose Direction + AddHtmlLocalized(133, 146, 120, 20, GetDirectionNumber(m_Statue.Direction), 0x77E); + AddButton(163, 167, 0xFA5, 0xFA7, (int)Buttons.DirNext); + AddButton(133, 167, 0xFAE, 0xFB0, (int)Buttons.DirPrev); + + // material + AddHtmlLocalized(133, 211, 120, 20, 1076171, 0x7FFF); // Choose Material + AddHtmlLocalized(133, 231, 120, 20, GetMaterialNumber(m_Statue.StatueType, m_Statue.Material), 0x77E); + AddButton(163, 253, 0xFA5, 0xFA7, (int)Buttons.MatNext); + AddButton(133, 253, 0xFAE, 0xFB0, (int)Buttons.MatPrev); + + // cancel + AddButton(10, 294, 0xFB1, 0xFB2, (int)Buttons.Close); + AddHtmlLocalized(45, 294, 80, 20, 1006045, 0x7FFF); // Cancel + + // sculpt + AddButton(234, 294, 0xFB7, 0xFB9, (int)Buttons.Sculpt); + AddHtmlLocalized(269, 294, 80, 20, 1076174, 0x7FFF); // Sculpt + + // restore + if (m_Maker is CharacterStatueDeed) + { + AddButton(107, 294, 0xFAB, 0xFAD, (int)Buttons.Restore); + AddHtmlLocalized(142, 294, 80, 20, 1076193, 0x7FFF); // Restore + } + } + + private int GetMaterialNumber(StatueType type, StatueMaterial material) + { + switch (material) + { + case StatueMaterial.Antique: + + return type switch + { + StatueType.Bronze => 1076187, + StatueType.Jade => 1076186, + StatueType.Marble => 1076182, + _ => 1076187 + }; + + case StatueMaterial.Dark: + + if (type == StatueType.Marble) + return 1076183; + + return 1076182; + case StatueMaterial.Medium: return 1076184; + case StatueMaterial.Light: return 1076185; + default: return 1076187; + } + } + + private int GetDirectionNumber(Direction direction) + { + return direction switch + { + Direction.North => 1075389, + Direction.Right => 1075388, + Direction.East => 1075387, + Direction.Down => 1076204, + Direction.South => 1075386, + Direction.Left => 1075391, + Direction.West => 1075390, + Direction.Up => 1076205, + _ => 1075386 + }; + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (m_Statue?.Deleted != false) + return; + + var sendGump = false; + + if (info.ButtonID == (int)Buttons.Sculpt) + { + if (m_Maker is CharacterStatueDeed deed) + { + var backup = deed.Statue; + + backup?.Delete(); + } + + m_Maker?.Delete(); + + m_Statue.Sculpt(state.Mobile); + } + else if (info.ButtonID == (int)Buttons.PosePrev) + { + m_Statue.Pose = (StatuePose)(((int)m_Statue.Pose + 5) % 6); + sendGump = true; + } + else if (info.ButtonID == (int)Buttons.PoseNext) + { + m_Statue.Pose = (StatuePose)(((int)m_Statue.Pose + 1) % 6); + sendGump = true; + } + else if (info.ButtonID == (int)Buttons.DirPrev) + { + m_Statue.Direction = (Direction)(((int)m_Statue.Direction + 7) % 8); + m_Statue.InvalidatePose(); + sendGump = true; + } + else if (info.ButtonID == (int)Buttons.DirNext) + { + m_Statue.Direction = (Direction)(((int)m_Statue.Direction + 1) % 8); + m_Statue.InvalidatePose(); + sendGump = true; + } + else if (info.ButtonID == (int)Buttons.MatPrev) + { + m_Statue.Material = (StatueMaterial)(((int)m_Statue.Material + 3) % 4); + sendGump = true; + } + else if (info.ButtonID == (int)Buttons.MatNext) + { + m_Statue.Material = (StatueMaterial)(((int)m_Statue.Material + 1) % 4); + sendGump = true; + } + else if (info.ButtonID == (int)Buttons.Restore) + { + if (m_Maker is CharacterStatueDeed deed) + { + var backup = deed.Statue; + + if (backup != null) + m_Statue.Restore(backup); + } + + sendGump = true; + } + else // Close + { + sendGump = !m_Statue.Demolish(state.Mobile); + } + + if (sendGump) + state.Mobile.SendGump(new CharacterStatueGump(m_Maker, m_Statue, m_Owner)); + } + + private enum Buttons + { + Close, + Sculpt, + PosePrev, + PoseNext, + DirPrev, + DirNext, + MatPrev, + MatNext, + Restore + } + } +} diff --git a/Projects/UOContent/Engines/VeteranRewards/Character Statue Maker/Packets.cs b/Projects/UOContent/Engines/VeteranRewards/Character Statue Maker/Packets.cs index a21a75c77..f31702064 100644 --- a/Projects/UOContent/Engines/VeteranRewards/Character Statue Maker/Packets.cs +++ b/Projects/UOContent/Engines/VeteranRewards/Character Statue Maker/Packets.cs @@ -1,20 +1,20 @@ -namespace Server.Network -{ - public class UpdateStatueAnimation : Packet - { - public UpdateStatueAnimation(Mobile m, int status, int animation, int frame) : base(0xBF, 17) - { - Stream.Write((short)0x11); - Stream.Write((short)0x19); - Stream.Write((byte)0x5); - Stream.Write(m.Serial); - Stream.Write((byte)0); - Stream.Write((byte)0xFF); - Stream.Write((byte)status); - Stream.Write((byte)0); - Stream.Write((byte)animation); - Stream.Write((byte)0); - Stream.Write((byte)frame); - } - } -} \ No newline at end of file +namespace Server.Network +{ + public class UpdateStatueAnimation : Packet + { + public UpdateStatueAnimation(Mobile m, int status, int animation, int frame) : base(0xBF, 17) + { + Stream.Write((short)0x11); + Stream.Write((short)0x19); + Stream.Write((byte)0x5); + Stream.Write(m.Serial); + Stream.Write((byte)0); + Stream.Write((byte)0xFF); + Stream.Write((byte)status); + Stream.Write((byte)0); + Stream.Write((byte)animation); + Stream.Write((byte)0); + Stream.Write((byte)frame); + } + } +} diff --git a/Projects/UOContent/Engines/VeteranRewards/RewardCategory.cs b/Projects/UOContent/Engines/VeteranRewards/RewardCategory.cs index d9bc078c1..ad990bf2b 100644 --- a/Projects/UOContent/Engines/VeteranRewards/RewardCategory.cs +++ b/Projects/UOContent/Engines/VeteranRewards/RewardCategory.cs @@ -1,25 +1,25 @@ -using System.Collections.Generic; - -namespace Server.Engines.VeteranRewards -{ - public class RewardCategory - { - public RewardCategory(int name) - { - Name = name; - Entries = new List(); - } - - public RewardCategory(string name) - { - NameString = name; - Entries = new List(); - } - - public int Name { get; } - - public string NameString { get; } - - public List Entries { get; } - } -} \ No newline at end of file +using System.Collections.Generic; + +namespace Server.Engines.VeteranRewards +{ + public class RewardCategory + { + public RewardCategory(int name) + { + Name = name; + Entries = new List(); + } + + public RewardCategory(string name) + { + NameString = name; + Entries = new List(); + } + + public int Name { get; } + + public string NameString { get; } + + public List Entries { get; } + } +} diff --git a/Projects/UOContent/Engines/VeteranRewards/RewardChoiceGump.cs b/Projects/UOContent/Engines/VeteranRewards/RewardChoiceGump.cs index 63761e4c7..12c3467ff 100644 --- a/Projects/UOContent/Engines/VeteranRewards/RewardChoiceGump.cs +++ b/Projects/UOContent/Engines/VeteranRewards/RewardChoiceGump.cs @@ -1,183 +1,189 @@ -using System; -using System.Collections.Generic; -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.VeteranRewards -{ - public class RewardChoiceGump : Gump - { - private readonly Mobile m_From; - - public RewardChoiceGump(Mobile from) : base(0, 0) - { - m_From = from; - - from.CloseGump(); - - RenderBackground(); - RenderCategories(); - } - - private void RenderBackground() - { - AddPage(0); - - AddBackground(10, 10, 600, 450, 2600); - - AddButton(530, 415, 4017, 4019, 0); - - AddButton(60, 415, 4014, 4016, 0, GumpButtonType.Page, 1); - AddHtmlLocalized(95, 415, 200, 20, 1049755); // Main Menu - } - - private void RenderCategories() - { - TimeSpan rewardInterval = RewardSystem.RewardInterval; - - string intervalAsString; - - if (rewardInterval == TimeSpan.FromDays(30.0)) - intervalAsString = "month"; - else if (rewardInterval == TimeSpan.FromDays(60.0)) - intervalAsString = "two months"; - else if (rewardInterval == TimeSpan.FromDays(90.0)) - intervalAsString = "three months"; - else if (rewardInterval == TimeSpan.FromDays(365.0)) - intervalAsString = "year"; - else - intervalAsString = $"{rewardInterval.TotalDays} day{(rewardInterval.TotalDays == 1 ? "" : "s")}"; - - AddPage(1); - - AddHtml(60, 35, 500, 70, - $"Ultima Online Rewards Program
Thank you for being a part of the Ultima Online community for a full {intervalAsString}. As a token of our appreciation, you may select from the following in-game reward items listed below. The gift items will be attributed to the character you have logged-in with on the shard you are on when you chose the item(s). The number of rewards you are entitled to are listed below and are for your entire account. To read more about these rewards before making a selection, feel free to visit the uo.com site at http://www.uo.com/rewards.", true, true); - - RewardSystem.ComputeRewardInfo(m_From, out int cur, out int max); - - AddHtmlLocalized(60, 105, 300, 35, 1006006); // Your current total of rewards to choose: - AddLabel(370, 107, 50, (max - cur).ToString()); - - AddHtmlLocalized(60, 140, 300, 35, 1006007); // You have already chosen: - AddLabel(370, 142, 50, cur.ToString()); - - RewardCategory[] categories = RewardSystem.Categories; - - int page = 2; - - for (int i = 0; i < categories.Length; ++i) - { - if (!RewardSystem.HasAccess(m_From, categories[i])) - { - page += 1; - continue; - } - - AddButton(100, 180 + i * 40, 4005, 4005, 0, GumpButtonType.Page, page); - - page += PagesPerCategory(categories[i]); - - if (categories[i].NameString != null) - AddHtml(135, 180 + i * 40, 300, 20, categories[i].NameString); - else - AddHtmlLocalized(135, 180 + i * 40, 300, 20, categories[i].Name); - } - - page = 2; - - for (int i = 0; i < categories.Length; ++i) - RenderCategory(categories[i], i, ref page); - } - - private int PagesPerCategory(RewardCategory category) - { - List entries = category.Entries; - int i = 0; - - for (int j = 0; j < entries.Count; j++) - if (RewardSystem.HasAccess(m_From, entries[j])) - i++; - - return (int)Math.Ceiling(i / 24.0); - } - - private int GetButtonID(int type, int index) => 2 + index * 20 + type; - - private void RenderCategory(RewardCategory category, int index, ref int page) - { - AddPage(page); - - List entries = category.Entries; - - int i = 0; - - for (int j = 0; j < entries.Count; ++j) - { - RewardEntry entry = entries[j]; - - if (!RewardSystem.HasAccess(m_From, entry)) - continue; - - if (i == 24) - { - AddButton(305, 415, 0xFA5, 0xFA7, 0, GumpButtonType.Page, ++page); - AddHtmlLocalized(340, 415, 200, 20, 1011066); // Next page - - AddPage(page); - - AddButton(270, 415, 0xFAE, 0xFB0, 0, GumpButtonType.Page, page - 1); - AddHtmlLocalized(185, 415, 200, 20, 1011067); // Previous page - - i = 0; - } - - AddButton(55 + i / 12 * 250, 80 + i % 12 * 25, 5540, 5541, GetButtonID(index, j)); - - if (entry.NameString != null) - AddHtml(80 + i / 12 * 250, 80 + i % 12 * 25, 250, 20, entry.NameString); - else - AddHtmlLocalized(80 + i / 12 * 250, 80 + i % 12 * 25, 250, 20, entry.Name); - ++i; - } - - page += 1; - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - int buttonID = info.ButtonID - 1; - - if (buttonID == 0) - { - RewardSystem.ComputeRewardInfo(m_From, out int cur, out int max); - - if (cur < max) - m_From.SendGump(new RewardNoticeGump(m_From)); - } - else - { - --buttonID; - - int type = buttonID % 20; - int index = buttonID / 20; - - RewardCategory[] categories = RewardSystem.Categories; - - if (type >= 0 && type < categories.Length) - { - RewardCategory category = categories[type]; - - if (index >= 0 && index < category.Entries.Count) - { - RewardEntry entry = category.Entries[index]; - - if (!RewardSystem.HasAccess(m_From, entry)) - return; - - m_From.SendGump(new RewardConfirmGump(m_From, entry)); - } - } - } - } - } -} +using System; +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.VeteranRewards +{ + public class RewardChoiceGump : Gump + { + private readonly Mobile m_From; + + public RewardChoiceGump(Mobile from) : base(0, 0) + { + m_From = from; + + from.CloseGump(); + + RenderBackground(); + RenderCategories(); + } + + private void RenderBackground() + { + AddPage(0); + + AddBackground(10, 10, 600, 450, 2600); + + AddButton(530, 415, 4017, 4019, 0); + + AddButton(60, 415, 4014, 4016, 0, GumpButtonType.Page, 1); + AddHtmlLocalized(95, 415, 200, 20, 1049755); // Main Menu + } + + private void RenderCategories() + { + var rewardInterval = RewardSystem.RewardInterval; + + string intervalAsString; + + if (rewardInterval == TimeSpan.FromDays(30.0)) + intervalAsString = "month"; + else if (rewardInterval == TimeSpan.FromDays(60.0)) + intervalAsString = "two months"; + else if (rewardInterval == TimeSpan.FromDays(90.0)) + intervalAsString = "three months"; + else if (rewardInterval == TimeSpan.FromDays(365.0)) + intervalAsString = "year"; + else + intervalAsString = $"{rewardInterval.TotalDays} day{(rewardInterval.TotalDays == 1 ? "" : "s")}"; + + AddPage(1); + + AddHtml( + 60, + 35, + 500, + 70, + $"Ultima Online Rewards Program
Thank you for being a part of the Ultima Online community for a full {intervalAsString}. As a token of our appreciation, you may select from the following in-game reward items listed below. The gift items will be attributed to the character you have logged-in with on the shard you are on when you chose the item(s). The number of rewards you are entitled to are listed below and are for your entire account. To read more about these rewards before making a selection, feel free to visit the uo.com site at http://www.uo.com/rewards.", + true, + true + ); + + RewardSystem.ComputeRewardInfo(m_From, out var cur, out var max); + + AddHtmlLocalized(60, 105, 300, 35, 1006006); // Your current total of rewards to choose: + AddLabel(370, 107, 50, (max - cur).ToString()); + + AddHtmlLocalized(60, 140, 300, 35, 1006007); // You have already chosen: + AddLabel(370, 142, 50, cur.ToString()); + + var categories = RewardSystem.Categories; + + var page = 2; + + for (var i = 0; i < categories.Length; ++i) + { + if (!RewardSystem.HasAccess(m_From, categories[i])) + { + page += 1; + continue; + } + + AddButton(100, 180 + i * 40, 4005, 4005, 0, GumpButtonType.Page, page); + + page += PagesPerCategory(categories[i]); + + if (categories[i].NameString != null) + AddHtml(135, 180 + i * 40, 300, 20, categories[i].NameString); + else + AddHtmlLocalized(135, 180 + i * 40, 300, 20, categories[i].Name); + } + + page = 2; + + for (var i = 0; i < categories.Length; ++i) + RenderCategory(categories[i], i, ref page); + } + + private int PagesPerCategory(RewardCategory category) + { + var entries = category.Entries; + var i = 0; + + for (var j = 0; j < entries.Count; j++) + if (RewardSystem.HasAccess(m_From, entries[j])) + i++; + + return (int)Math.Ceiling(i / 24.0); + } + + private int GetButtonID(int type, int index) => 2 + index * 20 + type; + + private void RenderCategory(RewardCategory category, int index, ref int page) + { + AddPage(page); + + var entries = category.Entries; + + var i = 0; + + for (var j = 0; j < entries.Count; ++j) + { + var entry = entries[j]; + + if (!RewardSystem.HasAccess(m_From, entry)) + continue; + + if (i == 24) + { + AddButton(305, 415, 0xFA5, 0xFA7, 0, GumpButtonType.Page, ++page); + AddHtmlLocalized(340, 415, 200, 20, 1011066); // Next page + + AddPage(page); + + AddButton(270, 415, 0xFAE, 0xFB0, 0, GumpButtonType.Page, page - 1); + AddHtmlLocalized(185, 415, 200, 20, 1011067); // Previous page + + i = 0; + } + + AddButton(55 + i / 12 * 250, 80 + i % 12 * 25, 5540, 5541, GetButtonID(index, j)); + + if (entry.NameString != null) + AddHtml(80 + i / 12 * 250, 80 + i % 12 * 25, 250, 20, entry.NameString); + else + AddHtmlLocalized(80 + i / 12 * 250, 80 + i % 12 * 25, 250, 20, entry.Name); + ++i; + } + + page += 1; + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var buttonID = info.ButtonID - 1; + + if (buttonID == 0) + { + RewardSystem.ComputeRewardInfo(m_From, out var cur, out var max); + + if (cur < max) + m_From.SendGump(new RewardNoticeGump(m_From)); + } + else + { + --buttonID; + + var type = buttonID % 20; + var index = buttonID / 20; + + var categories = RewardSystem.Categories; + + if (type >= 0 && type < categories.Length) + { + var category = categories[type]; + + if (index >= 0 && index < category.Entries.Count) + { + var entry = category.Entries[index]; + + if (!RewardSystem.HasAccess(m_From, entry)) + return; + + m_From.SendGump(new RewardConfirmGump(m_From, entry)); + } + } + } + } + } +} diff --git a/Projects/UOContent/Engines/VeteranRewards/RewardConfirmGump.cs b/Projects/UOContent/Engines/VeteranRewards/RewardConfirmGump.cs index 0baccb5c7..07947febd 100644 --- a/Projects/UOContent/Engines/VeteranRewards/RewardConfirmGump.cs +++ b/Projects/UOContent/Engines/VeteranRewards/RewardConfirmGump.cs @@ -1,70 +1,77 @@ -using Server.Gumps; -using Server.Items; -using Server.Network; - -namespace Server.Engines.VeteranRewards -{ - public class RewardConfirmGump : Gump - { - private readonly RewardEntry m_Entry; - private readonly Mobile m_From; - - public RewardConfirmGump(Mobile from, RewardEntry entry) : base(0, 0) - { - m_From = from; - m_Entry = entry; - - from.CloseGump(); - - AddPage(0); - - AddBackground(10, 10, 500, 300, 2600); - - AddHtmlLocalized(30, 55, 300, 35, 1006000); // You have selected: - - if (entry.NameString != null) - AddHtml(335, 55, 150, 35, entry.NameString); - else - AddHtmlLocalized(335, 55, 150, 35, entry.Name); - - AddHtmlLocalized(30, 95, 300, 35, 1006001); // This will be assigned to this character: - AddLabel(335, 95, 0, from.Name); - - AddHtmlLocalized(35, 160, 450, 90, 1006002, true, - true); // Are you sure you wish to select this reward for this character? You will not be able to transfer this reward to another character on another shard. Click 'ok' below to confirm your selection or 'cancel' to go back to the selection screen. - - AddButton(60, 265, 4005, 4007, 1); - AddHtmlLocalized(95, 266, 150, 35, 1006044); // Ok - - AddButton(295, 265, 4017, 4019, 0); - AddHtmlLocalized(330, 266, 150, 35, 1006045); // Cancel - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 1) - { - if (!RewardSystem.HasAccess(m_From, m_Entry)) - return; - - Item item = m_Entry.Construct(); - - if (item != null) - { - if (item is RedSoulstone soulstone) - soulstone.Account = m_From.Account.Username; - - if (RewardSystem.ConsumeRewardPoint(m_From)) - m_From.AddToBackpack(item); - else - item.Delete(); - } - } - - RewardSystem.ComputeRewardInfo(m_From, out int cur, out int max); - - if (cur < max) - m_From.SendGump(new RewardNoticeGump(m_From)); - } - } -} +using Server.Gumps; +using Server.Items; +using Server.Network; + +namespace Server.Engines.VeteranRewards +{ + public class RewardConfirmGump : Gump + { + private readonly RewardEntry m_Entry; + private readonly Mobile m_From; + + public RewardConfirmGump(Mobile from, RewardEntry entry) : base(0, 0) + { + m_From = from; + m_Entry = entry; + + from.CloseGump(); + + AddPage(0); + + AddBackground(10, 10, 500, 300, 2600); + + AddHtmlLocalized(30, 55, 300, 35, 1006000); // You have selected: + + if (entry.NameString != null) + AddHtml(335, 55, 150, 35, entry.NameString); + else + AddHtmlLocalized(335, 55, 150, 35, entry.Name); + + AddHtmlLocalized(30, 95, 300, 35, 1006001); // This will be assigned to this character: + AddLabel(335, 95, 0, from.Name); + + AddHtmlLocalized( + 35, + 160, + 450, + 90, + 1006002, + true, + true + ); // Are you sure you wish to select this reward for this character? You will not be able to transfer this reward to another character on another shard. Click 'ok' below to confirm your selection or 'cancel' to go back to the selection screen. + + AddButton(60, 265, 4005, 4007, 1); + AddHtmlLocalized(95, 266, 150, 35, 1006044); // Ok + + AddButton(295, 265, 4017, 4019, 0); + AddHtmlLocalized(330, 266, 150, 35, 1006045); // Cancel + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 1) + { + if (!RewardSystem.HasAccess(m_From, m_Entry)) + return; + + var item = m_Entry.Construct(); + + if (item != null) + { + if (item is RedSoulstone soulstone) + soulstone.Account = m_From.Account.Username; + + if (RewardSystem.ConsumeRewardPoint(m_From)) + m_From.AddToBackpack(item); + else + item.Delete(); + } + } + + RewardSystem.ComputeRewardInfo(m_From, out var cur, out var max); + + if (cur < max) + m_From.SendGump(new RewardNoticeGump(m_From)); + } + } +} diff --git a/Projects/UOContent/Engines/VeteranRewards/RewardDemolitionGump.cs b/Projects/UOContent/Engines/VeteranRewards/RewardDemolitionGump.cs index d6ef6abde..4fac605d9 100644 --- a/Projects/UOContent/Engines/VeteranRewards/RewardDemolitionGump.cs +++ b/Projects/UOContent/Engines/VeteranRewards/RewardDemolitionGump.cs @@ -1,74 +1,75 @@ -using Server.Items; -using Server.Multis; -using Server.Network; - -namespace Server.Gumps -{ - public class RewardDemolitionGump : Gump - { - private readonly IAddon m_Addon; - - public RewardDemolitionGump(IAddon addon, int question) : base(150, 50) - { - m_Addon = addon; - - Closable = true; - Disposable = true; - Draggable = true; - Resizable = false; - - AddBackground(0, 0, 220, 170, 0x13BE); - AddBackground(10, 10, 200, 150, 0xBB8); - - AddHtmlLocalized(20, 30, 180, 60, question); // Do you wish to re-deed this decoration? - - AddHtmlLocalized(55, 100, 150, 25, 1011011); // CONTINUE - AddButton(20, 100, 0xFA5, 0xFA7, (int)Buttons.Confirm); - - AddHtmlLocalized(55, 125, 150, 25, 1011012); // CANCEL - AddButton(20, 125, 0xFA5, 0xFA7, (int)Buttons.Cancel); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (!(m_Addon is Item item) || item.Deleted) - return; - - if (info.ButtonID == (int)Buttons.Confirm) - { - Mobile m = sender.Mobile; - BaseHouse house = BaseHouse.FindHouseAt(m); - - if (house?.IsOwner(m) == true) - { - if (m.InRange(item.Location, 2)) - { - Item deed = m_Addon.Deed; - - if (deed != null) - { - m.AddToBackpack(deed); - house.Addons.Remove(item); - item.Delete(); - } - } - else - { - m.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - } - else - { - m.SendLocalizedMessage( - 1049784); // You can only re-deed this decoration if you are the house owner or originally placed the decoration. - } - } - } - - private enum Buttons - { - Cancel, - Confirm - } - } -} +using Server.Items; +using Server.Multis; +using Server.Network; + +namespace Server.Gumps +{ + public class RewardDemolitionGump : Gump + { + private readonly IAddon m_Addon; + + public RewardDemolitionGump(IAddon addon, int question) : base(150, 50) + { + m_Addon = addon; + + Closable = true; + Disposable = true; + Draggable = true; + Resizable = false; + + AddBackground(0, 0, 220, 170, 0x13BE); + AddBackground(10, 10, 200, 150, 0xBB8); + + AddHtmlLocalized(20, 30, 180, 60, question); // Do you wish to re-deed this decoration? + + AddHtmlLocalized(55, 100, 150, 25, 1011011); // CONTINUE + AddButton(20, 100, 0xFA5, 0xFA7, (int)Buttons.Confirm); + + AddHtmlLocalized(55, 125, 150, 25, 1011012); // CANCEL + AddButton(20, 125, 0xFA5, 0xFA7, (int)Buttons.Cancel); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (!(m_Addon is Item item) || item.Deleted) + return; + + if (info.ButtonID == (int)Buttons.Confirm) + { + var m = sender.Mobile; + var house = BaseHouse.FindHouseAt(m); + + if (house?.IsOwner(m) == true) + { + if (m.InRange(item.Location, 2)) + { + var deed = m_Addon.Deed; + + if (deed != null) + { + m.AddToBackpack(deed); + house.Addons.Remove(item); + item.Delete(); + } + } + else + { + m.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + } + else + { + m.SendLocalizedMessage( + 1049784 + ); // You can only re-deed this decoration if you are the house owner or originally placed the decoration. + } + } + } + + private enum Buttons + { + Cancel, + Confirm + } + } +} diff --git a/Projects/UOContent/Engines/VeteranRewards/RewardEntry.cs b/Projects/UOContent/Engines/VeteranRewards/RewardEntry.cs index c0aa633d1..e2fb63206 100644 --- a/Projects/UOContent/Engines/VeteranRewards/RewardEntry.cs +++ b/Projects/UOContent/Engines/VeteranRewards/RewardEntry.cs @@ -1,83 +1,87 @@ -using System; -using Server.Utilities; - -namespace Server.Engines.VeteranRewards -{ - public class RewardEntry - { - public RewardEntry(RewardCategory category, int name, Type itemType, params object[] args) - { - Category = category; - ItemType = itemType; - RequiredExpansion = Expansion.None; - Name = name; - Args = args; - category.Entries.Add(this); - } - - public RewardEntry(RewardCategory category, string name, Type itemType, params object[] args) - { - Category = category; - ItemType = itemType; - RequiredExpansion = Expansion.None; - NameString = name; - Args = args; - category.Entries.Add(this); - } - - public RewardEntry(RewardCategory category, int name, Type itemType, Expansion requiredExpansion, - params object[] args) - { - Category = category; - ItemType = itemType; - RequiredExpansion = requiredExpansion; - Name = name; - Args = args; - category.Entries.Add(this); - } - - public RewardEntry(RewardCategory category, string name, Type itemType, Expansion requiredExpansion, - params object[] args) - { - Category = category; - ItemType = itemType; - RequiredExpansion = requiredExpansion; - NameString = name; - Args = args; - category.Entries.Add(this); - } - - public RewardList List { get; set; } - - public RewardCategory Category { get; } - - public Type ItemType { get; } - - public Expansion RequiredExpansion { get; } - - public int Name { get; } - - public string NameString { get; } - - public object[] Args { get; } - - public Item Construct() - { - try - { - Item item = ActivatorUtil.CreateInstance(ItemType, Args) as Item; - - if (item is IRewardItem rewardItem) - rewardItem.IsRewardItem = true; - - return item; - } - catch - { - // ignored - } - - return null; - } - } -} +using System; +using Server.Utilities; + +namespace Server.Engines.VeteranRewards +{ + public class RewardEntry + { + public RewardEntry(RewardCategory category, int name, Type itemType, params object[] args) + { + Category = category; + ItemType = itemType; + RequiredExpansion = Expansion.None; + Name = name; + Args = args; + category.Entries.Add(this); + } + + public RewardEntry(RewardCategory category, string name, Type itemType, params object[] args) + { + Category = category; + ItemType = itemType; + RequiredExpansion = Expansion.None; + NameString = name; + Args = args; + category.Entries.Add(this); + } + + public RewardEntry( + RewardCategory category, int name, Type itemType, Expansion requiredExpansion, + params object[] args + ) + { + Category = category; + ItemType = itemType; + RequiredExpansion = requiredExpansion; + Name = name; + Args = args; + category.Entries.Add(this); + } + + public RewardEntry( + RewardCategory category, string name, Type itemType, Expansion requiredExpansion, + params object[] args + ) + { + Category = category; + ItemType = itemType; + RequiredExpansion = requiredExpansion; + NameString = name; + Args = args; + category.Entries.Add(this); + } + + public RewardList List { get; set; } + + public RewardCategory Category { get; } + + public Type ItemType { get; } + + public Expansion RequiredExpansion { get; } + + public int Name { get; } + + public string NameString { get; } + + public object[] Args { get; } + + public Item Construct() + { + try + { + var item = ActivatorUtil.CreateInstance(ItemType, Args) as Item; + + if (item is IRewardItem rewardItem) + rewardItem.IsRewardItem = true; + + return item; + } + catch + { + // ignored + } + + return null; + } + } +} diff --git a/Projects/UOContent/Engines/VeteranRewards/RewardList.cs b/Projects/UOContent/Engines/VeteranRewards/RewardList.cs index 5f5eab211..e50264ddf 100644 --- a/Projects/UOContent/Engines/VeteranRewards/RewardList.cs +++ b/Projects/UOContent/Engines/VeteranRewards/RewardList.cs @@ -1,20 +1,20 @@ -using System; - -namespace Server.Engines.VeteranRewards -{ - public class RewardList - { - public RewardList(TimeSpan interval, int index, RewardEntry[] entries) - { - Age = TimeSpan.FromDays(interval.TotalDays * index); - Entries = entries; - - for (int i = 0; i < entries.Length; ++i) - entries[i].List = this; - } - - public TimeSpan Age { get; } - - public RewardEntry[] Entries { get; } - } -} \ No newline at end of file +using System; + +namespace Server.Engines.VeteranRewards +{ + public class RewardList + { + public RewardList(TimeSpan interval, int index, RewardEntry[] entries) + { + Age = TimeSpan.FromDays(interval.TotalDays * index); + Entries = entries; + + for (var i = 0; i < entries.Length; ++i) + entries[i].List = this; + } + + public TimeSpan Age { get; } + + public RewardEntry[] Entries { get; } + } +} diff --git a/Projects/UOContent/Engines/VeteranRewards/RewardNoticeGump.cs b/Projects/UOContent/Engines/VeteranRewards/RewardNoticeGump.cs index 691d24382..b70850d40 100644 --- a/Projects/UOContent/Engines/VeteranRewards/RewardNoticeGump.cs +++ b/Projects/UOContent/Engines/VeteranRewards/RewardNoticeGump.cs @@ -1,38 +1,38 @@ -using Server.Gumps; -using Server.Network; - -namespace Server.Engines.VeteranRewards -{ - public class RewardNoticeGump : Gump - { - private readonly Mobile m_From; - - public RewardNoticeGump(Mobile from) : base(0, 0) - { - m_From = from; - - from.CloseGump(); - - AddPage(0); - - AddBackground(10, 10, 500, 135, 2600); - - /* You have reward items available. - * Click 'ok' below to get the selection menu or 'cancel' to be prompted upon your next login. - */ - AddHtmlLocalized(52, 35, 420, 55, 1006046, true, true); - - AddButton(60, 95, 4005, 4007, 1); - AddHtmlLocalized(95, 96, 150, 35, 1006044); // Ok - - AddButton(285, 95, 4017, 4019, 0); - AddHtmlLocalized(320, 96, 150, 35, 1006045); // Cancel - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 1) - m_From.SendGump(new RewardChoiceGump(m_From)); - } - } -} +using Server.Gumps; +using Server.Network; + +namespace Server.Engines.VeteranRewards +{ + public class RewardNoticeGump : Gump + { + private readonly Mobile m_From; + + public RewardNoticeGump(Mobile from) : base(0, 0) + { + m_From = from; + + from.CloseGump(); + + AddPage(0); + + AddBackground(10, 10, 500, 135, 2600); + + /* You have reward items available. + * Click 'ok' below to get the selection menu or 'cancel' to be prompted upon your next login. + */ + AddHtmlLocalized(52, 35, 420, 55, 1006046, true, true); + + AddButton(60, 95, 4005, 4007, 1); + AddHtmlLocalized(95, 96, 150, 35, 1006044); // Ok + + AddButton(285, 95, 4017, 4019, 0); + AddHtmlLocalized(320, 96, 150, 35, 1006045); // Cancel + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 1) + m_From.SendGump(new RewardChoiceGump(m_From)); + } + } +} diff --git a/Projects/UOContent/Engines/VeteranRewards/RewardOptionGump.cs b/Projects/UOContent/Engines/VeteranRewards/RewardOptionGump.cs index 077c50952..baac91a36 100644 --- a/Projects/UOContent/Engines/VeteranRewards/RewardOptionGump.cs +++ b/Projects/UOContent/Engines/VeteranRewards/RewardOptionGump.cs @@ -1,87 +1,87 @@ -using System.Collections.Generic; -using Server.Network; - -namespace Server.Gumps -{ - public interface IRewardOption - { - void GetOptions(RewardOptionList list); - void OnOptionSelected(Mobile from, int choice); - } - - public class RewardOptionGump : Gump - { - private readonly IRewardOption m_Option; - private readonly RewardOptionList m_Options = new RewardOptionList(); - - public RewardOptionGump(IRewardOption option, int title = 0) : base(60, 36) - { - m_Option = option; - - m_Option?.GetOptions(m_Options); - - AddPage(0); - - AddBackground(0, 0, 273, 324, 0x13BE); - AddImageTiled(10, 10, 253, 20, 0xA40); - AddImageTiled(10, 40, 253, 244, 0xA40); - AddImageTiled(10, 294, 253, 20, 0xA40); - AddAlphaRegion(10, 10, 253, 304); - - AddButton(10, 294, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL - - if (title > 0) - AddHtmlLocalized(14, 12, 273, 20, title, 0x7FFF); - else - AddHtmlLocalized(14, 12, 273, 20, 1080392, 0x7FFF); // Select your choice from the menu below. - - AddPage(1); - - for (int i = 0; i < m_Options.Count; i++) - { - AddButton(19, 49 + i * 24, 0x845, 0x846, m_Options[i].ID); - AddHtmlLocalized(44, 47 + i * 24, 213, 20, m_Options[i].Cliloc, 0x7FFF); - } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Option != null && Contains(info.ButtonID)) - m_Option.OnOptionSelected(sender.Mobile, info.ButtonID); - } - - private bool Contains(int chosen) - { - if (m_Options == null) - return false; - - foreach (RewardOption option in m_Options) - if (option.ID == chosen) - return true; - - return false; - } - } - - public class RewardOption - { - public RewardOption(int id, int cliloc) - { - ID = id; - Cliloc = cliloc; - } - - public int ID { get; } - - public int Cliloc { get; } - } - - public class RewardOptionList : List - { - public void Add(int id, int cliloc) - { - Add(new RewardOption(id, cliloc)); - } - } -} +using System.Collections.Generic; +using Server.Network; + +namespace Server.Gumps +{ + public interface IRewardOption + { + void GetOptions(RewardOptionList list); + void OnOptionSelected(Mobile from, int choice); + } + + public class RewardOptionGump : Gump + { + private readonly IRewardOption m_Option; + private readonly RewardOptionList m_Options = new RewardOptionList(); + + public RewardOptionGump(IRewardOption option, int title = 0) : base(60, 36) + { + m_Option = option; + + m_Option?.GetOptions(m_Options); + + AddPage(0); + + AddBackground(0, 0, 273, 324, 0x13BE); + AddImageTiled(10, 10, 253, 20, 0xA40); + AddImageTiled(10, 40, 253, 244, 0xA40); + AddImageTiled(10, 294, 253, 20, 0xA40); + AddAlphaRegion(10, 10, 253, 304); + + AddButton(10, 294, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL + + if (title > 0) + AddHtmlLocalized(14, 12, 273, 20, title, 0x7FFF); + else + AddHtmlLocalized(14, 12, 273, 20, 1080392, 0x7FFF); // Select your choice from the menu below. + + AddPage(1); + + for (var i = 0; i < m_Options.Count; i++) + { + AddButton(19, 49 + i * 24, 0x845, 0x846, m_Options[i].ID); + AddHtmlLocalized(44, 47 + i * 24, 213, 20, m_Options[i].Cliloc, 0x7FFF); + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Option != null && Contains(info.ButtonID)) + m_Option.OnOptionSelected(sender.Mobile, info.ButtonID); + } + + private bool Contains(int chosen) + { + if (m_Options == null) + return false; + + foreach (var option in m_Options) + if (option.ID == chosen) + return true; + + return false; + } + } + + public class RewardOption + { + public RewardOption(int id, int cliloc) + { + ID = id; + Cliloc = cliloc; + } + + public int ID { get; } + + public int Cliloc { get; } + } + + public class RewardOptionList : List + { + public void Add(int id, int cliloc) + { + Add(new RewardOption(id, cliloc)); + } + } +} diff --git a/Projects/UOContent/Engines/VeteranRewards/RewardSystem.cs b/Projects/UOContent/Engines/VeteranRewards/RewardSystem.cs index 78a08b3ee..683d42345 100644 --- a/Projects/UOContent/Engines/VeteranRewards/RewardSystem.cs +++ b/Projects/UOContent/Engines/VeteranRewards/RewardSystem.cs @@ -1,494 +1,578 @@ -using System; -using System.Collections.Generic; -using Server.Accounting; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.VeteranRewards -{ - public class RewardSystem - { - private static RewardCategory[] m_Categories; - private static RewardList[] m_Lists; - - public static bool Enabled { get; private set; } - - // assuming vet rewards are enabled, should total skill cap bonuses be awarded? (720 skills total at 4th level) - public static bool SkillCapRewards { get; private set; } - - public static TimeSpan RewardInterval { get; private set; } - - public static RewardCategory[] Categories - { - get - { - if (m_Categories == null) - SetupRewardTables(); - - return m_Categories; - } - } - - public static RewardList[] Lists - { - get - { - if (m_Lists == null) - SetupRewardTables(); - - return m_Lists; - } - } - - public static bool HasAccess(Mobile mob, RewardCategory category) - { - List entries = category.Entries; - - for (int j = 0; j < entries.Count; ++j) - // RewardEntry entry = entries[j]; - if (HasAccess(mob, entries[j])) - return true; - return false; - } - - public static bool HasAccess(Mobile mob, RewardEntry entry) - { - if (Core.Expansion < entry.RequiredExpansion) - return false; - - return HasAccess(mob, entry.List, out TimeSpan _); - } - - public static bool HasAccess(Mobile mob, RewardList list, out TimeSpan ts) - { - if (list == null) - { - ts = TimeSpan.Zero; - return false; - } - - if (!(mob.Account is Account acct)) - { - ts = TimeSpan.Zero; - return false; - } - - TimeSpan totalTime = DateTime.UtcNow - acct.Created; - - ts = list.Age - totalTime; - - if (ts <= TimeSpan.Zero) - return true; - - return false; - } - - public static int GetRewardLevel(Mobile mob) - { - if (!(mob.Account is Account acct)) - return 0; - - return GetRewardLevel(acct); - } - - public static int GetRewardLevel(Account acct) - { - TimeSpan totalTime = DateTime.UtcNow - acct.Created; - - return Math.Max((int)(totalTime.TotalDays / RewardInterval.TotalDays), 0); - } - - public static bool HasHalfLevel(Mobile mob) - { - if (!(mob.Account is Account acct)) - return false; - - return HasHalfLevel(acct); - } - - public static bool HasHalfLevel(Account acct) - { - TimeSpan totalTime = DateTime.UtcNow - acct.Created; - - double level = totalTime.TotalDays / RewardInterval.TotalDays; - - return level >= 0.5; - } - - public static bool ConsumeRewardPoint(Mobile mob) - { - ComputeRewardInfo(mob, out int cur, out int max); - - if (cur >= max) - return false; - - if (!(mob.Account is Account acct)) - return false; - - // if (mob.AccessLevel < AccessLevel.GameMaster) - acct.SetTag("numRewardsChosen", (cur + 1).ToString()); - - return true; - } - - public static void ComputeRewardInfo(Mobile mob, out int cur, out int max) - { - ComputeRewardInfo(mob, out cur, out max, out _); - } - - public static void ComputeRewardInfo(Mobile mob, out int cur, out int max, out int level) - { - if (!(mob.Account is Account acct)) - { - cur = max = level = 0; - return; - } - - level = GetRewardLevel(acct); - - if (level == 0) - { - cur = max = 0; - return; - } - - string tag = acct.GetTag("numRewardsChosen"); - - if (string.IsNullOrEmpty(tag)) - cur = 0; - else - cur = Utility.ToInt32(tag); - - if (level >= 6) - max = 9 + (level - 6) * 2; - else - max = 2 + level; - } - - public static bool CheckIsUsableBy(Mobile from, Item item, object[] args = null) - { - bool isRelaxedRules = item is DyeTub || item is MonsterStatuette; - - Type type = item.GetType(); - - for (int i = 0; i < Lists.Length; ++i) - { - RewardList list = Lists[i]; - RewardEntry[] entries = list.Entries; - - for (int j = 0; j < entries.Length; ++j) - { - if (entries[j].ItemType != type) - continue; - - if (args == null && entries[j].Args.Length == 0) - { - if ((isRelaxedRules && i <= 0) || HasAccess(from, list, out TimeSpan ts)) - return true; - - from.SendLocalizedMessage(1008126, true, - Math.Ceiling(ts.TotalDays / 30.0) - .ToString()); // Your account is not old enough to use this item. Months until you can use this item : - return false; - } - - if (args?.Length != entries[j].Args.Length) - continue; - - bool match = true; - - for (int k = 0; match && k < args.Length; ++k) - match = args[k].Equals(entries[j].Args[k]); - - if (match) - { - if ((isRelaxedRules && i <= 0) || HasAccess(from, list, out TimeSpan ts)) - return true; - - from.SendLocalizedMessage(1008126, true, - Math.Ceiling(ts.TotalDays / 30.0) - .ToString()); // Your account is not old enough to use this item. Months until you can use this item : - return false; - } - } - } - - // no entry? - return true; - } - - public static int GetRewardYearLabel(Item item, object[] args) - { - int level = GetRewardYear(item, args); - - return 1076216 + (level < 10 ? level : level < 12 ? level - 9 + 4240 : level - 11 + 37585); - } - - public static int GetRewardYear(Item item, object[] args) - { - Type type = item.GetType(); - - for (int i = 0; i < Lists.Length; ++i) - { - RewardList list = Lists[i]; - RewardEntry[] entries = list.Entries; - - for (int j = 0; j < entries.Length; ++j) - if (entries[j].ItemType == type) - { - if (args == null && entries[j].Args.Length == 0) - return i + 1; - - if (args?.Length == entries[j].Args.Length) - { - bool match = true; - - for (int k = 0; match && k < args.Length; ++k) - match = args[k].Equals(entries[j].Args[k]); - - if (match) - return i + 1; - } - } - } - - // no entry? - return 0; - } - - public static void SetupRewardTables() - { - RewardCategory monsterStatues = new RewardCategory(1049750); - RewardCategory cloaksAndRobes = new RewardCategory(1049752); - RewardCategory etherealSteeds = new RewardCategory(1049751); - RewardCategory specialDyeTubs = new RewardCategory(1049753); - RewardCategory houseAddOns = new RewardCategory(1049754); - RewardCategory miscellaneous = new RewardCategory(1078596); - - m_Categories = new[] - { - monsterStatues, - cloaksAndRobes, - etherealSteeds, - specialDyeTubs, - houseAddOns, - miscellaneous - }; - - const int Bronze = 0x972; - const int Copper = 0x96D; - const int Golden = 0x8A5; - const int Agapite = 0x979; - const int Verite = 0x89F; - const int Valorite = 0x8AB; - const int IceGreen = 0x47F; - const int IceBlue = 0x482; - const int DarkGray = 0x497; - const int Fire = 0x489; - const int IceWhite = 0x47E; - const int JetBlack = 0x001; - const int Pink = 0x490; - const int Crimson = 0x485; - - m_Lists = new[] - { - new RewardList(RewardInterval, 1, new[] - { - new RewardEntry(specialDyeTubs, 1006008, typeof(RewardBlackDyeTub)), - new RewardEntry(specialDyeTubs, 1006013, typeof(FurnitureDyeTub)), - new RewardEntry(specialDyeTubs, 1006047, typeof(SpecialDyeTub)), - new RewardEntry(cloaksAndRobes, 1006009, typeof(RewardCloak), Bronze, 1041286), - new RewardEntry(cloaksAndRobes, 1006010, typeof(RewardRobe), Bronze, 1041287), - new RewardEntry(cloaksAndRobes, 1080366, typeof(RewardDress), Expansion.ML, Bronze, 1080366), - new RewardEntry(cloaksAndRobes, 1006011, typeof(RewardCloak), Copper, 1041288), - new RewardEntry(cloaksAndRobes, 1006012, typeof(RewardRobe), Copper, 1041289), - new RewardEntry(cloaksAndRobes, 1080367, typeof(RewardDress), Expansion.ML, Copper, 1080367), - new RewardEntry(monsterStatues, 1006024, typeof(MonsterStatuette), MonsterStatuetteType.Crocodile), - new RewardEntry(monsterStatues, 1006025, typeof(MonsterStatuette), MonsterStatuetteType.Daemon), - new RewardEntry(monsterStatues, 1006026, typeof(MonsterStatuette), MonsterStatuetteType.Dragon), - new RewardEntry(monsterStatues, 1006027, typeof(MonsterStatuette), MonsterStatuetteType.EarthElemental), - new RewardEntry(monsterStatues, 1006028, typeof(MonsterStatuette), MonsterStatuetteType.Ettin), - new RewardEntry(monsterStatues, 1006029, typeof(MonsterStatuette), MonsterStatuetteType.Gargoyle), - new RewardEntry(monsterStatues, 1006030, typeof(MonsterStatuette), MonsterStatuetteType.Gorilla), - new RewardEntry(monsterStatues, 1006031, typeof(MonsterStatuette), MonsterStatuetteType.Lich), - new RewardEntry(monsterStatues, 1006032, typeof(MonsterStatuette), MonsterStatuetteType.Lizardman), - new RewardEntry(monsterStatues, 1006033, typeof(MonsterStatuette), MonsterStatuetteType.Ogre), - new RewardEntry(monsterStatues, 1006034, typeof(MonsterStatuette), MonsterStatuetteType.Orc), - new RewardEntry(monsterStatues, 1006035, typeof(MonsterStatuette), MonsterStatuetteType.Ratman), - new RewardEntry(monsterStatues, 1006036, typeof(MonsterStatuette), MonsterStatuetteType.Skeleton), - new RewardEntry(monsterStatues, 1006037, typeof(MonsterStatuette), MonsterStatuetteType.Troll), - new RewardEntry(houseAddOns, 1062692, typeof(ContestMiniHouseDeed), Expansion.AOS, - MiniHouseType.MalasMountainPass), - new RewardEntry(houseAddOns, 1072216, typeof(ContestMiniHouseDeed), Expansion.SE, - MiniHouseType.ChurchAtNight), - new RewardEntry(miscellaneous, 1076155, typeof(RedSoulstone), Expansion.ML), - new RewardEntry(miscellaneous, 1080523, typeof(CommodityDeedBox), Expansion.ML) - }), - new RewardList(RewardInterval, 2, new[] - { - new RewardEntry(specialDyeTubs, 1006052, typeof(LeatherDyeTub)), - new RewardEntry(cloaksAndRobes, 1006014, typeof(RewardCloak), Agapite, 1041290), - new RewardEntry(cloaksAndRobes, 1006015, typeof(RewardRobe), Agapite, 1041291), - new RewardEntry(cloaksAndRobes, 1080369, typeof(RewardDress), Expansion.ML, Agapite, 1080369), - new RewardEntry(cloaksAndRobes, 1006016, typeof(RewardCloak), Golden, 1041292), - new RewardEntry(cloaksAndRobes, 1006017, typeof(RewardRobe), Golden, 1041293), - new RewardEntry(cloaksAndRobes, 1080368, typeof(RewardDress), Expansion.ML, Golden, 1080368), - new RewardEntry(houseAddOns, 1006048, typeof(BannerDeed)), - new RewardEntry(houseAddOns, 1006049, typeof(FlamingHeadDeed)), - new RewardEntry(houseAddOns, 1080409, typeof(MinotaurStatueDeed), Expansion.ML) - }), - new RewardList(RewardInterval, 3, new[] - { - new RewardEntry(cloaksAndRobes, 1006020, typeof(RewardCloak), Verite, 1041294), - new RewardEntry(cloaksAndRobes, 1006021, typeof(RewardRobe), Verite, 1041295), - new RewardEntry(cloaksAndRobes, 1080370, typeof(RewardDress), Expansion.ML, Verite, 1080370), - new RewardEntry(cloaksAndRobes, 1006022, typeof(RewardCloak), Valorite, 1041296), - new RewardEntry(cloaksAndRobes, 1006023, typeof(RewardRobe), Valorite, 1041297), - new RewardEntry(cloaksAndRobes, 1080371, typeof(RewardDress), Expansion.ML, Valorite, 1080371), - new RewardEntry(monsterStatues, 1006038, typeof(MonsterStatuette), MonsterStatuetteType.Cow), - new RewardEntry(monsterStatues, 1006039, typeof(MonsterStatuette), MonsterStatuetteType.Zombie), - new RewardEntry(monsterStatues, 1006040, typeof(MonsterStatuette), MonsterStatuetteType.Llama), - new RewardEntry(etherealSteeds, 1006019, typeof(EtherealHorse)), - new RewardEntry(etherealSteeds, 1006050, typeof(EtherealOstard)), - new RewardEntry(etherealSteeds, 1006051, typeof(EtherealLlama)), - new RewardEntry(houseAddOns, 1080407, typeof(PottedCactusDeed), Expansion.ML) - }), - new RewardList(RewardInterval, 4, new[] - { - new RewardEntry(specialDyeTubs, 1049740, typeof(RunebookDyeTub)), - new RewardEntry(cloaksAndRobes, 1049725, typeof(RewardCloak), DarkGray, 1049757), - new RewardEntry(cloaksAndRobes, 1049726, typeof(RewardRobe), DarkGray, 1049756), - new RewardEntry(cloaksAndRobes, 1080374, typeof(RewardDress), Expansion.ML, DarkGray, 1080374), - new RewardEntry(cloaksAndRobes, 1049727, typeof(RewardCloak), IceGreen, 1049759), - new RewardEntry(cloaksAndRobes, 1049728, typeof(RewardRobe), IceGreen, 1049758), - new RewardEntry(cloaksAndRobes, 1080372, typeof(RewardDress), Expansion.ML, IceGreen, 1080372), - - new RewardEntry(cloaksAndRobes, 1049729, typeof(RewardCloak), IceBlue, 1049761), - new RewardEntry(cloaksAndRobes, 1049730, typeof(RewardRobe), IceBlue, 1049760), - new RewardEntry(cloaksAndRobes, 1080373, typeof(RewardDress), Expansion.ML, IceBlue, 1080373), - new RewardEntry(monsterStatues, 1049742, typeof(MonsterStatuette), MonsterStatuetteType.Ophidian), - new RewardEntry(monsterStatues, 1049743, typeof(MonsterStatuette), MonsterStatuetteType.Reaper), - new RewardEntry(monsterStatues, 1049744, typeof(MonsterStatuette), MonsterStatuetteType.Mongbat), - new RewardEntry(etherealSteeds, 1049746, typeof(EtherealKirin)), - new RewardEntry(etherealSteeds, 1049745, typeof(EtherealUnicorn)), - new RewardEntry(etherealSteeds, 1049747, typeof(EtherealRidgeback)), - new RewardEntry(houseAddOns, 1049737, typeof(DecorativeShieldDeed)), - new RewardEntry(houseAddOns, 1049738, typeof(HangingSkeletonDeed)) - }), - new RewardList(RewardInterval, 5, new[] - { - new RewardEntry(specialDyeTubs, 1049741, typeof(StatuetteDyeTub)), - new RewardEntry(cloaksAndRobes, 1049731, typeof(RewardCloak), JetBlack, 1049763), - new RewardEntry(cloaksAndRobes, 1049732, typeof(RewardRobe), JetBlack, 1049762), - new RewardEntry(cloaksAndRobes, 1080377, typeof(RewardDress), Expansion.ML, JetBlack, 1080377), - new RewardEntry(cloaksAndRobes, 1049733, typeof(RewardCloak), IceWhite, 1049765), - new RewardEntry(cloaksAndRobes, 1049734, typeof(RewardRobe), IceWhite, 1049764), - new RewardEntry(cloaksAndRobes, 1080376, typeof(RewardDress), Expansion.ML, IceWhite, 1080376), - new RewardEntry(cloaksAndRobes, 1049735, typeof(RewardCloak), Fire, 1049767), - new RewardEntry(cloaksAndRobes, 1049736, typeof(RewardRobe), Fire, 1049766), - new RewardEntry(cloaksAndRobes, 1080375, typeof(RewardDress), Expansion.ML, Fire, 1080375), - new RewardEntry(monsterStatues, 1049768, typeof(MonsterStatuette), MonsterStatuetteType.Gazer), - new RewardEntry(monsterStatues, 1049769, typeof(MonsterStatuette), MonsterStatuetteType.FireElemental), - new RewardEntry(monsterStatues, 1049770, typeof(MonsterStatuette), MonsterStatuetteType.Wolf), - new RewardEntry(etherealSteeds, 1049749, typeof(EtherealSwampDragon)), - new RewardEntry(etherealSteeds, 1049748, typeof(EtherealBeetle)), - new RewardEntry(houseAddOns, 1049739, typeof(StoneAnkhDeed)), - new RewardEntry(houseAddOns, 1080384, typeof(BloodyPentagramDeed), Expansion.ML) - }), - new RewardList(RewardInterval, 6, new[] - { - new RewardEntry(houseAddOns, 1076188, typeof(CharacterStatueMaker), Expansion.ML, StatueType.Jade), - new RewardEntry(houseAddOns, 1076189, typeof(CharacterStatueMaker), Expansion.ML, StatueType.Marble), - new RewardEntry(houseAddOns, 1076190, typeof(CharacterStatueMaker), Expansion.ML, StatueType.Bronze), - new RewardEntry(houseAddOns, 1080527, typeof(RewardBrazierDeed), Expansion.ML) - }), - new RewardList(RewardInterval, 7, new[] - { - new RewardEntry(houseAddOns, 1076157, typeof(CannonDeed), Expansion.ML), - new RewardEntry(houseAddOns, 1080550, typeof(TreeStumpDeed), Expansion.ML) - }), - new RewardList(RewardInterval, 8, new[] - { - new RewardEntry(miscellaneous, 1076158, typeof(WeaponEngravingTool), Expansion.ML) - }), - new RewardList(RewardInterval, 9, new[] - { - new RewardEntry(etherealSteeds, 1076159, typeof(RideablePolarBear), Expansion.ML), - new RewardEntry(houseAddOns, 1080549, typeof(WallBannerDeed), Expansion.ML) - }), - new RewardList(RewardInterval, 10, new[] - { - new RewardEntry(monsterStatues, 1080520, typeof(MonsterStatuette), Expansion.ML, - MonsterStatuetteType.Harrower), - new RewardEntry(monsterStatues, 1080521, typeof(MonsterStatuette), Expansion.ML, - MonsterStatuetteType.Efreet), - - new RewardEntry(cloaksAndRobes, 1080382, typeof(RewardCloak), Expansion.ML, Pink, 1080382), - new RewardEntry(cloaksAndRobes, 1080380, typeof(RewardRobe), Expansion.ML, Pink, 1080380), - new RewardEntry(cloaksAndRobes, 1080378, typeof(RewardDress), Expansion.ML, Pink, 1080378), - new RewardEntry(cloaksAndRobes, 1080383, typeof(RewardCloak), Expansion.ML, Crimson, 1080383), - new RewardEntry(cloaksAndRobes, 1080381, typeof(RewardRobe), Expansion.ML, Crimson, 1080381), - new RewardEntry(cloaksAndRobes, 1080379, typeof(RewardDress), Expansion.ML, Crimson, 1080379), - - new RewardEntry(etherealSteeds, 1080386, typeof(EtherealCuSidhe), Expansion.ML), - - new RewardEntry(houseAddOns, 1080548, typeof(MiningCartDeed), Expansion.ML), - new RewardEntry(houseAddOns, 1080397, typeof(AnkhOfSacrificeDeed), Expansion.ML) - }), - - new RewardList(RewardInterval, 11, new[] - { - new RewardEntry(etherealSteeds, 1113908, typeof(EtherealReptalon), Expansion.ML) - }), - - new RewardList(RewardInterval, 12, new[] - { - new RewardEntry(etherealSteeds, 1113813, typeof(EtherealHiryu), Expansion.ML) - }) - }; - } - - public static void Initialize() - { - Enabled = ServerConfiguration.GetOrUpdateSetting("vetRewards.enable", true); - SkillCapRewards = ServerConfiguration.GetOrUpdateSetting("vetRewards.skillCapRewards", true); - RewardInterval = ServerConfiguration.GetOrUpdateSetting("vetRewards.rewardInterval", TimeSpan.FromDays(30.0)); - - if (Enabled) - EventSink.Login += EventSink_Login; - } - - private static void EventSink_Login(Mobile m) - { - if (!m.Alive) - return; - - ComputeRewardInfo(m, out int cur, out int max, out int level); - - if (m.SkillsCap == 7000 || m.SkillsCap == 7050 || m.SkillsCap == 7100 || - m.SkillsCap == 7150 || m.SkillsCap == 7200) - { - level = Math.Clamp(level, 0, 4); - - if (SkillCapRewards) - m.SkillsCap = 7000 + level * 50; - else - m.SkillsCap = 7000; - } - - if (Core.ML && m is PlayerMobile pm && !pm.HasStatReward && HasHalfLevel(pm)) - { - pm.HasStatReward = true; - pm.StatCap += 5; - } - - if (cur < max) - m.SendGump(new RewardNoticeGump(m)); - } - } - - public interface IRewardItem - { - bool IsRewardItem { get; set; } - } -} +using System; +using Server.Accounting; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.VeteranRewards +{ + public class RewardSystem + { + private static RewardCategory[] m_Categories; + private static RewardList[] m_Lists; + + public static bool Enabled { get; private set; } + + // assuming vet rewards are enabled, should total skill cap bonuses be awarded? (720 skills total at 4th level) + public static bool SkillCapRewards { get; private set; } + + public static TimeSpan RewardInterval { get; private set; } + + public static RewardCategory[] Categories + { + get + { + if (m_Categories == null) + SetupRewardTables(); + + return m_Categories; + } + } + + public static RewardList[] Lists + { + get + { + if (m_Lists == null) + SetupRewardTables(); + + return m_Lists; + } + } + + public static bool HasAccess(Mobile mob, RewardCategory category) + { + var entries = category.Entries; + + for (var j = 0; j < entries.Count; ++j) + // RewardEntry entry = entries[j]; + if (HasAccess(mob, entries[j])) + return true; + return false; + } + + public static bool HasAccess(Mobile mob, RewardEntry entry) + { + if (Core.Expansion < entry.RequiredExpansion) + return false; + + return HasAccess(mob, entry.List, out var _); + } + + public static bool HasAccess(Mobile mob, RewardList list, out TimeSpan ts) + { + if (list == null) + { + ts = TimeSpan.Zero; + return false; + } + + if (!(mob.Account is Account acct)) + { + ts = TimeSpan.Zero; + return false; + } + + var totalTime = DateTime.UtcNow - acct.Created; + + ts = list.Age - totalTime; + + if (ts <= TimeSpan.Zero) + return true; + + return false; + } + + public static int GetRewardLevel(Mobile mob) + { + if (!(mob.Account is Account acct)) + return 0; + + return GetRewardLevel(acct); + } + + public static int GetRewardLevel(Account acct) + { + var totalTime = DateTime.UtcNow - acct.Created; + + return Math.Max((int)(totalTime.TotalDays / RewardInterval.TotalDays), 0); + } + + public static bool HasHalfLevel(Mobile mob) + { + if (!(mob.Account is Account acct)) + return false; + + return HasHalfLevel(acct); + } + + public static bool HasHalfLevel(Account acct) + { + var totalTime = DateTime.UtcNow - acct.Created; + + var level = totalTime.TotalDays / RewardInterval.TotalDays; + + return level >= 0.5; + } + + public static bool ConsumeRewardPoint(Mobile mob) + { + ComputeRewardInfo(mob, out var cur, out var max); + + if (cur >= max) + return false; + + if (!(mob.Account is Account acct)) + return false; + + // if (mob.AccessLevel < AccessLevel.GameMaster) + acct.SetTag("numRewardsChosen", (cur + 1).ToString()); + + return true; + } + + public static void ComputeRewardInfo(Mobile mob, out int cur, out int max) + { + ComputeRewardInfo(mob, out cur, out max, out _); + } + + public static void ComputeRewardInfo(Mobile mob, out int cur, out int max, out int level) + { + if (!(mob.Account is Account acct)) + { + cur = max = level = 0; + return; + } + + level = GetRewardLevel(acct); + + if (level == 0) + { + cur = max = 0; + return; + } + + var tag = acct.GetTag("numRewardsChosen"); + + if (string.IsNullOrEmpty(tag)) + cur = 0; + else + cur = Utility.ToInt32(tag); + + if (level >= 6) + max = 9 + (level - 6) * 2; + else + max = 2 + level; + } + + public static bool CheckIsUsableBy(Mobile from, Item item, object[] args = null) + { + var isRelaxedRules = item is DyeTub || item is MonsterStatuette; + + var type = item.GetType(); + + for (var i = 0; i < Lists.Length; ++i) + { + var list = Lists[i]; + var entries = list.Entries; + + for (var j = 0; j < entries.Length; ++j) + { + if (entries[j].ItemType != type) + continue; + + if (args == null && entries[j].Args.Length == 0) + { + if (isRelaxedRules && i <= 0 || HasAccess(from, list, out var ts)) + return true; + + from.SendLocalizedMessage( + 1008126, + true, + Math.Ceiling(ts.TotalDays / 30.0) + .ToString() + ); // Your account is not old enough to use this item. Months until you can use this item : + return false; + } + + if (args?.Length != entries[j].Args.Length) + continue; + + var match = true; + + for (var k = 0; match && k < args.Length; ++k) + match = args[k].Equals(entries[j].Args[k]); + + if (match) + { + if (isRelaxedRules && i <= 0 || HasAccess(from, list, out var ts)) + return true; + + from.SendLocalizedMessage( + 1008126, + true, + Math.Ceiling(ts.TotalDays / 30.0) + .ToString() + ); // Your account is not old enough to use this item. Months until you can use this item : + return false; + } + } + } + + // no entry? + return true; + } + + public static int GetRewardYearLabel(Item item, object[] args) + { + var level = GetRewardYear(item, args); + + return 1076216 + (level < 10 ? level : + level < 12 ? level - 9 + 4240 : level - 11 + 37585); + } + + public static int GetRewardYear(Item item, object[] args) + { + var type = item.GetType(); + + for (var i = 0; i < Lists.Length; ++i) + { + var list = Lists[i]; + var entries = list.Entries; + + for (var j = 0; j < entries.Length; ++j) + if (entries[j].ItemType == type) + { + if (args == null && entries[j].Args.Length == 0) + return i + 1; + + if (args?.Length == entries[j].Args.Length) + { + var match = true; + + for (var k = 0; match && k < args.Length; ++k) + match = args[k].Equals(entries[j].Args[k]); + + if (match) + return i + 1; + } + } + } + + // no entry? + return 0; + } + + public static void SetupRewardTables() + { + var monsterStatues = new RewardCategory(1049750); + var cloaksAndRobes = new RewardCategory(1049752); + var etherealSteeds = new RewardCategory(1049751); + var specialDyeTubs = new RewardCategory(1049753); + var houseAddOns = new RewardCategory(1049754); + var miscellaneous = new RewardCategory(1078596); + + m_Categories = new[] + { + monsterStatues, + cloaksAndRobes, + etherealSteeds, + specialDyeTubs, + houseAddOns, + miscellaneous + }; + + const int Bronze = 0x972; + const int Copper = 0x96D; + const int Golden = 0x8A5; + const int Agapite = 0x979; + const int Verite = 0x89F; + const int Valorite = 0x8AB; + const int IceGreen = 0x47F; + const int IceBlue = 0x482; + const int DarkGray = 0x497; + const int Fire = 0x489; + const int IceWhite = 0x47E; + const int JetBlack = 0x001; + const int Pink = 0x490; + const int Crimson = 0x485; + + m_Lists = new[] + { + new RewardList( + RewardInterval, + 1, + new[] + { + new RewardEntry(specialDyeTubs, 1006008, typeof(RewardBlackDyeTub)), + new RewardEntry(specialDyeTubs, 1006013, typeof(FurnitureDyeTub)), + new RewardEntry(specialDyeTubs, 1006047, typeof(SpecialDyeTub)), + new RewardEntry(cloaksAndRobes, 1006009, typeof(RewardCloak), Bronze, 1041286), + new RewardEntry(cloaksAndRobes, 1006010, typeof(RewardRobe), Bronze, 1041287), + new RewardEntry(cloaksAndRobes, 1080366, typeof(RewardDress), Expansion.ML, Bronze, 1080366), + new RewardEntry(cloaksAndRobes, 1006011, typeof(RewardCloak), Copper, 1041288), + new RewardEntry(cloaksAndRobes, 1006012, typeof(RewardRobe), Copper, 1041289), + new RewardEntry(cloaksAndRobes, 1080367, typeof(RewardDress), Expansion.ML, Copper, 1080367), + new RewardEntry(monsterStatues, 1006024, typeof(MonsterStatuette), MonsterStatuetteType.Crocodile), + new RewardEntry(monsterStatues, 1006025, typeof(MonsterStatuette), MonsterStatuetteType.Daemon), + new RewardEntry(monsterStatues, 1006026, typeof(MonsterStatuette), MonsterStatuetteType.Dragon), + new RewardEntry( + monsterStatues, + 1006027, + typeof(MonsterStatuette), + MonsterStatuetteType.EarthElemental + ), + new RewardEntry(monsterStatues, 1006028, typeof(MonsterStatuette), MonsterStatuetteType.Ettin), + new RewardEntry(monsterStatues, 1006029, typeof(MonsterStatuette), MonsterStatuetteType.Gargoyle), + new RewardEntry(monsterStatues, 1006030, typeof(MonsterStatuette), MonsterStatuetteType.Gorilla), + new RewardEntry(monsterStatues, 1006031, typeof(MonsterStatuette), MonsterStatuetteType.Lich), + new RewardEntry(monsterStatues, 1006032, typeof(MonsterStatuette), MonsterStatuetteType.Lizardman), + new RewardEntry(monsterStatues, 1006033, typeof(MonsterStatuette), MonsterStatuetteType.Ogre), + new RewardEntry(monsterStatues, 1006034, typeof(MonsterStatuette), MonsterStatuetteType.Orc), + new RewardEntry(monsterStatues, 1006035, typeof(MonsterStatuette), MonsterStatuetteType.Ratman), + new RewardEntry(monsterStatues, 1006036, typeof(MonsterStatuette), MonsterStatuetteType.Skeleton), + new RewardEntry(monsterStatues, 1006037, typeof(MonsterStatuette), MonsterStatuetteType.Troll), + new RewardEntry( + houseAddOns, + 1062692, + typeof(ContestMiniHouseDeed), + Expansion.AOS, + MiniHouseType.MalasMountainPass + ), + new RewardEntry( + houseAddOns, + 1072216, + typeof(ContestMiniHouseDeed), + Expansion.SE, + MiniHouseType.ChurchAtNight + ), + new RewardEntry(miscellaneous, 1076155, typeof(RedSoulstone), Expansion.ML), + new RewardEntry(miscellaneous, 1080523, typeof(CommodityDeedBox), Expansion.ML) + } + ), + new RewardList( + RewardInterval, + 2, + new[] + { + new RewardEntry(specialDyeTubs, 1006052, typeof(LeatherDyeTub)), + new RewardEntry(cloaksAndRobes, 1006014, typeof(RewardCloak), Agapite, 1041290), + new RewardEntry(cloaksAndRobes, 1006015, typeof(RewardRobe), Agapite, 1041291), + new RewardEntry(cloaksAndRobes, 1080369, typeof(RewardDress), Expansion.ML, Agapite, 1080369), + new RewardEntry(cloaksAndRobes, 1006016, typeof(RewardCloak), Golden, 1041292), + new RewardEntry(cloaksAndRobes, 1006017, typeof(RewardRobe), Golden, 1041293), + new RewardEntry(cloaksAndRobes, 1080368, typeof(RewardDress), Expansion.ML, Golden, 1080368), + new RewardEntry(houseAddOns, 1006048, typeof(BannerDeed)), + new RewardEntry(houseAddOns, 1006049, typeof(FlamingHeadDeed)), + new RewardEntry(houseAddOns, 1080409, typeof(MinotaurStatueDeed), Expansion.ML) + } + ), + new RewardList( + RewardInterval, + 3, + new[] + { + new RewardEntry(cloaksAndRobes, 1006020, typeof(RewardCloak), Verite, 1041294), + new RewardEntry(cloaksAndRobes, 1006021, typeof(RewardRobe), Verite, 1041295), + new RewardEntry(cloaksAndRobes, 1080370, typeof(RewardDress), Expansion.ML, Verite, 1080370), + new RewardEntry(cloaksAndRobes, 1006022, typeof(RewardCloak), Valorite, 1041296), + new RewardEntry(cloaksAndRobes, 1006023, typeof(RewardRobe), Valorite, 1041297), + new RewardEntry(cloaksAndRobes, 1080371, typeof(RewardDress), Expansion.ML, Valorite, 1080371), + new RewardEntry(monsterStatues, 1006038, typeof(MonsterStatuette), MonsterStatuetteType.Cow), + new RewardEntry(monsterStatues, 1006039, typeof(MonsterStatuette), MonsterStatuetteType.Zombie), + new RewardEntry(monsterStatues, 1006040, typeof(MonsterStatuette), MonsterStatuetteType.Llama), + new RewardEntry(etherealSteeds, 1006019, typeof(EtherealHorse)), + new RewardEntry(etherealSteeds, 1006050, typeof(EtherealOstard)), + new RewardEntry(etherealSteeds, 1006051, typeof(EtherealLlama)), + new RewardEntry(houseAddOns, 1080407, typeof(PottedCactusDeed), Expansion.ML) + } + ), + new RewardList( + RewardInterval, + 4, + new[] + { + new RewardEntry(specialDyeTubs, 1049740, typeof(RunebookDyeTub)), + new RewardEntry(cloaksAndRobes, 1049725, typeof(RewardCloak), DarkGray, 1049757), + new RewardEntry(cloaksAndRobes, 1049726, typeof(RewardRobe), DarkGray, 1049756), + new RewardEntry(cloaksAndRobes, 1080374, typeof(RewardDress), Expansion.ML, DarkGray, 1080374), + new RewardEntry(cloaksAndRobes, 1049727, typeof(RewardCloak), IceGreen, 1049759), + new RewardEntry(cloaksAndRobes, 1049728, typeof(RewardRobe), IceGreen, 1049758), + new RewardEntry(cloaksAndRobes, 1080372, typeof(RewardDress), Expansion.ML, IceGreen, 1080372), + + new RewardEntry(cloaksAndRobes, 1049729, typeof(RewardCloak), IceBlue, 1049761), + new RewardEntry(cloaksAndRobes, 1049730, typeof(RewardRobe), IceBlue, 1049760), + new RewardEntry(cloaksAndRobes, 1080373, typeof(RewardDress), Expansion.ML, IceBlue, 1080373), + new RewardEntry(monsterStatues, 1049742, typeof(MonsterStatuette), MonsterStatuetteType.Ophidian), + new RewardEntry(monsterStatues, 1049743, typeof(MonsterStatuette), MonsterStatuetteType.Reaper), + new RewardEntry(monsterStatues, 1049744, typeof(MonsterStatuette), MonsterStatuetteType.Mongbat), + new RewardEntry(etherealSteeds, 1049746, typeof(EtherealKirin)), + new RewardEntry(etherealSteeds, 1049745, typeof(EtherealUnicorn)), + new RewardEntry(etherealSteeds, 1049747, typeof(EtherealRidgeback)), + new RewardEntry(houseAddOns, 1049737, typeof(DecorativeShieldDeed)), + new RewardEntry(houseAddOns, 1049738, typeof(HangingSkeletonDeed)) + } + ), + new RewardList( + RewardInterval, + 5, + new[] + { + new RewardEntry(specialDyeTubs, 1049741, typeof(StatuetteDyeTub)), + new RewardEntry(cloaksAndRobes, 1049731, typeof(RewardCloak), JetBlack, 1049763), + new RewardEntry(cloaksAndRobes, 1049732, typeof(RewardRobe), JetBlack, 1049762), + new RewardEntry(cloaksAndRobes, 1080377, typeof(RewardDress), Expansion.ML, JetBlack, 1080377), + new RewardEntry(cloaksAndRobes, 1049733, typeof(RewardCloak), IceWhite, 1049765), + new RewardEntry(cloaksAndRobes, 1049734, typeof(RewardRobe), IceWhite, 1049764), + new RewardEntry(cloaksAndRobes, 1080376, typeof(RewardDress), Expansion.ML, IceWhite, 1080376), + new RewardEntry(cloaksAndRobes, 1049735, typeof(RewardCloak), Fire, 1049767), + new RewardEntry(cloaksAndRobes, 1049736, typeof(RewardRobe), Fire, 1049766), + new RewardEntry(cloaksAndRobes, 1080375, typeof(RewardDress), Expansion.ML, Fire, 1080375), + new RewardEntry(monsterStatues, 1049768, typeof(MonsterStatuette), MonsterStatuetteType.Gazer), + new RewardEntry( + monsterStatues, + 1049769, + typeof(MonsterStatuette), + MonsterStatuetteType.FireElemental + ), + new RewardEntry(monsterStatues, 1049770, typeof(MonsterStatuette), MonsterStatuetteType.Wolf), + new RewardEntry(etherealSteeds, 1049749, typeof(EtherealSwampDragon)), + new RewardEntry(etherealSteeds, 1049748, typeof(EtherealBeetle)), + new RewardEntry(houseAddOns, 1049739, typeof(StoneAnkhDeed)), + new RewardEntry(houseAddOns, 1080384, typeof(BloodyPentagramDeed), Expansion.ML) + } + ), + new RewardList( + RewardInterval, + 6, + new[] + { + new RewardEntry(houseAddOns, 1076188, typeof(CharacterStatueMaker), Expansion.ML, StatueType.Jade), + new RewardEntry(houseAddOns, 1076189, typeof(CharacterStatueMaker), Expansion.ML, StatueType.Marble), + new RewardEntry(houseAddOns, 1076190, typeof(CharacterStatueMaker), Expansion.ML, StatueType.Bronze), + new RewardEntry(houseAddOns, 1080527, typeof(RewardBrazierDeed), Expansion.ML) + } + ), + new RewardList( + RewardInterval, + 7, + new[] + { + new RewardEntry(houseAddOns, 1076157, typeof(CannonDeed), Expansion.ML), + new RewardEntry(houseAddOns, 1080550, typeof(TreeStumpDeed), Expansion.ML) + } + ), + new RewardList( + RewardInterval, + 8, + new[] + { + new RewardEntry(miscellaneous, 1076158, typeof(WeaponEngravingTool), Expansion.ML) + } + ), + new RewardList( + RewardInterval, + 9, + new[] + { + new RewardEntry(etherealSteeds, 1076159, typeof(RideablePolarBear), Expansion.ML), + new RewardEntry(houseAddOns, 1080549, typeof(WallBannerDeed), Expansion.ML) + } + ), + new RewardList( + RewardInterval, + 10, + new[] + { + new RewardEntry( + monsterStatues, + 1080520, + typeof(MonsterStatuette), + Expansion.ML, + MonsterStatuetteType.Harrower + ), + new RewardEntry( + monsterStatues, + 1080521, + typeof(MonsterStatuette), + Expansion.ML, + MonsterStatuetteType.Efreet + ), + + new RewardEntry(cloaksAndRobes, 1080382, typeof(RewardCloak), Expansion.ML, Pink, 1080382), + new RewardEntry(cloaksAndRobes, 1080380, typeof(RewardRobe), Expansion.ML, Pink, 1080380), + new RewardEntry(cloaksAndRobes, 1080378, typeof(RewardDress), Expansion.ML, Pink, 1080378), + new RewardEntry(cloaksAndRobes, 1080383, typeof(RewardCloak), Expansion.ML, Crimson, 1080383), + new RewardEntry(cloaksAndRobes, 1080381, typeof(RewardRobe), Expansion.ML, Crimson, 1080381), + new RewardEntry(cloaksAndRobes, 1080379, typeof(RewardDress), Expansion.ML, Crimson, 1080379), + + new RewardEntry(etherealSteeds, 1080386, typeof(EtherealCuSidhe), Expansion.ML), + + new RewardEntry(houseAddOns, 1080548, typeof(MiningCartDeed), Expansion.ML), + new RewardEntry(houseAddOns, 1080397, typeof(AnkhOfSacrificeDeed), Expansion.ML) + } + ), + + new RewardList( + RewardInterval, + 11, + new[] + { + new RewardEntry(etherealSteeds, 1113908, typeof(EtherealReptalon), Expansion.ML) + } + ), + + new RewardList( + RewardInterval, + 12, + new[] + { + new RewardEntry(etherealSteeds, 1113813, typeof(EtherealHiryu), Expansion.ML) + } + ) + }; + } + + public static void Initialize() + { + Enabled = ServerConfiguration.GetOrUpdateSetting("vetRewards.enable", true); + SkillCapRewards = ServerConfiguration.GetOrUpdateSetting("vetRewards.skillCapRewards", true); + RewardInterval = ServerConfiguration.GetOrUpdateSetting("vetRewards.rewardInterval", TimeSpan.FromDays(30.0)); + + if (Enabled) + EventSink.Login += EventSink_Login; + } + + private static void EventSink_Login(Mobile m) + { + if (!m.Alive) + return; + + ComputeRewardInfo(m, out var cur, out var max, out var level); + + if (m.SkillsCap == 7000 || m.SkillsCap == 7050 || m.SkillsCap == 7100 || + m.SkillsCap == 7150 || m.SkillsCap == 7200) + { + level = Math.Clamp(level, 0, 4); + + if (SkillCapRewards) + m.SkillsCap = 7000 + level * 50; + else + m.SkillsCap = 7000; + } + + if (Core.ML && m is PlayerMobile pm && !pm.HasStatReward && HasHalfLevel(pm)) + { + pm.HasStatReward = true; + pm.StatCap += 5; + } + + if (cur < max) + m.SendGump(new RewardNoticeGump(m)); + } + } + + public interface IRewardItem + { + bool IsRewardItem { get; set; } + } +} diff --git a/Projects/UOContent/Engines/Virtues/Compassion.cs b/Projects/UOContent/Engines/Virtues/Compassion.cs index eba89fd68..394ea0c02 100644 --- a/Projects/UOContent/Engines/Virtues/Compassion.cs +++ b/Projects/UOContent/Engines/Virtues/Compassion.cs @@ -1,41 +1,41 @@ -using System; -using Server.Mobiles; - -namespace Server -{ - public class CompassionVirtue - { - private const int LossAmount = 500; - private static readonly TimeSpan LossDelay = TimeSpan.FromDays(7.0); - - public static void Initialize() - { - VirtueGump.Register(105, OnVirtueUsed); - } - - public static void OnVirtueUsed(Mobile from) - { - from.SendLocalizedMessage(1053001); // This virtue is not activated through the virtue menu. - } - - public static void CheckAtrophy(Mobile from) - { - if (!(from is PlayerMobile pm)) - return; - - try - { - if (pm.LastCompassionLoss + LossDelay < DateTime.UtcNow) - { - VirtueHelper.Atrophy(from, VirtueName.Compassion, LossAmount); - // OSI has no cliloc message for losing compassion. Weird. - pm.LastCompassionLoss = DateTime.UtcNow; - } - } - catch - { - // ignored - } - } - } -} \ No newline at end of file +using System; +using Server.Mobiles; + +namespace Server +{ + public class CompassionVirtue + { + private const int LossAmount = 500; + private static readonly TimeSpan LossDelay = TimeSpan.FromDays(7.0); + + public static void Initialize() + { + VirtueGump.Register(105, OnVirtueUsed); + } + + public static void OnVirtueUsed(Mobile from) + { + from.SendLocalizedMessage(1053001); // This virtue is not activated through the virtue menu. + } + + public static void CheckAtrophy(Mobile from) + { + if (!(from is PlayerMobile pm)) + return; + + try + { + if (pm.LastCompassionLoss + LossDelay < DateTime.UtcNow) + { + VirtueHelper.Atrophy(from, VirtueName.Compassion, LossAmount); + // OSI has no cliloc message for losing compassion. Weird. + pm.LastCompassionLoss = DateTime.UtcNow; + } + } + catch + { + // ignored + } + } + } +} diff --git a/Projects/UOContent/Engines/Virtues/Honor.cs b/Projects/UOContent/Engines/Virtues/Honor.cs index 2ab594fea..93fcee61e 100644 --- a/Projects/UOContent/Engines/Virtues/Honor.cs +++ b/Projects/UOContent/Engines/Virtues/Honor.cs @@ -1,397 +1,404 @@ -using System; -using Server.Gumps; -using Server.Mobiles; -using Server.Regions; -using Server.Targeting; - -namespace Server -{ - public class HonorVirtue - { - private static readonly TimeSpan UseDelay = TimeSpan.FromMinutes(5.0); - - public static void Initialize() - { - VirtueGump.Register(107, OnVirtueUsed); - } - - private static void OnVirtueUsed(Mobile from) - { - if (from.Alive) - { - from.SendLocalizedMessage(1063160); // Target what you wish to honor. - from.Target = new InternalTarget(); - } - } - - private static int GetHonorDuration(PlayerMobile from) - { - return VirtueHelper.GetLevel(from, VirtueName.Honor) switch - { - VirtueLevel.Seeker => 30, - VirtueLevel.Follower => 90, - VirtueLevel.Knight => 300, - _ => 0 - }; - } - - private static void EmbraceHonor(PlayerMobile pm) - { - if (pm.HonorActive) - { - pm.SendLocalizedMessage(1063230); // You must wait awhile before you can embrace honor again. - return; - } - - if (GetHonorDuration(pm) == 0) - { - pm.SendLocalizedMessage(1063234); // You do not have enough honor to do that - return; - } - - TimeSpan waitTime = DateTime.UtcNow - pm.LastHonorUse; - if (waitTime < UseDelay) - { - TimeSpan remainingTime = UseDelay - waitTime; - int remainingMinutes = (int)Math.Ceiling(remainingTime.TotalMinutes); - - pm.SendLocalizedMessage(1063240, - remainingMinutes.ToString()); // You must wait ~1_HONOR_WAIT~ minutes before embracing honor again - return; - } - - pm.SendGump(new HonorSelf(pm)); - } - - public static void ActivateEmbrace(PlayerMobile pm) - { - int duration = GetHonorDuration(pm); - int usedPoints; - - if (pm.Virtues.Honor < 4399) - usedPoints = 400; - else if (pm.Virtues.Honor < 10599) - usedPoints = 600; - else - usedPoints = 1000; - - VirtueHelper.Atrophy(pm, VirtueName.Honor, usedPoints); - - pm.HonorActive = true; - pm.SendLocalizedMessage(1063235); // You embrace your honor - - Timer.DelayCall(TimeSpan.FromSeconds(duration), - () => - { - pm.HonorActive = false; - pm.LastHonorUse = DateTime.UtcNow; - pm.SendLocalizedMessage(1063236); // You no longer embrace your honor - }); - } - - private static void Honor(PlayerMobile source, Mobile target) - { - IHonorTarget honorTarget = target as IHonorTarget; - GuardedRegion reg = source.Region.GetRegion(); - Map map = source.Map; - - if (honorTarget == null) - return; - - if (honorTarget.ReceivedHonorContext != null) - { - if (honorTarget.ReceivedHonorContext.Source == source) - return; - - if (honorTarget.ReceivedHonorContext.CheckDistance()) - { - source.SendLocalizedMessage(1063233); // Somebody else is honoring this opponent - return; - } - } - - if (target.Hits < target.HitsMax) - { - source.SendLocalizedMessage(1063166); // You cannot honor this monster because it is too damaged. - return; - } - - if (target.Body.IsHuman && (!(target is BaseCreature cret) || (!cret.AlwaysAttackable && !cret.AlwaysMurderer))) - { - if (reg?.IsDisabled() != true) - { - // Allow honor on blue if Out of guardzone - } - else if ((map?.Rules & MapRules.HarmfulRestrictions) == 0) - { - // Allow honor on blue if in Fel - } - else - { - source.SendLocalizedMessage(1001018); // You cannot perform negative acts - return; // cannot honor in trammel town on blue - } - } - - if (Core.ML && target is PlayerMobile) - { - source.SendLocalizedMessage(1075614); // You cannot honor other players. - return; - } - - source.SentHonorContext?.Cancel(); - - new HonorContext(source, target); - - source.Direction = source.GetDirectionTo(target); - - if (!source.Mounted) - source.Animate(32, 5, 1, true, true, 0); - } - - private class InternalTarget : Target - { - public InternalTarget() : base(12, false, TargetFlags.None) => CheckLOS = true; - - protected override void OnTarget(Mobile from, object targeted) - { - if (!(from is PlayerMobile pm)) - return; - - if (targeted == pm) - EmbraceHonor(pm); - else if (targeted is Mobile mobile) - Honor(pm, mobile); - } - - protected override void OnTargetOutOfRange(Mobile from, object targeted) - { - from.SendLocalizedMessage(1063232); // You are too far away to honor your opponent - } - } - } - - public interface IHonorTarget - { - HonorContext ReceivedHonorContext { get; set; } - } - - public class HonorContext - { - private FirstHit m_FirstHit; - private double m_HonorDamage; - private readonly Point3D m_InitialLocation; - private readonly Map m_InitialMap; - private bool m_Poisoned; - - private readonly InternalTimer m_Timer; - private int m_TotalDamage; - - public HonorContext(PlayerMobile source, Mobile target) - { - Source = source; - Target = target; - - m_FirstHit = FirstHit.NotDelivered; - m_Poisoned = false; - - m_InitialLocation = source.Location; - m_InitialMap = source.Map; - - source.SentHonorContext = this; - ((IHonorTarget)target).ReceivedHonorContext = this; - - m_Timer = new InternalTimer(this); - m_Timer.Start(); - source.m_hontime = DateTime.UtcNow + TimeSpan.FromMinutes(40); - - Timer.DelayCall(TimeSpan.FromMinutes(40), - () => - { - if (source.m_hontime < DateTime.UtcNow && source.SentHonorContext != null) Cancel(); - }); - } - - public PlayerMobile Source { get; } - - public Mobile Target { get; } - - public int PerfectionDamageBonus { get; private set; } - - public int PerfectionLuckBonus => PerfectionDamageBonus * PerfectionDamageBonus / 10; - - public void OnSourceDamaged(Mobile from, int amount) - { - if (from != Target) - return; - - if (m_FirstHit == FirstHit.NotDelivered) - m_FirstHit = FirstHit.Granted; - } - - public void OnTargetPoisoned() - { - m_Poisoned = true; // Set this flag for OnTargetDamaged which will be called next - } - - public void OnTargetDamaged(Mobile from, int amount) - { - if (m_FirstHit == FirstHit.NotDelivered) - m_FirstHit = FirstHit.Delivered; - - if (m_Poisoned) - { - m_HonorDamage += amount * 0.8; - m_Poisoned = false; // Reset the flag - - return; - } - - m_TotalDamage += amount; - - if (from == Source) - { - if (Target.CanSee(Source) && Target.InLOS(Source) && (Source.InRange(Target, 1) - || (Source.Location == m_InitialLocation && - Source.Map == m_InitialMap))) - m_HonorDamage += amount; - else - m_HonorDamage += amount * 0.8; - } - else if (from is BaseCreature creature && creature.GetMaster() == Source) - { - m_HonorDamage += amount * 0.8; - } - } - - public void OnTargetHit(Mobile from) - { - if (from != Source || PerfectionDamageBonus == 100) - return; - - int bushido = (int)from.Skills.Bushido.Value; - if (bushido < 50) - return; - - PerfectionDamageBonus += bushido / 10; - - if (PerfectionDamageBonus >= 100) - { - PerfectionDamageBonus = 100; - Source.SendLocalizedMessage(1063254); // You have Achieved Perfection in inflicting damage to this opponent! - } - else - { - Source.SendLocalizedMessage(1063255); // You gain in Perfection as you precisely strike your opponent. - } - } - - public void OnTargetMissed(Mobile from) - { - if (from != Source || PerfectionDamageBonus == 0) - return; - - PerfectionDamageBonus -= 25; - - if (PerfectionDamageBonus <= 0) - { - PerfectionDamageBonus = 0; - Source.SendLocalizedMessage(1063256); // You have lost all Perfection in fighting this opponent. - } - else - { - Source.SendLocalizedMessage(1063257); // You have lost some Perfection in fighting this opponent. - } - } - - public void OnSourceBeneficialAction(Mobile to) - { - if (to != Target) - return; - - if (PerfectionDamageBonus >= 0) - { - PerfectionDamageBonus = 0; - Source.SendLocalizedMessage(1063256); // You have lost all Perfection in fighting this opponent. - } - } - - public void OnSourceKilled() - { - } - - public void OnTargetKilled() - { - Cancel(); - - int targetFame = Target.Fame; - - if (PerfectionDamageBonus > 0) - { - int restore = Math.Min(PerfectionDamageBonus * (targetFame + 5000) / 25000, 10); - - Source.Hits += restore; - Source.Stam += restore; - Source.Mana += restore; - } - - if (Source.Virtues.Honor > targetFame) - return; - - double dGain = - targetFame / 100.0 * (m_HonorDamage / m_TotalDamage); // Initial honor gain is 100th of the monsters honor - - if (m_HonorDamage == m_TotalDamage && m_FirstHit == FirstHit.Granted) - dGain *= 1.5; // honor gain is increased alot more if the combat was fully honorable - else - dGain *= 0.9; - - // Minimum gain of 1 honor when the honor is under the monsters fame - int gain = Math.Clamp((int)dGain, 1, 200); - - if (VirtueHelper.IsHighestPath(Source, VirtueName.Honor)) - { - Source.SendLocalizedMessage(1063228); // You cannot gain more Honor. - return; - } - - bool gainedPath = false; - if (VirtueHelper.Award(Source, VirtueName.Honor, gain, ref gainedPath)) - { - if (gainedPath) - Source.SendLocalizedMessage(1063226); // You have gained a path in Honor! - else - Source.SendLocalizedMessage(1063225); // You have gained in Honor. - } - } - - public bool CheckDistance() => true; - - public void Cancel() - { - Source.SentHonorContext = null; - ((IHonorTarget)Target).ReceivedHonorContext = null; - - m_Timer.Stop(); - } - - private enum FirstHit - { - NotDelivered, - Delivered, - Granted - } - - private class InternalTimer : Timer - { - private readonly HonorContext m_Context; - - public InternalTimer(HonorContext context) : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)) => m_Context = context; - - protected override void OnTick() - { - m_Context.CheckDistance(); - } - } - } -} +using System; +using Server.Gumps; +using Server.Mobiles; +using Server.Regions; +using Server.Targeting; + +namespace Server +{ + public class HonorVirtue + { + private static readonly TimeSpan UseDelay = TimeSpan.FromMinutes(5.0); + + public static void Initialize() + { + VirtueGump.Register(107, OnVirtueUsed); + } + + private static void OnVirtueUsed(Mobile from) + { + if (from.Alive) + { + from.SendLocalizedMessage(1063160); // Target what you wish to honor. + from.Target = new InternalTarget(); + } + } + + private static int GetHonorDuration(PlayerMobile from) + { + return VirtueHelper.GetLevel(from, VirtueName.Honor) switch + { + VirtueLevel.Seeker => 30, + VirtueLevel.Follower => 90, + VirtueLevel.Knight => 300, + _ => 0 + }; + } + + private static void EmbraceHonor(PlayerMobile pm) + { + if (pm.HonorActive) + { + pm.SendLocalizedMessage(1063230); // You must wait awhile before you can embrace honor again. + return; + } + + if (GetHonorDuration(pm) == 0) + { + pm.SendLocalizedMessage(1063234); // You do not have enough honor to do that + return; + } + + var waitTime = DateTime.UtcNow - pm.LastHonorUse; + if (waitTime < UseDelay) + { + var remainingTime = UseDelay - waitTime; + var remainingMinutes = (int)Math.Ceiling(remainingTime.TotalMinutes); + + pm.SendLocalizedMessage( + 1063240, + remainingMinutes.ToString() + ); // You must wait ~1_HONOR_WAIT~ minutes before embracing honor again + return; + } + + pm.SendGump(new HonorSelf(pm)); + } + + public static void ActivateEmbrace(PlayerMobile pm) + { + var duration = GetHonorDuration(pm); + int usedPoints; + + if (pm.Virtues.Honor < 4399) + usedPoints = 400; + else if (pm.Virtues.Honor < 10599) + usedPoints = 600; + else + usedPoints = 1000; + + VirtueHelper.Atrophy(pm, VirtueName.Honor, usedPoints); + + pm.HonorActive = true; + pm.SendLocalizedMessage(1063235); // You embrace your honor + + Timer.DelayCall( + TimeSpan.FromSeconds(duration), + () => + { + pm.HonorActive = false; + pm.LastHonorUse = DateTime.UtcNow; + pm.SendLocalizedMessage(1063236); // You no longer embrace your honor + } + ); + } + + private static void Honor(PlayerMobile source, Mobile target) + { + var honorTarget = target as IHonorTarget; + var reg = source.Region.GetRegion(); + var map = source.Map; + + if (honorTarget == null) + return; + + if (honorTarget.ReceivedHonorContext != null) + { + if (honorTarget.ReceivedHonorContext.Source == source) + return; + + if (honorTarget.ReceivedHonorContext.CheckDistance()) + { + source.SendLocalizedMessage(1063233); // Somebody else is honoring this opponent + return; + } + } + + if (target.Hits < target.HitsMax) + { + source.SendLocalizedMessage(1063166); // You cannot honor this monster because it is too damaged. + return; + } + + if (target.Body.IsHuman && (!(target is BaseCreature cret) || !cret.AlwaysAttackable && !cret.AlwaysMurderer)) + { + if (reg?.IsDisabled() != true) + { + // Allow honor on blue if Out of guardzone + } + else if ((map?.Rules & MapRules.HarmfulRestrictions) == 0) + { + // Allow honor on blue if in Fel + } + else + { + source.SendLocalizedMessage(1001018); // You cannot perform negative acts + return; // cannot honor in trammel town on blue + } + } + + if (Core.ML && target is PlayerMobile) + { + source.SendLocalizedMessage(1075614); // You cannot honor other players. + return; + } + + source.SentHonorContext?.Cancel(); + + new HonorContext(source, target); + + source.Direction = source.GetDirectionTo(target); + + if (!source.Mounted) + source.Animate(32, 5, 1, true, true, 0); + } + + private class InternalTarget : Target + { + public InternalTarget() : base(12, false, TargetFlags.None) => CheckLOS = true; + + protected override void OnTarget(Mobile from, object targeted) + { + if (!(from is PlayerMobile pm)) + return; + + if (targeted == pm) + EmbraceHonor(pm); + else if (targeted is Mobile mobile) + Honor(pm, mobile); + } + + protected override void OnTargetOutOfRange(Mobile from, object targeted) + { + from.SendLocalizedMessage(1063232); // You are too far away to honor your opponent + } + } + } + + public interface IHonorTarget + { + HonorContext ReceivedHonorContext { get; set; } + } + + public class HonorContext + { + private readonly Point3D m_InitialLocation; + private readonly Map m_InitialMap; + + private readonly InternalTimer m_Timer; + private FirstHit m_FirstHit; + private double m_HonorDamage; + private bool m_Poisoned; + private int m_TotalDamage; + + public HonorContext(PlayerMobile source, Mobile target) + { + Source = source; + Target = target; + + m_FirstHit = FirstHit.NotDelivered; + m_Poisoned = false; + + m_InitialLocation = source.Location; + m_InitialMap = source.Map; + + source.SentHonorContext = this; + ((IHonorTarget)target).ReceivedHonorContext = this; + + m_Timer = new InternalTimer(this); + m_Timer.Start(); + source.m_hontime = DateTime.UtcNow + TimeSpan.FromMinutes(40); + + Timer.DelayCall( + TimeSpan.FromMinutes(40), + () => + { + if (source.m_hontime < DateTime.UtcNow && source.SentHonorContext != null) Cancel(); + } + ); + } + + public PlayerMobile Source { get; } + + public Mobile Target { get; } + + public int PerfectionDamageBonus { get; private set; } + + public int PerfectionLuckBonus => PerfectionDamageBonus * PerfectionDamageBonus / 10; + + public void OnSourceDamaged(Mobile from, int amount) + { + if (from != Target) + return; + + if (m_FirstHit == FirstHit.NotDelivered) + m_FirstHit = FirstHit.Granted; + } + + public void OnTargetPoisoned() + { + m_Poisoned = true; // Set this flag for OnTargetDamaged which will be called next + } + + public void OnTargetDamaged(Mobile from, int amount) + { + if (m_FirstHit == FirstHit.NotDelivered) + m_FirstHit = FirstHit.Delivered; + + if (m_Poisoned) + { + m_HonorDamage += amount * 0.8; + m_Poisoned = false; // Reset the flag + + return; + } + + m_TotalDamage += amount; + + if (from == Source) + { + if (Target.CanSee(Source) && Target.InLOS(Source) && (Source.InRange(Target, 1) + || Source.Location == m_InitialLocation && + Source.Map == m_InitialMap)) + m_HonorDamage += amount; + else + m_HonorDamage += amount * 0.8; + } + else if (from is BaseCreature creature && creature.GetMaster() == Source) + { + m_HonorDamage += amount * 0.8; + } + } + + public void OnTargetHit(Mobile from) + { + if (from != Source || PerfectionDamageBonus == 100) + return; + + var bushido = (int)from.Skills.Bushido.Value; + if (bushido < 50) + return; + + PerfectionDamageBonus += bushido / 10; + + if (PerfectionDamageBonus >= 100) + { + PerfectionDamageBonus = 100; + Source.SendLocalizedMessage(1063254); // You have Achieved Perfection in inflicting damage to this opponent! + } + else + { + Source.SendLocalizedMessage(1063255); // You gain in Perfection as you precisely strike your opponent. + } + } + + public void OnTargetMissed(Mobile from) + { + if (from != Source || PerfectionDamageBonus == 0) + return; + + PerfectionDamageBonus -= 25; + + if (PerfectionDamageBonus <= 0) + { + PerfectionDamageBonus = 0; + Source.SendLocalizedMessage(1063256); // You have lost all Perfection in fighting this opponent. + } + else + { + Source.SendLocalizedMessage(1063257); // You have lost some Perfection in fighting this opponent. + } + } + + public void OnSourceBeneficialAction(Mobile to) + { + if (to != Target) + return; + + if (PerfectionDamageBonus >= 0) + { + PerfectionDamageBonus = 0; + Source.SendLocalizedMessage(1063256); // You have lost all Perfection in fighting this opponent. + } + } + + public void OnSourceKilled() + { + } + + public void OnTargetKilled() + { + Cancel(); + + var targetFame = Target.Fame; + + if (PerfectionDamageBonus > 0) + { + var restore = Math.Min(PerfectionDamageBonus * (targetFame + 5000) / 25000, 10); + + Source.Hits += restore; + Source.Stam += restore; + Source.Mana += restore; + } + + if (Source.Virtues.Honor > targetFame) + return; + + var dGain = + targetFame / 100.0 * (m_HonorDamage / m_TotalDamage); // Initial honor gain is 100th of the monsters honor + + if (m_HonorDamage == m_TotalDamage && m_FirstHit == FirstHit.Granted) + dGain *= 1.5; // honor gain is increased alot more if the combat was fully honorable + else + dGain *= 0.9; + + // Minimum gain of 1 honor when the honor is under the monsters fame + var gain = Math.Clamp((int)dGain, 1, 200); + + if (VirtueHelper.IsHighestPath(Source, VirtueName.Honor)) + { + Source.SendLocalizedMessage(1063228); // You cannot gain more Honor. + return; + } + + var gainedPath = false; + if (VirtueHelper.Award(Source, VirtueName.Honor, gain, ref gainedPath)) + { + if (gainedPath) + Source.SendLocalizedMessage(1063226); // You have gained a path in Honor! + else + Source.SendLocalizedMessage(1063225); // You have gained in Honor. + } + } + + public bool CheckDistance() => true; + + public void Cancel() + { + Source.SentHonorContext = null; + ((IHonorTarget)Target).ReceivedHonorContext = null; + + m_Timer.Stop(); + } + + private enum FirstHit + { + NotDelivered, + Delivered, + Granted + } + + private class InternalTimer : Timer + { + private readonly HonorContext m_Context; + + public InternalTimer(HonorContext context) : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)) => + m_Context = context; + + protected override void OnTick() + { + m_Context.CheckDistance(); + } + } + } +} diff --git a/Projects/UOContent/Engines/Virtues/Justice.cs b/Projects/UOContent/Engines/Virtues/Justice.cs index 4ea83165a..317a8096f 100644 --- a/Projects/UOContent/Engines/Virtues/Justice.cs +++ b/Projects/UOContent/Engines/Virtues/Justice.cs @@ -1,237 +1,244 @@ -using System; -using Server.Gumps; -using Server.Mobiles; -using Server.Network; -using Server.Targeting; - -namespace Server -{ - public class JusticeVirtue - { - private const int LossAmount = 950; - private static readonly TimeSpan LossDelay = TimeSpan.FromDays(7.0); - - public static void Initialize() - { - VirtueGump.Register(109, OnVirtueUsed); - } - - public static bool CheckMapRegion(Mobile first, Mobile second) - { - Map map = first.Map; - - if (second.Map != map) - return false; - - return GetMapRegion(map, first.Location) == GetMapRegion(map, second.Location); - } - - public static int GetMapRegion(Map map, Point3D loc) - { - if (map == null || map.MapID >= 2) - return 0; - - if (loc.X < 5120) - return 0; - - if (loc.Y < 2304) - return 1; - - return 2; - } - - public static void OnVirtueUsed(Mobile from) - { - if (!from.CheckAlive()) - return; - - if (!(from is PlayerMobile protector)) - return; - - if (!VirtueHelper.IsSeeker(protector, VirtueName.Justice)) - { - protector.SendLocalizedMessage(1049610); // You must reach the first path in this virtue to invoke it. - } - else if (!protector.CanBeginAction()) - { - protector.SendLocalizedMessage(1049370); // You must wait a while before offering your protection again. - } - else if (protector.JusticeProtectors.Count > 0) - { - protector.SendLocalizedMessage(1049542); // You cannot protect someone while being protected. - } - else if (protector.Map != Map.Felucca) - { - protector.SendLocalizedMessage(1049372); // You cannot use this ability here. - } - else - { - protector.BeginTarget(14, false, TargetFlags.None, OnVirtueTargeted); - protector.SendLocalizedMessage(1049366); // Choose the player you wish to protect. - } - } - - public static void OnVirtueTargeted(Mobile from, object obj) - { - PlayerMobile protector = from as PlayerMobile; - PlayerMobile pm = obj as PlayerMobile; - - if (protector == null) - return; - - if (!VirtueHelper.IsSeeker(protector, VirtueName.Justice)) - protector.SendLocalizedMessage(1049610); // You must reach the first path in this virtue to invoke it. - else if (!protector.CanBeginAction()) - protector.SendLocalizedMessage(1049370); // You must wait a while before offering your protection again. - else if (protector.JusticeProtectors.Count > 0) - protector.SendLocalizedMessage(1049542); // You cannot protect someone while being protected. - else if (protector.Map != Map.Felucca) - protector.SendLocalizedMessage(1049372); // You cannot use this ability here. - else if (pm == null) - protector.SendLocalizedMessage(1049678); // Only players can be protected. - else if (pm.Map != Map.Felucca) - protector.SendLocalizedMessage(1049372); // You cannot use this ability here. - else if (pm == protector || pm.Criminal || pm.Kills >= 5) - protector.SendLocalizedMessage(1049436); // That player cannot be protected. - else if (pm.JusticeProtectors.Count > 0) - protector.SendLocalizedMessage(1049369); // You cannot protect that player right now. - else if (pm.HasGump()) - protector.SendLocalizedMessage(1049369); // You cannot protect that player right now. - else - pm.SendGump(new AcceptProtectorGump(protector, pm)); - } - - public static void OnVirtueAccepted(PlayerMobile protector, PlayerMobile protectee) - { - if (!VirtueHelper.IsSeeker(protector, VirtueName.Justice)) - { - protector.SendLocalizedMessage(1049610); // You must reach the first path in this virtue to invoke it. - } - else if (!protector.CanBeginAction()) - { - protector.SendLocalizedMessage(1049370); // You must wait a while before offering your protection again. - } - else if (protector.JusticeProtectors.Count > 0) - { - protector.SendLocalizedMessage(1049542); // You cannot protect someone while being protected. - } - else if (protector.Map != Map.Felucca) - { - protector.SendLocalizedMessage(1049372); // You cannot use this ability here. - } - else if (protectee.Map != Map.Felucca) - { - protector.SendLocalizedMessage(1049372); // You cannot use this ability here. - } - else if (protectee == protector || protectee.Criminal || protectee.Kills >= 5) - { - protector.SendLocalizedMessage(1049436); // That player cannot be protected. - } - else if (protectee.JusticeProtectors.Count > 0) - { - protector.SendLocalizedMessage(1049369); // You cannot protect that player right now. - } - else - { - protectee.JusticeProtectors.Add(protector); - - string args = $"{protector.Name}\t{protectee.Name}"; - - protectee.SendLocalizedMessage(1049451, args); // You are now being protected by ~1_NAME~. - protector.SendLocalizedMessage(1049452, args); // You are now protecting ~2_NAME~. - } - } - - public static void OnVirtueRejected(PlayerMobile protector, PlayerMobile protectee) - { - string args = $"{protector.Name}\t{protectee.Name}"; - - protectee.SendLocalizedMessage(1049453, args); // You have declined protection from ~1_NAME~. - protector.SendLocalizedMessage(1049454, args); // ~2_NAME~ has declined your protection. - - if (protector.BeginAction()) - Timer.DelayCall(TimeSpan.FromMinutes(15.0), protector.EndAction); - } - - public static void CheckAtrophy(Mobile from) - { - if (!(from is PlayerMobile pm)) - return; - - try - { - if (pm.LastJusticeLoss + LossDelay < DateTime.UtcNow) - { - if (VirtueHelper.Atrophy(from, VirtueName.Justice, LossAmount)) - from.SendLocalizedMessage(1049373); // You have lost some Justice. - - pm.LastJusticeLoss = DateTime.UtcNow; - } - } - catch - { - // ignored - } - } - } - - public class AcceptProtectorGump : Gump - { - private readonly PlayerMobile m_Protectee; - private readonly PlayerMobile m_Protector; - - public AcceptProtectorGump(PlayerMobile protector, PlayerMobile protectee) : base(150, 50) - { - m_Protector = protector; - m_Protectee = protectee; - - Closable = false; - - AddPage(0); - - AddBackground(0, 0, 396, 218, 3600); - - AddImageTiled(15, 15, 365, 190, 2624); - AddAlphaRegion(15, 15, 365, 190); - - AddHtmlLocalized(30, 20, 360, 25, 1049365, 0x7FFF); // Another player is offering you their protection: - AddLabel(90, 55, 1153, protector.Name); - - AddImage(50, 45, 9005); - AddImageTiled(80, 80, 200, 1, 9107); - AddImageTiled(95, 82, 200, 1, 9157); - - AddRadio(30, 110, 9727, 9730, true, 1); - AddHtmlLocalized(65, 115, 300, 25, 1049444, 0x7FFF); // Yes, I would like their protection. - - AddRadio(30, 145, 9727, 9730, false, 0); - AddHtmlLocalized(65, 148, 300, 25, 1049445, 0x7FFF); // No thanks, I can take care of myself. - - AddButton(160, 175, 247, 248, 2); - - AddImage(215, 0, 50581); - - AddImageTiled(15, 14, 365, 1, 9107); - AddImageTiled(380, 14, 1, 190, 9105); - AddImageTiled(15, 205, 365, 1, 9107); - AddImageTiled(15, 14, 1, 190, 9105); - AddImageTiled(0, 0, 395, 1, 9157); - AddImageTiled(394, 0, 1, 217, 9155); - AddImageTiled(0, 216, 395, 1, 9157); - AddImageTiled(0, 0, 1, 217, 9155); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 2) - { - bool okay = info.IsSwitched(1); - - if (okay) - JusticeVirtue.OnVirtueAccepted(m_Protector, m_Protectee); - else - JusticeVirtue.OnVirtueRejected(m_Protector, m_Protectee); - } - } - } -} +using System; +using Server.Gumps; +using Server.Mobiles; +using Server.Network; +using Server.Targeting; + +namespace Server +{ + public class JusticeVirtue + { + private const int LossAmount = 950; + private static readonly TimeSpan LossDelay = TimeSpan.FromDays(7.0); + + public static void Initialize() + { + VirtueGump.Register(109, OnVirtueUsed); + } + + public static bool CheckMapRegion(Mobile first, Mobile second) + { + var map = first.Map; + + if (second.Map != map) + return false; + + return GetMapRegion(map, first.Location) == GetMapRegion(map, second.Location); + } + + public static int GetMapRegion(Map map, Point3D loc) + { + if (map == null || map.MapID >= 2) + return 0; + + if (loc.X < 5120) + return 0; + + if (loc.Y < 2304) + return 1; + + return 2; + } + + public static void OnVirtueUsed(Mobile from) + { + if (!from.CheckAlive()) + return; + + if (!(from is PlayerMobile protector)) + return; + + if (!VirtueHelper.IsSeeker(protector, VirtueName.Justice)) + { + protector.SendLocalizedMessage(1049610); // You must reach the first path in this virtue to invoke it. + } + else if (!protector.CanBeginAction()) + { + protector.SendLocalizedMessage(1049370); // You must wait a while before offering your protection again. + } + else if (protector.JusticeProtectors.Count > 0) + { + protector.SendLocalizedMessage(1049542); // You cannot protect someone while being protected. + } + else if (protector.Map != Map.Felucca) + { + protector.SendLocalizedMessage(1049372); // You cannot use this ability here. + } + else + { + protector.BeginTarget(14, false, TargetFlags.None, OnVirtueTargeted); + protector.SendLocalizedMessage(1049366); // Choose the player you wish to protect. + } + } + + public static void OnVirtueTargeted(Mobile from, object obj) + { + var protector = from as PlayerMobile; + var pm = obj as PlayerMobile; + + if (protector == null) + return; + + if (!VirtueHelper.IsSeeker(protector, VirtueName.Justice)) + protector.SendLocalizedMessage(1049610); // You must reach the first path in this virtue to invoke it. + else if (!protector.CanBeginAction()) + protector.SendLocalizedMessage(1049370); // You must wait a while before offering your protection again. + else if (protector.JusticeProtectors.Count > 0) + protector.SendLocalizedMessage(1049542); // You cannot protect someone while being protected. + else if (protector.Map != Map.Felucca) + protector.SendLocalizedMessage(1049372); // You cannot use this ability here. + else if (pm == null) + protector.SendLocalizedMessage(1049678); // Only players can be protected. + else if (pm.Map != Map.Felucca) + protector.SendLocalizedMessage(1049372); // You cannot use this ability here. + else if (pm == protector || pm.Criminal || pm.Kills >= 5) + protector.SendLocalizedMessage(1049436); // That player cannot be protected. + else if (pm.JusticeProtectors.Count > 0) + protector.SendLocalizedMessage(1049369); // You cannot protect that player right now. + else if (pm.HasGump()) + protector.SendLocalizedMessage(1049369); // You cannot protect that player right now. + else + pm.SendGump(new AcceptProtectorGump(protector, pm)); + } + + public static void OnVirtueAccepted(PlayerMobile protector, PlayerMobile protectee) + { + if (!VirtueHelper.IsSeeker(protector, VirtueName.Justice)) + { + protector.SendLocalizedMessage(1049610); // You must reach the first path in this virtue to invoke it. + } + else if (!protector.CanBeginAction()) + { + protector.SendLocalizedMessage(1049370); // You must wait a while before offering your protection again. + } + else if (protector.JusticeProtectors.Count > 0) + { + protector.SendLocalizedMessage(1049542); // You cannot protect someone while being protected. + } + else if (protector.Map != Map.Felucca) + { + protector.SendLocalizedMessage(1049372); // You cannot use this ability here. + } + else if (protectee.Map != Map.Felucca) + { + protector.SendLocalizedMessage(1049372); // You cannot use this ability here. + } + else if (protectee == protector || protectee.Criminal || protectee.Kills >= 5) + { + protector.SendLocalizedMessage(1049436); // That player cannot be protected. + } + else if (protectee.JusticeProtectors.Count > 0) + { + protector.SendLocalizedMessage(1049369); // You cannot protect that player right now. + } + else + { + protectee.JusticeProtectors.Add(protector); + + var args = $"{protector.Name}\t{protectee.Name}"; + + protectee.SendLocalizedMessage(1049451, args); // You are now being protected by ~1_NAME~. + protector.SendLocalizedMessage(1049452, args); // You are now protecting ~2_NAME~. + } + } + + public static void OnVirtueRejected(PlayerMobile protector, PlayerMobile protectee) + { + var args = $"{protector.Name}\t{protectee.Name}"; + + protectee.SendLocalizedMessage(1049453, args); // You have declined protection from ~1_NAME~. + protector.SendLocalizedMessage(1049454, args); // ~2_NAME~ has declined your protection. + + if (protector.BeginAction()) + Timer.DelayCall(TimeSpan.FromMinutes(15.0), protector.EndAction); + } + + public static void CheckAtrophy(Mobile from) + { + if (!(from is PlayerMobile pm)) + return; + + try + { + if (pm.LastJusticeLoss + LossDelay < DateTime.UtcNow) + { + if (VirtueHelper.Atrophy(from, VirtueName.Justice, LossAmount)) + from.SendLocalizedMessage(1049373); // You have lost some Justice. + + pm.LastJusticeLoss = DateTime.UtcNow; + } + } + catch + { + // ignored + } + } + } + + public class AcceptProtectorGump : Gump + { + private readonly PlayerMobile m_Protectee; + private readonly PlayerMobile m_Protector; + + public AcceptProtectorGump(PlayerMobile protector, PlayerMobile protectee) : base(150, 50) + { + m_Protector = protector; + m_Protectee = protectee; + + Closable = false; + + AddPage(0); + + AddBackground(0, 0, 396, 218, 3600); + + AddImageTiled(15, 15, 365, 190, 2624); + AddAlphaRegion(15, 15, 365, 190); + + AddHtmlLocalized( + 30, + 20, + 360, + 25, + 1049365, + 0x7FFF + ); // Another player is offering you their protection: + AddLabel(90, 55, 1153, protector.Name); + + AddImage(50, 45, 9005); + AddImageTiled(80, 80, 200, 1, 9107); + AddImageTiled(95, 82, 200, 1, 9157); + + AddRadio(30, 110, 9727, 9730, true, 1); + AddHtmlLocalized(65, 115, 300, 25, 1049444, 0x7FFF); // Yes, I would like their protection. + + AddRadio(30, 145, 9727, 9730, false, 0); + AddHtmlLocalized(65, 148, 300, 25, 1049445, 0x7FFF); // No thanks, I can take care of myself. + + AddButton(160, 175, 247, 248, 2); + + AddImage(215, 0, 50581); + + AddImageTiled(15, 14, 365, 1, 9107); + AddImageTiled(380, 14, 1, 190, 9105); + AddImageTiled(15, 205, 365, 1, 9107); + AddImageTiled(15, 14, 1, 190, 9105); + AddImageTiled(0, 0, 395, 1, 9157); + AddImageTiled(394, 0, 1, 217, 9155); + AddImageTiled(0, 216, 395, 1, 9157); + AddImageTiled(0, 0, 1, 217, 9155); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 2) + { + var okay = info.IsSwitched(1); + + if (okay) + JusticeVirtue.OnVirtueAccepted(m_Protector, m_Protectee); + else + JusticeVirtue.OnVirtueRejected(m_Protector, m_Protectee); + } + } + } +} diff --git a/Projects/UOContent/Engines/Virtues/Sacrifice.cs b/Projects/UOContent/Engines/Virtues/Sacrifice.cs index cbafe0ef5..cc40fb19b 100644 --- a/Projects/UOContent/Engines/Virtues/Sacrifice.cs +++ b/Projects/UOContent/Engines/Virtues/Sacrifice.cs @@ -1,189 +1,189 @@ -using System; -using Server.Gumps; -using Server.Mobiles; -using Server.Network; -using Server.Targeting; - -namespace Server -{ - public class SacrificeVirtue - { - private const int LossAmount = 500; - private static readonly TimeSpan GainDelay = TimeSpan.FromDays(1.0); - private static readonly TimeSpan LossDelay = TimeSpan.FromDays(7.0); - - public static void Initialize() - { - VirtueGump.Register(110, OnVirtueUsed); - } - - public static void OnVirtueUsed(Mobile from) - { - if (!from.Hidden) - { - if (from.Alive) - from.Target = new InternalTarget(); - else - Resurrect(from); - } - else - { - from.SendLocalizedMessage(1052015); // You cannot do that while hidden. - } - } - - public static void CheckAtrophy(Mobile from) - { - if (!(from is PlayerMobile pm)) - return; - - try - { - if (pm.LastSacrificeLoss + LossDelay < DateTime.UtcNow) - { - if (VirtueHelper.Atrophy(from, VirtueName.Sacrifice, LossAmount)) - from.SendLocalizedMessage(1052041); // You have lost some Sacrifice. - - VirtueLevel level = VirtueHelper.GetLevel(from, VirtueName.Sacrifice); - - pm.AvailableResurrects = (int)level; - pm.LastSacrificeLoss = DateTime.UtcNow; - } - } - catch - { - // ignored - } - } - - public static void Resurrect(Mobile from) - { - if (from.Alive) - return; - - if (!(from is PlayerMobile pm)) - return; - - if (from.Criminal) - { - from.SendLocalizedMessage(1052007); // You cannot use this ability while flagged as a criminal. - } - else if (!VirtueHelper.IsSeeker(from, VirtueName.Sacrifice)) - { - from.SendLocalizedMessage(1052004); // You cannot use this ability. - } - else if (pm.AvailableResurrects <= 0) - { - from.SendLocalizedMessage(1052005); // You do not have any resurrections left. - } - else - { - /* - * We need to wait for them to accept the gump or they can just use - * Sacrifice and cancel to have items in their backpack for free. - */ - from.CloseGump(); - from.SendGump(new ResurrectGump(from, true)); - } - } - - public static void Sacrifice(Mobile from, object targeted) - { - if (!from.CheckAlive()) - return; - - if (!(from is PlayerMobile pm)) - return; - - if (!(targeted is Mobile targ)) - return; - - if (!ValidateCreature(targ)) - { - from.SendLocalizedMessage(1052014); // You cannot sacrifice your fame for that creature. - } - else if (targ.Hits * 100 / Math.Max(targ.HitsMax, 1) < 90) - { - from.SendLocalizedMessage(1052013); // You cannot sacrifice for this monster because it is too damaged. - } - else if (from.Hidden) - { - from.SendLocalizedMessage(1052015); // You cannot do that while hidden. - } - else if (VirtueHelper.IsHighestPath(from, VirtueName.Sacrifice)) - { - from.SendLocalizedMessage(1052068); // You have already attained the highest path in this virtue. - } - else if (from.Fame < 2500) - { - from.SendLocalizedMessage(1052017); // You do not have enough fame to sacrifice. - } - else if (DateTime.UtcNow < pm.LastSacrificeGain + GainDelay) - { - from.SendLocalizedMessage(1052016); // You must wait approximately one day before sacrificing again. - } - else - { - int toGain; - - if (from.Fame < 5000) - toGain = 500; - else if (from.Fame < 10000) - toGain = 1000; - else - toGain = 2000; - - from.Fame = 0; - - // I have seen the error of my ways! - targ.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1052009); - - from.SendLocalizedMessage(1052010); // You have set the creature free. - - Timer.DelayCall(TimeSpan.FromSeconds(1.0), targ.Delete); - - pm.LastSacrificeGain = DateTime.UtcNow; - - bool gainedPath = false; - - if (VirtueHelper.Award(from, VirtueName.Sacrifice, toGain, ref gainedPath)) - { - if (gainedPath) - { - from.SendLocalizedMessage(1052008); // You have gained a path in Sacrifice! - - if (pm.AvailableResurrects < 3) - ++pm.AvailableResurrects; - } - else - { - from.SendLocalizedMessage(1054160); // You have gained in sacrifice. - } - } - - from.SendLocalizedMessage(1052016); // You must wait approximately one day before sacrificing again. - } - } - - public static bool ValidateCreature(Mobile m) - { - if (m is BaseCreature creature && (creature.Controlled || creature.Summoned)) - return false; - - return m is Lich || m is Succubus || m is Daemon || m is EvilMage || m is EnslavedGargoyle || - m is GargoyleEnforcer; - } - - private class InternalTarget : Target - { - public InternalTarget() : base(8, false, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object targeted) - { - Sacrifice(from, targeted); - } - } - } -} \ No newline at end of file +using System; +using Server.Gumps; +using Server.Mobiles; +using Server.Network; +using Server.Targeting; + +namespace Server +{ + public class SacrificeVirtue + { + private const int LossAmount = 500; + private static readonly TimeSpan GainDelay = TimeSpan.FromDays(1.0); + private static readonly TimeSpan LossDelay = TimeSpan.FromDays(7.0); + + public static void Initialize() + { + VirtueGump.Register(110, OnVirtueUsed); + } + + public static void OnVirtueUsed(Mobile from) + { + if (!from.Hidden) + { + if (from.Alive) + from.Target = new InternalTarget(); + else + Resurrect(from); + } + else + { + from.SendLocalizedMessage(1052015); // You cannot do that while hidden. + } + } + + public static void CheckAtrophy(Mobile from) + { + if (!(from is PlayerMobile pm)) + return; + + try + { + if (pm.LastSacrificeLoss + LossDelay < DateTime.UtcNow) + { + if (VirtueHelper.Atrophy(from, VirtueName.Sacrifice, LossAmount)) + from.SendLocalizedMessage(1052041); // You have lost some Sacrifice. + + var level = VirtueHelper.GetLevel(from, VirtueName.Sacrifice); + + pm.AvailableResurrects = (int)level; + pm.LastSacrificeLoss = DateTime.UtcNow; + } + } + catch + { + // ignored + } + } + + public static void Resurrect(Mobile from) + { + if (from.Alive) + return; + + if (!(from is PlayerMobile pm)) + return; + + if (from.Criminal) + { + from.SendLocalizedMessage(1052007); // You cannot use this ability while flagged as a criminal. + } + else if (!VirtueHelper.IsSeeker(from, VirtueName.Sacrifice)) + { + from.SendLocalizedMessage(1052004); // You cannot use this ability. + } + else if (pm.AvailableResurrects <= 0) + { + from.SendLocalizedMessage(1052005); // You do not have any resurrections left. + } + else + { + /* + * We need to wait for them to accept the gump or they can just use + * Sacrifice and cancel to have items in their backpack for free. + */ + from.CloseGump(); + from.SendGump(new ResurrectGump(from, true)); + } + } + + public static void Sacrifice(Mobile from, object targeted) + { + if (!from.CheckAlive()) + return; + + if (!(from is PlayerMobile pm)) + return; + + if (!(targeted is Mobile targ)) + return; + + if (!ValidateCreature(targ)) + { + from.SendLocalizedMessage(1052014); // You cannot sacrifice your fame for that creature. + } + else if (targ.Hits * 100 / Math.Max(targ.HitsMax, 1) < 90) + { + from.SendLocalizedMessage(1052013); // You cannot sacrifice for this monster because it is too damaged. + } + else if (from.Hidden) + { + from.SendLocalizedMessage(1052015); // You cannot do that while hidden. + } + else if (VirtueHelper.IsHighestPath(from, VirtueName.Sacrifice)) + { + from.SendLocalizedMessage(1052068); // You have already attained the highest path in this virtue. + } + else if (from.Fame < 2500) + { + from.SendLocalizedMessage(1052017); // You do not have enough fame to sacrifice. + } + else if (DateTime.UtcNow < pm.LastSacrificeGain + GainDelay) + { + from.SendLocalizedMessage(1052016); // You must wait approximately one day before sacrificing again. + } + else + { + int toGain; + + if (from.Fame < 5000) + toGain = 500; + else if (from.Fame < 10000) + toGain = 1000; + else + toGain = 2000; + + from.Fame = 0; + + // I have seen the error of my ways! + targ.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1052009); + + from.SendLocalizedMessage(1052010); // You have set the creature free. + + Timer.DelayCall(TimeSpan.FromSeconds(1.0), targ.Delete); + + pm.LastSacrificeGain = DateTime.UtcNow; + + var gainedPath = false; + + if (VirtueHelper.Award(from, VirtueName.Sacrifice, toGain, ref gainedPath)) + { + if (gainedPath) + { + from.SendLocalizedMessage(1052008); // You have gained a path in Sacrifice! + + if (pm.AvailableResurrects < 3) + ++pm.AvailableResurrects; + } + else + { + from.SendLocalizedMessage(1054160); // You have gained in sacrifice. + } + } + + from.SendLocalizedMessage(1052016); // You must wait approximately one day before sacrificing again. + } + } + + public static bool ValidateCreature(Mobile m) + { + if (m is BaseCreature creature && (creature.Controlled || creature.Summoned)) + return false; + + return m is Lich || m is Succubus || m is Daemon || m is EvilMage || m is EnslavedGargoyle || + m is GargoyleEnforcer; + } + + private class InternalTarget : Target + { + public InternalTarget() : base(8, false, TargetFlags.None) + { + } + + protected override void OnTarget(Mobile from, object targeted) + { + Sacrifice(from, targeted); + } + } + } +} diff --git a/Projects/UOContent/Engines/Virtues/Valor.cs b/Projects/UOContent/Engines/Virtues/Valor.cs index a9f0146e0..098d13b51 100644 --- a/Projects/UOContent/Engines/Virtues/Valor.cs +++ b/Projects/UOContent/Engines/Virtues/Valor.cs @@ -1,142 +1,146 @@ -using System; -using Server.Engines.CannedEvil; -using Server.Mobiles; -using Server.Targeting; - -namespace Server -{ - public class ValorVirtue - { - private const int LossAmount = 250; - private static readonly TimeSpan LossDelay = TimeSpan.FromDays(7.0); - - public static void Initialize() - { - VirtueGump.Register(112, OnVirtueUsed); - } - - public static void OnVirtueUsed(Mobile from) - { - if (from.Alive) - { - from.SendLocalizedMessage(1054034); // Target the Champion Idol of the Champion you wish to challenge!. - from.Target = new InternalTarget(); - } - } - - public static void CheckAtrophy(Mobile from) - { - if (!(from is PlayerMobile pm)) - return; - - try - { - if (pm.LastValorLoss + LossDelay < DateTime.UtcNow) - { - if (VirtueHelper.Atrophy(from, VirtueName.Valor, LossAmount)) - from.SendLocalizedMessage(1054040); // You have lost some Valor. - - pm.LastValorLoss = DateTime.UtcNow; - } - } - catch - { - // ignored - } - } - - public static void Valor(Mobile from, object targ) - { - if (!(targ is IdolOfTheChampion idol) || idol.Deleted || idol.Spawn?.Deleted != false) - { - from.SendLocalizedMessage(1054035); // You must target a Champion Idol to challenge the Champion's spawn! - } - else if (from.Hidden) - { - from.SendLocalizedMessage(1052015); // You cannot do that while hidden. - } - else if (idol.Spawn.HasBeenAdvanced) - { - from.SendLocalizedMessage(1054038); // The Champion of this region has already been challenged! - } - else - { - VirtueLevel vl = VirtueHelper.GetLevel(from, VirtueName.Valor); - if (idol.Spawn.Active) - { - if (idol.Spawn.Champion != null) // TODO: Message? - return; - - int needed, consumed; - switch (idol.Spawn.GetSubLevel()) - { - case 0: - { - needed = consumed = 2500; - break; - } - case 1: - { - needed = consumed = 5000; - break; - } - case 2: - { - needed = 10000; - consumed = 7500; - break; - } - default: - { - needed = 20000; - consumed = 10000; - break; - } - } - - if (from.Virtues.GetValue((int)VirtueName.Valor) >= needed) - { - VirtueHelper.Atrophy(from, VirtueName.Valor, consumed); - from.SendLocalizedMessage( - 1054037); // Your challenge is heard by the Champion of this region! Beware its wrath! - idol.Spawn.HasBeenAdvanced = true; - idol.Spawn.AdvanceLevel(); - } - else - { - from.SendLocalizedMessage( - 1054039); // The Champion of this region ignores your challenge. You must further prove your valor. - } - } - else - { - if (vl == VirtueLevel.Knight) - { - VirtueHelper.Atrophy(from, VirtueName.Valor, 11000); - from.SendLocalizedMessage( - 1054037); // Your challenge is heard by the Champion of this region! Beware its wrath! - idol.Spawn.EndRestart(); - idol.Spawn.HasBeenAdvanced = true; - } - else - { - from.SendLocalizedMessage( - 1054036); // You must be a Knight of Valor to summon the champion's spawn in this manner! - } - } - } - } - - private class InternalTarget : Target - { - public InternalTarget() : base(14, false, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object targeted) - { - Valor(from, targeted); - } - } - } -} +using System; +using Server.Engines.CannedEvil; +using Server.Mobiles; +using Server.Targeting; + +namespace Server +{ + public class ValorVirtue + { + private const int LossAmount = 250; + private static readonly TimeSpan LossDelay = TimeSpan.FromDays(7.0); + + public static void Initialize() + { + VirtueGump.Register(112, OnVirtueUsed); + } + + public static void OnVirtueUsed(Mobile from) + { + if (from.Alive) + { + from.SendLocalizedMessage(1054034); // Target the Champion Idol of the Champion you wish to challenge!. + from.Target = new InternalTarget(); + } + } + + public static void CheckAtrophy(Mobile from) + { + if (!(from is PlayerMobile pm)) + return; + + try + { + if (pm.LastValorLoss + LossDelay < DateTime.UtcNow) + { + if (VirtueHelper.Atrophy(from, VirtueName.Valor, LossAmount)) + from.SendLocalizedMessage(1054040); // You have lost some Valor. + + pm.LastValorLoss = DateTime.UtcNow; + } + } + catch + { + // ignored + } + } + + public static void Valor(Mobile from, object targ) + { + if (!(targ is IdolOfTheChampion idol) || idol.Deleted || idol.Spawn?.Deleted != false) + { + from.SendLocalizedMessage(1054035); // You must target a Champion Idol to challenge the Champion's spawn! + } + else if (from.Hidden) + { + from.SendLocalizedMessage(1052015); // You cannot do that while hidden. + } + else if (idol.Spawn.HasBeenAdvanced) + { + from.SendLocalizedMessage(1054038); // The Champion of this region has already been challenged! + } + else + { + var vl = VirtueHelper.GetLevel(from, VirtueName.Valor); + if (idol.Spawn.Active) + { + if (idol.Spawn.Champion != null) // TODO: Message? + return; + + int needed, consumed; + switch (idol.Spawn.GetSubLevel()) + { + case 0: + { + needed = consumed = 2500; + break; + } + case 1: + { + needed = consumed = 5000; + break; + } + case 2: + { + needed = 10000; + consumed = 7500; + break; + } + default: + { + needed = 20000; + consumed = 10000; + break; + } + } + + if (from.Virtues.GetValue((int)VirtueName.Valor) >= needed) + { + VirtueHelper.Atrophy(from, VirtueName.Valor, consumed); + from.SendLocalizedMessage( + 1054037 + ); // Your challenge is heard by the Champion of this region! Beware its wrath! + idol.Spawn.HasBeenAdvanced = true; + idol.Spawn.AdvanceLevel(); + } + else + { + from.SendLocalizedMessage( + 1054039 + ); // The Champion of this region ignores your challenge. You must further prove your valor. + } + } + else + { + if (vl == VirtueLevel.Knight) + { + VirtueHelper.Atrophy(from, VirtueName.Valor, 11000); + from.SendLocalizedMessage( + 1054037 + ); // Your challenge is heard by the Champion of this region! Beware its wrath! + idol.Spawn.EndRestart(); + idol.Spawn.HasBeenAdvanced = true; + } + else + { + from.SendLocalizedMessage( + 1054036 + ); // You must be a Knight of Valor to summon the champion's spawn in this manner! + } + } + } + } + + private class InternalTarget : Target + { + public InternalTarget() : base(14, false, TargetFlags.None) + { + } + + protected override void OnTarget(Mobile from, object targeted) + { + Valor(from, targeted); + } + } + } +} diff --git a/Projects/UOContent/Engines/Virtues/VirtueGump.cs b/Projects/UOContent/Engines/Virtues/VirtueGump.cs index 06cbc19fc..bb8ab0b29 100644 --- a/Projects/UOContent/Engines/Virtues/VirtueGump.cs +++ b/Projects/UOContent/Engines/Virtues/VirtueGump.cs @@ -1,166 +1,168 @@ -using System.Collections.Generic; -using Server.Gumps; -using Server.Network; - -namespace Server -{ - public delegate void OnVirtueUsed(Mobile from); - - public class VirtueGump : Gump - { - private static readonly Dictionary m_Callbacks = new Dictionary(); - - private static readonly int[] m_Table = { - 0x0481, 0x0963, 0x0965, - 0x060A, 0x060F, 0x002A, - 0x08A4, 0x08A7, 0x0034, - 0x0965, 0x08FD, 0x0480, - 0x00EA, 0x0845, 0x0020, - 0x0011, 0x0269, 0x013D, - 0x08A1, 0x08A3, 0x0042, - 0x0543, 0x0547, 0x0061 - }; - - private readonly Mobile m_Beholder; - private readonly Mobile m_Beheld; - - public VirtueGump(Mobile beholder, Mobile beheld) : base(0, 0) - { - m_Beholder = beholder; - m_Beheld = beheld; - - Serial = beheld.Serial; - - AddPage(0); - - AddImage(30, 40, 104); - - AddPage(1); - - Add(new InternalEntry(61, 71, 108, GetHueFor(0))); // Humility - Add(new InternalEntry(123, 46, 112, GetHueFor(4))); // Valor - Add(new InternalEntry(187, 70, 107, GetHueFor(5))); // Honor - Add(new InternalEntry(35, 135, 110, GetHueFor(1))); // Sacrifice - Add(new InternalEntry(211, 133, 105, GetHueFor(2))); // Compassion - Add(new InternalEntry(61, 195, 111, GetHueFor(3))); // Spiritulaity - Add(new InternalEntry(186, 195, 109, GetHueFor(6))); // Justice - Add(new InternalEntry(121, 221, 106, GetHueFor(7))); // Honesty - - if (m_Beholder == m_Beheld) - { - AddButton(57, 269, 2027, 2027, 1); - AddButton(186, 269, 2071, 2071, 2); - } - } - - public static void Initialize() - { - EventSink.VirtueGumpRequest += EventSink_VirtueGumpRequest; - EventSink.VirtueItemRequest += EventSink_VirtueItemRequest; - EventSink.VirtueMacroRequest += EventSink_VirtueMacroRequest; - } - - public static void Register(int gumpID, OnVirtueUsed callback) - { - m_Callbacks[gumpID] = callback; - } - - private static void EventSink_VirtueItemRequest(Mobile beholder, Mobile beheld, int gumpID) - { - if (beholder != beheld) - return; - - beholder.CloseGump(); - - if (beholder.Kills >= 5) - { - beholder.SendLocalizedMessage(1049609); // Murderers cannot invoke this virtue. - return; - } - - if (m_Callbacks.TryGetValue(gumpID, out OnVirtueUsed callback)) - callback(beholder); - else - beholder.SendLocalizedMessage(1052066); // That virtue is not active yet. - } - - private static void EventSink_VirtueMacroRequest(Mobile beholder, int virtue) - { - var virtueID = virtue switch - { - 0 => 107, // Honor - 1 => 110, // Sacrifice - 2 => 112, // Valor; - _ => 0 - }; - - EventSink_VirtueItemRequest(beholder, beholder, virtueID); - } - - private static void EventSink_VirtueGumpRequest(Mobile beholder, Mobile beheld) - { - if (beholder == beheld && beholder.Kills >= 5) - { - beholder.SendLocalizedMessage(1049609); // Murderers cannot invoke this virtue. - } - else if (beholder.Map == beheld.Map && beholder.InRange(beheld, 12)) - { - beholder.CloseGump(); - beholder.SendGump(new VirtueGump(beholder, beheld)); - } - } - - private int GetHueFor(int index) - { - if (m_Beheld.Virtues.GetValue(index) == 0) - return 2402; - - int value = m_Beheld.Virtues.GetValue(index); - - if (value < 4000) - return 2402; - - if (value >= 30000) - value = 20000; // Sanity - - int vl; - - if (value < 10000) - vl = 0; - else if (value >= 20000 && index == 5) - vl = 2; - else if (value >= 21000 && index != 1) - vl = 2; - else if (value >= 22000 && index == 1) - vl = 2; - else - vl = 1; - - return m_Table[index * 3 + vl]; - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (info.ButtonID == 1 && m_Beholder == m_Beheld) - m_Beholder.SendGump(new VirtueStatusGump(m_Beholder)); - } - - private class InternalEntry : GumpImage - { - private static readonly byte[] m_Class = StringToBuffer(" class=VirtueGumpItem"); - - public InternalEntry(int x, int y, int gumpID, int hue) : base(x, y, gumpID, hue) - { - } - - public override string Compile(NetState ns) => $"{{ gumppic {X} {Y} {GumpID} hue={Hue} class=VirtueGumpItem }}"; - - public override void AppendTo(NetState ns, IGumpWriter disp) - { - base.AppendTo(ns, disp); - - disp.AppendLayout(m_Class); - } - } - } -} +using System.Collections.Generic; +using Server.Gumps; +using Server.Network; + +namespace Server +{ + public delegate void OnVirtueUsed(Mobile from); + + public class VirtueGump : Gump + { + private static readonly Dictionary m_Callbacks = new Dictionary(); + + private static readonly int[] m_Table = + { + 0x0481, 0x0963, 0x0965, + 0x060A, 0x060F, 0x002A, + 0x08A4, 0x08A7, 0x0034, + 0x0965, 0x08FD, 0x0480, + 0x00EA, 0x0845, 0x0020, + 0x0011, 0x0269, 0x013D, + 0x08A1, 0x08A3, 0x0042, + 0x0543, 0x0547, 0x0061 + }; + + private readonly Mobile m_Beheld; + + private readonly Mobile m_Beholder; + + public VirtueGump(Mobile beholder, Mobile beheld) : base(0, 0) + { + m_Beholder = beholder; + m_Beheld = beheld; + + Serial = beheld.Serial; + + AddPage(0); + + AddImage(30, 40, 104); + + AddPage(1); + + Add(new InternalEntry(61, 71, 108, GetHueFor(0))); // Humility + Add(new InternalEntry(123, 46, 112, GetHueFor(4))); // Valor + Add(new InternalEntry(187, 70, 107, GetHueFor(5))); // Honor + Add(new InternalEntry(35, 135, 110, GetHueFor(1))); // Sacrifice + Add(new InternalEntry(211, 133, 105, GetHueFor(2))); // Compassion + Add(new InternalEntry(61, 195, 111, GetHueFor(3))); // Spiritulaity + Add(new InternalEntry(186, 195, 109, GetHueFor(6))); // Justice + Add(new InternalEntry(121, 221, 106, GetHueFor(7))); // Honesty + + if (m_Beholder == m_Beheld) + { + AddButton(57, 269, 2027, 2027, 1); + AddButton(186, 269, 2071, 2071, 2); + } + } + + public static void Initialize() + { + EventSink.VirtueGumpRequest += EventSink_VirtueGumpRequest; + EventSink.VirtueItemRequest += EventSink_VirtueItemRequest; + EventSink.VirtueMacroRequest += EventSink_VirtueMacroRequest; + } + + public static void Register(int gumpID, OnVirtueUsed callback) + { + m_Callbacks[gumpID] = callback; + } + + private static void EventSink_VirtueItemRequest(Mobile beholder, Mobile beheld, int gumpID) + { + if (beholder != beheld) + return; + + beholder.CloseGump(); + + if (beholder.Kills >= 5) + { + beholder.SendLocalizedMessage(1049609); // Murderers cannot invoke this virtue. + return; + } + + if (m_Callbacks.TryGetValue(gumpID, out var callback)) + callback(beholder); + else + beholder.SendLocalizedMessage(1052066); // That virtue is not active yet. + } + + private static void EventSink_VirtueMacroRequest(Mobile beholder, int virtue) + { + var virtueID = virtue switch + { + 0 => 107, // Honor + 1 => 110, // Sacrifice + 2 => 112, // Valor; + _ => 0 + }; + + EventSink_VirtueItemRequest(beholder, beholder, virtueID); + } + + private static void EventSink_VirtueGumpRequest(Mobile beholder, Mobile beheld) + { + if (beholder == beheld && beholder.Kills >= 5) + { + beholder.SendLocalizedMessage(1049609); // Murderers cannot invoke this virtue. + } + else if (beholder.Map == beheld.Map && beholder.InRange(beheld, 12)) + { + beholder.CloseGump(); + beholder.SendGump(new VirtueGump(beholder, beheld)); + } + } + + private int GetHueFor(int index) + { + if (m_Beheld.Virtues.GetValue(index) == 0) + return 2402; + + var value = m_Beheld.Virtues.GetValue(index); + + if (value < 4000) + return 2402; + + if (value >= 30000) + value = 20000; // Sanity + + int vl; + + if (value < 10000) + vl = 0; + else if (value >= 20000 && index == 5) + vl = 2; + else if (value >= 21000 && index != 1) + vl = 2; + else if (value >= 22000 && index == 1) + vl = 2; + else + vl = 1; + + return m_Table[index * 3 + vl]; + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (info.ButtonID == 1 && m_Beholder == m_Beheld) + m_Beholder.SendGump(new VirtueStatusGump(m_Beholder)); + } + + private class InternalEntry : GumpImage + { + private static readonly byte[] m_Class = StringToBuffer(" class=VirtueGumpItem"); + + public InternalEntry(int x, int y, int gumpID, int hue) : base(x, y, gumpID, hue) + { + } + + public override string Compile(NetState ns) => $"{{ gumppic {X} {Y} {GumpID} hue={Hue} class=VirtueGumpItem }}"; + + public override void AppendTo(NetState ns, IGumpWriter disp) + { + base.AppendTo(ns, disp); + + disp.AppendLayout(m_Class); + } + } + } +} diff --git a/Projects/UOContent/Engines/Virtues/VirtueHelper.cs b/Projects/UOContent/Engines/Virtues/VirtueHelper.cs index 1f218eead..40450e172 100644 --- a/Projects/UOContent/Engines/Virtues/VirtueHelper.cs +++ b/Projects/UOContent/Engines/Virtues/VirtueHelper.cs @@ -1,141 +1,143 @@ -using System; -using Server.Mobiles; - -namespace Server -{ - public enum VirtueLevel - { - None, - Seeker, - Follower, - Knight - } - - public enum VirtueName - { - Humility, - Sacrifice, - Compassion, - Spirituality, - Valor, - Honor, - Justice, - Honesty - } - - public class VirtueHelper - { - public static bool HasAny(Mobile from, VirtueName virtue) => from.Virtues.GetValue((int)virtue) > 0; - - public static bool IsHighestPath(Mobile from, VirtueName virtue) => from.Virtues.GetValue((int)virtue) >= GetMaxAmount(virtue); - - public static VirtueLevel GetLevel(Mobile from, VirtueName virtue) - { - int v = from.Virtues.GetValue((int)virtue); - int vl; - - if (v < 4000) - vl = 0; - else if (v >= GetMaxAmount(virtue)) - vl = 3; - else - vl = (v + 9999) / 10000; - - return (VirtueLevel)vl; - } - - public static int GetMaxAmount(VirtueName virtue) => - virtue switch - { - VirtueName.Honor => 20000, - VirtueName.Sacrifice => 22000, - _ => 21000 - }; - - public static bool Award(Mobile from, VirtueName virtue, int amount, ref bool gainedPath) - { - int current = from.Virtues.GetValue((int)virtue); - - int maxAmount = GetMaxAmount(virtue); - - if (current >= maxAmount) - return false; - - if (current + amount >= maxAmount) - amount = maxAmount - current; - - VirtueLevel oldLevel = GetLevel(from, virtue); - - from.Virtues.SetValue((int)virtue, current + amount); - - gainedPath = GetLevel(from, virtue) != oldLevel; - - return true; - } - - public static bool Atrophy(Mobile from, VirtueName virtue) => Atrophy(from, virtue, 1); - - public static bool Atrophy(Mobile from, VirtueName virtue, int amount) - { - int current = from.Virtues.GetValue((int)virtue); - - if (current - amount >= 0) - from.Virtues.SetValue((int)virtue, current - amount); - else - from.Virtues.SetValue((int)virtue, 0); - - return current > 0; - } - - public static bool IsSeeker(Mobile from, VirtueName virtue) => GetLevel(from, virtue) >= VirtueLevel.Seeker; - - public static bool IsFollower(Mobile from, VirtueName virtue) => GetLevel(from, virtue) >= VirtueLevel.Follower; - - public static bool IsKnight(Mobile from, VirtueName virtue) => GetLevel(from, virtue) >= VirtueLevel.Knight; - - public static void AwardVirtue(PlayerMobile pm, VirtueName virtue, int amount) - { - if (virtue == VirtueName.Compassion) - { - if (pm.CompassionGains > 0 && DateTime.UtcNow > pm.NextCompassionDay) - { - pm.NextCompassionDay = DateTime.MinValue; - pm.CompassionGains = 0; - } - - if (pm.CompassionGains >= 5) - { - pm.SendLocalizedMessage(1053004); // You must wait about a day before you can gain in compassion again. - return; - } - } - - bool gainedPath = false; - string virtueName = Enum.GetName(typeof(VirtueName), virtue); - - if (Award(pm, virtue, amount, ref gainedPath)) - { - // TODO: Localize? - if (gainedPath) - pm.SendMessage("You have gained a path in {0}!", virtueName); - else - pm.SendMessage("You have gained in {0}.", virtueName); - - if (virtue == VirtueName.Compassion) - { - pm.NextCompassionDay = DateTime.UtcNow + TimeSpan.FromDays(1.0); - ++pm.CompassionGains; - - if (pm.CompassionGains >= 5) - pm.SendLocalizedMessage( - 1053004); // You must wait about a day before you can gain in compassion again. - } - } - else - { - // TODO: Localize? - pm.SendMessage("You have achieved the highest path of {0} and can no longer gain any further.", virtueName); - } - } - } -} +using System; +using Server.Mobiles; + +namespace Server +{ + public enum VirtueLevel + { + None, + Seeker, + Follower, + Knight + } + + public enum VirtueName + { + Humility, + Sacrifice, + Compassion, + Spirituality, + Valor, + Honor, + Justice, + Honesty + } + + public class VirtueHelper + { + public static bool HasAny(Mobile from, VirtueName virtue) => from.Virtues.GetValue((int)virtue) > 0; + + public static bool IsHighestPath(Mobile from, VirtueName virtue) => + from.Virtues.GetValue((int)virtue) >= GetMaxAmount(virtue); + + public static VirtueLevel GetLevel(Mobile from, VirtueName virtue) + { + var v = from.Virtues.GetValue((int)virtue); + int vl; + + if (v < 4000) + vl = 0; + else if (v >= GetMaxAmount(virtue)) + vl = 3; + else + vl = (v + 9999) / 10000; + + return (VirtueLevel)vl; + } + + public static int GetMaxAmount(VirtueName virtue) => + virtue switch + { + VirtueName.Honor => 20000, + VirtueName.Sacrifice => 22000, + _ => 21000 + }; + + public static bool Award(Mobile from, VirtueName virtue, int amount, ref bool gainedPath) + { + var current = from.Virtues.GetValue((int)virtue); + + var maxAmount = GetMaxAmount(virtue); + + if (current >= maxAmount) + return false; + + if (current + amount >= maxAmount) + amount = maxAmount - current; + + var oldLevel = GetLevel(from, virtue); + + from.Virtues.SetValue((int)virtue, current + amount); + + gainedPath = GetLevel(from, virtue) != oldLevel; + + return true; + } + + public static bool Atrophy(Mobile from, VirtueName virtue) => Atrophy(from, virtue, 1); + + public static bool Atrophy(Mobile from, VirtueName virtue, int amount) + { + var current = from.Virtues.GetValue((int)virtue); + + if (current - amount >= 0) + from.Virtues.SetValue((int)virtue, current - amount); + else + from.Virtues.SetValue((int)virtue, 0); + + return current > 0; + } + + public static bool IsSeeker(Mobile from, VirtueName virtue) => GetLevel(from, virtue) >= VirtueLevel.Seeker; + + public static bool IsFollower(Mobile from, VirtueName virtue) => GetLevel(from, virtue) >= VirtueLevel.Follower; + + public static bool IsKnight(Mobile from, VirtueName virtue) => GetLevel(from, virtue) >= VirtueLevel.Knight; + + public static void AwardVirtue(PlayerMobile pm, VirtueName virtue, int amount) + { + if (virtue == VirtueName.Compassion) + { + if (pm.CompassionGains > 0 && DateTime.UtcNow > pm.NextCompassionDay) + { + pm.NextCompassionDay = DateTime.MinValue; + pm.CompassionGains = 0; + } + + if (pm.CompassionGains >= 5) + { + pm.SendLocalizedMessage(1053004); // You must wait about a day before you can gain in compassion again. + return; + } + } + + var gainedPath = false; + var virtueName = Enum.GetName(typeof(VirtueName), virtue); + + if (Award(pm, virtue, amount, ref gainedPath)) + { + // TODO: Localize? + if (gainedPath) + pm.SendMessage("You have gained a path in {0}!", virtueName); + else + pm.SendMessage("You have gained in {0}.", virtueName); + + if (virtue == VirtueName.Compassion) + { + pm.NextCompassionDay = DateTime.UtcNow + TimeSpan.FromDays(1.0); + ++pm.CompassionGains; + + if (pm.CompassionGains >= 5) + pm.SendLocalizedMessage( + 1053004 + ); // You must wait about a day before you can gain in compassion again. + } + } + else + { + // TODO: Localize? + pm.SendMessage("You have achieved the highest path of {0} and can no longer gain any further.", virtueName); + } + } + } +} diff --git a/Projects/UOContent/Engines/Virtues/VirtueInfoGump.cs b/Projects/UOContent/Engines/Virtues/VirtueInfoGump.cs index 08053a059..46467f80a 100644 --- a/Projects/UOContent/Engines/Virtues/VirtueInfoGump.cs +++ b/Projects/UOContent/Engines/Virtues/VirtueInfoGump.cs @@ -1,100 +1,106 @@ -using Server.Gumps; -using Server.Network; - -namespace Server -{ - public class VirtueInfoGump : Gump - { - private readonly Mobile m_Beholder; - private readonly int m_Desc; - private readonly string m_Page; - private readonly VirtueName m_Virtue; - - public VirtueInfoGump(Mobile beholder, VirtueName virtue, int description, string webPage = null) : base(0, 0) - { - m_Beholder = beholder; - m_Virtue = virtue; - m_Desc = description; - m_Page = webPage; - - int value = beholder.Virtues.GetValue((int)virtue); - - AddPage(0); - - AddImage(30, 40, 2080); - AddImage(47, 77, 2081); - AddImage(47, 147, 2081); - AddImage(47, 217, 2081); - AddImage(47, 267, 2083); - AddImage(70, 213, 2091); - - AddPage(1); - - int maxValue = VirtueHelper.GetMaxAmount(m_Virtue); - - int valueDesc; - int dots; - - if (value < 4000) - dots = value / 400; - else if (value < 10000) - dots = (value - 4000) / 600; - else if (value < maxValue) - dots = (value - 10000) / ((maxValue - 10000) / 10); - else - dots = 10; - - for (int i = 0; i < 10; ++i) - AddImage(95 + i * 17, 50, i < dots ? 2362 : 2360); - - if (value < 1) - valueDesc = 1052044; // You have not started on the path of this Virtue. - else if (value < 400) - valueDesc = 1052045; // You have barely begun your journey through the path of this Virtue. - else if (value < 2000) - valueDesc = 1052046; // You have progressed in this Virtue, but still have much to do. - else if (value < 3600) - valueDesc = 1052047; // Your journey through the path of this Virtue is going well. - else if (value < 4000) - valueDesc = 1052048; // You feel very close to achieving your next path in this Virtue. - else if (dots < 1) - valueDesc = 1052049; // You have achieved a path in this Virtue. - else if (dots < 9) - valueDesc = 1052047; // Your journey through the path of this Virtue is going well. - else if (dots < 10) - valueDesc = 1052048; // You feel very close to achieving your next path in this Virtue. - else - valueDesc = 1052050; // You have achieved the highest path in this Virtue. - - AddHtmlLocalized(157, 73, 200, 40, 1051000 + (int)virtue); - AddHtmlLocalized(75, 95, 220, 140, description); - AddHtmlLocalized(70, 224, 229, 60, valueDesc); - - AddButton(65, 277, 1209, 1209, 1); - - AddButton(280, 43, 4014, 4014, 2); - - AddHtmlLocalized(83, 275, 400, 40, webPage == null ? 1052055 : 1052052); // This virtue is not yet defined. OR -click to learn more (opens webpage) - } - - public override void OnResponse(NetState state, RelayInfo info) - { - switch (info.ButtonID) - { - case 1: - { - m_Beholder.SendGump(new VirtueInfoGump(m_Beholder, m_Virtue, m_Desc, m_Page)); - - if (m_Page != null) - state.Send(new LaunchBrowser(m_Page)); // No message about web browser starting on OSI - break; - } - case 2: - { - m_Beholder.SendGump(new VirtueStatusGump(m_Beholder)); - break; - } - } - } - } -} +using Server.Gumps; +using Server.Network; + +namespace Server +{ + public class VirtueInfoGump : Gump + { + private readonly Mobile m_Beholder; + private readonly int m_Desc; + private readonly string m_Page; + private readonly VirtueName m_Virtue; + + public VirtueInfoGump(Mobile beholder, VirtueName virtue, int description, string webPage = null) : base(0, 0) + { + m_Beholder = beholder; + m_Virtue = virtue; + m_Desc = description; + m_Page = webPage; + + var value = beholder.Virtues.GetValue((int)virtue); + + AddPage(0); + + AddImage(30, 40, 2080); + AddImage(47, 77, 2081); + AddImage(47, 147, 2081); + AddImage(47, 217, 2081); + AddImage(47, 267, 2083); + AddImage(70, 213, 2091); + + AddPage(1); + + var maxValue = VirtueHelper.GetMaxAmount(m_Virtue); + + int valueDesc; + int dots; + + if (value < 4000) + dots = value / 400; + else if (value < 10000) + dots = (value - 4000) / 600; + else if (value < maxValue) + dots = (value - 10000) / ((maxValue - 10000) / 10); + else + dots = 10; + + for (var i = 0; i < 10; ++i) + AddImage(95 + i * 17, 50, i < dots ? 2362 : 2360); + + if (value < 1) + valueDesc = 1052044; // You have not started on the path of this Virtue. + else if (value < 400) + valueDesc = 1052045; // You have barely begun your journey through the path of this Virtue. + else if (value < 2000) + valueDesc = 1052046; // You have progressed in this Virtue, but still have much to do. + else if (value < 3600) + valueDesc = 1052047; // Your journey through the path of this Virtue is going well. + else if (value < 4000) + valueDesc = 1052048; // You feel very close to achieving your next path in this Virtue. + else if (dots < 1) + valueDesc = 1052049; // You have achieved a path in this Virtue. + else if (dots < 9) + valueDesc = 1052047; // Your journey through the path of this Virtue is going well. + else if (dots < 10) + valueDesc = 1052048; // You feel very close to achieving your next path in this Virtue. + else + valueDesc = 1052050; // You have achieved the highest path in this Virtue. + + AddHtmlLocalized(157, 73, 200, 40, 1051000 + (int)virtue); + AddHtmlLocalized(75, 95, 220, 140, description); + AddHtmlLocalized(70, 224, 229, 60, valueDesc); + + AddButton(65, 277, 1209, 1209, 1); + + AddButton(280, 43, 4014, 4014, 2); + + AddHtmlLocalized( + 83, + 275, + 400, + 40, + webPage == null ? 1052055 : 1052052 + ); // This virtue is not yet defined. OR -click to learn more (opens webpage) + } + + public override void OnResponse(NetState state, RelayInfo info) + { + switch (info.ButtonID) + { + case 1: + { + m_Beholder.SendGump(new VirtueInfoGump(m_Beholder, m_Virtue, m_Desc, m_Page)); + + if (m_Page != null) + state.Send(new LaunchBrowser(m_Page)); // No message about web browser starting on OSI + break; + } + case 2: + { + m_Beholder.SendGump(new VirtueStatusGump(m_Beholder)); + break; + } + } + } + } +} diff --git a/Projects/UOContent/Engines/Virtues/VirtueStatusGump.cs b/Projects/UOContent/Engines/Virtues/VirtueStatusGump.cs index b892be402..2375fa8a8 100644 --- a/Projects/UOContent/Engines/Virtues/VirtueStatusGump.cs +++ b/Projects/UOContent/Engines/Virtues/VirtueStatusGump.cs @@ -1,107 +1,137 @@ -using Server.Gumps; -using Server.Network; - -namespace Server -{ - public class VirtueStatusGump : Gump - { - private readonly Mobile m_Beholder; - - public VirtueStatusGump(Mobile beholder) : base(0, 0) - { - m_Beholder = beholder; - - AddPage(0); - - AddImage(30, 40, 2080); - AddImage(47, 77, 2081); - AddImage(47, 147, 2081); - AddImage(47, 217, 2081); - AddImage(47, 267, 2083); - AddImage(70, 213, 2091); - - AddPage(1); - - AddHtml(140, 73, 200, 20, "The Virtues"); - - AddHtmlLocalized(80, 100, 100, 40, 1051000); // Humility - AddHtmlLocalized(80, 129, 100, 40, 1051001); // Sacrifice - AddHtmlLocalized(80, 159, 100, 40, 1051002); // Compassion - AddHtmlLocalized(80, 189, 100, 40, 1051003); // Spirituality - AddHtmlLocalized(200, 100, 200, 40, 1051004); // Valor - AddHtmlLocalized(200, 129, 200, 40, 1051005); // Honor - AddHtmlLocalized(200, 159, 200, 40, 1051006); // Justice - AddHtmlLocalized(200, 189, 200, 40, 1051007); // Honesty - - AddHtmlLocalized(75, 224, 220, 60, 1052062); // Click on a blue gem to view your status in that virtue. - - AddButton(60, 100, 1210, 1210, 1); - AddButton(60, 129, 1210, 1210, 2); - AddButton(60, 159, 1210, 1210, 3); - AddButton(60, 189, 1210, 1210, 4); - AddButton(180, 100, 1210, 1210, 5); - AddButton(180, 129, 1210, 1210, 6); - AddButton(180, 159, 1210, 1210, 7); - AddButton(180, 189, 1210, 1210, 8); - - AddButton(280, 43, 4014, 4014, 9); - } - - public override void OnResponse(NetState state, RelayInfo info) - { - switch (info.ButtonID) - { - case 1: - { - m_Beholder.SendGump(new VirtueInfoGump(m_Beholder, VirtueName.Humility, 1052051)); - break; - } - case 2: - { - m_Beholder.SendGump(new VirtueInfoGump(m_Beholder, VirtueName.Sacrifice, 1052053, - @"http://update.uo.com/design_389.html")); - break; - } - case 3: - { - m_Beholder.SendGump(new VirtueInfoGump(m_Beholder, VirtueName.Compassion, 1053000, - @"http://update.uo.com/design_412.html")); - break; - } - case 4: - { - m_Beholder.SendGump(new VirtueInfoGump(m_Beholder, VirtueName.Spirituality, 1052056)); - break; - } - case 5: - { - m_Beholder.SendGump(new VirtueInfoGump(m_Beholder, VirtueName.Valor, 1054033, - @"http://update.uo.com/design_427.html")); - break; - } - case 6: - { - m_Beholder.SendGump(new VirtueInfoGump(m_Beholder, VirtueName.Honor, 1052058, - @"http://guide.uo.com/virtues_2.html")); - break; - } - case 7: - { - m_Beholder.SendGump(new VirtueInfoGump(m_Beholder, VirtueName.Justice, 1052059, - @"http://update.uo.com/design_413.html")); - break; - } - case 8: - { - m_Beholder.SendGump(new VirtueInfoGump(m_Beholder, VirtueName.Honesty, 1052060)); - break; - } - case 9: - { - m_Beholder.SendGump(new VirtueGump(m_Beholder, m_Beholder)); - break; - } - } - } - } -} +using Server.Gumps; +using Server.Network; + +namespace Server +{ + public class VirtueStatusGump : Gump + { + private readonly Mobile m_Beholder; + + public VirtueStatusGump(Mobile beholder) : base(0, 0) + { + m_Beholder = beholder; + + AddPage(0); + + AddImage(30, 40, 2080); + AddImage(47, 77, 2081); + AddImage(47, 147, 2081); + AddImage(47, 217, 2081); + AddImage(47, 267, 2083); + AddImage(70, 213, 2091); + + AddPage(1); + + AddHtml(140, 73, 200, 20, "The Virtues"); + + AddHtmlLocalized(80, 100, 100, 40, 1051000); // Humility + AddHtmlLocalized(80, 129, 100, 40, 1051001); // Sacrifice + AddHtmlLocalized(80, 159, 100, 40, 1051002); // Compassion + AddHtmlLocalized(80, 189, 100, 40, 1051003); // Spirituality + AddHtmlLocalized(200, 100, 200, 40, 1051004); // Valor + AddHtmlLocalized(200, 129, 200, 40, 1051005); // Honor + AddHtmlLocalized(200, 159, 200, 40, 1051006); // Justice + AddHtmlLocalized(200, 189, 200, 40, 1051007); // Honesty + + AddHtmlLocalized(75, 224, 220, 60, 1052062); // Click on a blue gem to view your status in that virtue. + + AddButton(60, 100, 1210, 1210, 1); + AddButton(60, 129, 1210, 1210, 2); + AddButton(60, 159, 1210, 1210, 3); + AddButton(60, 189, 1210, 1210, 4); + AddButton(180, 100, 1210, 1210, 5); + AddButton(180, 129, 1210, 1210, 6); + AddButton(180, 159, 1210, 1210, 7); + AddButton(180, 189, 1210, 1210, 8); + + AddButton(280, 43, 4014, 4014, 9); + } + + public override void OnResponse(NetState state, RelayInfo info) + { + switch (info.ButtonID) + { + case 1: + { + m_Beholder.SendGump(new VirtueInfoGump(m_Beholder, VirtueName.Humility, 1052051)); + break; + } + case 2: + { + m_Beholder.SendGump( + new VirtueInfoGump( + m_Beholder, + VirtueName.Sacrifice, + 1052053, + @"http://update.uo.com/design_389.html" + ) + ); + break; + } + case 3: + { + m_Beholder.SendGump( + new VirtueInfoGump( + m_Beholder, + VirtueName.Compassion, + 1053000, + @"http://update.uo.com/design_412.html" + ) + ); + break; + } + case 4: + { + m_Beholder.SendGump(new VirtueInfoGump(m_Beholder, VirtueName.Spirituality, 1052056)); + break; + } + case 5: + { + m_Beholder.SendGump( + new VirtueInfoGump( + m_Beholder, + VirtueName.Valor, + 1054033, + @"http://update.uo.com/design_427.html" + ) + ); + break; + } + case 6: + { + m_Beholder.SendGump( + new VirtueInfoGump( + m_Beholder, + VirtueName.Honor, + 1052058, + @"http://guide.uo.com/virtues_2.html" + ) + ); + break; + } + case 7: + { + m_Beholder.SendGump( + new VirtueInfoGump( + m_Beholder, + VirtueName.Justice, + 1052059, + @"http://update.uo.com/design_413.html" + ) + ); + break; + } + case 8: + { + m_Beholder.SendGump(new VirtueInfoGump(m_Beholder, VirtueName.Honesty, 1052060)); + break; + } + case 9: + { + m_Beholder.SendGump(new VirtueGump(m_Beholder, m_Beholder)); + break; + } + } + } + } +} diff --git a/Projects/UOContent/Gumps/AddDoorGump.cs b/Projects/UOContent/Gumps/AddDoorGump.cs index 81b035895..195850e65 100644 --- a/Projects/UOContent/Gumps/AddDoorGump.cs +++ b/Projects/UOContent/Gumps/AddDoorGump.cs @@ -1,120 +1,122 @@ -using System; -using Server.Items; -using Server.Network; - -namespace Server.Gumps -{ - public class AddDoorGump : Gump - { - public static DoorInfo[] m_Types = - { - new DoorInfo(typeof(MetalDoor), 0x675), - new DoorInfo(typeof(RattanDoor), 0x695), - new DoorInfo(typeof(DarkWoodDoor), 0x6A5), - new DoorInfo(typeof(LightWoodDoor), 0x6D5), - new DoorInfo(typeof(StrongWoodDoor), 0x6E5) - }; - - private readonly int m_Type; - - public AddDoorGump(int type = -1) : base(50, 40) - { - m_Type = type; - - AddPage(0); - - if (m_Type >= 0 && m_Type < m_Types.Length) - { - AddBlueBack(155, 174); - - int baseID = m_Types[m_Type].m_BaseID; - - AddItem(25, 24, baseID); - AddButton(26, 37, 0x5782, 0x5782, 1); - - AddItem(47, 45, baseID + 2); - AddButton(43, 57, 0x5783, 0x5783, 2); - - AddItem(87, 22, baseID + 10); - AddButton(116, 35, 0x5785, 0x5785, 6); - - AddItem(65, 45, baseID + 8); - AddButton(96, 55, 0x5784, 0x5784, 5); - - AddButton(73, 36, 0x2716, 0x2716, 9); - } - else - { - AddBlueBack(265, 145); - - for (int i = 0; i < m_Types.Length; ++i) - { - AddButton(30 + i * 49, 13, 0x2624, 0x2625, i + 1); - AddItem(22 + i * 49, 20, m_Types[i].m_BaseID); - } - } - } - - public void AddBlueBack(int width, int height) - { - AddBackground(0, 0, width - 00, height - 00, 0xE10); - AddBackground(8, 5, width - 16, height - 11, 0x053); - AddImageTiled(15, 14, width - 29, height - 29, 0xE14); - AddAlphaRegion(15, 14, width - 29, height - 29); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - Mobile from = sender.Mobile; - int button = info.ButtonID - 1; - - if (m_Type == -1) - { - if (button >= 0 && button < m_Types.Length) - from.SendGump(new AddDoorGump(button)); - } - else - { - if (button >= 0 && button < 8) - { - from.SendGump(new AddDoorGump(m_Type)); - CommandSystem.Handle(from, - $"{CommandSystem.Prefix}Add {m_Types[m_Type].m_Type.Name} {(DoorFacing)button}"); - } - else if (button == 8) - { - from.SendGump(new AddDoorGump(m_Type)); - CommandSystem.Handle(from, $"{CommandSystem.Prefix}Link"); - } - else - { - from.SendGump(new AddDoorGump()); - } - } - } - - public static void Initialize() - { - CommandSystem.Register("AddDoor", AccessLevel.GameMaster, AddDoor_OnCommand); - } - - [Usage("AddDoor")] - [Description("Displays a menu from which you can interactively add doors.")] - public static void AddDoor_OnCommand(CommandEventArgs e) - { - e.Mobile.SendGump(new AddDoorGump()); - } - } - - public class DoorInfo - { - public int m_BaseID; - public Type m_Type; - - public DoorInfo(Type type, int baseID) - { - m_Type = type; - m_BaseID = baseID; - } - } -} +using System; +using Server.Items; +using Server.Network; + +namespace Server.Gumps +{ + public class AddDoorGump : Gump + { + public static DoorInfo[] m_Types = + { + new DoorInfo(typeof(MetalDoor), 0x675), + new DoorInfo(typeof(RattanDoor), 0x695), + new DoorInfo(typeof(DarkWoodDoor), 0x6A5), + new DoorInfo(typeof(LightWoodDoor), 0x6D5), + new DoorInfo(typeof(StrongWoodDoor), 0x6E5) + }; + + private readonly int m_Type; + + public AddDoorGump(int type = -1) : base(50, 40) + { + m_Type = type; + + AddPage(0); + + if (m_Type >= 0 && m_Type < m_Types.Length) + { + AddBlueBack(155, 174); + + var baseID = m_Types[m_Type].m_BaseID; + + AddItem(25, 24, baseID); + AddButton(26, 37, 0x5782, 0x5782, 1); + + AddItem(47, 45, baseID + 2); + AddButton(43, 57, 0x5783, 0x5783, 2); + + AddItem(87, 22, baseID + 10); + AddButton(116, 35, 0x5785, 0x5785, 6); + + AddItem(65, 45, baseID + 8); + AddButton(96, 55, 0x5784, 0x5784, 5); + + AddButton(73, 36, 0x2716, 0x2716, 9); + } + else + { + AddBlueBack(265, 145); + + for (var i = 0; i < m_Types.Length; ++i) + { + AddButton(30 + i * 49, 13, 0x2624, 0x2625, i + 1); + AddItem(22 + i * 49, 20, m_Types[i].m_BaseID); + } + } + } + + public void AddBlueBack(int width, int height) + { + AddBackground(0, 0, width - 00, height - 00, 0xE10); + AddBackground(8, 5, width - 16, height - 11, 0x053); + AddImageTiled(15, 14, width - 29, height - 29, 0xE14); + AddAlphaRegion(15, 14, width - 29, height - 29); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var from = sender.Mobile; + var button = info.ButtonID - 1; + + if (m_Type == -1) + { + if (button >= 0 && button < m_Types.Length) + from.SendGump(new AddDoorGump(button)); + } + else + { + if (button >= 0 && button < 8) + { + from.SendGump(new AddDoorGump(m_Type)); + CommandSystem.Handle( + from, + $"{CommandSystem.Prefix}Add {m_Types[m_Type].m_Type.Name} {(DoorFacing)button}" + ); + } + else if (button == 8) + { + from.SendGump(new AddDoorGump(m_Type)); + CommandSystem.Handle(from, $"{CommandSystem.Prefix}Link"); + } + else + { + from.SendGump(new AddDoorGump()); + } + } + } + + public static void Initialize() + { + CommandSystem.Register("AddDoor", AccessLevel.GameMaster, AddDoor_OnCommand); + } + + [Usage("AddDoor")] + [Description("Displays a menu from which you can interactively add doors.")] + public static void AddDoor_OnCommand(CommandEventArgs e) + { + e.Mobile.SendGump(new AddDoorGump()); + } + } + + public class DoorInfo + { + public int m_BaseID; + public Type m_Type; + + public DoorInfo(Type type, int baseID) + { + m_Type = type; + m_BaseID = baseID; + } + } +} diff --git a/Projects/UOContent/Gumps/AdminGump.cs b/Projects/UOContent/Gumps/AdminGump.cs index 65ca452bf..621190c25 100644 --- a/Projects/UOContent/Gumps/AdminGump.cs +++ b/Projects/UOContent/Gumps/AdminGump.cs @@ -1,3109 +1,3831 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Text; -using System.Threading; -using Server.Accounting; -using Server.Commands; -using Server.Items; -using Server.Misc; -using Server.Multis; -using Server.Network; -using Server.Prompts; - -namespace Server.Gumps -{ - public enum AdminGumpPage - { - Information_General, - Information_Perf, - Administer, - Clients, - Accounts, - Accounts_Shared, - Firewall, - Administer_WorldBuilding, - Administer_Server, - Administer_Access, - Administer_Access_Lockdown, - Administer_Commands, - ClientInfo, - AccountDetails, - AccountDetails_Information, - AccountDetails_Characters, - AccountDetails_Access, - AccountDetails_Access_ClientIPs, - AccountDetails_Access_Restrictions, - AccountDetails_Comments, - AccountDetails_Tags, - AccountDetails_ChangePassword, - AccountDetails_ChangeAccess, - FirewallInfo - } - - public class AdminGump : Gump - { - private const int LabelColor = 0x7FFF; - private const int SelectedColor = 0x421F; - private const int DisabledColor = 0x4210; - - private const int LabelColor32 = 0xFFFFFF; - private const int SelectedColor32 = 0x8080FF; - private const int DisabledColor32 = 0x808080; - - private const int LabelHue = 0x480; - private const int GreenHue = 0x40; - private const int RedHue = 0x20; - - private static readonly string[] m_AccessLevelStrings = - { - "Player", - "Counselor", - "Game Master", - "Seer", - "Administrator", - "Developer", - "Owner" - }; - - private readonly Mobile m_From; - private readonly List m_List; - private readonly int m_ListPage; - private readonly AdminGumpPage m_PageType; - private readonly object m_State; - - public AdminGump(Mobile from, AdminGumpPage pageType, int listPage = 0, List list = null, string notice = null, - object state = null) : base(50, 40) - { - from.CloseGump(); - - m_From = from; - m_PageType = pageType; - m_ListPage = listPage; - m_State = state; - m_List = list; - - AddPage(0); - - AddBackground(0, 0, 420, 440, 5054); - - AddBlackAlpha(10, 10, 170, 100); - AddBlackAlpha(190, 10, 220, 100); - AddBlackAlpha(10, 120, 400, 260); - AddBlackAlpha(10, 390, 400, 40); - - AddPageButton(10, 10, GetButtonID(0, 0), "INFORMATION", AdminGumpPage.Information_General, - AdminGumpPage.Information_Perf); - AddPageButton(10, 30, GetButtonID(0, 1), "ADMINISTER", AdminGumpPage.Administer, AdminGumpPage.Administer_Access, - AdminGumpPage.Administer_Commands, AdminGumpPage.Administer_Server, AdminGumpPage.Administer_WorldBuilding, - AdminGumpPage.Administer_Access_Lockdown); - AddPageButton(10, 50, GetButtonID(0, 2), "CLIENT LIST", AdminGumpPage.Clients, AdminGumpPage.ClientInfo); - AddPageButton(10, 70, GetButtonID(0, 3), "ACCOUNT LIST", AdminGumpPage.Accounts, AdminGumpPage.Accounts_Shared, - AdminGumpPage.AccountDetails, AdminGumpPage.AccountDetails_Information, - AdminGumpPage.AccountDetails_Characters, AdminGumpPage.AccountDetails_Access, - AdminGumpPage.AccountDetails_Access_ClientIPs, AdminGumpPage.AccountDetails_Access_Restrictions, - AdminGumpPage.AccountDetails_Comments, AdminGumpPage.AccountDetails_Tags, - AdminGumpPage.AccountDetails_ChangeAccess, AdminGumpPage.AccountDetails_ChangePassword); - AddPageButton(10, 90, GetButtonID(0, 4), "FIREWALL", AdminGumpPage.Firewall, AdminGumpPage.FirewallInfo); - - if (notice != null) - AddHtml(12, 392, 396, 36, Color(notice, LabelColor32)); - - switch (pageType) - { - case AdminGumpPage.Information_General: - { - int banned = 0; - int active = 0; - - foreach (Account acct in Accounts.GetAccounts()) - if (acct.Banned) - ++banned; - else - ++active; - - AddLabel(20, 130, LabelHue, "Active Accounts:"); - AddLabel(150, 130, LabelHue, active.ToString()); - - AddLabel(20, 150, LabelHue, "Banned Accounts:"); - AddLabel(150, 150, LabelHue, banned.ToString()); - - AddLabel(20, 170, LabelHue, "Firewalled:"); - AddLabel(150, 170, LabelHue, Firewall.List.Count.ToString()); - - AddLabel(20, 190, LabelHue, "Clients:"); - AddLabel(150, 190, LabelHue, TcpServer.Instances.Count.ToString()); - - AddLabel(20, 210, LabelHue, "Mobiles:"); - AddLabel(150, 210, LabelHue, World.Mobiles.Count.ToString()); - - AddLabel(20, 230, LabelHue, "Mobile Scripts:"); - AddLabel(150, 230, LabelHue, Core.ScriptMobiles.ToString()); - - AddLabel(20, 250, LabelHue, "Items:"); - AddLabel(150, 250, LabelHue, World.Items.Count.ToString()); - - AddLabel(20, 270, LabelHue, "Item Scripts:"); - AddLabel(150, 270, LabelHue, Core.ScriptItems.ToString()); - - AddLabel(20, 290, LabelHue, "Uptime:"); - AddLabel(150, 290, LabelHue, FormatTimeSpan(DateTime.UtcNow - Clock.ServerStart)); - - AddLabel(20, 310, LabelHue, "Memory:"); - AddLabel(150, 310, LabelHue, FormatByteAmount(GC.GetTotalMemory(false))); - - AddLabel(20, 330, LabelHue, "Framework:"); - AddLabel(150, 330, LabelHue, Environment.Version.ToString()); - - AddLabel(20, 350, LabelHue, "Operating System: "); - string os = Environment.OSVersion.ToString(); - - os = os.Replace("Microsoft", "MSFT"); - os = os.Replace("Service Pack", "SP"); - - AddLabel(150, 350, LabelHue, os); - - /*string str; - - try{ str = FormatTimeSpan( Core.Process.TotalProcessorTime ); } - catch{ str = "(unable to retrieve)"; } - - AddLabel( 20, 330, LabelHue, "Process Time:" ); - AddLabel( 250, 330, LabelHue, str );*/ - - /*try{ str = Core.Process.PriorityClass.ToString(); } - catch{ str = "(unable to retrieve)"; } - - AddLabel( 20, 350, LabelHue, "Process Priority:" ); - AddLabel( 250, 350, LabelHue, str );*/ - - AddPageButton(200, 20, GetButtonID(0, 0), "General", AdminGumpPage.Information_General); - AddPageButton(200, 40, GetButtonID(0, 5), "Performance", AdminGumpPage.Information_Perf); - - break; - } - case AdminGumpPage.Information_Perf: - { - AddLabel(20, 130, LabelHue, "Cycles Per Second:"); - AddLabel(40, 150, LabelHue, $"Current: {Core.CyclesPerSecond:N2}"); - AddLabel(40, 170, LabelHue, $"Average: {Core.AverageCPS:N2}"); - - StringBuilder sb = new StringBuilder(); - - ThreadPool.GetAvailableThreads(out int curUser, out int curIOCP); - ThreadPool.GetMaxThreads(out int maxUser, out int maxIOCP); - - sb.Append("Worker Threads:
Capacity: "); - sb.Append(maxUser); - sb.Append("
Available: "); - sb.Append(curUser); - sb.Append("
Usage: "); - sb.Append((maxUser - curUser) * 100 / maxUser); - sb.Append("%

IOCP Threads:
Capacity: "); - sb.Append(maxIOCP); - sb.Append("
Available: "); - sb.Append(curIOCP); - sb.Append("
Usage: "); - sb.Append((maxIOCP - curIOCP) * 100 / maxIOCP); - sb.Append("%"); - - AddLabel(20, 200, LabelHue, "Pooling:"); - AddHtml(20, 220, 380, 150, sb.ToString(), true, true); - - AddPageButton(200, 20, GetButtonID(0, 0), "General", AdminGumpPage.Information_General); - AddPageButton(200, 40, GetButtonID(0, 5), "Performance", AdminGumpPage.Information_Perf); - - break; - } - case AdminGumpPage.Administer_WorldBuilding: - { - AddHtml(10, 125, 400, 20, Color(Center("Generating"), LabelColor32)); - - AddButtonLabeled(20, 150, GetButtonID(3, 100), "Documentation"); - AddButtonLabeled(220, 150, GetButtonID(3, 107), "Rebuild Categorization"); - - AddButtonLabeled(20, 175, GetButtonID(3, 101), "Teleporters"); - AddButtonLabeled(220, 175, GetButtonID(3, 102), "Moongates"); - - AddButtonLabeled(20, 200, GetButtonID(3, 103), "Vendors"); - AddButtonLabeled(220, 200, GetButtonID(3, 106), "Decoration"); - - AddButtonLabeled(20, 225, GetButtonID(3, 104), "Doors"); - AddButtonLabeled(220, 225, GetButtonID(3, 105), "Signs"); - - AddHtml(20, 275, 400, 30, Color(Center("Statics"), LabelColor32)); - - AddButtonLabeled(20, 300, GetButtonID(3, 110), "Freeze (Target)"); - AddButtonLabeled(20, 325, GetButtonID(3, 111), "Freeze (World)"); - AddButtonLabeled(20, 350, GetButtonID(3, 112), "Freeze (Map)"); - - AddButtonLabeled(220, 300, GetButtonID(3, 120), "Unfreeze (Target)"); - AddButtonLabeled(220, 325, GetButtonID(3, 121), "Unfreeze (World)"); - AddButtonLabeled(220, 350, GetButtonID(3, 122), "Unfreeze (Map)"); - - goto case AdminGumpPage.Administer; - } - case AdminGumpPage.Administer_Server: - { - AddHtml(10, 125, 400, 20, Color(Center("Server"), LabelColor32)); - - AddButtonLabeled(20, 150, GetButtonID(3, 200), "Save"); - - /*if (!Core.Service) - {*/ - AddButtonLabeled(20, 180, GetButtonID(3, 201), "Shutdown (With Save)"); - AddButtonLabeled(20, 200, GetButtonID(3, 202), "Shutdown (Without Save)"); - - AddButtonLabeled(20, 230, GetButtonID(3, 203), "Shutdown & Restart (With Save)"); - AddButtonLabeled(20, 250, GetButtonID(3, 204), "Shutdown & Restart (Without Save)"); - /*} - else - { - AddLabel( 20, 215, LabelHue, "Shutdown/Restart not available." ); - }*/ - - AddHtml(10, 295, 400, 20, Color(Center("Broadcast"), LabelColor32)); - - AddTextField(20, 320, 380, 20, 0); - AddButtonLabeled(20, 350, GetButtonID(3, 210), "To Everyone"); - AddButtonLabeled(220, 350, GetButtonID(3, 211), "To Staff"); - - goto case AdminGumpPage.Administer; - } - case AdminGumpPage.Administer_Access_Lockdown: - { - AddHtml(10, 125, 400, 20, Color(Center("Server Lockdown"), LabelColor32)); - - AddHtml(20, 150, 380, 80, - Color( - "When enabled, only clients with an access level equal to or greater than the specified lockdown level may access the server. After setting a lockdown level, use the Purge Invalid Clients button to disconnect those clients without access.", - LabelColor32)); - - AccessLevel level = AccountHandler.LockdownLevel; - bool isLockedDown = level > AccessLevel.Player; - - AddSelectedButton(20, 230, GetButtonID(3, 500), "Not Locked Down", !isLockedDown); - AddSelectedButton(20, 260, GetButtonID(3, 504), "Administrators", - isLockedDown && level <= AccessLevel.Administrator); - AddSelectedButton(20, 280, GetButtonID(3, 503), "Seers", isLockedDown && level <= AccessLevel.Seer); - AddSelectedButton(20, 300, GetButtonID(3, 502), "Game Masters", - isLockedDown && level <= AccessLevel.GameMaster); - AddSelectedButton(20, 320, GetButtonID(3, 501), "Counselors", - isLockedDown && level <= AccessLevel.Counselor); - - AddButtonLabeled(20, 350, GetButtonID(3, 510), "Purge Invalid Clients"); - - goto case AdminGumpPage.Administer; - } - case AdminGumpPage.Administer_Access: - { - AddHtml(10, 125, 400, 20, Color(Center("Access"), LabelColor32)); - - AddHtml(10, 155, 400, 20, Color(Center("Connectivity"), LabelColor32)); - - AddButtonLabeled(20, 180, GetButtonID(3, 300), "Kick"); - AddButtonLabeled(220, 180, GetButtonID(3, 301), "Ban"); - - AddButtonLabeled(20, 210, GetButtonID(3, 302), "Firewall"); - AddButtonLabeled(220, 210, GetButtonID(3, 303), "Lockdown"); - - AddHtml(10, 245, 400, 20, Color(Center("Staff"), LabelColor32)); - - AddButtonLabeled(20, 270, GetButtonID(3, 310), "Make Player"); - AddButtonLabeled(20, 290, GetButtonID(3, 311), "Make Counselor"); - AddButtonLabeled(20, 310, GetButtonID(3, 312), "Make Game Master"); - AddButtonLabeled(20, 330, GetButtonID(3, 313), "Make Seer"); - - if (from.AccessLevel > AccessLevel.Administrator) - { - AddButtonLabeled(220, 270, GetButtonID(3, 314), "Make Administrator"); - - if (from.AccessLevel > AccessLevel.Developer) - { - AddButtonLabeled(220, 290, GetButtonID(3, 315), "Make Developer"); - - if (from.AccessLevel >= AccessLevel.Owner) - AddButtonLabeled(220, 310, GetButtonID(3, 316), "Make Owner"); - } - } - - goto case AdminGumpPage.Administer; - } - case AdminGumpPage.Administer_Commands: - { - AddHtml(10, 125, 400, 20, Color(Center("Commands"), LabelColor32)); - - AddButtonLabeled(20, 150, GetButtonID(3, 400), "Add"); - AddButtonLabeled(220, 150, GetButtonID(3, 401), "Remove"); - - AddButtonLabeled(20, 170, GetButtonID(3, 402), "Dupe"); - AddButtonLabeled(220, 170, GetButtonID(3, 403), "Dupe in bag"); - - AddButtonLabeled(20, 200, GetButtonID(3, 404), "Properties"); - AddButtonLabeled(220, 200, GetButtonID(3, 405), "Skills"); - - AddButtonLabeled(20, 230, GetButtonID(3, 406), "Mortal"); - AddButtonLabeled(220, 230, GetButtonID(3, 407), "Immortal"); - - AddButtonLabeled(20, 250, GetButtonID(3, 408), "Squelch"); - AddButtonLabeled(220, 250, GetButtonID(3, 409), "Unsquelch"); - - AddButtonLabeled(20, 270, GetButtonID(3, 410), "Freeze"); - AddButtonLabeled(220, 270, GetButtonID(3, 411), "Unfreeze"); - - AddButtonLabeled(20, 290, GetButtonID(3, 412), "Hide"); - AddButtonLabeled(220, 290, GetButtonID(3, 413), "Unhide"); - - AddButtonLabeled(20, 310, GetButtonID(3, 414), "Kill"); - AddButtonLabeled(220, 310, GetButtonID(3, 415), "Resurrect"); - - AddButtonLabeled(20, 330, GetButtonID(3, 416), "Move"); - AddButtonLabeled(220, 330, GetButtonID(3, 417), "Wipe"); - - AddButtonLabeled(20, 350, GetButtonID(3, 418), "Teleport"); - AddButtonLabeled(220, 350, GetButtonID(3, 419), "Teleport (Multiple)"); - - goto case AdminGumpPage.Administer; - } - case AdminGumpPage.Administer: - { - AddPageButton(200, 20, GetButtonID(3, 0), "World Building", AdminGumpPage.Administer_WorldBuilding); - AddPageButton(200, 40, GetButtonID(3, 1), "Server", AdminGumpPage.Administer_Server); - AddPageButton(200, 60, GetButtonID(3, 2), "Access", AdminGumpPage.Administer_Access, - AdminGumpPage.Administer_Access_Lockdown); - AddPageButton(200, 80, GetButtonID(3, 3), "Commands", AdminGumpPage.Administer_Commands); - - break; - } - case AdminGumpPage.Clients: - { - if (m_List == null) - { - List states = TcpServer.Instances; - states.Sort(NetStateComparer.Instance); - - m_List = states.ToList(); - } - - AddClientHeader(); - - AddLabelCropped(12, 120, 81, 20, LabelHue, "Name"); - AddLabelCropped(95, 120, 81, 20, LabelHue, "Account"); - AddLabelCropped(178, 120, 81, 20, LabelHue, "Access Level"); - AddLabelCropped(273, 120, 109, 20, LabelHue, "IP Address"); - - if (listPage > 0) - AddButton(375, 122, 0x15E3, 0x15E7, GetButtonID(1, 0)); - else - AddImage(375, 122, 0x25EA); - - if ((listPage + 1) * 12 < m_List.Count) - AddButton(392, 122, 0x15E1, 0x15E5, GetButtonID(1, 1)); - else - AddImage(392, 122, 0x25E6); - - if (m_List.Count == 0) - AddLabel(12, 140, LabelHue, "There are no clients to display."); - - for (int i = 0, index = listPage * 12; i < 12 && index >= 0 && index < m_List.Count; ++i, ++index) - { - if (!(m_List[index] is NetState ns)) - continue; - - Mobile m = ns.Mobile; - Account a = ns.Account as Account; - int offset = 140 + i * 20; - - if (m == null) - AddLabelCropped(12, offset, 81, 20, LabelHue, "(logging in)"); - else - AddLabelCropped(12, offset, 81, 20, GetHueFor(m), m.Name); - AddLabelCropped(95, offset, 81, 20, LabelHue, a == null ? "(no account)" : a.Username); - AddLabelCropped(178, offset, 81, 20, LabelHue, - m == null - ? a != null ? FormatAccessLevel(a.AccessLevel) : "" - : FormatAccessLevel(m.AccessLevel)); - AddLabelCropped(273, offset, 109, 20, LabelHue, ns.ToString()); - - if (a != null || m != null) - AddButton(380, offset - 1, 0xFA5, 0xFA7, GetButtonID(4, index + 2)); - } - - break; - } - case AdminGumpPage.ClientInfo: - { - if (!(state is Mobile m)) - break; - - AddClientHeader(); - - AddHtml(10, 125, 400, 20, Color(Center("Information"), LabelColor32)); - - int y = 146; - - AddLabel(20, y, LabelHue, "Name:"); - AddLabel(200, y, GetHueFor(m), m.Name); - y += 20; - - Account a = m.Account as Account; - - AddLabel(20, y, LabelHue, "Account:"); - AddLabel(200, y, a?.Banned == true ? RedHue : LabelHue, a == null ? "(no account)" : a.Username); - AddButton(380, y, 0xFA5, 0xFA7, GetButtonID(7, 14)); - y += 20; - - NetState ns = m.NetState; - - if (ns == null) - { - AddLabel(20, y, LabelHue, "Address:"); - AddLabel(200, y, RedHue, "Offline"); - y += 20; - - AddLabel(20, y, LabelHue, "Location:"); - AddLabel(200, y, LabelHue, $"{m.Location} [{m.Map}]"); - y += 44; - } - else - { - AddLabel(20, y, LabelHue, "Address:"); - AddLabel(200, y, GreenHue, ns.ToString()); - y += 20; - - ClientVersion v = ns.Version; - - AddLabel(20, y, LabelHue, "Version:"); - AddLabel(200, y, LabelHue, v == null ? "(null)" : v.ToString()); - y += 20; - - AddLabel(20, y, LabelHue, "Location:"); - AddLabel(200, y, LabelHue, $"{m.Location} [{m.Map}]"); - y += 24; - } - - AddButtonLabeled(20, y, GetButtonID(7, 0), "Go to"); - AddButtonLabeled(200, y, GetButtonID(7, 1), "Get"); - y += 20; - - AddButtonLabeled(20, y, GetButtonID(7, 2), "Kick"); - AddButtonLabeled(200, y, GetButtonID(7, 3), "Ban"); - y += 20; - - AddButtonLabeled(20, y, GetButtonID(7, 4), "Properties"); - AddButtonLabeled(200, y, GetButtonID(7, 5), "Skills"); - y += 20; - - AddButtonLabeled(20, y, GetButtonID(7, 6), "Mortal"); - AddButtonLabeled(200, y, GetButtonID(7, 7), "Immortal"); - y += 20; - - AddButtonLabeled(20, y, GetButtonID(7, 8), "Squelch"); - AddButtonLabeled(200, y, GetButtonID(7, 9), "Unsquelch"); - y += 20; - - /*AddButtonLabeled( 20, y, GetButtonID( 7, 10 ), "Hide" ); - AddButtonLabeled( 200, y, GetButtonID( 7, 11 ), "Unhide" ); - y += 20;*/ - - AddButtonLabeled(20, y, GetButtonID(7, 12), "Kill"); - AddButtonLabeled(200, y, GetButtonID(7, 13), "Resurrect"); - - break; - } - case AdminGumpPage.Accounts_Shared: - { - List>> sharedAccounts; - - if (m_List == null) - { - sharedAccounts = GetAllSharedAccounts(); - m_List = Utility.CastListContravariant>, object>(sharedAccounts); - } - else - { - sharedAccounts = Utility.CastListCovariant>>(m_List); - } - - AddLabelCropped(12, 120, 60, 20, LabelHue, "Count"); - AddLabelCropped(72, 120, 120, 20, LabelHue, "Address"); - AddLabelCropped(192, 120, 180, 20, LabelHue, "Accounts"); - - if (listPage > 0) - AddButton(375, 122, 0x15E3, 0x15E7, GetButtonID(1, 0)); - else - AddImage(375, 122, 0x25EA); - - if ((listPage + 1) * 12 < sharedAccounts.Count) - AddButton(392, 122, 0x15E1, 0x15E5, GetButtonID(1, 1)); - else - AddImage(392, 122, 0x25E6); - - if (sharedAccounts.Count == 0) - AddLabel(12, 140, LabelHue, "There are no accounts to display."); - - StringBuilder sb = new StringBuilder(); - - for (int i = 0, index = listPage * 12; i < 12 && index >= 0 && index < sharedAccounts.Count; ++i, ++index) - { - KeyValuePair> kvp = sharedAccounts[index]; - - IPAddress ipAddr = kvp.Key; - List accts = kvp.Value; - - int offset = 140 + i * 20; - - AddLabelCropped(12, offset, 60, 20, LabelHue, accts.Count.ToString()); - AddLabelCropped(72, offset, 120, 20, LabelHue, ipAddr.ToString()); - - if (sb.Length > 0) - sb.Length = 0; - - for (int j = 0; j < accts.Count; ++j) - { - if (j > 0) - sb.Append(", "); - - if (j < 4) - { - Account acct = accts[j]; - - sb.Append(acct.Username); - } - else - { - sb.Append("..."); - break; - } - } - - AddLabelCropped(192, offset, 180, 20, LabelHue, sb.ToString()); - - AddButton(380, offset - 1, 0xFA5, 0xFA7, GetButtonID(5, index + 56)); - } - - break; - } - case AdminGumpPage.Accounts: - { - m_List ??= new List(); - - List rads = state as List; - - AddAccountHeader(); - - if (rads == null) - AddLabelCropped(12, 120, 120, 20, LabelHue, "Name"); - else - AddLabelCropped(32, 120, 100, 20, LabelHue, "Name"); - - AddLabelCropped(132, 120, 120, 20, LabelHue, "Access Level"); - AddLabelCropped(252, 120, 120, 20, LabelHue, "Status"); - - if (listPage > 0) - AddButton(375, 122, 0x15E3, 0x15E7, GetButtonID(1, 0)); - else - AddImage(375, 122, 0x25EA); - - if ((listPage + 1) * 12 < m_List.Count) - AddButton(392, 122, 0x15E1, 0x15E5, GetButtonID(1, 1)); - else - AddImage(392, 122, 0x25E6); - - if (m_List.Count == 0) - AddLabel(12, 140, LabelHue, "There are no accounts to display."); - - if (rads != null && notice == null) - { - AddButtonLabeled(10, 390, GetButtonID(5, 27), "Ban marked"); - AddButtonLabeled(10, 410, GetButtonID(5, 28), "Delete marked"); - - AddButtonLabeled(210, 390, GetButtonID(5, 29), "Mark all"); - AddButtonLabeled(210, 410, GetButtonID(5, 35), "Unmark house owners"); - } - - for (int i = 0, index = listPage * 12; i < 12 && index >= 0 && index < m_List.Count; ++i, ++index) - { - if (!(m_List[index] is Account a)) - continue; - - int offset = 140 + i * 20; - - GetAccountInfo(a, out AccessLevel accessLevel, out bool online); - - if (rads == null) - { - AddLabelCropped(12, offset, 120, 20, LabelHue, a.Username); - } - else - { - AddCheck(10, offset, 0xD2, 0xD3, rads.Contains(a), index); - AddLabelCropped(32, offset, 100, 20, LabelHue, a.Username); - } - - AddLabelCropped(132, offset, 120, 20, LabelHue, FormatAccessLevel(accessLevel)); - - if (online) - AddLabelCropped(252, offset, 120, 20, GreenHue, "Online"); - else if (a.Banned) - AddLabelCropped(252, offset, 120, 20, RedHue, "Banned"); - else - AddLabelCropped(252, offset, 120, 20, RedHue, "Offline"); - - AddButton(380, offset - 1, 0xFA5, 0xFA7, GetButtonID(5, index + 56)); - } - - break; - } - case AdminGumpPage.AccountDetails: - { - AddPageButton(190, 10, GetButtonID(5, 0), "Information", AdminGumpPage.AccountDetails_Information, - AdminGumpPage.AccountDetails_ChangeAccess, AdminGumpPage.AccountDetails_ChangePassword); - AddPageButton(190, 30, GetButtonID(5, 1), "Characters", AdminGumpPage.AccountDetails_Characters); - AddPageButton(190, 50, GetButtonID(5, 13), "Access", AdminGumpPage.AccountDetails_Access, - AdminGumpPage.AccountDetails_Access_ClientIPs, AdminGumpPage.AccountDetails_Access_Restrictions); - AddPageButton(190, 70, GetButtonID(5, 2), "Comments", AdminGumpPage.AccountDetails_Comments); - AddPageButton(190, 90, GetButtonID(5, 3), "Tags", AdminGumpPage.AccountDetails_Tags); - break; - } - case AdminGumpPage.AccountDetails_ChangePassword: - { - if (!(state is Account a)) - break; - - AddHtml(10, 125, 400, 20, Color(Center("Change Password"), LabelColor32)); - - AddLabel(20, 150, LabelHue, "Username:"); - AddLabel(200, 150, LabelHue, a.Username); - - AddLabel(20, 180, LabelHue, "Password:"); - AddTextField(200, 180, 160, 20, 0); - - AddLabel(20, 210, LabelHue, "Confirm:"); - AddTextField(200, 210, 160, 20, 1); - - AddButtonLabeled(20, 240, GetButtonID(5, 12), "Submit Change"); - - goto case AdminGumpPage.AccountDetails; - } - case AdminGumpPage.AccountDetails_ChangeAccess: - { - if (!(state is Account a)) - break; - - AddHtml(10, 125, 400, 20, Color(Center("Change Access Level"), LabelColor32)); - - AddLabel(20, 150, LabelHue, "Username:"); - AddLabel(200, 150, LabelHue, a.Username); - - AddLabel(20, 170, LabelHue, "Current Level:"); - AddLabel(200, 170, LabelHue, FormatAccessLevel(a.AccessLevel)); - - AddButtonLabeled(20, 200, GetButtonID(5, 20), "Player"); - AddButtonLabeled(20, 220, GetButtonID(5, 21), "Counselor"); - AddButtonLabeled(20, 240, GetButtonID(5, 22), "Game Master"); - AddButtonLabeled(20, 260, GetButtonID(5, 23), "Seer"); - - if (from.AccessLevel > AccessLevel.Administrator) - { - AddButtonLabeled(20, 280, GetButtonID(5, 24), "Administrator"); - - if (from.AccessLevel > AccessLevel.Developer) - { - AddButtonLabeled(20, 300, GetButtonID(5, 33), "Developer"); - - if (from.AccessLevel >= AccessLevel.Owner) - AddButtonLabeled(20, 320, GetButtonID(5, 34), "Owner"); - } - } - - goto case AdminGumpPage.AccountDetails; - } - case AdminGumpPage.AccountDetails_Information: - { - if (!(state is Account a)) - break; - - int charCount = 0; - - for (int i = 0; i < a.Length; ++i) - if (a[i] != null) - ++charCount; - - AddHtml(10, 125, 400, 20, Color(Center("Information"), LabelColor32)); - - AddLabel(20, 150, LabelHue, "Username:"); - AddLabel(200, 150, LabelHue, a.Username); - - AddLabel(20, 170, LabelHue, "Access Level:"); - AddLabel(200, 170, LabelHue, FormatAccessLevel(a.AccessLevel)); - - AddLabel(20, 190, LabelHue, "Status:"); - AddLabel(200, 190, a.Banned ? RedHue : GreenHue, a.Banned ? "Banned" : "Active"); - - if (a.Banned && a.GetBanTags(out DateTime banTime, out TimeSpan banDuration)) - { - if (banDuration == TimeSpan.MaxValue) - { - AddLabel(250, 190, LabelHue, "(Infinite)"); - } - else if (banDuration == TimeSpan.Zero) - { - AddLabel(250, 190, LabelHue, "(Zero)"); - } - else - { - TimeSpan remaining = DateTime.UtcNow - banTime; - - if (remaining < TimeSpan.Zero) - remaining = TimeSpan.Zero; - else if (remaining > banDuration) - remaining = banDuration; - - double remMinutes = remaining.TotalMinutes; - double totMinutes = banDuration.TotalMinutes; - - double perc = remMinutes / totMinutes; - - AddLabel(250, 190, LabelHue, $"{FormatTimeSpan(banDuration)} [{perc * 100:F0}%]"); - } - } - else if (a.Banned) - { - AddLabel(250, 190, LabelHue, "(Unspecified)"); - } - - AddLabel(20, 210, LabelHue, "Created:"); - AddLabel(200, 210, LabelHue, a.Created.ToString()); - - AddLabel(20, 230, LabelHue, "Last Login:"); - AddLabel(200, 230, LabelHue, a.LastLogin.ToString()); - - AddLabel(20, 250, LabelHue, "Character Count:"); - AddLabel(200, 250, LabelHue, charCount.ToString()); - - AddLabel(20, 270, LabelHue, "Comment Count:"); - AddLabel(200, 270, LabelHue, a.Comments.Count.ToString()); - - AddLabel(20, 290, LabelHue, "Tag Count:"); - AddLabel(200, 290, LabelHue, a.Tags.Count.ToString()); - - AddButtonLabeled(20, 320, GetButtonID(5, 8), "Change Password"); - AddButtonLabeled(200, 320, GetButtonID(5, 9), "Change Access Level"); - - if (!a.Banned) - AddButtonLabeled(20, 350, GetButtonID(5, 10), "Ban Account"); - else - AddButtonLabeled(20, 350, GetButtonID(5, 11), "Unban Account"); - - AddButtonLabeled(200, 350, GetButtonID(5, 25), "Delete Account"); - - goto case AdminGumpPage.AccountDetails; - } - case AdminGumpPage.AccountDetails_Access: - { - if (!(state is Account a)) - break; - - AddHtml(10, 125, 400, 20, Color(Center("Access"), LabelColor32)); - - AddPageButton(20, 150, GetButtonID(5, 14), "View client addresses", - AdminGumpPage.AccountDetails_Access_ClientIPs); - AddPageButton(20, 170, GetButtonID(5, 15), "Manage restrictions", - AdminGumpPage.AccountDetails_Access_Restrictions); - - goto case AdminGumpPage.AccountDetails; - } - case AdminGumpPage.AccountDetails_Access_ClientIPs: - { - if (!(state is Account a)) - break; - - List ipAddresses; - - if (m_List == null) - { - ipAddresses = a.LoginIPs.ToList(); - m_List = Utility.CastListContravariant(ipAddresses); - } - else - ipAddresses = Utility.CastListCovariant(m_List); - - AddHtml(10, 195, 400, 20, Color(Center("Client Addresses"), LabelColor32)); - - AddButtonLabeled(227, 225, GetButtonID(5, 16), "View all shared accounts"); - AddButtonLabeled(227, 245, GetButtonID(5, 17), "Ban all shared accounts"); - AddButtonLabeled(227, 265, GetButtonID(5, 18), "Firewall all addresses"); - AddButtonLabeled(227, 285, GetButtonID(5, 36), "Clear all addresses"); - - AddHtml(225, 315, 180, 80, Color("List of IP addresses which have accessed this account.", LabelColor32)); - - AddImageTiled(15, 219, 206, 156, 0xBBC); - AddBlackAlpha(16, 220, 204, 154); - - AddHtml(18, 221, 114, 20, Color("IP Address", LabelColor32)); - - if (listPage > 0) - AddButton(184, 223, 0x15E3, 0x15E7, GetButtonID(1, 0)); - else - AddImage(184, 223, 0x25EA); - - if ((listPage + 1) * 6 < ipAddresses.Count) - AddButton(201, 223, 0x15E1, 0x15E5, GetButtonID(1, 1)); - else - AddImage(201, 223, 0x25E6); - - if (ipAddresses.Count == 0) - AddHtml(18, 243, 200, 60, Color("This account has not yet been accessed.", LabelColor32)); - - for (int i = 0, index = listPage * 6; i < 6 && index >= 0 && index < ipAddresses.Count; ++i, ++index) - { - AddHtml(18, 243 + i * 22, 114, 20, Color(ipAddresses[index].ToString(), LabelColor32)); - AddButton(130, 242 + i * 22, 0xFA2, 0xFA4, GetButtonID(8, index)); - AddButton(160, 242 + i * 22, 0xFA8, 0xFAA, GetButtonID(9, index)); - AddButton(190, 242 + i * 22, 0xFB1, 0xFB3, GetButtonID(10, index)); - } - - goto case AdminGumpPage.AccountDetails_Access; - } - case AdminGumpPage.AccountDetails_Access_Restrictions: - { - if (!(state is Account a)) - break; - - List ipRestrictions; - - if (m_List == null) - { - ipRestrictions = a.IPRestrictions.ToList(); - m_List = Utility.CastListContravariant(ipRestrictions); - } - else - ipRestrictions = Utility.CastListCovariant(m_List); - - AddHtml(10, 195, 400, 20, Color(Center("Address Restrictions"), LabelColor32)); - - AddTextField(227, 225, 120, 20, 0); - - AddButtonLabeled(352, 225, GetButtonID(5, 19), "Add"); - - AddHtml(225, 255, 180, 120, - Color( - "Any clients connecting from an address not in this list will be rejected. Or, if the list is empty, any client may connect.", - LabelColor32)); - - AddImageTiled(15, 219, 206, 156, 0xBBC); - AddBlackAlpha(16, 220, 204, 154); - - AddHtml(18, 221, 114, 20, Color("IP Address", LabelColor32)); - - if (listPage > 0) - AddButton(184, 223, 0x15E3, 0x15E7, GetButtonID(1, 0)); - else - AddImage(184, 223, 0x25EA); - - if ((listPage + 1) * 6 < ipRestrictions.Count) - AddButton(201, 223, 0x15E1, 0x15E5, GetButtonID(1, 1)); - else - AddImage(201, 223, 0x25E6); - - if (ipRestrictions.Count == 0) - AddHtml(18, 243, 200, 60, Color("There are no addresses in this list.", LabelColor32)); - - for (int i = 0, index = listPage * 6; i < 6 && index >= 0 && index < ipRestrictions.Count; ++i, ++index) - { - AddHtml(18, 243 + i * 22, 114, 20, Color(ipRestrictions[index], LabelColor32)); - AddButton(190, 242 + i * 22, 0xFB1, 0xFB3, GetButtonID(8, index)); - } - - goto case AdminGumpPage.AccountDetails_Access; - } - case AdminGumpPage.AccountDetails_Characters: - { - if (!(state is Account a)) - break; - - AddHtml(10, 125, 400, 20, Color(Center("Characters"), LabelColor32)); - - AddLabelCropped(12, 150, 120, 20, LabelHue, "Name"); - AddLabelCropped(132, 150, 120, 20, LabelHue, "Access Level"); - AddLabelCropped(252, 150, 120, 20, LabelHue, "Status"); - - int index = 0; - - for (int i = 0; i < a.Length; ++i) - { - Mobile m = a[i]; - - if (m == null) - continue; - - int offset = 170 + index * 20; - - AddLabelCropped(12, offset, 120, 20, GetHueFor(m), m.Name); - AddLabelCropped(132, offset, 120, 20, LabelHue, FormatAccessLevel(m.AccessLevel)); - - if (m.NetState != null) - AddLabelCropped(252, offset, 120, 20, GreenHue, "Online"); - else - AddLabelCropped(252, offset, 120, 20, RedHue, "Offline"); - - AddButton(380, offset - 1, 0xFA5, 0xFA7, GetButtonID(5, i + 50)); - - ++index; - } - - if (index == 0) - AddLabel(12, 170, LabelHue, "The character list is empty."); - - goto case AdminGumpPage.AccountDetails; - } - case AdminGumpPage.AccountDetails_Comments: - { - if (!(state is Account a)) - break; - - AddHtml(10, 125, 400, 20, Color(Center("Comments"), LabelColor32)); - - AddButtonLabeled(20, 150, GetButtonID(5, 4), "Add Comment"); - - StringBuilder sb = new StringBuilder(); - - if (a.Comments.Count == 0) - sb.Append("There are no comments for this account."); - - for (int i = 0; i < a.Comments.Count; ++i) - { - if (i > 0) - sb.Append("

"); - - AccountComment c = a.Comments[i]; - - sb.AppendFormat("[{0} on {1}]
{2}", c.AddedBy, c.LastModified, c.Content); - } - - AddHtml(20, 180, 380, 190, sb.ToString(), true, true); - - goto case AdminGumpPage.AccountDetails; - } - case AdminGumpPage.AccountDetails_Tags: - { - if (!(state is Account a)) - break; - - AddHtml(10, 125, 400, 20, Color(Center("Tags"), LabelColor32)); - - AddButtonLabeled(20, 150, GetButtonID(5, 5), "Add Tag"); - - StringBuilder sb = new StringBuilder(); - - if (a.Tags.Count == 0) - sb.Append("There are no tags for this account."); - - for (int i = 0; i < a.Tags.Count; ++i) - { - if (i > 0) - sb.Append("
"); - - AccountTag tag = a.Tags[i]; - - sb.AppendFormat("{0} = {1}", tag.Name, tag.Value); - } - - AddHtml(20, 180, 380, 190, sb.ToString(), true, true); - - goto case AdminGumpPage.AccountDetails; - } - case AdminGumpPage.Firewall: - { - AddFirewallHeader(); - - List firewallEntries; - - if (m_List == null) - { - firewallEntries = Firewall.List; - m_List = Utility.CastListContravariant(firewallEntries); - } - else - firewallEntries = Utility.CastListCovariant(m_List); - - AddLabelCropped(12, 120, 358, 20, LabelHue, "IP Address"); - - if (listPage > 0) - AddButton(375, 122, 0x15E3, 0x15E7, GetButtonID(1, 0)); - else - AddImage(375, 122, 0x25EA); - - if ((listPage + 1) * 12 < firewallEntries.Count) - AddButton(392, 122, 0x15E1, 0x15E5, GetButtonID(1, 1)); - else - AddImage(392, 122, 0x25E6); - - if (firewallEntries.Count == 0) - AddLabel(12, 140, LabelHue, "The firewall list is empty."); - - for (int i = 0, index = listPage * 12; i < 12 && index >= 0 && index < firewallEntries.Count; ++i, ++index) - { - Firewall.IFirewallEntry firewallEntry = firewallEntries[index]; - - int offset = 140 + i * 20; - - AddLabelCropped(12, offset, 358, 20, LabelHue, firewallEntry.ToString()); - AddButton(380, offset - 1, 0xFA5, 0xFA7, GetButtonID(6, index + 4)); - } - - break; - } - case AdminGumpPage.FirewallInfo: - { - AddFirewallHeader(); - - if (!(state is Firewall.IFirewallEntry firewallEntry)) - break; - - AddHtml(10, 125, 400, 20, Color(Center(firewallEntry.ToString()), LabelColor32)); - - AddButtonLabeled(20, 150, GetButtonID(6, 3), "Remove"); - - AddHtml(10, 175, 400, 20, Color(Center("Potentially Affected Accounts"), LabelColor32)); - - List blockedAccts; - - if (m_List == null) - { - blockedAccts = new List(); - - foreach (IAccount ia in Accounts.GetAccounts()) - { - Account acct = (Account)ia; - - IPAddress[] loginList = acct.LoginIPs; - - bool contains = false; - - for (int i = 0; !contains && i < loginList.Length; ++i) - if (firewallEntry.IsBlocked(loginList[i])) - { - blockedAccts.Add(acct); - break; - } - } - - blockedAccts.Sort(AccountComparer.Instance); - m_List = Utility.CastListContravariant(blockedAccts); - } - else - blockedAccts = Utility.CastListCovariant(m_List); - - if (listPage > 0) - AddButton(375, 177, 0x15E3, 0x15E7, GetButtonID(1, 0)); - else - AddImage(375, 177, 0x25EA); - - if ((listPage + 1) * 12 < blockedAccts.Count) - AddButton(392, 177, 0x15E1, 0x15E5, GetButtonID(1, 1)); - else - AddImage(392, 177, 0x25E6); - - if (blockedAccts.Count == 0) - AddLabelCropped(12, 200, 398, 20, LabelHue, "No accounts found."); - - for (int i = 0, index = listPage * 9; i < 9 && index >= 0 && index < blockedAccts.Count; ++i, ++index) - { - Account a = blockedAccts[index]; - - int offset = 200 + i * 20; - - GetAccountInfo(a, out AccessLevel accessLevel, out bool online); - - AddLabelCropped(12, offset, 120, 20, LabelHue, a.Username); - AddLabelCropped(132, offset, 120, 20, LabelHue, FormatAccessLevel(accessLevel)); - - if (online) - AddLabelCropped(252, offset, 120, 20, GreenHue, "Online"); - else if (a.Banned) - AddLabelCropped(252, offset, 120, 20, RedHue, "Banned"); - else - AddLabelCropped(252, offset, 120, 20, RedHue, "Offline"); - - AddButton(380, offset - 1, 0xFA5, 0xFA7, GetButtonID(5, index + 56)); - } - - break; - } - } - } - - public void AddPageButton(int x, int y, int buttonID, string text, AdminGumpPage page, - params AdminGumpPage[] subPages) - { - bool isSelection = m_PageType == page; - - for (int i = 0; !isSelection && i < subPages.Length; ++i) - isSelection = m_PageType == subPages[i]; - - AddSelectedButton(x, y, buttonID, text, isSelection); - } - - public void AddSelectedButton(int x, int y, int buttonID, string text, bool isSelection) - { - AddButton(x, y - 1, isSelection ? 4006 : 4005, 4007, buttonID); - AddHtml(x + 35, y, 200, 20, Color(text, isSelection ? SelectedColor32 : LabelColor32)); - } - - public void AddButtonLabeled(int x, int y, int buttonID, string text) - { - AddButton(x, y - 1, 4005, 4007, buttonID); - AddHtml(x + 35, y, 240, 20, Color(text, LabelColor32)); - } - - public string Center(string text) => $"
{text}
"; - - public string Color(string text, int color) => $"{text}"; - - public void AddBlackAlpha(int x, int y, int width, int height) - { - AddImageTiled(x, y, width, height, 2624); - AddAlphaRegion(x, y, width, height); - } - - public int GetButtonID(int type, int index) => 1 + index * 11 + type; - - public static string FormatTimeSpan(TimeSpan ts) => $"{ts.Days:D2}:{ts.Hours % 24:D2}:{ts.Minutes % 60:D2}:{ts.Seconds % 60:D2}"; - - public static string FormatByteAmount(long totalBytes) - { - if (totalBytes > 1000000000) - return $"{(double)totalBytes / 1073741824:F1} GB"; - - if (totalBytes > 1000000) - return $"{(double)totalBytes / 1048576:F1} MB"; - - if (totalBytes > 1000) - return $"{(double)totalBytes / 1024:F1} KB"; - - return $"{totalBytes} Bytes"; - } - - public static void Initialize() - { - CommandSystem.Register("Admin", AccessLevel.Administrator, Admin_OnCommand); - } - - [Usage("Admin")] - [Description( - "Opens an interface providing server information and administration features including client, account, and firewall management.")] - public static void Admin_OnCommand(CommandEventArgs e) - { - e.Mobile.SendGump(new AdminGump(e.Mobile, AdminGumpPage.Clients)); - } - - public static int GetHueFor(Mobile m) - { - if (m == null) - return LabelHue; - - switch (m.AccessLevel) - { - case AccessLevel.Owner: - case AccessLevel.Developer: - case AccessLevel.Administrator: return 0x516; - case AccessLevel.Seer: return 0x144; - case AccessLevel.GameMaster: return 0x21; - case AccessLevel.Counselor: return 0x2; - default: - { - if (m.Kills >= 5) - return 0x21; - - return m.Criminal ? 0x3B1 : 0x58; - } - } - } - - public static string FormatAccessLevel(AccessLevel level) - { - int v = (int)level; - - if (v >= 0 && v < m_AccessLevelStrings.Length) - return m_AccessLevelStrings[v]; - - return "Unknown"; - } - - public void AddTextField(int x, int y, int width, int height, int index) - { - AddBackground(x - 2, y - 2, width + 4, height + 4, 0x2486); - AddTextEntry(x + 2, y + 2, width - 4, height - 4, 0, index, ""); - } - - public void AddClientHeader() - { - AddTextField(200, 20, 200, 20, 0); - AddButtonLabeled(200, 50, GetButtonID(4, 0), "Search For Name"); - AddButtonLabeled(200, 80, GetButtonID(4, 1), "Search For IP Address"); - } - - public void AddAccountHeader() - { - AddPage(1); - - AddLabel(200, 20, LabelHue, "Name:"); - AddTextField(250, 20, 150, 20, 0); - - AddLabel(200, 50, LabelHue, "Pass:"); - AddTextField(250, 50, 150, 20, 1); - - AddButtonLabeled(200, 80, GetButtonID(5, 6), "Add"); - AddButtonLabeled(290, 80, GetButtonID(5, 7), "Search"); - - AddButton(384, 84, 0x15E1, 0x15E5, 0, GumpButtonType.Page, 2); - - AddPage(2); - - AddButtonLabeled(200, 20, GetButtonID(5, 31), "View All: Inactive"); - AddButtonLabeled(200, 40, GetButtonID(5, 32), "View All: Banned"); - AddButtonLabeled(200, 60, GetButtonID(5, 26), "View All: Shared"); - AddButtonLabeled(200, 80, GetButtonID(5, 30), "View All: Empty"); - - AddButton(384, 84, 0x15E1, 0x15E5, 0, GumpButtonType.Page, 1); - - AddPage(0); - } - - public void AddFirewallHeader() - { - AddTextField(200, 20, 200, 20, 0); - AddButtonLabeled(320, 50, GetButtonID(6, 0), "Search"); - AddButtonLabeled(200, 50, GetButtonID(6, 1), "Add (Input)"); - AddButtonLabeled(200, 80, GetButtonID(6, 2), "Add (Target)"); - } - - private static List>> GetAllSharedAccounts() - { - Dictionary> table = new Dictionary>(); - - foreach (Account acct in Accounts.GetAccounts()) - { - IPAddress[] theirAddresses = acct.LoginIPs; - - for (int i = 0; i < theirAddresses.Length; ++i) - if (!table.ContainsKey(theirAddresses[i])) - table[theirAddresses[i]] = new List { acct }; - } - - List>> tableEntries = table.ToList(); - - for (int i = 0; i < tableEntries.Count; ++i) - { - KeyValuePair> kvp = tableEntries[i]; - List list = kvp.Value; - - if (kvp.Value.Count == 1) - list.RemoveAt(i--); - else - list.Sort(AccountComparer.Instance); - } - - tableEntries.Sort(SharedAccountComparer.Instance); - - return tableEntries; - } - - private static List GetSharedAccounts(IPAddress ipAddress) - { - List list = new List(); - - foreach (IAccount account in Accounts.GetAccounts()) - { - Account acct = (Account)account; - - IPAddress[] theirAddresses = acct.LoginIPs; - bool contains = false; - - for (int i = 0; !contains && i < theirAddresses.Length; ++i) - contains = ipAddress.Equals(theirAddresses[i]); - - if (contains) - list.Add(acct); - } - - list.Sort(AccountComparer.Instance); - return list; - } - - private static List GetSharedAccounts(IPAddress[] ipAddresses) - { - List list = new List(); - - foreach (Account acct in Accounts.GetAccounts()) - { - IPAddress[] theirAddresses = acct.LoginIPs; - bool contains = false; - - for (int i = 0; !contains && i < theirAddresses.Length; ++i) - { - IPAddress check = theirAddresses[i]; - - for (int j = 0; !contains && j < ipAddresses.Length; ++j) - contains = check.Equals(ipAddresses[j]); - } - - if (contains) - list.Add(acct); - } - - list.Sort(AccountComparer.Instance); - return list; - } - - public static void BanShared_Callback(Mobile from, bool okay, Account a) - { - if (from.AccessLevel < AccessLevel.Administrator) - return; - - string notice; - List list = null; - - if (okay) - { - list = GetSharedAccounts(a.LoginIPs); - - for (int i = 0; i < list.Count; ++i) - { - list[i].SetUnspecifiedBan(from); - list[i].Banned = true; - } - - notice = "All addresses in the list have been banned."; - } - else - { - notice = "You have chosen not to ban all shared accounts."; - } - - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access_ClientIPs, 0, null, notice, a)); - - if (okay) - from.SendGump(new BanDurationGump(list)); - } - - public static void AccountDelete_Callback(Mobile from, bool okay, Account a) - { - if (from.AccessLevel < AccessLevel.Administrator) - return; - - if (okay) - { - CommandLogging.WriteLine(from, "{0} {1} deleting account {2}", from.AccessLevel, CommandLogging.Format(from), - a.Username); - a.Delete(); - - from.SendGump(new AdminGump(from, AdminGumpPage.Accounts, 0, null, - $"{a.Username} : The account has been deleted.")); - } - else - { - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Information, 0, null, - "You have chosen not to delete the account.", a)); - } - } - - public static void ResendGump_Callback(Mobile from, List list, List rads, int page) - { - if (from.AccessLevel < AccessLevel.Administrator) - return; - - from.SendGump(new AdminGump(from, AdminGumpPage.Accounts, page, list, null, rads)); - } - - public static void Marked_Callback(Mobile from, bool okay, bool ban, List list, List rads, int page) - { - if (from.AccessLevel < AccessLevel.Administrator) - return; - - if (okay) - { - if (!ban) - NetState.Pause(); - - for (int i = 0; i < rads.Count; ++i) - { - Account acct = rads[i]; - - if (ban) - { - CommandLogging.WriteLine(from, "{0} {1} banning account {2}", from.AccessLevel, - CommandLogging.Format(from), acct.Username); - acct.SetUnspecifiedBan(from); - acct.Banned = true; - } - else - { - CommandLogging.WriteLine(from, "{0} {1} deleting account {2}", from.AccessLevel, - CommandLogging.Format(from), acct.Username); - acct.Delete(); - rads.RemoveAt(i--); - list.Remove(acct); - } - } - - if (!ban) - NetState.Resume(); - - from.SendGump(new NoticeGump(1060637, 30720, - $"You have {(ban ? "banned" : "deleted")} the account{(rads.Count == 1 ? "" : "s")}.", 0xFFC000, 420, - 280, () => ResendGump_Callback(from, list, rads, ban ? page : 0))); - - if (ban) - from.SendGump(new BanDurationGump(rads)); - } - else - { - from.SendGump(new NoticeGump(1060637, 30720, - $"You have chosen not to {(ban ? "ban" : "delete")} the account{(rads.Count == 1 ? "" : "s")}.", - 0xFFC000, 420, 280, () => ResendGump_Callback(from, list, rads, page))); - } - } - - public static void FirewallShared_Callback(Mobile from, bool okay, Account a) - { - if (from.AccessLevel < AccessLevel.Administrator) - return; - - string notice; - - if (okay) - { - for (int i = 0; i < a.LoginIPs.Length; ++i) - Firewall.Add(a.LoginIPs[i]); - - notice = "All addresses in the list have been firewalled."; - } - else - { - notice = "You have chosen not to firewall all addresses."; - } - - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access_ClientIPs, 0, null, notice, a)); - } - - public static void Firewall_Callback(Mobile from, bool okay, Account a, object toFirewall) - { - if (from.AccessLevel < AccessLevel.Administrator) - return; - - string notice; - - if (okay) - { - Firewall.Add(toFirewall); - - notice = $"{toFirewall} : Added to firewall."; - } - else - { - notice = "You have chosen not to firewall the address."; - } - - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access_ClientIPs, 0, null, notice, a)); - } - - public static void RemoveLoginIP_Callback(Mobile from, bool okay, Account a, IPAddress ip) - { - if (from.AccessLevel < AccessLevel.Administrator) - return; - - string notice; - - if (okay) - { - IPAddress[] ips = a.LoginIPs; - - if (ips.Length != 0 && Equals(ip, ips[0]) && AccountHandler.IPTable.ContainsKey(ips[0])) - --AccountHandler.IPTable[ip]; - - List newList = new List(ips); - newList.Remove(ip); - a.LoginIPs = newList.ToArray(); - - notice = $"{ip} : Removed address."; - } - else - { - notice = "You have chosen not to remove the address."; - } - - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access_ClientIPs, 0, null, notice, a)); - } - - public static void RemoveLoginIPs_Callback(Mobile from, bool okay, Account a) - { - if (from.AccessLevel < AccessLevel.Administrator) - return; - - string notice; - - if (okay) - { - IPAddress[] ips = a.LoginIPs; - - if (ips.Length != 0 && AccountHandler.IPTable.ContainsKey(ips[0])) - --AccountHandler.IPTable[ips[0]]; - - a.LoginIPs = Array.Empty(); - - notice = "All addresses in the list have been removed."; - } - else - { - notice = "You have chosen not to clear all addresses."; - } - - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access_ClientIPs, 0, null, notice, a)); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - int val = info.ButtonID - 1; - - if (val < 0) - return; - - Mobile from = m_From; - - if (from.AccessLevel < AccessLevel.Administrator) - return; - - if (m_PageType == AdminGumpPage.Accounts) - { - List list = Utility.CastListCovariant(m_List); - - if (list != null && m_State is List rads) - for (int i = 0, v = m_ListPage * 12; i < 12 && v < list.Count; ++i, ++v) - { - Account obj = list[v]; - - if (info.IsSwitched(v)) - { - if (!rads.Contains(obj)) - rads.Add(obj); - } - else if (rads.Contains(obj)) - { - rads.Remove(obj); - } - } - } - - int type = val % 11; - int index = val / 11; - - switch (type) - { - case 0: - { - AdminGumpPage page; - - switch (index) - { - case 0: - page = AdminGumpPage.Information_General; - break; - case 1: - page = AdminGumpPage.Administer; - break; - case 2: - page = AdminGumpPage.Clients; - break; - case 3: - page = AdminGumpPage.Accounts; - break; - case 4: - page = AdminGumpPage.Firewall; - break; - case 5: - page = AdminGumpPage.Information_Perf; - break; - default: return; - } - - from.SendGump(new AdminGump(from, page)); - break; - } - case 1: - { - switch (index) - { - case 0: - { - if (m_List != null && m_ListPage > 0) - from.SendGump(new AdminGump(from, m_PageType, m_ListPage - 1, m_List, null, m_State)); - - break; - } - case 1: - { - if (m_List != null /*&& (m_ListPage + 1) * 12 < m_List.Count*/) - from.SendGump(new AdminGump(from, m_PageType, m_ListPage + 1, m_List, null, m_State)); - - break; - } - } - - break; - } - case 3: - { - string notice = null; - AdminGumpPage page = AdminGumpPage.Administer; - - if (index >= 500) - page = AdminGumpPage.Administer_Access_Lockdown; - else if (index >= 400) - page = AdminGumpPage.Administer_Commands; - else if (index >= 300) - page = AdminGumpPage.Administer_Access; - else if (index >= 200) - page = AdminGumpPage.Administer_Server; - else if (index >= 100) - page = AdminGumpPage.Administer_WorldBuilding; - - switch (index) - { - case 0: - page = AdminGumpPage.Administer_WorldBuilding; - break; - case 1: - page = AdminGumpPage.Administer_Server; - break; - case 2: - page = AdminGumpPage.Administer_Access; - break; - case 3: - page = AdminGumpPage.Administer_Commands; - break; - - case 100: - InvokeCommand("DocGen"); - notice = "Documentation has been generated."; - break; - case 101: - InvokeCommand("TelGen"); - notice = "Teleporters have been generated."; - break; - case 102: - InvokeCommand("MoonGen"); - notice = "Moongates have been generated."; - break; - case 103: - InvokeCommand("UOAMVendors"); - notice = "Vendor spawners have been generated."; - break; - case 104: - InvokeCommand("DoorGen"); - notice = "Doors have been generated."; - break; - case 105: - InvokeCommand("SignGen"); - notice = "Signs have been generated."; - break; - case 106: - InvokeCommand("Decorate"); - notice = "Decoration has been generated."; - break; - case 107: - InvokeCommand("RebuildCategorization"); - notice = "Categorization menu has been regenerated. The server should be restarted."; - break; - - case 110: - InvokeCommand("Freeze"); - notice = "Target bounding points."; - break; - case 120: - InvokeCommand("Unfreeze"); - notice = "Target bounding points."; - break; - - case 200: - InvokeCommand("Save"); - notice = "The world has been saved."; - break; - case 201: - Shutdown(false, true); - break; - case 202: - Shutdown(false, false); - break; - case 203: - Shutdown(true, true); - break; - case 204: - Shutdown(true, false); - break; - case 210: - case 211: - { - string text = info.GetTextEntry(0)?.Text.Trim(); - - if (string.IsNullOrEmpty(text)) - { - notice = "You must enter text to broadcast it."; - } - else - { - notice = "Your message has been broadcasted."; - InvokeCommand($"{(index == 210 ? "BC" : "SM")} {text}"); - } - - break; - } - - case 300: - InvokeCommand("Kick"); - notice = "Target the player to kick."; - break; - case 301: - InvokeCommand("Ban"); - notice = "Target the player to ban."; - break; - case 302: - InvokeCommand("Firewall"); - notice = "Target the player to firewall."; - break; - - case 303: - page = AdminGumpPage.Administer_Access_Lockdown; - break; - - case 310: - InvokeCommand("Set AccessLevel Player"); - notice = "Target the player to change their access level. (Player)"; - break; - case 311: - InvokeCommand("Set AccessLevel Counselor"); - notice = "Target the player to change their access level. (Counselor)"; - break; - case 312: - InvokeCommand("Set AccessLevel GameMaster"); - notice = "Target the player to change their access level. (Game Master)"; - break; - case 313: - InvokeCommand("Set AccessLevel Seer"); - notice = "Target the player to change their access level. (Seer)"; - break; - - case 314: - { - if (from.AccessLevel > AccessLevel.Administrator) - { - InvokeCommand("Set AccessLevel Administrator"); - notice = "Target the player to change their access level. (Administrator)"; - } - - break; - } - - case 315: - { - if (from.AccessLevel > AccessLevel.Developer) - { - InvokeCommand("Set AccessLevel Developer"); - notice = "Target the player to change their access level. (Developer)"; - } - - break; - } - - case 316: - { - if (from.AccessLevel >= AccessLevel.Owner) - { - InvokeCommand("Set AccessLevel Owner"); - notice = "Target the player to change their access level. (Owner)"; - } - - break; - } - - case 400: - notice = "Enter search terms to add objects."; - break; - case 401: - InvokeCommand("Remove"); - notice = "Target the item or mobile to remove."; - break; - case 402: - InvokeCommand("Dupe"); - notice = "Target the item to dupe."; - break; - case 403: - InvokeCommand("DupeInBag"); - notice = "Target the item to dupe. The item will be duped at it's current location."; - break; - case 404: - InvokeCommand("Props"); - notice = "Target the item or mobile to inspect."; - break; - case 405: - InvokeCommand("Skills"); - notice = "Target a mobile to view their skills."; - break; - case 406: - InvokeCommand("Set Blessed False"); - notice = "Target the mobile to make mortal."; - break; - case 407: - InvokeCommand("Set Blessed True"); - notice = "Target the mobile to make immortal."; - break; - case 408: - InvokeCommand("Set Squelched True"); - notice = "Target the mobile to squelch."; - break; - case 409: - InvokeCommand("Set Squelched False"); - notice = "Target the mobile to unsquelch."; - break; - case 410: - InvokeCommand("Set Frozen True"); - notice = "Target the mobile to freeze."; - break; - case 411: - InvokeCommand("Set Frozen False"); - notice = "Target the mobile to unfreeze."; - break; - case 412: - InvokeCommand("Set Hidden True"); - notice = "Target the mobile to hide."; - break; - case 413: - InvokeCommand("Set Hidden False"); - notice = "Target the mobile to unhide."; - break; - case 414: - InvokeCommand("Kill"); - notice = "Target the mobile to kill."; - break; - case 415: - InvokeCommand("Resurrect"); - notice = "Target the mobile to resurrect."; - break; - case 416: - InvokeCommand("Move"); - notice = "Target the item or mobile to move."; - break; - case 417: - InvokeCommand("Wipe"); - notice = "Target bounding points."; - break; - case 418: - InvokeCommand("Tele"); - notice = "Choose your destination."; - break; - case 419: - InvokeCommand("Multi Tele"); - notice = "Choose your destination."; - break; - - case 500: - case 501: - case 502: - case 503: - case 504: - { - AccountHandler.LockdownLevel = (AccessLevel)(index - 500); - - if (AccountHandler.LockdownLevel > AccessLevel.Player) - notice = "The lockdown level has been changed."; - else - notice = "The server is now accessible to everyone."; - - break; - } - - case 510: - { - AccessLevel level = AccountHandler.LockdownLevel; - - if (level > AccessLevel.Player) - { - List clients = TcpServer.Instances; - int count = 0; - - for (int i = 0; i < clients.Count; ++i) - { - NetState ns = clients[i]; - IAccount a = ns.Account; - - if (a == null) - continue; - - bool hasAccess = false; - - if (a.AccessLevel >= level) - hasAccess = true; - else - for (int j = 0; !hasAccess && j < a.Length; ++j) - { - Mobile m = a[j]; - - if (m?.AccessLevel >= level) - hasAccess = true; - } - - if (!hasAccess) - { - ns.Dispose(); - ++count; - } - } - - if (count == 0) - notice = "Nobody without access was found to disconnect."; - else - notice = $"Number of players disconnected: {count}"; - } - else - { - notice = "The server is not currently locked down."; - } - - break; - } - } - - from.SendGump(new AdminGump(from, page, 0, null, notice)); - - switch (index) - { - case 400: - InvokeCommand("Add"); - break; - case 111: - InvokeCommand("FreezeWorld"); - break; - case 112: - InvokeCommand("FreezeMap"); - break; - case 121: - InvokeCommand("UnfreezeWorld"); - break; - case 122: - InvokeCommand("UnfreezeMap"); - break; - } - - break; - } - case 4: - { - switch (index) - { - case 0: - case 1: - { - bool forName = index == 0; - - List results = new List(); - - string match = info.GetTextEntry(0)?.Text.Trim().ToLower(); - string notice = null; - - if (string.IsNullOrEmpty(match)) - { - notice = $"You must enter {(forName ? "a name" : "an ip address")} to search."; - } - else - { - List instances = TcpServer.Instances; - - for (int i = 0; i < instances.Count; ++i) - { - NetState ns = instances[i]; - - bool isMatch; - - if (forName) - { - Mobile m = ns.Mobile; - IAccount a = ns.Account; - - isMatch = m?.Name.ToLower().IndexOf(match) >= 0 - || a?.Username.ToLower().IndexOf(match) >= 0; - } - else - { - isMatch = ns.ToString().IndexOf(match) >= 0; - } - - if (isMatch) - results.Add(ns); - } - - results.Sort(NetStateComparer.Instance); - } - - if (results.Count == 1) - { - NetState ns = results[0]; - object state = ns.Mobile ?? (object)ns.Account; - - if (state is Mobile) - from.SendGump(new AdminGump(from, AdminGumpPage.ClientInfo, 0, null, "One match found.", - state)); - else if (state is Account) - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Information, 0, null, - "One match found.", state)); - else - from.SendGump(new AdminGump(from, AdminGumpPage.Clients, 0, - Utility.CastListContravariant(results), "One match found.")); - } - else - { - from.SendGump(new AdminGump(from, AdminGumpPage.Clients, 0, - Utility.CastListContravariant(results), - notice ?? (results.Count == 0 ? "Nothing matched your search terms." : null))); - } - - break; - } - default: - { - index -= 2; - - if (m_List != null && index >= 0 && index < m_List.Count) - { - if (!(m_List[index] is NetState ns)) - break; - - Mobile m = ns.Mobile; - Account a = ns.Account as Account; - - if (m != null) - from.SendGump(new AdminGump(from, AdminGumpPage.ClientInfo, 0, null, null, m)); - else if (a != null) - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Information, 0, null, - null, a)); - } - - break; - } - } - - break; - } - case 5: - { - switch (index) - { - case 0: - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Information, 0, null, null, - m_State)); - break; - case 1: - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Characters, 0, null, null, - m_State)); - break; - case 2: - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Comments, 0, null, null, - m_State)); - break; - case 3: - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Tags, 0, null, null, m_State)); - break; - case 13: - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access, 0, null, null, m_State)); - break; - case 14: - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access_ClientIPs, 0, null, null, - m_State)); - break; - case 15: - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access_Restrictions, 0, null, - null, m_State)); - break; - case 4: - from.Prompt = new AddCommentPrompt(m_State as Account); - from.SendMessage("Enter the new account comment."); - break; - case 5: - from.Prompt = new AddTagNamePrompt(m_State as Account); - from.SendMessage("Enter the new tag name."); - break; - case 6: - { - string un = info.GetTextEntry(0)?.Text.Trim(); - string pw = info.GetTextEntry(1)?.Text.Trim(); - - Account dispAccount = null; - string notice; - - if (string.IsNullOrEmpty(un)) - { - notice = "You must enter a username to add an account."; - } - else if (string.IsNullOrEmpty(pw)) - { - notice = "You must enter a password to add an account."; - } - else - { - IAccount account = Accounts.GetAccount(un); - - if (account != null) - { - notice = "There is already an account with that username."; - } - else - { - dispAccount = new Account(un, pw); - notice = $"{un} : Account added."; - CommandLogging.WriteLine(from, "{0} {1} adding new account: {2}", from.AccessLevel, - CommandLogging.Format(from), un); - } - } - - from.SendGump(new AdminGump(from, - dispAccount != null ? AdminGumpPage.AccountDetails_Information : m_PageType, m_ListPage, - m_List, notice, dispAccount ?? m_State)); - break; - } - case 7: - { - List results; - - TextRelay matchEntry = info.GetTextEntry(0); - string match = matchEntry?.Text.Trim().ToLower(); - - if (string.IsNullOrEmpty(match)) - { - results = Accounts.GetAccounts().ToList(); - results.Sort(AccountComparer.Instance); - } - else - { - results = Accounts.GetAccounts().Where(acct => acct.Username.ToLower().IndexOf(match) >= 0).ToList(); - results.Sort(AccountComparer.Instance); - } - - if (results.Count == 1) - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Information, 0, null, - "One match found.", results[0])); - else - from.SendGump(new AdminGump(from, AdminGumpPage.Accounts, 0, - Utility.CastListContravariant(results), - results.Count == 0 ? "Nothing matched your search terms." : null, - new List())); - - break; - } - case 8: - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_ChangePassword, 0, null, null, - m_State)); - break; - case 9: - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_ChangeAccess, 0, null, null, - m_State)); - break; - case 10: - case 11: - { - if (!(m_State is Account a)) - break; - - a.SetUnspecifiedBan(from); - a.Banned = index == 10; - CommandLogging.WriteLine(from, "{0} {1} {3} account {2}", from.AccessLevel, - CommandLogging.Format(from), a.Username, a.Banned ? "banning" : "unbanning"); - from.SendGump(new AdminGump(from, m_PageType, m_ListPage, m_List, - $"The account has been {(a.Banned ? "banned" : "unbanned")}.", m_State)); - - if (index == 10) - from.SendGump(new BanDurationGump(a)); - - break; - } - case 12: - { - if (!(m_State is Account a)) - break; - - TextRelay passwordEntry = info.GetTextEntry(0); - TextRelay confirmEntry = info.GetTextEntry(1); - - string password = passwordEntry?.Text.Trim(); - string confirm = confirmEntry?.Text.Trim(); - - string notice; - AdminGumpPage page = AdminGumpPage.AccountDetails_ChangePassword; - - if (string.IsNullOrEmpty(password)) - { - notice = "You must enter the password."; - } - else if (confirm != password) - { - notice = - "You must confirm the password. That field must precisely match the password field."; - } - else - { - notice = "The password has been changed."; - a.SetPassword(password); - page = AdminGumpPage.AccountDetails_Information; - CommandLogging.WriteLine(from, "{0} {1} changing password of account {2}", from.AccessLevel, - CommandLogging.Format(from), a.Username); - } - - from.SendGump(new AdminGump(from, page, 0, null, notice, m_State)); - - break; - } - case 16: // view shared - { - if (!(m_State is Account a)) - break; - - List list = GetSharedAccounts(a.LoginIPs); - - if (list.Count > 1 || (list.Count == 1 && !list.Contains(a))) - from.SendGump(new AdminGump(from, AdminGumpPage.Accounts, 0, - Utility.CastListContravariant(list), null, new List())); - else if (a.LoginIPs.Length > 0) - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access_ClientIPs, 0, null, - "There are no other accounts which share an address with this one.", m_State)); - else - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access_ClientIPs, 0, null, - "This account has not yet been accessed.", m_State)); - - break; - } - case 17: // ban shared - { - if (!(m_State is Account a)) - break; - - List list = GetSharedAccounts(a.LoginIPs); - - if (list.Count > 0) - { - StringBuilder sb = new StringBuilder(); - - sb.AppendFormat("You are about to ban {0} account{1}. Do you wish to continue?", list.Count, - list.Count != 1 ? "s" : ""); - - for (int i = 0; i < list.Count; ++i) - sb.AppendFormat("
- {0}", list[i].Username); - - from.SendGump(new WarningGump(1060635, 30720, sb.ToString(), 0xFFC000, 420, 400, - okay => BanShared_Callback(from, okay, a))); - } - else if (a.LoginIPs.Length > 0) - { - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access_ClientIPs, 0, null, - "There are no accounts which share an address with this one.", m_State)); - } - else - { - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access_ClientIPs, 0, null, - "This account has not yet been accessed.", m_State)); - } - - break; - } - case 18: // firewall all - { - if (!(m_State is Account a)) - break; - - if (a.LoginIPs.Length > 0) - from.SendGump(new WarningGump(1060635, 30720, - $"You are about to firewall {a.LoginIPs.Length} address{(a.LoginIPs.Length != 1 ? "s" : "")}. Do you wish to continue?", - 0xFFC000, 420, 400, okay => FirewallShared_Callback(from, okay, a))); - else - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access_ClientIPs, 0, null, - "This account has not yet been accessed.", m_State)); - - break; - } - case 19: // add - { - if (!(m_State is Account a)) - break; - - TextRelay entry = info.GetTextEntry(0); - string ip = entry?.Text.Trim(); - - string notice; - - if (string.IsNullOrEmpty(ip)) - { - notice = "You must enter an address to add."; - } - else - { - string[] list = a.IPRestrictions; - - bool contains = false; - for (int i = 0; !contains && i < list.Length; ++i) - contains = list[i] == ip; - - if (contains) - { - notice = "That address is already contained in the list."; - } - else - { - string[] newList = new string[list.Length + 1]; - - for (int i = 0; i < list.Length; ++i) - newList[i] = list[i]; - - newList[list.Length] = ip; - - a.IPRestrictions = newList; - - notice = $"{ip} : Added to restriction list."; - } - } - - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access_Restrictions, 0, null, - notice, m_State)); - - break; - } - case 20: // Change access level - case 21: - case 22: - case 23: - case 24: - { - if (!(m_State is Account a)) - break; - - var newLevel = index switch - { - 21 => AccessLevel.Counselor, - 22 => AccessLevel.GameMaster, - 23 => AccessLevel.Seer, - 24 => AccessLevel.Administrator, - 33 => AccessLevel.Developer, - 34 => AccessLevel.Owner, - _ => AccessLevel.Player // 20 - }; - - if (newLevel < from.AccessLevel || from.AccessLevel == AccessLevel.Owner) - { - a.AccessLevel = newLevel; - - CommandLogging.WriteLine(from, "{0} {1} changing access level of account {2} to {3}", - from.AccessLevel, CommandLogging.Format(from), a.Username, a.AccessLevel); - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Information, 0, null, - "The access level has been changed.", m_State)); - } - - break; - } - case 25: - { - if (!(m_State is Account a)) - break; - - from.SendGump(new WarningGump(1060635, 30720, - $"
Account of {a.Username}

You are about to permanently delete the account. Likewise, all characters on the account will be deleted, including equipped, inventory, and banked items. Any houses tied to the account will be demolished.

Do you wish to continue?", - 0xFFC000, 420, 280, okay => AccountDelete_Callback(from, okay, a))); - break; - } - case 26: // View all shared accounts - { - from.SendGump(new AdminGump(from, AdminGumpPage.Accounts_Shared)); - break; - } - case 27: // Ban marked - { - List list = m_List; - - if (list == null || !(m_State is List rads)) - break; - - if (rads.Count > 0) - from.SendGump(new WarningGump(1060635, 30720, - $"You are about to ban {rads.Count} marked account{(rads.Count == 1 ? "" : "s")}. Be cautioned, the only way to reverse this is by hand--manually unbanning each account.

Do you wish to continue?", - 0xFFC000, 420, 280, okay => Marked_Callback(from, okay, true, list, rads, m_ListPage))); - else - from.SendGump(new NoticeGump(1060637, 30720, - "You have not yet marked any accounts. Place a check mark next to the accounts you wish to ban and then try again.", - 0xFFC000, 420, 280, () => ResendGump_Callback(from, list, rads, m_ListPage))); - - break; - } - case 28: // Delete marked - { - List list = m_List; - - if (list == null || !(m_State is List rads)) - break; - - if (rads.Count > 0) - from.SendGump(new WarningGump(1060635, 30720, - string.Format( - "You are about to permanently delete {0} marked account{1}. Likewise, all characters on the account{1} will be deleted, including equipped, inventory, and banked items. Any houses tied to the account{1} will be demolished.

Do you wish to continue?", - rads.Count, rads.Count == 1 ? "" : "s"), 0xFFC000, 420, 280, okay => Marked_Callback(from, okay, false, list, rads, m_ListPage))); - else - from.SendGump(new NoticeGump(1060637, 30720, - "You have not yet marked any accounts. Place a check mark next to the accounts you wish to ban and then try again.", - 0xFFC000, 420, 280, () => ResendGump_Callback(from, list, rads, m_ListPage))); - - break; - } - case 29: // Mark all - { - if (m_List == null || !(m_State is List)) - break; - - from.SendGump(new AdminGump(from, AdminGumpPage.Accounts, m_ListPage, m_List, null, - m_List.ToList())); - - break; - } - case 30: // View all empty accounts - { - List results = new List(); - - foreach (Account acct in Accounts.GetAccounts()) - { - bool empty = true; - - for (int i = 0; empty && i < acct.Length; ++i) - empty = acct[i] == null; - - if (empty) - results.Add(acct); - } - - if (results.Count == 1) - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Information, 0, null, - "One match found.", results[0])); - else - from.SendGump(new AdminGump(from, AdminGumpPage.Accounts, 0, results, - results.Count == 0 ? "Nothing matched your search terms." : null, new List())); - - break; - } - case 31: // View all inactive accounts - { - List results = new List(); - - foreach (Account acct in Accounts.GetAccounts()) - if (acct.Inactive) - results.Add(acct); - - if (results.Count == 1) - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Information, 0, null, - "One match found.", results[0])); - else - from.SendGump(new AdminGump(from, AdminGumpPage.Accounts, 0, results, - results.Count == 0 ? "Nothing matched your search terms." : null, new List())); - - break; - } - case 32: // View all banned accounts - { - List results = new List(); - - foreach (Account acct in Accounts.GetAccounts()) - if (acct.Banned) - results.Add(acct); - - if (results.Count == 1) - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Information, 0, null, - "One match found.", results[0])); - else - from.SendGump(new AdminGump(from, AdminGumpPage.Accounts, 0, results, - results.Count == 0 ? "Nothing matched your search terms." : null, new List())); - - break; - } - case 33: // Change access level (extended) - case 34: - { - goto case 20; - } - case 35: // Unmark house owners - { - List list = m_List; - List rads = m_State as List; - - if (list == null || rads == null) - break; - - List newRads = new List(); - - foreach (Account acct in rads) - { - bool hasHouse = false; - - for (int i = 0; i < acct.Length && !hasHouse; ++i) - if (acct[i] != null && BaseHouse.HasHouse(acct[i])) - hasHouse = true; - - if (!hasHouse) - newRads.Add(acct); - } - - from.SendGump(new AdminGump(from, AdminGumpPage.Accounts, m_ListPage, m_List, null, newRads)); - - break; - } - case 36: // Clear login addresses - { - if (!(m_State is Account a)) - break; - - IPAddress[] ips = a.LoginIPs; - - if (ips.Length == 0) - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access_ClientIPs, 0, null, - "This account has not yet been accessed.", m_State)); - else - from.SendGump(new WarningGump(1060635, 30720, - $"You are about to clear the address list for account {a} containing {ips.Length} {(ips.Length == 1 ? "entry" : "entries")}. Do you wish to continue?", - 0xFFC000, 420, 280, okay => RemoveLoginIPs_Callback(from, okay, a))); - - break; - } - default: - { - index -= 50; - - if (m_State is Account a && index >= 0 && index < a.Length) - { - Mobile m = a[index]; - - if (m != null) - from.SendGump(new AdminGump(from, AdminGumpPage.ClientInfo, 0, null, null, m)); - } - else - { - index -= 6; - - if (m_List != null && index >= 0 && index < m_List.Count) - { - if (m_List[index] is Account) - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Information, 0, null, - null, m_List[index])); - else if (m_List[index] is KeyValuePair> kvp) - from.SendGump(new AdminGump(from, AdminGumpPage.Accounts, 0, - Utility.CastListContravariant(kvp.Value), null, new List())); - } - } - - break; - } - } - - break; - } - case 6: - { - switch (index) - { - case 0: - { - TextRelay matchEntry = info.GetTextEntry(0); - string match = matchEntry?.Text.Trim(); - - string notice = null; - List results = new List(); - - if (string.IsNullOrEmpty(match)) - notice = "You must enter a username to search."; - else - for (int i = 0; i < Firewall.List.Count; ++i) - { - string check = Firewall.List[i].ToString(); - - if (check?.IndexOf(match) >= 0) - results.Add(Firewall.List[i]); - } - - if (results.Count == 1) - from.SendGump(new AdminGump(from, AdminGumpPage.FirewallInfo, 0, null, "One match found.", - results[0])); - else if (results.Count > 1) - from.SendGump(new AdminGump(from, AdminGumpPage.Firewall, 0, results, - $"Search results for : {match}", m_State)); - else - from.SendGump(new AdminGump(from, m_PageType, m_ListPage, m_List, - notice ?? "Nothing matched your search terms.", m_State)); - - break; - } - case 1: - { - TextRelay relay = info.GetTextEntry(0); - string text = relay?.Text.Trim(); - - if (string.IsNullOrEmpty(text)) - { - from.SendGump(new AdminGump(from, m_PageType, m_ListPage, m_List, - "You must enter an address or pattern to add.", m_State)); - } - else if (!Utility.IsValidIP(text)) - { - from.SendGump(new AdminGump(from, m_PageType, m_ListPage, m_List, - "That is not a valid address or pattern.", m_State)); - } - else - { - object toAdd = Firewall.ToFirewallEntry(text); - - CommandLogging.WriteLine(from, "{0} {1} firewalling {2}", from.AccessLevel, - CommandLogging.Format(from), toAdd); - - Firewall.Add(toAdd); - from.SendGump(new AdminGump(from, AdminGumpPage.FirewallInfo, 0, null, - $"{toAdd} : Added to firewall.", toAdd)); - } - - break; - } - case 2: - { - InvokeCommand("Firewall"); - from.SendGump(new AdminGump(from, m_PageType, m_ListPage, m_List, - "Target the player to firewall.", m_State)); - break; - } - case 3: - { - if (m_State is Firewall.IFirewallEntry) - { - CommandLogging.WriteLine(from, "{0} {1} removing {2} from firewall list", from.AccessLevel, - CommandLogging.Format(from), m_State); - - Firewall.Remove(m_State); - from.SendGump(new AdminGump(from, AdminGumpPage.Firewall, 0, null, - $"{m_State} : Removed from firewall.")); - } - - break; - } - default: - { - index -= 4; - - if (m_List != null && index >= 0 && index < m_List.Count) - from.SendGump(new AdminGump(from, AdminGumpPage.FirewallInfo, 0, null, null, m_List[index])); - - break; - } - } - - break; - } - case 7: - { - if (!(m_State is Mobile m)) - break; - - string notice = null; - bool sendGump = true; - - switch (index) - { - case 0: - { - Map map = m.Map; - Point3D loc = m.Location; - - if (map == null || map == Map.Internal) - { - map = m.LogoutMap; - loc = m.LogoutLocation; - } - - if (map != null && map != Map.Internal) - { - from.MoveToWorld(loc, map); - notice = "You have been teleported to their location."; - } - - break; - } - case 1: - { - m.MoveToWorld(from.Location, from.Map); - notice = "They have been teleported to your location."; - break; - } - case 2: - { - NetState ns = m.NetState; - - if (ns != null) - { - CommandLogging.WriteLine(from, "{0} {1} {2} {3}", from.AccessLevel, - CommandLogging.Format(from), "kicking", CommandLogging.Format(m)); - ns.Dispose(); - notice = "They have been kicked."; - } - else - { - notice = "They are already disconnected."; - } - - break; - } - case 3: - { - if (m.Account is Account a) - { - CommandLogging.WriteLine(from, "{0} {1} {2} {3}", from.AccessLevel, - CommandLogging.Format(from), "banning", CommandLogging.Format(m)); - a.Banned = true; - - NetState ns = m.NetState; - - ns?.Dispose(); - - notice = "They have been banned."; - } - - break; - } - case 6: - { - Properties.SetValue(from, m, "Blessed", "False"); - notice = "They are now mortal."; - break; - } - case 7: - { - Properties.SetValue(from, m, "Blessed", "True"); - notice = "They are now immortal."; - break; - } - case 8: - { - Properties.SetValue(from, m, "Squelched", "True"); - notice = "They are now squelched."; - break; - } - case 9: - { - Properties.SetValue(from, m, "Squelched", "False"); - notice = "They are now unsquelched."; - break; - } - case 10: - { - Properties.SetValue(from, m, "Hidden", "True"); - notice = "They are now hidden."; - break; - } - case 11: - { - Properties.SetValue(from, m, "Hidden", "False"); - notice = "They are now unhidden."; - break; - } - case 12: - { - CommandLogging.WriteLine(from, "{0} {1} killing {2}", from.AccessLevel, - CommandLogging.Format(from), CommandLogging.Format(m)); - m.Kill(); - notice = "They have been killed."; - break; - } - case 13: - { - CommandLogging.WriteLine(from, "{0} {1} resurrecting {2}", from.AccessLevel, - CommandLogging.Format(from), CommandLogging.Format(m)); - m.Resurrect(); - notice = "They have been resurrected."; - break; - } - case 14: - { - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Information, 0, null, null, - m.Account)); - sendGump = false; - break; - } - } - - if (sendGump) - from.SendGump(new AdminGump(from, AdminGumpPage.ClientInfo, 0, null, notice, m_State)); - - switch (index) - { - case 3: - { - if (m.Account is Account a) - from.SendGump(new BanDurationGump(a)); - - break; - } - case 4: - { - from.SendGump(new PropertiesGump(from, m)); - break; - } - case 5: - { - from.SendGump(new SkillsGump(from, m)); - break; - } - } - - break; - } - case 8: - { - if (m_List != null && index >= 0 && index < m_List.Count) - { - if (!(m_State is Account a)) - break; - - if (m_PageType == AdminGumpPage.AccountDetails_Access_ClientIPs) - { - from.SendGump(new WarningGump(1060635, 30720, - $"You are about to firewall {m_List[index]}. All connection attempts from a matching IP will be refused. Are you sure?", - 0xFFC000, 420, 280, okay => Firewall_Callback(from, okay, a, m_List[index]))); - } - else if (m_PageType == AdminGumpPage.AccountDetails_Access_Restrictions) - { - List list = a.IPRestrictions.ToList(); - list.Remove(m_List[index] as string); - a.IPRestrictions = list.ToArray(); - - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access_Restrictions, 0, null, - $"{m_List[index]} : Removed from list.", a)); - } - } - - break; - } - case 9: - { - if (m_List != null && index >= 0 && index < m_List.Count) - if (m_PageType == AdminGumpPage.AccountDetails_Access_ClientIPs) - { - object obj = m_List[index]; - - if (!(obj is IPAddress ip)) - break; - - if (!(m_State is Account a)) - break; - - List list = GetSharedAccounts(ip); - - if (list.Count > 1 || (list.Count == 1 && !list.Contains(a))) - from.SendGump(new AdminGump(from, AdminGumpPage.Accounts, 0, - Utility.CastListContravariant(list), null, new List())); - else - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access_ClientIPs, 0, null, - "There are no other accounts which share that address.", a)); - } - - break; - } - case 10: - { - if (m_List != null && index >= 0 && index < m_List.Count) - if (m_PageType == AdminGumpPage.AccountDetails_Access_ClientIPs) - { - IPAddress ip = m_List[index] as IPAddress; - - if (ip == null) - break; - - if (!(m_State is Account a)) - break; - - from.SendGump(new WarningGump(1060635, 30720, - $"You are about to remove address {ip} from account {a}. Do you wish to continue?", 0xFFC000, - 420, 280, okay => RemoveLoginIP_Callback(from, okay, a, ip))); - } - - break; - } - } - } - - private void Shutdown(bool restart, bool save) - { - CommandLogging.WriteLine(m_From, "{0} {1} shutting down server (Restart: {2}) (Save: {3})", m_From.AccessLevel, - CommandLogging.Format(m_From), restart, save); - - if (save) - InvokeCommand("Save"); - - Core.Kill(restart); - } - - private void InvokeCommand(string c) - { - CommandSystem.Handle(m_From, $"{CommandSystem.Prefix}{c}"); - } - - public static void GetAccountInfo(IAccount a, out AccessLevel accessLevel, out bool online) - { - accessLevel = a.AccessLevel; - online = false; - - for (int j = 0; j < a.Length; ++j) - { - Mobile check = a[j]; - - if (check == null) - continue; - - if (check.AccessLevel > accessLevel) - accessLevel = check.AccessLevel; - - if (check.NetState != null) - online = true; - } - } - - private class SharedAccountComparer : IComparer>> - { - public static readonly IComparer>> Instance = new SharedAccountComparer(); - - public int Compare(KeyValuePair> x, KeyValuePair> y) => x.Value.Count - y.Value.Count; - } - - private class AddCommentPrompt : Prompt - { - private readonly Account m_Account; - - public AddCommentPrompt(Account acct) => m_Account = acct; - - public override void OnCancel(Mobile from) - { - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Comments, 0, null, - "Request to add comment was canceled.", m_Account)); - } - - public override void OnResponse(Mobile from, string text) - { - if (m_Account != null) - { - m_Account.Comments.Add(new AccountComment(from.RawName, text)); - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Comments, 0, null, "Comment added.", - m_Account)); - } - } - } - - private class AddTagNamePrompt : Prompt - { - private readonly Account m_Account; - - public AddTagNamePrompt(Account acct) => m_Account = acct; - - public override void OnCancel(Mobile from) - { - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Tags, 0, null, - "Request to add tag was canceled.", m_Account)); - } - - public override void OnResponse(Mobile from, string text) - { - from.Prompt = new AddTagValuePrompt(m_Account, text); - from.SendMessage("Enter the new tag value."); - } - } - - private class AddTagValuePrompt : Prompt - { - private readonly Account m_Account; - private readonly string m_Name; - - public AddTagValuePrompt(Account acct, string name) - { - m_Account = acct; - m_Name = name; - } - - public override void OnCancel(Mobile from) - { - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Tags, 0, null, - "Request to add tag was canceled.", m_Account)); - } - - public override void OnResponse(Mobile from, string text) - { - if (m_Account != null) - { - m_Account.AddTag(m_Name, text); - from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Tags, 0, null, "Tag added.", m_Account)); - } - } - } - - private class NetStateComparer : IComparer - { - public static readonly IComparer Instance = new NetStateComparer(); - - public int Compare(NetState x, NetState y) - { - if (x == null && y == null) - return 0; - if (x == null) - return -1; - if (y == null) - return 1; - - Mobile aMob = x.Mobile; - Mobile bMob = y.Mobile; - - if (aMob == null && bMob == null) - return 0; - if (aMob == null) - return 1; - if (bMob == null) - return -1; - - if (aMob.AccessLevel > bMob.AccessLevel) - return -1; - - return aMob.AccessLevel < bMob.AccessLevel ? 1 : Insensitive.Compare(aMob.Name, bMob.Name); - } - } - - private class AccountComparer : IComparer - { - public static readonly IComparer Instance = new AccountComparer(); - - public int Compare(IAccount x, IAccount y) - { - if (x == null && y == null) - return 0; - if (x == null) - return -1; - if (y == null) - return 1; - - GetAccountInfo(x, out AccessLevel aLevel, out bool aOnline); - GetAccountInfo(y, out AccessLevel bLevel, out bool bOnline); - - if (aOnline && !bOnline) - return -1; - if (bOnline && !aOnline) - return 1; - if (aLevel > bLevel) - return -1; - - return aLevel < bLevel ? 1 : Insensitive.Compare(x.Username, y.Username); - } - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading; +using Server.Accounting; +using Server.Commands; +using Server.Items; +using Server.Misc; +using Server.Multis; +using Server.Network; +using Server.Prompts; + +namespace Server.Gumps +{ + public enum AdminGumpPage + { + Information_General, + Information_Perf, + Administer, + Clients, + Accounts, + Accounts_Shared, + Firewall, + Administer_WorldBuilding, + Administer_Server, + Administer_Access, + Administer_Access_Lockdown, + Administer_Commands, + ClientInfo, + AccountDetails, + AccountDetails_Information, + AccountDetails_Characters, + AccountDetails_Access, + AccountDetails_Access_ClientIPs, + AccountDetails_Access_Restrictions, + AccountDetails_Comments, + AccountDetails_Tags, + AccountDetails_ChangePassword, + AccountDetails_ChangeAccess, + FirewallInfo + } + + public class AdminGump : Gump + { + private const int LabelColor = 0x7FFF; + private const int SelectedColor = 0x421F; + private const int DisabledColor = 0x4210; + + private const int LabelColor32 = 0xFFFFFF; + private const int SelectedColor32 = 0x8080FF; + private const int DisabledColor32 = 0x808080; + + private const int LabelHue = 0x480; + private const int GreenHue = 0x40; + private const int RedHue = 0x20; + + private static readonly string[] m_AccessLevelStrings = + { + "Player", + "Counselor", + "Game Master", + "Seer", + "Administrator", + "Developer", + "Owner" + }; + + private readonly Mobile m_From; + private readonly List m_List; + private readonly int m_ListPage; + private readonly AdminGumpPage m_PageType; + private readonly object m_State; + + public AdminGump( + Mobile from, AdminGumpPage pageType, int listPage = 0, List list = null, string notice = null, + object state = null + ) : base(50, 40) + { + from.CloseGump(); + + m_From = from; + m_PageType = pageType; + m_ListPage = listPage; + m_State = state; + m_List = list; + + AddPage(0); + + AddBackground(0, 0, 420, 440, 5054); + + AddBlackAlpha(10, 10, 170, 100); + AddBlackAlpha(190, 10, 220, 100); + AddBlackAlpha(10, 120, 400, 260); + AddBlackAlpha(10, 390, 400, 40); + + AddPageButton( + 10, + 10, + GetButtonID(0, 0), + "INFORMATION", + AdminGumpPage.Information_General, + AdminGumpPage.Information_Perf + ); + AddPageButton( + 10, + 30, + GetButtonID(0, 1), + "ADMINISTER", + AdminGumpPage.Administer, + AdminGumpPage.Administer_Access, + AdminGumpPage.Administer_Commands, + AdminGumpPage.Administer_Server, + AdminGumpPage.Administer_WorldBuilding, + AdminGumpPage.Administer_Access_Lockdown + ); + AddPageButton(10, 50, GetButtonID(0, 2), "CLIENT LIST", AdminGumpPage.Clients, AdminGumpPage.ClientInfo); + AddPageButton( + 10, + 70, + GetButtonID(0, 3), + "ACCOUNT LIST", + AdminGumpPage.Accounts, + AdminGumpPage.Accounts_Shared, + AdminGumpPage.AccountDetails, + AdminGumpPage.AccountDetails_Information, + AdminGumpPage.AccountDetails_Characters, + AdminGumpPage.AccountDetails_Access, + AdminGumpPage.AccountDetails_Access_ClientIPs, + AdminGumpPage.AccountDetails_Access_Restrictions, + AdminGumpPage.AccountDetails_Comments, + AdminGumpPage.AccountDetails_Tags, + AdminGumpPage.AccountDetails_ChangeAccess, + AdminGumpPage.AccountDetails_ChangePassword + ); + AddPageButton(10, 90, GetButtonID(0, 4), "FIREWALL", AdminGumpPage.Firewall, AdminGumpPage.FirewallInfo); + + if (notice != null) + AddHtml(12, 392, 396, 36, Color(notice, LabelColor32)); + + switch (pageType) + { + case AdminGumpPage.Information_General: + { + var banned = 0; + var active = 0; + + foreach (Account acct in Accounts.GetAccounts()) + if (acct.Banned) + ++banned; + else + ++active; + + AddLabel(20, 130, LabelHue, "Active Accounts:"); + AddLabel(150, 130, LabelHue, active.ToString()); + + AddLabel(20, 150, LabelHue, "Banned Accounts:"); + AddLabel(150, 150, LabelHue, banned.ToString()); + + AddLabel(20, 170, LabelHue, "Firewalled:"); + AddLabel(150, 170, LabelHue, Firewall.List.Count.ToString()); + + AddLabel(20, 190, LabelHue, "Clients:"); + AddLabel(150, 190, LabelHue, TcpServer.Instances.Count.ToString()); + + AddLabel(20, 210, LabelHue, "Mobiles:"); + AddLabel(150, 210, LabelHue, World.Mobiles.Count.ToString()); + + AddLabel(20, 230, LabelHue, "Mobile Scripts:"); + AddLabel(150, 230, LabelHue, Core.ScriptMobiles.ToString()); + + AddLabel(20, 250, LabelHue, "Items:"); + AddLabel(150, 250, LabelHue, World.Items.Count.ToString()); + + AddLabel(20, 270, LabelHue, "Item Scripts:"); + AddLabel(150, 270, LabelHue, Core.ScriptItems.ToString()); + + AddLabel(20, 290, LabelHue, "Uptime:"); + AddLabel(150, 290, LabelHue, FormatTimeSpan(DateTime.UtcNow - Clock.ServerStart)); + + AddLabel(20, 310, LabelHue, "Memory:"); + AddLabel(150, 310, LabelHue, FormatByteAmount(GC.GetTotalMemory(false))); + + AddLabel(20, 330, LabelHue, "Framework:"); + AddLabel(150, 330, LabelHue, Environment.Version.ToString()); + + AddLabel(20, 350, LabelHue, "Operating System: "); + var os = Environment.OSVersion.ToString(); + + os = os.Replace("Microsoft", "MSFT"); + os = os.Replace("Service Pack", "SP"); + + AddLabel(150, 350, LabelHue, os); + + /*string str; + + try{ str = FormatTimeSpan( Core.Process.TotalProcessorTime ); } + catch{ str = "(unable to retrieve)"; } + + AddLabel( 20, 330, LabelHue, "Process Time:" ); + AddLabel( 250, 330, LabelHue, str );*/ + + /*try{ str = Core.Process.PriorityClass.ToString(); } + catch{ str = "(unable to retrieve)"; } + + AddLabel( 20, 350, LabelHue, "Process Priority:" ); + AddLabel( 250, 350, LabelHue, str );*/ + + AddPageButton(200, 20, GetButtonID(0, 0), "General", AdminGumpPage.Information_General); + AddPageButton(200, 40, GetButtonID(0, 5), "Performance", AdminGumpPage.Information_Perf); + + break; + } + case AdminGumpPage.Information_Perf: + { + AddLabel(20, 130, LabelHue, "Cycles Per Second:"); + AddLabel(40, 150, LabelHue, $"Current: {Core.CyclesPerSecond:N2}"); + AddLabel(40, 170, LabelHue, $"Average: {Core.AverageCPS:N2}"); + + var sb = new StringBuilder(); + + ThreadPool.GetAvailableThreads(out var curUser, out var curIOCP); + ThreadPool.GetMaxThreads(out var maxUser, out var maxIOCP); + + sb.Append("Worker Threads:
Capacity: "); + sb.Append(maxUser); + sb.Append("
Available: "); + sb.Append(curUser); + sb.Append("
Usage: "); + sb.Append((maxUser - curUser) * 100 / maxUser); + sb.Append("%

IOCP Threads:
Capacity: "); + sb.Append(maxIOCP); + sb.Append("
Available: "); + sb.Append(curIOCP); + sb.Append("
Usage: "); + sb.Append((maxIOCP - curIOCP) * 100 / maxIOCP); + sb.Append("%"); + + AddLabel(20, 200, LabelHue, "Pooling:"); + AddHtml(20, 220, 380, 150, sb.ToString(), true, true); + + AddPageButton(200, 20, GetButtonID(0, 0), "General", AdminGumpPage.Information_General); + AddPageButton(200, 40, GetButtonID(0, 5), "Performance", AdminGumpPage.Information_Perf); + + break; + } + case AdminGumpPage.Administer_WorldBuilding: + { + AddHtml(10, 125, 400, 20, Color(Center("Generating"), LabelColor32)); + + AddButtonLabeled(20, 150, GetButtonID(3, 100), "Documentation"); + AddButtonLabeled(220, 150, GetButtonID(3, 107), "Rebuild Categorization"); + + AddButtonLabeled(20, 175, GetButtonID(3, 101), "Teleporters"); + AddButtonLabeled(220, 175, GetButtonID(3, 102), "Moongates"); + + AddButtonLabeled(20, 200, GetButtonID(3, 103), "Vendors"); + AddButtonLabeled(220, 200, GetButtonID(3, 106), "Decoration"); + + AddButtonLabeled(20, 225, GetButtonID(3, 104), "Doors"); + AddButtonLabeled(220, 225, GetButtonID(3, 105), "Signs"); + + AddHtml(20, 275, 400, 30, Color(Center("Statics"), LabelColor32)); + + AddButtonLabeled(20, 300, GetButtonID(3, 110), "Freeze (Target)"); + AddButtonLabeled(20, 325, GetButtonID(3, 111), "Freeze (World)"); + AddButtonLabeled(20, 350, GetButtonID(3, 112), "Freeze (Map)"); + + AddButtonLabeled(220, 300, GetButtonID(3, 120), "Unfreeze (Target)"); + AddButtonLabeled(220, 325, GetButtonID(3, 121), "Unfreeze (World)"); + AddButtonLabeled(220, 350, GetButtonID(3, 122), "Unfreeze (Map)"); + + goto case AdminGumpPage.Administer; + } + case AdminGumpPage.Administer_Server: + { + AddHtml(10, 125, 400, 20, Color(Center("Server"), LabelColor32)); + + AddButtonLabeled(20, 150, GetButtonID(3, 200), "Save"); + + /*if (!Core.Service) + {*/ + AddButtonLabeled(20, 180, GetButtonID(3, 201), "Shutdown (With Save)"); + AddButtonLabeled(20, 200, GetButtonID(3, 202), "Shutdown (Without Save)"); + + AddButtonLabeled(20, 230, GetButtonID(3, 203), "Shutdown & Restart (With Save)"); + AddButtonLabeled(20, 250, GetButtonID(3, 204), "Shutdown & Restart (Without Save)"); + /*} + else + { + AddLabel( 20, 215, LabelHue, "Shutdown/Restart not available." ); + }*/ + + AddHtml(10, 295, 400, 20, Color(Center("Broadcast"), LabelColor32)); + + AddTextField(20, 320, 380, 20, 0); + AddButtonLabeled(20, 350, GetButtonID(3, 210), "To Everyone"); + AddButtonLabeled(220, 350, GetButtonID(3, 211), "To Staff"); + + goto case AdminGumpPage.Administer; + } + case AdminGumpPage.Administer_Access_Lockdown: + { + AddHtml(10, 125, 400, 20, Color(Center("Server Lockdown"), LabelColor32)); + + AddHtml( + 20, + 150, + 380, + 80, + Color( + "When enabled, only clients with an access level equal to or greater than the specified lockdown level may access the server. After setting a lockdown level, use the Purge Invalid Clients button to disconnect those clients without access.", + LabelColor32 + ) + ); + + var level = AccountHandler.LockdownLevel; + var isLockedDown = level > AccessLevel.Player; + + AddSelectedButton(20, 230, GetButtonID(3, 500), "Not Locked Down", !isLockedDown); + AddSelectedButton( + 20, + 260, + GetButtonID(3, 504), + "Administrators", + isLockedDown && level <= AccessLevel.Administrator + ); + AddSelectedButton(20, 280, GetButtonID(3, 503), "Seers", isLockedDown && level <= AccessLevel.Seer); + AddSelectedButton( + 20, + 300, + GetButtonID(3, 502), + "Game Masters", + isLockedDown && level <= AccessLevel.GameMaster + ); + AddSelectedButton( + 20, + 320, + GetButtonID(3, 501), + "Counselors", + isLockedDown && level <= AccessLevel.Counselor + ); + + AddButtonLabeled(20, 350, GetButtonID(3, 510), "Purge Invalid Clients"); + + goto case AdminGumpPage.Administer; + } + case AdminGumpPage.Administer_Access: + { + AddHtml(10, 125, 400, 20, Color(Center("Access"), LabelColor32)); + + AddHtml(10, 155, 400, 20, Color(Center("Connectivity"), LabelColor32)); + + AddButtonLabeled(20, 180, GetButtonID(3, 300), "Kick"); + AddButtonLabeled(220, 180, GetButtonID(3, 301), "Ban"); + + AddButtonLabeled(20, 210, GetButtonID(3, 302), "Firewall"); + AddButtonLabeled(220, 210, GetButtonID(3, 303), "Lockdown"); + + AddHtml(10, 245, 400, 20, Color(Center("Staff"), LabelColor32)); + + AddButtonLabeled(20, 270, GetButtonID(3, 310), "Make Player"); + AddButtonLabeled(20, 290, GetButtonID(3, 311), "Make Counselor"); + AddButtonLabeled(20, 310, GetButtonID(3, 312), "Make Game Master"); + AddButtonLabeled(20, 330, GetButtonID(3, 313), "Make Seer"); + + if (from.AccessLevel > AccessLevel.Administrator) + { + AddButtonLabeled(220, 270, GetButtonID(3, 314), "Make Administrator"); + + if (from.AccessLevel > AccessLevel.Developer) + { + AddButtonLabeled(220, 290, GetButtonID(3, 315), "Make Developer"); + + if (from.AccessLevel >= AccessLevel.Owner) + AddButtonLabeled(220, 310, GetButtonID(3, 316), "Make Owner"); + } + } + + goto case AdminGumpPage.Administer; + } + case AdminGumpPage.Administer_Commands: + { + AddHtml(10, 125, 400, 20, Color(Center("Commands"), LabelColor32)); + + AddButtonLabeled(20, 150, GetButtonID(3, 400), "Add"); + AddButtonLabeled(220, 150, GetButtonID(3, 401), "Remove"); + + AddButtonLabeled(20, 170, GetButtonID(3, 402), "Dupe"); + AddButtonLabeled(220, 170, GetButtonID(3, 403), "Dupe in bag"); + + AddButtonLabeled(20, 200, GetButtonID(3, 404), "Properties"); + AddButtonLabeled(220, 200, GetButtonID(3, 405), "Skills"); + + AddButtonLabeled(20, 230, GetButtonID(3, 406), "Mortal"); + AddButtonLabeled(220, 230, GetButtonID(3, 407), "Immortal"); + + AddButtonLabeled(20, 250, GetButtonID(3, 408), "Squelch"); + AddButtonLabeled(220, 250, GetButtonID(3, 409), "Unsquelch"); + + AddButtonLabeled(20, 270, GetButtonID(3, 410), "Freeze"); + AddButtonLabeled(220, 270, GetButtonID(3, 411), "Unfreeze"); + + AddButtonLabeled(20, 290, GetButtonID(3, 412), "Hide"); + AddButtonLabeled(220, 290, GetButtonID(3, 413), "Unhide"); + + AddButtonLabeled(20, 310, GetButtonID(3, 414), "Kill"); + AddButtonLabeled(220, 310, GetButtonID(3, 415), "Resurrect"); + + AddButtonLabeled(20, 330, GetButtonID(3, 416), "Move"); + AddButtonLabeled(220, 330, GetButtonID(3, 417), "Wipe"); + + AddButtonLabeled(20, 350, GetButtonID(3, 418), "Teleport"); + AddButtonLabeled(220, 350, GetButtonID(3, 419), "Teleport (Multiple)"); + + goto case AdminGumpPage.Administer; + } + case AdminGumpPage.Administer: + { + AddPageButton(200, 20, GetButtonID(3, 0), "World Building", AdminGumpPage.Administer_WorldBuilding); + AddPageButton(200, 40, GetButtonID(3, 1), "Server", AdminGumpPage.Administer_Server); + AddPageButton( + 200, + 60, + GetButtonID(3, 2), + "Access", + AdminGumpPage.Administer_Access, + AdminGumpPage.Administer_Access_Lockdown + ); + AddPageButton(200, 80, GetButtonID(3, 3), "Commands", AdminGumpPage.Administer_Commands); + + break; + } + case AdminGumpPage.Clients: + { + if (m_List == null) + { + var states = TcpServer.Instances; + states.Sort(NetStateComparer.Instance); + + m_List = states.ToList(); + } + + AddClientHeader(); + + AddLabelCropped(12, 120, 81, 20, LabelHue, "Name"); + AddLabelCropped(95, 120, 81, 20, LabelHue, "Account"); + AddLabelCropped(178, 120, 81, 20, LabelHue, "Access Level"); + AddLabelCropped(273, 120, 109, 20, LabelHue, "IP Address"); + + if (listPage > 0) + AddButton(375, 122, 0x15E3, 0x15E7, GetButtonID(1, 0)); + else + AddImage(375, 122, 0x25EA); + + if ((listPage + 1) * 12 < m_List.Count) + AddButton(392, 122, 0x15E1, 0x15E5, GetButtonID(1, 1)); + else + AddImage(392, 122, 0x25E6); + + if (m_List.Count == 0) + AddLabel(12, 140, LabelHue, "There are no clients to display."); + + for (int i = 0, index = listPage * 12; i < 12 && index >= 0 && index < m_List.Count; ++i, ++index) + { + if (!(m_List[index] is NetState ns)) + continue; + + var m = ns.Mobile; + var a = ns.Account as Account; + var offset = 140 + i * 20; + + if (m == null) + AddLabelCropped(12, offset, 81, 20, LabelHue, "(logging in)"); + else + AddLabelCropped(12, offset, 81, 20, GetHueFor(m), m.Name); + AddLabelCropped(95, offset, 81, 20, LabelHue, a == null ? "(no account)" : a.Username); + AddLabelCropped( + 178, + offset, + 81, + 20, + LabelHue, + m == null + ? a != null ? FormatAccessLevel(a.AccessLevel) : "" + : FormatAccessLevel(m.AccessLevel) + ); + AddLabelCropped(273, offset, 109, 20, LabelHue, ns.ToString()); + + if (a != null || m != null) + AddButton(380, offset - 1, 0xFA5, 0xFA7, GetButtonID(4, index + 2)); + } + + break; + } + case AdminGumpPage.ClientInfo: + { + if (!(state is Mobile m)) + break; + + AddClientHeader(); + + AddHtml(10, 125, 400, 20, Color(Center("Information"), LabelColor32)); + + var y = 146; + + AddLabel(20, y, LabelHue, "Name:"); + AddLabel(200, y, GetHueFor(m), m.Name); + y += 20; + + var a = m.Account as Account; + + AddLabel(20, y, LabelHue, "Account:"); + AddLabel(200, y, a?.Banned == true ? RedHue : LabelHue, a == null ? "(no account)" : a.Username); + AddButton(380, y, 0xFA5, 0xFA7, GetButtonID(7, 14)); + y += 20; + + var ns = m.NetState; + + if (ns == null) + { + AddLabel(20, y, LabelHue, "Address:"); + AddLabel(200, y, RedHue, "Offline"); + y += 20; + + AddLabel(20, y, LabelHue, "Location:"); + AddLabel(200, y, LabelHue, $"{m.Location} [{m.Map}]"); + y += 44; + } + else + { + AddLabel(20, y, LabelHue, "Address:"); + AddLabel(200, y, GreenHue, ns.ToString()); + y += 20; + + var v = ns.Version; + + AddLabel(20, y, LabelHue, "Version:"); + AddLabel(200, y, LabelHue, v == null ? "(null)" : v.ToString()); + y += 20; + + AddLabel(20, y, LabelHue, "Location:"); + AddLabel(200, y, LabelHue, $"{m.Location} [{m.Map}]"); + y += 24; + } + + AddButtonLabeled(20, y, GetButtonID(7, 0), "Go to"); + AddButtonLabeled(200, y, GetButtonID(7, 1), "Get"); + y += 20; + + AddButtonLabeled(20, y, GetButtonID(7, 2), "Kick"); + AddButtonLabeled(200, y, GetButtonID(7, 3), "Ban"); + y += 20; + + AddButtonLabeled(20, y, GetButtonID(7, 4), "Properties"); + AddButtonLabeled(200, y, GetButtonID(7, 5), "Skills"); + y += 20; + + AddButtonLabeled(20, y, GetButtonID(7, 6), "Mortal"); + AddButtonLabeled(200, y, GetButtonID(7, 7), "Immortal"); + y += 20; + + AddButtonLabeled(20, y, GetButtonID(7, 8), "Squelch"); + AddButtonLabeled(200, y, GetButtonID(7, 9), "Unsquelch"); + y += 20; + + /*AddButtonLabeled( 20, y, GetButtonID( 7, 10 ), "Hide" ); + AddButtonLabeled( 200, y, GetButtonID( 7, 11 ), "Unhide" ); + y += 20;*/ + + AddButtonLabeled(20, y, GetButtonID(7, 12), "Kill"); + AddButtonLabeled(200, y, GetButtonID(7, 13), "Resurrect"); + + break; + } + case AdminGumpPage.Accounts_Shared: + { + List>> sharedAccounts; + + if (m_List == null) + { + sharedAccounts = GetAllSharedAccounts(); + m_List = Utility.CastListContravariant>, object>( + sharedAccounts + ); + } + else + { + sharedAccounts = + Utility.CastListCovariant>>(m_List); + } + + AddLabelCropped(12, 120, 60, 20, LabelHue, "Count"); + AddLabelCropped(72, 120, 120, 20, LabelHue, "Address"); + AddLabelCropped(192, 120, 180, 20, LabelHue, "Accounts"); + + if (listPage > 0) + AddButton(375, 122, 0x15E3, 0x15E7, GetButtonID(1, 0)); + else + AddImage(375, 122, 0x25EA); + + if ((listPage + 1) * 12 < sharedAccounts.Count) + AddButton(392, 122, 0x15E1, 0x15E5, GetButtonID(1, 1)); + else + AddImage(392, 122, 0x25E6); + + if (sharedAccounts.Count == 0) + AddLabel(12, 140, LabelHue, "There are no accounts to display."); + + var sb = new StringBuilder(); + + for (int i = 0, index = listPage * 12; + i < 12 && index >= 0 && index < sharedAccounts.Count; + ++i, ++index) + { + var kvp = sharedAccounts[index]; + + var ipAddr = kvp.Key; + var accts = kvp.Value; + + var offset = 140 + i * 20; + + AddLabelCropped(12, offset, 60, 20, LabelHue, accts.Count.ToString()); + AddLabelCropped(72, offset, 120, 20, LabelHue, ipAddr.ToString()); + + if (sb.Length > 0) + sb.Length = 0; + + for (var j = 0; j < accts.Count; ++j) + { + if (j > 0) + sb.Append(", "); + + if (j < 4) + { + var acct = accts[j]; + + sb.Append(acct.Username); + } + else + { + sb.Append("..."); + break; + } + } + + AddLabelCropped(192, offset, 180, 20, LabelHue, sb.ToString()); + + AddButton(380, offset - 1, 0xFA5, 0xFA7, GetButtonID(5, index + 56)); + } + + break; + } + case AdminGumpPage.Accounts: + { + m_List ??= new List(); + + var rads = state as List; + + AddAccountHeader(); + + if (rads == null) + AddLabelCropped(12, 120, 120, 20, LabelHue, "Name"); + else + AddLabelCropped(32, 120, 100, 20, LabelHue, "Name"); + + AddLabelCropped(132, 120, 120, 20, LabelHue, "Access Level"); + AddLabelCropped(252, 120, 120, 20, LabelHue, "Status"); + + if (listPage > 0) + AddButton(375, 122, 0x15E3, 0x15E7, GetButtonID(1, 0)); + else + AddImage(375, 122, 0x25EA); + + if ((listPage + 1) * 12 < m_List.Count) + AddButton(392, 122, 0x15E1, 0x15E5, GetButtonID(1, 1)); + else + AddImage(392, 122, 0x25E6); + + if (m_List.Count == 0) + AddLabel(12, 140, LabelHue, "There are no accounts to display."); + + if (rads != null && notice == null) + { + AddButtonLabeled(10, 390, GetButtonID(5, 27), "Ban marked"); + AddButtonLabeled(10, 410, GetButtonID(5, 28), "Delete marked"); + + AddButtonLabeled(210, 390, GetButtonID(5, 29), "Mark all"); + AddButtonLabeled(210, 410, GetButtonID(5, 35), "Unmark house owners"); + } + + for (int i = 0, index = listPage * 12; i < 12 && index >= 0 && index < m_List.Count; ++i, ++index) + { + if (!(m_List[index] is Account a)) + continue; + + var offset = 140 + i * 20; + + GetAccountInfo(a, out var accessLevel, out var online); + + if (rads == null) + { + AddLabelCropped(12, offset, 120, 20, LabelHue, a.Username); + } + else + { + AddCheck(10, offset, 0xD2, 0xD3, rads.Contains(a), index); + AddLabelCropped(32, offset, 100, 20, LabelHue, a.Username); + } + + AddLabelCropped(132, offset, 120, 20, LabelHue, FormatAccessLevel(accessLevel)); + + if (online) + AddLabelCropped(252, offset, 120, 20, GreenHue, "Online"); + else if (a.Banned) + AddLabelCropped(252, offset, 120, 20, RedHue, "Banned"); + else + AddLabelCropped(252, offset, 120, 20, RedHue, "Offline"); + + AddButton(380, offset - 1, 0xFA5, 0xFA7, GetButtonID(5, index + 56)); + } + + break; + } + case AdminGumpPage.AccountDetails: + { + AddPageButton( + 190, + 10, + GetButtonID(5, 0), + "Information", + AdminGumpPage.AccountDetails_Information, + AdminGumpPage.AccountDetails_ChangeAccess, + AdminGumpPage.AccountDetails_ChangePassword + ); + AddPageButton(190, 30, GetButtonID(5, 1), "Characters", AdminGumpPage.AccountDetails_Characters); + AddPageButton( + 190, + 50, + GetButtonID(5, 13), + "Access", + AdminGumpPage.AccountDetails_Access, + AdminGumpPage.AccountDetails_Access_ClientIPs, + AdminGumpPage.AccountDetails_Access_Restrictions + ); + AddPageButton(190, 70, GetButtonID(5, 2), "Comments", AdminGumpPage.AccountDetails_Comments); + AddPageButton(190, 90, GetButtonID(5, 3), "Tags", AdminGumpPage.AccountDetails_Tags); + break; + } + case AdminGumpPage.AccountDetails_ChangePassword: + { + if (!(state is Account a)) + break; + + AddHtml(10, 125, 400, 20, Color(Center("Change Password"), LabelColor32)); + + AddLabel(20, 150, LabelHue, "Username:"); + AddLabel(200, 150, LabelHue, a.Username); + + AddLabel(20, 180, LabelHue, "Password:"); + AddTextField(200, 180, 160, 20, 0); + + AddLabel(20, 210, LabelHue, "Confirm:"); + AddTextField(200, 210, 160, 20, 1); + + AddButtonLabeled(20, 240, GetButtonID(5, 12), "Submit Change"); + + goto case AdminGumpPage.AccountDetails; + } + case AdminGumpPage.AccountDetails_ChangeAccess: + { + if (!(state is Account a)) + break; + + AddHtml(10, 125, 400, 20, Color(Center("Change Access Level"), LabelColor32)); + + AddLabel(20, 150, LabelHue, "Username:"); + AddLabel(200, 150, LabelHue, a.Username); + + AddLabel(20, 170, LabelHue, "Current Level:"); + AddLabel(200, 170, LabelHue, FormatAccessLevel(a.AccessLevel)); + + AddButtonLabeled(20, 200, GetButtonID(5, 20), "Player"); + AddButtonLabeled(20, 220, GetButtonID(5, 21), "Counselor"); + AddButtonLabeled(20, 240, GetButtonID(5, 22), "Game Master"); + AddButtonLabeled(20, 260, GetButtonID(5, 23), "Seer"); + + if (from.AccessLevel > AccessLevel.Administrator) + { + AddButtonLabeled(20, 280, GetButtonID(5, 24), "Administrator"); + + if (from.AccessLevel > AccessLevel.Developer) + { + AddButtonLabeled(20, 300, GetButtonID(5, 33), "Developer"); + + if (from.AccessLevel >= AccessLevel.Owner) + AddButtonLabeled(20, 320, GetButtonID(5, 34), "Owner"); + } + } + + goto case AdminGumpPage.AccountDetails; + } + case AdminGumpPage.AccountDetails_Information: + { + if (!(state is Account a)) + break; + + var charCount = 0; + + for (var i = 0; i < a.Length; ++i) + if (a[i] != null) + ++charCount; + + AddHtml(10, 125, 400, 20, Color(Center("Information"), LabelColor32)); + + AddLabel(20, 150, LabelHue, "Username:"); + AddLabel(200, 150, LabelHue, a.Username); + + AddLabel(20, 170, LabelHue, "Access Level:"); + AddLabel(200, 170, LabelHue, FormatAccessLevel(a.AccessLevel)); + + AddLabel(20, 190, LabelHue, "Status:"); + AddLabel(200, 190, a.Banned ? RedHue : GreenHue, a.Banned ? "Banned" : "Active"); + + if (a.Banned && a.GetBanTags(out var banTime, out var banDuration)) + { + if (banDuration == TimeSpan.MaxValue) + { + AddLabel(250, 190, LabelHue, "(Infinite)"); + } + else if (banDuration == TimeSpan.Zero) + { + AddLabel(250, 190, LabelHue, "(Zero)"); + } + else + { + var remaining = DateTime.UtcNow - banTime; + + if (remaining < TimeSpan.Zero) + remaining = TimeSpan.Zero; + else if (remaining > banDuration) + remaining = banDuration; + + var remMinutes = remaining.TotalMinutes; + var totMinutes = banDuration.TotalMinutes; + + var perc = remMinutes / totMinutes; + + AddLabel(250, 190, LabelHue, $"{FormatTimeSpan(banDuration)} [{perc * 100:F0}%]"); + } + } + else if (a.Banned) + { + AddLabel(250, 190, LabelHue, "(Unspecified)"); + } + + AddLabel(20, 210, LabelHue, "Created:"); + AddLabel(200, 210, LabelHue, a.Created.ToString()); + + AddLabel(20, 230, LabelHue, "Last Login:"); + AddLabel(200, 230, LabelHue, a.LastLogin.ToString()); + + AddLabel(20, 250, LabelHue, "Character Count:"); + AddLabel(200, 250, LabelHue, charCount.ToString()); + + AddLabel(20, 270, LabelHue, "Comment Count:"); + AddLabel(200, 270, LabelHue, a.Comments.Count.ToString()); + + AddLabel(20, 290, LabelHue, "Tag Count:"); + AddLabel(200, 290, LabelHue, a.Tags.Count.ToString()); + + AddButtonLabeled(20, 320, GetButtonID(5, 8), "Change Password"); + AddButtonLabeled(200, 320, GetButtonID(5, 9), "Change Access Level"); + + if (!a.Banned) + AddButtonLabeled(20, 350, GetButtonID(5, 10), "Ban Account"); + else + AddButtonLabeled(20, 350, GetButtonID(5, 11), "Unban Account"); + + AddButtonLabeled(200, 350, GetButtonID(5, 25), "Delete Account"); + + goto case AdminGumpPage.AccountDetails; + } + case AdminGumpPage.AccountDetails_Access: + { + if (!(state is Account a)) + break; + + AddHtml(10, 125, 400, 20, Color(Center("Access"), LabelColor32)); + + AddPageButton( + 20, + 150, + GetButtonID(5, 14), + "View client addresses", + AdminGumpPage.AccountDetails_Access_ClientIPs + ); + AddPageButton( + 20, + 170, + GetButtonID(5, 15), + "Manage restrictions", + AdminGumpPage.AccountDetails_Access_Restrictions + ); + + goto case AdminGumpPage.AccountDetails; + } + case AdminGumpPage.AccountDetails_Access_ClientIPs: + { + if (!(state is Account a)) + break; + + List ipAddresses; + + if (m_List == null) + { + ipAddresses = a.LoginIPs.ToList(); + m_List = Utility.CastListContravariant(ipAddresses); + } + else + { + ipAddresses = Utility.CastListCovariant(m_List); + } + + AddHtml(10, 195, 400, 20, Color(Center("Client Addresses"), LabelColor32)); + + AddButtonLabeled(227, 225, GetButtonID(5, 16), "View all shared accounts"); + AddButtonLabeled(227, 245, GetButtonID(5, 17), "Ban all shared accounts"); + AddButtonLabeled(227, 265, GetButtonID(5, 18), "Firewall all addresses"); + AddButtonLabeled(227, 285, GetButtonID(5, 36), "Clear all addresses"); + + AddHtml( + 225, + 315, + 180, + 80, + Color("List of IP addresses which have accessed this account.", LabelColor32) + ); + + AddImageTiled(15, 219, 206, 156, 0xBBC); + AddBlackAlpha(16, 220, 204, 154); + + AddHtml(18, 221, 114, 20, Color("IP Address", LabelColor32)); + + if (listPage > 0) + AddButton(184, 223, 0x15E3, 0x15E7, GetButtonID(1, 0)); + else + AddImage(184, 223, 0x25EA); + + if ((listPage + 1) * 6 < ipAddresses.Count) + AddButton(201, 223, 0x15E1, 0x15E5, GetButtonID(1, 1)); + else + AddImage(201, 223, 0x25E6); + + if (ipAddresses.Count == 0) + AddHtml(18, 243, 200, 60, Color("This account has not yet been accessed.", LabelColor32)); + + for (int i = 0, index = listPage * 6; i < 6 && index >= 0 && index < ipAddresses.Count; ++i, ++index) + { + AddHtml(18, 243 + i * 22, 114, 20, Color(ipAddresses[index].ToString(), LabelColor32)); + AddButton(130, 242 + i * 22, 0xFA2, 0xFA4, GetButtonID(8, index)); + AddButton(160, 242 + i * 22, 0xFA8, 0xFAA, GetButtonID(9, index)); + AddButton(190, 242 + i * 22, 0xFB1, 0xFB3, GetButtonID(10, index)); + } + + goto case AdminGumpPage.AccountDetails_Access; + } + case AdminGumpPage.AccountDetails_Access_Restrictions: + { + if (!(state is Account a)) + break; + + List ipRestrictions; + + if (m_List == null) + { + ipRestrictions = a.IPRestrictions.ToList(); + m_List = Utility.CastListContravariant(ipRestrictions); + } + else + { + ipRestrictions = Utility.CastListCovariant(m_List); + } + + AddHtml(10, 195, 400, 20, Color(Center("Address Restrictions"), LabelColor32)); + + AddTextField(227, 225, 120, 20, 0); + + AddButtonLabeled(352, 225, GetButtonID(5, 19), "Add"); + + AddHtml( + 225, + 255, + 180, + 120, + Color( + "Any clients connecting from an address not in this list will be rejected. Or, if the list is empty, any client may connect.", + LabelColor32 + ) + ); + + AddImageTiled(15, 219, 206, 156, 0xBBC); + AddBlackAlpha(16, 220, 204, 154); + + AddHtml(18, 221, 114, 20, Color("IP Address", LabelColor32)); + + if (listPage > 0) + AddButton(184, 223, 0x15E3, 0x15E7, GetButtonID(1, 0)); + else + AddImage(184, 223, 0x25EA); + + if ((listPage + 1) * 6 < ipRestrictions.Count) + AddButton(201, 223, 0x15E1, 0x15E5, GetButtonID(1, 1)); + else + AddImage(201, 223, 0x25E6); + + if (ipRestrictions.Count == 0) + AddHtml(18, 243, 200, 60, Color("There are no addresses in this list.", LabelColor32)); + + for (int i = 0, index = listPage * 6; + i < 6 && index >= 0 && index < ipRestrictions.Count; + ++i, ++index) + { + AddHtml(18, 243 + i * 22, 114, 20, Color(ipRestrictions[index], LabelColor32)); + AddButton(190, 242 + i * 22, 0xFB1, 0xFB3, GetButtonID(8, index)); + } + + goto case AdminGumpPage.AccountDetails_Access; + } + case AdminGumpPage.AccountDetails_Characters: + { + if (!(state is Account a)) + break; + + AddHtml(10, 125, 400, 20, Color(Center("Characters"), LabelColor32)); + + AddLabelCropped(12, 150, 120, 20, LabelHue, "Name"); + AddLabelCropped(132, 150, 120, 20, LabelHue, "Access Level"); + AddLabelCropped(252, 150, 120, 20, LabelHue, "Status"); + + var index = 0; + + for (var i = 0; i < a.Length; ++i) + { + var m = a[i]; + + if (m == null) + continue; + + var offset = 170 + index * 20; + + AddLabelCropped(12, offset, 120, 20, GetHueFor(m), m.Name); + AddLabelCropped(132, offset, 120, 20, LabelHue, FormatAccessLevel(m.AccessLevel)); + + if (m.NetState != null) + AddLabelCropped(252, offset, 120, 20, GreenHue, "Online"); + else + AddLabelCropped(252, offset, 120, 20, RedHue, "Offline"); + + AddButton(380, offset - 1, 0xFA5, 0xFA7, GetButtonID(5, i + 50)); + + ++index; + } + + if (index == 0) + AddLabel(12, 170, LabelHue, "The character list is empty."); + + goto case AdminGumpPage.AccountDetails; + } + case AdminGumpPage.AccountDetails_Comments: + { + if (!(state is Account a)) + break; + + AddHtml(10, 125, 400, 20, Color(Center("Comments"), LabelColor32)); + + AddButtonLabeled(20, 150, GetButtonID(5, 4), "Add Comment"); + + var sb = new StringBuilder(); + + if (a.Comments.Count == 0) + sb.Append("There are no comments for this account."); + + for (var i = 0; i < a.Comments.Count; ++i) + { + if (i > 0) + sb.Append("

"); + + var c = a.Comments[i]; + + sb.AppendFormat("[{0} on {1}]
{2}", c.AddedBy, c.LastModified, c.Content); + } + + AddHtml(20, 180, 380, 190, sb.ToString(), true, true); + + goto case AdminGumpPage.AccountDetails; + } + case AdminGumpPage.AccountDetails_Tags: + { + if (!(state is Account a)) + break; + + AddHtml(10, 125, 400, 20, Color(Center("Tags"), LabelColor32)); + + AddButtonLabeled(20, 150, GetButtonID(5, 5), "Add Tag"); + + var sb = new StringBuilder(); + + if (a.Tags.Count == 0) + sb.Append("There are no tags for this account."); + + for (var i = 0; i < a.Tags.Count; ++i) + { + if (i > 0) + sb.Append("
"); + + var tag = a.Tags[i]; + + sb.AppendFormat("{0} = {1}", tag.Name, tag.Value); + } + + AddHtml(20, 180, 380, 190, sb.ToString(), true, true); + + goto case AdminGumpPage.AccountDetails; + } + case AdminGumpPage.Firewall: + { + AddFirewallHeader(); + + List firewallEntries; + + if (m_List == null) + { + firewallEntries = Firewall.List; + m_List = Utility.CastListContravariant(firewallEntries); + } + else + { + firewallEntries = Utility.CastListCovariant(m_List); + } + + AddLabelCropped(12, 120, 358, 20, LabelHue, "IP Address"); + + if (listPage > 0) + AddButton(375, 122, 0x15E3, 0x15E7, GetButtonID(1, 0)); + else + AddImage(375, 122, 0x25EA); + + if ((listPage + 1) * 12 < firewallEntries.Count) + AddButton(392, 122, 0x15E1, 0x15E5, GetButtonID(1, 1)); + else + AddImage(392, 122, 0x25E6); + + if (firewallEntries.Count == 0) + AddLabel(12, 140, LabelHue, "The firewall list is empty."); + + for (int i = 0, index = listPage * 12; + i < 12 && index >= 0 && index < firewallEntries.Count; + ++i, ++index) + { + var firewallEntry = firewallEntries[index]; + + var offset = 140 + i * 20; + + AddLabelCropped(12, offset, 358, 20, LabelHue, firewallEntry.ToString()); + AddButton(380, offset - 1, 0xFA5, 0xFA7, GetButtonID(6, index + 4)); + } + + break; + } + case AdminGumpPage.FirewallInfo: + { + AddFirewallHeader(); + + if (!(state is Firewall.IFirewallEntry firewallEntry)) + break; + + AddHtml(10, 125, 400, 20, Color(Center(firewallEntry.ToString()), LabelColor32)); + + AddButtonLabeled(20, 150, GetButtonID(6, 3), "Remove"); + + AddHtml(10, 175, 400, 20, Color(Center("Potentially Affected Accounts"), LabelColor32)); + + List blockedAccts; + + if (m_List == null) + { + blockedAccts = new List(); + + foreach (var ia in Accounts.GetAccounts()) + { + var acct = (Account)ia; + + var loginList = acct.LoginIPs; + + var contains = false; + + for (var i = 0; !contains && i < loginList.Length; ++i) + if (firewallEntry.IsBlocked(loginList[i])) + { + blockedAccts.Add(acct); + break; + } + } + + blockedAccts.Sort(AccountComparer.Instance); + m_List = Utility.CastListContravariant(blockedAccts); + } + else + { + blockedAccts = Utility.CastListCovariant(m_List); + } + + if (listPage > 0) + AddButton(375, 177, 0x15E3, 0x15E7, GetButtonID(1, 0)); + else + AddImage(375, 177, 0x25EA); + + if ((listPage + 1) * 12 < blockedAccts.Count) + AddButton(392, 177, 0x15E1, 0x15E5, GetButtonID(1, 1)); + else + AddImage(392, 177, 0x25E6); + + if (blockedAccts.Count == 0) + AddLabelCropped(12, 200, 398, 20, LabelHue, "No accounts found."); + + for (int i = 0, index = listPage * 9; + i < 9 && index >= 0 && index < blockedAccts.Count; + ++i, ++index) + { + var a = blockedAccts[index]; + + var offset = 200 + i * 20; + + GetAccountInfo(a, out var accessLevel, out var online); + + AddLabelCropped(12, offset, 120, 20, LabelHue, a.Username); + AddLabelCropped(132, offset, 120, 20, LabelHue, FormatAccessLevel(accessLevel)); + + if (online) + AddLabelCropped(252, offset, 120, 20, GreenHue, "Online"); + else if (a.Banned) + AddLabelCropped(252, offset, 120, 20, RedHue, "Banned"); + else + AddLabelCropped(252, offset, 120, 20, RedHue, "Offline"); + + AddButton(380, offset - 1, 0xFA5, 0xFA7, GetButtonID(5, index + 56)); + } + + break; + } + } + } + + public void AddPageButton( + int x, int y, int buttonID, string text, AdminGumpPage page, + params AdminGumpPage[] subPages + ) + { + var isSelection = m_PageType == page; + + for (var i = 0; !isSelection && i < subPages.Length; ++i) + isSelection = m_PageType == subPages[i]; + + AddSelectedButton(x, y, buttonID, text, isSelection); + } + + public void AddSelectedButton(int x, int y, int buttonID, string text, bool isSelection) + { + AddButton(x, y - 1, isSelection ? 4006 : 4005, 4007, buttonID); + AddHtml(x + 35, y, 200, 20, Color(text, isSelection ? SelectedColor32 : LabelColor32)); + } + + public void AddButtonLabeled(int x, int y, int buttonID, string text) + { + AddButton(x, y - 1, 4005, 4007, buttonID); + AddHtml(x + 35, y, 240, 20, Color(text, LabelColor32)); + } + + public string Center(string text) => $"
{text}
"; + + public string Color(string text, int color) => $"{text}"; + + public void AddBlackAlpha(int x, int y, int width, int height) + { + AddImageTiled(x, y, width, height, 2624); + AddAlphaRegion(x, y, width, height); + } + + public int GetButtonID(int type, int index) => 1 + index * 11 + type; + + public static string FormatTimeSpan(TimeSpan ts) => + $"{ts.Days:D2}:{ts.Hours % 24:D2}:{ts.Minutes % 60:D2}:{ts.Seconds % 60:D2}"; + + public static string FormatByteAmount(long totalBytes) + { + if (totalBytes > 1000000000) + return $"{(double)totalBytes / 1073741824:F1} GB"; + + if (totalBytes > 1000000) + return $"{(double)totalBytes / 1048576:F1} MB"; + + if (totalBytes > 1000) + return $"{(double)totalBytes / 1024:F1} KB"; + + return $"{totalBytes} Bytes"; + } + + public static void Initialize() + { + CommandSystem.Register("Admin", AccessLevel.Administrator, Admin_OnCommand); + } + + [Usage("Admin")] + [Description( + "Opens an interface providing server information and administration features including client, account, and firewall management." + )] + public static void Admin_OnCommand(CommandEventArgs e) + { + e.Mobile.SendGump(new AdminGump(e.Mobile, AdminGumpPage.Clients)); + } + + public static int GetHueFor(Mobile m) + { + if (m == null) + return LabelHue; + + switch (m.AccessLevel) + { + case AccessLevel.Owner: + case AccessLevel.Developer: + case AccessLevel.Administrator: return 0x516; + case AccessLevel.Seer: return 0x144; + case AccessLevel.GameMaster: return 0x21; + case AccessLevel.Counselor: return 0x2; + default: + { + if (m.Kills >= 5) + return 0x21; + + return m.Criminal ? 0x3B1 : 0x58; + } + } + } + + public static string FormatAccessLevel(AccessLevel level) + { + var v = (int)level; + + if (v >= 0 && v < m_AccessLevelStrings.Length) + return m_AccessLevelStrings[v]; + + return "Unknown"; + } + + public void AddTextField(int x, int y, int width, int height, int index) + { + AddBackground(x - 2, y - 2, width + 4, height + 4, 0x2486); + AddTextEntry(x + 2, y + 2, width - 4, height - 4, 0, index, ""); + } + + public void AddClientHeader() + { + AddTextField(200, 20, 200, 20, 0); + AddButtonLabeled(200, 50, GetButtonID(4, 0), "Search For Name"); + AddButtonLabeled(200, 80, GetButtonID(4, 1), "Search For IP Address"); + } + + public void AddAccountHeader() + { + AddPage(1); + + AddLabel(200, 20, LabelHue, "Name:"); + AddTextField(250, 20, 150, 20, 0); + + AddLabel(200, 50, LabelHue, "Pass:"); + AddTextField(250, 50, 150, 20, 1); + + AddButtonLabeled(200, 80, GetButtonID(5, 6), "Add"); + AddButtonLabeled(290, 80, GetButtonID(5, 7), "Search"); + + AddButton(384, 84, 0x15E1, 0x15E5, 0, GumpButtonType.Page, 2); + + AddPage(2); + + AddButtonLabeled(200, 20, GetButtonID(5, 31), "View All: Inactive"); + AddButtonLabeled(200, 40, GetButtonID(5, 32), "View All: Banned"); + AddButtonLabeled(200, 60, GetButtonID(5, 26), "View All: Shared"); + AddButtonLabeled(200, 80, GetButtonID(5, 30), "View All: Empty"); + + AddButton(384, 84, 0x15E1, 0x15E5, 0, GumpButtonType.Page, 1); + + AddPage(0); + } + + public void AddFirewallHeader() + { + AddTextField(200, 20, 200, 20, 0); + AddButtonLabeled(320, 50, GetButtonID(6, 0), "Search"); + AddButtonLabeled(200, 50, GetButtonID(6, 1), "Add (Input)"); + AddButtonLabeled(200, 80, GetButtonID(6, 2), "Add (Target)"); + } + + private static List>> GetAllSharedAccounts() + { + var table = new Dictionary>(); + + foreach (Account acct in Accounts.GetAccounts()) + { + var theirAddresses = acct.LoginIPs; + + for (var i = 0; i < theirAddresses.Length; ++i) + if (!table.ContainsKey(theirAddresses[i])) + table[theirAddresses[i]] = new List { acct }; + } + + var tableEntries = table.ToList(); + + for (var i = 0; i < tableEntries.Count; ++i) + { + var kvp = tableEntries[i]; + var list = kvp.Value; + + if (kvp.Value.Count == 1) + list.RemoveAt(i--); + else + list.Sort(AccountComparer.Instance); + } + + tableEntries.Sort(SharedAccountComparer.Instance); + + return tableEntries; + } + + private static List GetSharedAccounts(IPAddress ipAddress) + { + var list = new List(); + + foreach (var account in Accounts.GetAccounts()) + { + var acct = (Account)account; + + var theirAddresses = acct.LoginIPs; + var contains = false; + + for (var i = 0; !contains && i < theirAddresses.Length; ++i) + contains = ipAddress.Equals(theirAddresses[i]); + + if (contains) + list.Add(acct); + } + + list.Sort(AccountComparer.Instance); + return list; + } + + private static List GetSharedAccounts(IPAddress[] ipAddresses) + { + var list = new List(); + + foreach (Account acct in Accounts.GetAccounts()) + { + var theirAddresses = acct.LoginIPs; + var contains = false; + + for (var i = 0; !contains && i < theirAddresses.Length; ++i) + { + var check = theirAddresses[i]; + + for (var j = 0; !contains && j < ipAddresses.Length; ++j) + contains = check.Equals(ipAddresses[j]); + } + + if (contains) + list.Add(acct); + } + + list.Sort(AccountComparer.Instance); + return list; + } + + public static void BanShared_Callback(Mobile from, bool okay, Account a) + { + if (from.AccessLevel < AccessLevel.Administrator) + return; + + string notice; + List list = null; + + if (okay) + { + list = GetSharedAccounts(a.LoginIPs); + + for (var i = 0; i < list.Count; ++i) + { + list[i].SetUnspecifiedBan(from); + list[i].Banned = true; + } + + notice = "All addresses in the list have been banned."; + } + else + { + notice = "You have chosen not to ban all shared accounts."; + } + + from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access_ClientIPs, 0, null, notice, a)); + + if (okay) + from.SendGump(new BanDurationGump(list)); + } + + public static void AccountDelete_Callback(Mobile from, bool okay, Account a) + { + if (from.AccessLevel < AccessLevel.Administrator) + return; + + if (okay) + { + CommandLogging.WriteLine( + from, + "{0} {1} deleting account {2}", + from.AccessLevel, + CommandLogging.Format(from), + a.Username + ); + a.Delete(); + + from.SendGump( + new AdminGump( + from, + AdminGumpPage.Accounts, + 0, + null, + $"{a.Username} : The account has been deleted." + ) + ); + } + else + { + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Information, + 0, + null, + "You have chosen not to delete the account.", + a + ) + ); + } + } + + public static void ResendGump_Callback(Mobile from, List list, List rads, int page) + { + if (from.AccessLevel < AccessLevel.Administrator) + return; + + from.SendGump(new AdminGump(from, AdminGumpPage.Accounts, page, list, null, rads)); + } + + public static void Marked_Callback(Mobile from, bool okay, bool ban, List list, List rads, int page) + { + if (from.AccessLevel < AccessLevel.Administrator) + return; + + if (okay) + { + if (!ban) + NetState.Pause(); + + for (var i = 0; i < rads.Count; ++i) + { + var acct = rads[i]; + + if (ban) + { + CommandLogging.WriteLine( + from, + "{0} {1} banning account {2}", + from.AccessLevel, + CommandLogging.Format(from), + acct.Username + ); + acct.SetUnspecifiedBan(from); + acct.Banned = true; + } + else + { + CommandLogging.WriteLine( + from, + "{0} {1} deleting account {2}", + from.AccessLevel, + CommandLogging.Format(from), + acct.Username + ); + acct.Delete(); + rads.RemoveAt(i--); + list.Remove(acct); + } + } + + if (!ban) + NetState.Resume(); + + from.SendGump( + new NoticeGump( + 1060637, + 30720, + $"You have {(ban ? "banned" : "deleted")} the account{(rads.Count == 1 ? "" : "s")}.", + 0xFFC000, + 420, + 280, + () => ResendGump_Callback(from, list, rads, ban ? page : 0) + ) + ); + + if (ban) + from.SendGump(new BanDurationGump(rads)); + } + else + { + from.SendGump( + new NoticeGump( + 1060637, + 30720, + $"You have chosen not to {(ban ? "ban" : "delete")} the account{(rads.Count == 1 ? "" : "s")}.", + 0xFFC000, + 420, + 280, + () => ResendGump_Callback(from, list, rads, page) + ) + ); + } + } + + public static void FirewallShared_Callback(Mobile from, bool okay, Account a) + { + if (from.AccessLevel < AccessLevel.Administrator) + return; + + string notice; + + if (okay) + { + for (var i = 0; i < a.LoginIPs.Length; ++i) + Firewall.Add(a.LoginIPs[i]); + + notice = "All addresses in the list have been firewalled."; + } + else + { + notice = "You have chosen not to firewall all addresses."; + } + + from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access_ClientIPs, 0, null, notice, a)); + } + + public static void Firewall_Callback(Mobile from, bool okay, Account a, object toFirewall) + { + if (from.AccessLevel < AccessLevel.Administrator) + return; + + string notice; + + if (okay) + { + Firewall.Add(toFirewall); + + notice = $"{toFirewall} : Added to firewall."; + } + else + { + notice = "You have chosen not to firewall the address."; + } + + from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access_ClientIPs, 0, null, notice, a)); + } + + public static void RemoveLoginIP_Callback(Mobile from, bool okay, Account a, IPAddress ip) + { + if (from.AccessLevel < AccessLevel.Administrator) + return; + + string notice; + + if (okay) + { + var ips = a.LoginIPs; + + if (ips.Length != 0 && Equals(ip, ips[0]) && AccountHandler.IPTable.ContainsKey(ips[0])) + --AccountHandler.IPTable[ip]; + + var newList = new List(ips); + newList.Remove(ip); + a.LoginIPs = newList.ToArray(); + + notice = $"{ip} : Removed address."; + } + else + { + notice = "You have chosen not to remove the address."; + } + + from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access_ClientIPs, 0, null, notice, a)); + } + + public static void RemoveLoginIPs_Callback(Mobile from, bool okay, Account a) + { + if (from.AccessLevel < AccessLevel.Administrator) + return; + + string notice; + + if (okay) + { + var ips = a.LoginIPs; + + if (ips.Length != 0 && AccountHandler.IPTable.ContainsKey(ips[0])) + --AccountHandler.IPTable[ips[0]]; + + a.LoginIPs = Array.Empty(); + + notice = "All addresses in the list have been removed."; + } + else + { + notice = "You have chosen not to clear all addresses."; + } + + from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Access_ClientIPs, 0, null, notice, a)); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var val = info.ButtonID - 1; + + if (val < 0) + return; + + var from = m_From; + + if (from.AccessLevel < AccessLevel.Administrator) + return; + + if (m_PageType == AdminGumpPage.Accounts) + { + var list = Utility.CastListCovariant(m_List); + + if (list != null && m_State is List rads) + for (int i = 0, v = m_ListPage * 12; i < 12 && v < list.Count; ++i, ++v) + { + var obj = list[v]; + + if (info.IsSwitched(v)) + { + if (!rads.Contains(obj)) + rads.Add(obj); + } + else if (rads.Contains(obj)) + { + rads.Remove(obj); + } + } + } + + var type = val % 11; + var index = val / 11; + + switch (type) + { + case 0: + { + AdminGumpPage page; + + switch (index) + { + case 0: + page = AdminGumpPage.Information_General; + break; + case 1: + page = AdminGumpPage.Administer; + break; + case 2: + page = AdminGumpPage.Clients; + break; + case 3: + page = AdminGumpPage.Accounts; + break; + case 4: + page = AdminGumpPage.Firewall; + break; + case 5: + page = AdminGumpPage.Information_Perf; + break; + default: return; + } + + from.SendGump(new AdminGump(from, page)); + break; + } + case 1: + { + switch (index) + { + case 0: + { + if (m_List != null && m_ListPage > 0) + from.SendGump( + new AdminGump(from, m_PageType, m_ListPage - 1, m_List, null, m_State) + ); + + break; + } + case 1: + { + if (m_List != null /*&& (m_ListPage + 1) * 12 < m_List.Count*/) + from.SendGump( + new AdminGump(from, m_PageType, m_ListPage + 1, m_List, null, m_State) + ); + + break; + } + } + + break; + } + case 3: + { + string notice = null; + var page = AdminGumpPage.Administer; + + if (index >= 500) + page = AdminGumpPage.Administer_Access_Lockdown; + else if (index >= 400) + page = AdminGumpPage.Administer_Commands; + else if (index >= 300) + page = AdminGumpPage.Administer_Access; + else if (index >= 200) + page = AdminGumpPage.Administer_Server; + else if (index >= 100) + page = AdminGumpPage.Administer_WorldBuilding; + + switch (index) + { + case 0: + page = AdminGumpPage.Administer_WorldBuilding; + break; + case 1: + page = AdminGumpPage.Administer_Server; + break; + case 2: + page = AdminGumpPage.Administer_Access; + break; + case 3: + page = AdminGumpPage.Administer_Commands; + break; + + case 100: + InvokeCommand("DocGen"); + notice = "Documentation has been generated."; + break; + case 101: + InvokeCommand("TelGen"); + notice = "Teleporters have been generated."; + break; + case 102: + InvokeCommand("MoonGen"); + notice = "Moongates have been generated."; + break; + case 103: + InvokeCommand("UOAMVendors"); + notice = "Vendor spawners have been generated."; + break; + case 104: + InvokeCommand("DoorGen"); + notice = "Doors have been generated."; + break; + case 105: + InvokeCommand("SignGen"); + notice = "Signs have been generated."; + break; + case 106: + InvokeCommand("Decorate"); + notice = "Decoration has been generated."; + break; + case 107: + InvokeCommand("RebuildCategorization"); + notice = "Categorization menu has been regenerated. The server should be restarted."; + break; + + case 110: + InvokeCommand("Freeze"); + notice = "Target bounding points."; + break; + case 120: + InvokeCommand("Unfreeze"); + notice = "Target bounding points."; + break; + + case 200: + InvokeCommand("Save"); + notice = "The world has been saved."; + break; + case 201: + Shutdown(false, true); + break; + case 202: + Shutdown(false, false); + break; + case 203: + Shutdown(true, true); + break; + case 204: + Shutdown(true, false); + break; + case 210: + case 211: + { + var text = info.GetTextEntry(0)?.Text.Trim(); + + if (string.IsNullOrEmpty(text)) + { + notice = "You must enter text to broadcast it."; + } + else + { + notice = "Your message has been broadcasted."; + InvokeCommand($"{(index == 210 ? "BC" : "SM")} {text}"); + } + + break; + } + + case 300: + InvokeCommand("Kick"); + notice = "Target the player to kick."; + break; + case 301: + InvokeCommand("Ban"); + notice = "Target the player to ban."; + break; + case 302: + InvokeCommand("Firewall"); + notice = "Target the player to firewall."; + break; + + case 303: + page = AdminGumpPage.Administer_Access_Lockdown; + break; + + case 310: + InvokeCommand("Set AccessLevel Player"); + notice = "Target the player to change their access level. (Player)"; + break; + case 311: + InvokeCommand("Set AccessLevel Counselor"); + notice = "Target the player to change their access level. (Counselor)"; + break; + case 312: + InvokeCommand("Set AccessLevel GameMaster"); + notice = "Target the player to change their access level. (Game Master)"; + break; + case 313: + InvokeCommand("Set AccessLevel Seer"); + notice = "Target the player to change their access level. (Seer)"; + break; + + case 314: + { + if (from.AccessLevel > AccessLevel.Administrator) + { + InvokeCommand("Set AccessLevel Administrator"); + notice = "Target the player to change their access level. (Administrator)"; + } + + break; + } + + case 315: + { + if (from.AccessLevel > AccessLevel.Developer) + { + InvokeCommand("Set AccessLevel Developer"); + notice = "Target the player to change their access level. (Developer)"; + } + + break; + } + + case 316: + { + if (from.AccessLevel >= AccessLevel.Owner) + { + InvokeCommand("Set AccessLevel Owner"); + notice = "Target the player to change their access level. (Owner)"; + } + + break; + } + + case 400: + notice = "Enter search terms to add objects."; + break; + case 401: + InvokeCommand("Remove"); + notice = "Target the item or mobile to remove."; + break; + case 402: + InvokeCommand("Dupe"); + notice = "Target the item to dupe."; + break; + case 403: + InvokeCommand("DupeInBag"); + notice = "Target the item to dupe. The item will be duped at it's current location."; + break; + case 404: + InvokeCommand("Props"); + notice = "Target the item or mobile to inspect."; + break; + case 405: + InvokeCommand("Skills"); + notice = "Target a mobile to view their skills."; + break; + case 406: + InvokeCommand("Set Blessed False"); + notice = "Target the mobile to make mortal."; + break; + case 407: + InvokeCommand("Set Blessed True"); + notice = "Target the mobile to make immortal."; + break; + case 408: + InvokeCommand("Set Squelched True"); + notice = "Target the mobile to squelch."; + break; + case 409: + InvokeCommand("Set Squelched False"); + notice = "Target the mobile to unsquelch."; + break; + case 410: + InvokeCommand("Set Frozen True"); + notice = "Target the mobile to freeze."; + break; + case 411: + InvokeCommand("Set Frozen False"); + notice = "Target the mobile to unfreeze."; + break; + case 412: + InvokeCommand("Set Hidden True"); + notice = "Target the mobile to hide."; + break; + case 413: + InvokeCommand("Set Hidden False"); + notice = "Target the mobile to unhide."; + break; + case 414: + InvokeCommand("Kill"); + notice = "Target the mobile to kill."; + break; + case 415: + InvokeCommand("Resurrect"); + notice = "Target the mobile to resurrect."; + break; + case 416: + InvokeCommand("Move"); + notice = "Target the item or mobile to move."; + break; + case 417: + InvokeCommand("Wipe"); + notice = "Target bounding points."; + break; + case 418: + InvokeCommand("Tele"); + notice = "Choose your destination."; + break; + case 419: + InvokeCommand("Multi Tele"); + notice = "Choose your destination."; + break; + + case 500: + case 501: + case 502: + case 503: + case 504: + { + AccountHandler.LockdownLevel = (AccessLevel)(index - 500); + + if (AccountHandler.LockdownLevel > AccessLevel.Player) + notice = "The lockdown level has been changed."; + else + notice = "The server is now accessible to everyone."; + + break; + } + + case 510: + { + var level = AccountHandler.LockdownLevel; + + if (level > AccessLevel.Player) + { + var clients = TcpServer.Instances; + var count = 0; + + for (var i = 0; i < clients.Count; ++i) + { + var ns = clients[i]; + var a = ns.Account; + + if (a == null) + continue; + + var hasAccess = false; + + if (a.AccessLevel >= level) + hasAccess = true; + else + for (var j = 0; !hasAccess && j < a.Length; ++j) + { + var m = a[j]; + + if (m?.AccessLevel >= level) + hasAccess = true; + } + + if (!hasAccess) + { + ns.Dispose(); + ++count; + } + } + + if (count == 0) + notice = "Nobody without access was found to disconnect."; + else + notice = $"Number of players disconnected: {count}"; + } + else + { + notice = "The server is not currently locked down."; + } + + break; + } + } + + from.SendGump(new AdminGump(from, page, 0, null, notice)); + + switch (index) + { + case 400: + InvokeCommand("Add"); + break; + case 111: + InvokeCommand("FreezeWorld"); + break; + case 112: + InvokeCommand("FreezeMap"); + break; + case 121: + InvokeCommand("UnfreezeWorld"); + break; + case 122: + InvokeCommand("UnfreezeMap"); + break; + } + + break; + } + case 4: + { + switch (index) + { + case 0: + case 1: + { + var forName = index == 0; + + var results = new List(); + + var match = info.GetTextEntry(0)?.Text.Trim().ToLower(); + string notice = null; + + if (string.IsNullOrEmpty(match)) + { + notice = $"You must enter {(forName ? "a name" : "an ip address")} to search."; + } + else + { + var instances = TcpServer.Instances; + + for (var i = 0; i < instances.Count; ++i) + { + var ns = instances[i]; + + bool isMatch; + + if (forName) + { + var m = ns.Mobile; + var a = ns.Account; + + isMatch = m?.Name.ToLower().IndexOf(match) >= 0 + || a?.Username.ToLower().IndexOf(match) >= 0; + } + else + { + isMatch = ns.ToString().IndexOf(match) >= 0; + } + + if (isMatch) + results.Add(ns); + } + + results.Sort(NetStateComparer.Instance); + } + + if (results.Count == 1) + { + var ns = results[0]; + var state = ns.Mobile ?? (object)ns.Account; + + if (state is Mobile) + from.SendGump( + new AdminGump( + from, + AdminGumpPage.ClientInfo, + 0, + null, + "One match found.", + state + ) + ); + else if (state is Account) + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Information, + 0, + null, + "One match found.", + state + ) + ); + else + from.SendGump( + new AdminGump( + from, + AdminGumpPage.Clients, + 0, + Utility.CastListContravariant(results), + "One match found." + ) + ); + } + else + { + from.SendGump( + new AdminGump( + from, + AdminGumpPage.Clients, + 0, + Utility.CastListContravariant(results), + notice ?? (results.Count == 0 ? "Nothing matched your search terms." : null) + ) + ); + } + + break; + } + default: + { + index -= 2; + + if (m_List != null && index >= 0 && index < m_List.Count) + { + if (!(m_List[index] is NetState ns)) + break; + + var m = ns.Mobile; + var a = ns.Account as Account; + + if (m != null) + from.SendGump(new AdminGump(from, AdminGumpPage.ClientInfo, 0, null, null, m)); + else if (a != null) + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Information, + 0, + null, + null, + a + ) + ); + } + + break; + } + } + + break; + } + case 5: + { + switch (index) + { + case 0: + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Information, + 0, + null, + null, + m_State + ) + ); + break; + case 1: + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Characters, + 0, + null, + null, + m_State + ) + ); + break; + case 2: + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Comments, + 0, + null, + null, + m_State + ) + ); + break; + case 3: + from.SendGump( + new AdminGump(from, AdminGumpPage.AccountDetails_Tags, 0, null, null, m_State) + ); + break; + case 13: + from.SendGump( + new AdminGump(from, AdminGumpPage.AccountDetails_Access, 0, null, null, m_State) + ); + break; + case 14: + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Access_ClientIPs, + 0, + null, + null, + m_State + ) + ); + break; + case 15: + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Access_Restrictions, + 0, + null, + null, + m_State + ) + ); + break; + case 4: + from.Prompt = new AddCommentPrompt(m_State as Account); + from.SendMessage("Enter the new account comment."); + break; + case 5: + from.Prompt = new AddTagNamePrompt(m_State as Account); + from.SendMessage("Enter the new tag name."); + break; + case 6: + { + var un = info.GetTextEntry(0)?.Text.Trim(); + var pw = info.GetTextEntry(1)?.Text.Trim(); + + Account dispAccount = null; + string notice; + + if (string.IsNullOrEmpty(un)) + { + notice = "You must enter a username to add an account."; + } + else if (string.IsNullOrEmpty(pw)) + { + notice = "You must enter a password to add an account."; + } + else + { + var account = Accounts.GetAccount(un); + + if (account != null) + { + notice = "There is already an account with that username."; + } + else + { + dispAccount = new Account(un, pw); + notice = $"{un} : Account added."; + CommandLogging.WriteLine( + from, + "{0} {1} adding new account: {2}", + from.AccessLevel, + CommandLogging.Format(from), + un + ); + } + } + + from.SendGump( + new AdminGump( + from, + dispAccount != null ? AdminGumpPage.AccountDetails_Information : m_PageType, + m_ListPage, + m_List, + notice, + dispAccount ?? m_State + ) + ); + break; + } + case 7: + { + List results; + + var matchEntry = info.GetTextEntry(0); + var match = matchEntry?.Text.Trim().ToLower(); + + if (string.IsNullOrEmpty(match)) + { + results = Accounts.GetAccounts().ToList(); + results.Sort(AccountComparer.Instance); + } + else + { + results = Accounts.GetAccounts() + .Where(acct => acct.Username.ToLower().IndexOf(match) >= 0) + .ToList(); + results.Sort(AccountComparer.Instance); + } + + if (results.Count == 1) + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Information, + 0, + null, + "One match found.", + results[0] + ) + ); + else + from.SendGump( + new AdminGump( + from, + AdminGumpPage.Accounts, + 0, + Utility.CastListContravariant(results), + results.Count == 0 ? "Nothing matched your search terms." : null, + new List() + ) + ); + + break; + } + case 8: + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_ChangePassword, + 0, + null, + null, + m_State + ) + ); + break; + case 9: + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_ChangeAccess, + 0, + null, + null, + m_State + ) + ); + break; + case 10: + case 11: + { + if (!(m_State is Account a)) + break; + + a.SetUnspecifiedBan(from); + a.Banned = index == 10; + CommandLogging.WriteLine( + from, + "{0} {1} {3} account {2}", + from.AccessLevel, + CommandLogging.Format(from), + a.Username, + a.Banned ? "banning" : "unbanning" + ); + from.SendGump( + new AdminGump( + from, + m_PageType, + m_ListPage, + m_List, + $"The account has been {(a.Banned ? "banned" : "unbanned")}.", + m_State + ) + ); + + if (index == 10) + from.SendGump(new BanDurationGump(a)); + + break; + } + case 12: + { + if (!(m_State is Account a)) + break; + + var passwordEntry = info.GetTextEntry(0); + var confirmEntry = info.GetTextEntry(1); + + var password = passwordEntry?.Text.Trim(); + var confirm = confirmEntry?.Text.Trim(); + + string notice; + var page = AdminGumpPage.AccountDetails_ChangePassword; + + if (string.IsNullOrEmpty(password)) + { + notice = "You must enter the password."; + } + else if (confirm != password) + { + notice = + "You must confirm the password. That field must precisely match the password field."; + } + else + { + notice = "The password has been changed."; + a.SetPassword(password); + page = AdminGumpPage.AccountDetails_Information; + CommandLogging.WriteLine( + from, + "{0} {1} changing password of account {2}", + from.AccessLevel, + CommandLogging.Format(from), + a.Username + ); + } + + from.SendGump(new AdminGump(from, page, 0, null, notice, m_State)); + + break; + } + case 16: // view shared + { + if (!(m_State is Account a)) + break; + + var list = GetSharedAccounts(a.LoginIPs); + + if (list.Count > 1 || list.Count == 1 && !list.Contains(a)) + from.SendGump( + new AdminGump( + from, + AdminGumpPage.Accounts, + 0, + Utility.CastListContravariant(list), + null, + new List() + ) + ); + else if (a.LoginIPs.Length > 0) + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Access_ClientIPs, + 0, + null, + "There are no other accounts which share an address with this one.", + m_State + ) + ); + else + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Access_ClientIPs, + 0, + null, + "This account has not yet been accessed.", + m_State + ) + ); + + break; + } + case 17: // ban shared + { + if (!(m_State is Account a)) + break; + + var list = GetSharedAccounts(a.LoginIPs); + + if (list.Count > 0) + { + var sb = new StringBuilder(); + + sb.AppendFormat( + "You are about to ban {0} account{1}. Do you wish to continue?", + list.Count, + list.Count != 1 ? "s" : "" + ); + + for (var i = 0; i < list.Count; ++i) + sb.AppendFormat("
- {0}", list[i].Username); + + from.SendGump( + new WarningGump( + 1060635, + 30720, + sb.ToString(), + 0xFFC000, + 420, + 400, + okay => BanShared_Callback(from, okay, a) + ) + ); + } + else if (a.LoginIPs.Length > 0) + { + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Access_ClientIPs, + 0, + null, + "There are no accounts which share an address with this one.", + m_State + ) + ); + } + else + { + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Access_ClientIPs, + 0, + null, + "This account has not yet been accessed.", + m_State + ) + ); + } + + break; + } + case 18: // firewall all + { + if (!(m_State is Account a)) + break; + + if (a.LoginIPs.Length > 0) + from.SendGump( + new WarningGump( + 1060635, + 30720, + $"You are about to firewall {a.LoginIPs.Length} address{(a.LoginIPs.Length != 1 ? "s" : "")}. Do you wish to continue?", + 0xFFC000, + 420, + 400, + okay => FirewallShared_Callback(from, okay, a) + ) + ); + else + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Access_ClientIPs, + 0, + null, + "This account has not yet been accessed.", + m_State + ) + ); + + break; + } + case 19: // add + { + if (!(m_State is Account a)) + break; + + var entry = info.GetTextEntry(0); + var ip = entry?.Text.Trim(); + + string notice; + + if (string.IsNullOrEmpty(ip)) + { + notice = "You must enter an address to add."; + } + else + { + var list = a.IPRestrictions; + + var contains = false; + for (var i = 0; !contains && i < list.Length; ++i) + contains = list[i] == ip; + + if (contains) + { + notice = "That address is already contained in the list."; + } + else + { + var newList = new string[list.Length + 1]; + + for (var i = 0; i < list.Length; ++i) + newList[i] = list[i]; + + newList[list.Length] = ip; + + a.IPRestrictions = newList; + + notice = $"{ip} : Added to restriction list."; + } + } + + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Access_Restrictions, + 0, + null, + notice, + m_State + ) + ); + + break; + } + case 20: // Change access level + case 21: + case 22: + case 23: + case 24: + { + if (!(m_State is Account a)) + break; + + var newLevel = index switch + { + 21 => AccessLevel.Counselor, + 22 => AccessLevel.GameMaster, + 23 => AccessLevel.Seer, + 24 => AccessLevel.Administrator, + 33 => AccessLevel.Developer, + 34 => AccessLevel.Owner, + _ => AccessLevel.Player // 20 + }; + + if (newLevel < from.AccessLevel || from.AccessLevel == AccessLevel.Owner) + { + a.AccessLevel = newLevel; + + CommandLogging.WriteLine( + from, + "{0} {1} changing access level of account {2} to {3}", + from.AccessLevel, + CommandLogging.Format(from), + a.Username, + a.AccessLevel + ); + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Information, + 0, + null, + "The access level has been changed.", + m_State + ) + ); + } + + break; + } + case 25: + { + if (!(m_State is Account a)) + break; + + from.SendGump( + new WarningGump( + 1060635, + 30720, + $"
Account of {a.Username}

You are about to permanently delete the account. Likewise, all characters on the account will be deleted, including equipped, inventory, and banked items. Any houses tied to the account will be demolished.

Do you wish to continue?", + 0xFFC000, + 420, + 280, + okay => AccountDelete_Callback(from, okay, a) + ) + ); + break; + } + case 26: // View all shared accounts + { + from.SendGump(new AdminGump(from, AdminGumpPage.Accounts_Shared)); + break; + } + case 27: // Ban marked + { + var list = m_List; + + if (list == null || !(m_State is List rads)) + break; + + if (rads.Count > 0) + from.SendGump( + new WarningGump( + 1060635, + 30720, + $"You are about to ban {rads.Count} marked account{(rads.Count == 1 ? "" : "s")}. Be cautioned, the only way to reverse this is by hand--manually unbanning each account.

Do you wish to continue?", + 0xFFC000, + 420, + 280, + okay => Marked_Callback(from, okay, true, list, rads, m_ListPage) + ) + ); + else + from.SendGump( + new NoticeGump( + 1060637, + 30720, + "You have not yet marked any accounts. Place a check mark next to the accounts you wish to ban and then try again.", + 0xFFC000, + 420, + 280, + () => ResendGump_Callback(from, list, rads, m_ListPage) + ) + ); + + break; + } + case 28: // Delete marked + { + var list = m_List; + + if (list == null || !(m_State is List rads)) + break; + + if (rads.Count > 0) + from.SendGump( + new WarningGump( + 1060635, + 30720, + string.Format( + "You are about to permanently delete {0} marked account{1}. Likewise, all characters on the account{1} will be deleted, including equipped, inventory, and banked items. Any houses tied to the account{1} will be demolished.

Do you wish to continue?", + rads.Count, + rads.Count == 1 ? "" : "s" + ), + 0xFFC000, + 420, + 280, + okay => Marked_Callback(from, okay, false, list, rads, m_ListPage) + ) + ); + else + from.SendGump( + new NoticeGump( + 1060637, + 30720, + "You have not yet marked any accounts. Place a check mark next to the accounts you wish to ban and then try again.", + 0xFFC000, + 420, + 280, + () => ResendGump_Callback(from, list, rads, m_ListPage) + ) + ); + + break; + } + case 29: // Mark all + { + if (m_List == null || !(m_State is List)) + break; + + from.SendGump( + new AdminGump( + from, + AdminGumpPage.Accounts, + m_ListPage, + m_List, + null, + m_List.ToList() + ) + ); + + break; + } + case 30: // View all empty accounts + { + var results = new List(); + + foreach (Account acct in Accounts.GetAccounts()) + { + var empty = true; + + for (var i = 0; empty && i < acct.Length; ++i) + empty = acct[i] == null; + + if (empty) + results.Add(acct); + } + + if (results.Count == 1) + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Information, + 0, + null, + "One match found.", + results[0] + ) + ); + else + from.SendGump( + new AdminGump( + from, + AdminGumpPage.Accounts, + 0, + results, + results.Count == 0 ? "Nothing matched your search terms." : null, + new List() + ) + ); + + break; + } + case 31: // View all inactive accounts + { + var results = new List(); + + foreach (Account acct in Accounts.GetAccounts()) + if (acct.Inactive) + results.Add(acct); + + if (results.Count == 1) + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Information, + 0, + null, + "One match found.", + results[0] + ) + ); + else + from.SendGump( + new AdminGump( + from, + AdminGumpPage.Accounts, + 0, + results, + results.Count == 0 ? "Nothing matched your search terms." : null, + new List() + ) + ); + + break; + } + case 32: // View all banned accounts + { + var results = new List(); + + foreach (Account acct in Accounts.GetAccounts()) + if (acct.Banned) + results.Add(acct); + + if (results.Count == 1) + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Information, + 0, + null, + "One match found.", + results[0] + ) + ); + else + from.SendGump( + new AdminGump( + from, + AdminGumpPage.Accounts, + 0, + results, + results.Count == 0 ? "Nothing matched your search terms." : null, + new List() + ) + ); + + break; + } + case 33: // Change access level (extended) + case 34: + { + goto case 20; + } + case 35: // Unmark house owners + { + var list = m_List; + var rads = m_State as List; + + if (list == null || rads == null) + break; + + var newRads = new List(); + + foreach (var acct in rads) + { + var hasHouse = false; + + for (var i = 0; i < acct.Length && !hasHouse; ++i) + if (acct[i] != null && BaseHouse.HasHouse(acct[i])) + hasHouse = true; + + if (!hasHouse) + newRads.Add(acct); + } + + from.SendGump( + new AdminGump(from, AdminGumpPage.Accounts, m_ListPage, m_List, null, newRads) + ); + + break; + } + case 36: // Clear login addresses + { + if (!(m_State is Account a)) + break; + + var ips = a.LoginIPs; + + if (ips.Length == 0) + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Access_ClientIPs, + 0, + null, + "This account has not yet been accessed.", + m_State + ) + ); + else + from.SendGump( + new WarningGump( + 1060635, + 30720, + $"You are about to clear the address list for account {a} containing {ips.Length} {(ips.Length == 1 ? "entry" : "entries")}. Do you wish to continue?", + 0xFFC000, + 420, + 280, + okay => RemoveLoginIPs_Callback(from, okay, a) + ) + ); + + break; + } + default: + { + index -= 50; + + if (m_State is Account a && index >= 0 && index < a.Length) + { + var m = a[index]; + + if (m != null) + from.SendGump(new AdminGump(from, AdminGumpPage.ClientInfo, 0, null, null, m)); + } + else + { + index -= 6; + + if (m_List != null && index >= 0 && index < m_List.Count) + { + if (m_List[index] is Account) + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Information, + 0, + null, + null, + m_List[index] + ) + ); + else if (m_List[index] is KeyValuePair> kvp) + from.SendGump( + new AdminGump( + from, + AdminGumpPage.Accounts, + 0, + Utility.CastListContravariant(kvp.Value), + null, + new List() + ) + ); + } + } + + break; + } + } + + break; + } + case 6: + { + switch (index) + { + case 0: + { + var matchEntry = info.GetTextEntry(0); + var match = matchEntry?.Text.Trim(); + + string notice = null; + var results = new List(); + + if (string.IsNullOrEmpty(match)) + notice = "You must enter a username to search."; + else + for (var i = 0; i < Firewall.List.Count; ++i) + { + var check = Firewall.List[i].ToString(); + + if (check?.IndexOf(match) >= 0) + results.Add(Firewall.List[i]); + } + + if (results.Count == 1) + from.SendGump( + new AdminGump( + from, + AdminGumpPage.FirewallInfo, + 0, + null, + "One match found.", + results[0] + ) + ); + else if (results.Count > 1) + from.SendGump( + new AdminGump( + from, + AdminGumpPage.Firewall, + 0, + results, + $"Search results for : {match}", + m_State + ) + ); + else + from.SendGump( + new AdminGump( + from, + m_PageType, + m_ListPage, + m_List, + notice ?? "Nothing matched your search terms.", + m_State + ) + ); + + break; + } + case 1: + { + var relay = info.GetTextEntry(0); + var text = relay?.Text.Trim(); + + if (string.IsNullOrEmpty(text)) + { + from.SendGump( + new AdminGump( + from, + m_PageType, + m_ListPage, + m_List, + "You must enter an address or pattern to add.", + m_State + ) + ); + } + else if (!Utility.IsValidIP(text)) + { + from.SendGump( + new AdminGump( + from, + m_PageType, + m_ListPage, + m_List, + "That is not a valid address or pattern.", + m_State + ) + ); + } + else + { + object toAdd = Firewall.ToFirewallEntry(text); + + CommandLogging.WriteLine( + from, + "{0} {1} firewalling {2}", + from.AccessLevel, + CommandLogging.Format(from), + toAdd + ); + + Firewall.Add(toAdd); + from.SendGump( + new AdminGump( + from, + AdminGumpPage.FirewallInfo, + 0, + null, + $"{toAdd} : Added to firewall.", + toAdd + ) + ); + } + + break; + } + case 2: + { + InvokeCommand("Firewall"); + from.SendGump( + new AdminGump( + from, + m_PageType, + m_ListPage, + m_List, + "Target the player to firewall.", + m_State + ) + ); + break; + } + case 3: + { + if (m_State is Firewall.IFirewallEntry) + { + CommandLogging.WriteLine( + from, + "{0} {1} removing {2} from firewall list", + from.AccessLevel, + CommandLogging.Format(from), + m_State + ); + + Firewall.Remove(m_State); + from.SendGump( + new AdminGump( + from, + AdminGumpPage.Firewall, + 0, + null, + $"{m_State} : Removed from firewall." + ) + ); + } + + break; + } + default: + { + index -= 4; + + if (m_List != null && index >= 0 && index < m_List.Count) + from.SendGump( + new AdminGump(from, AdminGumpPage.FirewallInfo, 0, null, null, m_List[index]) + ); + + break; + } + } + + break; + } + case 7: + { + if (!(m_State is Mobile m)) + break; + + string notice = null; + var sendGump = true; + + switch (index) + { + case 0: + { + var map = m.Map; + var loc = m.Location; + + if (map == null || map == Map.Internal) + { + map = m.LogoutMap; + loc = m.LogoutLocation; + } + + if (map != null && map != Map.Internal) + { + from.MoveToWorld(loc, map); + notice = "You have been teleported to their location."; + } + + break; + } + case 1: + { + m.MoveToWorld(from.Location, from.Map); + notice = "They have been teleported to your location."; + break; + } + case 2: + { + var ns = m.NetState; + + if (ns != null) + { + CommandLogging.WriteLine( + from, + "{0} {1} {2} {3}", + from.AccessLevel, + CommandLogging.Format(from), + "kicking", + CommandLogging.Format(m) + ); + ns.Dispose(); + notice = "They have been kicked."; + } + else + { + notice = "They are already disconnected."; + } + + break; + } + case 3: + { + if (m.Account is Account a) + { + CommandLogging.WriteLine( + from, + "{0} {1} {2} {3}", + from.AccessLevel, + CommandLogging.Format(from), + "banning", + CommandLogging.Format(m) + ); + a.Banned = true; + + var ns = m.NetState; + + ns?.Dispose(); + + notice = "They have been banned."; + } + + break; + } + case 6: + { + Properties.SetValue(from, m, "Blessed", "False"); + notice = "They are now mortal."; + break; + } + case 7: + { + Properties.SetValue(from, m, "Blessed", "True"); + notice = "They are now immortal."; + break; + } + case 8: + { + Properties.SetValue(from, m, "Squelched", "True"); + notice = "They are now squelched."; + break; + } + case 9: + { + Properties.SetValue(from, m, "Squelched", "False"); + notice = "They are now unsquelched."; + break; + } + case 10: + { + Properties.SetValue(from, m, "Hidden", "True"); + notice = "They are now hidden."; + break; + } + case 11: + { + Properties.SetValue(from, m, "Hidden", "False"); + notice = "They are now unhidden."; + break; + } + case 12: + { + CommandLogging.WriteLine( + from, + "{0} {1} killing {2}", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(m) + ); + m.Kill(); + notice = "They have been killed."; + break; + } + case 13: + { + CommandLogging.WriteLine( + from, + "{0} {1} resurrecting {2}", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(m) + ); + m.Resurrect(); + notice = "They have been resurrected."; + break; + } + case 14: + { + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Information, + 0, + null, + null, + m.Account + ) + ); + sendGump = false; + break; + } + } + + if (sendGump) + from.SendGump(new AdminGump(from, AdminGumpPage.ClientInfo, 0, null, notice, m_State)); + + switch (index) + { + case 3: + { + if (m.Account is Account a) + from.SendGump(new BanDurationGump(a)); + + break; + } + case 4: + { + from.SendGump(new PropertiesGump(from, m)); + break; + } + case 5: + { + from.SendGump(new SkillsGump(from, m)); + break; + } + } + + break; + } + case 8: + { + if (m_List != null && index >= 0 && index < m_List.Count) + { + if (!(m_State is Account a)) + break; + + if (m_PageType == AdminGumpPage.AccountDetails_Access_ClientIPs) + { + from.SendGump( + new WarningGump( + 1060635, + 30720, + $"You are about to firewall {m_List[index]}. All connection attempts from a matching IP will be refused. Are you sure?", + 0xFFC000, + 420, + 280, + okay => Firewall_Callback(from, okay, a, m_List[index]) + ) + ); + } + else if (m_PageType == AdminGumpPage.AccountDetails_Access_Restrictions) + { + var list = a.IPRestrictions.ToList(); + list.Remove(m_List[index] as string); + a.IPRestrictions = list.ToArray(); + + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Access_Restrictions, + 0, + null, + $"{m_List[index]} : Removed from list.", + a + ) + ); + } + } + + break; + } + case 9: + { + if (m_List != null && index >= 0 && index < m_List.Count) + if (m_PageType == AdminGumpPage.AccountDetails_Access_ClientIPs) + { + var obj = m_List[index]; + + if (!(obj is IPAddress ip)) + break; + + if (!(m_State is Account a)) + break; + + var list = GetSharedAccounts(ip); + + if (list.Count > 1 || list.Count == 1 && !list.Contains(a)) + from.SendGump( + new AdminGump( + from, + AdminGumpPage.Accounts, + 0, + Utility.CastListContravariant(list), + null, + new List() + ) + ); + else + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Access_ClientIPs, + 0, + null, + "There are no other accounts which share that address.", + a + ) + ); + } + + break; + } + case 10: + { + if (m_List != null && index >= 0 && index < m_List.Count) + if (m_PageType == AdminGumpPage.AccountDetails_Access_ClientIPs) + { + var ip = m_List[index] as IPAddress; + + if (ip == null) + break; + + if (!(m_State is Account a)) + break; + + from.SendGump( + new WarningGump( + 1060635, + 30720, + $"You are about to remove address {ip} from account {a}. Do you wish to continue?", + 0xFFC000, + 420, + 280, + okay => RemoveLoginIP_Callback(from, okay, a, ip) + ) + ); + } + + break; + } + } + } + + private void Shutdown(bool restart, bool save) + { + CommandLogging.WriteLine( + m_From, + "{0} {1} shutting down server (Restart: {2}) (Save: {3})", + m_From.AccessLevel, + CommandLogging.Format(m_From), + restart, + save + ); + + if (save) + InvokeCommand("Save"); + + Core.Kill(restart); + } + + private void InvokeCommand(string c) + { + CommandSystem.Handle(m_From, $"{CommandSystem.Prefix}{c}"); + } + + public static void GetAccountInfo(IAccount a, out AccessLevel accessLevel, out bool online) + { + accessLevel = a.AccessLevel; + online = false; + + for (var j = 0; j < a.Length; ++j) + { + var check = a[j]; + + if (check == null) + continue; + + if (check.AccessLevel > accessLevel) + accessLevel = check.AccessLevel; + + if (check.NetState != null) + online = true; + } + } + + private class SharedAccountComparer : IComparer>> + { + public static readonly IComparer>> Instance = new SharedAccountComparer(); + + public int Compare(KeyValuePair> x, KeyValuePair> y) => + x.Value.Count - y.Value.Count; + } + + private class AddCommentPrompt : Prompt + { + private readonly Account m_Account; + + public AddCommentPrompt(Account acct) => m_Account = acct; + + public override void OnCancel(Mobile from) + { + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Comments, + 0, + null, + "Request to add comment was canceled.", + m_Account + ) + ); + } + + public override void OnResponse(Mobile from, string text) + { + if (m_Account != null) + { + m_Account.Comments.Add(new AccountComment(from.RawName, text)); + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Comments, + 0, + null, + "Comment added.", + m_Account + ) + ); + } + } + } + + private class AddTagNamePrompt : Prompt + { + private readonly Account m_Account; + + public AddTagNamePrompt(Account acct) => m_Account = acct; + + public override void OnCancel(Mobile from) + { + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Tags, + 0, + null, + "Request to add tag was canceled.", + m_Account + ) + ); + } + + public override void OnResponse(Mobile from, string text) + { + from.Prompt = new AddTagValuePrompt(m_Account, text); + from.SendMessage("Enter the new tag value."); + } + } + + private class AddTagValuePrompt : Prompt + { + private readonly Account m_Account; + private readonly string m_Name; + + public AddTagValuePrompt(Account acct, string name) + { + m_Account = acct; + m_Name = name; + } + + public override void OnCancel(Mobile from) + { + from.SendGump( + new AdminGump( + from, + AdminGumpPage.AccountDetails_Tags, + 0, + null, + "Request to add tag was canceled.", + m_Account + ) + ); + } + + public override void OnResponse(Mobile from, string text) + { + if (m_Account != null) + { + m_Account.AddTag(m_Name, text); + from.SendGump(new AdminGump(from, AdminGumpPage.AccountDetails_Tags, 0, null, "Tag added.", m_Account)); + } + } + } + + private class NetStateComparer : IComparer + { + public static readonly IComparer Instance = new NetStateComparer(); + + public int Compare(NetState x, NetState y) + { + if (x == null && y == null) + return 0; + if (x == null) + return -1; + if (y == null) + return 1; + + var aMob = x.Mobile; + var bMob = y.Mobile; + + if (aMob == null && bMob == null) + return 0; + if (aMob == null) + return 1; + if (bMob == null) + return -1; + + if (aMob.AccessLevel > bMob.AccessLevel) + return -1; + + return aMob.AccessLevel < bMob.AccessLevel ? 1 : Insensitive.Compare(aMob.Name, bMob.Name); + } + } + + private class AccountComparer : IComparer + { + public static readonly IComparer Instance = new AccountComparer(); + + public int Compare(IAccount x, IAccount y) + { + if (x == null && y == null) + return 0; + if (x == null) + return -1; + if (y == null) + return 1; + + GetAccountInfo(x, out var aLevel, out var aOnline); + GetAccountInfo(y, out var bLevel, out var bOnline); + + if (aOnline && !bOnline) + return -1; + if (bOnline && !aOnline) + return 1; + if (aLevel > bLevel) + return -1; + + return aLevel < bLevel ? 1 : Insensitive.Compare(x.Username, y.Username); + } + } + } +} diff --git a/Projects/UOContent/Gumps/BanDurationGump.cs b/Projects/UOContent/Gumps/BanDurationGump.cs index ba38782fb..d24476dcd 100644 --- a/Projects/UOContent/Gumps/BanDurationGump.cs +++ b/Projects/UOContent/Gumps/BanDurationGump.cs @@ -1,235 +1,243 @@ -using System; -using System.Collections.Generic; -using Server.Accounting; -using Server.Network; - -namespace Server.Gumps -{ - public class BanDurationGump : Gump - { - private readonly List m_List; - - public BanDurationGump(Account a) : this(new List { a }) - { - } - - public BanDurationGump(List list) : base((640 - 500) / 2, (480 - 305) / 2) - { - m_List = list; - - int width = 500; - int height = 305; - - AddPage(0); - - AddBackground(0, 0, width, height, 5054); - - // AddImageTiled( 10, 10, width - 20, 20, 2624 ); - // AddAlphaRegion( 10, 10, width - 20, 20 ); - AddHtml(10, 10, width - 20, 20, "
Ban Duration
"); - - // AddImageTiled( 10, 40, width - 20, height - 50, 2624 ); - // AddAlphaRegion( 10, 40, width - 20, height - 50 ); - - AddButtonLabeled(15, 45, 1, "Infinite"); - AddButtonLabeled(15, 65, 2, "From D:H:M:S"); - - AddInput(3, 0, "Days"); - AddInput(4, 1, "Hours"); - AddInput(5, 2, "Minutes"); - AddInput(6, 3, "Seconds"); - - AddHtml(170, 45, 240, 20, "Comments:"); - AddTextField(170, 65, 315, height - 80, 10); - } - - public void AddButtonLabeled(int x, int y, int buttonID, string text) - { - AddButton(x, y - 1, 4005, 4007, buttonID); - AddHtml(x + 35, y, 240, 20, text); - } - - public void AddTextField(int x, int y, int width, int height, int index) - { - AddBackground(x - 2, y - 2, width + 4, height + 4, 0x2486); - AddTextEntry(x + 2, y + 2, width - 4, height - 4, 0, index, ""); - } - - public void AddInput(int bid, int idx, string name) - { - int x = 15; - int y = 95 + idx * 50; - - AddButtonLabeled(x, y, bid, name); - AddTextField(x + 35, y + 20, 100, 20, idx); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - Mobile from = sender.Mobile; - - if (from.AccessLevel < AccessLevel.Administrator) - return; - - TextRelay d = info.GetTextEntry(0); - TextRelay h = info.GetTextEntry(1); - TextRelay m = info.GetTextEntry(2); - TextRelay s = info.GetTextEntry(3); - - TextRelay c = info.GetTextEntry(10); - - TimeSpan duration; - bool shouldSet; - - switch (info.ButtonID) - { - case 0: - { - for (int i = 0; i < m_List.Count; ++i) - { - Account a = m_List[i]; - - a.SetUnspecifiedBan(from); - } - - from.SendMessage("Duration unspecified."); - return; - } - case 1: // infinite - { - duration = TimeSpan.MaxValue; - shouldSet = true; - break; - } - case 2: // From D:H:M:S - { - if (d != null && h != null && m != null && s != null) - try - { - duration = new TimeSpan(Utility.ToInt32(d.Text), Utility.ToInt32(h.Text), - Utility.ToInt32(m.Text), Utility.ToInt32(s.Text)); - shouldSet = true; - - break; - } - catch - { - // ignored - } - - duration = TimeSpan.Zero; - shouldSet = false; - - break; - } - case 3: // From D - { - if (d != null) - try - { - duration = TimeSpan.FromDays(Utility.ToDouble(d.Text)); - shouldSet = true; - - break; - } - catch - { - // ignored - } - - duration = TimeSpan.Zero; - shouldSet = false; - - break; - } - case 4: // From H - { - if (h != null) - try - { - duration = TimeSpan.FromHours(Utility.ToDouble(h.Text)); - shouldSet = true; - - break; - } - catch - { - // ignored - } - - duration = TimeSpan.Zero; - shouldSet = false; - - break; - } - case 5: // From M - { - if (m != null) - try - { - duration = TimeSpan.FromMinutes(Utility.ToDouble(m.Text)); - shouldSet = true; - - break; - } - catch - { - // ignored - } - - duration = TimeSpan.Zero; - shouldSet = false; - - break; - } - case 6: // From S - { - if (s != null) - try - { - duration = TimeSpan.FromSeconds(Utility.ToDouble(s.Text)); - shouldSet = true; - - break; - } - catch - { - // ignored - } - - duration = TimeSpan.Zero; - shouldSet = false; - - break; - } - default: return; - } - - if (shouldSet) - { - string comment = c?.Text.Trim().IsNullOrDefault(null); - - for (int i = 0; i < m_List.Count; ++i) - { - Account a = m_List[i]; - - a.SetBanTags(from, DateTime.UtcNow, duration); - - if (comment != null) - a.Comments.Add(new AccountComment(from.RawName, - $"Duration: {(duration == TimeSpan.MaxValue ? "Infinite" : duration.ToString())}, Comment: {comment}")); - } - - if (duration == TimeSpan.MaxValue) - from.SendMessage("Ban Duration: Infinite"); - else - from.SendMessage("Ban Duration: {0}", duration); - } - else - { - from.SendMessage("Time values were improperly formatted."); - from.SendGump(new BanDurationGump(m_List)); - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Accounting; +using Server.Network; + +namespace Server.Gumps +{ + public class BanDurationGump : Gump + { + private readonly List m_List; + + public BanDurationGump(Account a) : this(new List { a }) + { + } + + public BanDurationGump(List list) : base((640 - 500) / 2, (480 - 305) / 2) + { + m_List = list; + + var width = 500; + var height = 305; + + AddPage(0); + + AddBackground(0, 0, width, height, 5054); + + // AddImageTiled( 10, 10, width - 20, 20, 2624 ); + // AddAlphaRegion( 10, 10, width - 20, 20 ); + AddHtml(10, 10, width - 20, 20, "
Ban Duration
"); + + // AddImageTiled( 10, 40, width - 20, height - 50, 2624 ); + // AddAlphaRegion( 10, 40, width - 20, height - 50 ); + + AddButtonLabeled(15, 45, 1, "Infinite"); + AddButtonLabeled(15, 65, 2, "From D:H:M:S"); + + AddInput(3, 0, "Days"); + AddInput(4, 1, "Hours"); + AddInput(5, 2, "Minutes"); + AddInput(6, 3, "Seconds"); + + AddHtml(170, 45, 240, 20, "Comments:"); + AddTextField(170, 65, 315, height - 80, 10); + } + + public void AddButtonLabeled(int x, int y, int buttonID, string text) + { + AddButton(x, y - 1, 4005, 4007, buttonID); + AddHtml(x + 35, y, 240, 20, text); + } + + public void AddTextField(int x, int y, int width, int height, int index) + { + AddBackground(x - 2, y - 2, width + 4, height + 4, 0x2486); + AddTextEntry(x + 2, y + 2, width - 4, height - 4, 0, index, ""); + } + + public void AddInput(int bid, int idx, string name) + { + var x = 15; + var y = 95 + idx * 50; + + AddButtonLabeled(x, y, bid, name); + AddTextField(x + 35, y + 20, 100, 20, idx); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var from = sender.Mobile; + + if (from.AccessLevel < AccessLevel.Administrator) + return; + + var d = info.GetTextEntry(0); + var h = info.GetTextEntry(1); + var m = info.GetTextEntry(2); + var s = info.GetTextEntry(3); + + var c = info.GetTextEntry(10); + + TimeSpan duration; + bool shouldSet; + + switch (info.ButtonID) + { + case 0: + { + for (var i = 0; i < m_List.Count; ++i) + { + var a = m_List[i]; + + a.SetUnspecifiedBan(from); + } + + from.SendMessage("Duration unspecified."); + return; + } + case 1: // infinite + { + duration = TimeSpan.MaxValue; + shouldSet = true; + break; + } + case 2: // From D:H:M:S + { + if (d != null && h != null && m != null && s != null) + try + { + duration = new TimeSpan( + Utility.ToInt32(d.Text), + Utility.ToInt32(h.Text), + Utility.ToInt32(m.Text), + Utility.ToInt32(s.Text) + ); + shouldSet = true; + + break; + } + catch + { + // ignored + } + + duration = TimeSpan.Zero; + shouldSet = false; + + break; + } + case 3: // From D + { + if (d != null) + try + { + duration = TimeSpan.FromDays(Utility.ToDouble(d.Text)); + shouldSet = true; + + break; + } + catch + { + // ignored + } + + duration = TimeSpan.Zero; + shouldSet = false; + + break; + } + case 4: // From H + { + if (h != null) + try + { + duration = TimeSpan.FromHours(Utility.ToDouble(h.Text)); + shouldSet = true; + + break; + } + catch + { + // ignored + } + + duration = TimeSpan.Zero; + shouldSet = false; + + break; + } + case 5: // From M + { + if (m != null) + try + { + duration = TimeSpan.FromMinutes(Utility.ToDouble(m.Text)); + shouldSet = true; + + break; + } + catch + { + // ignored + } + + duration = TimeSpan.Zero; + shouldSet = false; + + break; + } + case 6: // From S + { + if (s != null) + try + { + duration = TimeSpan.FromSeconds(Utility.ToDouble(s.Text)); + shouldSet = true; + + break; + } + catch + { + // ignored + } + + duration = TimeSpan.Zero; + shouldSet = false; + + break; + } + default: return; + } + + if (shouldSet) + { + var comment = c?.Text.Trim().IsNullOrDefault(null); + + for (var i = 0; i < m_List.Count; ++i) + { + var a = m_List[i]; + + a.SetBanTags(from, DateTime.UtcNow, duration); + + if (comment != null) + a.Comments.Add( + new AccountComment( + from.RawName, + $"Duration: {(duration == TimeSpan.MaxValue ? "Infinite" : duration.ToString())}, Comment: {comment}" + ) + ); + } + + if (duration == TimeSpan.MaxValue) + from.SendMessage("Ban Duration: Infinite"); + else + from.SendMessage("Ban Duration: {0}", duration); + } + else + { + from.SendMessage("Time values were improperly formatted."); + from.SendGump(new BanDurationGump(m_List)); + } + } + } +} diff --git a/Projects/UOContent/Gumps/BaseConfirmGump.cs b/Projects/UOContent/Gumps/BaseConfirmGump.cs index eeb878c96..e76b66e0c 100644 --- a/Projects/UOContent/Gumps/BaseConfirmGump.cs +++ b/Projects/UOContent/Gumps/BaseConfirmGump.cs @@ -1,79 +1,79 @@ -using Server.Network; - -namespace Server.Gumps -{ - public class BaseConfirmGump : Gump - { - public BaseConfirmGump() : base(120, 50) - { - Closable = false; - Disposable = true; - Draggable = true; - Resizable = false; - - AddPage(0); - - AddImageTiled(0, 0, 348, 262, 0xA8E); - AddAlphaRegion(0, 0, 348, 262); - AddImage(0, 15, 0x27A8); - AddImageTiled(0, 30, 17, 200, 0x27A7); - AddImage(0, 230, 0x27AA); - AddImage(15, 230, 0x280C); - AddImageTiled(30, 0, 300, 17, 0x280A); - AddImage(315, 0, 0x280E); - AddImage(15, 244, 0x280C); - AddImageTiled(30, 244, 300, 17, 0x280A); - AddImage(315, 244, 0x280E); - AddImage(330, 15, 0x27A8); - AddImageTiled(330, 30, 17, 200, 0x27A7); - AddImage(330, 230, 0x27AA); - AddImage(333, 2, 0x2716); - AddImage(315, 248, 0x2716); - AddImage(2, 248, 0x2716); - AddImage(2, 2, 0x2716); - AddHtmlLocalized(25, 25, 200, 20, TitleNumber, 0x7D00); - AddImage(25, 40, 0xBBF); - AddHtmlLocalized(25, 55, 300, 120, LabelNumber, 0xFFFFFF); - - AddRadio(25, 175, 0x25F8, 0x25FB, true, (int)Buttons.Break); - AddRadio(25, 210, 0x25F8, 0x25FB, false, (int)Buttons.Close); - - AddHtmlLocalized(60, 180, 280, 20, 1074976, 0xFFFFFF); - AddHtmlLocalized(60, 215, 280, 20, 1074977, 0xFFFFFF); - - AddButton(265, 220, 0xF7, 0xF8, (int)Buttons.Confirm); - } - - public virtual int TitleNumber //
Warning!
- => 1075083; - - public virtual int LabelNumber // Are you sure you wish to select this? - => 1074975; - - public override void OnResponse(NetState state, RelayInfo info) - { - if (info.ButtonID == (int)Buttons.Confirm) - { - if (info.IsSwitched((int)Buttons.Break)) - Confirm(state.Mobile); - else - Refuse(state.Mobile); - } - } - - public virtual void Confirm(Mobile from) - { - } - - public virtual void Refuse(Mobile from) - { - } - - private enum Buttons - { - Close, - Break, - Confirm - } - } -} +using Server.Network; + +namespace Server.Gumps +{ + public class BaseConfirmGump : Gump + { + public BaseConfirmGump() : base(120, 50) + { + Closable = false; + Disposable = true; + Draggable = true; + Resizable = false; + + AddPage(0); + + AddImageTiled(0, 0, 348, 262, 0xA8E); + AddAlphaRegion(0, 0, 348, 262); + AddImage(0, 15, 0x27A8); + AddImageTiled(0, 30, 17, 200, 0x27A7); + AddImage(0, 230, 0x27AA); + AddImage(15, 230, 0x280C); + AddImageTiled(30, 0, 300, 17, 0x280A); + AddImage(315, 0, 0x280E); + AddImage(15, 244, 0x280C); + AddImageTiled(30, 244, 300, 17, 0x280A); + AddImage(315, 244, 0x280E); + AddImage(330, 15, 0x27A8); + AddImageTiled(330, 30, 17, 200, 0x27A7); + AddImage(330, 230, 0x27AA); + AddImage(333, 2, 0x2716); + AddImage(315, 248, 0x2716); + AddImage(2, 248, 0x2716); + AddImage(2, 2, 0x2716); + AddHtmlLocalized(25, 25, 200, 20, TitleNumber, 0x7D00); + AddImage(25, 40, 0xBBF); + AddHtmlLocalized(25, 55, 300, 120, LabelNumber, 0xFFFFFF); + + AddRadio(25, 175, 0x25F8, 0x25FB, true, (int)Buttons.Break); + AddRadio(25, 210, 0x25F8, 0x25FB, false, (int)Buttons.Close); + + AddHtmlLocalized(60, 180, 280, 20, 1074976, 0xFFFFFF); + AddHtmlLocalized(60, 215, 280, 20, 1074977, 0xFFFFFF); + + AddButton(265, 220, 0xF7, 0xF8, (int)Buttons.Confirm); + } + + public virtual int TitleNumber //
Warning!
+ => 1075083; + + public virtual int LabelNumber // Are you sure you wish to select this? + => 1074975; + + public override void OnResponse(NetState state, RelayInfo info) + { + if (info.ButtonID == (int)Buttons.Confirm) + { + if (info.IsSwitched((int)Buttons.Break)) + Confirm(state.Mobile); + else + Refuse(state.Mobile); + } + } + + public virtual void Confirm(Mobile from) + { + } + + public virtual void Refuse(Mobile from) + { + } + + private enum Buttons + { + Close, + Break, + Confirm + } + } +} diff --git a/Projects/UOContent/Gumps/BaseGridGump.cs b/Projects/UOContent/Gumps/BaseGridGump.cs index e420ca459..69b5a3b3d 100644 --- a/Projects/UOContent/Gumps/BaseGridGump.cs +++ b/Projects/UOContent/Gumps/BaseGridGump.cs @@ -1,179 +1,202 @@ -namespace Server.Gumps -{ - public abstract class BaseGridGump : Gump - { - public const int ArrowLeftID1 = 0x15E3; - public const int ArrowLeftID2 = 0x15E7; - public const int ArrowLeftWidth = 16; - public const int ArrowLeftHeight = 16; - - public const int ArrowRightID1 = 0x15E1; - public const int ArrowRightID2 = 0x15E5; - public const int ArrowRightWidth = 16; - public const int ArrowRightHeight = 16; - protected GumpBackground m_Background; - protected GumpImageTiled m_Offset; - - public BaseGridGump(int x, int y) : base(x, y) - { - } - - public int CurrentPage { get; private set; } - - public int CurrentX { get; private set; } - - public int CurrentY { get; private set; } - - public virtual int BorderSize => 10; - public virtual int OffsetSize => 1; - - public virtual int EntryHeight => 20; - - public virtual int OffsetGumpID => 0x0A40; - public virtual int HeaderGumpID => 0x0E14; - public virtual int EntryGumpID => 0x0BBC; - public virtual int BackGumpID => 0x13BE; - - public virtual int TextHue => 0; - public virtual int TextOffsetX => 2; - - public string Center(string text) => $"
{text}
"; - - public string Color(string text, int color) => $"{text}"; - - public int GetButtonID(int typeCount, int type, int index) => 1 + index * typeCount + type; - - public bool SplitButtonID(int buttonID, int typeCount, out int type, out int index) - { - if (buttonID < 1) - { - type = 0; - index = 0; - return false; - } - - buttonID -= 1; - - type = buttonID % typeCount; - index = buttonID / typeCount; - - return true; - } - - public void FinishPage() - { - if (m_Background != null) - m_Background.Height = CurrentY + EntryHeight + OffsetSize + BorderSize; - - if (m_Offset != null) - m_Offset.Height = CurrentY + EntryHeight + OffsetSize - BorderSize; - } - - public void AddNewPage() - { - FinishPage(); - - CurrentX = BorderSize + OffsetSize; - CurrentY = BorderSize + OffsetSize; - - AddPage(++CurrentPage); - - m_Background = new GumpBackground(0, 0, 100, 100, BackGumpID); - Add(m_Background); - - m_Offset = new GumpImageTiled(BorderSize, BorderSize, 100, 100, OffsetGumpID); - Add(m_Offset); - } - - public void AddNewLine() - { - CurrentY += EntryHeight + OffsetSize; - CurrentX = BorderSize + OffsetSize; - } - - public void IncreaseX(int width) - { - CurrentX += width + OffsetSize; - - width = CurrentX + BorderSize; - - if (m_Background != null && width > m_Background.Width) - m_Background.Width = width; - - width = CurrentX - BorderSize; - - if (m_Offset != null && width > m_Offset.Width) - m_Offset.Width = width; - } - - public void AddEntryLabel(int width, string text) - { - AddImageTiled(CurrentX, CurrentY, width, EntryHeight, EntryGumpID); - AddLabelCropped(CurrentX + TextOffsetX, CurrentY, width - TextOffsetX, EntryHeight, TextHue, text); - - IncreaseX(width); - } - - public void AddEntryHtml(int width, string text) - { - AddImageTiled(CurrentX, CurrentY, width, EntryHeight, EntryGumpID); - AddHtml(CurrentX + TextOffsetX, CurrentY, width - TextOffsetX, EntryHeight, text); - - IncreaseX(width); - } - - public void AddEntryHeader(int width) - { - AddEntryHeader(width, 1); - } - - public void AddEntryHeader(int width, int spannedEntries) - { - AddImageTiled(CurrentX, CurrentY, width, EntryHeight * spannedEntries + OffsetSize * (spannedEntries - 1), - HeaderGumpID); - IncreaseX(width); - } - - public void AddBlankLine() - { - if (m_Offset != null) - AddImageTiled(m_Offset.X, CurrentY, m_Offset.Width, EntryHeight, BackGumpID + 4); - - AddNewLine(); - } - - public void AddEntryButton(int width, int normalID, int pressedID, int buttonID, int buttonWidth, int buttonHeight) - { - AddEntryButton(width, normalID, pressedID, buttonID, buttonWidth, buttonHeight, 1); - } - - public void AddEntryButton(int width, int normalID, int pressedID, int buttonID, int buttonWidth, int buttonHeight, - int spannedEntries) - { - AddImageTiled(CurrentX, CurrentY, width, EntryHeight * spannedEntries + OffsetSize * (spannedEntries - 1), - HeaderGumpID); - AddButton(CurrentX + (width - buttonWidth) / 2, - CurrentY + (EntryHeight * spannedEntries + OffsetSize * (spannedEntries - 1) - buttonHeight) / 2, normalID, - pressedID, buttonID); - - IncreaseX(width); - } - - public void AddEntryPageButton(int width, int normalID, int pressedID, int page, int buttonWidth, int buttonHeight) - { - AddImageTiled(CurrentX, CurrentY, width, EntryHeight, HeaderGumpID); - AddButton(CurrentX + (width - buttonWidth) / 2, CurrentY + (EntryHeight - buttonHeight) / 2, normalID, pressedID, - 0, GumpButtonType.Page, page); - - IncreaseX(width); - } - - public void AddEntryText(int width, int entryID, string initialText) - { - AddImageTiled(CurrentX, CurrentY, width, EntryHeight, EntryGumpID); - AddTextEntry(CurrentX + TextOffsetX, CurrentY, width - TextOffsetX, EntryHeight, TextHue, entryID, initialText); - - IncreaseX(width); - } - } -} +namespace Server.Gumps +{ + public abstract class BaseGridGump : Gump + { + public const int ArrowLeftID1 = 0x15E3; + public const int ArrowLeftID2 = 0x15E7; + public const int ArrowLeftWidth = 16; + public const int ArrowLeftHeight = 16; + + public const int ArrowRightID1 = 0x15E1; + public const int ArrowRightID2 = 0x15E5; + public const int ArrowRightWidth = 16; + public const int ArrowRightHeight = 16; + protected GumpBackground m_Background; + protected GumpImageTiled m_Offset; + + public BaseGridGump(int x, int y) : base(x, y) + { + } + + public int CurrentPage { get; private set; } + + public int CurrentX { get; private set; } + + public int CurrentY { get; private set; } + + public virtual int BorderSize => 10; + public virtual int OffsetSize => 1; + + public virtual int EntryHeight => 20; + + public virtual int OffsetGumpID => 0x0A40; + public virtual int HeaderGumpID => 0x0E14; + public virtual int EntryGumpID => 0x0BBC; + public virtual int BackGumpID => 0x13BE; + + public virtual int TextHue => 0; + public virtual int TextOffsetX => 2; + + public string Center(string text) => $"
{text}
"; + + public string Color(string text, int color) => $"{text}"; + + public int GetButtonID(int typeCount, int type, int index) => 1 + index * typeCount + type; + + public bool SplitButtonID(int buttonID, int typeCount, out int type, out int index) + { + if (buttonID < 1) + { + type = 0; + index = 0; + return false; + } + + buttonID -= 1; + + type = buttonID % typeCount; + index = buttonID / typeCount; + + return true; + } + + public void FinishPage() + { + if (m_Background != null) + m_Background.Height = CurrentY + EntryHeight + OffsetSize + BorderSize; + + if (m_Offset != null) + m_Offset.Height = CurrentY + EntryHeight + OffsetSize - BorderSize; + } + + public void AddNewPage() + { + FinishPage(); + + CurrentX = BorderSize + OffsetSize; + CurrentY = BorderSize + OffsetSize; + + AddPage(++CurrentPage); + + m_Background = new GumpBackground(0, 0, 100, 100, BackGumpID); + Add(m_Background); + + m_Offset = new GumpImageTiled(BorderSize, BorderSize, 100, 100, OffsetGumpID); + Add(m_Offset); + } + + public void AddNewLine() + { + CurrentY += EntryHeight + OffsetSize; + CurrentX = BorderSize + OffsetSize; + } + + public void IncreaseX(int width) + { + CurrentX += width + OffsetSize; + + width = CurrentX + BorderSize; + + if (m_Background != null && width > m_Background.Width) + m_Background.Width = width; + + width = CurrentX - BorderSize; + + if (m_Offset != null && width > m_Offset.Width) + m_Offset.Width = width; + } + + public void AddEntryLabel(int width, string text) + { + AddImageTiled(CurrentX, CurrentY, width, EntryHeight, EntryGumpID); + AddLabelCropped(CurrentX + TextOffsetX, CurrentY, width - TextOffsetX, EntryHeight, TextHue, text); + + IncreaseX(width); + } + + public void AddEntryHtml(int width, string text) + { + AddImageTiled(CurrentX, CurrentY, width, EntryHeight, EntryGumpID); + AddHtml(CurrentX + TextOffsetX, CurrentY, width - TextOffsetX, EntryHeight, text); + + IncreaseX(width); + } + + public void AddEntryHeader(int width) + { + AddEntryHeader(width, 1); + } + + public void AddEntryHeader(int width, int spannedEntries) + { + AddImageTiled( + CurrentX, + CurrentY, + width, + EntryHeight * spannedEntries + OffsetSize * (spannedEntries - 1), + HeaderGumpID + ); + IncreaseX(width); + } + + public void AddBlankLine() + { + if (m_Offset != null) + AddImageTiled(m_Offset.X, CurrentY, m_Offset.Width, EntryHeight, BackGumpID + 4); + + AddNewLine(); + } + + public void AddEntryButton(int width, int normalID, int pressedID, int buttonID, int buttonWidth, int buttonHeight) + { + AddEntryButton(width, normalID, pressedID, buttonID, buttonWidth, buttonHeight, 1); + } + + public void AddEntryButton( + int width, int normalID, int pressedID, int buttonID, int buttonWidth, int buttonHeight, + int spannedEntries + ) + { + AddImageTiled( + CurrentX, + CurrentY, + width, + EntryHeight * spannedEntries + OffsetSize * (spannedEntries - 1), + HeaderGumpID + ); + AddButton( + CurrentX + (width - buttonWidth) / 2, + CurrentY + (EntryHeight * spannedEntries + OffsetSize * (spannedEntries - 1) - buttonHeight) / 2, + normalID, + pressedID, + buttonID + ); + + IncreaseX(width); + } + + public void AddEntryPageButton(int width, int normalID, int pressedID, int page, int buttonWidth, int buttonHeight) + { + AddImageTiled(CurrentX, CurrentY, width, EntryHeight, HeaderGumpID); + AddButton( + CurrentX + (width - buttonWidth) / 2, + CurrentY + (EntryHeight - buttonHeight) / 2, + normalID, + pressedID, + 0, + GumpButtonType.Page, + page + ); + + IncreaseX(width); + } + + public void AddEntryText(int width, int entryID, string initialText) + { + AddImageTiled(CurrentX, CurrentY, width, EntryHeight, EntryGumpID); + AddTextEntry(CurrentX + TextOffsetX, CurrentY, width - TextOffsetX, EntryHeight, TextHue, entryID, initialText); + + IncreaseX(width); + } + } +} diff --git a/Projects/UOContent/Gumps/BaseImageTileButtonsGump.cs b/Projects/UOContent/Gumps/BaseImageTileButtonsGump.cs index 80194473d..50b9e3c10 100644 --- a/Projects/UOContent/Gumps/BaseImageTileButtonsGump.cs +++ b/Projects/UOContent/Gumps/BaseImageTileButtonsGump.cs @@ -1,126 +1,142 @@ -using System.Collections.Generic; -using Server.Network; - -namespace Server.Gumps -{ - public class ImageTileButtonInfo - { - private int m_Hue; - private int m_ItemID; - - private TextDefinition m_Label; - private int m_LocalizedTooltip; - - public ImageTileButtonInfo(int itemID, int hue, TextDefinition label, int localizedTooltip = -1) - { - m_Hue = hue; - m_ItemID = itemID; - m_Label = label; - m_LocalizedTooltip = localizedTooltip; - } - - public virtual int ItemID - { - get => m_ItemID; - set => m_ItemID = value; - } - - public virtual int Hue - { - get => m_Hue; - set => m_Hue = value; - } - - public virtual int LocalizedTooltip - { - get => m_LocalizedTooltip; - set => m_LocalizedTooltip = value; - } - - public virtual TextDefinition Label - { - get => m_Label; - set => m_Label = value; - } - } - - public class BaseImageTileButtonsGump : Gump - { - public BaseImageTileButtonsGump(TextDefinition header, List buttons) : this(header, buttons.ToArray()) - { - } - - public BaseImageTileButtonsGump(TextDefinition header, ImageTileButtonInfo[] buttons) : base(10, 10) // Coords are 0, o on OSI, intentional difference - { - Buttons = buttons; - AddPage(0); - - int x = XItems * 250; - int y = YItems * 64; - - AddBackground(0, 0, x + 20, y + 84, 0x13BE); - AddImageTiled(10, 10, x, 20, 0xA40); - AddImageTiled(10, 40, x, y + 4, 0xA40); - AddImageTiled(10, y + 54, x, 20, 0xA40); - AddAlphaRegion(10, 10, x, y + 64); - - AddButton(10, y + 54, 0xFB1, 0xFB2, 0); // Cancel Button - AddHtmlLocalized(45, y + 56, x - 50, 20, 1060051, 0x7FFF); // CANCEL - TextDefinition.AddHtmlText(this, 14, 12, x, 20, header, false, false, 0x7FFF, 0xFFFFFF); - - AddPage(1); - - int itemsPerPage = XItems * YItems; - - for (int i = 0; i < buttons.Length; i++) - { - int position = i % itemsPerPage; - - int innerX = position % XItems * 250 + 14; - int innerY = position / XItems * 64 + 44; - - int pageNum = i / itemsPerPage + 1; - - if (position == 0 && i != 0) - { - AddButton(x - 100, y + 54, 0xFA5, 0xFA7, 0, GumpButtonType.Page, pageNum); - AddHtmlLocalized(x - 60, y + 56, 60, 20, 1043353, 0x7FFF); // Next - - AddPage(pageNum); - - AddButton(x - 200, y + 54, 0xFAE, 0xFB0, 0, GumpButtonType.Page, pageNum - 1); - AddHtmlLocalized(x - 160, y + 56, 60, 20, 1011393, 0x7FFF); // Back - } - - ImageTileButtonInfo b = buttons[i]; - - AddImageTiledButton(innerX, innerY, 0x918, 0x919, 100 + i, GumpButtonType.Reply, 0, b.ItemID, b.Hue, 15, 10, - b.LocalizedTooltip); - TextDefinition.AddHtmlText(this, innerX + 84, innerY, 250, 60, b.Label, false, false, 0x7FFF, 0xFFFFFF); - } - } - - protected ImageTileButtonInfo[] Buttons { get; } - - protected virtual int XItems => 2; - protected virtual int YItems => 5; - - public override void OnResponse(NetState sender, RelayInfo info) - { - int adjustedID = info.ButtonID - 100; - - if (adjustedID >= 0 && adjustedID < Buttons.Length) - HandleButtonResponse(sender, adjustedID, Buttons[adjustedID]); - else - HandleCancel(sender); - } - - public virtual void HandleButtonResponse(NetState sender, int adjustedButton, ImageTileButtonInfo buttonInfo) - { - } - - public virtual void HandleCancel(NetState sender) - { - } - } -} +using System.Collections.Generic; +using Server.Network; + +namespace Server.Gumps +{ + public class ImageTileButtonInfo + { + private int m_Hue; + private int m_ItemID; + + private TextDefinition m_Label; + private int m_LocalizedTooltip; + + public ImageTileButtonInfo(int itemID, int hue, TextDefinition label, int localizedTooltip = -1) + { + m_Hue = hue; + m_ItemID = itemID; + m_Label = label; + m_LocalizedTooltip = localizedTooltip; + } + + public virtual int ItemID + { + get => m_ItemID; + set => m_ItemID = value; + } + + public virtual int Hue + { + get => m_Hue; + set => m_Hue = value; + } + + public virtual int LocalizedTooltip + { + get => m_LocalizedTooltip; + set => m_LocalizedTooltip = value; + } + + public virtual TextDefinition Label + { + get => m_Label; + set => m_Label = value; + } + } + + public class BaseImageTileButtonsGump : Gump + { + public BaseImageTileButtonsGump(TextDefinition header, List buttons) : this( + header, + buttons.ToArray() + ) + { + } + + public BaseImageTileButtonsGump(TextDefinition header, ImageTileButtonInfo[] buttons) : + base(10, 10) // Coords are 0, o on OSI, intentional difference + { + Buttons = buttons; + AddPage(0); + + var x = XItems * 250; + var y = YItems * 64; + + AddBackground(0, 0, x + 20, y + 84, 0x13BE); + AddImageTiled(10, 10, x, 20, 0xA40); + AddImageTiled(10, 40, x, y + 4, 0xA40); + AddImageTiled(10, y + 54, x, 20, 0xA40); + AddAlphaRegion(10, 10, x, y + 64); + + AddButton(10, y + 54, 0xFB1, 0xFB2, 0); // Cancel Button + AddHtmlLocalized(45, y + 56, x - 50, 20, 1060051, 0x7FFF); // CANCEL + TextDefinition.AddHtmlText(this, 14, 12, x, 20, header, false, false, 0x7FFF, 0xFFFFFF); + + AddPage(1); + + var itemsPerPage = XItems * YItems; + + for (var i = 0; i < buttons.Length; i++) + { + var position = i % itemsPerPage; + + var innerX = position % XItems * 250 + 14; + var innerY = position / XItems * 64 + 44; + + var pageNum = i / itemsPerPage + 1; + + if (position == 0 && i != 0) + { + AddButton(x - 100, y + 54, 0xFA5, 0xFA7, 0, GumpButtonType.Page, pageNum); + AddHtmlLocalized(x - 60, y + 56, 60, 20, 1043353, 0x7FFF); // Next + + AddPage(pageNum); + + AddButton(x - 200, y + 54, 0xFAE, 0xFB0, 0, GumpButtonType.Page, pageNum - 1); + AddHtmlLocalized(x - 160, y + 56, 60, 20, 1011393, 0x7FFF); // Back + } + + var b = buttons[i]; + + AddImageTiledButton( + innerX, + innerY, + 0x918, + 0x919, + 100 + i, + GumpButtonType.Reply, + 0, + b.ItemID, + b.Hue, + 15, + 10, + b.LocalizedTooltip + ); + TextDefinition.AddHtmlText(this, innerX + 84, innerY, 250, 60, b.Label, false, false, 0x7FFF, 0xFFFFFF); + } + } + + protected ImageTileButtonInfo[] Buttons { get; } + + protected virtual int XItems => 2; + protected virtual int YItems => 5; + + public override void OnResponse(NetState sender, RelayInfo info) + { + var adjustedID = info.ButtonID - 100; + + if (adjustedID >= 0 && adjustedID < Buttons.Length) + HandleButtonResponse(sender, adjustedID, Buttons[adjustedID]); + else + HandleCancel(sender); + } + + public virtual void HandleButtonResponse(NetState sender, int adjustedButton, ImageTileButtonInfo buttonInfo) + { + } + + public virtual void HandleCancel(NetState sender) + { + } + } +} diff --git a/Projects/UOContent/Gumps/ClientGump.cs b/Projects/UOContent/Gumps/ClientGump.cs index 6f0c9ab6b..326fc8458 100644 --- a/Projects/UOContent/Gumps/ClientGump.cs +++ b/Projects/UOContent/Gumps/ClientGump.cs @@ -1,299 +1,349 @@ -using Server.Accounting; -using Server.Commands; -using Server.Commands.Generic; -using Server.Mobiles; -using Server.Network; -using Server.Targets; - -namespace Server.Gumps -{ - public class ClientGump : Gump - { - private const int LabelColor32 = 0xFFFFFF; - private readonly NetState m_State; - - public ClientGump(Mobile from, NetState state, string initialText = "") : base(30, 20) - { - if (state == null) - return; - - m_State = state; - - AddPage(0); - - AddBackground(0, 0, 400, 274, 5054); - - AddImageTiled(10, 10, 380, 19, 0xA40); - AddAlphaRegion(10, 10, 380, 19); - - AddImageTiled(10, 32, 380, 232, 0xA40); - AddAlphaRegion(10, 32, 380, 232); - - AddHtml(10, 10, 380, 20, Color(Center("User Information"), LabelColor32)); - - int line = 0; - - AddHtml(14, 36 + line * 20, 200, 20, Color("Address:", LabelColor32)); - AddHtml(70, 36 + line++ * 20, 200, 20, Color(state.ToString(), LabelColor32)); - - AddHtml(14, 36 + line * 20, 200, 20, Color("Client:", LabelColor32)); - AddHtml(70, 36 + line++ * 20, 200, 20, - Color(state.Version == null ? "(null)" : state.Version.ToString(), LabelColor32)); - - AddHtml(14, 36 + line * 20, 200, 20, Color("Version:", LabelColor32)); - - ExpansionInfo info = state.ExpansionInfo; - string expansionName = info.Name; - - AddHtml(70, 36 + line++ * 20, 200, 20, Color(expansionName, LabelColor32)); - - Account a = state.Account as Account; - Mobile m = state.Mobile; - - if (from.AccessLevel >= AccessLevel.GameMaster && a != null) - { - AddHtml(14, 36 + line * 20, 200, 20, Color("Account:", LabelColor32)); - AddHtml(70, 36 + line++ * 20, 200, 20, Color(a.Username, LabelColor32)); - } - - if (m != null) - { - AddHtml(14, 36 + line * 20, 200, 20, Color("Mobile:", LabelColor32)); - AddHtml(70, 36 + line++ * 20, 200, 20, Color($"{m.Name} (0x{m.Serial.Value:X})", LabelColor32)); - - AddHtml(14, 36 + line * 20, 200, 20, Color("Location:", LabelColor32)); - AddHtml(70, 36 + line++ * 20, 200, 20, Color($"{m.Location} [{m.Map}]", LabelColor32)); - - AddButton(13, 157, 0xFAB, 0xFAD, 1); - AddHtml(48, 158, 200, 20, Color("Send Message", LabelColor32)); - - AddImageTiled(12, 182, 376, 80, 0xA40); - AddImageTiled(13, 183, 374, 78, 0xBBC); - AddTextEntry(15, 183, 372, 78, 0x480, 0, ""); - - AddImageTiled(245, 35, 142, 144, 5058); - - AddImageTiled(246, 36, 140, 142, 0xA40); - AddAlphaRegion(246, 36, 140, 142); - - line = 0; - - if (BaseCommand.IsAccessible(from, m)) - { - AddButton(246, 36 + line * 20, 0xFA5, 0xFA7, 4); - AddHtml(280, 38 + line++ * 20, 100, 20, Color("Properties", LabelColor32)); - } - - if (from != m) - { - AddButton(246, 36 + line * 20, 0xFA5, 0xFA7, 5); - AddHtml(280, 38 + line++ * 20, 100, 20, Color("Go to them", LabelColor32)); - - AddButton(246, 36 + line * 20, 0xFA5, 0xFA7, 6); - AddHtml(280, 38 + line++ * 20, 100, 20, Color("Bring them here", LabelColor32)); - } - - AddButton(246, 36 + line * 20, 0xFA5, 0xFA7, 7); - AddHtml(280, 38 + line++ * 20, 100, 20, Color("Move to target", LabelColor32)); - - if (from.AccessLevel >= AccessLevel.GameMaster && from.AccessLevel > m.AccessLevel) - { - AddButton(246, 36 + line * 20, 0xFA5, 0xFA7, 8); - AddHtml(280, 38 + line++ * 20, 100, 20, Color("Disconnect", LabelColor32)); - - if (m.Alive) - { - AddButton(246, 36 + line * 20, 0xFA5, 0xFA7, 9); - AddHtml(280, 38 + line++ * 20, 100, 20, Color("Kill", LabelColor32)); - } - else - { - AddButton(246, 36 + line * 20, 0xFA5, 0xFA7, 10); - AddHtml(280, 38 + line++ * 20, 100, 20, Color("Resurrect", LabelColor32)); - } - } - - if (from.AccessLevel >= AccessLevel.Counselor && from.AccessLevel > m.AccessLevel) - { - AddButton(246, 36 + line * 20, 0xFA5, 0xFA7, 11); - AddHtml(280, 38 + line++ * 20, 100, 20, Color("Skills browser", LabelColor32)); - } - } - } - - private void Resend(Mobile to, RelayInfo info) - { - TextRelay te = info.GetTextEntry(0); - - to.SendGump(new ClientGump(to, m_State, te == null ? "" : te.Text)); - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (m_State == null) - return; - - Mobile focus = m_State.Mobile; - Mobile from = state.Mobile; - - if (focus == null) - { - from.SendMessage("That character is no longer online."); - return; - } - - if (focus.Deleted) - { - from.SendMessage("That character no longer exists."); - return; - } - - if (from != focus && focus.Hidden && from.AccessLevel < focus.AccessLevel && - (focus as PlayerMobile)?.VisibilityList.Contains(from) != true) - { - from.SendMessage("That character is no longer visible."); - return; - } - - switch (info.ButtonID) - { - case 1: // Tell - { - TextRelay text = info.GetTextEntry(0); - - if (text != null) - { - focus.SendMessage(0x482, "{0} tells you:", from.Name); - focus.SendMessage(0x482, text.Text); - - CommandLogging.WriteLine(from, "{0} {1} telling {2} \"{3}\" ", from.AccessLevel, - CommandLogging.Format(from), CommandLogging.Format(focus), text.Text); - } - - from.SendGump(new ClientGump(from, m_State)); - - break; - } - case 4: // Props - { - Resend(from, info); - - if (!BaseCommand.IsAccessible(from, focus)) - { - from.SendLocalizedMessage(500447); // That is not accessible. - } - else - { - from.SendGump(new PropertiesGump(from, focus)); - CommandLogging.WriteLine(from, "{0} {1} opening properties gump of {2} ", from.AccessLevel, - CommandLogging.Format(from), CommandLogging.Format(focus)); - } - - break; - } - case 5: // Go to - { - if (focus.Map == null || focus.Map == Map.Internal) - { - from.SendMessage("That character is not in the world."); - } - else - { - from.MoveToWorld(focus.Location, focus.Map); - Resend(from, info); - - CommandLogging.WriteLine(from, "{0} {1} going to {2}, Location {3}, Map {4}", from.AccessLevel, - CommandLogging.Format(from), CommandLogging.Format(focus), focus.Location, focus.Map); - } - - break; - } - case 6: // Get - { - if (from.Map == null || from.Map == Map.Internal) - { - from.SendMessage("You cannot bring that person here."); - } - else - { - focus.MoveToWorld(from.Location, from.Map); - Resend(from, info); - - CommandLogging.WriteLine(from, "{0} {1} bringing {2} to Location {3}, Map {4}", from.AccessLevel, - CommandLogging.Format(from), CommandLogging.Format(focus), from.Location, from.Map); - } - - break; - } - case 7: // Move - { - from.Target = new MoveTarget(focus); - Resend(from, info); - - break; - } - case 8: // Kick - { - if (from.AccessLevel >= AccessLevel.GameMaster && from.AccessLevel > focus.AccessLevel) - { - focus.Say("I've been kicked!"); - - m_State.Dispose(); - - CommandLogging.WriteLine(from, "{0} {1} kicking {2} ", from.AccessLevel, CommandLogging.Format(from), - CommandLogging.Format(focus)); - } - - break; - } - case 9: // Kill - { - if (from.AccessLevel >= AccessLevel.GameMaster && from.AccessLevel > focus.AccessLevel) - { - focus.Kill(); - CommandLogging.WriteLine(from, "{0} {1} killing {2} ", from.AccessLevel, CommandLogging.Format(from), - CommandLogging.Format(focus)); - } - - Resend(from, info); - - break; - } - case 10: // Res - { - if (from.AccessLevel >= AccessLevel.GameMaster && from.AccessLevel > focus.AccessLevel) - { - focus.PlaySound(0x214); - focus.FixedEffect(0x376A, 10, 16); - - focus.Resurrect(); - - CommandLogging.WriteLine(from, "{0} {1} resurrecting {2} ", from.AccessLevel, - CommandLogging.Format(from), CommandLogging.Format(focus)); - } - - Resend(from, info); - - break; - } - case 11: // Skills - { - Resend(from, info); - - if (from.AccessLevel > focus.AccessLevel) - { - from.SendGump(new SkillsGump(from, focus)); - CommandLogging.WriteLine(from, "{0} {1} Opening Skills gump of {2} ", from.AccessLevel, - CommandLogging.Format(from), CommandLogging.Format(focus)); - } - - break; - } - } - } - - public string Center(string text) => $"
{text}
"; - - public string Color(string text, int color) => $"{text}"; - } -} +using Server.Accounting; +using Server.Commands; +using Server.Commands.Generic; +using Server.Mobiles; +using Server.Network; +using Server.Targets; + +namespace Server.Gumps +{ + public class ClientGump : Gump + { + private const int LabelColor32 = 0xFFFFFF; + private readonly NetState m_State; + + public ClientGump(Mobile from, NetState state, string initialText = "") : base(30, 20) + { + if (state == null) + return; + + m_State = state; + + AddPage(0); + + AddBackground(0, 0, 400, 274, 5054); + + AddImageTiled(10, 10, 380, 19, 0xA40); + AddAlphaRegion(10, 10, 380, 19); + + AddImageTiled(10, 32, 380, 232, 0xA40); + AddAlphaRegion(10, 32, 380, 232); + + AddHtml(10, 10, 380, 20, Color(Center("User Information"), LabelColor32)); + + var line = 0; + + AddHtml(14, 36 + line * 20, 200, 20, Color("Address:", LabelColor32)); + AddHtml(70, 36 + line++ * 20, 200, 20, Color(state.ToString(), LabelColor32)); + + AddHtml(14, 36 + line * 20, 200, 20, Color("Client:", LabelColor32)); + AddHtml( + 70, + 36 + line++ * 20, + 200, + 20, + Color(state.Version == null ? "(null)" : state.Version.ToString(), LabelColor32) + ); + + AddHtml(14, 36 + line * 20, 200, 20, Color("Version:", LabelColor32)); + + var info = state.ExpansionInfo; + var expansionName = info.Name; + + AddHtml(70, 36 + line++ * 20, 200, 20, Color(expansionName, LabelColor32)); + + var a = state.Account as Account; + var m = state.Mobile; + + if (from.AccessLevel >= AccessLevel.GameMaster && a != null) + { + AddHtml(14, 36 + line * 20, 200, 20, Color("Account:", LabelColor32)); + AddHtml(70, 36 + line++ * 20, 200, 20, Color(a.Username, LabelColor32)); + } + + if (m != null) + { + AddHtml(14, 36 + line * 20, 200, 20, Color("Mobile:", LabelColor32)); + AddHtml(70, 36 + line++ * 20, 200, 20, Color($"{m.Name} (0x{m.Serial.Value:X})", LabelColor32)); + + AddHtml(14, 36 + line * 20, 200, 20, Color("Location:", LabelColor32)); + AddHtml(70, 36 + line++ * 20, 200, 20, Color($"{m.Location} [{m.Map}]", LabelColor32)); + + AddButton(13, 157, 0xFAB, 0xFAD, 1); + AddHtml(48, 158, 200, 20, Color("Send Message", LabelColor32)); + + AddImageTiled(12, 182, 376, 80, 0xA40); + AddImageTiled(13, 183, 374, 78, 0xBBC); + AddTextEntry(15, 183, 372, 78, 0x480, 0, ""); + + AddImageTiled(245, 35, 142, 144, 5058); + + AddImageTiled(246, 36, 140, 142, 0xA40); + AddAlphaRegion(246, 36, 140, 142); + + line = 0; + + if (BaseCommand.IsAccessible(from, m)) + { + AddButton(246, 36 + line * 20, 0xFA5, 0xFA7, 4); + AddHtml(280, 38 + line++ * 20, 100, 20, Color("Properties", LabelColor32)); + } + + if (from != m) + { + AddButton(246, 36 + line * 20, 0xFA5, 0xFA7, 5); + AddHtml(280, 38 + line++ * 20, 100, 20, Color("Go to them", LabelColor32)); + + AddButton(246, 36 + line * 20, 0xFA5, 0xFA7, 6); + AddHtml(280, 38 + line++ * 20, 100, 20, Color("Bring them here", LabelColor32)); + } + + AddButton(246, 36 + line * 20, 0xFA5, 0xFA7, 7); + AddHtml(280, 38 + line++ * 20, 100, 20, Color("Move to target", LabelColor32)); + + if (from.AccessLevel >= AccessLevel.GameMaster && from.AccessLevel > m.AccessLevel) + { + AddButton(246, 36 + line * 20, 0xFA5, 0xFA7, 8); + AddHtml(280, 38 + line++ * 20, 100, 20, Color("Disconnect", LabelColor32)); + + if (m.Alive) + { + AddButton(246, 36 + line * 20, 0xFA5, 0xFA7, 9); + AddHtml(280, 38 + line++ * 20, 100, 20, Color("Kill", LabelColor32)); + } + else + { + AddButton(246, 36 + line * 20, 0xFA5, 0xFA7, 10); + AddHtml(280, 38 + line++ * 20, 100, 20, Color("Resurrect", LabelColor32)); + } + } + + if (from.AccessLevel >= AccessLevel.Counselor && from.AccessLevel > m.AccessLevel) + { + AddButton(246, 36 + line * 20, 0xFA5, 0xFA7, 11); + AddHtml(280, 38 + line++ * 20, 100, 20, Color("Skills browser", LabelColor32)); + } + } + } + + private void Resend(Mobile to, RelayInfo info) + { + var te = info.GetTextEntry(0); + + to.SendGump(new ClientGump(to, m_State, te == null ? "" : te.Text)); + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (m_State == null) + return; + + var focus = m_State.Mobile; + var from = state.Mobile; + + if (focus == null) + { + from.SendMessage("That character is no longer online."); + return; + } + + if (focus.Deleted) + { + from.SendMessage("That character no longer exists."); + return; + } + + if (from != focus && focus.Hidden && from.AccessLevel < focus.AccessLevel && + (focus as PlayerMobile)?.VisibilityList.Contains(from) != true) + { + from.SendMessage("That character is no longer visible."); + return; + } + + switch (info.ButtonID) + { + case 1: // Tell + { + var text = info.GetTextEntry(0); + + if (text != null) + { + focus.SendMessage(0x482, "{0} tells you:", from.Name); + focus.SendMessage(0x482, text.Text); + + CommandLogging.WriteLine( + from, + "{0} {1} telling {2} \"{3}\" ", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(focus), + text.Text + ); + } + + from.SendGump(new ClientGump(from, m_State)); + + break; + } + case 4: // Props + { + Resend(from, info); + + if (!BaseCommand.IsAccessible(from, focus)) + { + from.SendLocalizedMessage(500447); // That is not accessible. + } + else + { + from.SendGump(new PropertiesGump(from, focus)); + CommandLogging.WriteLine( + from, + "{0} {1} opening properties gump of {2} ", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(focus) + ); + } + + break; + } + case 5: // Go to + { + if (focus.Map == null || focus.Map == Map.Internal) + { + from.SendMessage("That character is not in the world."); + } + else + { + from.MoveToWorld(focus.Location, focus.Map); + Resend(from, info); + + CommandLogging.WriteLine( + from, + "{0} {1} going to {2}, Location {3}, Map {4}", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(focus), + focus.Location, + focus.Map + ); + } + + break; + } + case 6: // Get + { + if (from.Map == null || from.Map == Map.Internal) + { + from.SendMessage("You cannot bring that person here."); + } + else + { + focus.MoveToWorld(from.Location, from.Map); + Resend(from, info); + + CommandLogging.WriteLine( + from, + "{0} {1} bringing {2} to Location {3}, Map {4}", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(focus), + from.Location, + from.Map + ); + } + + break; + } + case 7: // Move + { + from.Target = new MoveTarget(focus); + Resend(from, info); + + break; + } + case 8: // Kick + { + if (from.AccessLevel >= AccessLevel.GameMaster && from.AccessLevel > focus.AccessLevel) + { + focus.Say("I've been kicked!"); + + m_State.Dispose(); + + CommandLogging.WriteLine( + from, + "{0} {1} kicking {2} ", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(focus) + ); + } + + break; + } + case 9: // Kill + { + if (from.AccessLevel >= AccessLevel.GameMaster && from.AccessLevel > focus.AccessLevel) + { + focus.Kill(); + CommandLogging.WriteLine( + from, + "{0} {1} killing {2} ", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(focus) + ); + } + + Resend(from, info); + + break; + } + case 10: // Res + { + if (from.AccessLevel >= AccessLevel.GameMaster && from.AccessLevel > focus.AccessLevel) + { + focus.PlaySound(0x214); + focus.FixedEffect(0x376A, 10, 16); + + focus.Resurrect(); + + CommandLogging.WriteLine( + from, + "{0} {1} resurrecting {2} ", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(focus) + ); + } + + Resend(from, info); + + break; + } + case 11: // Skills + { + Resend(from, info); + + if (from.AccessLevel > focus.AccessLevel) + { + from.SendGump(new SkillsGump(from, focus)); + CommandLogging.WriteLine( + from, + "{0} {1} Opening Skills gump of {2} ", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(focus) + ); + } + + break; + } + } + } + + public string Center(string text) => $"
{text}
"; + + public string Color(string text, int color) => $"{text}"; + } +} diff --git a/Projects/UOContent/Gumps/CommentsGump.cs b/Projects/UOContent/Gumps/CommentsGump.cs index c4cf105d6..58e376b41 100644 --- a/Projects/UOContent/Gumps/CommentsGump.cs +++ b/Projects/UOContent/Gumps/CommentsGump.cs @@ -1,114 +1,113 @@ -using System.Collections.Generic; -using Server.Accounting; -using Server.Network; -using Server.Prompts; -using Server.Targeting; - -namespace Server.Gumps -{ - public class CommentsGump : Gump - { - private readonly Account m_Acct; - - public CommentsGump(Account acct) : base(30, 30) - { - m_Acct = acct; - - AddPage(0); - AddImageTiled(0, 0, 410, 448, 0xA40); - AddAlphaRegion(1, 1, 408, 446); - - string title = $"Comments for '{acct.Username}'"; - int x = 205 - title.Length / 2 * 7; - if (x < 120) - x = 120; - AddLabel(x, 12, 2100, title); - - AddPage(1); - AddButton(12, 12, 0xFA8, 0xFAA, 0x7F); - AddLabel(48, 12, 2100, "Add Comment"); - - List list = acct.Comments; - if (list.Count > 0) - for (int i = 0; i < list.Count; ++i) - { - AccountComment comment = list[i]; - - if (i >= 5 && i % 5 == 0) - { - AddButton(368, 12, 0xFA5, 0xFA7, 0, GumpButtonType.Page, i / 5 + 1); - AddLabel(298, 12, 2100, "Next Page"); - AddPage(i / 5 + 1); - AddButton(12, 12, 0xFAE, 0xFB0, 0, GumpButtonType.Page, i / 5); - AddLabel(48, 12, 2100, "Prev Page"); - } - - string html = - $"[Added By: {comment.AddedBy} on {comment.LastModified.ToString("H:mm M/d/yy")}]
{comment.Content}"; - AddHtml(12, 44 + i % 5 * 80, 386, 70, html, true, true); - } - else - AddLabel(12, 44, 2100, "There are no comments for this account."); - } - - public static void Initialize() - { - CommandSystem.Register("Comments", AccessLevel.Counselor, Comments_OnCommand); - } - - [Usage("Comments")] - [Description("View/Modify/Add account comments.")] - private static void Comments_OnCommand(CommandEventArgs args) - { - args.Mobile.SendMessage("Select the player to view account comments."); - args.Mobile.BeginTarget(-1, false, TargetFlags.None, OnTarget); - } - - private static void OnTarget(Mobile from, object target) - { - if (!(target is Mobile m) || !m.Player) - { - from.SendMessage("You must target a player."); - return; - } - - if (m.Account == null) - from.SendMessage("That player doesn't have an account loaded... weird."); - else - from.SendGump(new CommentsGump((Account)m.Account)); - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (info.ButtonID == 0x7F) - { - state.Mobile.SendMessage("Enter the text for the account comment (or press [Esc] to cancel):"); - state.Mobile.Prompt = new CommentPrompt(m_Acct); - } - } - - public class CommentPrompt : Prompt - { - private readonly Account m_Acct; - - public CommentPrompt(Account acct) => m_Acct = acct; - - public override void OnCancel(Mobile from) - { - from.CloseGump(); - from.SendGump(new CommentsGump(m_Acct)); - base.OnCancel(from); - } - - public override void OnResponse(Mobile from, string text) - { - base.OnResponse(from, text); - from.SendMessage("Comment added."); - // m_Acct.AddComment( from.Name, text ); - m_Acct.Comments.Add(new AccountComment(from.Name, text)); - from.CloseGump(); - from.SendGump(new CommentsGump(m_Acct)); - } - } - } -} +using Server.Accounting; +using Server.Network; +using Server.Prompts; +using Server.Targeting; + +namespace Server.Gumps +{ + public class CommentsGump : Gump + { + private readonly Account m_Acct; + + public CommentsGump(Account acct) : base(30, 30) + { + m_Acct = acct; + + AddPage(0); + AddImageTiled(0, 0, 410, 448, 0xA40); + AddAlphaRegion(1, 1, 408, 446); + + var title = $"Comments for '{acct.Username}'"; + var x = 205 - title.Length / 2 * 7; + if (x < 120) + x = 120; + AddLabel(x, 12, 2100, title); + + AddPage(1); + AddButton(12, 12, 0xFA8, 0xFAA, 0x7F); + AddLabel(48, 12, 2100, "Add Comment"); + + var list = acct.Comments; + if (list.Count > 0) + for (var i = 0; i < list.Count; ++i) + { + var comment = list[i]; + + if (i >= 5 && i % 5 == 0) + { + AddButton(368, 12, 0xFA5, 0xFA7, 0, GumpButtonType.Page, i / 5 + 1); + AddLabel(298, 12, 2100, "Next Page"); + AddPage(i / 5 + 1); + AddButton(12, 12, 0xFAE, 0xFB0, 0, GumpButtonType.Page, i / 5); + AddLabel(48, 12, 2100, "Prev Page"); + } + + var html = + $"[Added By: {comment.AddedBy} on {comment.LastModified.ToString("H:mm M/d/yy")}]
{comment.Content}"; + AddHtml(12, 44 + i % 5 * 80, 386, 70, html, true, true); + } + else + AddLabel(12, 44, 2100, "There are no comments for this account."); + } + + public static void Initialize() + { + CommandSystem.Register("Comments", AccessLevel.Counselor, Comments_OnCommand); + } + + [Usage("Comments")] + [Description("View/Modify/Add account comments.")] + private static void Comments_OnCommand(CommandEventArgs args) + { + args.Mobile.SendMessage("Select the player to view account comments."); + args.Mobile.BeginTarget(-1, false, TargetFlags.None, OnTarget); + } + + private static void OnTarget(Mobile from, object target) + { + if (!(target is Mobile m) || !m.Player) + { + from.SendMessage("You must target a player."); + return; + } + + if (m.Account == null) + from.SendMessage("That player doesn't have an account loaded... weird."); + else + from.SendGump(new CommentsGump((Account)m.Account)); + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (info.ButtonID == 0x7F) + { + state.Mobile.SendMessage("Enter the text for the account comment (or press [Esc] to cancel):"); + state.Mobile.Prompt = new CommentPrompt(m_Acct); + } + } + + public class CommentPrompt : Prompt + { + private readonly Account m_Acct; + + public CommentPrompt(Account acct) => m_Acct = acct; + + public override void OnCancel(Mobile from) + { + from.CloseGump(); + from.SendGump(new CommentsGump(m_Acct)); + base.OnCancel(from); + } + + public override void OnResponse(Mobile from, string text) + { + base.OnResponse(from, text); + from.SendMessage("Comment added."); + // m_Acct.AddComment( from.Name, text ); + m_Acct.Comments.Add(new AccountComment(from.Name, text)); + from.CloseGump(); + from.SendGump(new CommentsGump(m_Acct)); + } + } + } +} diff --git a/Projects/UOContent/Gumps/ConfirmBreakCrystalGump.cs b/Projects/UOContent/Gumps/ConfirmBreakCrystalGump.cs index 0adf559a9..8664ed4ea 100644 --- a/Projects/UOContent/Gumps/ConfirmBreakCrystalGump.cs +++ b/Projects/UOContent/Gumps/ConfirmBreakCrystalGump.cs @@ -1,50 +1,54 @@ -using Server.Items; -using Server.Mobiles; - -namespace Server.Gumps -{ - public class ConfirmBreakCrystalGump : BaseConfirmGump - { - private readonly BaseImprisonedMobile m_Item; - - public ConfirmBreakCrystalGump(BaseImprisonedMobile item) => m_Item = item; - - public override int LabelNumber => - 1075084; // This statuette will be destroyed when its trapped creature is summoned. The creature will be bonded to you but will disappear if released.

Do you wish to proceed? - - public override void Confirm(Mobile from) - { - if (m_Item?.Deleted != false) - return; - - BaseCreature summon = m_Item.Summon; - - if (summon == null) - return; - - if (!summon.SetControlMaster(from)) - { - summon.Delete(); - } - else - { - from.SendLocalizedMessage(1049666); // Your pet has bonded with you! - - summon.MoveToWorld(from.Location, from.Map); - summon.IsBonded = true; - - summon.Skills.Wrestling.Base = 100; - summon.Skills.Tactics.Base = 100; - summon.Skills.MagicResist.Base = 100; - summon.Skills.Anatomy.Base = 100; - - Effects.PlaySound(summon.Location, summon.Map, summon.BaseSoundID); - Effects.SendLocationParticles(EffectItem.Create(summon.Location, summon.Map, EffectItem.DefaultDuration), - 0x3728, 1, 10, 0x26B6); - - m_Item.Release(from, summon); - m_Item.Delete(); - } - } - } -} +using Server.Items; + +namespace Server.Gumps +{ + public class ConfirmBreakCrystalGump : BaseConfirmGump + { + private readonly BaseImprisonedMobile m_Item; + + public ConfirmBreakCrystalGump(BaseImprisonedMobile item) => m_Item = item; + + public override int LabelNumber => + 1075084; // This statuette will be destroyed when its trapped creature is summoned. The creature will be bonded to you but will disappear if released.

Do you wish to proceed? + + public override void Confirm(Mobile from) + { + if (m_Item?.Deleted != false) + return; + + var summon = m_Item.Summon; + + if (summon == null) + return; + + if (!summon.SetControlMaster(from)) + { + summon.Delete(); + } + else + { + from.SendLocalizedMessage(1049666); // Your pet has bonded with you! + + summon.MoveToWorld(from.Location, from.Map); + summon.IsBonded = true; + + summon.Skills.Wrestling.Base = 100; + summon.Skills.Tactics.Base = 100; + summon.Skills.MagicResist.Base = 100; + summon.Skills.Anatomy.Base = 100; + + Effects.PlaySound(summon.Location, summon.Map, summon.BaseSoundID); + Effects.SendLocationParticles( + EffectItem.Create(summon.Location, summon.Map, EffectItem.DefaultDuration), + 0x3728, + 1, + 10, + 0x26B6 + ); + + m_Item.Release(from, summon); + m_Item.Delete(); + } + } + } +} diff --git a/Projects/UOContent/Gumps/ConfirmHeritageGump.cs b/Projects/UOContent/Gumps/ConfirmHeritageGump.cs index 28497d464..e1eec6f98 100644 --- a/Projects/UOContent/Gumps/ConfirmHeritageGump.cs +++ b/Projects/UOContent/Gumps/ConfirmHeritageGump.cs @@ -1,74 +1,74 @@ -using System; -using Server.Items; -using Server.Network; -using Server.Utilities; - -namespace Server.Gumps -{ - public class ConfirmHeritageGump : Gump - { - private readonly Type[] m_Selected; - private readonly HeritageToken m_Token; - - public ConfirmHeritageGump(HeritageToken token, Type[] selected, int cliloc) : base(60, 36) - { - m_Token = token; - m_Selected = selected; - - AddPage(0); - - AddBackground(0, 0, 291, 99, 0x13BE); - AddImageTiled(5, 6, 280, 20, 0xA40); - AddHtmlLocalized(9, 8, 280, 20, 1070972, 0x7FFF); // Click "OKAY" to redeem the following promotional item: - AddImageTiled(5, 31, 280, 40, 0xA40); - AddHtmlLocalized(9, 35, 272, 40, cliloc, 0x7FFF); - AddButton(180, 73, 0xFB7, 0xFB8, (int)Buttons.Okay); - AddHtmlLocalized(215, 75, 100, 20, 1011036, 0x7FFF); // OKAY - AddButton(5, 73, 0xFB1, 0xFB2, (int)Buttons.Cancel); - AddHtmlLocalized(40, 75, 100, 20, 1060051, 0x7FFF); // CANCEL - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Token?.Deleted != false) - return; - - switch (info.ButtonID) - { - case (int)Buttons.Okay: - - Item item = null; - - foreach (Type type in m_Selected) - { - try - { - item = ActivatorUtil.CreateInstance(type) as Item; - } - catch (Exception ex) - { - Console.WriteLine(ex.Message); - Console.WriteLine(ex.StackTrace); - } - - if (item != null) - { - m_Token.Delete(); - sender.Mobile.AddToBackpack(item); - } - } - - break; - case (int)Buttons.Cancel: - sender.Mobile.SendGump(new HeritageTokenGump(m_Token)); - break; - } - } - - private enum Buttons - { - Cancel, - Okay - } - } -} +using System; +using Server.Items; +using Server.Network; +using Server.Utilities; + +namespace Server.Gumps +{ + public class ConfirmHeritageGump : Gump + { + private readonly Type[] m_Selected; + private readonly HeritageToken m_Token; + + public ConfirmHeritageGump(HeritageToken token, Type[] selected, int cliloc) : base(60, 36) + { + m_Token = token; + m_Selected = selected; + + AddPage(0); + + AddBackground(0, 0, 291, 99, 0x13BE); + AddImageTiled(5, 6, 280, 20, 0xA40); + AddHtmlLocalized(9, 8, 280, 20, 1070972, 0x7FFF); // Click "OKAY" to redeem the following promotional item: + AddImageTiled(5, 31, 280, 40, 0xA40); + AddHtmlLocalized(9, 35, 272, 40, cliloc, 0x7FFF); + AddButton(180, 73, 0xFB7, 0xFB8, (int)Buttons.Okay); + AddHtmlLocalized(215, 75, 100, 20, 1011036, 0x7FFF); // OKAY + AddButton(5, 73, 0xFB1, 0xFB2, (int)Buttons.Cancel); + AddHtmlLocalized(40, 75, 100, 20, 1060051, 0x7FFF); // CANCEL + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Token?.Deleted != false) + return; + + switch (info.ButtonID) + { + case (int)Buttons.Okay: + + Item item = null; + + foreach (var type in m_Selected) + { + try + { + item = ActivatorUtil.CreateInstance(type) as Item; + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + Console.WriteLine(ex.StackTrace); + } + + if (item != null) + { + m_Token.Delete(); + sender.Mobile.AddToBackpack(item); + } + } + + break; + case (int)Buttons.Cancel: + sender.Mobile.SendGump(new HeritageTokenGump(m_Token)); + break; + } + } + + private enum Buttons + { + Cancel, + Okay + } + } +} diff --git a/Projects/UOContent/Gumps/ConfirmHouseResize.cs b/Projects/UOContent/Gumps/ConfirmHouseResize.cs index 02126a76b..6151616d0 100644 --- a/Projects/UOContent/Gumps/ConfirmHouseResize.cs +++ b/Projects/UOContent/Gumps/ConfirmHouseResize.cs @@ -1,158 +1,164 @@ -using Server.Guilds; -using Server.Items; -using Server.Multis; -using Server.Network; - -namespace Server.Gumps -{ - public class ConfirmHouseResize : Gump - { - private readonly BaseHouse m_House; - private readonly Mobile m_Mobile; - - public ConfirmHouseResize(Mobile mobile, BaseHouse house) : base(110, 100) - { - m_Mobile = mobile; - m_House = house; - - mobile.CloseGump(); - - Closable = false; - - AddPage(0); - - AddBackground(0, 0, 420, 280, 0x13BE); - AddImageTiled(10, 10, 400, 20, 0xA40); - AddAlphaRegion(10, 10, 400, 20); - AddHtmlLocalized(10, 10, 400, 20, 1060635, 0x7800); //
WARNING
- AddImageTiled(10, 40, 400, 200, 0xA40); - AddAlphaRegion(10, 40, 400, 200); - - /* You are attempting to resize your house. You will be refunded the house's - value directly to your bank box. All items in the house will *remain behind* - and can be *freely picked up by anyone*. Once the house is demolished, however, - only this account will be able to place on the land for one hour. This *will* - circumvent the normal 7-day waiting period (if it applies to you). This action - will not un-condemn any other houses on your account. If you have other, - grandfathered houses, this action *WILL* condemn them. Are you sure you wish - to continue?*/ - AddHtmlLocalized(10, 40, 400, 200, 1080196, 0x7F00, false, true); - - AddImageTiled(10, 250, 400, 20, 0xA40); - AddAlphaRegion(10, 250, 400, 20); - AddButton(10, 250, 0xFA5, 0xFA7, 1); - AddButton(210, 250, 0xFA5, 0xFA7, 0); - AddHtmlLocalized(40, 250, 170, 20, 1011036, 0x7FFF); // OKAY - AddHtmlLocalized(240, 250, 170, 20, 1011012, 0x7FFF); // CANCEL - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (info.ButtonID == 1 && !m_House.Deleted) - { - if (m_House.IsOwner(m_Mobile)) - { - if (m_House.MovingCrate != null || m_House.InternalizedVendors.Count > 0) - { - m_Mobile.SendLocalizedMessage( - 1080455); // You can not resize your house at this time. Please remove all items fom the moving crate and try again. - return; - } - - if (!Guild.NewGuildSystem && m_House.FindGuildstone() != null) - { - m_Mobile.SendLocalizedMessage(501389); // You cannot redeed a house with a guildstone inside. - return; - } - - /*else if (m_House.PlayerVendors.Count > 0) - { - m_Mobile.SendLocalizedMessage( 503236 ); // You need to collect your vendor's belongings before moving. - return; - }*/ - if (m_House.HasRentedVendors && m_House.VendorInventories.Count > 0) - { - m_Mobile.SendLocalizedMessage( - 1062679); // You cannot do that that while you still have contract vendors or unclaimed contract vendor inventory in your house. - return; - } - - if (m_House.HasRentedVendors) - { - m_Mobile.SendLocalizedMessage( - 1062680); // You cannot do that that while you still have contract vendors in your house. - return; - } - - if (m_House.VendorInventories.Count > 0) - { - m_Mobile.SendLocalizedMessage( - 1062681); // You cannot do that that while you still have unclaimed contract vendor inventory in your house. - return; - } - - if (m_Mobile.AccessLevel >= AccessLevel.GameMaster) - { - m_Mobile.SendMessage("You do not get a refund for your house as you are not a player"); - m_House.RemoveKeys(m_Mobile); - new TempNoHousingRegion(m_House, m_Mobile); - m_House.Delete(); - } - else - { - Item toGive = null; - - if (m_House.IsAosRules) - { - if (m_House.Price > 0) - toGive = new BankCheck(m_House.Price); - else - toGive = m_House.GetDeed(); - } - else - { - toGive = m_House.GetDeed(); - - if (toGive == null && m_House.Price > 0) - toGive = new BankCheck(m_House.Price); - } - - if (toGive != null) - { - BankBox box = m_Mobile.BankBox; - - if (box.TryDropItem(m_Mobile, toGive, false)) - { - if (toGive is BankCheck check) - m_Mobile.SendLocalizedMessage(1060397, - check.Worth.ToString()); // ~1_AMOUNT~ gold has been deposited into your bank box. - - m_House.RemoveKeys(m_Mobile); - new TempNoHousingRegion(m_House, m_Mobile); - m_House.Delete(); - } - else - { - toGive.Delete(); - m_Mobile.SendLocalizedMessage(500390); // Your bank box is full. - } - } - else - { - m_Mobile.SendMessage("Unable to refund house."); - } - } - } - else - { - m_Mobile.SendLocalizedMessage(501320); // Only the house owner may do this. - } - } - else if (info.ButtonID == 0) - { - m_Mobile.CloseGump(); - m_Mobile.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Customize, m_Mobile, m_House)); - } - } - } -} +using Server.Guilds; +using Server.Items; +using Server.Multis; +using Server.Network; + +namespace Server.Gumps +{ + public class ConfirmHouseResize : Gump + { + private readonly BaseHouse m_House; + private readonly Mobile m_Mobile; + + public ConfirmHouseResize(Mobile mobile, BaseHouse house) : base(110, 100) + { + m_Mobile = mobile; + m_House = house; + + mobile.CloseGump(); + + Closable = false; + + AddPage(0); + + AddBackground(0, 0, 420, 280, 0x13BE); + AddImageTiled(10, 10, 400, 20, 0xA40); + AddAlphaRegion(10, 10, 400, 20); + AddHtmlLocalized(10, 10, 400, 20, 1060635, 0x7800); //
WARNING
+ AddImageTiled(10, 40, 400, 200, 0xA40); + AddAlphaRegion(10, 40, 400, 200); + + /* You are attempting to resize your house. You will be refunded the house's + value directly to your bank box. All items in the house will *remain behind* + and can be *freely picked up by anyone*. Once the house is demolished, however, + only this account will be able to place on the land for one hour. This *will* + circumvent the normal 7-day waiting period (if it applies to you). This action + will not un-condemn any other houses on your account. If you have other, + grandfathered houses, this action *WILL* condemn them. Are you sure you wish + to continue?*/ + AddHtmlLocalized(10, 40, 400, 200, 1080196, 0x7F00, false, true); + + AddImageTiled(10, 250, 400, 20, 0xA40); + AddAlphaRegion(10, 250, 400, 20); + AddButton(10, 250, 0xFA5, 0xFA7, 1); + AddButton(210, 250, 0xFA5, 0xFA7, 0); + AddHtmlLocalized(40, 250, 170, 20, 1011036, 0x7FFF); // OKAY + AddHtmlLocalized(240, 250, 170, 20, 1011012, 0x7FFF); // CANCEL + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (info.ButtonID == 1 && !m_House.Deleted) + { + if (m_House.IsOwner(m_Mobile)) + { + if (m_House.MovingCrate != null || m_House.InternalizedVendors.Count > 0) + { + m_Mobile.SendLocalizedMessage( + 1080455 + ); // You can not resize your house at this time. Please remove all items fom the moving crate and try again. + return; + } + + if (!Guild.NewGuildSystem && m_House.FindGuildstone() != null) + { + m_Mobile.SendLocalizedMessage(501389); // You cannot redeed a house with a guildstone inside. + return; + } + + /*else if (m_House.PlayerVendors.Count > 0) + { + m_Mobile.SendLocalizedMessage( 503236 ); // You need to collect your vendor's belongings before moving. + return; + }*/ + if (m_House.HasRentedVendors && m_House.VendorInventories.Count > 0) + { + m_Mobile.SendLocalizedMessage( + 1062679 + ); // You cannot do that that while you still have contract vendors or unclaimed contract vendor inventory in your house. + return; + } + + if (m_House.HasRentedVendors) + { + m_Mobile.SendLocalizedMessage( + 1062680 + ); // You cannot do that that while you still have contract vendors in your house. + return; + } + + if (m_House.VendorInventories.Count > 0) + { + m_Mobile.SendLocalizedMessage( + 1062681 + ); // You cannot do that that while you still have unclaimed contract vendor inventory in your house. + return; + } + + if (m_Mobile.AccessLevel >= AccessLevel.GameMaster) + { + m_Mobile.SendMessage("You do not get a refund for your house as you are not a player"); + m_House.RemoveKeys(m_Mobile); + new TempNoHousingRegion(m_House, m_Mobile); + m_House.Delete(); + } + else + { + Item toGive = null; + + if (m_House.IsAosRules) + { + if (m_House.Price > 0) + toGive = new BankCheck(m_House.Price); + else + toGive = m_House.GetDeed(); + } + else + { + toGive = m_House.GetDeed(); + + if (toGive == null && m_House.Price > 0) + toGive = new BankCheck(m_House.Price); + } + + if (toGive != null) + { + var box = m_Mobile.BankBox; + + if (box.TryDropItem(m_Mobile, toGive, false)) + { + if (toGive is BankCheck check) + m_Mobile.SendLocalizedMessage( + 1060397, + check.Worth.ToString() + ); // ~1_AMOUNT~ gold has been deposited into your bank box. + + m_House.RemoveKeys(m_Mobile); + new TempNoHousingRegion(m_House, m_Mobile); + m_House.Delete(); + } + else + { + toGive.Delete(); + m_Mobile.SendLocalizedMessage(500390); // Your bank box is full. + } + } + else + { + m_Mobile.SendMessage("Unable to refund house."); + } + } + } + else + { + m_Mobile.SendLocalizedMessage(501320); // Only the house owner may do this. + } + } + else if (info.ButtonID == 0) + { + m_Mobile.CloseGump(); + m_Mobile.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Customize, m_Mobile, m_House)); + } + } + } +} diff --git a/Projects/UOContent/Gumps/ConfirmReleaseGump.cs b/Projects/UOContent/Gumps/ConfirmReleaseGump.cs index e947eae2b..0dd5f204a 100644 --- a/Projects/UOContent/Gumps/ConfirmReleaseGump.cs +++ b/Projects/UOContent/Gumps/ConfirmReleaseGump.cs @@ -1,42 +1,42 @@ -using Server.Mobiles; -using Server.Network; - -namespace Server.Gumps -{ - public class ConfirmReleaseGump : Gump - { - private readonly Mobile m_From; - private readonly BaseCreature m_Pet; - - public ConfirmReleaseGump(Mobile from, BaseCreature pet) : base(50, 50) - { - m_From = from; - m_Pet = pet; - - m_From.CloseGump(); - - AddPage(0); - - AddBackground(0, 0, 270, 120, 5054); - AddBackground(10, 10, 250, 100, 3000); - - AddHtmlLocalized(20, 15, 230, 60, 1046257, true, true); // Are you sure you want to release your pet? - - AddButton(20, 80, 4005, 4007, 2); - AddHtmlLocalized(55, 80, 75, 20, 1011011); // CONTINUE - - AddButton(135, 80, 4005, 4007, 1); - AddHtmlLocalized(170, 80, 75, 20, 1011012); // CANCEL - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID != 2 || m_Pet.Deleted || - !(m_Pet.Controlled && m_From == m_Pet.ControlMaster && - m_From.CheckAlive() && m_Pet.Map == m_From.Map && m_Pet.InRange(m_From, 14))) - return; - m_Pet.ControlTarget = null; - m_Pet.ControlOrder = OrderType.Release; - } - } -} +using Server.Mobiles; +using Server.Network; + +namespace Server.Gumps +{ + public class ConfirmReleaseGump : Gump + { + private readonly Mobile m_From; + private readonly BaseCreature m_Pet; + + public ConfirmReleaseGump(Mobile from, BaseCreature pet) : base(50, 50) + { + m_From = from; + m_Pet = pet; + + m_From.CloseGump(); + + AddPage(0); + + AddBackground(0, 0, 270, 120, 5054); + AddBackground(10, 10, 250, 100, 3000); + + AddHtmlLocalized(20, 15, 230, 60, 1046257, true, true); // Are you sure you want to release your pet? + + AddButton(20, 80, 4005, 4007, 2); + AddHtmlLocalized(55, 80, 75, 20, 1011011); // CONTINUE + + AddButton(135, 80, 4005, 4007, 1); + AddHtmlLocalized(170, 80, 75, 20, 1011012); // CANCEL + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID != 2 || m_Pet.Deleted || + !(m_Pet.Controlled && m_From == m_Pet.ControlMaster && + m_From.CheckAlive() && m_Pet.Map == m_From.Map && m_Pet.InRange(m_From, 14))) + return; + m_Pet.ControlTarget = null; + m_Pet.ControlOrder = OrderType.Release; + } + } +} diff --git a/Projects/UOContent/Gumps/DawnsMusicBoxGump.cs b/Projects/UOContent/Gumps/DawnsMusicBoxGump.cs index 9a3714c0d..ed8bb1d8b 100644 --- a/Projects/UOContent/Gumps/DawnsMusicBoxGump.cs +++ b/Projects/UOContent/Gumps/DawnsMusicBoxGump.cs @@ -1,86 +1,87 @@ -using Server.Items; -using Server.Network; - -namespace Server.Gumps -{ - public class DawnsMusicBoxGump : Gump - { - private readonly DawnsMusicBox m_Box; - - public DawnsMusicBoxGump(DawnsMusicBox box) - : base(60, 36) - { - m_Box = box; - - AddPage(0); - - AddBackground(0, 0, 273, 324, 0x13BE); - AddImageTiled(10, 10, 253, 20, 0xA40); - AddImageTiled(10, 40, 253, 244, 0xA40); - AddImageTiled(10, 294, 253, 20, 0xA40); - AddAlphaRegion(10, 10, 253, 304); - AddButton(10, 294, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL - AddHtmlLocalized(14, 12, 273, 20, 1075130, 0x7FFF); // Choose a track to play - - int page = 1; - int i, y = 49; - - AddPage(page); - - for (i = 0; i < m_Box.Tracks.Count; i++, y += 24) - { - DawnsMusicInfo info = DawnsMusicBox.GetInfo(m_Box.Tracks[i]); - - if (i > 0 && i % 10 == 0) - { - AddButton(228, 294, 0xFA5, 0xFA6, 0, GumpButtonType.Page, page + 1); - - AddPage(page + 1); - y = 49; - - AddButton(193, 294, 0xFAE, 0xFAF, 0, GumpButtonType.Page, page); - - page++; - } - - if (info == null) - continue; - - AddButton(19, y, 0x845, 0x846, 100 + i); - AddHtmlLocalized(44, y - 2, 213, 20, info.Name, 0x7FFF); - } - - if (i % 10 == 0) - { - AddButton(228, 294, 0xFA5, 0xFA6, 0, GumpButtonType.Page, page + 1); - - AddPage(page + 1); - y = 49; - - AddButton(193, 294, 0xFAE, 0xFAF, 0, GumpButtonType.Page, page); - } - - AddButton(19, y, 0x845, 0x846, 1); - AddHtmlLocalized(44, y - 2, 213, 20, 1075207, 0x7FFF); // Stop Song - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Box?.Deleted != false) - return; - - Mobile m = sender.Mobile; - - if (!m_Box.IsChildOf(m.Backpack) && !m_Box.IsLockedDown) - m.SendLocalizedMessage( - 1061856); // You must have the item in your backpack or locked down in order to use it. - else if (m_Box.IsLockedDown && !m_Box.HasAccces(m)) - m.SendLocalizedMessage(502691); // You must be the owner to use this. - else if (info.ButtonID == 1) - m_Box.EndMusic(m); - else if (info.ButtonID >= 100 && info.ButtonID - 100 < m_Box.Tracks.Count) - m_Box.PlayMusic(m, m_Box.Tracks[info.ButtonID - 100]); - } - } -} +using Server.Items; +using Server.Network; + +namespace Server.Gumps +{ + public class DawnsMusicBoxGump : Gump + { + private readonly DawnsMusicBox m_Box; + + public DawnsMusicBoxGump(DawnsMusicBox box) + : base(60, 36) + { + m_Box = box; + + AddPage(0); + + AddBackground(0, 0, 273, 324, 0x13BE); + AddImageTiled(10, 10, 253, 20, 0xA40); + AddImageTiled(10, 40, 253, 244, 0xA40); + AddImageTiled(10, 294, 253, 20, 0xA40); + AddAlphaRegion(10, 10, 253, 304); + AddButton(10, 294, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL + AddHtmlLocalized(14, 12, 273, 20, 1075130, 0x7FFF); // Choose a track to play + + var page = 1; + int i, y = 49; + + AddPage(page); + + for (i = 0; i < m_Box.Tracks.Count; i++, y += 24) + { + var info = DawnsMusicBox.GetInfo(m_Box.Tracks[i]); + + if (i > 0 && i % 10 == 0) + { + AddButton(228, 294, 0xFA5, 0xFA6, 0, GumpButtonType.Page, page + 1); + + AddPage(page + 1); + y = 49; + + AddButton(193, 294, 0xFAE, 0xFAF, 0, GumpButtonType.Page, page); + + page++; + } + + if (info == null) + continue; + + AddButton(19, y, 0x845, 0x846, 100 + i); + AddHtmlLocalized(44, y - 2, 213, 20, info.Name, 0x7FFF); + } + + if (i % 10 == 0) + { + AddButton(228, 294, 0xFA5, 0xFA6, 0, GumpButtonType.Page, page + 1); + + AddPage(page + 1); + y = 49; + + AddButton(193, 294, 0xFAE, 0xFAF, 0, GumpButtonType.Page, page); + } + + AddButton(19, y, 0x845, 0x846, 1); + AddHtmlLocalized(44, y - 2, 213, 20, 1075207, 0x7FFF); // Stop Song + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Box?.Deleted != false) + return; + + var m = sender.Mobile; + + if (!m_Box.IsChildOf(m.Backpack) && !m_Box.IsLockedDown) + m.SendLocalizedMessage( + 1061856 + ); // You must have the item in your backpack or locked down in order to use it. + else if (m_Box.IsLockedDown && !m_Box.HasAccces(m)) + m.SendLocalizedMessage(502691); // You must be the owner to use this. + else if (info.ButtonID == 1) + m_Box.EndMusic(m); + else if (info.ButtonID >= 100 && info.ButtonID - 100 < m_Box.Tracks.Count) + m_Box.PlayMusic(m, m_Box.Tracks[info.ButtonID - 100]); + } + } +} diff --git a/Projects/UOContent/Gumps/Go/GoCategory.cs b/Projects/UOContent/Gumps/Go/GoCategory.cs index 019c038df..6d1588884 100644 --- a/Projects/UOContent/Gumps/Go/GoCategory.cs +++ b/Projects/UOContent/Gumps/Go/GoCategory.cs @@ -1,18 +1,15 @@ -using System.Text.Json.Serialization; - -namespace Server.Gumps -{ - public class GoCategory - { - public GoCategory Parent { get; set; } - - [JsonPropertyName("locations")] - public GoLocation[] Locations { get; set; } - - [JsonPropertyName("categories")] - public GoCategory[] Categories { get; set; } - - [JsonPropertyName("name")] - public string Name { get; set; } - } -} +using System.Text.Json.Serialization; + +namespace Server.Gumps +{ + public class GoCategory + { + public GoCategory Parent { get; set; } + + [JsonPropertyName("locations")] public GoLocation[] Locations { get; set; } + + [JsonPropertyName("categories")] public GoCategory[] Categories { get; set; } + + [JsonPropertyName("name")] public string Name { get; set; } + } +} diff --git a/Projects/UOContent/Gumps/Go/GoGump.cs b/Projects/UOContent/Gumps/Go/GoGump.cs index 9cdab1ad4..94607f9ac 100644 --- a/Projects/UOContent/Gumps/Go/GoGump.cs +++ b/Projects/UOContent/Gumps/Go/GoGump.cs @@ -1,244 +1,254 @@ -using System; -using Server.Network; - -namespace Server.Gumps -{ - public class GoGump : Gump - { - private static LocationTree Felucca; - private static LocationTree Trammel; - private static LocationTree Ilshenar; - private static LocationTree Malas; - private static LocationTree Tokuno; - private static LocationTree TerMur; - - public static bool OldStyle = PropsConfig.OldStyle; - - public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; - public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; - - public static readonly int TextHue = PropsConfig.TextHue; - public static readonly int TextOffsetX = PropsConfig.TextOffsetX; - - public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; - public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; - public static readonly int EntryGumpID = PropsConfig.EntryGumpID; - public static readonly int BackGumpID = PropsConfig.BackGumpID; - public static readonly int SetGumpID = PropsConfig.SetGumpID; - - public static readonly int SetWidth = PropsConfig.SetWidth; - public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY; - public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; - public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; - - public static readonly int PrevWidth = PropsConfig.PrevWidth; - public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY; - public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; - public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; - - public static readonly int NextWidth = PropsConfig.NextWidth; - public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY; - public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; - public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; - - public static readonly int OffsetSize = PropsConfig.OffsetSize; - - public static readonly int EntryHeight = PropsConfig.EntryHeight; - public static readonly int BorderSize = PropsConfig.BorderSize; - - private static readonly bool PrevLabel = false; - private static readonly bool NextLabel = false; - - private static readonly int PrevLabelOffsetX = PrevWidth + 1; - private static readonly int PrevLabelOffsetY = 0; - - private static readonly int NextLabelOffsetX = -29; - private static readonly int NextLabelOffsetY = 0; - - private static readonly int EntryWidth = 180; - private static readonly int EntryCount = 15; - - private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize; - private static readonly int TotalHeight = OffsetSize + (EntryHeight + OffsetSize) * (EntryCount + 1); - - private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; - private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize; - private readonly GoCategory m_Node; - private readonly int m_Page; - - private readonly LocationTree m_Tree; - - public static void DisplayTo(Mobile from) - { - LocationTree tree; - - if (from.Map == Map.Ilshenar) - tree = Ilshenar ??= new LocationTree("ilshenar", Map.Ilshenar); - else if (from.Map == Map.Felucca) - tree = Felucca ??= new LocationTree("felucca", Map.Felucca); - else if (from.Map == Map.Trammel) - tree = Trammel ??= new LocationTree("trammel", Map.Trammel); - else if (from.Map == Map.Malas) - tree = Malas ??= new LocationTree("malas", Map.Malas); - else if (from.Map == Map.Tokuno) - tree = Tokuno ??= new LocationTree("tokuno", Map.Tokuno); - else - tree = TerMur ??= new LocationTree("termur", Map.TerMur); - - if (!tree.LastBranch.TryGetValue(from, out GoCategory branch)) - branch = tree.Root; - - if (branch != null) - from.SendGump(new GoGump(0, from, tree, branch)); - } - - private GoGump(int page, Mobile from, LocationTree tree, GoCategory node) : base(50, 50) - { - from.CloseGump(); - - if (node == tree.Root) - tree.LastBranch.Remove(from); - else - tree.LastBranch[from] = node; - - m_Page = page; - m_Tree = tree; - m_Node = node; - - int x = BorderSize + OffsetSize; - int y = BorderSize + OffsetSize; - - int count = Math.Clamp(node.Categories.Length + node.Locations.Length - page * EntryCount, 0, EntryCount); - - int totalHeight = OffsetSize + (EntryHeight + OffsetSize) * (count + 1); - - AddPage(0); - - AddBackground(0, 0, BackWidth, BorderSize + totalHeight + BorderSize, BackGumpID); - AddImageTiled(BorderSize, BorderSize, TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), totalHeight, - OffsetGumpID); - - if (OldStyle) - AddImageTiled(x, y, TotalWidth - OffsetSize * 3 - SetWidth, EntryHeight, HeaderGumpID); - else - AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); - - if (node.Parent != null) - { - AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 1); - - if (PrevLabel) - AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous"); - } - - x += PrevWidth + OffsetSize; - - int emptyWidth = TotalWidth - PrevWidth * 2 - NextWidth - OffsetSize * 5 - - (OldStyle ? SetWidth + OffsetSize : 0); - - if (!OldStyle) - AddImageTiled(x - (OldStyle ? OffsetSize : 0), y, emptyWidth + (OldStyle ? OffsetSize * 2 : 0), EntryHeight, - EntryGumpID); - - AddHtml(x + TextOffsetX, y, emptyWidth - TextOffsetX, EntryHeight, $"
{node.Name}
"); - - x += emptyWidth + OffsetSize; - - if (OldStyle) - AddImageTiled(x, y, TotalWidth - OffsetSize * 3 - SetWidth, EntryHeight, HeaderGumpID); - else - AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); - - if (page > 0) - { - AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 2); - - if (PrevLabel) - AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous"); - } - - x += PrevWidth + OffsetSize; - - if (!OldStyle) - AddImageTiled(x, y, NextWidth, EntryHeight, HeaderGumpID); - - if ((page + 1) * EntryCount < node.Categories.Length + node.Locations.Length) - { - AddButton(x + NextOffsetX, y + NextOffsetY, NextButtonID1, NextButtonID2, 3, GumpButtonType.Reply, 1); - - if (NextLabel) - AddLabel(x + NextLabelOffsetX, y + NextLabelOffsetY, TextHue, "Next"); - } - - int totalEntryCount = node.Categories.Length + node.Locations.Length; - - for (int i = 0, index = page * EntryCount; i < EntryCount && index < totalEntryCount; ++i, ++index) - { - x = BorderSize + OffsetSize; - y += EntryHeight + OffsetSize; - - string name = index >= node.Categories.Length ? node.Locations[index].Name : node.Categories[index].Name; - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, name); - - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - - AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, index + 4); - } - } - - public override void OnResponse(NetState state, RelayInfo info) - { - Mobile from = state.Mobile; - - switch (info.ButtonID) - { - case 1: - { - if (m_Node.Parent != null) - from.SendGump(new GoGump(0, from, m_Tree, m_Node.Parent)); - - break; - } - case 2: - { - if (m_Page > 0) - from.SendGump(new GoGump(m_Page - 1, from, m_Tree, m_Node)); - - break; - } - case 3: - { - if ((m_Page + 1) * EntryCount < m_Node.Categories.Length + m_Node.Locations.Length) - from.SendGump(new GoGump(m_Page + 1, from, m_Tree, m_Node)); - - break; - } - default: - { - int index = info.ButtonID - 4; - - if (index < 0) - break; - - if (index < m_Node.Categories.Length) - { - from.SendGump(new GoGump(0, from, m_Tree, m_Node.Categories[index])); - } - else - { - index -= m_Node.Categories.Length; - if (index < m_Node.Locations.Length) - from.MoveToWorld(m_Node.Locations[index].Location, m_Tree.Map); - } - - break; - } - } - } - } -} +using System; +using Server.Network; + +namespace Server.Gumps +{ + public class GoGump : Gump + { + private static LocationTree Felucca; + private static LocationTree Trammel; + private static LocationTree Ilshenar; + private static LocationTree Malas; + private static LocationTree Tokuno; + private static LocationTree TerMur; + + public static bool OldStyle = PropsConfig.OldStyle; + + public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; + public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; + + public static readonly int TextHue = PropsConfig.TextHue; + public static readonly int TextOffsetX = PropsConfig.TextOffsetX; + + public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; + public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; + public static readonly int EntryGumpID = PropsConfig.EntryGumpID; + public static readonly int BackGumpID = PropsConfig.BackGumpID; + public static readonly int SetGumpID = PropsConfig.SetGumpID; + + public static readonly int SetWidth = PropsConfig.SetWidth; + public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY; + public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; + public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; + + public static readonly int PrevWidth = PropsConfig.PrevWidth; + public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY; + public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; + public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; + + public static readonly int NextWidth = PropsConfig.NextWidth; + public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY; + public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; + public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; + + public static readonly int OffsetSize = PropsConfig.OffsetSize; + + public static readonly int EntryHeight = PropsConfig.EntryHeight; + public static readonly int BorderSize = PropsConfig.BorderSize; + + private static readonly bool PrevLabel = false; + private static readonly bool NextLabel = false; + + private static readonly int PrevLabelOffsetX = PrevWidth + 1; + private static readonly int PrevLabelOffsetY = 0; + + private static readonly int NextLabelOffsetX = -29; + private static readonly int NextLabelOffsetY = 0; + + private static readonly int EntryWidth = 180; + private static readonly int EntryCount = 15; + + private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize; + private static readonly int TotalHeight = OffsetSize + (EntryHeight + OffsetSize) * (EntryCount + 1); + + private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; + private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize; + private readonly GoCategory m_Node; + private readonly int m_Page; + + private readonly LocationTree m_Tree; + + private GoGump(int page, Mobile from, LocationTree tree, GoCategory node) : base(50, 50) + { + from.CloseGump(); + + if (node == tree.Root) + tree.LastBranch.Remove(from); + else + tree.LastBranch[from] = node; + + m_Page = page; + m_Tree = tree; + m_Node = node; + + var x = BorderSize + OffsetSize; + var y = BorderSize + OffsetSize; + + var count = Math.Clamp(node.Categories.Length + node.Locations.Length - page * EntryCount, 0, EntryCount); + + var totalHeight = OffsetSize + (EntryHeight + OffsetSize) * (count + 1); + + AddPage(0); + + AddBackground(0, 0, BackWidth, BorderSize + totalHeight + BorderSize, BackGumpID); + AddImageTiled( + BorderSize, + BorderSize, + TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), + totalHeight, + OffsetGumpID + ); + + if (OldStyle) + AddImageTiled(x, y, TotalWidth - OffsetSize * 3 - SetWidth, EntryHeight, HeaderGumpID); + else + AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); + + if (node.Parent != null) + { + AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 1); + + if (PrevLabel) + AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous"); + } + + x += PrevWidth + OffsetSize; + + var emptyWidth = TotalWidth - PrevWidth * 2 - NextWidth - OffsetSize * 5 - + (OldStyle ? SetWidth + OffsetSize : 0); + + if (!OldStyle) + AddImageTiled( + x - (OldStyle ? OffsetSize : 0), + y, + emptyWidth + (OldStyle ? OffsetSize * 2 : 0), + EntryHeight, + EntryGumpID + ); + + AddHtml(x + TextOffsetX, y, emptyWidth - TextOffsetX, EntryHeight, $"
{node.Name}
"); + + x += emptyWidth + OffsetSize; + + if (OldStyle) + AddImageTiled(x, y, TotalWidth - OffsetSize * 3 - SetWidth, EntryHeight, HeaderGumpID); + else + AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); + + if (page > 0) + { + AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 2); + + if (PrevLabel) + AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous"); + } + + x += PrevWidth + OffsetSize; + + if (!OldStyle) + AddImageTiled(x, y, NextWidth, EntryHeight, HeaderGumpID); + + if ((page + 1) * EntryCount < node.Categories.Length + node.Locations.Length) + { + AddButton(x + NextOffsetX, y + NextOffsetY, NextButtonID1, NextButtonID2, 3, GumpButtonType.Reply, 1); + + if (NextLabel) + AddLabel(x + NextLabelOffsetX, y + NextLabelOffsetY, TextHue, "Next"); + } + + var totalEntryCount = node.Categories.Length + node.Locations.Length; + + for (int i = 0, index = page * EntryCount; i < EntryCount && index < totalEntryCount; ++i, ++index) + { + x = BorderSize + OffsetSize; + y += EntryHeight + OffsetSize; + + var name = index >= node.Categories.Length ? node.Locations[index].Name : node.Categories[index].Name; + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, name); + + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + + AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, index + 4); + } + } + + public static void DisplayTo(Mobile from) + { + LocationTree tree; + + if (from.Map == Map.Ilshenar) + tree = Ilshenar ??= new LocationTree("ilshenar", Map.Ilshenar); + else if (from.Map == Map.Felucca) + tree = Felucca ??= new LocationTree("felucca", Map.Felucca); + else if (from.Map == Map.Trammel) + tree = Trammel ??= new LocationTree("trammel", Map.Trammel); + else if (from.Map == Map.Malas) + tree = Malas ??= new LocationTree("malas", Map.Malas); + else if (from.Map == Map.Tokuno) + tree = Tokuno ??= new LocationTree("tokuno", Map.Tokuno); + else + tree = TerMur ??= new LocationTree("termur", Map.TerMur); + + if (!tree.LastBranch.TryGetValue(from, out var branch)) + branch = tree.Root; + + if (branch != null) + from.SendGump(new GoGump(0, from, tree, branch)); + } + + public override void OnResponse(NetState state, RelayInfo info) + { + var from = state.Mobile; + + switch (info.ButtonID) + { + case 1: + { + if (m_Node.Parent != null) + from.SendGump(new GoGump(0, from, m_Tree, m_Node.Parent)); + + break; + } + case 2: + { + if (m_Page > 0) + from.SendGump(new GoGump(m_Page - 1, from, m_Tree, m_Node)); + + break; + } + case 3: + { + if ((m_Page + 1) * EntryCount < m_Node.Categories.Length + m_Node.Locations.Length) + from.SendGump(new GoGump(m_Page + 1, from, m_Tree, m_Node)); + + break; + } + default: + { + var index = info.ButtonID - 4; + + if (index < 0) + break; + + if (index < m_Node.Categories.Length) + { + from.SendGump(new GoGump(0, from, m_Tree, m_Node.Categories[index])); + } + else + { + index -= m_Node.Categories.Length; + if (index < m_Node.Locations.Length) + from.MoveToWorld(m_Node.Locations[index].Location, m_Tree.Map); + } + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Gumps/Go/GoLocation.cs b/Projects/UOContent/Gumps/Go/GoLocation.cs index 39c97c8d4..50039a755 100644 --- a/Projects/UOContent/Gumps/Go/GoLocation.cs +++ b/Projects/UOContent/Gumps/Go/GoLocation.cs @@ -1,15 +1,13 @@ -using System.Text.Json.Serialization; - -namespace Server.Gumps -{ - public class GoLocation - { - public GoCategory Parent { get; set; } - - [JsonPropertyName("name")] - public string Name { get; set; } - - [JsonPropertyName("location")] - public Point3D Location { get; set; } - } -} +using System.Text.Json.Serialization; + +namespace Server.Gumps +{ + public class GoLocation + { + public GoCategory Parent { get; set; } + + [JsonPropertyName("name")] public string Name { get; set; } + + [JsonPropertyName("location")] public Point3D Location { get; set; } + } +} diff --git a/Projects/UOContent/Gumps/Go/LocationTree.cs b/Projects/UOContent/Gumps/Go/LocationTree.cs index 1a382813b..891a68231 100644 --- a/Projects/UOContent/Gumps/Go/LocationTree.cs +++ b/Projects/UOContent/Gumps/Go/LocationTree.cs @@ -1,58 +1,58 @@ -using System; -using System.Collections.Generic; -using System.IO; -using Server.Json; - -namespace Server.Gumps -{ - public class LocationTree - { - public LocationTree(string fileName, Map map) - { - LastBranch = new Dictionary(); - Map = map; - - string path = Path.Combine($"Data/Locations/{fileName}.json"); - - if (!File.Exists(path)) - { - Console.WriteLine("Go Locations: {0} does not exist", path); - return; - } - - try - { - Root = JsonConfig.Deserialize(path); - SetParents(Root); - } - catch (Exception e) - { - Console.WriteLine("Go Locations: Error in deserializing {0}", path); - Console.WriteLine(e); - } - } - - public Dictionary LastBranch { get; } - - public Map Map { get; } - - public GoCategory Root { get; } - - private static void SetParents(GoCategory parent) - { - // Deserialization may leave these null - parent.Categories ??= Array.Empty(); - parent.Locations ??= Array.Empty(); - - for (int i = 0; i < parent.Categories.Length; i++) - { - GoCategory category = parent.Categories[i]; - category.Parent = parent; - SetParents(category); - } - - for (int j = 0; j < parent.Locations.Length; j++) - parent.Locations[j].Parent = parent; - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using Server.Json; + +namespace Server.Gumps +{ + public class LocationTree + { + public LocationTree(string fileName, Map map) + { + LastBranch = new Dictionary(); + Map = map; + + var path = Path.Combine($"Data/Locations/{fileName}.json"); + + if (!File.Exists(path)) + { + Console.WriteLine("Go Locations: {0} does not exist", path); + return; + } + + try + { + Root = JsonConfig.Deserialize(path); + SetParents(Root); + } + catch (Exception e) + { + Console.WriteLine("Go Locations: Error in deserializing {0}", path); + Console.WriteLine(e); + } + } + + public Dictionary LastBranch { get; } + + public Map Map { get; } + + public GoCategory Root { get; } + + private static void SetParents(GoCategory parent) + { + // Deserialization may leave these null + parent.Categories ??= Array.Empty(); + parent.Locations ??= Array.Empty(); + + for (var i = 0; i < parent.Categories.Length; i++) + { + var category = parent.Categories[i]; + category.Parent = parent; + SetParents(category); + } + + for (var j = 0; j < parent.Locations.Length; j++) + parent.Locations[j].Parent = parent; + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/DeclareFealtyGump.cs b/Projects/UOContent/Gumps/Guilds/DeclareFealtyGump.cs index b6ade1cfa..017291c63 100644 --- a/Projects/UOContent/Gumps/Guilds/DeclareFealtyGump.cs +++ b/Projects/UOContent/Gumps/Guilds/DeclareFealtyGump.cs @@ -1,50 +1,50 @@ -using Server.Guilds; -using Server.Network; - -namespace Server.Gumps -{ - public class DeclareFealtyGump : GuildMobileListGump - { - public DeclareFealtyGump(Mobile from, Guild guild) : base(from, guild, true, guild.Members) - { - } - - protected override void Design() - { - AddHtmlLocalized(20, 10, 400, 35, 1011097); // Declare your fealty - - AddButton(20, 400, 4005, 4007, 1); - AddHtmlLocalized(55, 400, 250, 35, 1011098); // I have selected my new lord. - - AddButton(300, 400, 4005, 4007, 0); - AddHtmlLocalized(335, 400, 100, 35, 1011012); // CANCEL - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (GuildGump.BadMember(m_Mobile, m_Guild)) - return; - - if (info.ButtonID == 1) - { - int[] switches = info.Switches; - - if (switches.Length > 0) - { - int index = switches[0]; - - if (index >= 0 && index < m_List.Count) - { - Mobile m = m_List[index]; - - if (m?.Deleted == false) - state.Mobile.GuildFealty = m; - } - } - } - - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildGump(m_Mobile, m_Guild)); - } - } -} +using Server.Guilds; +using Server.Network; + +namespace Server.Gumps +{ + public class DeclareFealtyGump : GuildMobileListGump + { + public DeclareFealtyGump(Mobile from, Guild guild) : base(from, guild, true, guild.Members) + { + } + + protected override void Design() + { + AddHtmlLocalized(20, 10, 400, 35, 1011097); // Declare your fealty + + AddButton(20, 400, 4005, 4007, 1); + AddHtmlLocalized(55, 400, 250, 35, 1011098); // I have selected my new lord. + + AddButton(300, 400, 4005, 4007, 0); + AddHtmlLocalized(335, 400, 100, 35, 1011012); // CANCEL + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (GuildGump.BadMember(m_Mobile, m_Guild)) + return; + + if (info.ButtonID == 1) + { + var switches = info.Switches; + + if (switches.Length > 0) + { + var index = switches[0]; + + if (index >= 0 && index < m_List.Count) + { + var m = m_List[index]; + + if (m?.Deleted == false) + state.Mobile.GuildFealty = m; + } + } + } + + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildGump(m_Mobile, m_Guild)); + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GrantGuildTitleGump.cs b/Projects/UOContent/Gumps/Guilds/GrantGuildTitleGump.cs index 1af757d3b..edfac7e88 100644 --- a/Projects/UOContent/Gumps/Guilds/GrantGuildTitleGump.cs +++ b/Projects/UOContent/Gumps/Guilds/GrantGuildTitleGump.cs @@ -1,55 +1,55 @@ -using Server.Guilds; -using Server.Network; - -namespace Server.Gumps -{ - public class GrantGuildTitleGump : GuildMobileListGump - { - public GrantGuildTitleGump(Mobile from, Guild guild) : base(from, guild, true, guild.Members) - { - } - - protected override void Design() - { - AddHtmlLocalized(20, 10, 400, 35, 1011118); // Grant a title to another member. - - AddButton(20, 400, 4005, 4007, 1); - AddHtmlLocalized(55, 400, 245, 30, 1011127); // I dub thee... - - AddButton(300, 400, 4005, 4007, 2); - AddHtmlLocalized(335, 400, 100, 35, 1011012); // CANCEL - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (GuildGump.BadLeader(m_Mobile, m_Guild)) - return; - - if (info.ButtonID == 1) - { - int[] switches = info.Switches; - - if (switches.Length > 0) - { - int index = switches[0]; - - if (index >= 0 && index < m_List.Count) - { - Mobile m = m_List[index]; - - if (m?.Deleted == false) - { - m_Mobile.SendLocalizedMessage(1013074); // New title (20 characters max): - m_Mobile.Prompt = new GuildTitlePrompt(m_Mobile, m, m_Guild); - } - } - } - } - else if (info.ButtonID == 2) - { - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - } - } -} +using Server.Guilds; +using Server.Network; + +namespace Server.Gumps +{ + public class GrantGuildTitleGump : GuildMobileListGump + { + public GrantGuildTitleGump(Mobile from, Guild guild) : base(from, guild, true, guild.Members) + { + } + + protected override void Design() + { + AddHtmlLocalized(20, 10, 400, 35, 1011118); // Grant a title to another member. + + AddButton(20, 400, 4005, 4007, 1); + AddHtmlLocalized(55, 400, 245, 30, 1011127); // I dub thee... + + AddButton(300, 400, 4005, 4007, 2); + AddHtmlLocalized(335, 400, 100, 35, 1011012); // CANCEL + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (GuildGump.BadLeader(m_Mobile, m_Guild)) + return; + + if (info.ButtonID == 1) + { + var switches = info.Switches; + + if (switches.Length > 0) + { + var index = switches[0]; + + if (index >= 0 && index < m_List.Count) + { + var m = m_List[index]; + + if (m?.Deleted == false) + { + m_Mobile.SendLocalizedMessage(1013074); // New title (20 characters max): + m_Mobile.Prompt = new GuildTitlePrompt(m_Mobile, m, m_Guild); + } + } + } + } + else if (info.ButtonID == 2) + { + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildAbbrvPrompt.cs b/Projects/UOContent/Gumps/Guilds/GuildAbbrvPrompt.cs index 8b5ad63d0..cf4f6903b 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildAbbrvPrompt.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildAbbrvPrompt.cs @@ -1,53 +1,53 @@ -using Server.Guilds; -using Server.Prompts; - -namespace Server.Gumps -{ - public class GuildAbbrvPrompt : Prompt - { - private readonly Guild m_Guild; - private readonly Mobile m_Mobile; - - public GuildAbbrvPrompt(Mobile m, Guild g) - { - m_Mobile = m; - m_Guild = g; - } - - public override void OnCancel(Mobile from) - { - if (GuildGump.BadLeader(m_Mobile, m_Guild)) - return; - - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - - public override void OnResponse(Mobile from, string text) - { - if (GuildGump.BadLeader(m_Mobile, m_Guild)) - return; - - text = text.Trim(); - - if (text.Length > 3) - text = text.Substring(0, 3); - - if (text.Length > 0) - { - if (BaseGuild.FindByAbbrev(text) != null) - { - m_Mobile.SendMessage("{0} conflicts with the abbreviation of an existing guild.", text); - } - else - { - m_Guild.Abbreviation = text; - m_Guild.GuildMessage(1018025, true, text); // Your guild abbreviation has changed: - } - } - - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - } -} \ No newline at end of file +using Server.Guilds; +using Server.Prompts; + +namespace Server.Gumps +{ + public class GuildAbbrvPrompt : Prompt + { + private readonly Guild m_Guild; + private readonly Mobile m_Mobile; + + public GuildAbbrvPrompt(Mobile m, Guild g) + { + m_Mobile = m; + m_Guild = g; + } + + public override void OnCancel(Mobile from) + { + if (GuildGump.BadLeader(m_Mobile, m_Guild)) + return; + + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + + public override void OnResponse(Mobile from, string text) + { + if (GuildGump.BadLeader(m_Mobile, m_Guild)) + return; + + text = text.Trim(); + + if (text.Length > 3) + text = text.Substring(0, 3); + + if (text.Length > 0) + { + if (BaseGuild.FindByAbbrev(text) != null) + { + m_Mobile.SendMessage("{0} conflicts with the abbreviation of an existing guild.", text); + } + else + { + m_Guild.Abbreviation = text; + m_Guild.GuildMessage(1018025, true, text); // Your guild abbreviation has changed: + } + } + + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildAcceptWarGump.cs b/Projects/UOContent/Gumps/Guilds/GuildAcceptWarGump.cs index 021acd651..4cf9bf34c 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildAcceptWarGump.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildAcceptWarGump.cs @@ -1,65 +1,65 @@ -using Server.Guilds; -using Server.Network; - -namespace Server.Gumps -{ - public class GuildAcceptWarGump : GuildListGump - { - public GuildAcceptWarGump(Mobile from, Guild guild) : base(from, guild, true, guild.WarInvitations) - { - } - - protected override void Design() - { - AddHtmlLocalized(20, 10, 400, 35, 1011147); // Select the guild to accept the invitations: - - AddButton(20, 400, 4005, 4007, 1); - AddHtmlLocalized(55, 400, 245, 30, 1011100); // Accept war invitations. - - AddButton(300, 400, 4005, 4007, 2); - AddHtmlLocalized(335, 400, 100, 35, 1011012); // CANCEL - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (GuildGump.BadLeader(m_Mobile, m_Guild)) - return; - - if (info.ButtonID == 1) - { - int[] switches = info.Switches; - - if (switches.Length > 0) - { - int index = switches[0]; - - if (index >= 0 && index < m_List.Count) - { - Guild g = m_List[index]; - - if (g != null) - { - m_Guild.WarInvitations.Remove(g); - g.WarDeclarations.Remove(m_Guild); - - m_Guild.AddEnemy(g); - m_Guild.GuildMessage(1018020, true, "{0} ({1})", g.Name, g.Abbreviation); - - GuildGump.EnsureClosed(m_Mobile); - - if (m_Guild.WarInvitations.Count > 0) - m_Mobile.SendGump(new GuildAcceptWarGump(m_Mobile, m_Guild)); - else - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - } - } - } - else if (info.ButtonID == 2) - { - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - } - } -} +using Server.Guilds; +using Server.Network; + +namespace Server.Gumps +{ + public class GuildAcceptWarGump : GuildListGump + { + public GuildAcceptWarGump(Mobile from, Guild guild) : base(from, guild, true, guild.WarInvitations) + { + } + + protected override void Design() + { + AddHtmlLocalized(20, 10, 400, 35, 1011147); // Select the guild to accept the invitations: + + AddButton(20, 400, 4005, 4007, 1); + AddHtmlLocalized(55, 400, 245, 30, 1011100); // Accept war invitations. + + AddButton(300, 400, 4005, 4007, 2); + AddHtmlLocalized(335, 400, 100, 35, 1011012); // CANCEL + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (GuildGump.BadLeader(m_Mobile, m_Guild)) + return; + + if (info.ButtonID == 1) + { + var switches = info.Switches; + + if (switches.Length > 0) + { + var index = switches[0]; + + if (index >= 0 && index < m_List.Count) + { + var g = m_List[index]; + + if (g != null) + { + m_Guild.WarInvitations.Remove(g); + g.WarDeclarations.Remove(m_Guild); + + m_Guild.AddEnemy(g); + m_Guild.GuildMessage(1018020, true, "{0} ({1})", g.Name, g.Abbreviation); + + GuildGump.EnsureClosed(m_Mobile); + + if (m_Guild.WarInvitations.Count > 0) + m_Mobile.SendGump(new GuildAcceptWarGump(m_Mobile, m_Guild)); + else + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + } + } + } + else if (info.ButtonID == 2) + { + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildAdminCandidatesGump.cs b/Projects/UOContent/Gumps/Guilds/GuildAdminCandidatesGump.cs index 16e893918..8756c6b39 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildAdminCandidatesGump.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildAdminCandidatesGump.cs @@ -1,127 +1,131 @@ -using Server.Factions; -using Server.Guilds; -using Server.Network; - -namespace Server.Gumps -{ - public class GuildAdminCandidatesGump : GuildMobileListGump - { - public GuildAdminCandidatesGump(Mobile from, Guild guild) : base(from, guild, true, guild.Candidates) - { - } - - protected override void Design() - { - AddHtmlLocalized(20, 10, 400, 35, 1013075); // Accept or Refuse candidates for membership - - AddButton(20, 400, 4005, 4007, 1); - AddHtmlLocalized(55, 400, 245, 30, 1013076); // Accept - - AddButton(300, 400, 4005, 4007, 2); - AddHtmlLocalized(335, 400, 100, 35, 1013077); // Refuse - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (GuildGump.BadLeader(m_Mobile, m_Guild)) - return; - - switch (info.ButtonID) - { - case 0: - { - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - - break; - } - case 1: // Accept - { - int[] switches = info.Switches; - - if (switches.Length > 0) - { - int index = switches[0]; - - if (index >= 0 && index < m_List.Count) - { - Mobile m = m_List[index]; - - if (m?.Deleted == false) - { - PlayerState guildState = PlayerState.Find(m_Guild.Leader); - PlayerState targetState = PlayerState.Find(m); - - Faction guildFaction = guildState?.Faction; - Faction targetFaction = targetState?.Faction; - - if (guildFaction != targetFaction) - { - if (guildFaction == null) - m_Mobile.SendLocalizedMessage( - 1013027); // That player cannot join a non-faction guild. - else if (targetFaction == null) - m_Mobile.SendLocalizedMessage( - 1013026); // That player must be in a faction before joining this guild. - else - m_Mobile.SendLocalizedMessage( - 1013028); // That person has a different faction affiliation. - - break; - } - - if (targetState?.IsLeaving == true) - { - // OSI does this quite strangely, so we'll just do it this way - m_Mobile.SendMessage( - "That person is quitting their faction and so you may not recruit them."); - break; - } - - m_Guild.Candidates.Remove(m); - m_Guild.Accepted.Add(m); - - GuildGump.EnsureClosed(m_Mobile); - - if (m_Guild.Candidates.Count > 0) - m_Mobile.SendGump(new GuildAdminCandidatesGump(m_Mobile, m_Guild)); - else - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - } - } - - break; - } - case 2: // Refuse - { - int[] switches = info.Switches; - - if (switches.Length > 0) - { - int index = switches[0]; - - if (index >= 0 && index < m_List.Count) - { - Mobile m = m_List[index]; - - if (m?.Deleted == false) - { - m_Guild.Candidates.Remove(m); - - GuildGump.EnsureClosed(m_Mobile); - - if (m_Guild.Candidates.Count > 0) - m_Mobile.SendGump(new GuildAdminCandidatesGump(m_Mobile, m_Guild)); - else - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - } - } - - break; - } - } - } - } -} +using Server.Factions; +using Server.Guilds; +using Server.Network; + +namespace Server.Gumps +{ + public class GuildAdminCandidatesGump : GuildMobileListGump + { + public GuildAdminCandidatesGump(Mobile from, Guild guild) : base(from, guild, true, guild.Candidates) + { + } + + protected override void Design() + { + AddHtmlLocalized(20, 10, 400, 35, 1013075); // Accept or Refuse candidates for membership + + AddButton(20, 400, 4005, 4007, 1); + AddHtmlLocalized(55, 400, 245, 30, 1013076); // Accept + + AddButton(300, 400, 4005, 4007, 2); + AddHtmlLocalized(335, 400, 100, 35, 1013077); // Refuse + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (GuildGump.BadLeader(m_Mobile, m_Guild)) + return; + + switch (info.ButtonID) + { + case 0: + { + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + + break; + } + case 1: // Accept + { + var switches = info.Switches; + + if (switches.Length > 0) + { + var index = switches[0]; + + if (index >= 0 && index < m_List.Count) + { + var m = m_List[index]; + + if (m?.Deleted == false) + { + var guildState = PlayerState.Find(m_Guild.Leader); + var targetState = PlayerState.Find(m); + + var guildFaction = guildState?.Faction; + var targetFaction = targetState?.Faction; + + if (guildFaction != targetFaction) + { + if (guildFaction == null) + m_Mobile.SendLocalizedMessage( + 1013027 + ); // That player cannot join a non-faction guild. + else if (targetFaction == null) + m_Mobile.SendLocalizedMessage( + 1013026 + ); // That player must be in a faction before joining this guild. + else + m_Mobile.SendLocalizedMessage( + 1013028 + ); // That person has a different faction affiliation. + + break; + } + + if (targetState?.IsLeaving == true) + { + // OSI does this quite strangely, so we'll just do it this way + m_Mobile.SendMessage( + "That person is quitting their faction and so you may not recruit them." + ); + break; + } + + m_Guild.Candidates.Remove(m); + m_Guild.Accepted.Add(m); + + GuildGump.EnsureClosed(m_Mobile); + + if (m_Guild.Candidates.Count > 0) + m_Mobile.SendGump(new GuildAdminCandidatesGump(m_Mobile, m_Guild)); + else + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + } + } + + break; + } + case 2: // Refuse + { + var switches = info.Switches; + + if (switches.Length > 0) + { + var index = switches[0]; + + if (index >= 0 && index < m_List.Count) + { + var m = m_List[index]; + + if (m?.Deleted == false) + { + m_Guild.Candidates.Remove(m); + + GuildGump.EnsureClosed(m_Mobile); + + if (m_Guild.Candidates.Count > 0) + m_Mobile.SendGump(new GuildAdminCandidatesGump(m_Mobile, m_Guild)); + else + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + } + } + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildCandidatesGump.cs b/Projects/UOContent/Gumps/Guilds/GuildCandidatesGump.cs index 60ce45109..aae1c93f7 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildCandidatesGump.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildCandidatesGump.cs @@ -1,32 +1,32 @@ -using Server.Guilds; -using Server.Network; - -namespace Server.Gumps -{ - public class GuildCandidatesGump : GuildMobileListGump - { - public GuildCandidatesGump(Mobile from, Guild guild) : base(from, guild, false, guild.Candidates) - { - } - - protected override void Design() - { - AddHtmlLocalized(20, 10, 500, 35, 1013030); //
Candidates
- - AddButton(20, 400, 4005, 4007, 1); - AddHtmlLocalized(55, 400, 300, 35, 1011120); // Return to the main menu. - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (GuildGump.BadMember(m_Mobile, m_Guild)) - return; - - if (info.ButtonID == 1) - { - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildGump(m_Mobile, m_Guild)); - } - } - } -} +using Server.Guilds; +using Server.Network; + +namespace Server.Gumps +{ + public class GuildCandidatesGump : GuildMobileListGump + { + public GuildCandidatesGump(Mobile from, Guild guild) : base(from, guild, false, guild.Candidates) + { + } + + protected override void Design() + { + AddHtmlLocalized(20, 10, 500, 35, 1013030); //
Candidates
+ + AddButton(20, 400, 4005, 4007, 1); + AddHtmlLocalized(55, 400, 300, 35, 1011120); // Return to the main menu. + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (GuildGump.BadMember(m_Mobile, m_Guild)) + return; + + if (info.ButtonID == 1) + { + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildGump(m_Mobile, m_Guild)); + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildChangeTypeGump.cs b/Projects/UOContent/Gumps/Guilds/GuildChangeTypeGump.cs index a3ac3c979..5c7a3a90a 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildChangeTypeGump.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildChangeTypeGump.cs @@ -1,90 +1,90 @@ -using System; -using Server.Factions; -using Server.Guilds; -using Server.Mobiles; -using Server.Network; - -namespace Server.Gumps -{ - public class GuildChangeTypeGump : Gump - { - private readonly Guild m_Guild; - private readonly Mobile m_Mobile; - - public GuildChangeTypeGump(Mobile from, Guild guild) : base(20, 30) - { - m_Mobile = from; - m_Guild = guild; - - Draggable = false; - - AddPage(0); - AddBackground(0, 0, 550, 400, 5054); - AddBackground(10, 10, 530, 380, 3000); - - AddHtmlLocalized(20, 15, 510, 30, 1013062); //
Change Guild Type Menu
- - AddHtmlLocalized(50, 50, 450, 30, 1013066); // Please select the type of guild you would like to change to - - AddButton(20, 100, 4005, 4007, 1); - AddHtmlLocalized(85, 100, 300, 30, 1013063); // Standard guild - - AddButton(20, 150, 4005, 4007, 2); - AddItem(50, 143, 7109); - AddHtmlLocalized(85, 150, 300, 300, 1013064); // Order guild - - AddButton(20, 200, 4005, 4007, 3); - AddItem(45, 200, 7107); - AddHtmlLocalized(85, 200, 300, 300, 1013065); // Chaos guild - - AddButton(300, 360, 4005, 4007, 4); - AddHtmlLocalized(335, 360, 150, 30, 1011012); // CANCEL - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if ((Guild.NewGuildSystem && !BaseGuildGump.IsLeader(m_Mobile, m_Guild)) || - (!Guild.NewGuildSystem && GuildGump.BadLeader(m_Mobile, m_Guild))) - return; - - var newType = info.ButtonID switch - { - 1 => GuildType.Regular, - 2 => GuildType.Order, - 3 => GuildType.Chaos, - _ => m_Guild.Type - }; - - if (m_Guild.Type != newType) - { - PlayerState pl = PlayerState.Find(m_Mobile); - - if (pl != null) - { - m_Mobile.SendLocalizedMessage(1010405); // You cannot change guild types while in a Faction! - } - else if (m_Guild.TypeLastChange.AddDays(7) > DateTime.UtcNow) - { - m_Mobile.SendLocalizedMessage(1011142); // You have already changed your guild type recently. - // TODO: Clilocs 1011142-1011145 suggest a timer for pending changes - } - else - { - m_Guild.Type = newType; - m_Guild.GuildMessage(1018022, true, newType.ToString()); // Guild Message: Your guild type has changed: - } - } - - if (Guild.NewGuildSystem) - { - if (m_Mobile is PlayerMobile mobile) - mobile.SendGump(new GuildInfoGump(mobile, m_Guild)); - - return; - } - - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - } -} +using System; +using Server.Factions; +using Server.Guilds; +using Server.Mobiles; +using Server.Network; + +namespace Server.Gumps +{ + public class GuildChangeTypeGump : Gump + { + private readonly Guild m_Guild; + private readonly Mobile m_Mobile; + + public GuildChangeTypeGump(Mobile from, Guild guild) : base(20, 30) + { + m_Mobile = from; + m_Guild = guild; + + Draggable = false; + + AddPage(0); + AddBackground(0, 0, 550, 400, 5054); + AddBackground(10, 10, 530, 380, 3000); + + AddHtmlLocalized(20, 15, 510, 30, 1013062); //
Change Guild Type Menu
+ + AddHtmlLocalized(50, 50, 450, 30, 1013066); // Please select the type of guild you would like to change to + + AddButton(20, 100, 4005, 4007, 1); + AddHtmlLocalized(85, 100, 300, 30, 1013063); // Standard guild + + AddButton(20, 150, 4005, 4007, 2); + AddItem(50, 143, 7109); + AddHtmlLocalized(85, 150, 300, 300, 1013064); // Order guild + + AddButton(20, 200, 4005, 4007, 3); + AddItem(45, 200, 7107); + AddHtmlLocalized(85, 200, 300, 300, 1013065); // Chaos guild + + AddButton(300, 360, 4005, 4007, 4); + AddHtmlLocalized(335, 360, 150, 30, 1011012); // CANCEL + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (Guild.NewGuildSystem && !BaseGuildGump.IsLeader(m_Mobile, m_Guild) || + !Guild.NewGuildSystem && GuildGump.BadLeader(m_Mobile, m_Guild)) + return; + + var newType = info.ButtonID switch + { + 1 => GuildType.Regular, + 2 => GuildType.Order, + 3 => GuildType.Chaos, + _ => m_Guild.Type + }; + + if (m_Guild.Type != newType) + { + var pl = PlayerState.Find(m_Mobile); + + if (pl != null) + { + m_Mobile.SendLocalizedMessage(1010405); // You cannot change guild types while in a Faction! + } + else if (m_Guild.TypeLastChange.AddDays(7) > DateTime.UtcNow) + { + m_Mobile.SendLocalizedMessage(1011142); // You have already changed your guild type recently. + // TODO: Clilocs 1011142-1011145 suggest a timer for pending changes + } + else + { + m_Guild.Type = newType; + m_Guild.GuildMessage(1018022, true, newType.ToString()); // Guild Message: Your guild type has changed: + } + } + + if (Guild.NewGuildSystem) + { + if (m_Mobile is PlayerMobile mobile) + mobile.SendGump(new GuildInfoGump(mobile, m_Guild)); + + return; + } + + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildCharterGump.cs b/Projects/UOContent/Gumps/Guilds/GuildCharterGump.cs index b49c665c2..348df7165 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildCharterGump.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildCharterGump.cs @@ -1,69 +1,69 @@ -using Server.Guilds; -using Server.Network; - -namespace Server.Gumps -{ - public class GuildCharterGump : Gump - { - private const string DefaultWebsite = "https://www.modernuo.com"; - private readonly Guild m_Guild; - private readonly Mobile m_Mobile; - - public GuildCharterGump(Mobile from, Guild guild) : base(20, 30) - { - m_Mobile = from; - m_Guild = guild; - - Draggable = false; - - AddPage(0); - AddBackground(0, 0, 550, 400, 5054); - AddBackground(10, 10, 530, 380, 3000); - - AddButton(20, 360, 4005, 4007, 1); - AddHtmlLocalized(55, 360, 300, 35, 1011120); // Return to the main menu. - - string charter; - - if ((charter = guild.Charter) == null || (charter = charter.Trim()).Length <= 0) - AddHtmlLocalized(20, 20, 400, 35, 1013032); // No charter has been defined. - else - AddHtml(20, 20, 510, 75, charter, true, true); - - AddButton(20, 200, 4005, 4007, 2); - AddHtmlLocalized(55, 200, 300, 20, 1011122); // Visit the guild website : - - string website; - - if ((website = guild.Website) == null || (website = website.Trim()).Length <= 0) - website = DefaultWebsite; - - AddHtml(55, 220, 300, 20, website); - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (GuildGump.BadMember(m_Mobile, m_Guild)) - return; - - switch (info.ButtonID) - { - case 0: return; // Close - case 1: break; // Return to main menu - case 2: - { - string website; - - if ((website = m_Guild.Website) == null || (website = website.Trim()).Length <= 0) - website = DefaultWebsite; - - m_Mobile.LaunchBrowser(website); - break; - } - } - - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildGump(m_Mobile, m_Guild)); - } - } -} +using Server.Guilds; +using Server.Network; + +namespace Server.Gumps +{ + public class GuildCharterGump : Gump + { + private const string DefaultWebsite = "https://www.modernuo.com"; + private readonly Guild m_Guild; + private readonly Mobile m_Mobile; + + public GuildCharterGump(Mobile from, Guild guild) : base(20, 30) + { + m_Mobile = from; + m_Guild = guild; + + Draggable = false; + + AddPage(0); + AddBackground(0, 0, 550, 400, 5054); + AddBackground(10, 10, 530, 380, 3000); + + AddButton(20, 360, 4005, 4007, 1); + AddHtmlLocalized(55, 360, 300, 35, 1011120); // Return to the main menu. + + string charter; + + if ((charter = guild.Charter) == null || (charter = charter.Trim()).Length <= 0) + AddHtmlLocalized(20, 20, 400, 35, 1013032); // No charter has been defined. + else + AddHtml(20, 20, 510, 75, charter, true, true); + + AddButton(20, 200, 4005, 4007, 2); + AddHtmlLocalized(55, 200, 300, 20, 1011122); // Visit the guild website : + + string website; + + if ((website = guild.Website) == null || (website = website.Trim()).Length <= 0) + website = DefaultWebsite; + + AddHtml(55, 220, 300, 20, website); + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (GuildGump.BadMember(m_Mobile, m_Guild)) + return; + + switch (info.ButtonID) + { + case 0: return; // Close + case 1: break; // Return to main menu + case 2: + { + string website; + + if ((website = m_Guild.Website) == null || (website = website.Trim()).Length <= 0) + website = DefaultWebsite; + + m_Mobile.LaunchBrowser(website); + break; + } + } + + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildGump(m_Mobile, m_Guild)); + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildCharterPrompt.cs b/Projects/UOContent/Gumps/Guilds/GuildCharterPrompt.cs index 66b8d8f31..11cf443a0 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildCharterPrompt.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildCharterPrompt.cs @@ -1,46 +1,46 @@ -using Server.Guilds; -using Server.Prompts; - -namespace Server.Gumps -{ - public class GuildCharterPrompt : Prompt - { - private readonly Guild m_Guild; - private readonly Mobile m_Mobile; - - public GuildCharterPrompt(Mobile m, Guild g) - { - m_Mobile = m; - m_Guild = g; - } - - public override void OnCancel(Mobile from) - { - if (GuildGump.BadLeader(m_Mobile, m_Guild)) - return; - - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - - public override void OnResponse(Mobile from, string text) - { - if (GuildGump.BadLeader(m_Mobile, m_Guild)) - return; - - text = text.Trim(); - - if (text.Length > 50) - text = text.Substring(0, 50); - - if (text.Length > 0) - m_Guild.Charter = text; - - m_Mobile.SendLocalizedMessage(1013072); // Enter the new website for the guild (50 characters max): - m_Mobile.Prompt = new GuildWebsitePrompt(m_Mobile, m_Guild); - - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - } -} \ No newline at end of file +using Server.Guilds; +using Server.Prompts; + +namespace Server.Gumps +{ + public class GuildCharterPrompt : Prompt + { + private readonly Guild m_Guild; + private readonly Mobile m_Mobile; + + public GuildCharterPrompt(Mobile m, Guild g) + { + m_Mobile = m; + m_Guild = g; + } + + public override void OnCancel(Mobile from) + { + if (GuildGump.BadLeader(m_Mobile, m_Guild)) + return; + + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + + public override void OnResponse(Mobile from, string text) + { + if (GuildGump.BadLeader(m_Mobile, m_Guild)) + return; + + text = text.Trim(); + + if (text.Length > 50) + text = text.Substring(0, 50); + + if (text.Length > 0) + m_Guild.Charter = text; + + m_Mobile.SendLocalizedMessage(1013072); // Enter the new website for the guild (50 characters max): + m_Mobile.Prompt = new GuildWebsitePrompt(m_Mobile, m_Guild); + + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildDeclarePeaceGump.cs b/Projects/UOContent/Gumps/Guilds/GuildDeclarePeaceGump.cs index 00370e69d..b840305e1 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildDeclarePeaceGump.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildDeclarePeaceGump.cs @@ -1,63 +1,68 @@ -using Server.Guilds; -using Server.Network; - -namespace Server.Gumps -{ - public class GuildDeclarePeaceGump : GuildListGump - { - public GuildDeclarePeaceGump(Mobile from, Guild guild) : base(from, guild, true, guild.Enemies) - { - } - - protected override void Design() - { - AddHtmlLocalized(20, 10, 400, 35, 1011137); // Select the guild you wish to declare peace with. - - AddButton(20, 400, 4005, 4007, 1); - AddHtmlLocalized(55, 400, 245, 30, 1011138); // Send the olive branch. - - AddButton(300, 400, 4005, 4007, 2); - AddHtmlLocalized(335, 400, 100, 35, 1011012); // CANCEL - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (GuildGump.BadLeader(m_Mobile, m_Guild)) - return; - - if (info.ButtonID == 1) - { - int[] switches = info.Switches; - - if (switches.Length > 0) - { - int index = switches[0]; - - if (index >= 0 && index < m_List.Count) - { - Guild g = m_List[index]; - - if (g != null) - { - m_Guild.RemoveEnemy(g); - m_Guild.GuildMessage(1018018, true, "{0} ({1})", g.Name, - g.Abbreviation); // Guild Message: You are now at peace with this guild: - - GuildGump.EnsureClosed(m_Mobile); - - if (m_Guild.Enemies.Count > 0) - m_Mobile.SendGump(new GuildDeclarePeaceGump(m_Mobile, m_Guild)); - else - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - } - } - } - else if (info.ButtonID == 2) - { - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - } - } -} +using Server.Guilds; +using Server.Network; + +namespace Server.Gumps +{ + public class GuildDeclarePeaceGump : GuildListGump + { + public GuildDeclarePeaceGump(Mobile from, Guild guild) : base(from, guild, true, guild.Enemies) + { + } + + protected override void Design() + { + AddHtmlLocalized(20, 10, 400, 35, 1011137); // Select the guild you wish to declare peace with. + + AddButton(20, 400, 4005, 4007, 1); + AddHtmlLocalized(55, 400, 245, 30, 1011138); // Send the olive branch. + + AddButton(300, 400, 4005, 4007, 2); + AddHtmlLocalized(335, 400, 100, 35, 1011012); // CANCEL + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (GuildGump.BadLeader(m_Mobile, m_Guild)) + return; + + if (info.ButtonID == 1) + { + var switches = info.Switches; + + if (switches.Length > 0) + { + var index = switches[0]; + + if (index >= 0 && index < m_List.Count) + { + var g = m_List[index]; + + if (g != null) + { + m_Guild.RemoveEnemy(g); + m_Guild.GuildMessage( + 1018018, + true, + "{0} ({1})", + g.Name, + g.Abbreviation + ); // Guild Message: You are now at peace with this guild: + + GuildGump.EnsureClosed(m_Mobile); + + if (m_Guild.Enemies.Count > 0) + m_Mobile.SendGump(new GuildDeclarePeaceGump(m_Mobile, m_Guild)); + else + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + } + } + } + else if (info.ButtonID == 2) + { + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildDeclareWarGump.cs b/Projects/UOContent/Gumps/Guilds/GuildDeclareWarGump.cs index e3ddef954..6ef52c163 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildDeclareWarGump.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildDeclareWarGump.cs @@ -1,89 +1,99 @@ -using System.Collections.Generic; -using Server.Factions; -using Server.Guilds; -using Server.Network; - -namespace Server.Gumps -{ - public class GuildDeclareWarGump : GuildListGump - { - public GuildDeclareWarGump(Mobile from, Guild guild, List list) - : base(from, guild, true, list) - { - } - - protected override void Design() - { - AddHtmlLocalized(20, 10, 400, 35, 1011065); // Select the guild you wish to declare war on. - - AddButton(20, 400, 4005, 4007, 1); - AddHtmlLocalized(55, 400, 245, 30, 1011068); // Send the challenge! - - AddButton(300, 400, 4005, 4007, 2); - AddHtmlLocalized(335, 400, 100, 35, 1011012); // CANCEL - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (GuildGump.BadLeader(m_Mobile, m_Guild)) - return; - - if (info.ButtonID == 1) - { - int[] switches = info.Switches; - - if (switches.Length > 0) - { - int index = switches[0]; - - if (index >= 0 && index < m_List.Count) - { - Guild g = m_List[index]; - - if (g != null) - { - if (g == m_Guild) - { - m_Mobile.SendLocalizedMessage(501184); // You cannot declare war against yourself! - } - else if ((g.WarInvitations.Contains(m_Guild) && m_Guild.WarDeclarations.Contains(g)) || - m_Guild.IsWar(g)) - { - m_Mobile.SendLocalizedMessage(501183); // You are already at war with that guild. - } - else if (Faction.Find(m_Guild.Leader) != null) - { - m_Mobile.SendLocalizedMessage(1005288); // You cannot declare war while you are in a faction - } - else - { - if (!m_Guild.WarDeclarations.Contains(g)) - { - m_Guild.WarDeclarations.Add(g); - m_Guild.GuildMessage(1018019, true, "{0} ({1})", g.Name, - g.Abbreviation); // Guild Message: Your guild has sent an invitation for war: - } - - if (!g.WarInvitations.Contains(m_Guild)) - { - g.WarInvitations.Add(m_Guild); - g.GuildMessage(1018021, true, "{0} ({1})", m_Guild.Name, - m_Guild - .Abbreviation); // Guild Message: Your guild has received an invitation to war: - } - } - - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildWarAdminGump(m_Mobile, m_Guild)); - } - } - } - } - else if (info.ButtonID == 2) - { - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - } - } -} +using System.Collections.Generic; +using Server.Factions; +using Server.Guilds; +using Server.Network; + +namespace Server.Gumps +{ + public class GuildDeclareWarGump : GuildListGump + { + public GuildDeclareWarGump(Mobile from, Guild guild, List list) + : base(from, guild, true, list) + { + } + + protected override void Design() + { + AddHtmlLocalized(20, 10, 400, 35, 1011065); // Select the guild you wish to declare war on. + + AddButton(20, 400, 4005, 4007, 1); + AddHtmlLocalized(55, 400, 245, 30, 1011068); // Send the challenge! + + AddButton(300, 400, 4005, 4007, 2); + AddHtmlLocalized(335, 400, 100, 35, 1011012); // CANCEL + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (GuildGump.BadLeader(m_Mobile, m_Guild)) + return; + + if (info.ButtonID == 1) + { + var switches = info.Switches; + + if (switches.Length > 0) + { + var index = switches[0]; + + if (index >= 0 && index < m_List.Count) + { + var g = m_List[index]; + + if (g != null) + { + if (g == m_Guild) + { + m_Mobile.SendLocalizedMessage(501184); // You cannot declare war against yourself! + } + else if (g.WarInvitations.Contains(m_Guild) && m_Guild.WarDeclarations.Contains(g) || + m_Guild.IsWar(g)) + { + m_Mobile.SendLocalizedMessage(501183); // You are already at war with that guild. + } + else if (Faction.Find(m_Guild.Leader) != null) + { + m_Mobile.SendLocalizedMessage(1005288); // You cannot declare war while you are in a faction + } + else + { + if (!m_Guild.WarDeclarations.Contains(g)) + { + m_Guild.WarDeclarations.Add(g); + m_Guild.GuildMessage( + 1018019, + true, + "{0} ({1})", + g.Name, + g.Abbreviation + ); // Guild Message: Your guild has sent an invitation for war: + } + + if (!g.WarInvitations.Contains(m_Guild)) + { + g.WarInvitations.Add(m_Guild); + g.GuildMessage( + 1018021, + true, + "{0} ({1})", + m_Guild.Name, + m_Guild + .Abbreviation + ); // Guild Message: Your guild has received an invitation to war: + } + } + + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildWarAdminGump(m_Mobile, m_Guild)); + } + } + } + } + else if (info.ButtonID == 2) + { + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildDeclareWarPrompt.cs b/Projects/UOContent/Gumps/Guilds/GuildDeclareWarPrompt.cs index 281fedcf2..756322d01 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildDeclareWarPrompt.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildDeclareWarPrompt.cs @@ -1,56 +1,55 @@ -using System.Collections.Generic; -using Server.Guilds; -using Server.Prompts; - -namespace Server.Gumps -{ - public class GuildDeclareWarPrompt : Prompt - { - private readonly Guild m_Guild; - private readonly Mobile m_Mobile; - - public GuildDeclareWarPrompt(Mobile m, Guild g) - { - m_Mobile = m; - m_Guild = g; - } - - public override void OnCancel(Mobile from) - { - if (GuildGump.BadLeader(m_Mobile, m_Guild)) - return; - - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildWarAdminGump(m_Mobile, m_Guild)); - } - - public override void OnResponse(Mobile from, string text) - { - if (GuildGump.BadLeader(m_Mobile, m_Guild)) - return; - - text = text.Trim(); - - if (text.Length >= 3) - { - List guilds = Utility.CastListCovariant(BaseGuild.Search(text)); - - GuildGump.EnsureClosed(m_Mobile); - - if (guilds.Count > 0) - { - m_Mobile.SendGump(new GuildDeclareWarGump(m_Mobile, m_Guild, guilds)); - } - else - { - m_Mobile.SendGump(new GuildWarAdminGump(m_Mobile, m_Guild)); - m_Mobile.SendLocalizedMessage(1018003); // No guilds found matching - try another name in the search - } - } - else - { - m_Mobile.SendMessage("Search string must be at least three letters in length."); - } - } - } -} \ No newline at end of file +using Server.Guilds; +using Server.Prompts; + +namespace Server.Gumps +{ + public class GuildDeclareWarPrompt : Prompt + { + private readonly Guild m_Guild; + private readonly Mobile m_Mobile; + + public GuildDeclareWarPrompt(Mobile m, Guild g) + { + m_Mobile = m; + m_Guild = g; + } + + public override void OnCancel(Mobile from) + { + if (GuildGump.BadLeader(m_Mobile, m_Guild)) + return; + + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildWarAdminGump(m_Mobile, m_Guild)); + } + + public override void OnResponse(Mobile from, string text) + { + if (GuildGump.BadLeader(m_Mobile, m_Guild)) + return; + + text = text.Trim(); + + if (text.Length >= 3) + { + var guilds = Utility.CastListCovariant(BaseGuild.Search(text)); + + GuildGump.EnsureClosed(m_Mobile); + + if (guilds.Count > 0) + { + m_Mobile.SendGump(new GuildDeclareWarGump(m_Mobile, m_Guild, guilds)); + } + else + { + m_Mobile.SendGump(new GuildWarAdminGump(m_Mobile, m_Guild)); + m_Mobile.SendLocalizedMessage(1018003); // No guilds found matching - try another name in the search + } + } + else + { + m_Mobile.SendMessage("Search string must be at least three letters in length."); + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildDismissGump.cs b/Projects/UOContent/Gumps/Guilds/GuildDismissGump.cs index f86a03209..48cedfd9e 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildDismissGump.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildDismissGump.cs @@ -1,60 +1,60 @@ -using Server.Guilds; -using Server.Network; - -namespace Server.Gumps -{ - public class GuildDismissGump : GuildMobileListGump - { - public GuildDismissGump(Mobile from, Guild guild) : base(from, guild, true, guild.Members) - { - } - - protected override void Design() - { - AddHtmlLocalized(20, 10, 400, 35, 1011124); // Whom do you wish to dismiss? - - AddButton(20, 400, 4005, 4007, 1); - AddHtmlLocalized(55, 400, 245, 30, 1011125); // Kick them out! - - AddButton(300, 400, 4005, 4007, 2); - AddHtmlLocalized(335, 400, 100, 35, 1011012); // CANCEL - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (GuildGump.BadLeader(m_Mobile, m_Guild)) - return; - - if (info.ButtonID == 1) - { - int[] switches = info.Switches; - - if (switches.Length > 0) - { - int index = switches[0]; - - if (index >= 0 && index < m_List.Count) - { - Mobile m = m_List[index]; - - if (m?.Deleted == false) - { - m_Guild.RemoveMember(m); - - if (m_Mobile.AccessLevel >= AccessLevel.GameMaster || m_Mobile == m_Guild.Leader) - { - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - } - } - } - } - else if (info.ButtonID == 2 && (m_Mobile.AccessLevel >= AccessLevel.GameMaster || m_Mobile == m_Guild.Leader)) - { - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - } - } -} +using Server.Guilds; +using Server.Network; + +namespace Server.Gumps +{ + public class GuildDismissGump : GuildMobileListGump + { + public GuildDismissGump(Mobile from, Guild guild) : base(from, guild, true, guild.Members) + { + } + + protected override void Design() + { + AddHtmlLocalized(20, 10, 400, 35, 1011124); // Whom do you wish to dismiss? + + AddButton(20, 400, 4005, 4007, 1); + AddHtmlLocalized(55, 400, 245, 30, 1011125); // Kick them out! + + AddButton(300, 400, 4005, 4007, 2); + AddHtmlLocalized(335, 400, 100, 35, 1011012); // CANCEL + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (GuildGump.BadLeader(m_Mobile, m_Guild)) + return; + + if (info.ButtonID == 1) + { + var switches = info.Switches; + + if (switches.Length > 0) + { + var index = switches[0]; + + if (index >= 0 && index < m_List.Count) + { + var m = m_List[index]; + + if (m?.Deleted == false) + { + m_Guild.RemoveMember(m); + + if (m_Mobile.AccessLevel >= AccessLevel.GameMaster || m_Mobile == m_Guild.Leader) + { + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + } + } + } + } + else if (info.ButtonID == 2 && (m_Mobile.AccessLevel >= AccessLevel.GameMaster || m_Mobile == m_Guild.Leader)) + { + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildGump.cs b/Projects/UOContent/Gumps/Guilds/GuildGump.cs index 46e0ad4cd..b9ab49dda 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildGump.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildGump.cs @@ -1,208 +1,208 @@ -using Server.Guilds; -using Server.Network; - -namespace Server.Gumps -{ - public class GuildGump : Gump - { - private readonly Guild m_Guild; - private readonly Mobile m_Mobile; - - public GuildGump(Mobile beholder, Guild guild) : base(20, 30) - { - m_Mobile = beholder; - m_Guild = guild; - - Draggable = false; - - AddPage(0); - AddBackground(0, 0, 550, 400, 5054); - AddBackground(10, 10, 530, 380, 3000); - - AddHtml(20, 15, 200, 35, guild.Name); - - Mobile leader = guild.Leader; - - if (leader != null) - { - string leadTitle = leader.GuildTitle?.Trim(); - string leadName = leader.Name?.Trim().IsNullOrDefault("(empty)"); - string text = leadTitle?.Length > 0 ? $"{leadTitle}: {leadName}" : leadName; - - AddHtml(220, 15, 250, 35, text); - } - - AddButton(20, 50, 4005, 4007, 1); - AddHtmlLocalized(55, 50, 100, 20, 1013022); // Loyal to - - Mobile fealty = beholder.GuildFealty; - - if (fealty == null || !guild.IsMember(fealty)) - fealty = leader; - - fealty ??= beholder; - - string fealtyName = fealty.Name?.Trim().IsNullOrDefault("(empty)"); - - if (beholder == fealty) - AddHtmlLocalized(55, 70, 470, 20, 1018002); // yourself - else - AddHtml(55, 70, 470, 20, fealtyName); - - AddButton(215, 50, 4005, 4007, 2); - AddHtmlLocalized(250, 50, 170, 20, 1013023); // Display guild abbreviation - AddHtmlLocalized(250, 70, 50, 20, beholder.DisplayGuildTitle ? 1011262 : 1011263); // on/off - - AddButton(20, 100, 4005, 4007, 3); - AddHtmlLocalized(55, 100, 470, 30, 1011086); // View the current roster. - - AddButton(20, 130, 4005, 4007, 4); - AddHtmlLocalized(55, 130, 470, 30, 1011085); // Recruit someone into the guild. - - if (guild.Candidates.Count > 0) - { - AddButton(20, 160, 4005, 4007, 5); - AddHtmlLocalized(55, 160, 470, 30, 1011093); // View list of candidates who have been sponsored to the guild. - } - else - { - AddImage(20, 160, 4020); - AddHtmlLocalized(55, 160, 470, 30, 1013031); // There are currently no candidates for membership. - } - - AddButton(20, 220, 4005, 4007, 6); - AddHtmlLocalized(55, 220, 470, 30, 1011087); // View the guild's charter. - - AddButton(20, 250, 4005, 4007, 7); - AddHtmlLocalized(55, 250, 470, 30, 1011092); // Resign from the guild. - - AddButton(20, 280, 4005, 4007, 8); - AddHtmlLocalized(55, 280, 470, 30, 1011095); // View list of guilds you are at war with. - - if (beholder.AccessLevel >= AccessLevel.GameMaster || beholder == leader) - { - AddButton(20, 310, 4005, 4007, 9); - AddHtmlLocalized(55, 310, 470, 30, 1011094); // Access guildmaster functions. - } - else - { - AddImage(20, 310, 4020); - AddHtmlLocalized(55, 310, 470, 30, 1018013); // Reserved for guildmaster - } - - AddButton(20, 360, 4005, 4007, 0); - AddHtmlLocalized(55, 360, 470, 30, 1011441); // EXIT - } - - public static void EnsureClosed(Mobile m) - { - m.CloseGump(); - m.CloseGump(); - m.CloseGump(); - m.CloseGump(); - m.CloseGump(); - m.CloseGump(); - m.CloseGump(); - m.CloseGump(); - m.CloseGump(); - m.CloseGump(); - m.CloseGump(); - } - - public static bool BadLeader(Mobile m, Guild g) - { - if (m.Deleted || g.Disbanded || (m.AccessLevel < AccessLevel.GameMaster && g.Leader != m)) - return true; - - Item stone = g.Guildstone; - - return stone?.Deleted != false || !m.InRange(stone.GetWorldLocation(), 2); - } - - public static bool BadMember(Mobile m, Guild g) - { - if (m.Deleted || g.Disbanded || (m.AccessLevel < AccessLevel.GameMaster && !g.IsMember(m))) - return true; - - Item stone = g.Guildstone; - - return stone?.Deleted != false || !m.InRange(stone.GetWorldLocation(), 2); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (BadMember(m_Mobile, m_Guild)) - return; - - switch (info.ButtonID) - { - case 1: // Loyalty - { - EnsureClosed(m_Mobile); - m_Mobile.SendGump(new DeclareFealtyGump(m_Mobile, m_Guild)); - - break; - } - case 2: // Toggle display abbreviation - { - m_Mobile.DisplayGuildTitle = !m_Mobile.DisplayGuildTitle; - - EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildGump(m_Mobile, m_Guild)); - - break; - } - case 3: // View the current roster - { - EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildRosterGump(m_Mobile, m_Guild)); - - break; - } - case 4: // Recruit - { - m_Mobile.Target = new GuildRecruitTarget(m_Mobile, m_Guild); - - break; - } - case 5: // Membership candidates - { - EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildCandidatesGump(m_Mobile, m_Guild)); - - break; - } - case 6: // View charter - { - EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildCharterGump(m_Mobile, m_Guild)); - - break; - } - case 7: // Resign - { - m_Guild.RemoveMember(m_Mobile); - - break; - } - case 8: // View wars - { - EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildWarGump(m_Mobile, m_Guild)); - - break; - } - case 9: // Guildmaster functions - { - if (m_Mobile.AccessLevel >= AccessLevel.GameMaster || m_Guild.Leader == m_Mobile) - { - EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - - break; - } - } - } - } -} +using Server.Guilds; +using Server.Network; + +namespace Server.Gumps +{ + public class GuildGump : Gump + { + private readonly Guild m_Guild; + private readonly Mobile m_Mobile; + + public GuildGump(Mobile beholder, Guild guild) : base(20, 30) + { + m_Mobile = beholder; + m_Guild = guild; + + Draggable = false; + + AddPage(0); + AddBackground(0, 0, 550, 400, 5054); + AddBackground(10, 10, 530, 380, 3000); + + AddHtml(20, 15, 200, 35, guild.Name); + + var leader = guild.Leader; + + if (leader != null) + { + var leadTitle = leader.GuildTitle?.Trim(); + var leadName = leader.Name?.Trim().IsNullOrDefault("(empty)"); + var text = leadTitle?.Length > 0 ? $"{leadTitle}: {leadName}" : leadName; + + AddHtml(220, 15, 250, 35, text); + } + + AddButton(20, 50, 4005, 4007, 1); + AddHtmlLocalized(55, 50, 100, 20, 1013022); // Loyal to + + var fealty = beholder.GuildFealty; + + if (fealty == null || !guild.IsMember(fealty)) + fealty = leader; + + fealty ??= beholder; + + var fealtyName = fealty.Name?.Trim().IsNullOrDefault("(empty)"); + + if (beholder == fealty) + AddHtmlLocalized(55, 70, 470, 20, 1018002); // yourself + else + AddHtml(55, 70, 470, 20, fealtyName); + + AddButton(215, 50, 4005, 4007, 2); + AddHtmlLocalized(250, 50, 170, 20, 1013023); // Display guild abbreviation + AddHtmlLocalized(250, 70, 50, 20, beholder.DisplayGuildTitle ? 1011262 : 1011263); // on/off + + AddButton(20, 100, 4005, 4007, 3); + AddHtmlLocalized(55, 100, 470, 30, 1011086); // View the current roster. + + AddButton(20, 130, 4005, 4007, 4); + AddHtmlLocalized(55, 130, 470, 30, 1011085); // Recruit someone into the guild. + + if (guild.Candidates.Count > 0) + { + AddButton(20, 160, 4005, 4007, 5); + AddHtmlLocalized(55, 160, 470, 30, 1011093); // View list of candidates who have been sponsored to the guild. + } + else + { + AddImage(20, 160, 4020); + AddHtmlLocalized(55, 160, 470, 30, 1013031); // There are currently no candidates for membership. + } + + AddButton(20, 220, 4005, 4007, 6); + AddHtmlLocalized(55, 220, 470, 30, 1011087); // View the guild's charter. + + AddButton(20, 250, 4005, 4007, 7); + AddHtmlLocalized(55, 250, 470, 30, 1011092); // Resign from the guild. + + AddButton(20, 280, 4005, 4007, 8); + AddHtmlLocalized(55, 280, 470, 30, 1011095); // View list of guilds you are at war with. + + if (beholder.AccessLevel >= AccessLevel.GameMaster || beholder == leader) + { + AddButton(20, 310, 4005, 4007, 9); + AddHtmlLocalized(55, 310, 470, 30, 1011094); // Access guildmaster functions. + } + else + { + AddImage(20, 310, 4020); + AddHtmlLocalized(55, 310, 470, 30, 1018013); // Reserved for guildmaster + } + + AddButton(20, 360, 4005, 4007, 0); + AddHtmlLocalized(55, 360, 470, 30, 1011441); // EXIT + } + + public static void EnsureClosed(Mobile m) + { + m.CloseGump(); + m.CloseGump(); + m.CloseGump(); + m.CloseGump(); + m.CloseGump(); + m.CloseGump(); + m.CloseGump(); + m.CloseGump(); + m.CloseGump(); + m.CloseGump(); + m.CloseGump(); + } + + public static bool BadLeader(Mobile m, Guild g) + { + if (m.Deleted || g.Disbanded || m.AccessLevel < AccessLevel.GameMaster && g.Leader != m) + return true; + + var stone = g.Guildstone; + + return stone?.Deleted != false || !m.InRange(stone.GetWorldLocation(), 2); + } + + public static bool BadMember(Mobile m, Guild g) + { + if (m.Deleted || g.Disbanded || m.AccessLevel < AccessLevel.GameMaster && !g.IsMember(m)) + return true; + + var stone = g.Guildstone; + + return stone?.Deleted != false || !m.InRange(stone.GetWorldLocation(), 2); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (BadMember(m_Mobile, m_Guild)) + return; + + switch (info.ButtonID) + { + case 1: // Loyalty + { + EnsureClosed(m_Mobile); + m_Mobile.SendGump(new DeclareFealtyGump(m_Mobile, m_Guild)); + + break; + } + case 2: // Toggle display abbreviation + { + m_Mobile.DisplayGuildTitle = !m_Mobile.DisplayGuildTitle; + + EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildGump(m_Mobile, m_Guild)); + + break; + } + case 3: // View the current roster + { + EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildRosterGump(m_Mobile, m_Guild)); + + break; + } + case 4: // Recruit + { + m_Mobile.Target = new GuildRecruitTarget(m_Mobile, m_Guild); + + break; + } + case 5: // Membership candidates + { + EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildCandidatesGump(m_Mobile, m_Guild)); + + break; + } + case 6: // View charter + { + EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildCharterGump(m_Mobile, m_Guild)); + + break; + } + case 7: // Resign + { + m_Guild.RemoveMember(m_Mobile); + + break; + } + case 8: // View wars + { + EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildWarGump(m_Mobile, m_Guild)); + + break; + } + case 9: // Guildmaster functions + { + if (m_Mobile.AccessLevel >= AccessLevel.GameMaster || m_Guild.Leader == m_Mobile) + { + EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildListGump.cs b/Projects/UOContent/Gumps/Guilds/GuildListGump.cs index abde1ff9f..21e81e531 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildListGump.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildListGump.cs @@ -1,64 +1,64 @@ -using System.Collections.Generic; -using Server.Guilds; - -namespace Server.Gumps -{ - public abstract class GuildListGump : Gump - { - protected Guild m_Guild; - protected List m_List; - protected Mobile m_Mobile; - - public GuildListGump(Mobile from, Guild guild, bool radio, List list) : base(20, 30) - { - m_Mobile = from; - m_Guild = guild; - - Draggable = false; - - AddPage(0); - AddBackground(0, 0, 550, 440, 5054); - AddBackground(10, 10, 530, 420, 3000); - - Design(); - - m_List = new List(list); - - for (int i = 0; i < m_List.Count; ++i) - { - if (i % 11 == 0) - { - if (i != 0) - { - AddButton(300, 370, 4005, 4007, 0, GumpButtonType.Page, i / 11 + 1); - AddHtmlLocalized(335, 370, 300, 35, 1011066); // Next page - } - - AddPage(i / 11 + 1); - - if (i != 0) - { - AddButton(20, 370, 4014, 4016, 0, GumpButtonType.Page, i / 11); - AddHtmlLocalized(55, 370, 300, 35, 1011067); // Previous page - } - } - - if (radio) - AddRadio(20, 35 + i % 11 * 30, 208, 209, false, i); - - Guild g = m_List[i]; - - string name; - - if ((name = g.Name) != null && (name = name.Trim()).Length <= 0) - name = "(empty)"; - - AddLabel(radio ? 55 : 20, 35 + i % 11 * 30, 0, name); - } - } - - protected virtual void Design() - { - } - } -} \ No newline at end of file +using System.Collections.Generic; +using Server.Guilds; + +namespace Server.Gumps +{ + public abstract class GuildListGump : Gump + { + protected Guild m_Guild; + protected List m_List; + protected Mobile m_Mobile; + + public GuildListGump(Mobile from, Guild guild, bool radio, List list) : base(20, 30) + { + m_Mobile = from; + m_Guild = guild; + + Draggable = false; + + AddPage(0); + AddBackground(0, 0, 550, 440, 5054); + AddBackground(10, 10, 530, 420, 3000); + + Design(); + + m_List = new List(list); + + for (var i = 0; i < m_List.Count; ++i) + { + if (i % 11 == 0) + { + if (i != 0) + { + AddButton(300, 370, 4005, 4007, 0, GumpButtonType.Page, i / 11 + 1); + AddHtmlLocalized(335, 370, 300, 35, 1011066); // Next page + } + + AddPage(i / 11 + 1); + + if (i != 0) + { + AddButton(20, 370, 4014, 4016, 0, GumpButtonType.Page, i / 11); + AddHtmlLocalized(55, 370, 300, 35, 1011067); // Previous page + } + } + + if (radio) + AddRadio(20, 35 + i % 11 * 30, 208, 209, false, i); + + var g = m_List[i]; + + string name; + + if ((name = g.Name) != null && (name = name.Trim()).Length <= 0) + name = "(empty)"; + + AddLabel(radio ? 55 : 20, 35 + i % 11 * 30, 0, name); + } + } + + protected virtual void Design() + { + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildMobileListGump.cs b/Projects/UOContent/Gumps/Guilds/GuildMobileListGump.cs index 4179ee663..e7b48d27b 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildMobileListGump.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildMobileListGump.cs @@ -1,65 +1,65 @@ -using System.Collections.Generic; -using Server.Guilds; - -namespace Server.Gumps -{ - public abstract class GuildMobileListGump : Gump - { - protected Guild m_Guild; - protected List m_List; - protected Mobile m_Mobile; - - public GuildMobileListGump(Mobile from, Guild guild, bool radio, List list) - : base(20, 30) - { - m_Mobile = from; - m_Guild = guild; - - Draggable = false; - - AddPage(0); - AddBackground(0, 0, 550, 440, 5054); - AddBackground(10, 10, 530, 420, 3000); - - Design(); - - m_List = new List(list); - - for (int i = 0; i < m_List.Count; ++i) - { - if (i % 11 == 0) - { - if (i != 0) - { - AddButton(300, 370, 4005, 4007, 0, GumpButtonType.Page, i / 11 + 1); - AddHtmlLocalized(335, 370, 300, 35, 1011066); // Next page - } - - AddPage(i / 11 + 1); - - if (i != 0) - { - AddButton(20, 370, 4014, 4016, 0, GumpButtonType.Page, i / 11); - AddHtmlLocalized(55, 370, 300, 35, 1011067); // Previous page - } - } - - if (radio) - AddRadio(20, 35 + i % 11 * 30, 208, 209, false, i); - - Mobile m = m_List[i]; - - string name; - - if ((name = m.Name) != null && (name = name.Trim()).Length <= 0) - name = "(empty)"; - - AddLabel(radio ? 55 : 20, 35 + i % 11 * 30, 0, name); - } - } - - protected virtual void Design() - { - } - } -} \ No newline at end of file +using System.Collections.Generic; +using Server.Guilds; + +namespace Server.Gumps +{ + public abstract class GuildMobileListGump : Gump + { + protected Guild m_Guild; + protected List m_List; + protected Mobile m_Mobile; + + public GuildMobileListGump(Mobile from, Guild guild, bool radio, List list) + : base(20, 30) + { + m_Mobile = from; + m_Guild = guild; + + Draggable = false; + + AddPage(0); + AddBackground(0, 0, 550, 440, 5054); + AddBackground(10, 10, 530, 420, 3000); + + Design(); + + m_List = new List(list); + + for (var i = 0; i < m_List.Count; ++i) + { + if (i % 11 == 0) + { + if (i != 0) + { + AddButton(300, 370, 4005, 4007, 0, GumpButtonType.Page, i / 11 + 1); + AddHtmlLocalized(335, 370, 300, 35, 1011066); // Next page + } + + AddPage(i / 11 + 1); + + if (i != 0) + { + AddButton(20, 370, 4014, 4016, 0, GumpButtonType.Page, i / 11); + AddHtmlLocalized(55, 370, 300, 35, 1011067); // Previous page + } + } + + if (radio) + AddRadio(20, 35 + i % 11 * 30, 208, 209, false, i); + + var m = m_List[i]; + + string name; + + if ((name = m.Name) != null && (name = name.Trim()).Length <= 0) + name = "(empty)"; + + AddLabel(radio ? 55 : 20, 35 + i % 11 * 30, 0, name); + } + } + + protected virtual void Design() + { + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildNamePrompt.cs b/Projects/UOContent/Gumps/Guilds/GuildNamePrompt.cs index 44695a718..b748b8057 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildNamePrompt.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildNamePrompt.cs @@ -1,53 +1,53 @@ -using Server.Guilds; -using Server.Prompts; - -namespace Server.Gumps -{ - public class GuildNamePrompt : Prompt - { - private readonly Guild m_Guild; - private readonly Mobile m_Mobile; - - public GuildNamePrompt(Mobile m, Guild g) - { - m_Mobile = m; - m_Guild = g; - } - - public override void OnCancel(Mobile from) - { - if (GuildGump.BadLeader(m_Mobile, m_Guild)) - return; - - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - - public override void OnResponse(Mobile from, string text) - { - if (GuildGump.BadLeader(m_Mobile, m_Guild)) - return; - - text = text.Trim(); - - if (text.Length > 40) - text = text.Substring(0, 40); - - if (text.Length > 0) - { - if (BaseGuild.FindByName(text) != null) - { - m_Mobile.SendMessage("{0} conflicts with the name of an existing guild.", text); - } - else - { - m_Guild.Name = text; - m_Guild.GuildMessage(1018024, true, text); // The name of your guild has changed: - } - } - - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - } -} \ No newline at end of file +using Server.Guilds; +using Server.Prompts; + +namespace Server.Gumps +{ + public class GuildNamePrompt : Prompt + { + private readonly Guild m_Guild; + private readonly Mobile m_Mobile; + + public GuildNamePrompt(Mobile m, Guild g) + { + m_Mobile = m; + m_Guild = g; + } + + public override void OnCancel(Mobile from) + { + if (GuildGump.BadLeader(m_Mobile, m_Guild)) + return; + + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + + public override void OnResponse(Mobile from, string text) + { + if (GuildGump.BadLeader(m_Mobile, m_Guild)) + return; + + text = text.Trim(); + + if (text.Length > 40) + text = text.Substring(0, 40); + + if (text.Length > 0) + { + if (BaseGuild.FindByName(text) != null) + { + m_Mobile.SendMessage("{0} conflicts with the name of an existing guild.", text); + } + else + { + m_Guild.Name = text; + m_Guild.GuildMessage(1018024, true, text); // The name of your guild has changed: + } + } + + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildRejectWarGump.cs b/Projects/UOContent/Gumps/Guilds/GuildRejectWarGump.cs index 16761e975..5d240a339 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildRejectWarGump.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildRejectWarGump.cs @@ -1,62 +1,62 @@ -using Server.Guilds; -using Server.Network; - -namespace Server.Gumps -{ - public class GuildRejectWarGump : GuildListGump - { - public GuildRejectWarGump(Mobile from, Guild guild) : base(from, guild, true, guild.WarInvitations) - { - } - - protected override void Design() - { - AddHtmlLocalized(20, 10, 400, 35, 1011148); // Select the guild to reject their invitations: - - AddButton(20, 400, 4005, 4007, 1); - AddHtmlLocalized(55, 400, 245, 30, 1011101); // Reject war invitations. - - AddButton(300, 400, 4005, 4007, 2); - AddHtmlLocalized(335, 400, 100, 35, 1011012); // CANCEL - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (GuildGump.BadLeader(m_Mobile, m_Guild)) - return; - - if (info.ButtonID == 1) - { - int[] switches = info.Switches; - - if (switches.Length > 0) - { - int index = switches[0]; - - if (index >= 0 && index < m_List.Count) - { - Guild g = m_List[index]; - - if (g != null) - { - m_Guild.WarInvitations.Remove(g); - g.WarDeclarations.Remove(m_Guild); - - GuildGump.EnsureClosed(m_Mobile); - - if (m_Guild.WarInvitations.Count > 0) - m_Mobile.SendGump(new GuildRejectWarGump(m_Mobile, m_Guild)); - else - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - } - } - } - else if (info.ButtonID == 2) - { - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - } - } -} +using Server.Guilds; +using Server.Network; + +namespace Server.Gumps +{ + public class GuildRejectWarGump : GuildListGump + { + public GuildRejectWarGump(Mobile from, Guild guild) : base(from, guild, true, guild.WarInvitations) + { + } + + protected override void Design() + { + AddHtmlLocalized(20, 10, 400, 35, 1011148); // Select the guild to reject their invitations: + + AddButton(20, 400, 4005, 4007, 1); + AddHtmlLocalized(55, 400, 245, 30, 1011101); // Reject war invitations. + + AddButton(300, 400, 4005, 4007, 2); + AddHtmlLocalized(335, 400, 100, 35, 1011012); // CANCEL + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (GuildGump.BadLeader(m_Mobile, m_Guild)) + return; + + if (info.ButtonID == 1) + { + var switches = info.Switches; + + if (switches.Length > 0) + { + var index = switches[0]; + + if (index >= 0 && index < m_List.Count) + { + var g = m_List[index]; + + if (g != null) + { + m_Guild.WarInvitations.Remove(g); + g.WarDeclarations.Remove(m_Guild); + + GuildGump.EnsureClosed(m_Mobile); + + if (m_Guild.WarInvitations.Count > 0) + m_Mobile.SendGump(new GuildRejectWarGump(m_Mobile, m_Guild)); + else + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + } + } + } + else if (info.ButtonID == 2) + { + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildRescindDeclarationGump.cs b/Projects/UOContent/Gumps/Guilds/GuildRescindDeclarationGump.cs index 2a648b5d4..ec4b13c7c 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildRescindDeclarationGump.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildRescindDeclarationGump.cs @@ -1,62 +1,62 @@ -using Server.Guilds; -using Server.Network; - -namespace Server.Gumps -{ - public class GuildRescindDeclarationGump : GuildListGump - { - public GuildRescindDeclarationGump(Mobile from, Guild guild) : base(from, guild, true, guild.WarDeclarations) - { - } - - protected override void Design() - { - AddHtmlLocalized(20, 10, 400, 35, 1011150); // Select the guild to rescind our invitations: - - AddButton(20, 400, 4005, 4007, 1); - AddHtmlLocalized(55, 400, 245, 30, 1011102); // Rescind your war declarations. - - AddButton(300, 400, 4005, 4007, 2); - AddHtmlLocalized(335, 400, 100, 35, 1011012); // CANCEL - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (GuildGump.BadLeader(m_Mobile, m_Guild)) - return; - - if (info.ButtonID == 1) - { - int[] switches = info.Switches; - - if (switches.Length > 0) - { - int index = switches[0]; - - if (index >= 0 && index < m_List.Count) - { - Guild g = m_List[index]; - - if (g != null) - { - m_Guild.WarDeclarations.Remove(g); - g.WarInvitations.Remove(m_Guild); - - GuildGump.EnsureClosed(m_Mobile); - - if (m_Guild.WarDeclarations.Count > 0) - m_Mobile.SendGump(new GuildRescindDeclarationGump(m_Mobile, m_Guild)); - else - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - } - } - } - else if (info.ButtonID == 2) - { - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - } - } -} +using Server.Guilds; +using Server.Network; + +namespace Server.Gumps +{ + public class GuildRescindDeclarationGump : GuildListGump + { + public GuildRescindDeclarationGump(Mobile from, Guild guild) : base(from, guild, true, guild.WarDeclarations) + { + } + + protected override void Design() + { + AddHtmlLocalized(20, 10, 400, 35, 1011150); // Select the guild to rescind our invitations: + + AddButton(20, 400, 4005, 4007, 1); + AddHtmlLocalized(55, 400, 245, 30, 1011102); // Rescind your war declarations. + + AddButton(300, 400, 4005, 4007, 2); + AddHtmlLocalized(335, 400, 100, 35, 1011012); // CANCEL + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (GuildGump.BadLeader(m_Mobile, m_Guild)) + return; + + if (info.ButtonID == 1) + { + var switches = info.Switches; + + if (switches.Length > 0) + { + var index = switches[0]; + + if (index >= 0 && index < m_List.Count) + { + var g = m_List[index]; + + if (g != null) + { + m_Guild.WarDeclarations.Remove(g); + g.WarInvitations.Remove(m_Guild); + + GuildGump.EnsureClosed(m_Mobile); + + if (m_Guild.WarDeclarations.Count > 0) + m_Mobile.SendGump(new GuildRescindDeclarationGump(m_Mobile, m_Guild)); + else + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + } + } + } + else if (info.ButtonID == 2) + { + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildRosterGump.cs b/Projects/UOContent/Gumps/Guilds/GuildRosterGump.cs index 5588678a3..40a5bbb9e 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildRosterGump.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildRosterGump.cs @@ -1,32 +1,32 @@ -using Server.Guilds; -using Server.Network; - -namespace Server.Gumps -{ - public class GuildRosterGump : GuildMobileListGump - { - public GuildRosterGump(Mobile from, Guild guild) : base(from, guild, false, guild.Members) - { - } - - protected override void Design() - { - AddHtml(20, 10, 500, 35, $"
{m_Guild.Name}
"); - - AddButton(20, 400, 4005, 4007, 1); - AddHtmlLocalized(55, 400, 300, 35, 1011120); // Return to the main menu. - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (GuildGump.BadMember(m_Mobile, m_Guild)) - return; - - if (info.ButtonID == 1) - { - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildGump(m_Mobile, m_Guild)); - } - } - } -} +using Server.Guilds; +using Server.Network; + +namespace Server.Gumps +{ + public class GuildRosterGump : GuildMobileListGump + { + public GuildRosterGump(Mobile from, Guild guild) : base(from, guild, false, guild.Members) + { + } + + protected override void Design() + { + AddHtml(20, 10, 500, 35, $"
{m_Guild.Name}
"); + + AddButton(20, 400, 4005, 4007, 1); + AddHtmlLocalized(55, 400, 300, 35, 1011120); // Return to the main menu. + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (GuildGump.BadMember(m_Mobile, m_Guild)) + return; + + if (info.ButtonID == 1) + { + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildGump(m_Mobile, m_Guild)); + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildTitlePrompt.cs b/Projects/UOContent/Gumps/Guilds/GuildTitlePrompt.cs index 60bda09a1..af7225a7b 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildTitlePrompt.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildTitlePrompt.cs @@ -1,49 +1,49 @@ -using Server.Guilds; -using Server.Prompts; - -namespace Server.Gumps -{ - public class GuildTitlePrompt : Prompt - { - private readonly Guild m_Guild; - private readonly Mobile m_Leader; - private readonly Mobile m_Target; - - public GuildTitlePrompt(Mobile leader, Mobile target, Guild g) - { - m_Leader = leader; - m_Target = target; - m_Guild = g; - } - - public override void OnCancel(Mobile from) - { - if (GuildGump.BadLeader(m_Leader, m_Guild)) - return; - if (m_Target.Deleted || !m_Guild.IsMember(m_Target)) - return; - - GuildGump.EnsureClosed(m_Leader); - m_Leader.SendGump(new GuildmasterGump(m_Leader, m_Guild)); - } - - public override void OnResponse(Mobile from, string text) - { - if (GuildGump.BadLeader(m_Leader, m_Guild)) - return; - if (m_Target.Deleted || !m_Guild.IsMember(m_Target)) - return; - - text = text.Trim(); - - if (text.Length > 20) - text = text.Substring(0, 20); - - if (text.Length > 0) - m_Target.GuildTitle = text; - - GuildGump.EnsureClosed(m_Leader); - m_Leader.SendGump(new GuildmasterGump(m_Leader, m_Guild)); - } - } -} \ No newline at end of file +using Server.Guilds; +using Server.Prompts; + +namespace Server.Gumps +{ + public class GuildTitlePrompt : Prompt + { + private readonly Guild m_Guild; + private readonly Mobile m_Leader; + private readonly Mobile m_Target; + + public GuildTitlePrompt(Mobile leader, Mobile target, Guild g) + { + m_Leader = leader; + m_Target = target; + m_Guild = g; + } + + public override void OnCancel(Mobile from) + { + if (GuildGump.BadLeader(m_Leader, m_Guild)) + return; + if (m_Target.Deleted || !m_Guild.IsMember(m_Target)) + return; + + GuildGump.EnsureClosed(m_Leader); + m_Leader.SendGump(new GuildmasterGump(m_Leader, m_Guild)); + } + + public override void OnResponse(Mobile from, string text) + { + if (GuildGump.BadLeader(m_Leader, m_Guild)) + return; + if (m_Target.Deleted || !m_Guild.IsMember(m_Target)) + return; + + text = text.Trim(); + + if (text.Length > 20) + text = text.Substring(0, 20); + + if (text.Length > 0) + m_Target.GuildTitle = text; + + GuildGump.EnsureClosed(m_Leader); + m_Leader.SendGump(new GuildmasterGump(m_Leader, m_Guild)); + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildWarAdminGump.cs b/Projects/UOContent/Gumps/Guilds/GuildWarAdminGump.cs index f8401635a..26a0f3e03 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildWarAdminGump.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildWarAdminGump.cs @@ -1,118 +1,118 @@ -using Server.Guilds; -using Server.Network; - -namespace Server.Gumps -{ - public class GuildWarAdminGump : Gump - { - private readonly Guild m_Guild; - private readonly Mobile m_Mobile; - - public GuildWarAdminGump(Mobile from, Guild guild) : base(20, 30) - { - m_Mobile = from; - m_Guild = guild; - - Draggable = false; - - AddPage(0); - AddBackground(0, 0, 550, 440, 5054); - AddBackground(10, 10, 530, 420, 3000); - - AddHtmlLocalized(20, 10, 510, 35, 1011105); //
WAR FUNCTIONS
- - AddButton(20, 40, 4005, 4007, 1); - AddHtmlLocalized(55, 40, 400, 30, 1011099); // Declare war through guild name search. - - int count = 0; - - if (guild.Enemies.Count > 0) - { - AddButton(20, 160 + count * 30, 4005, 4007, 2); - AddHtmlLocalized(55, 160 + count++ * 30, 400, 30, 1011103); // Declare peace. - } - else - { - AddHtmlLocalized(20, 160 + count++ * 30, 400, 30, 1013033); // No current wars - } - - if (guild.WarInvitations.Count > 0) - { - AddButton(20, 160 + count * 30, 4005, 4007, 3); - AddHtmlLocalized(55, 160 + count++ * 30, 400, 30, 1011100); // Accept war invitations. - - AddButton(20, 160 + count * 30, 4005, 4007, 4); - AddHtmlLocalized(55, 160 + count++ * 30, 400, 30, 1011101); // Reject war invitations. - } - else - { - AddHtmlLocalized(20, 160 + count++ * 30, 400, 30, 1018012); // No current invitations received for war. - } - - if (guild.WarDeclarations.Count > 0) - { - AddButton(20, 160 + count * 30, 4005, 4007, 5); - AddHtmlLocalized(55, 160 + count++ * 30, 400, 30, 1011102); // Rescind your war declarations. - } - else - { - AddHtmlLocalized(20, 160 + count++ * 30, 400, 30, 1013055); // No current war declarations - } - - AddButton(20, 400, 4005, 4007, 6); - AddHtmlLocalized(55, 400, 400, 35, 1011104); // Return to the previous menu. - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (GuildGump.BadLeader(m_Mobile, m_Guild)) - return; - - switch (info.ButtonID) - { - case 1: // Declare war - { - m_Mobile.SendLocalizedMessage(1018001); // Declare war through search - Enter Guild Name: - m_Mobile.Prompt = new GuildDeclareWarPrompt(m_Mobile, m_Guild); - - break; - } - case 2: // Declare peace - { - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildDeclarePeaceGump(m_Mobile, m_Guild)); - - break; - } - case 3: // Accept war - { - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildAcceptWarGump(m_Mobile, m_Guild)); - - break; - } - case 4: // Reject war - { - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildRejectWarGump(m_Mobile, m_Guild)); - - break; - } - case 5: // Rescind declarations - { - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildRescindDeclarationGump(m_Mobile, m_Guild)); - - break; - } - case 6: // Return - { - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - - break; - } - } - } - } -} +using Server.Guilds; +using Server.Network; + +namespace Server.Gumps +{ + public class GuildWarAdminGump : Gump + { + private readonly Guild m_Guild; + private readonly Mobile m_Mobile; + + public GuildWarAdminGump(Mobile from, Guild guild) : base(20, 30) + { + m_Mobile = from; + m_Guild = guild; + + Draggable = false; + + AddPage(0); + AddBackground(0, 0, 550, 440, 5054); + AddBackground(10, 10, 530, 420, 3000); + + AddHtmlLocalized(20, 10, 510, 35, 1011105); //
WAR FUNCTIONS
+ + AddButton(20, 40, 4005, 4007, 1); + AddHtmlLocalized(55, 40, 400, 30, 1011099); // Declare war through guild name search. + + var count = 0; + + if (guild.Enemies.Count > 0) + { + AddButton(20, 160 + count * 30, 4005, 4007, 2); + AddHtmlLocalized(55, 160 + count++ * 30, 400, 30, 1011103); // Declare peace. + } + else + { + AddHtmlLocalized(20, 160 + count++ * 30, 400, 30, 1013033); // No current wars + } + + if (guild.WarInvitations.Count > 0) + { + AddButton(20, 160 + count * 30, 4005, 4007, 3); + AddHtmlLocalized(55, 160 + count++ * 30, 400, 30, 1011100); // Accept war invitations. + + AddButton(20, 160 + count * 30, 4005, 4007, 4); + AddHtmlLocalized(55, 160 + count++ * 30, 400, 30, 1011101); // Reject war invitations. + } + else + { + AddHtmlLocalized(20, 160 + count++ * 30, 400, 30, 1018012); // No current invitations received for war. + } + + if (guild.WarDeclarations.Count > 0) + { + AddButton(20, 160 + count * 30, 4005, 4007, 5); + AddHtmlLocalized(55, 160 + count++ * 30, 400, 30, 1011102); // Rescind your war declarations. + } + else + { + AddHtmlLocalized(20, 160 + count++ * 30, 400, 30, 1013055); // No current war declarations + } + + AddButton(20, 400, 4005, 4007, 6); + AddHtmlLocalized(55, 400, 400, 35, 1011104); // Return to the previous menu. + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (GuildGump.BadLeader(m_Mobile, m_Guild)) + return; + + switch (info.ButtonID) + { + case 1: // Declare war + { + m_Mobile.SendLocalizedMessage(1018001); // Declare war through search - Enter Guild Name: + m_Mobile.Prompt = new GuildDeclareWarPrompt(m_Mobile, m_Guild); + + break; + } + case 2: // Declare peace + { + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildDeclarePeaceGump(m_Mobile, m_Guild)); + + break; + } + case 3: // Accept war + { + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildAcceptWarGump(m_Mobile, m_Guild)); + + break; + } + case 4: // Reject war + { + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildRejectWarGump(m_Mobile, m_Guild)); + + break; + } + case 5: // Rescind declarations + { + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildRescindDeclarationGump(m_Mobile, m_Guild)); + + break; + } + case 6: // Return + { + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildWarGump.cs b/Projects/UOContent/Gumps/Guilds/GuildWarGump.cs index 54a8f8579..a05094d7b 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildWarGump.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildWarGump.cs @@ -1,101 +1,100 @@ -using System.Collections.Generic; -using Server.Guilds; -using Server.Network; - -namespace Server.Gumps -{ - public class GuildWarGump : Gump - { - private readonly Guild m_Guild; - private readonly Mobile m_Mobile; - - public GuildWarGump(Mobile from, Guild guild) : base(20, 30) - { - m_Mobile = from; - m_Guild = guild; - - Draggable = false; - - AddPage(0); - AddBackground(0, 0, 550, 440, 5054); - AddBackground(10, 10, 530, 420, 3000); - - AddHtmlLocalized(20, 10, 500, 35, 1011133); //
WARFARE STATUS
- - AddButton(20, 400, 4005, 4007, 1); - AddHtmlLocalized(55, 400, 300, 35, 1011120); // Return to the main menu. - - AddPage(1); - - AddButton(375, 375, 5224, 5224, 0, GumpButtonType.Page, 2); - AddHtmlLocalized(410, 373, 100, 25, 1011066); // Next page - - AddHtmlLocalized(20, 45, 400, 20, 1011134); // We are at war with: - - List enemies = guild.Enemies; - - if (enemies.Count == 0) - AddHtmlLocalized(20, 65, 400, 20, 1013033); // No current wars - else - for (int i = 0; i < enemies.Count; ++i) - { - Guild g = enemies[i]; - - AddHtml(20, 65 + i * 20, 300, 20, g.Name); - } - - AddPage(2); - - AddButton(375, 375, 5224, 5224, 0, GumpButtonType.Page, 3); - AddHtmlLocalized(410, 373, 100, 25, 1011066); // Next page - - AddButton(30, 375, 5223, 5223, 0, GumpButtonType.Page, 1); - AddHtmlLocalized(65, 373, 150, 25, 1011067); // Previous page - - AddHtmlLocalized(20, 45, 400, 20, 1011136); // Guilds that we have declared war on: - - List declared = guild.WarDeclarations; - - if (declared.Count == 0) - AddHtmlLocalized(20, 65, 400, 20, 1018012); // No current invitations received for war. - else - for (int i = 0; i < declared.Count; ++i) - { - Guild g = declared[i]; - - AddHtml(20, 65 + i * 20, 300, 20, g.Name); - } - - AddPage(3); - - AddButton(30, 375, 5223, 5223, 0, GumpButtonType.Page, 2); - AddHtmlLocalized(65, 373, 150, 25, 1011067); // Previous page - - AddHtmlLocalized(20, 45, 400, 20, 1011135); // Guilds that have declared war on us: - - List invites = guild.WarInvitations; - - if (invites.Count == 0) - AddHtmlLocalized(20, 65, 400, 20, 1013055); // No current war declarations - else - for (int i = 0; i < invites.Count; ++i) - { - Guild g = invites[i]; - - AddHtml(20, 65 + i * 20, 300, 20, g.Name); - } - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (GuildGump.BadMember(m_Mobile, m_Guild)) - return; - - if (info.ButtonID == 1) - { - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildGump(m_Mobile, m_Guild)); - } - } - } -} +using Server.Guilds; +using Server.Network; + +namespace Server.Gumps +{ + public class GuildWarGump : Gump + { + private readonly Guild m_Guild; + private readonly Mobile m_Mobile; + + public GuildWarGump(Mobile from, Guild guild) : base(20, 30) + { + m_Mobile = from; + m_Guild = guild; + + Draggable = false; + + AddPage(0); + AddBackground(0, 0, 550, 440, 5054); + AddBackground(10, 10, 530, 420, 3000); + + AddHtmlLocalized(20, 10, 500, 35, 1011133); //
WARFARE STATUS
+ + AddButton(20, 400, 4005, 4007, 1); + AddHtmlLocalized(55, 400, 300, 35, 1011120); // Return to the main menu. + + AddPage(1); + + AddButton(375, 375, 5224, 5224, 0, GumpButtonType.Page, 2); + AddHtmlLocalized(410, 373, 100, 25, 1011066); // Next page + + AddHtmlLocalized(20, 45, 400, 20, 1011134); // We are at war with: + + var enemies = guild.Enemies; + + if (enemies.Count == 0) + AddHtmlLocalized(20, 65, 400, 20, 1013033); // No current wars + else + for (var i = 0; i < enemies.Count; ++i) + { + var g = enemies[i]; + + AddHtml(20, 65 + i * 20, 300, 20, g.Name); + } + + AddPage(2); + + AddButton(375, 375, 5224, 5224, 0, GumpButtonType.Page, 3); + AddHtmlLocalized(410, 373, 100, 25, 1011066); // Next page + + AddButton(30, 375, 5223, 5223, 0, GumpButtonType.Page, 1); + AddHtmlLocalized(65, 373, 150, 25, 1011067); // Previous page + + AddHtmlLocalized(20, 45, 400, 20, 1011136); // Guilds that we have declared war on: + + var declared = guild.WarDeclarations; + + if (declared.Count == 0) + AddHtmlLocalized(20, 65, 400, 20, 1018012); // No current invitations received for war. + else + for (var i = 0; i < declared.Count; ++i) + { + var g = declared[i]; + + AddHtml(20, 65 + i * 20, 300, 20, g.Name); + } + + AddPage(3); + + AddButton(30, 375, 5223, 5223, 0, GumpButtonType.Page, 2); + AddHtmlLocalized(65, 373, 150, 25, 1011067); // Previous page + + AddHtmlLocalized(20, 45, 400, 20, 1011135); // Guilds that have declared war on us: + + var invites = guild.WarInvitations; + + if (invites.Count == 0) + AddHtmlLocalized(20, 65, 400, 20, 1013055); // No current war declarations + else + for (var i = 0; i < invites.Count; ++i) + { + var g = invites[i]; + + AddHtml(20, 65 + i * 20, 300, 20, g.Name); + } + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (GuildGump.BadMember(m_Mobile, m_Guild)) + return; + + if (info.ButtonID == 1) + { + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildGump(m_Mobile, m_Guild)); + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildWebsitePrompt.cs b/Projects/UOContent/Gumps/Guilds/GuildWebsitePrompt.cs index ba15f1960..54b76dd76 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildWebsitePrompt.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildWebsitePrompt.cs @@ -1,43 +1,43 @@ -using Server.Guilds; -using Server.Prompts; - -namespace Server.Gumps -{ - public class GuildWebsitePrompt : Prompt - { - private readonly Guild m_Guild; - private readonly Mobile m_Mobile; - - public GuildWebsitePrompt(Mobile m, Guild g) - { - m_Mobile = m; - m_Guild = g; - } - - public override void OnCancel(Mobile from) - { - if (GuildGump.BadLeader(m_Mobile, m_Guild)) - return; - - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - - public override void OnResponse(Mobile from, string text) - { - if (GuildGump.BadLeader(m_Mobile, m_Guild)) - return; - - text = text.Trim(); - - if (text.Length > 50) - text = text.Substring(0, 50); - - if (text.Length > 0) - m_Guild.Website = text; - - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - } - } -} \ No newline at end of file +using Server.Guilds; +using Server.Prompts; + +namespace Server.Gumps +{ + public class GuildWebsitePrompt : Prompt + { + private readonly Guild m_Guild; + private readonly Mobile m_Mobile; + + public GuildWebsitePrompt(Mobile m, Guild g) + { + m_Mobile = m; + m_Guild = g; + } + + public override void OnCancel(Mobile from) + { + if (GuildGump.BadLeader(m_Mobile, m_Guild)) + return; + + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + + public override void OnResponse(Mobile from, string text) + { + if (GuildGump.BadLeader(m_Mobile, m_Guild)) + return; + + text = text.Trim(); + + if (text.Length > 50) + text = text.Substring(0, 50); + + if (text.Length > 0) + m_Guild.Website = text; + + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/GuildmasterGump.cs b/Projects/UOContent/Gumps/Guilds/GuildmasterGump.cs index c96e30a9d..e8ca35e9a 100644 --- a/Projects/UOContent/Gumps/Guilds/GuildmasterGump.cs +++ b/Projects/UOContent/Gumps/Guilds/GuildmasterGump.cs @@ -1,188 +1,189 @@ -using Server.Guilds; -using Server.Items; -using Server.Network; - -namespace Server.Gumps -{ - public class GuildmasterGump : Gump - { - private readonly Guild m_Guild; - private readonly Mobile m_Mobile; - - public GuildmasterGump(Mobile from, Guild guild) : base(20, 30) - { - m_Mobile = from; - m_Guild = guild; - - Draggable = false; - - AddPage(0); - AddBackground(0, 0, 550, 400, 5054); - AddBackground(10, 10, 530, 380, 3000); - - AddHtmlLocalized(20, 15, 510, 35, 1011121); //
GUILDMASTER FUNCTIONS
- - AddButton(20, 40, 4005, 4007, 2); - AddHtmlLocalized(55, 40, 470, 30, 1011107); // Set the guild name. - - AddButton(20, 70, 4005, 4007, 3); - AddHtmlLocalized(55, 70, 470, 30, 1011109); // Set the guild's abbreviation. - - if (Guild.OrderChaos) - { - AddButton(20, 100, 4005, 4007, 4); - - switch (m_Guild.Type) - { - case GuildType.Regular: - AddHtmlLocalized(55, 100, 470, 30, 1013059); // Change guild type: Currently Standard - break; - case GuildType.Order: - AddHtmlLocalized(55, 100, 470, 30, 1013057); // Change guild type: Currently Order - break; - case GuildType.Chaos: - AddHtmlLocalized(55, 100, 470, 30, 1013058); // Change guild type: Currently Chaos - break; - } - } - - AddButton(20, 130, 4005, 4007, 5); - AddHtmlLocalized(55, 130, 470, 30, 1011112); // Set the guild's charter. - - AddButton(20, 160, 4005, 4007, 6); - AddHtmlLocalized(55, 160, 470, 30, 1011113); // Dismiss a member. - - AddButton(20, 190, 4005, 4007, 7); - AddHtmlLocalized(55, 190, 470, 30, 1011114); // Go to the WAR menu. - - if (m_Guild.Candidates.Count > 0) - { - AddButton(20, 220, 4005, 4007, 8); - AddHtmlLocalized(55, 220, 470, 30, 1013056); // Administer the list of candidates - } - else - { - AddImage(20, 220, 4020); - AddHtmlLocalized(55, 220, 470, 30, 1013031); // There are currently no candidates for membership. - } - - AddButton(20, 250, 4005, 4007, 9); - AddHtmlLocalized(55, 250, 470, 30, 1011117); // Set the guildmaster's title. - - AddButton(20, 280, 4005, 4007, 10); - AddHtmlLocalized(55, 280, 470, 30, 1011118); // Grant a title to another member. - - AddButton(20, 310, 4005, 4007, 11); - AddHtmlLocalized(55, 310, 470, 30, 1011119); // Move this guildstone. - - AddButton(20, 360, 4005, 4007, 1); - AddHtmlLocalized(55, 360, 245, 30, 1011120); // Return to the main menu. - - AddButton(300, 360, 4005, 4007, 0); - AddHtmlLocalized(335, 360, 100, 30, 1011441); // EXIT - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (GuildGump.BadLeader(m_Mobile, m_Guild)) - return; - - switch (info.ButtonID) - { - case 1: // Main menu - { - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildGump(m_Mobile, m_Guild)); - - break; - } - case 2: // Set guild name - { - m_Mobile.SendLocalizedMessage(1013060); // Enter new guild name (40 characters max): - m_Mobile.Prompt = new GuildNamePrompt(m_Mobile, m_Guild); - - break; - } - case 3: // Set guild abbreviation - { - m_Mobile.SendLocalizedMessage(1013061); // Enter new guild abbreviation (3 characters max): - m_Mobile.Prompt = new GuildAbbrvPrompt(m_Mobile, m_Guild); - - break; - } - case 4: // Change guild type - { - if (!Guild.OrderChaos) - return; - - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildChangeTypeGump(m_Mobile, m_Guild)); - - break; - } - case 5: // Set charter - { - m_Mobile.SendLocalizedMessage(1013071); // Enter the new guild charter (50 characters max): - m_Mobile.Prompt = new GuildCharterPrompt(m_Mobile, m_Guild); - - break; - } - case 6: // Dismiss member - { - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildDismissGump(m_Mobile, m_Guild)); - - break; - } - case 7: // War menu - { - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildWarAdminGump(m_Mobile, m_Guild)); - - break; - } - case 8: // Administer candidates - { - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildAdminCandidatesGump(m_Mobile, m_Guild)); - - break; - } - case 9: // Set guildmaster's title - { - m_Mobile.SendLocalizedMessage(1013073); // Enter new guildmaster title (20 characters max): - m_Mobile.Prompt = new GuildTitlePrompt(m_Mobile, m_Mobile, m_Guild); - - break; - } - case 10: // Grant title - { - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GrantGuildTitleGump(m_Mobile, m_Guild)); - - break; - } - case 11: // Move guildstone - { - if (m_Guild.Guildstone != null) - { - GuildTeleporter item = new GuildTeleporter(m_Guild.Guildstone); - - m_Guild.Teleporter?.Delete(); - - m_Mobile.SendLocalizedMessage( - 501133); // Use the teleporting object placed in your backpack to move this guildstone. - - m_Mobile.AddToBackpack(item); - m_Guild.Teleporter = item; - } - - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); - - break; - } - } - } - } -} +using Server.Guilds; +using Server.Items; +using Server.Network; + +namespace Server.Gumps +{ + public class GuildmasterGump : Gump + { + private readonly Guild m_Guild; + private readonly Mobile m_Mobile; + + public GuildmasterGump(Mobile from, Guild guild) : base(20, 30) + { + m_Mobile = from; + m_Guild = guild; + + Draggable = false; + + AddPage(0); + AddBackground(0, 0, 550, 400, 5054); + AddBackground(10, 10, 530, 380, 3000); + + AddHtmlLocalized(20, 15, 510, 35, 1011121); //
GUILDMASTER FUNCTIONS
+ + AddButton(20, 40, 4005, 4007, 2); + AddHtmlLocalized(55, 40, 470, 30, 1011107); // Set the guild name. + + AddButton(20, 70, 4005, 4007, 3); + AddHtmlLocalized(55, 70, 470, 30, 1011109); // Set the guild's abbreviation. + + if (Guild.OrderChaos) + { + AddButton(20, 100, 4005, 4007, 4); + + switch (m_Guild.Type) + { + case GuildType.Regular: + AddHtmlLocalized(55, 100, 470, 30, 1013059); // Change guild type: Currently Standard + break; + case GuildType.Order: + AddHtmlLocalized(55, 100, 470, 30, 1013057); // Change guild type: Currently Order + break; + case GuildType.Chaos: + AddHtmlLocalized(55, 100, 470, 30, 1013058); // Change guild type: Currently Chaos + break; + } + } + + AddButton(20, 130, 4005, 4007, 5); + AddHtmlLocalized(55, 130, 470, 30, 1011112); // Set the guild's charter. + + AddButton(20, 160, 4005, 4007, 6); + AddHtmlLocalized(55, 160, 470, 30, 1011113); // Dismiss a member. + + AddButton(20, 190, 4005, 4007, 7); + AddHtmlLocalized(55, 190, 470, 30, 1011114); // Go to the WAR menu. + + if (m_Guild.Candidates.Count > 0) + { + AddButton(20, 220, 4005, 4007, 8); + AddHtmlLocalized(55, 220, 470, 30, 1013056); // Administer the list of candidates + } + else + { + AddImage(20, 220, 4020); + AddHtmlLocalized(55, 220, 470, 30, 1013031); // There are currently no candidates for membership. + } + + AddButton(20, 250, 4005, 4007, 9); + AddHtmlLocalized(55, 250, 470, 30, 1011117); // Set the guildmaster's title. + + AddButton(20, 280, 4005, 4007, 10); + AddHtmlLocalized(55, 280, 470, 30, 1011118); // Grant a title to another member. + + AddButton(20, 310, 4005, 4007, 11); + AddHtmlLocalized(55, 310, 470, 30, 1011119); // Move this guildstone. + + AddButton(20, 360, 4005, 4007, 1); + AddHtmlLocalized(55, 360, 245, 30, 1011120); // Return to the main menu. + + AddButton(300, 360, 4005, 4007, 0); + AddHtmlLocalized(335, 360, 100, 30, 1011441); // EXIT + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (GuildGump.BadLeader(m_Mobile, m_Guild)) + return; + + switch (info.ButtonID) + { + case 1: // Main menu + { + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildGump(m_Mobile, m_Guild)); + + break; + } + case 2: // Set guild name + { + m_Mobile.SendLocalizedMessage(1013060); // Enter new guild name (40 characters max): + m_Mobile.Prompt = new GuildNamePrompt(m_Mobile, m_Guild); + + break; + } + case 3: // Set guild abbreviation + { + m_Mobile.SendLocalizedMessage(1013061); // Enter new guild abbreviation (3 characters max): + m_Mobile.Prompt = new GuildAbbrvPrompt(m_Mobile, m_Guild); + + break; + } + case 4: // Change guild type + { + if (!Guild.OrderChaos) + return; + + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildChangeTypeGump(m_Mobile, m_Guild)); + + break; + } + case 5: // Set charter + { + m_Mobile.SendLocalizedMessage(1013071); // Enter the new guild charter (50 characters max): + m_Mobile.Prompt = new GuildCharterPrompt(m_Mobile, m_Guild); + + break; + } + case 6: // Dismiss member + { + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildDismissGump(m_Mobile, m_Guild)); + + break; + } + case 7: // War menu + { + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildWarAdminGump(m_Mobile, m_Guild)); + + break; + } + case 8: // Administer candidates + { + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildAdminCandidatesGump(m_Mobile, m_Guild)); + + break; + } + case 9: // Set guildmaster's title + { + m_Mobile.SendLocalizedMessage(1013073); // Enter new guildmaster title (20 characters max): + m_Mobile.Prompt = new GuildTitlePrompt(m_Mobile, m_Mobile, m_Guild); + + break; + } + case 10: // Grant title + { + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GrantGuildTitleGump(m_Mobile, m_Guild)); + + break; + } + case 11: // Move guildstone + { + if (m_Guild.Guildstone != null) + { + var item = new GuildTeleporter(m_Guild.Guildstone); + + m_Guild.Teleporter?.Delete(); + + m_Mobile.SendLocalizedMessage( + 501133 + ); // Use the teleporting object placed in your backpack to move this guildstone. + + m_Mobile.AddToBackpack(item); + m_Guild.Teleporter = item; + } + + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildmasterGump(m_Mobile, m_Guild)); + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/New Guild System/AdvancedSearch.cs b/Projects/UOContent/Gumps/Guilds/New Guild System/AdvancedSearch.cs index c0e2d7fae..790f183df 100644 --- a/Projects/UOContent/Gumps/Guilds/New Guild System/AdvancedSearch.cs +++ b/Projects/UOContent/Gumps/Guilds/New Guild System/AdvancedSearch.cs @@ -1,67 +1,74 @@ -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Guilds -{ - public delegate void SearchSelectionCallback(GuildDisplayType display); - - public class GuildAdvancedSearchGump : BaseGuildGump - { - private readonly SearchSelectionCallback m_Callback; - private readonly GuildDisplayType m_Display; - - public GuildAdvancedSearchGump(PlayerMobile pm, Guild g, GuildDisplayType display, SearchSelectionCallback callback) - : base(pm, g) - { - m_Callback = callback; - m_Display = display; - PopulateGump(); - } - - public override void PopulateGump() - { - base.PopulateGump(); - - AddHtmlLocalized(431, 43, 110, 26, 1062978, 0xF); // Diplomacy - - AddHtmlLocalized(65, 80, 480, 26, 1063124, 0xF, true); // Advanced Search Options - - AddHtmlLocalized(65, 110, 480, 26, 1063136 + (int)m_Display, 0xF); // Showing All Guilds/w/Relation/Waiting Relation - - AddGroup(1); - AddRadio(75, 140, 0xD2, 0xD3, false, 2); - AddHtmlLocalized(105, 140, 200, 26, 1063006, 0x0); // Show Guilds with Relationship - AddRadio(75, 170, 0xD2, 0xD3, false, 1); - AddHtmlLocalized(105, 170, 200, 26, 1063005, 0x0); // Show Guilds Awaiting Action - AddRadio(75, 200, 0xD2, 0xD3, false, 0); - AddHtmlLocalized(105, 200, 200, 26, 1063007, 0x0); // Show All Guilds - - AddBackground(450, 370, 100, 26, 0x2486); - AddButton(455, 375, 0x845, 0x846, 5); - AddHtmlLocalized(480, 373, 60, 26, 1006044, 0x0); // OK - AddBackground(340, 370, 100, 26, 0x2486); - AddButton(345, 375, 0x845, 0x846, 0); - AddHtmlLocalized(370, 373, 60, 26, 1006045, 0x0); // Cancel - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - base.OnResponse(sender, info); - - if (!(sender.Mobile is PlayerMobile pm) || !IsMember(pm, guild)) - return; - - GuildDisplayType display = m_Display; - - if (info.ButtonID == 5) - for (int i = 0; i < 3; i++) - if (info.IsSwitched(i)) - { - display = (GuildDisplayType)i; - m_Callback(display); - break; - } - } - } -} +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Guilds +{ + public delegate void SearchSelectionCallback(GuildDisplayType display); + + public class GuildAdvancedSearchGump : BaseGuildGump + { + private readonly SearchSelectionCallback m_Callback; + private readonly GuildDisplayType m_Display; + + public GuildAdvancedSearchGump(PlayerMobile pm, Guild g, GuildDisplayType display, SearchSelectionCallback callback) + : base(pm, g) + { + m_Callback = callback; + m_Display = display; + PopulateGump(); + } + + public override void PopulateGump() + { + base.PopulateGump(); + + AddHtmlLocalized(431, 43, 110, 26, 1062978, 0xF); // Diplomacy + + AddHtmlLocalized(65, 80, 480, 26, 1063124, 0xF, true); // Advanced Search Options + + AddHtmlLocalized( + 65, + 110, + 480, + 26, + 1063136 + (int)m_Display, + 0xF + ); // Showing All Guilds/w/Relation/Waiting Relation + + AddGroup(1); + AddRadio(75, 140, 0xD2, 0xD3, false, 2); + AddHtmlLocalized(105, 140, 200, 26, 1063006, 0x0); // Show Guilds with Relationship + AddRadio(75, 170, 0xD2, 0xD3, false, 1); + AddHtmlLocalized(105, 170, 200, 26, 1063005, 0x0); // Show Guilds Awaiting Action + AddRadio(75, 200, 0xD2, 0xD3, false, 0); + AddHtmlLocalized(105, 200, 200, 26, 1063007, 0x0); // Show All Guilds + + AddBackground(450, 370, 100, 26, 0x2486); + AddButton(455, 375, 0x845, 0x846, 5); + AddHtmlLocalized(480, 373, 60, 26, 1006044, 0x0); // OK + AddBackground(340, 370, 100, 26, 0x2486); + AddButton(345, 375, 0x845, 0x846, 0); + AddHtmlLocalized(370, 373, 60, 26, 1006045, 0x0); // Cancel + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + base.OnResponse(sender, info); + + if (!(sender.Mobile is PlayerMobile pm) || !IsMember(pm, guild)) + return; + + var display = m_Display; + + if (info.ButtonID == 5) + for (var i = 0; i < 3; i++) + if (info.IsSwitched(i)) + { + display = (GuildDisplayType)i; + m_Callback(display); + break; + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/New Guild System/BaseGuildGump.cs b/Projects/UOContent/Gumps/Guilds/New Guild System/BaseGuildGump.cs index c504c605c..e0b57f77d 100644 --- a/Projects/UOContent/Gumps/Guilds/New Guild System/BaseGuildGump.cs +++ b/Projects/UOContent/Gumps/Guilds/New Guild System/BaseGuildGump.cs @@ -1,125 +1,125 @@ -using Server.Gumps; -using Server.Misc; -using Server.Mobiles; -using Server.Network; - -namespace Server.Guilds -{ - public abstract class BaseGuildGump : Gump - { - public BaseGuildGump(PlayerMobile pm, Guild g, int x = 10, int y = 10) : base(x, y) - { - guild = g; - player = pm; - - pm.CloseGump(); - } - - protected Guild guild { get; } - - protected PlayerMobile player { get; } - - // There's prolly a way to have all the vars set of inherited classes before something is called in the Ctor... but... I can't think of it right now, and I can't use Timer.DelayCall here :< - - public virtual void PopulateGump() - { - AddPage(0); - - AddBackground(0, 0, 600, 440, 0x24AE); - AddBackground(66, 40, 150, 26, 0x2486); - AddButton(71, 45, 0x845, 0x846, 1); - AddHtmlLocalized(96, 43, 110, 26, 1063014, 0x0); // My Guild - AddBackground(236, 40, 150, 26, 0x2486); - AddButton(241, 45, 0x845, 0x846, 2); - AddHtmlLocalized(266, 43, 110, 26, 1062974, 0x0); // Guild Roster - AddBackground(401, 40, 150, 26, 0x2486); - AddButton(406, 45, 0x845, 0x846, 3); - AddHtmlLocalized(431, 43, 110, 26, 1062978, 0x0); // Diplomacy - AddPage(1); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (!(sender.Mobile is PlayerMobile pm)) - return; - - if (!IsMember(pm, guild)) - return; - - switch (info.ButtonID) - { - case 1: - { - pm.SendGump(new GuildInfoGump(pm, guild)); - break; - } - case 2: - { - pm.SendGump(new GuildRosterGump(pm, guild)); - break; - } - case 3: - { - pm.SendGump(new GuildDiplomacyGump(pm, guild)); - break; - } - } - } - - public static bool IsLeader(Mobile m, Guild g) => - !(m.Deleted || g.Disbanded || !(m is PlayerMobile) || - (m.AccessLevel < AccessLevel.GameMaster && g.Leader != m)); - - public static bool IsMember(Mobile m, Guild g) => - !(m.Deleted || g.Disbanded || !(m is PlayerMobile) || - (m.AccessLevel < AccessLevel.GameMaster && !g.IsMember(m))); - - public static bool CheckProfanity(string s, int maxLength = 50) - { - // return NameVerification.Validate( s, 1, 50, true, true, false, int.MaxValue, ProfanityProtection.Exceptions, ProfanityProtection.Disallowed, ProfanityProtection.StartDisallowed ); //What am I doing wrong, this still allows chars like the <3 symbol... 3 AM. someone change this to use this - - // With testing on OSI, Guild stuff seems to follow a 'simpler' method of profanity protection - if (s.Length < 1 || s.Length > maxLength) - return false; - - char[] exceptions = ProfanityProtection.Exceptions; - - s = s.ToLower(); - - for (int i = 0; i < s.Length; ++i) - { - char c = s[i]; - - if ((c < 'a' || c > 'z') && (c < '0' || c > '9')) - { - bool except = false; - - for (int j = 0; !except && j < exceptions.Length; j++) - if (c == exceptions[j]) - except = true; - - if (!except) - return false; - } - } - - string[] disallowed = ProfanityProtection.Disallowed; - - for (int i = 0; i < disallowed.Length; i++) - if (s.IndexOf(disallowed[i]) != -1) - return false; - - return true; - } - - public void AddHtmlText(int x, int y, int width, int height, TextDefinition text, bool back, bool scroll) - { - if (text?.Number > 0) - AddHtmlLocalized(x, y, width, height, text.Number, back, scroll); - else if (text?.String != null) - AddHtml(x, y, width, height, text.String, back, scroll); - } - - public static string Color(string text, int color) => $"{text}"; - } -} +using Server.Gumps; +using Server.Misc; +using Server.Mobiles; +using Server.Network; + +namespace Server.Guilds +{ + public abstract class BaseGuildGump : Gump + { + public BaseGuildGump(PlayerMobile pm, Guild g, int x = 10, int y = 10) : base(x, y) + { + guild = g; + player = pm; + + pm.CloseGump(); + } + + protected Guild guild { get; } + + protected PlayerMobile player { get; } + + // There's prolly a way to have all the vars set of inherited classes before something is called in the Ctor... but... I can't think of it right now, and I can't use Timer.DelayCall here :< + + public virtual void PopulateGump() + { + AddPage(0); + + AddBackground(0, 0, 600, 440, 0x24AE); + AddBackground(66, 40, 150, 26, 0x2486); + AddButton(71, 45, 0x845, 0x846, 1); + AddHtmlLocalized(96, 43, 110, 26, 1063014, 0x0); // My Guild + AddBackground(236, 40, 150, 26, 0x2486); + AddButton(241, 45, 0x845, 0x846, 2); + AddHtmlLocalized(266, 43, 110, 26, 1062974, 0x0); // Guild Roster + AddBackground(401, 40, 150, 26, 0x2486); + AddButton(406, 45, 0x845, 0x846, 3); + AddHtmlLocalized(431, 43, 110, 26, 1062978, 0x0); // Diplomacy + AddPage(1); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (!(sender.Mobile is PlayerMobile pm)) + return; + + if (!IsMember(pm, guild)) + return; + + switch (info.ButtonID) + { + case 1: + { + pm.SendGump(new GuildInfoGump(pm, guild)); + break; + } + case 2: + { + pm.SendGump(new GuildRosterGump(pm, guild)); + break; + } + case 3: + { + pm.SendGump(new GuildDiplomacyGump(pm, guild)); + break; + } + } + } + + public static bool IsLeader(Mobile m, Guild g) => + !(m.Deleted || g.Disbanded || !(m is PlayerMobile) || + m.AccessLevel < AccessLevel.GameMaster && g.Leader != m); + + public static bool IsMember(Mobile m, Guild g) => + !(m.Deleted || g.Disbanded || !(m is PlayerMobile) || + m.AccessLevel < AccessLevel.GameMaster && !g.IsMember(m)); + + public static bool CheckProfanity(string s, int maxLength = 50) + { + // return NameVerification.Validate( s, 1, 50, true, true, false, int.MaxValue, ProfanityProtection.Exceptions, ProfanityProtection.Disallowed, ProfanityProtection.StartDisallowed ); //What am I doing wrong, this still allows chars like the <3 symbol... 3 AM. someone change this to use this + + // With testing on OSI, Guild stuff seems to follow a 'simpler' method of profanity protection + if (s.Length < 1 || s.Length > maxLength) + return false; + + var exceptions = ProfanityProtection.Exceptions; + + s = s.ToLower(); + + for (var i = 0; i < s.Length; ++i) + { + var c = s[i]; + + if ((c < 'a' || c > 'z') && (c < '0' || c > '9')) + { + var except = false; + + for (var j = 0; !except && j < exceptions.Length; j++) + if (c == exceptions[j]) + except = true; + + if (!except) + return false; + } + } + + var disallowed = ProfanityProtection.Disallowed; + + for (var i = 0; i < disallowed.Length; i++) + if (s.IndexOf(disallowed[i]) != -1) + return false; + + return true; + } + + public void AddHtmlText(int x, int y, int width, int height, TextDefinition text, bool back, bool scroll) + { + if (text?.Number > 0) + AddHtmlLocalized(x, y, width, height, text.Number, back, scroll); + else if (text?.String != null) + AddHtml(x, y, width, height, text.String, back, scroll); + } + + public static string Color(string text, int color) => $"{text}"; + } +} diff --git a/Projects/UOContent/Gumps/Guilds/New Guild System/BaseGuildListGump.cs b/Projects/UOContent/Gumps/Guilds/New Guild System/BaseGuildListGump.cs index 9da36e7ac..542d898d4 100644 --- a/Projects/UOContent/Gumps/Guilds/New Guild System/BaseGuildListGump.cs +++ b/Projects/UOContent/Gumps/Guilds/New Guild System/BaseGuildListGump.cs @@ -1,202 +1,215 @@ -using System; -using System.Collections.Generic; -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Guilds -{ - public abstract class BaseGuildListGump : BaseGuildGump - { - private const int itemsPerPage = 8; - private bool m_Ascending; - private readonly IComparer m_Comparer; - private readonly InfoField[] m_Fields; - private readonly string m_Filter; - private List m_List; - private int m_StartNumber; - - public BaseGuildListGump(PlayerMobile pm, Guild g, List list, IComparer currentComparer, bool ascending, - string filter, int startNumber, InfoField[] fields) - : base(pm, g) - { - m_Filter = filter.Trim(); - - m_Comparer = currentComparer; - m_Fields = fields; - m_Ascending = ascending; - m_StartNumber = startNumber; - m_List = list; - } - - public virtual bool WillFilter => m_Filter.Length >= 0; - - public override void PopulateGump() - { - base.PopulateGump(); - - List list = m_List; - if (WillFilter) - { - m_List = new List(); - for (int i = 0; i < list.Count; i++) - if (!IsFiltered(list[i], m_Filter)) - m_List.Add(list[i]); - } - else - { - m_List = new List(list); - } - - m_List.Sort(m_Comparer); - m_StartNumber = Math.Clamp(m_StartNumber, 0, m_List.Count - 1); - - AddBackground(130, 75, 385, 30, 0xBB8); - AddTextEntry(135, 80, 375, 30, 0x481, 1, m_Filter); - AddButton(520, 75, 0x867, 0x868, 5); // Filter Button - - int width = 0; - for (int i = 0; i < m_Fields.Length; i++) - { - InfoField f = m_Fields[i]; - - AddImageTiled(65 + width, 110, f.Width + 10, 26, 0xA40); - AddImageTiled(67 + width, 112, f.Width + 6, 22, 0xBBC); - AddHtmlText(70 + width, 113, f.Width, 20, f.Name, false, false); - - bool isComparer = m_Fields[i].Comparer.GetType() == m_Comparer.GetType(); - - int ButtonID = isComparer ? m_Ascending ? 0x983 : 0x985 : 0x2716; - - AddButton(59 + width + f.Width, 117, ButtonID, ButtonID + (isComparer ? 1 : 0), 100 + i); - - width += f.Width + 12; - } - - if (m_StartNumber <= 0) - AddButton(65, 80, 0x15E3, 0x15E7, 0, GumpButtonType.Page); - else - AddButton(65, 80, 0x15E3, 0x15E7, 6); // Back - - if (m_StartNumber + itemsPerPage > m_List.Count) - AddButton(95, 80, 0x15E1, 0x15E5, 0, GumpButtonType.Page); - else - AddButton(95, 80, 0x15E1, 0x15E5, 7); // Forward - - int itemNumber = 0; - - if (m_Ascending) - for (int i = m_StartNumber; i < m_StartNumber + itemsPerPage && i < m_List.Count; i++) - DrawEntry(m_List[i], i, itemNumber++); - else // descending, go from bottom of list to the top - for (int i = m_List.Count - 1 - m_StartNumber; - i >= 0 && i >= m_List.Count - itemsPerPage - m_StartNumber; - i--) - DrawEntry(m_List[i], i, itemNumber++); - - DrawEndingEntry(itemNumber); - } - - public virtual void DrawEndingEntry(int itemNumber) - { - } - - public virtual bool HasRelationship(T o) => false; - - public virtual void DrawEntry(T o, int index, int itemNumber) - { - int width = 0; - for (int j = 0; j < m_Fields.Length; j++) - { - InfoField f = m_Fields[j]; - - AddImageTiled(65 + width, 138 + itemNumber * 28, f.Width + 10, 26, 0xA40); - AddImageTiled(67 + width, 140 + itemNumber * 28, f.Width + 6, 22, 0xBBC); - AddHtmlText(70 + width, 141 + itemNumber * 28, f.Width, 20, GetValuesFor(o, m_Fields.Length)[j], false, - false); - - width += f.Width + 12; - } - - if (HasRelationship(o)) - AddButton(40, 143 + itemNumber * 28, 0x8AF, 0x8AF, 200 + index); // Info Button - else - AddButton(40, 143 + itemNumber * 28, 0x4B9, 0x4BA, 200 + index); // Info Button - } - - protected abstract TextDefinition[] GetValuesFor(T o, int aryLength); - protected abstract bool IsFiltered(T o, string filter); - - public override void OnResponse(NetState sender, RelayInfo info) - { - base.OnResponse(sender, info); - - if (!(sender.Mobile is PlayerMobile pm) || !IsMember(pm, guild)) - return; - - int id = info.ButtonID; - - switch (id) - { - case 5: // Filter - { - TextRelay t = info.GetTextEntry(1); - pm.SendGump(GetResentGump(player, guild, m_Comparer, m_Ascending, t == null ? "" : t.Text, 0)); - break; - } - case 6: // Back - { - pm.SendGump( - GetResentGump(player, guild, m_Comparer, m_Ascending, m_Filter, m_StartNumber - itemsPerPage)); - break; - } - case 7: // Forward - { - pm.SendGump( - GetResentGump(player, guild, m_Comparer, m_Ascending, m_Filter, m_StartNumber + itemsPerPage)); - break; - } - } - - if (id >= 100 && id < 100 + m_Fields.Length) - { - IComparer comparer = m_Fields[id - 100].Comparer; - - if (m_Comparer.GetType() == comparer.GetType()) - m_Ascending = !m_Ascending; - - pm.SendGump(GetResentGump(player, guild, comparer, m_Ascending, m_Filter, 0)); - } - else if (id >= 200 && id < 200 + m_List.Count) - { - pm.SendGump(GetObjectInfoGump(player, guild, m_List[id - 200])); - } - } - - public abstract Gump GetResentGump(PlayerMobile pm, Guild g, IComparer comparer, bool ascending, string filter, - int startNumber); - - public abstract Gump GetObjectInfoGump(PlayerMobile pm, Guild g, T o); - - public void ResendGump() - { - player.SendGump(GetResentGump(player, guild, m_Comparer, m_Ascending, m_Filter, m_StartNumber)); - } - } - - public struct InfoField - { - public TextDefinition Name { get; } - - public int Width { get; } - - public IComparer Comparer { get; } - - public InfoField(TextDefinition name, int width, IComparer comparer) - { - Name = name; - Width = width; - Comparer = comparer; - } - } -} +using System; +using System.Collections.Generic; +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Guilds +{ + public abstract class BaseGuildListGump : BaseGuildGump + { + private const int itemsPerPage = 8; + private readonly IComparer m_Comparer; + private readonly InfoField[] m_Fields; + private readonly string m_Filter; + private bool m_Ascending; + private List m_List; + private int m_StartNumber; + + public BaseGuildListGump( + PlayerMobile pm, Guild g, List list, IComparer currentComparer, bool ascending, + string filter, int startNumber, InfoField[] fields + ) + : base(pm, g) + { + m_Filter = filter.Trim(); + + m_Comparer = currentComparer; + m_Fields = fields; + m_Ascending = ascending; + m_StartNumber = startNumber; + m_List = list; + } + + public virtual bool WillFilter => m_Filter.Length >= 0; + + public override void PopulateGump() + { + base.PopulateGump(); + + var list = m_List; + if (WillFilter) + { + m_List = new List(); + for (var i = 0; i < list.Count; i++) + if (!IsFiltered(list[i], m_Filter)) + m_List.Add(list[i]); + } + else + { + m_List = new List(list); + } + + m_List.Sort(m_Comparer); + m_StartNumber = Math.Clamp(m_StartNumber, 0, m_List.Count - 1); + + AddBackground(130, 75, 385, 30, 0xBB8); + AddTextEntry(135, 80, 375, 30, 0x481, 1, m_Filter); + AddButton(520, 75, 0x867, 0x868, 5); // Filter Button + + var width = 0; + for (var i = 0; i < m_Fields.Length; i++) + { + var f = m_Fields[i]; + + AddImageTiled(65 + width, 110, f.Width + 10, 26, 0xA40); + AddImageTiled(67 + width, 112, f.Width + 6, 22, 0xBBC); + AddHtmlText(70 + width, 113, f.Width, 20, f.Name, false, false); + + var isComparer = m_Fields[i].Comparer.GetType() == m_Comparer.GetType(); + + var ButtonID = isComparer ? m_Ascending ? 0x983 : 0x985 : 0x2716; + + AddButton(59 + width + f.Width, 117, ButtonID, ButtonID + (isComparer ? 1 : 0), 100 + i); + + width += f.Width + 12; + } + + if (m_StartNumber <= 0) + AddButton(65, 80, 0x15E3, 0x15E7, 0, GumpButtonType.Page); + else + AddButton(65, 80, 0x15E3, 0x15E7, 6); // Back + + if (m_StartNumber + itemsPerPage > m_List.Count) + AddButton(95, 80, 0x15E1, 0x15E5, 0, GumpButtonType.Page); + else + AddButton(95, 80, 0x15E1, 0x15E5, 7); // Forward + + var itemNumber = 0; + + if (m_Ascending) + for (var i = m_StartNumber; i < m_StartNumber + itemsPerPage && i < m_List.Count; i++) + DrawEntry(m_List[i], i, itemNumber++); + else // descending, go from bottom of list to the top + for (var i = m_List.Count - 1 - m_StartNumber; + i >= 0 && i >= m_List.Count - itemsPerPage - m_StartNumber; + i--) + DrawEntry(m_List[i], i, itemNumber++); + + DrawEndingEntry(itemNumber); + } + + public virtual void DrawEndingEntry(int itemNumber) + { + } + + public virtual bool HasRelationship(T o) => false; + + public virtual void DrawEntry(T o, int index, int itemNumber) + { + var width = 0; + for (var j = 0; j < m_Fields.Length; j++) + { + var f = m_Fields[j]; + + AddImageTiled(65 + width, 138 + itemNumber * 28, f.Width + 10, 26, 0xA40); + AddImageTiled(67 + width, 140 + itemNumber * 28, f.Width + 6, 22, 0xBBC); + AddHtmlText( + 70 + width, + 141 + itemNumber * 28, + f.Width, + 20, + GetValuesFor(o, m_Fields.Length)[j], + false, + false + ); + + width += f.Width + 12; + } + + if (HasRelationship(o)) + AddButton(40, 143 + itemNumber * 28, 0x8AF, 0x8AF, 200 + index); // Info Button + else + AddButton(40, 143 + itemNumber * 28, 0x4B9, 0x4BA, 200 + index); // Info Button + } + + protected abstract TextDefinition[] GetValuesFor(T o, int aryLength); + protected abstract bool IsFiltered(T o, string filter); + + public override void OnResponse(NetState sender, RelayInfo info) + { + base.OnResponse(sender, info); + + if (!(sender.Mobile is PlayerMobile pm) || !IsMember(pm, guild)) + return; + + var id = info.ButtonID; + + switch (id) + { + case 5: // Filter + { + var t = info.GetTextEntry(1); + pm.SendGump(GetResentGump(player, guild, m_Comparer, m_Ascending, t == null ? "" : t.Text, 0)); + break; + } + case 6: // Back + { + pm.SendGump( + GetResentGump(player, guild, m_Comparer, m_Ascending, m_Filter, m_StartNumber - itemsPerPage) + ); + break; + } + case 7: // Forward + { + pm.SendGump( + GetResentGump(player, guild, m_Comparer, m_Ascending, m_Filter, m_StartNumber + itemsPerPage) + ); + break; + } + } + + if (id >= 100 && id < 100 + m_Fields.Length) + { + var comparer = m_Fields[id - 100].Comparer; + + if (m_Comparer.GetType() == comparer.GetType()) + m_Ascending = !m_Ascending; + + pm.SendGump(GetResentGump(player, guild, comparer, m_Ascending, m_Filter, 0)); + } + else if (id >= 200 && id < 200 + m_List.Count) + { + pm.SendGump(GetObjectInfoGump(player, guild, m_List[id - 200])); + } + } + + public abstract Gump GetResentGump( + PlayerMobile pm, Guild g, IComparer comparer, bool ascending, string filter, + int startNumber + ); + + public abstract Gump GetObjectInfoGump(PlayerMobile pm, Guild g, T o); + + public void ResendGump() + { + player.SendGump(GetResentGump(player, guild, m_Comparer, m_Ascending, m_Filter, m_StartNumber)); + } + } + + public struct InfoField + { + public TextDefinition Name { get; } + + public int Width { get; } + + public IComparer Comparer { get; } + + public InfoField(TextDefinition name, int width, IComparer comparer) + { + Name = name; + Width = width; + Comparer = comparer; + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/New Guild System/Create Guild Gump.cs b/Projects/UOContent/Gumps/Guilds/New Guild System/Create Guild Gump.cs index 324a2455e..f6e4ae824 100644 --- a/Projects/UOContent/Gumps/Guilds/New Guild System/Create Guild Gump.cs +++ b/Projects/UOContent/Gumps/Guilds/New Guild System/Create Guild Gump.cs @@ -1,112 +1,127 @@ -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Guilds -{ - public class CreateGuildGump : Gump - { - public CreateGuildGump(PlayerMobile pm, string guildName = "Guild Name", string guildAbbrev = "") : base(10, 10) - { - pm.CloseGump(); - pm.CloseGump(); - - AddPage(0); - - AddBackground(0, 0, 500, 300, 0x2422); - AddHtmlLocalized(25, 20, 450, 25, 1062939, 0x0, true); //
GUILD MENU
- AddHtmlLocalized(25, 60, 450, 60, 1062940, 0x0); // As you are not a member of any guild, you can create your own by providing a unique guild name and paying the standard guild registration fee. - AddHtmlLocalized(25, 135, 120, 25, 1062941, 0x0); // Registration Fee: - AddLabel(155, 135, 0x481, Guild.RegistrationFee.ToString()); - AddHtmlLocalized(25, 165, 120, 25, 1011140, 0x0); // Enter Guild Name: - AddBackground(155, 160, 320, 26, 0xBB8); - AddTextEntry(160, 163, 315, 21, 0x481, 5, guildName); - AddHtmlLocalized(25, 191, 120, 26, 1063035, 0x0); // Abbreviation: - AddBackground(155, 186, 320, 26, 0xBB8); - AddTextEntry(160, 189, 315, 21, 0x481, 6, guildAbbrev); - AddButton(415, 217, 0xF7, 0xF8, 1); - AddButton(345, 217, 0xF2, 0xF1, 0); - - if (pm.AcceptGuildInvites) - AddButton(20, 260, 0xD2, 0xD3, 2); - else - AddButton(20, 260, 0xD3, 0xD2, 2); - - AddHtmlLocalized(45, 260, 200, 30, 1062943, 0x0); // Ignore Guild Invites - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (!(sender.Mobile is PlayerMobile pm) || pm.Guild != null) - return; // Sanity - - switch (info.ButtonID) - { - case 1: - { - TextRelay tName = info.GetTextEntry(5); - TextRelay tAbbrev = info.GetTextEntry(6); - - string guildName = tName == null ? "" : tName.Text; - string guildAbbrev = tAbbrev == null ? "" : tAbbrev.Text; - - guildName = Utility.FixHtml(guildName.Trim()); - guildAbbrev = Utility.FixHtml(guildAbbrev.Trim()); - - if (guildName.Length <= 0) - { - pm.SendLocalizedMessage(1070884); // Guild name cannot be blank. - } - else if (guildAbbrev.Length <= 0) - { - pm.SendLocalizedMessage(1070885); // You must provide a guild abbreviation. - } - else if (guildName.Length > Guild.NameLimit) - { - pm.SendLocalizedMessage(1063036, - Guild.NameLimit.ToString()); // A guild name cannot be more than ~1_val~ characters in length. - } - else if (guildAbbrev.Length > Guild.AbbrevLimit) - { - pm.SendLocalizedMessage(1063037, - Guild.AbbrevLimit.ToString()); // An abbreviation cannot exceed ~1_val~ characters in length. - } - else if (BaseGuild.FindByAbbrev(guildAbbrev) != null || !BaseGuildGump.CheckProfanity(guildAbbrev)) - { - pm.SendLocalizedMessage(501153); // That abbreviation is not available. - } - else if (BaseGuild.FindByName(guildName) != null || !BaseGuildGump.CheckProfanity(guildName)) - { - pm.SendLocalizedMessage(1063000); // That guild name is not available. - } - else if (!Banker.Withdraw(pm, Guild.RegistrationFee)) - { - pm.SendLocalizedMessage(1063001, - Guild.RegistrationFee - .ToString()); // You do not possess the ~1_val~ gold piece fee required to create a guild. - } - else - { - pm.SendLocalizedMessage(1060398, - Guild.RegistrationFee.ToString()); // ~1_AMOUNT~ gold has been withdrawn from your bank box. - pm.SendLocalizedMessage(1063238); // Your new guild has been founded. - pm.Guild = new Guild(pm, guildName, guildAbbrev); - } - - break; - } - case 2: - { - pm.AcceptGuildInvites = !pm.AcceptGuildInvites; - - if (pm.AcceptGuildInvites) - pm.SendLocalizedMessage(1070699); // You are now accepting guild invitations. - else - pm.SendLocalizedMessage(1070698); // You are now ignoring guild invitations. - - break; - } - } - } - } -} +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Guilds +{ + public class CreateGuildGump : Gump + { + public CreateGuildGump(PlayerMobile pm, string guildName = "Guild Name", string guildAbbrev = "") : base(10, 10) + { + pm.CloseGump(); + pm.CloseGump(); + + AddPage(0); + + AddBackground(0, 0, 500, 300, 0x2422); + AddHtmlLocalized(25, 20, 450, 25, 1062939, 0x0, true); //
GUILD MENU
+ AddHtmlLocalized( + 25, + 60, + 450, + 60, + 1062940, + 0x0 + ); // As you are not a member of any guild, you can create your own by providing a unique guild name and paying the standard guild registration fee. + AddHtmlLocalized(25, 135, 120, 25, 1062941, 0x0); // Registration Fee: + AddLabel(155, 135, 0x481, Guild.RegistrationFee.ToString()); + AddHtmlLocalized(25, 165, 120, 25, 1011140, 0x0); // Enter Guild Name: + AddBackground(155, 160, 320, 26, 0xBB8); + AddTextEntry(160, 163, 315, 21, 0x481, 5, guildName); + AddHtmlLocalized(25, 191, 120, 26, 1063035, 0x0); // Abbreviation: + AddBackground(155, 186, 320, 26, 0xBB8); + AddTextEntry(160, 189, 315, 21, 0x481, 6, guildAbbrev); + AddButton(415, 217, 0xF7, 0xF8, 1); + AddButton(345, 217, 0xF2, 0xF1, 0); + + if (pm.AcceptGuildInvites) + AddButton(20, 260, 0xD2, 0xD3, 2); + else + AddButton(20, 260, 0xD3, 0xD2, 2); + + AddHtmlLocalized(45, 260, 200, 30, 1062943, 0x0); // Ignore Guild Invites + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (!(sender.Mobile is PlayerMobile pm) || pm.Guild != null) + return; // Sanity + + switch (info.ButtonID) + { + case 1: + { + var tName = info.GetTextEntry(5); + var tAbbrev = info.GetTextEntry(6); + + var guildName = tName == null ? "" : tName.Text; + var guildAbbrev = tAbbrev == null ? "" : tAbbrev.Text; + + guildName = Utility.FixHtml(guildName.Trim()); + guildAbbrev = Utility.FixHtml(guildAbbrev.Trim()); + + if (guildName.Length <= 0) + { + pm.SendLocalizedMessage(1070884); // Guild name cannot be blank. + } + else if (guildAbbrev.Length <= 0) + { + pm.SendLocalizedMessage(1070885); // You must provide a guild abbreviation. + } + else if (guildName.Length > Guild.NameLimit) + { + pm.SendLocalizedMessage( + 1063036, + Guild.NameLimit.ToString() + ); // A guild name cannot be more than ~1_val~ characters in length. + } + else if (guildAbbrev.Length > Guild.AbbrevLimit) + { + pm.SendLocalizedMessage( + 1063037, + Guild.AbbrevLimit.ToString() + ); // An abbreviation cannot exceed ~1_val~ characters in length. + } + else if (BaseGuild.FindByAbbrev(guildAbbrev) != null || !BaseGuildGump.CheckProfanity(guildAbbrev)) + { + pm.SendLocalizedMessage(501153); // That abbreviation is not available. + } + else if (BaseGuild.FindByName(guildName) != null || !BaseGuildGump.CheckProfanity(guildName)) + { + pm.SendLocalizedMessage(1063000); // That guild name is not available. + } + else if (!Banker.Withdraw(pm, Guild.RegistrationFee)) + { + pm.SendLocalizedMessage( + 1063001, + Guild.RegistrationFee + .ToString() + ); // You do not possess the ~1_val~ gold piece fee required to create a guild. + } + else + { + pm.SendLocalizedMessage( + 1060398, + Guild.RegistrationFee.ToString() + ); // ~1_AMOUNT~ gold has been withdrawn from your bank box. + pm.SendLocalizedMessage(1063238); // Your new guild has been founded. + pm.Guild = new Guild(pm, guildName, guildAbbrev); + } + + break; + } + case 2: + { + pm.AcceptGuildInvites = !pm.AcceptGuildInvites; + + if (pm.AcceptGuildInvites) + pm.SendLocalizedMessage(1070699); // You are now accepting guild invitations. + else + pm.SendLocalizedMessage(1070698); // You are now ignoring guild invitations. + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/New Guild System/DiplomacyGump.cs b/Projects/UOContent/Gumps/Guilds/New Guild System/DiplomacyGump.cs index 9d7ef253d..7533ed709 100644 --- a/Projects/UOContent/Gumps/Guilds/New Guild System/DiplomacyGump.cs +++ b/Projects/UOContent/Gumps/Guilds/New Guild System/DiplomacyGump.cs @@ -1,279 +1,314 @@ -using System.Collections.Generic; -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Guilds -{ - public enum GuildDisplayType - { - All, - AwaitingAction, - Relations - } - - public class GuildDiplomacyGump : BaseGuildListGump - { - private GuildDisplayType m_Display; - private readonly TextDefinition m_LowerText; - - public GuildDiplomacyGump(PlayerMobile pm, Guild g) - : this(pm, g, NameComparer.Instance, true, "", 0, GuildDisplayType.All, - Utility.CastListCovariant(new List(BaseGuild.List.Values)), - 1063136 + (int)GuildDisplayType.All) - { - } - - public GuildDiplomacyGump(PlayerMobile pm, Guild g, IComparer currentComparer, bool ascending, string filter, - int startNumber, GuildDisplayType display) - : this(pm, g, currentComparer, ascending, filter, startNumber, display, - Utility.CastListCovariant(new List(BaseGuild.List.Values)), - 1063136 + (int)display) - { - } - - public GuildDiplomacyGump(PlayerMobile pm, Guild g, IComparer currentComparer, bool ascending, string filter, - int startNumber, List list, TextDefinition lowerText) - : this(pm, g, currentComparer, ascending, filter, startNumber, GuildDisplayType.All, list, lowerText) - { - } - - public GuildDiplomacyGump(PlayerMobile pm, Guild g, bool ascending, string filter, int startNumber, List list, - TextDefinition lowerText) - : this(pm, g, NameComparer.Instance, ascending, filter, startNumber, GuildDisplayType.All, list, lowerText) - { - } - - public GuildDiplomacyGump(PlayerMobile pm, Guild g, IComparer currentComparer, bool ascending, string filter, - int startNumber, GuildDisplayType display, List list, TextDefinition lowerText) - : base(pm, g, list, currentComparer, ascending, filter, startNumber, - new[] - { - new InfoField(1062954, 280, NameComparer.Instance), // Guild Name - new InfoField(1062957, 50, AbbrevComparer.Instance), // Abbrev - new InfoField(1062958, 120, new StatusComparer(g)) // Guild Title - }) - { - m_Display = display; - m_LowerText = lowerText; - PopulateGump(); - } - - protected virtual bool AllowAdvancedSearch => true; - - public override bool WillFilter - { - get - { - if (m_Display == GuildDisplayType.All) - return base.WillFilter; - - return true; - } - } - - public override void PopulateGump() - { - base.PopulateGump(); - - AddHtmlLocalized(431, 43, 110, 26, 1062978, 0xF); // Diplomacy - } - - protected override TextDefinition[] GetValuesFor(Guild g, int aryLength) - { - TextDefinition[] defs = new TextDefinition[aryLength]; - - defs[0] = g == guild ? Color(g.Name, 0x006600) : g.Name; - defs[1] = g.Abbreviation; - - defs[2] = 3000085; // Peace - - if (guild.IsAlly(g)) - { - if (guild.Alliance.Leader == g) - defs[2] = 1063237; // Alliance Leader - else - defs[2] = 1062964; // Ally - } - else if (guild.IsWar(g)) - { - defs[2] = 3000086; // War - } - - return defs; - } - - public override bool HasRelationship(Guild g) - { - if (g == guild) - return false; - - if (guild.FindPendingWar(g) != null) - return true; - - AllianceInfo alliance = guild.Alliance; - - if (alliance != null) - { - Guild leader = alliance.Leader; - - if (leader != null) - { - if ((guild == leader && alliance.IsPendingMember(g)) || (g == leader && alliance.IsPendingMember(guild))) - return true; - } - else if (alliance.IsPendingMember(g)) - { - return true; - } - } - - return false; - } - - public override void DrawEndingEntry(int itemNumber) - { - // AddHtmlLocalized( 66, 153 + itemNumber * 28, 280, 26, 1063136 + (int)m_Display, 0xF, false, false ); // Showing All Guilds/Awaiting Action/ w/Relation Ship - // AddHtmlText( 66, 153 + itemNumber * 28, 280, 26, m_LowerText, false, false ); - - if (m_LowerText?.Number > 0) - AddHtmlLocalized(66, 153 + itemNumber * 28, 280, 26, m_LowerText.Number, 0xF); - else if (m_LowerText?.String != null) - AddHtml(66, 153 + itemNumber * 28, 280, 26, Color(m_LowerText.String, 0x99)); - - if (AllowAdvancedSearch) - { - AddBackground(350, 148 + itemNumber * 28, 200, 26, 0x2486); - AddButton(355, 153 + itemNumber * 28, 0x845, 0x846, 8); - AddHtmlLocalized(380, 151 + itemNumber * 28, 160, 26, 1063083, 0x0); // Advanced Search - } - } - - protected override bool IsFiltered(Guild g, string filter) - { - if (g == null) - return true; - - switch (m_Display) - { - case GuildDisplayType.Relations: - { - // if (!( guild.IsWar( g ) || guild.IsAlly( g ) )) - - if (!(guild.FindActiveWar(g) != null || guild.IsAlly(g))) // As per OSI, only the guild leader wars show up under the sorting by relation - return true; - - return false; - } - case GuildDisplayType.AwaitingAction: - { - return !HasRelationship(g); - } - } - - return !(Insensitive.Contains(g.Name, filter) || Insensitive.Contains(g.Abbreviation, filter)); - } - - public override Gump GetResentGump(PlayerMobile pm, Guild g, IComparer comparer, bool ascending, - string filter, int startNumber) => - new GuildDiplomacyGump(pm, g, comparer, ascending, filter, startNumber, m_Display); - - public override Gump GetObjectInfoGump(PlayerMobile pm, Guild g, Guild o) - { - if (guild == o) - return new GuildInfoGump(pm, g); - - return new OtherGuildInfo(pm, g, o); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - base.OnResponse(sender, info); - - if (!(sender.Mobile is PlayerMobile pm) || !IsMember(pm, guild)) - return; - - if (AllowAdvancedSearch && info.ButtonID == 8) - pm.SendGump(new GuildAdvancedSearchGump(pm, guild, m_Display, AdvancedSearch_Callback)); - } - - public void AdvancedSearch_Callback(GuildDisplayType display) - { - m_Display = display; - ResendGump(); - } - - private class NameComparer : IComparer - { - public static readonly IComparer Instance = new NameComparer(); - - public int Compare(Guild x, Guild y) - { - if (x == null && y == null) - return 0; - if (x == null) - return -1; - if (y == null) - return 1; - - return Insensitive.Compare(x.Name, y.Name); - } - } - - private class StatusComparer : IComparer - { - private readonly Guild m_Guild; - - public StatusComparer(Guild g) => m_Guild = g; - - public int Compare(Guild x, Guild y) - { - if (x == null && y == null) - return 0; - if (x == null) - return -1; - if (y == null) - return 1; - - GuildCompareStatus aStatus = GuildCompareStatus.Peace; - GuildCompareStatus bStatus = GuildCompareStatus.Peace; - - if (m_Guild.IsAlly(x)) - aStatus = GuildCompareStatus.Ally; - else if (m_Guild.IsWar(x)) - aStatus = GuildCompareStatus.War; - - if (m_Guild.IsAlly(y)) - bStatus = GuildCompareStatus.Ally; - else if (m_Guild.IsWar(y)) - bStatus = GuildCompareStatus.War; - - return ((int)aStatus).CompareTo((int)bStatus); - } - - private enum GuildCompareStatus - { - Peace, - Ally, - War - } - } - - private class AbbrevComparer : IComparer - { - public static readonly IComparer Instance = new AbbrevComparer(); - - public int Compare(Guild x, Guild y) - { - if (x == null && y == null) - return 0; - if (x == null) - return -1; - if (y == null) - return 1; - - return Insensitive.Compare(x.Abbreviation, y.Abbreviation); - } - } - } -} +using System.Collections.Generic; +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Guilds +{ + public enum GuildDisplayType + { + All, + AwaitingAction, + Relations + } + + public class GuildDiplomacyGump : BaseGuildListGump + { + private readonly TextDefinition m_LowerText; + private GuildDisplayType m_Display; + + public GuildDiplomacyGump(PlayerMobile pm, Guild g) + : this( + pm, + g, + NameComparer.Instance, + true, + "", + 0, + GuildDisplayType.All, + Utility.CastListCovariant(new List(BaseGuild.List.Values)), + 1063136 + (int)GuildDisplayType.All + ) + { + } + + public GuildDiplomacyGump( + PlayerMobile pm, Guild g, IComparer currentComparer, bool ascending, string filter, + int startNumber, GuildDisplayType display + ) + : this( + pm, + g, + currentComparer, + ascending, + filter, + startNumber, + display, + Utility.CastListCovariant(new List(BaseGuild.List.Values)), + 1063136 + (int)display + ) + { + } + + public GuildDiplomacyGump( + PlayerMobile pm, Guild g, IComparer currentComparer, bool ascending, string filter, + int startNumber, List list, TextDefinition lowerText + ) + : this(pm, g, currentComparer, ascending, filter, startNumber, GuildDisplayType.All, list, lowerText) + { + } + + public GuildDiplomacyGump( + PlayerMobile pm, Guild g, bool ascending, string filter, int startNumber, List list, + TextDefinition lowerText + ) + : this(pm, g, NameComparer.Instance, ascending, filter, startNumber, GuildDisplayType.All, list, lowerText) + { + } + + public GuildDiplomacyGump( + PlayerMobile pm, Guild g, IComparer currentComparer, bool ascending, string filter, + int startNumber, GuildDisplayType display, List list, TextDefinition lowerText + ) + : base( + pm, + g, + list, + currentComparer, + ascending, + filter, + startNumber, + new[] + { + new InfoField(1062954, 280, NameComparer.Instance), // Guild Name + new InfoField(1062957, 50, AbbrevComparer.Instance), // Abbrev + new InfoField(1062958, 120, new StatusComparer(g)) // Guild Title + } + ) + { + m_Display = display; + m_LowerText = lowerText; + PopulateGump(); + } + + protected virtual bool AllowAdvancedSearch => true; + + public override bool WillFilter + { + get + { + if (m_Display == GuildDisplayType.All) + return base.WillFilter; + + return true; + } + } + + public override void PopulateGump() + { + base.PopulateGump(); + + AddHtmlLocalized(431, 43, 110, 26, 1062978, 0xF); // Diplomacy + } + + protected override TextDefinition[] GetValuesFor(Guild g, int aryLength) + { + var defs = new TextDefinition[aryLength]; + + defs[0] = g == guild ? Color(g.Name, 0x006600) : g.Name; + defs[1] = g.Abbreviation; + + defs[2] = 3000085; // Peace + + if (guild.IsAlly(g)) + { + if (guild.Alliance.Leader == g) + defs[2] = 1063237; // Alliance Leader + else + defs[2] = 1062964; // Ally + } + else if (guild.IsWar(g)) + { + defs[2] = 3000086; // War + } + + return defs; + } + + public override bool HasRelationship(Guild g) + { + if (g == guild) + return false; + + if (guild.FindPendingWar(g) != null) + return true; + + var alliance = guild.Alliance; + + if (alliance != null) + { + var leader = alliance.Leader; + + if (leader != null) + { + if (guild == leader && alliance.IsPendingMember(g) || g == leader && alliance.IsPendingMember(guild)) + return true; + } + else if (alliance.IsPendingMember(g)) + { + return true; + } + } + + return false; + } + + public override void DrawEndingEntry(int itemNumber) + { + // AddHtmlLocalized( 66, 153 + itemNumber * 28, 280, 26, 1063136 + (int)m_Display, 0xF, false, false ); // Showing All Guilds/Awaiting Action/ w/Relation Ship + // AddHtmlText( 66, 153 + itemNumber * 28, 280, 26, m_LowerText, false, false ); + + if (m_LowerText?.Number > 0) + AddHtmlLocalized(66, 153 + itemNumber * 28, 280, 26, m_LowerText.Number, 0xF); + else if (m_LowerText?.String != null) + AddHtml(66, 153 + itemNumber * 28, 280, 26, Color(m_LowerText.String, 0x99)); + + if (AllowAdvancedSearch) + { + AddBackground(350, 148 + itemNumber * 28, 200, 26, 0x2486); + AddButton(355, 153 + itemNumber * 28, 0x845, 0x846, 8); + AddHtmlLocalized(380, 151 + itemNumber * 28, 160, 26, 1063083, 0x0); // Advanced Search + } + } + + protected override bool IsFiltered(Guild g, string filter) + { + if (g == null) + return true; + + switch (m_Display) + { + case GuildDisplayType.Relations: + { + // if (!( guild.IsWar( g ) || guild.IsAlly( g ) )) + + if (!(guild.FindActiveWar(g) != null || guild.IsAlly(g)) + ) // As per OSI, only the guild leader wars show up under the sorting by relation + return true; + + return false; + } + case GuildDisplayType.AwaitingAction: + { + return !HasRelationship(g); + } + } + + return !(Insensitive.Contains(g.Name, filter) || Insensitive.Contains(g.Abbreviation, filter)); + } + + public override Gump GetResentGump( + PlayerMobile pm, Guild g, IComparer comparer, bool ascending, + string filter, int startNumber + ) => + new GuildDiplomacyGump(pm, g, comparer, ascending, filter, startNumber, m_Display); + + public override Gump GetObjectInfoGump(PlayerMobile pm, Guild g, Guild o) + { + if (guild == o) + return new GuildInfoGump(pm, g); + + return new OtherGuildInfo(pm, g, o); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + base.OnResponse(sender, info); + + if (!(sender.Mobile is PlayerMobile pm) || !IsMember(pm, guild)) + return; + + if (AllowAdvancedSearch && info.ButtonID == 8) + pm.SendGump(new GuildAdvancedSearchGump(pm, guild, m_Display, AdvancedSearch_Callback)); + } + + public void AdvancedSearch_Callback(GuildDisplayType display) + { + m_Display = display; + ResendGump(); + } + + private class NameComparer : IComparer + { + public static readonly IComparer Instance = new NameComparer(); + + public int Compare(Guild x, Guild y) + { + if (x == null && y == null) + return 0; + if (x == null) + return -1; + if (y == null) + return 1; + + return Insensitive.Compare(x.Name, y.Name); + } + } + + private class StatusComparer : IComparer + { + private readonly Guild m_Guild; + + public StatusComparer(Guild g) => m_Guild = g; + + public int Compare(Guild x, Guild y) + { + if (x == null && y == null) + return 0; + if (x == null) + return -1; + if (y == null) + return 1; + + var aStatus = GuildCompareStatus.Peace; + var bStatus = GuildCompareStatus.Peace; + + if (m_Guild.IsAlly(x)) + aStatus = GuildCompareStatus.Ally; + else if (m_Guild.IsWar(x)) + aStatus = GuildCompareStatus.War; + + if (m_Guild.IsAlly(y)) + bStatus = GuildCompareStatus.Ally; + else if (m_Guild.IsWar(y)) + bStatus = GuildCompareStatus.War; + + return ((int)aStatus).CompareTo((int)bStatus); + } + + private enum GuildCompareStatus + { + Peace, + Ally, + War + } + } + + private class AbbrevComparer : IComparer + { + public static readonly IComparer Instance = new AbbrevComparer(); + + public int Compare(Guild x, Guild y) + { + if (x == null && y == null) + return 0; + if (x == null) + return -1; + if (y == null) + return 1; + + return Insensitive.Compare(x.Abbreviation, y.Abbreviation); + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/New Guild System/GuildInfoGump.cs b/Projects/UOContent/Gumps/Guilds/New Guild System/GuildInfoGump.cs index ef3e9690d..4efc64551 100644 --- a/Projects/UOContent/Gumps/Guilds/New Guild System/GuildInfoGump.cs +++ b/Projects/UOContent/Gumps/Guilds/New Guild System/GuildInfoGump.cs @@ -1,187 +1,191 @@ -using Server.Factions; -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Guilds -{ - public class GuildInfoGump : BaseGuildGump - { - private readonly bool m_IsResigning; - - public GuildInfoGump(PlayerMobile pm, Guild g, bool isResigning = false) : base(pm, g) - { - m_IsResigning = isResigning; - PopulateGump(); - } - - public override void PopulateGump() - { - bool isLeader = IsLeader(player, guild); - base.PopulateGump(); - - AddHtmlLocalized(96, 43, 110, 26, 1063014, 0xF); // My Guild - - AddImageTiled(65, 80, 160, 26, 0xA40); - AddImageTiled(67, 82, 156, 22, 0xBBC); - AddHtmlLocalized(70, 83, 150, 20, 1062954, 0x0); // Guild Name - AddHtml(233, 84, 320, 26, guild.Name); - - AddImageTiled(65, 114, 160, 26, 0xA40); - AddImageTiled(67, 116, 156, 22, 0xBBC); - AddHtmlLocalized(70, 117, 150, 20, 1063025, 0x0); // Alliance - - if (guild.Alliance?.IsMember(guild) == true) - { - AddHtml(233, 118, 320, 26, guild.Alliance.Name); - AddButton(40, 120, 0x4B9, 0x4BA, 6); // Alliance Roster - } - - if (Guild.OrderChaos && isLeader) - AddButton(40, 154, 0x4B9, 0x4BA, 100); // Guild Faction - - AddImageTiled(65, 148, 160, 26, 0xA40); - AddImageTiled(67, 150, 156, 22, 0xBBC); - AddHtmlLocalized(70, 151, 150, 20, 1063084, 0x0); // Guild Faction - - GuildType gt; - Faction f; - - if ((gt = guild.Type) != GuildType.Regular) - AddHtml(233, 152, 320, 26, gt.ToString()); - else if ((f = Faction.Find(guild.Leader)) != null) - AddHtml(233, 152, 320, 26, f.ToString()); - - AddImageTiled(65, 196, 480, 4, 0x238D); - - string s = guild.Charter.IsNullOrDefault("The guild leader has not yet set the guild charter."); - - AddHtml(65, 216, 480, 80, s, true, true); - if (isLeader) - AddButton(40, 251, 0x4B9, 0x4BA, 4); // Charter Edit button - - s = guild.Website.IsNullOrDefault("Guild website not yet set."); - - AddHtml(65, 306, 480, 30, s, true); - if (isLeader) - AddButton(40, 313, 0x4B9, 0x4BA, 5); // Website Edit button - - AddCheck(65, 370, 0xD2, 0xD3, player.DisplayGuildTitle, 0); - AddHtmlLocalized(95, 370, 150, 26, 1063085, 0x0); // Show Guild Title - AddBackground(450, 370, 100, 26, 0x2486); - - AddButton(455, 375, 0x845, 0x846, 7); - AddHtmlLocalized(480, 373, 60, 26, 3006115, m_IsResigning ? 0x5000 : 0); // Resign - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - base.OnResponse(sender, info); - - PlayerMobile pm = (PlayerMobile)sender.Mobile; - - if (!IsMember(pm, guild)) - return; - - pm.DisplayGuildTitle = info.IsSwitched(0); - - switch (info.ButtonID) - { - // 1-3 handled by base.OnResponse - case 4: - { - if (IsLeader(pm, guild)) - { - pm.SendLocalizedMessage(1013071); // Enter the new guild charter (50 characters max): - - pm.BeginPrompt(SetCharter_Callback, - true); // Have the same callback handle both canceling and deletion cause the 2nd callback would just get a text of "" - } - - break; - } - case 5: - { - if (IsLeader(pm, guild)) - { - pm.SendLocalizedMessage(1013072); // Enter the new website for the guild (50 characters max): - pm.BeginPrompt(SetWebsite_Callback, - true); // Have the same callback handle both canceling and deletion cause the 2nd callback would just get a text of "" - } - - break; - } - case 6: - { - // Alliance Roster - if (guild.Alliance?.IsMember(guild) == true) - pm.SendGump(new AllianceInfo.AllianceRosterGump(pm, guild, guild.Alliance)); - - break; - } - case 7: - { - // Resign - if (!m_IsResigning) - { - pm.SendLocalizedMessage(1063332); // Are you sure you wish to resign from your guild? - pm.SendGump(new GuildInfoGump(pm, guild, true)); - } - else - { - guild.RemoveMember(pm, 1063411); // You resign from your guild. - } - - break; - } - case 100: // Custom code to support Order/Chaos in the new guild system - { - // Guild Faction - if (Guild.OrderChaos && IsLeader(pm, guild)) - { - pm.CloseGump(); - pm.SendGump(new GuildChangeTypeGump(pm, guild)); - } - - break; - } - } - } - - public void SetCharter_Callback(Mobile from, string text) - { - if (!IsLeader(from, guild)) - return; - - string charter = Utility.FixHtml(text.Trim()); - - if (charter.Length > 50) - { - from.SendLocalizedMessage(1070774, "50"); // Your guild charter cannot exceed ~1_val~ characters. - } - else - { - guild.Charter = charter; - from.SendLocalizedMessage(1070775); // You submit a new guild charter. - } - } - - public void SetWebsite_Callback(Mobile from, string text) - { - if (!IsLeader(from, guild)) - return; - - string site = Utility.FixHtml(text.Trim()); - - if (site.Length > 50) - { - from.SendLocalizedMessage(1070777, "50"); // Your guild website cannot exceed ~1_val~ characters. - } - else - { - guild.Website = site; - from.SendLocalizedMessage(1070778); // You submit a new guild website. - } - } - } -} +using Server.Factions; +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Guilds +{ + public class GuildInfoGump : BaseGuildGump + { + private readonly bool m_IsResigning; + + public GuildInfoGump(PlayerMobile pm, Guild g, bool isResigning = false) : base(pm, g) + { + m_IsResigning = isResigning; + PopulateGump(); + } + + public override void PopulateGump() + { + var isLeader = IsLeader(player, guild); + base.PopulateGump(); + + AddHtmlLocalized(96, 43, 110, 26, 1063014, 0xF); // My Guild + + AddImageTiled(65, 80, 160, 26, 0xA40); + AddImageTiled(67, 82, 156, 22, 0xBBC); + AddHtmlLocalized(70, 83, 150, 20, 1062954, 0x0); // Guild Name + AddHtml(233, 84, 320, 26, guild.Name); + + AddImageTiled(65, 114, 160, 26, 0xA40); + AddImageTiled(67, 116, 156, 22, 0xBBC); + AddHtmlLocalized(70, 117, 150, 20, 1063025, 0x0); // Alliance + + if (guild.Alliance?.IsMember(guild) == true) + { + AddHtml(233, 118, 320, 26, guild.Alliance.Name); + AddButton(40, 120, 0x4B9, 0x4BA, 6); // Alliance Roster + } + + if (Guild.OrderChaos && isLeader) + AddButton(40, 154, 0x4B9, 0x4BA, 100); // Guild Faction + + AddImageTiled(65, 148, 160, 26, 0xA40); + AddImageTiled(67, 150, 156, 22, 0xBBC); + AddHtmlLocalized(70, 151, 150, 20, 1063084, 0x0); // Guild Faction + + GuildType gt; + Faction f; + + if ((gt = guild.Type) != GuildType.Regular) + AddHtml(233, 152, 320, 26, gt.ToString()); + else if ((f = Faction.Find(guild.Leader)) != null) + AddHtml(233, 152, 320, 26, f.ToString()); + + AddImageTiled(65, 196, 480, 4, 0x238D); + + var s = guild.Charter.IsNullOrDefault("The guild leader has not yet set the guild charter."); + + AddHtml(65, 216, 480, 80, s, true, true); + if (isLeader) + AddButton(40, 251, 0x4B9, 0x4BA, 4); // Charter Edit button + + s = guild.Website.IsNullOrDefault("Guild website not yet set."); + + AddHtml(65, 306, 480, 30, s, true); + if (isLeader) + AddButton(40, 313, 0x4B9, 0x4BA, 5); // Website Edit button + + AddCheck(65, 370, 0xD2, 0xD3, player.DisplayGuildTitle, 0); + AddHtmlLocalized(95, 370, 150, 26, 1063085, 0x0); // Show Guild Title + AddBackground(450, 370, 100, 26, 0x2486); + + AddButton(455, 375, 0x845, 0x846, 7); + AddHtmlLocalized(480, 373, 60, 26, 3006115, m_IsResigning ? 0x5000 : 0); // Resign + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + base.OnResponse(sender, info); + + var pm = (PlayerMobile)sender.Mobile; + + if (!IsMember(pm, guild)) + return; + + pm.DisplayGuildTitle = info.IsSwitched(0); + + switch (info.ButtonID) + { + // 1-3 handled by base.OnResponse + case 4: + { + if (IsLeader(pm, guild)) + { + pm.SendLocalizedMessage(1013071); // Enter the new guild charter (50 characters max): + + pm.BeginPrompt( + SetCharter_Callback, + true + ); // Have the same callback handle both canceling and deletion cause the 2nd callback would just get a text of "" + } + + break; + } + case 5: + { + if (IsLeader(pm, guild)) + { + pm.SendLocalizedMessage(1013072); // Enter the new website for the guild (50 characters max): + pm.BeginPrompt( + SetWebsite_Callback, + true + ); // Have the same callback handle both canceling and deletion cause the 2nd callback would just get a text of "" + } + + break; + } + case 6: + { + // Alliance Roster + if (guild.Alliance?.IsMember(guild) == true) + pm.SendGump(new AllianceInfo.AllianceRosterGump(pm, guild, guild.Alliance)); + + break; + } + case 7: + { + // Resign + if (!m_IsResigning) + { + pm.SendLocalizedMessage(1063332); // Are you sure you wish to resign from your guild? + pm.SendGump(new GuildInfoGump(pm, guild, true)); + } + else + { + guild.RemoveMember(pm, 1063411); // You resign from your guild. + } + + break; + } + case 100: // Custom code to support Order/Chaos in the new guild system + { + // Guild Faction + if (Guild.OrderChaos && IsLeader(pm, guild)) + { + pm.CloseGump(); + pm.SendGump(new GuildChangeTypeGump(pm, guild)); + } + + break; + } + } + } + + public void SetCharter_Callback(Mobile from, string text) + { + if (!IsLeader(from, guild)) + return; + + var charter = Utility.FixHtml(text.Trim()); + + if (charter.Length > 50) + { + from.SendLocalizedMessage(1070774, "50"); // Your guild charter cannot exceed ~1_val~ characters. + } + else + { + guild.Charter = charter; + from.SendLocalizedMessage(1070775); // You submit a new guild charter. + } + } + + public void SetWebsite_Callback(Mobile from, string text) + { + if (!IsLeader(from, guild)) + return; + + var site = Utility.FixHtml(text.Trim()); + + if (site.Length > 50) + { + from.SendLocalizedMessage(1070777, "50"); // Your guild website cannot exceed ~1_val~ characters. + } + else + { + guild.Website = site; + from.SendLocalizedMessage(1070778); // You submit a new guild website. + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/New Guild System/GuildInvitationRequest.cs b/Projects/UOContent/Gumps/Guilds/New Guild System/GuildInvitationRequest.cs index 76aecc4e4..bb7aecc4b 100644 --- a/Projects/UOContent/Gumps/Guilds/New Guild System/GuildInvitationRequest.cs +++ b/Projects/UOContent/Gumps/Guilds/New Guild System/GuildInvitationRequest.cs @@ -1,63 +1,75 @@ -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Guilds -{ - public class GuildInvitationRequest : BaseGuildGump - { - private readonly PlayerMobile m_Inviter; - - public GuildInvitationRequest(PlayerMobile pm, Guild g, PlayerMobile inviter) : base(pm, g) - { - m_Inviter = inviter; - - PopulateGump(); - } - - public override void PopulateGump() - { - AddPage(0); - - AddBackground(0, 0, 350, 170, 0x2422); - AddHtmlLocalized(25, 20, 300, 45, 1062946, 0x0, true); //
You have been invited to join a guild! (Warning: Accepting will make you attackable!)
- AddHtml(25, 75, 300, 25, $"
{guild.Name}
", true); - AddButton(265, 130, 0xF7, 0xF8, 1); - AddButton(195, 130, 0xF2, 0xF1, 0); - AddButton(20, 130, 0xD2, 0xD3, 2); - AddHtmlLocalized(45, 130, 150, 30, 1062943, 0x0); // Ignore Guild Invites - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (guild.Disbanded || player.Guild != null) - return; - - switch (info.ButtonID) - { - case 0: - { - m_Inviter.SendLocalizedMessage(1063250, - $"{player.Name}\t{guild.Name}"); // ~1_val~ has declined your invitation to join ~2_val~. - break; - } - case 1: - { - guild.AddMember(player); - player.SendLocalizedMessage(1063056, guild.Name); // You have joined ~1_val~. - m_Inviter.SendLocalizedMessage(1063249, - $"{player.Name}\t{guild.Name}"); // ~1_val~ has accepted your invitation to join ~2_val~. - - break; - } - case 2: - { - player.AcceptGuildInvites = false; - player.SendLocalizedMessage(1070698); // You are now ignoring guild invitations. - - break; - } - } - } - } -} +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Guilds +{ + public class GuildInvitationRequest : BaseGuildGump + { + private readonly PlayerMobile m_Inviter; + + public GuildInvitationRequest(PlayerMobile pm, Guild g, PlayerMobile inviter) : base(pm, g) + { + m_Inviter = inviter; + + PopulateGump(); + } + + public override void PopulateGump() + { + AddPage(0); + + AddBackground(0, 0, 350, 170, 0x2422); + AddHtmlLocalized( + 25, + 20, + 300, + 45, + 1062946, + 0x0, + true + ); //
You have been invited to join a guild! (Warning: Accepting will make you attackable!)
+ AddHtml(25, 75, 300, 25, $"
{guild.Name}
", true); + AddButton(265, 130, 0xF7, 0xF8, 1); + AddButton(195, 130, 0xF2, 0xF1, 0); + AddButton(20, 130, 0xD2, 0xD3, 2); + AddHtmlLocalized(45, 130, 150, 30, 1062943, 0x0); // Ignore Guild Invites + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (guild.Disbanded || player.Guild != null) + return; + + switch (info.ButtonID) + { + case 0: + { + m_Inviter.SendLocalizedMessage( + 1063250, + $"{player.Name}\t{guild.Name}" + ); // ~1_val~ has declined your invitation to join ~2_val~. + break; + } + case 1: + { + guild.AddMember(player); + player.SendLocalizedMessage(1063056, guild.Name); // You have joined ~1_val~. + m_Inviter.SendLocalizedMessage( + 1063249, + $"{player.Name}\t{guild.Name}" + ); // ~1_val~ has accepted your invitation to join ~2_val~. + + break; + } + case 2: + { + player.AcceptGuildInvites = false; + player.SendLocalizedMessage(1070698); // You are now ignoring guild invitations. + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/New Guild System/GuildMemberInfoGump.cs b/Projects/UOContent/Gumps/Guilds/New Guild System/GuildMemberInfoGump.cs index 84b7ce1e0..abb38fb95 100644 --- a/Projects/UOContent/Gumps/Guilds/New Guild System/GuildMemberInfoGump.cs +++ b/Projects/UOContent/Gumps/Guilds/New Guild System/GuildMemberInfoGump.cs @@ -1,251 +1,277 @@ -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Guilds -{ - public class GuildMemberInfoGump : BaseGuildGump - { - private readonly PlayerMobile m_Member; - private readonly bool m_ToLeader; - private readonly bool m_toKick; - - public GuildMemberInfoGump(PlayerMobile pm, Guild g, PlayerMobile member, bool toKick, bool toPromoteToLeader) : base(pm, g, 10, 40) - { - m_ToLeader = toPromoteToLeader; - m_toKick = toKick; - m_Member = member; - PopulateGump(); - } - - public override void PopulateGump() - { - AddPage(0); - - AddBackground(0, 0, 350, 255, 0x242C); - AddHtmlLocalized(20, 15, 310, 26, 1063018, 0x0); //
Guild Member Information
- AddImageTiled(20, 40, 310, 2, 0x2711); - - AddHtmlLocalized(20, 50, 150, 26, 1062955, 0x0, true); // Name - AddHtml(180, 53, 150, 26, m_Member.Name); - - AddHtmlLocalized(20, 80, 150, 26, 1062956, 0x0, true); // Rank - AddHtmlLocalized(180, 83, 150, 26, m_Member.GuildRank.Name, 0x0); - - AddHtmlLocalized(20, 110, 150, 26, 1062953, 0x0, true); // Guild Title - AddHtml(180, 113, 150, 26, m_Member.GuildTitle); - AddImageTiled(20, 142, 310, 2, 0x2711); - - AddBackground(20, 150, 310, 26, 0x2486); - AddButton(25, 155, 0x845, 0x846, 4); - AddHtmlLocalized(50, 153, 270, 26, - m_Member == player.GuildFealty && guild.Leader != m_Member ? 1063082 : 1062996, 0x0); // Clear/Cast Vote For This Member - - AddBackground(20, 180, 150, 26, 0x2486); - AddButton(25, 185, 0x845, 0x846, 1); - AddHtmlLocalized(50, 183, 110, 26, 1062993, m_ToLeader ? 0x990000 : 0); // Promote - - AddBackground(180, 180, 150, 26, 0x2486); - AddButton(185, 185, 0x845, 0x846, 3); - AddHtmlLocalized(210, 183, 110, 26, 1062995, 0x0); // Set Guild Title - - AddBackground(20, 210, 150, 26, 0x2486); - AddButton(25, 215, 0x845, 0x846, 2); - AddHtmlLocalized(50, 213, 110, 26, 1062994, 0x0); // Demote - - AddBackground(180, 210, 150, 26, 0x2486); - AddButton(185, 215, 0x845, 0x846, 5); - AddHtmlLocalized(210, 213, 110, 26, 1062997, m_toKick ? 0x5000 : 0); // Kick - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (!(sender.Mobile is PlayerMobile pm) || !IsMember(pm, guild) || !IsMember(m_Member, guild)) - return; - - RankDefinition playerRank = pm.GuildRank; - RankDefinition targetRank = m_Member.GuildRank; - - switch (info.ButtonID) - { - case 1: // Promote - { - if (playerRank.GetFlag(RankFlags.CanPromoteDemote) && - (playerRank.Rank - 1 > targetRank.Rank || - (playerRank == RankDefinition.Leader && playerRank.Rank > targetRank.Rank))) - { - targetRank = RankDefinition.Ranks[targetRank.Rank + 1]; - - if (targetRank == RankDefinition.Leader) - { - if (m_ToLeader) - { - m_Member.GuildRank = targetRank; - pm.SendLocalizedMessage(1063156, - m_Member.Name); // The guild information for ~1_val~ has been updated. - pm.SendLocalizedMessage(1063156, - pm.Name); // The guild information for ~1_val~ has been updated. - guild.Leader = m_Member; - } - else - { - pm.SendLocalizedMessage( - 1063144); // Are you sure you wish to make this member the new guild leader? - pm.SendGump(new GuildMemberInfoGump(player, guild, m_Member, false, true)); - } - } - else - { - m_Member.GuildRank = targetRank; - pm.SendLocalizedMessage(1063156, - m_Member.Name); // The guild information for ~1_val~ has been updated. - } - } - else - { - pm.SendLocalizedMessage(1063143); // You don't have permission to promote this member. - } - - break; - } - case 2: // Demote - { - if (playerRank.GetFlag(RankFlags.CanPromoteDemote) && playerRank.Rank > targetRank.Rank) - { - if (targetRank == RankDefinition.Lowest) - { - if (RankDefinition.Lowest.Name.Number == 1062963) - pm.SendLocalizedMessage(1063333); // You can't demote a ronin. - else - pm.SendMessage("You can't demote a {0}.", RankDefinition.Lowest.Name); - } - else - { - m_Member.GuildRank = RankDefinition.Ranks[targetRank.Rank - 1]; - pm.SendLocalizedMessage(1063156, - m_Member.Name); // The guild information for ~1_val~ has been updated. - } - } - else - { - pm.SendLocalizedMessage(1063146); // You don't have permission to demote this member. - } - - break; - } - case 3: // Set Guild title - { - if (playerRank.GetFlag(RankFlags.CanSetGuildTitle) && - (playerRank.Rank > targetRank.Rank || m_Member == player)) - { - pm.SendLocalizedMessage( - 1011128); // Enter the new title for this guild member or 'none' to remove a title: - - pm.BeginPrompt(SetTitle_Callback); - } - else if (m_Member.GuildTitle == null || m_Member.GuildTitle.Length <= 0) - { - pm.SendLocalizedMessage(1070746); // You don't have the permission to set that member's guild title. - } - else - { - pm.SendLocalizedMessage(1063148); // You don't have permission to change this member's guild title. - } - - break; - } - case 4: // Vote - { - if (m_Member == pm.GuildFealty && guild.Leader != m_Member) - { - pm.SendLocalizedMessage(1063158); // You have cleared your vote for guild leader. - } - else if (guild.CanVote(m_Member)) - { - if (m_Member == guild.Leader) - { - pm.SendLocalizedMessage(1063424); // You can't vote for the current guild leader. - } - else if (!guild.CanBeVotedFor(m_Member)) - { - pm.SendLocalizedMessage(1063425); // You can't vote for an inactive guild member. - } - else - { - pm.GuildFealty = m_Member; - pm.SendLocalizedMessage(1063159, - m_Member.Name); // You cast your vote for ~1_val~ for guild leader. - } - } - else - { - pm.SendLocalizedMessage(1063149); // You don't have permission to vote. - } - - break; - } - case 5: // Kick - { - if ((playerRank.GetFlag(RankFlags.RemovePlayers) && playerRank.Rank > targetRank.Rank) || - (playerRank.GetFlag(RankFlags.RemoveLowestRank) && targetRank == RankDefinition.Lowest)) - { - if (m_toKick) - { - guild.RemoveMember(m_Member); - pm.SendLocalizedMessage(1063157); // The member has been removed from your guild. - } - else - { - pm.SendLocalizedMessage(1063152); // Are you sure you wish to kick this member from the guild? - pm.SendGump(new GuildMemberInfoGump(player, guild, m_Member, true, false)); - } - } - else - { - pm.SendLocalizedMessage(1063151); // You don't have permission to remove this member. - } - - break; - } - } - } - - public void SetTitle_Callback(Mobile from, string text) - { - if (!(from is PlayerMobile pm) || m_Member == null) - return; - - if (!(m_Member.Guild is Guild g) || !IsMember(pm, g) || - !(pm.GuildRank.GetFlag(RankFlags.CanSetGuildTitle) && - (pm.GuildRank.Rank > m_Member.GuildRank.Rank || pm == m_Member))) - { - if (m_Member.GuildTitle == null || m_Member.GuildTitle.Length <= 0) - pm.SendLocalizedMessage(1070746); // You don't have the permission to set that member's guild title. - else - pm.SendLocalizedMessage(1063148); // You don't have permission to change this member's guild title. - - return; - } - - string title = Utility.FixHtml(text.Trim()); - - if (title.Length > 20) - { - from.SendLocalizedMessage(501178); // That title is too long. - } - else if (!CheckProfanity(title)) - { - from.SendLocalizedMessage(501179); // That title is disallowed. - } - else - { - if (Insensitive.Equals(title, "none")) - m_Member.GuildTitle = null; - else - m_Member.GuildTitle = title; - - pm.SendLocalizedMessage(1063156, m_Member.Name); // The guild information for ~1_val~ has been updated. - } - } - } -} +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Guilds +{ + public class GuildMemberInfoGump : BaseGuildGump + { + private readonly PlayerMobile m_Member; + private readonly bool m_toKick; + private readonly bool m_ToLeader; + + public GuildMemberInfoGump( + PlayerMobile pm, Guild g, PlayerMobile member, bool toKick, bool toPromoteToLeader + ) : base(pm, g, 10, 40) + { + m_ToLeader = toPromoteToLeader; + m_toKick = toKick; + m_Member = member; + PopulateGump(); + } + + public override void PopulateGump() + { + AddPage(0); + + AddBackground(0, 0, 350, 255, 0x242C); + AddHtmlLocalized(20, 15, 310, 26, 1063018, 0x0); //
Guild Member Information
+ AddImageTiled(20, 40, 310, 2, 0x2711); + + AddHtmlLocalized(20, 50, 150, 26, 1062955, 0x0, true); // Name + AddHtml(180, 53, 150, 26, m_Member.Name); + + AddHtmlLocalized(20, 80, 150, 26, 1062956, 0x0, true); // Rank + AddHtmlLocalized(180, 83, 150, 26, m_Member.GuildRank.Name, 0x0); + + AddHtmlLocalized(20, 110, 150, 26, 1062953, 0x0, true); // Guild Title + AddHtml(180, 113, 150, 26, m_Member.GuildTitle); + AddImageTiled(20, 142, 310, 2, 0x2711); + + AddBackground(20, 150, 310, 26, 0x2486); + AddButton(25, 155, 0x845, 0x846, 4); + AddHtmlLocalized( + 50, + 153, + 270, + 26, + m_Member == player.GuildFealty && guild.Leader != m_Member ? 1063082 : 1062996, + 0x0 + ); // Clear/Cast Vote For This Member + + AddBackground(20, 180, 150, 26, 0x2486); + AddButton(25, 185, 0x845, 0x846, 1); + AddHtmlLocalized(50, 183, 110, 26, 1062993, m_ToLeader ? 0x990000 : 0); // Promote + + AddBackground(180, 180, 150, 26, 0x2486); + AddButton(185, 185, 0x845, 0x846, 3); + AddHtmlLocalized(210, 183, 110, 26, 1062995, 0x0); // Set Guild Title + + AddBackground(20, 210, 150, 26, 0x2486); + AddButton(25, 215, 0x845, 0x846, 2); + AddHtmlLocalized(50, 213, 110, 26, 1062994, 0x0); // Demote + + AddBackground(180, 210, 150, 26, 0x2486); + AddButton(185, 215, 0x845, 0x846, 5); + AddHtmlLocalized(210, 213, 110, 26, 1062997, m_toKick ? 0x5000 : 0); // Kick + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (!(sender.Mobile is PlayerMobile pm) || !IsMember(pm, guild) || !IsMember(m_Member, guild)) + return; + + var playerRank = pm.GuildRank; + var targetRank = m_Member.GuildRank; + + switch (info.ButtonID) + { + case 1: // Promote + { + if (playerRank.GetFlag(RankFlags.CanPromoteDemote) && + (playerRank.Rank - 1 > targetRank.Rank || + playerRank == RankDefinition.Leader && playerRank.Rank > targetRank.Rank)) + { + targetRank = RankDefinition.Ranks[targetRank.Rank + 1]; + + if (targetRank == RankDefinition.Leader) + { + if (m_ToLeader) + { + m_Member.GuildRank = targetRank; + pm.SendLocalizedMessage( + 1063156, + m_Member.Name + ); // The guild information for ~1_val~ has been updated. + pm.SendLocalizedMessage( + 1063156, + pm.Name + ); // The guild information for ~1_val~ has been updated. + guild.Leader = m_Member; + } + else + { + pm.SendLocalizedMessage( + 1063144 + ); // Are you sure you wish to make this member the new guild leader? + pm.SendGump(new GuildMemberInfoGump(player, guild, m_Member, false, true)); + } + } + else + { + m_Member.GuildRank = targetRank; + pm.SendLocalizedMessage( + 1063156, + m_Member.Name + ); // The guild information for ~1_val~ has been updated. + } + } + else + { + pm.SendLocalizedMessage(1063143); // You don't have permission to promote this member. + } + + break; + } + case 2: // Demote + { + if (playerRank.GetFlag(RankFlags.CanPromoteDemote) && playerRank.Rank > targetRank.Rank) + { + if (targetRank == RankDefinition.Lowest) + { + if (RankDefinition.Lowest.Name.Number == 1062963) + pm.SendLocalizedMessage(1063333); // You can't demote a ronin. + else + pm.SendMessage("You can't demote a {0}.", RankDefinition.Lowest.Name); + } + else + { + m_Member.GuildRank = RankDefinition.Ranks[targetRank.Rank - 1]; + pm.SendLocalizedMessage( + 1063156, + m_Member.Name + ); // The guild information for ~1_val~ has been updated. + } + } + else + { + pm.SendLocalizedMessage(1063146); // You don't have permission to demote this member. + } + + break; + } + case 3: // Set Guild title + { + if (playerRank.GetFlag(RankFlags.CanSetGuildTitle) && + (playerRank.Rank > targetRank.Rank || m_Member == player)) + { + pm.SendLocalizedMessage( + 1011128 + ); // Enter the new title for this guild member or 'none' to remove a title: + + pm.BeginPrompt(SetTitle_Callback); + } + else if (m_Member.GuildTitle == null || m_Member.GuildTitle.Length <= 0) + { + pm.SendLocalizedMessage( + 1070746 + ); // You don't have the permission to set that member's guild title. + } + else + { + pm.SendLocalizedMessage( + 1063148 + ); // You don't have permission to change this member's guild title. + } + + break; + } + case 4: // Vote + { + if (m_Member == pm.GuildFealty && guild.Leader != m_Member) + { + pm.SendLocalizedMessage(1063158); // You have cleared your vote for guild leader. + } + else if (guild.CanVote(m_Member)) + { + if (m_Member == guild.Leader) + { + pm.SendLocalizedMessage(1063424); // You can't vote for the current guild leader. + } + else if (!guild.CanBeVotedFor(m_Member)) + { + pm.SendLocalizedMessage(1063425); // You can't vote for an inactive guild member. + } + else + { + pm.GuildFealty = m_Member; + pm.SendLocalizedMessage( + 1063159, + m_Member.Name + ); // You cast your vote for ~1_val~ for guild leader. + } + } + else + { + pm.SendLocalizedMessage(1063149); // You don't have permission to vote. + } + + break; + } + case 5: // Kick + { + if (playerRank.GetFlag(RankFlags.RemovePlayers) && playerRank.Rank > targetRank.Rank || + playerRank.GetFlag(RankFlags.RemoveLowestRank) && targetRank == RankDefinition.Lowest) + { + if (m_toKick) + { + guild.RemoveMember(m_Member); + pm.SendLocalizedMessage(1063157); // The member has been removed from your guild. + } + else + { + pm.SendLocalizedMessage( + 1063152 + ); // Are you sure you wish to kick this member from the guild? + pm.SendGump(new GuildMemberInfoGump(player, guild, m_Member, true, false)); + } + } + else + { + pm.SendLocalizedMessage(1063151); // You don't have permission to remove this member. + } + + break; + } + } + } + + public void SetTitle_Callback(Mobile from, string text) + { + if (!(from is PlayerMobile pm) || m_Member == null) + return; + + if (!(m_Member.Guild is Guild g) || !IsMember(pm, g) || + !(pm.GuildRank.GetFlag(RankFlags.CanSetGuildTitle) && + (pm.GuildRank.Rank > m_Member.GuildRank.Rank || pm == m_Member))) + { + if (m_Member.GuildTitle == null || m_Member.GuildTitle.Length <= 0) + pm.SendLocalizedMessage(1070746); // You don't have the permission to set that member's guild title. + else + pm.SendLocalizedMessage(1063148); // You don't have permission to change this member's guild title. + + return; + } + + var title = Utility.FixHtml(text.Trim()); + + if (title.Length > 20) + { + from.SendLocalizedMessage(501178); // That title is too long. + } + else if (!CheckProfanity(title)) + { + from.SendLocalizedMessage(501179); // That title is disallowed. + } + else + { + if (Insensitive.Equals(title, "none")) + m_Member.GuildTitle = null; + else + m_Member.GuildTitle = title; + + pm.SendLocalizedMessage(1063156, m_Member.Name); // The guild information for ~1_val~ has been updated. + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/New Guild System/GuildRosterGump.cs b/Projects/UOContent/Gumps/Guilds/New Guild System/GuildRosterGump.cs index c4132ab9d..eb70abd39 100644 --- a/Projects/UOContent/Gumps/Guilds/New Guild System/GuildRosterGump.cs +++ b/Projects/UOContent/Gumps/Guilds/New Guild System/GuildRosterGump.cs @@ -1,239 +1,253 @@ -using System.Collections.Generic; -using Server.Factions; -using Server.Gumps; -using Server.Mobiles; -using Server.Network; -using Server.Targeting; - -namespace Server.Guilds -{ - public class GuildRosterGump : BaseGuildListGump - { - private static readonly InfoField[] m_Fields = - { - new InfoField(1062955, 130, NameComparer.Instance), // Name - new InfoField(1062956, 80, RankComparer.Instance), // Rank - new InfoField(1062952, 80, LastOnComparer.Instance), // Last On - new InfoField(1062953, 150, TitleComparer.Instance) // Guild Title - }; - - public GuildRosterGump(PlayerMobile pm, Guild g) : this(pm, g, LastOnComparer.Instance) - { - } - - public GuildRosterGump(PlayerMobile pm, Guild g, IComparer currentComparer, bool ascending = false, - string filter = "", int startNumber = 0) - : base(pm, g, Utility.SafeConvertList(g.Members), currentComparer, ascending, filter, - startNumber, m_Fields) - { - PopulateGump(); - } - - public override void PopulateGump() - { - base.PopulateGump(); - - AddHtmlLocalized(266, 43, 110, 26, 1062974, 0xF); // Guild Roster - } - - public override void DrawEndingEntry(int itemNumber) - { - AddBackground(225, 148 + itemNumber * 28, 150, 26, 0x2486); - AddButton(230, 153 + itemNumber * 28, 0x845, 0x846, 8); - AddHtmlLocalized(255, 151 + itemNumber * 28, 110, 26, 1062992, 0x0); // Invite Player - } - - protected override TextDefinition[] GetValuesFor(PlayerMobile pm, int aryLength) - { - TextDefinition[] defs = new TextDefinition[aryLength]; - - string name = $"{pm.Name}{(player.GuildFealty == pm && player.GuildFealty != guild.Leader ? " *" : "")}"; - - if (pm == player) - name = Color(name, 0x006600); - else if (pm.NetState != null) - name = Color(name, 0x000066); - - defs[0] = name; - defs[1] = pm.GuildRank.Name; - defs[2] = pm.NetState != null - ? new TextDefinition(1063015) - : new TextDefinition(pm.LastOnline.ToString("yyyy-MM-dd")); - defs[3] = pm.GuildTitle ?? ""; - - return defs; - } - - protected override bool IsFiltered(PlayerMobile pm, string filter) - { - if (pm == null) - return true; - - return !Insensitive.Contains(pm.Name, filter); - } - - public override Gump GetResentGump(PlayerMobile pm, Guild g, IComparer comparer, bool ascending, - string filter, int startNumber) => - new GuildRosterGump(pm, g, comparer, ascending, filter, startNumber); - - public override Gump GetObjectInfoGump(PlayerMobile pm, Guild g, PlayerMobile o) => new GuildMemberInfoGump(pm, g, o, false, false); - - public override void OnResponse(NetState sender, RelayInfo info) - { - base.OnResponse(sender, info); - - if (!(sender.Mobile is PlayerMobile pm) || !IsMember(pm, guild)) - return; - - if (info.ButtonID == 8) - { - if (pm.GuildRank.GetFlag(RankFlags.CanInvitePlayer)) - { - pm.SendLocalizedMessage(1063048); // Whom do you wish to invite into your guild? - pm.BeginTarget(-1, false, TargetFlags.None, InvitePlayer_Callback, guild); - } - else - { - pm.SendLocalizedMessage(503301); // You don't have permission to do that. - } - } - } - - public void InvitePlayer_Callback(Mobile from, object targeted, Guild g) - { - PlayerMobile pm = from as PlayerMobile; - PlayerMobile targ = targeted as PlayerMobile; - - PlayerState guildState = PlayerState.Find(g.Leader); - PlayerState targetState = PlayerState.Find(targ); - - Faction guildFaction = guildState?.Faction; - Faction targetFaction = targetState?.Faction; - - if (pm == null || !IsMember(pm, guild) || !pm.GuildRank.GetFlag(RankFlags.CanInvitePlayer)) - { - pm.SendLocalizedMessage(503301); // You don't have permission to do that. - } - else if (targ == null) - { - pm.SendLocalizedMessage(1063334); // That isn't a valid player. - } - else if (!targ.AcceptGuildInvites) - { - pm.SendLocalizedMessage(1063049, targ.Name); // ~1_val~ is not accepting guild invitations. - } - else if (g.IsMember(targ)) - { - pm.SendLocalizedMessage(1063050, targ.Name); // ~1_val~ is already a member of your guild! - } - else if (targ.Guild != null) - { - pm.SendLocalizedMessage(1063051, targ.Name); // ~1_val~ is already a member of a guild. - } - else if (targ.HasGump() || targ.HasGump()) // TODO: Check message if CreateGuildGump Open - { - pm.SendLocalizedMessage(1063052, targ.Name); // ~1_val~ is currently considering another guild invitation. - } - else if (targ.Young && guildFaction != null) - { - pm.SendLocalizedMessage(1070766); // You cannot invite a young player to your faction-aligned guild. - } - else if (guildFaction != targetFaction) - { - if (guildFaction == null) - pm.SendLocalizedMessage(1013027); // That player cannot join a non-faction guild. - else if (targetFaction == null) - pm.SendLocalizedMessage(1013026); // That player must be in a faction before joining this guild. - else - pm.SendLocalizedMessage(1013028); // That person has a different faction affiliation. - } - else if (targetState?.IsLeaving == true) - { - // OSI does this quite strangely, so we'll just do it this way - pm.SendMessage("That person is quitting their faction and so you may not recruit them."); - } - else - { - pm.SendLocalizedMessage(1063053, targ.Name); // You invite ~1_val~ to join your guild. - targ.SendGump(new GuildInvitationRequest(targ, guild, pm)); - } - } - - private class NameComparer : IComparer - { - public static readonly IComparer Instance = new NameComparer(); - - public int Compare(PlayerMobile x, PlayerMobile y) - { - if (x == null && y == null) - return 0; - if (x == null) - return -1; - if (y == null) - return 1; - - return Insensitive.Compare(x.Name, y.Name); - } - } - - private class LastOnComparer : IComparer - { - public static readonly IComparer Instance = new LastOnComparer(); - - public int Compare(PlayerMobile x, PlayerMobile y) - { - if (x == null && y == null) - return 0; - if (x == null) - return -1; - if (y == null) - return 1; - - NetState aState = x.NetState; - NetState bState = y.NetState; - - if (aState == null && bState == null) - return x.LastOnline.CompareTo(y.LastOnline); - if (aState == null) - return -1; - if (bState == null) - return 1; - return 0; - } - } - - private class TitleComparer : IComparer - { - public static readonly IComparer Instance = new TitleComparer(); - - public int Compare(PlayerMobile x, PlayerMobile y) - { - if (x == null && y == null) - return 0; - if (x == null) - return -1; - if (y == null) - return 1; - - return Insensitive.Compare(x.GuildTitle, y.GuildTitle); - } - } - - private class RankComparer : IComparer - { - public static readonly IComparer Instance = new RankComparer(); - - public int Compare(PlayerMobile x, PlayerMobile y) - { - if (x == null && y == null) - return 0; - if (x == null) - return -1; - if (y == null) - return 1; - - return x.GuildRank.Rank.CompareTo(y.GuildRank.Rank); - } - } - } -} +using System.Collections.Generic; +using Server.Factions; +using Server.Gumps; +using Server.Mobiles; +using Server.Network; +using Server.Targeting; + +namespace Server.Guilds +{ + public class GuildRosterGump : BaseGuildListGump + { + private static readonly InfoField[] m_Fields = + { + new InfoField(1062955, 130, NameComparer.Instance), // Name + new InfoField(1062956, 80, RankComparer.Instance), // Rank + new InfoField(1062952, 80, LastOnComparer.Instance), // Last On + new InfoField(1062953, 150, TitleComparer.Instance) // Guild Title + }; + + public GuildRosterGump(PlayerMobile pm, Guild g) : this(pm, g, LastOnComparer.Instance) + { + } + + public GuildRosterGump( + PlayerMobile pm, Guild g, IComparer currentComparer, bool ascending = false, + string filter = "", int startNumber = 0 + ) + : base( + pm, + g, + Utility.SafeConvertList(g.Members), + currentComparer, + ascending, + filter, + startNumber, + m_Fields + ) + { + PopulateGump(); + } + + public override void PopulateGump() + { + base.PopulateGump(); + + AddHtmlLocalized(266, 43, 110, 26, 1062974, 0xF); // Guild Roster + } + + public override void DrawEndingEntry(int itemNumber) + { + AddBackground(225, 148 + itemNumber * 28, 150, 26, 0x2486); + AddButton(230, 153 + itemNumber * 28, 0x845, 0x846, 8); + AddHtmlLocalized(255, 151 + itemNumber * 28, 110, 26, 1062992, 0x0); // Invite Player + } + + protected override TextDefinition[] GetValuesFor(PlayerMobile pm, int aryLength) + { + var defs = new TextDefinition[aryLength]; + + var name = $"{pm.Name}{(player.GuildFealty == pm && player.GuildFealty != guild.Leader ? " *" : "")}"; + + if (pm == player) + name = Color(name, 0x006600); + else if (pm.NetState != null) + name = Color(name, 0x000066); + + defs[0] = name; + defs[1] = pm.GuildRank.Name; + defs[2] = pm.NetState != null + ? new TextDefinition(1063015) + : new TextDefinition(pm.LastOnline.ToString("yyyy-MM-dd")); + defs[3] = pm.GuildTitle ?? ""; + + return defs; + } + + protected override bool IsFiltered(PlayerMobile pm, string filter) + { + if (pm == null) + return true; + + return !Insensitive.Contains(pm.Name, filter); + } + + public override Gump GetResentGump( + PlayerMobile pm, Guild g, IComparer comparer, bool ascending, + string filter, int startNumber + ) => + new GuildRosterGump(pm, g, comparer, ascending, filter, startNumber); + + public override Gump GetObjectInfoGump(PlayerMobile pm, Guild g, PlayerMobile o) => + new GuildMemberInfoGump(pm, g, o, false, false); + + public override void OnResponse(NetState sender, RelayInfo info) + { + base.OnResponse(sender, info); + + if (!(sender.Mobile is PlayerMobile pm) || !IsMember(pm, guild)) + return; + + if (info.ButtonID == 8) + { + if (pm.GuildRank.GetFlag(RankFlags.CanInvitePlayer)) + { + pm.SendLocalizedMessage(1063048); // Whom do you wish to invite into your guild? + pm.BeginTarget(-1, false, TargetFlags.None, InvitePlayer_Callback, guild); + } + else + { + pm.SendLocalizedMessage(503301); // You don't have permission to do that. + } + } + } + + public void InvitePlayer_Callback(Mobile from, object targeted, Guild g) + { + var pm = from as PlayerMobile; + var targ = targeted as PlayerMobile; + + var guildState = PlayerState.Find(g.Leader); + var targetState = PlayerState.Find(targ); + + var guildFaction = guildState?.Faction; + var targetFaction = targetState?.Faction; + + if (pm == null || !IsMember(pm, guild) || !pm.GuildRank.GetFlag(RankFlags.CanInvitePlayer)) + { + pm.SendLocalizedMessage(503301); // You don't have permission to do that. + } + else if (targ == null) + { + pm.SendLocalizedMessage(1063334); // That isn't a valid player. + } + else if (!targ.AcceptGuildInvites) + { + pm.SendLocalizedMessage(1063049, targ.Name); // ~1_val~ is not accepting guild invitations. + } + else if (g.IsMember(targ)) + { + pm.SendLocalizedMessage(1063050, targ.Name); // ~1_val~ is already a member of your guild! + } + else if (targ.Guild != null) + { + pm.SendLocalizedMessage(1063051, targ.Name); // ~1_val~ is already a member of a guild. + } + else if (targ.HasGump() || targ.HasGump() + ) // TODO: Check message if CreateGuildGump Open + { + pm.SendLocalizedMessage(1063052, targ.Name); // ~1_val~ is currently considering another guild invitation. + } + else if (targ.Young && guildFaction != null) + { + pm.SendLocalizedMessage(1070766); // You cannot invite a young player to your faction-aligned guild. + } + else if (guildFaction != targetFaction) + { + if (guildFaction == null) + pm.SendLocalizedMessage(1013027); // That player cannot join a non-faction guild. + else if (targetFaction == null) + pm.SendLocalizedMessage(1013026); // That player must be in a faction before joining this guild. + else + pm.SendLocalizedMessage(1013028); // That person has a different faction affiliation. + } + else if (targetState?.IsLeaving == true) + { + // OSI does this quite strangely, so we'll just do it this way + pm.SendMessage("That person is quitting their faction and so you may not recruit them."); + } + else + { + pm.SendLocalizedMessage(1063053, targ.Name); // You invite ~1_val~ to join your guild. + targ.SendGump(new GuildInvitationRequest(targ, guild, pm)); + } + } + + private class NameComparer : IComparer + { + public static readonly IComparer Instance = new NameComparer(); + + public int Compare(PlayerMobile x, PlayerMobile y) + { + if (x == null && y == null) + return 0; + if (x == null) + return -1; + if (y == null) + return 1; + + return Insensitive.Compare(x.Name, y.Name); + } + } + + private class LastOnComparer : IComparer + { + public static readonly IComparer Instance = new LastOnComparer(); + + public int Compare(PlayerMobile x, PlayerMobile y) + { + if (x == null && y == null) + return 0; + if (x == null) + return -1; + if (y == null) + return 1; + + var aState = x.NetState; + var bState = y.NetState; + + if (aState == null && bState == null) + return x.LastOnline.CompareTo(y.LastOnline); + if (aState == null) + return -1; + if (bState == null) + return 1; + return 0; + } + } + + private class TitleComparer : IComparer + { + public static readonly IComparer Instance = new TitleComparer(); + + public int Compare(PlayerMobile x, PlayerMobile y) + { + if (x == null && y == null) + return 0; + if (x == null) + return -1; + if (y == null) + return 1; + + return Insensitive.Compare(x.GuildTitle, y.GuildTitle); + } + } + + private class RankComparer : IComparer + { + public static readonly IComparer Instance = new RankComparer(); + + public int Compare(PlayerMobile x, PlayerMobile y) + { + if (x == null && y == null) + return 0; + if (x == null) + return -1; + if (y == null) + return 1; + + return x.GuildRank.Rank.CompareTo(y.GuildRank.Rank); + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/New Guild System/OtherGuildInfo.cs b/Projects/UOContent/Gumps/Guilds/New Guild System/OtherGuildInfo.cs index 964da47e2..00964d29b 100644 --- a/Projects/UOContent/Gumps/Guilds/New Guild System/OtherGuildInfo.cs +++ b/Projects/UOContent/Gumps/Guilds/New Guild System/OtherGuildInfo.cs @@ -1,682 +1,771 @@ -using System; -using Server.Factions; -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Guilds -{ - public class OtherGuildInfo : BaseGuildGump - { - private readonly Guild m_Other; - - public OtherGuildInfo(PlayerMobile pm, Guild g, Guild otherGuild) : base(pm, g, 10, 40) - { - m_Other = otherGuild; - - g.CheckExpiredWars(); - - PopulateGump(); - } - - public void AddButtonAndBackground(int x, int y, int buttonID, int locNum) - { - AddBackground(x, y, 225, 26, 0x2486); - AddButton(x + 5, y + 5, 0x845, 0x846, buttonID); - AddHtmlLocalized(x + 30, y + 3, 185, 26, locNum, 0x0); - } - - public override void PopulateGump() - { - Guild g = Guild.GetAllianceLeader(guild); - Guild other = Guild.GetAllianceLeader(m_Other); - - WarDeclaration war = g.FindPendingWar(other); - WarDeclaration activeWar = g.FindActiveWar(other); - - AllianceInfo alliance = guild.Alliance; - AllianceInfo otherAlliance = m_Other.Alliance; - // NOTE TO SELF: Only only alliance leader can see pending guild alliance statuses - - bool PendingWar = war != null; - bool ActiveWar = activeWar != null; - AddPage(0); - - AddBackground(0, 0, 520, 335, 0x242C); - AddHtmlLocalized(20, 15, 480, 26, 1062975, 0x0); //
Guild Relationship
- AddImageTiled(20, 40, 480, 2, 0x2711); - AddHtmlLocalized(20, 50, 120, 26, 1062954, 0x0, true); // Guild Name - AddHtml(150, 53, 360, 26, m_Other.Name); - - AddHtmlLocalized(20, 80, 120, 26, 1063025, 0x0, true); // Alliance - - if (otherAlliance?.IsMember(m_Other) == true) - AddHtml(150, 83, 360, 26, otherAlliance.Name); - - AddHtmlLocalized(20, 110, 120, 26, 1063139, 0x0, true); // Abbreviation - AddHtml(150, 113, 120, 26, m_Other.Abbreviation); - - string kills = "0/0"; - string time = "00:00"; - string otherKills = "0/0"; - - WarDeclaration otherWar; - - if (ActiveWar) - { - kills = $"{activeWar.Kills}/{activeWar.MaxKills}"; - - TimeSpan timeRemaining = TimeSpan.Zero; - - if (activeWar.WarLength != TimeSpan.Zero && activeWar.WarBeginning + activeWar.WarLength > DateTime.UtcNow) - timeRemaining = activeWar.WarBeginning + activeWar.WarLength - DateTime.UtcNow; - - time = $"{timeRemaining.Hours:D2}:{DateTime.MinValue + timeRemaining:mm}"; - - otherWar = m_Other.FindActiveWar(guild); - if (otherWar != null) - otherKills = $"{otherWar.Kills}/{otherWar.MaxKills}"; - } - else if (PendingWar) - { - kills = Color($"{war.Kills}/{war.MaxKills}", 0x990000); - // time = Color( String.Format( "{0}:{1}", war.WarLength.Hours, ((TimeSpan)(war.WarLength - TimeSpan.FromHours( war.WarLength.Hours ))).Minutes ), 0xFF0000 ); - time = Color($"{war.WarLength.Hours:D2}:{DateTime.MinValue + war.WarLength:mm}", 0x990000); - - otherWar = m_Other.FindPendingWar(guild); - if (otherWar != null) - otherKills = Color($"{otherWar.Kills}/{otherWar.MaxKills}", 0x990000); - } - - AddHtmlLocalized(280, 110, 120, 26, 1062966, 0x0, true); // Your Kills - AddHtml(410, 113, 120, 26, kills); - - AddHtmlLocalized(20, 140, 120, 26, 1062968, 0x0, true); // Time Remaining - AddHtml(150, 143, 120, 26, time); - - AddHtmlLocalized(280, 140, 120, 26, 1062967, 0x0, true); // Their Kills - AddHtml(410, 143, 120, 26, otherKills); - - AddImageTiled(20, 172, 480, 2, 0x2711); - - int number = 1062973; //
You are at peace with this guild.
- - if (PendingWar) - { - if (war.WarRequester) - { - number = 1063027; //
You have challenged this guild to war!
- } - else - { - number = 1062969; //
This guild has challenged you to war!
- - AddButtonAndBackground(20, 260, 5, 1062981); // Accept Challenge - AddButtonAndBackground(275, 260, 6, 1062983); // Modify Terms - } - - AddButtonAndBackground(20, 290, 7, 1062982); // Dismiss Challenge - } - else if (ActiveWar) - { - number = 1062965; //
You are at war with this guild!
- AddButtonAndBackground(20, 290, 8, 1062980); // Surrender - } - else if (alliance != null && alliance == otherAlliance) // alliance, Same Alliance - { - if (alliance.IsMember(guild) && alliance.IsMember(m_Other)) // Both in Same alliance, full members - { - number = 1062970; //
You are allied with this guild.
- - if (alliance.Leader == guild) - { - AddButtonAndBackground(20, 260, 12, 1062984); // Remove Guild from Alliance - AddButtonAndBackground(275, 260, 13, - 1063433); // Promote to Alliance Leader //Note: No 'confirmation' like the other leader guild promotion things - // Remove guild from alliance //Promote to Alliance Leader - } - - // Show roster, Centered, up - AddButtonAndBackground(148, 215, 10, 1063164); // Show Alliance Roster - // Leave Alliance - AddButtonAndBackground(20, 290, 11, 1062985); // Leave Alliance - } - else if (alliance.Leader == guild && alliance.IsPendingMember(m_Other)) - { - number = 1062971; //
You have requested an alliance with this guild.
- - // Show Alliance Roster, Centered, down. - AddButtonAndBackground(148, 245, 10, 1063164); // Show Alliance Roster - // Withdraw Request - AddButtonAndBackground(20, 290, 14, 1062986); // Withdraw Request - - AddHtml(150, 83, 360, 26, Color(alliance.Name, 0x99)); - } - else if (alliance.Leader == m_Other && alliance.IsPendingMember(guild)) - { - number = 1062972; //
This guild has requested an alliance.
- - // Show alliance Roster, top - AddButtonAndBackground(148, 215, 10, 1063164); // Show Alliance Roster - // Deny Request - // Accept Request - AddButtonAndBackground(20, 260, 15, 1062988); // Deny Request - AddButtonAndBackground(20, 290, 16, 1062987); // Accept Request - - AddHtml(150, 83, 360, 26, Color(alliance.Name, 0x99)); - } - } - else - { - AddButtonAndBackground(20, 260, 2, 1062990); // Request Alliance - AddButtonAndBackground(20, 290, 1, 1062989); // Declare War! - } - - AddButtonAndBackground(275, 290, 0, 3000091); // Cancel - - AddHtmlLocalized(20, 180, 480, 30, number, 0x0, true); - AddImageTiled(20, 245, 480, 2, 0x2711); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (!(sender.Mobile is PlayerMobile pm && IsMember(pm, guild))) - return; - - RankDefinition playerRank = pm.GuildRank; - - Guild guildLeader = Guild.GetAllianceLeader(guild); - Guild otherGuild = Guild.GetAllianceLeader(m_Other); - - WarDeclaration war = guildLeader.FindPendingWar(otherGuild); - WarDeclaration activeWar = guildLeader.FindActiveWar(otherGuild); - WarDeclaration otherWar = otherGuild.FindPendingWar(guildLeader); - - AllianceInfo alliance = guild.Alliance; - AllianceInfo otherAlliance = otherGuild.Alliance; - - switch (info.ButtonID) - { - case 5: // Accept the war - { - if (war?.WarRequester == false && activeWar == null) - { - if (!playerRank.GetFlag(RankFlags.ControlWarStatus)) - { - pm.SendLocalizedMessage(1063440); // You don't have permission to negotiate wars. - } - else if (alliance != null && alliance.Leader != guild) - { - pm.SendLocalizedMessage(1063239, - $"{guild.Name}\t{alliance.Name}"); // ~1_val~ is not the leader of the ~2_val~ alliance. - pm.SendLocalizedMessage(1070707, - alliance.Leader.Name); // You need to negotiate via ~1_val~ instead. - } - else - { - // Accept the war - guild.PendingWars.Remove(war); - war.WarBeginning = DateTime.UtcNow; - guild.AcceptedWars.Add(war); - - if (alliance?.IsMember(guild) == true) - { - alliance.AllianceMessage(1070769, - otherAlliance != null - ? otherAlliance.Name - : otherGuild.Name); // Guild Message: Your guild is now at war with ~1_GUILDNAME~ - alliance.InvalidateMemberProperties(); - } - else - { - guild.GuildMessage(1070769, - otherAlliance != null - ? otherAlliance.Name - : otherGuild.Name); // Guild Message: Your guild is now at war with ~1_GUILDNAME~ - guild.InvalidateMemberProperties(); - } - // Technically SHOULD say Your guild is now at war w/out any info, intentional diff. - - otherGuild.PendingWars.Remove(otherWar); - otherWar.WarBeginning = DateTime.UtcNow; - otherGuild.AcceptedWars.Add(otherWar); - - if (otherAlliance != null && m_Other.Alliance.IsMember(m_Other)) - { - otherAlliance.AllianceMessage(1070769, - alliance != null - ? alliance.Name - : guild.Name); // Guild Message: Your guild is now at war with ~1_GUILDNAME~ - otherAlliance.InvalidateMemberProperties(); - } - else - { - otherGuild.GuildMessage(1070769, - alliance != null - ? alliance.Name - : guild.Name); // Guild Message: Your guild is now at war with ~1_GUILDNAME~ - otherGuild.InvalidateMemberProperties(); - } - } - } - - break; - } - case 6: // Modify war terms - { - if (war?.WarRequester == false && activeWar == null) - { - if (!playerRank.GetFlag(RankFlags.ControlWarStatus)) - { - pm.SendLocalizedMessage(1063440); // You don't have permission to negotiate wars. - } - else if (alliance != null && alliance.Leader != guild) - { - pm.SendLocalizedMessage(1063239, - $"{guild.Name}\t{alliance.Name}"); // ~1_val~ is not the leader of the ~2_val~ alliance. - pm.SendLocalizedMessage(1070707, - alliance.Leader.Name); // You need to negotiate via ~1_val~ instead. - } - else - { - pm.SendGump(new WarDeclarationGump(pm, guild, otherGuild)); - } - } - - break; - } - case 7: // Dismiss war - { - if (war != null) - { - if (!playerRank.GetFlag(RankFlags.ControlWarStatus)) - { - pm.SendLocalizedMessage(1063440); // You don't have permission to negotiate wars. - } - else if (alliance != null && alliance.Leader != guild) - { - pm.SendLocalizedMessage(1063239, - $"{guild.Name}\t{alliance.Name}"); // ~1_val~ is not the leader of the ~2_val~ alliance. - pm.SendLocalizedMessage(1070707, - alliance.Leader.Name); // You need to negotiate via ~1_val~ instead. - } - else - { - // Dismiss the war - guild.PendingWars.Remove(war); - otherGuild.PendingWars.Remove(otherWar); - pm.SendLocalizedMessage(1070752); // The proposal has been updated. - // Messages to opposing guild? (Testing on OSI says no) - } - } - - break; - } - case 8: // Surrender - { - if (!playerRank.GetFlag(RankFlags.ControlWarStatus)) - { - pm.SendLocalizedMessage(1063440); // You don't have permission to negotiate wars. - } - else if (alliance != null && alliance.Leader != guild) - { - pm.SendLocalizedMessage(1063239, - $"{guild.Name}\t{alliance.Name}"); // ~1_val~ is not the leader of the ~2_val~ alliance. - pm.SendLocalizedMessage(1070707, alliance.Leader.Name); // You need to negotiate via ~1_val~ instead. - } - else - { - if (activeWar != null) - { - if (alliance?.IsMember(guild) == true) - { - alliance.AllianceMessage(1070740, - otherAlliance != null - ? otherAlliance.Name - : otherGuild.Name); // You have lost the war with ~1_val~. - alliance.InvalidateMemberProperties(); - } - else - { - guild.GuildMessage(1070740, - otherAlliance != null - ? otherAlliance.Name - : otherGuild.Name); // You have lost the war with ~1_val~. - guild.InvalidateMemberProperties(); - } - - guild.AcceptedWars.Remove(activeWar); - - if (otherAlliance?.IsMember(otherGuild) == true) - { - otherAlliance.AllianceMessage(1070739, - guild.Alliance != null - ? guild.Alliance.Name - : guild.Name); // You have won the war against ~1_val~! - otherAlliance.InvalidateMemberProperties(); - } - else - { - otherGuild.GuildMessage(1070739, - guild.Alliance != null - ? guild.Alliance.Name - : guild.Name); // You have won the war against ~1_val~! - otherGuild.InvalidateMemberProperties(); - } - - otherGuild.AcceptedWars.Remove(otherGuild.FindActiveWar(guild)); - } - } - - break; - } - case 1: // Declare War - { - if (war == null && activeWar == null) - { - if (!playerRank.GetFlag(RankFlags.ControlWarStatus)) - { - pm.SendLocalizedMessage(1063440); // You don't have permission to negotiate wars. - } - else if (alliance != null && alliance.Leader != guild) - { - pm.SendLocalizedMessage(1063239, - $"{guild.Name}\t{alliance.Name}"); // ~1_val~ is not the leader of the ~2_val~ alliance. - pm.SendLocalizedMessage(1070707, - alliance.Leader.Name); // You need to negotiate via ~1_val~ instead. - } - else if (otherAlliance != null && otherAlliance.Leader != m_Other) - { - pm.SendLocalizedMessage(1063239, - $"{m_Other.Name}\t{otherAlliance.Name}"); // ~1_val~ is not the leader of the ~2_val~ alliance. - pm.SendLocalizedMessage(1070707, - otherAlliance.Leader.Name); // You need to negotiate via ~1_val~ instead. - } - else - { - pm.SendGump(new WarDeclarationGump(pm, guild, m_Other)); - } - } - - break; - } - - case 2: // Request Alliance - { - if (alliance == null) - { - if (!playerRank.GetFlag(RankFlags.AllianceControl)) - { - pm.SendLocalizedMessage(1070747); // You don't have permission to create an alliance. - } - else if (Faction.Find(guild.Leader) != Faction.Find(m_Other.Leader)) - { - pm.SendLocalizedMessage( - 1070758); // You cannot propose an alliance to a guild with a different faction allegiance. - } - else if (otherAlliance != null) - { - if (otherAlliance.IsPendingMember(m_Other)) - pm.SendLocalizedMessage(1063416, - m_Other.Name); // ~1_val~ is currently considering another alliance proposal. - else - pm.SendLocalizedMessage(1063426, m_Other.Name); // ~1_val~ already belongs to an alliance. - } - else if (m_Other.AcceptedWars.Count > 0 || m_Other.PendingWars.Count > 0) - { - pm.SendLocalizedMessage(1063427, m_Other.Name); // ~1_val~ is currently involved in a guild war. - } - else if (guild.AcceptedWars.Count > 0 || guild.PendingWars.Count > 0) - { - pm.SendLocalizedMessage(1063427, guild.Name); // ~1_val~ is currently involved in a guild war. - } - else - { - pm.SendLocalizedMessage(1063439); // Enter a name for the new alliance: - pm.BeginPrompt(CreateAlliance_Callback); - } - } - else - { - if (!playerRank.GetFlag(RankFlags.AllianceControl)) - { - pm.SendLocalizedMessage(1063436); // You don't have permission to negotiate an alliance. - } - else if (alliance.Leader != guild) - { - pm.SendLocalizedMessage(1063239, - $"{guild.Name}\t{alliance.Name}"); // ~1_val~ is not the leader of the ~2_val~ alliance. - } - else if (otherAlliance != null) - { - if (otherAlliance.IsPendingMember(m_Other)) - pm.SendLocalizedMessage(1063416, - m_Other.Name); // ~1_val~ is currently considering another alliance proposal. - else - pm.SendLocalizedMessage(1063426, m_Other.Name); // ~1_val~ already belongs to an alliance. - } - else if (alliance.IsPendingMember(guild)) - { - pm.SendLocalizedMessage(1063416, - guild.Name); // ~1_val~ is currently considering another alliance proposal. - } - else if (m_Other.AcceptedWars.Count > 0 || m_Other.PendingWars.Count > 0) - { - pm.SendLocalizedMessage(1063427, m_Other.Name); // ~1_val~ is currently involved in a guild war. - } - else if (guild.AcceptedWars.Count > 0 || guild.PendingWars.Count > 0) - { - pm.SendLocalizedMessage(1063427, guild.Name); // ~1_val~ is currently involved in a guild war. - } - else if (Faction.Find(guild.Leader) != Faction.Find(m_Other.Leader)) - { - pm.SendLocalizedMessage( - 1070758); // You cannot propose an alliance to a guild with a different faction allegiance. - } - else - { - pm.SendLocalizedMessage(1070750, - m_Other.Name); // An invitation to join your alliance has been sent to ~1_val~. - - m_Other.GuildMessage(1070780, guild.Name); // ~1_val~ has proposed an alliance. - - m_Other.Alliance = alliance; // Calls addPendingGuild - // alliance.AddPendingGuild( m_Other ); - } - } - - break; - } - case 10: // Show Alliance Roster - { - if (alliance != null && alliance == otherAlliance) - pm.SendGump(new AllianceInfo.AllianceRosterGump(pm, guild, alliance)); - - break; - } - case 11: // Leave Alliance - { - if (!playerRank.GetFlag(RankFlags.AllianceControl)) - { - pm.SendLocalizedMessage(1063436); // You don't have permission to negotiate an alliance. - } - else if (alliance?.IsMember(guild) == true) - { - guild.Alliance = null; // Calls alliance.Removeguild - // alliance.RemoveGuild( guild ); - - m_Other.InvalidateWarNotoriety(); - - guild.InvalidateMemberNotoriety(); - } - - break; - } - case 12: // Remove Guild from alliance - { - if (!playerRank.GetFlag(RankFlags.AllianceControl)) - { - pm.SendLocalizedMessage(1063436); // You don't have permission to negotiate an alliance. - } - else if (alliance != null && alliance.Leader != guild) - { - pm.SendLocalizedMessage(1063239, - $"{guild.Name}\t{alliance.Name}"); // ~1_val~ is not the leader of the ~2_val~ alliance. - } - else if (alliance?.IsMember(guild) == true && alliance.IsMember(m_Other)) - { - m_Other.Alliance = null; - - m_Other.InvalidateMemberNotoriety(); - - guild.InvalidateWarNotoriety(); - } - - break; - } - case 13: // Promote to Alliance leader - { - if (!playerRank.GetFlag(RankFlags.AllianceControl)) - { - pm.SendLocalizedMessage(1063436); // You don't have permission to negotiate an alliance. - } - else if (alliance != null && alliance.Leader != guild) - { - pm.SendLocalizedMessage(1063239, - $"{guild.Name}\t{alliance.Name}"); // ~1_val~ is not the leader of the ~2_val~ alliance. - } - else if (alliance?.IsMember(guild) == true && alliance.IsMember(m_Other)) - { - pm.SendLocalizedMessage(1063434, - $"{m_Other.Name}\t{alliance.Name}"); // ~1_val~ is now the leader of ~2_val~. - - alliance.Leader = m_Other; - } - - break; - } - case 14: // Withdraw Request - { - if (!playerRank.GetFlag(RankFlags.AllianceControl)) - { - pm.SendLocalizedMessage(1063436); // You don't have permission to negotiate an alliance. - } - else if (alliance != null && alliance.Leader == guild && alliance.IsPendingMember(m_Other)) - { - m_Other.Alliance = null; - pm.SendLocalizedMessage(1070752); // The proposal has been updated. - } - - break; - } - case 15: // Deny Alliance Request - { - if (!playerRank.GetFlag(RankFlags.AllianceControl)) - { - pm.SendLocalizedMessage(1063436); // You don't have permission to negotiate an alliance. - } - else if (alliance != null && otherAlliance != null && alliance.Leader == m_Other && - otherAlliance.IsPendingMember(guild)) - { - // The proposal has been updated. - // m_Other.GuildMessage( 1070782 ); - // // ~1_val~ has responded to your proposal. - // //Per OSI commented out. - pm.SendLocalizedMessage(1070752); - guild.Alliance = null; - } - - break; - } - case 16: // Accept Alliance Request - { - if (!playerRank.GetFlag(RankFlags.AllianceControl)) - { - pm.SendLocalizedMessage(1063436); // You don't have permission to negotiate an alliance. - } - else if (otherAlliance != null && otherAlliance.Leader == m_Other && - otherAlliance.IsPendingMember(guild)) - { - pm.SendLocalizedMessage(1070752); // The proposal has been updated. - - otherAlliance - .TurnToMember( - m_Other); // No need to verify it's in the guild or already a member, the function does this - - otherAlliance.TurnToMember(guild); - } - - break; - } - } - } - - public void CreateAlliance_Callback(Mobile from, string text) - { - if (!(from is PlayerMobile pm)) - return; - - AllianceInfo alliance = guild.Alliance; - AllianceInfo otherAlliance = m_Other.Alliance; - - if (!IsMember(from, guild) || alliance != null) - return; - - RankDefinition playerRank = pm.GuildRank; - - if (!playerRank.GetFlag(RankFlags.AllianceControl)) - { - pm.SendLocalizedMessage(1070747); // You don't have permission to create an alliance. - } - else if (Faction.Find(guild.Leader) != Faction.Find(m_Other.Leader)) - { - // Notes about this: OSI only cares/checks when proposing, you can change your faction all you want later. - pm.SendLocalizedMessage( - 1070758); // You cannot propose an alliance to a guild with a different faction allegiance. - } - else if (otherAlliance != null) - { - if (otherAlliance.IsPendingMember(m_Other)) - pm.SendLocalizedMessage(1063416, - m_Other.Name); // ~1_val~ is currently considering another alliance proposal. - else - pm.SendLocalizedMessage(1063426, m_Other.Name); // ~1_val~ already belongs to an alliance. - } - else if (m_Other.AcceptedWars.Count > 0 || m_Other.PendingWars.Count > 0) - { - pm.SendLocalizedMessage(1063427, m_Other.Name); // ~1_val~ is currently involved in a guild war. - } - else if (guild.AcceptedWars.Count > 0 || guild.PendingWars.Count > 0) - { - pm.SendLocalizedMessage(1063427, guild.Name); // ~1_val~ is currently involved in a guild war. - } - else - { - string name = Utility.FixHtml(text.Trim()); - - if (!CheckProfanity(name)) - { - pm.SendLocalizedMessage(1070886); // That alliance name is not allowed. - } - else if (name.Length > Guild.NameLimit) - { - pm.SendLocalizedMessage(1070887, - Guild.NameLimit.ToString()); // An alliance name cannot exceed ~1_val~ characters in length. - } - else if (AllianceInfo.Alliances.ContainsKey(name.ToLower())) - { - pm.SendLocalizedMessage(1063428); // That alliance name is not available. - } - else - { - pm.SendLocalizedMessage(1070750, - m_Other.Name); // An invitation to join your alliance has been sent to ~1_val~. - - m_Other.GuildMessage(1070780, guild.Name); // ~1_val~ has proposed an alliance. - - new AllianceInfo(guild, name, m_Other); - } - } - } - } -} +using System; +using Server.Factions; +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Guilds +{ + public class OtherGuildInfo : BaseGuildGump + { + private readonly Guild m_Other; + + public OtherGuildInfo(PlayerMobile pm, Guild g, Guild otherGuild) : base(pm, g, 10, 40) + { + m_Other = otherGuild; + + g.CheckExpiredWars(); + + PopulateGump(); + } + + public void AddButtonAndBackground(int x, int y, int buttonID, int locNum) + { + AddBackground(x, y, 225, 26, 0x2486); + AddButton(x + 5, y + 5, 0x845, 0x846, buttonID); + AddHtmlLocalized(x + 30, y + 3, 185, 26, locNum, 0x0); + } + + public override void PopulateGump() + { + var g = Guild.GetAllianceLeader(guild); + var other = Guild.GetAllianceLeader(m_Other); + + var war = g.FindPendingWar(other); + var activeWar = g.FindActiveWar(other); + + var alliance = guild.Alliance; + var otherAlliance = m_Other.Alliance; + // NOTE TO SELF: Only only alliance leader can see pending guild alliance statuses + + var PendingWar = war != null; + var ActiveWar = activeWar != null; + AddPage(0); + + AddBackground(0, 0, 520, 335, 0x242C); + AddHtmlLocalized(20, 15, 480, 26, 1062975, 0x0); //
Guild Relationship
+ AddImageTiled(20, 40, 480, 2, 0x2711); + AddHtmlLocalized(20, 50, 120, 26, 1062954, 0x0, true); // Guild Name + AddHtml(150, 53, 360, 26, m_Other.Name); + + AddHtmlLocalized(20, 80, 120, 26, 1063025, 0x0, true); // Alliance + + if (otherAlliance?.IsMember(m_Other) == true) + AddHtml(150, 83, 360, 26, otherAlliance.Name); + + AddHtmlLocalized(20, 110, 120, 26, 1063139, 0x0, true); // Abbreviation + AddHtml(150, 113, 120, 26, m_Other.Abbreviation); + + var kills = "0/0"; + var time = "00:00"; + var otherKills = "0/0"; + + WarDeclaration otherWar; + + if (ActiveWar) + { + kills = $"{activeWar.Kills}/{activeWar.MaxKills}"; + + var timeRemaining = TimeSpan.Zero; + + if (activeWar.WarLength != TimeSpan.Zero && activeWar.WarBeginning + activeWar.WarLength > DateTime.UtcNow) + timeRemaining = activeWar.WarBeginning + activeWar.WarLength - DateTime.UtcNow; + + time = $"{timeRemaining.Hours:D2}:{DateTime.MinValue + timeRemaining:mm}"; + + otherWar = m_Other.FindActiveWar(guild); + if (otherWar != null) + otherKills = $"{otherWar.Kills}/{otherWar.MaxKills}"; + } + else if (PendingWar) + { + kills = Color($"{war.Kills}/{war.MaxKills}", 0x990000); + // time = Color( String.Format( "{0}:{1}", war.WarLength.Hours, ((TimeSpan)(war.WarLength - TimeSpan.FromHours( war.WarLength.Hours ))).Minutes ), 0xFF0000 ); + time = Color($"{war.WarLength.Hours:D2}:{DateTime.MinValue + war.WarLength:mm}", 0x990000); + + otherWar = m_Other.FindPendingWar(guild); + if (otherWar != null) + otherKills = Color($"{otherWar.Kills}/{otherWar.MaxKills}", 0x990000); + } + + AddHtmlLocalized(280, 110, 120, 26, 1062966, 0x0, true); // Your Kills + AddHtml(410, 113, 120, 26, kills); + + AddHtmlLocalized(20, 140, 120, 26, 1062968, 0x0, true); // Time Remaining + AddHtml(150, 143, 120, 26, time); + + AddHtmlLocalized(280, 140, 120, 26, 1062967, 0x0, true); // Their Kills + AddHtml(410, 143, 120, 26, otherKills); + + AddImageTiled(20, 172, 480, 2, 0x2711); + + var number = 1062973; //
You are at peace with this guild.
+ + if (PendingWar) + { + if (war.WarRequester) + { + number = 1063027; //
You have challenged this guild to war!
+ } + else + { + number = 1062969; //
This guild has challenged you to war!
+ + AddButtonAndBackground(20, 260, 5, 1062981); // Accept Challenge + AddButtonAndBackground(275, 260, 6, 1062983); // Modify Terms + } + + AddButtonAndBackground(20, 290, 7, 1062982); // Dismiss Challenge + } + else if (ActiveWar) + { + number = 1062965; //
You are at war with this guild!
+ AddButtonAndBackground(20, 290, 8, 1062980); // Surrender + } + else if (alliance != null && alliance == otherAlliance) // alliance, Same Alliance + { + if (alliance.IsMember(guild) && alliance.IsMember(m_Other)) // Both in Same alliance, full members + { + number = 1062970; //
You are allied with this guild.
+ + if (alliance.Leader == guild) + { + AddButtonAndBackground(20, 260, 12, 1062984); // Remove Guild from Alliance + AddButtonAndBackground( + 275, + 260, + 13, + 1063433 + ); // Promote to Alliance Leader //Note: No 'confirmation' like the other leader guild promotion things + // Remove guild from alliance //Promote to Alliance Leader + } + + // Show roster, Centered, up + AddButtonAndBackground(148, 215, 10, 1063164); // Show Alliance Roster + // Leave Alliance + AddButtonAndBackground(20, 290, 11, 1062985); // Leave Alliance + } + else if (alliance.Leader == guild && alliance.IsPendingMember(m_Other)) + { + number = 1062971; //
You have requested an alliance with this guild.
+ + // Show Alliance Roster, Centered, down. + AddButtonAndBackground(148, 245, 10, 1063164); // Show Alliance Roster + // Withdraw Request + AddButtonAndBackground(20, 290, 14, 1062986); // Withdraw Request + + AddHtml(150, 83, 360, 26, Color(alliance.Name, 0x99)); + } + else if (alliance.Leader == m_Other && alliance.IsPendingMember(guild)) + { + number = 1062972; //
This guild has requested an alliance.
+ + // Show alliance Roster, top + AddButtonAndBackground(148, 215, 10, 1063164); // Show Alliance Roster + // Deny Request + // Accept Request + AddButtonAndBackground(20, 260, 15, 1062988); // Deny Request + AddButtonAndBackground(20, 290, 16, 1062987); // Accept Request + + AddHtml(150, 83, 360, 26, Color(alliance.Name, 0x99)); + } + } + else + { + AddButtonAndBackground(20, 260, 2, 1062990); // Request Alliance + AddButtonAndBackground(20, 290, 1, 1062989); // Declare War! + } + + AddButtonAndBackground(275, 290, 0, 3000091); // Cancel + + AddHtmlLocalized(20, 180, 480, 30, number, 0x0, true); + AddImageTiled(20, 245, 480, 2, 0x2711); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (!(sender.Mobile is PlayerMobile pm && IsMember(pm, guild))) + return; + + var playerRank = pm.GuildRank; + + var guildLeader = Guild.GetAllianceLeader(guild); + var otherGuild = Guild.GetAllianceLeader(m_Other); + + var war = guildLeader.FindPendingWar(otherGuild); + var activeWar = guildLeader.FindActiveWar(otherGuild); + var otherWar = otherGuild.FindPendingWar(guildLeader); + + var alliance = guild.Alliance; + var otherAlliance = otherGuild.Alliance; + + switch (info.ButtonID) + { + case 5: // Accept the war + { + if (war?.WarRequester == false && activeWar == null) + { + if (!playerRank.GetFlag(RankFlags.ControlWarStatus)) + { + pm.SendLocalizedMessage(1063440); // You don't have permission to negotiate wars. + } + else if (alliance != null && alliance.Leader != guild) + { + pm.SendLocalizedMessage( + 1063239, + $"{guild.Name}\t{alliance.Name}" + ); // ~1_val~ is not the leader of the ~2_val~ alliance. + pm.SendLocalizedMessage( + 1070707, + alliance.Leader.Name + ); // You need to negotiate via ~1_val~ instead. + } + else + { + // Accept the war + guild.PendingWars.Remove(war); + war.WarBeginning = DateTime.UtcNow; + guild.AcceptedWars.Add(war); + + if (alliance?.IsMember(guild) == true) + { + alliance.AllianceMessage( + 1070769, + otherAlliance != null + ? otherAlliance.Name + : otherGuild.Name + ); // Guild Message: Your guild is now at war with ~1_GUILDNAME~ + alliance.InvalidateMemberProperties(); + } + else + { + guild.GuildMessage( + 1070769, + otherAlliance != null + ? otherAlliance.Name + : otherGuild.Name + ); // Guild Message: Your guild is now at war with ~1_GUILDNAME~ + guild.InvalidateMemberProperties(); + } + // Technically SHOULD say Your guild is now at war w/out any info, intentional diff. + + otherGuild.PendingWars.Remove(otherWar); + otherWar.WarBeginning = DateTime.UtcNow; + otherGuild.AcceptedWars.Add(otherWar); + + if (otherAlliance != null && m_Other.Alliance.IsMember(m_Other)) + { + otherAlliance.AllianceMessage( + 1070769, + alliance != null + ? alliance.Name + : guild.Name + ); // Guild Message: Your guild is now at war with ~1_GUILDNAME~ + otherAlliance.InvalidateMemberProperties(); + } + else + { + otherGuild.GuildMessage( + 1070769, + alliance != null + ? alliance.Name + : guild.Name + ); // Guild Message: Your guild is now at war with ~1_GUILDNAME~ + otherGuild.InvalidateMemberProperties(); + } + } + } + + break; + } + case 6: // Modify war terms + { + if (war?.WarRequester == false && activeWar == null) + { + if (!playerRank.GetFlag(RankFlags.ControlWarStatus)) + { + pm.SendLocalizedMessage(1063440); // You don't have permission to negotiate wars. + } + else if (alliance != null && alliance.Leader != guild) + { + pm.SendLocalizedMessage( + 1063239, + $"{guild.Name}\t{alliance.Name}" + ); // ~1_val~ is not the leader of the ~2_val~ alliance. + pm.SendLocalizedMessage( + 1070707, + alliance.Leader.Name + ); // You need to negotiate via ~1_val~ instead. + } + else + { + pm.SendGump(new WarDeclarationGump(pm, guild, otherGuild)); + } + } + + break; + } + case 7: // Dismiss war + { + if (war != null) + { + if (!playerRank.GetFlag(RankFlags.ControlWarStatus)) + { + pm.SendLocalizedMessage(1063440); // You don't have permission to negotiate wars. + } + else if (alliance != null && alliance.Leader != guild) + { + pm.SendLocalizedMessage( + 1063239, + $"{guild.Name}\t{alliance.Name}" + ); // ~1_val~ is not the leader of the ~2_val~ alliance. + pm.SendLocalizedMessage( + 1070707, + alliance.Leader.Name + ); // You need to negotiate via ~1_val~ instead. + } + else + { + // Dismiss the war + guild.PendingWars.Remove(war); + otherGuild.PendingWars.Remove(otherWar); + pm.SendLocalizedMessage(1070752); // The proposal has been updated. + // Messages to opposing guild? (Testing on OSI says no) + } + } + + break; + } + case 8: // Surrender + { + if (!playerRank.GetFlag(RankFlags.ControlWarStatus)) + { + pm.SendLocalizedMessage(1063440); // You don't have permission to negotiate wars. + } + else if (alliance != null && alliance.Leader != guild) + { + pm.SendLocalizedMessage( + 1063239, + $"{guild.Name}\t{alliance.Name}" + ); // ~1_val~ is not the leader of the ~2_val~ alliance. + pm.SendLocalizedMessage( + 1070707, + alliance.Leader.Name + ); // You need to negotiate via ~1_val~ instead. + } + else + { + if (activeWar != null) + { + if (alliance?.IsMember(guild) == true) + { + alliance.AllianceMessage( + 1070740, + otherAlliance != null + ? otherAlliance.Name + : otherGuild.Name + ); // You have lost the war with ~1_val~. + alliance.InvalidateMemberProperties(); + } + else + { + guild.GuildMessage( + 1070740, + otherAlliance != null + ? otherAlliance.Name + : otherGuild.Name + ); // You have lost the war with ~1_val~. + guild.InvalidateMemberProperties(); + } + + guild.AcceptedWars.Remove(activeWar); + + if (otherAlliance?.IsMember(otherGuild) == true) + { + otherAlliance.AllianceMessage( + 1070739, + guild.Alliance != null + ? guild.Alliance.Name + : guild.Name + ); // You have won the war against ~1_val~! + otherAlliance.InvalidateMemberProperties(); + } + else + { + otherGuild.GuildMessage( + 1070739, + guild.Alliance != null + ? guild.Alliance.Name + : guild.Name + ); // You have won the war against ~1_val~! + otherGuild.InvalidateMemberProperties(); + } + + otherGuild.AcceptedWars.Remove(otherGuild.FindActiveWar(guild)); + } + } + + break; + } + case 1: // Declare War + { + if (war == null && activeWar == null) + { + if (!playerRank.GetFlag(RankFlags.ControlWarStatus)) + { + pm.SendLocalizedMessage(1063440); // You don't have permission to negotiate wars. + } + else if (alliance != null && alliance.Leader != guild) + { + pm.SendLocalizedMessage( + 1063239, + $"{guild.Name}\t{alliance.Name}" + ); // ~1_val~ is not the leader of the ~2_val~ alliance. + pm.SendLocalizedMessage( + 1070707, + alliance.Leader.Name + ); // You need to negotiate via ~1_val~ instead. + } + else if (otherAlliance != null && otherAlliance.Leader != m_Other) + { + pm.SendLocalizedMessage( + 1063239, + $"{m_Other.Name}\t{otherAlliance.Name}" + ); // ~1_val~ is not the leader of the ~2_val~ alliance. + pm.SendLocalizedMessage( + 1070707, + otherAlliance.Leader.Name + ); // You need to negotiate via ~1_val~ instead. + } + else + { + pm.SendGump(new WarDeclarationGump(pm, guild, m_Other)); + } + } + + break; + } + + case 2: // Request Alliance + { + if (alliance == null) + { + if (!playerRank.GetFlag(RankFlags.AllianceControl)) + { + pm.SendLocalizedMessage(1070747); // You don't have permission to create an alliance. + } + else if (Faction.Find(guild.Leader) != Faction.Find(m_Other.Leader)) + { + pm.SendLocalizedMessage( + 1070758 + ); // You cannot propose an alliance to a guild with a different faction allegiance. + } + else if (otherAlliance != null) + { + if (otherAlliance.IsPendingMember(m_Other)) + pm.SendLocalizedMessage( + 1063416, + m_Other.Name + ); // ~1_val~ is currently considering another alliance proposal. + else + pm.SendLocalizedMessage( + 1063426, + m_Other.Name + ); // ~1_val~ already belongs to an alliance. + } + else if (m_Other.AcceptedWars.Count > 0 || m_Other.PendingWars.Count > 0) + { + pm.SendLocalizedMessage( + 1063427, + m_Other.Name + ); // ~1_val~ is currently involved in a guild war. + } + else if (guild.AcceptedWars.Count > 0 || guild.PendingWars.Count > 0) + { + pm.SendLocalizedMessage( + 1063427, + guild.Name + ); // ~1_val~ is currently involved in a guild war. + } + else + { + pm.SendLocalizedMessage(1063439); // Enter a name for the new alliance: + pm.BeginPrompt(CreateAlliance_Callback); + } + } + else + { + if (!playerRank.GetFlag(RankFlags.AllianceControl)) + { + pm.SendLocalizedMessage(1063436); // You don't have permission to negotiate an alliance. + } + else if (alliance.Leader != guild) + { + pm.SendLocalizedMessage( + 1063239, + $"{guild.Name}\t{alliance.Name}" + ); // ~1_val~ is not the leader of the ~2_val~ alliance. + } + else if (otherAlliance != null) + { + if (otherAlliance.IsPendingMember(m_Other)) + pm.SendLocalizedMessage( + 1063416, + m_Other.Name + ); // ~1_val~ is currently considering another alliance proposal. + else + pm.SendLocalizedMessage( + 1063426, + m_Other.Name + ); // ~1_val~ already belongs to an alliance. + } + else if (alliance.IsPendingMember(guild)) + { + pm.SendLocalizedMessage( + 1063416, + guild.Name + ); // ~1_val~ is currently considering another alliance proposal. + } + else if (m_Other.AcceptedWars.Count > 0 || m_Other.PendingWars.Count > 0) + { + pm.SendLocalizedMessage( + 1063427, + m_Other.Name + ); // ~1_val~ is currently involved in a guild war. + } + else if (guild.AcceptedWars.Count > 0 || guild.PendingWars.Count > 0) + { + pm.SendLocalizedMessage( + 1063427, + guild.Name + ); // ~1_val~ is currently involved in a guild war. + } + else if (Faction.Find(guild.Leader) != Faction.Find(m_Other.Leader)) + { + pm.SendLocalizedMessage( + 1070758 + ); // You cannot propose an alliance to a guild with a different faction allegiance. + } + else + { + pm.SendLocalizedMessage( + 1070750, + m_Other.Name + ); // An invitation to join your alliance has been sent to ~1_val~. + + m_Other.GuildMessage(1070780, guild.Name); // ~1_val~ has proposed an alliance. + + m_Other.Alliance = alliance; // Calls addPendingGuild + // alliance.AddPendingGuild( m_Other ); + } + } + + break; + } + case 10: // Show Alliance Roster + { + if (alliance != null && alliance == otherAlliance) + pm.SendGump(new AllianceInfo.AllianceRosterGump(pm, guild, alliance)); + + break; + } + case 11: // Leave Alliance + { + if (!playerRank.GetFlag(RankFlags.AllianceControl)) + { + pm.SendLocalizedMessage(1063436); // You don't have permission to negotiate an alliance. + } + else if (alliance?.IsMember(guild) == true) + { + guild.Alliance = null; // Calls alliance.Removeguild + // alliance.RemoveGuild( guild ); + + m_Other.InvalidateWarNotoriety(); + + guild.InvalidateMemberNotoriety(); + } + + break; + } + case 12: // Remove Guild from alliance + { + if (!playerRank.GetFlag(RankFlags.AllianceControl)) + { + pm.SendLocalizedMessage(1063436); // You don't have permission to negotiate an alliance. + } + else if (alliance != null && alliance.Leader != guild) + { + pm.SendLocalizedMessage( + 1063239, + $"{guild.Name}\t{alliance.Name}" + ); // ~1_val~ is not the leader of the ~2_val~ alliance. + } + else if (alliance?.IsMember(guild) == true && alliance.IsMember(m_Other)) + { + m_Other.Alliance = null; + + m_Other.InvalidateMemberNotoriety(); + + guild.InvalidateWarNotoriety(); + } + + break; + } + case 13: // Promote to Alliance leader + { + if (!playerRank.GetFlag(RankFlags.AllianceControl)) + { + pm.SendLocalizedMessage(1063436); // You don't have permission to negotiate an alliance. + } + else if (alliance != null && alliance.Leader != guild) + { + pm.SendLocalizedMessage( + 1063239, + $"{guild.Name}\t{alliance.Name}" + ); // ~1_val~ is not the leader of the ~2_val~ alliance. + } + else if (alliance?.IsMember(guild) == true && alliance.IsMember(m_Other)) + { + pm.SendLocalizedMessage( + 1063434, + $"{m_Other.Name}\t{alliance.Name}" + ); // ~1_val~ is now the leader of ~2_val~. + + alliance.Leader = m_Other; + } + + break; + } + case 14: // Withdraw Request + { + if (!playerRank.GetFlag(RankFlags.AllianceControl)) + { + pm.SendLocalizedMessage(1063436); // You don't have permission to negotiate an alliance. + } + else if (alliance != null && alliance.Leader == guild && alliance.IsPendingMember(m_Other)) + { + m_Other.Alliance = null; + pm.SendLocalizedMessage(1070752); // The proposal has been updated. + } + + break; + } + case 15: // Deny Alliance Request + { + if (!playerRank.GetFlag(RankFlags.AllianceControl)) + { + pm.SendLocalizedMessage(1063436); // You don't have permission to negotiate an alliance. + } + else if (alliance != null && otherAlliance != null && alliance.Leader == m_Other && + otherAlliance.IsPendingMember(guild)) + { + // The proposal has been updated. + // m_Other.GuildMessage( 1070782 ); + // // ~1_val~ has responded to your proposal. + // //Per OSI commented out. + pm.SendLocalizedMessage(1070752); + guild.Alliance = null; + } + + break; + } + case 16: // Accept Alliance Request + { + if (!playerRank.GetFlag(RankFlags.AllianceControl)) + { + pm.SendLocalizedMessage(1063436); // You don't have permission to negotiate an alliance. + } + else if (otherAlliance != null && otherAlliance.Leader == m_Other && + otherAlliance.IsPendingMember(guild)) + { + pm.SendLocalizedMessage(1070752); // The proposal has been updated. + + otherAlliance + .TurnToMember( + m_Other + ); // No need to verify it's in the guild or already a member, the function does this + + otherAlliance.TurnToMember(guild); + } + + break; + } + } + } + + public void CreateAlliance_Callback(Mobile from, string text) + { + if (!(from is PlayerMobile pm)) + return; + + var alliance = guild.Alliance; + var otherAlliance = m_Other.Alliance; + + if (!IsMember(from, guild) || alliance != null) + return; + + var playerRank = pm.GuildRank; + + if (!playerRank.GetFlag(RankFlags.AllianceControl)) + { + pm.SendLocalizedMessage(1070747); // You don't have permission to create an alliance. + } + else if (Faction.Find(guild.Leader) != Faction.Find(m_Other.Leader)) + { + // Notes about this: OSI only cares/checks when proposing, you can change your faction all you want later. + pm.SendLocalizedMessage( + 1070758 + ); // You cannot propose an alliance to a guild with a different faction allegiance. + } + else if (otherAlliance != null) + { + if (otherAlliance.IsPendingMember(m_Other)) + pm.SendLocalizedMessage( + 1063416, + m_Other.Name + ); // ~1_val~ is currently considering another alliance proposal. + else + pm.SendLocalizedMessage(1063426, m_Other.Name); // ~1_val~ already belongs to an alliance. + } + else if (m_Other.AcceptedWars.Count > 0 || m_Other.PendingWars.Count > 0) + { + pm.SendLocalizedMessage(1063427, m_Other.Name); // ~1_val~ is currently involved in a guild war. + } + else if (guild.AcceptedWars.Count > 0 || guild.PendingWars.Count > 0) + { + pm.SendLocalizedMessage(1063427, guild.Name); // ~1_val~ is currently involved in a guild war. + } + else + { + var name = Utility.FixHtml(text.Trim()); + + if (!CheckProfanity(name)) + { + pm.SendLocalizedMessage(1070886); // That alliance name is not allowed. + } + else if (name.Length > Guild.NameLimit) + { + pm.SendLocalizedMessage( + 1070887, + Guild.NameLimit.ToString() + ); // An alliance name cannot exceed ~1_val~ characters in length. + } + else if (AllianceInfo.Alliances.ContainsKey(name.ToLower())) + { + pm.SendLocalizedMessage(1063428); // That alliance name is not available. + } + else + { + pm.SendLocalizedMessage( + 1070750, + m_Other.Name + ); // An invitation to join your alliance has been sent to ~1_val~. + + m_Other.GuildMessage(1070780, guild.Name); // ~1_val~ has proposed an alliance. + + new AllianceInfo(guild, name, m_Other); + } + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/New Guild System/War Declaration gump.cs b/Projects/UOContent/Gumps/Guilds/New Guild System/War Declaration gump.cs index de47fde2b..e479ffe69 100644 --- a/Projects/UOContent/Gumps/Guilds/New Guild System/War Declaration gump.cs +++ b/Projects/UOContent/Gumps/Guilds/New Guild System/War Declaration gump.cs @@ -1,137 +1,154 @@ -using System; -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Guilds -{ - public class WarDeclarationGump : BaseGuildGump - { - private readonly Guild m_Other; - - public WarDeclarationGump(PlayerMobile pm, Guild g, Guild otherGuild) : base(pm, g) - { - m_Other = otherGuild; - WarDeclaration war = g.FindPendingWar(otherGuild); - - AddPage(0); - - AddBackground(0, 0, 500, 340, 0x24AE); - AddBackground(65, 50, 370, 30, 0x2486); - AddHtmlLocalized(75, 55, 370, 26, 1062979, 0x3C00); //
Declaration of War
- AddImage(410, 45, 0x232C); - AddHtmlLocalized(65, 95, 200, 20, 1063009, 0x14AF); // Duration of War - AddHtmlLocalized(65, 120, 400, 20, 1063010, 0x0); // Enter the number of hours the war will last. - AddBackground(65, 150, 40, 30, 0x2486); - AddTextEntry(70, 154, 50, 30, 0x481, 10, war?.WarLength.Hours.ToString() ?? "0"); - AddHtmlLocalized(65, 195, 200, 20, 1063011, 0x14AF); // Victory Condition - AddHtmlLocalized(65, 220, 400, 20, 1063012, 0x0); // Enter the winning number of kills. - AddBackground(65, 250, 40, 30, 0x2486); - AddTextEntry(70, 254, 50, 30, 0x481, 11, war?.MaxKills.ToString() ?? "0"); - AddBackground(190, 270, 130, 26, 0x2486); - AddButton(195, 275, 0x845, 0x846, 0); - AddHtmlLocalized(220, 273, 90, 26, 1006045, 0x0); // Cancel - AddBackground(330, 270, 130, 26, 0x2486); - AddButton(335, 275, 0x845, 0x846, 1); - AddHtmlLocalized(360, 273, 90, 26, 1062989, 0x5000); // Declare War! - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - PlayerMobile pm = sender.Mobile as PlayerMobile; - - if (!IsMember(pm, guild)) - return; - - RankDefinition playerRank = pm.GuildRank; - - switch (info.ButtonID) - { - case 1: - { - AllianceInfo alliance = guild.Alliance; - AllianceInfo otherAlliance = m_Other.Alliance; - - if (!playerRank.GetFlag(RankFlags.ControlWarStatus)) - { - pm.SendLocalizedMessage(1063440); // You don't have permission to negotiate wars. - } - else if (alliance != null && alliance.Leader != guild) - { - pm.SendLocalizedMessage(1063239, - $"{guild.Name}\t{alliance.Name}"); // ~1_val~ is not the leader of the ~2_val~ alliance. - pm.SendLocalizedMessage(1070707, alliance.Leader.Name); // You need to negotiate via ~1_val~ instead. - } - else if (otherAlliance != null && otherAlliance.Leader != m_Other) - { - pm.SendLocalizedMessage(1063239, - $"{m_Other.Name}\t{otherAlliance.Name}"); // ~1_val~ is not the leader of the ~2_val~ alliance. - pm.SendLocalizedMessage(1070707, - otherAlliance.Leader.Name); // You need to negotiate via ~1_val~ instead. - } - else - { - WarDeclaration activeWar = guild.FindActiveWar(m_Other); - - if (activeWar == null) - { - WarDeclaration war = guild.FindPendingWar(m_Other); - WarDeclaration otherWar = m_Other.FindPendingWar(guild); - - // Note: OSI differs from what it says on website. unlimited war = 0 kills/ 0 hrs. Not > 999. (sidenote: they both cap at 65535, 7.5 years, but, still.) - TextRelay tKills = info.GetTextEntry(11); - TextRelay tWarLength = info.GetTextEntry(10); - - int maxKills = tKills == null - ? 0 : Math.Clamp(Utility.ToInt32(info.GetTextEntry(11).Text), 0, 0xFFFF); - TimeSpan warLength = TimeSpan.FromHours(tWarLength == null ? 0 - : Math.Clamp(Utility.ToInt32(info.GetTextEntry(10).Text), 0, 0xFFFF)); - - if (war != null) - { - war.MaxKills = maxKills; - war.WarLength = warLength; - war.WarRequester = true; - } - else - { - guild.PendingWars.Add(new WarDeclaration(guild, m_Other, maxKills, warLength, true)); - } - - if (otherWar != null) - { - otherWar.MaxKills = maxKills; - otherWar.WarLength = warLength; - otherWar.WarRequester = false; - } - else - { - m_Other.PendingWars.Add(new WarDeclaration(m_Other, guild, maxKills, warLength, false)); - } - - if (war != null) - pm.SendLocalizedMessage(1070752); // The proposal has been updated. - else - m_Other.GuildMessage(1070781, - guild.Alliance != null - ? guild.Alliance.Name - : guild.Name); // ~1_val~ has proposed a war. - - pm.SendLocalizedMessage(1070751, - m_Other.Alliance != null - ? m_Other.Alliance.Name - : m_Other.Name); // War proposal has been sent to ~1_val~. - } - } - - break; - } - default: - { - pm.SendGump(new OtherGuildInfo(pm, guild, m_Other)); - break; - } - } - } - } -} +using System; +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Guilds +{ + public class WarDeclarationGump : BaseGuildGump + { + private readonly Guild m_Other; + + public WarDeclarationGump(PlayerMobile pm, Guild g, Guild otherGuild) : base(pm, g) + { + m_Other = otherGuild; + var war = g.FindPendingWar(otherGuild); + + AddPage(0); + + AddBackground(0, 0, 500, 340, 0x24AE); + AddBackground(65, 50, 370, 30, 0x2486); + AddHtmlLocalized(75, 55, 370, 26, 1062979, 0x3C00); //
Declaration of War
+ AddImage(410, 45, 0x232C); + AddHtmlLocalized(65, 95, 200, 20, 1063009, 0x14AF); // Duration of War + AddHtmlLocalized(65, 120, 400, 20, 1063010, 0x0); // Enter the number of hours the war will last. + AddBackground(65, 150, 40, 30, 0x2486); + AddTextEntry(70, 154, 50, 30, 0x481, 10, war?.WarLength.Hours.ToString() ?? "0"); + AddHtmlLocalized(65, 195, 200, 20, 1063011, 0x14AF); // Victory Condition + AddHtmlLocalized(65, 220, 400, 20, 1063012, 0x0); // Enter the winning number of kills. + AddBackground(65, 250, 40, 30, 0x2486); + AddTextEntry(70, 254, 50, 30, 0x481, 11, war?.MaxKills.ToString() ?? "0"); + AddBackground(190, 270, 130, 26, 0x2486); + AddButton(195, 275, 0x845, 0x846, 0); + AddHtmlLocalized(220, 273, 90, 26, 1006045, 0x0); // Cancel + AddBackground(330, 270, 130, 26, 0x2486); + AddButton(335, 275, 0x845, 0x846, 1); + AddHtmlLocalized(360, 273, 90, 26, 1062989, 0x5000); // Declare War! + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var pm = sender.Mobile as PlayerMobile; + + if (!IsMember(pm, guild)) + return; + + var playerRank = pm.GuildRank; + + switch (info.ButtonID) + { + case 1: + { + var alliance = guild.Alliance; + var otherAlliance = m_Other.Alliance; + + if (!playerRank.GetFlag(RankFlags.ControlWarStatus)) + { + pm.SendLocalizedMessage(1063440); // You don't have permission to negotiate wars. + } + else if (alliance != null && alliance.Leader != guild) + { + pm.SendLocalizedMessage( + 1063239, + $"{guild.Name}\t{alliance.Name}" + ); // ~1_val~ is not the leader of the ~2_val~ alliance. + pm.SendLocalizedMessage( + 1070707, + alliance.Leader.Name + ); // You need to negotiate via ~1_val~ instead. + } + else if (otherAlliance != null && otherAlliance.Leader != m_Other) + { + pm.SendLocalizedMessage( + 1063239, + $"{m_Other.Name}\t{otherAlliance.Name}" + ); // ~1_val~ is not the leader of the ~2_val~ alliance. + pm.SendLocalizedMessage( + 1070707, + otherAlliance.Leader.Name + ); // You need to negotiate via ~1_val~ instead. + } + else + { + var activeWar = guild.FindActiveWar(m_Other); + + if (activeWar == null) + { + var war = guild.FindPendingWar(m_Other); + var otherWar = m_Other.FindPendingWar(guild); + + // Note: OSI differs from what it says on website. unlimited war = 0 kills/ 0 hrs. Not > 999. (sidenote: they both cap at 65535, 7.5 years, but, still.) + var tKills = info.GetTextEntry(11); + var tWarLength = info.GetTextEntry(10); + + var maxKills = tKills == null + ? 0 + : Math.Clamp(Utility.ToInt32(info.GetTextEntry(11).Text), 0, 0xFFFF); + var warLength = TimeSpan.FromHours( + tWarLength == null + ? 0 + : Math.Clamp(Utility.ToInt32(info.GetTextEntry(10).Text), 0, 0xFFFF) + ); + + if (war != null) + { + war.MaxKills = maxKills; + war.WarLength = warLength; + war.WarRequester = true; + } + else + { + guild.PendingWars.Add(new WarDeclaration(guild, m_Other, maxKills, warLength, true)); + } + + if (otherWar != null) + { + otherWar.MaxKills = maxKills; + otherWar.WarLength = warLength; + otherWar.WarRequester = false; + } + else + { + m_Other.PendingWars.Add(new WarDeclaration(m_Other, guild, maxKills, warLength, false)); + } + + if (war != null) + pm.SendLocalizedMessage(1070752); // The proposal has been updated. + else + m_Other.GuildMessage( + 1070781, + guild.Alliance != null + ? guild.Alliance.Name + : guild.Name + ); // ~1_val~ has proposed a war. + + pm.SendLocalizedMessage( + 1070751, + m_Other.Alliance != null + ? m_Other.Alliance.Name + : m_Other.Name + ); // War proposal has been sent to ~1_val~. + } + } + + break; + } + default: + { + pm.SendGump(new OtherGuildInfo(pm, guild, m_Other)); + break; + } + } + } + } +} diff --git a/Projects/UOContent/Gumps/Guilds/RecruitTarget.cs b/Projects/UOContent/Gumps/Guilds/RecruitTarget.cs index adb1117c1..1c3834939 100644 --- a/Projects/UOContent/Gumps/Guilds/RecruitTarget.cs +++ b/Projects/UOContent/Gumps/Guilds/RecruitTarget.cs @@ -1,91 +1,93 @@ -using Server.Factions; -using Server.Guilds; -using Server.Targeting; - -namespace Server.Gumps -{ - public class GuildRecruitTarget : Target - { - private readonly Guild m_Guild; - private readonly Mobile m_Mobile; - - public GuildRecruitTarget(Mobile m, Guild guild) : base(10, false, TargetFlags.None) - { - m_Mobile = m; - m_Guild = guild; - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (GuildGump.BadMember(m_Mobile, m_Guild)) - return; - - if (targeted is Mobile m) - { - PlayerState guildState = PlayerState.Find(m_Guild.Leader); - PlayerState targetState = PlayerState.Find(m); - - Faction guildFaction = guildState?.Faction; - Faction targetFaction = targetState?.Faction; - - if (!m.Player) - { - m_Mobile.SendLocalizedMessage(501161); // You may only recruit players into the guild. - } - else if (!m.Alive) - { - m_Mobile.SendLocalizedMessage(501162); // Only the living may be recruited. - } - else if (m_Guild.IsMember(m)) - { - m_Mobile.SendLocalizedMessage(501163); // They are already a guildmember! - } - else if (m_Guild.Candidates.Contains(m)) - { - m_Mobile.SendLocalizedMessage(501164); // They are already a candidate. - } - else if (m_Guild.Accepted.Contains(m)) - { - m_Mobile.SendLocalizedMessage( - 501165); // They have already been accepted for membership, and merely need to use the Guildstone to gain full membership. - } - else if (m.Guild != null) - { - m_Mobile.SendLocalizedMessage(501166); // You can only recruit candidates who are not already in a guild. - } - else if (guildFaction != targetFaction) - { - if (guildFaction == null) - m_Mobile.SendLocalizedMessage(1013027); // That player cannot join a non-faction guild. - else if (targetFaction == null) - m_Mobile.SendLocalizedMessage( - 1013026); // That player must be in a faction before joining this guild. - else - m_Mobile.SendLocalizedMessage(1013028); // That person has a different faction affiliation. - } - else if (targetState?.IsLeaving == true) - { - // OSI does this quite strangely, so we'll just do it this way - m_Mobile.SendMessage("That person is quitting their faction and so you may not recruit them."); - } - else if (m_Mobile.AccessLevel >= AccessLevel.GameMaster || m_Guild.Leader == m_Mobile) - { - m_Guild.Accepted.Add(m); - } - else - { - m_Guild.Candidates.Add(m); - } - } - } - - protected override void OnTargetFinish(Mobile from) - { - if (GuildGump.BadMember(m_Mobile, m_Guild)) - return; - - GuildGump.EnsureClosed(m_Mobile); - m_Mobile.SendGump(new GuildGump(m_Mobile, m_Guild)); - } - } -} +using Server.Factions; +using Server.Guilds; +using Server.Targeting; + +namespace Server.Gumps +{ + public class GuildRecruitTarget : Target + { + private readonly Guild m_Guild; + private readonly Mobile m_Mobile; + + public GuildRecruitTarget(Mobile m, Guild guild) : base(10, false, TargetFlags.None) + { + m_Mobile = m; + m_Guild = guild; + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (GuildGump.BadMember(m_Mobile, m_Guild)) + return; + + if (targeted is Mobile m) + { + var guildState = PlayerState.Find(m_Guild.Leader); + var targetState = PlayerState.Find(m); + + var guildFaction = guildState?.Faction; + var targetFaction = targetState?.Faction; + + if (!m.Player) + { + m_Mobile.SendLocalizedMessage(501161); // You may only recruit players into the guild. + } + else if (!m.Alive) + { + m_Mobile.SendLocalizedMessage(501162); // Only the living may be recruited. + } + else if (m_Guild.IsMember(m)) + { + m_Mobile.SendLocalizedMessage(501163); // They are already a guildmember! + } + else if (m_Guild.Candidates.Contains(m)) + { + m_Mobile.SendLocalizedMessage(501164); // They are already a candidate. + } + else if (m_Guild.Accepted.Contains(m)) + { + m_Mobile.SendLocalizedMessage( + 501165 + ); // They have already been accepted for membership, and merely need to use the Guildstone to gain full membership. + } + else if (m.Guild != null) + { + m_Mobile.SendLocalizedMessage(501166); // You can only recruit candidates who are not already in a guild. + } + else if (guildFaction != targetFaction) + { + if (guildFaction == null) + m_Mobile.SendLocalizedMessage(1013027); // That player cannot join a non-faction guild. + else if (targetFaction == null) + m_Mobile.SendLocalizedMessage( + 1013026 + ); // That player must be in a faction before joining this guild. + else + m_Mobile.SendLocalizedMessage(1013028); // That person has a different faction affiliation. + } + else if (targetState?.IsLeaving == true) + { + // OSI does this quite strangely, so we'll just do it this way + m_Mobile.SendMessage("That person is quitting their faction and so you may not recruit them."); + } + else if (m_Mobile.AccessLevel >= AccessLevel.GameMaster || m_Guild.Leader == m_Mobile) + { + m_Guild.Accepted.Add(m); + } + else + { + m_Guild.Candidates.Add(m); + } + } + } + + protected override void OnTargetFinish(Mobile from) + { + if (GuildGump.BadMember(m_Mobile, m_Guild)) + return; + + GuildGump.EnsureClosed(m_Mobile); + m_Mobile.SendGump(new GuildGump(m_Mobile, m_Guild)); + } + } +} diff --git a/Projects/UOContent/Gumps/HeritageTokenGump.cs b/Projects/UOContent/Gumps/HeritageTokenGump.cs index 63eae3c00..28a873f93 100644 --- a/Projects/UOContent/Gumps/HeritageTokenGump.cs +++ b/Projects/UOContent/Gumps/HeritageTokenGump.cs @@ -1,578 +1,579 @@ -using System; -using System.Collections.Generic; -using Server.Items; -using Server.Network; - -namespace Server.Gumps -{ - public class HeritageTokenGump : Gump - { - private readonly HeritageToken m_Token; - - public HeritageTokenGump(HeritageToken token) : base(60, 36) - { - m_Token = token; - - AddPage(0); - - AddBackground(0, 0, 520, 404, 0x13BE); - AddImageTiled(10, 10, 500, 20, 0xA40); - AddImageTiled(10, 40, 500, 324, 0xA40); - AddImageTiled(10, 374, 500, 20, 0xA40); - AddAlphaRegion(10, 10, 500, 384); - AddButton(10, 374, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(45, 376, 450, 20, 1060051, 0x7FFF); // CANCEL - AddHtmlLocalized(14, 12, 500, 20, 1075576, 0x7FFF); // Choose your item from the following pages - - AddPage(1); - - AddImageTiledButton(14, 44, 0x918, 0x919, 0x64, GumpButtonType.Reply, 0, 0x1411, 0x2C, 18, 8); - AddTooltip(1062912); - AddHtmlLocalized(98, 44, 250, 60, 1078147, 0x7FFF); // Royal Leggings of Embers - AddImageTiledButton(264, 44, 0x918, 0x919, 0x65, GumpButtonType.Reply, 0, 0x234D, 0x0, 18, 12); - AddTooltip(1062914); - AddHtmlLocalized(348, 44, 250, 60, 1062913, 0x7FFF); // Rose of Trinsic - AddImageTiledButton(14, 108, 0x918, 0x919, 0x66, GumpButtonType.Reply, 0, 0x26C3, 0x504, 18, 8); - AddTooltip(1062916); - AddHtmlLocalized(98, 108, 250, 60, 1062915, 0x7FFF); // Shamino’s Best Crossbow - AddImageTiledButton(264, 108, 0x918, 0x919, 0x67, GumpButtonType.Reply, 0, 0x3F1D, 0x0, 18, 8); - AddTooltip(1062918); - AddHtmlLocalized(348, 108, 250, 60, 1062917, 0x7FFF); // The Tapestry of Sosaria - AddImageTiledButton(14, 172, 0x918, 0x919, 0x68, GumpButtonType.Reply, 0, 0x3F14, 0x0, 18, 8); - AddTooltip(1062920); - AddHtmlLocalized(98, 172, 250, 60, 1062919, 0x7FFF); // Hearth of the Home Fire - AddImageTiledButton(264, 172, 0x918, 0x919, 0x69, GumpButtonType.Reply, 0, 0xF60, 0x482, -1, 10); - AddTooltip(1062922); - AddHtmlLocalized(348, 172, 250, 60, 1062921, 0x7FFF); // The Holy Sword - AddImageTiledButton(14, 236, 0x918, 0x919, 0x6A, GumpButtonType.Reply, 0, 0x236C, 0x0, 18, 6); - AddTooltip(1062924); - AddHtmlLocalized(98, 236, 250, 60, 1062923, 0x7FFF); // Ancient Samurai Helm - AddImageTiledButton(264, 236, 0x918, 0x919, 0x6B, GumpButtonType.Reply, 0, 0x2B10, 0x226, 18, 11); - AddTooltip(1075223); - AddHtmlLocalized(348, 236, 250, 60, 1075188, 0x7FFF); // Helm of Spirituality - AddImageTiledButton(14, 300, 0x918, 0x919, 0x6C, GumpButtonType.Reply, 0, 0x2B0C, 0x226, 18, 15); - AddTooltip(1075224); - AddHtmlLocalized(98, 300, 250, 60, 1075192, 0x7FFF); // Gauntlets of Valor - AddImageTiledButton(264, 300, 0x918, 0x919, 0x6D, GumpButtonType.Reply, 0, 0x2B01, 0x0, 18, 9); - AddTooltip(1075225); - AddHtmlLocalized(348, 300, 250, 60, 1075196, 0x7FFF); // Dupre’s Shield - AddButton(400, 374, 0xFA5, 0xFA7, 0, GumpButtonType.Page, 2); - AddHtmlLocalized(440, 376, 60, 20, 1043353, 0x7FFF); // Next - - AddPage(2); - - AddButton(300, 374, 0xFAE, 0xFB0, 0, GumpButtonType.Page, 1); - AddHtmlLocalized(340, 376, 60, 20, 1011393, 0x7FFF); // Back - AddImageTiledButton(14, 44, 0x918, 0x919, 0x6E, GumpButtonType.Reply, 0, 0x2AC6, 0x0, 29, 0); - AddTooltip(1075226); - AddHtmlLocalized(98, 44, 250, 60, 1075197, 0x7FFF); // Fountain of Life - AddImageTiledButton(264, 44, 0x918, 0x919, 0x6F, GumpButtonType.Reply, 0, 0x2AF9, 0x0, -4, -5); - AddTooltip(1075227); - AddHtmlLocalized(348, 44, 250, 60, 1075198, 0x7FFF); // Dawn’s Music Box - AddImageTiledButton(14, 108, 0x918, 0x919, 0x70, GumpButtonType.Reply, 0, 0x2253, 0x0, 18, 12); - AddTooltip(1075228); - AddHtmlLocalized(98, 108, 250, 60, 1078148, 0x7FFF); // Ossian Grimoire - AddImageTiledButton(264, 108, 0x918, 0x919, 0x71, GumpButtonType.Reply, 0, 0x2D98, 0x0, 19, 13); - AddTooltip(1078527); - AddHtmlLocalized(348, 108, 250, 60, 1078142, 0x7FFF); // Talisman of the Fey:
Ferret - AddImageTiledButton(14, 172, 0x918, 0x919, 0x72, GumpButtonType.Reply, 0, 0x2D97, 0x0, 19, 13); - AddTooltip(1078528); - AddHtmlLocalized(98, 172, 250, 60, 1078143, 0x7FFF); // Talisman of the Fey:
Squirrel - AddImageTiledButton(264, 172, 0x918, 0x919, 0x73, GumpButtonType.Reply, 0, 0x2D96, 0x0, 19, 8); - AddTooltip(1078529); - AddHtmlLocalized(348, 172, 250, 60, 1078144, 0x7FFF); // Talisman of the Fey:
Cu Sidhe - AddImageTiledButton(14, 236, 0x918, 0x919, 0x74, GumpButtonType.Reply, 0, 0x2D95, 0x0, -4, 2); - AddTooltip(1078530); - AddHtmlLocalized(98, 236, 250, 60, 1078145, 0x7FFF); // Talisman of the Fey:
Reptalon - AddImageTiledButton(264, 236, 0x918, 0x919, 0x75, GumpButtonType.Reply, 0, 0x2B02, 0x0, -2, 9); - AddTooltip(1078526); - AddHtmlLocalized(348, 236, 250, 60, 1075201, 0x7FFF); // Quiver of Infinity - AddImageTiledButton(14, 300, 0x918, 0x919, 0x76, GumpButtonType.Reply, 0, 0x2A91, 0x0, 25, 5); - AddTooltip(1075986); - AddHtmlLocalized(98, 300, 250, 60, 1074797, 0x7FFF); // Bone Throne, Bone Couch
and Bone Table - AddImageTiledButton(264, 300, 0x918, 0x919, 0x77, GumpButtonType.Reply, 0, 0x2A99, 0x0, 18, 1); - AddTooltip(1075987); - AddHtmlLocalized(348, 300, 250, 60, 1078146, 0x7FFF); // Creepy Portraits - AddButton(400, 374, 0xFA5, 0xFA7, 0, GumpButtonType.Page, 3); - AddHtmlLocalized(440, 376, 60, 20, 1043353, 0x7FFF); // Next - - AddPage(3); - - AddButton(300, 374, 0xFAE, 0xFB0, 0, GumpButtonType.Page, 2); - AddHtmlLocalized(340, 376, 60, 20, 1011393, 0x7FFF); // Back - AddImageTiledButton(14, 44, 0x918, 0x919, 0x78, GumpButtonType.Reply, 0, 0x2A71, 0x0, 13, 5); - AddTooltip(1075988); - AddHtmlLocalized(98, 44, 250, 60, 1074799, 0x7FFF); // Mounted Pixies (5) - AddImageTiledButton(264, 44, 0x918, 0x919, 0x79, GumpButtonType.Reply, 0, 0x2A98, 0x0, 26, 1); - AddTooltip(1075990); - AddHtmlLocalized(348, 44, 250, 60, 1074800, 0x7FFF); // Haunted Mirror - AddImageTiledButton(14, 108, 0x918, 0x919, 0x7A, GumpButtonType.Reply, 0, 0x2A92, 0x0, 18, 1); - AddTooltip(1075989); - AddHtmlLocalized(98, 108, 250, 60, 1074801, 0x7FFF); // Bed of Nails - AddImageTiledButton(264, 108, 0x918, 0x919, 0x7B, GumpButtonType.Reply, 0, 0x2AB8, 0x0, 18, 1); - AddTooltip(1075991); - AddHtmlLocalized(348, 108, 250, 60, 1074818, 0x7FFF); // Sacrificial Altar - AddImageTiledButton(14, 172, 0x918, 0x919, 0x7C, GumpButtonType.Reply, 0, 0x3F26, 0x0, 18, 8); - AddTooltip(1076610); - AddHtmlLocalized(98, 172, 250, 60, 1076257, 0x7FFF); // Broken Covered Chair - AddImageTiledButton(264, 172, 0x918, 0x919, 0x7D, GumpButtonType.Reply, 0, 0x3F22, 0x0, 18, 8); - AddTooltip(1076610); - AddHtmlLocalized(348, 172, 250, 60, 1076258, 0x7FFF); // Broken Bookcase - AddImageTiledButton(14, 236, 0x918, 0x919, 0x7E, GumpButtonType.Reply, 0, 0x3F24, 0x0, 18, 8); - AddTooltip(1076610); - AddHtmlLocalized(98, 236, 250, 60, 1076259, 0x7FFF); // Standing Broken Chair - AddImageTiledButton(264, 236, 0x918, 0x919, 0x7F, GumpButtonType.Reply, 0, 0x3F25, 0x0, 18, 8); - AddTooltip(1076610); - AddHtmlLocalized(348, 236, 250, 60, 1076260, 0x7FFF); // Broken Vanity - AddImageTiledButton(14, 300, 0x918, 0x919, 0x80, GumpButtonType.Reply, 0, 0x3F23, 0x0, 18, 8); - AddTooltip(1076610); - AddHtmlLocalized(98, 300, 250, 60, 1076261, 0x7FFF); // Broken Chest of Drawers - AddImageTiledButton(264, 300, 0x918, 0x919, 0x81, GumpButtonType.Reply, 0, 0x3F21, 0x0, 18, 8); - AddTooltip(1076610); - AddHtmlLocalized(348, 300, 250, 60, 1076262, 0x7FFF); // Broken Armoire - AddButton(400, 374, 0xFA5, 0xFA7, 0, GumpButtonType.Page, 4); - AddHtmlLocalized(440, 376, 60, 20, 1043353, 0x7FFF); // Next - - AddPage(4); - - AddButton(300, 374, 0xFAE, 0xFB0, 0, GumpButtonType.Page, 3); - AddHtmlLocalized(340, 376, 60, 20, 1011393, 0x7FFF); // Back - AddImageTiledButton(14, 44, 0x918, 0x919, 0x82, GumpButtonType.Reply, 0, 0x3F0B, 0x0, 18, 8); - AddTooltip(1076610); - AddHtmlLocalized(98, 44, 250, 60, 1076263, 0x7FFF); // Broken Bed - AddImageTiledButton(264, 44, 0x918, 0x919, 0x83, GumpButtonType.Reply, 0, 0xC19, 0x0, 13, 8); - AddTooltip(1076610); - AddHtmlLocalized(348, 44, 250, 60, 1076264, 0x7FFF); // Broken Fallen Chair - AddImageTiledButton(14, 108, 0x918, 0x919, 0x84, GumpButtonType.Reply, 0, 0x3DAA, 0x0, 20, -3); - AddTooltip(1076611); - AddHtmlLocalized(98, 108, 250, 60, 1076265, 0x7FFF); // Suit of Gold Armor - AddImageTiledButton(264, 108, 0x918, 0x919, 0x85, GumpButtonType.Reply, 0, 0x151C, 0x0, -20, -3); - AddTooltip(1076612); - AddHtmlLocalized(348, 108, 250, 60, 1076266, 0x7FFF); // Suit of Silver Armor - AddImageTiledButton(14, 172, 0x918, 0x919, 0x86, GumpButtonType.Reply, 0, 0x3DB1, 0x0, 18, 8); - AddTooltip(1076613); - AddHtmlLocalized(98, 172, 250, 60, 1076267, 0x7FFF); // Boiling Cauldron - AddImageTiledButton(264, 172, 0x918, 0x919, 0x87, GumpButtonType.Reply, 0, 0x3F27, 0x0, 18, 8); - AddTooltip(1076614); - AddHtmlLocalized(348, 172, 250, 60, 1024656, 0x7FFF); // Guillotine - AddImageTiledButton(14, 236, 0x918, 0x919, 0x88, GumpButtonType.Reply, 0, 0x3F0C, 0x0, 18, 8); - AddTooltip(1076615); - AddHtmlLocalized(98, 236, 250, 60, 1076268, 0x7FFF); // Cherry Blossom Tree - AddImageTiledButton(264, 236, 0x918, 0x919, 0x89, GumpButtonType.Reply, 0, 0x3F07, 0x0, 18, 8); - AddTooltip(1076616); - AddHtmlLocalized(348, 236, 250, 60, 1076269, 0x7FFF); // Apple Tree - AddImageTiledButton(14, 300, 0x918, 0x919, 0x8A, GumpButtonType.Reply, 0, 0x3F16, 0x0, 18, 8); - AddTooltip(1076617); - AddHtmlLocalized(98, 300, 250, 60, 1076270, 0x7FFF); // Peach Tree - AddImageTiledButton(264, 300, 0x918, 0x919, 0x8B, GumpButtonType.Reply, 0, 0x3F12, 0x0, 18, 8); - AddTooltip(1076618); - AddHtmlLocalized(348, 300, 250, 60, 1076271, 0x7FFF); // Hanging Axes - AddButton(400, 374, 0xFA5, 0xFA7, 0, GumpButtonType.Page, 5); - AddHtmlLocalized(440, 376, 60, 20, 1043353, 0x7FFF); // Next - - AddPage(5); - - AddButton(300, 374, 0xFAE, 0xFB0, 0, GumpButtonType.Page, 4); - AddHtmlLocalized(340, 376, 60, 20, 1011393, 0x7FFF); // Back - AddImageTiledButton(14, 44, 0x918, 0x919, 0x8C, GumpButtonType.Reply, 0, 0x3F13, 0x0, 18, 8); - AddTooltip(1076619); - AddHtmlLocalized(98, 44, 250, 60, 1076272, 0x7FFF); // Hanging Swords - AddImageTiledButton(264, 44, 0x918, 0x919, 0x8D, GumpButtonType.Reply, 0, 0x3F09, 0x0, 18, 8); - AddTooltip(1076620); - AddHtmlLocalized(348, 44, 250, 60, 1076273, 0x7FFF); // Blue fancy rug - AddImageTiledButton(14, 108, 0x918, 0x919, 0x8E, GumpButtonType.Reply, 0, 0x3F0E, 0x0, 18, 8); - AddTooltip(1076621); - AddHtmlLocalized(98, 108, 250, 60, 1076274, 0x7FFF); // Coffin - AddImageTiledButton(264, 108, 0x918, 0x919, 0x8F, GumpButtonType.Reply, 0, 0x3F1F, 0x0, 18, 8); - AddTooltip(1076623); - AddHtmlLocalized(348, 108, 250, 60, 1074027, 0x7FFF); // Vanity - AddImageTiledButton(14, 172, 0x918, 0x919, 0x90, GumpButtonType.Reply, 0, 0x118B, 0x0, -4, -9); - AddTooltip(1076624); - AddHtmlLocalized(98, 172, 250, 60, 1076635, 0x7FFF); // Table With A Purple
Tablecloth - AddImageTiledButton(264, 172, 0x918, 0x919, 0x91, GumpButtonType.Reply, 0, 0x118C, 0x0, -4, -9); - AddTooltip(1076624); - AddHtmlLocalized(348, 172, 250, 60, 1076636, 0x7FFF); // Table With A Blue
Tablecloth - AddImageTiledButton(14, 236, 0x918, 0x919, 0x92, GumpButtonType.Reply, 0, 0x118D, 0x0, -4, -9); - AddTooltip(1076624); - AddHtmlLocalized(98, 236, 250, 60, 1076637, 0x7FFF); // Table With A Red
Tablecloth - AddImageTiledButton(264, 236, 0x918, 0x919, 0x93, GumpButtonType.Reply, 0, 0x118E, 0x0, -4, -9); - AddTooltip(1076624); - AddHtmlLocalized(348, 236, 250, 60, 1076638, 0x7FFF); // Table With An Orange
Tablecloth - AddImageTiledButton(14, 300, 0x918, 0x919, 0x94, GumpButtonType.Reply, 0, 0x3F1E, 0x0, 18, 8); - AddTooltip(1076625); - AddHtmlLocalized(98, 300, 250, 60, 1076279, 0x7FFF); // Unmade Bed - AddImageTiledButton(264, 300, 0x918, 0x919, 0x95, GumpButtonType.Reply, 0, 0x3F0F, 0x0, 18, 8); - AddTooltip(1076626); - AddHtmlLocalized(348, 300, 250, 60, 1076280, 0x7FFF); // Curtains - AddButton(400, 374, 0xFA5, 0xFA7, 0, GumpButtonType.Page, 6); - AddHtmlLocalized(440, 376, 60, 20, 1043353, 0x7FFF); // Next - - AddPage(6); - - AddButton(300, 374, 0xFAE, 0xFB0, 0, GumpButtonType.Page, 5); - AddHtmlLocalized(340, 376, 60, 20, 1011393, 0x7FFF); // Back - AddImageTiledButton(14, 44, 0x918, 0x919, 0x96, GumpButtonType.Reply, 0, 0x1E34, 0x0, 18, -17); - AddTooltip(1076627); - AddHtmlLocalized(98, 44, 250, 60, 1076281, 0x7FFF); // Scarecrow - AddImageTiledButton(264, 44, 0x918, 0x919, 0x97, GumpButtonType.Reply, 0, 0xA0C, 0x0, 18, 8); - AddTooltip(1076628); - AddHtmlLocalized(348, 44, 250, 60, 1076282, 0x7FFF); // Wall Torch - AddImageTiledButton(14, 108, 0x918, 0x919, 0x98, GumpButtonType.Reply, 0, 0x3F10, 0x0, 18, 9); - AddTooltip(1076629); - AddHtmlLocalized(98, 108, 250, 60, 1076283, 0x7FFF); // Fountain - AddImageTiledButton(264, 108, 0x918, 0x919, 0x99, GumpButtonType.Reply, 0, 0x3F19, 0x0, 18, 8); - AddTooltip(1076630); - AddHtmlLocalized(348, 108, 250, 60, 1076284, 0x7FFF); // Statue - AddImageTiledButton(14, 172, 0x918, 0x919, 0x9A, GumpButtonType.Reply, 0, 0x1EA5, 0x0, 5, -25); - AddTooltip(1076631); - AddHtmlLocalized(98, 172, 250, 60, 1076285, 0x7FFF); // Large Fish Net - AddImageTiledButton(264, 172, 0x918, 0x919, 0x9B, GumpButtonType.Reply, 0, 0x1EA3, 0x0, 18, -27); - AddTooltip(1076632); - AddHtmlLocalized(348, 172, 250, 60, 1076286, 0x7FFF); // Small Fish Net - AddImageTiledButton(14, 236, 0x918, 0x919, 0x9C, GumpButtonType.Reply, 0, 0x2FDF, 0x0, 18, -36); - AddTooltip(1076633); - AddHtmlLocalized(98, 236, 250, 60, 1076287, 0x7FFF); // Ladder - AddImageTiledButton(264, 236, 0x918, 0x919, 0x9D, GumpButtonType.Reply, 0, 0x3F15, 0x0, 18, 8); - AddTooltip(1076622); - AddHtmlLocalized(348, 236, 250, 60, 1076288, 0x7FFF); // Iron Maiden - AddImageTiledButton(14, 300, 0x918, 0x919, 0x9E, GumpButtonType.Reply, 0, 0x3F0A, 0x0, 18, 8); - AddTooltip(1076620); - AddHtmlLocalized(98, 300, 250, 60, 1076585, 0x7FFF); // Blue plain rug - AddImageTiledButton(264, 300, 0x918, 0x919, 0x9F, GumpButtonType.Reply, 0, 0x3F11, 0x0, 18, 8); - AddTooltip(1076620); - AddHtmlLocalized(348, 300, 250, 60, 1076586, 0x7FFF); // Golden decorative rug - AddButton(400, 374, 0xFA5, 0xFA7, 0, GumpButtonType.Page, 7); - AddHtmlLocalized(440, 376, 60, 20, 1043353, 0x7FFF); // Next - - AddPage(7); - - AddButton(300, 374, 0xFAE, 0xFB0, 0, GumpButtonType.Page, 6); - AddHtmlLocalized(340, 376, 60, 20, 1011393, 0x7FFF); // Back - AddImageTiledButton(14, 44, 0x918, 0x919, 0xA0, GumpButtonType.Reply, 0, 0x3F0D, 0x0, 18, 8); - AddTooltip(1076620); - AddHtmlLocalized(98, 44, 250, 60, 1076587, 0x7FFF); // Cinnamon fancy rug - AddImageTiledButton(264, 44, 0x918, 0x919, 0xA1, GumpButtonType.Reply, 0, 0x3F18, 0x0, 18, 8); - AddTooltip(1076620); - AddHtmlLocalized(348, 44, 250, 60, 1076588, 0x7FFF); // Red plain rug - AddImageTiledButton(14, 108, 0x918, 0x919, 0xA2, GumpButtonType.Reply, 0, 0x3F08, 0x0, 18, 8); - AddTooltip(1076620); - AddHtmlLocalized(98, 108, 250, 60, 1076589, 0x7FFF); // Blue decorative rug - AddImageTiledButton(264, 108, 0x918, 0x919, 0xA3, GumpButtonType.Reply, 0, 0x3F17, 0x0, 18, 8); - AddTooltip(1076620); - AddHtmlLocalized(348, 108, 250, 60, 1076590, 0x7FFF); // Pink fancy rug - AddImageTiledButton(14, 172, 0x918, 0x919, 0xA4, GumpButtonType.Reply, 0, 0x312A, 0x0, 18, 8); - AddTooltip(1076615); - AddHtmlLocalized(98, 172, 250, 60, 1076784, 0x7FFF); // Cherry Blossom Trunk - AddImageTiledButton(264, 172, 0x918, 0x919, 0xA5, GumpButtonType.Reply, 0, 0x3128, 0x0, 18, 8); - AddTooltip(1076616); - AddHtmlLocalized(348, 172, 250, 60, 1076785, 0x7FFF); // Apple Trunk - AddImageTiledButton(14, 236, 0x918, 0x919, 0xA6, GumpButtonType.Reply, 0, 0x3129, 0x0, 18, 8); - AddTooltip(1076617); - AddHtmlLocalized(98, 236, 250, 60, 1076786, 0x7FFF); // Peach Trunk - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Token?.Deleted != false || info.ButtonID == 0) - return; - - List types = new List(); - int cliloc = 0; - - switch (info.ButtonID) - { - // 7th anniversary - case 0x64: - types.Add(typeof(LeggingsOfEmbers)); - cliloc = 1078147; - break; - case 0x65: - types.Add(typeof(RoseOfTrinsic)); - cliloc = 1062913; - break; - case 0x66: - types.Add(typeof(ShaminoCrossbow)); - cliloc = 1062915; - break; - case 0x67: - types.Add(typeof(TapestryOfSosaria)); - cliloc = 1062917; - break; - case 0x68: - types.Add(typeof(HearthOfHomeFireDeed)); - cliloc = 1062919; - break; - case 0x69: - types.Add(typeof(HolySword)); - cliloc = 1062921; - break; - case 0x6A: - types.Add(typeof(SamuraiHelm)); - cliloc = 1062923; - break; - - // 8th anniversary - /*case 0x6B: types.Add( typeof( SpiritualityHelm ) ); cliloc = 1075188; break; - case 0x6C: types.Add( typeof( ValorGauntlets ) ); cliloc = 1075192; break;*/ - case 0x6D: - types.Add(typeof(DupresShield)); - cliloc = 1075196; - break; - case 0x6E: - types.Add(typeof(FountainOfLifeDeed)); - cliloc = 1075197; - break; - case 0x6F: - types.Add(typeof(DawnsMusicBox)); - cliloc = 1075198; - break; - case 0x70: - types.Add(typeof(OssianGrimoire)); - cliloc = 1078148; - break; - case 0x71: - types.Add(typeof(FerretFormTalisman)); - cliloc = 1078142; - break; - case 0x72: - types.Add(typeof(SquirrelFormTalisman)); - cliloc = 1078143; - break; - case 0x73: - types.Add(typeof(CuSidheFormTalisman)); - cliloc = 1078144; - break; - case 0x74: - types.Add(typeof(ReptalonFormTalisman)); - cliloc = 1078145; - break; - case 0x75: - types.Add(typeof(QuiverOfInfinity)); - cliloc = 1075201; - break; - - // evil home decor - case 0x76: - types.Add(typeof(BoneThroneDeed)); - types.Add(typeof(BoneCouchDeed)); - types.Add(typeof(BoneTableDeed)); - cliloc = 1074797; - break; - case 0x77: - types.Add(typeof(CreepyPortraitDeed)); - types.Add(typeof(DisturbingPortraitDeed)); - types.Add(typeof(UnsettlingPortraitDeed)); - cliloc = 1078146; - break; - case 0x78: - types.Add(typeof(MountedPixieBlueDeed)); - types.Add(typeof(MountedPixieGreenDeed)); - types.Add(typeof(MountedPixieLimeDeed)); - types.Add(typeof(MountedPixieOrangeDeed)); - types.Add(typeof(MountedPixieWhiteDeed)); - cliloc = 1074799; - break; - case 0x79: - types.Add(typeof(HaunterMirrorDeed)); - cliloc = 1074800; - break; - case 0x7A: - types.Add(typeof(BedOfNailsDeed)); - cliloc = 1074801; - break; - case 0x7B: - types.Add(typeof(SacrificialAltarDeed)); - cliloc = 1074818; - break; - - // broken furniture - case 0x7C: - types.Add(typeof(BrokenCoveredChairDeed)); - cliloc = 1076257; - break; - case 0x7D: - types.Add(typeof(BrokenBookcaseDeed)); - cliloc = 1076258; - break; - case 0x7E: - types.Add(typeof(StandingBrokenChairDeed)); - cliloc = 1076259; - break; - case 0x7F: - types.Add(typeof(BrokenVanityDeed)); - cliloc = 1076260; - break; - case 0x80: - types.Add(typeof(BrokenChestOfDrawersDeed)); - cliloc = 1076261; - break; - case 0x81: - types.Add(typeof(BrokenArmoireDeed)); - cliloc = 1076262; - break; - case 0x82: - types.Add(typeof(BrokenBedDeed)); - cliloc = 1076263; - break; - case 0x83: - types.Add(typeof(BrokenFallenChairDeed)); - cliloc = 1076264; - break; - - // other - case 0x84: - types.Add(typeof(SuitOfGoldArmorDeed)); - cliloc = 1076265; - break; - case 0x85: - types.Add(typeof(SuitOfSilverArmorDeed)); - cliloc = 1076266; - break; - case 0x86: - types.Add(typeof(BoilingCauldronDeed)); - cliloc = 1076267; - break; - case 0x87: - types.Add(typeof(GuillotineDeed)); - cliloc = 1024656; - break; - case 0x88: - types.Add(typeof(CherryBlossomTreeDeed)); - cliloc = 1076268; - break; - case 0x89: - types.Add(typeof(AppleTreeDeed)); - cliloc = 1076269; - break; - case 0x8A: - types.Add(typeof(PeachTreeDeed)); - cliloc = 1076270; - break; - case 0x8B: - types.Add(typeof(HangingAxesDeed)); - cliloc = 1076271; - break; - case 0x8C: - types.Add(typeof(HangingSwordsDeed)); - cliloc = 1076272; - break; - case 0x8D: - types.Add(typeof(BlueFancyRugDeed)); - cliloc = 1076273; - break; - case 0x8E: - types.Add(typeof(WoodenCoffinDeed)); - cliloc = 1076274; - break; - case 0x8F: - types.Add(typeof(VanityDeed)); - cliloc = 1074027; - break; - case 0x90: - types.Add(typeof(TableWithPurpleClothDeed)); - cliloc = 1076635; - break; - case 0x91: - types.Add(typeof(TableWithBlueClothDeed)); - cliloc = 1076636; - break; - case 0x92: - types.Add(typeof(TableWithRedClothDeed)); - cliloc = 1076637; - break; - case 0x93: - types.Add(typeof(TableWithOrangeClothDeed)); - cliloc = 1076638; - break; - case 0x94: - types.Add(typeof(UnmadeBedDeed)); - cliloc = 1076279; - break; - case 0x95: - types.Add(typeof(CurtainsDeed)); - cliloc = 1076280; - break; - case 0x96: - types.Add(typeof(ScarecrowDeed)); - cliloc = 1076281; - break; - case 0x97: - types.Add(typeof(WallTorchDeed)); - cliloc = 1076282; - break; - case 0x98: - types.Add(typeof(FountainDeed)); - cliloc = 1076283; - break; - case 0x99: - types.Add(typeof(StoneStatueDeed)); - cliloc = 1076284; - break; - case 0x9A: - types.Add(typeof(LargeFishingNetDeed)); - cliloc = 1076285; - break; - case 0x9B: - types.Add(typeof(SmallFishingNetDeed)); - cliloc = 1076286; - break; - case 0x9C: - types.Add(typeof(HouseLadderDeed)); - cliloc = 1076287; - break; - case 0x9D: - types.Add(typeof(IronMaidenDeed)); - cliloc = 1076288; - break; - case 0x9E: - types.Add(typeof(BluePlainRugDeed)); - cliloc = 1076585; - break; - case 0x9F: - types.Add(typeof(GoldenDecorativeRugDeed)); - cliloc = 1076586; - break; - case 0xA0: - types.Add(typeof(CinnamonFancyRugDeed)); - cliloc = 1076587; - break; - case 0xA1: - types.Add(typeof(RedPlainRugDeed)); - cliloc = 1076588; - break; - case 0xA2: - types.Add(typeof(BlueDecorativeRugDeed)); - cliloc = 1076589; - break; - case 0xA3: - types.Add(typeof(PinkFancyRugDeed)); - cliloc = 1076590; - break; - case 0xA4: - types.Add(typeof(CherryBlossomTrunkDeed)); - cliloc = 1076784; - break; - case 0xA5: - types.Add(typeof(AppleTrunkDeed)); - cliloc = 1076785; - break; - case 0xA6: - types.Add(typeof(PeachTrunkDeed)); - cliloc = 1076786; - break; - } - - if (types.Count > 0 && cliloc > 0) - { - sender.Mobile.CloseGump(); - sender.Mobile.SendGump(new ConfirmHeritageGump(m_Token, types.ToArray(), cliloc)); - } - else - { - sender.Mobile - .SendLocalizedMessage( - 501311); // This option is currently disabled, while we evaluate it for game balance. - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Items; +using Server.Network; + +namespace Server.Gumps +{ + public class HeritageTokenGump : Gump + { + private readonly HeritageToken m_Token; + + public HeritageTokenGump(HeritageToken token) : base(60, 36) + { + m_Token = token; + + AddPage(0); + + AddBackground(0, 0, 520, 404, 0x13BE); + AddImageTiled(10, 10, 500, 20, 0xA40); + AddImageTiled(10, 40, 500, 324, 0xA40); + AddImageTiled(10, 374, 500, 20, 0xA40); + AddAlphaRegion(10, 10, 500, 384); + AddButton(10, 374, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(45, 376, 450, 20, 1060051, 0x7FFF); // CANCEL + AddHtmlLocalized(14, 12, 500, 20, 1075576, 0x7FFF); // Choose your item from the following pages + + AddPage(1); + + AddImageTiledButton(14, 44, 0x918, 0x919, 0x64, GumpButtonType.Reply, 0, 0x1411, 0x2C, 18, 8); + AddTooltip(1062912); + AddHtmlLocalized(98, 44, 250, 60, 1078147, 0x7FFF); // Royal Leggings of Embers + AddImageTiledButton(264, 44, 0x918, 0x919, 0x65, GumpButtonType.Reply, 0, 0x234D, 0x0, 18, 12); + AddTooltip(1062914); + AddHtmlLocalized(348, 44, 250, 60, 1062913, 0x7FFF); // Rose of Trinsic + AddImageTiledButton(14, 108, 0x918, 0x919, 0x66, GumpButtonType.Reply, 0, 0x26C3, 0x504, 18, 8); + AddTooltip(1062916); + AddHtmlLocalized(98, 108, 250, 60, 1062915, 0x7FFF); // Shamino’s Best Crossbow + AddImageTiledButton(264, 108, 0x918, 0x919, 0x67, GumpButtonType.Reply, 0, 0x3F1D, 0x0, 18, 8); + AddTooltip(1062918); + AddHtmlLocalized(348, 108, 250, 60, 1062917, 0x7FFF); // The Tapestry of Sosaria + AddImageTiledButton(14, 172, 0x918, 0x919, 0x68, GumpButtonType.Reply, 0, 0x3F14, 0x0, 18, 8); + AddTooltip(1062920); + AddHtmlLocalized(98, 172, 250, 60, 1062919, 0x7FFF); // Hearth of the Home Fire + AddImageTiledButton(264, 172, 0x918, 0x919, 0x69, GumpButtonType.Reply, 0, 0xF60, 0x482, -1, 10); + AddTooltip(1062922); + AddHtmlLocalized(348, 172, 250, 60, 1062921, 0x7FFF); // The Holy Sword + AddImageTiledButton(14, 236, 0x918, 0x919, 0x6A, GumpButtonType.Reply, 0, 0x236C, 0x0, 18, 6); + AddTooltip(1062924); + AddHtmlLocalized(98, 236, 250, 60, 1062923, 0x7FFF); // Ancient Samurai Helm + AddImageTiledButton(264, 236, 0x918, 0x919, 0x6B, GumpButtonType.Reply, 0, 0x2B10, 0x226, 18, 11); + AddTooltip(1075223); + AddHtmlLocalized(348, 236, 250, 60, 1075188, 0x7FFF); // Helm of Spirituality + AddImageTiledButton(14, 300, 0x918, 0x919, 0x6C, GumpButtonType.Reply, 0, 0x2B0C, 0x226, 18, 15); + AddTooltip(1075224); + AddHtmlLocalized(98, 300, 250, 60, 1075192, 0x7FFF); // Gauntlets of Valor + AddImageTiledButton(264, 300, 0x918, 0x919, 0x6D, GumpButtonType.Reply, 0, 0x2B01, 0x0, 18, 9); + AddTooltip(1075225); + AddHtmlLocalized(348, 300, 250, 60, 1075196, 0x7FFF); // Dupre’s Shield + AddButton(400, 374, 0xFA5, 0xFA7, 0, GumpButtonType.Page, 2); + AddHtmlLocalized(440, 376, 60, 20, 1043353, 0x7FFF); // Next + + AddPage(2); + + AddButton(300, 374, 0xFAE, 0xFB0, 0, GumpButtonType.Page, 1); + AddHtmlLocalized(340, 376, 60, 20, 1011393, 0x7FFF); // Back + AddImageTiledButton(14, 44, 0x918, 0x919, 0x6E, GumpButtonType.Reply, 0, 0x2AC6, 0x0, 29, 0); + AddTooltip(1075226); + AddHtmlLocalized(98, 44, 250, 60, 1075197, 0x7FFF); // Fountain of Life + AddImageTiledButton(264, 44, 0x918, 0x919, 0x6F, GumpButtonType.Reply, 0, 0x2AF9, 0x0, -4, -5); + AddTooltip(1075227); + AddHtmlLocalized(348, 44, 250, 60, 1075198, 0x7FFF); // Dawn’s Music Box + AddImageTiledButton(14, 108, 0x918, 0x919, 0x70, GumpButtonType.Reply, 0, 0x2253, 0x0, 18, 12); + AddTooltip(1075228); + AddHtmlLocalized(98, 108, 250, 60, 1078148, 0x7FFF); // Ossian Grimoire + AddImageTiledButton(264, 108, 0x918, 0x919, 0x71, GumpButtonType.Reply, 0, 0x2D98, 0x0, 19, 13); + AddTooltip(1078527); + AddHtmlLocalized(348, 108, 250, 60, 1078142, 0x7FFF); // Talisman of the Fey:
Ferret + AddImageTiledButton(14, 172, 0x918, 0x919, 0x72, GumpButtonType.Reply, 0, 0x2D97, 0x0, 19, 13); + AddTooltip(1078528); + AddHtmlLocalized(98, 172, 250, 60, 1078143, 0x7FFF); // Talisman of the Fey:
Squirrel + AddImageTiledButton(264, 172, 0x918, 0x919, 0x73, GumpButtonType.Reply, 0, 0x2D96, 0x0, 19, 8); + AddTooltip(1078529); + AddHtmlLocalized(348, 172, 250, 60, 1078144, 0x7FFF); // Talisman of the Fey:
Cu Sidhe + AddImageTiledButton(14, 236, 0x918, 0x919, 0x74, GumpButtonType.Reply, 0, 0x2D95, 0x0, -4, 2); + AddTooltip(1078530); + AddHtmlLocalized(98, 236, 250, 60, 1078145, 0x7FFF); // Talisman of the Fey:
Reptalon + AddImageTiledButton(264, 236, 0x918, 0x919, 0x75, GumpButtonType.Reply, 0, 0x2B02, 0x0, -2, 9); + AddTooltip(1078526); + AddHtmlLocalized(348, 236, 250, 60, 1075201, 0x7FFF); // Quiver of Infinity + AddImageTiledButton(14, 300, 0x918, 0x919, 0x76, GumpButtonType.Reply, 0, 0x2A91, 0x0, 25, 5); + AddTooltip(1075986); + AddHtmlLocalized(98, 300, 250, 60, 1074797, 0x7FFF); // Bone Throne, Bone Couch
and Bone Table + AddImageTiledButton(264, 300, 0x918, 0x919, 0x77, GumpButtonType.Reply, 0, 0x2A99, 0x0, 18, 1); + AddTooltip(1075987); + AddHtmlLocalized(348, 300, 250, 60, 1078146, 0x7FFF); // Creepy Portraits + AddButton(400, 374, 0xFA5, 0xFA7, 0, GumpButtonType.Page, 3); + AddHtmlLocalized(440, 376, 60, 20, 1043353, 0x7FFF); // Next + + AddPage(3); + + AddButton(300, 374, 0xFAE, 0xFB0, 0, GumpButtonType.Page, 2); + AddHtmlLocalized(340, 376, 60, 20, 1011393, 0x7FFF); // Back + AddImageTiledButton(14, 44, 0x918, 0x919, 0x78, GumpButtonType.Reply, 0, 0x2A71, 0x0, 13, 5); + AddTooltip(1075988); + AddHtmlLocalized(98, 44, 250, 60, 1074799, 0x7FFF); // Mounted Pixies (5) + AddImageTiledButton(264, 44, 0x918, 0x919, 0x79, GumpButtonType.Reply, 0, 0x2A98, 0x0, 26, 1); + AddTooltip(1075990); + AddHtmlLocalized(348, 44, 250, 60, 1074800, 0x7FFF); // Haunted Mirror + AddImageTiledButton(14, 108, 0x918, 0x919, 0x7A, GumpButtonType.Reply, 0, 0x2A92, 0x0, 18, 1); + AddTooltip(1075989); + AddHtmlLocalized(98, 108, 250, 60, 1074801, 0x7FFF); // Bed of Nails + AddImageTiledButton(264, 108, 0x918, 0x919, 0x7B, GumpButtonType.Reply, 0, 0x2AB8, 0x0, 18, 1); + AddTooltip(1075991); + AddHtmlLocalized(348, 108, 250, 60, 1074818, 0x7FFF); // Sacrificial Altar + AddImageTiledButton(14, 172, 0x918, 0x919, 0x7C, GumpButtonType.Reply, 0, 0x3F26, 0x0, 18, 8); + AddTooltip(1076610); + AddHtmlLocalized(98, 172, 250, 60, 1076257, 0x7FFF); // Broken Covered Chair + AddImageTiledButton(264, 172, 0x918, 0x919, 0x7D, GumpButtonType.Reply, 0, 0x3F22, 0x0, 18, 8); + AddTooltip(1076610); + AddHtmlLocalized(348, 172, 250, 60, 1076258, 0x7FFF); // Broken Bookcase + AddImageTiledButton(14, 236, 0x918, 0x919, 0x7E, GumpButtonType.Reply, 0, 0x3F24, 0x0, 18, 8); + AddTooltip(1076610); + AddHtmlLocalized(98, 236, 250, 60, 1076259, 0x7FFF); // Standing Broken Chair + AddImageTiledButton(264, 236, 0x918, 0x919, 0x7F, GumpButtonType.Reply, 0, 0x3F25, 0x0, 18, 8); + AddTooltip(1076610); + AddHtmlLocalized(348, 236, 250, 60, 1076260, 0x7FFF); // Broken Vanity + AddImageTiledButton(14, 300, 0x918, 0x919, 0x80, GumpButtonType.Reply, 0, 0x3F23, 0x0, 18, 8); + AddTooltip(1076610); + AddHtmlLocalized(98, 300, 250, 60, 1076261, 0x7FFF); // Broken Chest of Drawers + AddImageTiledButton(264, 300, 0x918, 0x919, 0x81, GumpButtonType.Reply, 0, 0x3F21, 0x0, 18, 8); + AddTooltip(1076610); + AddHtmlLocalized(348, 300, 250, 60, 1076262, 0x7FFF); // Broken Armoire + AddButton(400, 374, 0xFA5, 0xFA7, 0, GumpButtonType.Page, 4); + AddHtmlLocalized(440, 376, 60, 20, 1043353, 0x7FFF); // Next + + AddPage(4); + + AddButton(300, 374, 0xFAE, 0xFB0, 0, GumpButtonType.Page, 3); + AddHtmlLocalized(340, 376, 60, 20, 1011393, 0x7FFF); // Back + AddImageTiledButton(14, 44, 0x918, 0x919, 0x82, GumpButtonType.Reply, 0, 0x3F0B, 0x0, 18, 8); + AddTooltip(1076610); + AddHtmlLocalized(98, 44, 250, 60, 1076263, 0x7FFF); // Broken Bed + AddImageTiledButton(264, 44, 0x918, 0x919, 0x83, GumpButtonType.Reply, 0, 0xC19, 0x0, 13, 8); + AddTooltip(1076610); + AddHtmlLocalized(348, 44, 250, 60, 1076264, 0x7FFF); // Broken Fallen Chair + AddImageTiledButton(14, 108, 0x918, 0x919, 0x84, GumpButtonType.Reply, 0, 0x3DAA, 0x0, 20, -3); + AddTooltip(1076611); + AddHtmlLocalized(98, 108, 250, 60, 1076265, 0x7FFF); // Suit of Gold Armor + AddImageTiledButton(264, 108, 0x918, 0x919, 0x85, GumpButtonType.Reply, 0, 0x151C, 0x0, -20, -3); + AddTooltip(1076612); + AddHtmlLocalized(348, 108, 250, 60, 1076266, 0x7FFF); // Suit of Silver Armor + AddImageTiledButton(14, 172, 0x918, 0x919, 0x86, GumpButtonType.Reply, 0, 0x3DB1, 0x0, 18, 8); + AddTooltip(1076613); + AddHtmlLocalized(98, 172, 250, 60, 1076267, 0x7FFF); // Boiling Cauldron + AddImageTiledButton(264, 172, 0x918, 0x919, 0x87, GumpButtonType.Reply, 0, 0x3F27, 0x0, 18, 8); + AddTooltip(1076614); + AddHtmlLocalized(348, 172, 250, 60, 1024656, 0x7FFF); // Guillotine + AddImageTiledButton(14, 236, 0x918, 0x919, 0x88, GumpButtonType.Reply, 0, 0x3F0C, 0x0, 18, 8); + AddTooltip(1076615); + AddHtmlLocalized(98, 236, 250, 60, 1076268, 0x7FFF); // Cherry Blossom Tree + AddImageTiledButton(264, 236, 0x918, 0x919, 0x89, GumpButtonType.Reply, 0, 0x3F07, 0x0, 18, 8); + AddTooltip(1076616); + AddHtmlLocalized(348, 236, 250, 60, 1076269, 0x7FFF); // Apple Tree + AddImageTiledButton(14, 300, 0x918, 0x919, 0x8A, GumpButtonType.Reply, 0, 0x3F16, 0x0, 18, 8); + AddTooltip(1076617); + AddHtmlLocalized(98, 300, 250, 60, 1076270, 0x7FFF); // Peach Tree + AddImageTiledButton(264, 300, 0x918, 0x919, 0x8B, GumpButtonType.Reply, 0, 0x3F12, 0x0, 18, 8); + AddTooltip(1076618); + AddHtmlLocalized(348, 300, 250, 60, 1076271, 0x7FFF); // Hanging Axes + AddButton(400, 374, 0xFA5, 0xFA7, 0, GumpButtonType.Page, 5); + AddHtmlLocalized(440, 376, 60, 20, 1043353, 0x7FFF); // Next + + AddPage(5); + + AddButton(300, 374, 0xFAE, 0xFB0, 0, GumpButtonType.Page, 4); + AddHtmlLocalized(340, 376, 60, 20, 1011393, 0x7FFF); // Back + AddImageTiledButton(14, 44, 0x918, 0x919, 0x8C, GumpButtonType.Reply, 0, 0x3F13, 0x0, 18, 8); + AddTooltip(1076619); + AddHtmlLocalized(98, 44, 250, 60, 1076272, 0x7FFF); // Hanging Swords + AddImageTiledButton(264, 44, 0x918, 0x919, 0x8D, GumpButtonType.Reply, 0, 0x3F09, 0x0, 18, 8); + AddTooltip(1076620); + AddHtmlLocalized(348, 44, 250, 60, 1076273, 0x7FFF); // Blue fancy rug + AddImageTiledButton(14, 108, 0x918, 0x919, 0x8E, GumpButtonType.Reply, 0, 0x3F0E, 0x0, 18, 8); + AddTooltip(1076621); + AddHtmlLocalized(98, 108, 250, 60, 1076274, 0x7FFF); // Coffin + AddImageTiledButton(264, 108, 0x918, 0x919, 0x8F, GumpButtonType.Reply, 0, 0x3F1F, 0x0, 18, 8); + AddTooltip(1076623); + AddHtmlLocalized(348, 108, 250, 60, 1074027, 0x7FFF); // Vanity + AddImageTiledButton(14, 172, 0x918, 0x919, 0x90, GumpButtonType.Reply, 0, 0x118B, 0x0, -4, -9); + AddTooltip(1076624); + AddHtmlLocalized(98, 172, 250, 60, 1076635, 0x7FFF); // Table With A Purple
Tablecloth + AddImageTiledButton(264, 172, 0x918, 0x919, 0x91, GumpButtonType.Reply, 0, 0x118C, 0x0, -4, -9); + AddTooltip(1076624); + AddHtmlLocalized(348, 172, 250, 60, 1076636, 0x7FFF); // Table With A Blue
Tablecloth + AddImageTiledButton(14, 236, 0x918, 0x919, 0x92, GumpButtonType.Reply, 0, 0x118D, 0x0, -4, -9); + AddTooltip(1076624); + AddHtmlLocalized(98, 236, 250, 60, 1076637, 0x7FFF); // Table With A Red
Tablecloth + AddImageTiledButton(264, 236, 0x918, 0x919, 0x93, GumpButtonType.Reply, 0, 0x118E, 0x0, -4, -9); + AddTooltip(1076624); + AddHtmlLocalized(348, 236, 250, 60, 1076638, 0x7FFF); // Table With An Orange
Tablecloth + AddImageTiledButton(14, 300, 0x918, 0x919, 0x94, GumpButtonType.Reply, 0, 0x3F1E, 0x0, 18, 8); + AddTooltip(1076625); + AddHtmlLocalized(98, 300, 250, 60, 1076279, 0x7FFF); // Unmade Bed + AddImageTiledButton(264, 300, 0x918, 0x919, 0x95, GumpButtonType.Reply, 0, 0x3F0F, 0x0, 18, 8); + AddTooltip(1076626); + AddHtmlLocalized(348, 300, 250, 60, 1076280, 0x7FFF); // Curtains + AddButton(400, 374, 0xFA5, 0xFA7, 0, GumpButtonType.Page, 6); + AddHtmlLocalized(440, 376, 60, 20, 1043353, 0x7FFF); // Next + + AddPage(6); + + AddButton(300, 374, 0xFAE, 0xFB0, 0, GumpButtonType.Page, 5); + AddHtmlLocalized(340, 376, 60, 20, 1011393, 0x7FFF); // Back + AddImageTiledButton(14, 44, 0x918, 0x919, 0x96, GumpButtonType.Reply, 0, 0x1E34, 0x0, 18, -17); + AddTooltip(1076627); + AddHtmlLocalized(98, 44, 250, 60, 1076281, 0x7FFF); // Scarecrow + AddImageTiledButton(264, 44, 0x918, 0x919, 0x97, GumpButtonType.Reply, 0, 0xA0C, 0x0, 18, 8); + AddTooltip(1076628); + AddHtmlLocalized(348, 44, 250, 60, 1076282, 0x7FFF); // Wall Torch + AddImageTiledButton(14, 108, 0x918, 0x919, 0x98, GumpButtonType.Reply, 0, 0x3F10, 0x0, 18, 9); + AddTooltip(1076629); + AddHtmlLocalized(98, 108, 250, 60, 1076283, 0x7FFF); // Fountain + AddImageTiledButton(264, 108, 0x918, 0x919, 0x99, GumpButtonType.Reply, 0, 0x3F19, 0x0, 18, 8); + AddTooltip(1076630); + AddHtmlLocalized(348, 108, 250, 60, 1076284, 0x7FFF); // Statue + AddImageTiledButton(14, 172, 0x918, 0x919, 0x9A, GumpButtonType.Reply, 0, 0x1EA5, 0x0, 5, -25); + AddTooltip(1076631); + AddHtmlLocalized(98, 172, 250, 60, 1076285, 0x7FFF); // Large Fish Net + AddImageTiledButton(264, 172, 0x918, 0x919, 0x9B, GumpButtonType.Reply, 0, 0x1EA3, 0x0, 18, -27); + AddTooltip(1076632); + AddHtmlLocalized(348, 172, 250, 60, 1076286, 0x7FFF); // Small Fish Net + AddImageTiledButton(14, 236, 0x918, 0x919, 0x9C, GumpButtonType.Reply, 0, 0x2FDF, 0x0, 18, -36); + AddTooltip(1076633); + AddHtmlLocalized(98, 236, 250, 60, 1076287, 0x7FFF); // Ladder + AddImageTiledButton(264, 236, 0x918, 0x919, 0x9D, GumpButtonType.Reply, 0, 0x3F15, 0x0, 18, 8); + AddTooltip(1076622); + AddHtmlLocalized(348, 236, 250, 60, 1076288, 0x7FFF); // Iron Maiden + AddImageTiledButton(14, 300, 0x918, 0x919, 0x9E, GumpButtonType.Reply, 0, 0x3F0A, 0x0, 18, 8); + AddTooltip(1076620); + AddHtmlLocalized(98, 300, 250, 60, 1076585, 0x7FFF); // Blue plain rug + AddImageTiledButton(264, 300, 0x918, 0x919, 0x9F, GumpButtonType.Reply, 0, 0x3F11, 0x0, 18, 8); + AddTooltip(1076620); + AddHtmlLocalized(348, 300, 250, 60, 1076586, 0x7FFF); // Golden decorative rug + AddButton(400, 374, 0xFA5, 0xFA7, 0, GumpButtonType.Page, 7); + AddHtmlLocalized(440, 376, 60, 20, 1043353, 0x7FFF); // Next + + AddPage(7); + + AddButton(300, 374, 0xFAE, 0xFB0, 0, GumpButtonType.Page, 6); + AddHtmlLocalized(340, 376, 60, 20, 1011393, 0x7FFF); // Back + AddImageTiledButton(14, 44, 0x918, 0x919, 0xA0, GumpButtonType.Reply, 0, 0x3F0D, 0x0, 18, 8); + AddTooltip(1076620); + AddHtmlLocalized(98, 44, 250, 60, 1076587, 0x7FFF); // Cinnamon fancy rug + AddImageTiledButton(264, 44, 0x918, 0x919, 0xA1, GumpButtonType.Reply, 0, 0x3F18, 0x0, 18, 8); + AddTooltip(1076620); + AddHtmlLocalized(348, 44, 250, 60, 1076588, 0x7FFF); // Red plain rug + AddImageTiledButton(14, 108, 0x918, 0x919, 0xA2, GumpButtonType.Reply, 0, 0x3F08, 0x0, 18, 8); + AddTooltip(1076620); + AddHtmlLocalized(98, 108, 250, 60, 1076589, 0x7FFF); // Blue decorative rug + AddImageTiledButton(264, 108, 0x918, 0x919, 0xA3, GumpButtonType.Reply, 0, 0x3F17, 0x0, 18, 8); + AddTooltip(1076620); + AddHtmlLocalized(348, 108, 250, 60, 1076590, 0x7FFF); // Pink fancy rug + AddImageTiledButton(14, 172, 0x918, 0x919, 0xA4, GumpButtonType.Reply, 0, 0x312A, 0x0, 18, 8); + AddTooltip(1076615); + AddHtmlLocalized(98, 172, 250, 60, 1076784, 0x7FFF); // Cherry Blossom Trunk + AddImageTiledButton(264, 172, 0x918, 0x919, 0xA5, GumpButtonType.Reply, 0, 0x3128, 0x0, 18, 8); + AddTooltip(1076616); + AddHtmlLocalized(348, 172, 250, 60, 1076785, 0x7FFF); // Apple Trunk + AddImageTiledButton(14, 236, 0x918, 0x919, 0xA6, GumpButtonType.Reply, 0, 0x3129, 0x0, 18, 8); + AddTooltip(1076617); + AddHtmlLocalized(98, 236, 250, 60, 1076786, 0x7FFF); // Peach Trunk + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Token?.Deleted != false || info.ButtonID == 0) + return; + + var types = new List(); + var cliloc = 0; + + switch (info.ButtonID) + { + // 7th anniversary + case 0x64: + types.Add(typeof(LeggingsOfEmbers)); + cliloc = 1078147; + break; + case 0x65: + types.Add(typeof(RoseOfTrinsic)); + cliloc = 1062913; + break; + case 0x66: + types.Add(typeof(ShaminoCrossbow)); + cliloc = 1062915; + break; + case 0x67: + types.Add(typeof(TapestryOfSosaria)); + cliloc = 1062917; + break; + case 0x68: + types.Add(typeof(HearthOfHomeFireDeed)); + cliloc = 1062919; + break; + case 0x69: + types.Add(typeof(HolySword)); + cliloc = 1062921; + break; + case 0x6A: + types.Add(typeof(SamuraiHelm)); + cliloc = 1062923; + break; + + // 8th anniversary + /*case 0x6B: types.Add( typeof( SpiritualityHelm ) ); cliloc = 1075188; break; + case 0x6C: types.Add( typeof( ValorGauntlets ) ); cliloc = 1075192; break;*/ + case 0x6D: + types.Add(typeof(DupresShield)); + cliloc = 1075196; + break; + case 0x6E: + types.Add(typeof(FountainOfLifeDeed)); + cliloc = 1075197; + break; + case 0x6F: + types.Add(typeof(DawnsMusicBox)); + cliloc = 1075198; + break; + case 0x70: + types.Add(typeof(OssianGrimoire)); + cliloc = 1078148; + break; + case 0x71: + types.Add(typeof(FerretFormTalisman)); + cliloc = 1078142; + break; + case 0x72: + types.Add(typeof(SquirrelFormTalisman)); + cliloc = 1078143; + break; + case 0x73: + types.Add(typeof(CuSidheFormTalisman)); + cliloc = 1078144; + break; + case 0x74: + types.Add(typeof(ReptalonFormTalisman)); + cliloc = 1078145; + break; + case 0x75: + types.Add(typeof(QuiverOfInfinity)); + cliloc = 1075201; + break; + + // evil home decor + case 0x76: + types.Add(typeof(BoneThroneDeed)); + types.Add(typeof(BoneCouchDeed)); + types.Add(typeof(BoneTableDeed)); + cliloc = 1074797; + break; + case 0x77: + types.Add(typeof(CreepyPortraitDeed)); + types.Add(typeof(DisturbingPortraitDeed)); + types.Add(typeof(UnsettlingPortraitDeed)); + cliloc = 1078146; + break; + case 0x78: + types.Add(typeof(MountedPixieBlueDeed)); + types.Add(typeof(MountedPixieGreenDeed)); + types.Add(typeof(MountedPixieLimeDeed)); + types.Add(typeof(MountedPixieOrangeDeed)); + types.Add(typeof(MountedPixieWhiteDeed)); + cliloc = 1074799; + break; + case 0x79: + types.Add(typeof(HaunterMirrorDeed)); + cliloc = 1074800; + break; + case 0x7A: + types.Add(typeof(BedOfNailsDeed)); + cliloc = 1074801; + break; + case 0x7B: + types.Add(typeof(SacrificialAltarDeed)); + cliloc = 1074818; + break; + + // broken furniture + case 0x7C: + types.Add(typeof(BrokenCoveredChairDeed)); + cliloc = 1076257; + break; + case 0x7D: + types.Add(typeof(BrokenBookcaseDeed)); + cliloc = 1076258; + break; + case 0x7E: + types.Add(typeof(StandingBrokenChairDeed)); + cliloc = 1076259; + break; + case 0x7F: + types.Add(typeof(BrokenVanityDeed)); + cliloc = 1076260; + break; + case 0x80: + types.Add(typeof(BrokenChestOfDrawersDeed)); + cliloc = 1076261; + break; + case 0x81: + types.Add(typeof(BrokenArmoireDeed)); + cliloc = 1076262; + break; + case 0x82: + types.Add(typeof(BrokenBedDeed)); + cliloc = 1076263; + break; + case 0x83: + types.Add(typeof(BrokenFallenChairDeed)); + cliloc = 1076264; + break; + + // other + case 0x84: + types.Add(typeof(SuitOfGoldArmorDeed)); + cliloc = 1076265; + break; + case 0x85: + types.Add(typeof(SuitOfSilverArmorDeed)); + cliloc = 1076266; + break; + case 0x86: + types.Add(typeof(BoilingCauldronDeed)); + cliloc = 1076267; + break; + case 0x87: + types.Add(typeof(GuillotineDeed)); + cliloc = 1024656; + break; + case 0x88: + types.Add(typeof(CherryBlossomTreeDeed)); + cliloc = 1076268; + break; + case 0x89: + types.Add(typeof(AppleTreeDeed)); + cliloc = 1076269; + break; + case 0x8A: + types.Add(typeof(PeachTreeDeed)); + cliloc = 1076270; + break; + case 0x8B: + types.Add(typeof(HangingAxesDeed)); + cliloc = 1076271; + break; + case 0x8C: + types.Add(typeof(HangingSwordsDeed)); + cliloc = 1076272; + break; + case 0x8D: + types.Add(typeof(BlueFancyRugDeed)); + cliloc = 1076273; + break; + case 0x8E: + types.Add(typeof(WoodenCoffinDeed)); + cliloc = 1076274; + break; + case 0x8F: + types.Add(typeof(VanityDeed)); + cliloc = 1074027; + break; + case 0x90: + types.Add(typeof(TableWithPurpleClothDeed)); + cliloc = 1076635; + break; + case 0x91: + types.Add(typeof(TableWithBlueClothDeed)); + cliloc = 1076636; + break; + case 0x92: + types.Add(typeof(TableWithRedClothDeed)); + cliloc = 1076637; + break; + case 0x93: + types.Add(typeof(TableWithOrangeClothDeed)); + cliloc = 1076638; + break; + case 0x94: + types.Add(typeof(UnmadeBedDeed)); + cliloc = 1076279; + break; + case 0x95: + types.Add(typeof(CurtainsDeed)); + cliloc = 1076280; + break; + case 0x96: + types.Add(typeof(ScarecrowDeed)); + cliloc = 1076281; + break; + case 0x97: + types.Add(typeof(WallTorchDeed)); + cliloc = 1076282; + break; + case 0x98: + types.Add(typeof(FountainDeed)); + cliloc = 1076283; + break; + case 0x99: + types.Add(typeof(StoneStatueDeed)); + cliloc = 1076284; + break; + case 0x9A: + types.Add(typeof(LargeFishingNetDeed)); + cliloc = 1076285; + break; + case 0x9B: + types.Add(typeof(SmallFishingNetDeed)); + cliloc = 1076286; + break; + case 0x9C: + types.Add(typeof(HouseLadderDeed)); + cliloc = 1076287; + break; + case 0x9D: + types.Add(typeof(IronMaidenDeed)); + cliloc = 1076288; + break; + case 0x9E: + types.Add(typeof(BluePlainRugDeed)); + cliloc = 1076585; + break; + case 0x9F: + types.Add(typeof(GoldenDecorativeRugDeed)); + cliloc = 1076586; + break; + case 0xA0: + types.Add(typeof(CinnamonFancyRugDeed)); + cliloc = 1076587; + break; + case 0xA1: + types.Add(typeof(RedPlainRugDeed)); + cliloc = 1076588; + break; + case 0xA2: + types.Add(typeof(BlueDecorativeRugDeed)); + cliloc = 1076589; + break; + case 0xA3: + types.Add(typeof(PinkFancyRugDeed)); + cliloc = 1076590; + break; + case 0xA4: + types.Add(typeof(CherryBlossomTrunkDeed)); + cliloc = 1076784; + break; + case 0xA5: + types.Add(typeof(AppleTrunkDeed)); + cliloc = 1076785; + break; + case 0xA6: + types.Add(typeof(PeachTrunkDeed)); + cliloc = 1076786; + break; + } + + if (types.Count > 0 && cliloc > 0) + { + sender.Mobile.CloseGump(); + sender.Mobile.SendGump(new ConfirmHeritageGump(m_Token, types.ToArray(), cliloc)); + } + else + { + sender.Mobile + .SendLocalizedMessage( + 501311 + ); // This option is currently disabled, while we evaluate it for game balance. + } + } + } +} diff --git a/Projects/UOContent/Gumps/HonorSelf.cs b/Projects/UOContent/Gumps/HonorSelf.cs index f76e65445..7204fb6c6 100644 --- a/Projects/UOContent/Gumps/HonorSelf.cs +++ b/Projects/UOContent/Gumps/HonorSelf.cs @@ -1,24 +1,24 @@ -using Server.Mobiles; -using Server.Network; - -namespace Server.Gumps -{ - public class HonorSelf : Gump - { - private readonly PlayerMobile m_from; - - public HonorSelf(PlayerMobile from) : base(150, 50) - { - m_from = from; - AddBackground(0, 0, 245, 145, 9250); - AddButton(157, 101, 247, 248, 1); - AddButton(81, 100, 241, 248, 0); - AddHtml(21, 20, 203, 70, "Are you sure you want to use honor points on yourself?", true); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 1) HonorVirtue.ActivateEmbrace(m_from); - } - } -} +using Server.Mobiles; +using Server.Network; + +namespace Server.Gumps +{ + public class HonorSelf : Gump + { + private readonly PlayerMobile m_from; + + public HonorSelf(PlayerMobile from) : base(150, 50) + { + m_from = from; + AddBackground(0, 0, 245, 145, 9250); + AddButton(157, 101, 247, 248, 1); + AddButton(81, 100, 241, 248, 0); + AddHtml(21, 20, 203, 70, "Are you sure you want to use honor points on yourself?", true); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 1) HonorVirtue.ActivateEmbrace(m_from); + } + } +} diff --git a/Projects/UOContent/Gumps/HouseDemolishGump.cs b/Projects/UOContent/Gumps/HouseDemolishGump.cs index 7ddd19997..2657e1b8d 100644 --- a/Projects/UOContent/Gumps/HouseDemolishGump.cs +++ b/Projects/UOContent/Gumps/HouseDemolishGump.cs @@ -1,170 +1,175 @@ -using Server.Accounting; -using Server.Guilds; -using Server.Items; -using Server.Multis; -using Server.Network; - -namespace Server.Gumps -{ - public class HouseDemolishGump : Gump - { - private readonly BaseHouse m_House; - private readonly Mobile m_Mobile; - - public HouseDemolishGump(Mobile mobile, BaseHouse house) : base(110, 100) - { - m_Mobile = mobile; - m_House = house; - - mobile.CloseGump(); - - Closable = false; - - AddPage(0); - - AddBackground(0, 0, 420, 280, 5054); - - AddImageTiled(10, 10, 400, 20, 2624); - AddAlphaRegion(10, 10, 400, 20); - - AddHtmlLocalized(10, 10, 400, 20, 1060635, 30720); //
WARNING
- - AddImageTiled(10, 40, 400, 200, 2624); - AddAlphaRegion(10, 40, 400, 200); - - /* You are about to demolish your house. - * You will be refunded the house's value directly to your bank box. - * All items in the house will remain behind and can be freely picked up by anyone. - * Once the house is demolished, anyone can attempt to place a new house on the vacant land. - * This action will not un-condemn any other houses on your account, nor will it end your 7-day waiting period (if it applies to you). - * Are you sure you wish to continue? - */ - AddHtmlLocalized(10, 40, 400, 200, 1061795, 32512, false, true); - - AddImageTiled(10, 250, 400, 20, 2624); - AddAlphaRegion(10, 250, 400, 20); - - AddButton(10, 250, 4005, 4007, 1); - AddHtmlLocalized(40, 250, 170, 20, 1011036, 32767); // OKAY - - AddButton(210, 250, 4005, 4007, 0); - AddHtmlLocalized(240, 250, 170, 20, 1011012, 32767); // CANCEL - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (info.ButtonID == 1 && !m_House.Deleted) - { - if (m_House.IsOwner(m_Mobile)) - { - if (m_House.MovingCrate != null || m_House.InternalizedVendors.Count > 0) return; - - if (!Guild.NewGuildSystem && m_House.FindGuildstone() != null) - { - m_Mobile.SendLocalizedMessage(501389); // You cannot redeed a house with a guildstone inside. - return; - } - - /*else if (m_House.PlayerVendors.Count > 0) - { - m_Mobile.SendLocalizedMessage( 503236 ); // You need to collect your vendor's belongings before moving. - return; - }*/ - if (m_House.HasRentedVendors && m_House.VendorInventories.Count > 0) - { - m_Mobile.SendLocalizedMessage( - 1062679); // You cannot do that that while you still have contract vendors or unclaimed contract vendor inventory in your house. - return; - } - - if (m_House.HasRentedVendors) - { - m_Mobile.SendLocalizedMessage( - 1062680); // You cannot do that that while you still have contract vendors in your house. - return; - } - - if (m_House.VendorInventories.Count > 0) - { - m_Mobile.SendLocalizedMessage( - 1062681); // You cannot do that that while you still have unclaimed contract vendor inventory in your house. - return; - } - - if (m_Mobile.AccessLevel >= AccessLevel.GameMaster) - { - m_Mobile.SendMessage("You do not get a refund for your house as you are not a player"); - m_House.RemoveKeys(m_Mobile); - m_House.Delete(); - } - else - { - Item toGive = null; - - if (m_House.IsAosRules) - { - if (m_House.Price > 0) - toGive = new BankCheck(m_House.Price); - else - toGive = m_House.GetDeed(); - } - else - { - toGive = m_House.GetDeed(); - - if (toGive == null && m_House.Price > 0) - toGive = new BankCheck(m_House.Price); - } - - BankCheck check = toGive as BankCheck; - - if (AccountGold.Enabled && check != null) - { - int worth = check.Worth; - - if (m_Mobile.Account?.DepositGold(worth) == true) - { - check.Delete(); - - m_Mobile.SendLocalizedMessage(1060397, worth.ToString("#,0")); - // ~1_AMOUNT~ gold has been deposited into your bank box. - - m_House.RemoveKeys(m_Mobile); - m_House.Delete(); - return; - } - } - - if (toGive != null) - { - BankBox box = m_Mobile.BankBox; - - if (box.TryDropItem(m_Mobile, toGive, false)) - { - if (check != null) - m_Mobile.SendLocalizedMessage(1060397, - check.Worth.ToString()); // ~1_AMOUNT~ gold has been deposited into your bank box. - - m_House.RemoveKeys(m_Mobile); - m_House.Delete(); - } - else - { - toGive.Delete(); - m_Mobile.SendLocalizedMessage(500390); // Your bank box is full. - } - } - else - { - m_Mobile.SendMessage("Unable to refund house."); - } - } - } - else - { - m_Mobile.SendLocalizedMessage(501320); // Only the house owner may do this. - } - } - } - } -} +using Server.Accounting; +using Server.Guilds; +using Server.Items; +using Server.Multis; +using Server.Network; + +namespace Server.Gumps +{ + public class HouseDemolishGump : Gump + { + private readonly BaseHouse m_House; + private readonly Mobile m_Mobile; + + public HouseDemolishGump(Mobile mobile, BaseHouse house) : base(110, 100) + { + m_Mobile = mobile; + m_House = house; + + mobile.CloseGump(); + + Closable = false; + + AddPage(0); + + AddBackground(0, 0, 420, 280, 5054); + + AddImageTiled(10, 10, 400, 20, 2624); + AddAlphaRegion(10, 10, 400, 20); + + AddHtmlLocalized(10, 10, 400, 20, 1060635, 30720); //
WARNING
+ + AddImageTiled(10, 40, 400, 200, 2624); + AddAlphaRegion(10, 40, 400, 200); + + /* You are about to demolish your house. + * You will be refunded the house's value directly to your bank box. + * All items in the house will remain behind and can be freely picked up by anyone. + * Once the house is demolished, anyone can attempt to place a new house on the vacant land. + * This action will not un-condemn any other houses on your account, nor will it end your 7-day waiting period (if it applies to you). + * Are you sure you wish to continue? + */ + AddHtmlLocalized(10, 40, 400, 200, 1061795, 32512, false, true); + + AddImageTiled(10, 250, 400, 20, 2624); + AddAlphaRegion(10, 250, 400, 20); + + AddButton(10, 250, 4005, 4007, 1); + AddHtmlLocalized(40, 250, 170, 20, 1011036, 32767); // OKAY + + AddButton(210, 250, 4005, 4007, 0); + AddHtmlLocalized(240, 250, 170, 20, 1011012, 32767); // CANCEL + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (info.ButtonID == 1 && !m_House.Deleted) + { + if (m_House.IsOwner(m_Mobile)) + { + if (m_House.MovingCrate != null || m_House.InternalizedVendors.Count > 0) return; + + if (!Guild.NewGuildSystem && m_House.FindGuildstone() != null) + { + m_Mobile.SendLocalizedMessage(501389); // You cannot redeed a house with a guildstone inside. + return; + } + + /*else if (m_House.PlayerVendors.Count > 0) + { + m_Mobile.SendLocalizedMessage( 503236 ); // You need to collect your vendor's belongings before moving. + return; + }*/ + if (m_House.HasRentedVendors && m_House.VendorInventories.Count > 0) + { + m_Mobile.SendLocalizedMessage( + 1062679 + ); // You cannot do that that while you still have contract vendors or unclaimed contract vendor inventory in your house. + return; + } + + if (m_House.HasRentedVendors) + { + m_Mobile.SendLocalizedMessage( + 1062680 + ); // You cannot do that that while you still have contract vendors in your house. + return; + } + + if (m_House.VendorInventories.Count > 0) + { + m_Mobile.SendLocalizedMessage( + 1062681 + ); // You cannot do that that while you still have unclaimed contract vendor inventory in your house. + return; + } + + if (m_Mobile.AccessLevel >= AccessLevel.GameMaster) + { + m_Mobile.SendMessage("You do not get a refund for your house as you are not a player"); + m_House.RemoveKeys(m_Mobile); + m_House.Delete(); + } + else + { + Item toGive = null; + + if (m_House.IsAosRules) + { + if (m_House.Price > 0) + toGive = new BankCheck(m_House.Price); + else + toGive = m_House.GetDeed(); + } + else + { + toGive = m_House.GetDeed(); + + if (toGive == null && m_House.Price > 0) + toGive = new BankCheck(m_House.Price); + } + + var check = toGive as BankCheck; + + if (AccountGold.Enabled && check != null) + { + var worth = check.Worth; + + if (m_Mobile.Account?.DepositGold(worth) == true) + { + check.Delete(); + + m_Mobile.SendLocalizedMessage(1060397, worth.ToString("#,0")); + // ~1_AMOUNT~ gold has been deposited into your bank box. + + m_House.RemoveKeys(m_Mobile); + m_House.Delete(); + return; + } + } + + if (toGive != null) + { + var box = m_Mobile.BankBox; + + if (box.TryDropItem(m_Mobile, toGive, false)) + { + if (check != null) + m_Mobile.SendLocalizedMessage( + 1060397, + check.Worth.ToString() + ); // ~1_AMOUNT~ gold has been deposited into your bank box. + + m_House.RemoveKeys(m_Mobile); + m_House.Delete(); + } + else + { + toGive.Delete(); + m_Mobile.SendLocalizedMessage(500390); // Your bank box is full. + } + } + else + { + m_Mobile.SendMessage("Unable to refund house."); + } + } + } + else + { + m_Mobile.SendLocalizedMessage(501320); // Only the house owner may do this. + } + } + } + } +} diff --git a/Projects/UOContent/Gumps/HouseGump.cs b/Projects/UOContent/Gumps/HouseGump.cs index 5471ec842..975486884 100644 --- a/Projects/UOContent/Gumps/HouseGump.cs +++ b/Projects/UOContent/Gumps/HouseGump.cs @@ -1,738 +1,761 @@ -using System.Collections.Generic; -using Server.Guilds; -using Server.Multis; -using Server.Network; -using Server.Prompts; - -namespace Server.Gumps -{ - public class HouseListGump : Gump - { - private readonly BaseHouse m_House; - - public HouseListGump(int number, List list, BaseHouse house, bool accountOf) : base(20, 30) - { - if (house.Deleted) - return; - - m_House = house; - - AddPage(0); - - AddBackground(0, 0, 420, 430, 5054); - AddBackground(10, 10, 400, 410, 3000); - - AddButton(20, 388, 4005, 4007, 0); - AddHtmlLocalized(55, 388, 300, 20, 1011104); // Return to previous menu - - AddHtmlLocalized(20, 20, 350, 20, number); - - if (list == null) - return; - - for (int i = 0; i < list.Count; ++i) - { - if (i % 16 == 0) - { - if (i != 0) AddButton(370, 20, 4005, 4007, 0, GumpButtonType.Page, i / 16 + 1); - - AddPage(i / 16 + 1); - - if (i != 0) AddButton(340, 20, 4014, 4016, 0, GumpButtonType.Page, i / 16); - } - - Mobile m = list[i]; - - string name; - - if (m == null || (name = m.Name) == null || (name = name.Trim()).Length <= 0) - continue; - - AddLabel(55, 55 + i % 16 * 20, 0, accountOf && m.Player && m.Account != null - ? $"Account of {name}" - : name); - } - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (m_House.Deleted) - return; - - Mobile from = state.Mobile; - - from.SendGump(new HouseGump(from, m_House)); - } - } - - public class HouseRemoveGump : Gump - { - private readonly bool m_AccountOf; - private readonly BaseHouse m_House; - private readonly List m_List; - private readonly List m_Copy; - private readonly int m_Number; - - public HouseRemoveGump(int number, List list, BaseHouse house, bool accountOf) : base(20, 30) - { - if (house.Deleted) - return; - - m_House = house; - m_List = list; - m_Number = number; - m_AccountOf = accountOf; - - AddPage(0); - - AddBackground(0, 0, 420, 430, 5054); - AddBackground(10, 10, 400, 410, 3000); - - AddButton(20, 388, 4005, 4007, 0); - AddHtmlLocalized(55, 388, 300, 20, 1011104); // Return to previous menu - - AddButton(20, 365, 4005, 4007, 1); - AddHtmlLocalized(55, 365, 300, 20, 1011270); // Remove now! - - AddHtmlLocalized(20, 20, 350, 20, number); - - if (list == null) - return; - - m_Copy = new List(list); - - for (int i = 0; i < list.Count; ++i) - { - if (i % 15 == 0) - { - if (i != 0) AddButton(370, 20, 4005, 4007, 0, GumpButtonType.Page, i / 15 + 1); - - AddPage(i / 15 + 1); - - if (i != 0) AddButton(340, 20, 4014, 4016, 0, GumpButtonType.Page, i / 15); - } - - Mobile m = list[i]; - - string name; - - if (m == null || (name = m.Name) == null || (name = name.Trim()).Length <= 0) - continue; - - AddCheck(34, 52 + i % 15 * 20, 0xD2, 0xD3, false, i); - AddLabel(55, 52 + i % 15 * 20, 0, accountOf && m.Player && m.Account != null - ? $"Account of {name}" - : name); - } - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (m_House.Deleted) - return; - - Mobile from = state.Mobile; - - if (m_List != null && info.ButtonID == 1) // Remove now - { - int[] switches = info.Switches; - - if (switches.Length > 0) - { - for (int i = 0; i < switches.Length; ++i) - { - int index = switches[i]; - - if (index >= 0 && index < m_Copy.Count) - m_List.Remove(m_Copy[index]); - } - - if (m_List.Count > 0) - { - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - from.SendGump(new HouseRemoveGump(m_Number, m_List, m_House, m_AccountOf)); - return; - } - } - } - - from.SendGump(new HouseGump(from, m_House)); - } - } - - public class HouseGump : Gump - { - private readonly BaseHouse m_House; - - public HouseGump(Mobile from, BaseHouse house) : base(20, 30) - { - if (house.Deleted) - return; - - m_House = house; - - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - - bool isCombatRestricted = house.IsCombatRestricted(from); - - bool isOwner = m_House.IsOwner(from); - bool isCoOwner = isOwner || m_House.IsCoOwner(from); - bool isFriend = isCoOwner || m_House.IsFriend(from); - - if (isCombatRestricted) - isFriend = isCoOwner = isOwner = false; - - AddPage(0); - - if (isFriend) - { - AddBackground(0, 0, 420, 430, 5054); - AddBackground(10, 10, 400, 410, 3000); - } - - AddImage(130, 0, 100); - - if (m_House.Sign != null) - { - List lines = Wrap(m_House.Sign.GetName()); - - for (int i = 0, y = (101 - lines.Count * 14) / 2; i < lines.Count; ++i, y += 14) - { - string s = lines[i]; - - AddLabel(130 + (143 - s.Length * 8) / 2, y, 0, s); - } - } - - if (!isFriend) - return; - - AddHtmlLocalized(55, 103, 75, 20, 1011233); // INFO - AddButton(20, 103, 4005, 4007, 0, GumpButtonType.Page, 1); - - AddHtmlLocalized(170, 103, 75, 20, 1011234); // FRIENDS - AddButton(135, 103, 4005, 4007, 0, GumpButtonType.Page, 2); - - AddHtmlLocalized(295, 103, 75, 20, 1011235); // OPTIONS - AddButton(260, 103, 4005, 4007, 0, GumpButtonType.Page, 3); - - AddHtmlLocalized(295, 390, 75, 20, 1011441); // EXIT - AddButton(260, 390, 4005, 4007, 0); - - AddHtmlLocalized(55, 390, 200, 20, 1011236); // Change this house's name! - AddButton(20, 390, 4005, 4007, 1); - - // Info page - AddPage(1); - - AddHtmlLocalized(20, 135, 100, 20, 1011242); // Owned by: - AddHtml(120, 135, 100, 20, GetOwnerName()); - - AddHtmlLocalized(20, 170, 275, 20, 1011237); // Number of locked down items: - AddHtml(320, 170, 50, 20, m_House.LockDownCount.ToString()); - - AddHtmlLocalized(20, 190, 275, 20, 1011238); // Maximum locked down items: - AddHtml(320, 190, 50, 20, m_House.MaxLockDowns.ToString()); - - AddHtmlLocalized(20, 210, 275, 20, 1011239); // Number of secure containers: - AddHtml(320, 210, 50, 20, m_House.SecureCount.ToString()); - - AddHtmlLocalized(20, 230, 275, 20, 1011240); // Maximum number of secure containers: - AddHtml(320, 230, 50, 20, m_House.MaxSecures.ToString()); - - AddHtmlLocalized(20, 260, 400, 20, 1018032); // This house is properly placed. - AddHtmlLocalized(20, 280, 400, 20, 1018035); // This house is of modern design. - - if (m_House.Public) - { - // TODO: Validate exact placement - AddHtmlLocalized(20, 305, 275, 20, 1011241); // Number of visits this building has had - AddHtml(320, 305, 50, 20, m_House.Visits.ToString()); - } - - // Friends page - AddPage(2); - - AddHtmlLocalized(45, 130, 150, 20, 1011266); // List of co-owners - AddButton(20, 130, 2714, 2715, 2); - - AddHtmlLocalized(45, 150, 150, 20, 1011267); // Add a co-owner - AddButton(20, 150, 2714, 2715, 3); - - AddHtmlLocalized(45, 170, 150, 20, 1018036); // Remove a co-owner - AddButton(20, 170, 2714, 2715, 4); - - AddHtmlLocalized(45, 190, 150, 20, 1011268); // Clear co-owner list - AddButton(20, 190, 2714, 2715, 5); - - AddHtmlLocalized(225, 130, 155, 20, 1011243); // List of Friends - AddButton(200, 130, 2714, 2715, 6); - - AddHtmlLocalized(225, 150, 155, 20, 1011244); // Add a Friend - AddButton(200, 150, 2714, 2715, 7); - - AddHtmlLocalized(225, 170, 155, 20, 1018037); // Remove a Friend - AddButton(200, 170, 2714, 2715, 8); - - AddHtmlLocalized(225, 190, 155, 20, 1011245); // Clear Friends list - AddButton(200, 190, 2714, 2715, 9); - - AddHtmlLocalized(120, 215, 280, 20, 1011258); // Ban someone from the house - AddButton(95, 215, 2714, 2715, 10); - - AddHtmlLocalized(120, 235, 280, 20, 1011259); // Eject someone from the house - AddButton(95, 235, 2714, 2715, 11); - - AddHtmlLocalized(120, 255, 280, 20, 1011260); // View a list of banned people - AddButton(95, 255, 2714, 2715, 12); - - AddHtmlLocalized(120, 275, 280, 20, 1011261); // Lift a ban - AddButton(95, 275, 2714, 2715, 13); - - // Options page - AddPage(3); - - AddHtmlLocalized(45, 150, 355, 30, 1011248); // Transfer ownership of the house - AddButton(20, 150, 2714, 2715, 14); - - AddHtmlLocalized(45, 180, 355, 30, 1011249); // Demolish house and get deed back - AddButton(20, 180, 2714, 2715, 15); - - if (!m_House.Public) - { - AddHtmlLocalized(45, 210, 355, 30, 1011247); // Change the house locks - AddButton(20, 210, 2714, 2715, 16); - - AddHtmlLocalized(45, 240, 350, 90, 1011253); // Declare this building to be public. This will make your front door unlockable. - AddButton(20, 240, 2714, 2715, 17); - } - else - { - // AddHtmlLocalized( 45, 280, 350, 30, 1011250, false, false ); // Change the sign type - AddHtmlLocalized(45, 210, 350, 30, 1011250); // Change the sign type - AddButton(20, 210, 2714, 2715, 0, GumpButtonType.Page, 4); - - AddHtmlLocalized(45, 240, 350, 30, 1011252); // Declare this building to be private. - AddButton(20, 240, 2714, 2715, 17); - - // Change the sign type - AddPage(4); - - for (int i = 0; i < 24; ++i) - { - AddRadio(53 + i / 4 * 50, 137 + i % 4 * 35, 210, 211, false, i + 1); - AddItem(60 + i / 4 * 50, 130 + i % 4 * 35, 2980 + i * 2); - } - - AddHtmlLocalized(200, 305, 129, 20, 1011254); // Guild sign choices - AddButton(350, 305, 252, 253, 0, GumpButtonType.Page, 5); - - AddHtmlLocalized(200, 340, 355, 30, 1011277); // Okay that is fine. - AddButton(350, 340, 4005, 4007, 18); - - AddPage(5); - - for (int i = 0; i < 29; ++i) - { - AddRadio(53 + i / 5 * 50, 137 + i % 5 * 35, 210, 211, false, i + 25); - AddItem(60 + i / 5 * 50, 130 + i % 5 * 35, 3028 + i * 2); - } - - AddHtmlLocalized(200, 305, 129, 20, 1011255); // Shop sign choices - AddButton(350, 305, 250, 251, 0, GumpButtonType.Page, 4); - - AddHtmlLocalized(200, 340, 355, 30, 1011277); // Okay that is fine. - AddButton(350, 340, 4005, 4007, 18); - } - } - - private List Wrap(string value) - { - if (value == null || (value = value.Trim()).Length <= 0) - return null; - - string[] values = value.Split(' '); - List list = new List(); - string current = ""; - - for (int i = 0; i < values.Length; ++i) - { - string val = values[i]; - - string v = current.Length == 0 ? val : $"{current} {val}"; - - if (v.Length < 10) - { - current = v; - } - else if (v.Length == 10) - { - list.Add(v); - - if (list.Count == 6) - return list; - - current = ""; - } - else if (val.Length <= 10) - { - list.Add(current); - - if (list.Count == 6) - return list; - - current = val; - } - else - { - while (v.Length >= 10) - { - list.Add(v.Substring(0, 10)); - - if (list.Count == 6) - return list; - - v = v.Substring(10); - } - - current = v; - } - } - - if (current.Length > 0) - list.Add(current); - - return list; - } - - private string GetOwnerName() - { - Mobile m = m_House.Owner; - - if (m == null) - return "(unowned)"; - - string name; - - if ((name = m.Name) == null || (name = name.Trim()).Length <= 0) - name = "(no name)"; - - return name; - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_House.Deleted) - return; - - Mobile from = sender.Mobile; - - bool isCombatRestricted = m_House.IsCombatRestricted(from); - - bool isOwner = m_House.IsOwner(from); - bool isCoOwner = isOwner || m_House.IsCoOwner(from); - bool isFriend = isCoOwner || m_House.IsFriend(from); - - if (isCombatRestricted) - isFriend = isCoOwner = isOwner = false; - - if (!isFriend || !from.Alive) - return; - - Item sign = m_House.Sign; - - if (sign == null || from.Map != sign.Map || !from.InRange(sign.GetWorldLocation(), 18)) - return; - - switch (info.ButtonID) - { - case 1: // Rename sign - { - from.Prompt = new RenamePrompt(m_House); - from.SendLocalizedMessage(501302); // What dost thou wish the sign to say? - - break; - } - case 2: // List of co-owners - { - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - from.SendGump(new HouseListGump(1011275, m_House.CoOwners, m_House, false)); - - break; - } - case 3: // Add co-owner - { - if (isOwner) - { - from.SendLocalizedMessage( - 501328); // Target the person you wish to name a co-owner of your household. - from.Target = new CoOwnerTarget(true, m_House); - } - else - { - from.SendLocalizedMessage(501327); // Only the house owner may add Co-owners. - } - - break; - } - case 4: // Remove co-owner - { - if (isOwner) - { - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - from.SendGump(new HouseRemoveGump(1011274, m_House.CoOwners, m_House, false)); - } - else - { - from.SendLocalizedMessage(501329); // Only the house owner may remove co-owners. - } - - break; - } - case 5: // Clear co-owners - { - if (isOwner) - { - m_House.CoOwners?.Clear(); - - from.SendLocalizedMessage(501333); // All co-owners have been removed from this house. - } - else - { - from.SendLocalizedMessage(501330); // Only the house owner may remove co-owners. - } - - break; - } - case 6: // List friends - { - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - from.SendGump(new HouseListGump(1011273, m_House.Friends, m_House, false)); - - break; - } - case 7: // Add friend - { - if (isCoOwner) - { - from.SendLocalizedMessage(501317); // Target the person you wish to name a friend of your household. - from.Target = new HouseFriendTarget(true, m_House); - } - else - { - from.SendLocalizedMessage(501316); // Only the house owner may add friends. - } - - break; - } - case 8: // Remove friend - { - if (isCoOwner) - { - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - from.SendGump(new HouseRemoveGump(1011272, m_House.Friends, m_House, false)); - } - else - { - from.SendLocalizedMessage(501318); // Only the house owner may remove friends. - } - - break; - } - case 9: // Clear friends - { - if (isCoOwner) - { - m_House.Friends?.Clear(); - - from.SendLocalizedMessage(501332); // All friends have been removed from this house. - } - else - { - from.SendLocalizedMessage(501319); // Only the house owner may remove friends. - } - - break; - } - case 10: // Ban - { - from.SendLocalizedMessage(501325); // Target the individual to ban from this house. - from.Target = new HouseBanTarget(true, m_House); - - break; - } - case 11: // Eject - { - from.SendLocalizedMessage(501326); // Target the individual to eject from this house. - from.Target = new HouseKickTarget(m_House); - - break; - } - case 12: // List bans - { - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - from.SendGump(new HouseListGump(1011271, m_House.Bans, m_House, true)); - - break; - } - case 13: // Remove ban - { - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - from.SendGump(new HouseRemoveGump(1011269, m_House.Bans, m_House, true)); - - break; - } - case 14: // Transfer ownership - { - if (isOwner) - { - from.SendLocalizedMessage(501309); // Target the person to whom you wish to give this house. - from.Target = new HouseOwnerTarget(m_House); - } - else - { - from.SendLocalizedMessage(501310); // Only the house owner may do this. - } - - break; - } - case 15: // Demolish house - { - if (isOwner) - { - if (!Guild.NewGuildSystem && m_House.FindGuildstone() != null) - { - from.SendLocalizedMessage(501389); // You cannot redeed a house with a guildstone inside. - } - else - { - from.CloseGump(); - from.SendGump(new HouseDemolishGump(from, m_House)); - } - } - else - { - from.SendLocalizedMessage(501320); // Only the house owner may do this. - } - - break; - } - case 16: // Change locks - { - if (m_House.Public) - { - from.SendLocalizedMessage(501669); // Public houses are always unlocked. - } - else - { - if (isOwner) - { - m_House.RemoveKeys(from); - m_House.ChangeLocks(from); - - from.SendLocalizedMessage( - 501306); // The locks on your front door have been changed, and new master keys have been placed in your bank and your backpack. - } - else - { - from.SendLocalizedMessage(501303); // Only the house owner may change the house locks. - } - } - - break; - } - case 17: // Declare public/private - { - if (isOwner) - { - if (m_House.Public && m_House.PlayerVendors.Count > 0) - { - from.SendLocalizedMessage( - 501887); // You have vendors working out of this building. It cannot be declared private until there are no vendors in place. - break; - } - - m_House.Public = !m_House.Public; - if (!m_House.Public) - { - m_House.ChangeLocks(from); - - from.SendLocalizedMessage(501888); // This house is now private. - from.SendLocalizedMessage( - 501306); // The locks on your front door have been changed, and new master keys have been placed in your bank and your backpack. - } - else - { - m_House.RemoveKeys(from); - m_House.RemoveLocks(); - from.SendLocalizedMessage( - 501886); // This house is now public. Friends of the house my now have vendors working out of this building. - } - } - else - { - from.SendLocalizedMessage(501307); // Only the house owner may do this. - } - - break; - } - case 18: // Change type - { - if (isOwner) - { - if (m_House.Public && info.Switches.Length > 0) - { - int index = info.Switches[0] - 1; - - if (index >= 0 && index < 53) - m_House.ChangeSignType(2980 + index * 2); - } - } - else - { - from.SendLocalizedMessage(501307); // Only the house owner may do this. - } - - break; - } - } - } - } -} - -namespace Server.Prompts -{ - public class RenamePrompt : Prompt - { - private readonly BaseHouse m_House; - - public RenamePrompt(BaseHouse house) => m_House = house; - - public override void OnResponse(Mobile from, string text) - { - if (m_House.IsFriend(from)) - { - if (m_House.Sign != null) - m_House.Sign.Name = text; - - from.SendMessage("Sign changed."); - } - } - } -} +using System.Collections.Generic; +using Server.Guilds; +using Server.Multis; +using Server.Network; +using Server.Prompts; + +namespace Server.Gumps +{ + public class HouseListGump : Gump + { + private readonly BaseHouse m_House; + + public HouseListGump(int number, List list, BaseHouse house, bool accountOf) : base(20, 30) + { + if (house.Deleted) + return; + + m_House = house; + + AddPage(0); + + AddBackground(0, 0, 420, 430, 5054); + AddBackground(10, 10, 400, 410, 3000); + + AddButton(20, 388, 4005, 4007, 0); + AddHtmlLocalized(55, 388, 300, 20, 1011104); // Return to previous menu + + AddHtmlLocalized(20, 20, 350, 20, number); + + if (list == null) + return; + + for (var i = 0; i < list.Count; ++i) + { + if (i % 16 == 0) + { + if (i != 0) AddButton(370, 20, 4005, 4007, 0, GumpButtonType.Page, i / 16 + 1); + + AddPage(i / 16 + 1); + + if (i != 0) AddButton(340, 20, 4014, 4016, 0, GumpButtonType.Page, i / 16); + } + + var m = list[i]; + + string name; + + if (m == null || (name = m.Name) == null || (name = name.Trim()).Length <= 0) + continue; + + AddLabel( + 55, + 55 + i % 16 * 20, + 0, + accountOf && m.Player && m.Account != null + ? $"Account of {name}" + : name + ); + } + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (m_House.Deleted) + return; + + var from = state.Mobile; + + from.SendGump(new HouseGump(from, m_House)); + } + } + + public class HouseRemoveGump : Gump + { + private readonly bool m_AccountOf; + private readonly List m_Copy; + private readonly BaseHouse m_House; + private readonly List m_List; + private readonly int m_Number; + + public HouseRemoveGump(int number, List list, BaseHouse house, bool accountOf) : base(20, 30) + { + if (house.Deleted) + return; + + m_House = house; + m_List = list; + m_Number = number; + m_AccountOf = accountOf; + + AddPage(0); + + AddBackground(0, 0, 420, 430, 5054); + AddBackground(10, 10, 400, 410, 3000); + + AddButton(20, 388, 4005, 4007, 0); + AddHtmlLocalized(55, 388, 300, 20, 1011104); // Return to previous menu + + AddButton(20, 365, 4005, 4007, 1); + AddHtmlLocalized(55, 365, 300, 20, 1011270); // Remove now! + + AddHtmlLocalized(20, 20, 350, 20, number); + + if (list == null) + return; + + m_Copy = new List(list); + + for (var i = 0; i < list.Count; ++i) + { + if (i % 15 == 0) + { + if (i != 0) AddButton(370, 20, 4005, 4007, 0, GumpButtonType.Page, i / 15 + 1); + + AddPage(i / 15 + 1); + + if (i != 0) AddButton(340, 20, 4014, 4016, 0, GumpButtonType.Page, i / 15); + } + + var m = list[i]; + + string name; + + if (m == null || (name = m.Name) == null || (name = name.Trim()).Length <= 0) + continue; + + AddCheck(34, 52 + i % 15 * 20, 0xD2, 0xD3, false, i); + AddLabel( + 55, + 52 + i % 15 * 20, + 0, + accountOf && m.Player && m.Account != null + ? $"Account of {name}" + : name + ); + } + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (m_House.Deleted) + return; + + var from = state.Mobile; + + if (m_List != null && info.ButtonID == 1) // Remove now + { + var switches = info.Switches; + + if (switches.Length > 0) + { + for (var i = 0; i < switches.Length; ++i) + { + var index = switches[i]; + + if (index >= 0 && index < m_Copy.Count) + m_List.Remove(m_Copy[index]); + } + + if (m_List.Count > 0) + { + from.CloseGump(); + from.CloseGump(); + from.CloseGump(); + from.SendGump(new HouseRemoveGump(m_Number, m_List, m_House, m_AccountOf)); + return; + } + } + } + + from.SendGump(new HouseGump(from, m_House)); + } + } + + public class HouseGump : Gump + { + private readonly BaseHouse m_House; + + public HouseGump(Mobile from, BaseHouse house) : base(20, 30) + { + if (house.Deleted) + return; + + m_House = house; + + from.CloseGump(); + from.CloseGump(); + from.CloseGump(); + + var isCombatRestricted = house.IsCombatRestricted(from); + + var isOwner = m_House.IsOwner(from); + var isCoOwner = isOwner || m_House.IsCoOwner(from); + var isFriend = isCoOwner || m_House.IsFriend(from); + + if (isCombatRestricted) + isFriend = isCoOwner = isOwner = false; + + AddPage(0); + + if (isFriend) + { + AddBackground(0, 0, 420, 430, 5054); + AddBackground(10, 10, 400, 410, 3000); + } + + AddImage(130, 0, 100); + + if (m_House.Sign != null) + { + var lines = Wrap(m_House.Sign.GetName()); + + for (int i = 0, y = (101 - lines.Count * 14) / 2; i < lines.Count; ++i, y += 14) + { + var s = lines[i]; + + AddLabel(130 + (143 - s.Length * 8) / 2, y, 0, s); + } + } + + if (!isFriend) + return; + + AddHtmlLocalized(55, 103, 75, 20, 1011233); // INFO + AddButton(20, 103, 4005, 4007, 0, GumpButtonType.Page, 1); + + AddHtmlLocalized(170, 103, 75, 20, 1011234); // FRIENDS + AddButton(135, 103, 4005, 4007, 0, GumpButtonType.Page, 2); + + AddHtmlLocalized(295, 103, 75, 20, 1011235); // OPTIONS + AddButton(260, 103, 4005, 4007, 0, GumpButtonType.Page, 3); + + AddHtmlLocalized(295, 390, 75, 20, 1011441); // EXIT + AddButton(260, 390, 4005, 4007, 0); + + AddHtmlLocalized(55, 390, 200, 20, 1011236); // Change this house's name! + AddButton(20, 390, 4005, 4007, 1); + + // Info page + AddPage(1); + + AddHtmlLocalized(20, 135, 100, 20, 1011242); // Owned by: + AddHtml(120, 135, 100, 20, GetOwnerName()); + + AddHtmlLocalized(20, 170, 275, 20, 1011237); // Number of locked down items: + AddHtml(320, 170, 50, 20, m_House.LockDownCount.ToString()); + + AddHtmlLocalized(20, 190, 275, 20, 1011238); // Maximum locked down items: + AddHtml(320, 190, 50, 20, m_House.MaxLockDowns.ToString()); + + AddHtmlLocalized(20, 210, 275, 20, 1011239); // Number of secure containers: + AddHtml(320, 210, 50, 20, m_House.SecureCount.ToString()); + + AddHtmlLocalized(20, 230, 275, 20, 1011240); // Maximum number of secure containers: + AddHtml(320, 230, 50, 20, m_House.MaxSecures.ToString()); + + AddHtmlLocalized(20, 260, 400, 20, 1018032); // This house is properly placed. + AddHtmlLocalized(20, 280, 400, 20, 1018035); // This house is of modern design. + + if (m_House.Public) + { + // TODO: Validate exact placement + AddHtmlLocalized(20, 305, 275, 20, 1011241); // Number of visits this building has had + AddHtml(320, 305, 50, 20, m_House.Visits.ToString()); + } + + // Friends page + AddPage(2); + + AddHtmlLocalized(45, 130, 150, 20, 1011266); // List of co-owners + AddButton(20, 130, 2714, 2715, 2); + + AddHtmlLocalized(45, 150, 150, 20, 1011267); // Add a co-owner + AddButton(20, 150, 2714, 2715, 3); + + AddHtmlLocalized(45, 170, 150, 20, 1018036); // Remove a co-owner + AddButton(20, 170, 2714, 2715, 4); + + AddHtmlLocalized(45, 190, 150, 20, 1011268); // Clear co-owner list + AddButton(20, 190, 2714, 2715, 5); + + AddHtmlLocalized(225, 130, 155, 20, 1011243); // List of Friends + AddButton(200, 130, 2714, 2715, 6); + + AddHtmlLocalized(225, 150, 155, 20, 1011244); // Add a Friend + AddButton(200, 150, 2714, 2715, 7); + + AddHtmlLocalized(225, 170, 155, 20, 1018037); // Remove a Friend + AddButton(200, 170, 2714, 2715, 8); + + AddHtmlLocalized(225, 190, 155, 20, 1011245); // Clear Friends list + AddButton(200, 190, 2714, 2715, 9); + + AddHtmlLocalized(120, 215, 280, 20, 1011258); // Ban someone from the house + AddButton(95, 215, 2714, 2715, 10); + + AddHtmlLocalized(120, 235, 280, 20, 1011259); // Eject someone from the house + AddButton(95, 235, 2714, 2715, 11); + + AddHtmlLocalized(120, 255, 280, 20, 1011260); // View a list of banned people + AddButton(95, 255, 2714, 2715, 12); + + AddHtmlLocalized(120, 275, 280, 20, 1011261); // Lift a ban + AddButton(95, 275, 2714, 2715, 13); + + // Options page + AddPage(3); + + AddHtmlLocalized(45, 150, 355, 30, 1011248); // Transfer ownership of the house + AddButton(20, 150, 2714, 2715, 14); + + AddHtmlLocalized(45, 180, 355, 30, 1011249); // Demolish house and get deed back + AddButton(20, 180, 2714, 2715, 15); + + if (!m_House.Public) + { + AddHtmlLocalized(45, 210, 355, 30, 1011247); // Change the house locks + AddButton(20, 210, 2714, 2715, 16); + + AddHtmlLocalized( + 45, + 240, + 350, + 90, + 1011253 + ); // Declare this building to be public. This will make your front door unlockable. + AddButton(20, 240, 2714, 2715, 17); + } + else + { + // AddHtmlLocalized( 45, 280, 350, 30, 1011250, false, false ); // Change the sign type + AddHtmlLocalized(45, 210, 350, 30, 1011250); // Change the sign type + AddButton(20, 210, 2714, 2715, 0, GumpButtonType.Page, 4); + + AddHtmlLocalized(45, 240, 350, 30, 1011252); // Declare this building to be private. + AddButton(20, 240, 2714, 2715, 17); + + // Change the sign type + AddPage(4); + + for (var i = 0; i < 24; ++i) + { + AddRadio(53 + i / 4 * 50, 137 + i % 4 * 35, 210, 211, false, i + 1); + AddItem(60 + i / 4 * 50, 130 + i % 4 * 35, 2980 + i * 2); + } + + AddHtmlLocalized(200, 305, 129, 20, 1011254); // Guild sign choices + AddButton(350, 305, 252, 253, 0, GumpButtonType.Page, 5); + + AddHtmlLocalized(200, 340, 355, 30, 1011277); // Okay that is fine. + AddButton(350, 340, 4005, 4007, 18); + + AddPage(5); + + for (var i = 0; i < 29; ++i) + { + AddRadio(53 + i / 5 * 50, 137 + i % 5 * 35, 210, 211, false, i + 25); + AddItem(60 + i / 5 * 50, 130 + i % 5 * 35, 3028 + i * 2); + } + + AddHtmlLocalized(200, 305, 129, 20, 1011255); // Shop sign choices + AddButton(350, 305, 250, 251, 0, GumpButtonType.Page, 4); + + AddHtmlLocalized(200, 340, 355, 30, 1011277); // Okay that is fine. + AddButton(350, 340, 4005, 4007, 18); + } + } + + private List Wrap(string value) + { + if (value == null || (value = value.Trim()).Length <= 0) + return null; + + var values = value.Split(' '); + var list = new List(); + var current = ""; + + for (var i = 0; i < values.Length; ++i) + { + var val = values[i]; + + var v = current.Length == 0 ? val : $"{current} {val}"; + + if (v.Length < 10) + { + current = v; + } + else if (v.Length == 10) + { + list.Add(v); + + if (list.Count == 6) + return list; + + current = ""; + } + else if (val.Length <= 10) + { + list.Add(current); + + if (list.Count == 6) + return list; + + current = val; + } + else + { + while (v.Length >= 10) + { + list.Add(v.Substring(0, 10)); + + if (list.Count == 6) + return list; + + v = v.Substring(10); + } + + current = v; + } + } + + if (current.Length > 0) + list.Add(current); + + return list; + } + + private string GetOwnerName() + { + var m = m_House.Owner; + + if (m == null) + return "(unowned)"; + + string name; + + if ((name = m.Name) == null || (name = name.Trim()).Length <= 0) + name = "(no name)"; + + return name; + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_House.Deleted) + return; + + var from = sender.Mobile; + + var isCombatRestricted = m_House.IsCombatRestricted(from); + + var isOwner = m_House.IsOwner(from); + var isCoOwner = isOwner || m_House.IsCoOwner(from); + var isFriend = isCoOwner || m_House.IsFriend(from); + + if (isCombatRestricted) + isFriend = isCoOwner = isOwner = false; + + if (!isFriend || !from.Alive) + return; + + Item sign = m_House.Sign; + + if (sign == null || from.Map != sign.Map || !from.InRange(sign.GetWorldLocation(), 18)) + return; + + switch (info.ButtonID) + { + case 1: // Rename sign + { + from.Prompt = new RenamePrompt(m_House); + from.SendLocalizedMessage(501302); // What dost thou wish the sign to say? + + break; + } + case 2: // List of co-owners + { + from.CloseGump(); + from.CloseGump(); + from.CloseGump(); + from.SendGump(new HouseListGump(1011275, m_House.CoOwners, m_House, false)); + + break; + } + case 3: // Add co-owner + { + if (isOwner) + { + from.SendLocalizedMessage( + 501328 + ); // Target the person you wish to name a co-owner of your household. + from.Target = new CoOwnerTarget(true, m_House); + } + else + { + from.SendLocalizedMessage(501327); // Only the house owner may add Co-owners. + } + + break; + } + case 4: // Remove co-owner + { + if (isOwner) + { + from.CloseGump(); + from.CloseGump(); + from.CloseGump(); + from.SendGump(new HouseRemoveGump(1011274, m_House.CoOwners, m_House, false)); + } + else + { + from.SendLocalizedMessage(501329); // Only the house owner may remove co-owners. + } + + break; + } + case 5: // Clear co-owners + { + if (isOwner) + { + m_House.CoOwners?.Clear(); + + from.SendLocalizedMessage(501333); // All co-owners have been removed from this house. + } + else + { + from.SendLocalizedMessage(501330); // Only the house owner may remove co-owners. + } + + break; + } + case 6: // List friends + { + from.CloseGump(); + from.CloseGump(); + from.CloseGump(); + from.SendGump(new HouseListGump(1011273, m_House.Friends, m_House, false)); + + break; + } + case 7: // Add friend + { + if (isCoOwner) + { + from.SendLocalizedMessage( + 501317 + ); // Target the person you wish to name a friend of your household. + from.Target = new HouseFriendTarget(true, m_House); + } + else + { + from.SendLocalizedMessage(501316); // Only the house owner may add friends. + } + + break; + } + case 8: // Remove friend + { + if (isCoOwner) + { + from.CloseGump(); + from.CloseGump(); + from.CloseGump(); + from.SendGump(new HouseRemoveGump(1011272, m_House.Friends, m_House, false)); + } + else + { + from.SendLocalizedMessage(501318); // Only the house owner may remove friends. + } + + break; + } + case 9: // Clear friends + { + if (isCoOwner) + { + m_House.Friends?.Clear(); + + from.SendLocalizedMessage(501332); // All friends have been removed from this house. + } + else + { + from.SendLocalizedMessage(501319); // Only the house owner may remove friends. + } + + break; + } + case 10: // Ban + { + from.SendLocalizedMessage(501325); // Target the individual to ban from this house. + from.Target = new HouseBanTarget(true, m_House); + + break; + } + case 11: // Eject + { + from.SendLocalizedMessage(501326); // Target the individual to eject from this house. + from.Target = new HouseKickTarget(m_House); + + break; + } + case 12: // List bans + { + from.CloseGump(); + from.CloseGump(); + from.CloseGump(); + from.SendGump(new HouseListGump(1011271, m_House.Bans, m_House, true)); + + break; + } + case 13: // Remove ban + { + from.CloseGump(); + from.CloseGump(); + from.CloseGump(); + from.SendGump(new HouseRemoveGump(1011269, m_House.Bans, m_House, true)); + + break; + } + case 14: // Transfer ownership + { + if (isOwner) + { + from.SendLocalizedMessage(501309); // Target the person to whom you wish to give this house. + from.Target = new HouseOwnerTarget(m_House); + } + else + { + from.SendLocalizedMessage(501310); // Only the house owner may do this. + } + + break; + } + case 15: // Demolish house + { + if (isOwner) + { + if (!Guild.NewGuildSystem && m_House.FindGuildstone() != null) + { + from.SendLocalizedMessage(501389); // You cannot redeed a house with a guildstone inside. + } + else + { + from.CloseGump(); + from.SendGump(new HouseDemolishGump(from, m_House)); + } + } + else + { + from.SendLocalizedMessage(501320); // Only the house owner may do this. + } + + break; + } + case 16: // Change locks + { + if (m_House.Public) + { + from.SendLocalizedMessage(501669); // Public houses are always unlocked. + } + else + { + if (isOwner) + { + m_House.RemoveKeys(from); + m_House.ChangeLocks(from); + + from.SendLocalizedMessage( + 501306 + ); // The locks on your front door have been changed, and new master keys have been placed in your bank and your backpack. + } + else + { + from.SendLocalizedMessage(501303); // Only the house owner may change the house locks. + } + } + + break; + } + case 17: // Declare public/private + { + if (isOwner) + { + if (m_House.Public && m_House.PlayerVendors.Count > 0) + { + from.SendLocalizedMessage( + 501887 + ); // You have vendors working out of this building. It cannot be declared private until there are no vendors in place. + break; + } + + m_House.Public = !m_House.Public; + if (!m_House.Public) + { + m_House.ChangeLocks(from); + + from.SendLocalizedMessage(501888); // This house is now private. + from.SendLocalizedMessage( + 501306 + ); // The locks on your front door have been changed, and new master keys have been placed in your bank and your backpack. + } + else + { + m_House.RemoveKeys(from); + m_House.RemoveLocks(); + from.SendLocalizedMessage( + 501886 + ); // This house is now public. Friends of the house my now have vendors working out of this building. + } + } + else + { + from.SendLocalizedMessage(501307); // Only the house owner may do this. + } + + break; + } + case 18: // Change type + { + if (isOwner) + { + if (m_House.Public && info.Switches.Length > 0) + { + var index = info.Switches[0] - 1; + + if (index >= 0 && index < 53) + m_House.ChangeSignType(2980 + index * 2); + } + } + else + { + from.SendLocalizedMessage(501307); // Only the house owner may do this. + } + + break; + } + } + } + } +} + +namespace Server.Prompts +{ + public class RenamePrompt : Prompt + { + private readonly BaseHouse m_House; + + public RenamePrompt(BaseHouse house) => m_House = house; + + public override void OnResponse(Mobile from, string text) + { + if (m_House.IsFriend(from)) + { + if (m_House.Sign != null) + m_House.Sign.Name = text; + + from.SendMessage("Sign changed."); + } + } + } +} diff --git a/Projects/UOContent/Gumps/HouseGumpAOS.cs b/Projects/UOContent/Gumps/HouseGumpAOS.cs index 6c50681fc..9e6030409 100644 --- a/Projects/UOContent/Gumps/HouseGumpAOS.cs +++ b/Projects/UOContent/Gumps/HouseGumpAOS.cs @@ -1,1443 +1,1662 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Server.Guilds; -using Server.Items; -using Server.Mobiles; -using Server.Multis; -using Server.Network; -using Server.Prompts; - -namespace Server.Gumps -{ - public enum HouseGumpPageAOS - { - Information, - Security, - Storage, - Customize, - Ownership, - ChangeHanger, - ChangeFoundation, - ChangeSign, - RemoveCoOwner, - ListCoOwner, - RemoveFriend, - ListFriend, - RemoveBan, - ListBan, - RemoveAccess, - ListAccess, - ChangePost, - Vendors - } - - public class HouseGumpAOS : Gump - { - private const int LabelColor = 0x7FFF; - private const int SelectedColor = 0x421F; - private const int DisabledColor = 0x4210; - private const int WarningColor = 0x7E10; - - private const int LabelHue = 0x481; - private const int HighlightedLabelHue = 0x64; - - private static readonly int[] m_HangerNumbers = - { - 2968, 2970, 2972, - 2974, 2976, 2978 - }; - - private static readonly int[] m_FoundationNumbers = Core.ML - ? new[] - { - 20, 189, 765, 65, 101, 0x2DF7, 0x2DFB, 0x3672, 0x3676 - } - : new[] - { - 20, 189, 765, 65, 101 - }; - - private static readonly int[] m_PostNumbers = - { - 9, 29, 54, 90, 147, 169, - 177, 204, 251, 257, 263, - 298, 347, 424, 441, 466, - 514, 600, 601, 602, 603, - 660, 666, 672, 898, 970, - 974, 982 - }; - - private static readonly List _HouseSigns = new List(); - private readonly BaseHouse m_House; - - private List m_List; - private readonly HouseGumpPageAOS m_Page; - - public HouseGumpAOS(HouseGumpPageAOS page, Mobile from, BaseHouse house) : base(50, 40) - { - m_House = house; - m_Page = page; - - from.CloseGump(); - // from.CloseGump( typeof( HouseListGump ) ); - // from.CloseGump( typeof( HouseRemoveGump ) ); - - bool isCombatRestricted = house.IsCombatRestricted(from); - - bool isOwner = house.IsOwner(from); - bool isCoOwner = isOwner || house.IsCoOwner(from); - bool isFriend = isCoOwner || house.IsFriend(from); - - if (isCombatRestricted) - isFriend = isCoOwner = isOwner = false; - - AddPage(0); - - if (isFriend || page == HouseGumpPageAOS.Vendors) - { - AddBackground(0, 0, 420, page != HouseGumpPageAOS.Vendors ? 440 : 420, 5054); - - AddImageTiled(10, 10, 400, 100, 2624); - AddAlphaRegion(10, 10, 400, 100); - - AddImageTiled(10, 120, 400, 260, 2624); - AddAlphaRegion(10, 120, 400, 260); - - AddImageTiled(10, 390, 400, page != HouseGumpPageAOS.Vendors ? 40 : 20, 2624); - AddAlphaRegion(10, 390, 400, page != HouseGumpPageAOS.Vendors ? 40 : 20); - - AddButtonLabeled(250, page != HouseGumpPageAOS.Vendors ? 410 : 390, 0, 1060675); // CLOSE - } - - AddImage(10, 10, 100); - - if (m_House.Sign != null) - { - List lines = Wrap(m_House.Sign.GetName()); - - for (int i = 0, y = (114 - lines.Count * 14) / 2; i < lines.Count; ++i, y += 14) - { - string s = lines[i]; - - AddLabel(10 + (160 - s.Length * 8) / 2, y, 0, s); - } - } - - if (page == HouseGumpPageAOS.Vendors) - { - AddHtmlLocalized(10, 120, 400, 20, 1062428, LabelColor); //
SHOPS
- - AddList(house.AvailableVendorsFor(from), 1, false, false, from); - return; - } - - if (!isFriend) - return; - - if (house.Public) - { - AddButtonLabeled(10, 390, GetButtonID(0, 0), 1060674); // Banish - AddButtonLabeled(10, 410, GetButtonID(0, 1), 1011261); // Lift a Ban - } - else - { - AddButtonLabeled(10, 390, GetButtonID(0, 2), 1060676); // Grant Access - AddButtonLabeled(10, 410, GetButtonID(0, 3), 1060677); // Revoke Access - } - - AddPageButton(150, 10, GetButtonID(1, 0), 1060668, HouseGumpPageAOS.Information); - AddPageButton(150, 30, GetButtonID(1, 1), 1060669, HouseGumpPageAOS.Security); - AddPageButton(150, 50, GetButtonID(1, 2), 1060670, HouseGumpPageAOS.Storage); - AddPageButton(150, 70, GetButtonID(1, 3), 1060671, HouseGumpPageAOS.Customize); - AddPageButton(150, 90, GetButtonID(1, 4), 1060672, HouseGumpPageAOS.Ownership); - - switch (page) - { - case HouseGumpPageAOS.Information: - { - AddHtmlLocalized(20, 130, 200, 20, 1011242, LabelColor); // Owned By: - AddLabel(210, 130, LabelHue, GetOwnerName()); - - AddHtmlLocalized(20, 170, 380, 20, 1018032, SelectedColor); // This house is properly placed. - AddHtmlLocalized(20, 190, 380, 20, 1018035, SelectedColor); // This house is of modern design. - AddHtmlLocalized(20, 210, 380, 20, house is HouseFoundation ? 1060681 : 1060680, SelectedColor); // This is a (pre | custom)-built house. - AddHtmlLocalized(20, 230, 380, 20, house.Public ? 1060678 : 1060679, SelectedColor); // This house is (private | open to the public). - - switch (house.DecayType) - { - case DecayType.Ageless: - case DecayType.AutoRefresh: - { - AddHtmlLocalized(20, 250, 380, 20, 1062209, SelectedColor); // This house is Automatically refreshed. - break; - } - case DecayType.ManualRefresh: - { - AddHtmlLocalized(20, 250, 380, 20, 1062208, SelectedColor); // This house is Grandfathered. - break; - } - case DecayType.Condemned: - { - AddHtmlLocalized(20, 250, 380, 20, 1062207, WarningColor); // This house is Condemned. - break; - } - } - - AddHtmlLocalized(20, 290, 200, 20, 1060692, SelectedColor); // Built On: - AddLabel(250, 290, LabelHue, GetDateTime(house.BuiltOn)); - - AddHtmlLocalized(20, 310, 200, 20, 1060693, SelectedColor); // Last Traded: - AddLabel(250, 310, LabelHue, GetDateTime(house.LastTraded)); - - AddHtmlLocalized(20, 330, 200, 20, 1061793, SelectedColor); // House Value - AddLabel(250, 330, LabelHue, house.Price.ToString()); - - AddHtmlLocalized(20, 360, 300, 20, 1011241, SelectedColor); // Number of visits this building has had: - AddLabel(350, 360, LabelHue, house.Visits.ToString()); - - break; - } - case HouseGumpPageAOS.Security: - { - AddButtonLabeled(10, 130, GetButtonID(3, 0), 1011266, isCoOwner); // View Co-Owner List - AddButtonLabeled(10, 150, GetButtonID(3, 1), 1011267, isOwner); // Add a Co-Owner - AddButtonLabeled(10, 170, GetButtonID(3, 2), 1018036, isOwner); // Remove a Co-Owner - AddButtonLabeled(10, 190, GetButtonID(3, 3), 1011268, isOwner); // Clear Co-Owner List - - AddButtonLabeled(10, 220, GetButtonID(3, 4), 1011243); // View Friends List - AddButtonLabeled(10, 240, GetButtonID(3, 5), 1011244, isCoOwner); // Add a Friend - AddButtonLabeled(10, 260, GetButtonID(3, 6), 1018037, isCoOwner); // Remove a Friend - AddButtonLabeled(10, 280, GetButtonID(3, 7), 1011245, isCoOwner); // Clear Friend List - - if (house.Public) - { - AddButtonLabeled(10, 310, GetButtonID(3, 8), 1011260); // View Ban List - AddButtonLabeled(10, 330, GetButtonID(3, 9), 1060698); // Clear Ban List - - AddButtonLabeled(210, 130, GetButtonID(3, 12), 1060695, isOwner); // Change to Private - - AddHtmlLocalized(245, 150, 240, 20, 1060694, SelectedColor); // Change to Public - } - else - { - AddButtonLabeled(10, 310, GetButtonID(3, 10), 1060699); // View Access List - AddButtonLabeled(10, 330, GetButtonID(3, 11), 1060700); // Clear Access List - - AddHtmlLocalized(245, 130, 240, 20, 1060695, SelectedColor); // Change to Private - - AddButtonLabeled(210, 150, GetButtonID(3, 13), 1060694, isOwner); // Change to Public - } - - break; - } - case HouseGumpPageAOS.Storage: - { - AddHtmlLocalized(10, 130, 400, 20, 1060682, LabelColor); //
HOUSE STORAGE SUMMARY
- - // This is not as OSI; storage changes not yet implemented - - /*AddHtmlLocalized( 10, 170, 275, 20, 1011237, LabelColor, false, false ); // Number of locked down items: - AddLabel( 310, 170, LabelHue, m_House.LockDownCount.ToString() ); - - AddHtmlLocalized( 10, 190, 275, 20, 1011238, LabelColor, false, false ); // Maximum locked down items: - AddLabel( 310, 190, LabelHue, m_House.MaxLockDowns.ToString() ); - - AddHtmlLocalized( 10, 210, 275, 20, 1011239, LabelColor, false, false ); // Number of secure containers: - AddLabel( 310, 210, LabelHue, m_House.SecureCount.ToString() ); - - AddHtmlLocalized( 10, 230, 275, 20, 1011240, LabelColor, false, false ); // Maximum number of secure containers: - AddLabel( 310, 230, LabelHue, m_House.MaxSecures.ToString() );*/ - - int maxSecures = house.GetAosMaxSecures(); - int curSecures = house.GetAosCurSecures(out int fromSecures, out int fromVendors, out int fromLockdowns, - out int fromMovingCrate); - - int maxLockdowns = house.GetAosMaxLockdowns(); - int curLockdowns = house.GetAosCurLockdowns(); - - int bonusStorage = (int)(house.BonusStorageScalar * 100 - 100); - - if (bonusStorage > 0) - { - AddHtmlLocalized(10, 150, 300, 20, 1072519, LabelColor); // Increased Storage - AddLabel(310, 150, LabelHue, $"{bonusStorage}%"); - } - - AddHtmlLocalized(10, 170, 300, 20, 1060683, LabelColor); // Maximum Secure Storage - AddLabel(310, 170, LabelHue, maxSecures.ToString()); - - AddHtmlLocalized(10, 190, 300, 20, 1060685, LabelColor); // Used by Moving Crate - AddLabel(310, 190, LabelHue, fromMovingCrate.ToString()); - - AddHtmlLocalized(10, 210, 300, 20, 1060686, LabelColor); // Used by Lockdowns - AddLabel(310, 210, LabelHue, fromLockdowns.ToString()); - - if (BaseHouse.NewVendorSystem) - { - AddHtmlLocalized(10, 230, 300, 20, 1060688, LabelColor); // Used by Secure Containers - AddLabel(310, 230, LabelHue, fromSecures.ToString()); - - AddHtmlLocalized(10, 250, 300, 20, 1060689, LabelColor); // Available Storage - AddLabel(310, 250, LabelHue, Math.Max(maxSecures - curSecures, 0).ToString()); - - AddHtmlLocalized(10, 290, 300, 20, 1060690, LabelColor); // Maximum Lockdowns - AddLabel(310, 290, LabelHue, maxLockdowns.ToString()); - - AddHtmlLocalized(10, 310, 300, 20, 1060691, LabelColor); // Available Lockdowns - AddLabel(310, 310, LabelHue, Math.Max(maxLockdowns - curLockdowns, 0).ToString()); - - int maxVendors = house.GetNewVendorSystemMaxVendors(); - int vendors = house.PlayerVendors.Count + house.VendorRentalContracts.Count; - - AddHtmlLocalized(10, 350, 300, 20, 1062391, LabelColor); // Vendor Count - AddLabel(310, 350, LabelHue, $"{vendors} / {maxVendors}"); - } - else - { - AddHtmlLocalized(10, 230, 300, 20, 1060687, LabelColor); // Used by Vendors - AddLabel(310, 230, LabelHue, fromVendors.ToString()); - - AddHtmlLocalized(10, 250, 300, 20, 1060688, LabelColor); // Used by Secure Containers - AddLabel(310, 250, LabelHue, fromSecures.ToString()); - - AddHtmlLocalized(10, 270, 300, 20, 1060689, LabelColor); // Available Storage - AddLabel(310, 270, LabelHue, Math.Max(maxSecures - curSecures, 0).ToString()); - - AddHtmlLocalized(10, 330, 300, 20, 1060690, LabelColor); // Maximum Lockdowns - AddLabel(310, 330, LabelHue, maxLockdowns.ToString()); - - AddHtmlLocalized(10, 350, 300, 20, 1060691, LabelColor); // Available Lockdowns - AddLabel(310, 350, LabelHue, Math.Max(maxLockdowns - curLockdowns, 0).ToString()); - } - - break; - } - case HouseGumpPageAOS.Customize: - { - bool isCustomizable = isOwner && house is HouseFoundation; - - AddButtonLabeled(10, 120, GetButtonID(5, 0), 1060759, - isOwner && !isCustomizable && house.ConvertEntry != null); // Convert Into Customizable House - AddButtonLabeled(10, 160, GetButtonID(5, 1), 1060765, isOwner && isCustomizable); // Customize This House - AddButtonLabeled(10, 180, GetButtonID(5, 2), 1060760, - isOwner && house.MovingCrate != null); // Relocate Moving Crate - AddButtonLabeled(10, 210, GetButtonID(5, 3), 1060761, isOwner && house.Public); // Change House Sign - AddButtonLabeled(10, 230, GetButtonID(5, 4), 1060762, - isOwner && isCustomizable); // Change House Sign Hanger - AddButtonLabeled(10, 250, GetButtonID(5, 5), 1060763, - isOwner && isCustomizable && ((HouseFoundation)house).Signpost != null); // Change Signpost - AddButtonLabeled(10, 280, GetButtonID(5, 6), 1062004, - isOwner && isCustomizable); // Change Foundation Style - AddButtonLabeled(10, 310, GetButtonID(5, 7), 1060764, isCoOwner); // Rename House - - break; - } - case HouseGumpPageAOS.Ownership: - { - AddButtonLabeled(10, 130, GetButtonID(6, 0), 1061794, - isOwner && house.MovingCrate == null && house.InternalizedVendors.Count == 0); // Demolish House - AddButtonLabeled(10, 150, GetButtonID(6, 1), 1061797, isOwner); // Trade House - AddButtonLabeled(10, 190, GetButtonID(6, 2), 1061798, false); // Make Primary - - break; - } - case HouseGumpPageAOS.ChangeHanger: - { - for (int i = 0; i < m_HangerNumbers.Length; ++i) - { - int x = 50 + i % 3 * 100; - int y = 180 + i / 3 * 80; - - AddButton(x, y, 4005, 4007, GetButtonID(7, i)); - AddItem(x + 20, y, m_HangerNumbers[i]); - } - - break; - } - case HouseGumpPageAOS.ChangeFoundation: - { - for (int i = 0; i < m_FoundationNumbers.Length; ++i) - { - int x = 15 + i % 5 * 80; - int y = 180 + i / 5 * 100; - - AddButton(x, y, 4005, 4007, GetButtonID(8, i)); - AddItem(x + 25, y, m_FoundationNumbers[i]); - } - - break; - } - case HouseGumpPageAOS.ChangeSign: - { - int index = 0; - - if (_HouseSigns.Count == 0) - { - // Add standard signs - for (int i = 0; i < 54; ++i) _HouseSigns.Add(2980 + i * 2); - - // Add library and beekeeper signs ( ML ) - _HouseSigns.Add(2966); - _HouseSigns.Add(3140); - } - - int signsPerPage = Core.ML ? 24 : 18; - int totalSigns = Core.ML ? 56 : 54; - int pages = (int)Math.Ceiling((double)totalSigns / signsPerPage); - - for (int i = 0; i < pages; ++i) - { - AddPage(i + 1); - - AddButton(10, 360, 4005, 4007, 0, GumpButtonType.Page, (i + 1) % pages + 1); - - for (int j = 0; j < signsPerPage && totalSigns - signsPerPage * i - j > 0; ++j) - { - int x = 30 + j % 6 * 60; - int y = 130 + j / 6 * 60; - - AddButton(x, y, 4005, 4007, GetButtonID(9, index)); - AddItem(x + 20, y, _HouseSigns[index++]); - } - } - - break; - } - case HouseGumpPageAOS.RemoveCoOwner: - { - AddHtmlLocalized(10, 120, 400, 20, 1060730, LabelColor); //
CO-OWNER LIST
- AddList(house.CoOwners, 10, false, true, from); - break; - } - case HouseGumpPageAOS.ListCoOwner: - { - AddHtmlLocalized(10, 120, 400, 20, 1060730, LabelColor); //
CO-OWNER LIST
- AddList(house.CoOwners, -1, false, true, from); - break; - } - case HouseGumpPageAOS.RemoveFriend: - { - AddHtmlLocalized(10, 120, 400, 20, 1060731, LabelColor); //
FRIENDS LIST
- AddList(house.Friends, 11, false, true, from); - break; - } - case HouseGumpPageAOS.ListFriend: - { - AddHtmlLocalized(10, 120, 400, 20, 1060731, LabelColor); //
FRIENDS LIST
- AddList(house.Friends, -1, false, true, from); - break; - } - case HouseGumpPageAOS.RemoveBan: - { - AddHtmlLocalized(10, 120, 400, 20, 1060733, LabelColor); //
BAN LIST
- AddList(house.Bans, 12, true, true, from); - break; - } - case HouseGumpPageAOS.ListBan: - { - AddHtmlLocalized(10, 120, 400, 20, 1060733, LabelColor); //
BAN LIST
- AddList(house.Bans, -1, true, true, from); - break; - } - case HouseGumpPageAOS.RemoveAccess: - { - AddHtmlLocalized(10, 120, 400, 20, 1060732, LabelColor); //
ACCESS LIST
- AddList(house.Access, 13, false, true, from); - break; - } - case HouseGumpPageAOS.ListAccess: - { - AddHtmlLocalized(10, 120, 400, 20, 1060732, LabelColor); //
ACCESS LIST
- AddList(house.Access, -1, false, true, from); - break; - } - case HouseGumpPageAOS.ChangePost: - { - int index = 0; - - for (int i = 0; i < 2; ++i) - { - AddPage(i + 1); - - AddButton(10, 360, 4005, 4007, 0, GumpButtonType.Page, (i + 1) % 2 + 1); - - for (int j = 0; j < 16 && index < m_PostNumbers.Length; ++j) - { - int x = 15 + j % 8 * 50; - int y = 130 + j / 8 * 110; - - AddButton(x, y, 4005, 4007, GetButtonID(14, index)); - AddItem(x + 10, y, m_PostNumbers[index++]); - } - } - - break; - } - } - } - - private string GetOwnerName() - { - Mobile m = m_House.Owner; - - return m?.Deleted != false ? "(unowned)" : m.Name.Trim().IsNullOrDefault("(no name)"); - } - - private string GetDateTime(DateTime val) => val == DateTime.MinValue ? "" : val.ToString("yyyy'-'MM'-'dd HH':'mm':'ss"); - - public void AddPageButton(int x, int y, int buttonID, int number, HouseGumpPageAOS page) - { - bool isSelection = m_Page == page; - - AddButton(x, y, isSelection ? 4006 : 4005, 4007, buttonID); - AddHtmlLocalized(x + 45, y, 200, 20, number, isSelection ? SelectedColor : LabelColor); - } - - public void AddButtonLabeled(int x, int y, int buttonID, int number, bool enabled = true) - { - if (enabled) - AddButton(x, y, 4005, 4007, buttonID); - - AddHtmlLocalized(x + 35, y, 240, 20, number, enabled ? LabelColor : DisabledColor); - } - - public void AddList(List list, int button, bool accountOf, bool leadingStar, Mobile from) - { - if (list == null) - return; - - m_List = new List(list); - - int lastPage = 0; - int index = 0; - - for (int i = 0; i < list.Count; ++i) - { - int xoffset = index % 20 / 10 * 200; - int yoffset = index % 10 * 20; - int page = 1 + index / 20; - - if (page != lastPage) - { - if (lastPage != 0) - AddButton(40, 360, 4005, 4007, 0, GumpButtonType.Page, page); - - AddPage(page); - - if (lastPage != 0) - AddButton(10, 360, 4014, 4016, 0, GumpButtonType.Page, lastPage); - - lastPage = page; - } - - Mobile m = list[i]; - - string name; - int labelHue = LabelHue; - - if (m is PlayerVendor vendor) - { - name = vendor.ShopName; - - if (vendor.IsOwner(from)) - labelHue = HighlightedLabelHue; - } - else if (m != null) - { - name = m.Name; - } - else - { - continue; - } - - if ((name = name.Trim()).Length <= 0) - continue; - - if (button != -1) - AddButton(10 + xoffset, 150 + yoffset, 4005, 4007, GetButtonID(button, i)); - - if (accountOf && m.Player && m.Account != null) - name = $"Account of {name}"; - - if (leadingStar) - name = $"* {name}"; - - AddLabel(button > 0 ? 45 + xoffset : 10 + xoffset, 150 + yoffset, labelHue, name); - ++index; - } - } - - public static int GetButtonID(int type, int index) => 1 + index * 15 + type; - - public static void PublicPrivateNotice_Callback(Mobile from, BaseHouse house) - { - if (!house.Deleted) - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Security, from, house)); - } - - public static void CustomizeNotice_Callback(Mobile from, BaseHouse house) - { - if (!house.Deleted) - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Customize, from, house)); - } - - public static void ClearCoOwners_Callback(Mobile from, bool okay, BaseHouse house) - { - if (house.Deleted) - return; - - if (okay && house.IsOwner(from)) - { - house.CoOwners?.Clear(); - - from.SendLocalizedMessage(501333); // All co-owners have been removed from this house. - } - - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Security, from, house)); - } - - public static void ClearFriends_Callback(Mobile from, bool okay, BaseHouse house) - { - if (house.Deleted) - return; - - if (okay && house.IsCoOwner(from)) - { - house.Friends?.Clear(); - - from.SendLocalizedMessage(501332); // All friends have been removed from this house. - } - - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Security, from, house)); - } - - public static void ClearBans_Callback(Mobile from, bool okay, BaseHouse house) - { - if (house.Deleted) - return; - - if (okay && house.IsFriend(from)) - { - house.Bans?.Clear(); - - from.SendLocalizedMessage(1060754); // All bans for this house have been lifted. - } - - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Security, from, house)); - } - - public static void ClearAccess_Callback(Mobile from, bool okay, BaseHouse house) - { - if (house.Deleted) - return; - - if (okay && house.IsFriend(from)) - { - List list = house.Access.ToList(); - - house.Access?.Clear(); - - for (int i = 0; i < list.Count; ++i) - { - Mobile m = list[i]; - - if (!house.HasAccess(m) && house.IsInside(m)) - { - m.Location = house.BanLocation; - m.SendLocalizedMessage(1060734); // Your access to this house has been revoked. - } - } - - from.SendLocalizedMessage(1061843); // This house's Access List has been cleared. - } - - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Security, from, house)); - } - - public static void ConvertHouse_Callback(Mobile from, bool okay, BaseHouse house) - { - if (house.Deleted) - return; - - if (okay && house.IsOwner(from) && !house.HasRentedVendors) - { - HousePlacementEntry e = house.ConvertEntry; - - if (e == null) - return; - - int cost = e.Cost - house.Price; - - if (cost > 0) - { - if (Banker.Withdraw(from, cost)) - { - from.SendLocalizedMessage(1060398, - cost.ToString()); // ~1_AMOUNT~ gold has been withdrawn from your bank box. - } - else - { - from.SendLocalizedMessage( - 1061624); // You do not have enough funds in your bank to cover the difference between your old house and your new one. - return; - } - } - else if (cost < 0) - { - if (Banker.Deposit(from, -cost)) - from.SendLocalizedMessage(1060397, - (-cost).ToString()); // ~1_AMOUNT~ gold has been deposited into your bank box. - else - return; - } - - BaseHouse newHouse = e.ConstructHouse(from); - - if (newHouse != null) - { - newHouse.Price = e.Cost; - - house.MoveAllToCrate(); - - newHouse.Friends = new List(house.Friends); - newHouse.CoOwners = new List(house.CoOwners); - newHouse.Bans = new List(house.Bans); - newHouse.Access = new List(house.Access); - newHouse.BuiltOn = house.BuiltOn; - newHouse.LastTraded = house.LastTraded; - newHouse.Public = house.Public; - - newHouse.VendorInventories.AddRange(house.VendorInventories); - house.VendorInventories.Clear(); - - foreach (VendorInventory inventory in newHouse.VendorInventories) inventory.House = newHouse; - - newHouse.InternalizedVendors.AddRange(house.InternalizedVendors); - house.InternalizedVendors.Clear(); - - foreach (Mobile mobile in newHouse.InternalizedVendors) - if (mobile is PlayerVendor vendor) - vendor.House = newHouse; - else if (mobile is PlayerBarkeeper barkeeper) - barkeeper.House = newHouse; - - if (house.MovingCrate != null) - { - newHouse.MovingCrate = house.MovingCrate; - newHouse.MovingCrate.House = newHouse; - house.MovingCrate = null; - } - - List items = house.GetItems(); - List mobiles = house.GetMobiles(); - - newHouse.MoveToWorld( - new Point3D(house.X + house.ConvertOffsetX, house.Y + house.ConvertOffsetY, - house.Z + house.ConvertOffsetZ), house.Map); - house.Delete(); - - foreach (Item item in items) item.Location = newHouse.BanLocation; - - foreach (Mobile mobile in mobiles) mobile.Location = newHouse.BanLocation; - - /* You have successfully replaced your original house with a new house. - * The value of the replaced house has been deposited into your bank box. - * All of the items in your original house have been relocated to a Moving Crate in the new house. - * Any deed-based house add-ons have been converted back into deeds. - * Vendors and barkeeps in the house, if any, have been stored in the Moving Crate as well. - * Use the Get Vendor context-sensitive menu option on your character to retrieve them. - * These containers can be used to re-create the vendor in a new location. - * Any barkeepers have been converted into deeds. - */ - from.SendGump(new NoticeGump(1060637, 30720, 1060012, 32512, 420, 280)); - return; - } - } - - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Security, from, house)); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_House.Deleted) - return; - - Mobile from = sender.Mobile; - - bool isCombatRestricted = m_House.IsCombatRestricted(from); - - bool isOwner = m_House.IsOwner(from); - bool isCoOwner = isOwner || m_House.IsCoOwner(from); - bool isFriend = isCoOwner || m_House.IsFriend(from); - - if (isCombatRestricted) - isCoOwner = isFriend = false; - - if (!from.CheckAlive()) - return; - - Item sign = m_House.Sign; - - if (sign == null || from.Map != sign.Map || !from.InRange(sign.GetWorldLocation(), 18)) - return; - - HouseFoundation foundation = m_House as HouseFoundation; - bool isCustomizable = foundation != null; - - int val = info.ButtonID - 1; - - if (val < 0) - return; - - int type = val % 15; - int index = val / 15; - - if (m_Page == HouseGumpPageAOS.Vendors) - { - if (index < m_List.Count) - { - PlayerVendor vendor = (PlayerVendor)m_List[index]; - - if (!vendor.CanInteractWith(from, false)) - return; - - if (from.Map != sign.Map || !from.InRange(sign, 5)) - from.SendLocalizedMessage( - 1062429); // You must be within five paces of the house sign to use this option. - else if (vendor.IsOwner(from)) - vendor.SendOwnerGump(from); - else - vendor.OpenBackpack(from); - } - - return; - } - - if (!isFriend) - return; - - switch (type) - { - case 0: - { - switch (index) - { - case 0: // Banish - { - if (m_House.Public) - { - from.SendLocalizedMessage(501325); // Target the individual to ban from this house. - from.Target = new HouseBanTarget(true, m_House); - } - - break; - } - case 1: // Lift Ban - { - if (m_House.Public) - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.RemoveBan, from, m_House)); - - break; - } - case 2: // Grant Access - { - if (!m_House.Public) - { - from.SendLocalizedMessage(1060711); // Target the person you would like to grant access to. - from.Target = new HouseAccessTarget(m_House); - } - - break; - } - case 3: // Revoke Access - { - if (!m_House.Public) - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.RemoveAccess, from, m_House)); - - break; - } - } - - break; - } - case 1: - { - HouseGumpPageAOS page; - - switch (index) - { - case 0: - page = HouseGumpPageAOS.Information; - break; - case 1: - page = HouseGumpPageAOS.Security; - break; - case 2: - page = HouseGumpPageAOS.Storage; - break; - case 3: - page = HouseGumpPageAOS.Customize; - break; - case 4: - page = HouseGumpPageAOS.Ownership; - break; - default: return; - } - - from.SendGump(new HouseGumpAOS(page, from, m_House)); - break; - } - case 3: - { - switch (index) - { - case 0: // View Co-Owner List - { - if (isCoOwner) - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.ListCoOwner, from, m_House)); - - break; - } - case 1: // Add a Co-Owner - { - if (isOwner) - { - from.SendLocalizedMessage( - 501328); // Target the person you wish to name a co-owner of your household. - from.Target = new CoOwnerTarget(true, m_House); - } - - break; - } - case 2: // Remove a Co-Owner - { - if (isOwner) - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.RemoveCoOwner, from, m_House)); - - break; - } - case 3: // Clear Co-Owner List - { - if (isOwner) - from.SendGump(new WarningGump(1060635, 30720, 1060736, 32512, 420, 280, - okay => ClearCoOwners_Callback(from, okay, m_House))); - - break; - } - case 4: // View Friends List - { - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.ListFriend, from, m_House)); - - break; - } - case 5: // Add a Friend - { - if (isCoOwner) - { - from.SendLocalizedMessage( - 501317); // Target the person you wish to name a friend of your household. - from.Target = new HouseFriendTarget(true, m_House); - } - - break; - } - case 6: // Remove a Friend - { - if (isCoOwner) - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.RemoveFriend, from, m_House)); - - break; - } - case 7: // Clear Friend List - { - if (isCoOwner) - from.SendGump(new WarningGump(1060635, 30720, 1018039, 32512, 420, 280, - okay => ClearFriends_Callback(from, okay, m_House))); - - break; - } - case 8: // View Ban List - { - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.ListBan, from, m_House)); - - break; - } - case 9: // Clear Ban List - { - from.SendGump(new WarningGump(1060635, 30720, 1060753, 32512, 420, 280, - okay => ClearBans_Callback(from, okay, m_House))); - - break; - } - case 10: // View Access List - { - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.ListAccess, from, m_House)); - - break; - } - case 11: // Clear Access List - { - from.SendGump(new WarningGump(1060635, 30720, 1061842, 32512, 420, 280, - okay => ClearAccess_Callback(from, okay, m_House))); - - break; - } - case 12: // Make Private - { - if (isOwner) - { - if (m_House.PlayerVendors.Count > 0) - { - // You have vendors working out of this building. It cannot be declared private until there are no vendors in place. - from.SendGump(new NoticeGump(1060637, 30720, 501887, 32512, 320, 180, - () => PublicPrivateNotice_Callback(from, m_House))); - break; - } - - if (m_House.VendorRentalContracts.Count > 0) - { - // You cannot currently take this action because you have vendor contracts locked down in your home. You must remove them first. - from.SendGump(new NoticeGump(1060637, 30720, 1062351, 32512, 320, 180, - () => PublicPrivateNotice_Callback(from, m_House))); - break; - } - - m_House.Public = false; - - m_House.ChangeLocks(from); - - // This house is now private. - from.SendGump(new NoticeGump(1060637, 30720, 501888, 32512, 320, 180, - () => PublicPrivateNotice_Callback(from, m_House))); - - Region r = m_House.Region; - List list = r.GetMobiles(); - - for (int i = 0; i < list.Count; ++i) - { - Mobile m = list[i]; - - if (!m_House.HasAccess(m) && m_House.IsInside(m)) - m.Location = m_House.BanLocation; - } - } - - break; - } - case 13: // Make Public - { - if (isOwner) - { - m_House.Public = true; - - m_House.RemoveKeys(from); - m_House.RemoveLocks(); - - if (BaseHouse.NewVendorSystem) - from.SendGump(new NoticeGump(1060637, 30720, 501886, 32512, 320, 180, - () => PublicPrivateNotice_Callback(from, m_House))); - else - from.SendGump(new NoticeGump(1060637, 30720, - "This house is now public. Friends of the house may now have vendors working out of this building.", - 0xF8C000, 320, 180, () => PublicPrivateNotice_Callback(from, m_House))); - - Region r = m_House.Region; - List list = r.GetMobiles(); - - for (int i = 0; i < list.Count; ++i) - { - Mobile m = list[i]; - - if (m_House.IsBanned(m) && m_House.IsInside(m)) - m.Location = m_House.BanLocation; - } - } - - break; - } - } - - break; - } - case 5: - { - switch (index) - { - case 0: // Convert Into Customizable House - { - if (isOwner && !isCustomizable) - { - if (m_House.HasRentedVendors) - { - // You cannot perform this action while you still have vendors rented out in this house. - from.SendGump(new NoticeGump(1060637, 30720, 1062395, 32512, 320, 180, - () => CustomizeNotice_Callback(from, m_House))); - } - else - { - HousePlacementEntry e = m_House.ConvertEntry; - - if (e != null) - from.SendGump(new WarningGump(1060635, 30720, 1060013, 32512, 420, 280, - okay => ConvertHouse_Callback(from, okay, m_House))); - } - } - - break; - } - case 1: // Customize This House - { - if (isOwner && isCustomizable) - { - if (m_House.HasRentedVendors) - from.SendGump(new NoticeGump(1060637, 30720, 1062395, 32512, 320, 180, - () => CustomizeNotice_Callback(from, m_House))); - else if (m_House.HasAddonContainers) - from.SendGump(new NoticeGump(1060637, 30720, 1074863, 32512, 320, 180, - () => CustomizeNotice_Callback(from, m_House))); - else - foundation.BeginCustomize(from); - } - - break; - } - case 2: // Relocate Moving Crate - { - MovingCrate crate = m_House.MovingCrate; - - if (isOwner && crate != null) - { - if (!m_House.IsInside(from)) - { - from.SendLocalizedMessage(502092); // You must be in your house to do this. - } - else - { - crate.MoveToWorld(from.Location, from.Map); - crate.RestartTimer(); - } - } - - break; - } - case 3: // Change House Sign - { - if (isOwner && m_House.Public) - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.ChangeSign, from, m_House)); - - break; - } - case 4: // Change House Sign Hanger - { - if (isOwner && isCustomizable) - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.ChangeHanger, from, m_House)); - - break; - } - case 5: // Change Signpost - { - if (isOwner && isCustomizable && foundation.Signpost != null) - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.ChangePost, from, m_House)); - - break; - } - case 6: // Change Foundation Style - { - if (isOwner && isCustomizable) - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.ChangeFoundation, from, m_House)); - - break; - } - case 7: // Rename House - { - if (isCoOwner) - { - from.Prompt = new RenamePrompt(m_House); - from.SendLocalizedMessage(501302); // What dost thou wish the sign to say? - } - - break; - } - } - - break; - } - case 6: - { - switch (index) - { - case 0: // Demolish - { - if (isOwner && m_House.MovingCrate == null && m_House.InternalizedVendors.Count == 0) - { - if (!Guild.NewGuildSystem && m_House.FindGuildstone() != null) - { - from.SendLocalizedMessage(501389); // You cannot redeed a house with a guildstone inside. - } - else if (Core.ML && from.AccessLevel < AccessLevel.GameMaster && - DateTime.UtcNow <= m_House.BuiltOn.AddHours(1)) - { - from.SendLocalizedMessage( - 1080178); // You must wait one hour between each house demolition. - } - else - { - from.CloseGump(); - from.SendGump(new HouseDemolishGump(from, m_House)); - } - } - - break; - } - case 1: // Trade House - { - if (isOwner) - { - if (BaseHouse.NewVendorSystem && m_House.HasPersonalVendors) - { - from.SendLocalizedMessage( - 1062467); // You cannot trade this house while you still have personal vendors inside. - } - else if (m_House.DecayLevel == DecayLevel.DemolitionPending) - { - from.SendLocalizedMessage( - 1005321); // This house has been marked for demolition, and it cannot be transferred. - } - else - { - from.SendLocalizedMessage( - 501309); // Target the person to whom you wish to give this house. - from.Target = new HouseOwnerTarget(m_House); - } - } - - break; - } - case 2: // Make Primary - break; - } - - break; - } - case 7: - { - if (isOwner && isCustomizable && index < m_HangerNumbers.Length) - { - Item hanger = foundation.SignHanger; - - if (hanger != null) - hanger.ItemID = m_HangerNumbers[index]; - - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Customize, from, m_House)); - } - - break; - } - case 8: - { - if (isOwner && isCustomizable) - { - FoundationType newType; - - if (Core.ML && index >= 5) - switch (index) - { - case 5: - newType = FoundationType.ElvenGrey; - break; - case 6: - newType = FoundationType.ElvenNatural; - break; - case 7: - newType = FoundationType.Crystal; - break; - case 8: - newType = FoundationType.Shadow; - break; - default: return; - } - else - switch (index) - { - case 0: - newType = FoundationType.DarkWood; - break; - case 1: - newType = FoundationType.LightWood; - break; - case 2: - newType = FoundationType.Dungeon; - break; - case 3: - newType = FoundationType.Brick; - break; - case 4: - newType = FoundationType.Stone; - break; - default: return; - } - - foundation.Type = newType; - - DesignState state = foundation.BackupState; - HouseFoundation.ApplyFoundation(newType, state.Components); - state.OnRevised(); - - state = foundation.DesignState; - HouseFoundation.ApplyFoundation(newType, state.Components); - state.OnRevised(); - - state = foundation.CurrentState; - HouseFoundation.ApplyFoundation(newType, state.Components); - state.OnRevised(); - - foundation.Delta(ItemDelta.Update); - - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Customize, from, m_House)); - } - - break; - } - case 9: - { - if (isOwner && m_House.Public && index < _HouseSigns.Count) - { - m_House.ChangeSignType(_HouseSigns[index]); - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Customize, from, m_House)); - } - - break; - } - case 10: - { - if (isOwner && index < m_List?.Count) - { - m_House.RemoveCoOwner(from, m_List[index]); - - if (m_House.CoOwners.Count > 0) - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.RemoveCoOwner, from, m_House)); - else - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Security, from, m_House)); - } - - break; - } - case 11: - { - if (isCoOwner && index < m_List?.Count) - { - m_House.RemoveFriend(from, m_List[index]); - - if (m_House.Friends.Count > 0) - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.RemoveFriend, from, m_House)); - else - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Security, from, m_House)); - } - - break; - } - case 12: - { - if (index < m_List?.Count) - { - m_House.RemoveBan(from, m_List[index]); - - if (m_House.Bans.Count > 0) - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.RemoveBan, from, m_House)); - else - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Security, from, m_House)); - } - - break; - } - case 13: - { - if (index < m_List?.Count) - { - m_House.RemoveAccess(from, m_List[index]); - - if (m_House.Access.Count > 0) - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.RemoveAccess, from, m_House)); - else - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Security, from, m_House)); - } - - break; - } - case 14: - { - if (isOwner && isCustomizable && index < m_PostNumbers.Length) - { - foundation.SignpostGraphic = m_PostNumbers[index]; - foundation.CheckSignpost(); - - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Customize, from, m_House)); - } - - break; - } - } - } - - private List Wrap(string value) - { - if (value == null || (value = value.Trim()).Length <= 0) - return null; - - string[] values = value.Split(' '); - List list = new List(); - string current = ""; - - for (int i = 0; i < values.Length; ++i) - { - string val = values[i]; - - string v = current.Length == 0 ? val : $"{current} {val}"; - - if (v.Length < 10) - { - current = v; - } - else if (v.Length == 10) - { - list.Add(v); - - if (list.Count == 6) - return list; - - current = ""; - } - else if (val.Length <= 10) - { - list.Add(current); - - if (list.Count == 6) - return list; - - current = val; - } - else - { - while (v.Length >= 10) - { - list.Add(v.Substring(0, 10)); - - if (list.Count == 6) - return list; - - v = v.Substring(10); - } - - current = v; - } - } - - if (current.Length > 0) - list.Add(current); - - return list; - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using Server.Guilds; +using Server.Mobiles; +using Server.Multis; +using Server.Network; +using Server.Prompts; + +namespace Server.Gumps +{ + public enum HouseGumpPageAOS + { + Information, + Security, + Storage, + Customize, + Ownership, + ChangeHanger, + ChangeFoundation, + ChangeSign, + RemoveCoOwner, + ListCoOwner, + RemoveFriend, + ListFriend, + RemoveBan, + ListBan, + RemoveAccess, + ListAccess, + ChangePost, + Vendors + } + + public class HouseGumpAOS : Gump + { + private const int LabelColor = 0x7FFF; + private const int SelectedColor = 0x421F; + private const int DisabledColor = 0x4210; + private const int WarningColor = 0x7E10; + + private const int LabelHue = 0x481; + private const int HighlightedLabelHue = 0x64; + + private static readonly int[] m_HangerNumbers = + { + 2968, 2970, 2972, + 2974, 2976, 2978 + }; + + private static readonly int[] m_FoundationNumbers = Core.ML + ? new[] + { + 20, 189, 765, 65, 101, 0x2DF7, 0x2DFB, 0x3672, 0x3676 + } + : new[] + { + 20, 189, 765, 65, 101 + }; + + private static readonly int[] m_PostNumbers = + { + 9, 29, 54, 90, 147, 169, + 177, 204, 251, 257, 263, + 298, 347, 424, 441, 466, + 514, 600, 601, 602, 603, + 660, 666, 672, 898, 970, + 974, 982 + }; + + private static readonly List _HouseSigns = new List(); + private readonly BaseHouse m_House; + private readonly HouseGumpPageAOS m_Page; + + private List m_List; + + public HouseGumpAOS(HouseGumpPageAOS page, Mobile from, BaseHouse house) : base(50, 40) + { + m_House = house; + m_Page = page; + + from.CloseGump(); + // from.CloseGump( typeof( HouseListGump ) ); + // from.CloseGump( typeof( HouseRemoveGump ) ); + + var isCombatRestricted = house.IsCombatRestricted(from); + + var isOwner = house.IsOwner(from); + var isCoOwner = isOwner || house.IsCoOwner(from); + var isFriend = isCoOwner || house.IsFriend(from); + + if (isCombatRestricted) + isFriend = isCoOwner = isOwner = false; + + AddPage(0); + + if (isFriend || page == HouseGumpPageAOS.Vendors) + { + AddBackground(0, 0, 420, page != HouseGumpPageAOS.Vendors ? 440 : 420, 5054); + + AddImageTiled(10, 10, 400, 100, 2624); + AddAlphaRegion(10, 10, 400, 100); + + AddImageTiled(10, 120, 400, 260, 2624); + AddAlphaRegion(10, 120, 400, 260); + + AddImageTiled(10, 390, 400, page != HouseGumpPageAOS.Vendors ? 40 : 20, 2624); + AddAlphaRegion(10, 390, 400, page != HouseGumpPageAOS.Vendors ? 40 : 20); + + AddButtonLabeled(250, page != HouseGumpPageAOS.Vendors ? 410 : 390, 0, 1060675); // CLOSE + } + + AddImage(10, 10, 100); + + if (m_House.Sign != null) + { + var lines = Wrap(m_House.Sign.GetName()); + + for (int i = 0, y = (114 - lines.Count * 14) / 2; i < lines.Count; ++i, y += 14) + { + var s = lines[i]; + + AddLabel(10 + (160 - s.Length * 8) / 2, y, 0, s); + } + } + + if (page == HouseGumpPageAOS.Vendors) + { + AddHtmlLocalized(10, 120, 400, 20, 1062428, LabelColor); //
SHOPS
+ + AddList(house.AvailableVendorsFor(from), 1, false, false, from); + return; + } + + if (!isFriend) + return; + + if (house.Public) + { + AddButtonLabeled(10, 390, GetButtonID(0, 0), 1060674); // Banish + AddButtonLabeled(10, 410, GetButtonID(0, 1), 1011261); // Lift a Ban + } + else + { + AddButtonLabeled(10, 390, GetButtonID(0, 2), 1060676); // Grant Access + AddButtonLabeled(10, 410, GetButtonID(0, 3), 1060677); // Revoke Access + } + + AddPageButton(150, 10, GetButtonID(1, 0), 1060668, HouseGumpPageAOS.Information); + AddPageButton(150, 30, GetButtonID(1, 1), 1060669, HouseGumpPageAOS.Security); + AddPageButton(150, 50, GetButtonID(1, 2), 1060670, HouseGumpPageAOS.Storage); + AddPageButton(150, 70, GetButtonID(1, 3), 1060671, HouseGumpPageAOS.Customize); + AddPageButton(150, 90, GetButtonID(1, 4), 1060672, HouseGumpPageAOS.Ownership); + + switch (page) + { + case HouseGumpPageAOS.Information: + { + AddHtmlLocalized(20, 130, 200, 20, 1011242, LabelColor); // Owned By: + AddLabel(210, 130, LabelHue, GetOwnerName()); + + AddHtmlLocalized(20, 170, 380, 20, 1018032, SelectedColor); // This house is properly placed. + AddHtmlLocalized(20, 190, 380, 20, 1018035, SelectedColor); // This house is of modern design. + AddHtmlLocalized( + 20, + 210, + 380, + 20, + house is HouseFoundation ? 1060681 : 1060680, + SelectedColor + ); // This is a (pre | custom)-built house. + AddHtmlLocalized( + 20, + 230, + 380, + 20, + house.Public ? 1060678 : 1060679, + SelectedColor + ); // This house is (private | open to the public). + + switch (house.DecayType) + { + case DecayType.Ageless: + case DecayType.AutoRefresh: + { + AddHtmlLocalized( + 20, + 250, + 380, + 20, + 1062209, + SelectedColor + ); // This house is Automatically refreshed. + break; + } + case DecayType.ManualRefresh: + { + AddHtmlLocalized( + 20, + 250, + 380, + 20, + 1062208, + SelectedColor + ); // This house is Grandfathered. + break; + } + case DecayType.Condemned: + { + AddHtmlLocalized( + 20, + 250, + 380, + 20, + 1062207, + WarningColor + ); // This house is Condemned. + break; + } + } + + AddHtmlLocalized(20, 290, 200, 20, 1060692, SelectedColor); // Built On: + AddLabel(250, 290, LabelHue, GetDateTime(house.BuiltOn)); + + AddHtmlLocalized(20, 310, 200, 20, 1060693, SelectedColor); // Last Traded: + AddLabel(250, 310, LabelHue, GetDateTime(house.LastTraded)); + + AddHtmlLocalized(20, 330, 200, 20, 1061793, SelectedColor); // House Value + AddLabel(250, 330, LabelHue, house.Price.ToString()); + + AddHtmlLocalized( + 20, + 360, + 300, + 20, + 1011241, + SelectedColor + ); // Number of visits this building has had: + AddLabel(350, 360, LabelHue, house.Visits.ToString()); + + break; + } + case HouseGumpPageAOS.Security: + { + AddButtonLabeled(10, 130, GetButtonID(3, 0), 1011266, isCoOwner); // View Co-Owner List + AddButtonLabeled(10, 150, GetButtonID(3, 1), 1011267, isOwner); // Add a Co-Owner + AddButtonLabeled(10, 170, GetButtonID(3, 2), 1018036, isOwner); // Remove a Co-Owner + AddButtonLabeled(10, 190, GetButtonID(3, 3), 1011268, isOwner); // Clear Co-Owner List + + AddButtonLabeled(10, 220, GetButtonID(3, 4), 1011243); // View Friends List + AddButtonLabeled(10, 240, GetButtonID(3, 5), 1011244, isCoOwner); // Add a Friend + AddButtonLabeled(10, 260, GetButtonID(3, 6), 1018037, isCoOwner); // Remove a Friend + AddButtonLabeled(10, 280, GetButtonID(3, 7), 1011245, isCoOwner); // Clear Friend List + + if (house.Public) + { + AddButtonLabeled(10, 310, GetButtonID(3, 8), 1011260); // View Ban List + AddButtonLabeled(10, 330, GetButtonID(3, 9), 1060698); // Clear Ban List + + AddButtonLabeled(210, 130, GetButtonID(3, 12), 1060695, isOwner); // Change to Private + + AddHtmlLocalized(245, 150, 240, 20, 1060694, SelectedColor); // Change to Public + } + else + { + AddButtonLabeled(10, 310, GetButtonID(3, 10), 1060699); // View Access List + AddButtonLabeled(10, 330, GetButtonID(3, 11), 1060700); // Clear Access List + + AddHtmlLocalized(245, 130, 240, 20, 1060695, SelectedColor); // Change to Private + + AddButtonLabeled(210, 150, GetButtonID(3, 13), 1060694, isOwner); // Change to Public + } + + break; + } + case HouseGumpPageAOS.Storage: + { + AddHtmlLocalized(10, 130, 400, 20, 1060682, LabelColor); //
HOUSE STORAGE SUMMARY
+ + // This is not as OSI; storage changes not yet implemented + + /*AddHtmlLocalized( 10, 170, 275, 20, 1011237, LabelColor, false, false ); // Number of locked down items: + AddLabel( 310, 170, LabelHue, m_House.LockDownCount.ToString() ); + + AddHtmlLocalized( 10, 190, 275, 20, 1011238, LabelColor, false, false ); // Maximum locked down items: + AddLabel( 310, 190, LabelHue, m_House.MaxLockDowns.ToString() ); + + AddHtmlLocalized( 10, 210, 275, 20, 1011239, LabelColor, false, false ); // Number of secure containers: + AddLabel( 310, 210, LabelHue, m_House.SecureCount.ToString() ); + + AddHtmlLocalized( 10, 230, 275, 20, 1011240, LabelColor, false, false ); // Maximum number of secure containers: + AddLabel( 310, 230, LabelHue, m_House.MaxSecures.ToString() );*/ + + var maxSecures = house.GetAosMaxSecures(); + var curSecures = house.GetAosCurSecures( + out var fromSecures, + out var fromVendors, + out var fromLockdowns, + out var fromMovingCrate + ); + + var maxLockdowns = house.GetAosMaxLockdowns(); + var curLockdowns = house.GetAosCurLockdowns(); + + var bonusStorage = (int)(house.BonusStorageScalar * 100 - 100); + + if (bonusStorage > 0) + { + AddHtmlLocalized(10, 150, 300, 20, 1072519, LabelColor); // Increased Storage + AddLabel(310, 150, LabelHue, $"{bonusStorage}%"); + } + + AddHtmlLocalized(10, 170, 300, 20, 1060683, LabelColor); // Maximum Secure Storage + AddLabel(310, 170, LabelHue, maxSecures.ToString()); + + AddHtmlLocalized(10, 190, 300, 20, 1060685, LabelColor); // Used by Moving Crate + AddLabel(310, 190, LabelHue, fromMovingCrate.ToString()); + + AddHtmlLocalized(10, 210, 300, 20, 1060686, LabelColor); // Used by Lockdowns + AddLabel(310, 210, LabelHue, fromLockdowns.ToString()); + + if (BaseHouse.NewVendorSystem) + { + AddHtmlLocalized(10, 230, 300, 20, 1060688, LabelColor); // Used by Secure Containers + AddLabel(310, 230, LabelHue, fromSecures.ToString()); + + AddHtmlLocalized(10, 250, 300, 20, 1060689, LabelColor); // Available Storage + AddLabel(310, 250, LabelHue, Math.Max(maxSecures - curSecures, 0).ToString()); + + AddHtmlLocalized(10, 290, 300, 20, 1060690, LabelColor); // Maximum Lockdowns + AddLabel(310, 290, LabelHue, maxLockdowns.ToString()); + + AddHtmlLocalized(10, 310, 300, 20, 1060691, LabelColor); // Available Lockdowns + AddLabel(310, 310, LabelHue, Math.Max(maxLockdowns - curLockdowns, 0).ToString()); + + var maxVendors = house.GetNewVendorSystemMaxVendors(); + var vendors = house.PlayerVendors.Count + house.VendorRentalContracts.Count; + + AddHtmlLocalized(10, 350, 300, 20, 1062391, LabelColor); // Vendor Count + AddLabel(310, 350, LabelHue, $"{vendors} / {maxVendors}"); + } + else + { + AddHtmlLocalized(10, 230, 300, 20, 1060687, LabelColor); // Used by Vendors + AddLabel(310, 230, LabelHue, fromVendors.ToString()); + + AddHtmlLocalized(10, 250, 300, 20, 1060688, LabelColor); // Used by Secure Containers + AddLabel(310, 250, LabelHue, fromSecures.ToString()); + + AddHtmlLocalized(10, 270, 300, 20, 1060689, LabelColor); // Available Storage + AddLabel(310, 270, LabelHue, Math.Max(maxSecures - curSecures, 0).ToString()); + + AddHtmlLocalized(10, 330, 300, 20, 1060690, LabelColor); // Maximum Lockdowns + AddLabel(310, 330, LabelHue, maxLockdowns.ToString()); + + AddHtmlLocalized(10, 350, 300, 20, 1060691, LabelColor); // Available Lockdowns + AddLabel(310, 350, LabelHue, Math.Max(maxLockdowns - curLockdowns, 0).ToString()); + } + + break; + } + case HouseGumpPageAOS.Customize: + { + var isCustomizable = isOwner && house is HouseFoundation; + + AddButtonLabeled( + 10, + 120, + GetButtonID(5, 0), + 1060759, + isOwner && !isCustomizable && house.ConvertEntry != null + ); // Convert Into Customizable House + AddButtonLabeled( + 10, + 160, + GetButtonID(5, 1), + 1060765, + isOwner && isCustomizable + ); // Customize This House + AddButtonLabeled( + 10, + 180, + GetButtonID(5, 2), + 1060760, + isOwner && house.MovingCrate != null + ); // Relocate Moving Crate + AddButtonLabeled(10, 210, GetButtonID(5, 3), 1060761, isOwner && house.Public); // Change House Sign + AddButtonLabeled( + 10, + 230, + GetButtonID(5, 4), + 1060762, + isOwner && isCustomizable + ); // Change House Sign Hanger + AddButtonLabeled( + 10, + 250, + GetButtonID(5, 5), + 1060763, + isOwner && isCustomizable && ((HouseFoundation)house).Signpost != null + ); // Change Signpost + AddButtonLabeled( + 10, + 280, + GetButtonID(5, 6), + 1062004, + isOwner && isCustomizable + ); // Change Foundation Style + AddButtonLabeled(10, 310, GetButtonID(5, 7), 1060764, isCoOwner); // Rename House + + break; + } + case HouseGumpPageAOS.Ownership: + { + AddButtonLabeled( + 10, + 130, + GetButtonID(6, 0), + 1061794, + isOwner && house.MovingCrate == null && house.InternalizedVendors.Count == 0 + ); // Demolish House + AddButtonLabeled(10, 150, GetButtonID(6, 1), 1061797, isOwner); // Trade House + AddButtonLabeled(10, 190, GetButtonID(6, 2), 1061798, false); // Make Primary + + break; + } + case HouseGumpPageAOS.ChangeHanger: + { + for (var i = 0; i < m_HangerNumbers.Length; ++i) + { + var x = 50 + i % 3 * 100; + var y = 180 + i / 3 * 80; + + AddButton(x, y, 4005, 4007, GetButtonID(7, i)); + AddItem(x + 20, y, m_HangerNumbers[i]); + } + + break; + } + case HouseGumpPageAOS.ChangeFoundation: + { + for (var i = 0; i < m_FoundationNumbers.Length; ++i) + { + var x = 15 + i % 5 * 80; + var y = 180 + i / 5 * 100; + + AddButton(x, y, 4005, 4007, GetButtonID(8, i)); + AddItem(x + 25, y, m_FoundationNumbers[i]); + } + + break; + } + case HouseGumpPageAOS.ChangeSign: + { + var index = 0; + + if (_HouseSigns.Count == 0) + { + // Add standard signs + for (var i = 0; i < 54; ++i) _HouseSigns.Add(2980 + i * 2); + + // Add library and beekeeper signs ( ML ) + _HouseSigns.Add(2966); + _HouseSigns.Add(3140); + } + + var signsPerPage = Core.ML ? 24 : 18; + var totalSigns = Core.ML ? 56 : 54; + var pages = (int)Math.Ceiling((double)totalSigns / signsPerPage); + + for (var i = 0; i < pages; ++i) + { + AddPage(i + 1); + + AddButton(10, 360, 4005, 4007, 0, GumpButtonType.Page, (i + 1) % pages + 1); + + for (var j = 0; j < signsPerPage && totalSigns - signsPerPage * i - j > 0; ++j) + { + var x = 30 + j % 6 * 60; + var y = 130 + j / 6 * 60; + + AddButton(x, y, 4005, 4007, GetButtonID(9, index)); + AddItem(x + 20, y, _HouseSigns[index++]); + } + } + + break; + } + case HouseGumpPageAOS.RemoveCoOwner: + { + AddHtmlLocalized(10, 120, 400, 20, 1060730, LabelColor); //
CO-OWNER LIST
+ AddList(house.CoOwners, 10, false, true, from); + break; + } + case HouseGumpPageAOS.ListCoOwner: + { + AddHtmlLocalized(10, 120, 400, 20, 1060730, LabelColor); //
CO-OWNER LIST
+ AddList(house.CoOwners, -1, false, true, from); + break; + } + case HouseGumpPageAOS.RemoveFriend: + { + AddHtmlLocalized(10, 120, 400, 20, 1060731, LabelColor); //
FRIENDS LIST
+ AddList(house.Friends, 11, false, true, from); + break; + } + case HouseGumpPageAOS.ListFriend: + { + AddHtmlLocalized(10, 120, 400, 20, 1060731, LabelColor); //
FRIENDS LIST
+ AddList(house.Friends, -1, false, true, from); + break; + } + case HouseGumpPageAOS.RemoveBan: + { + AddHtmlLocalized(10, 120, 400, 20, 1060733, LabelColor); //
BAN LIST
+ AddList(house.Bans, 12, true, true, from); + break; + } + case HouseGumpPageAOS.ListBan: + { + AddHtmlLocalized(10, 120, 400, 20, 1060733, LabelColor); //
BAN LIST
+ AddList(house.Bans, -1, true, true, from); + break; + } + case HouseGumpPageAOS.RemoveAccess: + { + AddHtmlLocalized(10, 120, 400, 20, 1060732, LabelColor); //
ACCESS LIST
+ AddList(house.Access, 13, false, true, from); + break; + } + case HouseGumpPageAOS.ListAccess: + { + AddHtmlLocalized(10, 120, 400, 20, 1060732, LabelColor); //
ACCESS LIST
+ AddList(house.Access, -1, false, true, from); + break; + } + case HouseGumpPageAOS.ChangePost: + { + var index = 0; + + for (var i = 0; i < 2; ++i) + { + AddPage(i + 1); + + AddButton(10, 360, 4005, 4007, 0, GumpButtonType.Page, (i + 1) % 2 + 1); + + for (var j = 0; j < 16 && index < m_PostNumbers.Length; ++j) + { + var x = 15 + j % 8 * 50; + var y = 130 + j / 8 * 110; + + AddButton(x, y, 4005, 4007, GetButtonID(14, index)); + AddItem(x + 10, y, m_PostNumbers[index++]); + } + } + + break; + } + } + } + + private string GetOwnerName() + { + var m = m_House.Owner; + + return m?.Deleted != false ? "(unowned)" : m.Name.Trim().IsNullOrDefault("(no name)"); + } + + private string GetDateTime(DateTime val) => + val == DateTime.MinValue ? "" : val.ToString("yyyy'-'MM'-'dd HH':'mm':'ss"); + + public void AddPageButton(int x, int y, int buttonID, int number, HouseGumpPageAOS page) + { + var isSelection = m_Page == page; + + AddButton(x, y, isSelection ? 4006 : 4005, 4007, buttonID); + AddHtmlLocalized(x + 45, y, 200, 20, number, isSelection ? SelectedColor : LabelColor); + } + + public void AddButtonLabeled(int x, int y, int buttonID, int number, bool enabled = true) + { + if (enabled) + AddButton(x, y, 4005, 4007, buttonID); + + AddHtmlLocalized(x + 35, y, 240, 20, number, enabled ? LabelColor : DisabledColor); + } + + public void AddList(List list, int button, bool accountOf, bool leadingStar, Mobile from) + { + if (list == null) + return; + + m_List = new List(list); + + var lastPage = 0; + var index = 0; + + for (var i = 0; i < list.Count; ++i) + { + var xoffset = index % 20 / 10 * 200; + var yoffset = index % 10 * 20; + var page = 1 + index / 20; + + if (page != lastPage) + { + if (lastPage != 0) + AddButton(40, 360, 4005, 4007, 0, GumpButtonType.Page, page); + + AddPage(page); + + if (lastPage != 0) + AddButton(10, 360, 4014, 4016, 0, GumpButtonType.Page, lastPage); + + lastPage = page; + } + + var m = list[i]; + + string name; + var labelHue = LabelHue; + + if (m is PlayerVendor vendor) + { + name = vendor.ShopName; + + if (vendor.IsOwner(from)) + labelHue = HighlightedLabelHue; + } + else if (m != null) + { + name = m.Name; + } + else + { + continue; + } + + if ((name = name.Trim()).Length <= 0) + continue; + + if (button != -1) + AddButton(10 + xoffset, 150 + yoffset, 4005, 4007, GetButtonID(button, i)); + + if (accountOf && m.Player && m.Account != null) + name = $"Account of {name}"; + + if (leadingStar) + name = $"* {name}"; + + AddLabel(button > 0 ? 45 + xoffset : 10 + xoffset, 150 + yoffset, labelHue, name); + ++index; + } + } + + public static int GetButtonID(int type, int index) => 1 + index * 15 + type; + + public static void PublicPrivateNotice_Callback(Mobile from, BaseHouse house) + { + if (!house.Deleted) + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Security, from, house)); + } + + public static void CustomizeNotice_Callback(Mobile from, BaseHouse house) + { + if (!house.Deleted) + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Customize, from, house)); + } + + public static void ClearCoOwners_Callback(Mobile from, bool okay, BaseHouse house) + { + if (house.Deleted) + return; + + if (okay && house.IsOwner(from)) + { + house.CoOwners?.Clear(); + + from.SendLocalizedMessage(501333); // All co-owners have been removed from this house. + } + + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Security, from, house)); + } + + public static void ClearFriends_Callback(Mobile from, bool okay, BaseHouse house) + { + if (house.Deleted) + return; + + if (okay && house.IsCoOwner(from)) + { + house.Friends?.Clear(); + + from.SendLocalizedMessage(501332); // All friends have been removed from this house. + } + + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Security, from, house)); + } + + public static void ClearBans_Callback(Mobile from, bool okay, BaseHouse house) + { + if (house.Deleted) + return; + + if (okay && house.IsFriend(from)) + { + house.Bans?.Clear(); + + from.SendLocalizedMessage(1060754); // All bans for this house have been lifted. + } + + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Security, from, house)); + } + + public static void ClearAccess_Callback(Mobile from, bool okay, BaseHouse house) + { + if (house.Deleted) + return; + + if (okay && house.IsFriend(from)) + { + var list = house.Access.ToList(); + + house.Access?.Clear(); + + for (var i = 0; i < list.Count; ++i) + { + var m = list[i]; + + if (!house.HasAccess(m) && house.IsInside(m)) + { + m.Location = house.BanLocation; + m.SendLocalizedMessage(1060734); // Your access to this house has been revoked. + } + } + + from.SendLocalizedMessage(1061843); // This house's Access List has been cleared. + } + + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Security, from, house)); + } + + public static void ConvertHouse_Callback(Mobile from, bool okay, BaseHouse house) + { + if (house.Deleted) + return; + + if (okay && house.IsOwner(from) && !house.HasRentedVendors) + { + var e = house.ConvertEntry; + + if (e == null) + return; + + var cost = e.Cost - house.Price; + + if (cost > 0) + { + if (Banker.Withdraw(from, cost)) + { + from.SendLocalizedMessage( + 1060398, + cost.ToString() + ); // ~1_AMOUNT~ gold has been withdrawn from your bank box. + } + else + { + from.SendLocalizedMessage( + 1061624 + ); // You do not have enough funds in your bank to cover the difference between your old house and your new one. + return; + } + } + else if (cost < 0) + { + if (Banker.Deposit(from, -cost)) + from.SendLocalizedMessage( + 1060397, + (-cost).ToString() + ); // ~1_AMOUNT~ gold has been deposited into your bank box. + else + return; + } + + var newHouse = e.ConstructHouse(from); + + if (newHouse != null) + { + newHouse.Price = e.Cost; + + house.MoveAllToCrate(); + + newHouse.Friends = new List(house.Friends); + newHouse.CoOwners = new List(house.CoOwners); + newHouse.Bans = new List(house.Bans); + newHouse.Access = new List(house.Access); + newHouse.BuiltOn = house.BuiltOn; + newHouse.LastTraded = house.LastTraded; + newHouse.Public = house.Public; + + newHouse.VendorInventories.AddRange(house.VendorInventories); + house.VendorInventories.Clear(); + + foreach (var inventory in newHouse.VendorInventories) inventory.House = newHouse; + + newHouse.InternalizedVendors.AddRange(house.InternalizedVendors); + house.InternalizedVendors.Clear(); + + foreach (var mobile in newHouse.InternalizedVendors) + if (mobile is PlayerVendor vendor) + vendor.House = newHouse; + else if (mobile is PlayerBarkeeper barkeeper) + barkeeper.House = newHouse; + + if (house.MovingCrate != null) + { + newHouse.MovingCrate = house.MovingCrate; + newHouse.MovingCrate.House = newHouse; + house.MovingCrate = null; + } + + var items = house.GetItems(); + var mobiles = house.GetMobiles(); + + newHouse.MoveToWorld( + new Point3D( + house.X + house.ConvertOffsetX, + house.Y + house.ConvertOffsetY, + house.Z + house.ConvertOffsetZ + ), + house.Map + ); + house.Delete(); + + foreach (var item in items) item.Location = newHouse.BanLocation; + + foreach (var mobile in mobiles) mobile.Location = newHouse.BanLocation; + + /* You have successfully replaced your original house with a new house. + * The value of the replaced house has been deposited into your bank box. + * All of the items in your original house have been relocated to a Moving Crate in the new house. + * Any deed-based house add-ons have been converted back into deeds. + * Vendors and barkeeps in the house, if any, have been stored in the Moving Crate as well. + * Use the Get Vendor context-sensitive menu option on your character to retrieve them. + * These containers can be used to re-create the vendor in a new location. + * Any barkeepers have been converted into deeds. + */ + from.SendGump(new NoticeGump(1060637, 30720, 1060012, 32512, 420, 280)); + return; + } + } + + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Security, from, house)); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_House.Deleted) + return; + + var from = sender.Mobile; + + var isCombatRestricted = m_House.IsCombatRestricted(from); + + var isOwner = m_House.IsOwner(from); + var isCoOwner = isOwner || m_House.IsCoOwner(from); + var isFriend = isCoOwner || m_House.IsFriend(from); + + if (isCombatRestricted) + isCoOwner = isFriend = false; + + if (!from.CheckAlive()) + return; + + Item sign = m_House.Sign; + + if (sign == null || from.Map != sign.Map || !from.InRange(sign.GetWorldLocation(), 18)) + return; + + var foundation = m_House as HouseFoundation; + var isCustomizable = foundation != null; + + var val = info.ButtonID - 1; + + if (val < 0) + return; + + var type = val % 15; + var index = val / 15; + + if (m_Page == HouseGumpPageAOS.Vendors) + { + if (index < m_List.Count) + { + var vendor = (PlayerVendor)m_List[index]; + + if (!vendor.CanInteractWith(from, false)) + return; + + if (from.Map != sign.Map || !from.InRange(sign, 5)) + from.SendLocalizedMessage( + 1062429 + ); // You must be within five paces of the house sign to use this option. + else if (vendor.IsOwner(from)) + vendor.SendOwnerGump(from); + else + vendor.OpenBackpack(from); + } + + return; + } + + if (!isFriend) + return; + + switch (type) + { + case 0: + { + switch (index) + { + case 0: // Banish + { + if (m_House.Public) + { + from.SendLocalizedMessage(501325); // Target the individual to ban from this house. + from.Target = new HouseBanTarget(true, m_House); + } + + break; + } + case 1: // Lift Ban + { + if (m_House.Public) + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.RemoveBan, from, m_House)); + + break; + } + case 2: // Grant Access + { + if (!m_House.Public) + { + from.SendLocalizedMessage( + 1060711 + ); // Target the person you would like to grant access to. + from.Target = new HouseAccessTarget(m_House); + } + + break; + } + case 3: // Revoke Access + { + if (!m_House.Public) + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.RemoveAccess, from, m_House)); + + break; + } + } + + break; + } + case 1: + { + HouseGumpPageAOS page; + + switch (index) + { + case 0: + page = HouseGumpPageAOS.Information; + break; + case 1: + page = HouseGumpPageAOS.Security; + break; + case 2: + page = HouseGumpPageAOS.Storage; + break; + case 3: + page = HouseGumpPageAOS.Customize; + break; + case 4: + page = HouseGumpPageAOS.Ownership; + break; + default: return; + } + + from.SendGump(new HouseGumpAOS(page, from, m_House)); + break; + } + case 3: + { + switch (index) + { + case 0: // View Co-Owner List + { + if (isCoOwner) + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.ListCoOwner, from, m_House)); + + break; + } + case 1: // Add a Co-Owner + { + if (isOwner) + { + from.SendLocalizedMessage( + 501328 + ); // Target the person you wish to name a co-owner of your household. + from.Target = new CoOwnerTarget(true, m_House); + } + + break; + } + case 2: // Remove a Co-Owner + { + if (isOwner) + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.RemoveCoOwner, from, m_House)); + + break; + } + case 3: // Clear Co-Owner List + { + if (isOwner) + from.SendGump( + new WarningGump( + 1060635, + 30720, + 1060736, + 32512, + 420, + 280, + okay => ClearCoOwners_Callback(from, okay, m_House) + ) + ); + + break; + } + case 4: // View Friends List + { + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.ListFriend, from, m_House)); + + break; + } + case 5: // Add a Friend + { + if (isCoOwner) + { + from.SendLocalizedMessage( + 501317 + ); // Target the person you wish to name a friend of your household. + from.Target = new HouseFriendTarget(true, m_House); + } + + break; + } + case 6: // Remove a Friend + { + if (isCoOwner) + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.RemoveFriend, from, m_House)); + + break; + } + case 7: // Clear Friend List + { + if (isCoOwner) + from.SendGump( + new WarningGump( + 1060635, + 30720, + 1018039, + 32512, + 420, + 280, + okay => ClearFriends_Callback(from, okay, m_House) + ) + ); + + break; + } + case 8: // View Ban List + { + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.ListBan, from, m_House)); + + break; + } + case 9: // Clear Ban List + { + from.SendGump( + new WarningGump( + 1060635, + 30720, + 1060753, + 32512, + 420, + 280, + okay => ClearBans_Callback(from, okay, m_House) + ) + ); + + break; + } + case 10: // View Access List + { + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.ListAccess, from, m_House)); + + break; + } + case 11: // Clear Access List + { + from.SendGump( + new WarningGump( + 1060635, + 30720, + 1061842, + 32512, + 420, + 280, + okay => ClearAccess_Callback(from, okay, m_House) + ) + ); + + break; + } + case 12: // Make Private + { + if (isOwner) + { + if (m_House.PlayerVendors.Count > 0) + { + // You have vendors working out of this building. It cannot be declared private until there are no vendors in place. + from.SendGump( + new NoticeGump( + 1060637, + 30720, + 501887, + 32512, + 320, + 180, + () => PublicPrivateNotice_Callback(from, m_House) + ) + ); + break; + } + + if (m_House.VendorRentalContracts.Count > 0) + { + // You cannot currently take this action because you have vendor contracts locked down in your home. You must remove them first. + from.SendGump( + new NoticeGump( + 1060637, + 30720, + 1062351, + 32512, + 320, + 180, + () => PublicPrivateNotice_Callback(from, m_House) + ) + ); + break; + } + + m_House.Public = false; + + m_House.ChangeLocks(from); + + // This house is now private. + from.SendGump( + new NoticeGump( + 1060637, + 30720, + 501888, + 32512, + 320, + 180, + () => PublicPrivateNotice_Callback(from, m_House) + ) + ); + + var r = m_House.Region; + var list = r.GetMobiles(); + + for (var i = 0; i < list.Count; ++i) + { + var m = list[i]; + + if (!m_House.HasAccess(m) && m_House.IsInside(m)) + m.Location = m_House.BanLocation; + } + } + + break; + } + case 13: // Make Public + { + if (isOwner) + { + m_House.Public = true; + + m_House.RemoveKeys(from); + m_House.RemoveLocks(); + + if (BaseHouse.NewVendorSystem) + from.SendGump( + new NoticeGump( + 1060637, + 30720, + 501886, + 32512, + 320, + 180, + () => PublicPrivateNotice_Callback(from, m_House) + ) + ); + else + from.SendGump( + new NoticeGump( + 1060637, + 30720, + "This house is now public. Friends of the house may now have vendors working out of this building.", + 0xF8C000, + 320, + 180, + () => PublicPrivateNotice_Callback(from, m_House) + ) + ); + + var r = m_House.Region; + var list = r.GetMobiles(); + + for (var i = 0; i < list.Count; ++i) + { + var m = list[i]; + + if (m_House.IsBanned(m) && m_House.IsInside(m)) + m.Location = m_House.BanLocation; + } + } + + break; + } + } + + break; + } + case 5: + { + switch (index) + { + case 0: // Convert Into Customizable House + { + if (isOwner && !isCustomizable) + { + if (m_House.HasRentedVendors) + { + // You cannot perform this action while you still have vendors rented out in this house. + from.SendGump( + new NoticeGump( + 1060637, + 30720, + 1062395, + 32512, + 320, + 180, + () => CustomizeNotice_Callback(from, m_House) + ) + ); + } + else + { + var e = m_House.ConvertEntry; + + if (e != null) + from.SendGump( + new WarningGump( + 1060635, + 30720, + 1060013, + 32512, + 420, + 280, + okay => ConvertHouse_Callback(from, okay, m_House) + ) + ); + } + } + + break; + } + case 1: // Customize This House + { + if (isOwner && isCustomizable) + { + if (m_House.HasRentedVendors) + from.SendGump( + new NoticeGump( + 1060637, + 30720, + 1062395, + 32512, + 320, + 180, + () => CustomizeNotice_Callback(from, m_House) + ) + ); + else if (m_House.HasAddonContainers) + from.SendGump( + new NoticeGump( + 1060637, + 30720, + 1074863, + 32512, + 320, + 180, + () => CustomizeNotice_Callback(from, m_House) + ) + ); + else + foundation.BeginCustomize(from); + } + + break; + } + case 2: // Relocate Moving Crate + { + var crate = m_House.MovingCrate; + + if (isOwner && crate != null) + { + if (!m_House.IsInside(from)) + { + from.SendLocalizedMessage(502092); // You must be in your house to do this. + } + else + { + crate.MoveToWorld(from.Location, from.Map); + crate.RestartTimer(); + } + } + + break; + } + case 3: // Change House Sign + { + if (isOwner && m_House.Public) + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.ChangeSign, from, m_House)); + + break; + } + case 4: // Change House Sign Hanger + { + if (isOwner && isCustomizable) + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.ChangeHanger, from, m_House)); + + break; + } + case 5: // Change Signpost + { + if (isOwner && isCustomizable && foundation.Signpost != null) + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.ChangePost, from, m_House)); + + break; + } + case 6: // Change Foundation Style + { + if (isOwner && isCustomizable) + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.ChangeFoundation, from, m_House)); + + break; + } + case 7: // Rename House + { + if (isCoOwner) + { + from.Prompt = new RenamePrompt(m_House); + from.SendLocalizedMessage(501302); // What dost thou wish the sign to say? + } + + break; + } + } + + break; + } + case 6: + { + switch (index) + { + case 0: // Demolish + { + if (isOwner && m_House.MovingCrate == null && m_House.InternalizedVendors.Count == 0) + { + if (!Guild.NewGuildSystem && m_House.FindGuildstone() != null) + { + from.SendLocalizedMessage( + 501389 + ); // You cannot redeed a house with a guildstone inside. + } + else if (Core.ML && from.AccessLevel < AccessLevel.GameMaster && + DateTime.UtcNow <= m_House.BuiltOn.AddHours(1)) + { + from.SendLocalizedMessage( + 1080178 + ); // You must wait one hour between each house demolition. + } + else + { + from.CloseGump(); + from.SendGump(new HouseDemolishGump(from, m_House)); + } + } + + break; + } + case 1: // Trade House + { + if (isOwner) + { + if (BaseHouse.NewVendorSystem && m_House.HasPersonalVendors) + { + from.SendLocalizedMessage( + 1062467 + ); // You cannot trade this house while you still have personal vendors inside. + } + else if (m_House.DecayLevel == DecayLevel.DemolitionPending) + { + from.SendLocalizedMessage( + 1005321 + ); // This house has been marked for demolition, and it cannot be transferred. + } + else + { + from.SendLocalizedMessage( + 501309 + ); // Target the person to whom you wish to give this house. + from.Target = new HouseOwnerTarget(m_House); + } + } + + break; + } + case 2: // Make Primary + break; + } + + break; + } + case 7: + { + if (isOwner && isCustomizable && index < m_HangerNumbers.Length) + { + var hanger = foundation.SignHanger; + + if (hanger != null) + hanger.ItemID = m_HangerNumbers[index]; + + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Customize, from, m_House)); + } + + break; + } + case 8: + { + if (isOwner && isCustomizable) + { + FoundationType newType; + + if (Core.ML && index >= 5) + switch (index) + { + case 5: + newType = FoundationType.ElvenGrey; + break; + case 6: + newType = FoundationType.ElvenNatural; + break; + case 7: + newType = FoundationType.Crystal; + break; + case 8: + newType = FoundationType.Shadow; + break; + default: return; + } + else + switch (index) + { + case 0: + newType = FoundationType.DarkWood; + break; + case 1: + newType = FoundationType.LightWood; + break; + case 2: + newType = FoundationType.Dungeon; + break; + case 3: + newType = FoundationType.Brick; + break; + case 4: + newType = FoundationType.Stone; + break; + default: return; + } + + foundation.Type = newType; + + var state = foundation.BackupState; + HouseFoundation.ApplyFoundation(newType, state.Components); + state.OnRevised(); + + state = foundation.DesignState; + HouseFoundation.ApplyFoundation(newType, state.Components); + state.OnRevised(); + + state = foundation.CurrentState; + HouseFoundation.ApplyFoundation(newType, state.Components); + state.OnRevised(); + + foundation.Delta(ItemDelta.Update); + + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Customize, from, m_House)); + } + + break; + } + case 9: + { + if (isOwner && m_House.Public && index < _HouseSigns.Count) + { + m_House.ChangeSignType(_HouseSigns[index]); + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Customize, from, m_House)); + } + + break; + } + case 10: + { + if (isOwner && index < m_List?.Count) + { + m_House.RemoveCoOwner(from, m_List[index]); + + if (m_House.CoOwners.Count > 0) + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.RemoveCoOwner, from, m_House)); + else + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Security, from, m_House)); + } + + break; + } + case 11: + { + if (isCoOwner && index < m_List?.Count) + { + m_House.RemoveFriend(from, m_List[index]); + + if (m_House.Friends.Count > 0) + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.RemoveFriend, from, m_House)); + else + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Security, from, m_House)); + } + + break; + } + case 12: + { + if (index < m_List?.Count) + { + m_House.RemoveBan(from, m_List[index]); + + if (m_House.Bans.Count > 0) + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.RemoveBan, from, m_House)); + else + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Security, from, m_House)); + } + + break; + } + case 13: + { + if (index < m_List?.Count) + { + m_House.RemoveAccess(from, m_List[index]); + + if (m_House.Access.Count > 0) + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.RemoveAccess, from, m_House)); + else + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Security, from, m_House)); + } + + break; + } + case 14: + { + if (isOwner && isCustomizable && index < m_PostNumbers.Length) + { + foundation.SignpostGraphic = m_PostNumbers[index]; + foundation.CheckSignpost(); + + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Customize, from, m_House)); + } + + break; + } + } + } + + private List Wrap(string value) + { + if (value == null || (value = value.Trim()).Length <= 0) + return null; + + var values = value.Split(' '); + var list = new List(); + var current = ""; + + for (var i = 0; i < values.Length; ++i) + { + var val = values[i]; + + var v = current.Length == 0 ? val : $"{current} {val}"; + + if (v.Length < 10) + { + current = v; + } + else if (v.Length == 10) + { + list.Add(v); + + if (list.Count == 6) + return list; + + current = ""; + } + else if (val.Length <= 10) + { + list.Add(current); + + if (list.Count == 6) + return list; + + current = val; + } + else + { + while (v.Length >= 10) + { + list.Add(v.Substring(0, 10)); + + if (list.Count == 6) + return list; + + v = v.Substring(10); + } + + current = v; + } + } + + if (current.Length > 0) + list.Add(current); + + return list; + } + } +} diff --git a/Projects/UOContent/Gumps/HouseTransferGump.cs b/Projects/UOContent/Gumps/HouseTransferGump.cs index 8af408063..3bce440af 100644 --- a/Projects/UOContent/Gumps/HouseTransferGump.cs +++ b/Projects/UOContent/Gumps/HouseTransferGump.cs @@ -1,63 +1,63 @@ -using Server.Multis; -using Server.Network; - -namespace Server.Gumps -{ - public class HouseTransferGump : Gump - { - private readonly Mobile m_From; - private readonly Mobile m_To; - private readonly BaseHouse m_House; - - public HouseTransferGump(Mobile from, Mobile to, BaseHouse house) : base(110, 100) - { - m_From = from; - m_To = to; - m_House = house; - - Closable = false; - - AddPage(0); - - AddBackground(0, 0, 420, 280, 5054); - - AddImageTiled(10, 10, 400, 20, 2624); - AddAlphaRegion(10, 10, 400, 20); - - AddHtmlLocalized(10, 10, 400, 20, 1060635, 30720); //
WARNING
- - AddImageTiled(10, 40, 400, 200, 2624); - AddAlphaRegion(10, 40, 400, 200); - - /* Another player is attempting to initiate a house trade with you. - * In order for you to see this window, both you and the other person are standing within two paces of the house to be traded. - * If you click OKAY below, a house trade scroll will appear in your trade window and you can complete the transaction. - * This scroll is a distinctive blue color and will show the name of the house, the name of the owner of that house, and the sextant coordinates of the center of the house when you hover your mouse over it. - * In order for the transaction to be successful, you both must accept the trade and you both must remain within two paces of the house sign. - *

Accepting this house in trade will condemn any and all of your other houses that you may have. - * All of your houses on all shards will be affected. - *

In addition, you will not be able to place another house or have one transferred to you for one (1) real-life week.

- * Once you accept these terms, these effects cannot be reversed. - * Re-deeding or transferring your new house will not uncondemn your other house(s) nor will the one week timer be removed.

- * If you are absolutely certain you wish to proceed, click the button next to OKAY below. - * If you do not wish to trade for this house, click CANCEL. - */ - AddHtmlLocalized(10, 40, 400, 200, 1062086, 32512, false, true); - - AddImageTiled(10, 250, 400, 20, 2624); - AddAlphaRegion(10, 250, 400, 20); - - AddButton(10, 250, 4005, 4007, 1); - AddHtmlLocalized(40, 250, 170, 20, 1011036, 32767); // OKAY - - AddButton(210, 250, 4005, 4007, 0); - AddHtmlLocalized(240, 250, 170, 20, 1011012, 32767); // CANCEL - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (info.ButtonID == 1 && !m_House.Deleted) - m_House.EndConfirmTransfer(m_From, m_To); - } - } -} +using Server.Multis; +using Server.Network; + +namespace Server.Gumps +{ + public class HouseTransferGump : Gump + { + private readonly Mobile m_From; + private readonly BaseHouse m_House; + private readonly Mobile m_To; + + public HouseTransferGump(Mobile from, Mobile to, BaseHouse house) : base(110, 100) + { + m_From = from; + m_To = to; + m_House = house; + + Closable = false; + + AddPage(0); + + AddBackground(0, 0, 420, 280, 5054); + + AddImageTiled(10, 10, 400, 20, 2624); + AddAlphaRegion(10, 10, 400, 20); + + AddHtmlLocalized(10, 10, 400, 20, 1060635, 30720); //
WARNING
+ + AddImageTiled(10, 40, 400, 200, 2624); + AddAlphaRegion(10, 40, 400, 200); + + /* Another player is attempting to initiate a house trade with you. + * In order for you to see this window, both you and the other person are standing within two paces of the house to be traded. + * If you click OKAY below, a house trade scroll will appear in your trade window and you can complete the transaction. + * This scroll is a distinctive blue color and will show the name of the house, the name of the owner of that house, and the sextant coordinates of the center of the house when you hover your mouse over it. + * In order for the transaction to be successful, you both must accept the trade and you both must remain within two paces of the house sign. + *

Accepting this house in trade will condemn any and all of your other houses that you may have. + * All of your houses on all shards will be affected. + *

In addition, you will not be able to place another house or have one transferred to you for one (1) real-life week.

+ * Once you accept these terms, these effects cannot be reversed. + * Re-deeding or transferring your new house will not uncondemn your other house(s) nor will the one week timer be removed.

+ * If you are absolutely certain you wish to proceed, click the button next to OKAY below. + * If you do not wish to trade for this house, click CANCEL. + */ + AddHtmlLocalized(10, 40, 400, 200, 1062086, 32512, false, true); + + AddImageTiled(10, 250, 400, 20, 2624); + AddAlphaRegion(10, 250, 400, 20); + + AddButton(10, 250, 4005, 4007, 1); + AddHtmlLocalized(40, 250, 170, 20, 1011036, 32767); // OKAY + + AddButton(210, 250, 4005, 4007, 0); + AddHtmlLocalized(240, 250, 170, 20, 1011012, 32767); // CANCEL + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (info.ButtonID == 1 && !m_House.Deleted) + m_House.EndConfirmTransfer(m_From, m_To); + } + } +} diff --git a/Projects/UOContent/Gumps/NoticeGump.cs b/Projects/UOContent/Gumps/NoticeGump.cs index 15416f4c6..c06d398de 100644 --- a/Projects/UOContent/Gumps/NoticeGump.cs +++ b/Projects/UOContent/Gumps/NoticeGump.cs @@ -1,47 +1,56 @@ -using Server.Network; - -namespace Server.Gumps -{ - public delegate void NoticeGumpCallback(); - - public class NoticeGump : Gump - { - private readonly NoticeGumpCallback m_Callback; - - public NoticeGump(int header, int headerColor, object content, int contentColor, int width, int height, - NoticeGumpCallback callback = null) : base((640 - width) / 2, (480 - height) / 2) - { - m_Callback = callback; - - Closable = false; - - AddPage(0); - - AddBackground(0, 0, width, height, 5054); - - AddImageTiled(10, 10, width - 20, 20, 2624); - AddAlphaRegion(10, 10, width - 20, 20); - AddHtmlLocalized(10, 10, width - 20, 20, header, headerColor); - - AddImageTiled(10, 40, width - 20, height - 80, 2624); - AddAlphaRegion(10, 40, width - 20, height - 80); - - if (content is int i) - AddHtmlLocalized(10, 40, width - 20, height - 80, i, contentColor, false, true); - else if (content is string) - AddHtml(10, 40, width - 20, height - 80, $"{content}", false, - true); - - AddImageTiled(10, height - 30, width - 20, 20, 2624); - AddAlphaRegion(10, height - 30, width - 20, 20); - AddButton(10, height - 30, 4005, 4007, 1); - AddHtmlLocalized(40, height - 30, 120, 20, 1011036, 32767); // OKAY - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 1) - m_Callback?.Invoke(); - } - } -} +using Server.Network; + +namespace Server.Gumps +{ + public delegate void NoticeGumpCallback(); + + public class NoticeGump : Gump + { + private readonly NoticeGumpCallback m_Callback; + + public NoticeGump( + int header, int headerColor, object content, int contentColor, int width, int height, + NoticeGumpCallback callback = null + ) : base((640 - width) / 2, (480 - height) / 2) + { + m_Callback = callback; + + Closable = false; + + AddPage(0); + + AddBackground(0, 0, width, height, 5054); + + AddImageTiled(10, 10, width - 20, 20, 2624); + AddAlphaRegion(10, 10, width - 20, 20); + AddHtmlLocalized(10, 10, width - 20, 20, header, headerColor); + + AddImageTiled(10, 40, width - 20, height - 80, 2624); + AddAlphaRegion(10, 40, width - 20, height - 80); + + if (content is int i) + AddHtmlLocalized(10, 40, width - 20, height - 80, i, contentColor, false, true); + else if (content is string) + AddHtml( + 10, + 40, + width - 20, + height - 80, + $"{content}", + false, + true + ); + + AddImageTiled(10, height - 30, width - 20, 20, 2624); + AddAlphaRegion(10, height - 30, width - 20, 20); + AddButton(10, height - 30, 4005, 4007, 1); + AddHtmlLocalized(40, height - 30, 120, 20, 1011036, 32767); // OKAY + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 1) + m_Callback?.Invoke(); + } + } +} diff --git a/Projects/UOContent/Gumps/PetResurrectGump.cs b/Projects/UOContent/Gumps/PetResurrectGump.cs index ee9228fe8..07b07c78f 100644 --- a/Projects/UOContent/Gumps/PetResurrectGump.cs +++ b/Projects/UOContent/Gumps/PetResurrectGump.cs @@ -1,77 +1,78 @@ -using Server.Mobiles; -using Server.Network; - -namespace Server.Gumps -{ - public class PetResurrectGump : Gump - { - private readonly double m_HitsScalar; - private readonly BaseCreature m_Pet; - - public PetResurrectGump(Mobile from, BaseCreature pet, double hitsScalar = 0.0) : base(50, 50) - { - from.CloseGump(); - - m_Pet = pet; - m_HitsScalar = hitsScalar; - - AddPage(0); - - AddBackground(10, 10, 265, 140, 0x242C); - - AddItem(205, 40, 0x4); - AddItem(227, 40, 0x5); - - AddItem(180, 78, 0xCAE); - AddItem(195, 90, 0xCAD); - AddItem(218, 95, 0xCB0); - - AddHtmlLocalized(30, 30, 150, 75, 1049665); //
Wilt thou sanctify the resurrection of:
- AddHtml(30, 70, 150, 25, $"
{pet.Name}
", true); - - AddButton(40, 105, 0x81A, 0x81B, 0x1); // Okay - AddButton(110, 105, 0x819, 0x818, 0x2); // Cancel - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (m_Pet.Deleted || !m_Pet.IsBonded || !m_Pet.IsDeadPet) - return; - - Mobile from = state.Mobile; - - if (info.ButtonID == 1) - { - if (m_Pet.Map?.CanFit(m_Pet.Location, 16, false, false) != true) - { - from.SendLocalizedMessage(503256); // You fail to resurrect the creature. - return; - } - - if (m_Pet.Region?.IsPartOf("Khaldun") == true) // TODO: Confirm for pets, as per Bandage's script. - { - from.SendLocalizedMessage( - 1010395); // The veil of death in this area is too strong and resists thy efforts to restore life. - return; - } - - m_Pet.PlaySound(0x214); - m_Pet.FixedEffect(0x376A, 10, 16); - m_Pet.ResurrectPet(); - - double decreaseAmount; - - if (from == m_Pet.ControlMaster) - decreaseAmount = 0.1; - else - decreaseAmount = 0.2; - - for (int i = 0; i < m_Pet.Skills.Length; ++i) // Decrease all skills on pet. - m_Pet.Skills[i].Base -= decreaseAmount; - - if (!m_Pet.IsDeadPet && m_HitsScalar > 0) - m_Pet.Hits = (int)(m_Pet.HitsMax * m_HitsScalar); - } - } - } -} +using Server.Mobiles; +using Server.Network; + +namespace Server.Gumps +{ + public class PetResurrectGump : Gump + { + private readonly double m_HitsScalar; + private readonly BaseCreature m_Pet; + + public PetResurrectGump(Mobile from, BaseCreature pet, double hitsScalar = 0.0) : base(50, 50) + { + from.CloseGump(); + + m_Pet = pet; + m_HitsScalar = hitsScalar; + + AddPage(0); + + AddBackground(10, 10, 265, 140, 0x242C); + + AddItem(205, 40, 0x4); + AddItem(227, 40, 0x5); + + AddItem(180, 78, 0xCAE); + AddItem(195, 90, 0xCAD); + AddItem(218, 95, 0xCB0); + + AddHtmlLocalized(30, 30, 150, 75, 1049665); //
Wilt thou sanctify the resurrection of:
+ AddHtml(30, 70, 150, 25, $"
{pet.Name}
", true); + + AddButton(40, 105, 0x81A, 0x81B, 0x1); // Okay + AddButton(110, 105, 0x819, 0x818, 0x2); // Cancel + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (m_Pet.Deleted || !m_Pet.IsBonded || !m_Pet.IsDeadPet) + return; + + var from = state.Mobile; + + if (info.ButtonID == 1) + { + if (m_Pet.Map?.CanFit(m_Pet.Location, 16, false, false) != true) + { + from.SendLocalizedMessage(503256); // You fail to resurrect the creature. + return; + } + + if (m_Pet.Region?.IsPartOf("Khaldun") == true) // TODO: Confirm for pets, as per Bandage's script. + { + from.SendLocalizedMessage( + 1010395 + ); // The veil of death in this area is too strong and resists thy efforts to restore life. + return; + } + + m_Pet.PlaySound(0x214); + m_Pet.FixedEffect(0x376A, 10, 16); + m_Pet.ResurrectPet(); + + double decreaseAmount; + + if (from == m_Pet.ControlMaster) + decreaseAmount = 0.1; + else + decreaseAmount = 0.2; + + for (var i = 0; i < m_Pet.Skills.Length; ++i) // Decrease all skills on pet. + m_Pet.Skills[i].Base -= decreaseAmount; + + if (!m_Pet.IsDeadPet && m_HitsScalar > 0) + m_Pet.Hits = (int)(m_Pet.HitsMax * m_HitsScalar); + } + } + } +} diff --git a/Projects/UOContent/Gumps/PlayerVendorGumps.cs b/Projects/UOContent/Gumps/PlayerVendorGumps.cs index e2d11f629..b3b721462 100644 --- a/Projects/UOContent/Gumps/PlayerVendorGumps.cs +++ b/Projects/UOContent/Gumps/PlayerVendorGumps.cs @@ -1,1043 +1,1100 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using Server.HuePickers; -using Server.Items; -using Server.Mobiles; -using Server.Network; - -namespace Server.Gumps -{ - public class PlayerVendorBuyGump : Gump - { - private readonly PlayerVendor m_Vendor; - private readonly VendorItem m_VI; - - public PlayerVendorBuyGump(PlayerVendor vendor, VendorItem vi) : base(100, 200) - { - m_Vendor = vendor; - m_VI = vi; - - AddBackground(100, 10, 300, 150, 5054); - - AddHtmlLocalized(125, 20, 250, 24, 1019070); // You have agreed to purchase: - - if (!string.IsNullOrEmpty(vi.Description)) - AddLabel(125, 45, 0, vi.Description); - else - AddHtmlLocalized(125, 45, 250, 24, 1019072); // an item without a description - - AddHtmlLocalized(125, 70, 250, 24, 1019071); // for the amount of: - AddLabel(125, 95, 0, vi.Price.ToString()); - - AddButton(250, 130, 4005, 4007, 0); - AddHtmlLocalized(282, 130, 100, 24, 1011012); // CANCEL - - AddButton(120, 130, 4005, 4007, 1); - AddHtmlLocalized(152, 130, 100, 24, 1011036); // OKAY - } - - public override void OnResponse(NetState state, RelayInfo info) - { - Mobile from = state.Mobile; - - if (!m_Vendor.CanInteractWith(from, false)) - return; - - if (m_Vendor.IsOwner(from)) - { - m_Vendor.SayTo(from, 503212); // You own this shop, just take what you want. - return; - } - - if (info.ButtonID == 1) - { - m_Vendor.Say(from.Name); - - if (!m_VI.Valid || !m_VI.Item.IsChildOf(m_Vendor.Backpack)) - { - m_Vendor.SayTo(from, 503216); // You can't buy that. - return; - } - - int totalGold = 0; - - if (from.Backpack != null) - totalGold += from.Backpack.GetAmount(typeof(Gold)); - - totalGold += Banker.GetBalance(from); - - if (totalGold < m_VI.Price) - { - m_Vendor.SayTo(from, 503205); // You cannot afford this item. - } - else if (!from.PlaceInBackpack(m_VI.Item)) - { - m_Vendor.SayTo(from, 503204); // You do not have room in your backpack for this. - } - else - { - int leftPrice = m_VI.Price; - - if (from.Backpack != null) - leftPrice -= from.Backpack.ConsumeUpTo(typeof(Gold), leftPrice); - - if (leftPrice > 0) - Banker.Withdraw(from, leftPrice); - - m_Vendor.HoldGold += m_VI.Price; - - from.SendLocalizedMessage(503201); // You take the item. - } - } - else - { - from.SendLocalizedMessage(503207); // Cancelled purchase. - } - } - } - - public class PlayerVendorOwnerGump : Gump - { - private readonly PlayerVendor m_Vendor; - - public PlayerVendorOwnerGump(PlayerVendor vendor) : base(50, 200) - { - m_Vendor = vendor; - - int perDay = m_Vendor.ChargePerDay; - - AddPage(0); - AddBackground(25, 10, 530, 140, 5054); - - AddHtmlLocalized(425, 25, 120, 20, 1019068); // See goods - AddButton(390, 25, 4005, 4007, 1); - AddHtmlLocalized(425, 48, 120, 20, 1019069); // Customize - AddButton(390, 48, 4005, 4007, 2); - AddHtmlLocalized(425, 72, 120, 20, 1011012); // CANCEL - AddButton(390, 71, 4005, 4007, 0); - - AddHtmlLocalized(40, 72, 260, 20, 1038321); // Gold held for you: - AddLabel(300, 72, 0, m_Vendor.HoldGold.ToString()); - AddHtmlLocalized(40, 96, 260, 20, 1038322); // Gold held in my account: - AddLabel(300, 96, 0, m_Vendor.BankAccount.ToString()); - - // AddHtmlLocalized( 40, 120, 260, 20, 1038324, false, false ); // My charge per day is: - // Localization has changed, we must use a string here - AddHtml(40, 120, 260, 20, "My charge per day is:"); - AddLabel(300, 120, 0, perDay.ToString()); - - double days = (m_Vendor.HoldGold + m_Vendor.BankAccount) / (double)perDay; - - AddHtmlLocalized(40, 25, 260, 20, 1038318); // Amount of days I can work: - AddLabel(300, 25, 0, ((int)days).ToString()); - AddHtmlLocalized(40, 48, 260, 20, 1038319); // Earth days: - AddLabel(300, 48, 0, ((int)(days / 12.0)).ToString()); - } - - public override void OnResponse(NetState state, RelayInfo info) - { - Mobile from = state.Mobile; - - if (!m_Vendor.CanInteractWith(from, true)) - return; - - switch (info.ButtonID) - { - case 1: - { - m_Vendor.OpenBackpack(from); - - break; - } - case 2: - { - from.SendGump(new PlayerVendorCustomizeGump(m_Vendor, from)); - - break; - } - } - } - } - - public class NewPlayerVendorOwnerGump : Gump - { - private readonly PlayerVendor m_Vendor; - - public NewPlayerVendorOwnerGump(PlayerVendor vendor) : base(50, 200) - { - m_Vendor = vendor; - - int perRealWorldDay = vendor.ChargePerRealWorldDay; - int goldHeld = vendor.HoldGold; - - AddBackground(25, 10, 530, 180, 0x13BE); - - AddImageTiled(35, 20, 510, 160, 0xA40); - AddAlphaRegion(35, 20, 510, 160); - - AddImage(10, 0, 0x28DC); - AddImage(537, 175, 0x28DC); - AddImage(10, 175, 0x28DC); - AddImage(537, 0, 0x28DC); - - if (goldHeld < perRealWorldDay) - { - int goldNeeded = perRealWorldDay - goldHeld; - - AddHtmlLocalized(40, 35, 260, 20, 1038320, 0x7FFF); // Gold needed for 1 day of vendor salary: - AddLabel(300, 35, 0x1F, goldNeeded.ToString()); - } - else - { - int days = goldHeld / perRealWorldDay; - - AddHtmlLocalized(40, 35, 260, 20, 1038318, 0x7FFF); // # of days Vendor salary is paid for: - AddLabel(300, 35, 0x480, days.ToString()); - } - - AddHtmlLocalized(40, 58, 260, 20, 1038324, 0x7FFF); // My charge per real world day is: - AddLabel(300, 58, 0x480, perRealWorldDay.ToString()); - - AddHtmlLocalized(40, 82, 260, 20, 1038322, 0x7FFF); // Gold held in my account: - AddLabel(300, 82, 0x480, goldHeld.ToString()); - - AddHtmlLocalized(40, 108, 260, 20, 1062509, 0x7FFF); // Shop Name: - AddLabel(140, 106, 0x66D, vendor.ShopName); - - if (vendor is RentedVendor rentedVendor) - { - rentedVendor.ComputeRentalExpireDelay(out int days, out int hours); - - AddLabel(38, 132, 0x480, - $"Location rental will expire in {days} day{(days != 1 ? "s" : "")} and {hours} hour{(hours != 1 ? "s" : "")}."); - } - - AddButton(390, 24, 0x15E1, 0x15E5, 1); - AddHtmlLocalized(408, 21, 120, 20, 1019068, 0x7FFF); // See goods - - AddButton(390, 44, 0x15E1, 0x15E5, 2); - AddHtmlLocalized(408, 41, 120, 20, 1019069, 0x7FFF); // Customize - - AddButton(390, 64, 0x15E1, 0x15E5, 3); - AddHtmlLocalized(408, 61, 120, 20, 1062434, 0x7FFF); // Rename Shop - - AddButton(390, 84, 0x15E1, 0x15E5, 4); - AddHtmlLocalized(408, 81, 120, 20, 3006217, 0x7FFF); // Rename Vendor - - AddButton(390, 104, 0x15E1, 0x15E5, 5); - AddHtmlLocalized(408, 101, 120, 20, 3006123, 0x7FFF); // Open Paperdoll - - AddButton(390, 124, 0x15E1, 0x15E5, 6); - AddLabel(408, 121, 0x480, "Collect Gold"); - - AddButton(390, 144, 0x15E1, 0x15E5, 7); - AddLabel(408, 141, 0x480, "Dismiss Vendor"); - - AddButton(390, 162, 0x15E1, 0x15E5, 0); - AddHtmlLocalized(408, 161, 120, 20, 1011012, 0x7FFF); // CANCEL - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - Mobile from = sender.Mobile; - - if (info.ButtonID == 1 || info.ButtonID == 2) // See goods or Customize - m_Vendor.CheckTeleport(from); - - if (!m_Vendor.CanInteractWith(from, true)) - return; - - switch (info.ButtonID) - { - case 1: // See goods - { - m_Vendor.OpenBackpack(from); - - break; - } - case 2: // Customize - { - from.SendGump(new NewPlayerVendorCustomizeGump(m_Vendor)); - - break; - } - case 3: // Rename Shop - { - m_Vendor.RenameShop(from); - - break; - } - case 4: // Rename Vendor - { - m_Vendor.Rename(from); - - break; - } - case 5: // Open Paperdoll - { - m_Vendor.DisplayPaperdollTo(from); - - break; - } - case 6: // Collect Gold - { - m_Vendor.CollectGold(from); - - break; - } - case 7: // Dismiss Vendor - { - m_Vendor.Dismiss(from); - - break; - } - } - } - } - - public class PlayerVendorCustomizeGump : Gump - { - private static readonly CustomCategory[] Categories = - { - new CustomCategory(Layer.InnerTorso, 1011357, true, new[] - { - // Upper Torso - new CustomItem(typeof(Shirt), 1011359, 5399), - new CustomItem(typeof(FancyShirt), 1011360, 7933), - new CustomItem(typeof(PlainDress), 1011363, 7937), - new CustomItem(typeof(FancyDress), 1011364, 7935), - new CustomItem(typeof(Robe), 1011365, 7939) - }), - - new CustomCategory(Layer.MiddleTorso, 1011371, true, new[] - { - // Over chest - new CustomItem(typeof(Doublet), 1011358, 8059), - new CustomItem(typeof(Tunic), 1011361, 8097), - new CustomItem(typeof(JesterSuit), 1011366, 8095), - new CustomItem(typeof(BodySash), 1011372, 5441), - new CustomItem(typeof(Surcoat), 1011362, 8189), - new CustomItem(typeof(HalfApron), 1011373, 5435), - new CustomItem(typeof(FullApron), 1011374, 5437) - }), - - new CustomCategory(Layer.Shoes, 1011388, true, new[] - { - // Footwear - new CustomItem(typeof(Sandals), 1011389, 5901), - new CustomItem(typeof(Shoes), 1011390, 5904), - new CustomItem(typeof(Boots), 1011391, 5899), - new CustomItem(typeof(ThighBoots), 1011392, 5906) - }), - - new CustomCategory(Layer.Helm, 1011375, true, new[] - { - // Hats - new CustomItem(typeof(SkullCap), 1011376, 5444), - new CustomItem(typeof(Bandana), 1011377, 5440), - new CustomItem(typeof(FloppyHat), 1011378, 5907), - new CustomItem(typeof(WideBrimHat), 1011379, 5908), - new CustomItem(typeof(Cap), 1011380, 5909), - new CustomItem(typeof(TallStrawHat), 1011382, 5910) - }), - - new CustomCategory(Layer.Helm, 1015319, true, new[] - { - // More Hats - new CustomItem(typeof(StrawHat), 1011382, 5911), - new CustomItem(typeof(WizardsHat), 1011383, 5912), - new CustomItem(typeof(Bonnet), 1011384, 5913), - new CustomItem(typeof(FeatheredHat), 1011385, 5914), - new CustomItem(typeof(TricorneHat), 1011386, 5915), - new CustomItem(typeof(JesterHat), 1011387, 5916) - }), - - new CustomCategory(Layer.Pants, 1011367, true, new[] - { - // Lower Torso - new CustomItem(typeof(LongPants), 1011368, 5433), - new CustomItem(typeof(Kilt), 1011369, 5431), - new CustomItem(typeof(Skirt), 1011370, 5398) - }), - - new CustomCategory(Layer.Cloak, 1011393, true, new[] - { - // Back - new CustomItem(typeof(Cloak), 1011394, 5397) - }), - - new CustomCategory(Layer.Hair, 1011395, true, new[] - { - // Hair - new CustomItem(0x203B, 1011052), - new CustomItem(0x203C, 1011053), - new CustomItem(0x203D, 1011054), - new CustomItem(0x2044, 1011055), - new CustomItem(0x2045, 1011047), - new CustomItem(0x204A, 1011050), - new CustomItem(0x2047, 1011396), - new CustomItem(0x2048, 1011048), - new CustomItem(0x2049, 1011049) - }), - - new CustomCategory(Layer.FacialHair, 1015320, true, new[] - { - // Facial Hair - new CustomItem(0x2041, 1011062), - new CustomItem(0x203F, 1011060), - new CustomItem(0x204B, 1015321, true), - new CustomItem(0x203E, 1011061), - new CustomItem(0x204C, 1015322, true), - new CustomItem(0x2040, 1015323), - new CustomItem(0x204D, 1011401) - }), - - new CustomCategory(Layer.FirstValid, 1011397, false, new[] - { - // Held items - new CustomItem(typeof(FishingPole), 1011406, 3520), - new CustomItem(typeof(Pickaxe), 1011407, 3717), - new CustomItem(typeof(Pitchfork), 1011408, 3720), - new CustomItem(typeof(Cleaver), 1015324, 3778), - new CustomItem(typeof(Mace), 1011409, 3933), - new CustomItem(typeof(Torch), 1011410, 3940), - new CustomItem(typeof(Hammer), 1011411, 4020), - new CustomItem(typeof(Longsword), 1011412, 3936), - new CustomItem(typeof(GnarledStaff), 1011413, 5113) - }), - - new CustomCategory(Layer.FirstValid, 1015325, false, new[] - { - // More held items - new CustomItem(typeof(Crossbow), 1011414, 3920), - new CustomItem(typeof(WarMace), 1011415, 5126), - new CustomItem(typeof(TwoHandedAxe), 1011416, 5186), - new CustomItem(typeof(Spear), 1011417, 3939), - new CustomItem(typeof(Katana), 1011418, 5118), - new CustomItem(typeof(Spellbook), 1011419, 3834) - }) - }; - - private readonly Mobile m_Vendor; - - public PlayerVendorCustomizeGump(Mobile v, Mobile from) : base(30, 40) - { - m_Vendor = v; - int x, y; - - from.CloseGump(); - - AddPage(0); - AddBackground(0, 0, 585, 393, 5054); - AddBackground(195, 36, 387, 275, 3000); - AddHtmlLocalized(10, 10, 565, 18, 1011356); //
VENDOR CUSTOMIZATION MENU
- AddHtmlLocalized(60, 355, 150, 18, 1011036); // OKAY - AddButton(25, 355, 4005, 4007, 1); - AddHtmlLocalized(320, 355, 150, 18, 1011012); // CANCEL - AddButton(285, 355, 4005, 4007, 0); - - y = 35; - for (int i = 0; i < Categories.Length; i++) - { - CustomCategory cat = Categories[i]; - AddHtmlLocalized(5, y, 150, 25, cat.LocNumber, true); - AddButton(155, y, 4005, 4007, 0, GumpButtonType.Page, i + 1); - y += 25; - } - - for (int i = 0; i < Categories.Length; i++) - { - CustomCategory cat = Categories[i]; - AddPage(i + 1); - - for (int c = 0; c < cat.Entries.Length; c++) - { - CustomItem entry = cat.Entries[c]; - x = 198 + c % 3 * 129; - y = 38 + c / 3 * 67; - - AddHtmlLocalized(x, y, 100, entry.LongText ? 36 : 18, entry.LocNumber); - - if (entry.ArtNumber != 0) - AddItem(x + 20, y + 25, entry.ArtNumber); - - AddRadio(x, y + (entry.LongText ? 40 : 20), 210, 211, false, (c << 8) + i); - } - - if (cat.CanDye) - { - AddHtmlLocalized(327, 239, 100, 18, 1011402); // Color - AddRadio(327, 259, 210, 211, false, 100 + i); - } - - AddHtmlLocalized(456, 239, 100, 18, 1011403); // Remove - AddRadio(456, 259, 210, 211, false, 200 + i); - } - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (m_Vendor.Deleted) - return; - - Mobile from = state.Mobile; - - if (m_Vendor is PlayerVendor vendor && !vendor.CanInteractWith(from, true)) - return; - - if (m_Vendor is PlayerBarkeeper barkeeper && !barkeeper.IsOwner(from)) - return; - - if (info.ButtonID == 0) - { - if (m_Vendor is PlayerVendor) // do nothing for barkeeps - { - m_Vendor.Direction = m_Vendor.GetDirectionTo(from); - m_Vendor.Animate(32, 5, 1, true, false, 0); // bow - m_Vendor.SayTo(from, 1043310 + Utility.Random(12)); // a little random speech - } - } - else if (info.ButtonID == 1 && info.Switches.Length > 0) - { - int cnum = info.Switches[0]; - int cat = cnum % 256; - int ent = cnum >> 8; - - if (cat < Categories.Length && cat >= 0) - { - if (ent < Categories[cat].Entries.Length && ent >= 0) - { - Item item = m_Vendor.FindItemOnLayer(Categories[cat].Layer); - - item?.Delete(); - - List items = m_Vendor.Items; - - for (int i = 0; item == null && i < items.Count; ++i) - { - Item checkitem = items[i]; - Type type = checkitem.GetType(); - - for (int j = 0; item == null && j < Categories[cat].Entries.Length; ++j) - if (type == Categories[cat].Entries[j].Type) - item = checkitem; - } - - item?.Delete(); - - if (Categories[cat].Layer == Layer.FacialHair) - { - if (m_Vendor.Female) - { - from.SendLocalizedMessage(1010639); // You cannot place facial hair on a woman! - } - else - { - int hue = m_Vendor.FacialHairHue; - - m_Vendor.FacialHairItemID = 0; - m_Vendor.ProcessDelta(); // invalidate item ID for clients - - m_Vendor.FacialHairItemID = Categories[cat].Entries[ent].ItemID; - m_Vendor.FacialHairHue = hue; - } - } - else if (Categories[cat].Layer == Layer.Hair) - { - int hue = m_Vendor.HairHue; - - m_Vendor.HairItemID = 0; - m_Vendor.ProcessDelta(); // invalidate item ID for clients - - m_Vendor.HairItemID = Categories[cat].Entries[ent].ItemID; - m_Vendor.HairHue = hue; - } - else - { - item = Categories[cat].Entries[ent].Create(); - - if (item != null) - { - item.Layer = Categories[cat].Layer; - - if (!m_Vendor.EquipItem(item)) - item.Delete(); - } - } - - from.SendGump(new PlayerVendorCustomizeGump(m_Vendor, from)); - } - } - else - { - cat -= 100; - - if (cat < 100) - { - if (cat < Categories.Length && cat >= 0) - { - CustomCategory category = Categories[cat]; - - if (category.Layer == Layer.Hair) - { - new PVHairHuePicker(false, m_Vendor, from).SendTo(state); - } - else if (category.Layer == Layer.FacialHair) - { - new PVHairHuePicker(true, m_Vendor, from).SendTo(state); - } - else - { - Item item = null; - - List items = m_Vendor.Items; - - for (int i = 0; item == null && i < items.Count; ++i) - { - Item checkitem = items[i]; - Type type = checkitem.GetType(); - - for (int j = 0; item == null && j < category.Entries.Length; ++j) - if (type == category.Entries[j].Type) - item = checkitem; - } - - if (item != null) - new PVHuePicker(item, m_Vendor, from).SendTo(state); - } - } - } - else - { - cat -= 100; - - if (cat < Categories.Length) - { - CustomCategory category = Categories[cat]; - - if (category.Layer == Layer.Hair) - { - m_Vendor.HairItemID = 0; - } - else if (category.Layer == Layer.FacialHair) - { - m_Vendor.FacialHairItemID = 0; - } - else - { - Item item = null; - - List items = m_Vendor.Items; - - for (int i = 0; item == null && i < items.Count; ++i) - { - Item checkitem = items[i]; - Type type = checkitem.GetType(); - - for (int j = 0; item == null && j < category.Entries.Length; ++j) - if (type == category.Entries[j].Type) - item = checkitem; - } - - item?.Delete(); - } - - from.SendGump(new PlayerVendorCustomizeGump(m_Vendor, from)); - } - } - } - } - } - - private class CustomItem - { - public CustomItem(int itemID, int loc, bool longText = false) : this(null, itemID, loc, 0, longText) - { - } - - public CustomItem(Type type, int loc, int art = 0) : this(type, 0, loc, art) - { - } - - public CustomItem(Type type, int itemID = 0, int loc = 0, int art = 0, bool longText = false) - { - Type = type; - ItemID = itemID; - LocNumber = loc; - ArtNumber = art; - LongText = longText; - } - - public Type Type { get; } - - public int ItemID { get; } - - public int LocNumber { get; } - - public int ArtNumber { get; } - - public bool LongText { get; } - - public Item Create() - { - if (Type == null) - return null; - - Item i = null; - - try - { - ConstructorInfo ctor = Type.GetConstructor(Array.Empty()); - if (ctor != null) - i = ctor.Invoke(null) as Item; - } - catch - { - // ignored - } - - return i; - } - } - - private class CustomCategory - { - public CustomCategory(Layer layer, int loc, bool canDye, CustomItem[] items) - { - Entries = items; - CanDye = canDye; - Layer = layer; - LocNumber = loc; - } - - public bool CanDye { get; } - - public CustomItem[] Entries { get; } - - public Layer Layer { get; } - - public int LocNumber { get; } - } - - private class PVHuePicker : HuePicker - { - private readonly Item m_Item; - private readonly Mobile m_Mob; - private readonly Mobile m_Vendor; - - public PVHuePicker(Item item, Mobile v, Mobile from) : base(item.ItemID) - { - m_Item = item; - m_Vendor = v; - m_Mob = from; - } - - public override void OnResponse(int hue) - { - if (m_Item.Deleted) - return; - - if (m_Vendor is PlayerVendor vendor && !vendor.CanInteractWith(m_Mob, true)) - return; - - if (m_Vendor is PlayerBarkeeper barkeeper && !barkeeper.IsOwner(m_Mob)) - return; - - m_Item.Hue = hue; - m_Mob.SendGump(new PlayerVendorCustomizeGump(m_Vendor, m_Mob)); - } - } - - private class PVHairHuePicker : HuePicker - { - private readonly bool m_FacialHair; - private readonly Mobile m_Mob; - private readonly Mobile m_Vendor; - - public PVHairHuePicker(bool facialHair, Mobile v, Mobile from) : base(0xFAB) - { - m_FacialHair = facialHair; - m_Vendor = v; - m_Mob = from; - } - - public override void OnResponse(int hue) - { - if (m_Vendor.Deleted) - return; - - if (m_Vendor is PlayerVendor vendor && !vendor.CanInteractWith(m_Mob, true)) - return; - - if (m_Vendor is PlayerBarkeeper barkeeper && !barkeeper.IsOwner(m_Mob)) - return; - - if (m_FacialHair) - m_Vendor.FacialHairHue = hue; - else - m_Vendor.HairHue = hue; - - m_Mob.SendGump(new PlayerVendorCustomizeGump(m_Vendor, m_Mob)); - } - } - } - - public class NewPlayerVendorCustomizeGump : Gump - { - private static readonly HairOrBeard[] m_HairStyles = - { - new HairOrBeard(0x203B, 1011052), // Short - new HairOrBeard(0x203C, 1011053), // Long - new HairOrBeard(0x203D, 1011054), // Ponytail - new HairOrBeard(0x2044, 1011055), // Mohawk - new HairOrBeard(0x2045, 1011047), // Pageboy - new HairOrBeard(0x204A, 1011050), // Topknot - new HairOrBeard(0x2047, 1011396), // Curly - new HairOrBeard(0x2048, 1011048), // Receding - new HairOrBeard(0x2049, 1011049) // 2-tails - }; - - private static readonly HairOrBeard[] m_BeardStyles = - { - new HairOrBeard(0x2041, 1011062), // Mustache - new HairOrBeard(0x203F, 1011060), // Short beard - new HairOrBeard(0x204B, 1015321), // Short Beard & Moustache - new HairOrBeard(0x203E, 1011061), // Long beard - new HairOrBeard(0x204C, 1015322), // Long Beard & Moustache - new HairOrBeard(0x2040, 1015323), // Goatee - new HairOrBeard(0x204D, 1011401) // Vandyke - }; - - private readonly PlayerVendor m_Vendor; - - public NewPlayerVendorCustomizeGump(PlayerVendor vendor) : base(50, 50) - { - m_Vendor = vendor; - - AddBackground(0, 0, 370, 370, 0x13BE); - - AddImageTiled(10, 10, 350, 20, 0xA40); - AddImageTiled(10, 40, 350, 20, 0xA40); - AddImageTiled(10, 70, 350, 260, 0xA40); - AddImageTiled(10, 340, 350, 20, 0xA40); - - AddAlphaRegion(10, 10, 350, 350); - - AddHtmlLocalized(10, 12, 350, 18, 1011356, 0x7FFF); //
VENDOR CUSTOMIZATION MENU
- - AddHtmlLocalized(10, 42, 150, 18, 1062459, 0x421F); //
HAIR
- - for (int i = 0; i < m_HairStyles.Length; i++) - { - HairOrBeard hair = m_HairStyles[i]; - - AddButton(10, 70 + i * 20, 0xFA5, 0xFA7, 0x100 | i); - AddHtmlLocalized(45, 72 + i * 20, 110, 18, hair.Name, 0x7FFF); - } - - AddButton(10, 70 + m_HairStyles.Length * 20, 0xFB1, 0xFB3, 2); - AddHtmlLocalized(45, 72 + m_HairStyles.Length * 20, 110, 18, 1011403, 0x7FFF); // Remove - - AddButton(10, 70 + (m_HairStyles.Length + 1) * 20, 0xFA5, 0xFA7, 3); - AddHtmlLocalized(45, 72 + (m_HairStyles.Length + 1) * 20, 110, 18, 1011402, 0x7FFF); // Color - - if (vendor.Female) - { - AddButton(160, 290, 0xFA5, 0xFA7, 1); - AddHtmlLocalized(195, 292, 160, 18, 1015327, 0x7FFF); // Male - - AddHtmlLocalized(195, 312, 160, 18, 1015328, 0x421F); // Female - } - else - { - AddHtmlLocalized(160, 42, 210, 18, 1062460, 0x421F); //
BEARD
- - for (int i = 0; i < m_BeardStyles.Length; i++) - { - HairOrBeard beard = m_BeardStyles[i]; - - AddButton(160, 70 + i * 20, 0xFA5, 0xFA7, 0x200 | i); - AddHtmlLocalized(195, 72 + i * 20, 160, 18, beard.Name, 0x7FFF); - } - - AddButton(160, 70 + m_BeardStyles.Length * 20, 0xFB1, 0xFB3, 4); - AddHtmlLocalized(195, 72 + m_BeardStyles.Length * 20, 160, 18, 1011403, 0x7FFF); // Remove - - AddButton(160, 70 + (m_BeardStyles.Length + 1) * 20, 0xFA5, 0xFA7, 5); - AddHtmlLocalized(195, 72 + (m_BeardStyles.Length + 1) * 20, 160, 18, 1011402, 0x7FFF); // Color - - AddHtmlLocalized(195, 292, 160, 18, 1015327, 0x421F); // Male - - AddButton(160, 310, 0xFA5, 0xFA7, 1); - AddHtmlLocalized(195, 312, 160, 18, 1015328, 0x7FFF); // Female - } - - AddButton(10, 340, 0xFA5, 0xFA7, 0); - AddHtmlLocalized(45, 342, 305, 18, 1060675, 0x7FFF); // CLOSE - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - Mobile from = sender.Mobile; - - if (!m_Vendor.CanInteractWith(from, true)) - return; - - switch (info.ButtonID) - { - case 0: // CLOSE - { - m_Vendor.Direction = m_Vendor.GetDirectionTo(from); - m_Vendor.Animate(32, 5, 1, true, false, 0); // bow - m_Vendor.SayTo(from, 1043310 + Utility.Random(12)); // a little random speech - - break; - } - case 1: // Female/Male - { - if (m_Vendor.Female) - { - m_Vendor.BodyValue = 400; - m_Vendor.Female = false; - } - else - { - m_Vendor.BodyValue = 401; - m_Vendor.Female = true; - - m_Vendor.FacialHairItemID = 0; - } - - from.SendGump(new NewPlayerVendorCustomizeGump(m_Vendor)); - - break; - } - case 2: // Remove hair - { - m_Vendor.HairItemID = 0; - - from.SendGump(new NewPlayerVendorCustomizeGump(m_Vendor)); - - break; - } - case 3: // Color hair - { - if (m_Vendor.HairItemID > 0) - new PVHuePicker(m_Vendor, false, from).SendTo(from.NetState); - else - from.SendGump(new NewPlayerVendorCustomizeGump(m_Vendor)); - - break; - } - case 4: // Remove beard - { - m_Vendor.FacialHairItemID = 0; - - from.SendGump(new NewPlayerVendorCustomizeGump(m_Vendor)); - - break; - } - case 5: // Color beard - { - if (m_Vendor.FacialHairItemID > 0) - new PVHuePicker(m_Vendor, true, from).SendTo(from.NetState); - else - from.SendGump(new NewPlayerVendorCustomizeGump(m_Vendor)); - - break; - } - default: - { - int hairhue; - - if ((info.ButtonID & 0x100) != 0) // Hair style selected - { - int index = info.ButtonID & 0xFF; - - if (index >= m_HairStyles.Length) - return; - - HairOrBeard hairStyle = m_HairStyles[index]; - - hairhue = m_Vendor.HairHue; - - m_Vendor.HairItemID = 0; - m_Vendor.ProcessDelta(); - - m_Vendor.HairItemID = hairStyle.ItemID; - - m_Vendor.HairHue = hairhue; - - from.SendGump(new NewPlayerVendorCustomizeGump(m_Vendor)); - } - else if ((info.ButtonID & 0x200) != 0) // Beard style selected - { - if (m_Vendor.Female) - return; - - int index = info.ButtonID & 0xFF; - - if (index >= m_BeardStyles.Length) - return; - - HairOrBeard beardStyle = m_BeardStyles[index]; - - hairhue = m_Vendor.FacialHairHue; - - m_Vendor.FacialHairItemID = 0; - m_Vendor.ProcessDelta(); - - m_Vendor.FacialHairItemID = beardStyle.ItemID; - - m_Vendor.FacialHairHue = hairhue; - - from.SendGump(new NewPlayerVendorCustomizeGump(m_Vendor)); - } - - break; - } - } - } - - private class HairOrBeard - { - public HairOrBeard(int itemID, int name) - { - ItemID = itemID; - Name = name; - } - - public int ItemID { get; } - - public int Name { get; } - } - - private class PVHuePicker : HuePicker - { - private readonly bool m_FacialHair; - private readonly Mobile m_From; - private readonly PlayerVendor m_Vendor; - - public PVHuePicker(PlayerVendor vendor, bool facialHair, Mobile from) : base(0xFAB) - { - m_Vendor = vendor; - m_FacialHair = facialHair; - m_From = from; - } - - public override void OnResponse(int hue) - { - if (!m_Vendor.CanInteractWith(m_From, true)) - return; - - if (m_FacialHair) - m_Vendor.FacialHairHue = hue; - else - m_Vendor.HairHue = hue; - - m_From.SendGump(new NewPlayerVendorCustomizeGump(m_Vendor)); - } - } - } -} +using System; +using Server.HuePickers; +using Server.Items; +using Server.Mobiles; +using Server.Network; + +namespace Server.Gumps +{ + public class PlayerVendorBuyGump : Gump + { + private readonly PlayerVendor m_Vendor; + private readonly VendorItem m_VI; + + public PlayerVendorBuyGump(PlayerVendor vendor, VendorItem vi) : base(100, 200) + { + m_Vendor = vendor; + m_VI = vi; + + AddBackground(100, 10, 300, 150, 5054); + + AddHtmlLocalized(125, 20, 250, 24, 1019070); // You have agreed to purchase: + + if (!string.IsNullOrEmpty(vi.Description)) + AddLabel(125, 45, 0, vi.Description); + else + AddHtmlLocalized(125, 45, 250, 24, 1019072); // an item without a description + + AddHtmlLocalized(125, 70, 250, 24, 1019071); // for the amount of: + AddLabel(125, 95, 0, vi.Price.ToString()); + + AddButton(250, 130, 4005, 4007, 0); + AddHtmlLocalized(282, 130, 100, 24, 1011012); // CANCEL + + AddButton(120, 130, 4005, 4007, 1); + AddHtmlLocalized(152, 130, 100, 24, 1011036); // OKAY + } + + public override void OnResponse(NetState state, RelayInfo info) + { + var from = state.Mobile; + + if (!m_Vendor.CanInteractWith(from, false)) + return; + + if (m_Vendor.IsOwner(from)) + { + m_Vendor.SayTo(from, 503212); // You own this shop, just take what you want. + return; + } + + if (info.ButtonID == 1) + { + m_Vendor.Say(from.Name); + + if (!m_VI.Valid || !m_VI.Item.IsChildOf(m_Vendor.Backpack)) + { + m_Vendor.SayTo(from, 503216); // You can't buy that. + return; + } + + var totalGold = 0; + + if (from.Backpack != null) + totalGold += from.Backpack.GetAmount(typeof(Gold)); + + totalGold += Banker.GetBalance(from); + + if (totalGold < m_VI.Price) + { + m_Vendor.SayTo(from, 503205); // You cannot afford this item. + } + else if (!from.PlaceInBackpack(m_VI.Item)) + { + m_Vendor.SayTo(from, 503204); // You do not have room in your backpack for this. + } + else + { + var leftPrice = m_VI.Price; + + if (from.Backpack != null) + leftPrice -= from.Backpack.ConsumeUpTo(typeof(Gold), leftPrice); + + if (leftPrice > 0) + Banker.Withdraw(from, leftPrice); + + m_Vendor.HoldGold += m_VI.Price; + + from.SendLocalizedMessage(503201); // You take the item. + } + } + else + { + from.SendLocalizedMessage(503207); // Cancelled purchase. + } + } + } + + public class PlayerVendorOwnerGump : Gump + { + private readonly PlayerVendor m_Vendor; + + public PlayerVendorOwnerGump(PlayerVendor vendor) : base(50, 200) + { + m_Vendor = vendor; + + var perDay = m_Vendor.ChargePerDay; + + AddPage(0); + AddBackground(25, 10, 530, 140, 5054); + + AddHtmlLocalized(425, 25, 120, 20, 1019068); // See goods + AddButton(390, 25, 4005, 4007, 1); + AddHtmlLocalized(425, 48, 120, 20, 1019069); // Customize + AddButton(390, 48, 4005, 4007, 2); + AddHtmlLocalized(425, 72, 120, 20, 1011012); // CANCEL + AddButton(390, 71, 4005, 4007, 0); + + AddHtmlLocalized(40, 72, 260, 20, 1038321); // Gold held for you: + AddLabel(300, 72, 0, m_Vendor.HoldGold.ToString()); + AddHtmlLocalized(40, 96, 260, 20, 1038322); // Gold held in my account: + AddLabel(300, 96, 0, m_Vendor.BankAccount.ToString()); + + // AddHtmlLocalized( 40, 120, 260, 20, 1038324, false, false ); // My charge per day is: + // Localization has changed, we must use a string here + AddHtml(40, 120, 260, 20, "My charge per day is:"); + AddLabel(300, 120, 0, perDay.ToString()); + + var days = (m_Vendor.HoldGold + m_Vendor.BankAccount) / (double)perDay; + + AddHtmlLocalized(40, 25, 260, 20, 1038318); // Amount of days I can work: + AddLabel(300, 25, 0, ((int)days).ToString()); + AddHtmlLocalized(40, 48, 260, 20, 1038319); // Earth days: + AddLabel(300, 48, 0, ((int)(days / 12.0)).ToString()); + } + + public override void OnResponse(NetState state, RelayInfo info) + { + var from = state.Mobile; + + if (!m_Vendor.CanInteractWith(from, true)) + return; + + switch (info.ButtonID) + { + case 1: + { + m_Vendor.OpenBackpack(from); + + break; + } + case 2: + { + from.SendGump(new PlayerVendorCustomizeGump(m_Vendor, from)); + + break; + } + } + } + } + + public class NewPlayerVendorOwnerGump : Gump + { + private readonly PlayerVendor m_Vendor; + + public NewPlayerVendorOwnerGump(PlayerVendor vendor) : base(50, 200) + { + m_Vendor = vendor; + + var perRealWorldDay = vendor.ChargePerRealWorldDay; + var goldHeld = vendor.HoldGold; + + AddBackground(25, 10, 530, 180, 0x13BE); + + AddImageTiled(35, 20, 510, 160, 0xA40); + AddAlphaRegion(35, 20, 510, 160); + + AddImage(10, 0, 0x28DC); + AddImage(537, 175, 0x28DC); + AddImage(10, 175, 0x28DC); + AddImage(537, 0, 0x28DC); + + if (goldHeld < perRealWorldDay) + { + var goldNeeded = perRealWorldDay - goldHeld; + + AddHtmlLocalized(40, 35, 260, 20, 1038320, 0x7FFF); // Gold needed for 1 day of vendor salary: + AddLabel(300, 35, 0x1F, goldNeeded.ToString()); + } + else + { + var days = goldHeld / perRealWorldDay; + + AddHtmlLocalized(40, 35, 260, 20, 1038318, 0x7FFF); // # of days Vendor salary is paid for: + AddLabel(300, 35, 0x480, days.ToString()); + } + + AddHtmlLocalized(40, 58, 260, 20, 1038324, 0x7FFF); // My charge per real world day is: + AddLabel(300, 58, 0x480, perRealWorldDay.ToString()); + + AddHtmlLocalized(40, 82, 260, 20, 1038322, 0x7FFF); // Gold held in my account: + AddLabel(300, 82, 0x480, goldHeld.ToString()); + + AddHtmlLocalized(40, 108, 260, 20, 1062509, 0x7FFF); // Shop Name: + AddLabel(140, 106, 0x66D, vendor.ShopName); + + if (vendor is RentedVendor rentedVendor) + { + rentedVendor.ComputeRentalExpireDelay(out var days, out var hours); + + AddLabel( + 38, + 132, + 0x480, + $"Location rental will expire in {days} day{(days != 1 ? "s" : "")} and {hours} hour{(hours != 1 ? "s" : "")}." + ); + } + + AddButton(390, 24, 0x15E1, 0x15E5, 1); + AddHtmlLocalized(408, 21, 120, 20, 1019068, 0x7FFF); // See goods + + AddButton(390, 44, 0x15E1, 0x15E5, 2); + AddHtmlLocalized(408, 41, 120, 20, 1019069, 0x7FFF); // Customize + + AddButton(390, 64, 0x15E1, 0x15E5, 3); + AddHtmlLocalized(408, 61, 120, 20, 1062434, 0x7FFF); // Rename Shop + + AddButton(390, 84, 0x15E1, 0x15E5, 4); + AddHtmlLocalized(408, 81, 120, 20, 3006217, 0x7FFF); // Rename Vendor + + AddButton(390, 104, 0x15E1, 0x15E5, 5); + AddHtmlLocalized(408, 101, 120, 20, 3006123, 0x7FFF); // Open Paperdoll + + AddButton(390, 124, 0x15E1, 0x15E5, 6); + AddLabel(408, 121, 0x480, "Collect Gold"); + + AddButton(390, 144, 0x15E1, 0x15E5, 7); + AddLabel(408, 141, 0x480, "Dismiss Vendor"); + + AddButton(390, 162, 0x15E1, 0x15E5, 0); + AddHtmlLocalized(408, 161, 120, 20, 1011012, 0x7FFF); // CANCEL + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var from = sender.Mobile; + + if (info.ButtonID == 1 || info.ButtonID == 2) // See goods or Customize + m_Vendor.CheckTeleport(from); + + if (!m_Vendor.CanInteractWith(from, true)) + return; + + switch (info.ButtonID) + { + case 1: // See goods + { + m_Vendor.OpenBackpack(from); + + break; + } + case 2: // Customize + { + from.SendGump(new NewPlayerVendorCustomizeGump(m_Vendor)); + + break; + } + case 3: // Rename Shop + { + m_Vendor.RenameShop(from); + + break; + } + case 4: // Rename Vendor + { + m_Vendor.Rename(from); + + break; + } + case 5: // Open Paperdoll + { + m_Vendor.DisplayPaperdollTo(from); + + break; + } + case 6: // Collect Gold + { + m_Vendor.CollectGold(from); + + break; + } + case 7: // Dismiss Vendor + { + m_Vendor.Dismiss(from); + + break; + } + } + } + } + + public class PlayerVendorCustomizeGump : Gump + { + private static readonly CustomCategory[] Categories = + { + new CustomCategory( + Layer.InnerTorso, + 1011357, + true, + new[] + { + // Upper Torso + new CustomItem(typeof(Shirt), 1011359, 5399), + new CustomItem(typeof(FancyShirt), 1011360, 7933), + new CustomItem(typeof(PlainDress), 1011363, 7937), + new CustomItem(typeof(FancyDress), 1011364, 7935), + new CustomItem(typeof(Robe), 1011365, 7939) + } + ), + + new CustomCategory( + Layer.MiddleTorso, + 1011371, + true, + new[] + { + // Over chest + new CustomItem(typeof(Doublet), 1011358, 8059), + new CustomItem(typeof(Tunic), 1011361, 8097), + new CustomItem(typeof(JesterSuit), 1011366, 8095), + new CustomItem(typeof(BodySash), 1011372, 5441), + new CustomItem(typeof(Surcoat), 1011362, 8189), + new CustomItem(typeof(HalfApron), 1011373, 5435), + new CustomItem(typeof(FullApron), 1011374, 5437) + } + ), + + new CustomCategory( + Layer.Shoes, + 1011388, + true, + new[] + { + // Footwear + new CustomItem(typeof(Sandals), 1011389, 5901), + new CustomItem(typeof(Shoes), 1011390, 5904), + new CustomItem(typeof(Boots), 1011391, 5899), + new CustomItem(typeof(ThighBoots), 1011392, 5906) + } + ), + + new CustomCategory( + Layer.Helm, + 1011375, + true, + new[] + { + // Hats + new CustomItem(typeof(SkullCap), 1011376, 5444), + new CustomItem(typeof(Bandana), 1011377, 5440), + new CustomItem(typeof(FloppyHat), 1011378, 5907), + new CustomItem(typeof(WideBrimHat), 1011379, 5908), + new CustomItem(typeof(Cap), 1011380, 5909), + new CustomItem(typeof(TallStrawHat), 1011382, 5910) + } + ), + + new CustomCategory( + Layer.Helm, + 1015319, + true, + new[] + { + // More Hats + new CustomItem(typeof(StrawHat), 1011382, 5911), + new CustomItem(typeof(WizardsHat), 1011383, 5912), + new CustomItem(typeof(Bonnet), 1011384, 5913), + new CustomItem(typeof(FeatheredHat), 1011385, 5914), + new CustomItem(typeof(TricorneHat), 1011386, 5915), + new CustomItem(typeof(JesterHat), 1011387, 5916) + } + ), + + new CustomCategory( + Layer.Pants, + 1011367, + true, + new[] + { + // Lower Torso + new CustomItem(typeof(LongPants), 1011368, 5433), + new CustomItem(typeof(Kilt), 1011369, 5431), + new CustomItem(typeof(Skirt), 1011370, 5398) + } + ), + + new CustomCategory( + Layer.Cloak, + 1011393, + true, + new[] + { + // Back + new CustomItem(typeof(Cloak), 1011394, 5397) + } + ), + + new CustomCategory( + Layer.Hair, + 1011395, + true, + new[] + { + // Hair + new CustomItem(0x203B, 1011052), + new CustomItem(0x203C, 1011053), + new CustomItem(0x203D, 1011054), + new CustomItem(0x2044, 1011055), + new CustomItem(0x2045, 1011047), + new CustomItem(0x204A, 1011050), + new CustomItem(0x2047, 1011396), + new CustomItem(0x2048, 1011048), + new CustomItem(0x2049, 1011049) + } + ), + + new CustomCategory( + Layer.FacialHair, + 1015320, + true, + new[] + { + // Facial Hair + new CustomItem(0x2041, 1011062), + new CustomItem(0x203F, 1011060), + new CustomItem(0x204B, 1015321, true), + new CustomItem(0x203E, 1011061), + new CustomItem(0x204C, 1015322, true), + new CustomItem(0x2040, 1015323), + new CustomItem(0x204D, 1011401) + } + ), + + new CustomCategory( + Layer.FirstValid, + 1011397, + false, + new[] + { + // Held items + new CustomItem(typeof(FishingPole), 1011406, 3520), + new CustomItem(typeof(Pickaxe), 1011407, 3717), + new CustomItem(typeof(Pitchfork), 1011408, 3720), + new CustomItem(typeof(Cleaver), 1015324, 3778), + new CustomItem(typeof(Mace), 1011409, 3933), + new CustomItem(typeof(Torch), 1011410, 3940), + new CustomItem(typeof(Hammer), 1011411, 4020), + new CustomItem(typeof(Longsword), 1011412, 3936), + new CustomItem(typeof(GnarledStaff), 1011413, 5113) + } + ), + + new CustomCategory( + Layer.FirstValid, + 1015325, + false, + new[] + { + // More held items + new CustomItem(typeof(Crossbow), 1011414, 3920), + new CustomItem(typeof(WarMace), 1011415, 5126), + new CustomItem(typeof(TwoHandedAxe), 1011416, 5186), + new CustomItem(typeof(Spear), 1011417, 3939), + new CustomItem(typeof(Katana), 1011418, 5118), + new CustomItem(typeof(Spellbook), 1011419, 3834) + } + ) + }; + + private readonly Mobile m_Vendor; + + public PlayerVendorCustomizeGump(Mobile v, Mobile from) : base(30, 40) + { + m_Vendor = v; + int x, y; + + from.CloseGump(); + + AddPage(0); + AddBackground(0, 0, 585, 393, 5054); + AddBackground(195, 36, 387, 275, 3000); + AddHtmlLocalized(10, 10, 565, 18, 1011356); //
VENDOR CUSTOMIZATION MENU
+ AddHtmlLocalized(60, 355, 150, 18, 1011036); // OKAY + AddButton(25, 355, 4005, 4007, 1); + AddHtmlLocalized(320, 355, 150, 18, 1011012); // CANCEL + AddButton(285, 355, 4005, 4007, 0); + + y = 35; + for (var i = 0; i < Categories.Length; i++) + { + var cat = Categories[i]; + AddHtmlLocalized(5, y, 150, 25, cat.LocNumber, true); + AddButton(155, y, 4005, 4007, 0, GumpButtonType.Page, i + 1); + y += 25; + } + + for (var i = 0; i < Categories.Length; i++) + { + var cat = Categories[i]; + AddPage(i + 1); + + for (var c = 0; c < cat.Entries.Length; c++) + { + var entry = cat.Entries[c]; + x = 198 + c % 3 * 129; + y = 38 + c / 3 * 67; + + AddHtmlLocalized(x, y, 100, entry.LongText ? 36 : 18, entry.LocNumber); + + if (entry.ArtNumber != 0) + AddItem(x + 20, y + 25, entry.ArtNumber); + + AddRadio(x, y + (entry.LongText ? 40 : 20), 210, 211, false, (c << 8) + i); + } + + if (cat.CanDye) + { + AddHtmlLocalized(327, 239, 100, 18, 1011402); // Color + AddRadio(327, 259, 210, 211, false, 100 + i); + } + + AddHtmlLocalized(456, 239, 100, 18, 1011403); // Remove + AddRadio(456, 259, 210, 211, false, 200 + i); + } + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (m_Vendor.Deleted) + return; + + var from = state.Mobile; + + if (m_Vendor is PlayerVendor vendor && !vendor.CanInteractWith(from, true)) + return; + + if (m_Vendor is PlayerBarkeeper barkeeper && !barkeeper.IsOwner(from)) + return; + + if (info.ButtonID == 0) + { + if (m_Vendor is PlayerVendor) // do nothing for barkeeps + { + m_Vendor.Direction = m_Vendor.GetDirectionTo(from); + m_Vendor.Animate(32, 5, 1, true, false, 0); // bow + m_Vendor.SayTo(from, 1043310 + Utility.Random(12)); // a little random speech + } + } + else if (info.ButtonID == 1 && info.Switches.Length > 0) + { + var cnum = info.Switches[0]; + var cat = cnum % 256; + var ent = cnum >> 8; + + if (cat < Categories.Length && cat >= 0) + { + if (ent < Categories[cat].Entries.Length && ent >= 0) + { + var item = m_Vendor.FindItemOnLayer(Categories[cat].Layer); + + item?.Delete(); + + var items = m_Vendor.Items; + + for (var i = 0; item == null && i < items.Count; ++i) + { + var checkitem = items[i]; + var type = checkitem.GetType(); + + for (var j = 0; item == null && j < Categories[cat].Entries.Length; ++j) + if (type == Categories[cat].Entries[j].Type) + item = checkitem; + } + + item?.Delete(); + + if (Categories[cat].Layer == Layer.FacialHair) + { + if (m_Vendor.Female) + { + from.SendLocalizedMessage(1010639); // You cannot place facial hair on a woman! + } + else + { + var hue = m_Vendor.FacialHairHue; + + m_Vendor.FacialHairItemID = 0; + m_Vendor.ProcessDelta(); // invalidate item ID for clients + + m_Vendor.FacialHairItemID = Categories[cat].Entries[ent].ItemID; + m_Vendor.FacialHairHue = hue; + } + } + else if (Categories[cat].Layer == Layer.Hair) + { + var hue = m_Vendor.HairHue; + + m_Vendor.HairItemID = 0; + m_Vendor.ProcessDelta(); // invalidate item ID for clients + + m_Vendor.HairItemID = Categories[cat].Entries[ent].ItemID; + m_Vendor.HairHue = hue; + } + else + { + item = Categories[cat].Entries[ent].Create(); + + if (item != null) + { + item.Layer = Categories[cat].Layer; + + if (!m_Vendor.EquipItem(item)) + item.Delete(); + } + } + + from.SendGump(new PlayerVendorCustomizeGump(m_Vendor, from)); + } + } + else + { + cat -= 100; + + if (cat < 100) + { + if (cat < Categories.Length && cat >= 0) + { + var category = Categories[cat]; + + if (category.Layer == Layer.Hair) + { + new PVHairHuePicker(false, m_Vendor, from).SendTo(state); + } + else if (category.Layer == Layer.FacialHair) + { + new PVHairHuePicker(true, m_Vendor, from).SendTo(state); + } + else + { + Item item = null; + + var items = m_Vendor.Items; + + for (var i = 0; item == null && i < items.Count; ++i) + { + var checkitem = items[i]; + var type = checkitem.GetType(); + + for (var j = 0; item == null && j < category.Entries.Length; ++j) + if (type == category.Entries[j].Type) + item = checkitem; + } + + if (item != null) + new PVHuePicker(item, m_Vendor, from).SendTo(state); + } + } + } + else + { + cat -= 100; + + if (cat < Categories.Length) + { + var category = Categories[cat]; + + if (category.Layer == Layer.Hair) + { + m_Vendor.HairItemID = 0; + } + else if (category.Layer == Layer.FacialHair) + { + m_Vendor.FacialHairItemID = 0; + } + else + { + Item item = null; + + var items = m_Vendor.Items; + + for (var i = 0; item == null && i < items.Count; ++i) + { + var checkitem = items[i]; + var type = checkitem.GetType(); + + for (var j = 0; item == null && j < category.Entries.Length; ++j) + if (type == category.Entries[j].Type) + item = checkitem; + } + + item?.Delete(); + } + + from.SendGump(new PlayerVendorCustomizeGump(m_Vendor, from)); + } + } + } + } + } + + private class CustomItem + { + public CustomItem(int itemID, int loc, bool longText = false) : this(null, itemID, loc, 0, longText) + { + } + + public CustomItem(Type type, int loc, int art = 0) : this(type, 0, loc, art) + { + } + + public CustomItem(Type type, int itemID = 0, int loc = 0, int art = 0, bool longText = false) + { + Type = type; + ItemID = itemID; + LocNumber = loc; + ArtNumber = art; + LongText = longText; + } + + public Type Type { get; } + + public int ItemID { get; } + + public int LocNumber { get; } + + public int ArtNumber { get; } + + public bool LongText { get; } + + public Item Create() + { + if (Type == null) + return null; + + Item i = null; + + try + { + var ctor = Type.GetConstructor(Array.Empty()); + if (ctor != null) + i = ctor.Invoke(null) as Item; + } + catch + { + // ignored + } + + return i; + } + } + + private class CustomCategory + { + public CustomCategory(Layer layer, int loc, bool canDye, CustomItem[] items) + { + Entries = items; + CanDye = canDye; + Layer = layer; + LocNumber = loc; + } + + public bool CanDye { get; } + + public CustomItem[] Entries { get; } + + public Layer Layer { get; } + + public int LocNumber { get; } + } + + private class PVHuePicker : HuePicker + { + private readonly Item m_Item; + private readonly Mobile m_Mob; + private readonly Mobile m_Vendor; + + public PVHuePicker(Item item, Mobile v, Mobile from) : base(item.ItemID) + { + m_Item = item; + m_Vendor = v; + m_Mob = from; + } + + public override void OnResponse(int hue) + { + if (m_Item.Deleted) + return; + + if (m_Vendor is PlayerVendor vendor && !vendor.CanInteractWith(m_Mob, true)) + return; + + if (m_Vendor is PlayerBarkeeper barkeeper && !barkeeper.IsOwner(m_Mob)) + return; + + m_Item.Hue = hue; + m_Mob.SendGump(new PlayerVendorCustomizeGump(m_Vendor, m_Mob)); + } + } + + private class PVHairHuePicker : HuePicker + { + private readonly bool m_FacialHair; + private readonly Mobile m_Mob; + private readonly Mobile m_Vendor; + + public PVHairHuePicker(bool facialHair, Mobile v, Mobile from) : base(0xFAB) + { + m_FacialHair = facialHair; + m_Vendor = v; + m_Mob = from; + } + + public override void OnResponse(int hue) + { + if (m_Vendor.Deleted) + return; + + if (m_Vendor is PlayerVendor vendor && !vendor.CanInteractWith(m_Mob, true)) + return; + + if (m_Vendor is PlayerBarkeeper barkeeper && !barkeeper.IsOwner(m_Mob)) + return; + + if (m_FacialHair) + m_Vendor.FacialHairHue = hue; + else + m_Vendor.HairHue = hue; + + m_Mob.SendGump(new PlayerVendorCustomizeGump(m_Vendor, m_Mob)); + } + } + } + + public class NewPlayerVendorCustomizeGump : Gump + { + private static readonly HairOrBeard[] m_HairStyles = + { + new HairOrBeard(0x203B, 1011052), // Short + new HairOrBeard(0x203C, 1011053), // Long + new HairOrBeard(0x203D, 1011054), // Ponytail + new HairOrBeard(0x2044, 1011055), // Mohawk + new HairOrBeard(0x2045, 1011047), // Pageboy + new HairOrBeard(0x204A, 1011050), // Topknot + new HairOrBeard(0x2047, 1011396), // Curly + new HairOrBeard(0x2048, 1011048), // Receding + new HairOrBeard(0x2049, 1011049) // 2-tails + }; + + private static readonly HairOrBeard[] m_BeardStyles = + { + new HairOrBeard(0x2041, 1011062), // Mustache + new HairOrBeard(0x203F, 1011060), // Short beard + new HairOrBeard(0x204B, 1015321), // Short Beard & Moustache + new HairOrBeard(0x203E, 1011061), // Long beard + new HairOrBeard(0x204C, 1015322), // Long Beard & Moustache + new HairOrBeard(0x2040, 1015323), // Goatee + new HairOrBeard(0x204D, 1011401) // Vandyke + }; + + private readonly PlayerVendor m_Vendor; + + public NewPlayerVendorCustomizeGump(PlayerVendor vendor) : base(50, 50) + { + m_Vendor = vendor; + + AddBackground(0, 0, 370, 370, 0x13BE); + + AddImageTiled(10, 10, 350, 20, 0xA40); + AddImageTiled(10, 40, 350, 20, 0xA40); + AddImageTiled(10, 70, 350, 260, 0xA40); + AddImageTiled(10, 340, 350, 20, 0xA40); + + AddAlphaRegion(10, 10, 350, 350); + + AddHtmlLocalized(10, 12, 350, 18, 1011356, 0x7FFF); //
VENDOR CUSTOMIZATION MENU
+ + AddHtmlLocalized(10, 42, 150, 18, 1062459, 0x421F); //
HAIR
+ + for (var i = 0; i < m_HairStyles.Length; i++) + { + var hair = m_HairStyles[i]; + + AddButton(10, 70 + i * 20, 0xFA5, 0xFA7, 0x100 | i); + AddHtmlLocalized(45, 72 + i * 20, 110, 18, hair.Name, 0x7FFF); + } + + AddButton(10, 70 + m_HairStyles.Length * 20, 0xFB1, 0xFB3, 2); + AddHtmlLocalized(45, 72 + m_HairStyles.Length * 20, 110, 18, 1011403, 0x7FFF); // Remove + + AddButton(10, 70 + (m_HairStyles.Length + 1) * 20, 0xFA5, 0xFA7, 3); + AddHtmlLocalized(45, 72 + (m_HairStyles.Length + 1) * 20, 110, 18, 1011402, 0x7FFF); // Color + + if (vendor.Female) + { + AddButton(160, 290, 0xFA5, 0xFA7, 1); + AddHtmlLocalized(195, 292, 160, 18, 1015327, 0x7FFF); // Male + + AddHtmlLocalized(195, 312, 160, 18, 1015328, 0x421F); // Female + } + else + { + AddHtmlLocalized(160, 42, 210, 18, 1062460, 0x421F); //
BEARD
+ + for (var i = 0; i < m_BeardStyles.Length; i++) + { + var beard = m_BeardStyles[i]; + + AddButton(160, 70 + i * 20, 0xFA5, 0xFA7, 0x200 | i); + AddHtmlLocalized(195, 72 + i * 20, 160, 18, beard.Name, 0x7FFF); + } + + AddButton(160, 70 + m_BeardStyles.Length * 20, 0xFB1, 0xFB3, 4); + AddHtmlLocalized(195, 72 + m_BeardStyles.Length * 20, 160, 18, 1011403, 0x7FFF); // Remove + + AddButton(160, 70 + (m_BeardStyles.Length + 1) * 20, 0xFA5, 0xFA7, 5); + AddHtmlLocalized(195, 72 + (m_BeardStyles.Length + 1) * 20, 160, 18, 1011402, 0x7FFF); // Color + + AddHtmlLocalized(195, 292, 160, 18, 1015327, 0x421F); // Male + + AddButton(160, 310, 0xFA5, 0xFA7, 1); + AddHtmlLocalized(195, 312, 160, 18, 1015328, 0x7FFF); // Female + } + + AddButton(10, 340, 0xFA5, 0xFA7, 0); + AddHtmlLocalized(45, 342, 305, 18, 1060675, 0x7FFF); // CLOSE + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var from = sender.Mobile; + + if (!m_Vendor.CanInteractWith(from, true)) + return; + + switch (info.ButtonID) + { + case 0: // CLOSE + { + m_Vendor.Direction = m_Vendor.GetDirectionTo(from); + m_Vendor.Animate(32, 5, 1, true, false, 0); // bow + m_Vendor.SayTo(from, 1043310 + Utility.Random(12)); // a little random speech + + break; + } + case 1: // Female/Male + { + if (m_Vendor.Female) + { + m_Vendor.BodyValue = 400; + m_Vendor.Female = false; + } + else + { + m_Vendor.BodyValue = 401; + m_Vendor.Female = true; + + m_Vendor.FacialHairItemID = 0; + } + + from.SendGump(new NewPlayerVendorCustomizeGump(m_Vendor)); + + break; + } + case 2: // Remove hair + { + m_Vendor.HairItemID = 0; + + from.SendGump(new NewPlayerVendorCustomizeGump(m_Vendor)); + + break; + } + case 3: // Color hair + { + if (m_Vendor.HairItemID > 0) + new PVHuePicker(m_Vendor, false, from).SendTo(from.NetState); + else + from.SendGump(new NewPlayerVendorCustomizeGump(m_Vendor)); + + break; + } + case 4: // Remove beard + { + m_Vendor.FacialHairItemID = 0; + + from.SendGump(new NewPlayerVendorCustomizeGump(m_Vendor)); + + break; + } + case 5: // Color beard + { + if (m_Vendor.FacialHairItemID > 0) + new PVHuePicker(m_Vendor, true, from).SendTo(from.NetState); + else + from.SendGump(new NewPlayerVendorCustomizeGump(m_Vendor)); + + break; + } + default: + { + int hairhue; + + if ((info.ButtonID & 0x100) != 0) // Hair style selected + { + var index = info.ButtonID & 0xFF; + + if (index >= m_HairStyles.Length) + return; + + var hairStyle = m_HairStyles[index]; + + hairhue = m_Vendor.HairHue; + + m_Vendor.HairItemID = 0; + m_Vendor.ProcessDelta(); + + m_Vendor.HairItemID = hairStyle.ItemID; + + m_Vendor.HairHue = hairhue; + + from.SendGump(new NewPlayerVendorCustomizeGump(m_Vendor)); + } + else if ((info.ButtonID & 0x200) != 0) // Beard style selected + { + if (m_Vendor.Female) + return; + + var index = info.ButtonID & 0xFF; + + if (index >= m_BeardStyles.Length) + return; + + var beardStyle = m_BeardStyles[index]; + + hairhue = m_Vendor.FacialHairHue; + + m_Vendor.FacialHairItemID = 0; + m_Vendor.ProcessDelta(); + + m_Vendor.FacialHairItemID = beardStyle.ItemID; + + m_Vendor.FacialHairHue = hairhue; + + from.SendGump(new NewPlayerVendorCustomizeGump(m_Vendor)); + } + + break; + } + } + } + + private class HairOrBeard + { + public HairOrBeard(int itemID, int name) + { + ItemID = itemID; + Name = name; + } + + public int ItemID { get; } + + public int Name { get; } + } + + private class PVHuePicker : HuePicker + { + private readonly bool m_FacialHair; + private readonly Mobile m_From; + private readonly PlayerVendor m_Vendor; + + public PVHuePicker(PlayerVendor vendor, bool facialHair, Mobile from) : base(0xFAB) + { + m_Vendor = vendor; + m_FacialHair = facialHair; + m_From = from; + } + + public override void OnResponse(int hue) + { + if (!m_Vendor.CanInteractWith(m_From, true)) + return; + + if (m_FacialHair) + m_Vendor.FacialHairHue = hue; + else + m_Vendor.HairHue = hue; + + m_From.SendGump(new NewPlayerVendorCustomizeGump(m_Vendor)); + } + } + } +} diff --git a/Projects/UOContent/Gumps/PolymorphGump.cs b/Projects/UOContent/Gumps/PolymorphGump.cs index 77878f1f5..04388a4bf 100644 --- a/Projects/UOContent/Gumps/PolymorphGump.cs +++ b/Projects/UOContent/Gumps/PolymorphGump.cs @@ -1,239 +1,243 @@ -using Server.Network; -using Server.Spells; -using Server.Spells.Seventh; - -namespace Server.Gumps -{ - public class PolymorphEntry - { - public static readonly PolymorphEntry Chicken = new PolymorphEntry(8401, 0xD0, 1015236, 15, 10); - public static readonly PolymorphEntry Dog = new PolymorphEntry(8405, 0xD9, 1015237, 17, 10); - public static readonly PolymorphEntry Wolf = new PolymorphEntry(8426, 0xE1, 1015238, 18, 10); - public static readonly PolymorphEntry Panther = new PolymorphEntry(8473, 0xD6, 1015239, 20, 14); - public static readonly PolymorphEntry Gorilla = new PolymorphEntry(8437, 0x1D, 1015240, 23, 10); - public static readonly PolymorphEntry BlackBear = new PolymorphEntry(8399, 0xD3, 1015241, 22, 10); - public static readonly PolymorphEntry GrizzlyBear = new PolymorphEntry(8411, 0xD4, 1015242, 22, 12); - public static readonly PolymorphEntry PolarBear = new PolymorphEntry(8417, 0xD5, 1015243, 26, 10); - public static readonly PolymorphEntry HumanMale = new PolymorphEntry(8397, 0x190, 1015244, 29, 8); - public static readonly PolymorphEntry HumanFemale = new PolymorphEntry(8398, 0x191, 1015254, 29, 10); - public static readonly PolymorphEntry Slime = new PolymorphEntry(8424, 0x33, 1015246, 5, 10); - public static readonly PolymorphEntry Orc = new PolymorphEntry(8416, 0x11, 1015247, 29, 10); - public static readonly PolymorphEntry LizardMan = new PolymorphEntry(8414, 0x21, 1015248, 26, 10); - public static readonly PolymorphEntry Gargoyle = new PolymorphEntry(8409, 0x04, 1015249, 22, 10); - public static readonly PolymorphEntry Ogre = new PolymorphEntry(8415, 0x01, 1015250, 24, 9); - public static readonly PolymorphEntry Troll = new PolymorphEntry(8425, 0x36, 1015251, 25, 9); - public static readonly PolymorphEntry Ettin = new PolymorphEntry(8408, 0x02, 1015252, 25, 8); - public static readonly PolymorphEntry Daemon = new PolymorphEntry(8403, 0x09, 1015253, 25, 8); - - private PolymorphEntry(int art, int body, int locNum, int x, int y) - { - ArtID = art; - BodyID = body; - LocNumber = locNum; - X = x; - Y = y; - } - - public int ArtID { get; } - - public int BodyID { get; } - - public int LocNumber { get; } - - public int X { get; } - - public int Y { get; } - } - - public class PolymorphGump : Gump - { - private static readonly PolymorphCategory[] Categories = - { - new PolymorphCategory(1015235, // Animals - PolymorphEntry.Chicken, - PolymorphEntry.Dog, - PolymorphEntry.Wolf, - PolymorphEntry.Panther, - PolymorphEntry.Gorilla, - PolymorphEntry.BlackBear, - PolymorphEntry.GrizzlyBear, - PolymorphEntry.PolarBear, - PolymorphEntry.HumanMale), - - new PolymorphCategory(1015245, // Monsters - PolymorphEntry.Slime, - PolymorphEntry.Orc, - PolymorphEntry.LizardMan, - PolymorphEntry.Gargoyle, - PolymorphEntry.Ogre, - PolymorphEntry.Troll, - PolymorphEntry.Ettin, - PolymorphEntry.Daemon, - PolymorphEntry.HumanFemale) - }; - - private readonly Mobile m_Caster; - private readonly Item m_Scroll; - - public PolymorphGump(Mobile caster, Item scroll) : base(50, 50) - { - m_Caster = caster; - m_Scroll = scroll; - - int x, y; - AddPage(0); - AddBackground(0, 0, 585, 393, 5054); - AddBackground(195, 36, 387, 275, 3000); - AddHtmlLocalized(0, 0, 510, 18, 1015234); //
Polymorph Selection Menu
- AddHtmlLocalized(60, 355, 150, 18, 1011036); // OKAY - AddButton(25, 355, 4005, 4007, 1, GumpButtonType.Reply, 1); - AddHtmlLocalized(320, 355, 150, 18, 1011012); // CANCEL - AddButton(285, 355, 4005, 4007, 0, GumpButtonType.Reply, 2); - - y = 35; - for (int i = 0; i < Categories.Length; i++) - { - PolymorphCategory cat = Categories[i]; - AddHtmlLocalized(5, y, 150, 25, cat.LocNumber, true); - AddButton(155, y, 4005, 4007, 0, GumpButtonType.Page, i + 1); - y += 25; - } - - for (int i = 0; i < Categories.Length; i++) - { - PolymorphCategory cat = Categories[i]; - AddPage(i + 1); - - for (int c = 0; c < cat.Entries.Length; c++) - { - PolymorphEntry entry = cat.Entries[c]; - x = 198 + c % 3 * 129; - y = 38 + c / 3 * 67; - - AddHtmlLocalized(x, y, 100, 18, entry.LocNumber); - AddItem(x + 20, y + 25, entry.ArtID); - AddRadio(x, y + 20, 210, 211, false, (c << 8) + i); - } - } - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (info.ButtonID == 1 && info.Switches.Length > 0) - { - int cnum = info.Switches[0]; - int cat = cnum % 256; - int ent = cnum >> 8; - - if (cat >= 0 && cat < Categories.Length) - if (ent >= 0 && ent < Categories[cat].Entries.Length) - { - Spell spell = new PolymorphSpell(m_Caster, m_Scroll, Categories[cat].Entries[ent].BodyID); - spell.Cast(); - } - } - } - - private class PolymorphCategory - { - public PolymorphCategory(int num, params PolymorphEntry[] entries) - { - LocNumber = num; - Entries = entries; - } - - public PolymorphEntry[] Entries { get; } - - public int LocNumber { get; } - } - } - - public class NewPolymorphGump : Gump - { - private static readonly PolymorphEntry[] m_Entries = - { - PolymorphEntry.Chicken, - PolymorphEntry.Dog, - PolymorphEntry.Wolf, - PolymorphEntry.Panther, - PolymorphEntry.Gorilla, - PolymorphEntry.BlackBear, - PolymorphEntry.GrizzlyBear, - PolymorphEntry.PolarBear, - PolymorphEntry.HumanMale, - PolymorphEntry.HumanFemale, - PolymorphEntry.Slime, - PolymorphEntry.Orc, - PolymorphEntry.LizardMan, - PolymorphEntry.Gargoyle, - PolymorphEntry.Ogre, - PolymorphEntry.Troll, - PolymorphEntry.Ettin, - PolymorphEntry.Daemon - }; - - private readonly Mobile m_Caster; - private readonly Item m_Scroll; - - public NewPolymorphGump(Mobile caster, Item scroll) : base(0, 0) - { - m_Caster = caster; - m_Scroll = scroll; - - AddPage(0); - - AddBackground(0, 0, 520, 404, 0x13BE); - AddImageTiled(10, 10, 500, 20, 0xA40); - AddImageTiled(10, 40, 500, 324, 0xA40); - AddImageTiled(10, 374, 500, 20, 0xA40); - AddAlphaRegion(10, 10, 500, 384); - - AddHtmlLocalized(14, 12, 500, 20, 1015234, 0x7FFF); //
Polymorph Selection Menu
- - AddButton(10, 374, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(45, 376, 450, 20, 1060051, 0x7FFF); // CANCEL - - for (int i = 0; i < m_Entries.Length; i++) - { - PolymorphEntry entry = m_Entries[i]; - - int page = i / 10 + 1; - int pos = i % 10; - - if (pos == 0) - { - if (page > 1) - { - AddButton(400, 374, 0xFA5, 0xFA7, 0, GumpButtonType.Page, page); - AddHtmlLocalized(440, 376, 60, 20, 1043353, 0x7FFF); // Next - } - - AddPage(page); - - if (page > 1) - { - AddButton(300, 374, 0xFAE, 0xFB0, 0, GumpButtonType.Page, 1); - AddHtmlLocalized(340, 376, 60, 20, 1011393, 0x7FFF); // Back - } - } - - int x = pos % 2 == 0 ? 14 : 264; - int y = pos / 2 * 64 + 44; - - AddImageTiledButton(x, y, 0x918, 0x919, i + 1, GumpButtonType.Reply, 0, entry.ArtID, 0x0, entry.X, entry.Y); - AddHtmlLocalized(x + 84, y, 250, 60, entry.LocNumber, 0x7FFF); - } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - int idx = info.ButtonID - 1; - - if (idx < 0 || idx >= m_Entries.Length) - return; - - Spell spell = new PolymorphSpell(m_Caster, m_Scroll, m_Entries[idx].BodyID); - spell.Cast(); - } - } -} +using Server.Network; +using Server.Spells; +using Server.Spells.Seventh; + +namespace Server.Gumps +{ + public class PolymorphEntry + { + public static readonly PolymorphEntry Chicken = new PolymorphEntry(8401, 0xD0, 1015236, 15, 10); + public static readonly PolymorphEntry Dog = new PolymorphEntry(8405, 0xD9, 1015237, 17, 10); + public static readonly PolymorphEntry Wolf = new PolymorphEntry(8426, 0xE1, 1015238, 18, 10); + public static readonly PolymorphEntry Panther = new PolymorphEntry(8473, 0xD6, 1015239, 20, 14); + public static readonly PolymorphEntry Gorilla = new PolymorphEntry(8437, 0x1D, 1015240, 23, 10); + public static readonly PolymorphEntry BlackBear = new PolymorphEntry(8399, 0xD3, 1015241, 22, 10); + public static readonly PolymorphEntry GrizzlyBear = new PolymorphEntry(8411, 0xD4, 1015242, 22, 12); + public static readonly PolymorphEntry PolarBear = new PolymorphEntry(8417, 0xD5, 1015243, 26, 10); + public static readonly PolymorphEntry HumanMale = new PolymorphEntry(8397, 0x190, 1015244, 29, 8); + public static readonly PolymorphEntry HumanFemale = new PolymorphEntry(8398, 0x191, 1015254, 29, 10); + public static readonly PolymorphEntry Slime = new PolymorphEntry(8424, 0x33, 1015246, 5, 10); + public static readonly PolymorphEntry Orc = new PolymorphEntry(8416, 0x11, 1015247, 29, 10); + public static readonly PolymorphEntry LizardMan = new PolymorphEntry(8414, 0x21, 1015248, 26, 10); + public static readonly PolymorphEntry Gargoyle = new PolymorphEntry(8409, 0x04, 1015249, 22, 10); + public static readonly PolymorphEntry Ogre = new PolymorphEntry(8415, 0x01, 1015250, 24, 9); + public static readonly PolymorphEntry Troll = new PolymorphEntry(8425, 0x36, 1015251, 25, 9); + public static readonly PolymorphEntry Ettin = new PolymorphEntry(8408, 0x02, 1015252, 25, 8); + public static readonly PolymorphEntry Daemon = new PolymorphEntry(8403, 0x09, 1015253, 25, 8); + + private PolymorphEntry(int art, int body, int locNum, int x, int y) + { + ArtID = art; + BodyID = body; + LocNumber = locNum; + X = x; + Y = y; + } + + public int ArtID { get; } + + public int BodyID { get; } + + public int LocNumber { get; } + + public int X { get; } + + public int Y { get; } + } + + public class PolymorphGump : Gump + { + private static readonly PolymorphCategory[] Categories = + { + new PolymorphCategory( + 1015235, // Animals + PolymorphEntry.Chicken, + PolymorphEntry.Dog, + PolymorphEntry.Wolf, + PolymorphEntry.Panther, + PolymorphEntry.Gorilla, + PolymorphEntry.BlackBear, + PolymorphEntry.GrizzlyBear, + PolymorphEntry.PolarBear, + PolymorphEntry.HumanMale + ), + + new PolymorphCategory( + 1015245, // Monsters + PolymorphEntry.Slime, + PolymorphEntry.Orc, + PolymorphEntry.LizardMan, + PolymorphEntry.Gargoyle, + PolymorphEntry.Ogre, + PolymorphEntry.Troll, + PolymorphEntry.Ettin, + PolymorphEntry.Daemon, + PolymorphEntry.HumanFemale + ) + }; + + private readonly Mobile m_Caster; + private readonly Item m_Scroll; + + public PolymorphGump(Mobile caster, Item scroll) : base(50, 50) + { + m_Caster = caster; + m_Scroll = scroll; + + int x, y; + AddPage(0); + AddBackground(0, 0, 585, 393, 5054); + AddBackground(195, 36, 387, 275, 3000); + AddHtmlLocalized(0, 0, 510, 18, 1015234); //
Polymorph Selection Menu
+ AddHtmlLocalized(60, 355, 150, 18, 1011036); // OKAY + AddButton(25, 355, 4005, 4007, 1, GumpButtonType.Reply, 1); + AddHtmlLocalized(320, 355, 150, 18, 1011012); // CANCEL + AddButton(285, 355, 4005, 4007, 0, GumpButtonType.Reply, 2); + + y = 35; + for (var i = 0; i < Categories.Length; i++) + { + var cat = Categories[i]; + AddHtmlLocalized(5, y, 150, 25, cat.LocNumber, true); + AddButton(155, y, 4005, 4007, 0, GumpButtonType.Page, i + 1); + y += 25; + } + + for (var i = 0; i < Categories.Length; i++) + { + var cat = Categories[i]; + AddPage(i + 1); + + for (var c = 0; c < cat.Entries.Length; c++) + { + var entry = cat.Entries[c]; + x = 198 + c % 3 * 129; + y = 38 + c / 3 * 67; + + AddHtmlLocalized(x, y, 100, 18, entry.LocNumber); + AddItem(x + 20, y + 25, entry.ArtID); + AddRadio(x, y + 20, 210, 211, false, (c << 8) + i); + } + } + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (info.ButtonID == 1 && info.Switches.Length > 0) + { + var cnum = info.Switches[0]; + var cat = cnum % 256; + var ent = cnum >> 8; + + if (cat >= 0 && cat < Categories.Length) + if (ent >= 0 && ent < Categories[cat].Entries.Length) + { + Spell spell = new PolymorphSpell(m_Caster, m_Scroll, Categories[cat].Entries[ent].BodyID); + spell.Cast(); + } + } + } + + private class PolymorphCategory + { + public PolymorphCategory(int num, params PolymorphEntry[] entries) + { + LocNumber = num; + Entries = entries; + } + + public PolymorphEntry[] Entries { get; } + + public int LocNumber { get; } + } + } + + public class NewPolymorphGump : Gump + { + private static readonly PolymorphEntry[] m_Entries = + { + PolymorphEntry.Chicken, + PolymorphEntry.Dog, + PolymorphEntry.Wolf, + PolymorphEntry.Panther, + PolymorphEntry.Gorilla, + PolymorphEntry.BlackBear, + PolymorphEntry.GrizzlyBear, + PolymorphEntry.PolarBear, + PolymorphEntry.HumanMale, + PolymorphEntry.HumanFemale, + PolymorphEntry.Slime, + PolymorphEntry.Orc, + PolymorphEntry.LizardMan, + PolymorphEntry.Gargoyle, + PolymorphEntry.Ogre, + PolymorphEntry.Troll, + PolymorphEntry.Ettin, + PolymorphEntry.Daemon + }; + + private readonly Mobile m_Caster; + private readonly Item m_Scroll; + + public NewPolymorphGump(Mobile caster, Item scroll) : base(0, 0) + { + m_Caster = caster; + m_Scroll = scroll; + + AddPage(0); + + AddBackground(0, 0, 520, 404, 0x13BE); + AddImageTiled(10, 10, 500, 20, 0xA40); + AddImageTiled(10, 40, 500, 324, 0xA40); + AddImageTiled(10, 374, 500, 20, 0xA40); + AddAlphaRegion(10, 10, 500, 384); + + AddHtmlLocalized(14, 12, 500, 20, 1015234, 0x7FFF); //
Polymorph Selection Menu
+ + AddButton(10, 374, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(45, 376, 450, 20, 1060051, 0x7FFF); // CANCEL + + for (var i = 0; i < m_Entries.Length; i++) + { + var entry = m_Entries[i]; + + var page = i / 10 + 1; + var pos = i % 10; + + if (pos == 0) + { + if (page > 1) + { + AddButton(400, 374, 0xFA5, 0xFA7, 0, GumpButtonType.Page, page); + AddHtmlLocalized(440, 376, 60, 20, 1043353, 0x7FFF); // Next + } + + AddPage(page); + + if (page > 1) + { + AddButton(300, 374, 0xFAE, 0xFB0, 0, GumpButtonType.Page, 1); + AddHtmlLocalized(340, 376, 60, 20, 1011393, 0x7FFF); // Back + } + } + + var x = pos % 2 == 0 ? 14 : 264; + var y = pos / 2 * 64 + 44; + + AddImageTiledButton(x, y, 0x918, 0x919, i + 1, GumpButtonType.Reply, 0, entry.ArtID, 0x0, entry.X, entry.Y); + AddHtmlLocalized(x + 84, y, 250, 60, entry.LocNumber, 0x7FFF); + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var idx = info.ButtonID - 1; + + if (idx < 0 || idx >= m_Entries.Length) + return; + + Spell spell = new PolymorphSpell(m_Caster, m_Scroll, m_Entries[idx].BodyID); + spell.Cast(); + } + } +} diff --git a/Projects/UOContent/Gumps/Props/PropsConfig.cs b/Projects/UOContent/Gumps/Props/PropsConfig.cs index 1b0f23f8c..599db65bb 100644 --- a/Projects/UOContent/Gumps/Props/PropsConfig.cs +++ b/Projects/UOContent/Gumps/Props/PropsConfig.cs @@ -1,42 +1,42 @@ -namespace Server.Gumps -{ - public class PropsConfig - { - public static readonly bool OldStyle = false; - - public static readonly int GumpOffsetX = 30; - public static readonly int GumpOffsetY = 30; - - public static readonly int TextHue = 0; - public static readonly int TextOffsetX = 2; - - public static readonly int OffsetGumpID = 0x0A40; // Pure black - - public static readonly int - HeaderGumpID = OldStyle ? 0x0BBC : 0x0E14; // Light offwhite, textured : Dark navy blue, textured - - public static readonly int EntryGumpID = 0x0BBC; // Light offwhite, textured - public static readonly int BackGumpID = 0x13BE; // Gray slate/stoney - public static readonly int SetGumpID = OldStyle ? 0x0000 : 0x0E14; // Empty : Dark navy blue, textured - - public static readonly int SetWidth = 20; - public static readonly int SetOffsetX = OldStyle ? 4 : 2, SetOffsetY = 2; - public static readonly int SetButtonID1 = 0x15E1; // Arrow pointing right - public static readonly int SetButtonID2 = 0x15E5; // " pressed - - public static readonly int PrevWidth = 20; - public static readonly int PrevOffsetX = 2, PrevOffsetY = 2; - public static readonly int PrevButtonID1 = 0x15E3; // Arrow pointing left - public static readonly int PrevButtonID2 = 0x15E7; // " pressed - - public static readonly int NextWidth = 20; - public static readonly int NextOffsetX = 2, NextOffsetY = 2; - public static readonly int NextButtonID1 = 0x15E1; // Arrow pointing right - public static readonly int NextButtonID2 = 0x15E5; // " pressed - - public static readonly int OffsetSize = 1; - - public static readonly int EntryHeight = 20; - public static readonly int BorderSize = 10; - } -} \ No newline at end of file +namespace Server.Gumps +{ + public class PropsConfig + { + public static readonly bool OldStyle = false; + + public static readonly int GumpOffsetX = 30; + public static readonly int GumpOffsetY = 30; + + public static readonly int TextHue = 0; + public static readonly int TextOffsetX = 2; + + public static readonly int OffsetGumpID = 0x0A40; // Pure black + + public static readonly int + HeaderGumpID = OldStyle ? 0x0BBC : 0x0E14; // Light offwhite, textured : Dark navy blue, textured + + public static readonly int EntryGumpID = 0x0BBC; // Light offwhite, textured + public static readonly int BackGumpID = 0x13BE; // Gray slate/stoney + public static readonly int SetGumpID = OldStyle ? 0x0000 : 0x0E14; // Empty : Dark navy blue, textured + + public static readonly int SetWidth = 20; + public static readonly int SetOffsetX = OldStyle ? 4 : 2, SetOffsetY = 2; + public static readonly int SetButtonID1 = 0x15E1; // Arrow pointing right + public static readonly int SetButtonID2 = 0x15E5; // " pressed + + public static readonly int PrevWidth = 20; + public static readonly int PrevOffsetX = 2, PrevOffsetY = 2; + public static readonly int PrevButtonID1 = 0x15E3; // Arrow pointing left + public static readonly int PrevButtonID2 = 0x15E7; // " pressed + + public static readonly int NextWidth = 20; + public static readonly int NextOffsetX = 2, NextOffsetY = 2; + public static readonly int NextButtonID1 = 0x15E1; // Arrow pointing right + public static readonly int NextButtonID2 = 0x15E5; // " pressed + + public static readonly int OffsetSize = 1; + + public static readonly int EntryHeight = 20; + public static readonly int BorderSize = 10; + } +} diff --git a/Projects/UOContent/Gumps/Props/PropsGump.cs b/Projects/UOContent/Gumps/Props/PropsGump.cs index 571198e12..2a0d40ee3 100644 --- a/Projects/UOContent/Gumps/Props/PropsGump.cs +++ b/Projects/UOContent/Gumps/Props/PropsGump.cs @@ -1,668 +1,735 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using Server.Commands.Generic; -using Server.Network; -using CPA = Server.CommandPropertyAttribute; - -namespace Server.Gumps -{ - public class StackEntry - { - public object m_Object; - public PropertyInfo m_Property; - - public StackEntry(object obj, PropertyInfo prop) - { - m_Object = obj; - m_Property = prop; - } - } - - public class PropertiesGump : Gump - { - public static readonly bool OldStyle = PropsConfig.OldStyle; - - public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; - public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; - - public static readonly int TextHue = PropsConfig.TextHue; - public static readonly int TextOffsetX = PropsConfig.TextOffsetX; - - public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; - public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; - public static readonly int EntryGumpID = PropsConfig.EntryGumpID; - public static readonly int BackGumpID = PropsConfig.BackGumpID; - public static readonly int SetGumpID = PropsConfig.SetGumpID; - - public static readonly int SetWidth = PropsConfig.SetWidth; - public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY; - public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; - public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; - - public static readonly int PrevWidth = PropsConfig.PrevWidth; - public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY; - public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; - public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; - - public static readonly int NextWidth = PropsConfig.NextWidth; - public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY; - public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; - public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; - - public static readonly int OffsetSize = PropsConfig.OffsetSize; - - public static readonly int EntryHeight = PropsConfig.EntryHeight; - public static readonly int BorderSize = PropsConfig.BorderSize; - - private static readonly bool PrevLabel = OldStyle; - private static readonly bool NextLabel = OldStyle; - private static readonly bool TypeLabel = !OldStyle; - - private static readonly int PrevLabelOffsetX = PrevWidth + 1; - private static readonly int PrevLabelOffsetY = 0; - - private static readonly int NextLabelOffsetX = -29; - private static readonly int NextLabelOffsetY = 0; - - private static readonly int NameWidth = 107; - private static readonly int ValueWidth = 128; - - private static readonly int EntryCount = 15; - - private static readonly int TypeWidth = NameWidth + OffsetSize + ValueWidth; - - private static readonly int TotalWidth = - OffsetSize + NameWidth + OffsetSize + ValueWidth + OffsetSize + SetWidth + OffsetSize; - - private static readonly int TotalHeight = OffsetSize + (EntryHeight + OffsetSize) * (EntryCount + 1); - - private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; - private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize; - - public static string[] m_BoolNames = { "True", "False" }; - public static object[] m_BoolValues = { true, false }; - - public static string[] m_PoisonNames = { "None", "Lesser", "Regular", "Greater", "Deadly", "Lethal" }; - - public static object[] m_PoisonValues = - { null, Poison.Lesser, Poison.Regular, Poison.Greater, Poison.Deadly, Poison.Lethal }; - - private static readonly Type typeofMobile = typeof(Mobile); - private static readonly Type typeofItem = typeof(Item); - private static readonly Type typeofType = typeof(Type); - private static readonly Type typeofPoint3D = typeof(Point3D); - private static readonly Type typeofPoint2D = typeof(Point2D); - private static readonly Type typeofTimeSpan = typeof(TimeSpan); - private static readonly Type typeofCustomEnum = typeof(CustomEnumAttribute); - private static readonly Type typeofEnum = typeof(Enum); - private static readonly Type typeofBool = typeof(bool); - private static readonly Type typeofString = typeof(string); - private static readonly Type typeofText = typeof(TextDefinition); - private static readonly Type typeofPoison = typeof(Poison); - private static readonly Type typeofMap = typeof(Map); - private static readonly Type typeofSkills = typeof(Skills); - private static readonly Type typeofPropertyObject = typeof(PropertyObjectAttribute); - private static readonly Type typeofNoSort = typeof(NoSortAttribute); - - private static readonly Type[] typeofReal = - { - typeof(float), - typeof(double) - }; - - private static readonly Type[] typeofNumeric = - { - typeof(byte), - typeof(short), - typeof(int), - typeof(long), - typeof(sbyte), - typeof(ushort), - typeof(uint), - typeof(ulong) - }; - - private static readonly Type typeofCPA = typeof(CPA); - private static readonly Type typeofObject = typeof(object); - private readonly List m_List; - private readonly Mobile m_Mobile; - private readonly object m_Object; - private int m_Page; - private readonly Stack m_Stack; - private readonly Type m_Type; - - public PropertiesGump(Mobile mobile, object o) : base(GumpOffsetX, GumpOffsetY) - { - m_Mobile = mobile; - m_Object = o; - m_Type = o.GetType(); - m_List = BuildList(); - - Initialize(0); - } - - public PropertiesGump(Mobile mobile, object o, Stack stack, StackEntry parent) : base(GumpOffsetX, - GumpOffsetY) - { - m_Mobile = mobile; - m_Object = o; - m_Type = o.GetType(); - m_Stack = stack; - m_List = BuildList(); - - if (parent != null) - { - m_Stack ??= new Stack(); - m_Stack.Push(parent); - } - - Initialize(0); - } - - public PropertiesGump(Mobile mobile, object o, Stack stack, List list, int page) : base(GumpOffsetX, - GumpOffsetY) - { - m_Mobile = mobile; - m_Object = o; - - if (o != null) - m_Type = o.GetType(); - - m_List = list; - m_Stack = stack; - - Initialize(page); - } - - private void Initialize(int page) - { - m_Page = page; - - int count = Math.Clamp(m_List.Count - page * EntryCount, 0, EntryCount); - - int lastIndex = page * EntryCount + count - 1; - - if (lastIndex >= 0 && lastIndex < m_List.Count && m_List[lastIndex] == null) - --count; - - int totalHeight = OffsetSize + (EntryHeight + OffsetSize) * (count + 1); - - AddPage(0); - - AddBackground(0, 0, BackWidth, BorderSize + totalHeight + BorderSize, BackGumpID); - AddImageTiled(BorderSize, BorderSize, TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), totalHeight, - OffsetGumpID); - - int x = BorderSize + OffsetSize; - int y = BorderSize + OffsetSize; - - int emptyWidth = TotalWidth - PrevWidth - NextWidth - OffsetSize * 4 - (OldStyle ? SetWidth + OffsetSize : 0); - - if (OldStyle) - AddImageTiled(x, y, TotalWidth - OffsetSize * 3 - SetWidth, EntryHeight, HeaderGumpID); - else - AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); - - if (page > 0) - { - AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 1); - - if (PrevLabel) - AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous"); - } - - x += PrevWidth + OffsetSize; - - if (!OldStyle) - AddImageTiled(x, y, emptyWidth, EntryHeight, HeaderGumpID); - - if (TypeLabel && m_Type != null) - AddHtml(x, y, emptyWidth, EntryHeight, - $"
{m_Type.Name}
"); - - x += emptyWidth + OffsetSize; - - if (!OldStyle) - AddImageTiled(x, y, NextWidth, EntryHeight, HeaderGumpID); - - if ((page + 1) * EntryCount < m_List.Count) - { - AddButton(x + NextOffsetX, y + NextOffsetY, NextButtonID1, NextButtonID2, 2, GumpButtonType.Reply, 1); - - if (NextLabel) - AddLabel(x + NextLabelOffsetX, y + NextLabelOffsetY, TextHue, "Next"); - } - - for (int i = 0, index = page * EntryCount; i < count && index < m_List.Count; ++i, ++index) - { - x = BorderSize + OffsetSize; - y += EntryHeight + OffsetSize; - - object o = m_List[index]; - - if (o == null) - { - AddImageTiled(x - OffsetSize, y, TotalWidth, EntryHeight, BackGumpID + 4); - } - else if (o is Type type) - { - AddImageTiled(x, y, TypeWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, TypeWidth - TextOffsetX, EntryHeight, TextHue, type.Name); - x += TypeWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - } - else if (o is PropertyInfo prop) - { - AddImageTiled(x, y, NameWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, NameWidth - TextOffsetX, EntryHeight, TextHue, prop.Name); - x += NameWidth + OffsetSize; - AddImageTiled(x, y, ValueWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, ValueWidth - TextOffsetX, EntryHeight, TextHue, ValueToString(prop)); - x += ValueWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - - CPA cpa = GetCPA(prop); - - if ((!prop.GetType().IsValueType || prop.CanWrite) && cpa != null && m_Mobile.AccessLevel >= cpa.WriteLevel && !cpa.ReadOnly) - AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, i + 3); - } - } - } - - public override void OnResponse(NetState state, RelayInfo info) - { - Mobile from = state.Mobile; - - if (!BaseCommand.IsAccessible(from, m_Object)) - { - from.SendMessage("You may no longer access their properties."); - return; - } - - switch (info.ButtonID) - { - case 0: // Closed - { - if (m_Stack?.Count > 0) - { - StackEntry entry = m_Stack.Pop(); - from.SendGump(new PropertiesGump(from, entry.m_Object, m_Stack, null)); - } - - break; - } - case 1: // Previous - { - if (m_Page > 0) - from.SendGump(new PropertiesGump(from, m_Object, m_Stack, m_List, m_Page - 1)); - - break; - } - case 2: // Next - { - if ((m_Page + 1) * EntryCount < m_List.Count) - from.SendGump(new PropertiesGump(from, m_Object, m_Stack, m_List, m_Page + 1)); - - break; - } - default: - { - int index = m_Page * EntryCount + (info.ButtonID - 3); - - if (index >= 0 && index < m_List.Count) - { - PropertyInfo prop = m_List[index] as PropertyInfo; - - if (prop == null) - return; - - CPA attr = GetCPA(prop); - - if ((prop.GetType().IsValueType && !prop.CanWrite) || attr == null || from.AccessLevel < attr.WriteLevel || attr.ReadOnly) - return; - - Type type = prop.PropertyType; - - if (IsType(type, typeofMobile) || IsType(type, typeofItem)) - { - from.SendGump(new SetObjectGump(prop, from, m_Object, m_Stack, type, m_Page, m_List)); - } - else if (IsType(type, typeofType)) - { - from.Target = new SetObjectTarget(prop, from, m_Object, m_Stack, type, m_Page, m_List); - } - else if (IsType(type, typeofPoint3D)) - { - from.SendGump(new SetPoint3DGump(prop, from, m_Object, m_Stack, m_Page, m_List)); - } - else if (IsType(type, typeofPoint2D)) - { - from.SendGump(new SetPoint2DGump(prop, from, m_Object, m_Stack, m_Page, m_List)); - } - else if (IsType(type, typeofTimeSpan)) - { - from.SendGump(new SetTimeSpanGump(prop, from, m_Object, m_Stack, m_Page, m_List)); - } - else if (IsCustomEnum(type)) - { - from.SendGump(new SetCustomEnumGump(prop, from, m_Object, m_Stack, m_Page, m_List, - GetCustomEnumNames(type))); - } - else if (IsType(type, typeofEnum)) - { - from.SendGump(new SetListOptionGump(prop, from, m_Object, m_Stack, m_Page, m_List, - Enum.GetNames(type), GetObjects(Enum.GetValues(type)))); - } - else if (IsType(type, typeofBool)) - { - from.SendGump(new SetListOptionGump(prop, from, m_Object, m_Stack, m_Page, m_List, m_BoolNames, - m_BoolValues)); - } - else if (IsType(type, typeofString) || IsType(type, typeofReal) || IsType(type, typeofNumeric) || - IsType(type, typeofText)) - { - from.SendGump(new SetGump(prop, from, m_Object, m_Stack, m_Page, m_List)); - } - else if (IsType(type, typeofPoison)) - { - from.SendGump(new SetListOptionGump(prop, from, m_Object, m_Stack, m_Page, m_List, m_PoisonNames, - m_PoisonValues)); - } - else if (IsType(type, typeofMap)) - { - from.SendGump(new SetListOptionGump(prop, from, m_Object, m_Stack, m_Page, m_List, - Map.GetMapNames(), Map.GetMapValues().ToArray())); - } - else if (IsType(type, typeofSkills) && m_Object is Mobile mobile) - { - from.SendGump(new PropertiesGump(from, mobile, m_Stack, m_List, m_Page)); - from.SendGump(new SkillsGump(from, mobile)); - } - else if (HasAttribute(type, typeofPropertyObject, true)) - { - object obj = prop.GetValue(m_Object, null); - - if (obj != null) - from.SendGump(new PropertiesGump(from, obj, m_Stack, new StackEntry(m_Object, prop))); - else - from.SendGump(new PropertiesGump(from, m_Object, m_Stack, m_List, m_Page)); - } - } - - break; - } - } - } - - private static object[] GetObjects(Array a) - { - object[] list = new object[a.Length]; - - for (int i = 0; i < list.Length; ++i) - list[i] = a.GetValue(i); - - return list; - } - - private static bool IsCustomEnum(Type type) => type.IsDefined(typeofCustomEnum, false); - - public static void OnValueChanged(object obj, PropertyInfo prop, Stack stack) - { - if (stack == null || stack.Count == 0) - return; - - if (!prop.PropertyType.IsValueType) - return; - - StackEntry peek = stack.Peek(); - - if (peek.m_Property.CanWrite) - peek.m_Property.SetValue(peek.m_Object, obj, null); - } - - private static string[] GetCustomEnumNames(Type type) - { - object[] attrs = type.GetCustomAttributes(typeofCustomEnum, false); - - if (attrs.Length == 0) - return Array.Empty(); - - if (!(attrs[0] is CustomEnumAttribute ce)) - return Array.Empty(); - - return ce.Names; - } - - private static bool HasAttribute(Type type, Type check, bool inherit) => type.GetCustomAttributes(check, inherit).Length > 0; - - private static bool IsType(Type type, Type check) => type == check || type.IsSubclassOf(check); - - private static bool IsType(Type type, Type[] check) - { - for (int i = 0; i < check.Length; ++i) - if (IsType(type, check[i])) - return true; - - return false; - } - - private string ValueToString(PropertyInfo prop) => ValueToString(m_Object, prop); - - public static string ValueToString(object obj, PropertyInfo prop) - { - try - { - return ValueToString(prop.GetValue(obj, null)); - } - catch (Exception e) - { - return $"!{e.GetType()}!"; - } - } - - public static string ValueToString(object o) - { - if (o == null) return "-null-"; - if (o is string s) return $"\"{s}\""; - if (o is bool) return o.ToString(); - if (o is char c) return $"0x{(int)c:X} '{c}'"; - if (o is Serial serial) - { - if (serial.IsValid) - { - if (serial.IsItem) return $"(I) 0x{serial.Value:X}"; - if (serial.IsMobile) return $"(M) 0x{serial.Value:X}"; - } - - return $"(?) 0x{serial.Value:X}"; - } - - if (o is byte || o is sbyte || o is short || o is ushort || o is int || o is uint || o is long || o is ulong) - return $"{o} (0x{o:X})"; - if (o is Mobile mobile) return $"(M) 0x{mobile.Serial.Value:X} \"{mobile.Name}\""; - if (o is Item item) return $"(I) 0x{item.Serial.Value:X}"; - if (o is Type type) return type.Name; - if (o is TextDefinition definition) return definition.Format(true); - - return o.ToString(); - } - - private List BuildList() - { - List list = new List(); - - if (m_Type == null) - return list; - - PropertyInfo[] props = m_Type.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public); - - List>> groups = GetGroups(m_Type, props); - - for (int i = 0; i < groups.Count; ++i) - { - KeyValuePair> kvp = groups[i]; - - if (!HasAttribute(kvp.Key, typeofNoSort, false)) - kvp.Value.Sort(PropertySorter.Instance); - - if (i != 0) - list.Add(null); - - list.Add(kvp.Key); - list.AddRange(kvp.Value); - } - - return list; - } - - private static CPA GetCPA(PropertyInfo prop) - { - object[] attrs = prop.GetCustomAttributes(typeofCPA, false); - - if (attrs.Length > 0) - return attrs[0] as CPA; - return null; - } - - private List>> GetGroups(Type objectType, PropertyInfo[] props) - { - Dictionary> groups = new Dictionary>(); - - for (int i = 0; i < props.Length; ++i) - { - PropertyInfo prop = props[i]; - - if (prop.CanRead) - { - CPA attr = GetCPA(prop); - - if (attr != null && m_Mobile.AccessLevel >= attr.ReadLevel) - { - Type type = prop.DeclaringType; - - while (true) - { - Type baseType = type?.BaseType; - - if (baseType == typeofObject || baseType?.GetProperty(prop.Name, prop.PropertyType) == null) - break; - - type = baseType; - } - - if (type != null && !groups.ContainsKey(type)) - groups[type] = new List { prop }; - else - groups[type].Add(prop); - } - } - } - - List>> list = groups.ToList(); - list.Sort(new GroupComparer(objectType)); - - return list; - } - - public static object GetObjectFromString(Type t, string s) - { - if (t == typeof(string)) return s; - - if (t == typeof(byte) || t == typeof(sbyte) || t == typeof(short) || t == typeof(ushort) || t == typeof(int) || - t == typeof(uint) || t == typeof(long) || t == typeof(ulong)) - { - if (s.StartsWith("0x")) - { - if (t == typeof(ulong) || t == typeof(uint) || t == typeof(ushort) || t == typeof(byte)) - return Convert.ChangeType(Convert.ToUInt64(s.Substring(2), 16), t); - - return Convert.ChangeType(Convert.ToInt64(s.Substring(2), 16), t); - } - - return Convert.ChangeType(s, t); - } - - if (t == typeof(double) || t == typeof(float)) return Convert.ChangeType(s, t); - if (t.IsDefined(typeof(ParsableAttribute), false)) - { - MethodInfo parseMethod = t.GetMethod("Parse", new[] { typeof(string) }); - - return parseMethod?.Invoke(null, new object[] { s }); - } - - throw new Exception("bad"); - } - - private static string GetStringFromObject(object o) - { - if (o == null) return "-null-"; - if (o is string s) return $"\"{s}\""; - if (o is bool) return o.ToString(); - if (o is char c) return $"0x{(int)c:X} '{c}'"; - if (o is Serial serial) - { - if (serial.IsValid) - { - if (serial.IsItem) return $"(I) 0x{serial.Value:X}"; - if (serial.IsMobile) return $"(M) 0x{serial.Value:X}"; - } - - return $"(?) 0x{serial.Value:X}"; - } - - if (o is byte || o is sbyte || o is short || o is ushort || o is int || o is uint || o is long || o is ulong) - return $"{o} (0x{o:X})"; - if (o is Mobile mobile) return $"(M) 0x{mobile.Serial.Value:X} \"{mobile.Name}\""; - if (o is Item item) return $"(I) 0x{item.Serial.Value:X}"; - if (o is Type type) return type.Name; - - return o.ToString(); - } - - private class PropertySorter : IComparer - { - public static readonly PropertySorter Instance = new PropertySorter(); - - private PropertySorter() - { - } - - public int Compare(PropertyInfo x, PropertyInfo y) - { - if (x == null && y == null) - return 0; - if (x == null) - return -1; - - return y == null ? 1 : x.Name.CompareTo(x.Name); - } - } - - private class GroupComparer : IComparer>> - { - private readonly Type m_Start; - - public GroupComparer(Type start) => m_Start = start; - - public int Compare(KeyValuePair> x, KeyValuePair> y) => GetDistance(x.Key).CompareTo(GetDistance(y.Key)); - - private int GetDistance(Type type) - { - Type current = m_Start; - - int dist; - - for (dist = 0; current != null && current != typeofObject && current != type; ++dist) - current = current.BaseType; - - return dist; - } - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Server.Commands.Generic; +using Server.Network; +using CPA = Server.CommandPropertyAttribute; + +namespace Server.Gumps +{ + public class StackEntry + { + public object m_Object; + public PropertyInfo m_Property; + + public StackEntry(object obj, PropertyInfo prop) + { + m_Object = obj; + m_Property = prop; + } + } + + public class PropertiesGump : Gump + { + public static readonly bool OldStyle = PropsConfig.OldStyle; + + public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; + public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; + + public static readonly int TextHue = PropsConfig.TextHue; + public static readonly int TextOffsetX = PropsConfig.TextOffsetX; + + public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; + public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; + public static readonly int EntryGumpID = PropsConfig.EntryGumpID; + public static readonly int BackGumpID = PropsConfig.BackGumpID; + public static readonly int SetGumpID = PropsConfig.SetGumpID; + + public static readonly int SetWidth = PropsConfig.SetWidth; + public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY; + public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; + public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; + + public static readonly int PrevWidth = PropsConfig.PrevWidth; + public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY; + public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; + public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; + + public static readonly int NextWidth = PropsConfig.NextWidth; + public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY; + public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; + public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; + + public static readonly int OffsetSize = PropsConfig.OffsetSize; + + public static readonly int EntryHeight = PropsConfig.EntryHeight; + public static readonly int BorderSize = PropsConfig.BorderSize; + + private static readonly bool PrevLabel = OldStyle; + private static readonly bool NextLabel = OldStyle; + private static readonly bool TypeLabel = !OldStyle; + + private static readonly int PrevLabelOffsetX = PrevWidth + 1; + private static readonly int PrevLabelOffsetY = 0; + + private static readonly int NextLabelOffsetX = -29; + private static readonly int NextLabelOffsetY = 0; + + private static readonly int NameWidth = 107; + private static readonly int ValueWidth = 128; + + private static readonly int EntryCount = 15; + + private static readonly int TypeWidth = NameWidth + OffsetSize + ValueWidth; + + private static readonly int TotalWidth = + OffsetSize + NameWidth + OffsetSize + ValueWidth + OffsetSize + SetWidth + OffsetSize; + + private static readonly int TotalHeight = OffsetSize + (EntryHeight + OffsetSize) * (EntryCount + 1); + + private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; + private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize; + + public static string[] m_BoolNames = { "True", "False" }; + public static object[] m_BoolValues = { true, false }; + + public static string[] m_PoisonNames = { "None", "Lesser", "Regular", "Greater", "Deadly", "Lethal" }; + + public static object[] m_PoisonValues = + { null, Poison.Lesser, Poison.Regular, Poison.Greater, Poison.Deadly, Poison.Lethal }; + + private static readonly Type typeofMobile = typeof(Mobile); + private static readonly Type typeofItem = typeof(Item); + private static readonly Type typeofType = typeof(Type); + private static readonly Type typeofPoint3D = typeof(Point3D); + private static readonly Type typeofPoint2D = typeof(Point2D); + private static readonly Type typeofTimeSpan = typeof(TimeSpan); + private static readonly Type typeofCustomEnum = typeof(CustomEnumAttribute); + private static readonly Type typeofEnum = typeof(Enum); + private static readonly Type typeofBool = typeof(bool); + private static readonly Type typeofString = typeof(string); + private static readonly Type typeofText = typeof(TextDefinition); + private static readonly Type typeofPoison = typeof(Poison); + private static readonly Type typeofMap = typeof(Map); + private static readonly Type typeofSkills = typeof(Skills); + private static readonly Type typeofPropertyObject = typeof(PropertyObjectAttribute); + private static readonly Type typeofNoSort = typeof(NoSortAttribute); + + private static readonly Type[] typeofReal = + { + typeof(float), + typeof(double) + }; + + private static readonly Type[] typeofNumeric = + { + typeof(byte), + typeof(short), + typeof(int), + typeof(long), + typeof(sbyte), + typeof(ushort), + typeof(uint), + typeof(ulong) + }; + + private static readonly Type typeofCPA = typeof(CPA); + private static readonly Type typeofObject = typeof(object); + private readonly List m_List; + private readonly Mobile m_Mobile; + private readonly object m_Object; + private readonly Stack m_Stack; + private readonly Type m_Type; + private int m_Page; + + public PropertiesGump(Mobile mobile, object o) : base(GumpOffsetX, GumpOffsetY) + { + m_Mobile = mobile; + m_Object = o; + m_Type = o.GetType(); + m_List = BuildList(); + + Initialize(0); + } + + public PropertiesGump(Mobile mobile, object o, Stack stack, StackEntry parent) : base( + GumpOffsetX, + GumpOffsetY + ) + { + m_Mobile = mobile; + m_Object = o; + m_Type = o.GetType(); + m_Stack = stack; + m_List = BuildList(); + + if (parent != null) + { + m_Stack ??= new Stack(); + m_Stack.Push(parent); + } + + Initialize(0); + } + + public PropertiesGump(Mobile mobile, object o, Stack stack, List list, int page) : base( + GumpOffsetX, + GumpOffsetY + ) + { + m_Mobile = mobile; + m_Object = o; + + if (o != null) + m_Type = o.GetType(); + + m_List = list; + m_Stack = stack; + + Initialize(page); + } + + private void Initialize(int page) + { + m_Page = page; + + var count = Math.Clamp(m_List.Count - page * EntryCount, 0, EntryCount); + + var lastIndex = page * EntryCount + count - 1; + + if (lastIndex >= 0 && lastIndex < m_List.Count && m_List[lastIndex] == null) + --count; + + var totalHeight = OffsetSize + (EntryHeight + OffsetSize) * (count + 1); + + AddPage(0); + + AddBackground(0, 0, BackWidth, BorderSize + totalHeight + BorderSize, BackGumpID); + AddImageTiled( + BorderSize, + BorderSize, + TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), + totalHeight, + OffsetGumpID + ); + + var x = BorderSize + OffsetSize; + var y = BorderSize + OffsetSize; + + var emptyWidth = TotalWidth - PrevWidth - NextWidth - OffsetSize * 4 - (OldStyle ? SetWidth + OffsetSize : 0); + + if (OldStyle) + AddImageTiled(x, y, TotalWidth - OffsetSize * 3 - SetWidth, EntryHeight, HeaderGumpID); + else + AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); + + if (page > 0) + { + AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 1); + + if (PrevLabel) + AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous"); + } + + x += PrevWidth + OffsetSize; + + if (!OldStyle) + AddImageTiled(x, y, emptyWidth, EntryHeight, HeaderGumpID); + + if (TypeLabel && m_Type != null) + AddHtml( + x, + y, + emptyWidth, + EntryHeight, + $"
{m_Type.Name}
" + ); + + x += emptyWidth + OffsetSize; + + if (!OldStyle) + AddImageTiled(x, y, NextWidth, EntryHeight, HeaderGumpID); + + if ((page + 1) * EntryCount < m_List.Count) + { + AddButton(x + NextOffsetX, y + NextOffsetY, NextButtonID1, NextButtonID2, 2, GumpButtonType.Reply, 1); + + if (NextLabel) + AddLabel(x + NextLabelOffsetX, y + NextLabelOffsetY, TextHue, "Next"); + } + + for (int i = 0, index = page * EntryCount; i < count && index < m_List.Count; ++i, ++index) + { + x = BorderSize + OffsetSize; + y += EntryHeight + OffsetSize; + + var o = m_List[index]; + + if (o == null) + { + AddImageTiled(x - OffsetSize, y, TotalWidth, EntryHeight, BackGumpID + 4); + } + else if (o is Type type) + { + AddImageTiled(x, y, TypeWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, TypeWidth - TextOffsetX, EntryHeight, TextHue, type.Name); + x += TypeWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + } + else if (o is PropertyInfo prop) + { + AddImageTiled(x, y, NameWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, NameWidth - TextOffsetX, EntryHeight, TextHue, prop.Name); + x += NameWidth + OffsetSize; + AddImageTiled(x, y, ValueWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, ValueWidth - TextOffsetX, EntryHeight, TextHue, ValueToString(prop)); + x += ValueWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + + var cpa = GetCPA(prop); + + if ((!prop.GetType().IsValueType || prop.CanWrite) && cpa != null && + m_Mobile.AccessLevel >= cpa.WriteLevel && !cpa.ReadOnly) + AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, i + 3); + } + } + } + + public override void OnResponse(NetState state, RelayInfo info) + { + var from = state.Mobile; + + if (!BaseCommand.IsAccessible(from, m_Object)) + { + from.SendMessage("You may no longer access their properties."); + return; + } + + switch (info.ButtonID) + { + case 0: // Closed + { + if (m_Stack?.Count > 0) + { + var entry = m_Stack.Pop(); + from.SendGump(new PropertiesGump(from, entry.m_Object, m_Stack, null)); + } + + break; + } + case 1: // Previous + { + if (m_Page > 0) + from.SendGump(new PropertiesGump(from, m_Object, m_Stack, m_List, m_Page - 1)); + + break; + } + case 2: // Next + { + if ((m_Page + 1) * EntryCount < m_List.Count) + from.SendGump(new PropertiesGump(from, m_Object, m_Stack, m_List, m_Page + 1)); + + break; + } + default: + { + var index = m_Page * EntryCount + (info.ButtonID - 3); + + if (index >= 0 && index < m_List.Count) + { + var prop = m_List[index] as PropertyInfo; + + if (prop == null) + return; + + var attr = GetCPA(prop); + + if (prop.GetType().IsValueType && !prop.CanWrite || attr == null || + from.AccessLevel < attr.WriteLevel || attr.ReadOnly) + return; + + var type = prop.PropertyType; + + if (IsType(type, typeofMobile) || IsType(type, typeofItem)) + { + from.SendGump(new SetObjectGump(prop, from, m_Object, m_Stack, type, m_Page, m_List)); + } + else if (IsType(type, typeofType)) + { + from.Target = new SetObjectTarget(prop, from, m_Object, m_Stack, type, m_Page, m_List); + } + else if (IsType(type, typeofPoint3D)) + { + from.SendGump(new SetPoint3DGump(prop, from, m_Object, m_Stack, m_Page, m_List)); + } + else if (IsType(type, typeofPoint2D)) + { + from.SendGump(new SetPoint2DGump(prop, from, m_Object, m_Stack, m_Page, m_List)); + } + else if (IsType(type, typeofTimeSpan)) + { + from.SendGump(new SetTimeSpanGump(prop, from, m_Object, m_Stack, m_Page, m_List)); + } + else if (IsCustomEnum(type)) + { + from.SendGump( + new SetCustomEnumGump( + prop, + from, + m_Object, + m_Stack, + m_Page, + m_List, + GetCustomEnumNames(type) + ) + ); + } + else if (IsType(type, typeofEnum)) + { + from.SendGump( + new SetListOptionGump( + prop, + from, + m_Object, + m_Stack, + m_Page, + m_List, + Enum.GetNames(type), + GetObjects(Enum.GetValues(type)) + ) + ); + } + else if (IsType(type, typeofBool)) + { + from.SendGump( + new SetListOptionGump( + prop, + from, + m_Object, + m_Stack, + m_Page, + m_List, + m_BoolNames, + m_BoolValues + ) + ); + } + else if (IsType(type, typeofString) || IsType(type, typeofReal) || IsType(type, typeofNumeric) || + IsType(type, typeofText)) + { + from.SendGump(new SetGump(prop, from, m_Object, m_Stack, m_Page, m_List)); + } + else if (IsType(type, typeofPoison)) + { + from.SendGump( + new SetListOptionGump( + prop, + from, + m_Object, + m_Stack, + m_Page, + m_List, + m_PoisonNames, + m_PoisonValues + ) + ); + } + else if (IsType(type, typeofMap)) + { + from.SendGump( + new SetListOptionGump( + prop, + from, + m_Object, + m_Stack, + m_Page, + m_List, + Map.GetMapNames(), + Map.GetMapValues().ToArray() + ) + ); + } + else if (IsType(type, typeofSkills) && m_Object is Mobile mobile) + { + from.SendGump(new PropertiesGump(from, mobile, m_Stack, m_List, m_Page)); + from.SendGump(new SkillsGump(from, mobile)); + } + else if (HasAttribute(type, typeofPropertyObject, true)) + { + var obj = prop.GetValue(m_Object, null); + + if (obj != null) + from.SendGump(new PropertiesGump(from, obj, m_Stack, new StackEntry(m_Object, prop))); + else + from.SendGump(new PropertiesGump(from, m_Object, m_Stack, m_List, m_Page)); + } + } + + break; + } + } + } + + private static object[] GetObjects(Array a) + { + var list = new object[a.Length]; + + for (var i = 0; i < list.Length; ++i) + list[i] = a.GetValue(i); + + return list; + } + + private static bool IsCustomEnum(Type type) => type.IsDefined(typeofCustomEnum, false); + + public static void OnValueChanged(object obj, PropertyInfo prop, Stack stack) + { + if (stack == null || stack.Count == 0) + return; + + if (!prop.PropertyType.IsValueType) + return; + + var peek = stack.Peek(); + + if (peek.m_Property.CanWrite) + peek.m_Property.SetValue(peek.m_Object, obj, null); + } + + private static string[] GetCustomEnumNames(Type type) + { + var attrs = type.GetCustomAttributes(typeofCustomEnum, false); + + if (attrs.Length == 0) + return Array.Empty(); + + if (!(attrs[0] is CustomEnumAttribute ce)) + return Array.Empty(); + + return ce.Names; + } + + private static bool HasAttribute(Type type, Type check, bool inherit) => + type.GetCustomAttributes(check, inherit).Length > 0; + + private static bool IsType(Type type, Type check) => type == check || type.IsSubclassOf(check); + + private static bool IsType(Type type, Type[] check) + { + for (var i = 0; i < check.Length; ++i) + if (IsType(type, check[i])) + return true; + + return false; + } + + private string ValueToString(PropertyInfo prop) => ValueToString(m_Object, prop); + + public static string ValueToString(object obj, PropertyInfo prop) + { + try + { + return ValueToString(prop.GetValue(obj, null)); + } + catch (Exception e) + { + return $"!{e.GetType()}!"; + } + } + + public static string ValueToString(object o) + { + if (o == null) return "-null-"; + if (o is string s) return $"\"{s}\""; + if (o is bool) return o.ToString(); + if (o is char c) return $"0x{(int)c:X} '{c}'"; + if (o is Serial serial) + { + if (serial.IsValid) + { + if (serial.IsItem) return $"(I) 0x{serial.Value:X}"; + if (serial.IsMobile) return $"(M) 0x{serial.Value:X}"; + } + + return $"(?) 0x{serial.Value:X}"; + } + + if (o is byte || o is sbyte || o is short || o is ushort || o is int || o is uint || o is long || o is ulong) + return $"{o} (0x{o:X})"; + if (o is Mobile mobile) return $"(M) 0x{mobile.Serial.Value:X} \"{mobile.Name}\""; + if (o is Item item) return $"(I) 0x{item.Serial.Value:X}"; + if (o is Type type) return type.Name; + if (o is TextDefinition definition) return definition.Format(true); + + return o.ToString(); + } + + private List BuildList() + { + var list = new List(); + + if (m_Type == null) + return list; + + var props = m_Type.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public); + + var groups = GetGroups(m_Type, props); + + for (var i = 0; i < groups.Count; ++i) + { + var kvp = groups[i]; + + if (!HasAttribute(kvp.Key, typeofNoSort, false)) + kvp.Value.Sort(PropertySorter.Instance); + + if (i != 0) + list.Add(null); + + list.Add(kvp.Key); + list.AddRange(kvp.Value); + } + + return list; + } + + private static CPA GetCPA(PropertyInfo prop) + { + var attrs = prop.GetCustomAttributes(typeofCPA, false); + + if (attrs.Length > 0) + return attrs[0] as CPA; + return null; + } + + private List>> GetGroups(Type objectType, PropertyInfo[] props) + { + var groups = new Dictionary>(); + + for (var i = 0; i < props.Length; ++i) + { + var prop = props[i]; + + if (prop.CanRead) + { + var attr = GetCPA(prop); + + if (attr != null && m_Mobile.AccessLevel >= attr.ReadLevel) + { + var type = prop.DeclaringType; + + while (true) + { + var baseType = type?.BaseType; + + if (baseType == typeofObject || baseType?.GetProperty(prop.Name, prop.PropertyType) == null) + break; + + type = baseType; + } + + if (type != null && !groups.ContainsKey(type)) + groups[type] = new List { prop }; + else + groups[type].Add(prop); + } + } + } + + var list = groups.ToList(); + list.Sort(new GroupComparer(objectType)); + + return list; + } + + public static object GetObjectFromString(Type t, string s) + { + if (t == typeof(string)) return s; + + if (t == typeof(byte) || t == typeof(sbyte) || t == typeof(short) || t == typeof(ushort) || t == typeof(int) || + t == typeof(uint) || t == typeof(long) || t == typeof(ulong)) + { + if (s.StartsWith("0x")) + { + if (t == typeof(ulong) || t == typeof(uint) || t == typeof(ushort) || t == typeof(byte)) + return Convert.ChangeType(Convert.ToUInt64(s.Substring(2), 16), t); + + return Convert.ChangeType(Convert.ToInt64(s.Substring(2), 16), t); + } + + return Convert.ChangeType(s, t); + } + + if (t == typeof(double) || t == typeof(float)) return Convert.ChangeType(s, t); + if (t.IsDefined(typeof(ParsableAttribute), false)) + { + var parseMethod = t.GetMethod("Parse", new[] { typeof(string) }); + + return parseMethod?.Invoke(null, new object[] { s }); + } + + throw new Exception("bad"); + } + + private static string GetStringFromObject(object o) + { + if (o == null) return "-null-"; + if (o is string s) return $"\"{s}\""; + if (o is bool) return o.ToString(); + if (o is char c) return $"0x{(int)c:X} '{c}'"; + if (o is Serial serial) + { + if (serial.IsValid) + { + if (serial.IsItem) return $"(I) 0x{serial.Value:X}"; + if (serial.IsMobile) return $"(M) 0x{serial.Value:X}"; + } + + return $"(?) 0x{serial.Value:X}"; + } + + if (o is byte || o is sbyte || o is short || o is ushort || o is int || o is uint || o is long || o is ulong) + return $"{o} (0x{o:X})"; + if (o is Mobile mobile) return $"(M) 0x{mobile.Serial.Value:X} \"{mobile.Name}\""; + if (o is Item item) return $"(I) 0x{item.Serial.Value:X}"; + if (o is Type type) return type.Name; + + return o.ToString(); + } + + private class PropertySorter : IComparer + { + public static readonly PropertySorter Instance = new PropertySorter(); + + private PropertySorter() + { + } + + public int Compare(PropertyInfo x, PropertyInfo y) + { + if (x == null && y == null) + return 0; + if (x == null) + return -1; + + return y == null ? 1 : x.Name.CompareTo(x.Name); + } + } + + private class GroupComparer : IComparer>> + { + private readonly Type m_Start; + + public GroupComparer(Type start) => m_Start = start; + + public int Compare(KeyValuePair> x, KeyValuePair> y) => + GetDistance(x.Key).CompareTo(GetDistance(y.Key)); + + private int GetDistance(Type type) + { + var current = m_Start; + + int dist; + + for (dist = 0; current != null && current != typeofObject && current != type; ++dist) + current = current.BaseType; + + return dist; + } + } + } +} diff --git a/Projects/UOContent/Gumps/Props/SetBodyGump.cs b/Projects/UOContent/Gumps/Props/SetBodyGump.cs index 08dd08cf0..3f0c85c0c 100644 --- a/Projects/UOContent/Gumps/Props/SetBodyGump.cs +++ b/Projects/UOContent/Gumps/Props/SetBodyGump.cs @@ -1,295 +1,330 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using Server.Commands; -using Server.Network; - -namespace Server.Gumps -{ - public class SetBodyGump : Gump - { - private const int LabelColor32 = 0xFFFFFF; - private const int SelectedColor32 = 0x8080FF; - private const int TextColor32 = 0xFFFFFF; - - private static List m_Monster, m_Animal, m_Sea, m_Human; - private readonly List m_List; - private readonly Mobile m_Mobile; - private readonly object m_Object; - private readonly List m_OurList; - private readonly int m_OurPage; - private readonly ModelBodyType m_OurType; - private readonly int m_Page; - private readonly PropertyInfo m_Property; - private readonly Stack m_Stack; - - public SetBodyGump(PropertyInfo prop, Mobile mobile, object o, Stack stack, int page, List list, - int ourPage = 0, List ourList = null, ModelBodyType ourType = ModelBodyType.Invalid) - : base(20, 30) - { - m_Property = prop; - m_Mobile = mobile; - m_Object = o; - m_Stack = stack; - m_Page = page; - m_List = list; - m_OurPage = ourPage; - m_OurList = ourList; - m_OurType = ourType; - - AddPage(0); - - AddBackground(0, 0, 525, 328, 5054); - - AddImageTiled(10, 10, 505, 20, 0xA40); - AddAlphaRegion(10, 10, 505, 20); - - AddImageTiled(10, 35, 505, 283, 0xA40); - AddAlphaRegion(10, 35, 505, 283); - - AddTypeButton(10, 10, 1, "Monster", ModelBodyType.Monsters); - AddTypeButton(130, 10, 2, "Animal", ModelBodyType.Animals); - AddTypeButton(250, 10, 3, "Marine", ModelBodyType.Sea); - AddTypeButton(370, 10, 4, "Human", ModelBodyType.Human); - - AddImage(480, 12, 0x25EA); - AddImage(497, 12, 0x25E6); - - if (ourList == null) - { - AddLabel(15, 40, 0x480, "Choose a body type above."); - } - else if (ourList.Count == 0) - { - AddLabel(15, 40, 0x480, "The server must have UO:3D installed to use this feature."); - } - else - { - for (int i = 0, index = ourPage * 12; i < 12 && index >= 0 && index < ourList.Count; ++i, ++index) - { - InternalEntry entry = ourList[index]; - int itemID = entry.ItemID; - - Rectangle2D bounds = ItemBounds.Table[itemID & 0x3FFF]; - - int x = 15 + i % 4 * 125; - int y = 40 + i / 4 * 93; - - AddItem(x + (120 - bounds.Width) / 2 - bounds.X, y + (69 - bounds.Height) / 2 - bounds.Y, itemID); - AddButton(x + 6, y + 66, 0x98D, 0x98D, 7 + index); - - x += 6; - y += 67; - - AddHtml(x + 0, y - 1, 108, 21, Center(entry.DisplayName)); - AddHtml(x + 0, y + 1, 108, 21, Center(entry.DisplayName)); - AddHtml(x - 1, y + 0, 108, 21, Center(entry.DisplayName)); - AddHtml(x + 1, y + 0, 108, 21, Center(entry.DisplayName)); - AddHtml(x + 0, y + 0, 108, 21, Color(Center(entry.DisplayName), TextColor32)); - } - - if (ourPage > 0) - AddButton(480, 12, 0x15E3, 0x15E7, 5); - - if ((ourPage + 1) * 12 < ourList.Count) - AddButton(497, 12, 0x15E1, 0x15E5, 6); - } - } - - public string Center(string text) => $"
{text}
"; - - public string Color(string text, int color) => $"{text}"; - - public void AddTypeButton(int x, int y, int buttonID, string text, ModelBodyType type) - { - bool isSelection = m_OurType == type; - - AddButton(x, y - 1, isSelection ? 4006 : 4005, 4007, buttonID); - AddHtml(x + 35, y, 200, 20, Color(text, isSelection ? SelectedColor32 : LabelColor32)); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - int index = info.ButtonID - 1; - - if (index == -1) - { - m_Mobile.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); - } - else if (index >= 0 && index < 4) - { - if (m_Monster == null) - LoadLists(); - - ModelBodyType type; - List list; - - switch (index) - { - default: - type = ModelBodyType.Monsters; - list = m_Monster; - break; - case 1: - type = ModelBodyType.Animals; - list = m_Animal; - break; - case 2: - type = ModelBodyType.Sea; - list = m_Sea; - break; - case 3: - type = ModelBodyType.Human; - list = m_Human; - break; - } - - m_Mobile.SendGump(new SetBodyGump(m_Property, m_Mobile, m_Object, m_Stack, m_Page, m_List, 0, list, type)); - } - else if (m_OurList != null) - { - index -= 4; - - if (index == 0 && m_OurPage > 0) - { - m_Mobile.SendGump(new SetBodyGump(m_Property, m_Mobile, m_Object, m_Stack, m_Page, m_List, m_OurPage - 1, - m_OurList, m_OurType)); - } - else if (index == 1 && (m_OurPage + 1) * 12 < m_OurList.Count) - { - m_Mobile.SendGump(new SetBodyGump(m_Property, m_Mobile, m_Object, m_Stack, m_Page, m_List, m_OurPage + 1, - m_OurList, m_OurType)); - } - else - { - index -= 2; - - if (index >= 0 && index < m_OurList.Count) - { - try - { - InternalEntry entry = m_OurList[index]; - - CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, entry.Body.ToString()); - m_Property.SetValue(m_Object, entry.Body, null); - PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); - } - catch - { - m_Mobile.SendMessage("An exception was caught. The property may not have changed."); - } - - m_Mobile.SendGump(new SetBodyGump(m_Property, m_Mobile, m_Object, m_Stack, m_Page, m_List, m_OurPage, - m_OurList, m_OurType)); - } - } - } - } - - private static void LoadLists() - { - m_Monster = new List(); - m_Animal = new List(); - m_Sea = new List(); - m_Human = new List(); - - List entries = Docs.LoadBodies(); - - for (int i = 0; i < entries.Count; ++i) - { - BodyEntry oldEntry = entries[i]; - int bodyID = oldEntry.Body.BodyID; - - if (((Body)bodyID).IsEmpty) - continue; - - List list; - - switch (oldEntry.BodyType) - { - default: continue; - case ModelBodyType.Monsters: - list = m_Monster; - break; - case ModelBodyType.Animals: - list = m_Animal; - break; - case ModelBodyType.Sea: - list = m_Sea; - break; - case ModelBodyType.Human: - list = m_Human; - break; - } - - int itemID = ShrinkTable.Lookup(bodyID, -1); - - if (itemID != -1) - list.Add(new InternalEntry(bodyID, itemID, oldEntry.Name)); - } - - m_Monster.Sort(); - m_Animal.Sort(); - m_Sea.Sort(); - m_Human.Sort(); - } - - public class InternalEntry : IComparable - { - private static readonly string[] m_GroupNames = - { - "ogres_", "ettins_", "walking_dead_", "gargoyles_", - "orcs_", "flails_", "daemons_", "arachnids_", - "dragons_", "elementals_", "serpents_", "gazers_", - "liche_", "spirits_", "harpies_", "headless_", - "lizard_race_", "mongbat_", "rat_race_", "scorpions_", - "trolls_", "slimes_", "skeletons_", "ethereals_", - "terathan_", "imps_", "cyclops_", "krakens_", - "frogs_", "ophidians_", "centaurs_", "mages_", - "fey_race_", "genies_", "paladins_", "shadowlords_", - "succubi_", "lizards_", "rodents_", "birds_", - "bovines_", "bruins_", "canines_", "deer_", - "equines_", "felines_", "fowl_", "gorillas_", - "kirin_", "llamas_", "ostards_", "porcines_", - "ruminants_", "walrus_", "dolphins_", "sea_horse_", - "sea_serpents_", "character_", "h_", "titans_" - }; - - public InternalEntry(int body, int itemID, string name) - { - Body = body; - ItemID = itemID; - Name = name; - - DisplayName = name.ToLower(); - - for (int i = 0; i < m_GroupNames.Length; ++i) - if (DisplayName.StartsWith(m_GroupNames[i])) - { - DisplayName = DisplayName.Substring(m_GroupNames[i].Length); - break; - } - - DisplayName = DisplayName.Replace('_', ' '); - } - - public int Body { get; } - - public int ItemID { get; } - - public string Name { get; } - - public string DisplayName { get; } - - public int CompareTo(InternalEntry comp) - { - if (Name == null && comp.Name == null) - return 0; - - int v = Name?.CompareTo(comp.Name) ?? 1; - - return v == 0 ? Body.CompareTo(comp.Body) : v; - } - } - } -} +using System; +using System.Collections.Generic; +using System.Reflection; +using Server.Commands; +using Server.Network; + +namespace Server.Gumps +{ + public class SetBodyGump : Gump + { + private const int LabelColor32 = 0xFFFFFF; + private const int SelectedColor32 = 0x8080FF; + private const int TextColor32 = 0xFFFFFF; + + private static List m_Monster, m_Animal, m_Sea, m_Human; + private readonly List m_List; + private readonly Mobile m_Mobile; + private readonly object m_Object; + private readonly List m_OurList; + private readonly int m_OurPage; + private readonly ModelBodyType m_OurType; + private readonly int m_Page; + private readonly PropertyInfo m_Property; + private readonly Stack m_Stack; + + public SetBodyGump( + PropertyInfo prop, Mobile mobile, object o, Stack stack, int page, List list, + int ourPage = 0, List ourList = null, ModelBodyType ourType = ModelBodyType.Invalid + ) + : base(20, 30) + { + m_Property = prop; + m_Mobile = mobile; + m_Object = o; + m_Stack = stack; + m_Page = page; + m_List = list; + m_OurPage = ourPage; + m_OurList = ourList; + m_OurType = ourType; + + AddPage(0); + + AddBackground(0, 0, 525, 328, 5054); + + AddImageTiled(10, 10, 505, 20, 0xA40); + AddAlphaRegion(10, 10, 505, 20); + + AddImageTiled(10, 35, 505, 283, 0xA40); + AddAlphaRegion(10, 35, 505, 283); + + AddTypeButton(10, 10, 1, "Monster", ModelBodyType.Monsters); + AddTypeButton(130, 10, 2, "Animal", ModelBodyType.Animals); + AddTypeButton(250, 10, 3, "Marine", ModelBodyType.Sea); + AddTypeButton(370, 10, 4, "Human", ModelBodyType.Human); + + AddImage(480, 12, 0x25EA); + AddImage(497, 12, 0x25E6); + + if (ourList == null) + { + AddLabel(15, 40, 0x480, "Choose a body type above."); + } + else if (ourList.Count == 0) + { + AddLabel(15, 40, 0x480, "The server must have UO:3D installed to use this feature."); + } + else + { + for (int i = 0, index = ourPage * 12; i < 12 && index >= 0 && index < ourList.Count; ++i, ++index) + { + var entry = ourList[index]; + var itemID = entry.ItemID; + + var bounds = ItemBounds.Table[itemID & 0x3FFF]; + + var x = 15 + i % 4 * 125; + var y = 40 + i / 4 * 93; + + AddItem(x + (120 - bounds.Width) / 2 - bounds.X, y + (69 - bounds.Height) / 2 - bounds.Y, itemID); + AddButton(x + 6, y + 66, 0x98D, 0x98D, 7 + index); + + x += 6; + y += 67; + + AddHtml(x + 0, y - 1, 108, 21, Center(entry.DisplayName)); + AddHtml(x + 0, y + 1, 108, 21, Center(entry.DisplayName)); + AddHtml(x - 1, y + 0, 108, 21, Center(entry.DisplayName)); + AddHtml(x + 1, y + 0, 108, 21, Center(entry.DisplayName)); + AddHtml(x + 0, y + 0, 108, 21, Color(Center(entry.DisplayName), TextColor32)); + } + + if (ourPage > 0) + AddButton(480, 12, 0x15E3, 0x15E7, 5); + + if ((ourPage + 1) * 12 < ourList.Count) + AddButton(497, 12, 0x15E1, 0x15E5, 6); + } + } + + public string Center(string text) => $"
{text}
"; + + public string Color(string text, int color) => $"{text}"; + + public void AddTypeButton(int x, int y, int buttonID, string text, ModelBodyType type) + { + var isSelection = m_OurType == type; + + AddButton(x, y - 1, isSelection ? 4006 : 4005, 4007, buttonID); + AddHtml(x + 35, y, 200, 20, Color(text, isSelection ? SelectedColor32 : LabelColor32)); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var index = info.ButtonID - 1; + + if (index == -1) + { + m_Mobile.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); + } + else if (index >= 0 && index < 4) + { + if (m_Monster == null) + LoadLists(); + + ModelBodyType type; + List list; + + switch (index) + { + default: + type = ModelBodyType.Monsters; + list = m_Monster; + break; + case 1: + type = ModelBodyType.Animals; + list = m_Animal; + break; + case 2: + type = ModelBodyType.Sea; + list = m_Sea; + break; + case 3: + type = ModelBodyType.Human; + list = m_Human; + break; + } + + m_Mobile.SendGump(new SetBodyGump(m_Property, m_Mobile, m_Object, m_Stack, m_Page, m_List, 0, list, type)); + } + else if (m_OurList != null) + { + index -= 4; + + if (index == 0 && m_OurPage > 0) + { + m_Mobile.SendGump( + new SetBodyGump( + m_Property, + m_Mobile, + m_Object, + m_Stack, + m_Page, + m_List, + m_OurPage - 1, + m_OurList, + m_OurType + ) + ); + } + else if (index == 1 && (m_OurPage + 1) * 12 < m_OurList.Count) + { + m_Mobile.SendGump( + new SetBodyGump( + m_Property, + m_Mobile, + m_Object, + m_Stack, + m_Page, + m_List, + m_OurPage + 1, + m_OurList, + m_OurType + ) + ); + } + else + { + index -= 2; + + if (index >= 0 && index < m_OurList.Count) + { + try + { + var entry = m_OurList[index]; + + CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, entry.Body.ToString()); + m_Property.SetValue(m_Object, entry.Body, null); + PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); + } + catch + { + m_Mobile.SendMessage("An exception was caught. The property may not have changed."); + } + + m_Mobile.SendGump( + new SetBodyGump( + m_Property, + m_Mobile, + m_Object, + m_Stack, + m_Page, + m_List, + m_OurPage, + m_OurList, + m_OurType + ) + ); + } + } + } + } + + private static void LoadLists() + { + m_Monster = new List(); + m_Animal = new List(); + m_Sea = new List(); + m_Human = new List(); + + var entries = Docs.LoadBodies(); + + for (var i = 0; i < entries.Count; ++i) + { + var oldEntry = entries[i]; + var bodyID = oldEntry.Body.BodyID; + + if (((Body)bodyID).IsEmpty) + continue; + + List list; + + switch (oldEntry.BodyType) + { + default: continue; + case ModelBodyType.Monsters: + list = m_Monster; + break; + case ModelBodyType.Animals: + list = m_Animal; + break; + case ModelBodyType.Sea: + list = m_Sea; + break; + case ModelBodyType.Human: + list = m_Human; + break; + } + + var itemID = ShrinkTable.Lookup(bodyID, -1); + + if (itemID != -1) + list.Add(new InternalEntry(bodyID, itemID, oldEntry.Name)); + } + + m_Monster.Sort(); + m_Animal.Sort(); + m_Sea.Sort(); + m_Human.Sort(); + } + + public class InternalEntry : IComparable + { + private static readonly string[] m_GroupNames = + { + "ogres_", "ettins_", "walking_dead_", "gargoyles_", + "orcs_", "flails_", "daemons_", "arachnids_", + "dragons_", "elementals_", "serpents_", "gazers_", + "liche_", "spirits_", "harpies_", "headless_", + "lizard_race_", "mongbat_", "rat_race_", "scorpions_", + "trolls_", "slimes_", "skeletons_", "ethereals_", + "terathan_", "imps_", "cyclops_", "krakens_", + "frogs_", "ophidians_", "centaurs_", "mages_", + "fey_race_", "genies_", "paladins_", "shadowlords_", + "succubi_", "lizards_", "rodents_", "birds_", + "bovines_", "bruins_", "canines_", "deer_", + "equines_", "felines_", "fowl_", "gorillas_", + "kirin_", "llamas_", "ostards_", "porcines_", + "ruminants_", "walrus_", "dolphins_", "sea_horse_", + "sea_serpents_", "character_", "h_", "titans_" + }; + + public InternalEntry(int body, int itemID, string name) + { + Body = body; + ItemID = itemID; + Name = name; + + DisplayName = name.ToLower(); + + for (var i = 0; i < m_GroupNames.Length; ++i) + if (DisplayName.StartsWith(m_GroupNames[i])) + { + DisplayName = DisplayName.Substring(m_GroupNames[i].Length); + break; + } + + DisplayName = DisplayName.Replace('_', ' '); + } + + public int Body { get; } + + public int ItemID { get; } + + public string Name { get; } + + public string DisplayName { get; } + + public int CompareTo(InternalEntry comp) + { + if (Name == null && comp.Name == null) + return 0; + + var v = Name?.CompareTo(comp.Name) ?? 1; + + return v == 0 ? Body.CompareTo(comp.Body) : v; + } + } + } +} diff --git a/Projects/UOContent/Gumps/Props/SetCustomEnumGump.cs b/Projects/UOContent/Gumps/Props/SetCustomEnumGump.cs index db3cb4d14..997a20b06 100644 --- a/Projects/UOContent/Gumps/Props/SetCustomEnumGump.cs +++ b/Projects/UOContent/Gumps/Props/SetCustomEnumGump.cs @@ -1,50 +1,66 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using Server.Commands; -using Server.Network; - -namespace Server.Gumps -{ - public class SetCustomEnumGump : SetListOptionGump - { - private readonly string[] m_Names; - - public SetCustomEnumGump(PropertyInfo prop, Mobile mobile, object o, Stack stack, int propspage, - List list, string[] names) : base(prop, mobile, o, stack, propspage, list, names, null) => - m_Names = names; - - public override void OnResponse(NetState sender, RelayInfo relayInfo) - { - int index = relayInfo.ButtonID - 1; - - if (index >= 0 && index < m_Names.Length) - try - { - MethodInfo info = m_Property.PropertyType.GetMethod("Parse", new[] { typeof(string) }); - - string result; - - if (info != null) - result = Properties.SetDirect(m_Mobile, m_Object, m_Object, m_Property, m_Property.Name, - info.Invoke(null, new object[] { m_Names[index] }), true); - else if (m_Property.PropertyType == typeof(Enum) || m_Property.PropertyType.IsSubclassOf(typeof(Enum))) - result = Properties.SetDirect(m_Mobile, m_Object, m_Object, m_Property, m_Property.Name, - Enum.Parse(m_Property.PropertyType, m_Names[index], false), true); - else - result = ""; - - m_Mobile.SendMessage(result); - - if (result == "Property has been set.") - PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); - } - catch - { - m_Mobile.SendMessage("An exception was caught. The property may not have changed."); - } - - m_Mobile.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); - } - } -} \ No newline at end of file +using System; +using System.Collections.Generic; +using System.Reflection; +using Server.Commands; +using Server.Network; + +namespace Server.Gumps +{ + public class SetCustomEnumGump : SetListOptionGump + { + private readonly string[] m_Names; + + public SetCustomEnumGump( + PropertyInfo prop, Mobile mobile, object o, Stack stack, int propspage, + List list, string[] names + ) : base(prop, mobile, o, stack, propspage, list, names, null) => + m_Names = names; + + public override void OnResponse(NetState sender, RelayInfo relayInfo) + { + var index = relayInfo.ButtonID - 1; + + if (index >= 0 && index < m_Names.Length) + try + { + var info = m_Property.PropertyType.GetMethod("Parse", new[] { typeof(string) }); + + string result; + + if (info != null) + result = Properties.SetDirect( + m_Mobile, + m_Object, + m_Object, + m_Property, + m_Property.Name, + info.Invoke(null, new object[] { m_Names[index] }), + true + ); + else if (m_Property.PropertyType == typeof(Enum) || m_Property.PropertyType.IsSubclassOf(typeof(Enum))) + result = Properties.SetDirect( + m_Mobile, + m_Object, + m_Object, + m_Property, + m_Property.Name, + Enum.Parse(m_Property.PropertyType, m_Names[index], false), + true + ); + else + result = ""; + + m_Mobile.SendMessage(result); + + if (result == "Property has been set.") + PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); + } + catch + { + m_Mobile.SendMessage("An exception was caught. The property may not have changed."); + } + + m_Mobile.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); + } + } +} diff --git a/Projects/UOContent/Gumps/Props/SetGump.cs b/Projects/UOContent/Gumps/Props/SetGump.cs index ba2f95b0f..58bba761c 100644 --- a/Projects/UOContent/Gumps/Props/SetGump.cs +++ b/Projects/UOContent/Gumps/Props/SetGump.cs @@ -1,281 +1,301 @@ -using System.Collections.Generic; -using System.Reflection; -using Server.Commands; -using Server.HuePickers; -using Server.Network; - -namespace Server.Gumps -{ - public class SetGump : Gump - { - public static readonly bool OldStyle = PropsConfig.OldStyle; - - public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; - public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; - - public static readonly int TextHue = PropsConfig.TextHue; - public static readonly int TextOffsetX = PropsConfig.TextOffsetX; - - public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; - public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; - public static readonly int EntryGumpID = PropsConfig.EntryGumpID; - public static readonly int BackGumpID = PropsConfig.BackGumpID; - public static readonly int SetGumpID = PropsConfig.SetGumpID; - - public static readonly int SetWidth = PropsConfig.SetWidth; - public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY; - public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; - public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; - - public static readonly int PrevWidth = PropsConfig.PrevWidth; - public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY; - public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; - public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; - - public static readonly int NextWidth = PropsConfig.NextWidth; - public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY; - public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; - public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; - - public static readonly int OffsetSize = PropsConfig.OffsetSize; - - public static readonly int EntryHeight = PropsConfig.EntryHeight; - public static readonly int BorderSize = PropsConfig.BorderSize; - - private static readonly int EntryWidth = 212; - - private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize; - private static readonly int TotalHeight = OffsetSize + 2 * (EntryHeight + OffsetSize); - - private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; - private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize; - private readonly List m_List; - private readonly Mobile m_Mobile; - private readonly object m_Object; - private readonly int m_Page; - private readonly PropertyInfo m_Property; - private readonly Stack m_Stack; - - public SetGump(PropertyInfo prop, Mobile mobile, object o, Stack stack, int page, List list) : base( - GumpOffsetX, GumpOffsetY) - { - m_Property = prop; - m_Mobile = mobile; - m_Object = o; - m_Stack = stack; - m_Page = page; - m_List = list; - - bool canNull = !prop.PropertyType.IsValueType; - bool canDye = prop.IsDefined(typeof(HueAttribute), false); - bool isBody = prop.IsDefined(typeof(BodyAttribute), false); - - object val = prop.GetValue(m_Object, null); - string initialText = val switch - { - null => "", - TextDefinition definition => definition.GetValue(), - _ => val.ToString() - }; - - AddPage(0); - - AddBackground(0, 0, BackWidth, - BackHeight + (canNull ? EntryHeight + OffsetSize : 0) + (canDye ? EntryHeight + OffsetSize : 0) + - (isBody ? EntryHeight + OffsetSize : 0), BackGumpID); - AddImageTiled(BorderSize, BorderSize, TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), - TotalHeight + (canNull ? EntryHeight + OffsetSize : 0) + (canDye ? EntryHeight + OffsetSize : 0) + - (isBody ? EntryHeight + OffsetSize : 0), OffsetGumpID); - - int x = BorderSize + OffsetSize; - int y = BorderSize + OffsetSize; - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, prop.Name); - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - - x = BorderSize + OffsetSize; - y += EntryHeight + OffsetSize; - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddTextEntry(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, 0, initialText); - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - - AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 1); - - if (canNull) - { - x = BorderSize + OffsetSize; - y += EntryHeight + OffsetSize; - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Null"); - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - - AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 2); - } - - if (canDye) - { - x = BorderSize + OffsetSize; - y += EntryHeight + OffsetSize; - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Hue Picker"); - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - - AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 3); - } - - if (isBody) - { - x = BorderSize + OffsetSize; - y += EntryHeight + OffsetSize; - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Body Picker"); - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - - AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 4); - } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - object toSet; - bool shouldSet, shouldSend = true; - - switch (info.ButtonID) - { - case 1: - { - TextRelay text = info.GetTextEntry(0); - - if (text != null) - { - try - { - toSet = PropertiesGump.GetObjectFromString(m_Property.PropertyType, text.Text); - shouldSet = true; - } - catch - { - toSet = null; - shouldSet = false; - m_Mobile.SendMessage("Bad format"); - } - } - else - { - toSet = null; - shouldSet = false; - } - - break; - } - case 2: // Null - { - toSet = null; - shouldSet = true; - - break; - } - case 3: // Hue Picker - { - toSet = null; - shouldSet = false; - shouldSend = false; - - m_Mobile.SendHuePicker(new InternalPicker(m_Property, m_Mobile, m_Object, m_Stack, m_Page, m_List)); - - break; - } - case 4: // Body Picker - { - toSet = null; - shouldSet = false; - shouldSend = false; - - m_Mobile.SendGump(new SetBodyGump(m_Property, m_Mobile, m_Object, m_Stack, m_Page, m_List)); - - break; - } - default: - { - toSet = null; - shouldSet = false; - - break; - } - } - - if (shouldSet) - try - { - CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, - toSet?.ToString() ?? "(null)"); - m_Property.SetValue(m_Object, toSet, null); - PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); - } - catch - { - m_Mobile.SendMessage("An exception was caught. The property may not have changed."); - } - - if (shouldSend) - m_Mobile.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); - } - - private class InternalPicker : HuePicker - { - private readonly List m_List; - private readonly Mobile m_Mobile; - private readonly object m_Object; - private readonly int m_Page; - private readonly PropertyInfo m_Property; - private readonly Stack m_Stack; - - public InternalPicker(PropertyInfo prop, Mobile mobile, object o, Stack stack, int page, - List list) : base(((IHued)o).HuedItemID) - { - m_Property = prop; - m_Mobile = mobile; - m_Object = o; - m_Stack = stack; - m_Page = page; - m_List = list; - } - - public override void OnResponse(int hue) - { - try - { - CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, hue.ToString()); - m_Property.SetValue(m_Object, hue, null); - PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); - } - catch - { - m_Mobile.SendMessage("An exception was caught. The property may not have changed."); - } - - m_Mobile.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); - } - } - } -} +using System.Collections.Generic; +using System.Reflection; +using Server.Commands; +using Server.HuePickers; +using Server.Network; + +namespace Server.Gumps +{ + public class SetGump : Gump + { + public static readonly bool OldStyle = PropsConfig.OldStyle; + + public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; + public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; + + public static readonly int TextHue = PropsConfig.TextHue; + public static readonly int TextOffsetX = PropsConfig.TextOffsetX; + + public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; + public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; + public static readonly int EntryGumpID = PropsConfig.EntryGumpID; + public static readonly int BackGumpID = PropsConfig.BackGumpID; + public static readonly int SetGumpID = PropsConfig.SetGumpID; + + public static readonly int SetWidth = PropsConfig.SetWidth; + public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY; + public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; + public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; + + public static readonly int PrevWidth = PropsConfig.PrevWidth; + public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY; + public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; + public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; + + public static readonly int NextWidth = PropsConfig.NextWidth; + public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY; + public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; + public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; + + public static readonly int OffsetSize = PropsConfig.OffsetSize; + + public static readonly int EntryHeight = PropsConfig.EntryHeight; + public static readonly int BorderSize = PropsConfig.BorderSize; + + private static readonly int EntryWidth = 212; + + private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize; + private static readonly int TotalHeight = OffsetSize + 2 * (EntryHeight + OffsetSize); + + private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; + private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize; + private readonly List m_List; + private readonly Mobile m_Mobile; + private readonly object m_Object; + private readonly int m_Page; + private readonly PropertyInfo m_Property; + private readonly Stack m_Stack; + + public SetGump( + PropertyInfo prop, Mobile mobile, object o, Stack stack, int page, List list + ) : base( + GumpOffsetX, + GumpOffsetY + ) + { + m_Property = prop; + m_Mobile = mobile; + m_Object = o; + m_Stack = stack; + m_Page = page; + m_List = list; + + var canNull = !prop.PropertyType.IsValueType; + var canDye = prop.IsDefined(typeof(HueAttribute), false); + var isBody = prop.IsDefined(typeof(BodyAttribute), false); + + var val = prop.GetValue(m_Object, null); + var initialText = val switch + { + null => "", + TextDefinition definition => definition.GetValue(), + _ => val.ToString() + }; + + AddPage(0); + + AddBackground( + 0, + 0, + BackWidth, + BackHeight + (canNull ? EntryHeight + OffsetSize : 0) + (canDye ? EntryHeight + OffsetSize : 0) + + (isBody ? EntryHeight + OffsetSize : 0), + BackGumpID + ); + AddImageTiled( + BorderSize, + BorderSize, + TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), + TotalHeight + (canNull ? EntryHeight + OffsetSize : 0) + (canDye ? EntryHeight + OffsetSize : 0) + + (isBody ? EntryHeight + OffsetSize : 0), + OffsetGumpID + ); + + var x = BorderSize + OffsetSize; + var y = BorderSize + OffsetSize; + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, prop.Name); + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + + x = BorderSize + OffsetSize; + y += EntryHeight + OffsetSize; + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddTextEntry(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, 0, initialText); + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + + AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 1); + + if (canNull) + { + x = BorderSize + OffsetSize; + y += EntryHeight + OffsetSize; + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Null"); + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + + AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 2); + } + + if (canDye) + { + x = BorderSize + OffsetSize; + y += EntryHeight + OffsetSize; + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Hue Picker"); + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + + AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 3); + } + + if (isBody) + { + x = BorderSize + OffsetSize; + y += EntryHeight + OffsetSize; + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Body Picker"); + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + + AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 4); + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + object toSet; + bool shouldSet, shouldSend = true; + + switch (info.ButtonID) + { + case 1: + { + var text = info.GetTextEntry(0); + + if (text != null) + { + try + { + toSet = PropertiesGump.GetObjectFromString(m_Property.PropertyType, text.Text); + shouldSet = true; + } + catch + { + toSet = null; + shouldSet = false; + m_Mobile.SendMessage("Bad format"); + } + } + else + { + toSet = null; + shouldSet = false; + } + + break; + } + case 2: // Null + { + toSet = null; + shouldSet = true; + + break; + } + case 3: // Hue Picker + { + toSet = null; + shouldSet = false; + shouldSend = false; + + m_Mobile.SendHuePicker(new InternalPicker(m_Property, m_Mobile, m_Object, m_Stack, m_Page, m_List)); + + break; + } + case 4: // Body Picker + { + toSet = null; + shouldSet = false; + shouldSend = false; + + m_Mobile.SendGump(new SetBodyGump(m_Property, m_Mobile, m_Object, m_Stack, m_Page, m_List)); + + break; + } + default: + { + toSet = null; + shouldSet = false; + + break; + } + } + + if (shouldSet) + try + { + CommandLogging.LogChangeProperty( + m_Mobile, + m_Object, + m_Property.Name, + toSet?.ToString() ?? "(null)" + ); + m_Property.SetValue(m_Object, toSet, null); + PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); + } + catch + { + m_Mobile.SendMessage("An exception was caught. The property may not have changed."); + } + + if (shouldSend) + m_Mobile.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); + } + + private class InternalPicker : HuePicker + { + private readonly List m_List; + private readonly Mobile m_Mobile; + private readonly object m_Object; + private readonly int m_Page; + private readonly PropertyInfo m_Property; + private readonly Stack m_Stack; + + public InternalPicker( + PropertyInfo prop, Mobile mobile, object o, Stack stack, int page, + List list + ) : base(((IHued)o).HuedItemID) + { + m_Property = prop; + m_Mobile = mobile; + m_Object = o; + m_Stack = stack; + m_Page = page; + m_List = list; + } + + public override void OnResponse(int hue) + { + try + { + CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, hue.ToString()); + m_Property.SetValue(m_Object, hue, null); + PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); + } + catch + { + m_Mobile.SendMessage("An exception was caught. The property may not have changed."); + } + + m_Mobile.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); + } + } + } +} diff --git a/Projects/UOContent/Gumps/Props/SetListOptionGump.cs b/Projects/UOContent/Gumps/Props/SetListOptionGump.cs index 898108055..b92588d59 100644 --- a/Projects/UOContent/Gumps/Props/SetListOptionGump.cs +++ b/Projects/UOContent/Gumps/Props/SetListOptionGump.cs @@ -1,186 +1,219 @@ -using System.Collections.Generic; -using System.Reflection; -using Server.Commands; -using Server.Network; - -namespace Server.Gumps -{ - public class SetListOptionGump : Gump - { - public static readonly bool OldStyle = PropsConfig.OldStyle; - - public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; - public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; - - public static readonly int TextHue = PropsConfig.TextHue; - public static readonly int TextOffsetX = PropsConfig.TextOffsetX; - - public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; - public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; - public static readonly int EntryGumpID = PropsConfig.EntryGumpID; - public static readonly int BackGumpID = PropsConfig.BackGumpID; - public static readonly int SetGumpID = PropsConfig.SetGumpID; - - public static readonly int SetWidth = PropsConfig.SetWidth; - public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY; - public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; - public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; - - public static readonly int PrevWidth = PropsConfig.PrevWidth; - public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY; - public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; - public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; - - public static readonly int NextWidth = PropsConfig.NextWidth; - public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY; - public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; - public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; - - public static readonly int OffsetSize = PropsConfig.OffsetSize; - - public static readonly int EntryHeight = PropsConfig.EntryHeight; - public static readonly int BorderSize = PropsConfig.BorderSize; - - private static readonly int EntryWidth = 212; - private static readonly int EntryCount = 13; - - private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize; - - private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; - - private static readonly bool PrevLabel = OldStyle; - private static readonly bool NextLabel = OldStyle; - - private static readonly int PrevLabelOffsetX = PrevWidth + 1; - private static readonly int PrevLabelOffsetY = 0; - - private static readonly int NextLabelOffsetX = -29; - private static readonly int NextLabelOffsetY = 0; - protected List m_List; - protected Mobile m_Mobile; - protected object m_Object; - protected int m_Page; - protected PropertyInfo m_Property; - protected Stack m_Stack; - - private readonly object[] m_Values; - - public SetListOptionGump(PropertyInfo prop, Mobile mobile, object o, Stack stack, int propspage, - List list, string[] names, object[] values) : base(GumpOffsetX, GumpOffsetY) - { - m_Property = prop; - m_Mobile = mobile; - m_Object = o; - m_Stack = stack; - m_Page = propspage; - m_List = list; - - m_Values = values; - - int pages = (names.Length + EntryCount - 1) / EntryCount; - int index = 0; - - for (int page = 1; page <= pages; ++page) - { - AddPage(page); - - int start = (page - 1) * EntryCount; - int count = names.Length - start; - - if (count > EntryCount) - count = EntryCount; - - int totalHeight = OffsetSize + (count + 2) * (EntryHeight + OffsetSize); - int backHeight = BorderSize + totalHeight + BorderSize; - - AddBackground(0, 0, BackWidth, backHeight, BackGumpID); - AddImageTiled(BorderSize, BorderSize, TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), totalHeight, - OffsetGumpID); - - int x = BorderSize + OffsetSize; - int y = BorderSize + OffsetSize; - - int emptyWidth = TotalWidth - PrevWidth - NextWidth - OffsetSize * 4 - - (OldStyle ? SetWidth + OffsetSize : 0); - - AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); - - if (page > 1) - { - AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 0, GumpButtonType.Page, - page - 1); - - if (PrevLabel) - AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous"); - } - - x += PrevWidth + OffsetSize; - - if (!OldStyle) - AddImageTiled(x - (OldStyle ? OffsetSize : 0), y, emptyWidth + (OldStyle ? OffsetSize * 2 : 0), - EntryHeight, HeaderGumpID); - - x += emptyWidth + OffsetSize; - - if (!OldStyle) - AddImageTiled(x, y, NextWidth, EntryHeight, HeaderGumpID); - - if (page < pages) - { - AddButton(x + NextOffsetX, y + NextOffsetY, NextButtonID1, NextButtonID2, 0, GumpButtonType.Page, - page + 1); - - if (NextLabel) - AddLabel(x + NextLabelOffsetX, y + NextLabelOffsetY, TextHue, "Next"); - } - - AddRect(0, prop.Name, 0); - - for (int i = 0; i < count; ++i) - AddRect(i + 1, names[index], ++index); - } - } - - private void AddRect(int index, string str, int button) - { - int x = BorderSize + OffsetSize; - int y = BorderSize + OffsetSize + (index + 1) * (EntryHeight + OffsetSize); - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, str); - - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - - if (button != 0) - AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, button); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - int index = info.ButtonID - 1; - - if (index >= 0 && index < m_Values.Length) - try - { - object toSet = m_Values[index]; - - string result = Properties.SetDirect(m_Mobile, m_Object, m_Object, m_Property, m_Property.Name, toSet, - true); - - m_Mobile.SendMessage(result); - - if (result == "Property has been set.") - PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); - } - catch - { - m_Mobile.SendMessage("An exception was caught. The property may not have changed."); - } - - m_Mobile.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); - } - } -} +using System.Collections.Generic; +using System.Reflection; +using Server.Commands; +using Server.Network; + +namespace Server.Gumps +{ + public class SetListOptionGump : Gump + { + public static readonly bool OldStyle = PropsConfig.OldStyle; + + public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; + public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; + + public static readonly int TextHue = PropsConfig.TextHue; + public static readonly int TextOffsetX = PropsConfig.TextOffsetX; + + public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; + public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; + public static readonly int EntryGumpID = PropsConfig.EntryGumpID; + public static readonly int BackGumpID = PropsConfig.BackGumpID; + public static readonly int SetGumpID = PropsConfig.SetGumpID; + + public static readonly int SetWidth = PropsConfig.SetWidth; + public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY; + public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; + public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; + + public static readonly int PrevWidth = PropsConfig.PrevWidth; + public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY; + public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; + public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; + + public static readonly int NextWidth = PropsConfig.NextWidth; + public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY; + public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; + public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; + + public static readonly int OffsetSize = PropsConfig.OffsetSize; + + public static readonly int EntryHeight = PropsConfig.EntryHeight; + public static readonly int BorderSize = PropsConfig.BorderSize; + + private static readonly int EntryWidth = 212; + private static readonly int EntryCount = 13; + + private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize; + + private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; + + private static readonly bool PrevLabel = OldStyle; + private static readonly bool NextLabel = OldStyle; + + private static readonly int PrevLabelOffsetX = PrevWidth + 1; + private static readonly int PrevLabelOffsetY = 0; + + private static readonly int NextLabelOffsetX = -29; + private static readonly int NextLabelOffsetY = 0; + + private readonly object[] m_Values; + protected List m_List; + protected Mobile m_Mobile; + protected object m_Object; + protected int m_Page; + protected PropertyInfo m_Property; + protected Stack m_Stack; + + public SetListOptionGump( + PropertyInfo prop, Mobile mobile, object o, Stack stack, int propspage, + List list, string[] names, object[] values + ) : base(GumpOffsetX, GumpOffsetY) + { + m_Property = prop; + m_Mobile = mobile; + m_Object = o; + m_Stack = stack; + m_Page = propspage; + m_List = list; + + m_Values = values; + + var pages = (names.Length + EntryCount - 1) / EntryCount; + var index = 0; + + for (var page = 1; page <= pages; ++page) + { + AddPage(page); + + var start = (page - 1) * EntryCount; + var count = names.Length - start; + + if (count > EntryCount) + count = EntryCount; + + var totalHeight = OffsetSize + (count + 2) * (EntryHeight + OffsetSize); + var backHeight = BorderSize + totalHeight + BorderSize; + + AddBackground(0, 0, BackWidth, backHeight, BackGumpID); + AddImageTiled( + BorderSize, + BorderSize, + TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), + totalHeight, + OffsetGumpID + ); + + var x = BorderSize + OffsetSize; + var y = BorderSize + OffsetSize; + + var emptyWidth = TotalWidth - PrevWidth - NextWidth - OffsetSize * 4 - + (OldStyle ? SetWidth + OffsetSize : 0); + + AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); + + if (page > 1) + { + AddButton( + x + PrevOffsetX, + y + PrevOffsetY, + PrevButtonID1, + PrevButtonID2, + 0, + GumpButtonType.Page, + page - 1 + ); + + if (PrevLabel) + AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous"); + } + + x += PrevWidth + OffsetSize; + + if (!OldStyle) + AddImageTiled( + x - (OldStyle ? OffsetSize : 0), + y, + emptyWidth + (OldStyle ? OffsetSize * 2 : 0), + EntryHeight, + HeaderGumpID + ); + + x += emptyWidth + OffsetSize; + + if (!OldStyle) + AddImageTiled(x, y, NextWidth, EntryHeight, HeaderGumpID); + + if (page < pages) + { + AddButton( + x + NextOffsetX, + y + NextOffsetY, + NextButtonID1, + NextButtonID2, + 0, + GumpButtonType.Page, + page + 1 + ); + + if (NextLabel) + AddLabel(x + NextLabelOffsetX, y + NextLabelOffsetY, TextHue, "Next"); + } + + AddRect(0, prop.Name, 0); + + for (var i = 0; i < count; ++i) + AddRect(i + 1, names[index], ++index); + } + } + + private void AddRect(int index, string str, int button) + { + var x = BorderSize + OffsetSize; + var y = BorderSize + OffsetSize + (index + 1) * (EntryHeight + OffsetSize); + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, str); + + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + + if (button != 0) + AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, button); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var index = info.ButtonID - 1; + + if (index >= 0 && index < m_Values.Length) + try + { + var toSet = m_Values[index]; + + var result = Properties.SetDirect( + m_Mobile, + m_Object, + m_Object, + m_Property, + m_Property.Name, + toSet, + true + ); + + m_Mobile.SendMessage(result); + + if (result == "Property has been set.") + PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); + } + catch + { + m_Mobile.SendMessage("An exception was caught. The property may not have changed."); + } + + m_Mobile.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); + } + } +} diff --git a/Projects/UOContent/Gumps/Props/SetObjectGump.cs b/Projects/UOContent/Gumps/Props/SetObjectGump.cs index 348c20726..214cbfd99 100644 --- a/Projects/UOContent/Gumps/Props/SetObjectGump.cs +++ b/Projects/UOContent/Gumps/Props/SetObjectGump.cs @@ -1,266 +1,298 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using Server.Commands; -using Server.Commands.Generic; -using Server.Network; -using Server.Prompts; - -namespace Server.Gumps -{ - public class SetObjectGump : Gump - { - public static readonly bool OldStyle = PropsConfig.OldStyle; - - public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; - public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; - - public static readonly int TextHue = PropsConfig.TextHue; - public static readonly int TextOffsetX = PropsConfig.TextOffsetX; - - public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; - public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; - public static readonly int EntryGumpID = PropsConfig.EntryGumpID; - public static readonly int BackGumpID = PropsConfig.BackGumpID; - public static readonly int SetGumpID = PropsConfig.SetGumpID; - - public static readonly int SetWidth = PropsConfig.SetWidth; - public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY; - public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; - public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; - - public static readonly int PrevWidth = PropsConfig.PrevWidth; - public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY; - public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; - public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; - - public static readonly int NextWidth = PropsConfig.NextWidth; - public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY; - public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; - public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; - - public static readonly int OffsetSize = PropsConfig.OffsetSize; - - public static readonly int EntryHeight = PropsConfig.EntryHeight; - public static readonly int BorderSize = PropsConfig.BorderSize; - - private static readonly int EntryWidth = 212; - - private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize; - private static readonly int TotalHeight = OffsetSize + 5 * (EntryHeight + OffsetSize); - - private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; - private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize; - private readonly List m_List; - private readonly Mobile m_Mobile; - private readonly object m_Object; - private readonly int m_Page; - private readonly PropertyInfo m_Property; - private readonly Stack m_Stack; - private readonly Type m_Type; - - public SetObjectGump(PropertyInfo prop, Mobile mobile, object o, Stack stack, Type type, int page, - List list) : base(GumpOffsetX, GumpOffsetY) - { - m_Property = prop; - m_Mobile = mobile; - m_Object = o; - m_Stack = stack; - m_Type = type; - m_Page = page; - m_List = list; - - string initialText = PropertiesGump.ValueToString(o, prop); - - AddPage(0); - - AddBackground(0, 0, BackWidth, BackHeight, BackGumpID); - AddImageTiled(BorderSize, BorderSize, TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), TotalHeight, - OffsetGumpID); - - int x = BorderSize + OffsetSize; - int y = BorderSize + OffsetSize; - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, prop.Name); - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - - x = BorderSize + OffsetSize; - y += EntryHeight + OffsetSize; - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, initialText); - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - - AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 1); - - x = BorderSize + OffsetSize; - y += EntryHeight + OffsetSize; - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Change by Serial"); - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - - AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 2); - - x = BorderSize + OffsetSize; - y += EntryHeight + OffsetSize; - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Nullify"); - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - - AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 3); - - x = BorderSize + OffsetSize; - y += EntryHeight + OffsetSize; - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "View Properties"); - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - - AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 4); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - bool shouldSend = true; - object viewProps = null; - - switch (info.ButtonID) - { - case 0: // closed - { - m_Mobile.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); - shouldSend = false; - break; - } - case 1: // Change by Target - { - m_Mobile.Target = new SetObjectTarget(m_Property, m_Mobile, m_Object, m_Stack, m_Type, m_Page, m_List); - shouldSend = false; - break; - } - case 2: // Change by Serial - { - shouldSend = false; - - m_Mobile.SendMessage("Enter the serial you wish to find:"); - m_Mobile.Prompt = new InternalPrompt(m_Property, m_Mobile, m_Object, m_Stack, m_Type, m_Page, m_List); - - break; - } - case 3: // Nullify - { - try - { - CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, "(null)"); - m_Property.SetValue(m_Object, null, null); - PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); - } - catch - { - m_Mobile.SendMessage("An exception was caught. The property may not have changed."); - } - break; - } - case 4: // View Properties - { - object obj = m_Property.GetValue(m_Object, null); - - if (obj == null) - m_Mobile.SendMessage("The property is null and so you cannot view its properties."); - else if (!BaseCommand.IsAccessible(m_Mobile, obj)) - m_Mobile.SendMessage("You may not view their properties."); - else - viewProps = obj; - - break; - } - } - - if (shouldSend) - m_Mobile.SendGump(new SetObjectGump(m_Property, m_Mobile, m_Object, m_Stack, m_Type, m_Page, m_List)); - - if (viewProps != null) - m_Mobile.SendGump(new PropertiesGump(m_Mobile, viewProps)); - } - - private class InternalPrompt : Prompt - { - private readonly List m_List; - private readonly Mobile m_Mobile; - private readonly object m_Object; - private readonly int m_Page; - private readonly PropertyInfo m_Property; - private readonly Stack m_Stack; - private readonly Type m_Type; - - public InternalPrompt(PropertyInfo prop, Mobile mobile, object o, Stack stack, Type type, int page, - List list) - { - m_Property = prop; - m_Mobile = mobile; - m_Object = o; - m_Stack = stack; - m_Type = type; - m_Page = page; - m_List = list; - } - - public override void OnCancel(Mobile from) - { - m_Mobile.SendGump(new SetObjectGump(m_Property, m_Mobile, m_Object, m_Stack, m_Type, m_Page, m_List)); - } - - public override void OnResponse(Mobile from, string text) - { - try - { - uint serial = Utility.ToUInt32(text); - - IEntity toSet = World.FindEntity(serial); - - if (toSet == null) - m_Mobile.SendMessage("No object with that serial was found."); - else if (!m_Type.IsInstanceOfType(toSet)) - m_Mobile.SendMessage("The object with that serial could not be assigned to a property of type : {0}", - m_Type.Name); - else - try - { - CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, - toSet.ToString()); - m_Property.SetValue(m_Object, toSet, null); - PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); - } - catch - { - m_Mobile.SendMessage("An exception was caught. The property may not have changed."); - } - } - catch - { - m_Mobile.SendMessage("Bad format"); - } - - m_Mobile.SendGump(new SetObjectGump(m_Property, m_Mobile, m_Object, m_Stack, m_Type, m_Page, m_List)); - } - } - } -} +using System; +using System.Collections.Generic; +using System.Reflection; +using Server.Commands; +using Server.Commands.Generic; +using Server.Network; +using Server.Prompts; + +namespace Server.Gumps +{ + public class SetObjectGump : Gump + { + public static readonly bool OldStyle = PropsConfig.OldStyle; + + public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; + public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; + + public static readonly int TextHue = PropsConfig.TextHue; + public static readonly int TextOffsetX = PropsConfig.TextOffsetX; + + public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; + public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; + public static readonly int EntryGumpID = PropsConfig.EntryGumpID; + public static readonly int BackGumpID = PropsConfig.BackGumpID; + public static readonly int SetGumpID = PropsConfig.SetGumpID; + + public static readonly int SetWidth = PropsConfig.SetWidth; + public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY; + public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; + public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; + + public static readonly int PrevWidth = PropsConfig.PrevWidth; + public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY; + public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; + public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; + + public static readonly int NextWidth = PropsConfig.NextWidth; + public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY; + public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; + public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; + + public static readonly int OffsetSize = PropsConfig.OffsetSize; + + public static readonly int EntryHeight = PropsConfig.EntryHeight; + public static readonly int BorderSize = PropsConfig.BorderSize; + + private static readonly int EntryWidth = 212; + + private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize; + private static readonly int TotalHeight = OffsetSize + 5 * (EntryHeight + OffsetSize); + + private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; + private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize; + private readonly List m_List; + private readonly Mobile m_Mobile; + private readonly object m_Object; + private readonly int m_Page; + private readonly PropertyInfo m_Property; + private readonly Stack m_Stack; + private readonly Type m_Type; + + public SetObjectGump( + PropertyInfo prop, Mobile mobile, object o, Stack stack, Type type, int page, + List list + ) : base(GumpOffsetX, GumpOffsetY) + { + m_Property = prop; + m_Mobile = mobile; + m_Object = o; + m_Stack = stack; + m_Type = type; + m_Page = page; + m_List = list; + + var initialText = PropertiesGump.ValueToString(o, prop); + + AddPage(0); + + AddBackground(0, 0, BackWidth, BackHeight, BackGumpID); + AddImageTiled( + BorderSize, + BorderSize, + TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), + TotalHeight, + OffsetGumpID + ); + + var x = BorderSize + OffsetSize; + var y = BorderSize + OffsetSize; + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, prop.Name); + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + + x = BorderSize + OffsetSize; + y += EntryHeight + OffsetSize; + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, initialText); + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + + AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 1); + + x = BorderSize + OffsetSize; + y += EntryHeight + OffsetSize; + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Change by Serial"); + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + + AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 2); + + x = BorderSize + OffsetSize; + y += EntryHeight + OffsetSize; + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Nullify"); + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + + AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 3); + + x = BorderSize + OffsetSize; + y += EntryHeight + OffsetSize; + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "View Properties"); + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + + AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 4); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var shouldSend = true; + object viewProps = null; + + switch (info.ButtonID) + { + case 0: // closed + { + m_Mobile.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); + shouldSend = false; + break; + } + case 1: // Change by Target + { + m_Mobile.Target = new SetObjectTarget( + m_Property, + m_Mobile, + m_Object, + m_Stack, + m_Type, + m_Page, + m_List + ); + shouldSend = false; + break; + } + case 2: // Change by Serial + { + shouldSend = false; + + m_Mobile.SendMessage("Enter the serial you wish to find:"); + m_Mobile.Prompt = new InternalPrompt( + m_Property, + m_Mobile, + m_Object, + m_Stack, + m_Type, + m_Page, + m_List + ); + + break; + } + case 3: // Nullify + { + try + { + CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, "(null)"); + m_Property.SetValue(m_Object, null, null); + PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); + } + catch + { + m_Mobile.SendMessage("An exception was caught. The property may not have changed."); + } + + break; + } + case 4: // View Properties + { + var obj = m_Property.GetValue(m_Object, null); + + if (obj == null) + m_Mobile.SendMessage("The property is null and so you cannot view its properties."); + else if (!BaseCommand.IsAccessible(m_Mobile, obj)) + m_Mobile.SendMessage("You may not view their properties."); + else + viewProps = obj; + + break; + } + } + + if (shouldSend) + m_Mobile.SendGump(new SetObjectGump(m_Property, m_Mobile, m_Object, m_Stack, m_Type, m_Page, m_List)); + + if (viewProps != null) + m_Mobile.SendGump(new PropertiesGump(m_Mobile, viewProps)); + } + + private class InternalPrompt : Prompt + { + private readonly List m_List; + private readonly Mobile m_Mobile; + private readonly object m_Object; + private readonly int m_Page; + private readonly PropertyInfo m_Property; + private readonly Stack m_Stack; + private readonly Type m_Type; + + public InternalPrompt( + PropertyInfo prop, Mobile mobile, object o, Stack stack, Type type, int page, + List list + ) + { + m_Property = prop; + m_Mobile = mobile; + m_Object = o; + m_Stack = stack; + m_Type = type; + m_Page = page; + m_List = list; + } + + public override void OnCancel(Mobile from) + { + m_Mobile.SendGump(new SetObjectGump(m_Property, m_Mobile, m_Object, m_Stack, m_Type, m_Page, m_List)); + } + + public override void OnResponse(Mobile from, string text) + { + try + { + var serial = Utility.ToUInt32(text); + + var toSet = World.FindEntity(serial); + + if (toSet == null) + m_Mobile.SendMessage("No object with that serial was found."); + else if (!m_Type.IsInstanceOfType(toSet)) + m_Mobile.SendMessage( + "The object with that serial could not be assigned to a property of type : {0}", + m_Type.Name + ); + else + try + { + CommandLogging.LogChangeProperty( + m_Mobile, + m_Object, + m_Property.Name, + toSet.ToString() + ); + m_Property.SetValue(m_Object, toSet, null); + PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); + } + catch + { + m_Mobile.SendMessage("An exception was caught. The property may not have changed."); + } + } + catch + { + m_Mobile.SendMessage("Bad format"); + } + + m_Mobile.SendGump(new SetObjectGump(m_Property, m_Mobile, m_Object, m_Stack, m_Type, m_Page, m_List)); + } + } + } +} diff --git a/Projects/UOContent/Gumps/Props/SetObjectTarget.cs b/Projects/UOContent/Gumps/Props/SetObjectTarget.cs index 568582130..c7666eef3 100644 --- a/Projects/UOContent/Gumps/Props/SetObjectTarget.cs +++ b/Projects/UOContent/Gumps/Props/SetObjectTarget.cs @@ -1,67 +1,69 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using Server.Commands; -using Server.Items; -using Server.Targeting; - -namespace Server.Gumps -{ - public class SetObjectTarget : Target - { - private readonly List m_List; - private readonly Mobile m_Mobile; - private readonly object m_Object; - private readonly int m_Page; - private readonly PropertyInfo m_Property; - private readonly Stack m_Stack; - private readonly Type m_Type; - - public SetObjectTarget(PropertyInfo prop, Mobile mobile, object o, Stack stack, Type type, int page, - List list) : base(-1, false, TargetFlags.None) - { - m_Property = prop; - m_Mobile = mobile; - m_Object = o; - m_Stack = stack; - m_Type = type; - m_Page = page; - m_List = list; - } - - protected override void OnTarget(Mobile from, object targeted) - { - try - { - if (m_Type == typeof(Type)) - targeted = targeted.GetType(); - else if ((m_Type == typeof(BaseAddon) || m_Type.IsAssignableFrom(typeof(BaseAddon))) && - targeted is AddonComponent addonComponent) - targeted = addonComponent.Addon; - - if (m_Type.IsInstanceOfType(targeted)) - { - CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, targeted.ToString()); - m_Property.SetValue(m_Object, targeted, null); - PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); - } - else - { - m_Mobile.SendMessage("That cannot be assigned to a property of type : {0}", m_Type.Name); - } - } - catch - { - m_Mobile.SendMessage("An exception was caught. The property may not have changed."); - } - } - - protected override void OnTargetFinish(Mobile from) - { - if (m_Type == typeof(Type)) - from.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); - else - from.SendGump(new SetObjectGump(m_Property, m_Mobile, m_Object, m_Stack, m_Type, m_Page, m_List)); - } - } -} \ No newline at end of file +using System; +using System.Collections.Generic; +using System.Reflection; +using Server.Commands; +using Server.Items; +using Server.Targeting; + +namespace Server.Gumps +{ + public class SetObjectTarget : Target + { + private readonly List m_List; + private readonly Mobile m_Mobile; + private readonly object m_Object; + private readonly int m_Page; + private readonly PropertyInfo m_Property; + private readonly Stack m_Stack; + private readonly Type m_Type; + + public SetObjectTarget( + PropertyInfo prop, Mobile mobile, object o, Stack stack, Type type, int page, + List list + ) : base(-1, false, TargetFlags.None) + { + m_Property = prop; + m_Mobile = mobile; + m_Object = o; + m_Stack = stack; + m_Type = type; + m_Page = page; + m_List = list; + } + + protected override void OnTarget(Mobile from, object targeted) + { + try + { + if (m_Type == typeof(Type)) + targeted = targeted.GetType(); + else if ((m_Type == typeof(BaseAddon) || m_Type.IsAssignableFrom(typeof(BaseAddon))) && + targeted is AddonComponent addonComponent) + targeted = addonComponent.Addon; + + if (m_Type.IsInstanceOfType(targeted)) + { + CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, targeted.ToString()); + m_Property.SetValue(m_Object, targeted, null); + PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); + } + else + { + m_Mobile.SendMessage("That cannot be assigned to a property of type : {0}", m_Type.Name); + } + } + catch + { + m_Mobile.SendMessage("An exception was caught. The property may not have changed."); + } + } + + protected override void OnTargetFinish(Mobile from) + { + if (m_Type == typeof(Type)) + from.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); + else + from.SendGump(new SetObjectGump(m_Property, m_Mobile, m_Object, m_Stack, m_Type, m_Page, m_List)); + } + } +} diff --git a/Projects/UOContent/Gumps/Props/SetPoint2DGump.cs b/Projects/UOContent/Gumps/Props/SetPoint2DGump.cs index 7c650f031..95cd0ecb6 100644 --- a/Projects/UOContent/Gumps/Props/SetPoint2DGump.cs +++ b/Projects/UOContent/Gumps/Props/SetPoint2DGump.cs @@ -1,231 +1,243 @@ -using System.Collections.Generic; -using System.Reflection; -using Server.Commands; -using Server.Network; -using Server.Targeting; - -namespace Server.Gumps -{ - public class SetPoint2DGump : Gump - { - public static readonly bool OldStyle = PropsConfig.OldStyle; - - public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; - public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; - - public static readonly int TextHue = PropsConfig.TextHue; - public static readonly int TextOffsetX = PropsConfig.TextOffsetX; - - public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; - public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; - public static readonly int EntryGumpID = PropsConfig.EntryGumpID; - public static readonly int BackGumpID = PropsConfig.BackGumpID; - public static readonly int SetGumpID = PropsConfig.SetGumpID; - - public static readonly int SetWidth = PropsConfig.SetWidth; - public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY; - public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; - public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; - - public static readonly int PrevWidth = PropsConfig.PrevWidth; - public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY; - public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; - public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; - - public static readonly int NextWidth = PropsConfig.NextWidth; - public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY; - public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; - public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; - - public static readonly int OffsetSize = PropsConfig.OffsetSize; - - public static readonly int EntryHeight = PropsConfig.EntryHeight; - public static readonly int BorderSize = PropsConfig.BorderSize; - - private static readonly int CoordWidth = 105; - private static readonly int EntryWidth = CoordWidth + OffsetSize + CoordWidth; - - private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize; - private static readonly int TotalHeight = OffsetSize + 4 * (EntryHeight + OffsetSize); - - private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; - private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize; - private readonly List m_List; - private readonly Mobile m_Mobile; - private readonly object m_Object; - private readonly int m_Page; - private readonly PropertyInfo m_Property; - private readonly Stack m_Stack; - - public SetPoint2DGump(PropertyInfo prop, Mobile mobile, object o, Stack stack, int page, List list) - : base(GumpOffsetX, GumpOffsetY) - { - m_Property = prop; - m_Mobile = mobile; - m_Object = o; - m_Stack = stack; - m_Page = page; - m_List = list; - - Point2D p = (Point2D)prop.GetValue(o, null); - - AddPage(0); - - AddBackground(0, 0, BackWidth, BackHeight, BackGumpID); - AddImageTiled(BorderSize, BorderSize, TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), TotalHeight, - OffsetGumpID); - - int x = BorderSize + OffsetSize; - int y = BorderSize + OffsetSize; - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, prop.Name); - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - - x = BorderSize + OffsetSize; - y += EntryHeight + OffsetSize; - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Use your location"); - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 1); - - x = BorderSize + OffsetSize; - y += EntryHeight + OffsetSize; - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Target a location"); - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 2); - - x = BorderSize + OffsetSize; - y += EntryHeight + OffsetSize; - - AddImageTiled(x, y, CoordWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, CoordWidth - TextOffsetX, EntryHeight, TextHue, "X:"); - AddTextEntry(x + 16, y, CoordWidth - 16, EntryHeight, TextHue, 0, p.X.ToString()); - x += CoordWidth + OffsetSize; - - AddImageTiled(x, y, CoordWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, CoordWidth - TextOffsetX, EntryHeight, TextHue, "Y:"); - AddTextEntry(x + 16, y, CoordWidth - 16, EntryHeight, TextHue, 1, p.Y.ToString()); - x += CoordWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 3); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - Point2D toSet; - bool shouldSet, shouldSend; - - switch (info.ButtonID) - { - case 1: // Current location - { - toSet = new Point2D(m_Mobile.Location); - shouldSet = true; - shouldSend = true; - - break; - } - case 2: // Pick location - { - m_Mobile.Target = new InternalTarget(m_Property, m_Mobile, m_Object, m_Stack, m_Page, m_List); - - toSet = Point2D.Zero; - shouldSet = false; - shouldSend = false; - - break; - } - case 3: // Use values - { - TextRelay x = info.GetTextEntry(0); - TextRelay y = info.GetTextEntry(1); - - toSet = new Point2D(x == null ? 0 : Utility.ToInt32(x.Text), y == null ? 0 : Utility.ToInt32(y.Text)); - shouldSet = true; - shouldSend = true; - - break; - } - default: - { - toSet = Point2D.Zero; - shouldSet = false; - shouldSend = true; - - break; - } - } - - if (shouldSet) - try - { - CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, toSet.ToString()); - m_Property.SetValue(m_Object, toSet, null); - PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); - } - catch - { - m_Mobile.SendMessage("An exception was caught. The property may not have changed."); - } - - if (shouldSend) - m_Mobile.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); - } - - private class InternalTarget : Target - { - private readonly List m_List; - private readonly Mobile m_Mobile; - private readonly object m_Object; - private readonly int m_Page; - private readonly PropertyInfo m_Property; - private readonly Stack m_Stack; - - public InternalTarget(PropertyInfo prop, Mobile mobile, object o, Stack stack, int page, - List list) : base(-1, true, TargetFlags.None) - { - m_Property = prop; - m_Mobile = mobile; - m_Object = o; - m_Stack = stack; - m_Page = page; - m_List = list; - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is IPoint3D p) - try - { - CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, new Point2D(p).ToString()); - m_Property.SetValue(m_Object, new Point2D(p), null); - PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); - } - catch - { - m_Mobile.SendMessage("An exception was caught. The property may not have changed."); - } - } - - protected override void OnTargetFinish(Mobile from) - { - m_Mobile.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); - } - } - } -} +using System.Collections.Generic; +using System.Reflection; +using Server.Commands; +using Server.Network; +using Server.Targeting; + +namespace Server.Gumps +{ + public class SetPoint2DGump : Gump + { + public static readonly bool OldStyle = PropsConfig.OldStyle; + + public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; + public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; + + public static readonly int TextHue = PropsConfig.TextHue; + public static readonly int TextOffsetX = PropsConfig.TextOffsetX; + + public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; + public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; + public static readonly int EntryGumpID = PropsConfig.EntryGumpID; + public static readonly int BackGumpID = PropsConfig.BackGumpID; + public static readonly int SetGumpID = PropsConfig.SetGumpID; + + public static readonly int SetWidth = PropsConfig.SetWidth; + public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY; + public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; + public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; + + public static readonly int PrevWidth = PropsConfig.PrevWidth; + public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY; + public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; + public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; + + public static readonly int NextWidth = PropsConfig.NextWidth; + public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY; + public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; + public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; + + public static readonly int OffsetSize = PropsConfig.OffsetSize; + + public static readonly int EntryHeight = PropsConfig.EntryHeight; + public static readonly int BorderSize = PropsConfig.BorderSize; + + private static readonly int CoordWidth = 105; + private static readonly int EntryWidth = CoordWidth + OffsetSize + CoordWidth; + + private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize; + private static readonly int TotalHeight = OffsetSize + 4 * (EntryHeight + OffsetSize); + + private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; + private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize; + private readonly List m_List; + private readonly Mobile m_Mobile; + private readonly object m_Object; + private readonly int m_Page; + private readonly PropertyInfo m_Property; + private readonly Stack m_Stack; + + public SetPoint2DGump( + PropertyInfo prop, Mobile mobile, object o, Stack stack, int page, List list + ) + : base(GumpOffsetX, GumpOffsetY) + { + m_Property = prop; + m_Mobile = mobile; + m_Object = o; + m_Stack = stack; + m_Page = page; + m_List = list; + + var p = (Point2D)prop.GetValue(o, null); + + AddPage(0); + + AddBackground(0, 0, BackWidth, BackHeight, BackGumpID); + AddImageTiled( + BorderSize, + BorderSize, + TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), + TotalHeight, + OffsetGumpID + ); + + var x = BorderSize + OffsetSize; + var y = BorderSize + OffsetSize; + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, prop.Name); + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + + x = BorderSize + OffsetSize; + y += EntryHeight + OffsetSize; + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Use your location"); + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 1); + + x = BorderSize + OffsetSize; + y += EntryHeight + OffsetSize; + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Target a location"); + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 2); + + x = BorderSize + OffsetSize; + y += EntryHeight + OffsetSize; + + AddImageTiled(x, y, CoordWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, CoordWidth - TextOffsetX, EntryHeight, TextHue, "X:"); + AddTextEntry(x + 16, y, CoordWidth - 16, EntryHeight, TextHue, 0, p.X.ToString()); + x += CoordWidth + OffsetSize; + + AddImageTiled(x, y, CoordWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, CoordWidth - TextOffsetX, EntryHeight, TextHue, "Y:"); + AddTextEntry(x + 16, y, CoordWidth - 16, EntryHeight, TextHue, 1, p.Y.ToString()); + x += CoordWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 3); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + Point2D toSet; + bool shouldSet, shouldSend; + + switch (info.ButtonID) + { + case 1: // Current location + { + toSet = new Point2D(m_Mobile.Location); + shouldSet = true; + shouldSend = true; + + break; + } + case 2: // Pick location + { + m_Mobile.Target = new InternalTarget(m_Property, m_Mobile, m_Object, m_Stack, m_Page, m_List); + + toSet = Point2D.Zero; + shouldSet = false; + shouldSend = false; + + break; + } + case 3: // Use values + { + var x = info.GetTextEntry(0); + var y = info.GetTextEntry(1); + + toSet = new Point2D( + x == null ? 0 : Utility.ToInt32(x.Text), + y == null ? 0 : Utility.ToInt32(y.Text) + ); + shouldSet = true; + shouldSend = true; + + break; + } + default: + { + toSet = Point2D.Zero; + shouldSet = false; + shouldSend = true; + + break; + } + } + + if (shouldSet) + try + { + CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, toSet.ToString()); + m_Property.SetValue(m_Object, toSet, null); + PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); + } + catch + { + m_Mobile.SendMessage("An exception was caught. The property may not have changed."); + } + + if (shouldSend) + m_Mobile.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); + } + + private class InternalTarget : Target + { + private readonly List m_List; + private readonly Mobile m_Mobile; + private readonly object m_Object; + private readonly int m_Page; + private readonly PropertyInfo m_Property; + private readonly Stack m_Stack; + + public InternalTarget( + PropertyInfo prop, Mobile mobile, object o, Stack stack, int page, + List list + ) : base(-1, true, TargetFlags.None) + { + m_Property = prop; + m_Mobile = mobile; + m_Object = o; + m_Stack = stack; + m_Page = page; + m_List = list; + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted is IPoint3D p) + try + { + CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, new Point2D(p).ToString()); + m_Property.SetValue(m_Object, new Point2D(p), null); + PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); + } + catch + { + m_Mobile.SendMessage("An exception was caught. The property may not have changed."); + } + } + + protected override void OnTargetFinish(Mobile from) + { + m_Mobile.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); + } + } + } +} diff --git a/Projects/UOContent/Gumps/Props/SetPoint3DGump.cs b/Projects/UOContent/Gumps/Props/SetPoint3DGump.cs index 176793a96..75eee4232 100644 --- a/Projects/UOContent/Gumps/Props/SetPoint3DGump.cs +++ b/Projects/UOContent/Gumps/Props/SetPoint3DGump.cs @@ -1,238 +1,250 @@ -using System.Collections.Generic; -using System.Reflection; -using Server.Commands; -using Server.Network; -using Server.Targeting; - -namespace Server.Gumps -{ - public class SetPoint3DGump : Gump - { - public static readonly bool OldStyle = PropsConfig.OldStyle; - - public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; - public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; - - public static readonly int TextHue = PropsConfig.TextHue; - public static readonly int TextOffsetX = PropsConfig.TextOffsetX; - - public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; - public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; - public static readonly int EntryGumpID = PropsConfig.EntryGumpID; - public static readonly int BackGumpID = PropsConfig.BackGumpID; - public static readonly int SetGumpID = PropsConfig.SetGumpID; - - public static readonly int SetWidth = PropsConfig.SetWidth; - public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY; - public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; - public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; - - public static readonly int PrevWidth = PropsConfig.PrevWidth; - public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY; - public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; - public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; - - public static readonly int NextWidth = PropsConfig.NextWidth; - public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY; - public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; - public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; - - public static readonly int OffsetSize = PropsConfig.OffsetSize; - - public static readonly int EntryHeight = PropsConfig.EntryHeight; - public static readonly int BorderSize = PropsConfig.BorderSize; - - private static readonly int CoordWidth = 70; - private static readonly int EntryWidth = CoordWidth + OffsetSize + CoordWidth + OffsetSize + CoordWidth; - - private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize; - private static readonly int TotalHeight = OffsetSize + 4 * (EntryHeight + OffsetSize); - - private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; - private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize; - private readonly List m_List; - private readonly Mobile m_Mobile; - private readonly object m_Object; - private readonly int m_Page; - private readonly PropertyInfo m_Property; - private readonly Stack m_Stack; - - public SetPoint3DGump(PropertyInfo prop, Mobile mobile, object o, Stack stack, int page, List list) - : base(GumpOffsetX, GumpOffsetY) - { - m_Property = prop; - m_Mobile = mobile; - m_Object = o; - m_Stack = stack; - m_Page = page; - m_List = list; - - Point3D p = (Point3D)prop.GetValue(o, null); - - AddPage(0); - - AddBackground(0, 0, BackWidth, BackHeight, BackGumpID); - AddImageTiled(BorderSize, BorderSize, TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), TotalHeight, - OffsetGumpID); - - int x = BorderSize + OffsetSize; - int y = BorderSize + OffsetSize; - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, prop.Name); - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - - x = BorderSize + OffsetSize; - y += EntryHeight + OffsetSize; - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Use your location"); - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 1); - - x = BorderSize + OffsetSize; - y += EntryHeight + OffsetSize; - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Target a location"); - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 2); - - x = BorderSize + OffsetSize; - y += EntryHeight + OffsetSize; - - AddImageTiled(x, y, CoordWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, CoordWidth - TextOffsetX, EntryHeight, TextHue, "X:"); - AddTextEntry(x + 16, y, CoordWidth - 16, EntryHeight, TextHue, 0, p.X.ToString()); - x += CoordWidth + OffsetSize; - - AddImageTiled(x, y, CoordWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, CoordWidth - TextOffsetX, EntryHeight, TextHue, "Y:"); - AddTextEntry(x + 16, y, CoordWidth - 16, EntryHeight, TextHue, 1, p.Y.ToString()); - x += CoordWidth + OffsetSize; - - AddImageTiled(x, y, CoordWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, CoordWidth - TextOffsetX, EntryHeight, TextHue, "Z:"); - AddTextEntry(x + 16, y, CoordWidth - 16, EntryHeight, TextHue, 2, p.Z.ToString()); - x += CoordWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 3); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - Point3D toSet; - bool shouldSet, shouldSend; - - switch (info.ButtonID) - { - case 1: // Current location - { - toSet = m_Mobile.Location; - shouldSet = true; - shouldSend = true; - - break; - } - case 2: // Pick location - { - m_Mobile.Target = new InternalTarget(m_Property, m_Mobile, m_Object, m_Stack, m_Page, m_List); - - toSet = Point3D.Zero; - shouldSet = false; - shouldSend = false; - - break; - } - case 3: // Use values - { - TextRelay x = info.GetTextEntry(0); - TextRelay y = info.GetTextEntry(1); - TextRelay z = info.GetTextEntry(2); - - toSet = new Point3D(x == null ? 0 : Utility.ToInt32(x.Text), y == null ? 0 : Utility.ToInt32(y.Text), - z == null ? 0 : Utility.ToInt32(z.Text)); - shouldSet = true; - shouldSend = true; - - break; - } - default: - { - toSet = Point3D.Zero; - shouldSet = false; - shouldSend = true; - - break; - } - } - - if (shouldSet) - try - { - CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, toSet.ToString()); - m_Property.SetValue(m_Object, toSet, null); - PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); - } - catch - { - m_Mobile.SendMessage("An exception was caught. The property may not have changed."); - } - - if (shouldSend) - m_Mobile.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); - } - - private class InternalTarget : Target - { - private readonly List m_List; - private readonly Mobile m_Mobile; - private readonly object m_Object; - private readonly int m_Page; - private readonly PropertyInfo m_Property; - private readonly Stack m_Stack; - - public InternalTarget(PropertyInfo prop, Mobile mobile, object o, Stack stack, int page, - List list) : base(-1, true, TargetFlags.None) - { - m_Property = prop; - m_Mobile = mobile; - m_Object = o; - m_Stack = stack; - m_Page = page; - m_List = list; - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is IPoint3D p) - try - { - CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, new Point3D(p).ToString()); - m_Property.SetValue(m_Object, new Point3D(p), null); - PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); - } - catch - { - m_Mobile.SendMessage("An exception was caught. The property may not have changed."); - } - } - - protected override void OnTargetFinish(Mobile from) - { - m_Mobile.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); - } - } - } -} +using System.Collections.Generic; +using System.Reflection; +using Server.Commands; +using Server.Network; +using Server.Targeting; + +namespace Server.Gumps +{ + public class SetPoint3DGump : Gump + { + public static readonly bool OldStyle = PropsConfig.OldStyle; + + public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; + public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; + + public static readonly int TextHue = PropsConfig.TextHue; + public static readonly int TextOffsetX = PropsConfig.TextOffsetX; + + public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; + public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; + public static readonly int EntryGumpID = PropsConfig.EntryGumpID; + public static readonly int BackGumpID = PropsConfig.BackGumpID; + public static readonly int SetGumpID = PropsConfig.SetGumpID; + + public static readonly int SetWidth = PropsConfig.SetWidth; + public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY; + public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; + public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; + + public static readonly int PrevWidth = PropsConfig.PrevWidth; + public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY; + public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; + public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; + + public static readonly int NextWidth = PropsConfig.NextWidth; + public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY; + public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; + public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; + + public static readonly int OffsetSize = PropsConfig.OffsetSize; + + public static readonly int EntryHeight = PropsConfig.EntryHeight; + public static readonly int BorderSize = PropsConfig.BorderSize; + + private static readonly int CoordWidth = 70; + private static readonly int EntryWidth = CoordWidth + OffsetSize + CoordWidth + OffsetSize + CoordWidth; + + private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize; + private static readonly int TotalHeight = OffsetSize + 4 * (EntryHeight + OffsetSize); + + private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; + private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize; + private readonly List m_List; + private readonly Mobile m_Mobile; + private readonly object m_Object; + private readonly int m_Page; + private readonly PropertyInfo m_Property; + private readonly Stack m_Stack; + + public SetPoint3DGump( + PropertyInfo prop, Mobile mobile, object o, Stack stack, int page, List list + ) + : base(GumpOffsetX, GumpOffsetY) + { + m_Property = prop; + m_Mobile = mobile; + m_Object = o; + m_Stack = stack; + m_Page = page; + m_List = list; + + var p = (Point3D)prop.GetValue(o, null); + + AddPage(0); + + AddBackground(0, 0, BackWidth, BackHeight, BackGumpID); + AddImageTiled( + BorderSize, + BorderSize, + TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), + TotalHeight, + OffsetGumpID + ); + + var x = BorderSize + OffsetSize; + var y = BorderSize + OffsetSize; + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, prop.Name); + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + + x = BorderSize + OffsetSize; + y += EntryHeight + OffsetSize; + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Use your location"); + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 1); + + x = BorderSize + OffsetSize; + y += EntryHeight + OffsetSize; + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, "Target a location"); + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 2); + + x = BorderSize + OffsetSize; + y += EntryHeight + OffsetSize; + + AddImageTiled(x, y, CoordWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, CoordWidth - TextOffsetX, EntryHeight, TextHue, "X:"); + AddTextEntry(x + 16, y, CoordWidth - 16, EntryHeight, TextHue, 0, p.X.ToString()); + x += CoordWidth + OffsetSize; + + AddImageTiled(x, y, CoordWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, CoordWidth - TextOffsetX, EntryHeight, TextHue, "Y:"); + AddTextEntry(x + 16, y, CoordWidth - 16, EntryHeight, TextHue, 1, p.Y.ToString()); + x += CoordWidth + OffsetSize; + + AddImageTiled(x, y, CoordWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, CoordWidth - TextOffsetX, EntryHeight, TextHue, "Z:"); + AddTextEntry(x + 16, y, CoordWidth - 16, EntryHeight, TextHue, 2, p.Z.ToString()); + x += CoordWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 3); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + Point3D toSet; + bool shouldSet, shouldSend; + + switch (info.ButtonID) + { + case 1: // Current location + { + toSet = m_Mobile.Location; + shouldSet = true; + shouldSend = true; + + break; + } + case 2: // Pick location + { + m_Mobile.Target = new InternalTarget(m_Property, m_Mobile, m_Object, m_Stack, m_Page, m_List); + + toSet = Point3D.Zero; + shouldSet = false; + shouldSend = false; + + break; + } + case 3: // Use values + { + var x = info.GetTextEntry(0); + var y = info.GetTextEntry(1); + var z = info.GetTextEntry(2); + + toSet = new Point3D( + x == null ? 0 : Utility.ToInt32(x.Text), + y == null ? 0 : Utility.ToInt32(y.Text), + z == null ? 0 : Utility.ToInt32(z.Text) + ); + shouldSet = true; + shouldSend = true; + + break; + } + default: + { + toSet = Point3D.Zero; + shouldSet = false; + shouldSend = true; + + break; + } + } + + if (shouldSet) + try + { + CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, toSet.ToString()); + m_Property.SetValue(m_Object, toSet, null); + PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); + } + catch + { + m_Mobile.SendMessage("An exception was caught. The property may not have changed."); + } + + if (shouldSend) + m_Mobile.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); + } + + private class InternalTarget : Target + { + private readonly List m_List; + private readonly Mobile m_Mobile; + private readonly object m_Object; + private readonly int m_Page; + private readonly PropertyInfo m_Property; + private readonly Stack m_Stack; + + public InternalTarget( + PropertyInfo prop, Mobile mobile, object o, Stack stack, int page, + List list + ) : base(-1, true, TargetFlags.None) + { + m_Property = prop; + m_Mobile = mobile; + m_Object = o; + m_Stack = stack; + m_Page = page; + m_List = list; + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted is IPoint3D p) + try + { + CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, new Point3D(p).ToString()); + m_Property.SetValue(m_Object, new Point3D(p), null); + PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); + } + catch + { + m_Mobile.SendMessage("An exception was caught. The property may not have changed."); + } + } + + protected override void OnTargetFinish(Mobile from) + { + m_Mobile.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); + } + } + } +} diff --git a/Projects/UOContent/Gumps/Props/SetTimeSpanGump.cs b/Projects/UOContent/Gumps/Props/SetTimeSpanGump.cs index 90beb48f1..628372dde 100644 --- a/Projects/UOContent/Gumps/Props/SetTimeSpanGump.cs +++ b/Projects/UOContent/Gumps/Props/SetTimeSpanGump.cs @@ -1,229 +1,236 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using Server.Commands; -using Server.Network; - -namespace Server.Gumps -{ - public class SetTimeSpanGump : Gump - { - public static readonly bool OldStyle = PropsConfig.OldStyle; - - public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; - public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; - - public static readonly int TextHue = PropsConfig.TextHue; - public static readonly int TextOffsetX = PropsConfig.TextOffsetX; - - public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; - public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; - public static readonly int EntryGumpID = PropsConfig.EntryGumpID; - public static readonly int BackGumpID = PropsConfig.BackGumpID; - public static readonly int SetGumpID = PropsConfig.SetGumpID; - - public static readonly int SetWidth = PropsConfig.SetWidth; - public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY; - public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; - public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; - - public static readonly int PrevWidth = PropsConfig.PrevWidth; - public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY; - public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; - public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; - - public static readonly int NextWidth = PropsConfig.NextWidth; - public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY; - public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; - public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; - - public static readonly int OffsetSize = PropsConfig.OffsetSize; - - public static readonly int EntryHeight = PropsConfig.EntryHeight; - public static readonly int BorderSize = PropsConfig.BorderSize; - - private static readonly int EntryWidth = 212; - - private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize; - private static readonly int TotalHeight = OffsetSize + 7 * (EntryHeight + OffsetSize); - - private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; - private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize; - private readonly List m_List; - private readonly Mobile m_Mobile; - private readonly object m_Object; - private readonly int m_Page; - private readonly PropertyInfo m_Property; - private readonly Stack m_Stack; - - public SetTimeSpanGump(PropertyInfo prop, Mobile mobile, object o, Stack stack, int page, List list) - : base(GumpOffsetX, GumpOffsetY) - { - m_Property = prop; - m_Mobile = mobile; - m_Object = o; - m_Stack = stack; - m_Page = page; - m_List = list; - - TimeSpan ts = (TimeSpan)prop.GetValue(o, null); - - AddPage(0); - - AddBackground(0, 0, BackWidth, BackHeight, BackGumpID); - AddImageTiled(BorderSize, BorderSize, TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), TotalHeight, - OffsetGumpID); - - AddRect(0, prop.Name, 0, -1); - AddRect(1, ts.ToString(), 0, -1); - AddRect(2, "Zero", 1, -1); - AddRect(3, "From H:M:S", 2, -1); - AddRect(4, "H:", 3, 0); - AddRect(5, "M:", 4, 1); - AddRect(6, "S:", 5, 2); - } - - private void AddRect(int index, string str, int button, int text) - { - int x = BorderSize + OffsetSize; - int y = BorderSize + OffsetSize + index * (EntryHeight + OffsetSize); - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, str); - - if (text != -1) - AddTextEntry(x + 16 + TextOffsetX, y, EntryWidth - TextOffsetX - 16, EntryHeight, TextHue, text, ""); - - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - - if (button != 0) - AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, button); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - TimeSpan toSet; - bool shouldSet, shouldSend; - - TextRelay h = info.GetTextEntry(0); - TextRelay m = info.GetTextEntry(1); - TextRelay s = info.GetTextEntry(2); - - switch (info.ButtonID) - { - case 1: // Zero - { - toSet = TimeSpan.Zero; - shouldSet = true; - shouldSend = true; - - break; - } - case 2: // From H:M:S - { - bool successfulParse = false; - if (h != null && m != null && s != null) - successfulParse = TimeSpan.TryParse($"{h.Text}:{m.Text}:{s.Text}", out toSet); - else - toSet = TimeSpan.Zero; - - shouldSet = shouldSend = successfulParse; - - break; - } - case 3: // From H - { - if (h != null) - try - { - toSet = TimeSpan.FromHours(Utility.ToDouble(h.Text)); - shouldSet = true; - shouldSend = true; - - break; - } - catch - { - // ignored - } - - toSet = TimeSpan.Zero; - shouldSet = false; - shouldSend = false; - - break; - } - case 4: // From M - { - if (m != null) - try - { - toSet = TimeSpan.FromMinutes(Utility.ToDouble(m.Text)); - shouldSet = true; - shouldSend = true; - - break; - } - catch - { - // ignored - } - - toSet = TimeSpan.Zero; - shouldSet = false; - shouldSend = false; - - break; - } - case 5: // From S - { - if (s != null) - try - { - toSet = TimeSpan.FromSeconds(Utility.ToDouble(s.Text)); - shouldSet = true; - shouldSend = true; - - break; - } - catch - { - // ignored - } - - toSet = TimeSpan.Zero; - shouldSet = false; - shouldSend = false; - - break; - } - default: - { - toSet = TimeSpan.Zero; - shouldSet = false; - shouldSend = true; - - break; - } - } - - if (shouldSet) - try - { - CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, toSet.ToString()); - m_Property.SetValue(m_Object, toSet, null); - PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); - } - catch - { - m_Mobile.SendMessage("An exception was caught. The property may not have changed."); - } - - if (shouldSend) - m_Mobile.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); - } - } -} +using System; +using System.Collections.Generic; +using System.Reflection; +using Server.Commands; +using Server.Network; + +namespace Server.Gumps +{ + public class SetTimeSpanGump : Gump + { + public static readonly bool OldStyle = PropsConfig.OldStyle; + + public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; + public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; + + public static readonly int TextHue = PropsConfig.TextHue; + public static readonly int TextOffsetX = PropsConfig.TextOffsetX; + + public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; + public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; + public static readonly int EntryGumpID = PropsConfig.EntryGumpID; + public static readonly int BackGumpID = PropsConfig.BackGumpID; + public static readonly int SetGumpID = PropsConfig.SetGumpID; + + public static readonly int SetWidth = PropsConfig.SetWidth; + public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY; + public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; + public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; + + public static readonly int PrevWidth = PropsConfig.PrevWidth; + public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY; + public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; + public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; + + public static readonly int NextWidth = PropsConfig.NextWidth; + public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY; + public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; + public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; + + public static readonly int OffsetSize = PropsConfig.OffsetSize; + + public static readonly int EntryHeight = PropsConfig.EntryHeight; + public static readonly int BorderSize = PropsConfig.BorderSize; + + private static readonly int EntryWidth = 212; + + private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize; + private static readonly int TotalHeight = OffsetSize + 7 * (EntryHeight + OffsetSize); + + private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; + private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize; + private readonly List m_List; + private readonly Mobile m_Mobile; + private readonly object m_Object; + private readonly int m_Page; + private readonly PropertyInfo m_Property; + private readonly Stack m_Stack; + + public SetTimeSpanGump( + PropertyInfo prop, Mobile mobile, object o, Stack stack, int page, List list + ) + : base(GumpOffsetX, GumpOffsetY) + { + m_Property = prop; + m_Mobile = mobile; + m_Object = o; + m_Stack = stack; + m_Page = page; + m_List = list; + + var ts = (TimeSpan)prop.GetValue(o, null); + + AddPage(0); + + AddBackground(0, 0, BackWidth, BackHeight, BackGumpID); + AddImageTiled( + BorderSize, + BorderSize, + TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), + TotalHeight, + OffsetGumpID + ); + + AddRect(0, prop.Name, 0, -1); + AddRect(1, ts.ToString(), 0, -1); + AddRect(2, "Zero", 1, -1); + AddRect(3, "From H:M:S", 2, -1); + AddRect(4, "H:", 3, 0); + AddRect(5, "M:", 4, 1); + AddRect(6, "S:", 5, 2); + } + + private void AddRect(int index, string str, int button, int text) + { + var x = BorderSize + OffsetSize; + var y = BorderSize + OffsetSize + index * (EntryHeight + OffsetSize); + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, str); + + if (text != -1) + AddTextEntry(x + 16 + TextOffsetX, y, EntryWidth - TextOffsetX - 16, EntryHeight, TextHue, text, ""); + + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + + if (button != 0) + AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, button); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + TimeSpan toSet; + bool shouldSet, shouldSend; + + var h = info.GetTextEntry(0); + var m = info.GetTextEntry(1); + var s = info.GetTextEntry(2); + + switch (info.ButtonID) + { + case 1: // Zero + { + toSet = TimeSpan.Zero; + shouldSet = true; + shouldSend = true; + + break; + } + case 2: // From H:M:S + { + var successfulParse = false; + if (h != null && m != null && s != null) + successfulParse = TimeSpan.TryParse($"{h.Text}:{m.Text}:{s.Text}", out toSet); + else + toSet = TimeSpan.Zero; + + shouldSet = shouldSend = successfulParse; + + break; + } + case 3: // From H + { + if (h != null) + try + { + toSet = TimeSpan.FromHours(Utility.ToDouble(h.Text)); + shouldSet = true; + shouldSend = true; + + break; + } + catch + { + // ignored + } + + toSet = TimeSpan.Zero; + shouldSet = false; + shouldSend = false; + + break; + } + case 4: // From M + { + if (m != null) + try + { + toSet = TimeSpan.FromMinutes(Utility.ToDouble(m.Text)); + shouldSet = true; + shouldSend = true; + + break; + } + catch + { + // ignored + } + + toSet = TimeSpan.Zero; + shouldSet = false; + shouldSend = false; + + break; + } + case 5: // From S + { + if (s != null) + try + { + toSet = TimeSpan.FromSeconds(Utility.ToDouble(s.Text)); + shouldSet = true; + shouldSend = true; + + break; + } + catch + { + // ignored + } + + toSet = TimeSpan.Zero; + shouldSet = false; + shouldSend = false; + + break; + } + default: + { + toSet = TimeSpan.Zero; + shouldSet = false; + shouldSend = true; + + break; + } + } + + if (shouldSet) + try + { + CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, toSet.ToString()); + m_Property.SetValue(m_Object, toSet, null); + PropertiesGump.OnValueChanged(m_Object, m_Property, m_Stack); + } + catch + { + m_Mobile.SendMessage("An exception was caught. The property may not have changed."); + } + + if (shouldSend) + m_Mobile.SendGump(new PropertiesGump(m_Mobile, m_Object, m_Stack, m_List, m_Page)); + } + } +} diff --git a/Projects/UOContent/Gumps/ReclaimVendorGump.cs b/Projects/UOContent/Gumps/ReclaimVendorGump.cs index 6239d4a8b..bc332e76c 100644 --- a/Projects/UOContent/Gumps/ReclaimVendorGump.cs +++ b/Projects/UOContent/Gumps/ReclaimVendorGump.cs @@ -1,78 +1,78 @@ -using System.Collections.Generic; -using System.Linq; -using Server.Multis; -using Server.Network; - -namespace Server.Gumps -{ - public class ReclaimVendorGump : Gump - { - private readonly BaseHouse m_House; - private readonly List m_Vendors; - - public ReclaimVendorGump(BaseHouse house) : base(50, 50) - { - m_House = house; - m_Vendors = house.InternalizedVendors.ToList(); - - AddBackground(0, 0, 170, 50 + m_Vendors.Count * 20, 0x13BE); - - AddImageTiled(10, 10, 150, 20, 0xA40); - AddHtmlLocalized(10, 10, 150, 20, 1061827, 0x7FFF); //
Reclaim Vendor
- - AddImageTiled(10, 40, 150, m_Vendors.Count * 20, 0xA40); - - for (int i = 0; i < m_Vendors.Count; i++) - { - Mobile m = m_Vendors[i]; - - int y = 40 + i * 20; - - AddButton(10, y, 0xFA5, 0xFA7, i + 1); - AddLabel(45, y, 0x481, m.Name); - } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - Mobile from = sender.Mobile; - - if (info.ButtonID == 0 || !m_House.IsActive || !m_House.IsInside(from) || !m_House.IsOwner(from) || - !from.CheckAlive()) - return; - - int index = info.ButtonID - 1; - - if (index < 0 || index >= m_Vendors.Count) - return; - - Mobile mob = m_Vendors[index]; - - if (!m_House.InternalizedVendors.Contains(mob)) - return; - - if (mob.Deleted) - { - m_House.InternalizedVendors.Remove(mob); - } - else - { - BaseHouse.IsThereVendor(from.Location, from.Map, out bool vendor, out bool contract); - - if (vendor) - { - from.SendLocalizedMessage(1062677); // You cannot place a vendor or barkeep at this location. - } - else if (contract) - { - from.SendLocalizedMessage(1062678); // You cannot place a vendor or barkeep on top of a rental contract! - } - else - { - m_House.InternalizedVendors.Remove(mob); - mob.MoveToWorld(from.Location, from.Map); - } - } - } - } -} +using System.Collections.Generic; +using System.Linq; +using Server.Multis; +using Server.Network; + +namespace Server.Gumps +{ + public class ReclaimVendorGump : Gump + { + private readonly BaseHouse m_House; + private readonly List m_Vendors; + + public ReclaimVendorGump(BaseHouse house) : base(50, 50) + { + m_House = house; + m_Vendors = house.InternalizedVendors.ToList(); + + AddBackground(0, 0, 170, 50 + m_Vendors.Count * 20, 0x13BE); + + AddImageTiled(10, 10, 150, 20, 0xA40); + AddHtmlLocalized(10, 10, 150, 20, 1061827, 0x7FFF); //
Reclaim Vendor
+ + AddImageTiled(10, 40, 150, m_Vendors.Count * 20, 0xA40); + + for (var i = 0; i < m_Vendors.Count; i++) + { + var m = m_Vendors[i]; + + var y = 40 + i * 20; + + AddButton(10, y, 0xFA5, 0xFA7, i + 1); + AddLabel(45, y, 0x481, m.Name); + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var from = sender.Mobile; + + if (info.ButtonID == 0 || !m_House.IsActive || !m_House.IsInside(from) || !m_House.IsOwner(from) || + !from.CheckAlive()) + return; + + var index = info.ButtonID - 1; + + if (index < 0 || index >= m_Vendors.Count) + return; + + var mob = m_Vendors[index]; + + if (!m_House.InternalizedVendors.Contains(mob)) + return; + + if (mob.Deleted) + { + m_House.InternalizedVendors.Remove(mob); + } + else + { + BaseHouse.IsThereVendor(from.Location, from.Map, out var vendor, out var contract); + + if (vendor) + { + from.SendLocalizedMessage(1062677); // You cannot place a vendor or barkeep at this location. + } + else if (contract) + { + from.SendLocalizedMessage(1062678); // You cannot place a vendor or barkeep on top of a rental contract! + } + else + { + m_House.InternalizedVendors.Remove(mob); + mob.MoveToWorld(from.Location, from.Map); + } + } + } + } +} diff --git a/Projects/UOContent/Gumps/ReportMurderer.cs b/Projects/UOContent/Gumps/ReportMurderer.cs index 7ce990677..23f321162 100644 --- a/Projects/UOContent/Gumps/ReportMurderer.cs +++ b/Projects/UOContent/Gumps/ReportMurderer.cs @@ -1,173 +1,178 @@ -using System; -using System.Collections.Generic; -using Server.Misc; -using Server.Network; -using Server.Mobiles; - -namespace Server.Gumps -{ - public class ReportMurdererGump : Gump - { - private int m_Idx; - private readonly List m_Killers; - private Mobile m_Victum; - - public static void Initialize() - { - EventSink.PlayerDeath += EventSink_PlayerDeath; - } - - public static void EventSink_PlayerDeath(Mobile m) - { - List killers = new List(); - List toGive = new List(); - - foreach (AggressorInfo ai in m.Aggressors) - { - if (ai.Attacker.Player && ai.CanReportMurder && !ai.Reported) - if (!Core.SE || !((PlayerMobile)m).RecentlyReported.Contains(ai.Attacker)) - { - killers.Add(ai.Attacker); - ai.Reported = true; - ai.CanReportMurder = false; - } - - if (ai.Attacker.Player && DateTime.UtcNow - ai.LastCombatTime < TimeSpan.FromSeconds(30.0) && !toGive.Contains(ai.Attacker)) - toGive.Add(ai.Attacker); - } - - foreach (AggressorInfo ai in m.Aggressed) - if (ai.Defender.Player && DateTime.UtcNow - ai.LastCombatTime < TimeSpan.FromSeconds(30.0) && !toGive.Contains(ai.Defender)) - toGive.Add(ai.Defender); - - foreach (Mobile g in toGive) - { - int n = Notoriety.Compute(g, m); - - int ourKarma = g.Karma; - bool innocent = n == Notoriety.Innocent; - bool criminal = n == Notoriety.Criminal || n == Notoriety.Murderer; - - int fameAward = m.Fame / 200; - int karmaAward = 0; - - if (innocent) - karmaAward = ourKarma > -2500 ? -850 : -110 - m.Karma / 100; - else if (criminal) - karmaAward = 50; - - Titles.AwardFame(g, fameAward, false); - Titles.AwardKarma(g, karmaAward, true); - } - - if (m is PlayerMobile mobile && mobile.NpcGuild == NpcGuild.ThievesGuild) - return; - - if (killers.Count > 0) - new GumpTimer(m, killers).Start(); - } - - private class GumpTimer : Timer - { - private readonly Mobile m_Victim; - private readonly List m_Killers; - - public GumpTimer(Mobile victim, List killers) : base(TimeSpan.FromSeconds(4.0)) - { - m_Victim = victim; - m_Killers = killers; - } - - protected override void OnTick() - { - m_Victim.SendGump(new ReportMurdererGump(m_Victim, m_Killers)); - } - } - - private ReportMurdererGump(Mobile victum, List killers, int idx = 0) : base(0, 0) - { - m_Killers = killers; - m_Victum = victum; - m_Idx = idx; - BuildGump(); - } - - private void BuildGump() - { - AddBackground(265, 205, 320, 290, 5054); - Closable = false; - Resizable = false; - - AddPage(0); - - AddImageTiled(225, 175, 50, 45, 0xCE); // Top left corner - AddImageTiled(267, 175, 315, 44, 0xC9); // Top bar - AddImageTiled(582, 175, 43, 45, 0xCF); // Top right corner - AddImageTiled(225, 219, 44, 270, 0xCA); // Left side - AddImageTiled(582, 219, 44, 270, 0xCB); // Right side - AddImageTiled(225, 489, 44, 43, 0xCC); // Lower left corner - AddImageTiled(267, 489, 315, 43, 0xE9); // Lower Bar - AddImageTiled(582, 489, 43, 43, 0xCD); // Lower right corner - - AddPage(1); - - AddHtml(260, 234, 300, 140, m_Killers[m_Idx].Name); // Player's Name - AddHtmlLocalized(260, 254, 300, 140, 1049066); // Would you like to report... - - AddButton(260, 300, 0xFA5, 0xFA7, 1); - AddHtmlLocalized(300, 300, 300, 50, 1046362); // Yes - - AddButton(360, 300, 0xFA5, 0xFA7, 2); - AddHtmlLocalized(400, 300, 300, 50, 1046363); // No - } - - public static void ReportedListExpiry_Callback(PlayerMobile from, Mobile killer) - { - if (from.RecentlyReported.Contains(killer)) - from.RecentlyReported.Remove(killer); - } - - public override void OnResponse(NetState state, RelayInfo info) - { - PlayerMobile from = (PlayerMobile)state.Mobile; - - switch (info.ButtonID) - { - case 1: - { - Mobile killer = m_Killers[m_Idx]; - if (killer?.Deleted == false) - { - killer.Kills++; - killer.ShortTermMurders++; - - if (Core.SE) - { - from.RecentlyReported.Add(killer); - Timer.DelayCall(TimeSpan.FromMinutes(10), ReportedListExpiry_Callback, from, killer); - } - - if (killer is PlayerMobile pk) - { - pk.ResetKillTime(); - pk.SendLocalizedMessage(1049067);// You have been reported for murder! - - if (pk.Kills == 5) - pk.SendLocalizedMessage(502134);// You are now known as a murderer! - else if (SkillHandlers.Stealing.SuspendOnMurder && pk.Kills == 1 && pk.NpcGuild == NpcGuild.ThievesGuild) pk.SendLocalizedMessage(501562); // You have been suspended by the Thieves Guild. - } - } - break; - } - case 2: - { - break; - } - } - - m_Idx++; - if (m_Idx < m_Killers.Count) - from.SendGump(new ReportMurdererGump(from, m_Killers, m_Idx)); - } - } -} +using System; +using System.Collections.Generic; +using Server.Misc; +using Server.Mobiles; +using Server.Network; +using Server.SkillHandlers; + +namespace Server.Gumps +{ + public class ReportMurdererGump : Gump + { + private readonly List m_Killers; + private int m_Idx; + private Mobile m_Victum; + + private ReportMurdererGump(Mobile victum, List killers, int idx = 0) : base(0, 0) + { + m_Killers = killers; + m_Victum = victum; + m_Idx = idx; + BuildGump(); + } + + public static void Initialize() + { + EventSink.PlayerDeath += EventSink_PlayerDeath; + } + + public static void EventSink_PlayerDeath(Mobile m) + { + var killers = new List(); + var toGive = new List(); + + foreach (var ai in m.Aggressors) + { + if (ai.Attacker.Player && ai.CanReportMurder && !ai.Reported) + if (!Core.SE || !((PlayerMobile)m).RecentlyReported.Contains(ai.Attacker)) + { + killers.Add(ai.Attacker); + ai.Reported = true; + ai.CanReportMurder = false; + } + + if (ai.Attacker.Player && DateTime.UtcNow - ai.LastCombatTime < TimeSpan.FromSeconds(30.0) && + !toGive.Contains(ai.Attacker)) + toGive.Add(ai.Attacker); + } + + foreach (var ai in m.Aggressed) + if (ai.Defender.Player && DateTime.UtcNow - ai.LastCombatTime < TimeSpan.FromSeconds(30.0) && + !toGive.Contains(ai.Defender)) + toGive.Add(ai.Defender); + + foreach (var g in toGive) + { + var n = Notoriety.Compute(g, m); + + var ourKarma = g.Karma; + var innocent = n == Notoriety.Innocent; + var criminal = n == Notoriety.Criminal || n == Notoriety.Murderer; + + var fameAward = m.Fame / 200; + var karmaAward = 0; + + if (innocent) + karmaAward = ourKarma > -2500 ? -850 : -110 - m.Karma / 100; + else if (criminal) + karmaAward = 50; + + Titles.AwardFame(g, fameAward, false); + Titles.AwardKarma(g, karmaAward, true); + } + + if (m is PlayerMobile mobile && mobile.NpcGuild == NpcGuild.ThievesGuild) + return; + + if (killers.Count > 0) + new GumpTimer(m, killers).Start(); + } + + private void BuildGump() + { + AddBackground(265, 205, 320, 290, 5054); + Closable = false; + Resizable = false; + + AddPage(0); + + AddImageTiled(225, 175, 50, 45, 0xCE); // Top left corner + AddImageTiled(267, 175, 315, 44, 0xC9); // Top bar + AddImageTiled(582, 175, 43, 45, 0xCF); // Top right corner + AddImageTiled(225, 219, 44, 270, 0xCA); // Left side + AddImageTiled(582, 219, 44, 270, 0xCB); // Right side + AddImageTiled(225, 489, 44, 43, 0xCC); // Lower left corner + AddImageTiled(267, 489, 315, 43, 0xE9); // Lower Bar + AddImageTiled(582, 489, 43, 43, 0xCD); // Lower right corner + + AddPage(1); + + AddHtml(260, 234, 300, 140, m_Killers[m_Idx].Name); // Player's Name + AddHtmlLocalized(260, 254, 300, 140, 1049066); // Would you like to report... + + AddButton(260, 300, 0xFA5, 0xFA7, 1); + AddHtmlLocalized(300, 300, 300, 50, 1046362); // Yes + + AddButton(360, 300, 0xFA5, 0xFA7, 2); + AddHtmlLocalized(400, 300, 300, 50, 1046363); // No + } + + public static void ReportedListExpiry_Callback(PlayerMobile from, Mobile killer) + { + if (from.RecentlyReported.Contains(killer)) + from.RecentlyReported.Remove(killer); + } + + public override void OnResponse(NetState state, RelayInfo info) + { + var from = (PlayerMobile)state.Mobile; + + switch (info.ButtonID) + { + case 1: + { + var killer = m_Killers[m_Idx]; + if (killer?.Deleted == false) + { + killer.Kills++; + killer.ShortTermMurders++; + + if (Core.SE) + { + from.RecentlyReported.Add(killer); + Timer.DelayCall(TimeSpan.FromMinutes(10), ReportedListExpiry_Callback, from, killer); + } + + if (killer is PlayerMobile pk) + { + pk.ResetKillTime(); + pk.SendLocalizedMessage(1049067); // You have been reported for murder! + + if (pk.Kills == 5) + pk.SendLocalizedMessage(502134); // You are now known as a murderer! + else if (Stealing.SuspendOnMurder && pk.Kills == 1 && pk.NpcGuild == NpcGuild.ThievesGuild) + pk.SendLocalizedMessage(501562); // You have been suspended by the Thieves Guild. + } + } + + break; + } + case 2: + { + break; + } + } + + m_Idx++; + if (m_Idx < m_Killers.Count) + from.SendGump(new ReportMurdererGump(from, m_Killers, m_Idx)); + } + + private class GumpTimer : Timer + { + private readonly List m_Killers; + private readonly Mobile m_Victim; + + public GumpTimer(Mobile victim, List killers) : base(TimeSpan.FromSeconds(4.0)) + { + m_Victim = victim; + m_Killers = killers; + } + + protected override void OnTick() + { + m_Victim.SendGump(new ReportMurdererGump(m_Victim, m_Killers)); + } + } + } +} diff --git a/Projects/UOContent/Gumps/ResurrectGump.cs b/Projects/UOContent/Gumps/ResurrectGump.cs index 451be294e..0e42be518 100644 --- a/Projects/UOContent/Gumps/ResurrectGump.cs +++ b/Projects/UOContent/Gumps/ResurrectGump.cs @@ -1,228 +1,252 @@ -using System.Collections.Generic; -using Server.Items; -using Server.Network; -using Server.Mobiles; - -namespace Server.Gumps -{ - public enum ResurrectMessage - { - ChaosShrine = 0, - VirtueShrine = 1, - Healer = 2, - Generic = 3 - } - - public class ResurrectGump : Gump - { - private readonly Mobile m_Healer; - private readonly int m_Price; - private readonly bool m_FromSacrifice; - private readonly double m_HitsScalar; - - public ResurrectGump(Mobile owner, double hitsScalar) - : this(owner, owner, ResurrectMessage.Generic, false, hitsScalar) - { - } - - public ResurrectGump(Mobile owner, ResurrectMessage msg) : this(owner, owner, msg) - { - } - - public ResurrectGump(Mobile owner, bool fromSacrifice = false) - : this(owner, owner, ResurrectMessage.Generic, fromSacrifice) - { - } - - public ResurrectGump(Mobile owner, Mobile healer, ResurrectMessage msg = ResurrectMessage.Generic, - bool fromSacrifice = false, double hitsScalar = 0.0) - : base(100, 0) - { - m_Healer = healer; - m_FromSacrifice = fromSacrifice; - m_HitsScalar = hitsScalar; - - AddPage(0); - - AddBackground(0, 0, 400, 350, 2600); - - AddHtmlLocalized(0, 20, 400, 35, 1011022); //
Resurrection
- - /* It is possible for you to be resurrected here by this healer. Do you wish to try?
- * CONTINUE - You chose to try to come back to life now.
- * CANCEL - You prefer to remain a ghost for now. - */ - AddHtmlLocalized(50, 55, 300, 140, 1011023 + (int)msg, true, true); - - AddButton(200, 227, 4005, 4007, 0); - AddHtmlLocalized(235, 230, 110, 35, 1011012); // CANCEL - - AddButton(65, 227, 4005, 4007, 1); - AddHtmlLocalized(100, 230, 110, 35, 1011011); // CONTINUE - } - - public ResurrectGump(Mobile owner, Mobile healer, int price) - : base(150, 50) - { - m_Healer = healer; - m_Price = price; - - Closable = false; - - AddPage(0); - - AddImage(0, 0, 3600); - - AddImageTiled(0, 14, 15, 200, 3603); - AddImageTiled(380, 14, 14, 200, 3605); - - AddImage(0, 201, 3606); - - AddImageTiled(15, 201, 370, 16, 3607); - AddImageTiled(15, 0, 370, 16, 3601); - - AddImage(380, 0, 3602); - - AddImage(380, 201, 3608); - - AddImageTiled(15, 15, 365, 190, 2624); - - AddRadio(30, 140, 9727, 9730, true, 1); - AddHtmlLocalized(65, 145, 300, 25, 1060015, 0x7FFF); // Grudgingly pay the money - - AddRadio(30, 175, 9727, 9730, false, 0); - AddHtmlLocalized(65, 178, 300, 25, 1060016, 0x7FFF); // I'd rather stay dead, you scoundrel!!! - - AddHtmlLocalized(30, 20, 360, 35, 1060017, 0x7FFF); // Wishing to rejoin the living, are you? I can restore your body... for a price of course... - - AddHtmlLocalized(30, 105, 345, 40, 1060018, 0x5B2D); // Do you accept the fee, which will be withdrawn from your bank? - - AddImage(65, 72, 5605); - - AddImageTiled(80, 90, 200, 1, 9107); - AddImageTiled(95, 92, 200, 1, 9157); - - AddLabel(90, 70, 1645, price.ToString()); - AddHtmlLocalized(140, 70, 100, 25, 1023823, 0x7FFF); // gold coins - - AddButton(290, 175, 247, 248, 2); - - AddImageTiled(15, 14, 365, 1, 9107); - AddImageTiled(380, 14, 1, 190, 9105); - AddImageTiled(15, 205, 365, 1, 9107); - AddImageTiled(15, 14, 1, 190, 9105); - AddImageTiled(0, 0, 395, 1, 9157); - AddImageTiled(394, 0, 1, 217, 9155); - AddImageTiled(0, 216, 395, 1, 9157); - AddImageTiled(0, 0, 1, 217, 9155); - } - - public override void OnResponse(NetState state, RelayInfo info) - { - Mobile from = state.Mobile; - - from.CloseGump(); - - if (info.ButtonID != 1 && info.ButtonID != 2) - return; - - if (from.Map?.CanFit(from.Location, 16, false, false) != true) - { - from.SendLocalizedMessage(502391); // Thou can not be resurrected there! - return; - } - - if (m_Price > 0) - { - if (info.IsSwitched(1)) - { - if (Banker.Withdraw(from, m_Price)) - { - from.SendLocalizedMessage(1060398, m_Price.ToString()); // ~1_AMOUNT~ gold has been withdrawn from your bank box. - from.SendLocalizedMessage(1060022, Banker.GetBalance(from).ToString()); // You have ~1_AMOUNT~ gold in cash remaining in your bank box. - } - else - { - from.SendLocalizedMessage(1060020); // Unfortunately, you do not have enough cash in your bank to cover the cost of the healing. - return; - } - } - else - { - from.SendLocalizedMessage(1060019); // You decide against paying the healer, and thus remain dead. - return; - } - } - - from.PlaySound(0x214); - from.FixedEffect(0x376A, 10, 16); - - from.Resurrect(); - - if (m_Healer != null && from != m_Healer) - { - VirtueLevel level = VirtueHelper.GetLevel(m_Healer, VirtueName.Compassion); - - from.Hits = level switch - { - VirtueLevel.Seeker => AOS.Scale(from.HitsMax, 20), - VirtueLevel.Follower => AOS.Scale(from.HitsMax, 40), - VirtueLevel.Knight => AOS.Scale(from.HitsMax, 80), - _ => from.Hits - }; - } - - if (m_FromSacrifice && from is PlayerMobile mobile) - { - mobile.AvailableResurrects -= 1; - - Container pack = mobile.Backpack; - Container corpse = mobile.Corpse; - - if (pack != null && corpse != null) - { - List items = new List(corpse.Items); - - for (int i = 0; i < items.Count; ++i) - { - Item item = items[i]; - - if (item.Layer != Layer.Hair && item.Layer != Layer.FacialHair && item.Movable) - pack.DropItem(item); - } - } - } - - if (from.Fame > 0) - { - int amount = from.Fame / 10; - - Misc.Titles.AwardFame(from, -amount, true); - } - - if (!Core.AOS && from.ShortTermMurders >= 5) - { - double loss = (100.0 - (4.0 + from.ShortTermMurders / 5.0)) / 100.0; // 5 to 15% loss - - if (loss < 0.85) - loss = 0.85; - else if (loss > 0.95) - loss = 0.95; - - if (from.RawStr * loss > 10) - from.RawStr = (int)(from.RawStr * loss); - if (from.RawInt * loss > 10) - from.RawInt = (int)(from.RawInt * loss); - if (from.RawDex * loss > 10) - from.RawDex = (int)(from.RawDex * loss); - - for (int s = 0; s < from.Skills.Length; s++) - if (from.Skills[s].Base * loss > 35) - from.Skills[s].Base *= loss; - } - - if (from.Alive && m_HitsScalar > 0) - from.Hits = (int)(from.HitsMax * m_HitsScalar); - } - } -} +using System.Collections.Generic; +using Server.Misc; +using Server.Mobiles; +using Server.Network; + +namespace Server.Gumps +{ + public enum ResurrectMessage + { + ChaosShrine = 0, + VirtueShrine = 1, + Healer = 2, + Generic = 3 + } + + public class ResurrectGump : Gump + { + private readonly bool m_FromSacrifice; + private readonly Mobile m_Healer; + private readonly double m_HitsScalar; + private readonly int m_Price; + + public ResurrectGump(Mobile owner, double hitsScalar) + : this(owner, owner, ResurrectMessage.Generic, false, hitsScalar) + { + } + + public ResurrectGump(Mobile owner, ResurrectMessage msg) : this(owner, owner, msg) + { + } + + public ResurrectGump(Mobile owner, bool fromSacrifice = false) + : this(owner, owner, ResurrectMessage.Generic, fromSacrifice) + { + } + + public ResurrectGump( + Mobile owner, Mobile healer, ResurrectMessage msg = ResurrectMessage.Generic, + bool fromSacrifice = false, double hitsScalar = 0.0 + ) + : base(100, 0) + { + m_Healer = healer; + m_FromSacrifice = fromSacrifice; + m_HitsScalar = hitsScalar; + + AddPage(0); + + AddBackground(0, 0, 400, 350, 2600); + + AddHtmlLocalized(0, 20, 400, 35, 1011022); //
Resurrection
+ + /* It is possible for you to be resurrected here by this healer. Do you wish to try?
+ * CONTINUE - You chose to try to come back to life now.
+ * CANCEL - You prefer to remain a ghost for now. + */ + AddHtmlLocalized(50, 55, 300, 140, 1011023 + (int)msg, true, true); + + AddButton(200, 227, 4005, 4007, 0); + AddHtmlLocalized(235, 230, 110, 35, 1011012); // CANCEL + + AddButton(65, 227, 4005, 4007, 1); + AddHtmlLocalized(100, 230, 110, 35, 1011011); // CONTINUE + } + + public ResurrectGump(Mobile owner, Mobile healer, int price) + : base(150, 50) + { + m_Healer = healer; + m_Price = price; + + Closable = false; + + AddPage(0); + + AddImage(0, 0, 3600); + + AddImageTiled(0, 14, 15, 200, 3603); + AddImageTiled(380, 14, 14, 200, 3605); + + AddImage(0, 201, 3606); + + AddImageTiled(15, 201, 370, 16, 3607); + AddImageTiled(15, 0, 370, 16, 3601); + + AddImage(380, 0, 3602); + + AddImage(380, 201, 3608); + + AddImageTiled(15, 15, 365, 190, 2624); + + AddRadio(30, 140, 9727, 9730, true, 1); + AddHtmlLocalized(65, 145, 300, 25, 1060015, 0x7FFF); // Grudgingly pay the money + + AddRadio(30, 175, 9727, 9730, false, 0); + AddHtmlLocalized(65, 178, 300, 25, 1060016, 0x7FFF); // I'd rather stay dead, you scoundrel!!! + + AddHtmlLocalized( + 30, + 20, + 360, + 35, + 1060017, + 0x7FFF + ); // Wishing to rejoin the living, are you? I can restore your body... for a price of course... + + AddHtmlLocalized( + 30, + 105, + 345, + 40, + 1060018, + 0x5B2D + ); // Do you accept the fee, which will be withdrawn from your bank? + + AddImage(65, 72, 5605); + + AddImageTiled(80, 90, 200, 1, 9107); + AddImageTiled(95, 92, 200, 1, 9157); + + AddLabel(90, 70, 1645, price.ToString()); + AddHtmlLocalized(140, 70, 100, 25, 1023823, 0x7FFF); // gold coins + + AddButton(290, 175, 247, 248, 2); + + AddImageTiled(15, 14, 365, 1, 9107); + AddImageTiled(380, 14, 1, 190, 9105); + AddImageTiled(15, 205, 365, 1, 9107); + AddImageTiled(15, 14, 1, 190, 9105); + AddImageTiled(0, 0, 395, 1, 9157); + AddImageTiled(394, 0, 1, 217, 9155); + AddImageTiled(0, 216, 395, 1, 9157); + AddImageTiled(0, 0, 1, 217, 9155); + } + + public override void OnResponse(NetState state, RelayInfo info) + { + var from = state.Mobile; + + from.CloseGump(); + + if (info.ButtonID != 1 && info.ButtonID != 2) + return; + + if (from.Map?.CanFit(from.Location, 16, false, false) != true) + { + from.SendLocalizedMessage(502391); // Thou can not be resurrected there! + return; + } + + if (m_Price > 0) + { + if (info.IsSwitched(1)) + { + if (Banker.Withdraw(from, m_Price)) + { + from.SendLocalizedMessage( + 1060398, + m_Price.ToString() + ); // ~1_AMOUNT~ gold has been withdrawn from your bank box. + from.SendLocalizedMessage( + 1060022, + Banker.GetBalance(from).ToString() + ); // You have ~1_AMOUNT~ gold in cash remaining in your bank box. + } + else + { + from.SendLocalizedMessage( + 1060020 + ); // Unfortunately, you do not have enough cash in your bank to cover the cost of the healing. + return; + } + } + else + { + from.SendLocalizedMessage(1060019); // You decide against paying the healer, and thus remain dead. + return; + } + } + + from.PlaySound(0x214); + from.FixedEffect(0x376A, 10, 16); + + from.Resurrect(); + + if (m_Healer != null && from != m_Healer) + { + var level = VirtueHelper.GetLevel(m_Healer, VirtueName.Compassion); + + from.Hits = level switch + { + VirtueLevel.Seeker => AOS.Scale(from.HitsMax, 20), + VirtueLevel.Follower => AOS.Scale(from.HitsMax, 40), + VirtueLevel.Knight => AOS.Scale(from.HitsMax, 80), + _ => from.Hits + }; + } + + if (m_FromSacrifice && from is PlayerMobile mobile) + { + mobile.AvailableResurrects -= 1; + + var pack = mobile.Backpack; + var corpse = mobile.Corpse; + + if (pack != null && corpse != null) + { + var items = new List(corpse.Items); + + for (var i = 0; i < items.Count; ++i) + { + var item = items[i]; + + if (item.Layer != Layer.Hair && item.Layer != Layer.FacialHair && item.Movable) + pack.DropItem(item); + } + } + } + + if (from.Fame > 0) + { + var amount = from.Fame / 10; + + Titles.AwardFame(from, -amount, true); + } + + if (!Core.AOS && from.ShortTermMurders >= 5) + { + var loss = (100.0 - (4.0 + from.ShortTermMurders / 5.0)) / 100.0; // 5 to 15% loss + + if (loss < 0.85) + loss = 0.85; + else if (loss > 0.95) + loss = 0.95; + + if (from.RawStr * loss > 10) + from.RawStr = (int)(from.RawStr * loss); + if (from.RawInt * loss > 10) + from.RawInt = (int)(from.RawInt * loss); + if (from.RawDex * loss > 10) + from.RawDex = (int)(from.RawDex * loss); + + for (var s = 0; s < from.Skills.Length; s++) + if (from.Skills[s].Base * loss > 35) + from.Skills[s].Base *= loss; + } + + if (from.Alive && m_HitsScalar > 0) + from.Hits = (int)(from.HitsMax * m_HitsScalar); + } + } +} diff --git a/Projects/UOContent/Gumps/RewardGump.cs b/Projects/UOContent/Gumps/RewardGump.cs index bb53683f1..e47b1ba7a 100644 --- a/Projects/UOContent/Gumps/RewardGump.cs +++ b/Projects/UOContent/Gumps/RewardGump.cs @@ -1,187 +1,191 @@ -using System; -using Server.Network; - -namespace Server.Gumps -{ - /* - * A generic version of the EA Clean Up Britannia reward gump. - */ - - public interface IRewardEntry - { - int Price { get; } - int ItemID { get; } - int Hue { get; } - int Tooltip { get; } - TextDefinition Description { get; } - } - - public delegate void RewardPickedHandler(Mobile from, int index); - - public class RewardGump : Gump - { - public RewardGump(TextDefinition title, IRewardEntry[] rewards, int points, RewardPickedHandler onPicked) - : base(250, 50) - { - Title = title; - Rewards = rewards; - Points = points; - OnPicked = onPicked; - - AddPage(0); - - AddImage(0, 0, 0x1F40); - AddImageTiled(20, 37, 300, 308, 0x1F42); - AddImage(20, 325, 0x1F43); - AddImage(35, 8, 0x39); - AddImageTiled(65, 8, 257, 10, 0x3A); - AddImage(290, 8, 0x3B); - AddImage(32, 33, 0x2635); - AddImageTiled(70, 55, 230, 2, 0x23C5); - - if (Title.String != null) - AddHtml(70, 35, 270, 20, Title.String); - else if (Title.Number != 0) - AddHtmlLocalized(70, 35, 270, 20, Title.Number, 1); - - AddHtmlLocalized(50, 65, 150, 20, 1072843, 1); // Your Reward Points: - AddLabel(230, 65, 0x64, Points.ToString()); - AddImageTiled(35, 85, 270, 2, 0x23C5); - AddHtmlLocalized(35, 90, 270, 20, 1072844, 1); // Please Choose a Reward: - - AddPage(1); - - int offset = 110; - int page = 1; - - for (int i = 0; i < Rewards.Length; ++i) - { - IRewardEntry entry = Rewards[i]; - - Rectangle2D bounds = ItemBounds.Table[entry.ItemID]; - int height = Math.Max(36, bounds.Height); - - if (offset + height > 320) - { - AddHtmlLocalized(240, 335, 60, 20, 1072854, 1); //
Next
- AddButton(300, 335, 0x15E1, 0x15E5, 51, GumpButtonType.Page, page + 1); - - AddPage(++page); - - AddButton(150, 335, 0x15E3, 0x15E7, 52, GumpButtonType.Page, page - 1); - AddHtmlLocalized(170, 335, 60, 20, 1074880, 1); // Previous - - offset = 110; - } - - bool available = entry.Price <= Points; - int half = offset + height / 2; - - if (available) - AddButton(35, half - 6, 0x837, 0x838, 100 + i); - - AddItem(83 - bounds.Width / 2 - bounds.X, half - bounds.Height / 2 - bounds.Y, entry.ItemID, - available ? entry.Hue : 995); - - if (entry.Tooltip != 0) - AddTooltip(entry.Tooltip); - - AddLabel(133, half - 10, available ? 0x64 : 0x21, entry.Price.ToString()); - - if (entry.Description != null) - { - if (entry.Description.String != null) - AddHtml(190, offset, 114, height, entry.Description.String); - else if (entry.Description.Number != 0) - AddHtmlLocalized(190, offset, 114, height, entry.Description.Number, 1); - } - - offset += height + 10; - } - } - - public TextDefinition Title { get; } - - public IRewardEntry[] Rewards { get; } - - public int Points { get; } - - public RewardPickedHandler OnPicked { get; } - - public override void OnResponse(NetState sender, RelayInfo info) - { - int choice = info.ButtonID; - - if (choice == 0) - return; // Close - - choice -= 100; - - if (choice >= 0 && choice < Rewards.Length) - { - IRewardEntry entry = Rewards[choice]; - - if (entry.Price <= Points) - sender.Mobile.SendGump(new RewardConfirmGump(this, choice, entry)); - } - } - } - - public class RewardConfirmGump : Gump - { - private readonly int m_Index; - private readonly RewardGump m_Parent; - - public RewardConfirmGump(RewardGump parent, int index, IRewardEntry entry) - : base(120, 50) - { - m_Parent = parent; - m_Index = index; - - Closable = false; - - AddPage(0); - - AddImageTiled(0, 0, 348, 262, 0xA8E); - AddAlphaRegion(0, 0, 348, 262); - AddImage(0, 15, 0x27A8); - AddImageTiled(0, 30, 17, 200, 0x27A7); - AddImage(0, 230, 0x27AA); - AddImage(15, 0, 0x280C); - AddImageTiled(30, 0, 300, 17, 0x280A); - AddImage(315, 0, 0x280E); - AddImage(15, 244, 0x280C); - AddImageTiled(30, 244, 300, 17, 0x280A); - AddImage(315, 244, 0x280E); - AddImage(330, 15, 0x27A8); - AddImageTiled(330, 30, 17, 200, 0x27A7); - AddImage(330, 230, 0x27AA); - AddImage(333, 2, 0x2716); - AddImage(333, 248, 0x2716); - AddImage(2, 248, 0x2716); - AddImage(2, 2, 0x2716); - - AddItem(140, 120, entry.ItemID, entry.Hue); - - if (entry.Tooltip != 0) - AddTooltip(entry.Tooltip); - - AddHtmlLocalized(25, 22, 200, 20, 1074974, 0x7D00); // Confirm Selection - AddImage(25, 40, 0xBBF); - AddHtmlLocalized(25, 55, 300, 120, 1074975, 0xFFFFFF); // Are you sure you wish to select this? - AddRadio(25, 175, 0x25F8, 0x25FB, true, 1); - AddRadio(25, 210, 0x25F8, 0x25FB, false, 0); - AddHtmlLocalized(60, 180, 280, 20, 1074976, 0xFFFFFF); // Yes - AddHtmlLocalized(60, 215, 280, 20, 1074977, 0xFFFFFF); // No - AddButton(265, 220, 0xF7, 0xF8, 7); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 7 && info.IsSwitched(1)) - m_Parent.OnPicked(sender.Mobile, m_Index); - else - sender.Mobile.SendGump(new RewardGump(m_Parent.Title, m_Parent.Rewards, m_Parent.Points, m_Parent.OnPicked)); - } - } -} +using System; +using Server.Network; + +namespace Server.Gumps +{ + /* + * A generic version of the EA Clean Up Britannia reward gump. + */ + + public interface IRewardEntry + { + int Price { get; } + int ItemID { get; } + int Hue { get; } + int Tooltip { get; } + TextDefinition Description { get; } + } + + public delegate void RewardPickedHandler(Mobile from, int index); + + public class RewardGump : Gump + { + public RewardGump(TextDefinition title, IRewardEntry[] rewards, int points, RewardPickedHandler onPicked) + : base(250, 50) + { + Title = title; + Rewards = rewards; + Points = points; + OnPicked = onPicked; + + AddPage(0); + + AddImage(0, 0, 0x1F40); + AddImageTiled(20, 37, 300, 308, 0x1F42); + AddImage(20, 325, 0x1F43); + AddImage(35, 8, 0x39); + AddImageTiled(65, 8, 257, 10, 0x3A); + AddImage(290, 8, 0x3B); + AddImage(32, 33, 0x2635); + AddImageTiled(70, 55, 230, 2, 0x23C5); + + if (Title.String != null) + AddHtml(70, 35, 270, 20, Title.String); + else if (Title.Number != 0) + AddHtmlLocalized(70, 35, 270, 20, Title.Number, 1); + + AddHtmlLocalized(50, 65, 150, 20, 1072843, 1); // Your Reward Points: + AddLabel(230, 65, 0x64, Points.ToString()); + AddImageTiled(35, 85, 270, 2, 0x23C5); + AddHtmlLocalized(35, 90, 270, 20, 1072844, 1); // Please Choose a Reward: + + AddPage(1); + + var offset = 110; + var page = 1; + + for (var i = 0; i < Rewards.Length; ++i) + { + var entry = Rewards[i]; + + var bounds = ItemBounds.Table[entry.ItemID]; + var height = Math.Max(36, bounds.Height); + + if (offset + height > 320) + { + AddHtmlLocalized(240, 335, 60, 20, 1072854, 1); //
Next
+ AddButton(300, 335, 0x15E1, 0x15E5, 51, GumpButtonType.Page, page + 1); + + AddPage(++page); + + AddButton(150, 335, 0x15E3, 0x15E7, 52, GumpButtonType.Page, page - 1); + AddHtmlLocalized(170, 335, 60, 20, 1074880, 1); // Previous + + offset = 110; + } + + var available = entry.Price <= Points; + var half = offset + height / 2; + + if (available) + AddButton(35, half - 6, 0x837, 0x838, 100 + i); + + AddItem( + 83 - bounds.Width / 2 - bounds.X, + half - bounds.Height / 2 - bounds.Y, + entry.ItemID, + available ? entry.Hue : 995 + ); + + if (entry.Tooltip != 0) + AddTooltip(entry.Tooltip); + + AddLabel(133, half - 10, available ? 0x64 : 0x21, entry.Price.ToString()); + + if (entry.Description != null) + { + if (entry.Description.String != null) + AddHtml(190, offset, 114, height, entry.Description.String); + else if (entry.Description.Number != 0) + AddHtmlLocalized(190, offset, 114, height, entry.Description.Number, 1); + } + + offset += height + 10; + } + } + + public TextDefinition Title { get; } + + public IRewardEntry[] Rewards { get; } + + public int Points { get; } + + public RewardPickedHandler OnPicked { get; } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var choice = info.ButtonID; + + if (choice == 0) + return; // Close + + choice -= 100; + + if (choice >= 0 && choice < Rewards.Length) + { + var entry = Rewards[choice]; + + if (entry.Price <= Points) + sender.Mobile.SendGump(new RewardConfirmGump(this, choice, entry)); + } + } + } + + public class RewardConfirmGump : Gump + { + private readonly int m_Index; + private readonly RewardGump m_Parent; + + public RewardConfirmGump(RewardGump parent, int index, IRewardEntry entry) + : base(120, 50) + { + m_Parent = parent; + m_Index = index; + + Closable = false; + + AddPage(0); + + AddImageTiled(0, 0, 348, 262, 0xA8E); + AddAlphaRegion(0, 0, 348, 262); + AddImage(0, 15, 0x27A8); + AddImageTiled(0, 30, 17, 200, 0x27A7); + AddImage(0, 230, 0x27AA); + AddImage(15, 0, 0x280C); + AddImageTiled(30, 0, 300, 17, 0x280A); + AddImage(315, 0, 0x280E); + AddImage(15, 244, 0x280C); + AddImageTiled(30, 244, 300, 17, 0x280A); + AddImage(315, 244, 0x280E); + AddImage(330, 15, 0x27A8); + AddImageTiled(330, 30, 17, 200, 0x27A7); + AddImage(330, 230, 0x27AA); + AddImage(333, 2, 0x2716); + AddImage(333, 248, 0x2716); + AddImage(2, 248, 0x2716); + AddImage(2, 2, 0x2716); + + AddItem(140, 120, entry.ItemID, entry.Hue); + + if (entry.Tooltip != 0) + AddTooltip(entry.Tooltip); + + AddHtmlLocalized(25, 22, 200, 20, 1074974, 0x7D00); // Confirm Selection + AddImage(25, 40, 0xBBF); + AddHtmlLocalized(25, 55, 300, 120, 1074975, 0xFFFFFF); // Are you sure you wish to select this? + AddRadio(25, 175, 0x25F8, 0x25FB, true, 1); + AddRadio(25, 210, 0x25F8, 0x25FB, false, 0); + AddHtmlLocalized(60, 180, 280, 20, 1074976, 0xFFFFFF); // Yes + AddHtmlLocalized(60, 215, 280, 20, 1074977, 0xFFFFFF); // No + AddButton(265, 220, 0xF7, 0xF8, 7); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 7 && info.IsSwitched(1)) + m_Parent.OnPicked(sender.Mobile, m_Index); + else + sender.Mobile.SendGump(new RewardGump(m_Parent.Title, m_Parent.Rewards, m_Parent.Points, m_Parent.OnPicked)); + } + } +} diff --git a/Projects/UOContent/Gumps/RunebookGump.cs b/Projects/UOContent/Gumps/RunebookGump.cs index 1899a0a71..38c0ad257 100644 --- a/Projects/UOContent/Gumps/RunebookGump.cs +++ b/Projects/UOContent/Gumps/RunebookGump.cs @@ -1,446 +1,480 @@ -using System.Collections.Generic; -using Server.Items; -using Server.Multis; -using Server.Network; -using Server.Prompts; -using Server.Spells.Chivalry; -using Server.Spells.Fourth; -using Server.Spells.Seventh; - -namespace Server.Gumps -{ - public class RunebookGump : Gump - { - public RunebookGump(Mobile from, Runebook book) : base(150, 200) - { - Book = book; - - AddBackground(); - AddIndex(); - - for (int page = 0; page < 8; ++page) - { - AddPage(2 + page); - - AddButton(125, 14, 2205, 2205, 0, GumpButtonType.Page, 1 + page); - - if (page < 7) - AddButton(393, 14, 2206, 2206, 0, GumpButtonType.Page, 3 + page); - - for (int half = 0; half < 2; ++half) - AddDetails(page * 2 + half, half); - } - } - - public Runebook Book { get; } - - public int GetMapHue(Map map) - { - if (map == Map.Trammel) - return 10; - if (map == Map.Felucca) - return 81; - if (map == Map.Ilshenar) - return 1102; - if (map == Map.Malas) - return 1102; - if (map == Map.Tokuno) - return 1154; - - return 0; - } - - public string GetName(string name) - { - if (name == null || (name = name.Trim()).Length <= 0) - return "(indescript)"; - - return name; - } - - private void AddBackground() - { - AddPage(0); - - // Background image - AddImage(100, 10, 2200); - - // Two separators - for (int i = 0; i < 2; ++i) - { - int xOffset = 125 + i * 165; - - AddImage(xOffset, 50, 57); - xOffset += 20; - - for (int j = 0; j < 6; ++j, xOffset += 15) - AddImage(xOffset, 50, 58); - - AddImage(xOffset - 5, 50, 59); - } - - // First four page buttons - for (int i = 0, xOffset = 130, gumpID = 2225; i < 4; ++i, xOffset += 35, ++gumpID) - AddButton(xOffset, 187, gumpID, gumpID, 0, GumpButtonType.Page, 2 + i); - - // Next four page buttons - for (int i = 0, xOffset = 300, gumpID = 2229; i < 4; ++i, xOffset += 35, ++gumpID) - AddButton(xOffset, 187, gumpID, gumpID, 0, GumpButtonType.Page, 6 + i); - - // Charges - AddHtmlLocalized(140, 40, 80, 18, 1011296); // Charges: - AddHtml(220, 40, 30, 18, Book.CurCharges.ToString()); - - // Max charges - AddHtmlLocalized(300, 40, 100, 18, 1011297); // Max Charges: - AddHtml(400, 40, 30, 18, Book.MaxCharges.ToString()); - } - - private void AddIndex() - { - // Index - AddPage(1); - - // Rename button - AddButton(125, 15, 2472, 2473, 1); - AddHtmlLocalized(158, 22, 100, 18, 1011299); // Rename book - - // List of entries - List entries = Book.Entries; - - for (int i = 0; i < 16; ++i) - { - string desc; - int hue; - - if (i < entries.Count) - { - desc = GetName(entries[i].Description); - hue = GetMapHue(entries[i].Map); - } - else - { - desc = "Empty"; - hue = 0; - } - - // Use charge button - AddButton(130 + i / 8 * 160, 65 + i % 8 * 15, 2103, 2104, 2 + i * 6 + 0); - - // Description label - AddLabelCropped(145 + i / 8 * 160, 60 + i % 8 * 15, 115, 17, hue, desc); - } - - // Turn page button - AddButton(393, 14, 2206, 2206, 0, GumpButtonType.Page, 2); - } - - private void AddDetails(int index, int half) - { - // Use charge button - AddButton(130 + half * 160, 65, 2103, 2104, 2 + index * 6 + 0); - - string desc; - int hue; - - if (index < Book.Entries.Count) - { - RunebookEntry e = Book.Entries[index]; - - desc = GetName(e.Description); - hue = GetMapHue(e.Map); - - // Location labels - int xLong = 0, yLat = 0; - int xMins = 0, yMins = 0; - bool xEast = false, ySouth = false; - - if (Sextant.Format(e.Location, e.Map, ref xLong, ref yLat, ref xMins, ref yMins, ref xEast, ref ySouth)) - { - AddLabel(135 + half * 160, 80, 0, $"{yLat}� {yMins}'{(ySouth ? "S" : "N")}"); - AddLabel(135 + half * 160, 95, 0, $"{xLong}� {xMins}'{(xEast ? "E" : "W")}"); - } - - // Drop rune button - AddButton(135 + half * 160, 115, 2437, 2438, 2 + index * 6 + 1); - AddHtmlLocalized(150 + half * 160, 115, 100, 18, 1011298); // Drop rune - - // Set as default button - int defButtonID = e != Book.Default ? 2361 : 2360; - - AddButton(160 + half * 140, 20, defButtonID, defButtonID, 2 + index * 6 + 2); - AddHtmlLocalized(175 + half * 140, 15, 100, 18, 1011300); // Set default - - if (Core.AOS) - { - AddButton(135 + half * 160, 140, 2103, 2104, 2 + index * 6 + 3); - AddHtmlLocalized(150 + half * 160, 136, 110, 20, 1062722); // Recall - - AddButton(135 + half * 160, 158, 2103, 2104, 2 + index * 6 + 4); - AddHtmlLocalized(150 + half * 160, 154, 110, 20, 1062723); // Gate Travel - - AddButton(135 + half * 160, 176, 2103, 2104, 2 + index * 6 + 5); - AddHtmlLocalized(150 + half * 160, 172, 110, 20, 1062724); // Sacred Journey - } - else - { - // Recall button - AddButton(135 + half * 160, 140, 2271, 2271, 2 + index * 6 + 3); - - // Gate button - AddButton(205 + half * 160, 140, 2291, 2291, 2 + index * 6 + 4); - } - } - else - { - desc = "Empty"; - hue = 0; - } - - // Description label - AddLabelCropped(145 + half * 160, 60, 115, 17, hue, desc); - } - - public static bool HasSpell(Mobile from, int spellID) => Spellbook.Find(from, spellID)?.HasSpell(spellID) == true; - - public override void OnResponse(NetState state, RelayInfo info) - { - Mobile from = state.Mobile; - - if (Book.Deleted || !from.InRange(Book.GetWorldLocation(), Core.ML ? 3 : 1) || !DesignContext.Check(from)) - { - Book.Openers.Remove(from); - return; - } - - int buttonID = info.ButtonID; - - if (buttonID == 1) // Rename book - { - if (!Book.IsLockedDown || from.AccessLevel >= AccessLevel.GameMaster) - { - from.SendLocalizedMessage(502414); // Please enter a title for the runebook: - from.Prompt = new InternalPrompt(Book); - } - else - { - Book.Openers.Remove(from); - - from.SendLocalizedMessage(502413, null, 0x35); // That cannot be done while the book is locked down. - } - } - else - { - buttonID -= 2; - - int index = buttonID / 6; - int type = buttonID % 6; - - if (index >= 0 && index < Book.Entries.Count) - { - RunebookEntry e = Book.Entries[index]; - - switch (type) - { - case 0: // Use charges - { - if (Book.CurCharges <= 0) - { - from.CloseGump(); - from.SendGump(new RunebookGump(from, Book)); - - from.SendLocalizedMessage(502412); // There are no charges left on that item. - } - else - { - int xLong = 0, yLat = 0; - int xMins = 0, yMins = 0; - bool xEast = false, ySouth = false; - - if (Sextant.Format(e.Location, e.Map, ref xLong, ref yLat, ref xMins, ref yMins, ref xEast, - ref ySouth)) - { - string location = - $"{yLat}� {yMins}'{(ySouth ? "S" : "N")}, {xLong}� {xMins}'{(xEast ? "E" : "W")}"; - from.SendMessage(location); - } - - Book.OnTravel(); - new RecallSpell(from, e, Book, Book).Cast(); - - Book.Openers.Remove(from); - } - - break; - } - case 1: // Drop rune - { - if (!Book.IsLockedDown || from.AccessLevel >= AccessLevel.GameMaster) - { - Book.DropRune(from, e, index); - - from.CloseGump(); - if (!Core.ML) - from.SendGump(new RunebookGump(from, Book)); - } - else - { - Book.Openers.Remove(from); - - from.SendLocalizedMessage(502413, null, - 0x35); // That cannot be done while the book is locked down. - } - - break; - } - case 2: // Set default - { - if (Book.CheckAccess(from)) - { - Book.Default = e; - - from.CloseGump(); - from.SendGump(new RunebookGump(from, Book)); - - from.SendLocalizedMessage(502417); // New default location set. - } - - break; - } - case 3: // Recall - { - if (HasSpell(from, 31)) - { - int xLong = 0, yLat = 0; - int xMins = 0, yMins = 0; - bool xEast = false, ySouth = false; - - if (Sextant.Format(e.Location, e.Map, ref xLong, ref yLat, ref xMins, ref yMins, ref xEast, - ref ySouth)) - { - string location = - $"{yLat}� {yMins}'{(ySouth ? "S" : "N")}, {xLong}� {xMins}'{(xEast ? "E" : "W")}"; - from.SendMessage(location); - } - - Book.OnTravel(); - new RecallSpell(from, e).Cast(); - } - else - { - from.SendLocalizedMessage(500015); // You do not have that spell! - } - - Book.Openers.Remove(from); - - break; - } - case 4: // Gate - { - if (HasSpell(from, 51)) - { - int xLong = 0, yLat = 0; - int xMins = 0, yMins = 0; - bool xEast = false, ySouth = false; - - if (Sextant.Format(e.Location, e.Map, ref xLong, ref yLat, ref xMins, ref yMins, ref xEast, - ref ySouth)) - { - string location = - $"{yLat}� {yMins}'{(ySouth ? "S" : "N")}, {xLong}� {xMins}'{(xEast ? "E" : "W")}"; - from.SendMessage(location); - } - - Book.OnTravel(); - new GateTravelSpell(from, e).Cast(); - } - else - { - from.SendLocalizedMessage(500015); // You do not have that spell! - } - - Book.Openers.Remove(from); - - break; - } - case 5: // Sacred Journey - { - if (Core.AOS) - { - if (HasSpell(from, 209)) - { - int xLong = 0, yLat = 0; - int xMins = 0, yMins = 0; - bool xEast = false, ySouth = false; - - if (Sextant.Format(e.Location, e.Map, ref xLong, ref yLat, ref xMins, ref yMins, - ref xEast, ref ySouth)) - { - string location = - $"{yLat}� {yMins}'{(ySouth ? "S" : "N")}, {xLong}� {xMins}'{(xEast ? "E" : "W")}"; - from.SendMessage(location); - } - - Book.OnTravel(); - new SacredJourneySpell(from, e).Cast(); - } - else - { - from.SendLocalizedMessage(500015); // You do not have that spell! - } - } - - Book.Openers.Remove(from); - - break; - } - } - } - else - { - Book.Openers.Remove(from); - } - } - } - - private class InternalPrompt : Prompt - { - private readonly Runebook m_Book; - - public InternalPrompt(Runebook book) => m_Book = book; - - public override void OnResponse(Mobile from, string text) - { - if (m_Book.Deleted || !from.InRange(m_Book.GetWorldLocation(), Core.ML ? 3 : 1)) - return; - - if (m_Book.CheckAccess(from)) - { - m_Book.Description = Utility.FixHtml(text.Trim()); - - from.CloseGump(); - from.SendGump(new RunebookGump(from, m_Book)); - - from.SendMessage("The book's title has been changed."); - } - else - { - m_Book.Openers.Remove(from); - - from.SendLocalizedMessage(502416); // That cannot be done while the book is locked down. - } - } - - public override void OnCancel(Mobile from) - { - from.SendLocalizedMessage(502415); // Request cancelled. - - if (!m_Book.Deleted && from.InRange(m_Book.GetWorldLocation(), Core.ML ? 3 : 1)) - { - from.CloseGump(); - from.SendGump(new RunebookGump(from, m_Book)); - } - } - } - } -} +using Server.Items; +using Server.Multis; +using Server.Network; +using Server.Prompts; +using Server.Spells.Chivalry; +using Server.Spells.Fourth; +using Server.Spells.Seventh; + +namespace Server.Gumps +{ + public class RunebookGump : Gump + { + public RunebookGump(Mobile from, Runebook book) : base(150, 200) + { + Book = book; + + AddBackground(); + AddIndex(); + + for (var page = 0; page < 8; ++page) + { + AddPage(2 + page); + + AddButton(125, 14, 2205, 2205, 0, GumpButtonType.Page, 1 + page); + + if (page < 7) + AddButton(393, 14, 2206, 2206, 0, GumpButtonType.Page, 3 + page); + + for (var half = 0; half < 2; ++half) + AddDetails(page * 2 + half, half); + } + } + + public Runebook Book { get; } + + public int GetMapHue(Map map) + { + if (map == Map.Trammel) + return 10; + if (map == Map.Felucca) + return 81; + if (map == Map.Ilshenar) + return 1102; + if (map == Map.Malas) + return 1102; + if (map == Map.Tokuno) + return 1154; + + return 0; + } + + public string GetName(string name) + { + if (name == null || (name = name.Trim()).Length <= 0) + return "(indescript)"; + + return name; + } + + private void AddBackground() + { + AddPage(0); + + // Background image + AddImage(100, 10, 2200); + + // Two separators + for (var i = 0; i < 2; ++i) + { + var xOffset = 125 + i * 165; + + AddImage(xOffset, 50, 57); + xOffset += 20; + + for (var j = 0; j < 6; ++j, xOffset += 15) + AddImage(xOffset, 50, 58); + + AddImage(xOffset - 5, 50, 59); + } + + // First four page buttons + for (int i = 0, xOffset = 130, gumpID = 2225; i < 4; ++i, xOffset += 35, ++gumpID) + AddButton(xOffset, 187, gumpID, gumpID, 0, GumpButtonType.Page, 2 + i); + + // Next four page buttons + for (int i = 0, xOffset = 300, gumpID = 2229; i < 4; ++i, xOffset += 35, ++gumpID) + AddButton(xOffset, 187, gumpID, gumpID, 0, GumpButtonType.Page, 6 + i); + + // Charges + AddHtmlLocalized(140, 40, 80, 18, 1011296); // Charges: + AddHtml(220, 40, 30, 18, Book.CurCharges.ToString()); + + // Max charges + AddHtmlLocalized(300, 40, 100, 18, 1011297); // Max Charges: + AddHtml(400, 40, 30, 18, Book.MaxCharges.ToString()); + } + + private void AddIndex() + { + // Index + AddPage(1); + + // Rename button + AddButton(125, 15, 2472, 2473, 1); + AddHtmlLocalized(158, 22, 100, 18, 1011299); // Rename book + + // List of entries + var entries = Book.Entries; + + for (var i = 0; i < 16; ++i) + { + string desc; + int hue; + + if (i < entries.Count) + { + desc = GetName(entries[i].Description); + hue = GetMapHue(entries[i].Map); + } + else + { + desc = "Empty"; + hue = 0; + } + + // Use charge button + AddButton(130 + i / 8 * 160, 65 + i % 8 * 15, 2103, 2104, 2 + i * 6 + 0); + + // Description label + AddLabelCropped(145 + i / 8 * 160, 60 + i % 8 * 15, 115, 17, hue, desc); + } + + // Turn page button + AddButton(393, 14, 2206, 2206, 0, GumpButtonType.Page, 2); + } + + private void AddDetails(int index, int half) + { + // Use charge button + AddButton(130 + half * 160, 65, 2103, 2104, 2 + index * 6 + 0); + + string desc; + int hue; + + if (index < Book.Entries.Count) + { + var e = Book.Entries[index]; + + desc = GetName(e.Description); + hue = GetMapHue(e.Map); + + // Location labels + int xLong = 0, yLat = 0; + int xMins = 0, yMins = 0; + bool xEast = false, ySouth = false; + + if (Sextant.Format(e.Location, e.Map, ref xLong, ref yLat, ref xMins, ref yMins, ref xEast, ref ySouth)) + { + AddLabel(135 + half * 160, 80, 0, $"{yLat}� {yMins}'{(ySouth ? "S" : "N")}"); + AddLabel(135 + half * 160, 95, 0, $"{xLong}� {xMins}'{(xEast ? "E" : "W")}"); + } + + // Drop rune button + AddButton(135 + half * 160, 115, 2437, 2438, 2 + index * 6 + 1); + AddHtmlLocalized(150 + half * 160, 115, 100, 18, 1011298); // Drop rune + + // Set as default button + var defButtonID = e != Book.Default ? 2361 : 2360; + + AddButton(160 + half * 140, 20, defButtonID, defButtonID, 2 + index * 6 + 2); + AddHtmlLocalized(175 + half * 140, 15, 100, 18, 1011300); // Set default + + if (Core.AOS) + { + AddButton(135 + half * 160, 140, 2103, 2104, 2 + index * 6 + 3); + AddHtmlLocalized(150 + half * 160, 136, 110, 20, 1062722); // Recall + + AddButton(135 + half * 160, 158, 2103, 2104, 2 + index * 6 + 4); + AddHtmlLocalized(150 + half * 160, 154, 110, 20, 1062723); // Gate Travel + + AddButton(135 + half * 160, 176, 2103, 2104, 2 + index * 6 + 5); + AddHtmlLocalized(150 + half * 160, 172, 110, 20, 1062724); // Sacred Journey + } + else + { + // Recall button + AddButton(135 + half * 160, 140, 2271, 2271, 2 + index * 6 + 3); + + // Gate button + AddButton(205 + half * 160, 140, 2291, 2291, 2 + index * 6 + 4); + } + } + else + { + desc = "Empty"; + hue = 0; + } + + // Description label + AddLabelCropped(145 + half * 160, 60, 115, 17, hue, desc); + } + + public static bool HasSpell(Mobile from, int spellID) => Spellbook.Find(from, spellID)?.HasSpell(spellID) == true; + + public override void OnResponse(NetState state, RelayInfo info) + { + var from = state.Mobile; + + if (Book.Deleted || !from.InRange(Book.GetWorldLocation(), Core.ML ? 3 : 1) || !DesignContext.Check(from)) + { + Book.Openers.Remove(from); + return; + } + + var buttonID = info.ButtonID; + + if (buttonID == 1) // Rename book + { + if (!Book.IsLockedDown || from.AccessLevel >= AccessLevel.GameMaster) + { + from.SendLocalizedMessage(502414); // Please enter a title for the runebook: + from.Prompt = new InternalPrompt(Book); + } + else + { + Book.Openers.Remove(from); + + from.SendLocalizedMessage(502413, null, 0x35); // That cannot be done while the book is locked down. + } + } + else + { + buttonID -= 2; + + var index = buttonID / 6; + var type = buttonID % 6; + + if (index >= 0 && index < Book.Entries.Count) + { + var e = Book.Entries[index]; + + switch (type) + { + case 0: // Use charges + { + if (Book.CurCharges <= 0) + { + from.CloseGump(); + from.SendGump(new RunebookGump(from, Book)); + + from.SendLocalizedMessage(502412); // There are no charges left on that item. + } + else + { + int xLong = 0, yLat = 0; + int xMins = 0, yMins = 0; + bool xEast = false, ySouth = false; + + if (Sextant.Format( + e.Location, + e.Map, + ref xLong, + ref yLat, + ref xMins, + ref yMins, + ref xEast, + ref ySouth + )) + { + var location = + $"{yLat}� {yMins}'{(ySouth ? "S" : "N")}, {xLong}� {xMins}'{(xEast ? "E" : "W")}"; + from.SendMessage(location); + } + + Book.OnTravel(); + new RecallSpell(from, e, Book, Book).Cast(); + + Book.Openers.Remove(from); + } + + break; + } + case 1: // Drop rune + { + if (!Book.IsLockedDown || from.AccessLevel >= AccessLevel.GameMaster) + { + Book.DropRune(from, e, index); + + from.CloseGump(); + if (!Core.ML) + from.SendGump(new RunebookGump(from, Book)); + } + else + { + Book.Openers.Remove(from); + + from.SendLocalizedMessage( + 502413, + null, + 0x35 + ); // That cannot be done while the book is locked down. + } + + break; + } + case 2: // Set default + { + if (Book.CheckAccess(from)) + { + Book.Default = e; + + from.CloseGump(); + from.SendGump(new RunebookGump(from, Book)); + + from.SendLocalizedMessage(502417); // New default location set. + } + + break; + } + case 3: // Recall + { + if (HasSpell(from, 31)) + { + int xLong = 0, yLat = 0; + int xMins = 0, yMins = 0; + bool xEast = false, ySouth = false; + + if (Sextant.Format( + e.Location, + e.Map, + ref xLong, + ref yLat, + ref xMins, + ref yMins, + ref xEast, + ref ySouth + )) + { + var location = + $"{yLat}� {yMins}'{(ySouth ? "S" : "N")}, {xLong}� {xMins}'{(xEast ? "E" : "W")}"; + from.SendMessage(location); + } + + Book.OnTravel(); + new RecallSpell(from, e).Cast(); + } + else + { + from.SendLocalizedMessage(500015); // You do not have that spell! + } + + Book.Openers.Remove(from); + + break; + } + case 4: // Gate + { + if (HasSpell(from, 51)) + { + int xLong = 0, yLat = 0; + int xMins = 0, yMins = 0; + bool xEast = false, ySouth = false; + + if (Sextant.Format( + e.Location, + e.Map, + ref xLong, + ref yLat, + ref xMins, + ref yMins, + ref xEast, + ref ySouth + )) + { + var location = + $"{yLat}� {yMins}'{(ySouth ? "S" : "N")}, {xLong}� {xMins}'{(xEast ? "E" : "W")}"; + from.SendMessage(location); + } + + Book.OnTravel(); + new GateTravelSpell(from, e).Cast(); + } + else + { + from.SendLocalizedMessage(500015); // You do not have that spell! + } + + Book.Openers.Remove(from); + + break; + } + case 5: // Sacred Journey + { + if (Core.AOS) + { + if (HasSpell(from, 209)) + { + int xLong = 0, yLat = 0; + int xMins = 0, yMins = 0; + bool xEast = false, ySouth = false; + + if (Sextant.Format( + e.Location, + e.Map, + ref xLong, + ref yLat, + ref xMins, + ref yMins, + ref xEast, + ref ySouth + )) + { + var location = + $"{yLat}� {yMins}'{(ySouth ? "S" : "N")}, {xLong}� {xMins}'{(xEast ? "E" : "W")}"; + from.SendMessage(location); + } + + Book.OnTravel(); + new SacredJourneySpell(from, e).Cast(); + } + else + { + from.SendLocalizedMessage(500015); // You do not have that spell! + } + } + + Book.Openers.Remove(from); + + break; + } + } + } + else + { + Book.Openers.Remove(from); + } + } + } + + private class InternalPrompt : Prompt + { + private readonly Runebook m_Book; + + public InternalPrompt(Runebook book) => m_Book = book; + + public override void OnResponse(Mobile from, string text) + { + if (m_Book.Deleted || !from.InRange(m_Book.GetWorldLocation(), Core.ML ? 3 : 1)) + return; + + if (m_Book.CheckAccess(from)) + { + m_Book.Description = Utility.FixHtml(text.Trim()); + + from.CloseGump(); + from.SendGump(new RunebookGump(from, m_Book)); + + from.SendMessage("The book's title has been changed."); + } + else + { + m_Book.Openers.Remove(from); + + from.SendLocalizedMessage(502416); // That cannot be done while the book is locked down. + } + } + + public override void OnCancel(Mobile from) + { + from.SendLocalizedMessage(502415); // Request cancelled. + + if (!m_Book.Deleted && from.InRange(m_Book.GetWorldLocation(), Core.ML ? 3 : 1)) + { + from.CloseGump(); + from.SendGump(new RunebookGump(from, m_Book)); + } + } + } + } +} diff --git a/Projects/UOContent/Gumps/SetSecureLevelGump.cs b/Projects/UOContent/Gumps/SetSecureLevelGump.cs index 1c05318ce..1e274f93d 100644 --- a/Projects/UOContent/Gumps/SetSecureLevelGump.cs +++ b/Projects/UOContent/Gumps/SetSecureLevelGump.cs @@ -1,85 +1,86 @@ -using Server.Guilds; -using Server.Multis; -using Server.Network; - -namespace Server.Gumps -{ - public interface ISecurable - { - SecureLevel Level { get; set; } - } - - public class SetSecureLevelGump : Gump - { - private readonly ISecurable m_Info; - - public SetSecureLevelGump(Mobile owner, ISecurable info, BaseHouse house) : base(50, 50) - { - m_Info = info; - - AddPage(0); - - int offset = Guild.NewGuildSystem ? 20 : 0; - - AddBackground(0, 0, 220, 160 + offset, 5054); - - AddImageTiled(10, 10, 200, 20, 5124); - AddImageTiled(10, 40, 200, 20, 5124); - AddImageTiled(10, 70, 200, 80 + offset, 5124); - - AddAlphaRegion(10, 10, 200, 140); - - AddHtmlLocalized(10, 10, 200, 20, 1061276, 32767); //
SET ACCESS
- AddHtmlLocalized(10, 40, 100, 20, 1041474, 32767); // Owner: - - AddLabel(110, 40, 1152, owner == null ? "" : owner.Name); - - AddButton(10, 70, GetFirstID(SecureLevel.Owner), 4007, 1); - AddHtmlLocalized(45, 70, 150, 20, 1061277, GetColor(SecureLevel.Owner)); // Owner Only - - AddButton(10, 90, GetFirstID(SecureLevel.CoOwners), 4007, 2); - AddHtmlLocalized(45, 90, 150, 20, 1061278, GetColor(SecureLevel.CoOwners)); // Co-Owners - - AddButton(10, 110, GetFirstID(SecureLevel.Friends), 4007, 3); - AddHtmlLocalized(45, 110, 150, 20, 1061279, GetColor(SecureLevel.Friends)); // Friends - - Mobile houseOwner = house.Owner; - if (Guild.NewGuildSystem && houseOwner?.Guild != null && - ((Guild)houseOwner.Guild).Leader == houseOwner) // Only the actual House owner AND guild master can set guild secures - { - AddButton(10, 130, GetFirstID(SecureLevel.Guild), 4007, 5); - AddHtmlLocalized(45, 130, 150, 20, 1063455, GetColor(SecureLevel.Guild)); // Guild Members - } - - AddButton(10, 130 + offset, GetFirstID(SecureLevel.Anyone), 4007, 4); - AddHtmlLocalized(45, 130 + offset, 150, 20, 1061626, GetColor(SecureLevel.Anyone)); // Anyone - } - - public int GetColor(SecureLevel level) => m_Info.Level == level ? 0x7F18 : 0x7FFF; - - public int GetFirstID(SecureLevel level) => m_Info.Level == level ? 4006 : 4005; - - public override void OnResponse(NetState state, RelayInfo info) - { - var level = info.ButtonID switch - { - 1 => SecureLevel.Owner, - 2 => SecureLevel.CoOwners, - 3 => SecureLevel.Friends, - 4 => SecureLevel.Anyone, - 5 => SecureLevel.Guild, - _ => m_Info.Level - }; - - if (m_Info.Level == level) - { - state.Mobile.SendLocalizedMessage(1061281); // Access level unchanged. - } - else - { - m_Info.Level = level; - state.Mobile.SendLocalizedMessage(1061280); // New access level set. - } - } - } -} +using Server.Guilds; +using Server.Multis; +using Server.Network; + +namespace Server.Gumps +{ + public interface ISecurable + { + SecureLevel Level { get; set; } + } + + public class SetSecureLevelGump : Gump + { + private readonly ISecurable m_Info; + + public SetSecureLevelGump(Mobile owner, ISecurable info, BaseHouse house) : base(50, 50) + { + m_Info = info; + + AddPage(0); + + var offset = Guild.NewGuildSystem ? 20 : 0; + + AddBackground(0, 0, 220, 160 + offset, 5054); + + AddImageTiled(10, 10, 200, 20, 5124); + AddImageTiled(10, 40, 200, 20, 5124); + AddImageTiled(10, 70, 200, 80 + offset, 5124); + + AddAlphaRegion(10, 10, 200, 140); + + AddHtmlLocalized(10, 10, 200, 20, 1061276, 32767); //
SET ACCESS
+ AddHtmlLocalized(10, 40, 100, 20, 1041474, 32767); // Owner: + + AddLabel(110, 40, 1152, owner == null ? "" : owner.Name); + + AddButton(10, 70, GetFirstID(SecureLevel.Owner), 4007, 1); + AddHtmlLocalized(45, 70, 150, 20, 1061277, GetColor(SecureLevel.Owner)); // Owner Only + + AddButton(10, 90, GetFirstID(SecureLevel.CoOwners), 4007, 2); + AddHtmlLocalized(45, 90, 150, 20, 1061278, GetColor(SecureLevel.CoOwners)); // Co-Owners + + AddButton(10, 110, GetFirstID(SecureLevel.Friends), 4007, 3); + AddHtmlLocalized(45, 110, 150, 20, 1061279, GetColor(SecureLevel.Friends)); // Friends + + var houseOwner = house.Owner; + if (Guild.NewGuildSystem && houseOwner?.Guild != null && + ((Guild)houseOwner.Guild).Leader == houseOwner + ) // Only the actual House owner AND guild master can set guild secures + { + AddButton(10, 130, GetFirstID(SecureLevel.Guild), 4007, 5); + AddHtmlLocalized(45, 130, 150, 20, 1063455, GetColor(SecureLevel.Guild)); // Guild Members + } + + AddButton(10, 130 + offset, GetFirstID(SecureLevel.Anyone), 4007, 4); + AddHtmlLocalized(45, 130 + offset, 150, 20, 1061626, GetColor(SecureLevel.Anyone)); // Anyone + } + + public int GetColor(SecureLevel level) => m_Info.Level == level ? 0x7F18 : 0x7FFF; + + public int GetFirstID(SecureLevel level) => m_Info.Level == level ? 4006 : 4005; + + public override void OnResponse(NetState state, RelayInfo info) + { + var level = info.ButtonID switch + { + 1 => SecureLevel.Owner, + 2 => SecureLevel.CoOwners, + 3 => SecureLevel.Friends, + 4 => SecureLevel.Anyone, + 5 => SecureLevel.Guild, + _ => m_Info.Level + }; + + if (m_Info.Level == level) + { + state.Mobile.SendLocalizedMessage(1061281); // Access level unchanged. + } + else + { + m_Info.Level = level; + state.Mobile.SendLocalizedMessage(1061280); // New access level set. + } + } + } +} diff --git a/Projects/UOContent/Gumps/SkillsGump.cs b/Projects/UOContent/Gumps/SkillsGump.cs index d2433812a..4751e853e 100644 --- a/Projects/UOContent/Gumps/SkillsGump.cs +++ b/Projects/UOContent/Gumps/SkillsGump.cs @@ -1,552 +1,605 @@ -using System; -using System.Collections.Generic; -using Server.Commands; -using Server.Network; - -namespace Server.Gumps -{ - public class EditSkillGump : Gump - { - public static readonly bool OldStyle = PropsConfig.OldStyle; - - public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; - public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; - - public static readonly int TextHue = PropsConfig.TextHue; - public static readonly int TextOffsetX = PropsConfig.TextOffsetX; - - public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; - public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; - public static readonly int EntryGumpID = PropsConfig.EntryGumpID; - public static readonly int BackGumpID = PropsConfig.BackGumpID; - public static readonly int SetGumpID = PropsConfig.SetGumpID; - - public static readonly int SetWidth = PropsConfig.SetWidth; - public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY; - public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; - public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; - - public static readonly int PrevWidth = PropsConfig.PrevWidth; - public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY; - public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; - public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; - - public static readonly int NextWidth = PropsConfig.NextWidth; - public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY; - public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; - public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; - - public static readonly int OffsetSize = PropsConfig.OffsetSize; - - public static readonly int EntryHeight = PropsConfig.EntryHeight; - public static readonly int BorderSize = PropsConfig.BorderSize; - - private static readonly int EntryWidth = 160; - - private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize; - private static readonly int TotalHeight = OffsetSize + 2 * (EntryHeight + OffsetSize); - - private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; - private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize; - - private readonly Mobile m_From; - - private readonly SkillsGumpGroup m_Selected; - private readonly Skill m_Skill; - private readonly Mobile m_Target; - - public EditSkillGump(Mobile from, Mobile target, Skill skill, SkillsGumpGroup selected) : base(GumpOffsetX, - GumpOffsetY) - { - m_From = from; - m_Target = target; - m_Skill = skill; - m_Selected = selected; - - string initialText = m_Skill.Base.ToString("F1"); - - AddPage(0); - - AddBackground(0, 0, BackWidth, BackHeight, BackGumpID); - AddImageTiled(BorderSize, BorderSize, TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), TotalHeight, - OffsetGumpID); - - int x = BorderSize + OffsetSize; - int y = BorderSize + OffsetSize; - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, skill.Name); - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - - x = BorderSize + OffsetSize; - y += EntryHeight + OffsetSize; - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddTextEntry(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, 0, initialText); - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - - AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 1); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 1) - try - { - if (m_From.AccessLevel >= AccessLevel.GameMaster) - { - TextRelay text = info.GetTextEntry(0); - - if (text != null) - { - m_Skill.Base = Convert.ToDouble(text.Text); - CommandLogging.LogChangeProperty(m_From, m_Target, $"{m_Skill}.Base", m_Skill.Base.ToString()); - } - } - else - { - m_From.SendMessage("You may not change that."); - } - - m_From.SendGump(new SkillsGump(m_From, m_Target, m_Selected)); - } - catch - { - m_From.SendMessage("Bad format. ###.# expected."); - m_From.SendGump(new EditSkillGump(m_From, m_Target, m_Skill, m_Selected)); - } - else - m_From.SendGump(new SkillsGump(m_From, m_Target, m_Selected)); - } - } - - public class SkillsGump : Gump - { - public static bool OldStyle = PropsConfig.OldStyle; - - public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; - public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; - - public static readonly int TextHue = PropsConfig.TextHue; - public static readonly int TextOffsetX = PropsConfig.TextOffsetX; - - public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; - public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; - public static readonly int EntryGumpID = PropsConfig.EntryGumpID; - public static readonly int BackGumpID = PropsConfig.BackGumpID; - public static readonly int SetGumpID = PropsConfig.SetGumpID; - - public static readonly int SetWidth = PropsConfig.SetWidth; - public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY; - public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; - public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; - - public static readonly int PrevWidth = PropsConfig.PrevWidth; - public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY; - public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; - public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; - - public static readonly int NextWidth = PropsConfig.NextWidth; - public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY; - public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; - public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; - - public static readonly int OffsetSize = PropsConfig.OffsetSize; - - public static readonly int EntryHeight = PropsConfig.EntryHeight; - public static readonly int BorderSize = PropsConfig.BorderSize; - - /* - private static bool PrevLabel = OldStyle, NextLabel = OldStyle; - - private static readonly int PrevLabelOffsetX = PrevWidth + 1; - - private static readonly int PrevLabelOffsetY = 0; - - private static readonly int NextLabelOffsetX = -29; - private static readonly int NextLabelOffsetY = 0; - * */ - - private static readonly int NameWidth = 107; - private static readonly int ValueWidth = 128; - - private static readonly int EntryCount = 15; - - private static readonly int TypeWidth = NameWidth + OffsetSize + ValueWidth; - - private static readonly int TotalWidth = - OffsetSize + NameWidth + OffsetSize + ValueWidth + OffsetSize + SetWidth + OffsetSize; - - private static readonly int TotalHeight = OffsetSize + (EntryHeight + OffsetSize) * (EntryCount + 1); - - private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; - private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize; - - private static readonly int IndentWidth = 12; - - private readonly Mobile m_From; - - private readonly SkillsGumpGroup[] m_Groups; - private readonly SkillsGumpGroup m_Selected; - private readonly Mobile m_Target; - - public SkillsGump(Mobile from, Mobile target, SkillsGumpGroup selected = null) : base(GumpOffsetX, GumpOffsetY) - { - m_From = from; - m_Target = target; - - m_Groups = SkillsGumpGroup.Groups; - m_Selected = selected; - - int count = m_Groups.Length; - - if (selected != null) - count += selected.Skills.Length; - - int totalHeight = OffsetSize + (EntryHeight + OffsetSize) * (count + 1); - - AddPage(0); - - AddBackground(0, 0, BackWidth, BorderSize + totalHeight + BorderSize, BackGumpID); - AddImageTiled(BorderSize, BorderSize, TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), totalHeight, - OffsetGumpID); - - int x = BorderSize + OffsetSize; - int y = BorderSize + OffsetSize; - - int emptyWidth = TotalWidth - PrevWidth - NextWidth - OffsetSize * 4 - (OldStyle ? SetWidth + OffsetSize : 0); - - if (OldStyle) - AddImageTiled(x, y, TotalWidth - OffsetSize * 3 - SetWidth, EntryHeight, HeaderGumpID); - else - AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); - - x += PrevWidth + OffsetSize; - - if (!OldStyle) - AddImageTiled(x - (OldStyle ? OffsetSize : 0), y, emptyWidth + (OldStyle ? OffsetSize * 2 : 0), EntryHeight, - HeaderGumpID); - - x += emptyWidth + OffsetSize; - - if (!OldStyle) - AddImageTiled(x, y, NextWidth, EntryHeight, HeaderGumpID); - - for (int i = 0; i < m_Groups.Length; ++i) - { - x = BorderSize + OffsetSize; - y += EntryHeight + OffsetSize; - - SkillsGumpGroup group = m_Groups[i]; - - AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); - - if (group == selected) - AddButton(x + PrevOffsetX, y + PrevOffsetY, 0x15E2, 0x15E6, GetButtonID(0, i)); - else - AddButton(x + PrevOffsetX, y + PrevOffsetY, 0x15E1, 0x15E5, GetButtonID(0, i)); - - x += PrevWidth + OffsetSize; - - x -= OldStyle ? OffsetSize : 0; - - AddImageTiled(x, y, emptyWidth + (OldStyle ? OffsetSize * 2 : 0), EntryHeight, EntryGumpID); - AddLabel(x + TextOffsetX, y, TextHue, group?.Name ?? ""); - - x += emptyWidth + (OldStyle ? OffsetSize * 2 : 0); - x += OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - - if (group == selected) - { - int indentMaskX = BorderSize; - int indentMaskY = y + EntryHeight + OffsetSize; - - for (int j = 0; j < group.Skills.Length; ++j) - { - Skill sk = target.Skills[group.Skills[j]]; - - x = BorderSize + OffsetSize; - y += EntryHeight + OffsetSize; - - x += OffsetSize; - x += IndentWidth; - - AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); - - AddButton(x + PrevOffsetX, y + PrevOffsetY, 0x15E1, 0x15E5, GetButtonID(1, j)); - - x += PrevWidth + OffsetSize; - - x -= OldStyle ? OffsetSize : 0; - - AddImageTiled(x, y, emptyWidth + (OldStyle ? OffsetSize * 2 : 0) - OffsetSize - IndentWidth, - EntryHeight, EntryGumpID); - AddLabel(x + TextOffsetX, y, TextHue, sk == null ? "(null)" : sk.Name); - - x += emptyWidth + (OldStyle ? OffsetSize * 2 : 0) - OffsetSize - IndentWidth; - x += OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - - if (sk != null) - { - int buttonID1, buttonID2; - int xOffset, yOffset; - - switch (sk.Lock) - { - default: - buttonID1 = 0x983; - buttonID2 = 0x983; - xOffset = 6; - yOffset = 4; - break; - case SkillLock.Down: - buttonID1 = 0x985; - buttonID2 = 0x985; - xOffset = 6; - yOffset = 4; - break; - case SkillLock.Locked: - buttonID1 = 0x82C; - buttonID2 = 0x82C; - xOffset = 5; - yOffset = 2; - break; - } - - AddButton(x + xOffset, y + yOffset, buttonID1, buttonID2, GetButtonID(2, j)); - - y += 1; - x -= OffsetSize; - x -= 1; - x -= 50; - - AddImageTiled(x, y, 50, EntryHeight - 2, OffsetGumpID); - - x += 1; - y += 1; - - AddImageTiled(x, y, 48, EntryHeight - 4, EntryGumpID); - - AddLabelCropped(x + TextOffsetX, y - 1, 48 - TextOffsetX, EntryHeight - 3, TextHue, - sk.Base.ToString("F1")); - - y -= 2; - } - } - - AddImageTiled(indentMaskX, indentMaskY, IndentWidth + OffsetSize, - group.Skills.Length * (EntryHeight + OffsetSize) - (i < m_Groups.Length - 1 ? OffsetSize : 0), - BackGumpID + 4); - } - } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - int buttonID = info.ButtonID - 1; - - int index = buttonID / 3; - int type = buttonID % 3; - - switch (type) - { - case 0: - { - if (index >= 0 && index < m_Groups.Length) - { - SkillsGumpGroup newSelection = m_Groups[index]; - - if (m_Selected != newSelection) - m_From.SendGump(new SkillsGump(m_From, m_Target, newSelection)); - else - m_From.SendGump(new SkillsGump(m_From, m_Target)); - } - - break; - } - case 1: - { - if (m_Selected != null && index >= 0 && index < m_Selected.Skills.Length) - { - Skill sk = m_Target.Skills[m_Selected.Skills[index]]; - - if (sk != null) - { - if (m_From.AccessLevel >= AccessLevel.GameMaster) - { - m_From.SendGump(new EditSkillGump(m_From, m_Target, sk, m_Selected)); - } - else - { - m_From.SendMessage("You may not change that."); - m_From.SendGump(new SkillsGump(m_From, m_Target, m_Selected)); - } - } - else - { - m_From.SendGump(new SkillsGump(m_From, m_Target, m_Selected)); - } - } - - break; - } - case 2: - { - if (m_Selected != null && index >= 0 && index < m_Selected.Skills.Length) - { - Skill sk = m_Target.Skills[m_Selected.Skills[index]]; - - if (sk != null) - { - if (m_From.AccessLevel >= AccessLevel.GameMaster) - switch (sk.Lock) - { - case SkillLock.Up: - sk.SetLockNoRelay(SkillLock.Down); - sk.Update(); - break; - case SkillLock.Down: - sk.SetLockNoRelay(SkillLock.Locked); - sk.Update(); - break; - case SkillLock.Locked: - sk.SetLockNoRelay(SkillLock.Up); - sk.Update(); - break; - } - else - m_From.SendMessage("You may not change that."); - - m_From.SendGump(new SkillsGump(m_From, m_Target, m_Selected)); - } - } - - break; - } - } - } - - public int GetButtonID(int type, int index) => 1 + index * 3 + type; - } - - public class SkillsGumpGroup - { - public SkillsGumpGroup(string name, SkillName[] skills) - { - Name = name; - Skills = skills; - - Array.Sort(Skills, new SkillNameComparer()); - } - - public string Name { get; } - - public SkillName[] Skills { get; } - - public static SkillsGumpGroup[] Groups { get; } = - { - new SkillsGumpGroup("Crafting", new[] - { - SkillName.Alchemy, - SkillName.Blacksmith, - SkillName.Cartography, - SkillName.Carpentry, - SkillName.Cooking, - SkillName.Fletching, - SkillName.Inscribe, - SkillName.Tailoring, - SkillName.Tinkering, - SkillName.Imbuing - }), - new SkillsGumpGroup("Bardic", new[] - { - SkillName.Discordance, - SkillName.Musicianship, - SkillName.Peacemaking, - SkillName.Provocation - }), - new SkillsGumpGroup("Magical", new[] - { - SkillName.Chivalry, - SkillName.EvalInt, - SkillName.Magery, - SkillName.MagicResist, - SkillName.Meditation, - SkillName.Necromancy, - SkillName.SpiritSpeak, - SkillName.Ninjitsu, - SkillName.Bushido, - SkillName.Spellweaving, - SkillName.Mysticism - }), - new SkillsGumpGroup("Miscellaneous", new[] - { - SkillName.Camping, - SkillName.Fishing, - SkillName.Focus, - SkillName.Healing, - SkillName.Herding, - SkillName.Lockpicking, - SkillName.Lumberjacking, - SkillName.Mining, - SkillName.Snooping, - SkillName.Veterinary - }), - new SkillsGumpGroup("Combat Ratings", new[] - { - SkillName.Archery, - SkillName.Fencing, - SkillName.Macing, - SkillName.Parry, - SkillName.Swords, - SkillName.Tactics, - SkillName.Wrestling, - SkillName.Throwing - }), - new SkillsGumpGroup("Actions", new[] - { - SkillName.AnimalTaming, - SkillName.Begging, - SkillName.DetectHidden, - SkillName.Hiding, - SkillName.RemoveTrap, - SkillName.Poisoning, - SkillName.Stealing, - SkillName.Stealth, - SkillName.Tracking - }), - new SkillsGumpGroup("Lore & Knowledge", new[] - { - SkillName.Anatomy, - SkillName.AnimalLore, - SkillName.ArmsLore, - SkillName.Forensics, - SkillName.ItemID, - SkillName.TasteID - }) - }; - - private class SkillNameComparer : IComparer - { - public int Compare(SkillName a, SkillName b) - { - string aName = SkillInfo.Table[(int)a].Name; - string bName = SkillInfo.Table[(int)b].Name; - - return aName.CompareTo(bName); - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Commands; +using Server.Network; + +namespace Server.Gumps +{ + public class EditSkillGump : Gump + { + public static readonly bool OldStyle = PropsConfig.OldStyle; + + public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; + public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; + + public static readonly int TextHue = PropsConfig.TextHue; + public static readonly int TextOffsetX = PropsConfig.TextOffsetX; + + public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; + public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; + public static readonly int EntryGumpID = PropsConfig.EntryGumpID; + public static readonly int BackGumpID = PropsConfig.BackGumpID; + public static readonly int SetGumpID = PropsConfig.SetGumpID; + + public static readonly int SetWidth = PropsConfig.SetWidth; + public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY; + public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; + public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; + + public static readonly int PrevWidth = PropsConfig.PrevWidth; + public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY; + public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; + public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; + + public static readonly int NextWidth = PropsConfig.NextWidth; + public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY; + public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; + public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; + + public static readonly int OffsetSize = PropsConfig.OffsetSize; + + public static readonly int EntryHeight = PropsConfig.EntryHeight; + public static readonly int BorderSize = PropsConfig.BorderSize; + + private static readonly int EntryWidth = 160; + + private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize; + private static readonly int TotalHeight = OffsetSize + 2 * (EntryHeight + OffsetSize); + + private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; + private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize; + + private readonly Mobile m_From; + + private readonly SkillsGumpGroup m_Selected; + private readonly Skill m_Skill; + private readonly Mobile m_Target; + + public EditSkillGump(Mobile from, Mobile target, Skill skill, SkillsGumpGroup selected) : base( + GumpOffsetX, + GumpOffsetY + ) + { + m_From = from; + m_Target = target; + m_Skill = skill; + m_Selected = selected; + + var initialText = m_Skill.Base.ToString("F1"); + + AddPage(0); + + AddBackground(0, 0, BackWidth, BackHeight, BackGumpID); + AddImageTiled( + BorderSize, + BorderSize, + TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), + TotalHeight, + OffsetGumpID + ); + + var x = BorderSize + OffsetSize; + var y = BorderSize + OffsetSize; + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, skill.Name); + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + + x = BorderSize + OffsetSize; + y += EntryHeight + OffsetSize; + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddTextEntry(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, 0, initialText); + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + + AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, 1); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 1) + try + { + if (m_From.AccessLevel >= AccessLevel.GameMaster) + { + var text = info.GetTextEntry(0); + + if (text != null) + { + m_Skill.Base = Convert.ToDouble(text.Text); + CommandLogging.LogChangeProperty(m_From, m_Target, $"{m_Skill}.Base", m_Skill.Base.ToString()); + } + } + else + { + m_From.SendMessage("You may not change that."); + } + + m_From.SendGump(new SkillsGump(m_From, m_Target, m_Selected)); + } + catch + { + m_From.SendMessage("Bad format. ###.# expected."); + m_From.SendGump(new EditSkillGump(m_From, m_Target, m_Skill, m_Selected)); + } + else + m_From.SendGump(new SkillsGump(m_From, m_Target, m_Selected)); + } + } + + public class SkillsGump : Gump + { + public static bool OldStyle = PropsConfig.OldStyle; + + public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; + public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; + + public static readonly int TextHue = PropsConfig.TextHue; + public static readonly int TextOffsetX = PropsConfig.TextOffsetX; + + public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; + public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; + public static readonly int EntryGumpID = PropsConfig.EntryGumpID; + public static readonly int BackGumpID = PropsConfig.BackGumpID; + public static readonly int SetGumpID = PropsConfig.SetGumpID; + + public static readonly int SetWidth = PropsConfig.SetWidth; + public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY; + public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; + public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; + + public static readonly int PrevWidth = PropsConfig.PrevWidth; + public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY; + public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; + public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; + + public static readonly int NextWidth = PropsConfig.NextWidth; + public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY; + public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; + public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; + + public static readonly int OffsetSize = PropsConfig.OffsetSize; + + public static readonly int EntryHeight = PropsConfig.EntryHeight; + public static readonly int BorderSize = PropsConfig.BorderSize; + + /* + private static bool PrevLabel = OldStyle, NextLabel = OldStyle; + + private static readonly int PrevLabelOffsetX = PrevWidth + 1; + + private static readonly int PrevLabelOffsetY = 0; + + private static readonly int NextLabelOffsetX = -29; + private static readonly int NextLabelOffsetY = 0; + * */ + + private static readonly int NameWidth = 107; + private static readonly int ValueWidth = 128; + + private static readonly int EntryCount = 15; + + private static readonly int TypeWidth = NameWidth + OffsetSize + ValueWidth; + + private static readonly int TotalWidth = + OffsetSize + NameWidth + OffsetSize + ValueWidth + OffsetSize + SetWidth + OffsetSize; + + private static readonly int TotalHeight = OffsetSize + (EntryHeight + OffsetSize) * (EntryCount + 1); + + private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; + private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize; + + private static readonly int IndentWidth = 12; + + private readonly Mobile m_From; + + private readonly SkillsGumpGroup[] m_Groups; + private readonly SkillsGumpGroup m_Selected; + private readonly Mobile m_Target; + + public SkillsGump(Mobile from, Mobile target, SkillsGumpGroup selected = null) : base(GumpOffsetX, GumpOffsetY) + { + m_From = from; + m_Target = target; + + m_Groups = SkillsGumpGroup.Groups; + m_Selected = selected; + + var count = m_Groups.Length; + + if (selected != null) + count += selected.Skills.Length; + + var totalHeight = OffsetSize + (EntryHeight + OffsetSize) * (count + 1); + + AddPage(0); + + AddBackground(0, 0, BackWidth, BorderSize + totalHeight + BorderSize, BackGumpID); + AddImageTiled( + BorderSize, + BorderSize, + TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), + totalHeight, + OffsetGumpID + ); + + var x = BorderSize + OffsetSize; + var y = BorderSize + OffsetSize; + + var emptyWidth = TotalWidth - PrevWidth - NextWidth - OffsetSize * 4 - (OldStyle ? SetWidth + OffsetSize : 0); + + if (OldStyle) + AddImageTiled(x, y, TotalWidth - OffsetSize * 3 - SetWidth, EntryHeight, HeaderGumpID); + else + AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); + + x += PrevWidth + OffsetSize; + + if (!OldStyle) + AddImageTiled( + x - (OldStyle ? OffsetSize : 0), + y, + emptyWidth + (OldStyle ? OffsetSize * 2 : 0), + EntryHeight, + HeaderGumpID + ); + + x += emptyWidth + OffsetSize; + + if (!OldStyle) + AddImageTiled(x, y, NextWidth, EntryHeight, HeaderGumpID); + + for (var i = 0; i < m_Groups.Length; ++i) + { + x = BorderSize + OffsetSize; + y += EntryHeight + OffsetSize; + + var group = m_Groups[i]; + + AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); + + if (group == selected) + AddButton(x + PrevOffsetX, y + PrevOffsetY, 0x15E2, 0x15E6, GetButtonID(0, i)); + else + AddButton(x + PrevOffsetX, y + PrevOffsetY, 0x15E1, 0x15E5, GetButtonID(0, i)); + + x += PrevWidth + OffsetSize; + + x -= OldStyle ? OffsetSize : 0; + + AddImageTiled(x, y, emptyWidth + (OldStyle ? OffsetSize * 2 : 0), EntryHeight, EntryGumpID); + AddLabel(x + TextOffsetX, y, TextHue, group?.Name ?? ""); + + x += emptyWidth + (OldStyle ? OffsetSize * 2 : 0); + x += OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + + if (group == selected) + { + var indentMaskX = BorderSize; + var indentMaskY = y + EntryHeight + OffsetSize; + + for (var j = 0; j < group.Skills.Length; ++j) + { + var sk = target.Skills[group.Skills[j]]; + + x = BorderSize + OffsetSize; + y += EntryHeight + OffsetSize; + + x += OffsetSize; + x += IndentWidth; + + AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); + + AddButton(x + PrevOffsetX, y + PrevOffsetY, 0x15E1, 0x15E5, GetButtonID(1, j)); + + x += PrevWidth + OffsetSize; + + x -= OldStyle ? OffsetSize : 0; + + AddImageTiled( + x, + y, + emptyWidth + (OldStyle ? OffsetSize * 2 : 0) - OffsetSize - IndentWidth, + EntryHeight, + EntryGumpID + ); + AddLabel(x + TextOffsetX, y, TextHue, sk == null ? "(null)" : sk.Name); + + x += emptyWidth + (OldStyle ? OffsetSize * 2 : 0) - OffsetSize - IndentWidth; + x += OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + + if (sk != null) + { + int buttonID1, buttonID2; + int xOffset, yOffset; + + switch (sk.Lock) + { + default: + buttonID1 = 0x983; + buttonID2 = 0x983; + xOffset = 6; + yOffset = 4; + break; + case SkillLock.Down: + buttonID1 = 0x985; + buttonID2 = 0x985; + xOffset = 6; + yOffset = 4; + break; + case SkillLock.Locked: + buttonID1 = 0x82C; + buttonID2 = 0x82C; + xOffset = 5; + yOffset = 2; + break; + } + + AddButton(x + xOffset, y + yOffset, buttonID1, buttonID2, GetButtonID(2, j)); + + y += 1; + x -= OffsetSize; + x -= 1; + x -= 50; + + AddImageTiled(x, y, 50, EntryHeight - 2, OffsetGumpID); + + x += 1; + y += 1; + + AddImageTiled(x, y, 48, EntryHeight - 4, EntryGumpID); + + AddLabelCropped( + x + TextOffsetX, + y - 1, + 48 - TextOffsetX, + EntryHeight - 3, + TextHue, + sk.Base.ToString("F1") + ); + + y -= 2; + } + } + + AddImageTiled( + indentMaskX, + indentMaskY, + IndentWidth + OffsetSize, + group.Skills.Length * (EntryHeight + OffsetSize) - (i < m_Groups.Length - 1 ? OffsetSize : 0), + BackGumpID + 4 + ); + } + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var buttonID = info.ButtonID - 1; + + var index = buttonID / 3; + var type = buttonID % 3; + + switch (type) + { + case 0: + { + if (index >= 0 && index < m_Groups.Length) + { + var newSelection = m_Groups[index]; + + if (m_Selected != newSelection) + m_From.SendGump(new SkillsGump(m_From, m_Target, newSelection)); + else + m_From.SendGump(new SkillsGump(m_From, m_Target)); + } + + break; + } + case 1: + { + if (m_Selected != null && index >= 0 && index < m_Selected.Skills.Length) + { + var sk = m_Target.Skills[m_Selected.Skills[index]]; + + if (sk != null) + { + if (m_From.AccessLevel >= AccessLevel.GameMaster) + { + m_From.SendGump(new EditSkillGump(m_From, m_Target, sk, m_Selected)); + } + else + { + m_From.SendMessage("You may not change that."); + m_From.SendGump(new SkillsGump(m_From, m_Target, m_Selected)); + } + } + else + { + m_From.SendGump(new SkillsGump(m_From, m_Target, m_Selected)); + } + } + + break; + } + case 2: + { + if (m_Selected != null && index >= 0 && index < m_Selected.Skills.Length) + { + var sk = m_Target.Skills[m_Selected.Skills[index]]; + + if (sk != null) + { + if (m_From.AccessLevel >= AccessLevel.GameMaster) + switch (sk.Lock) + { + case SkillLock.Up: + sk.SetLockNoRelay(SkillLock.Down); + sk.Update(); + break; + case SkillLock.Down: + sk.SetLockNoRelay(SkillLock.Locked); + sk.Update(); + break; + case SkillLock.Locked: + sk.SetLockNoRelay(SkillLock.Up); + sk.Update(); + break; + } + else + m_From.SendMessage("You may not change that."); + + m_From.SendGump(new SkillsGump(m_From, m_Target, m_Selected)); + } + } + + break; + } + } + } + + public int GetButtonID(int type, int index) => 1 + index * 3 + type; + } + + public class SkillsGumpGroup + { + public SkillsGumpGroup(string name, SkillName[] skills) + { + Name = name; + Skills = skills; + + Array.Sort(Skills, new SkillNameComparer()); + } + + public string Name { get; } + + public SkillName[] Skills { get; } + + public static SkillsGumpGroup[] Groups { get; } = + { + new SkillsGumpGroup( + "Crafting", + new[] + { + SkillName.Alchemy, + SkillName.Blacksmith, + SkillName.Cartography, + SkillName.Carpentry, + SkillName.Cooking, + SkillName.Fletching, + SkillName.Inscribe, + SkillName.Tailoring, + SkillName.Tinkering, + SkillName.Imbuing + } + ), + new SkillsGumpGroup( + "Bardic", + new[] + { + SkillName.Discordance, + SkillName.Musicianship, + SkillName.Peacemaking, + SkillName.Provocation + } + ), + new SkillsGumpGroup( + "Magical", + new[] + { + SkillName.Chivalry, + SkillName.EvalInt, + SkillName.Magery, + SkillName.MagicResist, + SkillName.Meditation, + SkillName.Necromancy, + SkillName.SpiritSpeak, + SkillName.Ninjitsu, + SkillName.Bushido, + SkillName.Spellweaving, + SkillName.Mysticism + } + ), + new SkillsGumpGroup( + "Miscellaneous", + new[] + { + SkillName.Camping, + SkillName.Fishing, + SkillName.Focus, + SkillName.Healing, + SkillName.Herding, + SkillName.Lockpicking, + SkillName.Lumberjacking, + SkillName.Mining, + SkillName.Snooping, + SkillName.Veterinary + } + ), + new SkillsGumpGroup( + "Combat Ratings", + new[] + { + SkillName.Archery, + SkillName.Fencing, + SkillName.Macing, + SkillName.Parry, + SkillName.Swords, + SkillName.Tactics, + SkillName.Wrestling, + SkillName.Throwing + } + ), + new SkillsGumpGroup( + "Actions", + new[] + { + SkillName.AnimalTaming, + SkillName.Begging, + SkillName.DetectHidden, + SkillName.Hiding, + SkillName.RemoveTrap, + SkillName.Poisoning, + SkillName.Stealing, + SkillName.Stealth, + SkillName.Tracking + } + ), + new SkillsGumpGroup( + "Lore & Knowledge", + new[] + { + SkillName.Anatomy, + SkillName.AnimalLore, + SkillName.ArmsLore, + SkillName.Forensics, + SkillName.ItemID, + SkillName.TasteID + } + ) + }; + + private class SkillNameComparer : IComparer + { + public int Compare(SkillName a, SkillName b) + { + var aName = SkillInfo.Table[(int)a].Name; + var bName = SkillInfo.Table[(int)b].Name; + + return aName.CompareTo(bName); + } + } + } +} diff --git a/Projects/UOContent/Gumps/TithingGump.cs b/Projects/UOContent/Gumps/TithingGump.cs index 678f4e317..449011fc1 100644 --- a/Projects/UOContent/Gumps/TithingGump.cs +++ b/Projects/UOContent/Gumps/TithingGump.cs @@ -1,117 +1,124 @@ -using System; -using Server.Items; -using Server.Network; - -namespace Server.Gumps -{ - public class TithingGump : Gump - { - private readonly Mobile m_From; - private int m_Offer; - - public TithingGump(Mobile from, int offer) : base(160, 40) - { - int totalGold = from.TotalGold; - - offer = Math.Clamp(offer, 0, totalGold); - - m_From = from; - m_Offer = offer; - - AddPage(0); - - AddImage(30, 30, 102); - - AddHtmlLocalized(95, 100, 120, 100, 1060198, 0); // May your wealth bring blessings to those in need, if tithed upon this most sacred site. - - AddLabel(57, 274, 0, "Gold:"); - AddLabel(87, 274, 53, (totalGold - offer).ToString()); - - AddLabel(137, 274, 0, "Tithe:"); - AddLabel(172, 274, 53, offer.ToString()); - - AddButton(105, 230, 5220, 5220, 2); - AddButton(113, 230, 5222, 5222, 2); - AddLabel(108, 228, 0, "<"); - AddLabel(112, 228, 0, "<"); - - AddButton(127, 230, 5223, 5223, 1); - AddLabel(131, 228, 0, "<"); - - AddButton(147, 230, 5224, 5224, 3); - AddLabel(153, 228, 0, ">"); - - AddButton(168, 230, 5220, 5220, 4); - AddButton(176, 230, 5222, 5222, 4); - AddLabel(172, 228, 0, ">"); - AddLabel(176, 228, 0, ">"); - - AddButton(217, 272, 4023, 4024, 5); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - switch (info.ButtonID) - { - case 0: - { - // You have decided to tithe no gold to the shrine. - m_From.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1060193); - break; - } - case 1: - case 2: - case 3: - case 4: - { - var offer = info.ButtonID switch - { - 1 => m_Offer - 100, - 2 => 0, - 3 => m_Offer + 100, - 4 => m_From.TotalGold, - _ => 0 - }; - - m_From.SendGump(new TithingGump(m_From, offer)); - break; - } - case 5: - { - int totalGold = m_From.TotalGold; - - m_Offer = Math.Clamp(m_Offer, 0, totalGold); - - if (m_From.TithingPoints + m_Offer > 100000) // TODO: What's the maximum? - m_Offer = 100000 - m_From.TithingPoints; - - if (m_Offer <= 0) - { - // You have decided to tithe no gold to the shrine. - m_From.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1060193); - break; - } - - Container pack = m_From.Backpack; - - if (pack?.ConsumeTotal(typeof(Gold), m_Offer) == true) - { - // You tithe gold to the shrine as a sign of devotion. - m_From.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1060195); - m_From.TithingPoints += m_Offer; - - m_From.PlaySound(0x243); - m_From.PlaySound(0x2E6); - } - else - { - // You do not have enough gold to tithe that amount! - m_From.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1060194); - } - - break; - } - } - } - } -} +using System; +using Server.Items; +using Server.Network; + +namespace Server.Gumps +{ + public class TithingGump : Gump + { + private readonly Mobile m_From; + private int m_Offer; + + public TithingGump(Mobile from, int offer) : base(160, 40) + { + var totalGold = from.TotalGold; + + offer = Math.Clamp(offer, 0, totalGold); + + m_From = from; + m_Offer = offer; + + AddPage(0); + + AddImage(30, 30, 102); + + AddHtmlLocalized( + 95, + 100, + 120, + 100, + 1060198, + 0 + ); // May your wealth bring blessings to those in need, if tithed upon this most sacred site. + + AddLabel(57, 274, 0, "Gold:"); + AddLabel(87, 274, 53, (totalGold - offer).ToString()); + + AddLabel(137, 274, 0, "Tithe:"); + AddLabel(172, 274, 53, offer.ToString()); + + AddButton(105, 230, 5220, 5220, 2); + AddButton(113, 230, 5222, 5222, 2); + AddLabel(108, 228, 0, "<"); + AddLabel(112, 228, 0, "<"); + + AddButton(127, 230, 5223, 5223, 1); + AddLabel(131, 228, 0, "<"); + + AddButton(147, 230, 5224, 5224, 3); + AddLabel(153, 228, 0, ">"); + + AddButton(168, 230, 5220, 5220, 4); + AddButton(176, 230, 5222, 5222, 4); + AddLabel(172, 228, 0, ">"); + AddLabel(176, 228, 0, ">"); + + AddButton(217, 272, 4023, 4024, 5); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + switch (info.ButtonID) + { + case 0: + { + // You have decided to tithe no gold to the shrine. + m_From.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1060193); + break; + } + case 1: + case 2: + case 3: + case 4: + { + var offer = info.ButtonID switch + { + 1 => m_Offer - 100, + 2 => 0, + 3 => m_Offer + 100, + 4 => m_From.TotalGold, + _ => 0 + }; + + m_From.SendGump(new TithingGump(m_From, offer)); + break; + } + case 5: + { + var totalGold = m_From.TotalGold; + + m_Offer = Math.Clamp(m_Offer, 0, totalGold); + + if (m_From.TithingPoints + m_Offer > 100000) // TODO: What's the maximum? + m_Offer = 100000 - m_From.TithingPoints; + + if (m_Offer <= 0) + { + // You have decided to tithe no gold to the shrine. + m_From.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1060193); + break; + } + + var pack = m_From.Backpack; + + if (pack?.ConsumeTotal(typeof(Gold), m_Offer) == true) + { + // You tithe gold to the shrine as a sign of devotion. + m_From.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1060195); + m_From.TithingPoints += m_Offer; + + m_From.PlaySound(0x243); + m_From.PlaySound(0x2E6); + } + else + { + // You do not have enough gold to tithe that amount! + m_From.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1060194); + } + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Gumps/ToTAdminGump.cs b/Projects/UOContent/Gumps/ToTAdminGump.cs index 8a740186e..021dd3b8d 100644 --- a/Projects/UOContent/Gumps/ToTAdminGump.cs +++ b/Projects/UOContent/Gumps/ToTAdminGump.cs @@ -1,134 +1,134 @@ -using System; -using Server.Misc; -using Server.Network; - -namespace Server.Gumps -{ - public class ToTAdminGump : Gump - { - private static readonly string[] m_ToTInfo = - { - // Opening Message - "
Treasures of Tokuno Admin

" + - "-Use the gems to switch eras
" + - "-Drop era and Reward era can be changed seperately
" + - "-Drop era can be deactivated, Reward era is always activated", - // Treasures of Tokuno 1 message - "
Treasures of Tokuno 1

" + - "-10 charge Bleach Pigment can drop as a Lesser Artifact
" + - "-50 charge Neon Pigments available as a reward
", - // Treasures of Tokuno 2 message - "
Treasures of Tokuno 2

" + - "-30 types of 1 charge Metallic Pigments drop as Lesser Artifacts
" + - "-1 charge Bleach Pigment can drop as a Lesser Artifact
" + - "-10 charge Greater Metallic Pigments available as a reward", - // Treasures of Tokuno 3 message - "
Treasures of Tokuno 3

" + - "-10 types of 1 charge Fresh Pigments drop as Lesser Artifacts
" + - "-1 charge Bleach Pigment can drop as a Lesser Artifact
" + - "-Leurocian's Mempo Of Fortune can drop as a Lesser Artifact" - }; - - private readonly int m_ToTEras; - - public ToTAdminGump() : base(30, 50) - { - Closable = true; - Disposable = true; - Draggable = true; - Resizable = false; - - m_ToTEras = Enum.GetValues(typeof(TreasuresOfTokunoEra)).Length - 1; - - AddPage(0); - AddBackground(0, 0, 320, 75 + m_ToTEras * 25, 9200); - AddImageTiled(25, 18, 270, 10, 9267); - AddLabel(75, 5, 54, "Treasures of Tokuno Admin"); - AddLabel(10, 25, 54, "ToT Era"); - AddLabel(90, 25, 54, "Drop Era"); - AddLabel(195, 25, 54, "Reward Era"); - AddLabel(287, 25, 54, "Info"); - - AddBackground(320, 0, 200, 150, 9200); - AddImageTiled(325, 5, 190, 140, 2624); - AddAlphaRegion(325, 5, 190, 140); - - SetupToTEras(); - } - - public void SetupToTEras() - { - bool isActivated = TreasuresOfTokuno.DropEra != TreasuresOfTokunoEra.None; - AddButton(75, 50, isActivated ? 2361 : 2360, isActivated ? 2361 : 2360, 1); - AddLabel(90, 45, isActivated ? 167 : 137, isActivated ? "Activated" : "Deactivated"); - - for (int i = 0; i < m_ToTEras; i++) - { - int yoffset = i * 25; - - bool isThisDropEra = (int)TreasuresOfTokuno.DropEra - 1 == i; - bool isThisRewardEra = (int)TreasuresOfTokuno.RewardEra - 1 == i; - int dropButtonID = isThisDropEra ? 2361 : 2360; - int rewardButtonID = isThisRewardEra ? 2361 : 2360; - - AddLabel(10, 70 + yoffset, 2100, $"ToT {i + 1}"); - AddButton(75, 75 + yoffset, dropButtonID, dropButtonID, 2 + i * 2); - AddLabel(90, 70 + yoffset, isThisDropEra ? 167 : 137, isThisDropEra ? "Active" : "Inactive"); - AddButton(180, 75 + yoffset, rewardButtonID, rewardButtonID, 2 + i * 2 + 1); - AddLabel(195, 70 + yoffset, isThisRewardEra ? 167 : 137, isThisRewardEra ? "Active" : "Inactive"); - - AddButton(285, 70 + yoffset, 4005, 4006, i, GumpButtonType.Page, 2 + i); - } - - for (int i = 0; i < m_ToTInfo.Length; i++) - { - AddPage(1 + i); - AddHtml(330, 10, 180, 130, m_ToTInfo[i], false, true); - } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - int button = info.ButtonID; - Mobile from = sender.Mobile; - - if (button == 1) - { - TreasuresOfTokuno.DropEra = TreasuresOfTokunoEra.None; - from.SendMessage("Treasures of Tokuno Drops have been deactivated"); - } - else if (button >= 2) - { - int selectedToT; - if (button % 2 == 0) - { - selectedToT = button / 2; - TreasuresOfTokuno.DropEra = (TreasuresOfTokunoEra)selectedToT; - from.SendMessage($"Treasures of Tokuno {selectedToT} Drops have been enabled"); - } - else - { - selectedToT = (button - 1) / 2; - TreasuresOfTokuno.RewardEra = (TreasuresOfTokunoEra)selectedToT; - from.SendMessage($"Treasures of Tokuno {selectedToT} Rewards have been enabled"); - } - } - } - - public static void Initialize() - { - CommandSystem.Register("ToTAdmin", AccessLevel.Administrator, ToTAdmin_OnCommand); - } - - [Usage("ToTAdmin")] - [Description("Displays a menu to configure Treasures of Tokuno.")] - public static void ToTAdmin_OnCommand(CommandEventArgs e) - { - ToTAdminGump tg; - - tg = new ToTAdminGump(); - e.Mobile.CloseGump(); - e.Mobile.SendGump(tg); - } - } -} +using System; +using Server.Misc; +using Server.Network; + +namespace Server.Gumps +{ + public class ToTAdminGump : Gump + { + private static readonly string[] m_ToTInfo = + { + // Opening Message + "
Treasures of Tokuno Admin

" + + "-Use the gems to switch eras
" + + "-Drop era and Reward era can be changed seperately
" + + "-Drop era can be deactivated, Reward era is always activated", + // Treasures of Tokuno 1 message + "
Treasures of Tokuno 1

" + + "-10 charge Bleach Pigment can drop as a Lesser Artifact
" + + "-50 charge Neon Pigments available as a reward
", + // Treasures of Tokuno 2 message + "
Treasures of Tokuno 2

" + + "-30 types of 1 charge Metallic Pigments drop as Lesser Artifacts
" + + "-1 charge Bleach Pigment can drop as a Lesser Artifact
" + + "-10 charge Greater Metallic Pigments available as a reward", + // Treasures of Tokuno 3 message + "
Treasures of Tokuno 3

" + + "-10 types of 1 charge Fresh Pigments drop as Lesser Artifacts
" + + "-1 charge Bleach Pigment can drop as a Lesser Artifact
" + + "-Leurocian's Mempo Of Fortune can drop as a Lesser Artifact" + }; + + private readonly int m_ToTEras; + + public ToTAdminGump() : base(30, 50) + { + Closable = true; + Disposable = true; + Draggable = true; + Resizable = false; + + m_ToTEras = Enum.GetValues(typeof(TreasuresOfTokunoEra)).Length - 1; + + AddPage(0); + AddBackground(0, 0, 320, 75 + m_ToTEras * 25, 9200); + AddImageTiled(25, 18, 270, 10, 9267); + AddLabel(75, 5, 54, "Treasures of Tokuno Admin"); + AddLabel(10, 25, 54, "ToT Era"); + AddLabel(90, 25, 54, "Drop Era"); + AddLabel(195, 25, 54, "Reward Era"); + AddLabel(287, 25, 54, "Info"); + + AddBackground(320, 0, 200, 150, 9200); + AddImageTiled(325, 5, 190, 140, 2624); + AddAlphaRegion(325, 5, 190, 140); + + SetupToTEras(); + } + + public void SetupToTEras() + { + var isActivated = TreasuresOfTokuno.DropEra != TreasuresOfTokunoEra.None; + AddButton(75, 50, isActivated ? 2361 : 2360, isActivated ? 2361 : 2360, 1); + AddLabel(90, 45, isActivated ? 167 : 137, isActivated ? "Activated" : "Deactivated"); + + for (var i = 0; i < m_ToTEras; i++) + { + var yoffset = i * 25; + + var isThisDropEra = (int)TreasuresOfTokuno.DropEra - 1 == i; + var isThisRewardEra = (int)TreasuresOfTokuno.RewardEra - 1 == i; + var dropButtonID = isThisDropEra ? 2361 : 2360; + var rewardButtonID = isThisRewardEra ? 2361 : 2360; + + AddLabel(10, 70 + yoffset, 2100, $"ToT {i + 1}"); + AddButton(75, 75 + yoffset, dropButtonID, dropButtonID, 2 + i * 2); + AddLabel(90, 70 + yoffset, isThisDropEra ? 167 : 137, isThisDropEra ? "Active" : "Inactive"); + AddButton(180, 75 + yoffset, rewardButtonID, rewardButtonID, 2 + i * 2 + 1); + AddLabel(195, 70 + yoffset, isThisRewardEra ? 167 : 137, isThisRewardEra ? "Active" : "Inactive"); + + AddButton(285, 70 + yoffset, 4005, 4006, i, GumpButtonType.Page, 2 + i); + } + + for (var i = 0; i < m_ToTInfo.Length; i++) + { + AddPage(1 + i); + AddHtml(330, 10, 180, 130, m_ToTInfo[i], false, true); + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var button = info.ButtonID; + var from = sender.Mobile; + + if (button == 1) + { + TreasuresOfTokuno.DropEra = TreasuresOfTokunoEra.None; + from.SendMessage("Treasures of Tokuno Drops have been deactivated"); + } + else if (button >= 2) + { + int selectedToT; + if (button % 2 == 0) + { + selectedToT = button / 2; + TreasuresOfTokuno.DropEra = (TreasuresOfTokunoEra)selectedToT; + from.SendMessage($"Treasures of Tokuno {selectedToT} Drops have been enabled"); + } + else + { + selectedToT = (button - 1) / 2; + TreasuresOfTokuno.RewardEra = (TreasuresOfTokunoEra)selectedToT; + from.SendMessage($"Treasures of Tokuno {selectedToT} Rewards have been enabled"); + } + } + } + + public static void Initialize() + { + CommandSystem.Register("ToTAdmin", AccessLevel.Administrator, ToTAdmin_OnCommand); + } + + [Usage("ToTAdmin")] + [Description("Displays a menu to configure Treasures of Tokuno.")] + public static void ToTAdmin_OnCommand(CommandEventArgs e) + { + ToTAdminGump tg; + + tg = new ToTAdminGump(); + e.Mobile.CloseGump(); + e.Mobile.SendGump(tg); + } + } +} diff --git a/Projects/UOContent/Gumps/VendorInventoryGump.cs b/Projects/UOContent/Gumps/VendorInventoryGump.cs index 0d4fe4efd..ff838174c 100644 --- a/Projects/UOContent/Gumps/VendorInventoryGump.cs +++ b/Projects/UOContent/Gumps/VendorInventoryGump.cs @@ -1,123 +1,130 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Server.Mobiles; -using Server.Multis; -using Server.Network; - -namespace Server.Gumps -{ - public class VendorInventoryGump : Gump - { - private readonly BaseHouse m_House; - private readonly List m_Inventories; - - public VendorInventoryGump(BaseHouse house, Mobile from) : base(50, 50) - { - m_House = house; - m_Inventories = house.VendorInventories.ToList(); - - AddBackground(0, 0, 420, 50 + 20 * m_Inventories.Count, 0x13BE); - - AddImageTiled(10, 10, 400, 20, 0xA40); - AddHtmlLocalized(15, 10, 200, 20, 1062435, 0x7FFF); // Reclaim Vendor Inventory - AddHtmlLocalized(330, 10, 50, 20, 1062465, 0x7FFF); // Expires - - AddImageTiled(10, 40, 400, 20 * m_Inventories.Count, 0xA40); - - for (int i = 0; i < m_Inventories.Count; i++) - { - VendorInventory inventory = m_Inventories[i]; - - int y = 40 + 20 * i; - - if (inventory.Owner == from) - AddButton(10, y, 0xFA5, 0xFA7, i + 1); - - AddLabel(45, y, 0x481, $"{inventory.ShopName} ({inventory.VendorName})"); - - TimeSpan expire = inventory.ExpireTime - DateTime.UtcNow; - int hours = (int)expire.TotalHours; - - AddLabel(320, y, 0x481, hours.ToString()); - AddHtmlLocalized(350, y, 50, 20, 1062466, 0x7FFF); // hour(s) - } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 0) - return; - - Mobile from = sender.Mobile; - HouseSign sign = m_House.Sign; - - if (m_House.Deleted || sign?.Deleted != false || !from.CheckAlive()) - return; - - if (from.Map != sign.Map || !from.InRange(sign, 5)) - { - from.SendLocalizedMessage(1062429); // You must be within five paces of the house sign to use this option. - return; - } - - int index = info.ButtonID - 1; - if (index < 0 || index >= m_Inventories.Count) - return; - - VendorInventory inventory = m_Inventories[index]; - - if (inventory.Owner != from || !m_House.VendorInventories.Contains(inventory)) - return; - - int totalItems = 0; - int givenToBackpack = 0; - int givenToBankBox = 0; - for (int i = inventory.Items.Count - 1; i >= 0; i--) - { - Item item = inventory.Items[i]; - - if (item.Deleted) - { - inventory.Items.RemoveAt(i); - continue; - } - - totalItems += 1 + item.TotalItems; - - if (from.PlaceInBackpack(item)) - { - inventory.Items.RemoveAt(i); - givenToBackpack += 1 + item.TotalItems; - } - else if (from.BankBox.TryDropItem(from, item, false)) - { - inventory.Items.RemoveAt(i); - givenToBankBox += 1 + item.TotalItems; - } - } - - from.SendLocalizedMessage(1062436, - $"{totalItems}\t{inventory.Gold}"); // The vendor you selected had ~1_COUNT~ items in its inventory, and ~2_AMOUNT~ gold in its account. - - int givenGold = Banker.DepositUpTo(from, inventory.Gold); - inventory.Gold -= givenGold; - - from.SendLocalizedMessage(1060397, - givenGold.ToString()); // ~1_AMOUNT~ gold has been deposited into your bank box. - from.SendLocalizedMessage(1062437, - $"{givenToBackpack}\t{givenToBankBox}"); // ~1_COUNT~ items have been removed from the shop inventory and placed in your backpack. ~2_BANKCOUNT~ items were removed from the shop inventory and placed in your bank box. - - if (inventory.Gold > 0 || inventory.Items.Count > 0) - { - from.SendLocalizedMessage( - 1062440); // Some of the shop inventory would not fit in your backpack or bank box. Please free up some room and try again. - } - else - { - inventory.Delete(); - from.SendLocalizedMessage(1062438); // The shop is now empty of inventory and funds, so it has been deleted. - } - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using Server.Mobiles; +using Server.Multis; +using Server.Network; + +namespace Server.Gumps +{ + public class VendorInventoryGump : Gump + { + private readonly BaseHouse m_House; + private readonly List m_Inventories; + + public VendorInventoryGump(BaseHouse house, Mobile from) : base(50, 50) + { + m_House = house; + m_Inventories = house.VendorInventories.ToList(); + + AddBackground(0, 0, 420, 50 + 20 * m_Inventories.Count, 0x13BE); + + AddImageTiled(10, 10, 400, 20, 0xA40); + AddHtmlLocalized(15, 10, 200, 20, 1062435, 0x7FFF); // Reclaim Vendor Inventory + AddHtmlLocalized(330, 10, 50, 20, 1062465, 0x7FFF); // Expires + + AddImageTiled(10, 40, 400, 20 * m_Inventories.Count, 0xA40); + + for (var i = 0; i < m_Inventories.Count; i++) + { + var inventory = m_Inventories[i]; + + var y = 40 + 20 * i; + + if (inventory.Owner == from) + AddButton(10, y, 0xFA5, 0xFA7, i + 1); + + AddLabel(45, y, 0x481, $"{inventory.ShopName} ({inventory.VendorName})"); + + var expire = inventory.ExpireTime - DateTime.UtcNow; + var hours = (int)expire.TotalHours; + + AddLabel(320, y, 0x481, hours.ToString()); + AddHtmlLocalized(350, y, 50, 20, 1062466, 0x7FFF); // hour(s) + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 0) + return; + + var from = sender.Mobile; + var sign = m_House.Sign; + + if (m_House.Deleted || sign?.Deleted != false || !from.CheckAlive()) + return; + + if (from.Map != sign.Map || !from.InRange(sign, 5)) + { + from.SendLocalizedMessage(1062429); // You must be within five paces of the house sign to use this option. + return; + } + + var index = info.ButtonID - 1; + if (index < 0 || index >= m_Inventories.Count) + return; + + var inventory = m_Inventories[index]; + + if (inventory.Owner != from || !m_House.VendorInventories.Contains(inventory)) + return; + + var totalItems = 0; + var givenToBackpack = 0; + var givenToBankBox = 0; + for (var i = inventory.Items.Count - 1; i >= 0; i--) + { + var item = inventory.Items[i]; + + if (item.Deleted) + { + inventory.Items.RemoveAt(i); + continue; + } + + totalItems += 1 + item.TotalItems; + + if (from.PlaceInBackpack(item)) + { + inventory.Items.RemoveAt(i); + givenToBackpack += 1 + item.TotalItems; + } + else if (from.BankBox.TryDropItem(from, item, false)) + { + inventory.Items.RemoveAt(i); + givenToBankBox += 1 + item.TotalItems; + } + } + + from.SendLocalizedMessage( + 1062436, + $"{totalItems}\t{inventory.Gold}" + ); // The vendor you selected had ~1_COUNT~ items in its inventory, and ~2_AMOUNT~ gold in its account. + + var givenGold = Banker.DepositUpTo(from, inventory.Gold); + inventory.Gold -= givenGold; + + from.SendLocalizedMessage( + 1060397, + givenGold.ToString() + ); // ~1_AMOUNT~ gold has been deposited into your bank box. + from.SendLocalizedMessage( + 1062437, + $"{givenToBackpack}\t{givenToBankBox}" + ); // ~1_COUNT~ items have been removed from the shop inventory and placed in your backpack. ~2_BANKCOUNT~ items were removed from the shop inventory and placed in your bank box. + + if (inventory.Gold > 0 || inventory.Items.Count > 0) + { + from.SendLocalizedMessage( + 1062440 + ); // Some of the shop inventory would not fit in your backpack or bank box. Please free up some room and try again. + } + else + { + inventory.Delete(); + from.SendLocalizedMessage(1062438); // The shop is now empty of inventory and funds, so it has been deleted. + } + } + } +} diff --git a/Projects/UOContent/Gumps/VendorRentalGumps.cs b/Projects/UOContent/Gumps/VendorRentalGumps.cs index 2e68a811e..3538c901c 100644 --- a/Projects/UOContent/Gumps/VendorRentalGumps.cs +++ b/Projects/UOContent/Gumps/VendorRentalGumps.cs @@ -1,576 +1,646 @@ -using Server.Items; -using Server.Network; -using Server.Prompts; -using Server.Mobiles; -using Server.Targeting; -using Server.Multis; - -namespace Server.Gumps -{ - public abstract class BaseVendorRentalGump : Gump - { - protected enum GumpType - { - UnlockedContract, - LockedContract, - Offer, - VendorLandlord, - VendorRenter - } - - protected BaseVendorRentalGump(GumpType type, VendorRentalDuration duration, int price, int renewalPrice, - Mobile landlord, Mobile renter, bool landlordRenew, bool renterRenew, bool renew) : base(100, 100) - { - if (type == GumpType.Offer) - Closable = false; - - AddPage(0); - - AddImage(0, 0, 0x1F40); - AddImageTiled(20, 37, 300, 308, 0x1F42); - AddImage(20, 325, 0x1F43); - - AddImage(35, 8, 0x39); - AddImageTiled(65, 8, 257, 10, 0x3A); - AddImage(290, 8, 0x3B); - - AddImageTiled(70, 55, 230, 2, 0x23C5); - - AddImage(32, 33, 0x2635); - AddHtmlLocalized(70, 35, 270, 20, 1062353, 0x1); // Vendor Rental Contract - - AddPage(1); - - if (type != GumpType.UnlockedContract) - { - AddImage(65, 60, 0x827); - AddHtmlLocalized(79, 58, 270, 20, 1062370, 0x1); // Landlord: - AddLabel(150, 58, 0x64, landlord != null ? landlord.Name : ""); - - AddImageTiled(70, 80, 230, 2, 0x23C5); - } - - if (type == GumpType.UnlockedContract || type == GumpType.LockedContract) - AddButton(30, 96, 0x15E1, 0x15E5, 0, GumpButtonType.Page, 2); - AddHtmlLocalized(50, 95, 150, 20, 1062354, 0x1); // Contract Length - AddHtmlLocalized(230, 95, 270, 20, duration.Name, 0x1); - - if (type == GumpType.UnlockedContract || type == GumpType.LockedContract) - AddButton(30, 116, 0x15E1, 0x15E5, 1); - AddHtmlLocalized(50, 115, 150, 20, 1062356, 0x1); // Price Per Rental - AddLabel(230, 115, 0x64, price > 0 ? price.ToString() : "FREE"); - - AddImageTiled(50, 160, 250, 2, 0x23BF); - - if (type == GumpType.Offer) - { - AddButton(67, 180, 0x482, 0x483, 2); - AddHtmlLocalized(100, 180, 270, 20, 1049011, 0x28); // I accept! - - AddButton(67, 210, 0x47F, 0x480, 0); - AddHtmlLocalized(100, 210, 270, 20, 1049012, 0x28); // No thanks, I decline. - } - else - { - AddImage(49, 170, 0x61); - AddHtmlLocalized(60, 170, 250, 20, 1062355, 0x1); // Renew On Expiration? - - if (type == GumpType.LockedContract || type == GumpType.UnlockedContract || type == GumpType.VendorLandlord) - AddButton(30, 192, 0x15E1, 0x15E5, 3); - AddHtmlLocalized(85, 190, 250, 20, 1062359, 0x1); // Landlord: - AddHtmlLocalized(230, 190, 270, 20, landlordRenew ? 1049717 : 1049718, 0x1); // YES / NO - - if (type == GumpType.VendorRenter) - AddButton(30, 212, 0x15E1, 0x15E5, 4); - AddHtmlLocalized(85, 210, 250, 20, 1062360, 0x1); // Renter: - AddHtmlLocalized(230, 210, 270, 20, renterRenew ? 1049717 : 1049718, 0x1); // YES / NO - - if (renew) - { - AddImage(49, 233, 0x939); - AddHtmlLocalized(70, 230, 250, 20, 1062482, 0x1); // Contract WILL renew - } - else - { - AddImage(49, 233, 0x938); - AddHtmlLocalized(70, 230, 250, 20, 1062483, 0x1); // Contract WILL NOT renew - } - } - - AddImageTiled(30, 283, 257, 30, 0x5D); - AddImage(285, 283, 0x5E); - AddImage(20, 288, 0x232C); - - if (type == GumpType.LockedContract) - { - AddButton(67, 295, 0x15E1, 0x15E5, 5); - AddHtmlLocalized(85, 294, 270, 20, 1062358, 0x28); // Offer Contract To Someone - } - else if (type == GumpType.VendorLandlord || type == GumpType.VendorRenter) - { - if (type == GumpType.VendorLandlord) - AddButton(30, 250, 0x15E1, 0x15E1, 6); - AddHtmlLocalized(85, 250, 250, 20, 1062499, 0x1); // Renewal Price - AddLabel(230, 250, 0x64, renewalPrice.ToString()); - - AddHtmlLocalized(60, 294, 270, 20, 1062369, 0x1); // Renter: - AddLabel(120, 293, 0x64, renter != null ? renter.Name : ""); - } - - if (type == GumpType.UnlockedContract || type == GumpType.LockedContract) - { - AddPage(2); - - for (int i = 0; i < VendorRentalDuration.Instances.Length; i++) - { - VendorRentalDuration durationItem = VendorRentalDuration.Instances[i]; - - AddButton(30, 76 + i * 20, 0x15E1, 0x15E5, 0x10 | i, GumpButtonType.Reply, 1); - AddHtmlLocalized(50, 75 + i * 20, 150, 20, durationItem.Name, 0x1); - } - } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - Mobile from = sender.Mobile; - - if (!IsValidResponse(from)) - return; - - if ((info.ButtonID & 0x10) != 0) // Contract duration - { - int index = info.ButtonID & 0xF; - - if (index < VendorRentalDuration.Instances.Length) SetContractDuration(from, VendorRentalDuration.Instances[index]); - } - else - { - switch (info.ButtonID) - { - case 1: // Price Per Rental - SetPricePerRental(from); - break; - - case 2: // Accept offer - AcceptOffer(from); - break; - - case 3: // Renew on expiration - landlord - LandlordRenewOnExpiration(from); - break; - - case 4: // Renew on expiration - renter - RenterRenewOnExpiration(from); - break; - - case 5: // Offer Contract To Someone - OfferContract(from); - break; - - case 6: // Renewal price - SetRenewalPrice(from); - break; - - default: - Cancel(from); - break; - } - } - } - - protected abstract bool IsValidResponse(Mobile from); - - protected virtual void SetContractDuration(Mobile from, VendorRentalDuration duration) - { - } - - protected virtual void SetPricePerRental(Mobile from) - { - } - - protected virtual void AcceptOffer(Mobile from) - { - } - - protected virtual void LandlordRenewOnExpiration(Mobile from) - { - } - - protected virtual void RenterRenewOnExpiration(Mobile from) - { - } - - protected virtual void OfferContract(Mobile from) - { - } - - protected virtual void SetRenewalPrice(Mobile from) - { - } - - protected virtual void Cancel(Mobile from) - { - } - } - - public class VendorRentalContractGump : BaseVendorRentalGump - { - private readonly VendorRentalContract m_Contract; - - public VendorRentalContractGump(VendorRentalContract contract, Mobile from) : base( - contract.IsLockedDown ? GumpType.LockedContract : GumpType.UnlockedContract, contract.Duration, - contract.Price, contract.Price, from, null, contract.LandlordRenew, false, false) => - m_Contract = contract; - - protected override bool IsValidResponse(Mobile from) => m_Contract.IsUsableBy(from, true, true, true, true); - - protected override void SetContractDuration(Mobile from, VendorRentalDuration duration) - { - m_Contract.Duration = duration; - - from.SendGump(new VendorRentalContractGump(m_Contract, from)); - } - - protected override void SetPricePerRental(Mobile from) - { - from.SendLocalizedMessage(1062365); // Please enter the amount of gold that should be charged for this contract (ESC to cancel): - from.Prompt = new PricePerRentalPrompt(m_Contract); - } - - protected override void LandlordRenewOnExpiration(Mobile from) - { - m_Contract.LandlordRenew = !m_Contract.LandlordRenew; - - from.SendGump(new VendorRentalContractGump(m_Contract, from)); - } - - protected override void OfferContract(Mobile from) - { - if (m_Contract.IsLandlord(from)) - { - from.SendLocalizedMessage(1062371); // Please target the person you wish to offer this contract to. - from.Target = new OfferContractTarget(m_Contract); - } - } - - private class PricePerRentalPrompt : Prompt - { - private readonly VendorRentalContract m_Contract; - - public PricePerRentalPrompt(VendorRentalContract contract) => m_Contract = contract; - - public override void OnResponse(Mobile from, string text) - { - if (!m_Contract.IsUsableBy(from, true, true, true, true)) - return; - - text = text.Trim(); - - if (!int.TryParse(text, out int price)) - price = -1; - - if (price < 0) - { - from.SendLocalizedMessage(1062485); // Invalid entry. Rental fee set to 0. - m_Contract.Price = 0; - } - else if (price > 5000000) - { - m_Contract.Price = 5000000; - } - else - { - m_Contract.Price = price; - } - - from.SendGump(new VendorRentalContractGump(m_Contract, from)); - } - - public override void OnCancel(Mobile from) - { - if (m_Contract.IsUsableBy(from, true, true, true, true)) - from.SendGump(new VendorRentalContractGump(m_Contract, from)); - } - } - - private class OfferContractTarget : Target - { - private readonly VendorRentalContract m_Contract; - - public OfferContractTarget(VendorRentalContract contract) : base(-1, false, TargetFlags.None) => m_Contract = contract; - - protected override void OnTarget(Mobile from, object targeted) - { - if (!m_Contract.IsUsableBy(from, true, false, true, true)) - return; - - if (!(targeted is Mobile mob) || !mob.Player || !mob.Alive || mob == from) - { - from.SendLocalizedMessage(1071984); // That is not a valid target for a rental contract! - } - else if (!mob.InRange(m_Contract, 5)) - { - from.SendLocalizedMessage(501853); // Target is too far away. - } - else - { - from.SendLocalizedMessage(1062372); // Please wait while that person considers your offer. - - mob.SendLocalizedMessage(1062373, from.Name); // ~1_NAME~ is offering you a vendor rental. If you choose to accept this offer, you have 30 seconds to do so. - mob.SendGump(new VendorRentalOfferGump(m_Contract, from)); - - m_Contract.Offeree = mob; - } - } - - protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType) - { - from.SendLocalizedMessage(1062380); // You decide against offering the contract to anyone. - } - } - } - - public class VendorRentalOfferGump : BaseVendorRentalGump - { - private readonly VendorRentalContract m_Contract; - private readonly Mobile m_Landlord; - - public VendorRentalOfferGump(VendorRentalContract contract, Mobile landlord) : base( - GumpType.Offer, contract.Duration, contract.Price, contract.Price, - landlord, null, contract.LandlordRenew, false, false) - { - m_Contract = contract; - m_Landlord = landlord; - } - - protected override bool IsValidResponse(Mobile from) => m_Contract.IsUsableBy(m_Landlord, true, false, false, false) && from.CheckAlive() && m_Contract.Offeree == from; - - protected override void AcceptOffer(Mobile from) - { - m_Contract.Offeree = null; - - if (!m_Contract.Map.CanFit(m_Contract.Location, 16, false, false)) - { - m_Landlord.SendLocalizedMessage(1062486); // A vendor cannot exist at that location. Please try again. - return; - } - - BaseHouse house = BaseHouse.FindHouseAt(m_Contract); - if (house == null) - return; - - int price = m_Contract.Price; - int goldToGive; - - if (price > 0) - { - if (Banker.Withdraw(from, price)) - { - from.SendLocalizedMessage(1060398, price.ToString()); // ~1_AMOUNT~ gold has been withdrawn from your bank box. - - int depositedGold = Banker.DepositUpTo(m_Landlord, price); - goldToGive = price - depositedGold; - - if (depositedGold > 0) - m_Landlord.SendLocalizedMessage(1060397, price.ToString()); // ~1_AMOUNT~ gold has been deposited into your bank box. - - if (goldToGive > 0) - m_Landlord.SendLocalizedMessage(500390); // Your bank box is full. - } - else - { - from.SendLocalizedMessage(1062378); // You do not have enough gold in your bank account to cover the cost of the contract. - m_Landlord.SendLocalizedMessage(1062374, from.Name); // ~1_NAME~ has declined your vendor rental offer. - - return; - } - } - else - { - goldToGive = 0; - } - - PlayerVendor vendor = new RentedVendor(from, house, m_Contract.Duration, price, m_Contract.LandlordRenew, goldToGive); - vendor.MoveToWorld(m_Contract.Location, m_Contract.Map); - - m_Contract.Delete(); - - from.SendLocalizedMessage(1062377); // You have accepted the offer and now own a vendor in this house. Rental contract options and details may be viewed on this vendor via the 'Contract Options' context menu. - m_Landlord.SendLocalizedMessage(1062376, from.Name); // ~1_NAME~ has accepted your vendor rental offer. Rental contract details and options may be viewed on this vendor via the 'Contract Options' context menu. - } - - protected override void Cancel(Mobile from) - { - m_Contract.Offeree = null; - - from.SendLocalizedMessage(1062375); // You decline the offer for a vendor space rental. - m_Landlord.SendLocalizedMessage(1062374, from.Name); // ~1_NAME~ has declined your vendor rental offer. - } - } - - public class RenterVendorRentalGump : BaseVendorRentalGump - { - private readonly RentedVendor m_Vendor; - - public RenterVendorRentalGump(RentedVendor vendor) : base( - GumpType.VendorRenter, vendor.RentalDuration, vendor.RentalPrice, vendor.RenewalPrice, - vendor.Landlord, vendor.Owner, vendor.LandlordRenew, vendor.RenterRenew, vendor.Renew) => - m_Vendor = vendor; - - protected override bool IsValidResponse(Mobile from) => m_Vendor.CanInteractWith(from, true); - - protected override void RenterRenewOnExpiration(Mobile from) - { - m_Vendor.RenterRenew = !m_Vendor.RenterRenew; - - from.SendGump(new RenterVendorRentalGump(m_Vendor)); - } - } - - public class LandlordVendorRentalGump : BaseVendorRentalGump - { - private readonly RentedVendor m_Vendor; - - public LandlordVendorRentalGump(RentedVendor vendor) : base( - GumpType.VendorLandlord, vendor.RentalDuration, vendor.RentalPrice, vendor.RenewalPrice, - vendor.Landlord, vendor.Owner, vendor.LandlordRenew, vendor.RenterRenew, vendor.Renew) => - m_Vendor = vendor; - - protected override bool IsValidResponse(Mobile from) => m_Vendor.CanInteractWith(from, false) && m_Vendor.IsLandlord(from); - - protected override void LandlordRenewOnExpiration(Mobile from) - { - m_Vendor.LandlordRenew = !m_Vendor.LandlordRenew; - - from.SendGump(new LandlordVendorRentalGump(m_Vendor)); - } - - protected override void SetRenewalPrice(Mobile from) - { - from.SendLocalizedMessage(1062500); // Enter contract renewal price: - - from.Prompt = new ContractRenewalPricePrompt(m_Vendor); - } - - private class ContractRenewalPricePrompt : Prompt - { - private readonly RentedVendor m_Vendor; - - public ContractRenewalPricePrompt(RentedVendor vendor) => m_Vendor = vendor; - - public override void OnResponse(Mobile from, string text) - { - if (!m_Vendor.CanInteractWith(from, false) || !m_Vendor.IsLandlord(from)) - return; - - text = text.Trim(); - - if (!int.TryParse(text, out int price)) - price = -1; - - if (price < 0) - { - from.SendLocalizedMessage(1062485); // Invalid entry. Rental fee set to 0. - m_Vendor.RenewalPrice = 0; - } - else if (price > 5000000) - { - m_Vendor.RenewalPrice = 5000000; - } - else - { - m_Vendor.RenewalPrice = price; - } - - m_Vendor.RenterRenew = false; - - from.SendGump(new LandlordVendorRentalGump(m_Vendor)); - } - - public override void OnCancel(Mobile from) - { - if (m_Vendor.CanInteractWith(from, false) && m_Vendor.IsLandlord(from)) - from.SendGump(new LandlordVendorRentalGump(m_Vendor)); - } - } - } - - public class VendorRentalRefundGump : Gump - { - private readonly RentedVendor m_Vendor; - private readonly Mobile m_Landlord; - private readonly int m_RefundAmount; - - public VendorRentalRefundGump(RentedVendor vendor, Mobile landlord, int refundAmount) : base(50, 50) - { - m_Vendor = vendor; - m_Landlord = landlord; - m_RefundAmount = refundAmount; - - AddBackground(0, 0, 420, 320, 0x13BE); - - AddImageTiled(10, 10, 400, 300, 0xA40); - AddAlphaRegion(10, 10, 400, 300); - - /* The landlord for this vendor is offering you a partial refund of your rental fee - * in exchange for immediate termination of your rental contract.

- * - * If you accept this offer, the vendor will be immediately dismissed. You will then - * be able to claim the inventory and any funds the vendor may be holding for you via - * a context menu on the house sign for this house. - */ - AddHtmlLocalized(10, 10, 400, 150, 1062501, 0x7FFF, false, true); - - AddHtmlLocalized(10, 180, 150, 20, 1062508, 0x7FFF); // Vendor Name: - AddLabel(160, 180, 0x480, vendor.Name); - - AddHtmlLocalized(10, 200, 150, 20, 1062509, 0x7FFF); // Shop Name: - AddLabel(160, 200, 0x480, vendor.ShopName); - - AddHtmlLocalized(10, 220, 150, 20, 1062510, 0x7FFF); // Refund Amount: - AddLabel(160, 220, 0x480, refundAmount.ToString()); - - AddButton(10, 268, 0xFA5, 0xFA7, 1); - AddHtmlLocalized(45, 268, 350, 20, 1062511, 0x7FFF); // Agree, and dismiss vendor - - AddButton(10, 288, 0xFA5, 0xFA7, 0); - AddHtmlLocalized(45, 288, 350, 20, 1062512, 0x7FFF); // No, I want to keep my vendor - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - Mobile from = sender.Mobile; - - if (!m_Vendor.CanInteractWith(from, true) || !m_Vendor.CanInteractWith(m_Landlord, false) || !m_Vendor.IsLandlord(m_Landlord)) - return; - - if (info.ButtonID == 1) - { - if (Banker.Withdraw(m_Landlord, m_RefundAmount)) - { - m_Landlord.SendLocalizedMessage(1060398, m_RefundAmount.ToString()); // ~1_AMOUNT~ gold has been withdrawn from your bank box. - - int depositedGold = Banker.DepositUpTo(from, m_RefundAmount); - - if (depositedGold > 0) - from.SendLocalizedMessage(1060397, depositedGold.ToString()); // ~1_AMOUNT~ gold has been deposited into your bank box. - - m_Vendor.HoldGold += m_RefundAmount - depositedGold; - - m_Vendor.Destroy(false); - - from.SendLocalizedMessage(1071990); // Remember to claim your vendor's belongings from the house sign! - } - else - { - m_Landlord.SendLocalizedMessage(1062507); // You do not have that much money in your bank account. - } - } - else - { - m_Landlord.SendLocalizedMessage(1062513); // The renter declined your offer. - } - } - } -} +using Server.Items; +using Server.Mobiles; +using Server.Multis; +using Server.Network; +using Server.Prompts; +using Server.Targeting; + +namespace Server.Gumps +{ + public abstract class BaseVendorRentalGump : Gump + { + protected BaseVendorRentalGump( + GumpType type, VendorRentalDuration duration, int price, int renewalPrice, + Mobile landlord, Mobile renter, bool landlordRenew, bool renterRenew, bool renew + ) : base(100, 100) + { + if (type == GumpType.Offer) + Closable = false; + + AddPage(0); + + AddImage(0, 0, 0x1F40); + AddImageTiled(20, 37, 300, 308, 0x1F42); + AddImage(20, 325, 0x1F43); + + AddImage(35, 8, 0x39); + AddImageTiled(65, 8, 257, 10, 0x3A); + AddImage(290, 8, 0x3B); + + AddImageTiled(70, 55, 230, 2, 0x23C5); + + AddImage(32, 33, 0x2635); + AddHtmlLocalized(70, 35, 270, 20, 1062353, 0x1); // Vendor Rental Contract + + AddPage(1); + + if (type != GumpType.UnlockedContract) + { + AddImage(65, 60, 0x827); + AddHtmlLocalized(79, 58, 270, 20, 1062370, 0x1); // Landlord: + AddLabel(150, 58, 0x64, landlord != null ? landlord.Name : ""); + + AddImageTiled(70, 80, 230, 2, 0x23C5); + } + + if (type == GumpType.UnlockedContract || type == GumpType.LockedContract) + AddButton(30, 96, 0x15E1, 0x15E5, 0, GumpButtonType.Page, 2); + AddHtmlLocalized(50, 95, 150, 20, 1062354, 0x1); // Contract Length + AddHtmlLocalized(230, 95, 270, 20, duration.Name, 0x1); + + if (type == GumpType.UnlockedContract || type == GumpType.LockedContract) + AddButton(30, 116, 0x15E1, 0x15E5, 1); + AddHtmlLocalized(50, 115, 150, 20, 1062356, 0x1); // Price Per Rental + AddLabel(230, 115, 0x64, price > 0 ? price.ToString() : "FREE"); + + AddImageTiled(50, 160, 250, 2, 0x23BF); + + if (type == GumpType.Offer) + { + AddButton(67, 180, 0x482, 0x483, 2); + AddHtmlLocalized(100, 180, 270, 20, 1049011, 0x28); // I accept! + + AddButton(67, 210, 0x47F, 0x480, 0); + AddHtmlLocalized(100, 210, 270, 20, 1049012, 0x28); // No thanks, I decline. + } + else + { + AddImage(49, 170, 0x61); + AddHtmlLocalized(60, 170, 250, 20, 1062355, 0x1); // Renew On Expiration? + + if (type == GumpType.LockedContract || type == GumpType.UnlockedContract || type == GumpType.VendorLandlord) + AddButton(30, 192, 0x15E1, 0x15E5, 3); + AddHtmlLocalized(85, 190, 250, 20, 1062359, 0x1); // Landlord: + AddHtmlLocalized(230, 190, 270, 20, landlordRenew ? 1049717 : 1049718, 0x1); // YES / NO + + if (type == GumpType.VendorRenter) + AddButton(30, 212, 0x15E1, 0x15E5, 4); + AddHtmlLocalized(85, 210, 250, 20, 1062360, 0x1); // Renter: + AddHtmlLocalized(230, 210, 270, 20, renterRenew ? 1049717 : 1049718, 0x1); // YES / NO + + if (renew) + { + AddImage(49, 233, 0x939); + AddHtmlLocalized(70, 230, 250, 20, 1062482, 0x1); // Contract WILL renew + } + else + { + AddImage(49, 233, 0x938); + AddHtmlLocalized(70, 230, 250, 20, 1062483, 0x1); // Contract WILL NOT renew + } + } + + AddImageTiled(30, 283, 257, 30, 0x5D); + AddImage(285, 283, 0x5E); + AddImage(20, 288, 0x232C); + + if (type == GumpType.LockedContract) + { + AddButton(67, 295, 0x15E1, 0x15E5, 5); + AddHtmlLocalized(85, 294, 270, 20, 1062358, 0x28); // Offer Contract To Someone + } + else if (type == GumpType.VendorLandlord || type == GumpType.VendorRenter) + { + if (type == GumpType.VendorLandlord) + AddButton(30, 250, 0x15E1, 0x15E1, 6); + AddHtmlLocalized(85, 250, 250, 20, 1062499, 0x1); // Renewal Price + AddLabel(230, 250, 0x64, renewalPrice.ToString()); + + AddHtmlLocalized(60, 294, 270, 20, 1062369, 0x1); // Renter: + AddLabel(120, 293, 0x64, renter != null ? renter.Name : ""); + } + + if (type == GumpType.UnlockedContract || type == GumpType.LockedContract) + { + AddPage(2); + + for (var i = 0; i < VendorRentalDuration.Instances.Length; i++) + { + var durationItem = VendorRentalDuration.Instances[i]; + + AddButton(30, 76 + i * 20, 0x15E1, 0x15E5, 0x10 | i, GumpButtonType.Reply, 1); + AddHtmlLocalized(50, 75 + i * 20, 150, 20, durationItem.Name, 0x1); + } + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var from = sender.Mobile; + + if (!IsValidResponse(from)) + return; + + if ((info.ButtonID & 0x10) != 0) // Contract duration + { + var index = info.ButtonID & 0xF; + + if (index < VendorRentalDuration.Instances.Length) + SetContractDuration(from, VendorRentalDuration.Instances[index]); + } + else + { + switch (info.ButtonID) + { + case 1: // Price Per Rental + SetPricePerRental(from); + break; + + case 2: // Accept offer + AcceptOffer(from); + break; + + case 3: // Renew on expiration - landlord + LandlordRenewOnExpiration(from); + break; + + case 4: // Renew on expiration - renter + RenterRenewOnExpiration(from); + break; + + case 5: // Offer Contract To Someone + OfferContract(from); + break; + + case 6: // Renewal price + SetRenewalPrice(from); + break; + + default: + Cancel(from); + break; + } + } + } + + protected abstract bool IsValidResponse(Mobile from); + + protected virtual void SetContractDuration(Mobile from, VendorRentalDuration duration) + { + } + + protected virtual void SetPricePerRental(Mobile from) + { + } + + protected virtual void AcceptOffer(Mobile from) + { + } + + protected virtual void LandlordRenewOnExpiration(Mobile from) + { + } + + protected virtual void RenterRenewOnExpiration(Mobile from) + { + } + + protected virtual void OfferContract(Mobile from) + { + } + + protected virtual void SetRenewalPrice(Mobile from) + { + } + + protected virtual void Cancel(Mobile from) + { + } + + protected enum GumpType + { + UnlockedContract, + LockedContract, + Offer, + VendorLandlord, + VendorRenter + } + } + + public class VendorRentalContractGump : BaseVendorRentalGump + { + private readonly VendorRentalContract m_Contract; + + public VendorRentalContractGump(VendorRentalContract contract, Mobile from) : base( + contract.IsLockedDown ? GumpType.LockedContract : GumpType.UnlockedContract, + contract.Duration, + contract.Price, + contract.Price, + from, + null, + contract.LandlordRenew, + false, + false + ) => + m_Contract = contract; + + protected override bool IsValidResponse(Mobile from) => m_Contract.IsUsableBy(from, true, true, true, true); + + protected override void SetContractDuration(Mobile from, VendorRentalDuration duration) + { + m_Contract.Duration = duration; + + from.SendGump(new VendorRentalContractGump(m_Contract, from)); + } + + protected override void SetPricePerRental(Mobile from) + { + from.SendLocalizedMessage( + 1062365 + ); // Please enter the amount of gold that should be charged for this contract (ESC to cancel): + from.Prompt = new PricePerRentalPrompt(m_Contract); + } + + protected override void LandlordRenewOnExpiration(Mobile from) + { + m_Contract.LandlordRenew = !m_Contract.LandlordRenew; + + from.SendGump(new VendorRentalContractGump(m_Contract, from)); + } + + protected override void OfferContract(Mobile from) + { + if (m_Contract.IsLandlord(from)) + { + from.SendLocalizedMessage(1062371); // Please target the person you wish to offer this contract to. + from.Target = new OfferContractTarget(m_Contract); + } + } + + private class PricePerRentalPrompt : Prompt + { + private readonly VendorRentalContract m_Contract; + + public PricePerRentalPrompt(VendorRentalContract contract) => m_Contract = contract; + + public override void OnResponse(Mobile from, string text) + { + if (!m_Contract.IsUsableBy(from, true, true, true, true)) + return; + + text = text.Trim(); + + if (!int.TryParse(text, out var price)) + price = -1; + + if (price < 0) + { + from.SendLocalizedMessage(1062485); // Invalid entry. Rental fee set to 0. + m_Contract.Price = 0; + } + else if (price > 5000000) + { + m_Contract.Price = 5000000; + } + else + { + m_Contract.Price = price; + } + + from.SendGump(new VendorRentalContractGump(m_Contract, from)); + } + + public override void OnCancel(Mobile from) + { + if (m_Contract.IsUsableBy(from, true, true, true, true)) + from.SendGump(new VendorRentalContractGump(m_Contract, from)); + } + } + + private class OfferContractTarget : Target + { + private readonly VendorRentalContract m_Contract; + + public OfferContractTarget(VendorRentalContract contract) : base(-1, false, TargetFlags.None) => + m_Contract = contract; + + protected override void OnTarget(Mobile from, object targeted) + { + if (!m_Contract.IsUsableBy(from, true, false, true, true)) + return; + + if (!(targeted is Mobile mob) || !mob.Player || !mob.Alive || mob == from) + { + from.SendLocalizedMessage(1071984); // That is not a valid target for a rental contract! + } + else if (!mob.InRange(m_Contract, 5)) + { + from.SendLocalizedMessage(501853); // Target is too far away. + } + else + { + from.SendLocalizedMessage(1062372); // Please wait while that person considers your offer. + + mob.SendLocalizedMessage( + 1062373, + from.Name + ); // ~1_NAME~ is offering you a vendor rental. If you choose to accept this offer, you have 30 seconds to do so. + mob.SendGump(new VendorRentalOfferGump(m_Contract, from)); + + m_Contract.Offeree = mob; + } + } + + protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType) + { + from.SendLocalizedMessage(1062380); // You decide against offering the contract to anyone. + } + } + } + + public class VendorRentalOfferGump : BaseVendorRentalGump + { + private readonly VendorRentalContract m_Contract; + private readonly Mobile m_Landlord; + + public VendorRentalOfferGump(VendorRentalContract contract, Mobile landlord) : base( + GumpType.Offer, + contract.Duration, + contract.Price, + contract.Price, + landlord, + null, + contract.LandlordRenew, + false, + false + ) + { + m_Contract = contract; + m_Landlord = landlord; + } + + protected override bool IsValidResponse(Mobile from) => + m_Contract.IsUsableBy(m_Landlord, true, false, false, false) && from.CheckAlive() && m_Contract.Offeree == from; + + protected override void AcceptOffer(Mobile from) + { + m_Contract.Offeree = null; + + if (!m_Contract.Map.CanFit(m_Contract.Location, 16, false, false)) + { + m_Landlord.SendLocalizedMessage(1062486); // A vendor cannot exist at that location. Please try again. + return; + } + + var house = BaseHouse.FindHouseAt(m_Contract); + if (house == null) + return; + + var price = m_Contract.Price; + int goldToGive; + + if (price > 0) + { + if (Banker.Withdraw(from, price)) + { + from.SendLocalizedMessage( + 1060398, + price.ToString() + ); // ~1_AMOUNT~ gold has been withdrawn from your bank box. + + var depositedGold = Banker.DepositUpTo(m_Landlord, price); + goldToGive = price - depositedGold; + + if (depositedGold > 0) + m_Landlord.SendLocalizedMessage( + 1060397, + price.ToString() + ); // ~1_AMOUNT~ gold has been deposited into your bank box. + + if (goldToGive > 0) + m_Landlord.SendLocalizedMessage(500390); // Your bank box is full. + } + else + { + from.SendLocalizedMessage( + 1062378 + ); // You do not have enough gold in your bank account to cover the cost of the contract. + m_Landlord.SendLocalizedMessage(1062374, from.Name); // ~1_NAME~ has declined your vendor rental offer. + + return; + } + } + else + { + goldToGive = 0; + } + + PlayerVendor vendor = new RentedVendor( + from, + house, + m_Contract.Duration, + price, + m_Contract.LandlordRenew, + goldToGive + ); + vendor.MoveToWorld(m_Contract.Location, m_Contract.Map); + + m_Contract.Delete(); + + from.SendLocalizedMessage( + 1062377 + ); // You have accepted the offer and now own a vendor in this house. Rental contract options and details may be viewed on this vendor via the 'Contract Options' context menu. + m_Landlord.SendLocalizedMessage( + 1062376, + from.Name + ); // ~1_NAME~ has accepted your vendor rental offer. Rental contract details and options may be viewed on this vendor via the 'Contract Options' context menu. + } + + protected override void Cancel(Mobile from) + { + m_Contract.Offeree = null; + + from.SendLocalizedMessage(1062375); // You decline the offer for a vendor space rental. + m_Landlord.SendLocalizedMessage(1062374, from.Name); // ~1_NAME~ has declined your vendor rental offer. + } + } + + public class RenterVendorRentalGump : BaseVendorRentalGump + { + private readonly RentedVendor m_Vendor; + + public RenterVendorRentalGump(RentedVendor vendor) : base( + GumpType.VendorRenter, + vendor.RentalDuration, + vendor.RentalPrice, + vendor.RenewalPrice, + vendor.Landlord, + vendor.Owner, + vendor.LandlordRenew, + vendor.RenterRenew, + vendor.Renew + ) => + m_Vendor = vendor; + + protected override bool IsValidResponse(Mobile from) => m_Vendor.CanInteractWith(from, true); + + protected override void RenterRenewOnExpiration(Mobile from) + { + m_Vendor.RenterRenew = !m_Vendor.RenterRenew; + + from.SendGump(new RenterVendorRentalGump(m_Vendor)); + } + } + + public class LandlordVendorRentalGump : BaseVendorRentalGump + { + private readonly RentedVendor m_Vendor; + + public LandlordVendorRentalGump(RentedVendor vendor) : base( + GumpType.VendorLandlord, + vendor.RentalDuration, + vendor.RentalPrice, + vendor.RenewalPrice, + vendor.Landlord, + vendor.Owner, + vendor.LandlordRenew, + vendor.RenterRenew, + vendor.Renew + ) => + m_Vendor = vendor; + + protected override bool IsValidResponse(Mobile from) => + m_Vendor.CanInteractWith(from, false) && m_Vendor.IsLandlord(from); + + protected override void LandlordRenewOnExpiration(Mobile from) + { + m_Vendor.LandlordRenew = !m_Vendor.LandlordRenew; + + from.SendGump(new LandlordVendorRentalGump(m_Vendor)); + } + + protected override void SetRenewalPrice(Mobile from) + { + from.SendLocalizedMessage(1062500); // Enter contract renewal price: + + from.Prompt = new ContractRenewalPricePrompt(m_Vendor); + } + + private class ContractRenewalPricePrompt : Prompt + { + private readonly RentedVendor m_Vendor; + + public ContractRenewalPricePrompt(RentedVendor vendor) => m_Vendor = vendor; + + public override void OnResponse(Mobile from, string text) + { + if (!m_Vendor.CanInteractWith(from, false) || !m_Vendor.IsLandlord(from)) + return; + + text = text.Trim(); + + if (!int.TryParse(text, out var price)) + price = -1; + + if (price < 0) + { + from.SendLocalizedMessage(1062485); // Invalid entry. Rental fee set to 0. + m_Vendor.RenewalPrice = 0; + } + else if (price > 5000000) + { + m_Vendor.RenewalPrice = 5000000; + } + else + { + m_Vendor.RenewalPrice = price; + } + + m_Vendor.RenterRenew = false; + + from.SendGump(new LandlordVendorRentalGump(m_Vendor)); + } + + public override void OnCancel(Mobile from) + { + if (m_Vendor.CanInteractWith(from, false) && m_Vendor.IsLandlord(from)) + from.SendGump(new LandlordVendorRentalGump(m_Vendor)); + } + } + } + + public class VendorRentalRefundGump : Gump + { + private readonly Mobile m_Landlord; + private readonly int m_RefundAmount; + private readonly RentedVendor m_Vendor; + + public VendorRentalRefundGump(RentedVendor vendor, Mobile landlord, int refundAmount) : base(50, 50) + { + m_Vendor = vendor; + m_Landlord = landlord; + m_RefundAmount = refundAmount; + + AddBackground(0, 0, 420, 320, 0x13BE); + + AddImageTiled(10, 10, 400, 300, 0xA40); + AddAlphaRegion(10, 10, 400, 300); + + /* The landlord for this vendor is offering you a partial refund of your rental fee + * in exchange for immediate termination of your rental contract.

+ * + * If you accept this offer, the vendor will be immediately dismissed. You will then + * be able to claim the inventory and any funds the vendor may be holding for you via + * a context menu on the house sign for this house. + */ + AddHtmlLocalized(10, 10, 400, 150, 1062501, 0x7FFF, false, true); + + AddHtmlLocalized(10, 180, 150, 20, 1062508, 0x7FFF); // Vendor Name: + AddLabel(160, 180, 0x480, vendor.Name); + + AddHtmlLocalized(10, 200, 150, 20, 1062509, 0x7FFF); // Shop Name: + AddLabel(160, 200, 0x480, vendor.ShopName); + + AddHtmlLocalized(10, 220, 150, 20, 1062510, 0x7FFF); // Refund Amount: + AddLabel(160, 220, 0x480, refundAmount.ToString()); + + AddButton(10, 268, 0xFA5, 0xFA7, 1); + AddHtmlLocalized(45, 268, 350, 20, 1062511, 0x7FFF); // Agree, and dismiss vendor + + AddButton(10, 288, 0xFA5, 0xFA7, 0); + AddHtmlLocalized(45, 288, 350, 20, 1062512, 0x7FFF); // No, I want to keep my vendor + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var from = sender.Mobile; + + if (!m_Vendor.CanInteractWith(from, true) || !m_Vendor.CanInteractWith(m_Landlord, false) || + !m_Vendor.IsLandlord(m_Landlord)) + return; + + if (info.ButtonID == 1) + { + if (Banker.Withdraw(m_Landlord, m_RefundAmount)) + { + m_Landlord.SendLocalizedMessage( + 1060398, + m_RefundAmount.ToString() + ); // ~1_AMOUNT~ gold has been withdrawn from your bank box. + + var depositedGold = Banker.DepositUpTo(from, m_RefundAmount); + + if (depositedGold > 0) + from.SendLocalizedMessage( + 1060397, + depositedGold.ToString() + ); // ~1_AMOUNT~ gold has been deposited into your bank box. + + m_Vendor.HoldGold += m_RefundAmount - depositedGold; + + m_Vendor.Destroy(false); + + from.SendLocalizedMessage(1071990); // Remember to claim your vendor's belongings from the house sign! + } + else + { + m_Landlord.SendLocalizedMessage(1062507); // You do not have that much money in your bank account. + } + } + else + { + m_Landlord.SendLocalizedMessage(1062513); // The renter declined your offer. + } + } + } +} diff --git a/Projects/UOContent/Gumps/ViewHousesGump.cs b/Projects/UOContent/Gumps/ViewHousesGump.cs index 5bda4aea9..2384336ae 100644 --- a/Projects/UOContent/Gumps/ViewHousesGump.cs +++ b/Projects/UOContent/Gumps/ViewHousesGump.cs @@ -1,276 +1,285 @@ -using System.Collections.Generic; -using Server.Accounting; -using Server.Items; -using Server.Multis; -using Server.Network; -using Server.Targeting; - -namespace Server.Gumps -{ - public class ViewHousesGump : Gump - { - private const int White16 = 0x7FFF; - private const int White = 0xFFFFFF; - - private readonly Mobile m_From; - private readonly List m_List; - private readonly BaseHouse m_Selection; - - public ViewHousesGump(Mobile from, List list, BaseHouse sel) : base(50, 40) - { - m_From = from; - m_List = list; - m_Selection = sel; - - from.CloseGump(); - - AddPage(0); - - AddBackground(0, 0, 240, 360, 5054); - AddBlackAlpha(10, 10, 220, 340); - - if (sel?.Deleted != false) - { - m_Selection = null; - - AddHtml(35, 15, 120, 20, Color("House Type", White)); - - if (list.Count == 0) - AddHtml(35, 40, 160, 40, Color("There were no houses found for that player.", White)); - - AddImage(190, 17, 0x25EA); - AddImage(207, 17, 0x25E6); - - int page = 0; - - for (int i = 0; i < list.Count; ++i) - { - if (i % 15 == 0) - { - if (page > 0) - AddButton(207, 17, 0x15E1, 0x15E5, 0, GumpButtonType.Page, page + 1); - - AddPage(++page); - - if (page > 1) - AddButton(190, 17, 0x15E3, 0x15E7, 0, GumpButtonType.Page, page - 1); - } - - TextDefinition name = FindHouseName(list[i]); - - AddHtml(15, 40 + i % 15 * 20, 20, 20, Color($"{i + 1}.", White)); - - if (name.Number > 0) - AddHtmlLocalized(35, 40 + i % 15 * 20, 160, 20, name, White16); - else - AddHtml(35, 40 + i % 15 * 20, 160, 20, Color(name, White)); - - AddButton(198, 39 + i % 15 * 20, 4005, 4007, i + 1); - } - } - else - { - string location; - Map map = sel.Map; - - string houseName = sel.Sign == null ? "An Unnamed House" : sel.Sign.GetName(); - string owner = sel.Owner == null ? "nobody" : sel.Owner.Name; - - int xLong = 0, yLat = 0, xMins = 0, yMins = 0; - bool xEast = false, ySouth = false; - - bool valid = Sextant.Format(sel.Location, map, ref xLong, ref yLat, ref xMins, ref yMins, ref xEast, - ref ySouth); - - if (valid) - location = $"{yLat}° {yMins}'{(ySouth ? "S" : "N")}, {xLong}° {xMins}'{(xEast ? "E" : "W")}"; - else - location = "unknown"; - - AddHtml(10, 15, 220, 20, Color(Center("House Properties"), White)); - - AddHtml(15, 40, 210, 20, Color("Facet:", White)); - AddHtml(15, 40, 210, 20, Color(Right(map == null ? "(null)" : map.Name), White)); - - AddHtml(15, 60, 210, 20, Color("Location:", White)); - AddHtml(15, 60, 210, 20, Color(Right(sel.Location.ToString()), White)); - - AddHtml(15, 80, 210, 20, Color("Sextant:", White)); - AddHtml(15, 80, 210, 20, Color(Right(location), White)); - - AddHtml(15, 100, 210, 20, Color("Owner:", White)); - AddHtml(15, 100, 210, 20, Color(Right(owner), White)); - - AddHtml(15, 120, 210, 20, Color("Name:", White)); - AddHtml(15, 120, 210, 20, Color(Right(houseName), White)); - - AddHtml(15, 140, 210, 20, Color("Friends:", White)); - AddHtml(15, 140, 210, 20, Color(Right(sel.Friends.Count.ToString()), White)); - - AddHtml(15, 160, 210, 20, Color("Co-Owners:", White)); - AddHtml(15, 160, 210, 20, Color(Right(sel.CoOwners.Count.ToString()), White)); - - AddHtml(15, 180, 210, 20, Color("Bans:", White)); - AddHtml(15, 180, 210, 20, Color(Right(sel.Bans.Count.ToString()), White)); - - AddHtml(15, 200, 210, 20, Color("Decays:", White)); - AddHtml(15, 200, 210, 20, Color(Right(sel.CanDecay ? "Yes" : "No"), White)); - - AddHtml(15, 220, 210, 20, Color("Decay Level:", White)); - AddHtml(15, 220, 210, 20, Color(Right(sel.DecayLevel.ToString()), White)); - - AddButton(15, 245, 4005, 4007, 1); - AddHtml(50, 245, 120, 20, Color("Go to house", White)); - - AddButton(15, 265, 4005, 4007, 2); - AddHtml(50, 265, 120, 20, Color("Open house menu", White)); - - AddButton(15, 285, 4005, 4007, 3); - AddHtml(50, 285, 120, 20, Color("Demolish house", White)); - - AddButton(15, 305, 4005, 4007, 4); - AddHtml(50, 305, 120, 20, Color("Refresh house", White)); - } - } - - public static void Initialize() - { - CommandSystem.Register("ViewHouses", AccessLevel.GameMaster, ViewHouses_OnCommand); - } - - [Usage("ViewHouses")] - [Description( - "Displays a menu listing all houses of a targeted player. The menu also contains specific house details, and options to: go to house, open house menu, and demolish house.")] - public static void ViewHouses_OnCommand(CommandEventArgs e) - { - e.Mobile.BeginTarget(-1, false, TargetFlags.None, ViewHouses_OnTarget); - } - - public static void ViewHouses_OnTarget(Mobile from, object targeted) - { - if (targeted is Mobile mobile) - from.SendGump(new ViewHousesGump(from, GetHouses(mobile), null)); - } - - public static List GetHouses(Mobile owner) - { - List list = new List(); - - if (!(owner.Account is Account acct)) - list.AddRange(BaseHouse.GetHouses(owner)); - else - for (int i = 0; i < acct.Length; ++i) - { - Mobile mob = acct[i]; - - if (mob != null) - list.AddRange(BaseHouse.GetHouses(mob)); - } - - list.Sort(HouseComparer.Instance); - - return list; - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Selection == null) - { - int v = info.ButtonID - 1; - - if (v >= 0 && v < m_List.Count) - m_From.SendGump(new ViewHousesGump(m_From, m_List, m_List[v])); - } - else if (!m_Selection.Deleted) - { - switch (info.ButtonID) - { - case 0: - { - m_From.SendGump(new ViewHousesGump(m_From, m_List, null)); - break; - } - case 1: - { - Map map = m_Selection.Map; - - if (map != null && map != Map.Internal) - m_From.MoveToWorld(m_Selection.BanLocation, map); - - m_From.SendGump(new ViewHousesGump(m_From, m_List, m_Selection)); - - break; - } - case 2: - { - m_From.SendGump(new ViewHousesGump(m_From, m_List, m_Selection)); - - HouseSign sign = m_Selection.Sign; - - if (sign?.Deleted == false) - sign.OnDoubleClick(m_From); - - break; - } - case 3: - { - m_From.SendGump(new ViewHousesGump(m_From, m_List, m_Selection)); - m_From.SendGump(new HouseDemolishGump(m_From, m_Selection)); - - break; - } - case 4: - { - m_Selection.RefreshDecay(); - m_From.SendGump(new ViewHousesGump(m_From, m_List, m_Selection)); - - break; - } - } - } - } - - public static TextDefinition FindHouseName(BaseHouse house) - { - int multiID = house.ItemID; - HousePlacementEntry[] entries = HousePlacementEntry.ClassicHouses; - - for (int i = 0; i < entries.Length; ++i) - if (entries[i].MultiID == multiID) - return entries[i].Description; - - entries = HousePlacementEntry.TwoStoryFoundations; - - for (int i = 0; i < entries.Length; ++i) - if (entries[i].MultiID == multiID) - return entries[i].Description; - - entries = HousePlacementEntry.ThreeStoryFoundations; - - for (int i = 0; i < entries.Length; ++i) - if (entries[i].MultiID == multiID) - return entries[i].Description; - - return house.GetType().Name; - } - - public string Right(string text) => $"
{text}
"; - - public string Center(string text) => $"
{text}
"; - - public string Color(string text, int color) => $"{text}"; - - public void AddBlackAlpha(int x, int y, int width, int height) - { - AddImageTiled(x, y, width, height, 2624); - AddAlphaRegion(x, y, width, height); - } - - private class HouseComparer : IComparer - { - public static readonly IComparer Instance = new HouseComparer(); - - public int Compare(BaseHouse x, BaseHouse y) => x?.BuiltOn.CompareTo(y?.BuiltOn) ?? 0; - } - } -} +using System.Collections.Generic; +using Server.Accounting; +using Server.Items; +using Server.Multis; +using Server.Network; +using Server.Targeting; + +namespace Server.Gumps +{ + public class ViewHousesGump : Gump + { + private const int White16 = 0x7FFF; + private const int White = 0xFFFFFF; + + private readonly Mobile m_From; + private readonly List m_List; + private readonly BaseHouse m_Selection; + + public ViewHousesGump(Mobile from, List list, BaseHouse sel) : base(50, 40) + { + m_From = from; + m_List = list; + m_Selection = sel; + + from.CloseGump(); + + AddPage(0); + + AddBackground(0, 0, 240, 360, 5054); + AddBlackAlpha(10, 10, 220, 340); + + if (sel?.Deleted != false) + { + m_Selection = null; + + AddHtml(35, 15, 120, 20, Color("House Type", White)); + + if (list.Count == 0) + AddHtml(35, 40, 160, 40, Color("There were no houses found for that player.", White)); + + AddImage(190, 17, 0x25EA); + AddImage(207, 17, 0x25E6); + + var page = 0; + + for (var i = 0; i < list.Count; ++i) + { + if (i % 15 == 0) + { + if (page > 0) + AddButton(207, 17, 0x15E1, 0x15E5, 0, GumpButtonType.Page, page + 1); + + AddPage(++page); + + if (page > 1) + AddButton(190, 17, 0x15E3, 0x15E7, 0, GumpButtonType.Page, page - 1); + } + + var name = FindHouseName(list[i]); + + AddHtml(15, 40 + i % 15 * 20, 20, 20, Color($"{i + 1}.", White)); + + if (name.Number > 0) + AddHtmlLocalized(35, 40 + i % 15 * 20, 160, 20, name, White16); + else + AddHtml(35, 40 + i % 15 * 20, 160, 20, Color(name, White)); + + AddButton(198, 39 + i % 15 * 20, 4005, 4007, i + 1); + } + } + else + { + string location; + var map = sel.Map; + + var houseName = sel.Sign == null ? "An Unnamed House" : sel.Sign.GetName(); + var owner = sel.Owner == null ? "nobody" : sel.Owner.Name; + + int xLong = 0, yLat = 0, xMins = 0, yMins = 0; + bool xEast = false, ySouth = false; + + var valid = Sextant.Format( + sel.Location, + map, + ref xLong, + ref yLat, + ref xMins, + ref yMins, + ref xEast, + ref ySouth + ); + + if (valid) + location = $"{yLat}° {yMins}'{(ySouth ? "S" : "N")}, {xLong}° {xMins}'{(xEast ? "E" : "W")}"; + else + location = "unknown"; + + AddHtml(10, 15, 220, 20, Color(Center("House Properties"), White)); + + AddHtml(15, 40, 210, 20, Color("Facet:", White)); + AddHtml(15, 40, 210, 20, Color(Right(map == null ? "(null)" : map.Name), White)); + + AddHtml(15, 60, 210, 20, Color("Location:", White)); + AddHtml(15, 60, 210, 20, Color(Right(sel.Location.ToString()), White)); + + AddHtml(15, 80, 210, 20, Color("Sextant:", White)); + AddHtml(15, 80, 210, 20, Color(Right(location), White)); + + AddHtml(15, 100, 210, 20, Color("Owner:", White)); + AddHtml(15, 100, 210, 20, Color(Right(owner), White)); + + AddHtml(15, 120, 210, 20, Color("Name:", White)); + AddHtml(15, 120, 210, 20, Color(Right(houseName), White)); + + AddHtml(15, 140, 210, 20, Color("Friends:", White)); + AddHtml(15, 140, 210, 20, Color(Right(sel.Friends.Count.ToString()), White)); + + AddHtml(15, 160, 210, 20, Color("Co-Owners:", White)); + AddHtml(15, 160, 210, 20, Color(Right(sel.CoOwners.Count.ToString()), White)); + + AddHtml(15, 180, 210, 20, Color("Bans:", White)); + AddHtml(15, 180, 210, 20, Color(Right(sel.Bans.Count.ToString()), White)); + + AddHtml(15, 200, 210, 20, Color("Decays:", White)); + AddHtml(15, 200, 210, 20, Color(Right(sel.CanDecay ? "Yes" : "No"), White)); + + AddHtml(15, 220, 210, 20, Color("Decay Level:", White)); + AddHtml(15, 220, 210, 20, Color(Right(sel.DecayLevel.ToString()), White)); + + AddButton(15, 245, 4005, 4007, 1); + AddHtml(50, 245, 120, 20, Color("Go to house", White)); + + AddButton(15, 265, 4005, 4007, 2); + AddHtml(50, 265, 120, 20, Color("Open house menu", White)); + + AddButton(15, 285, 4005, 4007, 3); + AddHtml(50, 285, 120, 20, Color("Demolish house", White)); + + AddButton(15, 305, 4005, 4007, 4); + AddHtml(50, 305, 120, 20, Color("Refresh house", White)); + } + } + + public static void Initialize() + { + CommandSystem.Register("ViewHouses", AccessLevel.GameMaster, ViewHouses_OnCommand); + } + + [Usage("ViewHouses")] + [Description( + "Displays a menu listing all houses of a targeted player. The menu also contains specific house details, and options to: go to house, open house menu, and demolish house." + )] + public static void ViewHouses_OnCommand(CommandEventArgs e) + { + e.Mobile.BeginTarget(-1, false, TargetFlags.None, ViewHouses_OnTarget); + } + + public static void ViewHouses_OnTarget(Mobile from, object targeted) + { + if (targeted is Mobile mobile) + from.SendGump(new ViewHousesGump(from, GetHouses(mobile), null)); + } + + public static List GetHouses(Mobile owner) + { + var list = new List(); + + if (!(owner.Account is Account acct)) + list.AddRange(BaseHouse.GetHouses(owner)); + else + for (var i = 0; i < acct.Length; ++i) + { + var mob = acct[i]; + + if (mob != null) + list.AddRange(BaseHouse.GetHouses(mob)); + } + + list.Sort(HouseComparer.Instance); + + return list; + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Selection == null) + { + var v = info.ButtonID - 1; + + if (v >= 0 && v < m_List.Count) + m_From.SendGump(new ViewHousesGump(m_From, m_List, m_List[v])); + } + else if (!m_Selection.Deleted) + { + switch (info.ButtonID) + { + case 0: + { + m_From.SendGump(new ViewHousesGump(m_From, m_List, null)); + break; + } + case 1: + { + var map = m_Selection.Map; + + if (map != null && map != Map.Internal) + m_From.MoveToWorld(m_Selection.BanLocation, map); + + m_From.SendGump(new ViewHousesGump(m_From, m_List, m_Selection)); + + break; + } + case 2: + { + m_From.SendGump(new ViewHousesGump(m_From, m_List, m_Selection)); + + var sign = m_Selection.Sign; + + if (sign?.Deleted == false) + sign.OnDoubleClick(m_From); + + break; + } + case 3: + { + m_From.SendGump(new ViewHousesGump(m_From, m_List, m_Selection)); + m_From.SendGump(new HouseDemolishGump(m_From, m_Selection)); + + break; + } + case 4: + { + m_Selection.RefreshDecay(); + m_From.SendGump(new ViewHousesGump(m_From, m_List, m_Selection)); + + break; + } + } + } + } + + public static TextDefinition FindHouseName(BaseHouse house) + { + var multiID = house.ItemID; + var entries = HousePlacementEntry.ClassicHouses; + + for (var i = 0; i < entries.Length; ++i) + if (entries[i].MultiID == multiID) + return entries[i].Description; + + entries = HousePlacementEntry.TwoStoryFoundations; + + for (var i = 0; i < entries.Length; ++i) + if (entries[i].MultiID == multiID) + return entries[i].Description; + + entries = HousePlacementEntry.ThreeStoryFoundations; + + for (var i = 0; i < entries.Length; ++i) + if (entries[i].MultiID == multiID) + return entries[i].Description; + + return house.GetType().Name; + } + + public string Right(string text) => $"
{text}
"; + + public string Center(string text) => $"
{text}
"; + + public string Color(string text, int color) => $"{text}"; + + public void AddBlackAlpha(int x, int y, int width, int height) + { + AddImageTiled(x, y, width, height, 2624); + AddAlphaRegion(x, y, width, height); + } + + private class HouseComparer : IComparer + { + public static readonly IComparer Instance = new HouseComparer(); + + public int Compare(BaseHouse x, BaseHouse y) => x?.BuiltOn.CompareTo(y?.BuiltOn) ?? 0; + } + } +} diff --git a/Projects/UOContent/Gumps/WarningGump.cs b/Projects/UOContent/Gumps/WarningGump.cs index 3ccee7be9..8ecd0b909 100644 --- a/Projects/UOContent/Gumps/WarningGump.cs +++ b/Projects/UOContent/Gumps/WarningGump.cs @@ -1,55 +1,68 @@ -namespace Server.Gumps -{ - public delegate void WarningGumpCallback(bool okay); - - public class WarningGump : Gump - { - private readonly WarningGumpCallback m_Callback; - - public WarningGump(int header, int headerColor, object content, int contentColor, int width, int height, WarningGumpCallback callback = null, bool cancelButton = true) : base((640 - width) / 2, (480 - height) / 2) - { - m_Callback = callback; - - Closable = false; - - AddPage(0); - - AddBackground(0, 0, width, height, 5054); - - AddImageTiled(10, 10, width - 20, 20, 2624); - AddAlphaRegion(10, 10, width - 20, 20); - AddHtmlLocalized(10, 10, width - 20, 20, header, headerColor); - - AddImageTiled(10, 40, width - 20, height - 80, 2624); - AddAlphaRegion(10, 40, width - 20, height - 80); - - if (content is int i) - AddHtmlLocalized(10, 40, width - 20, height - 80, i, contentColor, false, true); - else if (content is string) - AddHtml(10, 40, width - 20, height - 80, $"{content}", false, true); - - AddImageTiled(10, height - 30, width - 20, 20, 2624); - AddAlphaRegion(10, height - 30, width - 20, 20); - - AddButton(10, height - 30, 4005, 4007, 1); - AddHtmlLocalized(40, height - 30, 170, 20, 1011036, 32767); // OKAY - - if (cancelButton) - { - AddButton(10 + (width - 20) / 2, height - 30, 4005, 4007, 0); - AddHtmlLocalized(40 + (width - 20) / 2, height - 30, 170, 20, 1011012, 32767); // CANCEL - } - } - - public override void OnResponse(Network.NetState sender, RelayInfo info) - { - if (m_Callback == null) - return; - - if (info.ButtonID == 1) - m_Callback(true); - else - m_Callback.Invoke(false); - } - } -} +using Server.Network; + +namespace Server.Gumps +{ + public delegate void WarningGumpCallback(bool okay); + + public class WarningGump : Gump + { + private readonly WarningGumpCallback m_Callback; + + public WarningGump( + int header, int headerColor, object content, int contentColor, int width, int height, + WarningGumpCallback callback = null, bool cancelButton = true + ) : base((640 - width) / 2, (480 - height) / 2) + { + m_Callback = callback; + + Closable = false; + + AddPage(0); + + AddBackground(0, 0, width, height, 5054); + + AddImageTiled(10, 10, width - 20, 20, 2624); + AddAlphaRegion(10, 10, width - 20, 20); + AddHtmlLocalized(10, 10, width - 20, 20, header, headerColor); + + AddImageTiled(10, 40, width - 20, height - 80, 2624); + AddAlphaRegion(10, 40, width - 20, height - 80); + + if (content is int i) + AddHtmlLocalized(10, 40, width - 20, height - 80, i, contentColor, false, true); + else if (content is string) + AddHtml( + 10, + 40, + width - 20, + height - 80, + $"{content}", + false, + true + ); + + AddImageTiled(10, height - 30, width - 20, 20, 2624); + AddAlphaRegion(10, height - 30, width - 20, 20); + + AddButton(10, height - 30, 4005, 4007, 1); + AddHtmlLocalized(40, height - 30, 170, 20, 1011036, 32767); // OKAY + + if (cancelButton) + { + AddButton(10 + (width - 20) / 2, height - 30, 4005, 4007, 0); + AddHtmlLocalized(40 + (width - 20) / 2, height - 30, 170, 20, 1011012, 32767); // CANCEL + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Callback == null) + return; + + if (info.ButtonID == 1) + m_Callback(true); + else + m_Callback.Invoke(false); + } + } +} diff --git a/Projects/UOContent/Gumps/WhoGump.cs b/Projects/UOContent/Gumps/WhoGump.cs index c478926e3..f2ce28130 100644 --- a/Projects/UOContent/Gumps/WhoGump.cs +++ b/Projects/UOContent/Gumps/WhoGump.cs @@ -1,283 +1,309 @@ -using System; -using System.Collections.Generic; -using Server.Mobiles; -using Server.Network; - -namespace Server.Gumps -{ - public class WhoGump : Gump - { - public static void Initialize() - { - CommandSystem.Register("Who", AccessLevel.Counselor, WhoList_OnCommand); - CommandSystem.Register("WhoList", AccessLevel.Counselor, WhoList_OnCommand); - } - - [Usage("WhoList [filter]")] - [Aliases("Who")] - [Description("Lists all connected clients. Optionally filters results by name.")] - private static void WhoList_OnCommand(CommandEventArgs e) - { - e.Mobile.SendGump(new WhoGump(e.Mobile, e.ArgString)); - } - - public static bool OldStyle = PropsConfig.OldStyle; - - public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; - public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; - - public static readonly int TextHue = PropsConfig.TextHue; - public static readonly int TextOffsetX = PropsConfig.TextOffsetX; - - public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; - public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; - public static readonly int EntryGumpID = PropsConfig.EntryGumpID; - public static readonly int BackGumpID = PropsConfig.BackGumpID; - public static readonly int SetGumpID = PropsConfig.SetGumpID; - - public static readonly int SetWidth = PropsConfig.SetWidth; - public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY; - public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; - public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; - - public static readonly int PrevWidth = PropsConfig.PrevWidth; - public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY; - public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; - public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; - - public static readonly int NextWidth = PropsConfig.NextWidth; - public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY; - public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; - public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; - - public static readonly int OffsetSize = PropsConfig.OffsetSize; - - public static readonly int EntryHeight = PropsConfig.EntryHeight; - public static readonly int BorderSize = PropsConfig.BorderSize; - - private static readonly bool PrevLabel = false; - private static readonly bool NextLabel = false; - - private static readonly int PrevLabelOffsetX = PrevWidth + 1; - private static readonly int PrevLabelOffsetY = 0; - - private static readonly int NextLabelOffsetX = -29; - private static readonly int NextLabelOffsetY = 0; - - private static readonly int EntryWidth = 180; - private static readonly int EntryCount = 15; - - private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize; - private static readonly int TotalHeight = OffsetSize + (EntryHeight + OffsetSize) * (EntryCount + 1); - - private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; - private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize; - - private Mobile m_Owner; - private readonly List m_Mobiles; - private int m_Page; - - private class InternalComparer : IComparer - { - public static readonly IComparer Instance = new InternalComparer(); - - public int Compare(Mobile x, Mobile y) - { - if (x == null || y == null) - throw new ArgumentException(); - - if (x.AccessLevel > y.AccessLevel) - return -1; - if (x.AccessLevel < y.AccessLevel) - return 1; - return Insensitive.Compare(x.Name, y.Name); - } - } - - public WhoGump(Mobile owner, string filter) : this(owner, BuildList(owner, filter)) - { - } - - public WhoGump(Mobile owner, List list, int page = 0) : base(GumpOffsetX, GumpOffsetY) - { - owner.CloseGump(); - - m_Owner = owner; - m_Mobiles = list; - - Initialize(page); - } - - public static List BuildList(Mobile owner, string rawFilter) - { - string filter = rawFilter.Trim().ToLower().IsNullOrDefault(null); - - List list = new List(); - List states = TcpServer.Instances; - - for (int i = 0; i < states.Count; ++i) - { - Mobile m = states[i].Mobile; - - if (m != null && (m == owner || !m.Hidden || owner.AccessLevel >= m.AccessLevel || (m is PlayerMobile mobile && mobile.VisibilityList.Contains(owner)))) - { - if (filter != null && !(m.Name?.ToLower().IndexOf(filter) >= 0)) - continue; - - list.Add(m); - } - } - - list.Sort(InternalComparer.Instance); - - return list; - } - - public void Initialize(int page) - { - m_Page = page; - - int count = Math.Clamp(m_Mobiles.Count - page * EntryCount, 0, EntryCount); - - int totalHeight = OffsetSize + (EntryHeight + OffsetSize) * (count + 1); - - AddPage(0); - - AddBackground(0, 0, BackWidth, BorderSize + totalHeight + BorderSize, BackGumpID); - AddImageTiled(BorderSize, BorderSize, TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), totalHeight, OffsetGumpID); - - int x = BorderSize + OffsetSize; - int y = BorderSize + OffsetSize; - - int emptyWidth = TotalWidth - PrevWidth - NextWidth - OffsetSize * 4 - (OldStyle ? SetWidth + OffsetSize : 0); - - if (!OldStyle) - AddImageTiled(x - (OldStyle ? OffsetSize : 0), y, emptyWidth + (OldStyle ? OffsetSize * 2 : 0), EntryHeight, EntryGumpID); - - AddLabel(x + TextOffsetX, y, TextHue, - $"Page {page + 1} of {(m_Mobiles.Count + EntryCount - 1) / EntryCount} ({m_Mobiles.Count})"); - - x += emptyWidth + OffsetSize; - - if (OldStyle) - AddImageTiled(x, y, TotalWidth - OffsetSize * 3 - SetWidth, EntryHeight, HeaderGumpID); - else - AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); - - if (page > 0) - { - AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 1); - - if (PrevLabel) - AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous"); - } - - x += PrevWidth + OffsetSize; - - if (!OldStyle) - AddImageTiled(x, y, NextWidth, EntryHeight, HeaderGumpID); - - if ((page + 1) * EntryCount < m_Mobiles.Count) - { - AddButton(x + NextOffsetX, y + NextOffsetY, NextButtonID1, NextButtonID2, 2, GumpButtonType.Reply, 1); - - if (NextLabel) - AddLabel(x + NextLabelOffsetX, y + NextLabelOffsetY, TextHue, "Next"); - } - - for (int i = 0, index = page * EntryCount; i < EntryCount && index < m_Mobiles.Count; ++i, ++index) - { - x = BorderSize + OffsetSize; - y += EntryHeight + OffsetSize; - - Mobile m = m_Mobiles[index]; - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, GetHueFor(m), m.Deleted ? "(deleted)" : m.Name); - - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - - if (m.NetState != null && !m.Deleted) - AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, i + 3); - } - } - - private static int GetHueFor(Mobile m) - { - switch (m.AccessLevel) - { - case AccessLevel.Owner: - case AccessLevel.Developer: - case AccessLevel.Administrator: return 0x516; - case AccessLevel.Seer: return 0x144; - case AccessLevel.GameMaster: return 0x21; - case AccessLevel.Counselor: return 0x2; - default: - { - return m.Kills >= 5 ? 0x21 : m.Criminal ? 0x3B1 : 0x58; - } - } - } - - public override void OnResponse(NetState state, RelayInfo info) - { - Mobile from = state.Mobile; - - switch (info.ButtonID) - { - case 0: // Closed - { - return; - } - case 1: // Previous - { - if (m_Page > 0) - from.SendGump(new WhoGump(from, m_Mobiles, m_Page - 1)); - - break; - } - case 2: // Next - { - if ((m_Page + 1) * EntryCount < m_Mobiles.Count) - from.SendGump(new WhoGump(from, m_Mobiles, m_Page + 1)); - - break; - } - default: - { - int index = m_Page * EntryCount + (info.ButtonID - 3); - - if (index >= 0 && index < m_Mobiles.Count) - { - Mobile m = m_Mobiles[index]; - - if (m.Deleted) - { - from.SendMessage("That player has deleted their character."); - from.SendGump(new WhoGump(from, m_Mobiles, m_Page)); - } - else if (m.NetState == null) - { - from.SendMessage("That player is no longer online."); - from.SendGump(new WhoGump(from, m_Mobiles, m_Page)); - } - else if (m == from || !m.Hidden || from.AccessLevel >= m.AccessLevel || (m is PlayerMobile mobile && mobile.VisibilityList.Contains(from))) - { - from.SendGump(new ClientGump(from, m.NetState)); - } - else - { - from.SendMessage("You cannot see them."); - from.SendGump(new WhoGump(from, m_Mobiles, m_Page)); - } - } - - break; - } - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Mobiles; +using Server.Network; + +namespace Server.Gumps +{ + public class WhoGump : Gump + { + public static bool OldStyle = PropsConfig.OldStyle; + + public static readonly int GumpOffsetX = PropsConfig.GumpOffsetX; + public static readonly int GumpOffsetY = PropsConfig.GumpOffsetY; + + public static readonly int TextHue = PropsConfig.TextHue; + public static readonly int TextOffsetX = PropsConfig.TextOffsetX; + + public static readonly int OffsetGumpID = PropsConfig.OffsetGumpID; + public static readonly int HeaderGumpID = PropsConfig.HeaderGumpID; + public static readonly int EntryGumpID = PropsConfig.EntryGumpID; + public static readonly int BackGumpID = PropsConfig.BackGumpID; + public static readonly int SetGumpID = PropsConfig.SetGumpID; + + public static readonly int SetWidth = PropsConfig.SetWidth; + public static readonly int SetOffsetX = PropsConfig.SetOffsetX, SetOffsetY = PropsConfig.SetOffsetY; + public static readonly int SetButtonID1 = PropsConfig.SetButtonID1; + public static readonly int SetButtonID2 = PropsConfig.SetButtonID2; + + public static readonly int PrevWidth = PropsConfig.PrevWidth; + public static readonly int PrevOffsetX = PropsConfig.PrevOffsetX, PrevOffsetY = PropsConfig.PrevOffsetY; + public static readonly int PrevButtonID1 = PropsConfig.PrevButtonID1; + public static readonly int PrevButtonID2 = PropsConfig.PrevButtonID2; + + public static readonly int NextWidth = PropsConfig.NextWidth; + public static readonly int NextOffsetX = PropsConfig.NextOffsetX, NextOffsetY = PropsConfig.NextOffsetY; + public static readonly int NextButtonID1 = PropsConfig.NextButtonID1; + public static readonly int NextButtonID2 = PropsConfig.NextButtonID2; + + public static readonly int OffsetSize = PropsConfig.OffsetSize; + + public static readonly int EntryHeight = PropsConfig.EntryHeight; + public static readonly int BorderSize = PropsConfig.BorderSize; + + private static readonly bool PrevLabel = false; + private static readonly bool NextLabel = false; + + private static readonly int PrevLabelOffsetX = PrevWidth + 1; + private static readonly int PrevLabelOffsetY = 0; + + private static readonly int NextLabelOffsetX = -29; + private static readonly int NextLabelOffsetY = 0; + + private static readonly int EntryWidth = 180; + private static readonly int EntryCount = 15; + + private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize; + private static readonly int TotalHeight = OffsetSize + (EntryHeight + OffsetSize) * (EntryCount + 1); + + private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; + private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize; + private readonly List m_Mobiles; + + private Mobile m_Owner; + private int m_Page; + + public WhoGump(Mobile owner, string filter) : this(owner, BuildList(owner, filter)) + { + } + + public WhoGump(Mobile owner, List list, int page = 0) : base(GumpOffsetX, GumpOffsetY) + { + owner.CloseGump(); + + m_Owner = owner; + m_Mobiles = list; + + Initialize(page); + } + + public static void Initialize() + { + CommandSystem.Register("Who", AccessLevel.Counselor, WhoList_OnCommand); + CommandSystem.Register("WhoList", AccessLevel.Counselor, WhoList_OnCommand); + } + + [Usage("WhoList [filter]")] + [Aliases("Who")] + [Description("Lists all connected clients. Optionally filters results by name.")] + private static void WhoList_OnCommand(CommandEventArgs e) + { + e.Mobile.SendGump(new WhoGump(e.Mobile, e.ArgString)); + } + + public static List BuildList(Mobile owner, string rawFilter) + { + var filter = rawFilter.Trim().ToLower().IsNullOrDefault(null); + + var list = new List(); + var states = TcpServer.Instances; + + for (var i = 0; i < states.Count; ++i) + { + var m = states[i].Mobile; + + if (m != null && (m == owner || !m.Hidden || owner.AccessLevel >= m.AccessLevel || + m is PlayerMobile mobile && mobile.VisibilityList.Contains(owner))) + { + if (filter != null && !(m.Name?.ToLower().IndexOf(filter) >= 0)) + continue; + + list.Add(m); + } + } + + list.Sort(InternalComparer.Instance); + + return list; + } + + public void Initialize(int page) + { + m_Page = page; + + var count = Math.Clamp(m_Mobiles.Count - page * EntryCount, 0, EntryCount); + + var totalHeight = OffsetSize + (EntryHeight + OffsetSize) * (count + 1); + + AddPage(0); + + AddBackground(0, 0, BackWidth, BorderSize + totalHeight + BorderSize, BackGumpID); + AddImageTiled( + BorderSize, + BorderSize, + TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), + totalHeight, + OffsetGumpID + ); + + var x = BorderSize + OffsetSize; + var y = BorderSize + OffsetSize; + + var emptyWidth = TotalWidth - PrevWidth - NextWidth - OffsetSize * 4 - (OldStyle ? SetWidth + OffsetSize : 0); + + if (!OldStyle) + AddImageTiled( + x - (OldStyle ? OffsetSize : 0), + y, + emptyWidth + (OldStyle ? OffsetSize * 2 : 0), + EntryHeight, + EntryGumpID + ); + + AddLabel( + x + TextOffsetX, + y, + TextHue, + $"Page {page + 1} of {(m_Mobiles.Count + EntryCount - 1) / EntryCount} ({m_Mobiles.Count})" + ); + + x += emptyWidth + OffsetSize; + + if (OldStyle) + AddImageTiled(x, y, TotalWidth - OffsetSize * 3 - SetWidth, EntryHeight, HeaderGumpID); + else + AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); + + if (page > 0) + { + AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 1); + + if (PrevLabel) + AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous"); + } + + x += PrevWidth + OffsetSize; + + if (!OldStyle) + AddImageTiled(x, y, NextWidth, EntryHeight, HeaderGumpID); + + if ((page + 1) * EntryCount < m_Mobiles.Count) + { + AddButton(x + NextOffsetX, y + NextOffsetY, NextButtonID1, NextButtonID2, 2, GumpButtonType.Reply, 1); + + if (NextLabel) + AddLabel(x + NextLabelOffsetX, y + NextLabelOffsetY, TextHue, "Next"); + } + + for (int i = 0, index = page * EntryCount; i < EntryCount && index < m_Mobiles.Count; ++i, ++index) + { + x = BorderSize + OffsetSize; + y += EntryHeight + OffsetSize; + + var m = m_Mobiles[index]; + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddLabelCropped( + x + TextOffsetX, + y, + EntryWidth - TextOffsetX, + EntryHeight, + GetHueFor(m), + m.Deleted ? "(deleted)" : m.Name + ); + + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); + + if (m.NetState != null && !m.Deleted) + AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, i + 3); + } + } + + private static int GetHueFor(Mobile m) + { + switch (m.AccessLevel) + { + case AccessLevel.Owner: + case AccessLevel.Developer: + case AccessLevel.Administrator: return 0x516; + case AccessLevel.Seer: return 0x144; + case AccessLevel.GameMaster: return 0x21; + case AccessLevel.Counselor: return 0x2; + default: + { + return m.Kills >= 5 ? 0x21 : + m.Criminal ? 0x3B1 : 0x58; + } + } + } + + public override void OnResponse(NetState state, RelayInfo info) + { + var from = state.Mobile; + + switch (info.ButtonID) + { + case 0: // Closed + { + return; + } + case 1: // Previous + { + if (m_Page > 0) + from.SendGump(new WhoGump(from, m_Mobiles, m_Page - 1)); + + break; + } + case 2: // Next + { + if ((m_Page + 1) * EntryCount < m_Mobiles.Count) + from.SendGump(new WhoGump(from, m_Mobiles, m_Page + 1)); + + break; + } + default: + { + var index = m_Page * EntryCount + (info.ButtonID - 3); + + if (index >= 0 && index < m_Mobiles.Count) + { + var m = m_Mobiles[index]; + + if (m.Deleted) + { + from.SendMessage("That player has deleted their character."); + from.SendGump(new WhoGump(from, m_Mobiles, m_Page)); + } + else if (m.NetState == null) + { + from.SendMessage("That player is no longer online."); + from.SendGump(new WhoGump(from, m_Mobiles, m_Page)); + } + else if (m == from || !m.Hidden || from.AccessLevel >= m.AccessLevel || + m is PlayerMobile mobile && mobile.VisibilityList.Contains(@from)) + { + from.SendGump(new ClientGump(from, m.NetState)); + } + else + { + from.SendMessage("You cannot see them."); + from.SendGump(new WhoGump(from, m_Mobiles, m_Page)); + } + } + + break; + } + } + } + + private class InternalComparer : IComparer + { + public static readonly IComparer Instance = new InternalComparer(); + + public int Compare(Mobile x, Mobile y) + { + if (x == null || y == null) + throw new ArgumentException(); + + if (x.AccessLevel > y.AccessLevel) + return -1; + if (x.AccessLevel < y.AccessLevel) + return 1; + return Insensitive.Compare(x.Name, y.Name); + } + } + } +} diff --git a/Projects/UOContent/Gumps/YoungGumps.cs b/Projects/UOContent/Gumps/YoungGumps.cs index 2891b10c0..abb420f3d 100644 --- a/Projects/UOContent/Gumps/YoungGumps.cs +++ b/Projects/UOContent/Gumps/YoungGumps.cs @@ -1,90 +1,99 @@ -using Server.Network; -using Server.Accounting; - -namespace Server.Gumps -{ - public class YoungDungeonWarning : Gump - { - public YoungDungeonWarning() : base(150, 200) - { - AddBackground(0, 0, 250, 170, 0xA28); - - AddHtmlLocalized(20, 43, 215, 70, 1018030, true, true); // Warning: monsters may attack you on site down here in the dungeons! - - AddButton(70, 123, 0xFA5, 0xFA7, 0); - AddHtmlLocalized(105, 125, 100, 35, 1011036); // OKAY - } - } - - public class YoungDeathNotice : Gump - { - public YoungDeathNotice() : base(100, 15) - { - Closable = false; - - AddBackground(25, 10, 425, 444, 0x13BE); - - AddImageTiled(33, 20, 407, 425, 0xA40); - AddAlphaRegion(33, 20, 407, 425); - - AddHtmlLocalized(190, 24, 120, 20, 1046287, 0x7D00); // You have died. - - // As a ghost you cannot interact with the world. You cannot touch items nor can you use them. - AddHtmlLocalized(50, 50, 380, 40, 1046288, 0xFFFFFF); - // You can pass through doors as though they do not exist. However, you cannot pass through walls. - AddHtmlLocalized(50, 100, 380, 45, 1046289, 0xFFFFFF); - // Since you are a new player, any items you had on your person at the time of your death will be in your backpack upon resurrection. - AddHtmlLocalized(50, 140, 380, 60, 1046291, 0xFFFFFF); - // To be resurrected you must find a healer in town or wandering in the wilderness. Some powerful players may also be able to resurrect you. - AddHtmlLocalized(50, 204, 380, 65, 1046292, 0xFFFFFF); - // While you are still in young status, you will be transported to the nearest healer (along with your items) at the time of your death. - AddHtmlLocalized(50, 269, 380, 65, 1046293, 0xFFFFFF); - // To rejoin the world of the living simply walk near one of the NPC healers, and they will resurrect you as long as you are not marked as a criminal. - AddHtmlLocalized(50, 334, 380, 70, 1046294, 0xFFFFFF); - - AddButton(195, 410, 0xF8, 0xF9, 0); - } - } - - public class RenounceYoungGump : Gump - { - public RenounceYoungGump() : base(150, 50) - { - AddBackground(0, 0, 450, 400, 0xA28); - - AddHtmlLocalized(0, 30, 450, 35, 1013004); //
Renouncing 'Young Player' Status
- - /* As a 'Young' player, you are currently under a system of protection that prevents - * you from being attacked by other players and certain monsters.

- * - * If you choose to renounce your status as a 'Young' player, you will lose this protection. - * You will become vulnerable to other players, and many monsters that had only glared - * at you menacingly before will now attack you on sight!

- * - * Select OKAY now if you wish to renounce your status as a 'Young' player, otherwise - * press CANCEL. - */ - AddHtmlLocalized(30, 70, 390, 210, 1013005, true, true); - - AddButton(45, 298, 0xFA5, 0xFA7, 1); - AddHtmlLocalized(78, 300, 100, 35, 1011036); // OKAY - - AddButton(178, 298, 0xFA5, 0xFA7, 0); - AddHtmlLocalized(211, 300, 100, 35, 1011012); // CANCEL - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - Mobile from = sender.Mobile; - - if (info.ButtonID == 1) - { - if (from.Account is Account acc) acc.RemoveYoungStatus(502085); // You have chosen to renounce your `Young' player status. - } - else - { - from.SendLocalizedMessage(502086); // You have chosen not to renounce your `Young' player status. - } - } - } -} +using Server.Accounting; +using Server.Network; + +namespace Server.Gumps +{ + public class YoungDungeonWarning : Gump + { + public YoungDungeonWarning() : base(150, 200) + { + AddBackground(0, 0, 250, 170, 0xA28); + + AddHtmlLocalized( + 20, + 43, + 215, + 70, + 1018030, + true, + true + ); // Warning: monsters may attack you on site down here in the dungeons! + + AddButton(70, 123, 0xFA5, 0xFA7, 0); + AddHtmlLocalized(105, 125, 100, 35, 1011036); // OKAY + } + } + + public class YoungDeathNotice : Gump + { + public YoungDeathNotice() : base(100, 15) + { + Closable = false; + + AddBackground(25, 10, 425, 444, 0x13BE); + + AddImageTiled(33, 20, 407, 425, 0xA40); + AddAlphaRegion(33, 20, 407, 425); + + AddHtmlLocalized(190, 24, 120, 20, 1046287, 0x7D00); // You have died. + + // As a ghost you cannot interact with the world. You cannot touch items nor can you use them. + AddHtmlLocalized(50, 50, 380, 40, 1046288, 0xFFFFFF); + // You can pass through doors as though they do not exist. However, you cannot pass through walls. + AddHtmlLocalized(50, 100, 380, 45, 1046289, 0xFFFFFF); + // Since you are a new player, any items you had on your person at the time of your death will be in your backpack upon resurrection. + AddHtmlLocalized(50, 140, 380, 60, 1046291, 0xFFFFFF); + // To be resurrected you must find a healer in town or wandering in the wilderness. Some powerful players may also be able to resurrect you. + AddHtmlLocalized(50, 204, 380, 65, 1046292, 0xFFFFFF); + // While you are still in young status, you will be transported to the nearest healer (along with your items) at the time of your death. + AddHtmlLocalized(50, 269, 380, 65, 1046293, 0xFFFFFF); + // To rejoin the world of the living simply walk near one of the NPC healers, and they will resurrect you as long as you are not marked as a criminal. + AddHtmlLocalized(50, 334, 380, 70, 1046294, 0xFFFFFF); + + AddButton(195, 410, 0xF8, 0xF9, 0); + } + } + + public class RenounceYoungGump : Gump + { + public RenounceYoungGump() : base(150, 50) + { + AddBackground(0, 0, 450, 400, 0xA28); + + AddHtmlLocalized(0, 30, 450, 35, 1013004); //
Renouncing 'Young Player' Status
+ + /* As a 'Young' player, you are currently under a system of protection that prevents + * you from being attacked by other players and certain monsters.

+ * + * If you choose to renounce your status as a 'Young' player, you will lose this protection. + * You will become vulnerable to other players, and many monsters that had only glared + * at you menacingly before will now attack you on sight!

+ * + * Select OKAY now if you wish to renounce your status as a 'Young' player, otherwise + * press CANCEL. + */ + AddHtmlLocalized(30, 70, 390, 210, 1013005, true, true); + + AddButton(45, 298, 0xFA5, 0xFA7, 1); + AddHtmlLocalized(78, 300, 100, 35, 1011036); // OKAY + + AddButton(178, 298, 0xFA5, 0xFA7, 0); + AddHtmlLocalized(211, 300, 100, 35, 1011012); // CANCEL + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var from = sender.Mobile; + + if (info.ButtonID == 1) + { + if (from.Account is Account acc) + acc.RemoveYoungStatus(502085); // You have chosen to renounce your `Young' player status. + } + else + { + from.SendLocalizedMessage(502086); // You have chosen not to renounce your `Young' player status. + } + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Christmas/2010/Addons/FireFliesDeed.cs b/Projects/UOContent/Holiday Stuff/Christmas/2010/Addons/FireFliesDeed.cs index d73ea708f..94d5e228a 100644 --- a/Projects/UOContent/Holiday Stuff/Christmas/2010/Addons/FireFliesDeed.cs +++ b/Projects/UOContent/Holiday Stuff/Christmas/2010/Addons/FireFliesDeed.cs @@ -1,283 +1,284 @@ -using System.Linq; -using Server.Gumps; -using Server.Multis; -using Server.Network; -using Server.Targeting; - -namespace Server.Items -{ - public class Fireflies : Item, IAddon - { - [Constructible] - public Fireflies(int itemID = 0x1596) - : base(itemID) - { - LootType = LootType.Blessed; - Movable = false; - } - - public Fireflies(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1150061; - - public bool FacingSouth - { - get - { - if (ItemID == 0x2336) - return true; - - return false; - } - } - - public Item Deed - { - get - { - FirefliesDeed deed = new FirefliesDeed(); - - return deed; - } - } - - public bool CouldFit(IPoint3D p, Map map) - { - if (map?.CanFit(p.X, p.Y, p.Z, ItemData.Height) != true) - return false; - - if (FacingSouth) - return BaseAddon.IsWall(p.X, p.Y - 1, p.Z, map); // north wall - return BaseAddon.IsWall(p.X - 1, p.Y, p.Z, map); // west wall - } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(Location, 3)) - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (house?.IsOwner(from) == true) - { - from.CloseGump(); - from.SendGump(new RewardDemolitionGump(this, 1049783)); // Do you wish to re-deed this decoration? - } - else - { - from.SendLocalizedMessage( - 1049784); // You can only re-deed this decoration if you are the house owner or originally placed the decoration. - } - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class FirefliesDeed : Item - { - [Constructible] - public FirefliesDeed() - : base(0x14F0) - { - LootType = LootType.Blessed; - Weight = 1.0; - } - - public FirefliesDeed(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1150061; - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - BaseHouse house = BaseHouse.FindHouseAt(from); - - if (house?.IsOwner(from) == true) - { - from.CloseGump(); - - if (!from.SendGump(new FacingGump(this, from))) - from.SendLocalizedMessage(1150062); // You fail to re-deed the holiday fireflies. - } - else - { - from.SendLocalizedMessage(502092); // You must be in your house to do this. - } - } - else - { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - private class FacingGump : Gump - { - private readonly FirefliesDeed m_Deed; - private readonly Mobile m_Placer; - - public FacingGump(FirefliesDeed deed, Mobile player) - : base(150, 50) - { - m_Deed = deed; - m_Placer = player; - - Closable = true; - Disposable = true; - Draggable = true; - Resizable = false; - - AddPage(0); - - AddBackground(0, 0, 300, 150, 0xA28); - - AddItem(90, 30, 0x2332); - AddItem(180, 30, 0x2336); - - AddButton(50, 35, 0x868, 0x869, (int)Buttons.East); - AddButton(145, 35, 0x868, 0x869, (int)Buttons.South); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - int m_ItemID; - - switch (info.ButtonID) - { - case (int)Buttons.East: - m_ItemID = 0x2332; - break; - case (int)Buttons.South: - m_ItemID = 0x2336; - break; - default: return; - } - - m_Placer.Target = new InternalTarget(m_Deed, m_ItemID); - } - - private enum Buttons - { - Cancel, - South, - East - } - } - - private class InternalTarget : Target - { - private readonly FirefliesDeed m_FirefliesDeed; - private readonly int m_ItemID; - - public InternalTarget(FirefliesDeed m_Deed, int itemid) - : base(-1, true, TargetFlags.None) - { - m_FirefliesDeed = m_Deed; - m_ItemID = itemid; - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_FirefliesDeed?.Deleted != false) - return; - - if (m_FirefliesDeed.IsChildOf(from.Backpack)) - { - BaseHouse house = BaseHouse.FindHouseAt(from); - - if (house?.IsOwner(from) == true) - { - IPoint3D p = targeted as IPoint3D; - Map map = from.Map; - - if (p == null || map == null || map == Map.Internal) - return; - - Point3D p3d = new Point3D(p); - ItemData id = TileData.ItemTable[m_ItemID & TileData.MaxItemValue]; - - if (map.CanFit(p3d, id.Height)) - { - house = BaseHouse.FindHouseAt(p3d, map, id.Height); - - if (house?.IsOwner(from) == true) - { - bool north = BaseAddon.IsWall(p3d.X, p3d.Y - 1, p3d.Z, map); - bool west = BaseAddon.IsWall(p3d.X - 1, p3d.Y, p3d.Z, map); - - bool isclear = !Map.Malas.GetItemsInRange(p3d, 0).OfType().Any(); - - if (((m_ItemID == 0x2336 && north) || (m_ItemID == 0x2332 && west)) && isclear) - { - Fireflies flies = new Fireflies(m_ItemID); - - house.Addons.Add(flies); - - flies.MoveToWorld(p3d, from.Map); - - m_FirefliesDeed.Delete(); - } - else - { - from.SendLocalizedMessage(1150065); // Holiday fireflies must be placed next to a wall. - } - } - else - { - from.SendLocalizedMessage(1042036); // That location is not in your house. - } - } - else - { - from.SendLocalizedMessage(500269); // You cannot build that there. - } - } - else - { - from.SendLocalizedMessage(502092); // You must be in your house to do this. - } - } - else - { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. - } - } - } - } -} +using System.Linq; +using Server.Gumps; +using Server.Multis; +using Server.Network; +using Server.Targeting; + +namespace Server.Items +{ + public class Fireflies : Item, IAddon + { + [Constructible] + public Fireflies(int itemID = 0x1596) + : base(itemID) + { + LootType = LootType.Blessed; + Movable = false; + } + + public Fireflies(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1150061; + + public bool FacingSouth + { + get + { + if (ItemID == 0x2336) + return true; + + return false; + } + } + + public Item Deed + { + get + { + var deed = new FirefliesDeed(); + + return deed; + } + } + + public bool CouldFit(IPoint3D p, Map map) + { + if (map?.CanFit(p.X, p.Y, p.Z, ItemData.Height) != true) + return false; + + if (FacingSouth) + return BaseAddon.IsWall(p.X, p.Y - 1, p.Z, map); // north wall + return BaseAddon.IsWall(p.X - 1, p.Y, p.Z, map); // west wall + } + + public override void OnDoubleClick(Mobile from) + { + if (from.InRange(Location, 3)) + { + var house = BaseHouse.FindHouseAt(this); + + if (house?.IsOwner(from) == true) + { + from.CloseGump(); + from.SendGump(new RewardDemolitionGump(this, 1049783)); // Do you wish to re-deed this decoration? + } + else + { + from.SendLocalizedMessage( + 1049784 + ); // You can only re-deed this decoration if you are the house owner or originally placed the decoration. + } + } + else + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + } + + 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(); + } + } + + public class FirefliesDeed : Item + { + [Constructible] + public FirefliesDeed() + : base(0x14F0) + { + LootType = LootType.Blessed; + Weight = 1.0; + } + + public FirefliesDeed(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1150061; + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + var house = BaseHouse.FindHouseAt(from); + + if (house?.IsOwner(from) == true) + { + from.CloseGump(); + + if (!from.SendGump(new FacingGump(this, from))) + from.SendLocalizedMessage(1150062); // You fail to re-deed the holiday fireflies. + } + else + { + from.SendLocalizedMessage(502092); // You must be in your house to do this. + } + } + else + { + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. + } + } + + 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(); + } + + private class FacingGump : Gump + { + private readonly FirefliesDeed m_Deed; + private readonly Mobile m_Placer; + + public FacingGump(FirefliesDeed deed, Mobile player) + : base(150, 50) + { + m_Deed = deed; + m_Placer = player; + + Closable = true; + Disposable = true; + Draggable = true; + Resizable = false; + + AddPage(0); + + AddBackground(0, 0, 300, 150, 0xA28); + + AddItem(90, 30, 0x2332); + AddItem(180, 30, 0x2336); + + AddButton(50, 35, 0x868, 0x869, (int)Buttons.East); + AddButton(145, 35, 0x868, 0x869, (int)Buttons.South); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + int m_ItemID; + + switch (info.ButtonID) + { + case (int)Buttons.East: + m_ItemID = 0x2332; + break; + case (int)Buttons.South: + m_ItemID = 0x2336; + break; + default: return; + } + + m_Placer.Target = new InternalTarget(m_Deed, m_ItemID); + } + + private enum Buttons + { + Cancel, + South, + East + } + } + + private class InternalTarget : Target + { + private readonly FirefliesDeed m_FirefliesDeed; + private readonly int m_ItemID; + + public InternalTarget(FirefliesDeed m_Deed, int itemid) + : base(-1, true, TargetFlags.None) + { + m_FirefliesDeed = m_Deed; + m_ItemID = itemid; + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_FirefliesDeed?.Deleted != false) + return; + + if (m_FirefliesDeed.IsChildOf(from.Backpack)) + { + var house = BaseHouse.FindHouseAt(from); + + if (house?.IsOwner(from) == true) + { + var p = targeted as IPoint3D; + var map = from.Map; + + if (p == null || map == null || map == Map.Internal) + return; + + var p3d = new Point3D(p); + var id = TileData.ItemTable[m_ItemID & TileData.MaxItemValue]; + + if (map.CanFit(p3d, id.Height)) + { + house = BaseHouse.FindHouseAt(p3d, map, id.Height); + + if (house?.IsOwner(from) == true) + { + var north = BaseAddon.IsWall(p3d.X, p3d.Y - 1, p3d.Z, map); + var west = BaseAddon.IsWall(p3d.X - 1, p3d.Y, p3d.Z, map); + + var isclear = !Map.Malas.GetItemsInRange(p3d, 0).OfType().Any(); + + if ((m_ItemID == 0x2336 && north || m_ItemID == 0x2332 && west) && isclear) + { + var flies = new Fireflies(m_ItemID); + + house.Addons.Add(flies); + + flies.MoveToWorld(p3d, from.Map); + + m_FirefliesDeed.Delete(); + } + else + { + from.SendLocalizedMessage(1150065); // Holiday fireflies must be placed next to a wall. + } + } + else + { + from.SendLocalizedMessage(1042036); // That location is not in your house. + } + } + else + { + from.SendLocalizedMessage(500269); // You cannot build that there. + } + } + else + { + from.SendLocalizedMessage(502092); // You must be in your house to do this. + } + } + else + { + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. + } + } + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Christmas/2010/Items/AngelDecoration.cs b/Projects/UOContent/Holiday Stuff/Christmas/2010/Items/AngelDecoration.cs index 407cec976..42d9563ac 100644 --- a/Projects/UOContent/Holiday Stuff/Christmas/2010/Items/AngelDecoration.cs +++ b/Projects/UOContent/Holiday Stuff/Christmas/2010/Items/AngelDecoration.cs @@ -1,33 +1,33 @@ -namespace Server.Items.Holiday -{ - [TypeAlias("Server.Items.AngelDecoration")] - [Flippable(0x46FA, 0x46FB)] - public class AngelDecoration : Item - { - public AngelDecoration() : base(0x46FA) - { - LootType = LootType.Blessed; - - Weight = 30; - } - - public AngelDecoration(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items.Holiday +{ + [TypeAlias("Server.Items.AngelDecoration")] + [Flippable(0x46FA, 0x46FB)] + public class AngelDecoration : Item + { + public AngelDecoration() : base(0x46FA) + { + LootType = LootType.Blessed; + + Weight = 30; + } + + public AngelDecoration(Serial serial) + : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Christmas/2010/Items/RockingHorse.cs b/Projects/UOContent/Holiday Stuff/Christmas/2010/Items/RockingHorse.cs index f4292899c..74720ad6f 100644 --- a/Projects/UOContent/Holiday Stuff/Christmas/2010/Items/RockingHorse.cs +++ b/Projects/UOContent/Holiday Stuff/Christmas/2010/Items/RockingHorse.cs @@ -1,33 +1,33 @@ -namespace Server.Items.Holiday -{ - [TypeAlias("Server.Items.RockingHorse")] - [Flippable(0x4214, 0x4215)] - public class RockingHorse : Item - { - public RockingHorse() : base(0x4214) - { - LootType = LootType.Blessed; - - Weight = 30; - } - - public RockingHorse(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items.Holiday +{ + [TypeAlias("Server.Items.RockingHorse")] + [Flippable(0x4214, 0x4215)] + public class RockingHorse : Item + { + public RockingHorse() : base(0x4214) + { + LootType = LootType.Blessed; + + Weight = 30; + } + + public RockingHorse(Serial serial) + : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Easter/2011/Items/DragonEasterEgg.cs b/Projects/UOContent/Holiday Stuff/Easter/2011/Items/DragonEasterEgg.cs index ca127d9c0..5c96dc7ec 100644 --- a/Projects/UOContent/Holiday Stuff/Easter/2011/Items/DragonEasterEgg.cs +++ b/Projects/UOContent/Holiday Stuff/Easter/2011/Items/DragonEasterEgg.cs @@ -1,42 +1,42 @@ -namespace Server.Items -{ - public class DragonEasterEgg : Item, IDyable - { - [Constructible] - public DragonEasterEgg() - : base(0x47E6) - { - } - - public DragonEasterEgg(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1097278; - - public bool Dye(Mobile from, DyeTub sender) - { - if (Deleted || !sender.AllowDyables) - return false; - - Hue = sender.DyedHue; - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class DragonEasterEgg : Item, IDyable + { + [Constructible] + public DragonEasterEgg() + : base(0x47E6) + { + } + + public DragonEasterEgg(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1097278; + + public bool Dye(Mobile from, DyeTub sender) + { + if (Deleted || !sender.AllowDyables) + return false; + + Hue = sender.DyedHue; + + return true; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2006/Engines/TrickOrTreat.cs b/Projects/UOContent/Holiday Stuff/Halloween/2006/Engines/TrickOrTreat.cs index 0e5fff56d..d473c19dc 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2006/Engines/TrickOrTreat.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2006/Engines/TrickOrTreat.cs @@ -1,319 +1,322 @@ -using System; -using System.Collections.Generic; -using Server.Events.Halloween; -using Server.Items; -using Server.Mobiles; -using Server.Targeting; - -namespace Server.Engines.Events -{ - public static class TrickOrTreat - { - public static TimeSpan OneSecond = TimeSpan.FromSeconds(1); - - public static void Initialize() - { - DateTime now = DateTime.UtcNow; - - if (DateTime.UtcNow >= HolidaySettings.StartHalloween && DateTime.UtcNow <= HolidaySettings.FinishHalloween) - EventSink.Speech += EventSink_Speech; - } - - private static void EventSink_Speech(SpeechEventArgs e) - { - if (Insensitive.Contains(e.Speech, "trick or treat")) - { - e.Mobile.Target = new TrickOrTreatTarget(); - - e.Mobile.SendLocalizedMessage(1076764); /* Pick someone to Trick or Treat. */ - } - } - - public static void Bleeding(Mobile m_From) - { - if (CheckMobile(m_From)) - if (m_From.Location != Point3D.Zero) - { - int amount = Utility.RandomMinMax(3, 7); - - for (int i = 0; i < amount; i++) - new Blood(Utility.RandomMinMax(0x122C, 0x122F)).MoveToWorld( - RandomPointOneAway(m_From.X, m_From.Y, m_From.Z, m_From.Map), m_From.Map); - } - } - - public static void RemoveHueMod(Mobile target) - { - if (target?.Deleted == false) - target.SolidHueOverride = -1; - } - - public static void SolidHueMobile(Mobile target) - { - if (CheckMobile(target)) - { - target.SolidHueOverride = Utility.RandomMinMax(2501, 2644); - - Timer.DelayCall(TimeSpan.FromSeconds(10), RemoveHueMod, target); - } - } - - public static void MakeTwin(Mobile m_From) - { - List m_Items = new List(); - - if (CheckMobile(m_From)) - { - Mobile twin = new NaughtyTwin(m_From); - - if (twin.Deleted) - return; - - foreach (Item item in m_From.Items) - if (item.Layer != Layer.Backpack && item.Layer != Layer.Mount && item.Layer != Layer.Bank) - m_Items.Add(item); - - if (m_Items.Count > 0) - { - for (int i = 0; i < m_Items.Count; i++) /* dupe exploits start out like this ... */ - twin.AddItem(Mobile.LiftItemDupe(m_Items[i], 1)); - - foreach (Item item in twin.Items) /* ... and end like this */ - if (item.Layer != Layer.Backpack && item.Layer != Layer.Mount && item.Layer != Layer.Bank) - item.Movable = false; - } - - twin.Hue = m_From.Hue; - twin.BodyValue = m_From.BodyValue; - twin.Kills = m_From.Kills; - - Point3D point = RandomPointOneAway(m_From.X, m_From.Y, m_From.Z, m_From.Map); - - twin.MoveToWorld(m_From.Map.CanSpawnMobile(point) ? point : m_From.Location, m_From.Map); - - Timer.DelayCall(TimeSpan.FromSeconds(5), DeleteTwin, twin); - } - } - - public static void DeleteTwin(Mobile m_Twin) - { - if (CheckMobile(m_Twin)) m_Twin.Delete(); - } - - public static Point3D RandomPointOneAway(int x, int y, int z, Map map) - { - Point3D loc = new Point3D(x + Utility.Random(-1, 3), y + Utility.Random(-1, 3), 0); - - loc.Z = map.CanFit(loc, 0) ? map.GetAverageZ(loc.X, loc.Y) : z; - - return loc; - } - - public static bool CheckMobile(Mobile mobile) => mobile?.Map != null && !mobile.Deleted && mobile.Alive && mobile.Map != Map.Internal; - - private class TrickOrTreatTarget : Target - { - public TrickOrTreatTarget() - : base(15, false, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object targ) - { - if (targ == null || !CheckMobile(from)) - return; - - if (!(targ is Mobile)) - { - from.SendLocalizedMessage(1076781); /* There is little chance of getting candy from that! */ - return; - } - - BaseVendor begged = targ as BaseVendor; - - if (begged?.Deleted != false) - { - from.SendLocalizedMessage(1076765); /* That doesn't look friendly. */ - return; - } - - DateTime now = DateTime.UtcNow; - - if (CheckMobile(begged)) - { - if (begged.NextTrickOrTreat > now) - { - from.SendLocalizedMessage(1076767); /* That doesn't appear to have any more candy. */ - return; - } - - begged.NextTrickOrTreat = now + TimeSpan.FromMinutes(Utility.RandomMinMax(5, 10)); - - if (from.Backpack?.Deleted != false) - return; - - if (Utility.RandomDouble() > .10) - { - begged.Say( - Utility.Random(3) switch - { - 0 => 1076768, // Oooooh, aren't you cute! - 1 => 1076779, // All right...This better not spoil your dinner! - _ => 1076778 // Here you go! Enjoy! - } - ); - - if (Utility.RandomDouble() <= .01 && from.Skills.Begging.Value >= 100) - { - from.AddToBackpack(HolidaySettings.RandomGMBeggerItem); - - from.SendLocalizedMessage(1076777); /* You receive a special treat! */ - } - else - { - from.AddToBackpack(HolidaySettings.RandomTreat); - - from.SendLocalizedMessage(1076769); /* You receive some candy. */ - } - } - else - { - begged.Say(1076770); /* TRICK! */ - - int action = Utility.Random(4); - - if (action == 0) - Timer.DelayCall(OneSecond, OneSecond, 10, Bleeding, from); - else if (action == 1) - Timer.DelayCall(TimeSpan.FromSeconds(2), SolidHueMobile, from); - else - Timer.DelayCall(TimeSpan.FromSeconds(2), MakeTwin, from); - } - } - } - } - } - - public class NaughtyTwin : BaseCreature - { - private static readonly Point3D[] Felucca_Locations = - { - new Point3D(4467, 1283, 5), // Moonglow - new Point3D(1336, 1997, 5), // Britain - new Point3D(1499, 3771, 5), // Jhelom - new Point3D(771, 752, 5), // Yew - new Point3D(2701, 692, 5), // Minoc - new Point3D(1828, 2948, -20), // Trinsic - new Point3D(643, 2067, 5), // Skara Brae - new Point3D(3563, 2139, Map.Trammel.GetAverageZ(3563, 2139)) // (New) Magincia - }; - - private static readonly Point3D[] Malas_Locations = - { - new Point3D(1015, 527, -65), // Luna - new Point3D(1997, 1386, -85) // Umbra - }; - - private static readonly Point3D[] Ilshenar_Locations = - { - new Point3D(1215, 467, -13), // Compassion - new Point3D(722, 1366, -60), // Honesty - new Point3D(744, 724, -28), // Honor - new Point3D(281, 1016, 0), // Humility - new Point3D(987, 1011, -32), // Justice - new Point3D(1174, 1286, -30), // Sacrifice - new Point3D(1532, 1340, -3), // Spirituality - new Point3D(528, 216, -45), // Valor - new Point3D(1721, 218, 96) // Chaos - }; - - private static readonly Point3D[] Tokuno_Locations = - { - new Point3D(1169, 998, 41), // Isamu-Jima - new Point3D(802, 1204, 25), // Makoto-Jima - new Point3D(270, 628, 15) // Homare-Jima - }; - - private readonly Mobile m_From; - - public NaughtyTwin(Mobile from) - : base(AIType.AI_Melee, FightMode.None, 10, 1, 0.2, 0.4) - { - if (TrickOrTreat.CheckMobile(from)) - { - Body = from.Body; - - m_From = from; - Name = $"{from.Name}\'s Naughty Twin"; - - Timer.DelayCall(TrickOrTreat.OneSecond, StealCandyOrGate, m_From); - } - } - - public NaughtyTwin(Serial serial) - : base(serial) - { - } - - public override void OnThink() - { - if (m_From?.Deleted != false) - Delete(); - } - - public static Item FindCandyTypes(Mobile target) - { - Type[] types = - { typeof(WrappedCandy), typeof(Lollipops), typeof(NougatSwirl), typeof(Taffy), typeof(JellyBeans) }; - - if (TrickOrTreat.CheckMobile(target)) - return target.Backpack.FindItemByType(types); - - return null; - } - - public static void StealCandyOrGate(Mobile target) - { - if (TrickOrTreat.CheckMobile(target)) - { - if (Utility.RandomBool()) - { - Item item = FindCandyTypes(target); - - target.SendLocalizedMessage(1113967); /* Your naughty twin steals some of your candy. */ - - if (item?.Deleted == false) - item.Delete(); - } - else - { - target.SendLocalizedMessage(1113972); /* Your naughty twin teleports you away with a naughty laugh! */ - target.MoveToWorld(RandomMoongate(target), target.Map); - } - } - } - - public static Point3D RandomMoongate(Mobile target) - { - return target.Map.MapID switch - { - 2 => Ilshenar_Locations.RandomElement(), - 3 => Malas_Locations.RandomElement(), - 4 => Tokuno_Locations.RandomElement(), - _ => Felucca_Locations.RandomElement() - }; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} +using System; +using System.Collections.Generic; +using Server.Events.Halloween; +using Server.Items; +using Server.Mobiles; +using Server.Targeting; + +namespace Server.Engines.Events +{ + public static class TrickOrTreat + { + public static TimeSpan OneSecond = TimeSpan.FromSeconds(1); + + public static void Initialize() + { + var now = DateTime.UtcNow; + + if (DateTime.UtcNow >= HolidaySettings.StartHalloween && DateTime.UtcNow <= HolidaySettings.FinishHalloween) + EventSink.Speech += EventSink_Speech; + } + + private static void EventSink_Speech(SpeechEventArgs e) + { + if (Insensitive.Contains(e.Speech, "trick or treat")) + { + e.Mobile.Target = new TrickOrTreatTarget(); + + e.Mobile.SendLocalizedMessage(1076764); /* Pick someone to Trick or Treat. */ + } + } + + public static void Bleeding(Mobile m_From) + { + if (CheckMobile(m_From)) + if (m_From.Location != Point3D.Zero) + { + var amount = Utility.RandomMinMax(3, 7); + + for (var i = 0; i < amount; i++) + new Blood(Utility.RandomMinMax(0x122C, 0x122F)).MoveToWorld( + RandomPointOneAway(m_From.X, m_From.Y, m_From.Z, m_From.Map), + m_From.Map + ); + } + } + + public static void RemoveHueMod(Mobile target) + { + if (target?.Deleted == false) + target.SolidHueOverride = -1; + } + + public static void SolidHueMobile(Mobile target) + { + if (CheckMobile(target)) + { + target.SolidHueOverride = Utility.RandomMinMax(2501, 2644); + + Timer.DelayCall(TimeSpan.FromSeconds(10), RemoveHueMod, target); + } + } + + public static void MakeTwin(Mobile m_From) + { + var m_Items = new List(); + + if (CheckMobile(m_From)) + { + Mobile twin = new NaughtyTwin(m_From); + + if (twin.Deleted) + return; + + foreach (var item in m_From.Items) + if (item.Layer != Layer.Backpack && item.Layer != Layer.Mount && item.Layer != Layer.Bank) + m_Items.Add(item); + + if (m_Items.Count > 0) + { + for (var i = 0; i < m_Items.Count; i++) /* dupe exploits start out like this ... */ + twin.AddItem(Mobile.LiftItemDupe(m_Items[i], 1)); + + foreach (var item in twin.Items) /* ... and end like this */ + if (item.Layer != Layer.Backpack && item.Layer != Layer.Mount && item.Layer != Layer.Bank) + item.Movable = false; + } + + twin.Hue = m_From.Hue; + twin.BodyValue = m_From.BodyValue; + twin.Kills = m_From.Kills; + + var point = RandomPointOneAway(m_From.X, m_From.Y, m_From.Z, m_From.Map); + + twin.MoveToWorld(m_From.Map.CanSpawnMobile(point) ? point : m_From.Location, m_From.Map); + + Timer.DelayCall(TimeSpan.FromSeconds(5), DeleteTwin, twin); + } + } + + public static void DeleteTwin(Mobile m_Twin) + { + if (CheckMobile(m_Twin)) m_Twin.Delete(); + } + + public static Point3D RandomPointOneAway(int x, int y, int z, Map map) + { + var loc = new Point3D(x + Utility.Random(-1, 3), y + Utility.Random(-1, 3), 0); + + loc.Z = map.CanFit(loc, 0) ? map.GetAverageZ(loc.X, loc.Y) : z; + + return loc; + } + + public static bool CheckMobile(Mobile mobile) => + mobile?.Map != null && !mobile.Deleted && mobile.Alive && mobile.Map != Map.Internal; + + private class TrickOrTreatTarget : Target + { + public TrickOrTreatTarget() + : base(15, false, TargetFlags.None) + { + } + + protected override void OnTarget(Mobile from, object targ) + { + if (targ == null || !CheckMobile(from)) + return; + + if (!(targ is Mobile)) + { + from.SendLocalizedMessage(1076781); /* There is little chance of getting candy from that! */ + return; + } + + var begged = targ as BaseVendor; + + if (begged?.Deleted != false) + { + from.SendLocalizedMessage(1076765); /* That doesn't look friendly. */ + return; + } + + var now = DateTime.UtcNow; + + if (CheckMobile(begged)) + { + if (begged.NextTrickOrTreat > now) + { + from.SendLocalizedMessage(1076767); /* That doesn't appear to have any more candy. */ + return; + } + + begged.NextTrickOrTreat = now + TimeSpan.FromMinutes(Utility.RandomMinMax(5, 10)); + + if (from.Backpack?.Deleted != false) + return; + + if (Utility.RandomDouble() > .10) + { + begged.Say( + Utility.Random(3) switch + { + 0 => 1076768, // Oooooh, aren't you cute! + 1 => 1076779, // All right...This better not spoil your dinner! + _ => 1076778 // Here you go! Enjoy! + } + ); + + if (Utility.RandomDouble() <= .01 && from.Skills.Begging.Value >= 100) + { + from.AddToBackpack(HolidaySettings.RandomGMBeggerItem); + + from.SendLocalizedMessage(1076777); /* You receive a special treat! */ + } + else + { + from.AddToBackpack(HolidaySettings.RandomTreat); + + from.SendLocalizedMessage(1076769); /* You receive some candy. */ + } + } + else + { + begged.Say(1076770); /* TRICK! */ + + var action = Utility.Random(4); + + if (action == 0) + Timer.DelayCall(OneSecond, OneSecond, 10, Bleeding, from); + else if (action == 1) + Timer.DelayCall(TimeSpan.FromSeconds(2), SolidHueMobile, from); + else + Timer.DelayCall(TimeSpan.FromSeconds(2), MakeTwin, from); + } + } + } + } + } + + public class NaughtyTwin : BaseCreature + { + private static readonly Point3D[] Felucca_Locations = + { + new Point3D(4467, 1283, 5), // Moonglow + new Point3D(1336, 1997, 5), // Britain + new Point3D(1499, 3771, 5), // Jhelom + new Point3D(771, 752, 5), // Yew + new Point3D(2701, 692, 5), // Minoc + new Point3D(1828, 2948, -20), // Trinsic + new Point3D(643, 2067, 5), // Skara Brae + new Point3D(3563, 2139, Map.Trammel.GetAverageZ(3563, 2139)) // (New) Magincia + }; + + private static readonly Point3D[] Malas_Locations = + { + new Point3D(1015, 527, -65), // Luna + new Point3D(1997, 1386, -85) // Umbra + }; + + private static readonly Point3D[] Ilshenar_Locations = + { + new Point3D(1215, 467, -13), // Compassion + new Point3D(722, 1366, -60), // Honesty + new Point3D(744, 724, -28), // Honor + new Point3D(281, 1016, 0), // Humility + new Point3D(987, 1011, -32), // Justice + new Point3D(1174, 1286, -30), // Sacrifice + new Point3D(1532, 1340, -3), // Spirituality + new Point3D(528, 216, -45), // Valor + new Point3D(1721, 218, 96) // Chaos + }; + + private static readonly Point3D[] Tokuno_Locations = + { + new Point3D(1169, 998, 41), // Isamu-Jima + new Point3D(802, 1204, 25), // Makoto-Jima + new Point3D(270, 628, 15) // Homare-Jima + }; + + private readonly Mobile m_From; + + public NaughtyTwin(Mobile from) + : base(AIType.AI_Melee, FightMode.None, 10, 1, 0.2, 0.4) + { + if (TrickOrTreat.CheckMobile(from)) + { + Body = from.Body; + + m_From = from; + Name = $"{from.Name}\'s Naughty Twin"; + + Timer.DelayCall(TrickOrTreat.OneSecond, StealCandyOrGate, m_From); + } + } + + public NaughtyTwin(Serial serial) + : base(serial) + { + } + + public override void OnThink() + { + if (m_From?.Deleted != false) + Delete(); + } + + public static Item FindCandyTypes(Mobile target) + { + Type[] types = + { typeof(WrappedCandy), typeof(Lollipops), typeof(NougatSwirl), typeof(Taffy), typeof(JellyBeans) }; + + if (TrickOrTreat.CheckMobile(target)) + return target.Backpack.FindItemByType(types); + + return null; + } + + public static void StealCandyOrGate(Mobile target) + { + if (TrickOrTreat.CheckMobile(target)) + { + if (Utility.RandomBool()) + { + var item = FindCandyTypes(target); + + target.SendLocalizedMessage(1113967); /* Your naughty twin steals some of your candy. */ + + if (item?.Deleted == false) + item.Delete(); + } + else + { + target.SendLocalizedMessage(1113972); /* Your naughty twin teleports you away with a naughty laugh! */ + target.MoveToWorld(RandomMoongate(target), target.Map); + } + } + } + + public static Point3D RandomMoongate(Mobile target) + { + return target.Map.MapID switch + { + 2 => Ilshenar_Locations.RandomElement(), + 3 => Malas_Locations.RandomElement(), + 4 => Tokuno_Locations.RandomElement(), + _ => Felucca_Locations.RandomElement() + }; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2006/Items/HalloweenPumpkin.cs b/Projects/UOContent/Holiday Stuff/Halloween/2006/Items/HalloweenPumpkin.cs index 9f405edee..45b04e151 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2006/Items/HalloweenPumpkin.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2006/Items/HalloweenPumpkin.cs @@ -1,96 +1,96 @@ -using Server.Mobiles; - -namespace Server.Items -{ - public class HalloweenPumpkin : Item - { - private static readonly string[] m_Staff = - { - "Ryan", "Mark", "Eos", "Athena", "Xavier", "Krrios", "Zippy" - }; - - [Constructible] - public HalloweenPumpkin() - { - Weight = Utility.RandomMinMax(3, 20); - ItemID = Utility.RandomDouble() <= .02 - ? Utility.RandomList(0x4694, 0x4698) - : Utility.RandomList(0xc6a, 0xc6b, 0xc6c); - } - - public HalloweenPumpkin(Serial serial) - : base(serial) - { - } - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 2)) - return; - - bool douse = false; - - switch (ItemID) - { - case 0x4694: - ItemID = 0x4691; - break; - case 0x4691: - ItemID = 0x4694; - douse = true; - break; - case 0x4698: - ItemID = 0x4695; - break; - case 0x4695: - ItemID = 0x4698; - douse = true; - break; - default: return; - } - - from.SendLocalizedMessage(douse ? 1113988 : 1113987); // You extinguish/light the Jack-O-Lantern - Effects.PlaySound(GetWorldLocation(), Map, douse ? 0x3be : 0x47); - } - - private void AssignRandomName() - { - Name = $"{m_Staff.RandomElement()}'s Jack-O-Lantern"; - } - - public override bool OnDragLift(Mobile from) - { - if (Name == null && (ItemID == 0x4694 || ItemID == 0x4691 || ItemID == 0x4698 || ItemID == 0x4695)) - { - if (Utility.RandomBool()) - { - new PumpkinHead().MoveToWorld(GetWorldLocation(), Map); - - Delete(); - return false; - } - - AssignRandomName(); - } - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version == 0 && Name == null && ItemID == 0x4698) - AssignRandomName(); - } - } -} +using Server.Mobiles; + +namespace Server.Items +{ + public class HalloweenPumpkin : Item + { + private static readonly string[] m_Staff = + { + "Ryan", "Mark", "Eos", "Athena", "Xavier", "Krrios", "Zippy" + }; + + [Constructible] + public HalloweenPumpkin() + { + Weight = Utility.RandomMinMax(3, 20); + ItemID = Utility.RandomDouble() <= .02 + ? Utility.RandomList(0x4694, 0x4698) + : Utility.RandomList(0xc6a, 0xc6b, 0xc6c); + } + + public HalloweenPumpkin(Serial serial) + : base(serial) + { + } + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 2)) + return; + + var douse = false; + + switch (ItemID) + { + case 0x4694: + ItemID = 0x4691; + break; + case 0x4691: + ItemID = 0x4694; + douse = true; + break; + case 0x4698: + ItemID = 0x4695; + break; + case 0x4695: + ItemID = 0x4698; + douse = true; + break; + default: return; + } + + from.SendLocalizedMessage(douse ? 1113988 : 1113987); // You extinguish/light the Jack-O-Lantern + Effects.PlaySound(GetWorldLocation(), Map, douse ? 0x3be : 0x47); + } + + private void AssignRandomName() + { + Name = $"{m_Staff.RandomElement()}'s Jack-O-Lantern"; + } + + public override bool OnDragLift(Mobile from) + { + if (Name == null && (ItemID == 0x4694 || ItemID == 0x4691 || ItemID == 0x4698 || ItemID == 0x4695)) + { + if (Utility.RandomBool()) + { + new PumpkinHead().MoveToWorld(GetWorldLocation(), Map); + + Delete(); + return false; + } + + AssignRandomName(); + } + + return true; + } + + 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 && Name == null && ItemID == 0x4698) + AssignRandomName(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2006/Items/PumpkinScarecrow.cs b/Projects/UOContent/Holiday Stuff/Halloween/2006/Items/PumpkinScarecrow.cs index 845a13cbc..b706cc945 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2006/Items/PumpkinScarecrow.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2006/Items/PumpkinScarecrow.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class PumpkinScarecrow : Item - { - [Constructible] - public PumpkinScarecrow() - : base(Utility.RandomBool() ? 0x469B : 0x469C) - { - } - - public PumpkinScarecrow(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1096947; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PumpkinScarecrow : Item + { + [Constructible] + public PumpkinScarecrow() + : base(Utility.RandomBool() ? 0x469B : 0x469C) + { + } + + public PumpkinScarecrow(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1096947; + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2006/Items/RuinedTapestry.cs b/Projects/UOContent/Holiday Stuff/Halloween/2006/Items/RuinedTapestry.cs index 49f0ff941..e253e368c 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2006/Items/RuinedTapestry.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2006/Items/RuinedTapestry.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class RuinedTapestry : Item - { - [Constructible] - public RuinedTapestry() - : base(Utility.RandomBool() ? 0x4699 : 0x469A) - { - } - - public RuinedTapestry(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "Ruined Tapestry "; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class RuinedTapestry : Item + { + [Constructible] + public RuinedTapestry() + : base(Utility.RandomBool() ? 0x4699 : 0x469A) + { + } + + public RuinedTapestry(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "Ruined Tapestry "; + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2006/Items/TwilightLantern.cs b/Projects/UOContent/Holiday Stuff/Halloween/2006/Items/TwilightLantern.cs index 90dc238b4..1be9fd5e9 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2006/Items/TwilightLantern.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2006/Items/TwilightLantern.cs @@ -1,38 +1,38 @@ -namespace Server.Items -{ - public class TwilightLantern : Lantern - { - [Constructible] - public TwilightLantern() => Hue = Utility.RandomBool() ? 244 : 997; - - public TwilightLantern(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "Twilight Lantern"; - - public override bool AllowEquippedCast(Mobile from) => true; - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1060482); // Spell Channeling - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TwilightLantern : Lantern + { + [Constructible] + public TwilightLantern() => Hue = Utility.RandomBool() ? 244 : 997; + + public TwilightLantern(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "Twilight Lantern"; + + public override bool AllowEquippedCast(Mobile from) => true; + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1060482); // Spell Channeling + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2009/Engines/PumpkinPatch.cs b/Projects/UOContent/Holiday Stuff/Halloween/2009/Engines/PumpkinPatch.cs index 34c7a00c7..80acd42c1 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2009/Engines/PumpkinPatch.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2009/Engines/PumpkinPatch.cs @@ -1,61 +1,61 @@ -using System; -using System.Linq; -using Server.Events.Halloween; -using Server.Items; - -namespace Server.Engines.Events -{ - public class PumpkinPatchSpawner - { - private static Timer m_Timer; - - private static readonly Rectangle2D[] m_PumpkinFields = - { - new Rectangle2D(4557, 1471, 20, 10), - new Rectangle2D(796, 2152, 36, 24), - new Rectangle2D(816, 2251, 16, 8), - new Rectangle2D(816, 2261, 16, 8), - new Rectangle2D(816, 2271, 16, 8), - new Rectangle2D(816, 2281, 16, 8), - new Rectangle2D(835, 2344, 16, 16), - new Rectangle2D(816, 2344, 16, 24) - }; - - public static void Initialize() - { - DateTime now = DateTime.UtcNow; - - if (now >= HolidaySettings.StartHalloween && now <= HolidaySettings.FinishHalloween) - m_Timer = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromSeconds(30), 0, PumpkinPatchSpawnerCallback); - } - - protected static void PumpkinPatchSpawnerCallback() - { - AddPumpkin(Map.Felucca); - AddPumpkin(Map.Trammel); - } - - private static void AddPumpkin(Map map) - { - for (int i = 0; i < m_PumpkinFields.Length; i++) - { - Rectangle2D rect = m_PumpkinFields[i]; - - int spawncount = rect.Height * rect.Width / 20; - int pumpkins = map.GetItemsInBounds(rect).OfType().Count(); - - if (spawncount > pumpkins) - new HalloweenPumpkin().MoveToWorld(RandomPointIn(rect, map), map); - } - } - - private static Point3D RandomPointIn(Rectangle2D rect, Map map) - { - int x = Utility.Random(rect.X, rect.Width); - int y = Utility.Random(rect.Y, rect.Height); - int z = map.GetAverageZ(x, y); - - return new Point3D(x, y, z); - } - } -} +using System; +using System.Linq; +using Server.Events.Halloween; +using Server.Items; + +namespace Server.Engines.Events +{ + public class PumpkinPatchSpawner + { + private static Timer m_Timer; + + private static readonly Rectangle2D[] m_PumpkinFields = + { + new Rectangle2D(4557, 1471, 20, 10), + new Rectangle2D(796, 2152, 36, 24), + new Rectangle2D(816, 2251, 16, 8), + new Rectangle2D(816, 2261, 16, 8), + new Rectangle2D(816, 2271, 16, 8), + new Rectangle2D(816, 2281, 16, 8), + new Rectangle2D(835, 2344, 16, 16), + new Rectangle2D(816, 2344, 16, 24) + }; + + public static void Initialize() + { + var now = DateTime.UtcNow; + + if (now >= HolidaySettings.StartHalloween && now <= HolidaySettings.FinishHalloween) + m_Timer = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromSeconds(30), 0, PumpkinPatchSpawnerCallback); + } + + protected static void PumpkinPatchSpawnerCallback() + { + AddPumpkin(Map.Felucca); + AddPumpkin(Map.Trammel); + } + + private static void AddPumpkin(Map map) + { + for (var i = 0; i < m_PumpkinFields.Length; i++) + { + var rect = m_PumpkinFields[i]; + + var spawncount = rect.Height * rect.Width / 20; + var pumpkins = map.GetItemsInBounds(rect).OfType().Count(); + + if (spawncount > pumpkins) + new HalloweenPumpkin().MoveToWorld(RandomPointIn(rect, map), map); + } + } + + private static Point3D RandomPointIn(Rectangle2D rect, Map map) + { + var x = Utility.Random(rect.X, rect.Width); + var y = Utility.Random(rect.Y, rect.Height); + var z = map.GetAverageZ(x, y); + + return new Point3D(x, y, z); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2009/Foods/CreepyCake.cs b/Projects/UOContent/Holiday Stuff/Halloween/2009/Foods/CreepyCake.cs index fc9423fed..efbf6a15c 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2009/Foods/CreepyCake.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2009/Foods/CreepyCake.cs @@ -1,34 +1,34 @@ -namespace Server.Items -{ - /* - first seen halloween 2009. subsequently in 2010, - 2011 and 2012. GM Beggar-only Semi-Rare Treats - */ - - public class CreepyCake : Food - { - [Constructible] - public CreepyCake() : base(0x9e9, 1) => Hue = 0x3E4; - - public CreepyCake(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "Creepy Cake"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + /* + first seen halloween 2009. subsequently in 2010, + 2011 and 2012. GM Beggar-only Semi-Rare Treats + */ + + public class CreepyCake : Food + { + [Constructible] + public CreepyCake() : base(0x9e9, 1) => Hue = 0x3E4; + + public CreepyCake(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "Creepy Cake"; + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2009/Foods/HarvestWine.cs b/Projects/UOContent/Holiday Stuff/Halloween/2009/Foods/HarvestWine.cs index bdb93d4fa..f90775732 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2009/Foods/HarvestWine.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2009/Foods/HarvestWine.cs @@ -1,37 +1,37 @@ -namespace Server.Items -{ - /* - first seen halloween 2009. subsequently in 2010, - 2011 and 2012. GM Beggar-only Semi-Rare Treats - */ - - public class HarvestWine : BeverageBottle - { - [Constructible] - public HarvestWine() - : base(BeverageType.Wine) => - Hue = 0xe0; - - public HarvestWine(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "Harvest Wine"; - public override double DefaultWeight => 1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + /* + first seen halloween 2009. subsequently in 2010, + 2011 and 2012. GM Beggar-only Semi-Rare Treats + */ + + public class HarvestWine : BeverageBottle + { + [Constructible] + public HarvestWine() + : base(BeverageType.Wine) => + Hue = 0xe0; + + public HarvestWine(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "Harvest Wine"; + public override double DefaultWeight => 1; + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2009/Foods/MrPlainsCookies.cs b/Projects/UOContent/Holiday Stuff/Halloween/2009/Foods/MrPlainsCookies.cs index 4fdb46a63..7580e24cd 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2009/Foods/MrPlainsCookies.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2009/Foods/MrPlainsCookies.cs @@ -1,34 +1,34 @@ -namespace Server.Items -{ - public class MrPlainsCookies : Food - { - [Constructible] - public MrPlainsCookies() : base(0x160C, 1) - { - Weight = 1.0; - FillFactor = 4; - Hue = 0xF4; - } - - public MrPlainsCookies(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "Mr Plain's Cookies"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class MrPlainsCookies : Food + { + [Constructible] + public MrPlainsCookies() : base(0x160C, 1) + { + Weight = 1.0; + FillFactor = 4; + Hue = 0xF4; + } + + public MrPlainsCookies(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "Mr Plain's Cookies"; + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2009/Foods/MurkyMilk.cs b/Projects/UOContent/Holiday Stuff/Halloween/2009/Foods/MurkyMilk.cs index 3c3fa9dc3..a97710af8 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2009/Foods/MurkyMilk.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2009/Foods/MurkyMilk.cs @@ -1,42 +1,42 @@ -namespace Server.Items -{ - /* - first seen halloween 2009. subsequently in 2010, - 2011 and 2012. GM Beggar-only Semi-Rare Treats - */ - - public class MurkyMilk : Pitcher - { - [Constructible] - public MurkyMilk() - : base(BeverageType.Milk) - { - Hue = 0x3e5; - Quantity = MaxQuantity; - ItemID = Utility.RandomBool() ? 0x09F0 : 0x09AD; - } - - public MurkyMilk(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "Murky Milk"; - public override int MaxQuantity => 5; - public override double DefaultWeight => 1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + /* + first seen halloween 2009. subsequently in 2010, + 2011 and 2012. GM Beggar-only Semi-Rare Treats + */ + + public class MurkyMilk : Pitcher + { + [Constructible] + public MurkyMilk() + : base(BeverageType.Milk) + { + Hue = 0x3e5; + Quantity = MaxQuantity; + ItemID = Utility.RandomBool() ? 0x09F0 : 0x09AD; + } + + public MurkyMilk(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "Murky Milk"; + public override int MaxQuantity => 5; + public override double DefaultWeight => 1; + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2009/Foods/PumpkinPizza.cs b/Projects/UOContent/Holiday Stuff/Halloween/2009/Foods/PumpkinPizza.cs index 3016adb08..971f1509e 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2009/Foods/PumpkinPizza.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2009/Foods/PumpkinPizza.cs @@ -1,34 +1,34 @@ -namespace Server.Items -{ - /* - first seen halloween 2009. subsequently in 2010, - 2011 and 2012. GM Beggar-only Semi-Rare Treats - */ - - public class PumpkinPizza : CheesePizza - { - [Constructible] - public PumpkinPizza() => Hue = 0xF3; - - public PumpkinPizza(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "Pumpkin Pizza"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + /* + first seen halloween 2009. subsequently in 2010, + 2011 and 2012. GM Beggar-only Semi-Rare Treats + */ + + public class PumpkinPizza : CheesePizza + { + [Constructible] + public PumpkinPizza() => Hue = 0xF3; + + public PumpkinPizza(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "Pumpkin Pizza"; + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2009/Items/GrimWarning.cs b/Projects/UOContent/Holiday Stuff/Halloween/2009/Items/GrimWarning.cs index 7d214edc0..a25f057d0 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2009/Items/GrimWarning.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2009/Items/GrimWarning.cs @@ -1,37 +1,37 @@ -namespace Server.Items -{ - /* - first seen halloween 2009. subsequently in 2010, - 2011 and 2012. GM Beggar-only Semi-Rare Treats - */ - - public class GrimWarning : Item - { - [Constructible] - public GrimWarning() - : base(0x42BD) - { - } - - public GrimWarning(Serial serial) - : base(serial) - { - } - - public override double DefaultWeight => 1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + /* + first seen halloween 2009. subsequently in 2010, + 2011 and 2012. GM Beggar-only Semi-Rare Treats + */ + + public class GrimWarning : Item + { + [Constructible] + public GrimWarning() + : base(0x42BD) + { + } + + public GrimWarning(Serial serial) + : base(serial) + { + } + + public override double DefaultWeight => 1; + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2009/Items/SkullsOnPike.cs b/Projects/UOContent/Holiday Stuff/Halloween/2009/Items/SkullsOnPike.cs index acdd5d432..1dd0b85aa 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2009/Items/SkullsOnPike.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2009/Items/SkullsOnPike.cs @@ -1,37 +1,37 @@ -namespace Server.Items -{ - /* - first seen halloween 2009. subsequently in 2010, - 2011 and 2012. GM Beggar-only Semi-Rare Treats - */ - - public class SkullsOnPike : Item - { - [Constructible] - public SkullsOnPike() - : base(0x42B5) - { - } - - public SkullsOnPike(Serial serial) - : base(serial) - { - } - - public override double DefaultWeight => 1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + /* + first seen halloween 2009. subsequently in 2010, + 2011 and 2012. GM Beggar-only Semi-Rare Treats + */ + + public class SkullsOnPike : Item + { + [Constructible] + public SkullsOnPike() + : base(0x42B5) + { + } + + public SkullsOnPike(Serial serial) + : base(serial) + { + } + + public override double DefaultWeight => 1; + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2010/Items/ChairInAGhostCostume.cs b/Projects/UOContent/Holiday Stuff/Halloween/2010/Items/ChairInAGhostCostume.cs index fff19daa4..07c9dee6c 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2010/Items/ChairInAGhostCostume.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2010/Items/ChairInAGhostCostume.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class ChairInAGhostCostume : Item - { - [Constructible] - public ChairInAGhostCostume() - : base(0x3F26) - { - } - - public ChairInAGhostCostume(Serial serial) - : base(serial) - { - } - - public override double DefaultWeight => 5; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ChairInAGhostCostume : Item + { + [Constructible] + public ChairInAGhostCostume() + : base(0x3F26) + { + } + + public ChairInAGhostCostume(Serial serial) + : base(serial) + { + } + + public override double DefaultWeight => 5; + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2010/Items/ColoredSmallWebs.cs b/Projects/UOContent/Holiday Stuff/Halloween/2010/Items/ColoredSmallWebs.cs index 457cebff1..d0c7e06b3 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2010/Items/ColoredSmallWebs.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2010/Items/ColoredSmallWebs.cs @@ -1,31 +1,31 @@ -namespace Server.Items -{ - public class ColoredSmallWebs : Item - { - [Constructible] - public ColoredSmallWebs() - : base(Utility.RandomBool() ? 0x10d6 : 0x10d7) => - Hue = Utility.RandomBool() ? 0x455 : 0x4E9; - - public ColoredSmallWebs(Serial serial) - : base(serial) - { - } - - public override double DefaultWeight => 5; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ColoredSmallWebs : Item + { + [Constructible] + public ColoredSmallWebs() + : base(Utility.RandomBool() ? 0x10d6 : 0x10d7) => + Hue = Utility.RandomBool() ? 0x455 : 0x4E9; + + public ColoredSmallWebs(Serial serial) + : base(serial) + { + } + + public override double DefaultWeight => 5; + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2010/Items/ExcellentIronMaiden.cs b/Projects/UOContent/Holiday Stuff/Halloween/2010/Items/ExcellentIronMaiden.cs index 6f488a48d..f67b95b25 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2010/Items/ExcellentIronMaiden.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2010/Items/ExcellentIronMaiden.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class ExcellentIronMaiden : Item - { - [Constructible] - public ExcellentIronMaiden() - : base(0x3f15) - { - } - - public ExcellentIronMaiden(Serial serial) - : base(serial) - { - } - - public override double DefaultWeight => 5; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ExcellentIronMaiden : Item + { + [Constructible] + public ExcellentIronMaiden() + : base(0x3f15) + { + } + + public ExcellentIronMaiden(Serial serial) + : base(serial) + { + } + + public override double DefaultWeight => 5; + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2010/Items/HalloweenGuillotine.cs b/Projects/UOContent/Holiday Stuff/Halloween/2010/Items/HalloweenGuillotine.cs index a37bec845..349123540 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2010/Items/HalloweenGuillotine.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2010/Items/HalloweenGuillotine.cs @@ -1,31 +1,31 @@ -namespace Server.Items -{ - public class HalloweenGuillotine : Item - { - [Constructible] - public HalloweenGuillotine() : base(0x3F27) - { - } - - public HalloweenGuillotine(Serial serial) - : base(serial) - { - } - - public override double DefaultWeight => 5; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class HalloweenGuillotine : Item + { + [Constructible] + public HalloweenGuillotine() : base(0x3F27) + { + } + + public HalloweenGuillotine(Serial serial) + : base(serial) + { + } + + public override double DefaultWeight => 5; + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2011/Items/BasePaintedMask.cs b/Projects/UOContent/Holiday Stuff/Halloween/2011/Items/BasePaintedMask.cs index 4c08732ef..a6b095b9f 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2011/Items/BasePaintedMask.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2011/Items/BasePaintedMask.cs @@ -1,57 +1,57 @@ -// using System.Collections.Generic; - -namespace Server.Items.Holiday -{ - [TypeAlias("Server.Items.ClownMask", "Server.Items.DaemonMask", "Server.Items.PlagueMask")] - public class BasePaintedMask : Item - { - private static readonly string[] m_Staffers = - { - "Ryan", - "Mark", - "Krrios", - "Zippy", - "Athena", - "Eos", - "Xavier" - }; - - private string m_Staffer; - - public BasePaintedMask(int itemid) : this(m_Staffers.RandomElement(), itemid) - { - } - - public BasePaintedMask(string staffer, int itemid) : base(itemid + Utility.Random(2)) - { - m_Staffer = staffer; - - Utility.Intern(m_Staffer); - } - - public BasePaintedMask(Serial serial) : base(serial) - { - } - - public override string DefaultName => m_Staffer != null ? $"{MaskName} hand painted by {m_Staffer}" : MaskName; - - public virtual string MaskName => "A Mask"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - writer.Write(m_Staffer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version == 1) m_Staffer = Utility.Intern(reader.ReadString()); - } - } -} +// using System.Collections.Generic; + +namespace Server.Items.Holiday +{ + [TypeAlias("Server.Items.ClownMask", "Server.Items.DaemonMask", "Server.Items.PlagueMask")] + public class BasePaintedMask : Item + { + private static readonly string[] m_Staffers = + { + "Ryan", + "Mark", + "Krrios", + "Zippy", + "Athena", + "Eos", + "Xavier" + }; + + private string m_Staffer; + + public BasePaintedMask(int itemid) : this(m_Staffers.RandomElement(), itemid) + { + } + + public BasePaintedMask(string staffer, int itemid) : base(itemid + Utility.Random(2)) + { + m_Staffer = staffer; + + Utility.Intern(m_Staffer); + } + + public BasePaintedMask(Serial serial) : base(serial) + { + } + + public override string DefaultName => m_Staffer != null ? $"{MaskName} hand painted by {m_Staffer}" : MaskName; + + public virtual string MaskName => "A Mask"; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + writer.Write(m_Staffer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version == 1) m_Staffer = Utility.Intern(reader.ReadString()); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2011/Items/ClownMask.cs b/Projects/UOContent/Holiday Stuff/Halloween/2011/Items/ClownMask.cs index 8357a21ae..2618a0c28 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2011/Items/ClownMask.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2011/Items/ClownMask.cs @@ -1,32 +1,32 @@ -namespace Server.Items.Holiday -{ - public class PaintedEvilClownMask : BasePaintedMask - { - [Constructible] - public PaintedEvilClownMask() - : base(0x4a90) - { - } - - public PaintedEvilClownMask(Serial serial) - : base(serial) - { - } - - public override string MaskName => "Evil Clown Mask"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items.Holiday +{ + public class PaintedEvilClownMask : BasePaintedMask + { + [Constructible] + public PaintedEvilClownMask() + : base(0x4a90) + { + } + + public PaintedEvilClownMask(Serial serial) + : base(serial) + { + } + + public override string MaskName => "Evil Clown Mask"; + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2011/Items/DaemonMask.cs b/Projects/UOContent/Holiday Stuff/Halloween/2011/Items/DaemonMask.cs index 232430e79..bcd867f69 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2011/Items/DaemonMask.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2011/Items/DaemonMask.cs @@ -1,32 +1,32 @@ -namespace Server.Items.Holiday -{ - public class PaintedDaemonMask : BasePaintedMask - { - [Constructible] - public PaintedDaemonMask() - : base(0x4a92) - { - } - - public PaintedDaemonMask(Serial serial) - : base(serial) - { - } - - public override string MaskName => "Daemon Mask"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items.Holiday +{ + public class PaintedDaemonMask : BasePaintedMask + { + [Constructible] + public PaintedDaemonMask() + : base(0x4a92) + { + } + + public PaintedDaemonMask(Serial serial) + : base(serial) + { + } + + public override string MaskName => "Daemon Mask"; + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2011/Items/PlagueMask.cs b/Projects/UOContent/Holiday Stuff/Halloween/2011/Items/PlagueMask.cs index dea065a60..f8eb3d1bf 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2011/Items/PlagueMask.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2011/Items/PlagueMask.cs @@ -1,32 +1,32 @@ -namespace Server.Items.Holiday -{ - public class PaintedPlagueMask : BasePaintedMask - { - [Constructible] - public PaintedPlagueMask() - : base(0x4A8E) - { - } - - public PaintedPlagueMask(Serial serial) - : base(serial) - { - } - - public override string MaskName => "Plague Mask"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items.Holiday +{ + public class PaintedPlagueMask : BasePaintedMask + { + [Constructible] + public PaintedPlagueMask() + : base(0x4A8E) + { + } + + public PaintedPlagueMask(Serial serial) + : base(serial) + { + } + + public override string MaskName => "Plague Mask"; + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2011/Mobiles/PumpkinHead.cs b/Projects/UOContent/Holiday Stuff/Halloween/2011/Mobiles/PumpkinHead.cs index 8a469e17a..4c7d41211 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2011/Mobiles/PumpkinHead.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2011/Mobiles/PumpkinHead.cs @@ -1,129 +1,129 @@ -using System; -using Server.Items; -using Server.Items.Holiday; - -namespace Server.Mobiles -{ - public class PumpkinHead : BaseCreature - { - [Constructible] - public PumpkinHead() - : base(Utility.RandomBool() ? AIType.AI_Melee : AIType.AI_Mage, FightMode.Closest, 10, 1, 0.05, 0.1) - { - Body = 1246 + Utility.Random(2); - - BaseSoundID = 268; - - SetStr(350); - SetDex(125); - SetInt(250); - - SetHits(500); - SetMana(1000); - - SetDamage(10, 15); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 55); - SetResistance(ResistanceType.Fire, 50); - SetResistance(ResistanceType.Cold, 50); - SetResistance(ResistanceType.Poison, 65); - SetResistance(ResistanceType.Energy, 80); - - SetSkill(SkillName.DetectHidden, 100.0); - SetSkill(SkillName.Meditation, 120.0); - SetSkill(SkillName.Necromancy, 100.0); - SetSkill(SkillName.SpiritSpeak, 120.0); - SetSkill(SkillName.Magery, 160.0); - SetSkill(SkillName.EvalInt, 100.0); - SetSkill(SkillName.MagicResist, 100.0); - SetSkill(SkillName.Tactics, 100.0); - SetSkill(SkillName.Wrestling, 80.0); - - Fame = 5000; - Karma = -5000; - - VirtualArmor = 49; - } - - public PumpkinHead(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a killer pumpkin corpse"; - public override bool AutoDispel => true; - public override bool BardImmune => true; - public override bool Unprovokable => true; - public override bool AreaPeaceImmune => true; - public override string DefaultName => "a killer pumpkin"; - - public override void GenerateLoot() - { - if (Utility.RandomDouble() < .05) - switch (Utility.Random(5)) - { - case 0: - PackItem(new PaintedEvilClownMask()); - break; - case 1: - PackItem(new PaintedDaemonMask()); - break; - case 2: - PackItem(new PaintedPlagueMask()); - break; - case 3: - PackItem(new PaintedEvilJesterMask()); - break; - case 4: - PackItem(new PaintedPorcelainMask()); - break; - } - - PackItem(new WrappedCandy()); - AddLoot(LootPack.UltraRich, 2); - } - - public virtual void Lifted_Callback(Mobile from) - { - if (from?.Deleted == false && from is PlayerMobile) - { - Combatant = from; - Warmode = true; - } - } - - public override Item NewHarmfulItem() - { - Item bad = new AcidSlime(TimeSpan.FromSeconds(10), 25, 30); - - bad.Name = "gooey nasty pumpkin hummus"; - - bad.Hue = 144; - - return bad; - } - - public override void OnDamage(int amount, Mobile from, bool willKill) - { - if (Utility.RandomBool()) - if (from?.Map != null && Map != Map.Internal && Map == from.Map && from.InRange(this, 12)) - SpillAcid(willKill ? this : from, willKill ? 3 : 1); - - base.OnDamage(amount, from, willKill); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} +using System; +using Server.Items; +using Server.Items.Holiday; + +namespace Server.Mobiles +{ + public class PumpkinHead : BaseCreature + { + [Constructible] + public PumpkinHead() + : base(Utility.RandomBool() ? AIType.AI_Melee : AIType.AI_Mage, FightMode.Closest, 10, 1, 0.05, 0.1) + { + Body = 1246 + Utility.Random(2); + + BaseSoundID = 268; + + SetStr(350); + SetDex(125); + SetInt(250); + + SetHits(500); + SetMana(1000); + + SetDamage(10, 15); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 55); + SetResistance(ResistanceType.Fire, 50); + SetResistance(ResistanceType.Cold, 50); + SetResistance(ResistanceType.Poison, 65); + SetResistance(ResistanceType.Energy, 80); + + SetSkill(SkillName.DetectHidden, 100.0); + SetSkill(SkillName.Meditation, 120.0); + SetSkill(SkillName.Necromancy, 100.0); + SetSkill(SkillName.SpiritSpeak, 120.0); + SetSkill(SkillName.Magery, 160.0); + SetSkill(SkillName.EvalInt, 100.0); + SetSkill(SkillName.MagicResist, 100.0); + SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.Wrestling, 80.0); + + Fame = 5000; + Karma = -5000; + + VirtualArmor = 49; + } + + public PumpkinHead(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a killer pumpkin corpse"; + public override bool AutoDispel => true; + public override bool BardImmune => true; + public override bool Unprovokable => true; + public override bool AreaPeaceImmune => true; + public override string DefaultName => "a killer pumpkin"; + + public override void GenerateLoot() + { + if (Utility.RandomDouble() < .05) + switch (Utility.Random(5)) + { + case 0: + PackItem(new PaintedEvilClownMask()); + break; + case 1: + PackItem(new PaintedDaemonMask()); + break; + case 2: + PackItem(new PaintedPlagueMask()); + break; + case 3: + PackItem(new PaintedEvilJesterMask()); + break; + case 4: + PackItem(new PaintedPorcelainMask()); + break; + } + + PackItem(new WrappedCandy()); + AddLoot(LootPack.UltraRich, 2); + } + + public virtual void Lifted_Callback(Mobile from) + { + if (from?.Deleted == false && from is PlayerMobile) + { + Combatant = from; + Warmode = true; + } + } + + public override Item NewHarmfulItem() + { + Item bad = new AcidSlime(TimeSpan.FromSeconds(10), 25, 30); + + bad.Name = "gooey nasty pumpkin hummus"; + + bad.Hue = 144; + + return bad; + } + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + if (Utility.RandomBool()) + if (from?.Map != null && Map != Map.Internal && Map == from.Map && from.InRange(this, 12)) + SpillAcid(willKill ? this : from, willKill ? 3 : 1); + + base.OnDamage(amount, from, willKill); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2012/Engines/PlayerZombies.cs b/Projects/UOContent/Holiday Stuff/Halloween/2012/Engines/PlayerZombies.cs index eb7277edc..7c0a8cc0d 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2012/Engines/PlayerZombies.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2012/Engines/PlayerZombies.cs @@ -1,263 +1,266 @@ -using System; -using System.Collections.Generic; -using Server.Events.Halloween; -using Server.Items; -using Server.Mobiles; - -namespace Server.Engines.Events -{ - public class HalloweenHauntings - { - public static Dictionary ReAnimated { get; set; } - - private static Timer m_Timer; - private static Timer m_ClearTimer; - - private static int m_TotalZombieLimit; - private static int m_DeathQueueLimit; - private static int m_QueueDelaySeconds; - private static int m_QueueClearIntervalSeconds; - - private static List m_DeathQueue; - - private static readonly Rectangle2D[] m_Cemetaries = { - new Rectangle2D(1272, 3712, 30, 20), // Jhelom - new Rectangle2D(1337, 1444, 48, 52), // Britain - new Rectangle2D(2424, 1098, 20, 28), // Trinsic - new Rectangle2D(2728, 840, 54, 54), // Vesper - new Rectangle2D(4528, 1314, 20, 28), // Moonglow - new Rectangle2D(712, 1104, 30, 22), // Yew - new Rectangle2D(5824, 1464, 22, 6), // Fire Dungeon - new Rectangle2D(5224, 3655, 14, 5), // T2A - - new Rectangle2D(1272, 3712, 20, 30), // Jhelom - new Rectangle2D(1337, 1444, 52, 48), // Britain - new Rectangle2D(2424, 1098, 28, 20), // Trinsic - new Rectangle2D(2728, 840, 54, 54), // Vesper - new Rectangle2D(4528, 1314, 28, 20), // Moonglow - new Rectangle2D(712, 1104, 22, 30), // Yew - new Rectangle2D(5824, 1464, 6, 22), // Fire Dungeon - new Rectangle2D(5224, 3655, 5, 14) // T2A - }; - - public static void Initialize() - { - m_TotalZombieLimit = 200; - m_DeathQueueLimit = 200; - m_QueueDelaySeconds = 120; - m_QueueClearIntervalSeconds = 1800; - - DateTime today = DateTime.UtcNow; - TimeSpan tick = TimeSpan.FromSeconds(m_QueueDelaySeconds); - TimeSpan clear = TimeSpan.FromSeconds(m_QueueClearIntervalSeconds); - - ReAnimated = new Dictionary(); - m_DeathQueue = new List(); - - if (today >= HolidaySettings.StartHalloween && today <= HolidaySettings.FinishHalloween) - { - m_Timer = Timer.DelayCall(tick, tick, Timer_Callback); - - m_ClearTimer = Timer.DelayCall(clear, clear, Clear_Callback); - - EventSink.PlayerDeath += EventSink_PlayerDeath; - } - } - - public static void EventSink_PlayerDeath(Mobile m) - { - if (m is PlayerMobile pm && !pm.Deleted && m_Timer.Running && !m_DeathQueue.Contains(pm) && m_DeathQueue.Count < m_DeathQueueLimit) - m_DeathQueue.Add(pm); - } - - private static void Clear_Callback() - { - ReAnimated.Clear(); - - m_DeathQueue.Clear(); - - if (DateTime.UtcNow <= HolidaySettings.FinishHalloween) m_ClearTimer.Stop(); - } - - private static void Timer_Callback() - { - PlayerMobile player = null; - - if (DateTime.UtcNow <= HolidaySettings.FinishHalloween) - { - for (int index = 0; m_DeathQueue.Count > 0 && index < m_DeathQueue.Count; index++) - if (!ReAnimated.ContainsKey(m_DeathQueue[index])) - { - player = m_DeathQueue[index]; - - break; - } - - if (player?.Deleted == false && ReAnimated.Count < m_TotalZombieLimit) - { - Map map = Utility.RandomBool() ? Map.Trammel : Map.Felucca; - - Point3D home = GetRandomPointInRect(m_Cemetaries.RandomElement(), map); - - if (map.CanSpawnMobile(home)) - { - ZombieSkeleton zombieskel = new ZombieSkeleton(player); - - ReAnimated.Add(player, zombieskel); - zombieskel.Home = home; - zombieskel.RangeHome = 10; - - zombieskel.MoveToWorld(home, map); - - m_DeathQueue.Remove(player); - } - } - } - else - { - m_Timer.Stop(); - } - } - - private static Point3D GetRandomPointInRect(Rectangle2D rect, Map map) - { - int x = Utility.Random(rect.X, rect.Width); - int y = Utility.Random(rect.Y, rect.Height); - - return new Point3D(x, y, map.GetAverageZ(x, y)); - } - } - - public class PlayerBones : BaseContainer - { - [Constructible] - public PlayerBones(string name) - : base(Utility.RandomMinMax(0x0ECA, 0x0ED2)) - { - Name = $"{name}'s bones"; - - Hue = Utility.Random(10) switch - { - 0 => 0xa09, - 1 => 0xa93, - 2 => 0xa47, - _ => Hue - }; - } - - public PlayerBones(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class ZombieSkeleton : BaseCreature - { - public override string CorpseName => "a rotting corpse"; - private static readonly string m_Name = "Zombie Skeleton"; - - private PlayerMobile m_DeadPlayer; - - public ZombieSkeleton(PlayerMobile player = null) - : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) - { - m_DeadPlayer = player; - - Name = player != null ? $"{player.Name}'s {m_Name}" : m_Name; - - Body = 0x93; - BaseSoundID = 0x1c3; - - SetStr(500); - SetDex(500); - SetInt(500); - - SetHits(2500); - SetMana(500); - SetStam(500); - - SetDamage(8, 18); - - SetDamageType(ResistanceType.Physical, 40); - SetDamageType(ResistanceType.Cold, 60); - - SetResistance(ResistanceType.Fire, 50); - SetResistance(ResistanceType.Energy, 50); - SetResistance(ResistanceType.Physical, 50); - SetResistance(ResistanceType.Cold, 50); - SetResistance(ResistanceType.Poison, 50); - - SetSkill(SkillName.MagicResist, 65.1, 80.0); - SetSkill(SkillName.Tactics, 95.1, 100); - SetSkill(SkillName.Wrestling, 85.1, 95); - - Fame = 1000; - Karma = -1000; - - VirtualArmor = 18; - } - - public override void GenerateLoot() - { - var deadPlayerExists = m_DeadPlayer?.Deleted == false; - - PackItem( - Utility.Random(deadPlayerExists ? 8 : 10) switch - { - 0 => new LeftArm(), - 1 => new RightArm(), - 2 => new Torso(), - 3 => new Bone(), - 4 => new RibCage(), - 9 => deadPlayerExists ? new PlayerBones(m_DeadPlayer.Name) : null, - _ => null // 5-8, 10 (50%) - } - ); - - AddLoot(LootPack.Meager); - } - - public override bool BleedImmune => true; - - public override Poison PoisonImmune => Poison.Regular; - - public ZombieSkeleton(Serial serial) - : base(serial) - { - } - - public override void OnDelete() - { - if (m_DeadPlayer?.Deleted == false) - HalloweenHauntings.ReAnimated?.Remove(m_DeadPlayer); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - - writer.WriteMobile(m_DeadPlayer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - m_DeadPlayer = reader.ReadMobile(); - } - } -} +using System; +using System.Collections.Generic; +using Server.Events.Halloween; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.Events +{ + public class HalloweenHauntings + { + private static Timer m_Timer; + private static Timer m_ClearTimer; + + private static int m_TotalZombieLimit; + private static int m_DeathQueueLimit; + private static int m_QueueDelaySeconds; + private static int m_QueueClearIntervalSeconds; + + private static List m_DeathQueue; + + private static readonly Rectangle2D[] m_Cemetaries = + { + new Rectangle2D(1272, 3712, 30, 20), // Jhelom + new Rectangle2D(1337, 1444, 48, 52), // Britain + new Rectangle2D(2424, 1098, 20, 28), // Trinsic + new Rectangle2D(2728, 840, 54, 54), // Vesper + new Rectangle2D(4528, 1314, 20, 28), // Moonglow + new Rectangle2D(712, 1104, 30, 22), // Yew + new Rectangle2D(5824, 1464, 22, 6), // Fire Dungeon + new Rectangle2D(5224, 3655, 14, 5), // T2A + + new Rectangle2D(1272, 3712, 20, 30), // Jhelom + new Rectangle2D(1337, 1444, 52, 48), // Britain + new Rectangle2D(2424, 1098, 28, 20), // Trinsic + new Rectangle2D(2728, 840, 54, 54), // Vesper + new Rectangle2D(4528, 1314, 28, 20), // Moonglow + new Rectangle2D(712, 1104, 22, 30), // Yew + new Rectangle2D(5824, 1464, 6, 22), // Fire Dungeon + new Rectangle2D(5224, 3655, 5, 14) // T2A + }; + + public static Dictionary ReAnimated { get; set; } + + public static void Initialize() + { + m_TotalZombieLimit = 200; + m_DeathQueueLimit = 200; + m_QueueDelaySeconds = 120; + m_QueueClearIntervalSeconds = 1800; + + var today = DateTime.UtcNow; + var tick = TimeSpan.FromSeconds(m_QueueDelaySeconds); + var clear = TimeSpan.FromSeconds(m_QueueClearIntervalSeconds); + + ReAnimated = new Dictionary(); + m_DeathQueue = new List(); + + if (today >= HolidaySettings.StartHalloween && today <= HolidaySettings.FinishHalloween) + { + m_Timer = Timer.DelayCall(tick, tick, Timer_Callback); + + m_ClearTimer = Timer.DelayCall(clear, clear, Clear_Callback); + + EventSink.PlayerDeath += EventSink_PlayerDeath; + } + } + + public static void EventSink_PlayerDeath(Mobile m) + { + if (m is PlayerMobile pm && !pm.Deleted && m_Timer.Running && !m_DeathQueue.Contains(pm) && + m_DeathQueue.Count < m_DeathQueueLimit) + m_DeathQueue.Add(pm); + } + + private static void Clear_Callback() + { + ReAnimated.Clear(); + + m_DeathQueue.Clear(); + + if (DateTime.UtcNow <= HolidaySettings.FinishHalloween) m_ClearTimer.Stop(); + } + + private static void Timer_Callback() + { + PlayerMobile player = null; + + if (DateTime.UtcNow <= HolidaySettings.FinishHalloween) + { + for (var index = 0; m_DeathQueue.Count > 0 && index < m_DeathQueue.Count; index++) + if (!ReAnimated.ContainsKey(m_DeathQueue[index])) + { + player = m_DeathQueue[index]; + + break; + } + + if (player?.Deleted == false && ReAnimated.Count < m_TotalZombieLimit) + { + var map = Utility.RandomBool() ? Map.Trammel : Map.Felucca; + + var home = GetRandomPointInRect(m_Cemetaries.RandomElement(), map); + + if (map.CanSpawnMobile(home)) + { + var zombieskel = new ZombieSkeleton(player); + + ReAnimated.Add(player, zombieskel); + zombieskel.Home = home; + zombieskel.RangeHome = 10; + + zombieskel.MoveToWorld(home, map); + + m_DeathQueue.Remove(player); + } + } + } + else + { + m_Timer.Stop(); + } + } + + private static Point3D GetRandomPointInRect(Rectangle2D rect, Map map) + { + var x = Utility.Random(rect.X, rect.Width); + var y = Utility.Random(rect.Y, rect.Height); + + return new Point3D(x, y, map.GetAverageZ(x, y)); + } + } + + public class PlayerBones : BaseContainer + { + [Constructible] + public PlayerBones(string name) + : base(Utility.RandomMinMax(0x0ECA, 0x0ED2)) + { + Name = $"{name}'s bones"; + + Hue = Utility.Random(10) switch + { + 0 => 0xa09, + 1 => 0xa93, + 2 => 0xa47, + _ => Hue + }; + } + + public PlayerBones(Serial serial) + : base(serial) + { + } + + 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(); + } + } + + public class ZombieSkeleton : BaseCreature + { + private static readonly string m_Name = "Zombie Skeleton"; + + private PlayerMobile m_DeadPlayer; + + public ZombieSkeleton(PlayerMobile player = null) + : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + m_DeadPlayer = player; + + Name = player != null ? $"{player.Name}'s {m_Name}" : m_Name; + + Body = 0x93; + BaseSoundID = 0x1c3; + + SetStr(500); + SetDex(500); + SetInt(500); + + SetHits(2500); + SetMana(500); + SetStam(500); + + SetDamage(8, 18); + + SetDamageType(ResistanceType.Physical, 40); + SetDamageType(ResistanceType.Cold, 60); + + SetResistance(ResistanceType.Fire, 50); + SetResistance(ResistanceType.Energy, 50); + SetResistance(ResistanceType.Physical, 50); + SetResistance(ResistanceType.Cold, 50); + SetResistance(ResistanceType.Poison, 50); + + SetSkill(SkillName.MagicResist, 65.1, 80.0); + SetSkill(SkillName.Tactics, 95.1, 100); + SetSkill(SkillName.Wrestling, 85.1, 95); + + Fame = 1000; + Karma = -1000; + + VirtualArmor = 18; + } + + public ZombieSkeleton(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a rotting corpse"; + + public override bool BleedImmune => true; + + public override Poison PoisonImmune => Poison.Regular; + + public override void GenerateLoot() + { + var deadPlayerExists = m_DeadPlayer?.Deleted == false; + + PackItem( + Utility.Random(deadPlayerExists ? 8 : 10) switch + { + 0 => new LeftArm(), + 1 => new RightArm(), + 2 => new Torso(), + 3 => new Bone(), + 4 => new RibCage(), + 9 => deadPlayerExists ? new PlayerBones(m_DeadPlayer.Name) : null, + _ => null // 5-8, 10 (50%) + } + ); + + AddLoot(LootPack.Meager); + } + + public override void OnDelete() + { + if (m_DeadPlayer?.Deleted == false) + HalloweenHauntings.ReAnimated?.Remove(m_DeadPlayer); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(0); + + writer.WriteMobile(m_DeadPlayer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + m_DeadPlayer = reader.ReadMobile(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2012/Items/EvilJesterMask.cs b/Projects/UOContent/Holiday Stuff/Halloween/2012/Items/EvilJesterMask.cs index 0d633c8b9..78fadd5ab 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2012/Items/EvilJesterMask.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2012/Items/EvilJesterMask.cs @@ -1,32 +1,32 @@ -namespace Server.Items.Holiday -{ - public class PaintedEvilJesterMask : BasePaintedMask - { - [Constructible] - public PaintedEvilJesterMask() - : base(0x4BA5) - { - } - - public PaintedEvilJesterMask(Serial serial) - : base(serial) - { - } - - public override string MaskName => "Evil Jester Mask"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items.Holiday +{ + public class PaintedEvilJesterMask : BasePaintedMask + { + [Constructible] + public PaintedEvilJesterMask() + : base(0x4BA5) + { + } + + public PaintedEvilJesterMask(Serial serial) + : base(serial) + { + } + + public override string MaskName => "Evil Jester Mask"; + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/2012/Items/PorcelainMask.cs b/Projects/UOContent/Holiday Stuff/Halloween/2012/Items/PorcelainMask.cs index 167d2ba10..be726de42 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/2012/Items/PorcelainMask.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/2012/Items/PorcelainMask.cs @@ -1,32 +1,32 @@ -namespace Server.Items.Holiday -{ - public class PaintedPorcelainMask : BasePaintedMask - { - [Constructible] - public PaintedPorcelainMask() - : base(0x4BA7) - { - } - - public PaintedPorcelainMask(Serial serial) - : base(serial) - { - } - - public override string MaskName => "Porcelain Mask"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items.Holiday +{ + public class PaintedPorcelainMask : BasePaintedMask + { + [Constructible] + public PaintedPorcelainMask() + : base(0x4BA7) + { + } + + public PaintedPorcelainMask(Serial serial) + : base(serial) + { + } + + public override string MaskName => "Porcelain Mask"; + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/HolidaySettings.cs b/Projects/UOContent/Holiday Stuff/Halloween/HolidaySettings.cs index 920cce7e6..e7b08ea00 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/HolidaySettings.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/HolidaySettings.cs @@ -1,43 +1,43 @@ -using System; -using Server.Items; -using Server.Utilities; - -namespace Server.Events.Halloween -{ - internal class HolidaySettings - { - private static readonly Type[] m_GMBeggarTreats = - { - typeof(CreepyCake), - typeof(PumpkinPizza), - typeof(GrimWarning), - typeof(HarvestWine), - typeof(MurkyMilk), - typeof(MrPlainsCookies), - typeof(SkullsOnPike), - typeof(ChairInAGhostCostume), - typeof(ExcellentIronMaiden), - typeof(HalloweenGuillotine), - typeof(ColoredSmallWebs) - }; - - private static readonly Type[] m_Treats = - { - typeof(Lollipops), - typeof(WrappedCandy), - typeof(JellyBeans), - typeof(Taffy), - typeof(NougatSwirl) - }; - - public static DateTime StartHalloween // YY MM DD - => new DateTime(2012, 10, 24); - - public static DateTime FinishHalloween => new DateTime(2012, 11, 15); - - public static Item RandomGMBeggerItem => - (Item)ActivatorUtil.CreateInstance(m_GMBeggarTreats.RandomElement()); - - public static Item RandomTreat => (Item)ActivatorUtil.CreateInstance(m_Treats.RandomElement()); - } -} +using System; +using Server.Items; +using Server.Utilities; + +namespace Server.Events.Halloween +{ + internal class HolidaySettings + { + private static readonly Type[] m_GMBeggarTreats = + { + typeof(CreepyCake), + typeof(PumpkinPizza), + typeof(GrimWarning), + typeof(HarvestWine), + typeof(MurkyMilk), + typeof(MrPlainsCookies), + typeof(SkullsOnPike), + typeof(ChairInAGhostCostume), + typeof(ExcellentIronMaiden), + typeof(HalloweenGuillotine), + typeof(ColoredSmallWebs) + }; + + private static readonly Type[] m_Treats = + { + typeof(Lollipops), + typeof(WrappedCandy), + typeof(JellyBeans), + typeof(Taffy), + typeof(NougatSwirl) + }; + + public static DateTime StartHalloween // YY MM DD + => new DateTime(2012, 10, 24); + + public static DateTime FinishHalloween => new DateTime(2012, 11, 15); + + public static Item RandomGMBeggerItem => + (Item)ActivatorUtil.CreateInstance(m_GMBeggarTreats.RandomElement()); + + public static Item RandomTreat => (Item)ActivatorUtil.CreateInstance(m_Treats.RandomElement()); + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/Treats/Jellybeans.cs b/Projects/UOContent/Holiday Stuff/Halloween/Treats/Jellybeans.cs index b80722969..c3a21e483 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/Treats/Jellybeans.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/Treats/Jellybeans.cs @@ -1,31 +1,31 @@ -namespace Server.Items -{ - public class JellyBeans : CandyCane - { - [Constructible] - public JellyBeans(int amount = 1) - : base(0x468C) => - Stackable = true; - - public JellyBeans(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1096932; /* jellybeans */ - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class JellyBeans : CandyCane + { + [Constructible] + public JellyBeans(int amount = 1) + : base(0x468C) => + Stackable = true; + + public JellyBeans(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1096932; /* jellybeans */ + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/Treats/Lollipops.cs b/Projects/UOContent/Holiday Stuff/Halloween/Treats/Lollipops.cs index c4a6d40d1..e60b54772 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/Treats/Lollipops.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/Treats/Lollipops.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - [TypeAlias("Server.Items.Lollipop")] - public class Lollipops : CandyCane - { - [Constructible] - public Lollipops(int amount = 1) - : base(0x468D + Utility.Random(3)) => - Stackable = true; - - public Lollipops(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + [TypeAlias("Server.Items.Lollipop")] + public class Lollipops : CandyCane + { + [Constructible] + public Lollipops(int amount = 1) + : base(0x468D + Utility.Random(3)) => + Stackable = true; + + public Lollipops(Serial serial) + : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/Treats/NougatSwirl.cs b/Projects/UOContent/Holiday Stuff/Halloween/Treats/NougatSwirl.cs index 809c4de21..320fd76ef 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/Treats/NougatSwirl.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/Treats/NougatSwirl.cs @@ -1,31 +1,31 @@ -namespace Server.Items -{ - public class NougatSwirl : CandyCane - { - [Constructible] - public NougatSwirl(int amount = 1) - : base(0x4690) => - Stackable = true; - - public NougatSwirl(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1096936; /* nougat swirl */ - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class NougatSwirl : CandyCane + { + [Constructible] + public NougatSwirl(int amount = 1) + : base(0x4690) => + Stackable = true; + + public NougatSwirl(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1096936; /* nougat swirl */ + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/Treats/Taffy.cs b/Projects/UOContent/Holiday Stuff/Halloween/Treats/Taffy.cs index 307896d31..12ee251cf 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/Treats/Taffy.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/Treats/Taffy.cs @@ -1,31 +1,31 @@ -namespace Server.Items -{ - public class Taffy : CandyCane - { - [Constructible] - public Taffy(int amount = 1) - : base(0x469D) => - Stackable = true; - - public Taffy(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1096949; /* taffy */ - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class Taffy : CandyCane + { + [Constructible] + public Taffy(int amount = 1) + : base(0x469D) => + Stackable = true; + + public Taffy(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1096949; /* taffy */ + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Halloween/Treats/WrappedCandy.cs b/Projects/UOContent/Holiday Stuff/Halloween/Treats/WrappedCandy.cs index bb328608c..0a70610c1 100644 --- a/Projects/UOContent/Holiday Stuff/Halloween/Treats/WrappedCandy.cs +++ b/Projects/UOContent/Holiday Stuff/Halloween/Treats/WrappedCandy.cs @@ -1,31 +1,31 @@ -namespace Server.Items -{ - public class WrappedCandy : CandyCane - { - [Constructible] - public WrappedCandy(int amount = 1) - : base(0x469e) => - Stackable = true; - - public WrappedCandy(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1096950; /* wrapped candy */ - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class WrappedCandy : CandyCane + { + [Constructible] + public WrappedCandy(int amount = 1) + : base(0x469e) => + Stackable = true; + + public WrappedCandy(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1096950; /* wrapped candy */ + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Valentine/2010/Items/AnimatedHeartShapedBox.cs b/Projects/UOContent/Holiday Stuff/Valentine/2010/Items/AnimatedHeartShapedBox.cs index 96cd4491a..30dd26702 100644 --- a/Projects/UOContent/Holiday Stuff/Valentine/2010/Items/AnimatedHeartShapedBox.cs +++ b/Projects/UOContent/Holiday Stuff/Valentine/2010/Items/AnimatedHeartShapedBox.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - [Flippable(0x49CC, 0x49D0)] - public class AnimatedHeartShapedBox : HeartShapedBox - { - [Constructible] - public AnimatedHeartShapedBox() => ItemID = 0x49CC; - - public AnimatedHeartShapedBox(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x49CC, 0x49D0)] + public class AnimatedHeartShapedBox : HeartShapedBox + { + [Constructible] + public AnimatedHeartShapedBox() => ItemID = 0x49CC; + + public AnimatedHeartShapedBox(Serial serial) + : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Valentine/2011/Items/StValentinesBears.cs b/Projects/UOContent/Holiday Stuff/Valentine/2011/Items/StValentinesBears.cs index 4b35030d0..4b89ad430 100644 --- a/Projects/UOContent/Holiday Stuff/Valentine/2011/Items/StValentinesBears.cs +++ b/Projects/UOContent/Holiday Stuff/Valentine/2011/Items/StValentinesBears.cs @@ -1,292 +1,299 @@ -using System; -using Server.Gumps; -using Server.Network; - -namespace Server.Items -{ - public abstract class StValentinesBear : Item - { - private string m_Line1; - private string m_Line2; - private string m_Line3; - - private string m_Owner; - - public StValentinesBear(int itemid, string name) - : base(itemid) - { - m_Owner = name; - LootType = LootType.Blessed; - } - - public StValentinesBear(Serial serial) - : base(serial) - { - } - - public override string DefaultName - { - get - { - if (m_Owner != null) - return $"{m_Owner}'s St. Valentine Bear"; - return "St. Valentine Bear"; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public string Owner - { - get => m_Owner; - set - { - m_Owner = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public string Line1 - { - get => m_Line1; - set - { - m_Line1 = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public string Line2 - { - get => m_Line2; - set - { - m_Line2 = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public string Line3 - { - get => m_Line3; - set - { - m_Line3 = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime EditLimit { get; set; } - - public bool IsSigned => m_Line1 != null || m_Line2 != null || m_Line3 != null; - - public bool CanSign => !IsSigned || DateTime.UtcNow <= EditLimit; - - public override void AddNameProperty(ObjectPropertyList list) - { - if (m_Owner != null) - list.Add(1150295, m_Owner); // ~1_NAME~'s St. Valentine Bear - else - list.Add(1150294); // St. Valentine Bear - - AddLine(list, 1150301, m_Line1); // [ ~1_LINE0~ ] - AddLine(list, 1150302, m_Line2); // [ ~1_LINE1~ ] - AddLine(list, 1150303, m_Line3); // [ ~1_LINE2~ ] - } - - private static void AddLine(ObjectPropertyList list, int cliloc, string line) - { - if (line != null) - list.Add(cliloc, line); - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - ShowLine(from, 1150301, m_Line1); // [ ~1_LINE0~ ] - ShowLine(from, 1150302, m_Line2); // [ ~1_LINE1~ ] - ShowLine(from, 1150303, m_Line3); // [ ~1_LINE2~ ] - } - - private void ShowLine(Mobile from, int cliloc, string line) - { - if (line != null) - LabelTo(from, cliloc, line); - } - - public override void OnDoubleClick(Mobile from) - { - if (!CupidsArrow.CheckSeason(from) || !CanSign) - return; - - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1080063); // This must be in your backpack to use it. - return; - } - - from.SendGump(new InternalGump(this)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(m_Owner); - writer.Write(m_Line1); - writer.Write(m_Line2); - writer.Write(m_Line3); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Owner = Utility.Intern(reader.ReadString()); - m_Line1 = Utility.Intern(reader.ReadString()); - m_Line2 = Utility.Intern(reader.ReadString()); - m_Line3 = Utility.Intern(reader.ReadString()); - } - - private class InternalGump : Gump - { - private readonly StValentinesBear m_Bear; - - public InternalGump(StValentinesBear bear) - : base(50, 50) - { - m_Bear = bear; - - AddPage(0); - AddBackground(0, 0, 420, 320, 9300); - AddHtml(10, 10, 400, 21, "
St. Valentine Bear
"); - AddHtmlLocalized(10, 40, 400, 75, 1150293, 0); // Enter up to three lines of personalized greeting for your St. Valentine Bear. You many enter up to 25 characters per line. Once you enter text, you will only be able to correct mistakes for 10 minutes. - - AddHtmlLocalized(10, 129, 400, 21, 1150296, 0); // Line 1: - AddBackground(10, 150, 400, 24, 9350); - AddTextEntry(15, 152, 390, 20, 0, 0, "", 25); - - AddHtmlLocalized(10, 179, 400, 21, 1150297, 0); // Line 2: - AddBackground(10, 200, 400, 24, 9350); - AddTextEntry(15, 202, 390, 20, 0, 1, "", 25); - - AddHtmlLocalized(10, 229, 400, 21, 1150298, 0); // Line 3: - AddBackground(10, 250, 400, 24, 9350); - AddTextEntry(15, 252, 390, 20, 0, 2, "", 25); - - AddButton(15, 285, 242, 241, 0); - AddButton(335, 285, 247, 248, 1); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - Mobile from = sender.Mobile; - - if (m_Bear.Deleted || !m_Bear.IsChildOf(from.Backpack) || !m_Bear.CanSign || info.ButtonID != 1) - return; - - string line1 = GetLine(info, 0); - string line2 = GetLine(info, 1); - string line3 = GetLine(info, 2); - - if (string.IsNullOrEmpty(line1) - || string.IsNullOrEmpty(line2) - || string.IsNullOrEmpty(line3)) - { - from.SendMessage("Lines cannot be left blank."); - return; - } - - if (line1.Length > 25 - || line2.Length > 25 - || line3.Length > 25) - { - from.SendMessage("Lines may not exceed 25 characters."); - return; - } - - if (!m_Bear.IsSigned) - m_Bear.EditLimit = DateTime.UtcNow + TimeSpan.FromMinutes(10); - - m_Bear.Line1 = Utility.FixHtml(line1); - m_Bear.Line2 = Utility.FixHtml(line2); - m_Bear.Line3 = Utility.FixHtml(line3); - - from.SendMessage("You add the personalized greeting to your St. Valentine Bear."); - } - - private static string GetLine(RelayInfo info, int idx) - { - TextRelay tr = info.GetTextEntry(idx); - - return tr?.Text; - } - } - } - - [Flippable(0x48E0, 0x48E1)] - public class StValentinesPanda : StValentinesBear - { - [Constructible] - public StValentinesPanda(string name = null) - : base(0x48E0, name) - { - } - - public StValentinesPanda(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x48E2, 0x48E3)] - public class StValentinesPolarBear : StValentinesBear - { - [Constructible] - public StValentinesPolarBear(string name = null) - : base(0x48E2, name) - { - } - - public StValentinesPolarBear(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using Server.Gumps; +using Server.Network; + +namespace Server.Items +{ + public abstract class StValentinesBear : Item + { + private string m_Line1; + private string m_Line2; + private string m_Line3; + + private string m_Owner; + + public StValentinesBear(int itemid, string name) + : base(itemid) + { + m_Owner = name; + LootType = LootType.Blessed; + } + + public StValentinesBear(Serial serial) + : base(serial) + { + } + + public override string DefaultName + { + get + { + if (m_Owner != null) + return $"{m_Owner}'s St. Valentine Bear"; + return "St. Valentine Bear"; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public string Owner + { + get => m_Owner; + set + { + m_Owner = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public string Line1 + { + get => m_Line1; + set + { + m_Line1 = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public string Line2 + { + get => m_Line2; + set + { + m_Line2 = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public string Line3 + { + get => m_Line3; + set + { + m_Line3 = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime EditLimit { get; set; } + + public bool IsSigned => m_Line1 != null || m_Line2 != null || m_Line3 != null; + + public bool CanSign => !IsSigned || DateTime.UtcNow <= EditLimit; + + public override void AddNameProperty(ObjectPropertyList list) + { + if (m_Owner != null) + list.Add(1150295, m_Owner); // ~1_NAME~'s St. Valentine Bear + else + list.Add(1150294); // St. Valentine Bear + + AddLine(list, 1150301, m_Line1); // [ ~1_LINE0~ ] + AddLine(list, 1150302, m_Line2); // [ ~1_LINE1~ ] + AddLine(list, 1150303, m_Line3); // [ ~1_LINE2~ ] + } + + private static void AddLine(ObjectPropertyList list, int cliloc, string line) + { + if (line != null) + list.Add(cliloc, line); + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + ShowLine(from, 1150301, m_Line1); // [ ~1_LINE0~ ] + ShowLine(from, 1150302, m_Line2); // [ ~1_LINE1~ ] + ShowLine(from, 1150303, m_Line3); // [ ~1_LINE2~ ] + } + + private void ShowLine(Mobile from, int cliloc, string line) + { + if (line != null) + LabelTo(from, cliloc, line); + } + + public override void OnDoubleClick(Mobile from) + { + if (!CupidsArrow.CheckSeason(from) || !CanSign) + return; + + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1080063); // This must be in your backpack to use it. + return; + } + + from.SendGump(new InternalGump(this)); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + writer.Write(m_Owner); + writer.Write(m_Line1); + writer.Write(m_Line2); + writer.Write(m_Line3); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Owner = Utility.Intern(reader.ReadString()); + m_Line1 = Utility.Intern(reader.ReadString()); + m_Line2 = Utility.Intern(reader.ReadString()); + m_Line3 = Utility.Intern(reader.ReadString()); + } + + private class InternalGump : Gump + { + private readonly StValentinesBear m_Bear; + + public InternalGump(StValentinesBear bear) + : base(50, 50) + { + m_Bear = bear; + + AddPage(0); + AddBackground(0, 0, 420, 320, 9300); + AddHtml(10, 10, 400, 21, "
St. Valentine Bear
"); + AddHtmlLocalized( + 10, + 40, + 400, + 75, + 1150293, + 0 + ); // Enter up to three lines of personalized greeting for your St. Valentine Bear. You many enter up to 25 characters per line. Once you enter text, you will only be able to correct mistakes for 10 minutes. + + AddHtmlLocalized(10, 129, 400, 21, 1150296, 0); // Line 1: + AddBackground(10, 150, 400, 24, 9350); + AddTextEntry(15, 152, 390, 20, 0, 0, "", 25); + + AddHtmlLocalized(10, 179, 400, 21, 1150297, 0); // Line 2: + AddBackground(10, 200, 400, 24, 9350); + AddTextEntry(15, 202, 390, 20, 0, 1, "", 25); + + AddHtmlLocalized(10, 229, 400, 21, 1150298, 0); // Line 3: + AddBackground(10, 250, 400, 24, 9350); + AddTextEntry(15, 252, 390, 20, 0, 2, "", 25); + + AddButton(15, 285, 242, 241, 0); + AddButton(335, 285, 247, 248, 1); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var from = sender.Mobile; + + if (m_Bear.Deleted || !m_Bear.IsChildOf(from.Backpack) || !m_Bear.CanSign || info.ButtonID != 1) + return; + + var line1 = GetLine(info, 0); + var line2 = GetLine(info, 1); + var line3 = GetLine(info, 2); + + if (string.IsNullOrEmpty(line1) + || string.IsNullOrEmpty(line2) + || string.IsNullOrEmpty(line3)) + { + from.SendMessage("Lines cannot be left blank."); + return; + } + + if (line1.Length > 25 + || line2.Length > 25 + || line3.Length > 25) + { + from.SendMessage("Lines may not exceed 25 characters."); + return; + } + + if (!m_Bear.IsSigned) + m_Bear.EditLimit = DateTime.UtcNow + TimeSpan.FromMinutes(10); + + m_Bear.Line1 = Utility.FixHtml(line1); + m_Bear.Line2 = Utility.FixHtml(line2); + m_Bear.Line3 = Utility.FixHtml(line3); + + from.SendMessage("You add the personalized greeting to your St. Valentine Bear."); + } + + private static string GetLine(RelayInfo info, int idx) + { + var tr = info.GetTextEntry(idx); + + return tr?.Text; + } + } + } + + [Flippable(0x48E0, 0x48E1)] + public class StValentinesPanda : StValentinesBear + { + [Constructible] + public StValentinesPanda(string name = null) + : base(0x48E0, name) + { + } + + public StValentinesPanda(Serial serial) + : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x48E2, 0x48E3)] + public class StValentinesPolarBear : StValentinesBear + { + [Constructible] + public StValentinesPolarBear(string name = null) + : base(0x48E2, name) + { + } + + public StValentinesPolarBear(Serial serial) + : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Valentine/2012/Items/CupidStatue.cs b/Projects/UOContent/Holiday Stuff/Valentine/2012/Items/CupidStatue.cs index ede905c12..05f2ec76f 100644 --- a/Projects/UOContent/Holiday Stuff/Valentine/2012/Items/CupidStatue.cs +++ b/Projects/UOContent/Holiday Stuff/Valentine/2012/Items/CupidStatue.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - [Flippable(0x4F7C, 0x4F7D)] - public class CupidStatue : Item - { - [Constructible] - public CupidStatue() - : base(0x4F7D) => - LootType = LootType.Blessed; - - public CupidStatue(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1099220; // cupid statue - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x4F7C, 0x4F7D)] + public class CupidStatue : Item + { + [Constructible] + public CupidStatue() + : base(0x4F7D) => + LootType = LootType.Blessed; + + public CupidStatue(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1099220; // cupid statue + + 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(); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Valentine/2012/Items/CupidsArrow.cs b/Projects/UOContent/Holiday Stuff/Valentine/2012/Items/CupidsArrow.cs index 09a104001..eaa3cef13 100644 --- a/Projects/UOContent/Holiday Stuff/Valentine/2012/Items/CupidsArrow.cs +++ b/Projects/UOContent/Holiday Stuff/Valentine/2012/Items/CupidsArrow.cs @@ -1,127 +1,136 @@ -using System; -using Server.Targeting; - -namespace Server.Items -{ - public class CupidsArrow : Item - { - // TODO: Check messages - - public override int LabelNumber => 1152270; // Cupid's Arrow 2012 - - private string m_From; - private string m_To; - - [CommandProperty(AccessLevel.GameMaster)] - public string From - { - get => m_From; - set { m_From = value; InvalidateProperties(); } - } - - [CommandProperty(AccessLevel.GameMaster)] - public string To - { - get => m_To; - set { m_To = value; InvalidateProperties(); } - } - - public bool IsSigned => m_From != null && m_To != null; - - [Constructible] - public CupidsArrow() - : base(0x4F7F) => - LootType = LootType.Blessed; - - public override void AddNameProperty(ObjectPropertyList list) - { - base.AddNameProperty(list); - - if (IsSigned) - list.Add(1152273, $"{m_From}\t{m_To}"); // ~1_val~ is madly in love with ~2_val~ - } - - public static bool CheckSeason(Mobile from) - { - if (DateTime.UtcNow.Month == 2) - return true; - - from.SendLocalizedMessage(1152318); // You may not use this item out of season. - return false; - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - if (IsSigned) - LabelTo(from, 1152273, $"{m_From}\t{m_To}"); // ~1_val~ is madly in love with ~2_val~ - } - - public override void OnDoubleClick(Mobile from) - { - if (IsSigned || !CheckSeason(from)) - return; - - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1080063); // This must be in your backpack to use it. - return; - } - - from.BeginTarget(10, false, TargetFlags.None, OnTarget); - from.SendMessage("Who do you wish to use this on?"); - } - - private void OnTarget(Mobile from, object targeted) - { - if (IsSigned || !IsChildOf(from.Backpack)) - return; - - if (targeted is Mobile m) - { - if (!m.Alive) - { - from.SendLocalizedMessage(1152269); // That target is dead and even Cupid's arrow won't make them love you. - return; - } - - m_From = from.Name; - m_To = m.Name; - - InvalidateProperties(); - - from.SendMessage("You inscribe the arrow."); - } - else - { - from.SendMessage("That is not a person."); - } - } - - public CupidsArrow(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(m_From); - writer.Write(m_To); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_From = Utility.Intern(reader.ReadString()); - m_To = Utility.Intern(reader.ReadString()); - } - } -} +using System; +using Server.Targeting; + +namespace Server.Items +{ + public class CupidsArrow : Item + { + private string m_From; + private string m_To; + + [Constructible] + public CupidsArrow() + : base(0x4F7F) => + LootType = LootType.Blessed; + + public CupidsArrow(Serial serial) + : base(serial) + { + } + // TODO: Check messages + + public override int LabelNumber => 1152270; // Cupid's Arrow 2012 + + [CommandProperty(AccessLevel.GameMaster)] + public string From + { + get => m_From; + set + { + m_From = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public string To + { + get => m_To; + set + { + m_To = value; + InvalidateProperties(); + } + } + + public bool IsSigned => m_From != null && m_To != null; + + public override void AddNameProperty(ObjectPropertyList list) + { + base.AddNameProperty(list); + + if (IsSigned) + list.Add(1152273, $"{m_From}\t{m_To}"); // ~1_val~ is madly in love with ~2_val~ + } + + public static bool CheckSeason(Mobile from) + { + if (DateTime.UtcNow.Month == 2) + return true; + + from.SendLocalizedMessage(1152318); // You may not use this item out of season. + return false; + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + if (IsSigned) + LabelTo(from, 1152273, $"{m_From}\t{m_To}"); // ~1_val~ is madly in love with ~2_val~ + } + + public override void OnDoubleClick(Mobile from) + { + if (IsSigned || !CheckSeason(from)) + return; + + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1080063); // This must be in your backpack to use it. + return; + } + + from.BeginTarget(10, false, TargetFlags.None, OnTarget); + from.SendMessage("Who do you wish to use this on?"); + } + + private void OnTarget(Mobile from, object targeted) + { + if (IsSigned || !IsChildOf(from.Backpack)) + return; + + if (targeted is Mobile m) + { + if (!m.Alive) + { + from.SendLocalizedMessage( + 1152269 + ); // That target is dead and even Cupid's arrow won't make them love you. + return; + } + + m_From = from.Name; + m_To = m.Name; + + InvalidateProperties(); + + from.SendMessage("You inscribe the arrow."); + } + else + { + from.SendMessage("That is not a person."); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + writer.Write(m_From); + writer.Write(m_To); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_From = Utility.Intern(reader.ReadString()); + m_To = Utility.Intern(reader.ReadString()); + } + } +} diff --git a/Projects/UOContent/Holiday Stuff/Valentine/2012/Items/HeartShapedBox.cs b/Projects/UOContent/Holiday Stuff/Valentine/2012/Items/HeartShapedBox.cs index 5eb057d06..1f2d176e0 100644 --- a/Projects/UOContent/Holiday Stuff/Valentine/2012/Items/HeartShapedBox.cs +++ b/Projects/UOContent/Holiday Stuff/Valentine/2012/Items/HeartShapedBox.cs @@ -1,52 +1,52 @@ -namespace Server.Items -{ - [Flippable(0x49CA, 0x49CB)] - public class HeartShapedBox : BaseContainer - { - private static int m_DropSound; - - [Constructible] - public HeartShapedBox() - : base(0x49CA) - { - } - - public HeartShapedBox(Serial serial) - : base(serial) - { - } - - public override int DefaultDropSound => m_DropSound; - - public override bool OnDragDropInto(Mobile from, Item item, Point3D p) - { - PrepareSound(from); - return base.OnDragDropInto(from, item, p); - } - - public override bool OnDragDrop(Mobile from, Item dropped) - { - PrepareSound(from); - return base.OnDragDrop(from, dropped); - } - - private static void PrepareSound(Mobile from) - { - m_DropSound = from.Female ? 0x430 : 0x320; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x49CA, 0x49CB)] + public class HeartShapedBox : BaseContainer + { + private static int m_DropSound; + + [Constructible] + public HeartShapedBox() + : base(0x49CA) + { + } + + public HeartShapedBox(Serial serial) + : base(serial) + { + } + + public override int DefaultDropSound => m_DropSound; + + public override bool OnDragDropInto(Mobile from, Item item, Point3D p) + { + PrepareSound(from); + return base.OnDragDropInto(from, item, p); + } + + public override bool OnDragDrop(Mobile from, Item dropped) + { + PrepareSound(from); + return base.OnDragDrop(from, dropped); + } + + private static void PrepareSound(Mobile from) + { + m_DropSound = from.Female ? 0x430 : 0x320; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/AbbatoirAddon.cs b/Projects/UOContent/Items/Addons/AbbatoirAddon.cs index 1ac0f581f..112de07db 100644 --- a/Projects/UOContent/Items/Addons/AbbatoirAddon.cs +++ b/Projects/UOContent/Items/Addons/AbbatoirAddon.cs @@ -1,68 +1,68 @@ -namespace Server.Items -{ - public class AbbatoirAddon : BaseAddon - { - [Constructible] - public AbbatoirAddon() - { - AddComponent(new AddonComponent(0x120E), -1, -1, 0); - AddComponent(new AddonComponent(0x120F), 0, -1, 0); - AddComponent(new AddonComponent(0x1210), 1, -1, 0); - AddComponent(new AddonComponent(0x1215), -1, 0, 0); - AddComponent(new AddonComponent(0x1216), 0, 0, 0); - AddComponent(new AddonComponent(0x1211), 1, 0, 0); - AddComponent(new AddonComponent(0x1214), -1, 1, 0); - AddComponent(new AddonComponent(0x1213), 0, 1, 0); - AddComponent(new AddonComponent(0x1212), 1, 1, 0); - } - - public AbbatoirAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new AbbatoirDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class AbbatoirDeed : BaseAddonDeed - { - [Constructible] - public AbbatoirDeed() - { - } - - public AbbatoirDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new AbbatoirAddon(); - public override int LabelNumber => 1044329; // abbatoir - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AbbatoirAddon : BaseAddon + { + [Constructible] + public AbbatoirAddon() + { + AddComponent(new AddonComponent(0x120E), -1, -1, 0); + AddComponent(new AddonComponent(0x120F), 0, -1, 0); + AddComponent(new AddonComponent(0x1210), 1, -1, 0); + AddComponent(new AddonComponent(0x1215), -1, 0, 0); + AddComponent(new AddonComponent(0x1216), 0, 0, 0); + AddComponent(new AddonComponent(0x1211), 1, 0, 0); + AddComponent(new AddonComponent(0x1214), -1, 1, 0); + AddComponent(new AddonComponent(0x1213), 0, 1, 0); + AddComponent(new AddonComponent(0x1212), 1, 1, 0); + } + + public AbbatoirAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new AbbatoirDeed(); + + 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 class AbbatoirDeed : BaseAddonDeed + { + [Constructible] + public AbbatoirDeed() + { + } + + public AbbatoirDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new AbbatoirAddon(); + public override int LabelNumber => 1044329; // abbatoir + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/AddonComponent.cs b/Projects/UOContent/Items/Addons/AddonComponent.cs index c03d1393a..fdc42ea46 100644 --- a/Projects/UOContent/Items/Addons/AddonComponent.cs +++ b/Projects/UOContent/Items/Addons/AddonComponent.cs @@ -1,259 +1,305 @@ -using Server.Engines.Craft; - -namespace Server.Items -{ - [Anvil] - public class AnvilComponent : AddonComponent - { - [Constructible] - public AnvilComponent(int itemID) : base(itemID) - { - } - - public AnvilComponent(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Forge] - public class ForgeComponent : AddonComponent - { - [Constructible] - public ForgeComponent(int itemID) : base(itemID) - { - } - - public ForgeComponent(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LocalizedAddonComponent : AddonComponent - { - private int m_LabelNumber; - - [Constructible] - public LocalizedAddonComponent(int itemID, int labelNumber) : base(itemID) => m_LabelNumber = labelNumber; - - public LocalizedAddonComponent(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(0); // version - - writer.Write(m_LabelNumber); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_LabelNumber = reader.ReadInt(); - break; - } - } - } - } - - public class AddonComponent : Item, IChoppable - { - private static readonly LightEntry[] m_Entries = - { - new LightEntry(LightType.WestSmall, 1122, 1123, 1124, 1141, 1142, 1143, 1144, 1145, 1146, 2347, 2359, 2360, 2361, - 2362, 2363, 2364, 2387, 2388, 2389, 2390, 2391, 2392), - new LightEntry(LightType.NorthSmall, 1131, 1133, 1134, 1147, 1148, 1149, 1150, 1151, 1152, 2352, 2373, 2374, - 2375, 2376, 2377, 2378, 2401, 2402, 2403, 2404, 2405, 2406), - new LightEntry(LightType.Circle300, 6526, 6538, 6571), - new LightEntry(LightType.Circle150, 5703, 6587) - }; - - [Constructible] - public AddonComponent(int itemID) : base(itemID) - { - Movable = false; - ApplyLightTo(this); - } - - public AddonComponent(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public BaseAddon Addon { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D Offset { get; set; } - - [Hue] - [CommandProperty(AccessLevel.GameMaster)] - public override int Hue - { - get => base.Hue; - set - { - base.Hue = value; - - if (Addon?.ShareHue == true) - Addon.Hue = value; - } - } - - public virtual bool NeedsWall => false; - public virtual Point3D WallPosition => Point3D.Zero; - - public void OnChop(Mobile from) - { - if (Addon != null && from.InRange(GetWorldLocation(), 3)) - Addon.OnChop(from); - else - from.SendLocalizedMessage(500446); // That is too far away. - } - - public override void OnDoubleClick(Mobile from) - { - Addon?.OnComponentUsed(this, from); - } - - public override void OnLocationChange(Point3D old) - { - if (Addon != null) - Addon.Location = new Point3D(X - Offset.X, Y - Offset.Y, Z - Offset.Z); - } - - public override void OnMapChange() - { - if (Addon != null) - Addon.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - Addon?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(Addon); - writer.Write(Offset); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - case 0: - { - Addon = reader.ReadItem() as BaseAddon; - Offset = reader.ReadPoint3D(); - - Addon?.OnComponentLoaded(this); - - ApplyLightTo(this); - - break; - } - } - - if (version < 1 && Weight == 0) - Weight = -1; - } - - public static void ApplyLightTo(Item item) - { - if ((item.ItemData.Flags & TileFlag.LightSource) == 0) - return; // not a light source - - int itemID = item.ItemID; - - for (int i = 0; i < m_Entries.Length; ++i) - { - LightEntry entry = m_Entries[i]; - int[] toMatch = entry.m_ItemIDs; - bool contains = false; - - for (int j = 0; !contains && j < toMatch.Length; ++j) - contains = itemID == toMatch[j]; - - if (contains) - { - item.Light = entry.m_Light; - return; - } - } - } - - private class LightEntry - { - public readonly int[] m_ItemIDs; - public readonly LightType m_Light; - - public LightEntry(LightType light, params int[] itemIDs) - { - m_Light = light; - m_ItemIDs = itemIDs; - } - } - } -} +using Server.Engines.Craft; + +namespace Server.Items +{ + [Anvil] + public class AnvilComponent : AddonComponent + { + [Constructible] + public AnvilComponent(int itemID) : base(itemID) + { + } + + public AnvilComponent(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Forge] + public class ForgeComponent : AddonComponent + { + [Constructible] + public ForgeComponent(int itemID) : base(itemID) + { + } + + public ForgeComponent(Serial serial) : base(serial) + { + } + + 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 class LocalizedAddonComponent : AddonComponent + { + private int m_LabelNumber; + + [Constructible] + public LocalizedAddonComponent(int itemID, int labelNumber) : base(itemID) => m_LabelNumber = labelNumber; + + public LocalizedAddonComponent(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(0); // version + + writer.Write(m_LabelNumber); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_LabelNumber = reader.ReadInt(); + break; + } + } + } + } + + public class AddonComponent : Item, IChoppable + { + private static readonly LightEntry[] m_Entries = + { + new LightEntry( + LightType.WestSmall, + 1122, + 1123, + 1124, + 1141, + 1142, + 1143, + 1144, + 1145, + 1146, + 2347, + 2359, + 2360, + 2361, + 2362, + 2363, + 2364, + 2387, + 2388, + 2389, + 2390, + 2391, + 2392 + ), + new LightEntry( + LightType.NorthSmall, + 1131, + 1133, + 1134, + 1147, + 1148, + 1149, + 1150, + 1151, + 1152, + 2352, + 2373, + 2374, + 2375, + 2376, + 2377, + 2378, + 2401, + 2402, + 2403, + 2404, + 2405, + 2406 + ), + new LightEntry(LightType.Circle300, 6526, 6538, 6571), + new LightEntry(LightType.Circle150, 5703, 6587) + }; + + [Constructible] + public AddonComponent(int itemID) : base(itemID) + { + Movable = false; + ApplyLightTo(this); + } + + public AddonComponent(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public BaseAddon Addon { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D Offset { get; set; } + + [Hue] + [CommandProperty(AccessLevel.GameMaster)] + public override int Hue + { + get => base.Hue; + set + { + base.Hue = value; + + if (Addon?.ShareHue == true) + Addon.Hue = value; + } + } + + public virtual bool NeedsWall => false; + public virtual Point3D WallPosition => Point3D.Zero; + + public void OnChop(Mobile from) + { + if (Addon != null && from.InRange(GetWorldLocation(), 3)) + Addon.OnChop(from); + else + from.SendLocalizedMessage(500446); // That is too far away. + } + + public override void OnDoubleClick(Mobile from) + { + Addon?.OnComponentUsed(this, from); + } + + public override void OnLocationChange(Point3D old) + { + if (Addon != null) + Addon.Location = new Point3D(X - Offset.X, Y - Offset.Y, Z - Offset.Z); + } + + public override void OnMapChange() + { + if (Addon != null) + Addon.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + Addon?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(Addon); + writer.Write(Offset); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + case 0: + { + Addon = reader.ReadItem() as BaseAddon; + Offset = reader.ReadPoint3D(); + + Addon?.OnComponentLoaded(this); + + ApplyLightTo(this); + + break; + } + } + + if (version < 1 && Weight == 0) + Weight = -1; + } + + public static void ApplyLightTo(Item item) + { + if ((item.ItemData.Flags & TileFlag.LightSource) == 0) + return; // not a light source + + var itemID = item.ItemID; + + for (var i = 0; i < m_Entries.Length; ++i) + { + var entry = m_Entries[i]; + var toMatch = entry.m_ItemIDs; + var contains = false; + + for (var j = 0; !contains && j < toMatch.Length; ++j) + contains = itemID == toMatch[j]; + + if (contains) + { + item.Light = entry.m_Light; + return; + } + } + } + + private class LightEntry + { + public readonly int[] m_ItemIDs; + public readonly LightType m_Light; + + public LightEntry(LightType light, params int[] itemIDs) + { + m_Light = light; + m_ItemIDs = itemIDs; + } + } + } +} diff --git a/Projects/UOContent/Items/Addons/AddonContainerComponent.cs b/Projects/UOContent/Items/Addons/AddonContainerComponent.cs index 19e5dd99c..fae148d6b 100644 --- a/Projects/UOContent/Items/Addons/AddonContainerComponent.cs +++ b/Projects/UOContent/Items/Addons/AddonContainerComponent.cs @@ -1,152 +1,152 @@ -using System.Collections.Generic; -using Server.ContextMenus; - -namespace Server.Items -{ - public class AddonContainerComponent : Item, IChoppable - { - [Constructible] - public AddonContainerComponent(int itemID) : base(itemID) - { - Movable = false; - - AddonComponent.ApplyLightTo(this); - } - - public AddonContainerComponent(Serial serial) : base(serial) - { - } - - public virtual bool NeedsWall => false; - public virtual Point3D WallPosition => Point3D.Zero; - - [CommandProperty(AccessLevel.GameMaster)] - public BaseAddonContainer Addon { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D Offset { get; set; } - - [Hue] - [CommandProperty(AccessLevel.GameMaster)] - public override int Hue - { - get => base.Hue; - set - { - base.Hue = value; - - if (Addon?.ShareHue == true) - Addon.Hue = value; - } - } - - public virtual void OnChop(Mobile from) - { - if (Addon != null && from.InRange(GetWorldLocation(), 3)) - Addon.OnChop(from); - else - from.SendLocalizedMessage(500446); // That is too far away. - } - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (Addon != null) - return Addon.OnDragDrop(from, dropped); - - return false; - } - - public override void OnDoubleClick(Mobile from) - { - Addon?.OnComponentUsed(this, from); - } - - public override void OnLocationChange(Point3D old) - { - if (Addon != null) - Addon.Location = new Point3D(X - Offset.X, Y - Offset.Y, Z - Offset.Z); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - Addon?.GetContextMenuEntries(from, list); - } - - public override void OnMapChange() - { - if (Addon != null) - Addon.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - Addon?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(Addon); - writer.Write(Offset); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Addon = reader.ReadItem() as BaseAddonContainer; - Offset = reader.ReadPoint3D(); - - Addon?.OnComponentLoaded(this); - - AddonComponent.ApplyLightTo(this); - } - } - - public class LocalizedContainerComponent : AddonContainerComponent - { - private int m_LabelNumber; - - public LocalizedContainerComponent(int itemID, int labelNumber) : base(itemID) => m_LabelNumber = labelNumber; - - public LocalizedContainerComponent(Serial serial) : base(serial) - { - } - - public override int LabelNumber - { - get - { - if (m_LabelNumber > 0) - return m_LabelNumber; - - return base.LabelNumber; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_LabelNumber); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_LabelNumber = reader.ReadInt(); - } - } -} +using System.Collections.Generic; +using Server.ContextMenus; + +namespace Server.Items +{ + public class AddonContainerComponent : Item, IChoppable + { + [Constructible] + public AddonContainerComponent(int itemID) : base(itemID) + { + Movable = false; + + AddonComponent.ApplyLightTo(this); + } + + public AddonContainerComponent(Serial serial) : base(serial) + { + } + + public virtual bool NeedsWall => false; + public virtual Point3D WallPosition => Point3D.Zero; + + [CommandProperty(AccessLevel.GameMaster)] + public BaseAddonContainer Addon { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D Offset { get; set; } + + [Hue] + [CommandProperty(AccessLevel.GameMaster)] + public override int Hue + { + get => base.Hue; + set + { + base.Hue = value; + + if (Addon?.ShareHue == true) + Addon.Hue = value; + } + } + + public virtual void OnChop(Mobile from) + { + if (Addon != null && from.InRange(GetWorldLocation(), 3)) + Addon.OnChop(from); + else + from.SendLocalizedMessage(500446); // That is too far away. + } + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (Addon != null) + return Addon.OnDragDrop(from, dropped); + + return false; + } + + public override void OnDoubleClick(Mobile from) + { + Addon?.OnComponentUsed(this, from); + } + + public override void OnLocationChange(Point3D old) + { + if (Addon != null) + Addon.Location = new Point3D(X - Offset.X, Y - Offset.Y, Z - Offset.Z); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + Addon?.GetContextMenuEntries(from, list); + } + + public override void OnMapChange() + { + if (Addon != null) + Addon.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + Addon?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(Addon); + writer.Write(Offset); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + Addon = reader.ReadItem() as BaseAddonContainer; + Offset = reader.ReadPoint3D(); + + Addon?.OnComponentLoaded(this); + + AddonComponent.ApplyLightTo(this); + } + } + + public class LocalizedContainerComponent : AddonContainerComponent + { + private int m_LabelNumber; + + public LocalizedContainerComponent(int itemID, int labelNumber) : base(itemID) => m_LabelNumber = labelNumber; + + public LocalizedContainerComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber + { + get + { + if (m_LabelNumber > 0) + return m_LabelNumber; + + return base.LabelNumber; + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_LabelNumber); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_LabelNumber = reader.ReadInt(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/AlchemistTableEastAddon.cs b/Projects/UOContent/Items/Addons/AlchemistTableEastAddon.cs index 98134456e..bd82f4dd9 100644 --- a/Projects/UOContent/Items/Addons/AlchemistTableEastAddon.cs +++ b/Projects/UOContent/Items/Addons/AlchemistTableEastAddon.cs @@ -1,60 +1,60 @@ -namespace Server.Items -{ - public class AlchemistTableEastAddon : BaseAddon - { - [Constructible] - public AlchemistTableEastAddon() - { - AddComponent(new AddonComponent(0x2DD3), 0, 0, 0); - } - - public AlchemistTableEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new AlchemistTableEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class AlchemistTableEastDeed : BaseAddonDeed - { - [Constructible] - public AlchemistTableEastDeed() - { - } - - public AlchemistTableEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new AlchemistTableEastAddon(); - public override int LabelNumber => 1073397; // alchemist table (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AlchemistTableEastAddon : BaseAddon + { + [Constructible] + public AlchemistTableEastAddon() + { + AddComponent(new AddonComponent(0x2DD3), 0, 0, 0); + } + + public AlchemistTableEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new AlchemistTableEastDeed(); + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(1); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } + + public class AlchemistTableEastDeed : BaseAddonDeed + { + [Constructible] + public AlchemistTableEastDeed() + { + } + + public AlchemistTableEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new AlchemistTableEastAddon(); + public override int LabelNumber => 1073397; // alchemist table (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/AlchemistTableSouthAddon.cs b/Projects/UOContent/Items/Addons/AlchemistTableSouthAddon.cs index e55592c39..97555c4df 100644 --- a/Projects/UOContent/Items/Addons/AlchemistTableSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/AlchemistTableSouthAddon.cs @@ -1,60 +1,60 @@ -namespace Server.Items -{ - public class AlchemistTableSouthAddon : BaseAddon - { - [Constructible] - public AlchemistTableSouthAddon() - { - AddComponent(new AddonComponent(0x2DD4), 0, 0, 0); - } - - public AlchemistTableSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new AlchemistTableSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class AlchemistTableSouthDeed : BaseAddonDeed - { - [Constructible] - public AlchemistTableSouthDeed() - { - } - - public AlchemistTableSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new AlchemistTableSouthAddon(); - public override int LabelNumber => 1073396; // alchemist table (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AlchemistTableSouthAddon : BaseAddon + { + [Constructible] + public AlchemistTableSouthAddon() + { + AddComponent(new AddonComponent(0x2DD4), 0, 0, 0); + } + + public AlchemistTableSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new AlchemistTableSouthDeed(); + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(1); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } + + public class AlchemistTableSouthDeed : BaseAddonDeed + { + [Constructible] + public AlchemistTableSouthDeed() + { + } + + public AlchemistTableSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new AlchemistTableSouthAddon(); + public override int LabelNumber => 1073396; // alchemist table (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/AnvilEastAddon.cs b/Projects/UOContent/Items/Addons/AnvilEastAddon.cs index cbe2183a8..4b353372c 100644 --- a/Projects/UOContent/Items/Addons/AnvilEastAddon.cs +++ b/Projects/UOContent/Items/Addons/AnvilEastAddon.cs @@ -1,60 +1,60 @@ -namespace Server.Items -{ - public class AnvilEastAddon : BaseAddon - { - [Constructible] - public AnvilEastAddon() - { - AddComponent(new AnvilComponent(0xFAF), 0, 0, 0); - } - - public AnvilEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new AnvilEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class AnvilEastDeed : BaseAddonDeed - { - [Constructible] - public AnvilEastDeed() - { - } - - public AnvilEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new AnvilEastAddon(); - public override int LabelNumber => 1044333; // anvil (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AnvilEastAddon : BaseAddon + { + [Constructible] + public AnvilEastAddon() + { + AddComponent(new AnvilComponent(0xFAF), 0, 0, 0); + } + + public AnvilEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new AnvilEastDeed(); + + 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 class AnvilEastDeed : BaseAddonDeed + { + [Constructible] + public AnvilEastDeed() + { + } + + public AnvilEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new AnvilEastAddon(); + public override int LabelNumber => 1044333; // anvil (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/AnvilSouthAddon.cs b/Projects/UOContent/Items/Addons/AnvilSouthAddon.cs index 2dcea6921..e86502598 100644 --- a/Projects/UOContent/Items/Addons/AnvilSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/AnvilSouthAddon.cs @@ -1,60 +1,60 @@ -namespace Server.Items -{ - public class AnvilSouthAddon : BaseAddon - { - [Constructible] - public AnvilSouthAddon() - { - AddComponent(new AnvilComponent(0xFB0), 0, 0, 0); - } - - public AnvilSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new AnvilSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class AnvilSouthDeed : BaseAddonDeed - { - [Constructible] - public AnvilSouthDeed() - { - } - - public AnvilSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new AnvilSouthAddon(); - public override int LabelNumber => 1044334; // anvil (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AnvilSouthAddon : BaseAddon + { + [Constructible] + public AnvilSouthAddon() + { + AddComponent(new AnvilComponent(0xFB0), 0, 0, 0); + } + + public AnvilSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new AnvilSouthDeed(); + + 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 class AnvilSouthDeed : BaseAddonDeed + { + [Constructible] + public AnvilSouthDeed() + { + } + + public AnvilSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new AnvilSouthAddon(); + public override int LabelNumber => 1044334; // anvil (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/ArcaneBookshelfEastAddon.cs b/Projects/UOContent/Items/Addons/ArcaneBookshelfEastAddon.cs index a454fc8c8..6be961e9b 100644 --- a/Projects/UOContent/Items/Addons/ArcaneBookshelfEastAddon.cs +++ b/Projects/UOContent/Items/Addons/ArcaneBookshelfEastAddon.cs @@ -1,61 +1,61 @@ -namespace Server.Items -{ - public class ArcaneBookshelfEastAddon : BaseAddon - { - [Constructible] - public ArcaneBookshelfEastAddon() - { - AddComponent(new AddonComponent(0x3084), 0, 0, 0); - AddComponent(new AddonComponent(0x3085), -1, 0, 0); - } - - public ArcaneBookshelfEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new ArcaneBookshelfEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ArcaneBookshelfEastDeed : BaseAddonDeed - { - [Constructible] - public ArcaneBookshelfEastDeed() - { - } - - public ArcaneBookshelfEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new ArcaneBookshelfEastAddon(); - public override int LabelNumber => 1073371; // arcane bookshelf (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ArcaneBookshelfEastAddon : BaseAddon + { + [Constructible] + public ArcaneBookshelfEastAddon() + { + AddComponent(new AddonComponent(0x3084), 0, 0, 0); + AddComponent(new AddonComponent(0x3085), -1, 0, 0); + } + + public ArcaneBookshelfEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new ArcaneBookshelfEastDeed(); + + 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(); + } + } + + public class ArcaneBookshelfEastDeed : BaseAddonDeed + { + [Constructible] + public ArcaneBookshelfEastDeed() + { + } + + public ArcaneBookshelfEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new ArcaneBookshelfEastAddon(); + public override int LabelNumber => 1073371; // arcane bookshelf (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/ArcaneBookshelfSouthAddon.cs b/Projects/UOContent/Items/Addons/ArcaneBookshelfSouthAddon.cs index b0b9f80de..e9476e83e 100644 --- a/Projects/UOContent/Items/Addons/ArcaneBookshelfSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/ArcaneBookshelfSouthAddon.cs @@ -1,61 +1,61 @@ -namespace Server.Items -{ - public class ArcaneBookshelfSouthAddon : BaseAddon - { - [Constructible] - public ArcaneBookshelfSouthAddon() - { - AddComponent(new AddonComponent(0x3087), 0, 0, 0); - AddComponent(new AddonComponent(0x3086), 0, 1, 0); - } - - public ArcaneBookshelfSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new ArcaneBookshelfSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ArcaneBookshelfSouthDeed : BaseAddonDeed - { - [Constructible] - public ArcaneBookshelfSouthDeed() - { - } - - public ArcaneBookshelfSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new ArcaneBookshelfSouthAddon(); - public override int LabelNumber => 1072871; // arcane bookshelf (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ArcaneBookshelfSouthAddon : BaseAddon + { + [Constructible] + public ArcaneBookshelfSouthAddon() + { + AddComponent(new AddonComponent(0x3087), 0, 0, 0); + AddComponent(new AddonComponent(0x3086), 0, 1, 0); + } + + public ArcaneBookshelfSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new ArcaneBookshelfSouthDeed(); + + 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(); + } + } + + public class ArcaneBookshelfSouthDeed : BaseAddonDeed + { + [Constructible] + public ArcaneBookshelfSouthDeed() + { + } + + public ArcaneBookshelfSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new ArcaneBookshelfSouthAddon(); + public override int LabelNumber => 1072871; // arcane bookshelf (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/ArcaneCircleAddon.cs b/Projects/UOContent/Items/Addons/ArcaneCircleAddon.cs index 19fd8c16c..3d903e66a 100644 --- a/Projects/UOContent/Items/Addons/ArcaneCircleAddon.cs +++ b/Projects/UOContent/Items/Addons/ArcaneCircleAddon.cs @@ -1,81 +1,81 @@ -namespace Server.Items -{ - public class ArcaneCircleAddon : BaseAddon - { - [Constructible] - public ArcaneCircleAddon() - { - AddComponent(new AddonComponent(0x3083), -1, -1, 0); - AddComponent(new AddonComponent(0x3080), -1, 0, 0); - AddComponent(new AddonComponent(0x3082), 0, -1, 0); - AddComponent(new AddonComponent(0x3081), 1, -1, 0); - AddComponent(new AddonComponent(0x307D), -1, 1, 0); - AddComponent(new AddonComponent(0x307F), 0, 0, 0); - AddComponent(new AddonComponent(0x307E), 1, 0, 0); - AddComponent(new AddonComponent(0x307C), 0, 1, 0); - AddComponent(new AddonComponent(0x307B), 1, 1, 0); - } - - public ArcaneCircleAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new ArcaneCircleDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - if (version == 0) - ValidationQueue.Add(this); - } - - public void Validate() - { - foreach (AddonComponent c in Components) - if (c.ItemID == 0x3083) - { - c.Offset = new Point3D(-1, -1, 0); - c.MoveToWorld(new Point3D(X + c.Offset.X, Y + c.Offset.Y, Z + c.Offset.Z), Map); - } - } - } - - public class ArcaneCircleDeed : BaseAddonDeed - { - [Constructible] - public ArcaneCircleDeed() - { - } - - public ArcaneCircleDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new ArcaneCircleAddon(); - public override int LabelNumber => 1072703; // arcane circle - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ArcaneCircleAddon : BaseAddon + { + [Constructible] + public ArcaneCircleAddon() + { + AddComponent(new AddonComponent(0x3083), -1, -1, 0); + AddComponent(new AddonComponent(0x3080), -1, 0, 0); + AddComponent(new AddonComponent(0x3082), 0, -1, 0); + AddComponent(new AddonComponent(0x3081), 1, -1, 0); + AddComponent(new AddonComponent(0x307D), -1, 1, 0); + AddComponent(new AddonComponent(0x307F), 0, 0, 0); + AddComponent(new AddonComponent(0x307E), 1, 0, 0); + AddComponent(new AddonComponent(0x307C), 0, 1, 0); + AddComponent(new AddonComponent(0x307B), 1, 1, 0); + } + + public ArcaneCircleAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new ArcaneCircleDeed(); + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(1); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + if (version == 0) + ValidationQueue.Add(this); + } + + public void Validate() + { + foreach (var c in Components) + if (c.ItemID == 0x3083) + { + c.Offset = new Point3D(-1, -1, 0); + c.MoveToWorld(new Point3D(X + c.Offset.X, Y + c.Offset.Y, Z + c.Offset.Z), Map); + } + } + } + + public class ArcaneCircleDeed : BaseAddonDeed + { + [Constructible] + public ArcaneCircleDeed() + { + } + + public ArcaneCircleDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new ArcaneCircleAddon(); + public override int LabelNumber => 1072703; // arcane circle + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/ArcanistStatueEastAddon.cs b/Projects/UOContent/Items/Addons/ArcanistStatueEastAddon.cs index 9853db6fc..d341f75e2 100644 --- a/Projects/UOContent/Items/Addons/ArcanistStatueEastAddon.cs +++ b/Projects/UOContent/Items/Addons/ArcanistStatueEastAddon.cs @@ -1,60 +1,60 @@ -namespace Server.Items -{ - public class ArcanistStatueEastAddon : BaseAddon - { - [Constructible] - public ArcanistStatueEastAddon() - { - AddComponent(new AddonComponent(0x2D0E), 0, 0, 0); - } - - public ArcanistStatueEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new ArcanistStatueEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ArcanistStatueEastDeed : BaseAddonDeed - { - [Constructible] - public ArcanistStatueEastDeed() - { - } - - public ArcanistStatueEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new ArcanistStatueEastAddon(); - public override int LabelNumber => 1072886; // arcanist statue (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ArcanistStatueEastAddon : BaseAddon + { + [Constructible] + public ArcanistStatueEastAddon() + { + AddComponent(new AddonComponent(0x2D0E), 0, 0, 0); + } + + public ArcanistStatueEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new ArcanistStatueEastDeed(); + + 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(); + } + } + + public class ArcanistStatueEastDeed : BaseAddonDeed + { + [Constructible] + public ArcanistStatueEastDeed() + { + } + + public ArcanistStatueEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new ArcanistStatueEastAddon(); + public override int LabelNumber => 1072886; // arcanist statue (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/ArcanistStatueSouthAddon.cs b/Projects/UOContent/Items/Addons/ArcanistStatueSouthAddon.cs index 0c8b684ee..3c1f0f931 100644 --- a/Projects/UOContent/Items/Addons/ArcanistStatueSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/ArcanistStatueSouthAddon.cs @@ -1,60 +1,60 @@ -namespace Server.Items -{ - public class ArcanistStatueSouthAddon : BaseAddon - { - [Constructible] - public ArcanistStatueSouthAddon() - { - AddComponent(new AddonComponent(0x2D0F), 0, 0, 0); - } - - public ArcanistStatueSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new ArcanistStatueSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ArcanistStatueSouthDeed : BaseAddonDeed - { - [Constructible] - public ArcanistStatueSouthDeed() - { - } - - public ArcanistStatueSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new ArcanistStatueSouthAddon(); - public override int LabelNumber => 1072885; // arcanist statue (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ArcanistStatueSouthAddon : BaseAddon + { + [Constructible] + public ArcanistStatueSouthAddon() + { + AddComponent(new AddonComponent(0x2D0F), 0, 0, 0); + } + + public ArcanistStatueSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new ArcanistStatueSouthDeed(); + + 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(); + } + } + + public class ArcanistStatueSouthDeed : BaseAddonDeed + { + [Constructible] + public ArcanistStatueSouthDeed() + { + } + + public ArcanistStatueSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new ArcanistStatueSouthAddon(); + public override int LabelNumber => 1072885; // arcanist statue (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/ArcheryButteAddon.cs b/Projects/UOContent/Items/Addons/ArcheryButteAddon.cs index 98cc76710..0644fc4c3 100644 --- a/Projects/UOContent/Items/Addons/ArcheryButteAddon.cs +++ b/Projects/UOContent/Items/Addons/ArcheryButteAddon.cs @@ -1,327 +1,351 @@ -using System; -using System.Collections.Generic; -using Server.Network; - -namespace Server.Items -{ - [FlippableAttribute(0x100A/*East*/, 0x100B/*South*/)] - public class ArcheryButte : AddonComponent - { - [CommandProperty(AccessLevel.GameMaster)] - public double MinSkill { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public double MaxSkill { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime LastUse { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool FacingEast - { - get => ItemID == 0x100A; - set => ItemID = value ? 0x100A : 0x100B; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Arrows { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Bolts { get; set; } - - [Constructible] - public ArcheryButte(int itemID = 0x100A) : base(itemID) - { - MinSkill = -25.0; - MaxSkill = +25.0; - } - - public ArcheryButte(Serial serial) : base(serial) - { - } - - public override void OnDoubleClick(Mobile from) - { - if ((Arrows > 0 || Bolts > 0) && from.InRange(GetWorldLocation(), 1)) - Gather(from); - else - Fire(from); - } - - public void Gather(Mobile from) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500592); // You gather the arrows and bolts. - - if (Arrows > 0) - from.AddToBackpack(new Arrow(Arrows)); - - if (Bolts > 0) - from.AddToBackpack(new Bolt(Bolts)); - - Arrows = 0; - Bolts = 0; - - m_Entries = null; - } - - private static readonly TimeSpan UseDelay = TimeSpan.FromSeconds(2.0); - - private class ScoreEntry - { - public int Total { get; set; } - - public int Count { get; set; } - - public void Record(int score) - { - Total += score; - Count += 1; - } - } - - private Dictionary m_Entries; - - private ScoreEntry GetEntryFor(Mobile from) - { - if (m_Entries == null) - m_Entries = new Dictionary(); - - if (!m_Entries.TryGetValue(from, out ScoreEntry e)) - m_Entries[from] = e = new ScoreEntry(); - - return e; - } - - public void Fire(Mobile from) - { - if (!(from.Weapon is BaseRanged bow)) - { - SendLocalizedMessageTo(from, 500593); // You must practice with ranged weapons on this. - return; - } - - if (DateTime.UtcNow < LastUse + UseDelay) - return; - - Point3D worldLoc = GetWorldLocation(); - - if (FacingEast ? from.X <= worldLoc.X : from.Y <= worldLoc.Y) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500596); // You would do better to stand in front of the archery butte. - return; - } - - if (FacingEast ? from.Y != worldLoc.Y : from.X != worldLoc.X) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500597); // You aren't properly lined up with the archery butte to get an accurate shot. - return; - } - - if (!from.InRange(worldLoc, 6)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500598); // You are too far away from the archery butte to get an accurate shot. - return; - } - - if (from.InRange(worldLoc, 4)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500599); // You are too close to the target. - return; - } - - Container pack = from.Backpack; - Type ammoType = bow.AmmoType; - - bool isArrow = ammoType == typeof(Arrow); - bool isBolt = ammoType == typeof(Bolt); - bool isKnown = isArrow || isBolt; - - if (pack?.ConsumeTotal(ammoType) != true) - { - if (isArrow) - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500594); // You do not have any arrows with which to practice. - else if (isBolt) - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500595); // You do not have any crossbow bolts with which to practice. - else - SendLocalizedMessageTo(from, 500593); // You must practice with ranged weapons on this. - - return; - } - - LastUse = DateTime.UtcNow; - - from.Direction = from.GetDirectionTo(GetWorldLocation()); - bow.PlaySwingAnimation(from); - from.MovingEffect(this, bow.EffectID, 18, 1, false, false); - - ScoreEntry se = GetEntryFor(from); - - if (!from.CheckSkill(bow.Skill, MinSkill, MaxSkill)) - { - from.PlaySound(bow.MissSound); - - PublicOverheadMessage(MessageType.Regular, 0x3B2, 500604, from.Name); // You miss the target altogether. - - se.Record(0); - - if (se.Count == 1) - PublicOverheadMessage(MessageType.Regular, 0x3B2, 1062719, se.Total.ToString()); - else - PublicOverheadMessage(MessageType.Regular, 0x3B2, 1042683, $"{se.Total}\t{se.Count}"); - - return; - } - - Effects.PlaySound(Location, Map, 0x2B1); - - double rand = Utility.RandomDouble(); - - int area, score, splitScore; - - if (rand < 0.10) - { - area = 0; // bullseye - score = 50; - splitScore = 100; - } - else if (rand < 0.25) - { - area = 1; // inner ring - score = 10; - splitScore = 20; - } - else if (rand < 0.50) - { - area = 2; // middle ring - score = 5; - splitScore = 15; - } - else - { - area = 3; // outer ring - score = 2; - splitScore = 5; - } - - bool split = isKnown && (Arrows + Bolts) * 0.02 > Utility.RandomDouble(); - - if (split) - { - PublicOverheadMessage(MessageType.Regular, 0x3B2, 1010027 + area, - $"{from.Name}\t{(isArrow ? "arrow" : "bolt")}"); - } - else - { - PublicOverheadMessage(MessageType.Regular, 0x3B2, 1010035 + area, from.Name); - - if (isArrow) - ++Arrows; - else if (isBolt) - ++Bolts; - } - - se.Record(split ? splitScore : score); - - if (se.Count == 1) - PublicOverheadMessage(MessageType.Regular, 0x3B2, 1062719, se.Total.ToString()); - else - PublicOverheadMessage(MessageType.Regular, 0x3B2, 1042683, $"{se.Total}\t{se.Count}"); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(MinSkill); - writer.Write(MaxSkill); - writer.Write(Arrows); - writer.Write(Bolts); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - MinSkill = reader.ReadDouble(); - MaxSkill = reader.ReadDouble(); - Arrows = reader.ReadInt(); - Bolts = reader.ReadInt(); - - if (MinSkill == 0.0 && MaxSkill == 30.0) - { - MinSkill = -25.0; - MaxSkill = +25.0; - } - - break; - } - } - } - } - - public class ArcheryButteAddon : BaseAddon - { - public override BaseAddonDeed Deed => new ArcheryButteDeed(); - - [Constructible] - public ArcheryButteAddon() - { - AddComponent(new ArcheryButte(), 0, 0, 0); - } - - public ArcheryButteAddon(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class ArcheryButteDeed : BaseAddonDeed - { - public override BaseAddon Addon => new ArcheryButteAddon(); - public override int LabelNumber => 1024106; // archery butte - - [Constructible] - public ArcheryButteDeed() - { - } - - public ArcheryButteDeed(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using System.Collections.Generic; +using Server.Network; + +namespace Server.Items +{ + [FlippableAttribute(0x100A /*East*/, 0x100B /*South*/)] + public class ArcheryButte : AddonComponent + { + private static readonly TimeSpan UseDelay = TimeSpan.FromSeconds(2.0); + + private Dictionary m_Entries; + + [Constructible] + public ArcheryButte(int itemID = 0x100A) : base(itemID) + { + MinSkill = -25.0; + MaxSkill = +25.0; + } + + public ArcheryButte(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public double MinSkill { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public double MaxSkill { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime LastUse { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool FacingEast + { + get => ItemID == 0x100A; + set => ItemID = value ? 0x100A : 0x100B; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Arrows { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Bolts { get; set; } + + public override void OnDoubleClick(Mobile from) + { + if ((Arrows > 0 || Bolts > 0) && from.InRange(GetWorldLocation(), 1)) + Gather(from); + else + Fire(from); + } + + public void Gather(Mobile from) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500592); // You gather the arrows and bolts. + + if (Arrows > 0) + from.AddToBackpack(new Arrow(Arrows)); + + if (Bolts > 0) + from.AddToBackpack(new Bolt(Bolts)); + + Arrows = 0; + Bolts = 0; + + m_Entries = null; + } + + private ScoreEntry GetEntryFor(Mobile from) + { + if (m_Entries == null) + m_Entries = new Dictionary(); + + if (!m_Entries.TryGetValue(from, out var e)) + m_Entries[from] = e = new ScoreEntry(); + + return e; + } + + public void Fire(Mobile from) + { + if (!(from.Weapon is BaseRanged bow)) + { + SendLocalizedMessageTo(from, 500593); // You must practice with ranged weapons on this. + return; + } + + if (DateTime.UtcNow < LastUse + UseDelay) + return; + + var worldLoc = GetWorldLocation(); + + if (FacingEast ? from.X <= worldLoc.X : from.Y <= worldLoc.Y) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 500596 + ); // You would do better to stand in front of the archery butte. + return; + } + + if (FacingEast ? from.Y != worldLoc.Y : from.X != worldLoc.X) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 500597 + ); // You aren't properly lined up with the archery butte to get an accurate shot. + return; + } + + if (!from.InRange(worldLoc, 6)) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 500598 + ); // You are too far away from the archery butte to get an accurate shot. + return; + } + + if (from.InRange(worldLoc, 4)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500599); // You are too close to the target. + return; + } + + var pack = from.Backpack; + var ammoType = bow.AmmoType; + + var isArrow = ammoType == typeof(Arrow); + var isBolt = ammoType == typeof(Bolt); + var isKnown = isArrow || isBolt; + + if (pack?.ConsumeTotal(ammoType) != true) + { + if (isArrow) + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 500594 + ); // You do not have any arrows with which to practice. + else if (isBolt) + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 500595 + ); // You do not have any crossbow bolts with which to practice. + else + SendLocalizedMessageTo(from, 500593); // You must practice with ranged weapons on this. + + return; + } + + LastUse = DateTime.UtcNow; + + from.Direction = from.GetDirectionTo(GetWorldLocation()); + bow.PlaySwingAnimation(from); + from.MovingEffect(this, bow.EffectID, 18, 1, false, false); + + var se = GetEntryFor(from); + + if (!from.CheckSkill(bow.Skill, MinSkill, MaxSkill)) + { + from.PlaySound(bow.MissSound); + + PublicOverheadMessage(MessageType.Regular, 0x3B2, 500604, from.Name); // You miss the target altogether. + + se.Record(0); + + if (se.Count == 1) + PublicOverheadMessage(MessageType.Regular, 0x3B2, 1062719, se.Total.ToString()); + else + PublicOverheadMessage(MessageType.Regular, 0x3B2, 1042683, $"{se.Total}\t{se.Count}"); + + return; + } + + Effects.PlaySound(Location, Map, 0x2B1); + + var rand = Utility.RandomDouble(); + + int area, score, splitScore; + + if (rand < 0.10) + { + area = 0; // bullseye + score = 50; + splitScore = 100; + } + else if (rand < 0.25) + { + area = 1; // inner ring + score = 10; + splitScore = 20; + } + else if (rand < 0.50) + { + area = 2; // middle ring + score = 5; + splitScore = 15; + } + else + { + area = 3; // outer ring + score = 2; + splitScore = 5; + } + + var split = isKnown && (Arrows + Bolts) * 0.02 > Utility.RandomDouble(); + + if (split) + { + PublicOverheadMessage( + MessageType.Regular, + 0x3B2, + 1010027 + area, + $"{from.Name}\t{(isArrow ? "arrow" : "bolt")}" + ); + } + else + { + PublicOverheadMessage(MessageType.Regular, 0x3B2, 1010035 + area, from.Name); + + if (isArrow) + ++Arrows; + else if (isBolt) + ++Bolts; + } + + se.Record(split ? splitScore : score); + + if (se.Count == 1) + PublicOverheadMessage(MessageType.Regular, 0x3B2, 1062719, se.Total.ToString()); + else + PublicOverheadMessage(MessageType.Regular, 0x3B2, 1042683, $"{se.Total}\t{se.Count}"); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + writer.Write(MinSkill); + writer.Write(MaxSkill); + writer.Write(Arrows); + writer.Write(Bolts); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + MinSkill = reader.ReadDouble(); + MaxSkill = reader.ReadDouble(); + Arrows = reader.ReadInt(); + Bolts = reader.ReadInt(); + + if (MinSkill == 0.0 && MaxSkill == 30.0) + { + MinSkill = -25.0; + MaxSkill = +25.0; + } + + break; + } + } + } + + private class ScoreEntry + { + public int Total { get; set; } + + public int Count { get; set; } + + public void Record(int score) + { + Total += score; + Count += 1; + } + } + } + + public class ArcheryButteAddon : BaseAddon + { + [Constructible] + public ArcheryButteAddon() + { + AddComponent(new ArcheryButte(), 0, 0, 0); + } + + public ArcheryButteAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new ArcheryButteDeed(); + + 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 class ArcheryButteDeed : BaseAddonDeed + { + [Constructible] + public ArcheryButteDeed() + { + } + + public ArcheryButteDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new ArcheryButteAddon(); + public override int LabelNumber => 1024106; // archery butte + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/BallotBox.cs b/Projects/UOContent/Items/Addons/BallotBox.cs index 81da2cd47..0ce3ad8cd 100644 --- a/Projects/UOContent/Items/Addons/BallotBox.cs +++ b/Projects/UOContent/Items/Addons/BallotBox.cs @@ -1,372 +1,375 @@ -using System; -using System.Collections.Generic; -using Server.Gumps; -using Server.Multis; -using Server.Network; -using Server.Prompts; - -namespace Server.Items -{ - public class BallotBox : AddonComponent - { - public static readonly int MaxTopicLines = 6; - - [Constructible] - public BallotBox() : base(0x9A8) - { - Topic = Array.Empty(); - Yes = new List(); - No = new List(); - } - - public BallotBox(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041006; // a ballot box - - public string[] Topic { get; private set; } - - public List Yes { get; private set; } - - public List No { get; private set; } - - public void ClearTopic() - { - Topic = Array.Empty(); - - ClearVotes(); - } - - public void AddLineToTopic(string line) - { - if (Topic.Length >= MaxTopicLines) - return; - - string[] newTopic = new string[Topic.Length + 1]; - Topic.CopyTo(newTopic, 0); - newTopic[Topic.Length] = line; - - Topic = newTopic; - - ClearVotes(); - } - - public void ClearVotes() - { - Yes.Clear(); - No.Clear(); - } - - public bool IsOwner(Mobile from) - { - if (from.AccessLevel >= AccessLevel.GameMaster) - return true; - - BaseHouse house = BaseHouse.FindHouseAt(this); - return house?.IsOwner(from) == true; - } - - public bool HasVoted(Mobile from) => Yes.Contains(from) || No.Contains(from); - - public override bool OnDragDrop(Mobile from, Item dropped) - { - SendLocalizedMessageTo(from, 500369); // I'm a ballot box, not a container! - return false; - } - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - else - { - bool isOwner = IsOwner(from); - from.SendGump(new InternalGump(this, isOwner)); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.WriteEncodedInt(Topic.Length); - - for (int i = 0; i < Topic.Length; i++) - writer.Write(Topic[i]); - - writer.Write(Yes, true); - writer.Write(No, true); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - Topic = new string[reader.ReadEncodedInt()]; - - for (int i = 0; i < Topic.Length; i++) - Topic[i] = reader.ReadString(); - - Yes = reader.ReadStrongMobileList(); - No = reader.ReadStrongMobileList(); - } - - private class InternalGump : Gump - { - private readonly BallotBox m_Box; - - public InternalGump(BallotBox box, bool isOwner) : base(110, 70) - { - m_Box = box; - - AddBackground(0, 0, 400, 350, 0xA28); - - if (isOwner) - AddHtmlLocalized(0, 15, 400, 35, 1011000); //
Ballot Box Owner's Menu
- else - AddHtmlLocalized(0, 15, 400, 35, 1011001); //
Ballot Box -- Vote Here!
- - AddHtmlLocalized(0, 50, 400, 35, 1011002); //
Topic
- - int lineCount = box.Topic.Length; - AddBackground(25, 90, 350, Math.Max(20 * lineCount, 20), 0x1400); - - for (int i = 0; i < lineCount; i++) - { - string line = box.Topic[i]; - - if (!string.IsNullOrEmpty(line)) - AddLabelCropped(30, 90 + i * 20, 340, 20, 0x3E3, line); - } - - int yesCount = box.Yes.Count; - int noCount = box.No.Count; - int totalVotes = yesCount + noCount; - - AddHtmlLocalized(0, 215, 400, 35, 1011003); //
votes
- - if (!isOwner) - AddButton(20, 240, 0xFA5, 0xFA7, 3); - AddHtmlLocalized(55, 242, 25, 35, 1011004); // aye: - AddLabel(78, 242, 0x0, $"[{yesCount}]"); - - if (!isOwner) - AddButton(20, 275, 0xFA5, 0xFA7, 4); - AddHtmlLocalized(55, 277, 25, 35, 1011005); // nay: - AddLabel(78, 277, 0x0, $"[{noCount}]"); - - if (totalVotes > 0) - { - AddImageTiled(130, 242, yesCount * 225 / totalVotes, 10, 0xD6); - AddImageTiled(130, 277, noCount * 225 / totalVotes, 10, 0xD6); - } - - AddButton(45, 305, 0xFA5, 0xFA7, 0); - AddHtmlLocalized(80, 308, 40, 35, 1011008); // done - - if (isOwner) - { - AddButton(120, 305, 0xFA5, 0xFA7, 1); - AddHtmlLocalized(155, 308, 100, 35, 1011006); // change topic - - AddButton(240, 305, 0xFA5, 0xFA7, 2); - AddHtmlLocalized(275, 308, 300, 100, 1011007); // reset votes - } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Box.Deleted || info.ButtonID == 0) - return; - - Mobile from = sender.Mobile; - - if (from.Map != m_Box.Map || !from.InRange(m_Box.GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return; - } - - bool isOwner = m_Box.IsOwner(from); - - switch (info.ButtonID) - { - case 1: // change topic - { - if (isOwner) - { - m_Box.ClearTopic(); - - from.SendLocalizedMessage(500370, "", - 0x35); // Enter a line of text for your ballot, and hit ENTER. Hit ESC after the last line is entered. - from.Prompt = new TopicPrompt(m_Box); - } - - break; - } - case 2: // reset votes - { - if (isOwner) - { - m_Box.ClearVotes(); - from.SendLocalizedMessage(500371); // Votes zeroed out. - } - - goto default; - } - case 3: // aye - { - if (!isOwner) - { - if (m_Box.HasVoted(from)) - { - from.SendLocalizedMessage(500374); // You have already voted on this ballot. - } - else - { - m_Box.Yes.Add(from); - from.SendLocalizedMessage(500373); // Your vote has been registered. - } - } - - goto default; - } - case 4: // nay - { - if (!isOwner) - { - if (m_Box.HasVoted(from)) - { - from.SendLocalizedMessage(500374); // You have already voted on this ballot. - } - else - { - m_Box.No.Add(from); - from.SendLocalizedMessage(500373); // Your vote has been registered. - } - } - - goto default; - } - default: - { - from.SendGump(new InternalGump(m_Box, isOwner)); - break; - } - } - } - } - - private class TopicPrompt : Prompt - { - private readonly BallotBox m_Box; - - public TopicPrompt(BallotBox box) => m_Box = box; - - public override void OnResponse(Mobile from, string text) - { - if (m_Box.Deleted || !m_Box.IsOwner(from)) - return; - - if (from.Map != m_Box.Map || !from.InRange(m_Box.GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return; - } - - m_Box.AddLineToTopic(text.TrimEnd()); - - if (m_Box.Topic.Length < MaxTopicLines) - { - from.SendLocalizedMessage(500377, "", 0x35); // Next line or ESC to finish: - from.Prompt = new TopicPrompt(m_Box); - } - else - { - from.SendLocalizedMessage(500376, "", 0x35); // Ballot entry complete. - from.SendGump(new InternalGump(m_Box, true)); - } - } - - public override void OnCancel(Mobile from) - { - if (m_Box.Deleted || !m_Box.IsOwner(from)) - return; - - if (from.Map != m_Box.Map || !from.InRange(m_Box.GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return; - } - - from.SendLocalizedMessage(500376, "", 0x35); // Ballot entry complete. - from.SendGump(new InternalGump(m_Box, true)); - } - } - } - - public class BallotBoxAddon : BaseAddon - { - public BallotBoxAddon() - { - AddComponent(new BallotBox(), 0, 0, 0); - } - - public BallotBoxAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new BallotBoxDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BallotBoxDeed : BaseAddonDeed - { - [Constructible] - public BallotBoxDeed() - { - } - - public BallotBoxDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new BallotBoxAddon(); - - public override int LabelNumber => 1044327; // ballot box - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} +using System; +using System.Collections.Generic; +using Server.Gumps; +using Server.Multis; +using Server.Network; +using Server.Prompts; + +namespace Server.Items +{ + public class BallotBox : AddonComponent + { + public static readonly int MaxTopicLines = 6; + + [Constructible] + public BallotBox() : base(0x9A8) + { + Topic = Array.Empty(); + Yes = new List(); + No = new List(); + } + + public BallotBox(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041006; // a ballot box + + public string[] Topic { get; private set; } + + public List Yes { get; private set; } + + public List No { get; private set; } + + public void ClearTopic() + { + Topic = Array.Empty(); + + ClearVotes(); + } + + public void AddLineToTopic(string line) + { + if (Topic.Length >= MaxTopicLines) + return; + + var newTopic = new string[Topic.Length + 1]; + Topic.CopyTo(newTopic, 0); + newTopic[Topic.Length] = line; + + Topic = newTopic; + + ClearVotes(); + } + + public void ClearVotes() + { + Yes.Clear(); + No.Clear(); + } + + public bool IsOwner(Mobile from) + { + if (from.AccessLevel >= AccessLevel.GameMaster) + return true; + + var house = BaseHouse.FindHouseAt(this); + return house?.IsOwner(from) == true; + } + + public bool HasVoted(Mobile from) => Yes.Contains(from) || No.Contains(from); + + public override bool OnDragDrop(Mobile from, Item dropped) + { + SendLocalizedMessageTo(from, 500369); // I'm a ballot box, not a container! + return false; + } + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + else + { + var isOwner = IsOwner(from); + from.SendGump(new InternalGump(this, isOwner)); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.WriteEncodedInt(Topic.Length); + + for (var i = 0; i < Topic.Length; i++) + writer.Write(Topic[i]); + + writer.Write(Yes, true); + writer.Write(No, true); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + Topic = new string[reader.ReadEncodedInt()]; + + for (var i = 0; i < Topic.Length; i++) + Topic[i] = reader.ReadString(); + + Yes = reader.ReadStrongMobileList(); + No = reader.ReadStrongMobileList(); + } + + private class InternalGump : Gump + { + private readonly BallotBox m_Box; + + public InternalGump(BallotBox box, bool isOwner) : base(110, 70) + { + m_Box = box; + + AddBackground(0, 0, 400, 350, 0xA28); + + if (isOwner) + AddHtmlLocalized(0, 15, 400, 35, 1011000); //
Ballot Box Owner's Menu
+ else + AddHtmlLocalized(0, 15, 400, 35, 1011001); //
Ballot Box -- Vote Here!
+ + AddHtmlLocalized(0, 50, 400, 35, 1011002); //
Topic
+ + var lineCount = box.Topic.Length; + AddBackground(25, 90, 350, Math.Max(20 * lineCount, 20), 0x1400); + + for (var i = 0; i < lineCount; i++) + { + var line = box.Topic[i]; + + if (!string.IsNullOrEmpty(line)) + AddLabelCropped(30, 90 + i * 20, 340, 20, 0x3E3, line); + } + + var yesCount = box.Yes.Count; + var noCount = box.No.Count; + var totalVotes = yesCount + noCount; + + AddHtmlLocalized(0, 215, 400, 35, 1011003); //
votes
+ + if (!isOwner) + AddButton(20, 240, 0xFA5, 0xFA7, 3); + AddHtmlLocalized(55, 242, 25, 35, 1011004); // aye: + AddLabel(78, 242, 0x0, $"[{yesCount}]"); + + if (!isOwner) + AddButton(20, 275, 0xFA5, 0xFA7, 4); + AddHtmlLocalized(55, 277, 25, 35, 1011005); // nay: + AddLabel(78, 277, 0x0, $"[{noCount}]"); + + if (totalVotes > 0) + { + AddImageTiled(130, 242, yesCount * 225 / totalVotes, 10, 0xD6); + AddImageTiled(130, 277, noCount * 225 / totalVotes, 10, 0xD6); + } + + AddButton(45, 305, 0xFA5, 0xFA7, 0); + AddHtmlLocalized(80, 308, 40, 35, 1011008); // done + + if (isOwner) + { + AddButton(120, 305, 0xFA5, 0xFA7, 1); + AddHtmlLocalized(155, 308, 100, 35, 1011006); // change topic + + AddButton(240, 305, 0xFA5, 0xFA7, 2); + AddHtmlLocalized(275, 308, 300, 100, 1011007); // reset votes + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Box.Deleted || info.ButtonID == 0) + return; + + var from = sender.Mobile; + + if (from.Map != m_Box.Map || !from.InRange(m_Box.GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return; + } + + var isOwner = m_Box.IsOwner(from); + + switch (info.ButtonID) + { + case 1: // change topic + { + if (isOwner) + { + m_Box.ClearTopic(); + + from.SendLocalizedMessage( + 500370, + "", + 0x35 + ); // Enter a line of text for your ballot, and hit ENTER. Hit ESC after the last line is entered. + from.Prompt = new TopicPrompt(m_Box); + } + + break; + } + case 2: // reset votes + { + if (isOwner) + { + m_Box.ClearVotes(); + from.SendLocalizedMessage(500371); // Votes zeroed out. + } + + goto default; + } + case 3: // aye + { + if (!isOwner) + { + if (m_Box.HasVoted(from)) + { + from.SendLocalizedMessage(500374); // You have already voted on this ballot. + } + else + { + m_Box.Yes.Add(from); + from.SendLocalizedMessage(500373); // Your vote has been registered. + } + } + + goto default; + } + case 4: // nay + { + if (!isOwner) + { + if (m_Box.HasVoted(from)) + { + from.SendLocalizedMessage(500374); // You have already voted on this ballot. + } + else + { + m_Box.No.Add(from); + from.SendLocalizedMessage(500373); // Your vote has been registered. + } + } + + goto default; + } + default: + { + from.SendGump(new InternalGump(m_Box, isOwner)); + break; + } + } + } + } + + private class TopicPrompt : Prompt + { + private readonly BallotBox m_Box; + + public TopicPrompt(BallotBox box) => m_Box = box; + + public override void OnResponse(Mobile from, string text) + { + if (m_Box.Deleted || !m_Box.IsOwner(from)) + return; + + if (from.Map != m_Box.Map || !from.InRange(m_Box.GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return; + } + + m_Box.AddLineToTopic(text.TrimEnd()); + + if (m_Box.Topic.Length < MaxTopicLines) + { + from.SendLocalizedMessage(500377, "", 0x35); // Next line or ESC to finish: + from.Prompt = new TopicPrompt(m_Box); + } + else + { + from.SendLocalizedMessage(500376, "", 0x35); // Ballot entry complete. + from.SendGump(new InternalGump(m_Box, true)); + } + } + + public override void OnCancel(Mobile from) + { + if (m_Box.Deleted || !m_Box.IsOwner(from)) + return; + + if (from.Map != m_Box.Map || !from.InRange(m_Box.GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return; + } + + from.SendLocalizedMessage(500376, "", 0x35); // Ballot entry complete. + from.SendGump(new InternalGump(m_Box, true)); + } + } + } + + public class BallotBoxAddon : BaseAddon + { + public BallotBoxAddon() + { + AddComponent(new BallotBox(), 0, 0, 0); + } + + public BallotBoxAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new BallotBoxDeed(); + + 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(); + } + } + + public class BallotBoxDeed : BaseAddonDeed + { + [Constructible] + public BallotBoxDeed() + { + } + + public BallotBoxDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new BallotBoxAddon(); + + public override int LabelNumber => 1044327; // ballot box + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/BaseAddon.cs b/Projects/UOContent/Items/Addons/BaseAddon.cs index d86221711..7d172edee 100644 --- a/Projects/UOContent/Items/Addons/BaseAddon.cs +++ b/Projects/UOContent/Items/Addons/BaseAddon.cs @@ -1,268 +1,269 @@ -using System.Collections.Generic; -using Server.Multis; - -namespace Server.Items -{ - public enum AddonFitResult - { - Valid, - Blocked, - NotInHouse, - DoorTooClose, - NoWall, - DoorsNotClosed - } - - public interface IAddon - { - Item Deed { get; } - - bool CouldFit(IPoint3D p, Map map); - } - - public abstract class BaseAddon : Item, IChoppable, IAddon - { - public BaseAddon() : base(1) - { - Movable = false; - Visible = false; - - Components = new List(); - } - - public BaseAddon(Serial serial) : base(serial) - { - } - - public virtual bool RetainDeedHue => false; - - public virtual BaseAddonDeed Deed => null; - - public List Components { get; private set; } - - public virtual bool ShareHue => true; - - [Hue] - [CommandProperty(AccessLevel.GameMaster)] - public override int Hue - { - get => base.Hue; - set - { - if (base.Hue != value) - { - base.Hue = value; - - if (!Deleted && ShareHue && Components != null) - foreach (AddonComponent c in Components) - c.Hue = value; - } - } - } - - Item IAddon.Deed => Deed; - - public bool CouldFit(IPoint3D p, Map map) - { - BaseHouse h = null; - return CouldFit(p, map, null, ref h) == AddonFitResult.Valid; - } - - public virtual void OnChop(Mobile from) - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (house?.IsOwner(from) == true && house.Addons.Contains(this)) - { - Effects.PlaySound(GetWorldLocation(), Map, 0x3B3); - from.SendLocalizedMessage(500461); // You destroy the item. - - int hue = 0; - - if (RetainDeedHue) - for (int i = 0; hue == 0 && i < Components.Count; ++i) - { - AddonComponent c = Components[i]; - - if (c.Hue != 0) - hue = c.Hue; - } - - Delete(); - - house.Addons.Remove(this); - - BaseAddonDeed deed = Deed; - - if (deed != null) - { - if (RetainDeedHue) - deed.Hue = hue; - - from.AddToBackpack(deed); - } - } - } - - public void AddComponent(AddonComponent c, int x, int y, int z) - { - if (Deleted) - return; - - Components.Add(c); - - c.Addon = this; - c.Offset = new Point3D(x, y, z); - c.MoveToWorld(new Point3D(X + x, Y + y, Z + z), Map); - } - - public virtual AddonFitResult CouldFit(IPoint3D p, Map map, Mobile from, ref BaseHouse house) - { - if (Deleted) - return AddonFitResult.Blocked; - - foreach (AddonComponent c in Components) - { - Point3D p3D = new Point3D(p.X + c.Offset.X, p.Y + c.Offset.Y, p.Z + c.Offset.Z); - - if (!map.CanFit(p3D.X, p3D.Y, p3D.Z, c.ItemData.Height, false, true, c.Z == 0)) - return AddonFitResult.Blocked; - if (!CheckHouse(from, p3D, map, c.ItemData.Height, ref house)) - return AddonFitResult.NotInHouse; - - if (c.NeedsWall) - { - Point3D wall = c.WallPosition; - - if (!IsWall(p3D.X + wall.X, p3D.Y + wall.Y, p3D.Z + wall.Z, map)) - return AddonFitResult.NoWall; - } - } - - List doors = house.Doors; - - for (int i = 0; i < doors.Count; ++i) - { - BaseDoor door = doors[i]; - - Point3D doorLoc = door.GetWorldLocation(); - int doorHeight = door.ItemData.CalcHeight; - - foreach (AddonComponent c in Components) - { - Point3D addonLoc = new Point3D(p.X + c.Offset.X, p.Y + c.Offset.Y, p.Z + c.Offset.Z); - int addonHeight = c.ItemData.CalcHeight; - - if (Utility.InRange(doorLoc, addonLoc, 1) && - (addonLoc.Z == doorLoc.Z || - (addonLoc.Z + addonHeight > doorLoc.Z && doorLoc.Z + doorHeight > addonLoc.Z))) - return AddonFitResult.DoorTooClose; - } - } - - return AddonFitResult.Valid; - } - - public static bool CheckHouse(Mobile from, Point3D p, Map map, int height, ref BaseHouse house) => from == null || BaseHouse.FindHouseAt(p, map, height)?.IsOwner(from) == true; - - public static bool IsWall(int x, int y, int z, Map map) - { - if (map == null) - return false; - - StaticTile[] tiles = map.Tiles.GetStaticTiles(x, y, true); - - for (int i = 0; i < tiles.Length; ++i) - { - StaticTile t = tiles[i]; - ItemData id = TileData.ItemTable[t.ID & TileData.MaxItemValue]; - - if ((id.Flags & TileFlag.Wall) != 0 && z + 16 > t.Z && t.Z + t.Height > z) - return true; - } - - return false; - } - - public virtual void OnComponentLoaded(AddonComponent c) - { - } - - public virtual void OnComponentUsed(AddonComponent c, Mobile from) - { - } - - public override void OnLocationChange(Point3D oldLoc) - { - if (Deleted) - return; - - foreach (AddonComponent c in Components) - c.Location = new Point3D(X + c.Offset.X, Y + c.Offset.Y, Z + c.Offset.Z); - } - - public override void OnMapChange() - { - if (Deleted) - return; - - foreach (AddonComponent c in Components) - c.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - foreach (AddonComponent c in Components) - c.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.WriteItemList(Components); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - case 0: - { - Components = reader.ReadStrongItemList(); - break; - } - } - - if (version < 1 && Weight == 0) - Weight = -1; - } - - private CraftResource m_Resource; - - [CommandProperty(AccessLevel.GameMaster)] - public CraftResource Resource - { - get => m_Resource; - set - { - if (m_Resource != value) - { - m_Resource = value; - Hue = CraftResources.GetHue(m_Resource); - - InvalidateProperties(); - } - } - } - } -} +using System.Collections.Generic; +using Server.Multis; + +namespace Server.Items +{ + public enum AddonFitResult + { + Valid, + Blocked, + NotInHouse, + DoorTooClose, + NoWall, + DoorsNotClosed + } + + public interface IAddon + { + Item Deed { get; } + + bool CouldFit(IPoint3D p, Map map); + } + + public abstract class BaseAddon : Item, IChoppable, IAddon + { + private CraftResource m_Resource; + + public BaseAddon() : base(1) + { + Movable = false; + Visible = false; + + Components = new List(); + } + + public BaseAddon(Serial serial) : base(serial) + { + } + + public virtual bool RetainDeedHue => false; + + public virtual BaseAddonDeed Deed => null; + + public List Components { get; private set; } + + public virtual bool ShareHue => true; + + [Hue] + [CommandProperty(AccessLevel.GameMaster)] + public override int Hue + { + get => base.Hue; + set + { + if (base.Hue != value) + { + base.Hue = value; + + if (!Deleted && ShareHue && Components != null) + foreach (var c in Components) + c.Hue = value; + } + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public CraftResource Resource + { + get => m_Resource; + set + { + if (m_Resource != value) + { + m_Resource = value; + Hue = CraftResources.GetHue(m_Resource); + + InvalidateProperties(); + } + } + } + + Item IAddon.Deed => Deed; + + public bool CouldFit(IPoint3D p, Map map) + { + BaseHouse h = null; + return CouldFit(p, map, null, ref h) == AddonFitResult.Valid; + } + + public virtual void OnChop(Mobile from) + { + var house = BaseHouse.FindHouseAt(this); + + if (house?.IsOwner(from) == true && house.Addons.Contains(this)) + { + Effects.PlaySound(GetWorldLocation(), Map, 0x3B3); + from.SendLocalizedMessage(500461); // You destroy the item. + + var hue = 0; + + if (RetainDeedHue) + for (var i = 0; hue == 0 && i < Components.Count; ++i) + { + var c = Components[i]; + + if (c.Hue != 0) + hue = c.Hue; + } + + Delete(); + + house.Addons.Remove(this); + + var deed = Deed; + + if (deed != null) + { + if (RetainDeedHue) + deed.Hue = hue; + + from.AddToBackpack(deed); + } + } + } + + public void AddComponent(AddonComponent c, int x, int y, int z) + { + if (Deleted) + return; + + Components.Add(c); + + c.Addon = this; + c.Offset = new Point3D(x, y, z); + c.MoveToWorld(new Point3D(X + x, Y + y, Z + z), Map); + } + + public virtual AddonFitResult CouldFit(IPoint3D p, Map map, Mobile from, ref BaseHouse house) + { + if (Deleted) + return AddonFitResult.Blocked; + + foreach (var c in Components) + { + var p3D = new Point3D(p.X + c.Offset.X, p.Y + c.Offset.Y, p.Z + c.Offset.Z); + + if (!map.CanFit(p3D.X, p3D.Y, p3D.Z, c.ItemData.Height, false, true, c.Z == 0)) + return AddonFitResult.Blocked; + if (!CheckHouse(from, p3D, map, c.ItemData.Height, ref house)) + return AddonFitResult.NotInHouse; + + if (c.NeedsWall) + { + var wall = c.WallPosition; + + if (!IsWall(p3D.X + wall.X, p3D.Y + wall.Y, p3D.Z + wall.Z, map)) + return AddonFitResult.NoWall; + } + } + + var doors = house.Doors; + + for (var i = 0; i < doors.Count; ++i) + { + var door = doors[i]; + + var doorLoc = door.GetWorldLocation(); + var doorHeight = door.ItemData.CalcHeight; + + foreach (var c in Components) + { + var addonLoc = new Point3D(p.X + c.Offset.X, p.Y + c.Offset.Y, p.Z + c.Offset.Z); + var addonHeight = c.ItemData.CalcHeight; + + if (Utility.InRange(doorLoc, addonLoc, 1) && + (addonLoc.Z == doorLoc.Z || + addonLoc.Z + addonHeight > doorLoc.Z && doorLoc.Z + doorHeight > addonLoc.Z)) + return AddonFitResult.DoorTooClose; + } + } + + return AddonFitResult.Valid; + } + + public static bool CheckHouse(Mobile from, Point3D p, Map map, int height, ref BaseHouse house) => + from == null || BaseHouse.FindHouseAt(p, map, height)?.IsOwner(from) == true; + + public static bool IsWall(int x, int y, int z, Map map) + { + if (map == null) + return false; + + var tiles = map.Tiles.GetStaticTiles(x, y, true); + + for (var i = 0; i < tiles.Length; ++i) + { + var t = tiles[i]; + var id = TileData.ItemTable[t.ID & TileData.MaxItemValue]; + + if ((id.Flags & TileFlag.Wall) != 0 && z + 16 > t.Z && t.Z + t.Height > z) + return true; + } + + return false; + } + + public virtual void OnComponentLoaded(AddonComponent c) + { + } + + public virtual void OnComponentUsed(AddonComponent c, Mobile from) + { + } + + public override void OnLocationChange(Point3D oldLoc) + { + if (Deleted) + return; + + foreach (var c in Components) + c.Location = new Point3D(X + c.Offset.X, Y + c.Offset.Y, Z + c.Offset.Z); + } + + public override void OnMapChange() + { + if (Deleted) + return; + + foreach (var c in Components) + c.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + foreach (var c in Components) + c.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.WriteItemList(Components); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + case 0: + { + Components = reader.ReadStrongItemList(); + break; + } + } + + if (version < 1 && Weight == 0) + Weight = -1; + } + } +} diff --git a/Projects/UOContent/Items/Addons/BaseAddonContainer.cs b/Projects/UOContent/Items/Addons/BaseAddonContainer.cs index 34f1ade94..919352897 100644 --- a/Projects/UOContent/Items/Addons/BaseAddonContainer.cs +++ b/Projects/UOContent/Items/Addons/BaseAddonContainer.cs @@ -1,296 +1,297 @@ -using System.Collections.Generic; -using Server.Multis; - -namespace Server.Items -{ - public abstract class BaseAddonContainer : BaseContainer, IChoppable, IAddon - { - private CraftResource m_Resource; - - public BaseAddonContainer(int itemID) : base(itemID) - { - AddonComponent.ApplyLightTo(this); - - Components = new List(); - } - - public BaseAddonContainer(Serial serial) : base(serial) - { - } - - public override bool DisplayWeight => false; - - [Hue] - [CommandProperty(AccessLevel.GameMaster)] - public override int Hue - { - get => base.Hue; - set - { - if (base.Hue != value) - { - base.Hue = value; - - if (!Deleted && ShareHue && Components != null) - { - Hue = value; - - foreach (AddonContainerComponent c in Components) - c.Hue = value; - } - } - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public CraftResource Resource - { - get => m_Resource; - set - { - if (m_Resource != value) - { - m_Resource = value; - Hue = CraftResources.GetHue(m_Resource); - - InvalidateProperties(); - } - } - } - - public virtual bool RetainDeedHue => false; - public virtual bool NeedsWall => false; - public virtual bool ShareHue => true; - public virtual Point3D WallPosition => Point3D.Zero; - public virtual BaseAddonContainerDeed Deed => null; - - public List Components { get; private set; } - - Item IAddon.Deed => Deed; - - public bool CouldFit(IPoint3D p, Map map) - { - BaseHouse house = null; - - return CouldFit(p, map, null, ref house) == AddonFitResult.Valid; - } - - public virtual void OnChop(Mobile from) - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (house?.IsOwner(from) == true) - { - if (!IsSecure) - { - Effects.PlaySound(GetWorldLocation(), Map, 0x3B3); - from.SendLocalizedMessage(500461); // You destroy the item. - - int hue = 0; - - if (RetainDeedHue) - for (int i = 0; hue == 0 && i < Components.Count; ++i) - { - AddonContainerComponent c = Components[i]; - - if (c.Hue != 0) - hue = c.Hue; - } - - DropItemsToGround(); - - Delete(); - - house.Addons.Remove(this); - - BaseAddonContainerDeed deed = Deed; - - if (deed != null) - { - deed.Resource = Resource; - - if (RetainDeedHue) - deed.Hue = hue; - - from.AddToBackpack(deed); - } - } - else - { - from.SendLocalizedMessage(1074870); // This item must be unlocked/unsecured before re-deeding it. - } - } - } - - public override void OnLocationChange(Point3D oldLoc) - { - base.OnLocationChange(oldLoc); - - if (Deleted) - return; - - foreach (AddonContainerComponent c in Components) - c.Location = new Point3D(X + c.Offset.X, Y + c.Offset.Y, Z + c.Offset.Z); - } - - public override void OnMapChange() - { - base.OnMapChange(); - - if (Deleted) - return; - - foreach (AddonContainerComponent c in Components) - c.Map = Map; - } - - public override void OnDelete() - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - house?.Addons.Remove(this); - - base.OnDelete(); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (!CraftResources.IsStandard(m_Resource)) - list.Add(CraftResources.GetLocalizationNumber(m_Resource)); - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - foreach (AddonContainerComponent c in Components) - c.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.WriteItemList(Components); - writer.Write((int)m_Resource); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Components = reader.ReadStrongItemList(); - m_Resource = (CraftResource)reader.ReadInt(); - - AddonComponent.ApplyLightTo(this); - } - - public virtual void DropItemsToGround() - { - for (int i = Items.Count - 1; i >= 0; i--) - Items[i].MoveToWorld(Location); - } - - public void AddComponent(AddonContainerComponent c, int x, int y, int z) - { - if (Deleted) - return; - - Components.Add(c); - - c.Addon = this; - c.Offset = new Point3D(x, y, z); - c.MoveToWorld(new Point3D(X + x, Y + y, Z + z), Map); - } - - public AddonFitResult CouldFit(IPoint3D p, Map map, Mobile from, ref BaseHouse house) - { - if (Deleted) - return AddonFitResult.Blocked; - - foreach (AddonContainerComponent c in Components) - { - Point3D p3D = new Point3D(p.X + c.Offset.X, p.Y + c.Offset.Y, p.Z + c.Offset.Z); - - if (!map.CanFit(p3D.X, p3D.Y, p3D.Z, c.ItemData.Height, false, true, c.Z == 0)) - return AddonFitResult.Blocked; - if (!BaseAddon.CheckHouse(from, p3D, map, c.ItemData.Height, ref house)) - return AddonFitResult.NotInHouse; - - if (c.NeedsWall) - { - Point3D wall = c.WallPosition; - - if (!BaseAddon.IsWall(p3D.X + wall.X, p3D.Y + wall.Y, p3D.Z + wall.Z, map)) - return AddonFitResult.NoWall; - } - } - - Point3D p3 = new Point3D(p.X, p.Y, p.Z); - - if (!map.CanFit(p3.X, p3.Y, p3.Z, ItemData.Height, false, true, Z == 0)) - return AddonFitResult.Blocked; - if (!BaseAddon.CheckHouse(from, p3, map, ItemData.Height, ref house)) - return AddonFitResult.NotInHouse; - - if (NeedsWall) - { - Point3D wall = WallPosition; - - if (!BaseAddon.IsWall(p3.X + wall.X, p3.Y + wall.Y, p3.Z + wall.Z, map)) - return AddonFitResult.NoWall; - } - - if (house != null) - { - List doors = house.Doors; - - for (int i = 0; i < doors.Count; ++i) - { - BaseDoor door = doors[i]; - - if (door?.Open == true) - return AddonFitResult.DoorsNotClosed; - - Point3D doorLoc = door.GetWorldLocation(); - int doorHeight = door.ItemData.CalcHeight; - int addonHeight; - - foreach (AddonContainerComponent c in Components) - { - Point3D addonLoc = new Point3D(p.X + c.Offset.X, p.Y + c.Offset.Y, p.Z + c.Offset.Z); - addonHeight = c.ItemData.CalcHeight; - - if (Utility.InRange(doorLoc, addonLoc, 1) && - (addonLoc.Z == doorLoc.Z || - (addonLoc.Z + addonHeight > doorLoc.Z && doorLoc.Z + doorHeight > addonLoc.Z))) - return AddonFitResult.DoorTooClose; - } - - Point3D addonLo = new Point3D(p.X, p.Y, p.Z); - addonHeight = ItemData.CalcHeight; - - if (Utility.InRange(doorLoc, addonLo, 1) && - (addonLo.Z == doorLoc.Z || (addonLo.Z + addonHeight > doorLoc.Z && doorLoc.Z + doorHeight > addonLo.Z))) - return AddonFitResult.DoorTooClose; - } - } - - return AddonFitResult.Valid; - } - - public virtual void OnComponentLoaded(AddonContainerComponent c) - { - } - - public virtual void OnComponentUsed(AddonContainerComponent c, Mobile from) - { - } - } -} +using System.Collections.Generic; +using Server.Multis; + +namespace Server.Items +{ + public abstract class BaseAddonContainer : BaseContainer, IChoppable, IAddon + { + private CraftResource m_Resource; + + public BaseAddonContainer(int itemID) : base(itemID) + { + AddonComponent.ApplyLightTo(this); + + Components = new List(); + } + + public BaseAddonContainer(Serial serial) : base(serial) + { + } + + public override bool DisplayWeight => false; + + [Hue] + [CommandProperty(AccessLevel.GameMaster)] + public override int Hue + { + get => base.Hue; + set + { + if (base.Hue != value) + { + base.Hue = value; + + if (!Deleted && ShareHue && Components != null) + { + Hue = value; + + foreach (var c in Components) + c.Hue = value; + } + } + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public CraftResource Resource + { + get => m_Resource; + set + { + if (m_Resource != value) + { + m_Resource = value; + Hue = CraftResources.GetHue(m_Resource); + + InvalidateProperties(); + } + } + } + + public virtual bool RetainDeedHue => false; + public virtual bool NeedsWall => false; + public virtual bool ShareHue => true; + public virtual Point3D WallPosition => Point3D.Zero; + public virtual BaseAddonContainerDeed Deed => null; + + public List Components { get; private set; } + + Item IAddon.Deed => Deed; + + public bool CouldFit(IPoint3D p, Map map) + { + BaseHouse house = null; + + return CouldFit(p, map, null, ref house) == AddonFitResult.Valid; + } + + public virtual void OnChop(Mobile from) + { + var house = BaseHouse.FindHouseAt(this); + + if (house?.IsOwner(from) == true) + { + if (!IsSecure) + { + Effects.PlaySound(GetWorldLocation(), Map, 0x3B3); + from.SendLocalizedMessage(500461); // You destroy the item. + + var hue = 0; + + if (RetainDeedHue) + for (var i = 0; hue == 0 && i < Components.Count; ++i) + { + var c = Components[i]; + + if (c.Hue != 0) + hue = c.Hue; + } + + DropItemsToGround(); + + Delete(); + + house.Addons.Remove(this); + + var deed = Deed; + + if (deed != null) + { + deed.Resource = Resource; + + if (RetainDeedHue) + deed.Hue = hue; + + from.AddToBackpack(deed); + } + } + else + { + from.SendLocalizedMessage(1074870); // This item must be unlocked/unsecured before re-deeding it. + } + } + } + + public override void OnLocationChange(Point3D oldLoc) + { + base.OnLocationChange(oldLoc); + + if (Deleted) + return; + + foreach (var c in Components) + c.Location = new Point3D(X + c.Offset.X, Y + c.Offset.Y, Z + c.Offset.Z); + } + + public override void OnMapChange() + { + base.OnMapChange(); + + if (Deleted) + return; + + foreach (var c in Components) + c.Map = Map; + } + + public override void OnDelete() + { + var house = BaseHouse.FindHouseAt(this); + + house?.Addons.Remove(this); + + base.OnDelete(); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (!CraftResources.IsStandard(m_Resource)) + list.Add(CraftResources.GetLocalizationNumber(m_Resource)); + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + foreach (var c in Components) + c.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.WriteItemList(Components); + writer.Write((int)m_Resource); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + Components = reader.ReadStrongItemList(); + m_Resource = (CraftResource)reader.ReadInt(); + + AddonComponent.ApplyLightTo(this); + } + + public virtual void DropItemsToGround() + { + for (var i = Items.Count - 1; i >= 0; i--) + Items[i].MoveToWorld(Location); + } + + public void AddComponent(AddonContainerComponent c, int x, int y, int z) + { + if (Deleted) + return; + + Components.Add(c); + + c.Addon = this; + c.Offset = new Point3D(x, y, z); + c.MoveToWorld(new Point3D(X + x, Y + y, Z + z), Map); + } + + public AddonFitResult CouldFit(IPoint3D p, Map map, Mobile from, ref BaseHouse house) + { + if (Deleted) + return AddonFitResult.Blocked; + + foreach (var c in Components) + { + var p3D = new Point3D(p.X + c.Offset.X, p.Y + c.Offset.Y, p.Z + c.Offset.Z); + + if (!map.CanFit(p3D.X, p3D.Y, p3D.Z, c.ItemData.Height, false, true, c.Z == 0)) + return AddonFitResult.Blocked; + if (!BaseAddon.CheckHouse(from, p3D, map, c.ItemData.Height, ref house)) + return AddonFitResult.NotInHouse; + + if (c.NeedsWall) + { + var wall = c.WallPosition; + + if (!BaseAddon.IsWall(p3D.X + wall.X, p3D.Y + wall.Y, p3D.Z + wall.Z, map)) + return AddonFitResult.NoWall; + } + } + + var p3 = new Point3D(p.X, p.Y, p.Z); + + if (!map.CanFit(p3.X, p3.Y, p3.Z, ItemData.Height, false, true, Z == 0)) + return AddonFitResult.Blocked; + if (!BaseAddon.CheckHouse(from, p3, map, ItemData.Height, ref house)) + return AddonFitResult.NotInHouse; + + if (NeedsWall) + { + var wall = WallPosition; + + if (!BaseAddon.IsWall(p3.X + wall.X, p3.Y + wall.Y, p3.Z + wall.Z, map)) + return AddonFitResult.NoWall; + } + + if (house != null) + { + var doors = house.Doors; + + for (var i = 0; i < doors.Count; ++i) + { + var door = doors[i]; + + if (door?.Open == true) + return AddonFitResult.DoorsNotClosed; + + var doorLoc = door.GetWorldLocation(); + var doorHeight = door.ItemData.CalcHeight; + int addonHeight; + + foreach (var c in Components) + { + var addonLoc = new Point3D(p.X + c.Offset.X, p.Y + c.Offset.Y, p.Z + c.Offset.Z); + addonHeight = c.ItemData.CalcHeight; + + if (Utility.InRange(doorLoc, addonLoc, 1) && + (addonLoc.Z == doorLoc.Z || + addonLoc.Z + addonHeight > doorLoc.Z && doorLoc.Z + doorHeight > addonLoc.Z)) + return AddonFitResult.DoorTooClose; + } + + var addonLo = new Point3D(p.X, p.Y, p.Z); + addonHeight = ItemData.CalcHeight; + + if (Utility.InRange(doorLoc, addonLo, 1) && + (addonLo.Z == doorLoc.Z || + addonLo.Z + addonHeight > doorLoc.Z && doorLoc.Z + doorHeight > addonLo.Z)) + return AddonFitResult.DoorTooClose; + } + } + + return AddonFitResult.Valid; + } + + public virtual void OnComponentLoaded(AddonContainerComponent c) + { + } + + public virtual void OnComponentUsed(AddonContainerComponent c, Mobile from) + { + } + } +} diff --git a/Projects/UOContent/Items/Addons/BaseAddonContainerDeed.cs b/Projects/UOContent/Items/Addons/BaseAddonContainerDeed.cs index 07147f378..ddbe3adca 100644 --- a/Projects/UOContent/Items/Addons/BaseAddonContainerDeed.cs +++ b/Projects/UOContent/Items/Addons/BaseAddonContainerDeed.cs @@ -1,159 +1,161 @@ -using System; -using Server.Engines.Craft; -using Server.Multis; -using Server.Spells; -using Server.Targeting; - -namespace Server.Items -{ - [Flippable(0x14F0, 0x14EF)] - public abstract class BaseAddonContainerDeed : Item, ICraftable - { - private CraftResource m_Resource; - - public BaseAddonContainerDeed() : base(0x14F0) - { - Weight = 1.0; - - if (!Core.AOS) - LootType = LootType.Newbied; - } - - public BaseAddonContainerDeed(Serial serial) : base(serial) - { - } - - public abstract BaseAddonContainer Addon { get; } - - [CommandProperty(AccessLevel.GameMaster)] - public CraftResource Resource - { - get => m_Resource; - set - { - if (m_Resource != value) - { - m_Resource = value; - Hue = CraftResources.GetHue(m_Resource); - - InvalidateProperties(); - } - } - } - - public virtual int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, - BaseTool tool, CraftItem craftItem, int resHue) - { - Type resourceType = typeRes ?? craftItem.Resources[0].ItemType; - - Resource = CraftResources.GetFromType(resourceType); - - CraftContext context = craftSystem.GetContext(from); - - if (context?.DoNotColor == true) - Hue = 0; - - return quality; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - // version 1 - writer.Write((int)m_Resource); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Resource = version switch - { - 1 => (CraftResource)reader.ReadInt(), - _ => m_Resource - }; - } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - from.Target = new InternalTarget(this); - else - from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (!CraftResources.IsStandard(m_Resource)) - list.Add(CraftResources.GetLocalizationNumber(m_Resource)); - } - - private class InternalTarget : Target - { - private readonly BaseAddonContainerDeed m_Deed; - - public InternalTarget(BaseAddonContainerDeed deed) : base(-1, true, TargetFlags.None) - { - m_Deed = deed; - - CheckLOS = false; - } - - protected override void OnTarget(Mobile from, object targeted) - { - IPoint3D p = targeted as IPoint3D; - Map map = from.Map; - - if (p == null || map == null || m_Deed.Deleted) - return; - - if (m_Deed.IsChildOf(from.Backpack)) - { - BaseAddonContainer addon = m_Deed.Addon; - addon.Resource = m_Deed.Resource; - - SpellHelper.GetSurfaceTop(ref p); - - BaseHouse house = null; - - AddonFitResult res = addon.CouldFit(p, map, from, ref house); - - if (res == AddonFitResult.Valid) - addon.MoveToWorld(new Point3D(p), map); - else if (res == AddonFitResult.Blocked) - from.SendLocalizedMessage(500269); // You cannot build that there. - else if (res == AddonFitResult.NotInHouse) - from.SendLocalizedMessage(500274); // You can only place this in a house that you own! - else if (res == AddonFitResult.DoorsNotClosed) - from.SendMessage("You must close all house doors before placing this."); - else if (res == AddonFitResult.DoorTooClose) - from.SendLocalizedMessage(500271); // You cannot build near the door. - else if (res == AddonFitResult.NoWall) - from.SendLocalizedMessage(500268); // This object needs to be mounted on something. - - if (res == AddonFitResult.Valid) - { - m_Deed.Delete(); - house.Addons.Add(addon); - house.AddSecure(from, addon); - } - else - { - addon.Delete(); - } - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - } - } -} +using System; +using Server.Engines.Craft; +using Server.Multis; +using Server.Spells; +using Server.Targeting; + +namespace Server.Items +{ + [Flippable(0x14F0, 0x14EF)] + public abstract class BaseAddonContainerDeed : Item, ICraftable + { + private CraftResource m_Resource; + + public BaseAddonContainerDeed() : base(0x14F0) + { + Weight = 1.0; + + if (!Core.AOS) + LootType = LootType.Newbied; + } + + public BaseAddonContainerDeed(Serial serial) : base(serial) + { + } + + public abstract BaseAddonContainer Addon { get; } + + [CommandProperty(AccessLevel.GameMaster)] + public CraftResource Resource + { + get => m_Resource; + set + { + if (m_Resource != value) + { + m_Resource = value; + Hue = CraftResources.GetHue(m_Resource); + + InvalidateProperties(); + } + } + } + + public virtual int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, + BaseTool tool, CraftItem craftItem, int resHue + ) + { + var resourceType = typeRes ?? craftItem.Resources[0].ItemType; + + Resource = CraftResources.GetFromType(resourceType); + + var context = craftSystem.GetContext(from); + + if (context?.DoNotColor == true) + Hue = 0; + + return quality; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + // version 1 + writer.Write((int)m_Resource); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Resource = version switch + { + 1 => (CraftResource)reader.ReadInt(), + _ => m_Resource + }; + } + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + from.Target = new InternalTarget(this); + else + from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (!CraftResources.IsStandard(m_Resource)) + list.Add(CraftResources.GetLocalizationNumber(m_Resource)); + } + + private class InternalTarget : Target + { + private readonly BaseAddonContainerDeed m_Deed; + + public InternalTarget(BaseAddonContainerDeed deed) : base(-1, true, TargetFlags.None) + { + m_Deed = deed; + + CheckLOS = false; + } + + protected override void OnTarget(Mobile from, object targeted) + { + var p = targeted as IPoint3D; + var map = from.Map; + + if (p == null || map == null || m_Deed.Deleted) + return; + + if (m_Deed.IsChildOf(from.Backpack)) + { + var addon = m_Deed.Addon; + addon.Resource = m_Deed.Resource; + + SpellHelper.GetSurfaceTop(ref p); + + BaseHouse house = null; + + var res = addon.CouldFit(p, map, from, ref house); + + if (res == AddonFitResult.Valid) + addon.MoveToWorld(new Point3D(p), map); + else if (res == AddonFitResult.Blocked) + from.SendLocalizedMessage(500269); // You cannot build that there. + else if (res == AddonFitResult.NotInHouse) + from.SendLocalizedMessage(500274); // You can only place this in a house that you own! + else if (res == AddonFitResult.DoorsNotClosed) + from.SendMessage("You must close all house doors before placing this."); + else if (res == AddonFitResult.DoorTooClose) + from.SendLocalizedMessage(500271); // You cannot build near the door. + else if (res == AddonFitResult.NoWall) + from.SendLocalizedMessage(500268); // This object needs to be mounted on something. + + if (res == AddonFitResult.Valid) + { + m_Deed.Delete(); + house.Addons.Add(addon); + house.AddSecure(from, addon); + } + else + { + addon.Delete(); + } + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + } + } +} diff --git a/Projects/UOContent/Items/Addons/BaseAddonDeed.cs b/Projects/UOContent/Items/Addons/BaseAddonDeed.cs index c12146af1..e58f89ac7 100644 --- a/Projects/UOContent/Items/Addons/BaseAddonDeed.cs +++ b/Projects/UOContent/Items/Addons/BaseAddonDeed.cs @@ -1,124 +1,124 @@ -using Server.Multis; -using Server.Spells; -using Server.Targeting; - -namespace Server.Items -{ - [Flippable(0x14F0, 0x14EF)] - public abstract class BaseAddonDeed : Item - { - public BaseAddonDeed() : base(0x14F0) - { - Weight = 1.0; - - if (!Core.AOS) - LootType = LootType.Newbied; - } - - public BaseAddonDeed(Serial serial) : base(serial) - { - } - - public abstract BaseAddon Addon { get; } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 0.0) - Weight = 1.0; - } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - from.Target = new InternalTarget(this); - else - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - - private class InternalTarget : Target - { - private readonly BaseAddonDeed m_Deed; - - public InternalTarget(BaseAddonDeed deed) : base(-1, true, TargetFlags.None) - { - m_Deed = deed; - - CheckLOS = false; - } - - protected override void OnTarget(Mobile from, object targeted) - { - IPoint3D p = targeted as IPoint3D; - Map map = from.Map; - - if (p == null || map == null || m_Deed.Deleted) - return; - - if (m_Deed.IsChildOf(from.Backpack)) - { - BaseAddon addon = m_Deed.Addon; - - SpellHelper.GetSurfaceTop(ref p); - - BaseHouse house = null; - - AddonFitResult res = addon.CouldFit(p, map, from, ref house); - - if (res == AddonFitResult.Valid) - addon.MoveToWorld(new Point3D(p), map); - else if (res == AddonFitResult.Blocked) - from.SendLocalizedMessage(500269); // You cannot build that there. - else if (res == AddonFitResult.NotInHouse) - from.SendLocalizedMessage(500274); // You can only place this in a house that you own! - else if (res == AddonFitResult.DoorTooClose) - from.SendLocalizedMessage(500271); // You cannot build near the door. - else if (res == AddonFitResult.NoWall) - from.SendLocalizedMessage(500268); // This object needs to be mounted on something. - - if (res == AddonFitResult.Valid) - { - m_Deed.Delete(); - house.Addons.Add(addon); - } - else - { - addon.Delete(); - } - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - } - - private CraftResource m_Resource; - - [CommandProperty(AccessLevel.GameMaster)] - public CraftResource Resource - { - get => m_Resource; - set - { - if (m_Resource != value) - { - m_Resource = value; - Hue = CraftResources.GetHue(m_Resource); - - InvalidateProperties(); - } - } - } - } -} \ No newline at end of file +using Server.Multis; +using Server.Spells; +using Server.Targeting; + +namespace Server.Items +{ + [Flippable(0x14F0, 0x14EF)] + public abstract class BaseAddonDeed : Item + { + private CraftResource m_Resource; + + public BaseAddonDeed() : base(0x14F0) + { + Weight = 1.0; + + if (!Core.AOS) + LootType = LootType.Newbied; + } + + public BaseAddonDeed(Serial serial) : base(serial) + { + } + + public abstract BaseAddon Addon { get; } + + [CommandProperty(AccessLevel.GameMaster)] + public CraftResource Resource + { + get => m_Resource; + set + { + if (m_Resource != value) + { + m_Resource = value; + Hue = CraftResources.GetHue(m_Resource); + + InvalidateProperties(); + } + } + } + + 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 (Weight == 0.0) + Weight = 1.0; + } + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + from.Target = new InternalTarget(this); + else + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + + private class InternalTarget : Target + { + private readonly BaseAddonDeed m_Deed; + + public InternalTarget(BaseAddonDeed deed) : base(-1, true, TargetFlags.None) + { + m_Deed = deed; + + CheckLOS = false; + } + + protected override void OnTarget(Mobile from, object targeted) + { + var p = targeted as IPoint3D; + var map = from.Map; + + if (p == null || map == null || m_Deed.Deleted) + return; + + if (m_Deed.IsChildOf(from.Backpack)) + { + var addon = m_Deed.Addon; + + SpellHelper.GetSurfaceTop(ref p); + + BaseHouse house = null; + + var res = addon.CouldFit(p, map, from, ref house); + + if (res == AddonFitResult.Valid) + addon.MoveToWorld(new Point3D(p), map); + else if (res == AddonFitResult.Blocked) + from.SendLocalizedMessage(500269); // You cannot build that there. + else if (res == AddonFitResult.NotInHouse) + from.SendLocalizedMessage(500274); // You can only place this in a house that you own! + else if (res == AddonFitResult.DoorTooClose) + from.SendLocalizedMessage(500271); // You cannot build near the door. + else if (res == AddonFitResult.NoWall) + from.SendLocalizedMessage(500268); // This object needs to be mounted on something. + + if (res == AddonFitResult.Valid) + { + m_Deed.Delete(); + house.Addons.Add(addon); + } + else + { + addon.Delete(); + } + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + } + } +} diff --git a/Projects/UOContent/Items/Addons/BearRugs.cs b/Projects/UOContent/Items/Addons/BearRugs.cs index 6b4c961fe..59c84a1c7 100644 --- a/Projects/UOContent/Items/Addons/BearRugs.cs +++ b/Projects/UOContent/Items/Addons/BearRugs.cs @@ -1,266 +1,266 @@ -namespace Server.Items -{ - public class BrownBearRugEastAddon : BaseAddon - { - [Constructible] - public BrownBearRugEastAddon() - { - AddComponent(new AddonComponent(0x1E40), 1, 1, 0); - AddComponent(new AddonComponent(0x1E41), 1, 0, 0); - AddComponent(new AddonComponent(0x1E42), 1, -1, 0); - AddComponent(new AddonComponent(0x1E43), 0, -1, 0); - AddComponent(new AddonComponent(0x1E44), 0, 0, 0); - AddComponent(new AddonComponent(0x1E45), 0, 1, 0); - AddComponent(new AddonComponent(0x1E46), -1, 1, 0); - AddComponent(new AddonComponent(0x1E47), -1, 0, 0); - AddComponent(new AddonComponent(0x1E48), -1, -1, 0); - } - - public BrownBearRugEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new BrownBearRugEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BrownBearRugEastDeed : BaseAddonDeed - { - [Constructible] - public BrownBearRugEastDeed() - { - } - - public BrownBearRugEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new BrownBearRugEastAddon(); - public override int LabelNumber => 1049397; // a brown bear rug deed facing east - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BrownBearRugSouthAddon : BaseAddon - { - [Constructible] - public BrownBearRugSouthAddon() - { - AddComponent(new AddonComponent(0x1E36), 1, 1, 0); - AddComponent(new AddonComponent(0x1E37), 0, 1, 0); - AddComponent(new AddonComponent(0x1E38), -1, 1, 0); - AddComponent(new AddonComponent(0x1E39), -1, 0, 0); - AddComponent(new AddonComponent(0x1E3A), 0, 0, 0); - AddComponent(new AddonComponent(0x1E3B), 1, 0, 0); - AddComponent(new AddonComponent(0x1E3C), 1, -1, 0); - AddComponent(new AddonComponent(0x1E3D), 0, -1, 0); - AddComponent(new AddonComponent(0x1E3E), -1, -1, 0); - } - - public BrownBearRugSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new BrownBearRugSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BrownBearRugSouthDeed : BaseAddonDeed - { - [Constructible] - public BrownBearRugSouthDeed() - { - } - - public BrownBearRugSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new BrownBearRugSouthAddon(); - public override int LabelNumber => 1049398; // a brown bear rug deed facing south - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PolarBearRugEastAddon : BaseAddon - { - [Constructible] - public PolarBearRugEastAddon() - { - AddComponent(new AddonComponent(0x1E53), 1, 1, 0); - AddComponent(new AddonComponent(0x1E54), 1, 0, 0); - AddComponent(new AddonComponent(0x1E55), 1, -1, 0); - AddComponent(new AddonComponent(0x1E56), 0, -1, 0); - AddComponent(new AddonComponent(0x1E57), 0, 0, 0); - AddComponent(new AddonComponent(0x1E58), 0, 1, 0); - AddComponent(new AddonComponent(0x1E59), -1, 1, 0); - AddComponent(new AddonComponent(0x1E5A), -1, 0, 0); - AddComponent(new AddonComponent(0x1E5B), -1, -1, 0); - } - - public PolarBearRugEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new PolarBearRugEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PolarBearRugEastDeed : BaseAddonDeed - { - [Constructible] - public PolarBearRugEastDeed() - { - } - - public PolarBearRugEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new PolarBearRugEastAddon(); - public override int LabelNumber => 1049399; // a polar bear rug deed facing east - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PolarBearRugSouthAddon : BaseAddon - { - [Constructible] - public PolarBearRugSouthAddon() - { - AddComponent(new AddonComponent(0x1E49), 1, 1, 0); - AddComponent(new AddonComponent(0x1E4A), 0, 1, 0); - AddComponent(new AddonComponent(0x1E4B), -1, 1, 0); - AddComponent(new AddonComponent(0x1E4C), -1, 0, 0); - AddComponent(new AddonComponent(0x1E4D), 0, 0, 0); - AddComponent(new AddonComponent(0x1E4E), 1, 0, 0); - AddComponent(new AddonComponent(0x1E4F), 1, -1, 0); - AddComponent(new AddonComponent(0x1E50), 0, -1, 0); - AddComponent(new AddonComponent(0x1E51), -1, -1, 0); - } - - public PolarBearRugSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new PolarBearRugSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PolarBearRugSouthDeed : BaseAddonDeed - { - [Constructible] - public PolarBearRugSouthDeed() - { - } - - public PolarBearRugSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new PolarBearRugSouthAddon(); - public override int LabelNumber => 1049400; // a polar bear rug deed facing south - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class BrownBearRugEastAddon : BaseAddon + { + [Constructible] + public BrownBearRugEastAddon() + { + AddComponent(new AddonComponent(0x1E40), 1, 1, 0); + AddComponent(new AddonComponent(0x1E41), 1, 0, 0); + AddComponent(new AddonComponent(0x1E42), 1, -1, 0); + AddComponent(new AddonComponent(0x1E43), 0, -1, 0); + AddComponent(new AddonComponent(0x1E44), 0, 0, 0); + AddComponent(new AddonComponent(0x1E45), 0, 1, 0); + AddComponent(new AddonComponent(0x1E46), -1, 1, 0); + AddComponent(new AddonComponent(0x1E47), -1, 0, 0); + AddComponent(new AddonComponent(0x1E48), -1, -1, 0); + } + + public BrownBearRugEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new BrownBearRugEastDeed(); + + 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 class BrownBearRugEastDeed : BaseAddonDeed + { + [Constructible] + public BrownBearRugEastDeed() + { + } + + public BrownBearRugEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new BrownBearRugEastAddon(); + public override int LabelNumber => 1049397; // a brown bear rug deed facing east + + 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 class BrownBearRugSouthAddon : BaseAddon + { + [Constructible] + public BrownBearRugSouthAddon() + { + AddComponent(new AddonComponent(0x1E36), 1, 1, 0); + AddComponent(new AddonComponent(0x1E37), 0, 1, 0); + AddComponent(new AddonComponent(0x1E38), -1, 1, 0); + AddComponent(new AddonComponent(0x1E39), -1, 0, 0); + AddComponent(new AddonComponent(0x1E3A), 0, 0, 0); + AddComponent(new AddonComponent(0x1E3B), 1, 0, 0); + AddComponent(new AddonComponent(0x1E3C), 1, -1, 0); + AddComponent(new AddonComponent(0x1E3D), 0, -1, 0); + AddComponent(new AddonComponent(0x1E3E), -1, -1, 0); + } + + public BrownBearRugSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new BrownBearRugSouthDeed(); + + 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 class BrownBearRugSouthDeed : BaseAddonDeed + { + [Constructible] + public BrownBearRugSouthDeed() + { + } + + public BrownBearRugSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new BrownBearRugSouthAddon(); + public override int LabelNumber => 1049398; // a brown bear rug deed facing south + + 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 class PolarBearRugEastAddon : BaseAddon + { + [Constructible] + public PolarBearRugEastAddon() + { + AddComponent(new AddonComponent(0x1E53), 1, 1, 0); + AddComponent(new AddonComponent(0x1E54), 1, 0, 0); + AddComponent(new AddonComponent(0x1E55), 1, -1, 0); + AddComponent(new AddonComponent(0x1E56), 0, -1, 0); + AddComponent(new AddonComponent(0x1E57), 0, 0, 0); + AddComponent(new AddonComponent(0x1E58), 0, 1, 0); + AddComponent(new AddonComponent(0x1E59), -1, 1, 0); + AddComponent(new AddonComponent(0x1E5A), -1, 0, 0); + AddComponent(new AddonComponent(0x1E5B), -1, -1, 0); + } + + public PolarBearRugEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new PolarBearRugEastDeed(); + + 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 class PolarBearRugEastDeed : BaseAddonDeed + { + [Constructible] + public PolarBearRugEastDeed() + { + } + + public PolarBearRugEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new PolarBearRugEastAddon(); + public override int LabelNumber => 1049399; // a polar bear rug deed facing east + + 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 class PolarBearRugSouthAddon : BaseAddon + { + [Constructible] + public PolarBearRugSouthAddon() + { + AddComponent(new AddonComponent(0x1E49), 1, 1, 0); + AddComponent(new AddonComponent(0x1E4A), 0, 1, 0); + AddComponent(new AddonComponent(0x1E4B), -1, 1, 0); + AddComponent(new AddonComponent(0x1E4C), -1, 0, 0); + AddComponent(new AddonComponent(0x1E4D), 0, 0, 0); + AddComponent(new AddonComponent(0x1E4E), 1, 0, 0); + AddComponent(new AddonComponent(0x1E4F), 1, -1, 0); + AddComponent(new AddonComponent(0x1E50), 0, -1, 0); + AddComponent(new AddonComponent(0x1E51), -1, -1, 0); + } + + public PolarBearRugSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new PolarBearRugSouthDeed(); + + 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 class PolarBearRugSouthDeed : BaseAddonDeed + { + [Constructible] + public PolarBearRugSouthDeed() + { + } + + public PolarBearRugSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new PolarBearRugSouthAddon(); + public override int LabelNumber => 1049400; // a polar bear rug deed facing south + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/BloodPentagram.cs b/Projects/UOContent/Items/Addons/BloodPentagram.cs index 67744d839..fab563bf3 100644 --- a/Projects/UOContent/Items/Addons/BloodPentagram.cs +++ b/Projects/UOContent/Items/Addons/BloodPentagram.cs @@ -1,67 +1,67 @@ -namespace Server.Items -{ - public class BloodPentagram : BaseAddon - { - [Constructible] - public BloodPentagram() - { - AddComponent(new AddonComponent(0x1CF9), 0, 1, 0); - AddComponent(new AddonComponent(0x1CF8), 0, 2, 0); - AddComponent(new AddonComponent(0x1CF7), 0, 3, 0); - AddComponent(new AddonComponent(0x1CF6), 0, 4, 0); - AddComponent(new AddonComponent(0x1CF5), 0, 5, 0); - - AddComponent(new AddonComponent(0x1CFB), 1, 0, 0); - AddComponent(new AddonComponent(0x1CFA), 1, 1, 0); - AddComponent(new AddonComponent(0x1D09), 1, 2, 0); - AddComponent(new AddonComponent(0x1D08), 1, 3, 0); - AddComponent(new AddonComponent(0x1D07), 1, 4, 0); - AddComponent(new AddonComponent(0x1CF4), 1, 5, 0); - - AddComponent(new AddonComponent(0x1CFC), 2, 0, 0); - AddComponent(new AddonComponent(0x1D0A), 2, 1, 0); - AddComponent(new AddonComponent(0x1D11), 2, 2, 0); - AddComponent(new AddonComponent(0x1D10), 2, 3, 0); - AddComponent(new AddonComponent(0x1D06), 2, 4, 0); - AddComponent(new AddonComponent(0x1CF3), 2, 5, 0); - - AddComponent(new AddonComponent(0x1CFD), 3, 0, 0); - AddComponent(new AddonComponent(0x1D0B), 3, 1, 0); - AddComponent(new AddonComponent(0x1D12), 3, 2, 0); - AddComponent(new AddonComponent(0x1D0F), 3, 3, 0); - AddComponent(new AddonComponent(0x1D05), 3, 4, 0); - AddComponent(new AddonComponent(0x1CF2), 3, 5, 0); - - AddComponent(new AddonComponent(0x1CFE), 4, 0, 0); - AddComponent(new AddonComponent(0x1D0C), 4, 1, 0); - AddComponent(new AddonComponent(0x1D0D), 4, 2, 0); - AddComponent(new AddonComponent(0x1D0E), 4, 3, 0); - AddComponent(new AddonComponent(0x1D04), 4, 4, 0); - AddComponent(new AddonComponent(0x1CF1), 4, 5, 0); - - AddComponent(new AddonComponent(0x1CFF), 5, 0, 0); - AddComponent(new AddonComponent(0x1D00), 5, 1, 0); - AddComponent(new AddonComponent(0x1D01), 5, 2, 0); - AddComponent(new AddonComponent(0x1D02), 5, 3, 0); - AddComponent(new AddonComponent(0x1D03), 5, 4, 0); - } - - public BloodPentagram(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class BloodPentagram : BaseAddon + { + [Constructible] + public BloodPentagram() + { + AddComponent(new AddonComponent(0x1CF9), 0, 1, 0); + AddComponent(new AddonComponent(0x1CF8), 0, 2, 0); + AddComponent(new AddonComponent(0x1CF7), 0, 3, 0); + AddComponent(new AddonComponent(0x1CF6), 0, 4, 0); + AddComponent(new AddonComponent(0x1CF5), 0, 5, 0); + + AddComponent(new AddonComponent(0x1CFB), 1, 0, 0); + AddComponent(new AddonComponent(0x1CFA), 1, 1, 0); + AddComponent(new AddonComponent(0x1D09), 1, 2, 0); + AddComponent(new AddonComponent(0x1D08), 1, 3, 0); + AddComponent(new AddonComponent(0x1D07), 1, 4, 0); + AddComponent(new AddonComponent(0x1CF4), 1, 5, 0); + + AddComponent(new AddonComponent(0x1CFC), 2, 0, 0); + AddComponent(new AddonComponent(0x1D0A), 2, 1, 0); + AddComponent(new AddonComponent(0x1D11), 2, 2, 0); + AddComponent(new AddonComponent(0x1D10), 2, 3, 0); + AddComponent(new AddonComponent(0x1D06), 2, 4, 0); + AddComponent(new AddonComponent(0x1CF3), 2, 5, 0); + + AddComponent(new AddonComponent(0x1CFD), 3, 0, 0); + AddComponent(new AddonComponent(0x1D0B), 3, 1, 0); + AddComponent(new AddonComponent(0x1D12), 3, 2, 0); + AddComponent(new AddonComponent(0x1D0F), 3, 3, 0); + AddComponent(new AddonComponent(0x1D05), 3, 4, 0); + AddComponent(new AddonComponent(0x1CF2), 3, 5, 0); + + AddComponent(new AddonComponent(0x1CFE), 4, 0, 0); + AddComponent(new AddonComponent(0x1D0C), 4, 1, 0); + AddComponent(new AddonComponent(0x1D0D), 4, 2, 0); + AddComponent(new AddonComponent(0x1D0E), 4, 3, 0); + AddComponent(new AddonComponent(0x1D04), 4, 4, 0); + AddComponent(new AddonComponent(0x1CF1), 4, 5, 0); + + AddComponent(new AddonComponent(0x1CFF), 5, 0, 0); + AddComponent(new AddonComponent(0x1D00), 5, 1, 0); + AddComponent(new AddonComponent(0x1D01), 5, 2, 0); + AddComponent(new AddonComponent(0x1D02), 5, 3, 0); + AddComponent(new AddonComponent(0x1D03), 5, 4, 0); + } + + public BloodPentagram(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/DartBoard.cs b/Projects/UOContent/Items/Addons/DartBoard.cs index 191dfb019..fa4b854f0 100644 --- a/Projects/UOContent/Items/Addons/DartBoard.cs +++ b/Projects/UOContent/Items/Addons/DartBoard.cs @@ -1,209 +1,209 @@ -using Server.Network; - -namespace Server.Items -{ - public class DartBoard : AddonComponent - { - [Constructible] - public DartBoard(bool east = true) : base(east ? 0x1E2F : 0x1E2E) - { - } - - public DartBoard(Serial serial) : base(serial) - { - } - - public override bool NeedsWall => true; - public override Point3D WallPosition => East ? new Point3D(-1, 0, 0) : new Point3D(0, -1, 0); - - public bool East => ItemID == 0x1E2F; - - public override void OnDoubleClick(Mobile from) - { - Direction dir; - if (from.Location != Location) - dir = from.GetDirectionTo(this); - else if (East) - dir = Direction.West; - else - dir = Direction.North; - - from.Direction = dir; - - bool canThrow; - - if (!from.InRange(this, 4) || !from.InLOS(this)) - canThrow = false; - else if (East) - canThrow = dir == Direction.Left || dir == Direction.West || dir == Direction.Up; - else - canThrow = dir == Direction.Up || dir == Direction.North || dir == Direction.Right; - - if (canThrow) - Throw(from); - else - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - - public void Throw(Mobile from) - { - if (!(from.Weapon is BaseKnife knife)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500751); // Try holding a knife... - return; - } - - from.Animate(from.Mounted ? 26 : 9, 7, 1, true, false, 0); - from.MovingEffect(this, knife.ItemID, 7, 1, false, false); - from.PlaySound(0x238); - - double rand = Utility.RandomDouble(); - - int message; - if (rand < 0.05) - message = 500752; // BULLSEYE! 50 Points! - else if (rand < 0.20) - message = 500753; // Just missed the center! 20 points. - else if (rand < 0.45) - message = 500754; // 10 point shot. - else if (rand < 0.70) - message = 500755; // 5 pointer. - else if (rand < 0.85) - message = 500756; // 1 point. Bad throw. - else - message = 500757; // Missed. - - PublicOverheadMessage(MessageType.Regular, 0x3B2, message); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class DartBoardEastAddon : BaseAddon - { - public DartBoardEastAddon() - { - AddComponent(new DartBoard(), 0, 0, 0); - } - - public DartBoardEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new DartBoardEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class DartBoardEastDeed : BaseAddonDeed - { - [Constructible] - public DartBoardEastDeed() - { - } - - public DartBoardEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new DartBoardEastAddon(); - - public override int LabelNumber => 1044326; // dartboard (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class DartBoardSouthAddon : BaseAddon - { - public DartBoardSouthAddon() - { - AddComponent(new DartBoard(false), 0, 0, 0); - } - - public DartBoardSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new DartBoardSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class DartBoardSouthDeed : BaseAddonDeed - { - [Constructible] - public DartBoardSouthDeed() - { - } - - public DartBoardSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new DartBoardSouthAddon(); - - public override int LabelNumber => 1044325; // dartboard (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} +using Server.Network; + +namespace Server.Items +{ + public class DartBoard : AddonComponent + { + [Constructible] + public DartBoard(bool east = true) : base(east ? 0x1E2F : 0x1E2E) + { + } + + public DartBoard(Serial serial) : base(serial) + { + } + + public override bool NeedsWall => true; + public override Point3D WallPosition => East ? new Point3D(-1, 0, 0) : new Point3D(0, -1, 0); + + public bool East => ItemID == 0x1E2F; + + public override void OnDoubleClick(Mobile from) + { + Direction dir; + if (from.Location != Location) + dir = from.GetDirectionTo(this); + else if (East) + dir = Direction.West; + else + dir = Direction.North; + + from.Direction = dir; + + bool canThrow; + + if (!from.InRange(this, 4) || !from.InLOS(this)) + canThrow = false; + else if (East) + canThrow = dir == Direction.Left || dir == Direction.West || dir == Direction.Up; + else + canThrow = dir == Direction.Up || dir == Direction.North || dir == Direction.Right; + + if (canThrow) + Throw(from); + else + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + + public void Throw(Mobile from) + { + if (!(from.Weapon is BaseKnife knife)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500751); // Try holding a knife... + return; + } + + from.Animate(from.Mounted ? 26 : 9, 7, 1, true, false, 0); + from.MovingEffect(this, knife.ItemID, 7, 1, false, false); + from.PlaySound(0x238); + + var rand = Utility.RandomDouble(); + + int message; + if (rand < 0.05) + message = 500752; // BULLSEYE! 50 Points! + else if (rand < 0.20) + message = 500753; // Just missed the center! 20 points. + else if (rand < 0.45) + message = 500754; // 10 point shot. + else if (rand < 0.70) + message = 500755; // 5 pointer. + else if (rand < 0.85) + message = 500756; // 1 point. Bad throw. + else + message = 500757; // Missed. + + PublicOverheadMessage(MessageType.Regular, 0x3B2, message); + } + + 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(); + } + } + + public class DartBoardEastAddon : BaseAddon + { + public DartBoardEastAddon() + { + AddComponent(new DartBoard(), 0, 0, 0); + } + + public DartBoardEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new DartBoardEastDeed(); + + 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(); + } + } + + public class DartBoardEastDeed : BaseAddonDeed + { + [Constructible] + public DartBoardEastDeed() + { + } + + public DartBoardEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new DartBoardEastAddon(); + + public override int LabelNumber => 1044326; // dartboard (east) + + 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(); + } + } + + public class DartBoardSouthAddon : BaseAddon + { + public DartBoardSouthAddon() + { + AddComponent(new DartBoard(false), 0, 0, 0); + } + + public DartBoardSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new DartBoardSouthDeed(); + + 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(); + } + } + + public class DartBoardSouthDeed : BaseAddonDeed + { + [Constructible] + public DartBoardSouthDeed() + { + } + + public DartBoardSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new DartBoardSouthAddon(); + + public override int LabelNumber => 1044325; // dartboard (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/ElvenBedEastAddon.cs b/Projects/UOContent/Items/Addons/ElvenBedEastAddon.cs index c83479767..4e5510489 100644 --- a/Projects/UOContent/Items/Addons/ElvenBedEastAddon.cs +++ b/Projects/UOContent/Items/Addons/ElvenBedEastAddon.cs @@ -1,61 +1,61 @@ -namespace Server.Items -{ - public class ElvenBedEastAddon : BaseAddon - { - [Constructible] - public ElvenBedEastAddon() - { - AddComponent(new AddonComponent(0x304D), 0, 0, 0); - AddComponent(new AddonComponent(0x304C), 1, 0, 0); - } - - public ElvenBedEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new ElvenBedEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ElvenBedEastDeed : BaseAddonDeed - { - [Constructible] - public ElvenBedEastDeed() - { - } - - public ElvenBedEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new ElvenBedEastAddon(); - public override int LabelNumber => 1072861; // elven bed (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ElvenBedEastAddon : BaseAddon + { + [Constructible] + public ElvenBedEastAddon() + { + AddComponent(new AddonComponent(0x304D), 0, 0, 0); + AddComponent(new AddonComponent(0x304C), 1, 0, 0); + } + + public ElvenBedEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new ElvenBedEastDeed(); + + 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(); + } + } + + public class ElvenBedEastDeed : BaseAddonDeed + { + [Constructible] + public ElvenBedEastDeed() + { + } + + public ElvenBedEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new ElvenBedEastAddon(); + public override int LabelNumber => 1072861; // elven bed (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/ElvenBedSouthAddon.cs b/Projects/UOContent/Items/Addons/ElvenBedSouthAddon.cs index 49f445a0a..8ad0f8e97 100644 --- a/Projects/UOContent/Items/Addons/ElvenBedSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/ElvenBedSouthAddon.cs @@ -1,61 +1,61 @@ -namespace Server.Items -{ - public class ElvenBedSouthAddon : BaseAddon - { - [Constructible] - public ElvenBedSouthAddon() - { - AddComponent(new AddonComponent(0x3050), 0, 0, 0); - AddComponent(new AddonComponent(0x3051), 0, -1, 0); - } - - public ElvenBedSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new ElvenBedSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ElvenBedSouthDeed : BaseAddonDeed - { - [Constructible] - public ElvenBedSouthDeed() - { - } - - public ElvenBedSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new ElvenBedSouthAddon(); - public override int LabelNumber => 1072860; // elven bed (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ElvenBedSouthAddon : BaseAddon + { + [Constructible] + public ElvenBedSouthAddon() + { + AddComponent(new AddonComponent(0x3050), 0, 0, 0); + AddComponent(new AddonComponent(0x3051), 0, -1, 0); + } + + public ElvenBedSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new ElvenBedSouthDeed(); + + 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(); + } + } + + public class ElvenBedSouthDeed : BaseAddonDeed + { + [Constructible] + public ElvenBedSouthDeed() + { + } + + public ElvenBedSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new ElvenBedSouthAddon(); + public override int LabelNumber => 1072860; // elven bed (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/ElvenDresserEastAddon.cs b/Projects/UOContent/Items/Addons/ElvenDresserEastAddon.cs index ab5d8ac51..5558df371 100644 --- a/Projects/UOContent/Items/Addons/ElvenDresserEastAddon.cs +++ b/Projects/UOContent/Items/Addons/ElvenDresserEastAddon.cs @@ -1,61 +1,61 @@ -namespace Server.Items -{ - public class ElvenDresserEastAddon : BaseAddon - { - [Constructible] - public ElvenDresserEastAddon() - { - AddComponent(new AddonComponent(0x30E4), 0, 0, 0); - AddComponent(new AddonComponent(0x30E3), 0, -1, 0); - } - - public ElvenDresserEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new ElvenDresserEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ElvenDresserEastDeed : BaseAddonDeed - { - [Constructible] - public ElvenDresserEastDeed() - { - } - - public ElvenDresserEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new ElvenDresserEastAddon(); - public override int LabelNumber => 1073388; // elven dresser (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ElvenDresserEastAddon : BaseAddon + { + [Constructible] + public ElvenDresserEastAddon() + { + AddComponent(new AddonComponent(0x30E4), 0, 0, 0); + AddComponent(new AddonComponent(0x30E3), 0, -1, 0); + } + + public ElvenDresserEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new ElvenDresserEastDeed(); + + 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(); + } + } + + public class ElvenDresserEastDeed : BaseAddonDeed + { + [Constructible] + public ElvenDresserEastDeed() + { + } + + public ElvenDresserEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new ElvenDresserEastAddon(); + public override int LabelNumber => 1073388; // elven dresser (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/ElvenDresserSouthAddon.cs b/Projects/UOContent/Items/Addons/ElvenDresserSouthAddon.cs index 3de551c3d..fd7efa496 100644 --- a/Projects/UOContent/Items/Addons/ElvenDresserSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/ElvenDresserSouthAddon.cs @@ -1,61 +1,61 @@ -namespace Server.Items -{ - public class ElvenDresserSouthAddon : BaseAddon - { - [Constructible] - public ElvenDresserSouthAddon() - { - AddComponent(new AddonComponent(0x30E5), 0, 0, 0); - AddComponent(new AddonComponent(0x30E6), 1, 0, 0); - } - - public ElvenDresserSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new ElvenDresserSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ElvenDresserSouthDeed : BaseAddonDeed - { - [Constructible] - public ElvenDresserSouthDeed() - { - } - - public ElvenDresserSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new ElvenDresserSouthAddon(); - public override int LabelNumber => 1072864; // elven dresser (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ElvenDresserSouthAddon : BaseAddon + { + [Constructible] + public ElvenDresserSouthAddon() + { + AddComponent(new AddonComponent(0x30E5), 0, 0, 0); + AddComponent(new AddonComponent(0x30E6), 1, 0, 0); + } + + public ElvenDresserSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new ElvenDresserSouthDeed(); + + 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(); + } + } + + public class ElvenDresserSouthDeed : BaseAddonDeed + { + [Constructible] + public ElvenDresserSouthDeed() + { + } + + public ElvenDresserSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new ElvenDresserSouthAddon(); + public override int LabelNumber => 1072864; // elven dresser (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/ElvenForgeAddon.cs b/Projects/UOContent/Items/Addons/ElvenForgeAddon.cs index a3cce38df..35dfef3ed 100644 --- a/Projects/UOContent/Items/Addons/ElvenForgeAddon.cs +++ b/Projects/UOContent/Items/Addons/ElvenForgeAddon.cs @@ -1,60 +1,60 @@ -namespace Server.Items -{ - public class ElvenForgeAddon : BaseAddon - { - [Constructible] - public ElvenForgeAddon() - { - AddComponent(new AddonComponent(0x2DD8), 0, 0, 0); - } - - public ElvenForgeAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new ElvenForgeDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ElvenForgeDeed : BaseAddonDeed - { - [Constructible] - public ElvenForgeDeed() - { - } - - public ElvenForgeDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new ElvenForgeAddon(); - public override int LabelNumber => 1072875; // squirrel statue (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ElvenForgeAddon : BaseAddon + { + [Constructible] + public ElvenForgeAddon() + { + AddComponent(new AddonComponent(0x2DD8), 0, 0, 0); + } + + public ElvenForgeAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new ElvenForgeDeed(); + + 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(); + } + } + + public class ElvenForgeDeed : BaseAddonDeed + { + [Constructible] + public ElvenForgeDeed() + { + } + + public ElvenForgeDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new ElvenForgeAddon(); + public override int LabelNumber => 1072875; // squirrel statue (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/ElvenLoveseatEastAddon.cs b/Projects/UOContent/Items/Addons/ElvenLoveseatEastAddon.cs index 3817a6408..132b325d8 100644 --- a/Projects/UOContent/Items/Addons/ElvenLoveseatEastAddon.cs +++ b/Projects/UOContent/Items/Addons/ElvenLoveseatEastAddon.cs @@ -1,61 +1,61 @@ -namespace Server.Items -{ - public class ElvenLoveseatEastAddon : BaseAddon - { - [Constructible] - public ElvenLoveseatEastAddon() - { - AddComponent(new AddonComponent(0x3089), 0, 0, 0); - AddComponent(new AddonComponent(0x3088), 1, 0, 0); - } - - public ElvenLoveseatEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new ElvenLoveseatEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ElvenLoveseatEastDeed : BaseAddonDeed - { - [Constructible] - public ElvenLoveseatEastDeed() - { - } - - public ElvenLoveseatEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new ElvenLoveseatEastAddon(); - public override int LabelNumber => 1073372; // elven loveseat (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ElvenLoveseatEastAddon : BaseAddon + { + [Constructible] + public ElvenLoveseatEastAddon() + { + AddComponent(new AddonComponent(0x3089), 0, 0, 0); + AddComponent(new AddonComponent(0x3088), 1, 0, 0); + } + + public ElvenLoveseatEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new ElvenLoveseatEastDeed(); + + 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(); + } + } + + public class ElvenLoveseatEastDeed : BaseAddonDeed + { + [Constructible] + public ElvenLoveseatEastDeed() + { + } + + public ElvenLoveseatEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new ElvenLoveseatEastAddon(); + public override int LabelNumber => 1073372; // elven loveseat (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/ElvenLoveseatSouthAddon.cs b/Projects/UOContent/Items/Addons/ElvenLoveseatSouthAddon.cs index 2e5f6e71d..2f2304ac0 100644 --- a/Projects/UOContent/Items/Addons/ElvenLoveseatSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/ElvenLoveseatSouthAddon.cs @@ -1,61 +1,61 @@ -namespace Server.Items -{ - public class ElvenLoveseatSouthAddon : BaseAddon - { - [Constructible] - public ElvenLoveseatSouthAddon() - { - AddComponent(new AddonComponent(0x308A), 0, 0, 0); - AddComponent(new AddonComponent(0x308B), 0, -1, 0); - } - - public ElvenLoveseatSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new ElvenLoveseatSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ElvenLoveseatSouthDeed : BaseAddonDeed - { - [Constructible] - public ElvenLoveseatSouthDeed() - { - } - - public ElvenLoveseatSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new ElvenLoveseatSouthAddon(); - public override int LabelNumber => 1072867; // elven loveseat (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ElvenLoveseatSouthAddon : BaseAddon + { + [Constructible] + public ElvenLoveseatSouthAddon() + { + AddComponent(new AddonComponent(0x308A), 0, 0, 0); + AddComponent(new AddonComponent(0x308B), 0, -1, 0); + } + + public ElvenLoveseatSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new ElvenLoveseatSouthDeed(); + + 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(); + } + } + + public class ElvenLoveseatSouthDeed : BaseAddonDeed + { + [Constructible] + public ElvenLoveseatSouthDeed() + { + } + + public ElvenLoveseatSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new ElvenLoveseatSouthAddon(); + public override int LabelNumber => 1072867; // elven loveseat (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/ElvenSpinningwheelEastAddon.cs b/Projects/UOContent/Items/Addons/ElvenSpinningwheelEastAddon.cs index c925398b1..7d170d716 100644 --- a/Projects/UOContent/Items/Addons/ElvenSpinningwheelEastAddon.cs +++ b/Projects/UOContent/Items/Addons/ElvenSpinningwheelEastAddon.cs @@ -1,137 +1,138 @@ -using System; - -namespace Server.Items -{ - public class ElvenSpinningwheelEastAddon : BaseAddon, ISpinningWheel - { - private Timer m_Timer; - - [Constructible] - public ElvenSpinningwheelEastAddon() - { - AddComponent(new AddonComponent(0x2DD9), 0, 0, 0); - } - - public ElvenSpinningwheelEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new ElvenSpinningwheelEastDeed(); - - public bool Spinning => m_Timer != null; - - public void BeginSpin(SpinCallback callback, Mobile from, int hue) - { - m_Timer = new SpinTimer(this, callback, from, hue); - m_Timer.Start(); - - foreach (AddonComponent c in Components) - switch (c.ItemID) - { - case 0x2DD9: - case 0x101C: - case 0x10A4: - ++c.ItemID; - break; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - public override void OnComponentLoaded(AddonComponent c) - { - switch (c.ItemID) - { - case 0x2E3D: - case 0x101D: - case 0x10A5: - --c.ItemID; - break; - } - } - - public void EndSpin(SpinCallback callback, Mobile from, int hue) - { - m_Timer?.Stop(); - - m_Timer = null; - - foreach (AddonComponent c in Components) - switch (c.ItemID) - { - case 0x1016: - case 0x101A: - case 0x101D: - case 0x10A5: - --c.ItemID; - break; - } - - callback?.Invoke(this, from, hue); - } - - private class SpinTimer : Timer - { - private readonly SpinCallback m_Callback; - private readonly Mobile m_From; - private readonly int m_Hue; - private readonly ElvenSpinningwheelEastAddon m_Wheel; - - public SpinTimer(ElvenSpinningwheelEastAddon wheel, SpinCallback callback, Mobile from, int hue) : base( - TimeSpan.FromSeconds(3.0)) - { - m_Wheel = wheel; - m_Callback = callback; - m_From = from; - m_Hue = hue; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - m_Wheel.EndSpin(m_Callback, m_From, m_Hue); - } - } - } - - public class ElvenSpinningwheelEastDeed : BaseAddonDeed - { - [Constructible] - public ElvenSpinningwheelEastDeed() - { - } - - public ElvenSpinningwheelEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new ElvenSpinningwheelEastAddon(); - public override int LabelNumber => 1073393; // elven spinning wheel (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class ElvenSpinningwheelEastAddon : BaseAddon, ISpinningWheel + { + private Timer m_Timer; + + [Constructible] + public ElvenSpinningwheelEastAddon() + { + AddComponent(new AddonComponent(0x2DD9), 0, 0, 0); + } + + public ElvenSpinningwheelEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new ElvenSpinningwheelEastDeed(); + + public bool Spinning => m_Timer != null; + + public void BeginSpin(SpinCallback callback, Mobile from, int hue) + { + m_Timer = new SpinTimer(this, callback, from, hue); + m_Timer.Start(); + + foreach (var c in Components) + switch (c.ItemID) + { + case 0x2DD9: + case 0x101C: + case 0x10A4: + ++c.ItemID; + break; + } + } + + 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(); + } + + public override void OnComponentLoaded(AddonComponent c) + { + switch (c.ItemID) + { + case 0x2E3D: + case 0x101D: + case 0x10A5: + --c.ItemID; + break; + } + } + + public void EndSpin(SpinCallback callback, Mobile from, int hue) + { + m_Timer?.Stop(); + + m_Timer = null; + + foreach (var c in Components) + switch (c.ItemID) + { + case 0x1016: + case 0x101A: + case 0x101D: + case 0x10A5: + --c.ItemID; + break; + } + + callback?.Invoke(this, from, hue); + } + + private class SpinTimer : Timer + { + private readonly SpinCallback m_Callback; + private readonly Mobile m_From; + private readonly int m_Hue; + private readonly ElvenSpinningwheelEastAddon m_Wheel; + + public SpinTimer(ElvenSpinningwheelEastAddon wheel, SpinCallback callback, Mobile from, int hue) : base( + TimeSpan.FromSeconds(3.0) + ) + { + m_Wheel = wheel; + m_Callback = callback; + m_From = from; + m_Hue = hue; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + m_Wheel.EndSpin(m_Callback, m_From, m_Hue); + } + } + } + + public class ElvenSpinningwheelEastDeed : BaseAddonDeed + { + [Constructible] + public ElvenSpinningwheelEastDeed() + { + } + + public ElvenSpinningwheelEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new ElvenSpinningwheelEastAddon(); + public override int LabelNumber => 1073393; // elven spinning wheel (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/ElvenSpinningwheelSouthAddon.cs b/Projects/UOContent/Items/Addons/ElvenSpinningwheelSouthAddon.cs index 3beae227f..1c73cd496 100644 --- a/Projects/UOContent/Items/Addons/ElvenSpinningwheelSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/ElvenSpinningwheelSouthAddon.cs @@ -1,139 +1,140 @@ -using System; - -namespace Server.Items -{ - public class ElvenSpinningwheelSouthAddon : BaseAddon, ISpinningWheel - { - private Timer m_Timer; - - [Constructible] - public ElvenSpinningwheelSouthAddon() - { - AddComponent(new AddonComponent(0x2DDA), 0, 0, 0); - } - - public ElvenSpinningwheelSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new ElvenSpinningwheelSouthDeed(); - - public bool Spinning => m_Timer != null; - - public void BeginSpin(SpinCallback callback, Mobile from, int hue) - { - m_Timer = new SpinTimer(this, callback, from, hue); - m_Timer.Start(); - - foreach (AddonComponent c in Components) - switch (c.ItemID) - { - case 0x1015: - case 0x1019: - case 0x101C: - case 0x10A4: - ++c.ItemID; - break; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - public override void OnComponentLoaded(AddonComponent c) - { - switch (c.ItemID) - { - case 0x1016: - case 0x101A: - case 0x101D: - case 0x10A5: - --c.ItemID; - break; - } - } - - public void EndSpin(SpinCallback callback, Mobile from, int hue) - { - m_Timer?.Stop(); - - m_Timer = null; - - foreach (AddonComponent c in Components) - switch (c.ItemID) - { - case 0x1016: - case 0x101A: - case 0x101D: - case 0x10A5: - --c.ItemID; - break; - } - - callback?.Invoke(this, from, hue); - } - - private class SpinTimer : Timer - { - private readonly SpinCallback m_Callback; - private readonly Mobile m_From; - private readonly int m_Hue; - private readonly ElvenSpinningwheelSouthAddon m_Wheel; - - public SpinTimer(ElvenSpinningwheelSouthAddon wheel, SpinCallback callback, Mobile from, int hue) : base( - TimeSpan.FromSeconds(3.0)) - { - m_Wheel = wheel; - m_Callback = callback; - m_From = from; - m_Hue = hue; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - m_Wheel.EndSpin(m_Callback, m_From, m_Hue); - } - } - } - - public class ElvenSpinningwheelSouthDeed : BaseAddonDeed - { - [Constructible] - public ElvenSpinningwheelSouthDeed() - { - } - - public ElvenSpinningwheelSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new ElvenSpinningwheelSouthAddon(); - public override int LabelNumber => 1072878; // spinning wheel (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class ElvenSpinningwheelSouthAddon : BaseAddon, ISpinningWheel + { + private Timer m_Timer; + + [Constructible] + public ElvenSpinningwheelSouthAddon() + { + AddComponent(new AddonComponent(0x2DDA), 0, 0, 0); + } + + public ElvenSpinningwheelSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new ElvenSpinningwheelSouthDeed(); + + public bool Spinning => m_Timer != null; + + public void BeginSpin(SpinCallback callback, Mobile from, int hue) + { + m_Timer = new SpinTimer(this, callback, from, hue); + m_Timer.Start(); + + foreach (var c in Components) + switch (c.ItemID) + { + case 0x1015: + case 0x1019: + case 0x101C: + case 0x10A4: + ++c.ItemID; + break; + } + } + + 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(); + } + + public override void OnComponentLoaded(AddonComponent c) + { + switch (c.ItemID) + { + case 0x1016: + case 0x101A: + case 0x101D: + case 0x10A5: + --c.ItemID; + break; + } + } + + public void EndSpin(SpinCallback callback, Mobile from, int hue) + { + m_Timer?.Stop(); + + m_Timer = null; + + foreach (var c in Components) + switch (c.ItemID) + { + case 0x1016: + case 0x101A: + case 0x101D: + case 0x10A5: + --c.ItemID; + break; + } + + callback?.Invoke(this, from, hue); + } + + private class SpinTimer : Timer + { + private readonly SpinCallback m_Callback; + private readonly Mobile m_From; + private readonly int m_Hue; + private readonly ElvenSpinningwheelSouthAddon m_Wheel; + + public SpinTimer(ElvenSpinningwheelSouthAddon wheel, SpinCallback callback, Mobile from, int hue) : base( + TimeSpan.FromSeconds(3.0) + ) + { + m_Wheel = wheel; + m_Callback = callback; + m_From = from; + m_Hue = hue; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + m_Wheel.EndSpin(m_Callback, m_From, m_Hue); + } + } + } + + public class ElvenSpinningwheelSouthDeed : BaseAddonDeed + { + [Constructible] + public ElvenSpinningwheelSouthDeed() + { + } + + public ElvenSpinningwheelSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new ElvenSpinningwheelSouthAddon(); + public override int LabelNumber => 1072878; // spinning wheel (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/ElvenStoveEastAddon.cs b/Projects/UOContent/Items/Addons/ElvenStoveEastAddon.cs index 56a69ea13..97f1a545d 100644 --- a/Projects/UOContent/Items/Addons/ElvenStoveEastAddon.cs +++ b/Projects/UOContent/Items/Addons/ElvenStoveEastAddon.cs @@ -1,60 +1,60 @@ -namespace Server.Items -{ - public class ElvenStoveEastAddon : BaseAddon - { - [Constructible] - public ElvenStoveEastAddon() - { - AddComponent(new AddonComponent(0x2DDB), 0, 0, 0); - } - - public ElvenStoveEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new ElvenStoveEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ElvenStoveEastDeed : BaseAddonDeed - { - [Constructible] - public ElvenStoveEastDeed() - { - } - - public ElvenStoveEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new ElvenStoveEastAddon(); - public override int LabelNumber => 1073395; // elven oven (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ElvenStoveEastAddon : BaseAddon + { + [Constructible] + public ElvenStoveEastAddon() + { + AddComponent(new AddonComponent(0x2DDB), 0, 0, 0); + } + + public ElvenStoveEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new ElvenStoveEastDeed(); + + 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(); + } + } + + public class ElvenStoveEastDeed : BaseAddonDeed + { + [Constructible] + public ElvenStoveEastDeed() + { + } + + public ElvenStoveEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new ElvenStoveEastAddon(); + public override int LabelNumber => 1073395; // elven oven (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/ElvenStoveSouthAddon.cs b/Projects/UOContent/Items/Addons/ElvenStoveSouthAddon.cs index 0b5cbb475..301eeea57 100644 --- a/Projects/UOContent/Items/Addons/ElvenStoveSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/ElvenStoveSouthAddon.cs @@ -1,60 +1,60 @@ -namespace Server.Items -{ - public class ElvenStoveSouthAddon : BaseAddon - { - [Constructible] - public ElvenStoveSouthAddon() - { - AddComponent(new AddonComponent(0x2DDC), 0, 0, 0); - } - - public ElvenStoveSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new ElvenStoveSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ElvenStoveSouthDeed : BaseAddonDeed - { - [Constructible] - public ElvenStoveSouthDeed() - { - } - - public ElvenStoveSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new ElvenStoveSouthAddon(); - public override int LabelNumber => 1073394; // elven oven (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ElvenStoveSouthAddon : BaseAddon + { + [Constructible] + public ElvenStoveSouthAddon() + { + AddComponent(new AddonComponent(0x2DDC), 0, 0, 0); + } + + public ElvenStoveSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new ElvenStoveSouthDeed(); + + 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(); + } + } + + public class ElvenStoveSouthDeed : BaseAddonDeed + { + [Constructible] + public ElvenStoveSouthDeed() + { + } + + public ElvenStoveSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new ElvenStoveSouthAddon(); + public override int LabelNumber => 1073394; // elven oven (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/ElvenWashbasinEastAddon.cs b/Projects/UOContent/Items/Addons/ElvenWashbasinEastAddon.cs index 13f3350d7..d4b15e17d 100644 --- a/Projects/UOContent/Items/Addons/ElvenWashbasinEastAddon.cs +++ b/Projects/UOContent/Items/Addons/ElvenWashbasinEastAddon.cs @@ -1,61 +1,61 @@ -namespace Server.Items -{ - public class ElvenWashBasinEastAddon : BaseAddon - { - [Constructible] - public ElvenWashBasinEastAddon() - { - AddComponent(new AddonComponent(0x30DF), 0, 0, 0); - AddComponent(new AddonComponent(0x30E0), 0, 1, 0); - } - - public ElvenWashBasinEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new ElvenWashBasinEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ElvenWashBasinEastDeed : BaseAddonDeed - { - [Constructible] - public ElvenWashBasinEastDeed() - { - } - - public ElvenWashBasinEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new ElvenWashBasinEastAddon(); - public override int LabelNumber => 1073387; // elven wash basin (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ElvenWashBasinEastAddon : BaseAddon + { + [Constructible] + public ElvenWashBasinEastAddon() + { + AddComponent(new AddonComponent(0x30DF), 0, 0, 0); + AddComponent(new AddonComponent(0x30E0), 0, 1, 0); + } + + public ElvenWashBasinEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new ElvenWashBasinEastDeed(); + + 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(); + } + } + + public class ElvenWashBasinEastDeed : BaseAddonDeed + { + [Constructible] + public ElvenWashBasinEastDeed() + { + } + + public ElvenWashBasinEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new ElvenWashBasinEastAddon(); + public override int LabelNumber => 1073387; // elven wash basin (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/ElvenWashbasinSouthAddon.cs b/Projects/UOContent/Items/Addons/ElvenWashbasinSouthAddon.cs index 13509eb3b..05ecb823f 100644 --- a/Projects/UOContent/Items/Addons/ElvenWashbasinSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/ElvenWashbasinSouthAddon.cs @@ -1,61 +1,61 @@ -namespace Server.Items -{ - public class ElvenWashBasinSouthAddon : BaseAddon - { - [Constructible] - public ElvenWashBasinSouthAddon() - { - AddComponent(new AddonComponent(0x30E1), 0, 0, 0); - AddComponent(new AddonComponent(0x30E2), 1, 0, 0); - } - - public ElvenWashBasinSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new ElvenWashBasinSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ElvenWashBasinSouthDeed : BaseAddonDeed - { - [Constructible] - public ElvenWashBasinSouthDeed() - { - } - - public ElvenWashBasinSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new ElvenWashBasinSouthAddon(); - public override int LabelNumber => 1072865; // elven wash basin (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ElvenWashBasinSouthAddon : BaseAddon + { + [Constructible] + public ElvenWashBasinSouthAddon() + { + AddComponent(new AddonComponent(0x30E1), 0, 0, 0); + AddComponent(new AddonComponent(0x30E2), 1, 0, 0); + } + + public ElvenWashBasinSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new ElvenWashBasinSouthDeed(); + + 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(); + } + } + + public class ElvenWashBasinSouthDeed : BaseAddonDeed + { + [Constructible] + public ElvenWashBasinSouthDeed() + { + } + + public ElvenWashBasinSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new ElvenWashBasinSouthAddon(); + public override int LabelNumber => 1072865; // elven wash basin (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/FancyElvenTableEastAddon.cs b/Projects/UOContent/Items/Addons/FancyElvenTableEastAddon.cs index ffad1e3da..b5438c04c 100644 --- a/Projects/UOContent/Items/Addons/FancyElvenTableEastAddon.cs +++ b/Projects/UOContent/Items/Addons/FancyElvenTableEastAddon.cs @@ -1,62 +1,62 @@ -namespace Server.Items -{ - public class FancyElvenTableEastAddon : BaseAddon - { - [Constructible] - public FancyElvenTableEastAddon() - { - AddComponent(new AddonComponent(0x3094), -1, 0, 0); - AddComponent(new AddonComponent(0x3093), 0, 0, 0); - AddComponent(new AddonComponent(0x3092), 1, 0, 0); - } - - public FancyElvenTableEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new FancyElvenTableEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class FancyElvenTableEastDeed : BaseAddonDeed - { - [Constructible] - public FancyElvenTableEastDeed() - { - } - - public FancyElvenTableEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new FancyElvenTableEastAddon(); - public override int LabelNumber => 1073386; // hardwood table (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FancyElvenTableEastAddon : BaseAddon + { + [Constructible] + public FancyElvenTableEastAddon() + { + AddComponent(new AddonComponent(0x3094), -1, 0, 0); + AddComponent(new AddonComponent(0x3093), 0, 0, 0); + AddComponent(new AddonComponent(0x3092), 1, 0, 0); + } + + public FancyElvenTableEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new FancyElvenTableEastDeed(); + + 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(); + } + } + + public class FancyElvenTableEastDeed : BaseAddonDeed + { + [Constructible] + public FancyElvenTableEastDeed() + { + } + + public FancyElvenTableEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new FancyElvenTableEastAddon(); + public override int LabelNumber => 1073386; // hardwood table (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/FancyElvenTableSouthAddon.cs b/Projects/UOContent/Items/Addons/FancyElvenTableSouthAddon.cs index 6d8d9a566..d559ba361 100644 --- a/Projects/UOContent/Items/Addons/FancyElvenTableSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/FancyElvenTableSouthAddon.cs @@ -1,62 +1,62 @@ -namespace Server.Items -{ - public class FancyElvenTableSouthAddon : BaseAddon - { - [Constructible] - public FancyElvenTableSouthAddon() - { - AddComponent(new AddonComponent(0x3095), 0, 1, 0); - AddComponent(new AddonComponent(0x3096), 0, 0, 0); - AddComponent(new AddonComponent(0x3097), 0, -1, 0); - } - - public FancyElvenTableSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new FancyElvenTableSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class FancyElvenTableSouthDeed : BaseAddonDeed - { - [Constructible] - public FancyElvenTableSouthDeed() - { - } - - public FancyElvenTableSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new FancyElvenTableSouthAddon(); - public override int LabelNumber => 1073385; // hardwood table (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FancyElvenTableSouthAddon : BaseAddon + { + [Constructible] + public FancyElvenTableSouthAddon() + { + AddComponent(new AddonComponent(0x3095), 0, 1, 0); + AddComponent(new AddonComponent(0x3096), 0, 0, 0); + AddComponent(new AddonComponent(0x3097), 0, -1, 0); + } + + public FancyElvenTableSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new FancyElvenTableSouthDeed(); + + 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(); + } + } + + public class FancyElvenTableSouthDeed : BaseAddonDeed + { + [Constructible] + public FancyElvenTableSouthDeed() + { + } + + public FancyElvenTableSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new FancyElvenTableSouthAddon(); + public override int LabelNumber => 1073385; // hardwood table (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/FireColumnAddon.cs b/Projects/UOContent/Items/Addons/FireColumnAddon.cs index 6b9fc9754..efbb01dd5 100644 --- a/Projects/UOContent/Items/Addons/FireColumnAddon.cs +++ b/Projects/UOContent/Items/Addons/FireColumnAddon.cs @@ -1,51 +1,51 @@ -namespace Server.Items -{ - public class FireColumnAddon : BaseAddon - { - [Constructible] - public FireColumnAddon(bool bloody = false) - { - AddComponent(new AddonComponent(0x3A5), 0, 0, 0); - AddComponent(new AddonComponent(0x3A5), 0, 0, 5); - AddComponent(new AddonComponent(0x3A5), 0, 0, 10); - AddComponent(new AddonComponent(0x3A5), 0, 0, 15); - - AddComponent(new AddonComponent(0x19BB), 0, 0, 21); - AddComponent(new AddonComponent(0x19AB), 0, 0, 23); - - if (bloody) - { - AddComponent(new AddonComponent(0x122B), -2, 0, 0); - AddComponent(new AddonComponent(0x122E), 0, -2, 0); - AddComponent(new AddonComponent(0x122D), -1, 1, 0); - AddComponent(new AddonComponent(0x122F), 1, -1, 0); - AddComponent(new AddonComponent(0x122D), 0, 1, 0); - AddComponent(new AddonComponent(0x122A), 1, 0, 0); - AddComponent(new AddonComponent(0x122B), 2, -1, 0); - AddComponent(new AddonComponent(0x122B), 0, 2, 0); - AddComponent(new AddonComponent(0x122E), 1, 1, 0); - } - } - - public FireColumnAddon(Serial serial) - : base(serial) - { - } - - public override bool ShareHue => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class FireColumnAddon : BaseAddon + { + [Constructible] + public FireColumnAddon(bool bloody = false) + { + AddComponent(new AddonComponent(0x3A5), 0, 0, 0); + AddComponent(new AddonComponent(0x3A5), 0, 0, 5); + AddComponent(new AddonComponent(0x3A5), 0, 0, 10); + AddComponent(new AddonComponent(0x3A5), 0, 0, 15); + + AddComponent(new AddonComponent(0x19BB), 0, 0, 21); + AddComponent(new AddonComponent(0x19AB), 0, 0, 23); + + if (bloody) + { + AddComponent(new AddonComponent(0x122B), -2, 0, 0); + AddComponent(new AddonComponent(0x122E), 0, -2, 0); + AddComponent(new AddonComponent(0x122D), -1, 1, 0); + AddComponent(new AddonComponent(0x122F), 1, -1, 0); + AddComponent(new AddonComponent(0x122D), 0, 1, 0); + AddComponent(new AddonComponent(0x122A), 1, 0, 0); + AddComponent(new AddonComponent(0x122B), 2, -1, 0); + AddComponent(new AddonComponent(0x122B), 0, 2, 0); + AddComponent(new AddonComponent(0x122E), 1, 1, 0); + } + } + + public FireColumnAddon(Serial serial) + : base(serial) + { + } + + public override bool ShareHue => 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/FlourMillEastAddon.cs b/Projects/UOContent/Items/Addons/FlourMillEastAddon.cs index 576ba6702..d874fc3c5 100644 --- a/Projects/UOContent/Items/Addons/FlourMillEastAddon.cs +++ b/Projects/UOContent/Items/Addons/FlourMillEastAddon.cs @@ -1,212 +1,211 @@ -using System; -using System.Collections.Generic; -using Server.Network; - -namespace Server.Items -{ - public interface IFlourMill - { - int MaxFlour { get; } - int CurFlour { get; set; } - } - - public enum FlourMillStage - { - Empty, - Filled, - Working - } - - public class FlourMillEastAddon : BaseAddon, IFlourMill - { - private static readonly int[][] m_StageTable = - { - new[] { 0x1920, 0x1921, 0x1925 }, - new[] { 0x1922, 0x1923, 0x1926 }, - new[] { 0x1924, 0x1924, 0x1928 } - }; - - private int m_Flour; - private Timer m_Timer; - - [Constructible] - public FlourMillEastAddon() - { - AddComponent(new AddonComponent(0x1920), -1, 0, 0); - AddComponent(new AddonComponent(0x1922), 0, 0, 0); - AddComponent(new AddonComponent(0x1924), 1, 0, 0); - } - - public FlourMillEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new FlourMillEastDeed(); - - [CommandProperty(AccessLevel.GameMaster)] - public bool HasFlour => m_Flour > 0; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsFull => m_Flour >= MaxFlour; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsWorking => m_Timer != null; - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxFlour => 2; - - [CommandProperty(AccessLevel.GameMaster)] - public int CurFlour - { - get => m_Flour; - set - { - m_Flour = Math.Max(0, Math.Min(value, MaxFlour)); - UpdateStage(); - } - } - - public void StartWorking(Mobile from) - { - if (IsWorking) - return; - - m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(5.0), FinishWorking_Callback, from); - UpdateStage(); - } - - private void FinishWorking_Callback(Mobile from) - { - if (m_Timer != null) - { - m_Timer.Stop(); - m_Timer = null; - } - - if (from?.Deleted == false && !Deleted && IsFull) - { - SackFlour flour = new SackFlour { ItemID = Utility.RandomBool() ? 4153 : 4165 }; - - if (from.PlaceInBackpack(flour)) - { - m_Flour = 0; - } - else - { - flour.Delete(); - from.SendLocalizedMessage(500998); // There is not enough room in your backpack! You stop grinding. - } - } - - UpdateStage(); - } - - private int[] FindItemTable(int itemID) - { - for (int i = 0; i < m_StageTable.Length; ++i) - { - int[] itemTable = m_StageTable[i]; - - for (int j = 0; j < itemTable.Length; ++j) - if (itemTable[j] == itemID) - return itemTable; - } - - return null; - } - - public void UpdateStage() - { - if (IsWorking) - UpdateStage(FlourMillStage.Working); - else if (HasFlour) - UpdateStage(FlourMillStage.Filled); - else - UpdateStage(FlourMillStage.Empty); - } - - public void UpdateStage(FlourMillStage stage) - { - List components = Components; - - int[][] stageTable = m_StageTable; - - for (int i = 0; i < components.Count; ++i) - { - if (!(components[i] is AddonComponent component)) - continue; - - int[] itemTable = FindItemTable(component.ItemID); - - if (itemTable != null) - component.ItemID = itemTable[(int)stage]; - } - } - - public override void OnComponentUsed(AddonComponent c, Mobile from) - { - if (!from.InRange(GetWorldLocation(), 4) || !from.InLOS(this)) - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - else if (!IsFull) - from.SendLocalizedMessage(500997); // You need more wheat to make a sack of flour. - else - StartWorking(from); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(m_Flour); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_Flour = reader.ReadInt(); - break; - } - } - - UpdateStage(); - } - } - - public class FlourMillEastDeed : BaseAddonDeed - { - [Constructible] - public FlourMillEastDeed() - { - } - - public FlourMillEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new FlourMillEastAddon(); - public override int LabelNumber => 1044347; // flour mill (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; +using Server.Network; + +namespace Server.Items +{ + public interface IFlourMill + { + int MaxFlour { get; } + int CurFlour { get; set; } + } + + public enum FlourMillStage + { + Empty, + Filled, + Working + } + + public class FlourMillEastAddon : BaseAddon, IFlourMill + { + private static readonly int[][] m_StageTable = + { + new[] { 0x1920, 0x1921, 0x1925 }, + new[] { 0x1922, 0x1923, 0x1926 }, + new[] { 0x1924, 0x1924, 0x1928 } + }; + + private int m_Flour; + private Timer m_Timer; + + [Constructible] + public FlourMillEastAddon() + { + AddComponent(new AddonComponent(0x1920), -1, 0, 0); + AddComponent(new AddonComponent(0x1922), 0, 0, 0); + AddComponent(new AddonComponent(0x1924), 1, 0, 0); + } + + public FlourMillEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new FlourMillEastDeed(); + + [CommandProperty(AccessLevel.GameMaster)] + public bool HasFlour => m_Flour > 0; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsFull => m_Flour >= MaxFlour; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsWorking => m_Timer != null; + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxFlour => 2; + + [CommandProperty(AccessLevel.GameMaster)] + public int CurFlour + { + get => m_Flour; + set + { + m_Flour = Math.Max(0, Math.Min(value, MaxFlour)); + UpdateStage(); + } + } + + public void StartWorking(Mobile from) + { + if (IsWorking) + return; + + m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(5.0), FinishWorking_Callback, from); + UpdateStage(); + } + + private void FinishWorking_Callback(Mobile from) + { + if (m_Timer != null) + { + m_Timer.Stop(); + m_Timer = null; + } + + if (from?.Deleted == false && !Deleted && IsFull) + { + var flour = new SackFlour { ItemID = Utility.RandomBool() ? 4153 : 4165 }; + + if (from.PlaceInBackpack(flour)) + { + m_Flour = 0; + } + else + { + flour.Delete(); + from.SendLocalizedMessage(500998); // There is not enough room in your backpack! You stop grinding. + } + } + + UpdateStage(); + } + + private int[] FindItemTable(int itemID) + { + for (var i = 0; i < m_StageTable.Length; ++i) + { + var itemTable = m_StageTable[i]; + + for (var j = 0; j < itemTable.Length; ++j) + if (itemTable[j] == itemID) + return itemTable; + } + + return null; + } + + public void UpdateStage() + { + if (IsWorking) + UpdateStage(FlourMillStage.Working); + else if (HasFlour) + UpdateStage(FlourMillStage.Filled); + else + UpdateStage(FlourMillStage.Empty); + } + + public void UpdateStage(FlourMillStage stage) + { + var components = Components; + + var stageTable = m_StageTable; + + for (var i = 0; i < components.Count; ++i) + { + if (!(components[i] is AddonComponent component)) + continue; + + var itemTable = FindItemTable(component.ItemID); + + if (itemTable != null) + component.ItemID = itemTable[(int)stage]; + } + } + + public override void OnComponentUsed(AddonComponent c, Mobile from) + { + if (!from.InRange(GetWorldLocation(), 4) || !from.InLOS(this)) + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + else if (!IsFull) + from.SendLocalizedMessage(500997); // You need more wheat to make a sack of flour. + else + StartWorking(from); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(m_Flour); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_Flour = reader.ReadInt(); + break; + } + } + + UpdateStage(); + } + } + + public class FlourMillEastDeed : BaseAddonDeed + { + [Constructible] + public FlourMillEastDeed() + { + } + + public FlourMillEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new FlourMillEastAddon(); + public override int LabelNumber => 1044347; // flour mill (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/FlourMillSouthAddon.cs b/Projects/UOContent/Items/Addons/FlourMillSouthAddon.cs index 8a03c6c2a..ba99f4987 100644 --- a/Projects/UOContent/Items/Addons/FlourMillSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/FlourMillSouthAddon.cs @@ -1,201 +1,200 @@ -using System; -using System.Collections.Generic; -using Server.Network; - -namespace Server.Items -{ - public class FlourMillSouthAddon : BaseAddon, IFlourMill - { - private static readonly int[][] m_StageTable = - { - new[] { 0x192C, 0x192D, 0x1931 }, - new[] { 0x192E, 0x192F, 0x1932 }, - new[] { 0x1930, 0x1930, 0x1934 } - }; - - private int m_Flour; - private Timer m_Timer; - - [Constructible] - public FlourMillSouthAddon() - { - AddComponent(new AddonComponent(0x192C), 0, -1, 0); - AddComponent(new AddonComponent(0x192E), 0, 0, 0); - AddComponent(new AddonComponent(0x1930), 0, 1, 0); - } - - public FlourMillSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new FlourMillSouthDeed(); - - [CommandProperty(AccessLevel.GameMaster)] - public bool HasFlour => m_Flour > 0; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsFull => m_Flour >= MaxFlour; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsWorking => m_Timer != null; - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxFlour => 2; - - [CommandProperty(AccessLevel.GameMaster)] - public int CurFlour - { - get => m_Flour; - set - { - m_Flour = Math.Max(0, Math.Min(value, MaxFlour)); - UpdateStage(); - } - } - - public void StartWorking(Mobile from) - { - if (IsWorking) - return; - - m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(5.0), FinishWorking_Callback, from); - UpdateStage(); - } - - private void FinishWorking_Callback(Mobile from) - { - if (m_Timer != null) - { - m_Timer.Stop(); - m_Timer = null; - } - - if (from?.Deleted == false && !Deleted && IsFull) - { - SackFlour flour = new SackFlour(); - - flour.ItemID = Utility.RandomBool() ? 4153 : 4165; - - if (from.PlaceInBackpack(flour)) - { - m_Flour = 0; - } - else - { - flour.Delete(); - from.SendLocalizedMessage(500998); // There is not enough room in your backpack! You stop grinding. - } - } - - UpdateStage(); - } - - private int[] FindItemTable(int itemID) - { - for (int i = 0; i < m_StageTable.Length; ++i) - { - int[] itemTable = m_StageTable[i]; - - for (int j = 0; j < itemTable.Length; ++j) - if (itemTable[j] == itemID) - return itemTable; - } - - return null; - } - - public void UpdateStage() - { - if (IsWorking) - UpdateStage(FlourMillStage.Working); - else if (HasFlour) - UpdateStage(FlourMillStage.Filled); - else - UpdateStage(FlourMillStage.Empty); - } - - public void UpdateStage(FlourMillStage stage) - { - List components = Components; - - int[][] stageTable = m_StageTable; - - for (int i = 0; i < components.Count; ++i) - { - if (!(components[i] is AddonComponent component)) - continue; - - int[] itemTable = FindItemTable(component.ItemID); - - if (itemTable != null) - component.ItemID = itemTable[(int)stage]; - } - } - - public override void OnComponentUsed(AddonComponent c, Mobile from) - { - if (!from.InRange(GetWorldLocation(), 4) || !from.InLOS(this)) - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - else if (!IsFull) - from.SendLocalizedMessage(500997); // You need more wheat to make a sack of flour. - else - StartWorking(from); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(m_Flour); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_Flour = reader.ReadInt(); - break; - } - } - - UpdateStage(); - } - } - - public class FlourMillSouthDeed : BaseAddonDeed - { - [Constructible] - public FlourMillSouthDeed() - { - } - - public FlourMillSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new FlourMillSouthAddon(); - public override int LabelNumber => 1044348; // flour mill (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; +using Server.Network; + +namespace Server.Items +{ + public class FlourMillSouthAddon : BaseAddon, IFlourMill + { + private static readonly int[][] m_StageTable = + { + new[] { 0x192C, 0x192D, 0x1931 }, + new[] { 0x192E, 0x192F, 0x1932 }, + new[] { 0x1930, 0x1930, 0x1934 } + }; + + private int m_Flour; + private Timer m_Timer; + + [Constructible] + public FlourMillSouthAddon() + { + AddComponent(new AddonComponent(0x192C), 0, -1, 0); + AddComponent(new AddonComponent(0x192E), 0, 0, 0); + AddComponent(new AddonComponent(0x1930), 0, 1, 0); + } + + public FlourMillSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new FlourMillSouthDeed(); + + [CommandProperty(AccessLevel.GameMaster)] + public bool HasFlour => m_Flour > 0; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsFull => m_Flour >= MaxFlour; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsWorking => m_Timer != null; + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxFlour => 2; + + [CommandProperty(AccessLevel.GameMaster)] + public int CurFlour + { + get => m_Flour; + set + { + m_Flour = Math.Max(0, Math.Min(value, MaxFlour)); + UpdateStage(); + } + } + + public void StartWorking(Mobile from) + { + if (IsWorking) + return; + + m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(5.0), FinishWorking_Callback, from); + UpdateStage(); + } + + private void FinishWorking_Callback(Mobile from) + { + if (m_Timer != null) + { + m_Timer.Stop(); + m_Timer = null; + } + + if (from?.Deleted == false && !Deleted && IsFull) + { + var flour = new SackFlour(); + + flour.ItemID = Utility.RandomBool() ? 4153 : 4165; + + if (from.PlaceInBackpack(flour)) + { + m_Flour = 0; + } + else + { + flour.Delete(); + from.SendLocalizedMessage(500998); // There is not enough room in your backpack! You stop grinding. + } + } + + UpdateStage(); + } + + private int[] FindItemTable(int itemID) + { + for (var i = 0; i < m_StageTable.Length; ++i) + { + var itemTable = m_StageTable[i]; + + for (var j = 0; j < itemTable.Length; ++j) + if (itemTable[j] == itemID) + return itemTable; + } + + return null; + } + + public void UpdateStage() + { + if (IsWorking) + UpdateStage(FlourMillStage.Working); + else if (HasFlour) + UpdateStage(FlourMillStage.Filled); + else + UpdateStage(FlourMillStage.Empty); + } + + public void UpdateStage(FlourMillStage stage) + { + var components = Components; + + var stageTable = m_StageTable; + + for (var i = 0; i < components.Count; ++i) + { + if (!(components[i] is AddonComponent component)) + continue; + + var itemTable = FindItemTable(component.ItemID); + + if (itemTable != null) + component.ItemID = itemTable[(int)stage]; + } + } + + public override void OnComponentUsed(AddonComponent c, Mobile from) + { + if (!from.InRange(GetWorldLocation(), 4) || !from.InLOS(this)) + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + else if (!IsFull) + from.SendLocalizedMessage(500997); // You need more wheat to make a sack of flour. + else + StartWorking(from); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(m_Flour); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_Flour = reader.ReadInt(); + break; + } + } + + UpdateStage(); + } + } + + public class FlourMillSouthDeed : BaseAddonDeed + { + [Constructible] + public FlourMillSouthDeed() + { + } + + public FlourMillSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new FlourMillSouthAddon(); + public override int LabelNumber => 1044348; // flour mill (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/FlowerTapestries.cs b/Projects/UOContent/Items/Addons/FlowerTapestries.cs index 2efb2215b..04272ede4 100644 --- a/Projects/UOContent/Items/Addons/FlowerTapestries.cs +++ b/Projects/UOContent/Items/Addons/FlowerTapestries.cs @@ -1,238 +1,238 @@ -namespace Server.Items -{ - public class LightFlowerTapestryEastAddon : BaseAddon - { - [Constructible] - public LightFlowerTapestryEastAddon() - { - AddComponent(new AddonComponent(0xFDC), 0, 0, 0); - AddComponent(new AddonComponent(0xFDB), 0, 1, 0); - } - - public LightFlowerTapestryEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new LightFlowerTapestryEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LightFlowerTapestryEastDeed : BaseAddonDeed - { - [Constructible] - public LightFlowerTapestryEastDeed() - { - } - - public LightFlowerTapestryEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new LightFlowerTapestryEastAddon(); - public override int LabelNumber => 1049393; // a flower tapestry deed facing east - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LightFlowerTapestrySouthAddon : BaseAddon - { - [Constructible] - public LightFlowerTapestrySouthAddon() - { - AddComponent(new AddonComponent(0xFD9), 0, 0, 0); - AddComponent(new AddonComponent(0xFDA), 1, 0, 0); - } - - public LightFlowerTapestrySouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new LightFlowerTapestrySouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LightFlowerTapestrySouthDeed : BaseAddonDeed - { - [Constructible] - public LightFlowerTapestrySouthDeed() - { - } - - public LightFlowerTapestrySouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new LightFlowerTapestrySouthAddon(); - public override int LabelNumber => 1049394; // a flower tapestry deed facing south - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DarkFlowerTapestryEastAddon : BaseAddon - { - [Constructible] - public DarkFlowerTapestryEastAddon() - { - AddComponent(new AddonComponent(0xFE0), 0, 0, 0); - AddComponent(new AddonComponent(0xFDF), 0, 1, 0); - } - - public DarkFlowerTapestryEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new DarkFlowerTapestryEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DarkFlowerTapestryEastDeed : BaseAddonDeed - { - [Constructible] - public DarkFlowerTapestryEastDeed() - { - } - - public DarkFlowerTapestryEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new DarkFlowerTapestryEastAddon(); - public override int LabelNumber => 1049395; // a dark flower tapestry deed facing east - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DarkFlowerTapestrySouthAddon : BaseAddon - { - [Constructible] - public DarkFlowerTapestrySouthAddon() - { - AddComponent(new AddonComponent(0xFDD), 0, 0, 0); - AddComponent(new AddonComponent(0xFDE), 1, 0, 0); - } - - public DarkFlowerTapestrySouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new DarkFlowerTapestrySouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DarkFlowerTapestrySouthDeed : BaseAddonDeed - { - [Constructible] - public DarkFlowerTapestrySouthDeed() - { - } - - public DarkFlowerTapestrySouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new DarkFlowerTapestrySouthAddon(); - public override int LabelNumber => 1049396; // a dark flower tapestry deed facing south - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LightFlowerTapestryEastAddon : BaseAddon + { + [Constructible] + public LightFlowerTapestryEastAddon() + { + AddComponent(new AddonComponent(0xFDC), 0, 0, 0); + AddComponent(new AddonComponent(0xFDB), 0, 1, 0); + } + + public LightFlowerTapestryEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new LightFlowerTapestryEastDeed(); + + 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 class LightFlowerTapestryEastDeed : BaseAddonDeed + { + [Constructible] + public LightFlowerTapestryEastDeed() + { + } + + public LightFlowerTapestryEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new LightFlowerTapestryEastAddon(); + public override int LabelNumber => 1049393; // a flower tapestry deed facing east + + 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 class LightFlowerTapestrySouthAddon : BaseAddon + { + [Constructible] + public LightFlowerTapestrySouthAddon() + { + AddComponent(new AddonComponent(0xFD9), 0, 0, 0); + AddComponent(new AddonComponent(0xFDA), 1, 0, 0); + } + + public LightFlowerTapestrySouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new LightFlowerTapestrySouthDeed(); + + 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 class LightFlowerTapestrySouthDeed : BaseAddonDeed + { + [Constructible] + public LightFlowerTapestrySouthDeed() + { + } + + public LightFlowerTapestrySouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new LightFlowerTapestrySouthAddon(); + public override int LabelNumber => 1049394; // a flower tapestry deed facing south + + 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 class DarkFlowerTapestryEastAddon : BaseAddon + { + [Constructible] + public DarkFlowerTapestryEastAddon() + { + AddComponent(new AddonComponent(0xFE0), 0, 0, 0); + AddComponent(new AddonComponent(0xFDF), 0, 1, 0); + } + + public DarkFlowerTapestryEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new DarkFlowerTapestryEastDeed(); + + 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 class DarkFlowerTapestryEastDeed : BaseAddonDeed + { + [Constructible] + public DarkFlowerTapestryEastDeed() + { + } + + public DarkFlowerTapestryEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new DarkFlowerTapestryEastAddon(); + public override int LabelNumber => 1049395; // a dark flower tapestry deed facing east + + 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 class DarkFlowerTapestrySouthAddon : BaseAddon + { + [Constructible] + public DarkFlowerTapestrySouthAddon() + { + AddComponent(new AddonComponent(0xFDD), 0, 0, 0); + AddComponent(new AddonComponent(0xFDE), 1, 0, 0); + } + + public DarkFlowerTapestrySouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new DarkFlowerTapestrySouthDeed(); + + 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 class DarkFlowerTapestrySouthDeed : BaseAddonDeed + { + [Constructible] + public DarkFlowerTapestrySouthDeed() + { + } + + public DarkFlowerTapestrySouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new DarkFlowerTapestrySouthAddon(); + public override int LabelNumber => 1049396; // a dark flower tapestry deed facing south + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/GiantWebs.cs b/Projects/UOContent/Items/Addons/GiantWebs.cs index c93dff306..179edc728 100644 --- a/Projects/UOContent/Items/Addons/GiantWebs.cs +++ b/Projects/UOContent/Items/Addons/GiantWebs.cs @@ -1,200 +1,224 @@ -namespace Server.Items -{ - public class GiantWeb1 : BaseAddon - { - [Constructible] - public GiantWeb1() - { - int itemID = 4280; - int count = 5; - - for (int i = 0; i < count; ++i) - AddComponent(new AddonComponent(itemID++), count - 1 - i, - -(count - 1 - i), 0); - } - - public GiantWeb1(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write((byte)0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadByte(); - } - } - - public class GiantWeb2 : BaseAddon - { - [Constructible] - public GiantWeb2() - { - int itemID = 4285; - int count = 5; - - for (int i = 0; i < count; ++i) - AddComponent(new AddonComponent(itemID++), i, - -i, 0); - } - - public GiantWeb2(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write((byte)0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadByte(); - } - } - - public class GiantWeb3 : BaseAddon - { - [Constructible] - public GiantWeb3() - { - int itemID = 4290; - int count = 4; - - for (int i = 0; i < count; ++i) - AddComponent(new AddonComponent(itemID++), i, - -i, 0); - } - - public GiantWeb3(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write((byte)0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadByte(); - } - } - - public class GiantWeb4 : BaseAddon - { - [Constructible] - public GiantWeb4() - { - int itemID = 4294; - int count = 4; - - for (int i = 0; i < count; ++i) - AddComponent(new AddonComponent(itemID++), count - 1 - i, - -(count - 1 - i), 0); - } - - public GiantWeb4(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write((byte)0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadByte(); - } - } - - public class GiantWeb5 : BaseAddon - { - [Constructible] - public GiantWeb5() - { - int itemID = 4298; - int count = 4; - - for (int i = 0; i < count; ++i) - AddComponent(new AddonComponent(itemID++), i, - -i, 0); - } - - public GiantWeb5(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write((byte)0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadByte(); - } - } - - public class GiantWeb6 : BaseAddon - { - [Constructible] - public GiantWeb6() - { - int itemID = 4302; - int count = 4; - - for (int i = 0; i < count; ++i) - AddComponent(new AddonComponent(itemID++), count - 1 - i, - -(count - 1 - i), 0); - } - - public GiantWeb6(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write((byte)0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadByte(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class GiantWeb1 : BaseAddon + { + [Constructible] + public GiantWeb1() + { + var itemID = 4280; + var count = 5; + + for (var i = 0; i < count; ++i) + AddComponent( + new AddonComponent(itemID++), + count - 1 - i, + -(count - 1 - i), + 0 + ); + } + + public GiantWeb1(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write((byte)0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + int version = reader.ReadByte(); + } + } + + public class GiantWeb2 : BaseAddon + { + [Constructible] + public GiantWeb2() + { + var itemID = 4285; + var count = 5; + + for (var i = 0; i < count; ++i) + AddComponent( + new AddonComponent(itemID++), + i, + -i, + 0 + ); + } + + public GiantWeb2(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write((byte)0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + int version = reader.ReadByte(); + } + } + + public class GiantWeb3 : BaseAddon + { + [Constructible] + public GiantWeb3() + { + var itemID = 4290; + var count = 4; + + for (var i = 0; i < count; ++i) + AddComponent( + new AddonComponent(itemID++), + i, + -i, + 0 + ); + } + + public GiantWeb3(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write((byte)0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + int version = reader.ReadByte(); + } + } + + public class GiantWeb4 : BaseAddon + { + [Constructible] + public GiantWeb4() + { + var itemID = 4294; + var count = 4; + + for (var i = 0; i < count; ++i) + AddComponent( + new AddonComponent(itemID++), + count - 1 - i, + -(count - 1 - i), + 0 + ); + } + + public GiantWeb4(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write((byte)0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + int version = reader.ReadByte(); + } + } + + public class GiantWeb5 : BaseAddon + { + [Constructible] + public GiantWeb5() + { + var itemID = 4298; + var count = 4; + + for (var i = 0; i < count; ++i) + AddComponent( + new AddonComponent(itemID++), + i, + -i, + 0 + ); + } + + public GiantWeb5(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write((byte)0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + int version = reader.ReadByte(); + } + } + + public class GiantWeb6 : BaseAddon + { + [Constructible] + public GiantWeb6() + { + var itemID = 4302; + var count = 4; + + for (var i = 0; i < count; ++i) + AddComponent( + new AddonComponent(itemID++), + count - 1 - i, + -(count - 1 - i), + 0 + ); + } + + public GiantWeb6(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write((byte)0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + int version = reader.ReadByte(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/GozaMats.cs b/Projects/UOContent/Items/Addons/GozaMats.cs index 5a8f7837d..16c5605a6 100644 --- a/Projects/UOContent/Items/Addons/GozaMats.cs +++ b/Projects/UOContent/Items/Addons/GozaMats.cs @@ -1,495 +1,495 @@ -namespace Server.Items -{ - public class GozaMatEastAddon : BaseAddon - { - [Constructible] - public GozaMatEastAddon(int hue = 0) - { - AddComponent(new LocalizedAddonComponent(0x28a4, 1030688), 1, 0, 0); - AddComponent(new LocalizedAddonComponent(0x28a5, 1030688), 0, 0, 0); - Hue = hue; - } - - public GozaMatEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new GozaMatEastDeed(); - - public override bool RetainDeedHue => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GozaMatEastDeed : BaseAddonDeed - { - [Constructible] - public GozaMatEastDeed() - { - } - - public GozaMatEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new GozaMatEastAddon(Hue); - public override int LabelNumber => 1030404; // goza (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GozaMatSouthAddon : BaseAddon - { - [Constructible] - public GozaMatSouthAddon(int hue = 0) - { - AddComponent(new LocalizedAddonComponent(0x28a6, 1030688), 0, 1, 0); - AddComponent(new LocalizedAddonComponent(0x28a7, 1030688), 0, 0, 0); - Hue = hue; - } - - public GozaMatSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new GozaMatSouthDeed(); - - public override bool RetainDeedHue => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GozaMatSouthDeed : BaseAddonDeed - { - [Constructible] - public GozaMatSouthDeed() - { - } - - public GozaMatSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new GozaMatSouthAddon(Hue); - public override int LabelNumber => 1030405; // goza (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SquareGozaMatEastAddon : BaseAddon - { - [Constructible] - public SquareGozaMatEastAddon(int hue = 0) - { - AddComponent(new LocalizedAddonComponent(0x28a8, 1030688), 0, 0, 0); - Hue = hue; - } - - public SquareGozaMatEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new SquareGozaMatEastDeed(); - public override int LabelNumber => 1030688; // goza mat - - public override bool RetainDeedHue => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SquareGozaMatEastDeed : BaseAddonDeed - { - [Constructible] - public SquareGozaMatEastDeed() - { - } - - public SquareGozaMatEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new SquareGozaMatEastAddon(Hue); - public override int LabelNumber => 1030407; // square goza (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SquareGozaMatSouthAddon : BaseAddon - { - [Constructible] - public SquareGozaMatSouthAddon(int hue = 0) - { - AddComponent(new LocalizedAddonComponent(0x28a9, 1030688), 0, 0, 0); - Hue = hue; - } - - public SquareGozaMatSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new SquareGozaMatSouthDeed(); - - public override bool RetainDeedHue => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SquareGozaMatSouthDeed : BaseAddonDeed - { - [Constructible] - public SquareGozaMatSouthDeed() - { - } - - public SquareGozaMatSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new SquareGozaMatSouthAddon(Hue); - public override int LabelNumber => 1030406; // square goza (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BrocadeGozaMatEastAddon : BaseAddon - { - [Constructible] - public BrocadeGozaMatEastAddon(int hue = 0) - { - AddComponent(new LocalizedAddonComponent(0x28AB, 1030688), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0x28AA, 1030688), 1, 0, 0); - Hue = hue; - } - - public BrocadeGozaMatEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new BrocadeGozaMatEastDeed(); - - public override bool RetainDeedHue => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BrocadeGozaMatEastDeed : BaseAddonDeed - { - [Constructible] - public BrocadeGozaMatEastDeed() - { - } - - public BrocadeGozaMatEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new BrocadeGozaMatEastAddon(Hue); - public override int LabelNumber => 1030408; // brocade goza (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BrocadeGozaMatSouthAddon : BaseAddon - { - [Constructible] - public BrocadeGozaMatSouthAddon(int hue = 0) - { - AddComponent(new LocalizedAddonComponent(0x28AD, 1030688), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0x28AC, 1030688), 0, 1, 0); - Hue = hue; - } - - public BrocadeGozaMatSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new BrocadeGozaMatSouthDeed(); - - public override bool RetainDeedHue => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BrocadeGozaMatSouthDeed : BaseAddonDeed - { - [Constructible] - public BrocadeGozaMatSouthDeed() - { - } - - public BrocadeGozaMatSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new BrocadeGozaMatSouthAddon(Hue); - public override int LabelNumber => 1030409; // brocade goza (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BrocadeSquareGozaMatEastAddon : BaseAddon - { - [Constructible] - public BrocadeSquareGozaMatEastAddon(int hue = 0) - { - AddComponent(new LocalizedAddonComponent(0x28AE, 1030688), 0, 0, 0); - Hue = hue; - } - - public BrocadeSquareGozaMatEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new BrocadeSquareGozaMatEastDeed(); - - public override bool RetainDeedHue => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BrocadeSquareGozaMatEastDeed : BaseAddonDeed - { - [Constructible] - public BrocadeSquareGozaMatEastDeed() - { - } - - public BrocadeSquareGozaMatEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new BrocadeSquareGozaMatEastAddon(Hue); - public override int LabelNumber => 1030411; // brocade square goza (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BrocadeSquareGozaMatSouthAddon : BaseAddon - { - [Constructible] - public BrocadeSquareGozaMatSouthAddon(int hue = 0) - { - AddComponent(new LocalizedAddonComponent(0x28AF, 1030688), 0, 0, 0); - Hue = hue; - } - - public BrocadeSquareGozaMatSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new BrocadeSquareGozaMatSouthDeed(); - - public override bool RetainDeedHue => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BrocadeSquareGozaMatSouthDeed : BaseAddonDeed - { - [Constructible] - public BrocadeSquareGozaMatSouthDeed() - { - } - - public BrocadeSquareGozaMatSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new BrocadeSquareGozaMatSouthAddon(Hue); - public override int LabelNumber => 1030410; // brocade square goza (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class GozaMatEastAddon : BaseAddon + { + [Constructible] + public GozaMatEastAddon(int hue = 0) + { + AddComponent(new LocalizedAddonComponent(0x28a4, 1030688), 1, 0, 0); + AddComponent(new LocalizedAddonComponent(0x28a5, 1030688), 0, 0, 0); + Hue = hue; + } + + public GozaMatEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new GozaMatEastDeed(); + + public override bool RetainDeedHue => true; + + 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 class GozaMatEastDeed : BaseAddonDeed + { + [Constructible] + public GozaMatEastDeed() + { + } + + public GozaMatEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new GozaMatEastAddon(Hue); + public override int LabelNumber => 1030404; // goza (east) + + 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 class GozaMatSouthAddon : BaseAddon + { + [Constructible] + public GozaMatSouthAddon(int hue = 0) + { + AddComponent(new LocalizedAddonComponent(0x28a6, 1030688), 0, 1, 0); + AddComponent(new LocalizedAddonComponent(0x28a7, 1030688), 0, 0, 0); + Hue = hue; + } + + public GozaMatSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new GozaMatSouthDeed(); + + public override bool RetainDeedHue => true; + + 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 class GozaMatSouthDeed : BaseAddonDeed + { + [Constructible] + public GozaMatSouthDeed() + { + } + + public GozaMatSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new GozaMatSouthAddon(Hue); + public override int LabelNumber => 1030405; // goza (south) + + 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 class SquareGozaMatEastAddon : BaseAddon + { + [Constructible] + public SquareGozaMatEastAddon(int hue = 0) + { + AddComponent(new LocalizedAddonComponent(0x28a8, 1030688), 0, 0, 0); + Hue = hue; + } + + public SquareGozaMatEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new SquareGozaMatEastDeed(); + public override int LabelNumber => 1030688; // goza mat + + public override bool RetainDeedHue => true; + + 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 class SquareGozaMatEastDeed : BaseAddonDeed + { + [Constructible] + public SquareGozaMatEastDeed() + { + } + + public SquareGozaMatEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new SquareGozaMatEastAddon(Hue); + public override int LabelNumber => 1030407; // square goza (east) + + 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 class SquareGozaMatSouthAddon : BaseAddon + { + [Constructible] + public SquareGozaMatSouthAddon(int hue = 0) + { + AddComponent(new LocalizedAddonComponent(0x28a9, 1030688), 0, 0, 0); + Hue = hue; + } + + public SquareGozaMatSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new SquareGozaMatSouthDeed(); + + public override bool RetainDeedHue => true; + + 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 class SquareGozaMatSouthDeed : BaseAddonDeed + { + [Constructible] + public SquareGozaMatSouthDeed() + { + } + + public SquareGozaMatSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new SquareGozaMatSouthAddon(Hue); + public override int LabelNumber => 1030406; // square goza (south) + + 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 class BrocadeGozaMatEastAddon : BaseAddon + { + [Constructible] + public BrocadeGozaMatEastAddon(int hue = 0) + { + AddComponent(new LocalizedAddonComponent(0x28AB, 1030688), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0x28AA, 1030688), 1, 0, 0); + Hue = hue; + } + + public BrocadeGozaMatEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new BrocadeGozaMatEastDeed(); + + public override bool RetainDeedHue => true; + + 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 class BrocadeGozaMatEastDeed : BaseAddonDeed + { + [Constructible] + public BrocadeGozaMatEastDeed() + { + } + + public BrocadeGozaMatEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new BrocadeGozaMatEastAddon(Hue); + public override int LabelNumber => 1030408; // brocade goza (east) + + 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 class BrocadeGozaMatSouthAddon : BaseAddon + { + [Constructible] + public BrocadeGozaMatSouthAddon(int hue = 0) + { + AddComponent(new LocalizedAddonComponent(0x28AD, 1030688), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0x28AC, 1030688), 0, 1, 0); + Hue = hue; + } + + public BrocadeGozaMatSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new BrocadeGozaMatSouthDeed(); + + public override bool RetainDeedHue => true; + + 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 class BrocadeGozaMatSouthDeed : BaseAddonDeed + { + [Constructible] + public BrocadeGozaMatSouthDeed() + { + } + + public BrocadeGozaMatSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new BrocadeGozaMatSouthAddon(Hue); + public override int LabelNumber => 1030409; // brocade goza (south) + + 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 class BrocadeSquareGozaMatEastAddon : BaseAddon + { + [Constructible] + public BrocadeSquareGozaMatEastAddon(int hue = 0) + { + AddComponent(new LocalizedAddonComponent(0x28AE, 1030688), 0, 0, 0); + Hue = hue; + } + + public BrocadeSquareGozaMatEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new BrocadeSquareGozaMatEastDeed(); + + public override bool RetainDeedHue => true; + + 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 class BrocadeSquareGozaMatEastDeed : BaseAddonDeed + { + [Constructible] + public BrocadeSquareGozaMatEastDeed() + { + } + + public BrocadeSquareGozaMatEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new BrocadeSquareGozaMatEastAddon(Hue); + public override int LabelNumber => 1030411; // brocade square goza (east) + + 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 class BrocadeSquareGozaMatSouthAddon : BaseAddon + { + [Constructible] + public BrocadeSquareGozaMatSouthAddon(int hue = 0) + { + AddComponent(new LocalizedAddonComponent(0x28AF, 1030688), 0, 0, 0); + Hue = hue; + } + + public BrocadeSquareGozaMatSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new BrocadeSquareGozaMatSouthDeed(); + + public override bool RetainDeedHue => true; + + 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 class BrocadeSquareGozaMatSouthDeed : BaseAddonDeed + { + [Constructible] + public BrocadeSquareGozaMatSouthDeed() + { + } + + public BrocadeSquareGozaMatSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new BrocadeSquareGozaMatSouthAddon(Hue); + public override int LabelNumber => 1030410; // brocade square goza (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/GrayBrickFireplaceEastAddon.cs b/Projects/UOContent/Items/Addons/GrayBrickFireplaceEastAddon.cs index 1e4eceac8..99b2b0a76 100644 --- a/Projects/UOContent/Items/Addons/GrayBrickFireplaceEastAddon.cs +++ b/Projects/UOContent/Items/Addons/GrayBrickFireplaceEastAddon.cs @@ -1,61 +1,61 @@ -namespace Server.Items -{ - public class GrayBrickFireplaceEastAddon : BaseAddon - { - [Constructible] - public GrayBrickFireplaceEastAddon() - { - AddComponent(new AddonComponent(0x93D), 0, 0, 0); - AddComponent(new AddonComponent(0x937), 0, 1, 0); - } - - public GrayBrickFireplaceEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new GrayBrickFireplaceEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GrayBrickFireplaceEastDeed : BaseAddonDeed - { - [Constructible] - public GrayBrickFireplaceEastDeed() - { - } - - public GrayBrickFireplaceEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new GrayBrickFireplaceEastAddon(); - public override int LabelNumber => 1061846; // grey brick fireplace (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class GrayBrickFireplaceEastAddon : BaseAddon + { + [Constructible] + public GrayBrickFireplaceEastAddon() + { + AddComponent(new AddonComponent(0x93D), 0, 0, 0); + AddComponent(new AddonComponent(0x937), 0, 1, 0); + } + + public GrayBrickFireplaceEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new GrayBrickFireplaceEastDeed(); + + 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 class GrayBrickFireplaceEastDeed : BaseAddonDeed + { + [Constructible] + public GrayBrickFireplaceEastDeed() + { + } + + public GrayBrickFireplaceEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new GrayBrickFireplaceEastAddon(); + public override int LabelNumber => 1061846; // grey brick fireplace (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/GrayBrickFireplaceSouthAddon.cs b/Projects/UOContent/Items/Addons/GrayBrickFireplaceSouthAddon.cs index dfc05f7fd..2e9b61cf1 100644 --- a/Projects/UOContent/Items/Addons/GrayBrickFireplaceSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/GrayBrickFireplaceSouthAddon.cs @@ -1,61 +1,61 @@ -namespace Server.Items -{ - public class GrayBrickFireplaceSouthAddon : BaseAddon - { - [Constructible] - public GrayBrickFireplaceSouthAddon() - { - AddComponent(new AddonComponent(0x94B), -1, 0, 0); - AddComponent(new AddonComponent(0x945), 0, 0, 0); - } - - public GrayBrickFireplaceSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new GrayBrickFireplaceSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GrayBrickFireplaceSouthDeed : BaseAddonDeed - { - [Constructible] - public GrayBrickFireplaceSouthDeed() - { - } - - public GrayBrickFireplaceSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new GrayBrickFireplaceSouthAddon(); - public override int LabelNumber => 1061847; // grey brick fireplace (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class GrayBrickFireplaceSouthAddon : BaseAddon + { + [Constructible] + public GrayBrickFireplaceSouthAddon() + { + AddComponent(new AddonComponent(0x94B), -1, 0, 0); + AddComponent(new AddonComponent(0x945), 0, 0, 0); + } + + public GrayBrickFireplaceSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new GrayBrickFireplaceSouthDeed(); + + 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 class GrayBrickFireplaceSouthDeed : BaseAddonDeed + { + [Constructible] + public GrayBrickFireplaceSouthDeed() + { + } + + public GrayBrickFireplaceSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new GrayBrickFireplaceSouthAddon(); + public override int LabelNumber => 1061847; // grey brick fireplace (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/JackOLantern.cs b/Projects/UOContent/Items/Addons/JackOLantern.cs index 6153398b2..5893b5ab4 100644 --- a/Projects/UOContent/Items/Addons/JackOLantern.cs +++ b/Projects/UOContent/Items/Addons/JackOLantern.cs @@ -1,87 +1,87 @@ -namespace Server.Items -{ - public class JackOLantern : BaseAddon - { - [Constructible] - public JackOLantern() - : this(Utility.Random(2) < 1) - { - } - - [Constructible] - public JackOLantern(bool south) - { - AddComponent(new AddonComponent(5703), 0, 0, +0); - - const int hue = 1161; - // ( 1 > Utility.Random( 5 ) ? 2118 : 1161 ); - - if (!south) - { - AddComponent(GetComponent(3178, 0), 0, 0, -1); - AddComponent(GetComponent(3883, hue), 0, 0, +1); - AddComponent(GetComponent(3862, hue), 0, 0, +0); - } - else - { - AddComponent(GetComponent(3179, 0), 0, 0, +0); - AddComponent(GetComponent(3885, hue), 0, 0, -1); - AddComponent(GetComponent(3871, hue), 0, 0, +0); - } - } - - public JackOLantern(Serial serial) - : base(serial) - { - } - - public override bool ShareHue => false; - - private static AddonComponent GetComponent(int itemID, int hue) => - new AddonComponent(itemID) - { - Hue = hue, - Name = "jack-o-lantern" - }; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write((byte)2); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadByte(); - - - if (version <= 1) - Timer.DelayCall(Fix, version); - } - - private void Fix(int version) - { - for (int i = 0; i < Components.Count; ++i) - { - var ac = Components[i]; - switch (version) - { - case 1: - { - ac.Name = "jack-o-lantern"; - goto case 0; - } - case 0: - { - if (ac.Hue == 2118) - ac.Hue = 1161; - break; - } - } - } - } - } -} +namespace Server.Items +{ + public class JackOLantern : BaseAddon + { + [Constructible] + public JackOLantern() + : this(Utility.Random(2) < 1) + { + } + + [Constructible] + public JackOLantern(bool south) + { + AddComponent(new AddonComponent(5703), 0, 0, +0); + + const int hue = 1161; + // ( 1 > Utility.Random( 5 ) ? 2118 : 1161 ); + + if (!south) + { + AddComponent(GetComponent(3178, 0), 0, 0, -1); + AddComponent(GetComponent(3883, hue), 0, 0, +1); + AddComponent(GetComponent(3862, hue), 0, 0, +0); + } + else + { + AddComponent(GetComponent(3179, 0), 0, 0, +0); + AddComponent(GetComponent(3885, hue), 0, 0, -1); + AddComponent(GetComponent(3871, hue), 0, 0, +0); + } + } + + public JackOLantern(Serial serial) + : base(serial) + { + } + + public override bool ShareHue => false; + + private static AddonComponent GetComponent(int itemID, int hue) => + new AddonComponent(itemID) + { + Hue = hue, + Name = "jack-o-lantern" + }; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write((byte)2); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + int version = reader.ReadByte(); + + + if (version <= 1) + Timer.DelayCall(Fix, version); + } + + private void Fix(int version) + { + for (var i = 0; i < Components.Count; ++i) + { + var ac = Components[i]; + switch (version) + { + case 1: + { + ac.Name = "jack-o-lantern"; + goto case 0; + } + case 0: + { + if (ac.Hue == 2118) + ac.Hue = 1161; + break; + } + } + } + } + } +} diff --git a/Projects/UOContent/Items/Addons/LargeBedEastAddon.cs b/Projects/UOContent/Items/Addons/LargeBedEastAddon.cs index 37536dbd6..0dab32b42 100644 --- a/Projects/UOContent/Items/Addons/LargeBedEastAddon.cs +++ b/Projects/UOContent/Items/Addons/LargeBedEastAddon.cs @@ -1,63 +1,63 @@ -namespace Server.Items -{ - public class LargeBedEastAddon : BaseAddon - { - [Constructible] - public LargeBedEastAddon() - { - AddComponent(new AddonComponent(0xA7D), 0, 0, 0); - AddComponent(new AddonComponent(0xA7C), 0, 1, 0); - AddComponent(new AddonComponent(0xA79), 1, 0, 0); - AddComponent(new AddonComponent(0xA78), 1, 1, 0); - } - - public LargeBedEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new LargeBedEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LargeBedEastDeed : BaseAddonDeed - { - [Constructible] - public LargeBedEastDeed() - { - } - - public LargeBedEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new LargeBedEastAddon(); - public override int LabelNumber => 1044324; // large bed (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LargeBedEastAddon : BaseAddon + { + [Constructible] + public LargeBedEastAddon() + { + AddComponent(new AddonComponent(0xA7D), 0, 0, 0); + AddComponent(new AddonComponent(0xA7C), 0, 1, 0); + AddComponent(new AddonComponent(0xA79), 1, 0, 0); + AddComponent(new AddonComponent(0xA78), 1, 1, 0); + } + + public LargeBedEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new LargeBedEastDeed(); + + 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 class LargeBedEastDeed : BaseAddonDeed + { + [Constructible] + public LargeBedEastDeed() + { + } + + public LargeBedEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new LargeBedEastAddon(); + public override int LabelNumber => 1044324; // large bed (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/LargeBedSouthAddon.cs b/Projects/UOContent/Items/Addons/LargeBedSouthAddon.cs index 002e4fc35..98d80ab0f 100644 --- a/Projects/UOContent/Items/Addons/LargeBedSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/LargeBedSouthAddon.cs @@ -1,63 +1,63 @@ -namespace Server.Items -{ - public class LargeBedSouthAddon : BaseAddon - { - [Constructible] - public LargeBedSouthAddon() - { - AddComponent(new AddonComponent(0xA83), 0, 0, 0); - AddComponent(new AddonComponent(0xA7F), 0, 1, 0); - AddComponent(new AddonComponent(0xA82), 1, 0, 0); - AddComponent(new AddonComponent(0xA7E), 1, 1, 0); - } - - public LargeBedSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new LargeBedSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LargeBedSouthDeed : BaseAddonDeed - { - [Constructible] - public LargeBedSouthDeed() - { - } - - public LargeBedSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new LargeBedSouthAddon(); - public override int LabelNumber => 1044323; // large bed (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LargeBedSouthAddon : BaseAddon + { + [Constructible] + public LargeBedSouthAddon() + { + AddComponent(new AddonComponent(0xA83), 0, 0, 0); + AddComponent(new AddonComponent(0xA7F), 0, 1, 0); + AddComponent(new AddonComponent(0xA82), 1, 0, 0); + AddComponent(new AddonComponent(0xA7E), 1, 1, 0); + } + + public LargeBedSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new LargeBedSouthDeed(); + + 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 class LargeBedSouthDeed : BaseAddonDeed + { + [Constructible] + public LargeBedSouthDeed() + { + } + + public LargeBedSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new LargeBedSouthAddon(); + public override int LabelNumber => 1044323; // large bed (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/LargeForgeEastAddon.cs b/Projects/UOContent/Items/Addons/LargeForgeEastAddon.cs index 8117f0f90..dbd1d4787 100644 --- a/Projects/UOContent/Items/Addons/LargeForgeEastAddon.cs +++ b/Projects/UOContent/Items/Addons/LargeForgeEastAddon.cs @@ -1,63 +1,63 @@ -namespace Server.Items -{ - public class LargeForgeEastAddon : BaseAddon - { - [Constructible] - public LargeForgeEastAddon() - { - AddComponent(new ForgeComponent(0x1986), 0, 0, 0); - AddComponent(new ForgeComponent(0x198A), 0, 1, 0); - AddComponent(new ForgeComponent(0x1996), 0, 2, 0); - AddComponent(new ForgeComponent(0x1992), 0, 3, 0); - } - - public LargeForgeEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new LargeForgeEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LargeForgeEastDeed : BaseAddonDeed - { - [Constructible] - public LargeForgeEastDeed() - { - } - - public LargeForgeEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new LargeForgeEastAddon(); - public override int LabelNumber => 1044331; // large forge (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LargeForgeEastAddon : BaseAddon + { + [Constructible] + public LargeForgeEastAddon() + { + AddComponent(new ForgeComponent(0x1986), 0, 0, 0); + AddComponent(new ForgeComponent(0x198A), 0, 1, 0); + AddComponent(new ForgeComponent(0x1996), 0, 2, 0); + AddComponent(new ForgeComponent(0x1992), 0, 3, 0); + } + + public LargeForgeEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new LargeForgeEastDeed(); + + 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 class LargeForgeEastDeed : BaseAddonDeed + { + [Constructible] + public LargeForgeEastDeed() + { + } + + public LargeForgeEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new LargeForgeEastAddon(); + public override int LabelNumber => 1044331; // large forge (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/LargeForgeSouthAddon.cs b/Projects/UOContent/Items/Addons/LargeForgeSouthAddon.cs index bc992f625..c35e7446c 100644 --- a/Projects/UOContent/Items/Addons/LargeForgeSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/LargeForgeSouthAddon.cs @@ -1,63 +1,63 @@ -namespace Server.Items -{ - public class LargeForgeSouthAddon : BaseAddon - { - [Constructible] - public LargeForgeSouthAddon() - { - AddComponent(new ForgeComponent(0x197A), 0, 0, 0); - AddComponent(new ForgeComponent(0x197E), 1, 0, 0); - AddComponent(new ForgeComponent(0x19A2), 2, 0, 0); - AddComponent(new ForgeComponent(0x199E), 3, 0, 0); - } - - public LargeForgeSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new LargeForgeSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LargeForgeSouthDeed : BaseAddonDeed - { - [Constructible] - public LargeForgeSouthDeed() - { - } - - public LargeForgeSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new LargeForgeSouthAddon(); - public override int LabelNumber => 1044332; // large forge (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LargeForgeSouthAddon : BaseAddon + { + [Constructible] + public LargeForgeSouthAddon() + { + AddComponent(new ForgeComponent(0x197A), 0, 0, 0); + AddComponent(new ForgeComponent(0x197E), 1, 0, 0); + AddComponent(new ForgeComponent(0x19A2), 2, 0, 0); + AddComponent(new ForgeComponent(0x199E), 3, 0, 0); + } + + public LargeForgeSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new LargeForgeSouthDeed(); + + 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 class LargeForgeSouthDeed : BaseAddonDeed + { + [Constructible] + public LargeForgeSouthDeed() + { + } + + public LargeForgeSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new LargeForgeSouthAddon(); + public override int LabelNumber => 1044332; // large forge (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/LargeStoneTableEastAddon.cs b/Projects/UOContent/Items/Addons/LargeStoneTableEastAddon.cs index ca9e28c22..a36dcdc6f 100644 --- a/Projects/UOContent/Items/Addons/LargeStoneTableEastAddon.cs +++ b/Projects/UOContent/Items/Addons/LargeStoneTableEastAddon.cs @@ -1,65 +1,65 @@ -namespace Server.Items -{ - public class LargeStoneTableEastAddon : BaseAddon - { - [Constructible] - public LargeStoneTableEastAddon(int hue = 0) - { - AddComponent(new AddonComponent(0x1202), 0, 0, 0); - AddComponent(new AddonComponent(0x1203), 0, 1, 0); - AddComponent(new AddonComponent(0x1201), 0, 2, 0); - Hue = hue; - } - - public LargeStoneTableEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new LargeStoneTableEastDeed(); - - public override bool RetainDeedHue => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LargeStoneTableEastDeed : BaseAddonDeed - { - [Constructible] - public LargeStoneTableEastDeed() - { - } - - public LargeStoneTableEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new LargeStoneTableEastAddon(Hue); - public override int LabelNumber => 1044511; // large stone table (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class LargeStoneTableEastAddon : BaseAddon + { + [Constructible] + public LargeStoneTableEastAddon(int hue = 0) + { + AddComponent(new AddonComponent(0x1202), 0, 0, 0); + AddComponent(new AddonComponent(0x1203), 0, 1, 0); + AddComponent(new AddonComponent(0x1201), 0, 2, 0); + Hue = hue; + } + + public LargeStoneTableEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new LargeStoneTableEastDeed(); + + public override bool RetainDeedHue => true; + + 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(); + } + } + + public class LargeStoneTableEastDeed : BaseAddonDeed + { + [Constructible] + public LargeStoneTableEastDeed() + { + } + + public LargeStoneTableEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new LargeStoneTableEastAddon(Hue); + public override int LabelNumber => 1044511; // large stone table (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/LargeStoneTableSouthAddon.cs b/Projects/UOContent/Items/Addons/LargeStoneTableSouthAddon.cs index 06a0bec66..b1ae0b6d5 100644 --- a/Projects/UOContent/Items/Addons/LargeStoneTableSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/LargeStoneTableSouthAddon.cs @@ -1,65 +1,65 @@ -namespace Server.Items -{ - public class LargeStoneTableSouthAddon : BaseAddon - { - [Constructible] - public LargeStoneTableSouthAddon(int hue = 0) - { - AddComponent(new AddonComponent(0x1205), 0, 0, 0); - AddComponent(new AddonComponent(0x1206), 1, 0, 0); - AddComponent(new AddonComponent(0x1204), 2, 0, 0); - Hue = hue; - } - - public LargeStoneTableSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new LargeStoneTableSouthDeed(); - - public override bool RetainDeedHue => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LargeStoneTableSouthDeed : BaseAddonDeed - { - [Constructible] - public LargeStoneTableSouthDeed() - { - } - - public LargeStoneTableSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new LargeStoneTableSouthAddon(Hue); - public override int LabelNumber => 1044512; // large stone table (South) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class LargeStoneTableSouthAddon : BaseAddon + { + [Constructible] + public LargeStoneTableSouthAddon(int hue = 0) + { + AddComponent(new AddonComponent(0x1205), 0, 0, 0); + AddComponent(new AddonComponent(0x1206), 1, 0, 0); + AddComponent(new AddonComponent(0x1204), 2, 0, 0); + Hue = hue; + } + + public LargeStoneTableSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new LargeStoneTableSouthDeed(); + + public override bool RetainDeedHue => true; + + 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(); + } + } + + public class LargeStoneTableSouthDeed : BaseAddonDeed + { + [Constructible] + public LargeStoneTableSouthDeed() + { + } + + public LargeStoneTableSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new LargeStoneTableSouthAddon(Hue); + public override int LabelNumber => 1044512; // large stone table (South) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/LoomEastAddon.cs b/Projects/UOContent/Items/Addons/LoomEastAddon.cs index a645ac28b..f16738e8d 100644 --- a/Projects/UOContent/Items/Addons/LoomEastAddon.cs +++ b/Projects/UOContent/Items/Addons/LoomEastAddon.cs @@ -1,79 +1,79 @@ -namespace Server.Items -{ - public interface ILoom - { - int Phase { get; set; } - } - - public class LoomEastAddon : BaseAddon, ILoom - { - [Constructible] - public LoomEastAddon() - { - AddComponent(new AddonComponent(0x1060), 0, 0, 0); - AddComponent(new AddonComponent(0x105F), 0, 1, 0); - } - - public LoomEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new LoomEastDeed(); - - public int Phase { get; set; } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(Phase); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - Phase = reader.ReadInt(); - break; - } - } - } - } - - public class LoomEastDeed : BaseAddonDeed - { - [Constructible] - public LoomEastDeed() - { - } - - public LoomEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new LoomEastAddon(); - public override int LabelNumber => 1044343; // loom (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public interface ILoom + { + int Phase { get; set; } + } + + public class LoomEastAddon : BaseAddon, ILoom + { + [Constructible] + public LoomEastAddon() + { + AddComponent(new AddonComponent(0x1060), 0, 0, 0); + AddComponent(new AddonComponent(0x105F), 0, 1, 0); + } + + public LoomEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new LoomEastDeed(); + + public int Phase { get; set; } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(Phase); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + Phase = reader.ReadInt(); + break; + } + } + } + } + + public class LoomEastDeed : BaseAddonDeed + { + [Constructible] + public LoomEastDeed() + { + } + + public LoomEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new LoomEastAddon(); + public override int LabelNumber => 1044343; // loom (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/LoomSouthAddon.cs b/Projects/UOContent/Items/Addons/LoomSouthAddon.cs index a3b0b32bf..13df17c7f 100644 --- a/Projects/UOContent/Items/Addons/LoomSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/LoomSouthAddon.cs @@ -1,74 +1,74 @@ -namespace Server.Items -{ - public class LoomSouthAddon : BaseAddon, ILoom - { - [Constructible] - public LoomSouthAddon() - { - AddComponent(new AddonComponent(0x1061), 0, 0, 0); - AddComponent(new AddonComponent(0x1062), 1, 0, 0); - } - - public LoomSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new LoomSouthDeed(); - - public int Phase { get; set; } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(Phase); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - Phase = reader.ReadInt(); - break; - } - } - } - } - - public class LoomSouthDeed : BaseAddonDeed - { - [Constructible] - public LoomSouthDeed() - { - } - - public LoomSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new LoomSouthAddon(); - public override int LabelNumber => 1044344; // loom (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LoomSouthAddon : BaseAddon, ILoom + { + [Constructible] + public LoomSouthAddon() + { + AddComponent(new AddonComponent(0x1061), 0, 0, 0); + AddComponent(new AddonComponent(0x1062), 1, 0, 0); + } + + public LoomSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new LoomSouthDeed(); + + public int Phase { get; set; } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(Phase); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + Phase = reader.ReadInt(); + break; + } + } + } + } + + public class LoomSouthDeed : BaseAddonDeed + { + [Constructible] + public LoomSouthDeed() + { + } + + public LoomSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new LoomSouthAddon(); + public override int LabelNumber => 1044344; // loom (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/MediumStoneTableEastAddon.cs b/Projects/UOContent/Items/Addons/MediumStoneTableEastAddon.cs index 11b547f8c..6b5d5324d 100644 --- a/Projects/UOContent/Items/Addons/MediumStoneTableEastAddon.cs +++ b/Projects/UOContent/Items/Addons/MediumStoneTableEastAddon.cs @@ -1,64 +1,64 @@ -namespace Server.Items -{ - public class MediumStoneTableEastAddon : BaseAddon - { - [Constructible] - public MediumStoneTableEastAddon(int hue = 0) - { - AddComponent(new AddonComponent(0x1202), 0, 0, 0); - AddComponent(new AddonComponent(0x1201), 0, 1, 0); - Hue = hue; - } - - public MediumStoneTableEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new MediumStoneTableEastDeed(); - - public override bool RetainDeedHue => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class MediumStoneTableEastDeed : BaseAddonDeed - { - [Constructible] - public MediumStoneTableEastDeed() - { - } - - public MediumStoneTableEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new MediumStoneTableEastAddon(Hue); - public override int LabelNumber => 1044508; // stone table (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class MediumStoneTableEastAddon : BaseAddon + { + [Constructible] + public MediumStoneTableEastAddon(int hue = 0) + { + AddComponent(new AddonComponent(0x1202), 0, 0, 0); + AddComponent(new AddonComponent(0x1201), 0, 1, 0); + Hue = hue; + } + + public MediumStoneTableEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new MediumStoneTableEastDeed(); + + public override bool RetainDeedHue => true; + + 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(); + } + } + + public class MediumStoneTableEastDeed : BaseAddonDeed + { + [Constructible] + public MediumStoneTableEastDeed() + { + } + + public MediumStoneTableEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new MediumStoneTableEastAddon(Hue); + public override int LabelNumber => 1044508; // stone table (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/MediumStoneTableSouthAddon.cs b/Projects/UOContent/Items/Addons/MediumStoneTableSouthAddon.cs index e72549714..e661e2876 100644 --- a/Projects/UOContent/Items/Addons/MediumStoneTableSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/MediumStoneTableSouthAddon.cs @@ -1,64 +1,64 @@ -namespace Server.Items -{ - public class MediumStoneTableSouthAddon : BaseAddon - { - [Constructible] - public MediumStoneTableSouthAddon(int hue = 0) - { - AddComponent(new AddonComponent(0x1205), 0, 0, 0); - AddComponent(new AddonComponent(0x1204), 1, 0, 0); - Hue = hue; - } - - public MediumStoneTableSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new MediumStoneTableSouthDeed(); - - public override bool RetainDeedHue => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class MediumStoneTableSouthDeed : BaseAddonDeed - { - [Constructible] - public MediumStoneTableSouthDeed() - { - } - - public MediumStoneTableSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new MediumStoneTableSouthAddon(Hue); - public override int LabelNumber => 1044509; // stone table (South) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class MediumStoneTableSouthAddon : BaseAddon + { + [Constructible] + public MediumStoneTableSouthAddon(int hue = 0) + { + AddComponent(new AddonComponent(0x1205), 0, 0, 0); + AddComponent(new AddonComponent(0x1204), 1, 0, 0); + Hue = hue; + } + + public MediumStoneTableSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new MediumStoneTableSouthDeed(); + + public override bool RetainDeedHue => true; + + 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(); + } + } + + public class MediumStoneTableSouthDeed : BaseAddonDeed + { + [Constructible] + public MediumStoneTableSouthDeed() + { + } + + public MediumStoneTableSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new MediumStoneTableSouthAddon(Hue); + public override int LabelNumber => 1044509; // stone table (South) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/OrnateElvenTableEastAddon.cs b/Projects/UOContent/Items/Addons/OrnateElvenTableEastAddon.cs index f24662608..edcb986a5 100644 --- a/Projects/UOContent/Items/Addons/OrnateElvenTableEastAddon.cs +++ b/Projects/UOContent/Items/Addons/OrnateElvenTableEastAddon.cs @@ -1,62 +1,62 @@ -namespace Server.Items -{ - public class OrnateElvenTableEastAddon : BaseAddon - { - [Constructible] - public OrnateElvenTableEastAddon() - { - AddComponent(new AddonComponent(0x308E), -1, 0, 0); - AddComponent(new AddonComponent(0x308D), 0, 0, 0); - AddComponent(new AddonComponent(0x308C), 1, 0, 0); - } - - public OrnateElvenTableEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new OrnateElvenTableEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class OrnateElvenTableEastDeed : BaseAddonDeed - { - [Constructible] - public OrnateElvenTableEastDeed() - { - } - - public OrnateElvenTableEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new OrnateElvenTableEastAddon(); - public override int LabelNumber => 1073384; // ornate table (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class OrnateElvenTableEastAddon : BaseAddon + { + [Constructible] + public OrnateElvenTableEastAddon() + { + AddComponent(new AddonComponent(0x308E), -1, 0, 0); + AddComponent(new AddonComponent(0x308D), 0, 0, 0); + AddComponent(new AddonComponent(0x308C), 1, 0, 0); + } + + public OrnateElvenTableEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new OrnateElvenTableEastDeed(); + + 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(); + } + } + + public class OrnateElvenTableEastDeed : BaseAddonDeed + { + [Constructible] + public OrnateElvenTableEastDeed() + { + } + + public OrnateElvenTableEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new OrnateElvenTableEastAddon(); + public override int LabelNumber => 1073384; // ornate table (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/OrnateElvenTableSouthAddon.cs b/Projects/UOContent/Items/Addons/OrnateElvenTableSouthAddon.cs index 9356a7449..e12d2aec7 100644 --- a/Projects/UOContent/Items/Addons/OrnateElvenTableSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/OrnateElvenTableSouthAddon.cs @@ -1,62 +1,62 @@ -namespace Server.Items -{ - public class OrnateElvenTableSouthAddon : BaseAddon - { - [Constructible] - public OrnateElvenTableSouthAddon() - { - AddComponent(new AddonComponent(0x308F), 0, 1, 0); - AddComponent(new AddonComponent(0x3090), 0, 0, 0); - AddComponent(new AddonComponent(0x3091), 0, -1, 0); - } - - public OrnateElvenTableSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new OrnateElvenTableSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class OrnateElvenTableSouthDeed : BaseAddonDeed - { - [Constructible] - public OrnateElvenTableSouthDeed() - { - } - - public OrnateElvenTableSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new OrnateElvenTableSouthAddon(); - public override int LabelNumber => 1072869; // ornate table (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class OrnateElvenTableSouthAddon : BaseAddon + { + [Constructible] + public OrnateElvenTableSouthAddon() + { + AddComponent(new AddonComponent(0x308F), 0, 1, 0); + AddComponent(new AddonComponent(0x3090), 0, 0, 0); + AddComponent(new AddonComponent(0x3091), 0, -1, 0); + } + + public OrnateElvenTableSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new OrnateElvenTableSouthDeed(); + + 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(); + } + } + + public class OrnateElvenTableSouthDeed : BaseAddonDeed + { + [Constructible] + public OrnateElvenTableSouthDeed() + { + } + + public OrnateElvenTableSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new OrnateElvenTableSouthAddon(); + public override int LabelNumber => 1072869; // ornate table (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/ParrotPerchAddon.cs b/Projects/UOContent/Items/Addons/ParrotPerchAddon.cs index e00db8974..20ad2a867 100644 --- a/Projects/UOContent/Items/Addons/ParrotPerchAddon.cs +++ b/Projects/UOContent/Items/Addons/ParrotPerchAddon.cs @@ -1,60 +1,60 @@ -namespace Server.Items -{ - public class ParrotPerchAddon : BaseAddon - { - [Constructible] - public ParrotPerchAddon() - { - AddComponent(new AddonComponent(0x2FF4), 0, 0, 0); - } - - public ParrotPerchAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new ParrotPerchDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ParrotPerchDeed : BaseAddonDeed - { - [Constructible] - public ParrotPerchDeed() - { - } - - public ParrotPerchDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new ParrotPerchAddon(); - public override int LabelNumber => 1072617; // parrot perch - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ParrotPerchAddon : BaseAddon + { + [Constructible] + public ParrotPerchAddon() + { + AddComponent(new AddonComponent(0x2FF4), 0, 0, 0); + } + + public ParrotPerchAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new ParrotPerchDeed(); + + 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(); + } + } + + public class ParrotPerchDeed : BaseAddonDeed + { + [Constructible] + public ParrotPerchDeed() + { + } + + public ParrotPerchDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new ParrotPerchAddon(); + public override int LabelNumber => 1072617; // parrot perch + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/PentagramAddon.cs b/Projects/UOContent/Items/Addons/PentagramAddon.cs index b04c968e2..049725ad6 100644 --- a/Projects/UOContent/Items/Addons/PentagramAddon.cs +++ b/Projects/UOContent/Items/Addons/PentagramAddon.cs @@ -1,68 +1,68 @@ -namespace Server.Items -{ - public class PentagramAddon : BaseAddon - { - [Constructible] - public PentagramAddon() - { - AddComponent(new AddonComponent(0xFE7), -1, -1, 0); - AddComponent(new AddonComponent(0xFE8), 0, -1, 0); - AddComponent(new AddonComponent(0xFEB), 1, -1, 0); - AddComponent(new AddonComponent(0xFE6), -1, 0, 0); - AddComponent(new AddonComponent(0xFEA), 0, 0, 0); - AddComponent(new AddonComponent(0xFEE), 1, 0, 0); - AddComponent(new AddonComponent(0xFE9), -1, 1, 0); - AddComponent(new AddonComponent(0xFEC), 0, 1, 0); - AddComponent(new AddonComponent(0xFED), 1, 1, 0); - } - - public PentagramAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new PentagramDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PentagramDeed : BaseAddonDeed - { - [Constructible] - public PentagramDeed() - { - } - - public PentagramDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new PentagramAddon(); - public override int LabelNumber => 1044328; // pentagram - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PentagramAddon : BaseAddon + { + [Constructible] + public PentagramAddon() + { + AddComponent(new AddonComponent(0xFE7), -1, -1, 0); + AddComponent(new AddonComponent(0xFE8), 0, -1, 0); + AddComponent(new AddonComponent(0xFEB), 1, -1, 0); + AddComponent(new AddonComponent(0xFE6), -1, 0, 0); + AddComponent(new AddonComponent(0xFEA), 0, 0, 0); + AddComponent(new AddonComponent(0xFEE), 1, 0, 0); + AddComponent(new AddonComponent(0xFE9), -1, 1, 0); + AddComponent(new AddonComponent(0xFEC), 0, 1, 0); + AddComponent(new AddonComponent(0xFED), 1, 1, 0); + } + + public PentagramAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new PentagramDeed(); + + 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 class PentagramDeed : BaseAddonDeed + { + [Constructible] + public PentagramDeed() + { + } + + public PentagramDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new PentagramAddon(); + public override int LabelNumber => 1044328; // pentagram + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/PickpocketDips.cs b/Projects/UOContent/Items/Addons/PickpocketDips.cs index 6cf3f33b7..90faf2897 100644 --- a/Projects/UOContent/Items/Addons/PickpocketDips.cs +++ b/Projects/UOContent/Items/Addons/PickpocketDips.cs @@ -1,258 +1,260 @@ -using System; - -namespace Server.Items -{ - [Flippable(0x1EC0, 0x1EC3)] - public class PickpocketDip : AddonComponent - { - private Timer m_Timer; - - public PickpocketDip(int itemID) : base(itemID) - { - MinSkill = -25.0; - MaxSkill = +25.0; - } - - public PickpocketDip(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public double MinSkill { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public double MaxSkill { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Swinging => m_Timer != null; - - public void UpdateItemID() - { - int baseItemID = 0x1EC0 + (ItemID - 0x1EC0) / 3 * 3; - - ItemID = baseItemID + (Swinging ? 1 : 0); - } - - public void BeginSwing() - { - m_Timer?.Stop(); - - m_Timer = new InternalTimer(this); - m_Timer.Start(); - - UpdateItemID(); - } - - public void EndSwing() - { - m_Timer?.Stop(); - - m_Timer = null; - - UpdateItemID(); - } - - public void Use(Mobile from) - { - from.Direction = from.GetDirectionTo(GetWorldLocation()); - - Effects.PlaySound(GetWorldLocation(), Map, 0x4F); - - if (from.CheckSkill(SkillName.Stealing, MinSkill, MaxSkill)) - { - SendLocalizedMessageTo(from, 501834); // You successfully avoid disturbing the dip while searching it. - } - else - { - Effects.PlaySound(GetWorldLocation(), Map, 0x390); - - BeginSwing(); - ProcessDelta(); - SendLocalizedMessageTo(from, 501831); // You carelessly bump the dip and start it swinging. - } - } - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 1)) - SendLocalizedMessageTo(from, 501816); // You are too far away to do that. - else if (Swinging) - SendLocalizedMessageTo(from, 501815); // You have to wait until it stops swinging. - else if (from.Skills.Stealing.Base >= MaxSkill) - SendLocalizedMessageTo(from, - 501830); // Your ability to steal cannot improve any further by simply practicing on a dummy. - else if (from.Mounted) - SendLocalizedMessageTo(from, 501829); // You can't practice on this while on a mount. - else - Use(from); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(MinSkill); - writer.Write(MaxSkill); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - MinSkill = reader.ReadDouble(); - MaxSkill = reader.ReadDouble(); - - if (MinSkill == 0.0 && MaxSkill == 30.0) - { - MinSkill = -25.0; - MaxSkill = +25.0; - } - - break; - } - } - - UpdateItemID(); - } - - private class InternalTimer : Timer - { - private readonly PickpocketDip m_Dip; - - public InternalTimer(PickpocketDip dip) : base(TimeSpan.FromSeconds(3.0)) - { - m_Dip = dip; - Priority = TimerPriority.FiftyMS; - } - - protected override void OnTick() - { - m_Dip.EndSwing(); - } - } - } - - public class PickpocketDipEastAddon : BaseAddon - { - [Constructible] - public PickpocketDipEastAddon() - { - AddComponent(new PickpocketDip(0x1EC3), 0, 0, 0); - } - - public PickpocketDipEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new PickpocketDipEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PickpocketDipEastDeed : BaseAddonDeed - { - [Constructible] - public PickpocketDipEastDeed() - { - } - - public PickpocketDipEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new PickpocketDipEastAddon(); - public override int LabelNumber => 1044337; // pickpocket dip (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PickpocketDipSouthAddon : BaseAddon - { - [Constructible] - public PickpocketDipSouthAddon() - { - AddComponent(new PickpocketDip(0x1EC0), 0, 0, 0); - } - - public PickpocketDipSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new PickpocketDipSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PickpocketDipSouthDeed : BaseAddonDeed - { - [Constructible] - public PickpocketDipSouthDeed() - { - } - - public PickpocketDipSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new PickpocketDipSouthAddon(); - public override int LabelNumber => 1044338; // pickpocket dip (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + [Flippable(0x1EC0, 0x1EC3)] + public class PickpocketDip : AddonComponent + { + private Timer m_Timer; + + public PickpocketDip(int itemID) : base(itemID) + { + MinSkill = -25.0; + MaxSkill = +25.0; + } + + public PickpocketDip(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public double MinSkill { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public double MaxSkill { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Swinging => m_Timer != null; + + public void UpdateItemID() + { + var baseItemID = 0x1EC0 + (ItemID - 0x1EC0) / 3 * 3; + + ItemID = baseItemID + (Swinging ? 1 : 0); + } + + public void BeginSwing() + { + m_Timer?.Stop(); + + m_Timer = new InternalTimer(this); + m_Timer.Start(); + + UpdateItemID(); + } + + public void EndSwing() + { + m_Timer?.Stop(); + + m_Timer = null; + + UpdateItemID(); + } + + public void Use(Mobile from) + { + from.Direction = from.GetDirectionTo(GetWorldLocation()); + + Effects.PlaySound(GetWorldLocation(), Map, 0x4F); + + if (from.CheckSkill(SkillName.Stealing, MinSkill, MaxSkill)) + { + SendLocalizedMessageTo(from, 501834); // You successfully avoid disturbing the dip while searching it. + } + else + { + Effects.PlaySound(GetWorldLocation(), Map, 0x390); + + BeginSwing(); + ProcessDelta(); + SendLocalizedMessageTo(from, 501831); // You carelessly bump the dip and start it swinging. + } + } + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 1)) + SendLocalizedMessageTo(from, 501816); // You are too far away to do that. + else if (Swinging) + SendLocalizedMessageTo(from, 501815); // You have to wait until it stops swinging. + else if (from.Skills.Stealing.Base >= MaxSkill) + SendLocalizedMessageTo( + from, + 501830 + ); // Your ability to steal cannot improve any further by simply practicing on a dummy. + else if (from.Mounted) + SendLocalizedMessageTo(from, 501829); // You can't practice on this while on a mount. + else + Use(from); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + writer.Write(MinSkill); + writer.Write(MaxSkill); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + MinSkill = reader.ReadDouble(); + MaxSkill = reader.ReadDouble(); + + if (MinSkill == 0.0 && MaxSkill == 30.0) + { + MinSkill = -25.0; + MaxSkill = +25.0; + } + + break; + } + } + + UpdateItemID(); + } + + private class InternalTimer : Timer + { + private readonly PickpocketDip m_Dip; + + public InternalTimer(PickpocketDip dip) : base(TimeSpan.FromSeconds(3.0)) + { + m_Dip = dip; + Priority = TimerPriority.FiftyMS; + } + + protected override void OnTick() + { + m_Dip.EndSwing(); + } + } + } + + public class PickpocketDipEastAddon : BaseAddon + { + [Constructible] + public PickpocketDipEastAddon() + { + AddComponent(new PickpocketDip(0x1EC3), 0, 0, 0); + } + + public PickpocketDipEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new PickpocketDipEastDeed(); + + 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 class PickpocketDipEastDeed : BaseAddonDeed + { + [Constructible] + public PickpocketDipEastDeed() + { + } + + public PickpocketDipEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new PickpocketDipEastAddon(); + public override int LabelNumber => 1044337; // pickpocket dip (east) + + 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 class PickpocketDipSouthAddon : BaseAddon + { + [Constructible] + public PickpocketDipSouthAddon() + { + AddComponent(new PickpocketDip(0x1EC0), 0, 0, 0); + } + + public PickpocketDipSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new PickpocketDipSouthDeed(); + + 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 class PickpocketDipSouthDeed : BaseAddonDeed + { + [Constructible] + public PickpocketDipSouthDeed() + { + } + + public PickpocketDipSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new PickpocketDipSouthAddon(); + public override int LabelNumber => 1044338; // pickpocket dip (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/PyramidAddon.cs b/Projects/UOContent/Items/Addons/PyramidAddon.cs index 19ae1d772..b806a72f4 100644 --- a/Projects/UOContent/Items/Addons/PyramidAddon.cs +++ b/Projects/UOContent/Items/Addons/PyramidAddon.cs @@ -1,53 +1,53 @@ -namespace Server.Items -{ - public class PyramidAddon : BaseAddon - { - [Constructible] - public PyramidAddon() - { - AddComponent(new AddonComponent(1006), 0, 0, 5); - - for (int o = 1; o <= 2; ++o) - { - AddComponent(new AddonComponent(1011), -o, -o, (2 - o) * 5); - AddComponent(new AddonComponent(1012), +o, +o, (2 - o) * 5); - AddComponent(new AddonComponent(1013), +o, -o, (2 - o) * 5); - AddComponent(new AddonComponent(1014), -o, +o, (2 - o) * 5); - } - - for (int o = -1; o <= 1; ++o) - { - AddComponent(new AddonComponent(1007), o, 2, 0); - AddComponent(new AddonComponent(1008), 2, o, 0); - AddComponent(new AddonComponent(1009), o, -2, 0); - AddComponent(new AddonComponent(1010), -2, o, 0); - } - - AddComponent(new AddonComponent(1007), 0, 1, 5); - AddComponent(new AddonComponent(1008), 1, 0, 5); - AddComponent(new AddonComponent(1009), 0, -1, 5); - AddComponent(new AddonComponent(1010), -1, 0, 5); - } - - public PyramidAddon(Serial serial) - : base(serial) - { - } - - public override bool ShareHue => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write((byte)0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadByte(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PyramidAddon : BaseAddon + { + [Constructible] + public PyramidAddon() + { + AddComponent(new AddonComponent(1006), 0, 0, 5); + + for (var o = 1; o <= 2; ++o) + { + AddComponent(new AddonComponent(1011), -o, -o, (2 - o) * 5); + AddComponent(new AddonComponent(1012), +o, +o, (2 - o) * 5); + AddComponent(new AddonComponent(1013), +o, -o, (2 - o) * 5); + AddComponent(new AddonComponent(1014), -o, +o, (2 - o) * 5); + } + + for (var o = -1; o <= 1; ++o) + { + AddComponent(new AddonComponent(1007), o, 2, 0); + AddComponent(new AddonComponent(1008), 2, o, 0); + AddComponent(new AddonComponent(1009), o, -2, 0); + AddComponent(new AddonComponent(1010), -2, o, 0); + } + + AddComponent(new AddonComponent(1007), 0, 1, 5); + AddComponent(new AddonComponent(1008), 1, 0, 5); + AddComponent(new AddonComponent(1009), 0, -1, 5); + AddComponent(new AddonComponent(1010), -1, 0, 5); + } + + public PyramidAddon(Serial serial) + : base(serial) + { + } + + public override bool ShareHue => false; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write((byte)0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + int version = reader.ReadByte(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/RejuvinationAnkhs.cs b/Projects/UOContent/Items/Addons/RejuvinationAnkhs.cs index 1967eed95..ec953aa69 100644 --- a/Projects/UOContent/Items/Addons/RejuvinationAnkhs.cs +++ b/Projects/UOContent/Items/Addons/RejuvinationAnkhs.cs @@ -1,171 +1,171 @@ -using System; - -namespace Server.Items -{ - public class RejuvinationAddonComponent : AddonComponent - { - public RejuvinationAddonComponent(int itemID) : base(itemID) - { - } - - public RejuvinationAddonComponent(Serial serial) : base(serial) - { - } - - public override void OnDoubleClick(Mobile from) - { - if (from.BeginAction()) - { - from.FixedEffect(0x373A, 1, 16); - - int random = Utility.Random(1, 4); - - if (random == 1 || random == 4) - { - from.Hits = from.HitsMax; - SendLocalizedMessageTo(from, 500801); // A sense of warmth fills your body! - } - - if (random == 2 || random == 4) - { - from.Mana = from.ManaMax; - SendLocalizedMessageTo(from, 500802); // A feeling of power surges through your veins! - } - - if (random == 3 || random == 4) - { - from.Stam = from.StamMax; - SendLocalizedMessageTo(from, 500803); // You feel as though you've slept for days! - } - - Timer.DelayCall(TimeSpan.FromHours(2.0), ReleaseUseLock_Callback, from, random); - } - } - - public virtual void ReleaseUseLock_Callback(Mobile from, int random) - { - from.EndAction(); - - if (random == 4) - { - from.Hits = from.HitsMax; - from.Mana = from.ManaMax; - from.Stam = from.StamMax; - SendLocalizedMessageTo(from, 500807); // You feel completely rejuvinated! - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public abstract class BaseRejuvinationAnkh : BaseAddon - { - private DateTime m_NextMessage; - - public BaseRejuvinationAnkh() - { - } - - public BaseRejuvinationAnkh(Serial serial) : base(serial) - { - } - - public override bool HandlesOnMovement => true; - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - base.OnMovement(m, oldLocation); - - if (m.Player && Utility.InRange(Location, m.Location, 3) && !Utility.InRange(Location, oldLocation, 3)) - if (DateTime.UtcNow >= m_NextMessage) - { - if (Components.Count > 0) - Components[0].SendLocalizedMessageTo(m, 1010061); // An overwhelming sense of peace fills you. - - m_NextMessage = DateTime.UtcNow + TimeSpan.FromSeconds(25.0); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class RejuvinationAnkhWest : BaseRejuvinationAnkh - { - [Constructible] - public RejuvinationAnkhWest() - { - AddComponent(new RejuvinationAddonComponent(0x3), 0, 0, 0); - AddComponent(new RejuvinationAddonComponent(0x2), 0, 1, 0); - } - - public RejuvinationAnkhWest(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class RejuvinationAnkhNorth : BaseRejuvinationAnkh - { - [Constructible] - public RejuvinationAnkhNorth() - { - AddComponent(new RejuvinationAddonComponent(0x4), 0, 0, 0); - AddComponent(new RejuvinationAddonComponent(0x5), 1, 0, 0); - } - - public RejuvinationAnkhNorth(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; + +namespace Server.Items +{ + public class RejuvinationAddonComponent : AddonComponent + { + public RejuvinationAddonComponent(int itemID) : base(itemID) + { + } + + public RejuvinationAddonComponent(Serial serial) : base(serial) + { + } + + public override void OnDoubleClick(Mobile from) + { + if (from.BeginAction()) + { + from.FixedEffect(0x373A, 1, 16); + + var random = Utility.Random(1, 4); + + if (random == 1 || random == 4) + { + from.Hits = from.HitsMax; + SendLocalizedMessageTo(from, 500801); // A sense of warmth fills your body! + } + + if (random == 2 || random == 4) + { + from.Mana = from.ManaMax; + SendLocalizedMessageTo(from, 500802); // A feeling of power surges through your veins! + } + + if (random == 3 || random == 4) + { + from.Stam = from.StamMax; + SendLocalizedMessageTo(from, 500803); // You feel as though you've slept for days! + } + + Timer.DelayCall(TimeSpan.FromHours(2.0), ReleaseUseLock_Callback, from, random); + } + } + + public virtual void ReleaseUseLock_Callback(Mobile from, int random) + { + from.EndAction(); + + if (random == 4) + { + from.Hits = from.HitsMax; + from.Mana = from.ManaMax; + from.Stam = from.StamMax; + SendLocalizedMessageTo(from, 500807); // You feel completely rejuvinated! + } + } + + 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(); + } + } + + public abstract class BaseRejuvinationAnkh : BaseAddon + { + private DateTime m_NextMessage; + + public BaseRejuvinationAnkh() + { + } + + public BaseRejuvinationAnkh(Serial serial) : base(serial) + { + } + + public override bool HandlesOnMovement => true; + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + base.OnMovement(m, oldLocation); + + if (m.Player && Utility.InRange(Location, m.Location, 3) && !Utility.InRange(Location, oldLocation, 3)) + if (DateTime.UtcNow >= m_NextMessage) + { + if (Components.Count > 0) + Components[0].SendLocalizedMessageTo(m, 1010061); // An overwhelming sense of peace fills you. + + m_NextMessage = DateTime.UtcNow + TimeSpan.FromSeconds(25.0); + } + } + + 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(); + } + } + + public class RejuvinationAnkhWest : BaseRejuvinationAnkh + { + [Constructible] + public RejuvinationAnkhWest() + { + AddComponent(new RejuvinationAddonComponent(0x3), 0, 0, 0); + AddComponent(new RejuvinationAddonComponent(0x2), 0, 1, 0); + } + + public RejuvinationAnkhWest(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class RejuvinationAnkhNorth : BaseRejuvinationAnkh + { + [Constructible] + public RejuvinationAnkhNorth() + { + AddComponent(new RejuvinationAddonComponent(0x4), 0, 0, 0); + AddComponent(new RejuvinationAddonComponent(0x5), 1, 0, 0); + } + + public RejuvinationAnkhNorth(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/SHTeleporter.cs b/Projects/UOContent/Items/Addons/SHTeleporter.cs index 1b3996e3f..489ef80fd 100644 --- a/Projects/UOContent/Items/Addons/SHTeleporter.cs +++ b/Projects/UOContent/Items/Addons/SHTeleporter.cs @@ -1,415 +1,419 @@ -using System; -using System.Linq; -using Server.Mobiles; - -namespace Server.Items -{ - public class SHTeleComponent : AddonComponent - { - private bool m_Active; - private SHTeleComponent m_TeleDest; - - [Constructible] - public SHTeleComponent(int itemID = 0x1775) : this(itemID, new Point3D(0, 0, 0)) - { - } - - [Constructible] - public SHTeleComponent(int itemID, Point3D offset) : base(itemID) - { - Movable = false; - Hue = 1; - - m_Active = true; - TeleOffset = offset; - } - - public SHTeleComponent(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Active - { - get => m_Active; - set - { - m_Active = value; - - if (Addon is SHTeleporter sourceAddon) - sourceAddon.ChangeActive(value); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D TeleOffset { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D TelePoint - { - get => new Point3D(Location.X + TeleOffset.X, Location.Y + TeleOffset.Y, Location.Z + TeleOffset.Z); - set => TeleOffset = new Point3D(value.X - Location.X, value.Y - Location.Y, value.Z - Location.Z); - } - - [CommandProperty(AccessLevel.GameMaster)] - public SHTeleComponent TeleDest - { - get => m_TeleDest; - set - { - m_TeleDest = value; - - if (Addon is SHTeleporter sourceAddon) - sourceAddon.ChangeDest(value); - } - } - - public override string DefaultName => "a hole"; - - public override void OnDoubleClick(Mobile m) - { - if (!m_Active || m_TeleDest?.Deleted != false || m_TeleDest.Map == Map.Internal) - return; - - if (m.InRange(this, 3)) - { - Map map = m_TeleDest.Map; - Point3D p = m_TeleDest.TelePoint; - - BaseCreature.TeleportPets(m, p, map); - - m.MoveToWorld(p, map); - } - else - { - m.SendLocalizedMessage(1019045); // I can't reach that. - } - } - - public override void OnDoubleClickDead(Mobile m) - { - OnDoubleClick(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Active); - writer.Write(m_TeleDest); - writer.Write(TeleOffset); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Active = reader.ReadBool(); - m_TeleDest = reader.ReadItem() as SHTeleComponent; - TeleOffset = reader.ReadPoint3D(); - } - } - - public class SHTeleporter : BaseAddon - { - private bool m_Changing; - - [Constructible] - public SHTeleporter(bool external = true) - { - m_Changing = false; - External = external; - - if (external) - { - AddComponent(new AddonComponent(0x549), -1, -1, 0); - AddComponent(new AddonComponent(0x54D), 0, -1, 0); - AddComponent(new AddonComponent(0x54E), 1, -1, 0); - AddComponent(new AddonComponent(0x548), 2, -1, 0); - AddComponent(new AddonComponent(0x54B), -1, 0, 0); - AddComponent(new AddonComponent(0x53B), 0, 0, 0); - AddComponent(new AddonComponent(0x53B), 1, 0, 0); - AddComponent(new AddonComponent(0x544), 2, 0, 0); - AddComponent(new AddonComponent(0x54C), -1, 1, 0); - AddComponent(new AddonComponent(0x53B), 0, 1, 0); - AddComponent(new AddonComponent(0x53B), 1, 1, 0); - AddComponent(new AddonComponent(0x545), 2, 1, 0); - AddComponent(new AddonComponent(0x547), -1, 2, 0); - AddComponent(new AddonComponent(0x541), 0, 2, 0); - AddComponent(new AddonComponent(0x543), 1, 2, 0); - AddComponent(new AddonComponent(0x540), 2, 2, 0); - } - - Point3D upOS = external ? new Point3D(-1, 0, 0) : new Point3D(-2, -1, 0); - UpTele = new SHTeleComponent(external ? 0x1775 : 0x495, upOS); - AddComponent(UpTele, 0, 0, 0); - - Point3D rightOS = external ? new Point3D(-2, 0, 0) : new Point3D(2, -1, 0); - RightTele = new SHTeleComponent(external ? 0x1775 : 0x495, rightOS); - AddComponent(RightTele, 1, 0, 0); - - Point3D downOS = external ? new Point3D(-2, -1, 0) : new Point3D(2, 2, 0); - DownTele = new SHTeleComponent(external ? 0x1776 : 0x495, downOS); - AddComponent(DownTele, 1, 1, 0); - - Point3D leftOS = external ? new Point3D(-1, -1, 0) : new Point3D(-1, 2, 0); - LeftTele = new SHTeleComponent(external ? 0x1775 : 0x495, leftOS); - AddComponent(LeftTele, 0, 1, 0); - } - - public SHTeleporter(Serial serial) : base(serial) => m_Changing = false; - - [CommandProperty(AccessLevel.GameMaster)] - public bool External { get; private set; } - - public SHTeleComponent UpTele { get; private set; } - - public SHTeleComponent RightTele { get; private set; } - - public SHTeleComponent DownTele { get; private set; } - - public SHTeleComponent LeftTele { get; private set; } - - public override bool ShareHue => false; - - public static void Initialize() - { - CommandSystem.Register("SHTelGen", AccessLevel.Administrator, SHTelGen_OnCommand); - } - - [Usage("SHTelGen")] - [Description("Generates solen hives teleporters.")] - public static void SHTelGen_OnCommand(CommandEventArgs e) - { - World.Broadcast(0x35, true, "Solen hives teleporters are being generated, please wait."); - - DateTime startTime = DateTime.UtcNow; - - int count = new SHTeleporterCreator().CreateSHTeleporters(); - - DateTime endTime = DateTime.UtcNow; - - World.Broadcast(0x35, true, - "{0} solen hives teleporters have been created. The entire process took {1:F1} seconds.", count, - (endTime - startTime).TotalSeconds); - } - - public void ChangeActive(bool active) - { - if (m_Changing) - return; - - m_Changing = true; - - UpTele.Active = active; - RightTele.Active = active; - DownTele.Active = active; - LeftTele.Active = active; - - m_Changing = false; - } - - public void ChangeDest(SHTeleComponent dest) - { - if (m_Changing) - return; - - m_Changing = true; - - if (!(dest?.Addon is SHTeleporter)) - { - UpTele.TeleDest = dest; - RightTele.TeleDest = dest; - DownTele.TeleDest = dest; - LeftTele.TeleDest = dest; - } - else - { - SHTeleporter destAddon = (SHTeleporter)dest.Addon; - - UpTele.TeleDest = destAddon.UpTele; - RightTele.TeleDest = destAddon.RightTele; - DownTele.TeleDest = destAddon.DownTele; - LeftTele.TeleDest = destAddon.LeftTele; - } - - m_Changing = false; - } - - public void ChangeDest(SHTeleporter destAddon) - { - if (m_Changing) - return; - - m_Changing = true; - - if (destAddon != null) - { - UpTele.TeleDest = destAddon.UpTele; - RightTele.TeleDest = destAddon.RightTele; - DownTele.TeleDest = destAddon.DownTele; - LeftTele.TeleDest = destAddon.LeftTele; - } - else - { - UpTele.TeleDest = null; - RightTele.TeleDest = null; - DownTele.TeleDest = null; - LeftTele.TeleDest = null; - } - - m_Changing = false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(External); - - writer.Write(UpTele); - writer.Write(RightTele); - writer.Write(DownTele); - writer.Write(LeftTele); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - External = reader.ReadBool(); - - UpTele = (SHTeleComponent)reader.ReadItem(); - RightTele = (SHTeleComponent)reader.ReadItem(); - DownTele = (SHTeleComponent)reader.ReadItem(); - LeftTele = (SHTeleComponent)reader.ReadItem(); - } - - public class SHTeleporterCreator - { - private int m_Count; - - public SHTeleporterCreator() => m_Count = 0; - - public static SHTeleporter FindSHTeleporter(Map map, Point3D p) - { - IPooledEnumerable eable = map.GetItemsInRange(p, 0); - SHTeleporter teleporter = eable.FirstOrDefault(item => item.Z == p.Z); - eable.Free(); - return teleporter; - } - - public SHTeleporter AddSHT(Map map, bool ext, int x, int y, int z) - { - Point3D p = new Point3D(x, y, z); - SHTeleporter tele = FindSHTeleporter(map, p); - - if (tele == null) - { - tele = new SHTeleporter(ext); - tele.MoveToWorld(p, map); - - m_Count++; - } - - return tele; - } - - public static void Link(SHTeleporter tele1, SHTeleporter tele2) - { - tele1.ChangeDest(tele2); - tele2.ChangeDest(tele1); - } - - public void AddSHTCouple(Map map, bool ext1, int x1, int y1, int z1, bool ext2, int x2, int y2, int z2) - { - SHTeleporter tele1 = AddSHT(map, ext1, x1, y1, z1); - SHTeleporter tele2 = AddSHT(map, ext2, x2, y2, z2); - - Link(tele1, tele2); - } - - public void AddSHTCouple(bool ext1, int x1, int y1, int z1, bool ext2, int x2, int y2, int z2) - { - AddSHTCouple(Map.Trammel, ext1, x1, y1, z1, ext2, x2, y2, z2); - AddSHTCouple(Map.Felucca, ext1, x1, y1, z1, ext2, x2, y2, z2); - } - - public int CreateSHTeleporters() - { - SHTeleporter tele1, tele2; - - AddSHTCouple(true, 2608, 763, 0, false, 5918, 1794, 0); - AddSHTCouple(false, 5897, 1877, 0, false, 5871, 1867, 0); - AddSHTCouple(false, 5852, 1848, 0, false, 5771, 1867, 0); - - tele1 = AddSHT(Map.Trammel, false, 5747, 1895, 0); - tele1.LeftTele.TeleOffset = new Point3D(-1, 3, 0); - tele2 = AddSHT(Map.Trammel, false, 5658, 1898, 0); - Link(tele1, tele2); - - tele1 = AddSHT(Map.Felucca, false, 5747, 1895, 0); - tele1.LeftTele.TeleOffset = new Point3D(-1, 3, 0); - tele2 = AddSHT(Map.Felucca, false, 5658, 1898, 0); - Link(tele1, tele2); - - AddSHTCouple(false, 5727, 1894, 0, false, 5756, 1794, 0); - AddSHTCouple(false, 5784, 1929, 0, false, 5700, 1929, 0); - - tele1 = AddSHT(Map.Trammel, false, 5711, 1952, 0); - tele1.LeftTele.TeleOffset = new Point3D(-1, 3, 0); - tele2 = AddSHT(Map.Trammel, false, 5657, 1954, 0); - Link(tele1, tele2); - - tele1 = AddSHT(Map.Felucca, false, 5711, 1952, 0); - tele1.LeftTele.TeleOffset = new Point3D(-1, 3, 0); - tele2 = AddSHT(Map.Felucca, false, 5657, 1954, 0); - Link(tele1, tele2); - - tele1 = AddSHT(Map.Trammel, false, 5655, 2018, 0); - tele1.LeftTele.TeleOffset = new Point3D(-1, 3, 0); - tele2 = AddSHT(Map.Trammel, true, 1690, 2789, 0); - Link(tele1, tele2); - - tele1 = AddSHT(Map.Felucca, false, 5655, 2018, 0); - tele1.LeftTele.TeleOffset = new Point3D(-1, 3, 0); - tele2 = AddSHT(Map.Felucca, true, 1690, 2789, 0); - Link(tele1, tele2); - - AddSHTCouple(false, 5809, 1905, 0, false, 5876, 1891, 0); - - tele1 = AddSHT(Map.Trammel, false, 5814, 2015, 0); - tele1.LeftTele.TeleOffset = new Point3D(-1, 3, 0); - tele2 = AddSHT(Map.Trammel, false, 5913, 1893, 0); - Link(tele1, tele2); - - tele1 = AddSHT(Map.Felucca, false, 5814, 2015, 0); - tele1.LeftTele.TeleOffset = new Point3D(-1, 3, 0); - tele2 = AddSHT(Map.Felucca, false, 5913, 1893, 0); - Link(tele1, tele2); - - AddSHTCouple(false, 5919, 2021, 0, true, 1724, 814, 0); - - tele1 = AddSHT(Map.Trammel, false, 5654, 1791, 0); - tele2 = AddSHT(Map.Trammel, true, 730, 1451, 0); - Link(tele1, tele2); - AddSHT(Map.Trammel, false, 5734, 1859, 0).ChangeDest(tele2); - - tele1 = AddSHT(Map.Felucca, false, 5654, 1791, 0); - tele2 = AddSHT(Map.Felucca, true, 730, 1451, 0); - Link(tele1, tele2); - AddSHT(Map.Felucca, false, 5734, 1859, 0).ChangeDest(tele2); - - return m_Count; - } - } - } -} +using System; +using System.Linq; +using Server.Mobiles; + +namespace Server.Items +{ + public class SHTeleComponent : AddonComponent + { + private bool m_Active; + private SHTeleComponent m_TeleDest; + + [Constructible] + public SHTeleComponent(int itemID = 0x1775) : this(itemID, new Point3D(0, 0, 0)) + { + } + + [Constructible] + public SHTeleComponent(int itemID, Point3D offset) : base(itemID) + { + Movable = false; + Hue = 1; + + m_Active = true; + TeleOffset = offset; + } + + public SHTeleComponent(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Active + { + get => m_Active; + set + { + m_Active = value; + + if (Addon is SHTeleporter sourceAddon) + sourceAddon.ChangeActive(value); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D TeleOffset { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D TelePoint + { + get => new Point3D(Location.X + TeleOffset.X, Location.Y + TeleOffset.Y, Location.Z + TeleOffset.Z); + set => TeleOffset = new Point3D(value.X - Location.X, value.Y - Location.Y, value.Z - Location.Z); + } + + [CommandProperty(AccessLevel.GameMaster)] + public SHTeleComponent TeleDest + { + get => m_TeleDest; + set + { + m_TeleDest = value; + + if (Addon is SHTeleporter sourceAddon) + sourceAddon.ChangeDest(value); + } + } + + public override string DefaultName => "a hole"; + + public override void OnDoubleClick(Mobile m) + { + if (!m_Active || m_TeleDest?.Deleted != false || m_TeleDest.Map == Map.Internal) + return; + + if (m.InRange(this, 3)) + { + var map = m_TeleDest.Map; + var p = m_TeleDest.TelePoint; + + BaseCreature.TeleportPets(m, p, map); + + m.MoveToWorld(p, map); + } + else + { + m.SendLocalizedMessage(1019045); // I can't reach that. + } + } + + public override void OnDoubleClickDead(Mobile m) + { + OnDoubleClick(m); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Active); + writer.Write(m_TeleDest); + writer.Write(TeleOffset); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Active = reader.ReadBool(); + m_TeleDest = reader.ReadItem() as SHTeleComponent; + TeleOffset = reader.ReadPoint3D(); + } + } + + public class SHTeleporter : BaseAddon + { + private bool m_Changing; + + [Constructible] + public SHTeleporter(bool external = true) + { + m_Changing = false; + External = external; + + if (external) + { + AddComponent(new AddonComponent(0x549), -1, -1, 0); + AddComponent(new AddonComponent(0x54D), 0, -1, 0); + AddComponent(new AddonComponent(0x54E), 1, -1, 0); + AddComponent(new AddonComponent(0x548), 2, -1, 0); + AddComponent(new AddonComponent(0x54B), -1, 0, 0); + AddComponent(new AddonComponent(0x53B), 0, 0, 0); + AddComponent(new AddonComponent(0x53B), 1, 0, 0); + AddComponent(new AddonComponent(0x544), 2, 0, 0); + AddComponent(new AddonComponent(0x54C), -1, 1, 0); + AddComponent(new AddonComponent(0x53B), 0, 1, 0); + AddComponent(new AddonComponent(0x53B), 1, 1, 0); + AddComponent(new AddonComponent(0x545), 2, 1, 0); + AddComponent(new AddonComponent(0x547), -1, 2, 0); + AddComponent(new AddonComponent(0x541), 0, 2, 0); + AddComponent(new AddonComponent(0x543), 1, 2, 0); + AddComponent(new AddonComponent(0x540), 2, 2, 0); + } + + var upOS = external ? new Point3D(-1, 0, 0) : new Point3D(-2, -1, 0); + UpTele = new SHTeleComponent(external ? 0x1775 : 0x495, upOS); + AddComponent(UpTele, 0, 0, 0); + + var rightOS = external ? new Point3D(-2, 0, 0) : new Point3D(2, -1, 0); + RightTele = new SHTeleComponent(external ? 0x1775 : 0x495, rightOS); + AddComponent(RightTele, 1, 0, 0); + + var downOS = external ? new Point3D(-2, -1, 0) : new Point3D(2, 2, 0); + DownTele = new SHTeleComponent(external ? 0x1776 : 0x495, downOS); + AddComponent(DownTele, 1, 1, 0); + + var leftOS = external ? new Point3D(-1, -1, 0) : new Point3D(-1, 2, 0); + LeftTele = new SHTeleComponent(external ? 0x1775 : 0x495, leftOS); + AddComponent(LeftTele, 0, 1, 0); + } + + public SHTeleporter(Serial serial) : base(serial) => m_Changing = false; + + [CommandProperty(AccessLevel.GameMaster)] + public bool External { get; private set; } + + public SHTeleComponent UpTele { get; private set; } + + public SHTeleComponent RightTele { get; private set; } + + public SHTeleComponent DownTele { get; private set; } + + public SHTeleComponent LeftTele { get; private set; } + + public override bool ShareHue => false; + + public static void Initialize() + { + CommandSystem.Register("SHTelGen", AccessLevel.Administrator, SHTelGen_OnCommand); + } + + [Usage("SHTelGen")] + [Description("Generates solen hives teleporters.")] + public static void SHTelGen_OnCommand(CommandEventArgs e) + { + World.Broadcast(0x35, true, "Solen hives teleporters are being generated, please wait."); + + var startTime = DateTime.UtcNow; + + var count = new SHTeleporterCreator().CreateSHTeleporters(); + + var endTime = DateTime.UtcNow; + + World.Broadcast( + 0x35, + true, + "{0} solen hives teleporters have been created. The entire process took {1:F1} seconds.", + count, + (endTime - startTime).TotalSeconds + ); + } + + public void ChangeActive(bool active) + { + if (m_Changing) + return; + + m_Changing = true; + + UpTele.Active = active; + RightTele.Active = active; + DownTele.Active = active; + LeftTele.Active = active; + + m_Changing = false; + } + + public void ChangeDest(SHTeleComponent dest) + { + if (m_Changing) + return; + + m_Changing = true; + + if (!(dest?.Addon is SHTeleporter)) + { + UpTele.TeleDest = dest; + RightTele.TeleDest = dest; + DownTele.TeleDest = dest; + LeftTele.TeleDest = dest; + } + else + { + var destAddon = (SHTeleporter)dest.Addon; + + UpTele.TeleDest = destAddon.UpTele; + RightTele.TeleDest = destAddon.RightTele; + DownTele.TeleDest = destAddon.DownTele; + LeftTele.TeleDest = destAddon.LeftTele; + } + + m_Changing = false; + } + + public void ChangeDest(SHTeleporter destAddon) + { + if (m_Changing) + return; + + m_Changing = true; + + if (destAddon != null) + { + UpTele.TeleDest = destAddon.UpTele; + RightTele.TeleDest = destAddon.RightTele; + DownTele.TeleDest = destAddon.DownTele; + LeftTele.TeleDest = destAddon.LeftTele; + } + else + { + UpTele.TeleDest = null; + RightTele.TeleDest = null; + DownTele.TeleDest = null; + LeftTele.TeleDest = null; + } + + m_Changing = false; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(External); + + writer.Write(UpTele); + writer.Write(RightTele); + writer.Write(DownTele); + writer.Write(LeftTele); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + External = reader.ReadBool(); + + UpTele = (SHTeleComponent)reader.ReadItem(); + RightTele = (SHTeleComponent)reader.ReadItem(); + DownTele = (SHTeleComponent)reader.ReadItem(); + LeftTele = (SHTeleComponent)reader.ReadItem(); + } + + public class SHTeleporterCreator + { + private int m_Count; + + public SHTeleporterCreator() => m_Count = 0; + + public static SHTeleporter FindSHTeleporter(Map map, Point3D p) + { + var eable = map.GetItemsInRange(p, 0); + var teleporter = eable.FirstOrDefault(item => item.Z == p.Z); + eable.Free(); + return teleporter; + } + + public SHTeleporter AddSHT(Map map, bool ext, int x, int y, int z) + { + var p = new Point3D(x, y, z); + var tele = FindSHTeleporter(map, p); + + if (tele == null) + { + tele = new SHTeleporter(ext); + tele.MoveToWorld(p, map); + + m_Count++; + } + + return tele; + } + + public static void Link(SHTeleporter tele1, SHTeleporter tele2) + { + tele1.ChangeDest(tele2); + tele2.ChangeDest(tele1); + } + + public void AddSHTCouple(Map map, bool ext1, int x1, int y1, int z1, bool ext2, int x2, int y2, int z2) + { + var tele1 = AddSHT(map, ext1, x1, y1, z1); + var tele2 = AddSHT(map, ext2, x2, y2, z2); + + Link(tele1, tele2); + } + + public void AddSHTCouple(bool ext1, int x1, int y1, int z1, bool ext2, int x2, int y2, int z2) + { + AddSHTCouple(Map.Trammel, ext1, x1, y1, z1, ext2, x2, y2, z2); + AddSHTCouple(Map.Felucca, ext1, x1, y1, z1, ext2, x2, y2, z2); + } + + public int CreateSHTeleporters() + { + SHTeleporter tele1, tele2; + + AddSHTCouple(true, 2608, 763, 0, false, 5918, 1794, 0); + AddSHTCouple(false, 5897, 1877, 0, false, 5871, 1867, 0); + AddSHTCouple(false, 5852, 1848, 0, false, 5771, 1867, 0); + + tele1 = AddSHT(Map.Trammel, false, 5747, 1895, 0); + tele1.LeftTele.TeleOffset = new Point3D(-1, 3, 0); + tele2 = AddSHT(Map.Trammel, false, 5658, 1898, 0); + Link(tele1, tele2); + + tele1 = AddSHT(Map.Felucca, false, 5747, 1895, 0); + tele1.LeftTele.TeleOffset = new Point3D(-1, 3, 0); + tele2 = AddSHT(Map.Felucca, false, 5658, 1898, 0); + Link(tele1, tele2); + + AddSHTCouple(false, 5727, 1894, 0, false, 5756, 1794, 0); + AddSHTCouple(false, 5784, 1929, 0, false, 5700, 1929, 0); + + tele1 = AddSHT(Map.Trammel, false, 5711, 1952, 0); + tele1.LeftTele.TeleOffset = new Point3D(-1, 3, 0); + tele2 = AddSHT(Map.Trammel, false, 5657, 1954, 0); + Link(tele1, tele2); + + tele1 = AddSHT(Map.Felucca, false, 5711, 1952, 0); + tele1.LeftTele.TeleOffset = new Point3D(-1, 3, 0); + tele2 = AddSHT(Map.Felucca, false, 5657, 1954, 0); + Link(tele1, tele2); + + tele1 = AddSHT(Map.Trammel, false, 5655, 2018, 0); + tele1.LeftTele.TeleOffset = new Point3D(-1, 3, 0); + tele2 = AddSHT(Map.Trammel, true, 1690, 2789, 0); + Link(tele1, tele2); + + tele1 = AddSHT(Map.Felucca, false, 5655, 2018, 0); + tele1.LeftTele.TeleOffset = new Point3D(-1, 3, 0); + tele2 = AddSHT(Map.Felucca, true, 1690, 2789, 0); + Link(tele1, tele2); + + AddSHTCouple(false, 5809, 1905, 0, false, 5876, 1891, 0); + + tele1 = AddSHT(Map.Trammel, false, 5814, 2015, 0); + tele1.LeftTele.TeleOffset = new Point3D(-1, 3, 0); + tele2 = AddSHT(Map.Trammel, false, 5913, 1893, 0); + Link(tele1, tele2); + + tele1 = AddSHT(Map.Felucca, false, 5814, 2015, 0); + tele1.LeftTele.TeleOffset = new Point3D(-1, 3, 0); + tele2 = AddSHT(Map.Felucca, false, 5913, 1893, 0); + Link(tele1, tele2); + + AddSHTCouple(false, 5919, 2021, 0, true, 1724, 814, 0); + + tele1 = AddSHT(Map.Trammel, false, 5654, 1791, 0); + tele2 = AddSHT(Map.Trammel, true, 730, 1451, 0); + Link(tele1, tele2); + AddSHT(Map.Trammel, false, 5734, 1859, 0).ChangeDest(tele2); + + tele1 = AddSHT(Map.Felucca, false, 5654, 1791, 0); + tele2 = AddSHT(Map.Felucca, true, 730, 1451, 0); + Link(tele1, tele2); + AddSHT(Map.Felucca, false, 5734, 1859, 0).ChangeDest(tele2); + + return m_Count; + } + } + } +} diff --git a/Projects/UOContent/Items/Addons/SandstoneFireplaceEastAddon.cs b/Projects/UOContent/Items/Addons/SandstoneFireplaceEastAddon.cs index 230547d1b..f9a6ce90c 100644 --- a/Projects/UOContent/Items/Addons/SandstoneFireplaceEastAddon.cs +++ b/Projects/UOContent/Items/Addons/SandstoneFireplaceEastAddon.cs @@ -1,61 +1,61 @@ -namespace Server.Items -{ - public class SandstoneFireplaceEastAddon : BaseAddon - { - [Constructible] - public SandstoneFireplaceEastAddon() - { - AddComponent(new AddonComponent(0x489), 0, 0, 0); - AddComponent(new AddonComponent(0x475), 0, 1, 0); - } - - public SandstoneFireplaceEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new SandstoneFireplaceEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SandstoneFireplaceEastDeed : BaseAddonDeed - { - [Constructible] - public SandstoneFireplaceEastDeed() - { - } - - public SandstoneFireplaceEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new SandstoneFireplaceEastAddon(); - public override int LabelNumber => 1061844; // sandstone fireplace (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SandstoneFireplaceEastAddon : BaseAddon + { + [Constructible] + public SandstoneFireplaceEastAddon() + { + AddComponent(new AddonComponent(0x489), 0, 0, 0); + AddComponent(new AddonComponent(0x475), 0, 1, 0); + } + + public SandstoneFireplaceEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new SandstoneFireplaceEastDeed(); + + 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 class SandstoneFireplaceEastDeed : BaseAddonDeed + { + [Constructible] + public SandstoneFireplaceEastDeed() + { + } + + public SandstoneFireplaceEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new SandstoneFireplaceEastAddon(); + public override int LabelNumber => 1061844; // sandstone fireplace (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/SandstoneFireplaceSouthAddon.cs b/Projects/UOContent/Items/Addons/SandstoneFireplaceSouthAddon.cs index 96289269e..f0384eb83 100644 --- a/Projects/UOContent/Items/Addons/SandstoneFireplaceSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/SandstoneFireplaceSouthAddon.cs @@ -1,61 +1,61 @@ -namespace Server.Items -{ - public class SandstoneFireplaceSouthAddon : BaseAddon - { - [Constructible] - public SandstoneFireplaceSouthAddon() - { - AddComponent(new AddonComponent(0x482), -1, 0, 0); - AddComponent(new AddonComponent(0x47B), 0, 0, 0); - } - - public SandstoneFireplaceSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new SandstoneFireplaceSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SandstoneFireplaceSouthDeed : BaseAddonDeed - { - [Constructible] - public SandstoneFireplaceSouthDeed() - { - } - - public SandstoneFireplaceSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new SandstoneFireplaceSouthAddon(); - public override int LabelNumber => 1061845; // sandstone fireplace (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SandstoneFireplaceSouthAddon : BaseAddon + { + [Constructible] + public SandstoneFireplaceSouthAddon() + { + AddComponent(new AddonComponent(0x482), -1, 0, 0); + AddComponent(new AddonComponent(0x47B), 0, 0, 0); + } + + public SandstoneFireplaceSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new SandstoneFireplaceSouthDeed(); + + 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 class SandstoneFireplaceSouthDeed : BaseAddonDeed + { + [Constructible] + public SandstoneFireplaceSouthDeed() + { + } + + public SandstoneFireplaceSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new SandstoneFireplaceSouthAddon(); + public override int LabelNumber => 1061845; // sandstone fireplace (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/SandstoneFountainAddon.cs b/Projects/UOContent/Items/Addons/SandstoneFountainAddon.cs index 84c4c90a3..3b944e9b4 100644 --- a/Projects/UOContent/Items/Addons/SandstoneFountainAddon.cs +++ b/Projects/UOContent/Items/Addons/SandstoneFountainAddon.cs @@ -1,51 +1,51 @@ -namespace Server.Items -{ - public class SandstoneFountainAddon : BaseAddon - { - [Constructible] - public SandstoneFountainAddon() - { - int itemID = 0x19C3; - - AddComponent(new AddonComponent(itemID++), -2, +1, 0); - AddComponent(new AddonComponent(itemID++), -1, +1, 0); - AddComponent(new AddonComponent(itemID++), +0, +1, 0); - AddComponent(new AddonComponent(itemID++), +1, +1, 0); - - AddComponent(new AddonComponent(itemID++), +1, +0, 0); - AddComponent(new AddonComponent(itemID++), +1, -1, 0); - AddComponent(new AddonComponent(itemID++), +1, -2, 0); - - AddComponent(new AddonComponent(itemID++), +0, -2, 0); - AddComponent(new AddonComponent(itemID++), +0, -1, 0); - AddComponent(new AddonComponent(itemID++), +0, +0, 0); - - AddComponent(new AddonComponent(itemID++), -1, +0, 0); - AddComponent(new AddonComponent(itemID++), -2, +0, 0); - - AddComponent(new AddonComponent(itemID++), -2, -1, 0); - AddComponent(new AddonComponent(itemID++), -1, -1, 0); - - AddComponent(new AddonComponent(itemID++), -1, -2, 0); - AddComponent(new AddonComponent(++itemID), -2, -2, 0); - } - - public SandstoneFountainAddon(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SandstoneFountainAddon : BaseAddon + { + [Constructible] + public SandstoneFountainAddon() + { + var itemID = 0x19C3; + + AddComponent(new AddonComponent(itemID++), -2, +1, 0); + AddComponent(new AddonComponent(itemID++), -1, +1, 0); + AddComponent(new AddonComponent(itemID++), +0, +1, 0); + AddComponent(new AddonComponent(itemID++), +1, +1, 0); + + AddComponent(new AddonComponent(itemID++), +1, +0, 0); + AddComponent(new AddonComponent(itemID++), +1, -1, 0); + AddComponent(new AddonComponent(itemID++), +1, -2, 0); + + AddComponent(new AddonComponent(itemID++), +0, -2, 0); + AddComponent(new AddonComponent(itemID++), +0, -1, 0); + AddComponent(new AddonComponent(itemID++), +0, +0, 0); + + AddComponent(new AddonComponent(itemID++), -1, +0, 0); + AddComponent(new AddonComponent(itemID++), -2, +0, 0); + + AddComponent(new AddonComponent(itemID++), -2, -1, 0); + AddComponent(new AddonComponent(itemID++), -1, -1, 0); + + AddComponent(new AddonComponent(itemID++), -1, -2, 0); + AddComponent(new AddonComponent(++itemID), -2, -2, 0); + } + + public SandstoneFountainAddon(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/SerpentPillarAddon.cs b/Projects/UOContent/Items/Addons/SerpentPillarAddon.cs index 81481f1dc..bd2731670 100644 --- a/Projects/UOContent/Items/Addons/SerpentPillarAddon.cs +++ b/Projects/UOContent/Items/Addons/SerpentPillarAddon.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - public class SerpentPillarAddon : BaseAddon - { - [Constructible] - public SerpentPillarAddon() - { - AddComponent(new AddonComponent(9020), -2, +1, 0); - AddComponent(new AddonComponent(9021), -2, +0, 0); - AddComponent(new AddonComponent(9022), -2, -1, 0); - AddComponent(new AddonComponent(9023), -2, -2, 0); - AddComponent(new AddonComponent(9024), -1, -2, 0); - AddComponent(new AddonComponent(9025), +0, -2, 0); - AddComponent(new AddonComponent(9026), +1, -2, 0); - - AddComponent(new AddonComponent(9027), -1, +1, 0); - AddComponent(new AddonComponent(9028), -1, +0, 0); - AddComponent(new AddonComponent(9029), -1, -1, 0); - - AddComponent(new AddonComponent(9030), +0, +1, 0); - AddComponent(new AddonComponent(9031), +0, +0, 0); - AddComponent(new AddonComponent(9032), +0, -1, 0); - - AddComponent(new AddonComponent(9033), +1, +0, 0); - AddComponent(new AddonComponent(9034), +1, -1, 0); - } - - public SerpentPillarAddon(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write((byte)0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadByte(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SerpentPillarAddon : BaseAddon + { + [Constructible] + public SerpentPillarAddon() + { + AddComponent(new AddonComponent(9020), -2, +1, 0); + AddComponent(new AddonComponent(9021), -2, +0, 0); + AddComponent(new AddonComponent(9022), -2, -1, 0); + AddComponent(new AddonComponent(9023), -2, -2, 0); + AddComponent(new AddonComponent(9024), -1, -2, 0); + AddComponent(new AddonComponent(9025), +0, -2, 0); + AddComponent(new AddonComponent(9026), +1, -2, 0); + + AddComponent(new AddonComponent(9027), -1, +1, 0); + AddComponent(new AddonComponent(9028), -1, +0, 0); + AddComponent(new AddonComponent(9029), -1, -1, 0); + + AddComponent(new AddonComponent(9030), +0, +1, 0); + AddComponent(new AddonComponent(9031), +0, +0, 0); + AddComponent(new AddonComponent(9032), +0, -1, 0); + + AddComponent(new AddonComponent(9033), +1, +0, 0); + AddComponent(new AddonComponent(9034), +1, -1, 0); + } + + public SerpentPillarAddon(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write((byte)0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + int version = reader.ReadByte(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/ShrineOfWisdomAddon.cs b/Projects/UOContent/Items/Addons/ShrineOfWisdomAddon.cs index 901aadeec..ec2b4722a 100644 --- a/Projects/UOContent/Items/Addons/ShrineOfWisdomAddon.cs +++ b/Projects/UOContent/Items/Addons/ShrineOfWisdomAddon.cs @@ -1,64 +1,64 @@ -using Server.Engines.Craft; - -namespace Server.Items -{ - public class ShrineOfWisdomAddon : BaseAddon - { - [Constructible] - public ShrineOfWisdomAddon() - { - AddComponent(new ShrineOfWisdomComponent(0x14C3), 0, 0, 0); - AddComponent(new ShrineOfWisdomComponent(0x14C6), 1, 0, 0); - AddComponent(new ShrineOfWisdomComponent(0x14D4), 0, 1, 0); - AddComponent(new ShrineOfWisdomComponent(0x14D5), 1, 1, 0); - Hue = 0x47E; - } - - public ShrineOfWisdomAddon(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Forge] - public class ShrineOfWisdomComponent : AddonComponent - { - [Constructible] - public ShrineOfWisdomComponent(int itemID) : base(itemID) - { - } - - public ShrineOfWisdomComponent(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1062046; // Shrine of Wisdom - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Engines.Craft; + +namespace Server.Items +{ + public class ShrineOfWisdomAddon : BaseAddon + { + [Constructible] + public ShrineOfWisdomAddon() + { + AddComponent(new ShrineOfWisdomComponent(0x14C3), 0, 0, 0); + AddComponent(new ShrineOfWisdomComponent(0x14C6), 1, 0, 0); + AddComponent(new ShrineOfWisdomComponent(0x14D4), 0, 1, 0); + AddComponent(new ShrineOfWisdomComponent(0x14D5), 1, 1, 0); + Hue = 0x47E; + } + + public ShrineOfWisdomAddon(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Forge] + public class ShrineOfWisdomComponent : AddonComponent + { + [Constructible] + public ShrineOfWisdomComponent(int itemID) : base(itemID) + { + } + + public ShrineOfWisdomComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1062046; // Shrine of Wisdom + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/SkullPileAddon.cs b/Projects/UOContent/Items/Addons/SkullPileAddon.cs index 69fb2fd9c..c091e5383 100644 --- a/Projects/UOContent/Items/Addons/SkullPileAddon.cs +++ b/Projects/UOContent/Items/Addons/SkullPileAddon.cs @@ -1,37 +1,37 @@ -namespace Server.Items -{ - public class SkullPileAddon : BaseAddon - { - [Constructible] - public SkullPileAddon() - { - AddComponent(new AddonComponent(6872), 1, 1, 0); - AddComponent(new AddonComponent(6873), 0, 1, 0); - AddComponent(new AddonComponent(6874), -1, 1, 0); - AddComponent(new AddonComponent(6875), 0, 0, 0); - AddComponent(new AddonComponent(6876), 1, 0, 0); - AddComponent(new AddonComponent(6877), 1, -1, 0); - AddComponent(new AddonComponent(6878), 2, -1, 0); - AddComponent(new AddonComponent(6879), 2, 0, 0); - } - - public SkullPileAddon(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write((byte)0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadByte(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SkullPileAddon : BaseAddon + { + [Constructible] + public SkullPileAddon() + { + AddComponent(new AddonComponent(6872), 1, 1, 0); + AddComponent(new AddonComponent(6873), 0, 1, 0); + AddComponent(new AddonComponent(6874), -1, 1, 0); + AddComponent(new AddonComponent(6875), 0, 0, 0); + AddComponent(new AddonComponent(6876), 1, 0, 0); + AddComponent(new AddonComponent(6877), 1, -1, 0); + AddComponent(new AddonComponent(6878), 2, -1, 0); + AddComponent(new AddonComponent(6879), 2, 0, 0); + } + + public SkullPileAddon(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write((byte)0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + int version = reader.ReadByte(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/SmallBedEastAddon.cs b/Projects/UOContent/Items/Addons/SmallBedEastAddon.cs index f85a44564..e1b68dc59 100644 --- a/Projects/UOContent/Items/Addons/SmallBedEastAddon.cs +++ b/Projects/UOContent/Items/Addons/SmallBedEastAddon.cs @@ -1,61 +1,61 @@ -namespace Server.Items -{ - public class SmallBedEastAddon : BaseAddon - { - [Constructible] - public SmallBedEastAddon() - { - AddComponent(new AddonComponent(0xA5D), 0, 0, 0); - AddComponent(new AddonComponent(0xA62), 1, 0, 0); - } - - public SmallBedEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new SmallBedEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SmallBedEastDeed : BaseAddonDeed - { - [Constructible] - public SmallBedEastDeed() - { - } - - public SmallBedEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new SmallBedEastAddon(); - public override int LabelNumber => 1044322; // small bed (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SmallBedEastAddon : BaseAddon + { + [Constructible] + public SmallBedEastAddon() + { + AddComponent(new AddonComponent(0xA5D), 0, 0, 0); + AddComponent(new AddonComponent(0xA62), 1, 0, 0); + } + + public SmallBedEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new SmallBedEastDeed(); + + 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 class SmallBedEastDeed : BaseAddonDeed + { + [Constructible] + public SmallBedEastDeed() + { + } + + public SmallBedEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new SmallBedEastAddon(); + public override int LabelNumber => 1044322; // small bed (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/SmallBedSouthAddon.cs b/Projects/UOContent/Items/Addons/SmallBedSouthAddon.cs index 313f3bcd8..24ab13c17 100644 --- a/Projects/UOContent/Items/Addons/SmallBedSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/SmallBedSouthAddon.cs @@ -1,61 +1,61 @@ -namespace Server.Items -{ - public class SmallBedSouthAddon : BaseAddon - { - [Constructible] - public SmallBedSouthAddon() - { - AddComponent(new AddonComponent(0xA63), 0, 0, 0); - AddComponent(new AddonComponent(0xA5C), 0, 1, 0); - } - - public SmallBedSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new SmallBedSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SmallBedSouthDeed : BaseAddonDeed - { - [Constructible] - public SmallBedSouthDeed() - { - } - - public SmallBedSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new SmallBedSouthAddon(); - public override int LabelNumber => 1044321; // small bed (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SmallBedSouthAddon : BaseAddon + { + [Constructible] + public SmallBedSouthAddon() + { + AddComponent(new AddonComponent(0xA63), 0, 0, 0); + AddComponent(new AddonComponent(0xA5C), 0, 1, 0); + } + + public SmallBedSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new SmallBedSouthDeed(); + + 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 class SmallBedSouthDeed : BaseAddonDeed + { + [Constructible] + public SmallBedSouthDeed() + { + } + + public SmallBedSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new SmallBedSouthAddon(); + public override int LabelNumber => 1044321; // small bed (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/SmallForgeAddon.cs b/Projects/UOContent/Items/Addons/SmallForgeAddon.cs index 535e0055b..226be9128 100644 --- a/Projects/UOContent/Items/Addons/SmallForgeAddon.cs +++ b/Projects/UOContent/Items/Addons/SmallForgeAddon.cs @@ -1,60 +1,60 @@ -namespace Server.Items -{ - public class SmallForgeAddon : BaseAddon - { - [Constructible] - public SmallForgeAddon() - { - AddComponent(new ForgeComponent(0xFB1), 0, 0, 0); - } - - public SmallForgeAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new SmallForgeDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SmallForgeDeed : BaseAddonDeed - { - [Constructible] - public SmallForgeDeed() - { - } - - public SmallForgeDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new SmallForgeAddon(); - public override int LabelNumber => 1044330; // small forge - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SmallForgeAddon : BaseAddon + { + [Constructible] + public SmallForgeAddon() + { + AddComponent(new ForgeComponent(0xFB1), 0, 0, 0); + } + + public SmallForgeAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new SmallForgeDeed(); + + 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 class SmallForgeDeed : BaseAddonDeed + { + [Constructible] + public SmallForgeDeed() + { + } + + public SmallForgeDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new SmallForgeAddon(); + public override int LabelNumber => 1044330; // small forge + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/SolenAntHole.cs b/Projects/UOContent/Items/Addons/SolenAntHole.cs index 9527a559b..52cb7ea09 100644 --- a/Projects/UOContent/Items/Addons/SolenAntHole.cs +++ b/Projects/UOContent/Items/Addons/SolenAntHole.cs @@ -1,168 +1,172 @@ -using System.Collections.Generic; -using Server.Mobiles; -using Server.Network; -using Server.Spells; - -namespace Server.Items -{ - public class SolenAntHoleComponent : AddonComponent - { - public SolenAntHoleComponent(int itemID) : base(itemID) - { - } - - public SolenAntHoleComponent(Serial serial) : base(serial) - { - } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(this, 2)) - { - Map map = Map; - - if (map == Map.Trammel || map == Map.Felucca) - { - from.MoveToWorld(new Point3D(5922, 2024, 0), map); - PublicOverheadMessage(MessageType.Regular, 0x3B2, true, - $"* {from.Name} dives into the hole and disappears!*"); - } - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SolenAntHole : BaseAddon - { - private List m_Spawned; - - [Constructible] - public SolenAntHole() - { - m_Spawned = new List(); - - AddComponent(new AddonComponent(0x914), "dirt", 0, 0, 0, 0); - AddComponent(new SolenAntHoleComponent(0x122A), "a hole", 0x1, 0, 0, 0); - AddComponent(new AddonComponent(0x1B23), "dirt", 0x970, 1, 1, 0); - AddComponent(new AddonComponent(0xEE0), "dirt", 0, 1, 0, 0); - AddComponent(new AddonComponent(0x1B24), "dirt", 0x970, 1, -1, 0); - AddComponent(new AddonComponent(0xEE1), "dirt", 0, 0, -1, 0); - AddComponent(new AddonComponent(0x1B25), "dirt", 0x970, -1, -1, 0); - AddComponent(new AddonComponent(0xEE2), "dirt", 0, -1, 0, 0); - AddComponent(new AddonComponent(0x1B26), "dirt", 0x970, -1, 1, 0); - AddComponent(new AddonComponent(0xED3), "dirt", 0, 0, 1, 0); - } - - public SolenAntHole(Serial serial) : base(serial) - { - } - - public override bool ShareHue => false; - public override bool HandlesOnMovement => true; - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (!m.Player || !m.Alive || m.Hidden || !SpawnKilled()) - return; - - if (Utility.InRange(Location, m.Location, 3) && !Utility.InRange(Location, oldLocation, 3)) - { - int count = 1 + Utility.Random(4); - - for (int i = 0; i < count; i++) - SpawnAnt(); - - if (Utility.RandomDouble() < 0.05) - SpawnAnt(new Beetle()); - } - } - - public void AddComponent(AddonComponent c, string name, int hue, int x, int y, int z) - { - c.Hue = hue; - c.Name = name; - AddComponent(c, x, y, z); - } - - public void SpawnAnt() - { - int random = Utility.Random(3); - Map map = Map; - - if (map == Map.Trammel) - { - if (random < 2) - SpawnAnt(new RedSolenWorker()); - else - SpawnAnt(new RedSolenWarrior()); - } - else if (map == Map.Felucca) - { - if (random < 2) - SpawnAnt(new BlackSolenWorker()); - else - SpawnAnt(new BlackSolenWarrior()); - } - } - - public void SpawnAnt(BaseCreature ant) - { - m_Spawned.Add(ant); - - Map map = Map; - Point3D p = Location; - - for (int i = 0; i < 5; i++) - if (SpellHelper.FindValidSpawnLocation(map, ref p, false)) - break; - - ant.MoveToWorld(p, map); - ant.Home = Location; - ant.RangeHome = 10; - } - - public bool SpawnKilled() - { - for (int i = m_Spawned.Count - 1; i >= 0; i--) - if (!m_Spawned[i].Alive || m_Spawned[i].Deleted) - m_Spawned.RemoveAt(i); - - return m_Spawned.Count < 2; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.WriteMobileList(m_Spawned); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_Spawned = reader.ReadStrongMobileList(); - } - } -} \ No newline at end of file +using System.Collections.Generic; +using Server.Mobiles; +using Server.Network; +using Server.Spells; + +namespace Server.Items +{ + public class SolenAntHoleComponent : AddonComponent + { + public SolenAntHoleComponent(int itemID) : base(itemID) + { + } + + public SolenAntHoleComponent(Serial serial) : base(serial) + { + } + + public override void OnDoubleClick(Mobile from) + { + if (from.InRange(this, 2)) + { + var map = Map; + + if (map == Map.Trammel || map == Map.Felucca) + { + from.MoveToWorld(new Point3D(5922, 2024, 0), map); + PublicOverheadMessage( + MessageType.Regular, + 0x3B2, + true, + $"* {from.Name} dives into the hole and disappears!*" + ); + } + } + else + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + } + + 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(); + } + } + + public class SolenAntHole : BaseAddon + { + private List m_Spawned; + + [Constructible] + public SolenAntHole() + { + m_Spawned = new List(); + + AddComponent(new AddonComponent(0x914), "dirt", 0, 0, 0, 0); + AddComponent(new SolenAntHoleComponent(0x122A), "a hole", 0x1, 0, 0, 0); + AddComponent(new AddonComponent(0x1B23), "dirt", 0x970, 1, 1, 0); + AddComponent(new AddonComponent(0xEE0), "dirt", 0, 1, 0, 0); + AddComponent(new AddonComponent(0x1B24), "dirt", 0x970, 1, -1, 0); + AddComponent(new AddonComponent(0xEE1), "dirt", 0, 0, -1, 0); + AddComponent(new AddonComponent(0x1B25), "dirt", 0x970, -1, -1, 0); + AddComponent(new AddonComponent(0xEE2), "dirt", 0, -1, 0, 0); + AddComponent(new AddonComponent(0x1B26), "dirt", 0x970, -1, 1, 0); + AddComponent(new AddonComponent(0xED3), "dirt", 0, 0, 1, 0); + } + + public SolenAntHole(Serial serial) : base(serial) + { + } + + public override bool ShareHue => false; + public override bool HandlesOnMovement => true; + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (!m.Player || !m.Alive || m.Hidden || !SpawnKilled()) + return; + + if (Utility.InRange(Location, m.Location, 3) && !Utility.InRange(Location, oldLocation, 3)) + { + var count = 1 + Utility.Random(4); + + for (var i = 0; i < count; i++) + SpawnAnt(); + + if (Utility.RandomDouble() < 0.05) + SpawnAnt(new Beetle()); + } + } + + public void AddComponent(AddonComponent c, string name, int hue, int x, int y, int z) + { + c.Hue = hue; + c.Name = name; + AddComponent(c, x, y, z); + } + + public void SpawnAnt() + { + var random = Utility.Random(3); + var map = Map; + + if (map == Map.Trammel) + { + if (random < 2) + SpawnAnt(new RedSolenWorker()); + else + SpawnAnt(new RedSolenWarrior()); + } + else if (map == Map.Felucca) + { + if (random < 2) + SpawnAnt(new BlackSolenWorker()); + else + SpawnAnt(new BlackSolenWarrior()); + } + } + + public void SpawnAnt(BaseCreature ant) + { + m_Spawned.Add(ant); + + var map = Map; + var p = Location; + + for (var i = 0; i < 5; i++) + if (SpellHelper.FindValidSpawnLocation(map, ref p, false)) + break; + + ant.MoveToWorld(p, map); + ant.Home = Location; + ant.RangeHome = 10; + } + + public bool SpawnKilled() + { + for (var i = m_Spawned.Count - 1; i >= 0; i--) + if (!m_Spawned[i].Alive || m_Spawned[i].Deleted) + m_Spawned.RemoveAt(i); + + return m_Spawned.Count < 2; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.WriteMobileList(m_Spawned); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_Spawned = reader.ReadStrongMobileList(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/SpinningwheelEastAddon.cs b/Projects/UOContent/Items/Addons/SpinningwheelEastAddon.cs index bb3bac255..247af640d 100644 --- a/Projects/UOContent/Items/Addons/SpinningwheelEastAddon.cs +++ b/Projects/UOContent/Items/Addons/SpinningwheelEastAddon.cs @@ -1,147 +1,148 @@ -using System; - -namespace Server.Items -{ - public delegate void SpinCallback(ISpinningWheel sender, Mobile from, int hue); - - public interface ISpinningWheel - { - bool Spinning { get; } - void BeginSpin(SpinCallback callback, Mobile from, int hue); - } - - public class SpinningwheelEastAddon : BaseAddon, ISpinningWheel - { - private Timer m_Timer; - - [Constructible] - public SpinningwheelEastAddon() - { - AddComponent(new AddonComponent(0x1019), 0, 0, 0); - } - - public SpinningwheelEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new SpinningwheelEastDeed(); - - public bool Spinning => m_Timer != null; - - public void BeginSpin(SpinCallback callback, Mobile from, int hue) - { - m_Timer = new SpinTimer(this, callback, from, hue); - m_Timer.Start(); - - foreach (AddonComponent c in Components) - switch (c.ItemID) - { - case 0x1015: - case 0x1019: - case 0x101C: - case 0x10A4: - ++c.ItemID; - break; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnComponentLoaded(AddonComponent c) - { - switch (c.ItemID) - { - case 0x1016: - case 0x101A: - case 0x101D: - case 0x10A5: - --c.ItemID; - break; - } - } - - public void EndSpin(SpinCallback callback, Mobile from, int hue) - { - m_Timer?.Stop(); - - m_Timer = null; - - foreach (AddonComponent c in Components) - switch (c.ItemID) - { - case 0x1016: - case 0x101A: - case 0x101D: - case 0x10A5: - --c.ItemID; - break; - } - - callback?.Invoke(this, from, hue); - } - - private class SpinTimer : Timer - { - private readonly SpinCallback m_Callback; - private readonly Mobile m_From; - private readonly int m_Hue; - private readonly SpinningwheelEastAddon m_Wheel; - - public SpinTimer(SpinningwheelEastAddon wheel, SpinCallback callback, Mobile from, int hue) : base( - TimeSpan.FromSeconds(3.0)) - { - m_Wheel = wheel; - m_Callback = callback; - m_From = from; - m_Hue = hue; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - m_Wheel.EndSpin(m_Callback, m_From, m_Hue); - } - } - } - - public class SpinningwheelEastDeed : BaseAddonDeed - { - [Constructible] - public SpinningwheelEastDeed() - { - } - - public SpinningwheelEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new SpinningwheelEastAddon(); - public override int LabelNumber => 1044341; // spining wheel (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public delegate void SpinCallback(ISpinningWheel sender, Mobile from, int hue); + + public interface ISpinningWheel + { + bool Spinning { get; } + void BeginSpin(SpinCallback callback, Mobile from, int hue); + } + + public class SpinningwheelEastAddon : BaseAddon, ISpinningWheel + { + private Timer m_Timer; + + [Constructible] + public SpinningwheelEastAddon() + { + AddComponent(new AddonComponent(0x1019), 0, 0, 0); + } + + public SpinningwheelEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new SpinningwheelEastDeed(); + + public bool Spinning => m_Timer != null; + + public void BeginSpin(SpinCallback callback, Mobile from, int hue) + { + m_Timer = new SpinTimer(this, callback, from, hue); + m_Timer.Start(); + + foreach (var c in Components) + switch (c.ItemID) + { + case 0x1015: + case 0x1019: + case 0x101C: + case 0x10A4: + ++c.ItemID; + break; + } + } + + 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 OnComponentLoaded(AddonComponent c) + { + switch (c.ItemID) + { + case 0x1016: + case 0x101A: + case 0x101D: + case 0x10A5: + --c.ItemID; + break; + } + } + + public void EndSpin(SpinCallback callback, Mobile from, int hue) + { + m_Timer?.Stop(); + + m_Timer = null; + + foreach (var c in Components) + switch (c.ItemID) + { + case 0x1016: + case 0x101A: + case 0x101D: + case 0x10A5: + --c.ItemID; + break; + } + + callback?.Invoke(this, from, hue); + } + + private class SpinTimer : Timer + { + private readonly SpinCallback m_Callback; + private readonly Mobile m_From; + private readonly int m_Hue; + private readonly SpinningwheelEastAddon m_Wheel; + + public SpinTimer(SpinningwheelEastAddon wheel, SpinCallback callback, Mobile from, int hue) : base( + TimeSpan.FromSeconds(3.0) + ) + { + m_Wheel = wheel; + m_Callback = callback; + m_From = from; + m_Hue = hue; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + m_Wheel.EndSpin(m_Callback, m_From, m_Hue); + } + } + } + + public class SpinningwheelEastDeed : BaseAddonDeed + { + [Constructible] + public SpinningwheelEastDeed() + { + } + + public SpinningwheelEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new SpinningwheelEastAddon(); + public override int LabelNumber => 1044341; // spining wheel (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/SpinningwheelSouthAddon.cs b/Projects/UOContent/Items/Addons/SpinningwheelSouthAddon.cs index 4933f7bbe..f6b5ea13b 100644 --- a/Projects/UOContent/Items/Addons/SpinningwheelSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/SpinningwheelSouthAddon.cs @@ -1,139 +1,140 @@ -using System; - -namespace Server.Items -{ - public class SpinningwheelSouthAddon : BaseAddon, ISpinningWheel - { - private Timer m_Timer; - - [Constructible] - public SpinningwheelSouthAddon() - { - AddComponent(new AddonComponent(0x1015), 0, 0, 0); - } - - public SpinningwheelSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new SpinningwheelSouthDeed(); - - public bool Spinning => m_Timer != null; - - public void BeginSpin(SpinCallback callback, Mobile from, int hue) - { - m_Timer = new SpinTimer(this, callback, from, hue); - m_Timer.Start(); - - foreach (AddonComponent c in Components) - switch (c.ItemID) - { - case 0x1015: - case 0x1019: - case 0x101C: - case 0x10A4: - ++c.ItemID; - break; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnComponentLoaded(AddonComponent c) - { - switch (c.ItemID) - { - case 0x1016: - case 0x101A: - case 0x101D: - case 0x10A5: - --c.ItemID; - break; - } - } - - public void EndSpin(SpinCallback callback, Mobile from, int hue) - { - m_Timer?.Stop(); - - m_Timer = null; - - foreach (AddonComponent c in Components) - switch (c.ItemID) - { - case 0x1016: - case 0x101A: - case 0x101D: - case 0x10A5: - --c.ItemID; - break; - } - - callback?.Invoke(this, from, hue); - } - - private class SpinTimer : Timer - { - private readonly SpinCallback m_Callback; - private readonly Mobile m_From; - private readonly int m_Hue; - private readonly SpinningwheelSouthAddon m_Wheel; - - public SpinTimer(SpinningwheelSouthAddon wheel, SpinCallback callback, Mobile from, int hue) : base( - TimeSpan.FromSeconds(3.0)) - { - m_Wheel = wheel; - m_Callback = callback; - m_From = from; - m_Hue = hue; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - m_Wheel.EndSpin(m_Callback, m_From, m_Hue); - } - } - } - - public class SpinningwheelSouthDeed : BaseAddonDeed - { - [Constructible] - public SpinningwheelSouthDeed() - { - } - - public SpinningwheelSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new SpinningwheelSouthAddon(); - public override int LabelNumber => 1044342; // spining wheel (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class SpinningwheelSouthAddon : BaseAddon, ISpinningWheel + { + private Timer m_Timer; + + [Constructible] + public SpinningwheelSouthAddon() + { + AddComponent(new AddonComponent(0x1015), 0, 0, 0); + } + + public SpinningwheelSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new SpinningwheelSouthDeed(); + + public bool Spinning => m_Timer != null; + + public void BeginSpin(SpinCallback callback, Mobile from, int hue) + { + m_Timer = new SpinTimer(this, callback, from, hue); + m_Timer.Start(); + + foreach (var c in Components) + switch (c.ItemID) + { + case 0x1015: + case 0x1019: + case 0x101C: + case 0x10A4: + ++c.ItemID; + break; + } + } + + 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 OnComponentLoaded(AddonComponent c) + { + switch (c.ItemID) + { + case 0x1016: + case 0x101A: + case 0x101D: + case 0x10A5: + --c.ItemID; + break; + } + } + + public void EndSpin(SpinCallback callback, Mobile from, int hue) + { + m_Timer?.Stop(); + + m_Timer = null; + + foreach (var c in Components) + switch (c.ItemID) + { + case 0x1016: + case 0x101A: + case 0x101D: + case 0x10A5: + --c.ItemID; + break; + } + + callback?.Invoke(this, from, hue); + } + + private class SpinTimer : Timer + { + private readonly SpinCallback m_Callback; + private readonly Mobile m_From; + private readonly int m_Hue; + private readonly SpinningwheelSouthAddon m_Wheel; + + public SpinTimer(SpinningwheelSouthAddon wheel, SpinCallback callback, Mobile from, int hue) : base( + TimeSpan.FromSeconds(3.0) + ) + { + m_Wheel = wheel; + m_Callback = callback; + m_From = from; + m_Hue = hue; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + m_Wheel.EndSpin(m_Callback, m_From, m_Hue); + } + } + } + + public class SpinningwheelSouthDeed : BaseAddonDeed + { + [Constructible] + public SpinningwheelSouthDeed() + { + } + + public SpinningwheelSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new SpinningwheelSouthAddon(); + public override int LabelNumber => 1044342; // spining wheel (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/SquirrelStatueEastAddon.cs b/Projects/UOContent/Items/Addons/SquirrelStatueEastAddon.cs index a2d246a56..4df51fe12 100644 --- a/Projects/UOContent/Items/Addons/SquirrelStatueEastAddon.cs +++ b/Projects/UOContent/Items/Addons/SquirrelStatueEastAddon.cs @@ -1,60 +1,60 @@ -namespace Server.Items -{ - public class SquirrelStatueEastAddon : BaseAddon - { - [Constructible] - public SquirrelStatueEastAddon() - { - AddComponent(new AddonComponent(0x2D10), 0, 0, 0); - } - - public SquirrelStatueEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new SquirrelStatueEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SquirrelStatueEastDeed : BaseAddonDeed - { - [Constructible] - public SquirrelStatueEastDeed() - { - } - - public SquirrelStatueEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new SquirrelStatueEastAddon(); - public override int LabelNumber => 1073398; // squirrel statue (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SquirrelStatueEastAddon : BaseAddon + { + [Constructible] + public SquirrelStatueEastAddon() + { + AddComponent(new AddonComponent(0x2D10), 0, 0, 0); + } + + public SquirrelStatueEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new SquirrelStatueEastDeed(); + + 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(); + } + } + + public class SquirrelStatueEastDeed : BaseAddonDeed + { + [Constructible] + public SquirrelStatueEastDeed() + { + } + + public SquirrelStatueEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new SquirrelStatueEastAddon(); + public override int LabelNumber => 1073398; // squirrel statue (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/SquirrelStatueSouthAddon.cs b/Projects/UOContent/Items/Addons/SquirrelStatueSouthAddon.cs index 926cdafed..6f4c6590f 100644 --- a/Projects/UOContent/Items/Addons/SquirrelStatueSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/SquirrelStatueSouthAddon.cs @@ -1,60 +1,60 @@ -namespace Server.Items -{ - public class SquirrelStatueSouthAddon : BaseAddon - { - [Constructible] - public SquirrelStatueSouthAddon() - { - AddComponent(new AddonComponent(0x2D11), 0, 0, 0); - } - - public SquirrelStatueSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new SquirrelStatueSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SquirrelStatueSouthDeed : BaseAddonDeed - { - [Constructible] - public SquirrelStatueSouthDeed() - { - } - - public SquirrelStatueSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new SquirrelStatueSouthAddon(); - public override int LabelNumber => 1072884; // squirrel statue (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SquirrelStatueSouthAddon : BaseAddon + { + [Constructible] + public SquirrelStatueSouthAddon() + { + AddComponent(new AddonComponent(0x2D11), 0, 0, 0); + } + + public SquirrelStatueSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new SquirrelStatueSouthDeed(); + + 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(); + } + } + + public class SquirrelStatueSouthDeed : BaseAddonDeed + { + [Constructible] + public SquirrelStatueSouthDeed() + { + } + + public SquirrelStatueSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new SquirrelStatueSouthAddon(); + public override int LabelNumber => 1072884; // squirrel statue (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/StoneFireplaceEastAddon.cs b/Projects/UOContent/Items/Addons/StoneFireplaceEastAddon.cs index 8d4a31373..eaf5d702f 100644 --- a/Projects/UOContent/Items/Addons/StoneFireplaceEastAddon.cs +++ b/Projects/UOContent/Items/Addons/StoneFireplaceEastAddon.cs @@ -1,61 +1,61 @@ -namespace Server.Items -{ - public class StoneFireplaceEastAddon : BaseAddon - { - [Constructible] - public StoneFireplaceEastAddon() - { - AddComponent(new AddonComponent(0x959), 0, 0, 0); - AddComponent(new AddonComponent(0x953), 0, 1, 0); - } - - public StoneFireplaceEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new StoneFireplaceEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class StoneFireplaceEastDeed : BaseAddonDeed - { - [Constructible] - public StoneFireplaceEastDeed() - { - } - - public StoneFireplaceEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new StoneFireplaceEastAddon(); - public override int LabelNumber => 1061848; // stone fireplace (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class StoneFireplaceEastAddon : BaseAddon + { + [Constructible] + public StoneFireplaceEastAddon() + { + AddComponent(new AddonComponent(0x959), 0, 0, 0); + AddComponent(new AddonComponent(0x953), 0, 1, 0); + } + + public StoneFireplaceEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new StoneFireplaceEastDeed(); + + 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 class StoneFireplaceEastDeed : BaseAddonDeed + { + [Constructible] + public StoneFireplaceEastDeed() + { + } + + public StoneFireplaceEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new StoneFireplaceEastAddon(); + public override int LabelNumber => 1061848; // stone fireplace (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/StoneFireplaceSouthAddon.cs b/Projects/UOContent/Items/Addons/StoneFireplaceSouthAddon.cs index a78478b5d..a6b6d7be1 100644 --- a/Projects/UOContent/Items/Addons/StoneFireplaceSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/StoneFireplaceSouthAddon.cs @@ -1,61 +1,61 @@ -namespace Server.Items -{ - public class StoneFireplaceSouthAddon : BaseAddon - { - [Constructible] - public StoneFireplaceSouthAddon() - { - AddComponent(new AddonComponent(0x967), -1, 0, 0); - AddComponent(new AddonComponent(0x961), 0, 0, 0); - } - - public StoneFireplaceSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new StoneFireplaceSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class StoneFireplaceSouthDeed : BaseAddonDeed - { - [Constructible] - public StoneFireplaceSouthDeed() - { - } - - public StoneFireplaceSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new StoneFireplaceSouthAddon(); - public override int LabelNumber => 1061849; // stone fireplace (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class StoneFireplaceSouthAddon : BaseAddon + { + [Constructible] + public StoneFireplaceSouthAddon() + { + AddComponent(new AddonComponent(0x967), -1, 0, 0); + AddComponent(new AddonComponent(0x961), 0, 0, 0); + } + + public StoneFireplaceSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new StoneFireplaceSouthDeed(); + + 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 class StoneFireplaceSouthDeed : BaseAddonDeed + { + [Constructible] + public StoneFireplaceSouthDeed() + { + } + + public StoneFireplaceSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new StoneFireplaceSouthAddon(); + public override int LabelNumber => 1061849; // stone fireplace (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/StoneFountainAddon.cs b/Projects/UOContent/Items/Addons/StoneFountainAddon.cs index 9bc63bcc9..15f0be694 100644 --- a/Projects/UOContent/Items/Addons/StoneFountainAddon.cs +++ b/Projects/UOContent/Items/Addons/StoneFountainAddon.cs @@ -1,51 +1,51 @@ -namespace Server.Items -{ - public class StoneFountainAddon : BaseAddon - { - [Constructible] - public StoneFountainAddon() - { - int itemID = 0x1731; - - AddComponent(new AddonComponent(itemID++), -2, +1, 0); - AddComponent(new AddonComponent(itemID++), -1, +1, 0); - AddComponent(new AddonComponent(itemID++), +0, +1, 0); - AddComponent(new AddonComponent(itemID++), +1, +1, 0); - - AddComponent(new AddonComponent(itemID++), +1, +0, 0); - AddComponent(new AddonComponent(itemID++), +1, -1, 0); - AddComponent(new AddonComponent(itemID++), +1, -2, 0); - - AddComponent(new AddonComponent(itemID++), +0, -2, 0); - AddComponent(new AddonComponent(itemID++), +0, -1, 0); - AddComponent(new AddonComponent(itemID++), +0, +0, 0); - - AddComponent(new AddonComponent(itemID++), -1, +0, 0); - AddComponent(new AddonComponent(itemID++), -2, +0, 0); - - AddComponent(new AddonComponent(itemID++), -2, -1, 0); - AddComponent(new AddonComponent(itemID++), -1, -1, 0); - - AddComponent(new AddonComponent(itemID++), -1, -2, 0); - AddComponent(new AddonComponent(++itemID), -2, -2, 0); - } - - public StoneFountainAddon(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class StoneFountainAddon : BaseAddon + { + [Constructible] + public StoneFountainAddon() + { + var itemID = 0x1731; + + AddComponent(new AddonComponent(itemID++), -2, +1, 0); + AddComponent(new AddonComponent(itemID++), -1, +1, 0); + AddComponent(new AddonComponent(itemID++), +0, +1, 0); + AddComponent(new AddonComponent(itemID++), +1, +1, 0); + + AddComponent(new AddonComponent(itemID++), +1, +0, 0); + AddComponent(new AddonComponent(itemID++), +1, -1, 0); + AddComponent(new AddonComponent(itemID++), +1, -2, 0); + + AddComponent(new AddonComponent(itemID++), +0, -2, 0); + AddComponent(new AddonComponent(itemID++), +0, -1, 0); + AddComponent(new AddonComponent(itemID++), +0, +0, 0); + + AddComponent(new AddonComponent(itemID++), -1, +0, 0); + AddComponent(new AddonComponent(itemID++), -2, +0, 0); + + AddComponent(new AddonComponent(itemID++), -2, -1, 0); + AddComponent(new AddonComponent(itemID++), -1, -1, 0); + + AddComponent(new AddonComponent(itemID++), -1, -2, 0); + AddComponent(new AddonComponent(++itemID), -2, -2, 0); + } + + public StoneFountainAddon(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/StoneOvenEastAddon.cs b/Projects/UOContent/Items/Addons/StoneOvenEastAddon.cs index 75ee90006..4d7a1a0a5 100644 --- a/Projects/UOContent/Items/Addons/StoneOvenEastAddon.cs +++ b/Projects/UOContent/Items/Addons/StoneOvenEastAddon.cs @@ -1,61 +1,61 @@ -namespace Server.Items -{ - public class StoneOvenEastAddon : BaseAddon - { - [Constructible] - public StoneOvenEastAddon() - { - AddComponent(new AddonComponent(0x92C), 0, 0, 0); - AddComponent(new AddonComponent(0x92B), 0, 1, 0); - } - - public StoneOvenEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new StoneOvenEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class StoneOvenEastDeed : BaseAddonDeed - { - [Constructible] - public StoneOvenEastDeed() - { - } - - public StoneOvenEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new StoneOvenEastAddon(); - public override int LabelNumber => 1044345; // stone oven (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class StoneOvenEastAddon : BaseAddon + { + [Constructible] + public StoneOvenEastAddon() + { + AddComponent(new AddonComponent(0x92C), 0, 0, 0); + AddComponent(new AddonComponent(0x92B), 0, 1, 0); + } + + public StoneOvenEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new StoneOvenEastDeed(); + + 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 class StoneOvenEastDeed : BaseAddonDeed + { + [Constructible] + public StoneOvenEastDeed() + { + } + + public StoneOvenEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new StoneOvenEastAddon(); + public override int LabelNumber => 1044345; // stone oven (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/StoneOvenSouthAddon.cs b/Projects/UOContent/Items/Addons/StoneOvenSouthAddon.cs index 3840f621f..9946180fc 100644 --- a/Projects/UOContent/Items/Addons/StoneOvenSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/StoneOvenSouthAddon.cs @@ -1,61 +1,61 @@ -namespace Server.Items -{ - public class StoneOvenSouthAddon : BaseAddon - { - [Constructible] - public StoneOvenSouthAddon() - { - AddComponent(new AddonComponent(0x931), -1, 0, 0); - AddComponent(new AddonComponent(0x930), 0, 0, 0); - } - - public StoneOvenSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new StoneOvenSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class StoneOvenSouthDeed : BaseAddonDeed - { - [Constructible] - public StoneOvenSouthDeed() - { - } - - public StoneOvenSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new StoneOvenSouthAddon(); - public override int LabelNumber => 1044346; // stone oven (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class StoneOvenSouthAddon : BaseAddon + { + [Constructible] + public StoneOvenSouthAddon() + { + AddComponent(new AddonComponent(0x931), -1, 0, 0); + AddComponent(new AddonComponent(0x930), 0, 0, 0); + } + + public StoneOvenSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new StoneOvenSouthDeed(); + + 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 class StoneOvenSouthDeed : BaseAddonDeed + { + [Constructible] + public StoneOvenSouthDeed() + { + } + + public StoneOvenSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new StoneOvenSouthAddon(); + public override int LabelNumber => 1044346; // stone oven (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/StretchedHides.cs b/Projects/UOContent/Items/Addons/StretchedHides.cs index b2485566a..636289410 100644 --- a/Projects/UOContent/Items/Addons/StretchedHides.cs +++ b/Projects/UOContent/Items/Addons/StretchedHides.cs @@ -1,234 +1,234 @@ -namespace Server.Items -{ - public class SmallStretchedHideEastAddon : BaseAddon - { - [Constructible] - public SmallStretchedHideEastAddon() - { - AddComponent(new AddonComponent(0x1069), 0, 0, 0); - } - - public SmallStretchedHideEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new SmallStretchedHideEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SmallStretchedHideEastDeed : BaseAddonDeed - { - [Constructible] - public SmallStretchedHideEastDeed() - { - } - - public SmallStretchedHideEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new SmallStretchedHideEastAddon(); - public override int LabelNumber => 1049401; // a small stretched hide deed facing east - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SmallStretchedHideSouthAddon : BaseAddon - { - [Constructible] - public SmallStretchedHideSouthAddon() - { - AddComponent(new AddonComponent(0x107A), 0, 0, 0); - } - - public SmallStretchedHideSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new SmallStretchedHideSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SmallStretchedHideSouthDeed : BaseAddonDeed - { - [Constructible] - public SmallStretchedHideSouthDeed() - { - } - - public SmallStretchedHideSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new SmallStretchedHideSouthAddon(); - public override int LabelNumber => 1049402; // a small stretched hide deed facing south - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class MediumStretchedHideEastAddon : BaseAddon - { - [Constructible] - public MediumStretchedHideEastAddon() - { - AddComponent(new AddonComponent(0x106B), 0, 0, 0); - } - - public MediumStretchedHideEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new MediumStretchedHideEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class MediumStretchedHideEastDeed : BaseAddonDeed - { - [Constructible] - public MediumStretchedHideEastDeed() - { - } - - public MediumStretchedHideEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new MediumStretchedHideEastAddon(); - public override int LabelNumber => 1049403; // a medium stretched hide deed facing east - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class MediumStretchedHideSouthAddon : BaseAddon - { - [Constructible] - public MediumStretchedHideSouthAddon() - { - AddComponent(new AddonComponent(0x107C), 0, 0, 0); - } - - public MediumStretchedHideSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new MediumStretchedHideSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class MediumStretchedHideSouthDeed : BaseAddonDeed - { - [Constructible] - public MediumStretchedHideSouthDeed() - { - } - - public MediumStretchedHideSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new MediumStretchedHideSouthAddon(); - public override int LabelNumber => 1049404; // a medium stretched hide deed facing south - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SmallStretchedHideEastAddon : BaseAddon + { + [Constructible] + public SmallStretchedHideEastAddon() + { + AddComponent(new AddonComponent(0x1069), 0, 0, 0); + } + + public SmallStretchedHideEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new SmallStretchedHideEastDeed(); + + 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 class SmallStretchedHideEastDeed : BaseAddonDeed + { + [Constructible] + public SmallStretchedHideEastDeed() + { + } + + public SmallStretchedHideEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new SmallStretchedHideEastAddon(); + public override int LabelNumber => 1049401; // a small stretched hide deed facing east + + 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 class SmallStretchedHideSouthAddon : BaseAddon + { + [Constructible] + public SmallStretchedHideSouthAddon() + { + AddComponent(new AddonComponent(0x107A), 0, 0, 0); + } + + public SmallStretchedHideSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new SmallStretchedHideSouthDeed(); + + 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 class SmallStretchedHideSouthDeed : BaseAddonDeed + { + [Constructible] + public SmallStretchedHideSouthDeed() + { + } + + public SmallStretchedHideSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new SmallStretchedHideSouthAddon(); + public override int LabelNumber => 1049402; // a small stretched hide deed facing south + + 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 class MediumStretchedHideEastAddon : BaseAddon + { + [Constructible] + public MediumStretchedHideEastAddon() + { + AddComponent(new AddonComponent(0x106B), 0, 0, 0); + } + + public MediumStretchedHideEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new MediumStretchedHideEastDeed(); + + 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 class MediumStretchedHideEastDeed : BaseAddonDeed + { + [Constructible] + public MediumStretchedHideEastDeed() + { + } + + public MediumStretchedHideEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new MediumStretchedHideEastAddon(); + public override int LabelNumber => 1049403; // a medium stretched hide deed facing east + + 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 class MediumStretchedHideSouthAddon : BaseAddon + { + [Constructible] + public MediumStretchedHideSouthAddon() + { + AddComponent(new AddonComponent(0x107C), 0, 0, 0); + } + + public MediumStretchedHideSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new MediumStretchedHideSouthDeed(); + + 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 class MediumStretchedHideSouthDeed : BaseAddonDeed + { + [Constructible] + public MediumStretchedHideSouthDeed() + { + } + + public MediumStretchedHideSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new MediumStretchedHideSouthAddon(); + public override int LabelNumber => 1049404; // a medium stretched hide deed facing south + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/TallElvenBedEastAddon.cs b/Projects/UOContent/Items/Addons/TallElvenBedEastAddon.cs index 312732f49..a358bef83 100644 --- a/Projects/UOContent/Items/Addons/TallElvenBedEastAddon.cs +++ b/Projects/UOContent/Items/Addons/TallElvenBedEastAddon.cs @@ -1,63 +1,63 @@ -namespace Server.Items -{ - public class TallElvenBedEastAddon : BaseAddon - { - [Constructible] - public TallElvenBedEastAddon() - { - AddComponent(new AddonComponent(0x3054), 0, 0, 0); - AddComponent(new AddonComponent(0x3053), 1, 0, 0); - AddComponent(new AddonComponent(0x3055), 2, -1, 0); - AddComponent(new AddonComponent(0x3052), 2, 0, 0); - } - - public TallElvenBedEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new TallElvenBedEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TallElvenBedEastDeed : BaseAddonDeed - { - [Constructible] - public TallElvenBedEastDeed() - { - } - - public TallElvenBedEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new TallElvenBedEastAddon(); - public override int LabelNumber => 1072859; // tall elven bed (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TallElvenBedEastAddon : BaseAddon + { + [Constructible] + public TallElvenBedEastAddon() + { + AddComponent(new AddonComponent(0x3054), 0, 0, 0); + AddComponent(new AddonComponent(0x3053), 1, 0, 0); + AddComponent(new AddonComponent(0x3055), 2, -1, 0); + AddComponent(new AddonComponent(0x3052), 2, 0, 0); + } + + public TallElvenBedEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new TallElvenBedEastDeed(); + + 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(); + } + } + + public class TallElvenBedEastDeed : BaseAddonDeed + { + [Constructible] + public TallElvenBedEastDeed() + { + } + + public TallElvenBedEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new TallElvenBedEastAddon(); + public override int LabelNumber => 1072859; // tall elven bed (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/TallElvenBedSouthAddon.cs b/Projects/UOContent/Items/Addons/TallElvenBedSouthAddon.cs index 53a42ab38..4dc6d8e0c 100644 --- a/Projects/UOContent/Items/Addons/TallElvenBedSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/TallElvenBedSouthAddon.cs @@ -1,63 +1,63 @@ -namespace Server.Items -{ - public class TallElvenBedSouthAddon : BaseAddon - { - [Constructible] - public TallElvenBedSouthAddon() - { - AddComponent(new AddonComponent(0x3058), 0, 0, 0); // angolo alto sx - AddComponent(new AddonComponent(0x3057), -1, 1, 0); // angolo basso sx - AddComponent(new AddonComponent(0x3059), 0, -1, 0); // angolo alto dx - AddComponent(new AddonComponent(0x3056), 0, 1, 0); // angolo basso dx - } - - public TallElvenBedSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new TallElvenBedSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TallElvenBedSouthDeed : BaseAddonDeed - { - [Constructible] - public TallElvenBedSouthDeed() - { - } - - public TallElvenBedSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new TallElvenBedSouthAddon(); - public override int LabelNumber => 1072858; // tall elven bed (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TallElvenBedSouthAddon : BaseAddon + { + [Constructible] + public TallElvenBedSouthAddon() + { + AddComponent(new AddonComponent(0x3058), 0, 0, 0); // angolo alto sx + AddComponent(new AddonComponent(0x3057), -1, 1, 0); // angolo basso sx + AddComponent(new AddonComponent(0x3059), 0, -1, 0); // angolo alto dx + AddComponent(new AddonComponent(0x3056), 0, 1, 0); // angolo basso dx + } + + public TallElvenBedSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new TallElvenBedSouthDeed(); + + 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(); + } + } + + public class TallElvenBedSouthDeed : BaseAddonDeed + { + [Constructible] + public TallElvenBedSouthDeed() + { + } + + public TallElvenBedSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new TallElvenBedSouthAddon(); + public override int LabelNumber => 1072858; // tall elven bed (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/Telescope.cs b/Projects/UOContent/Items/Addons/Telescope.cs index c9b7d2ae7..e0d4347a4 100644 --- a/Projects/UOContent/Items/Addons/Telescope.cs +++ b/Projects/UOContent/Items/Addons/Telescope.cs @@ -1,103 +1,103 @@ -namespace Server.Items -{ - public class Telescope : BaseAddon - { - [Constructible] - public Telescope() - { - AddComponent(new AddonComponent(0x1494), 0, 5, 0); - AddComponent(new AddonComponent(0x145B), 0, 6, 0); - AddComponent(new AddonComponent(0x145A), 0, 7, 0); - - AddComponent(new AddonComponent(0x1495), 1, 4, 0); - AddComponent(new AddonComponent(0x145C), 1, 7, 0); - AddComponent(new AddonComponent(0x145D), 1, 8, 0); - - AddComponent(new AddonComponent(0x1496), 2, 3, 0); - AddComponent(new AddonComponent(0x1499), 2, 4, 0); - AddComponent(new AddonComponent(0x148E), 2, 6, 0); - AddComponent(new AddonComponent(0x1493), 2, 7, 0); - AddComponent(new AddonComponent(0x1492), 2, 8, 0); - AddComponent(new AddonComponent(0x145E), 2, 9, 0); - AddComponent(new AddonComponent(0x1459), 2, 10, 0); - - AddComponent(new AddonComponent(0x1497), 3, 2, 0); - AddComponent(new AddonComponent(0x145F), 3, 9, 0); - AddComponent(new AddonComponent(0x1461), 3, 10, 0); - - AddComponent(new AddonComponent(0x149A), 4, 1, 0); - AddComponent(new AddonComponent(0x1498), 4, 2, 0); - AddComponent(new AddonComponent(0x148F), 4, 4, 0); - AddComponent(new AddonComponent(0x148D), 4, 6, 0); - AddComponent(new AddonComponent(0x1488), 4, 8, 0); - AddComponent(new AddonComponent(0x1460), 4, 9, 0); - AddComponent(new AddonComponent(0x1462), 4, 10, 0); - - AddComponent(new AddonComponent(0x147D), 5, 0, 0); - AddComponent(new AddonComponent(0x1490), 5, 4, 0); - AddComponent(new AddonComponent(0x148B), 5, 5, 0); - AddComponent(new AddonComponent(0x148A), 5, 6, 0); - AddComponent(new AddonComponent(0x1486), 5, 7, 0); - AddComponent(new AddonComponent(0x1485), 5, 8, 0); - - AddComponent(new AddonComponent(0x147C), 6, 0, 0); - AddComponent(new AddonComponent(0x1491), 6, 4, 0); - AddComponent(new AddonComponent(0x148C), 6, 5, 0); - AddComponent(new AddonComponent(0x1489), 6, 6, 0); - AddComponent(new AddonComponent(0x1487), 6, 7, 0); - AddComponent(new AddonComponent(0x1484), 6, 8, 0); - AddComponent(new AddonComponent(0x1463), 6, 10, 0); - - AddComponent(new AddonComponent(0x147B), 7, 0, 0); - AddComponent(new AddonComponent(0x147F), 7, 3, 0); - AddComponent(new AddonComponent(0x1480), 7, 4, 0); - AddComponent(new AddonComponent(0x1482), 7, 5, 0); - AddComponent(new AddonComponent(0x1469), 7, 6, 0); - AddComponent(new AddonComponent(0x1468), 7, 7, 0); - AddComponent(new AddonComponent(0x1465), 7, 8, 0); - AddComponent(new AddonComponent(0x1464), 7, 9, 0); - - AddComponent(new AddonComponent(0x147A), 8, 0, 0); - AddComponent(new AddonComponent(0x1479), 8, 1, 0); - AddComponent(new AddonComponent(0x1477), 8, 2, 0); - AddComponent(new AddonComponent(0x147E), 8, 3, 0); - AddComponent(new AddonComponent(0x1481), 8, 4, 0); - AddComponent(new AddonComponent(0x1483), 8, 5, 0); - AddComponent(new AddonComponent(0x146A), 8, 6, 0); - AddComponent(new AddonComponent(0x1467), 8, 7, 0); - AddComponent(new AddonComponent(0x1466), 8, 8, 0); - - AddComponent(new AddonComponent(0x1478), 9, 1, 0); - AddComponent(new AddonComponent(0x1475), 9, 2, 0); - AddComponent(new AddonComponent(0x1474), 9, 3, 0); - AddComponent(new AddonComponent(0x146F), 9, 4, 0); - AddComponent(new AddonComponent(0x146E), 9, 5, 0); - AddComponent(new AddonComponent(0x146D), 9, 6, 0); - AddComponent(new AddonComponent(0x146B), 9, 7, 0); - - AddComponent(new AddonComponent(0x1476), 10, 2, 0); - AddComponent(new AddonComponent(0x1473), 10, 3, 0); - AddComponent(new AddonComponent(0x1470), 10, 4, 0); - AddComponent(new AddonComponent(0x1471), 10, 5, 0); - AddComponent(new AddonComponent(0x1472), 10, 6, 0); - } - - public Telescope(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Telescope : BaseAddon + { + [Constructible] + public Telescope() + { + AddComponent(new AddonComponent(0x1494), 0, 5, 0); + AddComponent(new AddonComponent(0x145B), 0, 6, 0); + AddComponent(new AddonComponent(0x145A), 0, 7, 0); + + AddComponent(new AddonComponent(0x1495), 1, 4, 0); + AddComponent(new AddonComponent(0x145C), 1, 7, 0); + AddComponent(new AddonComponent(0x145D), 1, 8, 0); + + AddComponent(new AddonComponent(0x1496), 2, 3, 0); + AddComponent(new AddonComponent(0x1499), 2, 4, 0); + AddComponent(new AddonComponent(0x148E), 2, 6, 0); + AddComponent(new AddonComponent(0x1493), 2, 7, 0); + AddComponent(new AddonComponent(0x1492), 2, 8, 0); + AddComponent(new AddonComponent(0x145E), 2, 9, 0); + AddComponent(new AddonComponent(0x1459), 2, 10, 0); + + AddComponent(new AddonComponent(0x1497), 3, 2, 0); + AddComponent(new AddonComponent(0x145F), 3, 9, 0); + AddComponent(new AddonComponent(0x1461), 3, 10, 0); + + AddComponent(new AddonComponent(0x149A), 4, 1, 0); + AddComponent(new AddonComponent(0x1498), 4, 2, 0); + AddComponent(new AddonComponent(0x148F), 4, 4, 0); + AddComponent(new AddonComponent(0x148D), 4, 6, 0); + AddComponent(new AddonComponent(0x1488), 4, 8, 0); + AddComponent(new AddonComponent(0x1460), 4, 9, 0); + AddComponent(new AddonComponent(0x1462), 4, 10, 0); + + AddComponent(new AddonComponent(0x147D), 5, 0, 0); + AddComponent(new AddonComponent(0x1490), 5, 4, 0); + AddComponent(new AddonComponent(0x148B), 5, 5, 0); + AddComponent(new AddonComponent(0x148A), 5, 6, 0); + AddComponent(new AddonComponent(0x1486), 5, 7, 0); + AddComponent(new AddonComponent(0x1485), 5, 8, 0); + + AddComponent(new AddonComponent(0x147C), 6, 0, 0); + AddComponent(new AddonComponent(0x1491), 6, 4, 0); + AddComponent(new AddonComponent(0x148C), 6, 5, 0); + AddComponent(new AddonComponent(0x1489), 6, 6, 0); + AddComponent(new AddonComponent(0x1487), 6, 7, 0); + AddComponent(new AddonComponent(0x1484), 6, 8, 0); + AddComponent(new AddonComponent(0x1463), 6, 10, 0); + + AddComponent(new AddonComponent(0x147B), 7, 0, 0); + AddComponent(new AddonComponent(0x147F), 7, 3, 0); + AddComponent(new AddonComponent(0x1480), 7, 4, 0); + AddComponent(new AddonComponent(0x1482), 7, 5, 0); + AddComponent(new AddonComponent(0x1469), 7, 6, 0); + AddComponent(new AddonComponent(0x1468), 7, 7, 0); + AddComponent(new AddonComponent(0x1465), 7, 8, 0); + AddComponent(new AddonComponent(0x1464), 7, 9, 0); + + AddComponent(new AddonComponent(0x147A), 8, 0, 0); + AddComponent(new AddonComponent(0x1479), 8, 1, 0); + AddComponent(new AddonComponent(0x1477), 8, 2, 0); + AddComponent(new AddonComponent(0x147E), 8, 3, 0); + AddComponent(new AddonComponent(0x1481), 8, 4, 0); + AddComponent(new AddonComponent(0x1483), 8, 5, 0); + AddComponent(new AddonComponent(0x146A), 8, 6, 0); + AddComponent(new AddonComponent(0x1467), 8, 7, 0); + AddComponent(new AddonComponent(0x1466), 8, 8, 0); + + AddComponent(new AddonComponent(0x1478), 9, 1, 0); + AddComponent(new AddonComponent(0x1475), 9, 2, 0); + AddComponent(new AddonComponent(0x1474), 9, 3, 0); + AddComponent(new AddonComponent(0x146F), 9, 4, 0); + AddComponent(new AddonComponent(0x146E), 9, 5, 0); + AddComponent(new AddonComponent(0x146D), 9, 6, 0); + AddComponent(new AddonComponent(0x146B), 9, 7, 0); + + AddComponent(new AddonComponent(0x1476), 10, 2, 0); + AddComponent(new AddonComponent(0x1473), 10, 3, 0); + AddComponent(new AddonComponent(0x1470), 10, 4, 0); + AddComponent(new AddonComponent(0x1471), 10, 5, 0); + AddComponent(new AddonComponent(0x1472), 10, 6, 0); + } + + public Telescope(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/TrainingDummies.cs b/Projects/UOContent/Items/Addons/TrainingDummies.cs index 375aca6a2..7ebbee488 100644 --- a/Projects/UOContent/Items/Addons/TrainingDummies.cs +++ b/Projects/UOContent/Items/Addons/TrainingDummies.cs @@ -1,263 +1,265 @@ -using System; - -namespace Server.Items -{ - [Flippable(0x1070, 0x1074)] - public class TrainingDummy : AddonComponent - { - private Timer m_Timer; - - [Constructible] - public TrainingDummy(int itemID = 0x1074) : base(itemID) - { - MinSkill = -25.0; - MaxSkill = +25.0; - } - - public TrainingDummy(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public double MinSkill { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public double MaxSkill { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Swinging => m_Timer != null; - - public void UpdateItemID() - { - int baseItemID = ItemID / 2 * 2; - - ItemID = baseItemID + (Swinging ? 1 : 0); - } - - public void BeginSwing() - { - m_Timer?.Stop(); - - m_Timer = new InternalTimer(this); - m_Timer.Start(); - } - - public void EndSwing() - { - m_Timer?.Stop(); - - m_Timer = null; - - UpdateItemID(); - } - - public void OnHit() - { - UpdateItemID(); - Effects.PlaySound(GetWorldLocation(), Map, Utility.RandomList(0x3A4, 0x3A6, 0x3A9, 0x3AE, 0x3B4, 0x3B6)); - } - - public void Use(Mobile from, BaseWeapon weapon) - { - BeginSwing(); - - from.Direction = from.GetDirectionTo(GetWorldLocation()); - weapon.PlaySwingAnimation(from); - - from.CheckSkill(weapon.Skill, MinSkill, MaxSkill); - } - - public override void OnDoubleClick(Mobile from) - { - BaseWeapon weapon = from.Weapon as BaseWeapon; - - if (weapon is BaseRanged) - SendLocalizedMessageTo(from, 501822); // You can't practice ranged weapons on this. - else if (weapon == null || !from.InRange(GetWorldLocation(), weapon.MaxRange)) - SendLocalizedMessageTo(from, 501816); // You are too far away to do that. - else if (Swinging) - SendLocalizedMessageTo(from, 501815); // You have to wait until it stops swinging. - else if (from.Skills[weapon.Skill].Base >= MaxSkill) - SendLocalizedMessageTo(from, - 501828); // Your skill cannot improve any further by simply practicing with a dummy. - else if (from.Mounted) - SendLocalizedMessageTo(from, 501829); // You can't practice on this while on a mount. - else - Use(from, weapon); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(MinSkill); - writer.Write(MaxSkill); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - MinSkill = reader.ReadDouble(); - MaxSkill = reader.ReadDouble(); - - if (MinSkill == 0.0 && MaxSkill == 30.0) - { - MinSkill = -25.0; - MaxSkill = +25.0; - } - - break; - } - } - - UpdateItemID(); - } - - private class InternalTimer : Timer - { - private bool m_Delay = true; - private readonly TrainingDummy m_Dummy; - - public InternalTimer(TrainingDummy dummy) : base(TimeSpan.FromSeconds(0.25), TimeSpan.FromSeconds(2.75)) - { - m_Dummy = dummy; - Priority = TimerPriority.FiftyMS; - } - - protected override void OnTick() - { - if (m_Delay) - m_Dummy.OnHit(); - else - m_Dummy.EndSwing(); - - m_Delay = !m_Delay; - } - } - } - - public class TrainingDummyEastAddon : BaseAddon - { - [Constructible] - public TrainingDummyEastAddon() - { - AddComponent(new TrainingDummy(), 0, 0, 0); - } - - public TrainingDummyEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new TrainingDummyEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class TrainingDummyEastDeed : BaseAddonDeed - { - [Constructible] - public TrainingDummyEastDeed() - { - } - - public TrainingDummyEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new TrainingDummyEastAddon(); - public override int LabelNumber => 1044335; // training dummy (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class TrainingDummySouthAddon : BaseAddon - { - [Constructible] - public TrainingDummySouthAddon() - { - AddComponent(new TrainingDummy(0x1070), 0, 0, 0); - } - - public TrainingDummySouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new TrainingDummySouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class TrainingDummySouthDeed : BaseAddonDeed - { - [Constructible] - public TrainingDummySouthDeed() - { - } - - public TrainingDummySouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new TrainingDummySouthAddon(); - public override int LabelNumber => 1044336; // training dummy (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; + +namespace Server.Items +{ + [Flippable(0x1070, 0x1074)] + public class TrainingDummy : AddonComponent + { + private Timer m_Timer; + + [Constructible] + public TrainingDummy(int itemID = 0x1074) : base(itemID) + { + MinSkill = -25.0; + MaxSkill = +25.0; + } + + public TrainingDummy(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public double MinSkill { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public double MaxSkill { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Swinging => m_Timer != null; + + public void UpdateItemID() + { + var baseItemID = ItemID / 2 * 2; + + ItemID = baseItemID + (Swinging ? 1 : 0); + } + + public void BeginSwing() + { + m_Timer?.Stop(); + + m_Timer = new InternalTimer(this); + m_Timer.Start(); + } + + public void EndSwing() + { + m_Timer?.Stop(); + + m_Timer = null; + + UpdateItemID(); + } + + public void OnHit() + { + UpdateItemID(); + Effects.PlaySound(GetWorldLocation(), Map, Utility.RandomList(0x3A4, 0x3A6, 0x3A9, 0x3AE, 0x3B4, 0x3B6)); + } + + public void Use(Mobile from, BaseWeapon weapon) + { + BeginSwing(); + + from.Direction = from.GetDirectionTo(GetWorldLocation()); + weapon.PlaySwingAnimation(from); + + from.CheckSkill(weapon.Skill, MinSkill, MaxSkill); + } + + public override void OnDoubleClick(Mobile from) + { + var weapon = from.Weapon as BaseWeapon; + + if (weapon is BaseRanged) + SendLocalizedMessageTo(from, 501822); // You can't practice ranged weapons on this. + else if (weapon == null || !from.InRange(GetWorldLocation(), weapon.MaxRange)) + SendLocalizedMessageTo(from, 501816); // You are too far away to do that. + else if (Swinging) + SendLocalizedMessageTo(from, 501815); // You have to wait until it stops swinging. + else if (from.Skills[weapon.Skill].Base >= MaxSkill) + SendLocalizedMessageTo( + from, + 501828 + ); // Your skill cannot improve any further by simply practicing with a dummy. + else if (from.Mounted) + SendLocalizedMessageTo(from, 501829); // You can't practice on this while on a mount. + else + Use(from, weapon); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + writer.Write(MinSkill); + writer.Write(MaxSkill); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + MinSkill = reader.ReadDouble(); + MaxSkill = reader.ReadDouble(); + + if (MinSkill == 0.0 && MaxSkill == 30.0) + { + MinSkill = -25.0; + MaxSkill = +25.0; + } + + break; + } + } + + UpdateItemID(); + } + + private class InternalTimer : Timer + { + private readonly TrainingDummy m_Dummy; + private bool m_Delay = true; + + public InternalTimer(TrainingDummy dummy) : base(TimeSpan.FromSeconds(0.25), TimeSpan.FromSeconds(2.75)) + { + m_Dummy = dummy; + Priority = TimerPriority.FiftyMS; + } + + protected override void OnTick() + { + if (m_Delay) + m_Dummy.OnHit(); + else + m_Dummy.EndSwing(); + + m_Delay = !m_Delay; + } + } + } + + public class TrainingDummyEastAddon : BaseAddon + { + [Constructible] + public TrainingDummyEastAddon() + { + AddComponent(new TrainingDummy(), 0, 0, 0); + } + + public TrainingDummyEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new TrainingDummyEastDeed(); + + 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 class TrainingDummyEastDeed : BaseAddonDeed + { + [Constructible] + public TrainingDummyEastDeed() + { + } + + public TrainingDummyEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new TrainingDummyEastAddon(); + public override int LabelNumber => 1044335; // training dummy (east) + + 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 class TrainingDummySouthAddon : BaseAddon + { + [Constructible] + public TrainingDummySouthAddon() + { + AddComponent(new TrainingDummy(0x1070), 0, 0, 0); + } + + public TrainingDummySouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new TrainingDummySouthDeed(); + + 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 class TrainingDummySouthDeed : BaseAddonDeed + { + [Constructible] + public TrainingDummySouthDeed() + { + } + + public TrainingDummySouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new TrainingDummySouthAddon(); + public override int LabelNumber => 1044336; // training dummy (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/WarriorStatueEastAddon.cs b/Projects/UOContent/Items/Addons/WarriorStatueEastAddon.cs index 4f20529f0..3540c088d 100644 --- a/Projects/UOContent/Items/Addons/WarriorStatueEastAddon.cs +++ b/Projects/UOContent/Items/Addons/WarriorStatueEastAddon.cs @@ -1,60 +1,60 @@ -namespace Server.Items -{ - public class WarriorStatueEastAddon : BaseAddon - { - [Constructible] - public WarriorStatueEastAddon() - { - AddComponent(new AddonComponent(0x2D12), 0, 0, 0); - } - - public WarriorStatueEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new WarriorStatueEastDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class WarriorStatueEastDeed : BaseAddonDeed - { - [Constructible] - public WarriorStatueEastDeed() - { - } - - public WarriorStatueEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new WarriorStatueEastAddon(); - public override int LabelNumber => 1072888; // warrior statue (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class WarriorStatueEastAddon : BaseAddon + { + [Constructible] + public WarriorStatueEastAddon() + { + AddComponent(new AddonComponent(0x2D12), 0, 0, 0); + } + + public WarriorStatueEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new WarriorStatueEastDeed(); + + 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(); + } + } + + public class WarriorStatueEastDeed : BaseAddonDeed + { + [Constructible] + public WarriorStatueEastDeed() + { + } + + public WarriorStatueEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new WarriorStatueEastAddon(); + public override int LabelNumber => 1072888; // warrior statue (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/WarriorStatueSouthAddon.cs b/Projects/UOContent/Items/Addons/WarriorStatueSouthAddon.cs index 1ff45f351..9ae73ca15 100644 --- a/Projects/UOContent/Items/Addons/WarriorStatueSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/WarriorStatueSouthAddon.cs @@ -1,60 +1,60 @@ -namespace Server.Items -{ - public class WarriorStatueSouthAddon : BaseAddon - { - [Constructible] - public WarriorStatueSouthAddon() - { - AddComponent(new AddonComponent(0x2D13), 0, 0, 0); - } - - public WarriorStatueSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new WarriorStatueSouthDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class WarriorStatueSouthDeed : BaseAddonDeed - { - [Constructible] - public WarriorStatueSouthDeed() - { - } - - public WarriorStatueSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new WarriorStatueSouthAddon(); - public override int LabelNumber => 1072887; // warrior statue (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class WarriorStatueSouthAddon : BaseAddon + { + [Constructible] + public WarriorStatueSouthAddon() + { + AddComponent(new AddonComponent(0x2D13), 0, 0, 0); + } + + public WarriorStatueSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new WarriorStatueSouthDeed(); + + 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(); + } + } + + public class WarriorStatueSouthDeed : BaseAddonDeed + { + [Constructible] + public WarriorStatueSouthDeed() + { + } + + public WarriorStatueSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new WarriorStatueSouthAddon(); + public override int LabelNumber => 1072887; // warrior statue (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/WaterTroughEastAddon.cs b/Projects/UOContent/Items/Addons/WaterTroughEastAddon.cs index d521f8ea0..29fb619e0 100644 --- a/Projects/UOContent/Items/Addons/WaterTroughEastAddon.cs +++ b/Projects/UOContent/Items/Addons/WaterTroughEastAddon.cs @@ -1,67 +1,67 @@ -namespace Server.Items -{ - public class WaterTroughEastAddon : BaseAddon, IWaterSource - { - [Constructible] - public WaterTroughEastAddon() - { - AddComponent(new AddonComponent(0xB41), 0, 0, 0); - AddComponent(new AddonComponent(0xB42), 0, 1, 0); - } - - public WaterTroughEastAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new WaterTroughEastDeed(); - - int IHasQuantity.Quantity - { - get => 500; - set { } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class WaterTroughEastDeed : BaseAddonDeed - { - [Constructible] - public WaterTroughEastDeed() - { - } - - public WaterTroughEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new WaterTroughEastAddon(); - public override int LabelNumber => 1044349; // water trough (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class WaterTroughEastAddon : BaseAddon, IWaterSource + { + [Constructible] + public WaterTroughEastAddon() + { + AddComponent(new AddonComponent(0xB41), 0, 0, 0); + AddComponent(new AddonComponent(0xB42), 0, 1, 0); + } + + public WaterTroughEastAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new WaterTroughEastDeed(); + + int IHasQuantity.Quantity + { + get => 500; + set { } + } + + 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 class WaterTroughEastDeed : BaseAddonDeed + { + [Constructible] + public WaterTroughEastDeed() + { + } + + public WaterTroughEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new WaterTroughEastAddon(); + public override int LabelNumber => 1044349; // water trough (east) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/WaterTroughSouthAddon.cs b/Projects/UOContent/Items/Addons/WaterTroughSouthAddon.cs index e30b39429..cfab923b0 100644 --- a/Projects/UOContent/Items/Addons/WaterTroughSouthAddon.cs +++ b/Projects/UOContent/Items/Addons/WaterTroughSouthAddon.cs @@ -1,67 +1,67 @@ -namespace Server.Items -{ - public class WaterTroughSouthAddon : BaseAddon, IWaterSource - { - [Constructible] - public WaterTroughSouthAddon() - { - AddComponent(new AddonComponent(0xB43), 0, 0, 0); - AddComponent(new AddonComponent(0xB44), 1, 0, 0); - } - - public WaterTroughSouthAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new WaterTroughSouthDeed(); - - int IHasQuantity.Quantity - { - get => 500; - set { } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class WaterTroughSouthDeed : BaseAddonDeed - { - [Constructible] - public WaterTroughSouthDeed() - { - } - - public WaterTroughSouthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new WaterTroughSouthAddon(); - public override int LabelNumber => 1044350; // water trough (south) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class WaterTroughSouthAddon : BaseAddon, IWaterSource + { + [Constructible] + public WaterTroughSouthAddon() + { + AddComponent(new AddonComponent(0xB43), 0, 0, 0); + AddComponent(new AddonComponent(0xB44), 1, 0, 0); + } + + public WaterTroughSouthAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new WaterTroughSouthDeed(); + + int IHasQuantity.Quantity + { + get => 500; + set { } + } + + 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 class WaterTroughSouthDeed : BaseAddonDeed + { + [Constructible] + public WaterTroughSouthDeed() + { + } + + public WaterTroughSouthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new WaterTroughSouthAddon(); + public override int LabelNumber => 1044350; // water trough (south) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Addons/WaterVat.cs b/Projects/UOContent/Items/Addons/WaterVat.cs index 1edf83e81..e60101793 100644 --- a/Projects/UOContent/Items/Addons/WaterVat.cs +++ b/Projects/UOContent/Items/Addons/WaterVat.cs @@ -1,84 +1,84 @@ -namespace Server.Items -{ - public class WaterVatEast : BaseAddon - { - [Constructible] - public WaterVatEast() - { - AddComponent(new AddonComponent(0x1558), 0, 0, 0); - AddComponent(new AddonComponent(0x14DE), -1, 1, 0); - AddComponent(new AddonComponent(0x1552), 0, 1, 0); - AddComponent(new AddonComponent(0x14DF), 1, -1, 0); - AddComponent(new AddonComponent(0x1554), 1, 0, 0); - AddComponent(new AddonComponent(0x1559), 1, 1, 0); - AddComponent(new AddonComponent(0x1550), 1, 3, 0); - AddComponent(new AddonComponent(0x1555), 3, 1, 0); - AddComponent(new AddonComponent(0x14D7), 2, 2, 0); - - // Blockers - AddComponent(new AddonComponent(0x21A4), 2, -1, 0); - AddComponent(new AddonComponent(0x21A4), 3, 0, 0); - AddComponent(new AddonComponent(0x21A4), -1, 2, 0); - AddComponent(new AddonComponent(0x21A4), 0, 3, 0); - } - - public WaterVatEast(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class WaterVatSouth : BaseAddon - { - [Constructible] - public WaterVatSouth() - { - AddComponent(new AddonComponent(0x1558), 0, 0, 0); - AddComponent(new AddonComponent(0x14DE), -1, 1, 0); - AddComponent(new AddonComponent(0x1552), 0, 1, 0); - AddComponent(new AddonComponent(0x14DF), 1, -1, 0); - AddComponent(new AddonComponent(0x1554), 1, 0, 0); - AddComponent(new AddonComponent(0x1559), 1, 1, 0); - AddComponent(new AddonComponent(0x1551), 1, 3, 0); - AddComponent(new AddonComponent(0x1556), 3, 1, 0); - AddComponent(new AddonComponent(0x14D7), 2, 2, 0); - - // Blockers - AddComponent(new AddonComponent(0x21A4), 2, -1, 0); - AddComponent(new AddonComponent(0x21A4), 3, 0, 0); - AddComponent(new AddonComponent(0x21A4), -1, 2, 0); - AddComponent(new AddonComponent(0x21A4), 0, 3, 0); - } - - public WaterVatSouth(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class WaterVatEast : BaseAddon + { + [Constructible] + public WaterVatEast() + { + AddComponent(new AddonComponent(0x1558), 0, 0, 0); + AddComponent(new AddonComponent(0x14DE), -1, 1, 0); + AddComponent(new AddonComponent(0x1552), 0, 1, 0); + AddComponent(new AddonComponent(0x14DF), 1, -1, 0); + AddComponent(new AddonComponent(0x1554), 1, 0, 0); + AddComponent(new AddonComponent(0x1559), 1, 1, 0); + AddComponent(new AddonComponent(0x1550), 1, 3, 0); + AddComponent(new AddonComponent(0x1555), 3, 1, 0); + AddComponent(new AddonComponent(0x14D7), 2, 2, 0); + + // Blockers + AddComponent(new AddonComponent(0x21A4), 2, -1, 0); + AddComponent(new AddonComponent(0x21A4), 3, 0, 0); + AddComponent(new AddonComponent(0x21A4), -1, 2, 0); + AddComponent(new AddonComponent(0x21A4), 0, 3, 0); + } + + public WaterVatEast(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class WaterVatSouth : BaseAddon + { + [Constructible] + public WaterVatSouth() + { + AddComponent(new AddonComponent(0x1558), 0, 0, 0); + AddComponent(new AddonComponent(0x14DE), -1, 1, 0); + AddComponent(new AddonComponent(0x1552), 0, 1, 0); + AddComponent(new AddonComponent(0x14DF), 1, -1, 0); + AddComponent(new AddonComponent(0x1554), 1, 0, 0); + AddComponent(new AddonComponent(0x1559), 1, 1, 0); + AddComponent(new AddonComponent(0x1551), 1, 3, 0); + AddComponent(new AddonComponent(0x1556), 3, 1, 0); + AddComponent(new AddonComponent(0x14D7), 2, 2, 0); + + // Blockers + AddComponent(new AddonComponent(0x21A4), 2, -1, 0); + AddComponent(new AddonComponent(0x21A4), 3, 0, 0); + AddComponent(new AddonComponent(0x21A4), -1, 2, 0); + AddComponent(new AddonComponent(0x21A4), 0, 3, 0); + } + + public WaterVatSouth(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Aquarium.cs b/Projects/UOContent/Items/Aquarium/Aquarium.cs index 85e0b6dad..189ba7205 100644 --- a/Projects/UOContent/Items/Aquarium/Aquarium.cs +++ b/Projects/UOContent/Items/Aquarium/Aquarium.cs @@ -1,1126 +1,1154 @@ -using System; -using System.Collections.Generic; -using Server.ContextMenus; -using Server.Multis; -using Server.Network; -using Server.Utilities; - -namespace Server.Items -{ - public class Aquarium : BaseAddonContainer - { - public static readonly TimeSpan EvaluationInterval = TimeSpan.FromDays(1); - private bool m_EvaluateDay; - - // aquarium state - private AquariumState m_Food; - - // events - private bool m_RewardAvailable; - - // evaluate timer - private Timer m_Timer; - - // vacation info - private int m_VacationLeft; - private AquariumState m_Water; - - public Aquarium(int itemID) : base(itemID) - { - Movable = false; - - if (itemID == 0x3060) - AddComponent(new AddonContainerComponent(0x3061), -1, 0, 0); - - if (itemID == 0x3062) - AddComponent(new AddonContainerComponent(0x3063), 0, -1, 0); - - MaxItems = 30; - - m_Food = new AquariumState(); - m_Water = new AquariumState(); - - m_Food.State = (int)FoodState.Full; - m_Water.State = (int)WaterState.Strong; - - m_Food.Maintain = Utility.RandomMinMax(1, 2); - m_Food.Improve = m_Food.Maintain + Utility.RandomMinMax(1, 2); - - m_Water.Maintain = Utility.RandomMinMax(1, 3); - - Events = new List(); - - m_Timer = Timer.DelayCall(EvaluationInterval, EvaluationInterval, Evaluate); - } - - public Aquarium(Serial serial) : base(serial) - { - } - - // items info - - [CommandProperty(AccessLevel.GameMaster)] - public int LiveCreatures { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int DeadCreatures - { - get - { - int dead = 0; - - for (int i = 0; i < Items.Count; i++) - if (Items[i] is BaseFish) - { - BaseFish fish = (BaseFish)Items[i]; - - if (fish.Dead) - dead += 1; - } - - return dead; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxLiveCreatures - { - get - { - int state = m_Food.State == (int)FoodState.Overfed ? 1 : (int)FoodState.Full - m_Food.State; - - state += (int)WaterState.Strong - m_Water.State; - - state = (int)Math.Pow(state, 1.75); - - return MaxItems - state; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsFull => Items.Count >= MaxItems; - - [CommandProperty(AccessLevel.GameMaster)] - public int VacationLeft - { - get => m_VacationLeft; - set - { - m_VacationLeft = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public AquariumState Food - { - get => m_Food; - set - { - m_Food = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public AquariumState Water - { - get => m_Water; - set - { - m_Water = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool OptimalState => m_Food.State == (int)FoodState.Full && m_Water.State == (int)WaterState.Strong; - - public List Events { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool RewardAvailable - { - get => m_RewardAvailable; - set - { - m_RewardAvailable = value; - InvalidateProperties(); - } - } - - public override BaseAddonContainerDeed Deed - { - get - { - if (ItemID == 0x3062) - return new AquariumEastDeed(); - return new AquariumNorthDeed(); - } - } - - public override double DefaultWeight => 10.0; - - public override void OnDelete() - { - if (m_Timer != null) - { - m_Timer.Stop(); - m_Timer = null; - } - } - - public override void OnDoubleClick(Mobile from) - { - ExamineAquarium(from); - } - - public virtual bool HasAccess(Mobile from) => - from?.Deleted == false && ( - from.AccessLevel >= AccessLevel.GameMaster || - BaseHouse.FindHouseAt(this)?.IsCoOwner(from) == true); - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (!HasAccess(from)) - { - from.SendLocalizedMessage(1073821); // You do not have access to that item for use with the aquarium. - return false; - } - - if (m_VacationLeft > 0) - { - from.SendLocalizedMessage(1074427); // The aquarium is in vacation mode. - return false; - } - - bool takeItem = true; - - if (dropped is FishBowl bowl) - { - if (bowl.Empty || !AddFish(from, bowl.Fish)) - return false; - - bowl.InvalidateProperties(); - - takeItem = false; - } - else if (dropped is BaseFish fish) - { - if (!AddFish(from, fish)) - return false; - } - else if (dropped is VacationWafer) - { - m_VacationLeft = VacationWafer.VacationDays; - dropped.Delete(); - - from.SendLocalizedMessage(1074428, - m_VacationLeft.ToString()); // The aquarium will be in vacation mode for ~1_DAYS~ days - } - else if (dropped is AquariumFood) - { - m_Food.Added += 1; - dropped.Delete(); - - from.SendLocalizedMessage(1074259, "1"); // ~1_NUM~ unit(s) of food have been added to the aquarium. - } - else if (dropped is BaseBeverage beverage) - { - if (beverage.IsEmpty || !beverage.Pourable || beverage.Content != BeverageType.Water) - { - from.SendLocalizedMessage(500840); // Can't pour that in there. - return false; - } - - m_Water.Added += 1; - beverage.Quantity -= 1; - - from.PlaySound(0x4E); - from.SendLocalizedMessage(1074260, "1"); // ~1_NUM~ unit(s) of water have been added to the aquarium. - - takeItem = false; - } - else if (!AddDecoration(from, dropped)) - { - takeItem = false; - } - - from.CloseGump(); - - InvalidateProperties(); - - if (takeItem) - from.PlaySound(0x42); - - return takeItem; - } - - public override void DropItemsToGround() - { - Point3D loc = GetWorldLocation(); - - for (int i = Items.Count - 1; i >= 0; i--) - { - Item item = Items[i]; - - item.MoveToWorld(loc, Map); - - if (item is BaseFish fish && !fish.Dead) - fish.StartTimer(); - } - } - - public override bool CheckItemUse(Mobile from, Item item) - { - if (item != this) - return false; - - return base.CheckItemUse(from, item); - } - - public override bool CheckLift(Mobile from, Item item, ref LRReason reject) - { - if (item != this) - { - reject = LRReason.CannotLift; - return false; - } - - return base.CheckLift(from, item, ref reject); - } - - public override void OnSingleClick(Mobile from) - { - if (Deleted || !from.CanSee(this)) - return; - - base.OnSingleClick(from); - - if (m_VacationLeft > 0) - LabelTo(from, 1074430, m_VacationLeft.ToString()); // Vacation days left: ~1_DAYS - - if (Events.Count > 0) - LabelTo(from, 1074426, Events.Count.ToString()); // ~1_NUM~ event(s) to view! - - if (m_RewardAvailable) - LabelTo(from, 1074362); // A reward is available! - - LabelTo(from, 1074247, $"{LiveCreatures}\t{MaxLiveCreatures}"); // Live Creatures: ~1_NUM~ / ~2_MAX~ - - if (DeadCreatures > 0) - LabelTo(from, 1074248, DeadCreatures.ToString()); // Dead Creatures: ~1_NUM~ - - int decorations = Items.Count - LiveCreatures - DeadCreatures; - - if (decorations > 0) - LabelTo(from, 1074249, (Items.Count - LiveCreatures - DeadCreatures).ToString()); // Decorations: ~1_NUM~ - - LabelTo(from, 1074250, $"#{FoodNumber()}"); // Food state: ~1_STATE~ - LabelTo(from, 1074251, $"#{WaterNumber()}"); // Water state: ~1_STATE~ - - if (m_Food.State == (int)FoodState.Dead) - LabelTo(from, 1074577, $"{m_Food.Added}\t{m_Food.Improve}"); // Food Added: ~1_CUR~ Needed: ~2_NEED~ - else if (m_Food.State == (int)FoodState.Overfed) - LabelTo(from, 1074577, $"{m_Food.Added}\t{m_Food.Maintain}"); // Food Added: ~1_CUR~ Needed: ~2_NEED~ - else - LabelTo(from, 1074253, - $"{m_Food.Added}\t{m_Food.Maintain}\t{m_Food.Improve}"); // Food Added: ~1_CUR~ Feed: ~2_NEED~ Improve: ~3_GROW~ - - if (m_Water.State == (int)WaterState.Dead) - LabelTo(from, 1074578, $"{m_Water.Added}\t{m_Water.Improve}"); // Water Added: ~1_CUR~ Needed: ~2_NEED~ - else if (m_Water.State == (int)WaterState.Strong) - LabelTo(from, 1074578, $"{m_Water.Added}\t{m_Water.Maintain}"); // Water Added: ~1_CUR~ Needed: ~2_NEED~ - else - LabelTo(from, 1074254, - $"{m_Water.Added}\t{m_Water.Maintain}\t{m_Water.Improve}"); // Water Added: ~1_CUR~ Maintain: ~2_NEED~ Improve: ~3_GROW~ - } - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - if (m_VacationLeft > 0) - list.Add(1074430, m_VacationLeft.ToString()); // Vacation days left: ~1_DAYS - - if (Events.Count > 0) - list.Add(1074426, Events.Count.ToString()); // ~1_NUM~ event(s) to view! - - if (m_RewardAvailable) - list.Add(1074362); // A reward is available! - - list.Add(1074247, "{0}\t{1}", LiveCreatures, MaxLiveCreatures); // Live Creatures: ~1_NUM~ / ~2_MAX~ - - int dead = DeadCreatures; - - if (dead > 0) - list.Add(1074248, dead.ToString()); // Dead Creatures: ~1_NUM~ - - int decorations = Items.Count - LiveCreatures - dead; - - if (decorations > 0) - list.Add(1074249, decorations.ToString()); // Decorations: ~1_NUM~ - - list.Add(1074250, "#{0}", FoodNumber()); // Food state: ~1_STATE~ - list.Add(1074251, "#{0}", WaterNumber()); // Water state: ~1_STATE~ - - if (m_Food.State == (int)FoodState.Dead) - list.Add(1074577, "{0}\t{1}", m_Food.Added, m_Food.Improve); // Food Added: ~1_CUR~ Needed: ~2_NEED~ - else if (m_Food.State == (int)FoodState.Overfed) - list.Add(1074577, "{0}\t{1}", m_Food.Added, m_Food.Maintain); // Food Added: ~1_CUR~ Needed: ~2_NEED~ - else - list.Add(1074253, "{0}\t{1}\t{2}", m_Food.Added, m_Food.Maintain, - m_Food.Improve); // Food Added: ~1_CUR~ Feed: ~2_NEED~ Improve: ~3_GROW~ - - if (m_Water.State == (int)WaterState.Dead) - list.Add(1074578, "{0}\t{1}", m_Water.Added, m_Water.Improve); // Water Added: ~1_CUR~ Needed: ~2_NEED~ - else if (m_Water.State == (int)WaterState.Strong) - list.Add(1074578, "{0}\t{1}", m_Water.Added, m_Water.Maintain); // Water Added: ~1_CUR~ Needed: ~2_NEED~ - else - list.Add(1074254, "{0}\t{1}\t{2}", m_Water.Added, m_Water.Maintain, - m_Water.Improve); // Water Added: ~1_CUR~ Maintain: ~2_NEED~ Improve: ~3_GROW~ - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (from.Alive) - { - list.Add(new ExamineEntry(this)); - - if (HasAccess(from)) - { - if (m_RewardAvailable) - list.Add(new CollectRewardEntry(this)); - - if (Events.Count > 0) - list.Add(new ViewEventEntry(this)); - - if (m_VacationLeft > 0) - list.Add(new CancelVacationMode(this)); - } - } - - if (from.AccessLevel >= AccessLevel.GameMaster) - { - list.Add(new GMAddFood(this)); - list.Add(new GMAddWater(this)); - list.Add(new GMForceEvaluate(this)); - list.Add(new GMOpen(this)); - list.Add(new GMFill(this)); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(3); // Version - - // version 1 - if (m_Timer != null) - writer.Write(m_Timer.Next); - else - writer.Write(DateTime.UtcNow + EvaluationInterval); - - // version 0 - writer.Write(LiveCreatures); - writer.Write(m_VacationLeft); - - m_Food.Serialize(writer); - m_Water.Serialize(writer); - - writer.Write(Events.Count); - - for (int i = 0; i < Events.Count; i++) - writer.Write(Events[i]); - - writer.Write(m_RewardAvailable); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 3: - case 2: - case 1: - { - DateTime next = reader.ReadDateTime(); - - if (next < DateTime.UtcNow) - next = DateTime.UtcNow; - - m_Timer = Timer.DelayCall(next - DateTime.UtcNow, EvaluationInterval, Evaluate); - - goto case 0; - } - case 0: - { - LiveCreatures = reader.ReadInt(); - m_VacationLeft = reader.ReadInt(); - - m_Food = new AquariumState(); - m_Water = new AquariumState(); - - m_Food.Deserialize(reader); - m_Water.Deserialize(reader); - - Events = new List(); - - int count = reader.ReadInt(); - - for (int i = 0; i < count; i++) - Events.Add(reader.ReadInt()); - - m_RewardAvailable = reader.ReadBool(); - - break; - } - } - - if (version < 2) - { - Weight = DefaultWeight; - Movable = false; - } - - if (version < 3) - ValidationQueue.Add(this); - } - - private void RecountLiveCreatures() - { - LiveCreatures = 0; - - FindItemsByType().ForEach(fish => - { - if (!fish.Dead) - ++LiveCreatures; - }); - } - - public void Validate() - { - RecountLiveCreatures(); - } - - public int FoodNumber() - { - if (m_Food.State == (int)FoodState.Full) - return 1074240; - - if (m_Food.State == (int)FoodState.Overfed) - return 1074239; - - return 1074236 + m_Food.State; - } - - public int WaterNumber() => 1074242 + m_Water.State; - - public virtual void KillFish(int amount) - { - List toKill = new List(); - - for (int i = 0; i < Items.Count; i++) - if (Items[i] is BaseFish) - { - BaseFish fish = (BaseFish)Items[i]; - - if (!fish.Dead) - toKill.Add(fish); - } - - while (amount > 0 && toKill.Count > 0) - { - var kill = toKill.RandomElement(); - kill.Kill(); - toKill.Remove(kill); - - amount -= 1; - LiveCreatures = Math.Max(LiveCreatures - 1, 0); - - Events.Add(1074366); // An unfortunate accident has left a creature floating upside-down. It is starting to smell. - } - } - - public virtual void Evaluate() - { - if (m_VacationLeft > 0) - { - m_VacationLeft -= 1; - } - else if (m_EvaluateDay) - { - // reset events - Events = new List(); - - // food events - if ( - (m_Food.Added < m_Food.Maintain && m_Food.State != (int)FoodState.Overfed && - m_Food.State != (int)FoodState.Dead) || - (m_Food.Added >= m_Food.Improve && m_Food.State == (int)FoodState.Full)) - Events.Add(1074368); // The tank looks worse than it did yesterday. - - if ( - (m_Food.Added >= m_Food.Improve && m_Food.State != (int)FoodState.Full && - m_Food.State != (int)FoodState.Overfed) || - (m_Food.Added < m_Food.Maintain && m_Food.State == (int)FoodState.Overfed)) - Events.Add(1074367); // The tank looks healthier today. - - // water events - if (m_Water.Added < m_Water.Maintain && m_Water.State != (int)WaterState.Dead) - Events.Add(1074370); // This tank can use more water. - - if (m_Water.Added >= m_Water.Improve && m_Water.State != (int)WaterState.Strong) - Events.Add(1074369); // The water looks clearer today. - - UpdateFoodState(); - UpdateWaterState(); - - // reward - if (LiveCreatures > 0) - m_RewardAvailable = true; - } - else - { - // new fish - if (OptimalState && LiveCreatures < MaxLiveCreatures) - if (Utility.RandomDouble() < 0.005 * LiveCreatures) - { - BaseFish fish; - int message; - - switch (Utility.Random(6)) - { - case 0: - { - message = 1074371; // Brine shrimp have hatched overnight in the tank. - fish = new BrineShrimp(); - break; - } - case 1: - { - message = 1074365; // A new creature has hatched overnight in the tank. - fish = new Coral(); - break; - } - case 2: - { - message = 1074365; // A new creature has hatched overnight in the tank. - fish = new FullMoonFish(); - break; - } - case 3: - { - message = 1074373; // A sea horse has hatched overnight in the tank. - fish = new SeaHorseFish(); - break; - } - case 4: - { - message = 1074365; // A new creature has hatched overnight in the tank. - fish = new StrippedFlakeFish(); - break; - } - default: // 5 - { - message = 1074365; // A new creature has hatched overnight in the tank. - fish = new StrippedSosarianSwill(); - break; - } - } - - if (Utility.RandomDouble() < 0.05) - fish.Hue = FishHues.RandomElement(); - else if (Utility.RandomDouble() < 0.5) - fish.Hue = Utility.RandomMinMax(0x100, 0x3E5); - - if (AddFish(fish)) - Events.Add(message); - else - fish.Delete(); - } - - // kill fish *grins* - if (LiveCreatures < MaxLiveCreatures) - { - if (Utility.RandomDouble() < 0.01) - KillFish(1); - } - else - { - KillFish(LiveCreatures - MaxLiveCreatures); - } - } - - m_EvaluateDay = !m_EvaluateDay; - InvalidateProperties(); - } - - public virtual void GiveReward(Mobile to) - { - if (!m_RewardAvailable) - return; - - int max = (int)((double)LiveCreatures / 30 * m_Decorations.Length); - - int random = max <= 0 ? 0 : Utility.Random(max); - - if (random >= m_Decorations.Length) - random = m_Decorations.Length - 1; - - Item item; - - try - { - item = ActivatorUtil.CreateInstance(m_Decorations[random]) as Item; - } - catch - { - return; - } - - if (item == null) - return; - - if (!to.PlaceInBackpack(item)) - { - item.Delete(); - to.SendLocalizedMessage(1074361); // The reward could not be given. Make sure you have room in your pack. - return; - } - - to.SendLocalizedMessage(1074360, $"#{item.LabelNumber}"); // You receive a reward: ~1_REWARD~ - to.PlaySound(0x5A3); - - m_RewardAvailable = false; - - InvalidateProperties(); - } - - public virtual void UpdateFoodState() - { - if (m_Food.Added < m_Food.Maintain) - m_Food.State = m_Food.State <= 0 ? 0 : m_Food.State - 1; - else if (m_Food.Added >= m_Food.Improve) - m_Food.State = m_Food.State >= (int)FoodState.Overfed ? (int)FoodState.Overfed : m_Food.State + 1; - - m_Food.Maintain = Utility.Random((int)FoodState.Overfed + 1 - m_Food.State, 2); - - if (m_Food.State == (int)FoodState.Overfed) - m_Food.Improve = 0; - else - m_Food.Improve = m_Food.Maintain + 2; - - m_Food.Added = 0; - } - - public virtual void UpdateWaterState() - { - if (m_Water.Added < m_Water.Maintain) - m_Water.State = m_Water.State <= 0 ? 0 : m_Water.State - 1; - else if (m_Water.Added >= m_Water.Improve) - m_Water.State = m_Water.State >= (int)WaterState.Strong ? (int)WaterState.Strong : m_Water.State + 1; - - m_Water.Maintain = Utility.Random((int)WaterState.Strong + 2 - m_Water.State, 2); - - if (m_Water.State == (int)WaterState.Strong) - m_Water.Improve = 0; - else - m_Water.Improve = m_Water.Maintain + 2; - - m_Water.Added = 0; - } - - public virtual bool RemoveItem(Mobile from, int at) - { - if (at < 0 || at >= Items.Count) - return false; - - Item item = Items[at]; - - if (item.IsLockedDown) // for legacy aquariums - { - from.SendLocalizedMessage(1010449); // You may not use this object while it is locked down. - return false; - } - - if (item is BaseFish fish) - { - FishBowl bowl; - - if ((bowl = GetEmptyBowl(from)) != null) - { - bowl.AddItem(fish); - - from.SendLocalizedMessage(1074511); // You put the creature into a fish bowl. - } - else - { - if (!from.PlaceInBackpack(fish)) - { - from.SendLocalizedMessage(1074514); // You have no place to put it. - return false; - } - - from.SendLocalizedMessage(1074512); // You put the gasping creature into your pack. - } - - if (!fish.Dead) - LiveCreatures -= 1; - } - else - { - if (!from.PlaceInBackpack(item)) - { - from.SendLocalizedMessage(1074514); // You have no place to put it. - return false; - } - - from.SendLocalizedMessage(1074513); // You put the item into your pack. - } - - InvalidateProperties(); - return true; - } - - public virtual void ExamineAquarium(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return; - } - - from.CloseGump(); - from.SendGump(new AquariumGump(this, HasAccess(from))); - - from.PlaySound(0x5A4); - } - - public virtual bool AddFish(BaseFish fish) => AddFish(null, fish); - - public virtual bool AddFish(Mobile from, BaseFish fish) - { - if (fish == null) - return false; - - if (IsFull || LiveCreatures >= MaxLiveCreatures || fish.Dead) - { - from?.SendLocalizedMessage(1073633); // The aquarium can not hold the creature. - - return false; - } - - AddItem(fish); - fish.StopTimer(); - - LiveCreatures += 1; - - from?.SendLocalizedMessage(1073632, - $"#{fish.LabelNumber}"); // You add the following creature to your aquarium: ~1_FISH~ - - InvalidateProperties(); - return true; - } - - public virtual bool AddDecoration(Item item) => AddDecoration(null, item); - - public virtual bool AddDecoration(Mobile from, Item item) - { - if (item == null) - return false; - - if (IsFull) - { - from?.SendLocalizedMessage(1073636); // The decoration will not fit in the aquarium. - - return false; - } - - if (!Accepts(item)) - { - from?.SendLocalizedMessage(1073822); // The aquarium can not hold that item. - - return false; - } - - AddItem(item); - - from?.SendLocalizedMessage(1073635, - item.LabelNumber != 0 - ? $"#{item.LabelNumber}" - : item.Name); // You add the following decoration to your aquarium: ~1_NAME~ - - InvalidateProperties(); - return true; - } - - public static FishBowl GetEmptyBowl(Mobile from) - { - return from?.Backpack?.FindItemsByType().Find(bowl => bowl.Empty); - } - - private static readonly Type[] m_Decorations = - { - typeof(FishBones), - typeof(WaterloggedBoots), - typeof(CaptainBlackheartsFishingPole), - typeof(CraftysFishingHat), - typeof(AquariumFishNet), - typeof(AquariumMessage), - typeof(IslandStatue), - typeof(Shell), - typeof(ToyBoat) - }; - - public static bool Accepts(Item item) - { - if (item == null) - return false; - - Type type = item.GetType(); - - for (int i = 0; i < m_Decorations.Length; i++) - if (type == m_Decorations[i]) - return true; - - return false; - } - - public static int[] FishHues { get; } = - { - 0x1C2, 0x1C3, 0x2A3, 0x47E, 0x51D - }; - - private class ExamineEntry : ContextMenuEntry - { - private readonly Aquarium m_Aquarium; - - public ExamineEntry(Aquarium aquarium) : base(6235, 2) // Examine Aquarium - => - m_Aquarium = aquarium; - - public override void OnClick() - { - if (m_Aquarium.Deleted) - return; - - m_Aquarium.ExamineAquarium(Owner.From); - } - } - - private class CollectRewardEntry : ContextMenuEntry - { - private readonly Aquarium m_Aquarium; - - public CollectRewardEntry(Aquarium aquarium) : base(6237, 2) // Collect Reward - => - m_Aquarium = aquarium; - - public override void OnClick() - { - if (m_Aquarium.Deleted || !m_Aquarium.HasAccess(Owner.From)) - return; - - m_Aquarium.GiveReward(Owner.From); - } - } - - private class ViewEventEntry : ContextMenuEntry - { - private readonly Aquarium m_Aquarium; - - public ViewEventEntry(Aquarium aquarium) : base(6239, 2) // View events - => - m_Aquarium = aquarium; - - public override void OnClick() - { - if (m_Aquarium.Deleted || !m_Aquarium.HasAccess(Owner.From) || m_Aquarium.Events.Count == 0) - return; - - Owner.From.SendLocalizedMessage(m_Aquarium.Events[0]); - - if (m_Aquarium.Events[0] == 1074366) - Owner.From.PlaySound(0x5A2); - - m_Aquarium.Events.RemoveAt(0); - m_Aquarium.InvalidateProperties(); - } - } - - private class CancelVacationMode : ContextMenuEntry - { - private readonly Aquarium m_Aquarium; - - public CancelVacationMode(Aquarium aquarium) : base(6240, 2) // Cancel vacation mode - => - m_Aquarium = aquarium; - - public override void OnClick() - { - if (m_Aquarium.Deleted || !m_Aquarium.HasAccess(Owner.From)) - return; - - Owner.From.SendLocalizedMessage(1074429); // Vacation mode has been cancelled. - m_Aquarium.VacationLeft = 0; - m_Aquarium.InvalidateProperties(); - } - } - - // GM context entries - private class GMAddFood : ContextMenuEntry - { - private readonly Aquarium m_Aquarium; - - public GMAddFood(Aquarium aquarium) : base(6231) // GM Add Food - => - m_Aquarium = aquarium; - - public override void OnClick() - { - if (m_Aquarium.Deleted) - return; - - m_Aquarium.Food.Added += 1; - m_Aquarium.InvalidateProperties(); - } - } - - private class GMAddWater : ContextMenuEntry - { - private readonly Aquarium m_Aquarium; - - public GMAddWater(Aquarium aquarium) : base(6232) // GM Add Water - => - m_Aquarium = aquarium; - - public override void OnClick() - { - if (m_Aquarium.Deleted) - return; - - m_Aquarium.Water.Added += 1; - m_Aquarium.InvalidateProperties(); - } - } - - private class GMForceEvaluate : ContextMenuEntry - { - private readonly Aquarium m_Aquarium; - - public GMForceEvaluate(Aquarium aquarium) : base(6233) // GM Force Evaluate - => - m_Aquarium = aquarium; - - public override void OnClick() - { - if (m_Aquarium.Deleted) - return; - - m_Aquarium.Evaluate(); - } - } - - private class GMOpen : ContextMenuEntry - { - private readonly Aquarium m_Aquarium; - - public GMOpen(Aquarium aquarium) : base(6234) // GM Open Container - => - m_Aquarium = aquarium; - - public override void OnClick() - { - if (m_Aquarium.Deleted) - return; - - Owner.From.SendGump(new AquariumGump(m_Aquarium, true)); - } - } - - private class GMFill : ContextMenuEntry - { - private readonly Aquarium m_Aquarium; - - public GMFill(Aquarium aquarium) : base(6236) // GM Fill Food and Water - => - m_Aquarium = aquarium; - - public override void OnClick() - { - if (m_Aquarium.Deleted) - return; - - m_Aquarium.Food.Added = m_Aquarium.Food.Maintain; - m_Aquarium.Water.Added = m_Aquarium.Water.Maintain; - m_Aquarium.InvalidateProperties(); - } - } - } - - public class AquariumEastDeed : BaseAddonContainerDeed - { - [Constructible] - public AquariumEastDeed() - { - } - - public AquariumEastDeed(Serial serial) : base(serial) - { - } - - public override BaseAddonContainer Addon => new Aquarium(0x3062); - public override int LabelNumber => 1074501; // Large Aquarium (east) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class AquariumNorthDeed : BaseAddonContainerDeed - { - [Constructible] - public AquariumNorthDeed() - { - } - - public AquariumNorthDeed(Serial serial) : base(serial) - { - } - - public override BaseAddonContainer Addon => new Aquarium(0x3060); - public override int LabelNumber => 1074497; // Large Aquarium (north) - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // Version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using System.Collections.Generic; +using Server.ContextMenus; +using Server.Multis; +using Server.Network; +using Server.Utilities; + +namespace Server.Items +{ + public class Aquarium : BaseAddonContainer + { + public static readonly TimeSpan EvaluationInterval = TimeSpan.FromDays(1); + + private static readonly Type[] m_Decorations = + { + typeof(FishBones), + typeof(WaterloggedBoots), + typeof(CaptainBlackheartsFishingPole), + typeof(CraftysFishingHat), + typeof(AquariumFishNet), + typeof(AquariumMessage), + typeof(IslandStatue), + typeof(Shell), + typeof(ToyBoat) + }; + + private bool m_EvaluateDay; + + // aquarium state + private AquariumState m_Food; + + // events + private bool m_RewardAvailable; + + // evaluate timer + private Timer m_Timer; + + // vacation info + private int m_VacationLeft; + private AquariumState m_Water; + + public Aquarium(int itemID) : base(itemID) + { + Movable = false; + + if (itemID == 0x3060) + AddComponent(new AddonContainerComponent(0x3061), -1, 0, 0); + + if (itemID == 0x3062) + AddComponent(new AddonContainerComponent(0x3063), 0, -1, 0); + + MaxItems = 30; + + m_Food = new AquariumState(); + m_Water = new AquariumState(); + + m_Food.State = (int)FoodState.Full; + m_Water.State = (int)WaterState.Strong; + + m_Food.Maintain = Utility.RandomMinMax(1, 2); + m_Food.Improve = m_Food.Maintain + Utility.RandomMinMax(1, 2); + + m_Water.Maintain = Utility.RandomMinMax(1, 3); + + Events = new List(); + + m_Timer = Timer.DelayCall(EvaluationInterval, EvaluationInterval, Evaluate); + } + + public Aquarium(Serial serial) : base(serial) + { + } + + // items info + + [CommandProperty(AccessLevel.GameMaster)] + public int LiveCreatures { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int DeadCreatures + { + get + { + var dead = 0; + + for (var i = 0; i < Items.Count; i++) + if (Items[i] is BaseFish) + { + var fish = (BaseFish)Items[i]; + + if (fish.Dead) + dead += 1; + } + + return dead; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxLiveCreatures + { + get + { + var state = m_Food.State == (int)FoodState.Overfed ? 1 : (int)FoodState.Full - m_Food.State; + + state += (int)WaterState.Strong - m_Water.State; + + state = (int)Math.Pow(state, 1.75); + + return MaxItems - state; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsFull => Items.Count >= MaxItems; + + [CommandProperty(AccessLevel.GameMaster)] + public int VacationLeft + { + get => m_VacationLeft; + set + { + m_VacationLeft = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public AquariumState Food + { + get => m_Food; + set + { + m_Food = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public AquariumState Water + { + get => m_Water; + set + { + m_Water = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool OptimalState => m_Food.State == (int)FoodState.Full && m_Water.State == (int)WaterState.Strong; + + public List Events { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool RewardAvailable + { + get => m_RewardAvailable; + set + { + m_RewardAvailable = value; + InvalidateProperties(); + } + } + + public override BaseAddonContainerDeed Deed + { + get + { + if (ItemID == 0x3062) + return new AquariumEastDeed(); + return new AquariumNorthDeed(); + } + } + + public override double DefaultWeight => 10.0; + + public static int[] FishHues { get; } = + { + 0x1C2, 0x1C3, 0x2A3, 0x47E, 0x51D + }; + + public override void OnDelete() + { + if (m_Timer != null) + { + m_Timer.Stop(); + m_Timer = null; + } + } + + public override void OnDoubleClick(Mobile from) + { + ExamineAquarium(from); + } + + public virtual bool HasAccess(Mobile from) => + from?.Deleted == false && ( + from.AccessLevel >= AccessLevel.GameMaster || + BaseHouse.FindHouseAt(this)?.IsCoOwner(from) == true); + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (!HasAccess(from)) + { + from.SendLocalizedMessage(1073821); // You do not have access to that item for use with the aquarium. + return false; + } + + if (m_VacationLeft > 0) + { + from.SendLocalizedMessage(1074427); // The aquarium is in vacation mode. + return false; + } + + var takeItem = true; + + if (dropped is FishBowl bowl) + { + if (bowl.Empty || !AddFish(from, bowl.Fish)) + return false; + + bowl.InvalidateProperties(); + + takeItem = false; + } + else if (dropped is BaseFish fish) + { + if (!AddFish(from, fish)) + return false; + } + else if (dropped is VacationWafer) + { + m_VacationLeft = VacationWafer.VacationDays; + dropped.Delete(); + + from.SendLocalizedMessage( + 1074428, + m_VacationLeft.ToString() + ); // The aquarium will be in vacation mode for ~1_DAYS~ days + } + else if (dropped is AquariumFood) + { + m_Food.Added += 1; + dropped.Delete(); + + from.SendLocalizedMessage(1074259, "1"); // ~1_NUM~ unit(s) of food have been added to the aquarium. + } + else if (dropped is BaseBeverage beverage) + { + if (beverage.IsEmpty || !beverage.Pourable || beverage.Content != BeverageType.Water) + { + from.SendLocalizedMessage(500840); // Can't pour that in there. + return false; + } + + m_Water.Added += 1; + beverage.Quantity -= 1; + + from.PlaySound(0x4E); + from.SendLocalizedMessage(1074260, "1"); // ~1_NUM~ unit(s) of water have been added to the aquarium. + + takeItem = false; + } + else if (!AddDecoration(from, dropped)) + { + takeItem = false; + } + + from.CloseGump(); + + InvalidateProperties(); + + if (takeItem) + from.PlaySound(0x42); + + return takeItem; + } + + public override void DropItemsToGround() + { + var loc = GetWorldLocation(); + + for (var i = Items.Count - 1; i >= 0; i--) + { + var item = Items[i]; + + item.MoveToWorld(loc, Map); + + if (item is BaseFish fish && !fish.Dead) + fish.StartTimer(); + } + } + + public override bool CheckItemUse(Mobile from, Item item) + { + if (item != this) + return false; + + return base.CheckItemUse(from, item); + } + + public override bool CheckLift(Mobile from, Item item, ref LRReason reject) + { + if (item != this) + { + reject = LRReason.CannotLift; + return false; + } + + return base.CheckLift(from, item, ref reject); + } + + public override void OnSingleClick(Mobile from) + { + if (Deleted || !from.CanSee(this)) + return; + + base.OnSingleClick(from); + + if (m_VacationLeft > 0) + LabelTo(from, 1074430, m_VacationLeft.ToString()); // Vacation days left: ~1_DAYS + + if (Events.Count > 0) + LabelTo(from, 1074426, Events.Count.ToString()); // ~1_NUM~ event(s) to view! + + if (m_RewardAvailable) + LabelTo(from, 1074362); // A reward is available! + + LabelTo(from, 1074247, $"{LiveCreatures}\t{MaxLiveCreatures}"); // Live Creatures: ~1_NUM~ / ~2_MAX~ + + if (DeadCreatures > 0) + LabelTo(from, 1074248, DeadCreatures.ToString()); // Dead Creatures: ~1_NUM~ + + var decorations = Items.Count - LiveCreatures - DeadCreatures; + + if (decorations > 0) + LabelTo(from, 1074249, (Items.Count - LiveCreatures - DeadCreatures).ToString()); // Decorations: ~1_NUM~ + + LabelTo(from, 1074250, $"#{FoodNumber()}"); // Food state: ~1_STATE~ + LabelTo(from, 1074251, $"#{WaterNumber()}"); // Water state: ~1_STATE~ + + if (m_Food.State == (int)FoodState.Dead) + LabelTo(from, 1074577, $"{m_Food.Added}\t{m_Food.Improve}"); // Food Added: ~1_CUR~ Needed: ~2_NEED~ + else if (m_Food.State == (int)FoodState.Overfed) + LabelTo(from, 1074577, $"{m_Food.Added}\t{m_Food.Maintain}"); // Food Added: ~1_CUR~ Needed: ~2_NEED~ + else + LabelTo( + from, + 1074253, + $"{m_Food.Added}\t{m_Food.Maintain}\t{m_Food.Improve}" + ); // Food Added: ~1_CUR~ Feed: ~2_NEED~ Improve: ~3_GROW~ + + if (m_Water.State == (int)WaterState.Dead) + LabelTo(from, 1074578, $"{m_Water.Added}\t{m_Water.Improve}"); // Water Added: ~1_CUR~ Needed: ~2_NEED~ + else if (m_Water.State == (int)WaterState.Strong) + LabelTo(from, 1074578, $"{m_Water.Added}\t{m_Water.Maintain}"); // Water Added: ~1_CUR~ Needed: ~2_NEED~ + else + LabelTo( + from, + 1074254, + $"{m_Water.Added}\t{m_Water.Maintain}\t{m_Water.Improve}" + ); // Water Added: ~1_CUR~ Maintain: ~2_NEED~ Improve: ~3_GROW~ + } + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + if (m_VacationLeft > 0) + list.Add(1074430, m_VacationLeft.ToString()); // Vacation days left: ~1_DAYS + + if (Events.Count > 0) + list.Add(1074426, Events.Count.ToString()); // ~1_NUM~ event(s) to view! + + if (m_RewardAvailable) + list.Add(1074362); // A reward is available! + + list.Add(1074247, "{0}\t{1}", LiveCreatures, MaxLiveCreatures); // Live Creatures: ~1_NUM~ / ~2_MAX~ + + var dead = DeadCreatures; + + if (dead > 0) + list.Add(1074248, dead.ToString()); // Dead Creatures: ~1_NUM~ + + var decorations = Items.Count - LiveCreatures - dead; + + if (decorations > 0) + list.Add(1074249, decorations.ToString()); // Decorations: ~1_NUM~ + + list.Add(1074250, "#{0}", FoodNumber()); // Food state: ~1_STATE~ + list.Add(1074251, "#{0}", WaterNumber()); // Water state: ~1_STATE~ + + if (m_Food.State == (int)FoodState.Dead) + list.Add(1074577, "{0}\t{1}", m_Food.Added, m_Food.Improve); // Food Added: ~1_CUR~ Needed: ~2_NEED~ + else if (m_Food.State == (int)FoodState.Overfed) + list.Add(1074577, "{0}\t{1}", m_Food.Added, m_Food.Maintain); // Food Added: ~1_CUR~ Needed: ~2_NEED~ + else + list.Add( + 1074253, + "{0}\t{1}\t{2}", + m_Food.Added, + m_Food.Maintain, + m_Food.Improve + ); // Food Added: ~1_CUR~ Feed: ~2_NEED~ Improve: ~3_GROW~ + + if (m_Water.State == (int)WaterState.Dead) + list.Add(1074578, "{0}\t{1}", m_Water.Added, m_Water.Improve); // Water Added: ~1_CUR~ Needed: ~2_NEED~ + else if (m_Water.State == (int)WaterState.Strong) + list.Add(1074578, "{0}\t{1}", m_Water.Added, m_Water.Maintain); // Water Added: ~1_CUR~ Needed: ~2_NEED~ + else + list.Add( + 1074254, + "{0}\t{1}\t{2}", + m_Water.Added, + m_Water.Maintain, + m_Water.Improve + ); // Water Added: ~1_CUR~ Maintain: ~2_NEED~ Improve: ~3_GROW~ + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (from.Alive) + { + list.Add(new ExamineEntry(this)); + + if (HasAccess(from)) + { + if (m_RewardAvailable) + list.Add(new CollectRewardEntry(this)); + + if (Events.Count > 0) + list.Add(new ViewEventEntry(this)); + + if (m_VacationLeft > 0) + list.Add(new CancelVacationMode(this)); + } + } + + if (from.AccessLevel >= AccessLevel.GameMaster) + { + list.Add(new GMAddFood(this)); + list.Add(new GMAddWater(this)); + list.Add(new GMForceEvaluate(this)); + list.Add(new GMOpen(this)); + list.Add(new GMFill(this)); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(3); // Version + + // version 1 + if (m_Timer != null) + writer.Write(m_Timer.Next); + else + writer.Write(DateTime.UtcNow + EvaluationInterval); + + // version 0 + writer.Write(LiveCreatures); + writer.Write(m_VacationLeft); + + m_Food.Serialize(writer); + m_Water.Serialize(writer); + + writer.Write(Events.Count); + + for (var i = 0; i < Events.Count; i++) + writer.Write(Events[i]); + + writer.Write(m_RewardAvailable); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 3: + case 2: + case 1: + { + var next = reader.ReadDateTime(); + + if (next < DateTime.UtcNow) + next = DateTime.UtcNow; + + m_Timer = Timer.DelayCall(next - DateTime.UtcNow, EvaluationInterval, Evaluate); + + goto case 0; + } + case 0: + { + LiveCreatures = reader.ReadInt(); + m_VacationLeft = reader.ReadInt(); + + m_Food = new AquariumState(); + m_Water = new AquariumState(); + + m_Food.Deserialize(reader); + m_Water.Deserialize(reader); + + Events = new List(); + + var count = reader.ReadInt(); + + for (var i = 0; i < count; i++) + Events.Add(reader.ReadInt()); + + m_RewardAvailable = reader.ReadBool(); + + break; + } + } + + if (version < 2) + { + Weight = DefaultWeight; + Movable = false; + } + + if (version < 3) + ValidationQueue.Add(this); + } + + private void RecountLiveCreatures() + { + LiveCreatures = 0; + + FindItemsByType() + .ForEach( + fish => + { + if (!fish.Dead) + ++LiveCreatures; + } + ); + } + + public void Validate() + { + RecountLiveCreatures(); + } + + public int FoodNumber() + { + if (m_Food.State == (int)FoodState.Full) + return 1074240; + + if (m_Food.State == (int)FoodState.Overfed) + return 1074239; + + return 1074236 + m_Food.State; + } + + public int WaterNumber() => 1074242 + m_Water.State; + + public virtual void KillFish(int amount) + { + var toKill = new List(); + + for (var i = 0; i < Items.Count; i++) + if (Items[i] is BaseFish) + { + var fish = (BaseFish)Items[i]; + + if (!fish.Dead) + toKill.Add(fish); + } + + while (amount > 0 && toKill.Count > 0) + { + var kill = toKill.RandomElement(); + kill.Kill(); + toKill.Remove(kill); + + amount -= 1; + LiveCreatures = Math.Max(LiveCreatures - 1, 0); + + Events.Add( + 1074366 + ); // An unfortunate accident has left a creature floating upside-down. It is starting to smell. + } + } + + public virtual void Evaluate() + { + if (m_VacationLeft > 0) + { + m_VacationLeft -= 1; + } + else if (m_EvaluateDay) + { + // reset events + Events = new List(); + + // food events + if ( + m_Food.Added < m_Food.Maintain && m_Food.State != (int)FoodState.Overfed && + m_Food.State != (int)FoodState.Dead || + m_Food.Added >= m_Food.Improve && m_Food.State == (int)FoodState.Full) + Events.Add(1074368); // The tank looks worse than it did yesterday. + + if ( + m_Food.Added >= m_Food.Improve && m_Food.State != (int)FoodState.Full && + m_Food.State != (int)FoodState.Overfed || + m_Food.Added < m_Food.Maintain && m_Food.State == (int)FoodState.Overfed) + Events.Add(1074367); // The tank looks healthier today. + + // water events + if (m_Water.Added < m_Water.Maintain && m_Water.State != (int)WaterState.Dead) + Events.Add(1074370); // This tank can use more water. + + if (m_Water.Added >= m_Water.Improve && m_Water.State != (int)WaterState.Strong) + Events.Add(1074369); // The water looks clearer today. + + UpdateFoodState(); + UpdateWaterState(); + + // reward + if (LiveCreatures > 0) + m_RewardAvailable = true; + } + else + { + // new fish + if (OptimalState && LiveCreatures < MaxLiveCreatures) + if (Utility.RandomDouble() < 0.005 * LiveCreatures) + { + BaseFish fish; + int message; + + switch (Utility.Random(6)) + { + case 0: + { + message = 1074371; // Brine shrimp have hatched overnight in the tank. + fish = new BrineShrimp(); + break; + } + case 1: + { + message = 1074365; // A new creature has hatched overnight in the tank. + fish = new Coral(); + break; + } + case 2: + { + message = 1074365; // A new creature has hatched overnight in the tank. + fish = new FullMoonFish(); + break; + } + case 3: + { + message = 1074373; // A sea horse has hatched overnight in the tank. + fish = new SeaHorseFish(); + break; + } + case 4: + { + message = 1074365; // A new creature has hatched overnight in the tank. + fish = new StrippedFlakeFish(); + break; + } + default: // 5 + { + message = 1074365; // A new creature has hatched overnight in the tank. + fish = new StrippedSosarianSwill(); + break; + } + } + + if (Utility.RandomDouble() < 0.05) + fish.Hue = FishHues.RandomElement(); + else if (Utility.RandomDouble() < 0.5) + fish.Hue = Utility.RandomMinMax(0x100, 0x3E5); + + if (AddFish(fish)) + Events.Add(message); + else + fish.Delete(); + } + + // kill fish *grins* + if (LiveCreatures < MaxLiveCreatures) + { + if (Utility.RandomDouble() < 0.01) + KillFish(1); + } + else + { + KillFish(LiveCreatures - MaxLiveCreatures); + } + } + + m_EvaluateDay = !m_EvaluateDay; + InvalidateProperties(); + } + + public virtual void GiveReward(Mobile to) + { + if (!m_RewardAvailable) + return; + + var max = (int)((double)LiveCreatures / 30 * m_Decorations.Length); + + var random = max <= 0 ? 0 : Utility.Random(max); + + if (random >= m_Decorations.Length) + random = m_Decorations.Length - 1; + + Item item; + + try + { + item = ActivatorUtil.CreateInstance(m_Decorations[random]) as Item; + } + catch + { + return; + } + + if (item == null) + return; + + if (!to.PlaceInBackpack(item)) + { + item.Delete(); + to.SendLocalizedMessage(1074361); // The reward could not be given. Make sure you have room in your pack. + return; + } + + to.SendLocalizedMessage(1074360, $"#{item.LabelNumber}"); // You receive a reward: ~1_REWARD~ + to.PlaySound(0x5A3); + + m_RewardAvailable = false; + + InvalidateProperties(); + } + + public virtual void UpdateFoodState() + { + if (m_Food.Added < m_Food.Maintain) + m_Food.State = m_Food.State <= 0 ? 0 : m_Food.State - 1; + else if (m_Food.Added >= m_Food.Improve) + m_Food.State = m_Food.State >= (int)FoodState.Overfed ? (int)FoodState.Overfed : m_Food.State + 1; + + m_Food.Maintain = Utility.Random((int)FoodState.Overfed + 1 - m_Food.State, 2); + + if (m_Food.State == (int)FoodState.Overfed) + m_Food.Improve = 0; + else + m_Food.Improve = m_Food.Maintain + 2; + + m_Food.Added = 0; + } + + public virtual void UpdateWaterState() + { + if (m_Water.Added < m_Water.Maintain) + m_Water.State = m_Water.State <= 0 ? 0 : m_Water.State - 1; + else if (m_Water.Added >= m_Water.Improve) + m_Water.State = m_Water.State >= (int)WaterState.Strong ? (int)WaterState.Strong : m_Water.State + 1; + + m_Water.Maintain = Utility.Random((int)WaterState.Strong + 2 - m_Water.State, 2); + + if (m_Water.State == (int)WaterState.Strong) + m_Water.Improve = 0; + else + m_Water.Improve = m_Water.Maintain + 2; + + m_Water.Added = 0; + } + + public virtual bool RemoveItem(Mobile from, int at) + { + if (at < 0 || at >= Items.Count) + return false; + + var item = Items[at]; + + if (item.IsLockedDown) // for legacy aquariums + { + from.SendLocalizedMessage(1010449); // You may not use this object while it is locked down. + return false; + } + + if (item is BaseFish fish) + { + FishBowl bowl; + + if ((bowl = GetEmptyBowl(from)) != null) + { + bowl.AddItem(fish); + + from.SendLocalizedMessage(1074511); // You put the creature into a fish bowl. + } + else + { + if (!from.PlaceInBackpack(fish)) + { + from.SendLocalizedMessage(1074514); // You have no place to put it. + return false; + } + + from.SendLocalizedMessage(1074512); // You put the gasping creature into your pack. + } + + if (!fish.Dead) + LiveCreatures -= 1; + } + else + { + if (!from.PlaceInBackpack(item)) + { + from.SendLocalizedMessage(1074514); // You have no place to put it. + return false; + } + + from.SendLocalizedMessage(1074513); // You put the item into your pack. + } + + InvalidateProperties(); + return true; + } + + public virtual void ExamineAquarium(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return; + } + + from.CloseGump(); + from.SendGump(new AquariumGump(this, HasAccess(from))); + + from.PlaySound(0x5A4); + } + + public virtual bool AddFish(BaseFish fish) => AddFish(null, fish); + + public virtual bool AddFish(Mobile from, BaseFish fish) + { + if (fish == null) + return false; + + if (IsFull || LiveCreatures >= MaxLiveCreatures || fish.Dead) + { + from?.SendLocalizedMessage(1073633); // The aquarium can not hold the creature. + + return false; + } + + AddItem(fish); + fish.StopTimer(); + + LiveCreatures += 1; + + from?.SendLocalizedMessage( + 1073632, + $"#{fish.LabelNumber}" + ); // You add the following creature to your aquarium: ~1_FISH~ + + InvalidateProperties(); + return true; + } + + public virtual bool AddDecoration(Item item) => AddDecoration(null, item); + + public virtual bool AddDecoration(Mobile from, Item item) + { + if (item == null) + return false; + + if (IsFull) + { + from?.SendLocalizedMessage(1073636); // The decoration will not fit in the aquarium. + + return false; + } + + if (!Accepts(item)) + { + from?.SendLocalizedMessage(1073822); // The aquarium can not hold that item. + + return false; + } + + AddItem(item); + + from?.SendLocalizedMessage( + 1073635, + item.LabelNumber != 0 + ? $"#{item.LabelNumber}" + : item.Name + ); // You add the following decoration to your aquarium: ~1_NAME~ + + InvalidateProperties(); + return true; + } + + public static FishBowl GetEmptyBowl(Mobile from) + { + return from?.Backpack?.FindItemsByType().Find(bowl => bowl.Empty); + } + + public static bool Accepts(Item item) + { + if (item == null) + return false; + + var type = item.GetType(); + + for (var i = 0; i < m_Decorations.Length; i++) + if (type == m_Decorations[i]) + return true; + + return false; + } + + private class ExamineEntry : ContextMenuEntry + { + private readonly Aquarium m_Aquarium; + + public ExamineEntry(Aquarium aquarium) : base(6235, 2) // Examine Aquarium + => + m_Aquarium = aquarium; + + public override void OnClick() + { + if (m_Aquarium.Deleted) + return; + + m_Aquarium.ExamineAquarium(Owner.From); + } + } + + private class CollectRewardEntry : ContextMenuEntry + { + private readonly Aquarium m_Aquarium; + + public CollectRewardEntry(Aquarium aquarium) : base(6237, 2) // Collect Reward + => + m_Aquarium = aquarium; + + public override void OnClick() + { + if (m_Aquarium.Deleted || !m_Aquarium.HasAccess(Owner.From)) + return; + + m_Aquarium.GiveReward(Owner.From); + } + } + + private class ViewEventEntry : ContextMenuEntry + { + private readonly Aquarium m_Aquarium; + + public ViewEventEntry(Aquarium aquarium) : base(6239, 2) // View events + => + m_Aquarium = aquarium; + + public override void OnClick() + { + if (m_Aquarium.Deleted || !m_Aquarium.HasAccess(Owner.From) || m_Aquarium.Events.Count == 0) + return; + + Owner.From.SendLocalizedMessage(m_Aquarium.Events[0]); + + if (m_Aquarium.Events[0] == 1074366) + Owner.From.PlaySound(0x5A2); + + m_Aquarium.Events.RemoveAt(0); + m_Aquarium.InvalidateProperties(); + } + } + + private class CancelVacationMode : ContextMenuEntry + { + private readonly Aquarium m_Aquarium; + + public CancelVacationMode(Aquarium aquarium) : base(6240, 2) // Cancel vacation mode + => + m_Aquarium = aquarium; + + public override void OnClick() + { + if (m_Aquarium.Deleted || !m_Aquarium.HasAccess(Owner.From)) + return; + + Owner.From.SendLocalizedMessage(1074429); // Vacation mode has been cancelled. + m_Aquarium.VacationLeft = 0; + m_Aquarium.InvalidateProperties(); + } + } + + // GM context entries + private class GMAddFood : ContextMenuEntry + { + private readonly Aquarium m_Aquarium; + + public GMAddFood(Aquarium aquarium) : base(6231) // GM Add Food + => + m_Aquarium = aquarium; + + public override void OnClick() + { + if (m_Aquarium.Deleted) + return; + + m_Aquarium.Food.Added += 1; + m_Aquarium.InvalidateProperties(); + } + } + + private class GMAddWater : ContextMenuEntry + { + private readonly Aquarium m_Aquarium; + + public GMAddWater(Aquarium aquarium) : base(6232) // GM Add Water + => + m_Aquarium = aquarium; + + public override void OnClick() + { + if (m_Aquarium.Deleted) + return; + + m_Aquarium.Water.Added += 1; + m_Aquarium.InvalidateProperties(); + } + } + + private class GMForceEvaluate : ContextMenuEntry + { + private readonly Aquarium m_Aquarium; + + public GMForceEvaluate(Aquarium aquarium) : base(6233) // GM Force Evaluate + => + m_Aquarium = aquarium; + + public override void OnClick() + { + if (m_Aquarium.Deleted) + return; + + m_Aquarium.Evaluate(); + } + } + + private class GMOpen : ContextMenuEntry + { + private readonly Aquarium m_Aquarium; + + public GMOpen(Aquarium aquarium) : base(6234) // GM Open Container + => + m_Aquarium = aquarium; + + public override void OnClick() + { + if (m_Aquarium.Deleted) + return; + + Owner.From.SendGump(new AquariumGump(m_Aquarium, true)); + } + } + + private class GMFill : ContextMenuEntry + { + private readonly Aquarium m_Aquarium; + + public GMFill(Aquarium aquarium) : base(6236) // GM Fill Food and Water + => + m_Aquarium = aquarium; + + public override void OnClick() + { + if (m_Aquarium.Deleted) + return; + + m_Aquarium.Food.Added = m_Aquarium.Food.Maintain; + m_Aquarium.Water.Added = m_Aquarium.Water.Maintain; + m_Aquarium.InvalidateProperties(); + } + } + } + + public class AquariumEastDeed : BaseAddonContainerDeed + { + [Constructible] + public AquariumEastDeed() + { + } + + public AquariumEastDeed(Serial serial) : base(serial) + { + } + + public override BaseAddonContainer Addon => new Aquarium(0x3062); + public override int LabelNumber => 1074501; // Large Aquarium (east) + + 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 class AquariumNorthDeed : BaseAddonContainerDeed + { + [Constructible] + public AquariumNorthDeed() + { + } + + public AquariumNorthDeed(Serial serial) : base(serial) + { + } + + public override BaseAddonContainer Addon => new Aquarium(0x3060); + public override int LabelNumber => 1074497; // Large Aquarium (north) + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/AquariumFishingNet.cs b/Projects/UOContent/Items/Aquarium/AquariumFishingNet.cs index 2e270a20b..075ba5066 100644 --- a/Projects/UOContent/Items/Aquarium/AquariumFishingNet.cs +++ b/Projects/UOContent/Items/Aquarium/AquariumFishingNet.cs @@ -1,190 +1,191 @@ -namespace Server.Items -{ - public class AquariumFishNet : SpecialFishingNet - { - [Constructible] - public AquariumFishNet() - { - ItemID = 0xDC8; - - if (Hue == 0x8A0) - Hue = 0x240; - } - - public AquariumFishNet(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074463; // An aquarium fishing net - - public override bool RequireDeepWater => false; - - protected override void AddNetProperties(ObjectPropertyList list) - { - } - - protected override void FinishEffect(Point3D p, Map map, Mobile from) - { - if (from.Skills.Fishing.Value < 10) - { - from.SendLocalizedMessage(1074487); // The creatures are too quick for you! - } - else - { - BaseFish fish = GiveFish(from); - FishBowl bowl = Aquarium.GetEmptyBowl(from); - - if (bowl != null) - { - fish.StopTimer(); - bowl.AddItem(fish); - from.SendLocalizedMessage(1074489); // A live creature jumps into the fish bowl in your pack! - Delete(); - return; - } - - if (from.PlaceInBackpack(fish)) - { - from.PlaySound(0x5A2); - from.SendLocalizedMessage( - 1074490); // A live creature flops around in your pack before running out of air. - - fish.Kill(); - Delete(); - return; - } - - fish.Delete(); - - from.SendLocalizedMessage(1074488); // You could not hold the creature. - } - - InUse = false; - Movable = true; - - if (!from.PlaceInBackpack(this)) - { - if (from.Map == null || from.Map == Map.Internal) - Delete(); - else - MoveToWorld(from.Location, from.Map); - } - } - - private BaseFish GiveFish(Mobile from) - { - double skill = from.Skills.Fishing.Value; - - if (skill / 100.0 >= Utility.RandomDouble()) - { - int max = (int)skill / 5; - - if (max > 20) - max = 20; - - return Utility.Random(max) switch - { - 0 => (BaseFish)new MinocBlueFish(), - 1 => new Shrimp(), - 2 => new FandancerFish(), - 3 => new GoldenBroadtail(), - 4 => new RedDartFish(), - 5 => new AlbinoCourtesanFish(), - 6 => new MakotoCourtesanFish(), - 7 => new NujelmHoneyFish(), - 8 => new Jellyfish(), - 9 => new SpeckledCrab(), - 10 => new LongClawCrab(), - 11 => new AlbinoFrog(), - 12 => new KillerFrog(), - 13 => new VesperReefTiger(), - 14 => new PurpleFrog(), - 15 => new BritainCrownFish(), - 16 => new YellowFinBluebelly(), - 17 => new SpottedBuccaneer(), - 18 => new SpinedScratcherFish(), - _ => new SmallMouthSuckerFin() - }; - } - - return new MinocBlueFish(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - // Legacy code - public class AquariumFishingNet : Item - { - public AquariumFishingNet() - { - } - - public AquariumFishingNet(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074463; // An aquarium fishing net - - private Item CreateReplacement() - { - Item result = new AquariumFishNet(); - result.Hue = Hue; - result.LootType = LootType; - result.Movable = Movable; - result.Name = Name; - result.QuestItem = QuestItem; - result.Visible = Visible; - - return result; - } - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - return; - } - - Item replacement = CreateReplacement(); - - if (!from.PlaceInBackpack(replacement)) - { - replacement.Delete(); - from.SendLocalizedMessage(500720); // You don't have enough room in your backpack! - } - else - { - Delete(); - from.Use(replacement); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AquariumFishNet : SpecialFishingNet + { + [Constructible] + public AquariumFishNet() + { + ItemID = 0xDC8; + + if (Hue == 0x8A0) + Hue = 0x240; + } + + public AquariumFishNet(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074463; // An aquarium fishing net + + public override bool RequireDeepWater => false; + + protected override void AddNetProperties(ObjectPropertyList list) + { + } + + protected override void FinishEffect(Point3D p, Map map, Mobile from) + { + if (from.Skills.Fishing.Value < 10) + { + from.SendLocalizedMessage(1074487); // The creatures are too quick for you! + } + else + { + var fish = GiveFish(from); + var bowl = Aquarium.GetEmptyBowl(from); + + if (bowl != null) + { + fish.StopTimer(); + bowl.AddItem(fish); + from.SendLocalizedMessage(1074489); // A live creature jumps into the fish bowl in your pack! + Delete(); + return; + } + + if (from.PlaceInBackpack(fish)) + { + from.PlaySound(0x5A2); + from.SendLocalizedMessage( + 1074490 + ); // A live creature flops around in your pack before running out of air. + + fish.Kill(); + Delete(); + return; + } + + fish.Delete(); + + from.SendLocalizedMessage(1074488); // You could not hold the creature. + } + + InUse = false; + Movable = true; + + if (!from.PlaceInBackpack(this)) + { + if (from.Map == null || from.Map == Map.Internal) + Delete(); + else + MoveToWorld(from.Location, from.Map); + } + } + + private BaseFish GiveFish(Mobile from) + { + var skill = from.Skills.Fishing.Value; + + if (skill / 100.0 >= Utility.RandomDouble()) + { + var max = (int)skill / 5; + + if (max > 20) + max = 20; + + return Utility.Random(max) switch + { + 0 => new MinocBlueFish(), + 1 => new Shrimp(), + 2 => new FandancerFish(), + 3 => new GoldenBroadtail(), + 4 => new RedDartFish(), + 5 => new AlbinoCourtesanFish(), + 6 => new MakotoCourtesanFish(), + 7 => new NujelmHoneyFish(), + 8 => new Jellyfish(), + 9 => new SpeckledCrab(), + 10 => new LongClawCrab(), + 11 => new AlbinoFrog(), + 12 => new KillerFrog(), + 13 => new VesperReefTiger(), + 14 => new PurpleFrog(), + 15 => new BritainCrownFish(), + 16 => new YellowFinBluebelly(), + 17 => new SpottedBuccaneer(), + 18 => new SpinedScratcherFish(), + _ => new SmallMouthSuckerFin() + }; + } + + return new MinocBlueFish(); + } + + 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(); + } + } + + // Legacy code + public class AquariumFishingNet : Item + { + public AquariumFishingNet() + { + } + + public AquariumFishingNet(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074463; // An aquarium fishing net + + private Item CreateReplacement() + { + Item result = new AquariumFishNet(); + result.Hue = Hue; + result.LootType = LootType; + result.Movable = Movable; + result.Name = Name; + result.QuestItem = QuestItem; + result.Visible = Visible; + + return result; + } + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + return; + } + + var replacement = CreateReplacement(); + + if (!from.PlaceInBackpack(replacement)) + { + replacement.Delete(); + from.SendLocalizedMessage(500720); // You don't have enough room in your backpack! + } + else + { + Delete(); + from.Use(replacement); + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/AquariumFood.cs b/Projects/UOContent/Items/Aquarium/AquariumFood.cs index a2d7022cb..9927c53f5 100644 --- a/Projects/UOContent/Items/Aquarium/AquariumFood.cs +++ b/Projects/UOContent/Items/Aquarium/AquariumFood.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class AquariumFood : Item - { - [Constructible] - public AquariumFood() : base(0xEFC) - { - } - - public AquariumFood(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074819; // Aquarium food - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AquariumFood : Item + { + [Constructible] + public AquariumFood() : base(0xEFC) + { + } + + public AquariumFood(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074819; // Aquarium food + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/AquariumGump.cs b/Projects/UOContent/Items/Aquarium/AquariumGump.cs index 5f5d636f5..2d267c63b 100644 --- a/Projects/UOContent/Items/Aquarium/AquariumGump.cs +++ b/Projects/UOContent/Items/Aquarium/AquariumGump.cs @@ -1,89 +1,89 @@ -using Server.Gumps; -using Server.Network; - -namespace Server.Items -{ - public class AquariumGump : Gump - { - private readonly Aquarium m_Aquarium; - - public AquariumGump(Aquarium aquarium, bool edit) : base(100, 100) - { - m_Aquarium = aquarium; - - Closable = true; - Disposable = true; - Draggable = true; - Resizable = false; - - AddPage(0); - AddBackground(0, 0, 350, 323, 0xE10); - AddImage(0, 0, 0x2C96); - - if (m_Aquarium.Items.Count == 0) - return; - - for (int i = 1; i <= m_Aquarium.Items.Count; i++) - DisplayPage(i, edit); - } - - public void DisplayPage(int page, bool edit) - { - AddPage(page); - - Item item = m_Aquarium.Items[page - 1]; - - // item name - if (item.LabelNumber != 0) - AddHtmlLocalized(20, 217, 250, 20, item.LabelNumber, 0xFFFFFF); // Name - - // item details - if (item is BaseFish fish) - AddHtmlLocalized(20, 239, 315, 20, fish.GetDescription(), 0xFFFFFF); - else - AddHtmlLocalized(20, 239, 315, 20, 1073634, 0xFFFFFF); // An aquarium decoration - - // item image - AddItem(150, 80, item.ItemID, item.Hue); - - // item number / all items - AddHtml(20, 195, 250, 20, $"{page}/{m_Aquarium.Items.Count}"); - - // remove item - if (edit) - { - AddBackground(230, 195, 100, 26, 0x13BE); - AddButton(235, 200, 0x845, 0x846, page); - AddHtmlLocalized(260, 198, 60, 26, 1073838, 0x0); // Remove - } - - // next page - if (page < m_Aquarium.Items.Count) - { - AddButton(195, 280, 0xFA5, 0xFA7, 0, GumpButtonType.Page, page + 1); - AddHtmlLocalized(230, 283, 100, 18, 1044045, 0xFFFFFF); // NEXT PAGE - } - - // previous page - if (page > 1) - { - AddButton(45, 280, 0xFAE, 0xFAF, 0, GumpButtonType.Page, page - 1); - AddHtmlLocalized(80, 283, 100, 18, 1044044, 0xFFFFFF); // PREV PAGE - } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Aquarium?.Deleted != false) - return; - - bool edit = m_Aquarium.HasAccess(sender.Mobile); - - if (info.ButtonID > 0 && info.ButtonID <= m_Aquarium.Items.Count && edit) - m_Aquarium.RemoveItem(sender.Mobile, info.ButtonID - 1); - - if (info.ButtonID > 0) - sender.Mobile.SendGump(new AquariumGump(m_Aquarium, edit)); - } - } -} +using Server.Gumps; +using Server.Network; + +namespace Server.Items +{ + public class AquariumGump : Gump + { + private readonly Aquarium m_Aquarium; + + public AquariumGump(Aquarium aquarium, bool edit) : base(100, 100) + { + m_Aquarium = aquarium; + + Closable = true; + Disposable = true; + Draggable = true; + Resizable = false; + + AddPage(0); + AddBackground(0, 0, 350, 323, 0xE10); + AddImage(0, 0, 0x2C96); + + if (m_Aquarium.Items.Count == 0) + return; + + for (var i = 1; i <= m_Aquarium.Items.Count; i++) + DisplayPage(i, edit); + } + + public void DisplayPage(int page, bool edit) + { + AddPage(page); + + var item = m_Aquarium.Items[page - 1]; + + // item name + if (item.LabelNumber != 0) + AddHtmlLocalized(20, 217, 250, 20, item.LabelNumber, 0xFFFFFF); // Name + + // item details + if (item is BaseFish fish) + AddHtmlLocalized(20, 239, 315, 20, fish.GetDescription(), 0xFFFFFF); + else + AddHtmlLocalized(20, 239, 315, 20, 1073634, 0xFFFFFF); // An aquarium decoration + + // item image + AddItem(150, 80, item.ItemID, item.Hue); + + // item number / all items + AddHtml(20, 195, 250, 20, $"{page}/{m_Aquarium.Items.Count}"); + + // remove item + if (edit) + { + AddBackground(230, 195, 100, 26, 0x13BE); + AddButton(235, 200, 0x845, 0x846, page); + AddHtmlLocalized(260, 198, 60, 26, 1073838, 0x0); // Remove + } + + // next page + if (page < m_Aquarium.Items.Count) + { + AddButton(195, 280, 0xFA5, 0xFA7, 0, GumpButtonType.Page, page + 1); + AddHtmlLocalized(230, 283, 100, 18, 1044045, 0xFFFFFF); // NEXT PAGE + } + + // previous page + if (page > 1) + { + AddButton(45, 280, 0xFAE, 0xFAF, 0, GumpButtonType.Page, page - 1); + AddHtmlLocalized(80, 283, 100, 18, 1044044, 0xFFFFFF); // PREV PAGE + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Aquarium?.Deleted != false) + return; + + var edit = m_Aquarium.HasAccess(sender.Mobile); + + if (info.ButtonID > 0 && info.ButtonID <= m_Aquarium.Items.Count && edit) + m_Aquarium.RemoveItem(sender.Mobile, info.ButtonID - 1); + + if (info.ButtonID > 0) + sender.Mobile.SendGump(new AquariumGump(m_Aquarium, edit)); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/AquariumState.cs b/Projects/UOContent/Items/Aquarium/AquariumState.cs index 5204d9d9a..12eb83fc7 100644 --- a/Projects/UOContent/Items/Aquarium/AquariumState.cs +++ b/Projects/UOContent/Items/Aquarium/AquariumState.cs @@ -1,66 +1,66 @@ -using System; - -namespace Server.Items -{ - public enum WaterState - { - Dead, - Dying, - Unhealthy, - Healthy, - Strong - } - - public enum FoodState - { - Dead, - Starving, - Hungry, - Full, - Overfed - } - - [PropertyObject] - public class AquariumState - { - private int m_State; - - [CommandProperty(AccessLevel.GameMaster)] - public int State - { - get => m_State; - set => m_State = Math.Clamp(value, 0, 4); - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Maintain { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Improve { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Added { get; set; } - - public override string ToString() => "..."; - - public virtual void Serialize(IGenericWriter writer) - { - writer.Write(0); // version - - writer.Write(m_State); - writer.Write(Maintain); - writer.Write(Improve); - writer.Write(Added); - } - - public virtual void Deserialize(IGenericReader reader) - { - int version = reader.ReadInt(); - - m_State = reader.ReadInt(); - Maintain = reader.ReadInt(); - Improve = reader.ReadInt(); - Added = reader.ReadInt(); - } - } -} +using System; + +namespace Server.Items +{ + public enum WaterState + { + Dead, + Dying, + Unhealthy, + Healthy, + Strong + } + + public enum FoodState + { + Dead, + Starving, + Hungry, + Full, + Overfed + } + + [PropertyObject] + public class AquariumState + { + private int m_State; + + [CommandProperty(AccessLevel.GameMaster)] + public int State + { + get => m_State; + set => m_State = Math.Clamp(value, 0, 4); + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Maintain { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Improve { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Added { get; set; } + + public override string ToString() => "..."; + + public virtual void Serialize(IGenericWriter writer) + { + writer.Write(0); // version + + writer.Write(m_State); + writer.Write(Maintain); + writer.Write(Improve); + writer.Write(Added); + } + + public virtual void Deserialize(IGenericReader reader) + { + var version = reader.ReadInt(); + + m_State = reader.ReadInt(); + Maintain = reader.ReadInt(); + Improve = reader.ReadInt(); + Added = reader.ReadInt(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/BaseFish.cs b/Projects/UOContent/Items/Aquarium/BaseFish.cs index d50fd5c7b..1ab92eabe 100644 --- a/Projects/UOContent/Items/Aquarium/BaseFish.cs +++ b/Projects/UOContent/Items/Aquarium/BaseFish.cs @@ -1,93 +1,93 @@ -using System; - -namespace Server.Items -{ - public class BaseFish : Item - { - private static readonly TimeSpan DeathDelay = TimeSpan.FromMinutes(5); - - private Timer m_Timer; - - [Constructible] - public BaseFish(int itemID) : base(itemID) - { - StartTimer(); - } - - public BaseFish(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Dead => ItemID == 0x3B0C; - - public virtual void StartTimer() - { - m_Timer?.Stop(); - - m_Timer = Timer.DelayCall(DeathDelay, Kill); - - InvalidateProperties(); - } - - public virtual void StopTimer() - { - m_Timer?.Stop(); - - m_Timer = null; - - InvalidateProperties(); - } - - public override void OnDelete() - { - StopTimer(); - } - - public virtual void Kill() - { - ItemID = 0x3B0C; - StopTimer(); - - InvalidateProperties(); - } - - public int GetDescription() - { - // TODO: This will never return "very unusual dead aquarium creature" due to the way it is killed - if (ItemID > 0x3B0F) - return Dead ? 1074424 : 1074422; // A very unusual [dead/live] aquarium creature - if (Hue != 0) - return Dead ? 1074425 : 1074423; // A [dead/live] aquarium creature of unusual color - - return Dead ? 1073623 : 1073622; // A [dead/live] aquarium creature - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(GetDescription()); - - if (!Dead && m_Timer != null) - list.Add(1074507); // Gasping for air - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (!(Parent is Aquarium) && !(Parent is FishBowl)) - StartTimer(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class BaseFish : Item + { + private static readonly TimeSpan DeathDelay = TimeSpan.FromMinutes(5); + + private Timer m_Timer; + + [Constructible] + public BaseFish(int itemID) : base(itemID) + { + StartTimer(); + } + + public BaseFish(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Dead => ItemID == 0x3B0C; + + public virtual void StartTimer() + { + m_Timer?.Stop(); + + m_Timer = Timer.DelayCall(DeathDelay, Kill); + + InvalidateProperties(); + } + + public virtual void StopTimer() + { + m_Timer?.Stop(); + + m_Timer = null; + + InvalidateProperties(); + } + + public override void OnDelete() + { + StopTimer(); + } + + public virtual void Kill() + { + ItemID = 0x3B0C; + StopTimer(); + + InvalidateProperties(); + } + + public int GetDescription() + { + // TODO: This will never return "very unusual dead aquarium creature" due to the way it is killed + if (ItemID > 0x3B0F) + return Dead ? 1074424 : 1074422; // A very unusual [dead/live] aquarium creature + if (Hue != 0) + return Dead ? 1074425 : 1074423; // A [dead/live] aquarium creature of unusual color + + return Dead ? 1073623 : 1073622; // A [dead/live] aquarium creature + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(GetDescription()); + + if (!Dead && m_Timer != null) + list.Add(1074507); // Gasping for air + } + + 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 (!(Parent is Aquarium) && !(Parent is FishBowl)) + StartTimer(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Fish/AlbinoCourtesanFish.cs b/Projects/UOContent/Items/Aquarium/Fish/AlbinoCourtesanFish.cs index 536874026..3feb3ccdb 100644 --- a/Projects/UOContent/Items/Aquarium/Fish/AlbinoCourtesanFish.cs +++ b/Projects/UOContent/Items/Aquarium/Fish/AlbinoCourtesanFish.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class AlbinoCourtesanFish : BaseFish - { - [Constructible] - public AlbinoCourtesanFish() : base(0x3B04) - { - } - - public AlbinoCourtesanFish(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074592; // Albino Courtesan Fish - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AlbinoCourtesanFish : BaseFish + { + [Constructible] + public AlbinoCourtesanFish() : base(0x3B04) + { + } + + public AlbinoCourtesanFish(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074592; // Albino Courtesan Fish + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Fish/AlbinoFrog.cs b/Projects/UOContent/Items/Aquarium/Fish/AlbinoFrog.cs index e9223491f..84e6d140e 100644 --- a/Projects/UOContent/Items/Aquarium/Fish/AlbinoFrog.cs +++ b/Projects/UOContent/Items/Aquarium/Fish/AlbinoFrog.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class AlbinoFrog : BaseFish - { - [Constructible] - public AlbinoFrog() : base(0x3B0D) => Hue = 0x47E; - - public AlbinoFrog(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073824; // An Albino Frog - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AlbinoFrog : BaseFish + { + [Constructible] + public AlbinoFrog() : base(0x3B0D) => Hue = 0x47E; + + public AlbinoFrog(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073824; // An Albino Frog + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Fish/BritainCrownFish.cs b/Projects/UOContent/Items/Aquarium/Fish/BritainCrownFish.cs index 2f331fa7d..015165316 100644 --- a/Projects/UOContent/Items/Aquarium/Fish/BritainCrownFish.cs +++ b/Projects/UOContent/Items/Aquarium/Fish/BritainCrownFish.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class BritainCrownFish : BaseFish - { - [Constructible] - public BritainCrownFish() : base(0x3AFF) - { - } - - public BritainCrownFish(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074589; // Britain Crown Fish - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class BritainCrownFish : BaseFish + { + [Constructible] + public BritainCrownFish() : base(0x3AFF) + { + } + + public BritainCrownFish(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074589; // Britain Crown Fish + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Fish/FandancerFish.cs b/Projects/UOContent/Items/Aquarium/Fish/FandancerFish.cs index fc9876dea..c70e61812 100644 --- a/Projects/UOContent/Items/Aquarium/Fish/FandancerFish.cs +++ b/Projects/UOContent/Items/Aquarium/Fish/FandancerFish.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class FandancerFish : BaseFish - { - [Constructible] - public FandancerFish() : base(0x3B02) - { - } - - public FandancerFish(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074591; // Fandancer Fish - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FandancerFish : BaseFish + { + [Constructible] + public FandancerFish() : base(0x3B02) + { + } + + public FandancerFish(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074591; // Fandancer Fish + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Fish/GoldenBroadtail.cs b/Projects/UOContent/Items/Aquarium/Fish/GoldenBroadtail.cs index 60de6824b..96000bc23 100644 --- a/Projects/UOContent/Items/Aquarium/Fish/GoldenBroadtail.cs +++ b/Projects/UOContent/Items/Aquarium/Fish/GoldenBroadtail.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class GoldenBroadtail : BaseFish - { - [Constructible] - public GoldenBroadtail() : base(0x3B03) - { - } - - public GoldenBroadtail(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073828; // A Golden Broadtail - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class GoldenBroadtail : BaseFish + { + [Constructible] + public GoldenBroadtail() : base(0x3B03) + { + } + + public GoldenBroadtail(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073828; // A Golden Broadtail + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Fish/Jellyfish.cs b/Projects/UOContent/Items/Aquarium/Fish/Jellyfish.cs index 87bca63c7..067df5415 100644 --- a/Projects/UOContent/Items/Aquarium/Fish/Jellyfish.cs +++ b/Projects/UOContent/Items/Aquarium/Fish/Jellyfish.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class Jellyfish : BaseFish - { - [Constructible] - public Jellyfish() : base(0x3B0E) - { - } - - public Jellyfish(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074593; // Jellyfish - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Jellyfish : BaseFish + { + [Constructible] + public Jellyfish() : base(0x3B0E) + { + } + + public Jellyfish(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074593; // Jellyfish + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Fish/KillerFrog.cs b/Projects/UOContent/Items/Aquarium/Fish/KillerFrog.cs index d9c4b2ef1..a8a09d398 100644 --- a/Projects/UOContent/Items/Aquarium/Fish/KillerFrog.cs +++ b/Projects/UOContent/Items/Aquarium/Fish/KillerFrog.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class KillerFrog : BaseFish - { - [Constructible] - public KillerFrog() : base(0x3B0D) - { - } - - public KillerFrog(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073825; // A Killer Frog - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class KillerFrog : BaseFish + { + [Constructible] + public KillerFrog() : base(0x3B0D) + { + } + + public KillerFrog(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073825; // A Killer Frog + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Fish/LongClawCrab.cs b/Projects/UOContent/Items/Aquarium/Fish/LongClawCrab.cs index d5185bfaa..3601eec77 100644 --- a/Projects/UOContent/Items/Aquarium/Fish/LongClawCrab.cs +++ b/Projects/UOContent/Items/Aquarium/Fish/LongClawCrab.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class LongClawCrab : BaseFish - { - [Constructible] - public LongClawCrab() : base(0x3AFC) => Hue = 0x527; - - public LongClawCrab(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073827; // A Long Claw Crab - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LongClawCrab : BaseFish + { + [Constructible] + public LongClawCrab() : base(0x3AFC) => Hue = 0x527; + + public LongClawCrab(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073827; // A Long Claw Crab + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Fish/MakotoCourtesanFish.cs b/Projects/UOContent/Items/Aquarium/Fish/MakotoCourtesanFish.cs index d4f7ce13b..5cad6b22b 100644 --- a/Projects/UOContent/Items/Aquarium/Fish/MakotoCourtesanFish.cs +++ b/Projects/UOContent/Items/Aquarium/Fish/MakotoCourtesanFish.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class MakotoCourtesanFish : BaseFish - { - [Constructible] - public MakotoCourtesanFish() : base(0x3AFD) - { - } - - public MakotoCourtesanFish(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073835; // A Makoto Courtesan Fish - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class MakotoCourtesanFish : BaseFish + { + [Constructible] + public MakotoCourtesanFish() : base(0x3AFD) + { + } + + public MakotoCourtesanFish(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073835; // A Makoto Courtesan Fish + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Fish/MinocBlueFish.cs b/Projects/UOContent/Items/Aquarium/Fish/MinocBlueFish.cs index 069195093..b1bdd5675 100644 --- a/Projects/UOContent/Items/Aquarium/Fish/MinocBlueFish.cs +++ b/Projects/UOContent/Items/Aquarium/Fish/MinocBlueFish.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class MinocBlueFish : BaseFish - { - [Constructible] - public MinocBlueFish() : base(0x3AFE) - { - } - - public MinocBlueFish(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073829; // A Minoc Blue Fish - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class MinocBlueFish : BaseFish + { + [Constructible] + public MinocBlueFish() : base(0x3AFE) + { + } + + public MinocBlueFish(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073829; // A Minoc Blue Fish + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Fish/NujelmHoneyFish.cs b/Projects/UOContent/Items/Aquarium/Fish/NujelmHoneyFish.cs index cb89b314e..5750f822f 100644 --- a/Projects/UOContent/Items/Aquarium/Fish/NujelmHoneyFish.cs +++ b/Projects/UOContent/Items/Aquarium/Fish/NujelmHoneyFish.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class NujelmHoneyFish : BaseFish - { - [Constructible] - public NujelmHoneyFish() : base(0x3B06) - { - } - - public NujelmHoneyFish(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073830; // A Nujel'm Honey Fish - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class NujelmHoneyFish : BaseFish + { + [Constructible] + public NujelmHoneyFish() : base(0x3B06) + { + } + + public NujelmHoneyFish(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073830; // A Nujel'm Honey Fish + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Fish/PurpleFrog.cs b/Projects/UOContent/Items/Aquarium/Fish/PurpleFrog.cs index e8e193015..1657eee41 100644 --- a/Projects/UOContent/Items/Aquarium/Fish/PurpleFrog.cs +++ b/Projects/UOContent/Items/Aquarium/Fish/PurpleFrog.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class PurpleFrog : BaseFish - { - [Constructible] - public PurpleFrog() : base(0x3B0D) => Hue = 0x4FA; - - public PurpleFrog(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073823; // A Purple Frog - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PurpleFrog : BaseFish + { + [Constructible] + public PurpleFrog() : base(0x3B0D) => Hue = 0x4FA; + + public PurpleFrog(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073823; // A Purple Frog + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Fish/RedDartFish.cs b/Projects/UOContent/Items/Aquarium/Fish/RedDartFish.cs index 480d6701f..284cf4f2f 100644 --- a/Projects/UOContent/Items/Aquarium/Fish/RedDartFish.cs +++ b/Projects/UOContent/Items/Aquarium/Fish/RedDartFish.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class RedDartFish : BaseFish - { - [Constructible] - public RedDartFish() : base(0x3B00) - { - } - - public RedDartFish(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073834; // A Red Dart Fish - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class RedDartFish : BaseFish + { + [Constructible] + public RedDartFish() : base(0x3B00) + { + } + + public RedDartFish(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073834; // A Red Dart Fish + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Fish/Shrimp.cs b/Projects/UOContent/Items/Aquarium/Fish/Shrimp.cs index a4dcd69a7..f1ae5bb45 100644 --- a/Projects/UOContent/Items/Aquarium/Fish/Shrimp.cs +++ b/Projects/UOContent/Items/Aquarium/Fish/Shrimp.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class Shrimp : BaseFish - { - [Constructible] - public Shrimp() : base(0x3B14) - { - } - - public Shrimp(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074596; // Shrimp - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Shrimp : BaseFish + { + [Constructible] + public Shrimp() : base(0x3B14) + { + } + + public Shrimp(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074596; // Shrimp + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Fish/SmallMouthSuckerFin.cs b/Projects/UOContent/Items/Aquarium/Fish/SmallMouthSuckerFin.cs index d83583c16..48a230a5e 100644 --- a/Projects/UOContent/Items/Aquarium/Fish/SmallMouthSuckerFin.cs +++ b/Projects/UOContent/Items/Aquarium/Fish/SmallMouthSuckerFin.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class SmallMouthSuckerFin : BaseFish - { - [Constructible] - public SmallMouthSuckerFin() : base(0x3B01) - { - } - - public SmallMouthSuckerFin(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074590; // Small Mouth Sucker Fin - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SmallMouthSuckerFin : BaseFish + { + [Constructible] + public SmallMouthSuckerFin() : base(0x3B01) + { + } + + public SmallMouthSuckerFin(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074590; // Small Mouth Sucker Fin + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Fish/SpeckledCrab.cs b/Projects/UOContent/Items/Aquarium/Fish/SpeckledCrab.cs index fd273e5c4..8914dcd15 100644 --- a/Projects/UOContent/Items/Aquarium/Fish/SpeckledCrab.cs +++ b/Projects/UOContent/Items/Aquarium/Fish/SpeckledCrab.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class SpeckledCrab : BaseFish - { - [Constructible] - public SpeckledCrab() : base(0x3AFC) - { - } - - public SpeckledCrab(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073826; // A Speckled Crab - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SpeckledCrab : BaseFish + { + [Constructible] + public SpeckledCrab() : base(0x3AFC) + { + } + + public SpeckledCrab(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073826; // A Speckled Crab + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Fish/SpinedScratcherFish.cs b/Projects/UOContent/Items/Aquarium/Fish/SpinedScratcherFish.cs index 03c0142c3..83dfe5311 100644 --- a/Projects/UOContent/Items/Aquarium/Fish/SpinedScratcherFish.cs +++ b/Projects/UOContent/Items/Aquarium/Fish/SpinedScratcherFish.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class SpinedScratcherFish : BaseFish - { - [Constructible] - public SpinedScratcherFish() : base(0x3B05) - { - } - - public SpinedScratcherFish(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073832; // A Spined Scratcher Fish - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SpinedScratcherFish : BaseFish + { + [Constructible] + public SpinedScratcherFish() : base(0x3B05) + { + } + + public SpinedScratcherFish(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073832; // A Spined Scratcher Fish + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Fish/SpottedBuccaneer.cs b/Projects/UOContent/Items/Aquarium/Fish/SpottedBuccaneer.cs index 11e3e61b8..ec36623fb 100644 --- a/Projects/UOContent/Items/Aquarium/Fish/SpottedBuccaneer.cs +++ b/Projects/UOContent/Items/Aquarium/Fish/SpottedBuccaneer.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class SpottedBuccaneer : BaseFish - { - [Constructible] - public SpottedBuccaneer() : base(0x3B09) - { - } - - public SpottedBuccaneer(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073833; // A Spotted Buccaneer - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SpottedBuccaneer : BaseFish + { + [Constructible] + public SpottedBuccaneer() : base(0x3B09) + { + } + + public SpottedBuccaneer(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073833; // A Spotted Buccaneer + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Fish/VesperReefTiger.cs b/Projects/UOContent/Items/Aquarium/Fish/VesperReefTiger.cs index 5c8dbe3b7..64656cb1f 100644 --- a/Projects/UOContent/Items/Aquarium/Fish/VesperReefTiger.cs +++ b/Projects/UOContent/Items/Aquarium/Fish/VesperReefTiger.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class VesperReefTiger : BaseFish - { - [Constructible] - public VesperReefTiger() : base(0x3B08) - { - } - - public VesperReefTiger(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073836; // A Vesper Reef Tiger - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class VesperReefTiger : BaseFish + { + [Constructible] + public VesperReefTiger() : base(0x3B08) + { + } + + public VesperReefTiger(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073836; // A Vesper Reef Tiger + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Fish/YellowFinBluebelly.cs b/Projects/UOContent/Items/Aquarium/Fish/YellowFinBluebelly.cs index 7d7ca366f..e54dccdc0 100644 --- a/Projects/UOContent/Items/Aquarium/Fish/YellowFinBluebelly.cs +++ b/Projects/UOContent/Items/Aquarium/Fish/YellowFinBluebelly.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class YellowFinBluebelly : BaseFish - { - [Constructible] - public YellowFinBluebelly() : base(0x3B07) - { - } - - public YellowFinBluebelly(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073831; // A Yellow Fin Bluebelly - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class YellowFinBluebelly : BaseFish + { + [Constructible] + public YellowFinBluebelly() : base(0x3B07) + { + } + + public YellowFinBluebelly(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073831; // A Yellow Fin Bluebelly + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/FishBowl.cs b/Projects/UOContent/Items/Aquarium/FishBowl.cs index 91166d253..51442eade 100644 --- a/Projects/UOContent/Items/Aquarium/FishBowl.cs +++ b/Projects/UOContent/Items/Aquarium/FishBowl.cs @@ -1,169 +1,169 @@ -using System.Collections.Generic; -using Server.ContextMenus; -using Server.Network; - -namespace Server.Items -{ - public class FishBowl : BaseContainer - { - [Constructible] - public FishBowl() : base(0x241C) - { - Hue = 0x47E; - MaxItems = 1; - } - - public FishBowl(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074499; // A fish bowl - - [CommandProperty(AccessLevel.GameMaster)] - public bool Empty => Items.Count == 0; - - [CommandProperty(AccessLevel.GameMaster)] - public BaseFish Fish - { - get - { - if (Empty) - return null; - - return Items[0] as BaseFish; - } - } - - public override double DefaultWeight => 2.0; - - public override void OnDoubleClick(Mobile from) - { - } - - public override bool TryDropItem(Mobile from, Item dropped, bool sendFullMessage) - { - if (!CheckHold(from, dropped, sendFullMessage, true)) - return false; - - DropItem(dropped); - return true; - } - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (!IsAccessibleTo(from)) - { - from.SendLocalizedMessage(502436); // That is not accessible. - return false; - } - - if (!(dropped is BaseFish)) - { - from.SendLocalizedMessage(1074836); // The container can not hold that type of object. - return false; - } - - if (base.OnDragDrop(from, dropped)) - { - ((BaseFish)dropped).StopTimer(); - InvalidateProperties(); - - return true; - } - - return false; - } - - public override bool CheckItemUse(Mobile from, Item item) - { - if (item != this) - return false; - - return base.CheckItemUse(from, item); - } - - public override bool CheckLift(Mobile from, Item item, ref LRReason reject) - { - if (item != this) - { - reject = LRReason.CannotLift; - return false; - } - - return base.CheckLift(from, item, ref reject); - } - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - if (!Empty) - { - BaseFish fish = Fish; - - if (fish != null) - list.Add(1074494, "#{0}", fish.LabelNumber); // Contains: ~1_CREATURE~ - } - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (!Empty && IsAccessibleTo(from)) - list.Add(new RemoveCreature(this)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version == 0) - Weight = DefaultWeight; - } - - private class RemoveCreature : ContextMenuEntry - { - private readonly FishBowl m_Bowl; - - public RemoveCreature(FishBowl bowl) : base(6242, 3) // Remove creature - => - m_Bowl = bowl; - - public override void OnClick() - { - if (m_Bowl?.Deleted != false || !m_Bowl.IsAccessibleTo(Owner.From)) - return; - - BaseFish fish = m_Bowl.Fish; - - if (fish == null) - return; - - if (fish.IsLockedDown) // for legacy fish bowls - { - Owner.From.SendLocalizedMessage(1010449); // You may not use this object while it is locked down. - } - else if (!Owner.From.PlaceInBackpack(fish)) - { - Owner.From.SendLocalizedMessage(1074496); // There is no room in your pack for the creature. - } - else - { - Owner.From.SendLocalizedMessage(1074495); // The creature has been removed from the fish bowl. - fish.StartTimer(); - m_Bowl.InvalidateProperties(); - } - } - } - } -} +using System.Collections.Generic; +using Server.ContextMenus; +using Server.Network; + +namespace Server.Items +{ + public class FishBowl : BaseContainer + { + [Constructible] + public FishBowl() : base(0x241C) + { + Hue = 0x47E; + MaxItems = 1; + } + + public FishBowl(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074499; // A fish bowl + + [CommandProperty(AccessLevel.GameMaster)] + public bool Empty => Items.Count == 0; + + [CommandProperty(AccessLevel.GameMaster)] + public BaseFish Fish + { + get + { + if (Empty) + return null; + + return Items[0] as BaseFish; + } + } + + public override double DefaultWeight => 2.0; + + public override void OnDoubleClick(Mobile from) + { + } + + public override bool TryDropItem(Mobile from, Item dropped, bool sendFullMessage) + { + if (!CheckHold(from, dropped, sendFullMessage, true)) + return false; + + DropItem(dropped); + return true; + } + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (!IsAccessibleTo(from)) + { + from.SendLocalizedMessage(502436); // That is not accessible. + return false; + } + + if (!(dropped is BaseFish)) + { + from.SendLocalizedMessage(1074836); // The container can not hold that type of object. + return false; + } + + if (base.OnDragDrop(from, dropped)) + { + ((BaseFish)dropped).StopTimer(); + InvalidateProperties(); + + return true; + } + + return false; + } + + public override bool CheckItemUse(Mobile from, Item item) + { + if (item != this) + return false; + + return base.CheckItemUse(from, item); + } + + public override bool CheckLift(Mobile from, Item item, ref LRReason reject) + { + if (item != this) + { + reject = LRReason.CannotLift; + return false; + } + + return base.CheckLift(from, item, ref reject); + } + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + if (!Empty) + { + var fish = Fish; + + if (fish != null) + list.Add(1074494, "#{0}", fish.LabelNumber); // Contains: ~1_CREATURE~ + } + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (!Empty && IsAccessibleTo(from)) + list.Add(new RemoveCreature(this)); + } + + 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 = DefaultWeight; + } + + private class RemoveCreature : ContextMenuEntry + { + private readonly FishBowl m_Bowl; + + public RemoveCreature(FishBowl bowl) : base(6242, 3) // Remove creature + => + m_Bowl = bowl; + + public override void OnClick() + { + if (m_Bowl?.Deleted != false || !m_Bowl.IsAccessibleTo(Owner.From)) + return; + + var fish = m_Bowl.Fish; + + if (fish == null) + return; + + if (fish.IsLockedDown) // for legacy fish bowls + { + Owner.From.SendLocalizedMessage(1010449); // You may not use this object while it is locked down. + } + else if (!Owner.From.PlaceInBackpack(fish)) + { + Owner.From.SendLocalizedMessage(1074496); // There is no room in your pack for the creature. + } + else + { + Owner.From.SendLocalizedMessage(1074495); // The creature has been removed from the fish bowl. + fish.StartTimer(); + m_Bowl.InvalidateProperties(); + } + } + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Reward Fish/BrineShrimp.cs b/Projects/UOContent/Items/Aquarium/Reward Fish/BrineShrimp.cs index e00e08d34..9660945f2 100644 --- a/Projects/UOContent/Items/Aquarium/Reward Fish/BrineShrimp.cs +++ b/Projects/UOContent/Items/Aquarium/Reward Fish/BrineShrimp.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class BrineShrimp : BaseFish - { - [Constructible] - public BrineShrimp() : base(0x3B11) - { - } - - public BrineShrimp(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074415; // Brine shrimp - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class BrineShrimp : BaseFish + { + [Constructible] + public BrineShrimp() : base(0x3B11) + { + } + + public BrineShrimp(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074415; // Brine shrimp + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Reward Fish/Coral.cs b/Projects/UOContent/Items/Aquarium/Reward Fish/Coral.cs index 76d8b0495..fded9feba 100644 --- a/Projects/UOContent/Items/Aquarium/Reward Fish/Coral.cs +++ b/Projects/UOContent/Items/Aquarium/Reward Fish/Coral.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class Coral : BaseFish - { - [Constructible] - public Coral() : base(Utility.RandomList(0x3AF9, 0x3AFA, 0x3AFB)) - { - } - - public Coral(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074588; // Coral - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Coral : BaseFish + { + [Constructible] + public Coral() : base(Utility.RandomList(0x3AF9, 0x3AFA, 0x3AFB)) + { + } + + public Coral(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074588; // Coral + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Reward Fish/FullMoonFish.cs b/Projects/UOContent/Items/Aquarium/Reward Fish/FullMoonFish.cs index 790613f81..120143c44 100644 --- a/Projects/UOContent/Items/Aquarium/Reward Fish/FullMoonFish.cs +++ b/Projects/UOContent/Items/Aquarium/Reward Fish/FullMoonFish.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class FullMoonFish : BaseFish - { - [Constructible] - public FullMoonFish() : base(0x3B15) - { - } - - public FullMoonFish(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074597; // A Full Moon Fish - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FullMoonFish : BaseFish + { + [Constructible] + public FullMoonFish() : base(0x3B15) + { + } + + public FullMoonFish(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074597; // A Full Moon Fish + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Reward Fish/SeaHorse.cs b/Projects/UOContent/Items/Aquarium/Reward Fish/SeaHorse.cs index bc0b76607..4951ad2f3 100644 --- a/Projects/UOContent/Items/Aquarium/Reward Fish/SeaHorse.cs +++ b/Projects/UOContent/Items/Aquarium/Reward Fish/SeaHorse.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class SeaHorseFish : BaseFish - { - [Constructible] - public SeaHorseFish() : base(0x3B10) - { - } - - public SeaHorseFish(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074414; // A sea horse - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SeaHorseFish : BaseFish + { + [Constructible] + public SeaHorseFish() : base(0x3B10) + { + } + + public SeaHorseFish(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074414; // A sea horse + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Reward Fish/StrippedFlakeFish.cs b/Projects/UOContent/Items/Aquarium/Reward Fish/StrippedFlakeFish.cs index 9774bc84d..38c121876 100644 --- a/Projects/UOContent/Items/Aquarium/Reward Fish/StrippedFlakeFish.cs +++ b/Projects/UOContent/Items/Aquarium/Reward Fish/StrippedFlakeFish.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class StrippedFlakeFish : BaseFish - { - [Constructible] - public StrippedFlakeFish() : base(0x3B0A) - { - } - - public StrippedFlakeFish(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074595; // Stripped Flake Fish - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class StrippedFlakeFish : BaseFish + { + [Constructible] + public StrippedFlakeFish() : base(0x3B0A) + { + } + + public StrippedFlakeFish(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074595; // Stripped Flake Fish + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Reward Fish/StrippedSosarianSwill.cs b/Projects/UOContent/Items/Aquarium/Reward Fish/StrippedSosarianSwill.cs index a26064fd4..5dfebf7c9 100644 --- a/Projects/UOContent/Items/Aquarium/Reward Fish/StrippedSosarianSwill.cs +++ b/Projects/UOContent/Items/Aquarium/Reward Fish/StrippedSosarianSwill.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class StrippedSosarianSwill : BaseFish - { - [Constructible] - public StrippedSosarianSwill() : base(0x3B0A) - { - } - - public StrippedSosarianSwill(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074594; // Stripped Sosarian Swill - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class StrippedSosarianSwill : BaseFish + { + [Constructible] + public StrippedSosarianSwill() : base(0x3B0A) + { + } + + public StrippedSosarianSwill(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074594; // Stripped Sosarian Swill + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Rewards/AquariumMessage.cs b/Projects/UOContent/Items/Aquarium/Rewards/AquariumMessage.cs index aa170d526..190241649 100644 --- a/Projects/UOContent/Items/Aquarium/Rewards/AquariumMessage.cs +++ b/Projects/UOContent/Items/Aquarium/Rewards/AquariumMessage.cs @@ -1,37 +1,37 @@ -namespace Server.Items -{ - public class AquariumMessage : MessageInABottle - { - [Constructible] - public AquariumMessage() - { - } - - public AquariumMessage(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073894; // Message in a Bottle - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - list.Add(1073634); // An aquarium decoration - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AquariumMessage : MessageInABottle + { + [Constructible] + public AquariumMessage() + { + } + + public AquariumMessage(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073894; // Message in a Bottle + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + list.Add(1073634); // An aquarium decoration + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Rewards/CaptainBlackheartsFishingPole.cs b/Projects/UOContent/Items/Aquarium/Rewards/CaptainBlackheartsFishingPole.cs index 23c7cdbd6..83aa59c29 100644 --- a/Projects/UOContent/Items/Aquarium/Rewards/CaptainBlackheartsFishingPole.cs +++ b/Projects/UOContent/Items/Aquarium/Rewards/CaptainBlackheartsFishingPole.cs @@ -1,37 +1,37 @@ -namespace Server.Items -{ - public class CaptainBlackheartsFishingPole : FishingPole - { - [Constructible] - public CaptainBlackheartsFishingPole() - { - } - - public CaptainBlackheartsFishingPole(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074571; // Captain Blackheart's Fishing Pole - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - list.Add(1073634); // An aquarium decoration - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class CaptainBlackheartsFishingPole : FishingPole + { + [Constructible] + public CaptainBlackheartsFishingPole() + { + } + + public CaptainBlackheartsFishingPole(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074571; // Captain Blackheart's Fishing Pole + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + list.Add(1073634); // An aquarium decoration + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Rewards/CraftysFishingHat.cs b/Projects/UOContent/Items/Aquarium/Rewards/CraftysFishingHat.cs index 2a5e8e6e2..bf5de0bb5 100644 --- a/Projects/UOContent/Items/Aquarium/Rewards/CraftysFishingHat.cs +++ b/Projects/UOContent/Items/Aquarium/Rewards/CraftysFishingHat.cs @@ -1,46 +1,46 @@ -namespace Server.Items -{ - public class CraftysFishingHat : BaseHat - { - [Constructible] - public CraftysFishingHat() : base(0x1713) - { - } - - public CraftysFishingHat(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074572; // Crafty's Fishing Hat - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 9; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - list.Add(1073634); // An aquarium decoration - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class CraftysFishingHat : BaseHat + { + [Constructible] + public CraftysFishingHat() : base(0x1713) + { + } + + public CraftysFishingHat(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074572; // Crafty's Fishing Hat + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 9; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + list.Add(1073634); // An aquarium decoration + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Rewards/FishBones.cs b/Projects/UOContent/Items/Aquarium/Rewards/FishBones.cs index 937ed30e1..fc9f3ad2a 100644 --- a/Projects/UOContent/Items/Aquarium/Rewards/FishBones.cs +++ b/Projects/UOContent/Items/Aquarium/Rewards/FishBones.cs @@ -1,38 +1,38 @@ -namespace Server.Items -{ - public class FishBones : Item - { - [Constructible] - public FishBones() : base(0x3B0C) - { - } - - public FishBones(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074601; // Fish bones - public override double DefaultWeight => 1.0; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - list.Add(1073634); // An aquarium decoration - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FishBones : Item + { + [Constructible] + public FishBones() : base(0x3B0C) + { + } + + public FishBones(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074601; // Fish bones + public override double DefaultWeight => 1.0; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + list.Add(1073634); // An aquarium decoration + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Rewards/IslandStatue.cs b/Projects/UOContent/Items/Aquarium/Rewards/IslandStatue.cs index 4cb0982df..05fb1c9fc 100644 --- a/Projects/UOContent/Items/Aquarium/Rewards/IslandStatue.cs +++ b/Projects/UOContent/Items/Aquarium/Rewards/IslandStatue.cs @@ -1,38 +1,38 @@ -namespace Server.Items -{ - public class IslandStatue : Item - { - [Constructible] - public IslandStatue() : base(0x3B0F) - { - } - - public IslandStatue(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074600; // An island statue - public override double DefaultWeight => 1.0; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - list.Add(1073634); // An aquarium decoration - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class IslandStatue : Item + { + [Constructible] + public IslandStatue() : base(0x3B0F) + { + } + + public IslandStatue(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074600; // An island statue + public override double DefaultWeight => 1.0; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + list.Add(1073634); // An aquarium decoration + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Rewards/Shell.cs b/Projects/UOContent/Items/Aquarium/Rewards/Shell.cs index 3313e49ff..3852b54a1 100644 --- a/Projects/UOContent/Items/Aquarium/Rewards/Shell.cs +++ b/Projects/UOContent/Items/Aquarium/Rewards/Shell.cs @@ -1,38 +1,38 @@ -namespace Server.Items -{ - public class Shell : Item - { - [Constructible] - public Shell() : base(Utility.RandomList(0x3B12, 0x3B13)) - { - } - - public Shell(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074598; // A shell - public override double DefaultWeight => 1.0; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - list.Add(1073634); // An aquarium decoration - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Shell : Item + { + [Constructible] + public Shell() : base(Utility.RandomList(0x3B12, 0x3B13)) + { + } + + public Shell(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074598; // A shell + public override double DefaultWeight => 1.0; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + list.Add(1073634); // An aquarium decoration + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Rewards/ToyBoat.cs b/Projects/UOContent/Items/Aquarium/Rewards/ToyBoat.cs index f84de3598..2c9192b27 100644 --- a/Projects/UOContent/Items/Aquarium/Rewards/ToyBoat.cs +++ b/Projects/UOContent/Items/Aquarium/Rewards/ToyBoat.cs @@ -1,39 +1,39 @@ -namespace Server.Items -{ - [Flippable(0x14F3, 0x14F4)] - public class ToyBoat : Item - { - [Constructible] - public ToyBoat() : base(0x14F4) - { - } - - public ToyBoat(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074363; // A toy boat - public override double DefaultWeight => 1.0; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - list.Add(1073634); // An aquarium decoration - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x14F3, 0x14F4)] + public class ToyBoat : Item + { + [Constructible] + public ToyBoat() : base(0x14F4) + { + } + + public ToyBoat(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074363; // A toy boat + public override double DefaultWeight => 1.0; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + list.Add(1073634); // An aquarium decoration + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/Rewards/WaterloggedBoots.cs b/Projects/UOContent/Items/Aquarium/Rewards/WaterloggedBoots.cs index 4e376e967..39f954788 100644 --- a/Projects/UOContent/Items/Aquarium/Rewards/WaterloggedBoots.cs +++ b/Projects/UOContent/Items/Aquarium/Rewards/WaterloggedBoots.cs @@ -1,49 +1,49 @@ -namespace Server.Items -{ - public class WaterloggedBoots : BaseShoes - { - [Constructible] - public WaterloggedBoots() : base(0x1711) - { - if (Utility.RandomBool()) - { - // thigh boots - ItemID = 0x1711; - Weight = 4.0; - } - else - { - // boots - ItemID = 0x170B; - Weight = 3.0; - } - } - - public WaterloggedBoots(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074364; // Waterlogged boots - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - list.Add(1073634); // An aquarium decoration - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class WaterloggedBoots : BaseShoes + { + [Constructible] + public WaterloggedBoots() : base(0x1711) + { + if (Utility.RandomBool()) + { + // thigh boots + ItemID = 0x1711; + Weight = 4.0; + } + else + { + // boots + ItemID = 0x170B; + Weight = 3.0; + } + } + + public WaterloggedBoots(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074364; // Waterlogged boots + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + list.Add(1073634); // An aquarium decoration + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Aquarium/VacationWafer.cs b/Projects/UOContent/Items/Aquarium/VacationWafer.cs index 88c216c54..66589123b 100644 --- a/Projects/UOContent/Items/Aquarium/VacationWafer.cs +++ b/Projects/UOContent/Items/Aquarium/VacationWafer.cs @@ -1,42 +1,42 @@ -namespace Server.Items -{ - public class VacationWafer : Item - { - public const int VacationDays = 7; - - [Constructible] - public VacationWafer() : base(0x973) - { - } - - public VacationWafer(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074431; // An aquarium flake sphere - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - list.Add(1074432, VacationDays.ToString()); // Vacation days: ~1_DAYS~ - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1 && ItemID == 0x971) - ItemID = 0x973; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class VacationWafer : Item + { + public const int VacationDays = 7; + + [Constructible] + public VacationWafer() : base(0x973) + { + } + + public VacationWafer(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074431; // An aquarium flake sphere + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + list.Add(1074432, VacationDays.ToString()); // Vacation days: ~1_DAYS~ + } + + 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 < 1 && ItemID == 0x971) + ItemID = 0x973; + } + } +} diff --git a/Projects/UOContent/Items/Armor/ArmorEnums.cs b/Projects/UOContent/Items/Armor/ArmorEnums.cs index b51a89c8b..1ada0ded2 100644 --- a/Projects/UOContent/Items/Armor/ArmorEnums.cs +++ b/Projects/UOContent/Items/Armor/ArmorEnums.cs @@ -1,62 +1,62 @@ -namespace Server.Items -{ - public enum ArmorQuality - { - Low, - Regular, - Exceptional - } - - public enum ArmorDurabilityLevel - { - Regular, - Durable, - Substantial, - Massive, - Fortified, - Indestructible - } - - public enum ArmorProtectionLevel - { - Regular, - Defense, - Guarding, - Hardening, - Fortification, - Invulnerability - } - - public enum ArmorBodyType - { - Gorget, - Gloves, - Helmet, - Arms, - Legs, - Chest, - Shield - } - - public enum ArmorMaterialType - { - Cloth, - Leather, - Studded, - Bone, - Spined, - Horned, - Barbed, - Ringmail, - Chainmail, - Plate, - Dragon // On OSI, Dragon is seen and considered its own type. - } - - public enum ArmorMeditationAllowance - { - All, - Half, - None - } -} \ No newline at end of file +namespace Server.Items +{ + public enum ArmorQuality + { + Low, + Regular, + Exceptional + } + + public enum ArmorDurabilityLevel + { + Regular, + Durable, + Substantial, + Massive, + Fortified, + Indestructible + } + + public enum ArmorProtectionLevel + { + Regular, + Defense, + Guarding, + Hardening, + Fortification, + Invulnerability + } + + public enum ArmorBodyType + { + Gorget, + Gloves, + Helmet, + Arms, + Legs, + Chest, + Shield + } + + public enum ArmorMaterialType + { + Cloth, + Leather, + Studded, + Bone, + Spined, + Horned, + Barbed, + Ringmail, + Chainmail, + Plate, + Dragon // On OSI, Dragon is seen and considered its own type. + } + + public enum ArmorMeditationAllowance + { + All, + Half, + None + } +} diff --git a/Projects/UOContent/Items/Armor/Artifacts/ArmorOfFortune.cs b/Projects/UOContent/Items/Armor/Artifacts/ArmorOfFortune.cs index f56a73cae..cb99131b0 100644 --- a/Projects/UOContent/Items/Armor/Artifacts/ArmorOfFortune.cs +++ b/Projects/UOContent/Items/Armor/Artifacts/ArmorOfFortune.cs @@ -1,39 +1,39 @@ -namespace Server.Items -{ - public class ArmorOfFortune : StuddedChest - { - [Constructible] - public ArmorOfFortune() - { - Hue = 0x501; - Attributes.Luck = 200; - Attributes.DefendChance = 15; - Attributes.LowerRegCost = 40; - ArmorAttributes.MageArmor = 1; - } - - public ArmorOfFortune(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061098; // Armor of Fortune - public override int ArtifactRarity => 11; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ArmorOfFortune : StuddedChest + { + [Constructible] + public ArmorOfFortune() + { + Hue = 0x501; + Attributes.Luck = 200; + Attributes.DefendChance = 15; + Attributes.LowerRegCost = 40; + ArmorAttributes.MageArmor = 1; + } + + public ArmorOfFortune(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061098; // Armor of Fortune + public override int ArtifactRarity => 11; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Artifacts/Craftable/BrambleCoat.cs b/Projects/UOContent/Items/Armor/Artifacts/Craftable/BrambleCoat.cs index 6f04d312b..c354d5dc7 100644 --- a/Projects/UOContent/Items/Armor/Artifacts/Craftable/BrambleCoat.cs +++ b/Projects/UOContent/Items/Armor/Artifacts/Craftable/BrambleCoat.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - public class BrambleCoat : WoodlandChest - { - [Constructible] - public BrambleCoat() - { - Hue = 0x1; - - ArmorAttributes.SelfRepair = 3; - Attributes.BonusHits = 4; - Attributes.Luck = 150; - Attributes.ReflectPhysical = 25; - Attributes.DefendChance = 15; - } - - public BrambleCoat(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072925; // Bramble Coat - - public override int BasePhysicalResistance => 10; - public override int BaseFireResistance => 8; - public override int BaseColdResistance => 7; - public override int BasePoisonResistance => 8; - public override int BaseEnergyResistance => 7; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class BrambleCoat : WoodlandChest + { + [Constructible] + public BrambleCoat() + { + Hue = 0x1; + + ArmorAttributes.SelfRepair = 3; + Attributes.BonusHits = 4; + Attributes.Luck = 150; + Attributes.ReflectPhysical = 25; + Attributes.DefendChance = 15; + } + + public BrambleCoat(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072925; // Bramble Coat + + public override int BasePhysicalResistance => 10; + public override int BaseFireResistance => 8; + public override int BaseColdResistance => 7; + public override int BasePoisonResistance => 8; + public override int BaseEnergyResistance => 7; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Artifacts/Craftable/IronwoodCrown.cs b/Projects/UOContent/Items/Armor/Artifacts/Craftable/IronwoodCrown.cs index 49e70726e..9e09e917c 100644 --- a/Projects/UOContent/Items/Armor/Artifacts/Craftable/IronwoodCrown.cs +++ b/Projects/UOContent/Items/Armor/Artifacts/Craftable/IronwoodCrown.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - public class IronwoodCrown : RavenHelm - { - [Constructible] - public IronwoodCrown() - { - Hue = 0x1; - - ArmorAttributes.SelfRepair = 3; - - Attributes.BonusStr = 5; - Attributes.BonusDex = 5; - Attributes.BonusInt = 5; - } - - public IronwoodCrown(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072924; // Ironwood Crown - - public override int BasePhysicalResistance => 10; - public override int BaseFireResistance => 6; - public override int BaseColdResistance => 7; - public override int BasePoisonResistance => 7; - public override int BaseEnergyResistance => 10; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class IronwoodCrown : RavenHelm + { + [Constructible] + public IronwoodCrown() + { + Hue = 0x1; + + ArmorAttributes.SelfRepair = 3; + + Attributes.BonusStr = 5; + Attributes.BonusDex = 5; + Attributes.BonusInt = 5; + } + + public IronwoodCrown(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072924; // Ironwood Crown + + public override int BasePhysicalResistance => 10; + public override int BaseFireResistance => 6; + public override int BaseColdResistance => 7; + public override int BasePoisonResistance => 7; + public override int BaseEnergyResistance => 10; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Artifacts/Craftable/SongWovenMantle.cs b/Projects/UOContent/Items/Armor/Artifacts/Craftable/SongWovenMantle.cs index f50784d60..c47a0b140 100644 --- a/Projects/UOContent/Items/Armor/Artifacts/Craftable/SongWovenMantle.cs +++ b/Projects/UOContent/Items/Armor/Artifacts/Craftable/SongWovenMantle.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class SongWovenMantle : LeafArms - { - [Constructible] - public SongWovenMantle() - { - Hue = 0x493; - - SkillBonuses.SetValues(0, SkillName.Musicianship, 10.0); - - Attributes.Luck = 100; - Attributes.DefendChance = 5; - } - - public SongWovenMantle(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072931; // Song Woven Mantle - - public override int BasePhysicalResistance => 14; - public override int BaseColdResistance => 14; - public override int BaseEnergyResistance => 16; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SongWovenMantle : LeafArms + { + [Constructible] + public SongWovenMantle() + { + Hue = 0x493; + + SkillBonuses.SetValues(0, SkillName.Musicianship, 10.0); + + Attributes.Luck = 100; + Attributes.DefendChance = 5; + } + + public SongWovenMantle(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072931; // Song Woven Mantle + + public override int BasePhysicalResistance => 14; + public override int BaseColdResistance => 14; + public override int BaseEnergyResistance => 16; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Artifacts/Craftable/SpellWovenBritches.cs b/Projects/UOContent/Items/Armor/Artifacts/Craftable/SpellWovenBritches.cs index cb4fcc2bc..8f61a95b5 100644 --- a/Projects/UOContent/Items/Armor/Artifacts/Craftable/SpellWovenBritches.cs +++ b/Projects/UOContent/Items/Armor/Artifacts/Craftable/SpellWovenBritches.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class SpellWovenBritches : LeafLegs - { - [Constructible] - public SpellWovenBritches() - { - Hue = 0x487; - - SkillBonuses.SetValues(0, SkillName.Meditation, 10.0); - - Attributes.BonusInt = 8; - Attributes.SpellDamage = 10; - Attributes.LowerManaCost = 10; - } - - public SpellWovenBritches(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072929; // Spell Woven Britches - - public override int BaseFireResistance => 15; - public override int BasePoisonResistance => 16; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SpellWovenBritches : LeafLegs + { + [Constructible] + public SpellWovenBritches() + { + Hue = 0x487; + + SkillBonuses.SetValues(0, SkillName.Meditation, 10.0); + + Attributes.BonusInt = 8; + Attributes.SpellDamage = 10; + Attributes.LowerManaCost = 10; + } + + public SpellWovenBritches(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072929; // Spell Woven Britches + + public override int BaseFireResistance => 15; + public override int BasePoisonResistance => 16; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Artifacts/Craftable/StitchersMittens.cs b/Projects/UOContent/Items/Armor/Artifacts/Craftable/StitchersMittens.cs index 7cdff0901..173e56ce8 100644 --- a/Projects/UOContent/Items/Armor/Artifacts/Craftable/StitchersMittens.cs +++ b/Projects/UOContent/Items/Armor/Artifacts/Craftable/StitchersMittens.cs @@ -1,39 +1,39 @@ -namespace Server.Items -{ - public class StitchersMittens : LeafGloves - { - [Constructible] - public StitchersMittens() - { - Hue = 0x481; - - SkillBonuses.SetValues(0, SkillName.Healing, 10.0); - - Attributes.BonusDex = 5; - Attributes.LowerRegCost = 30; - } - - public StitchersMittens(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072932; // Stitcher's Mittens - - public override int BasePhysicalResistance => 20; - public override int BaseColdResistance => 20; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class StitchersMittens : LeafGloves + { + [Constructible] + public StitchersMittens() + { + Hue = 0x481; + + SkillBonuses.SetValues(0, SkillName.Healing, 10.0); + + Attributes.BonusDex = 5; + Attributes.LowerRegCost = 30; + } + + public StitchersMittens(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072932; // Stitcher's Mittens + + public override int BasePhysicalResistance => 20; + public override int BaseColdResistance => 20; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Artifacts/GauntletsOfNobility.cs b/Projects/UOContent/Items/Armor/Artifacts/GauntletsOfNobility.cs index 2377c218a..1124a43e9 100644 --- a/Projects/UOContent/Items/Armor/Artifacts/GauntletsOfNobility.cs +++ b/Projects/UOContent/Items/Armor/Artifacts/GauntletsOfNobility.cs @@ -1,50 +1,50 @@ -namespace Server.Items -{ - public class GauntletsOfNobility : RingmailGloves - { - [Constructible] - public GauntletsOfNobility() - { - Hue = 0x4FE; - Attributes.BonusStr = 8; - Attributes.Luck = 100; - Attributes.WeaponDamage = 20; - } - - public GauntletsOfNobility(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061092; // Gauntlets of Nobility - public override int ArtifactRarity => 11; - - public override int BasePhysicalResistance => 18; - public override int BasePoisonResistance => 20; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1) - { - if (Hue == 0x562) - Hue = 0x4FE; - - PhysicalBonus = 0; - PoisonBonus = 0; - } - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class GauntletsOfNobility : RingmailGloves + { + [Constructible] + public GauntletsOfNobility() + { + Hue = 0x4FE; + Attributes.BonusStr = 8; + Attributes.Luck = 100; + Attributes.WeaponDamage = 20; + } + + public GauntletsOfNobility(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061092; // Gauntlets of Nobility + public override int ArtifactRarity => 11; + + public override int BasePhysicalResistance => 18; + public override int BasePoisonResistance => 20; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version < 1) + { + if (Hue == 0x562) + Hue = 0x4FE; + + PhysicalBonus = 0; + PoisonBonus = 0; + } + } + } +} diff --git a/Projects/UOContent/Items/Armor/Artifacts/HelmOfInsight.cs b/Projects/UOContent/Items/Armor/Artifacts/HelmOfInsight.cs index 53d0f01fa..9e3bfaba9 100644 --- a/Projects/UOContent/Items/Armor/Artifacts/HelmOfInsight.cs +++ b/Projects/UOContent/Items/Armor/Artifacts/HelmOfInsight.cs @@ -1,44 +1,44 @@ -namespace Server.Items -{ - public class HelmOfInsight : PlateHelm - { - [Constructible] - public HelmOfInsight() - { - Hue = 0x554; - Attributes.BonusInt = 8; - Attributes.BonusMana = 15; - Attributes.RegenMana = 2; - Attributes.LowerManaCost = 8; - } - - public HelmOfInsight(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061096; // Helm of Insight - public override int ArtifactRarity => 11; - - public override int BaseEnergyResistance => 17; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1) - EnergyBonus = 0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class HelmOfInsight : PlateHelm + { + [Constructible] + public HelmOfInsight() + { + Hue = 0x554; + Attributes.BonusInt = 8; + Attributes.BonusMana = 15; + Attributes.RegenMana = 2; + Attributes.LowerManaCost = 8; + } + + public HelmOfInsight(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061096; // Helm of Insight + public override int ArtifactRarity => 11; + + public override int BaseEnergyResistance => 17; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version < 1) + EnergyBonus = 0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Artifacts/HolyKnightsBreastplate.cs b/Projects/UOContent/Items/Armor/Artifacts/HolyKnightsBreastplate.cs index f1e1b4846..c2f84aadd 100644 --- a/Projects/UOContent/Items/Armor/Artifacts/HolyKnightsBreastplate.cs +++ b/Projects/UOContent/Items/Armor/Artifacts/HolyKnightsBreastplate.cs @@ -1,42 +1,42 @@ -namespace Server.Items -{ - public class HolyKnightsBreastplate : PlateChest - { - [Constructible] - public HolyKnightsBreastplate() - { - Hue = 0x47E; - Attributes.BonusHits = 10; - Attributes.ReflectPhysical = 15; - } - - public HolyKnightsBreastplate(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061097; // Holy Knight's Breastplate - public override int ArtifactRarity => 11; - - public override int BasePhysicalResistance => 35; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1) - PhysicalBonus = 0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class HolyKnightsBreastplate : PlateChest + { + [Constructible] + public HolyKnightsBreastplate() + { + Hue = 0x47E; + Attributes.BonusHits = 10; + Attributes.ReflectPhysical = 15; + } + + public HolyKnightsBreastplate(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061097; // Holy Knight's Breastplate + public override int ArtifactRarity => 11; + + public override int BasePhysicalResistance => 35; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version < 1) + PhysicalBonus = 0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Artifacts/InquisitorsResolution.cs b/Projects/UOContent/Items/Armor/Artifacts/InquisitorsResolution.cs index d49d9ff2f..0f8595ebf 100644 --- a/Projects/UOContent/Items/Armor/Artifacts/InquisitorsResolution.cs +++ b/Projects/UOContent/Items/Armor/Artifacts/InquisitorsResolution.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - public class InquisitorsResolution : PlateGloves - { - [Constructible] - public InquisitorsResolution() - { - Hue = 0x4F2; - Attributes.CastRecovery = 3; - Attributes.LowerManaCost = 8; - ArmorAttributes.MageArmor = 1; - } - - public InquisitorsResolution(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1060206; // The Inquisitor's Resolution - public override int ArtifactRarity => 10; - - public override int BaseColdResistance => 22; - public override int BaseEnergyResistance => 17; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1) - { - ColdBonus = 0; - EnergyBonus = 0; - } - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class InquisitorsResolution : PlateGloves + { + [Constructible] + public InquisitorsResolution() + { + Hue = 0x4F2; + Attributes.CastRecovery = 3; + Attributes.LowerManaCost = 8; + ArmorAttributes.MageArmor = 1; + } + + public InquisitorsResolution(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1060206; // The Inquisitor's Resolution + public override int ArtifactRarity => 10; + + public override int BaseColdResistance => 22; + public override int BaseEnergyResistance => 17; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version < 1) + { + ColdBonus = 0; + EnergyBonus = 0; + } + } + } +} diff --git a/Projects/UOContent/Items/Armor/Artifacts/JackalsCollar.cs b/Projects/UOContent/Items/Armor/Artifacts/JackalsCollar.cs index 1d456bb35..4e6f08f00 100644 --- a/Projects/UOContent/Items/Armor/Artifacts/JackalsCollar.cs +++ b/Projects/UOContent/Items/Armor/Artifacts/JackalsCollar.cs @@ -1,49 +1,49 @@ -namespace Server.Items -{ - public class JackalsCollar : PlateGorget - { - [Constructible] - public JackalsCollar() - { - Hue = 0x6D1; - Attributes.BonusDex = 15; - Attributes.RegenHits = 2; - } - - public JackalsCollar(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061594; // Jackal's Collar - public override int ArtifactRarity => 11; - - public override int BaseFireResistance => 23; - public override int BaseColdResistance => 17; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1) - { - if (Hue == 0x54B) - Hue = 0x6D1; - - FireBonus = 0; - ColdBonus = 0; - } - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class JackalsCollar : PlateGorget + { + [Constructible] + public JackalsCollar() + { + Hue = 0x6D1; + Attributes.BonusDex = 15; + Attributes.RegenHits = 2; + } + + public JackalsCollar(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061594; // Jackal's Collar + public override int ArtifactRarity => 11; + + public override int BaseFireResistance => 23; + public override int BaseColdResistance => 17; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version < 1) + { + if (Hue == 0x54B) + Hue = 0x6D1; + + FireBonus = 0; + ColdBonus = 0; + } + } + } +} diff --git a/Projects/UOContent/Items/Armor/Artifacts/LeggingsOfBane.cs b/Projects/UOContent/Items/Armor/Artifacts/LeggingsOfBane.cs index 59f79d30a..1f6bdeb5d 100644 --- a/Projects/UOContent/Items/Armor/Artifacts/LeggingsOfBane.cs +++ b/Projects/UOContent/Items/Armor/Artifacts/LeggingsOfBane.cs @@ -1,57 +1,57 @@ -namespace Server.Items -{ - public class LeggingsOfBane : ChainLegs - { - [Constructible] - public LeggingsOfBane() - { - Hue = 0x4F5; - ArmorAttributes.DurabilityBonus = 100; - HitPoints = MaxHitPoints = - 255; // Cause the Durability bonus and such and the min/max hits as well as all other hits being whole #'s... - Attributes.BonusStam = 8; - Attributes.AttackChance = 20; - } - - public LeggingsOfBane(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061100; // Leggings of Bane - public override int ArtifactRarity => 11; - - public override int BasePoisonResistance => 36; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(2); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version <= 1) - if (HitPoints > 255 || MaxHitPoints > 255) - HitPoints = MaxHitPoints = 255; - - if (version < 1) - { - if (Hue == 0x559) - Hue = 0x4F5; - - if (ArmorAttributes.DurabilityBonus == 0) - ArmorAttributes.DurabilityBonus = 100; - - PoisonBonus = 0; - } - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LeggingsOfBane : ChainLegs + { + [Constructible] + public LeggingsOfBane() + { + Hue = 0x4F5; + ArmorAttributes.DurabilityBonus = 100; + HitPoints = MaxHitPoints = + 255; // Cause the Durability bonus and such and the min/max hits as well as all other hits being whole #'s... + Attributes.BonusStam = 8; + Attributes.AttackChance = 20; + } + + public LeggingsOfBane(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061100; // Leggings of Bane + public override int ArtifactRarity => 11; + + public override int BasePoisonResistance => 36; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(2); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version <= 1) + if (HitPoints > 255 || MaxHitPoints > 255) + HitPoints = MaxHitPoints = 255; + + if (version < 1) + { + if (Hue == 0x559) + Hue = 0x4F5; + + if (ArmorAttributes.DurabilityBonus == 0) + ArmorAttributes.DurabilityBonus = 100; + + PoisonBonus = 0; + } + } + } +} diff --git a/Projects/UOContent/Items/Armor/Artifacts/MidnightBracers.cs b/Projects/UOContent/Items/Armor/Artifacts/MidnightBracers.cs index 4d6eaa53a..5bfc46f07 100644 --- a/Projects/UOContent/Items/Armor/Artifacts/MidnightBracers.cs +++ b/Projects/UOContent/Items/Armor/Artifacts/MidnightBracers.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - public class MidnightBracers : BoneArms - { - [Constructible] - public MidnightBracers() - { - Hue = 0x455; - SkillBonuses.SetValues(0, SkillName.Necromancy, 20.0); - Attributes.SpellDamage = 10; - ArmorAttributes.MageArmor = 1; - } - - public MidnightBracers(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061093; // Midnight Bracers - public override int ArtifactRarity => 11; - - public override int BasePhysicalResistance => 23; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1) - PhysicalBonus = 0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class MidnightBracers : BoneArms + { + [Constructible] + public MidnightBracers() + { + Hue = 0x455; + SkillBonuses.SetValues(0, SkillName.Necromancy, 20.0); + Attributes.SpellDamage = 10; + ArmorAttributes.MageArmor = 1; + } + + public MidnightBracers(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061093; // Midnight Bracers + public override int ArtifactRarity => 11; + + public override int BasePhysicalResistance => 23; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version < 1) + PhysicalBonus = 0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Artifacts/OrnateCrownOfTheHarrower.cs b/Projects/UOContent/Items/Armor/Artifacts/OrnateCrownOfTheHarrower.cs index 98d9e8de5..0ab3f2896 100644 --- a/Projects/UOContent/Items/Armor/Artifacts/OrnateCrownOfTheHarrower.cs +++ b/Projects/UOContent/Items/Armor/Artifacts/OrnateCrownOfTheHarrower.cs @@ -1,48 +1,48 @@ -namespace Server.Items -{ - public class OrnateCrownOfTheHarrower : BoneHelm - { - [Constructible] - public OrnateCrownOfTheHarrower() - { - Hue = 0x4F6; - Attributes.RegenHits = 2; - Attributes.RegenStam = 3; - Attributes.WeaponDamage = 25; - } - - public OrnateCrownOfTheHarrower(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061095; // Ornate Crown of the Harrower - public override int ArtifactRarity => 11; - - public override int BasePoisonResistance => 17; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1) - { - if (Hue == 0x55A) - Hue = 0x4F6; - - PoisonBonus = 0; - } - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class OrnateCrownOfTheHarrower : BoneHelm + { + [Constructible] + public OrnateCrownOfTheHarrower() + { + Hue = 0x4F6; + Attributes.RegenHits = 2; + Attributes.RegenStam = 3; + Attributes.WeaponDamage = 25; + } + + public OrnateCrownOfTheHarrower(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061095; // Ornate Crown of the Harrower + public override int ArtifactRarity => 11; + + public override int BasePoisonResistance => 17; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version < 1) + { + if (Hue == 0x55A) + Hue = 0x4F6; + + PoisonBonus = 0; + } + } + } +} diff --git a/Projects/UOContent/Items/Armor/Artifacts/ShadowDancerLeggings.cs b/Projects/UOContent/Items/Armor/Artifacts/ShadowDancerLeggings.cs index 1aca37467..80bfbeee8 100644 --- a/Projects/UOContent/Items/Armor/Artifacts/ShadowDancerLeggings.cs +++ b/Projects/UOContent/Items/Armor/Artifacts/ShadowDancerLeggings.cs @@ -1,52 +1,52 @@ -namespace Server.Items -{ - public class ShadowDancerLeggings : LeatherLegs - { - [Constructible] - public ShadowDancerLeggings() - { - ItemID = 0x13D2; - Hue = 0x455; - SkillBonuses.SetValues(0, SkillName.Stealth, 20.0); - SkillBonuses.SetValues(1, SkillName.Stealing, 20.0); - } - - public ShadowDancerLeggings(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061598; // Shadow Dancer Leggings - public override int ArtifactRarity => 11; - - public override int BasePhysicalResistance => 17; - public override int BasePoisonResistance => 18; - public override int BaseEnergyResistance => 18; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1) - { - if (ItemID == 0x13CB) - ItemID = 0x13D2; - - PhysicalBonus = 0; - PoisonBonus = 0; - EnergyBonus = 0; - } - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ShadowDancerLeggings : LeatherLegs + { + [Constructible] + public ShadowDancerLeggings() + { + ItemID = 0x13D2; + Hue = 0x455; + SkillBonuses.SetValues(0, SkillName.Stealth, 20.0); + SkillBonuses.SetValues(1, SkillName.Stealing, 20.0); + } + + public ShadowDancerLeggings(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061598; // Shadow Dancer Leggings + public override int ArtifactRarity => 11; + + public override int BasePhysicalResistance => 17; + public override int BasePoisonResistance => 18; + public override int BaseEnergyResistance => 18; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version < 1) + { + if (ItemID == 0x13CB) + ItemID = 0x13D2; + + PhysicalBonus = 0; + PoisonBonus = 0; + EnergyBonus = 0; + } + } + } +} diff --git a/Projects/UOContent/Items/Armor/Artifacts/TunicOfFire.cs b/Projects/UOContent/Items/Armor/Artifacts/TunicOfFire.cs index 873857405..3d0202d8d 100644 --- a/Projects/UOContent/Items/Armor/Artifacts/TunicOfFire.cs +++ b/Projects/UOContent/Items/Armor/Artifacts/TunicOfFire.cs @@ -1,53 +1,53 @@ -namespace Server.Items -{ - public class TunicOfFire : ChainChest - { - [Constructible] - public TunicOfFire() - { - Hue = 0x54F; - ArmorAttributes.SelfRepair = 5; - Attributes.NightSight = 1; - Attributes.ReflectPhysical = 15; - } - - public TunicOfFire(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061099; // Tunic of Fire - public override int ArtifactRarity => 11; - - public override int BasePhysicalResistance => 24; - public override int BaseFireResistance => 34; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1) - { - if (Hue == 0x54E) - Hue = 0x54F; - - if (Attributes.NightSight == 0) - Attributes.NightSight = 1; - - PhysicalBonus = 0; - FireBonus = 0; - } - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TunicOfFire : ChainChest + { + [Constructible] + public TunicOfFire() + { + Hue = 0x54F; + ArmorAttributes.SelfRepair = 5; + Attributes.NightSight = 1; + Attributes.ReflectPhysical = 15; + } + + public TunicOfFire(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061099; // Tunic of Fire + public override int ArtifactRarity => 11; + + public override int BasePhysicalResistance => 24; + public override int BaseFireResistance => 34; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version < 1) + { + if (Hue == 0x54E) + Hue = 0x54F; + + if (Attributes.NightSight == 0) + Attributes.NightSight = 1; + + PhysicalBonus = 0; + FireBonus = 0; + } + } + } +} diff --git a/Projects/UOContent/Items/Armor/Artifacts/VoiceOfTheFallenKing.cs b/Projects/UOContent/Items/Armor/Artifacts/VoiceOfTheFallenKing.cs index 8481c11ab..6174ea716 100644 --- a/Projects/UOContent/Items/Armor/Artifacts/VoiceOfTheFallenKing.cs +++ b/Projects/UOContent/Items/Armor/Artifacts/VoiceOfTheFallenKing.cs @@ -1,50 +1,50 @@ -namespace Server.Items -{ - public class VoiceOfTheFallenKing : LeatherGorget - { - [Constructible] - public VoiceOfTheFallenKing() - { - Hue = 0x76D; - Attributes.BonusStr = 8; - Attributes.RegenHits = 5; - Attributes.RegenStam = 3; - } - - public VoiceOfTheFallenKing(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061094; // Voice of the Fallen King - public override int ArtifactRarity => 11; - - public override int BaseColdResistance => 18; - public override int BaseEnergyResistance => 18; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1) - { - if (Hue == 0x551) - Hue = 0x76D; - - ColdBonus = 0; - EnergyBonus = 0; - } - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class VoiceOfTheFallenKing : LeatherGorget + { + [Constructible] + public VoiceOfTheFallenKing() + { + Hue = 0x76D; + Attributes.BonusStr = 8; + Attributes.RegenHits = 5; + Attributes.RegenStam = 3; + } + + public VoiceOfTheFallenKing(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061094; // Voice of the Fallen King + public override int ArtifactRarity => 11; + + public override int BaseColdResistance => 18; + public override int BaseEnergyResistance => 18; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version < 1) + { + if (Hue == 0x551) + Hue = 0x76D; + + ColdBonus = 0; + EnergyBonus = 0; + } + } + } +} diff --git a/Projects/UOContent/Items/Armor/BaseArmor.cs b/Projects/UOContent/Items/Armor/BaseArmor.cs index 4d61606ad..f11b5840a 100644 --- a/Projects/UOContent/Items/Armor/BaseArmor.cs +++ b/Projects/UOContent/Items/Armor/BaseArmor.cs @@ -1,1697 +1,1705 @@ -using System; -using System.Collections.Generic; -using Server.Engines.Craft; -using Server.Ethics; -using Server.Factions; -using Server.Network; -using Server.Utilities; -using AMA = Server.Items.ArmorMeditationAllowance; -using AMT = Server.Items.ArmorMaterialType; - -namespace Server.Items -{ - public abstract class BaseArmor : Item, IScissorable, IFactionItem, ICraftable, IWearableDurability - { - // Overridable values. These values are provided to override the defaults which get defined in the individual armor scripts. - private int m_ArmorBase = -1; - private Mobile m_Crafter; - private ArmorDurabilityLevel m_Durability; - private int m_HitPoints; - private bool m_Identified; - - /* Armor internals work differently now (Jun 19 2003) - * - * The attributes defined below default to -1. - * If the value is -1, the corresponding virtual 'Aos/Old' property is used. - * If not, the attribute value itself is used. Here's the list: - * - ArmorBase - * - StrBonus - * - DexBonus - * - IntBonus - * - StrReq - * - DexReq - * - IntReq - * - MeditationAllowance - */ - - // Instance values. These values must are unique to each armor piece. - private int m_MaxHitPoints; - private AMA m_Meditate = (AMA)(-1); - private int m_PhysicalBonus, m_FireBonus, m_ColdBonus, m_PoisonBonus, m_EnergyBonus; - private ArmorProtectionLevel m_Protection; - private ArmorQuality m_Quality; - private CraftResource m_Resource; - private int m_StrBonus = -1, m_DexBonus = -1, m_IntBonus = -1; - private int m_StrReq = -1, m_DexReq = -1, m_IntReq = -1; - - public BaseArmor(Serial serial) : base(serial) - { - } - - public BaseArmor(int itemID) : base(itemID) - { - m_Quality = ArmorQuality.Regular; - m_Durability = ArmorDurabilityLevel.Regular; - m_Crafter = null; - - m_Resource = DefaultResource; - Hue = CraftResources.GetHue(m_Resource); - - m_HitPoints = m_MaxHitPoints = Utility.RandomMinMax(InitMinHits, InitMaxHits); - - Layer = (Layer)ItemData.Quality; - - Attributes = new AosAttributes(this); - ArmorAttributes = new AosArmorAttributes(this); - SkillBonuses = new AosSkillBonuses(this); - } - - public virtual bool AllowMaleWearer => true; - public virtual bool AllowFemaleWearer => true; - - public abstract AMT MaterialType { get; } - - public virtual int RevertArmorBase => ArmorBase; - public virtual int ArmorBase => 0; - - public virtual AMA DefMedAllowance => AMA.None; - public virtual AMA AosMedAllowance => DefMedAllowance; - public virtual AMA OldMedAllowance => DefMedAllowance; - - public virtual int AosStrBonus => 0; - public virtual int AosDexBonus => 0; - public virtual int AosIntBonus => 0; - public virtual int AosStrReq => 0; - public virtual int AosDexReq => 0; - public virtual int AosIntReq => 0; - - public virtual int OldStrBonus => 0; - public virtual int OldDexBonus => 0; - public virtual int OldIntBonus => 0; - public virtual int OldStrReq => 0; - public virtual int OldDexReq => 0; - public virtual int OldIntReq => 0; - - [CommandProperty(AccessLevel.GameMaster)] - public AMA MeditationAllowance - { - get => m_Meditate == (AMA)(-1) ? Core.AOS ? AosMedAllowance : OldMedAllowance : m_Meditate; - set => m_Meditate = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int BaseArmorRating - { - get - { - if (m_ArmorBase == -1) - return ArmorBase; - return m_ArmorBase; - } - set - { - m_ArmorBase = value; - Invalidate(); - } - } - - public double BaseArmorRatingScaled => BaseArmorRating * ArmorScalar; - - public virtual double ArmorRating - { - get - { - int ar = BaseArmorRating; - - if (m_Protection != ArmorProtectionLevel.Regular) - ar += 10 + 5 * (int)m_Protection; - - switch (m_Resource) - { - case CraftResource.DullCopper: - ar += 2; - break; - case CraftResource.ShadowIron: - ar += 4; - break; - case CraftResource.Copper: - ar += 6; - break; - case CraftResource.Bronze: - ar += 8; - break; - case CraftResource.Gold: - ar += 10; - break; - case CraftResource.Agapite: - ar += 12; - break; - case CraftResource.Verite: - ar += 14; - break; - case CraftResource.Valorite: - ar += 16; - break; - case CraftResource.SpinedLeather: - ar += 10; - break; - case CraftResource.HornedLeather: - ar += 13; - break; - case CraftResource.BarbedLeather: - ar += 16; - break; - } - - ar += -8 + 8 * (int)m_Quality; - return ScaleArmorByDurability(ar); - } - } - - public double ArmorRatingScaled => ArmorRating * ArmorScalar; - - [CommandProperty(AccessLevel.GameMaster)] - public int StrBonus - { - get => m_StrBonus == -1 ? Core.AOS ? AosStrBonus : OldStrBonus : m_StrBonus; - set - { - m_StrBonus = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int DexBonus - { - get => m_DexBonus == -1 ? Core.AOS ? AosDexBonus : OldDexBonus : m_DexBonus; - set - { - m_DexBonus = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int IntBonus - { - get => m_IntBonus == -1 ? Core.AOS ? AosIntBonus : OldIntBonus : m_IntBonus; - set - { - m_IntBonus = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int StrRequirement - { - get => m_StrReq == -1 ? Core.AOS ? AosStrReq : OldStrReq : m_StrReq; - set - { - m_StrReq = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int DexRequirement - { - get => m_DexReq == -1 ? Core.AOS ? AosDexReq : OldDexReq : m_DexReq; - set - { - m_DexReq = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int IntRequirement - { - get => m_IntReq == -1 ? Core.AOS ? AosIntReq : OldIntReq : m_IntReq; - set - { - m_IntReq = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Identified - { - get => m_Identified; - set - { - m_Identified = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool PlayerConstructed { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public CraftResource Resource - { - get => m_Resource; - set - { - if (m_Resource != value) - { - UnscaleDurability(); - - m_Resource = value; - - if (CraftItem.RetainsColor(GetType())) Hue = CraftResources.GetHue(m_Resource); - - Invalidate(); - InvalidateProperties(); - - (Parent as Mobile)?.UpdateResistances(); - - ScaleDurability(); - } - } - } - - public virtual double ArmorScalar - { - get - { - int pos = (int)BodyPosition; - - if (pos >= 0 && pos < ArmorScalars.Length) - return ArmorScalars[pos]; - - return 1.0; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Crafter - { - get => m_Crafter; - set - { - m_Crafter = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public ArmorQuality Quality - { - get => m_Quality; - set - { - UnscaleDurability(); - m_Quality = value; - Invalidate(); - InvalidateProperties(); - ScaleDurability(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public ArmorDurabilityLevel Durability - { - get => m_Durability; - set - { - UnscaleDurability(); - m_Durability = value; - ScaleDurability(); - InvalidateProperties(); - } - } - - public virtual int ArtifactRarity => 0; - - [CommandProperty(AccessLevel.GameMaster)] - public ArmorProtectionLevel ProtectionLevel - { - get => m_Protection; - set - { - if (m_Protection != value) - { - m_Protection = value; - - Invalidate(); - InvalidateProperties(); - - (Parent as Mobile)?.UpdateResistances(); - } - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public AosAttributes Attributes { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public AosArmorAttributes ArmorAttributes { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public AosSkillBonuses SkillBonuses { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int PhysicalBonus - { - get => m_PhysicalBonus; - set - { - m_PhysicalBonus = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int FireBonus - { - get => m_FireBonus; - set - { - m_FireBonus = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int ColdBonus - { - get => m_ColdBonus; - set - { - m_ColdBonus = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int PoisonBonus - { - get => m_PoisonBonus; - set - { - m_PoisonBonus = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int EnergyBonus - { - get => m_EnergyBonus; - set - { - m_EnergyBonus = value; - InvalidateProperties(); - } - } - - public virtual int BasePhysicalResistance => 0; - public virtual int BaseFireResistance => 0; - public virtual int BaseColdResistance => 0; - public virtual int BasePoisonResistance => 0; - public virtual int BaseEnergyResistance => 0; - - public override int PhysicalResistance => BasePhysicalResistance + GetProtOffset() + - GetResourceAttrs().ArmorPhysicalResist + m_PhysicalBonus; - - public override int FireResistance => - BaseFireResistance + GetProtOffset() + GetResourceAttrs().ArmorFireResist + m_FireBonus; - - public override int ColdResistance => - BaseColdResistance + GetProtOffset() + GetResourceAttrs().ArmorColdResist + m_ColdBonus; - - public override int PoisonResistance => - BasePoisonResistance + GetProtOffset() + GetResourceAttrs().ArmorPoisonResist + m_PoisonBonus; - - public override int EnergyResistance => - BaseEnergyResistance + GetProtOffset() + GetResourceAttrs().ArmorEnergyResist + m_EnergyBonus; - - [CommandProperty(AccessLevel.GameMaster)] - public ArmorBodyType BodyPosition - { - get - { - return Layer switch - { - Layer.Neck => ArmorBodyType.Gorget, - Layer.TwoHanded => ArmorBodyType.Shield, - Layer.Gloves => ArmorBodyType.Gloves, - Layer.Helm => ArmorBodyType.Helmet, - Layer.Arms => ArmorBodyType.Arms, - Layer.InnerLegs => ArmorBodyType.Legs, - Layer.OuterLegs => ArmorBodyType.Legs, - Layer.Pants => ArmorBodyType.Legs, - Layer.InnerTorso => ArmorBodyType.Chest, - Layer.OuterTorso => ArmorBodyType.Chest, - Layer.Shirt => ArmorBodyType.Chest, - _ => ArmorBodyType.Gorget - }; - } - } - - public static double[] ArmorScalars { get; set; } = { 0.07, 0.07, 0.14, 0.15, 0.22, 0.35 }; - - public virtual CraftResource DefaultResource => CraftResource.Iron; - - public virtual Race RequiredRace => null; - - [Hue] - [CommandProperty(AccessLevel.GameMaster)] - public override int Hue - { - get => base.Hue; - set - { - base.Hue = value; - InvalidateProperties(); - } - } - - public int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, - CraftItem craftItem, int resHue) - { - Quality = (ArmorQuality)quality; - - if (makersMark) - Crafter = from; - - Type resourceType = typeRes ?? craftItem.Resources[0].ItemType; - - Resource = CraftResources.GetFromType(resourceType); - PlayerConstructed = true; - - CraftContext context = craftSystem.GetContext(from); - - if (context?.DoNotColor == true) - Hue = 0; - - if (Quality == ArmorQuality.Exceptional) - { - if (!(Core.ML && this is BaseShield)) // Guessed Core.ML removed exceptional resist bonuses from crafted shields - DistributeBonuses(tool is BaseRunicTool ? 6 : - Core.SE ? 15 : 14); // Not sure since when, but right now 15 points are added, not 14. - - if (Core.ML && !(this is BaseShield)) - { - int bonus = (int)(from.Skills.ArmsLore.Value / 20); - - for (int i = 0; i < bonus; i++) - switch (Utility.Random(5)) - { - case 0: - m_PhysicalBonus++; - break; - case 1: - m_FireBonus++; - break; - case 2: - m_ColdBonus++; - break; - case 3: - m_EnergyBonus++; - break; - case 4: - m_PoisonBonus++; - break; - } - - from.CheckSkill(SkillName.ArmsLore, 0, 100); - } - } - - if (Core.AOS) - (tool as BaseRunicTool)?.ApplyAttributesTo(this); - - return quality; - } - - public bool Scissor(Mobile from, Scissors scissors) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(502437); // Items you wish to cut must be in your backpack. - return false; - } - - if (Ethic.IsImbued(this)) - { - from.SendLocalizedMessage(502440); // Scissors can not be used on that to produce anything. - return false; - } - - CraftSystem system = DefTailoring.CraftSystem; - - CraftItem item = system.CraftItems.SearchFor(GetType()); - - if (item?.Resources.Count == 1 && item.Resources[0].Amount >= 2) - try - { - Item res = (Item)ActivatorUtil.CreateInstance(CraftResources.GetInfo(m_Resource).ResourceTypes[0]); - - ScissorHelper(from, res, PlayerConstructed ? item.Resources[0].Amount / 2 : 1); - return true; - } - catch - { - // ignored - } - - from.SendLocalizedMessage(502440); // Scissors can not be used on that to produce anything. - return false; - } - - public virtual bool CanFortify => true; - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxHitPoints - { - get => m_MaxHitPoints; - set - { - m_MaxHitPoints = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int HitPoints - { - get => m_HitPoints; - set - { - if (value != m_HitPoints && MaxHitPoints > 0) - { - m_HitPoints = value; - - if (m_HitPoints < 0) - Delete(); - else if (m_HitPoints > MaxHitPoints) - m_HitPoints = MaxHitPoints; - - InvalidateProperties(); - } - } - } - - public virtual int InitMinHits => 0; - public virtual int InitMaxHits => 0; - - public void UnscaleDurability() - { - int scale = 100 + GetDurabilityBonus(); - - m_HitPoints = (m_HitPoints * 100 + (scale - 1)) / scale; - m_MaxHitPoints = (m_MaxHitPoints * 100 + (scale - 1)) / scale; - InvalidateProperties(); - } - - public void ScaleDurability() - { - int scale = 100 + GetDurabilityBonus(); - - m_HitPoints = (m_HitPoints * scale + 99) / 100; - m_MaxHitPoints = (m_MaxHitPoints * scale + 99) / 100; - InvalidateProperties(); - } - - public virtual int OnHit(BaseWeapon weapon, int damageTaken) - { - double halfar = ArmorRating / 2.0; - int absorbed = (int)(halfar + halfar * Utility.RandomDouble()); - - // Don't go below zero - damageTaken = Math.Min(absorbed, damageTaken); - - if (absorbed < 2) - absorbed = 2; - - if (Utility.Random(100) < 25) // 25% chance to lower durability - { - if (Core.AOS && ArmorAttributes.SelfRepair > Utility.Random(10)) - { - HitPoints += 2; - } - else - { - int wear; - - if (weapon.Type == WeaponType.Bashing) - wear = absorbed / 2; - else - wear = Utility.Random(2); - - if (wear > 0 && m_MaxHitPoints > 0) - { - if (m_HitPoints >= wear) - { - HitPoints -= wear; - wear = 0; - } - else - { - wear -= HitPoints; - HitPoints = 0; - } - - if (wear > 0) - { - if (m_MaxHitPoints > wear) - { - MaxHitPoints -= wear; - - if (Parent is Mobile mobile) - mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1061121); // Your equipment is severely damaged. - } - else - { - Delete(); - } - } - } - } - } - - return damageTaken; - } - - public override void OnAfterDuped(Item newItem) - { - if (!(newItem is BaseArmor armor)) - return; - - armor.Attributes = new AosAttributes(newItem, Attributes); - armor.ArmorAttributes = new AosArmorAttributes(newItem, ArmorAttributes); - armor.SkillBonuses = new AosSkillBonuses(newItem, SkillBonuses); - } - - public int ComputeStatReq(StatType type) - { - int v; - - if (type == StatType.Str) - v = StrRequirement; - else if (type == StatType.Dex) - v = DexRequirement; - else - v = IntRequirement; - - return AOS.Scale(v, 100 - GetLowerStatReq()); - } - - public int ComputeStatBonus(StatType type) - { - if (type == StatType.Str) - return StrBonus + Attributes.BonusStr; - if (type == StatType.Dex) - return DexBonus + Attributes.BonusDex; - return IntBonus + Attributes.BonusInt; - } - - public void DistributeBonuses(int amount) - { - for (int i = 0; i < amount; ++i) - switch (Utility.Random(5)) - { - case 0: - ++m_PhysicalBonus; - break; - case 1: - ++m_FireBonus; - break; - case 2: - ++m_ColdBonus; - break; - case 3: - ++m_PoisonBonus; - break; - case 4: - ++m_EnergyBonus; - break; - } - - InvalidateProperties(); - } - - public CraftAttributeInfo GetResourceAttrs() - { - CraftResourceInfo info = CraftResources.GetInfo(m_Resource); - - if (info == null) - return CraftAttributeInfo.Blank; - - return info.AttributeInfo; - } - - public int GetProtOffset() - { - return m_Protection switch - { - ArmorProtectionLevel.Guarding => 1, - ArmorProtectionLevel.Hardening => 2, - ArmorProtectionLevel.Fortification => 3, - ArmorProtectionLevel.Invulnerability => 4, - _ => 0 - }; - } - - public int GetDurabilityBonus() - { - int bonus = 0; - - if (m_Quality == ArmorQuality.Exceptional) - bonus += 20; - - switch (m_Durability) - { - case ArmorDurabilityLevel.Durable: - bonus += 20; - break; - case ArmorDurabilityLevel.Substantial: - bonus += 50; - break; - case ArmorDurabilityLevel.Massive: - bonus += 70; - break; - case ArmorDurabilityLevel.Fortified: - bonus += 100; - break; - case ArmorDurabilityLevel.Indestructible: - bonus += 120; - break; - } - - if (Core.AOS) - { - bonus += ArmorAttributes.DurabilityBonus; - - CraftResourceInfo resInfo = CraftResources.GetInfo(m_Resource); - CraftAttributeInfo attrInfo = null; - - if (resInfo != null) - attrInfo = resInfo.AttributeInfo; - - if (attrInfo != null) - bonus += attrInfo.ArmorDurability; - } - - return bonus; - } - - public static void ValidateMobile(Mobile m) - { - for (int i = m.Items.Count - 1; i >= 0; --i) - { - if (i >= m.Items.Count) - continue; - - Item item = m.Items[i]; - - if (item is BaseArmor armor) - { - if (armor.RequiredRace != null && m.Race != armor.RequiredRace) - { - if (armor.RequiredRace == Race.Elf) - m.SendLocalizedMessage(1072203); // Only Elves may use this. - else - m.SendMessage("Only {0} may use this.", armor.RequiredRace.PluralName); - - m.AddToBackpack(armor); - } - else if (!armor.AllowMaleWearer && !m.Female && m.AccessLevel < AccessLevel.GameMaster) - { - if (armor.AllowFemaleWearer) - m.SendLocalizedMessage(1010388); // Only females can wear this. - else - m.SendMessage("You may not wear this."); - - m.AddToBackpack(armor); - } - else if (!armor.AllowFemaleWearer && m.Female && m.AccessLevel < AccessLevel.GameMaster) - { - if (armor.AllowMaleWearer) - m.SendLocalizedMessage(1063343); // Only males can wear this. - else - m.SendMessage("You may not wear this."); - - m.AddToBackpack(armor); - } - } - } - } - - public int GetLowerStatReq() - { - if (!Core.AOS) - return 0; - - int v = ArmorAttributes.LowerStatReq; - - CraftResourceInfo info = CraftResources.GetInfo(m_Resource); - - CraftAttributeInfo attrInfo = info?.AttributeInfo; - - if (attrInfo != null) - v += attrInfo.ArmorLowerRequirements; - - if (v > 100) - v = 100; - - return v; - } - - public override void OnAdded(IEntity parent) - { - if (parent is Mobile from) - { - if (Core.AOS) - SkillBonuses.AddTo(from); - - from.Delta(MobileDelta.Armor); // Tell them armor rating has changed - } - } - - public virtual double ScaleArmorByDurability(double armor) - { - int scale = 100; - - if (m_MaxHitPoints > 0 && m_HitPoints < m_MaxHitPoints) - scale = 50 + 50 * m_HitPoints / m_MaxHitPoints; - - return armor * scale / 100; - } - - protected void Invalidate() - { - (Parent as Mobile)?.Delta(MobileDelta.Armor); // Tell them armor rating has changed - } - - private static void SetSaveFlag(ref SaveFlag flags, SaveFlag toSet, bool setIf) - { - if (setIf) - flags |= toSet; - } - - private static bool GetSaveFlag(SaveFlag flags, SaveFlag toGet) => (flags & toGet) != 0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(7); // version - - SaveFlag flags = SaveFlag.None; - - SetSaveFlag(ref flags, SaveFlag.Attributes, !Attributes.IsEmpty); - SetSaveFlag(ref flags, SaveFlag.ArmorAttributes, !ArmorAttributes.IsEmpty); - SetSaveFlag(ref flags, SaveFlag.PhysicalBonus, m_PhysicalBonus != 0); - SetSaveFlag(ref flags, SaveFlag.FireBonus, m_FireBonus != 0); - SetSaveFlag(ref flags, SaveFlag.ColdBonus, m_ColdBonus != 0); - SetSaveFlag(ref flags, SaveFlag.PoisonBonus, m_PoisonBonus != 0); - SetSaveFlag(ref flags, SaveFlag.EnergyBonus, m_EnergyBonus != 0); - SetSaveFlag(ref flags, SaveFlag.Identified, m_Identified); - SetSaveFlag(ref flags, SaveFlag.MaxHitPoints, m_MaxHitPoints != 0); - SetSaveFlag(ref flags, SaveFlag.HitPoints, m_HitPoints != 0); - SetSaveFlag(ref flags, SaveFlag.Crafter, m_Crafter != null); - SetSaveFlag(ref flags, SaveFlag.Quality, m_Quality != ArmorQuality.Regular); - SetSaveFlag(ref flags, SaveFlag.Durability, m_Durability != ArmorDurabilityLevel.Regular); - SetSaveFlag(ref flags, SaveFlag.Protection, m_Protection != ArmorProtectionLevel.Regular); - SetSaveFlag(ref flags, SaveFlag.Resource, m_Resource != DefaultResource); - SetSaveFlag(ref flags, SaveFlag.BaseArmor, m_ArmorBase != -1); - SetSaveFlag(ref flags, SaveFlag.StrBonus, m_StrBonus != -1); - SetSaveFlag(ref flags, SaveFlag.DexBonus, m_DexBonus != -1); - SetSaveFlag(ref flags, SaveFlag.IntBonus, m_IntBonus != -1); - SetSaveFlag(ref flags, SaveFlag.StrReq, m_StrReq != -1); - SetSaveFlag(ref flags, SaveFlag.DexReq, m_DexReq != -1); - SetSaveFlag(ref flags, SaveFlag.IntReq, m_IntReq != -1); - SetSaveFlag(ref flags, SaveFlag.MedAllowance, m_Meditate != (AMA)(-1)); - SetSaveFlag(ref flags, SaveFlag.SkillBonuses, !SkillBonuses.IsEmpty); - SetSaveFlag(ref flags, SaveFlag.PlayerConstructed, PlayerConstructed); - - writer.WriteEncodedInt((int)flags); - - if (GetSaveFlag(flags, SaveFlag.Attributes)) - Attributes.Serialize(writer); - - if (GetSaveFlag(flags, SaveFlag.ArmorAttributes)) - ArmorAttributes.Serialize(writer); - - if (GetSaveFlag(flags, SaveFlag.PhysicalBonus)) - writer.WriteEncodedInt(m_PhysicalBonus); - - if (GetSaveFlag(flags, SaveFlag.FireBonus)) - writer.WriteEncodedInt(m_FireBonus); - - if (GetSaveFlag(flags, SaveFlag.ColdBonus)) - writer.WriteEncodedInt(m_ColdBonus); - - if (GetSaveFlag(flags, SaveFlag.PoisonBonus)) - writer.WriteEncodedInt(m_PoisonBonus); - - if (GetSaveFlag(flags, SaveFlag.EnergyBonus)) - writer.WriteEncodedInt(m_EnergyBonus); - - if (GetSaveFlag(flags, SaveFlag.MaxHitPoints)) - writer.WriteEncodedInt(m_MaxHitPoints); - - if (GetSaveFlag(flags, SaveFlag.HitPoints)) - writer.WriteEncodedInt(m_HitPoints); - - if (GetSaveFlag(flags, SaveFlag.Crafter)) - writer.Write(m_Crafter); - - if (GetSaveFlag(flags, SaveFlag.Quality)) - writer.WriteEncodedInt((int)m_Quality); - - if (GetSaveFlag(flags, SaveFlag.Durability)) - writer.WriteEncodedInt((int)m_Durability); - - if (GetSaveFlag(flags, SaveFlag.Protection)) - writer.WriteEncodedInt((int)m_Protection); - - if (GetSaveFlag(flags, SaveFlag.Resource)) - writer.WriteEncodedInt((int)m_Resource); - - if (GetSaveFlag(flags, SaveFlag.BaseArmor)) - writer.WriteEncodedInt(m_ArmorBase); - - if (GetSaveFlag(flags, SaveFlag.StrBonus)) - writer.WriteEncodedInt(m_StrBonus); - - if (GetSaveFlag(flags, SaveFlag.DexBonus)) - writer.WriteEncodedInt(m_DexBonus); - - if (GetSaveFlag(flags, SaveFlag.IntBonus)) - writer.WriteEncodedInt(m_IntBonus); - - if (GetSaveFlag(flags, SaveFlag.StrReq)) - writer.WriteEncodedInt(m_StrReq); - - if (GetSaveFlag(flags, SaveFlag.DexReq)) - writer.WriteEncodedInt(m_DexReq); - - if (GetSaveFlag(flags, SaveFlag.IntReq)) - writer.WriteEncodedInt(m_IntReq); - - if (GetSaveFlag(flags, SaveFlag.MedAllowance)) - writer.WriteEncodedInt((int)m_Meditate); - - if (GetSaveFlag(flags, SaveFlag.SkillBonuses)) - SkillBonuses.Serialize(writer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 7: - case 6: - case 5: - { - SaveFlag flags = (SaveFlag)reader.ReadEncodedInt(); - - if (GetSaveFlag(flags, SaveFlag.Attributes)) - Attributes = new AosAttributes(this, reader); - else - Attributes = new AosAttributes(this); - - if (GetSaveFlag(flags, SaveFlag.ArmorAttributes)) - ArmorAttributes = new AosArmorAttributes(this, reader); - else - ArmorAttributes = new AosArmorAttributes(this); - - if (GetSaveFlag(flags, SaveFlag.PhysicalBonus)) - m_PhysicalBonus = reader.ReadEncodedInt(); - - if (GetSaveFlag(flags, SaveFlag.FireBonus)) - m_FireBonus = reader.ReadEncodedInt(); - - if (GetSaveFlag(flags, SaveFlag.ColdBonus)) - m_ColdBonus = reader.ReadEncodedInt(); - - if (GetSaveFlag(flags, SaveFlag.PoisonBonus)) - m_PoisonBonus = reader.ReadEncodedInt(); - - if (GetSaveFlag(flags, SaveFlag.EnergyBonus)) - m_EnergyBonus = reader.ReadEncodedInt(); - - if (GetSaveFlag(flags, SaveFlag.Identified)) - m_Identified = version >= 7 || reader.ReadBool(); - - if (GetSaveFlag(flags, SaveFlag.MaxHitPoints)) - m_MaxHitPoints = reader.ReadEncodedInt(); - - if (GetSaveFlag(flags, SaveFlag.HitPoints)) - m_HitPoints = reader.ReadEncodedInt(); - - if (GetSaveFlag(flags, SaveFlag.Crafter)) - m_Crafter = reader.ReadMobile(); - - if (GetSaveFlag(flags, SaveFlag.Quality)) - m_Quality = (ArmorQuality)reader.ReadEncodedInt(); - else - m_Quality = ArmorQuality.Regular; - - if (version == 5 && m_Quality == ArmorQuality.Low) - m_Quality = ArmorQuality.Regular; - - if (GetSaveFlag(flags, SaveFlag.Durability)) - { - m_Durability = (ArmorDurabilityLevel)reader.ReadEncodedInt(); - - if (m_Durability > ArmorDurabilityLevel.Indestructible) - m_Durability = ArmorDurabilityLevel.Durable; - } - - if (GetSaveFlag(flags, SaveFlag.Protection)) - { - m_Protection = (ArmorProtectionLevel)reader.ReadEncodedInt(); - - if (m_Protection > ArmorProtectionLevel.Invulnerability) - m_Protection = ArmorProtectionLevel.Defense; - } - - if (GetSaveFlag(flags, SaveFlag.Resource)) - m_Resource = (CraftResource)reader.ReadEncodedInt(); - else - m_Resource = DefaultResource; - - if (m_Resource == CraftResource.None) - m_Resource = DefaultResource; - - if (GetSaveFlag(flags, SaveFlag.BaseArmor)) - m_ArmorBase = reader.ReadEncodedInt(); - else - m_ArmorBase = -1; - - if (GetSaveFlag(flags, SaveFlag.StrBonus)) - m_StrBonus = reader.ReadEncodedInt(); - else - m_StrBonus = -1; - - if (GetSaveFlag(flags, SaveFlag.DexBonus)) - m_DexBonus = reader.ReadEncodedInt(); - else - m_DexBonus = -1; - - if (GetSaveFlag(flags, SaveFlag.IntBonus)) - m_IntBonus = reader.ReadEncodedInt(); - else - m_IntBonus = -1; - - if (GetSaveFlag(flags, SaveFlag.StrReq)) - m_StrReq = reader.ReadEncodedInt(); - else - m_StrReq = -1; - - if (GetSaveFlag(flags, SaveFlag.DexReq)) - m_DexReq = reader.ReadEncodedInt(); - else - m_DexReq = -1; - - if (GetSaveFlag(flags, SaveFlag.IntReq)) - m_IntReq = reader.ReadEncodedInt(); - else - m_IntReq = -1; - - if (GetSaveFlag(flags, SaveFlag.MedAllowance)) - m_Meditate = (AMA)reader.ReadEncodedInt(); - else - m_Meditate = (AMA)(-1); - - if (GetSaveFlag(flags, SaveFlag.SkillBonuses)) - SkillBonuses = new AosSkillBonuses(this, reader); - - if (GetSaveFlag(flags, SaveFlag.PlayerConstructed)) - PlayerConstructed = true; - - break; - } - case 4: - { - Attributes = new AosAttributes(this, reader); - ArmorAttributes = new AosArmorAttributes(this, reader); - goto case 3; - } - case 3: - { - m_PhysicalBonus = reader.ReadInt(); - m_FireBonus = reader.ReadInt(); - m_ColdBonus = reader.ReadInt(); - m_PoisonBonus = reader.ReadInt(); - m_EnergyBonus = reader.ReadInt(); - goto case 2; - } - case 2: - case 1: - { - m_Identified = reader.ReadBool(); - goto case 0; - } - case 0: - { - m_ArmorBase = reader.ReadInt(); - m_MaxHitPoints = reader.ReadInt(); - m_HitPoints = reader.ReadInt(); - m_Crafter = reader.ReadMobile(); - m_Quality = (ArmorQuality)reader.ReadInt(); - m_Durability = (ArmorDurabilityLevel)reader.ReadInt(); - m_Protection = (ArmorProtectionLevel)reader.ReadInt(); - - AMT mat = (AMT)reader.ReadInt(); - - if (m_ArmorBase == RevertArmorBase) - m_ArmorBase = -1; - - /*m_BodyPos = (ArmorBodyType)*/ - reader.ReadInt(); - - if (version < 4) - { - Attributes = new AosAttributes(this); - ArmorAttributes = new AosArmorAttributes(this); - } - - if (version < 3 && m_Quality == ArmorQuality.Exceptional) - DistributeBonuses(6); - - if (version >= 2) - { - m_Resource = (CraftResource)reader.ReadInt(); - } - else - { - var info = reader.ReadInt() switch - { - 0 => OreInfo.Iron, - 1 => OreInfo.DullCopper, - 2 => OreInfo.ShadowIron, - 3 => OreInfo.Copper, - 4 => OreInfo.Bronze, - 5 => OreInfo.Gold, - 6 => OreInfo.Agapite, - 7 => OreInfo.Verite, - 8 => OreInfo.Valorite, - _ => OreInfo.Iron - }; - - m_Resource = CraftResources.GetFromOreInfo(info, mat); - } - - m_StrBonus = reader.ReadInt(); - m_DexBonus = reader.ReadInt(); - m_IntBonus = reader.ReadInt(); - m_StrReq = reader.ReadInt(); - m_DexReq = reader.ReadInt(); - m_IntReq = reader.ReadInt(); - - if (m_StrBonus == OldStrBonus) - m_StrBonus = -1; - - if (m_DexBonus == OldDexBonus) - m_DexBonus = -1; - - if (m_IntBonus == OldIntBonus) - m_IntBonus = -1; - - if (m_StrReq == OldStrReq) - m_StrReq = -1; - - if (m_DexReq == OldDexReq) - m_DexReq = -1; - - if (m_IntReq == OldIntReq) - m_IntReq = -1; - - m_Meditate = (AMA)reader.ReadInt(); - - if (m_Meditate == OldMedAllowance) - m_Meditate = (AMA)(-1); - - if (m_Resource == CraftResource.None) - { - if (mat == ArmorMaterialType.Studded || mat == ArmorMaterialType.Leather) - m_Resource = CraftResource.RegularLeather; - else if (mat == ArmorMaterialType.Spined) - m_Resource = CraftResource.SpinedLeather; - else if (mat == ArmorMaterialType.Horned) - m_Resource = CraftResource.HornedLeather; - else if (mat == ArmorMaterialType.Barbed) - m_Resource = CraftResource.BarbedLeather; - else - m_Resource = CraftResource.Iron; - } - - if (m_MaxHitPoints == 0 && m_HitPoints == 0) - m_HitPoints = m_MaxHitPoints = Utility.RandomMinMax(InitMinHits, InitMaxHits); - - break; - } - } - - SkillBonuses ??= new AosSkillBonuses(this); - - Mobile m = Parent as Mobile; - - if (Core.AOS && m != null) - SkillBonuses.AddTo(m); - - int strBonus = ComputeStatBonus(StatType.Str); - int dexBonus = ComputeStatBonus(StatType.Dex); - int intBonus = ComputeStatBonus(StatType.Int); - - if (m != null && (strBonus != 0 || dexBonus != 0 || intBonus != 0)) - { - string modName = Serial.ToString(); - - if (strBonus != 0) - m.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero)); - - if (dexBonus != 0) - m.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero)); - - if (intBonus != 0) - m.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero)); - } - - m?.CheckStatTimers(); - - if (version < 7) - PlayerConstructed = true; // we don't know, so, assume it's crafted - } - - public override bool AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted) - { - if (!Ethic.CheckTrade(from, to, newOwner, this)) - return false; - - return base.AllowSecureTrade(from, to, newOwner, accepted); - } - - public override bool CanEquip(Mobile from) - { - if (!Ethic.CheckEquip(from, this)) - return false; - - if (from.AccessLevel < AccessLevel.GameMaster) - { - if (RequiredRace != null && from.Race != RequiredRace) - { - if (RequiredRace == Race.Elf) - from.SendLocalizedMessage(1072203); // Only Elves may use this. - else - from.SendMessage("Only {0} may use this.", RequiredRace.PluralName); - - return false; - } - - if (!AllowMaleWearer && !from.Female) - { - if (AllowFemaleWearer) - from.SendLocalizedMessage(1010388); // Only females can wear this. - else - from.SendMessage("You may not wear this."); - - return false; - } - - if (!AllowFemaleWearer && from.Female) - { - if (AllowMaleWearer) - from.SendLocalizedMessage(1063343); // Only males can wear this. - else - from.SendMessage("You may not wear this."); - - return false; - } - - int strBonus = ComputeStatBonus(StatType.Str), strReq = ComputeStatReq(StatType.Str); - int dexBonus = ComputeStatBonus(StatType.Dex), dexReq = ComputeStatReq(StatType.Dex); - int intBonus = ComputeStatBonus(StatType.Int), intReq = ComputeStatReq(StatType.Int); - - if (from.Dex < dexReq || from.Dex + dexBonus < 1) - { - from.SendLocalizedMessage(502077); // You do not have enough dexterity to equip this item. - return false; - } - - if (from.Str < strReq || from.Str + strBonus < 1) - { - from.SendLocalizedMessage(500213); // You are not strong enough to equip that. - return false; - } - - if (from.Int < intReq || from.Int + intBonus < 1) - { - from.SendMessage("You are not smart enough to equip that."); - return false; - } - } - - return base.CanEquip(from); - } - - public override bool CheckPropertyConflict(Mobile m) - { - if (base.CheckPropertyConflict(m)) - return true; - - if (Layer == Layer.Pants) - return m.FindItemOnLayer(Layer.InnerLegs) != null; - - if (Layer == Layer.Shirt) - return m.FindItemOnLayer(Layer.InnerTorso) != null; - - return false; - } - - public override bool OnEquip(Mobile from) - { - from.CheckStatTimers(); - - int strBonus = ComputeStatBonus(StatType.Str); - int dexBonus = ComputeStatBonus(StatType.Dex); - int intBonus = ComputeStatBonus(StatType.Int); - - if (strBonus != 0 || dexBonus != 0 || intBonus != 0) - { - string modName = Serial.ToString(); - - if (strBonus != 0) - from.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero)); - - if (dexBonus != 0) - from.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero)); - - if (intBonus != 0) - from.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero)); - } - - return base.OnEquip(from); - } - - public override void OnRemoved(IEntity parent) - { - if (parent is Mobile m) - { - string modName = Serial.ToString(); - - m.RemoveStatMod($"{modName}Str"); - m.RemoveStatMod($"{modName}Dex"); - m.RemoveStatMod($"{modName}Int"); - - if (Core.AOS) - SkillBonuses.Remove(); - - m.Delta(MobileDelta.Armor); // Tell them armor rating has changed - m.CheckStatTimers(); - } - - base.OnRemoved(parent); - } - - private string GetNameString() => Name ?? $"#{LabelNumber}"; - - public override void AddNameProperty(ObjectPropertyList list) - { - var oreType = m_Resource switch - { - CraftResource.DullCopper => 1053108, - CraftResource.ShadowIron => 1053107, - CraftResource.Copper => 1053106, - CraftResource.Bronze => 1053105, - CraftResource.Gold => 1053104, - CraftResource.Agapite => 1053103, - CraftResource.Verite => 1053102, - CraftResource.Valorite => 1053101, - CraftResource.SpinedLeather => 1061118, - CraftResource.HornedLeather => 1061117, - CraftResource.BarbedLeather => 1061116, - CraftResource.RedScales => 1060814, - CraftResource.YellowScales => 1060818, - CraftResource.BlackScales => 1060820, - CraftResource.GreenScales => 1060819, - CraftResource.WhiteScales => 1060821, - CraftResource.BlueScales => 1060815, - _ => 0 - }; - - if (m_Quality == ArmorQuality.Exceptional) - { - if (oreType != 0) - list.Add(1053100, "#{0}\t{1}", oreType, GetNameString()); // exceptional ~1_oretype~ ~2_armortype~ - else - list.Add(1050040, GetNameString()); // exceptional ~1_ITEMNAME~ - } - else - { - if (oreType != 0) - list.Add(1053099, "#{0}\t{1}", oreType, GetNameString()); // ~1_oretype~ ~2_armortype~ - else if (Name == null) - list.Add(LabelNumber); - else - list.Add(Name); - } - } - - public override bool AllowEquippedCast(Mobile from) - { - if (base.AllowEquippedCast(from)) - return true; - - return Attributes.SpellChanneling != 0; - } - - public virtual int GetLuckBonus() - { - CraftResourceInfo resInfo = CraftResources.GetInfo(m_Resource); - - CraftAttributeInfo attrInfo = resInfo?.AttributeInfo; - - if (attrInfo == null) - return 0; - - return attrInfo.ArmorLuck; - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_Crafter != null) - list.Add(1050043, m_Crafter.Name); // crafted by ~1_NAME~ - - if (m_FactionState != null) - list.Add(1041350); // faction item - - if (RequiredRace == Race.Elf) - list.Add(1075086); // Elves Only - - SkillBonuses.GetProperties(list); - - int prop; - - if ((prop = ArtifactRarity) > 0) - list.Add(1061078, prop.ToString()); // artifact rarity ~1_val~ - - if ((prop = Attributes.WeaponDamage) != 0) - list.Add(1060401, prop.ToString()); // damage increase ~1_val~% - - if ((prop = Attributes.DefendChance) != 0) - list.Add(1060408, prop.ToString()); // defense chance increase ~1_val~% - - if ((prop = Attributes.BonusDex) != 0) - list.Add(1060409, prop.ToString()); // dexterity bonus ~1_val~ - - if ((prop = Attributes.EnhancePotions) != 0) - list.Add(1060411, prop.ToString()); // enhance potions ~1_val~% - - if ((prop = Attributes.CastRecovery) != 0) - list.Add(1060412, prop.ToString()); // faster cast recovery ~1_val~ - - if ((prop = Attributes.CastSpeed) != 0) - list.Add(1060413, prop.ToString()); // faster casting ~1_val~ - - if ((prop = Attributes.AttackChance) != 0) - list.Add(1060415, prop.ToString()); // hit chance increase ~1_val~% - - if ((prop = Attributes.BonusHits) != 0) - list.Add(1060431, prop.ToString()); // hit point increase ~1_val~ - - if ((prop = Attributes.BonusInt) != 0) - list.Add(1060432, prop.ToString()); // intelligence bonus ~1_val~ - - if ((prop = Attributes.LowerManaCost) != 0) - list.Add(1060433, prop.ToString()); // lower mana cost ~1_val~% - - if ((prop = Attributes.LowerRegCost) != 0) - list.Add(1060434, prop.ToString()); // lower reagent cost ~1_val~% - - if ((prop = GetLowerStatReq()) != 0) - list.Add(1060435, prop.ToString()); // lower requirements ~1_val~% - - if ((prop = GetLuckBonus() + Attributes.Luck) != 0) - list.Add(1060436, prop.ToString()); // luck ~1_val~ - - if (ArmorAttributes.MageArmor != 0) - list.Add(1060437); // mage armor - - if ((prop = Attributes.BonusMana) != 0) - list.Add(1060439, prop.ToString()); // mana increase ~1_val~ - - if ((prop = Attributes.RegenMana) != 0) - list.Add(1060440, prop.ToString()); // mana regeneration ~1_val~ - - if (Attributes.NightSight != 0) - list.Add(1060441); // night sight - - if ((prop = Attributes.ReflectPhysical) != 0) - list.Add(1060442, prop.ToString()); // reflect physical damage ~1_val~% - - if ((prop = Attributes.RegenStam) != 0) - list.Add(1060443, prop.ToString()); // stamina regeneration ~1_val~ - - if ((prop = Attributes.RegenHits) != 0) - list.Add(1060444, prop.ToString()); // hit point regeneration ~1_val~ - - if ((prop = ArmorAttributes.SelfRepair) != 0) - list.Add(1060450, prop.ToString()); // self repair ~1_val~ - - if (Attributes.SpellChanneling != 0) - list.Add(1060482); // spell channeling - - if ((prop = Attributes.SpellDamage) != 0) - list.Add(1060483, prop.ToString()); // spell damage increase ~1_val~% - - if ((prop = Attributes.BonusStam) != 0) - list.Add(1060484, prop.ToString()); // stamina increase ~1_val~ - - if ((prop = Attributes.BonusStr) != 0) - list.Add(1060485, prop.ToString()); // strength bonus ~1_val~ - - if ((prop = Attributes.WeaponSpeed) != 0) - list.Add(1060486, prop.ToString()); // swing speed increase ~1_val~% - - if (Core.ML && (prop = Attributes.IncreasedKarmaLoss) != 0) - list.Add(1075210, prop.ToString()); // Increased Karma Loss ~1val~% - - AddResistanceProperties(list); - - if ((prop = GetDurabilityBonus()) > 0) - list.Add(1060410, prop.ToString()); // durability ~1_val~% - - if ((prop = ComputeStatReq(StatType.Str)) > 0) - list.Add(1061170, prop.ToString()); // strength requirement ~1_val~ - - if (m_HitPoints >= 0 && m_MaxHitPoints > 0) - list.Add(1060639, "{0}\t{1}", m_HitPoints, m_MaxHitPoints); // durability ~1_val~ / ~2_val~ - } - - public override void OnSingleClick(Mobile from) - { - List attrs = new List(); - - if (DisplayLootType) - { - if (LootType == LootType.Blessed) - attrs.Add(new EquipInfoAttribute(1038021)); // blessed - else if (LootType == LootType.Cursed) - attrs.Add(new EquipInfoAttribute(1049643)); // cursed - } - - if (m_FactionState != null) - attrs.Add(new EquipInfoAttribute(1041350)); // faction item - - if (m_Quality == ArmorQuality.Exceptional) - attrs.Add(new EquipInfoAttribute(1018305 - (int)m_Quality)); - - if (m_Identified || from.AccessLevel >= AccessLevel.GameMaster) - { - if (m_Durability != ArmorDurabilityLevel.Regular) - attrs.Add(new EquipInfoAttribute(1038000 + (int)m_Durability)); - - if (m_Protection > ArmorProtectionLevel.Regular && m_Protection <= ArmorProtectionLevel.Invulnerability) - attrs.Add(new EquipInfoAttribute(1038005 + (int)m_Protection)); - } - else if (m_Durability != ArmorDurabilityLevel.Regular || (m_Protection > ArmorProtectionLevel.Regular && - m_Protection <= ArmorProtectionLevel.Invulnerability)) - { - attrs.Add(new EquipInfoAttribute(1038000)); // Unidentified - } - - int number; - - if (Name == null) - { - number = LabelNumber; - } - else - { - LabelTo(from, Name); - number = 1041000; - } - - if (attrs.Count == 0 && Crafter == null && Name != null) - return; - - EquipmentInfo eqInfo = new EquipmentInfo(number, m_Crafter, false, attrs.ToArray()); - - from.Send(new DisplayEquipmentInfo(this, eqInfo)); - } - - [Flags] - private enum SaveFlag - { - None = 0x00000000, - Attributes = 0x00000001, - ArmorAttributes = 0x00000002, - PhysicalBonus = 0x00000004, - FireBonus = 0x00000008, - ColdBonus = 0x00000010, - PoisonBonus = 0x00000020, - EnergyBonus = 0x00000040, - Identified = 0x00000080, - MaxHitPoints = 0x00000100, - HitPoints = 0x00000200, - Crafter = 0x00000400, - Quality = 0x00000800, - Durability = 0x00001000, - Protection = 0x00002000, - Resource = 0x00004000, - BaseArmor = 0x00008000, - StrBonus = 0x00010000, - DexBonus = 0x00020000, - IntBonus = 0x00040000, - StrReq = 0x00080000, - DexReq = 0x00100000, - IntReq = 0x00200000, - MedAllowance = 0x00400000, - SkillBonuses = 0x00800000, - PlayerConstructed = 0x01000000 - } - - private FactionItem m_FactionState; - - public FactionItem FactionItemState - { - get => m_FactionState; - set - { - m_FactionState = value; - - if (m_FactionState == null) - Hue = CraftResources.GetHue(Resource); - - LootType = m_FactionState == null ? LootType.Regular : LootType.Blessed; - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Engines.Craft; +using Server.Ethics; +using Server.Factions; +using Server.Network; +using Server.Utilities; +using AMA = Server.Items.ArmorMeditationAllowance; +using AMT = Server.Items.ArmorMaterialType; + +namespace Server.Items +{ + public abstract class BaseArmor : Item, IScissorable, IFactionItem, ICraftable, IWearableDurability + { + // Overridable values. These values are provided to override the defaults which get defined in the individual armor scripts. + private int m_ArmorBase = -1; + private Mobile m_Crafter; + private ArmorDurabilityLevel m_Durability; + + private FactionItem m_FactionState; + private int m_HitPoints; + private bool m_Identified; + + /* Armor internals work differently now (Jun 19 2003) + * + * The attributes defined below default to -1. + * If the value is -1, the corresponding virtual 'Aos/Old' property is used. + * If not, the attribute value itself is used. Here's the list: + * - ArmorBase + * - StrBonus + * - DexBonus + * - IntBonus + * - StrReq + * - DexReq + * - IntReq + * - MeditationAllowance + */ + + // Instance values. These values must are unique to each armor piece. + private int m_MaxHitPoints; + private AMA m_Meditate = (AMA)(-1); + private int m_PhysicalBonus, m_FireBonus, m_ColdBonus, m_PoisonBonus, m_EnergyBonus; + private ArmorProtectionLevel m_Protection; + private ArmorQuality m_Quality; + private CraftResource m_Resource; + private int m_StrBonus = -1, m_DexBonus = -1, m_IntBonus = -1; + private int m_StrReq = -1, m_DexReq = -1, m_IntReq = -1; + + public BaseArmor(Serial serial) : base(serial) + { + } + + public BaseArmor(int itemID) : base(itemID) + { + m_Quality = ArmorQuality.Regular; + m_Durability = ArmorDurabilityLevel.Regular; + m_Crafter = null; + + m_Resource = DefaultResource; + Hue = CraftResources.GetHue(m_Resource); + + m_HitPoints = m_MaxHitPoints = Utility.RandomMinMax(InitMinHits, InitMaxHits); + + Layer = (Layer)ItemData.Quality; + + Attributes = new AosAttributes(this); + ArmorAttributes = new AosArmorAttributes(this); + SkillBonuses = new AosSkillBonuses(this); + } + + public virtual bool AllowMaleWearer => true; + public virtual bool AllowFemaleWearer => true; + + public abstract AMT MaterialType { get; } + + public virtual int RevertArmorBase => ArmorBase; + public virtual int ArmorBase => 0; + + public virtual AMA DefMedAllowance => AMA.None; + public virtual AMA AosMedAllowance => DefMedAllowance; + public virtual AMA OldMedAllowance => DefMedAllowance; + + public virtual int AosStrBonus => 0; + public virtual int AosDexBonus => 0; + public virtual int AosIntBonus => 0; + public virtual int AosStrReq => 0; + public virtual int AosDexReq => 0; + public virtual int AosIntReq => 0; + + public virtual int OldStrBonus => 0; + public virtual int OldDexBonus => 0; + public virtual int OldIntBonus => 0; + public virtual int OldStrReq => 0; + public virtual int OldDexReq => 0; + public virtual int OldIntReq => 0; + + [CommandProperty(AccessLevel.GameMaster)] + public AMA MeditationAllowance + { + get => m_Meditate == (AMA)(-1) ? Core.AOS ? AosMedAllowance : OldMedAllowance : m_Meditate; + set => m_Meditate = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int BaseArmorRating + { + get + { + if (m_ArmorBase == -1) + return ArmorBase; + return m_ArmorBase; + } + set + { + m_ArmorBase = value; + Invalidate(); + } + } + + public double BaseArmorRatingScaled => BaseArmorRating * ArmorScalar; + + public virtual double ArmorRating + { + get + { + var ar = BaseArmorRating; + + if (m_Protection != ArmorProtectionLevel.Regular) + ar += 10 + 5 * (int)m_Protection; + + switch (m_Resource) + { + case CraftResource.DullCopper: + ar += 2; + break; + case CraftResource.ShadowIron: + ar += 4; + break; + case CraftResource.Copper: + ar += 6; + break; + case CraftResource.Bronze: + ar += 8; + break; + case CraftResource.Gold: + ar += 10; + break; + case CraftResource.Agapite: + ar += 12; + break; + case CraftResource.Verite: + ar += 14; + break; + case CraftResource.Valorite: + ar += 16; + break; + case CraftResource.SpinedLeather: + ar += 10; + break; + case CraftResource.HornedLeather: + ar += 13; + break; + case CraftResource.BarbedLeather: + ar += 16; + break; + } + + ar += -8 + 8 * (int)m_Quality; + return ScaleArmorByDurability(ar); + } + } + + public double ArmorRatingScaled => ArmorRating * ArmorScalar; + + [CommandProperty(AccessLevel.GameMaster)] + public int StrBonus + { + get => m_StrBonus == -1 ? Core.AOS ? AosStrBonus : OldStrBonus : m_StrBonus; + set + { + m_StrBonus = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int DexBonus + { + get => m_DexBonus == -1 ? Core.AOS ? AosDexBonus : OldDexBonus : m_DexBonus; + set + { + m_DexBonus = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int IntBonus + { + get => m_IntBonus == -1 ? Core.AOS ? AosIntBonus : OldIntBonus : m_IntBonus; + set + { + m_IntBonus = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int StrRequirement + { + get => m_StrReq == -1 ? Core.AOS ? AosStrReq : OldStrReq : m_StrReq; + set + { + m_StrReq = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int DexRequirement + { + get => m_DexReq == -1 ? Core.AOS ? AosDexReq : OldDexReq : m_DexReq; + set + { + m_DexReq = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int IntRequirement + { + get => m_IntReq == -1 ? Core.AOS ? AosIntReq : OldIntReq : m_IntReq; + set + { + m_IntReq = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Identified + { + get => m_Identified; + set + { + m_Identified = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool PlayerConstructed { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public CraftResource Resource + { + get => m_Resource; + set + { + if (m_Resource != value) + { + UnscaleDurability(); + + m_Resource = value; + + if (CraftItem.RetainsColor(GetType())) Hue = CraftResources.GetHue(m_Resource); + + Invalidate(); + InvalidateProperties(); + + (Parent as Mobile)?.UpdateResistances(); + + ScaleDurability(); + } + } + } + + public virtual double ArmorScalar + { + get + { + var pos = (int)BodyPosition; + + if (pos >= 0 && pos < ArmorScalars.Length) + return ArmorScalars[pos]; + + return 1.0; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Crafter + { + get => m_Crafter; + set + { + m_Crafter = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public ArmorQuality Quality + { + get => m_Quality; + set + { + UnscaleDurability(); + m_Quality = value; + Invalidate(); + InvalidateProperties(); + ScaleDurability(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public ArmorDurabilityLevel Durability + { + get => m_Durability; + set + { + UnscaleDurability(); + m_Durability = value; + ScaleDurability(); + InvalidateProperties(); + } + } + + public virtual int ArtifactRarity => 0; + + [CommandProperty(AccessLevel.GameMaster)] + public ArmorProtectionLevel ProtectionLevel + { + get => m_Protection; + set + { + if (m_Protection != value) + { + m_Protection = value; + + Invalidate(); + InvalidateProperties(); + + (Parent as Mobile)?.UpdateResistances(); + } + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public AosAttributes Attributes { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public AosArmorAttributes ArmorAttributes { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public AosSkillBonuses SkillBonuses { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int PhysicalBonus + { + get => m_PhysicalBonus; + set + { + m_PhysicalBonus = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int FireBonus + { + get => m_FireBonus; + set + { + m_FireBonus = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int ColdBonus + { + get => m_ColdBonus; + set + { + m_ColdBonus = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int PoisonBonus + { + get => m_PoisonBonus; + set + { + m_PoisonBonus = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int EnergyBonus + { + get => m_EnergyBonus; + set + { + m_EnergyBonus = value; + InvalidateProperties(); + } + } + + public virtual int BasePhysicalResistance => 0; + public virtual int BaseFireResistance => 0; + public virtual int BaseColdResistance => 0; + public virtual int BasePoisonResistance => 0; + public virtual int BaseEnergyResistance => 0; + + public override int PhysicalResistance => BasePhysicalResistance + GetProtOffset() + + GetResourceAttrs().ArmorPhysicalResist + m_PhysicalBonus; + + public override int FireResistance => + BaseFireResistance + GetProtOffset() + GetResourceAttrs().ArmorFireResist + m_FireBonus; + + public override int ColdResistance => + BaseColdResistance + GetProtOffset() + GetResourceAttrs().ArmorColdResist + m_ColdBonus; + + public override int PoisonResistance => + BasePoisonResistance + GetProtOffset() + GetResourceAttrs().ArmorPoisonResist + m_PoisonBonus; + + public override int EnergyResistance => + BaseEnergyResistance + GetProtOffset() + GetResourceAttrs().ArmorEnergyResist + m_EnergyBonus; + + [CommandProperty(AccessLevel.GameMaster)] + public ArmorBodyType BodyPosition + { + get + { + return Layer switch + { + Layer.Neck => ArmorBodyType.Gorget, + Layer.TwoHanded => ArmorBodyType.Shield, + Layer.Gloves => ArmorBodyType.Gloves, + Layer.Helm => ArmorBodyType.Helmet, + Layer.Arms => ArmorBodyType.Arms, + Layer.InnerLegs => ArmorBodyType.Legs, + Layer.OuterLegs => ArmorBodyType.Legs, + Layer.Pants => ArmorBodyType.Legs, + Layer.InnerTorso => ArmorBodyType.Chest, + Layer.OuterTorso => ArmorBodyType.Chest, + Layer.Shirt => ArmorBodyType.Chest, + _ => ArmorBodyType.Gorget + }; + } + } + + public static double[] ArmorScalars { get; set; } = { 0.07, 0.07, 0.14, 0.15, 0.22, 0.35 }; + + public virtual CraftResource DefaultResource => CraftResource.Iron; + + public virtual Race RequiredRace => null; + + [Hue] + [CommandProperty(AccessLevel.GameMaster)] + public override int Hue + { + get => base.Hue; + set + { + base.Hue = value; + InvalidateProperties(); + } + } + + public int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, + CraftItem craftItem, int resHue + ) + { + Quality = (ArmorQuality)quality; + + if (makersMark) + Crafter = from; + + var resourceType = typeRes ?? craftItem.Resources[0].ItemType; + + Resource = CraftResources.GetFromType(resourceType); + PlayerConstructed = true; + + var context = craftSystem.GetContext(from); + + if (context?.DoNotColor == true) + Hue = 0; + + if (Quality == ArmorQuality.Exceptional) + { + if (!(Core.ML && this is BaseShield) + ) // Guessed Core.ML removed exceptional resist bonuses from crafted shields + DistributeBonuses( + tool is BaseRunicTool ? 6 : + Core.SE ? 15 : 14 + ); // Not sure since when, but right now 15 points are added, not 14. + + if (Core.ML && !(this is BaseShield)) + { + var bonus = (int)(from.Skills.ArmsLore.Value / 20); + + for (var i = 0; i < bonus; i++) + switch (Utility.Random(5)) + { + case 0: + m_PhysicalBonus++; + break; + case 1: + m_FireBonus++; + break; + case 2: + m_ColdBonus++; + break; + case 3: + m_EnergyBonus++; + break; + case 4: + m_PoisonBonus++; + break; + } + + from.CheckSkill(SkillName.ArmsLore, 0, 100); + } + } + + if (Core.AOS) + (tool as BaseRunicTool)?.ApplyAttributesTo(this); + + return quality; + } + + public FactionItem FactionItemState + { + get => m_FactionState; + set + { + m_FactionState = value; + + if (m_FactionState == null) + Hue = CraftResources.GetHue(Resource); + + LootType = m_FactionState == null ? LootType.Regular : LootType.Blessed; + } + } + + public bool Scissor(Mobile from, Scissors scissors) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(502437); // Items you wish to cut must be in your backpack. + return false; + } + + if (Ethic.IsImbued(this)) + { + from.SendLocalizedMessage(502440); // Scissors can not be used on that to produce anything. + return false; + } + + var system = DefTailoring.CraftSystem; + + var item = system.CraftItems.SearchFor(GetType()); + + if (item?.Resources.Count == 1 && item.Resources[0].Amount >= 2) + try + { + var res = (Item)ActivatorUtil.CreateInstance(CraftResources.GetInfo(m_Resource).ResourceTypes[0]); + + ScissorHelper(from, res, PlayerConstructed ? item.Resources[0].Amount / 2 : 1); + return true; + } + catch + { + // ignored + } + + from.SendLocalizedMessage(502440); // Scissors can not be used on that to produce anything. + return false; + } + + public virtual bool CanFortify => true; + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxHitPoints + { + get => m_MaxHitPoints; + set + { + m_MaxHitPoints = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int HitPoints + { + get => m_HitPoints; + set + { + if (value != m_HitPoints && MaxHitPoints > 0) + { + m_HitPoints = value; + + if (m_HitPoints < 0) + Delete(); + else if (m_HitPoints > MaxHitPoints) + m_HitPoints = MaxHitPoints; + + InvalidateProperties(); + } + } + } + + public virtual int InitMinHits => 0; + public virtual int InitMaxHits => 0; + + public void UnscaleDurability() + { + var scale = 100 + GetDurabilityBonus(); + + m_HitPoints = (m_HitPoints * 100 + (scale - 1)) / scale; + m_MaxHitPoints = (m_MaxHitPoints * 100 + (scale - 1)) / scale; + InvalidateProperties(); + } + + public void ScaleDurability() + { + var scale = 100 + GetDurabilityBonus(); + + m_HitPoints = (m_HitPoints * scale + 99) / 100; + m_MaxHitPoints = (m_MaxHitPoints * scale + 99) / 100; + InvalidateProperties(); + } + + public virtual int OnHit(BaseWeapon weapon, int damageTaken) + { + var halfar = ArmorRating / 2.0; + var absorbed = (int)(halfar + halfar * Utility.RandomDouble()); + + // Don't go below zero + damageTaken = Math.Min(absorbed, damageTaken); + + if (absorbed < 2) + absorbed = 2; + + if (Utility.Random(100) < 25) // 25% chance to lower durability + { + if (Core.AOS && ArmorAttributes.SelfRepair > Utility.Random(10)) + { + HitPoints += 2; + } + else + { + int wear; + + if (weapon.Type == WeaponType.Bashing) + wear = absorbed / 2; + else + wear = Utility.Random(2); + + if (wear > 0 && m_MaxHitPoints > 0) + { + if (m_HitPoints >= wear) + { + HitPoints -= wear; + wear = 0; + } + else + { + wear -= HitPoints; + HitPoints = 0; + } + + if (wear > 0) + { + if (m_MaxHitPoints > wear) + { + MaxHitPoints -= wear; + + if (Parent is Mobile mobile) + mobile.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1061121 + ); // Your equipment is severely damaged. + } + else + { + Delete(); + } + } + } + } + } + + return damageTaken; + } + + public override void OnAfterDuped(Item newItem) + { + if (!(newItem is BaseArmor armor)) + return; + + armor.Attributes = new AosAttributes(newItem, Attributes); + armor.ArmorAttributes = new AosArmorAttributes(newItem, ArmorAttributes); + armor.SkillBonuses = new AosSkillBonuses(newItem, SkillBonuses); + } + + public int ComputeStatReq(StatType type) + { + int v; + + if (type == StatType.Str) + v = StrRequirement; + else if (type == StatType.Dex) + v = DexRequirement; + else + v = IntRequirement; + + return AOS.Scale(v, 100 - GetLowerStatReq()); + } + + public int ComputeStatBonus(StatType type) + { + if (type == StatType.Str) + return StrBonus + Attributes.BonusStr; + if (type == StatType.Dex) + return DexBonus + Attributes.BonusDex; + return IntBonus + Attributes.BonusInt; + } + + public void DistributeBonuses(int amount) + { + for (var i = 0; i < amount; ++i) + switch (Utility.Random(5)) + { + case 0: + ++m_PhysicalBonus; + break; + case 1: + ++m_FireBonus; + break; + case 2: + ++m_ColdBonus; + break; + case 3: + ++m_PoisonBonus; + break; + case 4: + ++m_EnergyBonus; + break; + } + + InvalidateProperties(); + } + + public CraftAttributeInfo GetResourceAttrs() + { + var info = CraftResources.GetInfo(m_Resource); + + if (info == null) + return CraftAttributeInfo.Blank; + + return info.AttributeInfo; + } + + public int GetProtOffset() + { + return m_Protection switch + { + ArmorProtectionLevel.Guarding => 1, + ArmorProtectionLevel.Hardening => 2, + ArmorProtectionLevel.Fortification => 3, + ArmorProtectionLevel.Invulnerability => 4, + _ => 0 + }; + } + + public int GetDurabilityBonus() + { + var bonus = 0; + + if (m_Quality == ArmorQuality.Exceptional) + bonus += 20; + + switch (m_Durability) + { + case ArmorDurabilityLevel.Durable: + bonus += 20; + break; + case ArmorDurabilityLevel.Substantial: + bonus += 50; + break; + case ArmorDurabilityLevel.Massive: + bonus += 70; + break; + case ArmorDurabilityLevel.Fortified: + bonus += 100; + break; + case ArmorDurabilityLevel.Indestructible: + bonus += 120; + break; + } + + if (Core.AOS) + { + bonus += ArmorAttributes.DurabilityBonus; + + var resInfo = CraftResources.GetInfo(m_Resource); + CraftAttributeInfo attrInfo = null; + + if (resInfo != null) + attrInfo = resInfo.AttributeInfo; + + if (attrInfo != null) + bonus += attrInfo.ArmorDurability; + } + + return bonus; + } + + public static void ValidateMobile(Mobile m) + { + for (var i = m.Items.Count - 1; i >= 0; --i) + { + if (i >= m.Items.Count) + continue; + + var item = m.Items[i]; + + if (item is BaseArmor armor) + { + if (armor.RequiredRace != null && m.Race != armor.RequiredRace) + { + if (armor.RequiredRace == Race.Elf) + m.SendLocalizedMessage(1072203); // Only Elves may use this. + else + m.SendMessage("Only {0} may use this.", armor.RequiredRace.PluralName); + + m.AddToBackpack(armor); + } + else if (!armor.AllowMaleWearer && !m.Female && m.AccessLevel < AccessLevel.GameMaster) + { + if (armor.AllowFemaleWearer) + m.SendLocalizedMessage(1010388); // Only females can wear this. + else + m.SendMessage("You may not wear this."); + + m.AddToBackpack(armor); + } + else if (!armor.AllowFemaleWearer && m.Female && m.AccessLevel < AccessLevel.GameMaster) + { + if (armor.AllowMaleWearer) + m.SendLocalizedMessage(1063343); // Only males can wear this. + else + m.SendMessage("You may not wear this."); + + m.AddToBackpack(armor); + } + } + } + } + + public int GetLowerStatReq() + { + if (!Core.AOS) + return 0; + + var v = ArmorAttributes.LowerStatReq; + + var info = CraftResources.GetInfo(m_Resource); + + var attrInfo = info?.AttributeInfo; + + if (attrInfo != null) + v += attrInfo.ArmorLowerRequirements; + + if (v > 100) + v = 100; + + return v; + } + + public override void OnAdded(IEntity parent) + { + if (parent is Mobile from) + { + if (Core.AOS) + SkillBonuses.AddTo(from); + + from.Delta(MobileDelta.Armor); // Tell them armor rating has changed + } + } + + public virtual double ScaleArmorByDurability(double armor) + { + var scale = 100; + + if (m_MaxHitPoints > 0 && m_HitPoints < m_MaxHitPoints) + scale = 50 + 50 * m_HitPoints / m_MaxHitPoints; + + return armor * scale / 100; + } + + protected void Invalidate() + { + (Parent as Mobile)?.Delta(MobileDelta.Armor); // Tell them armor rating has changed + } + + private static void SetSaveFlag(ref SaveFlag flags, SaveFlag toSet, bool setIf) + { + if (setIf) + flags |= toSet; + } + + private static bool GetSaveFlag(SaveFlag flags, SaveFlag toGet) => (flags & toGet) != 0; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(7); // version + + var flags = SaveFlag.None; + + SetSaveFlag(ref flags, SaveFlag.Attributes, !Attributes.IsEmpty); + SetSaveFlag(ref flags, SaveFlag.ArmorAttributes, !ArmorAttributes.IsEmpty); + SetSaveFlag(ref flags, SaveFlag.PhysicalBonus, m_PhysicalBonus != 0); + SetSaveFlag(ref flags, SaveFlag.FireBonus, m_FireBonus != 0); + SetSaveFlag(ref flags, SaveFlag.ColdBonus, m_ColdBonus != 0); + SetSaveFlag(ref flags, SaveFlag.PoisonBonus, m_PoisonBonus != 0); + SetSaveFlag(ref flags, SaveFlag.EnergyBonus, m_EnergyBonus != 0); + SetSaveFlag(ref flags, SaveFlag.Identified, m_Identified); + SetSaveFlag(ref flags, SaveFlag.MaxHitPoints, m_MaxHitPoints != 0); + SetSaveFlag(ref flags, SaveFlag.HitPoints, m_HitPoints != 0); + SetSaveFlag(ref flags, SaveFlag.Crafter, m_Crafter != null); + SetSaveFlag(ref flags, SaveFlag.Quality, m_Quality != ArmorQuality.Regular); + SetSaveFlag(ref flags, SaveFlag.Durability, m_Durability != ArmorDurabilityLevel.Regular); + SetSaveFlag(ref flags, SaveFlag.Protection, m_Protection != ArmorProtectionLevel.Regular); + SetSaveFlag(ref flags, SaveFlag.Resource, m_Resource != DefaultResource); + SetSaveFlag(ref flags, SaveFlag.BaseArmor, m_ArmorBase != -1); + SetSaveFlag(ref flags, SaveFlag.StrBonus, m_StrBonus != -1); + SetSaveFlag(ref flags, SaveFlag.DexBonus, m_DexBonus != -1); + SetSaveFlag(ref flags, SaveFlag.IntBonus, m_IntBonus != -1); + SetSaveFlag(ref flags, SaveFlag.StrReq, m_StrReq != -1); + SetSaveFlag(ref flags, SaveFlag.DexReq, m_DexReq != -1); + SetSaveFlag(ref flags, SaveFlag.IntReq, m_IntReq != -1); + SetSaveFlag(ref flags, SaveFlag.MedAllowance, m_Meditate != (AMA)(-1)); + SetSaveFlag(ref flags, SaveFlag.SkillBonuses, !SkillBonuses.IsEmpty); + SetSaveFlag(ref flags, SaveFlag.PlayerConstructed, PlayerConstructed); + + writer.WriteEncodedInt((int)flags); + + if (GetSaveFlag(flags, SaveFlag.Attributes)) + Attributes.Serialize(writer); + + if (GetSaveFlag(flags, SaveFlag.ArmorAttributes)) + ArmorAttributes.Serialize(writer); + + if (GetSaveFlag(flags, SaveFlag.PhysicalBonus)) + writer.WriteEncodedInt(m_PhysicalBonus); + + if (GetSaveFlag(flags, SaveFlag.FireBonus)) + writer.WriteEncodedInt(m_FireBonus); + + if (GetSaveFlag(flags, SaveFlag.ColdBonus)) + writer.WriteEncodedInt(m_ColdBonus); + + if (GetSaveFlag(flags, SaveFlag.PoisonBonus)) + writer.WriteEncodedInt(m_PoisonBonus); + + if (GetSaveFlag(flags, SaveFlag.EnergyBonus)) + writer.WriteEncodedInt(m_EnergyBonus); + + if (GetSaveFlag(flags, SaveFlag.MaxHitPoints)) + writer.WriteEncodedInt(m_MaxHitPoints); + + if (GetSaveFlag(flags, SaveFlag.HitPoints)) + writer.WriteEncodedInt(m_HitPoints); + + if (GetSaveFlag(flags, SaveFlag.Crafter)) + writer.Write(m_Crafter); + + if (GetSaveFlag(flags, SaveFlag.Quality)) + writer.WriteEncodedInt((int)m_Quality); + + if (GetSaveFlag(flags, SaveFlag.Durability)) + writer.WriteEncodedInt((int)m_Durability); + + if (GetSaveFlag(flags, SaveFlag.Protection)) + writer.WriteEncodedInt((int)m_Protection); + + if (GetSaveFlag(flags, SaveFlag.Resource)) + writer.WriteEncodedInt((int)m_Resource); + + if (GetSaveFlag(flags, SaveFlag.BaseArmor)) + writer.WriteEncodedInt(m_ArmorBase); + + if (GetSaveFlag(flags, SaveFlag.StrBonus)) + writer.WriteEncodedInt(m_StrBonus); + + if (GetSaveFlag(flags, SaveFlag.DexBonus)) + writer.WriteEncodedInt(m_DexBonus); + + if (GetSaveFlag(flags, SaveFlag.IntBonus)) + writer.WriteEncodedInt(m_IntBonus); + + if (GetSaveFlag(flags, SaveFlag.StrReq)) + writer.WriteEncodedInt(m_StrReq); + + if (GetSaveFlag(flags, SaveFlag.DexReq)) + writer.WriteEncodedInt(m_DexReq); + + if (GetSaveFlag(flags, SaveFlag.IntReq)) + writer.WriteEncodedInt(m_IntReq); + + if (GetSaveFlag(flags, SaveFlag.MedAllowance)) + writer.WriteEncodedInt((int)m_Meditate); + + if (GetSaveFlag(flags, SaveFlag.SkillBonuses)) + SkillBonuses.Serialize(writer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 7: + case 6: + case 5: + { + var flags = (SaveFlag)reader.ReadEncodedInt(); + + if (GetSaveFlag(flags, SaveFlag.Attributes)) + Attributes = new AosAttributes(this, reader); + else + Attributes = new AosAttributes(this); + + if (GetSaveFlag(flags, SaveFlag.ArmorAttributes)) + ArmorAttributes = new AosArmorAttributes(this, reader); + else + ArmorAttributes = new AosArmorAttributes(this); + + if (GetSaveFlag(flags, SaveFlag.PhysicalBonus)) + m_PhysicalBonus = reader.ReadEncodedInt(); + + if (GetSaveFlag(flags, SaveFlag.FireBonus)) + m_FireBonus = reader.ReadEncodedInt(); + + if (GetSaveFlag(flags, SaveFlag.ColdBonus)) + m_ColdBonus = reader.ReadEncodedInt(); + + if (GetSaveFlag(flags, SaveFlag.PoisonBonus)) + m_PoisonBonus = reader.ReadEncodedInt(); + + if (GetSaveFlag(flags, SaveFlag.EnergyBonus)) + m_EnergyBonus = reader.ReadEncodedInt(); + + if (GetSaveFlag(flags, SaveFlag.Identified)) + m_Identified = version >= 7 || reader.ReadBool(); + + if (GetSaveFlag(flags, SaveFlag.MaxHitPoints)) + m_MaxHitPoints = reader.ReadEncodedInt(); + + if (GetSaveFlag(flags, SaveFlag.HitPoints)) + m_HitPoints = reader.ReadEncodedInt(); + + if (GetSaveFlag(flags, SaveFlag.Crafter)) + m_Crafter = reader.ReadMobile(); + + if (GetSaveFlag(flags, SaveFlag.Quality)) + m_Quality = (ArmorQuality)reader.ReadEncodedInt(); + else + m_Quality = ArmorQuality.Regular; + + if (version == 5 && m_Quality == ArmorQuality.Low) + m_Quality = ArmorQuality.Regular; + + if (GetSaveFlag(flags, SaveFlag.Durability)) + { + m_Durability = (ArmorDurabilityLevel)reader.ReadEncodedInt(); + + if (m_Durability > ArmorDurabilityLevel.Indestructible) + m_Durability = ArmorDurabilityLevel.Durable; + } + + if (GetSaveFlag(flags, SaveFlag.Protection)) + { + m_Protection = (ArmorProtectionLevel)reader.ReadEncodedInt(); + + if (m_Protection > ArmorProtectionLevel.Invulnerability) + m_Protection = ArmorProtectionLevel.Defense; + } + + if (GetSaveFlag(flags, SaveFlag.Resource)) + m_Resource = (CraftResource)reader.ReadEncodedInt(); + else + m_Resource = DefaultResource; + + if (m_Resource == CraftResource.None) + m_Resource = DefaultResource; + + if (GetSaveFlag(flags, SaveFlag.BaseArmor)) + m_ArmorBase = reader.ReadEncodedInt(); + else + m_ArmorBase = -1; + + if (GetSaveFlag(flags, SaveFlag.StrBonus)) + m_StrBonus = reader.ReadEncodedInt(); + else + m_StrBonus = -1; + + if (GetSaveFlag(flags, SaveFlag.DexBonus)) + m_DexBonus = reader.ReadEncodedInt(); + else + m_DexBonus = -1; + + if (GetSaveFlag(flags, SaveFlag.IntBonus)) + m_IntBonus = reader.ReadEncodedInt(); + else + m_IntBonus = -1; + + if (GetSaveFlag(flags, SaveFlag.StrReq)) + m_StrReq = reader.ReadEncodedInt(); + else + m_StrReq = -1; + + if (GetSaveFlag(flags, SaveFlag.DexReq)) + m_DexReq = reader.ReadEncodedInt(); + else + m_DexReq = -1; + + if (GetSaveFlag(flags, SaveFlag.IntReq)) + m_IntReq = reader.ReadEncodedInt(); + else + m_IntReq = -1; + + if (GetSaveFlag(flags, SaveFlag.MedAllowance)) + m_Meditate = (AMA)reader.ReadEncodedInt(); + else + m_Meditate = (AMA)(-1); + + if (GetSaveFlag(flags, SaveFlag.SkillBonuses)) + SkillBonuses = new AosSkillBonuses(this, reader); + + if (GetSaveFlag(flags, SaveFlag.PlayerConstructed)) + PlayerConstructed = true; + + break; + } + case 4: + { + Attributes = new AosAttributes(this, reader); + ArmorAttributes = new AosArmorAttributes(this, reader); + goto case 3; + } + case 3: + { + m_PhysicalBonus = reader.ReadInt(); + m_FireBonus = reader.ReadInt(); + m_ColdBonus = reader.ReadInt(); + m_PoisonBonus = reader.ReadInt(); + m_EnergyBonus = reader.ReadInt(); + goto case 2; + } + case 2: + case 1: + { + m_Identified = reader.ReadBool(); + goto case 0; + } + case 0: + { + m_ArmorBase = reader.ReadInt(); + m_MaxHitPoints = reader.ReadInt(); + m_HitPoints = reader.ReadInt(); + m_Crafter = reader.ReadMobile(); + m_Quality = (ArmorQuality)reader.ReadInt(); + m_Durability = (ArmorDurabilityLevel)reader.ReadInt(); + m_Protection = (ArmorProtectionLevel)reader.ReadInt(); + + var mat = (AMT)reader.ReadInt(); + + if (m_ArmorBase == RevertArmorBase) + m_ArmorBase = -1; + + /*m_BodyPos = (ArmorBodyType)*/ + reader.ReadInt(); + + if (version < 4) + { + Attributes = new AosAttributes(this); + ArmorAttributes = new AosArmorAttributes(this); + } + + if (version < 3 && m_Quality == ArmorQuality.Exceptional) + DistributeBonuses(6); + + if (version >= 2) + { + m_Resource = (CraftResource)reader.ReadInt(); + } + else + { + var info = reader.ReadInt() switch + { + 0 => OreInfo.Iron, + 1 => OreInfo.DullCopper, + 2 => OreInfo.ShadowIron, + 3 => OreInfo.Copper, + 4 => OreInfo.Bronze, + 5 => OreInfo.Gold, + 6 => OreInfo.Agapite, + 7 => OreInfo.Verite, + 8 => OreInfo.Valorite, + _ => OreInfo.Iron + }; + + m_Resource = CraftResources.GetFromOreInfo(info, mat); + } + + m_StrBonus = reader.ReadInt(); + m_DexBonus = reader.ReadInt(); + m_IntBonus = reader.ReadInt(); + m_StrReq = reader.ReadInt(); + m_DexReq = reader.ReadInt(); + m_IntReq = reader.ReadInt(); + + if (m_StrBonus == OldStrBonus) + m_StrBonus = -1; + + if (m_DexBonus == OldDexBonus) + m_DexBonus = -1; + + if (m_IntBonus == OldIntBonus) + m_IntBonus = -1; + + if (m_StrReq == OldStrReq) + m_StrReq = -1; + + if (m_DexReq == OldDexReq) + m_DexReq = -1; + + if (m_IntReq == OldIntReq) + m_IntReq = -1; + + m_Meditate = (AMA)reader.ReadInt(); + + if (m_Meditate == OldMedAllowance) + m_Meditate = (AMA)(-1); + + if (m_Resource == CraftResource.None) + { + if (mat == ArmorMaterialType.Studded || mat == ArmorMaterialType.Leather) + m_Resource = CraftResource.RegularLeather; + else if (mat == ArmorMaterialType.Spined) + m_Resource = CraftResource.SpinedLeather; + else if (mat == ArmorMaterialType.Horned) + m_Resource = CraftResource.HornedLeather; + else if (mat == ArmorMaterialType.Barbed) + m_Resource = CraftResource.BarbedLeather; + else + m_Resource = CraftResource.Iron; + } + + if (m_MaxHitPoints == 0 && m_HitPoints == 0) + m_HitPoints = m_MaxHitPoints = Utility.RandomMinMax(InitMinHits, InitMaxHits); + + break; + } + } + + SkillBonuses ??= new AosSkillBonuses(this); + + var m = Parent as Mobile; + + if (Core.AOS && m != null) + SkillBonuses.AddTo(m); + + var strBonus = ComputeStatBonus(StatType.Str); + var dexBonus = ComputeStatBonus(StatType.Dex); + var intBonus = ComputeStatBonus(StatType.Int); + + if (m != null && (strBonus != 0 || dexBonus != 0 || intBonus != 0)) + { + var modName = Serial.ToString(); + + if (strBonus != 0) + m.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero)); + + if (dexBonus != 0) + m.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero)); + + if (intBonus != 0) + m.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero)); + } + + m?.CheckStatTimers(); + + if (version < 7) + PlayerConstructed = true; // we don't know, so, assume it's crafted + } + + public override bool AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted) + { + if (!Ethic.CheckTrade(from, to, newOwner, this)) + return false; + + return base.AllowSecureTrade(from, to, newOwner, accepted); + } + + public override bool CanEquip(Mobile from) + { + if (!Ethic.CheckEquip(from, this)) + return false; + + if (from.AccessLevel < AccessLevel.GameMaster) + { + if (RequiredRace != null && from.Race != RequiredRace) + { + if (RequiredRace == Race.Elf) + from.SendLocalizedMessage(1072203); // Only Elves may use this. + else + from.SendMessage("Only {0} may use this.", RequiredRace.PluralName); + + return false; + } + + if (!AllowMaleWearer && !from.Female) + { + if (AllowFemaleWearer) + from.SendLocalizedMessage(1010388); // Only females can wear this. + else + from.SendMessage("You may not wear this."); + + return false; + } + + if (!AllowFemaleWearer && from.Female) + { + if (AllowMaleWearer) + from.SendLocalizedMessage(1063343); // Only males can wear this. + else + from.SendMessage("You may not wear this."); + + return false; + } + + int strBonus = ComputeStatBonus(StatType.Str), strReq = ComputeStatReq(StatType.Str); + int dexBonus = ComputeStatBonus(StatType.Dex), dexReq = ComputeStatReq(StatType.Dex); + int intBonus = ComputeStatBonus(StatType.Int), intReq = ComputeStatReq(StatType.Int); + + if (from.Dex < dexReq || from.Dex + dexBonus < 1) + { + from.SendLocalizedMessage(502077); // You do not have enough dexterity to equip this item. + return false; + } + + if (from.Str < strReq || from.Str + strBonus < 1) + { + from.SendLocalizedMessage(500213); // You are not strong enough to equip that. + return false; + } + + if (from.Int < intReq || from.Int + intBonus < 1) + { + from.SendMessage("You are not smart enough to equip that."); + return false; + } + } + + return base.CanEquip(from); + } + + public override bool CheckPropertyConflict(Mobile m) + { + if (base.CheckPropertyConflict(m)) + return true; + + if (Layer == Layer.Pants) + return m.FindItemOnLayer(Layer.InnerLegs) != null; + + if (Layer == Layer.Shirt) + return m.FindItemOnLayer(Layer.InnerTorso) != null; + + return false; + } + + public override bool OnEquip(Mobile from) + { + from.CheckStatTimers(); + + var strBonus = ComputeStatBonus(StatType.Str); + var dexBonus = ComputeStatBonus(StatType.Dex); + var intBonus = ComputeStatBonus(StatType.Int); + + if (strBonus != 0 || dexBonus != 0 || intBonus != 0) + { + var modName = Serial.ToString(); + + if (strBonus != 0) + from.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero)); + + if (dexBonus != 0) + from.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero)); + + if (intBonus != 0) + from.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero)); + } + + return base.OnEquip(from); + } + + public override void OnRemoved(IEntity parent) + { + if (parent is Mobile m) + { + var modName = Serial.ToString(); + + m.RemoveStatMod($"{modName}Str"); + m.RemoveStatMod($"{modName}Dex"); + m.RemoveStatMod($"{modName}Int"); + + if (Core.AOS) + SkillBonuses.Remove(); + + m.Delta(MobileDelta.Armor); // Tell them armor rating has changed + m.CheckStatTimers(); + } + + base.OnRemoved(parent); + } + + private string GetNameString() => Name ?? $"#{LabelNumber}"; + + public override void AddNameProperty(ObjectPropertyList list) + { + var oreType = m_Resource switch + { + CraftResource.DullCopper => 1053108, + CraftResource.ShadowIron => 1053107, + CraftResource.Copper => 1053106, + CraftResource.Bronze => 1053105, + CraftResource.Gold => 1053104, + CraftResource.Agapite => 1053103, + CraftResource.Verite => 1053102, + CraftResource.Valorite => 1053101, + CraftResource.SpinedLeather => 1061118, + CraftResource.HornedLeather => 1061117, + CraftResource.BarbedLeather => 1061116, + CraftResource.RedScales => 1060814, + CraftResource.YellowScales => 1060818, + CraftResource.BlackScales => 1060820, + CraftResource.GreenScales => 1060819, + CraftResource.WhiteScales => 1060821, + CraftResource.BlueScales => 1060815, + _ => 0 + }; + + if (m_Quality == ArmorQuality.Exceptional) + { + if (oreType != 0) + list.Add(1053100, "#{0}\t{1}", oreType, GetNameString()); // exceptional ~1_oretype~ ~2_armortype~ + else + list.Add(1050040, GetNameString()); // exceptional ~1_ITEMNAME~ + } + else + { + if (oreType != 0) + list.Add(1053099, "#{0}\t{1}", oreType, GetNameString()); // ~1_oretype~ ~2_armortype~ + else if (Name == null) + list.Add(LabelNumber); + else + list.Add(Name); + } + } + + public override bool AllowEquippedCast(Mobile from) + { + if (base.AllowEquippedCast(from)) + return true; + + return Attributes.SpellChanneling != 0; + } + + public virtual int GetLuckBonus() + { + var resInfo = CraftResources.GetInfo(m_Resource); + + var attrInfo = resInfo?.AttributeInfo; + + if (attrInfo == null) + return 0; + + return attrInfo.ArmorLuck; + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_Crafter != null) + list.Add(1050043, m_Crafter.Name); // crafted by ~1_NAME~ + + if (m_FactionState != null) + list.Add(1041350); // faction item + + if (RequiredRace == Race.Elf) + list.Add(1075086); // Elves Only + + SkillBonuses.GetProperties(list); + + int prop; + + if ((prop = ArtifactRarity) > 0) + list.Add(1061078, prop.ToString()); // artifact rarity ~1_val~ + + if ((prop = Attributes.WeaponDamage) != 0) + list.Add(1060401, prop.ToString()); // damage increase ~1_val~% + + if ((prop = Attributes.DefendChance) != 0) + list.Add(1060408, prop.ToString()); // defense chance increase ~1_val~% + + if ((prop = Attributes.BonusDex) != 0) + list.Add(1060409, prop.ToString()); // dexterity bonus ~1_val~ + + if ((prop = Attributes.EnhancePotions) != 0) + list.Add(1060411, prop.ToString()); // enhance potions ~1_val~% + + if ((prop = Attributes.CastRecovery) != 0) + list.Add(1060412, prop.ToString()); // faster cast recovery ~1_val~ + + if ((prop = Attributes.CastSpeed) != 0) + list.Add(1060413, prop.ToString()); // faster casting ~1_val~ + + if ((prop = Attributes.AttackChance) != 0) + list.Add(1060415, prop.ToString()); // hit chance increase ~1_val~% + + if ((prop = Attributes.BonusHits) != 0) + list.Add(1060431, prop.ToString()); // hit point increase ~1_val~ + + if ((prop = Attributes.BonusInt) != 0) + list.Add(1060432, prop.ToString()); // intelligence bonus ~1_val~ + + if ((prop = Attributes.LowerManaCost) != 0) + list.Add(1060433, prop.ToString()); // lower mana cost ~1_val~% + + if ((prop = Attributes.LowerRegCost) != 0) + list.Add(1060434, prop.ToString()); // lower reagent cost ~1_val~% + + if ((prop = GetLowerStatReq()) != 0) + list.Add(1060435, prop.ToString()); // lower requirements ~1_val~% + + if ((prop = GetLuckBonus() + Attributes.Luck) != 0) + list.Add(1060436, prop.ToString()); // luck ~1_val~ + + if (ArmorAttributes.MageArmor != 0) + list.Add(1060437); // mage armor + + if ((prop = Attributes.BonusMana) != 0) + list.Add(1060439, prop.ToString()); // mana increase ~1_val~ + + if ((prop = Attributes.RegenMana) != 0) + list.Add(1060440, prop.ToString()); // mana regeneration ~1_val~ + + if (Attributes.NightSight != 0) + list.Add(1060441); // night sight + + if ((prop = Attributes.ReflectPhysical) != 0) + list.Add(1060442, prop.ToString()); // reflect physical damage ~1_val~% + + if ((prop = Attributes.RegenStam) != 0) + list.Add(1060443, prop.ToString()); // stamina regeneration ~1_val~ + + if ((prop = Attributes.RegenHits) != 0) + list.Add(1060444, prop.ToString()); // hit point regeneration ~1_val~ + + if ((prop = ArmorAttributes.SelfRepair) != 0) + list.Add(1060450, prop.ToString()); // self repair ~1_val~ + + if (Attributes.SpellChanneling != 0) + list.Add(1060482); // spell channeling + + if ((prop = Attributes.SpellDamage) != 0) + list.Add(1060483, prop.ToString()); // spell damage increase ~1_val~% + + if ((prop = Attributes.BonusStam) != 0) + list.Add(1060484, prop.ToString()); // stamina increase ~1_val~ + + if ((prop = Attributes.BonusStr) != 0) + list.Add(1060485, prop.ToString()); // strength bonus ~1_val~ + + if ((prop = Attributes.WeaponSpeed) != 0) + list.Add(1060486, prop.ToString()); // swing speed increase ~1_val~% + + if (Core.ML && (prop = Attributes.IncreasedKarmaLoss) != 0) + list.Add(1075210, prop.ToString()); // Increased Karma Loss ~1val~% + + AddResistanceProperties(list); + + if ((prop = GetDurabilityBonus()) > 0) + list.Add(1060410, prop.ToString()); // durability ~1_val~% + + if ((prop = ComputeStatReq(StatType.Str)) > 0) + list.Add(1061170, prop.ToString()); // strength requirement ~1_val~ + + if (m_HitPoints >= 0 && m_MaxHitPoints > 0) + list.Add(1060639, "{0}\t{1}", m_HitPoints, m_MaxHitPoints); // durability ~1_val~ / ~2_val~ + } + + public override void OnSingleClick(Mobile from) + { + var attrs = new List(); + + if (DisplayLootType) + { + if (LootType == LootType.Blessed) + attrs.Add(new EquipInfoAttribute(1038021)); // blessed + else if (LootType == LootType.Cursed) + attrs.Add(new EquipInfoAttribute(1049643)); // cursed + } + + if (m_FactionState != null) + attrs.Add(new EquipInfoAttribute(1041350)); // faction item + + if (m_Quality == ArmorQuality.Exceptional) + attrs.Add(new EquipInfoAttribute(1018305 - (int)m_Quality)); + + if (m_Identified || from.AccessLevel >= AccessLevel.GameMaster) + { + if (m_Durability != ArmorDurabilityLevel.Regular) + attrs.Add(new EquipInfoAttribute(1038000 + (int)m_Durability)); + + if (m_Protection > ArmorProtectionLevel.Regular && m_Protection <= ArmorProtectionLevel.Invulnerability) + attrs.Add(new EquipInfoAttribute(1038005 + (int)m_Protection)); + } + else if (m_Durability != ArmorDurabilityLevel.Regular || m_Protection > ArmorProtectionLevel.Regular && + m_Protection <= ArmorProtectionLevel.Invulnerability) + { + attrs.Add(new EquipInfoAttribute(1038000)); // Unidentified + } + + int number; + + if (Name == null) + { + number = LabelNumber; + } + else + { + LabelTo(from, Name); + number = 1041000; + } + + if (attrs.Count == 0 && Crafter == null && Name != null) + return; + + var eqInfo = new EquipmentInfo(number, m_Crafter, false, attrs.ToArray()); + + from.Send(new DisplayEquipmentInfo(this, eqInfo)); + } + + [Flags] + private enum SaveFlag + { + None = 0x00000000, + Attributes = 0x00000001, + ArmorAttributes = 0x00000002, + PhysicalBonus = 0x00000004, + FireBonus = 0x00000008, + ColdBonus = 0x00000010, + PoisonBonus = 0x00000020, + EnergyBonus = 0x00000040, + Identified = 0x00000080, + MaxHitPoints = 0x00000100, + HitPoints = 0x00000200, + Crafter = 0x00000400, + Quality = 0x00000800, + Durability = 0x00001000, + Protection = 0x00002000, + Resource = 0x00004000, + BaseArmor = 0x00008000, + StrBonus = 0x00010000, + DexBonus = 0x00020000, + IntBonus = 0x00040000, + StrReq = 0x00080000, + DexReq = 0x00100000, + IntReq = 0x00200000, + MedAllowance = 0x00400000, + SkillBonuses = 0x00800000, + PlayerConstructed = 0x01000000 + } + } +} diff --git a/Projects/UOContent/Items/Armor/Bone/BoneArms.cs b/Projects/UOContent/Items/Armor/Bone/BoneArms.cs index 5244b105d..905926843 100644 --- a/Projects/UOContent/Items/Armor/Bone/BoneArms.cs +++ b/Projects/UOContent/Items/Armor/Bone/BoneArms.cs @@ -1,48 +1,48 @@ -namespace Server.Items -{ - [Flippable(0x144e, 0x1453)] - public class BoneArms : BaseArmor - { - [Constructible] - public BoneArms() : base(0x144E) => Weight = 2.0; - - public BoneArms(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 4; - public override int BasePoisonResistance => 2; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 25; - public override int InitMaxHits => 30; - - public override int AosStrReq => 55; - public override int OldStrReq => 40; - - public override int OldDexBonus => -2; - - public override int ArmorBase => 30; - public override int RevertArmorBase => 4; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Bone; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - - if (Weight == 1.0) - Weight = 2.0; - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x144e, 0x1453)] + public class BoneArms : BaseArmor + { + [Constructible] + public BoneArms() : base(0x144E) => Weight = 2.0; + + public BoneArms(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 4; + public override int BasePoisonResistance => 2; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 25; + public override int InitMaxHits => 30; + + public override int AosStrReq => 55; + public override int OldStrReq => 40; + + public override int OldDexBonus => -2; + + public override int ArmorBase => 30; + public override int RevertArmorBase => 4; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Bone; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(0); + + if (Weight == 1.0) + Weight = 2.0; + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Bone/BoneChest.cs b/Projects/UOContent/Items/Armor/Bone/BoneChest.cs index c42f47329..c276cb920 100644 --- a/Projects/UOContent/Items/Armor/Bone/BoneChest.cs +++ b/Projects/UOContent/Items/Armor/Bone/BoneChest.cs @@ -1,48 +1,48 @@ -namespace Server.Items -{ - [Flippable(0x144f, 0x1454)] - public class BoneChest : BaseArmor - { - [Constructible] - public BoneChest() : base(0x144F) => Weight = 6.0; - - public BoneChest(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 4; - public override int BasePoisonResistance => 2; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 25; - public override int InitMaxHits => 30; - - public override int AosStrReq => 60; - public override int OldStrReq => 40; - - public override int OldDexBonus => -6; - - public override int ArmorBase => 30; - public override int RevertArmorBase => 11; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Bone; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - - if (Weight == 1.0) - Weight = 6.0; - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x144f, 0x1454)] + public class BoneChest : BaseArmor + { + [Constructible] + public BoneChest() : base(0x144F) => Weight = 6.0; + + public BoneChest(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 4; + public override int BasePoisonResistance => 2; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 25; + public override int InitMaxHits => 30; + + public override int AosStrReq => 60; + public override int OldStrReq => 40; + + public override int OldDexBonus => -6; + + public override int ArmorBase => 30; + public override int RevertArmorBase => 11; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Bone; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(0); + + if (Weight == 1.0) + Weight = 6.0; + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Bone/BoneGloves.cs b/Projects/UOContent/Items/Armor/Bone/BoneGloves.cs index e1e4f5c46..cb00114e8 100644 --- a/Projects/UOContent/Items/Armor/Bone/BoneGloves.cs +++ b/Projects/UOContent/Items/Armor/Bone/BoneGloves.cs @@ -1,48 +1,48 @@ -namespace Server.Items -{ - [Flippable(0x1450, 0x1455)] - public class BoneGloves : BaseArmor - { - [Constructible] - public BoneGloves() : base(0x1450) => Weight = 2.0; - - public BoneGloves(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 4; - public override int BasePoisonResistance => 2; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 25; - public override int InitMaxHits => 30; - - public override int AosStrReq => 55; - public override int OldStrReq => 40; - - public override int OldDexBonus => -1; - - public override int ArmorBase => 30; - public override int RevertArmorBase => 2; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Bone; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - - if (Weight == 1.0) - Weight = 2.0; - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1450, 0x1455)] + public class BoneGloves : BaseArmor + { + [Constructible] + public BoneGloves() : base(0x1450) => Weight = 2.0; + + public BoneGloves(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 4; + public override int BasePoisonResistance => 2; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 25; + public override int InitMaxHits => 30; + + public override int AosStrReq => 55; + public override int OldStrReq => 40; + + public override int OldDexBonus => -1; + + public override int ArmorBase => 30; + public override int RevertArmorBase => 2; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Bone; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(0); + + if (Weight == 1.0) + Weight = 2.0; + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Bone/BoneLegs.cs b/Projects/UOContent/Items/Armor/Bone/BoneLegs.cs index 89a639364..73d318b5e 100644 --- a/Projects/UOContent/Items/Armor/Bone/BoneLegs.cs +++ b/Projects/UOContent/Items/Armor/Bone/BoneLegs.cs @@ -1,45 +1,45 @@ -namespace Server.Items -{ - [Flippable(0x1452, 0x1457)] - public class BoneLegs : BaseArmor - { - [Constructible] - public BoneLegs() : base(0x1452) => Weight = 3.0; - - public BoneLegs(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 4; - public override int BasePoisonResistance => 2; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 25; - public override int InitMaxHits => 30; - - public override int AosStrReq => 55; - public override int OldStrReq => 40; - - public override int OldDexBonus => -4; - - public override int ArmorBase => 30; - public override int RevertArmorBase => 7; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Bone; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1452, 0x1457)] + public class BoneLegs : BaseArmor + { + [Constructible] + public BoneLegs() : base(0x1452) => Weight = 3.0; + + public BoneLegs(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 4; + public override int BasePoisonResistance => 2; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 25; + public override int InitMaxHits => 30; + + public override int AosStrReq => 55; + public override int OldStrReq => 40; + + public override int OldDexBonus => -4; + + public override int ArmorBase => 30; + public override int RevertArmorBase => 7; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Bone; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Chain/ChainChest.cs b/Projects/UOContent/Items/Armor/Chain/ChainChest.cs index 26d00db27..3c50c2cca 100644 --- a/Projects/UOContent/Items/Armor/Chain/ChainChest.cs +++ b/Projects/UOContent/Items/Armor/Chain/ChainChest.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - [Flippable(0x13bf, 0x13c4)] - public class ChainChest : BaseArmor - { - [Constructible] - public ChainChest() : base(0x13BF) => Weight = 7.0; - - public ChainChest(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 4; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 4; - public override int BasePoisonResistance => 1; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 45; - public override int InitMaxHits => 60; - - public override int AosStrReq => 60; - public override int OldStrReq => 20; - - public override int OldDexBonus => -5; - - public override int ArmorBase => 28; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Chainmail; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x13bf, 0x13c4)] + public class ChainChest : BaseArmor + { + [Constructible] + public ChainChest() : base(0x13BF) => Weight = 7.0; + + public ChainChest(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 4; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 4; + public override int BasePoisonResistance => 1; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 45; + public override int InitMaxHits => 60; + + public override int AosStrReq => 60; + public override int OldStrReq => 20; + + public override int OldDexBonus => -5; + + public override int ArmorBase => 28; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Chainmail; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Chain/ChainHatsuburi.cs b/Projects/UOContent/Items/Armor/Chain/ChainHatsuburi.cs index a4ff444a5..f6b1f23ab 100644 --- a/Projects/UOContent/Items/Armor/Chain/ChainHatsuburi.cs +++ b/Projects/UOContent/Items/Armor/Chain/ChainHatsuburi.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class ChainHatsuburi : BaseArmor - { - [Constructible] - public ChainHatsuburi() : base(0x2774) => Weight = 7.0; - - public ChainHatsuburi(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 2; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 2; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 55; - public override int InitMaxHits => 75; - - public override int AosStrReq => 50; - public override int OldStrReq => 50; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Chainmail; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ChainHatsuburi : BaseArmor + { + [Constructible] + public ChainHatsuburi() : base(0x2774) => Weight = 7.0; + + public ChainHatsuburi(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 2; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 2; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 55; + public override int InitMaxHits => 75; + + public override int AosStrReq => 50; + public override int OldStrReq => 50; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Chainmail; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Chain/ChainLegs.cs b/Projects/UOContent/Items/Armor/Chain/ChainLegs.cs index 007bd6d7b..cd4f8dd61 100644 --- a/Projects/UOContent/Items/Armor/Chain/ChainLegs.cs +++ b/Projects/UOContent/Items/Armor/Chain/ChainLegs.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - [Flippable(0x13be, 0x13c3)] - public class ChainLegs : BaseArmor - { - [Constructible] - public ChainLegs() : base(0x13BE) => Weight = 7.0; - - public ChainLegs(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 4; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 4; - public override int BasePoisonResistance => 1; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 45; - public override int InitMaxHits => 60; - - public override int AosStrReq => 60; - public override int OldStrReq => 20; - - public override int OldDexBonus => -3; - - public override int ArmorBase => 28; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Chainmail; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x13be, 0x13c3)] + public class ChainLegs : BaseArmor + { + [Constructible] + public ChainLegs() : base(0x13BE) => Weight = 7.0; + + public ChainLegs(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 4; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 4; + public override int BasePoisonResistance => 1; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 45; + public override int InitMaxHits => 60; + + public override int AosStrReq => 60; + public override int OldStrReq => 20; + + public override int OldDexBonus => -3; + + public override int ArmorBase => 28; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Chainmail; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/DaemonBone/DaemonArms.cs b/Projects/UOContent/Items/Armor/DaemonBone/DaemonArms.cs index 5cbe3efef..0f77c01fb 100644 --- a/Projects/UOContent/Items/Armor/DaemonBone/DaemonArms.cs +++ b/Projects/UOContent/Items/Armor/DaemonBone/DaemonArms.cs @@ -1,60 +1,60 @@ -namespace Server.Items -{ - [Flippable(0x144e, 0x1453)] - public class DaemonArms : BaseArmor - { - [Constructible] - public DaemonArms() : base(0x144E) - { - Weight = 2.0; - Hue = 0x648; - - ArmorAttributes.SelfRepair = 1; - } - - public DaemonArms(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 6; - public override int BaseFireResistance => 6; - public override int BaseColdResistance => 7; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 7; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override int AosStrReq => 55; - public override int OldStrReq => 40; - - public override int OldDexBonus => -2; - - public override int ArmorBase => 46; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Bone; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override int LabelNumber => 1041371; // daemon bone arms - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - if (Weight == 1.0) - Weight = 2.0; - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (ArmorAttributes.SelfRepair == 0) - ArmorAttributes.SelfRepair = 1; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x144e, 0x1453)] + public class DaemonArms : BaseArmor + { + [Constructible] + public DaemonArms() : base(0x144E) + { + Weight = 2.0; + Hue = 0x648; + + ArmorAttributes.SelfRepair = 1; + } + + public DaemonArms(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 6; + public override int BaseFireResistance => 6; + public override int BaseColdResistance => 7; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 7; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override int AosStrReq => 55; + public override int OldStrReq => 40; + + public override int OldDexBonus => -2; + + public override int ArmorBase => 46; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Bone; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override int LabelNumber => 1041371; // daemon bone arms + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + if (Weight == 1.0) + Weight = 2.0; + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (ArmorAttributes.SelfRepair == 0) + ArmorAttributes.SelfRepair = 1; + } + } +} diff --git a/Projects/UOContent/Items/Armor/DaemonBone/DaemonChest.cs b/Projects/UOContent/Items/Armor/DaemonBone/DaemonChest.cs index 356c2504d..f5e98e98a 100644 --- a/Projects/UOContent/Items/Armor/DaemonBone/DaemonChest.cs +++ b/Projects/UOContent/Items/Armor/DaemonBone/DaemonChest.cs @@ -1,60 +1,60 @@ -namespace Server.Items -{ - [Flippable(0x144f, 0x1454)] - public class DaemonChest : BaseArmor - { - [Constructible] - public DaemonChest() : base(0x144F) - { - Weight = 6.0; - Hue = 0x648; - - ArmorAttributes.SelfRepair = 1; - } - - public DaemonChest(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 6; - public override int BaseFireResistance => 6; - public override int BaseColdResistance => 7; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 7; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override int AosStrReq => 60; - public override int OldStrReq => 40; - - public override int OldDexBonus => -6; - - public override int ArmorBase => 46; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Bone; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override int LabelNumber => 1041372; // daemon bone armor - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 6.0; - - if (ArmorAttributes.SelfRepair == 0) - ArmorAttributes.SelfRepair = 1; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x144f, 0x1454)] + public class DaemonChest : BaseArmor + { + [Constructible] + public DaemonChest() : base(0x144F) + { + Weight = 6.0; + Hue = 0x648; + + ArmorAttributes.SelfRepair = 1; + } + + public DaemonChest(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 6; + public override int BaseFireResistance => 6; + public override int BaseColdResistance => 7; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 7; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override int AosStrReq => 60; + public override int OldStrReq => 40; + + public override int OldDexBonus => -6; + + public override int ArmorBase => 46; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Bone; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override int LabelNumber => 1041372; // daemon bone armor + + 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 (Weight == 1.0) + Weight = 6.0; + + if (ArmorAttributes.SelfRepair == 0) + ArmorAttributes.SelfRepair = 1; + } + } +} diff --git a/Projects/UOContent/Items/Armor/DaemonBone/DaemonGloves.cs b/Projects/UOContent/Items/Armor/DaemonBone/DaemonGloves.cs index 1eb125c3e..73ad8ffc9 100644 --- a/Projects/UOContent/Items/Armor/DaemonBone/DaemonGloves.cs +++ b/Projects/UOContent/Items/Armor/DaemonBone/DaemonGloves.cs @@ -1,60 +1,60 @@ -namespace Server.Items -{ - [Flippable(0x1450, 0x1455)] - public class DaemonGloves : BaseArmor - { - [Constructible] - public DaemonGloves() : base(0x1450) - { - Weight = 2.0; - Hue = 0x648; - - ArmorAttributes.SelfRepair = 1; - } - - public DaemonGloves(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 6; - public override int BaseFireResistance => 6; - public override int BaseColdResistance => 7; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 7; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override int AosStrReq => 55; - public override int OldStrReq => 40; - - public override int OldDexBonus => -1; - - public override int ArmorBase => 46; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Bone; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override int LabelNumber => 1041373; // daemon bone gloves - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 2.0; - - if (ArmorAttributes.SelfRepair == 0) - ArmorAttributes.SelfRepair = 1; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1450, 0x1455)] + public class DaemonGloves : BaseArmor + { + [Constructible] + public DaemonGloves() : base(0x1450) + { + Weight = 2.0; + Hue = 0x648; + + ArmorAttributes.SelfRepair = 1; + } + + public DaemonGloves(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 6; + public override int BaseFireResistance => 6; + public override int BaseColdResistance => 7; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 7; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override int AosStrReq => 55; + public override int OldStrReq => 40; + + public override int OldDexBonus => -1; + + public override int ArmorBase => 46; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Bone; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override int LabelNumber => 1041373; // daemon bone gloves + + 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 (Weight == 1.0) + Weight = 2.0; + + if (ArmorAttributes.SelfRepair == 0) + ArmorAttributes.SelfRepair = 1; + } + } +} diff --git a/Projects/UOContent/Items/Armor/DaemonBone/DaemonLegs.cs b/Projects/UOContent/Items/Armor/DaemonBone/DaemonLegs.cs index 05ae30231..32c771118 100644 --- a/Projects/UOContent/Items/Armor/DaemonBone/DaemonLegs.cs +++ b/Projects/UOContent/Items/Armor/DaemonBone/DaemonLegs.cs @@ -1,55 +1,55 @@ -namespace Server.Items -{ - [Flippable(0x1452, 0x1457)] - public class DaemonLegs : BaseArmor - { - [Constructible] - public DaemonLegs() : base(0x1452) - { - Weight = 3.0; - Hue = 0x648; - - ArmorAttributes.SelfRepair = 1; - } - - public DaemonLegs(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 6; - public override int BaseFireResistance => 6; - public override int BaseColdResistance => 7; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 7; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override int AosStrReq => 55; - public override int OldStrReq => 40; - - public override int OldDexBonus => -4; - - public override int ArmorBase => 46; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Bone; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override int LabelNumber => 1041375; // daemon bone leggings - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (ArmorAttributes.SelfRepair == 0) - ArmorAttributes.SelfRepair = 1; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1452, 0x1457)] + public class DaemonLegs : BaseArmor + { + [Constructible] + public DaemonLegs() : base(0x1452) + { + Weight = 3.0; + Hue = 0x648; + + ArmorAttributes.SelfRepair = 1; + } + + public DaemonLegs(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 6; + public override int BaseFireResistance => 6; + public override int BaseColdResistance => 7; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 7; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override int AosStrReq => 55; + public override int OldStrReq => 40; + + public override int OldDexBonus => -4; + + public override int ArmorBase => 46; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Bone; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override int LabelNumber => 1041375; // daemon bone leggings + + 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 (ArmorAttributes.SelfRepair == 0) + ArmorAttributes.SelfRepair = 1; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Dragon/DragonArms.cs b/Projects/UOContent/Items/Armor/Dragon/DragonArms.cs index e9ab07901..400efed19 100644 --- a/Projects/UOContent/Items/Armor/Dragon/DragonArms.cs +++ b/Projects/UOContent/Items/Armor/Dragon/DragonArms.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - [Flippable(0x2657, 0x2658)] - public class DragonArms : BaseArmor - { - [Constructible] - public DragonArms() : base(0x2657) => Weight = 5.0; - - public DragonArms(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 55; - public override int InitMaxHits => 75; - - public override int AosStrReq => 75; - public override int OldStrReq => 20; - - public override int OldDexBonus => -2; - - public override int ArmorBase => 40; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Dragon; - public override CraftResource DefaultResource => CraftResource.RedScales; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 15.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2657, 0x2658)] + public class DragonArms : BaseArmor + { + [Constructible] + public DragonArms() : base(0x2657) => Weight = 5.0; + + public DragonArms(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 55; + public override int InitMaxHits => 75; + + public override int AosStrReq => 75; + public override int OldStrReq => 20; + + public override int OldDexBonus => -2; + + public override int ArmorBase => 40; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Dragon; + public override CraftResource DefaultResource => CraftResource.RedScales; + + 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 (Weight == 1.0) + Weight = 15.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Dragon/DragonChest.cs b/Projects/UOContent/Items/Armor/Dragon/DragonChest.cs index 877661544..175f703c8 100644 --- a/Projects/UOContent/Items/Armor/Dragon/DragonChest.cs +++ b/Projects/UOContent/Items/Armor/Dragon/DragonChest.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - [Flippable(0x2641, 0x2642)] - public class DragonChest : BaseArmor - { - [Constructible] - public DragonChest() : base(0x2641) => Weight = 10.0; - - public DragonChest(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 55; - public override int InitMaxHits => 75; - - public override int AosStrReq => 75; - public override int OldStrReq => 60; - - public override int OldDexBonus => -8; - - public override int ArmorBase => 40; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Dragon; - public override CraftResource DefaultResource => CraftResource.RedScales; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 15.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2641, 0x2642)] + public class DragonChest : BaseArmor + { + [Constructible] + public DragonChest() : base(0x2641) => Weight = 10.0; + + public DragonChest(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 55; + public override int InitMaxHits => 75; + + public override int AosStrReq => 75; + public override int OldStrReq => 60; + + public override int OldDexBonus => -8; + + public override int ArmorBase => 40; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Dragon; + public override CraftResource DefaultResource => CraftResource.RedScales; + + 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 (Weight == 1.0) + Weight = 15.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Dragon/DragonGloves.cs b/Projects/UOContent/Items/Armor/Dragon/DragonGloves.cs index 0a5c2714d..3417b34ea 100644 --- a/Projects/UOContent/Items/Armor/Dragon/DragonGloves.cs +++ b/Projects/UOContent/Items/Armor/Dragon/DragonGloves.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - [Flippable(0x2643, 0x2644)] - public class DragonGloves : BaseArmor - { - [Constructible] - public DragonGloves() : base(0x2643) => Weight = 2.0; - - public DragonGloves(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 55; - public override int InitMaxHits => 75; - - public override int AosStrReq => 75; - public override int OldStrReq => 30; - - public override int OldDexBonus => -2; - - public override int ArmorBase => 40; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Dragon; - public override CraftResource DefaultResource => CraftResource.RedScales; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 2.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2643, 0x2644)] + public class DragonGloves : BaseArmor + { + [Constructible] + public DragonGloves() : base(0x2643) => Weight = 2.0; + + public DragonGloves(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 55; + public override int InitMaxHits => 75; + + public override int AosStrReq => 75; + public override int OldStrReq => 30; + + public override int OldDexBonus => -2; + + public override int ArmorBase => 40; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Dragon; + public override CraftResource DefaultResource => CraftResource.RedScales; + + 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 (Weight == 1.0) + Weight = 2.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Dragon/DragonHelm.cs b/Projects/UOContent/Items/Armor/Dragon/DragonHelm.cs index d732c65ba..5cabc6ed9 100644 --- a/Projects/UOContent/Items/Armor/Dragon/DragonHelm.cs +++ b/Projects/UOContent/Items/Armor/Dragon/DragonHelm.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - [Flippable(0x2645, 0x2646)] - public class DragonHelm : BaseArmor - { - [Constructible] - public DragonHelm() : base(0x2645) => Weight = 5.0; - - public DragonHelm(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 55; - public override int InitMaxHits => 75; - - public override int AosStrReq => 75; - public override int OldStrReq => 40; - - public override int OldDexBonus => -1; - - public override int ArmorBase => 40; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Dragon; - public override CraftResource DefaultResource => CraftResource.RedScales; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 5.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2645, 0x2646)] + public class DragonHelm : BaseArmor + { + [Constructible] + public DragonHelm() : base(0x2645) => Weight = 5.0; + + public DragonHelm(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 55; + public override int InitMaxHits => 75; + + public override int AosStrReq => 75; + public override int OldStrReq => 40; + + public override int OldDexBonus => -1; + + public override int ArmorBase => 40; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Dragon; + public override CraftResource DefaultResource => CraftResource.RedScales; + + 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 (Weight == 1.0) + Weight = 5.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Dragon/DragonLegs.cs b/Projects/UOContent/Items/Armor/Dragon/DragonLegs.cs index ec8225e75..900604f09 100644 --- a/Projects/UOContent/Items/Armor/Dragon/DragonLegs.cs +++ b/Projects/UOContent/Items/Armor/Dragon/DragonLegs.cs @@ -1,44 +1,44 @@ -namespace Server.Items -{ - [Flippable(0x2647, 0x2648)] - public class DragonLegs : BaseArmor - { - [Constructible] - public DragonLegs() : base(0x2647) => Weight = 6.0; - - public DragonLegs(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 55; - public override int InitMaxHits => 75; - - public override int AosStrReq => 75; - public override int OldStrReq => 60; - - public override int OldDexBonus => -6; - - public override int ArmorBase => 40; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Dragon; - public override CraftResource DefaultResource => CraftResource.RedScales; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2647, 0x2648)] + public class DragonLegs : BaseArmor + { + [Constructible] + public DragonLegs() : base(0x2647) => Weight = 6.0; + + public DragonLegs(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 55; + public override int InitMaxHits => 75; + + public override int AosStrReq => 75; + public override int OldStrReq => 60; + + public override int OldDexBonus => -6; + + public override int ArmorBase => 40; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Dragon; + public override CraftResource DefaultResource => CraftResource.RedScales; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Glasses/AnthropomorphistGlasses.cs b/Projects/UOContent/Items/Armor/Glasses/AnthropomorphistGlasses.cs index 08aee505e..da5e120a8 100644 --- a/Projects/UOContent/Items/Armor/Glasses/AnthropomorphistGlasses.cs +++ b/Projects/UOContent/Items/Armor/Glasses/AnthropomorphistGlasses.cs @@ -1,45 +1,45 @@ -namespace Server.Items -{ - public class AnthropomorphistGlasses : ElvenGlasses - { - [Constructible] - public AnthropomorphistGlasses() - { - Attributes.BonusHits = 5; - Attributes.RegenMana = 3; - Attributes.ReflectPhysical = 20; - - Hue = 0x80; - } - - public AnthropomorphistGlasses(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073379; // Anthropomorphist Reading Glasses - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 10; - public override int BasePoisonResistance => 20; - public override int BaseEnergyResistance => 20; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (version == 0 && Hue == 0) - Hue = 0x80; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AnthropomorphistGlasses : ElvenGlasses + { + [Constructible] + public AnthropomorphistGlasses() + { + Attributes.BonusHits = 5; + Attributes.RegenMana = 3; + Attributes.ReflectPhysical = 20; + + Hue = 0x80; + } + + public AnthropomorphistGlasses(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073379; // Anthropomorphist Reading Glasses + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 10; + public override int BasePoisonResistance => 20; + public override int BaseEnergyResistance => 20; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + if (version == 0 && Hue == 0) + Hue = 0x80; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Glasses/ArtsGlasses.cs b/Projects/UOContent/Items/Armor/Glasses/ArtsGlasses.cs index 1c6076583..0a0d52735 100644 --- a/Projects/UOContent/Items/Armor/Glasses/ArtsGlasses.cs +++ b/Projects/UOContent/Items/Armor/Glasses/ArtsGlasses.cs @@ -1,45 +1,45 @@ -namespace Server.Items -{ - public class ArtsGlasses : ElvenGlasses - { - [Constructible] - public ArtsGlasses() - { - Attributes.BonusStr = 5; - Attributes.BonusInt = 5; - Attributes.BonusHits = 15; - - Hue = 0x73; - } - - public ArtsGlasses(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073363; // Reading Glasses of the Arts - - public override int BasePhysicalResistance => 10; - public override int BaseFireResistance => 8; - public override int BaseColdResistance => 8; - public override int BasePoisonResistance => 4; - public override int BaseEnergyResistance => 10; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (version == 0 && Hue == 0) - Hue = 0x73; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ArtsGlasses : ElvenGlasses + { + [Constructible] + public ArtsGlasses() + { + Attributes.BonusStr = 5; + Attributes.BonusInt = 5; + Attributes.BonusHits = 15; + + Hue = 0x73; + } + + public ArtsGlasses(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073363; // Reading Glasses of the Arts + + public override int BasePhysicalResistance => 10; + public override int BaseFireResistance => 8; + public override int BaseColdResistance => 8; + public override int BasePoisonResistance => 4; + public override int BaseEnergyResistance => 10; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + if (version == 0 && Hue == 0) + Hue = 0x73; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Glasses/ElvenGlasses.cs b/Projects/UOContent/Items/Armor/Glasses/ElvenGlasses.cs index 324b8a37d..cb2aabc25 100644 --- a/Projects/UOContent/Items/Armor/Glasses/ElvenGlasses.cs +++ b/Projects/UOContent/Items/Armor/Glasses/ElvenGlasses.cs @@ -1,138 +1,138 @@ -using System; - -namespace Server.Items -{ - public class ElvenGlasses : BaseArmor - { - [Constructible] - public ElvenGlasses() : base(0x2FB8) - { - Weight = 2; - WeaponAttributes = new AosWeaponAttributes(this); - } - - public ElvenGlasses(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1032216; // elven glasses - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 4; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 36; - public override int InitMaxHits => 48; - - public override int AosStrReq => 45; - public override int OldStrReq => 40; - - public override int ArmorBase => 30; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - [CommandProperty(AccessLevel.GameMaster)] - public AosWeaponAttributes WeaponAttributes { get; private set; } - - public override void AppendChildNameProperties(ObjectPropertyList list) - { - base.AppendChildNameProperties(list); - - int prop; - - if ((prop = WeaponAttributes.HitColdArea) != 0) - list.Add(1060416, prop.ToString()); // hit cold area ~1_val~% - - if ((prop = WeaponAttributes.HitDispel) != 0) - list.Add(1060417, prop.ToString()); // hit dispel ~1_val~% - - if ((prop = WeaponAttributes.HitEnergyArea) != 0) - list.Add(1060418, prop.ToString()); // hit energy area ~1_val~% - - if ((prop = WeaponAttributes.HitFireArea) != 0) - list.Add(1060419, prop.ToString()); // hit fire area ~1_val~% - - if ((prop = WeaponAttributes.HitFireball) != 0) - list.Add(1060420, prop.ToString()); // hit fireball ~1_val~% - - if ((prop = WeaponAttributes.HitHarm) != 0) - list.Add(1060421, prop.ToString()); // hit harm ~1_val~% - - if ((prop = WeaponAttributes.HitLeechHits) != 0) - list.Add(1060422, prop.ToString()); // hit life leech ~1_val~% - - if ((prop = WeaponAttributes.HitLightning) != 0) - list.Add(1060423, prop.ToString()); // hit lightning ~1_val~% - - if ((prop = WeaponAttributes.HitLowerAttack) != 0) - list.Add(1060424, prop.ToString()); // hit lower attack ~1_val~% - - if ((prop = WeaponAttributes.HitLowerDefend) != 0) - list.Add(1060425, prop.ToString()); // hit lower defense ~1_val~% - - if ((prop = WeaponAttributes.HitMagicArrow) != 0) - list.Add(1060426, prop.ToString()); // hit magic arrow ~1_val~% - - if ((prop = WeaponAttributes.HitLeechMana) != 0) - list.Add(1060427, prop.ToString()); // hit mana leech ~1_val~% - - if ((prop = WeaponAttributes.HitPhysicalArea) != 0) - list.Add(1060428, prop.ToString()); // hit physical area ~1_val~% - - if ((prop = WeaponAttributes.HitPoisonArea) != 0) - list.Add(1060429, prop.ToString()); // hit poison area ~1_val~% - - if ((prop = WeaponAttributes.HitLeechStam) != 0) - list.Add(1060430, prop.ToString()); // hit stamina leech ~1_val~% - } - - private static void SetSaveFlag(ref SaveFlag flags, SaveFlag toSet, bool setIf) - { - if (setIf) - flags |= toSet; - } - - private static bool GetSaveFlag(SaveFlag flags, SaveFlag toGet) => (flags & toGet) != 0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - SaveFlag flags = SaveFlag.None; - - SetSaveFlag(ref flags, SaveFlag.WeaponAttributes, !WeaponAttributes.IsEmpty); - - writer.Write((int)flags); - - if (GetSaveFlag(flags, SaveFlag.WeaponAttributes)) - WeaponAttributes.Serialize(writer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - SaveFlag flags = (SaveFlag)reader.ReadInt(); - - if (GetSaveFlag(flags, SaveFlag.WeaponAttributes)) - WeaponAttributes = new AosWeaponAttributes(this, reader); - else - WeaponAttributes = new AosWeaponAttributes(this); - } - - [Flags] - private enum SaveFlag - { - None = 0x00000000, - WeaponAttributes = 0x00000001 - } - } -} +using System; + +namespace Server.Items +{ + public class ElvenGlasses : BaseArmor + { + [Constructible] + public ElvenGlasses() : base(0x2FB8) + { + Weight = 2; + WeaponAttributes = new AosWeaponAttributes(this); + } + + public ElvenGlasses(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1032216; // elven glasses + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 4; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 36; + public override int InitMaxHits => 48; + + public override int AosStrReq => 45; + public override int OldStrReq => 40; + + public override int ArmorBase => 30; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + [CommandProperty(AccessLevel.GameMaster)] + public AosWeaponAttributes WeaponAttributes { get; private set; } + + public override void AppendChildNameProperties(ObjectPropertyList list) + { + base.AppendChildNameProperties(list); + + int prop; + + if ((prop = WeaponAttributes.HitColdArea) != 0) + list.Add(1060416, prop.ToString()); // hit cold area ~1_val~% + + if ((prop = WeaponAttributes.HitDispel) != 0) + list.Add(1060417, prop.ToString()); // hit dispel ~1_val~% + + if ((prop = WeaponAttributes.HitEnergyArea) != 0) + list.Add(1060418, prop.ToString()); // hit energy area ~1_val~% + + if ((prop = WeaponAttributes.HitFireArea) != 0) + list.Add(1060419, prop.ToString()); // hit fire area ~1_val~% + + if ((prop = WeaponAttributes.HitFireball) != 0) + list.Add(1060420, prop.ToString()); // hit fireball ~1_val~% + + if ((prop = WeaponAttributes.HitHarm) != 0) + list.Add(1060421, prop.ToString()); // hit harm ~1_val~% + + if ((prop = WeaponAttributes.HitLeechHits) != 0) + list.Add(1060422, prop.ToString()); // hit life leech ~1_val~% + + if ((prop = WeaponAttributes.HitLightning) != 0) + list.Add(1060423, prop.ToString()); // hit lightning ~1_val~% + + if ((prop = WeaponAttributes.HitLowerAttack) != 0) + list.Add(1060424, prop.ToString()); // hit lower attack ~1_val~% + + if ((prop = WeaponAttributes.HitLowerDefend) != 0) + list.Add(1060425, prop.ToString()); // hit lower defense ~1_val~% + + if ((prop = WeaponAttributes.HitMagicArrow) != 0) + list.Add(1060426, prop.ToString()); // hit magic arrow ~1_val~% + + if ((prop = WeaponAttributes.HitLeechMana) != 0) + list.Add(1060427, prop.ToString()); // hit mana leech ~1_val~% + + if ((prop = WeaponAttributes.HitPhysicalArea) != 0) + list.Add(1060428, prop.ToString()); // hit physical area ~1_val~% + + if ((prop = WeaponAttributes.HitPoisonArea) != 0) + list.Add(1060429, prop.ToString()); // hit poison area ~1_val~% + + if ((prop = WeaponAttributes.HitLeechStam) != 0) + list.Add(1060430, prop.ToString()); // hit stamina leech ~1_val~% + } + + private static void SetSaveFlag(ref SaveFlag flags, SaveFlag toSet, bool setIf) + { + if (setIf) + flags |= toSet; + } + + private static bool GetSaveFlag(SaveFlag flags, SaveFlag toGet) => (flags & toGet) != 0; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + var flags = SaveFlag.None; + + SetSaveFlag(ref flags, SaveFlag.WeaponAttributes, !WeaponAttributes.IsEmpty); + + writer.Write((int)flags); + + if (GetSaveFlag(flags, SaveFlag.WeaponAttributes)) + WeaponAttributes.Serialize(writer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + var flags = (SaveFlag)reader.ReadInt(); + + if (GetSaveFlag(flags, SaveFlag.WeaponAttributes)) + WeaponAttributes = new AosWeaponAttributes(this, reader); + else + WeaponAttributes = new AosWeaponAttributes(this); + } + + [Flags] + private enum SaveFlag + { + None = 0x00000000, + WeaponAttributes = 0x00000001 + } + } +} diff --git a/Projects/UOContent/Items/Armor/Glasses/FoldedSteelGlasses.cs b/Projects/UOContent/Items/Armor/Glasses/FoldedSteelGlasses.cs index 3a851395d..fc75a1485 100644 --- a/Projects/UOContent/Items/Armor/Glasses/FoldedSteelGlasses.cs +++ b/Projects/UOContent/Items/Armor/Glasses/FoldedSteelGlasses.cs @@ -1,45 +1,45 @@ -namespace Server.Items -{ - public class FoldedSteelGlasses : ElvenGlasses - { - [Constructible] - public FoldedSteelGlasses() - { - Attributes.BonusStr = 8; - Attributes.NightSight = 1; - Attributes.DefendChance = 15; - - Hue = 0x47E; - } - - public FoldedSteelGlasses(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073380; // Folded Steel Reading Glasses - - public override int BasePhysicalResistance => 20; - public override int BaseFireResistance => 10; - public override int BaseColdResistance => 10; - public override int BasePoisonResistance => 10; - public override int BaseEnergyResistance => 10; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (version == 0 && Hue == 0) - Hue = 0x47E; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FoldedSteelGlasses : ElvenGlasses + { + [Constructible] + public FoldedSteelGlasses() + { + Attributes.BonusStr = 8; + Attributes.NightSight = 1; + Attributes.DefendChance = 15; + + Hue = 0x47E; + } + + public FoldedSteelGlasses(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073380; // Folded Steel Reading Glasses + + public override int BasePhysicalResistance => 20; + public override int BaseFireResistance => 10; + public override int BaseColdResistance => 10; + public override int BasePoisonResistance => 10; + public override int BaseEnergyResistance => 10; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + if (version == 0 && Hue == 0) + Hue = 0x47E; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Glasses/LightOfWayGlasses.cs b/Projects/UOContent/Items/Armor/Glasses/LightOfWayGlasses.cs index 6c2b5842e..474b81183 100644 --- a/Projects/UOContent/Items/Armor/Glasses/LightOfWayGlasses.cs +++ b/Projects/UOContent/Items/Armor/Glasses/LightOfWayGlasses.cs @@ -1,45 +1,45 @@ -namespace Server.Items -{ - public class LightOfWayGlasses : ElvenGlasses - { - [Constructible] - public LightOfWayGlasses() - { - Attributes.BonusStr = 7; - Attributes.BonusInt = 5; - Attributes.WeaponDamage = 30; - - Hue = 0x256; - } - - public LightOfWayGlasses(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073378; // Light Of Way Reading Glasses - - public override int BasePhysicalResistance => 10; - public override int BaseFireResistance => 10; - public override int BaseColdResistance => 10; - public override int BasePoisonResistance => 10; - public override int BaseEnergyResistance => 10; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (version == 0 && Hue == 0) - Hue = 0x256; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LightOfWayGlasses : ElvenGlasses + { + [Constructible] + public LightOfWayGlasses() + { + Attributes.BonusStr = 7; + Attributes.BonusInt = 5; + Attributes.WeaponDamage = 30; + + Hue = 0x256; + } + + public LightOfWayGlasses(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073378; // Light Of Way Reading Glasses + + public override int BasePhysicalResistance => 10; + public override int BaseFireResistance => 10; + public override int BaseColdResistance => 10; + public override int BasePoisonResistance => 10; + public override int BaseEnergyResistance => 10; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + if (version == 0 && Hue == 0) + Hue = 0x256; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Glasses/LyricalGlasses.cs b/Projects/UOContent/Items/Armor/Glasses/LyricalGlasses.cs index 24c365f03..07050de9b 100644 --- a/Projects/UOContent/Items/Armor/Glasses/LyricalGlasses.cs +++ b/Projects/UOContent/Items/Armor/Glasses/LyricalGlasses.cs @@ -1,45 +1,45 @@ -namespace Server.Items -{ - public class LyricalGlasses : ElvenGlasses - { - [Constructible] - public LyricalGlasses() - { - WeaponAttributes.HitLowerDefend = 20; - Attributes.NightSight = 1; - Attributes.ReflectPhysical = 15; - - Hue = 0x47F; - } - - public LyricalGlasses(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073382; // Lyrical Reading Glasses - - public override int BasePhysicalResistance => 10; - public override int BaseFireResistance => 10; - public override int BaseColdResistance => 10; - public override int BasePoisonResistance => 10; - public override int BaseEnergyResistance => 10; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (version == 0 && Hue == 0) - Hue = 0x47F; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LyricalGlasses : ElvenGlasses + { + [Constructible] + public LyricalGlasses() + { + WeaponAttributes.HitLowerDefend = 20; + Attributes.NightSight = 1; + Attributes.ReflectPhysical = 15; + + Hue = 0x47F; + } + + public LyricalGlasses(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073382; // Lyrical Reading Glasses + + public override int BasePhysicalResistance => 10; + public override int BaseFireResistance => 10; + public override int BaseColdResistance => 10; + public override int BasePoisonResistance => 10; + public override int BaseEnergyResistance => 10; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + if (version == 0 && Hue == 0) + Hue = 0x47F; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Glasses/MaceShieldGlasses.cs b/Projects/UOContent/Items/Armor/Glasses/MaceShieldGlasses.cs index 4ed491a7a..4b7d61edb 100644 --- a/Projects/UOContent/Items/Armor/Glasses/MaceShieldGlasses.cs +++ b/Projects/UOContent/Items/Armor/Glasses/MaceShieldGlasses.cs @@ -1,45 +1,45 @@ -namespace Server.Items -{ - public class MaceShieldGlasses : ElvenGlasses - { - [Constructible] - public MaceShieldGlasses() - { - WeaponAttributes.HitLowerDefend = 30; - Attributes.BonusStr = 10; - Attributes.BonusDex = 5; - - Hue = 0x1DD; - } - - public MaceShieldGlasses(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073381; // Mace And Shield Reading Glasses - - public override int BasePhysicalResistance => 25; - public override int BaseFireResistance => 10; - public override int BaseColdResistance => 10; - public override int BasePoisonResistance => 10; - public override int BaseEnergyResistance => 10; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (version == 0 && Hue == 0) - Hue = 0x1DD; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class MaceShieldGlasses : ElvenGlasses + { + [Constructible] + public MaceShieldGlasses() + { + WeaponAttributes.HitLowerDefend = 30; + Attributes.BonusStr = 10; + Attributes.BonusDex = 5; + + Hue = 0x1DD; + } + + public MaceShieldGlasses(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073381; // Mace And Shield Reading Glasses + + public override int BasePhysicalResistance => 25; + public override int BaseFireResistance => 10; + public override int BaseColdResistance => 10; + public override int BasePoisonResistance => 10; + public override int BaseEnergyResistance => 10; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + if (version == 0 && Hue == 0) + Hue = 0x1DD; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Glasses/MaritimeGlasses.cs b/Projects/UOContent/Items/Armor/Glasses/MaritimeGlasses.cs index 9862149e2..9c7152618 100644 --- a/Projects/UOContent/Items/Armor/Glasses/MaritimeGlasses.cs +++ b/Projects/UOContent/Items/Armor/Glasses/MaritimeGlasses.cs @@ -1,45 +1,45 @@ -namespace Server.Items -{ - public class MaritimeGlasses : ElvenGlasses - { - [Constructible] - public MaritimeGlasses() - { - Attributes.Luck = 150; - Attributes.NightSight = 1; - Attributes.ReflectPhysical = 20; - - Hue = 0x581; - } - - public MaritimeGlasses(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073364; // Maritime Reading Glasses - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 30; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (version == 0 && Hue == 0) - Hue = 0x581; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class MaritimeGlasses : ElvenGlasses + { + [Constructible] + public MaritimeGlasses() + { + Attributes.Luck = 150; + Attributes.NightSight = 1; + Attributes.ReflectPhysical = 20; + + Hue = 0x581; + } + + public MaritimeGlasses(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073364; // Maritime Reading Glasses + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 30; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + if (version == 0 && Hue == 0) + Hue = 0x581; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Glasses/NecromanticGlasses.cs b/Projects/UOContent/Items/Armor/Glasses/NecromanticGlasses.cs index 3d07cc28a..fb59b6d60 100644 --- a/Projects/UOContent/Items/Armor/Glasses/NecromanticGlasses.cs +++ b/Projects/UOContent/Items/Armor/Glasses/NecromanticGlasses.cs @@ -1,44 +1,44 @@ -namespace Server.Items -{ - public class NecromanticGlasses : ElvenGlasses - { - [Constructible] - public NecromanticGlasses() - { - Attributes.LowerManaCost = 15; - Attributes.LowerRegCost = 30; - - Hue = 0x22D; - } - - public NecromanticGlasses(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073377; // Necromantic Reading Glasses - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 0; - public override int BaseColdResistance => 0; - public override int BasePoisonResistance => 0; - public override int BaseEnergyResistance => 0; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (version == 0 && Hue == 0) - Hue = 0x22D; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class NecromanticGlasses : ElvenGlasses + { + [Constructible] + public NecromanticGlasses() + { + Attributes.LowerManaCost = 15; + Attributes.LowerRegCost = 30; + + Hue = 0x22D; + } + + public NecromanticGlasses(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073377; // Necromantic Reading Glasses + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 0; + public override int BaseColdResistance => 0; + public override int BasePoisonResistance => 0; + public override int BaseEnergyResistance => 0; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + if (version == 0 && Hue == 0) + Hue = 0x22D; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Glasses/PoisonedGlasses.cs b/Projects/UOContent/Items/Armor/Glasses/PoisonedGlasses.cs index 49391e6f8..cd121ae37 100644 --- a/Projects/UOContent/Items/Armor/Glasses/PoisonedGlasses.cs +++ b/Projects/UOContent/Items/Armor/Glasses/PoisonedGlasses.cs @@ -1,44 +1,44 @@ -namespace Server.Items -{ - public class PoisonedGlasses : ElvenGlasses - { - [Constructible] - public PoisonedGlasses() - { - Attributes.BonusStam = 3; - Attributes.RegenStam = 4; - - Hue = 0x113; - } - - public PoisonedGlasses(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073376; // Poisoned Reading Glasses - - public override int BasePhysicalResistance => 10; - public override int BaseFireResistance => 10; - public override int BaseColdResistance => 10; - public override int BasePoisonResistance => 30; - public override int BaseEnergyResistance => 10; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (version == 0 && Hue == 0) - Hue = 0x113; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PoisonedGlasses : ElvenGlasses + { + [Constructible] + public PoisonedGlasses() + { + Attributes.BonusStam = 3; + Attributes.RegenStam = 4; + + Hue = 0x113; + } + + public PoisonedGlasses(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073376; // Poisoned Reading Glasses + + public override int BasePhysicalResistance => 10; + public override int BaseFireResistance => 10; + public override int BaseColdResistance => 10; + public override int BasePoisonResistance => 30; + public override int BaseEnergyResistance => 10; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + if (version == 0 && Hue == 0) + Hue = 0x113; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Glasses/TradeGlasses.cs b/Projects/UOContent/Items/Armor/Glasses/TradeGlasses.cs index d2f43192a..156f484c7 100644 --- a/Projects/UOContent/Items/Armor/Glasses/TradeGlasses.cs +++ b/Projects/UOContent/Items/Armor/Glasses/TradeGlasses.cs @@ -1,39 +1,39 @@ -namespace Server.Items -{ - public class TradeGlasses : ElvenGlasses - { - [Constructible] - public TradeGlasses() - { - Attributes.BonusStr = 10; - Attributes.BonusInt = 10; - } - - public TradeGlasses(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073362; // Reading Glasses of the Trades - - public override int BasePhysicalResistance => 10; - public override int BaseFireResistance => 10; - public override int BaseColdResistance => 10; - public override int BasePoisonResistance => 10; - public override int BaseEnergyResistance => 10; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TradeGlasses : ElvenGlasses + { + [Constructible] + public TradeGlasses() + { + Attributes.BonusStr = 10; + Attributes.BonusInt = 10; + } + + public TradeGlasses(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073362; // Reading Glasses of the Trades + + public override int BasePhysicalResistance => 10; + public override int BaseFireResistance => 10; + public override int BaseColdResistance => 10; + public override int BasePoisonResistance => 10; + public override int BaseEnergyResistance => 10; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Glasses/TreasureTrinketGlasses.cs b/Projects/UOContent/Items/Armor/Glasses/TreasureTrinketGlasses.cs index f6f5143c2..339ab9883 100644 --- a/Projects/UOContent/Items/Armor/Glasses/TreasureTrinketGlasses.cs +++ b/Projects/UOContent/Items/Armor/Glasses/TreasureTrinketGlasses.cs @@ -1,45 +1,45 @@ -namespace Server.Items -{ - public class TreasureTrinketGlasses : ElvenGlasses - { - [Constructible] - public TreasureTrinketGlasses() - { - Attributes.BonusInt = 10; - Attributes.BonusHits = 5; - Attributes.SpellDamage = 10; - - Hue = 0x1C2; - } - - public TreasureTrinketGlasses(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073373; // Treasures and Trinkets Reading Glasses - - public override int BasePhysicalResistance => 10; - public override int BaseFireResistance => 10; - public override int BaseColdResistance => 10; - public override int BasePoisonResistance => 10; - public override int BaseEnergyResistance => 10; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (version == 0 && Hue == 0) - Hue = 0x1C2; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TreasureTrinketGlasses : ElvenGlasses + { + [Constructible] + public TreasureTrinketGlasses() + { + Attributes.BonusInt = 10; + Attributes.BonusHits = 5; + Attributes.SpellDamage = 10; + + Hue = 0x1C2; + } + + public TreasureTrinketGlasses(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073373; // Treasures and Trinkets Reading Glasses + + public override int BasePhysicalResistance => 10; + public override int BaseFireResistance => 10; + public override int BaseColdResistance => 10; + public override int BasePoisonResistance => 10; + public override int BaseEnergyResistance => 10; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + if (version == 0 && Hue == 0) + Hue = 0x1C2; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Glasses/WizardsGlasses.cs b/Projects/UOContent/Items/Armor/Glasses/WizardsGlasses.cs index 58b6203ab..f2bba6eda 100644 --- a/Projects/UOContent/Items/Armor/Glasses/WizardsGlasses.cs +++ b/Projects/UOContent/Items/Armor/Glasses/WizardsGlasses.cs @@ -1,45 +1,45 @@ -namespace Server.Items -{ - public class WizardsGlasses : ElvenGlasses - { - [Constructible] - public WizardsGlasses() - { - Attributes.BonusMana = 10; - Attributes.RegenMana = 3; - Attributes.SpellDamage = 15; - - Hue = 0x2B0; - } - - public WizardsGlasses(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073374; // Wizard's Crystal Reading Glasses - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 5; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (version == 0 && Hue == 0) - Hue = 0x2B0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class WizardsGlasses : ElvenGlasses + { + [Constructible] + public WizardsGlasses() + { + Attributes.BonusMana = 10; + Attributes.RegenMana = 3; + Attributes.SpellDamage = 15; + + Hue = 0x2B0; + } + + public WizardsGlasses(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073374; // Wizard's Crystal Reading Glasses + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 5; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + if (version == 0 && Hue == 0) + Hue = 0x2B0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Helmets/Bascinet.cs b/Projects/UOContent/Items/Armor/Helmets/Bascinet.cs index bf9dc1292..396f12ff1 100644 --- a/Projects/UOContent/Items/Armor/Helmets/Bascinet.cs +++ b/Projects/UOContent/Items/Armor/Helmets/Bascinet.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - public class Bascinet : BaseArmor - { - [Constructible] - public Bascinet() : base(0x140C) => Weight = 5.0; - - public Bascinet(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 7; - public override int BaseFireResistance => 2; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 2; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 40; - public override int InitMaxHits => 50; - - public override int AosStrReq => 40; - public override int OldStrReq => 10; - - public override int ArmorBase => 18; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 5.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Bascinet : BaseArmor + { + [Constructible] + public Bascinet() : base(0x140C) => Weight = 5.0; + + public Bascinet(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 7; + public override int BaseFireResistance => 2; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 2; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 40; + public override int InitMaxHits => 50; + + public override int AosStrReq => 40; + public override int OldStrReq => 10; + + public override int ArmorBase => 18; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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 (Weight == 1.0) + Weight = 5.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Helmets/BoneHelm.cs b/Projects/UOContent/Items/Armor/Helmets/BoneHelm.cs index 2638edc20..ecaff7ed0 100644 --- a/Projects/UOContent/Items/Armor/Helmets/BoneHelm.cs +++ b/Projects/UOContent/Items/Armor/Helmets/BoneHelm.cs @@ -1,44 +1,44 @@ -namespace Server.Items -{ - [Flippable(0x1451, 0x1456)] - public class BoneHelm : BaseArmor - { - [Constructible] - public BoneHelm() : base(0x1451) => Weight = 3.0; - - public BoneHelm(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 4; - public override int BasePoisonResistance => 2; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 25; - public override int InitMaxHits => 30; - - public override int AosStrReq => 20; - public override int OldStrReq => 40; - - public override int ArmorBase => 30; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - - if (Weight == 1.0) - Weight = 3.0; - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1451, 0x1456)] + public class BoneHelm : BaseArmor + { + [Constructible] + public BoneHelm() : base(0x1451) => Weight = 3.0; + + public BoneHelm(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 4; + public override int BasePoisonResistance => 2; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 25; + public override int InitMaxHits => 30; + + public override int AosStrReq => 20; + public override int OldStrReq => 40; + + public override int ArmorBase => 30; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(0); + + if (Weight == 1.0) + Weight = 3.0; + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Helmets/ChainCoif.cs b/Projects/UOContent/Items/Armor/Helmets/ChainCoif.cs index f072c337f..67259c3c4 100644 --- a/Projects/UOContent/Items/Armor/Helmets/ChainCoif.cs +++ b/Projects/UOContent/Items/Armor/Helmets/ChainCoif.cs @@ -1,41 +1,41 @@ -namespace Server.Items -{ - [Flippable(0x13BB, 0x13C0)] - public class ChainCoif : BaseArmor - { - [Constructible] - public ChainCoif() : base(0x13BB) => Weight = 1.0; - - public ChainCoif(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 4; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 4; - public override int BasePoisonResistance => 1; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 35; - public override int InitMaxHits => 60; - - public override int AosStrReq => 60; - public override int OldStrReq => 20; - - public override int ArmorBase => 28; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Chainmail; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x13BB, 0x13C0)] + public class ChainCoif : BaseArmor + { + [Constructible] + public ChainCoif() : base(0x13BB) => Weight = 1.0; + + public ChainCoif(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 4; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 4; + public override int BasePoisonResistance => 1; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 35; + public override int InitMaxHits => 60; + + public override int AosStrReq => 60; + public override int OldStrReq => 20; + + public override int ArmorBase => 28; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Chainmail; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Helmets/Circlet.cs b/Projects/UOContent/Items/Armor/Helmets/Circlet.cs index 1e5d8d1be..3dbe25289 100644 --- a/Projects/UOContent/Items/Armor/Helmets/Circlet.cs +++ b/Projects/UOContent/Items/Armor/Helmets/Circlet.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - [Flippable(0x2B6E, 0x3165)] - public class Circlet : BaseArmor - { - [Constructible] - public Circlet() : base(0x2B6E) => Weight = 2.0; - - public Circlet(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 1; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 2; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 50; - public override int InitMaxHits => 65; - - public override int AosStrReq => 10; - public override int OldStrReq => 10; - - public override int ArmorBase => 30; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override Race RequiredRace => Race.Elf; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2B6E, 0x3165)] + public class Circlet : BaseArmor + { + [Constructible] + public Circlet() : base(0x2B6E) => Weight = 2.0; + + public Circlet(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 1; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 2; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 50; + public override int InitMaxHits => 65; + + public override int AosStrReq => 10; + public override int OldStrReq => 10; + + public override int ArmorBase => 30; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + public override Race RequiredRace => Race.Elf; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Helmets/CloseHelm.cs b/Projects/UOContent/Items/Armor/Helmets/CloseHelm.cs index 50b46566f..07c99b956 100644 --- a/Projects/UOContent/Items/Armor/Helmets/CloseHelm.cs +++ b/Projects/UOContent/Items/Armor/Helmets/CloseHelm.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - public class CloseHelm : BaseArmor - { - [Constructible] - public CloseHelm() : base(0x1408) => Weight = 5.0; - - public CloseHelm(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 45; - public override int InitMaxHits => 60; - - public override int AosStrReq => 55; - public override int OldStrReq => 40; - - public override int ArmorBase => 30; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 5.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class CloseHelm : BaseArmor + { + [Constructible] + public CloseHelm() : base(0x1408) => Weight = 5.0; + + public CloseHelm(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 45; + public override int InitMaxHits => 60; + + public override int AosStrReq => 55; + public override int OldStrReq => 40; + + public override int ArmorBase => 30; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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 (Weight == 1.0) + Weight = 5.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Helmets/DaemonHelm.cs b/Projects/UOContent/Items/Armor/Helmets/DaemonHelm.cs index a222f1b25..acad9de44 100644 --- a/Projects/UOContent/Items/Armor/Helmets/DaemonHelm.cs +++ b/Projects/UOContent/Items/Armor/Helmets/DaemonHelm.cs @@ -1,58 +1,58 @@ -namespace Server.Items -{ - [Flippable(0x1451, 0x1456)] - public class DaemonHelm : BaseArmor - { - [Constructible] - public DaemonHelm() : base(0x1451) - { - Hue = 0x648; - Weight = 3.0; - - ArmorAttributes.SelfRepair = 1; - } - - public DaemonHelm(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 6; - public override int BaseFireResistance => 6; - public override int BaseColdResistance => 7; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 7; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override int AosStrReq => 20; - public override int OldStrReq => 40; - - public override int ArmorBase => 46; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Bone; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override int LabelNumber => 1041374; // daemon bone helmet - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 3.0; - - if (ArmorAttributes.SelfRepair == 0) - ArmorAttributes.SelfRepair = 1; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1451, 0x1456)] + public class DaemonHelm : BaseArmor + { + [Constructible] + public DaemonHelm() : base(0x1451) + { + Hue = 0x648; + Weight = 3.0; + + ArmorAttributes.SelfRepair = 1; + } + + public DaemonHelm(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 6; + public override int BaseFireResistance => 6; + public override int BaseColdResistance => 7; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 7; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override int AosStrReq => 20; + public override int OldStrReq => 40; + + public override int ArmorBase => 46; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Bone; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override int LabelNumber => 1041374; // daemon bone helmet + + 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 (Weight == 1.0) + Weight = 3.0; + + if (ArmorAttributes.SelfRepair == 0) + ArmorAttributes.SelfRepair = 1; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Helmets/GemmedCirclet.cs b/Projects/UOContent/Items/Armor/Helmets/GemmedCirclet.cs index 02ab70c7c..141f3d76e 100644 --- a/Projects/UOContent/Items/Armor/Helmets/GemmedCirclet.cs +++ b/Projects/UOContent/Items/Armor/Helmets/GemmedCirclet.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - [Flippable(0x2B70, 0x3167)] - public class GemmedCirclet : BaseArmor - { - [Constructible] - public GemmedCirclet() : base(0x2B70) => Weight = 2.0; - - public GemmedCirclet(Serial serial) : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - - public override int BasePhysicalResistance => 1; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 2; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 20; - public override int InitMaxHits => 35; - - public override int AosStrReq => 10; - public override int OldStrReq => 10; - - public override int ArmorBase => 30; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2B70, 0x3167)] + public class GemmedCirclet : BaseArmor + { + [Constructible] + public GemmedCirclet() : base(0x2B70) => Weight = 2.0; + + public GemmedCirclet(Serial serial) : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + + public override int BasePhysicalResistance => 1; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 2; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 20; + public override int InitMaxHits => 35; + + public override int AosStrReq => 10; + public override int OldStrReq => 10; + + public override int ArmorBase => 30; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Helmets/Helmet.cs b/Projects/UOContent/Items/Armor/Helmets/Helmet.cs index 2daa6b2ae..2486bcb5b 100644 --- a/Projects/UOContent/Items/Armor/Helmets/Helmet.cs +++ b/Projects/UOContent/Items/Armor/Helmets/Helmet.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - public class Helmet : BaseArmor - { - [Constructible] - public Helmet() : base(0x140A) => Weight = 5.0; - - public Helmet(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 4; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 45; - public override int InitMaxHits => 60; - - public override int AosStrReq => 45; - public override int OldStrReq => 40; - - public override int ArmorBase => 30; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 5.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Helmet : BaseArmor + { + [Constructible] + public Helmet() : base(0x140A) => Weight = 5.0; + + public Helmet(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 4; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 45; + public override int InitMaxHits => 60; + + public override int AosStrReq => 45; + public override int OldStrReq => 40; + + public override int ArmorBase => 30; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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 (Weight == 1.0) + Weight = 5.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Helmets/LeatherCap.cs b/Projects/UOContent/Items/Armor/Helmets/LeatherCap.cs index 16f7f08c4..27b7d0f45 100644 --- a/Projects/UOContent/Items/Armor/Helmets/LeatherCap.cs +++ b/Projects/UOContent/Items/Armor/Helmets/LeatherCap.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - [Flippable(0x1db9, 0x1dba)] - public class LeatherCap : BaseArmor - { - [Constructible] - public LeatherCap() : base(0x1DB9) => Weight = 2.0; - - public LeatherCap(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 30; - public override int InitMaxHits => 40; - - public override int AosStrReq => 20; - public override int OldStrReq => 15; - - public override int ArmorBase => 13; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 2.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1db9, 0x1dba)] + public class LeatherCap : BaseArmor + { + [Constructible] + public LeatherCap() : base(0x1DB9) => Weight = 2.0; + + public LeatherCap(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 30; + public override int InitMaxHits => 40; + + public override int AosStrReq => 20; + public override int OldStrReq => 15; + + public override int ArmorBase => 13; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + 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 (Weight == 1.0) + Weight = 2.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Helmets/NorseHelm.cs b/Projects/UOContent/Items/Armor/Helmets/NorseHelm.cs index 29e21b3dd..8f88763ef 100644 --- a/Projects/UOContent/Items/Armor/Helmets/NorseHelm.cs +++ b/Projects/UOContent/Items/Armor/Helmets/NorseHelm.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - public class NorseHelm : BaseArmor - { - [Constructible] - public NorseHelm() : base(0x140E) => Weight = 5.0; - - public NorseHelm(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 4; - public override int BaseFireResistance => 1; - public override int BaseColdResistance => 4; - public override int BasePoisonResistance => 4; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 45; - public override int InitMaxHits => 60; - - public override int AosStrReq => 55; - public override int OldStrReq => 40; - - public override int ArmorBase => 30; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 5.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class NorseHelm : BaseArmor + { + [Constructible] + public NorseHelm() : base(0x140E) => Weight = 5.0; + + public NorseHelm(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 4; + public override int BaseFireResistance => 1; + public override int BaseColdResistance => 4; + public override int BasePoisonResistance => 4; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 45; + public override int InitMaxHits => 60; + + public override int AosStrReq => 55; + public override int OldStrReq => 40; + + public override int ArmorBase => 30; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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 (Weight == 1.0) + Weight = 5.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Helmets/OrcHelm.cs b/Projects/UOContent/Items/Armor/Helmets/OrcHelm.cs index cb77874ac..8b28ef918 100644 --- a/Projects/UOContent/Items/Armor/Helmets/OrcHelm.cs +++ b/Projects/UOContent/Items/Armor/Helmets/OrcHelm.cs @@ -1,49 +1,49 @@ -namespace Server.Items -{ - public class OrcHelm : BaseArmor - { - [Constructible] - public OrcHelm() : base(0x1F0B) - { - } - - public OrcHelm(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 1; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 30; - public override int InitMaxHits => 50; - - public override int AosStrReq => 30; - public override int OldStrReq => 10; - - public override int ArmorBase => 20; - - public override double DefaultWeight => 5; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.None; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (version == 0 && (Weight == 1 || Weight == 5)) Weight = -1; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class OrcHelm : BaseArmor + { + [Constructible] + public OrcHelm() : base(0x1F0B) + { + } + + public OrcHelm(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 1; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 30; + public override int InitMaxHits => 50; + + public override int AosStrReq => 30; + public override int OldStrReq => 10; + + public override int ArmorBase => 20; + + public override double DefaultWeight => 5; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.None; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + if (version == 0 && (Weight == 1 || Weight == 5)) Weight = -1; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Helmets/PlateHelm.cs b/Projects/UOContent/Items/Armor/Helmets/PlateHelm.cs index 077695ca6..7318496c1 100644 --- a/Projects/UOContent/Items/Armor/Helmets/PlateHelm.cs +++ b/Projects/UOContent/Items/Armor/Helmets/PlateHelm.cs @@ -1,45 +1,45 @@ -namespace Server.Items -{ - public class PlateHelm : BaseArmor - { - [Constructible] - public PlateHelm() : base(0x1412) => Weight = 5.0; - - public PlateHelm(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 50; - public override int InitMaxHits => 65; - - public override int AosStrReq => 80; - public override int OldStrReq => 40; - - public override int OldDexBonus => -1; - - public override int ArmorBase => 40; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 5.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PlateHelm : BaseArmor + { + [Constructible] + public PlateHelm() : base(0x1412) => Weight = 5.0; + + public PlateHelm(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 50; + public override int InitMaxHits => 65; + + public override int AosStrReq => 80; + public override int OldStrReq => 40; + + public override int OldDexBonus => -1; + + public override int ArmorBase => 40; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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 (Weight == 1.0) + Weight = 5.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Helmets/RavenHelm.cs b/Projects/UOContent/Items/Armor/Helmets/RavenHelm.cs index be1f5744e..6fe8593e1 100644 --- a/Projects/UOContent/Items/Armor/Helmets/RavenHelm.cs +++ b/Projects/UOContent/Items/Armor/Helmets/RavenHelm.cs @@ -1,45 +1,45 @@ -namespace Server.Items -{ - [Flippable(0x2B71, 0x3168)] - public class RavenHelm : BaseArmor - { - [Constructible] - public RavenHelm() : base(0x2B71) => Weight = 5.0; - - public RavenHelm(Serial serial) : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 1; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 2; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 50; - public override int InitMaxHits => 65; - - public override int AosStrReq => 25; - public override int OldStrReq => 25; - - public override int ArmorBase => 40; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2B71, 0x3168)] + public class RavenHelm : BaseArmor + { + [Constructible] + public RavenHelm() : base(0x2B71) => Weight = 5.0; + + public RavenHelm(Serial serial) : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 1; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 2; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 50; + public override int InitMaxHits => 65; + + public override int AosStrReq => 25; + public override int OldStrReq => 25; + + public override int ArmorBase => 40; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Helmets/RoyalCirclet.cs b/Projects/UOContent/Items/Armor/Helmets/RoyalCirclet.cs index bc945db0c..710199d98 100644 --- a/Projects/UOContent/Items/Armor/Helmets/RoyalCirclet.cs +++ b/Projects/UOContent/Items/Armor/Helmets/RoyalCirclet.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - [Flippable(0x2B6F, 0x3166)] - public class RoyalCirclet : BaseArmor - { - [Constructible] - public RoyalCirclet() : base(0x2B6F) => Weight = 2.0; - - public RoyalCirclet(Serial serial) : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - - public override int BasePhysicalResistance => 1; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 2; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 20; - public override int InitMaxHits => 35; - - public override int AosStrReq => 10; - public override int OldStrReq => 10; - - public override int ArmorBase => 30; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2B6F, 0x3166)] + public class RoyalCirclet : BaseArmor + { + [Constructible] + public RoyalCirclet() : base(0x2B6F) => Weight = 2.0; + + public RoyalCirclet(Serial serial) : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + + public override int BasePhysicalResistance => 1; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 2; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 20; + public override int InitMaxHits => 35; + + public override int AosStrReq => 10; + public override int OldStrReq => 10; + + public override int ArmorBase => 30; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Helmets/VultureHelm.cs b/Projects/UOContent/Items/Armor/Helmets/VultureHelm.cs index 8d9f8a372..36cb7fbe1 100644 --- a/Projects/UOContent/Items/Armor/Helmets/VultureHelm.cs +++ b/Projects/UOContent/Items/Armor/Helmets/VultureHelm.cs @@ -1,45 +1,45 @@ -namespace Server.Items -{ - [Flippable(0x2B72, 0x3169)] - public class VultureHelm : BaseArmor - { - [Constructible] - public VultureHelm() : base(0x2B72) => Weight = 5.0; - - public VultureHelm(Serial serial) : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 1; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 2; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 50; - public override int InitMaxHits => 65; - - public override int AosStrReq => 25; - public override int OldStrReq => 25; - - public override int ArmorBase => 40; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2B72, 0x3169)] + public class VultureHelm : BaseArmor + { + [Constructible] + public VultureHelm() : base(0x2B72) => Weight = 5.0; + + public VultureHelm(Serial serial) : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 1; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 2; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 50; + public override int InitMaxHits => 65; + + public override int AosStrReq => 25; + public override int OldStrReq => 25; + + public override int ArmorBase => 40; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Helmets/WingedHelm.cs b/Projects/UOContent/Items/Armor/Helmets/WingedHelm.cs index 60fc279f9..bb534b181 100644 --- a/Projects/UOContent/Items/Armor/Helmets/WingedHelm.cs +++ b/Projects/UOContent/Items/Armor/Helmets/WingedHelm.cs @@ -1,45 +1,45 @@ -namespace Server.Items -{ - [Flippable(0x2B73, 0x316A)] - public class WingedHelm : BaseArmor - { - [Constructible] - public WingedHelm() : base(0x2B73) => Weight = 5.0; - - public WingedHelm(Serial serial) : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 1; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 2; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 45; - public override int InitMaxHits => 55; - - public override int AosStrReq => 25; - public override int OldStrReq => 25; - - public override int ArmorBase => 40; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2B73, 0x316A)] + public class WingedHelm : BaseArmor + { + [Constructible] + public WingedHelm() : base(0x2B73) => Weight = 5.0; + + public WingedHelm(Serial serial) : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 1; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 2; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 45; + public override int InitMaxHits => 55; + + public override int AosStrReq => 25; + public override int OldStrReq => 25; + + public override int ArmorBase => 40; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/FemaleLeafChest.cs b/Projects/UOContent/Items/Armor/Leather/FemaleLeafChest.cs index 93e178651..54f9bfa9e 100644 --- a/Projects/UOContent/Items/Armor/Leather/FemaleLeafChest.cs +++ b/Projects/UOContent/Items/Armor/Leather/FemaleLeafChest.cs @@ -1,48 +1,48 @@ -namespace Server.Items -{ - [Flippable(0x2FCB, 0x3181)] - public class FemaleLeafChest : BaseArmor - { - [Constructible] - public FemaleLeafChest() : base(0x2FCB) => Weight = 2.0; - - public FemaleLeafChest(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 4; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 30; - public override int InitMaxHits => 40; - - public override int AosStrReq => 20; - public override int OldStrReq => 20; - - public override int ArmorBase => 13; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override bool AllowMaleWearer => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2FCB, 0x3181)] + public class FemaleLeafChest : BaseArmor + { + [Constructible] + public FemaleLeafChest() : base(0x2FCB) => Weight = 2.0; + + public FemaleLeafChest(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 4; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 30; + public override int InitMaxHits => 40; + + public override int AosStrReq => 20; + public override int OldStrReq => 20; + + public override int ArmorBase => 13; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + public override bool AllowMaleWearer => false; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/FemaleLeatherChest.cs b/Projects/UOContent/Items/Armor/Leather/FemaleLeatherChest.cs index 56738da0a..89caf82b1 100644 --- a/Projects/UOContent/Items/Armor/Leather/FemaleLeatherChest.cs +++ b/Projects/UOContent/Items/Armor/Leather/FemaleLeatherChest.cs @@ -1,46 +1,46 @@ -namespace Server.Items -{ - [Flippable(0x1c06, 0x1c07)] - public class FemaleLeatherChest : BaseArmor - { - [Constructible] - public FemaleLeatherChest() : base(0x1C06) => Weight = 1.0; - - public FemaleLeatherChest(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 30; - public override int InitMaxHits => 40; - - public override int AosStrReq => 25; - public override int OldStrReq => 15; - - public override int ArmorBase => 13; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override bool AllowMaleWearer => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1c06, 0x1c07)] + public class FemaleLeatherChest : BaseArmor + { + [Constructible] + public FemaleLeatherChest() : base(0x1C06) => Weight = 1.0; + + public FemaleLeatherChest(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 30; + public override int InitMaxHits => 40; + + public override int AosStrReq => 25; + public override int OldStrReq => 15; + + public override int ArmorBase => 13; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + public override bool AllowMaleWearer => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeafArms.cs b/Projects/UOContent/Items/Armor/Leather/LeafArms.cs index 0e70bf2e4..b1ad1de2a 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeafArms.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeafArms.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - [Flippable(0x2FC8, 0x317E)] - public class LeafArms : BaseArmor - { - [Constructible] - public LeafArms() : base(0x2FC8) => Weight = 2.0; - - public LeafArms(Serial serial) : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 4; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 30; - public override int InitMaxHits => 40; - - public override int AosStrReq => 15; - public override int OldStrReq => 15; - - public override int ArmorBase => 13; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2FC8, 0x317E)] + public class LeafArms : BaseArmor + { + [Constructible] + public LeafArms() : base(0x2FC8) => Weight = 2.0; + + public LeafArms(Serial serial) : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 4; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 30; + public override int InitMaxHits => 40; + + public override int AosStrReq => 15; + public override int OldStrReq => 15; + + public override int ArmorBase => 13; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeafChest.cs b/Projects/UOContent/Items/Armor/Leather/LeafChest.cs index 49eac490f..a16636b9d 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeafChest.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeafChest.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - [Flippable(0x2FC5, 0x317B)] - public class LeafChest : BaseArmor - { - [Constructible] - public LeafChest() : base(0x2FC5) => Weight = 2.0; - - public LeafChest(Serial serial) : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 4; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 30; - public override int InitMaxHits => 40; - - public override int AosStrReq => 20; - public override int OldStrReq => 20; - - public override int ArmorBase => 13; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2FC5, 0x317B)] + public class LeafChest : BaseArmor + { + [Constructible] + public LeafChest() : base(0x2FC5) => Weight = 2.0; + + public LeafChest(Serial serial) : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 4; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 30; + public override int InitMaxHits => 40; + + public override int AosStrReq => 20; + public override int OldStrReq => 20; + + public override int ArmorBase => 13; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeafGloves.cs b/Projects/UOContent/Items/Armor/Leather/LeafGloves.cs index f117547dc..0698898ec 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeafGloves.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeafGloves.cs @@ -1,139 +1,139 @@ -namespace Server.Items -{ - [Flippable] - public class LeafGloves : BaseArmor, IArcaneEquip - { - [Constructible] - public LeafGloves() : base(0x2FC6) => Weight = 2.0; - - public LeafGloves(Serial serial) : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 4; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 30; - public override int InitMaxHits => 40; - - public override int AosStrReq => 10; - public override int OldStrReq => 10; - - public override int ArmorBase => 13; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - if (IsArcane) - { - writer.Write(true); - writer.Write(m_CurArcaneCharges); - writer.Write(m_MaxArcaneCharges); - } - else - { - writer.Write(false); - } - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 0: - { - if (reader.ReadBool()) - { - m_CurArcaneCharges = reader.ReadInt(); - m_MaxArcaneCharges = reader.ReadInt(); - - if (Hue == 2118) - Hue = ArcaneGem.DefaultArcaneHue; - } - - break; - } - } - } - - private int m_MaxArcaneCharges, m_CurArcaneCharges; - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxArcaneCharges - { - get => m_MaxArcaneCharges; - set - { - m_MaxArcaneCharges = value; - InvalidateProperties(); - Update(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int CurArcaneCharges - { - get => m_CurArcaneCharges; - set - { - m_CurArcaneCharges = value; - InvalidateProperties(); - Update(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsArcane => m_MaxArcaneCharges > 0 && m_CurArcaneCharges >= 0; - - public void Update() - { - if (IsArcane) - ItemID = 0x26B0; // TODO: Check - else if (ItemID == 0x26B0) - ItemID = 0x2FC6; - - if (IsArcane && CurArcaneCharges == 0) - Hue = 0; - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (IsArcane) - list.Add(1061837, "{0}\t{1}", m_CurArcaneCharges, m_MaxArcaneCharges); // arcane charges: ~1_val~ / ~2_val~ - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - if (IsArcane) - LabelTo(from, 1061837, $"{m_CurArcaneCharges}\t{m_MaxArcaneCharges}"); - } - - public void Flip() - { - if (ItemID == 0x2FC6) - ItemID = 0x317C; - else if (ItemID == 0x317C) - ItemID = 0x2FC6; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable] + public class LeafGloves : BaseArmor, IArcaneEquip + { + private int m_MaxArcaneCharges, m_CurArcaneCharges; + + [Constructible] + public LeafGloves() : base(0x2FC6) => Weight = 2.0; + + public LeafGloves(Serial serial) : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 4; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 30; + public override int InitMaxHits => 40; + + public override int AosStrReq => 10; + public override int OldStrReq => 10; + + public override int ArmorBase => 13; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxArcaneCharges + { + get => m_MaxArcaneCharges; + set + { + m_MaxArcaneCharges = value; + InvalidateProperties(); + Update(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int CurArcaneCharges + { + get => m_CurArcaneCharges; + set + { + m_CurArcaneCharges = value; + InvalidateProperties(); + Update(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsArcane => m_MaxArcaneCharges > 0 && m_CurArcaneCharges >= 0; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + if (IsArcane) + { + writer.Write(true); + writer.Write(m_CurArcaneCharges); + writer.Write(m_MaxArcaneCharges); + } + else + { + writer.Write(false); + } + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 0: + { + if (reader.ReadBool()) + { + m_CurArcaneCharges = reader.ReadInt(); + m_MaxArcaneCharges = reader.ReadInt(); + + if (Hue == 2118) + Hue = ArcaneGem.DefaultArcaneHue; + } + + break; + } + } + } + + public void Update() + { + if (IsArcane) + ItemID = 0x26B0; // TODO: Check + else if (ItemID == 0x26B0) + ItemID = 0x2FC6; + + if (IsArcane && CurArcaneCharges == 0) + Hue = 0; + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (IsArcane) + list.Add(1061837, "{0}\t{1}", m_CurArcaneCharges, m_MaxArcaneCharges); // arcane charges: ~1_val~ / ~2_val~ + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + if (IsArcane) + LabelTo(from, 1061837, $"{m_CurArcaneCharges}\t{m_MaxArcaneCharges}"); + } + + public void Flip() + { + if (ItemID == 0x2FC6) + ItemID = 0x317C; + else if (ItemID == 0x317C) + ItemID = 0x2FC6; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeafGorget.cs b/Projects/UOContent/Items/Armor/Leather/LeafGorget.cs index 751d32627..afdf2f290 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeafGorget.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeafGorget.cs @@ -1,46 +1,46 @@ -namespace Server.Items -{ - public class LeafGorget : BaseArmor - { - [Constructible] - public LeafGorget() : base(0x2FC7) => Weight = 2.0; - - public LeafGorget(Serial serial) : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 4; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 30; - public override int InitMaxHits => 40; - - public override int AosStrReq => 10; - public override int OldStrReq => 10; - - public override int ArmorBase => 13; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LeafGorget : BaseArmor + { + [Constructible] + public LeafGorget() : base(0x2FC7) => Weight = 2.0; + + public LeafGorget(Serial serial) : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 4; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 30; + public override int InitMaxHits => 40; + + public override int AosStrReq => 10; + public override int OldStrReq => 10; + + public override int ArmorBase => 13; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeafLegs.cs b/Projects/UOContent/Items/Armor/Leather/LeafLegs.cs index 1b043ad81..b370ad320 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeafLegs.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeafLegs.cs @@ -1,48 +1,48 @@ -namespace Server.Items -{ - [Flippable(0x2FC9, 0x317F)] - public class LeafLegs : BaseArmor - { - [Constructible] - public LeafLegs() : base(0x2FC9) => Weight = 2.0; - - public LeafLegs(Serial serial) : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 4; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 30; - public override int InitMaxHits => 40; - - public override int AosStrReq => 20; - public override int OldStrReq => 20; - - public override int ArmorBase => 13; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2FC9, 0x317F)] + public class LeafLegs : BaseArmor + { + [Constructible] + public LeafLegs() : base(0x2FC9) => Weight = 2.0; + + public LeafLegs(Serial serial) : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 4; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 30; + public override int InitMaxHits => 40; + + public override int AosStrReq => 20; + public override int OldStrReq => 20; + + public override int ArmorBase => 13; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeafTonlet.cs b/Projects/UOContent/Items/Armor/Leather/LeafTonlet.cs index c8459f927..81a1fdf72 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeafTonlet.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeafTonlet.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - [Flippable(0x2FCA, 0x3180)] - public class LeafTonlet : BaseArmor - { - [Constructible] - public LeafTonlet() : base(0x2FCA) => Weight = 2.0; - - public LeafTonlet(Serial serial) : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 4; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 30; - public override int InitMaxHits => 40; - - public override int AosStrReq => 10; - public override int OldStrReq => 10; - - public override int ArmorBase => 13; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2FCA, 0x3180)] + public class LeafTonlet : BaseArmor + { + [Constructible] + public LeafTonlet() : base(0x2FCA) => Weight = 2.0; + + public LeafTonlet(Serial serial) : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 4; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 30; + public override int InitMaxHits => 40; + + public override int AosStrReq => 10; + public override int OldStrReq => 10; + + public override int ArmorBase => 13; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeatherArms.cs b/Projects/UOContent/Items/Armor/Leather/LeatherArms.cs index 087b90a19..897cb5761 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeatherArms.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeatherArms.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - [Flippable(0x13cd, 0x13c5)] - public class LeatherArms : BaseArmor - { - [Constructible] - public LeatherArms() : base(0x13CD) => Weight = 2.0; - - public LeatherArms(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 30; - public override int InitMaxHits => 40; - - public override int AosStrReq => 20; - public override int OldStrReq => 15; - - public override int ArmorBase => 13; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 2.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x13cd, 0x13c5)] + public class LeatherArms : BaseArmor + { + [Constructible] + public LeatherArms() : base(0x13CD) => Weight = 2.0; + + public LeatherArms(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 30; + public override int InitMaxHits => 40; + + public override int AosStrReq => 20; + public override int OldStrReq => 15; + + public override int ArmorBase => 13; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + 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 (Weight == 1.0) + Weight = 2.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeatherBustierArms.cs b/Projects/UOContent/Items/Armor/Leather/LeatherBustierArms.cs index 5c13fe509..a69dd4d4d 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeatherBustierArms.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeatherBustierArms.cs @@ -1,46 +1,46 @@ -namespace Server.Items -{ - [Flippable(0x1c0a, 0x1c0b)] - public class LeatherBustierArms : BaseArmor - { - [Constructible] - public LeatherBustierArms() : base(0x1C0A) => Weight = 1.0; - - public LeatherBustierArms(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 30; - public override int InitMaxHits => 40; - - public override int AosStrReq => 20; - public override int OldStrReq => 15; - - public override int ArmorBase => 13; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override bool AllowMaleWearer => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1c0a, 0x1c0b)] + public class LeatherBustierArms : BaseArmor + { + [Constructible] + public LeatherBustierArms() : base(0x1C0A) => Weight = 1.0; + + public LeatherBustierArms(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 30; + public override int InitMaxHits => 40; + + public override int AosStrReq => 20; + public override int OldStrReq => 15; + + public override int ArmorBase => 13; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + public override bool AllowMaleWearer => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeatherChest.cs b/Projects/UOContent/Items/Armor/Leather/LeatherChest.cs index 0b2c89ca2..56405a3d0 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeatherChest.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeatherChest.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - [Flippable(0x13cc, 0x13d3)] - public class LeatherChest : BaseArmor - { - [Constructible] - public LeatherChest() : base(0x13CC) => Weight = 6.0; - - public LeatherChest(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 30; - public override int InitMaxHits => 40; - - public override int AosStrReq => 25; - public override int OldStrReq => 15; - - public override int ArmorBase => 13; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 6.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x13cc, 0x13d3)] + public class LeatherChest : BaseArmor + { + [Constructible] + public LeatherChest() : base(0x13CC) => Weight = 6.0; + + public LeatherChest(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 30; + public override int InitMaxHits => 40; + + public override int AosStrReq => 25; + public override int OldStrReq => 15; + + public override int ArmorBase => 13; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + 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 (Weight == 1.0) + Weight = 6.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeatherDo.cs b/Projects/UOContent/Items/Armor/Leather/LeatherDo.cs index 4343e42d5..8ce578792 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeatherDo.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeatherDo.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - public class LeatherDo : BaseArmor - { - [Constructible] - public LeatherDo() : base(0x27C6) => Weight = 6.0; - - public LeatherDo(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 35; - public override int InitMaxHits => 45; - - public override int AosStrReq => 40; - public override int OldStrReq => 40; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LeatherDo : BaseArmor + { + [Constructible] + public LeatherDo() : base(0x27C6) => Weight = 6.0; + + public LeatherDo(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 35; + public override int InitMaxHits => 45; + + public override int AosStrReq => 40; + public override int OldStrReq => 40; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeatherGloves.cs b/Projects/UOContent/Items/Armor/Leather/LeatherGloves.cs index 7f226cf4d..e1ad83327 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeatherGloves.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeatherGloves.cs @@ -1,138 +1,138 @@ -namespace Server.Items -{ - [Flippable] - public class LeatherGloves : BaseArmor, IArcaneEquip - { - [Constructible] - public LeatherGloves() : base(0x13C6) => Weight = 1.0; - - public LeatherGloves(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 30; - public override int InitMaxHits => 40; - - public override int AosStrReq => 20; - public override int OldStrReq => 10; - - public override int ArmorBase => 13; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - if (IsArcane) - { - writer.Write(true); - writer.Write(m_CurArcaneCharges); - writer.Write(m_MaxArcaneCharges); - } - else - { - writer.Write(false); - } - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - if (reader.ReadBool()) - { - m_CurArcaneCharges = reader.ReadInt(); - m_MaxArcaneCharges = reader.ReadInt(); - - if (Hue == 2118) - Hue = ArcaneGem.DefaultArcaneHue; - } - - break; - } - } - } - - private int m_MaxArcaneCharges, m_CurArcaneCharges; - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxArcaneCharges - { - get => m_MaxArcaneCharges; - set - { - m_MaxArcaneCharges = value; - InvalidateProperties(); - Update(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int CurArcaneCharges - { - get => m_CurArcaneCharges; - set - { - m_CurArcaneCharges = value; - InvalidateProperties(); - Update(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsArcane => m_MaxArcaneCharges > 0 && m_CurArcaneCharges >= 0; - - public void Update() - { - if (IsArcane) - ItemID = 0x26B0; - else if (ItemID == 0x26B0) - ItemID = 0x13C6; - - if (IsArcane && CurArcaneCharges == 0) - Hue = 0; - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (IsArcane) - list.Add(1061837, "{0}\t{1}", m_CurArcaneCharges, m_MaxArcaneCharges); // arcane charges: ~1_val~ / ~2_val~ - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - if (IsArcane) - LabelTo(from, 1061837, $"{m_CurArcaneCharges}\t{m_MaxArcaneCharges}"); - } - - public void Flip() - { - if (ItemID == 0x13C6) - ItemID = 0x13CE; - else if (ItemID == 0x13CE) - ItemID = 0x13C6; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable] + public class LeatherGloves : BaseArmor, IArcaneEquip + { + private int m_MaxArcaneCharges, m_CurArcaneCharges; + + [Constructible] + public LeatherGloves() : base(0x13C6) => Weight = 1.0; + + public LeatherGloves(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 30; + public override int InitMaxHits => 40; + + public override int AosStrReq => 20; + public override int OldStrReq => 10; + + public override int ArmorBase => 13; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxArcaneCharges + { + get => m_MaxArcaneCharges; + set + { + m_MaxArcaneCharges = value; + InvalidateProperties(); + Update(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int CurArcaneCharges + { + get => m_CurArcaneCharges; + set + { + m_CurArcaneCharges = value; + InvalidateProperties(); + Update(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsArcane => m_MaxArcaneCharges > 0 && m_CurArcaneCharges >= 0; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + if (IsArcane) + { + writer.Write(true); + writer.Write(m_CurArcaneCharges); + writer.Write(m_MaxArcaneCharges); + } + else + { + writer.Write(false); + } + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + if (reader.ReadBool()) + { + m_CurArcaneCharges = reader.ReadInt(); + m_MaxArcaneCharges = reader.ReadInt(); + + if (Hue == 2118) + Hue = ArcaneGem.DefaultArcaneHue; + } + + break; + } + } + } + + public void Update() + { + if (IsArcane) + ItemID = 0x26B0; + else if (ItemID == 0x26B0) + ItemID = 0x13C6; + + if (IsArcane && CurArcaneCharges == 0) + Hue = 0; + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (IsArcane) + list.Add(1061837, "{0}\t{1}", m_CurArcaneCharges, m_MaxArcaneCharges); // arcane charges: ~1_val~ / ~2_val~ + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + if (IsArcane) + LabelTo(from, 1061837, $"{m_CurArcaneCharges}\t{m_MaxArcaneCharges}"); + } + + public void Flip() + { + if (ItemID == 0x13C6) + ItemID = 0x13CE; + else if (ItemID == 0x13CE) + ItemID = 0x13C6; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeatherGorget.cs b/Projects/UOContent/Items/Armor/Leather/LeatherGorget.cs index bd7b67616..9a7cb87a7 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeatherGorget.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeatherGorget.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - public class LeatherGorget : BaseArmor - { - [Constructible] - public LeatherGorget() : base(0x13C7) => Weight = 1.0; - - public LeatherGorget(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 30; - public override int InitMaxHits => 40; - - public override int AosStrReq => 20; - public override int OldStrReq => 10; - - public override int ArmorBase => 13; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LeatherGorget : BaseArmor + { + [Constructible] + public LeatherGorget() : base(0x13C7) => Weight = 1.0; + + public LeatherGorget(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 30; + public override int InitMaxHits => 40; + + public override int AosStrReq => 20; + public override int OldStrReq => 10; + + public override int ArmorBase => 13; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeatherHaidate.cs b/Projects/UOContent/Items/Armor/Leather/LeatherHaidate.cs index 376336e52..0ff994345 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeatherHaidate.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeatherHaidate.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - public class LeatherHaidate : BaseArmor - { - [Constructible] - public LeatherHaidate() : base(0x278A) => Weight = 4.0; - - public LeatherHaidate(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 30; - public override int InitMaxHits => 40; - - public override int AosStrReq => 20; - public override int OldStrReq => 20; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LeatherHaidate : BaseArmor + { + [Constructible] + public LeatherHaidate() : base(0x278A) => Weight = 4.0; + + public LeatherHaidate(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 30; + public override int InitMaxHits => 40; + + public override int AosStrReq => 20; + public override int OldStrReq => 20; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeatherHiroSode.cs b/Projects/UOContent/Items/Armor/Leather/LeatherHiroSode.cs index 40b5adc1c..4b117a004 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeatherHiroSode.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeatherHiroSode.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - public class LeatherHiroSode : BaseArmor - { - [Constructible] - public LeatherHiroSode() : base(0x277E) => Weight = 1.0; - - public LeatherHiroSode(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 40; - public override int InitMaxHits => 50; - - public override int AosStrReq => 25; - public override int OldStrReq => 25; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LeatherHiroSode : BaseArmor + { + [Constructible] + public LeatherHiroSode() : base(0x277E) => Weight = 1.0; + + public LeatherHiroSode(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 40; + public override int InitMaxHits => 50; + + public override int AosStrReq => 25; + public override int OldStrReq => 25; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeatherJingasa.cs b/Projects/UOContent/Items/Armor/Leather/LeatherJingasa.cs index 8776b423f..b8d19eb49 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeatherJingasa.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeatherJingasa.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - public class LeatherJingasa : BaseArmor - { - [Constructible] - public LeatherJingasa() : base(0x2776) => Weight = 3.0; - - public LeatherJingasa(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 4; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 2; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public override int AosStrReq => 25; - public override int OldStrReq => 25; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LeatherJingasa : BaseArmor + { + [Constructible] + public LeatherJingasa() : base(0x2776) => Weight = 3.0; + + public LeatherJingasa(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 4; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 2; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + public override int AosStrReq => 25; + public override int OldStrReq => 25; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeatherLegs.cs b/Projects/UOContent/Items/Armor/Leather/LeatherLegs.cs index 79844cafc..7834f02ca 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeatherLegs.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeatherLegs.cs @@ -1,44 +1,44 @@ -namespace Server.Items -{ - [Flippable(0x13cb, 0x13d2)] - public class LeatherLegs : BaseArmor - { - [Constructible] - public LeatherLegs() : base(0x13CB) => Weight = 4.0; - - public LeatherLegs(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 30; - public override int InitMaxHits => 40; - - public override int AosStrReq => 20; - public override int OldStrReq => 10; - - public override int ArmorBase => 13; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x13cb, 0x13d2)] + public class LeatherLegs : BaseArmor + { + [Constructible] + public LeatherLegs() : base(0x13CB) => Weight = 4.0; + + public LeatherLegs(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 30; + public override int InitMaxHits => 40; + + public override int AosStrReq => 20; + public override int OldStrReq => 10; + + public override int ArmorBase => 13; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeatherMempo.cs b/Projects/UOContent/Items/Armor/Leather/LeatherMempo.cs index 47d9f799f..246c5af69 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeatherMempo.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeatherMempo.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - public class LeatherMempo : BaseArmor - { - [Constructible] - public LeatherMempo() : base(0x277A) => Weight = 2.0; - - public LeatherMempo(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 35; - public override int InitMaxHits => 40; - - public override int AosStrReq => 30; - public override int OldStrReq => 30; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LeatherMempo : BaseArmor + { + [Constructible] + public LeatherMempo() : base(0x277A) => Weight = 2.0; + + public LeatherMempo(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 35; + public override int InitMaxHits => 40; + + public override int AosStrReq => 30; + public override int OldStrReq => 30; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeatherNinjaHood.cs b/Projects/UOContent/Items/Armor/Leather/LeatherNinjaHood.cs index 8aed0e924..c9c6f407a 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeatherNinjaHood.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeatherNinjaHood.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - public class LeatherNinjaHood : BaseArmor - { - [Constructible] - public LeatherNinjaHood() : base(0x278E) => Weight = 2.0; - - public LeatherNinjaHood(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 25; - public override int InitMaxHits => 45; - - public override int AosStrReq => 10; - public override int OldStrReq => 10; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LeatherNinjaHood : BaseArmor + { + [Constructible] + public LeatherNinjaHood() : base(0x278E) => Weight = 2.0; + + public LeatherNinjaHood(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 25; + public override int InitMaxHits => 45; + + public override int AosStrReq => 10; + public override int OldStrReq => 10; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeatherNinjaJacket.cs b/Projects/UOContent/Items/Armor/Leather/LeatherNinjaJacket.cs index f472e5341..180bc88ed 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeatherNinjaJacket.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeatherNinjaJacket.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - public class LeatherNinjaJacket : BaseArmor - { - [Constructible] - public LeatherNinjaJacket() : base(0x2793) => Weight = 5.0; - - public LeatherNinjaJacket(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 55; - public override int InitMaxHits => 65; - - public override int AosStrReq => 10; - public override int OldStrReq => 10; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LeatherNinjaJacket : BaseArmor + { + [Constructible] + public LeatherNinjaJacket() : base(0x2793) => Weight = 5.0; + + public LeatherNinjaJacket(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 55; + public override int InitMaxHits => 65; + + public override int AosStrReq => 10; + public override int OldStrReq => 10; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeatherNinjaMitts.cs b/Projects/UOContent/Items/Armor/Leather/LeatherNinjaMitts.cs index 2a64d5636..e556eceec 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeatherNinjaMitts.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeatherNinjaMitts.cs @@ -1,60 +1,60 @@ -namespace Server.Items -{ - public class LeatherNinjaMitts : BaseArmor - { - [Constructible] - public LeatherNinjaMitts() : base(0x2792) => Weight = 2.0; - - public LeatherNinjaMitts(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 25; - public override int InitMaxHits => 25; - - public override int AosStrReq => 10; - public override int OldStrReq => 10; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(2); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - if (reader.ReadBool()) - { - reader.ReadInt(); - reader.ReadInt(); - } - - Weight = 2.0; - ItemID = 0x2792; - - break; - } - } - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LeatherNinjaMitts : BaseArmor + { + [Constructible] + public LeatherNinjaMitts() : base(0x2792) => Weight = 2.0; + + public LeatherNinjaMitts(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 25; + public override int InitMaxHits => 25; + + public override int AosStrReq => 10; + public override int OldStrReq => 10; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(2); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + if (reader.ReadBool()) + { + reader.ReadInt(); + reader.ReadInt(); + } + + Weight = 2.0; + ItemID = 0x2792; + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeatherNinjaPants.cs b/Projects/UOContent/Items/Armor/Leather/LeatherNinjaPants.cs index 875622ccd..5fa20672e 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeatherNinjaPants.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeatherNinjaPants.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - public class LeatherNinjaPants : BaseArmor - { - [Constructible] - public LeatherNinjaPants() : base(0x2791) => Weight = 3.0; - - public LeatherNinjaPants(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 40; - public override int InitMaxHits => 50; - - public override int AosStrReq => 10; - public override int OldStrReq => 10; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LeatherNinjaPants : BaseArmor + { + [Constructible] + public LeatherNinjaPants() : base(0x2791) => Weight = 3.0; + + public LeatherNinjaPants(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 40; + public override int InitMaxHits => 50; + + public override int AosStrReq => 10; + public override int OldStrReq => 10; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeatherShorts.cs b/Projects/UOContent/Items/Armor/Leather/LeatherShorts.cs index 88bc2e286..27ed05b53 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeatherShorts.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeatherShorts.cs @@ -1,46 +1,46 @@ -namespace Server.Items -{ - [Flippable(0x1c00, 0x1c01)] - public class LeatherShorts : BaseArmor - { - [Constructible] - public LeatherShorts() : base(0x1C00) => Weight = 3.0; - - public LeatherShorts(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 30; - public override int InitMaxHits => 40; - - public override int AosStrReq => 20; - public override int OldStrReq => 10; - - public override int ArmorBase => 13; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override bool AllowMaleWearer => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1c00, 0x1c01)] + public class LeatherShorts : BaseArmor + { + [Constructible] + public LeatherShorts() : base(0x1C00) => Weight = 3.0; + + public LeatherShorts(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 30; + public override int InitMaxHits => 40; + + public override int AosStrReq => 20; + public override int OldStrReq => 10; + + public override int ArmorBase => 13; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + public override bool AllowMaleWearer => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeatherSkirt.cs b/Projects/UOContent/Items/Armor/Leather/LeatherSkirt.cs index a8f57783e..7f159e55c 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeatherSkirt.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeatherSkirt.cs @@ -1,49 +1,49 @@ -namespace Server.Items -{ - [Flippable(0x1c08, 0x1c09)] - public class LeatherSkirt : BaseArmor - { - [Constructible] - public LeatherSkirt() : base(0x1C08) => Weight = 1.0; - - public LeatherSkirt(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 30; - public override int InitMaxHits => 40; - - public override int AosStrReq => 20; - public override int OldStrReq => 10; - - public override int ArmorBase => 13; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override bool AllowMaleWearer => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - - if (Weight == 3.0) - Weight = 1.0; - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1c08, 0x1c09)] + public class LeatherSkirt : BaseArmor + { + [Constructible] + public LeatherSkirt() : base(0x1C08) => Weight = 1.0; + + public LeatherSkirt(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 30; + public override int InitMaxHits => 40; + + public override int AosStrReq => 20; + public override int OldStrReq => 10; + + public override int ArmorBase => 13; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + public override bool AllowMaleWearer => false; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(0); + + if (Weight == 3.0) + Weight = 1.0; + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Leather/LeatherSuneate.cs b/Projects/UOContent/Items/Armor/Leather/LeatherSuneate.cs index 6cad1b6ea..233a0f260 100644 --- a/Projects/UOContent/Items/Armor/Leather/LeatherSuneate.cs +++ b/Projects/UOContent/Items/Armor/Leather/LeatherSuneate.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - public class LeatherSuneate : BaseArmor - { - [Constructible] - public LeatherSuneate() : base(0x2786) => Weight = 4.0; - - public LeatherSuneate(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 25; - public override int InitMaxHits => 40; - - public override int AosStrReq => 20; - public override int OldStrReq => 20; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LeatherSuneate : BaseArmor + { + [Constructible] + public LeatherSuneate() : base(0x2786) => Weight = 4.0; + + public LeatherSuneate(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 25; + public override int InitMaxHits => 40; + + public override int AosStrReq => 20; + public override int OldStrReq => 20; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/DecorativePlateKabuto.cs b/Projects/UOContent/Items/Armor/Plate/DecorativePlateKabuto.cs index 2b96c8704..57a088cf1 100644 --- a/Projects/UOContent/Items/Armor/Plate/DecorativePlateKabuto.cs +++ b/Projects/UOContent/Items/Armor/Plate/DecorativePlateKabuto.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class DecorativePlateKabuto : BaseArmor - { - [Constructible] - public DecorativePlateKabuto() : base(0x2778) => Weight = 6.0; - - public DecorativePlateKabuto(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 6; - public override int BaseFireResistance => 2; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 2; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 55; - public override int InitMaxHits => 75; - - public override int AosStrReq => 70; - public override int OldStrReq => 70; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class DecorativePlateKabuto : BaseArmor + { + [Constructible] + public DecorativePlateKabuto() : base(0x2778) => Weight = 6.0; + + public DecorativePlateKabuto(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 6; + public override int BaseFireResistance => 2; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 2; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 55; + public override int InitMaxHits => 75; + + public override int AosStrReq => 70; + public override int OldStrReq => 70; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/FemalePlateChest.cs b/Projects/UOContent/Items/Armor/Plate/FemalePlateChest.cs index fe5599c64..5ae1975d6 100644 --- a/Projects/UOContent/Items/Armor/Plate/FemalePlateChest.cs +++ b/Projects/UOContent/Items/Armor/Plate/FemalePlateChest.cs @@ -1,48 +1,48 @@ -namespace Server.Items -{ - [Flippable(0x1c04, 0x1c05)] - public class FemalePlateChest : BaseArmor - { - [Constructible] - public FemalePlateChest() : base(0x1C04) => Weight = 4.0; - - public FemalePlateChest(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 50; - public override int InitMaxHits => 65; - - public override int AosStrReq => 95; - public override int OldStrReq => 45; - - public override int OldDexBonus => -5; - - public override bool AllowMaleWearer => false; - - public override int ArmorBase => 30; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 4.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1c04, 0x1c05)] + public class FemalePlateChest : BaseArmor + { + [Constructible] + public FemalePlateChest() : base(0x1C04) => Weight = 4.0; + + public FemalePlateChest(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 50; + public override int InitMaxHits => 65; + + public override int AosStrReq => 95; + public override int OldStrReq => 45; + + public override int OldDexBonus => -5; + + public override bool AllowMaleWearer => false; + + public override int ArmorBase => 30; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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 (Weight == 1.0) + Weight = 4.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/FemaleWoodlandChest.cs b/Projects/UOContent/Items/Armor/Plate/FemaleWoodlandChest.cs index 973aef575..02b8a0cde 100644 --- a/Projects/UOContent/Items/Armor/Plate/FemaleWoodlandChest.cs +++ b/Projects/UOContent/Items/Armor/Plate/FemaleWoodlandChest.cs @@ -1,46 +1,46 @@ -namespace Server.Items -{ - // Is this a filler-type item? the clilocs don't match up and at a glacnce I can't find direct reference of it - [Flippable(0x2B6D, 0x3164)] - public class FemaleElvenPlateChest : BaseArmor - { - [Constructible] - public FemaleElvenPlateChest() : base(0x2B6D) => Weight = 8.0; - - public FemaleElvenPlateChest(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 50; - public override int InitMaxHits => 65; - - public override int AosStrReq => 95; - public override int OldStrReq => 95; - - public override bool AllowMaleWearer => false; - - public override int ArmorBase => 30; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + // Is this a filler-type item? the clilocs don't match up and at a glacnce I can't find direct reference of it + [Flippable(0x2B6D, 0x3164)] + public class FemaleElvenPlateChest : BaseArmor + { + [Constructible] + public FemaleElvenPlateChest() : base(0x2B6D) => Weight = 8.0; + + public FemaleElvenPlateChest(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 50; + public override int InitMaxHits => 65; + + public override int AosStrReq => 95; + public override int OldStrReq => 95; + + public override bool AllowMaleWearer => false; + + public override int ArmorBase => 30; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/HeavyPlateJingasa.cs b/Projects/UOContent/Items/Armor/Plate/HeavyPlateJingasa.cs index 94e868ea0..b906df997 100644 --- a/Projects/UOContent/Items/Armor/Plate/HeavyPlateJingasa.cs +++ b/Projects/UOContent/Items/Armor/Plate/HeavyPlateJingasa.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class HeavyPlateJingasa : BaseArmor - { - [Constructible] - public HeavyPlateJingasa() : base(0x2777) => Weight = 5.0; - - public HeavyPlateJingasa(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 7; - public override int BaseFireResistance => 2; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 2; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 50; - public override int InitMaxHits => 70; - - public override int AosStrReq => 55; - public override int OldStrReq => 55; - - public override int ArmorBase => 4; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class HeavyPlateJingasa : BaseArmor + { + [Constructible] + public HeavyPlateJingasa() : base(0x2777) => Weight = 5.0; + + public HeavyPlateJingasa(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 7; + public override int BaseFireResistance => 2; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 2; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 50; + public override int InitMaxHits => 70; + + public override int AosStrReq => 55; + public override int OldStrReq => 55; + + public override int ArmorBase => 4; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/LightPlateJingasa.cs b/Projects/UOContent/Items/Armor/Plate/LightPlateJingasa.cs index 1695da77b..eb16788b2 100644 --- a/Projects/UOContent/Items/Armor/Plate/LightPlateJingasa.cs +++ b/Projects/UOContent/Items/Armor/Plate/LightPlateJingasa.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class LightPlateJingasa : BaseArmor - { - [Constructible] - public LightPlateJingasa() : base(0x2781) => Weight = 5.0; - - public LightPlateJingasa(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 7; - public override int BaseFireResistance => 2; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 2; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 55; - public override int InitMaxHits => 60; - - public override int AosStrReq => 55; - public override int OldStrReq => 55; - - public override int ArmorBase => 4; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LightPlateJingasa : BaseArmor + { + [Constructible] + public LightPlateJingasa() : base(0x2781) => Weight = 5.0; + + public LightPlateJingasa(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 7; + public override int BaseFireResistance => 2; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 2; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 55; + public override int InitMaxHits => 60; + + public override int AosStrReq => 55; + public override int OldStrReq => 55; + + public override int ArmorBase => 4; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/PlateArms.cs b/Projects/UOContent/Items/Armor/Plate/PlateArms.cs index ae1d9b533..a394475cf 100644 --- a/Projects/UOContent/Items/Armor/Plate/PlateArms.cs +++ b/Projects/UOContent/Items/Armor/Plate/PlateArms.cs @@ -1,46 +1,46 @@ -namespace Server.Items -{ - [Flippable(0x1410, 0x1417)] - public class PlateArms : BaseArmor - { - [Constructible] - public PlateArms() : base(0x1410) => Weight = 5.0; - - public PlateArms(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 50; - public override int InitMaxHits => 65; - - public override int AosStrReq => 80; - public override int OldStrReq => 40; - - public override int OldDexBonus => -2; - - public override int ArmorBase => 40; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 5.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1410, 0x1417)] + public class PlateArms : BaseArmor + { + [Constructible] + public PlateArms() : base(0x1410) => Weight = 5.0; + + public PlateArms(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 50; + public override int InitMaxHits => 65; + + public override int AosStrReq => 80; + public override int OldStrReq => 40; + + public override int OldDexBonus => -2; + + public override int ArmorBase => 40; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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 (Weight == 1.0) + Weight = 5.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/PlateBattleKabuto.cs b/Projects/UOContent/Items/Armor/Plate/PlateBattleKabuto.cs index 03e723e46..ab859eb12 100644 --- a/Projects/UOContent/Items/Armor/Plate/PlateBattleKabuto.cs +++ b/Projects/UOContent/Items/Armor/Plate/PlateBattleKabuto.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class PlateBattleKabuto : BaseArmor - { - [Constructible] - public PlateBattleKabuto() : base(0x2785) => Weight = 6.0; - - public PlateBattleKabuto(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 6; - public override int BaseFireResistance => 2; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 2; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 60; - public override int InitMaxHits => 65; - - public override int AosStrReq => 70; - public override int OldStrReq => 70; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PlateBattleKabuto : BaseArmor + { + [Constructible] + public PlateBattleKabuto() : base(0x2785) => Weight = 6.0; + + public PlateBattleKabuto(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 6; + public override int BaseFireResistance => 2; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 2; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 60; + public override int InitMaxHits => 65; + + public override int AosStrReq => 70; + public override int OldStrReq => 70; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/PlateChest.cs b/Projects/UOContent/Items/Armor/Plate/PlateChest.cs index a42542be7..6912181c8 100644 --- a/Projects/UOContent/Items/Armor/Plate/PlateChest.cs +++ b/Projects/UOContent/Items/Armor/Plate/PlateChest.cs @@ -1,46 +1,46 @@ -namespace Server.Items -{ - [Flippable(0x1415, 0x1416)] - public class PlateChest : BaseArmor - { - [Constructible] - public PlateChest() : base(0x1415) => Weight = 10.0; - - public PlateChest(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 50; - public override int InitMaxHits => 65; - - public override int AosStrReq => 95; - public override int OldStrReq => 60; - - public override int OldDexBonus => -8; - - public override int ArmorBase => 40; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 10.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1415, 0x1416)] + public class PlateChest : BaseArmor + { + [Constructible] + public PlateChest() : base(0x1415) => Weight = 10.0; + + public PlateChest(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 50; + public override int InitMaxHits => 65; + + public override int AosStrReq => 95; + public override int OldStrReq => 60; + + public override int OldDexBonus => -8; + + public override int ArmorBase => 40; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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 (Weight == 1.0) + Weight = 10.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/PlateDo.cs b/Projects/UOContent/Items/Armor/Plate/PlateDo.cs index 41196103d..75198caba 100644 --- a/Projects/UOContent/Items/Armor/Plate/PlateDo.cs +++ b/Projects/UOContent/Items/Armor/Plate/PlateDo.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class PlateDo : BaseArmor - { - [Constructible] - public PlateDo() : base(0x277D) => Weight = 10.0; - - public PlateDo(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 60; - public override int InitMaxHits => 70; - - public override int AosStrReq => 85; - public override int OldStrReq => 85; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PlateDo : BaseArmor + { + [Constructible] + public PlateDo() : base(0x277D) => Weight = 10.0; + + public PlateDo(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 60; + public override int InitMaxHits => 70; + + public override int AosStrReq => 85; + public override int OldStrReq => 85; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/PlateGloves.cs b/Projects/UOContent/Items/Armor/Plate/PlateGloves.cs index 491f9d70a..6c3dbf72c 100644 --- a/Projects/UOContent/Items/Armor/Plate/PlateGloves.cs +++ b/Projects/UOContent/Items/Armor/Plate/PlateGloves.cs @@ -1,46 +1,46 @@ -namespace Server.Items -{ - [Flippable(0x1414, 0x1418)] - public class PlateGloves : BaseArmor - { - [Constructible] - public PlateGloves() : base(0x1414) => Weight = 2.0; - - public PlateGloves(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 50; - public override int InitMaxHits => 65; - - public override int AosStrReq => 70; - public override int OldStrReq => 30; - - public override int OldDexBonus => -2; - - public override int ArmorBase => 40; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 2.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1414, 0x1418)] + public class PlateGloves : BaseArmor + { + [Constructible] + public PlateGloves() : base(0x1414) => Weight = 2.0; + + public PlateGloves(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 50; + public override int InitMaxHits => 65; + + public override int AosStrReq => 70; + public override int OldStrReq => 30; + + public override int OldDexBonus => -2; + + public override int ArmorBase => 40; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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 (Weight == 1.0) + Weight = 2.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/PlateGorget.cs b/Projects/UOContent/Items/Armor/Plate/PlateGorget.cs index 01bbd8900..dcaec124c 100644 --- a/Projects/UOContent/Items/Armor/Plate/PlateGorget.cs +++ b/Projects/UOContent/Items/Armor/Plate/PlateGorget.cs @@ -1,42 +1,42 @@ -namespace Server.Items -{ - public class PlateGorget : BaseArmor - { - [Constructible] - public PlateGorget() : base(0x1413) => Weight = 2.0; - - public PlateGorget(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 50; - public override int InitMaxHits => 65; - - public override int AosStrReq => 45; - public override int OldStrReq => 30; - - public override int OldDexBonus => -1; - - public override int ArmorBase => 40; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PlateGorget : BaseArmor + { + [Constructible] + public PlateGorget() : base(0x1413) => Weight = 2.0; + + public PlateGorget(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 50; + public override int InitMaxHits => 65; + + public override int AosStrReq => 45; + public override int OldStrReq => 30; + + public override int OldDexBonus => -1; + + public override int ArmorBase => 40; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/PlateHaidate.cs b/Projects/UOContent/Items/Armor/Plate/PlateHaidate.cs index 175230021..0115504b8 100644 --- a/Projects/UOContent/Items/Armor/Plate/PlateHaidate.cs +++ b/Projects/UOContent/Items/Armor/Plate/PlateHaidate.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class PlateHaidate : BaseArmor - { - [Constructible] - public PlateHaidate() : base(0x278D) => Weight = 7.0; - - public PlateHaidate(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 55; - public override int InitMaxHits => 65; - - public override int AosStrReq => 80; - public override int OldStrReq => 80; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PlateHaidate : BaseArmor + { + [Constructible] + public PlateHaidate() : base(0x278D) => Weight = 7.0; + + public PlateHaidate(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 55; + public override int InitMaxHits => 65; + + public override int AosStrReq => 80; + public override int OldStrReq => 80; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/PlateHatsuburi.cs b/Projects/UOContent/Items/Armor/Plate/PlateHatsuburi.cs index 71f40ffb4..2b8c85d6b 100644 --- a/Projects/UOContent/Items/Armor/Plate/PlateHatsuburi.cs +++ b/Projects/UOContent/Items/Armor/Plate/PlateHatsuburi.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class PlateHatsuburi : BaseArmor - { - [Constructible] - public PlateHatsuburi() : base(0x2775) => Weight = 5.0; - - public PlateHatsuburi(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 2; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 55; - public override int InitMaxHits => 75; - - public override int AosStrReq => 65; - public override int OldStrReq => 65; - - public override int ArmorBase => 4; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PlateHatsuburi : BaseArmor + { + [Constructible] + public PlateHatsuburi() : base(0x2775) => Weight = 5.0; + + public PlateHatsuburi(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 2; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 55; + public override int InitMaxHits => 75; + + public override int AosStrReq => 65; + public override int OldStrReq => 65; + + public override int ArmorBase => 4; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/PlateHiroSode.cs b/Projects/UOContent/Items/Armor/Plate/PlateHiroSode.cs index a7073d7dd..12f757ce3 100644 --- a/Projects/UOContent/Items/Armor/Plate/PlateHiroSode.cs +++ b/Projects/UOContent/Items/Armor/Plate/PlateHiroSode.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class PlateHiroSode : BaseArmor - { - [Constructible] - public PlateHiroSode() : base(0x2780) => Weight = 3.0; - - public PlateHiroSode(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 55; - public override int InitMaxHits => 75; - - public override int AosStrReq => 75; - public override int OldStrReq => 75; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PlateHiroSode : BaseArmor + { + [Constructible] + public PlateHiroSode() : base(0x2780) => Weight = 3.0; + + public PlateHiroSode(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 55; + public override int InitMaxHits => 75; + + public override int AosStrReq => 75; + public override int OldStrReq => 75; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/PlateLegs.cs b/Projects/UOContent/Items/Armor/Plate/PlateLegs.cs index 5f5d1bb02..697f94120 100644 --- a/Projects/UOContent/Items/Armor/Plate/PlateLegs.cs +++ b/Projects/UOContent/Items/Armor/Plate/PlateLegs.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - [Flippable(0x1411, 0x141a)] - public class PlateLegs : BaseArmor - { - [Constructible] - public PlateLegs() : base(0x1411) => Weight = 7.0; - - public PlateLegs(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 50; - public override int InitMaxHits => 65; - - public override int AosStrReq => 90; - - public override int OldStrReq => 60; - public override int OldDexBonus => -6; - - public override int ArmorBase => 40; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1411, 0x141a)] + public class PlateLegs : BaseArmor + { + [Constructible] + public PlateLegs() : base(0x1411) => Weight = 7.0; + + public PlateLegs(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 50; + public override int InitMaxHits => 65; + + public override int AosStrReq => 90; + + public override int OldStrReq => 60; + public override int OldDexBonus => -6; + + public override int ArmorBase => 40; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/PlateMempo.cs b/Projects/UOContent/Items/Armor/Plate/PlateMempo.cs index 4afe9fad3..01bf698c7 100644 --- a/Projects/UOContent/Items/Armor/Plate/PlateMempo.cs +++ b/Projects/UOContent/Items/Armor/Plate/PlateMempo.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class PlateMempo : BaseArmor - { - [Constructible] - public PlateMempo() : base(0x2779) => Weight = 3.0; - - public PlateMempo(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 60; - public override int InitMaxHits => 70; - - public override int AosStrReq => 50; - public override int OldStrReq => 50; - - public override int ArmorBase => 4; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PlateMempo : BaseArmor + { + [Constructible] + public PlateMempo() : base(0x2779) => Weight = 3.0; + + public PlateMempo(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 60; + public override int InitMaxHits => 70; + + public override int AosStrReq => 50; + public override int OldStrReq => 50; + + public override int ArmorBase => 4; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/PlateSuneate.cs b/Projects/UOContent/Items/Armor/Plate/PlateSuneate.cs index ea92efff8..984e0aff2 100644 --- a/Projects/UOContent/Items/Armor/Plate/PlateSuneate.cs +++ b/Projects/UOContent/Items/Armor/Plate/PlateSuneate.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class PlateSuneate : BaseArmor - { - [Constructible] - public PlateSuneate() : base(0x2788) => Weight = 7.0; - - public PlateSuneate(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 55; - public override int InitMaxHits => 65; - - public override int AosStrReq => 80; - public override int OldStrReq => 80; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PlateSuneate : BaseArmor + { + [Constructible] + public PlateSuneate() : base(0x2788) => Weight = 7.0; + + public PlateSuneate(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 55; + public override int InitMaxHits => 65; + + public override int AosStrReq => 80; + public override int OldStrReq => 80; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/SmallPlateJingasa.cs b/Projects/UOContent/Items/Armor/Plate/SmallPlateJingasa.cs index fc4c112b2..31f69e9b0 100644 --- a/Projects/UOContent/Items/Armor/Plate/SmallPlateJingasa.cs +++ b/Projects/UOContent/Items/Armor/Plate/SmallPlateJingasa.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class SmallPlateJingasa : BaseArmor - { - [Constructible] - public SmallPlateJingasa() : base(0x2784) => Weight = 5.0; - - public SmallPlateJingasa(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 7; - public override int BaseFireResistance => 2; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 2; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 55; - public override int InitMaxHits => 60; - - public override int AosStrReq => 55; - public override int OldStrReq => 55; - - public override int ArmorBase => 4; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SmallPlateJingasa : BaseArmor + { + [Constructible] + public SmallPlateJingasa() : base(0x2784) => Weight = 5.0; + + public SmallPlateJingasa(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 7; + public override int BaseFireResistance => 2; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 2; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 55; + public override int InitMaxHits => 60; + + public override int AosStrReq => 55; + public override int OldStrReq => 55; + + public override int ArmorBase => 4; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/StandardPlateKabuto.cs b/Projects/UOContent/Items/Armor/Plate/StandardPlateKabuto.cs index 961772d49..9e581bed2 100644 --- a/Projects/UOContent/Items/Armor/Plate/StandardPlateKabuto.cs +++ b/Projects/UOContent/Items/Armor/Plate/StandardPlateKabuto.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class StandardPlateKabuto : BaseArmor - { - [Constructible] - public StandardPlateKabuto() : base(0x2789) => Weight = 6.0; - - public StandardPlateKabuto(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 6; - public override int BaseFireResistance => 2; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 2; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 60; - public override int InitMaxHits => 65; - - public override int AosStrReq => 70; - public override int OldStrReq => 70; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class StandardPlateKabuto : BaseArmor + { + [Constructible] + public StandardPlateKabuto() : base(0x2789) => Weight = 6.0; + + public StandardPlateKabuto(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 6; + public override int BaseFireResistance => 2; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 2; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 60; + public override int InitMaxHits => 65; + + public override int AosStrReq => 70; + public override int OldStrReq => 70; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/WoodlandArms.cs b/Projects/UOContent/Items/Armor/Plate/WoodlandArms.cs index b0e0b61f6..fcaa94ed9 100644 --- a/Projects/UOContent/Items/Armor/Plate/WoodlandArms.cs +++ b/Projects/UOContent/Items/Armor/Plate/WoodlandArms.cs @@ -1,44 +1,44 @@ -namespace Server.Items -{ - [Flippable(0x2B6C, 0x3163)] - public class WoodlandArms : BaseArmor - { - [Constructible] - public WoodlandArms() : base(0x2B6C) => Weight = 5.0; - - public WoodlandArms(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 50; - public override int InitMaxHits => 65; - - public override int AosStrReq => 80; - public override int OldStrReq => 80; - - public override int ArmorBase => 40; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - public override Race RequiredRace => Race.Elf; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2B6C, 0x3163)] + public class WoodlandArms : BaseArmor + { + [Constructible] + public WoodlandArms() : base(0x2B6C) => Weight = 5.0; + + public WoodlandArms(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 50; + public override int InitMaxHits => 65; + + public override int AosStrReq => 80; + public override int OldStrReq => 80; + + public override int ArmorBase => 40; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + public override Race RequiredRace => Race.Elf; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/WoodlandChest.cs b/Projects/UOContent/Items/Armor/Plate/WoodlandChest.cs index b1b523af2..44d90357c 100644 --- a/Projects/UOContent/Items/Armor/Plate/WoodlandChest.cs +++ b/Projects/UOContent/Items/Armor/Plate/WoodlandChest.cs @@ -1,44 +1,44 @@ -namespace Server.Items -{ - [Flippable(0x2B67, 0x315E)] - public class WoodlandChest : BaseArmor - { - [Constructible] - public WoodlandChest() : base(0x2B67) => Weight = 8.0; - - public WoodlandChest(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 50; - public override int InitMaxHits => 65; - - public override int AosStrReq => 95; - public override int OldStrReq => 95; - - public override int ArmorBase => 40; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - public override Race RequiredRace => Race.Elf; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2B67, 0x315E)] + public class WoodlandChest : BaseArmor + { + [Constructible] + public WoodlandChest() : base(0x2B67) => Weight = 8.0; + + public WoodlandChest(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 50; + public override int InitMaxHits => 65; + + public override int AosStrReq => 95; + public override int OldStrReq => 95; + + public override int ArmorBase => 40; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + public override Race RequiredRace => Race.Elf; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/WoodlandGloves.cs b/Projects/UOContent/Items/Armor/Plate/WoodlandGloves.cs index 58929c88b..cc7e28fb0 100644 --- a/Projects/UOContent/Items/Armor/Plate/WoodlandGloves.cs +++ b/Projects/UOContent/Items/Armor/Plate/WoodlandGloves.cs @@ -1,44 +1,44 @@ -namespace Server.Items -{ - [Flippable(0x2B6A, 0x3161)] - public class WoodlandGloves : BaseArmor - { - [Constructible] - public WoodlandGloves() : base(0x2B6A) => Weight = 2.0; - - public WoodlandGloves(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 50; - public override int InitMaxHits => 65; - - public override int AosStrReq => 70; - public override int OldStrReq => 70; - - public override int ArmorBase => 40; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - public override Race RequiredRace => Race.Elf; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2B6A, 0x3161)] + public class WoodlandGloves : BaseArmor + { + [Constructible] + public WoodlandGloves() : base(0x2B6A) => Weight = 2.0; + + public WoodlandGloves(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 50; + public override int InitMaxHits => 65; + + public override int AosStrReq => 70; + public override int OldStrReq => 70; + + public override int ArmorBase => 40; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + public override Race RequiredRace => Race.Elf; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/WoodlandGorget.cs b/Projects/UOContent/Items/Armor/Plate/WoodlandGorget.cs index 421622ac7..d4a2a577c 100644 --- a/Projects/UOContent/Items/Armor/Plate/WoodlandGorget.cs +++ b/Projects/UOContent/Items/Armor/Plate/WoodlandGorget.cs @@ -1,49 +1,49 @@ -namespace Server.Items -{ - [Flippable(0x2B69, 0x3160)] - public class WoodlandGorget : BaseArmor - { - [Constructible] - public WoodlandGorget() : base(0x2B69) - { - } - - public WoodlandGorget(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 50; - public override int InitMaxHits => 65; - - public override int AosStrReq => 45; - public override int OldStrReq => 45; - - public override int ArmorBase => 40; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - public override Race RequiredRace => Race.Elf; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - if (version == 0) - Weight = -1; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2B69, 0x3160)] + public class WoodlandGorget : BaseArmor + { + [Constructible] + public WoodlandGorget() : base(0x2B69) + { + } + + public WoodlandGorget(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 50; + public override int InitMaxHits => 65; + + public override int AosStrReq => 45; + public override int OldStrReq => 45; + + public override int ArmorBase => 40; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + public override Race RequiredRace => Race.Elf; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(1); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + if (version == 0) + Weight = -1; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Plate/WoodlandLegs.cs b/Projects/UOContent/Items/Armor/Plate/WoodlandLegs.cs index 0056b0a9d..094ca3722 100644 --- a/Projects/UOContent/Items/Armor/Plate/WoodlandLegs.cs +++ b/Projects/UOContent/Items/Armor/Plate/WoodlandLegs.cs @@ -1,44 +1,44 @@ -namespace Server.Items -{ - [Flippable(0x2B6B, 0x3162)] - public class WoodlandLegs : BaseArmor - { - [Constructible] - public WoodlandLegs() : base(0x2B6B) => Weight = 8.0; - - public WoodlandLegs(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 2; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 50; - public override int InitMaxHits => 65; - - public override int AosStrReq => 90; - public override int OldStrReq => 90; - - public override int ArmorBase => 40; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - public override Race RequiredRace => Race.Elf; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2B6B, 0x3162)] + public class WoodlandLegs : BaseArmor + { + [Constructible] + public WoodlandLegs() : base(0x2B6B) => Weight = 8.0; + + public WoodlandLegs(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 2; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 50; + public override int InitMaxHits => 65; + + public override int AosStrReq => 90; + public override int OldStrReq => 90; + + public override int ArmorBase => 40; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + public override Race RequiredRace => Race.Elf; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Ranger/RangerArms.cs b/Projects/UOContent/Items/Armor/Ranger/RangerArms.cs index 70cd1dbb3..70fb1e87e 100644 --- a/Projects/UOContent/Items/Armor/Ranger/RangerArms.cs +++ b/Projects/UOContent/Items/Armor/Ranger/RangerArms.cs @@ -1,51 +1,51 @@ -namespace Server.Items -{ - [Flippable(0x13dc, 0x13d4)] - public class RangerArms : BaseArmor - { - [Constructible] - public RangerArms() : base(0x13DC) - { - Weight = 4.0; - Hue = 0x59C; - } - - public RangerArms(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 35; - public override int InitMaxHits => 45; - - public override int AosStrReq => 25; - public override int OldStrReq => 25; - - public override int ArmorBase => 16; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override int LabelNumber => 1041493; // studded sleeves, ranger armor - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 4.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x13dc, 0x13d4)] + public class RangerArms : BaseArmor + { + [Constructible] + public RangerArms() : base(0x13DC) + { + Weight = 4.0; + Hue = 0x59C; + } + + public RangerArms(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 35; + public override int InitMaxHits => 45; + + public override int AosStrReq => 25; + public override int OldStrReq => 25; + + public override int ArmorBase => 16; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override int LabelNumber => 1041493; // studded sleeves, ranger armor + + 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 (Weight == 1.0) + Weight = 4.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Ranger/RangerChest.cs b/Projects/UOContent/Items/Armor/Ranger/RangerChest.cs index 02c830aa2..ff6dc1189 100644 --- a/Projects/UOContent/Items/Armor/Ranger/RangerChest.cs +++ b/Projects/UOContent/Items/Armor/Ranger/RangerChest.cs @@ -1,51 +1,51 @@ -namespace Server.Items -{ - [Flippable(0x13db, 0x13e2)] - public class RangerChest : BaseArmor - { - [Constructible] - public RangerChest() : base(0x13DB) - { - Weight = 8.0; - Hue = 0x59C; - } - - public RangerChest(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 35; - public override int InitMaxHits => 45; - - public override int AosStrReq => 35; - public override int OldStrReq => 35; - - public override int ArmorBase => 16; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override int LabelNumber => 1041497; // studded tunic, ranger armor - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 8.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x13db, 0x13e2)] + public class RangerChest : BaseArmor + { + [Constructible] + public RangerChest() : base(0x13DB) + { + Weight = 8.0; + Hue = 0x59C; + } + + public RangerChest(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 35; + public override int InitMaxHits => 45; + + public override int AosStrReq => 35; + public override int OldStrReq => 35; + + public override int ArmorBase => 16; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override int LabelNumber => 1041497; // studded tunic, ranger armor + + 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 (Weight == 1.0) + Weight = 8.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Ranger/RangerGloves.cs b/Projects/UOContent/Items/Armor/Ranger/RangerGloves.cs index e76250092..918af1c94 100644 --- a/Projects/UOContent/Items/Armor/Ranger/RangerGloves.cs +++ b/Projects/UOContent/Items/Armor/Ranger/RangerGloves.cs @@ -1,48 +1,48 @@ -namespace Server.Items -{ - [Flippable(0x13d5, 0x13dd)] - public class RangerGloves : BaseArmor - { - [Constructible] - public RangerGloves() : base(0x13D5) - { - Weight = 1.0; - Hue = 0x59C; - } - - public RangerGloves(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 35; - public override int InitMaxHits => 45; - - public override int AosStrReq => 25; - public override int OldStrReq => 25; - - public override int ArmorBase => 16; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override int LabelNumber => 1041494; // studded gloves, ranger armor - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x13d5, 0x13dd)] + public class RangerGloves : BaseArmor + { + [Constructible] + public RangerGloves() : base(0x13D5) + { + Weight = 1.0; + Hue = 0x59C; + } + + public RangerGloves(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 35; + public override int InitMaxHits => 45; + + public override int AosStrReq => 25; + public override int OldStrReq => 25; + + public override int ArmorBase => 16; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override int LabelNumber => 1041494; // studded gloves, ranger armor + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Ranger/RangerGorget.cs b/Projects/UOContent/Items/Armor/Ranger/RangerGorget.cs index 2cbe6c50d..d161fffac 100644 --- a/Projects/UOContent/Items/Armor/Ranger/RangerGorget.cs +++ b/Projects/UOContent/Items/Armor/Ranger/RangerGorget.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - public class RangerGorget : BaseArmor - { - [Constructible] - public RangerGorget() : base(0x13D6) - { - Weight = 1.0; - Hue = 0x59C; - } - - public RangerGorget(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 35; - public override int InitMaxHits => 45; - - public override int AosStrReq => 25; - public override int OldStrReq => 25; - - public override int ArmorBase => 16; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override int LabelNumber => 1041495; // studded gorget, ranger armor - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class RangerGorget : BaseArmor + { + [Constructible] + public RangerGorget() : base(0x13D6) + { + Weight = 1.0; + Hue = 0x59C; + } + + public RangerGorget(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 35; + public override int InitMaxHits => 45; + + public override int AosStrReq => 25; + public override int OldStrReq => 25; + + public override int ArmorBase => 16; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override int LabelNumber => 1041495; // studded gorget, ranger armor + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Ranger/RangerLegs.cs b/Projects/UOContent/Items/Armor/Ranger/RangerLegs.cs index 41651b576..a51f90a43 100644 --- a/Projects/UOContent/Items/Armor/Ranger/RangerLegs.cs +++ b/Projects/UOContent/Items/Armor/Ranger/RangerLegs.cs @@ -1,51 +1,51 @@ -namespace Server.Items -{ - [Flippable(0x13da, 0x13e1)] - public class RangerLegs : BaseArmor - { - [Constructible] - public RangerLegs() : base(0x13DA) - { - Weight = 3.0; - Hue = 0x59C; - } - - public RangerLegs(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 35; - public override int InitMaxHits => 45; - - public override int AosStrReq => 30; - public override int OldStrReq => 35; - - public override int ArmorBase => 16; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override int LabelNumber => 1041496; // studded leggings, ranger armor - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 3.0) - Weight = 5.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x13da, 0x13e1)] + public class RangerLegs : BaseArmor + { + [Constructible] + public RangerLegs() : base(0x13DA) + { + Weight = 3.0; + Hue = 0x59C; + } + + public RangerLegs(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 35; + public override int InitMaxHits => 45; + + public override int AosStrReq => 30; + public override int OldStrReq => 35; + + public override int ArmorBase => 16; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override int LabelNumber => 1041496; // studded leggings, ranger armor + + 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 (Weight == 3.0) + Weight = 5.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Ring/RingmailArms.cs b/Projects/UOContent/Items/Armor/Ring/RingmailArms.cs index 8c720058b..b12c4f04f 100644 --- a/Projects/UOContent/Items/Armor/Ring/RingmailArms.cs +++ b/Projects/UOContent/Items/Armor/Ring/RingmailArms.cs @@ -1,46 +1,46 @@ -namespace Server.Items -{ - [Flippable(0x13ee, 0x13ef)] - public class RingmailArms : BaseArmor - { - [Constructible] - public RingmailArms() : base(0x13EE) => Weight = 15.0; - - public RingmailArms(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 1; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 40; - public override int InitMaxHits => 50; - - public override int AosStrReq => 40; - public override int OldStrReq => 20; - - public override int OldDexBonus => -1; - - public override int ArmorBase => 22; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Ringmail; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 15.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x13ee, 0x13ef)] + public class RingmailArms : BaseArmor + { + [Constructible] + public RingmailArms() : base(0x13EE) => Weight = 15.0; + + public RingmailArms(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 1; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 40; + public override int InitMaxHits => 50; + + public override int AosStrReq => 40; + public override int OldStrReq => 20; + + public override int OldDexBonus => -1; + + public override int ArmorBase => 22; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Ringmail; + + 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 (Weight == 1.0) + Weight = 15.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Ring/RingmailChest.cs b/Projects/UOContent/Items/Armor/Ring/RingmailChest.cs index 7f2e525b7..211343652 100644 --- a/Projects/UOContent/Items/Armor/Ring/RingmailChest.cs +++ b/Projects/UOContent/Items/Armor/Ring/RingmailChest.cs @@ -1,46 +1,46 @@ -namespace Server.Items -{ - [Flippable(0x13ec, 0x13ed)] - public class RingmailChest : BaseArmor - { - [Constructible] - public RingmailChest() : base(0x13EC) => Weight = 15.0; - - public RingmailChest(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 1; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 40; - public override int InitMaxHits => 50; - - public override int AosStrReq => 40; - public override int OldStrReq => 20; - - public override int OldDexBonus => -2; - - public override int ArmorBase => 22; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Ringmail; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 15.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x13ec, 0x13ed)] + public class RingmailChest : BaseArmor + { + [Constructible] + public RingmailChest() : base(0x13EC) => Weight = 15.0; + + public RingmailChest(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 1; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 40; + public override int InitMaxHits => 50; + + public override int AosStrReq => 40; + public override int OldStrReq => 20; + + public override int OldDexBonus => -2; + + public override int ArmorBase => 22; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Ringmail; + + 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 (Weight == 1.0) + Weight = 15.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Ring/RingmailGloves.cs b/Projects/UOContent/Items/Armor/Ring/RingmailGloves.cs index a690d88db..6cab3074a 100644 --- a/Projects/UOContent/Items/Armor/Ring/RingmailGloves.cs +++ b/Projects/UOContent/Items/Armor/Ring/RingmailGloves.cs @@ -1,46 +1,46 @@ -namespace Server.Items -{ - [Flippable(0x13eb, 0x13f2)] - public class RingmailGloves : BaseArmor - { - [Constructible] - public RingmailGloves() : base(0x13EB) => Weight = 2.0; - - public RingmailGloves(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 1; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 40; - public override int InitMaxHits => 50; - - public override int AosStrReq => 40; - public override int OldStrReq => 20; - - public override int OldDexBonus => -1; - - public override int ArmorBase => 22; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Ringmail; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 2.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x13eb, 0x13f2)] + public class RingmailGloves : BaseArmor + { + [Constructible] + public RingmailGloves() : base(0x13EB) => Weight = 2.0; + + public RingmailGloves(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 1; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 40; + public override int InitMaxHits => 50; + + public override int AosStrReq => 40; + public override int OldStrReq => 20; + + public override int OldDexBonus => -1; + + public override int ArmorBase => 22; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Ringmail; + + 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 (Weight == 1.0) + Weight = 2.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Ring/RingmailLegs.cs b/Projects/UOContent/Items/Armor/Ring/RingmailLegs.cs index e912b714e..aa30dbd4b 100644 --- a/Projects/UOContent/Items/Armor/Ring/RingmailLegs.cs +++ b/Projects/UOContent/Items/Armor/Ring/RingmailLegs.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - [Flippable(0x13f0, 0x13f1)] - public class RingmailLegs : BaseArmor - { - [Constructible] - public RingmailLegs() : base(0x13F0) => Weight = 15.0; - - public RingmailLegs(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 1; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 40; - public override int InitMaxHits => 50; - - public override int AosStrReq => 40; - public override int OldStrReq => 20; - - public override int OldDexBonus => -1; - - public override int ArmorBase => 22; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Ringmail; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x13f0, 0x13f1)] + public class RingmailLegs : BaseArmor + { + [Constructible] + public RingmailLegs() : base(0x13F0) => Weight = 15.0; + + public RingmailLegs(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 1; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 40; + public override int InitMaxHits => 50; + + public override int AosStrReq => 40; + public override int OldStrReq => 20; + + public override int OldDexBonus => -1; + + public override int ArmorBase => 22; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Ringmail; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Studded/FemaleStuddedChest.cs b/Projects/UOContent/Items/Armor/Studded/FemaleStuddedChest.cs index 1e43ab9cd..b28a2c370 100644 --- a/Projects/UOContent/Items/Armor/Studded/FemaleStuddedChest.cs +++ b/Projects/UOContent/Items/Armor/Studded/FemaleStuddedChest.cs @@ -1,49 +1,49 @@ -namespace Server.Items -{ - [Flippable(0x1c02, 0x1c03)] - public class FemaleStuddedChest : BaseArmor - { - [Constructible] - public FemaleStuddedChest() : base(0x1C02) => Weight = 6.0; - - public FemaleStuddedChest(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 35; - public override int InitMaxHits => 45; - - public override int AosStrReq => 35; - public override int OldStrReq => 35; - - public override int ArmorBase => 16; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; - - public override bool AllowMaleWearer => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 6.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1c02, 0x1c03)] + public class FemaleStuddedChest : BaseArmor + { + [Constructible] + public FemaleStuddedChest() : base(0x1C02) => Weight = 6.0; + + public FemaleStuddedChest(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 35; + public override int InitMaxHits => 45; + + public override int AosStrReq => 35; + public override int OldStrReq => 35; + + public override int ArmorBase => 16; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; + + public override bool AllowMaleWearer => false; + + 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 (Weight == 1.0) + Weight = 6.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Studded/HideChest.cs b/Projects/UOContent/Items/Armor/Studded/HideChest.cs index 6d64fab37..5a1b0ca24 100644 --- a/Projects/UOContent/Items/Armor/Studded/HideChest.cs +++ b/Projects/UOContent/Items/Armor/Studded/HideChest.cs @@ -1,48 +1,48 @@ -namespace Server.Items -{ - [Flippable(0x2B74, 0x316B)] - public class HideChest : BaseArmor - { - [Constructible] - public HideChest() : base(0x2B74) => Weight = 6.0; - - public HideChest(Serial serial) : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 4; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 35; - public override int InitMaxHits => 45; - - public override int AosStrReq => 25; - public override int OldStrReq => 25; - - public override int ArmorBase => 15; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2B74, 0x316B)] + public class HideChest : BaseArmor + { + [Constructible] + public HideChest() : base(0x2B74) => Weight = 6.0; + + public HideChest(Serial serial) : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 4; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 35; + public override int InitMaxHits => 45; + + public override int AosStrReq => 25; + public override int OldStrReq => 25; + + public override int ArmorBase => 15; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Studded/HideFemaleChest.cs b/Projects/UOContent/Items/Armor/Studded/HideFemaleChest.cs index 60804fc87..921ab37bd 100644 --- a/Projects/UOContent/Items/Armor/Studded/HideFemaleChest.cs +++ b/Projects/UOContent/Items/Armor/Studded/HideFemaleChest.cs @@ -1,50 +1,50 @@ -namespace Server.Items -{ - [Flippable(0x2B79, 0x3170)] - public class HideFemaleChest : BaseArmor - { - [Constructible] - public HideFemaleChest() : base(0x2B79) => Weight = 6.0; - - public HideFemaleChest(Serial serial) : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 4; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 35; - public override int InitMaxHits => 45; - - public override int AosStrReq => 35; - public override int OldStrReq => 35; - - public override int ArmorBase => 15; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; - - public override bool AllowMaleWearer => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2B79, 0x3170)] + public class HideFemaleChest : BaseArmor + { + [Constructible] + public HideFemaleChest() : base(0x2B79) => Weight = 6.0; + + public HideFemaleChest(Serial serial) : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 4; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 35; + public override int InitMaxHits => 45; + + public override int AosStrReq => 35; + public override int OldStrReq => 35; + + public override int ArmorBase => 15; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; + + public override bool AllowMaleWearer => false; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Studded/HideGloves.cs b/Projects/UOContent/Items/Armor/Studded/HideGloves.cs index fa6ed5e82..b5e75569d 100644 --- a/Projects/UOContent/Items/Armor/Studded/HideGloves.cs +++ b/Projects/UOContent/Items/Armor/Studded/HideGloves.cs @@ -1,48 +1,48 @@ -namespace Server.Items -{ - [Flippable(0x2B75, 0x316C)] - public class HideGloves : BaseArmor - { - [Constructible] - public HideGloves() : base(0x2B75) => Weight = 2.0; - - public HideGloves(Serial serial) : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 4; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 35; - public override int InitMaxHits => 45; - - public override int AosStrReq => 15; - public override int OldStrReq => 15; - - public override int ArmorBase => 15; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2B75, 0x316C)] + public class HideGloves : BaseArmor + { + [Constructible] + public HideGloves() : base(0x2B75) => Weight = 2.0; + + public HideGloves(Serial serial) : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 4; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 35; + public override int InitMaxHits => 45; + + public override int AosStrReq => 15; + public override int OldStrReq => 15; + + public override int ArmorBase => 15; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Studded/HideGorget.cs b/Projects/UOContent/Items/Armor/Studded/HideGorget.cs index 9d12a01a5..3b192547d 100644 --- a/Projects/UOContent/Items/Armor/Studded/HideGorget.cs +++ b/Projects/UOContent/Items/Armor/Studded/HideGorget.cs @@ -1,49 +1,49 @@ -namespace Server.Items -{ - [Flippable(0x2B76, 0x316D)] - public class HideGorget : BaseArmor - { - [Constructible] - public HideGorget() : base(0x2B76) => Weight = 3.0; - - public HideGorget(Serial serial) : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 4; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 35; - public override int InitMaxHits => 45; - - public override int AosStrReq => 15; - public override int OldStrReq => 15; - - public override int ArmorBase => 15; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 2.0) - Weight = 1.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2B76, 0x316D)] + public class HideGorget : BaseArmor + { + [Constructible] + public HideGorget() : base(0x2B76) => Weight = 3.0; + + public HideGorget(Serial serial) : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 4; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 35; + public override int InitMaxHits => 45; + + public override int AosStrReq => 15; + public override int OldStrReq => 15; + + public override int ArmorBase => 15; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; + + 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 (Weight == 2.0) + Weight = 1.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Studded/HidePants.cs b/Projects/UOContent/Items/Armor/Studded/HidePants.cs index 3c0bd44b7..814cdb6cd 100644 --- a/Projects/UOContent/Items/Armor/Studded/HidePants.cs +++ b/Projects/UOContent/Items/Armor/Studded/HidePants.cs @@ -1,48 +1,48 @@ -namespace Server.Items -{ - [Flippable(0x2B78, 0x316F)] - public class HidePants : BaseArmor - { - [Constructible] - public HidePants() : base(0x2B78) => Weight = 5.0; - - public HidePants(Serial serial) : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 4; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 35; - public override int InitMaxHits => 45; - - public override int AosStrReq => 25; - public override int OldStrReq => 25; - - public override int ArmorBase => 15; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2B78, 0x316F)] + public class HidePants : BaseArmor + { + [Constructible] + public HidePants() : base(0x2B78) => Weight = 5.0; + + public HidePants(Serial serial) : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 4; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 35; + public override int InitMaxHits => 45; + + public override int AosStrReq => 25; + public override int OldStrReq => 25; + + public override int ArmorBase => 15; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Studded/HidePauldrons.cs b/Projects/UOContent/Items/Armor/Studded/HidePauldrons.cs index d29084562..5b02e8a84 100644 --- a/Projects/UOContent/Items/Armor/Studded/HidePauldrons.cs +++ b/Projects/UOContent/Items/Armor/Studded/HidePauldrons.cs @@ -1,48 +1,48 @@ -namespace Server.Items -{ - [Flippable(0x2B77, 0x316E)] - public class HidePauldrons : BaseArmor - { - [Constructible] - public HidePauldrons() : base(0x2B77) => Weight = 4.0; - - public HidePauldrons(Serial serial) : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 4; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 2; - - public override int InitMinHits => 35; - public override int InitMaxHits => 45; - - public override int AosStrReq => 20; - public override int OldStrReq => 20; - - public override int ArmorBase => 15; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x2B77, 0x316E)] + public class HidePauldrons : BaseArmor + { + [Constructible] + public HidePauldrons() : base(0x2B77) => Weight = 4.0; + + public HidePauldrons(Serial serial) : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 4; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 2; + + public override int InitMinHits => 35; + public override int InitMaxHits => 45; + + public override int AosStrReq => 20; + public override int OldStrReq => 20; + + public override int ArmorBase => 15; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Studded/StuddedArms.cs b/Projects/UOContent/Items/Armor/Studded/StuddedArms.cs index 64e17fce6..712ebb779 100644 --- a/Projects/UOContent/Items/Armor/Studded/StuddedArms.cs +++ b/Projects/UOContent/Items/Armor/Studded/StuddedArms.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - [Flippable(0x13dc, 0x13d4)] - public class StuddedArms : BaseArmor - { - [Constructible] - public StuddedArms() : base(0x13DC) => Weight = 4.0; - - public StuddedArms(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 35; - public override int InitMaxHits => 45; - - public override int AosStrReq => 25; - public override int OldStrReq => 25; - - public override int ArmorBase => 16; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 4.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x13dc, 0x13d4)] + public class StuddedArms : BaseArmor + { + [Constructible] + public StuddedArms() : base(0x13DC) => Weight = 4.0; + + public StuddedArms(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 35; + public override int InitMaxHits => 45; + + public override int AosStrReq => 25; + public override int OldStrReq => 25; + + public override int ArmorBase => 16; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; + + 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 (Weight == 1.0) + Weight = 4.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Studded/StuddedBustierArms.cs b/Projects/UOContent/Items/Armor/Studded/StuddedBustierArms.cs index 06216e67f..0315eca90 100644 --- a/Projects/UOContent/Items/Armor/Studded/StuddedBustierArms.cs +++ b/Projects/UOContent/Items/Armor/Studded/StuddedBustierArms.cs @@ -1,46 +1,46 @@ -namespace Server.Items -{ - [Flippable(0x1c0c, 0x1c0d)] - public class StuddedBustierArms : BaseArmor - { - [Constructible] - public StuddedBustierArms() : base(0x1C0C) => Weight = 1.0; - - public StuddedBustierArms(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 35; - public override int InitMaxHits => 45; - - public override int AosStrReq => 35; - public override int OldStrReq => 35; - - public override int ArmorBase => 16; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; - - public override bool AllowMaleWearer => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1c0c, 0x1c0d)] + public class StuddedBustierArms : BaseArmor + { + [Constructible] + public StuddedBustierArms() : base(0x1C0C) => Weight = 1.0; + + public StuddedBustierArms(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 35; + public override int InitMaxHits => 45; + + public override int AosStrReq => 35; + public override int OldStrReq => 35; + + public override int ArmorBase => 16; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; + + public override bool AllowMaleWearer => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Studded/StuddedChest.cs b/Projects/UOContent/Items/Armor/Studded/StuddedChest.cs index c03e14b12..2fae92e92 100644 --- a/Projects/UOContent/Items/Armor/Studded/StuddedChest.cs +++ b/Projects/UOContent/Items/Armor/Studded/StuddedChest.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - [Flippable(0x13db, 0x13e2)] - public class StuddedChest : BaseArmor - { - [Constructible] - public StuddedChest() : base(0x13DB) => Weight = 8.0; - - public StuddedChest(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 35; - public override int InitMaxHits => 45; - - public override int AosStrReq => 35; - public override int OldStrReq => 35; - - public override int ArmorBase => 16; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 8.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x13db, 0x13e2)] + public class StuddedChest : BaseArmor + { + [Constructible] + public StuddedChest() : base(0x13DB) => Weight = 8.0; + + public StuddedChest(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 35; + public override int InitMaxHits => 45; + + public override int AosStrReq => 35; + public override int OldStrReq => 35; + + public override int ArmorBase => 16; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; + + 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 (Weight == 1.0) + Weight = 8.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Studded/StuddedDo.cs b/Projects/UOContent/Items/Armor/Studded/StuddedDo.cs index a7174d176..7ea80dee7 100644 --- a/Projects/UOContent/Items/Armor/Studded/StuddedDo.cs +++ b/Projects/UOContent/Items/Armor/Studded/StuddedDo.cs @@ -1,41 +1,41 @@ -namespace Server.Items -{ - public class StuddedDo : BaseArmor - { - [Constructible] - public StuddedDo() : base(0x27C7) => Weight = 8.0; - - public StuddedDo(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 40; - public override int InitMaxHits => 50; - - public override int AosStrReq => 55; - public override int OldStrReq => 55; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class StuddedDo : BaseArmor + { + [Constructible] + public StuddedDo() : base(0x27C7) => Weight = 8.0; + + public StuddedDo(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 40; + public override int InitMaxHits => 50; + + public override int AosStrReq => 55; + public override int OldStrReq => 55; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Studded/StuddedGloves.cs b/Projects/UOContent/Items/Armor/Studded/StuddedGloves.cs index bfe7655e7..f0e014222 100644 --- a/Projects/UOContent/Items/Armor/Studded/StuddedGloves.cs +++ b/Projects/UOContent/Items/Armor/Studded/StuddedGloves.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - [Flippable(0x13d5, 0x13dd)] - public class StuddedGloves : BaseArmor - { - [Constructible] - public StuddedGloves() : base(0x13D5) => Weight = 1.0; - - public StuddedGloves(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 35; - public override int InitMaxHits => 45; - - public override int AosStrReq => 25; - public override int OldStrReq => 25; - - public override int ArmorBase => 16; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 2.0) - Weight = 1.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x13d5, 0x13dd)] + public class StuddedGloves : BaseArmor + { + [Constructible] + public StuddedGloves() : base(0x13D5) => Weight = 1.0; + + public StuddedGloves(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 35; + public override int InitMaxHits => 45; + + public override int AosStrReq => 25; + public override int OldStrReq => 25; + + public override int ArmorBase => 16; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; + + 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 (Weight == 2.0) + Weight = 1.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Studded/StuddedGorget.cs b/Projects/UOContent/Items/Armor/Studded/StuddedGorget.cs index cc4aaec2a..6579d6317 100644 --- a/Projects/UOContent/Items/Armor/Studded/StuddedGorget.cs +++ b/Projects/UOContent/Items/Armor/Studded/StuddedGorget.cs @@ -1,46 +1,46 @@ -namespace Server.Items -{ - public class StuddedGorget : BaseArmor - { - [Constructible] - public StuddedGorget() : base(0x13D6) => Weight = 1.0; - - public StuddedGorget(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 35; - public override int InitMaxHits => 45; - - public override int AosStrReq => 25; - public override int OldStrReq => 25; - - public override int ArmorBase => 16; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 2.0) - Weight = 1.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class StuddedGorget : BaseArmor + { + [Constructible] + public StuddedGorget() : base(0x13D6) => Weight = 1.0; + + public StuddedGorget(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 35; + public override int InitMaxHits => 45; + + public override int AosStrReq => 25; + public override int OldStrReq => 25; + + public override int ArmorBase => 16; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; + + 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 (Weight == 2.0) + Weight = 1.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Studded/StuddedHaidate.cs b/Projects/UOContent/Items/Armor/Studded/StuddedHaidate.cs index a44a75c9e..b47742197 100644 --- a/Projects/UOContent/Items/Armor/Studded/StuddedHaidate.cs +++ b/Projects/UOContent/Items/Armor/Studded/StuddedHaidate.cs @@ -1,41 +1,41 @@ -namespace Server.Items -{ - public class StuddedHaidate : BaseArmor - { - [Constructible] - public StuddedHaidate() : base(0x278B) => Weight = 5.0; - - public StuddedHaidate(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 35; - public override int InitMaxHits => 45; - - public override int AosStrReq => 30; - public override int OldStrReq => 30; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class StuddedHaidate : BaseArmor + { + [Constructible] + public StuddedHaidate() : base(0x278B) => Weight = 5.0; + + public StuddedHaidate(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 35; + public override int InitMaxHits => 45; + + public override int AosStrReq => 30; + public override int OldStrReq => 30; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Studded/StuddedHiroSode.cs b/Projects/UOContent/Items/Armor/Studded/StuddedHiroSode.cs index 318ff12d9..981012223 100644 --- a/Projects/UOContent/Items/Armor/Studded/StuddedHiroSode.cs +++ b/Projects/UOContent/Items/Armor/Studded/StuddedHiroSode.cs @@ -1,41 +1,41 @@ -namespace Server.Items -{ - public class StuddedHiroSode : BaseArmor - { - [Constructible] - public StuddedHiroSode() : base(0x277F) => Weight = 1.0; - - public StuddedHiroSode(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 45; - public override int InitMaxHits => 55; - - public override int AosStrReq => 30; - public override int OldStrReq => 30; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class StuddedHiroSode : BaseArmor + { + [Constructible] + public StuddedHiroSode() : base(0x277F) => Weight = 1.0; + + public StuddedHiroSode(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 45; + public override int InitMaxHits => 55; + + public override int AosStrReq => 30; + public override int OldStrReq => 30; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Studded/StuddedLegs.cs b/Projects/UOContent/Items/Armor/Studded/StuddedLegs.cs index 2ffda14ad..031835191 100644 --- a/Projects/UOContent/Items/Armor/Studded/StuddedLegs.cs +++ b/Projects/UOContent/Items/Armor/Studded/StuddedLegs.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - [Flippable(0x13da, 0x13e1)] - public class StuddedLegs : BaseArmor - { - [Constructible] - public StuddedLegs() : base(0x13DA) => Weight = 5.0; - - public StuddedLegs(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 35; - public override int InitMaxHits => 45; - - public override int AosStrReq => 30; - public override int OldStrReq => 35; - - public override int ArmorBase => 16; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 3.0) - Weight = 5.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x13da, 0x13e1)] + public class StuddedLegs : BaseArmor + { + [Constructible] + public StuddedLegs() : base(0x13DA) => Weight = 5.0; + + public StuddedLegs(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 35; + public override int InitMaxHits => 45; + + public override int AosStrReq => 30; + public override int OldStrReq => 35; + + public override int ArmorBase => 16; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.Half; + + 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 (Weight == 3.0) + Weight = 5.0; + } + } +} diff --git a/Projects/UOContent/Items/Armor/Studded/StuddedMempo.cs b/Projects/UOContent/Items/Armor/Studded/StuddedMempo.cs index 3521ff8ef..2c0a76e5e 100644 --- a/Projects/UOContent/Items/Armor/Studded/StuddedMempo.cs +++ b/Projects/UOContent/Items/Armor/Studded/StuddedMempo.cs @@ -1,41 +1,41 @@ -namespace Server.Items -{ - public class StuddedMempo : BaseArmor - { - [Constructible] - public StuddedMempo() : base(0x279D) => Weight = 2.0; - - public StuddedMempo(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 30; - public override int InitMaxHits => 40; - - public override int AosStrReq => 30; - public override int OldStrReq => 30; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class StuddedMempo : BaseArmor + { + [Constructible] + public StuddedMempo() : base(0x279D) => Weight = 2.0; + + public StuddedMempo(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 30; + public override int InitMaxHits => 40; + + public override int AosStrReq => 30; + public override int OldStrReq => 30; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Armor/Studded/StuddedSuneate.cs b/Projects/UOContent/Items/Armor/Studded/StuddedSuneate.cs index 12858102f..bd0e0a77f 100644 --- a/Projects/UOContent/Items/Armor/Studded/StuddedSuneate.cs +++ b/Projects/UOContent/Items/Armor/Studded/StuddedSuneate.cs @@ -1,41 +1,41 @@ -namespace Server.Items -{ - public class StuddedSuneate : BaseArmor - { - [Constructible] - public StuddedSuneate() : base(0x27D2) => Weight = 5.0; - - public StuddedSuneate(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 35; - public override int InitMaxHits => 50; - - public override int AosStrReq => 30; - public override int OldStrReq => 30; - - public override int ArmorBase => 3; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class StuddedSuneate : BaseArmor + { + [Constructible] + public StuddedSuneate() : base(0x27D2) => Weight = 5.0; + + public StuddedSuneate(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 35; + public override int InitMaxHits => 50; + + public override int AosStrReq => 30; + public override int OldStrReq => 30; + + public override int ArmorBase => 3; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Body Parts/BonePile.cs b/Projects/UOContent/Items/Body Parts/BonePile.cs index 5cce8e911..72bedc69d 100644 --- a/Projects/UOContent/Items/Body Parts/BonePile.cs +++ b/Projects/UOContent/Items/Body Parts/BonePile.cs @@ -1,41 +1,41 @@ -namespace Server.Items -{ - [Flippable(0x1B09, 0x1B10)] - public class BonePile : Item, IScissorable - { - [Constructible] - public BonePile() : base(0x1B09 + Utility.Random(8)) - { - Stackable = false; - Weight = 10.0; - } - - public BonePile(Serial serial) : base(serial) - { - } - - public bool Scissor(Mobile from, Scissors scissors) - { - if (Deleted || !from.CanSee(this)) - return false; - - ScissorHelper(from, new Bone(), Utility.RandomMinMax(10, 15)); - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1B09, 0x1B10)] + public class BonePile : Item, IScissorable + { + [Constructible] + public BonePile() : base(0x1B09 + Utility.Random(8)) + { + Stackable = false; + Weight = 10.0; + } + + public BonePile(Serial serial) : base(serial) + { + } + + public bool Scissor(Mobile from, Scissors scissors) + { + if (Deleted || !from.CanSee(this)) + return false; + + ScissorHelper(from, new Bone(), Utility.RandomMinMax(10, 15)); + + return true; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Body Parts/Head.cs b/Projects/UOContent/Items/Body Parts/Head.cs index 71c9f96a8..59522d0db 100644 --- a/Projects/UOContent/Items/Body Parts/Head.cs +++ b/Projects/UOContent/Items/Body Parts/Head.cs @@ -1,102 +1,102 @@ -namespace Server.Items -{ - public enum HeadType - { - Regular, - Duel, - Tournament - } - - public class Head : Item - { - [Constructible] - public Head(string playerName) : this(HeadType.Regular, playerName) - { - } - - [Constructible] - public Head(HeadType headType = HeadType.Regular, string playerName = null) - : base(0x1DA0) - { - HeadType = headType; - PlayerName = playerName; - } - - public Head(Serial serial) - : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public string PlayerName { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public HeadType HeadType { get; set; } - - public override string DefaultName - { - get - { - if (PlayerName == null) - return base.DefaultName; - - return HeadType switch - { - HeadType.Duel => $"the head of {PlayerName}, taken in a duel", - HeadType.Tournament => $"the head of {PlayerName}, taken in a tournament", - _ => $"the head of {PlayerName}" - }; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(PlayerName); - writer.WriteEncodedInt((int)HeadType); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - PlayerName = reader.ReadString(); - HeadType = (HeadType)reader.ReadEncodedInt(); - break; - - case 0: - string format = Name; - - if (format != null) - { - if (format.StartsWith("the head of ")) - format = format.Substring("the head of ".Length); - - if (format.EndsWith(", taken in a duel")) - { - format = format.Substring(0, format.Length - ", taken in a duel".Length); - HeadType = HeadType.Duel; - } - else if (format.EndsWith(", taken in a tournament")) - { - format = format.Substring(0, format.Length - ", taken in a tournament".Length); - HeadType = HeadType.Tournament; - } - } - - PlayerName = format; - Name = null; - - break; - } - } - } -} +namespace Server.Items +{ + public enum HeadType + { + Regular, + Duel, + Tournament + } + + public class Head : Item + { + [Constructible] + public Head(string playerName) : this(HeadType.Regular, playerName) + { + } + + [Constructible] + public Head(HeadType headType = HeadType.Regular, string playerName = null) + : base(0x1DA0) + { + HeadType = headType; + PlayerName = playerName; + } + + public Head(Serial serial) + : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public string PlayerName { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public HeadType HeadType { get; set; } + + public override string DefaultName + { + get + { + if (PlayerName == null) + return base.DefaultName; + + return HeadType switch + { + HeadType.Duel => $"the head of {PlayerName}, taken in a duel", + HeadType.Tournament => $"the head of {PlayerName}, taken in a tournament", + _ => $"the head of {PlayerName}" + }; + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(PlayerName); + writer.WriteEncodedInt((int)HeadType); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + PlayerName = reader.ReadString(); + HeadType = (HeadType)reader.ReadEncodedInt(); + break; + + case 0: + var format = Name; + + if (format != null) + { + if (format.StartsWith("the head of ")) + format = format.Substring("the head of ".Length); + + if (format.EndsWith(", taken in a duel")) + { + format = format.Substring(0, format.Length - ", taken in a duel".Length); + HeadType = HeadType.Duel; + } + else if (format.EndsWith(", taken in a tournament")) + { + format = format.Substring(0, format.Length - ", taken in a tournament".Length); + HeadType = HeadType.Tournament; + } + } + + PlayerName = format; + Name = null; + + break; + } + } + } +} diff --git a/Projects/UOContent/Items/Body Parts/LeftArm.cs b/Projects/UOContent/Items/Body Parts/LeftArm.cs index e60fd1907..7b9472ba2 100644 --- a/Projects/UOContent/Items/Body Parts/LeftArm.cs +++ b/Projects/UOContent/Items/Body Parts/LeftArm.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class LeftArm : Item - { - [Constructible] - public LeftArm() : base(0x1DA1) - { - } - - public LeftArm(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LeftArm : Item + { + [Constructible] + public LeftArm() : base(0x1DA1) + { + } + + public LeftArm(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Body Parts/LeftLeg.cs b/Projects/UOContent/Items/Body Parts/LeftLeg.cs index cc5aa6ebb..e3b600c24 100644 --- a/Projects/UOContent/Items/Body Parts/LeftLeg.cs +++ b/Projects/UOContent/Items/Body Parts/LeftLeg.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class LeftLeg : Item - { - [Constructible] - public LeftLeg() : base(0x1DA3) - { - } - - public LeftLeg(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LeftLeg : Item + { + [Constructible] + public LeftLeg() : base(0x1DA3) + { + } + + public LeftLeg(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Body Parts/RibCage.cs b/Projects/UOContent/Items/Body Parts/RibCage.cs index 25be14e48..bee865e3f 100644 --- a/Projects/UOContent/Items/Body Parts/RibCage.cs +++ b/Projects/UOContent/Items/Body Parts/RibCage.cs @@ -1,41 +1,41 @@ -namespace Server.Items -{ - [Flippable(0x1B17, 0x1B18)] - public class RibCage : Item, IScissorable - { - [Constructible] - public RibCage() : base(0x1B17 + Utility.Random(2)) - { - Stackable = false; - Weight = 5.0; - } - - public RibCage(Serial serial) : base(serial) - { - } - - public bool Scissor(Mobile from, Scissors scissors) - { - if (Deleted || !from.CanSee(this)) - return false; - - ScissorHelper(from, new Bone(), Utility.RandomMinMax(3, 5)); - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1B17, 0x1B18)] + public class RibCage : Item, IScissorable + { + [Constructible] + public RibCage() : base(0x1B17 + Utility.Random(2)) + { + Stackable = false; + Weight = 5.0; + } + + public RibCage(Serial serial) : base(serial) + { + } + + public bool Scissor(Mobile from, Scissors scissors) + { + if (Deleted || !from.CanSee(this)) + return false; + + ScissorHelper(from, new Bone(), Utility.RandomMinMax(3, 5)); + + return true; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Body Parts/RightArm.cs b/Projects/UOContent/Items/Body Parts/RightArm.cs index 09af98478..c7713e797 100644 --- a/Projects/UOContent/Items/Body Parts/RightArm.cs +++ b/Projects/UOContent/Items/Body Parts/RightArm.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class RightArm : Item - { - [Constructible] - public RightArm() : base(0x1DA2) - { - } - - public RightArm(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class RightArm : Item + { + [Constructible] + public RightArm() : base(0x1DA2) + { + } + + public RightArm(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Body Parts/RightLeg.cs b/Projects/UOContent/Items/Body Parts/RightLeg.cs index 49196d325..b16178948 100644 --- a/Projects/UOContent/Items/Body Parts/RightLeg.cs +++ b/Projects/UOContent/Items/Body Parts/RightLeg.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class RightLeg : Item - { - [Constructible] - public RightLeg() : base(0x1DA4) - { - } - - public RightLeg(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class RightLeg : Item + { + [Constructible] + public RightLeg() : base(0x1DA4) + { + } + + public RightLeg(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Body Parts/Torso.cs b/Projects/UOContent/Items/Body Parts/Torso.cs index c77d5fd7f..b1250f135 100644 --- a/Projects/UOContent/Items/Body Parts/Torso.cs +++ b/Projects/UOContent/Items/Body Parts/Torso.cs @@ -1,26 +1,26 @@ -namespace Server.Items -{ - public class Torso : Item - { - [Constructible] - public Torso() : base(0x1D9F) => Weight = 2.0; - - public Torso(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Torso : Item + { + [Constructible] + public Torso() : base(0x1D9F) => Weight = 2.0; + + public Torso(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Books/BaseBook.cs b/Projects/UOContent/Items/Books/BaseBook.cs index aca3da2a0..f1165cb0b 100644 --- a/Projects/UOContent/Items/Books/BaseBook.cs +++ b/Projects/UOContent/Items/Books/BaseBook.cs @@ -1,470 +1,470 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using Server.ContextMenus; -using Server.Gumps; -using Server.Multis; -using Server.Network; - -namespace Server.Items -{ - public class BookPageInfo - { - public BookPageInfo() => Lines = Array.Empty(); - - public BookPageInfo(params string[] lines) => Lines = lines; - - public BookPageInfo(IGenericReader reader) - { - int length = reader.ReadInt(); - - Lines = new string[length]; - - for (int i = 0; i < Lines.Length; ++i) - Lines[i] = Utility.Intern(reader.ReadString()); - } - - public string[] Lines { get; set; } - - public void Serialize(IGenericWriter writer) - { - writer.Write(Lines.Length); - - for (int i = 0; i < Lines.Length; ++i) - writer.Write(Lines[i]); - } - } - - public class BaseBook : Item, ISecurable - { - private string m_Author; - private string m_Title; - - [Constructible] - public BaseBook(int itemID, int pageCount = 20, bool writable = true) : this(itemID, null, null, pageCount, writable) - { - } - - [Constructible] - public BaseBook(int itemID, string title, string author, int pageCount, bool writable) : base(itemID) - { - BookContent content = DefaultContent; - - m_Title = title ?? content?.Title; - m_Author = author ?? content?.Author; - Writable = writable; - - if (content == null) - { - Pages = new BookPageInfo[pageCount]; - - for (int i = 0; i < Pages.Length; ++i) - Pages[i] = new BookPageInfo(); - } - else - { - Pages = content.Copy(); - } - } - - // Intended for defined books only - public BaseBook(int itemID, bool writable) : this(itemID, 0, writable) - { - } - - public BaseBook(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public string Title - { - get => m_Title; - set - { - m_Title = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public string Author - { - get => m_Author; - set - { - m_Author = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Writable { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int PagesCount => Pages.Length; - - public BookPageInfo[] Pages { get; private set; } - - public virtual BookContent DefaultContent => null; - - public string ContentAsString - { - get - { - StringBuilder sb = new StringBuilder(); - - foreach (BookPageInfo bpi in Pages) - foreach (string line in bpi.Lines) - sb.AppendLine(line); - - return sb.ToString(); - } - } - - public string[] ContentAsStringArray - { - get - { - List lines = new List(); - - foreach (BookPageInfo bpi in Pages) lines.AddRange(bpi.Lines); - - return lines.ToArray(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public SecureLevel Level { get; set; } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - SetSecureLevelEntry.AddTo(from, this, list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - BookContent content = DefaultContent; - - SaveFlags flags = SaveFlags.None; - - if (m_Title != content?.Title) - flags |= SaveFlags.Title; - - if (m_Author != content?.Author) - flags |= SaveFlags.Author; - - if (Writable) - flags |= SaveFlags.Writable; - - if (content?.IsMatch(Pages) != true) - flags |= SaveFlags.Content; - - writer.Write(4); // version - - writer.Write((int)Level); - - writer.Write((byte)flags); - - if ((flags & SaveFlags.Title) != 0) - writer.Write(m_Title); - - if ((flags & SaveFlags.Author) != 0) - writer.Write(m_Author); - - if ((flags & SaveFlags.Content) != 0) - { - writer.WriteEncodedInt(Pages.Length); - - for (int i = 0; i < Pages.Length; ++i) - Pages[i].Serialize(writer); - } - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 4: - { - Level = (SecureLevel)reader.ReadInt(); - goto case 3; - } - case 3: - case 2: - { - BookContent content = DefaultContent; - - SaveFlags flags = (SaveFlags)reader.ReadByte(); - - if ((flags & SaveFlags.Title) != 0) - m_Title = Utility.Intern(reader.ReadString()); - else if (content != null) - m_Title = content.Title; - - if ((flags & SaveFlags.Author) != 0) - m_Author = reader.ReadString(); - else if (content != null) - m_Author = content.Author; - - Writable = (flags & SaveFlags.Writable) != 0; - - if ((flags & SaveFlags.Content) != 0) - { - Pages = new BookPageInfo[reader.ReadEncodedInt()]; - - for (int i = 0; i < Pages.Length; ++i) - Pages[i] = new BookPageInfo(reader); - } - else - { - if (content != null) - Pages = content.Copy(); - else - Pages = Array.Empty(); - } - - break; - } - case 1: - case 0: - { - m_Title = reader.ReadString(); - m_Author = reader.ReadString(); - Writable = reader.ReadBool(); - - if (version == 0 || reader.ReadBool()) - { - Pages = new BookPageInfo[reader.ReadInt()]; - - for (int i = 0; i < Pages.Length; ++i) - Pages[i] = new BookPageInfo(reader); - } - else - { - BookContent content = DefaultContent; - - if (content != null) - Pages = content.Copy(); - else - Pages = Array.Empty(); - } - - break; - } - } - - if (version < 3 && (Weight == 1 || Weight == 2)) - Weight = -1; - } - - public override void AddNameProperty(ObjectPropertyList list) - { - if (!string.IsNullOrEmpty(m_Title)) - list.Add(m_Title); - else - base.AddNameProperty(list); - } - - /*public override void GetProperties( ObjectPropertyList list ) - { - base.GetProperties( list ); - - if (m_Title?.Length > 0) - list.Add( 1060658, "Title\t{0}", m_Title ); // ~1_val~: ~2_val~ - - if (m_Author?.Length > 0) - list.Add( 1060659, "Author\t{0}", m_Author ); // ~1_val~: ~2_val~ - - if (m_Pages?.Length > 0) - list.Add( 1060660, "Pages\t{0}", m_Pages.Length ); // ~1_val~: ~2_val~ - }*/ - - public override void OnSingleClick(Mobile from) - { - LabelTo(from, "{0} by {1}", m_Title, m_Author); - LabelTo(from, "[{0} pages]", Pages.Length); - } - - public override void OnDoubleClick(Mobile from) - { - if (m_Title == null && m_Author == null && Writable) - { - Title = "a book"; - Author = from.Name; - } - - from.Send(new BookHeader(from, this)); - from.Send(new BookPageDetails(this)); - } - - public static void Initialize() - { - PacketHandlers.Register(0xD4, 0, true, HeaderChange); - PacketHandlers.Register(0x66, 0, true, ContentChange); - PacketHandlers.Register(0x93, 99, true, OldHeaderChange); - } - - public static void OldHeaderChange(NetState state, PacketReader pvSrc) - { - Mobile from = state.Mobile; - - if (!(World.FindItem(pvSrc.ReadUInt32()) is BaseBook book) || !book.Writable || - !from.InRange(book.GetWorldLocation(), 1) || !book.IsAccessibleTo(from)) - return; - - pvSrc.Seek(4, SeekOrigin.Current); // Skip flags and page count - - string title = pvSrc.ReadStringSafe(60); - string author = pvSrc.ReadStringSafe(30); - - book.Title = Utility.FixHtml(title); - book.Author = Utility.FixHtml(author); - } - - public static void HeaderChange(NetState state, PacketReader pvSrc) - { - Mobile from = state.Mobile; - - if (!(World.FindItem(pvSrc.ReadUInt32()) is BaseBook book) || !book.Writable || - !from.InRange(book.GetWorldLocation(), 1) || !book.IsAccessibleTo(from)) - return; - - pvSrc.Seek(4, SeekOrigin.Current); // Skip flags and page count - - int titleLength = pvSrc.ReadUInt16(); - - if (titleLength > 60) - return; - - string title = pvSrc.ReadUTF8StringSafe(titleLength); - - int authorLength = pvSrc.ReadUInt16(); - - if (authorLength > 30) - return; - - string author = pvSrc.ReadUTF8StringSafe(authorLength); - - book.Title = Utility.FixHtml(title); - book.Author = Utility.FixHtml(author); - } - - public static void ContentChange(NetState state, PacketReader pvSrc) - { - Mobile from = state.Mobile; - - if (!(World.FindItem(pvSrc.ReadUInt32()) is BaseBook book) || !book.Writable || - !from.InRange(book.GetWorldLocation(), 1) || !book.IsAccessibleTo(from)) - return; - - int pageCount = pvSrc.ReadUInt16(); - - if (pageCount > book.PagesCount) - return; - - for (int i = 0; i < pageCount; ++i) - { - int index = pvSrc.ReadUInt16(); - - if (index >= 1 && index <= book.PagesCount) - { - --index; - - int lineCount = pvSrc.ReadUInt16(); - - if (lineCount <= 8) - { - string[] lines = new string[lineCount]; - - for (int j = 0; j < lineCount; ++j) - if ((lines[j] = pvSrc.ReadUTF8StringSafe()).Length >= 80) - return; - - book.Pages[index].Lines = lines; - } - else - { - return; - } - } - else - { - return; - } - } - } - - [Flags] - private enum SaveFlags - { - None = 0x00, - Title = 0x01, - Author = 0x02, - Writable = 0x04, - Content = 0x08 - } - } - - public sealed class BookPageDetails : Packet - { - public BookPageDetails(BaseBook book) : base(0x66) - { - EnsureCapacity(256); - - Stream.Write(book.Serial); - Stream.Write((ushort)book.PagesCount); - - for (int i = 0; i < book.PagesCount; ++i) - { - BookPageInfo page = book.Pages[i]; - - Stream.Write((ushort)(i + 1)); - Stream.Write((ushort)page.Lines.Length); - - for (int j = 0; j < page.Lines.Length; ++j) - { - byte[] buffer = Utility.UTF8.GetBytes(page.Lines[j]); - - Stream.Write(buffer, 0, buffer.Length); - Stream.Write((byte)0); - } - } - } - } - - public sealed class BookHeader : Packet - { - public BookHeader(Mobile from, BaseBook book) : base(0xD4) - { - string title = book.Title ?? ""; - string author = book.Author ?? ""; - - byte[] titleBuffer = Utility.UTF8.GetBytes(title); - byte[] authorBuffer = Utility.UTF8.GetBytes(author); - - EnsureCapacity(15 + titleBuffer.Length + authorBuffer.Length); - - Stream.Write(book.Serial); - Stream.Write(true); - Stream.Write(book.Writable && from.InRange(book.GetWorldLocation(), 1)); - Stream.Write((ushort)book.PagesCount); - - Stream.Write((ushort)(titleBuffer.Length + 1)); - Stream.Write(titleBuffer, 0, titleBuffer.Length); - Stream.Write((byte)0); // terminate - - Stream.Write((ushort)(authorBuffer.Length + 1)); - Stream.Write(authorBuffer, 0, authorBuffer.Length); - Stream.Write((byte)0); // terminate - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using Server.ContextMenus; +using Server.Gumps; +using Server.Multis; +using Server.Network; + +namespace Server.Items +{ + public class BookPageInfo + { + public BookPageInfo() => Lines = Array.Empty(); + + public BookPageInfo(params string[] lines) => Lines = lines; + + public BookPageInfo(IGenericReader reader) + { + var length = reader.ReadInt(); + + Lines = new string[length]; + + for (var i = 0; i < Lines.Length; ++i) + Lines[i] = Utility.Intern(reader.ReadString()); + } + + public string[] Lines { get; set; } + + public void Serialize(IGenericWriter writer) + { + writer.Write(Lines.Length); + + for (var i = 0; i < Lines.Length; ++i) + writer.Write(Lines[i]); + } + } + + public class BaseBook : Item, ISecurable + { + private string m_Author; + private string m_Title; + + [Constructible] + public BaseBook(int itemID, int pageCount = 20, bool writable = true) : this(itemID, null, null, pageCount, writable) + { + } + + [Constructible] + public BaseBook(int itemID, string title, string author, int pageCount, bool writable) : base(itemID) + { + var content = DefaultContent; + + m_Title = title ?? content?.Title; + m_Author = author ?? content?.Author; + Writable = writable; + + if (content == null) + { + Pages = new BookPageInfo[pageCount]; + + for (var i = 0; i < Pages.Length; ++i) + Pages[i] = new BookPageInfo(); + } + else + { + Pages = content.Copy(); + } + } + + // Intended for defined books only + public BaseBook(int itemID, bool writable) : this(itemID, 0, writable) + { + } + + public BaseBook(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public string Title + { + get => m_Title; + set + { + m_Title = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public string Author + { + get => m_Author; + set + { + m_Author = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Writable { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int PagesCount => Pages.Length; + + public BookPageInfo[] Pages { get; private set; } + + public virtual BookContent DefaultContent => null; + + public string ContentAsString + { + get + { + var sb = new StringBuilder(); + + foreach (var bpi in Pages) + foreach (var line in bpi.Lines) + sb.AppendLine(line); + + return sb.ToString(); + } + } + + public string[] ContentAsStringArray + { + get + { + var lines = new List(); + + foreach (var bpi in Pages) lines.AddRange(bpi.Lines); + + return lines.ToArray(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public SecureLevel Level { get; set; } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + SetSecureLevelEntry.AddTo(from, this, list); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + var content = DefaultContent; + + var flags = SaveFlags.None; + + if (m_Title != content?.Title) + flags |= SaveFlags.Title; + + if (m_Author != content?.Author) + flags |= SaveFlags.Author; + + if (Writable) + flags |= SaveFlags.Writable; + + if (content?.IsMatch(Pages) != true) + flags |= SaveFlags.Content; + + writer.Write(4); // version + + writer.Write((int)Level); + + writer.Write((byte)flags); + + if ((flags & SaveFlags.Title) != 0) + writer.Write(m_Title); + + if ((flags & SaveFlags.Author) != 0) + writer.Write(m_Author); + + if ((flags & SaveFlags.Content) != 0) + { + writer.WriteEncodedInt(Pages.Length); + + for (var i = 0; i < Pages.Length; ++i) + Pages[i].Serialize(writer); + } + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 4: + { + Level = (SecureLevel)reader.ReadInt(); + goto case 3; + } + case 3: + case 2: + { + var content = DefaultContent; + + var flags = (SaveFlags)reader.ReadByte(); + + if ((flags & SaveFlags.Title) != 0) + m_Title = Utility.Intern(reader.ReadString()); + else if (content != null) + m_Title = content.Title; + + if ((flags & SaveFlags.Author) != 0) + m_Author = reader.ReadString(); + else if (content != null) + m_Author = content.Author; + + Writable = (flags & SaveFlags.Writable) != 0; + + if ((flags & SaveFlags.Content) != 0) + { + Pages = new BookPageInfo[reader.ReadEncodedInt()]; + + for (var i = 0; i < Pages.Length; ++i) + Pages[i] = new BookPageInfo(reader); + } + else + { + if (content != null) + Pages = content.Copy(); + else + Pages = Array.Empty(); + } + + break; + } + case 1: + case 0: + { + m_Title = reader.ReadString(); + m_Author = reader.ReadString(); + Writable = reader.ReadBool(); + + if (version == 0 || reader.ReadBool()) + { + Pages = new BookPageInfo[reader.ReadInt()]; + + for (var i = 0; i < Pages.Length; ++i) + Pages[i] = new BookPageInfo(reader); + } + else + { + var content = DefaultContent; + + if (content != null) + Pages = content.Copy(); + else + Pages = Array.Empty(); + } + + break; + } + } + + if (version < 3 && (Weight == 1 || Weight == 2)) + Weight = -1; + } + + public override void AddNameProperty(ObjectPropertyList list) + { + if (!string.IsNullOrEmpty(m_Title)) + list.Add(m_Title); + else + base.AddNameProperty(list); + } + + /*public override void GetProperties( ObjectPropertyList list ) + { + base.GetProperties( list ); + + if (m_Title?.Length > 0) + list.Add( 1060658, "Title\t{0}", m_Title ); // ~1_val~: ~2_val~ + + if (m_Author?.Length > 0) + list.Add( 1060659, "Author\t{0}", m_Author ); // ~1_val~: ~2_val~ + + if (m_Pages?.Length > 0) + list.Add( 1060660, "Pages\t{0}", m_Pages.Length ); // ~1_val~: ~2_val~ + }*/ + + public override void OnSingleClick(Mobile from) + { + LabelTo(from, "{0} by {1}", m_Title, m_Author); + LabelTo(from, "[{0} pages]", Pages.Length); + } + + public override void OnDoubleClick(Mobile from) + { + if (m_Title == null && m_Author == null && Writable) + { + Title = "a book"; + Author = from.Name; + } + + from.Send(new BookHeader(from, this)); + from.Send(new BookPageDetails(this)); + } + + public static void Initialize() + { + PacketHandlers.Register(0xD4, 0, true, HeaderChange); + PacketHandlers.Register(0x66, 0, true, ContentChange); + PacketHandlers.Register(0x93, 99, true, OldHeaderChange); + } + + public static void OldHeaderChange(NetState state, PacketReader pvSrc) + { + var from = state.Mobile; + + if (!(World.FindItem(pvSrc.ReadUInt32()) is BaseBook book) || !book.Writable || + !from.InRange(book.GetWorldLocation(), 1) || !book.IsAccessibleTo(from)) + return; + + pvSrc.Seek(4, SeekOrigin.Current); // Skip flags and page count + + var title = pvSrc.ReadStringSafe(60); + var author = pvSrc.ReadStringSafe(30); + + book.Title = Utility.FixHtml(title); + book.Author = Utility.FixHtml(author); + } + + public static void HeaderChange(NetState state, PacketReader pvSrc) + { + var from = state.Mobile; + + if (!(World.FindItem(pvSrc.ReadUInt32()) is BaseBook book) || !book.Writable || + !from.InRange(book.GetWorldLocation(), 1) || !book.IsAccessibleTo(from)) + return; + + pvSrc.Seek(4, SeekOrigin.Current); // Skip flags and page count + + int titleLength = pvSrc.ReadUInt16(); + + if (titleLength > 60) + return; + + var title = pvSrc.ReadUTF8StringSafe(titleLength); + + int authorLength = pvSrc.ReadUInt16(); + + if (authorLength > 30) + return; + + var author = pvSrc.ReadUTF8StringSafe(authorLength); + + book.Title = Utility.FixHtml(title); + book.Author = Utility.FixHtml(author); + } + + public static void ContentChange(NetState state, PacketReader pvSrc) + { + var from = state.Mobile; + + if (!(World.FindItem(pvSrc.ReadUInt32()) is BaseBook book) || !book.Writable || + !from.InRange(book.GetWorldLocation(), 1) || !book.IsAccessibleTo(from)) + return; + + int pageCount = pvSrc.ReadUInt16(); + + if (pageCount > book.PagesCount) + return; + + for (var i = 0; i < pageCount; ++i) + { + int index = pvSrc.ReadUInt16(); + + if (index >= 1 && index <= book.PagesCount) + { + --index; + + int lineCount = pvSrc.ReadUInt16(); + + if (lineCount <= 8) + { + var lines = new string[lineCount]; + + for (var j = 0; j < lineCount; ++j) + if ((lines[j] = pvSrc.ReadUTF8StringSafe()).Length >= 80) + return; + + book.Pages[index].Lines = lines; + } + else + { + return; + } + } + else + { + return; + } + } + } + + [Flags] + private enum SaveFlags + { + None = 0x00, + Title = 0x01, + Author = 0x02, + Writable = 0x04, + Content = 0x08 + } + } + + public sealed class BookPageDetails : Packet + { + public BookPageDetails(BaseBook book) : base(0x66) + { + EnsureCapacity(256); + + Stream.Write(book.Serial); + Stream.Write((ushort)book.PagesCount); + + for (var i = 0; i < book.PagesCount; ++i) + { + var page = book.Pages[i]; + + Stream.Write((ushort)(i + 1)); + Stream.Write((ushort)page.Lines.Length); + + for (var j = 0; j < page.Lines.Length; ++j) + { + var buffer = Utility.UTF8.GetBytes(page.Lines[j]); + + Stream.Write(buffer, 0, buffer.Length); + Stream.Write((byte)0); + } + } + } + } + + public sealed class BookHeader : Packet + { + public BookHeader(Mobile from, BaseBook book) : base(0xD4) + { + var title = book.Title ?? ""; + var author = book.Author ?? ""; + + var titleBuffer = Utility.UTF8.GetBytes(title); + var authorBuffer = Utility.UTF8.GetBytes(author); + + EnsureCapacity(15 + titleBuffer.Length + authorBuffer.Length); + + Stream.Write(book.Serial); + Stream.Write(true); + Stream.Write(book.Writable && from.InRange(book.GetWorldLocation(), 1)); + Stream.Write((ushort)book.PagesCount); + + Stream.Write((ushort)(titleBuffer.Length + 1)); + Stream.Write(titleBuffer, 0, titleBuffer.Length); + Stream.Write((byte)0); // terminate + + Stream.Write((ushort)(authorBuffer.Length + 1)); + Stream.Write(authorBuffer, 0, authorBuffer.Length); + Stream.Write((byte)0); // terminate + } + } +} diff --git a/Projects/UOContent/Items/Books/BlueBook.cs b/Projects/UOContent/Items/Books/BlueBook.cs index d531604c1..f012a456b 100644 --- a/Projects/UOContent/Items/Books/BlueBook.cs +++ b/Projects/UOContent/Items/Books/BlueBook.cs @@ -1,44 +1,49 @@ -namespace Server.Items -{ - public class BlueBook : BaseBook - { - [Constructible] - public BlueBook() : base(0xFF2, 40) - { - } - - [Constructible] - public BlueBook(int pageCount, bool writable) : base(0xFF2, pageCount, writable) - { - } - - [Constructible] - public BlueBook(string title, string author, int pageCount, bool writable) : base(0xFF2, title, author, pageCount, - writable) - { - } - - // Intended for defined books only - public BlueBook(bool writable) : base(0xFF2, writable) - { - } - - public BlueBook(Serial serial) : base(serial) - { - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class BlueBook : BaseBook + { + [Constructible] + public BlueBook() : base(0xFF2, 40) + { + } + + [Constructible] + public BlueBook(int pageCount, bool writable) : base(0xFF2, pageCount, writable) + { + } + + [Constructible] + public BlueBook(string title, string author, int pageCount, bool writable) : base( + 0xFF2, + title, + author, + pageCount, + writable + ) + { + } + + // Intended for defined books only + public BlueBook(bool writable) : base(0xFF2, writable) + { + } + + public BlueBook(Serial serial) : base(serial) + { + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + } +} diff --git a/Projects/UOContent/Items/Books/BrownBook.cs b/Projects/UOContent/Items/Books/BrownBook.cs index 41cd379ff..b02b4ab04 100644 --- a/Projects/UOContent/Items/Books/BrownBook.cs +++ b/Projects/UOContent/Items/Books/BrownBook.cs @@ -1,44 +1,49 @@ -namespace Server.Items -{ - public class BrownBook : BaseBook - { - [Constructible] - public BrownBook() : base(0xFEF) - { - } - - [Constructible] - public BrownBook(int pageCount, bool writable) : base(0xFEF, pageCount, writable) - { - } - - [Constructible] - public BrownBook(string title, string author, int pageCount, bool writable) : base(0xFEF, title, author, pageCount, - writable) - { - } - - // Intended for defined books only - public BrownBook(bool writable) : base(0xFEF, writable) - { - } - - public BrownBook(Serial serial) : base(serial) - { - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class BrownBook : BaseBook + { + [Constructible] + public BrownBook() : base(0xFEF) + { + } + + [Constructible] + public BrownBook(int pageCount, bool writable) : base(0xFEF, pageCount, writable) + { + } + + [Constructible] + public BrownBook(string title, string author, int pageCount, bool writable) : base( + 0xFEF, + title, + author, + pageCount, + writable + ) + { + } + + // Intended for defined books only + public BrownBook(bool writable) : base(0xFEF, writable) + { + } + + public BrownBook(Serial serial) : base(serial) + { + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + } +} diff --git a/Projects/UOContent/Items/Books/Defined/BlackthornWelcomeBook.cs b/Projects/UOContent/Items/Books/Defined/BlackthornWelcomeBook.cs index 19726b58c..41a4592c8 100644 --- a/Projects/UOContent/Items/Books/Defined/BlackthornWelcomeBook.cs +++ b/Projects/UOContent/Items/Books/Defined/BlackthornWelcomeBook.cs @@ -1,241 +1,267 @@ -namespace Server.Items -{ - public class BlackthornWelcomeBook : RedBook - { - public static readonly BookContent Content = new BookContent( - "A Welcome", "Lord Blackthorn", - new BookPageInfo( - " Greetings to you,", - "new member of the", - "Trusted.", - " You now read these", - "words because you", - "have been deemed", - "worthy to join the", - "ranks of"), - new BookPageInfo( - "Britannia's defenders.", - "Some will call you a", - "betrayer of mankind, I", - "say they are", - "misguided. I call you", - "a defender for Sosaria", - "needs saving from", - "itself."), - new BookPageInfo( - " The forces of order", - "once ruled our world.", - "Like a great", - "darkness over our", - "lives we lived under", - "the oppressive watch", - "of a king who", - "dictated our actions"), - new BookPageInfo( - "and passed judgment", - "on our character. He", - "suppressed our way of", - "life by denying our", - "freedom and the", - "ability to determine", - "who we are and what", - "we stand for. Even"), - new BookPageInfo( - "today in the absence", - "of this man we still", - "see the symbol of his", - "tyranny, we watch his", - "personal guards patrol", - "the cities to", - "intimidate us, and we", - "feel his laws like a"), - new BookPageInfo( - "vice on our lives.", - " You are here", - "because you choose to", - "be free. Like many", - "Britannians you have", - "felt the oppression of", - "one man's ideas", - "weighing down upon"), - new BookPageInfo( - "you like chains. You", - "have felt the embrace", - "of fear, wondering if", - "you face consequence", - "for simply having", - "ideas not in harmony", - "with those forced upon", - "you. You have seen"), - new BookPageInfo( - "men fight and die for", - "the principles of a", - "zealot and wondered,", - "'Who will fight for", - "my principles should", - "they be opposed?'", - "You tire of living", - "under the shadow of"), - new BookPageInfo( - "dreams that do not", - "belong to you. And", - "most of all, you have", - "wondered what you", - "can do to live free.", - " Your journey to", - "freedom begins here.", - " I, like you, once"), - new BookPageInfo( - "desired my freedom", - "from the limits placed", - "on me. I watched in", - "disgust as this world", - "became engrossed with", - "the preaching of", - "virtue and none of the", - "practice. I held my"), - new BookPageInfo( - "convictions in check,", - "fearful of the reaction", - "of men blinded by", - "belief. I forced", - "myself to bury the", - "very ideology that", - "made me an individual.", - "I was fortunate that"), - new BookPageInfo( - "a being of unique", - "power and", - "unimaginable", - "intelligence saw", - "through to the true", - "person I was, the", - "person I was meant to", - "be. Exodus found"), - new BookPageInfo( - "within me a man of", - "free will,", - "determination, and", - "incomprehension for", - "the plight of", - "oppression forced on so", - "many Britannians.", - " Exodus has also"), - new BookPageInfo( - "chosen you because of", - "the strength of your", - "character.", - " Many of the men", - "who were once my", - "peers look upon me", - "and see a betrayer of", - "humanity. They"), - new BookPageInfo( - "claim my newfound", - "form is unnatural and", - "wrong. Because they", - "see the unknown in", - "me, they show fear.", - "They disapprove of", - "my choices and in", - "their ignorance see"), - new BookPageInfo( - "evil. Yet I hide my", - "true self no longer", - "from these men. My", - "thoughts and my", - "personal morality have", - "been liberated in the", - "face of the oppression", - "that once consumed me."), - new BookPageInfo( - "Where they see a", - "man no longer human.", - "I see a man that has", - "not betrayed his", - "humanity but has been", - "freed from it. This", - "is the power that has", - "been granted to me by"), - new BookPageInfo( - "Exodus. I have been", - "given my freedom. I", - "have been released", - "from my fears.", - " Exodus will give", - "you the power to", - "conquer your fears as", - "well."), - new BookPageInfo( - " When your fear", - "of this world is gone,", - "then the world truly", - "belongs to you in a", - "way it never has", - "before. You, trusted", - "one, will soon be given", - "a gift. Your body,"), - new BookPageInfo( - "like mine, will be", - "enlightened and raised", - "to a level no mortal", - "can know. The power", - "to control your own", - "destiny will belong to", - "you for the first time", - "in your life."), - new BookPageInfo( - " You will, at long", - "last, be cleansed of", - "fear.", - " Together, with the", - "power of Exodus", - "behind us, we shall", - "finally wage war on", - "the oppression that"), - new BookPageInfo( - "once held us back", - "from our full", - "potential. We shall", - "claim this world, and", - "reshape it in an image", - "of freedom for all of", - "us. Those who once", - "told you who you are"), - new BookPageInfo( - "and how you should", - "live will no longer be", - "able to stand in the", - "way of your free will.", - "Many say you will", - "be abandoning your", - "humanity but in truth,", - "you will be more than"), - new BookPageInfo( - "human.", - " You will be freed.")); - - [Constructible] - public BlackthornWelcomeBook() : base(false) => Hue = 0x89B; - - public BlackthornWelcomeBook(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class BlackthornWelcomeBook : RedBook + { + public static readonly BookContent Content = new BookContent( + "A Welcome", + "Lord Blackthorn", + new BookPageInfo( + " Greetings to you,", + "new member of the", + "Trusted.", + " You now read these", + "words because you", + "have been deemed", + "worthy to join the", + "ranks of" + ), + new BookPageInfo( + "Britannia's defenders.", + "Some will call you a", + "betrayer of mankind, I", + "say they are", + "misguided. I call you", + "a defender for Sosaria", + "needs saving from", + "itself." + ), + new BookPageInfo( + " The forces of order", + "once ruled our world.", + "Like a great", + "darkness over our", + "lives we lived under", + "the oppressive watch", + "of a king who", + "dictated our actions" + ), + new BookPageInfo( + "and passed judgment", + "on our character. He", + "suppressed our way of", + "life by denying our", + "freedom and the", + "ability to determine", + "who we are and what", + "we stand for. Even" + ), + new BookPageInfo( + "today in the absence", + "of this man we still", + "see the symbol of his", + "tyranny, we watch his", + "personal guards patrol", + "the cities to", + "intimidate us, and we", + "feel his laws like a" + ), + new BookPageInfo( + "vice on our lives.", + " You are here", + "because you choose to", + "be free. Like many", + "Britannians you have", + "felt the oppression of", + "one man's ideas", + "weighing down upon" + ), + new BookPageInfo( + "you like chains. You", + "have felt the embrace", + "of fear, wondering if", + "you face consequence", + "for simply having", + "ideas not in harmony", + "with those forced upon", + "you. You have seen" + ), + new BookPageInfo( + "men fight and die for", + "the principles of a", + "zealot and wondered,", + "'Who will fight for", + "my principles should", + "they be opposed?'", + "You tire of living", + "under the shadow of" + ), + new BookPageInfo( + "dreams that do not", + "belong to you. And", + "most of all, you have", + "wondered what you", + "can do to live free.", + " Your journey to", + "freedom begins here.", + " I, like you, once" + ), + new BookPageInfo( + "desired my freedom", + "from the limits placed", + "on me. I watched in", + "disgust as this world", + "became engrossed with", + "the preaching of", + "virtue and none of the", + "practice. I held my" + ), + new BookPageInfo( + "convictions in check,", + "fearful of the reaction", + "of men blinded by", + "belief. I forced", + "myself to bury the", + "very ideology that", + "made me an individual.", + "I was fortunate that" + ), + new BookPageInfo( + "a being of unique", + "power and", + "unimaginable", + "intelligence saw", + "through to the true", + "person I was, the", + "person I was meant to", + "be. Exodus found" + ), + new BookPageInfo( + "within me a man of", + "free will,", + "determination, and", + "incomprehension for", + "the plight of", + "oppression forced on so", + "many Britannians.", + " Exodus has also" + ), + new BookPageInfo( + "chosen you because of", + "the strength of your", + "character.", + " Many of the men", + "who were once my", + "peers look upon me", + "and see a betrayer of", + "humanity. They" + ), + new BookPageInfo( + "claim my newfound", + "form is unnatural and", + "wrong. Because they", + "see the unknown in", + "me, they show fear.", + "They disapprove of", + "my choices and in", + "their ignorance see" + ), + new BookPageInfo( + "evil. Yet I hide my", + "true self no longer", + "from these men. My", + "thoughts and my", + "personal morality have", + "been liberated in the", + "face of the oppression", + "that once consumed me." + ), + new BookPageInfo( + "Where they see a", + "man no longer human.", + "I see a man that has", + "not betrayed his", + "humanity but has been", + "freed from it. This", + "is the power that has", + "been granted to me by" + ), + new BookPageInfo( + "Exodus. I have been", + "given my freedom. I", + "have been released", + "from my fears.", + " Exodus will give", + "you the power to", + "conquer your fears as", + "well." + ), + new BookPageInfo( + " When your fear", + "of this world is gone,", + "then the world truly", + "belongs to you in a", + "way it never has", + "before. You, trusted", + "one, will soon be given", + "a gift. Your body," + ), + new BookPageInfo( + "like mine, will be", + "enlightened and raised", + "to a level no mortal", + "can know. The power", + "to control your own", + "destiny will belong to", + "you for the first time", + "in your life." + ), + new BookPageInfo( + " You will, at long", + "last, be cleansed of", + "fear.", + " Together, with the", + "power of Exodus", + "behind us, we shall", + "finally wage war on", + "the oppression that" + ), + new BookPageInfo( + "once held us back", + "from our full", + "potential. We shall", + "claim this world, and", + "reshape it in an image", + "of freedom for all of", + "us. Those who once", + "told you who you are" + ), + new BookPageInfo( + "and how you should", + "live will no longer be", + "able to stand in the", + "way of your free will.", + "Many say you will", + "be abandoning your", + "humanity but in truth,", + "you will be more than" + ), + new BookPageInfo( + "human.", + " You will be freed." + ) + ); + + [Constructible] + public BlackthornWelcomeBook() : base(false) => Hue = 0x89B; + + public BlackthornWelcomeBook(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Books/Defined/BookContent.cs b/Projects/UOContent/Items/Books/Defined/BookContent.cs index 48d3cd25a..18d6395cc 100644 --- a/Projects/UOContent/Items/Books/Defined/BookContent.cs +++ b/Projects/UOContent/Items/Books/Defined/BookContent.cs @@ -1,49 +1,49 @@ -namespace Server.Items -{ - public class BookContent - { - public BookContent(string title, string author, params BookPageInfo[] pages) - { - Title = title; - Author = author; - Pages = pages; - } - - public string Title { get; } - - public string Author { get; } - - public BookPageInfo[] Pages { get; } - - public BookPageInfo[] Copy() - { - BookPageInfo[] copy = new BookPageInfo[Pages.Length]; - - for (int i = 0; i < copy.Length; ++i) - copy[i] = new BookPageInfo(Pages[i].Lines); - - return copy; - } - - public bool IsMatch(BookPageInfo[] cmp) - { - if (cmp.Length != Pages.Length) - return false; - - for (int i = 0; i < cmp.Length; ++i) - { - string[] a = Pages[i].Lines; - string[] b = cmp[i].Lines; - - if (a.Length != b.Length) return false; - - if (a != b) - for (int j = 0; j < a.Length; ++j) - if (a[j] != b[j]) - return false; - } - - return true; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class BookContent + { + public BookContent(string title, string author, params BookPageInfo[] pages) + { + Title = title; + Author = author; + Pages = pages; + } + + public string Title { get; } + + public string Author { get; } + + public BookPageInfo[] Pages { get; } + + public BookPageInfo[] Copy() + { + var copy = new BookPageInfo[Pages.Length]; + + for (var i = 0; i < copy.Length; ++i) + copy[i] = new BookPageInfo(Pages[i].Lines); + + return copy; + } + + public bool IsMatch(BookPageInfo[] cmp) + { + if (cmp.Length != Pages.Length) + return false; + + for (var i = 0; i < cmp.Length; ++i) + { + var a = Pages[i].Lines; + var b = cmp[i].Lines; + + if (a.Length != b.Length) return false; + + if (a != b) + for (var j = 0; j < a.Length; ++j) + if (a[j] != b[j]) + return false; + } + + return true; + } + } +} diff --git a/Projects/UOContent/Items/Books/Defined/DrakovsJournal.cs b/Projects/UOContent/Items/Books/Defined/DrakovsJournal.cs index 67f6c2865..e42443b90 100644 --- a/Projects/UOContent/Items/Books/Defined/DrakovsJournal.cs +++ b/Projects/UOContent/Items/Books/Defined/DrakovsJournal.cs @@ -1,106 +1,117 @@ -namespace Server.Items -{ - public class DrakovsJournal : BlueBook - { - public static readonly BookContent Content = new BookContent( - "Drakov's Journal", "Drakov", - new BookPageInfo( - "My Master", - "", - "This journal was", - "found on one of", - "our controllers. It", - "seems he has lost", - "faith in you. Know", - "that he has been"), - new BookPageInfo( - "dealth with and will", - "never again speak", - "ill of you or our", - "cause.", - " -Galzon"), - new BookPageInfo( - "We have completted", - "construction of the", - "devices needed to", - "build the clockwork", - "overseers and minions", - "as per the request of", - "the Master. The", - "gargoyles have been"), - new BookPageInfo( - "most useful and their", - "knowledge of the", - "techniques for the", - "construction of these", - "creatures will serve", - "us well.", - " -----", - "I am not one to"), - new BookPageInfo( - "criticize the Master,", - "but I believe he may", - "have erred in his", - "decision to destroy", - "the wingless ones.", - "Already our forces", - "are weakened by the", - "constant attacks of"), - new BookPageInfo( - "the humans Their", - "strength and", - "unquestioning", - "compliance would", - "have made them very", - "useful in the fight", - "against the humans.", - "But the Master felt"), - new BookPageInfo( - "their presence to be", - "an annoyance and", - "a distraction to the", - "winged ones. It was", - "not difficult at all", - "to remove them from", - "this world. But now", - "I fear without more"), - new BookPageInfo( - "allies, willing or", - "not, we stand", - "little chance of", - "defeating the foul", - "humans from our", - "lands. Perhaps if", - "the Master had", - "shown a little"), - new BookPageInfo( - "mercy and forsight", - "we would not be", - "in such dire peril.")); - - [Constructible] - public DrakovsJournal() : base(false) - { - } - - public DrakovsJournal(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class DrakovsJournal : BlueBook + { + public static readonly BookContent Content = new BookContent( + "Drakov's Journal", + "Drakov", + new BookPageInfo( + "My Master", + "", + "This journal was", + "found on one of", + "our controllers. It", + "seems he has lost", + "faith in you. Know", + "that he has been" + ), + new BookPageInfo( + "dealth with and will", + "never again speak", + "ill of you or our", + "cause.", + " -Galzon" + ), + new BookPageInfo( + "We have completted", + "construction of the", + "devices needed to", + "build the clockwork", + "overseers and minions", + "as per the request of", + "the Master. The", + "gargoyles have been" + ), + new BookPageInfo( + "most useful and their", + "knowledge of the", + "techniques for the", + "construction of these", + "creatures will serve", + "us well.", + " -----", + "I am not one to" + ), + new BookPageInfo( + "criticize the Master,", + "but I believe he may", + "have erred in his", + "decision to destroy", + "the wingless ones.", + "Already our forces", + "are weakened by the", + "constant attacks of" + ), + new BookPageInfo( + "the humans Their", + "strength and", + "unquestioning", + "compliance would", + "have made them very", + "useful in the fight", + "against the humans.", + "But the Master felt" + ), + new BookPageInfo( + "their presence to be", + "an annoyance and", + "a distraction to the", + "winged ones. It was", + "not difficult at all", + "to remove them from", + "this world. But now", + "I fear without more" + ), + new BookPageInfo( + "allies, willing or", + "not, we stand", + "little chance of", + "defeating the foul", + "humans from our", + "lands. Perhaps if", + "the Master had", + "shown a little" + ), + new BookPageInfo( + "mercy and forsight", + "we would not be", + "in such dire peril." + ) + ); + + [Constructible] + public DrakovsJournal() : base(false) + { + } + + public DrakovsJournal(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Books/Defined/FropozJournal.cs b/Projects/UOContent/Items/Books/Defined/FropozJournal.cs index aa43f6e78..cf053ce7d 100644 --- a/Projects/UOContent/Items/Books/Defined/FropozJournal.cs +++ b/Projects/UOContent/Items/Books/Defined/FropozJournal.cs @@ -1,151 +1,165 @@ -namespace Server.Items -{ - public class FropozJournal : RedBook - { - public static readonly BookContent Content = new BookContent( - "Journal", "Fropoz", - new BookPageInfo( - "I have done as my", - "Master has", - "instructed me.", - "", - "The painted humans", - "have been driven into", - "Britannia and are even", - "now wreaking havoc"), - new BookPageInfo( - "across the land,", - "providing us with the", - "distraction my Master", - "requested. We", - "have provided them", - "with the masks", - "necessary to defeat", - "the orcs, thus"), - new BookPageInfo( - "causing even more", - "distress for the people", - "of Britannia. The", - "unsuspecting fools", - "are too busy dealing", - "with the orc hordes to", - "continue their", - "exploration of our"), - new BookPageInfo( - "lands. We are", - "safe...for now.", - " ----", - "The attacks", - "continue exactly as", - "planned. My Master", - "is pleased with my", - "work and we are"), - new BookPageInfo( - "closer to our goals than", - "ever before. The", - "gargoyles have proven", - "to be more troublesome", - "than we first", - "anticipated, but I", - "believe we can", - "subjugate them fully"), - new BookPageInfo( - "given enough time. It's", - "unfortunate that we", - "did not discover their", - "knowledge sooner.", - "Even now they", - "prepare our armies", - "for battle, but not", - "without resistance."), - new BookPageInfo( - "Now that some of", - "them know of the", - "other lands and of", - "humans, they will", - "double their efforts to", - "seek help. This", - "cannot be allowed.", - " -----"), - new BookPageInfo( - "Damn them!! The", - "humans proved", - "more resourcefull than", - "we thought them", - "capable of. Already", - "their homes are free", - "of orcs and savages", - "and they once again"), - new BookPageInfo( - "are treading in our", - "lands. We may have to", - "move sooner than we", - "thought. I will", - "prepar my brethern", - "and our golems.", - "Hopefully, we can", - "buy our Master some"), - new BookPageInfo( - "more time before the", - "humans discover us.", - " -----", - "It's too late. The", - "gargoyles whom have", - "evaded our capture", - "have opened the doors", - "to our land."), - new BookPageInfo( - "They pray the", - "humans will help", - "them, despite the", - "actions of their", - "cousins in Britannia. I", - "fear they are right.", - "I must go to warn", - "the MastKai Hohiro,"), - new BookPageInfo(), - new BookPageInfo( - "10.11.2001", - "first one to be here", - "", - "Congrats. I didn't really", - "care to log on earlier,", - "nor did I come straight", - "here. 2pm, Magus")); - - [Constructible] - public FropozJournal() : base(false) - { - } - - public FropozJournal(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void AddNameProperty(ObjectPropertyList list) - { - list.Add("Fropoz's Journal"); - } - - public override void OnSingleClick(Mobile from) - { - LabelTo(from, "Fropoz's Journal"); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FropozJournal : RedBook + { + public static readonly BookContent Content = new BookContent( + "Journal", + "Fropoz", + new BookPageInfo( + "I have done as my", + "Master has", + "instructed me.", + "", + "The painted humans", + "have been driven into", + "Britannia and are even", + "now wreaking havoc" + ), + new BookPageInfo( + "across the land,", + "providing us with the", + "distraction my Master", + "requested. We", + "have provided them", + "with the masks", + "necessary to defeat", + "the orcs, thus" + ), + new BookPageInfo( + "causing even more", + "distress for the people", + "of Britannia. The", + "unsuspecting fools", + "are too busy dealing", + "with the orc hordes to", + "continue their", + "exploration of our" + ), + new BookPageInfo( + "lands. We are", + "safe...for now.", + " ----", + "The attacks", + "continue exactly as", + "planned. My Master", + "is pleased with my", + "work and we are" + ), + new BookPageInfo( + "closer to our goals than", + "ever before. The", + "gargoyles have proven", + "to be more troublesome", + "than we first", + "anticipated, but I", + "believe we can", + "subjugate them fully" + ), + new BookPageInfo( + "given enough time. It's", + "unfortunate that we", + "did not discover their", + "knowledge sooner.", + "Even now they", + "prepare our armies", + "for battle, but not", + "without resistance." + ), + new BookPageInfo( + "Now that some of", + "them know of the", + "other lands and of", + "humans, they will", + "double their efforts to", + "seek help. This", + "cannot be allowed.", + " -----" + ), + new BookPageInfo( + "Damn them!! The", + "humans proved", + "more resourcefull than", + "we thought them", + "capable of. Already", + "their homes are free", + "of orcs and savages", + "and they once again" + ), + new BookPageInfo( + "are treading in our", + "lands. We may have to", + "move sooner than we", + "thought. I will", + "prepar my brethern", + "and our golems.", + "Hopefully, we can", + "buy our Master some" + ), + new BookPageInfo( + "more time before the", + "humans discover us.", + " -----", + "It's too late. The", + "gargoyles whom have", + "evaded our capture", + "have opened the doors", + "to our land." + ), + new BookPageInfo( + "They pray the", + "humans will help", + "them, despite the", + "actions of their", + "cousins in Britannia. I", + "fear they are right.", + "I must go to warn", + "the MastKai Hohiro," + ), + new BookPageInfo(), + new BookPageInfo( + "10.11.2001", + "first one to be here", + "", + "Congrats. I didn't really", + "care to log on earlier,", + "nor did I come straight", + "here. 2pm, Magus" + ) + ); + + [Constructible] + public FropozJournal() : base(false) + { + } + + public FropozJournal(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + public override void AddNameProperty(ObjectPropertyList list) + { + list.Add("Fropoz's Journal"); + } + + public override void OnSingleClick(Mobile from) + { + LabelTo(from, "Fropoz's Journal"); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Books/Defined/KaburJournal.cs b/Projects/UOContent/Items/Books/Defined/KaburJournal.cs index 5f1a7beb9..fbd0c9469 100644 --- a/Projects/UOContent/Items/Books/Defined/KaburJournal.cs +++ b/Projects/UOContent/Items/Books/Defined/KaburJournal.cs @@ -1,222 +1,244 @@ -namespace Server.Items -{ - public class KaburJournal : RedBook - { - public static readonly BookContent Content = new BookContent( - "Journal", "Kabur", - new BookPageInfo( - "The campaign to slaughter", - "the Meer goes well.", - "Although they seem to", - "oppose the forces of", - "ours at every turn, we", - "still defeat them in", - "combat. Spies of the", - "Meer have been found and"), - new BookPageInfo( - "slain outside of the", - "fortress of ours. The", - "fools underestimate us.", - "We have the power of", - "Lord Exodus behind us.", - "Soon they will learn to", - "serve the Juka and I", - "shall carry the head of"), - new BookPageInfo( - "the wench, Dasha, on a", - "spike for all the warriors", - "of ours to share triumph", - "under.", - "", - "One of the warriors of", - "the Juka died today.", - "During the training"), - new BookPageInfo( - "exercises of ours he", - "spoke out in favor of", - "the warriors of the", - "Meer, saying that they", - "were indeed powerful and", - "would provide a challenge", - "to the Juka. A Juka in", - "fear is no Juka. I gave"), - new BookPageInfo( - "him the death of a", - "coward, outside of battle.", - "", - "More spies of the Meer", - "have been found around", - "the fortress of ours.", - "Many have been seen and", - "escaped the wrath of the"), - new BookPageInfo( - "warriors of ours. Those", - "who have been captured", - "and tortured have", - "revealed nothing to us,", - "even when subjected to", - "the spells of the females.", - " I know the Meer must", - "have plans against us if"), - new BookPageInfo( - "they send so many spies.", - " I may send the troops", - "of the Juka to invade", - "the camps of theirs as a", - "warning.", - "", - "I have met Dasha in", - "battle this day. The"), - new BookPageInfo( - "efforts of hers to draw", - "me into a Black Duel", - "were foolish. Had we", - "not been interrupted in", - "the cave I would have", - "ended the life of hers", - "but I will have to wait", - "for another battle. Lord"), - new BookPageInfo( - "Exodus has ordered more", - "patrols around the", - "fortress of ours. If", - "Dasha is any indication,", - "the Meer will strike soon.", - "", - "More Meer stand outside", - "of the fortress of ours"), - new BookPageInfo( - "than I have ever seen at", - "once. They must seek", - "vengeance for the", - "destruction of their", - "forest. Many Juka stand", - "ready at the base of the", - "mountain to face the", - "forces of theirs but"), - new BookPageInfo( - "today may be the final", - "battle. Exodus has", - "summoned me, I must", - "prepare.", - "", - "Dusk has passed and the", - "Juka now live in a new", - "age, a later time. I have"), - new BookPageInfo( - "just returned from", - "exploring the new world", - "that surrounds the", - "fortress of the Juka.", - "During the attack of the", - "Meer the madman", - "Adranath tried to destroy", - "the fortress of ours"), - new BookPageInfo( - "with great magic. At", - "once he was still and", - "light surrounded the", - "fortress. Everything", - "faded from view. When I", - "regained the senses of", - "mine I saw no sign of", - "the Meer but Dasha."), - new BookPageInfo( - "She has not been found", - "since this new being,", - "Blackthorn, blasted her", - "from the top of the", - "fortress.", - "The forest was gone, now", - "replaced by grasslands.", - "In the far distance I"), - new BookPageInfo( - "could see humans that", - "had covered the bodies of", - "theirs in marks. Even", - "Gargoyles populate this", - "place. Exodus has", - "explained to me that the", - "Juka and the fortress of", - "ours have been pulled"), - new BookPageInfo( - "forward in time. The", - "world we knew is now", - "thousands of years in the", - "past. Lord Exodus say", - "he has has saved the", - "Juka from extinction. I", - "do not want to believe", - "him. I asked this"), - new BookPageInfo( - "stranger about the Meer,", - "but he tells me a new", - "enemy remains to be", - "destroyed. It seems the", - "enemies of ours have", - "passed away to dust like", - "the forest."), - new BookPageInfo( - "I have spoken with other", - "Juka and I suspect I have", - "been told the truth. All", - "the Juka had powerful", - "dreams. In the dreams", - "of ours the Meer invaded", - "the fortress of ours and", - "a great battle took place."), - new BookPageInfo( - " All the Juka and all the", - "Meer perished and the", - "fortress was destroyed", - "from Adranath's spells. I", - "would not like to believe", - "that the Meer could ever", - "destroy us, but now it", - "seems we have seen a"), - new BookPageInfo( - "vision of the fate of", - "ours now lost in time. I", - "must now wonder if the", - "Meer did not die in the", - "battle with the Juka, how", - "did they die? And more", - "importantly, where is", - "Dasha?")); - - [Constructible] - public KaburJournal() : base(false) - { - } - - public KaburJournal(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void AddNameProperty(ObjectPropertyList list) - { - list.Add("Khabur's Journal"); - } - - public override void OnSingleClick(Mobile from) - { - LabelTo(from, "Khabur's Journal"); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class KaburJournal : RedBook + { + public static readonly BookContent Content = new BookContent( + "Journal", + "Kabur", + new BookPageInfo( + "The campaign to slaughter", + "the Meer goes well.", + "Although they seem to", + "oppose the forces of", + "ours at every turn, we", + "still defeat them in", + "combat. Spies of the", + "Meer have been found and" + ), + new BookPageInfo( + "slain outside of the", + "fortress of ours. The", + "fools underestimate us.", + "We have the power of", + "Lord Exodus behind us.", + "Soon they will learn to", + "serve the Juka and I", + "shall carry the head of" + ), + new BookPageInfo( + "the wench, Dasha, on a", + "spike for all the warriors", + "of ours to share triumph", + "under.", + "", + "One of the warriors of", + "the Juka died today.", + "During the training" + ), + new BookPageInfo( + "exercises of ours he", + "spoke out in favor of", + "the warriors of the", + "Meer, saying that they", + "were indeed powerful and", + "would provide a challenge", + "to the Juka. A Juka in", + "fear is no Juka. I gave" + ), + new BookPageInfo( + "him the death of a", + "coward, outside of battle.", + "", + "More spies of the Meer", + "have been found around", + "the fortress of ours.", + "Many have been seen and", + "escaped the wrath of the" + ), + new BookPageInfo( + "warriors of ours. Those", + "who have been captured", + "and tortured have", + "revealed nothing to us,", + "even when subjected to", + "the spells of the females.", + " I know the Meer must", + "have plans against us if" + ), + new BookPageInfo( + "they send so many spies.", + " I may send the troops", + "of the Juka to invade", + "the camps of theirs as a", + "warning.", + "", + "I have met Dasha in", + "battle this day. The" + ), + new BookPageInfo( + "efforts of hers to draw", + "me into a Black Duel", + "were foolish. Had we", + "not been interrupted in", + "the cave I would have", + "ended the life of hers", + "but I will have to wait", + "for another battle. Lord" + ), + new BookPageInfo( + "Exodus has ordered more", + "patrols around the", + "fortress of ours. If", + "Dasha is any indication,", + "the Meer will strike soon.", + "", + "More Meer stand outside", + "of the fortress of ours" + ), + new BookPageInfo( + "than I have ever seen at", + "once. They must seek", + "vengeance for the", + "destruction of their", + "forest. Many Juka stand", + "ready at the base of the", + "mountain to face the", + "forces of theirs but" + ), + new BookPageInfo( + "today may be the final", + "battle. Exodus has", + "summoned me, I must", + "prepare.", + "", + "Dusk has passed and the", + "Juka now live in a new", + "age, a later time. I have" + ), + new BookPageInfo( + "just returned from", + "exploring the new world", + "that surrounds the", + "fortress of the Juka.", + "During the attack of the", + "Meer the madman", + "Adranath tried to destroy", + "the fortress of ours" + ), + new BookPageInfo( + "with great magic. At", + "once he was still and", + "light surrounded the", + "fortress. Everything", + "faded from view. When I", + "regained the senses of", + "mine I saw no sign of", + "the Meer but Dasha." + ), + new BookPageInfo( + "She has not been found", + "since this new being,", + "Blackthorn, blasted her", + "from the top of the", + "fortress.", + "The forest was gone, now", + "replaced by grasslands.", + "In the far distance I" + ), + new BookPageInfo( + "could see humans that", + "had covered the bodies of", + "theirs in marks. Even", + "Gargoyles populate this", + "place. Exodus has", + "explained to me that the", + "Juka and the fortress of", + "ours have been pulled" + ), + new BookPageInfo( + "forward in time. The", + "world we knew is now", + "thousands of years in the", + "past. Lord Exodus say", + "he has has saved the", + "Juka from extinction. I", + "do not want to believe", + "him. I asked this" + ), + new BookPageInfo( + "stranger about the Meer,", + "but he tells me a new", + "enemy remains to be", + "destroyed. It seems the", + "enemies of ours have", + "passed away to dust like", + "the forest." + ), + new BookPageInfo( + "I have spoken with other", + "Juka and I suspect I have", + "been told the truth. All", + "the Juka had powerful", + "dreams. In the dreams", + "of ours the Meer invaded", + "the fortress of ours and", + "a great battle took place." + ), + new BookPageInfo( + " All the Juka and all the", + "Meer perished and the", + "fortress was destroyed", + "from Adranath's spells. I", + "would not like to believe", + "that the Meer could ever", + "destroy us, but now it", + "seems we have seen a" + ), + new BookPageInfo( + "vision of the fate of", + "ours now lost in time. I", + "must now wonder if the", + "Meer did not die in the", + "battle with the Juka, how", + "did they die? And more", + "importantly, where is", + "Dasha?" + ) + ); + + [Constructible] + public KaburJournal() : base(false) + { + } + + public KaburJournal(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + public override void AddNameProperty(ObjectPropertyList list) + { + list.Add("Khabur's Journal"); + } + + public override void OnSingleClick(Mobile from) + { + LabelTo(from, "Khabur's Journal"); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Books/Defined/LibraryBooks.cs b/Projects/UOContent/Items/Books/Defined/LibraryBooks.cs index 290f22564..74cbe8d29 100644 --- a/Projects/UOContent/Items/Books/Defined/LibraryBooks.cs +++ b/Projects/UOContent/Items/Books/Defined/LibraryBooks.cs @@ -1,5124 +1,5665 @@ -namespace Server.Items -{ - public class GrammarOfOrcish : BaseBook - { - public static readonly BookContent Content = new BookContent( - "A Grammar of Orcish", "Yorick of Yew", - new BookPageInfo( - "This volume, and", - "others in the series,", - "are sponsored by", - "donations from Lord", - "Blackthorn, ever a", - "supporter of", - "understanding the", - "other sentient races"), - new BookPageInfo( - "of Britannia.", - "-", - "", - " The Orcish tongue", - "may fall unpleasingly", - "'pon the ear, yet it", - "has within it a", - "complex grammar oft"), - new BookPageInfo( - "misunderstood by", - "those who merely", - "hear the few broken", - "words of English our", - "orcish brothers", - "manage without", - "education.", - " These are the basic"), - new BookPageInfo( - "rules of orcish:", - " Orcish has five", - "tenses: present, past,", - "future imperfect,", - "present interjectional,", - "and prehensile.", - " Examples: gugroflu,", - "gugrofloog, gugrobo,"), - new BookPageInfo( - "gugroglu!, gugrogug.", - " All transitive verbs", - "in the prehensile", - "tense end in \"ug.\"", - " Examples:", - "urgleighug,", - "biggugdaghgug,", - "curdakalmug."), - new BookPageInfo( - " All present", - "interjectional", - "conjugations start", - "with the letter G", - "unless the contain the", - "third declensive", - "accent of the letter U.", - " Examples:"), - new BookPageInfo( - "ghothudunglug, but not", - "azhbuugub.", - " The past tense can", - "only refer to events", - "since the last meal,", - "but the prehensile", - "tense can refer to", - "any event within"), - new BookPageInfo( - "reach.", - " The present tense", - "is conjugated like the", - "future imperfect", - "tense, when the", - "interrogative mode is", - "used by pitching the", - "sound a quarter-tone"), - new BookPageInfo( - "higher.", - "Orcish hath no", - "concept of person, as", - "in first person, third", - "person, I, we, etc.", - " Orcish grammar", - "relies upon the three", - "cardinal rules of"), - new BookPageInfo( - "accretion, prefixing,", - "and agglutination, in", - "addition to pitch. In", - "the former, phonemes", - "combine into larger", - "words which may", - "contain full phrasal", - "significance. In the"), - new BookPageInfo( - "second, prefixing", - "specific phonetic", - "sounds changes the", - "subject of the", - "sentence into object,", - "interrogative,", - "addressed individual,", - "or dinner."), - new BookPageInfo( - " Agglutination occurs", - "whenever four of the", - "same letter are", - "present in a word, in", - "which case, any two", - "of them may be", - "removed or slurred.", - " Pitch changes the"), - new BookPageInfo( - "phoneme value of", - "individual syllables,", - "thus completely", - "altering what a word", - "may mean. The", - "classic example is", - "\"Aktgluthugrot", - "bigglogubuu"), - new BookPageInfo( - "dargilgaglug lublublub\"", - "which can mean \"You", - "are such a pretty", - "girl,\" \"My mother ate", - "your primroses,\" or", - "\"Jellyfish nose paints", - "alms potato,\"", - "depending on pitch."), - new BookPageInfo( - " Orcish poetry often", - "relies upon repeating", - "the same phrase in", - "multiple pitches, even", - "changing pitch", - "midword. None of", - "this great art is", - "translatable."), - new BookPageInfo( - " The orcish language", - "uses the following", - "vowels: ab, ad, ag, akt,", - "at, augh, auh, azh, e,", - "i, o, oo, u, uu. The", - "vowel sound a is not", - "recognized as a vowel", - "and does not exist in"), - new BookPageInfo( - "their alphabet.", - "The orcish alphabet is", - "best learned using the", - "classic rhyme", - "repeated at 23", - "different pitches:", - " Lugnog ghu blat", - "suggaroglug,"), - new BookPageInfo( - "Gaghbuu dakdar ab", - "highugbo,", - " Gothnogbuim ad", - "gilgubbugbuilug", - "Bilgeaugh thurggulg", - "stuiggro!", - "", - "A translation of the"), - new BookPageInfo( - "first pitch:", - "Eat food, the first", - "letter is ab,", - "Kill people, next letter", - "is ad,", - "I forget the rest", - "But augh is in there", - "somewhere!"), - new BookPageInfo( - "", - " What follows is a", - "complete phonetic", - "library of the orcish", - "language:", - "ab, ad, ag, akt, alm,", - "at, augh, auh, azh,", - "ba, ba, bag, bar, baz,"), - new BookPageInfo( - "bid, bilge, bo, bog, bog,", - "brui, bu, buad, bug,", - "bug, buil, buim, bum,", - "buo, buor, buu, ca,", - "car, clog, cro, cuk,", - "cur, da, dagh, dagh,", - "dak, dar, deak, der,", - "dil, dit, dor, dre, dri,"), - new BookPageInfo( - "dru, du, dud, duf,", - "dug, dug, duh, dun,", - "eag, eg, egg, eichel,", - "ek, ep, ewk, faugh,", - "fid, flu, fog, foo,", - "foz, fruk, fu, fub,", - "fud, fun, fup, fur,", - "gaa, gag, gagh, gan,"), - new BookPageInfo( - "gar, gh, gha, ghat,", - "ghed, ghig, gho, ghu,", - "gig, gil, gka, glu, glu,", - "glug, gna, gno, gnu,", - "gol, gom, goth, grunt,", - "grut, gu, gub, gub,", - "gug, gug, gugh, guk,", - "guk,")); - - [Constructible] - public GrammarOfOrcish() : base(Utility.Random(0xFEF, 2), false) - { - } - - public GrammarOfOrcish(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class CallToAnarchy : BaseBook - { - public static readonly BookContent Content = new BookContent( - "A Politic Call to Anarchy", "Lord Blackthorn", - new BookPageInfo( - " Let it never be said", - "that I have aught as", - "quarrel with my liege", - "Lord British, for", - "indeed we be of the", - "best of friends,", - "sharing amicable", - "games of chess 'pon a"), - new BookPageInfo( - "winter's night, and", - "talking at length into", - "the wee hours of the", - "issues that affect the", - "realm of Britannia.", - " Yet true friendship", - "doth not prevent true", - "philosophical"), - new BookPageInfo( - "disagreement either.", - "While I view with", - "approval my lord's", - "affection for his", - "carefully crafted", - "philosophy of the", - "Eight Virtues,", - "wherein moral"), - new BookPageInfo( - "behavior is", - "encouraged in the", - "populace, I view with", - "less approval the", - "expenditure of public", - "funds upon the", - "construction of", - "\"shrines\" to said"), - new BookPageInfo( - "ideals.", - " The issue is not one", - "of funds, however,", - "but a disagreement", - "most intellectual over", - "the proper way of", - "humankind in an", - "ethical sense. Surely"), - new BookPageInfo( - "freedom of decision", - "must be regarded as", - "paramount in any", - "such moral decision?", - "Though none fail to", - "censure the", - "murderer, a subtler", - "question arises when"), - new BookPageInfo( - "we ask if his", - "behavior would be", - "ethical if he were", - "forced to it.", - " I say to thee, the", - "reader, quite flatly,", - "that no ethical system", - "shall have sway over"), - new BookPageInfo( - "me unless it", - "convinceth me, for", - "that freely made", - "choice is to me the", - "sign that the system", - "hath validity.", - " Whereas the system", - "of \"Virtues\" that my"), - new BookPageInfo( - "liege espouses is", - "indeed a compilation", - "of commonly approved", - "virtues, I approve of", - "it. Where it seeks to", - "control the populace", - "and restrict their", - "diversity and their"), - new BookPageInfo( - "range of behaviors, I", - "quarrel with it. And", - "thus do I issue this", - "politic call to anarchy,", - "whilst humbly", - "begging forgiveness", - "of Lord British for", - "my impertinence:"), - new BookPageInfo( - " Celebrate thy", - "differences. Take", - "thy actions according", - "to thy own lights.", - "Question from what", - "source a law, a rule,", - "a judge, and a virtue", - "may arise. 'Twere"), - new BookPageInfo( - "possible (though I", - "suggest it not", - "seriously) that a", - "daemon planted the", - "seed of these", - "\"Virtues\" in my Lord", - "British's mind; 'twere", - "possible that the"), - new BookPageInfo( - "Shrines were but a", - "plan to destroy this", - "world. Thou canst not", - "know unless thou", - "questioneth, doubteth,", - "and in the end,", - "unless thou relyest", - "upon THYSELF and"), - new BookPageInfo( - "thy judgement.", - " I offer these words", - "as mere philosophical", - "musings for those", - "who seek", - "enlightenment, for", - "'tis the issue that", - "hath occupied mine"), - new BookPageInfo( - "interest and that of", - "Lord British for", - "some time now.")); - - [Constructible] - public CallToAnarchy() : base(Utility.Random(0xFEF, 2), false) - { - } - - public CallToAnarchy(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ArmsAndWeaponsPrimer : BaseBook - { - public static readonly BookContent Content = new BookContent( - "A Primer on Arms and Weapons", "Martin", - new BookPageInfo( - " These are the", - "basic elements to", - "consider in assessing", - "a weapon, of which", - "all warriors who", - "regard themselves as", - "more than mere", - "mercenaries should be"), - new BookPageInfo( - "aware.", - " First and most", - "obvious is the amount", - "of damage that the", - "weapon may do", - "against unprotected", - "flesh. While 'tis this", - "which first attracts"), - new BookPageInfo( - "the attention of the", - "novice, 'tis a deadly", - "mistake to regard it", - "as the sole value of a", - "weapon. While it may", - "prove devastating", - "indeed as a means of", - "causing damage, a"), - new BookPageInfo( - "weapon must also", - "serve as stout shield", - "when engaged in", - "combat.", - " Hence the second", - "issue to which to pay", - "attention is the", - "amount of protection"), - new BookPageInfo( - "that a weapon may", - "offer. Pay close", - "attention to the guard", - "on it, if it be a blade,", - "or the stoutness of", - "its wood if it is a pole", - "arm.", - " Oft related to this"), - new BookPageInfo( - "is the weight of the", - "weapon, for a heavy", - "weapon is more", - "difficult to maneuver", - "to block with, though", - "it may do more", - "damage to thy", - "opponent."), - new BookPageInfo( - " If a weapon is too", - "heavy for the wielder", - "to move it freely,", - "they should choose", - "another and not", - "attempt to prove their", - "prowess by the size", - "of their sword."), - new BookPageInfo( - " The reach of a", - "weapon both increases", - "its defensive ability,", - "and renders it more", - "useful in open spaces", - "as it allows attack", - "against the opponent", - "without the need to"), - new BookPageInfo( - "close. But be aware of", - "the limitations of thy", - "weapon! For a", - "weapon with great", - "reach may be useless", - "in close quarters, for", - "lack of space to", - "maneuver it. Should"), - new BookPageInfo( - "that dagger-wielding", - "enemy close on thee", - "and thy halberd, 'tis", - "best to flee.", - " Lastly, a factor", - "that must always be", - "considered is the", - "condition of the"), - new BookPageInfo( - "weapon. It might be a", - "wondrous magical", - "blade of surpassing", - "sharpness and it may", - "leap to block blows", - "with a mind of its", - "own. It also might be", - "of such flimsy"), - new BookPageInfo( - "construction, or", - "damaged to such an", - "extent, that the first", - "time it clangs against", - "steel, 'twill shatter", - "into useless shards.", - " Seek ye a good", - "blacksmith should thy"), - new BookPageInfo( - "weapon become", - "damaged, but be", - "aware that their", - "ministrations may", - "simply make the", - "matter worse.", - " While mages of", - "some ability oft create"), - new BookPageInfo( - "magical weapons", - "which enhance skill,", - "are preternaturally", - "sharp, or incinerate", - "the enemy as they", - "fall, to my mind the", - "greatest gift that they", - "can grant a stout"), - new BookPageInfo( - "sword is to make it", - "resistant to damage,", - "for thy own skill can", - "make up the", - "difference. Except", - "for the fireball, but", - "if the corpse is", - "charred, then so will"), - new BookPageInfo( - "be the possessions,", - "which maketh looting", - "difficult!")); - - [Constructible] - public ArmsAndWeaponsPrimer() : base(Utility.Random(0xFEF, 2), false) - { - } - - public ArmsAndWeaponsPrimer(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SongOfSamlethe : BaseBook - { - public static readonly BookContent Content = new BookContent( - "A Song of Samlethe", "Sandra", - new BookPageInfo( - "The first bear did", - "swim by day,", - "And it did sleep by", - "night.", - "It kept itself within", - "its cave", - "and ate by starry", - "light."), - new BookPageInfo( - "", - "The second bear it did", - "cavort", - "'Neath canopies of", - "trees,", - "And danced its", - "strange bearish sort", - "Of joy for all to see."), - new BookPageInfo( - "", - "The first bear, well,", - "'twas hunted,", - "And today adorns a", - "floor.", - "Its ruggish face has", - "been dented", - "By footfalls and the"), - new BookPageInfo( - "door.", - "", - "The second bear did", - "step once", - "Into a mushroom ring,", - "And now does dance", - "the dunce", - "For wisps and"), - new BookPageInfo( - "unseen things.", - "", - "So do not dance, and", - "do not sleep,", - "Or else be led astray!", - "For bears all end up", - "six feet deep", - "At the end of"), - new BookPageInfo( - "Samlethe's day.")); - - [Constructible] - public SongOfSamlethe() : base(Utility.Random(0xFEF, 2), false) - { - } - - public SongOfSamlethe(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TaleOfThreeTribes : BaseBook - { - public static readonly BookContent Content = new BookContent( - "A Tale of Three Tribes", "Janet, Scribe", - new BookPageInfo( - " The dungeon known", - "as Despise is in fact", - "not a dungeon as", - "such, but rather a", - "large natural cave.", - "Inhospitable and", - "unfriendly to", - "visitors, it is filled"), - new BookPageInfo( - "with damp spots", - "where the deadly", - "Exploding Red Spotted", - "Toadstool grows in", - "abundance.", - " According to the", - "oldest of historical", - "texts, in days gone"), - new BookPageInfo( - "by the cave was once", - "the home of three", - "separate tribes who", - "had come to an", - "accommodation with", - "each other. Oddly", - "enough, the three", - "tribes were of"), - new BookPageInfo( - "dragons, lizard men,", - "and rat men. While", - "today few except", - "extremists associated", - "with Lord Blackthorn", - "regard these latter", - "two as being", - "intelligent beings,"), - new BookPageInfo( - "apparently they have", - "indeed fallen from a", - "more evolved state", - "over the years.", - " 'Tis said that these", - "three races did dwell", - "in relative harmony", - "within the vast cave,"), - new BookPageInfo( - "building when they", - "required it, and", - "trading amongst", - "themselves if needed.", - " But over time,", - "something happened,", - "and they were forced", - "to withdraw from"), - new BookPageInfo( - "their society, until", - "today thou mayst", - "find individuals of", - "each species within", - "the dungeon, but", - "never again as a", - "civilization.", - " 'Tis also said that"), - new BookPageInfo( - "someday the three", - "tribes may return to", - "Despise, to once again", - "inhabit it together.", - " Until then, nothing", - "remains as token of", - "this save an oddly", - "intelligent skeleton,"), - new BookPageInfo( - "magically enchanted,", - "that doth speak when", - "questions are asked,", - "and from whom I", - "obtained these tales", - "one day, when I was", - "pursued by evil", - "monsters and fled"), - new BookPageInfo( - "into his skeletal arms.", - " Fortunately, I", - "escaped and lived to", - "write it all down!")); - - [Constructible] - public TaleOfThreeTribes() : base(Utility.Random(0xFEF, 2), false) - { - } - - public TaleOfThreeTribes(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class GuideToGuilds : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Beltran's Guide to Guilds", "Beltran", - new BookPageInfo( - " This reference", - "work is intended", - "merely to serve as", - "resource for those", - "curious as to the full", - "range of trades and", - "societies extant in", - "Britannia and nearby"), - new BookPageInfo( - "nations. For each", - "trade or guild, their", - "blazon is given.", - "", - " Armourer's Guild.", - "Gold bar above black", - "bar."), - new BookPageInfo( - " Association of", - "Warriors. Blue cross", - "on a red field.", - "", - " Barters' Guild.", - "Green and white", - "stripes, diagonal."), - new BookPageInfo( - " Blacksmith's Guild.", - "Gold alongside black.", - "", - " Federation of", - "Rogues and Beggars.", - "Red above black.", - "", - " Fighters and"), - new BookPageInfo( - "Footmen. Blue", - "horzontal bar on red", - "field.", - "", - " Guild of Archers.", - "A gold swath parting", - "red and blue."), - new BookPageInfo( - " Guild of", - "Armaments. Swath of", - "gold on black field,", - "gold accents.", - "", - " Guild of Assassins.", - "Black and red", - "quartered."), - new BookPageInfo( - "", - " Guild of Barbers.", - "Red and white", - "stripes.", - "", - " Guild of Cavalry and", - "Horse. Vertical blue", - "on a red field."), - new BookPageInfo( - "", - " Guild of", - "Fishermen. Blue and", - "white, quartered.", - "", - " Guild of Mages.", - "Purple and blue, in a", - "crossed pennant"), - new BookPageInfo( - "pattern.", - "", - " Guild of", - "Provisioners. White", - "bar above green bar.", - "", - " Guild of Sorcery. A", - "field divided"), - new BookPageInfo( - "diagonally in blue and", - "purple.", - "", - " Healers Guild. Gold", - "swath dividing green", - "from purple, gold", - "accents."), - new BookPageInfo( - " Lord British's", - "Healers of Virtue.", - "Golden ankh on dark", - "green.", - "", - " Masters of Illusion.", - "Blue and purple", - "checkers."), - new BookPageInfo( - "", - " Merchants' Guild.", - "Gold coins on green", - "field.", - "", - " Mining Cooperative.", - "A gold cross,", - "quartering blue and"), - new BookPageInfo( - "black.", - "", - " Order of Engineers.", - "Purple, gold, and blue", - "vertical.", - "", - " Sailors' Maritime", - "Association. A white"), - new BookPageInfo( - "bar centered on a blue", - "field.", - "", - " Seamen's Chapter.", - "Blue and white in a", - "crossed pennant", - "pattern."), - new BookPageInfo( - " Society of Cooks and", - "Chefs. White and red", - "diagonal fields", - "checker on green", - "field.", - "", - " Society of", - "Shipwrights. White"), - new BookPageInfo( - "diagonal above blue.", - "", - " Society of Thieves.", - "Black and red diagonal", - "stripes.", - "", - " Society of", - "Weaponsmakers. Gold"), - new BookPageInfo( - "diagonal above black.", - "", - " Tailor's Hall. Purple", - "above gold above red.", - "", - " The Bardic", - "Collegium. Purple and", - "red checkers on gold"), - new BookPageInfo( - "field.", - "", - " Traders' Guild.", - "White bar centered", - "down green field.")); - - [Constructible] - public GuideToGuilds() : base(Utility.Random(0xFEF, 2), false) - { - } - - public GuideToGuilds(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BirdsOfBritannia : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Birds of Britannia", "Thom the Heathen", - new BookPageInfo( - " The WREN is a", - "tiny insect-eating", - "bird with a loud voice.", - " The cheerful trills", - "of Wrens are", - "extraordinarily", - "varied and melodious.", - " The SWALLOW"), - new BookPageInfo( - "is easily recognized", - "by its forked tail.", - "Swallows catch", - "insects in flight, and", - "have squeaky,", - "twittering songs.", - " The WARBLER is", - "an exceptional singer,"), - new BookPageInfo( - "whose extensive", - "songs combine the", - "best qualities of", - "Wrens and Swallows.", - " The NUTHATCH", - "climbs down trees", - "head first, searching", - "for insects in the"), - new BookPageInfo( - "bark. It sings a", - "repetitive series of", - "notes with a nasal", - "tone quality.", - " The agile", - "CHICKADEE has a", - "buzzy", - "\"chick-a-dee-dee\""), - new BookPageInfo( - "call, from which its", - "name is derived. Its", - "song is a series of", - "whistled notes.", - " The THRUSH is a", - "brown bird with a", - "spotted breast, which", - "eats worms and"), - new BookPageInfo( - "snails, and has a", - "beautiful singing", - "voice. Thrushes use", - "a stone as an anvil to", - "smash the shells of", - "snails.", - " The little", - "NIGHTINGALE is"), - new BookPageInfo( - "also known for its", - "beautiful song, which", - "it sings even at night.", - " The STARLING", - "is a small dark bird", - "with a yellow bill and", - "a squeaky,", - "high-pitched song."), - new BookPageInfo( - "Starlings can mimic", - "the sounds of other", - "birds.", - " The SKYLARK", - "sings a series of", - "high-pitched", - "melodious trills in", - "flight."), - new BookPageInfo( - " The FINCH is a", - "small seed-eating bird", - "with a conical beak", - "and a musical,", - "warbling song.", - " The CROSSBILL", - "is a kind of Finch", - "with a strange"), - new BookPageInfo( - "crossed bill, which it", - "uses to extract seeds", - "from pine cones.", - " The CANARY is a", - "kind of Finch that is", - "often kept as a pet.", - "Miners would often", - "take Canaries"), - new BookPageInfo( - "underground with", - "them, to warn them", - "of the presence of", - "hazardous vapors in", - "the air.", - " The SPARROW", - "weaves a nest of", - "grass, and has an"), - new BookPageInfo( - "unmusical chirp for a", - "voice.", - " The TOWHEE is a", - "kind of Sparrow that", - "continually reminds", - "listeners to drink", - "their tea.", - " The SHRIKE is a"), - new BookPageInfo( - "gray bird with a", - "hooked bill. Shrikes", - "have the habit of", - "impaling their prey", - "on thorns.", - " The", - "WOODPECKER has a", - "pointed beak that is"), - new BookPageInfo( - "suitable for pecking at", - "wood to get at the", - "insects inside.", - " The", - "KINGFISHER dives", - "for fish, which it", - "catches with its long,", - "pointed beak."), - new BookPageInfo( - " The TERN", - "migrates over great", - "distances, from one", - "end of Britannia to", - "the other each year.", - "Terns dive from the", - "air to catch fish.", - " The PLOVER is a"), - new BookPageInfo( - "bird that distracts", - "predators by", - "pretending to have a", - "broken wing.", - " The LAPWING is", - "a kind of Plover that", - "has a long black crest.", - " The HAWK is a"), - new BookPageInfo( - "predator that feeds on", - "small birds, mice,", - "squirrels, and other", - "small animals. Small", - "hawks are known as", - "Kites.", - " The DOVE is a", - "seed-eating bird with"), - new BookPageInfo( - "a peaceful reputation.", - " Doves have a", - "low-pitched cooing", - "song.", - " The PARROT is a", - "brightly colored bird", - "with a hooked bill,", - "favored as a"), - new BookPageInfo( - "companion by pirates.", - " Parrots can be", - "taught to imitate the", - "human voice.", - " The CUCKOO is a", - "devious bird that lays", - "eggs in the nests of", - "Warblers and other"), - new BookPageInfo( - "small birds. Cuckoos", - "have the uncanny", - "ability to keep track", - "of time, singing once", - "at the beginning of", - "each hour.", - " The", - "ROADRUNNER is"), - new BookPageInfo( - "an unusual bird with", - "a long tail, which", - "runs swiftly along", - "the ground hunting", - "for lizards and", - "snakes.", - " The SWIFT is a", - "very agile bird that"), - new BookPageInfo( - "spends nearly its", - "entire life in the air.", - "With their mouths", - "wide open, Swifts", - "capture insects in", - "mid-flight.", - " The", - "HUMMINGBIRD is a"), - new BookPageInfo( - "cross between a", - "Swift and a Fairy.", - "These tiny, brightly", - "colored birds hover", - "magically near", - "flowers, and live on", - "the nectar they", - "provide."), - new BookPageInfo( - " The OWL is a", - "reputedly wise bird", - "that is active at night,", - "unlike most birds.", - "Owls have excellent", - "night vision and", - "low-pitched hooting", - "calls. Their wings"), - new BookPageInfo( - "are silent in flight.", - " The", - "GOATSUCKER is a", - "strange owl-like bird", - "that is thought to live", - "on the milk of goats.", - "These mysterious", - "birds make jarring"), - new BookPageInfo( - "sounds at night, for", - "which reason they", - "are also called", - "Nightjars.", - " The DUCK is a", - "bird that swims more", - "often than it flies,", - "and has a nasal voice"), - new BookPageInfo( - "that is described as a", - "\"quack\".", - " The SWAN is a", - "kind of long-necked", - "Duck that is all white.", - " Swans are usually", - "voiceless, but they", - "are said to have an"), - new BookPageInfo( - "extraordinarily", - "beautiful song.")); - - [Constructible] - public BirdsOfBritannia() : base(Utility.Random(0xFEF, 2), false) - { - } - - public BirdsOfBritannia(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BritannianFlora : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Britannian Flora: A Casual Guide", "Herbert the Lost", - new BookPageInfo( - " Oft 'pon rambling", - "through the woods", - "avoiding bears have I", - "spotted some plant", - "whose like I have", - "never seen before,", - "and concluded that I", - "was a blithering idiot"), - new BookPageInfo( - "for failing to notice it", - "in the past. Equally", - "as oft have I", - "concluded that I was a", - "worse idiot for not", - "running faster from", - "the bear.", - " While not all my"), - new BookPageInfo( - "readers may share", - "my proclivities for", - "tree-climbing, it", - "occurred to me that", - "mayhap mine", - "information might", - "serve some humble", - "purpose."), - new BookPageInfo( - " The two most", - "unique flowering", - "plants in the", - "Britannian", - "countryside are the", - "orfleur and the", - "whiteflower, also", - "called white horns."), - new BookPageInfo( - " The orfleur is", - "notable for its", - "massive orange-red", - "blossoms, which", - "dwarf marigolds like", - "the sun dwarfs your", - "common fireball spell.", - "The odor of said"), - new BookPageInfo( - "blooms is best", - "described as", - "peppermint-apple,", - "with a dash of garlic.", - "'Tis a popular potted", - "plant despite, or", - "perhaps because of,", - "its exotic nature."), - new BookPageInfo( - " Whiteflowers exude", - "a subtle fragrance not", - "unlike that of freshly", - "shaven wood mixed", - "with cool lemon ice.", - "Their tall stands", - "always droop with the", - "heavy weight of the"), - new BookPageInfo( - "massive blooms, oft", - "as large as a child's", - "head.", - " The flowers are so", - "large that one may", - "scoop out the pollen in", - "handfuls, and during", - "the spring season"), - new BookPageInfo( - "many a prank hath", - "been played by idle", - "boys 'pon their", - "sisters by dumping", - "said pollen into their", - "clothing drawers,", - "causing sneezes for", - "days."), - new BookPageInfo( - " The most", - "interesting native tree", - "to Britannia is the", - "spider tree. The", - "reason for its naming", - "is obscure, but may", - "have to do with the", - "twisted gray stalks"), - new BookPageInfo( - "from which the", - "spherical canopy", - "sprouts. 'Tis", - "something of a", - "misnomer to term", - "these \"trunks\" as", - "they are spindly and", - "flexible. Spider trees"), - new BookPageInfo( - "provide a fresh,", - "piney smell to a room", - "and are therefore", - "often potted.", - " In jungle climes,", - "one finds the blade", - "plant, whose sharp", - "leaves oft collect"), - new BookPageInfo( - "water for the thirsty", - "traveler, yet can", - "draw blood easily.", - " The deadliest plant,", - "if you can call a", - "fungus such, is the", - "Exploding Red Spotted", - "Toadstool. No pattern"), - new BookPageInfo( - "can be discerned to", - "its habitats save", - "malice, for merely", - "approaching results in", - "the cap exploding", - "with powder, noxious", - "gas, and tiny painful", - "pellets flying in all"), - new BookPageInfo( - "directions.", - "Unfortunately, 'tis", - "impossible to tell it", - "apart from the", - "Ordinary Red Spotted", - "Toadstool save through", - "experimentation.", - " Truly odd among the"), - new BookPageInfo( - "varied flora of", - "Britannia, however,", - "are those which bear", - "names clearly alien to", - "our tongue. Among", - "these I name the", - "Tuscany pine (for I", - "have never seen a"), - new BookPageInfo( - "region of this world", - "named Tuscany), the", - "o'hii tree, whose very", - "name sounds like", - "some tropical isle, and", - "the welsh poppy,", - "which while", - "different from the"), - new BookPageInfo( - "ordinary poppy in", - "color and appearance,", - "is prefaced with the", - "odd word \"welsh,\"", - "which as far as I", - "know means to forgo", - "paying a debt.")); - - [Constructible] - public BritannianFlora() : base(Utility.Random(0xFEF, 2), false) - { - } - - public BritannianFlora(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ChildrenTalesVol2 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Classic Children's Tales, Volume 2", "Guilhem, Editor", - new BookPageInfo( - "Clarke's Printery", - "is Honored to", - "Present Tales from", - "Ages Past!", - " Guilhem the", - "Scholar Shall End", - "EachVolume with", - "Staid Commentary."), - new BookPageInfo( - "", - "THE RHYME", - "Dance in the Star", - "Chamber", - "And Dance in the Pit", - "And Eat of your", - "Entrees", - "In the Glass House"), - new BookPageInfo( - "you Sit", - "", - "COMMENTARY", - " A common feeding", - "rhyme for little", - "babies, 'tis thought", - "that this little ditty is", - "part of the corpus of"), - new BookPageInfo( - "legendary tales", - "regarding the world", - "before Sosaria (see", - "the wonderful fables", - "of Fabio the Poor for", - "fictionalized versions", - "of these stories, also", - "available from this"), - new BookPageInfo( - "same publisher).", - " According to these", - "old tales, which", - "survive mostly in the", - "hills and remote", - "villages where Lord", - "British is as yet a", - "distant and mythical"), - new BookPageInfo( - "ruler, the gods of old", - "(a fanciful notion!)", - "met to discuss the", - "progress of creating", - "the world in mystical", - "rooms. A simple", - "analysis reveals these", - "rooms to be mere"), - new BookPageInfo( - "mythological", - "generalizations.", - " \"The Star", - "Chamber\" is clearly a", - "reference to the sky.", - "\"The Pit\" is certainly", - "an Underworld", - "analogous to the"), - new BookPageInfo( - "Snakehills of other", - "tales, and \"the Glass", - "House\" is no doubt the", - "vantage point from", - "which the gods", - "observed their", - "creation. All is simple", - "when seen from this"), - new BookPageInfo( - "perspective, leaving", - "only the mysterious", - "reference to dinners.", - "Oddly enough, the", - "rhyme is universally", - "used only for", - "midnight feedings,", - "never during the day."), - new BookPageInfo()); - - [Constructible] - public ChildrenTalesVol2() : base(Utility.Random(0xFEF, 2), false) - { - } - - public ChildrenTalesVol2(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TalesOfVesperVol1 : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Classic Tales of Vesper, Volume 1", "Clarke's Printery", - new BookPageInfo( - "'Tis an Honor to", - "present to Thee these", - "Tales collected from", - "Ages Past. In this", - "Inaugural Volume, we", - "present this Verse", - "oft Recited as a", - "Lullabye for sleepy"), - new BookPageInfo( - "Children.", - "", - "Preface", - "by Guilhem the", - "Scholar", - "", - " The meaning of this", - "verse has oft been"), - new BookPageInfo( - "discussed in halls of", - "scholarly sorts, for", - "its mysterious", - "singsongy melody is", - "oddly disturbing to", - "adult ears, though", - "children seem to find", - "it restful as they"), - new BookPageInfo( - "sleep. Perhaps it is", - "but the remnant of a", - "longer ballad once", - "extant, for there are", - "internal indications", - "that it once told a", - "longer story about", - "ill-fated lovers, and a"), - new BookPageInfo( - "magical experiment", - "gone awry. However,", - "poetic license and the", - "folk process has", - "distorted the words", - "until now the locale of", - "the tale is no more", - "than \"in the wind,\""), - new BookPageInfo( - "which while it serves", - "a pleasingly", - "metaphorical purpose,", - "fails to inform the", - "listener as to any real", - "locale!", - " Another possibility", - "is that this is some"), - new BookPageInfo( - "form of creation", - "myth explaining the", - "genesis of the various", - "humanoid creatures", - "that roam the lands of", - "Britannia. It does not", - "take a stretch of the", - "imagination to name"), - new BookPageInfo( - "the middle verse's", - "\"girl becomes tree\" as", - "a possible explanation", - "for the reaper, for in", - "the area surrounding", - "Minoc, reapers are", - "oft referred to among", - "the lumberjacking"), - new BookPageInfo( - "community as", - "\"widowmakers.\" That", - "these creatures are", - "of arcane origin is", - "assumed, but the", - "verse seems to imply", - "a long ago creator, and", - "uses the antique"), - new BookPageInfo( - "magickal terminology", - "of \"plaiting strands", - "of ether\" that is so", - "often found in", - "ancient texts. In", - "addition, the", - "reference to", - "\"snakehills\" may"), - new BookPageInfo( - "profitably be regarded", - "as a reference to an", - "actual location, such", - "as perhaps a local", - "term for the", - "Serpent's Spine.", - " A commoner", - "interpretation is that"), - new BookPageInfo( - "like many nursery", - "rhymes, it is a", - "simple explanation", - "for death, wherein", - "the wind snatches up", - "boys and girls and", - "when they sleep in", - "order to keep the"), - new BookPageInfo( - "balance of the world.", - "Notable tales have", - "been written for", - "children of", - "adventures in \"the", - "Snakehills,\" which", - "are presumed to be an", - "Afterworld whence"), - new BookPageInfo( - "the spirit lives on. A", - "grim lullabye, to be", - "sure, but no worse", - "than \"lest I die before", - "I wake\" surely.", - " In either case, 'tis", - "an old favorite,", - "herein printed for"), - new BookPageInfo( - "the first time for", - "thy enjoyment and", - "perusal!", - "", - "In the Wind where", - "the Balance", - "Is Whispered in", - "Hallways"), - new BookPageInfo( - "In the Wind where", - "the Magic", - "Flows All through the", - "Night", - "There live Mages and", - "Mages", - "With Robes made of", - "Whole Days"), - new BookPageInfo( - "Reading Books full of", - "Doings", - "Printed on Light", - "", - "In the Wind where", - "the Lovers", - "Are Crossed under", - "Shadows"), - new BookPageInfo( - "Where they Meet and", - "are Parted", - "By the Orders of", - "Fate", - "The Girl becomes", - "Tree,", - "And thus becomes", - "Widow"), - new BookPageInfo( - "The Boy becomes", - "Earth", - "And Wanders Till", - "Late", - "", - "In the Wind are the", - "Monsters", - "First Born First"), - new BookPageInfo( - "Created", - "When Chanting and", - "Ether", - "Mix Meddling and", - "Nigh", - "Fear going to Wind,", - "Fear Finding its", - "Plaitings,"), - new BookPageInfo( - "Go Not to the", - "Snakehills", - "Lest You Care to Die")); - - [Constructible] - public TalesOfVesperVol1() : base(Utility.Random(0xFEF, 2), false) - { - } - - public TalesOfVesperVol1(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class DeceitDungeonOfHorror : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Deceit: A Dungeon of Horrors", "Mercenary Justin", - new BookPageInfo( - " My employers have", - "oft taken me into this", - "den of hideous", - "creatures, and I", - "thought that it", - "behooved me to write", - "down what I know of", - "it, now that I am"), - new BookPageInfo( - "retired from the life", - "of an adventurer for", - "hire.", - " Deceit was once a", - "temple to forgotten", - "powers of old. It was", - "taken over by mages", - "who eventually were"), - new BookPageInfo( - "driven out by the", - "depredations of their", - "own evil lackeys.", - "However, many of", - "the magical traps and", - "devices that they", - "placed for their", - "defenses remain,"), - new BookPageInfo( - "particularly those the", - "wizards used to", - "protect their", - "treasures.", - " The dungeon is", - "mystically linked by", - "crystal balls placed in", - "different locations."), - new BookPageInfo( - "These magical orbs do", - "transmit speech, and", - "even have memory of", - "things that have been", - "said near them. No", - "doubt they once", - "served as a warning", - "system"), - new BookPageInfo( - " Be wary of a", - "brazier that giveth", - "warning when", - "approached; thou canst", - "use it to summon", - "deadly creatures.", - " There be a", - "tantalizing chest,"), - new BookPageInfo( - "undoubtedly full of", - "treasure, that cannot", - "be reached save past a", - "complex set of", - "pressure plates that", - "trigger deadly spikes.", - "As I never had", - "sufficient folk with"), - new BookPageInfo( - "me to unlock the", - "puzzle, I never", - "obtained the riches", - "that awaited there.", - " Do not investigate", - "iron maidens too", - "closely, for they may", - "suck you within"), - new BookPageInfo( - "them!", - " There is one place", - "where a deadly trap", - "can only be disarmed", - "by making use of a", - "statue that cleverly", - "conceals a lever.", - " Oft one encounters"), - new BookPageInfo( - "the deadly exploding", - "toadstool; the ones in", - "Deceit are deadlier", - "than most, as they", - "explode continually.", - "Likewise, the very", - "pools of water and", - "slime on the floor"), - new BookPageInfo( - "may poison thee.", - " The most magical", - "device in the dungeon", - "is a mystical bridge", - "that can only be", - "triggered by a level", - "embedded in the floor.", - "Be wary however,"), - new BookPageInfo( - "for the bridge thus", - "created doth burst", - "into flame when one", - "passeth across it!")); - - [Constructible] - public DeceitDungeonOfHorror() : base(Utility.Random(0xFEF, 2), false) - { - } - - public DeceitDungeonOfHorror(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class DimensionalTravel : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Dimensional Travel, a Monograph", "Dryus Doost, Mage", - new BookPageInfo( - " 'Tis beyond the", - "scope of this small", - "monograph to discuss", - "the details of", - "moongates, and the", - "manners in which", - "they distort the", - "fabric of reality in"), - new BookPageInfo( - "such a manner as to", - "permit the passage of", - "living flesh from", - "place to place, world to", - "world, or indeed from", - "dimension to", - "dimension.", - " Instead, allow me to"), - new BookPageInfo( - "bring thy attention,", - "Gentle Reader, to the", - "curious", - "characteristics that", - "are shared by certain", - "individuals within", - "our realm.", - " Long has it been"), - new BookPageInfo( - "known that the blue", - "moongate permits", - "travel from place to", - "place, and none have", - "trouble in taking this", - "path. Yet 'tis also", - "known, albeit only to a", - "few, that certain"), - new BookPageInfo( - "individuals are unable", - "to traverse the black", - "moongates that permit", - "travel from one", - "dimension to another.", - " The noted mage and", - "peer of our realm,", - "Lord Blackthorn, once"), - new BookPageInfo( - "told me in", - "conversation that his", - "arcane research had", - "indicated that the", - "issue was one of", - "conversation of ether.", - "To wit, given the", - "postulate that matter"), - new BookPageInfo( - "within a given", - "dimension may be but", - "a cross-section of", - "ethereal matter that", - "exists in multiple", - "dimensions, it", - "becomes obvious that", - "said ethereal"), - new BookPageInfo( - "structure cannot", - "enter dimensions in", - "which it is already", - "present.", - " Imagine an", - "individual (and the", - "Lord Blackthorn", - "hinted that he was"), - new BookPageInfo( - "one such) who exists", - "already in some form", - "in multiple", - "dimensions; said", - "individual would not", - "be able to cross into", - "another dimension", - "because HE IS"), - new BookPageInfo( - "ALREADY THERE.", - " The implications of", - "this are staggering,", - "and merit further", - "study. 'Tis well", - "known by theorists in", - "the field that", - "divisions in the"), - new BookPageInfo( - "ethereal structure of", - "an individual are", - "already implicit at the", - "temporal level, as", - "causality forces", - "divisions upon the", - "ether. This is the", - "basic operating"), - new BookPageInfo( - "mechanism by which", - "white moongates", - "function, permitting", - "time travel.", - " As time travel is", - "not barred by the", - "presence of an earlier", - "self (though"), - new BookPageInfo( - "encountering said", - "earlier self can prove", - "arcanely perilous),", - "there must be some", - "rigidity to the", - "ethereal structure", - "that bars multiple", - "instantiations of"), - new BookPageInfo( - "structures from", - "manifesting within", - "the same context.", - " If one regards time", - "and causal bifurcation", - "as a web, perhaps the", - "appropriate analogy", - "for dimensional"), - new BookPageInfo( - "matrices is that of a", - "crystalline structure,", - "with rigid linkages.", - "The only way in", - "which an individual", - "such as Lord", - "Blackthorn, who", - "exists in multiple"), - new BookPageInfo( - "dimensional matrices,", - "can cross worlds via", - "a black moongate,", - "would be for the", - "entire crystalline", - "structure of the", - "dimension to", - "perfectly match the"), - new BookPageInfo( - "ethereal resonance of", - "the destination", - "dimension.", - " The problem of why", - "certain individuals", - "are already replicated", - "in multiple crystalline", - "matrices is one that I"), - new BookPageInfo( - "fail to provide any", - "schema for in these", - "poor theories. It is", - "my fondest hope that", - "someday someone", - "shall conquer that", - "thorny problem and", - "enlighten the world.")); - - [Constructible] - public DimensionalTravel() : base(Utility.Random(0xFEF, 2), false) - { - } - - public DimensionalTravel(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class EthicalHedonism : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Ethical Hedonism: An Introduction", "Richard Garriott", - new BookPageInfo( - " Societies oft have", - "common codes of", - "conduct which it", - "expects all its people", - "to abide by. Now,", - "while 'tis true that", - "this can offer some", - "advantages, most of"), - new BookPageInfo( - "the codes I see today", - "around Britannia have", - "fatal flaws. Let us", - "examine them.", - " First, there is", - "Blackthorn's code of", - "Chaos or basically", - "Anarchy. Whereas"), - new BookPageInfo( - "this affords the", - "individual maximum", - "opportunity for", - "individuality and even", - "pursuit of personal", - "happiness, it does not", - "offer even basic", - "interpersonal conduct"), - new BookPageInfo( - "codes to prevent", - "people from killing", - "each other.", - " Without such basic", - "tenets, all the people", - "will need to spend a", - "significant portion of", - "their time and effort"), - new BookPageInfo( - "towards personal", - "protection and thus", - "less time towards", - "other more beneficial", - "pursuits.", - " Then there are the", - "moral codes that are", - "so popular today."), - new BookPageInfo( - "These codes are built", - "largely on historical", - "tradition rather than", - "current logic and thus", - "are also antiquated.", - "For example many", - "moral codes we see", - "today include"), - new BookPageInfo( - "statements about not", - "eating certain foods", - "that once were often", - "poisonous, but today", - "can be prepared", - "safely.", - " Many forbid contact", - "between young people"), - new BookPageInfo( - "of the opposite", - "gender, which can in", - "fact be hazardous; but", - "the codes often have", - "lost the context as to", - "why this is done,", - "instead merely calling", - "it amoral. In this day"), - new BookPageInfo( - "and age to call that a", - "necessary moral", - "would need a new", - "reasoning. I put forth", - "that tradition is not", - "enough", - " Then there are", - "Lord British's"), - new BookPageInfo( - "Virtues. It strikes me", - "that while a system", - "of virtues is", - "wonderful as a", - "touchstone to guide a", - "society to good", - "behavior, these are", - "but shades of the"), - new BookPageInfo( - "underlying truth as to", - "why one may wish to", - "live a life according to", - "certain rules of", - "conduct.", - " On the other hand,", - "clearly the Virtues", - "that I have heard"), - new BookPageInfo( - "Lord British speak of", - "are clearly positive", - "codes of conduct, far", - "better than the world", - "of anarchy that Lord", - "Blackthorn suggests.", - "Yet, are not these", - "Virtues still derived"), - new BookPageInfo( - "from a set of", - "principles which", - "though they sound", - "good, are difficult to", - "pin down as actual,", - "undeniable, rational", - "truths?", - " Worse yet though"), - new BookPageInfo( - "imagine a society", - "who's code of", - "conduct was based on", - "pure survival of the", - "strongest. While this", - "society may function", - "and even accomplish", - "much, it can be"), - new BookPageInfo( - "fairly argued that", - "personal happiness", - "would suffer greatly,", - "except for those at", - "the top. To rule that", - "out, however, we", - "must first believe", - "that people have a"), - new BookPageInfo( - "right to pursue", - "happiness.", - " I hope is a safe", - "assumption that all", - "beings wish to be", - "happy; I will broadly", - "describe this as", - "Hedonism. Yet, if all"), - new BookPageInfo( - "people did is live a", - "life of hedonism,", - "their hedonism might", - "be in conflict with", - "those near them, so I", - "will use the term", - "Ethics to describe", - "limits one might put"), - new BookPageInfo( - "on one's hedonistic", - "tendencies to allow", - "others to pursue their", - "happiness as well.", - " Allow me to give", - "this example: If one", - "were to live alone on a", - "desert isle, one could"), - new BookPageInfo( - "live a life of pure", - "hedonism, for no", - "action one might take", - "could interfere with", - "another's right to", - "pursue their", - "happiness. Poison the", - "lake if you like, there"), - new BookPageInfo( - "is no one to blame but", - "yourself!", - " Now suppose two", - "of you live on that", - "island. Thou dost not", - "want thy neighbor to", - "feel free to poison the", - "lake. Would it not be"), - new BookPageInfo( - "better to consider it", - "unethical to poison the", - "lake without first", - "thinking of those", - "whose pursuit of", - "happiness might be", - "affected by this", - "action?"), - new BookPageInfo( - " I put forth that it is", - "the fact that we as a", - "people choose to live in", - "groups known as a", - "society that causes us", - "to compromise our", - "pure hedonism with", - "logical ethics."), - new BookPageInfo( - "Likewise we accept", - "not being able to kill", - "others without", - "reason, because our", - "own pursuit of", - "happiness would be", - "greatly interfered", - "with if we feared"), - new BookPageInfo( - "others would do the", - "same to us. From", - "this basis of logic can", - "be formed the Tenets", - "of Ethical Hedonism.", - " For more on this", - "subject, see The", - "Tenants of Ethical"), - new BookPageInfo( - "Hedonism, by", - "Richard Garriott and", - "Herman Miller.")); - - [Constructible] - public EthicalHedonism() : base(Utility.Random(0xFEF, 2), false) - { - } - - public EthicalHedonism(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class MyStory : BaseBook - { - public static readonly BookContent Content = new BookContent( - "My Story", "Sherry the Mouse", - new BookPageInfo( - " 'Twas on a chill", - "night, when the moon", - "shone pasty-faced", - "above the horizon,", - "balanced on the", - "towers of Lord", - "British's castle, that", - "the events I am about"), - new BookPageInfo( - "to relate took place,", - "some years ago now. I", - "witnessed them all", - "from my tiny", - "mousehole.", - " Milords British and", - "Blackthorn are", - "accustomed to a game"), - new BookPageInfo( - "of chess 'pon an", - "evening, over which", - "they argue the issues", - "that affect the course", - "of the realm. Lord", - "Blackthorn was on his", - "way to Lord British's", - "chambers, and Lord"), - new BookPageInfo( - "British stood by a", - "window casement,", - "just having finished", - "setting the pieces", - "upon the board.", - " Suddenly the", - "shutters blew open,", - "and Lord British fell"), - new BookPageInfo( - "to the ground, one", - "hand shielding his", - "eyes. A chill wind", - "entered the room, and", - "it seemed a gash was", - "torn in the very air.", - "Through the gash I", - "could see stars and"), - new BookPageInfo( - "swirling clouds of", - "stellar dust, and a", - "coldness sucked all", - "the warmth from the", - "air. A terrible wind", - "tossed books and", - "blankets across the", - "room, and furniture"), - new BookPageInfo( - "toppled.", - " From within this", - "gash issued a great", - "voice, unlike any I", - "have ever heard. And", - "these are the words it", - "spoke (for I", - "memorized them most"), - new BookPageInfo( - "carefully):", - " \"Greetings, Lord", - "British. I am the", - "Time Lord, a being", - "from beyond your", - "dimension, as thou", - "art from a world", - "other than Sosaria. I"), - new BookPageInfo( - "am here to bring thee", - "warning. Dost thou", - "recall how long ago a", - "mysterious Stranger", - "came to Sosaria and", - "saved the world from", - "the evil wizard", - "Mondain? He"), - new BookPageInfo( - "shattered the Gem of", - "Immortality, within", - "which dwelled a", - "perfect likeness of", - "this world.\"", - " Lord British slowly", - "stood and faced the", - "hole in the air. \"I"), - new BookPageInfo( - "remember,\" he said.", - "\"Oft have I wished", - "that stranger would", - "return.\"", - " \"He hath returned,\"", - "spoke the voice. \"But", - "not to here. When the", - "Gem was shattered, a"), - new BookPageInfo( - "thousand shards were", - "scattered across the", - "dimensions, and in", - "each shard there is a", - "perfect likeness of", - "this world. And thou", - "dost live upon one", - "such shard, for thou"), - new BookPageInfo( - "art not of the true", - "world-thou art", - "merely a reflection.\"", - " Lord British looked", - "shaken by this, and I", - "did not know what to", - "think! Was I merely a", - "shadow of the real"), - new BookPageInfo( - "me, which lives still", - "somewhere else", - "across uncounted", - "universes?", - " \"My task is to heal", - "this shattered world,", - "Lord British,\" said", - "the voice. \"And I seek"), - new BookPageInfo( - "to enlist thee in my", - "cause. Be warned that", - "in this case, healing", - "carries with it a", - "terrible price.\"", - " Concern warred", - "with curiosity on my", - "liege's face, but ever"), - new BookPageInfo( - "one to shoulder a", - "burden, he", - "straightened and", - "faced the gash in the", - "air bravely. \"Name", - "thy price.\"", - " \"A shard of a", - "universe is a"), - new BookPageInfo( - "powerful thing, and a", - "universe shattered is", - "always in danger", - "from the powers of", - "darkness. Already", - "three shards were", - "turned to evil, and", - "sent to plague the"), - new BookPageInfo( - "original universe in", - "the form of", - "Shadowlords. Many", - "times have I brought", - "the Stranger back to", - "Britannia, to preserve", - "it from its own folly", - "or from outside"), - new BookPageInfo( - "dangers. Yet as long", - "as the world", - "remaineth in pieces,", - "it remaineth", - "vulnerable. We must", - "bring the shards into", - "harmony, so that they", - "resonate in such a"), - new BookPageInfo( - "manner that matches", - "the original universe.", - "Then the two", - "universes shall", - "merge, and be again", - "as one.\"", - " \"But if we are only", - "shadows...\" Lord"), - new BookPageInfo( - "British said", - "wonderingly.", - " The light from the", - "stars within the hole", - "seemed to dim.", - "\"Indeed, the", - "reflections shall", - "become one with the"), - new BookPageInfo( - "original. Thou wouldst", - "cease to be as thou", - "art, and become part", - "of the larger you.", - "Thou shalt not die;", - "however, uncounted", - "generations have", - "passed and borne"), - new BookPageInfo( - "children since that", - "day, and they have no", - "counterparts. They", - "would perish utterly.\"", - " Lord British sagged", - "in shock, realizing", - "the terrible price that", - "would be paid to heal"), - new BookPageInfo( - "the universe. \"All of", - "my people,\" he", - "breathed.", - " \"'Tis for the greater", - "good.\"", - " Lord British bowed", - "his head.", - " 'Twas then I saw"), - new BookPageInfo( - "the movement by the", - "door, half-hid by the", - "heavy red curtains.", - "Lord Blackthorn stood", - "there, concealed from", - "the rest of the room,", - "his face white. How", - "long had he been"), - new BookPageInfo( - "listening? I cannot", - "say, yet I suspect", - "that he had heard all", - "that the mysterious", - "voice had to say.", - " \"How then, shall I", - "aid thee?\" Lord", - "British said,"), - new BookPageInfo( - "weariness in his", - "voice.", - " \"Aid the nobilty that", - "resideth in the", - "human heart. Protect", - "the Virtues that so", - "recently came to thee", - "in thought late at"), - new BookPageInfo( - "night. They are the", - "Virtues of life, as", - "your counterpart", - "understands them to", - "be. For when thy", - "populace doth live and", - "breathe these Virtues,", - "shall it match the"), - new BookPageInfo( - "true Britannia, and", - "thy shard shall", - "rejoin with it.\"", - " The gash in the air", - "began to close, and", - "with it warmth stole", - "back into the room.", - " \"I was going to"), - new BookPageInfo( - "discuss my idea with", - "Blackthorn tonight,\"", - "Lord British", - "breathed. \"Have I no", - "thoughts that are my", - "own? Is my life but", - "a reflection of", - "another me?\""), - new BookPageInfo( - " \"Nay,\" said the", - "voice, smaller through", - "the diminished", - "opening. \"Say, rather,", - "that you are parallel,", - "for there is no", - "guarantee that thou", - "shalt accomplish what"), - new BookPageInfo( - "I have set thee to. I", - "speak tonight to a", - "thousand of thee, and", - "ask the same of all.", - "Perhaps not all shall", - "seek to aid me.\" And", - "with that, the gash", - "closed, and the voice"), - new BookPageInfo( - "was gone, leaving a", - "room that appeare", - "tossed by a mighty", - "storm.", - " \"Destroy the world", - "to save the universe,\"", - "Lord British said", - "bitterly. \"I do not"), - new BookPageInfo( - "wonder that some", - "may balk.\"", - " Lord Blackthorn", - "collected himself, and", - "strode into the room,", - "a decent mimicry of", - "surprise on his face.", - "\"My liege! What has"), - new BookPageInfo( - "happened here?\" he", - "exclaimed, feigning", - "dismay well. But not", - "well enough to fool", - "his old friend, whose", - "eyes narrowed at", - "seeing him there.", - " \"How much didst"), - new BookPageInfo( - "thou hear?\" demanded", - "Lord British.", - " \"Why, nothing,\"", - "managed Blackthorn,", - "his head ducked away", - "from his friend, as", - "he bent to retrieve the", - "fallen chess pieces. \"I"), - new BookPageInfo( - "merely came for our", - "game of chess.\"", - " Together they", - "righted the pedestal", - "table, and set the", - "pieces upon the black", - "and white squares.", - "\"Such simplicity to"), - new BookPageInfo( - "the game, Blackthorn,\"", - "mused Lord British,", - "idly brushing one", - "finger against the", - "board. \"Black and", - "white, each to its own", - "color, as if life were", - "so simple. What think"), - new BookPageInfo( - "you?\"", - " Blackthorn sat", - "heavily on a hassock", - "beside the chess table.", - "\"I think that matters", - "are never so simple,", - "my liege. And that I", - "would regret it deeply"), - new BookPageInfo( - "if someone, such as a", - "friend, saw it thus.\"", - " Lord British's eyes", - "met his. \"Yet", - "sometimes one must", - "sacrifice a pawn to", - "save a king.\"", - " Lord Blackthorn met"), - new BookPageInfo( - "his gaze squarely.", - "\"Even pawns have", - "lives and loves at", - "home, my lord.\" Then", - "he reached out for a", - "pawn, and firmly", - "moved it forward two", - "squares. \"Shall we"), - new BookPageInfo( - "play a game?\" he", - "asked.", - " The chess game that", - "night was a draw,", - "and they played", - "grimly.", - " And the next day,", - "Lord British gathered"), - new BookPageInfo( - "the nobles to proclaim", - "the idea of a new", - "system of Virtues,", - "and declared that", - "shrines should be", - "built across the land.", - " Lord Blackthorn", - "opposed it bitterly,"), - new BookPageInfo( - "and many thought", - "him strange for doing", - "so, for ever had he", - "been a noble and", - "upright man, and", - "ever had he and Lord", - "British been in", - "accord. Declaring that"), - new BookPageInfo( - "he should start his", - "own shrine, he", - "departed the castle", - "that day to live in a", - "tower in a lake on the", - "north side of the", - "city.", - " They are still the"), - new BookPageInfo( - "best of friends, yet a", - "sadness hangs", - "between them, as if", - "they were forced into", - "making choices that", - "appealed not to them.", - "And at night, when I", - "creep softly from one"), - new BookPageInfo( - "corner of my liege's", - "bedchamber to", - "another, I sometimes", - "see him take a pawn", - "from his night table,", - "and hold it in his", - "hand, and quietly", - "weep."), - new BookPageInfo( - " But I am but a", - "mouse, and none hear", - "me. This tale goes", - "unknown, save for", - "my writing these", - "enormous letters with", - "mine ink-stained tiny", - "paws for thee to"), - new BookPageInfo( - "read, for I fear", - "indeed for our world", - "and for our people in", - "these perilous times.")); - - [Constructible] - public MyStory() : base(Utility.Random(0xFEF, 2), false) - { - } - - public MyStory(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class DiversityOfOurLand : BaseBook - { - public static readonly BookContent Content = new BookContent( - "On the Diversity of Our Land", "Lord Blackthorn", - new BookPageInfo( - " While I deplore the", - "depredations of the", - "misguided and", - "belligerent races with", - "which we share our", - "fair Britannia, and", - "alongside the populace,", - "do mourn the needless"), - new BookPageInfo( - "deaths that their", - "raids cause, I cannot", - "countenance the policy", - "of wholesale slaughter", - "of these races that", - "seems to be the habit", - "of our soldierly", - "element."), - new BookPageInfo( - " Can we not regard", - "the ratmen, lizard", - "men, and orcs are", - "fellow intelligent", - "beings with whom we", - "share a planet? Why", - "must we slay them", - "on sight, rather than"), - new BookPageInfo( - "attempt to engage", - "them in dialogue?", - "There is no policy of", - "shooting at wisps", - "when they grace us", - "with their presence", - "(not that an arrow", - "could do much to"), - new BookPageInfo( - "pierce them!).", - " To view these", - "creatures as vermin", - "denies their obvious", - "intelligence, and we", - "cannot underestimate", - "the repercussions", - "that their slaughter"), - new BookPageInfo( - "may have. If we", - "regard the slaying of", - "fellow humans as a", - "crime, so must we", - "regard the killing of", - "an orc.", - " At the same time,", - "should a lizardman"), - new BookPageInfo( - "slay a human, should", - "we not forgive their", - "ignorance and", - "foolishness? Let us", - "not surrender the", - "high moral ground by", - "descending to", - "bestiality."), - new BookPageInfo( - " Now, I say not that", - "we should fail to", - "defend ourselves in", - "case of attack, for", - "even amongst humans", - "we see war, we see", - "famine, and we see", - "assault (though we"), - new BookPageInfo( - "owe a debt of", - "gratitude to our Lord", - "British for", - "preserving us from", - "the worst of these!).", - "However, incursions", - "such as the recent", - "tragedy which cost us"), - new BookPageInfo( - "the life of Japheth,", - "Guildmaster of", - "Trinsic's Paladins,", - "are folly.", - " I had met Japheth,", - "and like all paladins,", - "he burned with an", - "inner fire. Yet"), - new BookPageInfo( - "though I had the", - "utmost respect for", - "him, none could deny", - "the hatred that", - "flashed in his eyes at", - "the mere mention of", - "orcs. And thus he", - "carried his battle to"), - new BookPageInfo( - "the orc camps, and", - "died there, unable to", - "rise above his own", - "childhood experiences", - "depicted in his book,", - "\"The Burning of", - "Trinsic.\" 'Tis a", - "shame that even our"), - new BookPageInfo( - "mightiest men fall", - "prey to this", - "ignorance!", - " Are there not", - "legends of orcs", - "adopting human", - "children to raise as", - "their own? Tales of"), - new BookPageInfo( - "complex societies built", - "underground by races", - "we regard as bestial?", - " Let us not repeat", - "the mistake of", - "Japheth of the", - "Paladins, and let us", - "cease to persecute the"), - new BookPageInfo( - "nonhuman races,", - "before we discover", - "that we are harming", - "ourselves in the", - "process.")); - - [Constructible] - public DiversityOfOurLand() : base(Utility.Random(0xFEF, 2), false) - { - } - - public DiversityOfOurLand(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class QuestOfVirtues : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Quest of the Virtues", "Autenil", - new BookPageInfo( - "Volume 1", - "Chapter 1: Starting out", - "I begin my Quest in the", - "fine bank of Skara Brae.", - "My Quest is to travel by", - "foot to the eight shrines", - "of Britannia. Although", - "this may sound easy, it"), - new BookPageInfo( - "is hampered because I", - "have forsaken my abilities", - "and worldly possessions.", - "Instead, all that I have", - "to live by are a set of", - "plain clothes, a ship to", - "sail the seas and my", - "diary in which to record"), - new BookPageInfo( - "my adventures. Onward", - "Ho towards the Shrine of", - "Spirituality!", - "", - "Chapter 2: The Road to", - "Spirituality", - "", - "Since I have forsaken"), - new BookPageInfo( - "magic as a form of", - "travel, I must find a way", - "to the mainland from this", - "island town. Fortunately,", - "I was able to barter a", - "ride from the ferryman.", - "Upon reaching the", - "mainland, I followed the"), - new BookPageInfo( - "road until it turned", - "North, yet I must", - "continue Eastward. I", - "paused to listen to the", - "pleasant sounds of the", - "birds chirping and enjoyed", - "the peace away from the", - "busy life. Upon reaching"), - new BookPageInfo( - "the Hedge Maze I recalled", - "a story about the mage", - "Relvinian in the days of", - "old and turned South to", - "go around it. Possessing", - "no weapons and having", - "forsaken my training, I", - "heeded the sign that said,"), - new BookPageInfo( - "\"Enter and Become One", - "Among Ghosts.\" The River", - "forced me to turn South", - "and then continue East.", - "", - "Chapter 3: Spirituality", - "", - "Spirituality is the leader"), - new BookPageInfo( - "of the Virtues. It is the", - "meditation and", - "understanding of all other", - "Virtues. Without", - "Spirituality, one cannot", - "completely follow the", - "Virtues, for It is the", - "dedication and adherance"), - new BookPageInfo( - "to them.", - "", - "Chapter 4: Finding Honor", - "", - "My next visit will be to", - "the Shrine of Honor,", - "which lies a fair distance", - "to the South. There is a"), - new BookPageInfo( - "road to my East that I", - "will follow to the town", - "of Trinsic. I found a", - "warm room at the", - "Traveller's Inn, and woke", - "refreshed in the morning", - "to hear the sounds of", - "nature as I prepared to"), - new BookPageInfo( - "continue my journeys. I", - "thanked the kind innkeeper", - "and headed out of Trinsic", - "and South. I conversed", - "briefly with one lucky", - "enough to own a house in", - "the beautiful country and", - "he bade me good fortune"), - new BookPageInfo( - "on my travels. I used my", - "rusty blade to cut", - "through dense jungles", - "past ruins of a forgotten", - "realm, now inhabited only", - "by the Undead. Many a", - "mongbat did hamper my", - "journey, but finally I"), - new BookPageInfo( - "arrived at the Shrine of", - "Honor.", - "", - "Chapter 5: Honor", - "", - "Many link Honor and", - "battle, but it can be", - "used with any aspect of"), - new BookPageInfo( - "Life. Honor is to abide", - "by the rules, dishonor is", - "to cheat; to seek the", - "unfair advantage. I vowed", - "to always live life with", - "Honor.", - "", - "Chapter 6: Seeking Valor"), - new BookPageInfo( - "I must now embark on my", - "trusty small ship, the", - "Hollandia, to the South", - "and East, to a small", - "island where few have", - "travelled. I know not yet", - "what I will encounter at", - "sea, so I bid the Virtues"), - new BookPageInfo( - "grant me safety. So", - "begins my voyage. I", - "managed to sail unnoticed", - "past some water", - "elementals which took a", - "fair bit of navigation", - "from my tillerman.", - "However, I arrived without"), - new BookPageInfo( - "incident.", - "", - "Chapter 7: Valor", - "", - "The Shrine of Valor is", - "protected by many a", - "beast far too poisonous", - "and foul for myself to"), - new BookPageInfo( - "vanquish. One mush show", - "Valor to approach the", - "Shrine! Valor is often", - "shown in one's willingness", - "to fight what maybe a", - "losing battle upon which", - "he believes. It takes", - "Valor to stand your"), - new BookPageInfo( - "ground against the many", - "murderers and lawbreakers", - "in our lands. You may", - "lose, but you show Valor", - "in that you fight that", - "which must be opposed.", - "Fight the fights you", - "believe in, not just the"), - new BookPageInfo( - "fights you think you can", - "win.", - "", - "Chapter 8: The Voyage to", - "Humility", - "", - "My journey will continue", - "to the East towards the"), - new BookPageInfo( - "Shrine of Humility. I", - "launch my boat from the", - "West side of the Island", - "of Valor, where I made", - "my daring escape from", - "the many Giant Serpents", - "chasing me with their", - "poisonous venom and"), - new BookPageInfo( - "hissing tongues. Beautiful", - "blue waves washed over", - "the bow of the boat as", - "dolphins played, merrily", - "leading me on. The voyage", - "is long and the water", - "turbulent but finally land", - "was struck. Quickly I ran,"), - new BookPageInfo( - "eager to find my final", - "destination for the day.", - "", - "Chapter 9: Humility", - "", - "The Shrine of Humility is", - "surprisingly spartan; it is", - "merely a grove of stone"), - new BookPageInfo( - "pillars with an ankh and", - "the Humility stone at its", - "center. I would", - "characterize Humility as", - "this Quest; returning to", - "my roots in this world. I", - "have rejected my", - "possessions and my wealth"), - new BookPageInfo( - "in order to rely only", - "upon my cunning and", - "instincts. No longer have", - "I that which makes me", - "Glorious to others, but I", - "have only that which I", - "need to survive. I may no", - "longer rely upon myself, I"), - new BookPageInfo( - "must rely upon others", - "for my survival. My", - "journey to Humility has", - "only made me realize even", - "more how Blessed I have", - "been."), - new BookPageInfo( - "Chapter 10: Onward to", - "Honesty", - "", - "Now the journey will turn", - "South towards the Island", - "of Ice. However, my", - "voyages and excursions", - "into the jungle have made"), - new BookPageInfo( - "me quite tired, so I will", - "camp here beside a river", - "near the Shrine of", - "Humility for the night. I", - "awake the next morning", - "refreshed and invigorated,", - "but also under attack! A", - "Headless One has noticed"), - new BookPageInfo( - "my rise from slumber and", - "attacks viciously. My", - "trusty cleaver was in my", - "hand instantly, but my", - "lack of skill with the", - "weapon delayed the death", - "of the creature. I", - "launched the Hollandia and"), - new BookPageInfo( - "set sail for the Island of", - "Ice, seeking the Shrine of", - "Honesty. As I sail the", - "vast oceans, I find myself", - "desiring the company of", - "my fellow man. Hopefully I", - "shall meet some kind of", - "traveller with whom I may"), - new BookPageInfo( - "exchange a few words.", - "Shortly I was landing my", - "boat on the North end of", - "the Island of Ice. I", - "quickly made my way", - "through snow across the", - "frigid tundra while trying", - "to keep warm. The Shrine"), - new BookPageInfo( - "of Honesty bid me", - "welcome as I felth the", - "warmth radiate throughout", - "me.", - "", - "Chapter 11: Honesty", - "", - "Honesty is to uphold and"), - new BookPageInfo( - "defend the truth at all", - "times. Furthermore,", - "Honesty requires us to", - "be fair and true to our", - "fellow man; not taking", - "undue advantage. Honesty", - "is a Virtue often lacking", - "in today's world. It seems"), - new BookPageInfo( - "as though people are out", - "to gain wealth with no", - "regard to Honesty", - "towards other people.", - "Honesty is the foundation", - "upon which trust is built.", - "If the foundation", - "crumbles, everything built"), - new BookPageInfo( - "upon it must fall. The", - "cold environment which", - "houses the Shrine of", - "Honesty is a testament", - "to its value in today's", - "society. The symbolic cold", - "and secluded location", - "shows us that only the"), - new BookPageInfo( - "most dedicated to", - "pursuing Honesty will", - "achieve it. May we all be", - "Honest with our fellow", - "man and remember to", - "treat them how we would", - "like to be treated."), - new BookPageInfo( - "Chapter 12: The Path to", - "Sacrifice.", - "", - "I made my way to the", - "West side of the Island", - "of Ice. From there I", - "launch the Hollandia and", - "sail slightly to the North"), - new BookPageInfo( - "and West. I land my boat", - "just East of the Shrine", - "of Sacrifice, so my road", - "is West. Although I enjoy", - "the sea, I am happy to", - "be back on the mainland", - "for the final three", - "Shrines.")); - - [Constructible] - public QuestOfVirtues() : base(Utility.Random(0xFEF, 2), false) - { - } - - public QuestOfVirtues(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class RegardingLlamas : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Regarding Llamas", "Simon", - new BookPageInfo( - " Llamas are curious", - "beasts, shaggy and", - "sought after for their", - "wool, yet of a", - "curiously arrogant", - "disposition reflected", - "in their eyes. They", - "live in mountainous"), - new BookPageInfo( - "areas, though who", - "may have first tamed", - "them is lost in the", - "mists of history.", - " 'Tis a well-known", - "fact that llamas can", - "indeed be tamed, and", - "used as grazing"), - new BookPageInfo( - "animals, for their", - "meat, and of course", - "for their wool. Yet", - "'tis lesser known that", - "their ornery", - "disposition and", - "tendency to spit at", - "those they dislike"), - new BookPageInfo( - "makes them appealing", - "guard creatures as", - "well, though they", - "have little sound with", - "which to sound an", - "alarum.")); - - [Constructible] - public RegardingLlamas() : base(Utility.Random(0xFEF, 2), false) - { - } - - public RegardingLlamas(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TalkingToWisps : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Talking to Wisps", "Yorick ofMoonglow", - new BookPageInfo( - "This volume was", - "sponsored by", - "donations from Lord", - "Blackthorn, ever a", - "supporter of", - "understanding the", - "other sentient races", - "of Britannia."), - new BookPageInfo( - "-", - " Wisps are the most", - "intelligent of the", - "nonhuman races", - "inhabiting Britannia.", - "'Tis claimed by the", - "great sages that", - "someday we shall be"), - new BookPageInfo( - "able to converse with", - "them openly in our", - "native", - "tongue--indeed, we", - "must hope that wisps", - "learn our language,", - "for it is not possible", - "for humans to"), - new BookPageInfo( - "pronounce wispish!", - " The wispish", - "language seems to", - "only contain one", - "vowel, the letter Y.", - "However, the letters", - "W, C, M, and L seem", - "to be treated"), - new BookPageInfo( - "grammatically as", - "vowels, and in", - "addition every letter", - "is followed by what", - "sounds to the human", - "ear like a glottal stop.", - "It is possible that the", - "glottal stop is"), - new BookPageInfo( - "considered a vowel as", - "well.", - " Wisps do make use", - "of what sound to us", - "like pitch and", - "emphasis shifts", - "similar to", - "exclamations and"), - new BookPageInfo( - "questions.", - " The average word is", - "wispish seems to", - "consist of three", - "phonemes and three", - "glottal stops, plus", - "possibly a pitch shift.", - "It often sounds like a"), - new BookPageInfo( - "fire burning or", - "crackling. Some have", - "speculated that what", - "we are analyzing is", - "in fact nothing more", - "than the very air", - "crackling near the", - "wisp's glow, and not"), - new BookPageInfo( - "language, but this is", - "of course unlikely.")); - - [Constructible] - public TalkingToWisps() : base(Utility.Random(0xFEF, 2), false) - { - } - - public TalkingToWisps(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TamingDragons : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Taming Dragons", "Wyrd Beastmaster", - new BookPageInfo( - " I have not much to", - "tell about dragons. The", - "sole time I approached", - "one with an eye", - "towards taming it,", - "my initial attempts at", - "calming it met with", - "failure. It fixed a"), - new BookPageInfo( - "massive beady eye", - "upon me, and began", - "its slithering", - "approach, intending no", - "doubt to insert me", - "into its maw and bear", - "down with its teeth.", - " However, as I was"), - new BookPageInfo( - "engaged in what", - "remains to this day", - "the most terrifying", - "combat of my life,", - "the dragon suddenly", - "whirled as if in a", - "panic, ran a short", - "distance, took off into"), - new BookPageInfo( - "the air, then", - "transformed into a", - "whirlwind. Lastly, it", - "exploded, showering", - "gouts of black blood", - "and heaving, stinking", - "flesh upon miles of", - "countryside. The"), - new BookPageInfo( - "fireball was massive,", - "enough to light a city,", - "I should surmise.", - " I never did discover", - "the exact cause of", - "this strange behavior,", - "except to assume that", - "it was not typical for"), - new BookPageInfo( - "this reptilian species.", - "My best guesses", - "revolve around a", - "magical fracture in", - "the nature of reality,", - "which is far too", - "esoteric a territory", - "for one of my limited"), - new BookPageInfo( - "scholarship.", - " Hence my basic", - "advice to those who", - "seek to tame a", - "dragon-be sure that", - "thou hast mastered", - "the twin skills of", - "taming animals, and"), - new BookPageInfo( - "running away very", - "very fast.")); - - [Constructible] - public TamingDragons() : base(Utility.Random(0xFEF, 2), false) - { - } - - public TamingDragons(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BoldStranger : BaseBook - { - public static readonly BookContent Content = new BookContent( - "The Bold Stranger", "Old Fabio the Poor", - new BookPageInfo( - " In a time before", - "time, the Gods that Be", - "assembled a group of", - "artisans, craftsmen", - "and lore masters", - "(for, yes, even in", - "those days, art", - "existed) to create the"), - new BookPageInfo( - "world of Sosaria. To", - "this group, the gods", - "gave a tiny world,", - "Rytabul, in which to", - "test their works, to", - "see if they were of", - "the quality desired", - "for the true world in"), - new BookPageInfo( - "which they would be", - "placed. And though", - "the gods were tight", - "fisted with their gold,", - "this small crew", - "worked hard and long,", - "and were happy in", - "their tasks."), - new BookPageInfo( - " A small corner of", - "Rytabul had been", - "claimed by the artisan", - "Selrahc the Slow.", - "Though he was not", - "the fastest of the", - "assembled workers,", - "the gods smiled upon"), - new BookPageInfo( - "his work, even", - "presenting him with", - "a mystic talisman", - "proclaiming his work", - "the best among the", - "newer artisans. And", - "so Selrahc went about", - "his business, creating"), - new BookPageInfo( - "hundreds of designs", - "which would one day", - "add color and variety", - "to Sosaria.", - " One day a", - "stranger appeared to", - "Selrahc. His chest", - "was bare and he wore"), - new BookPageInfo( - "trousers of the", - "brightest green, and", - "wherever he went,", - "plants grew in his", - "footsteps. This", - "caused Selrahc no end", - "of trouble, the", - "stranger always"), - new BookPageInfo( - "looking over his", - "shoulder, and the", - "plants sprouting in", - "places Selrahc", - "required to ply his", - "art. And so Selrahc", - "approached the", - "stranger and bade"), - new BookPageInfo( - "him speak. But this", - "man in green", - "remained silent.", - "Selrahc pleaded with", - "the stranger to give", - "his name, and would", - "he please leave", - "Selrahc to his work."), - new BookPageInfo( - "But this mysterious", - "stranger remained", - "mute.", - " This angered", - "Selrahc mightily. Who", - "was this silent man,", - "interfering with", - "tasks the gods"), - new BookPageInfo( - "themselves had", - "entrusted to Selrahc?", - "In an attempt to", - "embarrass this", - "interloper, Selrahc", - "stole his green", - "trousers, leaving him", - "naked and open to"), - new BookPageInfo( - "comments about his", - "very manhood, and", - "still the stranger", - "would not speak,", - "would not leave this", - "tiny corner of", - "Rytabul.", - " Vexed to his very"), - new BookPageInfo( - "limits, Selrahc took", - "his war axe and", - "smote the silent one", - "mightily, again and", - "again, until the silent", - "stranger ran away,", - "having never said a", - "word, and never"), - new BookPageInfo( - "showed himself in", - "Rytabul again.", - " Thus endeth the", - "tale of the bold", - "stranger.")); - - [Constructible] - public BoldStranger() : base(Utility.Random(0xFEF, 2), false) - { - } - - public BoldStranger(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BurningOfTrinsic : BaseBook - { - public static readonly BookContent Content = new BookContent( - "The Burning of Trinsic", "Japheth of Trinsic", - new BookPageInfo( - " 'Twas a sight to", - "see, the sunlight", - "falling lightly on the", - "sandstone walls of", - "Trinsic 'pon a", - "morning in spring.", - " Children ran along", - "the parapets and"), - new BookPageInfo( - "walkways, their", - "laughter and running", - "providing music to the", - "daybreak, despite", - "their oft-ragged", - "clothing.", - " And I was one of", - "those young ones,"), - new BookPageInfo( - "letting my joy rise", - "up to the skies.", - " Little did we all", - "know of the darker", - "days that would lie", - "ahead, for we were", - "too young.", - " Had we but gained"), - new BookPageInfo( - "access to the quiet", - "councils held in the", - "Paladin tower as it", - "faced the sea,", - "councils lit by", - "candlelight and", - "worry, we would", - "have learned more of"), - new BookPageInfo( - "the fears of", - "imminent attack from", - "the forest, where", - "foul creatures born", - "of dank caves and", - "darkness were", - "marauding ever more", - "often into the lands"), - new BookPageInfo( - "around Trinsic's", - "moat.", - " But we were", - "children! The", - "parapets and the moat", - "were places to play,", - "not stout defenses,", - "and we gave no"), - new BookPageInfo( - "thought to the", - "necessities that must", - "have required their", - "construction.", - " We used to reach", - "the sheltered", - "orchards on the lee", - "side of the parapet"), - new BookPageInfo( - "walls, where the", - "southern river cut", - "through the city, by", - "swimming across the", - "water.", - " The rich folk who", - "lived in the great", - "manses there would"), - new BookPageInfo( - "shout from their", - "windows and shake", - "their fists, for we", - "would run through", - "their gardens and", - "tear up the delicate", - "foxgloves and", - "orfleurs with our"), - new BookPageInfo( - "unshod dirty feet.", - "Then we would dive", - "into the water and", - "splash merrily to the", - "fruit trees.", - " The southern", - "river lazily slid", - "under the an ungated"), - new BookPageInfo( - "arch in the mighty", - "wall, and we would", - "lay on the grassy", - "bank and watch it", - "gurgle by the lily", - "pads.", - " That spring that", - "pleasant spot became"), - new BookPageInfo( - "the doorway through", - "which our city of", - "Trinsic let in the", - "monstrous deformed", - "humanoids that", - "savaged us. I lay upon", - "that grassy bank and", - "watched them wade"), - new BookPageInfo( - "in, their coarse hair", - "wet and matted, algae", - "and muck festooning", - "their wild brows.", - " They caught sight", - "of a quicksilver girl", - "with bright blond hair", - "and lively eyes. Her"), - new BookPageInfo( - "name was Leyla, and", - "that spring I had held", - "fond dreams of", - "holding her hand and", - "sharing flavored ice", - "while dangling our", - "feet off the small", - "bridge by Smugglers"), - new BookPageInfo( - "Gate.", - " And I said nothing", - "when they caught", - "her, and did not cry", - "out when they", - "dragged her off", - "through that breach in", - "our wall, and did not"), - new BookPageInfo( - "warn the city when I", - "saw the helmeted orc", - "captains call the", - "charge upon the", - "mansions.", - " Blame me not, for", - "I was but a child, and", - "one who hid in the"), - new BookPageInfo( - "branches of the peach", - "trees, all a-tremble", - "whilst I watched the", - "smoke rise from Sean", - "the tailor's, and fire", - "lash out at the roof of", - "witchy Eleanor's", - "tavern."), - new BookPageInfo( - " To this day I have", - "had no word of", - "Leyla, and to this", - "day the smell of", - "burning wood can", - "conjure terrible", - "dreams. Yet with the", - "eyes of adulthood, 'tis"), - new BookPageInfo( - "possible to examine", - "the flaws in the", - "defense of Trinsic on", - "that fateful day, and", - "the reasons why our", - "walls are now", - "double-thick, and", - "why our buildings"), - new BookPageInfo( - "are now built as", - "fortresses within a", - "somber fortified city.", - " While I can look", - "out from the top of", - "the new Paladin", - "tower, and spy the", - "mighty white sails"), - new BookPageInfo( - "across the barrier", - "island, and can", - "descry the small", - "hollow south of the", - "city where gypsies", - "are wont to camp, I", - "can also envision the", - "city as it might be"), - new BookPageInfo( - "burning, and I bless", - "the bargain we made:", - "space for safety,", - "grace for sturdiness,", - "and wood for stone.", - " Whilst I live, I", - "shall not see Trinsic", - "burn, and no more"), - new BookPageInfo( - "cries of little girls", - "will haunt the sleep", - "of our fair citizens.", - " - Japheth, Paladin", - "Guildmaster of the", - "City of Trinsic")); - - [Constructible] - public BurningOfTrinsic() : base(Utility.Random(0xFEF, 2), false) - { - } - - public BurningOfTrinsic(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TheFight : BaseBook - { - public static readonly BookContent Content = new BookContent( - "The Fight", "M. de la Garza", - new BookPageInfo( - " A cold autumn's", - "morning with misty", - "fog secures a dozen", - "brave knights,", - "supplying hidden", - "shelter from prying", - "eyes deep in the", - "foothills of the"), - new BookPageInfo( - "vibrant valley.", - "Dragons soar like", - "fierce warriors,", - "circling around and", - "around, then roaring", - "like thunder, rallying", - "all that listen. The", - "dragons land swiftly"), - new BookPageInfo( - "beside the proud", - "warriors, bending", - "necks and extending", - "wings, lifting black", - "claws and allowing", - "valiant fighters to", - "ride forth and win an", - "arisen battle. The"), - new BookPageInfo( - "increasing winds", - "silence the sounds of", - "combat, and they", - "fight, standing their", - "ground like mothers", - "protecting their", - "childern, bright", - "armor flashing as"), - new BookPageInfo( - "each one falls.", - " A cold autumn's", - "evening with misty", - "fog cradles a dozen", - "battered corpses of", - "knights, creasing", - "them in currents of", - "winds that run deep"), - new BookPageInfo( - "in the foothills of the", - "desolate valley.", - "Dragons glide like", - "silent angels, circling", - "around and around,", - "then calling like", - "banshees; keening", - "cries of mourning."), - new BookPageInfo( - "The dragons land", - "heavily beside the", - "peaceful bodies,", - "bending necks and", - "extending wings,", - "lifting black claws", - "and allowing valiant", - "fighters to ride forth"), - new BookPageInfo( - "and win an arisen", - "battle. The increasing", - "winds silence the", - "sounds of combat, and", - "they fight, standing", - "their ground like", - "mothers protecting", - "their childern, bright"), - new BookPageInfo( - "armor flashing as", - "each one falls.", - " A cold autumn's", - "evening with misty", - "fog cradles a dozen", - "battered corpses of", - "knights, creasing", - "them in currents of"), - new BookPageInfo( - "winds that run deep", - "in the foothills of the", - "desolate valley.", - "Dragons glide like", - "silent angels, circling", - "around and around,", - "then calling like", - "banshees; keening"), - new BookPageInfo( - "cries of mourning.", - "The dragons land", - "heavily beside the", - "peaceful bodies,", - "bending necks and", - "extending wings,", - "lifting black claws", - "and pinching the"), - new BookPageInfo( - "sacred ground and", - "new eternal home.", - "The dying winds", - "whistle among the", - "dead in somber", - "procession, and they", - "lie, grasping weapons", - "to protect themselves"), - new BookPageInfo( - "like knights still in", - "battle, shattered", - "armor shining like", - "newly born stars.")); - - [Constructible] - public TheFight() : base(Utility.Random(0xFEF, 2), false) - { - } - - public TheFight(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class LifeOfATravellingMinstrel : BaseBook - { - public static readonly BookContent Content = new BookContent( - "The Life of a Travelling Minstrel", "Sarah of Yew", - new BookPageInfo( - " While 'tis true that", - "the musician who", - "seeketh only to make", - "sweet music for", - "herself and for", - "others needs little", - "more than some", - "talent, and stern"), - new BookPageInfo( - "practice at the chosen", - "instrument, those of", - "us who seek the open", - "road shall find indeed", - "that a greater skill is", - "required. Herein", - "discover those secrets", - "which I have learned"), - new BookPageInfo( - "over the years as an", - "itinerant performer...", - " Once I was in", - "Jhelom, and", - "accidentally angered a", - "bravo of some local", - "repute, whose blade", - "flickered all too"), - new BookPageInfo( - "eagerly near my", - "slender neck (for I", - "was young then).", - "After various threats", - "to \"ruin my pretty", - "face\" this bravo", - "grabbed my arm in a", - "most unseemly"), - new BookPageInfo( - "fashion and tossed", - "me into a barbaric", - "enclosure locally", - "entitled a dueling pit.", - "My plaintive cries", - "for help went", - "unheeded by the", - "guards, for the"), - new BookPageInfo( - "inhabitants of Jhelom", - "are eager indeed to", - "measure fighting", - "prowess at any time!", - " What saved me was", - "the ability to", - "improvise a melody", - "and tune that"), - new BookPageInfo( - "satirized the", - "proceedings, and", - "sufficiently angered", - "an onlooker to prod", - "him to coming to my", - "defense. Once that", - "fight was underway,", - "I was able to make"), - new BookPageInfo( - "good my escape.", - "Hence, I regard the", - "ability to incite fights", - "as indispensable to", - "the prudent bard.", - " Upon another", - "occasion, 'twas the", - "obverse side of that"), - new BookPageInfo( - "coin which saved me,", - "for I was being held", - "prisoner by a", - "particularly nasty", - "band of ruffians who", - "had seized me", - "unawares from the", - "road to Vesper."), - new BookPageInfo( - " They had worked", - "themselves into a", - "frenzy and were", - "ready to attack and I", - "fear, tear me limb", - "from limb, when I", - "began to sing", - "frantically, tapping"), - new BookPageInfo( - "my falled drum with", - "my tied up feet. The", - "melody developed into", - "a soothing one, and", - "the brigands slowly", - "calmed down to the", - "extent of apologizing,", - "and they let me go!"), - new BookPageInfo( - " A final example I", - "would pray you grant", - "your attention: once I", - "was lost upon a large", - "isle far to the east of", - "the mainland, well", - "beyond Serpent's", - "Hold, where lava"), - new BookPageInfo( - "made its sluggish", - "way across the", - "surface landscape.", - "And this accursed", - "land was filled with", - "vile beasts and", - "cunning dragons.", - " I was being pursued"), - new BookPageInfo( - "by one of said fell", - "dragons when I found", - "myself trapped. I", - "quickly skirted a", - "bubbling pool of molten", - "rock and attempted to", - "hide.", - " The dragon scented"), - new BookPageInfo( - "me and was", - "preparing to skirt the", - "pool, when I began to", - "play a lusty tune", - "upon my lute that", - "attracted its attention.", - "Mesmerized and", - "enticed by the"), - new BookPageInfo( - "melody, it stepped", - "directly toward sme,", - "and into the", - "lava-where its foot", - "was so burned that it", - "quickly hopped away,", - "undignified and", - "annoyed."), - new BookPageInfo( - " 'Tis my fond hope", - "that other travelling", - "minstrels shall learn", - "from my experiences", - "and apply themselves", - "to practicing these", - "skills in order to", - "preserve life and"), - new BookPageInfo( - "limb.")); - - [Constructible] - public LifeOfATravellingMinstrel() : base(Utility.Random(0xFEF, 2), false) - { - } - - public LifeOfATravellingMinstrel(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class MajorTradeAssociation : BaseBook - { - public static readonly BookContent Content = new BookContent( - "The Major Trade Associations", "Pieter of Vesper", - new BookPageInfo( - " There are ten major", - "trade associations that", - "operate legitimately in", - "the lands of Britannia", - "and among its trading", - "partners. Many of", - "these guilds are", - "divided into local or"), - new BookPageInfo( - "specialty subguilds,", - "who use the same", - "colors but vary the", - "heraldic pattern.", - " There are many", - "lesser trade", - "associations that have", - "closed membership,"), - new BookPageInfo( - "and one can join them", - "only by invitation.", - "Beltran's Guide to", - "Guilds is the", - "definitive text on the", - "full range of guilds", - "and other associations", - "in Britannia, and I"), - new BookPageInfo( - "heartily recommend", - "it.", - " In what follows I", - "have attempted to", - "bring together the", - "known information", - "regarding these", - "guilds. I offer thee"), - new BookPageInfo( - "the name, typical", - "membership, heraldic", - "colors, known", - "specialty", - "organizations within", - "the larger guild, and", - "any known", - "affiliations to other"), - new BookPageInfo( - "guilds, which often", - "occur because of", - "trade reasons.", - "", - "The Guild of Arcane", - "Arts", - "Members: alchemists", - "and wizards"), - new BookPageInfo( - "Colors: blue and purple", - "Subguilds: Illusionists,", - "Mages, Wizards", - "Affiliations: Healer's", - "Guild", - "", - "The Warrior's Guild", - "Members:"), - new BookPageInfo( - "mercenaries,", - "soldiery, guardsmen,", - "weapons masters,", - "paladins.", - "Colors: Blue and red", - "Subguilds: Cavalry,", - "Fighters, Warriors", - "Affiliations: League"), - new BookPageInfo( - "of Rangers", - "", - "League of Rangers", - "Members: rangers,", - "bowyers, animal", - "trainers", - "Colors: Red, gold and", - "blue"), - new BookPageInfo( - "", - "Guild of Healers", - "Members: healers", - "Colors: Green, gold,", - "and purple", - "Affiliations: Guild of", - "Arcane Arts"), - new BookPageInfo( - "Mining Cooperative", - "Members: miners", - "Colors: blue and black", - "checkers, with a gold", - "cross", - "Affiliations: Order of", - "Engineers"), - new BookPageInfo( - "Merchants'", - "Association", - "Members:", - "innkeepers,", - "tavernkeepers,", - "jewelers,", - "provisioners", - "Colors: gold coins on a"), - new BookPageInfo( - "green field for", - "Merchants. White", - "and green for the", - "others.", - "Subguilds: Barters,", - "Provisioners,", - "Traders, Merchants"), - new BookPageInfo( - "Order of Engineers", - "Members: tinkers and", - "engineers", - "Colors: Blue, gold, and", - "purple vertical bars", - "Affiliations: Mining", - "Cooperative"), - new BookPageInfo( - "Society of Clothiers", - "Members: tailors and", - "weavers", - "Colors: Purple, gold,", - "and red horizontal", - "bars", - "", - "Maritime Guild"), - new BookPageInfo( - "Members: fishermen,", - "sailors, mapmakers,", - "shipwrights", - "Colors: blue and white", - "Subguilds:", - "Fishermen, Sailors,", - "Shipwrights"), - new BookPageInfo( - "Bardic Collegium", - "Members: bards,", - "musicians,", - "storytellers, and other", - "performers", - "Colors: Purple, red", - "and gold checkerboard"), - new BookPageInfo( - "Society of Thieves", - "Members: beggars,", - "cutpurses, assassins,", - "and brigands", - "Colors: red and black", - "Subguilds: Rogues", - "(beggars), Assassins,", - "Thieves")); - - [Constructible] - public MajorTradeAssociation() : base(Utility.Random(0xFEF, 2), false) - { - } - - public MajorTradeAssociation(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class RankingsOfTrades : BaseBook - { - public static readonly BookContent Content = new BookContent( - "The Rankings of Trades", "Lord Higginbotham", - new BookPageInfo( - " Whilst 'tis true that", - "within each trade, one", - "finds differing titles", - "and accolades granted", - "to the members of a", - "given guild,", - "nonetheless for the", - "betterment of trade"), - new BookPageInfo( - "and understanding,", - "we must have a", - "commonality of", - "titling.", - " For those who may", - "find themselves", - "ignorant of the finer", - "distinctions between a"), - new BookPageInfo( - "three-knot member of", - "the Sailors' Maritime", - "Association and a", - "second thaumaturge,", - "this book shall serve", - "as a simple", - "introduction to the", - "common cant used"), - new BookPageInfo( - "when members of", - "differing guilds and", - "trade organizations", - "must trade with each", - "other and must", - "establish relative", - "credentials.", - " Neophyte"), - new BookPageInfo( - "Has shown interest", - "in learning the craft", - "and some meager", - "talent.", - " Novice", - "Is practicing basic", - "skills but has not been", - "admitted to full"), - new BookPageInfo( - "standing.", - " Apprentice", - "A student of the", - "discipline.", - " Journeyman", - "Warranted to practice", - "the discipline under", - "the eyes of a tutor."), - new BookPageInfo( - " Expert", - "A full member of the", - "guild.", - " Adept", - "A member of the", - "guild qualified to", - "teach others.", - " Master"), - new BookPageInfo( - "Acknowledged as", - "qualified to lead a hall", - "or business.", - " Grandmaster", - "Rarely a permanent", - "title, granted in", - "common parlance to", - "those who have"), - new BookPageInfo( - "shown extreme", - "mastery of their", - "craft recently.")); - - [Constructible] - public RankingsOfTrades() : base(Utility.Random(0xFEF, 2), false) - { - } - - public RankingsOfTrades(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class WildGirlOfTheForest : BaseBook - { - public static readonly BookContent Content = new BookContent( - "The Wild Girl of the Forest", "Horace the Trader", - new BookPageInfo( - " Her name was", - "Leyla, she said, and", - "her hair was braided", - "wild with creepers", - "and thorns. I", - "marveled that they", - "did not hurt her, but", - "when I asked, she but"), - new BookPageInfo( - "shrugged and let her", - "eyes roam once more", - "across the woods.", - "Though I had my", - "hands securely", - "fastened by her", - "ropes, I itched to", - "reach out and comb"), - new BookPageInfo( - "that unruly golden", - "mane, dirtied and", - "leaf-ridden.", - " Her provenance,", - "she told me over", - "nights illumined by", - "campfires, was once", - "the city of Trinsic."), - new BookPageInfo( - "She claimed to have", - "been kidnapped and", - "raised by orcs, which", - "I judged an unlikely", - "tale, for all know orcs", - "delight in eating the", - "meat of honest folk.", - "When I told her this,"), - new BookPageInfo( - "she laughed a fey", - "laugh, and gaily", - "admitted that honest", - "she was not, for oft", - "had she stolen folk", - "away from caravans", - "to loot their", - "possessions from an"), - new BookPageInfo( - "unconscious body!", - " At this, I began to", - "fear for my life, and", - "her smile seemed full", - "of teeth sharper than", - "a human ought to", - "have, for the tale of", - "orcish raising had"), - new BookPageInfo( - "struck fear into the", - "marrow of my bones.", - "\"Wilt thou eat me?\" I", - "asked, a-tremble,", - "fearing the answer.", - " And she cocked", - "her head at me, like a", - "wild animal facing a"), - new BookPageInfo( - "word that it dost not", - "understand, and the", - "fixity in her eyes", - "was a glimpse into", - "the deeper reaches of", - "the Abyss. But she", - "finally grunted, and", - "said, \"Nay,\" in a"), - new BookPageInfo( - "voice that recalled to", - "me a child. \"Nay,\"", - "she said, \"for thou", - "dost remind me of a", - "boy I knew once,", - "when I was a girl", - "who played in a city", - "of great sandstone"), - new BookPageInfo( - "walls, before I was", - "taken. He had sandy", - "hair like thee, and I", - "dreamt as a child of", - "holding his hand and", - "sharing flavored ice.", - "His name was", - "Japheth.\""), - new BookPageInfo( - " The next morning", - "she let me go,", - "stripped of my pouch", - "and clothes, and bade", - "me run through the", - "woods, and to fear", - "recapture, for surely", - "her heart would not"), - new BookPageInfo( - "soften again. 'Twas a", - "fearful run, and I", - "came to the road to", - "Yew with welts and", - "scratches run", - "rampant crost my", - "skin, but I did not see", - "her again."), - new BookPageInfo( - " Oft have I", - "wondered of the boy", - "named Japheth, and", - "whether he", - "remembers a girl who", - "lived in sandstone", - "walls. The only", - "Japheth I know is the"), - new BookPageInfo( - "Guildmaster of", - "Paladins who died", - "last year warring", - "amidst the orcs, and", - "though he had indeed", - "sandy hair, I cannot", - "picture him side by", - "side with a feral girl"), - new BookPageInfo( - "whose tongue has", - "tasted of human", - "flesh.", - " Yet the paths of", - "fate are strange", - "indeed, and I suppose", - "'tis possible that this", - "paladin died"), - new BookPageInfo( - "defending his", - "remembered lady's", - "honor, unknowingly", - "struck down by the", - "orc that she called", - "father.")); - - [Constructible] - public WildGirlOfTheForest() : base(Utility.Random(0xFEF, 2), false) - { - } - - public WildGirlOfTheForest(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TreatiseOnAlchemy : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Treatise on Alchemy", "Felicia Hierophant", - new BookPageInfo( - " The alchemical", - "arts are notable for", - "their deceptive", - "simplicity. 'Tis true", - "that to our best", - "knowledge currently,", - "there are but eight", - "valid potions that can"), - new BookPageInfo( - "be made (though I", - "emphasize that new", - "discoveries may", - "always await).", - "However, the delicate", - "balance of confecting", - "the potions is", - "difficult indeed, and"), - new BookPageInfo( - "requires great skill.", - " To give thee an", - "example of the", - "simpler potions that", - "can be created by", - "those well-versed in", - "the subtleties of", - "alchemy:"), - new BookPageInfo( - " Black pearl, that", - "rare substance that is", - "oft found lying", - "unannounced upon the", - "surface of the", - "ground, when", - "properly crushed", - "with mortar and"), - new BookPageInfo( - "pestle, can yield a", - "fine powder. Said", - "powder in the proper", - "proportions when", - "mixed via the", - "alchemical arts can", - "yield a wonderfully", - "refreshing drink."), - new BookPageInfo( - " The revolting blood", - "moss so gingerly", - "scraped off of", - "windowsills by", - "fastidious housewives", - "is but a tiny cousin to", - "the wilder version,", - "which when properly"), - new BookPageInfo( - "prepared yields a", - "magical liquid that for", - "a time can make the", - "imbiber a more agile", - "and dextrous", - "individual.", - " However, beware", - "of the deadly"), - new BookPageInfo( - "nightshade, for it", - "yields a deceptively", - "sweet-tasting poison", - "that can prove highly", - "fatal to the drinker,", - "and in fact is also", - "used by assassins to", - "coat their blades."), - new BookPageInfo( - "Fortunately, this", - "latter art of poisoning", - "is little known!", - " There is much to", - "reward the student of", - "alchemy, indeed. The", - "rumours of longtime", - "alchemists losing"), - new BookPageInfo( - "their hair and", - "acquiring an", - "unhealthy pallor, not", - "to mention unsightly", - "blotches upon their", - "once-fair skin, are", - "unhappily, true. Yet", - "the joys of the mind"), - new BookPageInfo( - "make up for the", - "complete loss of", - "interest that others", - "may have in thee as", - "an object of", - "courtship, and I have", - "never regretted that", - "choice. Honestly,"), - new BookPageInfo( - "truly. Not once.")); - - [Constructible] - public TreatiseOnAlchemy() : base(Utility.Random(0xFEF, 2), false) - { - } - - public TreatiseOnAlchemy(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class VirtueBook : BaseBook - { - public static readonly BookContent Content = new BookContent( - "Virtue", "Lord British", - new BookPageInfo( - " Within this world", - "live people with many", - "different ideals, and", - "this is good. Yet what", - "is it within the people", - "of our land that sorts", - "out the good from the", - "evil, the cherished"), - new BookPageInfo( - "form the disdained?", - "Virtue, I say it is,", - "and virtue is the", - "logical outcome of a", - "people who wish to", - "live together in a", - "bonded society.", - " For without Virtues"), - new BookPageInfo( - "as a code of conduct", - "which people maintain", - "in their relations", - "with each other, the", - "fabric of that society", - "will become weakened.", - "For a society to grow", - "and prosper for all,"), - new BookPageInfo( - "each must grant the", - "others a common base", - "of consideration.", - " I call this base the", - "Virtues. For though", - "one person might gain", - "personal advantage by", - "breaching such a"), - new BookPageInfo( - "code, the society as a", - "whole would suffer.", - " There are three", - "Principle Virtues that", - "should guide people to", - "enlightenment. These", - "are: Truth, Love and", - "Courage. From all the"), - new BookPageInfo( - "infinite reasons one", - "may have to found an", - "action, such as greed", - "or charity, envy or", - "pity, the three", - "Principle Virtues", - "stand out.", - " In fact all other"), - new BookPageInfo( - "virtues and vices can", - "be show to be built", - "from these principles", - "and their opposite", - "corruption's of", - "Falsehood, Hatred and", - "Cowardice. These", - "three Principles can"), - new BookPageInfo( - "be combined in eight", - "ways, which I will", - "call the eight virtues.", - "The eight virtues", - "which we should", - "build our society upon", - "follow.", - " Truth alone becomes"), - new BookPageInfo( - "Honesty, for without", - "honesty between our", - "people, how can we", - "build the trust which", - "is needed to", - "maximize our", - "successes.", - " Love alone becomes"), - new BookPageInfo( - "compassion, for at", - "some time or another", - "all of us will need the", - "compassion of others,", - "and most likely", - "compassion will be", - "shown to those who", - "have shown it."), - new BookPageInfo( - " Courage alone", - "becomes Valor,", - "without valor our", - "people will never", - "reach into the", - "unknown or to the", - "risky and will never", - "achieve."), - new BookPageInfo( - " Truth tempered by", - "Love give us Justice,", - "for only in a loving", - "search for the truth", - "can one dispense fair", - "Justice, rather than", - "create a cold and", - "callous people."), - new BookPageInfo( - " Love and Courage", - "give us Sacrifice, for", - "a people who love each", - "other will be willing", - "to make personal", - "sacrifices to help", - "other in need, which", - "one day, may be"), - new BookPageInfo( - "needed in return.", - " Courage and Truth", - "give us Honor, great", - "knights know this", - "well, that chivalric", - "honor can be found", - "by adhering to this", - "code of conduct."), - new BookPageInfo( - " Combining Truth,", - "Love and Courage", - "suggest the virtue of", - "Spirituality the virtue", - "that causes one to be", - "introspective, to", - "wonder about ones", - "place in this world"), - new BookPageInfo( - "and whether one's", - "deeds will be recorded", - "as a gift to the world", - "or a plague.", - " The final Virtue is", - "more complicated. For", - "the eighth combination", - "is that devoid of"), - new BookPageInfo( - "Truth, Love or", - "Courage which can", - "only exist in a state", - "of great Pride, which", - "of course is not a", - "virtue at all. Perhaps", - "this trick of fate is a", - "test to see if one can"), - new BookPageInfo( - "realize that the true", - "virtue is that of", - "Humility. I feel that", - "the people of", - "Magincia fail to see", - "this to such a degree", - "that I would not be", - "surprised if some ill"), - new BookPageInfo( - "fate awaited their", - "future.", - " Thus from the", - "infinite possibilities", - "which spawned the", - "Three Principles of", - "Truth, Love and", - "Courage, come the"), - new BookPageInfo( - "Eight Virtues of", - "Honesty, Compassion,", - "Valor, Justice,", - "Sacrifice, Honor,", - "Spirituality, and", - "Humility.")); - - [Constructible] - public VirtueBook() : base(Utility.Random(0xFEF, 2), false) - { - } - - public VirtueBook(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class GrammarOfOrcish : BaseBook + { + public static readonly BookContent Content = new BookContent( + "A Grammar of Orcish", + "Yorick of Yew", + new BookPageInfo( + "This volume, and", + "others in the series,", + "are sponsored by", + "donations from Lord", + "Blackthorn, ever a", + "supporter of", + "understanding the", + "other sentient races" + ), + new BookPageInfo( + "of Britannia.", + "-", + "", + " The Orcish tongue", + "may fall unpleasingly", + "'pon the ear, yet it", + "has within it a", + "complex grammar oft" + ), + new BookPageInfo( + "misunderstood by", + "those who merely", + "hear the few broken", + "words of English our", + "orcish brothers", + "manage without", + "education.", + " These are the basic" + ), + new BookPageInfo( + "rules of orcish:", + " Orcish has five", + "tenses: present, past,", + "future imperfect,", + "present interjectional,", + "and prehensile.", + " Examples: gugroflu,", + "gugrofloog, gugrobo," + ), + new BookPageInfo( + "gugroglu!, gugrogug.", + " All transitive verbs", + "in the prehensile", + "tense end in \"ug.\"", + " Examples:", + "urgleighug,", + "biggugdaghgug,", + "curdakalmug." + ), + new BookPageInfo( + " All present", + "interjectional", + "conjugations start", + "with the letter G", + "unless the contain the", + "third declensive", + "accent of the letter U.", + " Examples:" + ), + new BookPageInfo( + "ghothudunglug, but not", + "azhbuugub.", + " The past tense can", + "only refer to events", + "since the last meal,", + "but the prehensile", + "tense can refer to", + "any event within" + ), + new BookPageInfo( + "reach.", + " The present tense", + "is conjugated like the", + "future imperfect", + "tense, when the", + "interrogative mode is", + "used by pitching the", + "sound a quarter-tone" + ), + new BookPageInfo( + "higher.", + "Orcish hath no", + "concept of person, as", + "in first person, third", + "person, I, we, etc.", + " Orcish grammar", + "relies upon the three", + "cardinal rules of" + ), + new BookPageInfo( + "accretion, prefixing,", + "and agglutination, in", + "addition to pitch. In", + "the former, phonemes", + "combine into larger", + "words which may", + "contain full phrasal", + "significance. In the" + ), + new BookPageInfo( + "second, prefixing", + "specific phonetic", + "sounds changes the", + "subject of the", + "sentence into object,", + "interrogative,", + "addressed individual,", + "or dinner." + ), + new BookPageInfo( + " Agglutination occurs", + "whenever four of the", + "same letter are", + "present in a word, in", + "which case, any two", + "of them may be", + "removed or slurred.", + " Pitch changes the" + ), + new BookPageInfo( + "phoneme value of", + "individual syllables,", + "thus completely", + "altering what a word", + "may mean. The", + "classic example is", + "\"Aktgluthugrot", + "bigglogubuu" + ), + new BookPageInfo( + "dargilgaglug lublublub\"", + "which can mean \"You", + "are such a pretty", + "girl,\" \"My mother ate", + "your primroses,\" or", + "\"Jellyfish nose paints", + "alms potato,\"", + "depending on pitch." + ), + new BookPageInfo( + " Orcish poetry often", + "relies upon repeating", + "the same phrase in", + "multiple pitches, even", + "changing pitch", + "midword. None of", + "this great art is", + "translatable." + ), + new BookPageInfo( + " The orcish language", + "uses the following", + "vowels: ab, ad, ag, akt,", + "at, augh, auh, azh, e,", + "i, o, oo, u, uu. The", + "vowel sound a is not", + "recognized as a vowel", + "and does not exist in" + ), + new BookPageInfo( + "their alphabet.", + "The orcish alphabet is", + "best learned using the", + "classic rhyme", + "repeated at 23", + "different pitches:", + " Lugnog ghu blat", + "suggaroglug," + ), + new BookPageInfo( + "Gaghbuu dakdar ab", + "highugbo,", + " Gothnogbuim ad", + "gilgubbugbuilug", + "Bilgeaugh thurggulg", + "stuiggro!", + "", + "A translation of the" + ), + new BookPageInfo( + "first pitch:", + "Eat food, the first", + "letter is ab,", + "Kill people, next letter", + "is ad,", + "I forget the rest", + "But augh is in there", + "somewhere!" + ), + new BookPageInfo( + "", + " What follows is a", + "complete phonetic", + "library of the orcish", + "language:", + "ab, ad, ag, akt, alm,", + "at, augh, auh, azh,", + "ba, ba, bag, bar, baz," + ), + new BookPageInfo( + "bid, bilge, bo, bog, bog,", + "brui, bu, buad, bug,", + "bug, buil, buim, bum,", + "buo, buor, buu, ca,", + "car, clog, cro, cuk,", + "cur, da, dagh, dagh,", + "dak, dar, deak, der,", + "dil, dit, dor, dre, dri," + ), + new BookPageInfo( + "dru, du, dud, duf,", + "dug, dug, duh, dun,", + "eag, eg, egg, eichel,", + "ek, ep, ewk, faugh,", + "fid, flu, fog, foo,", + "foz, fruk, fu, fub,", + "fud, fun, fup, fur,", + "gaa, gag, gagh, gan," + ), + new BookPageInfo( + "gar, gh, gha, ghat,", + "ghed, ghig, gho, ghu,", + "gig, gil, gka, glu, glu,", + "glug, gna, gno, gnu,", + "gol, gom, goth, grunt,", + "grut, gu, gub, gub,", + "gug, gug, gugh, guk,", + "guk," + ) + ); + + [Constructible] + public GrammarOfOrcish() : base(Utility.Random(0xFEF, 2), false) + { + } + + public GrammarOfOrcish(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class CallToAnarchy : BaseBook + { + public static readonly BookContent Content = new BookContent( + "A Politic Call to Anarchy", + "Lord Blackthorn", + new BookPageInfo( + " Let it never be said", + "that I have aught as", + "quarrel with my liege", + "Lord British, for", + "indeed we be of the", + "best of friends,", + "sharing amicable", + "games of chess 'pon a" + ), + new BookPageInfo( + "winter's night, and", + "talking at length into", + "the wee hours of the", + "issues that affect the", + "realm of Britannia.", + " Yet true friendship", + "doth not prevent true", + "philosophical" + ), + new BookPageInfo( + "disagreement either.", + "While I view with", + "approval my lord's", + "affection for his", + "carefully crafted", + "philosophy of the", + "Eight Virtues,", + "wherein moral" + ), + new BookPageInfo( + "behavior is", + "encouraged in the", + "populace, I view with", + "less approval the", + "expenditure of public", + "funds upon the", + "construction of", + "\"shrines\" to said" + ), + new BookPageInfo( + "ideals.", + " The issue is not one", + "of funds, however,", + "but a disagreement", + "most intellectual over", + "the proper way of", + "humankind in an", + "ethical sense. Surely" + ), + new BookPageInfo( + "freedom of decision", + "must be regarded as", + "paramount in any", + "such moral decision?", + "Though none fail to", + "censure the", + "murderer, a subtler", + "question arises when" + ), + new BookPageInfo( + "we ask if his", + "behavior would be", + "ethical if he were", + "forced to it.", + " I say to thee, the", + "reader, quite flatly,", + "that no ethical system", + "shall have sway over" + ), + new BookPageInfo( + "me unless it", + "convinceth me, for", + "that freely made", + "choice is to me the", + "sign that the system", + "hath validity.", + " Whereas the system", + "of \"Virtues\" that my" + ), + new BookPageInfo( + "liege espouses is", + "indeed a compilation", + "of commonly approved", + "virtues, I approve of", + "it. Where it seeks to", + "control the populace", + "and restrict their", + "diversity and their" + ), + new BookPageInfo( + "range of behaviors, I", + "quarrel with it. And", + "thus do I issue this", + "politic call to anarchy,", + "whilst humbly", + "begging forgiveness", + "of Lord British for", + "my impertinence:" + ), + new BookPageInfo( + " Celebrate thy", + "differences. Take", + "thy actions according", + "to thy own lights.", + "Question from what", + "source a law, a rule,", + "a judge, and a virtue", + "may arise. 'Twere" + ), + new BookPageInfo( + "possible (though I", + "suggest it not", + "seriously) that a", + "daemon planted the", + "seed of these", + "\"Virtues\" in my Lord", + "British's mind; 'twere", + "possible that the" + ), + new BookPageInfo( + "Shrines were but a", + "plan to destroy this", + "world. Thou canst not", + "know unless thou", + "questioneth, doubteth,", + "and in the end,", + "unless thou relyest", + "upon THYSELF and" + ), + new BookPageInfo( + "thy judgement.", + " I offer these words", + "as mere philosophical", + "musings for those", + "who seek", + "enlightenment, for", + "'tis the issue that", + "hath occupied mine" + ), + new BookPageInfo( + "interest and that of", + "Lord British for", + "some time now." + ) + ); + + [Constructible] + public CallToAnarchy() : base(Utility.Random(0xFEF, 2), false) + { + } + + public CallToAnarchy(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class ArmsAndWeaponsPrimer : BaseBook + { + public static readonly BookContent Content = new BookContent( + "A Primer on Arms and Weapons", + "Martin", + new BookPageInfo( + " These are the", + "basic elements to", + "consider in assessing", + "a weapon, of which", + "all warriors who", + "regard themselves as", + "more than mere", + "mercenaries should be" + ), + new BookPageInfo( + "aware.", + " First and most", + "obvious is the amount", + "of damage that the", + "weapon may do", + "against unprotected", + "flesh. While 'tis this", + "which first attracts" + ), + new BookPageInfo( + "the attention of the", + "novice, 'tis a deadly", + "mistake to regard it", + "as the sole value of a", + "weapon. While it may", + "prove devastating", + "indeed as a means of", + "causing damage, a" + ), + new BookPageInfo( + "weapon must also", + "serve as stout shield", + "when engaged in", + "combat.", + " Hence the second", + "issue to which to pay", + "attention is the", + "amount of protection" + ), + new BookPageInfo( + "that a weapon may", + "offer. Pay close", + "attention to the guard", + "on it, if it be a blade,", + "or the stoutness of", + "its wood if it is a pole", + "arm.", + " Oft related to this" + ), + new BookPageInfo( + "is the weight of the", + "weapon, for a heavy", + "weapon is more", + "difficult to maneuver", + "to block with, though", + "it may do more", + "damage to thy", + "opponent." + ), + new BookPageInfo( + " If a weapon is too", + "heavy for the wielder", + "to move it freely,", + "they should choose", + "another and not", + "attempt to prove their", + "prowess by the size", + "of their sword." + ), + new BookPageInfo( + " The reach of a", + "weapon both increases", + "its defensive ability,", + "and renders it more", + "useful in open spaces", + "as it allows attack", + "against the opponent", + "without the need to" + ), + new BookPageInfo( + "close. But be aware of", + "the limitations of thy", + "weapon! For a", + "weapon with great", + "reach may be useless", + "in close quarters, for", + "lack of space to", + "maneuver it. Should" + ), + new BookPageInfo( + "that dagger-wielding", + "enemy close on thee", + "and thy halberd, 'tis", + "best to flee.", + " Lastly, a factor", + "that must always be", + "considered is the", + "condition of the" + ), + new BookPageInfo( + "weapon. It might be a", + "wondrous magical", + "blade of surpassing", + "sharpness and it may", + "leap to block blows", + "with a mind of its", + "own. It also might be", + "of such flimsy" + ), + new BookPageInfo( + "construction, or", + "damaged to such an", + "extent, that the first", + "time it clangs against", + "steel, 'twill shatter", + "into useless shards.", + " Seek ye a good", + "blacksmith should thy" + ), + new BookPageInfo( + "weapon become", + "damaged, but be", + "aware that their", + "ministrations may", + "simply make the", + "matter worse.", + " While mages of", + "some ability oft create" + ), + new BookPageInfo( + "magical weapons", + "which enhance skill,", + "are preternaturally", + "sharp, or incinerate", + "the enemy as they", + "fall, to my mind the", + "greatest gift that they", + "can grant a stout" + ), + new BookPageInfo( + "sword is to make it", + "resistant to damage,", + "for thy own skill can", + "make up the", + "difference. Except", + "for the fireball, but", + "if the corpse is", + "charred, then so will" + ), + new BookPageInfo( + "be the possessions,", + "which maketh looting", + "difficult!" + ) + ); + + [Constructible] + public ArmsAndWeaponsPrimer() : base(Utility.Random(0xFEF, 2), false) + { + } + + public ArmsAndWeaponsPrimer(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class SongOfSamlethe : BaseBook + { + public static readonly BookContent Content = new BookContent( + "A Song of Samlethe", + "Sandra", + new BookPageInfo( + "The first bear did", + "swim by day,", + "And it did sleep by", + "night.", + "It kept itself within", + "its cave", + "and ate by starry", + "light." + ), + new BookPageInfo( + "", + "The second bear it did", + "cavort", + "'Neath canopies of", + "trees,", + "And danced its", + "strange bearish sort", + "Of joy for all to see." + ), + new BookPageInfo( + "", + "The first bear, well,", + "'twas hunted,", + "And today adorns a", + "floor.", + "Its ruggish face has", + "been dented", + "By footfalls and the" + ), + new BookPageInfo( + "door.", + "", + "The second bear did", + "step once", + "Into a mushroom ring,", + "And now does dance", + "the dunce", + "For wisps and" + ), + new BookPageInfo( + "unseen things.", + "", + "So do not dance, and", + "do not sleep,", + "Or else be led astray!", + "For bears all end up", + "six feet deep", + "At the end of" + ), + new BookPageInfo( + "Samlethe's day." + ) + ); + + [Constructible] + public SongOfSamlethe() : base(Utility.Random(0xFEF, 2), false) + { + } + + public SongOfSamlethe(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class TaleOfThreeTribes : BaseBook + { + public static readonly BookContent Content = new BookContent( + "A Tale of Three Tribes", + "Janet, Scribe", + new BookPageInfo( + " The dungeon known", + "as Despise is in fact", + "not a dungeon as", + "such, but rather a", + "large natural cave.", + "Inhospitable and", + "unfriendly to", + "visitors, it is filled" + ), + new BookPageInfo( + "with damp spots", + "where the deadly", + "Exploding Red Spotted", + "Toadstool grows in", + "abundance.", + " According to the", + "oldest of historical", + "texts, in days gone" + ), + new BookPageInfo( + "by the cave was once", + "the home of three", + "separate tribes who", + "had come to an", + "accommodation with", + "each other. Oddly", + "enough, the three", + "tribes were of" + ), + new BookPageInfo( + "dragons, lizard men,", + "and rat men. While", + "today few except", + "extremists associated", + "with Lord Blackthorn", + "regard these latter", + "two as being", + "intelligent beings," + ), + new BookPageInfo( + "apparently they have", + "indeed fallen from a", + "more evolved state", + "over the years.", + " 'Tis said that these", + "three races did dwell", + "in relative harmony", + "within the vast cave," + ), + new BookPageInfo( + "building when they", + "required it, and", + "trading amongst", + "themselves if needed.", + " But over time,", + "something happened,", + "and they were forced", + "to withdraw from" + ), + new BookPageInfo( + "their society, until", + "today thou mayst", + "find individuals of", + "each species within", + "the dungeon, but", + "never again as a", + "civilization.", + " 'Tis also said that" + ), + new BookPageInfo( + "someday the three", + "tribes may return to", + "Despise, to once again", + "inhabit it together.", + " Until then, nothing", + "remains as token of", + "this save an oddly", + "intelligent skeleton," + ), + new BookPageInfo( + "magically enchanted,", + "that doth speak when", + "questions are asked,", + "and from whom I", + "obtained these tales", + "one day, when I was", + "pursued by evil", + "monsters and fled" + ), + new BookPageInfo( + "into his skeletal arms.", + " Fortunately, I", + "escaped and lived to", + "write it all down!" + ) + ); + + [Constructible] + public TaleOfThreeTribes() : base(Utility.Random(0xFEF, 2), false) + { + } + + public TaleOfThreeTribes(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class GuideToGuilds : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Beltran's Guide to Guilds", + "Beltran", + new BookPageInfo( + " This reference", + "work is intended", + "merely to serve as", + "resource for those", + "curious as to the full", + "range of trades and", + "societies extant in", + "Britannia and nearby" + ), + new BookPageInfo( + "nations. For each", + "trade or guild, their", + "blazon is given.", + "", + " Armourer's Guild.", + "Gold bar above black", + "bar." + ), + new BookPageInfo( + " Association of", + "Warriors. Blue cross", + "on a red field.", + "", + " Barters' Guild.", + "Green and white", + "stripes, diagonal." + ), + new BookPageInfo( + " Blacksmith's Guild.", + "Gold alongside black.", + "", + " Federation of", + "Rogues and Beggars.", + "Red above black.", + "", + " Fighters and" + ), + new BookPageInfo( + "Footmen. Blue", + "horzontal bar on red", + "field.", + "", + " Guild of Archers.", + "A gold swath parting", + "red and blue." + ), + new BookPageInfo( + " Guild of", + "Armaments. Swath of", + "gold on black field,", + "gold accents.", + "", + " Guild of Assassins.", + "Black and red", + "quartered." + ), + new BookPageInfo( + "", + " Guild of Barbers.", + "Red and white", + "stripes.", + "", + " Guild of Cavalry and", + "Horse. Vertical blue", + "on a red field." + ), + new BookPageInfo( + "", + " Guild of", + "Fishermen. Blue and", + "white, quartered.", + "", + " Guild of Mages.", + "Purple and blue, in a", + "crossed pennant" + ), + new BookPageInfo( + "pattern.", + "", + " Guild of", + "Provisioners. White", + "bar above green bar.", + "", + " Guild of Sorcery. A", + "field divided" + ), + new BookPageInfo( + "diagonally in blue and", + "purple.", + "", + " Healers Guild. Gold", + "swath dividing green", + "from purple, gold", + "accents." + ), + new BookPageInfo( + " Lord British's", + "Healers of Virtue.", + "Golden ankh on dark", + "green.", + "", + " Masters of Illusion.", + "Blue and purple", + "checkers." + ), + new BookPageInfo( + "", + " Merchants' Guild.", + "Gold coins on green", + "field.", + "", + " Mining Cooperative.", + "A gold cross,", + "quartering blue and" + ), + new BookPageInfo( + "black.", + "", + " Order of Engineers.", + "Purple, gold, and blue", + "vertical.", + "", + " Sailors' Maritime", + "Association. A white" + ), + new BookPageInfo( + "bar centered on a blue", + "field.", + "", + " Seamen's Chapter.", + "Blue and white in a", + "crossed pennant", + "pattern." + ), + new BookPageInfo( + " Society of Cooks and", + "Chefs. White and red", + "diagonal fields", + "checker on green", + "field.", + "", + " Society of", + "Shipwrights. White" + ), + new BookPageInfo( + "diagonal above blue.", + "", + " Society of Thieves.", + "Black and red diagonal", + "stripes.", + "", + " Society of", + "Weaponsmakers. Gold" + ), + new BookPageInfo( + "diagonal above black.", + "", + " Tailor's Hall. Purple", + "above gold above red.", + "", + " The Bardic", + "Collegium. Purple and", + "red checkers on gold" + ), + new BookPageInfo( + "field.", + "", + " Traders' Guild.", + "White bar centered", + "down green field." + ) + ); + + [Constructible] + public GuideToGuilds() : base(Utility.Random(0xFEF, 2), false) + { + } + + public GuideToGuilds(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class BirdsOfBritannia : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Birds of Britannia", + "Thom the Heathen", + new BookPageInfo( + " The WREN is a", + "tiny insect-eating", + "bird with a loud voice.", + " The cheerful trills", + "of Wrens are", + "extraordinarily", + "varied and melodious.", + " The SWALLOW" + ), + new BookPageInfo( + "is easily recognized", + "by its forked tail.", + "Swallows catch", + "insects in flight, and", + "have squeaky,", + "twittering songs.", + " The WARBLER is", + "an exceptional singer," + ), + new BookPageInfo( + "whose extensive", + "songs combine the", + "best qualities of", + "Wrens and Swallows.", + " The NUTHATCH", + "climbs down trees", + "head first, searching", + "for insects in the" + ), + new BookPageInfo( + "bark. It sings a", + "repetitive series of", + "notes with a nasal", + "tone quality.", + " The agile", + "CHICKADEE has a", + "buzzy", + "\"chick-a-dee-dee\"" + ), + new BookPageInfo( + "call, from which its", + "name is derived. Its", + "song is a series of", + "whistled notes.", + " The THRUSH is a", + "brown bird with a", + "spotted breast, which", + "eats worms and" + ), + new BookPageInfo( + "snails, and has a", + "beautiful singing", + "voice. Thrushes use", + "a stone as an anvil to", + "smash the shells of", + "snails.", + " The little", + "NIGHTINGALE is" + ), + new BookPageInfo( + "also known for its", + "beautiful song, which", + "it sings even at night.", + " The STARLING", + "is a small dark bird", + "with a yellow bill and", + "a squeaky,", + "high-pitched song." + ), + new BookPageInfo( + "Starlings can mimic", + "the sounds of other", + "birds.", + " The SKYLARK", + "sings a series of", + "high-pitched", + "melodious trills in", + "flight." + ), + new BookPageInfo( + " The FINCH is a", + "small seed-eating bird", + "with a conical beak", + "and a musical,", + "warbling song.", + " The CROSSBILL", + "is a kind of Finch", + "with a strange" + ), + new BookPageInfo( + "crossed bill, which it", + "uses to extract seeds", + "from pine cones.", + " The CANARY is a", + "kind of Finch that is", + "often kept as a pet.", + "Miners would often", + "take Canaries" + ), + new BookPageInfo( + "underground with", + "them, to warn them", + "of the presence of", + "hazardous vapors in", + "the air.", + " The SPARROW", + "weaves a nest of", + "grass, and has an" + ), + new BookPageInfo( + "unmusical chirp for a", + "voice.", + " The TOWHEE is a", + "kind of Sparrow that", + "continually reminds", + "listeners to drink", + "their tea.", + " The SHRIKE is a" + ), + new BookPageInfo( + "gray bird with a", + "hooked bill. Shrikes", + "have the habit of", + "impaling their prey", + "on thorns.", + " The", + "WOODPECKER has a", + "pointed beak that is" + ), + new BookPageInfo( + "suitable for pecking at", + "wood to get at the", + "insects inside.", + " The", + "KINGFISHER dives", + "for fish, which it", + "catches with its long,", + "pointed beak." + ), + new BookPageInfo( + " The TERN", + "migrates over great", + "distances, from one", + "end of Britannia to", + "the other each year.", + "Terns dive from the", + "air to catch fish.", + " The PLOVER is a" + ), + new BookPageInfo( + "bird that distracts", + "predators by", + "pretending to have a", + "broken wing.", + " The LAPWING is", + "a kind of Plover that", + "has a long black crest.", + " The HAWK is a" + ), + new BookPageInfo( + "predator that feeds on", + "small birds, mice,", + "squirrels, and other", + "small animals. Small", + "hawks are known as", + "Kites.", + " The DOVE is a", + "seed-eating bird with" + ), + new BookPageInfo( + "a peaceful reputation.", + " Doves have a", + "low-pitched cooing", + "song.", + " The PARROT is a", + "brightly colored bird", + "with a hooked bill,", + "favored as a" + ), + new BookPageInfo( + "companion by pirates.", + " Parrots can be", + "taught to imitate the", + "human voice.", + " The CUCKOO is a", + "devious bird that lays", + "eggs in the nests of", + "Warblers and other" + ), + new BookPageInfo( + "small birds. Cuckoos", + "have the uncanny", + "ability to keep track", + "of time, singing once", + "at the beginning of", + "each hour.", + " The", + "ROADRUNNER is" + ), + new BookPageInfo( + "an unusual bird with", + "a long tail, which", + "runs swiftly along", + "the ground hunting", + "for lizards and", + "snakes.", + " The SWIFT is a", + "very agile bird that" + ), + new BookPageInfo( + "spends nearly its", + "entire life in the air.", + "With their mouths", + "wide open, Swifts", + "capture insects in", + "mid-flight.", + " The", + "HUMMINGBIRD is a" + ), + new BookPageInfo( + "cross between a", + "Swift and a Fairy.", + "These tiny, brightly", + "colored birds hover", + "magically near", + "flowers, and live on", + "the nectar they", + "provide." + ), + new BookPageInfo( + " The OWL is a", + "reputedly wise bird", + "that is active at night,", + "unlike most birds.", + "Owls have excellent", + "night vision and", + "low-pitched hooting", + "calls. Their wings" + ), + new BookPageInfo( + "are silent in flight.", + " The", + "GOATSUCKER is a", + "strange owl-like bird", + "that is thought to live", + "on the milk of goats.", + "These mysterious", + "birds make jarring" + ), + new BookPageInfo( + "sounds at night, for", + "which reason they", + "are also called", + "Nightjars.", + " The DUCK is a", + "bird that swims more", + "often than it flies,", + "and has a nasal voice" + ), + new BookPageInfo( + "that is described as a", + "\"quack\".", + " The SWAN is a", + "kind of long-necked", + "Duck that is all white.", + " Swans are usually", + "voiceless, but they", + "are said to have an" + ), + new BookPageInfo( + "extraordinarily", + "beautiful song." + ) + ); + + [Constructible] + public BirdsOfBritannia() : base(Utility.Random(0xFEF, 2), false) + { + } + + public BirdsOfBritannia(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class BritannianFlora : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Britannian Flora: A Casual Guide", + "Herbert the Lost", + new BookPageInfo( + " Oft 'pon rambling", + "through the woods", + "avoiding bears have I", + "spotted some plant", + "whose like I have", + "never seen before,", + "and concluded that I", + "was a blithering idiot" + ), + new BookPageInfo( + "for failing to notice it", + "in the past. Equally", + "as oft have I", + "concluded that I was a", + "worse idiot for not", + "running faster from", + "the bear.", + " While not all my" + ), + new BookPageInfo( + "readers may share", + "my proclivities for", + "tree-climbing, it", + "occurred to me that", + "mayhap mine", + "information might", + "serve some humble", + "purpose." + ), + new BookPageInfo( + " The two most", + "unique flowering", + "plants in the", + "Britannian", + "countryside are the", + "orfleur and the", + "whiteflower, also", + "called white horns." + ), + new BookPageInfo( + " The orfleur is", + "notable for its", + "massive orange-red", + "blossoms, which", + "dwarf marigolds like", + "the sun dwarfs your", + "common fireball spell.", + "The odor of said" + ), + new BookPageInfo( + "blooms is best", + "described as", + "peppermint-apple,", + "with a dash of garlic.", + "'Tis a popular potted", + "plant despite, or", + "perhaps because of,", + "its exotic nature." + ), + new BookPageInfo( + " Whiteflowers exude", + "a subtle fragrance not", + "unlike that of freshly", + "shaven wood mixed", + "with cool lemon ice.", + "Their tall stands", + "always droop with the", + "heavy weight of the" + ), + new BookPageInfo( + "massive blooms, oft", + "as large as a child's", + "head.", + " The flowers are so", + "large that one may", + "scoop out the pollen in", + "handfuls, and during", + "the spring season" + ), + new BookPageInfo( + "many a prank hath", + "been played by idle", + "boys 'pon their", + "sisters by dumping", + "said pollen into their", + "clothing drawers,", + "causing sneezes for", + "days." + ), + new BookPageInfo( + " The most", + "interesting native tree", + "to Britannia is the", + "spider tree. The", + "reason for its naming", + "is obscure, but may", + "have to do with the", + "twisted gray stalks" + ), + new BookPageInfo( + "from which the", + "spherical canopy", + "sprouts. 'Tis", + "something of a", + "misnomer to term", + "these \"trunks\" as", + "they are spindly and", + "flexible. Spider trees" + ), + new BookPageInfo( + "provide a fresh,", + "piney smell to a room", + "and are therefore", + "often potted.", + " In jungle climes,", + "one finds the blade", + "plant, whose sharp", + "leaves oft collect" + ), + new BookPageInfo( + "water for the thirsty", + "traveler, yet can", + "draw blood easily.", + " The deadliest plant,", + "if you can call a", + "fungus such, is the", + "Exploding Red Spotted", + "Toadstool. No pattern" + ), + new BookPageInfo( + "can be discerned to", + "its habitats save", + "malice, for merely", + "approaching results in", + "the cap exploding", + "with powder, noxious", + "gas, and tiny painful", + "pellets flying in all" + ), + new BookPageInfo( + "directions.", + "Unfortunately, 'tis", + "impossible to tell it", + "apart from the", + "Ordinary Red Spotted", + "Toadstool save through", + "experimentation.", + " Truly odd among the" + ), + new BookPageInfo( + "varied flora of", + "Britannia, however,", + "are those which bear", + "names clearly alien to", + "our tongue. Among", + "these I name the", + "Tuscany pine (for I", + "have never seen a" + ), + new BookPageInfo( + "region of this world", + "named Tuscany), the", + "o'hii tree, whose very", + "name sounds like", + "some tropical isle, and", + "the welsh poppy,", + "which while", + "different from the" + ), + new BookPageInfo( + "ordinary poppy in", + "color and appearance,", + "is prefaced with the", + "odd word \"welsh,\"", + "which as far as I", + "know means to forgo", + "paying a debt." + ) + ); + + [Constructible] + public BritannianFlora() : base(Utility.Random(0xFEF, 2), false) + { + } + + public BritannianFlora(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class ChildrenTalesVol2 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Classic Children's Tales, Volume 2", + "Guilhem, Editor", + new BookPageInfo( + "Clarke's Printery", + "is Honored to", + "Present Tales from", + "Ages Past!", + " Guilhem the", + "Scholar Shall End", + "EachVolume with", + "Staid Commentary." + ), + new BookPageInfo( + "", + "THE RHYME", + "Dance in the Star", + "Chamber", + "And Dance in the Pit", + "And Eat of your", + "Entrees", + "In the Glass House" + ), + new BookPageInfo( + "you Sit", + "", + "COMMENTARY", + " A common feeding", + "rhyme for little", + "babies, 'tis thought", + "that this little ditty is", + "part of the corpus of" + ), + new BookPageInfo( + "legendary tales", + "regarding the world", + "before Sosaria (see", + "the wonderful fables", + "of Fabio the Poor for", + "fictionalized versions", + "of these stories, also", + "available from this" + ), + new BookPageInfo( + "same publisher).", + " According to these", + "old tales, which", + "survive mostly in the", + "hills and remote", + "villages where Lord", + "British is as yet a", + "distant and mythical" + ), + new BookPageInfo( + "ruler, the gods of old", + "(a fanciful notion!)", + "met to discuss the", + "progress of creating", + "the world in mystical", + "rooms. A simple", + "analysis reveals these", + "rooms to be mere" + ), + new BookPageInfo( + "mythological", + "generalizations.", + " \"The Star", + "Chamber\" is clearly a", + "reference to the sky.", + "\"The Pit\" is certainly", + "an Underworld", + "analogous to the" + ), + new BookPageInfo( + "Snakehills of other", + "tales, and \"the Glass", + "House\" is no doubt the", + "vantage point from", + "which the gods", + "observed their", + "creation. All is simple", + "when seen from this" + ), + new BookPageInfo( + "perspective, leaving", + "only the mysterious", + "reference to dinners.", + "Oddly enough, the", + "rhyme is universally", + "used only for", + "midnight feedings,", + "never during the day." + ), + new BookPageInfo() + ); + + [Constructible] + public ChildrenTalesVol2() : base(Utility.Random(0xFEF, 2), false) + { + } + + public ChildrenTalesVol2(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class TalesOfVesperVol1 : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Classic Tales of Vesper, Volume 1", + "Clarke's Printery", + new BookPageInfo( + "'Tis an Honor to", + "present to Thee these", + "Tales collected from", + "Ages Past. In this", + "Inaugural Volume, we", + "present this Verse", + "oft Recited as a", + "Lullabye for sleepy" + ), + new BookPageInfo( + "Children.", + "", + "Preface", + "by Guilhem the", + "Scholar", + "", + " The meaning of this", + "verse has oft been" + ), + new BookPageInfo( + "discussed in halls of", + "scholarly sorts, for", + "its mysterious", + "singsongy melody is", + "oddly disturbing to", + "adult ears, though", + "children seem to find", + "it restful as they" + ), + new BookPageInfo( + "sleep. Perhaps it is", + "but the remnant of a", + "longer ballad once", + "extant, for there are", + "internal indications", + "that it once told a", + "longer story about", + "ill-fated lovers, and a" + ), + new BookPageInfo( + "magical experiment", + "gone awry. However,", + "poetic license and the", + "folk process has", + "distorted the words", + "until now the locale of", + "the tale is no more", + "than \"in the wind,\"" + ), + new BookPageInfo( + "which while it serves", + "a pleasingly", + "metaphorical purpose,", + "fails to inform the", + "listener as to any real", + "locale!", + " Another possibility", + "is that this is some" + ), + new BookPageInfo( + "form of creation", + "myth explaining the", + "genesis of the various", + "humanoid creatures", + "that roam the lands of", + "Britannia. It does not", + "take a stretch of the", + "imagination to name" + ), + new BookPageInfo( + "the middle verse's", + "\"girl becomes tree\" as", + "a possible explanation", + "for the reaper, for in", + "the area surrounding", + "Minoc, reapers are", + "oft referred to among", + "the lumberjacking" + ), + new BookPageInfo( + "community as", + "\"widowmakers.\" That", + "these creatures are", + "of arcane origin is", + "assumed, but the", + "verse seems to imply", + "a long ago creator, and", + "uses the antique" + ), + new BookPageInfo( + "magickal terminology", + "of \"plaiting strands", + "of ether\" that is so", + "often found in", + "ancient texts. In", + "addition, the", + "reference to", + "\"snakehills\" may" + ), + new BookPageInfo( + "profitably be regarded", + "as a reference to an", + "actual location, such", + "as perhaps a local", + "term for the", + "Serpent's Spine.", + " A commoner", + "interpretation is that" + ), + new BookPageInfo( + "like many nursery", + "rhymes, it is a", + "simple explanation", + "for death, wherein", + "the wind snatches up", + "boys and girls and", + "when they sleep in", + "order to keep the" + ), + new BookPageInfo( + "balance of the world.", + "Notable tales have", + "been written for", + "children of", + "adventures in \"the", + "Snakehills,\" which", + "are presumed to be an", + "Afterworld whence" + ), + new BookPageInfo( + "the spirit lives on. A", + "grim lullabye, to be", + "sure, but no worse", + "than \"lest I die before", + "I wake\" surely.", + " In either case, 'tis", + "an old favorite,", + "herein printed for" + ), + new BookPageInfo( + "the first time for", + "thy enjoyment and", + "perusal!", + "", + "In the Wind where", + "the Balance", + "Is Whispered in", + "Hallways" + ), + new BookPageInfo( + "In the Wind where", + "the Magic", + "Flows All through the", + "Night", + "There live Mages and", + "Mages", + "With Robes made of", + "Whole Days" + ), + new BookPageInfo( + "Reading Books full of", + "Doings", + "Printed on Light", + "", + "In the Wind where", + "the Lovers", + "Are Crossed under", + "Shadows" + ), + new BookPageInfo( + "Where they Meet and", + "are Parted", + "By the Orders of", + "Fate", + "The Girl becomes", + "Tree,", + "And thus becomes", + "Widow" + ), + new BookPageInfo( + "The Boy becomes", + "Earth", + "And Wanders Till", + "Late", + "", + "In the Wind are the", + "Monsters", + "First Born First" + ), + new BookPageInfo( + "Created", + "When Chanting and", + "Ether", + "Mix Meddling and", + "Nigh", + "Fear going to Wind,", + "Fear Finding its", + "Plaitings," + ), + new BookPageInfo( + "Go Not to the", + "Snakehills", + "Lest You Care to Die" + ) + ); + + [Constructible] + public TalesOfVesperVol1() : base(Utility.Random(0xFEF, 2), false) + { + } + + public TalesOfVesperVol1(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class DeceitDungeonOfHorror : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Deceit: A Dungeon of Horrors", + "Mercenary Justin", + new BookPageInfo( + " My employers have", + "oft taken me into this", + "den of hideous", + "creatures, and I", + "thought that it", + "behooved me to write", + "down what I know of", + "it, now that I am" + ), + new BookPageInfo( + "retired from the life", + "of an adventurer for", + "hire.", + " Deceit was once a", + "temple to forgotten", + "powers of old. It was", + "taken over by mages", + "who eventually were" + ), + new BookPageInfo( + "driven out by the", + "depredations of their", + "own evil lackeys.", + "However, many of", + "the magical traps and", + "devices that they", + "placed for their", + "defenses remain," + ), + new BookPageInfo( + "particularly those the", + "wizards used to", + "protect their", + "treasures.", + " The dungeon is", + "mystically linked by", + "crystal balls placed in", + "different locations." + ), + new BookPageInfo( + "These magical orbs do", + "transmit speech, and", + "even have memory of", + "things that have been", + "said near them. No", + "doubt they once", + "served as a warning", + "system" + ), + new BookPageInfo( + " Be wary of a", + "brazier that giveth", + "warning when", + "approached; thou canst", + "use it to summon", + "deadly creatures.", + " There be a", + "tantalizing chest," + ), + new BookPageInfo( + "undoubtedly full of", + "treasure, that cannot", + "be reached save past a", + "complex set of", + "pressure plates that", + "trigger deadly spikes.", + "As I never had", + "sufficient folk with" + ), + new BookPageInfo( + "me to unlock the", + "puzzle, I never", + "obtained the riches", + "that awaited there.", + " Do not investigate", + "iron maidens too", + "closely, for they may", + "suck you within" + ), + new BookPageInfo( + "them!", + " There is one place", + "where a deadly trap", + "can only be disarmed", + "by making use of a", + "statue that cleverly", + "conceals a lever.", + " Oft one encounters" + ), + new BookPageInfo( + "the deadly exploding", + "toadstool; the ones in", + "Deceit are deadlier", + "than most, as they", + "explode continually.", + "Likewise, the very", + "pools of water and", + "slime on the floor" + ), + new BookPageInfo( + "may poison thee.", + " The most magical", + "device in the dungeon", + "is a mystical bridge", + "that can only be", + "triggered by a level", + "embedded in the floor.", + "Be wary however," + ), + new BookPageInfo( + "for the bridge thus", + "created doth burst", + "into flame when one", + "passeth across it!" + ) + ); + + [Constructible] + public DeceitDungeonOfHorror() : base(Utility.Random(0xFEF, 2), false) + { + } + + public DeceitDungeonOfHorror(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class DimensionalTravel : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Dimensional Travel, a Monograph", + "Dryus Doost, Mage", + new BookPageInfo( + " 'Tis beyond the", + "scope of this small", + "monograph to discuss", + "the details of", + "moongates, and the", + "manners in which", + "they distort the", + "fabric of reality in" + ), + new BookPageInfo( + "such a manner as to", + "permit the passage of", + "living flesh from", + "place to place, world to", + "world, or indeed from", + "dimension to", + "dimension.", + " Instead, allow me to" + ), + new BookPageInfo( + "bring thy attention,", + "Gentle Reader, to the", + "curious", + "characteristics that", + "are shared by certain", + "individuals within", + "our realm.", + " Long has it been" + ), + new BookPageInfo( + "known that the blue", + "moongate permits", + "travel from place to", + "place, and none have", + "trouble in taking this", + "path. Yet 'tis also", + "known, albeit only to a", + "few, that certain" + ), + new BookPageInfo( + "individuals are unable", + "to traverse the black", + "moongates that permit", + "travel from one", + "dimension to another.", + " The noted mage and", + "peer of our realm,", + "Lord Blackthorn, once" + ), + new BookPageInfo( + "told me in", + "conversation that his", + "arcane research had", + "indicated that the", + "issue was one of", + "conversation of ether.", + "To wit, given the", + "postulate that matter" + ), + new BookPageInfo( + "within a given", + "dimension may be but", + "a cross-section of", + "ethereal matter that", + "exists in multiple", + "dimensions, it", + "becomes obvious that", + "said ethereal" + ), + new BookPageInfo( + "structure cannot", + "enter dimensions in", + "which it is already", + "present.", + " Imagine an", + "individual (and the", + "Lord Blackthorn", + "hinted that he was" + ), + new BookPageInfo( + "one such) who exists", + "already in some form", + "in multiple", + "dimensions; said", + "individual would not", + "be able to cross into", + "another dimension", + "because HE IS" + ), + new BookPageInfo( + "ALREADY THERE.", + " The implications of", + "this are staggering,", + "and merit further", + "study. 'Tis well", + "known by theorists in", + "the field that", + "divisions in the" + ), + new BookPageInfo( + "ethereal structure of", + "an individual are", + "already implicit at the", + "temporal level, as", + "causality forces", + "divisions upon the", + "ether. This is the", + "basic operating" + ), + new BookPageInfo( + "mechanism by which", + "white moongates", + "function, permitting", + "time travel.", + " As time travel is", + "not barred by the", + "presence of an earlier", + "self (though" + ), + new BookPageInfo( + "encountering said", + "earlier self can prove", + "arcanely perilous),", + "there must be some", + "rigidity to the", + "ethereal structure", + "that bars multiple", + "instantiations of" + ), + new BookPageInfo( + "structures from", + "manifesting within", + "the same context.", + " If one regards time", + "and causal bifurcation", + "as a web, perhaps the", + "appropriate analogy", + "for dimensional" + ), + new BookPageInfo( + "matrices is that of a", + "crystalline structure,", + "with rigid linkages.", + "The only way in", + "which an individual", + "such as Lord", + "Blackthorn, who", + "exists in multiple" + ), + new BookPageInfo( + "dimensional matrices,", + "can cross worlds via", + "a black moongate,", + "would be for the", + "entire crystalline", + "structure of the", + "dimension to", + "perfectly match the" + ), + new BookPageInfo( + "ethereal resonance of", + "the destination", + "dimension.", + " The problem of why", + "certain individuals", + "are already replicated", + "in multiple crystalline", + "matrices is one that I" + ), + new BookPageInfo( + "fail to provide any", + "schema for in these", + "poor theories. It is", + "my fondest hope that", + "someday someone", + "shall conquer that", + "thorny problem and", + "enlighten the world." + ) + ); + + [Constructible] + public DimensionalTravel() : base(Utility.Random(0xFEF, 2), false) + { + } + + public DimensionalTravel(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class EthicalHedonism : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Ethical Hedonism: An Introduction", + "Richard Garriott", + new BookPageInfo( + " Societies oft have", + "common codes of", + "conduct which it", + "expects all its people", + "to abide by. Now,", + "while 'tis true that", + "this can offer some", + "advantages, most of" + ), + new BookPageInfo( + "the codes I see today", + "around Britannia have", + "fatal flaws. Let us", + "examine them.", + " First, there is", + "Blackthorn's code of", + "Chaos or basically", + "Anarchy. Whereas" + ), + new BookPageInfo( + "this affords the", + "individual maximum", + "opportunity for", + "individuality and even", + "pursuit of personal", + "happiness, it does not", + "offer even basic", + "interpersonal conduct" + ), + new BookPageInfo( + "codes to prevent", + "people from killing", + "each other.", + " Without such basic", + "tenets, all the people", + "will need to spend a", + "significant portion of", + "their time and effort" + ), + new BookPageInfo( + "towards personal", + "protection and thus", + "less time towards", + "other more beneficial", + "pursuits.", + " Then there are the", + "moral codes that are", + "so popular today." + ), + new BookPageInfo( + "These codes are built", + "largely on historical", + "tradition rather than", + "current logic and thus", + "are also antiquated.", + "For example many", + "moral codes we see", + "today include" + ), + new BookPageInfo( + "statements about not", + "eating certain foods", + "that once were often", + "poisonous, but today", + "can be prepared", + "safely.", + " Many forbid contact", + "between young people" + ), + new BookPageInfo( + "of the opposite", + "gender, which can in", + "fact be hazardous; but", + "the codes often have", + "lost the context as to", + "why this is done,", + "instead merely calling", + "it amoral. In this day" + ), + new BookPageInfo( + "and age to call that a", + "necessary moral", + "would need a new", + "reasoning. I put forth", + "that tradition is not", + "enough", + " Then there are", + "Lord British's" + ), + new BookPageInfo( + "Virtues. It strikes me", + "that while a system", + "of virtues is", + "wonderful as a", + "touchstone to guide a", + "society to good", + "behavior, these are", + "but shades of the" + ), + new BookPageInfo( + "underlying truth as to", + "why one may wish to", + "live a life according to", + "certain rules of", + "conduct.", + " On the other hand,", + "clearly the Virtues", + "that I have heard" + ), + new BookPageInfo( + "Lord British speak of", + "are clearly positive", + "codes of conduct, far", + "better than the world", + "of anarchy that Lord", + "Blackthorn suggests.", + "Yet, are not these", + "Virtues still derived" + ), + new BookPageInfo( + "from a set of", + "principles which", + "though they sound", + "good, are difficult to", + "pin down as actual,", + "undeniable, rational", + "truths?", + " Worse yet though" + ), + new BookPageInfo( + "imagine a society", + "who's code of", + "conduct was based on", + "pure survival of the", + "strongest. While this", + "society may function", + "and even accomplish", + "much, it can be" + ), + new BookPageInfo( + "fairly argued that", + "personal happiness", + "would suffer greatly,", + "except for those at", + "the top. To rule that", + "out, however, we", + "must first believe", + "that people have a" + ), + new BookPageInfo( + "right to pursue", + "happiness.", + " I hope is a safe", + "assumption that all", + "beings wish to be", + "happy; I will broadly", + "describe this as", + "Hedonism. Yet, if all" + ), + new BookPageInfo( + "people did is live a", + "life of hedonism,", + "their hedonism might", + "be in conflict with", + "those near them, so I", + "will use the term", + "Ethics to describe", + "limits one might put" + ), + new BookPageInfo( + "on one's hedonistic", + "tendencies to allow", + "others to pursue their", + "happiness as well.", + " Allow me to give", + "this example: If one", + "were to live alone on a", + "desert isle, one could" + ), + new BookPageInfo( + "live a life of pure", + "hedonism, for no", + "action one might take", + "could interfere with", + "another's right to", + "pursue their", + "happiness. Poison the", + "lake if you like, there" + ), + new BookPageInfo( + "is no one to blame but", + "yourself!", + " Now suppose two", + "of you live on that", + "island. Thou dost not", + "want thy neighbor to", + "feel free to poison the", + "lake. Would it not be" + ), + new BookPageInfo( + "better to consider it", + "unethical to poison the", + "lake without first", + "thinking of those", + "whose pursuit of", + "happiness might be", + "affected by this", + "action?" + ), + new BookPageInfo( + " I put forth that it is", + "the fact that we as a", + "people choose to live in", + "groups known as a", + "society that causes us", + "to compromise our", + "pure hedonism with", + "logical ethics." + ), + new BookPageInfo( + "Likewise we accept", + "not being able to kill", + "others without", + "reason, because our", + "own pursuit of", + "happiness would be", + "greatly interfered", + "with if we feared" + ), + new BookPageInfo( + "others would do the", + "same to us. From", + "this basis of logic can", + "be formed the Tenets", + "of Ethical Hedonism.", + " For more on this", + "subject, see The", + "Tenants of Ethical" + ), + new BookPageInfo( + "Hedonism, by", + "Richard Garriott and", + "Herman Miller." + ) + ); + + [Constructible] + public EthicalHedonism() : base(Utility.Random(0xFEF, 2), false) + { + } + + public EthicalHedonism(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class MyStory : BaseBook + { + public static readonly BookContent Content = new BookContent( + "My Story", + "Sherry the Mouse", + new BookPageInfo( + " 'Twas on a chill", + "night, when the moon", + "shone pasty-faced", + "above the horizon,", + "balanced on the", + "towers of Lord", + "British's castle, that", + "the events I am about" + ), + new BookPageInfo( + "to relate took place,", + "some years ago now. I", + "witnessed them all", + "from my tiny", + "mousehole.", + " Milords British and", + "Blackthorn are", + "accustomed to a game" + ), + new BookPageInfo( + "of chess 'pon an", + "evening, over which", + "they argue the issues", + "that affect the course", + "of the realm. Lord", + "Blackthorn was on his", + "way to Lord British's", + "chambers, and Lord" + ), + new BookPageInfo( + "British stood by a", + "window casement,", + "just having finished", + "setting the pieces", + "upon the board.", + " Suddenly the", + "shutters blew open,", + "and Lord British fell" + ), + new BookPageInfo( + "to the ground, one", + "hand shielding his", + "eyes. A chill wind", + "entered the room, and", + "it seemed a gash was", + "torn in the very air.", + "Through the gash I", + "could see stars and" + ), + new BookPageInfo( + "swirling clouds of", + "stellar dust, and a", + "coldness sucked all", + "the warmth from the", + "air. A terrible wind", + "tossed books and", + "blankets across the", + "room, and furniture" + ), + new BookPageInfo( + "toppled.", + " From within this", + "gash issued a great", + "voice, unlike any I", + "have ever heard. And", + "these are the words it", + "spoke (for I", + "memorized them most" + ), + new BookPageInfo( + "carefully):", + " \"Greetings, Lord", + "British. I am the", + "Time Lord, a being", + "from beyond your", + "dimension, as thou", + "art from a world", + "other than Sosaria. I" + ), + new BookPageInfo( + "am here to bring thee", + "warning. Dost thou", + "recall how long ago a", + "mysterious Stranger", + "came to Sosaria and", + "saved the world from", + "the evil wizard", + "Mondain? He" + ), + new BookPageInfo( + "shattered the Gem of", + "Immortality, within", + "which dwelled a", + "perfect likeness of", + "this world.\"", + " Lord British slowly", + "stood and faced the", + "hole in the air. \"I" + ), + new BookPageInfo( + "remember,\" he said.", + "\"Oft have I wished", + "that stranger would", + "return.\"", + " \"He hath returned,\"", + "spoke the voice. \"But", + "not to here. When the", + "Gem was shattered, a" + ), + new BookPageInfo( + "thousand shards were", + "scattered across the", + "dimensions, and in", + "each shard there is a", + "perfect likeness of", + "this world. And thou", + "dost live upon one", + "such shard, for thou" + ), + new BookPageInfo( + "art not of the true", + "world-thou art", + "merely a reflection.\"", + " Lord British looked", + "shaken by this, and I", + "did not know what to", + "think! Was I merely a", + "shadow of the real" + ), + new BookPageInfo( + "me, which lives still", + "somewhere else", + "across uncounted", + "universes?", + " \"My task is to heal", + "this shattered world,", + "Lord British,\" said", + "the voice. \"And I seek" + ), + new BookPageInfo( + "to enlist thee in my", + "cause. Be warned that", + "in this case, healing", + "carries with it a", + "terrible price.\"", + " Concern warred", + "with curiosity on my", + "liege's face, but ever" + ), + new BookPageInfo( + "one to shoulder a", + "burden, he", + "straightened and", + "faced the gash in the", + "air bravely. \"Name", + "thy price.\"", + " \"A shard of a", + "universe is a" + ), + new BookPageInfo( + "powerful thing, and a", + "universe shattered is", + "always in danger", + "from the powers of", + "darkness. Already", + "three shards were", + "turned to evil, and", + "sent to plague the" + ), + new BookPageInfo( + "original universe in", + "the form of", + "Shadowlords. Many", + "times have I brought", + "the Stranger back to", + "Britannia, to preserve", + "it from its own folly", + "or from outside" + ), + new BookPageInfo( + "dangers. Yet as long", + "as the world", + "remaineth in pieces,", + "it remaineth", + "vulnerable. We must", + "bring the shards into", + "harmony, so that they", + "resonate in such a" + ), + new BookPageInfo( + "manner that matches", + "the original universe.", + "Then the two", + "universes shall", + "merge, and be again", + "as one.\"", + " \"But if we are only", + "shadows...\" Lord" + ), + new BookPageInfo( + "British said", + "wonderingly.", + " The light from the", + "stars within the hole", + "seemed to dim.", + "\"Indeed, the", + "reflections shall", + "become one with the" + ), + new BookPageInfo( + "original. Thou wouldst", + "cease to be as thou", + "art, and become part", + "of the larger you.", + "Thou shalt not die;", + "however, uncounted", + "generations have", + "passed and borne" + ), + new BookPageInfo( + "children since that", + "day, and they have no", + "counterparts. They", + "would perish utterly.\"", + " Lord British sagged", + "in shock, realizing", + "the terrible price that", + "would be paid to heal" + ), + new BookPageInfo( + "the universe. \"All of", + "my people,\" he", + "breathed.", + " \"'Tis for the greater", + "good.\"", + " Lord British bowed", + "his head.", + " 'Twas then I saw" + ), + new BookPageInfo( + "the movement by the", + "door, half-hid by the", + "heavy red curtains.", + "Lord Blackthorn stood", + "there, concealed from", + "the rest of the room,", + "his face white. How", + "long had he been" + ), + new BookPageInfo( + "listening? I cannot", + "say, yet I suspect", + "that he had heard all", + "that the mysterious", + "voice had to say.", + " \"How then, shall I", + "aid thee?\" Lord", + "British said," + ), + new BookPageInfo( + "weariness in his", + "voice.", + " \"Aid the nobilty that", + "resideth in the", + "human heart. Protect", + "the Virtues that so", + "recently came to thee", + "in thought late at" + ), + new BookPageInfo( + "night. They are the", + "Virtues of life, as", + "your counterpart", + "understands them to", + "be. For when thy", + "populace doth live and", + "breathe these Virtues,", + "shall it match the" + ), + new BookPageInfo( + "true Britannia, and", + "thy shard shall", + "rejoin with it.\"", + " The gash in the air", + "began to close, and", + "with it warmth stole", + "back into the room.", + " \"I was going to" + ), + new BookPageInfo( + "discuss my idea with", + "Blackthorn tonight,\"", + "Lord British", + "breathed. \"Have I no", + "thoughts that are my", + "own? Is my life but", + "a reflection of", + "another me?\"" + ), + new BookPageInfo( + " \"Nay,\" said the", + "voice, smaller through", + "the diminished", + "opening. \"Say, rather,", + "that you are parallel,", + "for there is no", + "guarantee that thou", + "shalt accomplish what" + ), + new BookPageInfo( + "I have set thee to. I", + "speak tonight to a", + "thousand of thee, and", + "ask the same of all.", + "Perhaps not all shall", + "seek to aid me.\" And", + "with that, the gash", + "closed, and the voice" + ), + new BookPageInfo( + "was gone, leaving a", + "room that appeare", + "tossed by a mighty", + "storm.", + " \"Destroy the world", + "to save the universe,\"", + "Lord British said", + "bitterly. \"I do not" + ), + new BookPageInfo( + "wonder that some", + "may balk.\"", + " Lord Blackthorn", + "collected himself, and", + "strode into the room,", + "a decent mimicry of", + "surprise on his face.", + "\"My liege! What has" + ), + new BookPageInfo( + "happened here?\" he", + "exclaimed, feigning", + "dismay well. But not", + "well enough to fool", + "his old friend, whose", + "eyes narrowed at", + "seeing him there.", + " \"How much didst" + ), + new BookPageInfo( + "thou hear?\" demanded", + "Lord British.", + " \"Why, nothing,\"", + "managed Blackthorn,", + "his head ducked away", + "from his friend, as", + "he bent to retrieve the", + "fallen chess pieces. \"I" + ), + new BookPageInfo( + "merely came for our", + "game of chess.\"", + " Together they", + "righted the pedestal", + "table, and set the", + "pieces upon the black", + "and white squares.", + "\"Such simplicity to" + ), + new BookPageInfo( + "the game, Blackthorn,\"", + "mused Lord British,", + "idly brushing one", + "finger against the", + "board. \"Black and", + "white, each to its own", + "color, as if life were", + "so simple. What think" + ), + new BookPageInfo( + "you?\"", + " Blackthorn sat", + "heavily on a hassock", + "beside the chess table.", + "\"I think that matters", + "are never so simple,", + "my liege. And that I", + "would regret it deeply" + ), + new BookPageInfo( + "if someone, such as a", + "friend, saw it thus.\"", + " Lord British's eyes", + "met his. \"Yet", + "sometimes one must", + "sacrifice a pawn to", + "save a king.\"", + " Lord Blackthorn met" + ), + new BookPageInfo( + "his gaze squarely.", + "\"Even pawns have", + "lives and loves at", + "home, my lord.\" Then", + "he reached out for a", + "pawn, and firmly", + "moved it forward two", + "squares. \"Shall we" + ), + new BookPageInfo( + "play a game?\" he", + "asked.", + " The chess game that", + "night was a draw,", + "and they played", + "grimly.", + " And the next day,", + "Lord British gathered" + ), + new BookPageInfo( + "the nobles to proclaim", + "the idea of a new", + "system of Virtues,", + "and declared that", + "shrines should be", + "built across the land.", + " Lord Blackthorn", + "opposed it bitterly," + ), + new BookPageInfo( + "and many thought", + "him strange for doing", + "so, for ever had he", + "been a noble and", + "upright man, and", + "ever had he and Lord", + "British been in", + "accord. Declaring that" + ), + new BookPageInfo( + "he should start his", + "own shrine, he", + "departed the castle", + "that day to live in a", + "tower in a lake on the", + "north side of the", + "city.", + " They are still the" + ), + new BookPageInfo( + "best of friends, yet a", + "sadness hangs", + "between them, as if", + "they were forced into", + "making choices that", + "appealed not to them.", + "And at night, when I", + "creep softly from one" + ), + new BookPageInfo( + "corner of my liege's", + "bedchamber to", + "another, I sometimes", + "see him take a pawn", + "from his night table,", + "and hold it in his", + "hand, and quietly", + "weep." + ), + new BookPageInfo( + " But I am but a", + "mouse, and none hear", + "me. This tale goes", + "unknown, save for", + "my writing these", + "enormous letters with", + "mine ink-stained tiny", + "paws for thee to" + ), + new BookPageInfo( + "read, for I fear", + "indeed for our world", + "and for our people in", + "these perilous times." + ) + ); + + [Constructible] + public MyStory() : base(Utility.Random(0xFEF, 2), false) + { + } + + public MyStory(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class DiversityOfOurLand : BaseBook + { + public static readonly BookContent Content = new BookContent( + "On the Diversity of Our Land", + "Lord Blackthorn", + new BookPageInfo( + " While I deplore the", + "depredations of the", + "misguided and", + "belligerent races with", + "which we share our", + "fair Britannia, and", + "alongside the populace,", + "do mourn the needless" + ), + new BookPageInfo( + "deaths that their", + "raids cause, I cannot", + "countenance the policy", + "of wholesale slaughter", + "of these races that", + "seems to be the habit", + "of our soldierly", + "element." + ), + new BookPageInfo( + " Can we not regard", + "the ratmen, lizard", + "men, and orcs are", + "fellow intelligent", + "beings with whom we", + "share a planet? Why", + "must we slay them", + "on sight, rather than" + ), + new BookPageInfo( + "attempt to engage", + "them in dialogue?", + "There is no policy of", + "shooting at wisps", + "when they grace us", + "with their presence", + "(not that an arrow", + "could do much to" + ), + new BookPageInfo( + "pierce them!).", + " To view these", + "creatures as vermin", + "denies their obvious", + "intelligence, and we", + "cannot underestimate", + "the repercussions", + "that their slaughter" + ), + new BookPageInfo( + "may have. If we", + "regard the slaying of", + "fellow humans as a", + "crime, so must we", + "regard the killing of", + "an orc.", + " At the same time,", + "should a lizardman" + ), + new BookPageInfo( + "slay a human, should", + "we not forgive their", + "ignorance and", + "foolishness? Let us", + "not surrender the", + "high moral ground by", + "descending to", + "bestiality." + ), + new BookPageInfo( + " Now, I say not that", + "we should fail to", + "defend ourselves in", + "case of attack, for", + "even amongst humans", + "we see war, we see", + "famine, and we see", + "assault (though we" + ), + new BookPageInfo( + "owe a debt of", + "gratitude to our Lord", + "British for", + "preserving us from", + "the worst of these!).", + "However, incursions", + "such as the recent", + "tragedy which cost us" + ), + new BookPageInfo( + "the life of Japheth,", + "Guildmaster of", + "Trinsic's Paladins,", + "are folly.", + " I had met Japheth,", + "and like all paladins,", + "he burned with an", + "inner fire. Yet" + ), + new BookPageInfo( + "though I had the", + "utmost respect for", + "him, none could deny", + "the hatred that", + "flashed in his eyes at", + "the mere mention of", + "orcs. And thus he", + "carried his battle to" + ), + new BookPageInfo( + "the orc camps, and", + "died there, unable to", + "rise above his own", + "childhood experiences", + "depicted in his book,", + "\"The Burning of", + "Trinsic.\" 'Tis a", + "shame that even our" + ), + new BookPageInfo( + "mightiest men fall", + "prey to this", + "ignorance!", + " Are there not", + "legends of orcs", + "adopting human", + "children to raise as", + "their own? Tales of" + ), + new BookPageInfo( + "complex societies built", + "underground by races", + "we regard as bestial?", + " Let us not repeat", + "the mistake of", + "Japheth of the", + "Paladins, and let us", + "cease to persecute the" + ), + new BookPageInfo( + "nonhuman races,", + "before we discover", + "that we are harming", + "ourselves in the", + "process." + ) + ); + + [Constructible] + public DiversityOfOurLand() : base(Utility.Random(0xFEF, 2), false) + { + } + + public DiversityOfOurLand(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class QuestOfVirtues : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Quest of the Virtues", + "Autenil", + new BookPageInfo( + "Volume 1", + "Chapter 1: Starting out", + "I begin my Quest in the", + "fine bank of Skara Brae.", + "My Quest is to travel by", + "foot to the eight shrines", + "of Britannia. Although", + "this may sound easy, it" + ), + new BookPageInfo( + "is hampered because I", + "have forsaken my abilities", + "and worldly possessions.", + "Instead, all that I have", + "to live by are a set of", + "plain clothes, a ship to", + "sail the seas and my", + "diary in which to record" + ), + new BookPageInfo( + "my adventures. Onward", + "Ho towards the Shrine of", + "Spirituality!", + "", + "Chapter 2: The Road to", + "Spirituality", + "", + "Since I have forsaken" + ), + new BookPageInfo( + "magic as a form of", + "travel, I must find a way", + "to the mainland from this", + "island town. Fortunately,", + "I was able to barter a", + "ride from the ferryman.", + "Upon reaching the", + "mainland, I followed the" + ), + new BookPageInfo( + "road until it turned", + "North, yet I must", + "continue Eastward. I", + "paused to listen to the", + "pleasant sounds of the", + "birds chirping and enjoyed", + "the peace away from the", + "busy life. Upon reaching" + ), + new BookPageInfo( + "the Hedge Maze I recalled", + "a story about the mage", + "Relvinian in the days of", + "old and turned South to", + "go around it. Possessing", + "no weapons and having", + "forsaken my training, I", + "heeded the sign that said," + ), + new BookPageInfo( + "\"Enter and Become One", + "Among Ghosts.\" The River", + "forced me to turn South", + "and then continue East.", + "", + "Chapter 3: Spirituality", + "", + "Spirituality is the leader" + ), + new BookPageInfo( + "of the Virtues. It is the", + "meditation and", + "understanding of all other", + "Virtues. Without", + "Spirituality, one cannot", + "completely follow the", + "Virtues, for It is the", + "dedication and adherance" + ), + new BookPageInfo( + "to them.", + "", + "Chapter 4: Finding Honor", + "", + "My next visit will be to", + "the Shrine of Honor,", + "which lies a fair distance", + "to the South. There is a" + ), + new BookPageInfo( + "road to my East that I", + "will follow to the town", + "of Trinsic. I found a", + "warm room at the", + "Traveller's Inn, and woke", + "refreshed in the morning", + "to hear the sounds of", + "nature as I prepared to" + ), + new BookPageInfo( + "continue my journeys. I", + "thanked the kind innkeeper", + "and headed out of Trinsic", + "and South. I conversed", + "briefly with one lucky", + "enough to own a house in", + "the beautiful country and", + "he bade me good fortune" + ), + new BookPageInfo( + "on my travels. I used my", + "rusty blade to cut", + "through dense jungles", + "past ruins of a forgotten", + "realm, now inhabited only", + "by the Undead. Many a", + "mongbat did hamper my", + "journey, but finally I" + ), + new BookPageInfo( + "arrived at the Shrine of", + "Honor.", + "", + "Chapter 5: Honor", + "", + "Many link Honor and", + "battle, but it can be", + "used with any aspect of" + ), + new BookPageInfo( + "Life. Honor is to abide", + "by the rules, dishonor is", + "to cheat; to seek the", + "unfair advantage. I vowed", + "to always live life with", + "Honor.", + "", + "Chapter 6: Seeking Valor" + ), + new BookPageInfo( + "I must now embark on my", + "trusty small ship, the", + "Hollandia, to the South", + "and East, to a small", + "island where few have", + "travelled. I know not yet", + "what I will encounter at", + "sea, so I bid the Virtues" + ), + new BookPageInfo( + "grant me safety. So", + "begins my voyage. I", + "managed to sail unnoticed", + "past some water", + "elementals which took a", + "fair bit of navigation", + "from my tillerman.", + "However, I arrived without" + ), + new BookPageInfo( + "incident.", + "", + "Chapter 7: Valor", + "", + "The Shrine of Valor is", + "protected by many a", + "beast far too poisonous", + "and foul for myself to" + ), + new BookPageInfo( + "vanquish. One mush show", + "Valor to approach the", + "Shrine! Valor is often", + "shown in one's willingness", + "to fight what maybe a", + "losing battle upon which", + "he believes. It takes", + "Valor to stand your" + ), + new BookPageInfo( + "ground against the many", + "murderers and lawbreakers", + "in our lands. You may", + "lose, but you show Valor", + "in that you fight that", + "which must be opposed.", + "Fight the fights you", + "believe in, not just the" + ), + new BookPageInfo( + "fights you think you can", + "win.", + "", + "Chapter 8: The Voyage to", + "Humility", + "", + "My journey will continue", + "to the East towards the" + ), + new BookPageInfo( + "Shrine of Humility. I", + "launch my boat from the", + "West side of the Island", + "of Valor, where I made", + "my daring escape from", + "the many Giant Serpents", + "chasing me with their", + "poisonous venom and" + ), + new BookPageInfo( + "hissing tongues. Beautiful", + "blue waves washed over", + "the bow of the boat as", + "dolphins played, merrily", + "leading me on. The voyage", + "is long and the water", + "turbulent but finally land", + "was struck. Quickly I ran," + ), + new BookPageInfo( + "eager to find my final", + "destination for the day.", + "", + "Chapter 9: Humility", + "", + "The Shrine of Humility is", + "surprisingly spartan; it is", + "merely a grove of stone" + ), + new BookPageInfo( + "pillars with an ankh and", + "the Humility stone at its", + "center. I would", + "characterize Humility as", + "this Quest; returning to", + "my roots in this world. I", + "have rejected my", + "possessions and my wealth" + ), + new BookPageInfo( + "in order to rely only", + "upon my cunning and", + "instincts. No longer have", + "I that which makes me", + "Glorious to others, but I", + "have only that which I", + "need to survive. I may no", + "longer rely upon myself, I" + ), + new BookPageInfo( + "must rely upon others", + "for my survival. My", + "journey to Humility has", + "only made me realize even", + "more how Blessed I have", + "been." + ), + new BookPageInfo( + "Chapter 10: Onward to", + "Honesty", + "", + "Now the journey will turn", + "South towards the Island", + "of Ice. However, my", + "voyages and excursions", + "into the jungle have made" + ), + new BookPageInfo( + "me quite tired, so I will", + "camp here beside a river", + "near the Shrine of", + "Humility for the night. I", + "awake the next morning", + "refreshed and invigorated,", + "but also under attack! A", + "Headless One has noticed" + ), + new BookPageInfo( + "my rise from slumber and", + "attacks viciously. My", + "trusty cleaver was in my", + "hand instantly, but my", + "lack of skill with the", + "weapon delayed the death", + "of the creature. I", + "launched the Hollandia and" + ), + new BookPageInfo( + "set sail for the Island of", + "Ice, seeking the Shrine of", + "Honesty. As I sail the", + "vast oceans, I find myself", + "desiring the company of", + "my fellow man. Hopefully I", + "shall meet some kind of", + "traveller with whom I may" + ), + new BookPageInfo( + "exchange a few words.", + "Shortly I was landing my", + "boat on the North end of", + "the Island of Ice. I", + "quickly made my way", + "through snow across the", + "frigid tundra while trying", + "to keep warm. The Shrine" + ), + new BookPageInfo( + "of Honesty bid me", + "welcome as I felth the", + "warmth radiate throughout", + "me.", + "", + "Chapter 11: Honesty", + "", + "Honesty is to uphold and" + ), + new BookPageInfo( + "defend the truth at all", + "times. Furthermore,", + "Honesty requires us to", + "be fair and true to our", + "fellow man; not taking", + "undue advantage. Honesty", + "is a Virtue often lacking", + "in today's world. It seems" + ), + new BookPageInfo( + "as though people are out", + "to gain wealth with no", + "regard to Honesty", + "towards other people.", + "Honesty is the foundation", + "upon which trust is built.", + "If the foundation", + "crumbles, everything built" + ), + new BookPageInfo( + "upon it must fall. The", + "cold environment which", + "houses the Shrine of", + "Honesty is a testament", + "to its value in today's", + "society. The symbolic cold", + "and secluded location", + "shows us that only the" + ), + new BookPageInfo( + "most dedicated to", + "pursuing Honesty will", + "achieve it. May we all be", + "Honest with our fellow", + "man and remember to", + "treat them how we would", + "like to be treated." + ), + new BookPageInfo( + "Chapter 12: The Path to", + "Sacrifice.", + "", + "I made my way to the", + "West side of the Island", + "of Ice. From there I", + "launch the Hollandia and", + "sail slightly to the North" + ), + new BookPageInfo( + "and West. I land my boat", + "just East of the Shrine", + "of Sacrifice, so my road", + "is West. Although I enjoy", + "the sea, I am happy to", + "be back on the mainland", + "for the final three", + "Shrines." + ) + ); + + [Constructible] + public QuestOfVirtues() : base(Utility.Random(0xFEF, 2), false) + { + } + + public QuestOfVirtues(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class RegardingLlamas : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Regarding Llamas", + "Simon", + new BookPageInfo( + " Llamas are curious", + "beasts, shaggy and", + "sought after for their", + "wool, yet of a", + "curiously arrogant", + "disposition reflected", + "in their eyes. They", + "live in mountainous" + ), + new BookPageInfo( + "areas, though who", + "may have first tamed", + "them is lost in the", + "mists of history.", + " 'Tis a well-known", + "fact that llamas can", + "indeed be tamed, and", + "used as grazing" + ), + new BookPageInfo( + "animals, for their", + "meat, and of course", + "for their wool. Yet", + "'tis lesser known that", + "their ornery", + "disposition and", + "tendency to spit at", + "those they dislike" + ), + new BookPageInfo( + "makes them appealing", + "guard creatures as", + "well, though they", + "have little sound with", + "which to sound an", + "alarum." + ) + ); + + [Constructible] + public RegardingLlamas() : base(Utility.Random(0xFEF, 2), false) + { + } + + public RegardingLlamas(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class TalkingToWisps : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Talking to Wisps", + "Yorick ofMoonglow", + new BookPageInfo( + "This volume was", + "sponsored by", + "donations from Lord", + "Blackthorn, ever a", + "supporter of", + "understanding the", + "other sentient races", + "of Britannia." + ), + new BookPageInfo( + "-", + " Wisps are the most", + "intelligent of the", + "nonhuman races", + "inhabiting Britannia.", + "'Tis claimed by the", + "great sages that", + "someday we shall be" + ), + new BookPageInfo( + "able to converse with", + "them openly in our", + "native", + "tongue--indeed, we", + "must hope that wisps", + "learn our language,", + "for it is not possible", + "for humans to" + ), + new BookPageInfo( + "pronounce wispish!", + " The wispish", + "language seems to", + "only contain one", + "vowel, the letter Y.", + "However, the letters", + "W, C, M, and L seem", + "to be treated" + ), + new BookPageInfo( + "grammatically as", + "vowels, and in", + "addition every letter", + "is followed by what", + "sounds to the human", + "ear like a glottal stop.", + "It is possible that the", + "glottal stop is" + ), + new BookPageInfo( + "considered a vowel as", + "well.", + " Wisps do make use", + "of what sound to us", + "like pitch and", + "emphasis shifts", + "similar to", + "exclamations and" + ), + new BookPageInfo( + "questions.", + " The average word is", + "wispish seems to", + "consist of three", + "phonemes and three", + "glottal stops, plus", + "possibly a pitch shift.", + "It often sounds like a" + ), + new BookPageInfo( + "fire burning or", + "crackling. Some have", + "speculated that what", + "we are analyzing is", + "in fact nothing more", + "than the very air", + "crackling near the", + "wisp's glow, and not" + ), + new BookPageInfo( + "language, but this is", + "of course unlikely." + ) + ); + + [Constructible] + public TalkingToWisps() : base(Utility.Random(0xFEF, 2), false) + { + } + + public TalkingToWisps(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class TamingDragons : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Taming Dragons", + "Wyrd Beastmaster", + new BookPageInfo( + " I have not much to", + "tell about dragons. The", + "sole time I approached", + "one with an eye", + "towards taming it,", + "my initial attempts at", + "calming it met with", + "failure. It fixed a" + ), + new BookPageInfo( + "massive beady eye", + "upon me, and began", + "its slithering", + "approach, intending no", + "doubt to insert me", + "into its maw and bear", + "down with its teeth.", + " However, as I was" + ), + new BookPageInfo( + "engaged in what", + "remains to this day", + "the most terrifying", + "combat of my life,", + "the dragon suddenly", + "whirled as if in a", + "panic, ran a short", + "distance, took off into" + ), + new BookPageInfo( + "the air, then", + "transformed into a", + "whirlwind. Lastly, it", + "exploded, showering", + "gouts of black blood", + "and heaving, stinking", + "flesh upon miles of", + "countryside. The" + ), + new BookPageInfo( + "fireball was massive,", + "enough to light a city,", + "I should surmise.", + " I never did discover", + "the exact cause of", + "this strange behavior,", + "except to assume that", + "it was not typical for" + ), + new BookPageInfo( + "this reptilian species.", + "My best guesses", + "revolve around a", + "magical fracture in", + "the nature of reality,", + "which is far too", + "esoteric a territory", + "for one of my limited" + ), + new BookPageInfo( + "scholarship.", + " Hence my basic", + "advice to those who", + "seek to tame a", + "dragon-be sure that", + "thou hast mastered", + "the twin skills of", + "taming animals, and" + ), + new BookPageInfo( + "running away very", + "very fast." + ) + ); + + [Constructible] + public TamingDragons() : base(Utility.Random(0xFEF, 2), false) + { + } + + public TamingDragons(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class BoldStranger : BaseBook + { + public static readonly BookContent Content = new BookContent( + "The Bold Stranger", + "Old Fabio the Poor", + new BookPageInfo( + " In a time before", + "time, the Gods that Be", + "assembled a group of", + "artisans, craftsmen", + "and lore masters", + "(for, yes, even in", + "those days, art", + "existed) to create the" + ), + new BookPageInfo( + "world of Sosaria. To", + "this group, the gods", + "gave a tiny world,", + "Rytabul, in which to", + "test their works, to", + "see if they were of", + "the quality desired", + "for the true world in" + ), + new BookPageInfo( + "which they would be", + "placed. And though", + "the gods were tight", + "fisted with their gold,", + "this small crew", + "worked hard and long,", + "and were happy in", + "their tasks." + ), + new BookPageInfo( + " A small corner of", + "Rytabul had been", + "claimed by the artisan", + "Selrahc the Slow.", + "Though he was not", + "the fastest of the", + "assembled workers,", + "the gods smiled upon" + ), + new BookPageInfo( + "his work, even", + "presenting him with", + "a mystic talisman", + "proclaiming his work", + "the best among the", + "newer artisans. And", + "so Selrahc went about", + "his business, creating" + ), + new BookPageInfo( + "hundreds of designs", + "which would one day", + "add color and variety", + "to Sosaria.", + " One day a", + "stranger appeared to", + "Selrahc. His chest", + "was bare and he wore" + ), + new BookPageInfo( + "trousers of the", + "brightest green, and", + "wherever he went,", + "plants grew in his", + "footsteps. This", + "caused Selrahc no end", + "of trouble, the", + "stranger always" + ), + new BookPageInfo( + "looking over his", + "shoulder, and the", + "plants sprouting in", + "places Selrahc", + "required to ply his", + "art. And so Selrahc", + "approached the", + "stranger and bade" + ), + new BookPageInfo( + "him speak. But this", + "man in green", + "remained silent.", + "Selrahc pleaded with", + "the stranger to give", + "his name, and would", + "he please leave", + "Selrahc to his work." + ), + new BookPageInfo( + "But this mysterious", + "stranger remained", + "mute.", + " This angered", + "Selrahc mightily. Who", + "was this silent man,", + "interfering with", + "tasks the gods" + ), + new BookPageInfo( + "themselves had", + "entrusted to Selrahc?", + "In an attempt to", + "embarrass this", + "interloper, Selrahc", + "stole his green", + "trousers, leaving him", + "naked and open to" + ), + new BookPageInfo( + "comments about his", + "very manhood, and", + "still the stranger", + "would not speak,", + "would not leave this", + "tiny corner of", + "Rytabul.", + " Vexed to his very" + ), + new BookPageInfo( + "limits, Selrahc took", + "his war axe and", + "smote the silent one", + "mightily, again and", + "again, until the silent", + "stranger ran away,", + "having never said a", + "word, and never" + ), + new BookPageInfo( + "showed himself in", + "Rytabul again.", + " Thus endeth the", + "tale of the bold", + "stranger." + ) + ); + + [Constructible] + public BoldStranger() : base(Utility.Random(0xFEF, 2), false) + { + } + + public BoldStranger(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class BurningOfTrinsic : BaseBook + { + public static readonly BookContent Content = new BookContent( + "The Burning of Trinsic", + "Japheth of Trinsic", + new BookPageInfo( + " 'Twas a sight to", + "see, the sunlight", + "falling lightly on the", + "sandstone walls of", + "Trinsic 'pon a", + "morning in spring.", + " Children ran along", + "the parapets and" + ), + new BookPageInfo( + "walkways, their", + "laughter and running", + "providing music to the", + "daybreak, despite", + "their oft-ragged", + "clothing.", + " And I was one of", + "those young ones," + ), + new BookPageInfo( + "letting my joy rise", + "up to the skies.", + " Little did we all", + "know of the darker", + "days that would lie", + "ahead, for we were", + "too young.", + " Had we but gained" + ), + new BookPageInfo( + "access to the quiet", + "councils held in the", + "Paladin tower as it", + "faced the sea,", + "councils lit by", + "candlelight and", + "worry, we would", + "have learned more of" + ), + new BookPageInfo( + "the fears of", + "imminent attack from", + "the forest, where", + "foul creatures born", + "of dank caves and", + "darkness were", + "marauding ever more", + "often into the lands" + ), + new BookPageInfo( + "around Trinsic's", + "moat.", + " But we were", + "children! The", + "parapets and the moat", + "were places to play,", + "not stout defenses,", + "and we gave no" + ), + new BookPageInfo( + "thought to the", + "necessities that must", + "have required their", + "construction.", + " We used to reach", + "the sheltered", + "orchards on the lee", + "side of the parapet" + ), + new BookPageInfo( + "walls, where the", + "southern river cut", + "through the city, by", + "swimming across the", + "water.", + " The rich folk who", + "lived in the great", + "manses there would" + ), + new BookPageInfo( + "shout from their", + "windows and shake", + "their fists, for we", + "would run through", + "their gardens and", + "tear up the delicate", + "foxgloves and", + "orfleurs with our" + ), + new BookPageInfo( + "unshod dirty feet.", + "Then we would dive", + "into the water and", + "splash merrily to the", + "fruit trees.", + " The southern", + "river lazily slid", + "under the an ungated" + ), + new BookPageInfo( + "arch in the mighty", + "wall, and we would", + "lay on the grassy", + "bank and watch it", + "gurgle by the lily", + "pads.", + " That spring that", + "pleasant spot became" + ), + new BookPageInfo( + "the doorway through", + "which our city of", + "Trinsic let in the", + "monstrous deformed", + "humanoids that", + "savaged us. I lay upon", + "that grassy bank and", + "watched them wade" + ), + new BookPageInfo( + "in, their coarse hair", + "wet and matted, algae", + "and muck festooning", + "their wild brows.", + " They caught sight", + "of a quicksilver girl", + "with bright blond hair", + "and lively eyes. Her" + ), + new BookPageInfo( + "name was Leyla, and", + "that spring I had held", + "fond dreams of", + "holding her hand and", + "sharing flavored ice", + "while dangling our", + "feet off the small", + "bridge by Smugglers" + ), + new BookPageInfo( + "Gate.", + " And I said nothing", + "when they caught", + "her, and did not cry", + "out when they", + "dragged her off", + "through that breach in", + "our wall, and did not" + ), + new BookPageInfo( + "warn the city when I", + "saw the helmeted orc", + "captains call the", + "charge upon the", + "mansions.", + " Blame me not, for", + "I was but a child, and", + "one who hid in the" + ), + new BookPageInfo( + "branches of the peach", + "trees, all a-tremble", + "whilst I watched the", + "smoke rise from Sean", + "the tailor's, and fire", + "lash out at the roof of", + "witchy Eleanor's", + "tavern." + ), + new BookPageInfo( + " To this day I have", + "had no word of", + "Leyla, and to this", + "day the smell of", + "burning wood can", + "conjure terrible", + "dreams. Yet with the", + "eyes of adulthood, 'tis" + ), + new BookPageInfo( + "possible to examine", + "the flaws in the", + "defense of Trinsic on", + "that fateful day, and", + "the reasons why our", + "walls are now", + "double-thick, and", + "why our buildings" + ), + new BookPageInfo( + "are now built as", + "fortresses within a", + "somber fortified city.", + " While I can look", + "out from the top of", + "the new Paladin", + "tower, and spy the", + "mighty white sails" + ), + new BookPageInfo( + "across the barrier", + "island, and can", + "descry the small", + "hollow south of the", + "city where gypsies", + "are wont to camp, I", + "can also envision the", + "city as it might be" + ), + new BookPageInfo( + "burning, and I bless", + "the bargain we made:", + "space for safety,", + "grace for sturdiness,", + "and wood for stone.", + " Whilst I live, I", + "shall not see Trinsic", + "burn, and no more" + ), + new BookPageInfo( + "cries of little girls", + "will haunt the sleep", + "of our fair citizens.", + " - Japheth, Paladin", + "Guildmaster of the", + "City of Trinsic" + ) + ); + + [Constructible] + public BurningOfTrinsic() : base(Utility.Random(0xFEF, 2), false) + { + } + + public BurningOfTrinsic(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class TheFight : BaseBook + { + public static readonly BookContent Content = new BookContent( + "The Fight", + "M. de la Garza", + new BookPageInfo( + " A cold autumn's", + "morning with misty", + "fog secures a dozen", + "brave knights,", + "supplying hidden", + "shelter from prying", + "eyes deep in the", + "foothills of the" + ), + new BookPageInfo( + "vibrant valley.", + "Dragons soar like", + "fierce warriors,", + "circling around and", + "around, then roaring", + "like thunder, rallying", + "all that listen. The", + "dragons land swiftly" + ), + new BookPageInfo( + "beside the proud", + "warriors, bending", + "necks and extending", + "wings, lifting black", + "claws and allowing", + "valiant fighters to", + "ride forth and win an", + "arisen battle. The" + ), + new BookPageInfo( + "increasing winds", + "silence the sounds of", + "combat, and they", + "fight, standing their", + "ground like mothers", + "protecting their", + "childern, bright", + "armor flashing as" + ), + new BookPageInfo( + "each one falls.", + " A cold autumn's", + "evening with misty", + "fog cradles a dozen", + "battered corpses of", + "knights, creasing", + "them in currents of", + "winds that run deep" + ), + new BookPageInfo( + "in the foothills of the", + "desolate valley.", + "Dragons glide like", + "silent angels, circling", + "around and around,", + "then calling like", + "banshees; keening", + "cries of mourning." + ), + new BookPageInfo( + "The dragons land", + "heavily beside the", + "peaceful bodies,", + "bending necks and", + "extending wings,", + "lifting black claws", + "and allowing valiant", + "fighters to ride forth" + ), + new BookPageInfo( + "and win an arisen", + "battle. The increasing", + "winds silence the", + "sounds of combat, and", + "they fight, standing", + "their ground like", + "mothers protecting", + "their childern, bright" + ), + new BookPageInfo( + "armor flashing as", + "each one falls.", + " A cold autumn's", + "evening with misty", + "fog cradles a dozen", + "battered corpses of", + "knights, creasing", + "them in currents of" + ), + new BookPageInfo( + "winds that run deep", + "in the foothills of the", + "desolate valley.", + "Dragons glide like", + "silent angels, circling", + "around and around,", + "then calling like", + "banshees; keening" + ), + new BookPageInfo( + "cries of mourning.", + "The dragons land", + "heavily beside the", + "peaceful bodies,", + "bending necks and", + "extending wings,", + "lifting black claws", + "and pinching the" + ), + new BookPageInfo( + "sacred ground and", + "new eternal home.", + "The dying winds", + "whistle among the", + "dead in somber", + "procession, and they", + "lie, grasping weapons", + "to protect themselves" + ), + new BookPageInfo( + "like knights still in", + "battle, shattered", + "armor shining like", + "newly born stars." + ) + ); + + [Constructible] + public TheFight() : base(Utility.Random(0xFEF, 2), false) + { + } + + public TheFight(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class LifeOfATravellingMinstrel : BaseBook + { + public static readonly BookContent Content = new BookContent( + "The Life of a Travelling Minstrel", + "Sarah of Yew", + new BookPageInfo( + " While 'tis true that", + "the musician who", + "seeketh only to make", + "sweet music for", + "herself and for", + "others needs little", + "more than some", + "talent, and stern" + ), + new BookPageInfo( + "practice at the chosen", + "instrument, those of", + "us who seek the open", + "road shall find indeed", + "that a greater skill is", + "required. Herein", + "discover those secrets", + "which I have learned" + ), + new BookPageInfo( + "over the years as an", + "itinerant performer...", + " Once I was in", + "Jhelom, and", + "accidentally angered a", + "bravo of some local", + "repute, whose blade", + "flickered all too" + ), + new BookPageInfo( + "eagerly near my", + "slender neck (for I", + "was young then).", + "After various threats", + "to \"ruin my pretty", + "face\" this bravo", + "grabbed my arm in a", + "most unseemly" + ), + new BookPageInfo( + "fashion and tossed", + "me into a barbaric", + "enclosure locally", + "entitled a dueling pit.", + "My plaintive cries", + "for help went", + "unheeded by the", + "guards, for the" + ), + new BookPageInfo( + "inhabitants of Jhelom", + "are eager indeed to", + "measure fighting", + "prowess at any time!", + " What saved me was", + "the ability to", + "improvise a melody", + "and tune that" + ), + new BookPageInfo( + "satirized the", + "proceedings, and", + "sufficiently angered", + "an onlooker to prod", + "him to coming to my", + "defense. Once that", + "fight was underway,", + "I was able to make" + ), + new BookPageInfo( + "good my escape.", + "Hence, I regard the", + "ability to incite fights", + "as indispensable to", + "the prudent bard.", + " Upon another", + "occasion, 'twas the", + "obverse side of that" + ), + new BookPageInfo( + "coin which saved me,", + "for I was being held", + "prisoner by a", + "particularly nasty", + "band of ruffians who", + "had seized me", + "unawares from the", + "road to Vesper." + ), + new BookPageInfo( + " They had worked", + "themselves into a", + "frenzy and were", + "ready to attack and I", + "fear, tear me limb", + "from limb, when I", + "began to sing", + "frantically, tapping" + ), + new BookPageInfo( + "my falled drum with", + "my tied up feet. The", + "melody developed into", + "a soothing one, and", + "the brigands slowly", + "calmed down to the", + "extent of apologizing,", + "and they let me go!" + ), + new BookPageInfo( + " A final example I", + "would pray you grant", + "your attention: once I", + "was lost upon a large", + "isle far to the east of", + "the mainland, well", + "beyond Serpent's", + "Hold, where lava" + ), + new BookPageInfo( + "made its sluggish", + "way across the", + "surface landscape.", + "And this accursed", + "land was filled with", + "vile beasts and", + "cunning dragons.", + " I was being pursued" + ), + new BookPageInfo( + "by one of said fell", + "dragons when I found", + "myself trapped. I", + "quickly skirted a", + "bubbling pool of molten", + "rock and attempted to", + "hide.", + " The dragon scented" + ), + new BookPageInfo( + "me and was", + "preparing to skirt the", + "pool, when I began to", + "play a lusty tune", + "upon my lute that", + "attracted its attention.", + "Mesmerized and", + "enticed by the" + ), + new BookPageInfo( + "melody, it stepped", + "directly toward sme,", + "and into the", + "lava-where its foot", + "was so burned that it", + "quickly hopped away,", + "undignified and", + "annoyed." + ), + new BookPageInfo( + " 'Tis my fond hope", + "that other travelling", + "minstrels shall learn", + "from my experiences", + "and apply themselves", + "to practicing these", + "skills in order to", + "preserve life and" + ), + new BookPageInfo( + "limb." + ) + ); + + [Constructible] + public LifeOfATravellingMinstrel() : base(Utility.Random(0xFEF, 2), false) + { + } + + public LifeOfATravellingMinstrel(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class MajorTradeAssociation : BaseBook + { + public static readonly BookContent Content = new BookContent( + "The Major Trade Associations", + "Pieter of Vesper", + new BookPageInfo( + " There are ten major", + "trade associations that", + "operate legitimately in", + "the lands of Britannia", + "and among its trading", + "partners. Many of", + "these guilds are", + "divided into local or" + ), + new BookPageInfo( + "specialty subguilds,", + "who use the same", + "colors but vary the", + "heraldic pattern.", + " There are many", + "lesser trade", + "associations that have", + "closed membership," + ), + new BookPageInfo( + "and one can join them", + "only by invitation.", + "Beltran's Guide to", + "Guilds is the", + "definitive text on the", + "full range of guilds", + "and other associations", + "in Britannia, and I" + ), + new BookPageInfo( + "heartily recommend", + "it.", + " In what follows I", + "have attempted to", + "bring together the", + "known information", + "regarding these", + "guilds. I offer thee" + ), + new BookPageInfo( + "the name, typical", + "membership, heraldic", + "colors, known", + "specialty", + "organizations within", + "the larger guild, and", + "any known", + "affiliations to other" + ), + new BookPageInfo( + "guilds, which often", + "occur because of", + "trade reasons.", + "", + "The Guild of Arcane", + "Arts", + "Members: alchemists", + "and wizards" + ), + new BookPageInfo( + "Colors: blue and purple", + "Subguilds: Illusionists,", + "Mages, Wizards", + "Affiliations: Healer's", + "Guild", + "", + "The Warrior's Guild", + "Members:" + ), + new BookPageInfo( + "mercenaries,", + "soldiery, guardsmen,", + "weapons masters,", + "paladins.", + "Colors: Blue and red", + "Subguilds: Cavalry,", + "Fighters, Warriors", + "Affiliations: League" + ), + new BookPageInfo( + "of Rangers", + "", + "League of Rangers", + "Members: rangers,", + "bowyers, animal", + "trainers", + "Colors: Red, gold and", + "blue" + ), + new BookPageInfo( + "", + "Guild of Healers", + "Members: healers", + "Colors: Green, gold,", + "and purple", + "Affiliations: Guild of", + "Arcane Arts" + ), + new BookPageInfo( + "Mining Cooperative", + "Members: miners", + "Colors: blue and black", + "checkers, with a gold", + "cross", + "Affiliations: Order of", + "Engineers" + ), + new BookPageInfo( + "Merchants'", + "Association", + "Members:", + "innkeepers,", + "tavernkeepers,", + "jewelers,", + "provisioners", + "Colors: gold coins on a" + ), + new BookPageInfo( + "green field for", + "Merchants. White", + "and green for the", + "others.", + "Subguilds: Barters,", + "Provisioners,", + "Traders, Merchants" + ), + new BookPageInfo( + "Order of Engineers", + "Members: tinkers and", + "engineers", + "Colors: Blue, gold, and", + "purple vertical bars", + "Affiliations: Mining", + "Cooperative" + ), + new BookPageInfo( + "Society of Clothiers", + "Members: tailors and", + "weavers", + "Colors: Purple, gold,", + "and red horizontal", + "bars", + "", + "Maritime Guild" + ), + new BookPageInfo( + "Members: fishermen,", + "sailors, mapmakers,", + "shipwrights", + "Colors: blue and white", + "Subguilds:", + "Fishermen, Sailors,", + "Shipwrights" + ), + new BookPageInfo( + "Bardic Collegium", + "Members: bards,", + "musicians,", + "storytellers, and other", + "performers", + "Colors: Purple, red", + "and gold checkerboard" + ), + new BookPageInfo( + "Society of Thieves", + "Members: beggars,", + "cutpurses, assassins,", + "and brigands", + "Colors: red and black", + "Subguilds: Rogues", + "(beggars), Assassins,", + "Thieves" + ) + ); + + [Constructible] + public MajorTradeAssociation() : base(Utility.Random(0xFEF, 2), false) + { + } + + public MajorTradeAssociation(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class RankingsOfTrades : BaseBook + { + public static readonly BookContent Content = new BookContent( + "The Rankings of Trades", + "Lord Higginbotham", + new BookPageInfo( + " Whilst 'tis true that", + "within each trade, one", + "finds differing titles", + "and accolades granted", + "to the members of a", + "given guild,", + "nonetheless for the", + "betterment of trade" + ), + new BookPageInfo( + "and understanding,", + "we must have a", + "commonality of", + "titling.", + " For those who may", + "find themselves", + "ignorant of the finer", + "distinctions between a" + ), + new BookPageInfo( + "three-knot member of", + "the Sailors' Maritime", + "Association and a", + "second thaumaturge,", + "this book shall serve", + "as a simple", + "introduction to the", + "common cant used" + ), + new BookPageInfo( + "when members of", + "differing guilds and", + "trade organizations", + "must trade with each", + "other and must", + "establish relative", + "credentials.", + " Neophyte" + ), + new BookPageInfo( + "Has shown interest", + "in learning the craft", + "and some meager", + "talent.", + " Novice", + "Is practicing basic", + "skills but has not been", + "admitted to full" + ), + new BookPageInfo( + "standing.", + " Apprentice", + "A student of the", + "discipline.", + " Journeyman", + "Warranted to practice", + "the discipline under", + "the eyes of a tutor." + ), + new BookPageInfo( + " Expert", + "A full member of the", + "guild.", + " Adept", + "A member of the", + "guild qualified to", + "teach others.", + " Master" + ), + new BookPageInfo( + "Acknowledged as", + "qualified to lead a hall", + "or business.", + " Grandmaster", + "Rarely a permanent", + "title, granted in", + "common parlance to", + "those who have" + ), + new BookPageInfo( + "shown extreme", + "mastery of their", + "craft recently." + ) + ); + + [Constructible] + public RankingsOfTrades() : base(Utility.Random(0xFEF, 2), false) + { + } + + public RankingsOfTrades(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class WildGirlOfTheForest : BaseBook + { + public static readonly BookContent Content = new BookContent( + "The Wild Girl of the Forest", + "Horace the Trader", + new BookPageInfo( + " Her name was", + "Leyla, she said, and", + "her hair was braided", + "wild with creepers", + "and thorns. I", + "marveled that they", + "did not hurt her, but", + "when I asked, she but" + ), + new BookPageInfo( + "shrugged and let her", + "eyes roam once more", + "across the woods.", + "Though I had my", + "hands securely", + "fastened by her", + "ropes, I itched to", + "reach out and comb" + ), + new BookPageInfo( + "that unruly golden", + "mane, dirtied and", + "leaf-ridden.", + " Her provenance,", + "she told me over", + "nights illumined by", + "campfires, was once", + "the city of Trinsic." + ), + new BookPageInfo( + "She claimed to have", + "been kidnapped and", + "raised by orcs, which", + "I judged an unlikely", + "tale, for all know orcs", + "delight in eating the", + "meat of honest folk.", + "When I told her this," + ), + new BookPageInfo( + "she laughed a fey", + "laugh, and gaily", + "admitted that honest", + "she was not, for oft", + "had she stolen folk", + "away from caravans", + "to loot their", + "possessions from an" + ), + new BookPageInfo( + "unconscious body!", + " At this, I began to", + "fear for my life, and", + "her smile seemed full", + "of teeth sharper than", + "a human ought to", + "have, for the tale of", + "orcish raising had" + ), + new BookPageInfo( + "struck fear into the", + "marrow of my bones.", + "\"Wilt thou eat me?\" I", + "asked, a-tremble,", + "fearing the answer.", + " And she cocked", + "her head at me, like a", + "wild animal facing a" + ), + new BookPageInfo( + "word that it dost not", + "understand, and the", + "fixity in her eyes", + "was a glimpse into", + "the deeper reaches of", + "the Abyss. But she", + "finally grunted, and", + "said, \"Nay,\" in a" + ), + new BookPageInfo( + "voice that recalled to", + "me a child. \"Nay,\"", + "she said, \"for thou", + "dost remind me of a", + "boy I knew once,", + "when I was a girl", + "who played in a city", + "of great sandstone" + ), + new BookPageInfo( + "walls, before I was", + "taken. He had sandy", + "hair like thee, and I", + "dreamt as a child of", + "holding his hand and", + "sharing flavored ice.", + "His name was", + "Japheth.\"" + ), + new BookPageInfo( + " The next morning", + "she let me go,", + "stripped of my pouch", + "and clothes, and bade", + "me run through the", + "woods, and to fear", + "recapture, for surely", + "her heart would not" + ), + new BookPageInfo( + "soften again. 'Twas a", + "fearful run, and I", + "came to the road to", + "Yew with welts and", + "scratches run", + "rampant crost my", + "skin, but I did not see", + "her again." + ), + new BookPageInfo( + " Oft have I", + "wondered of the boy", + "named Japheth, and", + "whether he", + "remembers a girl who", + "lived in sandstone", + "walls. The only", + "Japheth I know is the" + ), + new BookPageInfo( + "Guildmaster of", + "Paladins who died", + "last year warring", + "amidst the orcs, and", + "though he had indeed", + "sandy hair, I cannot", + "picture him side by", + "side with a feral girl" + ), + new BookPageInfo( + "whose tongue has", + "tasted of human", + "flesh.", + " Yet the paths of", + "fate are strange", + "indeed, and I suppose", + "'tis possible that this", + "paladin died" + ), + new BookPageInfo( + "defending his", + "remembered lady's", + "honor, unknowingly", + "struck down by the", + "orc that she called", + "father." + ) + ); + + [Constructible] + public WildGirlOfTheForest() : base(Utility.Random(0xFEF, 2), false) + { + } + + public WildGirlOfTheForest(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class TreatiseOnAlchemy : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Treatise on Alchemy", + "Felicia Hierophant", + new BookPageInfo( + " The alchemical", + "arts are notable for", + "their deceptive", + "simplicity. 'Tis true", + "that to our best", + "knowledge currently,", + "there are but eight", + "valid potions that can" + ), + new BookPageInfo( + "be made (though I", + "emphasize that new", + "discoveries may", + "always await).", + "However, the delicate", + "balance of confecting", + "the potions is", + "difficult indeed, and" + ), + new BookPageInfo( + "requires great skill.", + " To give thee an", + "example of the", + "simpler potions that", + "can be created by", + "those well-versed in", + "the subtleties of", + "alchemy:" + ), + new BookPageInfo( + " Black pearl, that", + "rare substance that is", + "oft found lying", + "unannounced upon the", + "surface of the", + "ground, when", + "properly crushed", + "with mortar and" + ), + new BookPageInfo( + "pestle, can yield a", + "fine powder. Said", + "powder in the proper", + "proportions when", + "mixed via the", + "alchemical arts can", + "yield a wonderfully", + "refreshing drink." + ), + new BookPageInfo( + " The revolting blood", + "moss so gingerly", + "scraped off of", + "windowsills by", + "fastidious housewives", + "is but a tiny cousin to", + "the wilder version,", + "which when properly" + ), + new BookPageInfo( + "prepared yields a", + "magical liquid that for", + "a time can make the", + "imbiber a more agile", + "and dextrous", + "individual.", + " However, beware", + "of the deadly" + ), + new BookPageInfo( + "nightshade, for it", + "yields a deceptively", + "sweet-tasting poison", + "that can prove highly", + "fatal to the drinker,", + "and in fact is also", + "used by assassins to", + "coat their blades." + ), + new BookPageInfo( + "Fortunately, this", + "latter art of poisoning", + "is little known!", + " There is much to", + "reward the student of", + "alchemy, indeed. The", + "rumours of longtime", + "alchemists losing" + ), + new BookPageInfo( + "their hair and", + "acquiring an", + "unhealthy pallor, not", + "to mention unsightly", + "blotches upon their", + "once-fair skin, are", + "unhappily, true. Yet", + "the joys of the mind" + ), + new BookPageInfo( + "make up for the", + "complete loss of", + "interest that others", + "may have in thee as", + "an object of", + "courtship, and I have", + "never regretted that", + "choice. Honestly," + ), + new BookPageInfo( + "truly. Not once." + ) + ); + + [Constructible] + public TreatiseOnAlchemy() : base(Utility.Random(0xFEF, 2), false) + { + } + + public TreatiseOnAlchemy(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } + + public class VirtueBook : BaseBook + { + public static readonly BookContent Content = new BookContent( + "Virtue", + "Lord British", + new BookPageInfo( + " Within this world", + "live people with many", + "different ideals, and", + "this is good. Yet what", + "is it within the people", + "of our land that sorts", + "out the good from the", + "evil, the cherished" + ), + new BookPageInfo( + "form the disdained?", + "Virtue, I say it is,", + "and virtue is the", + "logical outcome of a", + "people who wish to", + "live together in a", + "bonded society.", + " For without Virtues" + ), + new BookPageInfo( + "as a code of conduct", + "which people maintain", + "in their relations", + "with each other, the", + "fabric of that society", + "will become weakened.", + "For a society to grow", + "and prosper for all," + ), + new BookPageInfo( + "each must grant the", + "others a common base", + "of consideration.", + " I call this base the", + "Virtues. For though", + "one person might gain", + "personal advantage by", + "breaching such a" + ), + new BookPageInfo( + "code, the society as a", + "whole would suffer.", + " There are three", + "Principle Virtues that", + "should guide people to", + "enlightenment. These", + "are: Truth, Love and", + "Courage. From all the" + ), + new BookPageInfo( + "infinite reasons one", + "may have to found an", + "action, such as greed", + "or charity, envy or", + "pity, the three", + "Principle Virtues", + "stand out.", + " In fact all other" + ), + new BookPageInfo( + "virtues and vices can", + "be show to be built", + "from these principles", + "and their opposite", + "corruption's of", + "Falsehood, Hatred and", + "Cowardice. These", + "three Principles can" + ), + new BookPageInfo( + "be combined in eight", + "ways, which I will", + "call the eight virtues.", + "The eight virtues", + "which we should", + "build our society upon", + "follow.", + " Truth alone becomes" + ), + new BookPageInfo( + "Honesty, for without", + "honesty between our", + "people, how can we", + "build the trust which", + "is needed to", + "maximize our", + "successes.", + " Love alone becomes" + ), + new BookPageInfo( + "compassion, for at", + "some time or another", + "all of us will need the", + "compassion of others,", + "and most likely", + "compassion will be", + "shown to those who", + "have shown it." + ), + new BookPageInfo( + " Courage alone", + "becomes Valor,", + "without valor our", + "people will never", + "reach into the", + "unknown or to the", + "risky and will never", + "achieve." + ), + new BookPageInfo( + " Truth tempered by", + "Love give us Justice,", + "for only in a loving", + "search for the truth", + "can one dispense fair", + "Justice, rather than", + "create a cold and", + "callous people." + ), + new BookPageInfo( + " Love and Courage", + "give us Sacrifice, for", + "a people who love each", + "other will be willing", + "to make personal", + "sacrifices to help", + "other in need, which", + "one day, may be" + ), + new BookPageInfo( + "needed in return.", + " Courage and Truth", + "give us Honor, great", + "knights know this", + "well, that chivalric", + "honor can be found", + "by adhering to this", + "code of conduct." + ), + new BookPageInfo( + " Combining Truth,", + "Love and Courage", + "suggest the virtue of", + "Spirituality the virtue", + "that causes one to be", + "introspective, to", + "wonder about ones", + "place in this world" + ), + new BookPageInfo( + "and whether one's", + "deeds will be recorded", + "as a gift to the world", + "or a plague.", + " The final Virtue is", + "more complicated. For", + "the eighth combination", + "is that devoid of" + ), + new BookPageInfo( + "Truth, Love or", + "Courage which can", + "only exist in a state", + "of great Pride, which", + "of course is not a", + "virtue at all. Perhaps", + "this trick of fate is a", + "test to see if one can" + ), + new BookPageInfo( + "realize that the true", + "virtue is that of", + "Humility. I feel that", + "the people of", + "Magincia fail to see", + "this to such a degree", + "that I would not be", + "surprised if some ill" + ), + new BookPageInfo( + "fate awaited their", + "future.", + " Thus from the", + "infinite possibilities", + "which spawned the", + "Three Principles of", + "Truth, Love and", + "Courage, come the" + ), + new BookPageInfo( + "Eight Virtues of", + "Honesty, Compassion,", + "Valor, Justice,", + "Sacrifice, Honor,", + "Spirituality, and", + "Humility." + ) + ); + + [Constructible] + public VirtueBook() : base(Utility.Random(0xFEF, 2), false) + { + } + + public VirtueBook(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Books/Defined/NewAquariumBook.cs b/Projects/UOContent/Items/Books/Defined/NewAquariumBook.cs index c3b78e54d..1f9ec8612 100644 --- a/Projects/UOContent/Items/Books/Defined/NewAquariumBook.cs +++ b/Projects/UOContent/Items/Books/Defined/NewAquariumBook.cs @@ -1,106 +1,117 @@ -namespace Server.Items -{ - public class NewAquariumBook : BlueBook - { - public static readonly BookContent Content = new BookContent( - "Your New Aquarium", "Les Bilgewater", - new BookPageInfo( - "Welcome to the", - "wonderful world", - "of aquarium ownership.", - "With a little time and", - "skill your aquarium can", - "become a work of art!"), - new BookPageInfo( - "Catching Fish:", - "You will need to", - "aquire a fishing net,", - "and a number of fish", - "bowls, from your local", - "fisherman.", - "To use the net,", - "select it from your"), - new BookPageInfo( - "backpack, and cast it", - "into shallow water.", - "Then we wait.", - " The fish will be so", - "happy to be in your", - "aquarium, they will", - "jump right into your", - "fish bowl when caught!"), - new BookPageInfo( - "Just take them home", - "and pour them into", - "your aquarium, and", - "BING! You have a happy", - "new addition to your", - "collection!"), - new BookPageInfo( - "Caring for our", - "Underwater Allies:", - "", - " Fish need clean", - "water and food to", - "survive.", - " Our aquarium comes", - "with a status monitoring"), - new BookPageInfo( - "aid. Must be Magic!", - " Just look at the", - "front of your aquarium", - "(mouse over). See the", - "helpful and friendly", - "guide? It tells how much", - "food and water is", - "needed to maintain,"), - new BookPageInfo( - "and improve the quality", - "of your tank.", - " You dont want to", - "overfeed your fish", - "very often. In fact,", - "you only want to feed", - "them every other day.", - "But, remember to keep"), - new BookPageInfo( - "the water strong and", - "healthy, and add more", - "on a regular basis", - "to keep your aquarium", - "a pretty, sparkely blue.", - "", - " Well, I hope you", - "get as much enjoyment,"), - new BookPageInfo( - "collecting a beautiful", - "array of our fine, finned,", - "friends from the sea,", - "as I do!", - "", - "Happy Fishing!")); - - [Constructible] - public NewAquariumBook() : base(false) => Hue = 0; - - public NewAquariumBook(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class NewAquariumBook : BlueBook + { + public static readonly BookContent Content = new BookContent( + "Your New Aquarium", + "Les Bilgewater", + new BookPageInfo( + "Welcome to the", + "wonderful world", + "of aquarium ownership.", + "With a little time and", + "skill your aquarium can", + "become a work of art!" + ), + new BookPageInfo( + "Catching Fish:", + "You will need to", + "aquire a fishing net,", + "and a number of fish", + "bowls, from your local", + "fisherman.", + "To use the net,", + "select it from your" + ), + new BookPageInfo( + "backpack, and cast it", + "into shallow water.", + "Then we wait.", + " The fish will be so", + "happy to be in your", + "aquarium, they will", + "jump right into your", + "fish bowl when caught!" + ), + new BookPageInfo( + "Just take them home", + "and pour them into", + "your aquarium, and", + "BING! You have a happy", + "new addition to your", + "collection!" + ), + new BookPageInfo( + "Caring for our", + "Underwater Allies:", + "", + " Fish need clean", + "water and food to", + "survive.", + " Our aquarium comes", + "with a status monitoring" + ), + new BookPageInfo( + "aid. Must be Magic!", + " Just look at the", + "front of your aquarium", + "(mouse over). See the", + "helpful and friendly", + "guide? It tells how much", + "food and water is", + "needed to maintain," + ), + new BookPageInfo( + "and improve the quality", + "of your tank.", + " You dont want to", + "overfeed your fish", + "very often. In fact,", + "you only want to feed", + "them every other day.", + "But, remember to keep" + ), + new BookPageInfo( + "the water strong and", + "healthy, and add more", + "on a regular basis", + "to keep your aquarium", + "a pretty, sparkely blue.", + "", + " Well, I hope you", + "get as much enjoyment," + ), + new BookPageInfo( + "collecting a beautiful", + "array of our fine, finned,", + "friends from the sea,", + "as I do!", + "", + "Happy Fishing!" + ) + ); + + [Constructible] + public NewAquariumBook() : base(false) => Hue = 0; + + public NewAquariumBook(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Books/Defined/TranslatedGargoyleJournal.cs b/Projects/UOContent/Items/Books/Defined/TranslatedGargoyleJournal.cs index 5b00f6f6b..9f2881cd7 100644 --- a/Projects/UOContent/Items/Books/Defined/TranslatedGargoyleJournal.cs +++ b/Projects/UOContent/Items/Books/Defined/TranslatedGargoyleJournal.cs @@ -1,133 +1,146 @@ -namespace Server.Items -{ - public class TranslatedGargoyleJournal : BlueBook - { - public static readonly BookContent Content = new BookContent( - "Translated Journal", "Velis", - new BookPageInfo( - "This text has been", - "translated from a", - "gargoyle's journal", - "following his capture", - "and subsequent", - "reeducation.", - "", - " -Velis"), - new BookPageInfo( - "I write this in the", - "hopes that someday a", - "soul of pure heart and", - "mind will read it. We", - "are not the evil beings", - "that our cousin", - "gargoyles have made", - "us out to be. We"), - new BookPageInfo( - "consider them", - "uncivilized and they", - "have no concept of the", - "Principles. To you", - "who reads this, I beg", - "for your help in", - "saving my brethern", - "and preserving my"), - new BookPageInfo( - "race. We stand at the", - "edge of destruction as", - "does the rest of the", - "world. Once it was", - "written law that we", - "would not allow the", - "knowledge of our", - "civilization to spread"), - new BookPageInfo( - "into the world, no we", - "are left with little", - "choice...contact the", - "outside world in the hopes", - "of finding help to save", - "it or becoming the", - "unwilling bringers of", - "its damnation."), - new BookPageInfo( - " I fear my capture is", - "certain, the", - "controllers grow ever", - "closer to my hiding", - "place and I know if", - "they discover me, my", - "fate will be as that of", - "my brothers."), - new BookPageInfo( - "Although we resisted", - "with all our strength", - "it is now clear that we", - "must have assistance", - "or our people will be", - "gone. And if our", - "oppressor achieves", - "his goals our race will"), - new BookPageInfo( - "surely be joined buy", - "others.", - " Those of us who", - "have not yet been", - "taken hope to open a", - "path from the outside", - "world into the city.", - "We believe we have"), - new BookPageInfo( - "found weak areas in", - "the mountains that we", - "can successfully", - "knock through with", - "our limited supplies.", - "We will have to work", - "quickly and the risk", - "of being discovered is"), - new BookPageInfo( - "great, but no choice", - "remains..."), - new BookPageInfo(), - new BookPageInfo(), - new BookPageInfo( - "Kai Hohiro, 12pm.", - "10.11.2001", - "first one to be here")); - - [Constructible] - public TranslatedGargoyleJournal() : base(false) - { - } - - public TranslatedGargoyleJournal(Serial serial) : base(serial) - { - } - - public override BookContent DefaultContent => Content; - - public override void AddNameProperty(ObjectPropertyList list) - { - list.Add("Translated Gargoyle Journal"); - } - - public override void OnSingleClick(Mobile from) - { - LabelTo(from, "Translated Gargoyle Journal"); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TranslatedGargoyleJournal : BlueBook + { + public static readonly BookContent Content = new BookContent( + "Translated Journal", + "Velis", + new BookPageInfo( + "This text has been", + "translated from a", + "gargoyle's journal", + "following his capture", + "and subsequent", + "reeducation.", + "", + " -Velis" + ), + new BookPageInfo( + "I write this in the", + "hopes that someday a", + "soul of pure heart and", + "mind will read it. We", + "are not the evil beings", + "that our cousin", + "gargoyles have made", + "us out to be. We" + ), + new BookPageInfo( + "consider them", + "uncivilized and they", + "have no concept of the", + "Principles. To you", + "who reads this, I beg", + "for your help in", + "saving my brethern", + "and preserving my" + ), + new BookPageInfo( + "race. We stand at the", + "edge of destruction as", + "does the rest of the", + "world. Once it was", + "written law that we", + "would not allow the", + "knowledge of our", + "civilization to spread" + ), + new BookPageInfo( + "into the world, no we", + "are left with little", + "choice...contact the", + "outside world in the hopes", + "of finding help to save", + "it or becoming the", + "unwilling bringers of", + "its damnation." + ), + new BookPageInfo( + " I fear my capture is", + "certain, the", + "controllers grow ever", + "closer to my hiding", + "place and I know if", + "they discover me, my", + "fate will be as that of", + "my brothers." + ), + new BookPageInfo( + "Although we resisted", + "with all our strength", + "it is now clear that we", + "must have assistance", + "or our people will be", + "gone. And if our", + "oppressor achieves", + "his goals our race will" + ), + new BookPageInfo( + "surely be joined buy", + "others.", + " Those of us who", + "have not yet been", + "taken hope to open a", + "path from the outside", + "world into the city.", + "We believe we have" + ), + new BookPageInfo( + "found weak areas in", + "the mountains that we", + "can successfully", + "knock through with", + "our limited supplies.", + "We will have to work", + "quickly and the risk", + "of being discovered is" + ), + new BookPageInfo( + "great, but no choice", + "remains..." + ), + new BookPageInfo(), + new BookPageInfo(), + new BookPageInfo( + "Kai Hohiro, 12pm.", + "10.11.2001", + "first one to be here" + ) + ); + + [Constructible] + public TranslatedGargoyleJournal() : base(false) + { + } + + public TranslatedGargoyleJournal(Serial serial) : base(serial) + { + } + + public override BookContent DefaultContent => Content; + + public override void AddNameProperty(ObjectPropertyList list) + { + list.Add("Translated Gargoyle Journal"); + } + + public override void OnSingleClick(Mobile from) + { + LabelTo(from, "Translated Gargoyle Journal"); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Books/RedBook.cs b/Projects/UOContent/Items/Books/RedBook.cs index 3b0fe3a9c..6737426ef 100644 --- a/Projects/UOContent/Items/Books/RedBook.cs +++ b/Projects/UOContent/Items/Books/RedBook.cs @@ -1,44 +1,49 @@ -namespace Server.Items -{ - public class RedBook : BaseBook - { - [Constructible] - public RedBook() : base(0xFF1) - { - } - - [Constructible] - public RedBook(int pageCount, bool writable) : base(0xFF1, pageCount, writable) - { - } - - [Constructible] - public RedBook(string title, string author, int pageCount, bool writable) : base(0xFF1, title, author, pageCount, - writable) - { - } - - // Intended for defined books only - public RedBook(bool writable) : base(0xFF1, writable) - { - } - - public RedBook(Serial serial) : base(serial) - { - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class RedBook : BaseBook + { + [Constructible] + public RedBook() : base(0xFF1) + { + } + + [Constructible] + public RedBook(int pageCount, bool writable) : base(0xFF1, pageCount, writable) + { + } + + [Constructible] + public RedBook(string title, string author, int pageCount, bool writable) : base( + 0xFF1, + title, + author, + pageCount, + writable + ) + { + } + + // Intended for defined books only + public RedBook(bool writable) : base(0xFF1, writable) + { + } + + public RedBook(Serial serial) : base(serial) + { + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + } +} diff --git a/Projects/UOContent/Items/Books/TanBook.cs b/Projects/UOContent/Items/Books/TanBook.cs index 0953bd12b..1ef28d8bd 100644 --- a/Projects/UOContent/Items/Books/TanBook.cs +++ b/Projects/UOContent/Items/Books/TanBook.cs @@ -1,44 +1,49 @@ -namespace Server.Items -{ - public class TanBook : BaseBook - { - [Constructible] - public TanBook() : base(0xFF0) - { - } - - [Constructible] - public TanBook(int pageCount, bool writable) : base(0xFF0, pageCount, writable) - { - } - - [Constructible] - public TanBook(string title, string author, int pageCount, bool writable) : base(0xFF0, title, author, pageCount, - writable) - { - } - - // Intended for defined books only - public TanBook(bool writable) : base(0xFF0, writable) - { - } - - public TanBook(Serial serial) : base(serial) - { - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TanBook : BaseBook + { + [Constructible] + public TanBook() : base(0xFF0) + { + } + + [Constructible] + public TanBook(int pageCount, bool writable) : base(0xFF0, pageCount, writable) + { + } + + [Constructible] + public TanBook(string title, string author, int pageCount, bool writable) : base( + 0xFF0, + title, + author, + pageCount, + writable + ) + { + } + + // Intended for defined books only + public TanBook(bool writable) : base(0xFF0, writable) + { + } + + public TanBook(Serial serial) : base(serial) + { + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Decorative/ArtifactLargeVase.cs b/Projects/UOContent/Items/Champion Artifacts/Decorative/ArtifactLargeVase.cs index a53cb37df..2794f5198 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Decorative/ArtifactLargeVase.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Decorative/ArtifactLargeVase.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class ArtifactLargeVase : Item - { - [Constructible] - public ArtifactLargeVase() : base(0x0B47) - { - } - - public ArtifactLargeVase(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ArtifactLargeVase : Item + { + [Constructible] + public ArtifactLargeVase() : base(0x0B47) + { + } + + public ArtifactLargeVase(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Decorative/ArtifactVase.cs b/Projects/UOContent/Items/Champion Artifacts/Decorative/ArtifactVase.cs index a42996cf6..7c901f142 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Decorative/ArtifactVase.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Decorative/ArtifactVase.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class ArtifactVase : Item - { - [Constructible] - public ArtifactVase() : base(0x0B48) - { - } - - public ArtifactVase(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ArtifactVase : Item + { + [Constructible] + public ArtifactVase() : base(0x0B48) + { + } + + public ArtifactVase(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Decorative/DemonSkull.cs b/Projects/UOContent/Items/Champion Artifacts/Decorative/DemonSkull.cs index 966e80a5e..89fa7907c 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Decorative/DemonSkull.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Decorative/DemonSkull.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class DemonSkull : Item - { - [Constructible] - public DemonSkull() : base(0x224e + Utility.Random(4)) - { - } - - public DemonSkull(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class DemonSkull : Item + { + [Constructible] + public DemonSkull() : base(0x224e + Utility.Random(4)) + { + } + + public DemonSkull(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Decorative/DirtPatch.cs b/Projects/UOContent/Items/Champion Artifacts/Decorative/DirtPatch.cs index 82cbc846d..e15f2db6f 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Decorative/DirtPatch.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Decorative/DirtPatch.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class DirtPatch : Item - { - [Constructible] - public DirtPatch() : base(0x0913) - { - } - - public DirtPatch(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class DirtPatch : Item + { + [Constructible] + public DirtPatch() : base(0x0913) + { + } + + public DirtPatch(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Decorative/EvilIdolSkull.cs b/Projects/UOContent/Items/Champion Artifacts/Decorative/EvilIdolSkull.cs index b2cf136fd..1074e8a4e 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Decorative/EvilIdolSkull.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Decorative/EvilIdolSkull.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class EvilIdolSkull : Item - { - [Constructible] - public EvilIdolSkull() : base(0x1F18) - { - } - - public EvilIdolSkull(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1095237; // Evil Idol - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class EvilIdolSkull : Item + { + [Constructible] + public EvilIdolSkull() : base(0x1F18) + { + } + + public EvilIdolSkull(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1095237; // Evil Idol + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Decorative/Futon.cs b/Projects/UOContent/Items/Champion Artifacts/Decorative/Futon.cs index fc605ff4d..8cf907157 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Decorative/Futon.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Decorative/Futon.cs @@ -1,39 +1,39 @@ -namespace Server.Items -{ - [Flippable] - public class Futon : Item - { - [Constructible] - public Futon() : base(Utility.RandomDouble() > 0.5 ? 0x295C : 0x295E) - { - } - - public Futon(Serial serial) : base(serial) - { - } - - public void Flip() - { - ItemID = ItemID switch - { - 0x295C => 0x295D, - 0x295E => 0x295F, - 0x295D => 0x295C, - 0x295F => 0x295E, - _ => ItemID - }; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable] + public class Futon : Item + { + [Constructible] + public Futon() : base(Utility.RandomDouble() > 0.5 ? 0x295C : 0x295E) + { + } + + public Futon(Serial serial) : base(serial) + { + } + + public void Flip() + { + ItemID = ItemID switch + { + 0x295C => 0x295D, + 0x295E => 0x295F, + 0x295D => 0x295C, + 0x295F => 0x295E, + _ => ItemID + }; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Decorative/LavaTile.cs b/Projects/UOContent/Items/Champion Artifacts/Decorative/LavaTile.cs index 9d7118854..ad3caa8ef 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Decorative/LavaTile.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Decorative/LavaTile.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class LavaTile : Item - { - [Constructible] - public LavaTile() : base(0x12EE) - { - } - - public LavaTile(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LavaTile : Item + { + [Constructible] + public LavaTile() : base(0x12EE) + { + } + + public LavaTile(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Decorative/Pier.cs b/Projects/UOContent/Items/Champion Artifacts/Decorative/Pier.cs index aa22818dc..ee6ef0d94 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Decorative/Pier.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Decorative/Pier.cs @@ -1,53 +1,53 @@ -namespace Server.Items -{ - public class Pier : Item - { - /* - * This does not make a lot of sense, being a "Pier" - * and having possible itemids that have nothing - * to do with piers. The three items here are basically - * permutations of the same "drop", or item that - * will be randomly selected when the item drops. - * - * It was either this, or make 2 - * new classes named to reflect that they are rocks - * in water, or put them all in one class. Either - * is kind of senseless, so it is what it is. - * - */ - - private static readonly int[] m_itemids = - { - 0x3486, 0x348b, 0x3ae - }; - - [Constructible] - public Pier() - : base(m_itemids[Utility.Random(3)]) - { - } - - public Pier(int itemid) - : base(itemid) - { - } - - public Pier(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Pier : Item + { + /* + * This does not make a lot of sense, being a "Pier" + * and having possible itemids that have nothing + * to do with piers. The three items here are basically + * permutations of the same "drop", or item that + * will be randomly selected when the item drops. + * + * It was either this, or make 2 + * new classes named to reflect that they are rocks + * in water, or put them all in one class. Either + * is kind of senseless, so it is what it is. + * + */ + + private static readonly int[] m_itemids = + { + 0x3486, 0x348b, 0x3ae + }; + + [Constructible] + public Pier() + : base(m_itemids[Utility.Random(3)]) + { + } + + public Pier(int itemid) + : base(itemid) + { + } + + public Pier(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Decorative/SkullPole.cs b/Projects/UOContent/Items/Champion Artifacts/Decorative/SkullPole.cs index 169026592..5062e4b90 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Decorative/SkullPole.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Decorative/SkullPole.cs @@ -1,26 +1,26 @@ -namespace Server.Items -{ - public class SkullPole : Item - { - [Constructible] - public SkullPole() : base(0x2204) => Weight = 5; - - public SkullPole(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SkullPole : Item + { + [Constructible] + public SkullPole() : base(0x2204) => Weight = 5; + + public SkullPole(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Decorative/SwampTile.cs b/Projects/UOContent/Items/Champion Artifacts/Decorative/SwampTile.cs index 1e2f72327..76e3e5899 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Decorative/SwampTile.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Decorative/SwampTile.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class SwampTile : Item - { - [Constructible] - public SwampTile() : base(0x320D) - { - } - - public SwampTile(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SwampTile : Item + { + [Constructible] + public SwampTile() : base(0x320D) + { + } + + public SwampTile(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Decorative/TatteredAncientMummyWrapping.cs b/Projects/UOContent/Items/Champion Artifacts/Decorative/TatteredAncientMummyWrapping.cs index 60ad85589..81ea05fce 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Decorative/TatteredAncientMummyWrapping.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Decorative/TatteredAncientMummyWrapping.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class TatteredAncientMummyWrapping : Item - { - [Constructible] - public TatteredAncientMummyWrapping() : base(0xE21) => Hue = 0x909; - - public TatteredAncientMummyWrapping(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094912; // Tattered Ancient Mummy Wrapping [Replica] - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TatteredAncientMummyWrapping : Item + { + [Constructible] + public TatteredAncientMummyWrapping() : base(0xE21) => Hue = 0x909; + + public TatteredAncientMummyWrapping(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094912; // Tattered Ancient Mummy Wrapping [Replica] + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Decorative/WallBlood.cs b/Projects/UOContent/Items/Champion Artifacts/Decorative/WallBlood.cs index a1a1e85dd..4f32ded0a 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Decorative/WallBlood.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Decorative/WallBlood.cs @@ -1,29 +1,29 @@ -namespace Server.Items -{ - public class WallBlood : Item - { - [Constructible] - public WallBlood() - : base(Utility.RandomBool() ? 0x1D95 : 0x1D94) - { - } - - public WallBlood(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class WallBlood : Item + { + [Constructible] + public WallBlood() + : base(Utility.RandomBool() ? 0x1D95 : 0x1D94) + { + } + + public WallBlood(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Decorative/WaterTile.cs b/Projects/UOContent/Items/Champion Artifacts/Decorative/WaterTile.cs index 355282858..786e4b1df 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Decorative/WaterTile.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Decorative/WaterTile.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class WaterTile : Item - { - [Constructible] - public WaterTile() : base(0x346E) - { - } - - public WaterTile(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class WaterTile : Item + { + [Constructible] + public WaterTile() : base(0x346E) + { + } + + public WaterTile(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Decorative/Web.cs b/Projects/UOContent/Items/Champion Artifacts/Decorative/Web.cs index c8018d093..27d6c1332 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Decorative/Web.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Decorative/Web.cs @@ -1,37 +1,37 @@ -namespace Server.Items -{ - public class Web : Item - { - private static readonly int[] m_itemids = - { - 0x10d7, 0x10d8, 0x10dd - }; - - [Constructible] - public Web() - : base(m_itemids[Utility.Random(3)]) - { - } - - [Constructible] - public Web(int itemid) : base(itemid) - { - } - - public Web(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Web : Item + { + private static readonly int[] m_itemids = + { + 0x10d7, 0x10d8, 0x10dd + }; + + [Constructible] + public Web() + : base(m_itemids[Utility.Random(3)]) + { + } + + [Constructible] + public Web(int itemid) : base(itemid) + { + } + + public Web(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Decorative/WindSpirit.cs b/Projects/UOContent/Items/Champion Artifacts/Decorative/WindSpirit.cs index 6af3b948a..3d48234dc 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Decorative/WindSpirit.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Decorative/WindSpirit.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class WindSpirit : Item - { - [Constructible] - public WindSpirit() : base(0x1F1F) - { - } - - public WindSpirit(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094925; // Wind Spirit [Replica] - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class WindSpirit : Item + { + [Constructible] + public WindSpirit() : base(0x1F1F) + { + } + + public WindSpirit(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094925; // Wind Spirit [Replica] + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Shared/ANecromancerShroud.cs b/Projects/UOContent/Items/Champion Artifacts/Shared/ANecromancerShroud.cs index cc4512ad9..193021910 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Shared/ANecromancerShroud.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Shared/ANecromancerShroud.cs @@ -1,35 +1,35 @@ -namespace Server.Items -{ - public class ANecromancerShroud : Robe - { - [Constructible] - public ANecromancerShroud() => Hue = 0x455; - - public ANecromancerShroud(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094913; // A Necromancer Shroud [Replica] - - public override int BaseColdResistance => 5; - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override bool CanFortify => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ANecromancerShroud : Robe + { + [Constructible] + public ANecromancerShroud() => Hue = 0x455; + + public ANecromancerShroud(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094913; // A Necromancer Shroud [Replica] + + public override int BaseColdResistance => 5; + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + public override bool CanFortify => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Shared/BraveKnightOfTheBritannia.cs b/Projects/UOContent/Items/Champion Artifacts/Shared/BraveKnightOfTheBritannia.cs index b8e44f350..8505b0508 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Shared/BraveKnightOfTheBritannia.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Shared/BraveKnightOfTheBritannia.cs @@ -1,53 +1,55 @@ -namespace Server.Items -{ - public class BraveKnightOfTheBritannia : Katana - { - [Constructible] - public BraveKnightOfTheBritannia() - { - Hue = 0x47e; - - Attributes.WeaponSpeed = 30; - Attributes.WeaponDamage = 35; - - WeaponAttributes.HitLeechStam = 48; - WeaponAttributes.HitHarm = 26; - WeaponAttributes.HitLeechHits = 22; - } - - public BraveKnightOfTheBritannia(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094909; // Brave Knight of The Britannia [Replica] - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override bool CanFortify => false; - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - phys = chaos = direct = 0; - fire = 40; - cold = 30; - pois = 10; - nrgy = 20; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class BraveKnightOfTheBritannia : Katana + { + [Constructible] + public BraveKnightOfTheBritannia() + { + Hue = 0x47e; + + Attributes.WeaponSpeed = 30; + Attributes.WeaponDamage = 35; + + WeaponAttributes.HitLeechStam = 48; + WeaponAttributes.HitHarm = 26; + WeaponAttributes.HitLeechHits = 22; + } + + public BraveKnightOfTheBritannia(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094909; // Brave Knight of The Britannia [Replica] + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + public override bool CanFortify => false; + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + phys = chaos = direct = 0; + fire = 40; + cold = 30; + pois = 10; + nrgy = 20; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Shared/CaptainJohnsHat.cs b/Projects/UOContent/Items/Champion Artifacts/Shared/CaptainJohnsHat.cs index 349d175d8..2b719831d 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Shared/CaptainJohnsHat.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Shared/CaptainJohnsHat.cs @@ -1,49 +1,49 @@ -namespace Server.Items -{ - public class CaptainJohnsHat : TricorneHat - { - [Constructible] - public CaptainJohnsHat() - { - Hue = 0x455; - - Attributes.BonusDex = 8; - Attributes.NightSight = 1; - Attributes.AttackChance = 15; - - SkillBonuses.Skill_1_Name = SkillName.Swords; - SkillBonuses.Skill_1_Value = 20; - } - - public CaptainJohnsHat(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094911; // Captain John's Hat [Replica] - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 6; - public override int BaseColdResistance => 9; - public override int BasePoisonResistance => 7; - public override int BaseEnergyResistance => 23; - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override bool CanFortify => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class CaptainJohnsHat : TricorneHat + { + [Constructible] + public CaptainJohnsHat() + { + Hue = 0x455; + + Attributes.BonusDex = 8; + Attributes.NightSight = 1; + Attributes.AttackChance = 15; + + SkillBonuses.Skill_1_Name = SkillName.Swords; + SkillBonuses.Skill_1_Value = 20; + } + + public CaptainJohnsHat(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094911; // Captain John's Hat [Replica] + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 6; + public override int BaseColdResistance => 9; + public override int BasePoisonResistance => 7; + public override int BaseEnergyResistance => 23; + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + public override bool CanFortify => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Shared/DetectiveBoots.cs b/Projects/UOContent/Items/Champion Artifacts/Shared/DetectiveBoots.cs index 44d447e83..d4d62bc1f 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Shared/DetectiveBoots.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Shared/DetectiveBoots.cs @@ -1,55 +1,55 @@ -using System; - -namespace Server.Items -{ - public class DetectiveBoots : Boots - { - private int m_Level; - - [Constructible] - public DetectiveBoots() - { - Hue = 0x455; - Level = Utility.RandomMinMax(0, 2); - } - - public DetectiveBoots(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094894 + m_Level; // [Quality] Detective of the Royal Guard [Replica] - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override bool CanFortify => false; - - [CommandProperty(AccessLevel.GameMaster)] - public int Level - { - get => m_Level; - set - { - m_Level = Math.Clamp(value, 0, 2); - Attributes.BonusInt = 2 + m_Level; - InvalidateProperties(); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Level = Attributes.BonusInt - 2; - } - } -} +using System; + +namespace Server.Items +{ + public class DetectiveBoots : Boots + { + private int m_Level; + + [Constructible] + public DetectiveBoots() + { + Hue = 0x455; + Level = Utility.RandomMinMax(0, 2); + } + + public DetectiveBoots(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094894 + m_Level; // [Quality] Detective of the Royal Guard [Replica] + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + public override bool CanFortify => false; + + [CommandProperty(AccessLevel.GameMaster)] + public int Level + { + get => m_Level; + set + { + m_Level = Math.Clamp(value, 0, 2); + Attributes.BonusInt = 2 + m_Level; + InvalidateProperties(); + } + } + + 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(); + + Level = Attributes.BonusInt - 2; + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Shared/DjinnisRing.cs b/Projects/UOContent/Items/Champion Artifacts/Shared/DjinnisRing.cs index c701a462a..01e9b84a3 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Shared/DjinnisRing.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Shared/DjinnisRing.cs @@ -1,36 +1,36 @@ -namespace Server.Items -{ - public class DjinnisRing : SilverRing - { - [Constructible] - public DjinnisRing() - { - Attributes.BonusInt = 5; - Attributes.SpellDamage = 10; - Attributes.CastSpeed = 2; - } - - public DjinnisRing(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094927; // Djinni's Ring [Replica] - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class DjinnisRing : SilverRing + { + [Constructible] + public DjinnisRing() + { + Attributes.BonusInt = 5; + Attributes.SpellDamage = 10; + Attributes.CastSpeed = 2; + } + + public DjinnisRing(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094927; // Djinni's Ring [Replica] + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Shared/EmbroideredOakLeafCloak.cs b/Projects/UOContent/Items/Champion Artifacts/Shared/EmbroideredOakLeafCloak.cs index 51d54899e..229b64778 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Shared/EmbroideredOakLeafCloak.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Shared/EmbroideredOakLeafCloak.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class EmbroideredOakLeafCloak : BaseOuterTorso - { - [Constructible] - public EmbroideredOakLeafCloak() : base(0x2684) - { - Hue = 0x483; - StrRequirement = 0; - - SkillBonuses.Skill_1_Name = SkillName.Stealth; - SkillBonuses.Skill_1_Value = 5; - } - - public EmbroideredOakLeafCloak(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094901; // Embroidered Oak Leaf Cloak [Replica] - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override bool CanFortify => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class EmbroideredOakLeafCloak : BaseOuterTorso + { + [Constructible] + public EmbroideredOakLeafCloak() : base(0x2684) + { + Hue = 0x483; + StrRequirement = 0; + + SkillBonuses.Skill_1_Name = SkillName.Stealth; + SkillBonuses.Skill_1_Value = 5; + } + + public EmbroideredOakLeafCloak(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094901; // Embroidered Oak Leaf Cloak [Replica] + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + public override bool CanFortify => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Shared/GauntletsOfAnger.cs b/Projects/UOContent/Items/Champion Artifacts/Shared/GauntletsOfAnger.cs index 0f007128e..badc1fe8b 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Shared/GauntletsOfAnger.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Shared/GauntletsOfAnger.cs @@ -1,46 +1,46 @@ -namespace Server.Items -{ - public class GuantletsOfAnger : PlateGloves - { - [Constructible] - public GuantletsOfAnger() - { - Hue = 0x29b; - - Attributes.BonusHits = 8; - Attributes.RegenHits = 2; - Attributes.DefendChance = 10; - } - - public GuantletsOfAnger(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094902; // Gauntlets of Anger [Replica] - - public override int BasePhysicalResistance => 4; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 5; - public override int BasePoisonResistance => 6; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override bool CanFortify => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class GuantletsOfAnger : PlateGloves + { + [Constructible] + public GuantletsOfAnger() + { + Hue = 0x29b; + + Attributes.BonusHits = 8; + Attributes.RegenHits = 2; + Attributes.DefendChance = 10; + } + + public GuantletsOfAnger(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094902; // Gauntlets of Anger [Replica] + + public override int BasePhysicalResistance => 4; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 5; + public override int BasePoisonResistance => 6; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + public override bool CanFortify => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Shared/LieutenantOfTheBritannianRoyalGuard.cs b/Projects/UOContent/Items/Champion Artifacts/Shared/LieutenantOfTheBritannianRoyalGuard.cs index ff47fdf51..4bad9d370 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Shared/LieutenantOfTheBritannianRoyalGuard.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Shared/LieutenantOfTheBritannianRoyalGuard.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class LieutenantOfTheBritannianRoyalGuard : BodySash - { - [Constructible] - public LieutenantOfTheBritannianRoyalGuard() - { - Hue = 0xe8; - - Attributes.BonusInt = 5; - Attributes.RegenMana = 2; - Attributes.LowerRegCost = 10; - } - - public LieutenantOfTheBritannianRoyalGuard(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094910; // Lieutenant of the Britannian Royal Guard [Replica] - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override bool CanFortify => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LieutenantOfTheBritannianRoyalGuard : BodySash + { + [Constructible] + public LieutenantOfTheBritannianRoyalGuard() + { + Hue = 0xe8; + + Attributes.BonusInt = 5; + Attributes.RegenMana = 2; + Attributes.LowerRegCost = 10; + } + + public LieutenantOfTheBritannianRoyalGuard(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094910; // Lieutenant of the Britannian Royal Guard [Replica] + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + public override bool CanFortify => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Shared/OblivionsNeedle.cs b/Projects/UOContent/Items/Champion Artifacts/Shared/OblivionsNeedle.cs index 8b1aa9078..91d2cb40b 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Shared/OblivionsNeedle.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Shared/OblivionsNeedle.cs @@ -1,41 +1,41 @@ -namespace Server.Items -{ - public class OblivionsNeedle : Dagger - { - [Constructible] - public OblivionsNeedle() - { - Attributes.BonusStam = 20; - Attributes.AttackChance = 20; - Attributes.DefendChance = -20; - Attributes.WeaponDamage = 40; - - WeaponAttributes.HitLeechStam = 50; - } - - public OblivionsNeedle(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094916; // Oblivion's Needle [Replica] - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override bool CanFortify => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class OblivionsNeedle : Dagger + { + [Constructible] + public OblivionsNeedle() + { + Attributes.BonusStam = 20; + Attributes.AttackChance = 20; + Attributes.DefendChance = -20; + Attributes.WeaponDamage = 40; + + WeaponAttributes.HitLeechStam = 50; + } + + public OblivionsNeedle(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094916; // Oblivion's Needle [Replica] + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + public override bool CanFortify => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Shared/RoyalGuardSurvivalKnife.cs b/Projects/UOContent/Items/Champion Artifacts/Shared/RoyalGuardSurvivalKnife.cs index 7757edff6..51694f6f4 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Shared/RoyalGuardSurvivalKnife.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Shared/RoyalGuardSurvivalKnife.cs @@ -1,41 +1,41 @@ -namespace Server.Items -{ - public class RoyalGuardSurvivalKnife : SkinningKnife - { - [Constructible] - public RoyalGuardSurvivalKnife() - { - Attributes.SpellChanneling = 1; - Attributes.Luck = 140; - Attributes.EnhancePotions = 25; - - WeaponAttributes.UseBestSkill = 1; - WeaponAttributes.LowerStatReq = 50; - } - - public RoyalGuardSurvivalKnife(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094918; // Royal Guard Survival Knife [Replica] - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override bool CanFortify => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class RoyalGuardSurvivalKnife : SkinningKnife + { + [Constructible] + public RoyalGuardSurvivalKnife() + { + Attributes.SpellChanneling = 1; + Attributes.Luck = 140; + Attributes.EnhancePotions = 25; + + WeaponAttributes.UseBestSkill = 1; + WeaponAttributes.LowerStatReq = 50; + } + + public RoyalGuardSurvivalKnife(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094918; // Royal Guard Survival Knife [Replica] + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + public override bool CanFortify => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Shared/SamaritanRobe.cs b/Projects/UOContent/Items/Champion Artifacts/Shared/SamaritanRobe.cs index ff258a783..ec082ea30 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Shared/SamaritanRobe.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Shared/SamaritanRobe.cs @@ -1,35 +1,35 @@ -namespace Server.Items -{ - public class SamaritanRobe : Robe - { - [Constructible] - public SamaritanRobe() => Hue = 0x2a3; - - public SamaritanRobe(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094926; // Good Samaritan of Britannia [Replica] - - public override int BasePhysicalResistance => 5; - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override bool CanFortify => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SamaritanRobe : Robe + { + [Constructible] + public SamaritanRobe() => Hue = 0x2a3; + + public SamaritanRobe(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094926; // Good Samaritan of Britannia [Replica] + + public override int BasePhysicalResistance => 5; + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + public override bool CanFortify => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Shared/TheMostKnowledgePerson.cs b/Projects/UOContent/Items/Champion Artifacts/Shared/TheMostKnowledgePerson.cs index 64bd0ecd4..b861a0b97 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Shared/TheMostKnowledgePerson.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Shared/TheMostKnowledgePerson.cs @@ -1,41 +1,41 @@ -namespace Server.Items -{ - public class TheMostKnowledgePerson : BaseOuterTorso - { - [Constructible] - public TheMostKnowledgePerson() : base(0x2684) - { - Hue = 0x117; - StrRequirement = 0; - - Attributes.BonusHits = 3 + Utility.RandomMinMax(0, 2); - } - - public TheMostKnowledgePerson(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094893; // The Most Knowledge Person [Replica] - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override bool CanFortify => false; - - public override bool CanBeBlessed => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TheMostKnowledgePerson : BaseOuterTorso + { + [Constructible] + public TheMostKnowledgePerson() : base(0x2684) + { + Hue = 0x117; + StrRequirement = 0; + + Attributes.BonusHits = 3 + Utility.RandomMinMax(0, 2); + } + + public TheMostKnowledgePerson(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094893; // The Most Knowledge Person [Replica] + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + public override bool CanFortify => false; + + public override bool CanBeBlessed => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Shared/TheRobeOfBritanniaAri.cs b/Projects/UOContent/Items/Champion Artifacts/Shared/TheRobeOfBritanniaAri.cs index 667b46819..e05eda4c6 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Shared/TheRobeOfBritanniaAri.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Shared/TheRobeOfBritanniaAri.cs @@ -1,39 +1,39 @@ -namespace Server.Items -{ - public class TheRobeOfBritanniaAri : BaseOuterTorso - { - [Constructible] - public TheRobeOfBritanniaAri() : base(0x2684) - { - Hue = 0x48b; - StrRequirement = 0; - } - - public TheRobeOfBritanniaAri(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094931; // The Robe of Britannia "Ari" [Replica] - - public override int BasePhysicalResistance => 10; - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override bool CanFortify => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TheRobeOfBritanniaAri : BaseOuterTorso + { + [Constructible] + public TheRobeOfBritanniaAri() : base(0x2684) + { + Hue = 0x48b; + StrRequirement = 0; + } + + public TheRobeOfBritanniaAri(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094931; // The Robe of Britannia "Ari" [Replica] + + public override int BasePhysicalResistance => 10; + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + public override bool CanFortify => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Unique/AcidProofRobe.cs b/Projects/UOContent/Items/Champion Artifacts/Unique/AcidProofRobe.cs index 423eff9bc..3ed25653d 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Unique/AcidProofRobe.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Unique/AcidProofRobe.cs @@ -1,41 +1,41 @@ -namespace Server.Items -{ - public class AcidProofRobe : Robe - { - [Constructible] - public AcidProofRobe() - { - Hue = 0x455; - LootType = LootType.Blessed; - } - - public AcidProofRobe(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1095236; // Acid-Proof Robe [Replica] - - public override int BaseFireResistance => 4; - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override bool CanFortify => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1 && Hue == 1) Hue = 0x455; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AcidProofRobe : Robe + { + [Constructible] + public AcidProofRobe() + { + Hue = 0x455; + LootType = LootType.Blessed; + } + + public AcidProofRobe(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1095236; // Acid-Proof Robe [Replica] + + public override int BaseFireResistance => 4; + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + public override bool CanFortify => false; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version < 1 && Hue == 1) Hue = 0x455; + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Unique/Calm.cs b/Projects/UOContent/Items/Champion Artifacts/Unique/Calm.cs index 815595d3e..070ffb035 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Unique/Calm.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Unique/Calm.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - public class Calm : Halberd - { - [Constructible] - public Calm() - { - Hue = 0x2cb; - - Attributes.SpellChanneling = 1; - Attributes.WeaponSpeed = 20; - Attributes.WeaponDamage = 50; - - WeaponAttributes.HitLeechMana = 100; - WeaponAttributes.UseBestSkill = 1; - } - - public Calm(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094915; // Calm [Replica] - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override bool CanFortify => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Calm : Halberd + { + [Constructible] + public Calm() + { + Hue = 0x2cb; + + Attributes.SpellChanneling = 1; + Attributes.WeaponSpeed = 20; + Attributes.WeaponDamage = 50; + + WeaponAttributes.HitLeechMana = 100; + WeaponAttributes.UseBestSkill = 1; + } + + public Calm(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094915; // Calm [Replica] + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + public override bool CanFortify => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Unique/CrownOfTalKeesh.cs b/Projects/UOContent/Items/Champion Artifacts/Unique/CrownOfTalKeesh.cs index 9be00d162..113febe03 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Unique/CrownOfTalKeesh.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Unique/CrownOfTalKeesh.cs @@ -1,46 +1,46 @@ -namespace Server.Items -{ - public class CrownOfTalKeesh : Bandana - { - [Constructible] - public CrownOfTalKeesh() - { - Hue = 0x4F2; - - Attributes.BonusInt = 8; - Attributes.RegenMana = 4; - Attributes.SpellDamage = 10; - } - - public CrownOfTalKeesh(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094903; // Crown of Tal'Keesh [Replica] - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 9; - public override int BasePoisonResistance => 20; - public override int BaseEnergyResistance => 20; - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override bool CanFortify => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class CrownOfTalKeesh : Bandana + { + [Constructible] + public CrownOfTalKeesh() + { + Hue = 0x4F2; + + Attributes.BonusInt = 8; + Attributes.RegenMana = 4; + Attributes.SpellDamage = 10; + } + + public CrownOfTalKeesh(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094903; // Crown of Tal'Keesh [Replica] + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 9; + public override int BasePoisonResistance => 20; + public override int BaseEnergyResistance => 20; + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + public override bool CanFortify => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Unique/FangOfRactus.cs b/Projects/UOContent/Items/Champion Artifacts/Unique/FangOfRactus.cs index ba8fe4fc2..3cd5a85a5 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Unique/FangOfRactus.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Unique/FangOfRactus.cs @@ -1,44 +1,44 @@ -namespace Server.Items -{ - public class FangOfRactus : Kryss - { - [Constructible] - public FangOfRactus() - { - Hue = 0x117; - - Attributes.SpellChanneling = 1; - Attributes.AttackChance = 5; - Attributes.DefendChance = 5; - Attributes.WeaponDamage = 35; - - WeaponAttributes.HitPoisonArea = 20; - WeaponAttributes.ResistPoisonBonus = 15; - } - - public FangOfRactus(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094892; // Fang of Ractus [Replica] - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override bool CanFortify => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FangOfRactus : Kryss + { + [Constructible] + public FangOfRactus() + { + Hue = 0x117; + + Attributes.SpellChanneling = 1; + Attributes.AttackChance = 5; + Attributes.DefendChance = 5; + Attributes.WeaponDamage = 35; + + WeaponAttributes.HitPoisonArea = 20; + WeaponAttributes.ResistPoisonBonus = 15; + } + + public FangOfRactus(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094892; // Fang of Ractus [Replica] + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + public override bool CanFortify => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Unique/GladiatorsCollar.cs b/Projects/UOContent/Items/Champion Artifacts/Unique/GladiatorsCollar.cs index 525952219..6e6d345cc 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Unique/GladiatorsCollar.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Unique/GladiatorsCollar.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - public class GladiatorsCollar : PlateGorget - { - [Constructible] - public GladiatorsCollar() - { - Hue = 0x26d; - - Attributes.BonusHits = 10; - Attributes.AttackChance = 10; - - ArmorAttributes.MageArmor = 1; - } - - public GladiatorsCollar(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094917; // Gladiator's Collar [Replica] - - public override int BasePhysicalResistance => 18; - public override int BaseFireResistance => 18; - public override int BaseColdResistance => 17; - public override int BasePoisonResistance => 18; - public override int BaseEnergyResistance => 16; - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override bool CanFortify => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class GladiatorsCollar : PlateGorget + { + [Constructible] + public GladiatorsCollar() + { + Hue = 0x26d; + + Attributes.BonusHits = 10; + Attributes.AttackChance = 10; + + ArmorAttributes.MageArmor = 1; + } + + public GladiatorsCollar(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094917; // Gladiator's Collar [Replica] + + public override int BasePhysicalResistance => 18; + public override int BaseFireResistance => 18; + public override int BaseColdResistance => 17; + public override int BasePoisonResistance => 18; + public override int BaseEnergyResistance => 16; + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + public override bool CanFortify => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Unique/OrcChieftainHelm.cs b/Projects/UOContent/Items/Champion Artifacts/Unique/OrcChieftainHelm.cs index a36ea9e0a..be47d808a 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Unique/OrcChieftainHelm.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Unique/OrcChieftainHelm.cs @@ -1,52 +1,52 @@ -namespace Server.Items -{ - public class OrcChieftainHelm : OrcHelm - { - [Constructible] - public OrcChieftainHelm() - { - Hue = 0x2a3; - - Attributes.Luck = 100; - Attributes.RegenHits = 3; - - if (Utility.RandomBool()) - Attributes.BonusHits = 30; - else - Attributes.AttackChance = 30; - } - - public OrcChieftainHelm(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094924; // Orc Chieftain Helm [Replica] - - public override int BasePhysicalResistance => 23; - public override int BaseFireResistance => 1; - public override int BaseColdResistance => 23; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override bool CanFortify => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1 && Hue == 0x3f) /* Pigmented? */ Hue = 0x2a3; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class OrcChieftainHelm : OrcHelm + { + [Constructible] + public OrcChieftainHelm() + { + Hue = 0x2a3; + + Attributes.Luck = 100; + Attributes.RegenHits = 3; + + if (Utility.RandomBool()) + Attributes.BonusHits = 30; + else + Attributes.AttackChance = 30; + } + + public OrcChieftainHelm(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094924; // Orc Chieftain Helm [Replica] + + public override int BasePhysicalResistance => 23; + public override int BaseFireResistance => 1; + public override int BaseColdResistance => 23; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + public override bool CanFortify => false; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version < 1 && Hue == 0x3f) /* Pigmented? */ Hue = 0x2a3; + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Unique/Pacify.cs b/Projects/UOContent/Items/Champion Artifacts/Unique/Pacify.cs index e406abaf0..5b9ec9a68 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Unique/Pacify.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Unique/Pacify.cs @@ -1,44 +1,44 @@ -namespace Server.Items -{ - public class Pacify : Pike - { - [Constructible] - public Pacify() - { - Hue = 0x835; - - Attributes.SpellChanneling = 1; - Attributes.AttackChance = 10; - Attributes.WeaponSpeed = 20; - Attributes.WeaponDamage = 50; - - WeaponAttributes.HitLeechMana = 100; - WeaponAttributes.UseBestSkill = 1; - } - - public Pacify(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094929; // Pacify [Replica] - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override bool CanFortify => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Pacify : Pike + { + [Constructible] + public Pacify() + { + Hue = 0x835; + + Attributes.SpellChanneling = 1; + Attributes.AttackChance = 10; + Attributes.WeaponSpeed = 20; + Attributes.WeaponDamage = 50; + + WeaponAttributes.HitLeechMana = 100; + WeaponAttributes.UseBestSkill = 1; + } + + public Pacify(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094929; // Pacify [Replica] + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + public override bool CanFortify => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Unique/Quell.cs b/Projects/UOContent/Items/Champion Artifacts/Unique/Quell.cs index 4aa3c1ce1..cff8535eb 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Unique/Quell.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Unique/Quell.cs @@ -1,44 +1,44 @@ -namespace Server.Items -{ - public class Quell : Bardiche - { - [Constructible] - public Quell() - { - Hue = 0x225; - - Attributes.SpellChanneling = 1; - Attributes.WeaponSpeed = 20; - Attributes.WeaponDamage = 50; - Attributes.AttackChance = 10; - - WeaponAttributes.HitLeechMana = 100; - WeaponAttributes.UseBestSkill = 1; - } - - public Quell(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094928; // Quell [Replica] - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override bool CanFortify => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Quell : Bardiche + { + [Constructible] + public Quell() + { + Hue = 0x225; + + Attributes.SpellChanneling = 1; + Attributes.WeaponSpeed = 20; + Attributes.WeaponDamage = 50; + Attributes.AttackChance = 10; + + WeaponAttributes.HitLeechMana = 100; + WeaponAttributes.UseBestSkill = 1; + } + + public Quell(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094928; // Quell [Replica] + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + public override bool CanFortify => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Unique/ShroudOfDeceit.cs b/Projects/UOContent/Items/Champion Artifacts/Unique/ShroudOfDeceit.cs index 5c16a964c..a8b21b825 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Unique/ShroudOfDeceit.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Unique/ShroudOfDeceit.cs @@ -1,49 +1,49 @@ -namespace Server.Items -{ - public class ShroudOfDeciet : BoneChest - { - [Constructible] - public ShroudOfDeciet() - { - Hue = 0x38F; - - Attributes.RegenHits = 3; - - ArmorAttributes.MageArmor = 1; - - SkillBonuses.Skill_1_Name = SkillName.MagicResist; - SkillBonuses.Skill_1_Value = 10; - } - - public ShroudOfDeciet(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094914; // Shroud of Deceit [Replica] - - public override int BasePhysicalResistance => 11; - public override int BaseFireResistance => 6; - public override int BaseColdResistance => 18; - public override int BasePoisonResistance => 15; - public override int BaseEnergyResistance => 13; - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override bool CanFortify => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ShroudOfDeciet : BoneChest + { + [Constructible] + public ShroudOfDeciet() + { + Hue = 0x38F; + + Attributes.RegenHits = 3; + + ArmorAttributes.MageArmor = 1; + + SkillBonuses.Skill_1_Name = SkillName.MagicResist; + SkillBonuses.Skill_1_Value = 10; + } + + public ShroudOfDeciet(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094914; // Shroud of Deceit [Replica] + + public override int BasePhysicalResistance => 11; + public override int BaseFireResistance => 6; + public override int BaseColdResistance => 18; + public override int BasePoisonResistance => 15; + public override int BaseEnergyResistance => 13; + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + public override bool CanFortify => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Champion Artifacts/Unique/Subdue.cs b/Projects/UOContent/Items/Champion Artifacts/Unique/Subdue.cs index 9f0dd3850..c19278b08 100644 --- a/Projects/UOContent/Items/Champion Artifacts/Unique/Subdue.cs +++ b/Projects/UOContent/Items/Champion Artifacts/Unique/Subdue.cs @@ -1,44 +1,44 @@ -namespace Server.Items -{ - public class Subdue : Scythe - { - [Constructible] - public Subdue() - { - Hue = 0x2cb; - - Attributes.SpellChanneling = 1; - Attributes.WeaponSpeed = 20; - Attributes.WeaponDamage = 50; - Attributes.AttackChance = 10; - - WeaponAttributes.HitLeechMana = 100; - WeaponAttributes.UseBestSkill = 1; - } - - public Subdue(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094930; // Subdue [Replica] - - public override int InitMinHits => 150; - public override int InitMaxHits => 150; - - public override bool CanFortify => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Subdue : Scythe + { + [Constructible] + public Subdue() + { + Hue = 0x2cb; + + Attributes.SpellChanneling = 1; + Attributes.WeaponSpeed = 20; + Attributes.WeaponDamage = 50; + Attributes.AttackChance = 10; + + WeaponAttributes.HitLeechMana = 100; + WeaponAttributes.UseBestSkill = 1; + } + + public Subdue(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1094930; // Subdue [Replica] + + public override int InitMinHits => 150; + public override int InitMaxHits => 150; + + public override bool CanFortify => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Clothing/Artifacts/CrimsonCincture.cs b/Projects/UOContent/Items/Clothing/Artifacts/CrimsonCincture.cs index 58b1ef032..8229aca34 100644 --- a/Projects/UOContent/Items/Clothing/Artifacts/CrimsonCincture.cs +++ b/Projects/UOContent/Items/Clothing/Artifacts/CrimsonCincture.cs @@ -1,35 +1,35 @@ -namespace Server.Items -{ - public class CrimsonCincture : HalfApron, ITokunoDyable - { - [Constructible] - public CrimsonCincture() - { - Hue = 0x485; - - Attributes.BonusDex = 5; - Attributes.BonusHits = 10; - Attributes.RegenHits = 2; - } - - public CrimsonCincture(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075043; // Crimson Cincture - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class CrimsonCincture : HalfApron, ITokunoDyable + { + [Constructible] + public CrimsonCincture() + { + Hue = 0x485; + + Attributes.BonusDex = 5; + Attributes.BonusHits = 10; + Attributes.RegenHits = 2; + } + + public CrimsonCincture(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075043; // Crimson Cincture + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Clothing/Artifacts/DivineCountenance.cs b/Projects/UOContent/Items/Clothing/Artifacts/DivineCountenance.cs index 71df83612..2bea1de05 100644 --- a/Projects/UOContent/Items/Clothing/Artifacts/DivineCountenance.cs +++ b/Projects/UOContent/Items/Clothing/Artifacts/DivineCountenance.cs @@ -1,58 +1,58 @@ -namespace Server.Items -{ - public class DivineCountenance : HornedTribalMask - { - [Constructible] - public DivineCountenance() - { - Hue = 0x482; - - Attributes.BonusInt = 8; - Attributes.RegenMana = 2; - Attributes.ReflectPhysical = 15; - Attributes.LowerManaCost = 8; - } - - public DivineCountenance(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061289; // Divine Countenance - - public override int ArtifactRarity => 11; - - public override int BasePhysicalResistance => 8; - public override int BaseFireResistance => 6; - public override int BaseColdResistance => 9; - public override int BaseEnergyResistance => 25; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Resistances.Physical = 0; - Resistances.Fire = 0; - Resistances.Cold = 0; - Resistances.Energy = 0; - break; - } - } - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class DivineCountenance : HornedTribalMask + { + [Constructible] + public DivineCountenance() + { + Hue = 0x482; + + Attributes.BonusInt = 8; + Attributes.RegenMana = 2; + Attributes.ReflectPhysical = 15; + Attributes.LowerManaCost = 8; + } + + public DivineCountenance(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061289; // Divine Countenance + + public override int ArtifactRarity => 11; + + public override int BasePhysicalResistance => 8; + public override int BaseFireResistance => 6; + public override int BaseColdResistance => 9; + public override int BaseEnergyResistance => 25; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Resistances.Physical = 0; + Resistances.Fire = 0; + Resistances.Cold = 0; + Resistances.Energy = 0; + break; + } + } + } + } +} diff --git a/Projects/UOContent/Items/Clothing/Artifacts/HatOfTheMagi.cs b/Projects/UOContent/Items/Clothing/Artifacts/HatOfTheMagi.cs index 03fa2d6ed..f7fc11610 100644 --- a/Projects/UOContent/Items/Clothing/Artifacts/HatOfTheMagi.cs +++ b/Projects/UOContent/Items/Clothing/Artifacts/HatOfTheMagi.cs @@ -1,53 +1,53 @@ -namespace Server.Items -{ - public class HatOfTheMagi : WizardsHat - { - [Constructible] - public HatOfTheMagi() - { - Hue = 0x481; - - Attributes.BonusInt = 8; - Attributes.RegenMana = 4; - Attributes.SpellDamage = 10; - } - - public HatOfTheMagi(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061597; // Hat of the Magi - - public override int ArtifactRarity => 11; - - public override int BasePoisonResistance => 20; - public override int BaseEnergyResistance => 20; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Resistances.Poison = 0; - Resistances.Energy = 0; - break; - } - } - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class HatOfTheMagi : WizardsHat + { + [Constructible] + public HatOfTheMagi() + { + Hue = 0x481; + + Attributes.BonusInt = 8; + Attributes.RegenMana = 4; + Attributes.SpellDamage = 10; + } + + public HatOfTheMagi(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061597; // Hat of the Magi + + public override int ArtifactRarity => 11; + + public override int BasePoisonResistance => 20; + public override int BaseEnergyResistance => 20; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Resistances.Poison = 0; + Resistances.Energy = 0; + break; + } + } + } + } +} diff --git a/Projects/UOContent/Items/Clothing/Artifacts/HuntersHeaddress.cs b/Projects/UOContent/Items/Clothing/Artifacts/HuntersHeaddress.cs index 05ece8103..e43713b72 100644 --- a/Projects/UOContent/Items/Clothing/Artifacts/HuntersHeaddress.cs +++ b/Projects/UOContent/Items/Clothing/Artifacts/HuntersHeaddress.cs @@ -1,52 +1,52 @@ -namespace Server.Items -{ - public class HuntersHeaddress : DeerMask - { - [Constructible] - public HuntersHeaddress() - { - Hue = 0x594; - - SkillBonuses.SetValues(0, SkillName.Archery, 20); - - Attributes.BonusDex = 8; - Attributes.NightSight = 1; - Attributes.AttackChance = 15; - } - - public HuntersHeaddress(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061595; // Hunter's Headdress - - public override int ArtifactRarity => 11; - - public override int BaseColdResistance => 23; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - switch (version) - { - case 0: - { - Resistances.Cold = 0; - break; - } - } - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class HuntersHeaddress : DeerMask + { + [Constructible] + public HuntersHeaddress() + { + Hue = 0x594; + + SkillBonuses.SetValues(0, SkillName.Archery, 20); + + Attributes.BonusDex = 8; + Attributes.NightSight = 1; + Attributes.AttackChance = 15; + } + + public HuntersHeaddress(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061595; // Hunter's Headdress + + public override int ArtifactRarity => 11; + + public override int BaseColdResistance => 23; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + switch (version) + { + case 0: + { + Resistances.Cold = 0; + break; + } + } + } + } +} diff --git a/Projects/UOContent/Items/Clothing/Artifacts/SpiritOfTheTotem.cs b/Projects/UOContent/Items/Clothing/Artifacts/SpiritOfTheTotem.cs index 6b63788b0..25a3c800f 100644 --- a/Projects/UOContent/Items/Clothing/Artifacts/SpiritOfTheTotem.cs +++ b/Projects/UOContent/Items/Clothing/Artifacts/SpiritOfTheTotem.cs @@ -1,51 +1,51 @@ -namespace Server.Items -{ - public class SpiritOfTheTotem : BearMask - { - [Constructible] - public SpiritOfTheTotem() - { - Hue = 0x455; - - Attributes.BonusStr = 20; - Attributes.ReflectPhysical = 15; - Attributes.AttackChance = 15; - } - - public SpiritOfTheTotem(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061599; // Spirit of the Totem - - public override int ArtifactRarity => 11; - - public override int BasePhysicalResistance => 20; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Resistances.Physical = 0; - break; - } - } - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SpiritOfTheTotem : BearMask + { + [Constructible] + public SpiritOfTheTotem() + { + Hue = 0x455; + + Attributes.BonusStr = 20; + Attributes.ReflectPhysical = 15; + Attributes.AttackChance = 15; + } + + public SpiritOfTheTotem(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061599; // Spirit of the Totem + + public override int ArtifactRarity => 11; + + public override int BasePhysicalResistance => 20; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Resistances.Physical = 0; + break; + } + } + } + } +} diff --git a/Projects/UOContent/Items/Clothing/BaseClothing.cs b/Projects/UOContent/Items/Clothing/BaseClothing.cs index 21d77d458..f6ebbd219 100644 --- a/Projects/UOContent/Items/Clothing/BaseClothing.cs +++ b/Projects/UOContent/Items/Clothing/BaseClothing.cs @@ -1,977 +1,983 @@ -using System; -using System.Collections.Generic; -using Server.Engines.Craft; -using Server.Ethics; -using Server.Factions; -using Server.Network; -using Server.Utilities; - -namespace Server.Items -{ - public enum ClothingQuality - { - Low, - Regular, - Exceptional - } - - public interface IArcaneEquip - { - bool IsArcane { get; } - int CurArcaneCharges { get; set; } - int MaxArcaneCharges { get; set; } - } - - public abstract class BaseClothing : Item, IDyable, IScissorable, IFactionItem, ICraftable, IWearableDurability - { - private Mobile m_Crafter; - private int m_HitPoints; - - private int m_MaxHitPoints; - private ClothingQuality m_Quality; - protected CraftResource m_Resource; - private int m_StrReq = -1; - - public BaseClothing(int itemID, Layer layer, int hue = 0) : base(itemID) - { - Layer = layer; - Hue = hue; - - m_Resource = DefaultResource; - m_Quality = ClothingQuality.Regular; - - m_HitPoints = m_MaxHitPoints = Utility.RandomMinMax(InitMinHits, InitMaxHits); - - Attributes = new AosAttributes(this); - ClothingAttributes = new AosArmorAttributes(this); - SkillBonuses = new AosSkillBonuses(this); - Resistances = new AosElementAttributes(this); - } - - public BaseClothing(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Crafter - { - get => m_Crafter; - set - { - m_Crafter = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int StrRequirement - { - get => m_StrReq == -1 ? Core.AOS ? AosStrReq : OldStrReq : m_StrReq; - set - { - m_StrReq = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public ClothingQuality Quality - { - get => m_Quality; - set - { - m_Quality = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool PlayerConstructed { get; set; } - - public virtual CraftResource DefaultResource => CraftResource.None; - - [CommandProperty(AccessLevel.GameMaster)] - public CraftResource Resource - { - get => m_Resource; - set - { - m_Resource = value; - Hue = CraftResources.GetHue(m_Resource); - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public AosAttributes Attributes { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public AosArmorAttributes ClothingAttributes { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public AosSkillBonuses SkillBonuses { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public AosElementAttributes Resistances { get; private set; } - - public virtual int BasePhysicalResistance => 0; - public virtual int BaseFireResistance => 0; - public virtual int BaseColdResistance => 0; - public virtual int BasePoisonResistance => 0; - public virtual int BaseEnergyResistance => 0; - - public override int PhysicalResistance => BasePhysicalResistance + Resistances.Physical; - public override int FireResistance => BaseFireResistance + Resistances.Fire; - public override int ColdResistance => BaseColdResistance + Resistances.Cold; - public override int PoisonResistance => BasePoisonResistance + Resistances.Poison; - public override int EnergyResistance => BaseEnergyResistance + Resistances.Energy; - - public virtual int ArtifactRarity => 0; - - public virtual int BaseStrBonus => 0; - public virtual int BaseDexBonus => 0; - public virtual int BaseIntBonus => 0; - - public virtual Race RequiredRace => null; - - public virtual int AosStrReq => 10; - public virtual int OldStrReq => 0; - - public virtual bool AllowMaleWearer => true; - public virtual bool AllowFemaleWearer => true; - public virtual bool CanBeBlessed => true; - - public virtual int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, - BaseTool tool, CraftItem craftItem, int resHue) - { - Quality = (ClothingQuality)quality; - - if (makersMark) - Crafter = from; - - if (DefaultResource != CraftResource.None) - { - Type resourceType = typeRes ?? craftItem.Resources[0].ItemType; - - Resource = CraftResources.GetFromType(resourceType); - } - else - { - Hue = resHue; - } - - PlayerConstructed = true; - - CraftContext context = craftSystem.GetContext(from); - - if (context?.DoNotColor == true) - Hue = 0; - - return quality; - } - - public virtual bool Dye(Mobile from, DyeTub sender) - { - if (Deleted) - return false; - if (RootParent is Mobile && from != RootParent) - return false; - - Hue = sender.DyedHue; - - return true; - } - - public virtual bool Scissor(Mobile from, Scissors scissors) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(502437); // Items you wish to cut must be in your backpack. - return false; - } - - if (Ethic.IsImbued(this)) - { - from.SendLocalizedMessage(502440); // Scissors can not be used on that to produce anything. - return false; - } - - CraftSystem system = DefTailoring.CraftSystem; - - CraftItem item = system.CraftItems.SearchFor(GetType()); - - if (item?.Resources.Count == 1 && item.Resources[0].Amount >= 2) - try - { - CraftResourceInfo info = CraftResources.GetInfo(m_Resource); - - Type resourceType = info.ResourceTypes?[0] ?? item.Resources[0].ItemType; - - Item res = (Item)ActivatorUtil.CreateInstance(resourceType); - - ScissorHelper(from, res, PlayerConstructed ? item.Resources[0].Amount / 2 : 1); - - res.LootType = LootType.Regular; - - return true; - } - catch - { - // ignored - } - - from.SendLocalizedMessage(502440); // Scissors can not be used on that to produce anything. - return false; - } - - public virtual bool CanFortify => true; - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxHitPoints - { - get => m_MaxHitPoints; - set - { - m_MaxHitPoints = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int HitPoints - { - get => m_HitPoints; - set - { - if (value != m_HitPoints && MaxHitPoints > 0) - { - m_HitPoints = value; - - if (m_HitPoints < 0) - Delete(); - else if (m_HitPoints > MaxHitPoints) - m_HitPoints = MaxHitPoints; - - InvalidateProperties(); - } - } - } - - public virtual int InitMinHits => 0; - public virtual int InitMaxHits => 0; - - public virtual int OnHit(BaseWeapon weapon, int damageTaken) - { - int absorbed = Utility.RandomMinMax(1, 4); - - // Don't go below zero - damageTaken = Math.Min(absorbed, damageTaken); - - if (Utility.Random(100) < 25) // 25% chance to lower durability - { - if (Core.AOS && ClothingAttributes.SelfRepair > Utility.Random(10)) - { - HitPoints += 2; - } - else - { - int wear; - - if (weapon.Type == WeaponType.Bashing) - wear = absorbed / 2; - else - wear = Utility.Random(2); - - if (wear > 0 && m_MaxHitPoints > 0) - { - if (m_HitPoints >= wear) - { - HitPoints -= wear; - wear = 0; - } - else - { - wear -= HitPoints; - HitPoints = 0; - } - - if (wear > 0) - { - if (m_MaxHitPoints > wear) - { - MaxHitPoints -= wear; - - (Parent as Mobile)?.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1061121); // Your equipment is severely damaged. - } - else - { - Delete(); - } - } - } - } - } - - return damageTaken; - } - - public void UnscaleDurability() - { - int scale = 100 + ClothingAttributes.DurabilityBonus; - - m_HitPoints = (m_HitPoints * 100 + (scale - 1)) / scale; - m_MaxHitPoints = (m_MaxHitPoints * 100 + (scale - 1)) / scale; - - InvalidateProperties(); - } - - public void ScaleDurability() - { - int scale = 100 + ClothingAttributes.DurabilityBonus; - - m_HitPoints = (m_HitPoints * scale + 99) / 100; - m_MaxHitPoints = (m_MaxHitPoints * scale + 99) / 100; - - InvalidateProperties(); - } - - public override bool AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted) => - Ethic.CheckTrade(from, to, newOwner, this) && base.AllowSecureTrade(from, to, newOwner, accepted); - - public override bool CanEquip(Mobile from) - { - if (!Ethic.CheckEquip(from, this)) - return false; - - if (from.AccessLevel < AccessLevel.GameMaster) - { - if (RequiredRace != null && from.Race != RequiredRace) - { - if (RequiredRace == Race.Elf) - from.SendLocalizedMessage(1072203); // Only Elves may use this. - else - from.SendMessage("Only {0} may use this.", RequiredRace.PluralName); - - return false; - } - - if (!AllowMaleWearer && !from.Female) - { - if (AllowFemaleWearer) - from.SendLocalizedMessage(1010388); // Only females can wear this. - else - from.SendMessage("You may not wear this."); - - return false; - } - - if (!AllowFemaleWearer && from.Female) - { - if (AllowMaleWearer) - from.SendLocalizedMessage(1063343); // Only males can wear this. - else - from.SendMessage("You may not wear this."); - - return false; - } - - int strBonus = ComputeStatBonus(StatType.Str); - int strReq = ComputeStatReq(StatType.Str); - - if (from.Str < strReq || from.Str + strBonus < 1) - { - from.SendLocalizedMessage(500213); // You are not strong enough to equip that. - return false; - } - } - - return base.CanEquip(from); - } - - public int ComputeStatReq(StatType type) - { - int v; - - // if (type == StatType.Str) - v = StrRequirement; - - return AOS.Scale(v, 100 - GetLowerStatReq()); - } - - public int ComputeStatBonus(StatType type) => - type switch - { - StatType.Str => BaseStrBonus + Attributes.BonusStr, - StatType.Dex => BaseDexBonus + Attributes.BonusDex, - _ => BaseIntBonus + Attributes.BonusInt - }; - - public virtual void AddStatBonuses(Mobile parent) - { - if (parent == null) - return; - - int strBonus = ComputeStatBonus(StatType.Str); - int dexBonus = ComputeStatBonus(StatType.Dex); - int intBonus = ComputeStatBonus(StatType.Int); - - if (strBonus == 0 && dexBonus == 0 && intBonus == 0) - return; - - string modName = Serial.ToString(); - - if (strBonus != 0) - parent.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero)); - - if (dexBonus != 0) - parent.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero)); - - if (intBonus != 0) - parent.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero)); - } - - public static void ValidateMobile(Mobile m) - { - for (int i = m.Items.Count - 1; i >= 0; --i) - { - if (i >= m.Items.Count) - continue; - - Item item = m.Items[i]; - - if (item is BaseClothing clothing) - { - if (clothing.RequiredRace != null && m.Race != clothing.RequiredRace) - { - if (clothing.RequiredRace == Race.Elf) - m.SendLocalizedMessage(1072203); // Only Elves may use this. - else - m.SendMessage("Only {0} may use this.", clothing.RequiredRace.PluralName); - - m.AddToBackpack(clothing); - } - else if (!clothing.AllowMaleWearer && !m.Female && m.AccessLevel < AccessLevel.GameMaster) - { - if (clothing.AllowFemaleWearer) - m.SendLocalizedMessage(1010388); // Only females can wear this. - else - m.SendMessage("You may not wear this."); - - m.AddToBackpack(clothing); - } - else if (!clothing.AllowFemaleWearer && m.Female && m.AccessLevel < AccessLevel.GameMaster) - { - if (clothing.AllowMaleWearer) - m.SendLocalizedMessage(1063343); // Only males can wear this. - else - m.SendMessage("You may not wear this."); - - m.AddToBackpack(clothing); - } - } - } - } - - public int GetLowerStatReq() - { - if (!Core.AOS) - return 0; - - return ClothingAttributes.LowerStatReq; - } - - public override void OnAdded(IEntity parent) - { - if (parent is Mobile mob) - { - if (Core.AOS) - SkillBonuses.AddTo(mob); - - AddStatBonuses(mob); - mob.CheckStatTimers(); - } - - base.OnAdded(parent); - } - - public override void OnRemoved(IEntity parent) - { - if (parent is Mobile mob) - { - if (Core.AOS) - SkillBonuses.Remove(); - - string modName = Serial.ToString(); - - mob.RemoveStatMod($"{modName}Str"); - mob.RemoveStatMod($"{modName}Dex"); - mob.RemoveStatMod($"{modName}Int"); - - mob.CheckStatTimers(); - } - - base.OnRemoved(parent); - } - - public override void OnAfterDuped(Item newItem) - { - if (!(newItem is BaseClothing clothing)) - return; - - clothing.Attributes = new AosAttributes(newItem, Attributes); - clothing.Resistances = new AosElementAttributes(newItem, Resistances); - clothing.SkillBonuses = new AosSkillBonuses(newItem, SkillBonuses); - clothing.ClothingAttributes = new AosArmorAttributes(newItem, ClothingAttributes); - } - - public override bool AllowEquippedCast(Mobile from) => base.AllowEquippedCast(from) || Attributes.SpellChanneling != 0; - - public override bool CheckPropertyConflict(Mobile m) - { - if (base.CheckPropertyConflict(m)) - return true; - - return Layer switch - { - Layer.Pants => m.FindItemOnLayer(Layer.InnerLegs) != null, - Layer.Shirt => m.FindItemOnLayer(Layer.InnerTorso) != null, - _ => false - }; - } - - private string GetNameString() => Name ?? $"#{LabelNumber}"; - - public override void AddNameProperty(ObjectPropertyList list) - { - var oreType = m_Resource switch - { - CraftResource.DullCopper => 1053108, - CraftResource.ShadowIron => 1053107, - CraftResource.Copper => 1053106, - CraftResource.Bronze => 1053105, - CraftResource.Gold => 1053104, - CraftResource.Agapite => 1053103, - CraftResource.Verite => 1053102, - CraftResource.Valorite => 1053101, - CraftResource.SpinedLeather => 1061118, - CraftResource.HornedLeather => 1061117, - CraftResource.BarbedLeather => 1061116, - CraftResource.RedScales => 1060814, - CraftResource.YellowScales => 1060818, - CraftResource.BlackScales => 1060820, - CraftResource.GreenScales => 1060819, - CraftResource.WhiteScales => 1060821, - CraftResource.BlueScales => 1060815, - _ => 0 - }; - - if (oreType != 0) - list.Add(1053099, "#{0}\t{1}", oreType, GetNameString()); // ~1_oretype~ ~2_armortype~ - else if (Name == null) - list.Add(LabelNumber); - else - list.Add(Name); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_Crafter != null) - list.Add(1050043, m_Crafter.Name); // crafted by ~1_NAME~ - - if (m_FactionState != null) - list.Add(1041350); // faction item - - if (m_Quality == ClothingQuality.Exceptional) - list.Add(1060636); // exceptional - - if (RequiredRace == Race.Elf) - list.Add(1075086); // Elves Only - - SkillBonuses?.GetProperties(list); - - int prop; - - if ((prop = ArtifactRarity) > 0) - list.Add(1061078, prop.ToString()); // artifact rarity ~1_val~ - - if ((prop = Attributes.WeaponDamage) != 0) - list.Add(1060401, prop.ToString()); // damage increase ~1_val~% - - if ((prop = Attributes.DefendChance) != 0) - list.Add(1060408, prop.ToString()); // defense chance increase ~1_val~% - - if ((prop = Attributes.BonusDex) != 0) - list.Add(1060409, prop.ToString()); // dexterity bonus ~1_val~ - - if ((prop = Attributes.EnhancePotions) != 0) - list.Add(1060411, prop.ToString()); // enhance potions ~1_val~% - - if ((prop = Attributes.CastRecovery) != 0) - list.Add(1060412, prop.ToString()); // faster cast recovery ~1_val~ - - if ((prop = Attributes.CastSpeed) != 0) - list.Add(1060413, prop.ToString()); // faster casting ~1_val~ - - if ((prop = Attributes.AttackChance) != 0) - list.Add(1060415, prop.ToString()); // hit chance increase ~1_val~% - - if ((prop = Attributes.BonusHits) != 0) - list.Add(1060431, prop.ToString()); // hit point increase ~1_val~ - - if ((prop = Attributes.BonusInt) != 0) - list.Add(1060432, prop.ToString()); // intelligence bonus ~1_val~ - - if ((prop = Attributes.LowerManaCost) != 0) - list.Add(1060433, prop.ToString()); // lower mana cost ~1_val~% - - if ((prop = Attributes.LowerRegCost) != 0) - list.Add(1060434, prop.ToString()); // lower reagent cost ~1_val~% - - if ((prop = ClothingAttributes.LowerStatReq) != 0) - list.Add(1060435, prop.ToString()); // lower requirements ~1_val~% - - if ((prop = Attributes.Luck) != 0) - list.Add(1060436, prop.ToString()); // luck ~1_val~ - - if ((prop = ClothingAttributes.MageArmor) != 0) - list.Add(1060437); // mage armor - - if ((prop = Attributes.BonusMana) != 0) - list.Add(1060439, prop.ToString()); // mana increase ~1_val~ - - if ((prop = Attributes.RegenMana) != 0) - list.Add(1060440, prop.ToString()); // mana regeneration ~1_val~ - - if ((prop = Attributes.NightSight) != 0) - list.Add(1060441); // night sight - - if ((prop = Attributes.ReflectPhysical) != 0) - list.Add(1060442, prop.ToString()); // reflect physical damage ~1_val~% - - if ((prop = Attributes.RegenStam) != 0) - list.Add(1060443, prop.ToString()); // stamina regeneration ~1_val~ - - if ((prop = Attributes.RegenHits) != 0) - list.Add(1060444, prop.ToString()); // hit point regeneration ~1_val~ - - if ((prop = ClothingAttributes.SelfRepair) != 0) - list.Add(1060450, prop.ToString()); // self repair ~1_val~ - - if ((prop = Attributes.SpellChanneling) != 0) - list.Add(1060482); // spell channeling - - if ((prop = Attributes.SpellDamage) != 0) - list.Add(1060483, prop.ToString()); // spell damage increase ~1_val~% - - if ((prop = Attributes.BonusStam) != 0) - list.Add(1060484, prop.ToString()); // stamina increase ~1_val~ - - if ((prop = Attributes.BonusStr) != 0) - list.Add(1060485, prop.ToString()); // strength bonus ~1_val~ - - if ((prop = Attributes.WeaponSpeed) != 0) - list.Add(1060486, prop.ToString()); // swing speed increase ~1_val~% - - if (Core.ML && (prop = Attributes.IncreasedKarmaLoss) != 0) - list.Add(1075210, prop.ToString()); // Increased Karma Loss ~1val~% - - AddResistanceProperties(list); - - if ((prop = ClothingAttributes.DurabilityBonus) > 0) - list.Add(1060410, prop.ToString()); // durability ~1_val~% - - if ((prop = ComputeStatReq(StatType.Str)) > 0) - list.Add(1061170, prop.ToString()); // strength requirement ~1_val~ - - if (m_HitPoints >= 0 && m_MaxHitPoints > 0) - list.Add(1060639, "{0}\t{1}", m_HitPoints, m_MaxHitPoints); // durability ~1_val~ / ~2_val~ - } - - public override void OnSingleClick(Mobile from) - { - List attrs = new List(); - - AddEquipInfoAttributes(from, attrs); - - int number; - - if (Name == null) - { - number = LabelNumber; - } - else - { - LabelTo(from, Name); - number = 1041000; - } - - if (attrs.Count == 0 && Crafter == null && Name != null) - return; - - EquipmentInfo eqInfo = new EquipmentInfo(number, m_Crafter, false, attrs.ToArray()); - - from.Send(new DisplayEquipmentInfo(this, eqInfo)); - } - - public virtual void AddEquipInfoAttributes(Mobile from, List attrs) - { - if (DisplayLootType) - { - if (LootType == LootType.Blessed) - attrs.Add(new EquipInfoAttribute(1038021)); // blessed - else if (LootType == LootType.Cursed) - attrs.Add(new EquipInfoAttribute(1049643)); // cursed - } - - if (m_FactionState != null) - attrs.Add(new EquipInfoAttribute(1041350)); // faction item - - if (m_Quality == ClothingQuality.Exceptional) - attrs.Add(new EquipInfoAttribute(1018305 - (int)m_Quality)); - } - - public void DistributeBonuses(int amount) - { - for (int i = 0; i < amount; ++i) - switch (Utility.Random(5)) - { - case 0: - ++Resistances.Physical; - break; - case 1: - ++Resistances.Fire; - break; - case 2: - ++Resistances.Cold; - break; - case 3: - ++Resistances.Poison; - break; - case 4: - ++Resistances.Energy; - break; - } - - InvalidateProperties(); - } - - private FactionItem m_FactionState; - - public FactionItem FactionItemState - { - get => m_FactionState; - set - { - m_FactionState = value; - - if (m_FactionState == null) - Hue = 0; - - LootType = m_FactionState == null ? LootType.Regular : LootType.Blessed; - } - } - - private static void SetSaveFlag(ref SaveFlag flags, SaveFlag toSet, bool setIf) - { - if (setIf) - flags |= toSet; - } - - private static bool GetSaveFlag(SaveFlag flags, SaveFlag toGet) => (flags & toGet) != 0; - - [Flags] - private enum SaveFlag - { - None = 0x00000000, - Resource = 0x00000001, - Attributes = 0x00000002, - ClothingAttributes = 0x00000004, - SkillBonuses = 0x00000008, - Resistances = 0x00000010, - MaxHitPoints = 0x00000020, - HitPoints = 0x00000040, - PlayerConstructed = 0x00000080, - Crafter = 0x00000100, - Quality = 0x00000200, - StrReq = 0x00000400 - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(5); // version - - SaveFlag flags = SaveFlag.None; - - SetSaveFlag(ref flags, SaveFlag.Resource, m_Resource != DefaultResource); - SetSaveFlag(ref flags, SaveFlag.Attributes, !Attributes.IsEmpty); - SetSaveFlag(ref flags, SaveFlag.ClothingAttributes, !ClothingAttributes.IsEmpty); - SetSaveFlag(ref flags, SaveFlag.SkillBonuses, !SkillBonuses.IsEmpty); - SetSaveFlag(ref flags, SaveFlag.Resistances, !Resistances.IsEmpty); - SetSaveFlag(ref flags, SaveFlag.MaxHitPoints, m_MaxHitPoints != 0); - SetSaveFlag(ref flags, SaveFlag.HitPoints, m_HitPoints != 0); - SetSaveFlag(ref flags, SaveFlag.PlayerConstructed, PlayerConstructed); - SetSaveFlag(ref flags, SaveFlag.Crafter, m_Crafter != null); - SetSaveFlag(ref flags, SaveFlag.Quality, m_Quality != ClothingQuality.Regular); - SetSaveFlag(ref flags, SaveFlag.StrReq, m_StrReq != -1); - - writer.WriteEncodedInt((int)flags); - - if (GetSaveFlag(flags, SaveFlag.Resource)) - writer.WriteEncodedInt((int)m_Resource); - - if (GetSaveFlag(flags, SaveFlag.Attributes)) - Attributes.Serialize(writer); - - if (GetSaveFlag(flags, SaveFlag.ClothingAttributes)) - ClothingAttributes.Serialize(writer); - - if (GetSaveFlag(flags, SaveFlag.SkillBonuses)) - SkillBonuses.Serialize(writer); - - if (GetSaveFlag(flags, SaveFlag.Resistances)) - Resistances.Serialize(writer); - - if (GetSaveFlag(flags, SaveFlag.MaxHitPoints)) - writer.WriteEncodedInt(m_MaxHitPoints); - - if (GetSaveFlag(flags, SaveFlag.HitPoints)) - writer.WriteEncodedInt(m_HitPoints); - - if (GetSaveFlag(flags, SaveFlag.Crafter)) - writer.Write(m_Crafter); - - if (GetSaveFlag(flags, SaveFlag.Quality)) - writer.WriteEncodedInt((int)m_Quality); - - if (GetSaveFlag(flags, SaveFlag.StrReq)) - writer.WriteEncodedInt(m_StrReq); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 5: - { - SaveFlag flags = (SaveFlag)reader.ReadEncodedInt(); - - if (GetSaveFlag(flags, SaveFlag.Resource)) - m_Resource = (CraftResource)reader.ReadEncodedInt(); - else - m_Resource = DefaultResource; - - if (GetSaveFlag(flags, SaveFlag.Attributes)) - Attributes = new AosAttributes(this, reader); - else - Attributes = new AosAttributes(this); - - if (GetSaveFlag(flags, SaveFlag.ClothingAttributes)) - ClothingAttributes = new AosArmorAttributes(this, reader); - else - ClothingAttributes = new AosArmorAttributes(this); - - if (GetSaveFlag(flags, SaveFlag.SkillBonuses)) - SkillBonuses = new AosSkillBonuses(this, reader); - else - SkillBonuses = new AosSkillBonuses(this); - - if (GetSaveFlag(flags, SaveFlag.Resistances)) - Resistances = new AosElementAttributes(this, reader); - else - Resistances = new AosElementAttributes(this); - - if (GetSaveFlag(flags, SaveFlag.MaxHitPoints)) - m_MaxHitPoints = reader.ReadEncodedInt(); - - if (GetSaveFlag(flags, SaveFlag.HitPoints)) - m_HitPoints = reader.ReadEncodedInt(); - - if (GetSaveFlag(flags, SaveFlag.Crafter)) - m_Crafter = reader.ReadMobile(); - - if (GetSaveFlag(flags, SaveFlag.Quality)) - m_Quality = (ClothingQuality)reader.ReadEncodedInt(); - else - m_Quality = ClothingQuality.Regular; - - if (GetSaveFlag(flags, SaveFlag.StrReq)) - m_StrReq = reader.ReadEncodedInt(); - else - m_StrReq = -1; - - if (GetSaveFlag(flags, SaveFlag.PlayerConstructed)) - PlayerConstructed = true; - - break; - } - case 4: - { - m_Resource = (CraftResource)reader.ReadInt(); - - goto case 3; - } - case 3: - { - Attributes = new AosAttributes(this, reader); - ClothingAttributes = new AosArmorAttributes(this, reader); - SkillBonuses = new AosSkillBonuses(this, reader); - Resistances = new AosElementAttributes(this, reader); - - goto case 2; - } - case 2: - { - PlayerConstructed = reader.ReadBool(); - goto case 1; - } - case 1: - { - m_Crafter = reader.ReadMobile(); - m_Quality = (ClothingQuality)reader.ReadInt(); - break; - } - case 0: - { - m_Crafter = null; - m_Quality = ClothingQuality.Regular; - break; - } - } - - if (version < 2) - PlayerConstructed = true; // we don't know, so, assume it's crafted - - if (version < 3) - { - Attributes = new AosAttributes(this); - ClothingAttributes = new AosArmorAttributes(this); - SkillBonuses = new AosSkillBonuses(this); - Resistances = new AosElementAttributes(this); - } - - if (version < 4) - m_Resource = DefaultResource; - - if (m_MaxHitPoints == 0 && m_HitPoints == 0) - m_HitPoints = m_MaxHitPoints = Utility.RandomMinMax(InitMinHits, InitMaxHits); - - if (Parent is Mobile parent) - { - if (Core.AOS) - SkillBonuses.AddTo(parent); - - AddStatBonuses(parent); - parent.CheckStatTimers(); - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Engines.Craft; +using Server.Ethics; +using Server.Factions; +using Server.Network; +using Server.Utilities; + +namespace Server.Items +{ + public enum ClothingQuality + { + Low, + Regular, + Exceptional + } + + public interface IArcaneEquip + { + bool IsArcane { get; } + int CurArcaneCharges { get; set; } + int MaxArcaneCharges { get; set; } + } + + public abstract class BaseClothing : Item, IDyable, IScissorable, IFactionItem, ICraftable, IWearableDurability + { + private Mobile m_Crafter; + + private FactionItem m_FactionState; + private int m_HitPoints; + + private int m_MaxHitPoints; + private ClothingQuality m_Quality; + protected CraftResource m_Resource; + private int m_StrReq = -1; + + public BaseClothing(int itemID, Layer layer, int hue = 0) : base(itemID) + { + Layer = layer; + Hue = hue; + + m_Resource = DefaultResource; + m_Quality = ClothingQuality.Regular; + + m_HitPoints = m_MaxHitPoints = Utility.RandomMinMax(InitMinHits, InitMaxHits); + + Attributes = new AosAttributes(this); + ClothingAttributes = new AosArmorAttributes(this); + SkillBonuses = new AosSkillBonuses(this); + Resistances = new AosElementAttributes(this); + } + + public BaseClothing(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Crafter + { + get => m_Crafter; + set + { + m_Crafter = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int StrRequirement + { + get => m_StrReq == -1 ? Core.AOS ? AosStrReq : OldStrReq : m_StrReq; + set + { + m_StrReq = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public ClothingQuality Quality + { + get => m_Quality; + set + { + m_Quality = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool PlayerConstructed { get; set; } + + public virtual CraftResource DefaultResource => CraftResource.None; + + [CommandProperty(AccessLevel.GameMaster)] + public CraftResource Resource + { + get => m_Resource; + set + { + m_Resource = value; + Hue = CraftResources.GetHue(m_Resource); + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public AosAttributes Attributes { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public AosArmorAttributes ClothingAttributes { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public AosSkillBonuses SkillBonuses { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public AosElementAttributes Resistances { get; private set; } + + public virtual int BasePhysicalResistance => 0; + public virtual int BaseFireResistance => 0; + public virtual int BaseColdResistance => 0; + public virtual int BasePoisonResistance => 0; + public virtual int BaseEnergyResistance => 0; + + public override int PhysicalResistance => BasePhysicalResistance + Resistances.Physical; + public override int FireResistance => BaseFireResistance + Resistances.Fire; + public override int ColdResistance => BaseColdResistance + Resistances.Cold; + public override int PoisonResistance => BasePoisonResistance + Resistances.Poison; + public override int EnergyResistance => BaseEnergyResistance + Resistances.Energy; + + public virtual int ArtifactRarity => 0; + + public virtual int BaseStrBonus => 0; + public virtual int BaseDexBonus => 0; + public virtual int BaseIntBonus => 0; + + public virtual Race RequiredRace => null; + + public virtual int AosStrReq => 10; + public virtual int OldStrReq => 0; + + public virtual bool AllowMaleWearer => true; + public virtual bool AllowFemaleWearer => true; + public virtual bool CanBeBlessed => true; + + public virtual int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, + BaseTool tool, CraftItem craftItem, int resHue + ) + { + Quality = (ClothingQuality)quality; + + if (makersMark) + Crafter = from; + + if (DefaultResource != CraftResource.None) + { + var resourceType = typeRes ?? craftItem.Resources[0].ItemType; + + Resource = CraftResources.GetFromType(resourceType); + } + else + { + Hue = resHue; + } + + PlayerConstructed = true; + + var context = craftSystem.GetContext(from); + + if (context?.DoNotColor == true) + Hue = 0; + + return quality; + } + + public virtual bool Dye(Mobile from, DyeTub sender) + { + if (Deleted) + return false; + if (RootParent is Mobile && from != RootParent) + return false; + + Hue = sender.DyedHue; + + return true; + } + + public FactionItem FactionItemState + { + get => m_FactionState; + set + { + m_FactionState = value; + + if (m_FactionState == null) + Hue = 0; + + LootType = m_FactionState == null ? LootType.Regular : LootType.Blessed; + } + } + + public virtual bool Scissor(Mobile from, Scissors scissors) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(502437); // Items you wish to cut must be in your backpack. + return false; + } + + if (Ethic.IsImbued(this)) + { + from.SendLocalizedMessage(502440); // Scissors can not be used on that to produce anything. + return false; + } + + var system = DefTailoring.CraftSystem; + + var item = system.CraftItems.SearchFor(GetType()); + + if (item?.Resources.Count == 1 && item.Resources[0].Amount >= 2) + try + { + var info = CraftResources.GetInfo(m_Resource); + + var resourceType = info.ResourceTypes?[0] ?? item.Resources[0].ItemType; + + var res = (Item)ActivatorUtil.CreateInstance(resourceType); + + ScissorHelper(from, res, PlayerConstructed ? item.Resources[0].Amount / 2 : 1); + + res.LootType = LootType.Regular; + + return true; + } + catch + { + // ignored + } + + from.SendLocalizedMessage(502440); // Scissors can not be used on that to produce anything. + return false; + } + + public virtual bool CanFortify => true; + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxHitPoints + { + get => m_MaxHitPoints; + set + { + m_MaxHitPoints = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int HitPoints + { + get => m_HitPoints; + set + { + if (value != m_HitPoints && MaxHitPoints > 0) + { + m_HitPoints = value; + + if (m_HitPoints < 0) + Delete(); + else if (m_HitPoints > MaxHitPoints) + m_HitPoints = MaxHitPoints; + + InvalidateProperties(); + } + } + } + + public virtual int InitMinHits => 0; + public virtual int InitMaxHits => 0; + + public virtual int OnHit(BaseWeapon weapon, int damageTaken) + { + var absorbed = Utility.RandomMinMax(1, 4); + + // Don't go below zero + damageTaken = Math.Min(absorbed, damageTaken); + + if (Utility.Random(100) < 25) // 25% chance to lower durability + { + if (Core.AOS && ClothingAttributes.SelfRepair > Utility.Random(10)) + { + HitPoints += 2; + } + else + { + int wear; + + if (weapon.Type == WeaponType.Bashing) + wear = absorbed / 2; + else + wear = Utility.Random(2); + + if (wear > 0 && m_MaxHitPoints > 0) + { + if (m_HitPoints >= wear) + { + HitPoints -= wear; + wear = 0; + } + else + { + wear -= HitPoints; + HitPoints = 0; + } + + if (wear > 0) + { + if (m_MaxHitPoints > wear) + { + MaxHitPoints -= wear; + + (Parent as Mobile)?.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1061121 + ); // Your equipment is severely damaged. + } + else + { + Delete(); + } + } + } + } + } + + return damageTaken; + } + + public void UnscaleDurability() + { + var scale = 100 + ClothingAttributes.DurabilityBonus; + + m_HitPoints = (m_HitPoints * 100 + (scale - 1)) / scale; + m_MaxHitPoints = (m_MaxHitPoints * 100 + (scale - 1)) / scale; + + InvalidateProperties(); + } + + public void ScaleDurability() + { + var scale = 100 + ClothingAttributes.DurabilityBonus; + + m_HitPoints = (m_HitPoints * scale + 99) / 100; + m_MaxHitPoints = (m_MaxHitPoints * scale + 99) / 100; + + InvalidateProperties(); + } + + public override bool AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted) => + Ethic.CheckTrade(from, to, newOwner, this) && base.AllowSecureTrade(from, to, newOwner, accepted); + + public override bool CanEquip(Mobile from) + { + if (!Ethic.CheckEquip(from, this)) + return false; + + if (from.AccessLevel < AccessLevel.GameMaster) + { + if (RequiredRace != null && from.Race != RequiredRace) + { + if (RequiredRace == Race.Elf) + from.SendLocalizedMessage(1072203); // Only Elves may use this. + else + from.SendMessage("Only {0} may use this.", RequiredRace.PluralName); + + return false; + } + + if (!AllowMaleWearer && !from.Female) + { + if (AllowFemaleWearer) + from.SendLocalizedMessage(1010388); // Only females can wear this. + else + from.SendMessage("You may not wear this."); + + return false; + } + + if (!AllowFemaleWearer && from.Female) + { + if (AllowMaleWearer) + from.SendLocalizedMessage(1063343); // Only males can wear this. + else + from.SendMessage("You may not wear this."); + + return false; + } + + var strBonus = ComputeStatBonus(StatType.Str); + var strReq = ComputeStatReq(StatType.Str); + + if (from.Str < strReq || from.Str + strBonus < 1) + { + from.SendLocalizedMessage(500213); // You are not strong enough to equip that. + return false; + } + } + + return base.CanEquip(from); + } + + public int ComputeStatReq(StatType type) + { + int v; + + // if (type == StatType.Str) + v = StrRequirement; + + return AOS.Scale(v, 100 - GetLowerStatReq()); + } + + public int ComputeStatBonus(StatType type) => + type switch + { + StatType.Str => BaseStrBonus + Attributes.BonusStr, + StatType.Dex => BaseDexBonus + Attributes.BonusDex, + _ => BaseIntBonus + Attributes.BonusInt + }; + + public virtual void AddStatBonuses(Mobile parent) + { + if (parent == null) + return; + + var strBonus = ComputeStatBonus(StatType.Str); + var dexBonus = ComputeStatBonus(StatType.Dex); + var intBonus = ComputeStatBonus(StatType.Int); + + if (strBonus == 0 && dexBonus == 0 && intBonus == 0) + return; + + var modName = Serial.ToString(); + + if (strBonus != 0) + parent.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero)); + + if (dexBonus != 0) + parent.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero)); + + if (intBonus != 0) + parent.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero)); + } + + public static void ValidateMobile(Mobile m) + { + for (var i = m.Items.Count - 1; i >= 0; --i) + { + if (i >= m.Items.Count) + continue; + + var item = m.Items[i]; + + if (item is BaseClothing clothing) + { + if (clothing.RequiredRace != null && m.Race != clothing.RequiredRace) + { + if (clothing.RequiredRace == Race.Elf) + m.SendLocalizedMessage(1072203); // Only Elves may use this. + else + m.SendMessage("Only {0} may use this.", clothing.RequiredRace.PluralName); + + m.AddToBackpack(clothing); + } + else if (!clothing.AllowMaleWearer && !m.Female && m.AccessLevel < AccessLevel.GameMaster) + { + if (clothing.AllowFemaleWearer) + m.SendLocalizedMessage(1010388); // Only females can wear this. + else + m.SendMessage("You may not wear this."); + + m.AddToBackpack(clothing); + } + else if (!clothing.AllowFemaleWearer && m.Female && m.AccessLevel < AccessLevel.GameMaster) + { + if (clothing.AllowMaleWearer) + m.SendLocalizedMessage(1063343); // Only males can wear this. + else + m.SendMessage("You may not wear this."); + + m.AddToBackpack(clothing); + } + } + } + } + + public int GetLowerStatReq() + { + if (!Core.AOS) + return 0; + + return ClothingAttributes.LowerStatReq; + } + + public override void OnAdded(IEntity parent) + { + if (parent is Mobile mob) + { + if (Core.AOS) + SkillBonuses.AddTo(mob); + + AddStatBonuses(mob); + mob.CheckStatTimers(); + } + + base.OnAdded(parent); + } + + public override void OnRemoved(IEntity parent) + { + if (parent is Mobile mob) + { + if (Core.AOS) + SkillBonuses.Remove(); + + var modName = Serial.ToString(); + + mob.RemoveStatMod($"{modName}Str"); + mob.RemoveStatMod($"{modName}Dex"); + mob.RemoveStatMod($"{modName}Int"); + + mob.CheckStatTimers(); + } + + base.OnRemoved(parent); + } + + public override void OnAfterDuped(Item newItem) + { + if (!(newItem is BaseClothing clothing)) + return; + + clothing.Attributes = new AosAttributes(newItem, Attributes); + clothing.Resistances = new AosElementAttributes(newItem, Resistances); + clothing.SkillBonuses = new AosSkillBonuses(newItem, SkillBonuses); + clothing.ClothingAttributes = new AosArmorAttributes(newItem, ClothingAttributes); + } + + public override bool AllowEquippedCast(Mobile from) => + base.AllowEquippedCast(from) || Attributes.SpellChanneling != 0; + + public override bool CheckPropertyConflict(Mobile m) + { + if (base.CheckPropertyConflict(m)) + return true; + + return Layer switch + { + Layer.Pants => m.FindItemOnLayer(Layer.InnerLegs) != null, + Layer.Shirt => m.FindItemOnLayer(Layer.InnerTorso) != null, + _ => false + }; + } + + private string GetNameString() => Name ?? $"#{LabelNumber}"; + + public override void AddNameProperty(ObjectPropertyList list) + { + var oreType = m_Resource switch + { + CraftResource.DullCopper => 1053108, + CraftResource.ShadowIron => 1053107, + CraftResource.Copper => 1053106, + CraftResource.Bronze => 1053105, + CraftResource.Gold => 1053104, + CraftResource.Agapite => 1053103, + CraftResource.Verite => 1053102, + CraftResource.Valorite => 1053101, + CraftResource.SpinedLeather => 1061118, + CraftResource.HornedLeather => 1061117, + CraftResource.BarbedLeather => 1061116, + CraftResource.RedScales => 1060814, + CraftResource.YellowScales => 1060818, + CraftResource.BlackScales => 1060820, + CraftResource.GreenScales => 1060819, + CraftResource.WhiteScales => 1060821, + CraftResource.BlueScales => 1060815, + _ => 0 + }; + + if (oreType != 0) + list.Add(1053099, "#{0}\t{1}", oreType, GetNameString()); // ~1_oretype~ ~2_armortype~ + else if (Name == null) + list.Add(LabelNumber); + else + list.Add(Name); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_Crafter != null) + list.Add(1050043, m_Crafter.Name); // crafted by ~1_NAME~ + + if (m_FactionState != null) + list.Add(1041350); // faction item + + if (m_Quality == ClothingQuality.Exceptional) + list.Add(1060636); // exceptional + + if (RequiredRace == Race.Elf) + list.Add(1075086); // Elves Only + + SkillBonuses?.GetProperties(list); + + int prop; + + if ((prop = ArtifactRarity) > 0) + list.Add(1061078, prop.ToString()); // artifact rarity ~1_val~ + + if ((prop = Attributes.WeaponDamage) != 0) + list.Add(1060401, prop.ToString()); // damage increase ~1_val~% + + if ((prop = Attributes.DefendChance) != 0) + list.Add(1060408, prop.ToString()); // defense chance increase ~1_val~% + + if ((prop = Attributes.BonusDex) != 0) + list.Add(1060409, prop.ToString()); // dexterity bonus ~1_val~ + + if ((prop = Attributes.EnhancePotions) != 0) + list.Add(1060411, prop.ToString()); // enhance potions ~1_val~% + + if ((prop = Attributes.CastRecovery) != 0) + list.Add(1060412, prop.ToString()); // faster cast recovery ~1_val~ + + if ((prop = Attributes.CastSpeed) != 0) + list.Add(1060413, prop.ToString()); // faster casting ~1_val~ + + if ((prop = Attributes.AttackChance) != 0) + list.Add(1060415, prop.ToString()); // hit chance increase ~1_val~% + + if ((prop = Attributes.BonusHits) != 0) + list.Add(1060431, prop.ToString()); // hit point increase ~1_val~ + + if ((prop = Attributes.BonusInt) != 0) + list.Add(1060432, prop.ToString()); // intelligence bonus ~1_val~ + + if ((prop = Attributes.LowerManaCost) != 0) + list.Add(1060433, prop.ToString()); // lower mana cost ~1_val~% + + if ((prop = Attributes.LowerRegCost) != 0) + list.Add(1060434, prop.ToString()); // lower reagent cost ~1_val~% + + if ((prop = ClothingAttributes.LowerStatReq) != 0) + list.Add(1060435, prop.ToString()); // lower requirements ~1_val~% + + if ((prop = Attributes.Luck) != 0) + list.Add(1060436, prop.ToString()); // luck ~1_val~ + + if ((prop = ClothingAttributes.MageArmor) != 0) + list.Add(1060437); // mage armor + + if ((prop = Attributes.BonusMana) != 0) + list.Add(1060439, prop.ToString()); // mana increase ~1_val~ + + if ((prop = Attributes.RegenMana) != 0) + list.Add(1060440, prop.ToString()); // mana regeneration ~1_val~ + + if ((prop = Attributes.NightSight) != 0) + list.Add(1060441); // night sight + + if ((prop = Attributes.ReflectPhysical) != 0) + list.Add(1060442, prop.ToString()); // reflect physical damage ~1_val~% + + if ((prop = Attributes.RegenStam) != 0) + list.Add(1060443, prop.ToString()); // stamina regeneration ~1_val~ + + if ((prop = Attributes.RegenHits) != 0) + list.Add(1060444, prop.ToString()); // hit point regeneration ~1_val~ + + if ((prop = ClothingAttributes.SelfRepair) != 0) + list.Add(1060450, prop.ToString()); // self repair ~1_val~ + + if ((prop = Attributes.SpellChanneling) != 0) + list.Add(1060482); // spell channeling + + if ((prop = Attributes.SpellDamage) != 0) + list.Add(1060483, prop.ToString()); // spell damage increase ~1_val~% + + if ((prop = Attributes.BonusStam) != 0) + list.Add(1060484, prop.ToString()); // stamina increase ~1_val~ + + if ((prop = Attributes.BonusStr) != 0) + list.Add(1060485, prop.ToString()); // strength bonus ~1_val~ + + if ((prop = Attributes.WeaponSpeed) != 0) + list.Add(1060486, prop.ToString()); // swing speed increase ~1_val~% + + if (Core.ML && (prop = Attributes.IncreasedKarmaLoss) != 0) + list.Add(1075210, prop.ToString()); // Increased Karma Loss ~1val~% + + AddResistanceProperties(list); + + if ((prop = ClothingAttributes.DurabilityBonus) > 0) + list.Add(1060410, prop.ToString()); // durability ~1_val~% + + if ((prop = ComputeStatReq(StatType.Str)) > 0) + list.Add(1061170, prop.ToString()); // strength requirement ~1_val~ + + if (m_HitPoints >= 0 && m_MaxHitPoints > 0) + list.Add(1060639, "{0}\t{1}", m_HitPoints, m_MaxHitPoints); // durability ~1_val~ / ~2_val~ + } + + public override void OnSingleClick(Mobile from) + { + var attrs = new List(); + + AddEquipInfoAttributes(from, attrs); + + int number; + + if (Name == null) + { + number = LabelNumber; + } + else + { + LabelTo(from, Name); + number = 1041000; + } + + if (attrs.Count == 0 && Crafter == null && Name != null) + return; + + var eqInfo = new EquipmentInfo(number, m_Crafter, false, attrs.ToArray()); + + from.Send(new DisplayEquipmentInfo(this, eqInfo)); + } + + public virtual void AddEquipInfoAttributes(Mobile from, List attrs) + { + if (DisplayLootType) + { + if (LootType == LootType.Blessed) + attrs.Add(new EquipInfoAttribute(1038021)); // blessed + else if (LootType == LootType.Cursed) + attrs.Add(new EquipInfoAttribute(1049643)); // cursed + } + + if (m_FactionState != null) + attrs.Add(new EquipInfoAttribute(1041350)); // faction item + + if (m_Quality == ClothingQuality.Exceptional) + attrs.Add(new EquipInfoAttribute(1018305 - (int)m_Quality)); + } + + public void DistributeBonuses(int amount) + { + for (var i = 0; i < amount; ++i) + switch (Utility.Random(5)) + { + case 0: + ++Resistances.Physical; + break; + case 1: + ++Resistances.Fire; + break; + case 2: + ++Resistances.Cold; + break; + case 3: + ++Resistances.Poison; + break; + case 4: + ++Resistances.Energy; + break; + } + + InvalidateProperties(); + } + + private static void SetSaveFlag(ref SaveFlag flags, SaveFlag toSet, bool setIf) + { + if (setIf) + flags |= toSet; + } + + private static bool GetSaveFlag(SaveFlag flags, SaveFlag toGet) => (flags & toGet) != 0; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(5); // version + + var flags = SaveFlag.None; + + SetSaveFlag(ref flags, SaveFlag.Resource, m_Resource != DefaultResource); + SetSaveFlag(ref flags, SaveFlag.Attributes, !Attributes.IsEmpty); + SetSaveFlag(ref flags, SaveFlag.ClothingAttributes, !ClothingAttributes.IsEmpty); + SetSaveFlag(ref flags, SaveFlag.SkillBonuses, !SkillBonuses.IsEmpty); + SetSaveFlag(ref flags, SaveFlag.Resistances, !Resistances.IsEmpty); + SetSaveFlag(ref flags, SaveFlag.MaxHitPoints, m_MaxHitPoints != 0); + SetSaveFlag(ref flags, SaveFlag.HitPoints, m_HitPoints != 0); + SetSaveFlag(ref flags, SaveFlag.PlayerConstructed, PlayerConstructed); + SetSaveFlag(ref flags, SaveFlag.Crafter, m_Crafter != null); + SetSaveFlag(ref flags, SaveFlag.Quality, m_Quality != ClothingQuality.Regular); + SetSaveFlag(ref flags, SaveFlag.StrReq, m_StrReq != -1); + + writer.WriteEncodedInt((int)flags); + + if (GetSaveFlag(flags, SaveFlag.Resource)) + writer.WriteEncodedInt((int)m_Resource); + + if (GetSaveFlag(flags, SaveFlag.Attributes)) + Attributes.Serialize(writer); + + if (GetSaveFlag(flags, SaveFlag.ClothingAttributes)) + ClothingAttributes.Serialize(writer); + + if (GetSaveFlag(flags, SaveFlag.SkillBonuses)) + SkillBonuses.Serialize(writer); + + if (GetSaveFlag(flags, SaveFlag.Resistances)) + Resistances.Serialize(writer); + + if (GetSaveFlag(flags, SaveFlag.MaxHitPoints)) + writer.WriteEncodedInt(m_MaxHitPoints); + + if (GetSaveFlag(flags, SaveFlag.HitPoints)) + writer.WriteEncodedInt(m_HitPoints); + + if (GetSaveFlag(flags, SaveFlag.Crafter)) + writer.Write(m_Crafter); + + if (GetSaveFlag(flags, SaveFlag.Quality)) + writer.WriteEncodedInt((int)m_Quality); + + if (GetSaveFlag(flags, SaveFlag.StrReq)) + writer.WriteEncodedInt(m_StrReq); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 5: + { + var flags = (SaveFlag)reader.ReadEncodedInt(); + + if (GetSaveFlag(flags, SaveFlag.Resource)) + m_Resource = (CraftResource)reader.ReadEncodedInt(); + else + m_Resource = DefaultResource; + + if (GetSaveFlag(flags, SaveFlag.Attributes)) + Attributes = new AosAttributes(this, reader); + else + Attributes = new AosAttributes(this); + + if (GetSaveFlag(flags, SaveFlag.ClothingAttributes)) + ClothingAttributes = new AosArmorAttributes(this, reader); + else + ClothingAttributes = new AosArmorAttributes(this); + + if (GetSaveFlag(flags, SaveFlag.SkillBonuses)) + SkillBonuses = new AosSkillBonuses(this, reader); + else + SkillBonuses = new AosSkillBonuses(this); + + if (GetSaveFlag(flags, SaveFlag.Resistances)) + Resistances = new AosElementAttributes(this, reader); + else + Resistances = new AosElementAttributes(this); + + if (GetSaveFlag(flags, SaveFlag.MaxHitPoints)) + m_MaxHitPoints = reader.ReadEncodedInt(); + + if (GetSaveFlag(flags, SaveFlag.HitPoints)) + m_HitPoints = reader.ReadEncodedInt(); + + if (GetSaveFlag(flags, SaveFlag.Crafter)) + m_Crafter = reader.ReadMobile(); + + if (GetSaveFlag(flags, SaveFlag.Quality)) + m_Quality = (ClothingQuality)reader.ReadEncodedInt(); + else + m_Quality = ClothingQuality.Regular; + + if (GetSaveFlag(flags, SaveFlag.StrReq)) + m_StrReq = reader.ReadEncodedInt(); + else + m_StrReq = -1; + + if (GetSaveFlag(flags, SaveFlag.PlayerConstructed)) + PlayerConstructed = true; + + break; + } + case 4: + { + m_Resource = (CraftResource)reader.ReadInt(); + + goto case 3; + } + case 3: + { + Attributes = new AosAttributes(this, reader); + ClothingAttributes = new AosArmorAttributes(this, reader); + SkillBonuses = new AosSkillBonuses(this, reader); + Resistances = new AosElementAttributes(this, reader); + + goto case 2; + } + case 2: + { + PlayerConstructed = reader.ReadBool(); + goto case 1; + } + case 1: + { + m_Crafter = reader.ReadMobile(); + m_Quality = (ClothingQuality)reader.ReadInt(); + break; + } + case 0: + { + m_Crafter = null; + m_Quality = ClothingQuality.Regular; + break; + } + } + + if (version < 2) + PlayerConstructed = true; // we don't know, so, assume it's crafted + + if (version < 3) + { + Attributes = new AosAttributes(this); + ClothingAttributes = new AosArmorAttributes(this); + SkillBonuses = new AosSkillBonuses(this); + Resistances = new AosElementAttributes(this); + } + + if (version < 4) + m_Resource = DefaultResource; + + if (m_MaxHitPoints == 0 && m_HitPoints == 0) + m_HitPoints = m_MaxHitPoints = Utility.RandomMinMax(InitMinHits, InitMaxHits); + + if (Parent is Mobile parent) + { + if (Core.AOS) + SkillBonuses.AddTo(parent); + + AddStatBonuses(parent); + parent.CheckStatTimers(); + } + } + + [Flags] + private enum SaveFlag + { + None = 0x00000000, + Resource = 0x00000001, + Attributes = 0x00000002, + ClothingAttributes = 0x00000004, + SkillBonuses = 0x00000008, + Resistances = 0x00000010, + MaxHitPoints = 0x00000020, + HitPoints = 0x00000040, + PlayerConstructed = 0x00000080, + Crafter = 0x00000100, + Quality = 0x00000200, + StrReq = 0x00000400 + } + } +} diff --git a/Projects/UOContent/Items/Clothing/Cloaks.cs b/Projects/UOContent/Items/Clothing/Cloaks.cs index 02d23e035..d98e890fe 100644 --- a/Projects/UOContent/Items/Clothing/Cloaks.cs +++ b/Projects/UOContent/Items/Clothing/Cloaks.cs @@ -1,289 +1,293 @@ -using Server.Engines.VeteranRewards; - -namespace Server.Items -{ - public abstract class BaseCloak : BaseClothing - { - public BaseCloak(int itemID, int hue = 0) : base(itemID, Layer.Cloak, hue) - { - } - - public BaseCloak(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable] - public class Cloak : BaseCloak, IArcaneEquip - { - [Constructible] - public Cloak(int hue = 0) : base(0x1515, hue) => Weight = 5.0; - - public Cloak(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - if (IsArcane) - { - writer.Write(true); - writer.Write(m_CurArcaneCharges); - writer.Write(m_MaxArcaneCharges); - } - else - { - writer.Write(false); - } - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - if (reader.ReadBool()) - { - m_CurArcaneCharges = reader.ReadInt(); - m_MaxArcaneCharges = reader.ReadInt(); - - if (Hue == 2118) - Hue = ArcaneGem.DefaultArcaneHue; - } - - break; - } - } - - if (Weight == 4.0) - Weight = 5.0; - } - - private int m_MaxArcaneCharges, m_CurArcaneCharges; - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxArcaneCharges - { - get => m_MaxArcaneCharges; - set - { - m_MaxArcaneCharges = value; - InvalidateProperties(); - Update(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int CurArcaneCharges - { - get => m_CurArcaneCharges; - set - { - m_CurArcaneCharges = value; - InvalidateProperties(); - Update(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsArcane => m_MaxArcaneCharges > 0 && m_CurArcaneCharges >= 0; - - public void Update() - { - if (IsArcane) - ItemID = 0x26AD; - else if (ItemID == 0x26AD) - ItemID = 0x1515; - - if (IsArcane && CurArcaneCharges == 0) - Hue = 0; - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (IsArcane) - list.Add(1061837, "{0}\t{1}", m_CurArcaneCharges, m_MaxArcaneCharges); // arcane charges: ~1_val~ / ~2_val~ - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - if (IsArcane) - LabelTo(from, 1061837, $"{m_CurArcaneCharges}\t{m_MaxArcaneCharges}"); - } - - public void Flip() - { - if (ItemID == 0x1515) - ItemID = 0x1530; - else if (ItemID == 0x1530) - ItemID = 0x1515; - } - } - - [Flippable] - public class RewardCloak : BaseCloak, IRewardItem - { - private int m_LabelNumber; - - [Constructible] - public RewardCloak(int hue = 0, int labelNumber = 0) : base(0x1515, hue) - { - Weight = 5.0; - LootType = LootType.Blessed; - - m_LabelNumber = labelNumber; - } - - public RewardCloak(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Number - { - get => m_LabelNumber; - set - { - m_LabelNumber = value; - InvalidateProperties(); - } - } - - public override int LabelNumber - { - get - { - if (m_LabelNumber > 0) - return m_LabelNumber; - - return base.LabelNumber; - } - } - - public override int BasePhysicalResistance => 3; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem { get; set; } - - public override void OnAdded(IEntity parent) - { - base.OnAdded(parent); - - if (parent is Mobile mobile) - mobile.VirtualArmorMod += 2; - } - - public override void OnRemoved(IEntity parent) - { - base.OnRemoved(parent); - - if (parent is Mobile mobile) - mobile.VirtualArmorMod -= 2; - } - - public override bool Dye(Mobile from, DyeTub sender) - { - from.SendLocalizedMessage(sender.FailMessage); - return false; - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Core.ML && IsRewardItem) - list.Add(RewardSystem.GetRewardYearLabel(this, - new object[] { Hue, m_LabelNumber })); // X Year Veteran Reward - } - - public override bool CanEquip(Mobile m) - { - if (!base.CanEquip(m)) - return false; - - return !IsRewardItem || RewardSystem.CheckIsUsableBy(m, this, new object[] { Hue, m_LabelNumber }); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_LabelNumber); - writer.Write(IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_LabelNumber = reader.ReadInt(); - IsRewardItem = reader.ReadBool(); - break; - } - } - - if (Parent is Mobile mobile) - mobile.VirtualArmorMod += 2; - } - } - - [Flippable(0x230A, 0x2309)] - public class FurCape : BaseCloak - { - [Constructible] - public FurCape(int hue = 0) : base(0x230A, hue) => Weight = 4.0; - - public FurCape(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using Server.Engines.VeteranRewards; + +namespace Server.Items +{ + public abstract class BaseCloak : BaseClothing + { + public BaseCloak(int itemID, int hue = 0) : base(itemID, Layer.Cloak, hue) + { + } + + public BaseCloak(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable] + public class Cloak : BaseCloak, IArcaneEquip + { + private int m_MaxArcaneCharges, m_CurArcaneCharges; + + [Constructible] + public Cloak(int hue = 0) : base(0x1515, hue) => Weight = 5.0; + + public Cloak(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxArcaneCharges + { + get => m_MaxArcaneCharges; + set + { + m_MaxArcaneCharges = value; + InvalidateProperties(); + Update(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int CurArcaneCharges + { + get => m_CurArcaneCharges; + set + { + m_CurArcaneCharges = value; + InvalidateProperties(); + Update(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsArcane => m_MaxArcaneCharges > 0 && m_CurArcaneCharges >= 0; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + if (IsArcane) + { + writer.Write(true); + writer.Write(m_CurArcaneCharges); + writer.Write(m_MaxArcaneCharges); + } + else + { + writer.Write(false); + } + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + if (reader.ReadBool()) + { + m_CurArcaneCharges = reader.ReadInt(); + m_MaxArcaneCharges = reader.ReadInt(); + + if (Hue == 2118) + Hue = ArcaneGem.DefaultArcaneHue; + } + + break; + } + } + + if (Weight == 4.0) + Weight = 5.0; + } + + public void Update() + { + if (IsArcane) + ItemID = 0x26AD; + else if (ItemID == 0x26AD) + ItemID = 0x1515; + + if (IsArcane && CurArcaneCharges == 0) + Hue = 0; + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (IsArcane) + list.Add(1061837, "{0}\t{1}", m_CurArcaneCharges, m_MaxArcaneCharges); // arcane charges: ~1_val~ / ~2_val~ + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + if (IsArcane) + LabelTo(from, 1061837, $"{m_CurArcaneCharges}\t{m_MaxArcaneCharges}"); + } + + public void Flip() + { + if (ItemID == 0x1515) + ItemID = 0x1530; + else if (ItemID == 0x1530) + ItemID = 0x1515; + } + } + + [Flippable] + public class RewardCloak : BaseCloak, IRewardItem + { + private int m_LabelNumber; + + [Constructible] + public RewardCloak(int hue = 0, int labelNumber = 0) : base(0x1515, hue) + { + Weight = 5.0; + LootType = LootType.Blessed; + + m_LabelNumber = labelNumber; + } + + public RewardCloak(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Number + { + get => m_LabelNumber; + set + { + m_LabelNumber = value; + InvalidateProperties(); + } + } + + public override int LabelNumber + { + get + { + if (m_LabelNumber > 0) + return m_LabelNumber; + + return base.LabelNumber; + } + } + + public override int BasePhysicalResistance => 3; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem { get; set; } + + public override void OnAdded(IEntity parent) + { + base.OnAdded(parent); + + if (parent is Mobile mobile) + mobile.VirtualArmorMod += 2; + } + + public override void OnRemoved(IEntity parent) + { + base.OnRemoved(parent); + + if (parent is Mobile mobile) + mobile.VirtualArmorMod -= 2; + } + + public override bool Dye(Mobile from, DyeTub sender) + { + from.SendLocalizedMessage(sender.FailMessage); + return false; + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (Core.ML && IsRewardItem) + list.Add( + RewardSystem.GetRewardYearLabel( + this, + new object[] { Hue, m_LabelNumber } + ) + ); // X Year Veteran Reward + } + + public override bool CanEquip(Mobile m) + { + if (!base.CanEquip(m)) + return false; + + return !IsRewardItem || RewardSystem.CheckIsUsableBy(m, this, new object[] { Hue, m_LabelNumber }); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_LabelNumber); + writer.Write(IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_LabelNumber = reader.ReadInt(); + IsRewardItem = reader.ReadBool(); + break; + } + } + + if (Parent is Mobile mobile) + mobile.VirtualArmorMod += 2; + } + } + + [Flippable(0x230A, 0x2309)] + public class FurCape : BaseCloak + { + [Constructible] + public FurCape(int hue = 0) : base(0x230A, hue) => Weight = 4.0; + + public FurCape(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Clothing/Hats.cs b/Projects/UOContent/Items/Clothing/Hats.cs index 1029a4c9b..306a8dcaa 100644 --- a/Projects/UOContent/Items/Clothing/Hats.cs +++ b/Projects/UOContent/Items/Clothing/Hats.cs @@ -1,889 +1,895 @@ -using System; -using System.Collections.Generic; -using Server.Engines.Craft; -using Server.Misc; -using Server.Network; - -namespace Server.Items -{ - public abstract class BaseHat : BaseClothing, IShipwreckedItem - { - public BaseHat(int itemID, int hue = 0) : base(itemID, Layer.Helm, hue) - { - } - - public BaseHat(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsShipwreckedItem { get; set; } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(IsShipwreckedItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - IsShipwreckedItem = reader.ReadBool(); - break; - } - } - } - - public override void AddEquipInfoAttributes(Mobile from, List attrs) - { - base.AddEquipInfoAttributes(from, attrs); - - if (IsShipwreckedItem) - attrs.Add(new EquipInfoAttribute(1041645)); // recovered from a shipwreck - } - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - if (IsShipwreckedItem) - list.Add(1041645); // recovered from a shipwreck - } - - public override int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, - BaseTool tool, CraftItem craftItem, int resHue) - { - Quality = (ClothingQuality)quality; - - if (Quality == ClothingQuality.Exceptional) - DistributeBonuses(tool is BaseRunicTool ? 6 : - Core.SE ? 15 : 14); // BLAME OSI. (We can't confirm it's an OSI bug yet.) - - return base.OnCraft(quality, makersMark, from, craftSystem, typeRes, tool, craftItem, resHue); - } - } - - [Flippable(0x2798, 0x27E3)] - public class Kasa : BaseHat - { - [Constructible] - public Kasa(int hue = 0) : base(0x2798, hue) => Weight = 3.0; - - public Kasa(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 9; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x278F, 0x27DA)] - public class ClothNinjaHood : BaseHat - { - [Constructible] - public ClothNinjaHood(int hue = 0) : base(0x278F, hue) => Weight = 2.0; - - public ClothNinjaHood(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 6; - public override int BasePoisonResistance => 9; - public override int BaseEnergyResistance => 9; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x2306, 0x2305)] - public class FlowerGarland : BaseHat - { - [Constructible] - public FlowerGarland(int hue = 0) : base(0x2306, hue) => Weight = 1.0; - - public FlowerGarland(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 6; - public override int BasePoisonResistance => 9; - public override int BaseEnergyResistance => 9; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class FloppyHat : BaseHat - { - [Constructible] - public FloppyHat(int hue = 0) : base(0x1713, hue) => Weight = 1.0; - - public FloppyHat(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 9; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class WideBrimHat : BaseHat - { - [Constructible] - public WideBrimHat(int hue = 0) : base(0x1714, hue) => Weight = 1.0; - - public WideBrimHat(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 9; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Cap : BaseHat - { - [Constructible] - public Cap(int hue = 0) : base(0x1715, hue) => Weight = 1.0; - - public Cap(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 9; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SkullCap : BaseHat - { - [Constructible] - public SkullCap(int hue = 0) : base(0x1544, hue) => Weight = 1.0; - - public SkullCap(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 5; - public override int BasePoisonResistance => 8; - public override int BaseEnergyResistance => 8; - - public override int InitMinHits => Core.ML ? 14 : 7; - public override int InitMaxHits => Core.ML ? 28 : 12; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Bandana : BaseHat - { - [Constructible] - public Bandana(int hue = 0) : base(0x1540, hue) => Weight = 1.0; - - public Bandana(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 5; - public override int BasePoisonResistance => 8; - public override int BaseEnergyResistance => 8; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BearMask : BaseHat - { - [Constructible] - public BearMask(int hue = 0) : base(0x1545, hue) => Weight = 5.0; - - public BearMask(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 8; - public override int BasePoisonResistance => 4; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public override bool Dye(Mobile from, DyeTub sender) - { - from.SendLocalizedMessage(sender.FailMessage); - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DeerMask : BaseHat - { - [Constructible] - public DeerMask(int hue = 0) : base(0x1547, hue) => Weight = 4.0; - - public DeerMask(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 6; - public override int BaseColdResistance => 8; - public override int BasePoisonResistance => 1; - public override int BaseEnergyResistance => 7; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public override bool Dye(Mobile from, DyeTub sender) - { - from.SendLocalizedMessage(sender.FailMessage); - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class HornedTribalMask : BaseHat - { - [Constructible] - public HornedTribalMask(int hue = 0) : base(0x1549, hue) => Weight = 2.0; - - public HornedTribalMask(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 6; - public override int BaseFireResistance => 9; - public override int BaseColdResistance => 0; - public override int BasePoisonResistance => 4; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public override bool Dye(Mobile from, DyeTub sender) - { - from.SendLocalizedMessage(sender.FailMessage); - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class TribalMask : BaseHat - { - [Constructible] - public TribalMask(int hue = 0) : base(0x154B, hue) => Weight = 2.0; - - public TribalMask(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 0; - public override int BaseColdResistance => 6; - public override int BasePoisonResistance => 10; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public override bool Dye(Mobile from, DyeTub sender) - { - from.SendLocalizedMessage(sender.FailMessage); - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class TallStrawHat : BaseHat - { - [Constructible] - public TallStrawHat(int hue = 0) : base(0x1716, hue) => Weight = 1.0; - - public TallStrawHat(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 9; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class StrawHat : BaseHat - { - [Constructible] - public StrawHat(int hue = 0) : base(0x1717, hue) => Weight = 1.0; - - public StrawHat(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 9; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class OrcishKinMask : BaseHat - { - [Constructible] - public OrcishKinMask(int hue = 0x8A4) : base(0x141B, hue) => Weight = 2.0; - - public OrcishKinMask(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 1; - public override int BaseFireResistance => 1; - public override int BaseColdResistance => 7; - public override int BasePoisonResistance => 7; - public override int BaseEnergyResistance => 8; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public override string DefaultName => "a mask of orcish kin"; - - public override bool Dye(Mobile from, DyeTub sender) - { - from.SendLocalizedMessage(sender.FailMessage); - return false; - } - - public override bool CanEquip(Mobile m) - { - if (!base.CanEquip(m)) - return false; - - if (m.BodyMod == 183 || m.BodyMod == 184) - { - m.SendLocalizedMessage(1061629); // You can't do that while wearing savage kin paint. - return false; - } - - return true; - } - - public override void OnAdded(IEntity parent) - { - base.OnAdded(parent); - - if (parent is Mobile mobile) - Titles.AwardKarma(mobile, -20, true); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - /*if (Hue != 0x8A4) - Hue = 0x8A4;*/ - } - } - - public class SavageMask : BaseHat - { - [Constructible] - public SavageMask() : this(GetRandomHue()) { } - - [Constructible] - public SavageMask(int hue) : base(0x154B, hue) => Weight = 2.0; - - public SavageMask(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 0; - public override int BaseColdResistance => 6; - public override int BasePoisonResistance => 10; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public static int GetRandomHue() - { - int v = Utility.RandomBirdHue(); - - if (v == 2101) - v = 0; - - return v; - } - - public override bool Dye(Mobile from, DyeTub sender) - { - from.SendLocalizedMessage(sender.FailMessage); - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - /*if (Hue != 0 && (Hue < 2101 || Hue > 2130)) - Hue = GetRandomHue();*/ - } - } - - public class WizardsHat : BaseHat - { - [Constructible] - public WizardsHat(int hue = 0) : base(0x1718, hue) => Weight = 1.0; - - public WizardsHat(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 9; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class MagicWizardsHat : BaseHat - { - [Constructible] - public MagicWizardsHat(int hue = 0) : base(0x1718, hue) => Weight = 1.0; - - public MagicWizardsHat(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 9; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public override int LabelNumber => 1041072; // a magical wizard's hat - - public override int BaseStrBonus => -5; - public override int BaseDexBonus => -5; - public override int BaseIntBonus => +5; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Bonnet : BaseHat - { - [Constructible] - public Bonnet(int hue = 0) : base(0x1719, hue) => Weight = 1.0; - - public Bonnet(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 9; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class FeatheredHat : BaseHat - { - [Constructible] - public FeatheredHat(int hue = 0) : base(0x171A, hue) => Weight = 1.0; - - public FeatheredHat(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 9; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class TricorneHat : BaseHat - { - [Constructible] - public TricorneHat(int hue = 0) : base(0x171B, hue) => Weight = 1.0; - - public TricorneHat(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 9; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class JesterHat : BaseHat - { - [Constructible] - public JesterHat(int hue = 0) : base(0x171C, hue) => Weight = 1.0; - - public JesterHat(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 9; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 20; - public override int InitMaxHits => 30; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using System.Collections.Generic; +using Server.Engines.Craft; +using Server.Misc; +using Server.Network; + +namespace Server.Items +{ + public abstract class BaseHat : BaseClothing, IShipwreckedItem + { + public BaseHat(int itemID, int hue = 0) : base(itemID, Layer.Helm, hue) + { + } + + public BaseHat(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsShipwreckedItem { get; set; } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(IsShipwreckedItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + IsShipwreckedItem = reader.ReadBool(); + break; + } + } + } + + public override void AddEquipInfoAttributes(Mobile from, List attrs) + { + base.AddEquipInfoAttributes(from, attrs); + + if (IsShipwreckedItem) + attrs.Add(new EquipInfoAttribute(1041645)); // recovered from a shipwreck + } + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + if (IsShipwreckedItem) + list.Add(1041645); // recovered from a shipwreck + } + + public override int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, + BaseTool tool, CraftItem craftItem, int resHue + ) + { + Quality = (ClothingQuality)quality; + + if (Quality == ClothingQuality.Exceptional) + DistributeBonuses( + tool is BaseRunicTool ? 6 : + Core.SE ? 15 : 14 + ); // BLAME OSI. (We can't confirm it's an OSI bug yet.) + + return base.OnCraft(quality, makersMark, from, craftSystem, typeRes, tool, craftItem, resHue); + } + } + + [Flippable(0x2798, 0x27E3)] + public class Kasa : BaseHat + { + [Constructible] + public Kasa(int hue = 0) : base(0x2798, hue) => Weight = 3.0; + + public Kasa(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 9; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + 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(); + } + } + + [Flippable(0x278F, 0x27DA)] + public class ClothNinjaHood : BaseHat + { + [Constructible] + public ClothNinjaHood(int hue = 0) : base(0x278F, hue) => Weight = 2.0; + + public ClothNinjaHood(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 6; + public override int BasePoisonResistance => 9; + public override int BaseEnergyResistance => 9; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + 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(); + } + } + + [Flippable(0x2306, 0x2305)] + public class FlowerGarland : BaseHat + { + [Constructible] + public FlowerGarland(int hue = 0) : base(0x2306, hue) => Weight = 1.0; + + public FlowerGarland(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 6; + public override int BasePoisonResistance => 9; + public override int BaseEnergyResistance => 9; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + 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 class FloppyHat : BaseHat + { + [Constructible] + public FloppyHat(int hue = 0) : base(0x1713, hue) => Weight = 1.0; + + public FloppyHat(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 9; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + 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 class WideBrimHat : BaseHat + { + [Constructible] + public WideBrimHat(int hue = 0) : base(0x1714, hue) => Weight = 1.0; + + public WideBrimHat(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 9; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + 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 class Cap : BaseHat + { + [Constructible] + public Cap(int hue = 0) : base(0x1715, hue) => Weight = 1.0; + + public Cap(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 9; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + 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 class SkullCap : BaseHat + { + [Constructible] + public SkullCap(int hue = 0) : base(0x1544, hue) => Weight = 1.0; + + public SkullCap(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 5; + public override int BasePoisonResistance => 8; + public override int BaseEnergyResistance => 8; + + public override int InitMinHits => Core.ML ? 14 : 7; + public override int InitMaxHits => Core.ML ? 28 : 12; + + 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 class Bandana : BaseHat + { + [Constructible] + public Bandana(int hue = 0) : base(0x1540, hue) => Weight = 1.0; + + public Bandana(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 5; + public override int BasePoisonResistance => 8; + public override int BaseEnergyResistance => 8; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + 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 class BearMask : BaseHat + { + [Constructible] + public BearMask(int hue = 0) : base(0x1545, hue) => Weight = 5.0; + + public BearMask(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 8; + public override int BasePoisonResistance => 4; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + public override bool Dye(Mobile from, DyeTub sender) + { + from.SendLocalizedMessage(sender.FailMessage); + return 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 class DeerMask : BaseHat + { + [Constructible] + public DeerMask(int hue = 0) : base(0x1547, hue) => Weight = 4.0; + + public DeerMask(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 6; + public override int BaseColdResistance => 8; + public override int BasePoisonResistance => 1; + public override int BaseEnergyResistance => 7; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + public override bool Dye(Mobile from, DyeTub sender) + { + from.SendLocalizedMessage(sender.FailMessage); + return 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 class HornedTribalMask : BaseHat + { + [Constructible] + public HornedTribalMask(int hue = 0) : base(0x1549, hue) => Weight = 2.0; + + public HornedTribalMask(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 6; + public override int BaseFireResistance => 9; + public override int BaseColdResistance => 0; + public override int BasePoisonResistance => 4; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + public override bool Dye(Mobile from, DyeTub sender) + { + from.SendLocalizedMessage(sender.FailMessage); + return 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 class TribalMask : BaseHat + { + [Constructible] + public TribalMask(int hue = 0) : base(0x154B, hue) => Weight = 2.0; + + public TribalMask(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 0; + public override int BaseColdResistance => 6; + public override int BasePoisonResistance => 10; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + public override bool Dye(Mobile from, DyeTub sender) + { + from.SendLocalizedMessage(sender.FailMessage); + return 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 class TallStrawHat : BaseHat + { + [Constructible] + public TallStrawHat(int hue = 0) : base(0x1716, hue) => Weight = 1.0; + + public TallStrawHat(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 9; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + 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 class StrawHat : BaseHat + { + [Constructible] + public StrawHat(int hue = 0) : base(0x1717, hue) => Weight = 1.0; + + public StrawHat(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 9; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + 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 class OrcishKinMask : BaseHat + { + [Constructible] + public OrcishKinMask(int hue = 0x8A4) : base(0x141B, hue) => Weight = 2.0; + + public OrcishKinMask(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 1; + public override int BaseFireResistance => 1; + public override int BaseColdResistance => 7; + public override int BasePoisonResistance => 7; + public override int BaseEnergyResistance => 8; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + public override string DefaultName => "a mask of orcish kin"; + + public override bool Dye(Mobile from, DyeTub sender) + { + from.SendLocalizedMessage(sender.FailMessage); + return false; + } + + public override bool CanEquip(Mobile m) + { + if (!base.CanEquip(m)) + return false; + + if (m.BodyMod == 183 || m.BodyMod == 184) + { + m.SendLocalizedMessage(1061629); // You can't do that while wearing savage kin paint. + return false; + } + + return true; + } + + public override void OnAdded(IEntity parent) + { + base.OnAdded(parent); + + if (parent is Mobile mobile) + Titles.AwardKarma(mobile, -20, true); + } + + 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 (Hue != 0x8A4) + Hue = 0x8A4;*/ + } + } + + public class SavageMask : BaseHat + { + [Constructible] + public SavageMask() : this(GetRandomHue()) + { + } + + [Constructible] + public SavageMask(int hue) : base(0x154B, hue) => Weight = 2.0; + + public SavageMask(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 0; + public override int BaseColdResistance => 6; + public override int BasePoisonResistance => 10; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + public static int GetRandomHue() + { + var v = Utility.RandomBirdHue(); + + if (v == 2101) + v = 0; + + return v; + } + + public override bool Dye(Mobile from, DyeTub sender) + { + from.SendLocalizedMessage(sender.FailMessage); + return 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(); + + /*if (Hue != 0 && (Hue < 2101 || Hue > 2130)) + Hue = GetRandomHue();*/ + } + } + + public class WizardsHat : BaseHat + { + [Constructible] + public WizardsHat(int hue = 0) : base(0x1718, hue) => Weight = 1.0; + + public WizardsHat(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 9; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + 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 class MagicWizardsHat : BaseHat + { + [Constructible] + public MagicWizardsHat(int hue = 0) : base(0x1718, hue) => Weight = 1.0; + + public MagicWizardsHat(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 9; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + public override int LabelNumber => 1041072; // a magical wizard's hat + + public override int BaseStrBonus => -5; + public override int BaseDexBonus => -5; + public override int BaseIntBonus => +5; + + 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 class Bonnet : BaseHat + { + [Constructible] + public Bonnet(int hue = 0) : base(0x1719, hue) => Weight = 1.0; + + public Bonnet(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 9; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + 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 class FeatheredHat : BaseHat + { + [Constructible] + public FeatheredHat(int hue = 0) : base(0x171A, hue) => Weight = 1.0; + + public FeatheredHat(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 9; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + 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 class TricorneHat : BaseHat + { + [Constructible] + public TricorneHat(int hue = 0) : base(0x171B, hue) => Weight = 1.0; + + public TricorneHat(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 9; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + 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 class JesterHat : BaseHat + { + [Constructible] + public JesterHat(int hue = 0) : base(0x171C, hue) => Weight = 1.0; + + public JesterHat(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 9; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 20; + public override int InitMaxHits => 30; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Clothing/MiddleTorso.cs b/Projects/UOContent/Items/Clothing/MiddleTorso.cs index ce0c29493..18c2d62e2 100644 --- a/Projects/UOContent/Items/Clothing/MiddleTorso.cs +++ b/Projects/UOContent/Items/Clothing/MiddleTorso.cs @@ -1,233 +1,233 @@ -namespace Server.Items -{ - public abstract class BaseMiddleTorso : BaseClothing - { - public BaseMiddleTorso(int itemID, int hue = 0) : base(itemID, Layer.MiddleTorso, hue) - { - } - - public BaseMiddleTorso(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1541, 0x1542)] - public class BodySash : BaseMiddleTorso - { - [Constructible] - public BodySash(int hue = 0) : base(0x1541, hue) => Weight = 1.0; - - public BodySash(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x153d, 0x153e)] - public class FullApron : BaseMiddleTorso - { - [Constructible] - public FullApron(int hue = 0) : base(0x153d, hue) => Weight = 4.0; - - public FullApron(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1f7b, 0x1f7c)] - public class Doublet : BaseMiddleTorso - { - [Constructible] - public Doublet(int hue = 0) : base(0x1F7B, hue) => Weight = 2.0; - - public Doublet(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1ffd, 0x1ffe)] - public class Surcoat : BaseMiddleTorso - { - [Constructible] - public Surcoat(int hue = 0) : base(0x1FFD, hue) => Weight = 6.0; - - public Surcoat(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 3.0) - Weight = 6.0; - } - } - - [Flippable(0x1fa1, 0x1fa2)] - public class Tunic : BaseMiddleTorso - { - [Constructible] - public Tunic(int hue = 0) : base(0x1FA1, hue) => Weight = 5.0; - - public Tunic(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x2310, 0x230F)] - public class FormalShirt : BaseMiddleTorso - { - [Constructible] - public FormalShirt(int hue = 0) : base(0x2310, hue) => Weight = 1.0; - - public FormalShirt(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - if (Weight == 2.0) - Weight = 1.0; - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1f9f, 0x1fa0)] - public class JesterSuit : BaseMiddleTorso - { - [Constructible] - public JesterSuit(int hue = 0) : base(0x1F9F, hue) => Weight = 4.0; - - public JesterSuit(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x27A1, 0x27EC)] - public class JinBaori : BaseMiddleTorso - { - [Constructible] - public JinBaori(int hue = 0) : base(0x27A1, hue) => Weight = 3.0; - - public JinBaori(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public abstract class BaseMiddleTorso : BaseClothing + { + public BaseMiddleTorso(int itemID, int hue = 0) : base(itemID, Layer.MiddleTorso, hue) + { + } + + public BaseMiddleTorso(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1541, 0x1542)] + public class BodySash : BaseMiddleTorso + { + [Constructible] + public BodySash(int hue = 0) : base(0x1541, hue) => Weight = 1.0; + + public BodySash(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x153d, 0x153e)] + public class FullApron : BaseMiddleTorso + { + [Constructible] + public FullApron(int hue = 0) : base(0x153d, hue) => Weight = 4.0; + + public FullApron(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1f7b, 0x1f7c)] + public class Doublet : BaseMiddleTorso + { + [Constructible] + public Doublet(int hue = 0) : base(0x1F7B, hue) => Weight = 2.0; + + public Doublet(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1ffd, 0x1ffe)] + public class Surcoat : BaseMiddleTorso + { + [Constructible] + public Surcoat(int hue = 0) : base(0x1FFD, hue) => Weight = 6.0; + + public Surcoat(Serial serial) : base(serial) + { + } + + 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 (Weight == 3.0) + Weight = 6.0; + } + } + + [Flippable(0x1fa1, 0x1fa2)] + public class Tunic : BaseMiddleTorso + { + [Constructible] + public Tunic(int hue = 0) : base(0x1FA1, hue) => Weight = 5.0; + + public Tunic(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x2310, 0x230F)] + public class FormalShirt : BaseMiddleTorso + { + [Constructible] + public FormalShirt(int hue = 0) : base(0x2310, hue) => Weight = 1.0; + + public FormalShirt(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + if (Weight == 2.0) + Weight = 1.0; + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + [Flippable(0x1f9f, 0x1fa0)] + public class JesterSuit : BaseMiddleTorso + { + [Constructible] + public JesterSuit(int hue = 0) : base(0x1F9F, hue) => Weight = 4.0; + + public JesterSuit(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x27A1, 0x27EC)] + public class JinBaori : BaseMiddleTorso + { + [Constructible] + public JinBaori(int hue = 0) : base(0x27A1, hue) => Weight = 3.0; + + public JinBaori(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Clothing/OuterLegs.cs b/Projects/UOContent/Items/Clothing/OuterLegs.cs index 4d56bd184..9beb4542b 100644 --- a/Projects/UOContent/Items/Clothing/OuterLegs.cs +++ b/Projects/UOContent/Items/Clothing/OuterLegs.cs @@ -1,130 +1,130 @@ -namespace Server.Items -{ - public abstract class BaseOuterLegs : BaseClothing - { - public BaseOuterLegs(int itemID, int hue = 0) : base(itemID, Layer.OuterLegs, hue) - { - } - - public BaseOuterLegs(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x230C, 0x230B)] - public class FurSarong : BaseOuterLegs - { - [Constructible] - public FurSarong(int hue = 0) : base(0x230C, hue) => Weight = 3.0; - - public FurSarong(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 4.0) - Weight = 3.0; - } - } - - [Flippable(0x1516, 0x1531)] - public class Skirt : BaseOuterLegs - { - [Constructible] - public Skirt(int hue = 0) : base(0x1516, hue) => Weight = 4.0; - - public Skirt(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1537, 0x1538)] - public class Kilt : BaseOuterLegs - { - [Constructible] - public Kilt(int hue = 0) : base(0x1537, hue) => Weight = 2.0; - - public Kilt(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x279A, 0x27E5)] - public class Hakama : BaseOuterLegs - { - [Constructible] - public Hakama(int hue = 0) : base(0x279A, hue) => Weight = 2.0; - - public Hakama(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public abstract class BaseOuterLegs : BaseClothing + { + public BaseOuterLegs(int itemID, int hue = 0) : base(itemID, Layer.OuterLegs, hue) + { + } + + public BaseOuterLegs(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x230C, 0x230B)] + public class FurSarong : BaseOuterLegs + { + [Constructible] + public FurSarong(int hue = 0) : base(0x230C, hue) => Weight = 3.0; + + public FurSarong(Serial serial) : base(serial) + { + } + + 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 (Weight == 4.0) + Weight = 3.0; + } + } + + [Flippable(0x1516, 0x1531)] + public class Skirt : BaseOuterLegs + { + [Constructible] + public Skirt(int hue = 0) : base(0x1516, hue) => Weight = 4.0; + + public Skirt(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1537, 0x1538)] + public class Kilt : BaseOuterLegs + { + [Constructible] + public Kilt(int hue = 0) : base(0x1537, hue) => Weight = 2.0; + + public Kilt(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x279A, 0x27E5)] + public class Hakama : BaseOuterLegs + { + [Constructible] + public Hakama(int hue = 0) : base(0x279A, hue) => Weight = 2.0; + + public Hakama(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Clothing/OuterTorso.cs b/Projects/UOContent/Items/Clothing/OuterTorso.cs index 6a08f7d86..f39647aab 100644 --- a/Projects/UOContent/Items/Clothing/OuterTorso.cs +++ b/Projects/UOContent/Items/Clothing/OuterTorso.cs @@ -1,781 +1,789 @@ -using System; -using Server.Engines.VeteranRewards; - -namespace Server.Items -{ - public abstract class BaseOuterTorso : BaseClothing - { - public BaseOuterTorso(int itemID, int hue = 0) : base(itemID, Layer.OuterTorso, hue) - { - } - - public BaseOuterTorso(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x230E, 0x230D)] - public class GildedDress : BaseOuterTorso - { - [Constructible] - public GildedDress(int hue = 0) : base(0x230E, hue) => Weight = 3.0; - - public GildedDress(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1F00, 0x1EFF)] - public class FancyDress : BaseOuterTorso - { - [Constructible] - public FancyDress(int hue = 0) : base(0x1F00, hue) => Weight = 3.0; - - public FancyDress(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DeathRobe : Robe - { - private static readonly TimeSpan m_DefaultDecayTime = TimeSpan.FromMinutes(1.0); - private DateTime m_DecayTime; - private Timer m_DecayTimer; - - [Constructible] - public DeathRobe() - { - LootType = LootType.Newbied; - Hue = 2301; - BeginDecay(m_DefaultDecayTime); - } - - public DeathRobe(Serial serial) : base(serial) - { - } - - public override bool DisplayLootType => false; - - public new bool Scissor(Mobile from, Scissors scissors) - { - from.SendLocalizedMessage(502440); // Scissors can not be used on that to produce anything. - return false; - } - - public void BeginDecay() - { - BeginDecay(m_DefaultDecayTime); - } - - private void BeginDecay(TimeSpan delay) - { - m_DecayTimer?.Stop(); - - m_DecayTime = DateTime.UtcNow + delay; - - m_DecayTimer = new InternalTimer(this, delay); - m_DecayTimer.Start(); - } - - public override bool OnDroppedToWorld(Mobile from, Point3D p) - { - BeginDecay(m_DefaultDecayTime); - - return true; - } - - public override bool OnDroppedToMobile(Mobile from, Mobile target) - { - if (m_DecayTimer != null) - { - m_DecayTimer.Stop(); - m_DecayTimer = null; - } - - return true; - } - - public override void OnAfterDelete() - { - m_DecayTimer?.Stop(); - - m_DecayTimer = null; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(2); // version - - writer.Write(m_DecayTimer != null); - - if (m_DecayTimer != null) - writer.WriteDeltaTime(m_DecayTime); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 2: - { - if (reader.ReadBool()) - { - m_DecayTime = reader.ReadDeltaTime(); - BeginDecay(m_DecayTime - DateTime.UtcNow); - } - - break; - } - case 1: - case 0: - { - if (Parent == null) - BeginDecay(m_DefaultDecayTime); - break; - } - } - - if (version < 1 && Hue == 0) - Hue = 2301; - } - - private class InternalTimer : Timer - { - private readonly DeathRobe m_Robe; - - public InternalTimer(DeathRobe c, TimeSpan delay) : base(delay) - { - m_Robe = c; - Priority = TimerPriority.FiveSeconds; - } - - protected override void OnTick() - { - if (m_Robe.Parent != null || m_Robe.IsLockedDown) - Stop(); - else - m_Robe.Delete(); - } - } - } - - [Flippable] - public class RewardRobe : BaseOuterTorso, IRewardItem - { - private int m_LabelNumber; - - [Constructible] - public RewardRobe(int hue = 0, int labelNumber = 0) : base(0x1F03, hue) - { - Weight = 3.0; - LootType = LootType.Blessed; - - m_LabelNumber = labelNumber; - } - - public RewardRobe(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Number - { - get => m_LabelNumber; - set - { - m_LabelNumber = value; - InvalidateProperties(); - } - } - - public override int LabelNumber - { - get - { - if (m_LabelNumber > 0) - return m_LabelNumber; - - return base.LabelNumber; - } - } - - public override int BasePhysicalResistance => 3; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem { get; set; } - - public override void OnAdded(IEntity parent) - { - base.OnAdded(parent); - - if (parent is Mobile mobile) - mobile.VirtualArmorMod += 2; - } - - public override void OnRemoved(IEntity parent) - { - base.OnRemoved(parent); - - if (parent is Mobile mobile) - mobile.VirtualArmorMod -= 2; - } - - public override bool Dye(Mobile from, DyeTub sender) - { - from.SendLocalizedMessage(sender.FailMessage); - return false; - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Core.ML && IsRewardItem) - list.Add(RewardSystem.GetRewardYearLabel(this, - new object[] { Hue, m_LabelNumber })); // X Year Veteran Reward - } - - public override bool CanEquip(Mobile m) - { - if (!base.CanEquip(m)) - return false; - - return !IsRewardItem || RewardSystem.CheckIsUsableBy(m, this, new object[] { Hue, m_LabelNumber }); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_LabelNumber); - writer.Write(IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_LabelNumber = reader.ReadInt(); - IsRewardItem = reader.ReadBool(); - break; - } - } - - if (Parent is Mobile mobile) - mobile.VirtualArmorMod += 2; - } - } - - [Flippable] - public class RewardDress : BaseOuterTorso, IRewardItem - { - private int m_LabelNumber; - - [Constructible] - public RewardDress(int hue = 0, int labelNumber = 0) : base(0x1F01, hue) - { - Weight = 2.0; - LootType = LootType.Blessed; - - m_LabelNumber = labelNumber; - } - - public RewardDress(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Number - { - get => m_LabelNumber; - set - { - m_LabelNumber = value; - InvalidateProperties(); - } - } - - public override int LabelNumber - { - get - { - if (m_LabelNumber > 0) - return m_LabelNumber; - - return base.LabelNumber; - } - } - - public override int BasePhysicalResistance => 3; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem { get; set; } - - public override void OnAdded(IEntity parent) - { - base.OnAdded(parent); - - if (parent is Mobile mobile) - mobile.VirtualArmorMod += 2; - } - - public override void OnRemoved(IEntity parent) - { - base.OnRemoved(parent); - - if (parent is Mobile mobile) - mobile.VirtualArmorMod -= 2; - } - - public override bool Dye(Mobile from, DyeTub sender) - { - from.SendLocalizedMessage(sender.FailMessage); - return false; - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (IsRewardItem) - list.Add(RewardSystem.GetRewardYearLabel(this, - new object[] { Hue, m_LabelNumber })); // X Year Veteran Reward - } - - public override bool CanEquip(Mobile m) - { - if (!base.CanEquip(m)) - return false; - - return !IsRewardItem || RewardSystem.CheckIsUsableBy(m, this, new object[] { Hue, m_LabelNumber }); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_LabelNumber); - writer.Write(IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_LabelNumber = reader.ReadInt(); - IsRewardItem = reader.ReadBool(); - break; - } - } - - if (Parent is Mobile mobile) - mobile.VirtualArmorMod += 2; - } - } - - [Flippable] - public class Robe : BaseOuterTorso, IArcaneEquip - { - [Constructible] - public Robe(int hue = 0) : base(0x1F03, hue) => Weight = 3.0; - - public Robe(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - if (IsArcane) - { - writer.Write(true); - writer.Write(m_CurArcaneCharges); - writer.Write(m_MaxArcaneCharges); - } - else - { - writer.Write(false); - } - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - if (reader.ReadBool()) - { - m_CurArcaneCharges = reader.ReadInt(); - m_MaxArcaneCharges = reader.ReadInt(); - - if (Hue == 2118) - Hue = ArcaneGem.DefaultArcaneHue; - } - - break; - } - } - } - - private int m_MaxArcaneCharges, m_CurArcaneCharges; - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxArcaneCharges - { - get => m_MaxArcaneCharges; - set - { - m_MaxArcaneCharges = value; - InvalidateProperties(); - Update(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int CurArcaneCharges - { - get => m_CurArcaneCharges; - set - { - m_CurArcaneCharges = value; - InvalidateProperties(); - Update(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsArcane => m_MaxArcaneCharges > 0 && m_CurArcaneCharges >= 0; - - public void Update() - { - if (IsArcane) - ItemID = 0x26AE; - else if (ItemID == 0x26AE) - ItemID = 0x1F04; - - if (IsArcane && CurArcaneCharges == 0) - Hue = 0; - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (IsArcane) - list.Add(1061837, "{0}\t{1}", m_CurArcaneCharges, m_MaxArcaneCharges); // arcane charges: ~1_val~ / ~2_val~ - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - if (IsArcane) - LabelTo(from, 1061837, $"{m_CurArcaneCharges}\t{m_MaxArcaneCharges}"); - } - - public void Flip() - { - if (ItemID == 0x1F03) - ItemID = 0x1F04; - else if (ItemID == 0x1F04) - ItemID = 0x1F03; - } - } - - public class MonkRobe : BaseOuterTorso - { - [Constructible] - public MonkRobe(int hue = 0x21E) : base(0x2687, hue) - { - Weight = 1.0; - StrRequirement = 0; - } - - public MonkRobe(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1076584; // A monk's robe - public override bool CanBeBlessed => false; - - public override bool Dye(Mobile from, DyeTub sender) - { - from.SendLocalizedMessage(sender.FailMessage); - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1f01, 0x1f02)] - public class PlainDress : BaseOuterTorso - { - [Constructible] - public PlainDress(int hue = 0) : base(0x1F01, hue) => Weight = 2.0; - - public PlainDress(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 3.0) - Weight = 2.0; - } - } - - [Flippable(0x2799, 0x27E4)] - public class Kamishimo : BaseOuterTorso - { - [Constructible] - public Kamishimo(int hue = 0) : base(0x2799, hue) => Weight = 3.0; - - public Kamishimo(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x279C, 0x27E7)] - public class HakamaShita : BaseOuterTorso - { - [Constructible] - public HakamaShita(int hue = 0) : base(0x279C, hue) => Weight = 3.0; - - public HakamaShita(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x2782, 0x27CD)] - public class MaleKimono : BaseOuterTorso - { - [Constructible] - public MaleKimono(int hue = 0) : base(0x2782, hue) => Weight = 3.0; - - public MaleKimono(Serial serial) : base(serial) - { - } - - public override bool AllowFemaleWearer => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x2783, 0x27CE)] - public class FemaleKimono : BaseOuterTorso - { - [Constructible] - public FemaleKimono(int hue = 0) : base(0x2783, hue) => Weight = 3.0; - - public FemaleKimono(Serial serial) : base(serial) - { - } - - public override bool AllowMaleWearer => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x2FB9, 0x3173)] - public class MaleElvenRobe : BaseOuterTorso - { - [Constructible] - public MaleElvenRobe(int hue = 0) : base(0x2FB9, hue) => Weight = 2.0; - - public MaleElvenRobe(Serial serial) : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - [Flippable(0x2FBA, 0x3174)] - public class FemaleElvenRobe : BaseOuterTorso - { - [Constructible] - public FemaleElvenRobe(int hue = 0) : base(0x2FBA, hue) => Weight = 2.0; - - public FemaleElvenRobe(Serial serial) : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - - public override bool AllowMaleWearer => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} +using System; +using Server.Engines.VeteranRewards; + +namespace Server.Items +{ + public abstract class BaseOuterTorso : BaseClothing + { + public BaseOuterTorso(int itemID, int hue = 0) : base(itemID, Layer.OuterTorso, hue) + { + } + + public BaseOuterTorso(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x230E, 0x230D)] + public class GildedDress : BaseOuterTorso + { + [Constructible] + public GildedDress(int hue = 0) : base(0x230E, hue) => Weight = 3.0; + + public GildedDress(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1F00, 0x1EFF)] + public class FancyDress : BaseOuterTorso + { + [Constructible] + public FancyDress(int hue = 0) : base(0x1F00, hue) => Weight = 3.0; + + public FancyDress(Serial serial) : base(serial) + { + } + + 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 class DeathRobe : Robe + { + private static readonly TimeSpan m_DefaultDecayTime = TimeSpan.FromMinutes(1.0); + private DateTime m_DecayTime; + private Timer m_DecayTimer; + + [Constructible] + public DeathRobe() + { + LootType = LootType.Newbied; + Hue = 2301; + BeginDecay(m_DefaultDecayTime); + } + + public DeathRobe(Serial serial) : base(serial) + { + } + + public override bool DisplayLootType => false; + + public new bool Scissor(Mobile from, Scissors scissors) + { + from.SendLocalizedMessage(502440); // Scissors can not be used on that to produce anything. + return false; + } + + public void BeginDecay() + { + BeginDecay(m_DefaultDecayTime); + } + + private void BeginDecay(TimeSpan delay) + { + m_DecayTimer?.Stop(); + + m_DecayTime = DateTime.UtcNow + delay; + + m_DecayTimer = new InternalTimer(this, delay); + m_DecayTimer.Start(); + } + + public override bool OnDroppedToWorld(Mobile from, Point3D p) + { + BeginDecay(m_DefaultDecayTime); + + return true; + } + + public override bool OnDroppedToMobile(Mobile from, Mobile target) + { + if (m_DecayTimer != null) + { + m_DecayTimer.Stop(); + m_DecayTimer = null; + } + + return true; + } + + public override void OnAfterDelete() + { + m_DecayTimer?.Stop(); + + m_DecayTimer = null; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(2); // version + + writer.Write(m_DecayTimer != null); + + if (m_DecayTimer != null) + writer.WriteDeltaTime(m_DecayTime); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 2: + { + if (reader.ReadBool()) + { + m_DecayTime = reader.ReadDeltaTime(); + BeginDecay(m_DecayTime - DateTime.UtcNow); + } + + break; + } + case 1: + case 0: + { + if (Parent == null) + BeginDecay(m_DefaultDecayTime); + break; + } + } + + if (version < 1 && Hue == 0) + Hue = 2301; + } + + private class InternalTimer : Timer + { + private readonly DeathRobe m_Robe; + + public InternalTimer(DeathRobe c, TimeSpan delay) : base(delay) + { + m_Robe = c; + Priority = TimerPriority.FiveSeconds; + } + + protected override void OnTick() + { + if (m_Robe.Parent != null || m_Robe.IsLockedDown) + Stop(); + else + m_Robe.Delete(); + } + } + } + + [Flippable] + public class RewardRobe : BaseOuterTorso, IRewardItem + { + private int m_LabelNumber; + + [Constructible] + public RewardRobe(int hue = 0, int labelNumber = 0) : base(0x1F03, hue) + { + Weight = 3.0; + LootType = LootType.Blessed; + + m_LabelNumber = labelNumber; + } + + public RewardRobe(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Number + { + get => m_LabelNumber; + set + { + m_LabelNumber = value; + InvalidateProperties(); + } + } + + public override int LabelNumber + { + get + { + if (m_LabelNumber > 0) + return m_LabelNumber; + + return base.LabelNumber; + } + } + + public override int BasePhysicalResistance => 3; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem { get; set; } + + public override void OnAdded(IEntity parent) + { + base.OnAdded(parent); + + if (parent is Mobile mobile) + mobile.VirtualArmorMod += 2; + } + + public override void OnRemoved(IEntity parent) + { + base.OnRemoved(parent); + + if (parent is Mobile mobile) + mobile.VirtualArmorMod -= 2; + } + + public override bool Dye(Mobile from, DyeTub sender) + { + from.SendLocalizedMessage(sender.FailMessage); + return false; + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (Core.ML && IsRewardItem) + list.Add( + RewardSystem.GetRewardYearLabel( + this, + new object[] { Hue, m_LabelNumber } + ) + ); // X Year Veteran Reward + } + + public override bool CanEquip(Mobile m) + { + if (!base.CanEquip(m)) + return false; + + return !IsRewardItem || RewardSystem.CheckIsUsableBy(m, this, new object[] { Hue, m_LabelNumber }); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_LabelNumber); + writer.Write(IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_LabelNumber = reader.ReadInt(); + IsRewardItem = reader.ReadBool(); + break; + } + } + + if (Parent is Mobile mobile) + mobile.VirtualArmorMod += 2; + } + } + + [Flippable] + public class RewardDress : BaseOuterTorso, IRewardItem + { + private int m_LabelNumber; + + [Constructible] + public RewardDress(int hue = 0, int labelNumber = 0) : base(0x1F01, hue) + { + Weight = 2.0; + LootType = LootType.Blessed; + + m_LabelNumber = labelNumber; + } + + public RewardDress(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Number + { + get => m_LabelNumber; + set + { + m_LabelNumber = value; + InvalidateProperties(); + } + } + + public override int LabelNumber + { + get + { + if (m_LabelNumber > 0) + return m_LabelNumber; + + return base.LabelNumber; + } + } + + public override int BasePhysicalResistance => 3; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem { get; set; } + + public override void OnAdded(IEntity parent) + { + base.OnAdded(parent); + + if (parent is Mobile mobile) + mobile.VirtualArmorMod += 2; + } + + public override void OnRemoved(IEntity parent) + { + base.OnRemoved(parent); + + if (parent is Mobile mobile) + mobile.VirtualArmorMod -= 2; + } + + public override bool Dye(Mobile from, DyeTub sender) + { + from.SendLocalizedMessage(sender.FailMessage); + return false; + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (IsRewardItem) + list.Add( + RewardSystem.GetRewardYearLabel( + this, + new object[] { Hue, m_LabelNumber } + ) + ); // X Year Veteran Reward + } + + public override bool CanEquip(Mobile m) + { + if (!base.CanEquip(m)) + return false; + + return !IsRewardItem || RewardSystem.CheckIsUsableBy(m, this, new object[] { Hue, m_LabelNumber }); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_LabelNumber); + writer.Write(IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_LabelNumber = reader.ReadInt(); + IsRewardItem = reader.ReadBool(); + break; + } + } + + if (Parent is Mobile mobile) + mobile.VirtualArmorMod += 2; + } + } + + [Flippable] + public class Robe : BaseOuterTorso, IArcaneEquip + { + private int m_MaxArcaneCharges, m_CurArcaneCharges; + + [Constructible] + public Robe(int hue = 0) : base(0x1F03, hue) => Weight = 3.0; + + public Robe(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxArcaneCharges + { + get => m_MaxArcaneCharges; + set + { + m_MaxArcaneCharges = value; + InvalidateProperties(); + Update(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int CurArcaneCharges + { + get => m_CurArcaneCharges; + set + { + m_CurArcaneCharges = value; + InvalidateProperties(); + Update(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsArcane => m_MaxArcaneCharges > 0 && m_CurArcaneCharges >= 0; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + if (IsArcane) + { + writer.Write(true); + writer.Write(m_CurArcaneCharges); + writer.Write(m_MaxArcaneCharges); + } + else + { + writer.Write(false); + } + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + if (reader.ReadBool()) + { + m_CurArcaneCharges = reader.ReadInt(); + m_MaxArcaneCharges = reader.ReadInt(); + + if (Hue == 2118) + Hue = ArcaneGem.DefaultArcaneHue; + } + + break; + } + } + } + + public void Update() + { + if (IsArcane) + ItemID = 0x26AE; + else if (ItemID == 0x26AE) + ItemID = 0x1F04; + + if (IsArcane && CurArcaneCharges == 0) + Hue = 0; + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (IsArcane) + list.Add(1061837, "{0}\t{1}", m_CurArcaneCharges, m_MaxArcaneCharges); // arcane charges: ~1_val~ / ~2_val~ + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + if (IsArcane) + LabelTo(from, 1061837, $"{m_CurArcaneCharges}\t{m_MaxArcaneCharges}"); + } + + public void Flip() + { + if (ItemID == 0x1F03) + ItemID = 0x1F04; + else if (ItemID == 0x1F04) + ItemID = 0x1F03; + } + } + + public class MonkRobe : BaseOuterTorso + { + [Constructible] + public MonkRobe(int hue = 0x21E) : base(0x2687, hue) + { + Weight = 1.0; + StrRequirement = 0; + } + + public MonkRobe(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1076584; // A monk's robe + public override bool CanBeBlessed => false; + + public override bool Dye(Mobile from, DyeTub sender) + { + from.SendLocalizedMessage(sender.FailMessage); + return 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(); + } + } + + [Flippable(0x1f01, 0x1f02)] + public class PlainDress : BaseOuterTorso + { + [Constructible] + public PlainDress(int hue = 0) : base(0x1F01, hue) => Weight = 2.0; + + public PlainDress(Serial serial) : base(serial) + { + } + + 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 (Weight == 3.0) + Weight = 2.0; + } + } + + [Flippable(0x2799, 0x27E4)] + public class Kamishimo : BaseOuterTorso + { + [Constructible] + public Kamishimo(int hue = 0) : base(0x2799, hue) => Weight = 3.0; + + public Kamishimo(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x279C, 0x27E7)] + public class HakamaShita : BaseOuterTorso + { + [Constructible] + public HakamaShita(int hue = 0) : base(0x279C, hue) => Weight = 3.0; + + public HakamaShita(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x2782, 0x27CD)] + public class MaleKimono : BaseOuterTorso + { + [Constructible] + public MaleKimono(int hue = 0) : base(0x2782, hue) => Weight = 3.0; + + public MaleKimono(Serial serial) : base(serial) + { + } + + public override bool AllowFemaleWearer => 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(); + } + } + + [Flippable(0x2783, 0x27CE)] + public class FemaleKimono : BaseOuterTorso + { + [Constructible] + public FemaleKimono(int hue = 0) : base(0x2783, hue) => Weight = 3.0; + + public FemaleKimono(Serial serial) : base(serial) + { + } + + public override bool AllowMaleWearer => 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(); + } + } + + [Flippable(0x2FB9, 0x3173)] + public class MaleElvenRobe : BaseOuterTorso + { + [Constructible] + public MaleElvenRobe(int hue = 0) : base(0x2FB9, hue) => Weight = 2.0; + + public MaleElvenRobe(Serial serial) : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + + 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(); + } + } + + [Flippable(0x2FBA, 0x3174)] + public class FemaleElvenRobe : BaseOuterTorso + { + [Constructible] + public FemaleElvenRobe(int hue = 0) : base(0x2FBA, hue) => Weight = 2.0; + + public FemaleElvenRobe(Serial serial) : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + + public override bool AllowMaleWearer => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Clothing/Pants.cs b/Projects/UOContent/Items/Clothing/Pants.cs index 9a839e2d0..eb967aa8f 100644 --- a/Projects/UOContent/Items/Clothing/Pants.cs +++ b/Projects/UOContent/Items/Clothing/Pants.cs @@ -1,129 +1,129 @@ -namespace Server.Items -{ - public abstract class BasePants : BaseClothing - { - public BasePants(int itemID, int hue = 0) : base(itemID, Layer.Pants, hue) - { - } - - public BasePants(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x152e, 0x152f)] - public class ShortPants : BasePants - { - [Constructible] - public ShortPants(int hue = 0) : base(0x152E, hue) => Weight = 2.0; - - public ShortPants(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1539, 0x153a)] - public class LongPants : BasePants - { - [Constructible] - public LongPants(int hue = 0) : base(0x1539, hue) => Weight = 2.0; - - public LongPants(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x279B, 0x27E6)] - public class TattsukeHakama : BasePants - { - [Constructible] - public TattsukeHakama(int hue = 0) : base(0x279B, hue) => Weight = 2.0; - - public TattsukeHakama(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x2FC3, 0x3179)] - public class ElvenPants : BasePants - { - [Constructible] - public ElvenPants(int hue = 0) : base(0x2FC3, hue) => Weight = 2.0; - - public ElvenPants(Serial serial) : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} +namespace Server.Items +{ + public abstract class BasePants : BaseClothing + { + public BasePants(int itemID, int hue = 0) : base(itemID, Layer.Pants, hue) + { + } + + public BasePants(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x152e, 0x152f)] + public class ShortPants : BasePants + { + [Constructible] + public ShortPants(int hue = 0) : base(0x152E, hue) => Weight = 2.0; + + public ShortPants(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1539, 0x153a)] + public class LongPants : BasePants + { + [Constructible] + public LongPants(int hue = 0) : base(0x1539, hue) => Weight = 2.0; + + public LongPants(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x279B, 0x27E6)] + public class TattsukeHakama : BasePants + { + [Constructible] + public TattsukeHakama(int hue = 0) : base(0x279B, hue) => Weight = 2.0; + + public TattsukeHakama(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x2FC3, 0x3179)] + public class ElvenPants : BasePants + { + [Constructible] + public ElvenPants(int hue = 0) : base(0x2FC3, hue) => Weight = 2.0; + + public ElvenPants(Serial serial) : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Clothing/Shirts.cs b/Projects/UOContent/Items/Clothing/Shirts.cs index 91d5081c0..014fb0494 100644 --- a/Projects/UOContent/Items/Clothing/Shirts.cs +++ b/Projects/UOContent/Items/Clothing/Shirts.cs @@ -1,162 +1,162 @@ -namespace Server.Items -{ - public abstract class BaseShirt : BaseClothing - { - public BaseShirt(int itemID, int hue = 0) : base(itemID, Layer.Shirt, hue) - { - } - - public BaseShirt(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1efd, 0x1efe)] - public class FancyShirt : BaseShirt - { - [Constructible] - public FancyShirt(int hue = 0) : base(0x1EFD, hue) => Weight = 2.0; - - public FancyShirt(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1517, 0x1518)] - public class Shirt : BaseShirt - { - [Constructible] - public Shirt(int hue = 0) : base(0x1517, hue) => Weight = 1.0; - - public Shirt(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 2.0) - Weight = 1.0; - } - } - - [Flippable(0x2794, 0x27DF)] - public class ClothNinjaJacket : BaseShirt - { - [Constructible] - public ClothNinjaJacket(int hue = 0) : base(0x2794, hue) - { - Weight = 5.0; - Layer = Layer.InnerTorso; - } - - public ClothNinjaJacket(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class ElvenShirt : BaseShirt - { - [Constructible] - public ElvenShirt(int hue = 0) : base(0x3175, hue) => Weight = 2.0; - - public ElvenShirt(Serial serial) - : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ElvenDarkShirt : BaseShirt - { - [Constructible] - public ElvenDarkShirt(int hue = 0) : base(0x3176, hue) => Weight = 2.0; - - public ElvenDarkShirt(Serial serial) : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} +namespace Server.Items +{ + public abstract class BaseShirt : BaseClothing + { + public BaseShirt(int itemID, int hue = 0) : base(itemID, Layer.Shirt, hue) + { + } + + public BaseShirt(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1efd, 0x1efe)] + public class FancyShirt : BaseShirt + { + [Constructible] + public FancyShirt(int hue = 0) : base(0x1EFD, hue) => Weight = 2.0; + + public FancyShirt(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1517, 0x1518)] + public class Shirt : BaseShirt + { + [Constructible] + public Shirt(int hue = 0) : base(0x1517, hue) => Weight = 1.0; + + public Shirt(Serial serial) : base(serial) + { + } + + 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 (Weight == 2.0) + Weight = 1.0; + } + } + + [Flippable(0x2794, 0x27DF)] + public class ClothNinjaJacket : BaseShirt + { + [Constructible] + public ClothNinjaJacket(int hue = 0) : base(0x2794, hue) + { + Weight = 5.0; + Layer = Layer.InnerTorso; + } + + public ClothNinjaJacket(Serial serial) : base(serial) + { + } + + 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 class ElvenShirt : BaseShirt + { + [Constructible] + public ElvenShirt(int hue = 0) : base(0x3175, hue) => Weight = 2.0; + + public ElvenShirt(Serial serial) + : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + + 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(); + } + } + + public class ElvenDarkShirt : BaseShirt + { + [Constructible] + public ElvenDarkShirt(int hue = 0) : base(0x3176, hue) => Weight = 2.0; + + public ElvenDarkShirt(Serial serial) : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Clothing/Shoes.cs b/Projects/UOContent/Items/Clothing/Shoes.cs index 28754a817..2c611fbcb 100644 --- a/Projects/UOContent/Items/Clothing/Shoes.cs +++ b/Projects/UOContent/Items/Clothing/Shoes.cs @@ -1,384 +1,384 @@ -namespace Server.Items -{ - public abstract class BaseShoes : BaseClothing - { - public BaseShoes(int itemID, int hue = 0) : base(itemID, Layer.Shoes, hue) - { - } - - public BaseShoes(Serial serial) : base(serial) - { - } - - public override bool Scissor(Mobile from, Scissors scissors) - { - if (DefaultResource == CraftResource.None) - return base.Scissor(from, scissors); - - from.SendLocalizedMessage(502440); // Scissors can not be used on that to produce anything. - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(2); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 2: break; // empty, resource removed - case 1: - { - m_Resource = (CraftResource)reader.ReadInt(); - break; - } - case 0: - { - m_Resource = DefaultResource; - break; - } - } - } - } - - [Flippable(0x2307, 0x2308)] - public class FurBoots : BaseShoes - { - [Constructible] - public FurBoots(int hue = 0) : base(0x2307, hue) => Weight = 3.0; - - public FurBoots(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x170b, 0x170c)] - public class Boots : BaseShoes - { - [Constructible] - public Boots(int hue = 0) : base(0x170B, hue) => Weight = 3.0; - - public Boots(Serial serial) : base(serial) - { - } - - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable] - public class ThighBoots : BaseShoes, IArcaneEquip - { - [Constructible] - public ThighBoots(int hue = 0) : base(0x1711, hue) => Weight = 4.0; - - public ThighBoots(Serial serial) : base(serial) - { - } - - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - if (IsArcane) - { - writer.Write(true); - writer.Write(m_CurArcaneCharges); - writer.Write(m_MaxArcaneCharges); - } - else - { - writer.Write(false); - } - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - if (reader.ReadBool()) - { - m_CurArcaneCharges = reader.ReadInt(); - m_MaxArcaneCharges = reader.ReadInt(); - - if (Hue == 2118) - Hue = ArcaneGem.DefaultArcaneHue; - } - - break; - } - } - } - - private int m_MaxArcaneCharges, m_CurArcaneCharges; - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxArcaneCharges - { - get => m_MaxArcaneCharges; - set - { - m_MaxArcaneCharges = value; - InvalidateProperties(); - Update(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int CurArcaneCharges - { - get => m_CurArcaneCharges; - set - { - m_CurArcaneCharges = value; - InvalidateProperties(); - Update(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsArcane => m_MaxArcaneCharges > 0 && m_CurArcaneCharges >= 0; - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - if (IsArcane) - LabelTo(from, 1061837, $"{m_CurArcaneCharges}\t{m_MaxArcaneCharges}"); - } - - public void Update() - { - if (IsArcane) - ItemID = 0x26AF; - else if (ItemID == 0x26AF) - ItemID = 0x1711; - - if (IsArcane && CurArcaneCharges == 0) - Hue = 0; - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (IsArcane) - list.Add(1061837, "{0}\t{1}", m_CurArcaneCharges, m_MaxArcaneCharges); // arcane charges: ~1_val~ / ~2_val~ - } - - public void Flip() - { - if (ItemID == 0x1711) - ItemID = 0x1712; - else if (ItemID == 0x1712) - ItemID = 0x1711; - } - } - - [Flippable(0x170f, 0x1710)] - public class Shoes : BaseShoes - { - [Constructible] - public Shoes(int hue = 0) : base(0x170F, hue) => Weight = 2.0; - - public Shoes(Serial serial) : base(serial) - { - } - - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x170d, 0x170e)] - public class Sandals : BaseShoes - { - [Constructible] - public Sandals(int hue = 0) : base(0x170D, hue) => Weight = 1.0; - - public Sandals(Serial serial) : base(serial) - { - } - - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override bool Dye(Mobile from, DyeTub sender) => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x2797, 0x27E2)] - public class NinjaTabi : BaseShoes - { - [Constructible] - public NinjaTabi(int hue = 0) : base(0x2797, hue) => Weight = 2.0; - - public NinjaTabi(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x2796, 0x27E1)] - public class SamuraiTabi : BaseShoes - { - [Constructible] - public SamuraiTabi(int hue = 0) : base(0x2796, hue) => Weight = 2.0; - - public SamuraiTabi(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x2796, 0x27E1)] - public class Waraji : BaseShoes - { - [Constructible] - public Waraji(int hue = 0) : base(0x2796, hue) => Weight = 2.0; - - public Waraji(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x2FC4, 0x317A)] - public class ElvenBoots : BaseShoes - { - [Constructible] - public ElvenBoots(int hue = 0) : base(0x2FC4, hue) => Weight = 2.0; - - public ElvenBoots(Serial serial) : base(serial) - { - } - - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override Race RequiredRace => Race.Elf; - - public override bool Dye(Mobile from, DyeTub sender) => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} +namespace Server.Items +{ + public abstract class BaseShoes : BaseClothing + { + public BaseShoes(int itemID, int hue = 0) : base(itemID, Layer.Shoes, hue) + { + } + + public BaseShoes(Serial serial) : base(serial) + { + } + + public override bool Scissor(Mobile from, Scissors scissors) + { + if (DefaultResource == CraftResource.None) + return base.Scissor(from, scissors); + + from.SendLocalizedMessage(502440); // Scissors can not be used on that to produce anything. + return false; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(2); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 2: break; // empty, resource removed + case 1: + { + m_Resource = (CraftResource)reader.ReadInt(); + break; + } + case 0: + { + m_Resource = DefaultResource; + break; + } + } + } + } + + [Flippable(0x2307, 0x2308)] + public class FurBoots : BaseShoes + { + [Constructible] + public FurBoots(int hue = 0) : base(0x2307, hue) => Weight = 3.0; + + public FurBoots(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x170b, 0x170c)] + public class Boots : BaseShoes + { + [Constructible] + public Boots(int hue = 0) : base(0x170B, hue) => Weight = 3.0; + + public Boots(Serial serial) : base(serial) + { + } + + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + 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(); + } + } + + [Flippable] + public class ThighBoots : BaseShoes, IArcaneEquip + { + private int m_MaxArcaneCharges, m_CurArcaneCharges; + + [Constructible] + public ThighBoots(int hue = 0) : base(0x1711, hue) => Weight = 4.0; + + public ThighBoots(Serial serial) : base(serial) + { + } + + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxArcaneCharges + { + get => m_MaxArcaneCharges; + set + { + m_MaxArcaneCharges = value; + InvalidateProperties(); + Update(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int CurArcaneCharges + { + get => m_CurArcaneCharges; + set + { + m_CurArcaneCharges = value; + InvalidateProperties(); + Update(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsArcane => m_MaxArcaneCharges > 0 && m_CurArcaneCharges >= 0; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + if (IsArcane) + { + writer.Write(true); + writer.Write(m_CurArcaneCharges); + writer.Write(m_MaxArcaneCharges); + } + else + { + writer.Write(false); + } + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + if (reader.ReadBool()) + { + m_CurArcaneCharges = reader.ReadInt(); + m_MaxArcaneCharges = reader.ReadInt(); + + if (Hue == 2118) + Hue = ArcaneGem.DefaultArcaneHue; + } + + break; + } + } + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + if (IsArcane) + LabelTo(from, 1061837, $"{m_CurArcaneCharges}\t{m_MaxArcaneCharges}"); + } + + public void Update() + { + if (IsArcane) + ItemID = 0x26AF; + else if (ItemID == 0x26AF) + ItemID = 0x1711; + + if (IsArcane && CurArcaneCharges == 0) + Hue = 0; + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (IsArcane) + list.Add(1061837, "{0}\t{1}", m_CurArcaneCharges, m_MaxArcaneCharges); // arcane charges: ~1_val~ / ~2_val~ + } + + public void Flip() + { + if (ItemID == 0x1711) + ItemID = 0x1712; + else if (ItemID == 0x1712) + ItemID = 0x1711; + } + } + + [Flippable(0x170f, 0x1710)] + public class Shoes : BaseShoes + { + [Constructible] + public Shoes(int hue = 0) : base(0x170F, hue) => Weight = 2.0; + + public Shoes(Serial serial) : base(serial) + { + } + + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + 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(); + } + } + + [Flippable(0x170d, 0x170e)] + public class Sandals : BaseShoes + { + [Constructible] + public Sandals(int hue = 0) : base(0x170D, hue) => Weight = 1.0; + + public Sandals(Serial serial) : base(serial) + { + } + + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override bool Dye(Mobile from, DyeTub sender) => 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(); + } + } + + [Flippable(0x2797, 0x27E2)] + public class NinjaTabi : BaseShoes + { + [Constructible] + public NinjaTabi(int hue = 0) : base(0x2797, hue) => Weight = 2.0; + + public NinjaTabi(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x2796, 0x27E1)] + public class SamuraiTabi : BaseShoes + { + [Constructible] + public SamuraiTabi(int hue = 0) : base(0x2796, hue) => Weight = 2.0; + + public SamuraiTabi(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x2796, 0x27E1)] + public class Waraji : BaseShoes + { + [Constructible] + public Waraji(int hue = 0) : base(0x2796, hue) => Weight = 2.0; + + public Waraji(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x2FC4, 0x317A)] + public class ElvenBoots : BaseShoes + { + [Constructible] + public ElvenBoots(int hue = 0) : base(0x2FC4, hue) => Weight = 2.0; + + public ElvenBoots(Serial serial) : base(serial) + { + } + + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override Race RequiredRace => Race.Elf; + + public override bool Dye(Mobile from, DyeTub sender) => false; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Clothing/Waist.cs b/Projects/UOContent/Items/Clothing/Waist.cs index 751116c93..0996a1f66 100644 --- a/Projects/UOContent/Items/Clothing/Waist.cs +++ b/Projects/UOContent/Items/Clothing/Waist.cs @@ -1,116 +1,116 @@ -namespace Server.Items -{ - public abstract class BaseWaist : BaseClothing - { - public BaseWaist(int itemID, int hue = 0) : base(itemID, Layer.Waist, hue) - { - } - - public BaseWaist(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x153b, 0x153c)] - public class HalfApron : BaseWaist - { - [Constructible] - public HalfApron(int hue = 0) : base(0x153b, hue) => Weight = 2.0; - - public HalfApron(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x27A0, 0x27EB)] - public class Obi : BaseWaist - { - [Constructible] - public Obi(int hue = 0) : base(0x27A0, hue) => Weight = 1.0; - - public Obi(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x2B68, 0x315F)] - public class WoodlandBelt : BaseWaist - { - [Constructible] - public WoodlandBelt(int hue = 0) : base(0x2B68, hue) => Weight = 4.0; - - public WoodlandBelt(Serial serial) : base(serial) - { - } - - public override Race RequiredRace => Race.Elf; - - public override bool Dye(Mobile from, DyeTub sender) - { - from.SendLocalizedMessage(sender.FailMessage); - return false; - } - - public override bool Scissor(Mobile from, Scissors scissors) - { - from.SendLocalizedMessage(502440); // Scissors can not be used on that to produce anything. - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} +namespace Server.Items +{ + public abstract class BaseWaist : BaseClothing + { + public BaseWaist(int itemID, int hue = 0) : base(itemID, Layer.Waist, hue) + { + } + + public BaseWaist(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x153b, 0x153c)] + public class HalfApron : BaseWaist + { + [Constructible] + public HalfApron(int hue = 0) : base(0x153b, hue) => Weight = 2.0; + + public HalfApron(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x27A0, 0x27EB)] + public class Obi : BaseWaist + { + [Constructible] + public Obi(int hue = 0) : base(0x27A0, hue) => Weight = 1.0; + + public Obi(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x2B68, 0x315F)] + public class WoodlandBelt : BaseWaist + { + [Constructible] + public WoodlandBelt(int hue = 0) : base(0x2B68, hue) => Weight = 4.0; + + public WoodlandBelt(Serial serial) : base(serial) + { + } + + public override Race RequiredRace => Race.Elf; + + public override bool Dye(Mobile from, DyeTub sender) + { + from.SendLocalizedMessage(sender.FailMessage); + return false; + } + + public override bool Scissor(Mobile from, Scissors scissors) + { + from.SendLocalizedMessage(502440); // Scissors can not be used on that to produce anything. + return false; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Ankhs.cs b/Projects/UOContent/Items/Construction/Ankhs.cs index 2a31bc35a..c63736a0f 100644 --- a/Projects/UOContent/Items/Construction/Ankhs.cs +++ b/Projects/UOContent/Items/Construction/Ankhs.cs @@ -1,442 +1,444 @@ -using System.Collections.Generic; -using Server.ContextMenus; -using Server.Gumps; -using Server.Mobiles; - -namespace Server.Items -{ - public class Ankhs - { - public const int ResurrectRange = 2; - public const int TitheRange = 2; - public const int LockRange = 2; - - public static void GetContextMenuEntries(Mobile from, Item item, List list) - { - if (from is PlayerMobile mobile) - list.Add(new LockKarmaEntry(mobile)); - - list.Add(new ResurrectEntry(from, item)); - - if (Core.AOS) - list.Add(new TitheEntry(from)); - } - - public static void Resurrect(Mobile m, Item item) - { - if (m.Alive) - return; - - if (!m.InRange(item.GetWorldLocation(), ResurrectRange)) - { - m.SendLocalizedMessage(500446); // That is too far away. - } - else if (m.Map?.CanFit(m.Location, 16, false, false) == true) - { - m.CloseGump(); - m.SendGump(new ResurrectGump(m, ResurrectMessage.VirtueShrine)); - } - else - { - m.SendLocalizedMessage(502391); // Thou can not be resurrected there! - } - } - - private class ResurrectEntry : ContextMenuEntry - { - private readonly Item m_Item; - private readonly Mobile m_Mobile; - - public ResurrectEntry(Mobile mobile, Item item) : base(6195, ResurrectRange) - { - m_Mobile = mobile; - m_Item = item; - - Enabled = !m_Mobile.Alive; - } - - public override void OnClick() - { - Resurrect(m_Mobile, m_Item); - } - } - - private class LockKarmaEntry : ContextMenuEntry - { - private readonly PlayerMobile m_Mobile; - - public LockKarmaEntry(PlayerMobile mobile) : base(mobile.KarmaLocked ? 6197 : 6196, LockRange) => m_Mobile = mobile; - - public override void OnClick() - { - m_Mobile.KarmaLocked = !m_Mobile.KarmaLocked; - - if (m_Mobile.KarmaLocked) - m_Mobile.SendLocalizedMessage( - 1060192); // Your karma has been locked. Your karma can no longer be raised. - else - m_Mobile.SendLocalizedMessage(1060191); // Your karma has been unlocked. Your karma can be raised again. - } - } - - private class TitheEntry : ContextMenuEntry - { - private readonly Mobile m_Mobile; - - public TitheEntry(Mobile mobile) : base(6198, TitheRange) - { - m_Mobile = mobile; - - Enabled = m_Mobile.Alive; - } - - public override void OnClick() - { - if (m_Mobile.CheckAlive()) - m_Mobile.SendGump(new TithingGump(m_Mobile, 0)); - } - } - } - - public class AnkhWest : Item - { - private InternalItem m_Item; - - [Constructible] - public AnkhWest(bool bloodied = false) : base(bloodied ? 0x1D98 : 0x3) - { - Movable = false; - - m_Item = new InternalItem(bloodied, this); - } - - public AnkhWest(Serial serial) : base(serial) - { - } - - public override bool HandlesOnMovement => true; // Tell the core that we implement OnMovement - - [Hue] - [CommandProperty(AccessLevel.GameMaster)] - public override int Hue - { - get => base.Hue; - set - { - base.Hue = value; - if (m_Item.Hue != value) m_Item.Hue = value; - } - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (Parent == null && Utility.InRange(Location, m.Location, 1) && !Utility.InRange(Location, oldLocation, 1)) - Ankhs.Resurrect(m, this); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - Ankhs.GetContextMenuEntries(from, this, list); - } - - public override void OnDoubleClickDead(Mobile m) - { - Ankhs.Resurrect(m, this); - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X, Y + 1, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as InternalItem; - } - - private class InternalItem : Item - { - private AnkhWest m_Item; - - public InternalItem(bool bloodied, AnkhWest item) : base(bloodied ? 0x1D97 : 0x2) - { - Movable = false; - - m_Item = item; - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public override bool HandlesOnMovement => true; // Tell the core that we implement OnMovement - - [Hue] - [CommandProperty(AccessLevel.GameMaster)] - public override int Hue - { - get => base.Hue; - set - { - base.Hue = value; - if (m_Item.Hue != value) m_Item.Hue = value; - } - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X, Y - 1, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (Parent == null && Utility.InRange(Location, m.Location, 1) && !Utility.InRange(Location, oldLocation, 1)) - Ankhs.Resurrect(m, this); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - Ankhs.GetContextMenuEntries(from, this, list); - } - - public override void OnDoubleClickDead(Mobile m) - { - Ankhs.Resurrect(m, this); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as AnkhWest; - } - } - } - - [TypeAlias("Server.Items.AnkhEast")] - public class AnkhNorth : Item - { - private InternalItem m_Item; - - [Constructible] - public AnkhNorth(bool bloodied = false) : base(bloodied ? 0x1E5D : 0x4) - { - Movable = false; - - m_Item = new InternalItem(bloodied, this); - } - - public AnkhNorth(Serial serial) - : base(serial) - { - } - - public override bool HandlesOnMovement => true; // Tell the core that we implement OnMovement - - [Hue] - [CommandProperty(AccessLevel.GameMaster)] - public override int Hue - { - get => base.Hue; - set - { - base.Hue = value; - if (m_Item.Hue != value) m_Item.Hue = value; - } - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (Parent == null && Utility.InRange(Location, m.Location, 1) && !Utility.InRange(Location, oldLocation, 1)) - Ankhs.Resurrect(m, this); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - Ankhs.GetContextMenuEntries(from, this, list); - } - - public override void OnDoubleClickDead(Mobile m) - { - Ankhs.Resurrect(m, this); - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X + 1, Y, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as InternalItem; - } - - [TypeAlias("Server.Items.AnkhEast+InternalItem")] - private class InternalItem : Item - { - private AnkhNorth m_Item; - - public InternalItem(bool bloodied, AnkhNorth item) - : base(bloodied ? 0x1E5C : 0x5) - { - Movable = false; - - m_Item = item; - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public override bool HandlesOnMovement => true; // Tell the core that we implement OnMovement - - [Hue] - [CommandProperty(AccessLevel.GameMaster)] - public override int Hue - { - get => base.Hue; - set - { - base.Hue = value; - if (m_Item.Hue != value) m_Item.Hue = value; - } - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X - 1, Y, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (Parent == null && Utility.InRange(Location, m.Location, 1) && !Utility.InRange(Location, oldLocation, 1)) - Ankhs.Resurrect(m, this); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - Ankhs.GetContextMenuEntries(from, this, list); - } - - public override void OnDoubleClickDead(Mobile m) - { - Ankhs.Resurrect(m, this); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as AnkhNorth; - } - } - } -} +using System.Collections.Generic; +using Server.ContextMenus; +using Server.Gumps; +using Server.Mobiles; + +namespace Server.Items +{ + public class Ankhs + { + public const int ResurrectRange = 2; + public const int TitheRange = 2; + public const int LockRange = 2; + + public static void GetContextMenuEntries(Mobile from, Item item, List list) + { + if (from is PlayerMobile mobile) + list.Add(new LockKarmaEntry(mobile)); + + list.Add(new ResurrectEntry(from, item)); + + if (Core.AOS) + list.Add(new TitheEntry(from)); + } + + public static void Resurrect(Mobile m, Item item) + { + if (m.Alive) + return; + + if (!m.InRange(item.GetWorldLocation(), ResurrectRange)) + { + m.SendLocalizedMessage(500446); // That is too far away. + } + else if (m.Map?.CanFit(m.Location, 16, false, false) == true) + { + m.CloseGump(); + m.SendGump(new ResurrectGump(m, ResurrectMessage.VirtueShrine)); + } + else + { + m.SendLocalizedMessage(502391); // Thou can not be resurrected there! + } + } + + private class ResurrectEntry : ContextMenuEntry + { + private readonly Item m_Item; + private readonly Mobile m_Mobile; + + public ResurrectEntry(Mobile mobile, Item item) : base(6195, ResurrectRange) + { + m_Mobile = mobile; + m_Item = item; + + Enabled = !m_Mobile.Alive; + } + + public override void OnClick() + { + Resurrect(m_Mobile, m_Item); + } + } + + private class LockKarmaEntry : ContextMenuEntry + { + private readonly PlayerMobile m_Mobile; + + public LockKarmaEntry(PlayerMobile mobile) : base(mobile.KarmaLocked ? 6197 : 6196, LockRange) => + m_Mobile = mobile; + + public override void OnClick() + { + m_Mobile.KarmaLocked = !m_Mobile.KarmaLocked; + + if (m_Mobile.KarmaLocked) + m_Mobile.SendLocalizedMessage( + 1060192 + ); // Your karma has been locked. Your karma can no longer be raised. + else + m_Mobile.SendLocalizedMessage(1060191); // Your karma has been unlocked. Your karma can be raised again. + } + } + + private class TitheEntry : ContextMenuEntry + { + private readonly Mobile m_Mobile; + + public TitheEntry(Mobile mobile) : base(6198, TitheRange) + { + m_Mobile = mobile; + + Enabled = m_Mobile.Alive; + } + + public override void OnClick() + { + if (m_Mobile.CheckAlive()) + m_Mobile.SendGump(new TithingGump(m_Mobile, 0)); + } + } + } + + public class AnkhWest : Item + { + private InternalItem m_Item; + + [Constructible] + public AnkhWest(bool bloodied = false) : base(bloodied ? 0x1D98 : 0x3) + { + Movable = false; + + m_Item = new InternalItem(bloodied, this); + } + + public AnkhWest(Serial serial) : base(serial) + { + } + + public override bool HandlesOnMovement => true; // Tell the core that we implement OnMovement + + [Hue] + [CommandProperty(AccessLevel.GameMaster)] + public override int Hue + { + get => base.Hue; + set + { + base.Hue = value; + if (m_Item.Hue != value) m_Item.Hue = value; + } + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (Parent == null && Utility.InRange(Location, m.Location, 1) && !Utility.InRange(Location, oldLocation, 1)) + Ankhs.Resurrect(m, this); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + Ankhs.GetContextMenuEntries(from, this, list); + } + + public override void OnDoubleClickDead(Mobile m) + { + Ankhs.Resurrect(m, this); + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X, Y + 1, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as InternalItem; + } + + private class InternalItem : Item + { + private AnkhWest m_Item; + + public InternalItem(bool bloodied, AnkhWest item) : base(bloodied ? 0x1D97 : 0x2) + { + Movable = false; + + m_Item = item; + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override bool HandlesOnMovement => true; // Tell the core that we implement OnMovement + + [Hue] + [CommandProperty(AccessLevel.GameMaster)] + public override int Hue + { + get => base.Hue; + set + { + base.Hue = value; + if (m_Item.Hue != value) m_Item.Hue = value; + } + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X, Y - 1, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (Parent == null && Utility.InRange(Location, m.Location, 1) && !Utility.InRange(Location, oldLocation, 1)) + Ankhs.Resurrect(m, this); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + Ankhs.GetContextMenuEntries(from, this, list); + } + + public override void OnDoubleClickDead(Mobile m) + { + Ankhs.Resurrect(m, this); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as AnkhWest; + } + } + } + + [TypeAlias("Server.Items.AnkhEast")] + public class AnkhNorth : Item + { + private InternalItem m_Item; + + [Constructible] + public AnkhNorth(bool bloodied = false) : base(bloodied ? 0x1E5D : 0x4) + { + Movable = false; + + m_Item = new InternalItem(bloodied, this); + } + + public AnkhNorth(Serial serial) + : base(serial) + { + } + + public override bool HandlesOnMovement => true; // Tell the core that we implement OnMovement + + [Hue] + [CommandProperty(AccessLevel.GameMaster)] + public override int Hue + { + get => base.Hue; + set + { + base.Hue = value; + if (m_Item.Hue != value) m_Item.Hue = value; + } + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (Parent == null && Utility.InRange(Location, m.Location, 1) && !Utility.InRange(Location, oldLocation, 1)) + Ankhs.Resurrect(m, this); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + Ankhs.GetContextMenuEntries(from, this, list); + } + + public override void OnDoubleClickDead(Mobile m) + { + Ankhs.Resurrect(m, this); + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X + 1, Y, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as InternalItem; + } + + [TypeAlias("Server.Items.AnkhEast+InternalItem")] + private class InternalItem : Item + { + private AnkhNorth m_Item; + + public InternalItem(bool bloodied, AnkhNorth item) + : base(bloodied ? 0x1E5C : 0x5) + { + Movable = false; + + m_Item = item; + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override bool HandlesOnMovement => true; // Tell the core that we implement OnMovement + + [Hue] + [CommandProperty(AccessLevel.GameMaster)] + public override int Hue + { + get => base.Hue; + set + { + base.Hue = value; + if (m_Item.Hue != value) m_Item.Hue = value; + } + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X - 1, Y, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (Parent == null && Utility.InRange(Location, m.Location, 1) && !Utility.InRange(Location, oldLocation, 1)) + Ankhs.Resurrect(m, this); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + Ankhs.GetContextMenuEntries(from, this, list); + } + + public override void OnDoubleClickDead(Mobile m) + { + Ankhs.Resurrect(m, this); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as AnkhNorth; + } + } + } +} diff --git a/Projects/UOContent/Items/Construction/Chairs/Benchs.cs b/Projects/UOContent/Items/Construction/Chairs/Benchs.cs index b847cc848..6f693b8ff 100644 --- a/Projects/UOContent/Items/Construction/Chairs/Benchs.cs +++ b/Projects/UOContent/Items/Construction/Chairs/Benchs.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - [Furniture] - [Flippable(0xB2D, 0xB2C)] - public class WoodenBench : Item - { - [Constructible] - public WoodenBench() : base(0xB2D) => Weight = 6; - - public WoodenBench(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Furniture] + [Flippable(0xB2D, 0xB2C)] + public class WoodenBench : Item + { + [Constructible] + public WoodenBench() : base(0xB2D) => Weight = 6; + + public WoodenBench(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Chairs/Chairs.cs b/Projects/UOContent/Items/Construction/Chairs/Chairs.cs index 487e4722a..469490b42 100644 --- a/Projects/UOContent/Items/Construction/Chairs/Chairs.cs +++ b/Projects/UOContent/Items/Construction/Chairs/Chairs.cs @@ -1,226 +1,226 @@ -namespace Server.Items -{ - [Furniture] - [Flippable(0xB4F, 0xB4E, 0xB50, 0xB51)] - public class FancyWoodenChairCushion : Item - { - [Constructible] - public FancyWoodenChairCushion() : base(0xB4F) => Weight = 20.0; - - public FancyWoodenChairCushion(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 6.0) - Weight = 20.0; - } - } - - [Furniture] - [Flippable(0xB53, 0xB52, 0xB54, 0xB55)] - public class WoodenChairCushion : Item - { - [Constructible] - public WoodenChairCushion() : base(0xB53) => Weight = 20.0; - - public WoodenChairCushion(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 6.0) - Weight = 20.0; - } - } - - [Furniture] - [Flippable(0xB57, 0xB56, 0xB59, 0xB58)] - public class WoodenChair : Item - { - [Constructible] - public WoodenChair() : base(0xB57) => Weight = 20.0; - - public WoodenChair(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 6.0) - Weight = 20.0; - } - } - - [Furniture] - [Flippable(0xB5B, 0xB5A, 0xB5C, 0xB5D)] - public class BambooChair : Item - { - [Constructible] - public BambooChair() : base(0xB5B) => Weight = 20.0; - - public BambooChair(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 6.0) - Weight = 20.0; - } - } - - [DynamicFliping] - [Flippable(0x1218, 0x1219, 0x121A, 0x121B)] - public class StoneChair : Item - { - [Constructible] - public StoneChair() : base(0x1218) => Weight = 20; - - public StoneChair(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [DynamicFliping] - [Flippable(0x2DE3, 0x2DE4, 0x2DE5, 0x2DE6)] - public class OrnateElvenChair : Item - { - [Constructible] - public OrnateElvenChair() : base(0x2DE3) => Weight = 1.0; - - public OrnateElvenChair(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - [DynamicFliping] - [Flippable(0x2DEB, 0x2DEC, 0x2DED, 0x2DEE)] - public class BigElvenChair : Item - { - [Constructible] - public BigElvenChair() : base(0x2DEB) - { - } - - public BigElvenChair(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - [DynamicFliping] - [Flippable(0x2DF5, 0x2DF6)] - public class ElvenReadingChair : Item - { - [Constructible] - public ElvenReadingChair() : base(0x2DF5) - { - } - - public ElvenReadingChair(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Furniture] + [Flippable(0xB4F, 0xB4E, 0xB50, 0xB51)] + public class FancyWoodenChairCushion : Item + { + [Constructible] + public FancyWoodenChairCushion() : base(0xB4F) => Weight = 20.0; + + public FancyWoodenChairCushion(Serial serial) : base(serial) + { + } + + 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 (Weight == 6.0) + Weight = 20.0; + } + } + + [Furniture] + [Flippable(0xB53, 0xB52, 0xB54, 0xB55)] + public class WoodenChairCushion : Item + { + [Constructible] + public WoodenChairCushion() : base(0xB53) => Weight = 20.0; + + public WoodenChairCushion(Serial serial) : base(serial) + { + } + + 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 (Weight == 6.0) + Weight = 20.0; + } + } + + [Furniture] + [Flippable(0xB57, 0xB56, 0xB59, 0xB58)] + public class WoodenChair : Item + { + [Constructible] + public WoodenChair() : base(0xB57) => Weight = 20.0; + + public WoodenChair(Serial serial) : base(serial) + { + } + + 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 (Weight == 6.0) + Weight = 20.0; + } + } + + [Furniture] + [Flippable(0xB5B, 0xB5A, 0xB5C, 0xB5D)] + public class BambooChair : Item + { + [Constructible] + public BambooChair() : base(0xB5B) => Weight = 20.0; + + public BambooChair(Serial serial) : base(serial) + { + } + + 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 (Weight == 6.0) + Weight = 20.0; + } + } + + [DynamicFliping] + [Flippable(0x1218, 0x1219, 0x121A, 0x121B)] + public class StoneChair : Item + { + [Constructible] + public StoneChair() : base(0x1218) => Weight = 20; + + public StoneChair(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [DynamicFliping] + [Flippable(0x2DE3, 0x2DE4, 0x2DE5, 0x2DE6)] + public class OrnateElvenChair : Item + { + [Constructible] + public OrnateElvenChair() : base(0x2DE3) => Weight = 1.0; + + public OrnateElvenChair(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [DynamicFliping] + [Flippable(0x2DEB, 0x2DEC, 0x2DED, 0x2DEE)] + public class BigElvenChair : Item + { + [Constructible] + public BigElvenChair() : base(0x2DEB) + { + } + + public BigElvenChair(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [DynamicFliping] + [Flippable(0x2DF5, 0x2DF6)] + public class ElvenReadingChair : Item + { + [Constructible] + public ElvenReadingChair() : base(0x2DF5) + { + } + + public ElvenReadingChair(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Chairs/Stools.cs b/Projects/UOContent/Items/Construction/Chairs/Stools.cs index 1d27c812e..6895f34a1 100644 --- a/Projects/UOContent/Items/Construction/Chairs/Stools.cs +++ b/Projects/UOContent/Items/Construction/Chairs/Stools.cs @@ -1,58 +1,58 @@ -namespace Server.Items -{ - [Furniture] - public class Stool : Item - { - [Constructible] - public Stool() : base(0xA2A) => Weight = 10.0; - - public Stool(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 6.0) - Weight = 10.0; - } - } - - [Furniture] - public class FootStool : Item - { - [Constructible] - public FootStool() : base(0xB5E) => Weight = 6.0; - - public FootStool(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 6.0) - Weight = 10.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Furniture] + public class Stool : Item + { + [Constructible] + public Stool() : base(0xA2A) => Weight = 10.0; + + public Stool(Serial serial) : base(serial) + { + } + + 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 (Weight == 6.0) + Weight = 10.0; + } + } + + [Furniture] + public class FootStool : Item + { + [Constructible] + public FootStool() : base(0xB5E) => Weight = 6.0; + + public FootStool(Serial serial) : base(serial) + { + } + + 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 (Weight == 6.0) + Weight = 10.0; + } + } +} diff --git a/Projects/UOContent/Items/Construction/Chairs/Thrones.cs b/Projects/UOContent/Items/Construction/Chairs/Thrones.cs index 7136e8264..a5e396877 100644 --- a/Projects/UOContent/Items/Construction/Chairs/Thrones.cs +++ b/Projects/UOContent/Items/Construction/Chairs/Thrones.cs @@ -1,60 +1,60 @@ -namespace Server.Items -{ - [Furniture] - [Flippable(0xB32, 0xB33)] - public class Throne : Item - { - [Constructible] - public Throne() : base(0xB33) => Weight = 1.0; - - public Throne(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 6.0) - Weight = 1.0; - } - } - - [Furniture] - [Flippable(0xB2E, 0xB2F, 0xB31, 0xB30)] - public class WoodenThrone : Item - { - [Constructible] - public WoodenThrone() : base(0xB2E) => Weight = 15.0; - - public WoodenThrone(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 6.0) - Weight = 15.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Furniture] + [Flippable(0xB32, 0xB33)] + public class Throne : Item + { + [Constructible] + public Throne() : base(0xB33) => Weight = 1.0; + + public Throne(Serial serial) : base(serial) + { + } + + 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 (Weight == 6.0) + Weight = 1.0; + } + } + + [Furniture] + [Flippable(0xB2E, 0xB2F, 0xB31, 0xB30)] + public class WoodenThrone : Item + { + [Constructible] + public WoodenThrone() : base(0xB2E) => Weight = 15.0; + + public WoodenThrone(Serial serial) : base(serial) + { + } + + 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 (Weight == 6.0) + Weight = 15.0; + } + } +} diff --git a/Projects/UOContent/Items/Construction/Decorative/DecorativeShield.cs b/Projects/UOContent/Items/Construction/Decorative/DecorativeShield.cs index d0f444bb7..17da20500 100644 --- a/Projects/UOContent/Items/Construction/Decorative/DecorativeShield.cs +++ b/Projects/UOContent/Items/Construction/Decorative/DecorativeShield.cs @@ -1,377 +1,377 @@ -namespace Server.Items -{ - [Flippable(0x156C, 0x156D)] - public class DecorativeShield1 : Item - { - [Constructible] - public DecorativeShield1() : base(0x156C) => Movable = false; - - public DecorativeShield1(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x156E, 0x156F)] - public class DecorativeShield2 : Item - { - [Constructible] - public DecorativeShield2() : base(0x156E) => Movable = false; - - public DecorativeShield2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1570, 0x1571)] - public class DecorativeShield3 : Item - { - [Constructible] - public DecorativeShield3() : base(0x1570) => Movable = false; - - public DecorativeShield3(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1572, 0x1573)] - public class DecorativeShield4 : Item - { - [Constructible] - public DecorativeShield4() : base(0x1572) => Movable = false; - - public DecorativeShield4(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1574, 0x1575)] - public class DecorativeShield5 : Item - { - [Constructible] - public DecorativeShield5() : base(0x1574) => Movable = false; - - public DecorativeShield5(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1576, 0x1577)] - public class DecorativeShield6 : Item - { - [Constructible] - public DecorativeShield6() : base(0x1576) => Movable = false; - - public DecorativeShield6(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1578, 0x1579)] - public class DecorativeShield7 : Item - { - [Constructible] - public DecorativeShield7() : base(0x1578) => Movable = false; - - public DecorativeShield7(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x157A, 0x157B)] - public class DecorativeShield8 : Item - { - [Constructible] - public DecorativeShield8() : base(0x157A) => Movable = false; - - public DecorativeShield8(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x157C, 0x157D)] - public class DecorativeShield9 : Item - { - [Constructible] - public DecorativeShield9() : base(0x157C) => Movable = false; - - public DecorativeShield9(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x157E, 0x157F)] - public class DecorativeShield10 : Item - { - [Constructible] - public DecorativeShield10() : base(0x157E) => Movable = false; - - public DecorativeShield10(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1580, 0x1581)] - public class DecorativeShield11 : Item - { - [Constructible] - public DecorativeShield11() : base(0x1580) => Movable = false; - - public DecorativeShield11(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1582, 0x1583, 0x1634, 0x1635)] - public class DecorativeShieldSword1North : Item - { - [Constructible] - public DecorativeShieldSword1North() : base(Utility.Random(0x1582, 2)) => Movable = false; - - public DecorativeShieldSword1North(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1634, 0x1635, 0x1582, 0x1583)] - public class DecorativeShieldSword1West : Item - { - [Constructible] - public DecorativeShieldSword1West() : base(Utility.Random(0x1634, 2)) => Movable = false; - - public DecorativeShieldSword1West(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1584, 0x1585, 0x1636, 0x1637)] - public class DecorativeShieldSword2North : Item - { - [Constructible] - public DecorativeShieldSword2North() : base(Utility.Random(0x1584, 2)) => Movable = false; - - public DecorativeShieldSword2North(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1636, 0x1637, 0x1584, 0x1585)] - public class DecorativeShieldSword2West : Item - { - [Constructible] - public DecorativeShieldSword2West() : base(Utility.Random(0x1636, 2)) => Movable = false; - - public DecorativeShieldSword2West(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x156C, 0x156D)] + public class DecorativeShield1 : Item + { + [Constructible] + public DecorativeShield1() : base(0x156C) => Movable = false; + + public DecorativeShield1(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x156E, 0x156F)] + public class DecorativeShield2 : Item + { + [Constructible] + public DecorativeShield2() : base(0x156E) => Movable = false; + + public DecorativeShield2(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1570, 0x1571)] + public class DecorativeShield3 : Item + { + [Constructible] + public DecorativeShield3() : base(0x1570) => Movable = false; + + public DecorativeShield3(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1572, 0x1573)] + public class DecorativeShield4 : Item + { + [Constructible] + public DecorativeShield4() : base(0x1572) => Movable = false; + + public DecorativeShield4(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1574, 0x1575)] + public class DecorativeShield5 : Item + { + [Constructible] + public DecorativeShield5() : base(0x1574) => Movable = false; + + public DecorativeShield5(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1576, 0x1577)] + public class DecorativeShield6 : Item + { + [Constructible] + public DecorativeShield6() : base(0x1576) => Movable = false; + + public DecorativeShield6(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1578, 0x1579)] + public class DecorativeShield7 : Item + { + [Constructible] + public DecorativeShield7() : base(0x1578) => Movable = false; + + public DecorativeShield7(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x157A, 0x157B)] + public class DecorativeShield8 : Item + { + [Constructible] + public DecorativeShield8() : base(0x157A) => Movable = false; + + public DecorativeShield8(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x157C, 0x157D)] + public class DecorativeShield9 : Item + { + [Constructible] + public DecorativeShield9() : base(0x157C) => Movable = false; + + public DecorativeShield9(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x157E, 0x157F)] + public class DecorativeShield10 : Item + { + [Constructible] + public DecorativeShield10() : base(0x157E) => Movable = false; + + public DecorativeShield10(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1580, 0x1581)] + public class DecorativeShield11 : Item + { + [Constructible] + public DecorativeShield11() : base(0x1580) => Movable = false; + + public DecorativeShield11(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1582, 0x1583, 0x1634, 0x1635)] + public class DecorativeShieldSword1North : Item + { + [Constructible] + public DecorativeShieldSword1North() : base(Utility.Random(0x1582, 2)) => Movable = false; + + public DecorativeShieldSword1North(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1634, 0x1635, 0x1582, 0x1583)] + public class DecorativeShieldSword1West : Item + { + [Constructible] + public DecorativeShieldSword1West() : base(Utility.Random(0x1634, 2)) => Movable = false; + + public DecorativeShieldSword1West(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1584, 0x1585, 0x1636, 0x1637)] + public class DecorativeShieldSword2North : Item + { + [Constructible] + public DecorativeShieldSword2North() : base(Utility.Random(0x1584, 2)) => Movable = false; + + public DecorativeShieldSword2North(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1636, 0x1637, 0x1584, 0x1585)] + public class DecorativeShieldSword2West : Item + { + [Constructible] + public DecorativeShieldSword2West() : base(Utility.Random(0x1636, 2)) => Movable = false; + + public DecorativeShieldSword2West(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Decorative/DecorativeWeapon.cs b/Projects/UOContent/Items/Construction/Decorative/DecorativeWeapon.cs index 20299cda8..9d0a678a8 100644 --- a/Projects/UOContent/Items/Construction/Decorative/DecorativeWeapon.cs +++ b/Projects/UOContent/Items/Construction/Decorative/DecorativeWeapon.cs @@ -1,530 +1,530 @@ -namespace Server.Items -{ - [Flippable(0x155E, 0x155F, 0x155C, 0x155D)] - public class DecorativeBowWest : Item - { - [Constructible] - public DecorativeBowWest() : base(Utility.Random(0x155E, 2)) => Movable = false; - - public DecorativeBowWest(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x155C, 0x155D, 0x155E, 0x155F)] - public class DecorativeBowNorth : Item - { - [Constructible] - public DecorativeBowNorth() : base(Utility.Random(0x155C, 2)) => Movable = false; - - public DecorativeBowNorth(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1560, 0x1561, 0x1562, 0x1563)] - public class DecorativeAxeNorth : Item - { - [Constructible] - public DecorativeAxeNorth() : base(Utility.Random(0x1560, 2)) => Movable = false; - - public DecorativeAxeNorth(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1562, 0x1563, 0x1560, 0x1561)] - public class DecorativeAxeWest : Item - { - [Constructible] - public DecorativeAxeWest() : base(Utility.Random(0x1562, 2)) => Movable = false; - - public DecorativeAxeWest(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DecorativeSwordNorth : Item - { - private InternalItem m_Item; - - [Constructible] - public DecorativeSwordNorth() : base(0x1565) - { - Movable = false; - - m_Item = new InternalItem(this); - } - - public DecorativeSwordNorth(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X - 1, Y, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as InternalItem; - } - - private class InternalItem : Item - { - private DecorativeSwordNorth m_Item; - - public InternalItem(DecorativeSwordNorth item) : base(0x1564) - { - Movable = true; - - m_Item = item; - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X + 1, Y, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as DecorativeSwordNorth; - } - } - } - - public class DecorativeSwordWest : Item - { - private InternalItem m_Item; - - [Constructible] - public DecorativeSwordWest() : base(0x1566) - { - Movable = false; - - m_Item = new InternalItem(this); - } - - public DecorativeSwordWest(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X, Y - 1, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as InternalItem; - } - - private class InternalItem : Item - { - private DecorativeSwordWest m_Item; - - public InternalItem(DecorativeSwordWest item) : base(0x1567) - { - Movable = true; - - m_Item = item; - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X, Y + 1, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as DecorativeSwordWest; - } - } - } - - public class DecorativeDAxeNorth : Item - { - private InternalItem m_Item; - - [Constructible] - public DecorativeDAxeNorth() : base(0x1569) - { - Movable = false; - - m_Item = new InternalItem(this); - } - - public DecorativeDAxeNorth(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X - 1, Y, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as InternalItem; - } - - private class InternalItem : Item - { - private DecorativeDAxeNorth m_Item; - - public InternalItem(DecorativeDAxeNorth item) : base(0x1568) - { - Movable = true; - - m_Item = item; - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X + 1, Y, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as DecorativeDAxeNorth; - } - } - } - - public class DecorativeDAxeWest : Item - { - private InternalItem m_Item; - - [Constructible] - public DecorativeDAxeWest() : base(0x156A) - { - Movable = false; - - m_Item = new InternalItem(this); - } - - public DecorativeDAxeWest(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X, Y - 1, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as InternalItem; - } - - private class InternalItem : Item - { - private DecorativeDAxeWest m_Item; - - public InternalItem(DecorativeDAxeWest item) : base(0x156B) - { - Movable = true; - - m_Item = item; - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X, Y + 1, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as DecorativeDAxeWest; - } - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x155E, 0x155F, 0x155C, 0x155D)] + public class DecorativeBowWest : Item + { + [Constructible] + public DecorativeBowWest() : base(Utility.Random(0x155E, 2)) => Movable = false; + + public DecorativeBowWest(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x155C, 0x155D, 0x155E, 0x155F)] + public class DecorativeBowNorth : Item + { + [Constructible] + public DecorativeBowNorth() : base(Utility.Random(0x155C, 2)) => Movable = false; + + public DecorativeBowNorth(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1560, 0x1561, 0x1562, 0x1563)] + public class DecorativeAxeNorth : Item + { + [Constructible] + public DecorativeAxeNorth() : base(Utility.Random(0x1560, 2)) => Movable = false; + + public DecorativeAxeNorth(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1562, 0x1563, 0x1560, 0x1561)] + public class DecorativeAxeWest : Item + { + [Constructible] + public DecorativeAxeWest() : base(Utility.Random(0x1562, 2)) => Movable = false; + + public DecorativeAxeWest(Serial serial) : base(serial) + { + } + + 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 class DecorativeSwordNorth : Item + { + private InternalItem m_Item; + + [Constructible] + public DecorativeSwordNorth() : base(0x1565) + { + Movable = false; + + m_Item = new InternalItem(this); + } + + public DecorativeSwordNorth(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X - 1, Y, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as InternalItem; + } + + private class InternalItem : Item + { + private DecorativeSwordNorth m_Item; + + public InternalItem(DecorativeSwordNorth item) : base(0x1564) + { + Movable = true; + + m_Item = item; + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X + 1, Y, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as DecorativeSwordNorth; + } + } + } + + public class DecorativeSwordWest : Item + { + private InternalItem m_Item; + + [Constructible] + public DecorativeSwordWest() : base(0x1566) + { + Movable = false; + + m_Item = new InternalItem(this); + } + + public DecorativeSwordWest(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X, Y - 1, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as InternalItem; + } + + private class InternalItem : Item + { + private DecorativeSwordWest m_Item; + + public InternalItem(DecorativeSwordWest item) : base(0x1567) + { + Movable = true; + + m_Item = item; + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X, Y + 1, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as DecorativeSwordWest; + } + } + } + + public class DecorativeDAxeNorth : Item + { + private InternalItem m_Item; + + [Constructible] + public DecorativeDAxeNorth() : base(0x1569) + { + Movable = false; + + m_Item = new InternalItem(this); + } + + public DecorativeDAxeNorth(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X - 1, Y, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as InternalItem; + } + + private class InternalItem : Item + { + private DecorativeDAxeNorth m_Item; + + public InternalItem(DecorativeDAxeNorth item) : base(0x1568) + { + Movable = true; + + m_Item = item; + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X + 1, Y, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as DecorativeDAxeNorth; + } + } + } + + public class DecorativeDAxeWest : Item + { + private InternalItem m_Item; + + [Constructible] + public DecorativeDAxeWest() : base(0x156A) + { + Movable = false; + + m_Item = new InternalItem(this); + } + + public DecorativeDAxeWest(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X, Y - 1, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as InternalItem; + } + + private class InternalItem : Item + { + private DecorativeDAxeWest m_Item; + + public InternalItem(DecorativeDAxeWest item) : base(0x156B) + { + Movable = true; + + m_Item = item; + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X, Y + 1, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as DecorativeDAxeWest; + } + } + } +} diff --git a/Projects/UOContent/Items/Construction/Decorative/PaintingPortraits.cs b/Projects/UOContent/Items/Construction/Decorative/PaintingPortraits.cs index d99340ef3..688bcd52b 100644 --- a/Projects/UOContent/Items/Construction/Decorative/PaintingPortraits.cs +++ b/Projects/UOContent/Items/Construction/Decorative/PaintingPortraits.cs @@ -1,176 +1,176 @@ -namespace Server.Items -{ - public class LargePainting : Item - { - [Constructible] - public LargePainting() : base(0x0EA0) => Movable = false; - - public LargePainting(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x0E9F, 0x0EC8)] - public class WomanPortrait1 : Item - { - [Constructible] - public WomanPortrait1() : base(0x0E9F) => Movable = false; - - public WomanPortrait1(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x0EE7, 0x0EC9)] - public class WomanPortrait2 : Item - { - [Constructible] - public WomanPortrait2() : base(0x0EE7) => Movable = false; - - public WomanPortrait2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x0EA2, 0x0EA1)] - public class ManPortrait1 : Item - { - [Constructible] - public ManPortrait1() : base(0x0EA2) => Movable = false; - - public ManPortrait1(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x0EA3, 0x0EA4)] - public class ManPortrait2 : Item - { - [Constructible] - public ManPortrait2() : base(0x0EA3) => Movable = false; - - public ManPortrait2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x0EA6, 0x0EA5)] - public class LadyPortrait1 : Item - { - [Constructible] - public LadyPortrait1() : base(0x0EA6) => Movable = false; - - public LadyPortrait1(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x0EA7, 0x0EA8)] - public class LadyPortrait2 : Item - { - [Constructible] - public LadyPortrait2() : base(0x0EA7) => Movable = false; - - public LadyPortrait2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LargePainting : Item + { + [Constructible] + public LargePainting() : base(0x0EA0) => Movable = false; + + public LargePainting(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x0E9F, 0x0EC8)] + public class WomanPortrait1 : Item + { + [Constructible] + public WomanPortrait1() : base(0x0E9F) => Movable = false; + + public WomanPortrait1(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x0EE7, 0x0EC9)] + public class WomanPortrait2 : Item + { + [Constructible] + public WomanPortrait2() : base(0x0EE7) => Movable = false; + + public WomanPortrait2(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x0EA2, 0x0EA1)] + public class ManPortrait1 : Item + { + [Constructible] + public ManPortrait1() : base(0x0EA2) => Movable = false; + + public ManPortrait1(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x0EA3, 0x0EA4)] + public class ManPortrait2 : Item + { + [Constructible] + public ManPortrait2() : base(0x0EA3) => Movable = false; + + public ManPortrait2(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x0EA6, 0x0EA5)] + public class LadyPortrait1 : Item + { + [Constructible] + public LadyPortrait1() : base(0x0EA6) => Movable = false; + + public LadyPortrait1(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x0EA7, 0x0EA8)] + public class LadyPortrait2 : Item + { + [Constructible] + public LadyPortrait2() : base(0x0EA7) => Movable = false; + + public LadyPortrait2(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Decorative/Tapestry.cs b/Projects/UOContent/Items/Construction/Decorative/Tapestry.cs index e20daf38f..baeda8976 100644 --- a/Projects/UOContent/Items/Construction/Decorative/Tapestry.cs +++ b/Projects/UOContent/Items/Construction/Decorative/Tapestry.cs @@ -1,1179 +1,1179 @@ -namespace Server.Items -{ - public class Tapestry1N : Item - { - private InternalItem m_Item; - - [Constructible] - public Tapestry1N() : base(0xEAA) - { - Movable = false; - - m_Item = new InternalItem(this); - } - - public Tapestry1N(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X + 1, Y, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as InternalItem; - } - - private class InternalItem : Item - { - private Tapestry1N m_Item; - - public InternalItem(Tapestry1N item) : base(0xEAB) - { - Movable = true; - - m_Item = item; - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X - 1, Y, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as Tapestry1N; - } - } - } - - public class Tapestry2N : Item - { - private InternalItem m_Item; - - [Constructible] - public Tapestry2N() : base(0xEAC) - { - Movable = false; - - m_Item = new InternalItem(this); - } - - public Tapestry2N(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X + 1, Y, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as InternalItem; - } - - private class InternalItem : Item - { - private Tapestry2N m_Item; - - public InternalItem(Tapestry2N item) : base(0xEAD) - { - Movable = true; - - m_Item = item; - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X - 1, Y, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as Tapestry2N; - } - } - } - - public class Tapestry2W : Item - { - private InternalItem m_Item; - - [Constructible] - public Tapestry2W() : base(0xEAE) - { - Movable = false; - - m_Item = new InternalItem(this); - } - - public Tapestry2W(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X, Y - 1, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as InternalItem; - } - - private class InternalItem : Item - { - private Tapestry2W m_Item; - - public InternalItem(Tapestry2W item) : base(0xEAF) - { - Movable = true; - - m_Item = item; - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X, Y + 1, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as Tapestry2W; - } - } - } - - public class Tapestry3N : Item - { - private InternalItem m_Item; - - [Constructible] - public Tapestry3N() : base(0xFD6) - { - Movable = false; - - m_Item = new InternalItem(this); - } - - public Tapestry3N(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X - 2, Y, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as InternalItem; - } - - private class InternalItem : Item - { - private Tapestry3N m_Item; - - public InternalItem(Tapestry3N item) : base(0xFD5) - { - Movable = true; - - m_Item = item; - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X + 2, Y, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as Tapestry3N; - } - } - } - - public class Tapestry3W : Item - { - private InternalItem m_Item; - - [Constructible] - public Tapestry3W() : base(0xFD7) - { - Movable = false; - - m_Item = new InternalItem(this); - } - - public Tapestry3W(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X, Y - 2, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as InternalItem; - } - - private class InternalItem : Item - { - private Tapestry3W m_Item; - - public InternalItem(Tapestry3W item) : base(0xFD8) - { - Movable = true; - - m_Item = item; - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X, Y + 2, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as Tapestry3W; - } - } - } - - public class Tapestry4N : Item - { - private InternalItem m_Item; - - [Constructible] - public Tapestry4N() : base(0xFDA) - { - Movable = false; - - m_Item = new InternalItem(this); - } - - public Tapestry4N(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X - 1, Y, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as InternalItem; - } - - private class InternalItem : Item - { - private Tapestry4N m_Item; - - public InternalItem(Tapestry4N item) : base(0xFD9) - { - Movable = true; - - m_Item = item; - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X + 1, Y, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as Tapestry4N; - } - } - } - - public class Tapestry4W : Item - { - private InternalItem m_Item; - - [Constructible] - public Tapestry4W() : base(0xFDB) - { - Movable = false; - - m_Item = new InternalItem(this); - } - - public Tapestry4W(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X, Y - 1, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as InternalItem; - } - - private class InternalItem : Item - { - private Tapestry4W m_Item; - - public InternalItem(Tapestry4W item) : base(0xFDC) - { - Movable = true; - - m_Item = item; - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X, Y + 1, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as Tapestry4W; - } - } - } - - public class Tapestry5N : Item - { - private InternalItem m_Item; - - [Constructible] - public Tapestry5N() : base(0xFDE) - { - Movable = false; - - m_Item = new InternalItem(this); - } - - public Tapestry5N(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X - 1, Y, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as InternalItem; - } - - private class InternalItem : Item - { - private Tapestry5N m_Item; - - public InternalItem(Tapestry5N item) : base(0xFDD) - { - Movable = true; - - m_Item = item; - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X + 1, Y, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as Tapestry5N; - } - } - } - - public class Tapestry5W : Item - { - private InternalItem m_Item; - - [Constructible] - public Tapestry5W() : base(0xFDF) - { - Movable = false; - - m_Item = new InternalItem(this); - } - - public Tapestry5W(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X, Y - 1, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as InternalItem; - } - - private class InternalItem : Item - { - private Tapestry5W m_Item; - - public InternalItem(Tapestry5W item) : base(0xFE0) - { - Movable = true; - - m_Item = item; - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X, Y + 1, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as Tapestry5W; - } - } - } - - public class Tapestry6N : Item - { - private InternalItem m_Item; - - [Constructible] - public Tapestry6N() : base(0xFE2) - { - Movable = false; - - m_Item = new InternalItem(this); - } - - public Tapestry6N(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X - 1, Y, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as InternalItem; - } - - private class InternalItem : Item - { - private Tapestry6N m_Item; - - public InternalItem(Tapestry6N item) : base(0xFE1) - { - Movable = true; - - m_Item = item; - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X + 1, Y, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as Tapestry6N; - } - } - } - - public class Tapestry6W : Item - { - private InternalItem m_Item; - - [Constructible] - public Tapestry6W() : base(0xFE3) - { - Movable = false; - - m_Item = new InternalItem(this); - } - - public Tapestry6W(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X, Y - 1, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as InternalItem; - } - - private class InternalItem : Item - { - private Tapestry6W m_Item; - - public InternalItem(Tapestry6W item) : base(0xFE4) - { - Movable = true; - - m_Item = item; - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X, Y + 1, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as Tapestry6W; - } - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Tapestry1N : Item + { + private InternalItem m_Item; + + [Constructible] + public Tapestry1N() : base(0xEAA) + { + Movable = false; + + m_Item = new InternalItem(this); + } + + public Tapestry1N(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X + 1, Y, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as InternalItem; + } + + private class InternalItem : Item + { + private Tapestry1N m_Item; + + public InternalItem(Tapestry1N item) : base(0xEAB) + { + Movable = true; + + m_Item = item; + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X - 1, Y, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as Tapestry1N; + } + } + } + + public class Tapestry2N : Item + { + private InternalItem m_Item; + + [Constructible] + public Tapestry2N() : base(0xEAC) + { + Movable = false; + + m_Item = new InternalItem(this); + } + + public Tapestry2N(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X + 1, Y, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as InternalItem; + } + + private class InternalItem : Item + { + private Tapestry2N m_Item; + + public InternalItem(Tapestry2N item) : base(0xEAD) + { + Movable = true; + + m_Item = item; + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X - 1, Y, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as Tapestry2N; + } + } + } + + public class Tapestry2W : Item + { + private InternalItem m_Item; + + [Constructible] + public Tapestry2W() : base(0xEAE) + { + Movable = false; + + m_Item = new InternalItem(this); + } + + public Tapestry2W(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X, Y - 1, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as InternalItem; + } + + private class InternalItem : Item + { + private Tapestry2W m_Item; + + public InternalItem(Tapestry2W item) : base(0xEAF) + { + Movable = true; + + m_Item = item; + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X, Y + 1, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as Tapestry2W; + } + } + } + + public class Tapestry3N : Item + { + private InternalItem m_Item; + + [Constructible] + public Tapestry3N() : base(0xFD6) + { + Movable = false; + + m_Item = new InternalItem(this); + } + + public Tapestry3N(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X - 2, Y, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as InternalItem; + } + + private class InternalItem : Item + { + private Tapestry3N m_Item; + + public InternalItem(Tapestry3N item) : base(0xFD5) + { + Movable = true; + + m_Item = item; + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X + 2, Y, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as Tapestry3N; + } + } + } + + public class Tapestry3W : Item + { + private InternalItem m_Item; + + [Constructible] + public Tapestry3W() : base(0xFD7) + { + Movable = false; + + m_Item = new InternalItem(this); + } + + public Tapestry3W(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X, Y - 2, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as InternalItem; + } + + private class InternalItem : Item + { + private Tapestry3W m_Item; + + public InternalItem(Tapestry3W item) : base(0xFD8) + { + Movable = true; + + m_Item = item; + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X, Y + 2, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as Tapestry3W; + } + } + } + + public class Tapestry4N : Item + { + private InternalItem m_Item; + + [Constructible] + public Tapestry4N() : base(0xFDA) + { + Movable = false; + + m_Item = new InternalItem(this); + } + + public Tapestry4N(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X - 1, Y, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as InternalItem; + } + + private class InternalItem : Item + { + private Tapestry4N m_Item; + + public InternalItem(Tapestry4N item) : base(0xFD9) + { + Movable = true; + + m_Item = item; + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X + 1, Y, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as Tapestry4N; + } + } + } + + public class Tapestry4W : Item + { + private InternalItem m_Item; + + [Constructible] + public Tapestry4W() : base(0xFDB) + { + Movable = false; + + m_Item = new InternalItem(this); + } + + public Tapestry4W(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X, Y - 1, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as InternalItem; + } + + private class InternalItem : Item + { + private Tapestry4W m_Item; + + public InternalItem(Tapestry4W item) : base(0xFDC) + { + Movable = true; + + m_Item = item; + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X, Y + 1, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as Tapestry4W; + } + } + } + + public class Tapestry5N : Item + { + private InternalItem m_Item; + + [Constructible] + public Tapestry5N() : base(0xFDE) + { + Movable = false; + + m_Item = new InternalItem(this); + } + + public Tapestry5N(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X - 1, Y, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as InternalItem; + } + + private class InternalItem : Item + { + private Tapestry5N m_Item; + + public InternalItem(Tapestry5N item) : base(0xFDD) + { + Movable = true; + + m_Item = item; + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X + 1, Y, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as Tapestry5N; + } + } + } + + public class Tapestry5W : Item + { + private InternalItem m_Item; + + [Constructible] + public Tapestry5W() : base(0xFDF) + { + Movable = false; + + m_Item = new InternalItem(this); + } + + public Tapestry5W(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X, Y - 1, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as InternalItem; + } + + private class InternalItem : Item + { + private Tapestry5W m_Item; + + public InternalItem(Tapestry5W item) : base(0xFE0) + { + Movable = true; + + m_Item = item; + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X, Y + 1, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as Tapestry5W; + } + } + } + + public class Tapestry6N : Item + { + private InternalItem m_Item; + + [Constructible] + public Tapestry6N() : base(0xFE2) + { + Movable = false; + + m_Item = new InternalItem(this); + } + + public Tapestry6N(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X - 1, Y, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as InternalItem; + } + + private class InternalItem : Item + { + private Tapestry6N m_Item; + + public InternalItem(Tapestry6N item) : base(0xFE1) + { + Movable = true; + + m_Item = item; + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X + 1, Y, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as Tapestry6N; + } + } + } + + public class Tapestry6W : Item + { + private InternalItem m_Item; + + [Constructible] + public Tapestry6W() : base(0xFE3) + { + Movable = false; + + m_Item = new InternalItem(this); + } + + public Tapestry6W(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X, Y - 1, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as InternalItem; + } + + private class InternalItem : Item + { + private Tapestry6W m_Item; + + public InternalItem(Tapestry6W item) : base(0xFE4) + { + Movable = true; + + m_Item = item; + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X, Y + 1, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as Tapestry6W; + } + } + } +} diff --git a/Projects/UOContent/Items/Construction/Doors/BaseDoor.cs b/Projects/UOContent/Items/Construction/Doors/BaseDoor.cs index 505810a4c..8ce8d5a7d 100644 --- a/Projects/UOContent/Items/Construction/Doors/BaseDoor.cs +++ b/Projects/UOContent/Items/Construction/Doors/BaseDoor.cs @@ -1,511 +1,521 @@ -using System; -using System.Collections.Generic; -using Server.Network; -using Server.Targeting; - -namespace Server.Items -{ - public abstract class BaseDoor : Item, ILockable, ITelekinesisable - { - private static readonly Point3D[] m_Offsets = - { - new Point3D(-1, 1, 0), - new Point3D(1, 1, 0), - new Point3D(-1, 0, 0), - new Point3D(1, -1, 0), - new Point3D(1, 1, 0), - new Point3D(1, -1, 0), - new Point3D(0, 0, 0), - new Point3D(0, -1, 0), - - new Point3D(0, 0, 0), - new Point3D(0, 0, 0), - new Point3D(0, 0, 0), - new Point3D(0, 0, 0) - }; - - private BaseDoor m_Link; - private bool m_Open; - - private Timer m_Timer; - - public BaseDoor(int closedID, int openedID, int openedSound, int closedSound, Point3D offset) : base(closedID) - { - OpenedID = openedID; - ClosedID = closedID; - OpenedSound = openedSound; - ClosedSound = closedSound; - Offset = offset; - - m_Timer = new InternalTimer(this); - - Movable = false; - } - - public BaseDoor(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Open - { - get => m_Open; - set - { - if (m_Open != value) - { - m_Open = value; - - ItemID = m_Open ? OpenedID : ClosedID; - - if (m_Open) - Location = new Point3D(X + Offset.X, Y + Offset.Y, Z + Offset.Z); - else - Location = new Point3D(X - Offset.X, Y - Offset.Y, Z - Offset.Z); - - Effects.PlaySound(this, Map, m_Open ? OpenedSound : ClosedSound); - - if (m_Open) - m_Timer.Start(); - else - m_Timer.Stop(); - } - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int OpenedID { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int ClosedID { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int OpenedSound { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int ClosedSound { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D Offset { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public BaseDoor Link - { - get - { - if (m_Link?.Deleted == true) - m_Link = null; - - return m_Link; - } - set => m_Link = value; - } - - public virtual bool UseChainedFunctionality => false; - - [CommandProperty(AccessLevel.GameMaster)] - public bool Locked { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public uint KeyValue { get; set; } - - public void OnTelekinesis(Mobile from) - { - Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x376A, 9, 32, 5022); - Effects.PlaySound(Location, Map, 0x1F5); - - Use(from); - } - - // Called by RunUO - public static void Initialize() - { - EventSink.OpenDoorMacroUsed += EventSink_OpenDoorMacroUsed; - - CommandSystem.Register("Link", AccessLevel.GameMaster, Link_OnCommand); - CommandSystem.Register("ChainLink", AccessLevel.GameMaster, ChainLink_OnCommand); - } - - [Usage("Link")] - [Description("Links two targeted doors together.")] - private static void Link_OnCommand(CommandEventArgs e) - { - e.Mobile.BeginTarget(-1, false, TargetFlags.None, Link_OnFirstTarget); - e.Mobile.SendMessage("Target the first door to link."); - } - - private static void Link_OnFirstTarget(Mobile from, object targeted) - { - if (!(targeted is BaseDoor door)) - { - from.BeginTarget(-1, false, TargetFlags.None, Link_OnFirstTarget); - from.SendMessage("That is not a door. Try again."); - } - else - { - from.BeginTarget(-1, false, TargetFlags.None, Link_OnSecondTarget, door); - from.SendMessage("Target the second door to link."); - } - } - - private static void Link_OnSecondTarget(Mobile from, object targeted, BaseDoor first) - { - if (!(targeted is BaseDoor second)) - { - from.BeginTarget(-1, false, TargetFlags.None, Link_OnSecondTarget, first); - from.SendMessage("That is not a door. Try again."); - } - else - { - first.Link = second; - second.Link = first; - from.SendMessage("The doors have been linked."); - } - } - - [Usage("ChainLink")] - [Description("Chain-links two or more targeted doors together.")] - private static void ChainLink_OnCommand(CommandEventArgs e) - { - e.Mobile.BeginTarget(-1, false, TargetFlags.None, ChainLink_OnTarget, new List()); - e.Mobile.SendMessage("Target the first of a sequence of doors to link."); - } - - private static void ChainLink_OnTarget(Mobile from, object targeted, List list) - { - if (!(targeted is BaseDoor door)) - { - from.BeginTarget(-1, false, TargetFlags.None, ChainLink_OnTarget, list); - from.SendMessage("That is not a door. Try again."); - } - else - { - if (list.Count > 0 && list[0] == door) - { - if (list.Count >= 2) - { - for (int i = 0; i < list.Count; ++i) - list[i].Link = list[(i + 1) % list.Count]; - - from.SendMessage("The chain of doors have been linked."); - } - else - { - from.BeginTarget(-1, false, TargetFlags.None, ChainLink_OnTarget, list); - from.SendMessage("You have not yet targeted two unique doors. Target the second door to link."); - } - } - else if (list.Contains(door)) - { - from.BeginTarget(-1, false, TargetFlags.None, ChainLink_OnTarget, list); - from.SendMessage( - "You have already targeted that door. Target another door, or retarget the first door to complete the chain."); - } - else - { - list.Add(door); - - from.BeginTarget(-1, false, TargetFlags.None, ChainLink_OnTarget, list); - - if (list.Count == 1) - from.SendMessage("Target the second door to link."); - else - from.SendMessage("Target another door to link. To complete the chain, retarget the first door."); - } - } - } - - private static void EventSink_OpenDoorMacroUsed(Mobile m) - { - if (m.Map == null) return; - - int x = m.X, y = m.Y; - - switch (m.Direction & Direction.Mask) - { - case Direction.North: - --y; - break; - case Direction.Right: - ++x; - --y; - break; - case Direction.East: - ++x; - break; - case Direction.Down: - ++x; - ++y; - break; - case Direction.South: - ++y; - break; - case Direction.Left: - --x; - ++y; - break; - case Direction.West: - --x; - break; - case Direction.Up: - --x; - --y; - break; - } - - Sector sector = m.Map.GetSector(x, y); - - foreach (Item item in sector.Items) - if (item.Location.X == x && item.Location.Y == y && item.Z + item.ItemData.Height > m.Z && - m.Z + 16 > item.Z && item is BaseDoor && m.CanSee(item) && m.InLOS(item)) - { - if (m.CheckAlive()) - { - m.SendLocalizedMessage(500024); // Opening door... - item.OnDoubleClick(m); - } - - break; - } - } - - public static Point3D GetOffset(DoorFacing facing) => m_Offsets[(int)facing]; - - public bool CanClose() - { - if (!m_Open) - return true; - - Map map = Map; - - if (map == null) - return false; - - Point3D p = new Point3D(X - Offset.X, Y - Offset.Y, Z - Offset.Z); - - return CheckFit(map, p, 16); - } - - private bool CheckFit(Map map, Point3D p, int height) - { - if (map == Map.Internal) - return false; - - int x = p.X; - int y = p.Y; - int z = p.Z; - - Sector sector = map.GetSector(x, y); - List items = sector.Items; - List mobs = sector.Mobiles; - - for (int i = 0; i < items.Count; ++i) - { - Item item = items[i]; - - if (!(item is BaseMulti) && item.ItemID <= TileData.MaxItemValue && item.AtWorldPoint(x, y) && - !(item is BaseDoor)) - { - ItemData id = item.ItemData; - bool surface = id.Surface; - bool impassable = id.Impassable; - - if ((surface || impassable) && item.Z + id.CalcHeight > z && z + height > item.Z) - return false; - } - } - - for (int i = 0; i < mobs.Count; ++i) - { - Mobile m = mobs[i]; - - if (m.Location.X == x && m.Location.Y == y) - { - if (m.Hidden && m.AccessLevel > AccessLevel.Player) - continue; - - if (!m.Alive) - continue; - - if (m.Z + 16 > z && z + height > m.Z) - return false; - } - } - - return true; - } - - public List GetChain() - { - List list = new List(); - BaseDoor c = this; - - do - { - list.Add(c); - c = c.Link; - } while (c != null && !list.Contains(c)); - - return list; - } - - public bool IsFreeToClose() - { - if (!UseChainedFunctionality) - return CanClose(); - - List list = GetChain(); - - bool freeToClose = true; - - for (int i = 0; freeToClose && i < list.Count; ++i) - freeToClose = list[i].CanClose(); - - return freeToClose; - } - - public virtual bool IsInside(Mobile from) => false; - - public virtual bool UseLocks() => true; - - public virtual void Use(Mobile from) - { - if (Locked && !m_Open && UseLocks()) - { - if (from.AccessLevel >= AccessLevel.GameMaster) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 502502); // That is locked, but you open it with your godly powers. - // from.Send( new MessageLocalized( Serial, ItemID, MessageType.Regular, 0x3B2, 3, 502502, "", "" ) ); // That is locked, but you open it with your godly powers. - } - else if (Key.ContainsKey(from.Backpack, KeyValue)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 501282); // You quickly unlock, open, and relock the door - } - else if (IsInside(from)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 501280); // That is locked, but is usable from the inside. - } - else - { - if (Hue == 0x44E && Map == Map.Malas) // doom door into healer room in doom - SendLocalizedMessageTo(from, 1060014); // Only the dead may pass. - else - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502503); // That is locked. - - return; - } - } - - if (m_Open && !IsFreeToClose()) - return; - - if (m_Open) - OnClosed(from); - else - OnOpened(from); - - if (UseChainedFunctionality) - { - bool open = !m_Open; - - List list = GetChain(); - - for (int i = 0; i < list.Count; ++i) - list[i].Open = open; - } - else - { - Open = !m_Open; - - BaseDoor link = Link; - - if (m_Open && link?.Open == false) - link.Open = true; - } - } - - public virtual void OnOpened(Mobile from) - { - } - - public virtual void OnClosed(Mobile from) - { - } - - public override void OnDoubleClick(Mobile from) - { - if (from.AccessLevel == AccessLevel.Player && !from.InRange(GetWorldLocation(), 2)) - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - else - Use(from); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(KeyValue); - - writer.Write(m_Open); - writer.Write(Locked); - writer.Write(OpenedID); - writer.Write(ClosedID); - writer.Write(OpenedSound); - writer.Write(ClosedSound); - writer.Write(Offset); - writer.Write(m_Link); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - KeyValue = reader.ReadUInt(); - m_Open = reader.ReadBool(); - Locked = reader.ReadBool(); - OpenedID = reader.ReadInt(); - ClosedID = reader.ReadInt(); - OpenedSound = reader.ReadInt(); - ClosedSound = reader.ReadInt(); - Offset = reader.ReadPoint3D(); - m_Link = reader.ReadItem() as BaseDoor; - - m_Timer = new InternalTimer(this); - - if (m_Open) - m_Timer.Start(); - - break; - } - } - } - - private class InternalTimer : Timer - { - private readonly BaseDoor m_Door; - - public InternalTimer(BaseDoor door) : base(TimeSpan.FromSeconds(20.0), TimeSpan.FromSeconds(10.0)) - { - Priority = TimerPriority.OneSecond; - m_Door = door; - } - - protected override void OnTick() - { - if (m_Door.Open && m_Door.IsFreeToClose()) - m_Door.Open = false; - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Network; +using Server.Targeting; + +namespace Server.Items +{ + public abstract class BaseDoor : Item, ILockable, ITelekinesisable + { + private static readonly Point3D[] m_Offsets = + { + new Point3D(-1, 1, 0), + new Point3D(1, 1, 0), + new Point3D(-1, 0, 0), + new Point3D(1, -1, 0), + new Point3D(1, 1, 0), + new Point3D(1, -1, 0), + new Point3D(0, 0, 0), + new Point3D(0, -1, 0), + + new Point3D(0, 0, 0), + new Point3D(0, 0, 0), + new Point3D(0, 0, 0), + new Point3D(0, 0, 0) + }; + + private BaseDoor m_Link; + private bool m_Open; + + private Timer m_Timer; + + public BaseDoor(int closedID, int openedID, int openedSound, int closedSound, Point3D offset) : base(closedID) + { + OpenedID = openedID; + ClosedID = closedID; + OpenedSound = openedSound; + ClosedSound = closedSound; + Offset = offset; + + m_Timer = new InternalTimer(this); + + Movable = false; + } + + public BaseDoor(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Open + { + get => m_Open; + set + { + if (m_Open != value) + { + m_Open = value; + + ItemID = m_Open ? OpenedID : ClosedID; + + if (m_Open) + Location = new Point3D(X + Offset.X, Y + Offset.Y, Z + Offset.Z); + else + Location = new Point3D(X - Offset.X, Y - Offset.Y, Z - Offset.Z); + + Effects.PlaySound(this, Map, m_Open ? OpenedSound : ClosedSound); + + if (m_Open) + m_Timer.Start(); + else + m_Timer.Stop(); + } + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int OpenedID { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int ClosedID { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int OpenedSound { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int ClosedSound { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D Offset { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public BaseDoor Link + { + get + { + if (m_Link?.Deleted == true) + m_Link = null; + + return m_Link; + } + set => m_Link = value; + } + + public virtual bool UseChainedFunctionality => false; + + [CommandProperty(AccessLevel.GameMaster)] + public bool Locked { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public uint KeyValue { get; set; } + + public void OnTelekinesis(Mobile from) + { + Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x376A, 9, 32, 5022); + Effects.PlaySound(Location, Map, 0x1F5); + + Use(from); + } + + // Called by RunUO + public static void Initialize() + { + EventSink.OpenDoorMacroUsed += EventSink_OpenDoorMacroUsed; + + CommandSystem.Register("Link", AccessLevel.GameMaster, Link_OnCommand); + CommandSystem.Register("ChainLink", AccessLevel.GameMaster, ChainLink_OnCommand); + } + + [Usage("Link")] + [Description("Links two targeted doors together.")] + private static void Link_OnCommand(CommandEventArgs e) + { + e.Mobile.BeginTarget(-1, false, TargetFlags.None, Link_OnFirstTarget); + e.Mobile.SendMessage("Target the first door to link."); + } + + private static void Link_OnFirstTarget(Mobile from, object targeted) + { + if (!(targeted is BaseDoor door)) + { + from.BeginTarget(-1, false, TargetFlags.None, Link_OnFirstTarget); + from.SendMessage("That is not a door. Try again."); + } + else + { + from.BeginTarget(-1, false, TargetFlags.None, Link_OnSecondTarget, door); + from.SendMessage("Target the second door to link."); + } + } + + private static void Link_OnSecondTarget(Mobile from, object targeted, BaseDoor first) + { + if (!(targeted is BaseDoor second)) + { + from.BeginTarget(-1, false, TargetFlags.None, Link_OnSecondTarget, first); + from.SendMessage("That is not a door. Try again."); + } + else + { + first.Link = second; + second.Link = first; + from.SendMessage("The doors have been linked."); + } + } + + [Usage("ChainLink")] + [Description("Chain-links two or more targeted doors together.")] + private static void ChainLink_OnCommand(CommandEventArgs e) + { + e.Mobile.BeginTarget(-1, false, TargetFlags.None, ChainLink_OnTarget, new List()); + e.Mobile.SendMessage("Target the first of a sequence of doors to link."); + } + + private static void ChainLink_OnTarget(Mobile from, object targeted, List list) + { + if (!(targeted is BaseDoor door)) + { + from.BeginTarget(-1, false, TargetFlags.None, ChainLink_OnTarget, list); + from.SendMessage("That is not a door. Try again."); + } + else + { + if (list.Count > 0 && list[0] == door) + { + if (list.Count >= 2) + { + for (var i = 0; i < list.Count; ++i) + list[i].Link = list[(i + 1) % list.Count]; + + from.SendMessage("The chain of doors have been linked."); + } + else + { + from.BeginTarget(-1, false, TargetFlags.None, ChainLink_OnTarget, list); + from.SendMessage("You have not yet targeted two unique doors. Target the second door to link."); + } + } + else if (list.Contains(door)) + { + from.BeginTarget(-1, false, TargetFlags.None, ChainLink_OnTarget, list); + from.SendMessage( + "You have already targeted that door. Target another door, or retarget the first door to complete the chain." + ); + } + else + { + list.Add(door); + + from.BeginTarget(-1, false, TargetFlags.None, ChainLink_OnTarget, list); + + if (list.Count == 1) + from.SendMessage("Target the second door to link."); + else + from.SendMessage("Target another door to link. To complete the chain, retarget the first door."); + } + } + } + + private static void EventSink_OpenDoorMacroUsed(Mobile m) + { + if (m.Map == null) return; + + int x = m.X, y = m.Y; + + switch (m.Direction & Direction.Mask) + { + case Direction.North: + --y; + break; + case Direction.Right: + ++x; + --y; + break; + case Direction.East: + ++x; + break; + case Direction.Down: + ++x; + ++y; + break; + case Direction.South: + ++y; + break; + case Direction.Left: + --x; + ++y; + break; + case Direction.West: + --x; + break; + case Direction.Up: + --x; + --y; + break; + } + + var sector = m.Map.GetSector(x, y); + + foreach (var item in sector.Items) + if (item.Location.X == x && item.Location.Y == y && item.Z + item.ItemData.Height > m.Z && + m.Z + 16 > item.Z && item is BaseDoor && m.CanSee(item) && m.InLOS(item)) + { + if (m.CheckAlive()) + { + m.SendLocalizedMessage(500024); // Opening door... + item.OnDoubleClick(m); + } + + break; + } + } + + public static Point3D GetOffset(DoorFacing facing) => m_Offsets[(int)facing]; + + public bool CanClose() + { + if (!m_Open) + return true; + + var map = Map; + + if (map == null) + return false; + + var p = new Point3D(X - Offset.X, Y - Offset.Y, Z - Offset.Z); + + return CheckFit(map, p, 16); + } + + private bool CheckFit(Map map, Point3D p, int height) + { + if (map == Map.Internal) + return false; + + var x = p.X; + var y = p.Y; + var z = p.Z; + + var sector = map.GetSector(x, y); + var items = sector.Items; + var mobs = sector.Mobiles; + + for (var i = 0; i < items.Count; ++i) + { + var item = items[i]; + + if (!(item is BaseMulti) && item.ItemID <= TileData.MaxItemValue && item.AtWorldPoint(x, y) && + !(item is BaseDoor)) + { + var id = item.ItemData; + var surface = id.Surface; + var impassable = id.Impassable; + + if ((surface || impassable) && item.Z + id.CalcHeight > z && z + height > item.Z) + return false; + } + } + + for (var i = 0; i < mobs.Count; ++i) + { + var m = mobs[i]; + + if (m.Location.X == x && m.Location.Y == y) + { + if (m.Hidden && m.AccessLevel > AccessLevel.Player) + continue; + + if (!m.Alive) + continue; + + if (m.Z + 16 > z && z + height > m.Z) + return false; + } + } + + return true; + } + + public List GetChain() + { + var list = new List(); + var c = this; + + do + { + list.Add(c); + c = c.Link; + } while (c != null && !list.Contains(c)); + + return list; + } + + public bool IsFreeToClose() + { + if (!UseChainedFunctionality) + return CanClose(); + + var list = GetChain(); + + var freeToClose = true; + + for (var i = 0; freeToClose && i < list.Count; ++i) + freeToClose = list[i].CanClose(); + + return freeToClose; + } + + public virtual bool IsInside(Mobile from) => false; + + public virtual bool UseLocks() => true; + + public virtual void Use(Mobile from) + { + if (Locked && !m_Open && UseLocks()) + { + if (from.AccessLevel >= AccessLevel.GameMaster) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 502502 + ); // That is locked, but you open it with your godly powers. + // from.Send( new MessageLocalized( Serial, ItemID, MessageType.Regular, 0x3B2, 3, 502502, "", "" ) ); // That is locked, but you open it with your godly powers. + } + else if (Key.ContainsKey(from.Backpack, KeyValue)) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 501282 + ); // You quickly unlock, open, and relock the door + } + else if (IsInside(from)) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 501280 + ); // That is locked, but is usable from the inside. + } + else + { + if (Hue == 0x44E && Map == Map.Malas) // doom door into healer room in doom + SendLocalizedMessageTo(from, 1060014); // Only the dead may pass. + else + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502503); // That is locked. + + return; + } + } + + if (m_Open && !IsFreeToClose()) + return; + + if (m_Open) + OnClosed(from); + else + OnOpened(from); + + if (UseChainedFunctionality) + { + var open = !m_Open; + + var list = GetChain(); + + for (var i = 0; i < list.Count; ++i) + list[i].Open = open; + } + else + { + Open = !m_Open; + + var link = Link; + + if (m_Open && link?.Open == false) + link.Open = true; + } + } + + public virtual void OnOpened(Mobile from) + { + } + + public virtual void OnClosed(Mobile from) + { + } + + public override void OnDoubleClick(Mobile from) + { + if (from.AccessLevel == AccessLevel.Player && !from.InRange(GetWorldLocation(), 2)) + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + else + Use(from); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(KeyValue); + + writer.Write(m_Open); + writer.Write(Locked); + writer.Write(OpenedID); + writer.Write(ClosedID); + writer.Write(OpenedSound); + writer.Write(ClosedSound); + writer.Write(Offset); + writer.Write(m_Link); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + KeyValue = reader.ReadUInt(); + m_Open = reader.ReadBool(); + Locked = reader.ReadBool(); + OpenedID = reader.ReadInt(); + ClosedID = reader.ReadInt(); + OpenedSound = reader.ReadInt(); + ClosedSound = reader.ReadInt(); + Offset = reader.ReadPoint3D(); + m_Link = reader.ReadItem() as BaseDoor; + + m_Timer = new InternalTimer(this); + + if (m_Open) + m_Timer.Start(); + + break; + } + } + } + + private class InternalTimer : Timer + { + private readonly BaseDoor m_Door; + + public InternalTimer(BaseDoor door) : base(TimeSpan.FromSeconds(20.0), TimeSpan.FromSeconds(10.0)) + { + Priority = TimerPriority.OneSecond; + m_Door = door; + } + + protected override void OnTick() + { + if (m_Door.Open && m_Door.IsFreeToClose()) + m_Door.Open = false; + } + } + } +} diff --git a/Projects/UOContent/Items/Construction/Doors/Doors.cs b/Projects/UOContent/Items/Construction/Doors/Doors.cs index 3e4f9434c..1990fbb83 100644 --- a/Projects/UOContent/Items/Construction/Doors/Doors.cs +++ b/Projects/UOContent/Items/Construction/Doors/Doors.cs @@ -1,371 +1,436 @@ -namespace Server.Items -{ - public enum DoorFacing - { - WestCW, - EastCCW, - WestCCW, - EastCW, - SouthCW, - NorthCCW, - SouthCCW, - NorthCW, - - // Sliding Doors - SouthSW, - SouthSE, - WestSS, - WestSN - } - - public class IronGateShort : BaseDoor - { - [Constructible] - public IronGateShort(DoorFacing facing) : base(0x84c + 2 * (int)facing, 0x84d + 2 * (int)facing, 0xEC, 0xF3, - GetOffset(facing)) - { - } - - public IronGateShort(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) // Default Serialize method - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) // Default Deserialize method - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class IronGate : BaseDoor - { - [Constructible] - public IronGate(DoorFacing facing) : base(0x824 + 2 * (int)facing, 0x825 + 2 * (int)facing, 0xEC, 0xF3, - GetOffset(facing)) - { - } - - public IronGate(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) // Default Serialize method - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) // Default Deserialize method - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LightWoodGate : BaseDoor - { - [Constructible] - public LightWoodGate(DoorFacing facing) : base(0x839 + 2 * (int)facing, 0x83A + 2 * (int)facing, 0xEB, 0xF2, - GetOffset(facing)) - { - } - - public LightWoodGate(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) // Default Serialize method - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) // Default Deserialize method - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DarkWoodGate : BaseDoor - { - [Constructible] - public DarkWoodGate(DoorFacing facing) : base(0x866 + 2 * (int)facing, 0x867 + 2 * (int)facing, 0xEB, 0xF2, - GetOffset(facing)) - { - } - - public DarkWoodGate(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) // Default Serialize method - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) // Default Deserialize method - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class MetalDoor : BaseDoor - { - [Constructible] - public MetalDoor(DoorFacing facing) : base(0x675 + 2 * (int)facing, 0x676 + 2 * (int)facing, 0xEC, 0xF3, - GetOffset(facing)) - { - } - - public MetalDoor(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) // Default Serialize method - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) // Default Deserialize method - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BarredMetalDoor : BaseDoor - { - [Constructible] - public BarredMetalDoor(DoorFacing facing) : base(0x685 + 2 * (int)facing, 0x686 + 2 * (int)facing, 0xEC, 0xF3, - GetOffset(facing)) - { - } - - public BarredMetalDoor(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) // Default Serialize method - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) // Default Deserialize method - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BarredMetalDoor2 : BaseDoor - { - [Constructible] - public BarredMetalDoor2(DoorFacing facing) : base(0x1FED + 2 * (int)facing, 0x1FEE + 2 * (int)facing, 0xEC, 0xF3, - GetOffset(facing)) - { - } - - public BarredMetalDoor2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) // Default Serialize method - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) // Default Deserialize method - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class RattanDoor : BaseDoor - { - [Constructible] - public RattanDoor(DoorFacing facing) : base(0x695 + 2 * (int)facing, 0x696 + 2 * (int)facing, 0xEB, 0xF2, - GetOffset(facing)) - { - } - - public RattanDoor(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) // Default Serialize method - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) // Default Deserialize method - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DarkWoodDoor : BaseDoor - { - [Constructible] - public DarkWoodDoor(DoorFacing facing) : base(0x6A5 + 2 * (int)facing, 0x6A6 + 2 * (int)facing, 0xEA, 0xF1, - GetOffset(facing)) - { - } - - public DarkWoodDoor(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) // Default Serialize method - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) // Default Deserialize method - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class MediumWoodDoor : BaseDoor - { - [Constructible] - public MediumWoodDoor(DoorFacing facing) : base(0x6B5 + 2 * (int)facing, 0x6B6 + 2 * (int)facing, 0xEA, 0xF1, - GetOffset(facing)) - { - } - - public MediumWoodDoor(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) // Default Serialize method - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) // Default Deserialize method - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class MetalDoor2 : BaseDoor - { - [Constructible] - public MetalDoor2(DoorFacing facing) : base(0x6C5 + 2 * (int)facing, 0x6C6 + 2 * (int)facing, 0xEC, 0xF3, - GetOffset(facing)) - { - } - - public MetalDoor2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) // Default Serialize method - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) // Default Deserialize method - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LightWoodDoor : BaseDoor - { - [Constructible] - public LightWoodDoor(DoorFacing facing) : base(0x6D5 + 2 * (int)facing, 0x6D6 + 2 * (int)facing, 0xEA, 0xF1, - GetOffset(facing)) - { - } - - public LightWoodDoor(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) // Default Serialize method - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) // Default Deserialize method - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class StrongWoodDoor : BaseDoor - { - [Constructible] - public StrongWoodDoor(DoorFacing facing) : base(0x6E5 + 2 * (int)facing, 0x6E6 + 2 * (int)facing, 0xEA, 0xF1, - GetOffset(facing)) - { - } - - public StrongWoodDoor(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) // Default Serialize method - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) // Default Deserialize method - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public enum DoorFacing + { + WestCW, + EastCCW, + WestCCW, + EastCW, + SouthCW, + NorthCCW, + SouthCCW, + NorthCW, + + // Sliding Doors + SouthSW, + SouthSE, + WestSS, + WestSN + } + + public class IronGateShort : BaseDoor + { + [Constructible] + public IronGateShort(DoorFacing facing) : base( + 0x84c + 2 * (int)facing, + 0x84d + 2 * (int)facing, + 0xEC, + 0xF3, + GetOffset(facing) + ) + { + } + + public IronGateShort(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) // Default Serialize method + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) // Default Deserialize method + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public class IronGate : BaseDoor + { + [Constructible] + public IronGate(DoorFacing facing) : base( + 0x824 + 2 * (int)facing, + 0x825 + 2 * (int)facing, + 0xEC, + 0xF3, + GetOffset(facing) + ) + { + } + + public IronGate(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) // Default Serialize method + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) // Default Deserialize method + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public class LightWoodGate : BaseDoor + { + [Constructible] + public LightWoodGate(DoorFacing facing) : base( + 0x839 + 2 * (int)facing, + 0x83A + 2 * (int)facing, + 0xEB, + 0xF2, + GetOffset(facing) + ) + { + } + + public LightWoodGate(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) // Default Serialize method + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) // Default Deserialize method + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public class DarkWoodGate : BaseDoor + { + [Constructible] + public DarkWoodGate(DoorFacing facing) : base( + 0x866 + 2 * (int)facing, + 0x867 + 2 * (int)facing, + 0xEB, + 0xF2, + GetOffset(facing) + ) + { + } + + public DarkWoodGate(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) // Default Serialize method + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) // Default Deserialize method + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public class MetalDoor : BaseDoor + { + [Constructible] + public MetalDoor(DoorFacing facing) : base( + 0x675 + 2 * (int)facing, + 0x676 + 2 * (int)facing, + 0xEC, + 0xF3, + GetOffset(facing) + ) + { + } + + public MetalDoor(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) // Default Serialize method + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) // Default Deserialize method + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public class BarredMetalDoor : BaseDoor + { + [Constructible] + public BarredMetalDoor(DoorFacing facing) : base( + 0x685 + 2 * (int)facing, + 0x686 + 2 * (int)facing, + 0xEC, + 0xF3, + GetOffset(facing) + ) + { + } + + public BarredMetalDoor(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) // Default Serialize method + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) // Default Deserialize method + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public class BarredMetalDoor2 : BaseDoor + { + [Constructible] + public BarredMetalDoor2(DoorFacing facing) : base( + 0x1FED + 2 * (int)facing, + 0x1FEE + 2 * (int)facing, + 0xEC, + 0xF3, + GetOffset(facing) + ) + { + } + + public BarredMetalDoor2(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) // Default Serialize method + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) // Default Deserialize method + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public class RattanDoor : BaseDoor + { + [Constructible] + public RattanDoor(DoorFacing facing) : base( + 0x695 + 2 * (int)facing, + 0x696 + 2 * (int)facing, + 0xEB, + 0xF2, + GetOffset(facing) + ) + { + } + + public RattanDoor(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) // Default Serialize method + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) // Default Deserialize method + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public class DarkWoodDoor : BaseDoor + { + [Constructible] + public DarkWoodDoor(DoorFacing facing) : base( + 0x6A5 + 2 * (int)facing, + 0x6A6 + 2 * (int)facing, + 0xEA, + 0xF1, + GetOffset(facing) + ) + { + } + + public DarkWoodDoor(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) // Default Serialize method + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) // Default Deserialize method + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public class MediumWoodDoor : BaseDoor + { + [Constructible] + public MediumWoodDoor(DoorFacing facing) : base( + 0x6B5 + 2 * (int)facing, + 0x6B6 + 2 * (int)facing, + 0xEA, + 0xF1, + GetOffset(facing) + ) + { + } + + public MediumWoodDoor(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) // Default Serialize method + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) // Default Deserialize method + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public class MetalDoor2 : BaseDoor + { + [Constructible] + public MetalDoor2(DoorFacing facing) : base( + 0x6C5 + 2 * (int)facing, + 0x6C6 + 2 * (int)facing, + 0xEC, + 0xF3, + GetOffset(facing) + ) + { + } + + public MetalDoor2(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) // Default Serialize method + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) // Default Deserialize method + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public class LightWoodDoor : BaseDoor + { + [Constructible] + public LightWoodDoor(DoorFacing facing) : base( + 0x6D5 + 2 * (int)facing, + 0x6D6 + 2 * (int)facing, + 0xEA, + 0xF1, + GetOffset(facing) + ) + { + } + + public LightWoodDoor(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) // Default Serialize method + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) // Default Deserialize method + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public class StrongWoodDoor : BaseDoor + { + [Constructible] + public StrongWoodDoor(DoorFacing facing) : base( + 0x6E5 + 2 * (int)facing, + 0x6E6 + 2 * (int)facing, + 0xEA, + 0xF1, + GetOffset(facing) + ) + { + } + + public StrongWoodDoor(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) // Default Serialize method + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) // Default Deserialize method + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Doors/HouseDoors.cs b/Projects/UOContent/Items/Construction/Doors/HouseDoors.cs index 6fbebdf4c..ea97a4a59 100644 --- a/Projects/UOContent/Items/Construction/Doors/HouseDoors.cs +++ b/Projects/UOContent/Items/Construction/Doors/HouseDoors.cs @@ -1,254 +1,272 @@ -using System; -using System.Collections.Generic; -using Server.ContextMenus; -using Server.Gumps; -using Server.Multis; - -namespace Server.Items -{ - public class MetalHouseDoor : BaseHouseDoor - { - [Constructible] - public MetalHouseDoor(DoorFacing facing) : base(facing, 0x675 + 2 * (int)facing, 0x676 + 2 * (int)facing, 0xEC, 0xF3, - GetOffset(facing)) - { - } - - public MetalHouseDoor(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) // Default Serialize method - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) // Default Deserialize method - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DarkWoodHouseDoor : BaseHouseDoor - { - [Constructible] - public DarkWoodHouseDoor(DoorFacing facing) : base(facing, 0x6A5 + 2 * (int)facing, 0x6A6 + 2 * (int)facing, 0xEA, - 0xF1, GetOffset(facing)) - { - } - - public DarkWoodHouseDoor(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) // Default Serialize method - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) // Default Deserialize method - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GenericHouseDoor : BaseHouseDoor - { - [Constructible] - public GenericHouseDoor(DoorFacing facing, int baseItemID, int openedSound, int closedSound, bool autoAdjust = true) - : base(facing, baseItemID + (autoAdjust ? 2 * (int)facing : 0), - baseItemID + 1 + (autoAdjust ? 2 * (int)facing : 0), openedSound, closedSound, GetOffset(facing)) - { - } - - public GenericHouseDoor(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) // Default Serialize method - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) // Default Deserialize method - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public abstract class BaseHouseDoor : BaseDoor, ISecurable - { - public BaseHouseDoor(DoorFacing facing, int closedID, int openedID, int openedSound, int closedSound, Point3D offset) - : base(closedID, openedID, openedSound, closedSound, offset) - { - Facing = facing; - Level = SecureLevel.Anyone; - } - - public BaseHouseDoor(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public DoorFacing Facing { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public SecureLevel Level { get; set; } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - SetSecureLevelEntry.AddTo(from, this, list); - } - - public BaseHouse FindHouse() - { - Point3D loc; - - if (Open) - loc = new Point3D(X - Offset.X, Y - Offset.Y, Z - Offset.Z); - else - loc = Location; - - return BaseHouse.FindHouseAt(loc, Map, 20); - } - - public bool CheckAccess(Mobile m) - { - BaseHouse house = FindHouse(); - - if (house == null) - return false; - - if (!house.IsAosRules) - return true; - - if (house.Public ? house.IsBanned(m) : !house.HasAccess(m)) - return false; - - return house.HasSecureAccess(m, Level); - } - - public override void OnOpened(Mobile from) - { - BaseHouse house = FindHouse(); - - if (house?.IsFriend(from) == true && from.AccessLevel == AccessLevel.Player && house.RefreshDecay()) - from.SendLocalizedMessage(1043293); // Your house's age and contents have been refreshed. - - if (house?.Public == true && !house.IsFriend(from)) - house.Visits++; - } - - public override bool UseLocks() => FindHouse()?.IsAosRules != true; - - public override void Use(Mobile from) - { - if (!CheckAccess(from)) - from.SendLocalizedMessage(1061637); // You are not allowed to access this. - else - base.Use(from); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write((int)Level); - - writer.Write((int)Facing); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - Level = (SecureLevel)reader.ReadInt(); - goto case 0; - } - case 0: - { - if (version < 1) - Level = SecureLevel.Anyone; - - Facing = (DoorFacing)reader.ReadInt(); - break; - } - } - } - - public override bool IsInside(Mobile from) - { - int x, y, w, h; - - const int r = 2; - const int bs = r * 2 + 1; - const int ss = r + 1; - - switch (Facing) - { - case DoorFacing.WestCW: - case DoorFacing.EastCCW: - x = -r; - y = -r; - w = bs; - h = ss; - break; - - case DoorFacing.EastCW: - case DoorFacing.WestCCW: - x = -r; - y = 0; - w = bs; - h = ss; - break; - - case DoorFacing.SouthCW: - case DoorFacing.NorthCCW: - x = -r; - y = -r; - w = ss; - h = bs; - break; - - case DoorFacing.NorthCW: - case DoorFacing.SouthCCW: - x = 0; - y = -r; - w = ss; - h = bs; - break; - - // No way to test the 'insideness' of SE Sliding doors on OSI, so leaving them default to false until further information gained - - default: return false; - } - - int rx = from.X - X; - int ry = from.Y - Y; - int az = Math.Abs(from.Z - Z); - - return rx >= x && rx < x + w && ry >= y && ry < y + h && az <= 4; - } - } -} +using System; +using System.Collections.Generic; +using Server.ContextMenus; +using Server.Gumps; +using Server.Multis; + +namespace Server.Items +{ + public class MetalHouseDoor : BaseHouseDoor + { + [Constructible] + public MetalHouseDoor(DoorFacing facing) : base( + facing, + 0x675 + 2 * (int)facing, + 0x676 + 2 * (int)facing, + 0xEC, + 0xF3, + GetOffset(facing) + ) + { + } + + public MetalHouseDoor(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) // Default Serialize method + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) // Default Deserialize method + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public class DarkWoodHouseDoor : BaseHouseDoor + { + [Constructible] + public DarkWoodHouseDoor(DoorFacing facing) : base( + facing, + 0x6A5 + 2 * (int)facing, + 0x6A6 + 2 * (int)facing, + 0xEA, + 0xF1, + GetOffset(facing) + ) + { + } + + public DarkWoodHouseDoor(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) // Default Serialize method + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) // Default Deserialize method + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public class GenericHouseDoor : BaseHouseDoor + { + [Constructible] + public GenericHouseDoor(DoorFacing facing, int baseItemID, int openedSound, int closedSound, bool autoAdjust = true) + : base( + facing, + baseItemID + (autoAdjust ? 2 * (int)facing : 0), + baseItemID + 1 + (autoAdjust ? 2 * (int)facing : 0), + openedSound, + closedSound, + GetOffset(facing) + ) + { + } + + public GenericHouseDoor(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) // Default Serialize method + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) // Default Deserialize method + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public abstract class BaseHouseDoor : BaseDoor, ISecurable + { + public BaseHouseDoor(DoorFacing facing, int closedID, int openedID, int openedSound, int closedSound, Point3D offset) + : base(closedID, openedID, openedSound, closedSound, offset) + { + Facing = facing; + Level = SecureLevel.Anyone; + } + + public BaseHouseDoor(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public DoorFacing Facing { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public SecureLevel Level { get; set; } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + SetSecureLevelEntry.AddTo(from, this, list); + } + + public BaseHouse FindHouse() + { + Point3D loc; + + if (Open) + loc = new Point3D(X - Offset.X, Y - Offset.Y, Z - Offset.Z); + else + loc = Location; + + return BaseHouse.FindHouseAt(loc, Map, 20); + } + + public bool CheckAccess(Mobile m) + { + var house = FindHouse(); + + if (house == null) + return false; + + if (!house.IsAosRules) + return true; + + if (house.Public ? house.IsBanned(m) : !house.HasAccess(m)) + return false; + + return house.HasSecureAccess(m, Level); + } + + public override void OnOpened(Mobile from) + { + var house = FindHouse(); + + if (house?.IsFriend(from) == true && from.AccessLevel == AccessLevel.Player && house.RefreshDecay()) + from.SendLocalizedMessage(1043293); // Your house's age and contents have been refreshed. + + if (house?.Public == true && !house.IsFriend(from)) + house.Visits++; + } + + public override bool UseLocks() => FindHouse()?.IsAosRules != true; + + public override void Use(Mobile from) + { + if (!CheckAccess(from)) + from.SendLocalizedMessage(1061637); // You are not allowed to access this. + else + base.Use(from); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write((int)Level); + + writer.Write((int)Facing); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + Level = (SecureLevel)reader.ReadInt(); + goto case 0; + } + case 0: + { + if (version < 1) + Level = SecureLevel.Anyone; + + Facing = (DoorFacing)reader.ReadInt(); + break; + } + } + } + + public override bool IsInside(Mobile from) + { + int x, y, w, h; + + const int r = 2; + const int bs = r * 2 + 1; + const int ss = r + 1; + + switch (Facing) + { + case DoorFacing.WestCW: + case DoorFacing.EastCCW: + x = -r; + y = -r; + w = bs; + h = ss; + break; + + case DoorFacing.EastCW: + case DoorFacing.WestCCW: + x = -r; + y = 0; + w = bs; + h = ss; + break; + + case DoorFacing.SouthCW: + case DoorFacing.NorthCCW: + x = -r; + y = -r; + w = ss; + h = bs; + break; + + case DoorFacing.NorthCW: + case DoorFacing.SouthCCW: + x = 0; + y = -r; + w = ss; + h = bs; + break; + + // No way to test the 'insideness' of SE Sliding doors on OSI, so leaving them default to false until further information gained + + default: return false; + } + + var rx = from.X - X; + var ry = from.Y - Y; + var az = Math.Abs(from.Z - Z); + + return rx >= x && rx < x + w && ry >= y && ry < y + h && az <= 4; + } + } +} diff --git a/Projects/UOContent/Items/Construction/Doors/Portcullis.cs b/Projects/UOContent/Items/Construction/Doors/Portcullis.cs index 4f145bb13..fc7bf3cdb 100644 --- a/Projects/UOContent/Items/Construction/Doors/Portcullis.cs +++ b/Projects/UOContent/Items/Construction/Doors/Portcullis.cs @@ -1,58 +1,58 @@ -namespace Server.Items -{ - public class PortcullisNS : BaseDoor - { - [Constructible] - public PortcullisNS() : base(0x6F5, 0x6F5, 0xF0, 0xEF, new Point3D(0, 0, 20)) - { - } - - public PortcullisNS(Serial serial) : base(serial) - { - } - - public override bool UseChainedFunctionality => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PortcullisEW : BaseDoor - { - [Constructible] - public PortcullisEW() : base(0x6F6, 0x6F6, 0xF0, 0xEF, new Point3D(0, 0, 20)) - { - } - - public PortcullisEW(Serial serial) : base(serial) - { - } - - public override bool UseChainedFunctionality => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PortcullisNS : BaseDoor + { + [Constructible] + public PortcullisNS() : base(0x6F5, 0x6F5, 0xF0, 0xEF, new Point3D(0, 0, 20)) + { + } + + public PortcullisNS(Serial serial) : base(serial) + { + } + + public override bool UseChainedFunctionality => true; + + 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 class PortcullisEW : BaseDoor + { + [Constructible] + public PortcullisEW() : base(0x6F6, 0x6F6, 0xF0, 0xEF, new Point3D(0, 0, 20)) + { + } + + public PortcullisEW(Serial serial) : base(serial) + { + } + + public override bool UseChainedFunctionality => true; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Doors/SecretDoors.cs b/Projects/UOContent/Items/Construction/Doors/SecretDoors.cs index c56500bf4..074b60d7c 100644 --- a/Projects/UOContent/Items/Construction/Doors/SecretDoors.cs +++ b/Projects/UOContent/Items/Construction/Doors/SecretDoors.cs @@ -1,164 +1,194 @@ -namespace Server.Items -{ - public class SecretStoneDoor1 : BaseDoor - { - [Constructible] - public SecretStoneDoor1(DoorFacing facing) : base(0xE8 + 2 * (int)facing, 0xE9 + 2 * (int)facing, 0xED, 0xF4, - GetOffset(facing)) - { - } - - public SecretStoneDoor1(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) // Default Serialize method - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) // Default Deserialize method - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SecretDungeonDoor : BaseDoor - { - [Constructible] - public SecretDungeonDoor(DoorFacing facing) : base(0x314 + 2 * (int)facing, 0x315 + 2 * (int)facing, 0xED, 0xF4, - GetOffset(facing)) - { - } - - public SecretDungeonDoor(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) // Default Serialize method - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) // Default Deserialize method - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SecretStoneDoor2 : BaseDoor - { - [Constructible] - public SecretStoneDoor2(DoorFacing facing) : base(0x324 + 2 * (int)facing, 0x325 + 2 * (int)facing, 0xED, 0xF4, - GetOffset(facing)) - { - } - - public SecretStoneDoor2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) // Default Serialize method - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) // Default Deserialize method - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SecretWoodenDoor : BaseDoor - { - [Constructible] - public SecretWoodenDoor(DoorFacing facing) : base(0x334 + 2 * (int)facing, 0x335 + 2 * (int)facing, 0xED, 0xF4, - GetOffset(facing)) - { - } - - public SecretWoodenDoor(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) // Default Serialize method - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) // Default Deserialize method - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SecretLightWoodDoor : BaseDoor - { - [Constructible] - public SecretLightWoodDoor(DoorFacing facing) : base(0x344 + 2 * (int)facing, 0x345 + 2 * (int)facing, 0xED, 0xF4, - GetOffset(facing)) - { - } - - public SecretLightWoodDoor(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) // Default Serialize method - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) // Default Deserialize method - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SecretStoneDoor3 : BaseDoor - { - [Constructible] - public SecretStoneDoor3(DoorFacing facing) : base(0x354 + 2 * (int)facing, 0x355 + 2 * (int)facing, 0xED, 0xF4, - GetOffset(facing)) - { - } - - public SecretStoneDoor3(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) // Default Serialize method - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) // Default Deserialize method - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SecretStoneDoor1 : BaseDoor + { + [Constructible] + public SecretStoneDoor1(DoorFacing facing) : base( + 0xE8 + 2 * (int)facing, + 0xE9 + 2 * (int)facing, + 0xED, + 0xF4, + GetOffset(facing) + ) + { + } + + public SecretStoneDoor1(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) // Default Serialize method + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) // Default Deserialize method + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public class SecretDungeonDoor : BaseDoor + { + [Constructible] + public SecretDungeonDoor(DoorFacing facing) : base( + 0x314 + 2 * (int)facing, + 0x315 + 2 * (int)facing, + 0xED, + 0xF4, + GetOffset(facing) + ) + { + } + + public SecretDungeonDoor(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) // Default Serialize method + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) // Default Deserialize method + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public class SecretStoneDoor2 : BaseDoor + { + [Constructible] + public SecretStoneDoor2(DoorFacing facing) : base( + 0x324 + 2 * (int)facing, + 0x325 + 2 * (int)facing, + 0xED, + 0xF4, + GetOffset(facing) + ) + { + } + + public SecretStoneDoor2(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) // Default Serialize method + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) // Default Deserialize method + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public class SecretWoodenDoor : BaseDoor + { + [Constructible] + public SecretWoodenDoor(DoorFacing facing) : base( + 0x334 + 2 * (int)facing, + 0x335 + 2 * (int)facing, + 0xED, + 0xF4, + GetOffset(facing) + ) + { + } + + public SecretWoodenDoor(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) // Default Serialize method + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) // Default Deserialize method + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public class SecretLightWoodDoor : BaseDoor + { + [Constructible] + public SecretLightWoodDoor(DoorFacing facing) : base( + 0x344 + 2 * (int)facing, + 0x345 + 2 * (int)facing, + 0xED, + 0xF4, + GetOffset(facing) + ) + { + } + + public SecretLightWoodDoor(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) // Default Serialize method + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) // Default Deserialize method + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public class SecretStoneDoor3 : BaseDoor + { + [Constructible] + public SecretStoneDoor3(DoorFacing facing) : base( + 0x354 + 2 * (int)facing, + 0x355 + 2 * (int)facing, + 0xED, + 0xF4, + GetOffset(facing) + ) + { + } + + public SecretStoneDoor3(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) // Default Serialize method + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) // Default Deserialize method + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Floors/Floors.cs b/Projects/UOContent/Items/Construction/Floors/Floors.cs index 1bf2dafc7..d5b1fa310 100644 --- a/Projects/UOContent/Items/Construction/Floors/Floors.cs +++ b/Projects/UOContent/Items/Construction/Floors/Floors.cs @@ -1,623 +1,623 @@ -namespace Server.Items -{ - public abstract class BaseFloor : Item - { - public BaseFloor(int itemID, int count) : base(Utility.Random(itemID, count)) => Movable = false; - - public BaseFloor(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class StonePaversLight : BaseFloor - { - [Constructible] - public StonePaversLight() : base(0x519, 4) - { - } - - public StonePaversLight(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class StonePaversMedium : BaseFloor - { - [Constructible] - public StonePaversMedium() : base(0x51D, 4) - { - } - - public StonePaversMedium(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class StonePaversDark : BaseFloor - { - [Constructible] - public StonePaversDark() : base(0x521, 4) - { - } - - public StonePaversDark(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GreyFlagstones : BaseFloor - { - [Constructible] - public GreyFlagstones() : base(0x4FC, 4) - { - } - - public GreyFlagstones(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SandFlagstones : BaseFloor - { - [Constructible] - public SandFlagstones() : base(0x500, 4) - { - } - - public SandFlagstones(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class MarbleFloor : BaseFloor - { - [Constructible] - public MarbleFloor() : base(0x50D, 2) - { - } - - public MarbleFloor(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GreenMarbleFloor : BaseFloor - { - [Constructible] - public GreenMarbleFloor() : base(0x50F, 2) - { - } - - public GreenMarbleFloor(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GreyMarbleFloor : BaseFloor - { - [Constructible] - public GreyMarbleFloor() : base(0x511, 4) - { - } - - public GreyMarbleFloor(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class CobblestonesFloor : BaseFloor - { - [Constructible] - public CobblestonesFloor() : base(0x515, 4) - { - } - - public CobblestonesFloor(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SandstoneFloorN : BaseFloor - { - [Constructible] - public SandstoneFloorN() : base(0x525, 4) - { - } - - public SandstoneFloorN(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SandstoneFloorW : BaseFloor - { - [Constructible] - public SandstoneFloorW() : base(0x529, 4) - { - } - - public SandstoneFloorW(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DarkSandstoneFloorN : BaseFloor - { - [Constructible] - public DarkSandstoneFloorN() : base(0x52F, 4) - { - } - - public DarkSandstoneFloorN(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DarkSandstoneFloorW : BaseFloor - { - [Constructible] - public DarkSandstoneFloorW() : base(0x533, 4) - { - } - - public DarkSandstoneFloorW(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BricksFloor1 : BaseFloor - { - [Constructible] - public BricksFloor1() : base(0x4E2, 8) - { - } - - public BricksFloor1(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BricksFloor2 : BaseFloor - { - [Constructible] - public BricksFloor2() : base(0x537, 4) - { - } - - public BricksFloor2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class CaveFloorCenter : BaseFloor - { - [Constructible] - public CaveFloorCenter() : base(0x53B, 4) - { - } - - public CaveFloorCenter(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class CaveFloorSouth : BaseFloor - { - [Constructible] - public CaveFloorSouth() : base(0x541, 3) - { - } - - public CaveFloorSouth(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class CaveFloorEast : BaseFloor - { - [Constructible] - public CaveFloorEast() : base(0x544, 3) - { - } - - public CaveFloorEast(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class CaveFloorWest : BaseFloor - { - [Constructible] - public CaveFloorWest() : base(0x54A, 3) - { - } - - public CaveFloorWest(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class CaveFloorNorth : BaseFloor - { - [Constructible] - public CaveFloorNorth() : base(0x54D, 3) - { - } - - public CaveFloorNorth(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class MarblePavers : BaseFloor - { - [Constructible] - public MarblePavers() : base(0x495, 4) - { - } - - public MarblePavers(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BlueSlateFloorCenter : BaseFloor - { - [Constructible] - public BlueSlateFloorCenter() : base(0x49B, 1) - { - } - - public BlueSlateFloorCenter(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GreySlateFloor : BaseFloor - { - [Constructible] - public GreySlateFloor() : base(0x49C, 1) - { - } - - public GreySlateFloor(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public abstract class BaseFloor : Item + { + public BaseFloor(int itemID, int count) : base(Utility.Random(itemID, count)) => Movable = false; + + public BaseFloor(Serial serial) : base(serial) + { + } + + 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 class StonePaversLight : BaseFloor + { + [Constructible] + public StonePaversLight() : base(0x519, 4) + { + } + + public StonePaversLight(Serial serial) : base(serial) + { + } + + 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 class StonePaversMedium : BaseFloor + { + [Constructible] + public StonePaversMedium() : base(0x51D, 4) + { + } + + public StonePaversMedium(Serial serial) : base(serial) + { + } + + 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 class StonePaversDark : BaseFloor + { + [Constructible] + public StonePaversDark() : base(0x521, 4) + { + } + + public StonePaversDark(Serial serial) : base(serial) + { + } + + 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 class GreyFlagstones : BaseFloor + { + [Constructible] + public GreyFlagstones() : base(0x4FC, 4) + { + } + + public GreyFlagstones(Serial serial) : base(serial) + { + } + + 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 class SandFlagstones : BaseFloor + { + [Constructible] + public SandFlagstones() : base(0x500, 4) + { + } + + public SandFlagstones(Serial serial) : base(serial) + { + } + + 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 class MarbleFloor : BaseFloor + { + [Constructible] + public MarbleFloor() : base(0x50D, 2) + { + } + + public MarbleFloor(Serial serial) : base(serial) + { + } + + 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 class GreenMarbleFloor : BaseFloor + { + [Constructible] + public GreenMarbleFloor() : base(0x50F, 2) + { + } + + public GreenMarbleFloor(Serial serial) : base(serial) + { + } + + 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 class GreyMarbleFloor : BaseFloor + { + [Constructible] + public GreyMarbleFloor() : base(0x511, 4) + { + } + + public GreyMarbleFloor(Serial serial) : base(serial) + { + } + + 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 class CobblestonesFloor : BaseFloor + { + [Constructible] + public CobblestonesFloor() : base(0x515, 4) + { + } + + public CobblestonesFloor(Serial serial) : base(serial) + { + } + + 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 class SandstoneFloorN : BaseFloor + { + [Constructible] + public SandstoneFloorN() : base(0x525, 4) + { + } + + public SandstoneFloorN(Serial serial) : base(serial) + { + } + + 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 class SandstoneFloorW : BaseFloor + { + [Constructible] + public SandstoneFloorW() : base(0x529, 4) + { + } + + public SandstoneFloorW(Serial serial) : base(serial) + { + } + + 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 class DarkSandstoneFloorN : BaseFloor + { + [Constructible] + public DarkSandstoneFloorN() : base(0x52F, 4) + { + } + + public DarkSandstoneFloorN(Serial serial) : base(serial) + { + } + + 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 class DarkSandstoneFloorW : BaseFloor + { + [Constructible] + public DarkSandstoneFloorW() : base(0x533, 4) + { + } + + public DarkSandstoneFloorW(Serial serial) : base(serial) + { + } + + 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 class BricksFloor1 : BaseFloor + { + [Constructible] + public BricksFloor1() : base(0x4E2, 8) + { + } + + public BricksFloor1(Serial serial) : base(serial) + { + } + + 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 class BricksFloor2 : BaseFloor + { + [Constructible] + public BricksFloor2() : base(0x537, 4) + { + } + + public BricksFloor2(Serial serial) : base(serial) + { + } + + 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 class CaveFloorCenter : BaseFloor + { + [Constructible] + public CaveFloorCenter() : base(0x53B, 4) + { + } + + public CaveFloorCenter(Serial serial) : base(serial) + { + } + + 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 class CaveFloorSouth : BaseFloor + { + [Constructible] + public CaveFloorSouth() : base(0x541, 3) + { + } + + public CaveFloorSouth(Serial serial) : base(serial) + { + } + + 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 class CaveFloorEast : BaseFloor + { + [Constructible] + public CaveFloorEast() : base(0x544, 3) + { + } + + public CaveFloorEast(Serial serial) : base(serial) + { + } + + 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 class CaveFloorWest : BaseFloor + { + [Constructible] + public CaveFloorWest() : base(0x54A, 3) + { + } + + public CaveFloorWest(Serial serial) : base(serial) + { + } + + 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 class CaveFloorNorth : BaseFloor + { + [Constructible] + public CaveFloorNorth() : base(0x54D, 3) + { + } + + public CaveFloorNorth(Serial serial) : base(serial) + { + } + + 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 class MarblePavers : BaseFloor + { + [Constructible] + public MarblePavers() : base(0x495, 4) + { + } + + public MarblePavers(Serial serial) : base(serial) + { + } + + 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 class BlueSlateFloorCenter : BaseFloor + { + [Constructible] + public BlueSlateFloorCenter() : base(0x49B, 1) + { + } + + public BlueSlateFloorCenter(Serial serial) : base(serial) + { + } + + 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 class GreySlateFloor : BaseFloor + { + [Constructible] + public GreySlateFloor() : base(0x49C, 1) + { + } + + public GreySlateFloor(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Misc/BarrelParts.cs b/Projects/UOContent/Items/Construction/Misc/BarrelParts.cs index cc04139dc..fb9e7b879 100644 --- a/Projects/UOContent/Items/Construction/Misc/BarrelParts.cs +++ b/Projects/UOContent/Items/Construction/Misc/BarrelParts.cs @@ -1,101 +1,101 @@ -namespace Server.Items -{ - public class BarrelLid : Item - { - [Constructible] - public BarrelLid() : base(0x1DB8) => Weight = 2; - - public BarrelLid(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1EB1, 0x1EB2, 0x1EB3, 0x1EB4)] - public class BarrelStaves : Item - { - [Constructible] - public BarrelStaves() : base(0x1EB1) => Weight = 1; - - public BarrelStaves(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BarrelHoops : Item - { - [Constructible] - public BarrelHoops() : base(0x1DB7) => Weight = 5; - - public BarrelHoops(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1011228; // Barrel hoops - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BarrelTap : Item - { - [Constructible] - public BarrelTap() : base(0x1004) => Weight = 1; - - public BarrelTap(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class BarrelLid : Item + { + [Constructible] + public BarrelLid() : base(0x1DB8) => Weight = 2; + + public BarrelLid(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1EB1, 0x1EB2, 0x1EB3, 0x1EB4)] + public class BarrelStaves : Item + { + [Constructible] + public BarrelStaves() : base(0x1EB1) => Weight = 1; + + public BarrelStaves(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class BarrelHoops : Item + { + [Constructible] + public BarrelHoops() : base(0x1DB7) => Weight = 5; + + public BarrelHoops(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1011228; // Barrel hoops + + 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(); + } + } + + public class BarrelTap : Item + { + [Constructible] + public BarrelTap() : base(0x1004) => Weight = 1; + + public BarrelTap(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Misc/Easel.cs b/Projects/UOContent/Items/Construction/Misc/Easel.cs index 967d36b66..452c37347 100644 --- a/Projects/UOContent/Items/Construction/Misc/Easel.cs +++ b/Projects/UOContent/Items/Construction/Misc/Easel.cs @@ -1,31 +1,31 @@ -namespace Server.Items -{ - [Furniture] - [Flippable(0xF65, 0xF67, 0xF69)] - public class Easel : Item - { - [Constructible] - public Easel() : base(0xF65) => Weight = 25.0; - - public Easel(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 10.0) - Weight = 25.0; - } - } -} +namespace Server.Items +{ + [Furniture] + [Flippable(0xF65, 0xF67, 0xF69)] + public class Easel : Item + { + [Constructible] + public Easel() : base(0xF65) => Weight = 25.0; + + public Easel(Serial serial) : base(serial) + { + } + + 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 (Weight == 10.0) + Weight = 25.0; + } + } +} diff --git a/Projects/UOContent/Items/Construction/Misc/MeltedWax.cs b/Projects/UOContent/Items/Construction/Misc/MeltedWax.cs index 05bd933e5..467998137 100644 --- a/Projects/UOContent/Items/Construction/Misc/MeltedWax.cs +++ b/Projects/UOContent/Items/Construction/Misc/MeltedWax.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class MeltedWax : Item - { - [Constructible] - public MeltedWax() : base(0x122A) - { - Movable = false; - Hue = 0x835; - } - - public MeltedWax(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1016492; // melted wax - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class MeltedWax : Item + { + [Constructible] + public MeltedWax() : base(0x122A) + { + Movable = false; + Hue = 0x835; + } + + public MeltedWax(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1016492; // melted wax + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Misc/MusicStand.cs b/Projects/UOContent/Items/Construction/Misc/MusicStand.cs index 2f2e7b7f8..48f6e86ce 100644 --- a/Projects/UOContent/Items/Construction/Misc/MusicStand.cs +++ b/Projects/UOContent/Items/Construction/Misc/MusicStand.cs @@ -1,60 +1,60 @@ -namespace Server.Items -{ - [Furniture] - [Flippable(0xEBB, 0xEBC)] - public class TallMusicStand : Item - { - [Constructible] - public TallMusicStand() : base(0xEBB) => Weight = 10.0; - - public TallMusicStand(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 8.0) - Weight = 10.0; - } - } - - [Furniture] - [Flippable(0xEB6, 0xEB8)] - public class ShortMusicStand : Item - { - [Constructible] - public ShortMusicStand() : base(0xEB6) => Weight = 10.0; - - public ShortMusicStand(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 6.0) - Weight = 10.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Furniture] + [Flippable(0xEBB, 0xEBC)] + public class TallMusicStand : Item + { + [Constructible] + public TallMusicStand() : base(0xEBB) => Weight = 10.0; + + public TallMusicStand(Serial serial) : base(serial) + { + } + + 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 (Weight == 8.0) + Weight = 10.0; + } + } + + [Furniture] + [Flippable(0xEB6, 0xEB8)] + public class ShortMusicStand : Item + { + [Constructible] + public ShortMusicStand() : base(0xEB6) => Weight = 10.0; + + public ShortMusicStand(Serial serial) : base(serial) + { + } + + 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 (Weight == 6.0) + Weight = 10.0; + } + } +} diff --git a/Projects/UOContent/Items/Construction/Misc/Obelisk.cs b/Projects/UOContent/Items/Construction/Misc/Obelisk.cs index 4d90fa450..a6aec17fb 100644 --- a/Projects/UOContent/Items/Construction/Misc/Obelisk.cs +++ b/Projects/UOContent/Items/Construction/Misc/Obelisk.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class Obelisk : Item - { - [Constructible] - public Obelisk() : base(0x1184) => Movable = false; - - public Obelisk(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1016474; // an obelisk - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Obelisk : Item + { + [Constructible] + public Obelisk() : base(0x1184) => Movable = false; + + public Obelisk(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1016474; // an obelisk + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Misc/Screens.cs b/Projects/UOContent/Items/Construction/Misc/Screens.cs index 6a6f69159..3f6f0a506 100644 --- a/Projects/UOContent/Items/Construction/Misc/Screens.cs +++ b/Projects/UOContent/Items/Construction/Misc/Screens.cs @@ -1,54 +1,54 @@ -namespace Server.Items -{ - [Furniture] - [Flippable(0x24D0, 0x24D1, 0x24D2, 0x24D3, 0x24D4)] - public class BambooScreen : Item - { - [Constructible] - public BambooScreen() : base(0x24D0) => Weight = 20.0; - - public BambooScreen(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Furniture] - [Flippable(0x24CB, 0x24CC, 0x24CD, 0x24CE, 0x24CF)] - public class ShojiScreen : Item - { - [Constructible] - public ShojiScreen() : base(0x24CB) => Weight = 20.0; - - public ShojiScreen(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Furniture] + [Flippable(0x24D0, 0x24D1, 0x24D2, 0x24D3, 0x24D4)] + public class BambooScreen : Item + { + [Constructible] + public BambooScreen() : base(0x24D0) => Weight = 20.0; + + public BambooScreen(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Furniture] + [Flippable(0x24CB, 0x24CC, 0x24CD, 0x24CE, 0x24CF)] + public class ShojiScreen : Item + { + [Constructible] + public ShojiScreen() : base(0x24CB) => Weight = 20.0; + + public ShojiScreen(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Misc/Statues.cs b/Projects/UOContent/Items/Construction/Misc/Statues.cs index e51d01ece..4565140b0 100644 --- a/Projects/UOContent/Items/Construction/Misc/Statues.cs +++ b/Projects/UOContent/Items/Construction/Misc/Statues.cs @@ -1,312 +1,312 @@ -namespace Server.Items -{ - public class StatueSouth : Item - { - [Constructible] - public StatueSouth() : base(0x139A) => Weight = 10; - - public StatueSouth(Serial serial) : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class StatueSouth2 : Item - { - [Constructible] - public StatueSouth2() : base(0x1227) => Weight = 10; - - public StatueSouth2(Serial serial) : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class StatueNorth : Item - { - [Constructible] - public StatueNorth() : base(0x139B) => Weight = 10; - - public StatueNorth(Serial serial) : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class StatueWest : Item - { - [Constructible] - public StatueWest() : base(0x1226) => Weight = 10; - - public StatueWest(Serial serial) : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class StatueEast : Item - { - [Constructible] - public StatueEast() : base(0x139C) => Weight = 10; - - public StatueEast(Serial serial) : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class StatueEast2 : Item - { - [Constructible] - public StatueEast2() : base(0x1224) => Weight = 10; - - public StatueEast2(Serial serial) : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class StatueSouthEast : Item - { - [Constructible] - public StatueSouthEast() : base(0x1225) => Weight = 10; - - public StatueSouthEast(Serial serial) : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BustSouth : Item - { - [Constructible] - public BustSouth() : base(0x12CB) => Weight = 10; - - public BustSouth(Serial serial) : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BustEast : Item - { - [Constructible] - public BustEast() : base(0x12CA) => Weight = 10; - - public BustEast(Serial serial) : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class StatuePegasus : Item - { - [Constructible] - public StatuePegasus() : base(0x139D) => Weight = 10; - - public StatuePegasus(Serial serial) : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class StatuePegasus2 : Item - { - [Constructible] - public StatuePegasus2() : base(0x1228) => Weight = 10; - - public StatuePegasus2(Serial serial) : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SmallTowerSculpture : Item - { - [Constructible] - public SmallTowerSculpture() : base(0x241A) => Weight = 20.0; - - public SmallTowerSculpture(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class StatueSouth : Item + { + [Constructible] + public StatueSouth() : base(0x139A) => Weight = 10; + + public StatueSouth(Serial serial) : base(serial) + { + } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + 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(); + } + } + + public class StatueSouth2 : Item + { + [Constructible] + public StatueSouth2() : base(0x1227) => Weight = 10; + + public StatueSouth2(Serial serial) : base(serial) + { + } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + 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(); + } + } + + public class StatueNorth : Item + { + [Constructible] + public StatueNorth() : base(0x139B) => Weight = 10; + + public StatueNorth(Serial serial) : base(serial) + { + } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + 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(); + } + } + + public class StatueWest : Item + { + [Constructible] + public StatueWest() : base(0x1226) => Weight = 10; + + public StatueWest(Serial serial) : base(serial) + { + } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + 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(); + } + } + + public class StatueEast : Item + { + [Constructible] + public StatueEast() : base(0x139C) => Weight = 10; + + public StatueEast(Serial serial) : base(serial) + { + } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + 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(); + } + } + + public class StatueEast2 : Item + { + [Constructible] + public StatueEast2() : base(0x1224) => Weight = 10; + + public StatueEast2(Serial serial) : base(serial) + { + } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + 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(); + } + } + + public class StatueSouthEast : Item + { + [Constructible] + public StatueSouthEast() : base(0x1225) => Weight = 10; + + public StatueSouthEast(Serial serial) : base(serial) + { + } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + 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(); + } + } + + public class BustSouth : Item + { + [Constructible] + public BustSouth() : base(0x12CB) => Weight = 10; + + public BustSouth(Serial serial) : base(serial) + { + } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + 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(); + } + } + + public class BustEast : Item + { + [Constructible] + public BustEast() : base(0x12CA) => Weight = 10; + + public BustEast(Serial serial) : base(serial) + { + } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + 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(); + } + } + + public class StatuePegasus : Item + { + [Constructible] + public StatuePegasus() : base(0x139D) => Weight = 10; + + public StatuePegasus(Serial serial) : base(serial) + { + } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + 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(); + } + } + + public class StatuePegasus2 : Item + { + [Constructible] + public StatuePegasus2() : base(0x1228) => Weight = 10; + + public StatuePegasus2(Serial serial) : base(serial) + { + } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + 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(); + } + } + + public class SmallTowerSculpture : Item + { + [Constructible] + public SmallTowerSculpture() : base(0x241A) => Weight = 20.0; + + public SmallTowerSculpture(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Misc/Vase.cs b/Projects/UOContent/Items/Construction/Misc/Vase.cs index 8c78eb57b..c5863a3e2 100644 --- a/Projects/UOContent/Items/Construction/Misc/Vase.cs +++ b/Projects/UOContent/Items/Construction/Misc/Vase.cs @@ -1,74 +1,74 @@ -namespace Server.Items -{ - public class Vase : Item - { - [Constructible] - public Vase() : base(0xB46) => Weight = 10; - - public Vase(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LargeVase : Item - { - [Constructible] - public LargeVase() : base(0xB45) => Weight = 15; - - public LargeVase(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SmallUrn : Item - { - [Constructible] - public SmallUrn() : base(0x241C) => Weight = 20.0; - - public SmallUrn(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Vase : Item + { + [Constructible] + public Vase() : base(0xB46) => Weight = 10; + + public Vase(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class LargeVase : Item + { + [Constructible] + public LargeVase() : base(0xB45) => Weight = 15; + + public LargeVase(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class SmallUrn : Item + { + [Constructible] + public SmallUrn() : base(0x241C) => Weight = 20.0; + + public SmallUrn(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Misc/Vines.cs b/Projects/UOContent/Items/Construction/Misc/Vines.cs index a49881753..0233ea30b 100644 --- a/Projects/UOContent/Items/Construction/Misc/Vines.cs +++ b/Projects/UOContent/Items/Construction/Misc/Vines.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class Vines : Item - { - [Constructible] - public Vines() : this(Utility.Random(8)) - { - } - - [Constructible] - public Vines(int v) : base(0xCEB) - { - if (v < 0 || v > 7) - v = 0; - - ItemID += v; - Weight = 1.0; - } - - public Vines(Serial serial) : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Vines : Item + { + [Constructible] + public Vines() : this(Utility.Random(8)) + { + } + + [Constructible] + public Vines(int v) : base(0xCEB) + { + if (v < 0 || v > 7) + v = 0; + + ItemID += v; + Weight = 1.0; + } + + public Vines(Serial serial) : base(serial) + { + } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Ruined/RuinedItemSingle.cs b/Projects/UOContent/Items/Construction/Ruined/RuinedItemSingle.cs index 47c1ed68b..0c3f36ed3 100644 --- a/Projects/UOContent/Items/Construction/Ruined/RuinedItemSingle.cs +++ b/Projects/UOContent/Items/Construction/Ruined/RuinedItemSingle.cs @@ -1,274 +1,274 @@ -namespace Server.Items -{ - [Flippable(0xC10, 0xC11)] - public class RuinedFallenChairA : Item - { - [Constructible] - public RuinedFallenChairA() : base(0xC10) => Movable = false; - - public RuinedFallenChairA(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0xC13, 0xC12)] - public class RuinedArmoire : Item - { - [Constructible] - public RuinedArmoire() : base(0xC13) => Movable = false; - - public RuinedArmoire(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0xC14, 0xC15)] - public class RuinedBookcase : Item - { - [Constructible] - public RuinedBookcase() : base(0xC14) => Movable = false; - - public RuinedBookcase(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class RuinedBooks : Item - { - [Constructible] - public RuinedBooks() : base(0xC16) => Movable = false; - - public RuinedBooks(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0xC17, 0xC18)] - public class CoveredChair : Item - { - [Constructible] - public CoveredChair() : base(0xC17) => Movable = false; - - public CoveredChair(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0xC19, 0xC1A)] - public class RuinedFallenChairB : Item - { - [Constructible] - public RuinedFallenChairB() : base(0xC19) => Movable = false; - - public RuinedFallenChairB(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0xC1B, 0xC1C, 0xC1E, 0xC1D)] - public class RuinedChair : Item - { - [Constructible] - public RuinedChair() : base(0xC1B) => Movable = false; - - public RuinedChair(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class RuinedClock : Item - { - [Constructible] - public RuinedClock() : base(0xC1F) => Movable = false; - - public RuinedClock(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0xC24, 0xC25)] - public class RuinedDrawers : Item - { - [Constructible] - public RuinedDrawers() : base(0xC24) => Movable = false; - - public RuinedDrawers(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class RuinedPainting : Item - { - [Constructible] - public RuinedPainting() : base(0xC2C) => Movable = false; - - public RuinedPainting(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0xC2D, 0xC2F, 0xC2E, 0xC30)] - public class WoodDebris : Item - { - [Constructible] - public WoodDebris() : base(0xC2D) => Movable = false; - - public WoodDebris(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0xC10, 0xC11)] + public class RuinedFallenChairA : Item + { + [Constructible] + public RuinedFallenChairA() : base(0xC10) => Movable = false; + + public RuinedFallenChairA(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0xC13, 0xC12)] + public class RuinedArmoire : Item + { + [Constructible] + public RuinedArmoire() : base(0xC13) => Movable = false; + + public RuinedArmoire(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0xC14, 0xC15)] + public class RuinedBookcase : Item + { + [Constructible] + public RuinedBookcase() : base(0xC14) => Movable = false; + + public RuinedBookcase(Serial serial) : base(serial) + { + } + + 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 class RuinedBooks : Item + { + [Constructible] + public RuinedBooks() : base(0xC16) => Movable = false; + + public RuinedBooks(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0xC17, 0xC18)] + public class CoveredChair : Item + { + [Constructible] + public CoveredChair() : base(0xC17) => Movable = false; + + public CoveredChair(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0xC19, 0xC1A)] + public class RuinedFallenChairB : Item + { + [Constructible] + public RuinedFallenChairB() : base(0xC19) => Movable = false; + + public RuinedFallenChairB(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0xC1B, 0xC1C, 0xC1E, 0xC1D)] + public class RuinedChair : Item + { + [Constructible] + public RuinedChair() : base(0xC1B) => Movable = false; + + public RuinedChair(Serial serial) : base(serial) + { + } + + 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 class RuinedClock : Item + { + [Constructible] + public RuinedClock() : base(0xC1F) => Movable = false; + + public RuinedClock(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0xC24, 0xC25)] + public class RuinedDrawers : Item + { + [Constructible] + public RuinedDrawers() : base(0xC24) => Movable = false; + + public RuinedDrawers(Serial serial) : base(serial) + { + } + + 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 class RuinedPainting : Item + { + [Constructible] + public RuinedPainting() : base(0xC2C) => Movable = false; + + public RuinedPainting(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0xC2D, 0xC2F, 0xC2E, 0xC30)] + public class WoodDebris : Item + { + [Constructible] + public WoodDebris() : base(0xC2D) => Movable = false; + + public WoodDebris(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Signs/BaseSign.cs b/Projects/UOContent/Items/Construction/Signs/BaseSign.cs index edace5bdb..02a266183 100644 --- a/Projects/UOContent/Items/Construction/Signs/BaseSign.cs +++ b/Projects/UOContent/Items/Construction/Signs/BaseSign.cs @@ -1,25 +1,25 @@ -namespace Server.Items -{ - public abstract class BaseSign : Item - { - public BaseSign(int dispID) : base(dispID) => Movable = false; - - public BaseSign(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public abstract class BaseSign : Item + { + public BaseSign(int dispID) : base(dispID) => Movable = false; + + public BaseSign(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Signs/LocalizedSign.cs b/Projects/UOContent/Items/Construction/Signs/LocalizedSign.cs index a81a468a7..dfbd723de 100644 --- a/Projects/UOContent/Items/Construction/Signs/LocalizedSign.cs +++ b/Projects/UOContent/Items/Construction/Signs/LocalizedSign.cs @@ -1,55 +1,56 @@ -namespace Server.Items -{ - public class LocalizedSign : Sign - { - private int m_LabelNumber; - - [Constructible] - public LocalizedSign(SignType type, SignFacing facing, int labelNumber) : base(0xB95 + 2 * (int)type + (int)facing) => m_LabelNumber = labelNumber; - - [Constructible] - public LocalizedSign(int itemID, int labelNumber) : base(itemID) => m_LabelNumber = labelNumber; - - public LocalizedSign(Serial serial) : base(serial) - { - } - - public override int LabelNumber => m_LabelNumber; - - [CommandProperty(AccessLevel.GameMaster)] - public int Number - { - get => m_LabelNumber; - set - { - m_LabelNumber = value; - InvalidateProperties(); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(m_LabelNumber); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_LabelNumber = reader.ReadInt(); - break; - } - } - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LocalizedSign : Sign + { + private int m_LabelNumber; + + [Constructible] + public LocalizedSign(SignType type, SignFacing facing, int labelNumber) : + base(0xB95 + 2 * (int)type + (int)facing) => m_LabelNumber = labelNumber; + + [Constructible] + public LocalizedSign(int itemID, int labelNumber) : base(itemID) => m_LabelNumber = labelNumber; + + public LocalizedSign(Serial serial) : base(serial) + { + } + + public override int LabelNumber => m_LabelNumber; + + [CommandProperty(AccessLevel.GameMaster)] + public int Number + { + get => m_LabelNumber; + set + { + m_LabelNumber = value; + InvalidateProperties(); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + writer.Write(m_LabelNumber); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_LabelNumber = reader.ReadInt(); + break; + } + } + } + } +} diff --git a/Projects/UOContent/Items/Construction/Signs/Sign.cs b/Projects/UOContent/Items/Construction/Signs/Sign.cs index 8bf9c60ca..4916c33e4 100644 --- a/Projects/UOContent/Items/Construction/Signs/Sign.cs +++ b/Projects/UOContent/Items/Construction/Signs/Sign.cs @@ -1,104 +1,104 @@ -namespace Server.Items -{ - public enum SignFacing - { - North, - West - } - - public enum SignType - { - Library, - DarkWoodenPost, - LightWoodenPost, - MetalPostC, - MetalPostB, - MetalPostA, - MetalPost, - Bakery, - Tailor, - Tinker, - Butcher, - Healer, - Mage, - Woodworker, - Customs, - Inn, - Shipwright, - Stables, - BarberShop, - Bard, - Fletcher, - Armourer, - Jeweler, - Tavern, - ReagentShop, - Blacksmith, - Painter, - Provisioner, - Bowyer, - WoodenSign, - BrassSign, - ArmamentsGuild, - ArmourersGuild, - BlacksmithsGuild, - WeaponsGuild, - BardicGuild, - BartersGuild, - ProvisionersGuild, - TradersGuild, - CooksGuild, - HealersGuild, - MagesGuild, - SorcerersGuild, - IllusionistGuild, - MinersGuild, - ArchersGuild, - SeamensGuild, - FishermensGuild, - SailorsGuild, - ShipwrightsGuild, - TailorsGuild, - ThievesGuild, - RoguesGuild, - AssassinsGuild, - TinkersGuild, - WarriorsGuild, - CavalryGuild, - FightersGuild, - MerchantsGuild, - Bank, - Theatre - } - - public class Sign : BaseSign - { - [Constructible] - public Sign(SignType type, SignFacing facing) : base(0xB95 + 2 * (int)type + (int)facing) - { - } - - [Constructible] - public Sign(int itemID) : base(itemID) - { - } - - public Sign(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public enum SignFacing + { + North, + West + } + + public enum SignType + { + Library, + DarkWoodenPost, + LightWoodenPost, + MetalPostC, + MetalPostB, + MetalPostA, + MetalPost, + Bakery, + Tailor, + Tinker, + Butcher, + Healer, + Mage, + Woodworker, + Customs, + Inn, + Shipwright, + Stables, + BarberShop, + Bard, + Fletcher, + Armourer, + Jeweler, + Tavern, + ReagentShop, + Blacksmith, + Painter, + Provisioner, + Bowyer, + WoodenSign, + BrassSign, + ArmamentsGuild, + ArmourersGuild, + BlacksmithsGuild, + WeaponsGuild, + BardicGuild, + BartersGuild, + ProvisionersGuild, + TradersGuild, + CooksGuild, + HealersGuild, + MagesGuild, + SorcerersGuild, + IllusionistGuild, + MinersGuild, + ArchersGuild, + SeamensGuild, + FishermensGuild, + SailorsGuild, + ShipwrightsGuild, + TailorsGuild, + ThievesGuild, + RoguesGuild, + AssassinsGuild, + TinkersGuild, + WarriorsGuild, + CavalryGuild, + FightersGuild, + MerchantsGuild, + Bank, + Theatre + } + + public class Sign : BaseSign + { + [Constructible] + public Sign(SignType type, SignFacing facing) : base(0xB95 + 2 * (int)type + (int)facing) + { + } + + [Constructible] + public Sign(int itemID) : base(itemID) + { + } + + public Sign(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Signs/SubtextSign.cs b/Projects/UOContent/Items/Construction/Signs/SubtextSign.cs index 1dc78146e..1f2f7572b 100644 --- a/Projects/UOContent/Items/Construction/Signs/SubtextSign.cs +++ b/Projects/UOContent/Items/Construction/Signs/SubtextSign.cs @@ -1,67 +1,67 @@ -namespace Server.Items -{ - public class SubtextSign : Sign - { - private string m_Subtext; - - [Constructible] - public SubtextSign(SignType type, SignFacing facing, string subtext) - : base(type, facing) => - m_Subtext = subtext; - - [Constructible] - public SubtextSign(int itemID, string subtext) - : base(itemID) => - m_Subtext = subtext; - - public SubtextSign(Serial serial) - : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public string Subtext - { - get => m_Subtext; - set - { - m_Subtext = value; - InvalidateProperties(); - } - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - if (!string.IsNullOrEmpty(m_Subtext)) - LabelTo(from, m_Subtext); - } - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - if (!string.IsNullOrEmpty(m_Subtext)) - list.Add(m_Subtext); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(m_Subtext); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Subtext = reader.ReadString(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SubtextSign : Sign + { + private string m_Subtext; + + [Constructible] + public SubtextSign(SignType type, SignFacing facing, string subtext) + : base(type, facing) => + m_Subtext = subtext; + + [Constructible] + public SubtextSign(int itemID, string subtext) + : base(itemID) => + m_Subtext = subtext; + + public SubtextSign(Serial serial) + : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public string Subtext + { + get => m_Subtext; + set + { + m_Subtext = value; + InvalidateProperties(); + } + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + if (!string.IsNullOrEmpty(m_Subtext)) + LabelTo(from, m_Subtext); + } + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + if (!string.IsNullOrEmpty(m_Subtext)) + list.Add(m_Subtext); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + writer.Write(m_Subtext); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Subtext = reader.ReadString(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Tables/Tables.cs b/Projects/UOContent/Items/Construction/Tables/Tables.cs index 4b7d6d7db..afa113ce9 100644 --- a/Projects/UOContent/Items/Construction/Tables/Tables.cs +++ b/Projects/UOContent/Items/Construction/Tables/Tables.cs @@ -1,139 +1,139 @@ -namespace Server.Items -{ - [Furniture] - public class ElegantLowTable : Item - { - [Constructible] - public ElegantLowTable() : base(0x2819) => Weight = 1.0; - - public ElegantLowTable(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Furniture] - public class PlainLowTable : Item - { - [Constructible] - public PlainLowTable() : base(0x281A) => Weight = 1.0; - - public PlainLowTable(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Furniture] - [Flippable(0xB90, 0xB7D)] - public class LargeTable : Item - { - [Constructible] - public LargeTable() : base(0xB90) => Weight = 1.0; - - public LargeTable(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 4.0) - Weight = 1.0; - } - } - - [Furniture] - [Flippable(0xB35, 0xB34)] - public class Nightstand : Item - { - [Constructible] - public Nightstand() : base(0xB35) => Weight = 1.0; - - public Nightstand(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 4.0) - Weight = 1.0; - } - } - - [Furniture] - [Flippable(0xB8F, 0xB7C)] - public class YewWoodTable : Item - { - [Constructible] - public YewWoodTable() : base(0xB8F) => Weight = 1.0; - - public YewWoodTable(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 4.0) - Weight = 1.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Furniture] + public class ElegantLowTable : Item + { + [Constructible] + public ElegantLowTable() : base(0x2819) => Weight = 1.0; + + public ElegantLowTable(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Furniture] + public class PlainLowTable : Item + { + [Constructible] + public PlainLowTable() : base(0x281A) => Weight = 1.0; + + public PlainLowTable(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Furniture] + [Flippable(0xB90, 0xB7D)] + public class LargeTable : Item + { + [Constructible] + public LargeTable() : base(0xB90) => Weight = 1.0; + + public LargeTable(Serial serial) : base(serial) + { + } + + 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 (Weight == 4.0) + Weight = 1.0; + } + } + + [Furniture] + [Flippable(0xB35, 0xB34)] + public class Nightstand : Item + { + [Constructible] + public Nightstand() : base(0xB35) => Weight = 1.0; + + public Nightstand(Serial serial) : base(serial) + { + } + + 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 (Weight == 4.0) + Weight = 1.0; + } + } + + [Furniture] + [Flippable(0xB8F, 0xB7C)] + public class YewWoodTable : Item + { + [Constructible] + public YewWoodTable() : base(0xB8F) => Weight = 1.0; + + public YewWoodTable(Serial serial) : base(serial) + { + } + + 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 (Weight == 4.0) + Weight = 1.0; + } + } +} diff --git a/Projects/UOContent/Items/Construction/Tables/WritingTable.cs b/Projects/UOContent/Items/Construction/Tables/WritingTable.cs index 47097de1b..48064100c 100644 --- a/Projects/UOContent/Items/Construction/Tables/WritingTable.cs +++ b/Projects/UOContent/Items/Construction/Tables/WritingTable.cs @@ -1,31 +1,31 @@ -namespace Server.Items -{ - [Furniture] - [Flippable(0xB4A, 0xB49, 0xB4B, 0xB4C)] - public class WritingTable : Item - { - [Constructible] - public WritingTable() : base(0xB4A) => Weight = 1.0; - - public WritingTable(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 4.0) - Weight = 1.0; - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Furniture] + [Flippable(0xB4A, 0xB49, 0xB4B, 0xB4C)] + public class WritingTable : Item + { + [Constructible] + public WritingTable() : base(0xB4A) => Weight = 1.0; + + public WritingTable(Serial serial) : base(serial) + { + } + + 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 (Weight == 4.0) + Weight = 1.0; + } + } +} diff --git a/Projects/UOContent/Items/Construction/Walls/BaseWall.cs b/Projects/UOContent/Items/Construction/Walls/BaseWall.cs index b35c02041..d7ab25c27 100644 --- a/Projects/UOContent/Items/Construction/Walls/BaseWall.cs +++ b/Projects/UOContent/Items/Construction/Walls/BaseWall.cs @@ -1,25 +1,25 @@ -namespace Server.Items -{ - public abstract class BaseWall : Item - { - public BaseWall(int itemID) : base(itemID) => Movable = false; - - public BaseWall(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public abstract class BaseWall : Item + { + public BaseWall(int itemID) : base(itemID) => Movable = false; + + public BaseWall(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Walls/DarkWoodWall.cs b/Projects/UOContent/Items/Construction/Walls/DarkWoodWall.cs index a105b7c5a..282863781 100644 --- a/Projects/UOContent/Items/Construction/Walls/DarkWoodWall.cs +++ b/Projects/UOContent/Items/Construction/Walls/DarkWoodWall.cs @@ -1,52 +1,52 @@ -namespace Server.Items -{ - public enum DarkWoodWallTypes - { - Corner, - SouthWall, - EastWall, - CornerPost, - EastDoorFrame, - SouthDoorFrame, - WestDoorFrame, - NorthDoorFrame, - SouthWindow, - EastWindow, - CornerMedium, - EastWallMedium, - SouthWallMedium, - CornerPostMedium, - CornerShort, - EastWallShort, - SouthWallShort, - CornerPostShort, - SouthWallVShort, - EastWallVShort - } - - public class DarkWoodWall : BaseWall - { - [Constructible] - public DarkWoodWall(DarkWoodWallTypes type) : base(0x0006 + (int)type) - { - } - - public DarkWoodWall(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public enum DarkWoodWallTypes + { + Corner, + SouthWall, + EastWall, + CornerPost, + EastDoorFrame, + SouthDoorFrame, + WestDoorFrame, + NorthDoorFrame, + SouthWindow, + EastWindow, + CornerMedium, + EastWallMedium, + SouthWallMedium, + CornerPostMedium, + CornerShort, + EastWallShort, + SouthWallShort, + CornerPostShort, + SouthWallVShort, + EastWallVShort + } + + public class DarkWoodWall : BaseWall + { + [Constructible] + public DarkWoodWall(DarkWoodWallTypes type) : base(0x0006 + (int)type) + { + } + + public DarkWoodWall(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Walls/ThickGrayStoneWall.cs b/Projects/UOContent/Items/Construction/Walls/ThickGrayStoneWall.cs index 2b5c53e81..044af3bc8 100644 --- a/Projects/UOContent/Items/Construction/Walls/ThickGrayStoneWall.cs +++ b/Projects/UOContent/Items/Construction/Walls/ThickGrayStoneWall.cs @@ -1,62 +1,62 @@ -/**************************************** - * NAME : Thick Gray Stone Wall * - * SCRIPT : ThickGrayStoneWall.cs * - * VERSION : v1.00 * - * CREATOR : Mans Sjoberg (Allmight) * - * CREATED : 10-07.2002 * - * **************************************/ - -namespace Server.Items -{ - public enum ThickGrayStoneWallTypes - { - WestArch, - NorthArch, - SouthArchTop, - EastArchTop, - EastArch, - SouthArch, - Wall1, - Wall2, - Wall3, - SouthWindow, - Wall4, - EastWindow, - WestArch2, - NorthArch2, - SouthArchTop2, - EastArchTop2, - EastArch2, - SouthArch2, - SWArchEdge2, - SouthWindow2, - NEArchEdge2, - EastWindow2 - } - - public class ThickGrayStoneWall : BaseWall - { - [Constructible] - public ThickGrayStoneWall(ThickGrayStoneWallTypes type) : base(0x007A + (int)type) - { - } - - public ThickGrayStoneWall(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +/**************************************** + * NAME : Thick Gray Stone Wall * + * SCRIPT : ThickGrayStoneWall.cs * + * VERSION : v1.00 * + * CREATOR : Mans Sjoberg (Allmight) * + * CREATED : 10-07.2002 * + * **************************************/ + +namespace Server.Items +{ + public enum ThickGrayStoneWallTypes + { + WestArch, + NorthArch, + SouthArchTop, + EastArchTop, + EastArch, + SouthArch, + Wall1, + Wall2, + Wall3, + SouthWindow, + Wall4, + EastWindow, + WestArch2, + NorthArch2, + SouthArchTop2, + EastArchTop2, + EastArch2, + SouthArch2, + SWArchEdge2, + SouthWindow2, + NEArchEdge2, + EastWindow2 + } + + public class ThickGrayStoneWall : BaseWall + { + [Constructible] + public ThickGrayStoneWall(ThickGrayStoneWallTypes type) : base(0x007A + (int)type) + { + } + + public ThickGrayStoneWall(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Walls/ThinBrickWall.cs b/Projects/UOContent/Items/Construction/Walls/ThinBrickWall.cs index b114bae50..a7636cccf 100644 --- a/Projects/UOContent/Items/Construction/Walls/ThinBrickWall.cs +++ b/Projects/UOContent/Items/Construction/Walls/ThinBrickWall.cs @@ -1,68 +1,68 @@ -namespace Server.Items -{ - public enum ThinBrickWallTypes - { - Corner, - SouthWall, - EastWall, - CornerPost, - EastDoorFrame, - SouthDoorFrame, - WestDoorFrame, - NorthDoorFrame, - SouthWindow, - EastWindow, - CornerMedium, - SouthWallMedium, - EastWallMedium, - CornerPostMedium, - CornerShort, - SouthWallShort, - EastWallShort, - CornerPostShort, - CornerArch, - SouthArch, - WestArch, - EastArch, - NorthArch, - SouthCenterArchTall, - EastCenterArchTall, - EastCornerArchTall, - SouthCornerArchTall, - SouthCornerArch, - EastCornerArch, - SouthCenterArch, - EastCenterArch, - CornerVVShort, - SouthWallVVShort, - EastWallVVShort, - SouthWallVShort, - EastWallVShort - } - - public class ThinBrickWall : BaseWall - { - [Constructible] - public ThinBrickWall(ThinBrickWallTypes type) : base(0x0033 + (int)type) - { - } - - public ThinBrickWall(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public enum ThinBrickWallTypes + { + Corner, + SouthWall, + EastWall, + CornerPost, + EastDoorFrame, + SouthDoorFrame, + WestDoorFrame, + NorthDoorFrame, + SouthWindow, + EastWindow, + CornerMedium, + SouthWallMedium, + EastWallMedium, + CornerPostMedium, + CornerShort, + SouthWallShort, + EastWallShort, + CornerPostShort, + CornerArch, + SouthArch, + WestArch, + EastArch, + NorthArch, + SouthCenterArchTall, + EastCenterArchTall, + EastCornerArchTall, + SouthCornerArchTall, + SouthCornerArch, + EastCornerArch, + SouthCenterArch, + EastCenterArch, + CornerVVShort, + SouthWallVVShort, + EastWallVVShort, + SouthWallVShort, + EastWallVShort + } + + public class ThinBrickWall : BaseWall + { + [Constructible] + public ThinBrickWall(ThinBrickWallTypes type) : base(0x0033 + (int)type) + { + } + + public ThinBrickWall(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Walls/ThinStoneWall.cs b/Projects/UOContent/Items/Construction/Walls/ThinStoneWall.cs index e284af150..49794458c 100644 --- a/Projects/UOContent/Items/Construction/Walls/ThinStoneWall.cs +++ b/Projects/UOContent/Items/Construction/Walls/ThinStoneWall.cs @@ -1,57 +1,57 @@ -namespace Server.Items -{ - public enum ThinStoneWallTypes - { - Corner, - EastWall, - SouthWall, - CornerPost, - EastDoorFrame, - SouthDoorFrame, - NorthDoorFrame, - WestDoorFrame, - SouthWindow, - EastWindow, - CornerMedium, - SouthWallMedium, - EastWallMedium, - CornerPostMedium, - CornerArch, - EastArch, - SouthArch, - NorthArch, - WestArch, - CornerShort, - EastWallShort, - SouthWallShort, - CornerPostShort, - SouthWallShort2, - EastWallShort2 - } - - public class ThinStoneWall : BaseWall - { - [Constructible] - public ThinStoneWall(ThinStoneWallTypes type) : base(0x001A + (int)type) - { - } - - public ThinStoneWall(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public enum ThinStoneWallTypes + { + Corner, + EastWall, + SouthWall, + CornerPost, + EastDoorFrame, + SouthDoorFrame, + NorthDoorFrame, + WestDoorFrame, + SouthWindow, + EastWindow, + CornerMedium, + SouthWallMedium, + EastWallMedium, + CornerPostMedium, + CornerArch, + EastArch, + SouthArch, + NorthArch, + WestArch, + CornerShort, + EastWallShort, + SouthWallShort, + CornerPostShort, + SouthWallShort2, + EastWallShort2 + } + + public class ThinStoneWall : BaseWall + { + [Constructible] + public ThinStoneWall(ThinStoneWallTypes type) : base(0x001A + (int)type) + { + } + + public ThinStoneWall(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Construction/Walls/WhiteStoneWall.cs b/Projects/UOContent/Items/Construction/Walls/WhiteStoneWall.cs index e16b14cd6..093892d15 100644 --- a/Projects/UOContent/Items/Construction/Walls/WhiteStoneWall.cs +++ b/Projects/UOContent/Items/Construction/Walls/WhiteStoneWall.cs @@ -1,75 +1,75 @@ -/**************************************** - * NAME : White Stone Wall * - * SCRIPT : WhiteStoneWall.cs * - * VERSION : v1.00 * - * CREATOR : Mans Sjoberg (Allmight) * - * CREATED : 10-07.2002 * - * **************************************/ - -namespace Server.Items -{ - public enum WhiteStoneWallTypes - { - EastWall, - SouthWall, - SECorner, - NWCornerPost, - EastArrowLoop, - SouthArrowLoop, - EastWindow, - SouthWindow, - SouthWallMedium, - EastWallMedium, - SECornerMedium, - NWCornerPostMedium, - SouthWallShort, - EastWallShort, - SECornerShort, - NWCornerPostShort, - NECornerPostShort, - SWCornerPostShort, - SouthWallVShort, - EastWallVShort, - SECornerVShort, - NWCornerPostVShort, - SECornerArch, - SouthArch, - WestArch, - EastArch, - NorthArch, - EastBattlement, - SECornerBattlement, - SouthBattlement, - NECornerBattlement, - SWCornerBattlement, - Column, - SouthWallVVShort, - EastWallVVShort - } - - public class WhiteStoneWall : BaseWall - { - [Constructible] - public WhiteStoneWall(WhiteStoneWallTypes type) : base(0x0057 + (int)type) - { - } - - public WhiteStoneWall(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +/**************************************** + * NAME : White Stone Wall * + * SCRIPT : WhiteStoneWall.cs * + * VERSION : v1.00 * + * CREATOR : Mans Sjoberg (Allmight) * + * CREATED : 10-07.2002 * + * **************************************/ + +namespace Server.Items +{ + public enum WhiteStoneWallTypes + { + EastWall, + SouthWall, + SECorner, + NWCornerPost, + EastArrowLoop, + SouthArrowLoop, + EastWindow, + SouthWindow, + SouthWallMedium, + EastWallMedium, + SECornerMedium, + NWCornerPostMedium, + SouthWallShort, + EastWallShort, + SECornerShort, + NWCornerPostShort, + NECornerPostShort, + SWCornerPostShort, + SouthWallVShort, + EastWallVShort, + SECornerVShort, + NWCornerPostVShort, + SECornerArch, + SouthArch, + WestArch, + EastArch, + NorthArch, + EastBattlement, + SECornerBattlement, + SouthBattlement, + NECornerBattlement, + SWCornerBattlement, + Column, + SouthWallVVShort, + EastWallVVShort + } + + public class WhiteStoneWall : BaseWall + { + [Constructible] + public WhiteStoneWall(WhiteStoneWallTypes type) : base(0x0057 + (int)type) + { + } + + public WhiteStoneWall(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Containers/BaseTreasureChest.cs b/Projects/UOContent/Items/Containers/BaseTreasureChest.cs index 449347b2b..a3cc06630 100644 --- a/Projects/UOContent/Items/Containers/BaseTreasureChest.cs +++ b/Projects/UOContent/Items/Containers/BaseTreasureChest.cs @@ -1,196 +1,197 @@ -using System; - -namespace Server.Items -{ - public class BaseTreasureChest : LockableContainer - { - public enum TreasureLevel - { - Level1, - Level2, - Level3, - Level4, - Level5, - Level6 - } - - private TreasureResetTimer m_ResetTimer; - - public BaseTreasureChest(int itemID, TreasureLevel level = TreasureLevel.Level2) - : base(itemID) - { - Level = level; - Locked = true; - Movable = false; - - SetLockLevel(); - GenerateTreasure(); - } - - public BaseTreasureChest(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public TreasureLevel Level { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public short MaxSpawnTime { get; set; } = 60; - - [CommandProperty(AccessLevel.GameMaster)] - public short MinSpawnTime { get; set; } = 10; - - [CommandProperty(AccessLevel.GameMaster)] - public override bool Locked - { - get => base.Locked; - set - { - if (base.Locked != value) - { - base.Locked = value; - - if (!value) - StartResetTimer(); - } - } - } - - public override bool IsDecoContainer => false; - - public override string DefaultName - { - get - { - if (Locked) - return "a locked treasure chest"; - - return "a treasure chest"; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - writer.Write((byte)Level); - writer.Write(MinSpawnTime); - writer.Write(MaxSpawnTime); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Level = (TreasureLevel)reader.ReadByte(); - MinSpawnTime = reader.ReadShort(); - MaxSpawnTime = reader.ReadShort(); - - if (!Locked) - StartResetTimer(); - } - - protected virtual void SetLockLevel() - { - RequiredSkill = Level switch - { - TreasureLevel.Level1 => LockLevel = 5, - TreasureLevel.Level2 => LockLevel = 20, - TreasureLevel.Level3 => LockLevel = 50, - TreasureLevel.Level4 => LockLevel = 70, - TreasureLevel.Level5 => LockLevel = 90, - TreasureLevel.Level6 => LockLevel = 100, - _ => RequiredSkill - }; - } - - private void StartResetTimer() - { - if (m_ResetTimer == null) - m_ResetTimer = new TreasureResetTimer(this); - else - m_ResetTimer.Delay = TimeSpan.FromMinutes(Utility.Random(MinSpawnTime, MaxSpawnTime)); - - m_ResetTimer.Start(); - } - - protected virtual void GenerateTreasure() - { - int MinGold = 1; - int MaxGold = 2; - - switch (Level) - { - case TreasureLevel.Level1: - MinGold = 100; - MaxGold = 300; - break; - - case TreasureLevel.Level2: - MinGold = 300; - MaxGold = 600; - break; - - case TreasureLevel.Level3: - MinGold = 600; - MaxGold = 900; - break; - - case TreasureLevel.Level4: - MinGold = 900; - MaxGold = 1200; - break; - - case TreasureLevel.Level5: - MinGold = 1200; - MaxGold = 5000; - break; - - case TreasureLevel.Level6: - MinGold = 5000; - MaxGold = 9000; - break; - } - - DropItem(new Gold(MinGold, MaxGold)); - } - - public void ClearContents() - { - for (int i = Items.Count - 1; i >= 0; --i) - if (i < Items.Count) - Items[i].Delete(); - } - - public void Reset() - { - if (m_ResetTimer != null) - if (m_ResetTimer.Running) - m_ResetTimer.Stop(); - - Locked = true; - ClearContents(); - GenerateTreasure(); - } - - private class TreasureResetTimer : Timer - { - private readonly BaseTreasureChest m_Chest; - - public TreasureResetTimer(BaseTreasureChest chest) : base( - TimeSpan.FromMinutes(Utility.Random(chest.MinSpawnTime, chest.MaxSpawnTime))) - { - m_Chest = chest; - Priority = TimerPriority.OneMinute; - } - - protected override void OnTick() - { - m_Chest.Reset(); - } - } - } -} +using System; + +namespace Server.Items +{ + public class BaseTreasureChest : LockableContainer + { + public enum TreasureLevel + { + Level1, + Level2, + Level3, + Level4, + Level5, + Level6 + } + + private TreasureResetTimer m_ResetTimer; + + public BaseTreasureChest(int itemID, TreasureLevel level = TreasureLevel.Level2) + : base(itemID) + { + Level = level; + Locked = true; + Movable = false; + + SetLockLevel(); + GenerateTreasure(); + } + + public BaseTreasureChest(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public TreasureLevel Level { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public short MaxSpawnTime { get; set; } = 60; + + [CommandProperty(AccessLevel.GameMaster)] + public short MinSpawnTime { get; set; } = 10; + + [CommandProperty(AccessLevel.GameMaster)] + public override bool Locked + { + get => base.Locked; + set + { + if (base.Locked != value) + { + base.Locked = value; + + if (!value) + StartResetTimer(); + } + } + } + + public override bool IsDecoContainer => false; + + public override string DefaultName + { + get + { + if (Locked) + return "a locked treasure chest"; + + return "a treasure chest"; + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + writer.Write((byte)Level); + writer.Write(MinSpawnTime); + writer.Write(MaxSpawnTime); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + Level = (TreasureLevel)reader.ReadByte(); + MinSpawnTime = reader.ReadShort(); + MaxSpawnTime = reader.ReadShort(); + + if (!Locked) + StartResetTimer(); + } + + protected virtual void SetLockLevel() + { + RequiredSkill = Level switch + { + TreasureLevel.Level1 => LockLevel = 5, + TreasureLevel.Level2 => LockLevel = 20, + TreasureLevel.Level3 => LockLevel = 50, + TreasureLevel.Level4 => LockLevel = 70, + TreasureLevel.Level5 => LockLevel = 90, + TreasureLevel.Level6 => LockLevel = 100, + _ => RequiredSkill + }; + } + + private void StartResetTimer() + { + if (m_ResetTimer == null) + m_ResetTimer = new TreasureResetTimer(this); + else + m_ResetTimer.Delay = TimeSpan.FromMinutes(Utility.Random(MinSpawnTime, MaxSpawnTime)); + + m_ResetTimer.Start(); + } + + protected virtual void GenerateTreasure() + { + var MinGold = 1; + var MaxGold = 2; + + switch (Level) + { + case TreasureLevel.Level1: + MinGold = 100; + MaxGold = 300; + break; + + case TreasureLevel.Level2: + MinGold = 300; + MaxGold = 600; + break; + + case TreasureLevel.Level3: + MinGold = 600; + MaxGold = 900; + break; + + case TreasureLevel.Level4: + MinGold = 900; + MaxGold = 1200; + break; + + case TreasureLevel.Level5: + MinGold = 1200; + MaxGold = 5000; + break; + + case TreasureLevel.Level6: + MinGold = 5000; + MaxGold = 9000; + break; + } + + DropItem(new Gold(MinGold, MaxGold)); + } + + public void ClearContents() + { + for (var i = Items.Count - 1; i >= 0; --i) + if (i < Items.Count) + Items[i].Delete(); + } + + public void Reset() + { + if (m_ResetTimer != null) + if (m_ResetTimer.Running) + m_ResetTimer.Stop(); + + Locked = true; + ClearContents(); + GenerateTreasure(); + } + + private class TreasureResetTimer : Timer + { + private readonly BaseTreasureChest m_Chest; + + public TreasureResetTimer(BaseTreasureChest chest) : base( + TimeSpan.FromMinutes(Utility.Random(chest.MinSpawnTime, chest.MaxSpawnTime)) + ) + { + m_Chest = chest; + Priority = TimerPriority.OneMinute; + } + + protected override void OnTick() + { + m_Chest.Reset(); + } + } + } +} diff --git a/Projects/UOContent/Items/Containers/Container.cs b/Projects/UOContent/Items/Containers/Container.cs index 35ebbeade..0e33a3d3c 100644 --- a/Projects/UOContent/Items/Containers/Container.cs +++ b/Projects/UOContent/Items/Containers/Container.cs @@ -1,939 +1,940 @@ -using System.Collections.Generic; -using Server.ContextMenus; -using Server.Mobiles; -using Server.Multis; -using Server.Network; - -namespace Server.Items -{ - public abstract class BaseContainer : Container - { - public BaseContainer(int itemID) : base(itemID) - { - } - - public BaseContainer(Serial serial) : base(serial) - { - } - - public override int DefaultMaxWeight - { - get - { - if (IsSecure) - return 0; - - return base.DefaultMaxWeight; - } - } - - public override bool IsAccessibleTo(Mobile m) - { - if (!BaseHouse.CheckAccessible(m, this)) - return false; - - return base.IsAccessibleTo(m); - } - - public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight) - { - if (IsSecure && !BaseHouse.CheckHold(m, this, item, message, checkItems, plusItems, plusWeight)) - return false; - - return base.CheckHold(m, item, message, checkItems, plusItems, plusWeight); - } - - public override bool CheckItemUse(Mobile from, Item item) - { - if (IsDecoContainer && item is BaseBook) - return true; - - return base.CheckItemUse(from, item); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - SetSecureLevelEntry.AddTo(from, this, list); - } - - public override bool TryDropItem(Mobile from, Item dropped, bool sendFullMessage) - { - if (!CheckHold(from, dropped, sendFullMessage, true)) - return false; - - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (house?.HasLockedDownItem(this) == true) - { - if (dropped is VendorRentalContract || (dropped is Container container && - container.FindItemByType() != null)) - { - from.SendLocalizedMessage(1062492); // You cannot place a rental contract in a locked down container. - return false; - } - - if (!house.LockDown(from, dropped, false)) - return false; - } - - List list = Items; - - for (int i = 0; i < list.Count; ++i) - { - Item item = list[i]; - - if (!(item is Container) && item.StackWith(from, dropped, false)) - return true; - } - - DropItem(dropped); - - return true; - } - - public override bool OnDragDropInto(Mobile from, Item item, Point3D p) - { - if (!CheckHold(from, item, true, true)) - return false; - - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (house?.HasLockedDownItem(this) == true) - { - if (item is VendorRentalContract || (item is Container container && - container.FindItemByType() != null)) - { - from.SendLocalizedMessage(1062492); // You cannot place a rental contract in a locked down container. - return false; - } - - if (!house.LockDown(from, item, false)) - return false; - } - - item.Location = new Point3D(p.X, p.Y, 0); - AddItem(item); - - from.SendSound(GetDroppedSound(item), GetWorldLocation()); - - return true; - } - - public override void UpdateTotal(Item sender, TotalType type, int delta) - { - base.UpdateTotal(sender, type, delta); - - if (type == TotalType.Weight) - (RootParent as Mobile)?.InvalidateProperties(); - } - - public override void OnDoubleClick(Mobile from) - { - if (from.AccessLevel > AccessLevel.Player || from.InRange(GetWorldLocation(), 2) || RootParent is PlayerVendor) - Open(from); - else - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - - public virtual void Open(Mobile from) - { - DisplayTo(from); - } - - /* Note: base class insertion; we cannot serialize anything here */ - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - } - } - - public class CreatureBackpack : Backpack // Used on BaseCreature - { - [Constructible] - public CreatureBackpack(string name) - { - Name = name; - Layer = Layer.Backpack; - Hue = 5; - Weight = 3.0; - } - - public CreatureBackpack(Serial serial) : base(serial) - { - } - - public override void AddNameProperty(ObjectPropertyList list) - { - if (Name != null) - list.Add(1075257, Name); // Contents of ~1_PETNAME~'s pack. - else - base.AddNameProperty(list); - } - - public override void OnItemRemoved(Item item) - { - if (Items.Count == 0) - Delete(); - - base.OnItemRemoved(item); - } - - public override bool OnDragLift(Mobile from) - { - if (from.AccessLevel > AccessLevel.Player) - return true; - - from.SendLocalizedMessage(500169); // You cannot pick that up. - return false; - } - - public override bool OnDragDropInto(Mobile from, Item item, Point3D p) => false; - - public override bool TryDropItem(Mobile from, Item dropped, bool sendFullMessage) => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version == 0) - Weight = 13.0; - } - } - - public class StrongBackpack : Backpack // Used on Pack animals - { - [Constructible] - public StrongBackpack() - { - Layer = Layer.Backpack; - Weight = 13.0; - } - - public StrongBackpack(Serial serial) : base(serial) - { - } - - public override int DefaultMaxWeight => 1600; - - public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight) => base.CheckHold(m, item, false, checkItems, plusItems, plusWeight); - - public override bool CheckContentDisplay(Mobile from) => - (RootParent is BaseCreature creature && creature.Controlled && creature.ControlMaster == from) || - base.CheckContentDisplay(from); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version == 0) - Weight = 13.0; - } - } - - public class Backpack : BaseContainer, IDyable - { - [Constructible] - public Backpack() : base(0xE75) - { - Layer = Layer.Backpack; - Weight = 3.0; - } - - public Backpack(Serial serial) : base(serial) - { - } - - public override int DefaultMaxWeight - { - get - { - if (Core.ML && Parent is Mobile m && m.Player && m.Backpack == this) - return 550; - - return base.DefaultMaxWeight; - } - } - - public bool Dye(Mobile from, DyeTub sender) - { - if (Deleted) return false; - - Hue = sender.DyedHue; - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version == 0 && ItemID == 0x9B2) - ItemID = 0xE75; - } - } - - public class Pouch : TrappableContainer - { - [Constructible] - public Pouch() : base(0xE79) => Weight = 1.0; - - public Pouch(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public abstract class BaseBagBall : BaseContainer, IDyable - { - public BaseBagBall(int itemID) : base(itemID) => Weight = 1.0; - - public BaseBagBall(Serial serial) : base(serial) - { - } - - public bool Dye(Mobile from, DyeTub sender) - { - if (Deleted) - return false; - - Hue = sender.DyedHue; - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SmallBagBall : BaseBagBall - { - [Constructible] - public SmallBagBall() : base(0x2256) - { - } - - public SmallBagBall(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LargeBagBall : BaseBagBall - { - [Constructible] - public LargeBagBall() : base(0x2257) - { - } - - public LargeBagBall(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Bag : BaseContainer, IDyable - { - [Constructible] - public Bag() : base(0xE76) => Weight = 2.0; - - public Bag(Serial serial) : base(serial) - { - } - - public bool Dye(Mobile from, DyeTub sender) - { - if (Deleted) return false; - - Hue = sender.DyedHue; - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Barrel : BaseContainer - { - [Constructible] - public Barrel() : base(0xE77) => Weight = 25.0; - - public Barrel(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 0.0) - Weight = 25.0; - } - } - - public class Keg : BaseContainer - { - [Constructible] - public Keg() : base(0xE7F) => Weight = 15.0; - - public Keg(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PicnicBasket : BaseContainer - { - [Constructible] - public PicnicBasket() : base(0xE7A) => Weight = 2.0; - - public PicnicBasket(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Basket : BaseContainer - { - [Constructible] - public Basket() : base(0x990) => Weight = 1.0; - - public Basket(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Furniture] - [Flippable(0x9AA, 0xE7D)] - public class WoodenBox : LockableContainer - { - [Constructible] - public WoodenBox() : base(0x9AA) => Weight = 4.0; - - public WoodenBox(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Furniture] - [Flippable(0x9A9, 0xE7E)] - public class SmallCrate : LockableContainer - { - [Constructible] - public SmallCrate() : base(0x9A9) => Weight = 2.0; - - public SmallCrate(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 4.0) - Weight = 2.0; - } - } - - [Furniture] - [Flippable(0xE3F, 0xE3E)] - public class MediumCrate : LockableContainer - { - [Constructible] - public MediumCrate() : base(0xE3F) => Weight = 2.0; - - public MediumCrate(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 6.0) - Weight = 2.0; - } - } - - [Furniture] - [Flippable(0xE3D, 0xE3C)] - public class LargeCrate : LockableContainer - { - [Constructible] - public LargeCrate() : base(0xE3D) => Weight = 1.0; - - public LargeCrate(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 8.0) - Weight = 1.0; - } - } - - [DynamicFliping] - [Flippable(0x9A8, 0xE80)] - public class MetalBox : LockableContainer - { - [Constructible] - public MetalBox() : base(0x9A8) - { - } - - public MetalBox(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); - - int version = reader.ReadInt(); - - if (version == 0 && Weight == 3) - Weight = -1; - } - } - - [DynamicFliping] - [Flippable(0x9AB, 0xE7C)] - public class MetalChest : LockableContainer - { - [Constructible] - public MetalChest() : base(0x9AB) - { - } - - public MetalChest(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); - - int version = reader.ReadInt(); - - if (version == 0 && Weight == 25) - Weight = -1; - } - } - - [DynamicFliping] - [Flippable(0xE41, 0xE40)] - public class MetalGoldenChest : LockableContainer - { - [Constructible] - public MetalGoldenChest() : base(0xE41) - { - } - - public MetalGoldenChest(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); - - int version = reader.ReadInt(); - - if (version == 0 && Weight == 25) - Weight = -1; - } - } - - [Furniture] - [Flippable(0xe43, 0xe42)] - public class WoodenChest : LockableContainer - { - [Constructible] - public WoodenChest() : base(0xe43) => Weight = 2.0; - - public WoodenChest(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 15.0) - Weight = 2.0; - } - } - - [Furniture] - [Flippable(0x280B, 0x280C)] - public class PlainWoodenChest : LockableContainer - { - [Constructible] - public PlainWoodenChest() : base(0x280B) - { - } - - public PlainWoodenChest(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); - - int version = reader.ReadInt(); - - if (version == 0 && Weight == 15) - Weight = -1; - } - } - - [Furniture] - [Flippable(0x280D, 0x280E)] - public class OrnateWoodenChest : LockableContainer - { - [Constructible] - public OrnateWoodenChest() : base(0x280D) - { - } - - public OrnateWoodenChest(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); - - int version = reader.ReadInt(); - - if (version == 0 && Weight == 15) - Weight = -1; - } - } - - [Furniture] - [Flippable(0x280F, 0x2810)] - public class GildedWoodenChest : LockableContainer - { - [Constructible] - public GildedWoodenChest() : base(0x280F) - { - } - - public GildedWoodenChest(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); - - int version = reader.ReadInt(); - - if (version == 0 && Weight == 15) - Weight = -1; - } - } - - [Furniture] - [Flippable(0x2811, 0x2812)] - public class WoodenFootLocker : LockableContainer - { - [Constructible] - public WoodenFootLocker() : base(0x2811) => GumpID = 0x10B; - - public WoodenFootLocker(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(2); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version == 0 && Weight == 15) - Weight = -1; - - if (version < 2) - GumpID = 0x10B; - } - } - - [Furniture] - [Flippable(0x2813, 0x2814)] - public class FinishedWoodenChest : LockableContainer - { - [Constructible] - public FinishedWoodenChest() : base(0x2813) - { - } - - public FinishedWoodenChest(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); - - int version = reader.ReadInt(); - - if (version == 0 && Weight == 15) - Weight = -1; - } - } -} \ No newline at end of file +using System.Collections.Generic; +using Server.ContextMenus; +using Server.Mobiles; +using Server.Multis; +using Server.Network; + +namespace Server.Items +{ + public abstract class BaseContainer : Container + { + public BaseContainer(int itemID) : base(itemID) + { + } + + public BaseContainer(Serial serial) : base(serial) + { + } + + public override int DefaultMaxWeight + { + get + { + if (IsSecure) + return 0; + + return base.DefaultMaxWeight; + } + } + + public override bool IsAccessibleTo(Mobile m) + { + if (!BaseHouse.CheckAccessible(m, this)) + return false; + + return base.IsAccessibleTo(m); + } + + public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight) + { + if (IsSecure && !BaseHouse.CheckHold(m, this, item, message, checkItems, plusItems, plusWeight)) + return false; + + return base.CheckHold(m, item, message, checkItems, plusItems, plusWeight); + } + + public override bool CheckItemUse(Mobile from, Item item) + { + if (IsDecoContainer && item is BaseBook) + return true; + + return base.CheckItemUse(from, item); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + SetSecureLevelEntry.AddTo(from, this, list); + } + + public override bool TryDropItem(Mobile from, Item dropped, bool sendFullMessage) + { + if (!CheckHold(from, dropped, sendFullMessage, true)) + return false; + + var house = BaseHouse.FindHouseAt(this); + + if (house?.HasLockedDownItem(this) == true) + { + if (dropped is VendorRentalContract || dropped is Container container && + container.FindItemByType() != null) + { + from.SendLocalizedMessage(1062492); // You cannot place a rental contract in a locked down container. + return false; + } + + if (!house.LockDown(from, dropped, false)) + return false; + } + + var list = Items; + + for (var i = 0; i < list.Count; ++i) + { + var item = list[i]; + + if (!(item is Container) && item.StackWith(from, dropped, false)) + return true; + } + + DropItem(dropped); + + return true; + } + + public override bool OnDragDropInto(Mobile from, Item item, Point3D p) + { + if (!CheckHold(from, item, true, true)) + return false; + + var house = BaseHouse.FindHouseAt(this); + + if (house?.HasLockedDownItem(this) == true) + { + if (item is VendorRentalContract || item is Container container && + container.FindItemByType() != null) + { + from.SendLocalizedMessage(1062492); // You cannot place a rental contract in a locked down container. + return false; + } + + if (!house.LockDown(from, item, false)) + return false; + } + + item.Location = new Point3D(p.X, p.Y, 0); + AddItem(item); + + from.SendSound(GetDroppedSound(item), GetWorldLocation()); + + return true; + } + + public override void UpdateTotal(Item sender, TotalType type, int delta) + { + base.UpdateTotal(sender, type, delta); + + if (type == TotalType.Weight) + (RootParent as Mobile)?.InvalidateProperties(); + } + + public override void OnDoubleClick(Mobile from) + { + if (from.AccessLevel > AccessLevel.Player || from.InRange(GetWorldLocation(), 2) || RootParent is PlayerVendor) + Open(from); + else + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + + public virtual void Open(Mobile from) + { + DisplayTo(from); + } + + /* Note: base class insertion; we cannot serialize anything here */ + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + } + } + + public class CreatureBackpack : Backpack // Used on BaseCreature + { + [Constructible] + public CreatureBackpack(string name) + { + Name = name; + Layer = Layer.Backpack; + Hue = 5; + Weight = 3.0; + } + + public CreatureBackpack(Serial serial) : base(serial) + { + } + + public override void AddNameProperty(ObjectPropertyList list) + { + if (Name != null) + list.Add(1075257, Name); // Contents of ~1_PETNAME~'s pack. + else + base.AddNameProperty(list); + } + + public override void OnItemRemoved(Item item) + { + if (Items.Count == 0) + Delete(); + + base.OnItemRemoved(item); + } + + public override bool OnDragLift(Mobile from) + { + if (from.AccessLevel > AccessLevel.Player) + return true; + + from.SendLocalizedMessage(500169); // You cannot pick that up. + return false; + } + + public override bool OnDragDropInto(Mobile from, Item item, Point3D p) => false; + + public override bool TryDropItem(Mobile from, Item dropped, bool sendFullMessage) => false; + + 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 = 13.0; + } + } + + public class StrongBackpack : Backpack // Used on Pack animals + { + [Constructible] + public StrongBackpack() + { + Layer = Layer.Backpack; + Weight = 13.0; + } + + public StrongBackpack(Serial serial) : base(serial) + { + } + + public override int DefaultMaxWeight => 1600; + + public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight) => + base.CheckHold(m, item, false, checkItems, plusItems, plusWeight); + + public override bool CheckContentDisplay(Mobile from) => + RootParent is BaseCreature creature && creature.Controlled && creature.ControlMaster == @from || + base.CheckContentDisplay(from); + + 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 = 13.0; + } + } + + public class Backpack : BaseContainer, IDyable + { + [Constructible] + public Backpack() : base(0xE75) + { + Layer = Layer.Backpack; + Weight = 3.0; + } + + public Backpack(Serial serial) : base(serial) + { + } + + public override int DefaultMaxWeight + { + get + { + if (Core.ML && Parent is Mobile m && m.Player && m.Backpack == this) + return 550; + + return base.DefaultMaxWeight; + } + } + + public bool Dye(Mobile from, DyeTub sender) + { + if (Deleted) return false; + + Hue = sender.DyedHue; + + return true; + } + + 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 && ItemID == 0x9B2) + ItemID = 0xE75; + } + } + + public class Pouch : TrappableContainer + { + [Constructible] + public Pouch() : base(0xE79) => Weight = 1.0; + + public Pouch(Serial serial) : base(serial) + { + } + + 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 abstract class BaseBagBall : BaseContainer, IDyable + { + public BaseBagBall(int itemID) : base(itemID) => Weight = 1.0; + + public BaseBagBall(Serial serial) : base(serial) + { + } + + public bool Dye(Mobile from, DyeTub sender) + { + if (Deleted) + return false; + + Hue = sender.DyedHue; + + return true; + } + + 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 class SmallBagBall : BaseBagBall + { + [Constructible] + public SmallBagBall() : base(0x2256) + { + } + + public SmallBagBall(Serial serial) : base(serial) + { + } + + 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 class LargeBagBall : BaseBagBall + { + [Constructible] + public LargeBagBall() : base(0x2257) + { + } + + public LargeBagBall(Serial serial) : base(serial) + { + } + + 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 class Bag : BaseContainer, IDyable + { + [Constructible] + public Bag() : base(0xE76) => Weight = 2.0; + + public Bag(Serial serial) : base(serial) + { + } + + public bool Dye(Mobile from, DyeTub sender) + { + if (Deleted) return false; + + Hue = sender.DyedHue; + + return true; + } + + 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 class Barrel : BaseContainer + { + [Constructible] + public Barrel() : base(0xE77) => Weight = 25.0; + + public Barrel(Serial serial) : base(serial) + { + } + + 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 (Weight == 0.0) + Weight = 25.0; + } + } + + public class Keg : BaseContainer + { + [Constructible] + public Keg() : base(0xE7F) => Weight = 15.0; + + public Keg(Serial serial) : base(serial) + { + } + + 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 class PicnicBasket : BaseContainer + { + [Constructible] + public PicnicBasket() : base(0xE7A) => Weight = 2.0; + + public PicnicBasket(Serial serial) : base(serial) + { + } + + 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 class Basket : BaseContainer + { + [Constructible] + public Basket() : base(0x990) => Weight = 1.0; + + public Basket(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Furniture] + [Flippable(0x9AA, 0xE7D)] + public class WoodenBox : LockableContainer + { + [Constructible] + public WoodenBox() : base(0x9AA) => Weight = 4.0; + + public WoodenBox(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Furniture] + [Flippable(0x9A9, 0xE7E)] + public class SmallCrate : LockableContainer + { + [Constructible] + public SmallCrate() : base(0x9A9) => Weight = 2.0; + + public SmallCrate(Serial serial) : base(serial) + { + } + + 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 (Weight == 4.0) + Weight = 2.0; + } + } + + [Furniture] + [Flippable(0xE3F, 0xE3E)] + public class MediumCrate : LockableContainer + { + [Constructible] + public MediumCrate() : base(0xE3F) => Weight = 2.0; + + public MediumCrate(Serial serial) : base(serial) + { + } + + 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 (Weight == 6.0) + Weight = 2.0; + } + } + + [Furniture] + [Flippable(0xE3D, 0xE3C)] + public class LargeCrate : LockableContainer + { + [Constructible] + public LargeCrate() : base(0xE3D) => Weight = 1.0; + + public LargeCrate(Serial serial) : base(serial) + { + } + + 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 (Weight == 8.0) + Weight = 1.0; + } + } + + [DynamicFliping] + [Flippable(0x9A8, 0xE80)] + public class MetalBox : LockableContainer + { + [Constructible] + public MetalBox() : base(0x9A8) + { + } + + public MetalBox(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 == 3) + Weight = -1; + } + } + + [DynamicFliping] + [Flippable(0x9AB, 0xE7C)] + public class MetalChest : LockableContainer + { + [Constructible] + public MetalChest() : base(0x9AB) + { + } + + public MetalChest(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 == 25) + Weight = -1; + } + } + + [DynamicFliping] + [Flippable(0xE41, 0xE40)] + public class MetalGoldenChest : LockableContainer + { + [Constructible] + public MetalGoldenChest() : base(0xE41) + { + } + + public MetalGoldenChest(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 == 25) + Weight = -1; + } + } + + [Furniture] + [Flippable(0xe43, 0xe42)] + public class WoodenChest : LockableContainer + { + [Constructible] + public WoodenChest() : base(0xe43) => Weight = 2.0; + + public WoodenChest(Serial serial) : base(serial) + { + } + + 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 (Weight == 15.0) + Weight = 2.0; + } + } + + [Furniture] + [Flippable(0x280B, 0x280C)] + public class PlainWoodenChest : LockableContainer + { + [Constructible] + public PlainWoodenChest() : base(0x280B) + { + } + + public PlainWoodenChest(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 == 15) + Weight = -1; + } + } + + [Furniture] + [Flippable(0x280D, 0x280E)] + public class OrnateWoodenChest : LockableContainer + { + [Constructible] + public OrnateWoodenChest() : base(0x280D) + { + } + + public OrnateWoodenChest(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 == 15) + Weight = -1; + } + } + + [Furniture] + [Flippable(0x280F, 0x2810)] + public class GildedWoodenChest : LockableContainer + { + [Constructible] + public GildedWoodenChest() : base(0x280F) + { + } + + public GildedWoodenChest(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 == 15) + Weight = -1; + } + } + + [Furniture] + [Flippable(0x2811, 0x2812)] + public class WoodenFootLocker : LockableContainer + { + [Constructible] + public WoodenFootLocker() : base(0x2811) => GumpID = 0x10B; + + public WoodenFootLocker(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(2); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version == 0 && Weight == 15) + Weight = -1; + + if (version < 2) + GumpID = 0x10B; + } + } + + [Furniture] + [Flippable(0x2813, 0x2814)] + public class FinishedWoodenChest : LockableContainer + { + [Constructible] + public FinishedWoodenChest() : base(0x2813) + { + } + + public FinishedWoodenChest(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 == 15) + Weight = -1; + } + } +} diff --git a/Projects/UOContent/Items/Containers/FillableContainers.cs b/Projects/UOContent/Items/Containers/FillableContainers.cs index 28b7c0ca9..26b48ae61 100644 --- a/Projects/UOContent/Items/Containers/FillableContainers.cs +++ b/Projects/UOContent/Items/Containers/FillableContainers.cs @@ -1,1525 +1,1565 @@ -using System; -using System.Collections.Generic; -using Server.Mobiles; - -namespace Server.Items -{ - public abstract class FillableContainer : LockableContainer - { - protected FillableContent m_Content; - - protected DateTime m_NextRespawnTime; - protected Timer m_RespawnTimer; - - public FillableContainer(int itemID) - : base(itemID) => - Movable = false; - - public FillableContainer(Serial serial) - : base(serial) - { - } - - public virtual int MinRespawnMinutes => 60; - public virtual int MaxRespawnMinutes => 90; - - public virtual bool IsLockable => true; - public virtual bool IsTrappable => IsLockable; - - public virtual int SpawnThreshold => 2; - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime NextRespawnTime => m_NextRespawnTime; - - [CommandProperty(AccessLevel.GameMaster)] - public FillableContentType ContentType - { - get => FillableContent.Lookup(m_Content); - set => Content = FillableContent.Lookup(value); - } - - public FillableContent Content - { - get => m_Content; - set - { - if (m_Content == value) - return; - - m_Content = value; - - for (int i = Items.Count - 1; i >= 0; --i) - if (i < Items.Count) - Items[i].Delete(); - - Respawn(); - } - } - - public override void OnMapChange() - { - base.OnMapChange(); - AcquireContent(); - } - - public override void OnLocationChange(Point3D oldLocation) - { - base.OnLocationChange(oldLocation); - AcquireContent(); - } - - public virtual void AcquireContent() - { - if (m_Content != null) - return; - - m_Content = FillableContent.Acquire(GetWorldLocation(), Map); - - if (m_Content != null) - Respawn(); - } - - public override void OnItemRemoved(Item item) - { - CheckRespawn(); - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - if (m_RespawnTimer != null) - { - m_RespawnTimer.Stop(); - m_RespawnTimer = null; - } - } - - public int GetItemsCount() - { - int count = 0; - - foreach (Item item in Items) count += item.Amount; - - return count; - } - - public void CheckRespawn() - { - bool canSpawn = m_Content != null && !Deleted && GetItemsCount() <= SpawnThreshold && !Movable && - Parent == null && !IsLockedDown && !IsSecure; - - if (canSpawn) - { - if (m_RespawnTimer == null) - { - int mins = Utility.RandomMinMax(MinRespawnMinutes, MaxRespawnMinutes); - TimeSpan delay = TimeSpan.FromMinutes(mins); - - m_NextRespawnTime = DateTime.UtcNow + delay; - m_RespawnTimer = Timer.DelayCall(delay, Respawn); - } - } - else if (m_RespawnTimer != null) - { - m_RespawnTimer.Stop(); - m_RespawnTimer = null; - } - } - - public void Respawn() - { - if (m_RespawnTimer != null) - { - m_RespawnTimer.Stop(); - m_RespawnTimer = null; - } - - if (m_Content == null || Deleted) - return; - - GenerateContent(); - - if (IsLockable) - { - Locked = true; - - int difficulty = (m_Content.Level - 1) * 30; - - LockLevel = difficulty - 10; - MaxLockLevel = difficulty + 30; - RequiredSkill = difficulty; - } - - if (IsTrappable && (m_Content.Level > 1 || Utility.Random(5) < 4)) - { - if (m_Content.Level > Utility.Random(5)) - TrapType = TrapType.PoisonTrap; - else - TrapType = TrapType.ExplosionTrap; - - TrapPower = m_Content.Level * Utility.RandomMinMax(10, 30); - TrapLevel = m_Content.Level; - } - else - { - TrapType = TrapType.None; - TrapPower = 0; - TrapLevel = 0; - } - - CheckRespawn(); - } - - protected virtual int GetSpawnCount() - { - int itemsCount = GetItemsCount(); - - if (itemsCount > SpawnThreshold) - return 0; - - int maxSpawnCount = (1 + SpawnThreshold - itemsCount) * 2; - - return Utility.RandomMinMax(0, maxSpawnCount); - } - - public virtual void GenerateContent() - { - if (m_Content == null || Deleted) - return; - - int toSpawn = GetSpawnCount(); - - for (int i = 0; i < toSpawn; ++i) - { - Item item = m_Content.Construct(); - - if (item == null) - continue; - - List list = Items; - - for (int j = 0; j < list.Count; ++j) - { - Item subItem = list[j]; - - if (!(subItem is Container) && subItem.StackWith(null, item, false)) - break; - } - - if (!item.Deleted) - DropItem(item); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(1); // version - - writer.Write((int)ContentType); - - if (m_RespawnTimer != null) - { - writer.Write(true); - writer.WriteDeltaTime(m_NextRespawnTime); - } - else - { - writer.Write(false); - } - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 1: - { - m_Content = FillableContent.Lookup((FillableContentType)reader.ReadInt()); - goto case 0; - } - case 0: - { - if (reader.ReadBool()) - { - m_NextRespawnTime = reader.ReadDeltaTime(); - - TimeSpan delay = m_NextRespawnTime - DateTime.UtcNow; - m_RespawnTimer = Timer.DelayCall(delay > TimeSpan.Zero ? delay : TimeSpan.Zero, Respawn); - } - else - { - CheckRespawn(); - } - - break; - } - } - } - } - - [Flippable(0xA97, 0xA99, 0xA98, 0xA9A, 0xA9B, 0xA9C)] - public class LibraryBookcase : FillableContainer - { - [Constructible] - public LibraryBookcase() - : base(0xA97) => - Weight = 1.0; - - public LibraryBookcase(Serial serial) - : base(serial) - { - } - - public override bool IsLockable => false; - public override int SpawnThreshold => 5; - - protected override int GetSpawnCount() => 5 - GetItemsCount(); - - public override void AcquireContent() - { - if (m_Content != null) - return; - - m_Content = FillableContent.Library; - - if (m_Content != null) - Respawn(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - if (version == 0 && m_Content == null) - Timer.DelayCall(AcquireContent); - } - } - - [Flippable(0xE3D, 0xE3C)] - public class FillableLargeCrate : FillableContainer - { - [Constructible] - public FillableLargeCrate() - : base(0xE3D) => - Weight = 1.0; - - public FillableLargeCrate(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - [Flippable(0x9A9, 0xE7E)] - public class FillableSmallCrate : FillableContainer - { - [Constructible] - public FillableSmallCrate() - : base(0x9A9) => - Weight = 1.0; - - public FillableSmallCrate(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - [Flippable(0x9AA, 0xE7D)] - public class FillableWoodenBox : FillableContainer - { - [Constructible] - public FillableWoodenBox() - : base(0x9AA) => - Weight = 4.0; - - public FillableWoodenBox(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x9A8, 0xE80)] - public class FillableMetalBox : FillableContainer - { - [Constructible] - public FillableMetalBox() - : base(0x9A8) - { - } - - public FillableMetalBox(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - if (version == 0 && Weight == 3) - Weight = -1; - } - } - - public class FillableBarrel : FillableContainer - { - [Constructible] - public FillableBarrel() - : base(0xE77) - { - } - - public FillableBarrel(Serial serial) - : base(serial) - { - } - - public override bool IsLockable => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - if (version == 0 && Weight == 25) - Weight = -1; - } - } - - [Flippable(0x9AB, 0xE7C)] - public class FillableMetalChest : FillableContainer - { - [Constructible] - public FillableMetalChest() - : base(0x9AB) - { - } - - public FillableMetalChest(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); - - int version = reader.ReadInt(); - - if (version == 0 && Weight == 25) - Weight = -1; - } - } - - [Flippable(0xE41, 0xE40)] - public class FillableMetalGoldenChest : FillableContainer - { - [Constructible] - public FillableMetalGoldenChest() - : base(0xE41) - { - } - - public FillableMetalGoldenChest(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); - - int version = reader.ReadInt(); - - if (version == 0 && Weight == 25) - Weight = -1; - } - } - - [Flippable(0xE43, 0xE42)] - public class FillableWoodenChest : FillableContainer - { - [Constructible] - public FillableWoodenChest() - : base(0xE43) - { - } - - public FillableWoodenChest(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); - - int version = reader.ReadInt(); - - if (version == 0 && Weight == 2) - Weight = -1; - } - } - - public class FillableEntry - { - protected Type[] m_Types; - protected int m_Weight; - - public FillableEntry(Type type) - : this(1, new[] { type }) - { - } - - public FillableEntry(int weight, Type type) - : this(weight, new[] { type }) - { - } - - public FillableEntry(Type[] types) - : this(1, types) - { - } - - public FillableEntry(int weight, Type[] types) - { - m_Weight = weight; - m_Types = types; - } - - public FillableEntry(int weight, Type[] types, int offset, int count) - { - m_Weight = weight; - m_Types = new Type[count]; - - for (int i = 0; i < m_Types.Length; ++i) - m_Types[i] = types[offset + i]; - } - - public Type[] Types => m_Types; - public int Weight => m_Weight; - - public virtual Item Construct() - { - Item item = Loot.Construct(m_Types); - - if (item is Key key) - key.ItemID = Utility.RandomList((int)KeyType.Copper, (int)KeyType.Gold, (int)KeyType.Iron, (int)KeyType.Rusty); - else if (item is Arrow || item is Bolt) - item.Amount = Utility.RandomMinMax(2, 6); - else if (item is Bandage || item is Lockpick) - item.Amount = Utility.RandomMinMax(1, 3); - - return item; - } - } - - public class FillableBvrge : FillableEntry - { - public FillableBvrge(Type type, BeverageType content) - : this(1, type, content) - { - } - - public FillableBvrge(int weight, Type type, BeverageType content) - : base(weight, type) => - Content = content; - - public BeverageType Content { get; } - - public override Item Construct() - { - Item item; - - int index = Utility.Random(m_Types.Length); - - if (m_Types[index] == typeof(BeverageBottle)) - { - item = new BeverageBottle(Content); - } - else if (m_Types[index] == typeof(Jug)) - { - item = new Jug(Content); - } - else - { - item = base.Construct(); - - if (item is BaseBeverage bev) - { - bev.Content = Content; - bev.Quantity = bev.MaxQuantity; - } - } - - return item; - } - } - - public enum FillableContentType - { - None = -1, - Weaponsmith, - Provisioner, - Mage, - Alchemist, - Armorer, - ArtisanGuild, - Baker, - Bard, - Blacksmith, - Bowyer, - Butcher, - Carpenter, - Clothier, - Cobbler, - Docks, - Farm, - FighterGuild, - Guard, - Healer, - Herbalist, - Inn, - Jeweler, - Library, - Merchant, - Mill, - Mine, - Observatory, - Painter, - Ranger, - Stables, - Tanner, - Tavern, - ThiefGuild, - Tinker, - Veterinarian - } - - public class FillableContent - { - public static FillableContent Alchemist = new FillableContent( - 1, - new[] - { - typeof(Alchemist) - }, - new[] - { - new FillableEntry(typeof(NightSightPotion)), - new FillableEntry(typeof(LesserCurePotion)), - new FillableEntry(typeof(AgilityPotion)), - new FillableEntry(typeof(StrengthPotion)), - new FillableEntry(typeof(LesserPoisonPotion)), - new FillableEntry(typeof(RefreshPotion)), - new FillableEntry(typeof(LesserHealPotion)), - new FillableEntry(typeof(LesserExplosionPotion)), - new FillableEntry(typeof(MortarPestle)) - }); - - public static FillableContent Armorer = new FillableContent( - 2, - new[] - { - typeof(Armorer) - }, - new[] - { - new FillableEntry(2, typeof(ChainCoif)), - new FillableEntry(1, typeof(PlateGorget)), - new FillableEntry(1, typeof(BronzeShield)), - new FillableEntry(1, typeof(Buckler)), - new FillableEntry(2, typeof(MetalKiteShield)), - new FillableEntry(2, typeof(HeaterShield)), - new FillableEntry(1, typeof(WoodenShield)), - new FillableEntry(1, typeof(MetalShield)) - }); - - public static FillableContent ArtisanGuild = new FillableContent( - 1, - new Type[] - { - }, - new[] - { - new FillableEntry(1, typeof(PaintsAndBrush)), - new FillableEntry(1, typeof(SledgeHammer)), - new FillableEntry(2, typeof(SmithHammer)), - new FillableEntry(2, typeof(Tongs)), - new FillableEntry(4, typeof(Lockpick)), - new FillableEntry(4, typeof(TinkerTools)), - new FillableEntry(1, typeof(MalletAndChisel)), - new FillableEntry(1, typeof(StatueEast2)), - new FillableEntry(1, typeof(StatueSouth)), - new FillableEntry(1, typeof(StatueSouthEast)), - new FillableEntry(1, typeof(StatueWest)), - new FillableEntry(1, typeof(StatueNorth)), - new FillableEntry(1, typeof(StatueEast)), - new FillableEntry(1, typeof(BustEast)), - new FillableEntry(1, typeof(BustSouth)), - new FillableEntry(1, typeof(BearMask)), - new FillableEntry(1, typeof(DeerMask)), - new FillableEntry(4, typeof(OrcHelm)), - new FillableEntry(1, typeof(TribalMask)), - new FillableEntry(1, typeof(HornedTribalMask)) - }); - - public static FillableContent Baker = new FillableContent( - 1, - new[] - { - typeof(Baker) - }, - new[] - { - new FillableEntry(1, typeof(RollingPin)), - new FillableEntry(2, typeof(SackFlour)), - new FillableEntry(2, typeof(BreadLoaf)), - new FillableEntry(1, typeof(FrenchBread)) - }); - - public static FillableContent Bard = new FillableContent( - 1, - new[] - { - typeof(Bard), - typeof(BardGuildmaster) - }, - new[] - { - new FillableEntry(1, typeof(LapHarp)), - new FillableEntry(2, typeof(Lute)), - new FillableEntry(1, typeof(Drums)), - new FillableEntry(1, typeof(Tambourine)), - new FillableEntry(1, typeof(TambourineTassel)) - }); - - public static FillableContent Blacksmith = new FillableContent( - 2, - new[] - { - typeof(Blacksmith), - typeof(BlacksmithGuildmaster) - }, - new[] - { - new FillableEntry(8, typeof(SmithHammer)), - new FillableEntry(8, typeof(Tongs)), - new FillableEntry(8, typeof(SledgeHammer)), - // new FillableEntry( 8, typeof( IronOre ) ), TODO: Smaller ore - new FillableEntry(8, typeof(IronIngot)), - new FillableEntry(1, typeof(IronWire)), - new FillableEntry(1, typeof(SilverWire)), - new FillableEntry(1, typeof(GoldWire)), - new FillableEntry(1, typeof(CopperWire)), - new FillableEntry(1, typeof(HorseShoes)), - new FillableEntry(1, typeof(ForgedMetal)) - }); - - public static FillableContent Bowyer = new FillableContent( - 2, - new[] - { - typeof(Bowyer) - }, - new[] - { - new FillableEntry(2, typeof(Bow)), - new FillableEntry(2, typeof(Crossbow)), - new FillableEntry(1, typeof(Arrow)) - }); - - public static FillableContent Butcher = new FillableContent( - 1, - new[] - { - typeof(Butcher) - }, - new[] - { - new FillableEntry(2, typeof(Cleaver)), - new FillableEntry(2, typeof(SlabOfBacon)), - new FillableEntry(2, typeof(Bacon)), - new FillableEntry(1, typeof(RawFishSteak)), - new FillableEntry(1, typeof(FishSteak)), - new FillableEntry(2, typeof(CookedBird)), - new FillableEntry(2, typeof(RawBird)), - new FillableEntry(2, typeof(Ham)), - new FillableEntry(1, typeof(RawLambLeg)), - new FillableEntry(1, typeof(LambLeg)), - new FillableEntry(1, typeof(Ribs)), - new FillableEntry(1, typeof(RawRibs)), - new FillableEntry(2, typeof(Sausage)), - new FillableEntry(1, typeof(RawChickenLeg)), - new FillableEntry(1, typeof(ChickenLeg)) - }); - - public static FillableContent Carpenter = new FillableContent( - 1, - new[] - { - typeof(Carpenter), - typeof(Architect), - typeof(RealEstateBroker) - }, - new[] - { - new FillableEntry(1, typeof(ChiselsNorth)), - new FillableEntry(1, typeof(ChiselsWest)), - new FillableEntry(2, typeof(DovetailSaw)), - new FillableEntry(2, typeof(Hammer)), - new FillableEntry(2, typeof(MouldingPlane)), - new FillableEntry(2, typeof(Nails)), - new FillableEntry(2, typeof(JointingPlane)), - new FillableEntry(2, typeof(SmoothingPlane)), - new FillableEntry(2, typeof(Saw)), - new FillableEntry(2, typeof(DrawKnife)), - new FillableEntry(1, typeof(Log)), - new FillableEntry(1, typeof(Froe)), - new FillableEntry(1, typeof(Inshave)), - new FillableEntry(1, typeof(Scorp)) - }); - - public static FillableContent Clothier = new FillableContent( - 1, - new[] - { - typeof(Tailor), - typeof(Weaver), - typeof(TailorGuildmaster) - }, - new[] - { - new FillableEntry(1, typeof(Cotton)), - new FillableEntry(1, typeof(Wool)), - new FillableEntry(1, typeof(DarkYarn)), - new FillableEntry(1, typeof(LightYarn)), - new FillableEntry(1, typeof(LightYarnUnraveled)), - new FillableEntry(1, typeof(SpoolOfThread)), - // Four different types - // new FillableEntry( 1, typeof( FoldedCloth ) ), - // new FillableEntry( 1, typeof( FoldedCloth ) ), - // new FillableEntry( 1, typeof( FoldedCloth ) ), - // new FillableEntry( 1, typeof( FoldedCloth ) ), - new FillableEntry(1, typeof(Dyes)), - new FillableEntry(2, typeof(Leather)) - }); - - public static FillableContent Cobbler = new FillableContent( - 1, - new[] - { - typeof(Cobbler) - }, - new[] - { - new FillableEntry(1, typeof(Boots)), - new FillableEntry(2, typeof(Shoes)), - new FillableEntry(2, typeof(Sandals)), - new FillableEntry(1, typeof(ThighBoots)) - }); - - public static FillableContent Docks = new FillableContent( - 1, - new[] - { - typeof(Fisherman), - typeof(FisherGuildmaster) - }, - new[] - { - new FillableEntry(1, typeof(FishingPole)), - // Two different types - // new FillableEntry( 1, typeof( SmallFish ) ), - // new FillableEntry( 1, typeof( SmallFish ) ), - new FillableEntry(4, typeof(Fish)) - }); - - public static FillableContent Farm = new FillableContent( - 1, - new[] - { - typeof(Farmer), - typeof(Rancher) - }, - new[] - { - new FillableEntry(1, typeof(Shirt)), - new FillableEntry(1, typeof(ShortPants)), - new FillableEntry(1, typeof(Skirt)), - new FillableEntry(1, typeof(PlainDress)), - new FillableEntry(1, typeof(Cap)), - new FillableEntry(2, typeof(Sandals)), - new FillableEntry(2, typeof(GnarledStaff)), - new FillableEntry(2, typeof(Pitchfork)), - new FillableEntry(1, typeof(Bag)), - new FillableEntry(1, typeof(Kindling)), - new FillableEntry(1, typeof(Lettuce)), - new FillableEntry(1, typeof(Onion)), - new FillableEntry(1, typeof(Turnip)), - new FillableEntry(1, typeof(Ham)), - new FillableEntry(1, typeof(Bacon)), - new FillableEntry(1, typeof(RawLambLeg)), - new FillableEntry(1, typeof(SheafOfHay)), - new FillableBvrge(1, typeof(Pitcher), BeverageType.Milk) - }); - - public static FillableContent FighterGuild = new FillableContent( - 3, - new[] - { - typeof(WarriorGuildmaster) - }, - new[] - { - new FillableEntry(12, Loot.ArmorTypes), - new FillableEntry(8, Loot.WeaponTypes), - new FillableEntry(3, Loot.ShieldTypes), - new FillableEntry(1, typeof(Arrow)) - }); - - public static FillableContent Guard = new FillableContent( - 3, - new Type[] - { - }, - new[] - { - new FillableEntry(12, Loot.ArmorTypes), - new FillableEntry(8, Loot.WeaponTypes), - new FillableEntry(3, Loot.ShieldTypes), - new FillableEntry(1, typeof(Arrow)) - }); - - public static FillableContent Healer = new FillableContent( - 1, - new[] - { - typeof(Healer), - typeof(HealerGuildmaster) - }, - new[] - { - new FillableEntry(1, typeof(Bandage)), - new FillableEntry(1, typeof(MortarPestle)), - new FillableEntry(1, typeof(LesserHealPotion)) - }); - - public static FillableContent Herbalist = new FillableContent( - 1, - new[] - { - typeof(Herbalist) - }, - new[] - { - new FillableEntry(10, typeof(Garlic)), - new FillableEntry(10, typeof(Ginseng)), - new FillableEntry(10, typeof(MandrakeRoot)), - new FillableEntry(1, typeof(DeadWood)), - new FillableEntry(1, typeof(WhiteDriedFlowers)), - new FillableEntry(1, typeof(GreenDriedFlowers)), - new FillableEntry(1, typeof(DriedOnions)), - new FillableEntry(1, typeof(DriedHerbs)) - }); - - public static FillableContent Inn = new FillableContent( - 1, - new Type[] - { - }, - new[] - { - new FillableEntry(1, typeof(Candle)), - new FillableEntry(1, typeof(Torch)), - new FillableEntry(1, typeof(Lantern)) - }); - - public static FillableContent Jeweler = new FillableContent( - 2, - new[] - { - typeof(Jeweler) - }, - new[] - { - new FillableEntry(1, typeof(GoldRing)), - new FillableEntry(1, typeof(GoldBracelet)), - new FillableEntry(1, typeof(GoldEarrings)), - new FillableEntry(1, typeof(GoldNecklace)), - new FillableEntry(1, typeof(GoldBeadNecklace)), - new FillableEntry(1, typeof(Necklace)), - new FillableEntry(1, typeof(Beads)), - new FillableEntry(9, Loot.GemTypes) - }); - - public static FillableContent Library = new FillableContent( - 1, - new[] - { - typeof(Scribe) - }, - new[] - { - new FillableEntry(8, Loot.LibraryBookTypes), - new FillableEntry(1, typeof(RedBook)), - new FillableEntry(1, typeof(BlueBook)) - }); - - public static FillableContent Mage = new FillableContent( - 2, - new[] - { - typeof(Mage), - typeof(HolyMage), - typeof(MageGuildmaster) - }, - new[] - { - new FillableEntry(16, typeof(BlankScroll)), - new FillableEntry(14, typeof(Spellbook)), - new FillableEntry(12, Loot.RegularScrollTypes, 0, 8), - new FillableEntry(11, Loot.RegularScrollTypes, 8, 8), - new FillableEntry(10, Loot.RegularScrollTypes, 16, 8), - new FillableEntry(9, Loot.RegularScrollTypes, 24, 8), - new FillableEntry(8, Loot.RegularScrollTypes, 32, 8), - new FillableEntry(7, Loot.RegularScrollTypes, 40, 8), - new FillableEntry(6, Loot.RegularScrollTypes, 48, 8), - new FillableEntry(5, Loot.RegularScrollTypes, 56, 8) - }); - - public static FillableContent Merchant = new FillableContent( - 1, - new[] - { - typeof(MerchantGuildmaster) - }, - new[] - { - new FillableEntry(1, typeof(CheeseWheel)), - new FillableEntry(1, typeof(CheeseWedge)), - new FillableEntry(1, typeof(CheeseSlice)), - new FillableEntry(1, typeof(Eggs)), - new FillableEntry(4, typeof(Fish)), - new FillableEntry(2, typeof(RawFishSteak)), - new FillableEntry(2, typeof(FishSteak)), - new FillableEntry(1, typeof(Apple)), - new FillableEntry(2, typeof(Banana)), - new FillableEntry(2, typeof(Bananas)), - new FillableEntry(2, typeof(OpenCoconut)), - new FillableEntry(1, typeof(SplitCoconut)), - new FillableEntry(1, typeof(Coconut)), - new FillableEntry(1, typeof(Dates)), - new FillableEntry(1, typeof(Grapes)), - new FillableEntry(1, typeof(Lemon)), - new FillableEntry(1, typeof(Lemons)), - new FillableEntry(1, typeof(Lime)), - new FillableEntry(1, typeof(Limes)), - new FillableEntry(1, typeof(Peach)), - new FillableEntry(1, typeof(Pear)), - new FillableEntry(2, typeof(SlabOfBacon)), - new FillableEntry(2, typeof(Bacon)), - new FillableEntry(2, typeof(CookedBird)), - new FillableEntry(2, typeof(RawBird)), - new FillableEntry(2, typeof(Ham)), - new FillableEntry(1, typeof(RawLambLeg)), - new FillableEntry(1, typeof(LambLeg)), - new FillableEntry(1, typeof(Ribs)), - new FillableEntry(1, typeof(RawRibs)), - new FillableEntry(2, typeof(Sausage)), - new FillableEntry(1, typeof(RawChickenLeg)), - new FillableEntry(1, typeof(ChickenLeg)), - new FillableEntry(1, typeof(Watermelon)), - new FillableEntry(1, typeof(SmallWatermelon)), - new FillableEntry(3, typeof(Turnip)), - new FillableEntry(2, typeof(YellowGourd)), - new FillableEntry(2, typeof(GreenGourd)), - new FillableEntry(2, typeof(Pumpkin)), - new FillableEntry(1, typeof(SmallPumpkin)), - new FillableEntry(2, typeof(Onion)), - new FillableEntry(2, typeof(Lettuce)), - new FillableEntry(2, typeof(Squash)), - new FillableEntry(2, typeof(HoneydewMelon)), - new FillableEntry(1, typeof(Carrot)), - new FillableEntry(2, typeof(Cantaloupe)), - new FillableEntry(2, typeof(Cabbage)), - new FillableEntry(4, typeof(EarOfCorn)) - }); - - public static FillableContent Mill = new FillableContent( - 1, - new Type[] - { - }, - new[] - { - new FillableEntry(1, typeof(SackFlour)) - }); - - public static FillableContent Mine = new FillableContent( - 1, - new[] - { - typeof(Miner) - }, - new[] - { - new FillableEntry(2, typeof(Pickaxe)), - new FillableEntry(2, typeof(Shovel)), - new FillableEntry(2, typeof(IronIngot)), - // new FillableEntry( 2, typeof( IronOre ) ), TODO: Smaller Ore - new FillableEntry(1, typeof(ForgedMetal)) - }); - - public static FillableContent Observatory = new FillableContent( - 1, - new Type[] - { - }, - new[] - { - new FillableEntry(2, typeof(Sextant)), - new FillableEntry(2, typeof(Clock)), - new FillableEntry(1, typeof(Spyglass)) - }); - - public static FillableContent Painter = new FillableContent( - 1, - new Type[] - { - }, - new[] - { - new FillableEntry(1, typeof(PaintsAndBrush)), - new FillableEntry(2, typeof(PenAndInk)) - }); - - public static FillableContent Provisioner = new FillableContent( - 1, - new[] - { - typeof(Provisioner) - }, - new[] - { - new FillableEntry(1, typeof(CheeseWheel)), - new FillableEntry(1, typeof(CheeseWedge)), - new FillableEntry(1, typeof(CheeseSlice)), - new FillableEntry(1, typeof(Eggs)), - new FillableEntry(4, typeof(Fish)), - new FillableEntry(1, typeof(DirtyFrypan)), - new FillableEntry(1, typeof(DirtyPan)), - new FillableEntry(1, typeof(DirtyKettle)), - new FillableEntry(1, typeof(DirtySmallRoundPot)), - new FillableEntry(1, typeof(DirtyRoundPot)), - new FillableEntry(1, typeof(DirtySmallPot)), - new FillableEntry(1, typeof(DirtyPot)), - new FillableEntry(1, typeof(Apple)), - new FillableEntry(2, typeof(Banana)), - new FillableEntry(2, typeof(Bananas)), - new FillableEntry(2, typeof(OpenCoconut)), - new FillableEntry(1, typeof(SplitCoconut)), - new FillableEntry(1, typeof(Coconut)), - new FillableEntry(1, typeof(Dates)), - new FillableEntry(1, typeof(Grapes)), - new FillableEntry(1, typeof(Lemon)), - new FillableEntry(1, typeof(Lemons)), - new FillableEntry(1, typeof(Lime)), - new FillableEntry(1, typeof(Limes)), - new FillableEntry(1, typeof(Peach)), - new FillableEntry(1, typeof(Pear)), - new FillableEntry(2, typeof(SlabOfBacon)), - new FillableEntry(2, typeof(Bacon)), - new FillableEntry(1, typeof(RawFishSteak)), - new FillableEntry(1, typeof(FishSteak)), - new FillableEntry(2, typeof(CookedBird)), - new FillableEntry(2, typeof(RawBird)), - new FillableEntry(2, typeof(Ham)), - new FillableEntry(1, typeof(RawLambLeg)), - new FillableEntry(1, typeof(LambLeg)), - new FillableEntry(1, typeof(Ribs)), - new FillableEntry(1, typeof(RawRibs)), - new FillableEntry(2, typeof(Sausage)), - new FillableEntry(1, typeof(RawChickenLeg)), - new FillableEntry(1, typeof(ChickenLeg)), - new FillableEntry(1, typeof(Watermelon)), - new FillableEntry(1, typeof(SmallWatermelon)), - new FillableEntry(3, typeof(Turnip)), - new FillableEntry(2, typeof(YellowGourd)), - new FillableEntry(2, typeof(GreenGourd)), - new FillableEntry(2, typeof(Pumpkin)), - new FillableEntry(1, typeof(SmallPumpkin)), - new FillableEntry(2, typeof(Onion)), - new FillableEntry(2, typeof(Lettuce)), - new FillableEntry(2, typeof(Squash)), - new FillableEntry(2, typeof(HoneydewMelon)), - new FillableEntry(1, typeof(Carrot)), - new FillableEntry(2, typeof(Cantaloupe)), - new FillableEntry(2, typeof(Cabbage)), - new FillableEntry(4, typeof(EarOfCorn)) - }); - - public static FillableContent Ranger = new FillableContent( - 2, - new[] - { - typeof(Ranger), - typeof(RangerGuildmaster) - }, - new[] - { - new FillableEntry(2, typeof(StuddedChest)), - new FillableEntry(2, typeof(StuddedLegs)), - new FillableEntry(2, typeof(StuddedArms)), - new FillableEntry(2, typeof(StuddedGloves)), - new FillableEntry(1, typeof(StuddedGorget)), - - new FillableEntry(2, typeof(LeatherChest)), - new FillableEntry(2, typeof(LeatherLegs)), - new FillableEntry(2, typeof(LeatherArms)), - new FillableEntry(2, typeof(LeatherGloves)), - new FillableEntry(1, typeof(LeatherGorget)), - - new FillableEntry(2, typeof(FeatheredHat)), - new FillableEntry(1, typeof(CloseHelm)), - new FillableEntry(1, typeof(TallStrawHat)), - new FillableEntry(1, typeof(Bandana)), - new FillableEntry(1, typeof(Cloak)), - new FillableEntry(2, typeof(Boots)), - new FillableEntry(2, typeof(ThighBoots)), - - new FillableEntry(2, typeof(GnarledStaff)), - new FillableEntry(1, typeof(Whip)), - - new FillableEntry(2, typeof(Bow)), - new FillableEntry(2, typeof(Crossbow)), - new FillableEntry(2, typeof(HeavyCrossbow)), - new FillableEntry(4, typeof(Arrow)) - }); - - public static FillableContent Stables = new FillableContent( - 1, - new[] - { - typeof(AnimalTrainer), - typeof(GypsyAnimalTrainer) - }, - new[] - { - // new FillableEntry( 1, typeof( Wheat ) ), - new FillableEntry(1, typeof(Carrot)) - }); - - public static FillableContent Tanner = new FillableContent( - 2, - new[] - { - typeof(Tanner), - typeof(LeatherWorker), - typeof(Furtrader) - }, - new[] - { - new FillableEntry(1, typeof(FeatheredHat)), - new FillableEntry(1, typeof(LeatherArms)), - new FillableEntry(2, typeof(LeatherLegs)), - new FillableEntry(2, typeof(LeatherChest)), - new FillableEntry(2, typeof(LeatherGloves)), - new FillableEntry(1, typeof(LeatherGorget)), - new FillableEntry(2, typeof(Leather)) - }); - - public static FillableContent Tavern = new FillableContent( - 1, - new[] - { - typeof(TavernKeeper), - typeof(Barkeeper), - typeof(Waiter), - typeof(Cook) - }, - new FillableEntry[] - { - new FillableBvrge(1, typeof(BeverageBottle), BeverageType.Ale), - new FillableBvrge(1, typeof(BeverageBottle), BeverageType.Wine), - new FillableBvrge(1, typeof(BeverageBottle), BeverageType.Liquor), - new FillableBvrge(1, typeof(Jug), BeverageType.Cider) - }); - - public static FillableContent ThiefGuild = new FillableContent( - 1, - new[] - { - typeof(Thief), - typeof(ThiefGuildmaster) - }, - new[] - { - new FillableEntry(1, typeof(Lockpick)), - new FillableEntry(1, typeof(BearMask)), - new FillableEntry(1, typeof(DeerMask)), - new FillableEntry(1, typeof(TribalMask)), - new FillableEntry(1, typeof(HornedTribalMask)), - new FillableEntry(4, typeof(OrcHelm)) - }); - - public static FillableContent Tinker = new FillableContent( - 1, - new[] - { - typeof(Tinker), - typeof(TinkerGuildmaster) - }, - new[] - { - new FillableEntry(1, typeof(Lockpick)), - // new FillableEntry( 1, typeof( KeyRing ) ), - new FillableEntry(2, typeof(Clock)), - new FillableEntry(2, typeof(ClockParts)), - new FillableEntry(2, typeof(AxleGears)), - new FillableEntry(2, typeof(Gears)), - new FillableEntry(2, typeof(Hinge)), - // new FillableEntry( 1, typeof( ArrowShafts ) ), - new FillableEntry(2, typeof(Sextant)), - new FillableEntry(2, typeof(SextantParts)), - new FillableEntry(2, typeof(Axle)), - new FillableEntry(2, typeof(Springs)), - new FillableEntry(5, typeof(TinkerTools)), - new FillableEntry(4, typeof(Key)), - new FillableEntry(1, typeof(DecoArrowShafts)), - new FillableEntry(1, typeof(Lockpicks)), - new FillableEntry(1, typeof(ToolKit)) - }); - - public static FillableContent Veterinarian = new FillableContent( - 1, - new[] - { - typeof(Veterinarian) - }, - new[] - { - new FillableEntry(1, typeof(Bandage)), - new FillableEntry(1, typeof(MortarPestle)), - new FillableEntry(1, typeof(LesserHealPotion)), - // new FillableEntry( 1, typeof( Wheat ) ), - new FillableEntry(1, typeof(Carrot)) - }); - - public static FillableContent Weaponsmith = new FillableContent( - 2, - new[] - { - typeof(Weaponsmith) - }, - new[] - { - new FillableEntry(8, Loot.WeaponTypes), - new FillableEntry(1, typeof(Arrow)) - }); - - private static Dictionary m_AcquireTable; - - private static readonly FillableContent[] m_ContentTypes = - { - Weaponsmith, Provisioner, Mage, - Alchemist, Armorer, ArtisanGuild, - Baker, Bard, Blacksmith, - Bowyer, Butcher, Carpenter, - Clothier, Cobbler, Docks, - Farm, FighterGuild, Guard, - Healer, Herbalist, Inn, - Jeweler, Library, Merchant, - Mill, Mine, Observatory, - Painter, Ranger, Stables, - Tanner, Tavern, ThiefGuild, - Tinker, Veterinarian - }; - - private readonly FillableEntry[] m_Entries; - private readonly int m_Weight; - - public FillableContent(int level, Type[] vendors, FillableEntry[] entries) - { - Level = level; - Vendors = vendors; - m_Entries = entries; - - for (int i = 0; i < entries.Length; ++i) - m_Weight += entries[i].Weight; - } - - public int Level { get; } - - public Type[] Vendors { get; } - - public FillableContentType TypeID => Lookup(this); - - public virtual Item Construct() - { - int index = Utility.Random(m_Weight); - - for (int i = 0; i < m_Entries.Length; ++i) - { - FillableEntry entry = m_Entries[i]; - - if (index < entry.Weight) - return entry.Construct(); - - index -= entry.Weight; - } - - return null; - } - - public static FillableContent Lookup(FillableContentType type) - { - int v = (int)type; - - if (v >= 0 && v < m_ContentTypes.Length) - return m_ContentTypes[v]; - - return null; - } - - public static FillableContentType Lookup(FillableContent content) - { - if (content == null) - return FillableContentType.None; - - return (FillableContentType)Array.IndexOf(m_ContentTypes, content); - } - - public static FillableContent Acquire(Point3D loc, Map map) - { - if (map == null || map == Map.Internal) - return null; - - if (m_AcquireTable == null) - { - m_AcquireTable = new Dictionary(); - - for (int i = 0; i < m_ContentTypes.Length; ++i) - { - FillableContent fill = m_ContentTypes[i]; - - for (int j = 0; j < fill.Vendors.Length; ++j) - m_AcquireTable[fill.Vendors[j]] = fill; - } - } - - Mobile nearest = null; - FillableContent content = null; - - foreach (Mobile mob in map.GetMobilesInRange(loc, 20)) - { - if (nearest != null && mob.GetDistanceToSqrt(loc) > nearest.GetDistanceToSqrt(loc) && - !(nearest is Cobbler && mob is Provisioner)) - continue; - - if (m_AcquireTable.TryGetValue(mob.GetType(), out FillableContent check)) - { - nearest = mob; - content = check; - } - } - - return content; - } - } -} +using System; +using System.Collections.Generic; +using Server.Mobiles; + +namespace Server.Items +{ + public abstract class FillableContainer : LockableContainer + { + protected FillableContent m_Content; + + protected DateTime m_NextRespawnTime; + protected Timer m_RespawnTimer; + + public FillableContainer(int itemID) + : base(itemID) => + Movable = false; + + public FillableContainer(Serial serial) + : base(serial) + { + } + + public virtual int MinRespawnMinutes => 60; + public virtual int MaxRespawnMinutes => 90; + + public virtual bool IsLockable => true; + public virtual bool IsTrappable => IsLockable; + + public virtual int SpawnThreshold => 2; + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime NextRespawnTime => m_NextRespawnTime; + + [CommandProperty(AccessLevel.GameMaster)] + public FillableContentType ContentType + { + get => FillableContent.Lookup(m_Content); + set => Content = FillableContent.Lookup(value); + } + + public FillableContent Content + { + get => m_Content; + set + { + if (m_Content == value) + return; + + m_Content = value; + + for (var i = Items.Count - 1; i >= 0; --i) + if (i < Items.Count) + Items[i].Delete(); + + Respawn(); + } + } + + public override void OnMapChange() + { + base.OnMapChange(); + AcquireContent(); + } + + public override void OnLocationChange(Point3D oldLocation) + { + base.OnLocationChange(oldLocation); + AcquireContent(); + } + + public virtual void AcquireContent() + { + if (m_Content != null) + return; + + m_Content = FillableContent.Acquire(GetWorldLocation(), Map); + + if (m_Content != null) + Respawn(); + } + + public override void OnItemRemoved(Item item) + { + CheckRespawn(); + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + if (m_RespawnTimer != null) + { + m_RespawnTimer.Stop(); + m_RespawnTimer = null; + } + } + + public int GetItemsCount() + { + var count = 0; + + foreach (var item in Items) count += item.Amount; + + return count; + } + + public void CheckRespawn() + { + var canSpawn = m_Content != null && !Deleted && GetItemsCount() <= SpawnThreshold && !Movable && + Parent == null && !IsLockedDown && !IsSecure; + + if (canSpawn) + { + if (m_RespawnTimer == null) + { + var mins = Utility.RandomMinMax(MinRespawnMinutes, MaxRespawnMinutes); + var delay = TimeSpan.FromMinutes(mins); + + m_NextRespawnTime = DateTime.UtcNow + delay; + m_RespawnTimer = Timer.DelayCall(delay, Respawn); + } + } + else if (m_RespawnTimer != null) + { + m_RespawnTimer.Stop(); + m_RespawnTimer = null; + } + } + + public void Respawn() + { + if (m_RespawnTimer != null) + { + m_RespawnTimer.Stop(); + m_RespawnTimer = null; + } + + if (m_Content == null || Deleted) + return; + + GenerateContent(); + + if (IsLockable) + { + Locked = true; + + var difficulty = (m_Content.Level - 1) * 30; + + LockLevel = difficulty - 10; + MaxLockLevel = difficulty + 30; + RequiredSkill = difficulty; + } + + if (IsTrappable && (m_Content.Level > 1 || Utility.Random(5) < 4)) + { + if (m_Content.Level > Utility.Random(5)) + TrapType = TrapType.PoisonTrap; + else + TrapType = TrapType.ExplosionTrap; + + TrapPower = m_Content.Level * Utility.RandomMinMax(10, 30); + TrapLevel = m_Content.Level; + } + else + { + TrapType = TrapType.None; + TrapPower = 0; + TrapLevel = 0; + } + + CheckRespawn(); + } + + protected virtual int GetSpawnCount() + { + var itemsCount = GetItemsCount(); + + if (itemsCount > SpawnThreshold) + return 0; + + var maxSpawnCount = (1 + SpawnThreshold - itemsCount) * 2; + + return Utility.RandomMinMax(0, maxSpawnCount); + } + + public virtual void GenerateContent() + { + if (m_Content == null || Deleted) + return; + + var toSpawn = GetSpawnCount(); + + for (var i = 0; i < toSpawn; ++i) + { + var item = m_Content.Construct(); + + if (item == null) + continue; + + var list = Items; + + for (var j = 0; j < list.Count; ++j) + { + var subItem = list[j]; + + if (!(subItem is Container) && subItem.StackWith(null, item, false)) + break; + } + + if (!item.Deleted) + DropItem(item); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(1); // version + + writer.Write((int)ContentType); + + if (m_RespawnTimer != null) + { + writer.Write(true); + writer.WriteDeltaTime(m_NextRespawnTime); + } + else + { + writer.Write(false); + } + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 1: + { + m_Content = FillableContent.Lookup((FillableContentType)reader.ReadInt()); + goto case 0; + } + case 0: + { + if (reader.ReadBool()) + { + m_NextRespawnTime = reader.ReadDeltaTime(); + + var delay = m_NextRespawnTime - DateTime.UtcNow; + m_RespawnTimer = Timer.DelayCall(delay > TimeSpan.Zero ? delay : TimeSpan.Zero, Respawn); + } + else + { + CheckRespawn(); + } + + break; + } + } + } + } + + [Flippable(0xA97, 0xA99, 0xA98, 0xA9A, 0xA9B, 0xA9C)] + public class LibraryBookcase : FillableContainer + { + [Constructible] + public LibraryBookcase() + : base(0xA97) => + Weight = 1.0; + + public LibraryBookcase(Serial serial) + : base(serial) + { + } + + public override bool IsLockable => false; + public override int SpawnThreshold => 5; + + protected override int GetSpawnCount() => 5 - GetItemsCount(); + + public override void AcquireContent() + { + if (m_Content != null) + return; + + m_Content = FillableContent.Library; + + if (m_Content != null) + Respawn(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(1); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + if (version == 0 && m_Content == null) + Timer.DelayCall(AcquireContent); + } + } + + [Flippable(0xE3D, 0xE3C)] + public class FillableLargeCrate : FillableContainer + { + [Constructible] + public FillableLargeCrate() + : base(0xE3D) => + Weight = 1.0; + + public FillableLargeCrate(Serial serial) + : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x9A9, 0xE7E)] + public class FillableSmallCrate : FillableContainer + { + [Constructible] + public FillableSmallCrate() + : base(0x9A9) => + Weight = 1.0; + + public FillableSmallCrate(Serial serial) + : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x9AA, 0xE7D)] + public class FillableWoodenBox : FillableContainer + { + [Constructible] + public FillableWoodenBox() + : base(0x9AA) => + Weight = 4.0; + + public FillableWoodenBox(Serial serial) + : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x9A8, 0xE80)] + public class FillableMetalBox : FillableContainer + { + [Constructible] + public FillableMetalBox() + : base(0x9A8) + { + } + + public FillableMetalBox(Serial serial) + : base(serial) + { + } + + 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 (version == 0 && Weight == 3) + Weight = -1; + } + } + + public class FillableBarrel : FillableContainer + { + [Constructible] + public FillableBarrel() + : base(0xE77) + { + } + + public FillableBarrel(Serial serial) + : base(serial) + { + } + + public override bool IsLockable => false; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(1); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + if (version == 0 && Weight == 25) + Weight = -1; + } + } + + [Flippable(0x9AB, 0xE7C)] + public class FillableMetalChest : FillableContainer + { + [Constructible] + public FillableMetalChest() + : base(0x9AB) + { + } + + public FillableMetalChest(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 == 25) + Weight = -1; + } + } + + [Flippable(0xE41, 0xE40)] + public class FillableMetalGoldenChest : FillableContainer + { + [Constructible] + public FillableMetalGoldenChest() + : base(0xE41) + { + } + + public FillableMetalGoldenChest(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 == 25) + Weight = -1; + } + } + + [Flippable(0xE43, 0xE42)] + public class FillableWoodenChest : FillableContainer + { + [Constructible] + public FillableWoodenChest() + : base(0xE43) + { + } + + public FillableWoodenChest(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 == 2) + Weight = -1; + } + } + + public class FillableEntry + { + protected Type[] m_Types; + protected int m_Weight; + + public FillableEntry(Type type) + : this(1, new[] { type }) + { + } + + public FillableEntry(int weight, Type type) + : this(weight, new[] { type }) + { + } + + public FillableEntry(Type[] types) + : this(1, types) + { + } + + public FillableEntry(int weight, Type[] types) + { + m_Weight = weight; + m_Types = types; + } + + public FillableEntry(int weight, Type[] types, int offset, int count) + { + m_Weight = weight; + m_Types = new Type[count]; + + for (var i = 0; i < m_Types.Length; ++i) + m_Types[i] = types[offset + i]; + } + + public Type[] Types => m_Types; + public int Weight => m_Weight; + + public virtual Item Construct() + { + var item = Loot.Construct(m_Types); + + if (item is Key key) + key.ItemID = Utility.RandomList( + (int)KeyType.Copper, + (int)KeyType.Gold, + (int)KeyType.Iron, + (int)KeyType.Rusty + ); + else if (item is Arrow || item is Bolt) + item.Amount = Utility.RandomMinMax(2, 6); + else if (item is Bandage || item is Lockpick) + item.Amount = Utility.RandomMinMax(1, 3); + + return item; + } + } + + public class FillableBvrge : FillableEntry + { + public FillableBvrge(Type type, BeverageType content) + : this(1, type, content) + { + } + + public FillableBvrge(int weight, Type type, BeverageType content) + : base(weight, type) => + Content = content; + + public BeverageType Content { get; } + + public override Item Construct() + { + Item item; + + var index = Utility.Random(m_Types.Length); + + if (m_Types[index] == typeof(BeverageBottle)) + { + item = new BeverageBottle(Content); + } + else if (m_Types[index] == typeof(Jug)) + { + item = new Jug(Content); + } + else + { + item = base.Construct(); + + if (item is BaseBeverage bev) + { + bev.Content = Content; + bev.Quantity = bev.MaxQuantity; + } + } + + return item; + } + } + + public enum FillableContentType + { + None = -1, + Weaponsmith, + Provisioner, + Mage, + Alchemist, + Armorer, + ArtisanGuild, + Baker, + Bard, + Blacksmith, + Bowyer, + Butcher, + Carpenter, + Clothier, + Cobbler, + Docks, + Farm, + FighterGuild, + Guard, + Healer, + Herbalist, + Inn, + Jeweler, + Library, + Merchant, + Mill, + Mine, + Observatory, + Painter, + Ranger, + Stables, + Tanner, + Tavern, + ThiefGuild, + Tinker, + Veterinarian + } + + public class FillableContent + { + public static FillableContent Alchemist = new FillableContent( + 1, + new[] + { + typeof(Alchemist) + }, + new[] + { + new FillableEntry(typeof(NightSightPotion)), + new FillableEntry(typeof(LesserCurePotion)), + new FillableEntry(typeof(AgilityPotion)), + new FillableEntry(typeof(StrengthPotion)), + new FillableEntry(typeof(LesserPoisonPotion)), + new FillableEntry(typeof(RefreshPotion)), + new FillableEntry(typeof(LesserHealPotion)), + new FillableEntry(typeof(LesserExplosionPotion)), + new FillableEntry(typeof(MortarPestle)) + } + ); + + public static FillableContent Armorer = new FillableContent( + 2, + new[] + { + typeof(Armorer) + }, + new[] + { + new FillableEntry(2, typeof(ChainCoif)), + new FillableEntry(1, typeof(PlateGorget)), + new FillableEntry(1, typeof(BronzeShield)), + new FillableEntry(1, typeof(Buckler)), + new FillableEntry(2, typeof(MetalKiteShield)), + new FillableEntry(2, typeof(HeaterShield)), + new FillableEntry(1, typeof(WoodenShield)), + new FillableEntry(1, typeof(MetalShield)) + } + ); + + public static FillableContent ArtisanGuild = new FillableContent( + 1, + new Type[] + { + }, + new[] + { + new FillableEntry(1, typeof(PaintsAndBrush)), + new FillableEntry(1, typeof(SledgeHammer)), + new FillableEntry(2, typeof(SmithHammer)), + new FillableEntry(2, typeof(Tongs)), + new FillableEntry(4, typeof(Lockpick)), + new FillableEntry(4, typeof(TinkerTools)), + new FillableEntry(1, typeof(MalletAndChisel)), + new FillableEntry(1, typeof(StatueEast2)), + new FillableEntry(1, typeof(StatueSouth)), + new FillableEntry(1, typeof(StatueSouthEast)), + new FillableEntry(1, typeof(StatueWest)), + new FillableEntry(1, typeof(StatueNorth)), + new FillableEntry(1, typeof(StatueEast)), + new FillableEntry(1, typeof(BustEast)), + new FillableEntry(1, typeof(BustSouth)), + new FillableEntry(1, typeof(BearMask)), + new FillableEntry(1, typeof(DeerMask)), + new FillableEntry(4, typeof(OrcHelm)), + new FillableEntry(1, typeof(TribalMask)), + new FillableEntry(1, typeof(HornedTribalMask)) + } + ); + + public static FillableContent Baker = new FillableContent( + 1, + new[] + { + typeof(Baker) + }, + new[] + { + new FillableEntry(1, typeof(RollingPin)), + new FillableEntry(2, typeof(SackFlour)), + new FillableEntry(2, typeof(BreadLoaf)), + new FillableEntry(1, typeof(FrenchBread)) + } + ); + + public static FillableContent Bard = new FillableContent( + 1, + new[] + { + typeof(Bard), + typeof(BardGuildmaster) + }, + new[] + { + new FillableEntry(1, typeof(LapHarp)), + new FillableEntry(2, typeof(Lute)), + new FillableEntry(1, typeof(Drums)), + new FillableEntry(1, typeof(Tambourine)), + new FillableEntry(1, typeof(TambourineTassel)) + } + ); + + public static FillableContent Blacksmith = new FillableContent( + 2, + new[] + { + typeof(Blacksmith), + typeof(BlacksmithGuildmaster) + }, + new[] + { + new FillableEntry(8, typeof(SmithHammer)), + new FillableEntry(8, typeof(Tongs)), + new FillableEntry(8, typeof(SledgeHammer)), + // new FillableEntry( 8, typeof( IronOre ) ), TODO: Smaller ore + new FillableEntry(8, typeof(IronIngot)), + new FillableEntry(1, typeof(IronWire)), + new FillableEntry(1, typeof(SilverWire)), + new FillableEntry(1, typeof(GoldWire)), + new FillableEntry(1, typeof(CopperWire)), + new FillableEntry(1, typeof(HorseShoes)), + new FillableEntry(1, typeof(ForgedMetal)) + } + ); + + public static FillableContent Bowyer = new FillableContent( + 2, + new[] + { + typeof(Bowyer) + }, + new[] + { + new FillableEntry(2, typeof(Bow)), + new FillableEntry(2, typeof(Crossbow)), + new FillableEntry(1, typeof(Arrow)) + } + ); + + public static FillableContent Butcher = new FillableContent( + 1, + new[] + { + typeof(Butcher) + }, + new[] + { + new FillableEntry(2, typeof(Cleaver)), + new FillableEntry(2, typeof(SlabOfBacon)), + new FillableEntry(2, typeof(Bacon)), + new FillableEntry(1, typeof(RawFishSteak)), + new FillableEntry(1, typeof(FishSteak)), + new FillableEntry(2, typeof(CookedBird)), + new FillableEntry(2, typeof(RawBird)), + new FillableEntry(2, typeof(Ham)), + new FillableEntry(1, typeof(RawLambLeg)), + new FillableEntry(1, typeof(LambLeg)), + new FillableEntry(1, typeof(Ribs)), + new FillableEntry(1, typeof(RawRibs)), + new FillableEntry(2, typeof(Sausage)), + new FillableEntry(1, typeof(RawChickenLeg)), + new FillableEntry(1, typeof(ChickenLeg)) + } + ); + + public static FillableContent Carpenter = new FillableContent( + 1, + new[] + { + typeof(Carpenter), + typeof(Architect), + typeof(RealEstateBroker) + }, + new[] + { + new FillableEntry(1, typeof(ChiselsNorth)), + new FillableEntry(1, typeof(ChiselsWest)), + new FillableEntry(2, typeof(DovetailSaw)), + new FillableEntry(2, typeof(Hammer)), + new FillableEntry(2, typeof(MouldingPlane)), + new FillableEntry(2, typeof(Nails)), + new FillableEntry(2, typeof(JointingPlane)), + new FillableEntry(2, typeof(SmoothingPlane)), + new FillableEntry(2, typeof(Saw)), + new FillableEntry(2, typeof(DrawKnife)), + new FillableEntry(1, typeof(Log)), + new FillableEntry(1, typeof(Froe)), + new FillableEntry(1, typeof(Inshave)), + new FillableEntry(1, typeof(Scorp)) + } + ); + + public static FillableContent Clothier = new FillableContent( + 1, + new[] + { + typeof(Tailor), + typeof(Weaver), + typeof(TailorGuildmaster) + }, + new[] + { + new FillableEntry(1, typeof(Cotton)), + new FillableEntry(1, typeof(Wool)), + new FillableEntry(1, typeof(DarkYarn)), + new FillableEntry(1, typeof(LightYarn)), + new FillableEntry(1, typeof(LightYarnUnraveled)), + new FillableEntry(1, typeof(SpoolOfThread)), + // Four different types + // new FillableEntry( 1, typeof( FoldedCloth ) ), + // new FillableEntry( 1, typeof( FoldedCloth ) ), + // new FillableEntry( 1, typeof( FoldedCloth ) ), + // new FillableEntry( 1, typeof( FoldedCloth ) ), + new FillableEntry(1, typeof(Dyes)), + new FillableEntry(2, typeof(Leather)) + } + ); + + public static FillableContent Cobbler = new FillableContent( + 1, + new[] + { + typeof(Cobbler) + }, + new[] + { + new FillableEntry(1, typeof(Boots)), + new FillableEntry(2, typeof(Shoes)), + new FillableEntry(2, typeof(Sandals)), + new FillableEntry(1, typeof(ThighBoots)) + } + ); + + public static FillableContent Docks = new FillableContent( + 1, + new[] + { + typeof(Fisherman), + typeof(FisherGuildmaster) + }, + new[] + { + new FillableEntry(1, typeof(FishingPole)), + // Two different types + // new FillableEntry( 1, typeof( SmallFish ) ), + // new FillableEntry( 1, typeof( SmallFish ) ), + new FillableEntry(4, typeof(Fish)) + } + ); + + public static FillableContent Farm = new FillableContent( + 1, + new[] + { + typeof(Farmer), + typeof(Rancher) + }, + new[] + { + new FillableEntry(1, typeof(Shirt)), + new FillableEntry(1, typeof(ShortPants)), + new FillableEntry(1, typeof(Skirt)), + new FillableEntry(1, typeof(PlainDress)), + new FillableEntry(1, typeof(Cap)), + new FillableEntry(2, typeof(Sandals)), + new FillableEntry(2, typeof(GnarledStaff)), + new FillableEntry(2, typeof(Pitchfork)), + new FillableEntry(1, typeof(Bag)), + new FillableEntry(1, typeof(Kindling)), + new FillableEntry(1, typeof(Lettuce)), + new FillableEntry(1, typeof(Onion)), + new FillableEntry(1, typeof(Turnip)), + new FillableEntry(1, typeof(Ham)), + new FillableEntry(1, typeof(Bacon)), + new FillableEntry(1, typeof(RawLambLeg)), + new FillableEntry(1, typeof(SheafOfHay)), + new FillableBvrge(1, typeof(Pitcher), BeverageType.Milk) + } + ); + + public static FillableContent FighterGuild = new FillableContent( + 3, + new[] + { + typeof(WarriorGuildmaster) + }, + new[] + { + new FillableEntry(12, Loot.ArmorTypes), + new FillableEntry(8, Loot.WeaponTypes), + new FillableEntry(3, Loot.ShieldTypes), + new FillableEntry(1, typeof(Arrow)) + } + ); + + public static FillableContent Guard = new FillableContent( + 3, + new Type[] + { + }, + new[] + { + new FillableEntry(12, Loot.ArmorTypes), + new FillableEntry(8, Loot.WeaponTypes), + new FillableEntry(3, Loot.ShieldTypes), + new FillableEntry(1, typeof(Arrow)) + } + ); + + public static FillableContent Healer = new FillableContent( + 1, + new[] + { + typeof(Healer), + typeof(HealerGuildmaster) + }, + new[] + { + new FillableEntry(1, typeof(Bandage)), + new FillableEntry(1, typeof(MortarPestle)), + new FillableEntry(1, typeof(LesserHealPotion)) + } + ); + + public static FillableContent Herbalist = new FillableContent( + 1, + new[] + { + typeof(Herbalist) + }, + new[] + { + new FillableEntry(10, typeof(Garlic)), + new FillableEntry(10, typeof(Ginseng)), + new FillableEntry(10, typeof(MandrakeRoot)), + new FillableEntry(1, typeof(DeadWood)), + new FillableEntry(1, typeof(WhiteDriedFlowers)), + new FillableEntry(1, typeof(GreenDriedFlowers)), + new FillableEntry(1, typeof(DriedOnions)), + new FillableEntry(1, typeof(DriedHerbs)) + } + ); + + public static FillableContent Inn = new FillableContent( + 1, + new Type[] + { + }, + new[] + { + new FillableEntry(1, typeof(Candle)), + new FillableEntry(1, typeof(Torch)), + new FillableEntry(1, typeof(Lantern)) + } + ); + + public static FillableContent Jeweler = new FillableContent( + 2, + new[] + { + typeof(Jeweler) + }, + new[] + { + new FillableEntry(1, typeof(GoldRing)), + new FillableEntry(1, typeof(GoldBracelet)), + new FillableEntry(1, typeof(GoldEarrings)), + new FillableEntry(1, typeof(GoldNecklace)), + new FillableEntry(1, typeof(GoldBeadNecklace)), + new FillableEntry(1, typeof(Necklace)), + new FillableEntry(1, typeof(Beads)), + new FillableEntry(9, Loot.GemTypes) + } + ); + + public static FillableContent Library = new FillableContent( + 1, + new[] + { + typeof(Scribe) + }, + new[] + { + new FillableEntry(8, Loot.LibraryBookTypes), + new FillableEntry(1, typeof(RedBook)), + new FillableEntry(1, typeof(BlueBook)) + } + ); + + public static FillableContent Mage = new FillableContent( + 2, + new[] + { + typeof(Mage), + typeof(HolyMage), + typeof(MageGuildmaster) + }, + new[] + { + new FillableEntry(16, typeof(BlankScroll)), + new FillableEntry(14, typeof(Spellbook)), + new FillableEntry(12, Loot.RegularScrollTypes, 0, 8), + new FillableEntry(11, Loot.RegularScrollTypes, 8, 8), + new FillableEntry(10, Loot.RegularScrollTypes, 16, 8), + new FillableEntry(9, Loot.RegularScrollTypes, 24, 8), + new FillableEntry(8, Loot.RegularScrollTypes, 32, 8), + new FillableEntry(7, Loot.RegularScrollTypes, 40, 8), + new FillableEntry(6, Loot.RegularScrollTypes, 48, 8), + new FillableEntry(5, Loot.RegularScrollTypes, 56, 8) + } + ); + + public static FillableContent Merchant = new FillableContent( + 1, + new[] + { + typeof(MerchantGuildmaster) + }, + new[] + { + new FillableEntry(1, typeof(CheeseWheel)), + new FillableEntry(1, typeof(CheeseWedge)), + new FillableEntry(1, typeof(CheeseSlice)), + new FillableEntry(1, typeof(Eggs)), + new FillableEntry(4, typeof(Fish)), + new FillableEntry(2, typeof(RawFishSteak)), + new FillableEntry(2, typeof(FishSteak)), + new FillableEntry(1, typeof(Apple)), + new FillableEntry(2, typeof(Banana)), + new FillableEntry(2, typeof(Bananas)), + new FillableEntry(2, typeof(OpenCoconut)), + new FillableEntry(1, typeof(SplitCoconut)), + new FillableEntry(1, typeof(Coconut)), + new FillableEntry(1, typeof(Dates)), + new FillableEntry(1, typeof(Grapes)), + new FillableEntry(1, typeof(Lemon)), + new FillableEntry(1, typeof(Lemons)), + new FillableEntry(1, typeof(Lime)), + new FillableEntry(1, typeof(Limes)), + new FillableEntry(1, typeof(Peach)), + new FillableEntry(1, typeof(Pear)), + new FillableEntry(2, typeof(SlabOfBacon)), + new FillableEntry(2, typeof(Bacon)), + new FillableEntry(2, typeof(CookedBird)), + new FillableEntry(2, typeof(RawBird)), + new FillableEntry(2, typeof(Ham)), + new FillableEntry(1, typeof(RawLambLeg)), + new FillableEntry(1, typeof(LambLeg)), + new FillableEntry(1, typeof(Ribs)), + new FillableEntry(1, typeof(RawRibs)), + new FillableEntry(2, typeof(Sausage)), + new FillableEntry(1, typeof(RawChickenLeg)), + new FillableEntry(1, typeof(ChickenLeg)), + new FillableEntry(1, typeof(Watermelon)), + new FillableEntry(1, typeof(SmallWatermelon)), + new FillableEntry(3, typeof(Turnip)), + new FillableEntry(2, typeof(YellowGourd)), + new FillableEntry(2, typeof(GreenGourd)), + new FillableEntry(2, typeof(Pumpkin)), + new FillableEntry(1, typeof(SmallPumpkin)), + new FillableEntry(2, typeof(Onion)), + new FillableEntry(2, typeof(Lettuce)), + new FillableEntry(2, typeof(Squash)), + new FillableEntry(2, typeof(HoneydewMelon)), + new FillableEntry(1, typeof(Carrot)), + new FillableEntry(2, typeof(Cantaloupe)), + new FillableEntry(2, typeof(Cabbage)), + new FillableEntry(4, typeof(EarOfCorn)) + } + ); + + public static FillableContent Mill = new FillableContent( + 1, + new Type[] + { + }, + new[] + { + new FillableEntry(1, typeof(SackFlour)) + } + ); + + public static FillableContent Mine = new FillableContent( + 1, + new[] + { + typeof(Miner) + }, + new[] + { + new FillableEntry(2, typeof(Pickaxe)), + new FillableEntry(2, typeof(Shovel)), + new FillableEntry(2, typeof(IronIngot)), + // new FillableEntry( 2, typeof( IronOre ) ), TODO: Smaller Ore + new FillableEntry(1, typeof(ForgedMetal)) + } + ); + + public static FillableContent Observatory = new FillableContent( + 1, + new Type[] + { + }, + new[] + { + new FillableEntry(2, typeof(Sextant)), + new FillableEntry(2, typeof(Clock)), + new FillableEntry(1, typeof(Spyglass)) + } + ); + + public static FillableContent Painter = new FillableContent( + 1, + new Type[] + { + }, + new[] + { + new FillableEntry(1, typeof(PaintsAndBrush)), + new FillableEntry(2, typeof(PenAndInk)) + } + ); + + public static FillableContent Provisioner = new FillableContent( + 1, + new[] + { + typeof(Provisioner) + }, + new[] + { + new FillableEntry(1, typeof(CheeseWheel)), + new FillableEntry(1, typeof(CheeseWedge)), + new FillableEntry(1, typeof(CheeseSlice)), + new FillableEntry(1, typeof(Eggs)), + new FillableEntry(4, typeof(Fish)), + new FillableEntry(1, typeof(DirtyFrypan)), + new FillableEntry(1, typeof(DirtyPan)), + new FillableEntry(1, typeof(DirtyKettle)), + new FillableEntry(1, typeof(DirtySmallRoundPot)), + new FillableEntry(1, typeof(DirtyRoundPot)), + new FillableEntry(1, typeof(DirtySmallPot)), + new FillableEntry(1, typeof(DirtyPot)), + new FillableEntry(1, typeof(Apple)), + new FillableEntry(2, typeof(Banana)), + new FillableEntry(2, typeof(Bananas)), + new FillableEntry(2, typeof(OpenCoconut)), + new FillableEntry(1, typeof(SplitCoconut)), + new FillableEntry(1, typeof(Coconut)), + new FillableEntry(1, typeof(Dates)), + new FillableEntry(1, typeof(Grapes)), + new FillableEntry(1, typeof(Lemon)), + new FillableEntry(1, typeof(Lemons)), + new FillableEntry(1, typeof(Lime)), + new FillableEntry(1, typeof(Limes)), + new FillableEntry(1, typeof(Peach)), + new FillableEntry(1, typeof(Pear)), + new FillableEntry(2, typeof(SlabOfBacon)), + new FillableEntry(2, typeof(Bacon)), + new FillableEntry(1, typeof(RawFishSteak)), + new FillableEntry(1, typeof(FishSteak)), + new FillableEntry(2, typeof(CookedBird)), + new FillableEntry(2, typeof(RawBird)), + new FillableEntry(2, typeof(Ham)), + new FillableEntry(1, typeof(RawLambLeg)), + new FillableEntry(1, typeof(LambLeg)), + new FillableEntry(1, typeof(Ribs)), + new FillableEntry(1, typeof(RawRibs)), + new FillableEntry(2, typeof(Sausage)), + new FillableEntry(1, typeof(RawChickenLeg)), + new FillableEntry(1, typeof(ChickenLeg)), + new FillableEntry(1, typeof(Watermelon)), + new FillableEntry(1, typeof(SmallWatermelon)), + new FillableEntry(3, typeof(Turnip)), + new FillableEntry(2, typeof(YellowGourd)), + new FillableEntry(2, typeof(GreenGourd)), + new FillableEntry(2, typeof(Pumpkin)), + new FillableEntry(1, typeof(SmallPumpkin)), + new FillableEntry(2, typeof(Onion)), + new FillableEntry(2, typeof(Lettuce)), + new FillableEntry(2, typeof(Squash)), + new FillableEntry(2, typeof(HoneydewMelon)), + new FillableEntry(1, typeof(Carrot)), + new FillableEntry(2, typeof(Cantaloupe)), + new FillableEntry(2, typeof(Cabbage)), + new FillableEntry(4, typeof(EarOfCorn)) + } + ); + + public static FillableContent Ranger = new FillableContent( + 2, + new[] + { + typeof(Ranger), + typeof(RangerGuildmaster) + }, + new[] + { + new FillableEntry(2, typeof(StuddedChest)), + new FillableEntry(2, typeof(StuddedLegs)), + new FillableEntry(2, typeof(StuddedArms)), + new FillableEntry(2, typeof(StuddedGloves)), + new FillableEntry(1, typeof(StuddedGorget)), + + new FillableEntry(2, typeof(LeatherChest)), + new FillableEntry(2, typeof(LeatherLegs)), + new FillableEntry(2, typeof(LeatherArms)), + new FillableEntry(2, typeof(LeatherGloves)), + new FillableEntry(1, typeof(LeatherGorget)), + + new FillableEntry(2, typeof(FeatheredHat)), + new FillableEntry(1, typeof(CloseHelm)), + new FillableEntry(1, typeof(TallStrawHat)), + new FillableEntry(1, typeof(Bandana)), + new FillableEntry(1, typeof(Cloak)), + new FillableEntry(2, typeof(Boots)), + new FillableEntry(2, typeof(ThighBoots)), + + new FillableEntry(2, typeof(GnarledStaff)), + new FillableEntry(1, typeof(Whip)), + + new FillableEntry(2, typeof(Bow)), + new FillableEntry(2, typeof(Crossbow)), + new FillableEntry(2, typeof(HeavyCrossbow)), + new FillableEntry(4, typeof(Arrow)) + } + ); + + public static FillableContent Stables = new FillableContent( + 1, + new[] + { + typeof(AnimalTrainer), + typeof(GypsyAnimalTrainer) + }, + new[] + { + // new FillableEntry( 1, typeof( Wheat ) ), + new FillableEntry(1, typeof(Carrot)) + } + ); + + public static FillableContent Tanner = new FillableContent( + 2, + new[] + { + typeof(Tanner), + typeof(LeatherWorker), + typeof(Furtrader) + }, + new[] + { + new FillableEntry(1, typeof(FeatheredHat)), + new FillableEntry(1, typeof(LeatherArms)), + new FillableEntry(2, typeof(LeatherLegs)), + new FillableEntry(2, typeof(LeatherChest)), + new FillableEntry(2, typeof(LeatherGloves)), + new FillableEntry(1, typeof(LeatherGorget)), + new FillableEntry(2, typeof(Leather)) + } + ); + + public static FillableContent Tavern = new FillableContent( + 1, + new[] + { + typeof(TavernKeeper), + typeof(Barkeeper), + typeof(Waiter), + typeof(Cook) + }, + new FillableEntry[] + { + new FillableBvrge(1, typeof(BeverageBottle), BeverageType.Ale), + new FillableBvrge(1, typeof(BeverageBottle), BeverageType.Wine), + new FillableBvrge(1, typeof(BeverageBottle), BeverageType.Liquor), + new FillableBvrge(1, typeof(Jug), BeverageType.Cider) + } + ); + + public static FillableContent ThiefGuild = new FillableContent( + 1, + new[] + { + typeof(Thief), + typeof(ThiefGuildmaster) + }, + new[] + { + new FillableEntry(1, typeof(Lockpick)), + new FillableEntry(1, typeof(BearMask)), + new FillableEntry(1, typeof(DeerMask)), + new FillableEntry(1, typeof(TribalMask)), + new FillableEntry(1, typeof(HornedTribalMask)), + new FillableEntry(4, typeof(OrcHelm)) + } + ); + + public static FillableContent Tinker = new FillableContent( + 1, + new[] + { + typeof(Tinker), + typeof(TinkerGuildmaster) + }, + new[] + { + new FillableEntry(1, typeof(Lockpick)), + // new FillableEntry( 1, typeof( KeyRing ) ), + new FillableEntry(2, typeof(Clock)), + new FillableEntry(2, typeof(ClockParts)), + new FillableEntry(2, typeof(AxleGears)), + new FillableEntry(2, typeof(Gears)), + new FillableEntry(2, typeof(Hinge)), + // new FillableEntry( 1, typeof( ArrowShafts ) ), + new FillableEntry(2, typeof(Sextant)), + new FillableEntry(2, typeof(SextantParts)), + new FillableEntry(2, typeof(Axle)), + new FillableEntry(2, typeof(Springs)), + new FillableEntry(5, typeof(TinkerTools)), + new FillableEntry(4, typeof(Key)), + new FillableEntry(1, typeof(DecoArrowShafts)), + new FillableEntry(1, typeof(Lockpicks)), + new FillableEntry(1, typeof(ToolKit)) + } + ); + + public static FillableContent Veterinarian = new FillableContent( + 1, + new[] + { + typeof(Veterinarian) + }, + new[] + { + new FillableEntry(1, typeof(Bandage)), + new FillableEntry(1, typeof(MortarPestle)), + new FillableEntry(1, typeof(LesserHealPotion)), + // new FillableEntry( 1, typeof( Wheat ) ), + new FillableEntry(1, typeof(Carrot)) + } + ); + + public static FillableContent Weaponsmith = new FillableContent( + 2, + new[] + { + typeof(Weaponsmith) + }, + new[] + { + new FillableEntry(8, Loot.WeaponTypes), + new FillableEntry(1, typeof(Arrow)) + } + ); + + private static Dictionary m_AcquireTable; + + private static readonly FillableContent[] m_ContentTypes = + { + Weaponsmith, Provisioner, Mage, + Alchemist, Armorer, ArtisanGuild, + Baker, Bard, Blacksmith, + Bowyer, Butcher, Carpenter, + Clothier, Cobbler, Docks, + Farm, FighterGuild, Guard, + Healer, Herbalist, Inn, + Jeweler, Library, Merchant, + Mill, Mine, Observatory, + Painter, Ranger, Stables, + Tanner, Tavern, ThiefGuild, + Tinker, Veterinarian + }; + + private readonly FillableEntry[] m_Entries; + private readonly int m_Weight; + + public FillableContent(int level, Type[] vendors, FillableEntry[] entries) + { + Level = level; + Vendors = vendors; + m_Entries = entries; + + for (var i = 0; i < entries.Length; ++i) + m_Weight += entries[i].Weight; + } + + public int Level { get; } + + public Type[] Vendors { get; } + + public FillableContentType TypeID => Lookup(this); + + public virtual Item Construct() + { + var index = Utility.Random(m_Weight); + + for (var i = 0; i < m_Entries.Length; ++i) + { + var entry = m_Entries[i]; + + if (index < entry.Weight) + return entry.Construct(); + + index -= entry.Weight; + } + + return null; + } + + public static FillableContent Lookup(FillableContentType type) + { + var v = (int)type; + + if (v >= 0 && v < m_ContentTypes.Length) + return m_ContentTypes[v]; + + return null; + } + + public static FillableContentType Lookup(FillableContent content) + { + if (content == null) + return FillableContentType.None; + + return (FillableContentType)Array.IndexOf(m_ContentTypes, content); + } + + public static FillableContent Acquire(Point3D loc, Map map) + { + if (map == null || map == Map.Internal) + return null; + + if (m_AcquireTable == null) + { + m_AcquireTable = new Dictionary(); + + for (var i = 0; i < m_ContentTypes.Length; ++i) + { + var fill = m_ContentTypes[i]; + + for (var j = 0; j < fill.Vendors.Length; ++j) + m_AcquireTable[fill.Vendors[j]] = fill; + } + } + + Mobile nearest = null; + FillableContent content = null; + + foreach (var mob in map.GetMobilesInRange(loc, 20)) + { + if (nearest != null && mob.GetDistanceToSqrt(loc) > nearest.GetDistanceToSqrt(loc) && + !(nearest is Cobbler && mob is Provisioner)) + continue; + + if (m_AcquireTable.TryGetValue(mob.GetType(), out var check)) + { + nearest = mob; + content = check; + } + } + + return content; + } + } +} diff --git a/Projects/UOContent/Items/Containers/FurnitureContainer.cs b/Projects/UOContent/Items/Containers/FurnitureContainer.cs index c319d118d..5169dc43b 100644 --- a/Projects/UOContent/Items/Containers/FurnitureContainer.cs +++ b/Projects/UOContent/Items/Containers/FurnitureContainer.cs @@ -1,389 +1,389 @@ -using System; -using System.Collections.Generic; - -namespace Server.Items -{ - [Furniture] - [Flippable(0x2815, 0x2816)] - public class TallCabinet : BaseContainer - { - [Constructible] - public TallCabinet() : base(0x2815) => Weight = 1.0; - - public TallCabinet(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - [Furniture] - [Flippable(0x2817, 0x2818)] - public class ShortCabinet : BaseContainer - { - [Constructible] - public ShortCabinet() : base(0x2817) => Weight = 1.0; - - public ShortCabinet(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - [Furniture] - [Flippable(0x2857, 0x2858)] - public class RedArmoire : BaseContainer - { - [Constructible] - public RedArmoire() : base(0x2857) => Weight = 1.0; - - public RedArmoire(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - [Furniture] - [Flippable(0x285D, 0x285E)] - public class CherryArmoire : BaseContainer - { - [Constructible] - public CherryArmoire() : base(0x285D) => Weight = 1.0; - - public CherryArmoire(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - [Furniture] - [Flippable(0x285B, 0x285C)] - public class MapleArmoire : BaseContainer - { - [Constructible] - public MapleArmoire() : base(0x285B) => Weight = 1.0; - - public MapleArmoire(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - [Furniture] - [Flippable(0x2859, 0x285A)] - public class ElegantArmoire : BaseContainer - { - [Constructible] - public ElegantArmoire() : base(0x2859) => Weight = 1.0; - - public ElegantArmoire(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - [Furniture] - [Flippable(0xa97, 0xa99, 0xa98, 0xa9a, 0xa9b, 0xa9c)] - public class FullBookcase : BaseContainer - { - [Constructible] - public FullBookcase() : base(0xA97) => Weight = 1.0; - - public FullBookcase(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - [Furniture] - [Flippable(0xa9d, 0xa9e)] - public class EmptyBookcase : BaseContainer - { - [Constructible] - public EmptyBookcase() : base(0xA9D) - { - } - - public EmptyBookcase(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); - int version = reader.ReadInt(); - - if (version == 0 && Weight == 1.0) - Weight = -1; - } - } - - [Furniture] - [Flippable(0xa2c, 0xa34)] - public class Drawer : BaseContainer - { - [Constructible] - public Drawer() : base(0xA2C) => Weight = 1.0; - - public Drawer(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - [Furniture] - [Flippable(0xa30, 0xa38)] - public class FancyDrawer : BaseContainer - { - [Constructible] - public FancyDrawer() : base(0xA30) => Weight = 1.0; - - public FancyDrawer(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - [Furniture] - [Flippable(0xa4f, 0xa53)] - public class Armoire : BaseContainer - { - [Constructible] - public Armoire() : base(0xA4F) => Weight = 1.0; - - public Armoire(Serial serial) : base(serial) - { - } - - public override void DisplayTo(Mobile m) - { - if (DynamicFurniture.Open(this, m)) - base.DisplayTo(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - DynamicFurniture.Close(this); - } - } - - [Furniture] - [Flippable(0xa4d, 0xa51)] - public class FancyArmoire : BaseContainer - { - [Constructible] - public FancyArmoire() : base(0xA4D) => Weight = 1.0; - - public FancyArmoire(Serial serial) : base(serial) - { - } - - public override void DisplayTo(Mobile m) - { - if (DynamicFurniture.Open(this, m)) - base.DisplayTo(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - DynamicFurniture.Close(this); - } - } - - public class DynamicFurniture - { - private static readonly Dictionary m_Table = new Dictionary(); - - public static bool Open(Container c, Mobile m) - { - if (m_Table.ContainsKey(c)) - { - c.SendRemovePacket(); - Close(c); - c.Delta(ItemDelta.Update); - c.ProcessDelta(); - return false; - } - - if (c is Armoire || c is FancyArmoire) - { - Timer t = new FurnitureTimer(c, m); - t.Start(); - m_Table[c] = t; - - c.ItemID = c.ItemID switch - { - 0xA4D => 0xA4C, - 0xA4F => 0xA4E, - 0xA51 => 0xA50, - 0xA53 => 0xA52, - _ => c.ItemID - }; - } - - return true; - } - - public static void Close(Container c) - { - if (m_Table.TryGetValue(c, out Timer t)) - { - t.Stop(); - m_Table.Remove(c); - } - - if (c is Armoire || c is FancyArmoire) - c.ItemID = c.ItemID switch - { - 0xA4C => 0xA4D, - 0xA4E => 0xA4F, - 0xA50 => 0xA51, - 0xA52 => 0xA53, - _ => c.ItemID - }; - } - } - - public class FurnitureTimer : Timer - { - private readonly Container m_Container; - private readonly Mobile m_Mobile; - - public FurnitureTimer(Container c, Mobile m) : base(TimeSpan.FromSeconds(0.5), TimeSpan.FromSeconds(0.5)) - { - Priority = TimerPriority.TwoFiftyMS; - - m_Container = c; - m_Mobile = m; - } - - protected override void OnTick() - { - if (m_Mobile.Map != m_Container.Map || !m_Mobile.InRange(m_Container.GetWorldLocation(), 3)) - DynamicFurniture.Close(m_Container); - } - } -} +using System; +using System.Collections.Generic; + +namespace Server.Items +{ + [Furniture] + [Flippable(0x2815, 0x2816)] + public class TallCabinet : BaseContainer + { + [Constructible] + public TallCabinet() : base(0x2815) => Weight = 1.0; + + public TallCabinet(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Furniture] + [Flippable(0x2817, 0x2818)] + public class ShortCabinet : BaseContainer + { + [Constructible] + public ShortCabinet() : base(0x2817) => Weight = 1.0; + + public ShortCabinet(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Furniture] + [Flippable(0x2857, 0x2858)] + public class RedArmoire : BaseContainer + { + [Constructible] + public RedArmoire() : base(0x2857) => Weight = 1.0; + + public RedArmoire(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Furniture] + [Flippable(0x285D, 0x285E)] + public class CherryArmoire : BaseContainer + { + [Constructible] + public CherryArmoire() : base(0x285D) => Weight = 1.0; + + public CherryArmoire(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Furniture] + [Flippable(0x285B, 0x285C)] + public class MapleArmoire : BaseContainer + { + [Constructible] + public MapleArmoire() : base(0x285B) => Weight = 1.0; + + public MapleArmoire(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Furniture] + [Flippable(0x2859, 0x285A)] + public class ElegantArmoire : BaseContainer + { + [Constructible] + public ElegantArmoire() : base(0x2859) => Weight = 1.0; + + public ElegantArmoire(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Furniture] + [Flippable(0xa97, 0xa99, 0xa98, 0xa9a, 0xa9b, 0xa9c)] + public class FullBookcase : BaseContainer + { + [Constructible] + public FullBookcase() : base(0xA97) => Weight = 1.0; + + public FullBookcase(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Furniture] + [Flippable(0xa9d, 0xa9e)] + public class EmptyBookcase : BaseContainer + { + [Constructible] + public EmptyBookcase() : base(0xA9D) + { + } + + public EmptyBookcase(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 == 1.0) + Weight = -1; + } + } + + [Furniture] + [Flippable(0xa2c, 0xa34)] + public class Drawer : BaseContainer + { + [Constructible] + public Drawer() : base(0xA2C) => Weight = 1.0; + + public Drawer(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Furniture] + [Flippable(0xa30, 0xa38)] + public class FancyDrawer : BaseContainer + { + [Constructible] + public FancyDrawer() : base(0xA30) => Weight = 1.0; + + public FancyDrawer(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Furniture] + [Flippable(0xa4f, 0xa53)] + public class Armoire : BaseContainer + { + [Constructible] + public Armoire() : base(0xA4F) => Weight = 1.0; + + public Armoire(Serial serial) : base(serial) + { + } + + public override void DisplayTo(Mobile m) + { + if (DynamicFurniture.Open(this, m)) + base.DisplayTo(m); + } + + 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(); + + DynamicFurniture.Close(this); + } + } + + [Furniture] + [Flippable(0xa4d, 0xa51)] + public class FancyArmoire : BaseContainer + { + [Constructible] + public FancyArmoire() : base(0xA4D) => Weight = 1.0; + + public FancyArmoire(Serial serial) : base(serial) + { + } + + public override void DisplayTo(Mobile m) + { + if (DynamicFurniture.Open(this, m)) + base.DisplayTo(m); + } + + 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(); + + DynamicFurniture.Close(this); + } + } + + public class DynamicFurniture + { + private static readonly Dictionary m_Table = new Dictionary(); + + public static bool Open(Container c, Mobile m) + { + if (m_Table.ContainsKey(c)) + { + c.SendRemovePacket(); + Close(c); + c.Delta(ItemDelta.Update); + c.ProcessDelta(); + return false; + } + + if (c is Armoire || c is FancyArmoire) + { + Timer t = new FurnitureTimer(c, m); + t.Start(); + m_Table[c] = t; + + c.ItemID = c.ItemID switch + { + 0xA4D => 0xA4C, + 0xA4F => 0xA4E, + 0xA51 => 0xA50, + 0xA53 => 0xA52, + _ => c.ItemID + }; + } + + return true; + } + + public static void Close(Container c) + { + if (m_Table.TryGetValue(c, out var t)) + { + t.Stop(); + m_Table.Remove(c); + } + + if (c is Armoire || c is FancyArmoire) + c.ItemID = c.ItemID switch + { + 0xA4C => 0xA4D, + 0xA4E => 0xA4F, + 0xA50 => 0xA51, + 0xA52 => 0xA53, + _ => c.ItemID + }; + } + } + + public class FurnitureTimer : Timer + { + private readonly Container m_Container; + private readonly Mobile m_Mobile; + + public FurnitureTimer(Container c, Mobile m) : base(TimeSpan.FromSeconds(0.5), TimeSpan.FromSeconds(0.5)) + { + Priority = TimerPriority.TwoFiftyMS; + + m_Container = c; + m_Mobile = m; + } + + protected override void OnTick() + { + if (m_Mobile.Map != m_Container.Map || !m_Mobile.InRange(m_Container.GetWorldLocation(), 3)) + DynamicFurniture.Close(m_Container); + } + } +} diff --git a/Projects/UOContent/Items/Containers/LockableContainer.cs b/Projects/UOContent/Items/Containers/LockableContainer.cs index 20b70dec1..779962de9 100644 --- a/Projects/UOContent/Items/Containers/LockableContainer.cs +++ b/Projects/UOContent/Items/Containers/LockableContainer.cs @@ -1,318 +1,325 @@ -using System; -using Server.Engines.Craft; -using Server.Network; - -namespace Server.Items -{ - public abstract class LockableContainer : TrappableContainer, ILockable, ILockpickable, ICraftable, IShipwreckedItem - { - private bool m_Locked; - - public LockableContainer(int itemID) : base(itemID) => MaxLockLevel = 100; - - public LockableContainer(Serial serial) : base(serial) - { - } - - public override bool TrapOnOpen => !TrapOnLockpick; - - [CommandProperty(AccessLevel.GameMaster)] - public bool TrapOnLockpick { get; set; } - - public override bool DisplaysContent => !m_Locked; - - public int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, - CraftItem craftItem, int resHue) - { - if (from.CheckSkill(SkillName.Tinkering, -5.0, 15.0)) - { - from.SendLocalizedMessage(500636); // Your tinker skill was sufficient to make the item lockable. - - Key key = new Key(KeyType.Copper, Key.RandomValue()); - - KeyValue = key.KeyValue; - DropItem(key); - - double tinkering = from.Skills.Tinkering.Value; - int level = (int)(tinkering * 0.8); - - RequiredSkill = level - 4; - LockLevel = level - 14; - MaxLockLevel = level + 35; - - if (LockLevel == 0) - LockLevel = -1; - else if (LockLevel > 95) - LockLevel = 95; - - if (RequiredSkill > 95) - RequiredSkill = 95; - - if (MaxLockLevel > 95) - MaxLockLevel = 95; - } - else - { - from.SendLocalizedMessage(500637); // Your tinker skill was insufficient to make the item lockable. - } - - return 1; - } - - [CommandProperty(AccessLevel.GameMaster)] - public virtual bool Locked - { - get => m_Locked; - set - { - m_Locked = value; - - if (m_Locked) - Picker = null; - - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public uint KeyValue { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Picker { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxLockLevel { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int LockLevel { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int RequiredSkill { get; set; } - - public virtual void LockPick(Mobile from) - { - Locked = false; - Picker = from; - - if (TrapOnLockpick && ExecuteTrap(from)) TrapOnLockpick = false; - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsShipwreckedItem { get; set; } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(6); // version - - writer.Write(IsShipwreckedItem); - - writer.Write(TrapOnLockpick); - - writer.Write(RequiredSkill); - - writer.Write(MaxLockLevel); - - writer.Write(KeyValue); - writer.Write(LockLevel); - writer.Write(m_Locked); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 6: - { - IsShipwreckedItem = reader.ReadBool(); - - goto case 5; - } - case 5: - { - TrapOnLockpick = reader.ReadBool(); - - goto case 4; - } - case 4: - { - RequiredSkill = reader.ReadInt(); - - goto case 3; - } - case 3: - { - MaxLockLevel = reader.ReadInt(); - - goto case 2; - } - case 2: - { - KeyValue = reader.ReadUInt(); - - goto case 1; - } - case 1: - { - LockLevel = reader.ReadInt(); - - goto case 0; - } - case 0: - { - if (version < 3) - MaxLockLevel = 100; - - if (version < 4) - { - if (MaxLockLevel - LockLevel == 40) - { - RequiredSkill = LockLevel + 6; - LockLevel = RequiredSkill - 10; - MaxLockLevel = RequiredSkill + 39; - } - else - { - RequiredSkill = LockLevel; - } - } - - m_Locked = reader.ReadBool(); - - break; - } - } - } - - public override bool CheckContentDisplay(Mobile from) => !m_Locked && base.CheckContentDisplay(from); - - public override bool TryDropItem(Mobile from, Item dropped, bool sendFullMessage) - { - if (from.AccessLevel < AccessLevel.GameMaster && m_Locked) - { - from.SendLocalizedMessage(501747); // It appears to be locked. - return false; - } - - return base.TryDropItem(from, dropped, sendFullMessage); - } - - public override bool OnDragDropInto(Mobile from, Item item, Point3D p) - { - if (from.AccessLevel < AccessLevel.GameMaster && m_Locked) - { - from.SendLocalizedMessage(501747); // It appears to be locked. - return false; - } - - return base.OnDragDropInto(from, item, p); - } - - public override bool CheckLift(Mobile from, Item item, ref LRReason reject) - { - if (!base.CheckLift(from, item, ref reject)) - return false; - - if (item != this && from.AccessLevel < AccessLevel.GameMaster && m_Locked) - return false; - - return true; - } - - public override bool CheckItemUse(Mobile from, Item item) - { - if (!base.CheckItemUse(from, item)) - return false; - - if (item != this && from.AccessLevel < AccessLevel.GameMaster && m_Locked) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return false; - } - - return true; - } - - public virtual bool CheckLocked(Mobile from) - { - bool inaccessible = false; - - if (m_Locked) - { - int number; - - if (from.AccessLevel >= AccessLevel.GameMaster) - { - number = 502502; // That is locked, but you open it with your godly powers. - } - else - { - number = 501747; // It appears to be locked. - inaccessible = true; - } - - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, 0x3B2, 3, number, "", "")); - } - - return inaccessible; - } - - public override void OnTelekinesis(Mobile from) - { - if (CheckLocked(from)) - { - Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x376A, 9, 32, - 5022); - Effects.PlaySound(Location, Map, 0x1F5); - return; - } - - base.OnTelekinesis(from); - } - - public override void OnDoubleClickSecureTrade(Mobile from) - { - if (CheckLocked(from)) - return; - - base.OnDoubleClickSecureTrade(from); - } - - public override void Open(Mobile from) - { - if (CheckLocked(from)) - return; - - base.Open(from); - } - - public override void OnSnoop(Mobile from) - { - if (CheckLocked(from)) - return; - - base.OnSnoop(from); - } - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - if (IsShipwreckedItem) - list.Add(1041645); // recovered from a shipwreck - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - if (IsShipwreckedItem) - LabelTo(from, 1041645); // recovered from a shipwreck - } - } -} \ No newline at end of file +using System; +using Server.Engines.Craft; +using Server.Network; + +namespace Server.Items +{ + public abstract class LockableContainer : TrappableContainer, ILockable, ILockpickable, ICraftable, IShipwreckedItem + { + private bool m_Locked; + + public LockableContainer(int itemID) : base(itemID) => MaxLockLevel = 100; + + public LockableContainer(Serial serial) : base(serial) + { + } + + public override bool TrapOnOpen => !TrapOnLockpick; + + [CommandProperty(AccessLevel.GameMaster)] + public bool TrapOnLockpick { get; set; } + + public override bool DisplaysContent => !m_Locked; + + public int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, + CraftItem craftItem, int resHue + ) + { + if (from.CheckSkill(SkillName.Tinkering, -5.0, 15.0)) + { + from.SendLocalizedMessage(500636); // Your tinker skill was sufficient to make the item lockable. + + var key = new Key(KeyType.Copper, Key.RandomValue()); + + KeyValue = key.KeyValue; + DropItem(key); + + var tinkering = from.Skills.Tinkering.Value; + var level = (int)(tinkering * 0.8); + + RequiredSkill = level - 4; + LockLevel = level - 14; + MaxLockLevel = level + 35; + + if (LockLevel == 0) + LockLevel = -1; + else if (LockLevel > 95) + LockLevel = 95; + + if (RequiredSkill > 95) + RequiredSkill = 95; + + if (MaxLockLevel > 95) + MaxLockLevel = 95; + } + else + { + from.SendLocalizedMessage(500637); // Your tinker skill was insufficient to make the item lockable. + } + + return 1; + } + + [CommandProperty(AccessLevel.GameMaster)] + public virtual bool Locked + { + get => m_Locked; + set + { + m_Locked = value; + + if (m_Locked) + Picker = null; + + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public uint KeyValue { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Picker { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxLockLevel { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int LockLevel { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int RequiredSkill { get; set; } + + public virtual void LockPick(Mobile from) + { + Locked = false; + Picker = from; + + if (TrapOnLockpick && ExecuteTrap(from)) TrapOnLockpick = false; + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsShipwreckedItem { get; set; } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(6); // version + + writer.Write(IsShipwreckedItem); + + writer.Write(TrapOnLockpick); + + writer.Write(RequiredSkill); + + writer.Write(MaxLockLevel); + + writer.Write(KeyValue); + writer.Write(LockLevel); + writer.Write(m_Locked); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 6: + { + IsShipwreckedItem = reader.ReadBool(); + + goto case 5; + } + case 5: + { + TrapOnLockpick = reader.ReadBool(); + + goto case 4; + } + case 4: + { + RequiredSkill = reader.ReadInt(); + + goto case 3; + } + case 3: + { + MaxLockLevel = reader.ReadInt(); + + goto case 2; + } + case 2: + { + KeyValue = reader.ReadUInt(); + + goto case 1; + } + case 1: + { + LockLevel = reader.ReadInt(); + + goto case 0; + } + case 0: + { + if (version < 3) + MaxLockLevel = 100; + + if (version < 4) + { + if (MaxLockLevel - LockLevel == 40) + { + RequiredSkill = LockLevel + 6; + LockLevel = RequiredSkill - 10; + MaxLockLevel = RequiredSkill + 39; + } + else + { + RequiredSkill = LockLevel; + } + } + + m_Locked = reader.ReadBool(); + + break; + } + } + } + + public override bool CheckContentDisplay(Mobile from) => !m_Locked && base.CheckContentDisplay(from); + + public override bool TryDropItem(Mobile from, Item dropped, bool sendFullMessage) + { + if (from.AccessLevel < AccessLevel.GameMaster && m_Locked) + { + from.SendLocalizedMessage(501747); // It appears to be locked. + return false; + } + + return base.TryDropItem(from, dropped, sendFullMessage); + } + + public override bool OnDragDropInto(Mobile from, Item item, Point3D p) + { + if (from.AccessLevel < AccessLevel.GameMaster && m_Locked) + { + from.SendLocalizedMessage(501747); // It appears to be locked. + return false; + } + + return base.OnDragDropInto(from, item, p); + } + + public override bool CheckLift(Mobile from, Item item, ref LRReason reject) + { + if (!base.CheckLift(from, item, ref reject)) + return false; + + if (item != this && from.AccessLevel < AccessLevel.GameMaster && m_Locked) + return false; + + return true; + } + + public override bool CheckItemUse(Mobile from, Item item) + { + if (!base.CheckItemUse(from, item)) + return false; + + if (item != this && from.AccessLevel < AccessLevel.GameMaster && m_Locked) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return false; + } + + return true; + } + + public virtual bool CheckLocked(Mobile from) + { + var inaccessible = false; + + if (m_Locked) + { + int number; + + if (from.AccessLevel >= AccessLevel.GameMaster) + { + number = 502502; // That is locked, but you open it with your godly powers. + } + else + { + number = 501747; // It appears to be locked. + inaccessible = true; + } + + from.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, 0x3B2, 3, number, "", "")); + } + + return inaccessible; + } + + public override void OnTelekinesis(Mobile from) + { + if (CheckLocked(from)) + { + Effects.SendLocationParticles( + EffectItem.Create(Location, Map, EffectItem.DefaultDuration), + 0x376A, + 9, + 32, + 5022 + ); + Effects.PlaySound(Location, Map, 0x1F5); + return; + } + + base.OnTelekinesis(from); + } + + public override void OnDoubleClickSecureTrade(Mobile from) + { + if (CheckLocked(from)) + return; + + base.OnDoubleClickSecureTrade(from); + } + + public override void Open(Mobile from) + { + if (CheckLocked(from)) + return; + + base.Open(from); + } + + public override void OnSnoop(Mobile from) + { + if (CheckLocked(from)) + return; + + base.OnSnoop(from); + } + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + if (IsShipwreckedItem) + list.Add(1041645); // recovered from a shipwreck + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + if (IsShipwreckedItem) + LabelTo(from, 1041645); // recovered from a shipwreck + } + } +} diff --git a/Projects/UOContent/Items/Containers/MarkContainer.cs b/Projects/UOContent/Items/Containers/MarkContainer.cs index d4dd66cf1..0aa4f495b 100644 --- a/Projects/UOContent/Items/Containers/MarkContainer.cs +++ b/Projects/UOContent/Items/Containers/MarkContainer.cs @@ -1,231 +1,233 @@ -using System; -using System.Linq; - -namespace Server.Items -{ - public class MarkContainer : LockableContainer - { - private bool m_AutoLock; - private InternalTimer m_RelockTimer; - - [Constructible] - public MarkContainer(bool bone = false, bool locked = false) : base(bone ? 0xECA : 0xE79) - { - Movable = false; - - if (bone) - Hue = 1102; - - m_AutoLock = locked; - Locked = locked; - - if (locked) - LockLevel = -255; - } - - public MarkContainer(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool AutoLock - { - get => m_AutoLock; - set - { - m_AutoLock = value; - - if (!m_AutoLock) - StopTimer(); - else if (!Locked && m_RelockTimer == null) - m_RelockTimer = new InternalTimer(this); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Map TargetMap { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D Target { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Bone - { - get => ItemID == 0xECA; - set - { - ItemID = value ? 0xECA : 0xE79; - Hue = value ? 1102 : 0; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public string Description { get; set; } - - public override bool IsDecoContainer => false; - - [CommandProperty(AccessLevel.GameMaster)] - public override bool Locked - { - get => base.Locked; - set - { - base.Locked = value; - - if (m_AutoLock) - { - StopTimer(); - - if (!Locked) - m_RelockTimer = new InternalTimer(this); - } - } - } - - public static void Initialize() - { - CommandSystem.Register("SecretLocGen", AccessLevel.Administrator, SecretLocGen_OnCommand); - } - - [Usage("SecretLocGen")] - [Description("Generates mark containers to Malas secret locations.")] - public static void SecretLocGen_OnCommand(CommandEventArgs e) - { - CreateMalasPassage(951, 546, -70, 1006, 994, -70, false, false); - CreateMalasPassage(914, 192, -79, 1019, 1062, -70, false, false); - CreateMalasPassage(1614, 143, -90, 1214, 1313, -90, false, false); - CreateMalasPassage(2176, 324, -90, 1554, 172, -90, false, false); - CreateMalasPassage(864, 812, -90, 1061, 1161, -70, false, false); - CreateMalasPassage(1051, 1434, -85, 1076, 1244, -70, false, true); - CreateMalasPassage(1326, 523, -87, 1201, 1554, -70, false, false); - CreateMalasPassage(424, 189, -1, 2333, 1501, -90, true, false); - CreateMalasPassage(1313, 1115, -85, 1183, 462, -45, false, false); - - e.Mobile.SendMessage("Secret mark containers have been created."); - } - - private static bool FindMarkContainer(Point3D p, Map map) - { - IPooledEnumerable eable = map.GetItemsInRange(p, 0); - bool found = eable.Any(item => item.Z == p.Z); - eable.Free(); - - return found; - } - - private static void CreateMalasPassage(int x, int y, int z, int xTarget, int yTarget, int zTarget, bool bone, - bool locked) - { - Point3D location = new Point3D(x, y, z); - - if (FindMarkContainer(location, Map.Malas)) - return; - - MarkContainer cont = new MarkContainer(bone, locked) - { - TargetMap = Map.Malas, - Target = new Point3D(xTarget, yTarget, zTarget), - Description = "strange location" - }; - - cont.MoveToWorld(location, Map.Malas); - } - - public void StopTimer() - { - m_RelockTimer?.Stop(); - m_RelockTimer = null; - } - - public void Mark(RecallRune rune) - { - if (TargetMap != null) - { - rune.Marked = true; - rune.TargetMap = TargetMap; - rune.Target = Target; - rune.Description = Description; - rune.House = null; - } - } - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (dropped is RecallRune rune && base.OnDragDrop(from, dropped)) - { - Mark(rune); - return true; - } - - return false; - } - - public override bool OnDragDropInto(Mobile from, Item dropped, Point3D p) - { - if (dropped is RecallRune rune && base.OnDragDropInto(from, dropped, p)) - { - Mark(rune); - return true; - } - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_AutoLock); - - if (!Locked && m_AutoLock) - writer.WriteDeltaTime(m_RelockTimer.RelockTime); - - writer.Write(TargetMap); - writer.Write(Target); - writer.Write(Description); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_AutoLock = reader.ReadBool(); - - if (!Locked && m_AutoLock) - m_RelockTimer = new InternalTimer(this, reader.ReadDeltaTime() - DateTime.UtcNow); - - TargetMap = reader.ReadMap(); - Target = reader.ReadPoint3D(); - Description = reader.ReadString(); - } - - private class InternalTimer : Timer - { - public InternalTimer(MarkContainer container) : this(container, TimeSpan.FromMinutes(5.0)) - { - } - - public InternalTimer(MarkContainer container, TimeSpan delay) : base(delay) - { - Container = container; - RelockTime = DateTime.UtcNow + delay; - - Start(); - } - - public MarkContainer Container { get; } - - public DateTime RelockTime { get; } - - protected override void OnTick() - { - Container.Locked = true; - Container.LockLevel = -255; - } - } - } -} +using System; +using System.Linq; + +namespace Server.Items +{ + public class MarkContainer : LockableContainer + { + private bool m_AutoLock; + private InternalTimer m_RelockTimer; + + [Constructible] + public MarkContainer(bool bone = false, bool locked = false) : base(bone ? 0xECA : 0xE79) + { + Movable = false; + + if (bone) + Hue = 1102; + + m_AutoLock = locked; + Locked = locked; + + if (locked) + LockLevel = -255; + } + + public MarkContainer(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool AutoLock + { + get => m_AutoLock; + set + { + m_AutoLock = value; + + if (!m_AutoLock) + StopTimer(); + else if (!Locked && m_RelockTimer == null) + m_RelockTimer = new InternalTimer(this); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Map TargetMap { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D Target { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Bone + { + get => ItemID == 0xECA; + set + { + ItemID = value ? 0xECA : 0xE79; + Hue = value ? 1102 : 0; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public string Description { get; set; } + + public override bool IsDecoContainer => false; + + [CommandProperty(AccessLevel.GameMaster)] + public override bool Locked + { + get => base.Locked; + set + { + base.Locked = value; + + if (m_AutoLock) + { + StopTimer(); + + if (!Locked) + m_RelockTimer = new InternalTimer(this); + } + } + } + + public static void Initialize() + { + CommandSystem.Register("SecretLocGen", AccessLevel.Administrator, SecretLocGen_OnCommand); + } + + [Usage("SecretLocGen")] + [Description("Generates mark containers to Malas secret locations.")] + public static void SecretLocGen_OnCommand(CommandEventArgs e) + { + CreateMalasPassage(951, 546, -70, 1006, 994, -70, false, false); + CreateMalasPassage(914, 192, -79, 1019, 1062, -70, false, false); + CreateMalasPassage(1614, 143, -90, 1214, 1313, -90, false, false); + CreateMalasPassage(2176, 324, -90, 1554, 172, -90, false, false); + CreateMalasPassage(864, 812, -90, 1061, 1161, -70, false, false); + CreateMalasPassage(1051, 1434, -85, 1076, 1244, -70, false, true); + CreateMalasPassage(1326, 523, -87, 1201, 1554, -70, false, false); + CreateMalasPassage(424, 189, -1, 2333, 1501, -90, true, false); + CreateMalasPassage(1313, 1115, -85, 1183, 462, -45, false, false); + + e.Mobile.SendMessage("Secret mark containers have been created."); + } + + private static bool FindMarkContainer(Point3D p, Map map) + { + var eable = map.GetItemsInRange(p, 0); + var found = eable.Any(item => item.Z == p.Z); + eable.Free(); + + return found; + } + + private static void CreateMalasPassage( + int x, int y, int z, int xTarget, int yTarget, int zTarget, bool bone, + bool locked + ) + { + var location = new Point3D(x, y, z); + + if (FindMarkContainer(location, Map.Malas)) + return; + + var cont = new MarkContainer(bone, locked) + { + TargetMap = Map.Malas, + Target = new Point3D(xTarget, yTarget, zTarget), + Description = "strange location" + }; + + cont.MoveToWorld(location, Map.Malas); + } + + public void StopTimer() + { + m_RelockTimer?.Stop(); + m_RelockTimer = null; + } + + public void Mark(RecallRune rune) + { + if (TargetMap != null) + { + rune.Marked = true; + rune.TargetMap = TargetMap; + rune.Target = Target; + rune.Description = Description; + rune.House = null; + } + } + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (dropped is RecallRune rune && base.OnDragDrop(from, dropped)) + { + Mark(rune); + return true; + } + + return false; + } + + public override bool OnDragDropInto(Mobile from, Item dropped, Point3D p) + { + if (dropped is RecallRune rune && base.OnDragDropInto(from, dropped, p)) + { + Mark(rune); + return true; + } + + return false; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_AutoLock); + + if (!Locked && m_AutoLock) + writer.WriteDeltaTime(m_RelockTimer.RelockTime); + + writer.Write(TargetMap); + writer.Write(Target); + writer.Write(Description); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_AutoLock = reader.ReadBool(); + + if (!Locked && m_AutoLock) + m_RelockTimer = new InternalTimer(this, reader.ReadDeltaTime() - DateTime.UtcNow); + + TargetMap = reader.ReadMap(); + Target = reader.ReadPoint3D(); + Description = reader.ReadString(); + } + + private class InternalTimer : Timer + { + public InternalTimer(MarkContainer container) : this(container, TimeSpan.FromMinutes(5.0)) + { + } + + public InternalTimer(MarkContainer container, TimeSpan delay) : base(delay) + { + Container = container; + RelockTime = DateTime.UtcNow + delay; + + Start(); + } + + public MarkContainer Container { get; } + + public DateTime RelockTime { get; } + + protected override void OnTick() + { + Container.Locked = true; + Container.LockLevel = -255; + } + } + } +} diff --git a/Projects/UOContent/Items/Containers/ParagonChest.cs b/Projects/UOContent/Items/Containers/ParagonChest.cs index 112d2ad92..1758d3b6a 100644 --- a/Projects/UOContent/Items/Containers/ParagonChest.cs +++ b/Projects/UOContent/Items/Containers/ParagonChest.cs @@ -1,210 +1,210 @@ -namespace Server.Items -{ - [Flippable] - public class ParagonChest : LockableContainer - { - private static readonly int[] m_ItemIDs = - { - 0x9AB, 0xE40, 0xE41, 0xE7C - }; - - private static readonly int[] m_Hues = - { - 0x0, 0x455, 0x47E, 0x89F, 0x8A5, 0x8AB, - 0x966, 0x96D, 0x972, 0x973, 0x979 - }; - - private string m_Name; - - [Constructible] - public ParagonChest(string name, int level) : base(m_ItemIDs.RandomElement()) - { - m_Name = name; - Hue = m_Hues.RandomElement(); - Fill(level); - } - - public ParagonChest(Serial serial) : base(serial) - { - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - LabelTo(from, 1063449, m_Name); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1063449, m_Name); - } - - private static void GetRandomAOSStats(out int attributeCount, out int min, out int max) - { - int rnd = Utility.Random(15); - - if (rnd < 1) - { - attributeCount = Utility.RandomMinMax(2, 6); - min = 20; - max = 70; - } - else if (rnd < 3) - { - attributeCount = Utility.RandomMinMax(2, 4); - min = 20; - max = 50; - } - else if (rnd < 6) - { - attributeCount = Utility.RandomMinMax(2, 3); - min = 20; - max = 40; - } - else if (rnd < 10) - { - attributeCount = Utility.RandomMinMax(1, 2); - min = 10; - max = 30; - } - else - { - attributeCount = 1; - min = 10; - max = 20; - } - } - - public void Flip() - { - ItemID = ItemID switch - { - 0x9AB => 0xE7C, - 0xE7C => 0x9AB, - 0xE40 => 0xE41, - 0xE41 => 0xE40, - _ => ItemID - }; - } - - private void Fill(int level) - { - TrapType = TrapType.ExplosionTrap; - TrapPower = level * 25; - TrapLevel = level; - Locked = true; - - RequiredSkill = level switch - { - 1 => 36, - 2 => 76, - 3 => 84, - 4 => 92, - 5 => 100, - _ => RequiredSkill - }; - - LockLevel = RequiredSkill - 10; - MaxLockLevel = RequiredSkill + 40; - - DropItem(new Gold(level * 200)); - - for (int i = 0; i < level; ++i) - DropItem(Loot.RandomScroll(0, 63, SpellbookType.Regular)); - - for (int i = 0; i < level * 2; ++i) - { - Item item; - - if (Core.AOS) - item = Loot.RandomArmorOrShieldOrWeaponOrJewelry(); - else - item = Loot.RandomArmorOrShieldOrWeapon(); - - if (item is BaseWeapon weapon) - { - if (Core.AOS) - { - GetRandomAOSStats(out int attributeCount, out int min, out int max); - BaseRunicTool.ApplyAttributesTo(weapon, attributeCount, min, max); - } - else - { - weapon.DamageLevel = (WeaponDamageLevel)Utility.Random(6); - weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random(6); - weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random(6); - } - - DropItem(weapon); - } - else if (item is BaseArmor armor) - { - if (Core.AOS) - { - GetRandomAOSStats(out int attributeCount, out int min, out int max); - BaseRunicTool.ApplyAttributesTo(armor, attributeCount, min, max); - } - else - { - armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(6); - armor.Durability = (ArmorDurabilityLevel)Utility.Random(6); - } - - DropItem(armor); - } - else if (item is BaseHat hat) - { - if (Core.AOS) - { - GetRandomAOSStats(out int attributeCount, out int min, out int max); - BaseRunicTool.ApplyAttributesTo(hat, attributeCount, min, max); - } - - DropItem(hat); - } - else if (item is BaseJewel jewel) - { - GetRandomAOSStats(out int attributeCount, out int min, out int max); - BaseRunicTool.ApplyAttributesTo(jewel, attributeCount, min, max); - - DropItem(jewel); - } - } - - for (int i = 0; i < level; i++) - { - Item item = Loot.RandomPossibleReagent(); - item.Amount = Utility.RandomMinMax(40, 60); - DropItem(item); - } - - for (int i = 0; i < level; i++) - { - Item item = Loot.RandomGem(); - DropItem(item); - } - - DropItem(new TreasureMap(level + 1, Utility.RandomBool() ? Map.Felucca : Map.Trammel)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Name); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Name = Utility.Intern(reader.ReadString()); - } - } -} +namespace Server.Items +{ + [Flippable] + public class ParagonChest : LockableContainer + { + private static readonly int[] m_ItemIDs = + { + 0x9AB, 0xE40, 0xE41, 0xE7C + }; + + private static readonly int[] m_Hues = + { + 0x0, 0x455, 0x47E, 0x89F, 0x8A5, 0x8AB, + 0x966, 0x96D, 0x972, 0x973, 0x979 + }; + + private string m_Name; + + [Constructible] + public ParagonChest(string name, int level) : base(m_ItemIDs.RandomElement()) + { + m_Name = name; + Hue = m_Hues.RandomElement(); + Fill(level); + } + + public ParagonChest(Serial serial) : base(serial) + { + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + LabelTo(from, 1063449, m_Name); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1063449, m_Name); + } + + private static void GetRandomAOSStats(out int attributeCount, out int min, out int max) + { + var rnd = Utility.Random(15); + + if (rnd < 1) + { + attributeCount = Utility.RandomMinMax(2, 6); + min = 20; + max = 70; + } + else if (rnd < 3) + { + attributeCount = Utility.RandomMinMax(2, 4); + min = 20; + max = 50; + } + else if (rnd < 6) + { + attributeCount = Utility.RandomMinMax(2, 3); + min = 20; + max = 40; + } + else if (rnd < 10) + { + attributeCount = Utility.RandomMinMax(1, 2); + min = 10; + max = 30; + } + else + { + attributeCount = 1; + min = 10; + max = 20; + } + } + + public void Flip() + { + ItemID = ItemID switch + { + 0x9AB => 0xE7C, + 0xE7C => 0x9AB, + 0xE40 => 0xE41, + 0xE41 => 0xE40, + _ => ItemID + }; + } + + private void Fill(int level) + { + TrapType = TrapType.ExplosionTrap; + TrapPower = level * 25; + TrapLevel = level; + Locked = true; + + RequiredSkill = level switch + { + 1 => 36, + 2 => 76, + 3 => 84, + 4 => 92, + 5 => 100, + _ => RequiredSkill + }; + + LockLevel = RequiredSkill - 10; + MaxLockLevel = RequiredSkill + 40; + + DropItem(new Gold(level * 200)); + + for (var i = 0; i < level; ++i) + DropItem(Loot.RandomScroll(0, 63, SpellbookType.Regular)); + + for (var i = 0; i < level * 2; ++i) + { + Item item; + + if (Core.AOS) + item = Loot.RandomArmorOrShieldOrWeaponOrJewelry(); + else + item = Loot.RandomArmorOrShieldOrWeapon(); + + if (item is BaseWeapon weapon) + { + if (Core.AOS) + { + GetRandomAOSStats(out var attributeCount, out var min, out var max); + BaseRunicTool.ApplyAttributesTo(weapon, attributeCount, min, max); + } + else + { + weapon.DamageLevel = (WeaponDamageLevel)Utility.Random(6); + weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random(6); + weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random(6); + } + + DropItem(weapon); + } + else if (item is BaseArmor armor) + { + if (Core.AOS) + { + GetRandomAOSStats(out var attributeCount, out var min, out var max); + BaseRunicTool.ApplyAttributesTo(armor, attributeCount, min, max); + } + else + { + armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(6); + armor.Durability = (ArmorDurabilityLevel)Utility.Random(6); + } + + DropItem(armor); + } + else if (item is BaseHat hat) + { + if (Core.AOS) + { + GetRandomAOSStats(out var attributeCount, out var min, out var max); + BaseRunicTool.ApplyAttributesTo(hat, attributeCount, min, max); + } + + DropItem(hat); + } + else if (item is BaseJewel jewel) + { + GetRandomAOSStats(out var attributeCount, out var min, out var max); + BaseRunicTool.ApplyAttributesTo(jewel, attributeCount, min, max); + + DropItem(jewel); + } + } + + for (var i = 0; i < level; i++) + { + var item = Loot.RandomPossibleReagent(); + item.Amount = Utility.RandomMinMax(40, 60); + DropItem(item); + } + + for (var i = 0; i < level; i++) + { + var item = Loot.RandomGem(); + DropItem(item); + } + + DropItem(new TreasureMap(level + 1, Utility.RandomBool() ? Map.Felucca : Map.Trammel)); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Name); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Name = Utility.Intern(reader.ReadString()); + } + } +} diff --git a/Projects/UOContent/Items/Containers/SalvageBag.cs b/Projects/UOContent/Items/Containers/SalvageBag.cs index 280c02cf8..f04fe34e7 100644 --- a/Projects/UOContent/Items/Containers/SalvageBag.cs +++ b/Projects/UOContent/Items/Containers/SalvageBag.cs @@ -1,340 +1,347 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Server.ContextMenus; -using Server.Engines.Craft; -using Server.Network; -using Server.Utilities; - -namespace Server.Items -{ - public class SalvageBag : Bag - { - private bool m_Failure; - - [Constructible] - public SalvageBag() - : this(Utility.RandomBlueHue()) - { - } - - [Constructible] - public SalvageBag(int hue) - { - Weight = 2.0; - Hue = hue; - m_Failure = false; - } - - public override int LabelNumber => 1079931; // Salvage Bag - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (from.Alive) - { - list.Add(new SalvageIngotsEntry(this, IsChildOf(from.Backpack) && Resmeltables())); - list.Add(new SalvageClothEntry(this, IsChildOf(from.Backpack) && Scissorables())); - list.Add(new SalvageAllEntry(this, IsChildOf(from.Backpack) && Resmeltables() && Scissorables())); - } - } - - private bool Resmelt(Mobile from, Item item, CraftResource resource) - { - try - { - if (CraftResources.GetType(resource) != CraftResourceType.Metal) - return false; - - CraftResourceInfo info = CraftResources.GetInfo(resource); - - if (info == null || info.ResourceTypes.Length == 0) - return false; - - CraftItem craftItem = DefBlacksmithy.CraftSystem.CraftItems.SearchFor(item.GetType()); - - if (craftItem == null || craftItem.Resources.Count == 0) - return false; - - CraftRes craftResource = craftItem.Resources[0]; - - if (craftResource.Amount < 2) - return false; // Not enough metal to resmelt - - var difficulty = resource switch - { - CraftResource.DullCopper => 65.0, - CraftResource.ShadowIron => 70.0, - CraftResource.Copper => 75.0, - CraftResource.Bronze => 80.0, - CraftResource.Gold => 85.0, - CraftResource.Agapite => 90.0, - CraftResource.Verite => 95.0, - CraftResource.Valorite => 99.0, - _ => 0.0 - }; - - Type resourceType = info.ResourceTypes[0]; - Item ingot = (Item)ActivatorUtil.CreateInstance(resourceType); - - if (item is DragonBardingDeed || (item is BaseArmor armor && armor.PlayerConstructed) || - (item is BaseWeapon weapon && weapon.PlayerConstructed) || - (item is BaseClothing clothing && clothing.PlayerConstructed)) - { - double mining = from.Skills.Mining.Value; - if (mining > 100.0) - mining = 100.0; - double amount = ((4 + mining) * craftResource.Amount - 4) * 0.0068; - if (amount < 2) - ingot.Amount = 2; - else - ingot.Amount = (int)amount; - } - else - { - ingot.Amount = 2; - } - - if (difficulty > from.Skills.Mining.Value) - { - m_Failure = true; - ingot.Delete(); - } - else - { - item.Delete(); - } - - from.AddToBackpack(ingot); - - from.PlaySound(0x2A); - from.PlaySound(0x240); - - return true; - } - catch (Exception ex) - { - Console.WriteLine(ex.ToString()); - } - - return false; - } - - private bool Resmeltables() // Where context menu checks for metal items and dragon barding deeds - { - foreach (Item i in Items) - return i?.Deleted == false && ( - (i is BaseWeapon weapon && CraftResources.GetType(weapon.Resource) == CraftResourceType.Metal) || - (i is BaseArmor armor && CraftResources.GetType(armor.Resource) == CraftResourceType.Metal) || - i is DragonBardingDeed); - - return false; - } - - private bool Scissorables() // Where context menu checks for Leather items and cloth items - { - foreach (Item i in Items) - { - if (!(i is IScissorable) || i.Deleted) - continue; - - if (i is BaseClothing || i is Cloth || i is BoltOfCloth || i is Hides || i is BonePile || - (i is BaseArmor armor && CraftResources.GetType(armor.Resource) == CraftResourceType.Leather)) - return true; - } - - return false; - } - - private void SalvageIngots(Mobile from) - { - if (from.Backpack.FindItemsByType().All(tool => tool.CraftSystem != DefBlacksmithy.CraftSystem)) - { - from.SendLocalizedMessage(1079822); // You need a blacksmithing tool in order to salvage ingots. - return; - } - - DefBlacksmithy.CheckAnvilAndForge(from, 2, out _, out bool forge); - - if (!forge) - { - from.SendLocalizedMessage(1044265); // You must be near a forge. - return; - } - - int salvaged = 0; - int notSalvaged = 0; - - Container sBag = this; - - List smeltables = sBag.FindItemsByType(); - - foreach (Item item in smeltables) - { - if (item?.Deleted != false) - continue; - - if ((item is BaseArmor armor && Resmelt(from, armor, armor.Resource)) || - (item is BaseWeapon weapon && Resmelt(from, weapon, weapon.Resource)) || - item is DragonBardingDeed) - salvaged++; - else - notSalvaged++; - } - - if (m_Failure) - { - from.SendLocalizedMessage(1079975); // You failed to smelt some metal for lack of skill. - m_Failure = false; - } - else - { - from.SendLocalizedMessage(1079973, - $"{salvaged}\t{salvaged + notSalvaged}"); // Salvaged: ~1_COUNT~/~2_NUM~ blacksmithed items - } - } - - private void SalvageCloth(Mobile from) - { - Scissors scissors = from.Backpack.FindItemByType(); - - if (scissors == null) - { - from.SendLocalizedMessage(1079823); // You need scissors in order to salvage cloth. - return; - } - - int salvaged = 0; - int notSalvaged = 0; - - Container sBag = this; - - List scissorables = sBag.FindItemsByType(); - - for (int i = scissorables.Count - 1; i >= 0; --i) - { - Item item = scissorables[i]; - - if (!(item is IScissorable scissorable)) - continue; - - if (Scissors.CanScissor(from, scissorable) && scissorable.Scissor(from, scissors)) - ++salvaged; - else - ++notSalvaged; - } - - from.SendLocalizedMessage(1079974, - $"{salvaged}\t{salvaged + notSalvaged}"); // Salvaged: ~1_COUNT~/~2_NUM~ tailored items - - Item[] items = FindItemsByType(new[]{ - typeof(Leather), typeof(Cloth), typeof(SpinedLeather), typeof(HornedLeather), typeof(BarbedLeather), - typeof(Bandage), typeof(Bone) - }); - - for (int i = 0; i < items.Length; i++) from.AddToBackpack(items[i]); - } - - private void SalvageAll(Mobile from) - { - SalvageIngots(from); - - SalvageCloth(from); - } - - private class SalvageAllEntry : ContextMenuEntry - { - private readonly SalvageBag m_Bag; - - public SalvageAllEntry(SalvageBag bag, bool enabled) - : base(6276) - { - m_Bag = bag; - - if (!enabled) - Flags |= CMEFlags.Disabled; - } - - public override void OnClick() - { - if (m_Bag.Deleted) - return; - - Mobile from = Owner.From; - - if (from.CheckAlive()) - m_Bag.SalvageAll(from); - } - } - - private class SalvageIngotsEntry : ContextMenuEntry - { - private readonly SalvageBag m_Bag; - - public SalvageIngotsEntry(SalvageBag bag, bool enabled) - : base(6277) - { - m_Bag = bag; - - if (!enabled) - Flags |= CMEFlags.Disabled; - } - - public override void OnClick() - { - if (m_Bag.Deleted) - return; - - Mobile from = Owner.From; - - if (from.CheckAlive()) - m_Bag.SalvageIngots(from); - } - } - - private class SalvageClothEntry : ContextMenuEntry - { - private readonly SalvageBag m_Bag; - - public SalvageClothEntry(SalvageBag bag, bool enabled) - : base(6278) - { - m_Bag = bag; - - if (!enabled) - Flags |= CMEFlags.Disabled; - } - - public override void OnClick() - { - if (m_Bag.Deleted) - return; - - Mobile from = Owner.From; - - if (from.CheckAlive()) - m_Bag.SalvageCloth(from); - } - } - - public SalvageBag(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using Server.ContextMenus; +using Server.Engines.Craft; +using Server.Network; +using Server.Utilities; + +namespace Server.Items +{ + public class SalvageBag : Bag + { + private bool m_Failure; + + [Constructible] + public SalvageBag() + : this(Utility.RandomBlueHue()) + { + } + + [Constructible] + public SalvageBag(int hue) + { + Weight = 2.0; + Hue = hue; + m_Failure = false; + } + + public SalvageBag(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1079931; // Salvage Bag + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (from.Alive) + { + list.Add(new SalvageIngotsEntry(this, IsChildOf(from.Backpack) && Resmeltables())); + list.Add(new SalvageClothEntry(this, IsChildOf(from.Backpack) && Scissorables())); + list.Add(new SalvageAllEntry(this, IsChildOf(from.Backpack) && Resmeltables() && Scissorables())); + } + } + + private bool Resmelt(Mobile from, Item item, CraftResource resource) + { + try + { + if (CraftResources.GetType(resource) != CraftResourceType.Metal) + return false; + + var info = CraftResources.GetInfo(resource); + + if (info == null || info.ResourceTypes.Length == 0) + return false; + + var craftItem = DefBlacksmithy.CraftSystem.CraftItems.SearchFor(item.GetType()); + + if (craftItem == null || craftItem.Resources.Count == 0) + return false; + + var craftResource = craftItem.Resources[0]; + + if (craftResource.Amount < 2) + return false; // Not enough metal to resmelt + + var difficulty = resource switch + { + CraftResource.DullCopper => 65.0, + CraftResource.ShadowIron => 70.0, + CraftResource.Copper => 75.0, + CraftResource.Bronze => 80.0, + CraftResource.Gold => 85.0, + CraftResource.Agapite => 90.0, + CraftResource.Verite => 95.0, + CraftResource.Valorite => 99.0, + _ => 0.0 + }; + + var resourceType = info.ResourceTypes[0]; + var ingot = (Item)ActivatorUtil.CreateInstance(resourceType); + + if (item is DragonBardingDeed || item is BaseArmor armor && armor.PlayerConstructed || + item is BaseWeapon weapon && weapon.PlayerConstructed || + item is BaseClothing clothing && clothing.PlayerConstructed) + { + var mining = from.Skills.Mining.Value; + if (mining > 100.0) + mining = 100.0; + var amount = ((4 + mining) * craftResource.Amount - 4) * 0.0068; + if (amount < 2) + ingot.Amount = 2; + else + ingot.Amount = (int)amount; + } + else + { + ingot.Amount = 2; + } + + if (difficulty > from.Skills.Mining.Value) + { + m_Failure = true; + ingot.Delete(); + } + else + { + item.Delete(); + } + + from.AddToBackpack(ingot); + + from.PlaySound(0x2A); + from.PlaySound(0x240); + + return true; + } + catch (Exception ex) + { + Console.WriteLine(ex.ToString()); + } + + return false; + } + + private bool Resmeltables() // Where context menu checks for metal items and dragon barding deeds + { + foreach (var i in Items) + return i?.Deleted == false && ( + i is BaseWeapon weapon && CraftResources.GetType(weapon.Resource) == CraftResourceType.Metal || + i is BaseArmor armor && CraftResources.GetType(armor.Resource) == CraftResourceType.Metal || + i is DragonBardingDeed); + + return false; + } + + private bool Scissorables() // Where context menu checks for Leather items and cloth items + { + foreach (var i in Items) + { + if (!(i is IScissorable) || i.Deleted) + continue; + + if (i is BaseClothing || i is Cloth || i is BoltOfCloth || i is Hides || i is BonePile || + i is BaseArmor armor && CraftResources.GetType(armor.Resource) == CraftResourceType.Leather) + return true; + } + + return false; + } + + private void SalvageIngots(Mobile from) + { + if (from.Backpack.FindItemsByType().All(tool => tool.CraftSystem != DefBlacksmithy.CraftSystem)) + { + from.SendLocalizedMessage(1079822); // You need a blacksmithing tool in order to salvage ingots. + return; + } + + DefBlacksmithy.CheckAnvilAndForge(from, 2, out _, out var forge); + + if (!forge) + { + from.SendLocalizedMessage(1044265); // You must be near a forge. + return; + } + + var salvaged = 0; + var notSalvaged = 0; + + Container sBag = this; + + var smeltables = sBag.FindItemsByType(); + + foreach (var item in smeltables) + { + if (item?.Deleted != false) + continue; + + if (item is BaseArmor armor && Resmelt(@from, armor, armor.Resource) || + item is BaseWeapon weapon && Resmelt(@from, weapon, weapon.Resource) || + item is DragonBardingDeed) + salvaged++; + else + notSalvaged++; + } + + if (m_Failure) + { + from.SendLocalizedMessage(1079975); // You failed to smelt some metal for lack of skill. + m_Failure = false; + } + else + { + from.SendLocalizedMessage( + 1079973, + $"{salvaged}\t{salvaged + notSalvaged}" + ); // Salvaged: ~1_COUNT~/~2_NUM~ blacksmithed items + } + } + + private void SalvageCloth(Mobile from) + { + var scissors = from.Backpack.FindItemByType(); + + if (scissors == null) + { + from.SendLocalizedMessage(1079823); // You need scissors in order to salvage cloth. + return; + } + + var salvaged = 0; + var notSalvaged = 0; + + Container sBag = this; + + var scissorables = sBag.FindItemsByType(); + + for (var i = scissorables.Count - 1; i >= 0; --i) + { + var item = scissorables[i]; + + if (!(item is IScissorable scissorable)) + continue; + + if (Scissors.CanScissor(from, scissorable) && scissorable.Scissor(from, scissors)) + ++salvaged; + else + ++notSalvaged; + } + + from.SendLocalizedMessage( + 1079974, + $"{salvaged}\t{salvaged + notSalvaged}" + ); // Salvaged: ~1_COUNT~/~2_NUM~ tailored items + + var items = FindItemsByType( + new[] + { + typeof(Leather), typeof(Cloth), typeof(SpinedLeather), typeof(HornedLeather), typeof(BarbedLeather), + typeof(Bandage), typeof(Bone) + } + ); + + for (var i = 0; i < items.Length; i++) from.AddToBackpack(items[i]); + } + + private void SalvageAll(Mobile from) + { + SalvageIngots(from); + + SalvageCloth(from); + } + + 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(); + } + + private class SalvageAllEntry : ContextMenuEntry + { + private readonly SalvageBag m_Bag; + + public SalvageAllEntry(SalvageBag bag, bool enabled) + : base(6276) + { + m_Bag = bag; + + if (!enabled) + Flags |= CMEFlags.Disabled; + } + + public override void OnClick() + { + if (m_Bag.Deleted) + return; + + var from = Owner.From; + + if (from.CheckAlive()) + m_Bag.SalvageAll(from); + } + } + + private class SalvageIngotsEntry : ContextMenuEntry + { + private readonly SalvageBag m_Bag; + + public SalvageIngotsEntry(SalvageBag bag, bool enabled) + : base(6277) + { + m_Bag = bag; + + if (!enabled) + Flags |= CMEFlags.Disabled; + } + + public override void OnClick() + { + if (m_Bag.Deleted) + return; + + var from = Owner.From; + + if (from.CheckAlive()) + m_Bag.SalvageIngots(from); + } + } + + private class SalvageClothEntry : ContextMenuEntry + { + private readonly SalvageBag m_Bag; + + public SalvageClothEntry(SalvageBag bag, bool enabled) + : base(6278) + { + m_Bag = bag; + + if (!enabled) + Flags |= CMEFlags.Disabled; + } + + public override void OnClick() + { + if (m_Bag.Deleted) + return; + + var from = Owner.From; + + if (from.CheckAlive()) + m_Bag.SalvageCloth(from); + } + } + } +} diff --git a/Projects/UOContent/Items/Containers/Strongbox.cs b/Projects/UOContent/Items/Containers/Strongbox.cs index bb21cf6c0..b4493fd58 100644 --- a/Projects/UOContent/Items/Containers/Strongbox.cs +++ b/Projects/UOContent/Items/Containers/Strongbox.cs @@ -1,137 +1,137 @@ -using System; -using System.Collections.Generic; -using Server.Multis; - -namespace Server.Items -{ - [Flippable(0xE80, 0x9A8)] - public class StrongBox : BaseContainer, IChoppable - { - private BaseHouse m_House; - private Mobile m_Owner; - - public StrongBox(Mobile owner, BaseHouse house) : base(0xE80) - { - m_Owner = owner; - m_House = house; - - MaxItems = 25; - } - - public StrongBox(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 100; - public override int LabelNumber => 1023712; - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Owner - { - get => m_Owner; - set - { - m_Owner = value; - InvalidateProperties(); - } - } - - public override int DefaultMaxWeight => 0; - - public override bool Decays => m_House == null || m_Owner?.Deleted != false || !m_House.IsCoOwner(m_Owner); - - public override TimeSpan DecayTime => TimeSpan.FromMinutes(30.0); - - public void OnChop(Mobile from) - { - if (m_House?.Deleted != false || m_Owner?.Deleted != false || from == m_Owner || m_House.IsOwner(from)) - Chop(from); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Owner); - writer.Write(m_House); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Owner = reader.ReadMobile(); - m_House = reader.ReadItem() as BaseHouse; - - break; - } - } - - Timer.DelayCall(TimeSpan.FromSeconds(1.0), Validate); - } - - private void Validate() - { - if (m_Owner != null && m_House?.IsCoOwner(m_Owner) == false) - { - Console.WriteLine("Warning: Destroying strongbox of {0}", m_Owner.Name); - Destroy(); - } - } - - public override void AddNameProperty(ObjectPropertyList list) - { - if (m_Owner != null) - list.Add(1042887, m_Owner.Name); // a strong box owned by ~1_OWNER_NAME~ - else - base.AddNameProperty(list); - } - - public override void OnSingleClick(Mobile from) - { - if (m_Owner != null) - { - LabelTo(from, 1042887, m_Owner.Name); // a strong box owned by ~1_OWNER_NAME~ - - if (CheckContentDisplay(from)) - LabelTo(from, "({0} items, {1} stones)", TotalItems, TotalWeight); - } - else - { - base.OnSingleClick(from); - } - } - - public override bool IsAccessibleTo(Mobile m) => - m_Owner?.Deleted != false || m_House?.Deleted != false || - m.AccessLevel >= AccessLevel.GameMaster || - (m == m_Owner && m_House.IsCoOwner(m) && base.IsAccessibleTo(m)); - - private void Chop(Mobile from) - { - Effects.PlaySound(Location, Map, 0x3B3); - from.SendLocalizedMessage(500461); // You destroy the item. - Destroy(); - } - - public Container ConvertToStandardContainer() - { - Container metalBox = new MetalBox(); - List subItems = new List(Items); - - foreach (Item subItem in subItems) metalBox.AddItem(subItem); - - Delete(); - - return metalBox; - } - } -} +using System; +using System.Collections.Generic; +using Server.Multis; + +namespace Server.Items +{ + [Flippable(0xE80, 0x9A8)] + public class StrongBox : BaseContainer, IChoppable + { + private BaseHouse m_House; + private Mobile m_Owner; + + public StrongBox(Mobile owner, BaseHouse house) : base(0xE80) + { + m_Owner = owner; + m_House = house; + + MaxItems = 25; + } + + public StrongBox(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 100; + public override int LabelNumber => 1023712; + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Owner + { + get => m_Owner; + set + { + m_Owner = value; + InvalidateProperties(); + } + } + + public override int DefaultMaxWeight => 0; + + public override bool Decays => m_House == null || m_Owner?.Deleted != false || !m_House.IsCoOwner(m_Owner); + + public override TimeSpan DecayTime => TimeSpan.FromMinutes(30.0); + + public void OnChop(Mobile from) + { + if (m_House?.Deleted != false || m_Owner?.Deleted != false || from == m_Owner || m_House.IsOwner(from)) + Chop(from); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Owner); + writer.Write(m_House); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Owner = reader.ReadMobile(); + m_House = reader.ReadItem() as BaseHouse; + + break; + } + } + + Timer.DelayCall(TimeSpan.FromSeconds(1.0), Validate); + } + + private void Validate() + { + if (m_Owner != null && m_House?.IsCoOwner(m_Owner) == false) + { + Console.WriteLine("Warning: Destroying strongbox of {0}", m_Owner.Name); + Destroy(); + } + } + + public override void AddNameProperty(ObjectPropertyList list) + { + if (m_Owner != null) + list.Add(1042887, m_Owner.Name); // a strong box owned by ~1_OWNER_NAME~ + else + base.AddNameProperty(list); + } + + public override void OnSingleClick(Mobile from) + { + if (m_Owner != null) + { + LabelTo(from, 1042887, m_Owner.Name); // a strong box owned by ~1_OWNER_NAME~ + + if (CheckContentDisplay(from)) + LabelTo(from, "({0} items, {1} stones)", TotalItems, TotalWeight); + } + else + { + base.OnSingleClick(from); + } + } + + public override bool IsAccessibleTo(Mobile m) => + m_Owner?.Deleted != false || m_House?.Deleted != false || + m.AccessLevel >= AccessLevel.GameMaster || + m == m_Owner && m_House.IsCoOwner(m) && base.IsAccessibleTo(m); + + private void Chop(Mobile from) + { + Effects.PlaySound(Location, Map, 0x3B3); + from.SendLocalizedMessage(500461); // You destroy the item. + Destroy(); + } + + public Container ConvertToStandardContainer() + { + Container metalBox = new MetalBox(); + var subItems = new List(Items); + + foreach (var subItem in subItems) metalBox.AddItem(subItem); + + Delete(); + + return metalBox; + } + } +} diff --git a/Projects/UOContent/Items/Containers/TrappableContainer.cs b/Projects/UOContent/Items/Containers/TrappableContainer.cs index c1499cdd7..73bb0e86f 100644 --- a/Projects/UOContent/Items/Containers/TrappableContainer.cs +++ b/Projects/UOContent/Items/Containers/TrappableContainer.cs @@ -1,224 +1,224 @@ -using System; -using Server.Network; - -namespace Server.Items -{ - public enum TrapType - { - None, - MagicTrap, - ExplosionTrap, - DartTrap, - PoisonTrap - } - - public abstract class TrappableContainer : BaseContainer, ITelekinesisable - { - public TrappableContainer(int itemID) : base(itemID) - { - } - - public TrappableContainer(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public TrapType TrapType { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int TrapPower { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int TrapLevel { get; set; } - - public virtual bool TrapOnOpen => true; - - public virtual void OnTelekinesis(Mobile from) - { - Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x376A, 9, 32, 5022); - Effects.PlaySound(Location, Map, 0x1F5); - - if (TrapOnOpen) ExecuteTrap(from); - } - - private void SendMessageTo(Mobile to, int number, int hue) - { - if (Deleted || !to.CanSee(this)) - return; - - to.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, hue, 3, number, "", "")); - } - - private void SendMessageTo(Mobile to, string text, int hue) - { - if (Deleted || !to.CanSee(this)) - return; - - to.Send(new UnicodeMessage(Serial, ItemID, MessageType.Regular, hue, 3, "ENU", "", text)); - } - - public virtual bool ExecuteTrap(Mobile from) - { - if (TrapType != TrapType.None) - { - Point3D loc = GetWorldLocation(); - Map facet = Map; - - if (from.AccessLevel >= AccessLevel.GameMaster) - { - SendMessageTo(from, "That is trapped, but you open it with your godly powers.", 0x3B2); - return false; - } - - switch (TrapType) - { - case TrapType.ExplosionTrap: - { - SendMessageTo(from, 502999, 0x3B2); // You set off a trap! - - if (from.InRange(loc, 3)) - { - int damage; - - if (TrapLevel > 0) - damage = Utility.RandomMinMax(10, 30) * TrapLevel; - else - damage = TrapPower; - - AOS.Damage(from, damage, 0, 100, 0, 0, 0); - - // Your skin blisters from the heat! - from.LocalOverheadMessage(MessageType.Regular, 0x2A, 503000); - } - - Effects.SendLocationEffect(loc, facet, 0x36BD, 15, 10); - Effects.PlaySound(loc, facet, 0x307); - - break; - } - case TrapType.MagicTrap: - { - if (from.InRange(loc, 1)) - from.Damage(TrapPower); - // AOS.Damage( from, m_TrapPower, 0, 100, 0, 0, 0 ); - - Effects.PlaySound(loc, Map, 0x307); - - Effects.SendLocationEffect(new Point3D(loc.X - 1, loc.Y, loc.Z), Map, 0x36BD, 15); - Effects.SendLocationEffect(new Point3D(loc.X + 1, loc.Y, loc.Z), Map, 0x36BD, 15); - - Effects.SendLocationEffect(new Point3D(loc.X, loc.Y - 1, loc.Z), Map, 0x36BD, 15); - Effects.SendLocationEffect(new Point3D(loc.X, loc.Y + 1, loc.Z), Map, 0x36BD, 15); - - Effects.SendLocationEffect(new Point3D(loc.X + 1, loc.Y + 1, loc.Z + 11), Map, 0x36BD, 15); - - break; - } - case TrapType.DartTrap: - { - SendMessageTo(from, 502999, 0x3B2); // You set off a trap! - - if (from.InRange(loc, 3)) - { - int damage; - - if (TrapLevel > 0) - damage = Utility.RandomMinMax(5, 15) * TrapLevel; - else - damage = TrapPower; - - AOS.Damage(from, damage, 100, 0, 0, 0, 0); - - // A dart imbeds itself in your flesh! - from.LocalOverheadMessage(MessageType.Regular, 0x62, 502998); - } - - Effects.PlaySound(loc, facet, 0x223); - - break; - } - case TrapType.PoisonTrap: - { - SendMessageTo(from, 502999, 0x3B2); // You set off a trap! - - if (from.InRange(loc, 3)) - { - Poison poison; - - if (TrapLevel > 0) - { - poison = Poison.GetPoison(Math.Max(0, Math.Min(4, TrapLevel - 1))); - } - else - { - AOS.Damage(from, TrapPower, 0, 0, 0, 100, 0); - poison = Poison.Greater; - } - - from.ApplyPoison(from, poison); - - // You are enveloped in a noxious green cloud! - from.LocalOverheadMessage(MessageType.Regular, 0x44, 503004); - } - - Effects.SendLocationEffect(loc, facet, 0x113A, 10, 20); - Effects.PlaySound(loc, facet, 0x231); - - break; - } - } - - TrapType = TrapType.None; - TrapPower = 0; - TrapLevel = 0; - return true; - } - - return false; - } - - public override void Open(Mobile from) - { - if (!TrapOnOpen || !ExecuteTrap(from)) - base.Open(from); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(2); // version - - writer.Write(TrapLevel); - - writer.Write(TrapPower); - writer.Write((int)TrapType); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 2: - { - TrapLevel = reader.ReadInt(); - goto case 1; - } - case 1: - { - TrapPower = reader.ReadInt(); - goto case 0; - } - case 0: - { - TrapType = (TrapType)reader.ReadInt(); - break; - } - } - } - } -} \ No newline at end of file +using System; +using Server.Network; + +namespace Server.Items +{ + public enum TrapType + { + None, + MagicTrap, + ExplosionTrap, + DartTrap, + PoisonTrap + } + + public abstract class TrappableContainer : BaseContainer, ITelekinesisable + { + public TrappableContainer(int itemID) : base(itemID) + { + } + + public TrappableContainer(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public TrapType TrapType { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int TrapPower { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int TrapLevel { get; set; } + + public virtual bool TrapOnOpen => true; + + public virtual void OnTelekinesis(Mobile from) + { + Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x376A, 9, 32, 5022); + Effects.PlaySound(Location, Map, 0x1F5); + + if (TrapOnOpen) ExecuteTrap(from); + } + + private void SendMessageTo(Mobile to, int number, int hue) + { + if (Deleted || !to.CanSee(this)) + return; + + to.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, hue, 3, number, "", "")); + } + + private void SendMessageTo(Mobile to, string text, int hue) + { + if (Deleted || !to.CanSee(this)) + return; + + to.Send(new UnicodeMessage(Serial, ItemID, MessageType.Regular, hue, 3, "ENU", "", text)); + } + + public virtual bool ExecuteTrap(Mobile from) + { + if (TrapType != TrapType.None) + { + var loc = GetWorldLocation(); + var facet = Map; + + if (from.AccessLevel >= AccessLevel.GameMaster) + { + SendMessageTo(from, "That is trapped, but you open it with your godly powers.", 0x3B2); + return false; + } + + switch (TrapType) + { + case TrapType.ExplosionTrap: + { + SendMessageTo(from, 502999, 0x3B2); // You set off a trap! + + if (from.InRange(loc, 3)) + { + int damage; + + if (TrapLevel > 0) + damage = Utility.RandomMinMax(10, 30) * TrapLevel; + else + damage = TrapPower; + + AOS.Damage(from, damage, 0, 100, 0, 0, 0); + + // Your skin blisters from the heat! + from.LocalOverheadMessage(MessageType.Regular, 0x2A, 503000); + } + + Effects.SendLocationEffect(loc, facet, 0x36BD, 15, 10); + Effects.PlaySound(loc, facet, 0x307); + + break; + } + case TrapType.MagicTrap: + { + if (from.InRange(loc, 1)) + from.Damage(TrapPower); + // AOS.Damage( from, m_TrapPower, 0, 100, 0, 0, 0 ); + + Effects.PlaySound(loc, Map, 0x307); + + Effects.SendLocationEffect(new Point3D(loc.X - 1, loc.Y, loc.Z), Map, 0x36BD, 15); + Effects.SendLocationEffect(new Point3D(loc.X + 1, loc.Y, loc.Z), Map, 0x36BD, 15); + + Effects.SendLocationEffect(new Point3D(loc.X, loc.Y - 1, loc.Z), Map, 0x36BD, 15); + Effects.SendLocationEffect(new Point3D(loc.X, loc.Y + 1, loc.Z), Map, 0x36BD, 15); + + Effects.SendLocationEffect(new Point3D(loc.X + 1, loc.Y + 1, loc.Z + 11), Map, 0x36BD, 15); + + break; + } + case TrapType.DartTrap: + { + SendMessageTo(from, 502999, 0x3B2); // You set off a trap! + + if (from.InRange(loc, 3)) + { + int damage; + + if (TrapLevel > 0) + damage = Utility.RandomMinMax(5, 15) * TrapLevel; + else + damage = TrapPower; + + AOS.Damage(from, damage, 100, 0, 0, 0, 0); + + // A dart imbeds itself in your flesh! + from.LocalOverheadMessage(MessageType.Regular, 0x62, 502998); + } + + Effects.PlaySound(loc, facet, 0x223); + + break; + } + case TrapType.PoisonTrap: + { + SendMessageTo(from, 502999, 0x3B2); // You set off a trap! + + if (from.InRange(loc, 3)) + { + Poison poison; + + if (TrapLevel > 0) + { + poison = Poison.GetPoison(Math.Max(0, Math.Min(4, TrapLevel - 1))); + } + else + { + AOS.Damage(from, TrapPower, 0, 0, 0, 100, 0); + poison = Poison.Greater; + } + + from.ApplyPoison(from, poison); + + // You are enveloped in a noxious green cloud! + from.LocalOverheadMessage(MessageType.Regular, 0x44, 503004); + } + + Effects.SendLocationEffect(loc, facet, 0x113A, 10, 20); + Effects.PlaySound(loc, facet, 0x231); + + break; + } + } + + TrapType = TrapType.None; + TrapPower = 0; + TrapLevel = 0; + return true; + } + + return false; + } + + public override void Open(Mobile from) + { + if (!TrapOnOpen || !ExecuteTrap(from)) + base.Open(from); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(2); // version + + writer.Write(TrapLevel); + + writer.Write(TrapPower); + writer.Write((int)TrapType); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 2: + { + TrapLevel = reader.ReadInt(); + goto case 1; + } + case 1: + { + TrapPower = reader.ReadInt(); + goto case 0; + } + case 0: + { + TrapType = (TrapType)reader.ReadInt(); + break; + } + } + } + } +} diff --git a/Projects/UOContent/Items/Containers/TreasureChest.cs b/Projects/UOContent/Items/Containers/TreasureChest.cs index 1f49ff3b3..b578438c4 100644 --- a/Projects/UOContent/Items/Containers/TreasureChest.cs +++ b/Projects/UOContent/Items/Containers/TreasureChest.cs @@ -1,83 +1,83 @@ -namespace Server.Items -{ - [Flippable(0xe43, 0xe42)] - public class WoodenTreasureChest : BaseTreasureChest - { - [Constructible] - public WoodenTreasureChest() : base(0xE43) - { - } - - public WoodenTreasureChest(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0xe41, 0xe40)] - public class MetalGoldenTreasureChest : BaseTreasureChest - { - [Constructible] - public MetalGoldenTreasureChest() : base(0xE41) - { - } - - public MetalGoldenTreasureChest(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x9ab, 0xe7c)] - public class MetalTreasureChest : BaseTreasureChest - { - [Constructible] - public MetalTreasureChest() : base(0x9AB) - { - } - - public MetalTreasureChest(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0xe43, 0xe42)] + public class WoodenTreasureChest : BaseTreasureChest + { + [Constructible] + public WoodenTreasureChest() : base(0xE43) + { + } + + public WoodenTreasureChest(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0xe41, 0xe40)] + public class MetalGoldenTreasureChest : BaseTreasureChest + { + [Constructible] + public MetalGoldenTreasureChest() : base(0xE41) + { + } + + public MetalGoldenTreasureChest(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x9ab, 0xe7c)] + public class MetalTreasureChest : BaseTreasureChest + { + [Constructible] + public MetalTreasureChest() : base(0x9AB) + { + } + + public MetalTreasureChest(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Containers/TreasureMapChest.cs b/Projects/UOContent/Items/Containers/TreasureMapChest.cs index 156aeb32d..f1e371fd8 100644 --- a/Projects/UOContent/Items/Containers/TreasureMapChest.cs +++ b/Projects/UOContent/Items/Containers/TreasureMapChest.cs @@ -1,542 +1,548 @@ -using System; -using System.Collections.Generic; -using Server.ContextMenus; -using Server.Engines.PartySystem; -using Server.Gumps; -using Server.Network; -using Server.Utilities; - -namespace Server.Items -{ - public class TreasureMapChest : LockableContainer - { - private List m_Lifted = new List(); - - private Timer m_Timer; - - [Constructible] - public TreasureMapChest(int level) : this(null, level) - { - } - - public TreasureMapChest(Mobile owner, int level, bool temporary = false) : base(0xE40) - { - Owner = owner; - Level = level; - DeleteTime = DateTime.UtcNow + TimeSpan.FromHours(3.0); - - Temporary = temporary; - Guardians = new List(); - - m_Timer = new DeleteTimer(this, DeleteTime); - m_Timer.Start(); - - Fill(this, level); - } - - public TreasureMapChest(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 3000541; - - public static Type[] Artifacts { get; } = - { - typeof(CandelabraOfSouls), typeof(GoldBricks), typeof(PhillipsWoodenSteed), - typeof(ArcticDeathDealer), typeof(BlazeOfDeath), typeof(BurglarsBandana), - typeof(CavortingClub), typeof(DreadPirateHat), - typeof(EnchantedTitanLegBone), typeof(GwennosHarp), typeof(IolosLute), - typeof(LunaLance), typeof(NightsKiss), typeof(NoxRangersHeavyCrossbow), - typeof(PolarBearMask), typeof(VioletCourage), typeof(HeartOfTheLion), - typeof(ColdBlood), typeof(AlchemistsBauble) - }; - - [CommandProperty(AccessLevel.GameMaster)] - public int Level { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Owner { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime DeleteTime { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Temporary { get; set; } - - public List Guardians { get; private set; } - - public override bool IsDecoContainer => false; - - private static void GetRandomAOSStats(out int attributeCount, out int min, out int max) - { - int rnd = Utility.Random(15); - - if (Core.SE) - { - if (rnd < 1) - { - attributeCount = Utility.RandomMinMax(3, 5); - min = 50; - max = 100; - } - else if (rnd < 3) - { - attributeCount = Utility.RandomMinMax(2, 5); - min = 40; - max = 80; - } - else if (rnd < 6) - { - attributeCount = Utility.RandomMinMax(2, 4); - min = 30; - max = 60; - } - else if (rnd < 10) - { - attributeCount = Utility.RandomMinMax(1, 3); - min = 20; - max = 40; - } - else - { - attributeCount = 1; - min = 10; - max = 20; - } - } - else - { - if (rnd < 1) - { - attributeCount = Utility.RandomMinMax(2, 5); - min = 20; - max = 70; - } - else if (rnd < 3) - { - attributeCount = Utility.RandomMinMax(2, 4); - min = 20; - max = 50; - } - else if (rnd < 6) - { - attributeCount = Utility.RandomMinMax(2, 3); - min = 20; - max = 40; - } - else if (rnd < 10) - { - attributeCount = Utility.RandomMinMax(1, 2); - min = 10; - max = 30; - } - else - { - attributeCount = 1; - min = 10; - max = 20; - } - } - } - - public static void Fill(LockableContainer cont, int level) - { - cont.Movable = false; - cont.Locked = true; - int numberItems; - - if (level == 0) - { - cont.LockLevel = 0; // Can't be unlocked - - cont.DropItem(new Gold(Utility.RandomMinMax(50, 100))); - - if (Utility.RandomDouble() < 0.75) - cont.DropItem(new TreasureMap(0, Map.Trammel)); - } - else - { - cont.TrapType = TrapType.ExplosionTrap; - cont.TrapPower = level * 25; - cont.TrapLevel = level; - - cont.RequiredSkill = level switch - { - 1 => 36, - 2 => 76, - 3 => 84, - 4 => 92, - 5 => 100, - 6 => 100, - _ => cont.RequiredSkill - }; - - cont.LockLevel = cont.RequiredSkill - 10; - cont.MaxLockLevel = cont.RequiredSkill + 40; - - // Publish 67 gold change - // if (Core.SA) - // cont.DropItem( new Gold( level * 5000 ) ); - // else - cont.DropItem(new Gold(level * 1000)); - - for (int i = 0; i < level * 5; ++i) - cont.DropItem(Loot.RandomScroll(0, 63, SpellbookType.Regular)); - - if (Core.SE) - { - numberItems = level switch - { - 1 => 5, - 2 => 10, - 3 => 15, - 4 => 38, - 5 => 50, - 6 => 60, - _ => 0 - }; - } - else - { - numberItems = level * 6; - } - - for (int i = 0; i < numberItems; ++i) - { - Item item; - - if (Core.AOS) - item = Loot.RandomArmorOrShieldOrWeaponOrJewelry(); - else - item = Loot.RandomArmorOrShieldOrWeapon(); - - if (item is BaseWeapon weapon) - { - if (Core.AOS) - { - GetRandomAOSStats(out int attributeCount, out int min, out int max); - BaseRunicTool.ApplyAttributesTo(weapon, attributeCount, min, max); - } - else - { - weapon.DamageLevel = (WeaponDamageLevel)Utility.Random(6); - weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random(6); - weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random(6); - } - - cont.DropItem(weapon); - } - else if (item is BaseArmor armor) - { - if (Core.AOS) - { - GetRandomAOSStats(out int attributeCount, out int min, out int max); - BaseRunicTool.ApplyAttributesTo(armor, attributeCount, min, max); - } - else - { - armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(6); - armor.Durability = (ArmorDurabilityLevel)Utility.Random(6); - } - - cont.DropItem(armor); - } - else if (item is BaseHat hat) - { - if (Core.AOS) - { - GetRandomAOSStats(out int attributeCount, out int min, out int max); - BaseRunicTool.ApplyAttributesTo(hat, attributeCount, min, max); - } - - cont.DropItem(hat); - } - else if (item is BaseJewel jewel) - { - GetRandomAOSStats(out int attributeCount, out int min, out int max); - BaseRunicTool.ApplyAttributesTo(jewel, attributeCount, min, max); - - cont.DropItem(jewel); - } - } - } - - int reagents; - if (level == 0) - reagents = 12; - else - reagents = level * 3; - - for (int i = 0; i < reagents; i++) - { - Item item = Loot.RandomPossibleReagent(); - item.Amount = Utility.RandomMinMax(40, 60); - cont.DropItem(item); - } - - int gems; - if (level == 0) - gems = 2; - else - gems = level * 3; - - for (int i = 0; i < gems; i++) - { - Item item = Loot.RandomGem(); - cont.DropItem(item); - } - - if (level == 6 && Core.AOS) - cont.DropItem((Item)ActivatorUtil.CreateInstance(Artifacts.RandomElement())); - } - - public override bool CheckLocked(Mobile from) - { - if (!Locked) - return false; - - if (Level == 0 && from.AccessLevel < AccessLevel.GameMaster) - { - foreach (Mobile m in Guardians) - if (m.Alive) - { - from.SendLocalizedMessage( - 1046448); // You must first kill the guardians before you may open this chest. - return true; - } - - LockPick(from); - return false; - } - - return base.CheckLocked(from); - } - - private bool CheckLoot(Mobile m, bool criminalAction) - { - if (Temporary) - return false; - - if (m.AccessLevel >= AccessLevel.GameMaster || Owner == null || m == Owner) - return true; - - if (Party.Get(Owner)?.Contains(m) == true) - return true; - - Map map = Map; - - if ((map?.Rules & MapRules.HarmfulRestrictions) == 0) - { - if (criminalAction) - m.CriminalAction(true); - else - m.SendLocalizedMessage(1010630); // Taking someone else's treasure is a criminal offense! - - return true; - } - - m.SendLocalizedMessage(1010631); // You did not discover this chest! - return false; - } - - public override bool CheckItemUse(Mobile from, Item item) => CheckLoot(from, item != this) && base.CheckItemUse(from, item); - - public override bool CheckLift(Mobile from, Item item, ref LRReason reject) => CheckLoot(from, true) && base.CheckLift(from, item, ref reject); - - public override void OnItemLifted(Mobile from, Item item) - { - bool notYetLifted = !m_Lifted.Contains(item); - - from.RevealingAction(); - - if (notYetLifted) - { - m_Lifted.Add(item); - - if (Utility.RandomDouble() <= 0.1) // 10% chance to spawn a new monster - TreasureMap.Spawn(Level, GetWorldLocation(), Map, from, false); - } - - base.OnItemLifted(from, item); - } - - public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight) - { - if (m.AccessLevel < AccessLevel.GameMaster) - { - m.SendLocalizedMessage(1048122, "", 0x8A5); // The chest refuses to be filled with treasure again. - return false; - } - - return base.CheckHold(m, item, message, checkItems, plusItems, plusWeight); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(2); // version - - writer.Write(Guardians, true); - writer.Write(Temporary); - - writer.Write(Owner); - - writer.Write(Level); - writer.WriteDeltaTime(DeleteTime); - writer.Write(m_Lifted, true); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 2: - { - Guardians = reader.ReadStrongMobileList(); - Temporary = reader.ReadBool(); - - goto case 1; - } - case 1: - { - Owner = reader.ReadMobile(); - - goto case 0; - } - case 0: - { - Level = reader.ReadInt(); - DeleteTime = reader.ReadDeltaTime(); - m_Lifted = reader.ReadStrongItemList(); - - if (version < 2) - Guardians = new List(); - - break; - } - } - - if (!Temporary) - { - m_Timer = new DeleteTimer(this, DeleteTime); - m_Timer.Start(); - } - else - { - Delete(); - } - } - - public override void OnAfterDelete() - { - m_Timer?.Stop(); - - m_Timer = null; - - base.OnAfterDelete(); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (from.Alive) - list.Add(new RemoveEntry(from, this)); - } - - public void BeginRemove(Mobile from) - { - if (!from.Alive) - return; - - from.CloseGump(); - from.SendGump(new RemoveGump(from, this)); - } - - public void EndRemove(Mobile from) - { - if (Deleted || from != Owner || !from.InRange(GetWorldLocation(), 3)) - return; - - from.SendLocalizedMessage(1048124, "", 0x8A5); // The old, rusted chest crumbles when you hit it. - Delete(); - } - - private class RemoveGump : Gump - { - private readonly TreasureMapChest m_Chest; - private readonly Mobile m_From; - - public RemoveGump(Mobile from, TreasureMapChest chest) : base(15, 15) - { - m_From = from; - m_Chest = chest; - - Closable = false; - Disposable = false; - - AddPage(0); - - AddBackground(30, 0, 240, 240, 2620); - - AddHtmlLocalized(45, 15, 200, 80, 1048125, 0xFFFFFF); // When this treasure chest is removed, any items still inside of it will be lost. - AddHtmlLocalized(45, 95, 200, 60, 1048126, 0xFFFFFF); // Are you certain you're ready to remove this chest? - - AddButton(40, 153, 4005, 4007, 1); - AddHtmlLocalized(75, 155, 180, 40, 1048127, 0xFFFFFF); // Remove the Treasure Chest - - AddButton(40, 195, 4005, 4007, 2); - AddHtmlLocalized(75, 197, 180, 35, 1006045, 0xFFFFFF); // Cancel - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 1) - m_Chest.EndRemove(m_From); - } - } - - private class RemoveEntry : ContextMenuEntry - { - private readonly TreasureMapChest m_Chest; - private readonly Mobile m_From; - - public RemoveEntry(Mobile from, TreasureMapChest chest) : base(6149, 3) - { - m_From = from; - m_Chest = chest; - - Enabled = from == chest.Owner; - } - - public override void OnClick() - { - if (m_Chest.Deleted || m_From != m_Chest.Owner || !m_From.CheckAlive()) - return; - - m_Chest.BeginRemove(m_From); - } - } - - private class DeleteTimer : Timer - { - private readonly Item m_Item; - - public DeleteTimer(Item item, DateTime time) : base(time - DateTime.UtcNow) - { - m_Item = item; - Priority = TimerPriority.OneMinute; - } - - protected override void OnTick() - { - m_Item.Delete(); - } - } - } -} +using System; +using System.Collections.Generic; +using Server.ContextMenus; +using Server.Engines.PartySystem; +using Server.Gumps; +using Server.Network; +using Server.Utilities; + +namespace Server.Items +{ + public class TreasureMapChest : LockableContainer + { + private List m_Lifted = new List(); + + private Timer m_Timer; + + [Constructible] + public TreasureMapChest(int level) : this(null, level) + { + } + + public TreasureMapChest(Mobile owner, int level, bool temporary = false) : base(0xE40) + { + Owner = owner; + Level = level; + DeleteTime = DateTime.UtcNow + TimeSpan.FromHours(3.0); + + Temporary = temporary; + Guardians = new List(); + + m_Timer = new DeleteTimer(this, DeleteTime); + m_Timer.Start(); + + Fill(this, level); + } + + public TreasureMapChest(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 3000541; + + public static Type[] Artifacts { get; } = + { + typeof(CandelabraOfSouls), typeof(GoldBricks), typeof(PhillipsWoodenSteed), + typeof(ArcticDeathDealer), typeof(BlazeOfDeath), typeof(BurglarsBandana), + typeof(CavortingClub), typeof(DreadPirateHat), + typeof(EnchantedTitanLegBone), typeof(GwennosHarp), typeof(IolosLute), + typeof(LunaLance), typeof(NightsKiss), typeof(NoxRangersHeavyCrossbow), + typeof(PolarBearMask), typeof(VioletCourage), typeof(HeartOfTheLion), + typeof(ColdBlood), typeof(AlchemistsBauble) + }; + + [CommandProperty(AccessLevel.GameMaster)] + public int Level { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Owner { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime DeleteTime { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Temporary { get; set; } + + public List Guardians { get; private set; } + + public override bool IsDecoContainer => false; + + private static void GetRandomAOSStats(out int attributeCount, out int min, out int max) + { + var rnd = Utility.Random(15); + + if (Core.SE) + { + if (rnd < 1) + { + attributeCount = Utility.RandomMinMax(3, 5); + min = 50; + max = 100; + } + else if (rnd < 3) + { + attributeCount = Utility.RandomMinMax(2, 5); + min = 40; + max = 80; + } + else if (rnd < 6) + { + attributeCount = Utility.RandomMinMax(2, 4); + min = 30; + max = 60; + } + else if (rnd < 10) + { + attributeCount = Utility.RandomMinMax(1, 3); + min = 20; + max = 40; + } + else + { + attributeCount = 1; + min = 10; + max = 20; + } + } + else + { + if (rnd < 1) + { + attributeCount = Utility.RandomMinMax(2, 5); + min = 20; + max = 70; + } + else if (rnd < 3) + { + attributeCount = Utility.RandomMinMax(2, 4); + min = 20; + max = 50; + } + else if (rnd < 6) + { + attributeCount = Utility.RandomMinMax(2, 3); + min = 20; + max = 40; + } + else if (rnd < 10) + { + attributeCount = Utility.RandomMinMax(1, 2); + min = 10; + max = 30; + } + else + { + attributeCount = 1; + min = 10; + max = 20; + } + } + } + + public static void Fill(LockableContainer cont, int level) + { + cont.Movable = false; + cont.Locked = true; + int numberItems; + + if (level == 0) + { + cont.LockLevel = 0; // Can't be unlocked + + cont.DropItem(new Gold(Utility.RandomMinMax(50, 100))); + + if (Utility.RandomDouble() < 0.75) + cont.DropItem(new TreasureMap(0, Map.Trammel)); + } + else + { + cont.TrapType = TrapType.ExplosionTrap; + cont.TrapPower = level * 25; + cont.TrapLevel = level; + + cont.RequiredSkill = level switch + { + 1 => 36, + 2 => 76, + 3 => 84, + 4 => 92, + 5 => 100, + 6 => 100, + _ => cont.RequiredSkill + }; + + cont.LockLevel = cont.RequiredSkill - 10; + cont.MaxLockLevel = cont.RequiredSkill + 40; + + // Publish 67 gold change + // if (Core.SA) + // cont.DropItem( new Gold( level * 5000 ) ); + // else + cont.DropItem(new Gold(level * 1000)); + + for (var i = 0; i < level * 5; ++i) + cont.DropItem(Loot.RandomScroll(0, 63, SpellbookType.Regular)); + + if (Core.SE) + numberItems = level switch + { + 1 => 5, + 2 => 10, + 3 => 15, + 4 => 38, + 5 => 50, + 6 => 60, + _ => 0 + }; + else + numberItems = level * 6; + + for (var i = 0; i < numberItems; ++i) + { + Item item; + + if (Core.AOS) + item = Loot.RandomArmorOrShieldOrWeaponOrJewelry(); + else + item = Loot.RandomArmorOrShieldOrWeapon(); + + if (item is BaseWeapon weapon) + { + if (Core.AOS) + { + GetRandomAOSStats(out var attributeCount, out var min, out var max); + BaseRunicTool.ApplyAttributesTo(weapon, attributeCount, min, max); + } + else + { + weapon.DamageLevel = (WeaponDamageLevel)Utility.Random(6); + weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random(6); + weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random(6); + } + + cont.DropItem(weapon); + } + else if (item is BaseArmor armor) + { + if (Core.AOS) + { + GetRandomAOSStats(out var attributeCount, out var min, out var max); + BaseRunicTool.ApplyAttributesTo(armor, attributeCount, min, max); + } + else + { + armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(6); + armor.Durability = (ArmorDurabilityLevel)Utility.Random(6); + } + + cont.DropItem(armor); + } + else if (item is BaseHat hat) + { + if (Core.AOS) + { + GetRandomAOSStats(out var attributeCount, out var min, out var max); + BaseRunicTool.ApplyAttributesTo(hat, attributeCount, min, max); + } + + cont.DropItem(hat); + } + else if (item is BaseJewel jewel) + { + GetRandomAOSStats(out var attributeCount, out var min, out var max); + BaseRunicTool.ApplyAttributesTo(jewel, attributeCount, min, max); + + cont.DropItem(jewel); + } + } + } + + int reagents; + if (level == 0) + reagents = 12; + else + reagents = level * 3; + + for (var i = 0; i < reagents; i++) + { + var item = Loot.RandomPossibleReagent(); + item.Amount = Utility.RandomMinMax(40, 60); + cont.DropItem(item); + } + + int gems; + if (level == 0) + gems = 2; + else + gems = level * 3; + + for (var i = 0; i < gems; i++) + { + var item = Loot.RandomGem(); + cont.DropItem(item); + } + + if (level == 6 && Core.AOS) + cont.DropItem((Item)ActivatorUtil.CreateInstance(Artifacts.RandomElement())); + } + + public override bool CheckLocked(Mobile from) + { + if (!Locked) + return false; + + if (Level == 0 && from.AccessLevel < AccessLevel.GameMaster) + { + foreach (var m in Guardians) + if (m.Alive) + { + from.SendLocalizedMessage( + 1046448 + ); // You must first kill the guardians before you may open this chest. + return true; + } + + LockPick(from); + return false; + } + + return base.CheckLocked(from); + } + + private bool CheckLoot(Mobile m, bool criminalAction) + { + if (Temporary) + return false; + + if (m.AccessLevel >= AccessLevel.GameMaster || Owner == null || m == Owner) + return true; + + if (Party.Get(Owner)?.Contains(m) == true) + return true; + + var map = Map; + + if ((map?.Rules & MapRules.HarmfulRestrictions) == 0) + { + if (criminalAction) + m.CriminalAction(true); + else + m.SendLocalizedMessage(1010630); // Taking someone else's treasure is a criminal offense! + + return true; + } + + m.SendLocalizedMessage(1010631); // You did not discover this chest! + return false; + } + + public override bool CheckItemUse(Mobile from, Item item) => + CheckLoot(from, item != this) && base.CheckItemUse(from, item); + + public override bool CheckLift(Mobile from, Item item, ref LRReason reject) => + CheckLoot(from, true) && base.CheckLift(from, item, ref reject); + + public override void OnItemLifted(Mobile from, Item item) + { + var notYetLifted = !m_Lifted.Contains(item); + + from.RevealingAction(); + + if (notYetLifted) + { + m_Lifted.Add(item); + + if (Utility.RandomDouble() <= 0.1) // 10% chance to spawn a new monster + TreasureMap.Spawn(Level, GetWorldLocation(), Map, from, false); + } + + base.OnItemLifted(from, item); + } + + public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight) + { + if (m.AccessLevel < AccessLevel.GameMaster) + { + m.SendLocalizedMessage(1048122, "", 0x8A5); // The chest refuses to be filled with treasure again. + return false; + } + + return base.CheckHold(m, item, message, checkItems, plusItems, plusWeight); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(2); // version + + writer.Write(Guardians, true); + writer.Write(Temporary); + + writer.Write(Owner); + + writer.Write(Level); + writer.WriteDeltaTime(DeleteTime); + writer.Write(m_Lifted, true); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 2: + { + Guardians = reader.ReadStrongMobileList(); + Temporary = reader.ReadBool(); + + goto case 1; + } + case 1: + { + Owner = reader.ReadMobile(); + + goto case 0; + } + case 0: + { + Level = reader.ReadInt(); + DeleteTime = reader.ReadDeltaTime(); + m_Lifted = reader.ReadStrongItemList(); + + if (version < 2) + Guardians = new List(); + + break; + } + } + + if (!Temporary) + { + m_Timer = new DeleteTimer(this, DeleteTime); + m_Timer.Start(); + } + else + { + Delete(); + } + } + + public override void OnAfterDelete() + { + m_Timer?.Stop(); + + m_Timer = null; + + base.OnAfterDelete(); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (from.Alive) + list.Add(new RemoveEntry(from, this)); + } + + public void BeginRemove(Mobile from) + { + if (!from.Alive) + return; + + from.CloseGump(); + from.SendGump(new RemoveGump(from, this)); + } + + public void EndRemove(Mobile from) + { + if (Deleted || from != Owner || !from.InRange(GetWorldLocation(), 3)) + return; + + from.SendLocalizedMessage(1048124, "", 0x8A5); // The old, rusted chest crumbles when you hit it. + Delete(); + } + + private class RemoveGump : Gump + { + private readonly TreasureMapChest m_Chest; + private readonly Mobile m_From; + + public RemoveGump(Mobile from, TreasureMapChest chest) : base(15, 15) + { + m_From = from; + m_Chest = chest; + + Closable = false; + Disposable = false; + + AddPage(0); + + AddBackground(30, 0, 240, 240, 2620); + + AddHtmlLocalized( + 45, + 15, + 200, + 80, + 1048125, + 0xFFFFFF + ); // When this treasure chest is removed, any items still inside of it will be lost. + AddHtmlLocalized(45, 95, 200, 60, 1048126, 0xFFFFFF); // Are you certain you're ready to remove this chest? + + AddButton(40, 153, 4005, 4007, 1); + AddHtmlLocalized(75, 155, 180, 40, 1048127, 0xFFFFFF); // Remove the Treasure Chest + + AddButton(40, 195, 4005, 4007, 2); + AddHtmlLocalized(75, 197, 180, 35, 1006045, 0xFFFFFF); // Cancel + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 1) + m_Chest.EndRemove(m_From); + } + } + + private class RemoveEntry : ContextMenuEntry + { + private readonly TreasureMapChest m_Chest; + private readonly Mobile m_From; + + public RemoveEntry(Mobile from, TreasureMapChest chest) : base(6149, 3) + { + m_From = from; + m_Chest = chest; + + Enabled = from == chest.Owner; + } + + public override void OnClick() + { + if (m_Chest.Deleted || m_From != m_Chest.Owner || !m_From.CheckAlive()) + return; + + m_Chest.BeginRemove(m_From); + } + } + + private class DeleteTimer : Timer + { + private readonly Item m_Item; + + public DeleteTimer(Item item, DateTime time) : base(time - DateTime.UtcNow) + { + m_Item = item; + Priority = TimerPriority.OneMinute; + } + + protected override void OnTick() + { + m_Item.Delete(); + } + } + } +} diff --git a/Projects/UOContent/Items/Decoration Artifacts/BaseDecorationArtifact.cs b/Projects/UOContent/Items/Decoration Artifacts/BaseDecorationArtifact.cs index 1e1981c50..4cdc905c8 100644 --- a/Projects/UOContent/Items/Decoration Artifacts/BaseDecorationArtifact.cs +++ b/Projects/UOContent/Items/Decoration Artifacts/BaseDecorationArtifact.cs @@ -1,70 +1,70 @@ -namespace Server.Items -{ - public abstract class BaseDecorationArtifact : Item - { - public BaseDecorationArtifact(int itemID) : base(itemID) => Weight = 10.0; - - public BaseDecorationArtifact(Serial serial) : base(serial) - { - } - - public abstract int ArtifactRarity { get; } - - public override bool ForceShowProperties => true; - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1061078, ArtifactRarity.ToString()); // artifact rarity ~1_val~ - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public abstract class BaseDecorationContainerArtifact : BaseContainer - { - public BaseDecorationContainerArtifact(int itemID) : base(itemID) => Weight = 10.0; - - public BaseDecorationContainerArtifact(Serial serial) : base(serial) - { - } - - public abstract int ArtifactRarity { get; } - - public override bool ForceShowProperties => true; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - list.Add(1061078, ArtifactRarity.ToString()); // artifact rarity ~1_val~ - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public abstract class BaseDecorationArtifact : Item + { + public BaseDecorationArtifact(int itemID) : base(itemID) => Weight = 10.0; + + public BaseDecorationArtifact(Serial serial) : base(serial) + { + } + + public abstract int ArtifactRarity { get; } + + public override bool ForceShowProperties => true; + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1061078, ArtifactRarity.ToString()); // artifact rarity ~1_val~ + } + + 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(); + } + } + + public abstract class BaseDecorationContainerArtifact : BaseContainer + { + public BaseDecorationContainerArtifact(int itemID) : base(itemID) => Weight = 10.0; + + public BaseDecorationContainerArtifact(Serial serial) : base(serial) + { + } + + public abstract int ArtifactRarity { get; } + + public override bool ForceShowProperties => true; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + list.Add(1061078, ArtifactRarity.ToString()); // artifact rarity ~1_val~ + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Decoration Artifacts/DoomDecorationArtifacts.cs b/Projects/UOContent/Items/Decoration Artifacts/DoomDecorationArtifacts.cs index 90e89d8c1..b920a1c35 100644 --- a/Projects/UOContent/Items/Decoration Artifacts/DoomDecorationArtifacts.cs +++ b/Projects/UOContent/Items/Decoration Artifacts/DoomDecorationArtifacts.cs @@ -1,640 +1,640 @@ -namespace Server.Items -{ - public class BackpackArtifact : BaseDecorationContainerArtifact - { - [Constructible] - public BackpackArtifact() : base(0x9B2) - { - } - - public BackpackArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 5; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BloodyWaterArtifact : BaseDecorationArtifact - { - [Constructible] - public BloodyWaterArtifact() : base(0xE23) - { - } - - public BloodyWaterArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 5; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BooksWestArtifact : BaseDecorationArtifact - { - [Constructible] - public BooksWestArtifact() : base(0x1E25) - { - } - - public BooksWestArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 3; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BooksNorthArtifact : BaseDecorationArtifact - { - [Constructible] - public BooksNorthArtifact() : base(0x1E24) - { - } - - public BooksNorthArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 3; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BooksFaceDownArtifact : BaseDecorationArtifact - { - [Constructible] - public BooksFaceDownArtifact() : base(0x1E21) - { - } - - public BooksFaceDownArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 3; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BottleArtifact : BaseDecorationArtifact - { - [Constructible] - public BottleArtifact() : base(0xE28) - { - } - - public BottleArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BrazierArtifact : BaseDecorationArtifact - { - [Constructible] - public BrazierArtifact() : base(0xE31) => Light = LightType.Circle150; - - public BrazierArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 2; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class CocoonArtifact : BaseDecorationArtifact - { - [Constructible] - public CocoonArtifact() : base(0x10DA) - { - } - - public CocoonArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 7; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class DamagedBooksArtifact : BaseDecorationArtifact - { - [Constructible] - public DamagedBooksArtifact() : base(0xC16) - { - } - - public DamagedBooksArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class EggCaseArtifact : BaseDecorationArtifact - { - [Constructible] - public EggCaseArtifact() : base(0x10D9) - { - } - - public EggCaseArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 5; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class GruesomeStandardArtifact : BaseDecorationArtifact - { - [Constructible] - public GruesomeStandardArtifact() : base(0x428) - { - } - - public GruesomeStandardArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 5; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class LampPostArtifact : BaseDecorationArtifact - { - [Constructible] - public LampPostArtifact() : base(0xB24) => Light = LightType.Circle300; - - public LampPostArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 3; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class LeatherTunicArtifact : BaseDecorationArtifact - { - [Constructible] - public LeatherTunicArtifact() : base(0x13CA) - { - } - - public LeatherTunicArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 9; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class RockArtifact : BaseDecorationArtifact - { - [Constructible] - public RockArtifact() : base(0x1363) - { - } - - public RockArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class RuinedPaintingArtifact : BaseDecorationArtifact - { - [Constructible] - public RuinedPaintingArtifact() : base(0xC2C) - { - } - - public RuinedPaintingArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 12; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SaddleArtifact : BaseDecorationArtifact - { - [Constructible] - public SaddleArtifact() : base(0xF38) - { - } - - public SaddleArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 9; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SkinnedDeerArtifact : BaseDecorationArtifact - { - [Constructible] - public SkinnedDeerArtifact() : base(0x1E91) - { - } - - public SkinnedDeerArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 8; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SkinnedGoatArtifact : BaseDecorationArtifact - { - [Constructible] - public SkinnedGoatArtifact() : base(0x1E88) - { - } - - public SkinnedGoatArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 5; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SkullCandleArtifact : BaseDecorationArtifact - { - [Constructible] - public SkullCandleArtifact() : base(0x1858) => Light = LightType.Circle150; - - public SkullCandleArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class StretchedHideArtifact : BaseDecorationArtifact - { - [Constructible] - public StretchedHideArtifact() : base(0x106B) - { - } - - public StretchedHideArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 2; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class StuddedLeggingsArtifact : BaseDecorationArtifact - { - [Constructible] - public StuddedLeggingsArtifact() : base(0x13D8) - { - } - - public StuddedLeggingsArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 5; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class StuddedTunicArtifact : BaseDecorationArtifact - { - [Constructible] - public StuddedTunicArtifact() : base(0x13D9) - { - } - - public StuddedTunicArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 7; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TarotCardsArtifact : BaseDecorationArtifact - { - [Constructible] - public TarotCardsArtifact() : base(0x12A5) - { - } - - public TarotCardsArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 5; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class BackpackArtifact : BaseDecorationContainerArtifact + { + [Constructible] + public BackpackArtifact() : base(0x9B2) + { + } + + public BackpackArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 5; + + 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(); + } + } + + public class BloodyWaterArtifact : BaseDecorationArtifact + { + [Constructible] + public BloodyWaterArtifact() : base(0xE23) + { + } + + public BloodyWaterArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 5; + + 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(); + } + } + + public class BooksWestArtifact : BaseDecorationArtifact + { + [Constructible] + public BooksWestArtifact() : base(0x1E25) + { + } + + public BooksWestArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 3; + + 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(); + } + } + + public class BooksNorthArtifact : BaseDecorationArtifact + { + [Constructible] + public BooksNorthArtifact() : base(0x1E24) + { + } + + public BooksNorthArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 3; + + 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(); + } + } + + public class BooksFaceDownArtifact : BaseDecorationArtifact + { + [Constructible] + public BooksFaceDownArtifact() : base(0x1E21) + { + } + + public BooksFaceDownArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 3; + + 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(); + } + } + + public class BottleArtifact : BaseDecorationArtifact + { + [Constructible] + public BottleArtifact() : base(0xE28) + { + } + + public BottleArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 1; + + 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(); + } + } + + public class BrazierArtifact : BaseDecorationArtifact + { + [Constructible] + public BrazierArtifact() : base(0xE31) => Light = LightType.Circle150; + + public BrazierArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 2; + + 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(); + } + } + + public class CocoonArtifact : BaseDecorationArtifact + { + [Constructible] + public CocoonArtifact() : base(0x10DA) + { + } + + public CocoonArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 7; + + 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(); + } + } + + public class DamagedBooksArtifact : BaseDecorationArtifact + { + [Constructible] + public DamagedBooksArtifact() : base(0xC16) + { + } + + public DamagedBooksArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 1; + + 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(); + } + } + + public class EggCaseArtifact : BaseDecorationArtifact + { + [Constructible] + public EggCaseArtifact() : base(0x10D9) + { + } + + public EggCaseArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 5; + + 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(); + } + } + + public class GruesomeStandardArtifact : BaseDecorationArtifact + { + [Constructible] + public GruesomeStandardArtifact() : base(0x428) + { + } + + public GruesomeStandardArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 5; + + 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(); + } + } + + public class LampPostArtifact : BaseDecorationArtifact + { + [Constructible] + public LampPostArtifact() : base(0xB24) => Light = LightType.Circle300; + + public LampPostArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 3; + + 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(); + } + } + + public class LeatherTunicArtifact : BaseDecorationArtifact + { + [Constructible] + public LeatherTunicArtifact() : base(0x13CA) + { + } + + public LeatherTunicArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 9; + + 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(); + } + } + + public class RockArtifact : BaseDecorationArtifact + { + [Constructible] + public RockArtifact() : base(0x1363) + { + } + + public RockArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 1; + + 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(); + } + } + + public class RuinedPaintingArtifact : BaseDecorationArtifact + { + [Constructible] + public RuinedPaintingArtifact() : base(0xC2C) + { + } + + public RuinedPaintingArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 12; + + 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(); + } + } + + public class SaddleArtifact : BaseDecorationArtifact + { + [Constructible] + public SaddleArtifact() : base(0xF38) + { + } + + public SaddleArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 9; + + 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(); + } + } + + public class SkinnedDeerArtifact : BaseDecorationArtifact + { + [Constructible] + public SkinnedDeerArtifact() : base(0x1E91) + { + } + + public SkinnedDeerArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 8; + + 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(); + } + } + + public class SkinnedGoatArtifact : BaseDecorationArtifact + { + [Constructible] + public SkinnedGoatArtifact() : base(0x1E88) + { + } + + public SkinnedGoatArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 5; + + 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(); + } + } + + public class SkullCandleArtifact : BaseDecorationArtifact + { + [Constructible] + public SkullCandleArtifact() : base(0x1858) => Light = LightType.Circle150; + + public SkullCandleArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 1; + + 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(); + } + } + + public class StretchedHideArtifact : BaseDecorationArtifact + { + [Constructible] + public StretchedHideArtifact() : base(0x106B) + { + } + + public StretchedHideArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 2; + + 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(); + } + } + + public class StuddedLeggingsArtifact : BaseDecorationArtifact + { + [Constructible] + public StuddedLeggingsArtifact() : base(0x13D8) + { + } + + public StuddedLeggingsArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 5; + + 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(); + } + } + + public class StuddedTunicArtifact : BaseDecorationArtifact + { + [Constructible] + public StuddedTunicArtifact() : base(0x13D9) + { + } + + public StuddedTunicArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 7; + + 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(); + } + } + + public class TarotCardsArtifact : BaseDecorationArtifact + { + [Constructible] + public TarotCardsArtifact() : base(0x12A5) + { + } + + public TarotCardsArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 5; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Decoration Artifacts/SEDecorationArtifacts.cs b/Projects/UOContent/Items/Decoration Artifacts/SEDecorationArtifacts.cs index de0c4dbfc..07d3ae445 100644 --- a/Projects/UOContent/Items/Decoration Artifacts/SEDecorationArtifacts.cs +++ b/Projects/UOContent/Items/Decoration Artifacts/SEDecorationArtifacts.cs @@ -1,1517 +1,1517 @@ -using Server.Network; - -namespace Server.Items -{ - public class Basket1Artifact : BaseDecorationContainerArtifact - { - [Constructible] - public Basket1Artifact() : base(0x24DD) - { - } - - public Basket1Artifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class Basket2Artifact : BaseDecorationContainerArtifact - { - [Constructible] - public Basket2Artifact() : base(0x24D7) - { - } - - public Basket2Artifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class Basket3WestArtifact : BaseDecorationContainerArtifact - { - [Constructible] - public Basket3WestArtifact() : base(0x24D9) - { - } - - public Basket3WestArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class Basket3NorthArtifact : BaseDecorationContainerArtifact - { - [Constructible] - public Basket3NorthArtifact() : base(0x24DA) - { - } - - public Basket3NorthArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class Basket4Artifact : BaseDecorationContainerArtifact - { - [Constructible] - public Basket4Artifact() : base(0x24D8) - { - } - - public Basket4Artifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 2; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class Basket5WestArtifact : BaseDecorationContainerArtifact - { - [Constructible] - public Basket5WestArtifact() : base(0x24DC) - { - } - - public Basket5WestArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 2; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class Basket5NorthArtifact : BaseDecorationContainerArtifact - { - [Constructible] - public Basket5NorthArtifact() : base(0x24DB) - { - } - - public Basket5NorthArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 2; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class Basket6Artifact : BaseDecorationContainerArtifact - { - [Constructible] - public Basket6Artifact() : base(0x24D5) - { - } - - public Basket6Artifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 2; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BowlArtifact : BaseDecorationArtifact - { - [Constructible] - public BowlArtifact() : base(0x24DE) - { - } - - public BowlArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 4; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BowlsVerticalArtifact : BaseDecorationArtifact - { - [Constructible] - public BowlsVerticalArtifact() : base(0x24DF) - { - } - - public BowlsVerticalArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 3; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BowlsHorizontalArtifact : BaseDecorationArtifact - { - [Constructible] - public BowlsHorizontalArtifact() : base(0x24E0) - { - } - - public BowlsHorizontalArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 4; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class CupsArtifact : BaseDecorationArtifact - { - [Constructible] - public CupsArtifact() : base(0x24E1) - { - } - - public CupsArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 4; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class FanWestArtifact : BaseDecorationArtifact - { - [Constructible] - public FanWestArtifact() : base(0x240A) - { - } - - public FanWestArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 3; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class FanNorthArtifact : BaseDecorationArtifact - { - [Constructible] - public FanNorthArtifact() : base(0x2409) - { - } - - public FanNorthArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 3; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TripleFanWestArtifact : BaseDecorationArtifact - { - [Constructible] - public TripleFanWestArtifact() : base(0x240C) - { - } - - public TripleFanWestArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 4; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TripleFanNorthArtifact : BaseDecorationArtifact - { - [Constructible] - public TripleFanNorthArtifact() : base(0x240B) - { - } - - public TripleFanNorthArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 4; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class FlowersArtifact : BaseDecorationArtifact - { - [Constructible] - public FlowersArtifact() : base(0x284A) - { - } - - public FlowersArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 7; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class Painting1WestArtifact : BaseDecorationArtifact - { - [Constructible] - public Painting1WestArtifact() : base(0x240E) - { - } - - public Painting1WestArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 4; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class Painting1NorthArtifact : BaseDecorationArtifact - { - [Constructible] - public Painting1NorthArtifact() : base(0x240D) - { - } - - public Painting1NorthArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 4; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class Painting2WestArtifact : BaseDecorationArtifact - { - [Constructible] - public Painting2WestArtifact() : base(0x2410) - { - } - - public Painting2WestArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 4; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class Painting2NorthArtifact : BaseDecorationArtifact - { - [Constructible] - public Painting2NorthArtifact() : base(0x240F) - { - } - - public Painting2NorthArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 4; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class Painting3Artifact : BaseDecorationArtifact - { - [Constructible] - public Painting3Artifact() : base(0x2411) - { - } - - public Painting3Artifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 5; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class Painting4WestArtifact : BaseDecorationArtifact - { - [Constructible] - public Painting4WestArtifact() : base(0x2412) - { - } - - public Painting4WestArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 6; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class Painting4NorthArtifact : BaseDecorationArtifact - { - [Constructible] - public Painting4NorthArtifact() : base(0x2411) - { - } - - public Painting4NorthArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 6; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class Painting5WestArtifact : BaseDecorationArtifact - { - [Constructible] - public Painting5WestArtifact() : base(0x2416) - { - } - - public Painting5WestArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 8; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class Painting5NorthArtifact : BaseDecorationArtifact - { - [Constructible] - public Painting5NorthArtifact() : base(0x2415) - { - } - - public Painting5NorthArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 8; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class Painting6WestArtifact : BaseDecorationArtifact - { - [Constructible] - public Painting6WestArtifact() : base(0x2418) - { - } - - public Painting6WestArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 9; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class Painting6NorthArtifact : BaseDecorationArtifact - { - [Constructible] - public Painting6NorthArtifact() : base(0x2417) - { - } - - public Painting6NorthArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 9; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SakeArtifact : BaseDecorationArtifact - { - [Constructible] - public SakeArtifact() : base(0x24E2) - { - } - - public SakeArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 4; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class Sculpture1Artifact : BaseDecorationArtifact - { - [Constructible] - public Sculpture1Artifact() : base(0x2419) - { - } - - public Sculpture1Artifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 3; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class Sculpture2Artifact : BaseDecorationArtifact - { - [Constructible] - public Sculpture2Artifact() : base(0x241B) - { - } - - public Sculpture2Artifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 3; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class DolphinLeftArtifact : BaseDecorationArtifact - { - [Constructible] - public DolphinLeftArtifact() : base(0x2846) - { - } - - public DolphinLeftArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 8; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class DolphinRightArtifact : BaseDecorationArtifact - { - [Constructible] - public DolphinRightArtifact() : base(0x2847) - { - } - - public DolphinRightArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 8; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ManStatuetteSouthArtifact : BaseDecorationArtifact - { - [Constructible] - public ManStatuetteSouthArtifact() : base(0x2848) - { - } - - public ManStatuetteSouthArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 9; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ManStatuetteEastArtifact : BaseDecorationArtifact - { - [Constructible] - public ManStatuetteEastArtifact() : base(0x2849) - { - } - - public ManStatuetteEastArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 9; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SwordDisplay1WestArtifact : BaseDecorationArtifact - { - [Constructible] - public SwordDisplay1WestArtifact() : base(0x2842) - { - } - - public SwordDisplay1WestArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 5; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SwordDisplay1NorthArtifact : BaseDecorationArtifact - { - [Constructible] - public SwordDisplay1NorthArtifact() : base(0x2843) - { - } - - public SwordDisplay1NorthArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 5; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SwordDisplay2WestArtifact : BaseDecorationArtifact - { - [Constructible] - public SwordDisplay2WestArtifact() : base(0x2844) - { - } - - public SwordDisplay2WestArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 6; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SwordDisplay2NorthArtifact : BaseDecorationArtifact - { - [Constructible] - public SwordDisplay2NorthArtifact() : base(0x2845) - { - } - - public SwordDisplay2NorthArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 6; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SwordDisplay3SouthArtifact : BaseDecorationArtifact - { - [Constructible] - public SwordDisplay3SouthArtifact() : base(0x2855) - { - } - - public SwordDisplay3SouthArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 8; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SwordDisplay3EastArtifact : BaseDecorationArtifact - { - [Constructible] - public SwordDisplay3EastArtifact() : base(0x2856) - { - } - - public SwordDisplay3EastArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 8; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SwordDisplay4WestArtifact : BaseDecorationArtifact - { - [Constructible] - public SwordDisplay4WestArtifact() : base(0x2853) - { - } - - public SwordDisplay4WestArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 8; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SwordDisplay4NorthArtifact : BaseDecorationArtifact - { - [Constructible] - public SwordDisplay4NorthArtifact() : base(0x2854) - { - } - - public SwordDisplay4NorthArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 9; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SwordDisplay5WestArtifact : BaseDecorationArtifact - { - [Constructible] - public SwordDisplay5WestArtifact() : base(0x2851) - { - } - - public SwordDisplay5WestArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 9; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SwordDisplay5NorthArtifact : BaseDecorationArtifact - { - [Constructible] - public SwordDisplay5NorthArtifact() : base(0x2852) - { - } - - public SwordDisplay5NorthArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 9; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TeapotWestArtifact : BaseDecorationArtifact - { - [Constructible] - public TeapotWestArtifact() : base(0x24E7) - { - } - - public TeapotWestArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 3; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TeapotNorthArtifact : BaseDecorationArtifact - { - [Constructible] - public TeapotNorthArtifact() : base(0x24E6) - { - } - - public TeapotNorthArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 3; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TowerLanternArtifact : BaseDecorationArtifact - { - [Constructible] - public TowerLanternArtifact() : base(0x24C0) => Light = LightType.Circle225; - - public TowerLanternArtifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 3; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsOn - { - get => ItemID == 0x24BF; - set => ItemID = value ? 0x24BF : 0x24C0; - } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(GetWorldLocation(), 2)) - { - if (IsOn) - { - IsOn = false; - from.PlaySound(0x3BE); - } - else - { - IsOn = true; - from.PlaySound(0x47); - } - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - if (version == 0) - Light = LightType.Circle225; - } - } - - public class Urn1Artifact : BaseDecorationArtifact - { - [Constructible] - public Urn1Artifact() : base(0x241D) - { - } - - public Urn1Artifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 3; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class Urn2Artifact : BaseDecorationArtifact - { - [Constructible] - public Urn2Artifact() : base(0x241E) - { - } - - public Urn2Artifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 3; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ZenRock1Artifact : BaseDecorationArtifact - { - [Constructible] - public ZenRock1Artifact() : base(0x24E4) - { - } - - public ZenRock1Artifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 2; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ZenRock2Artifact : BaseDecorationArtifact - { - [Constructible] - public ZenRock2Artifact() : base(0x24E3) - { - } - - public ZenRock2Artifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 3; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ZenRock3Artifact : BaseDecorationArtifact - { - [Constructible] - public ZenRock3Artifact() : base(0x24E5) - { - } - - public ZenRock3Artifact(Serial serial) : base(serial) - { - } - - public override int ArtifactRarity => 3; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +using Server.Network; + +namespace Server.Items +{ + public class Basket1Artifact : BaseDecorationContainerArtifact + { + [Constructible] + public Basket1Artifact() : base(0x24DD) + { + } + + public Basket1Artifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 1; + + 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(); + } + } + + public class Basket2Artifact : BaseDecorationContainerArtifact + { + [Constructible] + public Basket2Artifact() : base(0x24D7) + { + } + + public Basket2Artifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 1; + + 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(); + } + } + + public class Basket3WestArtifact : BaseDecorationContainerArtifact + { + [Constructible] + public Basket3WestArtifact() : base(0x24D9) + { + } + + public Basket3WestArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 1; + + 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(); + } + } + + public class Basket3NorthArtifact : BaseDecorationContainerArtifact + { + [Constructible] + public Basket3NorthArtifact() : base(0x24DA) + { + } + + public Basket3NorthArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 1; + + 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(); + } + } + + public class Basket4Artifact : BaseDecorationContainerArtifact + { + [Constructible] + public Basket4Artifact() : base(0x24D8) + { + } + + public Basket4Artifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 2; + + 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(); + } + } + + public class Basket5WestArtifact : BaseDecorationContainerArtifact + { + [Constructible] + public Basket5WestArtifact() : base(0x24DC) + { + } + + public Basket5WestArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 2; + + 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(); + } + } + + public class Basket5NorthArtifact : BaseDecorationContainerArtifact + { + [Constructible] + public Basket5NorthArtifact() : base(0x24DB) + { + } + + public Basket5NorthArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 2; + + 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(); + } + } + + public class Basket6Artifact : BaseDecorationContainerArtifact + { + [Constructible] + public Basket6Artifact() : base(0x24D5) + { + } + + public Basket6Artifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 2; + + 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(); + } + } + + public class BowlArtifact : BaseDecorationArtifact + { + [Constructible] + public BowlArtifact() : base(0x24DE) + { + } + + public BowlArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 4; + + 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(); + } + } + + public class BowlsVerticalArtifact : BaseDecorationArtifact + { + [Constructible] + public BowlsVerticalArtifact() : base(0x24DF) + { + } + + public BowlsVerticalArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 3; + + 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(); + } + } + + public class BowlsHorizontalArtifact : BaseDecorationArtifact + { + [Constructible] + public BowlsHorizontalArtifact() : base(0x24E0) + { + } + + public BowlsHorizontalArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 4; + + 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(); + } + } + + public class CupsArtifact : BaseDecorationArtifact + { + [Constructible] + public CupsArtifact() : base(0x24E1) + { + } + + public CupsArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 4; + + 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(); + } + } + + public class FanWestArtifact : BaseDecorationArtifact + { + [Constructible] + public FanWestArtifact() : base(0x240A) + { + } + + public FanWestArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 3; + + 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(); + } + } + + public class FanNorthArtifact : BaseDecorationArtifact + { + [Constructible] + public FanNorthArtifact() : base(0x2409) + { + } + + public FanNorthArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 3; + + 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(); + } + } + + public class TripleFanWestArtifact : BaseDecorationArtifact + { + [Constructible] + public TripleFanWestArtifact() : base(0x240C) + { + } + + public TripleFanWestArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 4; + + 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(); + } + } + + public class TripleFanNorthArtifact : BaseDecorationArtifact + { + [Constructible] + public TripleFanNorthArtifact() : base(0x240B) + { + } + + public TripleFanNorthArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 4; + + 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(); + } + } + + public class FlowersArtifact : BaseDecorationArtifact + { + [Constructible] + public FlowersArtifact() : base(0x284A) + { + } + + public FlowersArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 7; + + 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(); + } + } + + public class Painting1WestArtifact : BaseDecorationArtifact + { + [Constructible] + public Painting1WestArtifact() : base(0x240E) + { + } + + public Painting1WestArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 4; + + 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(); + } + } + + public class Painting1NorthArtifact : BaseDecorationArtifact + { + [Constructible] + public Painting1NorthArtifact() : base(0x240D) + { + } + + public Painting1NorthArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 4; + + 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(); + } + } + + public class Painting2WestArtifact : BaseDecorationArtifact + { + [Constructible] + public Painting2WestArtifact() : base(0x2410) + { + } + + public Painting2WestArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 4; + + 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(); + } + } + + public class Painting2NorthArtifact : BaseDecorationArtifact + { + [Constructible] + public Painting2NorthArtifact() : base(0x240F) + { + } + + public Painting2NorthArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 4; + + 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(); + } + } + + public class Painting3Artifact : BaseDecorationArtifact + { + [Constructible] + public Painting3Artifact() : base(0x2411) + { + } + + public Painting3Artifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 5; + + 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(); + } + } + + public class Painting4WestArtifact : BaseDecorationArtifact + { + [Constructible] + public Painting4WestArtifact() : base(0x2412) + { + } + + public Painting4WestArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 6; + + 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(); + } + } + + public class Painting4NorthArtifact : BaseDecorationArtifact + { + [Constructible] + public Painting4NorthArtifact() : base(0x2411) + { + } + + public Painting4NorthArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 6; + + 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(); + } + } + + public class Painting5WestArtifact : BaseDecorationArtifact + { + [Constructible] + public Painting5WestArtifact() : base(0x2416) + { + } + + public Painting5WestArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 8; + + 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(); + } + } + + public class Painting5NorthArtifact : BaseDecorationArtifact + { + [Constructible] + public Painting5NorthArtifact() : base(0x2415) + { + } + + public Painting5NorthArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 8; + + 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(); + } + } + + public class Painting6WestArtifact : BaseDecorationArtifact + { + [Constructible] + public Painting6WestArtifact() : base(0x2418) + { + } + + public Painting6WestArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 9; + + 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(); + } + } + + public class Painting6NorthArtifact : BaseDecorationArtifact + { + [Constructible] + public Painting6NorthArtifact() : base(0x2417) + { + } + + public Painting6NorthArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 9; + + 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(); + } + } + + public class SakeArtifact : BaseDecorationArtifact + { + [Constructible] + public SakeArtifact() : base(0x24E2) + { + } + + public SakeArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 4; + + 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(); + } + } + + public class Sculpture1Artifact : BaseDecorationArtifact + { + [Constructible] + public Sculpture1Artifact() : base(0x2419) + { + } + + public Sculpture1Artifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 3; + + 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(); + } + } + + public class Sculpture2Artifact : BaseDecorationArtifact + { + [Constructible] + public Sculpture2Artifact() : base(0x241B) + { + } + + public Sculpture2Artifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 3; + + 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(); + } + } + + public class DolphinLeftArtifact : BaseDecorationArtifact + { + [Constructible] + public DolphinLeftArtifact() : base(0x2846) + { + } + + public DolphinLeftArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 8; + + 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(); + } + } + + public class DolphinRightArtifact : BaseDecorationArtifact + { + [Constructible] + public DolphinRightArtifact() : base(0x2847) + { + } + + public DolphinRightArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 8; + + 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(); + } + } + + public class ManStatuetteSouthArtifact : BaseDecorationArtifact + { + [Constructible] + public ManStatuetteSouthArtifact() : base(0x2848) + { + } + + public ManStatuetteSouthArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 9; + + 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(); + } + } + + public class ManStatuetteEastArtifact : BaseDecorationArtifact + { + [Constructible] + public ManStatuetteEastArtifact() : base(0x2849) + { + } + + public ManStatuetteEastArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 9; + + 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(); + } + } + + public class SwordDisplay1WestArtifact : BaseDecorationArtifact + { + [Constructible] + public SwordDisplay1WestArtifact() : base(0x2842) + { + } + + public SwordDisplay1WestArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 5; + + 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(); + } + } + + public class SwordDisplay1NorthArtifact : BaseDecorationArtifact + { + [Constructible] + public SwordDisplay1NorthArtifact() : base(0x2843) + { + } + + public SwordDisplay1NorthArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 5; + + 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(); + } + } + + public class SwordDisplay2WestArtifact : BaseDecorationArtifact + { + [Constructible] + public SwordDisplay2WestArtifact() : base(0x2844) + { + } + + public SwordDisplay2WestArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 6; + + 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(); + } + } + + public class SwordDisplay2NorthArtifact : BaseDecorationArtifact + { + [Constructible] + public SwordDisplay2NorthArtifact() : base(0x2845) + { + } + + public SwordDisplay2NorthArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 6; + + 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(); + } + } + + public class SwordDisplay3SouthArtifact : BaseDecorationArtifact + { + [Constructible] + public SwordDisplay3SouthArtifact() : base(0x2855) + { + } + + public SwordDisplay3SouthArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 8; + + 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(); + } + } + + public class SwordDisplay3EastArtifact : BaseDecorationArtifact + { + [Constructible] + public SwordDisplay3EastArtifact() : base(0x2856) + { + } + + public SwordDisplay3EastArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 8; + + 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(); + } + } + + public class SwordDisplay4WestArtifact : BaseDecorationArtifact + { + [Constructible] + public SwordDisplay4WestArtifact() : base(0x2853) + { + } + + public SwordDisplay4WestArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 8; + + 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(); + } + } + + public class SwordDisplay4NorthArtifact : BaseDecorationArtifact + { + [Constructible] + public SwordDisplay4NorthArtifact() : base(0x2854) + { + } + + public SwordDisplay4NorthArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 9; + + 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(); + } + } + + public class SwordDisplay5WestArtifact : BaseDecorationArtifact + { + [Constructible] + public SwordDisplay5WestArtifact() : base(0x2851) + { + } + + public SwordDisplay5WestArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 9; + + 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(); + } + } + + public class SwordDisplay5NorthArtifact : BaseDecorationArtifact + { + [Constructible] + public SwordDisplay5NorthArtifact() : base(0x2852) + { + } + + public SwordDisplay5NorthArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 9; + + 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(); + } + } + + public class TeapotWestArtifact : BaseDecorationArtifact + { + [Constructible] + public TeapotWestArtifact() : base(0x24E7) + { + } + + public TeapotWestArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 3; + + 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(); + } + } + + public class TeapotNorthArtifact : BaseDecorationArtifact + { + [Constructible] + public TeapotNorthArtifact() : base(0x24E6) + { + } + + public TeapotNorthArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 3; + + 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(); + } + } + + public class TowerLanternArtifact : BaseDecorationArtifact + { + [Constructible] + public TowerLanternArtifact() : base(0x24C0) => Light = LightType.Circle225; + + public TowerLanternArtifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 3; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsOn + { + get => ItemID == 0x24BF; + set => ItemID = value ? 0x24BF : 0x24C0; + } + + public override void OnDoubleClick(Mobile from) + { + if (from.InRange(GetWorldLocation(), 2)) + { + if (IsOn) + { + IsOn = false; + from.PlaySound(0x3BE); + } + else + { + IsOn = true; + from.PlaySound(0x47); + } + } + else + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(1); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + if (version == 0) + Light = LightType.Circle225; + } + } + + public class Urn1Artifact : BaseDecorationArtifact + { + [Constructible] + public Urn1Artifact() : base(0x241D) + { + } + + public Urn1Artifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 3; + + 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(); + } + } + + public class Urn2Artifact : BaseDecorationArtifact + { + [Constructible] + public Urn2Artifact() : base(0x241E) + { + } + + public Urn2Artifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 3; + + 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(); + } + } + + public class ZenRock1Artifact : BaseDecorationArtifact + { + [Constructible] + public ZenRock1Artifact() : base(0x24E4) + { + } + + public ZenRock1Artifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 2; + + 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(); + } + } + + public class ZenRock2Artifact : BaseDecorationArtifact + { + [Constructible] + public ZenRock2Artifact() : base(0x24E3) + { + } + + public ZenRock2Artifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 3; + + 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(); + } + } + + public class ZenRock3Artifact : BaseDecorationArtifact + { + [Constructible] + public ZenRock3Artifact() : base(0x24E5) + { + } + + public ZenRock3Artifact(Serial serial) : base(serial) + { + } + + public override int ArtifactRarity => 3; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Decoration Artifacts/StealableArtifactsSpawner.cs b/Projects/UOContent/Items/Decoration Artifacts/StealableArtifactsSpawner.cs index 7b3ec1256..fe70cd6c1 100644 --- a/Projects/UOContent/Items/Decoration Artifacts/StealableArtifactsSpawner.cs +++ b/Projects/UOContent/Items/Decoration Artifacts/StealableArtifactsSpawner.cs @@ -1,384 +1,384 @@ -using System; -using System.Collections.Generic; -using Server.Utilities; - -namespace Server.Items -{ - public class StealableArtifactsSpawner : Item - { - private static Type[] m_TypesOfEntries; - private StealableInstance[] m_Artifacts; - - private Timer m_RespawnTimer; - private Dictionary m_Table; - - private StealableArtifactsSpawner() : base(1) - { - Movable = false; - - m_Artifacts = new StealableInstance[Entries.Length]; - m_Table = new Dictionary(Entries.Length); - - for (int i = 0; i < Entries.Length; i++) - m_Artifacts[i] = new StealableInstance(Entries[i]); - - m_RespawnTimer = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromMinutes(15.0), CheckRespawn); - } - - public StealableArtifactsSpawner(Serial serial) : base(serial) => Instance = this; - - public static StealableEntry[] Entries { get; } = - { - // Doom - Artifact rarity 1 - new StealableEntry(Map.Malas, new Point3D(317, 56, -1), 72, 108, typeof(RockArtifact)), - new StealableEntry(Map.Malas, new Point3D(360, 31, 8), 72, 108, typeof(SkullCandleArtifact)), - new StealableEntry(Map.Malas, new Point3D(369, 372, -1), 72, 108, typeof(BottleArtifact)), - new StealableEntry(Map.Malas, new Point3D(378, 372, 0), 72, 108, typeof(DamagedBooksArtifact)), - // Doom - Artifact rarity 2 - new StealableEntry(Map.Malas, new Point3D(432, 16, -1), 144, 216, typeof(StretchedHideArtifact)), - new StealableEntry(Map.Malas, new Point3D(489, 9, 0), 144, 216, typeof(BrazierArtifact)), - // Doom - Artifact rarity 3 - new StealableEntry(Map.Malas, new Point3D(471, 96, -1), 288, 432, typeof(LampPostArtifact), GetLampPostHue()), - new StealableEntry(Map.Malas, new Point3D(421, 198, 2), 288, 432, typeof(BooksNorthArtifact)), - new StealableEntry(Map.Malas, new Point3D(431, 189, -1), 288, 432, typeof(BooksWestArtifact)), - new StealableEntry(Map.Malas, new Point3D(435, 196, -1), 288, 432, typeof(BooksFaceDownArtifact)), - // Doom - Artifact rarity 5 - new StealableEntry(Map.Malas, new Point3D(447, 9, 8), 1152, 1728, typeof(StuddedLeggingsArtifact)), - new StealableEntry(Map.Malas, new Point3D(423, 28, 0), 1152, 1728, typeof(EggCaseArtifact)), - new StealableEntry(Map.Malas, new Point3D(347, 44, 4), 1152, 1728, typeof(SkinnedGoatArtifact)), - new StealableEntry(Map.Malas, new Point3D(497, 57, -1), 1152, 1728, typeof(GruesomeStandardArtifact)), - new StealableEntry(Map.Malas, new Point3D(381, 375, 11), 1152, 1728, typeof(BloodyWaterArtifact)), - new StealableEntry(Map.Malas, new Point3D(489, 369, 2), 1152, 1728, typeof(TarotCardsArtifact)), - new StealableEntry(Map.Malas, new Point3D(497, 369, 5), 1152, 1728, typeof(BackpackArtifact)), - // Doom - Artifact rarity 7 - new StealableEntry(Map.Malas, new Point3D(475, 23, 4), 4608, 6912, typeof(StuddedTunicArtifact)), - new StealableEntry(Map.Malas, new Point3D(423, 28, 0), 4608, 6912, typeof(CocoonArtifact)), - // Doom - Artifact rarity 8 - new StealableEntry(Map.Malas, new Point3D(354, 36, -1), 9216, 13824, typeof(SkinnedDeerArtifact)), - // Doom - Artifact rarity 9 - new StealableEntry(Map.Malas, new Point3D(433, 11, -1), 18432, 27648, typeof(SaddleArtifact)), - new StealableEntry(Map.Malas, new Point3D(403, 31, 4), 18432, 27648, typeof(LeatherTunicArtifact)), - // Doom - Artifact rarity 10 - new StealableEntry(Map.Malas, new Point3D(257, 70, -2), 36864, 55296, typeof(ZyronicClaw)), - new StealableEntry(Map.Malas, new Point3D(354, 176, 7), 36864, 55296, typeof(TitansHammer)), - new StealableEntry(Map.Malas, new Point3D(369, 389, -1), 36864, 55296, typeof(BladeOfTheRighteous)), - new StealableEntry(Map.Malas, new Point3D(467, 92, 4), 36864, 55296, typeof(InquisitorsResolution)), - // Doom - Artifact rarity 12 - new StealableEntry(Map.Malas, new Point3D(487, 364, -1), 147456, 221184, typeof(RuinedPaintingArtifact)), - - // Yomotsu Mines - Artifact rarity 1 - new StealableEntry(Map.Malas, new Point3D(18, 110, -1), 72, 108, typeof(Basket1Artifact)), - new StealableEntry(Map.Malas, new Point3D(66, 114, -1), 72, 108, typeof(Basket2Artifact)), - // Yomotsu Mines - Artifact rarity 2 - new StealableEntry(Map.Malas, new Point3D(63, 12, 11), 144, 216, typeof(Basket4Artifact)), - new StealableEntry(Map.Malas, new Point3D(5, 29, -1), 144, 216, typeof(Basket5NorthArtifact)), - new StealableEntry(Map.Malas, new Point3D(30, 81, 3), 144, 216, typeof(Basket5WestArtifact)), - // Yomotsu Mines - Artifact rarity 3 - new StealableEntry(Map.Malas, new Point3D(115, 7, -1), 288, 432, typeof(Urn1Artifact)), - new StealableEntry(Map.Malas, new Point3D(85, 13, -1), 288, 432, typeof(Urn2Artifact)), - new StealableEntry(Map.Malas, new Point3D(110, 53, -1), 288, 432, typeof(Sculpture1Artifact)), - new StealableEntry(Map.Malas, new Point3D(108, 37, -1), 288, 432, typeof(Sculpture2Artifact)), - new StealableEntry(Map.Malas, new Point3D(121, 14, -1), 288, 432, typeof(TeapotNorthArtifact)), - new StealableEntry(Map.Malas, new Point3D(121, 115, -1), 288, 432, typeof(TeapotWestArtifact)), - new StealableEntry(Map.Malas, new Point3D(84, 40, -1), 288, 432, typeof(TowerLanternArtifact)), - // Yomotsu Mines - Artifact rarity 9 - new StealableEntry(Map.Malas, new Point3D(94, 7, -1), 18432, 27648, typeof(ManStatuetteSouthArtifact)), - - // Fan Dancer's Dojo - Artifact rarity 1 - new StealableEntry(Map.Malas, new Point3D(113, 640, -2), 72, 108, typeof(Basket3NorthArtifact)), - new StealableEntry(Map.Malas, new Point3D(102, 355, -1), 72, 108, typeof(Basket3WestArtifact)), - // Fan Dancer's Dojo - Artifact rarity 2 - new StealableEntry(Map.Malas, new Point3D(99, 370, -1), 144, 216, typeof(Basket6Artifact)), - new StealableEntry(Map.Malas, new Point3D(100, 357, -1), 144, 216, typeof(ZenRock1Artifact)), - // Fan Dancer's Dojo - Artifact rarity 3 - new StealableEntry(Map.Malas, new Point3D(73, 473, -1), 288, 432, typeof(FanNorthArtifact)), - new StealableEntry(Map.Malas, new Point3D(99, 372, -1), 288, 432, typeof(FanWestArtifact)), - new StealableEntry(Map.Malas, new Point3D(92, 326, -1), 288, 432, typeof(BowlsVerticalArtifact)), - new StealableEntry(Map.Malas, new Point3D(97, 470, -1), 288, 432, typeof(ZenRock2Artifact)), - new StealableEntry(Map.Malas, new Point3D(103, 691, -1), 288, 432, typeof(ZenRock3Artifact)), - // Fan Dancer's Dojo - Artifact rarity 4 - new StealableEntry(Map.Malas, new Point3D(103, 336, 4), 576, 864, typeof(Painting1NorthArtifact)), - new StealableEntry(Map.Malas, new Point3D(59, 381, 4), 576, 864, typeof(Painting1WestArtifact)), - new StealableEntry(Map.Malas, new Point3D(84, 401, 2), 576, 864, typeof(Painting2NorthArtifact)), - new StealableEntry(Map.Malas, new Point3D(59, 392, 2), 576, 864, typeof(Painting2WestArtifact)), - new StealableEntry(Map.Malas, new Point3D(107, 483, -1), 576, 864, typeof(TripleFanNorthArtifact)), - new StealableEntry(Map.Malas, new Point3D(50, 475, -1), 576, 864, typeof(TripleFanWestArtifact)), - new StealableEntry(Map.Malas, new Point3D(107, 460, -1), 576, 864, typeof(BowlArtifact)), - new StealableEntry(Map.Malas, new Point3D(90, 502, -1), 576, 864, typeof(CupsArtifact)), - new StealableEntry(Map.Malas, new Point3D(107, 688, -1), 576, 864, typeof(BowlsHorizontalArtifact)), - new StealableEntry(Map.Malas, new Point3D(112, 676, -1), 576, 864, typeof(SakeArtifact)), - // Fan Dancer's Dojo - Artifact rarity 5 - new StealableEntry(Map.Malas, new Point3D(135, 614, -1), 1152, 1728, typeof(SwordDisplay1NorthArtifact)), - new StealableEntry(Map.Malas, new Point3D(50, 482, -1), 1152, 1728, typeof(SwordDisplay1WestArtifact)), - new StealableEntry(Map.Malas, new Point3D(119, 672, -1), 1152, 1728, typeof(Painting3Artifact)), - // Fan Dancer's Dojo - Artifact rarity 6 - new StealableEntry(Map.Malas, new Point3D(90, 326, -1), 2304, 3456, typeof(Painting4NorthArtifact)), - new StealableEntry(Map.Malas, new Point3D(99, 354, -1), 2304, 3456, typeof(Painting4WestArtifact)), - new StealableEntry(Map.Malas, new Point3D(179, 652, -1), 2304, 3456, typeof(SwordDisplay2NorthArtifact)), - new StealableEntry(Map.Malas, new Point3D(118, 627, -1), 2304, 3456, typeof(SwordDisplay2WestArtifact)), - // Fan Dancer's Dojo - Artifact rarity 7 - new StealableEntry(Map.Malas, new Point3D(90, 483, -1), 4608, 6912, typeof(FlowersArtifact)), - // Fan Dancer's Dojo - Artifact rarity 8 - new StealableEntry(Map.Malas, new Point3D(71, 562, -1), 9216, 13824, typeof(DolphinLeftArtifact)), - new StealableEntry(Map.Malas, new Point3D(102, 677, -1), 9216, 13824, typeof(DolphinRightArtifact)), - new StealableEntry(Map.Malas, new Point3D(61, 499, 0), 9216, 13824, typeof(SwordDisplay3SouthArtifact)), - new StealableEntry(Map.Malas, new Point3D(182, 669, -1), 9216, 13824, typeof(SwordDisplay3EastArtifact)), - new StealableEntry(Map.Malas, new Point3D(162, 647, -1), 9216, 13824, typeof(SwordDisplay4WestArtifact)), - new StealableEntry(Map.Malas, new Point3D(124, 624, 0), 9216, 13824, typeof(Painting5NorthArtifact)), - new StealableEntry(Map.Malas, new Point3D(146, 649, 2), 9216, 13824, typeof(Painting5WestArtifact)), - // Fan Dancer's Dojo - Artifact rarity 9 - new StealableEntry(Map.Malas, new Point3D(100, 488, -1), 18432, 27648, typeof(SwordDisplay4NorthArtifact)), - new StealableEntry(Map.Malas, new Point3D(175, 606, 0), 18432, 27648, typeof(SwordDisplay5NorthArtifact)), - new StealableEntry(Map.Malas, new Point3D(157, 608, -1), 18432, 27648, typeof(SwordDisplay5WestArtifact)), - new StealableEntry(Map.Malas, new Point3D(187, 643, 1), 18432, 27648, typeof(Painting6NorthArtifact)), - new StealableEntry(Map.Malas, new Point3D(146, 623, 1), 18432, 27648, typeof(Painting6WestArtifact)), - new StealableEntry(Map.Malas, new Point3D(178, 629, -1), 18432, 27648, typeof(ManStatuetteEastArtifact)) - }; - - public static Type[] TypesOfEntires - { - get - { - if (m_TypesOfEntries == null) - { - m_TypesOfEntries = new Type[Entries.Length]; - - for (int i = 0; i < Entries.Length; i++) - m_TypesOfEntries[i] = Entries[i].Type; - } - - return m_TypesOfEntries; - } - } - - public static StealableArtifactsSpawner Instance { get; private set; } - - public override string DefaultName => "Stealable Artifacts Spawner - Internal"; - - private static int GetLampPostHue() - { - if (Utility.RandomDouble() < 0.9) - return 0; - - return Utility.RandomList(0x455, 0x47E, 0x482, 0x486, 0x48F, 0x4F2, 0x58C, 0x66C); - } - - public static void Initialize() - { - CommandSystem.Register("GenStealArties", AccessLevel.Administrator, GenStealArties_OnCommand); - CommandSystem.Register("RemoveStealArties", AccessLevel.Administrator, RemoveStealArties_OnCommand); - } - - [Usage("GenStealArties")] - [Description("Generates the stealable artifacts spawner.")] - private static void GenStealArties_OnCommand(CommandEventArgs args) - { - Mobile from = args.Mobile; - - if (Create()) - from.SendMessage("Stealable artifacts spawner generated."); - else - from.SendMessage("Stealable artifacts spawner already present."); - } - - [Usage("RemoveStealArties")] - [Description("Removes the stealable artifacts spawner and every not yet stolen stealable artifacts.")] - private static void RemoveStealArties_OnCommand(CommandEventArgs args) - { - Mobile from = args.Mobile; - - if (Remove()) - from.SendMessage("Stealable artifacts spawner removed."); - else - from.SendMessage("Stealable artifacts spawner not present."); - } - - public static bool Create() - { - if (Instance?.Deleted == false) - return false; - - Instance = new StealableArtifactsSpawner(); - return true; - } - - public static bool Remove() - { - if (Instance == null) - return false; - - Instance.Delete(); - Instance = null; - return true; - } - - public static StealableInstance GetStealableInstance(Item item) - { - if (Instance == null) - return null; - - Instance.m_Table.TryGetValue(item, out StealableInstance value); - return value; - } - - public override void OnDelete() - { - base.OnDelete(); - - if (m_RespawnTimer != null) - { - m_RespawnTimer.Stop(); - m_RespawnTimer = null; - } - - foreach (StealableInstance si in m_Artifacts) si.Item?.Delete(); - - Instance = null; - } - - public void CheckRespawn() - { - foreach (StealableInstance si in m_Artifacts) - si.CheckRespawn(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.WriteEncodedInt(m_Artifacts.Length); - - for (int i = 0; i < m_Artifacts.Length; i++) - { - StealableInstance si = m_Artifacts[i]; - - writer.Write(si.Item); - writer.WriteDeltaTime(si.NextRespawn); - } - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_Artifacts = new StealableInstance[Entries.Length]; - m_Table = new Dictionary(Entries.Length); - - int length = reader.ReadEncodedInt(); - - for (int i = 0; i < length; i++) - { - Item item = reader.ReadItem(); - DateTime nextRespawn = reader.ReadDeltaTime(); - - if (i < m_Artifacts.Length) - { - StealableInstance si = new StealableInstance(Entries[i], item, nextRespawn); - m_Artifacts[i] = si; - - if (si.Item != null) - m_Table[si.Item] = si; - } - } - - for (int i = length; i < Entries.Length; i++) m_Artifacts[i] = new StealableInstance(Entries[i]); - - m_RespawnTimer = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromMinutes(15.0), CheckRespawn); - } - - public class StealableEntry - { - public StealableEntry(Map map, Point3D location, int minDelay, int maxDelay, Type type, int hue = 0) - { - Map = map; - Location = location; - MinDelay = minDelay; - MaxDelay = maxDelay; - Type = type; - Hue = hue; - } - - public Map Map { get; } - - public Point3D Location { get; } - - public int MinDelay { get; } - - public int MaxDelay { get; } - - public Type Type { get; } - - public int Hue { get; } - - public Item CreateInstance() - { - Item item = (Item)ActivatorUtil.CreateInstance(Type); - - if (Hue > 0) - item.Hue = Hue; - - item.Movable = false; - item.MoveToWorld(Location, Map); - - return item; - } - } - - public class StealableInstance - { - private Item m_Item; - - public StealableInstance(StealableEntry entry) : this(entry, null, DateTime.UtcNow) - { - } - - public StealableInstance(StealableEntry entry, Item item, DateTime nextRespawn) - { - m_Item = item; - NextRespawn = nextRespawn; - Entry = entry; - } - - public StealableEntry Entry { get; } - - public Item Item - { - get => m_Item; - set - { - if (m_Item != null && value == null) - { - int delay = Utility.RandomMinMax(Entry.MinDelay, Entry.MaxDelay); - NextRespawn = DateTime.UtcNow + TimeSpan.FromMinutes(delay); - } - - if (Instance != null) - { - if (m_Item != null) - Instance.m_Table.Remove(m_Item); - - if (value != null) - Instance.m_Table[value] = this; - } - - m_Item = value; - } - } - - public DateTime NextRespawn { get; set; } - - public void CheckRespawn() - { - if (Item != null && (Item.Deleted || Item.Movable || Item.Parent != null)) - Item = null; - - if (Item == null && DateTime.UtcNow >= NextRespawn) - Item = Entry.CreateInstance(); - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Utilities; + +namespace Server.Items +{ + public class StealableArtifactsSpawner : Item + { + private static Type[] m_TypesOfEntries; + private StealableInstance[] m_Artifacts; + + private Timer m_RespawnTimer; + private Dictionary m_Table; + + private StealableArtifactsSpawner() : base(1) + { + Movable = false; + + m_Artifacts = new StealableInstance[Entries.Length]; + m_Table = new Dictionary(Entries.Length); + + for (var i = 0; i < Entries.Length; i++) + m_Artifacts[i] = new StealableInstance(Entries[i]); + + m_RespawnTimer = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromMinutes(15.0), CheckRespawn); + } + + public StealableArtifactsSpawner(Serial serial) : base(serial) => Instance = this; + + public static StealableEntry[] Entries { get; } = + { + // Doom - Artifact rarity 1 + new StealableEntry(Map.Malas, new Point3D(317, 56, -1), 72, 108, typeof(RockArtifact)), + new StealableEntry(Map.Malas, new Point3D(360, 31, 8), 72, 108, typeof(SkullCandleArtifact)), + new StealableEntry(Map.Malas, new Point3D(369, 372, -1), 72, 108, typeof(BottleArtifact)), + new StealableEntry(Map.Malas, new Point3D(378, 372, 0), 72, 108, typeof(DamagedBooksArtifact)), + // Doom - Artifact rarity 2 + new StealableEntry(Map.Malas, new Point3D(432, 16, -1), 144, 216, typeof(StretchedHideArtifact)), + new StealableEntry(Map.Malas, new Point3D(489, 9, 0), 144, 216, typeof(BrazierArtifact)), + // Doom - Artifact rarity 3 + new StealableEntry(Map.Malas, new Point3D(471, 96, -1), 288, 432, typeof(LampPostArtifact), GetLampPostHue()), + new StealableEntry(Map.Malas, new Point3D(421, 198, 2), 288, 432, typeof(BooksNorthArtifact)), + new StealableEntry(Map.Malas, new Point3D(431, 189, -1), 288, 432, typeof(BooksWestArtifact)), + new StealableEntry(Map.Malas, new Point3D(435, 196, -1), 288, 432, typeof(BooksFaceDownArtifact)), + // Doom - Artifact rarity 5 + new StealableEntry(Map.Malas, new Point3D(447, 9, 8), 1152, 1728, typeof(StuddedLeggingsArtifact)), + new StealableEntry(Map.Malas, new Point3D(423, 28, 0), 1152, 1728, typeof(EggCaseArtifact)), + new StealableEntry(Map.Malas, new Point3D(347, 44, 4), 1152, 1728, typeof(SkinnedGoatArtifact)), + new StealableEntry(Map.Malas, new Point3D(497, 57, -1), 1152, 1728, typeof(GruesomeStandardArtifact)), + new StealableEntry(Map.Malas, new Point3D(381, 375, 11), 1152, 1728, typeof(BloodyWaterArtifact)), + new StealableEntry(Map.Malas, new Point3D(489, 369, 2), 1152, 1728, typeof(TarotCardsArtifact)), + new StealableEntry(Map.Malas, new Point3D(497, 369, 5), 1152, 1728, typeof(BackpackArtifact)), + // Doom - Artifact rarity 7 + new StealableEntry(Map.Malas, new Point3D(475, 23, 4), 4608, 6912, typeof(StuddedTunicArtifact)), + new StealableEntry(Map.Malas, new Point3D(423, 28, 0), 4608, 6912, typeof(CocoonArtifact)), + // Doom - Artifact rarity 8 + new StealableEntry(Map.Malas, new Point3D(354, 36, -1), 9216, 13824, typeof(SkinnedDeerArtifact)), + // Doom - Artifact rarity 9 + new StealableEntry(Map.Malas, new Point3D(433, 11, -1), 18432, 27648, typeof(SaddleArtifact)), + new StealableEntry(Map.Malas, new Point3D(403, 31, 4), 18432, 27648, typeof(LeatherTunicArtifact)), + // Doom - Artifact rarity 10 + new StealableEntry(Map.Malas, new Point3D(257, 70, -2), 36864, 55296, typeof(ZyronicClaw)), + new StealableEntry(Map.Malas, new Point3D(354, 176, 7), 36864, 55296, typeof(TitansHammer)), + new StealableEntry(Map.Malas, new Point3D(369, 389, -1), 36864, 55296, typeof(BladeOfTheRighteous)), + new StealableEntry(Map.Malas, new Point3D(467, 92, 4), 36864, 55296, typeof(InquisitorsResolution)), + // Doom - Artifact rarity 12 + new StealableEntry(Map.Malas, new Point3D(487, 364, -1), 147456, 221184, typeof(RuinedPaintingArtifact)), + + // Yomotsu Mines - Artifact rarity 1 + new StealableEntry(Map.Malas, new Point3D(18, 110, -1), 72, 108, typeof(Basket1Artifact)), + new StealableEntry(Map.Malas, new Point3D(66, 114, -1), 72, 108, typeof(Basket2Artifact)), + // Yomotsu Mines - Artifact rarity 2 + new StealableEntry(Map.Malas, new Point3D(63, 12, 11), 144, 216, typeof(Basket4Artifact)), + new StealableEntry(Map.Malas, new Point3D(5, 29, -1), 144, 216, typeof(Basket5NorthArtifact)), + new StealableEntry(Map.Malas, new Point3D(30, 81, 3), 144, 216, typeof(Basket5WestArtifact)), + // Yomotsu Mines - Artifact rarity 3 + new StealableEntry(Map.Malas, new Point3D(115, 7, -1), 288, 432, typeof(Urn1Artifact)), + new StealableEntry(Map.Malas, new Point3D(85, 13, -1), 288, 432, typeof(Urn2Artifact)), + new StealableEntry(Map.Malas, new Point3D(110, 53, -1), 288, 432, typeof(Sculpture1Artifact)), + new StealableEntry(Map.Malas, new Point3D(108, 37, -1), 288, 432, typeof(Sculpture2Artifact)), + new StealableEntry(Map.Malas, new Point3D(121, 14, -1), 288, 432, typeof(TeapotNorthArtifact)), + new StealableEntry(Map.Malas, new Point3D(121, 115, -1), 288, 432, typeof(TeapotWestArtifact)), + new StealableEntry(Map.Malas, new Point3D(84, 40, -1), 288, 432, typeof(TowerLanternArtifact)), + // Yomotsu Mines - Artifact rarity 9 + new StealableEntry(Map.Malas, new Point3D(94, 7, -1), 18432, 27648, typeof(ManStatuetteSouthArtifact)), + + // Fan Dancer's Dojo - Artifact rarity 1 + new StealableEntry(Map.Malas, new Point3D(113, 640, -2), 72, 108, typeof(Basket3NorthArtifact)), + new StealableEntry(Map.Malas, new Point3D(102, 355, -1), 72, 108, typeof(Basket3WestArtifact)), + // Fan Dancer's Dojo - Artifact rarity 2 + new StealableEntry(Map.Malas, new Point3D(99, 370, -1), 144, 216, typeof(Basket6Artifact)), + new StealableEntry(Map.Malas, new Point3D(100, 357, -1), 144, 216, typeof(ZenRock1Artifact)), + // Fan Dancer's Dojo - Artifact rarity 3 + new StealableEntry(Map.Malas, new Point3D(73, 473, -1), 288, 432, typeof(FanNorthArtifact)), + new StealableEntry(Map.Malas, new Point3D(99, 372, -1), 288, 432, typeof(FanWestArtifact)), + new StealableEntry(Map.Malas, new Point3D(92, 326, -1), 288, 432, typeof(BowlsVerticalArtifact)), + new StealableEntry(Map.Malas, new Point3D(97, 470, -1), 288, 432, typeof(ZenRock2Artifact)), + new StealableEntry(Map.Malas, new Point3D(103, 691, -1), 288, 432, typeof(ZenRock3Artifact)), + // Fan Dancer's Dojo - Artifact rarity 4 + new StealableEntry(Map.Malas, new Point3D(103, 336, 4), 576, 864, typeof(Painting1NorthArtifact)), + new StealableEntry(Map.Malas, new Point3D(59, 381, 4), 576, 864, typeof(Painting1WestArtifact)), + new StealableEntry(Map.Malas, new Point3D(84, 401, 2), 576, 864, typeof(Painting2NorthArtifact)), + new StealableEntry(Map.Malas, new Point3D(59, 392, 2), 576, 864, typeof(Painting2WestArtifact)), + new StealableEntry(Map.Malas, new Point3D(107, 483, -1), 576, 864, typeof(TripleFanNorthArtifact)), + new StealableEntry(Map.Malas, new Point3D(50, 475, -1), 576, 864, typeof(TripleFanWestArtifact)), + new StealableEntry(Map.Malas, new Point3D(107, 460, -1), 576, 864, typeof(BowlArtifact)), + new StealableEntry(Map.Malas, new Point3D(90, 502, -1), 576, 864, typeof(CupsArtifact)), + new StealableEntry(Map.Malas, new Point3D(107, 688, -1), 576, 864, typeof(BowlsHorizontalArtifact)), + new StealableEntry(Map.Malas, new Point3D(112, 676, -1), 576, 864, typeof(SakeArtifact)), + // Fan Dancer's Dojo - Artifact rarity 5 + new StealableEntry(Map.Malas, new Point3D(135, 614, -1), 1152, 1728, typeof(SwordDisplay1NorthArtifact)), + new StealableEntry(Map.Malas, new Point3D(50, 482, -1), 1152, 1728, typeof(SwordDisplay1WestArtifact)), + new StealableEntry(Map.Malas, new Point3D(119, 672, -1), 1152, 1728, typeof(Painting3Artifact)), + // Fan Dancer's Dojo - Artifact rarity 6 + new StealableEntry(Map.Malas, new Point3D(90, 326, -1), 2304, 3456, typeof(Painting4NorthArtifact)), + new StealableEntry(Map.Malas, new Point3D(99, 354, -1), 2304, 3456, typeof(Painting4WestArtifact)), + new StealableEntry(Map.Malas, new Point3D(179, 652, -1), 2304, 3456, typeof(SwordDisplay2NorthArtifact)), + new StealableEntry(Map.Malas, new Point3D(118, 627, -1), 2304, 3456, typeof(SwordDisplay2WestArtifact)), + // Fan Dancer's Dojo - Artifact rarity 7 + new StealableEntry(Map.Malas, new Point3D(90, 483, -1), 4608, 6912, typeof(FlowersArtifact)), + // Fan Dancer's Dojo - Artifact rarity 8 + new StealableEntry(Map.Malas, new Point3D(71, 562, -1), 9216, 13824, typeof(DolphinLeftArtifact)), + new StealableEntry(Map.Malas, new Point3D(102, 677, -1), 9216, 13824, typeof(DolphinRightArtifact)), + new StealableEntry(Map.Malas, new Point3D(61, 499, 0), 9216, 13824, typeof(SwordDisplay3SouthArtifact)), + new StealableEntry(Map.Malas, new Point3D(182, 669, -1), 9216, 13824, typeof(SwordDisplay3EastArtifact)), + new StealableEntry(Map.Malas, new Point3D(162, 647, -1), 9216, 13824, typeof(SwordDisplay4WestArtifact)), + new StealableEntry(Map.Malas, new Point3D(124, 624, 0), 9216, 13824, typeof(Painting5NorthArtifact)), + new StealableEntry(Map.Malas, new Point3D(146, 649, 2), 9216, 13824, typeof(Painting5WestArtifact)), + // Fan Dancer's Dojo - Artifact rarity 9 + new StealableEntry(Map.Malas, new Point3D(100, 488, -1), 18432, 27648, typeof(SwordDisplay4NorthArtifact)), + new StealableEntry(Map.Malas, new Point3D(175, 606, 0), 18432, 27648, typeof(SwordDisplay5NorthArtifact)), + new StealableEntry(Map.Malas, new Point3D(157, 608, -1), 18432, 27648, typeof(SwordDisplay5WestArtifact)), + new StealableEntry(Map.Malas, new Point3D(187, 643, 1), 18432, 27648, typeof(Painting6NorthArtifact)), + new StealableEntry(Map.Malas, new Point3D(146, 623, 1), 18432, 27648, typeof(Painting6WestArtifact)), + new StealableEntry(Map.Malas, new Point3D(178, 629, -1), 18432, 27648, typeof(ManStatuetteEastArtifact)) + }; + + public static Type[] TypesOfEntires + { + get + { + if (m_TypesOfEntries == null) + { + m_TypesOfEntries = new Type[Entries.Length]; + + for (var i = 0; i < Entries.Length; i++) + m_TypesOfEntries[i] = Entries[i].Type; + } + + return m_TypesOfEntries; + } + } + + public static StealableArtifactsSpawner Instance { get; private set; } + + public override string DefaultName => "Stealable Artifacts Spawner - Internal"; + + private static int GetLampPostHue() + { + if (Utility.RandomDouble() < 0.9) + return 0; + + return Utility.RandomList(0x455, 0x47E, 0x482, 0x486, 0x48F, 0x4F2, 0x58C, 0x66C); + } + + public static void Initialize() + { + CommandSystem.Register("GenStealArties", AccessLevel.Administrator, GenStealArties_OnCommand); + CommandSystem.Register("RemoveStealArties", AccessLevel.Administrator, RemoveStealArties_OnCommand); + } + + [Usage("GenStealArties")] + [Description("Generates the stealable artifacts spawner.")] + private static void GenStealArties_OnCommand(CommandEventArgs args) + { + var from = args.Mobile; + + if (Create()) + from.SendMessage("Stealable artifacts spawner generated."); + else + from.SendMessage("Stealable artifacts spawner already present."); + } + + [Usage("RemoveStealArties")] + [Description("Removes the stealable artifacts spawner and every not yet stolen stealable artifacts.")] + private static void RemoveStealArties_OnCommand(CommandEventArgs args) + { + var from = args.Mobile; + + if (Remove()) + from.SendMessage("Stealable artifacts spawner removed."); + else + from.SendMessage("Stealable artifacts spawner not present."); + } + + public static bool Create() + { + if (Instance?.Deleted == false) + return false; + + Instance = new StealableArtifactsSpawner(); + return true; + } + + public static bool Remove() + { + if (Instance == null) + return false; + + Instance.Delete(); + Instance = null; + return true; + } + + public static StealableInstance GetStealableInstance(Item item) + { + if (Instance == null) + return null; + + Instance.m_Table.TryGetValue(item, out var value); + return value; + } + + public override void OnDelete() + { + base.OnDelete(); + + if (m_RespawnTimer != null) + { + m_RespawnTimer.Stop(); + m_RespawnTimer = null; + } + + foreach (var si in m_Artifacts) si.Item?.Delete(); + + Instance = null; + } + + public void CheckRespawn() + { + foreach (var si in m_Artifacts) + si.CheckRespawn(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.WriteEncodedInt(m_Artifacts.Length); + + for (var i = 0; i < m_Artifacts.Length; i++) + { + var si = m_Artifacts[i]; + + writer.Write(si.Item); + writer.WriteDeltaTime(si.NextRespawn); + } + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_Artifacts = new StealableInstance[Entries.Length]; + m_Table = new Dictionary(Entries.Length); + + var length = reader.ReadEncodedInt(); + + for (var i = 0; i < length; i++) + { + var item = reader.ReadItem(); + var nextRespawn = reader.ReadDeltaTime(); + + if (i < m_Artifacts.Length) + { + var si = new StealableInstance(Entries[i], item, nextRespawn); + m_Artifacts[i] = si; + + if (si.Item != null) + m_Table[si.Item] = si; + } + } + + for (var i = length; i < Entries.Length; i++) m_Artifacts[i] = new StealableInstance(Entries[i]); + + m_RespawnTimer = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromMinutes(15.0), CheckRespawn); + } + + public class StealableEntry + { + public StealableEntry(Map map, Point3D location, int minDelay, int maxDelay, Type type, int hue = 0) + { + Map = map; + Location = location; + MinDelay = minDelay; + MaxDelay = maxDelay; + Type = type; + Hue = hue; + } + + public Map Map { get; } + + public Point3D Location { get; } + + public int MinDelay { get; } + + public int MaxDelay { get; } + + public Type Type { get; } + + public int Hue { get; } + + public Item CreateInstance() + { + var item = (Item)ActivatorUtil.CreateInstance(Type); + + if (Hue > 0) + item.Hue = Hue; + + item.Movable = false; + item.MoveToWorld(Location, Map); + + return item; + } + } + + public class StealableInstance + { + private Item m_Item; + + public StealableInstance(StealableEntry entry) : this(entry, null, DateTime.UtcNow) + { + } + + public StealableInstance(StealableEntry entry, Item item, DateTime nextRespawn) + { + m_Item = item; + NextRespawn = nextRespawn; + Entry = entry; + } + + public StealableEntry Entry { get; } + + public Item Item + { + get => m_Item; + set + { + if (m_Item != null && value == null) + { + var delay = Utility.RandomMinMax(Entry.MinDelay, Entry.MaxDelay); + NextRespawn = DateTime.UtcNow + TimeSpan.FromMinutes(delay); + } + + if (Instance != null) + { + if (m_Item != null) + Instance.m_Table.Remove(m_Item); + + if (value != null) + Instance.m_Table[value] = this; + } + + m_Item = value; + } + } + + public DateTime NextRespawn { get; set; } + + public void CheckRespawn() + { + if (Item != null && (Item.Deleted || Item.Movable || Item.Parent != null)) + Item = null; + + if (Item == null && DateTime.UtcNow >= NextRespawn) + Item = Entry.CreateInstance(); + } + } + } +} diff --git a/Projects/UOContent/Items/Deeds/BarkeepContract.cs b/Projects/UOContent/Items/Deeds/BarkeepContract.cs index e4c300214..086088722 100644 --- a/Projects/UOContent/Items/Deeds/BarkeepContract.cs +++ b/Projects/UOContent/Items/Deeds/BarkeepContract.cs @@ -1,93 +1,99 @@ -using Server.Mobiles; -using Server.Multis; -using Server.Network; - -namespace Server.Items -{ - public class BarkeepContract : Item - { - [Constructible] - public BarkeepContract() : base(0x14F0) - { - Weight = 1.0; - LootType = LootType.Blessed; - } - - public BarkeepContract(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a barkeep contract"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (from.AccessLevel >= AccessLevel.GameMaster) - { - from.SendLocalizedMessage(503248); // Your godly powers allow you to place this vendor whereever you wish. - - Mobile v = new PlayerBarkeeper(from, BaseHouse.FindHouseAt(from)); - - v.Direction = from.Direction & Direction.Mask; - v.MoveToWorld(from.Location, from.Map); - - Delete(); - } - else - { - BaseHouse house = BaseHouse.FindHouseAt(from); - - if (house?.IsOwner(from) != true) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, - "You are not the full owner of this house."); - } - else if (!house.CanPlaceNewBarkeep()) - { - from.SendLocalizedMessage( - 1062490); // That action would exceed the maximum number of barkeeps for this house. - } - else - { - BaseHouse.IsThereVendor(from.Location, from.Map, out bool vendor, out bool contract); - - if (vendor) - { - from.SendLocalizedMessage(1062677); // You cannot place a vendor or barkeep at this location. - } - else if (contract) - { - from.SendLocalizedMessage( - 1062678); // You cannot place a vendor or barkeep on top of a rental contract! - } - else - { - Mobile v = new PlayerBarkeeper(from, house); - - v.Direction = from.Direction & Direction.Mask; - v.MoveToWorld(from.Location, from.Map); - - Delete(); - } - } - } - } - } -} +using Server.Mobiles; +using Server.Multis; +using Server.Network; + +namespace Server.Items +{ + public class BarkeepContract : Item + { + [Constructible] + public BarkeepContract() : base(0x14F0) + { + Weight = 1.0; + LootType = LootType.Blessed; + } + + public BarkeepContract(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a barkeep contract"; + + 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 (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else if (from.AccessLevel >= AccessLevel.GameMaster) + { + from.SendLocalizedMessage(503248); // Your godly powers allow you to place this vendor whereever you wish. + + Mobile v = new PlayerBarkeeper(from, BaseHouse.FindHouseAt(from)); + + v.Direction = from.Direction & Direction.Mask; + v.MoveToWorld(from.Location, from.Map); + + Delete(); + } + else + { + var house = BaseHouse.FindHouseAt(from); + + if (house?.IsOwner(from) != true) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + false, + "You are not the full owner of this house." + ); + } + else if (!house.CanPlaceNewBarkeep()) + { + from.SendLocalizedMessage( + 1062490 + ); // That action would exceed the maximum number of barkeeps for this house. + } + else + { + BaseHouse.IsThereVendor(from.Location, from.Map, out var vendor, out var contract); + + if (vendor) + { + from.SendLocalizedMessage(1062677); // You cannot place a vendor or barkeep at this location. + } + else if (contract) + { + from.SendLocalizedMessage( + 1062678 + ); // You cannot place a vendor or barkeep on top of a rental contract! + } + else + { + Mobile v = new PlayerBarkeeper(from, house); + + v.Direction = from.Direction & Direction.Mask; + v.MoveToWorld(from.Location, from.Map); + + Delete(); + } + } + } + } + } +} diff --git a/Projects/UOContent/Items/Deeds/ClothingBlessDeed.cs b/Projects/UOContent/Items/Deeds/ClothingBlessDeed.cs index 2a5ba8df0..7785529a6 100644 --- a/Projects/UOContent/Items/Deeds/ClothingBlessDeed.cs +++ b/Projects/UOContent/Items/Deeds/ClothingBlessDeed.cs @@ -1,96 +1,97 @@ -using Server.Targeting; - -namespace Server.Items -{ - public class ClothingBlessTarget : Target // Create our targeting class (which we derive from the base target class) - { - private readonly ClothingBlessDeed m_Deed; - - public ClothingBlessTarget(ClothingBlessDeed deed) : base(1, false, TargetFlags.None) => m_Deed = deed; - - protected override void OnTarget(Mobile from, object target) // Override the protected OnTarget() for our feature - { - if (m_Deed.Deleted || m_Deed.RootParent != from) - return; - - if (target is BaseClothing item) - { - if ((item as IArcaneEquip)?.IsArcane == true) - { - from.SendLocalizedMessage(1005019); // This bless deed is for Clothes only. - return; - } - - if (item.LootType == LootType.Blessed || item.BlessedFor == from || (Mobile.InsuranceEnabled && item.Insured)) // Check if its already newbied (blessed) - { - from.SendLocalizedMessage(1045113); // That item is already blessed - } - else if (item.LootType != LootType.Regular) - { - from.SendLocalizedMessage(1045114); // You can not bless that item - } - else if (!item.CanBeBlessed || item.RootParent != from) - { - from.SendLocalizedMessage(500509); // You cannot bless that object - } - else - { - item.LootType = LootType.Blessed; - from.SendLocalizedMessage(1010026); // You bless the item.... - - m_Deed.Delete(); // Delete the bless deed - } - } - else - { - from.SendLocalizedMessage(500509); // You cannot bless that object - } - } - } - - public class ClothingBlessDeed : Item // Create the item class which is derived from the base item class - { - [Constructible] - public ClothingBlessDeed() : base(0x14F0) - { - Weight = 1.0; - LootType = LootType.Blessed; - } - - public ClothingBlessDeed(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a clothing bless deed"; - - public override bool DisplayLootType => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - LootType = LootType.Blessed; - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) // Override double click of the deed to call our target - { - if (!IsChildOf(from.Backpack)) // Make sure its in their pack - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else - { - from.SendLocalizedMessage(1005018); // What would you like to bless? (Clothes Only) - from.Target = new ClothingBlessTarget(this); // Call our target - } - } - } -} \ No newline at end of file +using Server.Targeting; + +namespace Server.Items +{ + public class ClothingBlessTarget : Target // Create our targeting class (which we derive from the base target class) + { + private readonly ClothingBlessDeed m_Deed; + + public ClothingBlessTarget(ClothingBlessDeed deed) : base(1, false, TargetFlags.None) => m_Deed = deed; + + protected override void OnTarget(Mobile from, object target) // Override the protected OnTarget() for our feature + { + if (m_Deed.Deleted || m_Deed.RootParent != from) + return; + + if (target is BaseClothing item) + { + if ((item as IArcaneEquip)?.IsArcane == true) + { + from.SendLocalizedMessage(1005019); // This bless deed is for Clothes only. + return; + } + + if (item.LootType == LootType.Blessed || item.BlessedFor == from || Mobile.InsuranceEnabled && item.Insured + ) // Check if its already newbied (blessed) + { + from.SendLocalizedMessage(1045113); // That item is already blessed + } + else if (item.LootType != LootType.Regular) + { + from.SendLocalizedMessage(1045114); // You can not bless that item + } + else if (!item.CanBeBlessed || item.RootParent != from) + { + from.SendLocalizedMessage(500509); // You cannot bless that object + } + else + { + item.LootType = LootType.Blessed; + from.SendLocalizedMessage(1010026); // You bless the item.... + + m_Deed.Delete(); // Delete the bless deed + } + } + else + { + from.SendLocalizedMessage(500509); // You cannot bless that object + } + } + } + + public class ClothingBlessDeed : Item // Create the item class which is derived from the base item class + { + [Constructible] + public ClothingBlessDeed() : base(0x14F0) + { + Weight = 1.0; + LootType = LootType.Blessed; + } + + public ClothingBlessDeed(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a clothing bless deed"; + + public override bool DisplayLootType => false; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + LootType = LootType.Blessed; + + var version = reader.ReadInt(); + } + + public override void OnDoubleClick(Mobile from) // Override double click of the deed to call our target + { + if (!IsChildOf(from.Backpack)) // Make sure its in their pack + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else + { + from.SendLocalizedMessage(1005018); // What would you like to bless? (Clothes Only) + from.Target = new ClothingBlessTarget(this); // Call our target + } + } + } +} diff --git a/Projects/UOContent/Items/Deeds/CommodityDeed.cs b/Projects/UOContent/Items/Deeds/CommodityDeed.cs index 0d8874751..a6c653c81 100644 --- a/Projects/UOContent/Items/Deeds/CommodityDeed.cs +++ b/Projects/UOContent/Items/Deeds/CommodityDeed.cs @@ -1,237 +1,237 @@ -using Server.Targeting; - -namespace Server.Items -{ - public interface ICommodity /* added IsDeedable prop so expansion-based deedables can determine true/false */ - { - int DescriptionNumber { get; } - bool IsDeedable { get; } - } - - public class CommodityDeed : Item - { - [Constructible] - public CommodityDeed(Item commodity = null) : base(0x14F0) - { - Weight = 1.0; - Hue = 0x47; - - Commodity = commodity; - - LootType = LootType.Blessed; - } - - public CommodityDeed(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public Item Commodity { get; private set; } - - public override int LabelNumber => Commodity == null ? 1047016 : 1047017; - - public bool SetCommodity(Item item) - { - InvalidateProperties(); - - if (Commodity == null && (item as ICommodity)?.IsDeedable == true) - { - Commodity = item; - Commodity.Internalize(); - InvalidateProperties(); - - return true; - } - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(Commodity); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Commodity = reader.ReadItem(); - - switch (version) - { - case 0: - { - if (Commodity != null) Hue = 0x592; - break; - } - } - } - - public override void OnDelete() - { - Commodity?.Delete(); - - base.OnDelete(); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Commodity != null) - { - var args = Commodity.Name == null ? - $"#{(Commodity is ICommodity commodity ? commodity.DescriptionNumber : Commodity.LabelNumber)}\t{Commodity.Amount}" : - $"{Commodity.Name}\t{Commodity.Amount}"; - - list.Add(1060658, args); // ~1_val~: ~2_val~ - } - else - { - list.Add(1060748); // unfilled - } - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - if (Commodity != null) - { - string args; - - if (Commodity.Name == null) - args = - $"#{(Commodity is ICommodity commodity ? commodity.DescriptionNumber : Commodity.LabelNumber)}\t{Commodity.Amount}"; - else - args = $"{Commodity.Name}\t{Commodity.Amount}"; - - LabelTo(from, 1060658, args); // ~1_val~: ~2_val~ - } - } - - public override void OnDoubleClick(Mobile from) - { - int number; - - BankBox box = from.FindBankNoCreate(); - CommodityDeedBox cox = CommodityDeedBox.Find(this); - - // Veteran Rewards mods - if (Commodity != null) - { - if (box != null && IsChildOf(box)) - { - number = 1047031; // The commodity has been redeemed. - - box.DropItem(Commodity); - - Commodity = null; - Delete(); - } - else if (cox != null) - { - if (cox.IsSecure) - { - number = 1047031; // The commodity has been redeemed. - - cox.DropItem(Commodity); - - Commodity = null; - Delete(); - } - else - { - number = 1080525; // The commodity deed box must be secured before you can use it. - } - } - else - { - if (Core.ML) - number = 1080526; // That must be in your bank box or commodity deed box to use it. - else - number = 1047024; // To claim the resources .... - } - } - else if (cox?.IsSecure == false) - { - number = 1080525; // The commodity deed box must be secured before you can use it. - } - else if ((box == null || !IsChildOf(box)) && cox == null) - { - if (Core.ML) - number = 1080526; // That must be in your bank box or commodity deed box to use it. - else - number = 1047026; // That must be in your bank box to use it. - } - else - { - number = 1047029; // Target the commodity to fill this deed with. - - from.Target = new InternalTarget(this); - } - - from.SendLocalizedMessage(number); - } - - private class InternalTarget : Target - { - private readonly CommodityDeed m_Deed; - - public InternalTarget(CommodityDeed deed) : base(3, false, TargetFlags.None) => m_Deed = deed; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Deed.Deleted) - return; - - int number; - - if (m_Deed.Commodity != null) - { - number = 1047028; // The commodity deed has already been filled. - } - else if (targeted is Item item) - { - BankBox box = from.FindBankNoCreate(); - CommodityDeedBox cox = CommodityDeedBox.Find(m_Deed); - - // Veteran Rewards mods - if ((box != null && m_Deed.IsChildOf(box) && item.IsChildOf(box)) || - (cox?.IsSecure != true && item.IsChildOf(cox))) - { - if (m_Deed.SetCommodity(item)) - { - m_Deed.Hue = 0x592; - number = 1047030; // The commodity deed has been filled. - } - else - { - number = 1047027; // That is not a commodity the bankers will fill a commodity deed with. - } - } - else if (Core.ML) - { - number = 1080526; // That must be in your bank box or commodity deed box to use it. - } - else - { - number = 1047026; // That must be in your bank box to use it. - } - } - else - { - number = 1047027; // That is not a commodity the bankers will fill a commodity deed with. - } - - from.SendLocalizedMessage(number); - } - } - } -} +using Server.Targeting; + +namespace Server.Items +{ + public interface ICommodity /* added IsDeedable prop so expansion-based deedables can determine true/false */ + { + int DescriptionNumber { get; } + bool IsDeedable { get; } + } + + public class CommodityDeed : Item + { + [Constructible] + public CommodityDeed(Item commodity = null) : base(0x14F0) + { + Weight = 1.0; + Hue = 0x47; + + Commodity = commodity; + + LootType = LootType.Blessed; + } + + public CommodityDeed(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public Item Commodity { get; private set; } + + public override int LabelNumber => Commodity == null ? 1047016 : 1047017; + + public bool SetCommodity(Item item) + { + InvalidateProperties(); + + if (Commodity == null && (item as ICommodity)?.IsDeedable == true) + { + Commodity = item; + Commodity.Internalize(); + InvalidateProperties(); + + return true; + } + + return false; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(Commodity); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + Commodity = reader.ReadItem(); + + switch (version) + { + case 0: + { + if (Commodity != null) Hue = 0x592; + break; + } + } + } + + public override void OnDelete() + { + Commodity?.Delete(); + + base.OnDelete(); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (Commodity != null) + { + var args = Commodity.Name == null + ? $"#{(Commodity is ICommodity commodity ? commodity.DescriptionNumber : Commodity.LabelNumber)}\t{Commodity.Amount}" + : $"{Commodity.Name}\t{Commodity.Amount}"; + + list.Add(1060658, args); // ~1_val~: ~2_val~ + } + else + { + list.Add(1060748); // unfilled + } + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + if (Commodity != null) + { + string args; + + if (Commodity.Name == null) + args = + $"#{(Commodity is ICommodity commodity ? commodity.DescriptionNumber : Commodity.LabelNumber)}\t{Commodity.Amount}"; + else + args = $"{Commodity.Name}\t{Commodity.Amount}"; + + LabelTo(from, 1060658, args); // ~1_val~: ~2_val~ + } + } + + public override void OnDoubleClick(Mobile from) + { + int number; + + var box = from.FindBankNoCreate(); + var cox = CommodityDeedBox.Find(this); + + // Veteran Rewards mods + if (Commodity != null) + { + if (box != null && IsChildOf(box)) + { + number = 1047031; // The commodity has been redeemed. + + box.DropItem(Commodity); + + Commodity = null; + Delete(); + } + else if (cox != null) + { + if (cox.IsSecure) + { + number = 1047031; // The commodity has been redeemed. + + cox.DropItem(Commodity); + + Commodity = null; + Delete(); + } + else + { + number = 1080525; // The commodity deed box must be secured before you can use it. + } + } + else + { + if (Core.ML) + number = 1080526; // That must be in your bank box or commodity deed box to use it. + else + number = 1047024; // To claim the resources .... + } + } + else if (cox?.IsSecure == false) + { + number = 1080525; // The commodity deed box must be secured before you can use it. + } + else if ((box == null || !IsChildOf(box)) && cox == null) + { + if (Core.ML) + number = 1080526; // That must be in your bank box or commodity deed box to use it. + else + number = 1047026; // That must be in your bank box to use it. + } + else + { + number = 1047029; // Target the commodity to fill this deed with. + + from.Target = new InternalTarget(this); + } + + from.SendLocalizedMessage(number); + } + + private class InternalTarget : Target + { + private readonly CommodityDeed m_Deed; + + public InternalTarget(CommodityDeed deed) : base(3, false, TargetFlags.None) => m_Deed = deed; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Deed.Deleted) + return; + + int number; + + if (m_Deed.Commodity != null) + { + number = 1047028; // The commodity deed has already been filled. + } + else if (targeted is Item item) + { + var box = from.FindBankNoCreate(); + var cox = CommodityDeedBox.Find(m_Deed); + + // Veteran Rewards mods + if (box != null && m_Deed.IsChildOf(box) && item.IsChildOf(box) || + cox?.IsSecure != true && item.IsChildOf(cox)) + { + if (m_Deed.SetCommodity(item)) + { + m_Deed.Hue = 0x592; + number = 1047030; // The commodity deed has been filled. + } + else + { + number = 1047027; // That is not a commodity the bankers will fill a commodity deed with. + } + } + else if (Core.ML) + { + number = 1080526; // That must be in your bank box or commodity deed box to use it. + } + else + { + number = 1047026; // That must be in your bank box to use it. + } + } + else + { + number = 1047027; // That is not a commodity the bankers will fill a commodity deed with. + } + + from.SendLocalizedMessage(number); + } + } + } +} diff --git a/Projects/UOContent/Items/Deeds/DragonBardingDeed.cs b/Projects/UOContent/Items/Deeds/DragonBardingDeed.cs index c6c0d3953..0b699164e 100644 --- a/Projects/UOContent/Items/Deeds/DragonBardingDeed.cs +++ b/Projects/UOContent/Items/Deeds/DragonBardingDeed.cs @@ -1,165 +1,168 @@ -using System; -using Server.Engines.Craft; -using Server.Mobiles; -using Server.Targeting; - -namespace Server.Items -{ - [TypeAlias("Server.Items.DragonBarding")] - public class DragonBardingDeed : Item, ICraftable - { - private Mobile m_Crafter; - private bool m_Exceptional; - private CraftResource m_Resource; - - public DragonBardingDeed() : base(0x14F0) => Weight = 1.0; - - public DragonBardingDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => m_Exceptional ? 1053181 : 1053012; // dragon barding deed - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Crafter - { - get => m_Crafter; - set - { - m_Crafter = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Exceptional - { - get => m_Exceptional; - set - { - m_Exceptional = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public CraftResource Resource - { - get => m_Resource; - set - { - m_Resource = value; - Hue = CraftResources.GetHue(value); - InvalidateProperties(); - } - } - - public int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, - CraftItem craftItem, int resHue) - { - Exceptional = quality >= 2; - - if (makersMark) - Crafter = from; - - Type resourceType = typeRes ?? craftItem.Resources[0].ItemType; - - Resource = CraftResources.GetFromType(resourceType); - - CraftContext context = craftSystem.GetContext(from); - - if (context?.DoNotColor == true) - Hue = 0; - - return quality; - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_Exceptional && m_Crafter != null) - list.Add(1050043, m_Crafter.Name); // crafted by ~1_NAME~ - } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - from.BeginTarget(6, false, TargetFlags.None, OnTarget); - from.SendLocalizedMessage(1053024); // Select the swamp dragon you wish to place the barding on. - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - - public virtual void OnTarget(Mobile from, object obj) - { - if (Deleted) - return; - - if (!(obj is SwampDragon pet) || pet.HasBarding) - { - from.SendLocalizedMessage(1053025); // That is not an unarmored swamp dragon. - } - else if (!pet.Controlled || pet.ControlMaster != from) - { - from.SendLocalizedMessage(1053026); // You can only put barding on a tamed swamp dragon that you own. - } - else if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1060640); // The item must be in your backpack to use it. - } - else - { - pet.BardingExceptional = Exceptional; - pet.BardingCrafter = Crafter; - pet.BardingHP = pet.BardingMaxHP; - pet.BardingResource = Resource; - pet.HasBarding = true; - pet.Hue = Hue; - - Delete(); - - from.SendLocalizedMessage( - 1053027); // You place the barding on your swamp dragon. Use a bladed item on your dragon to remove the armor. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(m_Exceptional); - writer.Write(m_Crafter); - writer.Write((int)m_Resource); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - case 0: - { - m_Exceptional = reader.ReadBool(); - m_Crafter = reader.ReadMobile(); - - if (version < 1) - reader.ReadInt(); - - m_Resource = (CraftResource)reader.ReadInt(); - break; - } - } - } - } -} +using System; +using Server.Engines.Craft; +using Server.Mobiles; +using Server.Targeting; + +namespace Server.Items +{ + [TypeAlias("Server.Items.DragonBarding")] + public class DragonBardingDeed : Item, ICraftable + { + private Mobile m_Crafter; + private bool m_Exceptional; + private CraftResource m_Resource; + + public DragonBardingDeed() : base(0x14F0) => Weight = 1.0; + + public DragonBardingDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => m_Exceptional ? 1053181 : 1053012; // dragon barding deed + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Crafter + { + get => m_Crafter; + set + { + m_Crafter = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Exceptional + { + get => m_Exceptional; + set + { + m_Exceptional = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public CraftResource Resource + { + get => m_Resource; + set + { + m_Resource = value; + Hue = CraftResources.GetHue(value); + InvalidateProperties(); + } + } + + public int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, + CraftItem craftItem, int resHue + ) + { + Exceptional = quality >= 2; + + if (makersMark) + Crafter = from; + + var resourceType = typeRes ?? craftItem.Resources[0].ItemType; + + Resource = CraftResources.GetFromType(resourceType); + + var context = craftSystem.GetContext(from); + + if (context?.DoNotColor == true) + Hue = 0; + + return quality; + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_Exceptional && m_Crafter != null) + list.Add(1050043, m_Crafter.Name); // crafted by ~1_NAME~ + } + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + from.BeginTarget(6, false, TargetFlags.None, OnTarget); + from.SendLocalizedMessage(1053024); // Select the swamp dragon you wish to place the barding on. + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + + public virtual void OnTarget(Mobile from, object obj) + { + if (Deleted) + return; + + if (!(obj is SwampDragon pet) || pet.HasBarding) + { + from.SendLocalizedMessage(1053025); // That is not an unarmored swamp dragon. + } + else if (!pet.Controlled || pet.ControlMaster != from) + { + from.SendLocalizedMessage(1053026); // You can only put barding on a tamed swamp dragon that you own. + } + else if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1060640); // The item must be in your backpack to use it. + } + else + { + pet.BardingExceptional = Exceptional; + pet.BardingCrafter = Crafter; + pet.BardingHP = pet.BardingMaxHP; + pet.BardingResource = Resource; + pet.HasBarding = true; + pet.Hue = Hue; + + Delete(); + + from.SendLocalizedMessage( + 1053027 + ); // You place the barding on your swamp dragon. Use a bladed item on your dragon to remove the armor. + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(m_Exceptional); + writer.Write(m_Crafter); + writer.Write((int)m_Resource); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + case 0: + { + m_Exceptional = reader.ReadBool(); + m_Crafter = reader.ReadMobile(); + + if (version < 1) + reader.ReadInt(); + + m_Resource = (CraftResource)reader.ReadInt(); + break; + } + } + } + } +} diff --git a/Projects/UOContent/Items/Deeds/HairRestylingDeed.cs b/Projects/UOContent/Items/Deeds/HairRestylingDeed.cs index 709a9e353..834cf8530 100644 --- a/Projects/UOContent/Items/Deeds/HairRestylingDeed.cs +++ b/Projects/UOContent/Items/Deeds/HairRestylingDeed.cs @@ -1,150 +1,155 @@ -using Server.Gumps; -using Server.Mobiles; -using Server.Network; - -namespace Server.Items -{ - public class HairRestylingDeed : Item - { - [Constructible] - public HairRestylingDeed() : base(0x14F0) - { - Weight = 1.0; - LootType = LootType.Blessed; - } - - public HairRestylingDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041061; // a coupon for a free hair restyling - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - from.SendLocalizedMessage(1042001); // That must be in your pack... - else - from.SendGump(new InternalGump(from, this)); - } - - private class InternalGump : Gump - { - private readonly int[][] ElvenArray = - { - new[] { 0 }, - new[] { 1011064, 1011064, 0, 0, 0, 0 }, // bald - new[] { 1074386, 1074386, 0x2fc0, 0x2fc0, 0xedf5, 0xc6e5 }, // long feather - new[] { 1074387, 1074387, 0x2fc1, 0x2fc1, 0xedf6, 0xc6e6 }, // short - new[] { 1074388, 1074388, 0x2fc2, 0x2fc2, 0xedf7, 0xc6e7 }, // mullet - new[] { 1074391, 1074391, 0x2fce, 0x2fce, 0xeddc, 0xc6cc }, // knob - new[] { 1074392, 1074392, 0x2fcf, 0x2fcf, 0xeddd, 0xc6cd }, // braided - new[] { 1074394, 1074394, 0x2fd1, 0x2fd1, 0xeddf, 0xc6cf }, // spiked - new[] { 1074389, 1074385, 0x2fcc, 0x2fbf, 0xedda, 0xc6e4 }, // flower, mid-long - new[] { 1074393, 1074390, 0x2fd0, 0x2fcd, 0xedde, 0xc6cb } // buns, long - }; - - /* - racial arrays are: cliloc_F, cliloc_M, ItemID_F, ItemID_M, gump_img_F, gump_img_M - */ - private readonly int[][] HumanArray = /* why on earth cant these utilies be consistent with hex/dec */ - { - new[] { 0 }, - new[] { 1011064, 1011064, 0, 0, 0, 0 }, // bald - new[] { 1011052, 1011052, 0x203B, 0x203B, 0xed1c, 0xC60C }, // Short - new[] { 1011053, 1011053, 0x203C, 0x203C, 0xed1d, 0xc60d }, // Long - new[] { 1011054, 1011054, 0x203D, 0x203D, 0xed1e, 0xc60e }, // Ponytail - new[] { 1011055, 1011055, 0x2044, 0x2044, 0xed27, 0xC60F }, // Mohawk - new[] { 1011047, 1011047, 0x2045, 0x2045, 0xED26, 0xED26 }, // Pageboy - new[] { 1074393, 1011048, 0x2046, 0x2048, 0xed28, 0xEDE5 }, // Buns, Receding - new[] { 1011049, 1011049, 0x2049, 0x2049, 0xede6, 0xede6 }, // 2-tails - new[] { 1011050, 1011050, 0x204A, 0x204A, 0xED29, 0xED29 }, // Topknot - new[] { 1011396, 1011396, 0x2047, 0x2047, 0xed25, 0xc618 } // Curly - }; - /* - gump data: bgX, bgY, htmlX, htmlY, imgX, imgY, butX, butY - */ - - private readonly int[][] LayoutArray = - { - new[] { 0 }, /* padding: its more efficient than code to ++ the index/buttonid */ - new[] { 425, 280, 342, 295, 000, 000, 310, 292 }, - new[] { 235, 060, 150, 075, 168, 020, 118, 073 }, - new[] { 235, 115, 150, 130, 168, 070, 118, 128 }, - new[] { 235, 170, 150, 185, 168, 130, 118, 183 }, - new[] { 235, 225, 150, 240, 168, 185, 118, 238 }, - new[] { 425, 060, 342, 075, 358, 018, 310, 073 }, - new[] { 425, 115, 342, 130, 358, 075, 310, 128 }, - new[] { 425, 170, 342, 185, 358, 125, 310, 183 }, - new[] { 425, 225, 342, 240, 358, 185, 310, 238 }, - new[] { 235, 280, 150, 295, 168, 245, 118, 292 } // slot 10, Curly - N/A for elfs. - }; - - private readonly HairRestylingDeed m_Deed; - private readonly Mobile m_From; - - public InternalGump(Mobile from, HairRestylingDeed deed) : base(50, 50) - { - m_From = from; - m_Deed = deed; - - from.CloseGump(); - - AddBackground(100, 10, 400, 385, 0xA28); - - AddHtmlLocalized(100, 25, 400, 35, 1013008); - AddButton(175, 340, 0xFA5, 0xFA7, 0x0); // CANCEL - - AddHtmlLocalized(210, 342, 90, 35, 1011012); //
HAIRSTYLE SELECTION MENU
- - int[][] RacialData = from.Race == Race.Human ? HumanArray : ElvenArray; - - for (int i = 1; i < RacialData.Length; i++) - { - AddHtmlLocalized(LayoutArray[i][2], LayoutArray[i][3], i == 1 ? 125 : 80, i == 1 ? 70 : 35, - m_From.Female ? RacialData[i][0] : RacialData[i][1]); - if (LayoutArray[i][4] != 0) - { - AddBackground(LayoutArray[i][0], LayoutArray[i][1], 50, 50, 0xA3C); - AddImage(LayoutArray[i][4], LayoutArray[i][5], m_From.Female ? RacialData[i][4] : RacialData[i][5]); - } - - AddButton(LayoutArray[i][6], LayoutArray[i][7], 0xFA5, 0xFA7, i); - } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_From?.Alive != true) - return; - - if (m_Deed.Deleted) - return; - - if (info.ButtonID < 1 || info.ButtonID > 10) - return; - - int[][] RacialData = m_From.Race == Race.Human ? HumanArray : ElvenArray; - - if (m_From is PlayerMobile pm) - { - pm.SetHairMods(-1, -1); // clear any hairmods (disguise kit, incognito) - pm.HairItemID = pm.Female ? RacialData[info.ButtonID][2] : RacialData[info.ButtonID][3]; - m_Deed.Delete(); - } - } - } - } -} +using Server.Gumps; +using Server.Mobiles; +using Server.Network; + +namespace Server.Items +{ + public class HairRestylingDeed : Item + { + [Constructible] + public HairRestylingDeed() : base(0x14F0) + { + Weight = 1.0; + LootType = LootType.Blessed; + } + + public HairRestylingDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041061; // a coupon for a free hair restyling + + 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 (!IsChildOf(from.Backpack)) + from.SendLocalizedMessage(1042001); // That must be in your pack... + else + from.SendGump(new InternalGump(from, this)); + } + + private class InternalGump : Gump + { + private readonly int[][] ElvenArray = + { + new[] { 0 }, + new[] { 1011064, 1011064, 0, 0, 0, 0 }, // bald + new[] { 1074386, 1074386, 0x2fc0, 0x2fc0, 0xedf5, 0xc6e5 }, // long feather + new[] { 1074387, 1074387, 0x2fc1, 0x2fc1, 0xedf6, 0xc6e6 }, // short + new[] { 1074388, 1074388, 0x2fc2, 0x2fc2, 0xedf7, 0xc6e7 }, // mullet + new[] { 1074391, 1074391, 0x2fce, 0x2fce, 0xeddc, 0xc6cc }, // knob + new[] { 1074392, 1074392, 0x2fcf, 0x2fcf, 0xeddd, 0xc6cd }, // braided + new[] { 1074394, 1074394, 0x2fd1, 0x2fd1, 0xeddf, 0xc6cf }, // spiked + new[] { 1074389, 1074385, 0x2fcc, 0x2fbf, 0xedda, 0xc6e4 }, // flower, mid-long + new[] { 1074393, 1074390, 0x2fd0, 0x2fcd, 0xedde, 0xc6cb } // buns, long + }; + + /* + racial arrays are: cliloc_F, cliloc_M, ItemID_F, ItemID_M, gump_img_F, gump_img_M + */ + private readonly int[][] HumanArray = /* why on earth cant these utilies be consistent with hex/dec */ + { + new[] { 0 }, + new[] { 1011064, 1011064, 0, 0, 0, 0 }, // bald + new[] { 1011052, 1011052, 0x203B, 0x203B, 0xed1c, 0xC60C }, // Short + new[] { 1011053, 1011053, 0x203C, 0x203C, 0xed1d, 0xc60d }, // Long + new[] { 1011054, 1011054, 0x203D, 0x203D, 0xed1e, 0xc60e }, // Ponytail + new[] { 1011055, 1011055, 0x2044, 0x2044, 0xed27, 0xC60F }, // Mohawk + new[] { 1011047, 1011047, 0x2045, 0x2045, 0xED26, 0xED26 }, // Pageboy + new[] { 1074393, 1011048, 0x2046, 0x2048, 0xed28, 0xEDE5 }, // Buns, Receding + new[] { 1011049, 1011049, 0x2049, 0x2049, 0xede6, 0xede6 }, // 2-tails + new[] { 1011050, 1011050, 0x204A, 0x204A, 0xED29, 0xED29 }, // Topknot + new[] { 1011396, 1011396, 0x2047, 0x2047, 0xed25, 0xc618 } // Curly + }; + /* + gump data: bgX, bgY, htmlX, htmlY, imgX, imgY, butX, butY + */ + + private readonly int[][] LayoutArray = + { + new[] { 0 }, /* padding: its more efficient than code to ++ the index/buttonid */ + new[] { 425, 280, 342, 295, 000, 000, 310, 292 }, + new[] { 235, 060, 150, 075, 168, 020, 118, 073 }, + new[] { 235, 115, 150, 130, 168, 070, 118, 128 }, + new[] { 235, 170, 150, 185, 168, 130, 118, 183 }, + new[] { 235, 225, 150, 240, 168, 185, 118, 238 }, + new[] { 425, 060, 342, 075, 358, 018, 310, 073 }, + new[] { 425, 115, 342, 130, 358, 075, 310, 128 }, + new[] { 425, 170, 342, 185, 358, 125, 310, 183 }, + new[] { 425, 225, 342, 240, 358, 185, 310, 238 }, + new[] { 235, 280, 150, 295, 168, 245, 118, 292 } // slot 10, Curly - N/A for elfs. + }; + + private readonly HairRestylingDeed m_Deed; + private readonly Mobile m_From; + + public InternalGump(Mobile from, HairRestylingDeed deed) : base(50, 50) + { + m_From = from; + m_Deed = deed; + + from.CloseGump(); + + AddBackground(100, 10, 400, 385, 0xA28); + + AddHtmlLocalized(100, 25, 400, 35, 1013008); + AddButton(175, 340, 0xFA5, 0xFA7, 0x0); // CANCEL + + AddHtmlLocalized(210, 342, 90, 35, 1011012); //
HAIRSTYLE SELECTION MENU
+ + var RacialData = from.Race == Race.Human ? HumanArray : ElvenArray; + + for (var i = 1; i < RacialData.Length; i++) + { + AddHtmlLocalized( + LayoutArray[i][2], + LayoutArray[i][3], + i == 1 ? 125 : 80, + i == 1 ? 70 : 35, + m_From.Female ? RacialData[i][0] : RacialData[i][1] + ); + if (LayoutArray[i][4] != 0) + { + AddBackground(LayoutArray[i][0], LayoutArray[i][1], 50, 50, 0xA3C); + AddImage(LayoutArray[i][4], LayoutArray[i][5], m_From.Female ? RacialData[i][4] : RacialData[i][5]); + } + + AddButton(LayoutArray[i][6], LayoutArray[i][7], 0xFA5, 0xFA7, i); + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_From?.Alive != true) + return; + + if (m_Deed.Deleted) + return; + + if (info.ButtonID < 1 || info.ButtonID > 10) + return; + + var RacialData = m_From.Race == Race.Human ? HumanArray : ElvenArray; + + if (m_From is PlayerMobile pm) + { + pm.SetHairMods(-1, -1); // clear any hairmods (disguise kit, incognito) + pm.HairItemID = pm.Female ? RacialData[info.ButtonID][2] : RacialData[info.ButtonID][3]; + m_Deed.Delete(); + } + } + } + } +} diff --git a/Projects/UOContent/Items/Deeds/HolidayTreeDeed.cs b/Projects/UOContent/Items/Deeds/HolidayTreeDeed.cs index bc129bfb9..97889782f 100644 --- a/Projects/UOContent/Items/Deeds/HolidayTreeDeed.cs +++ b/Projects/UOContent/Items/Deeds/HolidayTreeDeed.cs @@ -1,161 +1,162 @@ -using System; -using Server.Gumps; -using Server.Multis; -using Server.Network; -using Server.Targeting; - -namespace Server.Items -{ - public class HolidayTreeDeed : Item - { - [Constructible] - public HolidayTreeDeed() : base(0x14F0) - { - Hue = 0x488; - Weight = 1.0; - LootType = LootType.Blessed; - } - - public HolidayTreeDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041116; // a deed for a holiday tree - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - LootType = LootType.Blessed; - } - - public bool ValidatePlacement(Mobile from, Point3D loc) - { - if (from.AccessLevel >= AccessLevel.GameMaster) - return true; - - if (!from.InRange(GetWorldLocation(), 1)) - { - from.SendLocalizedMessage(500446); // That is too far away. - return false; - } - - if (DateTime.UtcNow.Month != 12) - { - from.SendLocalizedMessage( - 1005700); // You will have to wait till next December to put your tree back up for display. - return false; - } - - Map map = from.Map; - - if (map == null) - return false; - - BaseHouse house = BaseHouse.FindHouseAt(loc, map, 20); - - if (house?.IsFriend(from) != true) - { - from.SendLocalizedMessage(1005701); // The holiday tree can only be placed in your house. - return false; - } - - if (!map.CanFit(loc, 20)) - { - from.SendLocalizedMessage(500269); // You cannot build that there. - return false; - } - - return true; - } - - public void BeginPlace(Mobile from, HolidayTreeType type) - { - from.BeginTarget(-1, true, TargetFlags.None, Placement_OnTarget, type); - } - - public void Placement_OnTarget(Mobile from, object targeted, HolidayTreeType type) - { - if (!(targeted is IPoint3D p)) - return; - - Point3D loc = new Point3D(p); - - if (p is StaticTarget target) - /* NOTE: OSI does not properly normalize Z positioning here. - * A side affect is that you can only place on floors (due to the CanFit call). - * That functionality may be desired. And so, it's included in this script. - */ - loc.Z -= TileData.ItemTable[target.ItemID] - .CalcHeight; - - if (ValidatePlacement(from, loc)) - EndPlace(from, type, loc); - } - - public void EndPlace(Mobile from, HolidayTreeType type, Point3D loc) - { - Delete(); - HolidayTree tree = new HolidayTree(from, type, loc); - BaseHouse.FindHouseAt(tree)?.Addons.Add(tree); - } - - public override void OnDoubleClick(Mobile from) - { - from.CloseGump(); - from.SendGump(new HolidayTreeChoiceGump(from, this)); - } - } - - public class HolidayTreeChoiceGump : Gump - { - private readonly HolidayTreeDeed m_Deed; - private readonly Mobile m_From; - - public HolidayTreeChoiceGump(Mobile from, HolidayTreeDeed deed) : base(200, 200) - { - m_From = from; - m_Deed = deed; - - AddPage(0); - - AddBackground(0, 0, 220, 120, 5054); - AddBackground(10, 10, 200, 100, 3000); - - AddButton(20, 35, 4005, 4007, 1); - AddHtmlLocalized(55, 35, 145, 25, 1018322); // Classic - - AddButton(20, 65, 4005, 4007, 2); - AddHtmlLocalized(55, 65, 145, 25, 1018321); // Modern - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Deed.Deleted) - return; - - switch (info.ButtonID) - { - case 1: - { - m_Deed.BeginPlace(m_From, HolidayTreeType.Classic); - break; - } - case 2: - { - m_Deed.BeginPlace(m_From, HolidayTreeType.Modern); - break; - } - } - } - } -} +using System; +using Server.Gumps; +using Server.Multis; +using Server.Network; +using Server.Targeting; + +namespace Server.Items +{ + public class HolidayTreeDeed : Item + { + [Constructible] + public HolidayTreeDeed() : base(0x14F0) + { + Hue = 0x488; + Weight = 1.0; + LootType = LootType.Blessed; + } + + public HolidayTreeDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041116; // a deed for a holiday tree + + 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(); + + LootType = LootType.Blessed; + } + + public bool ValidatePlacement(Mobile from, Point3D loc) + { + if (from.AccessLevel >= AccessLevel.GameMaster) + return true; + + if (!from.InRange(GetWorldLocation(), 1)) + { + from.SendLocalizedMessage(500446); // That is too far away. + return false; + } + + if (DateTime.UtcNow.Month != 12) + { + from.SendLocalizedMessage( + 1005700 + ); // You will have to wait till next December to put your tree back up for display. + return false; + } + + var map = from.Map; + + if (map == null) + return false; + + var house = BaseHouse.FindHouseAt(loc, map, 20); + + if (house?.IsFriend(from) != true) + { + from.SendLocalizedMessage(1005701); // The holiday tree can only be placed in your house. + return false; + } + + if (!map.CanFit(loc, 20)) + { + from.SendLocalizedMessage(500269); // You cannot build that there. + return false; + } + + return true; + } + + public void BeginPlace(Mobile from, HolidayTreeType type) + { + from.BeginTarget(-1, true, TargetFlags.None, Placement_OnTarget, type); + } + + public void Placement_OnTarget(Mobile from, object targeted, HolidayTreeType type) + { + if (!(targeted is IPoint3D p)) + return; + + var loc = new Point3D(p); + + if (p is StaticTarget target) + /* NOTE: OSI does not properly normalize Z positioning here. + * A side affect is that you can only place on floors (due to the CanFit call). + * That functionality may be desired. And so, it's included in this script. + */ + loc.Z -= TileData.ItemTable[target.ItemID] + .CalcHeight; + + if (ValidatePlacement(from, loc)) + EndPlace(from, type, loc); + } + + public void EndPlace(Mobile from, HolidayTreeType type, Point3D loc) + { + Delete(); + var tree = new HolidayTree(from, type, loc); + BaseHouse.FindHouseAt(tree)?.Addons.Add(tree); + } + + public override void OnDoubleClick(Mobile from) + { + from.CloseGump(); + from.SendGump(new HolidayTreeChoiceGump(from, this)); + } + } + + public class HolidayTreeChoiceGump : Gump + { + private readonly HolidayTreeDeed m_Deed; + private readonly Mobile m_From; + + public HolidayTreeChoiceGump(Mobile from, HolidayTreeDeed deed) : base(200, 200) + { + m_From = from; + m_Deed = deed; + + AddPage(0); + + AddBackground(0, 0, 220, 120, 5054); + AddBackground(10, 10, 200, 100, 3000); + + AddButton(20, 35, 4005, 4007, 1); + AddHtmlLocalized(55, 35, 145, 25, 1018322); // Classic + + AddButton(20, 65, 4005, 4007, 2); + AddHtmlLocalized(55, 65, 145, 25, 1018321); // Modern + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Deed.Deleted) + return; + + switch (info.ButtonID) + { + case 1: + { + m_Deed.BeginPlace(m_From, HolidayTreeType.Classic); + break; + } + case 2: + { + m_Deed.BeginPlace(m_From, HolidayTreeType.Modern); + break; + } + } + } + } +} diff --git a/Projects/UOContent/Items/Deeds/NameChangeDeed.cs b/Projects/UOContent/Items/Deeds/NameChangeDeed.cs index 319116cc1..a203cd43b 100644 --- a/Projects/UOContent/Items/Deeds/NameChangeDeed.cs +++ b/Projects/UOContent/Items/Deeds/NameChangeDeed.cs @@ -1,114 +1,114 @@ -using Server.Gumps; -using Server.Misc; -using Server.Network; - -namespace Server.Items -{ - public class NameChangeDeed : Item - { - [Constructible] - public NameChangeDeed() : base(0x14F0) => LootType = LootType.Blessed; - - public NameChangeDeed(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a name change deed"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - if (RootParent == from) - { - from.CloseGump(); - from.SendGump(new NameChangeDeedGump(this)); - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - } - - public class NameChangeDeedGump : Gump - { - private readonly Item m_Sender; - - public NameChangeDeedGump(Item sender) : base(50, 50) - { - m_Sender = sender; - - Closable = true; - Draggable = true; - Resizable = false; - - AddPage(0); - - AddBlackAlpha(10, 120, 250, 85); - AddHtml(10, 125, 250, 20, Color(Center("Name Change Deed"), 0xFFFFFF)); - - AddLabel(73, 15, 1152, ""); - AddLabel(20, 150, 0x480, "New Name:"); - AddTextField(100, 150, 150, 20, 0); - - AddButtonLabeled(75, 180, 1, "Submit"); - } - - public void AddBlackAlpha(int x, int y, int width, int height) - { - AddImageTiled(x, y, width, height, 2624); - AddAlphaRegion(x, y, width, height); - } - - public void AddTextField(int x, int y, int width, int height, int index) - { - AddBackground(x - 2, y - 2, width + 4, height + 4, 0x2486); - AddTextEntry(x + 2, y + 2, width - 4, height - 4, 0, index, ""); - } - - public string Center(string text) => $"
{text}
"; - - public string Color(string text, int color) => $"{text}"; - - public void AddButtonLabeled(int x, int y, int buttonID, string text) - { - AddButton(x, y - 1, 4005, 4007, buttonID); - AddHtml(x + 35, y, 240, 20, Color(text, 0xFFFFFF)); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Sender?.Deleted != false || info.ButtonID != 1 || m_Sender.RootParent != sender.Mobile) - return; - - Mobile m = sender.Mobile; - TextRelay nameEntry = info.GetTextEntry(0); - - string newName = nameEntry?.Text.Trim(); - - if (!NameVerification.Validate(newName, 2, 16, true, false, true, 1, NameVerification.SpaceDashPeriodQuote)) - { - m.SendMessage("That name is unacceptable."); - return; - } - - m.RawName = newName; - m.SendMessage("Your name has been changed!"); - m.SendMessage($"You are now known as {newName}"); - m_Sender.Delete(); - } - } -} +using Server.Gumps; +using Server.Misc; +using Server.Network; + +namespace Server.Items +{ + public class NameChangeDeed : Item + { + [Constructible] + public NameChangeDeed() : base(0x14F0) => LootType = LootType.Blessed; + + public NameChangeDeed(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a name change deed"; + + 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 (RootParent == from) + { + from.CloseGump(); + from.SendGump(new NameChangeDeedGump(this)); + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + } + + public class NameChangeDeedGump : Gump + { + private readonly Item m_Sender; + + public NameChangeDeedGump(Item sender) : base(50, 50) + { + m_Sender = sender; + + Closable = true; + Draggable = true; + Resizable = false; + + AddPage(0); + + AddBlackAlpha(10, 120, 250, 85); + AddHtml(10, 125, 250, 20, Color(Center("Name Change Deed"), 0xFFFFFF)); + + AddLabel(73, 15, 1152, ""); + AddLabel(20, 150, 0x480, "New Name:"); + AddTextField(100, 150, 150, 20, 0); + + AddButtonLabeled(75, 180, 1, "Submit"); + } + + public void AddBlackAlpha(int x, int y, int width, int height) + { + AddImageTiled(x, y, width, height, 2624); + AddAlphaRegion(x, y, width, height); + } + + public void AddTextField(int x, int y, int width, int height, int index) + { + AddBackground(x - 2, y - 2, width + 4, height + 4, 0x2486); + AddTextEntry(x + 2, y + 2, width - 4, height - 4, 0, index, ""); + } + + public string Center(string text) => $"
{text}
"; + + public string Color(string text, int color) => $"{text}"; + + public void AddButtonLabeled(int x, int y, int buttonID, string text) + { + AddButton(x, y - 1, 4005, 4007, buttonID); + AddHtml(x + 35, y, 240, 20, Color(text, 0xFFFFFF)); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Sender?.Deleted != false || info.ButtonID != 1 || m_Sender.RootParent != sender.Mobile) + return; + + var m = sender.Mobile; + var nameEntry = info.GetTextEntry(0); + + var newName = nameEntry?.Text.Trim(); + + if (!NameVerification.Validate(newName, 2, 16, true, false, true, 1, NameVerification.SpaceDashPeriodQuote)) + { + m.SendMessage("That name is unacceptable."); + return; + } + + m.RawName = newName; + m.SendMessage("Your name has been changed!"); + m.SendMessage($"You are now known as {newName}"); + m_Sender.Delete(); + } + } +} diff --git a/Projects/UOContent/Items/Deeds/NewPlayerTicket.cs b/Projects/UOContent/Items/Deeds/NewPlayerTicket.cs index 0c12f2ae7..3d8325366 100644 --- a/Projects/UOContent/Items/Deeds/NewPlayerTicket.cs +++ b/Projects/UOContent/Items/Deeds/NewPlayerTicket.cs @@ -1,205 +1,214 @@ -using Server.Gumps; -using Server.Network; -using Server.Targeting; - -namespace Server.Items -{ - public class NewPlayerTicket : Item - { - [Constructible] - public NewPlayerTicket() : base(0x14EF) - { - Weight = 1.0; - LootType = LootType.Blessed; - } - - public NewPlayerTicket(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Owner { get; set; } - - public override int LabelNumber => 1062094; // a young player ticket - - public override bool DisplayLootType => false; - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1041492); // This is half a prize ticket! Double-click this ticket and target any other ticket marked NEW PLAYER and get a prize! This ticket will only work for YOU, so don't give it away! - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(Owner); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Owner = reader.ReadMobile(); - break; - } - } - - if (Name == "a young player ticket") - Name = null; - } - - public override void OnDoubleClick(Mobile from) - { - if (from != Owner) - { - from.SendLocalizedMessage(501926); // This isn't your ticket! Shame on you! You have to use YOUR ticket. - } - else if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else - { - from.SendLocalizedMessage(501927); // Target any other ticket marked NEW PLAYER to win a prize. - from.Target = new InternalTarget(this); - } - } - - private class InternalTarget : Target - { - private readonly NewPlayerTicket m_Ticket; - - public InternalTarget(NewPlayerTicket ticket) : base(2, false, TargetFlags.None) => m_Ticket = ticket; - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted == m_Ticket) - { - from.SendLocalizedMessage(501928); // You can't target the same ticket! - } - else if (targeted is NewPlayerTicket theirTicket) - { - Mobile them = theirTicket.Owner; - - if (them?.Deleted != false) - { - from.SendLocalizedMessage(501930); // That is not a valid ticket. - } - else - { - from.SendGump(new InternalGump(from, m_Ticket)); - them.SendGump(new InternalGump(them, theirTicket)); - } - } - else if ((targeted as Item)?.ItemID == 0x14F0) - { - from.SendLocalizedMessage(501931); // You need to find another ticket marked NEW PLAYER. - } - else - { - from.SendLocalizedMessage(501929); // You will need to select a ticket. - } - } - } - - private class InternalGump : Gump - { - private readonly Mobile m_From; - private readonly NewPlayerTicket m_Ticket; - - public InternalGump(Mobile from, NewPlayerTicket ticket) : base(50, 50) - { - m_From = from; - m_Ticket = ticket; - - AddBackground(0, 0, 400, 385, 0xA28); - - AddHtmlLocalized(30, 45, 340, 70, 1013011, true, - true); // Choose the gift you prefer. WARNING: if you cancel, and your partner does not, you will need to find another matching ticket! - - AddButton(46, 128, 0xFA5, 0xFA7, 1); - AddHtmlLocalized(80, 130, 320, 35, 1013012); // A sextant - - AddButton(46, 163, 0xFA5, 0xFA7, 2); - AddHtmlLocalized(80, 165, 320, 35, 1013013); // A coupon for a single hair restyling - - AddButton(46, 198, 0xFA5, 0xFA7, 3); - AddHtmlLocalized(80, 200, 320, 35, 1013014); // A spellbook with all 1st - 4th spells. - - AddButton(46, 233, 0xFA5, 0xFA7, 4); - AddHtmlLocalized(80, 235, 320, 35, 1013015); // A wand of fireworks - - AddButton(46, 268, 0xFA5, 0xFA7, 5); - AddHtmlLocalized(80, 270, 320, 35, 1013016); // A spyglass - - AddButton(46, 303, 0xFA5, 0xFA7, 6); - AddHtmlLocalized(80, 305, 320, 35, 1013017); // Dyes and a dye tub - - AddButton(120, 340, 0xFA5, 0xFA7, 0); - AddHtmlLocalized(154, 342, 100, 35, 1011012); // CANCEL - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Ticket.Deleted) - return; - - int number = 0; - - Item item = null; - Item item2 = null; - - switch (info.ButtonID) - { - case 1: - item = new Sextant(); - number = 1010494; - break; // A sextant has been placed in your backpack. - case 2: - item = new HairRestylingDeed(); - number = 501933; - break; // A coupon for a free hair restyling has been placed in your backpack. - case 3: - item = new Spellbook(0xFFFFFFFF); - number = 1010495; - break; // A spellbook with all 1st to 4th circle spells has been placed in your backpack. - case 4: - item = new FireworksWand(); - number = 501935; - break; // A wand of fireworks has been placed in your backpack. - case 5: - item = new Spyglass(); - number = 501936; - break; // A spyglass has been placed in your backpack. - case 6: - item = new DyeTub(); - item2 = new Dyes(); - number = 501937; - break; // The dyes and dye tub have been placed in your backpack. - } - - if (item != null) - { - m_Ticket.Delete(); - - m_From.SendLocalizedMessage(number); - m_From.AddToBackpack(item); - - if (item2 != null) - m_From.AddToBackpack(item2); - } - } - } - } -} +using Server.Gumps; +using Server.Network; +using Server.Targeting; + +namespace Server.Items +{ + public class NewPlayerTicket : Item + { + [Constructible] + public NewPlayerTicket() : base(0x14EF) + { + Weight = 1.0; + LootType = LootType.Blessed; + } + + public NewPlayerTicket(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Owner { get; set; } + + public override int LabelNumber => 1062094; // a young player ticket + + public override bool DisplayLootType => false; + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add( + 1041492 + ); // This is half a prize ticket! Double-click this ticket and target any other ticket marked NEW PLAYER and get a prize! This ticket will only work for YOU, so don't give it away! + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(Owner); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Owner = reader.ReadMobile(); + break; + } + } + + if (Name == "a young player ticket") + Name = null; + } + + public override void OnDoubleClick(Mobile from) + { + if (from != Owner) + { + from.SendLocalizedMessage(501926); // This isn't your ticket! Shame on you! You have to use YOUR ticket. + } + else if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else + { + from.SendLocalizedMessage(501927); // Target any other ticket marked NEW PLAYER to win a prize. + from.Target = new InternalTarget(this); + } + } + + private class InternalTarget : Target + { + private readonly NewPlayerTicket m_Ticket; + + public InternalTarget(NewPlayerTicket ticket) : base(2, false, TargetFlags.None) => m_Ticket = ticket; + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted == m_Ticket) + { + from.SendLocalizedMessage(501928); // You can't target the same ticket! + } + else if (targeted is NewPlayerTicket theirTicket) + { + var them = theirTicket.Owner; + + if (them?.Deleted != false) + { + from.SendLocalizedMessage(501930); // That is not a valid ticket. + } + else + { + from.SendGump(new InternalGump(from, m_Ticket)); + them.SendGump(new InternalGump(them, theirTicket)); + } + } + else if ((targeted as Item)?.ItemID == 0x14F0) + { + from.SendLocalizedMessage(501931); // You need to find another ticket marked NEW PLAYER. + } + else + { + from.SendLocalizedMessage(501929); // You will need to select a ticket. + } + } + } + + private class InternalGump : Gump + { + private readonly Mobile m_From; + private readonly NewPlayerTicket m_Ticket; + + public InternalGump(Mobile from, NewPlayerTicket ticket) : base(50, 50) + { + m_From = from; + m_Ticket = ticket; + + AddBackground(0, 0, 400, 385, 0xA28); + + AddHtmlLocalized( + 30, + 45, + 340, + 70, + 1013011, + true, + true + ); // Choose the gift you prefer. WARNING: if you cancel, and your partner does not, you will need to find another matching ticket! + + AddButton(46, 128, 0xFA5, 0xFA7, 1); + AddHtmlLocalized(80, 130, 320, 35, 1013012); // A sextant + + AddButton(46, 163, 0xFA5, 0xFA7, 2); + AddHtmlLocalized(80, 165, 320, 35, 1013013); // A coupon for a single hair restyling + + AddButton(46, 198, 0xFA5, 0xFA7, 3); + AddHtmlLocalized(80, 200, 320, 35, 1013014); // A spellbook with all 1st - 4th spells. + + AddButton(46, 233, 0xFA5, 0xFA7, 4); + AddHtmlLocalized(80, 235, 320, 35, 1013015); // A wand of fireworks + + AddButton(46, 268, 0xFA5, 0xFA7, 5); + AddHtmlLocalized(80, 270, 320, 35, 1013016); // A spyglass + + AddButton(46, 303, 0xFA5, 0xFA7, 6); + AddHtmlLocalized(80, 305, 320, 35, 1013017); // Dyes and a dye tub + + AddButton(120, 340, 0xFA5, 0xFA7, 0); + AddHtmlLocalized(154, 342, 100, 35, 1011012); // CANCEL + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Ticket.Deleted) + return; + + var number = 0; + + Item item = null; + Item item2 = null; + + switch (info.ButtonID) + { + case 1: + item = new Sextant(); + number = 1010494; + break; // A sextant has been placed in your backpack. + case 2: + item = new HairRestylingDeed(); + number = 501933; + break; // A coupon for a free hair restyling has been placed in your backpack. + case 3: + item = new Spellbook(0xFFFFFFFF); + number = 1010495; + break; // A spellbook with all 1st to 4th circle spells has been placed in your backpack. + case 4: + item = new FireworksWand(); + number = 501935; + break; // A wand of fireworks has been placed in your backpack. + case 5: + item = new Spyglass(); + number = 501936; + break; // A spyglass has been placed in your backpack. + case 6: + item = new DyeTub(); + item2 = new Dyes(); + number = 501937; + break; // The dyes and dye tub have been placed in your backpack. + } + + if (item != null) + { + m_Ticket.Delete(); + + m_From.SendLocalizedMessage(number); + m_From.AddToBackpack(item); + + if (item2 != null) + m_From.AddToBackpack(item2); + } + } + } + } +} diff --git a/Projects/UOContent/Items/Deeds/VendorRentalContract.cs b/Projects/UOContent/Items/Deeds/VendorRentalContract.cs index 12b790403..12b97fca9 100644 --- a/Projects/UOContent/Items/Deeds/VendorRentalContract.cs +++ b/Projects/UOContent/Items/Deeds/VendorRentalContract.cs @@ -1,343 +1,347 @@ -using System; -using System.Collections.Generic; -using Server.ContextMenus; -using Server.Gumps; -using Server.Mobiles; -using Server.Multis; -using Server.Targeting; - -namespace Server.Items -{ - public class VendorRentalContract : Item - { - private VendorRentalDuration m_Duration; - - private Mobile m_Offeree; - private Timer m_OfferExpireTimer; - - [Constructible] - public VendorRentalContract() : base(0x14F0) - { - Weight = 1.0; - Hue = 0x672; - - m_Duration = VendorRentalDuration.Instances[0]; - Price = 1500; - } - - public VendorRentalContract(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1062332; // a vendor rental contract - - public VendorRentalDuration Duration - { - get => m_Duration; - set - { - if (value != null) - m_Duration = value; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Price { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool LandlordRenew { get; set; } - - public Mobile Offeree - { - get => m_Offeree; - set - { - if (m_OfferExpireTimer != null) - { - m_OfferExpireTimer.Stop(); - m_OfferExpireTimer = null; - } - - m_Offeree = value; - - if (value != null) - { - m_OfferExpireTimer = new OfferExpireTimer(this); - m_OfferExpireTimer.Start(); - } - - InvalidateProperties(); - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Offeree != null) - list.Add(1062368, Offeree.Name); // Being Offered To ~1_NAME~ - } - - public bool IsLandlord(Mobile m) - { - if (IsLockedDown) - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (house != null && house.DecayType != DecayType.Condemned) - return house.IsOwner(m); - } - - return false; - } - - public bool IsUsableBy(Mobile from, bool byLandlord, bool byBackpack, bool noOfferee, bool sendMessage) - { - if (Deleted || !from.CheckAlive(sendMessage)) - return false; - - if (noOfferee && Offeree != null) - { - if (sendMessage) - from.SendLocalizedMessage(1062343); // That item is currently in use. - - return false; - } - - if (byBackpack && IsChildOf(from.Backpack)) - return true; - - if (byLandlord && IsLandlord(from)) - { - if (from.Map != Map || !from.InRange(this, 5)) - { - if (sendMessage) - from.SendLocalizedMessage(501853); // Target is too far away. - - return false; - } - - return true; - } - - return false; - } - - public override void OnDelete() - { - if (IsLockedDown) - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - house?.VendorRentalContracts.Remove(this); - } - } - - public override void OnDoubleClick(Mobile from) - { - if (Offeree != null) - { - from.SendLocalizedMessage(1062343); // That item is currently in use. - } - else if (!IsLockedDown) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. - return; - } - - BaseHouse house = BaseHouse.FindHouseAt(from); - - if (house?.IsOwner(from) != true) - { - from.SendLocalizedMessage( - 1062333); // You must be standing inside of a house that you own to make use of this contract. - } - else if (!house.IsAosRules) - { - from.SendMessage("Rental contracts can only be placed in AOS-enabled houses."); - } - else if (!house.Public) - { - from.SendLocalizedMessage(1062335); // Rental contracts can only be placed in public houses. - } - else if (!house.CanPlaceNewVendor()) - { - from.SendLocalizedMessage(1062352); // You do not have enough storage available to place this contract. - } - else - { - from.SendLocalizedMessage(1062337); // Target the exact location you wish to rent out. - from.Target = new RentTarget(this); - } - } - else if (IsLandlord(from)) - { - if (from.InRange(this, 5)) - { - from.CloseGump(); - from.SendGump(new VendorRentalContractGump(this, from)); - } - else - { - from.SendLocalizedMessage(501853); // Target is too far away. - } - } - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (IsUsableBy(from, true, true, true, false)) list.Add(new ContractOptionEntry(this)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.WriteEncodedInt(m_Duration.ID); - - writer.Write(Price); - writer.Write(LandlordRenew); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - int durationID = reader.ReadEncodedInt(); - if (durationID < VendorRentalDuration.Instances.Length) - m_Duration = VendorRentalDuration.Instances[durationID]; - else - m_Duration = VendorRentalDuration.Instances[0]; - - Price = reader.ReadInt(); - LandlordRenew = reader.ReadBool(); - } - - private class ContractOptionEntry : ContextMenuEntry - { - private readonly VendorRentalContract m_Contract; - - public ContractOptionEntry(VendorRentalContract contract) : base(6209) => m_Contract = contract; - - public override void OnClick() - { - Mobile from = Owner.From; - - if (m_Contract.IsUsableBy(from, true, true, true, true)) - { - from.CloseGump(); - from.SendGump(new VendorRentalContractGump(m_Contract, from)); - } - } - } - - private class RentTarget : Target - { - private readonly VendorRentalContract m_Contract; - - public RentTarget(VendorRentalContract contract) : base(-1, false, TargetFlags.None) => m_Contract = contract; - - protected override void OnTarget(Mobile from, object targeted) - { - if (!m_Contract.IsUsableBy(from, false, true, true, true)) - return; - - if (!(targeted is IPoint3D location)) - return; - - Point3D pLocation = new Point3D(location); - Map map = from.Map; - - BaseHouse house = BaseHouse.FindHouseAt(pLocation, map, 0); - - if (house?.IsOwner(from) != true) - { - from.SendLocalizedMessage(1062338); // The location being rented out must be inside of your house. - } - else if (BaseHouse.FindHouseAt(from) != house) - { - from.SendLocalizedMessage( - 1062339); // You must be located inside of the house in which you are trying to place the contract. - } - else if (!house.IsAosRules) - { - from.SendMessage("Rental contracts can only be placed in AOS-enabled houses."); - } - else if (!house.Public) - { - from.SendLocalizedMessage(1062335); // Rental contracts can only be placed in public houses. - } - else if (house.DecayType == DecayType.Condemned) - { - from.SendLocalizedMessage(1062468); // You cannot place a contract in a condemned house. - } - else if (!house.CanPlaceNewVendor()) - { - from.SendLocalizedMessage(1062352); // You do not have enought storage available to place this contract. - } - else if (!map.CanFit(pLocation, 16, false, false)) - { - from.SendLocalizedMessage(1062486); // A vendor cannot exist at that location. Please try again. - } - else - { - BaseHouse.IsThereVendor(pLocation, map, out bool vendor, out bool contract); - - if (vendor) - { - from.SendLocalizedMessage( - 1062342); // You may not place a rental contract at this location while other beings occupy it. - } - else if (contract) - { - from.SendLocalizedMessage( - 1062341); // That location is cluttered. Please clear out any objects there and try again. - } - else - { - m_Contract.MoveToWorld(pLocation, map); - - if (!house.LockDown(from, m_Contract)) from.AddToBackpack(m_Contract); - } - } - } - - protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType) - { - from.SendLocalizedMessage(1062336); // You decide not to place the contract at this time. - } - } - - private class OfferExpireTimer : Timer - { - private readonly VendorRentalContract m_Contract; - - public OfferExpireTimer(VendorRentalContract contract) : base(TimeSpan.FromSeconds(30.0)) - { - m_Contract = contract; - - Priority = TimerPriority.OneSecond; - } - - protected override void OnTick() - { - Mobile offeree = m_Contract.Offeree; - - if (offeree != null) - { - offeree.CloseGump(); - - m_Contract.Offeree = null; - } - } - } - } -} +using System; +using System.Collections.Generic; +using Server.ContextMenus; +using Server.Gumps; +using Server.Mobiles; +using Server.Multis; +using Server.Targeting; + +namespace Server.Items +{ + public class VendorRentalContract : Item + { + private VendorRentalDuration m_Duration; + + private Mobile m_Offeree; + private Timer m_OfferExpireTimer; + + [Constructible] + public VendorRentalContract() : base(0x14F0) + { + Weight = 1.0; + Hue = 0x672; + + m_Duration = VendorRentalDuration.Instances[0]; + Price = 1500; + } + + public VendorRentalContract(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1062332; // a vendor rental contract + + public VendorRentalDuration Duration + { + get => m_Duration; + set + { + if (value != null) + m_Duration = value; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Price { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool LandlordRenew { get; set; } + + public Mobile Offeree + { + get => m_Offeree; + set + { + if (m_OfferExpireTimer != null) + { + m_OfferExpireTimer.Stop(); + m_OfferExpireTimer = null; + } + + m_Offeree = value; + + if (value != null) + { + m_OfferExpireTimer = new OfferExpireTimer(this); + m_OfferExpireTimer.Start(); + } + + InvalidateProperties(); + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (Offeree != null) + list.Add(1062368, Offeree.Name); // Being Offered To ~1_NAME~ + } + + public bool IsLandlord(Mobile m) + { + if (IsLockedDown) + { + var house = BaseHouse.FindHouseAt(this); + + if (house != null && house.DecayType != DecayType.Condemned) + return house.IsOwner(m); + } + + return false; + } + + public bool IsUsableBy(Mobile from, bool byLandlord, bool byBackpack, bool noOfferee, bool sendMessage) + { + if (Deleted || !from.CheckAlive(sendMessage)) + return false; + + if (noOfferee && Offeree != null) + { + if (sendMessage) + from.SendLocalizedMessage(1062343); // That item is currently in use. + + return false; + } + + if (byBackpack && IsChildOf(from.Backpack)) + return true; + + if (byLandlord && IsLandlord(from)) + { + if (from.Map != Map || !from.InRange(this, 5)) + { + if (sendMessage) + from.SendLocalizedMessage(501853); // Target is too far away. + + return false; + } + + return true; + } + + return false; + } + + public override void OnDelete() + { + if (IsLockedDown) + { + var house = BaseHouse.FindHouseAt(this); + + house?.VendorRentalContracts.Remove(this); + } + } + + public override void OnDoubleClick(Mobile from) + { + if (Offeree != null) + { + from.SendLocalizedMessage(1062343); // That item is currently in use. + } + else if (!IsLockedDown) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. + return; + } + + var house = BaseHouse.FindHouseAt(from); + + if (house?.IsOwner(from) != true) + { + from.SendLocalizedMessage( + 1062333 + ); // You must be standing inside of a house that you own to make use of this contract. + } + else if (!house.IsAosRules) + { + from.SendMessage("Rental contracts can only be placed in AOS-enabled houses."); + } + else if (!house.Public) + { + from.SendLocalizedMessage(1062335); // Rental contracts can only be placed in public houses. + } + else if (!house.CanPlaceNewVendor()) + { + from.SendLocalizedMessage(1062352); // You do not have enough storage available to place this contract. + } + else + { + from.SendLocalizedMessage(1062337); // Target the exact location you wish to rent out. + from.Target = new RentTarget(this); + } + } + else if (IsLandlord(from)) + { + if (from.InRange(this, 5)) + { + from.CloseGump(); + from.SendGump(new VendorRentalContractGump(this, from)); + } + else + { + from.SendLocalizedMessage(501853); // Target is too far away. + } + } + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (IsUsableBy(from, true, true, true, false)) list.Add(new ContractOptionEntry(this)); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.WriteEncodedInt(m_Duration.ID); + + writer.Write(Price); + writer.Write(LandlordRenew); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + var durationID = reader.ReadEncodedInt(); + if (durationID < VendorRentalDuration.Instances.Length) + m_Duration = VendorRentalDuration.Instances[durationID]; + else + m_Duration = VendorRentalDuration.Instances[0]; + + Price = reader.ReadInt(); + LandlordRenew = reader.ReadBool(); + } + + private class ContractOptionEntry : ContextMenuEntry + { + private readonly VendorRentalContract m_Contract; + + public ContractOptionEntry(VendorRentalContract contract) : base(6209) => m_Contract = contract; + + public override void OnClick() + { + var from = Owner.From; + + if (m_Contract.IsUsableBy(from, true, true, true, true)) + { + from.CloseGump(); + from.SendGump(new VendorRentalContractGump(m_Contract, from)); + } + } + } + + private class RentTarget : Target + { + private readonly VendorRentalContract m_Contract; + + public RentTarget(VendorRentalContract contract) : base(-1, false, TargetFlags.None) => m_Contract = contract; + + protected override void OnTarget(Mobile from, object targeted) + { + if (!m_Contract.IsUsableBy(from, false, true, true, true)) + return; + + if (!(targeted is IPoint3D location)) + return; + + var pLocation = new Point3D(location); + var map = from.Map; + + var house = BaseHouse.FindHouseAt(pLocation, map, 0); + + if (house?.IsOwner(from) != true) + { + from.SendLocalizedMessage(1062338); // The location being rented out must be inside of your house. + } + else if (BaseHouse.FindHouseAt(from) != house) + { + from.SendLocalizedMessage( + 1062339 + ); // You must be located inside of the house in which you are trying to place the contract. + } + else if (!house.IsAosRules) + { + from.SendMessage("Rental contracts can only be placed in AOS-enabled houses."); + } + else if (!house.Public) + { + from.SendLocalizedMessage(1062335); // Rental contracts can only be placed in public houses. + } + else if (house.DecayType == DecayType.Condemned) + { + from.SendLocalizedMessage(1062468); // You cannot place a contract in a condemned house. + } + else if (!house.CanPlaceNewVendor()) + { + from.SendLocalizedMessage(1062352); // You do not have enought storage available to place this contract. + } + else if (!map.CanFit(pLocation, 16, false, false)) + { + from.SendLocalizedMessage(1062486); // A vendor cannot exist at that location. Please try again. + } + else + { + BaseHouse.IsThereVendor(pLocation, map, out var vendor, out var contract); + + if (vendor) + { + from.SendLocalizedMessage( + 1062342 + ); // You may not place a rental contract at this location while other beings occupy it. + } + else if (contract) + { + from.SendLocalizedMessage( + 1062341 + ); // That location is cluttered. Please clear out any objects there and try again. + } + else + { + m_Contract.MoveToWorld(pLocation, map); + + if (!house.LockDown(from, m_Contract)) from.AddToBackpack(m_Contract); + } + } + } + + protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType) + { + from.SendLocalizedMessage(1062336); // You decide not to place the contract at this time. + } + } + + private class OfferExpireTimer : Timer + { + private readonly VendorRentalContract m_Contract; + + public OfferExpireTimer(VendorRentalContract contract) : base(TimeSpan.FromSeconds(30.0)) + { + m_Contract = contract; + + Priority = TimerPriority.OneSecond; + } + + protected override void OnTick() + { + var offeree = m_Contract.Offeree; + + if (offeree != null) + { + offeree.CloseGump(); + + m_Contract.Offeree = null; + } + } + } + } +} diff --git a/Projects/UOContent/Items/Facial/Beard.cs b/Projects/UOContent/Items/Facial/Beard.cs index f6c1e4d94..cbede5e74 100644 --- a/Projects/UOContent/Items/Facial/Beard.cs +++ b/Projects/UOContent/Items/Facial/Beard.cs @@ -1,14 +1,14 @@ -namespace Server.Items -{ - public static class Beard - { - public static int LongBeard = 0x203E; - public static int ShortBeard = 0x203f; - public static int Goatee = 0x2040; - public static int Mustache = 0x2041; - - public static int MediumShortBeard = 0x204B; - public static int MediumLongBeard = 0x204C; - public static int Vandyke = 0x204D; - } -} \ No newline at end of file +namespace Server.Items +{ + public static class Beard + { + public static int LongBeard = 0x203E; + public static int ShortBeard = 0x203f; + public static int Goatee = 0x2040; + public static int Mustache = 0x2041; + + public static int MediumShortBeard = 0x204B; + public static int MediumLongBeard = 0x204C; + public static int Vandyke = 0x204D; + } +} diff --git a/Projects/UOContent/Items/Facial/Hair.cs b/Projects/UOContent/Items/Facial/Hair.cs index 28abe8fa4..fee06a68f 100644 --- a/Projects/UOContent/Items/Facial/Hair.cs +++ b/Projects/UOContent/Items/Facial/Hair.cs @@ -1,31 +1,31 @@ -namespace Server.Items -{ - public static class Hair - { - // Human - public static readonly int Long = 0x203C; - public static readonly int Shor = 0x203B; - public static readonly int PonyTail = 0x203D; - - public static readonly int Mohawk = 0x2044; - public static readonly int Pageboy = 0x2045; - public static readonly int Bun = 0x2046; // Female Only - public static readonly int Afro = 0x2047; - public static readonly int Receding = 0x2048; // Male Only - public static readonly int TwoPigTails = 0x2049; - public static readonly int Krisna = 0x204A; - - // Elf - public static readonly int MidLongElf = 0x2FBF; // Male Only - public static readonly int LongFeather = 0x2FC0; - public static readonly int ShortElf = 0x2FC1; - public static readonly int Mullet = 0x2FC2; - - public static readonly int Flower = 0x2FCC; // Female only - public static readonly int LongElf = 0x2FCD; // Male Only - public static readonly int Knob = 0x2FCE; - public static readonly int Braided = 0x2FCF; - public static readonly int BunElf = 0x2FD0; // Female Only - public static readonly int Spiked = 0x2FD1; - } -} +namespace Server.Items +{ + public static class Hair + { + // Human + public static readonly int Long = 0x203C; + public static readonly int Shor = 0x203B; + public static readonly int PonyTail = 0x203D; + + public static readonly int Mohawk = 0x2044; + public static readonly int Pageboy = 0x2045; + public static readonly int Bun = 0x2046; // Female Only + public static readonly int Afro = 0x2047; + public static readonly int Receding = 0x2048; // Male Only + public static readonly int TwoPigTails = 0x2049; + public static readonly int Krisna = 0x204A; + + // Elf + public static readonly int MidLongElf = 0x2FBF; // Male Only + public static readonly int LongFeather = 0x2FC0; + public static readonly int ShortElf = 0x2FC1; + public static readonly int Mullet = 0x2FC2; + + public static readonly int Flower = 0x2FCC; // Female only + public static readonly int LongElf = 0x2FCD; // Male Only + public static readonly int Knob = 0x2FCE; + public static readonly int Braided = 0x2FCF; + public static readonly int BunElf = 0x2FD0; // Female Only + public static readonly int Spiked = 0x2FD1; + } +} diff --git a/Projects/UOContent/Items/Farming/FarmableCabbage.cs b/Projects/UOContent/Items/Farming/FarmableCabbage.cs index 0a0c4861b..f9fb4563b 100644 --- a/Projects/UOContent/Items/Farming/FarmableCabbage.cs +++ b/Projects/UOContent/Items/Farming/FarmableCabbage.cs @@ -1,41 +1,41 @@ -namespace Server.Items -{ - public class FarmableCabbage : FarmableCrop - { - [Constructible] - public FarmableCabbage() : base(GetCropID()) - { - } - - public FarmableCabbage(Serial serial) : base(serial) - { - } - - public static int GetCropID() => 3254; - - public override Item GetCropObject() - { - Cabbage cabbage = new Cabbage(); - - cabbage.ItemID = Utility.Random(3195, 2); - - return cabbage; - } - - public override int GetPickedID() => 3254; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FarmableCabbage : FarmableCrop + { + [Constructible] + public FarmableCabbage() : base(GetCropID()) + { + } + + public FarmableCabbage(Serial serial) : base(serial) + { + } + + public static int GetCropID() => 3254; + + public override Item GetCropObject() + { + var cabbage = new Cabbage(); + + cabbage.ItemID = Utility.Random(3195, 2); + + return cabbage; + } + + public override int GetPickedID() => 3254; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Farming/FarmableCarrot.cs b/Projects/UOContent/Items/Farming/FarmableCarrot.cs index 89270a9b2..5c4e79f5d 100644 --- a/Projects/UOContent/Items/Farming/FarmableCarrot.cs +++ b/Projects/UOContent/Items/Farming/FarmableCarrot.cs @@ -1,41 +1,41 @@ -namespace Server.Items -{ - public class FarmableCarrot : FarmableCrop - { - [Constructible] - public FarmableCarrot() : base(GetCropID()) - { - } - - public FarmableCarrot(Serial serial) : base(serial) - { - } - - public static int GetCropID() => 3190; - - public override Item GetCropObject() - { - Carrot carrot = new Carrot(); - - carrot.ItemID = Utility.Random(3191, 2); - - return carrot; - } - - public override int GetPickedID() => 3254; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FarmableCarrot : FarmableCrop + { + [Constructible] + public FarmableCarrot() : base(GetCropID()) + { + } + + public FarmableCarrot(Serial serial) : base(serial) + { + } + + public static int GetCropID() => 3190; + + public override Item GetCropObject() + { + var carrot = new Carrot(); + + carrot.ItemID = Utility.Random(3191, 2); + + return carrot; + } + + public override int GetPickedID() => 3254; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Farming/FarmableCotton.cs b/Projects/UOContent/Items/Farming/FarmableCotton.cs index e06423b39..f4ff49e08 100644 --- a/Projects/UOContent/Items/Farming/FarmableCotton.cs +++ b/Projects/UOContent/Items/Farming/FarmableCotton.cs @@ -1,34 +1,34 @@ -namespace Server.Items -{ - public class FarmableCotton : FarmableCrop - { - [Constructible] - public FarmableCotton() : base(GetCropID()) - { - } - - public FarmableCotton(Serial serial) : base(serial) - { - } - - public static int GetCropID() => Utility.Random(3153, 4); - - public override Item GetCropObject() => new Cotton(); - - public override int GetPickedID() => 3254; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FarmableCotton : FarmableCrop + { + [Constructible] + public FarmableCotton() : base(GetCropID()) + { + } + + public FarmableCotton(Serial serial) : base(serial) + { + } + + public static int GetCropID() => Utility.Random(3153, 4); + + public override Item GetCropObject() => new Cotton(); + + public override int GetPickedID() => 3254; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Farming/FarmableCrop.cs b/Projects/UOContent/Items/Farming/FarmableCrop.cs index af6248d99..a4b1b73df 100644 --- a/Projects/UOContent/Items/Farming/FarmableCrop.cs +++ b/Projects/UOContent/Items/Farming/FarmableCrop.cs @@ -1,87 +1,87 @@ -using System; -using Server.Network; - -namespace Server.Items -{ - public abstract class FarmableCrop : Item - { - private bool m_Picked; - - public FarmableCrop(int itemID) : base(itemID) => Movable = false; - - public FarmableCrop(Serial serial) : base(serial) - { - } - - public abstract Item GetCropObject(); - public abstract int GetPickedID(); - - public override void OnDoubleClick(Mobile from) - { - Map map = Map; - Point3D loc = Location; - - if (Parent != null || Movable || IsLockedDown || IsSecure || map == null || map == Map.Internal) - return; - - if (!from.InRange(loc, 2) || !from.InLOS(this)) - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - else if (!m_Picked) - OnPicked(from, loc, map); - } - - public virtual void OnPicked(Mobile from, Point3D loc, Map map) - { - ItemID = GetPickedID(); - - Item spawn = GetCropObject(); - - spawn?.MoveToWorld(loc, map); - - m_Picked = true; - - Unlink(); - - Timer.DelayCall(TimeSpan.FromMinutes(5.0), Delete); - } - - public void Unlink() - { - ISpawner se = Spawner; - - if (se != null) - { - Spawner.Remove(this); - Spawner = null; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_Picked); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_Picked = version switch - { - 0 => reader.ReadBool(), - _ => m_Picked - }; - - if (m_Picked) - { - Unlink(); - Delete(); - } - } - } -} \ No newline at end of file +using System; +using Server.Network; + +namespace Server.Items +{ + public abstract class FarmableCrop : Item + { + private bool m_Picked; + + public FarmableCrop(int itemID) : base(itemID) => Movable = false; + + public FarmableCrop(Serial serial) : base(serial) + { + } + + public abstract Item GetCropObject(); + public abstract int GetPickedID(); + + public override void OnDoubleClick(Mobile from) + { + var map = Map; + var loc = Location; + + if (Parent != null || Movable || IsLockedDown || IsSecure || map == null || map == Map.Internal) + return; + + if (!from.InRange(loc, 2) || !from.InLOS(this)) + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + else if (!m_Picked) + OnPicked(from, loc, map); + } + + public virtual void OnPicked(Mobile from, Point3D loc, Map map) + { + ItemID = GetPickedID(); + + var spawn = GetCropObject(); + + spawn?.MoveToWorld(loc, map); + + m_Picked = true; + + Unlink(); + + Timer.DelayCall(TimeSpan.FromMinutes(5.0), Delete); + } + + public void Unlink() + { + var se = Spawner; + + if (se != null) + { + Spawner.Remove(this); + Spawner = null; + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_Picked); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_Picked = version switch + { + 0 => reader.ReadBool(), + _ => m_Picked + }; + + if (m_Picked) + { + Unlink(); + Delete(); + } + } + } +} diff --git a/Projects/UOContent/Items/Farming/FarmableFlax.cs b/Projects/UOContent/Items/Farming/FarmableFlax.cs index 8ab117127..e698b6560 100644 --- a/Projects/UOContent/Items/Farming/FarmableFlax.cs +++ b/Projects/UOContent/Items/Farming/FarmableFlax.cs @@ -1,41 +1,41 @@ -namespace Server.Items -{ - public class FarmableFlax : FarmableCrop - { - [Constructible] - public FarmableFlax() : base(GetCropID()) - { - } - - public FarmableFlax(Serial serial) : base(serial) - { - } - - public static int GetCropID() => Utility.Random(6809, 3); - - public override Item GetCropObject() - { - Flax flax = new Flax(); - - flax.ItemID = Utility.Random(6812, 2); - - return flax; - } - - public override int GetPickedID() => 3254; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FarmableFlax : FarmableCrop + { + [Constructible] + public FarmableFlax() : base(GetCropID()) + { + } + + public FarmableFlax(Serial serial) : base(serial) + { + } + + public static int GetCropID() => Utility.Random(6809, 3); + + public override Item GetCropObject() + { + var flax = new Flax(); + + flax.ItemID = Utility.Random(6812, 2); + + return flax; + } + + public override int GetPickedID() => 3254; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Farming/FarmableLettuce.cs b/Projects/UOContent/Items/Farming/FarmableLettuce.cs index e762b63f7..bc930b824 100644 --- a/Projects/UOContent/Items/Farming/FarmableLettuce.cs +++ b/Projects/UOContent/Items/Farming/FarmableLettuce.cs @@ -1,41 +1,41 @@ -namespace Server.Items -{ - public class FarmableLettuce : FarmableCrop - { - [Constructible] - public FarmableLettuce() : base(GetCropID()) - { - } - - public FarmableLettuce(Serial serial) : base(serial) - { - } - - public static int GetCropID() => 3254; - - public override Item GetCropObject() - { - Lettuce lettuce = new Lettuce(); - - lettuce.ItemID = Utility.Random(3184, 2); - - return lettuce; - } - - public override int GetPickedID() => 3254; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FarmableLettuce : FarmableCrop + { + [Constructible] + public FarmableLettuce() : base(GetCropID()) + { + } + + public FarmableLettuce(Serial serial) : base(serial) + { + } + + public static int GetCropID() => 3254; + + public override Item GetCropObject() + { + var lettuce = new Lettuce(); + + lettuce.ItemID = Utility.Random(3184, 2); + + return lettuce; + } + + public override int GetPickedID() => 3254; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Farming/FarmableOnion.cs b/Projects/UOContent/Items/Farming/FarmableOnion.cs index 3bfe25b80..22d86df48 100644 --- a/Projects/UOContent/Items/Farming/FarmableOnion.cs +++ b/Projects/UOContent/Items/Farming/FarmableOnion.cs @@ -1,41 +1,41 @@ -namespace Server.Items -{ - public class FarmableOnion : FarmableCrop - { - [Constructible] - public FarmableOnion() : base(GetCropID()) - { - } - - public FarmableOnion(Serial serial) : base(serial) - { - } - - public static int GetCropID() => 3183; - - public override Item GetCropObject() - { - Onion onion = new Onion(); - - onion.ItemID = Utility.Random(3181, 2); - - return onion; - } - - public override int GetPickedID() => 3254; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FarmableOnion : FarmableCrop + { + [Constructible] + public FarmableOnion() : base(GetCropID()) + { + } + + public FarmableOnion(Serial serial) : base(serial) + { + } + + public static int GetCropID() => 3183; + + public override Item GetCropObject() + { + var onion = new Onion(); + + onion.ItemID = Utility.Random(3181, 2); + + return onion; + } + + public override int GetPickedID() => 3254; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Farming/FarmablePumpkin.cs b/Projects/UOContent/Items/Farming/FarmablePumpkin.cs index c2029415d..dc6c0f4be 100644 --- a/Projects/UOContent/Items/Farming/FarmablePumpkin.cs +++ b/Projects/UOContent/Items/Farming/FarmablePumpkin.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - public class FarmablePumpkin : FarmableCrop - { - [Constructible] - public FarmablePumpkin() - : base(GetCropID()) - { - } - - public FarmablePumpkin(Serial serial) - : base(serial) - { - } - - public static int GetCropID() => Utility.Random(3166, 3); - - public override Item GetCropObject() - { - Pumpkin pumpkin = new Pumpkin(); - - pumpkin.ItemID = Utility.Random(3178, 3); - - return pumpkin; - } - - public override int GetPickedID() => Utility.Random(3166, 3); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FarmablePumpkin : FarmableCrop + { + [Constructible] + public FarmablePumpkin() + : base(GetCropID()) + { + } + + public FarmablePumpkin(Serial serial) + : base(serial) + { + } + + public static int GetCropID() => Utility.Random(3166, 3); + + public override Item GetCropObject() + { + var pumpkin = new Pumpkin(); + + pumpkin.ItemID = Utility.Random(3178, 3); + + return pumpkin; + } + + public override int GetPickedID() => Utility.Random(3166, 3); + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Farming/FarmableTurnip.cs b/Projects/UOContent/Items/Farming/FarmableTurnip.cs index 8032f045d..eec9facbd 100644 --- a/Projects/UOContent/Items/Farming/FarmableTurnip.cs +++ b/Projects/UOContent/Items/Farming/FarmableTurnip.cs @@ -1,41 +1,41 @@ -namespace Server.Items -{ - public class FarmableTurnip : FarmableCrop - { - [Constructible] - public FarmableTurnip() : base(GetCropID()) - { - } - - public FarmableTurnip(Serial serial) : base(serial) - { - } - - public static int GetCropID() => Utility.Random(3169, 3); - - public override Item GetCropObject() - { - Turnip turnip = new Turnip(); - - turnip.ItemID = Utility.Random(3385, 2); - - return turnip; - } - - public override int GetPickedID() => 3254; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FarmableTurnip : FarmableCrop + { + [Constructible] + public FarmableTurnip() : base(GetCropID()) + { + } + + public FarmableTurnip(Serial serial) : base(serial) + { + } + + public static int GetCropID() => Utility.Random(3169, 3); + + public override Item GetCropObject() + { + var turnip = new Turnip(); + + turnip.ItemID = Utility.Random(3385, 2); + + return turnip; + } + + public override int GetPickedID() => 3254; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Farming/FarmableWheat.cs b/Projects/UOContent/Items/Farming/FarmableWheat.cs index 35fa900f8..d3fcbf109 100644 --- a/Projects/UOContent/Items/Farming/FarmableWheat.cs +++ b/Projects/UOContent/Items/Farming/FarmableWheat.cs @@ -1,34 +1,34 @@ -namespace Server.Items -{ - public class FarmableWheat : FarmableCrop - { - [Constructible] - public FarmableWheat() : base(GetCropID()) - { - } - - public FarmableWheat(Serial serial) : base(serial) - { - } - - public static int GetCropID() => Utility.Random(3157, 4); - - public override Item GetCropObject() => new WheatSheaf(); - - public override int GetPickedID() => Utility.Random(3502, 2); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FarmableWheat : FarmableCrop + { + [Constructible] + public FarmableWheat() : base(GetCropID()) + { + } + + public FarmableWheat(Serial serial) : base(serial) + { + } + + public static int GetCropID() => Utility.Random(3157, 4); + + public override Item GetCropObject() => new WheatSheaf(); + + public override int GetPickedID() => Utility.Random(3502, 2); + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Food/Asian.cs b/Projects/UOContent/Items/Food/Asian.cs index 30d78f257..1b621b602 100644 --- a/Projects/UOContent/Items/Food/Asian.cs +++ b/Projects/UOContent/Items/Food/Asian.cs @@ -1,344 +1,344 @@ -namespace Server.Items -{ - public class Wasabi : Item - { - [Constructible] - public Wasabi() : base(0x24E8) => Weight = 1.0; - - public Wasabi(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class WasabiClumps : Food - { - [Constructible] - public WasabiClumps() : base(0x24EB, 1) - { - Stackable = false; - Weight = 1.0; - FillFactor = 2; - } - - public WasabiClumps(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class EmptyBentoBox : Item - { - [Constructible] - public EmptyBentoBox() : base(0x2834) => Weight = 5.0; - - public EmptyBentoBox(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BentoBox : Food - { - [Constructible] - public BentoBox() : base(0x2836, 1) - { - Stackable = false; - Weight = 5.0; - FillFactor = 2; - } - - public BentoBox(Serial serial) : base(serial) - { - } - - public override bool Eat(Mobile from) - { - if (!base.Eat(from)) - return false; - - from.AddToBackpack(new EmptyBentoBox()); - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SushiRolls : Food - { - [Constructible] - public SushiRolls() : base(0x283E, 1) - { - Stackable = false; - Weight = 3.0; - FillFactor = 2; - } - - public SushiRolls(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SushiPlatter : Food - { - [Constructible] - public SushiPlatter() : base(0x2840, 1) - { - Stackable = Core.ML; - Weight = 3.0; - FillFactor = 2; - } - - public SushiPlatter(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GreenTeaBasket : Item - { - [Constructible] - public GreenTeaBasket() : base(0x284B) => Weight = 10.0; - - public GreenTeaBasket(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GreenTea : Food - { - [Constructible] - public GreenTea() : base(0x284C, 1) - { - Stackable = false; - Weight = 4.0; - FillFactor = 2; - } - - public GreenTea(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class MisoSoup : Food - { - [Constructible] - public MisoSoup() : base(0x284D, 1) - { - Stackable = false; - Weight = 4.0; - FillFactor = 2; - } - - public MisoSoup(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class WhiteMisoSoup : Food - { - [Constructible] - public WhiteMisoSoup() : base(0x284E, 1) - { - Stackable = false; - Weight = 4.0; - FillFactor = 2; - } - - public WhiteMisoSoup(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class RedMisoSoup : Food - { - [Constructible] - public RedMisoSoup() : base(0x284F, 1) - { - Stackable = false; - Weight = 4.0; - FillFactor = 2; - } - - public RedMisoSoup(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class AwaseMisoSoup : Food - { - [Constructible] - public AwaseMisoSoup() : base(0x2850, 1) - { - Stackable = false; - Weight = 4.0; - FillFactor = 2; - } - - public AwaseMisoSoup(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class Wasabi : Item + { + [Constructible] + public Wasabi() : base(0x24E8) => Weight = 1.0; + + public Wasabi(Serial serial) : base(serial) + { + } + + 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 class WasabiClumps : Food + { + [Constructible] + public WasabiClumps() : base(0x24EB, 1) + { + Stackable = false; + Weight = 1.0; + FillFactor = 2; + } + + public WasabiClumps(Serial serial) : base(serial) + { + } + + 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 class EmptyBentoBox : Item + { + [Constructible] + public EmptyBentoBox() : base(0x2834) => Weight = 5.0; + + public EmptyBentoBox(Serial serial) : base(serial) + { + } + + 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 class BentoBox : Food + { + [Constructible] + public BentoBox() : base(0x2836, 1) + { + Stackable = false; + Weight = 5.0; + FillFactor = 2; + } + + public BentoBox(Serial serial) : base(serial) + { + } + + public override bool Eat(Mobile from) + { + if (!base.Eat(from)) + return false; + + from.AddToBackpack(new EmptyBentoBox()); + return true; + } + + 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 class SushiRolls : Food + { + [Constructible] + public SushiRolls() : base(0x283E, 1) + { + Stackable = false; + Weight = 3.0; + FillFactor = 2; + } + + public SushiRolls(Serial serial) : base(serial) + { + } + + 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 class SushiPlatter : Food + { + [Constructible] + public SushiPlatter() : base(0x2840, 1) + { + Stackable = Core.ML; + Weight = 3.0; + FillFactor = 2; + } + + public SushiPlatter(Serial serial) : base(serial) + { + } + + 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 class GreenTeaBasket : Item + { + [Constructible] + public GreenTeaBasket() : base(0x284B) => Weight = 10.0; + + public GreenTeaBasket(Serial serial) : base(serial) + { + } + + 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 class GreenTea : Food + { + [Constructible] + public GreenTea() : base(0x284C, 1) + { + Stackable = false; + Weight = 4.0; + FillFactor = 2; + } + + public GreenTea(Serial serial) : base(serial) + { + } + + 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 class MisoSoup : Food + { + [Constructible] + public MisoSoup() : base(0x284D, 1) + { + Stackable = false; + Weight = 4.0; + FillFactor = 2; + } + + public MisoSoup(Serial serial) : base(serial) + { + } + + 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 class WhiteMisoSoup : Food + { + [Constructible] + public WhiteMisoSoup() : base(0x284E, 1) + { + Stackable = false; + Weight = 4.0; + FillFactor = 2; + } + + public WhiteMisoSoup(Serial serial) : base(serial) + { + } + + 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 class RedMisoSoup : Food + { + [Constructible] + public RedMisoSoup() : base(0x284F, 1) + { + Stackable = false; + Weight = 4.0; + FillFactor = 2; + } + + public RedMisoSoup(Serial serial) : base(serial) + { + } + + 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 class AwaseMisoSoup : Food + { + [Constructible] + public AwaseMisoSoup() : base(0x2850, 1) + { + Stackable = false; + Weight = 4.0; + FillFactor = 2; + } + + public AwaseMisoSoup(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Food/Beverage.cs b/Projects/UOContent/Items/Food/Beverage.cs index acaddd9bb..3a345f06a 100644 --- a/Projects/UOContent/Items/Food/Beverage.cs +++ b/Projects/UOContent/Items/Food/Beverage.cs @@ -1,1128 +1,1142 @@ -using System; -using System.Collections.Generic; -using Server.Engines.Plants; -using Server.Engines.Quests; -using Server.Engines.Quests.Hag; -using Server.Engines.Quests.Matriarch; -using Server.Mobiles; -using Server.Multis; -using Server.Network; -using Server.Targeting; - -namespace Server.Items -{ - public enum BeverageType - { - Ale, - Cider, - Liquor, - Milk, - Wine, - Water - } - - public interface IHasQuantity - { - int Quantity { get; set; } - } - - public interface IWaterSource : IHasQuantity - { - } - - // TODO: Flippable attributes - - [TypeAlias("Server.Items.BottleAle", "Server.Items.BottleLiquor", "Server.Items.BottleWine")] - public class BeverageBottle : BaseBeverage - { - [Constructible] - public BeverageBottle(BeverageType type) - : base(type) => - Weight = 1.0; - - public BeverageBottle(Serial serial) - : base(serial) - { - } - - public override int BaseLabelNumber => 1042959; // a bottle of Ale - public override int MaxQuantity => 5; - public override bool Fillable => false; - - public override int ComputeItemID() - { - if (!IsEmpty) - switch (Content) - { - case BeverageType.Ale: return 0x99F; - case BeverageType.Cider: return 0x99F; - case BeverageType.Liquor: return 0x99B; - case BeverageType.Milk: return 0x99B; - case BeverageType.Wine: return 0x9C7; - case BeverageType.Water: return 0x99B; - } - - return 0; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - if (CheckType("BottleAle")) - { - Quantity = MaxQuantity; - Content = BeverageType.Ale; - } - else if (CheckType("BottleLiquor")) - { - Quantity = MaxQuantity; - Content = BeverageType.Liquor; - } - else if (CheckType("BottleWine")) - { - Quantity = MaxQuantity; - Content = BeverageType.Wine; - } - else - { - throw new Exception(World.LoadingType); - } - - break; - } - } - } - } - - public class Jug : BaseBeverage - { - [Constructible] - public Jug(BeverageType type) - : base(type) => - Weight = 1.0; - - public Jug(Serial serial) - : base(serial) - { - } - - public override int BaseLabelNumber => 1042965; // a jug of Ale - public override int MaxQuantity => 10; - public override bool Fillable => false; - - public override int ComputeItemID() - { - if (!IsEmpty) - return 0x9C8; - - return 0; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class CeramicMug : BaseBeverage - { - [Constructible] - public CeramicMug() => Weight = 1.0; - - [Constructible] - public CeramicMug(BeverageType type) - : base(type) => - Weight = 1.0; - - public CeramicMug(Serial serial) - : base(serial) - { - } - - public override int BaseLabelNumber => 1042982; // a ceramic mug of Ale - public override int MaxQuantity => 1; - - public override int ComputeItemID() - { - if (ItemID >= 0x995 && ItemID <= 0x999) - return ItemID; - if (ItemID == 0x9CA) - return ItemID; - - return 0x995; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PewterMug : BaseBeverage - { - [Constructible] - public PewterMug() => Weight = 1.0; - - [Constructible] - public PewterMug(BeverageType type) - : base(type) => - Weight = 1.0; - - public PewterMug(Serial serial) - : base(serial) - { - } - - public override int BaseLabelNumber => 1042994; // a pewter mug with Ale - public override int MaxQuantity => 1; - - public override int ComputeItemID() - { - if (ItemID >= 0xFFF && ItemID <= 0x1002) - return ItemID; - - return 0xFFF; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Goblet : BaseBeverage - { - [Constructible] - public Goblet() => Weight = 1.0; - - [Constructible] - public Goblet(BeverageType type) - : base(type) => - Weight = 1.0; - - public Goblet(Serial serial) - : base(serial) - { - } - - public override int BaseLabelNumber => 1043000; // a goblet of Ale - public override int MaxQuantity => 1; - - public override int ComputeItemID() - { - if (ItemID == 0x99A || ItemID == 0x9B3 || ItemID == 0x9BF || ItemID == 0x9CB) - return ItemID; - - return 0x99A; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [TypeAlias("Server.Items.MugAle", "Server.Items.GlassCider", "Server.Items.GlassLiquor", - "Server.Items.GlassMilk", "Server.Items.GlassWine", "Server.Items.GlassWater")] - public class GlassMug : BaseBeverage - { - [Constructible] - public GlassMug() => Weight = 1.0; - - [Constructible] - public GlassMug(BeverageType type) - : base(type) => - Weight = 1.0; - - public GlassMug(Serial serial) - : base(serial) - { - } - - public override int EmptyLabelNumber => 1022456; // mug - public override int BaseLabelNumber => 1042976; // a mug of Ale - public override int MaxQuantity => 5; - - public override int ComputeItemID() - { - if (IsEmpty) - return ItemID >= 0x1F81 && ItemID <= 0x1F84 ? ItemID : 0x1F81; - - return Content switch - { - BeverageType.Ale => ItemID == 0x9EF ? 0x9EF : 0x9EE, - BeverageType.Cider => ItemID >= 0x1F7D && ItemID <= 0x1F80 ? ItemID : 0x1F7D, - BeverageType.Liquor => ItemID >= 0x1F85 && ItemID <= 0x1F88 ? ItemID : 0x1F85, - BeverageType.Milk => ItemID >= 0x1F89 && ItemID <= 0x1F8C ? ItemID : 0x1F89, - BeverageType.Wine => ItemID >= 0x1F8D && ItemID <= 0x1F90 ? ItemID : 0x1F8D, - BeverageType.Water => ItemID >= 0x1F91 && ItemID <= 0x1F94 ? ItemID : 0x1F91, - _ => 0 - }; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - if (CheckType("MugAle")) - { - Quantity = MaxQuantity; - Content = BeverageType.Ale; - } - else if (CheckType("GlassCider")) - { - Quantity = MaxQuantity; - Content = BeverageType.Cider; - } - else if (CheckType("GlassLiquor")) - { - Quantity = MaxQuantity; - Content = BeverageType.Liquor; - } - else if (CheckType("GlassMilk")) - { - Quantity = MaxQuantity; - Content = BeverageType.Milk; - } - else if (CheckType("GlassWine")) - { - Quantity = MaxQuantity; - Content = BeverageType.Wine; - } - else if (CheckType("GlassWater")) - { - Quantity = MaxQuantity; - Content = BeverageType.Water; - } - else - { - throw new Exception(World.LoadingType); - } - - break; - } - } - } - } - - [TypeAlias("Server.Items.PitcherAle", "Server.Items.PitcherCider", "Server.Items.PitcherLiquor", - "Server.Items.PitcherMilk", "Server.Items.PitcherWine", "Server.Items.PitcherWater", - "Server.Items.GlassPitcher")] - public class Pitcher : BaseBeverage - { - [Constructible] - public Pitcher() => Weight = 2.0; - - [Constructible] - public Pitcher(BeverageType type) - : base(type) => - Weight = 2.0; - - public Pitcher(Serial serial) - : base(serial) - { - } - - public override int BaseLabelNumber => 1048128; // a Pitcher of Ale - public override int MaxQuantity => 5; - - public override int ComputeItemID() - { - if (IsEmpty) - { - if (ItemID == 0x9A7 || ItemID == 0xFF7) - return ItemID; - - return 0xFF6; - } - - switch (Content) - { - case BeverageType.Ale: - { - if (ItemID == 0x1F96) - return ItemID; - - return 0x1F95; - } - case BeverageType.Cider: - { - if (ItemID == 0x1F98) - return ItemID; - - return 0x1F97; - } - case BeverageType.Liquor: - { - if (ItemID == 0x1F9A) - return ItemID; - - return 0x1F99; - } - case BeverageType.Milk: - { - if (ItemID == 0x9AD) - return ItemID; - - return 0x9F0; - } - case BeverageType.Wine: - { - if (ItemID == 0x1F9C) - return ItemID; - - return 0x1F9B; - } - case BeverageType.Water: - { - if (ItemID == 0xFF8 || ItemID == 0xFF9 || ItemID == 0x1F9E) - return ItemID; - - return 0x1F9D; - } - } - - return 0; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - if (CheckType("PitcherWater") || CheckType("GlassPitcher")) - InternalDeserialize(reader, false); - else - InternalDeserialize(reader, true); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - if (CheckType("PitcherAle")) - { - Quantity = MaxQuantity; - Content = BeverageType.Ale; - } - else if (CheckType("PitcherCider")) - { - Quantity = MaxQuantity; - Content = BeverageType.Cider; - } - else if (CheckType("PitcherLiquor")) - { - Quantity = MaxQuantity; - Content = BeverageType.Liquor; - } - else if (CheckType("PitcherMilk")) - { - Quantity = MaxQuantity; - Content = BeverageType.Milk; - } - else if (CheckType("PitcherWine")) - { - Quantity = MaxQuantity; - Content = BeverageType.Wine; - } - else if (CheckType("PitcherWater")) - { - Quantity = MaxQuantity; - Content = BeverageType.Water; - } - else if (CheckType("GlassPitcher")) - { - Quantity = 0; - Content = BeverageType.Water; - } - else - { - throw new Exception(World.LoadingType); - } - - break; - } - } - } - } - - public abstract class BaseBeverage : Item, IHasQuantity - { - private static readonly int[] m_SwampTiles = - { - 0x9C4, 0x9EB, - 0x3D65, 0x3D65, - 0x3DC0, 0x3DD9, - 0x3DDB, 0x3DDC, - 0x3DDE, 0x3EF0, - 0x3FF6, 0x3FF6, - 0x3FFC, 0x3FFE - }; - - private BeverageType m_Content; - private int m_Quantity; - - public BaseBeverage() => ItemID = ComputeItemID(); - - public BaseBeverage(BeverageType type) - { - m_Content = type; - m_Quantity = MaxQuantity; - ItemID = ComputeItemID(); - } - - public BaseBeverage(Serial serial) - : base(serial) - { - } - - public override int LabelNumber - { - get - { - int num = BaseLabelNumber; - - if (IsEmpty || num == 0) - return EmptyLabelNumber; - - return BaseLabelNumber + (int)m_Content; - } - } - - public virtual bool ShowQuantity => MaxQuantity > 1; - public virtual bool Fillable => true; - public virtual bool Pourable => true; - - public virtual int EmptyLabelNumber => base.LabelNumber; - public virtual int BaseLabelNumber => 0; - - public abstract int MaxQuantity { get; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsEmpty => m_Quantity <= 0; - - [CommandProperty(AccessLevel.GameMaster)] - public bool ContainsAlchohol => !IsEmpty && m_Content != BeverageType.Milk && m_Content != BeverageType.Water; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsFull => m_Quantity >= MaxQuantity; - - [CommandProperty(AccessLevel.GameMaster)] - public Poison Poison { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Poisoner { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public BeverageType Content - { - get => m_Content; - set - { - m_Content = value; - - InvalidateProperties(); - - int itemID = ComputeItemID(); - - if (itemID > 0) - ItemID = itemID; - else - Delete(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Quantity - { - get => m_Quantity; - set - { - m_Quantity = Math.Clamp(value, 0, MaxQuantity); - - InvalidateProperties(); - - int itemID = ComputeItemID(); - - if (itemID > 0) - ItemID = itemID; - else - Delete(); - } - } - - public abstract int ComputeItemID(); - - public virtual int GetQuantityDescription() - { - int perc = m_Quantity * 100 / MaxQuantity; - - if (perc <= 0) - return 1042975; // It's empty. - if (perc <= 33) - return 1042974; // It's nearly empty. - if (perc <= 66) - return 1042973; // It's half full. - return 1042972; // It's full. - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (ShowQuantity) - list.Add(GetQuantityDescription()); - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - if (ShowQuantity) - LabelTo(from, GetQuantityDescription()); - } - - public virtual bool ValidateUse(Mobile from, bool message) - { - if (Deleted) - return false; - - if (!Movable && !Fillable) - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (house?.HasLockedDownItem(this) != true) - { - if (message) - from.SendLocalizedMessage(502946, "", 0x59); // That belongs to someone else. - - return false; - } - } - - if (from.Map != Map || !from.InRange(GetWorldLocation(), 2) || !from.InLOS(this)) - { - if (message) - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - - return false; - } - - return true; - } - - public virtual void Fill_OnTarget(Mobile from, object targ) - { - if (!IsEmpty || !Fillable || !ValidateUse(from, false)) - return; - - if (targ is BaseBeverage bev) - { - if (bev.IsEmpty || !bev.ValidateUse(from, true)) - return; - - Content = bev.Content; - Poison = bev.Poison; - Poisoner = bev.Poisoner; - - if (bev.Quantity > MaxQuantity) - { - Quantity = MaxQuantity; - bev.Quantity -= MaxQuantity; - } - else - { - Quantity += bev.Quantity; - bev.Quantity = 0; - } - } - else if (targ is BaseWaterContainer bwc) - { - if (Quantity == 0 || (Content == BeverageType.Water && !IsFull)) - { - int iNeed = Math.Min(MaxQuantity - Quantity, bwc.Quantity); - - if (iNeed > 0 && !bwc.IsEmpty && !IsFull) - { - bwc.Quantity -= iNeed; - Quantity += iNeed; - Content = BeverageType.Water; - - from.PlaySound(0x4E); - } - } - } - else if (targ is Item item) - { - IWaterSource src = item as IWaterSource; - - if (src == null && item is AddonComponent component) - src = component.Addon as IWaterSource; - - if (src == null || src.Quantity <= 0) - return; - - if (from.Map != item.Map || !from.InRange(item.GetWorldLocation(), 2) || !from.InLOS(item)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return; - } - - Content = BeverageType.Water; - Poison = null; - Poisoner = null; - - if (src.Quantity > MaxQuantity) - { - Quantity = MaxQuantity; - src.Quantity -= MaxQuantity; - } - else - { - Quantity += src.Quantity; - src.Quantity = 0; - } - - from.SendLocalizedMessage(1010089); // You fill the container with water. - } - else if (targ is Cow cow) - { - if (cow.TryMilk(from)) - { - Content = BeverageType.Milk; - Quantity = MaxQuantity; - from.SendLocalizedMessage(1080197); // You fill the container with milk. - } - } - else if (targ is LandTarget target) - { - int tileID = target.TileID; - - if (from is PlayerMobile player) - { - QuestSystem qs = player.Quest; - - if (!(qs is WitchApprenticeQuest)) - return; - - FindIngredientObjective obj = qs.FindObjective(); - - if (obj?.Completed == true && obj.Ingredient == Ingredient.SwampWater) - { - bool contains = false; - - for (int i = 0; !contains && i < m_SwampTiles.Length; i += 2) - contains = tileID >= m_SwampTiles[i] && tileID <= m_SwampTiles[i + 1]; - - if (contains) - { - Delete(); - - player.SendLocalizedMessage( - 1055035); // You dip the container into the disgusting swamp water, collecting enough for the Hag's vile stew. - obj.Complete(); - } - } - } - } - } - - public virtual void Pour_OnTarget(Mobile from, object targ) - { - if (IsEmpty || !Pourable || !ValidateUse(from, false)) - return; - - if (targ is BaseBeverage bev) - { - if (!bev.ValidateUse(from, true)) - return; - - if (bev.IsFull && bev.Content == Content) - { - from.SendLocalizedMessage(500848); // Couldn't pour it there. It was already full. - } - else if (!bev.IsEmpty) - { - from.SendLocalizedMessage(500846); // Can't pour it there. - } - else - { - bev.Content = Content; - bev.Poison = Poison; - bev.Poisoner = Poisoner; - - if (Quantity > bev.MaxQuantity) - { - bev.Quantity = bev.MaxQuantity; - Quantity -= bev.MaxQuantity; - } - else - { - bev.Quantity += Quantity; - Quantity = 0; - } - - from.PlaySound(0x4E); - } - } - else if (from == targ) - { - if (from.Thirst < 20) - from.Thirst += 1; - - if (ContainsAlchohol) - { - var bac = Content switch - { - BeverageType.Ale => 1, - BeverageType.Wine => 2, - BeverageType.Cider => 3, - BeverageType.Liquor => 4, - _ => 0 - }; - - from.BAC = Math.Min(from.BAC + bac, 60); - - CheckHeaveTimer(from); - } - - from.PlaySound(Utility.RandomList(0x30, 0x2D6)); - - if (Poison != null) - from.ApplyPoison(Poisoner, Poison); - - --Quantity; - } - else if (targ is BaseWaterContainer bwc) - { - if (Content != BeverageType.Water) - { - from.SendLocalizedMessage(500842); // Can't pour that in there. - } - else if (bwc.Items.Count != 0) - { - from.SendLocalizedMessage(500841); // That has something in it. - } - else - { - int itNeeds = Math.Min(bwc.MaxQuantity - bwc.Quantity, Quantity); - - if (itNeeds > 0) - { - bwc.Quantity += itNeeds; - Quantity -= itNeeds; - - from.PlaySound(0x4E); - } - } - } - else if (targ is PlantItem item) - { - item.Pour(from, this); - } - else if (targ is AddonComponent component && - (component.Addon is WaterVatEast || component.Addon is WaterVatSouth) && - Content == BeverageType.Water) - { - if (from is PlayerMobile player) - if (player.Quest is SolenMatriarchQuest qs) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) - { - BaseAddon vat = component.Addon; - - if (vat.X > 5784 && vat.X < 5814 && vat.Y > 1903 && vat.Y < 1934 && - ((qs.RedSolen && vat.Map == Map.Trammel) || (!qs.RedSolen && vat.Map == Map.Felucca))) - { - if (obj.CurProgress + Quantity > obj.MaxProgress) - { - int delta = obj.MaxProgress - obj.CurProgress; - - Quantity -= delta; - obj.CurProgress = obj.MaxProgress; - } - else - { - obj.CurProgress += Quantity; - Quantity = 0; - } - } - } - } - } - else - { - from.SendLocalizedMessage(500846); // Can't pour it there. - } - } - - public override void OnDoubleClick(Mobile from) - { - if (IsEmpty) - { - if (!Fillable || !ValidateUse(from, true)) - return; - - from.BeginTarget(-1, true, TargetFlags.None, Fill_OnTarget); - SendLocalizedMessageTo(from, 500837); // Fill from what? - } - else if (Pourable && ValidateUse(from, true)) - { - from.BeginTarget(-1, true, TargetFlags.None, Pour_OnTarget); - from.SendLocalizedMessage(1010086); // What do you want to use this on? - } - } - - public static bool ConsumeTotal(Container pack, BeverageType content, int quantity) => ConsumeTotal(pack, typeof(BaseBeverage), content, quantity); - - public static bool ConsumeTotal(Container pack, Type itemType, BeverageType content, int quantity) - { - Item[] items = pack.FindItemsByType(itemType); - - // First pass, compute total - int total = 0; - - for (int i = 0; i < items.Length; ++i) - if (items[i] is BaseBeverage bev && bev.Content == content && !bev.IsEmpty) - total += bev.Quantity; - - if (total >= quantity) - { - // We've enough, so consume it - - int need = quantity; - - for (int i = 0; i < items.Length; ++i) - { - if (!(items[i] is BaseBeverage bev) || bev.Content != content || bev.IsEmpty) - continue; - - int theirQuantity = bev.Quantity; - - if (theirQuantity < need) - { - bev.Quantity = 0; - need -= theirQuantity; - } - else - { - bev.Quantity -= need; - return true; - } - } - } - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(Poisoner); - - Poison.Serialize(Poison, writer); - writer.Write((int)m_Content); - writer.Write(m_Quantity); - } - - protected bool CheckType(string name) => World.LoadingType == $"Server.Items.{name}"; - - public override void Deserialize(IGenericReader reader) - { - InternalDeserialize(reader, true); - } - - protected void InternalDeserialize(IGenericReader reader, bool read) - { - base.Deserialize(reader); - - if (!read) - return; - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - Poisoner = reader.ReadMobile(); - goto case 0; - } - case 0: - { - Poison = Poison.Deserialize(reader); - m_Content = (BeverageType)reader.ReadInt(); - m_Quantity = reader.ReadInt(); - break; - } - } - } - - private static readonly Dictionary m_Table = new Dictionary(); - - public static void Initialize() - { - EventSink.Login += EventSink_Login; - } - - private static void EventSink_Login(Mobile m) - { - CheckHeaveTimer(m); - } - - public static void CheckHeaveTimer(Mobile from) - { - if (from.BAC > 0 && from.Map != Map.Internal && !from.Deleted) - { - if (m_Table.ContainsKey(from)) - return; - - if (from.BAC > 60) - from.BAC = 60; - - Timer t = new HeaveTimer(from); - t.Start(); - - m_Table[from] = t; - } - else if (m_Table.TryGetValue(from, out var t)) - { - t.Stop(); - m_Table.Remove(from); - - from.SendLocalizedMessage(500850); // You feel sober. - } - } - - private class HeaveTimer : Timer - { - private readonly Mobile m_Drunk; - - public HeaveTimer(Mobile drunk) - : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0)) - { - m_Drunk = drunk; - - Priority = TimerPriority.OneSecond; - } - - protected override void OnTick() - { - if (m_Drunk.Deleted || m_Drunk.Map == Map.Internal) - { - Stop(); - m_Table.Remove(m_Drunk); - } - else if (m_Drunk.Alive) - { - if (m_Drunk.BAC > 60) - m_Drunk.BAC = 60; - - // chance to get sober - if (Utility.Random(100) < 10) - --m_Drunk.BAC; - - // lose some stats - m_Drunk.Stam -= 1; - m_Drunk.Mana -= 1; - - if (Utility.Random(1, 4) == 1) - { - if (!m_Drunk.Mounted) - { - // turn in a random direction - m_Drunk.Direction = (Direction)Utility.Random(8); - - // heave - m_Drunk.Animate(32, 5, 1, true, false, 0); - } - - // *hic* - m_Drunk.PublicOverheadMessage(MessageType.Regular, 0x3B2, 500849); - } - - if (m_Drunk.BAC <= 0) - { - Stop(); - m_Table.Remove(m_Drunk); - - m_Drunk.SendLocalizedMessage(500850); // You feel sober. - } - } - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Engines.Plants; +using Server.Engines.Quests; +using Server.Engines.Quests.Hag; +using Server.Engines.Quests.Matriarch; +using Server.Mobiles; +using Server.Multis; +using Server.Network; +using Server.Targeting; + +namespace Server.Items +{ + public enum BeverageType + { + Ale, + Cider, + Liquor, + Milk, + Wine, + Water + } + + public interface IHasQuantity + { + int Quantity { get; set; } + } + + public interface IWaterSource : IHasQuantity + { + } + + // TODO: Flippable attributes + + [TypeAlias("Server.Items.BottleAle", "Server.Items.BottleLiquor", "Server.Items.BottleWine")] + public class BeverageBottle : BaseBeverage + { + [Constructible] + public BeverageBottle(BeverageType type) + : base(type) => + Weight = 1.0; + + public BeverageBottle(Serial serial) + : base(serial) + { + } + + public override int BaseLabelNumber => 1042959; // a bottle of Ale + public override int MaxQuantity => 5; + public override bool Fillable => false; + + public override int ComputeItemID() + { + if (!IsEmpty) + switch (Content) + { + case BeverageType.Ale: return 0x99F; + case BeverageType.Cider: return 0x99F; + case BeverageType.Liquor: return 0x99B; + case BeverageType.Milk: return 0x99B; + case BeverageType.Wine: return 0x9C7; + case BeverageType.Water: return 0x99B; + } + + return 0; + } + + 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(); + + switch (version) + { + case 0: + { + if (CheckType("BottleAle")) + { + Quantity = MaxQuantity; + Content = BeverageType.Ale; + } + else if (CheckType("BottleLiquor")) + { + Quantity = MaxQuantity; + Content = BeverageType.Liquor; + } + else if (CheckType("BottleWine")) + { + Quantity = MaxQuantity; + Content = BeverageType.Wine; + } + else + { + throw new Exception(World.LoadingType); + } + + break; + } + } + } + } + + public class Jug : BaseBeverage + { + [Constructible] + public Jug(BeverageType type) + : base(type) => + Weight = 1.0; + + public Jug(Serial serial) + : base(serial) + { + } + + public override int BaseLabelNumber => 1042965; // a jug of Ale + public override int MaxQuantity => 10; + public override bool Fillable => false; + + public override int ComputeItemID() + { + if (!IsEmpty) + return 0x9C8; + + return 0; + } + + 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(); + } + } + + public class CeramicMug : BaseBeverage + { + [Constructible] + public CeramicMug() => Weight = 1.0; + + [Constructible] + public CeramicMug(BeverageType type) + : base(type) => + Weight = 1.0; + + public CeramicMug(Serial serial) + : base(serial) + { + } + + public override int BaseLabelNumber => 1042982; // a ceramic mug of Ale + public override int MaxQuantity => 1; + + public override int ComputeItemID() + { + if (ItemID >= 0x995 && ItemID <= 0x999) + return ItemID; + if (ItemID == 0x9CA) + return ItemID; + + return 0x995; + } + + 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(); + } + } + + public class PewterMug : BaseBeverage + { + [Constructible] + public PewterMug() => Weight = 1.0; + + [Constructible] + public PewterMug(BeverageType type) + : base(type) => + Weight = 1.0; + + public PewterMug(Serial serial) + : base(serial) + { + } + + public override int BaseLabelNumber => 1042994; // a pewter mug with Ale + public override int MaxQuantity => 1; + + public override int ComputeItemID() + { + if (ItemID >= 0xFFF && ItemID <= 0x1002) + return ItemID; + + return 0xFFF; + } + + 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(); + } + } + + public class Goblet : BaseBeverage + { + [Constructible] + public Goblet() => Weight = 1.0; + + [Constructible] + public Goblet(BeverageType type) + : base(type) => + Weight = 1.0; + + public Goblet(Serial serial) + : base(serial) + { + } + + public override int BaseLabelNumber => 1043000; // a goblet of Ale + public override int MaxQuantity => 1; + + public override int ComputeItemID() + { + if (ItemID == 0x99A || ItemID == 0x9B3 || ItemID == 0x9BF || ItemID == 0x9CB) + return ItemID; + + return 0x99A; + } + + 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(); + } + } + + [TypeAlias( + "Server.Items.MugAle", + "Server.Items.GlassCider", + "Server.Items.GlassLiquor", + "Server.Items.GlassMilk", + "Server.Items.GlassWine", + "Server.Items.GlassWater" + )] + public class GlassMug : BaseBeverage + { + [Constructible] + public GlassMug() => Weight = 1.0; + + [Constructible] + public GlassMug(BeverageType type) + : base(type) => + Weight = 1.0; + + public GlassMug(Serial serial) + : base(serial) + { + } + + public override int EmptyLabelNumber => 1022456; // mug + public override int BaseLabelNumber => 1042976; // a mug of Ale + public override int MaxQuantity => 5; + + public override int ComputeItemID() + { + if (IsEmpty) + return ItemID >= 0x1F81 && ItemID <= 0x1F84 ? ItemID : 0x1F81; + + return Content switch + { + BeverageType.Ale => ItemID == 0x9EF ? 0x9EF : 0x9EE, + BeverageType.Cider => ItemID >= 0x1F7D && ItemID <= 0x1F80 ? ItemID : 0x1F7D, + BeverageType.Liquor => ItemID >= 0x1F85 && ItemID <= 0x1F88 ? ItemID : 0x1F85, + BeverageType.Milk => ItemID >= 0x1F89 && ItemID <= 0x1F8C ? ItemID : 0x1F89, + BeverageType.Wine => ItemID >= 0x1F8D && ItemID <= 0x1F90 ? ItemID : 0x1F8D, + BeverageType.Water => ItemID >= 0x1F91 && ItemID <= 0x1F94 ? ItemID : 0x1F91, + _ => 0 + }; + } + + 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(); + + switch (version) + { + case 0: + { + if (CheckType("MugAle")) + { + Quantity = MaxQuantity; + Content = BeverageType.Ale; + } + else if (CheckType("GlassCider")) + { + Quantity = MaxQuantity; + Content = BeverageType.Cider; + } + else if (CheckType("GlassLiquor")) + { + Quantity = MaxQuantity; + Content = BeverageType.Liquor; + } + else if (CheckType("GlassMilk")) + { + Quantity = MaxQuantity; + Content = BeverageType.Milk; + } + else if (CheckType("GlassWine")) + { + Quantity = MaxQuantity; + Content = BeverageType.Wine; + } + else if (CheckType("GlassWater")) + { + Quantity = MaxQuantity; + Content = BeverageType.Water; + } + else + { + throw new Exception(World.LoadingType); + } + + break; + } + } + } + } + + [TypeAlias( + "Server.Items.PitcherAle", + "Server.Items.PitcherCider", + "Server.Items.PitcherLiquor", + "Server.Items.PitcherMilk", + "Server.Items.PitcherWine", + "Server.Items.PitcherWater", + "Server.Items.GlassPitcher" + )] + public class Pitcher : BaseBeverage + { + [Constructible] + public Pitcher() => Weight = 2.0; + + [Constructible] + public Pitcher(BeverageType type) + : base(type) => + Weight = 2.0; + + public Pitcher(Serial serial) + : base(serial) + { + } + + public override int BaseLabelNumber => 1048128; // a Pitcher of Ale + public override int MaxQuantity => 5; + + public override int ComputeItemID() + { + if (IsEmpty) + { + if (ItemID == 0x9A7 || ItemID == 0xFF7) + return ItemID; + + return 0xFF6; + } + + switch (Content) + { + case BeverageType.Ale: + { + if (ItemID == 0x1F96) + return ItemID; + + return 0x1F95; + } + case BeverageType.Cider: + { + if (ItemID == 0x1F98) + return ItemID; + + return 0x1F97; + } + case BeverageType.Liquor: + { + if (ItemID == 0x1F9A) + return ItemID; + + return 0x1F99; + } + case BeverageType.Milk: + { + if (ItemID == 0x9AD) + return ItemID; + + return 0x9F0; + } + case BeverageType.Wine: + { + if (ItemID == 0x1F9C) + return ItemID; + + return 0x1F9B; + } + case BeverageType.Water: + { + if (ItemID == 0xFF8 || ItemID == 0xFF9 || ItemID == 0x1F9E) + return ItemID; + + return 0x1F9D; + } + } + + return 0; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + } + + public override void Deserialize(IGenericReader reader) + { + if (CheckType("PitcherWater") || CheckType("GlassPitcher")) + InternalDeserialize(reader, false); + else + InternalDeserialize(reader, true); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + if (CheckType("PitcherAle")) + { + Quantity = MaxQuantity; + Content = BeverageType.Ale; + } + else if (CheckType("PitcherCider")) + { + Quantity = MaxQuantity; + Content = BeverageType.Cider; + } + else if (CheckType("PitcherLiquor")) + { + Quantity = MaxQuantity; + Content = BeverageType.Liquor; + } + else if (CheckType("PitcherMilk")) + { + Quantity = MaxQuantity; + Content = BeverageType.Milk; + } + else if (CheckType("PitcherWine")) + { + Quantity = MaxQuantity; + Content = BeverageType.Wine; + } + else if (CheckType("PitcherWater")) + { + Quantity = MaxQuantity; + Content = BeverageType.Water; + } + else if (CheckType("GlassPitcher")) + { + Quantity = 0; + Content = BeverageType.Water; + } + else + { + throw new Exception(World.LoadingType); + } + + break; + } + } + } + } + + public abstract class BaseBeverage : Item, IHasQuantity + { + private static readonly int[] m_SwampTiles = + { + 0x9C4, 0x9EB, + 0x3D65, 0x3D65, + 0x3DC0, 0x3DD9, + 0x3DDB, 0x3DDC, + 0x3DDE, 0x3EF0, + 0x3FF6, 0x3FF6, + 0x3FFC, 0x3FFE + }; + + private static readonly Dictionary m_Table = new Dictionary(); + + private BeverageType m_Content; + private int m_Quantity; + + public BaseBeverage() => ItemID = ComputeItemID(); + + public BaseBeverage(BeverageType type) + { + m_Content = type; + m_Quantity = MaxQuantity; + ItemID = ComputeItemID(); + } + + public BaseBeverage(Serial serial) + : base(serial) + { + } + + public override int LabelNumber + { + get + { + var num = BaseLabelNumber; + + if (IsEmpty || num == 0) + return EmptyLabelNumber; + + return BaseLabelNumber + (int)m_Content; + } + } + + public virtual bool ShowQuantity => MaxQuantity > 1; + public virtual bool Fillable => true; + public virtual bool Pourable => true; + + public virtual int EmptyLabelNumber => base.LabelNumber; + public virtual int BaseLabelNumber => 0; + + public abstract int MaxQuantity { get; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsEmpty => m_Quantity <= 0; + + [CommandProperty(AccessLevel.GameMaster)] + public bool ContainsAlchohol => !IsEmpty && m_Content != BeverageType.Milk && m_Content != BeverageType.Water; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsFull => m_Quantity >= MaxQuantity; + + [CommandProperty(AccessLevel.GameMaster)] + public Poison Poison { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Poisoner { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public BeverageType Content + { + get => m_Content; + set + { + m_Content = value; + + InvalidateProperties(); + + var itemID = ComputeItemID(); + + if (itemID > 0) + ItemID = itemID; + else + Delete(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Quantity + { + get => m_Quantity; + set + { + m_Quantity = Math.Clamp(value, 0, MaxQuantity); + + InvalidateProperties(); + + var itemID = ComputeItemID(); + + if (itemID > 0) + ItemID = itemID; + else + Delete(); + } + } + + public abstract int ComputeItemID(); + + public virtual int GetQuantityDescription() + { + var perc = m_Quantity * 100 / MaxQuantity; + + if (perc <= 0) + return 1042975; // It's empty. + if (perc <= 33) + return 1042974; // It's nearly empty. + if (perc <= 66) + return 1042973; // It's half full. + return 1042972; // It's full. + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (ShowQuantity) + list.Add(GetQuantityDescription()); + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + if (ShowQuantity) + LabelTo(from, GetQuantityDescription()); + } + + public virtual bool ValidateUse(Mobile from, bool message) + { + if (Deleted) + return false; + + if (!Movable && !Fillable) + { + var house = BaseHouse.FindHouseAt(this); + + if (house?.HasLockedDownItem(this) != true) + { + if (message) + from.SendLocalizedMessage(502946, "", 0x59); // That belongs to someone else. + + return false; + } + } + + if (from.Map != Map || !from.InRange(GetWorldLocation(), 2) || !from.InLOS(this)) + { + if (message) + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + + return false; + } + + return true; + } + + public virtual void Fill_OnTarget(Mobile from, object targ) + { + if (!IsEmpty || !Fillable || !ValidateUse(from, false)) + return; + + if (targ is BaseBeverage bev) + { + if (bev.IsEmpty || !bev.ValidateUse(from, true)) + return; + + Content = bev.Content; + Poison = bev.Poison; + Poisoner = bev.Poisoner; + + if (bev.Quantity > MaxQuantity) + { + Quantity = MaxQuantity; + bev.Quantity -= MaxQuantity; + } + else + { + Quantity += bev.Quantity; + bev.Quantity = 0; + } + } + else if (targ is BaseWaterContainer bwc) + { + if (Quantity == 0 || Content == BeverageType.Water && !IsFull) + { + var iNeed = Math.Min(MaxQuantity - Quantity, bwc.Quantity); + + if (iNeed > 0 && !bwc.IsEmpty && !IsFull) + { + bwc.Quantity -= iNeed; + Quantity += iNeed; + Content = BeverageType.Water; + + from.PlaySound(0x4E); + } + } + } + else if (targ is Item item) + { + var src = item as IWaterSource; + + if (src == null && item is AddonComponent component) + src = component.Addon as IWaterSource; + + if (src == null || src.Quantity <= 0) + return; + + if (from.Map != item.Map || !from.InRange(item.GetWorldLocation(), 2) || !from.InLOS(item)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return; + } + + Content = BeverageType.Water; + Poison = null; + Poisoner = null; + + if (src.Quantity > MaxQuantity) + { + Quantity = MaxQuantity; + src.Quantity -= MaxQuantity; + } + else + { + Quantity += src.Quantity; + src.Quantity = 0; + } + + from.SendLocalizedMessage(1010089); // You fill the container with water. + } + else if (targ is Cow cow) + { + if (cow.TryMilk(from)) + { + Content = BeverageType.Milk; + Quantity = MaxQuantity; + from.SendLocalizedMessage(1080197); // You fill the container with milk. + } + } + else if (targ is LandTarget target) + { + var tileID = target.TileID; + + if (from is PlayerMobile player) + { + var qs = player.Quest; + + if (!(qs is WitchApprenticeQuest)) + return; + + var obj = qs.FindObjective(); + + if (obj?.Completed == true && obj.Ingredient == Ingredient.SwampWater) + { + var contains = false; + + for (var i = 0; !contains && i < m_SwampTiles.Length; i += 2) + contains = tileID >= m_SwampTiles[i] && tileID <= m_SwampTiles[i + 1]; + + if (contains) + { + Delete(); + + player.SendLocalizedMessage( + 1055035 + ); // You dip the container into the disgusting swamp water, collecting enough for the Hag's vile stew. + obj.Complete(); + } + } + } + } + } + + public virtual void Pour_OnTarget(Mobile from, object targ) + { + if (IsEmpty || !Pourable || !ValidateUse(from, false)) + return; + + if (targ is BaseBeverage bev) + { + if (!bev.ValidateUse(from, true)) + return; + + if (bev.IsFull && bev.Content == Content) + { + from.SendLocalizedMessage(500848); // Couldn't pour it there. It was already full. + } + else if (!bev.IsEmpty) + { + from.SendLocalizedMessage(500846); // Can't pour it there. + } + else + { + bev.Content = Content; + bev.Poison = Poison; + bev.Poisoner = Poisoner; + + if (Quantity > bev.MaxQuantity) + { + bev.Quantity = bev.MaxQuantity; + Quantity -= bev.MaxQuantity; + } + else + { + bev.Quantity += Quantity; + Quantity = 0; + } + + from.PlaySound(0x4E); + } + } + else if (from == targ) + { + if (from.Thirst < 20) + from.Thirst += 1; + + if (ContainsAlchohol) + { + var bac = Content switch + { + BeverageType.Ale => 1, + BeverageType.Wine => 2, + BeverageType.Cider => 3, + BeverageType.Liquor => 4, + _ => 0 + }; + + from.BAC = Math.Min(from.BAC + bac, 60); + + CheckHeaveTimer(from); + } + + from.PlaySound(Utility.RandomList(0x30, 0x2D6)); + + if (Poison != null) + from.ApplyPoison(Poisoner, Poison); + + --Quantity; + } + else if (targ is BaseWaterContainer bwc) + { + if (Content != BeverageType.Water) + { + from.SendLocalizedMessage(500842); // Can't pour that in there. + } + else if (bwc.Items.Count != 0) + { + from.SendLocalizedMessage(500841); // That has something in it. + } + else + { + var itNeeds = Math.Min(bwc.MaxQuantity - bwc.Quantity, Quantity); + + if (itNeeds > 0) + { + bwc.Quantity += itNeeds; + Quantity -= itNeeds; + + from.PlaySound(0x4E); + } + } + } + else if (targ is PlantItem item) + { + item.Pour(from, this); + } + else if (targ is AddonComponent component && + (component.Addon is WaterVatEast || component.Addon is WaterVatSouth) && + Content == BeverageType.Water) + { + if (from is PlayerMobile player) + if (player.Quest is SolenMatriarchQuest qs) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + var vat = component.Addon; + + if (vat.X > 5784 && vat.X < 5814 && vat.Y > 1903 && vat.Y < 1934 && + (qs.RedSolen && vat.Map == Map.Trammel || !qs.RedSolen && vat.Map == Map.Felucca)) + { + if (obj.CurProgress + Quantity > obj.MaxProgress) + { + var delta = obj.MaxProgress - obj.CurProgress; + + Quantity -= delta; + obj.CurProgress = obj.MaxProgress; + } + else + { + obj.CurProgress += Quantity; + Quantity = 0; + } + } + } + } + } + else + { + from.SendLocalizedMessage(500846); // Can't pour it there. + } + } + + public override void OnDoubleClick(Mobile from) + { + if (IsEmpty) + { + if (!Fillable || !ValidateUse(from, true)) + return; + + from.BeginTarget(-1, true, TargetFlags.None, Fill_OnTarget); + SendLocalizedMessageTo(from, 500837); // Fill from what? + } + else if (Pourable && ValidateUse(from, true)) + { + from.BeginTarget(-1, true, TargetFlags.None, Pour_OnTarget); + from.SendLocalizedMessage(1010086); // What do you want to use this on? + } + } + + public static bool ConsumeTotal(Container pack, BeverageType content, int quantity) => + ConsumeTotal(pack, typeof(BaseBeverage), content, quantity); + + public static bool ConsumeTotal(Container pack, Type itemType, BeverageType content, int quantity) + { + var items = pack.FindItemsByType(itemType); + + // First pass, compute total + var total = 0; + + for (var i = 0; i < items.Length; ++i) + if (items[i] is BaseBeverage bev && bev.Content == content && !bev.IsEmpty) + total += bev.Quantity; + + if (total >= quantity) + { + // We've enough, so consume it + + var need = quantity; + + for (var i = 0; i < items.Length; ++i) + { + if (!(items[i] is BaseBeverage bev) || bev.Content != content || bev.IsEmpty) + continue; + + var theirQuantity = bev.Quantity; + + if (theirQuantity < need) + { + bev.Quantity = 0; + need -= theirQuantity; + } + else + { + bev.Quantity -= need; + return true; + } + } + } + + return false; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(Poisoner); + + Poison.Serialize(Poison, writer); + writer.Write((int)m_Content); + writer.Write(m_Quantity); + } + + protected bool CheckType(string name) => World.LoadingType == $"Server.Items.{name}"; + + public override void Deserialize(IGenericReader reader) + { + InternalDeserialize(reader, true); + } + + protected void InternalDeserialize(IGenericReader reader, bool read) + { + base.Deserialize(reader); + + if (!read) + return; + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + Poisoner = reader.ReadMobile(); + goto case 0; + } + case 0: + { + Poison = Poison.Deserialize(reader); + m_Content = (BeverageType)reader.ReadInt(); + m_Quantity = reader.ReadInt(); + break; + } + } + } + + public static void Initialize() + { + EventSink.Login += EventSink_Login; + } + + private static void EventSink_Login(Mobile m) + { + CheckHeaveTimer(m); + } + + public static void CheckHeaveTimer(Mobile from) + { + if (from.BAC > 0 && from.Map != Map.Internal && !from.Deleted) + { + if (m_Table.ContainsKey(from)) + return; + + if (from.BAC > 60) + from.BAC = 60; + + Timer t = new HeaveTimer(from); + t.Start(); + + m_Table[from] = t; + } + else if (m_Table.TryGetValue(from, out var t)) + { + t.Stop(); + m_Table.Remove(from); + + from.SendLocalizedMessage(500850); // You feel sober. + } + } + + private class HeaveTimer : Timer + { + private readonly Mobile m_Drunk; + + public HeaveTimer(Mobile drunk) + : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0)) + { + m_Drunk = drunk; + + Priority = TimerPriority.OneSecond; + } + + protected override void OnTick() + { + if (m_Drunk.Deleted || m_Drunk.Map == Map.Internal) + { + Stop(); + m_Table.Remove(m_Drunk); + } + else if (m_Drunk.Alive) + { + if (m_Drunk.BAC > 60) + m_Drunk.BAC = 60; + + // chance to get sober + if (Utility.Random(100) < 10) + --m_Drunk.BAC; + + // lose some stats + m_Drunk.Stam -= 1; + m_Drunk.Mana -= 1; + + if (Utility.Random(1, 4) == 1) + { + if (!m_Drunk.Mounted) + { + // turn in a random direction + m_Drunk.Direction = (Direction)Utility.Random(8); + + // heave + m_Drunk.Animate(32, 5, 1, true, false, 0); + } + + // *hic* + m_Drunk.PublicOverheadMessage(MessageType.Regular, 0x3B2, 500849); + } + + if (m_Drunk.BAC <= 0) + { + Stop(); + m_Table.Remove(m_Drunk); + + m_Drunk.SendLocalizedMessage(500850); // You feel sober. + } + } + } + } + } +} diff --git a/Projects/UOContent/Items/Food/BeverageEmpty.cs b/Projects/UOContent/Items/Food/BeverageEmpty.cs index f3758abae..fb75dad41 100644 --- a/Projects/UOContent/Items/Food/BeverageEmpty.cs +++ b/Projects/UOContent/Items/Food/BeverageEmpty.cs @@ -1,51 +1,51 @@ -namespace Server.Items -{ - [Flippable(0x1f81, 0x1f82, 0x1f83, 0x1f84)] - public class Glass : Item - { - [Constructible] - public Glass() : base(0x1f81) => Weight = 0.1; - - public Glass(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GlassBottle : Item - { - [Constructible] - public GlassBottle() : base(0xe2b) => Weight = 0.3; - - public GlassBottle(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1f81, 0x1f82, 0x1f83, 0x1f84)] + public class Glass : Item + { + [Constructible] + public Glass() : base(0x1f81) => Weight = 0.1; + + public Glass(Serial serial) : base(serial) + { + } + + 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 class GlassBottle : Item + { + [Constructible] + public GlassBottle() : base(0xe2b) => Weight = 0.3; + + public GlassBottle(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Food/Bowls.cs b/Projects/UOContent/Items/Food/Bowls.cs index 298c31530..c631c5598 100644 --- a/Projects/UOContent/Items/Food/Bowls.cs +++ b/Projects/UOContent/Items/Food/Bowls.cs @@ -1,518 +1,518 @@ -namespace Server.Items -{ - public class EmptyWoodenBowl : Item - { - [Constructible] - public EmptyWoodenBowl() : base(0x15F8) => Weight = 1.0; - - public EmptyWoodenBowl(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class EmptyPewterBowl : Item - { - [Constructible] - public EmptyPewterBowl() : base(0x15FD) => Weight = 1.0; - - public EmptyPewterBowl(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class WoodenBowlOfCarrots : Food - { - [Constructible] - public WoodenBowlOfCarrots() : base(0x15F9, 1) - { - Stackable = false; - Weight = 1.0; - FillFactor = 2; - } - - public WoodenBowlOfCarrots(Serial serial) : base(serial) - { - } - - public override bool Eat(Mobile from) - { - if (!base.Eat(from)) - return false; - - from.AddToBackpack(new EmptyWoodenBowl()); - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class WoodenBowlOfCorn : Food - { - [Constructible] - public WoodenBowlOfCorn() : base(0x15FA, 1) - { - Stackable = false; - Weight = 1.0; - FillFactor = 2; - } - - public WoodenBowlOfCorn(Serial serial) : base(serial) - { - } - - public override bool Eat(Mobile from) - { - if (!base.Eat(from)) - return false; - - from.AddToBackpack(new EmptyWoodenBowl()); - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class WoodenBowlOfLettuce : Food - { - [Constructible] - public WoodenBowlOfLettuce() : base(0x15FB, 1) - { - Stackable = false; - Weight = 1.0; - FillFactor = 2; - } - - public WoodenBowlOfLettuce(Serial serial) : base(serial) - { - } - - public override bool Eat(Mobile from) - { - if (!base.Eat(from)) - return false; - - from.AddToBackpack(new EmptyWoodenBowl()); - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class WoodenBowlOfPeas : Food - { - [Constructible] - public WoodenBowlOfPeas() : base(0x15FC, 1) - { - Stackable = false; - Weight = 1.0; - FillFactor = 2; - } - - public WoodenBowlOfPeas(Serial serial) : base(serial) - { - } - - public override bool Eat(Mobile from) - { - if (!base.Eat(from)) - return false; - - from.AddToBackpack(new EmptyWoodenBowl()); - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PewterBowlOfCarrots : Food - { - [Constructible] - public PewterBowlOfCarrots() : base(0x15FE, 1) - { - Stackable = false; - Weight = 1.0; - FillFactor = 2; - } - - public PewterBowlOfCarrots(Serial serial) : base(serial) - { - } - - public override bool Eat(Mobile from) - { - if (!base.Eat(from)) - return false; - - from.AddToBackpack(new EmptyPewterBowl()); - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PewterBowlOfCorn : Food - { - [Constructible] - public PewterBowlOfCorn() : base(0x15FF, 1) - { - Stackable = false; - Weight = 1.0; - FillFactor = 2; - } - - public PewterBowlOfCorn(Serial serial) : base(serial) - { - } - - public override bool Eat(Mobile from) - { - if (!base.Eat(from)) - return false; - - from.AddToBackpack(new EmptyPewterBowl()); - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PewterBowlOfLettuce : Food - { - [Constructible] - public PewterBowlOfLettuce() : base(0x1600, 1) - { - Stackable = false; - Weight = 1.0; - FillFactor = 2; - } - - public PewterBowlOfLettuce(Serial serial) : base(serial) - { - } - - public override bool Eat(Mobile from) - { - if (!base.Eat(from)) - return false; - - from.AddToBackpack(new EmptyPewterBowl()); - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PewterBowlOfPeas : Food - { - [Constructible] - public PewterBowlOfPeas() : base(0x1601, 1) - { - Stackable = false; - Weight = 1.0; - FillFactor = 2; - } - - public PewterBowlOfPeas(Serial serial) : base(serial) - { - } - - public override bool Eat(Mobile from) - { - if (!base.Eat(from)) - return false; - - from.AddToBackpack(new EmptyPewterBowl()); - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PewterBowlOfPotatos : Food - { - [Constructible] - public PewterBowlOfPotatos() : base(0x1602, 1) - { - Stackable = false; - Weight = 1.0; - FillFactor = 2; - } - - public PewterBowlOfPotatos(Serial serial) : base(serial) - { - } - - public override bool Eat(Mobile from) - { - if (!base.Eat(from)) - return false; - - from.AddToBackpack(new EmptyPewterBowl()); - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [TypeAlias("Server.Items.EmptyLargeWoodenBowl")] - public class EmptyWoodenTub : Item - { - [Constructible] - public EmptyWoodenTub() : base(0x1605) => Weight = 2.0; - - public EmptyWoodenTub(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [TypeAlias("Server.Items.EmptyLargePewterBowl")] - public class EmptyPewterTub : Item - { - [Constructible] - public EmptyPewterTub() : base(0x1603) => Weight = 2.0; - - public EmptyPewterTub(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class WoodenBowlOfStew : Food - { - [Constructible] - public WoodenBowlOfStew() : base(0x1604, 1) - { - Stackable = false; - Weight = 2.0; - FillFactor = 2; - } - - public WoodenBowlOfStew(Serial serial) : base(serial) - { - } - - public override bool Eat(Mobile from) - { - if (!base.Eat(from)) - return false; - - from.AddToBackpack(new EmptyWoodenTub()); - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class WoodenBowlOfTomatoSoup : Food - { - [Constructible] - public WoodenBowlOfTomatoSoup() : base(0x1606, 1) - { - Stackable = false; - Weight = 2.0; - FillFactor = 2; - } - - public WoodenBowlOfTomatoSoup(Serial serial) : base(serial) - { - } - - public override bool Eat(Mobile from) - { - if (!base.Eat(from)) - return false; - - from.AddToBackpack(new EmptyWoodenTub()); - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class EmptyWoodenBowl : Item + { + [Constructible] + public EmptyWoodenBowl() : base(0x15F8) => Weight = 1.0; + + public EmptyWoodenBowl(Serial serial) : base(serial) + { + } + + 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 class EmptyPewterBowl : Item + { + [Constructible] + public EmptyPewterBowl() : base(0x15FD) => Weight = 1.0; + + public EmptyPewterBowl(Serial serial) : base(serial) + { + } + + 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 class WoodenBowlOfCarrots : Food + { + [Constructible] + public WoodenBowlOfCarrots() : base(0x15F9, 1) + { + Stackable = false; + Weight = 1.0; + FillFactor = 2; + } + + public WoodenBowlOfCarrots(Serial serial) : base(serial) + { + } + + public override bool Eat(Mobile from) + { + if (!base.Eat(from)) + return false; + + from.AddToBackpack(new EmptyWoodenBowl()); + return true; + } + + 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 class WoodenBowlOfCorn : Food + { + [Constructible] + public WoodenBowlOfCorn() : base(0x15FA, 1) + { + Stackable = false; + Weight = 1.0; + FillFactor = 2; + } + + public WoodenBowlOfCorn(Serial serial) : base(serial) + { + } + + public override bool Eat(Mobile from) + { + if (!base.Eat(from)) + return false; + + from.AddToBackpack(new EmptyWoodenBowl()); + return true; + } + + 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 class WoodenBowlOfLettuce : Food + { + [Constructible] + public WoodenBowlOfLettuce() : base(0x15FB, 1) + { + Stackable = false; + Weight = 1.0; + FillFactor = 2; + } + + public WoodenBowlOfLettuce(Serial serial) : base(serial) + { + } + + public override bool Eat(Mobile from) + { + if (!base.Eat(from)) + return false; + + from.AddToBackpack(new EmptyWoodenBowl()); + return true; + } + + 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 class WoodenBowlOfPeas : Food + { + [Constructible] + public WoodenBowlOfPeas() : base(0x15FC, 1) + { + Stackable = false; + Weight = 1.0; + FillFactor = 2; + } + + public WoodenBowlOfPeas(Serial serial) : base(serial) + { + } + + public override bool Eat(Mobile from) + { + if (!base.Eat(from)) + return false; + + from.AddToBackpack(new EmptyWoodenBowl()); + return true; + } + + 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 class PewterBowlOfCarrots : Food + { + [Constructible] + public PewterBowlOfCarrots() : base(0x15FE, 1) + { + Stackable = false; + Weight = 1.0; + FillFactor = 2; + } + + public PewterBowlOfCarrots(Serial serial) : base(serial) + { + } + + public override bool Eat(Mobile from) + { + if (!base.Eat(from)) + return false; + + from.AddToBackpack(new EmptyPewterBowl()); + return true; + } + + 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 class PewterBowlOfCorn : Food + { + [Constructible] + public PewterBowlOfCorn() : base(0x15FF, 1) + { + Stackable = false; + Weight = 1.0; + FillFactor = 2; + } + + public PewterBowlOfCorn(Serial serial) : base(serial) + { + } + + public override bool Eat(Mobile from) + { + if (!base.Eat(from)) + return false; + + from.AddToBackpack(new EmptyPewterBowl()); + return true; + } + + 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 class PewterBowlOfLettuce : Food + { + [Constructible] + public PewterBowlOfLettuce() : base(0x1600, 1) + { + Stackable = false; + Weight = 1.0; + FillFactor = 2; + } + + public PewterBowlOfLettuce(Serial serial) : base(serial) + { + } + + public override bool Eat(Mobile from) + { + if (!base.Eat(from)) + return false; + + from.AddToBackpack(new EmptyPewterBowl()); + return true; + } + + 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 class PewterBowlOfPeas : Food + { + [Constructible] + public PewterBowlOfPeas() : base(0x1601, 1) + { + Stackable = false; + Weight = 1.0; + FillFactor = 2; + } + + public PewterBowlOfPeas(Serial serial) : base(serial) + { + } + + public override bool Eat(Mobile from) + { + if (!base.Eat(from)) + return false; + + from.AddToBackpack(new EmptyPewterBowl()); + return true; + } + + 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 class PewterBowlOfPotatos : Food + { + [Constructible] + public PewterBowlOfPotatos() : base(0x1602, 1) + { + Stackable = false; + Weight = 1.0; + FillFactor = 2; + } + + public PewterBowlOfPotatos(Serial serial) : base(serial) + { + } + + public override bool Eat(Mobile from) + { + if (!base.Eat(from)) + return false; + + from.AddToBackpack(new EmptyPewterBowl()); + return true; + } + + 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(); + } + } + + [TypeAlias("Server.Items.EmptyLargeWoodenBowl")] + public class EmptyWoodenTub : Item + { + [Constructible] + public EmptyWoodenTub() : base(0x1605) => Weight = 2.0; + + public EmptyWoodenTub(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [TypeAlias("Server.Items.EmptyLargePewterBowl")] + public class EmptyPewterTub : Item + { + [Constructible] + public EmptyPewterTub() : base(0x1603) => Weight = 2.0; + + public EmptyPewterTub(Serial serial) : base(serial) + { + } + + 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 class WoodenBowlOfStew : Food + { + [Constructible] + public WoodenBowlOfStew() : base(0x1604, 1) + { + Stackable = false; + Weight = 2.0; + FillFactor = 2; + } + + public WoodenBowlOfStew(Serial serial) : base(serial) + { + } + + public override bool Eat(Mobile from) + { + if (!base.Eat(from)) + return false; + + from.AddToBackpack(new EmptyWoodenTub()); + return true; + } + + 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 class WoodenBowlOfTomatoSoup : Food + { + [Constructible] + public WoodenBowlOfTomatoSoup() : base(0x1606, 1) + { + Stackable = false; + Weight = 2.0; + FillFactor = 2; + } + + public WoodenBowlOfTomatoSoup(Serial serial) : base(serial) + { + } + + public override bool Eat(Mobile from) + { + if (!base.Eat(from)) + return false; + + from.AddToBackpack(new EmptyWoodenTub()); + return true; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Food/Chocolatiering.cs b/Projects/UOContent/Items/Food/Chocolatiering.cs index 3e9dac66d..90dd2b640 100644 --- a/Projects/UOContent/Items/Food/Chocolatiering.cs +++ b/Projects/UOContent/Items/Food/Chocolatiering.cs @@ -1,263 +1,263 @@ -namespace Server.Items -{ - public class CocoaLiquor : Item - { - [Constructible] - public CocoaLiquor() - : base(0x103F) => - Hue = 0x46A; - - public CocoaLiquor(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1080007; // Cocoa liquor - public override double DefaultWeight => 1.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SackOfSugar : Item - { - [Constructible] - public SackOfSugar(int amount = 1) - : base(0x1039) - { - Hue = 0x461; - Stackable = true; - Amount = amount; - } - - public SackOfSugar(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1080003; // Sack of sugar - public override double DefaultWeight => 1.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class CocoaButter : Item - { - [Constructible] - public CocoaButter() - : base(0x1044) => - Hue = 0x457; - - public CocoaButter(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1080005; // Cocoa butter - public override double DefaultWeight => 1.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Vanilla : Item - { - [Constructible] - public Vanilla(int amount = 1) - : base(0xE2A) - { - Hue = 0x462; - Stackable = true; - Amount = amount; - } - - public Vanilla(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1080009; // Vanilla - public override double DefaultWeight => 1.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class CocoaPulp : Item - { - [Constructible] - public CocoaPulp(int amount = 1) - : base(0xF7C) - { - Hue = 0x219; - Stackable = true; - Amount = amount; - } - - public CocoaPulp(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1080530; // cocoa pulp - public override double DefaultWeight => 1.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DarkChocolate : CandyCane - { - [Constructible] - public DarkChocolate() - : base(0xF10) - { - Hue = 0x465; - LootType = LootType.Regular; - } - - public DarkChocolate(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1079994; // Dark chocolate - public override double DefaultWeight => 1.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class MilkChocolate : CandyCane - { - [Constructible] - public MilkChocolate() - : base(0xF18) - { - Hue = 0x461; - LootType = LootType.Regular; - } - - public MilkChocolate(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1079995; // Milk chocolate - public override double DefaultWeight => 1.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class WhiteChocolate : CandyCane - { - [Constructible] - public WhiteChocolate() - : base(0xF11) - { - Hue = 0x47E; - LootType = LootType.Regular; - } - - public WhiteChocolate(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1079996; // White chocolate - public override double DefaultWeight => 1.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class CocoaLiquor : Item + { + [Constructible] + public CocoaLiquor() + : base(0x103F) => + Hue = 0x46A; + + public CocoaLiquor(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1080007; // Cocoa liquor + public override double DefaultWeight => 1.0; + + 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 class SackOfSugar : Item + { + [Constructible] + public SackOfSugar(int amount = 1) + : base(0x1039) + { + Hue = 0x461; + Stackable = true; + Amount = amount; + } + + public SackOfSugar(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1080003; // Sack of sugar + public override double DefaultWeight => 1.0; + + 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 class CocoaButter : Item + { + [Constructible] + public CocoaButter() + : base(0x1044) => + Hue = 0x457; + + public CocoaButter(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1080005; // Cocoa butter + public override double DefaultWeight => 1.0; + + 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 class Vanilla : Item + { + [Constructible] + public Vanilla(int amount = 1) + : base(0xE2A) + { + Hue = 0x462; + Stackable = true; + Amount = amount; + } + + public Vanilla(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1080009; // Vanilla + public override double DefaultWeight => 1.0; + + 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 class CocoaPulp : Item + { + [Constructible] + public CocoaPulp(int amount = 1) + : base(0xF7C) + { + Hue = 0x219; + Stackable = true; + Amount = amount; + } + + public CocoaPulp(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1080530; // cocoa pulp + public override double DefaultWeight => 1.0; + + 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 class DarkChocolate : CandyCane + { + [Constructible] + public DarkChocolate() + : base(0xF10) + { + Hue = 0x465; + LootType = LootType.Regular; + } + + public DarkChocolate(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1079994; // Dark chocolate + public override double DefaultWeight => 1.0; + + 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(); + } + } + + public class MilkChocolate : CandyCane + { + [Constructible] + public MilkChocolate() + : base(0xF18) + { + Hue = 0x461; + LootType = LootType.Regular; + } + + public MilkChocolate(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1079995; // Milk chocolate + public override double DefaultWeight => 1.0; + + 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(); + } + } + + public class WhiteChocolate : CandyCane + { + [Constructible] + public WhiteChocolate() + : base(0xF11) + { + Hue = 0x47E; + LootType = LootType.Regular; + } + + public WhiteChocolate(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1079996; // White chocolate + public override double DefaultWeight => 1.0; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Food/CookableFood.cs b/Projects/UOContent/Items/Food/CookableFood.cs index de6fe142a..bb220f2a5 100644 --- a/Projects/UOContent/Items/Food/CookableFood.cs +++ b/Projects/UOContent/Items/Food/CookableFood.cs @@ -1,705 +1,706 @@ -using System; -using Server.Targeting; - -namespace Server.Items -{ - public abstract class CookableFood : Item - { - [CommandProperty(AccessLevel.GameMaster)] - public int CookingLevel { get; set; } - - public CookableFood(int itemID, int cookingLevel) : base(itemID) => CookingLevel = cookingLevel; - - public CookableFood(Serial serial) : base(serial) - { - } - - public abstract Food Cook(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - // Version 1 - writer.Write(CookingLevel); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - CookingLevel = reader.ReadInt(); - - break; - } - } - } - - public static bool IsHeatSource(object targeted) - { - int itemID; - - if (targeted is Item item) - itemID = item.ItemID; - else if (targeted is StaticTarget target) - itemID = target.ItemID; - else - return false; - - if (itemID >= 0xDE3 && itemID <= 0xDE9) - return true; // Campfire - if (itemID >= 0x461 && itemID <= 0x48E) - return true; // Sandstone oven/fireplace - if (itemID >= 0x92B && itemID <= 0x96C) - return true; // Stone oven/fireplace - if (itemID == 0xFAC) - return true; // Firepit - if (itemID >= 0x184A && itemID <= 0x184C) - return true; // Heating stand (left) - if (itemID >= 0x184E && itemID <= 0x1850) - return true; // Heating stand (right) - if (itemID >= 0x398C && itemID <= 0x399F) - return true; // Fire field - - return false; - } - - private class InternalTarget : Target - { - private readonly CookableFood m_Item; - - public InternalTarget(CookableFood item) : base(1, false, TargetFlags.None) => m_Item = item; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Item.Deleted) return; - - if (IsHeatSource(targeted)) - { - if (from.BeginAction()) - { - from.PlaySound(0x225); - - m_Item.Consume(); - - InternalTimer t = new InternalTimer(from, targeted as IPoint3D, from.Map, m_Item); - t.Start(); - } - else - { - from.SendLocalizedMessage(500119); // You must wait to perform another action - } - } - } - - private class InternalTimer : Timer - { - private readonly CookableFood m_CookableFood; - private readonly Mobile m_From; - private readonly Map m_Map; - private readonly IPoint3D m_Point; - - public InternalTimer(Mobile from, IPoint3D p, Map map, CookableFood cookableFood) : base( - TimeSpan.FromSeconds(5.0)) - { - m_From = from; - m_Point = p; - m_Map = map; - m_CookableFood = cookableFood; - } - - protected override void OnTick() - { - m_From.EndAction(); - - if (m_From.Map != m_Map || (m_Point != null && m_From.GetDistanceToSqrt(m_Point) > 3)) - { - m_From.SendLocalizedMessage(500686); // You burn the food to a crisp! It's ruined. - return; - } - - if (m_From.CheckSkill(SkillName.Cooking, m_CookableFood.CookingLevel, 100)) - { - Food cookedFood = m_CookableFood.Cook(); - - if (m_From.AddToBackpack(cookedFood)) - m_From.PlaySound(0x57); - } - else - { - m_From.SendLocalizedMessage(500686); // You burn the food to a crisp! It's ruined. - } - } - } - } - } - - // ********** RawRibs ********** - public class RawRibs : CookableFood - { - [Constructible] - public RawRibs(int amount = 1) : base(0x9F1, 10) - { - Weight = 1.0; - Stackable = true; - Amount = amount; - } - - public RawRibs(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override Food Cook() => new Ribs(); - } - - // ********** RawLambLeg ********** - public class RawLambLeg : CookableFood - { - [Constructible] - public RawLambLeg(int amount = 1) : base(0x1609, 10) - { - Stackable = true; - Amount = amount; - } - - public RawLambLeg(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); - - int version = reader.ReadInt(); - - if (version == 0 && Weight == 1) - Weight = -1; - } - - public override Food Cook() => new LambLeg(); - } - - // ********** RawChickenLeg ********** - public class RawChickenLeg : CookableFood - { - [Constructible] - public RawChickenLeg() : base(0x1607, 10) - { - Weight = 1.0; - Stackable = true; - } - - public RawChickenLeg(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override Food Cook() => new ChickenLeg(); - } - - // ********** RawBird ********** - public class RawBird : CookableFood - { - [Constructible] - public RawBird(int amount = 1) : base(0x9B9, 10) - { - Weight = 1.0; - Stackable = true; - Amount = amount; - } - - public RawBird(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override Food Cook() => new CookedBird(); - } - - // ********** UnbakedPeachCobbler ********** - public class UnbakedPeachCobbler : CookableFood - { - [Constructible] - public UnbakedPeachCobbler() : base(0x1042, 25) => Weight = 1.0; - - public UnbakedPeachCobbler(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041335; // unbaked peach cobbler - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override Food Cook() => new PeachCobbler(); - } - - // ********** UnbakedFruitPie ********** - public class UnbakedFruitPie : CookableFood - { - [Constructible] - public UnbakedFruitPie() : base(0x1042, 25) => Weight = 1.0; - - public UnbakedFruitPie(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041334; // unbaked fruit pie - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override Food Cook() => new FruitPie(); - } - - // ********** UnbakedMeatPie ********** - public class UnbakedMeatPie : CookableFood - { - [Constructible] - public UnbakedMeatPie() : base(0x1042, 25) => Weight = 1.0; - - public UnbakedMeatPie(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041338; // unbaked meat pie - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override Food Cook() => new MeatPie(); - } - - // ********** UnbakedPumpkinPie ********** - public class UnbakedPumpkinPie : CookableFood - { - [Constructible] - public UnbakedPumpkinPie() : base(0x1042, 25) => Weight = 1.0; - - public UnbakedPumpkinPie(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041342; // unbaked pumpkin pie - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override Food Cook() => new PumpkinPie(); - } - - // ********** UnbakedApplePie ********** - public class UnbakedApplePie : CookableFood - { - [Constructible] - public UnbakedApplePie() : base(0x1042, 25) => Weight = 1.0; - - public UnbakedApplePie(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041336; // unbaked apple pie - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override Food Cook() => new ApplePie(); - } - - // ********** UncookedCheesePizza ********** - [TypeAlias("Server.Items.UncookedPizza")] - public class UncookedCheesePizza : CookableFood - { - [Constructible] - public UncookedCheesePizza() : base(0x1083, 20) => Weight = 1.0; - - public UncookedCheesePizza(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041341; // uncooked cheese pizza - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (ItemID == 0x1040) - ItemID = 0x1083; - - if (Hue == 51) - Hue = 0; - } - - public override Food Cook() => new CheesePizza(); - } - - // ********** UncookedSausagePizza ********** - public class UncookedSausagePizza : CookableFood - { - [Constructible] - public UncookedSausagePizza() : base(0x1083, 20) => Weight = 1.0; - - public UncookedSausagePizza(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041337; // uncooked sausage pizza - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override Food Cook() => new SausagePizza(); - } - - // ********** UnbakedQuiche ********** - public class UnbakedQuiche : CookableFood - { - [Constructible] - public UnbakedQuiche() : base(0x1042, 25) => Weight = 1.0; - - public UnbakedQuiche(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041339; // unbaked quiche - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override Food Cook() => new Quiche(); - } - - // ********** Eggs ********** - public class Eggs : CookableFood - { - [Constructible] - public Eggs(int amount = 1) : base(0x9B5, 15) - { - Weight = 1.0; - Stackable = true; - Amount = amount; - } - - public Eggs(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); - - int version = reader.ReadInt(); - - if (version < 1) - { - Stackable = true; - - if (Weight == 0.5) - Weight = 1.0; - } - } - - public override Food Cook() => new FriedEggs(); - } - - // ********** BrightlyColoredEggs ********** - public class BrightlyColoredEggs : CookableFood - { - [Constructible] - public BrightlyColoredEggs() : base(0x9B5, 15) - { - Weight = 0.5; - Hue = 3 + Utility.Random(20) * 5; - } - - public BrightlyColoredEggs(Serial serial) : base(serial) - { - } - - public override string DefaultName => "brightly colored eggs"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override Food Cook() => new FriedEggs(); - } - - // ********** EasterEggs ********** - public class EasterEggs : CookableFood - { - [Constructible] - public EasterEggs() : base(0x9B5, 15) - { - Weight = 0.5; - Hue = 3 + Utility.Random(20) * 5; - } - - public EasterEggs(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1016105; // Easter Eggs - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override Food Cook() => new FriedEggs(); - } - - // ********** CookieMix ********** - public class CookieMix : CookableFood - { - [Constructible] - public CookieMix() : base(0x103F, 20) => Weight = 1.0; - - public CookieMix(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override Food Cook() => new Cookies(); - } - - // ********** CakeMix ********** - public class CakeMix : CookableFood - { - [Constructible] - public CakeMix() : base(0x103F, 40) => Weight = 1.0; - - public CakeMix(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041002; // cake mix - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override Food Cook() => new Cake(); - } - - public class RawFishSteak : CookableFood - { - [Constructible] - public RawFishSteak(int amount = 1) : base(0x097A, 10) - { - Stackable = true; - Amount = amount; - } - - public RawFishSteak(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.1; - - public override Food Cook() => new FishSteak(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using Server.Targeting; + +namespace Server.Items +{ + public abstract class CookableFood : Item + { + public CookableFood(int itemID, int cookingLevel) : base(itemID) => CookingLevel = cookingLevel; + + public CookableFood(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int CookingLevel { get; set; } + + public abstract Food Cook(); + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + // Version 1 + writer.Write(CookingLevel); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + CookingLevel = reader.ReadInt(); + + break; + } + } + } + + public static bool IsHeatSource(object targeted) + { + int itemID; + + if (targeted is Item item) + itemID = item.ItemID; + else if (targeted is StaticTarget target) + itemID = target.ItemID; + else + return false; + + if (itemID >= 0xDE3 && itemID <= 0xDE9) + return true; // Campfire + if (itemID >= 0x461 && itemID <= 0x48E) + return true; // Sandstone oven/fireplace + if (itemID >= 0x92B && itemID <= 0x96C) + return true; // Stone oven/fireplace + if (itemID == 0xFAC) + return true; // Firepit + if (itemID >= 0x184A && itemID <= 0x184C) + return true; // Heating stand (left) + if (itemID >= 0x184E && itemID <= 0x1850) + return true; // Heating stand (right) + if (itemID >= 0x398C && itemID <= 0x399F) + return true; // Fire field + + return false; + } + + private class InternalTarget : Target + { + private readonly CookableFood m_Item; + + public InternalTarget(CookableFood item) : base(1, false, TargetFlags.None) => m_Item = item; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Item.Deleted) return; + + if (IsHeatSource(targeted)) + { + if (from.BeginAction()) + { + from.PlaySound(0x225); + + m_Item.Consume(); + + var t = new InternalTimer(from, targeted as IPoint3D, from.Map, m_Item); + t.Start(); + } + else + { + from.SendLocalizedMessage(500119); // You must wait to perform another action + } + } + } + + private class InternalTimer : Timer + { + private readonly CookableFood m_CookableFood; + private readonly Mobile m_From; + private readonly Map m_Map; + private readonly IPoint3D m_Point; + + public InternalTimer(Mobile from, IPoint3D p, Map map, CookableFood cookableFood) : base( + TimeSpan.FromSeconds(5.0) + ) + { + m_From = from; + m_Point = p; + m_Map = map; + m_CookableFood = cookableFood; + } + + protected override void OnTick() + { + m_From.EndAction(); + + if (m_From.Map != m_Map || m_Point != null && m_From.GetDistanceToSqrt(m_Point) > 3) + { + m_From.SendLocalizedMessage(500686); // You burn the food to a crisp! It's ruined. + return; + } + + if (m_From.CheckSkill(SkillName.Cooking, m_CookableFood.CookingLevel, 100)) + { + var cookedFood = m_CookableFood.Cook(); + + if (m_From.AddToBackpack(cookedFood)) + m_From.PlaySound(0x57); + } + else + { + m_From.SendLocalizedMessage(500686); // You burn the food to a crisp! It's ruined. + } + } + } + } + } + + // ********** RawRibs ********** + public class RawRibs : CookableFood + { + [Constructible] + public RawRibs(int amount = 1) : base(0x9F1, 10) + { + Weight = 1.0; + Stackable = true; + Amount = amount; + } + + public RawRibs(Serial serial) : base(serial) + { + } + + 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 Food Cook() => new Ribs(); + } + + // ********** RawLambLeg ********** + public class RawLambLeg : CookableFood + { + [Constructible] + public RawLambLeg(int amount = 1) : base(0x1609, 10) + { + Stackable = true; + Amount = amount; + } + + public RawLambLeg(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 == 1) + Weight = -1; + } + + public override Food Cook() => new LambLeg(); + } + + // ********** RawChickenLeg ********** + public class RawChickenLeg : CookableFood + { + [Constructible] + public RawChickenLeg() : base(0x1607, 10) + { + Weight = 1.0; + Stackable = true; + } + + public RawChickenLeg(Serial serial) : base(serial) + { + } + + 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 Food Cook() => new ChickenLeg(); + } + + // ********** RawBird ********** + public class RawBird : CookableFood + { + [Constructible] + public RawBird(int amount = 1) : base(0x9B9, 10) + { + Weight = 1.0; + Stackable = true; + Amount = amount; + } + + public RawBird(Serial serial) : base(serial) + { + } + + 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 Food Cook() => new CookedBird(); + } + + // ********** UnbakedPeachCobbler ********** + public class UnbakedPeachCobbler : CookableFood + { + [Constructible] + public UnbakedPeachCobbler() : base(0x1042, 25) => Weight = 1.0; + + public UnbakedPeachCobbler(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041335; // unbaked peach cobbler + + 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 Food Cook() => new PeachCobbler(); + } + + // ********** UnbakedFruitPie ********** + public class UnbakedFruitPie : CookableFood + { + [Constructible] + public UnbakedFruitPie() : base(0x1042, 25) => Weight = 1.0; + + public UnbakedFruitPie(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041334; // unbaked fruit pie + + 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 Food Cook() => new FruitPie(); + } + + // ********** UnbakedMeatPie ********** + public class UnbakedMeatPie : CookableFood + { + [Constructible] + public UnbakedMeatPie() : base(0x1042, 25) => Weight = 1.0; + + public UnbakedMeatPie(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041338; // unbaked meat pie + + 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 Food Cook() => new MeatPie(); + } + + // ********** UnbakedPumpkinPie ********** + public class UnbakedPumpkinPie : CookableFood + { + [Constructible] + public UnbakedPumpkinPie() : base(0x1042, 25) => Weight = 1.0; + + public UnbakedPumpkinPie(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041342; // unbaked pumpkin pie + + 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 Food Cook() => new PumpkinPie(); + } + + // ********** UnbakedApplePie ********** + public class UnbakedApplePie : CookableFood + { + [Constructible] + public UnbakedApplePie() : base(0x1042, 25) => Weight = 1.0; + + public UnbakedApplePie(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041336; // unbaked apple pie + + 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 Food Cook() => new ApplePie(); + } + + // ********** UncookedCheesePizza ********** + [TypeAlias("Server.Items.UncookedPizza")] + public class UncookedCheesePizza : CookableFood + { + [Constructible] + public UncookedCheesePizza() : base(0x1083, 20) => Weight = 1.0; + + public UncookedCheesePizza(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041341; // uncooked cheese pizza + + 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 (ItemID == 0x1040) + ItemID = 0x1083; + + if (Hue == 51) + Hue = 0; + } + + public override Food Cook() => new CheesePizza(); + } + + // ********** UncookedSausagePizza ********** + public class UncookedSausagePizza : CookableFood + { + [Constructible] + public UncookedSausagePizza() : base(0x1083, 20) => Weight = 1.0; + + public UncookedSausagePizza(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041337; // uncooked sausage pizza + + 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 Food Cook() => new SausagePizza(); + } + + // ********** UnbakedQuiche ********** + public class UnbakedQuiche : CookableFood + { + [Constructible] + public UnbakedQuiche() : base(0x1042, 25) => Weight = 1.0; + + public UnbakedQuiche(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041339; // unbaked quiche + + 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 Food Cook() => new Quiche(); + } + + // ********** Eggs ********** + public class Eggs : CookableFood + { + [Constructible] + public Eggs(int amount = 1) : base(0x9B5, 15) + { + Weight = 1.0; + Stackable = true; + Amount = amount; + } + + public Eggs(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 < 1) + { + Stackable = true; + + if (Weight == 0.5) + Weight = 1.0; + } + } + + public override Food Cook() => new FriedEggs(); + } + + // ********** BrightlyColoredEggs ********** + public class BrightlyColoredEggs : CookableFood + { + [Constructible] + public BrightlyColoredEggs() : base(0x9B5, 15) + { + Weight = 0.5; + Hue = 3 + Utility.Random(20) * 5; + } + + public BrightlyColoredEggs(Serial serial) : base(serial) + { + } + + public override string DefaultName => "brightly colored eggs"; + + 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 Food Cook() => new FriedEggs(); + } + + // ********** EasterEggs ********** + public class EasterEggs : CookableFood + { + [Constructible] + public EasterEggs() : base(0x9B5, 15) + { + Weight = 0.5; + Hue = 3 + Utility.Random(20) * 5; + } + + public EasterEggs(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1016105; // Easter Eggs + + 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 Food Cook() => new FriedEggs(); + } + + // ********** CookieMix ********** + public class CookieMix : CookableFood + { + [Constructible] + public CookieMix() : base(0x103F, 20) => Weight = 1.0; + + public CookieMix(Serial serial) : base(serial) + { + } + + 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 Food Cook() => new Cookies(); + } + + // ********** CakeMix ********** + public class CakeMix : CookableFood + { + [Constructible] + public CakeMix() : base(0x103F, 40) => Weight = 1.0; + + public CakeMix(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041002; // cake mix + + 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 Food Cook() => new Cake(); + } + + public class RawFishSteak : CookableFood + { + [Constructible] + public RawFishSteak(int amount = 1) : base(0x097A, 10) + { + Stackable = true; + Amount = amount; + } + + public RawFishSteak(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0.1; + + public override Food Cook() => new FishSteak(); + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Food/Cooking.cs b/Projects/UOContent/Items/Food/Cooking.cs index 7e736c11c..f23329665 100644 --- a/Projects/UOContent/Items/Food/Cooking.cs +++ b/Projects/UOContent/Items/Food/Cooking.cs @@ -1,516 +1,518 @@ -using System; -using Server.Targeting; - -namespace Server.Items -{ - public class UtilityItem - { - public static int RandomChoice(int itemID1, int itemID2) - { - var iRet = Utility.Random(2) switch - { - 0 => itemID1, - 1 => itemID2, - _ => itemID1 - }; - - return iRet; - } - } - - // ********** Dough ********** - public class Dough : Item - { - [Constructible] - public Dough() : base(0x103d) - { - Stackable = Core.ML; - Weight = 1.0; - } - - public Dough(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private class InternalTarget : Target - { - private readonly Dough m_Item; - - public InternalTarget(Dough item) : base(1, false, TargetFlags.None) => m_Item = item; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Item.Deleted) return; - - if (!(targeted is Item targetItem) || targetItem.Deleted) - return; - - m_Item.Consume(); - - if (targeted is Eggs) - { - from.AddToBackpack(new UnbakedQuiche()); - from.AddToBackpack(new Eggshells()); - } - else if (targeted is CheeseWheel) - { - from.AddToBackpack(new CheesePizza()); - } - else if (targeted is Sausage) - { - from.AddToBackpack(new SausagePizza()); - } - else if (targeted is Apple) - { - from.AddToBackpack(new UnbakedApplePie()); - } - else if (targeted is Peach) - { - from.AddToBackpack(new UnbakedPeachCobbler()); - } - else - return; - - targetItem.Consume(); - } - } - } - - // ********** SweetDough ********** - public class SweetDough : Item - { - public override int LabelNumber => 1041340; // sweet dough - - [Constructible] - public SweetDough() : base(0x103d) - { - Stackable = Core.ML; - Weight = 1.0; - Hue = 150; - } - - public SweetDough(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Hue == 51) - Hue = 150; - } - - private class InternalTarget : Target - { - private readonly SweetDough m_Item; - - public InternalTarget(SweetDough item) : base(1, false, TargetFlags.None) => m_Item = item; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Item.Deleted) return; - - m_Item.Consume(); - - if (targeted is BowlFlour flour) - { - flour.Delete(); - - from.AddToBackpack(new CakeMix()); - } - else if (targeted is Campfire campfire) - { - from.PlaySound(0x225); - InternalTimer t = new InternalTimer(from, campfire); - t.Start(); - } - } - - private class InternalTimer : Timer - { - private readonly Campfire m_Campfire; - private readonly Mobile m_From; - - public InternalTimer(Mobile from, Campfire campfire) : base(TimeSpan.FromSeconds(5.0)) - { - m_From = from; - m_Campfire = campfire; - } - - protected override void OnTick() - { - if (m_From.GetDistanceToSqrt(m_Campfire) > 3) - { - m_From.SendLocalizedMessage(500686); // You burn the food to a crisp! It's ruined. - return; - } - - if (m_From.CheckSkill(SkillName.Cooking, 0, 10)) - { - if (m_From.AddToBackpack(new Muffins())) - m_From.PlaySound(0x57); - } - else - { - m_From.SendLocalizedMessage(500686); // You burn the food to a crisp! It's ruined. - } - } - } - } - } - - // ********** JarHoney ********** - public class JarHoney : Item - { - [Constructible] - public JarHoney() : base(0x9ec) - { - Weight = 1.0; - Stackable = true; - } - - public JarHoney(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - Stackable = true; - } - - /*public override void OnDoubleClick( Mobile from ) - { - if (!Movable) - return; - - from.Target = new InternalTarget( this ); - }*/ - - private class InternalTarget : Target - { - private readonly JarHoney m_Item; - - public InternalTarget(JarHoney item) : base(1, false, TargetFlags.None) => m_Item = item; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Item.Deleted) return; - - m_Item.Consume(); - - if (targeted is Dough dough) - { - dough.Consume(); - - from.AddToBackpack(new SweetDough()); - } - - if (targeted is BowlFlour flour) - { - flour.Delete(); - - from.AddToBackpack(new CookieMix()); - } - } - } - } - - // ********** BowlFlour ********** - public class BowlFlour : Item - { - [Constructible] - public BowlFlour() : base(0xa1e) => Weight = 1.0; - - public BowlFlour(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - // ********** WoodenBowl ********** - public class WoodenBowl : Item - { - [Constructible] - public WoodenBowl() : base(0x15f8) => Weight = 1.0; - - public WoodenBowl(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - // ********** PitcherWater ********** - /*public class PitcherWater : Item - { - [Constructible] - public PitcherWater() : base(Utility.Random( 0x1f9d, 2 )) - { - Weight = 1.0; - } - - public PitcherWater( Serial serial ) : base( serial ) - { - } - - public override void Serialize( GenericWriter writer ) - { - base.Serialize( writer ); - - writer.Write( (int) 0 ); // version - } - - public override void Deserialize( GenericReader reader ) - { - base.Deserialize( reader ); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick( Mobile from ) - { - if (!Movable) - return; - - from.Target = new InternalTarget( this ); - } - - private class InternalTarget : Target - { - private PitcherWater m_Item; - - public InternalTarget( PitcherWater item ) : base( 1, false, TargetFlags.None ) - { - m_Item = item; - } - - protected override void OnTarget( Mobile from, object targeted ) - { - if (m_Item.Deleted ) return; - - if (targeted is BowlFlour) - { - m_Item.Delete(); - ((BowlFlour)targeted).Delete(); - - from.AddToBackpack( new Dough() ); - from.AddToBackpack( new WoodenBowl() ); - } - } - } - }*/ - - // ********** SackFlour ********** - [TypeAlias("Server.Items.SackFlourOpen")] - public class SackFlour : Item, IHasQuantity - { - private int m_Quantity; - - [Constructible] - public SackFlour() : base(0x1039) - { - Weight = 5.0; - m_Quantity = 20; - } - - public SackFlour(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Quantity - { - get => m_Quantity; - set - { - m_Quantity = Math.Min(20, Math.Max(0, value)); - - if (m_Quantity == 0) - Delete(); - else if (m_Quantity < 20 && (ItemID == 0x1039 || ItemID == 0x1045)) - ++ItemID; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(2); // version - - writer.Write(m_Quantity); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 2: - case 1: - { - m_Quantity = reader.ReadInt(); - break; - } - case 0: - { - m_Quantity = 20; - break; - } - } - - if (version < 2 && Weight == 1.0) - Weight = 5.0; - } - - public override void OnDoubleClick(Mobile from) - { - if (!Movable) - return; - - if (ItemID == 0x1039 || ItemID == 0x1045) - ++ItemID; - } - } - - // ********** Eggshells ********** - public class Eggshells : Item - { - [Constructible] - public Eggshells() : base(0x9b4) => Weight = 0.5; - - public Eggshells(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class WheatSheaf : Item - { - [Constructible] - public WheatSheaf(int amount = 1) : base(7869) - { - Weight = 1.0; - Stackable = true; - Amount = amount; - } - - public WheatSheaf(Serial serial) : base(serial) - { - } - - public override void OnDoubleClick(Mobile from) - { - if (!Movable) - return; - - from.BeginTarget(4, false, TargetFlags.None, OnTarget); - } - - public virtual void OnTarget(Mobile from, object obj) - { - if (obj is AddonComponent addon) - obj = addon.Addon; - - if (obj is IFlourMill mill) - { - int needs = mill.MaxFlour - mill.CurFlour; - - if (needs > Amount) - needs = Amount; - - mill.CurFlour += needs; - Consume(needs); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using Server.Targeting; + +namespace Server.Items +{ + public class UtilityItem + { + public static int RandomChoice(int itemID1, int itemID2) + { + var iRet = Utility.Random(2) switch + { + 0 => itemID1, + 1 => itemID2, + _ => itemID1 + }; + + return iRet; + } + } + + // ********** Dough ********** + public class Dough : Item + { + [Constructible] + public Dough() : base(0x103d) + { + Stackable = Core.ML; + Weight = 1.0; + } + + public Dough(Serial serial) : base(serial) + { + } + + 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(); + } + + private class InternalTarget : Target + { + private readonly Dough m_Item; + + public InternalTarget(Dough item) : base(1, false, TargetFlags.None) => m_Item = item; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Item.Deleted) return; + + if (!(targeted is Item targetItem) || targetItem.Deleted) + return; + + m_Item.Consume(); + + if (targeted is Eggs) + { + from.AddToBackpack(new UnbakedQuiche()); + from.AddToBackpack(new Eggshells()); + } + else if (targeted is CheeseWheel) + { + from.AddToBackpack(new CheesePizza()); + } + else if (targeted is Sausage) + { + from.AddToBackpack(new SausagePizza()); + } + else if (targeted is Apple) + { + from.AddToBackpack(new UnbakedApplePie()); + } + else if (targeted is Peach) + { + from.AddToBackpack(new UnbakedPeachCobbler()); + } + else + { + return; + } + + targetItem.Consume(); + } + } + } + + // ********** SweetDough ********** + public class SweetDough : Item + { + [Constructible] + public SweetDough() : base(0x103d) + { + Stackable = Core.ML; + Weight = 1.0; + Hue = 150; + } + + public SweetDough(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041340; // sweet dough + + 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 (Hue == 51) + Hue = 150; + } + + private class InternalTarget : Target + { + private readonly SweetDough m_Item; + + public InternalTarget(SweetDough item) : base(1, false, TargetFlags.None) => m_Item = item; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Item.Deleted) return; + + m_Item.Consume(); + + if (targeted is BowlFlour flour) + { + flour.Delete(); + + from.AddToBackpack(new CakeMix()); + } + else if (targeted is Campfire campfire) + { + from.PlaySound(0x225); + var t = new InternalTimer(from, campfire); + t.Start(); + } + } + + private class InternalTimer : Timer + { + private readonly Campfire m_Campfire; + private readonly Mobile m_From; + + public InternalTimer(Mobile from, Campfire campfire) : base(TimeSpan.FromSeconds(5.0)) + { + m_From = from; + m_Campfire = campfire; + } + + protected override void OnTick() + { + if (m_From.GetDistanceToSqrt(m_Campfire) > 3) + { + m_From.SendLocalizedMessage(500686); // You burn the food to a crisp! It's ruined. + return; + } + + if (m_From.CheckSkill(SkillName.Cooking, 0, 10)) + { + if (m_From.AddToBackpack(new Muffins())) + m_From.PlaySound(0x57); + } + else + { + m_From.SendLocalizedMessage(500686); // You burn the food to a crisp! It's ruined. + } + } + } + } + } + + // ********** JarHoney ********** + public class JarHoney : Item + { + [Constructible] + public JarHoney() : base(0x9ec) + { + Weight = 1.0; + Stackable = true; + } + + public JarHoney(Serial serial) : base(serial) + { + } + + 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(); + Stackable = true; + } + + /*public override void OnDoubleClick( Mobile from ) + { + if (!Movable) + return; + + from.Target = new InternalTarget( this ); + }*/ + + private class InternalTarget : Target + { + private readonly JarHoney m_Item; + + public InternalTarget(JarHoney item) : base(1, false, TargetFlags.None) => m_Item = item; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Item.Deleted) return; + + m_Item.Consume(); + + if (targeted is Dough dough) + { + dough.Consume(); + + from.AddToBackpack(new SweetDough()); + } + + if (targeted is BowlFlour flour) + { + flour.Delete(); + + from.AddToBackpack(new CookieMix()); + } + } + } + } + + // ********** BowlFlour ********** + public class BowlFlour : Item + { + [Constructible] + public BowlFlour() : base(0xa1e) => Weight = 1.0; + + public BowlFlour(Serial serial) : base(serial) + { + } + + 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(); + } + } + + // ********** WoodenBowl ********** + public class WoodenBowl : Item + { + [Constructible] + public WoodenBowl() : base(0x15f8) => Weight = 1.0; + + public WoodenBowl(Serial serial) : base(serial) + { + } + + 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(); + } + } + + // ********** PitcherWater ********** + /*public class PitcherWater : Item + { + [Constructible] + public PitcherWater() : base(Utility.Random( 0x1f9d, 2 )) + { + Weight = 1.0; + } + + public PitcherWater( Serial serial ) : base( serial ) + { + } + + public override void Serialize( GenericWriter writer ) + { + base.Serialize( writer ); + + writer.Write( (int) 0 ); // version + } + + public override void Deserialize( GenericReader reader ) + { + base.Deserialize( reader ); + + int version = reader.ReadInt(); + } + + public override void OnDoubleClick( Mobile from ) + { + if (!Movable) + return; + + from.Target = new InternalTarget( this ); + } + + private class InternalTarget : Target + { + private PitcherWater m_Item; + + public InternalTarget( PitcherWater item ) : base( 1, false, TargetFlags.None ) + { + m_Item = item; + } + + protected override void OnTarget( Mobile from, object targeted ) + { + if (m_Item.Deleted ) return; + + if (targeted is BowlFlour) + { + m_Item.Delete(); + ((BowlFlour)targeted).Delete(); + + from.AddToBackpack( new Dough() ); + from.AddToBackpack( new WoodenBowl() ); + } + } + } + }*/ + + // ********** SackFlour ********** + [TypeAlias("Server.Items.SackFlourOpen")] + public class SackFlour : Item, IHasQuantity + { + private int m_Quantity; + + [Constructible] + public SackFlour() : base(0x1039) + { + Weight = 5.0; + m_Quantity = 20; + } + + public SackFlour(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Quantity + { + get => m_Quantity; + set + { + m_Quantity = Math.Min(20, Math.Max(0, value)); + + if (m_Quantity == 0) + Delete(); + else if (m_Quantity < 20 && (ItemID == 0x1039 || ItemID == 0x1045)) + ++ItemID; + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(2); // version + + writer.Write(m_Quantity); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 2: + case 1: + { + m_Quantity = reader.ReadInt(); + break; + } + case 0: + { + m_Quantity = 20; + break; + } + } + + if (version < 2 && Weight == 1.0) + Weight = 5.0; + } + + public override void OnDoubleClick(Mobile from) + { + if (!Movable) + return; + + if (ItemID == 0x1039 || ItemID == 0x1045) + ++ItemID; + } + } + + // ********** Eggshells ********** + public class Eggshells : Item + { + [Constructible] + public Eggshells() : base(0x9b4) => Weight = 0.5; + + public Eggshells(Serial serial) : base(serial) + { + } + + 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 class WheatSheaf : Item + { + [Constructible] + public WheatSheaf(int amount = 1) : base(7869) + { + Weight = 1.0; + Stackable = true; + Amount = amount; + } + + public WheatSheaf(Serial serial) : base(serial) + { + } + + public override void OnDoubleClick(Mobile from) + { + if (!Movable) + return; + + from.BeginTarget(4, false, TargetFlags.None, OnTarget); + } + + public virtual void OnTarget(Mobile from, object obj) + { + if (obj is AddonComponent addon) + obj = addon.Addon; + + if (obj is IFlourMill mill) + { + var needs = mill.MaxFlour - mill.CurFlour; + + if (needs > Amount) + needs = Amount; + + mill.CurFlour += needs; + Consume(needs); + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Food/Food.cs b/Projects/UOContent/Items/Food/Food.cs index dd1e135fe..93b11fe71 100644 --- a/Projects/UOContent/Items/Food/Food.cs +++ b/Projects/UOContent/Items/Food/Food.cs @@ -1,1100 +1,1100 @@ -using System.Collections.Generic; -using Server.ContextMenus; - -namespace Server.Items -{ - public abstract class Food : Item - { - public Food(int itemID, int amount) : base(itemID) - { - Stackable = true; - Amount = amount; - FillFactor = 1; - } - - public Food(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Poisoner { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Poison Poison { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int FillFactor { get; set; } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (from.Alive) - list.Add(new EatEntry(from, this)); - } - - public override void OnDoubleClick(Mobile from) - { - if (!Movable) - return; - - if (from.InRange(GetWorldLocation(), 1)) Eat(from); - } - - public virtual bool Eat(Mobile from) - { - // Fill the Mobile with FillFactor - if (CheckHunger(from)) - { - // Play a random "eat" sound - from.PlaySound(Utility.Random(0x3A, 3)); - - if (from.Body.IsHuman && !from.Mounted) - from.Animate(34, 5, 1, true, false, 0); - - if (Poison != null) - from.ApplyPoison(Poisoner, Poison); - - Consume(); - - return true; - } - - return false; - } - - public virtual bool CheckHunger(Mobile from) => FillHunger(from, FillFactor); - - public static bool FillHunger(Mobile from, int fillFactor) - { - if (from.Hunger >= 20) - { - from.SendLocalizedMessage(500867); // You are simply too full to eat any more! - return false; - } - - int iHunger = from.Hunger + fillFactor; - - if (from.Stam < from.StamMax) - from.Stam += Utility.Random(6, 3) + fillFactor / 5; - - if (iHunger >= 20) - { - from.Hunger = 20; - from.SendLocalizedMessage(500872); // You manage to eat the food, but you are stuffed! - } - else - { - from.Hunger = iHunger; - - if (iHunger < 5) - from.SendLocalizedMessage(500868); // You eat the food, but are still extremely hungry. - else if (iHunger < 10) - from.SendLocalizedMessage(500869); // You eat the food, and begin to feel more satiated. - else if (iHunger < 15) - from.SendLocalizedMessage(500870); // After eating the food, you feel much less hungry. - else - from.SendLocalizedMessage(500871); // You feel quite full after consuming the food. - } - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(4); // version - - writer.Write(Poisoner); - - Poison.Serialize(Poison, writer); - writer.Write(FillFactor); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - Poison = reader.ReadInt() switch - { - 0 => null, - 1 => Poison.Lesser, - 2 => Poison.Regular, - 3 => Poison.Greater, - 4 => Poison.Deadly, - _ => Poison - }; - - break; - } - case 2: - { - Poison = Poison.Deserialize(reader); - break; - } - case 3: - { - Poison = Poison.Deserialize(reader); - FillFactor = reader.ReadInt(); - break; - } - case 4: - { - Poisoner = reader.ReadMobile(); - goto case 3; - } - } - } - } - - public class BreadLoaf : Food - { - [Constructible] - public BreadLoaf(int amount = 1) : base(0x103B, amount) - { - Weight = 1.0; - FillFactor = 3; - } - - public BreadLoaf(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Bacon : Food - { - [Constructible] - public Bacon(int amount = 1) : base(0x979, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public Bacon(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SlabOfBacon : Food - { - [Constructible] - public SlabOfBacon(int amount = 1) : base(0x976, amount) - { - Weight = 1.0; - FillFactor = 3; - } - - public SlabOfBacon(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class FishSteak : Food - { - [Constructible] - public FishSteak(int amount = 1) : base(0x97B, amount) => FillFactor = 3; - - public FishSteak(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class CheeseWheel : Food - { - [Constructible] - public CheeseWheel(int amount = 1) : base(0x97E, amount) => FillFactor = 3; - - public CheeseWheel(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class CheeseWedge : Food - { - [Constructible] - public CheeseWedge(int amount = 1) : base(0x97D, amount) => FillFactor = 3; - - public CheeseWedge(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class CheeseSlice : Food - { - [Constructible] - public CheeseSlice(int amount = 1) : base(0x97C, amount) => FillFactor = 1; - - public CheeseSlice(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class FrenchBread : Food - { - [Constructible] - public FrenchBread(int amount = 1) : base(0x98C, amount) - { - Weight = 2.0; - FillFactor = 3; - } - - public FrenchBread(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class FriedEggs : Food - { - [Constructible] - public FriedEggs(int amount = 1) : base(0x9B6, amount) - { - Weight = 1.0; - FillFactor = 4; - } - - public FriedEggs(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class CookedBird : Food - { - [Constructible] - public CookedBird(int amount = 1) : base(0x9B7, amount) - { - Weight = 1.0; - FillFactor = 5; - } - - public CookedBird(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class RoastPig : Food - { - [Constructible] - public RoastPig(int amount = 1) : base(0x9BB, amount) - { - Weight = 45.0; - FillFactor = 20; - } - - public RoastPig(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Sausage : Food - { - [Constructible] - public Sausage(int amount = 1) : base(0x9C0, amount) - { - Weight = 1.0; - FillFactor = 4; - } - - public Sausage(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Ham : Food - { - [Constructible] - public Ham(int amount = 1) : base(0x9C9, amount) - { - Weight = 1.0; - FillFactor = 5; - } - - public Ham(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Cake : Food - { - [Constructible] - public Cake() : base(0x9E9, 1) - { - Stackable = false; - Weight = 1.0; - FillFactor = 10; - } - - public Cake(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Ribs : Food - { - [Constructible] - public Ribs(int amount = 1) : base(0x9F2, amount) - { - Weight = 1.0; - FillFactor = 5; - } - - public Ribs(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Cookies : Food - { - [Constructible] - public Cookies() : base(0x160b, 1) - { - Stackable = Core.ML; - Weight = 1.0; - FillFactor = 4; - } - - public Cookies(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Muffins : Food - { - [Constructible] - public Muffins() : base(0x9eb, 1) - { - Stackable = false; - Weight = 1.0; - FillFactor = 4; - } - - public Muffins(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [TypeAlias("Server.Items.Pizza")] - public class CheesePizza : Food - { - [Constructible] - public CheesePizza() : base(0x1040, 1) - { - Stackable = false; - Weight = 1.0; - FillFactor = 6; - } - - public CheesePizza(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1044516; // cheese pizza - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SausagePizza : Food - { - [Constructible] - public SausagePizza() : base(0x1040, 1) - { - Stackable = false; - Weight = 1.0; - FillFactor = 6; - } - - public SausagePizza(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1044517; // sausage pizza - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class FruitPie : Food - { - [Constructible] - public FruitPie() : base(0x1041, 1) - { - Stackable = false; - Weight = 1.0; - FillFactor = 5; - } - - public FruitPie(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041346; // baked fruit pie - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class MeatPie : Food - { - [Constructible] - public MeatPie() : base(0x1041, 1) - { - Stackable = false; - Weight = 1.0; - FillFactor = 5; - } - - public MeatPie(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041347; // baked meat pie - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PumpkinPie : Food - { - [Constructible] - public PumpkinPie() : base(0x1041, 1) - { - Stackable = false; - Weight = 1.0; - FillFactor = 5; - } - - public PumpkinPie(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041348; // baked pumpkin pie - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class ApplePie : Food - { - [Constructible] - public ApplePie() : base(0x1041, 1) - { - Stackable = false; - Weight = 1.0; - FillFactor = 5; - } - - public ApplePie(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041343; // baked apple pie - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PeachCobbler : Food - { - [Constructible] - public PeachCobbler() : base(0x1041, 1) - { - Stackable = false; - Weight = 1.0; - FillFactor = 5; - } - - public PeachCobbler(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041344; // baked peach cobbler - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Quiche : Food - { - [Constructible] - public Quiche() : base(0x1041, 1) - { - Stackable = Core.ML; - Weight = 1.0; - FillFactor = 5; - } - - public Quiche(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041345; // baked quiche - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LambLeg : Food - { - [Constructible] - public LambLeg(int amount = 1) : base(0x160a, amount) - { - Weight = 2.0; - FillFactor = 5; - } - - public LambLeg(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class ChickenLeg : Food - { - [Constructible] - public ChickenLeg(int amount = 1) : base(0x1608, amount) - { - Weight = 1.0; - FillFactor = 4; - } - - public ChickenLeg(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0xC74, 0xC75)] - public class HoneydewMelon : Food - { - [Constructible] - public HoneydewMelon(int amount = 1) : base(0xC74, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public HoneydewMelon(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0xC64, 0xC65)] - public class YellowGourd : Food - { - [Constructible] - public YellowGourd(int amount = 1) : base(0xC64, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public YellowGourd(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0xC66, 0xC67)] - public class GreenGourd : Food - { - [Constructible] - public GreenGourd(int amount = 1) : base(0xC66, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public GreenGourd(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0xC7F, 0xC81)] - public class EarOfCorn : Food - { - [Constructible] - public EarOfCorn(int amount = 1) : base(0xC81, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public EarOfCorn(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Turnip : Food - { - [Constructible] - public Turnip(int amount = 1) : base(0xD3A, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public Turnip(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SheafOfHay : Item - { - [Constructible] - public SheafOfHay() : base(0xF36) => Weight = 10.0; - - public SheafOfHay(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System.Collections.Generic; +using Server.ContextMenus; + +namespace Server.Items +{ + public abstract class Food : Item + { + public Food(int itemID, int amount) : base(itemID) + { + Stackable = true; + Amount = amount; + FillFactor = 1; + } + + public Food(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Poisoner { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Poison Poison { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int FillFactor { get; set; } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (from.Alive) + list.Add(new EatEntry(from, this)); + } + + public override void OnDoubleClick(Mobile from) + { + if (!Movable) + return; + + if (from.InRange(GetWorldLocation(), 1)) Eat(from); + } + + public virtual bool Eat(Mobile from) + { + // Fill the Mobile with FillFactor + if (CheckHunger(from)) + { + // Play a random "eat" sound + from.PlaySound(Utility.Random(0x3A, 3)); + + if (from.Body.IsHuman && !from.Mounted) + from.Animate(34, 5, 1, true, false, 0); + + if (Poison != null) + from.ApplyPoison(Poisoner, Poison); + + Consume(); + + return true; + } + + return false; + } + + public virtual bool CheckHunger(Mobile from) => FillHunger(from, FillFactor); + + public static bool FillHunger(Mobile from, int fillFactor) + { + if (from.Hunger >= 20) + { + from.SendLocalizedMessage(500867); // You are simply too full to eat any more! + return false; + } + + var iHunger = from.Hunger + fillFactor; + + if (from.Stam < from.StamMax) + from.Stam += Utility.Random(6, 3) + fillFactor / 5; + + if (iHunger >= 20) + { + from.Hunger = 20; + from.SendLocalizedMessage(500872); // You manage to eat the food, but you are stuffed! + } + else + { + from.Hunger = iHunger; + + if (iHunger < 5) + from.SendLocalizedMessage(500868); // You eat the food, but are still extremely hungry. + else if (iHunger < 10) + from.SendLocalizedMessage(500869); // You eat the food, and begin to feel more satiated. + else if (iHunger < 15) + from.SendLocalizedMessage(500870); // After eating the food, you feel much less hungry. + else + from.SendLocalizedMessage(500871); // You feel quite full after consuming the food. + } + + return true; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(4); // version + + writer.Write(Poisoner); + + Poison.Serialize(Poison, writer); + writer.Write(FillFactor); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + Poison = reader.ReadInt() switch + { + 0 => null, + 1 => Poison.Lesser, + 2 => Poison.Regular, + 3 => Poison.Greater, + 4 => Poison.Deadly, + _ => Poison + }; + + break; + } + case 2: + { + Poison = Poison.Deserialize(reader); + break; + } + case 3: + { + Poison = Poison.Deserialize(reader); + FillFactor = reader.ReadInt(); + break; + } + case 4: + { + Poisoner = reader.ReadMobile(); + goto case 3; + } + } + } + } + + public class BreadLoaf : Food + { + [Constructible] + public BreadLoaf(int amount = 1) : base(0x103B, amount) + { + Weight = 1.0; + FillFactor = 3; + } + + public BreadLoaf(Serial serial) : base(serial) + { + } + + 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 class Bacon : Food + { + [Constructible] + public Bacon(int amount = 1) : base(0x979, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public Bacon(Serial serial) : base(serial) + { + } + + 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 class SlabOfBacon : Food + { + [Constructible] + public SlabOfBacon(int amount = 1) : base(0x976, amount) + { + Weight = 1.0; + FillFactor = 3; + } + + public SlabOfBacon(Serial serial) : base(serial) + { + } + + 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 class FishSteak : Food + { + [Constructible] + public FishSteak(int amount = 1) : base(0x97B, amount) => FillFactor = 3; + + public FishSteak(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0.1; + + 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 class CheeseWheel : Food + { + [Constructible] + public CheeseWheel(int amount = 1) : base(0x97E, amount) => FillFactor = 3; + + public CheeseWheel(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0.1; + + 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 class CheeseWedge : Food + { + [Constructible] + public CheeseWedge(int amount = 1) : base(0x97D, amount) => FillFactor = 3; + + public CheeseWedge(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0.1; + + 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 class CheeseSlice : Food + { + [Constructible] + public CheeseSlice(int amount = 1) : base(0x97C, amount) => FillFactor = 1; + + public CheeseSlice(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0.1; + + 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 class FrenchBread : Food + { + [Constructible] + public FrenchBread(int amount = 1) : base(0x98C, amount) + { + Weight = 2.0; + FillFactor = 3; + } + + public FrenchBread(Serial serial) : base(serial) + { + } + + 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 class FriedEggs : Food + { + [Constructible] + public FriedEggs(int amount = 1) : base(0x9B6, amount) + { + Weight = 1.0; + FillFactor = 4; + } + + public FriedEggs(Serial serial) : base(serial) + { + } + + 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 class CookedBird : Food + { + [Constructible] + public CookedBird(int amount = 1) : base(0x9B7, amount) + { + Weight = 1.0; + FillFactor = 5; + } + + public CookedBird(Serial serial) : base(serial) + { + } + + 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 class RoastPig : Food + { + [Constructible] + public RoastPig(int amount = 1) : base(0x9BB, amount) + { + Weight = 45.0; + FillFactor = 20; + } + + public RoastPig(Serial serial) : base(serial) + { + } + + 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 class Sausage : Food + { + [Constructible] + public Sausage(int amount = 1) : base(0x9C0, amount) + { + Weight = 1.0; + FillFactor = 4; + } + + public Sausage(Serial serial) : base(serial) + { + } + + 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 class Ham : Food + { + [Constructible] + public Ham(int amount = 1) : base(0x9C9, amount) + { + Weight = 1.0; + FillFactor = 5; + } + + public Ham(Serial serial) : base(serial) + { + } + + 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 class Cake : Food + { + [Constructible] + public Cake() : base(0x9E9, 1) + { + Stackable = false; + Weight = 1.0; + FillFactor = 10; + } + + public Cake(Serial serial) : base(serial) + { + } + + 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 class Ribs : Food + { + [Constructible] + public Ribs(int amount = 1) : base(0x9F2, amount) + { + Weight = 1.0; + FillFactor = 5; + } + + public Ribs(Serial serial) : base(serial) + { + } + + 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 class Cookies : Food + { + [Constructible] + public Cookies() : base(0x160b, 1) + { + Stackable = Core.ML; + Weight = 1.0; + FillFactor = 4; + } + + public Cookies(Serial serial) : base(serial) + { + } + + 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 class Muffins : Food + { + [Constructible] + public Muffins() : base(0x9eb, 1) + { + Stackable = false; + Weight = 1.0; + FillFactor = 4; + } + + public Muffins(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [TypeAlias("Server.Items.Pizza")] + public class CheesePizza : Food + { + [Constructible] + public CheesePizza() : base(0x1040, 1) + { + Stackable = false; + Weight = 1.0; + FillFactor = 6; + } + + public CheesePizza(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1044516; // cheese pizza + + 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 class SausagePizza : Food + { + [Constructible] + public SausagePizza() : base(0x1040, 1) + { + Stackable = false; + Weight = 1.0; + FillFactor = 6; + } + + public SausagePizza(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1044517; // sausage pizza + + 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 class FruitPie : Food + { + [Constructible] + public FruitPie() : base(0x1041, 1) + { + Stackable = false; + Weight = 1.0; + FillFactor = 5; + } + + public FruitPie(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041346; // baked fruit pie + + 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 class MeatPie : Food + { + [Constructible] + public MeatPie() : base(0x1041, 1) + { + Stackable = false; + Weight = 1.0; + FillFactor = 5; + } + + public MeatPie(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041347; // baked meat pie + + 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 class PumpkinPie : Food + { + [Constructible] + public PumpkinPie() : base(0x1041, 1) + { + Stackable = false; + Weight = 1.0; + FillFactor = 5; + } + + public PumpkinPie(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041348; // baked pumpkin pie + + 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 class ApplePie : Food + { + [Constructible] + public ApplePie() : base(0x1041, 1) + { + Stackable = false; + Weight = 1.0; + FillFactor = 5; + } + + public ApplePie(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041343; // baked apple pie + + 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 class PeachCobbler : Food + { + [Constructible] + public PeachCobbler() : base(0x1041, 1) + { + Stackable = false; + Weight = 1.0; + FillFactor = 5; + } + + public PeachCobbler(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041344; // baked peach cobbler + + 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 class Quiche : Food + { + [Constructible] + public Quiche() : base(0x1041, 1) + { + Stackable = Core.ML; + Weight = 1.0; + FillFactor = 5; + } + + public Quiche(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041345; // baked quiche + + 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 class LambLeg : Food + { + [Constructible] + public LambLeg(int amount = 1) : base(0x160a, amount) + { + Weight = 2.0; + FillFactor = 5; + } + + public LambLeg(Serial serial) : base(serial) + { + } + + 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 class ChickenLeg : Food + { + [Constructible] + public ChickenLeg(int amount = 1) : base(0x1608, amount) + { + Weight = 1.0; + FillFactor = 4; + } + + public ChickenLeg(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0xC74, 0xC75)] + public class HoneydewMelon : Food + { + [Constructible] + public HoneydewMelon(int amount = 1) : base(0xC74, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public HoneydewMelon(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0xC64, 0xC65)] + public class YellowGourd : Food + { + [Constructible] + public YellowGourd(int amount = 1) : base(0xC64, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public YellowGourd(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0xC66, 0xC67)] + public class GreenGourd : Food + { + [Constructible] + public GreenGourd(int amount = 1) : base(0xC66, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public GreenGourd(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0xC7F, 0xC81)] + public class EarOfCorn : Food + { + [Constructible] + public EarOfCorn(int amount = 1) : base(0xC81, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public EarOfCorn(Serial serial) : base(serial) + { + } + + 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 class Turnip : Food + { + [Constructible] + public Turnip(int amount = 1) : base(0xD3A, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public Turnip(Serial serial) : base(serial) + { + } + + 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 class SheafOfHay : Item + { + [Constructible] + public SheafOfHay() : base(0xF36) => Weight = 10.0; + + public SheafOfHay(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Food/Fruits.cs b/Projects/UOContent/Items/Food/Fruits.cs index 4143e9e05..7299d18f1 100644 --- a/Projects/UOContent/Items/Food/Fruits.cs +++ b/Projects/UOContent/Items/Food/Fruits.cs @@ -1,557 +1,557 @@ -namespace Server.Items -{ - public class FruitBasket : Food - { - [Constructible] - public FruitBasket() : base(0x993, 1) - { - Weight = 2.0; - FillFactor = 5; - Stackable = false; - } - - public FruitBasket(Serial serial) : base(serial) - { - } - - public override bool Eat(Mobile from) - { - if (!base.Eat(from)) - return false; - - from.AddToBackpack(new Basket()); - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x171f, 0x1720)] - public class Banana : Food - { - [Constructible] - public Banana(int amount = 1) : base(0x171f, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public Banana(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1721, 0x1722)] - public class Bananas : Food - { - [Constructible] - public Bananas(int amount = 1) : base(0x1721, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public Bananas(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SplitCoconut : Food - { - [Constructible] - public SplitCoconut(int amount = 1) : base(0x1725, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public SplitCoconut(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Lemon : Food - { - [Constructible] - public Lemon(int amount = 1) : base(0x1728, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public Lemon(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Lemons : Food - { - [Constructible] - public Lemons(int amount = 1) : base(0x1729, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public Lemons(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Lime : Food - { - [Constructible] - public Lime(int amount = 1) : base(0x172a, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public Lime(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Limes : Food - { - [Constructible] - public Limes(int amount = 1) : base(0x172B, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public Limes(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Coconut : Food - { - [Constructible] - public Coconut(int amount = 1) : base(0x1726, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public Coconut(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class OpenCoconut : Food - { - [Constructible] - public OpenCoconut(int amount = 1) : base(0x1723, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public OpenCoconut(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Dates : Food - { - [Constructible] - public Dates(int amount = 1) : base(0x1727, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public Dates(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Grapes : Food - { - [Constructible] - public Grapes(int amount = 1) : base(0x9D1, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public Grapes(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Peach : Food - { - [Constructible] - public Peach(int amount = 1) : base(0x9D2, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public Peach(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Pear : Food - { - [Constructible] - public Pear(int amount = 1) : base(0x994, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public Pear(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Apple : Food - { - [Constructible] - public Apple(int amount = 1) : base(0x9D0, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public Apple(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Watermelon : Food - { - [Constructible] - public Watermelon(int amount = 1) : base(0xC5C, amount) - { - Weight = 5.0; - FillFactor = 5; - } - - public Watermelon(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); - - int version = reader.ReadInt(); - - if (version < 1) - { - if (FillFactor == 2) - FillFactor = 5; - - if (Weight == 2.0) - Weight = 5.0; - } - } - } - - public class SmallWatermelon : Food - { - [Constructible] - public SmallWatermelon(int amount = 1) : base(0xC5D, amount) - { - Weight = 5.0; - FillFactor = 5; - } - - public SmallWatermelon(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0xc72, 0xc73)] - public class Squash : Food - { - [Constructible] - public Squash(int amount = 1) : base(0xc72, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public Squash(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0xc79, 0xc7a)] - public class Cantaloupe : Food - { - [Constructible] - public Cantaloupe(int amount = 1) : base(0xc79, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public Cantaloupe(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class FruitBasket : Food + { + [Constructible] + public FruitBasket() : base(0x993, 1) + { + Weight = 2.0; + FillFactor = 5; + Stackable = false; + } + + public FruitBasket(Serial serial) : base(serial) + { + } + + public override bool Eat(Mobile from) + { + if (!base.Eat(from)) + return false; + + from.AddToBackpack(new Basket()); + return true; + } + + 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(); + } + } + + [Flippable(0x171f, 0x1720)] + public class Banana : Food + { + [Constructible] + public Banana(int amount = 1) : base(0x171f, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public Banana(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1721, 0x1722)] + public class Bananas : Food + { + [Constructible] + public Bananas(int amount = 1) : base(0x1721, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public Bananas(Serial serial) : base(serial) + { + } + + 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 class SplitCoconut : Food + { + [Constructible] + public SplitCoconut(int amount = 1) : base(0x1725, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public SplitCoconut(Serial serial) : base(serial) + { + } + + 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 class Lemon : Food + { + [Constructible] + public Lemon(int amount = 1) : base(0x1728, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public Lemon(Serial serial) : base(serial) + { + } + + 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 class Lemons : Food + { + [Constructible] + public Lemons(int amount = 1) : base(0x1729, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public Lemons(Serial serial) : base(serial) + { + } + + 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 class Lime : Food + { + [Constructible] + public Lime(int amount = 1) : base(0x172a, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public Lime(Serial serial) : base(serial) + { + } + + 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 class Limes : Food + { + [Constructible] + public Limes(int amount = 1) : base(0x172B, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public Limes(Serial serial) : base(serial) + { + } + + 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 class Coconut : Food + { + [Constructible] + public Coconut(int amount = 1) : base(0x1726, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public Coconut(Serial serial) : base(serial) + { + } + + 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 class OpenCoconut : Food + { + [Constructible] + public OpenCoconut(int amount = 1) : base(0x1723, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public OpenCoconut(Serial serial) : base(serial) + { + } + + 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 class Dates : Food + { + [Constructible] + public Dates(int amount = 1) : base(0x1727, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public Dates(Serial serial) : base(serial) + { + } + + 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 class Grapes : Food + { + [Constructible] + public Grapes(int amount = 1) : base(0x9D1, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public Grapes(Serial serial) : base(serial) + { + } + + 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 class Peach : Food + { + [Constructible] + public Peach(int amount = 1) : base(0x9D2, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public Peach(Serial serial) : base(serial) + { + } + + 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 class Pear : Food + { + [Constructible] + public Pear(int amount = 1) : base(0x994, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public Pear(Serial serial) : base(serial) + { + } + + 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 class Apple : Food + { + [Constructible] + public Apple(int amount = 1) : base(0x9D0, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public Apple(Serial serial) : base(serial) + { + } + + 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 class Watermelon : Food + { + [Constructible] + public Watermelon(int amount = 1) : base(0xC5C, amount) + { + Weight = 5.0; + FillFactor = 5; + } + + public Watermelon(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 < 1) + { + if (FillFactor == 2) + FillFactor = 5; + + if (Weight == 2.0) + Weight = 5.0; + } + } + } + + public class SmallWatermelon : Food + { + [Constructible] + public SmallWatermelon(int amount = 1) : base(0xC5D, amount) + { + Weight = 5.0; + FillFactor = 5; + } + + public SmallWatermelon(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0xc72, 0xc73)] + public class Squash : Food + { + [Constructible] + public Squash(int amount = 1) : base(0xc72, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public Squash(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0xc79, 0xc7a)] + public class Cantaloupe : Food + { + [Constructible] + public Cantaloupe(int amount = 1) : base(0xc79, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public Cantaloupe(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Food/Vegetables.cs b/Projects/UOContent/Items/Food/Vegetables.cs index 364b46646..16a3d5ca1 100644 --- a/Projects/UOContent/Items/Food/Vegetables.cs +++ b/Projects/UOContent/Items/Food/Vegetables.cs @@ -1,184 +1,184 @@ -namespace Server.Items -{ - [Flippable(0xc77, 0xc78)] - public class Carrot : Food - { - [Constructible] - public Carrot(int amount = 1) : base(0xc78, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public Carrot(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0xc7b, 0xc7c)] - public class Cabbage : Food - { - [Constructible] - public Cabbage(int amount = 1) : base(0xc7b, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public Cabbage(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0xc6d, 0xc6e)] - public class Onion : Food - { - [Constructible] - public Onion(int amount = 1) : base(0xc6d, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public Onion(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0xc70, 0xc71)] - public class Lettuce : Food - { - [Constructible] - public Lettuce(int amount = 1) : base(0xc70, amount) - { - Weight = 1.0; - FillFactor = 1; - } - - public Lettuce(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0xC6A, 0xC6B)] - public class Pumpkin : Food - { - [Constructible] - public Pumpkin(int amount = 1) : base(0xC6A, amount) - { - Weight = 1.0; - FillFactor = 8; - } - - public Pumpkin(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); - - int version = reader.ReadInt(); - - if (version < 1) - { - if (FillFactor == 4) - FillFactor = 8; - - if (Weight == 5.0) - Weight = 1.0; - } - } - } - - public class SmallPumpkin : Food - { - [Constructible] - public SmallPumpkin(int amount = 1) : base(0xC6C, amount) - { - Weight = 1.0; - FillFactor = 8; - } - - public SmallPumpkin(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + [Flippable(0xc77, 0xc78)] + public class Carrot : Food + { + [Constructible] + public Carrot(int amount = 1) : base(0xc78, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public Carrot(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0xc7b, 0xc7c)] + public class Cabbage : Food + { + [Constructible] + public Cabbage(int amount = 1) : base(0xc7b, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public Cabbage(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0xc6d, 0xc6e)] + public class Onion : Food + { + [Constructible] + public Onion(int amount = 1) : base(0xc6d, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public Onion(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0xc70, 0xc71)] + public class Lettuce : Food + { + [Constructible] + public Lettuce(int amount = 1) : base(0xc70, amount) + { + Weight = 1.0; + FillFactor = 1; + } + + public Lettuce(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0xC6A, 0xC6B)] + public class Pumpkin : Food + { + [Constructible] + public Pumpkin(int amount = 1) : base(0xC6A, amount) + { + Weight = 1.0; + FillFactor = 8; + } + + public Pumpkin(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 < 1) + { + if (FillFactor == 4) + FillFactor = 8; + + if (Weight == 5.0) + Weight = 1.0; + } + } + } + + public class SmallPumpkin : Food + { + [Constructible] + public SmallPumpkin(int amount = 1) : base(0xC6C, amount) + { + Weight = 1.0; + FillFactor = 8; + } + + public SmallPumpkin(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Games/Backgammon.cs b/Projects/UOContent/Items/Games/Backgammon.cs index 2c39a4041..836a62786 100644 --- a/Projects/UOContent/Items/Games/Backgammon.cs +++ b/Projects/UOContent/Items/Games/Backgammon.cs @@ -1,51 +1,51 @@ -namespace Server.Items -{ - [Flippable(0xE1C, 0xFAD)] - public class Backgammon : BaseBoard - { - [Constructible] - public Backgammon() : base(0xE1C) - { - } - - public Backgammon(Serial serial) : base(serial) - { - } - - public override void CreatePieces() - { - for (int i = 0; i < 5; i++) - { - CreatePiece(new PieceWhiteChecker(this), 42, 17 * i + 6); - CreatePiece(new PieceBlackChecker(this), 42, 17 * i + 119); - - CreatePiece(new PieceBlackChecker(this), 142, 17 * i + 6); - CreatePiece(new PieceWhiteChecker(this), 142, 17 * i + 119); - } - - for (int i = 0; i < 3; i++) - { - CreatePiece(new PieceBlackChecker(this), 108, 17 * i + 6); - CreatePiece(new PieceWhiteChecker(this), 108, 17 * i + 153); - } - - for (int i = 0; i < 2; i++) - { - CreatePiece(new PieceWhiteChecker(this), 223, 17 * i + 6); - CreatePiece(new PieceBlackChecker(this), 223, 17 * i + 170); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0xE1C, 0xFAD)] + public class Backgammon : BaseBoard + { + [Constructible] + public Backgammon() : base(0xE1C) + { + } + + public Backgammon(Serial serial) : base(serial) + { + } + + public override void CreatePieces() + { + for (var i = 0; i < 5; i++) + { + CreatePiece(new PieceWhiteChecker(this), 42, 17 * i + 6); + CreatePiece(new PieceBlackChecker(this), 42, 17 * i + 119); + + CreatePiece(new PieceBlackChecker(this), 142, 17 * i + 6); + CreatePiece(new PieceWhiteChecker(this), 142, 17 * i + 119); + } + + for (var i = 0; i < 3; i++) + { + CreatePiece(new PieceBlackChecker(this), 108, 17 * i + 6); + CreatePiece(new PieceWhiteChecker(this), 108, 17 * i + 153); + } + + for (var i = 0; i < 2; i++) + { + CreatePiece(new PieceWhiteChecker(this), 223, 17 * i + 6); + CreatePiece(new PieceBlackChecker(this), 223, 17 * i + 170); + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Games/BaseBoard.cs b/Projects/UOContent/Items/Games/BaseBoard.cs index a369ac47f..e3a0100a0 100644 --- a/Projects/UOContent/Items/Games/BaseBoard.cs +++ b/Projects/UOContent/Items/Games/BaseBoard.cs @@ -1,128 +1,131 @@ -using System; -using System.Collections.Generic; -using Server.ContextMenus; -using Server.Gumps; -using Server.Multis; -using Server.Network; - -namespace Server.Items -{ - public abstract class BaseBoard : Container, ISecurable - { - public BaseBoard(int itemID) : base(itemID) - { - CreatePieces(); - - Weight = 5.0; - } - - public BaseBoard(Serial serial) : base(serial) - { - } - - public override bool DisplaysContent => false; // Do not display (x items, y stones) - - public override bool IsDecoContainer => false; - - public override TimeSpan DecayTime => TimeSpan.FromDays(1.0); - - [CommandProperty(AccessLevel.GameMaster)] - public SecureLevel Level { get; set; } - - public abstract void CreatePieces(); - - public void Reset() - { - for (int i = Items.Count - 1; i >= 0; --i) - if (i < Items.Count) - Items[i].Delete(); - - CreatePieces(); - } - - public void CreatePiece(BasePiece piece, int x, int y) - { - AddItem(piece); - piece.Location = new Point3D(x, y, 0); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); // version - - writer.Write((int)Level); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (version == 1) - Level = (SecureLevel)reader.ReadInt(); - - if (Weight == 1.0) - Weight = 5.0; - } - - public override bool OnDragDrop(Mobile from, Item dropped) => dropped is BasePiece piece && piece.Board == this && base.OnDragDrop(from, dropped); - - public override bool OnDragDropInto(Mobile from, Item dropped, Point3D point) - { - if (dropped is BasePiece piece && piece.Board == this && base.OnDragDropInto(from, dropped, point)) - { - Packet p = new PlaySound(0x127, GetWorldLocation()); - - p.Acquire(); - - if (RootParent == from) - from.Send(p); - else - foreach (NetState state in GetClientsInRange(2)) - state.Send(p); - - p.Release(); - - return true; - } - - return false; - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (ValidateDefault(from, this)) - list.Add(new DefaultEntry(from, this)); - - SetSecureLevelEntry.AddTo(from, this, list); - } - - public static bool ValidateDefault(Mobile from, BaseBoard board) => - !board.Deleted && (from.AccessLevel >= AccessLevel.GameMaster || (from.Alive && - (board.IsChildOf(from.Backpack) || (!(board.RootParent is Mobile) && - board.Map == from.Map && from.InRange(board.GetWorldLocation(), 1) && - BaseHouse.FindHouseAt(board)?.IsOwner(from) == true)))); - - public class DefaultEntry : ContextMenuEntry - { - private readonly BaseBoard m_Board; - private readonly Mobile m_From; - - public DefaultEntry(Mobile from, BaseBoard board) : base(6162, - from.AccessLevel >= AccessLevel.GameMaster ? -1 : 1) - { - m_From = from; - m_Board = board; - } - - public override void OnClick() - { - if (ValidateDefault(m_From, m_Board)) - m_Board.Reset(); - } - } - } -} +using System; +using System.Collections.Generic; +using Server.ContextMenus; +using Server.Gumps; +using Server.Multis; +using Server.Network; + +namespace Server.Items +{ + public abstract class BaseBoard : Container, ISecurable + { + public BaseBoard(int itemID) : base(itemID) + { + CreatePieces(); + + Weight = 5.0; + } + + public BaseBoard(Serial serial) : base(serial) + { + } + + public override bool DisplaysContent => false; // Do not display (x items, y stones) + + public override bool IsDecoContainer => false; + + public override TimeSpan DecayTime => TimeSpan.FromDays(1.0); + + [CommandProperty(AccessLevel.GameMaster)] + public SecureLevel Level { get; set; } + + public abstract void CreatePieces(); + + public void Reset() + { + for (var i = Items.Count - 1; i >= 0; --i) + if (i < Items.Count) + Items[i].Delete(); + + CreatePieces(); + } + + public void CreatePiece(BasePiece piece, int x, int y) + { + AddItem(piece); + piece.Location = new Point3D(x, y, 0); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(1); // version + + writer.Write((int)Level); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + if (version == 1) + Level = (SecureLevel)reader.ReadInt(); + + if (Weight == 1.0) + Weight = 5.0; + } + + public override bool OnDragDrop(Mobile from, Item dropped) => + dropped is BasePiece piece && piece.Board == this && base.OnDragDrop(from, dropped); + + public override bool OnDragDropInto(Mobile from, Item dropped, Point3D point) + { + if (dropped is BasePiece piece && piece.Board == this && base.OnDragDropInto(from, dropped, point)) + { + Packet p = new PlaySound(0x127, GetWorldLocation()); + + p.Acquire(); + + if (RootParent == from) + from.Send(p); + else + foreach (var state in GetClientsInRange(2)) + state.Send(p); + + p.Release(); + + return true; + } + + return false; + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (ValidateDefault(from, this)) + list.Add(new DefaultEntry(from, this)); + + SetSecureLevelEntry.AddTo(from, this, list); + } + + public static bool ValidateDefault(Mobile from, BaseBoard board) => + !board.Deleted && (from.AccessLevel >= AccessLevel.GameMaster || @from.Alive && + (board.IsChildOf(@from.Backpack) || !(board.RootParent is Mobile) && + board.Map == @from.Map && @from.InRange(board.GetWorldLocation(), 1) && + BaseHouse.FindHouseAt(board)?.IsOwner(@from) == true)); + + public class DefaultEntry : ContextMenuEntry + { + private readonly BaseBoard m_Board; + private readonly Mobile m_From; + + public DefaultEntry(Mobile from, BaseBoard board) : base( + 6162, + from.AccessLevel >= AccessLevel.GameMaster ? -1 : 1 + ) + { + m_From = from; + m_Board = board; + } + + public override void OnClick() + { + if (ValidateDefault(m_From, m_Board)) + m_Board.Reset(); + } + } + } +} diff --git a/Projects/UOContent/Items/Games/BasePiece.cs b/Projects/UOContent/Items/Games/BasePiece.cs index 93949ffe6..59198e09a 100644 --- a/Projects/UOContent/Items/Games/BasePiece.cs +++ b/Projects/UOContent/Items/Games/BasePiece.cs @@ -1,80 +1,81 @@ -namespace Server.Items -{ - public class BasePiece : Item - { - public BasePiece(int itemID, BaseBoard board) : base(itemID) => Board = board; - - public BasePiece(Serial serial) : base(serial) - { - } - - public BaseBoard Board { get; set; } - - public override bool IsVirtualItem => true; - - public override bool CanTarget => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - writer.Write(Board); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Board = (BaseBoard)reader.ReadItem(); - - if (Board == null || Parent == null) - Delete(); - - break; - } - } - } - - public override void OnSingleClick(Mobile from) - { - if (Board?.Deleted != false) - Delete(); - else if (!IsChildOf(Board)) - Board.DropItem(this); - else - base.OnSingleClick(from); - } - - public override bool OnDragLift(Mobile from) - { - if (Board?.Deleted != false) - { - Delete(); - return false; - } - - if (!IsChildOf(Board)) - { - Board.DropItem(this); - return false; - } - - return true; - } - - public override bool DropToMobile(Mobile from, Mobile target, Point3D p) => false; - - public override bool DropToItem(Mobile from, Item target, Point3D p) => target == Board && p.X != -1 && p.Y != -1 && base.DropToItem(from, target, p); - - public override bool DropToWorld(Mobile from, Point3D p) => false; - - public override int GetLiftSound(Mobile from) => -1; - } -} +namespace Server.Items +{ + public class BasePiece : Item + { + public BasePiece(int itemID, BaseBoard board) : base(itemID) => Board = board; + + public BasePiece(Serial serial) : base(serial) + { + } + + public BaseBoard Board { get; set; } + + public override bool IsVirtualItem => true; + + public override bool CanTarget => false; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + writer.Write(Board); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Board = (BaseBoard)reader.ReadItem(); + + if (Board == null || Parent == null) + Delete(); + + break; + } + } + } + + public override void OnSingleClick(Mobile from) + { + if (Board?.Deleted != false) + Delete(); + else if (!IsChildOf(Board)) + Board.DropItem(this); + else + base.OnSingleClick(from); + } + + public override bool OnDragLift(Mobile from) + { + if (Board?.Deleted != false) + { + Delete(); + return false; + } + + if (!IsChildOf(Board)) + { + Board.DropItem(this); + return false; + } + + return true; + } + + public override bool DropToMobile(Mobile from, Mobile target, Point3D p) => false; + + public override bool DropToItem(Mobile from, Item target, Point3D p) => + target == Board && p.X != -1 && p.Y != -1 && base.DropToItem(from, target, p); + + public override bool DropToWorld(Mobile from, Point3D p) => false; + + public override int GetLiftSound(Mobile from) => -1; + } +} diff --git a/Projects/UOContent/Items/Games/CheckerBoard.cs b/Projects/UOContent/Items/Games/CheckerBoard.cs index 8e30c37b3..815666784 100644 --- a/Projects/UOContent/Items/Games/CheckerBoard.cs +++ b/Projects/UOContent/Items/Games/CheckerBoard.cs @@ -1,41 +1,41 @@ -namespace Server.Items -{ - public class CheckerBoard : BaseBoard - { - [Constructible] - public CheckerBoard() : base(0xFA6) - { - } - - public CheckerBoard(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1016449; // a checker board - - public override void CreatePieces() - { - for (int i = 0; i < 4; i++) - { - CreatePiece(new PieceWhiteChecker(this), 50 * i + 45, 25); - CreatePiece(new PieceWhiteChecker(this), 50 * i + 70, 50); - CreatePiece(new PieceWhiteChecker(this), 50 * i + 45, 75); - CreatePiece(new PieceBlackChecker(this), 50 * i + 70, 150); - CreatePiece(new PieceBlackChecker(this), 50 * i + 45, 175); - CreatePiece(new PieceBlackChecker(this), 50 * i + 70, 200); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class CheckerBoard : BaseBoard + { + [Constructible] + public CheckerBoard() : base(0xFA6) + { + } + + public CheckerBoard(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1016449; // a checker board + + public override void CreatePieces() + { + for (var i = 0; i < 4; i++) + { + CreatePiece(new PieceWhiteChecker(this), 50 * i + 45, 25); + CreatePiece(new PieceWhiteChecker(this), 50 * i + 70, 50); + CreatePiece(new PieceWhiteChecker(this), 50 * i + 45, 75); + CreatePiece(new PieceBlackChecker(this), 50 * i + 70, 150); + CreatePiece(new PieceBlackChecker(this), 50 * i + 45, 175); + CreatePiece(new PieceBlackChecker(this), 50 * i + 70, 200); + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Games/CheckersPieces.cs b/Projects/UOContent/Items/Games/CheckersPieces.cs index 5cb505cba..1030b60c8 100644 --- a/Projects/UOContent/Items/Games/CheckersPieces.cs +++ b/Projects/UOContent/Items/Games/CheckersPieces.cs @@ -1,52 +1,52 @@ -namespace Server.Items -{ - public class PieceWhiteChecker : BasePiece - { - public PieceWhiteChecker(BaseBoard board) : base(0x3584, board) - { - } - - public PieceWhiteChecker(Serial serial) : base(serial) - { - } - - public override string DefaultName => "white checker"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class PieceBlackChecker : BasePiece - { - public PieceBlackChecker(BaseBoard board) : base(0x358B, board) - { - } - - public PieceBlackChecker(Serial serial) : base(serial) - { - } - - public override string DefaultName => "black checker"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PieceWhiteChecker : BasePiece + { + public PieceWhiteChecker(BaseBoard board) : base(0x3584, board) + { + } + + public PieceWhiteChecker(Serial serial) : base(serial) + { + } + + public override string DefaultName => "white checker"; + + 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(); + } + } + + public class PieceBlackChecker : BasePiece + { + public PieceBlackChecker(BaseBoard board) : base(0x358B, board) + { + } + + public PieceBlackChecker(Serial serial) : base(serial) + { + } + + public override string DefaultName => "black checker"; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Games/ChessPieces.cs b/Projects/UOContent/Items/Games/ChessPieces.cs index edc6f9cd6..01b76c21e 100644 --- a/Projects/UOContent/Items/Games/ChessPieces.cs +++ b/Projects/UOContent/Items/Games/ChessPieces.cs @@ -1,302 +1,302 @@ -namespace Server.Items -{ - public class PieceWhiteKing : BasePiece - { - public PieceWhiteKing(BaseBoard board) : base(0x3587, board) - { - } - - public PieceWhiteKing(Serial serial) : base(serial) - { - } - - public override string DefaultName => "white king"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class PieceBlackKing : BasePiece - { - public PieceBlackKing(BaseBoard board) : base(0x358E, board) - { - } - - public PieceBlackKing(Serial serial) : base(serial) - { - } - - public override string DefaultName => "black king"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class PieceWhiteQueen : BasePiece - { - public PieceWhiteQueen(BaseBoard board) : base(0x358A, board) - { - } - - public PieceWhiteQueen(Serial serial) : base(serial) - { - } - - public override string DefaultName => "white queen"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class PieceBlackQueen : BasePiece - { - public PieceBlackQueen(BaseBoard board) : base(0x3591, board) - { - } - - public PieceBlackQueen(Serial serial) : base(serial) - { - } - - public override string DefaultName => "black queen"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class PieceWhiteRook : BasePiece - { - public PieceWhiteRook(BaseBoard board) : base(0x3586, board) - { - } - - public PieceWhiteRook(Serial serial) : base(serial) - { - } - - public override string DefaultName => "white rook"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class PieceBlackRook : BasePiece - { - public PieceBlackRook(BaseBoard board) : base(0x358D, board) - { - } - - public PieceBlackRook(Serial serial) : base(serial) - { - } - - public override string DefaultName => "black rook"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class PieceWhiteBishop : BasePiece - { - public PieceWhiteBishop(BaseBoard board) : base(0x3585, board) - { - } - - public PieceWhiteBishop(Serial serial) : base(serial) - { - } - - public override string DefaultName => "white bishop"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class PieceBlackBishop : BasePiece - { - public PieceBlackBishop(BaseBoard board) : base(0x358C, board) - { - } - - public PieceBlackBishop(Serial serial) : base(serial) - { - } - - public override string DefaultName => "black bishop"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class PieceWhiteKnight : BasePiece - { - public PieceWhiteKnight(BaseBoard board) : base(0x3588, board) - { - } - - public PieceWhiteKnight(Serial serial) : base(serial) - { - } - - public override string DefaultName => "white knight"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class PieceBlackKnight : BasePiece - { - public PieceBlackKnight(BaseBoard board) : base(0x358F, board) - { - } - - public PieceBlackKnight(Serial serial) : base(serial) - { - } - - public override string DefaultName => "black knight"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class PieceWhitePawn : BasePiece - { - public PieceWhitePawn(BaseBoard board) : base(0x3589, board) - { - } - - public PieceWhitePawn(Serial serial) : base(serial) - { - } - - public override string DefaultName => "white pawn"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class PieceBlackPawn : BasePiece - { - public PieceBlackPawn(BaseBoard board) : base(0x3590, board) - { - } - - public PieceBlackPawn(Serial serial) : base(serial) - { - } - - public override string DefaultName => "black pawn"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PieceWhiteKing : BasePiece + { + public PieceWhiteKing(BaseBoard board) : base(0x3587, board) + { + } + + public PieceWhiteKing(Serial serial) : base(serial) + { + } + + public override string DefaultName => "white king"; + + 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(); + } + } + + public class PieceBlackKing : BasePiece + { + public PieceBlackKing(BaseBoard board) : base(0x358E, board) + { + } + + public PieceBlackKing(Serial serial) : base(serial) + { + } + + public override string DefaultName => "black king"; + + 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(); + } + } + + public class PieceWhiteQueen : BasePiece + { + public PieceWhiteQueen(BaseBoard board) : base(0x358A, board) + { + } + + public PieceWhiteQueen(Serial serial) : base(serial) + { + } + + public override string DefaultName => "white queen"; + + 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(); + } + } + + public class PieceBlackQueen : BasePiece + { + public PieceBlackQueen(BaseBoard board) : base(0x3591, board) + { + } + + public PieceBlackQueen(Serial serial) : base(serial) + { + } + + public override string DefaultName => "black queen"; + + 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(); + } + } + + public class PieceWhiteRook : BasePiece + { + public PieceWhiteRook(BaseBoard board) : base(0x3586, board) + { + } + + public PieceWhiteRook(Serial serial) : base(serial) + { + } + + public override string DefaultName => "white rook"; + + 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(); + } + } + + public class PieceBlackRook : BasePiece + { + public PieceBlackRook(BaseBoard board) : base(0x358D, board) + { + } + + public PieceBlackRook(Serial serial) : base(serial) + { + } + + public override string DefaultName => "black rook"; + + 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(); + } + } + + public class PieceWhiteBishop : BasePiece + { + public PieceWhiteBishop(BaseBoard board) : base(0x3585, board) + { + } + + public PieceWhiteBishop(Serial serial) : base(serial) + { + } + + public override string DefaultName => "white bishop"; + + 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(); + } + } + + public class PieceBlackBishop : BasePiece + { + public PieceBlackBishop(BaseBoard board) : base(0x358C, board) + { + } + + public PieceBlackBishop(Serial serial) : base(serial) + { + } + + public override string DefaultName => "black bishop"; + + 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(); + } + } + + public class PieceWhiteKnight : BasePiece + { + public PieceWhiteKnight(BaseBoard board) : base(0x3588, board) + { + } + + public PieceWhiteKnight(Serial serial) : base(serial) + { + } + + public override string DefaultName => "white knight"; + + 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(); + } + } + + public class PieceBlackKnight : BasePiece + { + public PieceBlackKnight(BaseBoard board) : base(0x358F, board) + { + } + + public PieceBlackKnight(Serial serial) : base(serial) + { + } + + public override string DefaultName => "black knight"; + + 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(); + } + } + + public class PieceWhitePawn : BasePiece + { + public PieceWhitePawn(BaseBoard board) : base(0x3589, board) + { + } + + public PieceWhitePawn(Serial serial) : base(serial) + { + } + + public override string DefaultName => "white pawn"; + + 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(); + } + } + + public class PieceBlackPawn : BasePiece + { + public PieceBlackPawn(BaseBoard board) : base(0x3590, board) + { + } + + public PieceBlackPawn(Serial serial) : base(serial) + { + } + + public override string DefaultName => "black pawn"; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Games/Chessboard.cs b/Projects/UOContent/Items/Games/Chessboard.cs index efc5ea6f2..5ac9e4141 100644 --- a/Projects/UOContent/Items/Games/Chessboard.cs +++ b/Projects/UOContent/Items/Games/Chessboard.cs @@ -1,66 +1,66 @@ -namespace Server.Items -{ - public class Chessboard : BaseBoard - { - [Constructible] - public Chessboard() : base(0xFA6) - { - } - - public Chessboard(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1016450; // a chessboard - - public override void CreatePieces() - { - for (int i = 0; i < 8; i++) - { - CreatePiece(new PieceBlackPawn(this), 67, 25 * i + 17); - CreatePiece(new PieceWhitePawn(this), 192, 25 * i + 17); - } - - // Rook - CreatePiece(new PieceBlackRook(this), 42, 5); - CreatePiece(new PieceBlackRook(this), 42, 180); - - CreatePiece(new PieceWhiteRook(this), 216, 5); - CreatePiece(new PieceWhiteRook(this), 216, 180); - - // Knight - CreatePiece(new PieceBlackKnight(this), 42, 30); - CreatePiece(new PieceBlackKnight(this), 42, 155); - - CreatePiece(new PieceWhiteKnight(this), 216, 30); - CreatePiece(new PieceWhiteKnight(this), 216, 155); - - // Bishop - CreatePiece(new PieceBlackBishop(this), 42, 55); - CreatePiece(new PieceBlackBishop(this), 42, 130); - - CreatePiece(new PieceWhiteBishop(this), 216, 55); - CreatePiece(new PieceWhiteBishop(this), 216, 130); - - // Queen - CreatePiece(new PieceBlackQueen(this), 42, 105); - CreatePiece(new PieceWhiteQueen(this), 216, 105); - - // King - CreatePiece(new PieceBlackKing(this), 42, 80); - CreatePiece(new PieceWhiteKing(this), 216, 80); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Chessboard : BaseBoard + { + [Constructible] + public Chessboard() : base(0xFA6) + { + } + + public Chessboard(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1016450; // a chessboard + + public override void CreatePieces() + { + for (var i = 0; i < 8; i++) + { + CreatePiece(new PieceBlackPawn(this), 67, 25 * i + 17); + CreatePiece(new PieceWhitePawn(this), 192, 25 * i + 17); + } + + // Rook + CreatePiece(new PieceBlackRook(this), 42, 5); + CreatePiece(new PieceBlackRook(this), 42, 180); + + CreatePiece(new PieceWhiteRook(this), 216, 5); + CreatePiece(new PieceWhiteRook(this), 216, 180); + + // Knight + CreatePiece(new PieceBlackKnight(this), 42, 30); + CreatePiece(new PieceBlackKnight(this), 42, 155); + + CreatePiece(new PieceWhiteKnight(this), 216, 30); + CreatePiece(new PieceWhiteKnight(this), 216, 155); + + // Bishop + CreatePiece(new PieceBlackBishop(this), 42, 55); + CreatePiece(new PieceBlackBishop(this), 42, 130); + + CreatePiece(new PieceWhiteBishop(this), 216, 55); + CreatePiece(new PieceWhiteBishop(this), 216, 130); + + // Queen + CreatePiece(new PieceBlackQueen(this), 42, 105); + CreatePiece(new PieceWhiteQueen(this), 216, 105); + + // King + CreatePiece(new PieceBlackKing(this), 42, 80); + CreatePiece(new PieceWhiteKing(this), 216, 80); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Games/Dices.cs b/Projects/UOContent/Items/Games/Dices.cs index e3bedbcbe..f4398e90b 100644 --- a/Projects/UOContent/Items/Games/Dices.cs +++ b/Projects/UOContent/Items/Games/Dices.cs @@ -1,48 +1,52 @@ -using Server.Network; - -namespace Server.Items -{ - public class Dices : Item, ITelekinesisable - { - [Constructible] - public Dices() : base(0xFA7) => Weight = 1.0; - - public Dices(Serial serial) : base(serial) - { - } - - public void OnTelekinesis(Mobile from) - { - Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x376A, 9, 32, 5022); - Effects.PlaySound(Location, Map, 0x1F5); - - Roll(from); - } - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 2)) - return; - - Roll(from); - } - - public void Roll(Mobile from) - { - PublicOverheadMessage(MessageType.Regular, 0, false, - $"*{from.Name} rolls {Utility.Random(1, 6)}, {Utility.Random(1, 6)}*"); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Network; + +namespace Server.Items +{ + public class Dices : Item, ITelekinesisable + { + [Constructible] + public Dices() : base(0xFA7) => Weight = 1.0; + + public Dices(Serial serial) : base(serial) + { + } + + public void OnTelekinesis(Mobile from) + { + Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x376A, 9, 32, 5022); + Effects.PlaySound(Location, Map, 0x1F5); + + Roll(from); + } + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 2)) + return; + + Roll(from); + } + + public void Roll(Mobile from) + { + PublicOverheadMessage( + MessageType.Regular, + 0, + false, + $"*{from.Name} rolls {Utility.Random(1, 6)}, {Utility.Random(1, 6)}*" + ); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Games/Mahjong/MahjongDealerIndicator.cs b/Projects/UOContent/Items/Games/Mahjong/MahjongDealerIndicator.cs index 73122cc70..dfcf16343 100644 --- a/Projects/UOContent/Items/Games/Mahjong/MahjongDealerIndicator.cs +++ b/Projects/UOContent/Items/Games/Mahjong/MahjongDealerIndicator.cs @@ -1,64 +1,64 @@ -namespace Server.Engines.Mahjong -{ - public class MahjongDealerIndicator - { - public MahjongDealerIndicator(MahjongGame game, Point2D position, MahjongPieceDirection direction, MahjongWind wind) - { - Game = game; - Position = position; - Direction = direction; - Wind = wind; - } - - public MahjongDealerIndicator(MahjongGame game, IGenericReader reader) - { - Game = game; - - int version = reader.ReadInt(); - - Position = reader.ReadPoint2D(); - Direction = (MahjongPieceDirection)reader.ReadInt(); - Wind = (MahjongWind)reader.ReadInt(); - } - - public MahjongGame Game { get; } - - public Point2D Position { get; private set; } - - public MahjongPieceDirection Direction { get; private set; } - - public MahjongWind Wind { get; private set; } - - public MahjongPieceDim Dimensions => GetDimensions(Position, Direction); - - public static MahjongPieceDim GetDimensions(Point2D position, MahjongPieceDirection direction) - { - if (direction == MahjongPieceDirection.Up || direction == MahjongPieceDirection.Down) - return new MahjongPieceDim(position, 40, 20); - return new MahjongPieceDim(position, 20, 40); - } - - public void Move(Point2D position, MahjongPieceDirection direction, MahjongWind wind) - { - MahjongPieceDim dim = GetDimensions(position, direction); - - if (!dim.IsValid()) - return; - - Position = position; - Direction = direction; - Wind = wind; - - Game.Players.SendGeneralPacket(true, true); - } - - public void Save(IGenericWriter writer) - { - writer.Write(0); // version - - writer.Write(Position); - writer.Write((int)Direction); - writer.Write((int)Wind); - } - } -} \ No newline at end of file +namespace Server.Engines.Mahjong +{ + public class MahjongDealerIndicator + { + public MahjongDealerIndicator(MahjongGame game, Point2D position, MahjongPieceDirection direction, MahjongWind wind) + { + Game = game; + Position = position; + Direction = direction; + Wind = wind; + } + + public MahjongDealerIndicator(MahjongGame game, IGenericReader reader) + { + Game = game; + + var version = reader.ReadInt(); + + Position = reader.ReadPoint2D(); + Direction = (MahjongPieceDirection)reader.ReadInt(); + Wind = (MahjongWind)reader.ReadInt(); + } + + public MahjongGame Game { get; } + + public Point2D Position { get; private set; } + + public MahjongPieceDirection Direction { get; private set; } + + public MahjongWind Wind { get; private set; } + + public MahjongPieceDim Dimensions => GetDimensions(Position, Direction); + + public static MahjongPieceDim GetDimensions(Point2D position, MahjongPieceDirection direction) + { + if (direction == MahjongPieceDirection.Up || direction == MahjongPieceDirection.Down) + return new MahjongPieceDim(position, 40, 20); + return new MahjongPieceDim(position, 20, 40); + } + + public void Move(Point2D position, MahjongPieceDirection direction, MahjongWind wind) + { + var dim = GetDimensions(position, direction); + + if (!dim.IsValid()) + return; + + Position = position; + Direction = direction; + Wind = wind; + + Game.Players.SendGeneralPacket(true, true); + } + + public void Save(IGenericWriter writer) + { + writer.Write(0); // version + + writer.Write(Position); + writer.Write((int)Direction); + writer.Write((int)Wind); + } + } +} diff --git a/Projects/UOContent/Items/Games/Mahjong/MahjongDices.cs b/Projects/UOContent/Items/Games/Mahjong/MahjongDices.cs index 49e607b59..876f30057 100644 --- a/Projects/UOContent/Items/Games/Mahjong/MahjongDices.cs +++ b/Projects/UOContent/Items/Games/Mahjong/MahjongDices.cs @@ -1,48 +1,50 @@ -namespace Server.Engines.Mahjong -{ - public class MahjongDices - { - public MahjongDices(MahjongGame game) - { - Game = game; - First = Utility.Random(1, 6); - Second = Utility.Random(1, 6); - } - - public MahjongDices(MahjongGame game, IGenericReader reader) - { - Game = game; - - int version = reader.ReadInt(); - - First = reader.ReadInt(); - Second = reader.ReadInt(); - } - - public MahjongGame Game { get; } - - public int First { get; private set; } - - public int Second { get; private set; } - - public void RollDices(Mobile from) - { - First = Utility.Random(1, 6); - Second = Utility.Random(1, 6); - - Game.Players.SendGeneralPacket(true, true); - - if (from != null) - Game.Players.SendLocalizedMessage(1062695, - $"{from.Name}\t{First}\t{Second}"); // ~1_name~ rolls the dice and gets a ~2_number~ and a ~3_number~! - } - - public void Save(IGenericWriter writer) - { - writer.Write(0); // version - - writer.Write(First); - writer.Write(Second); - } - } -} \ No newline at end of file +namespace Server.Engines.Mahjong +{ + public class MahjongDices + { + public MahjongDices(MahjongGame game) + { + Game = game; + First = Utility.Random(1, 6); + Second = Utility.Random(1, 6); + } + + public MahjongDices(MahjongGame game, IGenericReader reader) + { + Game = game; + + var version = reader.ReadInt(); + + First = reader.ReadInt(); + Second = reader.ReadInt(); + } + + public MahjongGame Game { get; } + + public int First { get; private set; } + + public int Second { get; private set; } + + public void RollDices(Mobile from) + { + First = Utility.Random(1, 6); + Second = Utility.Random(1, 6); + + Game.Players.SendGeneralPacket(true, true); + + if (from != null) + Game.Players.SendLocalizedMessage( + 1062695, + $"{from.Name}\t{First}\t{Second}" + ); // ~1_name~ rolls the dice and gets a ~2_number~ and a ~3_number~! + } + + public void Save(IGenericWriter writer) + { + writer.Write(0); // version + + writer.Write(First); + writer.Write(Second); + } + } +} diff --git a/Projects/UOContent/Items/Games/Mahjong/MahjongEnums.cs b/Projects/UOContent/Items/Games/Mahjong/MahjongEnums.cs index 633bf8968..4dd79a98d 100644 --- a/Projects/UOContent/Items/Games/Mahjong/MahjongEnums.cs +++ b/Projects/UOContent/Items/Games/Mahjong/MahjongEnums.cs @@ -1,56 +1,56 @@ -namespace Server.Engines.Mahjong -{ - public enum MahjongPieceDirection - { - Up, - Left, - Down, - Right - } - - public enum MahjongWind - { - North, - East, - South, - West - } - - public enum MahjongTileType - { - Dagger1 = 1, - Dagger2, - Dagger3, - Dagger4, - Dagger5, - Dagger6, - Dagger7, - Dagger8, - Dagger9, - Gem1, - Gem2, - Gem3, - Gem4, - Gem5, - Gem6, - Gem7, - Gem8, - Gem9, - Number1, - Number2, - Number3, - Number4, - Number5, - Number6, - Number7, - Number8, - Number9, - North, - East, - South, - West, - Green, - Red, - White - } -} \ No newline at end of file +namespace Server.Engines.Mahjong +{ + public enum MahjongPieceDirection + { + Up, + Left, + Down, + Right + } + + public enum MahjongWind + { + North, + East, + South, + West + } + + public enum MahjongTileType + { + Dagger1 = 1, + Dagger2, + Dagger3, + Dagger4, + Dagger5, + Dagger6, + Dagger7, + Dagger8, + Dagger9, + Gem1, + Gem2, + Gem3, + Gem4, + Gem5, + Gem6, + Gem7, + Gem8, + Gem9, + Number1, + Number2, + Number3, + Number4, + Number5, + Number6, + Number7, + Number8, + Number9, + North, + East, + South, + West, + Green, + Red, + White + } +} diff --git a/Projects/UOContent/Items/Games/Mahjong/MahjongGame.cs b/Projects/UOContent/Items/Games/Mahjong/MahjongGame.cs index 91f60d32f..248446fde 100644 --- a/Projects/UOContent/Items/Games/Mahjong/MahjongGame.cs +++ b/Projects/UOContent/Items/Games/Mahjong/MahjongGame.cs @@ -1,295 +1,313 @@ -using System; -using System.Collections.Generic; -using Server.ContextMenus; -using Server.Gumps; -using Server.Multis; - -namespace Server.Engines.Mahjong -{ - public class MahjongGame : Item, ISecurable - { - public const int MaxPlayers = 4; - public const int BaseScore = 30000; - private DateTime m_LastReset; - - private bool m_ShowScores; - private bool m_SpectatorVision; - - [Constructible] - public MahjongGame() : base(0xFAA) - { - Weight = 5.0; - - BuildWalls(); - DealerIndicator = - new MahjongDealerIndicator(this, new Point2D(300, 300), MahjongPieceDirection.Up, MahjongWind.North); - WallBreakIndicator = new MahjongWallBreakIndicator(this, new Point2D(335, 335)); - Dices = new MahjongDices(this); - Players = new MahjongPlayers(this, MaxPlayers, BaseScore); - m_LastReset = DateTime.UtcNow; - Level = SecureLevel.CoOwners; - } - - public MahjongGame(Serial serial) : base(serial) - { - } - - public MahjongTile[] Tiles { get; private set; } - - public MahjongDealerIndicator DealerIndicator { get; private set; } - - public MahjongWallBreakIndicator WallBreakIndicator { get; private set; } - - public MahjongDices Dices { get; private set; } - - public MahjongPlayers Players { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool ShowScores - { - get => m_ShowScores; - set - { - if (m_ShowScores == value) - return; - - m_ShowScores = value; - - if (value) - Players.SendPlayersPacket(true, true); - - Players.SendGeneralPacket(true, true); - - Players.SendLocalizedMessage(value ? 1062777 : 1062778); // The dealer has enabled/disabled score display. - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool SpectatorVision - { - get => m_SpectatorVision; - set - { - if (m_SpectatorVision == value) - return; - - m_SpectatorVision = value; - - if (Players.IsInGamePlayer(Players.DealerPosition)) - Players.Dealer.Send(new MahjongGeneralInfo(this)); - - Players.SendTilesPacket(false, true); - - Players.SendLocalizedMessage(value ? 1062715 : 1062716); // The dealer has enabled/disabled Spectator Vision. - - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public SecureLevel Level { get; set; } - - private void BuildHorizontalWall(ref int index, int x, int y, int stackLevel, MahjongPieceDirection direction, - MahjongTileTypeGenerator typeGenerator) - { - for (int i = 0; i < 17; i++) - { - Point2D position = new Point2D(x + i * 20, y); - Tiles[index + i] = new MahjongTile(this, index + i, typeGenerator.Next(), position, stackLevel, direction, - false); - } - - index += 17; - } - - private void BuildVerticalWall(ref int index, int x, int y, int stackLevel, MahjongPieceDirection direction, - MahjongTileTypeGenerator typeGenerator) - { - for (int i = 0; i < 17; i++) - { - Point2D position = new Point2D(x, y + i * 20); - Tiles[index + i] = new MahjongTile(this, index + i, typeGenerator.Next(), position, stackLevel, direction, - false); - } - - index += 17; - } - - private void BuildWalls() - { - Tiles = new MahjongTile[136]; - - MahjongTileTypeGenerator typeGenerator = new MahjongTileTypeGenerator(); - - int i = 0; - - BuildHorizontalWall(ref i, 165, 110, 0, MahjongPieceDirection.Up, typeGenerator); - BuildHorizontalWall(ref i, 165, 115, 1, MahjongPieceDirection.Up, typeGenerator); - - BuildVerticalWall(ref i, 530, 165, 0, MahjongPieceDirection.Left, typeGenerator); - BuildVerticalWall(ref i, 525, 165, 1, MahjongPieceDirection.Left, typeGenerator); - - BuildHorizontalWall(ref i, 165, 530, 0, MahjongPieceDirection.Down, typeGenerator); - BuildHorizontalWall(ref i, 165, 525, 1, MahjongPieceDirection.Down, typeGenerator); - - BuildVerticalWall(ref i, 110, 165, 0, MahjongPieceDirection.Right, typeGenerator); - BuildVerticalWall(ref i, 115, 165, 1, MahjongPieceDirection.Right, typeGenerator); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_SpectatorVision) - list.Add(1062717); // Spectator Vision Enabled - else - list.Add(1062718); // Spectator Vision Disabled - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - Players.CheckPlayers(); - - if (from.Alive && IsAccessibleTo(from) && Players.GetInGameMobiles(true, false).Count == 0) - list.Add(new ResetGameEntry(this)); - - SetSecureLevelEntry.AddTo(from, this, list); - } - - public override void OnDoubleClick(Mobile from) - { - Players.CheckPlayers(); - - Players.Join(from); - } - - public void ResetGame(Mobile from) - { - if (DateTime.UtcNow - m_LastReset < TimeSpan.FromSeconds(5.0)) - return; - - m_LastReset = DateTime.UtcNow; - - if (from != null) - Players.SendLocalizedMessage(1062771, from.Name); // ~1_name~ has reset the game. - - Players.SendRelievePacket(true, true); - - BuildWalls(); - DealerIndicator = - new MahjongDealerIndicator(this, new Point2D(300, 300), MahjongPieceDirection.Up, MahjongWind.North); - WallBreakIndicator = new MahjongWallBreakIndicator(this, new Point2D(335, 335)); - Players = new MahjongPlayers(this, MaxPlayers, BaseScore); - } - - public void ResetWalls(Mobile from) - { - if (DateTime.UtcNow - m_LastReset < TimeSpan.FromSeconds(5.0)) - return; - - m_LastReset = DateTime.UtcNow; - - BuildWalls(); - - Players.SendTilesPacket(true, true); - - if (from != null) - Players.SendLocalizedMessage(1062696); // The dealer rebuilds the wall. - } - - public int GetStackLevel(MahjongPieceDim dim) - { - int level = -1; - foreach (MahjongTile tile in Tiles) - if (tile.StackLevel > level && dim.IsOverlapping(tile.Dimensions)) - level = tile.StackLevel; - return level; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write((int)Level); - - writer.Write(Tiles.Length); - - for (int i = 0; i < Tiles.Length; i++) - Tiles[i].Save(writer); - - DealerIndicator.Save(writer); - - WallBreakIndicator.Save(writer); - - Dices.Save(writer); - - Players.Save(writer); - - writer.Write(m_ShowScores); - writer.Write(m_SpectatorVision); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - Level = (SecureLevel)reader.ReadInt(); - - goto case 0; - } - case 0: - { - if (version < 1) - Level = SecureLevel.CoOwners; - - int length = reader.ReadInt(); - Tiles = new MahjongTile[length]; - - for (int i = 0; i < length; i++) - Tiles[i] = new MahjongTile(this, reader); - - DealerIndicator = new MahjongDealerIndicator(this, reader); - - WallBreakIndicator = new MahjongWallBreakIndicator(this, reader); - - Dices = new MahjongDices(this, reader); - - Players = new MahjongPlayers(this, reader); - - m_ShowScores = reader.ReadBool(); - m_SpectatorVision = reader.ReadBool(); - - m_LastReset = DateTime.UtcNow; - - break; - } - } - } - - private class ResetGameEntry : ContextMenuEntry - { - private readonly MahjongGame m_Game; - - public ResetGameEntry(MahjongGame game) : base(6162) => m_Game = game; - - public override void OnClick() - { - Mobile from = Owner.From; - - if (from.CheckAlive() && !m_Game.Deleted && m_Game.IsAccessibleTo(from) && - m_Game.Players.GetInGameMobiles(true, false).Count == 0) - m_Game.ResetGame(from); - } - } - } -} \ No newline at end of file +using System; +using System.Collections.Generic; +using Server.ContextMenus; +using Server.Gumps; +using Server.Multis; + +namespace Server.Engines.Mahjong +{ + public class MahjongGame : Item, ISecurable + { + public const int MaxPlayers = 4; + public const int BaseScore = 30000; + private DateTime m_LastReset; + + private bool m_ShowScores; + private bool m_SpectatorVision; + + [Constructible] + public MahjongGame() : base(0xFAA) + { + Weight = 5.0; + + BuildWalls(); + DealerIndicator = + new MahjongDealerIndicator(this, new Point2D(300, 300), MahjongPieceDirection.Up, MahjongWind.North); + WallBreakIndicator = new MahjongWallBreakIndicator(this, new Point2D(335, 335)); + Dices = new MahjongDices(this); + Players = new MahjongPlayers(this, MaxPlayers, BaseScore); + m_LastReset = DateTime.UtcNow; + Level = SecureLevel.CoOwners; + } + + public MahjongGame(Serial serial) : base(serial) + { + } + + public MahjongTile[] Tiles { get; private set; } + + public MahjongDealerIndicator DealerIndicator { get; private set; } + + public MahjongWallBreakIndicator WallBreakIndicator { get; private set; } + + public MahjongDices Dices { get; private set; } + + public MahjongPlayers Players { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool ShowScores + { + get => m_ShowScores; + set + { + if (m_ShowScores == value) + return; + + m_ShowScores = value; + + if (value) + Players.SendPlayersPacket(true, true); + + Players.SendGeneralPacket(true, true); + + Players.SendLocalizedMessage(value ? 1062777 : 1062778); // The dealer has enabled/disabled score display. + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool SpectatorVision + { + get => m_SpectatorVision; + set + { + if (m_SpectatorVision == value) + return; + + m_SpectatorVision = value; + + if (Players.IsInGamePlayer(Players.DealerPosition)) + Players.Dealer.Send(new MahjongGeneralInfo(this)); + + Players.SendTilesPacket(false, true); + + Players.SendLocalizedMessage(value ? 1062715 : 1062716); // The dealer has enabled/disabled Spectator Vision. + + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public SecureLevel Level { get; set; } + + private void BuildHorizontalWall( + ref int index, int x, int y, int stackLevel, MahjongPieceDirection direction, + MahjongTileTypeGenerator typeGenerator + ) + { + for (var i = 0; i < 17; i++) + { + var position = new Point2D(x + i * 20, y); + Tiles[index + i] = new MahjongTile( + this, + index + i, + typeGenerator.Next(), + position, + stackLevel, + direction, + false + ); + } + + index += 17; + } + + private void BuildVerticalWall( + ref int index, int x, int y, int stackLevel, MahjongPieceDirection direction, + MahjongTileTypeGenerator typeGenerator + ) + { + for (var i = 0; i < 17; i++) + { + var position = new Point2D(x, y + i * 20); + Tiles[index + i] = new MahjongTile( + this, + index + i, + typeGenerator.Next(), + position, + stackLevel, + direction, + false + ); + } + + index += 17; + } + + private void BuildWalls() + { + Tiles = new MahjongTile[136]; + + var typeGenerator = new MahjongTileTypeGenerator(); + + var i = 0; + + BuildHorizontalWall(ref i, 165, 110, 0, MahjongPieceDirection.Up, typeGenerator); + BuildHorizontalWall(ref i, 165, 115, 1, MahjongPieceDirection.Up, typeGenerator); + + BuildVerticalWall(ref i, 530, 165, 0, MahjongPieceDirection.Left, typeGenerator); + BuildVerticalWall(ref i, 525, 165, 1, MahjongPieceDirection.Left, typeGenerator); + + BuildHorizontalWall(ref i, 165, 530, 0, MahjongPieceDirection.Down, typeGenerator); + BuildHorizontalWall(ref i, 165, 525, 1, MahjongPieceDirection.Down, typeGenerator); + + BuildVerticalWall(ref i, 110, 165, 0, MahjongPieceDirection.Right, typeGenerator); + BuildVerticalWall(ref i, 115, 165, 1, MahjongPieceDirection.Right, typeGenerator); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_SpectatorVision) + list.Add(1062717); // Spectator Vision Enabled + else + list.Add(1062718); // Spectator Vision Disabled + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + Players.CheckPlayers(); + + if (from.Alive && IsAccessibleTo(from) && Players.GetInGameMobiles(true, false).Count == 0) + list.Add(new ResetGameEntry(this)); + + SetSecureLevelEntry.AddTo(from, this, list); + } + + public override void OnDoubleClick(Mobile from) + { + Players.CheckPlayers(); + + Players.Join(from); + } + + public void ResetGame(Mobile from) + { + if (DateTime.UtcNow - m_LastReset < TimeSpan.FromSeconds(5.0)) + return; + + m_LastReset = DateTime.UtcNow; + + if (from != null) + Players.SendLocalizedMessage(1062771, from.Name); // ~1_name~ has reset the game. + + Players.SendRelievePacket(true, true); + + BuildWalls(); + DealerIndicator = + new MahjongDealerIndicator(this, new Point2D(300, 300), MahjongPieceDirection.Up, MahjongWind.North); + WallBreakIndicator = new MahjongWallBreakIndicator(this, new Point2D(335, 335)); + Players = new MahjongPlayers(this, MaxPlayers, BaseScore); + } + + public void ResetWalls(Mobile from) + { + if (DateTime.UtcNow - m_LastReset < TimeSpan.FromSeconds(5.0)) + return; + + m_LastReset = DateTime.UtcNow; + + BuildWalls(); + + Players.SendTilesPacket(true, true); + + if (from != null) + Players.SendLocalizedMessage(1062696); // The dealer rebuilds the wall. + } + + public int GetStackLevel(MahjongPieceDim dim) + { + var level = -1; + foreach (var tile in Tiles) + if (tile.StackLevel > level && dim.IsOverlapping(tile.Dimensions)) + level = tile.StackLevel; + return level; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write((int)Level); + + writer.Write(Tiles.Length); + + for (var i = 0; i < Tiles.Length; i++) + Tiles[i].Save(writer); + + DealerIndicator.Save(writer); + + WallBreakIndicator.Save(writer); + + Dices.Save(writer); + + Players.Save(writer); + + writer.Write(m_ShowScores); + writer.Write(m_SpectatorVision); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + Level = (SecureLevel)reader.ReadInt(); + + goto case 0; + } + case 0: + { + if (version < 1) + Level = SecureLevel.CoOwners; + + var length = reader.ReadInt(); + Tiles = new MahjongTile[length]; + + for (var i = 0; i < length; i++) + Tiles[i] = new MahjongTile(this, reader); + + DealerIndicator = new MahjongDealerIndicator(this, reader); + + WallBreakIndicator = new MahjongWallBreakIndicator(this, reader); + + Dices = new MahjongDices(this, reader); + + Players = new MahjongPlayers(this, reader); + + m_ShowScores = reader.ReadBool(); + m_SpectatorVision = reader.ReadBool(); + + m_LastReset = DateTime.UtcNow; + + break; + } + } + } + + private class ResetGameEntry : ContextMenuEntry + { + private readonly MahjongGame m_Game; + + public ResetGameEntry(MahjongGame game) : base(6162) => m_Game = game; + + public override void OnClick() + { + var from = Owner.From; + + if (from.CheckAlive() && !m_Game.Deleted && m_Game.IsAccessibleTo(from) && + m_Game.Players.GetInGameMobiles(true, false).Count == 0) + m_Game.ResetGame(from); + } + } + } +} diff --git a/Projects/UOContent/Items/Games/Mahjong/MahjongPacketHandlers.cs b/Projects/UOContent/Items/Games/Mahjong/MahjongPacketHandlers.cs index eb5816ead..fac66c5b9 100644 --- a/Projects/UOContent/Items/Games/Mahjong/MahjongPacketHandlers.cs +++ b/Projects/UOContent/Items/Games/Mahjong/MahjongPacketHandlers.cs @@ -1,233 +1,233 @@ -using Server.Network; - -namespace Server.Engines.Mahjong -{ - public delegate void OnMahjongPacketReceive(MahjongGame game, NetState state, PacketReader pvSrc); - - public sealed class MahjongPacketHandlers - { - private static readonly OnMahjongPacketReceive[] m_SubCommandDelegates = new OnMahjongPacketReceive[0x100]; - - public static void RegisterSubCommand(int subCmd, OnMahjongPacketReceive onReceive) - { - m_SubCommandDelegates[subCmd] = onReceive; - } - - public static OnMahjongPacketReceive GetSubCommandDelegate(int cmd) - { - if (cmd >= 0 && cmd < 0x100) return m_SubCommandDelegates[cmd]; - - return null; - } - - public static void Initialize() - { - PacketHandlers.Register(0xDA, 0, true, OnPacket); - - RegisterSubCommand(0x6, ExitGame); - RegisterSubCommand(0xA, GivePoints); - RegisterSubCommand(0xB, RollDice); - RegisterSubCommand(0xC, BuildWalls); - RegisterSubCommand(0xD, ResetScores); - RegisterSubCommand(0xF, AssignDealer); - RegisterSubCommand(0x10, OpenSeat); - RegisterSubCommand(0x11, ChangeOption); - RegisterSubCommand(0x15, MoveWallBreakIndicator); - RegisterSubCommand(0x16, TogglePublicHand); - RegisterSubCommand(0x17, MoveTile); - RegisterSubCommand(0x18, MoveDealerIndicator); - } - - public static void OnPacket(NetState state, PacketReader pvSrc) - { - MahjongGame game = World.FindItem(pvSrc.ReadUInt32()) as MahjongGame; - - game?.Players.CheckPlayers(); - - pvSrc.ReadByte(); - - int cmd = pvSrc.ReadByte(); - - OnMahjongPacketReceive onReceive = GetSubCommandDelegate(cmd); - - if (onReceive != null) - onReceive(game, state, pvSrc); - else - pvSrc.Trace(state); - } - - private static MahjongPieceDirection GetDirection(int value) - { - return value switch - { - 0 => MahjongPieceDirection.Up, - 1 => MahjongPieceDirection.Left, - 2 => MahjongPieceDirection.Down, - _ => MahjongPieceDirection.Right - }; - } - - private static MahjongWind GetWind(int value) - { - return value switch - { - 0 => MahjongWind.North, - 1 => MahjongWind.East, - 2 => MahjongWind.South, - _ => MahjongWind.West - }; - } - - public static void ExitGame(MahjongGame game, NetState state, PacketReader pvSrc) - { - if (game == null) - return; - - Mobile from = state.Mobile; - - game.Players.LeaveGame(from); - } - - public static void GivePoints(MahjongGame game, NetState state, PacketReader pvSrc) - { - if (game?.Players.IsInGamePlayer(state.Mobile) != true) - return; - - int to = pvSrc.ReadByte(); - int amount = pvSrc.ReadInt32(); - - game.Players.TransferScore(state.Mobile, to, amount); - } - - public static void RollDice(MahjongGame game, NetState state, PacketReader pvSrc) - { - if (game?.Players.IsInGamePlayer(state.Mobile) != true) - return; - - game.Dices.RollDices(state.Mobile); - } - - public static void BuildWalls(MahjongGame game, NetState state, PacketReader pvSrc) - { - if (game?.Players.IsInGameDealer(state.Mobile) != true) - return; - - game.ResetWalls(state.Mobile); - } - - public static void ResetScores(MahjongGame game, NetState state, PacketReader pvSrc) - { - if (game?.Players.IsInGameDealer(state.Mobile) != true) - return; - - game.Players.ResetScores(MahjongGame.BaseScore); - } - - public static void AssignDealer(MahjongGame game, NetState state, PacketReader pvSrc) - { - if (game?.Players.IsInGameDealer(state.Mobile) != true) - return; - - int position = pvSrc.ReadByte(); - - game.Players.AssignDealer(position); - } - - public static void OpenSeat(MahjongGame game, NetState state, PacketReader pvSrc) - { - if (game?.Players.IsInGameDealer(state.Mobile) != true) - return; - - int position = pvSrc.ReadByte(); - - if (game.Players.GetPlayer(position) == state.Mobile) - return; - - game.Players.OpenSeat(position); - } - - public static void ChangeOption(MahjongGame game, NetState state, PacketReader pvSrc) - { - if (game?.Players.IsInGameDealer(state.Mobile) != true) - return; - - pvSrc.ReadInt16(); - pvSrc.ReadByte(); - - int options = pvSrc.ReadByte(); - - game.ShowScores = (options & 0x1) != 0; - game.SpectatorVision = (options & 0x2) != 0; - } - - public static void MoveWallBreakIndicator(MahjongGame game, NetState state, PacketReader pvSrc) - { - if (game?.Players.IsInGameDealer(state.Mobile) != true) - return; - - int y = pvSrc.ReadInt16(); - int x = pvSrc.ReadInt16(); - - game.WallBreakIndicator.Move(new Point2D(x, y)); - } - - public static void TogglePublicHand(MahjongGame game, NetState state, PacketReader pvSrc) - { - if (game?.Players.IsInGamePlayer(state.Mobile) != true) - return; - - pvSrc.ReadInt16(); - pvSrc.ReadByte(); - - bool publicHand = pvSrc.ReadBoolean(); - - game.Players.SetPublic(game.Players.GetPlayerIndex(state.Mobile), publicHand); - } - - public static void MoveTile(MahjongGame game, NetState state, PacketReader pvSrc) - { - if (game?.Players.IsInGamePlayer(state.Mobile) != true) - return; - - int number = pvSrc.ReadByte(); - - if (number < 0 || number >= game.Tiles.Length) - return; - - pvSrc.ReadByte(); // Current direction - - MahjongPieceDirection direction = GetDirection(pvSrc.ReadByte()); - - pvSrc.ReadByte(); - - bool flip = pvSrc.ReadBoolean(); - - pvSrc.ReadInt16(); // Current Y - pvSrc.ReadInt16(); // Current X - - pvSrc.ReadByte(); - - int y = pvSrc.ReadInt16(); - int x = pvSrc.ReadInt16(); - - pvSrc.ReadByte(); - - game.Tiles[number].Move(new Point2D(x, y), direction, flip, game.Players.GetPlayerIndex(state.Mobile)); - } - - public static void MoveDealerIndicator(MahjongGame game, NetState state, PacketReader pvSrc) - { - if (game?.Players.IsInGameDealer(state.Mobile) != true) - return; - - MahjongPieceDirection direction = GetDirection(pvSrc.ReadByte()); - - MahjongWind wind = GetWind(pvSrc.ReadByte()); - - int y = pvSrc.ReadInt16(); - int x = pvSrc.ReadInt16(); - - game.DealerIndicator.Move(new Point2D(x, y), direction, wind); - } - } -} \ No newline at end of file +using Server.Network; + +namespace Server.Engines.Mahjong +{ + public delegate void OnMahjongPacketReceive(MahjongGame game, NetState state, PacketReader pvSrc); + + public sealed class MahjongPacketHandlers + { + private static readonly OnMahjongPacketReceive[] m_SubCommandDelegates = new OnMahjongPacketReceive[0x100]; + + public static void RegisterSubCommand(int subCmd, OnMahjongPacketReceive onReceive) + { + m_SubCommandDelegates[subCmd] = onReceive; + } + + public static OnMahjongPacketReceive GetSubCommandDelegate(int cmd) + { + if (cmd >= 0 && cmd < 0x100) return m_SubCommandDelegates[cmd]; + + return null; + } + + public static void Initialize() + { + PacketHandlers.Register(0xDA, 0, true, OnPacket); + + RegisterSubCommand(0x6, ExitGame); + RegisterSubCommand(0xA, GivePoints); + RegisterSubCommand(0xB, RollDice); + RegisterSubCommand(0xC, BuildWalls); + RegisterSubCommand(0xD, ResetScores); + RegisterSubCommand(0xF, AssignDealer); + RegisterSubCommand(0x10, OpenSeat); + RegisterSubCommand(0x11, ChangeOption); + RegisterSubCommand(0x15, MoveWallBreakIndicator); + RegisterSubCommand(0x16, TogglePublicHand); + RegisterSubCommand(0x17, MoveTile); + RegisterSubCommand(0x18, MoveDealerIndicator); + } + + public static void OnPacket(NetState state, PacketReader pvSrc) + { + var game = World.FindItem(pvSrc.ReadUInt32()) as MahjongGame; + + game?.Players.CheckPlayers(); + + pvSrc.ReadByte(); + + int cmd = pvSrc.ReadByte(); + + var onReceive = GetSubCommandDelegate(cmd); + + if (onReceive != null) + onReceive(game, state, pvSrc); + else + pvSrc.Trace(state); + } + + private static MahjongPieceDirection GetDirection(int value) + { + return value switch + { + 0 => MahjongPieceDirection.Up, + 1 => MahjongPieceDirection.Left, + 2 => MahjongPieceDirection.Down, + _ => MahjongPieceDirection.Right + }; + } + + private static MahjongWind GetWind(int value) + { + return value switch + { + 0 => MahjongWind.North, + 1 => MahjongWind.East, + 2 => MahjongWind.South, + _ => MahjongWind.West + }; + } + + public static void ExitGame(MahjongGame game, NetState state, PacketReader pvSrc) + { + if (game == null) + return; + + var from = state.Mobile; + + game.Players.LeaveGame(from); + } + + public static void GivePoints(MahjongGame game, NetState state, PacketReader pvSrc) + { + if (game?.Players.IsInGamePlayer(state.Mobile) != true) + return; + + int to = pvSrc.ReadByte(); + var amount = pvSrc.ReadInt32(); + + game.Players.TransferScore(state.Mobile, to, amount); + } + + public static void RollDice(MahjongGame game, NetState state, PacketReader pvSrc) + { + if (game?.Players.IsInGamePlayer(state.Mobile) != true) + return; + + game.Dices.RollDices(state.Mobile); + } + + public static void BuildWalls(MahjongGame game, NetState state, PacketReader pvSrc) + { + if (game?.Players.IsInGameDealer(state.Mobile) != true) + return; + + game.ResetWalls(state.Mobile); + } + + public static void ResetScores(MahjongGame game, NetState state, PacketReader pvSrc) + { + if (game?.Players.IsInGameDealer(state.Mobile) != true) + return; + + game.Players.ResetScores(MahjongGame.BaseScore); + } + + public static void AssignDealer(MahjongGame game, NetState state, PacketReader pvSrc) + { + if (game?.Players.IsInGameDealer(state.Mobile) != true) + return; + + int position = pvSrc.ReadByte(); + + game.Players.AssignDealer(position); + } + + public static void OpenSeat(MahjongGame game, NetState state, PacketReader pvSrc) + { + if (game?.Players.IsInGameDealer(state.Mobile) != true) + return; + + int position = pvSrc.ReadByte(); + + if (game.Players.GetPlayer(position) == state.Mobile) + return; + + game.Players.OpenSeat(position); + } + + public static void ChangeOption(MahjongGame game, NetState state, PacketReader pvSrc) + { + if (game?.Players.IsInGameDealer(state.Mobile) != true) + return; + + pvSrc.ReadInt16(); + pvSrc.ReadByte(); + + int options = pvSrc.ReadByte(); + + game.ShowScores = (options & 0x1) != 0; + game.SpectatorVision = (options & 0x2) != 0; + } + + public static void MoveWallBreakIndicator(MahjongGame game, NetState state, PacketReader pvSrc) + { + if (game?.Players.IsInGameDealer(state.Mobile) != true) + return; + + int y = pvSrc.ReadInt16(); + int x = pvSrc.ReadInt16(); + + game.WallBreakIndicator.Move(new Point2D(x, y)); + } + + public static void TogglePublicHand(MahjongGame game, NetState state, PacketReader pvSrc) + { + if (game?.Players.IsInGamePlayer(state.Mobile) != true) + return; + + pvSrc.ReadInt16(); + pvSrc.ReadByte(); + + var publicHand = pvSrc.ReadBoolean(); + + game.Players.SetPublic(game.Players.GetPlayerIndex(state.Mobile), publicHand); + } + + public static void MoveTile(MahjongGame game, NetState state, PacketReader pvSrc) + { + if (game?.Players.IsInGamePlayer(state.Mobile) != true) + return; + + int number = pvSrc.ReadByte(); + + if (number < 0 || number >= game.Tiles.Length) + return; + + pvSrc.ReadByte(); // Current direction + + var direction = GetDirection(pvSrc.ReadByte()); + + pvSrc.ReadByte(); + + var flip = pvSrc.ReadBoolean(); + + pvSrc.ReadInt16(); // Current Y + pvSrc.ReadInt16(); // Current X + + pvSrc.ReadByte(); + + int y = pvSrc.ReadInt16(); + int x = pvSrc.ReadInt16(); + + pvSrc.ReadByte(); + + game.Tiles[number].Move(new Point2D(x, y), direction, flip, game.Players.GetPlayerIndex(state.Mobile)); + } + + public static void MoveDealerIndicator(MahjongGame game, NetState state, PacketReader pvSrc) + { + if (game?.Players.IsInGameDealer(state.Mobile) != true) + return; + + var direction = GetDirection(pvSrc.ReadByte()); + + var wind = GetWind(pvSrc.ReadByte()); + + int y = pvSrc.ReadInt16(); + int x = pvSrc.ReadInt16(); + + game.DealerIndicator.Move(new Point2D(x, y), direction, wind); + } + } +} diff --git a/Projects/UOContent/Items/Games/Mahjong/MahjongPieceDim.cs b/Projects/UOContent/Items/Games/Mahjong/MahjongPieceDim.cs index 2a4248cda..e58b2fe1d 100644 --- a/Projects/UOContent/Items/Games/Mahjong/MahjongPieceDim.cs +++ b/Projects/UOContent/Items/Games/Mahjong/MahjongPieceDim.cs @@ -1,41 +1,42 @@ -namespace Server.Engines.Mahjong -{ - public struct MahjongPieceDim - { - public Point2D Position { get; } - - public int Width { get; } - - public int Height { get; } - - public MahjongPieceDim(Point2D position, int width, int height) - { - Position = position; - Width = width; - Height = height; - } - - public bool IsValid() => Position.X >= 0 && Position.Y >= 0 && Position.X + Width <= 670 && Position.Y + Height <= 670; - - public bool IsOverlapping(MahjongPieceDim dim) => - Position.X < dim.Position.X + dim.Width && Position.Y < dim.Position.Y + dim.Height && - Position.X + Width > dim.Position.X && Position.Y + Height > dim.Position.Y; - - public int GetHandArea() - { - if (Position.X + Width > 150 && Position.X < 520 && Position.Y < 35) - return 0; - - if (Position.X + Width > 635 && Position.Y + Height > 150 && Position.Y < 520) - return 1; - - if (Position.X + Width > 150 && Position.X < 520 && Position.Y + Height > 635) - return 2; - - if (Position.X < 35 && Position.Y + Height > 150 && Position.Y < 520) - return 3; - - return -1; - } - } -} \ No newline at end of file +namespace Server.Engines.Mahjong +{ + public struct MahjongPieceDim + { + public Point2D Position { get; } + + public int Width { get; } + + public int Height { get; } + + public MahjongPieceDim(Point2D position, int width, int height) + { + Position = position; + Width = width; + Height = height; + } + + public bool IsValid() => + Position.X >= 0 && Position.Y >= 0 && Position.X + Width <= 670 && Position.Y + Height <= 670; + + public bool IsOverlapping(MahjongPieceDim dim) => + Position.X < dim.Position.X + dim.Width && Position.Y < dim.Position.Y + dim.Height && + Position.X + Width > dim.Position.X && Position.Y + Height > dim.Position.Y; + + public int GetHandArea() + { + if (Position.X + Width > 150 && Position.X < 520 && Position.Y < 35) + return 0; + + if (Position.X + Width > 635 && Position.Y + Height > 150 && Position.Y < 520) + return 1; + + if (Position.X + Width > 150 && Position.X < 520 && Position.Y + Height > 635) + return 2; + + if (Position.X < 35 && Position.Y + Height > 150 && Position.Y < 520) + return 3; + + return -1; + } + } +} diff --git a/Projects/UOContent/Items/Games/Mahjong/MahjongPlayers.cs b/Projects/UOContent/Items/Games/Mahjong/MahjongPlayers.cs index 18697cf8c..40c8ba452 100644 --- a/Projects/UOContent/Items/Games/Mahjong/MahjongPlayers.cs +++ b/Projects/UOContent/Items/Games/Mahjong/MahjongPlayers.cs @@ -1,502 +1,504 @@ -using System.Collections.Generic; - -namespace Server.Engines.Mahjong -{ - public class MahjongPlayers - { - private readonly bool[] m_InGame; - private readonly Mobile[] m_Players; - private readonly bool[] m_PublicHand; - private readonly int[] m_Scores; - private readonly List m_Spectators; - - public MahjongPlayers(MahjongGame game, int maxPlayers, int baseScore) - { - Game = game; - m_Spectators = new List(); - - m_Players = new Mobile[maxPlayers]; - m_InGame = new bool[maxPlayers]; - m_PublicHand = new bool[maxPlayers]; - m_Scores = new int[maxPlayers]; - - for (int i = 0; i < m_Scores.Length; i++) - m_Scores[i] = baseScore; - } - - public MahjongPlayers(MahjongGame game, IGenericReader reader) - { - Game = game; - m_Spectators = new List(); - - int version = reader.ReadInt(); - - int seats = reader.ReadInt(); - m_Players = new Mobile[seats]; - m_InGame = new bool[seats]; - m_PublicHand = new bool[seats]; - m_Scores = new int[seats]; - - for (int i = 0; i < seats; i++) - { - m_Players[i] = reader.ReadMobile(); - m_PublicHand[i] = reader.ReadBool(); - m_Scores[i] = reader.ReadInt(); - } - - DealerPosition = reader.ReadInt(); - } - - public MahjongGame Game { get; } - - public int Seats => m_Players.Length; - public Mobile Dealer => m_Players[DealerPosition]; - public int DealerPosition { get; private set; } - - public Mobile GetPlayer(int index) - { - if (index < 0 || index >= m_Players.Length) - return null; - return m_Players[index]; - } - - public int GetPlayerIndex(Mobile mobile) - { - for (int i = 0; i < m_Players.Length; i++) - if (m_Players[i] == mobile) - return i; - return -1; - } - - public bool IsInGameDealer(Mobile mobile) - { - if (Dealer != mobile) - return false; - return m_InGame[DealerPosition]; - } - - public bool IsInGamePlayer(int index) - { - if (index < 0 || index >= m_Players.Length || m_Players[index] == null) - return false; - return m_InGame[index]; - } - - public bool IsInGamePlayer(Mobile mobile) - { - int index = GetPlayerIndex(mobile); - - return IsInGamePlayer(index); - } - - public bool IsSpectator(Mobile mobile) => m_Spectators.Contains(mobile); - - public int GetScore(int index) - { - if (index < 0 || index >= m_Scores.Length) - return 0; - return m_Scores[index]; - } - - public bool IsPublic(int index) - { - if (index < 0 || index >= m_PublicHand.Length) - return false; - return m_PublicHand[index]; - } - - public void SetPublic(int index, bool value) - { - if (index < 0 || index >= m_PublicHand.Length || m_PublicHand[index] == value) - return; - - m_PublicHand[index] = value; - - SendTilesPacket(true, !Game.SpectatorVision); - - if (IsInGamePlayer(index)) - m_Players[index].SendLocalizedMessage(value ? 1062775 : 1062776); // Your hand is [not] publicly viewable. - } - - public List GetInGameMobiles(bool players, bool spectators) - { - List list = new List(); - - if (players) - for (int i = 0; i < m_Players.Length; i++) - if (IsInGamePlayer(i)) - list.Add(m_Players[i]); - - if (spectators) - list.AddRange(m_Spectators); - - return list; - } - - public void CheckPlayers() - { - bool removed = false; - - for (int i = 0; i < m_Players.Length; i++) - { - Mobile player = m_Players[i]; - - if (player == null) - continue; - - if (player.Deleted) - { - m_Players[i] = null; - - SendPlayerExitMessage(player); - UpdateDealer(true); - - removed = true; - } - else if (m_InGame[i]) - { - if (player.NetState == null) - { - m_InGame[i] = false; - - SendPlayerExitMessage(player); - UpdateDealer(true); - - removed = true; - } - else if (!Game.IsAccessibleTo(player) || player.Map != Game.Map || - !player.InRange(Game.GetWorldLocation(), 5)) - { - m_InGame[i] = false; - - player.Send(new MahjongRelieve(Game)); - - SendPlayerExitMessage(player); - UpdateDealer(true); - - removed = true; - } - } - } - - for (int i = 0; i < m_Spectators.Count;) - { - Mobile mobile = m_Spectators[i]; - - if (mobile.NetState == null || mobile.Deleted) - { - m_Spectators.RemoveAt(i); - } - else if (!Game.IsAccessibleTo(mobile) || mobile.Map != Game.Map || - !mobile.InRange(Game.GetWorldLocation(), 5)) - { - m_Spectators.RemoveAt(i); - - mobile.Send(new MahjongRelieve(Game)); - } - else - { - i++; - } - } - - if (removed && !UpdateSpectators()) - SendPlayersPacket(true, true); - } - - private void UpdateDealer(bool message) - { - if (IsInGamePlayer(DealerPosition)) - return; - - for (int i = DealerPosition + 1; i < m_Players.Length; i++) - if (IsInGamePlayer(i)) - { - DealerPosition = i; - - if (message) - SendDealerChangedMessage(); - - return; - } - - for (int i = 0; i < DealerPosition; i++) - if (IsInGamePlayer(i)) - { - DealerPosition = i; - - if (message) - SendDealerChangedMessage(); - - return; - } - } - - private int GetNextSeat() - { - for (int i = DealerPosition; i < m_Players.Length; i++) - if (m_Players[i] == null) - return i; - - for (int i = 0; i < DealerPosition; i++) - if (m_Players[i] == null) - return i; - - return -1; - } - - private bool UpdateSpectators() - { - if (m_Spectators.Count == 0) - return false; - - int nextSeat = GetNextSeat(); - - if (nextSeat >= 0) - { - Mobile newPlayer = m_Spectators[0]; - - m_Spectators.RemoveAt(0); - - AddPlayer(newPlayer, nextSeat, false); - - UpdateSpectators(); - - return true; - } - - return false; - } - - private void AddPlayer(Mobile player, int index, bool sendJoinGame) - { - m_Players[index] = player; - m_InGame[index] = true; - - UpdateDealer(false); - - if (sendJoinGame) - player.Send(new MahjongJoinGame(Game)); - - SendPlayersPacket(true, true); - - player.Send(new MahjongGeneralInfo(Game)); - player.Send(new MahjongTilesInfo(Game, player)); - - if (DealerPosition == index) - SendLocalizedMessage(1062773, player.Name); // ~1_name~ has entered the game as the dealer. - else - SendLocalizedMessage(1062772, player.Name); // ~1_name~ has entered the game as a player. - } - - private void AddSpectator(Mobile mobile) - { - if (!IsSpectator(mobile)) m_Spectators.Add(mobile); - - mobile.Send(new MahjongJoinGame(Game)); - mobile.Send(new MahjongPlayersInfo(Game, mobile)); - mobile.Send(new MahjongGeneralInfo(Game)); - mobile.Send(new MahjongTilesInfo(Game, mobile)); - } - - public void Join(Mobile mobile) - { - int index = GetPlayerIndex(mobile); - - if (index >= 0) - { - AddPlayer(mobile, index, true); - } - else - { - int nextSeat = GetNextSeat(); - - if (nextSeat >= 0) - AddPlayer(mobile, nextSeat, true); - else - AddSpectator(mobile); - } - } - - public void LeaveGame(Mobile player) - { - int index = GetPlayerIndex(player); - if (index >= 0) - { - m_InGame[index] = false; - - SendPlayerExitMessage(player); - UpdateDealer(true); - - SendPlayersPacket(true, true); - } - else - { - m_Spectators.Remove(player); - } - } - - public void ResetScores(int value) - { - for (int i = 0; i < m_Scores.Length; i++) m_Scores[i] = value; - - SendPlayersPacket(true, Game.ShowScores); - - SendLocalizedMessage(1062697); // The dealer redistributes the score sticks evenly. - } - - public void TransferScore(Mobile from, int toPosition, int amount) - { - int fromPosition = GetPlayerIndex(from); - Mobile to = GetPlayer(toPosition); - - if (fromPosition < 0 || to == null || m_Scores[fromPosition] < amount) - return; - - m_Scores[fromPosition] -= amount; - m_Scores[toPosition] += amount; - - if (Game.ShowScores) - { - SendPlayersPacket(true, true); - } - else - { - from.Send(new MahjongPlayersInfo(Game, from)); - to.Send(new MahjongPlayersInfo(Game, to)); - } - - SendLocalizedMessage(1062774, - $"{from.Name}\t{to.Name}\t{amount}"); // ~1_giver~ gives ~2_receiver~ ~3_number~ points. - } - - public void OpenSeat(int index) - { - Mobile player = GetPlayer(index); - if (player == null) - return; - - if (m_InGame[index]) - player.Send(new MahjongRelieve(Game)); - - m_Players[index] = null; - - SendLocalizedMessage(1062699, player.Name); // ~1_name~ is relieved from the game by the dealer. - - UpdateDealer(true); - - if (!UpdateSpectators()) - SendPlayersPacket(true, true); - } - - public void AssignDealer(int index) - { - Mobile to = GetPlayer(index); - - if (to == null || !m_InGame[index]) - return; - - int oldDealer = DealerPosition; - - DealerPosition = index; - - if (IsInGamePlayer(oldDealer)) - m_Players[oldDealer].Send(new MahjongPlayersInfo(Game, m_Players[oldDealer])); - - to.Send(new MahjongPlayersInfo(Game, to)); - - SendDealerChangedMessage(); - } - - private void SendDealerChangedMessage() - { - if (Dealer != null) - SendLocalizedMessage(1062698, Dealer.Name); // ~1_name~ is assigned the dealer. - } - - private void SendPlayerExitMessage(Mobile who) - { - SendLocalizedMessage(1062762, who.Name); // ~1_name~ has left the game. - } - - public void SendPlayersPacket(bool players, bool spectators) - { - foreach (Mobile mobile in GetInGameMobiles(players, spectators)) - mobile.Send(new MahjongPlayersInfo(Game, mobile)); - } - - public void SendGeneralPacket(bool players, bool spectators) - { - List mobiles = GetInGameMobiles(players, spectators); - - if (mobiles.Count == 0) - return; - - MahjongGeneralInfo generalInfo = new MahjongGeneralInfo(Game); - - generalInfo.Acquire(); - - foreach (Mobile mobile in mobiles) - mobile.Send(generalInfo); - - generalInfo.Release(); - } - - public void SendTilesPacket(bool players, bool spectators) - { - foreach (Mobile mobile in GetInGameMobiles(players, spectators)) - mobile.Send(new MahjongTilesInfo(Game, mobile)); - } - - public void SendTilePacket(MahjongTile tile, bool players, bool spectators) - { - foreach (Mobile mobile in GetInGameMobiles(players, spectators)) - mobile.Send(new MahjongTileInfo(tile, mobile)); - } - - public void SendRelievePacket(bool players, bool spectators) - { - List mobiles = GetInGameMobiles(players, spectators); - - if (mobiles.Count == 0) - return; - - MahjongRelieve relieve = new MahjongRelieve(Game); - - relieve.Acquire(); - - foreach (Mobile mobile in mobiles) - mobile.Send(relieve); - - relieve.Release(); - } - - public void SendLocalizedMessage(int number) - { - foreach (Mobile mobile in GetInGameMobiles(true, true)) - mobile.SendLocalizedMessage(number); - } - - public void SendLocalizedMessage(int number, string args) - { - foreach (Mobile mobile in GetInGameMobiles(true, true)) - mobile.SendLocalizedMessage(number, args); - } - - public void Save(IGenericWriter writer) - { - writer.Write(0); // version - - writer.Write(Seats); - - for (int i = 0; i < Seats; i++) - { - writer.Write(m_Players[i]); - writer.Write(m_PublicHand[i]); - writer.Write(m_Scores[i]); - } - - writer.Write(DealerPosition); - } - } -} +using System.Collections.Generic; + +namespace Server.Engines.Mahjong +{ + public class MahjongPlayers + { + private readonly bool[] m_InGame; + private readonly Mobile[] m_Players; + private readonly bool[] m_PublicHand; + private readonly int[] m_Scores; + private readonly List m_Spectators; + + public MahjongPlayers(MahjongGame game, int maxPlayers, int baseScore) + { + Game = game; + m_Spectators = new List(); + + m_Players = new Mobile[maxPlayers]; + m_InGame = new bool[maxPlayers]; + m_PublicHand = new bool[maxPlayers]; + m_Scores = new int[maxPlayers]; + + for (var i = 0; i < m_Scores.Length; i++) + m_Scores[i] = baseScore; + } + + public MahjongPlayers(MahjongGame game, IGenericReader reader) + { + Game = game; + m_Spectators = new List(); + + var version = reader.ReadInt(); + + var seats = reader.ReadInt(); + m_Players = new Mobile[seats]; + m_InGame = new bool[seats]; + m_PublicHand = new bool[seats]; + m_Scores = new int[seats]; + + for (var i = 0; i < seats; i++) + { + m_Players[i] = reader.ReadMobile(); + m_PublicHand[i] = reader.ReadBool(); + m_Scores[i] = reader.ReadInt(); + } + + DealerPosition = reader.ReadInt(); + } + + public MahjongGame Game { get; } + + public int Seats => m_Players.Length; + public Mobile Dealer => m_Players[DealerPosition]; + public int DealerPosition { get; private set; } + + public Mobile GetPlayer(int index) + { + if (index < 0 || index >= m_Players.Length) + return null; + return m_Players[index]; + } + + public int GetPlayerIndex(Mobile mobile) + { + for (var i = 0; i < m_Players.Length; i++) + if (m_Players[i] == mobile) + return i; + return -1; + } + + public bool IsInGameDealer(Mobile mobile) + { + if (Dealer != mobile) + return false; + return m_InGame[DealerPosition]; + } + + public bool IsInGamePlayer(int index) + { + if (index < 0 || index >= m_Players.Length || m_Players[index] == null) + return false; + return m_InGame[index]; + } + + public bool IsInGamePlayer(Mobile mobile) + { + var index = GetPlayerIndex(mobile); + + return IsInGamePlayer(index); + } + + public bool IsSpectator(Mobile mobile) => m_Spectators.Contains(mobile); + + public int GetScore(int index) + { + if (index < 0 || index >= m_Scores.Length) + return 0; + return m_Scores[index]; + } + + public bool IsPublic(int index) + { + if (index < 0 || index >= m_PublicHand.Length) + return false; + return m_PublicHand[index]; + } + + public void SetPublic(int index, bool value) + { + if (index < 0 || index >= m_PublicHand.Length || m_PublicHand[index] == value) + return; + + m_PublicHand[index] = value; + + SendTilesPacket(true, !Game.SpectatorVision); + + if (IsInGamePlayer(index)) + m_Players[index].SendLocalizedMessage(value ? 1062775 : 1062776); // Your hand is [not] publicly viewable. + } + + public List GetInGameMobiles(bool players, bool spectators) + { + var list = new List(); + + if (players) + for (var i = 0; i < m_Players.Length; i++) + if (IsInGamePlayer(i)) + list.Add(m_Players[i]); + + if (spectators) + list.AddRange(m_Spectators); + + return list; + } + + public void CheckPlayers() + { + var removed = false; + + for (var i = 0; i < m_Players.Length; i++) + { + var player = m_Players[i]; + + if (player == null) + continue; + + if (player.Deleted) + { + m_Players[i] = null; + + SendPlayerExitMessage(player); + UpdateDealer(true); + + removed = true; + } + else if (m_InGame[i]) + { + if (player.NetState == null) + { + m_InGame[i] = false; + + SendPlayerExitMessage(player); + UpdateDealer(true); + + removed = true; + } + else if (!Game.IsAccessibleTo(player) || player.Map != Game.Map || + !player.InRange(Game.GetWorldLocation(), 5)) + { + m_InGame[i] = false; + + player.Send(new MahjongRelieve(Game)); + + SendPlayerExitMessage(player); + UpdateDealer(true); + + removed = true; + } + } + } + + for (var i = 0; i < m_Spectators.Count;) + { + var mobile = m_Spectators[i]; + + if (mobile.NetState == null || mobile.Deleted) + { + m_Spectators.RemoveAt(i); + } + else if (!Game.IsAccessibleTo(mobile) || mobile.Map != Game.Map || + !mobile.InRange(Game.GetWorldLocation(), 5)) + { + m_Spectators.RemoveAt(i); + + mobile.Send(new MahjongRelieve(Game)); + } + else + { + i++; + } + } + + if (removed && !UpdateSpectators()) + SendPlayersPacket(true, true); + } + + private void UpdateDealer(bool message) + { + if (IsInGamePlayer(DealerPosition)) + return; + + for (var i = DealerPosition + 1; i < m_Players.Length; i++) + if (IsInGamePlayer(i)) + { + DealerPosition = i; + + if (message) + SendDealerChangedMessage(); + + return; + } + + for (var i = 0; i < DealerPosition; i++) + if (IsInGamePlayer(i)) + { + DealerPosition = i; + + if (message) + SendDealerChangedMessage(); + + return; + } + } + + private int GetNextSeat() + { + for (var i = DealerPosition; i < m_Players.Length; i++) + if (m_Players[i] == null) + return i; + + for (var i = 0; i < DealerPosition; i++) + if (m_Players[i] == null) + return i; + + return -1; + } + + private bool UpdateSpectators() + { + if (m_Spectators.Count == 0) + return false; + + var nextSeat = GetNextSeat(); + + if (nextSeat >= 0) + { + var newPlayer = m_Spectators[0]; + + m_Spectators.RemoveAt(0); + + AddPlayer(newPlayer, nextSeat, false); + + UpdateSpectators(); + + return true; + } + + return false; + } + + private void AddPlayer(Mobile player, int index, bool sendJoinGame) + { + m_Players[index] = player; + m_InGame[index] = true; + + UpdateDealer(false); + + if (sendJoinGame) + player.Send(new MahjongJoinGame(Game)); + + SendPlayersPacket(true, true); + + player.Send(new MahjongGeneralInfo(Game)); + player.Send(new MahjongTilesInfo(Game, player)); + + if (DealerPosition == index) + SendLocalizedMessage(1062773, player.Name); // ~1_name~ has entered the game as the dealer. + else + SendLocalizedMessage(1062772, player.Name); // ~1_name~ has entered the game as a player. + } + + private void AddSpectator(Mobile mobile) + { + if (!IsSpectator(mobile)) m_Spectators.Add(mobile); + + mobile.Send(new MahjongJoinGame(Game)); + mobile.Send(new MahjongPlayersInfo(Game, mobile)); + mobile.Send(new MahjongGeneralInfo(Game)); + mobile.Send(new MahjongTilesInfo(Game, mobile)); + } + + public void Join(Mobile mobile) + { + var index = GetPlayerIndex(mobile); + + if (index >= 0) + { + AddPlayer(mobile, index, true); + } + else + { + var nextSeat = GetNextSeat(); + + if (nextSeat >= 0) + AddPlayer(mobile, nextSeat, true); + else + AddSpectator(mobile); + } + } + + public void LeaveGame(Mobile player) + { + var index = GetPlayerIndex(player); + if (index >= 0) + { + m_InGame[index] = false; + + SendPlayerExitMessage(player); + UpdateDealer(true); + + SendPlayersPacket(true, true); + } + else + { + m_Spectators.Remove(player); + } + } + + public void ResetScores(int value) + { + for (var i = 0; i < m_Scores.Length; i++) m_Scores[i] = value; + + SendPlayersPacket(true, Game.ShowScores); + + SendLocalizedMessage(1062697); // The dealer redistributes the score sticks evenly. + } + + public void TransferScore(Mobile from, int toPosition, int amount) + { + var fromPosition = GetPlayerIndex(from); + var to = GetPlayer(toPosition); + + if (fromPosition < 0 || to == null || m_Scores[fromPosition] < amount) + return; + + m_Scores[fromPosition] -= amount; + m_Scores[toPosition] += amount; + + if (Game.ShowScores) + { + SendPlayersPacket(true, true); + } + else + { + from.Send(new MahjongPlayersInfo(Game, from)); + to.Send(new MahjongPlayersInfo(Game, to)); + } + + SendLocalizedMessage( + 1062774, + $"{from.Name}\t{to.Name}\t{amount}" + ); // ~1_giver~ gives ~2_receiver~ ~3_number~ points. + } + + public void OpenSeat(int index) + { + var player = GetPlayer(index); + if (player == null) + return; + + if (m_InGame[index]) + player.Send(new MahjongRelieve(Game)); + + m_Players[index] = null; + + SendLocalizedMessage(1062699, player.Name); // ~1_name~ is relieved from the game by the dealer. + + UpdateDealer(true); + + if (!UpdateSpectators()) + SendPlayersPacket(true, true); + } + + public void AssignDealer(int index) + { + var to = GetPlayer(index); + + if (to == null || !m_InGame[index]) + return; + + var oldDealer = DealerPosition; + + DealerPosition = index; + + if (IsInGamePlayer(oldDealer)) + m_Players[oldDealer].Send(new MahjongPlayersInfo(Game, m_Players[oldDealer])); + + to.Send(new MahjongPlayersInfo(Game, to)); + + SendDealerChangedMessage(); + } + + private void SendDealerChangedMessage() + { + if (Dealer != null) + SendLocalizedMessage(1062698, Dealer.Name); // ~1_name~ is assigned the dealer. + } + + private void SendPlayerExitMessage(Mobile who) + { + SendLocalizedMessage(1062762, who.Name); // ~1_name~ has left the game. + } + + public void SendPlayersPacket(bool players, bool spectators) + { + foreach (var mobile in GetInGameMobiles(players, spectators)) + mobile.Send(new MahjongPlayersInfo(Game, mobile)); + } + + public void SendGeneralPacket(bool players, bool spectators) + { + var mobiles = GetInGameMobiles(players, spectators); + + if (mobiles.Count == 0) + return; + + var generalInfo = new MahjongGeneralInfo(Game); + + generalInfo.Acquire(); + + foreach (var mobile in mobiles) + mobile.Send(generalInfo); + + generalInfo.Release(); + } + + public void SendTilesPacket(bool players, bool spectators) + { + foreach (var mobile in GetInGameMobiles(players, spectators)) + mobile.Send(new MahjongTilesInfo(Game, mobile)); + } + + public void SendTilePacket(MahjongTile tile, bool players, bool spectators) + { + foreach (var mobile in GetInGameMobiles(players, spectators)) + mobile.Send(new MahjongTileInfo(tile, mobile)); + } + + public void SendRelievePacket(bool players, bool spectators) + { + var mobiles = GetInGameMobiles(players, spectators); + + if (mobiles.Count == 0) + return; + + var relieve = new MahjongRelieve(Game); + + relieve.Acquire(); + + foreach (var mobile in mobiles) + mobile.Send(relieve); + + relieve.Release(); + } + + public void SendLocalizedMessage(int number) + { + foreach (var mobile in GetInGameMobiles(true, true)) + mobile.SendLocalizedMessage(number); + } + + public void SendLocalizedMessage(int number, string args) + { + foreach (var mobile in GetInGameMobiles(true, true)) + mobile.SendLocalizedMessage(number, args); + } + + public void Save(IGenericWriter writer) + { + writer.Write(0); // version + + writer.Write(Seats); + + for (var i = 0; i < Seats; i++) + { + writer.Write(m_Players[i]); + writer.Write(m_PublicHand[i]); + writer.Write(m_Scores[i]); + } + + writer.Write(DealerPosition); + } + } +} diff --git a/Projects/UOContent/Items/Games/Mahjong/MahjongTile.cs b/Projects/UOContent/Items/Games/Mahjong/MahjongTile.cs index 3e0480978..6099bc317 100644 --- a/Projects/UOContent/Items/Games/Mahjong/MahjongTile.cs +++ b/Projects/UOContent/Items/Games/Mahjong/MahjongTile.cs @@ -1,88 +1,90 @@ -namespace Server.Engines.Mahjong -{ - public class MahjongTile - { - protected Point2D m_Position; - - public MahjongTile(MahjongGame game, int number, MahjongTileType value, Point2D position, int stackLevel, - MahjongPieceDirection direction, bool flipped) - { - Game = game; - Number = number; - Value = value; - m_Position = position; - StackLevel = stackLevel; - Direction = direction; - Flipped = flipped; - } - - public MahjongTile(MahjongGame game, IGenericReader reader) - { - Game = game; - - int version = reader.ReadInt(); - - Number = reader.ReadInt(); - Value = (MahjongTileType)reader.ReadInt(); - m_Position = reader.ReadPoint2D(); - StackLevel = reader.ReadInt(); - Direction = (MahjongPieceDirection)reader.ReadInt(); - Flipped = reader.ReadBool(); - } - - public MahjongGame Game { get; } - - public int Number { get; } - - public MahjongTileType Value { get; } - - public Point2D Position => m_Position; - public int StackLevel { get; private set; } - - public MahjongPieceDirection Direction { get; private set; } - - public bool Flipped { get; private set; } - - public MahjongPieceDim Dimensions => GetDimensions(m_Position, Direction); - - public bool IsMovable => Game.GetStackLevel(Dimensions) <= StackLevel; - - public static MahjongPieceDim GetDimensions(Point2D position, MahjongPieceDirection direction) - { - if (direction == MahjongPieceDirection.Up || direction == MahjongPieceDirection.Down) - return new MahjongPieceDim(position, 20, 30); - return new MahjongPieceDim(position, 30, 20); - } - - public void Move(Point2D position, MahjongPieceDirection direction, bool flip, int validHandArea) - { - MahjongPieceDim dim = GetDimensions(position, direction); - int curHandArea = Dimensions.GetHandArea(); - int newHandArea = dim.GetHandArea(); - - if (!IsMovable || !dim.IsValid() || (validHandArea >= 0 && - ((curHandArea >= 0 && curHandArea != validHandArea) || (newHandArea >= 0 && newHandArea != validHandArea)))) - return; - - m_Position = position; - Direction = direction; - StackLevel = -1; // Avoid self interference - StackLevel = Game.GetStackLevel(dim) + 1; - Flipped = flip; - - Game.Players.SendTilePacket(this, true, true); - } - - public void Save(IGenericWriter writer) - { - writer.Write(0); // version - - writer.Write(Number); - writer.Write((int)Value); - writer.Write(m_Position); - writer.Write(StackLevel); - writer.Write((int)Direction); - writer.Write(Flipped); - } - } -} \ No newline at end of file +namespace Server.Engines.Mahjong +{ + public class MahjongTile + { + protected Point2D m_Position; + + public MahjongTile( + MahjongGame game, int number, MahjongTileType value, Point2D position, int stackLevel, + MahjongPieceDirection direction, bool flipped + ) + { + Game = game; + Number = number; + Value = value; + m_Position = position; + StackLevel = stackLevel; + Direction = direction; + Flipped = flipped; + } + + public MahjongTile(MahjongGame game, IGenericReader reader) + { + Game = game; + + var version = reader.ReadInt(); + + Number = reader.ReadInt(); + Value = (MahjongTileType)reader.ReadInt(); + m_Position = reader.ReadPoint2D(); + StackLevel = reader.ReadInt(); + Direction = (MahjongPieceDirection)reader.ReadInt(); + Flipped = reader.ReadBool(); + } + + public MahjongGame Game { get; } + + public int Number { get; } + + public MahjongTileType Value { get; } + + public Point2D Position => m_Position; + public int StackLevel { get; private set; } + + public MahjongPieceDirection Direction { get; private set; } + + public bool Flipped { get; private set; } + + public MahjongPieceDim Dimensions => GetDimensions(m_Position, Direction); + + public bool IsMovable => Game.GetStackLevel(Dimensions) <= StackLevel; + + public static MahjongPieceDim GetDimensions(Point2D position, MahjongPieceDirection direction) + { + if (direction == MahjongPieceDirection.Up || direction == MahjongPieceDirection.Down) + return new MahjongPieceDim(position, 20, 30); + return new MahjongPieceDim(position, 30, 20); + } + + public void Move(Point2D position, MahjongPieceDirection direction, bool flip, int validHandArea) + { + var dim = GetDimensions(position, direction); + var curHandArea = Dimensions.GetHandArea(); + var newHandArea = dim.GetHandArea(); + + if (!IsMovable || !dim.IsValid() || validHandArea >= 0 && + (curHandArea >= 0 && curHandArea != validHandArea || newHandArea >= 0 && newHandArea != validHandArea)) + return; + + m_Position = position; + Direction = direction; + StackLevel = -1; // Avoid self interference + StackLevel = Game.GetStackLevel(dim) + 1; + Flipped = flip; + + Game.Players.SendTilePacket(this, true, true); + } + + public void Save(IGenericWriter writer) + { + writer.Write(0); // version + + writer.Write(Number); + writer.Write((int)Value); + writer.Write(m_Position); + writer.Write(StackLevel); + writer.Write((int)Direction); + writer.Write(Flipped); + } + } +} diff --git a/Projects/UOContent/Items/Games/Mahjong/MahjongTileTypeGenerator.cs b/Projects/UOContent/Items/Games/Mahjong/MahjongTileTypeGenerator.cs index 0f6ebf563..099e3b610 100644 --- a/Projects/UOContent/Items/Games/Mahjong/MahjongTileTypeGenerator.cs +++ b/Projects/UOContent/Items/Games/Mahjong/MahjongTileTypeGenerator.cs @@ -1,31 +1,31 @@ -using System.Collections.Generic; - -namespace Server.Engines.Mahjong -{ - public class MahjongTileTypeGenerator - { - public MahjongTileTypeGenerator() - { - LeftTileTypes = new List(136); - - for (int i = 1; i <= 34; i++) - { - MahjongTileType tile = (MahjongTileType)i; - LeftTileTypes.Add(tile); - LeftTileTypes.Add(tile); - LeftTileTypes.Add(tile); - LeftTileTypes.Add(tile); - } - } - - public List LeftTileTypes { get; } - - public MahjongTileType Next() - { - MahjongTileType next = LeftTileTypes.RandomElement(); - LeftTileTypes.Remove(next); - - return next; - } - } -} +using System.Collections.Generic; + +namespace Server.Engines.Mahjong +{ + public class MahjongTileTypeGenerator + { + public MahjongTileTypeGenerator() + { + LeftTileTypes = new List(136); + + for (var i = 1; i <= 34; i++) + { + var tile = (MahjongTileType)i; + LeftTileTypes.Add(tile); + LeftTileTypes.Add(tile); + LeftTileTypes.Add(tile); + LeftTileTypes.Add(tile); + } + } + + public List LeftTileTypes { get; } + + public MahjongTileType Next() + { + var next = LeftTileTypes.RandomElement(); + LeftTileTypes.Remove(next); + + return next; + } + } +} diff --git a/Projects/UOContent/Items/Games/Mahjong/MahjongWallBreakIndicator.cs b/Projects/UOContent/Items/Games/Mahjong/MahjongWallBreakIndicator.cs index e918553aa..d6df87963 100644 --- a/Projects/UOContent/Items/Games/Mahjong/MahjongWallBreakIndicator.cs +++ b/Projects/UOContent/Items/Games/Mahjong/MahjongWallBreakIndicator.cs @@ -1,47 +1,47 @@ -namespace Server.Engines.Mahjong -{ - public class MahjongWallBreakIndicator - { - public MahjongWallBreakIndicator(MahjongGame game, Point2D position) - { - Game = game; - Position = position; - } - - public MahjongWallBreakIndicator(MahjongGame game, IGenericReader reader) - { - Game = game; - - int version = reader.ReadInt(); - - Position = reader.ReadPoint2D(); - } - - public MahjongGame Game { get; } - - public Point2D Position { get; private set; } - - public MahjongPieceDim Dimensions => GetDimensions(Position); - - public static MahjongPieceDim GetDimensions(Point2D position) => new MahjongPieceDim(position, 20, 20); - - public void Move(Point2D position) - { - MahjongPieceDim dim = GetDimensions(position); - - if (!dim.IsValid()) - return; - - Position = position; - - Game.Players.SendGeneralPacket(true, true); - } - - public void Save(IGenericWriter writer) - { - writer.Write(0); // version - - writer.Write(Position); - } - } -} \ No newline at end of file +namespace Server.Engines.Mahjong +{ + public class MahjongWallBreakIndicator + { + public MahjongWallBreakIndicator(MahjongGame game, Point2D position) + { + Game = game; + Position = position; + } + + public MahjongWallBreakIndicator(MahjongGame game, IGenericReader reader) + { + Game = game; + + var version = reader.ReadInt(); + + Position = reader.ReadPoint2D(); + } + + public MahjongGame Game { get; } + + public Point2D Position { get; private set; } + + public MahjongPieceDim Dimensions => GetDimensions(Position); + + public static MahjongPieceDim GetDimensions(Point2D position) => new MahjongPieceDim(position, 20, 20); + + public void Move(Point2D position) + { + var dim = GetDimensions(position); + + if (!dim.IsValid()) + return; + + Position = position; + + Game.Players.SendGeneralPacket(true, true); + } + + public void Save(IGenericWriter writer) + { + writer.Write(0); // version + + writer.Write(Position); + } + } +} diff --git a/Projects/UOContent/Items/Games/Mahjong/Packets.cs b/Projects/UOContent/Items/Games/Mahjong/Packets.cs index 6c49e4d64..5ddf03e1e 100644 --- a/Projects/UOContent/Items/Games/Mahjong/Packets.cs +++ b/Projects/UOContent/Items/Games/Mahjong/Packets.cs @@ -1,209 +1,209 @@ -using System.IO; -using Server.Network; - -namespace Server.Engines.Mahjong -{ - public sealed class MahjongJoinGame : Packet - { - public MahjongJoinGame(MahjongGame game) : base(0xDA) - { - EnsureCapacity(9); - - Stream.Write(game.Serial); - Stream.Write((byte)0); - Stream.Write((byte)0x19); - } - } - - public sealed class MahjongPlayersInfo : Packet - { - public MahjongPlayersInfo(MahjongGame game, Mobile to) : base(0xDA) - { - MahjongPlayers players = game.Players; - - EnsureCapacity(11 + 45 * players.Seats); - - Stream.Write(game.Serial); - Stream.Write((byte)0); - Stream.Write((byte)0x2); - - Stream.Write((byte)0); - Stream.Write((byte)players.Seats); - - int n = 0; - for (int i = 0; i < players.Seats; i++) - { - Mobile mobile = players.GetPlayer(i); - - if (mobile != null) - { - Stream.Write(mobile.Serial); - Stream.Write(players.DealerPosition == i ? (byte)0x1 : (byte)0x2); - Stream.Write((byte)i); - - if (game.ShowScores || mobile == to) - Stream.Write(players.GetScore(i)); - else - Stream.Write(0); - - Stream.Write((short)0); - Stream.Write((byte)0); - - Stream.Write(players.IsPublic(i)); - - Stream.WriteAsciiFixed(mobile.Name, 30); - Stream.Write(!players.IsInGamePlayer(i)); - - n++; - } - else if (game.ShowScores) - { - Stream.Write(0); - Stream.Write((byte)0x2); - Stream.Write((byte)i); - - Stream.Write(players.GetScore(i)); - - Stream.Write((short)0); - Stream.Write((byte)0); - - Stream.Write(players.IsPublic(i)); - - Stream.WriteAsciiFixed("", 30); - Stream.Write(true); - - n++; - } - } - - if (n != players.Seats) - { - Stream.Seek(10, SeekOrigin.Begin); - Stream.Write((byte)n); - } - } - } - - public sealed class MahjongGeneralInfo : Packet - { - public MahjongGeneralInfo(MahjongGame game) : base(0xDA) - { - EnsureCapacity(13); - - Stream.Write(game.Serial); - Stream.Write((byte)0); - Stream.Write((byte)0x5); - - Stream.Write((short)0); - Stream.Write((byte)0); - - Stream.Write((byte)((game.ShowScores ? 0x1 : 0x0) | (game.SpectatorVision ? 0x2 : 0x0))); - - Stream.Write((byte)game.Dices.First); - Stream.Write((byte)game.Dices.Second); - - Stream.Write((byte)game.DealerIndicator.Wind); - Stream.Write((short)game.DealerIndicator.Position.Y); - Stream.Write((short)game.DealerIndicator.Position.X); - Stream.Write((byte)game.DealerIndicator.Direction); - - Stream.Write((short)game.WallBreakIndicator.Position.Y); - Stream.Write((short)game.WallBreakIndicator.Position.X); - } - } - - public sealed class MahjongTilesInfo : Packet - { - public MahjongTilesInfo(MahjongGame game, Mobile to) : base(0xDA) - { - MahjongTile[] tiles = game.Tiles; - MahjongPlayers players = game.Players; - - EnsureCapacity(11 + 9 * tiles.Length); - - Stream.Write(game.Serial); - Stream.Write((byte)0); - Stream.Write((byte)0x4); - - Stream.Write((short)tiles.Length); - - foreach (MahjongTile tile in tiles) - { - Stream.Write((byte)tile.Number); - - if (tile.Flipped) - { - int hand = tile.Dimensions.GetHandArea(); - - if (hand < 0 || players.IsPublic(hand) || players.GetPlayer(hand) == to || - game.SpectatorVision && players.IsSpectator(to)) - Stream.Write((byte)tile.Value); - else - Stream.Write((byte)0); - } - else - { - Stream.Write((byte)0); - } - - Stream.Write((short)tile.Position.Y); - Stream.Write((short)tile.Position.X); - Stream.Write((byte)tile.StackLevel); - Stream.Write((byte)tile.Direction); - - Stream.Write(tile.Flipped ? (byte)0x10 : (byte)0x0); - } - } - } - - public sealed class MahjongTileInfo : Packet - { - public MahjongTileInfo(MahjongTile tile, Mobile to) : base(0xDA) - { - MahjongGame game = tile.Game; - MahjongPlayers players = game.Players; - - EnsureCapacity(18); - - Stream.Write(tile.Game.Serial); - Stream.Write((byte)0); - Stream.Write((byte)0x3); - - Stream.Write((byte)tile.Number); - - if (tile.Flipped) - { - int hand = tile.Dimensions.GetHandArea(); - - if (hand < 0 || players.IsPublic(hand) || players.GetPlayer(hand) == to || - game.SpectatorVision && players.IsSpectator(to)) - Stream.Write((byte)tile.Value); - else - Stream.Write((byte)0); - } - else - { - Stream.Write((byte)0); - } - - Stream.Write((short)tile.Position.Y); - Stream.Write((short)tile.Position.X); - Stream.Write((byte)tile.StackLevel); - Stream.Write((byte)tile.Direction); - - Stream.Write(tile.Flipped ? (byte)0x10 : (byte)0x0); - } - } - - public sealed class MahjongRelieve : Packet - { - public MahjongRelieve(MahjongGame game) : base(0xDA) - { - EnsureCapacity(9); - - Stream.Write(game.Serial); - Stream.Write((byte)0); - Stream.Write((byte)0x1A); - } - } -} +using System.IO; +using Server.Network; + +namespace Server.Engines.Mahjong +{ + public sealed class MahjongJoinGame : Packet + { + public MahjongJoinGame(MahjongGame game) : base(0xDA) + { + EnsureCapacity(9); + + Stream.Write(game.Serial); + Stream.Write((byte)0); + Stream.Write((byte)0x19); + } + } + + public sealed class MahjongPlayersInfo : Packet + { + public MahjongPlayersInfo(MahjongGame game, Mobile to) : base(0xDA) + { + var players = game.Players; + + EnsureCapacity(11 + 45 * players.Seats); + + Stream.Write(game.Serial); + Stream.Write((byte)0); + Stream.Write((byte)0x2); + + Stream.Write((byte)0); + Stream.Write((byte)players.Seats); + + var n = 0; + for (var i = 0; i < players.Seats; i++) + { + var mobile = players.GetPlayer(i); + + if (mobile != null) + { + Stream.Write(mobile.Serial); + Stream.Write(players.DealerPosition == i ? (byte)0x1 : (byte)0x2); + Stream.Write((byte)i); + + if (game.ShowScores || mobile == to) + Stream.Write(players.GetScore(i)); + else + Stream.Write(0); + + Stream.Write((short)0); + Stream.Write((byte)0); + + Stream.Write(players.IsPublic(i)); + + Stream.WriteAsciiFixed(mobile.Name, 30); + Stream.Write(!players.IsInGamePlayer(i)); + + n++; + } + else if (game.ShowScores) + { + Stream.Write(0); + Stream.Write((byte)0x2); + Stream.Write((byte)i); + + Stream.Write(players.GetScore(i)); + + Stream.Write((short)0); + Stream.Write((byte)0); + + Stream.Write(players.IsPublic(i)); + + Stream.WriteAsciiFixed("", 30); + Stream.Write(true); + + n++; + } + } + + if (n != players.Seats) + { + Stream.Seek(10, SeekOrigin.Begin); + Stream.Write((byte)n); + } + } + } + + public sealed class MahjongGeneralInfo : Packet + { + public MahjongGeneralInfo(MahjongGame game) : base(0xDA) + { + EnsureCapacity(13); + + Stream.Write(game.Serial); + Stream.Write((byte)0); + Stream.Write((byte)0x5); + + Stream.Write((short)0); + Stream.Write((byte)0); + + Stream.Write((byte)((game.ShowScores ? 0x1 : 0x0) | (game.SpectatorVision ? 0x2 : 0x0))); + + Stream.Write((byte)game.Dices.First); + Stream.Write((byte)game.Dices.Second); + + Stream.Write((byte)game.DealerIndicator.Wind); + Stream.Write((short)game.DealerIndicator.Position.Y); + Stream.Write((short)game.DealerIndicator.Position.X); + Stream.Write((byte)game.DealerIndicator.Direction); + + Stream.Write((short)game.WallBreakIndicator.Position.Y); + Stream.Write((short)game.WallBreakIndicator.Position.X); + } + } + + public sealed class MahjongTilesInfo : Packet + { + public MahjongTilesInfo(MahjongGame game, Mobile to) : base(0xDA) + { + var tiles = game.Tiles; + var players = game.Players; + + EnsureCapacity(11 + 9 * tiles.Length); + + Stream.Write(game.Serial); + Stream.Write((byte)0); + Stream.Write((byte)0x4); + + Stream.Write((short)tiles.Length); + + foreach (var tile in tiles) + { + Stream.Write((byte)tile.Number); + + if (tile.Flipped) + { + var hand = tile.Dimensions.GetHandArea(); + + if (hand < 0 || players.IsPublic(hand) || players.GetPlayer(hand) == to || + game.SpectatorVision && players.IsSpectator(to)) + Stream.Write((byte)tile.Value); + else + Stream.Write((byte)0); + } + else + { + Stream.Write((byte)0); + } + + Stream.Write((short)tile.Position.Y); + Stream.Write((short)tile.Position.X); + Stream.Write((byte)tile.StackLevel); + Stream.Write((byte)tile.Direction); + + Stream.Write(tile.Flipped ? (byte)0x10 : (byte)0x0); + } + } + } + + public sealed class MahjongTileInfo : Packet + { + public MahjongTileInfo(MahjongTile tile, Mobile to) : base(0xDA) + { + var game = tile.Game; + var players = game.Players; + + EnsureCapacity(18); + + Stream.Write(tile.Game.Serial); + Stream.Write((byte)0); + Stream.Write((byte)0x3); + + Stream.Write((byte)tile.Number); + + if (tile.Flipped) + { + var hand = tile.Dimensions.GetHandArea(); + + if (hand < 0 || players.IsPublic(hand) || players.GetPlayer(hand) == to || + game.SpectatorVision && players.IsSpectator(to)) + Stream.Write((byte)tile.Value); + else + Stream.Write((byte)0); + } + else + { + Stream.Write((byte)0); + } + + Stream.Write((short)tile.Position.Y); + Stream.Write((short)tile.Position.X); + Stream.Write((byte)tile.StackLevel); + Stream.Write((byte)tile.Direction); + + Stream.Write(tile.Flipped ? (byte)0x10 : (byte)0x0); + } + } + + public sealed class MahjongRelieve : Packet + { + public MahjongRelieve(MahjongGame game) : base(0xDA) + { + EnsureCapacity(9); + + Stream.Write(game.Serial); + Stream.Write((byte)0); + Stream.Write((byte)0x1A); + } + } +} diff --git a/Projects/UOContent/Items/Gems/Amber.cs b/Projects/UOContent/Items/Gems/Amber.cs index 60bac43f8..d811421cf 100644 --- a/Projects/UOContent/Items/Gems/Amber.cs +++ b/Projects/UOContent/Items/Gems/Amber.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class Amber : Item - { - [Constructible] - public Amber(int amount = 1) : base(0xF25) - { - Stackable = true; - Amount = amount; - } - - public Amber(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class Amber : Item + { + [Constructible] + public Amber(int amount = 1) : base(0xF25) + { + Stackable = true; + Amount = amount; + } + + public Amber(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0.1; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Gems/Amethyst.cs b/Projects/UOContent/Items/Gems/Amethyst.cs index 7bd8c130a..99f684cc7 100644 --- a/Projects/UOContent/Items/Gems/Amethyst.cs +++ b/Projects/UOContent/Items/Gems/Amethyst.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class Amethyst : Item - { - [Constructible] - public Amethyst(int amount = 1) : base(0xF16) - { - Stackable = true; - Amount = amount; - } - - public Amethyst(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class Amethyst : Item + { + [Constructible] + public Amethyst(int amount = 1) : base(0xF16) + { + Stackable = true; + Amount = amount; + } + + public Amethyst(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0.1; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Gems/Citrine.cs b/Projects/UOContent/Items/Gems/Citrine.cs index 8be77e70b..2f87a0462 100644 --- a/Projects/UOContent/Items/Gems/Citrine.cs +++ b/Projects/UOContent/Items/Gems/Citrine.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class Citrine : Item - { - [Constructible] - public Citrine(int amount = 1) : base(0xF15) - { - Stackable = true; - Amount = amount; - } - - public Citrine(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class Citrine : Item + { + [Constructible] + public Citrine(int amount = 1) : base(0xF15) + { + Stackable = true; + Amount = amount; + } + + public Citrine(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0.1; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Gems/Diamond.cs b/Projects/UOContent/Items/Gems/Diamond.cs index be818dd37..22802ba8e 100644 --- a/Projects/UOContent/Items/Gems/Diamond.cs +++ b/Projects/UOContent/Items/Gems/Diamond.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class Diamond : Item - { - [Constructible] - public Diamond(int amount = 1) : base(0xF26) - { - Stackable = true; - Amount = amount; - } - - public Diamond(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class Diamond : Item + { + [Constructible] + public Diamond(int amount = 1) : base(0xF26) + { + Stackable = true; + Amount = amount; + } + + public Diamond(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0.1; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Gems/Emerald.cs b/Projects/UOContent/Items/Gems/Emerald.cs index 622f017b9..90bde6ffc 100644 --- a/Projects/UOContent/Items/Gems/Emerald.cs +++ b/Projects/UOContent/Items/Gems/Emerald.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class Emerald : Item - { - [Constructible] - public Emerald(int amount = 1) : base(0xF10) - { - Stackable = true; - Amount = amount; - } - - public Emerald(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class Emerald : Item + { + [Constructible] + public Emerald(int amount = 1) : base(0xF10) + { + Stackable = true; + Amount = amount; + } + + public Emerald(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0.1; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Gems/Ruby.cs b/Projects/UOContent/Items/Gems/Ruby.cs index c933199a3..536f2a06b 100644 --- a/Projects/UOContent/Items/Gems/Ruby.cs +++ b/Projects/UOContent/Items/Gems/Ruby.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class Ruby : Item - { - [Constructible] - public Ruby(int amount = 1) : base(0xF13) - { - Stackable = true; - Amount = amount; - } - - public Ruby(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class Ruby : Item + { + [Constructible] + public Ruby(int amount = 1) : base(0xF13) + { + Stackable = true; + Amount = amount; + } + + public Ruby(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0.1; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Gems/Sapphire.cs b/Projects/UOContent/Items/Gems/Sapphire.cs index cfa3388fd..a43a7b7f5 100644 --- a/Projects/UOContent/Items/Gems/Sapphire.cs +++ b/Projects/UOContent/Items/Gems/Sapphire.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class Sapphire : Item - { - [Constructible] - public Sapphire(int amount = 1) : base(0xF19) - { - Stackable = true; - Amount = amount; - } - - public Sapphire(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class Sapphire : Item + { + [Constructible] + public Sapphire(int amount = 1) : base(0xF19) + { + Stackable = true; + Amount = amount; + } + + public Sapphire(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0.1; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Gems/StarSapphire.cs b/Projects/UOContent/Items/Gems/StarSapphire.cs index 3ca0ab5bd..04f2aa463 100644 --- a/Projects/UOContent/Items/Gems/StarSapphire.cs +++ b/Projects/UOContent/Items/Gems/StarSapphire.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class StarSapphire : Item - { - [Constructible] - public StarSapphire(int amount = 1) : base(0xF21) - { - Stackable = true; - Amount = amount; - } - - public StarSapphire(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class StarSapphire : Item + { + [Constructible] + public StarSapphire(int amount = 1) : base(0xF21) + { + Stackable = true; + Amount = amount; + } + + public StarSapphire(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0.1; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Gems/Tourmaline.cs b/Projects/UOContent/Items/Gems/Tourmaline.cs index 4d25610fc..c17503f80 100644 --- a/Projects/UOContent/Items/Gems/Tourmaline.cs +++ b/Projects/UOContent/Items/Gems/Tourmaline.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class Tourmaline : Item - { - [Constructible] - public Tourmaline(int amount = 1) : base(0xF2D) - { - Stackable = true; - Amount = amount; - } - - public Tourmaline(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class Tourmaline : Item + { + [Constructible] + public Tourmaline(int amount = 1) : base(0xF2D) + { + Stackable = true; + Amount = amount; + } + + public Tourmaline(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0.1; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Guilds/GuildDeed.cs b/Projects/UOContent/Items/Guilds/GuildDeed.cs index c904eb0bd..28992c601 100644 --- a/Projects/UOContent/Items/Guilds/GuildDeed.cs +++ b/Projects/UOContent/Items/Guilds/GuildDeed.cs @@ -1,134 +1,134 @@ -using Server.Guilds; -using Server.Multis; -using Server.Prompts; - -namespace Server.Items -{ - public class GuildDeed : Item - { - [Constructible] - public GuildDeed() : base(0x14F0) => Weight = 1.0; - - public GuildDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041055; // a guild deed - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 0.0) - Weight = 1.0; - } - - public override void OnDoubleClick(Mobile from) - { - if (Guild.NewGuildSystem) - return; - - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (from.Guild != null) - { - from.SendLocalizedMessage(501137); // You must resign from your current guild before founding another! - } - else - { - BaseHouse house = BaseHouse.FindHouseAt(from); - - if (house == null) - { - from.SendLocalizedMessage(501138); // You can only place a guildstone in a house. - } - else if (house.FindGuildstone() != null) - { - from.SendLocalizedMessage(501142); // Only one guildstone may reside in a given house. - } - else if (!house.IsOwner(from)) - { - from.SendLocalizedMessage(501141); // You can only place a guildstone in a house you own! - } - else - { - from.SendLocalizedMessage(1013060); // Enter new guild name (40 characters max): - from.Prompt = new InternalPrompt(this); - } - } - } - - private class InternalPrompt : Prompt - { - private readonly GuildDeed m_Deed; - - public InternalPrompt(GuildDeed deed) => m_Deed = deed; - - public override void OnResponse(Mobile from, string text) - { - if (m_Deed.Deleted) - return; - - if (!m_Deed.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (from.Guild != null) - { - from.SendLocalizedMessage(501137); // You must resign from your current guild before founding another! - } - else - { - BaseHouse house = BaseHouse.FindHouseAt(from); - - if (house == null) - { - from.SendLocalizedMessage(501138); // You can only place a guildstone in a house. - } - else if (house.FindGuildstone() != null) - { - from.SendLocalizedMessage(501142); // Only one guildstone may reside in a given house. - } - else if (!house.IsOwner(from)) - { - from.SendLocalizedMessage(501141); // You can only place a guildstone in a house you own! - } - else - { - m_Deed.Delete(); - - if (text.Length > 40) - text = text.Substring(0, 40); - - Guild guild = new Guild(from, text, "none"); - - from.Guild = guild; - from.GuildTitle = "Guildmaster"; - - Guildstone stone = new Guildstone(guild); - - stone.MoveToWorld(from.Location, from.Map); - - guild.Guildstone = stone; - } - } - } - - public override void OnCancel(Mobile from) - { - from.SendLocalizedMessage(501145); // Placement of guildstone cancelled. - } - } - } -} \ No newline at end of file +using Server.Guilds; +using Server.Multis; +using Server.Prompts; + +namespace Server.Items +{ + public class GuildDeed : Item + { + [Constructible] + public GuildDeed() : base(0x14F0) => Weight = 1.0; + + public GuildDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041055; // a guild deed + + 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 (Weight == 0.0) + Weight = 1.0; + } + + public override void OnDoubleClick(Mobile from) + { + if (Guild.NewGuildSystem) + return; + + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else if (from.Guild != null) + { + from.SendLocalizedMessage(501137); // You must resign from your current guild before founding another! + } + else + { + var house = BaseHouse.FindHouseAt(from); + + if (house == null) + { + from.SendLocalizedMessage(501138); // You can only place a guildstone in a house. + } + else if (house.FindGuildstone() != null) + { + from.SendLocalizedMessage(501142); // Only one guildstone may reside in a given house. + } + else if (!house.IsOwner(from)) + { + from.SendLocalizedMessage(501141); // You can only place a guildstone in a house you own! + } + else + { + from.SendLocalizedMessage(1013060); // Enter new guild name (40 characters max): + from.Prompt = new InternalPrompt(this); + } + } + } + + private class InternalPrompt : Prompt + { + private readonly GuildDeed m_Deed; + + public InternalPrompt(GuildDeed deed) => m_Deed = deed; + + public override void OnResponse(Mobile from, string text) + { + if (m_Deed.Deleted) + return; + + if (!m_Deed.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else if (from.Guild != null) + { + from.SendLocalizedMessage(501137); // You must resign from your current guild before founding another! + } + else + { + var house = BaseHouse.FindHouseAt(from); + + if (house == null) + { + from.SendLocalizedMessage(501138); // You can only place a guildstone in a house. + } + else if (house.FindGuildstone() != null) + { + from.SendLocalizedMessage(501142); // Only one guildstone may reside in a given house. + } + else if (!house.IsOwner(from)) + { + from.SendLocalizedMessage(501141); // You can only place a guildstone in a house you own! + } + else + { + m_Deed.Delete(); + + if (text.Length > 40) + text = text.Substring(0, 40); + + var guild = new Guild(from, text, "none"); + + from.Guild = guild; + from.GuildTitle = "Guildmaster"; + + var stone = new Guildstone(guild); + + stone.MoveToWorld(from.Location, from.Map); + + guild.Guildstone = stone; + } + } + } + + public override void OnCancel(Mobile from) + { + from.SendLocalizedMessage(501145); // Placement of guildstone cancelled. + } + } + } +} diff --git a/Projects/UOContent/Items/Guilds/GuildTeleporter.cs b/Projects/UOContent/Items/Guilds/GuildTeleporter.cs index bc6fc028c..4c0a78f66 100644 --- a/Projects/UOContent/Items/Guilds/GuildTeleporter.cs +++ b/Projects/UOContent/Items/Guilds/GuildTeleporter.cs @@ -1,97 +1,97 @@ -using Server.Guilds; -using Server.Multis; - -namespace Server.Items -{ - public class GuildTeleporter : Item - { - private Item m_Stone; - - [Constructible] - public GuildTeleporter(Item stone = null) : base(0x1869) - { - Weight = 1.0; - LootType = LootType.Blessed; - - m_Stone = stone; - } - - public GuildTeleporter(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041054; // guildstone teleporter - - public override bool DisplayLootType => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Stone); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - LootType = LootType.Blessed; - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Stone = reader.ReadItem(); - - break; - } - } - - if (Weight == 0.0) - Weight = 1.0; - } - - public override void OnDoubleClick(Mobile from) - { - if (Guild.NewGuildSystem) - return; - - Guildstone stone = m_Stone as Guildstone; - - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (stone?.Deleted != false || stone.Guild?.Teleporter != this) - { - from.SendLocalizedMessage(501197); // This teleporting object can not determine what guildstone to teleport - } - else - { - BaseHouse house = BaseHouse.FindHouseAt(from); - - if (house == null) - { - from.SendLocalizedMessage(501138); // You can only place a guildstone in a house. - } - else if (!house.IsOwner(from)) - { - from.SendLocalizedMessage(501141); // You can only place a guildstone in a house you own! - } - else if (house.FindGuildstone() != null) - { - from.SendLocalizedMessage(501142); // Only one guildstone may reside in a given house. - } - else - { - m_Stone.MoveToWorld(from.Location, from.Map); - Delete(); - stone.Guild.Teleporter = null; - } - } - } - } -} +using Server.Guilds; +using Server.Multis; + +namespace Server.Items +{ + public class GuildTeleporter : Item + { + private Item m_Stone; + + [Constructible] + public GuildTeleporter(Item stone = null) : base(0x1869) + { + Weight = 1.0; + LootType = LootType.Blessed; + + m_Stone = stone; + } + + public GuildTeleporter(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041054; // guildstone teleporter + + public override bool DisplayLootType => false; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Stone); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + LootType = LootType.Blessed; + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Stone = reader.ReadItem(); + + break; + } + } + + if (Weight == 0.0) + Weight = 1.0; + } + + public override void OnDoubleClick(Mobile from) + { + if (Guild.NewGuildSystem) + return; + + var stone = m_Stone as Guildstone; + + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else if (stone?.Deleted != false || stone.Guild?.Teleporter != this) + { + from.SendLocalizedMessage(501197); // This teleporting object can not determine what guildstone to teleport + } + else + { + var house = BaseHouse.FindHouseAt(from); + + if (house == null) + { + from.SendLocalizedMessage(501138); // You can only place a guildstone in a house. + } + else if (!house.IsOwner(from)) + { + from.SendLocalizedMessage(501141); // You can only place a guildstone in a house you own! + } + else if (house.FindGuildstone() != null) + { + from.SendLocalizedMessage(501142); // Only one guildstone may reside in a given house. + } + else + { + m_Stone.MoveToWorld(from.Location, from.Map); + Delete(); + stone.Guild.Teleporter = null; + } + } + } + } +} diff --git a/Projects/UOContent/Items/Guilds/Guildstone.cs b/Projects/UOContent/Items/Guilds/Guildstone.cs index 330b89b5c..8d805d146 100644 --- a/Projects/UOContent/Items/Guilds/Guildstone.cs +++ b/Projects/UOContent/Items/Guilds/Guildstone.cs @@ -1,424 +1,435 @@ -using Server.Factions; -using Server.Guilds; -using Server.Gumps; -using Server.Multis; -using Server.Network; -using Server.Targeting; - -namespace Server.Items -{ - public class Guildstone : Item, IAddon, IChoppable - { - private bool m_BeforeChangeover; - private string m_GuildAbbrev; - private string m_GuildName; - - public Guildstone(Guild g) : this(g, g.Name, g.Abbreviation) - { - } - - public Guildstone(Guild g, string guildName, string abbrev) : base(Guild.NewGuildSystem ? 0xED6 : 0xED4) - { - Guild = g; - m_GuildName = guildName; - m_GuildAbbrev = abbrev; - - Movable = false; - } - - public Guildstone(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public string GuildName - { - get => m_GuildName; - set - { - m_GuildName = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public string GuildAbbrev - { - get => m_GuildAbbrev; - set - { - m_GuildAbbrev = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Guild Guild { get; private set; } - - public override int LabelNumber => 1041429; // a guildstone - - public void OnChop(Mobile from) - { - if (!Guild.NewGuildSystem) - return; - - BaseHouse house = BaseHouse.FindHouseAt(this); - - bool contains = false; - - if ((house == null && m_BeforeChangeover) || (house?.IsOwner(from) == true && (contains = house.Addons.Contains(this)))) - { - Effects.PlaySound(GetWorldLocation(), Map, 0x3B3); - from.SendLocalizedMessage(500461); // You destroy the item. - - Delete(); - - if (contains) - house.Addons.Remove(this); - - Item deed = Deed; - - if (deed != null) - from.AddToBackpack(deed); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - if (Guild?.Disbanded == false) - { - m_GuildName = Guild.Name; - m_GuildAbbrev = Guild.Abbreviation; - } - - writer.Write(3); // version - - writer.Write(m_BeforeChangeover); - - writer.Write(m_GuildName); - writer.Write(m_GuildAbbrev); - - writer.Write(Guild); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 3: - { - m_BeforeChangeover = reader.ReadBool(); - goto case 2; - } - case 2: - { - m_GuildName = reader.ReadString(); - m_GuildAbbrev = reader.ReadString(); - - goto case 1; - } - case 1: - { - Guild = reader.ReadGuild() as Guild; - - goto case 0; - } - case 0: - { - break; - } - } - - if (Guild.NewGuildSystem && ItemID == 0xED4) - ItemID = 0xED6; - - if (version <= 2) - m_BeforeChangeover = true; - - if (Guild.NewGuildSystem && m_BeforeChangeover) - Timer.DelayCall(AddToHouse); - - if (!Guild.NewGuildSystem && Guild == null) - Delete(); - } - - private void AddToHouse() - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (Guild.NewGuildSystem && m_BeforeChangeover && house?.Addons.Contains(this) == false) - { - house.Addons.Add(this); - m_BeforeChangeover = false; - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Guild?.Disbanded == false) - { - string name; - string abbr; - - if ((name = Guild.Name) == null || (name = name.Trim()).Length <= 0) - name = "(unnamed)"; - - if ((abbr = Guild.Abbreviation) == null || (abbr = abbr.Trim()).Length <= 0) - abbr = ""; - - // list.Add( 1060802, Utility.FixHtml( name ) ); // Guild name: ~1_val~ - list.Add(1060802, $"{Utility.FixHtml(name)} [{Utility.FixHtml(abbr)}]"); - } - else if (m_GuildName != null && m_GuildAbbrev != null) - { - list.Add(1060802, $"{Utility.FixHtml(m_GuildName)} [{Utility.FixHtml(m_GuildAbbrev)}]"); - } - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - if (Guild?.Disbanded == false) - { - string name; - - if ((name = Guild.Name) == null || (name = name.Trim()).Length <= 0) - name = "(unnamed)"; - - LabelTo(from, name); - } - else if (m_GuildName != null) - { - LabelTo(from, m_GuildName); - } - } - - public override void OnAfterDelete() - { - if (!Guild.NewGuildSystem && Guild?.Disbanded == false) - Guild.Disband(); - } - - public override void OnDoubleClick(Mobile from) - { - if (Guild.NewGuildSystem) - return; - - if (Guild?.Disbanded != false) - { - Delete(); - } - else if (!from.InRange(GetWorldLocation(), 2)) - { - from.SendLocalizedMessage(500446); // That is too far away. - } - else if (Guild.Accepted.Contains(from)) - { - PlayerState guildState = PlayerState.Find(Guild.Leader); - PlayerState targetState = PlayerState.Find(from); - - Faction guildFaction = guildState?.Faction; - Faction targetFaction = targetState?.Faction; - - if (guildFaction != targetFaction || targetState?.IsLeaving == true) - return; - - if (guildState != null && targetState != null) - targetState.Leaving = guildState.Leaving; - - Guild.Accepted.Remove(from); - Guild.AddMember(from); - - GuildGump.EnsureClosed(from); - from.SendGump(new GuildGump(from, Guild)); - } - else if (from.AccessLevel < AccessLevel.GameMaster && !Guild.IsMember(from)) - { - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, 0x3B2, 3, 501158, "", - "")); // You are not a member ... - } - else - { - GuildGump.EnsureClosed(from); - from.SendGump(new GuildGump(from, Guild)); - } - } - - public Item Deed => new GuildstoneDeed(Guild, m_GuildName, m_GuildAbbrev); - - public bool CouldFit(IPoint3D p, Map map) => map.CanFit(p.X, p.Y, p.Z, ItemData.Height); - } - - [Flippable(0x14F0, 0x14EF)] - public class GuildstoneDeed : Item - { - private string m_GuildAbbrev; - - private string m_GuildName; - - [Constructible] - public GuildstoneDeed(Guild g = null, string guildName = null, string abbrev = null) : base(0x14F0) - { - Guild = g; - m_GuildName = guildName; - m_GuildAbbrev = abbrev; - - Weight = 1.0; - } - - public GuildstoneDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041233; // deed to a guildstone - - [CommandProperty(AccessLevel.GameMaster)] - public string GuildName - { - get => m_GuildName; - set - { - m_GuildName = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public string GuildAbbrev - { - get => m_GuildAbbrev; - set - { - m_GuildAbbrev = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Guild Guild { get; private set; } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - if (Guild?.Disbanded == false) - { - m_GuildName = Guild.Name; - m_GuildAbbrev = Guild.Abbreviation; - } - - writer.Write(1); // version - - writer.Write(m_GuildName); - writer.Write(m_GuildAbbrev); - - writer.Write(Guild); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_GuildName = reader.ReadString(); - m_GuildAbbrev = reader.ReadString(); - - Guild = reader.ReadGuild() as Guild; - - break; - } - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Guild?.Disbanded == false) - { - string name; - string abbr; - - if ((name = Guild.Name) == null || (name = name.Trim()).Length <= 0) - name = "(unnamed)"; - - if ((abbr = Guild.Abbreviation) == null || (abbr = abbr.Trim()).Length <= 0) - abbr = ""; - - // list.Add( 1060802, Utility.FixHtml( name ) ); // Guild name: ~1_val~ - list.Add(1060802, $"{Utility.FixHtml(name)} [{Utility.FixHtml(abbr)}]"); - } - else if (m_GuildName != null && m_GuildAbbrev != null) - { - list.Add(1060802, $"{Utility.FixHtml(m_GuildName)} [{Utility.FixHtml(m_GuildAbbrev)}]"); - } - } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - BaseHouse house = BaseHouse.FindHouseAt(from); - - if (house?.IsOwner(from) == true) - { - from.SendLocalizedMessage(1062838); // Where would you like to place this decoration? - from.BeginTarget(-1, true, TargetFlags.None, Placement_OnTarget); - } - else - { - from.SendLocalizedMessage(502092); // You must be in your house to do this. - } - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - - public void Placement_OnTarget(Mobile from, object targeted) - { - if (!(targeted is IPoint3D p) || Deleted) - return; - - Point3D loc = new Point3D(p); - - BaseHouse house = BaseHouse.FindHouseAt(loc, from.Map, 16); - - if (IsChildOf(from.Backpack)) - { - if (house?.IsOwner(from) == true) - { - Item addon = new Guildstone(Guild, m_GuildName, m_GuildAbbrev); - - addon.MoveToWorld(loc, from.Map); - - house.Addons.Add(addon); - Delete(); - } - else - { - from.SendLocalizedMessage(1042036); // That location is not in your house. - } - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - } -} +using Server.Factions; +using Server.Guilds; +using Server.Gumps; +using Server.Multis; +using Server.Network; +using Server.Targeting; + +namespace Server.Items +{ + public class Guildstone : Item, IAddon, IChoppable + { + private bool m_BeforeChangeover; + private string m_GuildAbbrev; + private string m_GuildName; + + public Guildstone(Guild g) : this(g, g.Name, g.Abbreviation) + { + } + + public Guildstone(Guild g, string guildName, string abbrev) : base(Guild.NewGuildSystem ? 0xED6 : 0xED4) + { + Guild = g; + m_GuildName = guildName; + m_GuildAbbrev = abbrev; + + Movable = false; + } + + public Guildstone(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public string GuildName + { + get => m_GuildName; + set + { + m_GuildName = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public string GuildAbbrev + { + get => m_GuildAbbrev; + set + { + m_GuildAbbrev = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Guild Guild { get; private set; } + + public override int LabelNumber => 1041429; // a guildstone + + public Item Deed => new GuildstoneDeed(Guild, m_GuildName, m_GuildAbbrev); + + public bool CouldFit(IPoint3D p, Map map) => map.CanFit(p.X, p.Y, p.Z, ItemData.Height); + + public void OnChop(Mobile from) + { + if (!Guild.NewGuildSystem) + return; + + var house = BaseHouse.FindHouseAt(this); + + var contains = false; + + if (house == null && m_BeforeChangeover || + house?.IsOwner(@from) == true && (contains = house.Addons.Contains(this))) + { + Effects.PlaySound(GetWorldLocation(), Map, 0x3B3); + from.SendLocalizedMessage(500461); // You destroy the item. + + Delete(); + + if (contains) + house.Addons.Remove(this); + + var deed = Deed; + + if (deed != null) + from.AddToBackpack(deed); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + if (Guild?.Disbanded == false) + { + m_GuildName = Guild.Name; + m_GuildAbbrev = Guild.Abbreviation; + } + + writer.Write(3); // version + + writer.Write(m_BeforeChangeover); + + writer.Write(m_GuildName); + writer.Write(m_GuildAbbrev); + + writer.Write(Guild); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 3: + { + m_BeforeChangeover = reader.ReadBool(); + goto case 2; + } + case 2: + { + m_GuildName = reader.ReadString(); + m_GuildAbbrev = reader.ReadString(); + + goto case 1; + } + case 1: + { + Guild = reader.ReadGuild() as Guild; + + goto case 0; + } + case 0: + { + break; + } + } + + if (Guild.NewGuildSystem && ItemID == 0xED4) + ItemID = 0xED6; + + if (version <= 2) + m_BeforeChangeover = true; + + if (Guild.NewGuildSystem && m_BeforeChangeover) + Timer.DelayCall(AddToHouse); + + if (!Guild.NewGuildSystem && Guild == null) + Delete(); + } + + private void AddToHouse() + { + var house = BaseHouse.FindHouseAt(this); + + if (Guild.NewGuildSystem && m_BeforeChangeover && house?.Addons.Contains(this) == false) + { + house.Addons.Add(this); + m_BeforeChangeover = false; + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (Guild?.Disbanded == false) + { + string name; + string abbr; + + if ((name = Guild.Name) == null || (name = name.Trim()).Length <= 0) + name = "(unnamed)"; + + if ((abbr = Guild.Abbreviation) == null || (abbr = abbr.Trim()).Length <= 0) + abbr = ""; + + // list.Add( 1060802, Utility.FixHtml( name ) ); // Guild name: ~1_val~ + list.Add(1060802, $"{Utility.FixHtml(name)} [{Utility.FixHtml(abbr)}]"); + } + else if (m_GuildName != null && m_GuildAbbrev != null) + { + list.Add(1060802, $"{Utility.FixHtml(m_GuildName)} [{Utility.FixHtml(m_GuildAbbrev)}]"); + } + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + if (Guild?.Disbanded == false) + { + string name; + + if ((name = Guild.Name) == null || (name = name.Trim()).Length <= 0) + name = "(unnamed)"; + + LabelTo(from, name); + } + else if (m_GuildName != null) + { + LabelTo(from, m_GuildName); + } + } + + public override void OnAfterDelete() + { + if (!Guild.NewGuildSystem && Guild?.Disbanded == false) + Guild.Disband(); + } + + public override void OnDoubleClick(Mobile from) + { + if (Guild.NewGuildSystem) + return; + + if (Guild?.Disbanded != false) + { + Delete(); + } + else if (!from.InRange(GetWorldLocation(), 2)) + { + from.SendLocalizedMessage(500446); // That is too far away. + } + else if (Guild.Accepted.Contains(from)) + { + var guildState = PlayerState.Find(Guild.Leader); + var targetState = PlayerState.Find(from); + + var guildFaction = guildState?.Faction; + var targetFaction = targetState?.Faction; + + if (guildFaction != targetFaction || targetState?.IsLeaving == true) + return; + + if (guildState != null && targetState != null) + targetState.Leaving = guildState.Leaving; + + Guild.Accepted.Remove(from); + Guild.AddMember(from); + + GuildGump.EnsureClosed(from); + from.SendGump(new GuildGump(from, Guild)); + } + else if (from.AccessLevel < AccessLevel.GameMaster && !Guild.IsMember(from)) + { + from.Send( + new MessageLocalized( + Serial, + ItemID, + MessageType.Regular, + 0x3B2, + 3, + 501158, + "", + "" + ) + ); // You are not a member ... + } + else + { + GuildGump.EnsureClosed(from); + from.SendGump(new GuildGump(from, Guild)); + } + } + } + + [Flippable(0x14F0, 0x14EF)] + public class GuildstoneDeed : Item + { + private string m_GuildAbbrev; + + private string m_GuildName; + + [Constructible] + public GuildstoneDeed(Guild g = null, string guildName = null, string abbrev = null) : base(0x14F0) + { + Guild = g; + m_GuildName = guildName; + m_GuildAbbrev = abbrev; + + Weight = 1.0; + } + + public GuildstoneDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041233; // deed to a guildstone + + [CommandProperty(AccessLevel.GameMaster)] + public string GuildName + { + get => m_GuildName; + set + { + m_GuildName = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public string GuildAbbrev + { + get => m_GuildAbbrev; + set + { + m_GuildAbbrev = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Guild Guild { get; private set; } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + if (Guild?.Disbanded == false) + { + m_GuildName = Guild.Name; + m_GuildAbbrev = Guild.Abbreviation; + } + + writer.Write(1); // version + + writer.Write(m_GuildName); + writer.Write(m_GuildAbbrev); + + writer.Write(Guild); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_GuildName = reader.ReadString(); + m_GuildAbbrev = reader.ReadString(); + + Guild = reader.ReadGuild() as Guild; + + break; + } + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (Guild?.Disbanded == false) + { + string name; + string abbr; + + if ((name = Guild.Name) == null || (name = name.Trim()).Length <= 0) + name = "(unnamed)"; + + if ((abbr = Guild.Abbreviation) == null || (abbr = abbr.Trim()).Length <= 0) + abbr = ""; + + // list.Add( 1060802, Utility.FixHtml( name ) ); // Guild name: ~1_val~ + list.Add(1060802, $"{Utility.FixHtml(name)} [{Utility.FixHtml(abbr)}]"); + } + else if (m_GuildName != null && m_GuildAbbrev != null) + { + list.Add(1060802, $"{Utility.FixHtml(m_GuildName)} [{Utility.FixHtml(m_GuildAbbrev)}]"); + } + } + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + var house = BaseHouse.FindHouseAt(from); + + if (house?.IsOwner(from) == true) + { + from.SendLocalizedMessage(1062838); // Where would you like to place this decoration? + from.BeginTarget(-1, true, TargetFlags.None, Placement_OnTarget); + } + else + { + from.SendLocalizedMessage(502092); // You must be in your house to do this. + } + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + + public void Placement_OnTarget(Mobile from, object targeted) + { + if (!(targeted is IPoint3D p) || Deleted) + return; + + var loc = new Point3D(p); + + var house = BaseHouse.FindHouseAt(loc, from.Map, 16); + + if (IsChildOf(from.Backpack)) + { + if (house?.IsOwner(from) == true) + { + Item addon = new Guildstone(Guild, m_GuildName, m_GuildAbbrev); + + addon.MoveToWorld(loc, from.Map); + + house.Addons.Add(addon); + Delete(); + } + else + { + from.SendLocalizedMessage(1042036); // That location is not in your house. + } + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + } +} diff --git a/Projects/UOContent/Items/Jewels/Artifacts/BraceletOfHealth.cs b/Projects/UOContent/Items/Jewels/Artifacts/BraceletOfHealth.cs index 619a3e4a2..6aaf3a314 100644 --- a/Projects/UOContent/Items/Jewels/Artifacts/BraceletOfHealth.cs +++ b/Projects/UOContent/Items/Jewels/Artifacts/BraceletOfHealth.cs @@ -1,34 +1,34 @@ -namespace Server.Items -{ - public class BraceletOfHealth : GoldBracelet - { - [Constructible] - public BraceletOfHealth() - { - Hue = 0x21; - Attributes.BonusHits = 5; - Attributes.RegenHits = 10; - } - - public BraceletOfHealth(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061103; // Bracelet of Health - public override int ArtifactRarity => 11; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class BraceletOfHealth : GoldBracelet + { + [Constructible] + public BraceletOfHealth() + { + Hue = 0x21; + Attributes.BonusHits = 5; + Attributes.RegenHits = 10; + } + + public BraceletOfHealth(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061103; // Bracelet of Health + public override int ArtifactRarity => 11; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Jewels/Artifacts/Craftable/EssenceOfBattle.cs b/Projects/UOContent/Items/Jewels/Artifacts/Craftable/EssenceOfBattle.cs index 90c86b540..779ba556e 100644 --- a/Projects/UOContent/Items/Jewels/Artifacts/Craftable/EssenceOfBattle.cs +++ b/Projects/UOContent/Items/Jewels/Artifacts/Craftable/EssenceOfBattle.cs @@ -1,34 +1,34 @@ -namespace Server.Items -{ - public class EssenceOfBattle : GoldRing - { - [Constructible] - public EssenceOfBattle() - { - Hue = 0x550; - Attributes.BonusDex = 7; - Attributes.BonusStr = 7; - Attributes.WeaponDamage = 30; - } - - public EssenceOfBattle(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072935; // Essence of Battle - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class EssenceOfBattle : GoldRing + { + [Constructible] + public EssenceOfBattle() + { + Hue = 0x550; + Attributes.BonusDex = 7; + Attributes.BonusStr = 7; + Attributes.WeaponDamage = 30; + } + + public EssenceOfBattle(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072935; // Essence of Battle + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Jewels/Artifacts/Craftable/PendantOfTheMagi.cs b/Projects/UOContent/Items/Jewels/Artifacts/Craftable/PendantOfTheMagi.cs index b30a7847d..180930246 100644 --- a/Projects/UOContent/Items/Jewels/Artifacts/Craftable/PendantOfTheMagi.cs +++ b/Projects/UOContent/Items/Jewels/Artifacts/Craftable/PendantOfTheMagi.cs @@ -1,36 +1,36 @@ -namespace Server.Items -{ - public class PendantOfTheMagi : GoldNecklace - { - [Constructible] - public PendantOfTheMagi() - { - Hue = 0x48D; - Attributes.BonusInt = 10; - Attributes.RegenMana = 3; - Attributes.SpellDamage = 5; - Attributes.LowerManaCost = 10; - Attributes.LowerRegCost = 30; - } - - public PendantOfTheMagi(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072937; // Pendant of the Magi - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PendantOfTheMagi : GoldNecklace + { + [Constructible] + public PendantOfTheMagi() + { + Hue = 0x48D; + Attributes.BonusInt = 10; + Attributes.RegenMana = 3; + Attributes.SpellDamage = 5; + Attributes.LowerManaCost = 10; + Attributes.LowerRegCost = 30; + } + + public PendantOfTheMagi(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072937; // Pendant of the Magi + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Jewels/Artifacts/Craftable/ResillientBracer.cs b/Projects/UOContent/Items/Jewels/Artifacts/Craftable/ResillientBracer.cs index f8018a225..7e0edd560 100644 --- a/Projects/UOContent/Items/Jewels/Artifacts/Craftable/ResillientBracer.cs +++ b/Projects/UOContent/Items/Jewels/Artifacts/Craftable/ResillientBracer.cs @@ -1,39 +1,39 @@ -namespace Server.Items -{ - public class ResilientBracer : GoldBracelet - { - [Constructible] - public ResilientBracer() - { - Hue = 0x488; - - SkillBonuses.SetValues(0, SkillName.MagicResist, 15.0); - - Attributes.BonusHits = 5; - Attributes.RegenHits = 2; - Attributes.DefendChance = 10; - } - - public ResilientBracer(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072933; // Resillient Bracer - - public override int PhysicalResistance => 20; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ResilientBracer : GoldBracelet + { + [Constructible] + public ResilientBracer() + { + Hue = 0x488; + + SkillBonuses.SetValues(0, SkillName.MagicResist, 15.0); + + Attributes.BonusHits = 5; + Attributes.RegenHits = 2; + Attributes.DefendChance = 10; + } + + public ResilientBracer(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072933; // Resillient Bracer + + public override int PhysicalResistance => 20; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Jewels/Artifacts/OrnamentOfTheMagician.cs b/Projects/UOContent/Items/Jewels/Artifacts/OrnamentOfTheMagician.cs index d472a3418..48a400415 100644 --- a/Projects/UOContent/Items/Jewels/Artifacts/OrnamentOfTheMagician.cs +++ b/Projects/UOContent/Items/Jewels/Artifacts/OrnamentOfTheMagician.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class OrnamentOfTheMagician : GoldBracelet - { - [Constructible] - public OrnamentOfTheMagician() - { - Hue = 0x554; - Attributes.CastRecovery = 3; - Attributes.CastSpeed = 2; - Attributes.LowerManaCost = 10; - Attributes.LowerRegCost = 20; - Resistances.Energy = 15; - } - - public OrnamentOfTheMagician(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061105; // Ornament of the Magician - public override int ArtifactRarity => 11; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Hue == 0x12B) - Hue = 0x554; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class OrnamentOfTheMagician : GoldBracelet + { + [Constructible] + public OrnamentOfTheMagician() + { + Hue = 0x554; + Attributes.CastRecovery = 3; + Attributes.CastSpeed = 2; + Attributes.LowerManaCost = 10; + Attributes.LowerRegCost = 20; + Resistances.Energy = 15; + } + + public OrnamentOfTheMagician(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061105; // Ornament of the Magician + public override int ArtifactRarity => 11; + + 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 == 0x12B) + Hue = 0x554; + } + } +} diff --git a/Projects/UOContent/Items/Jewels/Artifacts/RingOfTheElements.cs b/Projects/UOContent/Items/Jewels/Artifacts/RingOfTheElements.cs index 2c69ee1f7..25ffd9f83 100644 --- a/Projects/UOContent/Items/Jewels/Artifacts/RingOfTheElements.cs +++ b/Projects/UOContent/Items/Jewels/Artifacts/RingOfTheElements.cs @@ -1,37 +1,37 @@ -namespace Server.Items -{ - public class RingOfTheElements : GoldRing - { - [Constructible] - public RingOfTheElements() - { - Hue = 0x4E9; - Attributes.Luck = 100; - Resistances.Fire = 16; - Resistances.Cold = 16; - Resistances.Poison = 16; - Resistances.Energy = 16; - } - - public RingOfTheElements(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061104; // Ring of the Elements - public override int ArtifactRarity => 11; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class RingOfTheElements : GoldRing + { + [Constructible] + public RingOfTheElements() + { + Hue = 0x4E9; + Attributes.Luck = 100; + Resistances.Fire = 16; + Resistances.Cold = 16; + Resistances.Poison = 16; + Resistances.Energy = 16; + } + + public RingOfTheElements(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061104; // Ring of the Elements + public override int ArtifactRarity => 11; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Jewels/Artifacts/RingOfTheVile.cs b/Projects/UOContent/Items/Jewels/Artifacts/RingOfTheVile.cs index 70c6bc01b..bf17145bd 100644 --- a/Projects/UOContent/Items/Jewels/Artifacts/RingOfTheVile.cs +++ b/Projects/UOContent/Items/Jewels/Artifacts/RingOfTheVile.cs @@ -1,39 +1,39 @@ -namespace Server.Items -{ - public class RingOfTheVile : GoldRing - { - [Constructible] - public RingOfTheVile() - { - Hue = 0x4F7; - Attributes.BonusDex = 8; - Attributes.RegenStam = 6; - Attributes.AttackChance = 15; - Resistances.Poison = 20; - } - - public RingOfTheVile(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061102; // Ring of the Vile - public override int ArtifactRarity => 11; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Hue == 0x4F4) - Hue = 0x4F7; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class RingOfTheVile : GoldRing + { + [Constructible] + public RingOfTheVile() + { + Hue = 0x4F7; + Attributes.BonusDex = 8; + Attributes.RegenStam = 6; + Attributes.AttackChance = 15; + Resistances.Poison = 20; + } + + public RingOfTheVile(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061102; // Ring of the Vile + public override int ArtifactRarity => 11; + + 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 == 0x4F4) + Hue = 0x4F7; + } + } +} diff --git a/Projects/UOContent/Items/Jewels/BaseJewel.cs b/Projects/UOContent/Items/Jewels/BaseJewel.cs index b801e6032..21c40d228 100644 --- a/Projects/UOContent/Items/Jewels/BaseJewel.cs +++ b/Projects/UOContent/Items/Jewels/BaseJewel.cs @@ -1,400 +1,401 @@ -using System; -using Server.Engines.Craft; - -namespace Server.Items -{ - public enum GemType - { - None, - StarSapphire, - Emerald, - Sapphire, - Ruby, - Citrine, - Amethyst, - Tourmaline, - Amber, - Diamond - } - - public abstract class BaseJewel : Item, ICraftable - { - private GemType m_GemType; - private int m_HitPoints; - private int m_MaxHitPoints; - private CraftResource m_Resource; - - public BaseJewel(int itemID, Layer layer) : base(itemID) - { - Attributes = new AosAttributes(this); - Resistances = new AosElementAttributes(this); - SkillBonuses = new AosSkillBonuses(this); - m_Resource = CraftResource.Iron; - m_GemType = GemType.None; - - Layer = layer; - - m_HitPoints = m_MaxHitPoints = Utility.RandomMinMax(InitMinHits, InitMaxHits); - } - - public BaseJewel(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxHitPoints - { - get => m_MaxHitPoints; - set - { - m_MaxHitPoints = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int HitPoints - { - get => m_HitPoints; - set - { - if (value != m_HitPoints && MaxHitPoints > 0) - { - m_HitPoints = value; - - if (m_HitPoints < 0) - Delete(); - else if (m_HitPoints > MaxHitPoints) - m_HitPoints = MaxHitPoints; - - InvalidateProperties(); - } - } - } - - [CommandProperty(AccessLevel.Player)] - public AosAttributes Attributes { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public AosElementAttributes Resistances { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public AosSkillBonuses SkillBonuses { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public CraftResource Resource - { - get => m_Resource; - set - { - m_Resource = value; - Hue = CraftResources.GetHue(m_Resource); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public GemType GemType - { - get => m_GemType; - set - { - m_GemType = value; - InvalidateProperties(); - } - } - - public override int PhysicalResistance => Resistances.Physical; - public override int FireResistance => Resistances.Fire; - public override int ColdResistance => Resistances.Cold; - public override int PoisonResistance => Resistances.Poison; - public override int EnergyResistance => Resistances.Energy; - public virtual int BaseGemTypeNumber => 0; - - public virtual int InitMinHits => 0; - public virtual int InitMaxHits => 0; - - public override int LabelNumber - { - get - { - if (m_GemType == GemType.None) - return base.LabelNumber; - - return BaseGemTypeNumber + (int)m_GemType - 1; - } - } - - public virtual int ArtifactRarity => 0; - - public int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, - CraftItem craftItem, int resHue) - { - Type resourceType = typeRes ?? craftItem.Resources[0].ItemType; - - Resource = CraftResources.GetFromType(resourceType); - - CraftContext context = craftSystem.GetContext(from); - - if (context?.DoNotColor == true) - Hue = 0; - - if (craftItem.Resources.Count > 1) - { - resourceType = craftItem.Resources[1].ItemType; - - if (resourceType == typeof(StarSapphire)) - GemType = GemType.StarSapphire; - else if (resourceType == typeof(Emerald)) - GemType = GemType.Emerald; - else if (resourceType == typeof(Sapphire)) - GemType = GemType.Sapphire; - else if (resourceType == typeof(Ruby)) - GemType = GemType.Ruby; - else if (resourceType == typeof(Citrine)) - GemType = GemType.Citrine; - else if (resourceType == typeof(Amethyst)) - GemType = GemType.Amethyst; - else if (resourceType == typeof(Tourmaline)) - GemType = GemType.Tourmaline; - else if (resourceType == typeof(Amber)) - GemType = GemType.Amber; - else if (resourceType == typeof(Diamond)) - GemType = GemType.Diamond; - } - - return 1; - } - - public override void OnAfterDuped(Item newItem) - { - if (!(newItem is BaseJewel jewel)) - return; - - jewel.Attributes = new AosAttributes(newItem, Attributes); - jewel.Resistances = new AosElementAttributes(newItem, Resistances); - jewel.SkillBonuses = new AosSkillBonuses(newItem, SkillBonuses); - } - - public override void OnAdded(IEntity parent) - { - if (Core.AOS && parent is Mobile from) - { - SkillBonuses.AddTo(from); - - int strBonus = Attributes.BonusStr; - int dexBonus = Attributes.BonusDex; - int intBonus = Attributes.BonusInt; - - if (strBonus != 0 || dexBonus != 0 || intBonus != 0) - { - string modName = Serial.ToString(); - - if (strBonus != 0) - from.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero)); - - if (dexBonus != 0) - from.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero)); - - if (intBonus != 0) - from.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero)); - } - - from.CheckStatTimers(); - } - } - - public override void OnRemoved(IEntity parent) - { - if (Core.AOS && parent is Mobile from) - { - SkillBonuses.Remove(); - - string modName = Serial.ToString(); - - from.RemoveStatMod($"{modName}Str"); - from.RemoveStatMod($"{modName}Dex"); - from.RemoveStatMod($"{modName}Int"); - - from.CheckStatTimers(); - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - SkillBonuses.GetProperties(list); - - int prop; - - if ((prop = ArtifactRarity) > 0) - list.Add(1061078, prop.ToString()); // artifact rarity ~1_val~ - - if ((prop = Attributes.WeaponDamage) != 0) - list.Add(1060401, prop.ToString()); // damage increase ~1_val~% - - if ((prop = Attributes.DefendChance) != 0) - list.Add(1060408, prop.ToString()); // defense chance increase ~1_val~% - - if ((prop = Attributes.BonusDex) != 0) - list.Add(1060409, prop.ToString()); // dexterity bonus ~1_val~ - - if ((prop = Attributes.EnhancePotions) != 0) - list.Add(1060411, prop.ToString()); // enhance potions ~1_val~% - - if ((prop = Attributes.CastRecovery) != 0) - list.Add(1060412, prop.ToString()); // faster cast recovery ~1_val~ - - if ((prop = Attributes.CastSpeed) != 0) - list.Add(1060413, prop.ToString()); // faster casting ~1_val~ - - if ((prop = Attributes.AttackChance) != 0) - list.Add(1060415, prop.ToString()); // hit chance increase ~1_val~% - - if ((prop = Attributes.BonusHits) != 0) - list.Add(1060431, prop.ToString()); // hit point increase ~1_val~ - - if ((prop = Attributes.BonusInt) != 0) - list.Add(1060432, prop.ToString()); // intelligence bonus ~1_val~ - - if ((prop = Attributes.LowerManaCost) != 0) - list.Add(1060433, prop.ToString()); // lower mana cost ~1_val~% - - if ((prop = Attributes.LowerRegCost) != 0) - list.Add(1060434, prop.ToString()); // lower reagent cost ~1_val~% - - if ((prop = Attributes.Luck) != 0) - list.Add(1060436, prop.ToString()); // luck ~1_val~ - - if ((prop = Attributes.BonusMana) != 0) - list.Add(1060439, prop.ToString()); // mana increase ~1_val~ - - if ((prop = Attributes.RegenMana) != 0) - list.Add(1060440, prop.ToString()); // mana regeneration ~1_val~ - - if (Attributes.NightSight != 0) - list.Add(1060441); // night sight - - if ((prop = Attributes.ReflectPhysical) != 0) - list.Add(1060442, prop.ToString()); // reflect physical damage ~1_val~% - - if ((prop = Attributes.RegenStam) != 0) - list.Add(1060443, prop.ToString()); // stamina regeneration ~1_val~ - - if ((prop = Attributes.RegenHits) != 0) - list.Add(1060444, prop.ToString()); // hit point regeneration ~1_val~ - - if (Attributes.SpellChanneling != 0) - list.Add(1060482); // spell channeling - - if ((prop = Attributes.SpellDamage) != 0) - list.Add(1060483, prop.ToString()); // spell damage increase ~1_val~% - - if ((prop = Attributes.BonusStam) != 0) - list.Add(1060484, prop.ToString()); // stamina increase ~1_val~ - - if ((prop = Attributes.BonusStr) != 0) - list.Add(1060485, prop.ToString()); // strength bonus ~1_val~ - - if ((prop = Attributes.WeaponSpeed) != 0) - list.Add(1060486, prop.ToString()); // swing speed increase ~1_val~% - - if (Core.ML && (prop = Attributes.IncreasedKarmaLoss) != 0) - list.Add(1075210, prop.ToString()); // Increased Karma Loss ~1val~% - - AddResistanceProperties(list); - - if (m_HitPoints >= 0 && m_MaxHitPoints > 0) - list.Add(1060639, "{0}\t{1}", m_HitPoints, m_MaxHitPoints); // durability ~1_val~ / ~2_val~ - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(3); // version - - writer.WriteEncodedInt(m_MaxHitPoints); - writer.WriteEncodedInt(m_HitPoints); - - writer.WriteEncodedInt((int)m_Resource); - writer.WriteEncodedInt((int)m_GemType); - - Attributes.Serialize(writer); - Resistances.Serialize(writer); - SkillBonuses.Serialize(writer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 3: - { - m_MaxHitPoints = reader.ReadEncodedInt(); - m_HitPoints = reader.ReadEncodedInt(); - - goto case 2; - } - case 2: - { - m_Resource = (CraftResource)reader.ReadEncodedInt(); - m_GemType = (GemType)reader.ReadEncodedInt(); - - goto case 1; - } - case 1: - { - Attributes = new AosAttributes(this, reader); - Resistances = new AosElementAttributes(this, reader); - SkillBonuses = new AosSkillBonuses(this, reader); - - Mobile m = Parent as Mobile; - - if (Core.AOS && m != null) - SkillBonuses.AddTo(m); - - int strBonus = Attributes.BonusStr; - int dexBonus = Attributes.BonusDex; - int intBonus = Attributes.BonusInt; - - if (m != null && (strBonus != 0 || dexBonus != 0 || intBonus != 0)) - { - string modName = Serial.ToString(); - - if (strBonus != 0) - m.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero)); - - if (dexBonus != 0) - m.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero)); - - if (intBonus != 0) - m.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero)); - } - - m?.CheckStatTimers(); - - break; - } - case 0: - { - Attributes = new AosAttributes(this); - Resistances = new AosElementAttributes(this); - SkillBonuses = new AosSkillBonuses(this); - - break; - } - } - - if (version < 2) - { - m_Resource = CraftResource.Iron; - m_GemType = GemType.None; - } - } - } -} +using System; +using Server.Engines.Craft; + +namespace Server.Items +{ + public enum GemType + { + None, + StarSapphire, + Emerald, + Sapphire, + Ruby, + Citrine, + Amethyst, + Tourmaline, + Amber, + Diamond + } + + public abstract class BaseJewel : Item, ICraftable + { + private GemType m_GemType; + private int m_HitPoints; + private int m_MaxHitPoints; + private CraftResource m_Resource; + + public BaseJewel(int itemID, Layer layer) : base(itemID) + { + Attributes = new AosAttributes(this); + Resistances = new AosElementAttributes(this); + SkillBonuses = new AosSkillBonuses(this); + m_Resource = CraftResource.Iron; + m_GemType = GemType.None; + + Layer = layer; + + m_HitPoints = m_MaxHitPoints = Utility.RandomMinMax(InitMinHits, InitMaxHits); + } + + public BaseJewel(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxHitPoints + { + get => m_MaxHitPoints; + set + { + m_MaxHitPoints = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int HitPoints + { + get => m_HitPoints; + set + { + if (value != m_HitPoints && MaxHitPoints > 0) + { + m_HitPoints = value; + + if (m_HitPoints < 0) + Delete(); + else if (m_HitPoints > MaxHitPoints) + m_HitPoints = MaxHitPoints; + + InvalidateProperties(); + } + } + } + + [CommandProperty(AccessLevel.Player)] public AosAttributes Attributes { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public AosElementAttributes Resistances { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public AosSkillBonuses SkillBonuses { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public CraftResource Resource + { + get => m_Resource; + set + { + m_Resource = value; + Hue = CraftResources.GetHue(m_Resource); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public GemType GemType + { + get => m_GemType; + set + { + m_GemType = value; + InvalidateProperties(); + } + } + + public override int PhysicalResistance => Resistances.Physical; + public override int FireResistance => Resistances.Fire; + public override int ColdResistance => Resistances.Cold; + public override int PoisonResistance => Resistances.Poison; + public override int EnergyResistance => Resistances.Energy; + public virtual int BaseGemTypeNumber => 0; + + public virtual int InitMinHits => 0; + public virtual int InitMaxHits => 0; + + public override int LabelNumber + { + get + { + if (m_GemType == GemType.None) + return base.LabelNumber; + + return BaseGemTypeNumber + (int)m_GemType - 1; + } + } + + public virtual int ArtifactRarity => 0; + + public int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, + CraftItem craftItem, int resHue + ) + { + var resourceType = typeRes ?? craftItem.Resources[0].ItemType; + + Resource = CraftResources.GetFromType(resourceType); + + var context = craftSystem.GetContext(from); + + if (context?.DoNotColor == true) + Hue = 0; + + if (craftItem.Resources.Count > 1) + { + resourceType = craftItem.Resources[1].ItemType; + + if (resourceType == typeof(StarSapphire)) + GemType = GemType.StarSapphire; + else if (resourceType == typeof(Emerald)) + GemType = GemType.Emerald; + else if (resourceType == typeof(Sapphire)) + GemType = GemType.Sapphire; + else if (resourceType == typeof(Ruby)) + GemType = GemType.Ruby; + else if (resourceType == typeof(Citrine)) + GemType = GemType.Citrine; + else if (resourceType == typeof(Amethyst)) + GemType = GemType.Amethyst; + else if (resourceType == typeof(Tourmaline)) + GemType = GemType.Tourmaline; + else if (resourceType == typeof(Amber)) + GemType = GemType.Amber; + else if (resourceType == typeof(Diamond)) + GemType = GemType.Diamond; + } + + return 1; + } + + public override void OnAfterDuped(Item newItem) + { + if (!(newItem is BaseJewel jewel)) + return; + + jewel.Attributes = new AosAttributes(newItem, Attributes); + jewel.Resistances = new AosElementAttributes(newItem, Resistances); + jewel.SkillBonuses = new AosSkillBonuses(newItem, SkillBonuses); + } + + public override void OnAdded(IEntity parent) + { + if (Core.AOS && parent is Mobile from) + { + SkillBonuses.AddTo(from); + + var strBonus = Attributes.BonusStr; + var dexBonus = Attributes.BonusDex; + var intBonus = Attributes.BonusInt; + + if (strBonus != 0 || dexBonus != 0 || intBonus != 0) + { + var modName = Serial.ToString(); + + if (strBonus != 0) + from.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero)); + + if (dexBonus != 0) + from.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero)); + + if (intBonus != 0) + from.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero)); + } + + from.CheckStatTimers(); + } + } + + public override void OnRemoved(IEntity parent) + { + if (Core.AOS && parent is Mobile from) + { + SkillBonuses.Remove(); + + var modName = Serial.ToString(); + + from.RemoveStatMod($"{modName}Str"); + from.RemoveStatMod($"{modName}Dex"); + from.RemoveStatMod($"{modName}Int"); + + from.CheckStatTimers(); + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + SkillBonuses.GetProperties(list); + + int prop; + + if ((prop = ArtifactRarity) > 0) + list.Add(1061078, prop.ToString()); // artifact rarity ~1_val~ + + if ((prop = Attributes.WeaponDamage) != 0) + list.Add(1060401, prop.ToString()); // damage increase ~1_val~% + + if ((prop = Attributes.DefendChance) != 0) + list.Add(1060408, prop.ToString()); // defense chance increase ~1_val~% + + if ((prop = Attributes.BonusDex) != 0) + list.Add(1060409, prop.ToString()); // dexterity bonus ~1_val~ + + if ((prop = Attributes.EnhancePotions) != 0) + list.Add(1060411, prop.ToString()); // enhance potions ~1_val~% + + if ((prop = Attributes.CastRecovery) != 0) + list.Add(1060412, prop.ToString()); // faster cast recovery ~1_val~ + + if ((prop = Attributes.CastSpeed) != 0) + list.Add(1060413, prop.ToString()); // faster casting ~1_val~ + + if ((prop = Attributes.AttackChance) != 0) + list.Add(1060415, prop.ToString()); // hit chance increase ~1_val~% + + if ((prop = Attributes.BonusHits) != 0) + list.Add(1060431, prop.ToString()); // hit point increase ~1_val~ + + if ((prop = Attributes.BonusInt) != 0) + list.Add(1060432, prop.ToString()); // intelligence bonus ~1_val~ + + if ((prop = Attributes.LowerManaCost) != 0) + list.Add(1060433, prop.ToString()); // lower mana cost ~1_val~% + + if ((prop = Attributes.LowerRegCost) != 0) + list.Add(1060434, prop.ToString()); // lower reagent cost ~1_val~% + + if ((prop = Attributes.Luck) != 0) + list.Add(1060436, prop.ToString()); // luck ~1_val~ + + if ((prop = Attributes.BonusMana) != 0) + list.Add(1060439, prop.ToString()); // mana increase ~1_val~ + + if ((prop = Attributes.RegenMana) != 0) + list.Add(1060440, prop.ToString()); // mana regeneration ~1_val~ + + if (Attributes.NightSight != 0) + list.Add(1060441); // night sight + + if ((prop = Attributes.ReflectPhysical) != 0) + list.Add(1060442, prop.ToString()); // reflect physical damage ~1_val~% + + if ((prop = Attributes.RegenStam) != 0) + list.Add(1060443, prop.ToString()); // stamina regeneration ~1_val~ + + if ((prop = Attributes.RegenHits) != 0) + list.Add(1060444, prop.ToString()); // hit point regeneration ~1_val~ + + if (Attributes.SpellChanneling != 0) + list.Add(1060482); // spell channeling + + if ((prop = Attributes.SpellDamage) != 0) + list.Add(1060483, prop.ToString()); // spell damage increase ~1_val~% + + if ((prop = Attributes.BonusStam) != 0) + list.Add(1060484, prop.ToString()); // stamina increase ~1_val~ + + if ((prop = Attributes.BonusStr) != 0) + list.Add(1060485, prop.ToString()); // strength bonus ~1_val~ + + if ((prop = Attributes.WeaponSpeed) != 0) + list.Add(1060486, prop.ToString()); // swing speed increase ~1_val~% + + if (Core.ML && (prop = Attributes.IncreasedKarmaLoss) != 0) + list.Add(1075210, prop.ToString()); // Increased Karma Loss ~1val~% + + AddResistanceProperties(list); + + if (m_HitPoints >= 0 && m_MaxHitPoints > 0) + list.Add(1060639, "{0}\t{1}", m_HitPoints, m_MaxHitPoints); // durability ~1_val~ / ~2_val~ + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(3); // version + + writer.WriteEncodedInt(m_MaxHitPoints); + writer.WriteEncodedInt(m_HitPoints); + + writer.WriteEncodedInt((int)m_Resource); + writer.WriteEncodedInt((int)m_GemType); + + Attributes.Serialize(writer); + Resistances.Serialize(writer); + SkillBonuses.Serialize(writer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 3: + { + m_MaxHitPoints = reader.ReadEncodedInt(); + m_HitPoints = reader.ReadEncodedInt(); + + goto case 2; + } + case 2: + { + m_Resource = (CraftResource)reader.ReadEncodedInt(); + m_GemType = (GemType)reader.ReadEncodedInt(); + + goto case 1; + } + case 1: + { + Attributes = new AosAttributes(this, reader); + Resistances = new AosElementAttributes(this, reader); + SkillBonuses = new AosSkillBonuses(this, reader); + + var m = Parent as Mobile; + + if (Core.AOS && m != null) + SkillBonuses.AddTo(m); + + var strBonus = Attributes.BonusStr; + var dexBonus = Attributes.BonusDex; + var intBonus = Attributes.BonusInt; + + if (m != null && (strBonus != 0 || dexBonus != 0 || intBonus != 0)) + { + var modName = Serial.ToString(); + + if (strBonus != 0) + m.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero)); + + if (dexBonus != 0) + m.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero)); + + if (intBonus != 0) + m.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero)); + } + + m?.CheckStatTimers(); + + break; + } + case 0: + { + Attributes = new AosAttributes(this); + Resistances = new AosElementAttributes(this); + SkillBonuses = new AosSkillBonuses(this); + + break; + } + } + + if (version < 2) + { + m_Resource = CraftResource.Iron; + m_GemType = GemType.None; + } + } + } +} diff --git a/Projects/UOContent/Items/Jewels/Beads.cs b/Projects/UOContent/Items/Jewels/Beads.cs index 87075e221..da34bfca4 100644 --- a/Projects/UOContent/Items/Jewels/Beads.cs +++ b/Projects/UOContent/Items/Jewels/Beads.cs @@ -1,24 +1,24 @@ -namespace Server.Items -{ - public class Beads : Item - { - [Constructible] - public Beads() : base(0x108B) => Weight = 1.0; - - public Beads(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Beads : Item + { + [Constructible] + public Beads() : base(0x108B) => Weight = 1.0; + + public Beads(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Jewels/Bracelet.cs b/Projects/UOContent/Items/Jewels/Bracelet.cs index 094962642..f300bd582 100644 --- a/Projects/UOContent/Items/Jewels/Bracelet.cs +++ b/Projects/UOContent/Items/Jewels/Bracelet.cs @@ -1,77 +1,77 @@ -namespace Server.Items -{ - public abstract class BaseBracelet : BaseJewel - { - public BaseBracelet(int itemID) : base(itemID, Layer.Bracelet) - { - } - - public BaseBracelet(Serial serial) : base(serial) - { - } - - public override int BaseGemTypeNumber => 1044221; // star sapphire bracelet - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GoldBracelet : BaseBracelet - { - [Constructible] - public GoldBracelet() : base(0x1086) => Weight = 0.1; - - public GoldBracelet(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SilverBracelet : BaseBracelet - { - [Constructible] - public SilverBracelet() : base(0x1F06) => Weight = 0.1; - - public SilverBracelet(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public abstract class BaseBracelet : BaseJewel + { + public BaseBracelet(int itemID) : base(itemID, Layer.Bracelet) + { + } + + public BaseBracelet(Serial serial) : base(serial) + { + } + + public override int BaseGemTypeNumber => 1044221; // star sapphire bracelet + + 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 class GoldBracelet : BaseBracelet + { + [Constructible] + public GoldBracelet() : base(0x1086) => Weight = 0.1; + + public GoldBracelet(Serial serial) : base(serial) + { + } + + 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 class SilverBracelet : BaseBracelet + { + [Constructible] + public SilverBracelet() : base(0x1F06) => Weight = 0.1; + + public SilverBracelet(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Jewels/Earrings.cs b/Projects/UOContent/Items/Jewels/Earrings.cs index 2a323495c..f99ae91dd 100644 --- a/Projects/UOContent/Items/Jewels/Earrings.cs +++ b/Projects/UOContent/Items/Jewels/Earrings.cs @@ -1,77 +1,77 @@ -namespace Server.Items -{ - public abstract class BaseEarrings : BaseJewel - { - public BaseEarrings(int itemID) : base(itemID, Layer.Earrings) - { - } - - public BaseEarrings(Serial serial) : base(serial) - { - } - - public override int BaseGemTypeNumber => 1044203; // star sapphire earrings - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GoldEarrings : BaseEarrings - { - [Constructible] - public GoldEarrings() : base(0x1087) => Weight = 0.1; - - public GoldEarrings(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SilverEarrings : BaseEarrings - { - [Constructible] - public SilverEarrings() : base(0x1F07) => Weight = 0.1; - - public SilverEarrings(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public abstract class BaseEarrings : BaseJewel + { + public BaseEarrings(int itemID) : base(itemID, Layer.Earrings) + { + } + + public BaseEarrings(Serial serial) : base(serial) + { + } + + public override int BaseGemTypeNumber => 1044203; // star sapphire earrings + + 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 class GoldEarrings : BaseEarrings + { + [Constructible] + public GoldEarrings() : base(0x1087) => Weight = 0.1; + + public GoldEarrings(Serial serial) : base(serial) + { + } + + 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 class SilverEarrings : BaseEarrings + { + [Constructible] + public SilverEarrings() : base(0x1F07) => Weight = 0.1; + + public SilverEarrings(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Jewels/Necklace.cs b/Projects/UOContent/Items/Jewels/Necklace.cs index 93ab4f3ae..baa9cc827 100644 --- a/Projects/UOContent/Items/Jewels/Necklace.cs +++ b/Projects/UOContent/Items/Jewels/Necklace.cs @@ -1,149 +1,149 @@ -namespace Server.Items -{ - public abstract class BaseNecklace : BaseJewel - { - public BaseNecklace(int itemID) : base(itemID, Layer.Neck) - { - } - - public BaseNecklace(Serial serial) : base(serial) - { - } - - public override int BaseGemTypeNumber => 1044241; // star sapphire necklace - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Necklace : BaseNecklace - { - [Constructible] - public Necklace() : base(0x1085) => Weight = 0.1; - - public Necklace(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GoldNecklace : BaseNecklace - { - [Constructible] - public GoldNecklace() : base(0x1088) => Weight = 0.1; - - public GoldNecklace(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GoldBeadNecklace : BaseNecklace - { - [Constructible] - public GoldBeadNecklace() : base(0x1089) => Weight = 0.1; - - public GoldBeadNecklace(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SilverNecklace : BaseNecklace - { - [Constructible] - public SilverNecklace() : base(0x1F08) => Weight = 0.1; - - public SilverNecklace(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SilverBeadNecklace : BaseNecklace - { - [Constructible] - public SilverBeadNecklace() : base(0x1F05) => Weight = 0.1; - - public SilverBeadNecklace(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public abstract class BaseNecklace : BaseJewel + { + public BaseNecklace(int itemID) : base(itemID, Layer.Neck) + { + } + + public BaseNecklace(Serial serial) : base(serial) + { + } + + public override int BaseGemTypeNumber => 1044241; // star sapphire necklace + + 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 class Necklace : BaseNecklace + { + [Constructible] + public Necklace() : base(0x1085) => Weight = 0.1; + + public Necklace(Serial serial) : base(serial) + { + } + + 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 class GoldNecklace : BaseNecklace + { + [Constructible] + public GoldNecklace() : base(0x1088) => Weight = 0.1; + + public GoldNecklace(Serial serial) : base(serial) + { + } + + 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 class GoldBeadNecklace : BaseNecklace + { + [Constructible] + public GoldBeadNecklace() : base(0x1089) => Weight = 0.1; + + public GoldBeadNecklace(Serial serial) : base(serial) + { + } + + 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 class SilverNecklace : BaseNecklace + { + [Constructible] + public SilverNecklace() : base(0x1F08) => Weight = 0.1; + + public SilverNecklace(Serial serial) : base(serial) + { + } + + 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 class SilverBeadNecklace : BaseNecklace + { + [Constructible] + public SilverBeadNecklace() : base(0x1F05) => Weight = 0.1; + + public SilverBeadNecklace(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Jewels/Ring.cs b/Projects/UOContent/Items/Jewels/Ring.cs index a542d7b0a..140840ace 100644 --- a/Projects/UOContent/Items/Jewels/Ring.cs +++ b/Projects/UOContent/Items/Jewels/Ring.cs @@ -1,77 +1,77 @@ -namespace Server.Items -{ - public abstract class BaseRing : BaseJewel - { - public BaseRing(int itemID) : base(itemID, Layer.Ring) - { - } - - public BaseRing(Serial serial) : base(serial) - { - } - - public override int BaseGemTypeNumber => 1044176; // star sapphire ring - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GoldRing : BaseRing - { - [Constructible] - public GoldRing() : base(0x108a) => Weight = 0.1; - - public GoldRing(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SilverRing : BaseRing - { - [Constructible] - public SilverRing() : base(0x1F09) => Weight = 0.1; - - public SilverRing(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public abstract class BaseRing : BaseJewel + { + public BaseRing(int itemID) : base(itemID, Layer.Ring) + { + } + + public BaseRing(Serial serial) : base(serial) + { + } + + public override int BaseGemTypeNumber => 1044176; // star sapphire ring + + 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 class GoldRing : BaseRing + { + [Constructible] + public GoldRing() : base(0x108a) => Weight = 0.1; + + public GoldRing(Serial serial) : base(serial) + { + } + + 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 class SilverRing : BaseRing + { + [Constructible] + public SilverRing() : base(0x1F09) => Weight = 0.1; + + public SilverRing(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/BaseEquippableLight.cs b/Projects/UOContent/Items/Lights/BaseEquippableLight.cs index e687056a1..69014e04e 100644 --- a/Projects/UOContent/Items/Lights/BaseEquippableLight.cs +++ b/Projects/UOContent/Items/Lights/BaseEquippableLight.cs @@ -1,56 +1,56 @@ -namespace Server.Items -{ - public abstract class BaseEquipableLight : BaseLight - { - [Constructible] - public BaseEquipableLight(int itemID) : base(itemID) => Layer = Layer.TwoHanded; - - public BaseEquipableLight(Serial serial) : base(serial) - { - } - - public override void Ignite() - { - if (!(Parent is Mobile) && RootParent is Mobile holder) - { - if (holder.EquipItem(this)) - { - if (this is Candle) - holder.SendLocalizedMessage(502969); // You put the candle in your left hand. - else if (this is Torch) - holder.SendLocalizedMessage(502971); // You put the torch in your left hand. - - base.Ignite(); - } - else - { - holder.SendLocalizedMessage(502449); // You cannot hold this item. - } - } - else - { - base.Ignite(); - } - } - - public override void OnAdded(IEntity parent) - { - if (Burning && parent is Container) - Douse(); - - base.OnAdded(parent); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public abstract class BaseEquipableLight : BaseLight + { + [Constructible] + public BaseEquipableLight(int itemID) : base(itemID) => Layer = Layer.TwoHanded; + + public BaseEquipableLight(Serial serial) : base(serial) + { + } + + public override void Ignite() + { + if (!(Parent is Mobile) && RootParent is Mobile holder) + { + if (holder.EquipItem(this)) + { + if (this is Candle) + holder.SendLocalizedMessage(502969); // You put the candle in your left hand. + else if (this is Torch) + holder.SendLocalizedMessage(502971); // You put the torch in your left hand. + + base.Ignite(); + } + else + { + holder.SendLocalizedMessage(502449); // You cannot hold this item. + } + } + else + { + base.Ignite(); + } + } + + public override void OnAdded(IEntity parent) + { + if (Burning && parent is Container) + Douse(); + + base.OnAdded(parent); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/BaseLight.cs b/Projects/UOContent/Items/Lights/BaseLight.cs index 895d5f6dd..c14a26f53 100644 --- a/Projects/UOContent/Items/Lights/BaseLight.cs +++ b/Projects/UOContent/Items/Lights/BaseLight.cs @@ -1,215 +1,215 @@ -using System; - -namespace Server.Items -{ - public abstract class BaseLight : Item - { - public static readonly bool Burnout = false; - private bool m_Burning; - private TimeSpan m_Duration = TimeSpan.Zero; - private DateTime m_End; - private Timer m_Timer; - - [Constructible] - public BaseLight(int itemID) : base(itemID) - { - } - - public BaseLight(Serial serial) : base(serial) - { - } - - public abstract int LitItemID { get; } - - public virtual int UnlitItemID => 0; - public virtual int BurntOutItemID => 0; - - public virtual int LitSound => 0x47; - public virtual int UnlitSound => 0x3be; - public virtual int BurntOutSound => 0x4b8; - - [CommandProperty(AccessLevel.GameMaster)] - public bool Burning - { - get => m_Burning; - set - { - if (m_Burning != value) - { - m_Burning = true; - DoTimer(m_Duration); - } - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool BurntOut { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Protected { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan Duration - { - get - { - if (m_Duration != TimeSpan.Zero && m_Burning) return m_End - DateTime.UtcNow; - - return m_Duration; - } - - set => m_Duration = value; - } - - public virtual void PlayLitSound() - { - if (LitSound != 0) - { - Point3D loc = GetWorldLocation(); - Effects.PlaySound(loc, Map, LitSound); - } - } - - public virtual void PlayUnlitSound() - { - int sound = UnlitSound; - - if (BurntOut && BurntOutSound != 0) - sound = BurntOutSound; - - if (sound != 0) - { - Point3D loc = GetWorldLocation(); - Effects.PlaySound(loc, Map, sound); - } - } - - public virtual void Ignite() - { - if (!BurntOut) - { - PlayLitSound(); - - m_Burning = true; - ItemID = LitItemID; - DoTimer(m_Duration); - } - } - - public virtual void Douse() - { - m_Burning = false; - - if (BurntOut && BurntOutItemID != 0) - ItemID = BurntOutItemID; - else - ItemID = UnlitItemID; - - if (BurntOut) - m_Duration = TimeSpan.Zero; - else if (m_Duration != TimeSpan.Zero) - m_Duration = m_End - DateTime.UtcNow; - - m_Timer?.Stop(); - - PlayUnlitSound(); - } - - public virtual void Burn() - { - BurntOut = true; - Douse(); - } - - private void DoTimer(TimeSpan delay) - { - m_Duration = delay; - - m_Timer?.Stop(); - - if (delay == TimeSpan.Zero) - return; - - m_End = DateTime.UtcNow + delay; - - m_Timer = new InternalTimer(this, delay); - m_Timer.Start(); - } - - public override void OnDoubleClick(Mobile from) - { - if (BurntOut) - return; - - if (Protected && from.AccessLevel == AccessLevel.Player) - return; - - if (!from.InRange(GetWorldLocation(), 2)) - return; - - if (m_Burning) - { - if (UnlitItemID != 0) - Douse(); - } - else - { - Ignite(); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - writer.Write(BurntOut); - writer.Write(m_Burning); - writer.Write(m_Duration); - writer.Write(Protected); - - if (m_Burning && m_Duration != TimeSpan.Zero) - writer.WriteDeltaTime(m_End); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - BurntOut = reader.ReadBool(); - m_Burning = reader.ReadBool(); - m_Duration = reader.ReadTimeSpan(); - Protected = reader.ReadBool(); - - if (m_Burning && m_Duration != TimeSpan.Zero) - DoTimer(reader.ReadDeltaTime() - DateTime.UtcNow); - - break; - } - } - } - - private class InternalTimer : Timer - { - private readonly BaseLight m_Light; - - public InternalTimer(BaseLight light, TimeSpan delay) : base(delay) - { - m_Light = light; - Priority = TimerPriority.FiveSeconds; - } - - protected override void OnTick() - { - if (m_Light?.Deleted == false) - m_Light.Burn(); - } - } - } -} +using System; + +namespace Server.Items +{ + public abstract class BaseLight : Item + { + public static readonly bool Burnout = false; + private bool m_Burning; + private TimeSpan m_Duration = TimeSpan.Zero; + private DateTime m_End; + private Timer m_Timer; + + [Constructible] + public BaseLight(int itemID) : base(itemID) + { + } + + public BaseLight(Serial serial) : base(serial) + { + } + + public abstract int LitItemID { get; } + + public virtual int UnlitItemID => 0; + public virtual int BurntOutItemID => 0; + + public virtual int LitSound => 0x47; + public virtual int UnlitSound => 0x3be; + public virtual int BurntOutSound => 0x4b8; + + [CommandProperty(AccessLevel.GameMaster)] + public bool Burning + { + get => m_Burning; + set + { + if (m_Burning != value) + { + m_Burning = true; + DoTimer(m_Duration); + } + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool BurntOut { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Protected { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan Duration + { + get + { + if (m_Duration != TimeSpan.Zero && m_Burning) return m_End - DateTime.UtcNow; + + return m_Duration; + } + + set => m_Duration = value; + } + + public virtual void PlayLitSound() + { + if (LitSound != 0) + { + var loc = GetWorldLocation(); + Effects.PlaySound(loc, Map, LitSound); + } + } + + public virtual void PlayUnlitSound() + { + var sound = UnlitSound; + + if (BurntOut && BurntOutSound != 0) + sound = BurntOutSound; + + if (sound != 0) + { + var loc = GetWorldLocation(); + Effects.PlaySound(loc, Map, sound); + } + } + + public virtual void Ignite() + { + if (!BurntOut) + { + PlayLitSound(); + + m_Burning = true; + ItemID = LitItemID; + DoTimer(m_Duration); + } + } + + public virtual void Douse() + { + m_Burning = false; + + if (BurntOut && BurntOutItemID != 0) + ItemID = BurntOutItemID; + else + ItemID = UnlitItemID; + + if (BurntOut) + m_Duration = TimeSpan.Zero; + else if (m_Duration != TimeSpan.Zero) + m_Duration = m_End - DateTime.UtcNow; + + m_Timer?.Stop(); + + PlayUnlitSound(); + } + + public virtual void Burn() + { + BurntOut = true; + Douse(); + } + + private void DoTimer(TimeSpan delay) + { + m_Duration = delay; + + m_Timer?.Stop(); + + if (delay == TimeSpan.Zero) + return; + + m_End = DateTime.UtcNow + delay; + + m_Timer = new InternalTimer(this, delay); + m_Timer.Start(); + } + + public override void OnDoubleClick(Mobile from) + { + if (BurntOut) + return; + + if (Protected && from.AccessLevel == AccessLevel.Player) + return; + + if (!from.InRange(GetWorldLocation(), 2)) + return; + + if (m_Burning) + { + if (UnlitItemID != 0) + Douse(); + } + else + { + Ignite(); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + writer.Write(BurntOut); + writer.Write(m_Burning); + writer.Write(m_Duration); + writer.Write(Protected); + + if (m_Burning && m_Duration != TimeSpan.Zero) + writer.WriteDeltaTime(m_End); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + BurntOut = reader.ReadBool(); + m_Burning = reader.ReadBool(); + m_Duration = reader.ReadTimeSpan(); + Protected = reader.ReadBool(); + + if (m_Burning && m_Duration != TimeSpan.Zero) + DoTimer(reader.ReadDeltaTime() - DateTime.UtcNow); + + break; + } + } + } + + private class InternalTimer : Timer + { + private readonly BaseLight m_Light; + + public InternalTimer(BaseLight light, TimeSpan delay) : base(delay) + { + m_Light = light; + Priority = TimerPriority.FiveSeconds; + } + + protected override void OnTick() + { + if (m_Light?.Deleted == false) + m_Light.Burn(); + } + } + } +} diff --git a/Projects/UOContent/Items/Lights/Brazier.cs b/Projects/UOContent/Items/Lights/Brazier.cs index b3c00b15f..65b6f8066 100644 --- a/Projects/UOContent/Items/Lights/Brazier.cs +++ b/Projects/UOContent/Items/Lights/Brazier.cs @@ -1,35 +1,35 @@ -using System; - -namespace Server.Items -{ - public class Brazier : BaseLight - { - [Constructible] - public Brazier() : base(0xE31) - { - Movable = false; - Duration = TimeSpan.Zero; // Never burnt out - Burning = true; - Light = LightType.Circle225; - Weight = 20.0; - } - - public Brazier(Serial serial) : base(serial) - { - } - - public override int LitItemID => 0xE31; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class Brazier : BaseLight + { + [Constructible] + public Brazier() : base(0xE31) + { + Movable = false; + Duration = TimeSpan.Zero; // Never burnt out + Burning = true; + Light = LightType.Circle225; + Weight = 20.0; + } + + public Brazier(Serial serial) : base(serial) + { + } + + public override int LitItemID => 0xE31; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/BrazierTall.cs b/Projects/UOContent/Items/Lights/BrazierTall.cs index 30bf1d9f0..0774217a8 100644 --- a/Projects/UOContent/Items/Lights/BrazierTall.cs +++ b/Projects/UOContent/Items/Lights/BrazierTall.cs @@ -1,35 +1,35 @@ -using System; - -namespace Server.Items -{ - public class BrazierTall : BaseLight - { - [Constructible] - public BrazierTall() : base(0x19AA) - { - Movable = false; - Duration = TimeSpan.Zero; // Never burnt out - Burning = true; - Light = LightType.Circle300; - Weight = 25.0; - } - - public BrazierTall(Serial serial) : base(serial) - { - } - - public override int LitItemID => 0x19AA; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class BrazierTall : BaseLight + { + [Constructible] + public BrazierTall() : base(0x19AA) + { + Movable = false; + Duration = TimeSpan.Zero; // Never burnt out + Burning = true; + Light = LightType.Circle300; + Weight = 25.0; + } + + public BrazierTall(Serial serial) : base(serial) + { + } + + public override int LitItemID => 0x19AA; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/Candelabra.cs b/Projects/UOContent/Items/Lights/Candelabra.cs index 645fd66db..4d45c9fae 100644 --- a/Projects/UOContent/Items/Lights/Candelabra.cs +++ b/Projects/UOContent/Items/Lights/Candelabra.cs @@ -1,65 +1,65 @@ -using System; - -namespace Server.Items -{ - public class Candelabra : BaseLight, IShipwreckedItem - { - [Constructible] - public Candelabra() : base(0xA27) - { - Duration = TimeSpan.Zero; // Never burnt out - Burning = false; - Light = LightType.Circle225; - Weight = 3.0; - } - - public Candelabra(Serial serial) : base(serial) - { - } - - public override int LitItemID => 0xB1D; - public override int UnlitItemID => 0xA27; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsShipwreckedItem { get; set; } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); - - writer.Write(IsShipwreckedItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - IsShipwreckedItem = reader.ReadBool(); - break; - } - } - } - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - if (IsShipwreckedItem) - list.Add(1041645); // recovered from a shipwreck - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - if (IsShipwreckedItem) - LabelTo(from, 1041645); // recovered from a shipwreck - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class Candelabra : BaseLight, IShipwreckedItem + { + [Constructible] + public Candelabra() : base(0xA27) + { + Duration = TimeSpan.Zero; // Never burnt out + Burning = false; + Light = LightType.Circle225; + Weight = 3.0; + } + + public Candelabra(Serial serial) : base(serial) + { + } + + public override int LitItemID => 0xB1D; + public override int UnlitItemID => 0xA27; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsShipwreckedItem { get; set; } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(1); + + writer.Write(IsShipwreckedItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + IsShipwreckedItem = reader.ReadBool(); + break; + } + } + } + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + if (IsShipwreckedItem) + list.Add(1041645); // recovered from a shipwreck + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + if (IsShipwreckedItem) + LabelTo(from, 1041645); // recovered from a shipwreck + } + } +} diff --git a/Projects/UOContent/Items/Lights/CandelabraStand.cs b/Projects/UOContent/Items/Lights/CandelabraStand.cs index fc56baa18..4f32f5d39 100644 --- a/Projects/UOContent/Items/Lights/CandelabraStand.cs +++ b/Projects/UOContent/Items/Lights/CandelabraStand.cs @@ -1,35 +1,35 @@ -using System; - -namespace Server.Items -{ - public class CandelabraStand : BaseLight - { - [Constructible] - public CandelabraStand() : base(0xA29) - { - Duration = TimeSpan.Zero; // Never burnt out - Burning = false; - Light = LightType.Circle225; - Weight = 20.0; - } - - public CandelabraStand(Serial serial) : base(serial) - { - } - - public override int LitItemID => 0xB26; - public override int UnlitItemID => 0xA29; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class CandelabraStand : BaseLight + { + [Constructible] + public CandelabraStand() : base(0xA29) + { + Duration = TimeSpan.Zero; // Never burnt out + Burning = false; + Light = LightType.Circle225; + Weight = 20.0; + } + + public CandelabraStand(Serial serial) : base(serial) + { + } + + public override int LitItemID => 0xB26; + public override int UnlitItemID => 0xA29; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/Candle.cs b/Projects/UOContent/Items/Lights/Candle.cs index 203df781e..24ab792b9 100644 --- a/Projects/UOContent/Items/Lights/Candle.cs +++ b/Projects/UOContent/Items/Lights/Candle.cs @@ -1,39 +1,39 @@ -using System; - -namespace Server.Items -{ - public class Candle : BaseEquipableLight - { - [Constructible] - public Candle() : base(0xA28) - { - if (Burnout) - Duration = TimeSpan.FromMinutes(20); - else - Duration = TimeSpan.Zero; - - Burning = false; - Light = LightType.Circle150; - Weight = 1.0; - } - - public Candle(Serial serial) : base(serial) - { - } - - public override int LitItemID => 0xA0F; - public override int UnlitItemID => 0xA28; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class Candle : BaseEquipableLight + { + [Constructible] + public Candle() : base(0xA28) + { + if (Burnout) + Duration = TimeSpan.FromMinutes(20); + else + Duration = TimeSpan.Zero; + + Burning = false; + Light = LightType.Circle150; + Weight = 1.0; + } + + public Candle(Serial serial) : base(serial) + { + } + + public override int LitItemID => 0xA0F; + public override int UnlitItemID => 0xA28; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/CandleLarge.cs b/Projects/UOContent/Items/Lights/CandleLarge.cs index c8546a3d0..7adbdb4d7 100644 --- a/Projects/UOContent/Items/Lights/CandleLarge.cs +++ b/Projects/UOContent/Items/Lights/CandleLarge.cs @@ -1,39 +1,39 @@ -using System; - -namespace Server.Items -{ - public class CandleLarge : BaseLight - { - [Constructible] - public CandleLarge() : base(0xA26) - { - if (Burnout) - Duration = TimeSpan.FromMinutes(25); - else - Duration = TimeSpan.Zero; - - Burning = false; - Light = LightType.Circle150; - Weight = 2.0; - } - - public CandleLarge(Serial serial) : base(serial) - { - } - - public override int LitItemID => 0xB1A; - public override int UnlitItemID => 0xA26; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class CandleLarge : BaseLight + { + [Constructible] + public CandleLarge() : base(0xA26) + { + if (Burnout) + Duration = TimeSpan.FromMinutes(25); + else + Duration = TimeSpan.Zero; + + Burning = false; + Light = LightType.Circle150; + Weight = 2.0; + } + + public CandleLarge(Serial serial) : base(serial) + { + } + + public override int LitItemID => 0xB1A; + public override int UnlitItemID => 0xA26; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/CandleLong.cs b/Projects/UOContent/Items/Lights/CandleLong.cs index a4cb0548b..5d905f370 100644 --- a/Projects/UOContent/Items/Lights/CandleLong.cs +++ b/Projects/UOContent/Items/Lights/CandleLong.cs @@ -1,39 +1,39 @@ -using System; - -namespace Server.Items -{ - public class CandleLong : BaseLight - { - [Constructible] - public CandleLong() : base(0x1433) - { - if (Burnout) - Duration = TimeSpan.FromMinutes(30); - else - Duration = TimeSpan.Zero; - - Burning = false; - Light = LightType.Circle150; - Weight = 1.0; - } - - public CandleLong(Serial serial) : base(serial) - { - } - - public override int LitItemID => 0x1430; - public override int UnlitItemID => 0x1433; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class CandleLong : BaseLight + { + [Constructible] + public CandleLong() : base(0x1433) + { + if (Burnout) + Duration = TimeSpan.FromMinutes(30); + else + Duration = TimeSpan.Zero; + + Burning = false; + Light = LightType.Circle150; + Weight = 1.0; + } + + public CandleLong(Serial serial) : base(serial) + { + } + + public override int LitItemID => 0x1430; + public override int UnlitItemID => 0x1433; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/CandleShort.cs b/Projects/UOContent/Items/Lights/CandleShort.cs index 296c81d34..9d92a54ee 100644 --- a/Projects/UOContent/Items/Lights/CandleShort.cs +++ b/Projects/UOContent/Items/Lights/CandleShort.cs @@ -1,39 +1,39 @@ -using System; - -namespace Server.Items -{ - public class CandleShort : BaseLight - { - [Constructible] - public CandleShort() : base(0x142F) - { - if (Burnout) - Duration = TimeSpan.FromMinutes(25); - else - Duration = TimeSpan.Zero; - - Burning = false; - Light = LightType.Circle150; - Weight = 1.0; - } - - public CandleShort(Serial serial) : base(serial) - { - } - - public override int LitItemID => 0x142C; - public override int UnlitItemID => 0x142F; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class CandleShort : BaseLight + { + [Constructible] + public CandleShort() : base(0x142F) + { + if (Burnout) + Duration = TimeSpan.FromMinutes(25); + else + Duration = TimeSpan.Zero; + + Burning = false; + Light = LightType.Circle150; + Weight = 1.0; + } + + public CandleShort(Serial serial) : base(serial) + { + } + + public override int LitItemID => 0x142C; + public override int UnlitItemID => 0x142F; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/CandleSkull.cs b/Projects/UOContent/Items/Lights/CandleSkull.cs index 8696719f1..d1a66fa90 100644 --- a/Projects/UOContent/Items/Lights/CandleSkull.cs +++ b/Projects/UOContent/Items/Lights/CandleSkull.cs @@ -1,58 +1,58 @@ -using System; - -namespace Server.Items -{ - public class CandleSkull : BaseLight - { - [Constructible] - public CandleSkull() : base(0x1853) - { - if (Burnout) - Duration = TimeSpan.FromMinutes(25); - else - Duration = TimeSpan.Zero; - - Burning = false; - Light = LightType.Circle150; - Weight = 5.0; - } - - public CandleSkull(Serial serial) : base(serial) - { - } - - public override int LitItemID - { - get - { - if (ItemID == 0x1583 || ItemID == 0x1854) - return 0x1854; - - return 0x1858; - } - } - - public override int UnlitItemID - { - get - { - if (ItemID == 0x1853 || ItemID == 0x1584) - return 0x1853; - - return 0x1857; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class CandleSkull : BaseLight + { + [Constructible] + public CandleSkull() : base(0x1853) + { + if (Burnout) + Duration = TimeSpan.FromMinutes(25); + else + Duration = TimeSpan.Zero; + + Burning = false; + Light = LightType.Circle150; + Weight = 5.0; + } + + public CandleSkull(Serial serial) : base(serial) + { + } + + public override int LitItemID + { + get + { + if (ItemID == 0x1583 || ItemID == 0x1854) + return 0x1854; + + return 0x1858; + } + } + + public override int UnlitItemID + { + get + { + if (ItemID == 0x1853 || ItemID == 0x1584) + return 0x1853; + + return 0x1857; + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/DarkSource.cs b/Projects/UOContent/Items/Lights/DarkSource.cs index 5d8b3fc9b..6cf443480 100644 --- a/Projects/UOContent/Items/Lights/DarkSource.cs +++ b/Projects/UOContent/Items/Lights/DarkSource.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class DarkSource : Item - { - [Constructible] - public DarkSource() : base(0x1646) - { - Layer = Layer.TwoHanded; - Movable = false; - } - - public DarkSource(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class DarkSource : Item + { + [Constructible] + public DarkSource() : base(0x1646) + { + Layer = Layer.TwoHanded; + Movable = false; + } + + public DarkSource(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/HangingLantern.cs b/Projects/UOContent/Items/Lights/HangingLantern.cs index 010605dc3..cf4e2fba1 100644 --- a/Projects/UOContent/Items/Lights/HangingLantern.cs +++ b/Projects/UOContent/Items/Lights/HangingLantern.cs @@ -1,36 +1,36 @@ -using System; - -namespace Server.Items -{ - public class HangingLantern : BaseLight - { - [Constructible] - public HangingLantern() : base(0xA1D) - { - Movable = false; - Duration = TimeSpan.Zero; // Never burnt out - Burning = false; - Light = LightType.Circle300; - Weight = 40.0; - } - - public HangingLantern(Serial serial) : base(serial) - { - } - - public override int LitItemID => 0xA1A; - public override int UnlitItemID => 0xA1D; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class HangingLantern : BaseLight + { + [Constructible] + public HangingLantern() : base(0xA1D) + { + Movable = false; + Duration = TimeSpan.Zero; // Never burnt out + Burning = false; + Light = LightType.Circle300; + Weight = 40.0; + } + + public HangingLantern(Serial serial) : base(serial) + { + } + + public override int LitItemID => 0xA1A; + public override int UnlitItemID => 0xA1D; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/HeatingStand.cs b/Projects/UOContent/Items/Lights/HeatingStand.cs index 210bbde90..c668affb3 100644 --- a/Projects/UOContent/Items/Lights/HeatingStand.cs +++ b/Projects/UOContent/Items/Lights/HeatingStand.cs @@ -1,59 +1,59 @@ -using System; - -namespace Server.Items -{ - public class HeatingStand : BaseLight - { - [Constructible] - public HeatingStand() : base(0x1849) - { - if (Burnout) - Duration = TimeSpan.FromMinutes(25); - else - Duration = TimeSpan.Zero; - - Burning = false; - Light = LightType.Empty; - Weight = 1.0; - } - - public HeatingStand(Serial serial) : base(serial) - { - } - - public override int LitItemID => 0x184A; - public override int UnlitItemID => 0x1849; - - public override void Ignite() - { - base.Ignite(); - - if (ItemID == LitItemID) - Light = LightType.Circle150; - else if (ItemID == UnlitItemID) - Light = LightType.Empty; - } - - public override void Douse() - { - base.Douse(); - - if (ItemID == LitItemID) - Light = LightType.Circle150; - else if (ItemID == UnlitItemID) - Light = LightType.Empty; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class HeatingStand : BaseLight + { + [Constructible] + public HeatingStand() : base(0x1849) + { + if (Burnout) + Duration = TimeSpan.FromMinutes(25); + else + Duration = TimeSpan.Zero; + + Burning = false; + Light = LightType.Empty; + Weight = 1.0; + } + + public HeatingStand(Serial serial) : base(serial) + { + } + + public override int LitItemID => 0x184A; + public override int UnlitItemID => 0x1849; + + public override void Ignite() + { + base.Ignite(); + + if (ItemID == LitItemID) + Light = LightType.Circle150; + else if (ItemID == UnlitItemID) + Light = LightType.Empty; + } + + public override void Douse() + { + base.Douse(); + + if (ItemID == LitItemID) + Light = LightType.Circle150; + else if (ItemID == UnlitItemID) + Light = LightType.Empty; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/LampPost1.cs b/Projects/UOContent/Items/Lights/LampPost1.cs index 83547b3d9..8d9c2bae0 100644 --- a/Projects/UOContent/Items/Lights/LampPost1.cs +++ b/Projects/UOContent/Items/Lights/LampPost1.cs @@ -1,36 +1,36 @@ -using System; - -namespace Server.Items -{ - public class LampPost1 : BaseLight - { - [Constructible] - public LampPost1() : base(0xB21) - { - Movable = false; - Duration = TimeSpan.Zero; // Never burnt out - Burning = false; - Light = LightType.Circle300; - Weight = 40.0; - } - - public LampPost1(Serial serial) : base(serial) - { - } - - public override int LitItemID => 0xB20; - public override int UnlitItemID => 0xB21; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class LampPost1 : BaseLight + { + [Constructible] + public LampPost1() : base(0xB21) + { + Movable = false; + Duration = TimeSpan.Zero; // Never burnt out + Burning = false; + Light = LightType.Circle300; + Weight = 40.0; + } + + public LampPost1(Serial serial) : base(serial) + { + } + + public override int LitItemID => 0xB20; + public override int UnlitItemID => 0xB21; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/LampPost2.cs b/Projects/UOContent/Items/Lights/LampPost2.cs index aa25380dd..e041ea02d 100644 --- a/Projects/UOContent/Items/Lights/LampPost2.cs +++ b/Projects/UOContent/Items/Lights/LampPost2.cs @@ -1,36 +1,36 @@ -using System; - -namespace Server.Items -{ - public class LampPost2 : BaseLight - { - [Constructible] - public LampPost2() : base(0xB23) - { - Movable = false; - Duration = TimeSpan.Zero; // Never burnt out - Burning = false; - Light = LightType.Circle300; - Weight = 40.0; - } - - public LampPost2(Serial serial) : base(serial) - { - } - - public override int LitItemID => 0xB22; - public override int UnlitItemID => 0xB23; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class LampPost2 : BaseLight + { + [Constructible] + public LampPost2() : base(0xB23) + { + Movable = false; + Duration = TimeSpan.Zero; // Never burnt out + Burning = false; + Light = LightType.Circle300; + Weight = 40.0; + } + + public LampPost2(Serial serial) : base(serial) + { + } + + public override int LitItemID => 0xB22; + public override int UnlitItemID => 0xB23; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/LampPost3.cs b/Projects/UOContent/Items/Lights/LampPost3.cs index d02667f6a..16000c03b 100644 --- a/Projects/UOContent/Items/Lights/LampPost3.cs +++ b/Projects/UOContent/Items/Lights/LampPost3.cs @@ -1,36 +1,36 @@ -using System; - -namespace Server.Items -{ - public class LampPost3 : BaseLight - { - [Constructible] - public LampPost3() : base(0xb25) - { - Movable = false; - Duration = TimeSpan.Zero; // Never burnt out - Burning = false; - Light = LightType.Circle300; - Weight = 40.0; - } - - public LampPost3(Serial serial) : base(serial) - { - } - - public override int LitItemID => 0xB24; - public override int UnlitItemID => 0xB25; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class LampPost3 : BaseLight + { + [Constructible] + public LampPost3() : base(0xb25) + { + Movable = false; + Duration = TimeSpan.Zero; // Never burnt out + Burning = false; + Light = LightType.Circle300; + Weight = 40.0; + } + + public LampPost3(Serial serial) : base(serial) + { + } + + public override int LitItemID => 0xB24; + public override int UnlitItemID => 0xB25; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/Lantern.cs b/Projects/UOContent/Items/Lights/Lantern.cs index 524a348d9..d42985206 100644 --- a/Projects/UOContent/Items/Lights/Lantern.cs +++ b/Projects/UOContent/Items/Lights/Lantern.cs @@ -1,82 +1,82 @@ -using System; - -namespace Server.Items -{ - public class Lantern : BaseEquipableLight - { - [Constructible] - public Lantern() : base(0xA25) - { - if (Burnout) - Duration = TimeSpan.FromMinutes(20); - else - Duration = TimeSpan.Zero; - - Burning = false; - Light = LightType.Circle300; - Weight = 2.0; - } - - public Lantern(Serial serial) : base(serial) - { - } - - public override int LitItemID - { - get - { - if (ItemID == 0xA15 || ItemID == 0xA17) - return ItemID; - - return 0xA22; - } - } - - public override int UnlitItemID - { - get - { - if (ItemID == 0xA18) - return ItemID; - - return 0xA25; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class LanternOfSouls : Lantern - { - [Constructible] - public LanternOfSouls() => Hue = 0x482; - - public LanternOfSouls(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061618; // Lantern of Souls - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class Lantern : BaseEquipableLight + { + [Constructible] + public Lantern() : base(0xA25) + { + if (Burnout) + Duration = TimeSpan.FromMinutes(20); + else + Duration = TimeSpan.Zero; + + Burning = false; + Light = LightType.Circle300; + Weight = 2.0; + } + + public Lantern(Serial serial) : base(serial) + { + } + + public override int LitItemID + { + get + { + if (ItemID == 0xA15 || ItemID == 0xA17) + return ItemID; + + return 0xA22; + } + } + + public override int UnlitItemID + { + get + { + if (ItemID == 0xA18) + return ItemID; + + return 0xA25; + } + } + + 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(); + } + } + + public class LanternOfSouls : Lantern + { + [Constructible] + public LanternOfSouls() => Hue = 0x482; + + public LanternOfSouls(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061618; // Lantern of Souls + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/LightSource.cs b/Projects/UOContent/Items/Lights/LightSource.cs index 9dc61541b..fb6061ae3 100644 --- a/Projects/UOContent/Items/Lights/LightSource.cs +++ b/Projects/UOContent/Items/Lights/LightSource.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class LightSource : Item - { - [Constructible] - public LightSource() : base(0x1647) - { - Layer = Layer.TwoHanded; - Movable = false; - } - - public LightSource(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LightSource : Item + { + [Constructible] + public LightSource() : base(0x1647) + { + Layer = Layer.TwoHanded; + Movable = false; + } + + public LightSource(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/PaperLantern.cs b/Projects/UOContent/Items/Lights/PaperLantern.cs index 32f1f6396..eabaaa561 100644 --- a/Projects/UOContent/Items/Lights/PaperLantern.cs +++ b/Projects/UOContent/Items/Lights/PaperLantern.cs @@ -1,37 +1,37 @@ -using System; - -namespace Server.Items -{ - [Flippable] - public class PaperLantern : BaseLight - { - [Constructible] - public PaperLantern() : base(0x24BE) - { - Movable = true; - Duration = TimeSpan.Zero; // Never burnt out - Burning = false; - Light = LightType.Circle150; - Weight = 3.0; - } - - public PaperLantern(Serial serial) : base(serial) - { - } - - public override int LitItemID => 0x24BD; - public override int UnlitItemID => 0x24BE; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + [Flippable] + public class PaperLantern : BaseLight + { + [Constructible] + public PaperLantern() : base(0x24BE) + { + Movable = true; + Duration = TimeSpan.Zero; // Never burnt out + Burning = false; + Light = LightType.Circle150; + Weight = 3.0; + } + + public PaperLantern(Serial serial) : base(serial) + { + } + + public override int LitItemID => 0x24BD; + public override int UnlitItemID => 0x24BE; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/RedHangingLantern.cs b/Projects/UOContent/Items/Lights/RedHangingLantern.cs index bb43921b8..54a50f38c 100644 --- a/Projects/UOContent/Items/Lights/RedHangingLantern.cs +++ b/Projects/UOContent/Items/Lights/RedHangingLantern.cs @@ -1,68 +1,68 @@ -using System; - -namespace Server.Items -{ - [Flippable] - public class RedHangingLantern : BaseLight - { - [Constructible] - public RedHangingLantern() : base(0x24C2) - { - Movable = true; - Duration = TimeSpan.Zero; // Never burnt out - Burning = false; - Light = LightType.Circle300; - Weight = 3.0; - } - - public RedHangingLantern(Serial serial) : base(serial) - { - } - - public override int LitItemID - { - get - { - if (ItemID == 0x24C2) - return 0x24C1; - return 0x24C3; - } - } - - public override int UnlitItemID - { - get - { - if (ItemID == 0x24C1) - return 0x24C2; - return 0x24C4; - } - } - - public void Flip() - { - Light = LightType.Circle300; - - ItemID = ItemID switch - { - 0x24C2 => 0x24C4, - 0x24C1 => 0x24C3, - 0x24C4 => 0x24C2, - 0x24C3 => 0x24C1, - _ => ItemID - }; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + [Flippable] + public class RedHangingLantern : BaseLight + { + [Constructible] + public RedHangingLantern() : base(0x24C2) + { + Movable = true; + Duration = TimeSpan.Zero; // Never burnt out + Burning = false; + Light = LightType.Circle300; + Weight = 3.0; + } + + public RedHangingLantern(Serial serial) : base(serial) + { + } + + public override int LitItemID + { + get + { + if (ItemID == 0x24C2) + return 0x24C1; + return 0x24C3; + } + } + + public override int UnlitItemID + { + get + { + if (ItemID == 0x24C1) + return 0x24C2; + return 0x24C4; + } + } + + public void Flip() + { + Light = LightType.Circle300; + + ItemID = ItemID switch + { + 0x24C2 => 0x24C4, + 0x24C1 => 0x24C3, + 0x24C4 => 0x24C2, + 0x24C3 => 0x24C1, + _ => ItemID + }; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/RoundPaperLantern.cs b/Projects/UOContent/Items/Lights/RoundPaperLantern.cs index bb65eefc3..54c732995 100644 --- a/Projects/UOContent/Items/Lights/RoundPaperLantern.cs +++ b/Projects/UOContent/Items/Lights/RoundPaperLantern.cs @@ -1,37 +1,37 @@ -using System; - -namespace Server.Items -{ - [Flippable] - public class RoundPaperLantern : BaseLight - { - [Constructible] - public RoundPaperLantern() : base(0x24CA) - { - Movable = true; - Duration = TimeSpan.Zero; // Never burnt out - Burning = false; - Light = LightType.Circle150; - Weight = 3.0; - } - - public RoundPaperLantern(Serial serial) : base(serial) - { - } - - public override int LitItemID => 0x24C9; - public override int UnlitItemID => 0x24CA; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + [Flippable] + public class RoundPaperLantern : BaseLight + { + [Constructible] + public RoundPaperLantern() : base(0x24CA) + { + Movable = true; + Duration = TimeSpan.Zero; // Never burnt out + Burning = false; + Light = LightType.Circle150; + Weight = 3.0; + } + + public RoundPaperLantern(Serial serial) : base(serial) + { + } + + public override int LitItemID => 0x24C9; + public override int UnlitItemID => 0x24CA; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/ShojiLantern.cs b/Projects/UOContent/Items/Lights/ShojiLantern.cs index 399de4932..979566251 100644 --- a/Projects/UOContent/Items/Lights/ShojiLantern.cs +++ b/Projects/UOContent/Items/Lights/ShojiLantern.cs @@ -1,37 +1,37 @@ -using System; - -namespace Server.Items -{ - [Flippable] - public class ShojiLantern : BaseLight - { - [Constructible] - public ShojiLantern() : base(0x24BC) - { - Movable = true; - Duration = TimeSpan.Zero; // Never burnt out - Burning = false; - Light = LightType.Circle150; - Weight = 3.0; - } - - public ShojiLantern(Serial serial) : base(serial) - { - } - - public override int LitItemID => 0x24BB; - public override int UnlitItemID => 0x24BC; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + [Flippable] + public class ShojiLantern : BaseLight + { + [Constructible] + public ShojiLantern() : base(0x24BC) + { + Movable = true; + Duration = TimeSpan.Zero; // Never burnt out + Burning = false; + Light = LightType.Circle150; + Weight = 3.0; + } + + public ShojiLantern(Serial serial) : base(serial) + { + } + + public override int LitItemID => 0x24BB; + public override int UnlitItemID => 0x24BC; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/Torch.cs b/Projects/UOContent/Items/Lights/Torch.cs index b642a24ae..eb37e27bc 100644 --- a/Projects/UOContent/Items/Lights/Torch.cs +++ b/Projects/UOContent/Items/Lights/Torch.cs @@ -1,62 +1,62 @@ -using System; -using Server.Mobiles; - -namespace Server.Items -{ - public class Torch : BaseEquipableLight - { - [Constructible] - public Torch() : base(0xF6B) - { - if (Burnout) - Duration = TimeSpan.FromMinutes(30); - else - Duration = TimeSpan.Zero; - - Burning = false; - Light = LightType.Circle300; - Weight = 1.0; - } - - public Torch(Serial serial) : base(serial) - { - } - - public override int LitItemID => 0xA12; - public override int UnlitItemID => 0xF6B; - - public override int LitSound => 0x54; - public override int UnlitSound => 0x4BB; - - public override void OnAdded(IEntity parent) - { - base.OnAdded(parent); - - if (parent is Mobile mobile && Burning) - MeerMage.StopEffect(mobile, true); - } - - public override void Ignite() - { - base.Ignite(); - - if (Parent is Mobile mobile && Burning) - MeerMage.StopEffect(mobile, true); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Weight == 2.0) - Weight = 1.0; - } - } -} \ No newline at end of file +using System; +using Server.Mobiles; + +namespace Server.Items +{ + public class Torch : BaseEquipableLight + { + [Constructible] + public Torch() : base(0xF6B) + { + if (Burnout) + Duration = TimeSpan.FromMinutes(30); + else + Duration = TimeSpan.Zero; + + Burning = false; + Light = LightType.Circle300; + Weight = 1.0; + } + + public Torch(Serial serial) : base(serial) + { + } + + public override int LitItemID => 0xA12; + public override int UnlitItemID => 0xF6B; + + public override int LitSound => 0x54; + public override int UnlitSound => 0x4BB; + + public override void OnAdded(IEntity parent) + { + base.OnAdded(parent); + + if (parent is Mobile mobile && Burning) + MeerMage.StopEffect(mobile, true); + } + + public override void Ignite() + { + base.Ignite(); + + if (Parent is Mobile mobile && Burning) + MeerMage.StopEffect(mobile, true); + } + + 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 (Weight == 2.0) + Weight = 1.0; + } + } +} diff --git a/Projects/UOContent/Items/Lights/WallSconce.cs b/Projects/UOContent/Items/Lights/WallSconce.cs index 3cd4a5e39..ae260cadb 100644 --- a/Projects/UOContent/Items/Lights/WallSconce.cs +++ b/Projects/UOContent/Items/Lights/WallSconce.cs @@ -1,71 +1,71 @@ -using System; - -namespace Server.Items -{ - [Flippable] - public class WallSconce : BaseLight - { - [Constructible] - public WallSconce() : base(0x9FB) - { - Movable = false; - Duration = TimeSpan.Zero; // Never burnt out - Burning = false; - Light = LightType.WestBig; - Weight = 3.0; - } - - public WallSconce(Serial serial) : base(serial) - { - } - - public override int LitItemID - { - get - { - if (ItemID == 0x9FB) - return 0x9FD; - return 0xA02; - } - } - - public override int UnlitItemID - { - get - { - if (ItemID == 0x9FD) - return 0x9FB; - return 0xA00; - } - } - - public void Flip() - { - if (Light == LightType.WestBig) - Light = LightType.NorthBig; - else if (Light == LightType.NorthBig) - Light = LightType.WestBig; - - ItemID = ItemID switch - { - 0x9FB => 0xA00, - 0x9FD => 0xA02, - 0xA00 => 0x9FB, - 0xA02 => 0x9FD, - _ => ItemID - }; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + [Flippable] + public class WallSconce : BaseLight + { + [Constructible] + public WallSconce() : base(0x9FB) + { + Movable = false; + Duration = TimeSpan.Zero; // Never burnt out + Burning = false; + Light = LightType.WestBig; + Weight = 3.0; + } + + public WallSconce(Serial serial) : base(serial) + { + } + + public override int LitItemID + { + get + { + if (ItemID == 0x9FB) + return 0x9FD; + return 0xA02; + } + } + + public override int UnlitItemID + { + get + { + if (ItemID == 0x9FD) + return 0x9FB; + return 0xA00; + } + } + + public void Flip() + { + if (Light == LightType.WestBig) + Light = LightType.NorthBig; + else if (Light == LightType.NorthBig) + Light = LightType.WestBig; + + ItemID = ItemID switch + { + 0x9FB => 0xA00, + 0x9FD => 0xA02, + 0xA00 => 0x9FB, + 0xA02 => 0x9FD, + _ => ItemID + }; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/WallTorch.cs b/Projects/UOContent/Items/Lights/WallTorch.cs index 2d0007a87..870797101 100644 --- a/Projects/UOContent/Items/Lights/WallTorch.cs +++ b/Projects/UOContent/Items/Lights/WallTorch.cs @@ -1,71 +1,71 @@ -using System; - -namespace Server.Items -{ - [Flippable] - public class WallTorch : BaseLight - { - [Constructible] - public WallTorch() : base(0xA05) - { - Movable = false; - Duration = TimeSpan.Zero; // Never burnt out - Burning = false; - Light = LightType.WestBig; - Weight = 3.0; - } - - public WallTorch(Serial serial) : base(serial) - { - } - - public override int LitItemID - { - get - { - if (ItemID == 0xA05) - return 0xA07; - return 0xA0C; - } - } - - public override int UnlitItemID - { - get - { - if (ItemID == 0xA07) - return 0xA05; - return 0xA0A; - } - } - - public void Flip() - { - if (Light == LightType.WestBig) - Light = LightType.NorthBig; - else if (Light == LightType.NorthBig) - Light = LightType.WestBig; - - ItemID = ItemID switch - { - 0xA05 => 0xA0A, - 0xA07 => 0xA0C, - 0xA0A => 0xA05, - 0xA0C => 0xA07, - _ => ItemID - }; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + [Flippable] + public class WallTorch : BaseLight + { + [Constructible] + public WallTorch() : base(0xA05) + { + Movable = false; + Duration = TimeSpan.Zero; // Never burnt out + Burning = false; + Light = LightType.WestBig; + Weight = 3.0; + } + + public WallTorch(Serial serial) : base(serial) + { + } + + public override int LitItemID + { + get + { + if (ItemID == 0xA05) + return 0xA07; + return 0xA0C; + } + } + + public override int UnlitItemID + { + get + { + if (ItemID == 0xA07) + return 0xA05; + return 0xA0A; + } + } + + public void Flip() + { + if (Light == LightType.WestBig) + Light = LightType.NorthBig; + else if (Light == LightType.NorthBig) + Light = LightType.WestBig; + + ItemID = ItemID switch + { + 0xA05 => 0xA0A, + 0xA07 => 0xA0C, + 0xA0A => 0xA05, + 0xA0C => 0xA07, + _ => ItemID + }; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Lights/WhiteHangingLantern.cs b/Projects/UOContent/Items/Lights/WhiteHangingLantern.cs index 35a84e1b7..fa3919abe 100644 --- a/Projects/UOContent/Items/Lights/WhiteHangingLantern.cs +++ b/Projects/UOContent/Items/Lights/WhiteHangingLantern.cs @@ -1,68 +1,68 @@ -using System; - -namespace Server.Items -{ - [Flippable] - public class WhiteHangingLantern : BaseLight - { - [Constructible] - public WhiteHangingLantern() : base(0x24C6) - { - Movable = true; - Duration = TimeSpan.Zero; // Never burnt out - Burning = false; - Light = LightType.Circle300; - Weight = 3.0; - } - - public WhiteHangingLantern(Serial serial) : base(serial) - { - } - - public override int LitItemID - { - get - { - if (ItemID == 0x24C6) - return 0x24C5; - return 0x24C7; - } - } - - public override int UnlitItemID - { - get - { - if (ItemID == 0x24C5) - return 0x24C6; - return 0x24C8; - } - } - - public void Flip() - { - Light = LightType.Circle300; - - ItemID = ItemID switch - { - 0x24C6 => 0x24C8, - 0x24C5 => 0x24C7, - 0x24C8 => 0x24C6, - 0x24C7 => 0x24C5, - _ => ItemID - }; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + [Flippable] + public class WhiteHangingLantern : BaseLight + { + [Constructible] + public WhiteHangingLantern() : base(0x24C6) + { + Movable = true; + Duration = TimeSpan.Zero; // Never burnt out + Burning = false; + Light = LightType.Circle300; + Weight = 3.0; + } + + public WhiteHangingLantern(Serial serial) : base(serial) + { + } + + public override int LitItemID + { + get + { + if (ItemID == 0x24C6) + return 0x24C5; + return 0x24C7; + } + } + + public override int UnlitItemID + { + get + { + if (ItemID == 0x24C5) + return 0x24C6; + return 0x24C8; + } + } + + public void Flip() + { + Light = LightType.Circle300; + + ItemID = ItemID switch + { + 0x24C6 => 0x24C8, + 0x24C5 => 0x24C7, + 0x24C8 => 0x24C6, + 0x24C7 => 0x24C5, + _ => ItemID + }; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Maps/BlankMap.cs b/Projects/UOContent/Items/Maps/BlankMap.cs index e1c5cd5aa..5c7667e1a 100644 --- a/Projects/UOContent/Items/Maps/BlankMap.cs +++ b/Projects/UOContent/Items/Maps/BlankMap.cs @@ -1,33 +1,33 @@ -namespace Server.Items -{ - public class BlankMap : MapItem - { - [Constructible] - public BlankMap() - { - } - - public BlankMap(Serial serial) : base(serial) - { - } - - public override void OnDoubleClick(Mobile from) - { - SendLocalizedMessageTo(from, 500208); // It appears to be blank. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class BlankMap : MapItem + { + [Constructible] + public BlankMap() + { + } + + public BlankMap(Serial serial) : base(serial) + { + } + + public override void OnDoubleClick(Mobile from) + { + SendLocalizedMessageTo(from, 500208); // It appears to be blank. + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Maps/CityMap.cs b/Projects/UOContent/Items/Maps/CityMap.cs index 995891ef4..16031a02f 100644 --- a/Projects/UOContent/Items/Maps/CityMap.cs +++ b/Projects/UOContent/Items/Maps/CityMap.cs @@ -1,49 +1,49 @@ -namespace Server.Items -{ - public class CityMap : MapItem - { - [Constructible] - public CityMap() - { - SetDisplay(0, 0, 5119, 4095, 400, 400); - } - - public CityMap(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1015231; // city map - - public override void CraftInit(Mobile from) - { - double skillValue = from.Skills.Cartography.Value; - int dist = 64 + (int)(skillValue * 4); - - if (dist < 200) - dist = 200; - - int size = 32 + (int)(skillValue * 2); - - if (size < 200) - size = 200; - else if (size > 400) - size = 400; - - SetDisplay(from.X - dist, from.Y - dist, from.X + dist, from.Y + dist, size, size); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class CityMap : MapItem + { + [Constructible] + public CityMap() + { + SetDisplay(0, 0, 5119, 4095, 400, 400); + } + + public CityMap(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1015231; // city map + + public override void CraftInit(Mobile from) + { + var skillValue = from.Skills.Cartography.Value; + var dist = 64 + (int)(skillValue * 4); + + if (dist < 200) + dist = 200; + + var size = 32 + (int)(skillValue * 2); + + if (size < 200) + size = 200; + else if (size > 400) + size = 400; + + SetDisplay(from.X - dist, from.Y - dist, from.X + dist, from.Y + dist, size, size); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Maps/IndecipherableMap.cs b/Projects/UOContent/Items/Maps/IndecipherableMap.cs index a06eac766..b6332e7ca 100644 --- a/Projects/UOContent/Items/Maps/IndecipherableMap.cs +++ b/Projects/UOContent/Items/Maps/IndecipherableMap.cs @@ -1,39 +1,39 @@ -namespace Server.Items -{ - public class IndecipherableMap : MapItem - { - [Constructible] - public IndecipherableMap() - { - if (Utility.RandomDouble() < 0.2) - Hue = 0x965; - else - Hue = 0x961; - } - - public IndecipherableMap(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070799; // indecipherable map - - public override void OnDoubleClick(Mobile from) - { - from.SendLocalizedMessage(1070801); // You cannot decipher this ruined map. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class IndecipherableMap : MapItem + { + [Constructible] + public IndecipherableMap() + { + if (Utility.RandomDouble() < 0.2) + Hue = 0x965; + else + Hue = 0x961; + } + + public IndecipherableMap(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070799; // indecipherable map + + public override void OnDoubleClick(Mobile from) + { + from.SendLocalizedMessage(1070801); // You cannot decipher this ruined map. + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Maps/LocalMap.cs b/Projects/UOContent/Items/Maps/LocalMap.cs index ba66310d0..574bf64e7 100644 --- a/Projects/UOContent/Items/Maps/LocalMap.cs +++ b/Projects/UOContent/Items/Maps/LocalMap.cs @@ -1,39 +1,39 @@ -namespace Server.Items -{ - public class LocalMap : MapItem - { - [Constructible] - public LocalMap() - { - SetDisplay(0, 0, 5119, 4095, 400, 400); - } - - public LocalMap(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1015230; // local map - - public override void CraftInit(Mobile from) - { - double skillValue = from.Skills.Cartography.Value; - int dist = 64 + (int)(skillValue * 2); - - SetDisplay(from.X - dist, from.Y - dist, from.X + dist, from.Y + dist, 200, 200); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LocalMap : MapItem + { + [Constructible] + public LocalMap() + { + SetDisplay(0, 0, 5119, 4095, 400, 400); + } + + public LocalMap(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1015230; // local map + + public override void CraftInit(Mobile from) + { + var skillValue = from.Skills.Cartography.Value; + var dist = 64 + (int)(skillValue * 2); + + SetDisplay(from.X - dist, from.Y - dist, from.X + dist, from.Y + dist, 200, 200); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Maps/MapItem.cs b/Projects/UOContent/Items/Maps/MapItem.cs index 971a40664..b90375bb1 100644 --- a/Projects/UOContent/Items/Maps/MapItem.cs +++ b/Projects/UOContent/Items/Maps/MapItem.cs @@ -1,378 +1,385 @@ -using System; -using System.Collections.Generic; -using Server.Engines.Craft; -using Server.Network; - -namespace Server.Items -{ - [Flippable(0x14EB, 0x14EC)] - public class MapItem : Item, ICraftable - { - private const int MaxUserPins = 50; - private bool m_Editable; - - [Constructible] - public MapItem(Map facet = null) : base(0x14EC) - { - Weight = 1.0; - - Width = 200; - Height = 200; - Facet = facet; - } - - public MapItem(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Protected { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Rectangle2D Bounds { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Width { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Height { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Map Facet { get; set; } - - public List Pins { get; } = new List(); - - public int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, - CraftItem craftItem, int resHue) - { - CraftInit(from); - return 1; - } - - public virtual void CraftInit(Mobile from) - { - } - - public void SetDisplay(int x1, int y1, int x2, int y2, int w, int h) - { - Width = w; - Height = h; - - if (x1 < 0) - x1 = 0; - - if (y1 < 0) - y1 = 0; - - if (x2 >= 5120) - x2 = 5119; - - if (y2 >= 4096) - y2 = 4095; - - Bounds = new Rectangle2D(x1, y1, x2 - x1, y2 - y1); - } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(GetWorldLocation(), 2)) - DisplayTo(from); - else - from.SendLocalizedMessage(500446); // That is too far away. - } - - public virtual void DisplayTo(Mobile from) - { - NetState ns = from.NetState; - - if (ns.NewCharacterList) // 7.0.13.0+ supports maps on all facets - from.Send(new MapDetailsNew(this)); - else if (Facet != null && Facet != Map.Felucca && Facet != Map.Trammel) // Is it Felucca and Trammel, or just Felucca? - { - from.SendMessage("You must have client 7.0.13.0 or higher to display this map."); - return; - } - else - from.Send(new MapDetails(this)); - - from.Send(new MapDisplay(this)); - - for (int i = 0; i < Pins.Count; ++i) - from.Send(new MapAddPin(this, Pins[i])); - - from.Send(new MapSetEditable(this, ValidateEdit(from))); - } - - public virtual void OnAddPin(Mobile from, int x, int y) - { - if (!ValidateEdit(from)) - return; - if (Pins.Count >= MaxUserPins) - return; - - Validate(ref x, ref y); - AddPin(x, y); - } - - public virtual void OnRemovePin(Mobile from, int number) - { - if (!ValidateEdit(from)) - return; - - RemovePin(number); - } - - public virtual void OnChangePin(Mobile from, int number, int x, int y) - { - if (!ValidateEdit(from)) - return; - - Validate(ref x, ref y); - ChangePin(number, x, y); - } - - public virtual void OnInsertPin(Mobile from, int number, int x, int y) - { - if (!ValidateEdit(from)) - return; - if (Pins.Count >= MaxUserPins) - return; - - Validate(ref x, ref y); - InsertPin(number, x, y); - } - - public virtual void OnClearPins(Mobile from) - { - if (!ValidateEdit(from)) - return; - - ClearPins(); - } - - public virtual void OnToggleEditable(Mobile from) - { - if (Validate(from)) - m_Editable = !m_Editable; - - from.Send(new MapSetEditable(this, Validate(from) && m_Editable)); - } - - public virtual void Validate(ref int x, ref int y) - { - x = Math.Clamp(x, 0, Width - 1); - y = Math.Clamp(y, 0, Height - 1); - } - - public virtual bool ValidateEdit(Mobile from) => m_Editable && Validate(from); - - public virtual bool Validate(Mobile from) - { - if (!from.CanSee(this) || from.Map != Map || !from.Alive || InSecureTrade) - return false; - if (from.AccessLevel >= AccessLevel.GameMaster) - return true; - if (!Movable || Protected || !from.InRange(GetWorldLocation(), 2)) - return false; - - return !(RootParent is Mobile && RootParent != from); - } - - public void ConvertToWorld(int x, int y, out int worldX, out int worldY) - { - worldX = Bounds.Width * x / Width + Bounds.X; - worldY = Bounds.Height * y / Height + Bounds.Y; - } - - public void ConvertToMap(int x, int y, out int mapX, out int mapY) - { - mapX = (x - Bounds.X) * Width / Bounds.Width; - mapY = (y - Bounds.Y) * Width / Bounds.Height; - } - - public virtual void AddWorldPin(int x, int y) - { - ConvertToMap(x, y, out int mapX, out int mapY); - AddPin(mapX, mapY); - } - - public virtual void AddPin(int x, int y) - { - Pins.Add(new Point2D(x, y)); - } - - public virtual void RemovePin(int index) - { - if (index > 0 && index < Pins.Count) - Pins.RemoveAt(index); - } - - public virtual void InsertPin(int index, int x, int y) - { - if (index < 0 || index >= Pins.Count) - Pins.Add(new Point2D(x, y)); - else - Pins.Insert(index, new Point2D(x, y)); - } - - public virtual void ChangePin(int index, int x, int y) - { - if (index >= 0 && index < Pins.Count) - Pins[index] = new Point2D(x, y); - } - - public virtual void ClearPins() - { - Pins.Clear(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(Bounds); - - writer.Write(Width); - writer.Write(Height); - - writer.Write(Protected); - - writer.Write(Pins.Count); - for (int i = 0; i < Pins.Count; ++i) - writer.Write(Pins[i]); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Bounds = reader.ReadRect2D(); - - Width = reader.ReadInt(); - Height = reader.ReadInt(); - - Protected = reader.ReadBool(); - - int count = reader.ReadInt(); - for (int i = 0; i < count; i++) - Pins.Add(reader.ReadPoint2D()); - - break; - } - } - } - - public static void Initialize() - { - PacketHandlers.Register(0x56, 11, true, OnMapCommand); - } - - private static void OnMapCommand(NetState state, PacketReader pvSrc) - { - Mobile from = state.Mobile; - - if (!(World.FindItem(pvSrc.ReadUInt32()) is MapItem map)) - return; - - int command = pvSrc.ReadByte(); - int number = pvSrc.ReadByte(); - - int x = pvSrc.ReadInt16(); - int y = pvSrc.ReadInt16(); - - switch (command) - { - case 1: - map.OnAddPin(from, x, y); - break; - case 2: - map.OnInsertPin(from, number, x, y); - break; - case 3: - map.OnChangePin(from, number, x, y); - break; - case 4: - map.OnRemovePin(from, number); - break; - case 5: - map.OnClearPins(from); - break; - case 6: - map.OnToggleEditable(from); - break; - } - } - - private sealed class MapDetails : Packet - { - public MapDetails(MapItem map) : base(0x90, 19) - { - Stream.Write(map.Serial); - Stream.Write((short)0x139D); - Stream.Write((short)map.Bounds.Start.X); - Stream.Write((short)map.Bounds.Start.Y); - Stream.Write((short)map.Bounds.End.X); - Stream.Write((short)map.Bounds.End.Y); - Stream.Write((short)map.Width); - Stream.Write((short)map.Height); - } - } - - private sealed class MapDetailsNew : Packet - { - public MapDetailsNew(MapItem map) : base(0xF5, 21) - { - Stream.Write(map.Serial); - Stream.Write((short)0x139D); - Stream.Write((short)map.Bounds.Start.X); - Stream.Write((short)map.Bounds.Start.Y); - Stream.Write((short)map.Bounds.End.X); - Stream.Write((short)map.Bounds.End.Y); - Stream.Write((short)map.Width); - Stream.Write((short)map.Height); - Stream.Write((short)(map.Facet?.MapID ?? 0)); - } - } - - private abstract class MapCommand : Packet - { - public MapCommand(MapItem map, int command, int number, int x, int y) : base(0x56, 11) - { - Stream.Write(map.Serial); - Stream.Write((byte)command); - Stream.Write((byte)number); - Stream.Write((short)x); - Stream.Write((short)y); - } - } - - private sealed class MapDisplay : MapCommand - { - public MapDisplay(MapItem map) : base(map, 5, 0, 0, 0) - { - } - } - - private sealed class MapAddPin : MapCommand - { - public MapAddPin(MapItem map, Point2D point) : base(map, 1, 0, point.X, point.Y) - { - } - } - - private sealed class MapSetEditable : MapCommand - { - public MapSetEditable(MapItem map, bool editable) : base(map, 7, editable ? 1 : 0, 0, 0) - { - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Engines.Craft; +using Server.Network; + +namespace Server.Items +{ + [Flippable(0x14EB, 0x14EC)] + public class MapItem : Item, ICraftable + { + private const int MaxUserPins = 50; + private bool m_Editable; + + [Constructible] + public MapItem(Map facet = null) : base(0x14EC) + { + Weight = 1.0; + + Width = 200; + Height = 200; + Facet = facet; + } + + public MapItem(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Protected { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Rectangle2D Bounds { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Width { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Height { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Map Facet { get; set; } + + public List Pins { get; } = new List(); + + public int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, + CraftItem craftItem, int resHue + ) + { + CraftInit(from); + return 1; + } + + public virtual void CraftInit(Mobile from) + { + } + + public void SetDisplay(int x1, int y1, int x2, int y2, int w, int h) + { + Width = w; + Height = h; + + if (x1 < 0) + x1 = 0; + + if (y1 < 0) + y1 = 0; + + if (x2 >= 5120) + x2 = 5119; + + if (y2 >= 4096) + y2 = 4095; + + Bounds = new Rectangle2D(x1, y1, x2 - x1, y2 - y1); + } + + public override void OnDoubleClick(Mobile from) + { + if (from.InRange(GetWorldLocation(), 2)) + DisplayTo(from); + else + from.SendLocalizedMessage(500446); // That is too far away. + } + + public virtual void DisplayTo(Mobile from) + { + var ns = from.NetState; + + if (ns.NewCharacterList) // 7.0.13.0+ supports maps on all facets + { + from.Send(new MapDetailsNew(this)); + } + else if (Facet != null && Facet != Map.Felucca && Facet != Map.Trammel + ) // Is it Felucca and Trammel, or just Felucca? + { + from.SendMessage("You must have client 7.0.13.0 or higher to display this map."); + return; + } + else + { + from.Send(new MapDetails(this)); + } + + from.Send(new MapDisplay(this)); + + for (var i = 0; i < Pins.Count; ++i) + from.Send(new MapAddPin(this, Pins[i])); + + from.Send(new MapSetEditable(this, ValidateEdit(from))); + } + + public virtual void OnAddPin(Mobile from, int x, int y) + { + if (!ValidateEdit(from)) + return; + if (Pins.Count >= MaxUserPins) + return; + + Validate(ref x, ref y); + AddPin(x, y); + } + + public virtual void OnRemovePin(Mobile from, int number) + { + if (!ValidateEdit(from)) + return; + + RemovePin(number); + } + + public virtual void OnChangePin(Mobile from, int number, int x, int y) + { + if (!ValidateEdit(from)) + return; + + Validate(ref x, ref y); + ChangePin(number, x, y); + } + + public virtual void OnInsertPin(Mobile from, int number, int x, int y) + { + if (!ValidateEdit(from)) + return; + if (Pins.Count >= MaxUserPins) + return; + + Validate(ref x, ref y); + InsertPin(number, x, y); + } + + public virtual void OnClearPins(Mobile from) + { + if (!ValidateEdit(from)) + return; + + ClearPins(); + } + + public virtual void OnToggleEditable(Mobile from) + { + if (Validate(from)) + m_Editable = !m_Editable; + + from.Send(new MapSetEditable(this, Validate(from) && m_Editable)); + } + + public virtual void Validate(ref int x, ref int y) + { + x = Math.Clamp(x, 0, Width - 1); + y = Math.Clamp(y, 0, Height - 1); + } + + public virtual bool ValidateEdit(Mobile from) => m_Editable && Validate(from); + + public virtual bool Validate(Mobile from) + { + if (!from.CanSee(this) || from.Map != Map || !from.Alive || InSecureTrade) + return false; + if (from.AccessLevel >= AccessLevel.GameMaster) + return true; + if (!Movable || Protected || !from.InRange(GetWorldLocation(), 2)) + return false; + + return !(RootParent is Mobile && RootParent != from); + } + + public void ConvertToWorld(int x, int y, out int worldX, out int worldY) + { + worldX = Bounds.Width * x / Width + Bounds.X; + worldY = Bounds.Height * y / Height + Bounds.Y; + } + + public void ConvertToMap(int x, int y, out int mapX, out int mapY) + { + mapX = (x - Bounds.X) * Width / Bounds.Width; + mapY = (y - Bounds.Y) * Width / Bounds.Height; + } + + public virtual void AddWorldPin(int x, int y) + { + ConvertToMap(x, y, out var mapX, out var mapY); + AddPin(mapX, mapY); + } + + public virtual void AddPin(int x, int y) + { + Pins.Add(new Point2D(x, y)); + } + + public virtual void RemovePin(int index) + { + if (index > 0 && index < Pins.Count) + Pins.RemoveAt(index); + } + + public virtual void InsertPin(int index, int x, int y) + { + if (index < 0 || index >= Pins.Count) + Pins.Add(new Point2D(x, y)); + else + Pins.Insert(index, new Point2D(x, y)); + } + + public virtual void ChangePin(int index, int x, int y) + { + if (index >= 0 && index < Pins.Count) + Pins[index] = new Point2D(x, y); + } + + public virtual void ClearPins() + { + Pins.Clear(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + writer.Write(Bounds); + + writer.Write(Width); + writer.Write(Height); + + writer.Write(Protected); + + writer.Write(Pins.Count); + for (var i = 0; i < Pins.Count; ++i) + writer.Write(Pins[i]); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Bounds = reader.ReadRect2D(); + + Width = reader.ReadInt(); + Height = reader.ReadInt(); + + Protected = reader.ReadBool(); + + var count = reader.ReadInt(); + for (var i = 0; i < count; i++) + Pins.Add(reader.ReadPoint2D()); + + break; + } + } + } + + public static void Initialize() + { + PacketHandlers.Register(0x56, 11, true, OnMapCommand); + } + + private static void OnMapCommand(NetState state, PacketReader pvSrc) + { + var from = state.Mobile; + + if (!(World.FindItem(pvSrc.ReadUInt32()) is MapItem map)) + return; + + int command = pvSrc.ReadByte(); + int number = pvSrc.ReadByte(); + + int x = pvSrc.ReadInt16(); + int y = pvSrc.ReadInt16(); + + switch (command) + { + case 1: + map.OnAddPin(from, x, y); + break; + case 2: + map.OnInsertPin(from, number, x, y); + break; + case 3: + map.OnChangePin(from, number, x, y); + break; + case 4: + map.OnRemovePin(from, number); + break; + case 5: + map.OnClearPins(from); + break; + case 6: + map.OnToggleEditable(from); + break; + } + } + + private sealed class MapDetails : Packet + { + public MapDetails(MapItem map) : base(0x90, 19) + { + Stream.Write(map.Serial); + Stream.Write((short)0x139D); + Stream.Write((short)map.Bounds.Start.X); + Stream.Write((short)map.Bounds.Start.Y); + Stream.Write((short)map.Bounds.End.X); + Stream.Write((short)map.Bounds.End.Y); + Stream.Write((short)map.Width); + Stream.Write((short)map.Height); + } + } + + private sealed class MapDetailsNew : Packet + { + public MapDetailsNew(MapItem map) : base(0xF5, 21) + { + Stream.Write(map.Serial); + Stream.Write((short)0x139D); + Stream.Write((short)map.Bounds.Start.X); + Stream.Write((short)map.Bounds.Start.Y); + Stream.Write((short)map.Bounds.End.X); + Stream.Write((short)map.Bounds.End.Y); + Stream.Write((short)map.Width); + Stream.Write((short)map.Height); + Stream.Write((short)(map.Facet?.MapID ?? 0)); + } + } + + private abstract class MapCommand : Packet + { + public MapCommand(MapItem map, int command, int number, int x, int y) : base(0x56, 11) + { + Stream.Write(map.Serial); + Stream.Write((byte)command); + Stream.Write((byte)number); + Stream.Write((short)x); + Stream.Write((short)y); + } + } + + private sealed class MapDisplay : MapCommand + { + public MapDisplay(MapItem map) : base(map, 5, 0, 0, 0) + { + } + } + + private sealed class MapAddPin : MapCommand + { + public MapAddPin(MapItem map, Point2D point) : base(map, 1, 0, point.X, point.Y) + { + } + } + + private sealed class MapSetEditable : MapCommand + { + public MapSetEditable(MapItem map, bool editable) : base(map, 7, editable ? 1 : 0, 0, 0) + { + } + } + } +} diff --git a/Projects/UOContent/Items/Maps/PresetMap.cs b/Projects/UOContent/Items/Maps/PresetMap.cs index 23dccbb54..54128d472 100644 --- a/Projects/UOContent/Items/Maps/PresetMap.cs +++ b/Projects/UOContent/Items/Maps/PresetMap.cs @@ -1,145 +1,145 @@ -namespace Server.Items -{ - public class PresetMap : MapItem - { - private int m_LabelNumber; - - [Constructible] - public PresetMap(PresetMapType type) - { - int v = (int)type; - - if (v >= 0 && v < PresetMapEntry.Table.Length) - InitEntry(PresetMapEntry.Table[v]); - } - - public PresetMap(PresetMapEntry entry) - { - InitEntry(entry); - } - - public PresetMap(Serial serial) : base(serial) - { - } - - public override int LabelNumber => m_LabelNumber == 0 ? base.LabelNumber : m_LabelNumber; - - public void InitEntry(PresetMapEntry entry) - { - m_LabelNumber = entry.Name; - - Width = entry.Width; - Height = entry.Height; - - Bounds = entry.Bounds; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(m_LabelNumber); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_LabelNumber = reader.ReadInt(); - break; - } - } - } - } - - public class PresetMapEntry - { - public PresetMapEntry(int name, int width, int height, int xLeft, int yTop, int xRight, int yBottom) - { - Name = name; - Width = width; - Height = height; - Bounds = new Rectangle2D(xLeft, yTop, xRight - xLeft, yBottom - yTop); - } - - public int Name { get; } - - public int Width { get; } - - public int Height { get; } - - public Rectangle2D Bounds { get; } - - public static PresetMapEntry[] Table { get; } = - { - new PresetMapEntry(1041189, 200, 200, 1092, 1396, 1736, 1924), // map of Britain - new PresetMapEntry(1041203, 200, 200, 0256, 1792, 1736, 2560), // map of Britain to Skara Brae - new PresetMapEntry(1041192, 200, 200, 1024, 1280, 2304, 3072), // map of Britain to Trinsic - new PresetMapEntry(1041183, 200, 200, 2500, 1900, 3000, 2400), // map of Buccaneer's Den - new PresetMapEntry(1041198, 200, 200, 2560, 1792, 3840, 2560), // map of Buccaneer's Den to Magincia - new PresetMapEntry(1041194, 200, 200, 2560, 1792, 3840, 3072), // map of Buccaneer's Den to Ocllo - new PresetMapEntry(1041181, 200, 200, 1088, 3572, 1528, 4056), // map of Jhelom - new PresetMapEntry(1041186, 200, 200, 3530, 2022, 3818, 2298), // map of Magincia - new PresetMapEntry(1041199, 200, 200, 3328, 1792, 3840, 2304), // map of Magincia to Ocllo - new PresetMapEntry(1041182, 200, 200, 2360, 0356, 2706, 0702), // map of Minoc - new PresetMapEntry(1041190, 200, 200, 0000, 0256, 2304, 3072), // map of Minoc to Yew - new PresetMapEntry(1041191, 200, 200, 2467, 0572, 2878, 0746), // map of Minoc to Vesper - new PresetMapEntry(1041188, 200, 200, 4156, 0808, 4732, 1528), // map of Moonglow - new PresetMapEntry(1041201, 200, 200, 3328, 0768, 4864, 1536), // map of Moonglow to Nujelm - new PresetMapEntry(1041185, 200, 200, 3446, 1030, 3832, 1424), // map of Nujelm - new PresetMapEntry(1041197, 200, 200, 3328, 1024, 3840, 2304), // map of Nujelm to Magincia - new PresetMapEntry(1041187, 200, 200, 3582, 2456, 3770, 2742), // map of Ocllo - new PresetMapEntry(1041184, 200, 200, 2714, 3329, 3100, 3639), // map of Serpent's Hold - new PresetMapEntry(1041200, 200, 200, 2560, 2560, 3840, 3840), // map of Serpent's Hold to Ocllo - new PresetMapEntry(1041180, 200, 200, 0524, 2064, 0960, 2452), // map of Skara Brae - new PresetMapEntry(1041204, 200, 200, 0000, 0000, 5199, 4095), // map of The World - new PresetMapEntry(1041177, 200, 200, 1792, 2630, 2118, 2952), // map of Trinsic - new PresetMapEntry(1041193, 200, 200, 1792, 1792, 3072, 3072), // map of Trinsic to Buccaneer's Den - new PresetMapEntry(1041195, 200, 200, 0256, 1792, 2304, 4095), // map of Trinsic to Jhelom - new PresetMapEntry(1041178, 200, 200, 2636, 0592, 3064, 1012), // map of Vesper - new PresetMapEntry(1041196, 200, 200, 2636, 0592, 3840, 1536), // map of Vesper to Nujelm - new PresetMapEntry(1041179, 200, 200, 0236, 0741, 0766, 1269), // map of Yew - new PresetMapEntry(1041202, 200, 200, 0000, 0512, 1792, 2048) // map of Yew to Britain - }; - } - - public enum PresetMapType - { - Britain, - BritainToSkaraBrae, - BritainToTrinsic, - BucsDen, - BucsDenToMagincia, - BucsDenToOcllo, - Jhelom, - Magincia, - MaginciaToOcllo, - Minoc, - MinocToYew, - MinocToVesper, - Moonglow, - MoonglowToNujelm, - Nujelm, - NujelmToMagincia, - Ocllo, - SerpentsHold, - SerpentsHoldToOcllo, - SkaraBrae, - TheWorld, - Trinsic, - TrinsicToBucsDen, - TrinsicToJhelom, - Vesper, - VesperToNujelm, - Yew, - YewToBritain - } -} \ No newline at end of file +namespace Server.Items +{ + public class PresetMap : MapItem + { + private int m_LabelNumber; + + [Constructible] + public PresetMap(PresetMapType type) + { + var v = (int)type; + + if (v >= 0 && v < PresetMapEntry.Table.Length) + InitEntry(PresetMapEntry.Table[v]); + } + + public PresetMap(PresetMapEntry entry) + { + InitEntry(entry); + } + + public PresetMap(Serial serial) : base(serial) + { + } + + public override int LabelNumber => m_LabelNumber == 0 ? base.LabelNumber : m_LabelNumber; + + public void InitEntry(PresetMapEntry entry) + { + m_LabelNumber = entry.Name; + + Width = entry.Width; + Height = entry.Height; + + Bounds = entry.Bounds; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + writer.Write(m_LabelNumber); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_LabelNumber = reader.ReadInt(); + break; + } + } + } + } + + public class PresetMapEntry + { + public PresetMapEntry(int name, int width, int height, int xLeft, int yTop, int xRight, int yBottom) + { + Name = name; + Width = width; + Height = height; + Bounds = new Rectangle2D(xLeft, yTop, xRight - xLeft, yBottom - yTop); + } + + public int Name { get; } + + public int Width { get; } + + public int Height { get; } + + public Rectangle2D Bounds { get; } + + public static PresetMapEntry[] Table { get; } = + { + new PresetMapEntry(1041189, 200, 200, 1092, 1396, 1736, 1924), // map of Britain + new PresetMapEntry(1041203, 200, 200, 0256, 1792, 1736, 2560), // map of Britain to Skara Brae + new PresetMapEntry(1041192, 200, 200, 1024, 1280, 2304, 3072), // map of Britain to Trinsic + new PresetMapEntry(1041183, 200, 200, 2500, 1900, 3000, 2400), // map of Buccaneer's Den + new PresetMapEntry(1041198, 200, 200, 2560, 1792, 3840, 2560), // map of Buccaneer's Den to Magincia + new PresetMapEntry(1041194, 200, 200, 2560, 1792, 3840, 3072), // map of Buccaneer's Den to Ocllo + new PresetMapEntry(1041181, 200, 200, 1088, 3572, 1528, 4056), // map of Jhelom + new PresetMapEntry(1041186, 200, 200, 3530, 2022, 3818, 2298), // map of Magincia + new PresetMapEntry(1041199, 200, 200, 3328, 1792, 3840, 2304), // map of Magincia to Ocllo + new PresetMapEntry(1041182, 200, 200, 2360, 0356, 2706, 0702), // map of Minoc + new PresetMapEntry(1041190, 200, 200, 0000, 0256, 2304, 3072), // map of Minoc to Yew + new PresetMapEntry(1041191, 200, 200, 2467, 0572, 2878, 0746), // map of Minoc to Vesper + new PresetMapEntry(1041188, 200, 200, 4156, 0808, 4732, 1528), // map of Moonglow + new PresetMapEntry(1041201, 200, 200, 3328, 0768, 4864, 1536), // map of Moonglow to Nujelm + new PresetMapEntry(1041185, 200, 200, 3446, 1030, 3832, 1424), // map of Nujelm + new PresetMapEntry(1041197, 200, 200, 3328, 1024, 3840, 2304), // map of Nujelm to Magincia + new PresetMapEntry(1041187, 200, 200, 3582, 2456, 3770, 2742), // map of Ocllo + new PresetMapEntry(1041184, 200, 200, 2714, 3329, 3100, 3639), // map of Serpent's Hold + new PresetMapEntry(1041200, 200, 200, 2560, 2560, 3840, 3840), // map of Serpent's Hold to Ocllo + new PresetMapEntry(1041180, 200, 200, 0524, 2064, 0960, 2452), // map of Skara Brae + new PresetMapEntry(1041204, 200, 200, 0000, 0000, 5199, 4095), // map of The World + new PresetMapEntry(1041177, 200, 200, 1792, 2630, 2118, 2952), // map of Trinsic + new PresetMapEntry(1041193, 200, 200, 1792, 1792, 3072, 3072), // map of Trinsic to Buccaneer's Den + new PresetMapEntry(1041195, 200, 200, 0256, 1792, 2304, 4095), // map of Trinsic to Jhelom + new PresetMapEntry(1041178, 200, 200, 2636, 0592, 3064, 1012), // map of Vesper + new PresetMapEntry(1041196, 200, 200, 2636, 0592, 3840, 1536), // map of Vesper to Nujelm + new PresetMapEntry(1041179, 200, 200, 0236, 0741, 0766, 1269), // map of Yew + new PresetMapEntry(1041202, 200, 200, 0000, 0512, 1792, 2048) // map of Yew to Britain + }; + } + + public enum PresetMapType + { + Britain, + BritainToSkaraBrae, + BritainToTrinsic, + BucsDen, + BucsDenToMagincia, + BucsDenToOcllo, + Jhelom, + Magincia, + MaginciaToOcllo, + Minoc, + MinocToYew, + MinocToVesper, + Moonglow, + MoonglowToNujelm, + Nujelm, + NujelmToMagincia, + Ocllo, + SerpentsHold, + SerpentsHoldToOcllo, + SkaraBrae, + TheWorld, + Trinsic, + TrinsicToBucsDen, + TrinsicToJhelom, + Vesper, + VesperToNujelm, + Yew, + YewToBritain + } +} diff --git a/Projects/UOContent/Items/Maps/SeaChart.cs b/Projects/UOContent/Items/Maps/SeaChart.cs index e90f2185b..a3465d6b4 100644 --- a/Projects/UOContent/Items/Maps/SeaChart.cs +++ b/Projects/UOContent/Items/Maps/SeaChart.cs @@ -1,49 +1,49 @@ -namespace Server.Items -{ - public class SeaChart : MapItem - { - [Constructible] - public SeaChart() - { - SetDisplay(0, 0, 5119, 4095, 400, 400); - } - - public SeaChart(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1015232; // sea chart - - public override void CraftInit(Mobile from) - { - double skillValue = from.Skills.Cartography.Value; - int dist = 64 + (int)(skillValue * 10); - - if (dist < 200) - dist = 200; - - int size = 24 + (int)(skillValue * 3.3); - - if (size < 200) - size = 200; - else if (size > 400) - size = 400; - - SetDisplay(from.X - dist, from.Y - dist, from.X + dist, from.Y + dist, size, size); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SeaChart : MapItem + { + [Constructible] + public SeaChart() + { + SetDisplay(0, 0, 5119, 4095, 400, 400); + } + + public SeaChart(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1015232; // sea chart + + public override void CraftInit(Mobile from) + { + var skillValue = from.Skills.Cartography.Value; + var dist = 64 + (int)(skillValue * 10); + + if (dist < 200) + dist = 200; + + var size = 24 + (int)(skillValue * 3.3); + + if (size < 200) + size = 200; + else if (size > 400) + size = 400; + + SetDisplay(from.X - dist, from.Y - dist, from.X + dist, from.Y + dist, size, size); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Maps/TreasureMap.cs b/Projects/UOContent/Items/Maps/TreasureMap.cs index ac7826c37..d348eac91 100644 --- a/Projects/UOContent/Items/Maps/TreasureMap.cs +++ b/Projects/UOContent/Items/Maps/TreasureMap.cs @@ -1,933 +1,955 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Server.ContextMenus; -using Server.Engines.Harvest; -using Server.Mobiles; -using Server.Network; -using Server.Targeting; -using Server.Utilities; - -namespace Server.Items -{ - public class TreasureMap : MapItem - { - public const double LootChance = 0.01; // 1% chance to appear as loot - - private static Point2D[] m_Locations; - private static Point2D[] m_HavenLocations; - - private static readonly Type[][] m_SpawnTypes = - { - new[] { typeof(HeadlessOne), typeof(Skeleton) }, - new[] { typeof(Mongbat), typeof(Ratman), typeof(HeadlessOne), typeof(Skeleton), typeof(Zombie) }, - new[] { typeof(OrcishMage), typeof(Gargoyle), typeof(Gazer), typeof(HellHound), typeof(EarthElemental) }, - new[] { typeof(Lich), typeof(OgreLord), typeof(DreadSpider), typeof(AirElemental), typeof(FireElemental) }, - new[] { typeof(DreadSpider), typeof(LichLord), typeof(Daemon), typeof(ElderGazer), typeof(OgreLord) }, - new[] { typeof(LichLord), typeof(Daemon), typeof(ElderGazer), typeof(PoisonElemental), typeof(BloodElemental) }, - new[] { typeof(AncientWyrm), typeof(Balron), typeof(BloodElemental), typeof(PoisonElemental), typeof(Titan) } - }; - - private bool m_Completed; - private Mobile m_CompletedBy; - private Mobile m_Decoder; - private int m_Level; - private Map m_Map; - - [Constructible] - public TreasureMap(int level, Map map) - { - m_Level = level; - m_Map = map; - - if (level == 0) - ChestLocation = GetRandomHavenLocation(); - else - ChestLocation = GetRandomLocation(); - - Width = 300; - Height = 300; - - int width = 600; - int height = 600; - - int x1 = ChestLocation.X - Utility.RandomMinMax(width / 4, width / 4 * 3); - int y1 = ChestLocation.Y - Utility.RandomMinMax(height / 4, height / 4 * 3); - - if (x1 < 0) - x1 = 0; - - if (y1 < 0) - y1 = 0; - - int x2 = x1 + width; - int y2 = y1 + height; - - if (x2 >= 5120) - x2 = 5119; - - if (y2 >= 4096) - y2 = 4095; - - x1 = x2 - width; - y1 = y2 - height; - - Bounds = new Rectangle2D(x1, y1, width, height); - Protected = true; - - AddWorldPin(ChestLocation.X, ChestLocation.Y); - } - - public TreasureMap(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Level - { - get => m_Level; - set - { - m_Level = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Completed - { - get => m_Completed; - set - { - m_Completed = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile CompletedBy - { - get => m_CompletedBy; - set - { - m_CompletedBy = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Decoder - { - get => m_Decoder; - set - { - m_Decoder = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Map ChestMap - { - get => m_Map; - set - { - m_Map = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Point2D ChestLocation { get; set; } - - public override int LabelNumber - { - get - { - if (m_Decoder != null) - { - if (m_Level == 6) - return 1063453; - return 1041516 + m_Level; - } - - if (m_Level == 6) - return 1063452; - return 1041510 + m_Level; - } - } - - public static Point2D GetRandomLocation() - { - if (m_Locations == null) - LoadLocations(); - - return m_Locations?.RandomElement() ?? Point2D.Zero; - } - - public static Point2D GetRandomHavenLocation() - { - if (m_HavenLocations == null) - LoadLocations(); - - return m_HavenLocations?.RandomElement() ?? Point2D.Zero; - } - - private static void LoadLocations() - { - string filePath = Path.Combine(Core.BaseDirectory, "Data/treasure.cfg"); - - List list = new List(); - List havenList = new List(); - - if (File.Exists(filePath)) - { - using StreamReader ip = new StreamReader(filePath); - string line; - - while ((line = ip.ReadLine()) != null) - try - { - string[] split = line.Split(' '); - - int x = Convert.ToInt32(split[0]), y = Convert.ToInt32(split[1]); - - Point2D loc = new Point2D(x, y); - list.Add(loc); - - if (IsInHavenIsland(loc)) - havenList.Add(loc); - } - catch - { - // ignored - } - } - - m_Locations = list.ToArray(); - m_HavenLocations = havenList.ToArray(); - } - - public static bool IsInHavenIsland(IPoint2D loc) => loc.X >= 3314 && loc.X <= 3814 && loc.Y >= 2345 && loc.Y <= 3095; - - public static BaseCreature Spawn(int level, Point3D p, bool guardian) - { - if (level >= 0 && level < m_SpawnTypes.Length) - { - BaseCreature bc; - - try - { - bc = (BaseCreature)ActivatorUtil.CreateInstance(m_SpawnTypes[level].RandomElement()); - } - catch - { - return null; - } - - bc.Home = p; - bc.RangeHome = 5; - - if (guardian && level == 0) - { - bc.Name = "a chest guardian"; - bc.Hue = 0x835; - } - - return bc; - } - - return null; - } - - public static BaseCreature Spawn(int level, Point3D p, Map map, Mobile target, bool guardian) - { - if (map == null) - return null; - - BaseCreature c = Spawn(level, p, guardian); - - if (c != null) - { - bool spawned = false; - - for (int i = 0; !spawned && i < 10; ++i) - { - int x = p.X - 3 + Utility.Random(7); - int y = p.Y - 3 + Utility.Random(7); - - if (map.CanSpawnMobile(x, y, p.Z)) - { - c.MoveToWorld(new Point3D(x, y, p.Z), map); - spawned = true; - } - else - { - int z = map.GetAverageZ(x, y); - - if (map.CanSpawnMobile(x, y, z)) - { - c.MoveToWorld(new Point3D(x, y, z), map); - spawned = true; - } - } - } - - if (!spawned) - { - c.Delete(); - return null; - } - - if (target != null) - c.Combatant = target; - - return c; - } - - return null; - } - - public static bool HasDiggingTool(Mobile m) - { - return m.Backpack?.FindItemsByType().Any(tool => tool.HarvestSystem == Mining.System) == true; - } - - public void OnBeginDig(Mobile from) - { - if (m_Completed) - { - from.SendLocalizedMessage(503028); // The treasure for this map has already been found. - } - else if (m_Level == 0 && !CheckYoung(from)) - { - from.SendLocalizedMessage(1046447); // Only a young player may use this treasure map. - } - /* - else if (from != m_Decoder) - { - from.SendLocalizedMessage( 503016 ); // Only the person who decoded this map may actually dig up the treasure. - } - */ - else if (m_Decoder != from && !HasRequiredSkill(from)) - { - from.SendLocalizedMessage( - 503031); // You did not decode this map and have no clue where to look for the treasure. - } - else if (!from.CanBeginAction()) - { - from.SendLocalizedMessage(503020); // You are already digging treasure. - } - else if (from.Map != m_Map) - { - from.SendLocalizedMessage(1010479); // You seem to be in the right place, but may be on the wrong facet! - } - else - { - from.SendLocalizedMessage(503033); // Where do you wish to dig? - from.Target = new DigTarget(this); - } - } - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return; - } - - if (!m_Completed && m_Decoder == null) - Decode(from); - else - DisplayTo(from); - } - - private bool CheckYoung(Mobile from) - { - if (from.AccessLevel >= AccessLevel.GameMaster) - return true; - - if (from is PlayerMobile mobile && mobile.Young) - return true; - - if (from == Decoder) - { - Level = 1; - from.SendLocalizedMessage(1046446); // This is now a level one treasure map. - return true; - } - - return false; - } - - private double GetMinSkillLevel() - { - return m_Level switch - { - 1 => -3.0, - 2 => 41.0, - 3 => 51.0, - 4 => 61.0, - 5 => 70.0, - 6 => 70.0, - _ => 0.0 - }; - } - - private bool HasRequiredSkill(Mobile from) => from.Skills.Cartography.Value >= GetMinSkillLevel(); - - public void Decode(Mobile from) - { - if (m_Completed || m_Decoder != null) - return; - - if (m_Level == 0) - { - if (!CheckYoung(from)) - { - from.SendLocalizedMessage(1046447); // Only a young player may use this treasure map. - return; - } - } - else - { - double minSkill = GetMinSkillLevel(); - - if (from.Skills.Cartography.Value < minSkill) - from.SendLocalizedMessage(503013); // The map is too difficult to attempt to decode. - - double maxSkill = minSkill + 60.0; - - if (!from.CheckSkill(SkillName.Cartography, minSkill, maxSkill)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 503018); // You fail to make anything of the map. - return; - } - } - - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 503019); // You successfully decode a treasure map! - Decoder = from; - - if (Core.AOS) - LootType = LootType.Blessed; - - DisplayTo(from); - } - - public override void DisplayTo(Mobile from) - { - if (m_Completed) - { - SendLocalizedMessageTo(from, 503014); // This treasure hunt has already been completed. - } - else if (m_Level == 0 && !CheckYoung(from)) - { - from.SendLocalizedMessage(1046447); // Only a young player may use this treasure map. - return; - } - else if (m_Decoder != from && !HasRequiredSkill(from)) - { - from.SendLocalizedMessage( - 503031); // You did not decode this map and have no clue where to look for the treasure. - return; - } - else - { - SendLocalizedMessageTo(from, - 503017); // The treasure is marked by the red pin. Grab a shovel and go dig it up! - } - - from.PlaySound(0x249); - base.DisplayTo(from); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (!m_Completed) - { - if (m_Decoder == null) - { - list.Add(new DecodeMapEntry(this)); - } - else - { - bool digTool = HasDiggingTool(from); - - list.Add(new OpenMapEntry(this)); - list.Add(new DigEntry(this, digTool)); - } - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(m_Map == Map.Felucca ? 1041502 : 1041503); // for somewhere in Felucca : for somewhere in Trammel - - if (m_Completed) - list.Add(1041507, m_CompletedBy == null ? "someone" : m_CompletedBy.Name); // completed by ~1_val~ - } - - public override void OnSingleClick(Mobile from) - { - if (m_Completed) - { - from.Send(new MessageLocalizedAffix(Serial, ItemID, MessageType.Label, 0x3B2, 3, 1048030, "", - AffixType.Append, - $" completed by {(m_CompletedBy == null ? "someone" : m_CompletedBy.Name)}", "")); - } - else if (m_Decoder != null) - { - if (m_Level == 6) - LabelTo(from, 1063453); - else - LabelTo(from, 1041516 + m_Level); - } - else - { - if (m_Level == 6) - LabelTo(from, 1041522, $"#{1063452}\t \t#{(m_Map == Map.Felucca ? 1041502 : 1041503)}"); - else - LabelTo(from, 1041522, $"#{1041510 + m_Level}\t \t#{(m_Map == Map.Felucca ? 1041502 : 1041503)}"); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - - writer.Write(m_CompletedBy); - - writer.Write(m_Level); - writer.Write(m_Completed); - writer.Write(m_Decoder); - writer.Write(m_Map); - writer.Write(ChestLocation); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_CompletedBy = reader.ReadMobile(); - - goto case 0; - } - case 0: - { - m_Level = reader.ReadInt(); - m_Completed = reader.ReadBool(); - m_Decoder = reader.ReadMobile(); - m_Map = reader.ReadMap(); - ChestLocation = reader.ReadPoint2D(); - - if (version == 0 && m_Completed) - m_CompletedBy = m_Decoder; - - break; - } - } - - if (Core.AOS && m_Decoder != null && LootType == LootType.Regular) - LootType = LootType.Blessed; - } - - private class DigTarget : Target - { - private readonly TreasureMap m_Map; - - public DigTarget(TreasureMap map) : base(6, true, TargetFlags.None) => m_Map = map; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Map.Deleted) - return; - - Map map = m_Map.m_Map; - - if (m_Map.m_Completed) - { - from.SendLocalizedMessage(503028); // The treasure for this map has already been found. - } - /* - else if (from != m_Map.m_Decoder) - { - from.SendLocalizedMessage( 503016 ); // Only the person who decoded this map may actually dig up the treasure. - } - */ - else if (m_Map.m_Decoder != from && !m_Map.HasRequiredSkill(from)) - { - from.SendLocalizedMessage( - 503031); // You did not decode this map and have no clue where to look for the treasure. - } - else if (!from.CanBeginAction()) - { - from.SendLocalizedMessage(503020); // You are already digging treasure. - } - else if (!HasDiggingTool(from)) - { - from.SendMessage("You must have a digging tool to dig for treasure."); - } - else if (from.Map != map) - { - from.SendLocalizedMessage(1010479); // You seem to be in the right place, but may be on the wrong facet! - } - else - { - IPoint3D p = targeted as IPoint3D; - - Point3D targ3D = (p as Item)?.GetWorldLocation() ?? new Point3D(p); - - int maxRange; - double skillValue = from.Skills.Mining.Value; - - if (skillValue >= 100.0) - maxRange = 4; - else if (skillValue >= 81.0) - maxRange = 3; - else if (skillValue >= 51.0) - maxRange = 2; - else - maxRange = 1; - - Point2D loc = m_Map.ChestLocation; - int x = loc.X, y = loc.Y; - - Point3D chest3D0 = new Point3D(loc, 0); - - if (Utility.InRange(targ3D, chest3D0, maxRange)) - { - if (from.Location.X == x && from.Location.Y == y) - { - from.SendLocalizedMessage( - 503030); // The chest can't be dug up because you are standing on top of it. - } - else if (map != null) - { - int z = map.GetAverageZ(x, y); - - if (!map.CanFit(x, y, z, 16, true)) - from.SendLocalizedMessage( - 503021); // You have found the treasure chest but something is keeping it from being dug up. - else if (from.BeginAction()) - new DigTimer(from, m_Map, new Point3D(x, y, z), map).Start(); - else - from.SendLocalizedMessage(503020); // You are already digging treasure. - } - } - else if (m_Map.Level > 0) - { - if (Utility.InRange(targ3D, chest3D0, 8)) // We're close, but not quite - from.SendLocalizedMessage(503032); // You dig and dig but no treasure seems to be here. - else - from.SendLocalizedMessage(503035); // You dig and dig but fail to find any treasure. - } - else - { - if (Utility.InRange(targ3D, chest3D0, 8)) // We're close, but not quite - { - from.SendAsciiMessage(0x44, "The treasure chest is very close!"); - } - else - { - Direction dir = Utility.GetDirection(targ3D, chest3D0); - - var sDir = dir switch - { - Direction.North => "north", - Direction.Right => "northeast", - Direction.East => "east", - Direction.Down => "southeast", - Direction.South => "south", - Direction.Left => "southwest", - Direction.West => "west", - _ => "northwest" - }; - - from.SendAsciiMessage(0x44, "Try looking for the treasure chest more to the {0}.", sDir); - } - } - } - } - } - - private class DigTimer : Timer - { - private TreasureMapChest m_Chest; - - private int m_Count; - - private TreasureChestDirt m_Dirt1; - private TreasureChestDirt m_Dirt2; - private readonly Mobile m_From; - private readonly long m_LastMoveTime; - - private Point3D m_Location; - private readonly Map m_Map; - private readonly long m_NextActionTime; - - private readonly long m_NextSkillTime; - private readonly long m_NextSpellTime; - private readonly TreasureMap m_TreasureMap; - - public DigTimer(Mobile from, TreasureMap treasureMap, Point3D location, Map map) : base(TimeSpan.Zero, - TimeSpan.FromSeconds(1.0)) - { - m_From = from; - m_TreasureMap = treasureMap; - - m_Location = location; - m_Map = map; - - m_NextSkillTime = from.NextSkillTime; - m_NextSpellTime = from.NextSpellTime; - m_NextActionTime = from.NextActionTime; - m_LastMoveTime = from.LastMoveTime; - - Priority = TimerPriority.TenMS; - } - - private void Terminate() - { - Stop(); - m_From.EndAction(); - - m_Chest?.Delete(); - - if (m_Dirt1 != null) - { - m_Dirt1.Delete(); - m_Dirt2.Delete(); - } - } - - protected override void OnTick() - { - if (m_NextSkillTime != m_From.NextSkillTime || m_NextSpellTime != m_From.NextSpellTime || - m_NextActionTime != m_From.NextActionTime) - { - Terminate(); - return; - } - - if (m_LastMoveTime != m_From.LastMoveTime) - { - m_From.SendLocalizedMessage( - 503023); // You cannot move around while digging up treasure. You will need to start digging anew. - Terminate(); - return; - } - - int z = m_Chest != null ? m_Chest.Z + m_Chest.ItemData.Height : int.MinValue; - int height = 16; - - if (z > m_Location.Z) - height -= z - m_Location.Z; - else - z = m_Location.Z; - - if (!m_Map.CanFit(m_Location.X, m_Location.Y, z, height, true, true, false)) - { - m_From.SendLocalizedMessage( - 503024); // You stop digging because something is directly on top of the treasure chest. - Terminate(); - return; - } - - m_Count++; - - m_From.RevealingAction(); - m_From.Direction = m_From.GetDirectionTo(m_Location); - - if (m_Count > 1 && m_Dirt1 == null) - { - m_Dirt1 = new TreasureChestDirt(); - m_Dirt1.MoveToWorld(m_Location, m_Map); - - m_Dirt2 = new TreasureChestDirt(); - m_Dirt2.MoveToWorld(new Point3D(m_Location.X, m_Location.Y - 1, m_Location.Z), m_Map); - } - - if (m_Count == 5) - { - m_Dirt1.Turn1(); - } - else if (m_Count == 10) - { - m_Dirt1.Turn2(); - m_Dirt2.Turn2(); - } - else if (m_Count > 10) - { - if (m_Chest == null) - { - m_Chest = new TreasureMapChest(m_From, m_TreasureMap.Level, true); - m_Chest.MoveToWorld(new Point3D(m_Location.X, m_Location.Y, m_Location.Z - 15), m_Map); - } - else - { - m_Chest.Z++; - } - - Effects.PlaySound(m_Chest, m_Map, 0x33B); - } - - if (m_Chest?.Location.Z >= m_Location.Z) - { - Stop(); - m_From.EndAction(); - - m_Chest.Temporary = false; - m_TreasureMap.Completed = true; - m_TreasureMap.CompletedBy = m_From; - - var spawns = m_TreasureMap.Level switch - { - 0 => 3, - 1 => 0, - _ => 4 - }; - - for (int i = 0; i < spawns; ++i) - { - BaseCreature bc = Spawn(m_TreasureMap.Level, m_Chest.Location, m_Chest.Map, null, true); - - if (bc != null) - m_Chest.Guardians.Add(bc); - } - } - else - { - if (m_From.Body.IsHuman && !m_From.Mounted) - m_From.Animate(11, 5, 1, true, false, 0); - - new SoundTimer(m_From, 0x125 + m_Count % 2).Start(); - } - } - - private class SoundTimer : Timer - { - private readonly Mobile m_From; - private readonly int m_SoundID; - - public SoundTimer(Mobile from, int soundID) : base(TimeSpan.FromSeconds(0.9)) - { - m_From = from; - m_SoundID = soundID; - - Priority = TimerPriority.TenMS; - } - - protected override void OnTick() - { - m_From.PlaySound(m_SoundID); - } - } - } - - private class DecodeMapEntry : ContextMenuEntry - { - private readonly TreasureMap m_Map; - - public DecodeMapEntry(TreasureMap map) : base(6147, 2) => m_Map = map; - - public override void OnClick() - { - if (!m_Map.Deleted) - m_Map.Decode(Owner.From); - } - } - - private class OpenMapEntry : ContextMenuEntry - { - private readonly TreasureMap m_Map; - - public OpenMapEntry(TreasureMap map) : base(6150, 2) => m_Map = map; - - public override void OnClick() - { - if (!m_Map.Deleted) - m_Map.DisplayTo(Owner.From); - } - } - - private class DigEntry : ContextMenuEntry - { - private readonly TreasureMap m_Map; - - public DigEntry(TreasureMap map, bool enabled) : base(6148, 2) - { - m_Map = map; - - if (!enabled) - Flags |= CMEFlags.Disabled; - } - - public override void OnClick() - { - if (m_Map.Deleted) - return; - - Mobile from = Owner.From; - - if (HasDiggingTool(from)) - m_Map.OnBeginDig(from); - else - from.SendMessage("You must have a digging tool to dig for treasure."); - } - } - } - - public class TreasureChestDirt : Item - { - public TreasureChestDirt() : base(0x912) - { - Movable = false; - - Timer.DelayCall(TimeSpan.FromMinutes(2.0), Delete); - } - - public TreasureChestDirt(Serial serial) : base(serial) - { - } - - public void Turn1() - { - ItemID = 0x913; - } - - public void Turn2() - { - ItemID = 0x914; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - Delete(); - } - } -} +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Server.ContextMenus; +using Server.Engines.Harvest; +using Server.Mobiles; +using Server.Network; +using Server.Targeting; +using Server.Utilities; + +namespace Server.Items +{ + public class TreasureMap : MapItem + { + public const double LootChance = 0.01; // 1% chance to appear as loot + + private static Point2D[] m_Locations; + private static Point2D[] m_HavenLocations; + + private static readonly Type[][] m_SpawnTypes = + { + new[] { typeof(HeadlessOne), typeof(Skeleton) }, + new[] { typeof(Mongbat), typeof(Ratman), typeof(HeadlessOne), typeof(Skeleton), typeof(Zombie) }, + new[] { typeof(OrcishMage), typeof(Gargoyle), typeof(Gazer), typeof(HellHound), typeof(EarthElemental) }, + new[] { typeof(Lich), typeof(OgreLord), typeof(DreadSpider), typeof(AirElemental), typeof(FireElemental) }, + new[] { typeof(DreadSpider), typeof(LichLord), typeof(Daemon), typeof(ElderGazer), typeof(OgreLord) }, + new[] { typeof(LichLord), typeof(Daemon), typeof(ElderGazer), typeof(PoisonElemental), typeof(BloodElemental) }, + new[] { typeof(AncientWyrm), typeof(Balron), typeof(BloodElemental), typeof(PoisonElemental), typeof(Titan) } + }; + + private bool m_Completed; + private Mobile m_CompletedBy; + private Mobile m_Decoder; + private int m_Level; + private Map m_Map; + + [Constructible] + public TreasureMap(int level, Map map) + { + m_Level = level; + m_Map = map; + + if (level == 0) + ChestLocation = GetRandomHavenLocation(); + else + ChestLocation = GetRandomLocation(); + + Width = 300; + Height = 300; + + var width = 600; + var height = 600; + + var x1 = ChestLocation.X - Utility.RandomMinMax(width / 4, width / 4 * 3); + var y1 = ChestLocation.Y - Utility.RandomMinMax(height / 4, height / 4 * 3); + + if (x1 < 0) + x1 = 0; + + if (y1 < 0) + y1 = 0; + + var x2 = x1 + width; + var y2 = y1 + height; + + if (x2 >= 5120) + x2 = 5119; + + if (y2 >= 4096) + y2 = 4095; + + x1 = x2 - width; + y1 = y2 - height; + + Bounds = new Rectangle2D(x1, y1, width, height); + Protected = true; + + AddWorldPin(ChestLocation.X, ChestLocation.Y); + } + + public TreasureMap(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Level + { + get => m_Level; + set + { + m_Level = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Completed + { + get => m_Completed; + set + { + m_Completed = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile CompletedBy + { + get => m_CompletedBy; + set + { + m_CompletedBy = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Decoder + { + get => m_Decoder; + set + { + m_Decoder = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Map ChestMap + { + get => m_Map; + set + { + m_Map = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Point2D ChestLocation { get; set; } + + public override int LabelNumber + { + get + { + if (m_Decoder != null) + { + if (m_Level == 6) + return 1063453; + return 1041516 + m_Level; + } + + if (m_Level == 6) + return 1063452; + return 1041510 + m_Level; + } + } + + public static Point2D GetRandomLocation() + { + if (m_Locations == null) + LoadLocations(); + + return m_Locations?.RandomElement() ?? Point2D.Zero; + } + + public static Point2D GetRandomHavenLocation() + { + if (m_HavenLocations == null) + LoadLocations(); + + return m_HavenLocations?.RandomElement() ?? Point2D.Zero; + } + + private static void LoadLocations() + { + var filePath = Path.Combine(Core.BaseDirectory, "Data/treasure.cfg"); + + var list = new List(); + var havenList = new List(); + + if (File.Exists(filePath)) + { + using var ip = new StreamReader(filePath); + string line; + + while ((line = ip.ReadLine()) != null) + try + { + var split = line.Split(' '); + + int x = Convert.ToInt32(split[0]), y = Convert.ToInt32(split[1]); + + var loc = new Point2D(x, y); + list.Add(loc); + + if (IsInHavenIsland(loc)) + havenList.Add(loc); + } + catch + { + // ignored + } + } + + m_Locations = list.ToArray(); + m_HavenLocations = havenList.ToArray(); + } + + public static bool IsInHavenIsland(IPoint2D loc) => loc.X >= 3314 && loc.X <= 3814 && loc.Y >= 2345 && loc.Y <= 3095; + + public static BaseCreature Spawn(int level, Point3D p, bool guardian) + { + if (level >= 0 && level < m_SpawnTypes.Length) + { + BaseCreature bc; + + try + { + bc = (BaseCreature)ActivatorUtil.CreateInstance(m_SpawnTypes[level].RandomElement()); + } + catch + { + return null; + } + + bc.Home = p; + bc.RangeHome = 5; + + if (guardian && level == 0) + { + bc.Name = "a chest guardian"; + bc.Hue = 0x835; + } + + return bc; + } + + return null; + } + + public static BaseCreature Spawn(int level, Point3D p, Map map, Mobile target, bool guardian) + { + if (map == null) + return null; + + var c = Spawn(level, p, guardian); + + if (c != null) + { + var spawned = false; + + for (var i = 0; !spawned && i < 10; ++i) + { + var x = p.X - 3 + Utility.Random(7); + var y = p.Y - 3 + Utility.Random(7); + + if (map.CanSpawnMobile(x, y, p.Z)) + { + c.MoveToWorld(new Point3D(x, y, p.Z), map); + spawned = true; + } + else + { + var z = map.GetAverageZ(x, y); + + if (map.CanSpawnMobile(x, y, z)) + { + c.MoveToWorld(new Point3D(x, y, z), map); + spawned = true; + } + } + } + + if (!spawned) + { + c.Delete(); + return null; + } + + if (target != null) + c.Combatant = target; + + return c; + } + + return null; + } + + public static bool HasDiggingTool(Mobile m) + { + return m.Backpack?.FindItemsByType().Any(tool => tool.HarvestSystem == Mining.System) == true; + } + + public void OnBeginDig(Mobile from) + { + if (m_Completed) + { + from.SendLocalizedMessage(503028); // The treasure for this map has already been found. + } + else if (m_Level == 0 && !CheckYoung(from)) + { + from.SendLocalizedMessage(1046447); // Only a young player may use this treasure map. + } + /* + else if (from != m_Decoder) + { + from.SendLocalizedMessage( 503016 ); // Only the person who decoded this map may actually dig up the treasure. + } + */ + else if (m_Decoder != from && !HasRequiredSkill(from)) + { + from.SendLocalizedMessage( + 503031 + ); // You did not decode this map and have no clue where to look for the treasure. + } + else if (!from.CanBeginAction()) + { + from.SendLocalizedMessage(503020); // You are already digging treasure. + } + else if (from.Map != m_Map) + { + from.SendLocalizedMessage(1010479); // You seem to be in the right place, but may be on the wrong facet! + } + else + { + from.SendLocalizedMessage(503033); // Where do you wish to dig? + from.Target = new DigTarget(this); + } + } + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return; + } + + if (!m_Completed && m_Decoder == null) + Decode(from); + else + DisplayTo(from); + } + + private bool CheckYoung(Mobile from) + { + if (from.AccessLevel >= AccessLevel.GameMaster) + return true; + + if (from is PlayerMobile mobile && mobile.Young) + return true; + + if (from == Decoder) + { + Level = 1; + from.SendLocalizedMessage(1046446); // This is now a level one treasure map. + return true; + } + + return false; + } + + private double GetMinSkillLevel() + { + return m_Level switch + { + 1 => -3.0, + 2 => 41.0, + 3 => 51.0, + 4 => 61.0, + 5 => 70.0, + 6 => 70.0, + _ => 0.0 + }; + } + + private bool HasRequiredSkill(Mobile from) => from.Skills.Cartography.Value >= GetMinSkillLevel(); + + public void Decode(Mobile from) + { + if (m_Completed || m_Decoder != null) + return; + + if (m_Level == 0) + { + if (!CheckYoung(from)) + { + from.SendLocalizedMessage(1046447); // Only a young player may use this treasure map. + return; + } + } + else + { + var minSkill = GetMinSkillLevel(); + + if (from.Skills.Cartography.Value < minSkill) + from.SendLocalizedMessage(503013); // The map is too difficult to attempt to decode. + + var maxSkill = minSkill + 60.0; + + if (!from.CheckSkill(SkillName.Cartography, minSkill, maxSkill)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 503018); // You fail to make anything of the map. + return; + } + } + + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 503019); // You successfully decode a treasure map! + Decoder = from; + + if (Core.AOS) + LootType = LootType.Blessed; + + DisplayTo(from); + } + + public override void DisplayTo(Mobile from) + { + if (m_Completed) + { + SendLocalizedMessageTo(from, 503014); // This treasure hunt has already been completed. + } + else if (m_Level == 0 && !CheckYoung(from)) + { + from.SendLocalizedMessage(1046447); // Only a young player may use this treasure map. + return; + } + else if (m_Decoder != from && !HasRequiredSkill(from)) + { + from.SendLocalizedMessage( + 503031 + ); // You did not decode this map and have no clue where to look for the treasure. + return; + } + else + { + SendLocalizedMessageTo( + from, + 503017 + ); // The treasure is marked by the red pin. Grab a shovel and go dig it up! + } + + from.PlaySound(0x249); + base.DisplayTo(from); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (!m_Completed) + { + if (m_Decoder == null) + { + list.Add(new DecodeMapEntry(this)); + } + else + { + var digTool = HasDiggingTool(from); + + list.Add(new OpenMapEntry(this)); + list.Add(new DigEntry(this, digTool)); + } + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(m_Map == Map.Felucca ? 1041502 : 1041503); // for somewhere in Felucca : for somewhere in Trammel + + if (m_Completed) + list.Add(1041507, m_CompletedBy == null ? "someone" : m_CompletedBy.Name); // completed by ~1_val~ + } + + public override void OnSingleClick(Mobile from) + { + if (m_Completed) + { + from.Send( + new MessageLocalizedAffix( + Serial, + ItemID, + MessageType.Label, + 0x3B2, + 3, + 1048030, + "", + AffixType.Append, + $" completed by {(m_CompletedBy == null ? "someone" : m_CompletedBy.Name)}", + "" + ) + ); + } + else if (m_Decoder != null) + { + if (m_Level == 6) + LabelTo(from, 1063453); + else + LabelTo(from, 1041516 + m_Level); + } + else + { + if (m_Level == 6) + LabelTo(from, 1041522, $"#{1063452}\t \t#{(m_Map == Map.Felucca ? 1041502 : 1041503)}"); + else + LabelTo(from, 1041522, $"#{1041510 + m_Level}\t \t#{(m_Map == Map.Felucca ? 1041502 : 1041503)}"); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + + writer.Write(m_CompletedBy); + + writer.Write(m_Level); + writer.Write(m_Completed); + writer.Write(m_Decoder); + writer.Write(m_Map); + writer.Write(ChestLocation); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_CompletedBy = reader.ReadMobile(); + + goto case 0; + } + case 0: + { + m_Level = reader.ReadInt(); + m_Completed = reader.ReadBool(); + m_Decoder = reader.ReadMobile(); + m_Map = reader.ReadMap(); + ChestLocation = reader.ReadPoint2D(); + + if (version == 0 && m_Completed) + m_CompletedBy = m_Decoder; + + break; + } + } + + if (Core.AOS && m_Decoder != null && LootType == LootType.Regular) + LootType = LootType.Blessed; + } + + private class DigTarget : Target + { + private readonly TreasureMap m_Map; + + public DigTarget(TreasureMap map) : base(6, true, TargetFlags.None) => m_Map = map; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Map.Deleted) + return; + + var map = m_Map.m_Map; + + if (m_Map.m_Completed) + { + from.SendLocalizedMessage(503028); // The treasure for this map has already been found. + } + /* + else if (from != m_Map.m_Decoder) + { + from.SendLocalizedMessage( 503016 ); // Only the person who decoded this map may actually dig up the treasure. + } + */ + else if (m_Map.m_Decoder != from && !m_Map.HasRequiredSkill(from)) + { + from.SendLocalizedMessage( + 503031 + ); // You did not decode this map and have no clue where to look for the treasure. + } + else if (!from.CanBeginAction()) + { + from.SendLocalizedMessage(503020); // You are already digging treasure. + } + else if (!HasDiggingTool(from)) + { + from.SendMessage("You must have a digging tool to dig for treasure."); + } + else if (from.Map != map) + { + from.SendLocalizedMessage(1010479); // You seem to be in the right place, but may be on the wrong facet! + } + else + { + var p = targeted as IPoint3D; + + var targ3D = (p as Item)?.GetWorldLocation() ?? new Point3D(p); + + int maxRange; + var skillValue = from.Skills.Mining.Value; + + if (skillValue >= 100.0) + maxRange = 4; + else if (skillValue >= 81.0) + maxRange = 3; + else if (skillValue >= 51.0) + maxRange = 2; + else + maxRange = 1; + + var loc = m_Map.ChestLocation; + int x = loc.X, y = loc.Y; + + var chest3D0 = new Point3D(loc, 0); + + if (Utility.InRange(targ3D, chest3D0, maxRange)) + { + if (from.Location.X == x && from.Location.Y == y) + { + from.SendLocalizedMessage( + 503030 + ); // The chest can't be dug up because you are standing on top of it. + } + else if (map != null) + { + var z = map.GetAverageZ(x, y); + + if (!map.CanFit(x, y, z, 16, true)) + from.SendLocalizedMessage( + 503021 + ); // You have found the treasure chest but something is keeping it from being dug up. + else if (from.BeginAction()) + new DigTimer(from, m_Map, new Point3D(x, y, z), map).Start(); + else + from.SendLocalizedMessage(503020); // You are already digging treasure. + } + } + else if (m_Map.Level > 0) + { + if (Utility.InRange(targ3D, chest3D0, 8)) // We're close, but not quite + from.SendLocalizedMessage(503032); // You dig and dig but no treasure seems to be here. + else + from.SendLocalizedMessage(503035); // You dig and dig but fail to find any treasure. + } + else + { + if (Utility.InRange(targ3D, chest3D0, 8)) // We're close, but not quite + { + from.SendAsciiMessage(0x44, "The treasure chest is very close!"); + } + else + { + var dir = Utility.GetDirection(targ3D, chest3D0); + + var sDir = dir switch + { + Direction.North => "north", + Direction.Right => "northeast", + Direction.East => "east", + Direction.Down => "southeast", + Direction.South => "south", + Direction.Left => "southwest", + Direction.West => "west", + _ => "northwest" + }; + + from.SendAsciiMessage(0x44, "Try looking for the treasure chest more to the {0}.", sDir); + } + } + } + } + } + + private class DigTimer : Timer + { + private readonly Mobile m_From; + private readonly long m_LastMoveTime; + private readonly Map m_Map; + private readonly long m_NextActionTime; + + private readonly long m_NextSkillTime; + private readonly long m_NextSpellTime; + private readonly TreasureMap m_TreasureMap; + private TreasureMapChest m_Chest; + + private int m_Count; + + private TreasureChestDirt m_Dirt1; + private TreasureChestDirt m_Dirt2; + + private Point3D m_Location; + + public DigTimer(Mobile from, TreasureMap treasureMap, Point3D location, Map map) : base( + TimeSpan.Zero, + TimeSpan.FromSeconds(1.0) + ) + { + m_From = from; + m_TreasureMap = treasureMap; + + m_Location = location; + m_Map = map; + + m_NextSkillTime = from.NextSkillTime; + m_NextSpellTime = from.NextSpellTime; + m_NextActionTime = from.NextActionTime; + m_LastMoveTime = from.LastMoveTime; + + Priority = TimerPriority.TenMS; + } + + private void Terminate() + { + Stop(); + m_From.EndAction(); + + m_Chest?.Delete(); + + if (m_Dirt1 != null) + { + m_Dirt1.Delete(); + m_Dirt2.Delete(); + } + } + + protected override void OnTick() + { + if (m_NextSkillTime != m_From.NextSkillTime || m_NextSpellTime != m_From.NextSpellTime || + m_NextActionTime != m_From.NextActionTime) + { + Terminate(); + return; + } + + if (m_LastMoveTime != m_From.LastMoveTime) + { + m_From.SendLocalizedMessage( + 503023 + ); // You cannot move around while digging up treasure. You will need to start digging anew. + Terminate(); + return; + } + + var z = m_Chest != null ? m_Chest.Z + m_Chest.ItemData.Height : int.MinValue; + var height = 16; + + if (z > m_Location.Z) + height -= z - m_Location.Z; + else + z = m_Location.Z; + + if (!m_Map.CanFit(m_Location.X, m_Location.Y, z, height, true, true, false)) + { + m_From.SendLocalizedMessage( + 503024 + ); // You stop digging because something is directly on top of the treasure chest. + Terminate(); + return; + } + + m_Count++; + + m_From.RevealingAction(); + m_From.Direction = m_From.GetDirectionTo(m_Location); + + if (m_Count > 1 && m_Dirt1 == null) + { + m_Dirt1 = new TreasureChestDirt(); + m_Dirt1.MoveToWorld(m_Location, m_Map); + + m_Dirt2 = new TreasureChestDirt(); + m_Dirt2.MoveToWorld(new Point3D(m_Location.X, m_Location.Y - 1, m_Location.Z), m_Map); + } + + if (m_Count == 5) + { + m_Dirt1.Turn1(); + } + else if (m_Count == 10) + { + m_Dirt1.Turn2(); + m_Dirt2.Turn2(); + } + else if (m_Count > 10) + { + if (m_Chest == null) + { + m_Chest = new TreasureMapChest(m_From, m_TreasureMap.Level, true); + m_Chest.MoveToWorld(new Point3D(m_Location.X, m_Location.Y, m_Location.Z - 15), m_Map); + } + else + { + m_Chest.Z++; + } + + Effects.PlaySound(m_Chest, m_Map, 0x33B); + } + + if (m_Chest?.Location.Z >= m_Location.Z) + { + Stop(); + m_From.EndAction(); + + m_Chest.Temporary = false; + m_TreasureMap.Completed = true; + m_TreasureMap.CompletedBy = m_From; + + var spawns = m_TreasureMap.Level switch + { + 0 => 3, + 1 => 0, + _ => 4 + }; + + for (var i = 0; i < spawns; ++i) + { + var bc = Spawn(m_TreasureMap.Level, m_Chest.Location, m_Chest.Map, null, true); + + if (bc != null) + m_Chest.Guardians.Add(bc); + } + } + else + { + if (m_From.Body.IsHuman && !m_From.Mounted) + m_From.Animate(11, 5, 1, true, false, 0); + + new SoundTimer(m_From, 0x125 + m_Count % 2).Start(); + } + } + + private class SoundTimer : Timer + { + private readonly Mobile m_From; + private readonly int m_SoundID; + + public SoundTimer(Mobile from, int soundID) : base(TimeSpan.FromSeconds(0.9)) + { + m_From = from; + m_SoundID = soundID; + + Priority = TimerPriority.TenMS; + } + + protected override void OnTick() + { + m_From.PlaySound(m_SoundID); + } + } + } + + private class DecodeMapEntry : ContextMenuEntry + { + private readonly TreasureMap m_Map; + + public DecodeMapEntry(TreasureMap map) : base(6147, 2) => m_Map = map; + + public override void OnClick() + { + if (!m_Map.Deleted) + m_Map.Decode(Owner.From); + } + } + + private class OpenMapEntry : ContextMenuEntry + { + private readonly TreasureMap m_Map; + + public OpenMapEntry(TreasureMap map) : base(6150, 2) => m_Map = map; + + public override void OnClick() + { + if (!m_Map.Deleted) + m_Map.DisplayTo(Owner.From); + } + } + + private class DigEntry : ContextMenuEntry + { + private readonly TreasureMap m_Map; + + public DigEntry(TreasureMap map, bool enabled) : base(6148, 2) + { + m_Map = map; + + if (!enabled) + Flags |= CMEFlags.Disabled; + } + + public override void OnClick() + { + if (m_Map.Deleted) + return; + + var from = Owner.From; + + if (HasDiggingTool(from)) + m_Map.OnBeginDig(from); + else + from.SendMessage("You must have a digging tool to dig for treasure."); + } + } + } + + public class TreasureChestDirt : Item + { + public TreasureChestDirt() : base(0x912) + { + Movable = false; + + Timer.DelayCall(TimeSpan.FromMinutes(2.0), Delete); + } + + public TreasureChestDirt(Serial serial) : base(serial) + { + } + + public void Turn1() + { + ItemID = 0x913; + } + + public void Turn2() + { + ItemID = 0x914; + } + + 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(); + + Delete(); + } + } +} diff --git a/Projects/UOContent/Items/Maps/WorldMap.cs b/Projects/UOContent/Items/Maps/WorldMap.cs index 82ee2d7c5..0eff29b64 100644 --- a/Projects/UOContent/Items/Maps/WorldMap.cs +++ b/Projects/UOContent/Items/Maps/WorldMap.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - public class WorldMap : MapItem - { - [Constructible] - public WorldMap() - { - SetDisplay(0, 0, 5119, 4095, 400, 400); - } - - public WorldMap(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1015233; // world map - - public override void CraftInit(Mobile from) - { - // Unlike the others, world map is not based on crafted location - - double skillValue = from.Skills.Cartography.Value; - int x20 = (int)(skillValue * 20); - int size = 25 + (int)(skillValue * 6.6); - - if (size < 200) - size = 200; - else if (size > 400) - size = 400; - - SetDisplay(1344 - x20, 1600 - x20, 1472 + x20, 1728 + x20, size, size); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class WorldMap : MapItem + { + [Constructible] + public WorldMap() + { + SetDisplay(0, 0, 5119, 4095, 400, 400); + } + + public WorldMap(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1015233; // world map + + public override void CraftInit(Mobile from) + { + // Unlike the others, world map is not based on crafted location + + var skillValue = from.Skills.Cartography.Value; + var x20 = (int)(skillValue * 20); + var size = 25 + (int)(skillValue * 6.6); + + if (size < 200) + size = 200; + else if (size > 400) + size = 400; + + SetDisplay(1344 - x20, 1600 - x20, 1472 + x20, 1728 + x20, size, size); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/AdmiralsHeartyRum.cs b/Projects/UOContent/Items/Minor Artifacts/AdmiralsHeartyRum.cs index ab744b7f2..bd655f5cf 100644 --- a/Projects/UOContent/Items/Minor Artifacts/AdmiralsHeartyRum.cs +++ b/Projects/UOContent/Items/Minor Artifacts/AdmiralsHeartyRum.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class AdmiralsHeartyRum : BeverageBottle - { - [Constructible] - public AdmiralsHeartyRum() : base(BeverageType.Ale) => Hue = 0x66C; - - public AdmiralsHeartyRum(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1063477; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AdmiralsHeartyRum : BeverageBottle + { + [Constructible] + public AdmiralsHeartyRum() : base(BeverageType.Ale) => Hue = 0x66C; + + public AdmiralsHeartyRum(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1063477; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/AlchemistsBauble.cs b/Projects/UOContent/Items/Minor Artifacts/AlchemistsBauble.cs index 2d0b2ca87..b65f714c5 100644 --- a/Projects/UOContent/Items/Minor Artifacts/AlchemistsBauble.cs +++ b/Projects/UOContent/Items/Minor Artifacts/AlchemistsBauble.cs @@ -1,35 +1,35 @@ -namespace Server.Items -{ - public class AlchemistsBauble : GoldBracelet - { - [Constructible] - public AlchemistsBauble() - { - Hue = 0x290; - SkillBonuses.SetValues(0, SkillName.Magery, 10.0); - Attributes.EnhancePotions = 30; - Attributes.LowerRegCost = 20; - Resistances.Poison = 10; - } - - public AlchemistsBauble(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070638; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AlchemistsBauble : GoldBracelet + { + [Constructible] + public AlchemistsBauble() + { + Hue = 0x290; + SkillBonuses.SetValues(0, SkillName.Magery, 10.0); + Attributes.EnhancePotions = 30; + Attributes.LowerRegCost = 20; + Resistances.Poison = 10; + } + + public AlchemistsBauble(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070638; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ArcticDeathDealer.cs b/Projects/UOContent/Items/Minor Artifacts/ArcticDeathDealer.cs index be60b47ec..5bf5dc2bc 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ArcticDeathDealer.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ArcticDeathDealer.cs @@ -1,48 +1,50 @@ -namespace Server.Items -{ - public class ArcticDeathDealer : WarMace - { - [Constructible] - public ArcticDeathDealer() - { - Hue = 0x480; - WeaponAttributes.HitHarm = 33; - WeaponAttributes.HitLowerAttack = 40; - Attributes.WeaponSpeed = 20; - Attributes.WeaponDamage = 40; - WeaponAttributes.ResistColdBonus = 10; - } - - public ArcticDeathDealer(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1063481; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - cold = 50; - phys = 50; - - pois = fire = nrgy = chaos = direct = 0; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ArcticDeathDealer : WarMace + { + [Constructible] + public ArcticDeathDealer() + { + Hue = 0x480; + WeaponAttributes.HitHarm = 33; + WeaponAttributes.HitLowerAttack = 40; + Attributes.WeaponSpeed = 20; + Attributes.WeaponDamage = 40; + WeaponAttributes.ResistColdBonus = 10; + } + + public ArcticDeathDealer(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1063481; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + cold = 50; + phys = 50; + + pois = fire = nrgy = chaos = direct = 0; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/BlazeOfDeath.cs b/Projects/UOContent/Items/Minor Artifacts/BlazeOfDeath.cs index 83e305b03..0b7cffdd1 100644 --- a/Projects/UOContent/Items/Minor Artifacts/BlazeOfDeath.cs +++ b/Projects/UOContent/Items/Minor Artifacts/BlazeOfDeath.cs @@ -1,49 +1,51 @@ -namespace Server.Items -{ - public class BlazeOfDeath : Halberd - { - [Constructible] - public BlazeOfDeath() - { - Hue = 0x501; - WeaponAttributes.HitFireArea = 50; - WeaponAttributes.HitFireball = 50; - Attributes.WeaponSpeed = 25; - Attributes.WeaponDamage = 35; - WeaponAttributes.ResistFireBonus = 10; - WeaponAttributes.LowerStatReq = 100; - } - - public BlazeOfDeath(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1063486; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - fire = 50; - phys = 50; - - cold = pois = nrgy = chaos = direct = 0; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class BlazeOfDeath : Halberd + { + [Constructible] + public BlazeOfDeath() + { + Hue = 0x501; + WeaponAttributes.HitFireArea = 50; + WeaponAttributes.HitFireball = 50; + Attributes.WeaponSpeed = 25; + Attributes.WeaponDamage = 35; + WeaponAttributes.ResistFireBonus = 10; + WeaponAttributes.LowerStatReq = 100; + } + + public BlazeOfDeath(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1063486; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + fire = 50; + phys = 50; + + cold = pois = nrgy = chaos = direct = 0; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/BowOfTheJukaKing.cs b/Projects/UOContent/Items/Minor Artifacts/BowOfTheJukaKing.cs index 2166f3c15..f48fe44af 100644 --- a/Projects/UOContent/Items/Minor Artifacts/BowOfTheJukaKing.cs +++ b/Projects/UOContent/Items/Minor Artifacts/BowOfTheJukaKing.cs @@ -1,38 +1,38 @@ -namespace Server.Items -{ - public class BowOfTheJukaKing : Bow - { - [Constructible] - public BowOfTheJukaKing() - { - Hue = 0x460; - WeaponAttributes.HitMagicArrow = 25; - Slayer = SlayerName.ReptilianDeath; - Attributes.AttackChance = 15; - Attributes.WeaponDamage = 40; - } - - public BowOfTheJukaKing(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070636; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class BowOfTheJukaKing : Bow + { + [Constructible] + public BowOfTheJukaKing() + { + Hue = 0x460; + WeaponAttributes.HitMagicArrow = 25; + Slayer = SlayerName.ReptilianDeath; + Attributes.AttackChance = 15; + Attributes.WeaponDamage = 40; + } + + public BowOfTheJukaKing(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070636; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/BurglarsBandana.cs b/Projects/UOContent/Items/Minor Artifacts/BurglarsBandana.cs index e0f47c54e..b754369d2 100644 --- a/Projects/UOContent/Items/Minor Artifacts/BurglarsBandana.cs +++ b/Projects/UOContent/Items/Minor Artifacts/BurglarsBandana.cs @@ -1,55 +1,55 @@ -namespace Server.Items -{ - public class BurglarsBandana : Bandana - { - [Constructible] - public BurglarsBandana() - { - Hue = Utility.RandomBool() ? 0x58C : 0x10; - - SkillBonuses.SetValues(0, SkillName.Stealing, 10.0); - SkillBonuses.SetValues(1, SkillName.Stealth, 10.0); - SkillBonuses.SetValues(2, SkillName.Snooping, 10.0); - - Attributes.BonusDex = 5; - } - - public BurglarsBandana(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1063473; - - public override int BasePhysicalResistance => 10; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 7; - public override int BasePoisonResistance => 10; - public override int BaseEnergyResistance => 10; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(2); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 2) - { - Resistances.Physical = 0; - Resistances.Fire = 0; - Resistances.Cold = 0; - Resistances.Poison = 0; - Resistances.Energy = 0; - } - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class BurglarsBandana : Bandana + { + [Constructible] + public BurglarsBandana() + { + Hue = Utility.RandomBool() ? 0x58C : 0x10; + + SkillBonuses.SetValues(0, SkillName.Stealing, 10.0); + SkillBonuses.SetValues(1, SkillName.Stealth, 10.0); + SkillBonuses.SetValues(2, SkillName.Snooping, 10.0); + + Attributes.BonusDex = 5; + } + + public BurglarsBandana(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1063473; + + public override int BasePhysicalResistance => 10; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 7; + public override int BasePoisonResistance => 10; + public override int BaseEnergyResistance => 10; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(2); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version < 2) + { + Resistances.Physical = 0; + Resistances.Fire = 0; + Resistances.Cold = 0; + Resistances.Poison = 0; + Resistances.Energy = 0; + } + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/CandelabraOfSouls.cs b/Projects/UOContent/Items/Minor Artifacts/CandelabraOfSouls.cs index 453306ff0..89732edb8 100644 --- a/Projects/UOContent/Items/Minor Artifacts/CandelabraOfSouls.cs +++ b/Projects/UOContent/Items/Minor Artifacts/CandelabraOfSouls.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class CandelabraOfSouls : Item - { - [Constructible] - public CandelabraOfSouls() : base(0xB26) - { - } - - public CandelabraOfSouls(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1063478; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class CandelabraOfSouls : Item + { + [Constructible] + public CandelabraOfSouls() : base(0xB26) + { + } + + public CandelabraOfSouls(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1063478; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/CaptainQuacklebushsCutlass.cs b/Projects/UOContent/Items/Minor Artifacts/CaptainQuacklebushsCutlass.cs index 01fd177c3..d1179d14f 100644 --- a/Projects/UOContent/Items/Minor Artifacts/CaptainQuacklebushsCutlass.cs +++ b/Projects/UOContent/Items/Minor Artifacts/CaptainQuacklebushsCutlass.cs @@ -1,42 +1,42 @@ -namespace Server.Items -{ - public class CaptainQuacklebushsCutlass : Cutlass - { - [Constructible] - public CaptainQuacklebushsCutlass() - { - Hue = 0x66C; - Attributes.BonusDex = 5; - Attributes.AttackChance = 10; - Attributes.WeaponSpeed = 20; - Attributes.WeaponDamage = 50; - WeaponAttributes.UseBestSkill = 1; - } - - public CaptainQuacklebushsCutlass(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1063474; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Attributes.AttackChance == 50) - Attributes.AttackChance = 10; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class CaptainQuacklebushsCutlass : Cutlass + { + [Constructible] + public CaptainQuacklebushsCutlass() + { + Hue = 0x66C; + Attributes.BonusDex = 5; + Attributes.AttackChance = 10; + Attributes.WeaponSpeed = 20; + Attributes.WeaponDamage = 50; + WeaponAttributes.UseBestSkill = 1; + } + + public CaptainQuacklebushsCutlass(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1063474; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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 (Attributes.AttackChance == 50) + Attributes.AttackChance = 10; + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/CavortingClub.cs b/Projects/UOContent/Items/Minor Artifacts/CavortingClub.cs index 0e4867f70..eee50049c 100644 --- a/Projects/UOContent/Items/Minor Artifacts/CavortingClub.cs +++ b/Projects/UOContent/Items/Minor Artifacts/CavortingClub.cs @@ -1,41 +1,41 @@ -namespace Server.Items -{ - public class CavortingClub : Club - { - [Constructible] - public CavortingClub() - { - Hue = 0x593; - WeaponAttributes.SelfRepair = 3; - Attributes.WeaponSpeed = 25; - Attributes.WeaponDamage = 35; - WeaponAttributes.ResistFireBonus = 8; - WeaponAttributes.ResistColdBonus = 8; - WeaponAttributes.ResistPoisonBonus = 8; - WeaponAttributes.ResistEnergyBonus = 8; - } - - public CavortingClub(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1063472; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class CavortingClub : Club + { + [Constructible] + public CavortingClub() + { + Hue = 0x593; + WeaponAttributes.SelfRepair = 3; + Attributes.WeaponSpeed = 25; + Attributes.WeaponDamage = 35; + WeaponAttributes.ResistFireBonus = 8; + WeaponAttributes.ResistColdBonus = 8; + WeaponAttributes.ResistPoisonBonus = 8; + WeaponAttributes.ResistEnergyBonus = 8; + } + + public CavortingClub(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1063472; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ColdBlood.cs b/Projects/UOContent/Items/Minor Artifacts/ColdBlood.cs index 526481f7a..113f73d84 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ColdBlood.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ColdBlood.cs @@ -1,48 +1,50 @@ -namespace Server.Items -{ - public class ColdBlood : Cleaver - { - [Constructible] - public ColdBlood() - { - Hue = 0x4F2; - - Attributes.WeaponSpeed = 40; - - Attributes.BonusHits = 6; - Attributes.BonusStam = 6; - Attributes.BonusMana = 6; - } - - public ColdBlood(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070818; // Cold Blood - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - cold = 100; - - fire = phys = pois = nrgy = chaos = direct = 0; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ColdBlood : Cleaver + { + [Constructible] + public ColdBlood() + { + Hue = 0x4F2; + + Attributes.WeaponSpeed = 40; + + Attributes.BonusHits = 6; + Attributes.BonusStam = 6; + Attributes.BonusMana = 6; + } + + public ColdBlood(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070818; // Cold Blood + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + cold = 100; + + fire = phys = pois = nrgy = chaos = direct = 0; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/DreadPirateHat.cs b/Projects/UOContent/Items/Minor Artifacts/DreadPirateHat.cs index 1ab13cd53..14e74279c 100644 --- a/Projects/UOContent/Items/Minor Artifacts/DreadPirateHat.cs +++ b/Projects/UOContent/Items/Minor Artifacts/DreadPirateHat.cs @@ -1,58 +1,58 @@ -namespace Server.Items -{ - public class DreadPirateHat : TricorneHat - { - [Constructible] - public DreadPirateHat() - { - Hue = 0x497; - - SkillBonuses.SetValues(0, Utility.RandomCombatSkill(), 10.0); - - Attributes.BonusDex = 8; - Attributes.AttackChance = 10; - Attributes.NightSight = 1; - } - - public DreadPirateHat(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1063467; - - public override int BaseColdResistance => 14; - public override int BasePoisonResistance => 10; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(3); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 3) - { - Resistances.Cold = 0; - Resistances.Poison = 0; - } - - if (version < 1) - { - Attributes.Luck = 0; - Attributes.AttackChance = 10; - Attributes.NightSight = 1; - SkillBonuses.SetValues(0, Utility.RandomCombatSkill(), 10.0); - SkillBonuses.SetBonus(1, 0); - } - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class DreadPirateHat : TricorneHat + { + [Constructible] + public DreadPirateHat() + { + Hue = 0x497; + + SkillBonuses.SetValues(0, Utility.RandomCombatSkill(), 10.0); + + Attributes.BonusDex = 8; + Attributes.AttackChance = 10; + Attributes.NightSight = 1; + } + + public DreadPirateHat(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1063467; + + public override int BaseColdResistance => 14; + public override int BasePoisonResistance => 10; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(3); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version < 3) + { + Resistances.Cold = 0; + Resistances.Poison = 0; + } + + if (version < 1) + { + Attributes.Luck = 0; + Attributes.AttackChance = 10; + Attributes.NightSight = 1; + SkillBonuses.SetValues(0, Utility.RandomCombatSkill(), 10.0); + SkillBonuses.SetBonus(1, 0); + } + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/EnchantedTitanLegBone.cs b/Projects/UOContent/Items/Minor Artifacts/EnchantedTitanLegBone.cs index eed346a92..36da7685b 100644 --- a/Projects/UOContent/Items/Minor Artifacts/EnchantedTitanLegBone.cs +++ b/Projects/UOContent/Items/Minor Artifacts/EnchantedTitanLegBone.cs @@ -1,39 +1,39 @@ -namespace Server.Items -{ - public class EnchantedTitanLegBone : ShortSpear - { - [Constructible] - public EnchantedTitanLegBone() - { - Hue = 0x8A5; - WeaponAttributes.HitLowerDefend = 40; - WeaponAttributes.HitLightning = 40; - Attributes.AttackChance = 10; - Attributes.WeaponDamage = 20; - WeaponAttributes.ResistPhysicalBonus = 10; - } - - public EnchantedTitanLegBone(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1063482; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class EnchantedTitanLegBone : ShortSpear + { + [Constructible] + public EnchantedTitanLegBone() + { + Hue = 0x8A5; + WeaponAttributes.HitLowerDefend = 40; + WeaponAttributes.HitLightning = 40; + Attributes.AttackChance = 10; + Attributes.WeaponDamage = 20; + WeaponAttributes.ResistPhysicalBonus = 10; + } + + public EnchantedTitanLegBone(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1063482; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/GhostShipAnchor.cs b/Projects/UOContent/Items/Minor Artifacts/GhostShipAnchor.cs index f00df924a..b912778d8 100644 --- a/Projects/UOContent/Items/Minor Artifacts/GhostShipAnchor.cs +++ b/Projects/UOContent/Items/Minor Artifacts/GhostShipAnchor.cs @@ -1,31 +1,31 @@ -namespace Server.Items -{ - public class GhostShipAnchor : Item - { - [Constructible] - public GhostShipAnchor() : base(0x14F7) => Hue = 0x47E; - - public GhostShipAnchor(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070816; // Ghost Ship Anchor - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (ItemID == 0x1F47) - ItemID = 0x14F7; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class GhostShipAnchor : Item + { + [Constructible] + public GhostShipAnchor() : base(0x14F7) => Hue = 0x47E; + + public GhostShipAnchor(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070816; // Ghost Ship Anchor + + 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 (ItemID == 0x1F47) + ItemID = 0x14F7; + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/GlovesOfThePugilist.cs b/Projects/UOContent/Items/Minor Artifacts/GlovesOfThePugilist.cs index 5427df4c3..99f3e22f2 100644 --- a/Projects/UOContent/Items/Minor Artifacts/GlovesOfThePugilist.cs +++ b/Projects/UOContent/Items/Minor Artifacts/GlovesOfThePugilist.cs @@ -1,39 +1,39 @@ -namespace Server.Items -{ - public class GlovesOfThePugilist : LeatherGloves - { - [Constructible] - public GlovesOfThePugilist() - { - Hue = 0x6D1; - SkillBonuses.SetValues(0, SkillName.Wrestling, 10.0); - Attributes.BonusDex = 8; - Attributes.WeaponDamage = 15; - } - - public GlovesOfThePugilist(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070690; - - public override int BasePhysicalResistance => 18; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class GlovesOfThePugilist : LeatherGloves + { + [Constructible] + public GlovesOfThePugilist() + { + Hue = 0x6D1; + SkillBonuses.SetValues(0, SkillName.Wrestling, 10.0); + Attributes.BonusDex = 8; + Attributes.WeaponDamage = 15; + } + + public GlovesOfThePugilist(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070690; + + public override int BasePhysicalResistance => 18; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/GoldBricks.cs b/Projects/UOContent/Items/Minor Artifacts/GoldBricks.cs index 78e116c56..75efb7ace 100644 --- a/Projects/UOContent/Items/Minor Artifacts/GoldBricks.cs +++ b/Projects/UOContent/Items/Minor Artifacts/GoldBricks.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class GoldBricks : Item - { - [Constructible] - public GoldBricks() : base(0x1BEB) - { - } - - public GoldBricks(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1063489; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class GoldBricks : Item + { + [Constructible] + public GoldBricks() : base(0x1BEB) + { + } + + public GoldBricks(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1063489; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/GwennosHarp.cs b/Projects/UOContent/Items/Minor Artifacts/GwennosHarp.cs index 78ed526c1..5dd48e3bb 100644 --- a/Projects/UOContent/Items/Minor Artifacts/GwennosHarp.cs +++ b/Projects/UOContent/Items/Minor Artifacts/GwennosHarp.cs @@ -1,36 +1,36 @@ -namespace Server.Items -{ - public class GwennosHarp : LapHarp - { - [Constructible] - public GwennosHarp() - { - Hue = 0x47E; - Slayer = SlayerName.Repond; - Slayer2 = SlayerName.ReptilianDeath; - } - - public GwennosHarp(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1063480; - - public override int InitMinUses => 1600; - public override int InitMaxUses => 1600; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class GwennosHarp : LapHarp + { + [Constructible] + public GwennosHarp() + { + Hue = 0x47E; + Slayer = SlayerName.Repond; + Slayer2 = SlayerName.ReptilianDeath; + } + + public GwennosHarp(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1063480; + + public override int InitMinUses => 1600; + public override int InitMaxUses => 1600; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/HeartOfTheLion.cs b/Projects/UOContent/Items/Minor Artifacts/HeartOfTheLion.cs index 70dfd82e9..881567035 100644 --- a/Projects/UOContent/Items/Minor Artifacts/HeartOfTheLion.cs +++ b/Projects/UOContent/Items/Minor Artifacts/HeartOfTheLion.cs @@ -1,44 +1,44 @@ -namespace Server.Items -{ - public class HeartOfTheLion : PlateChest - { - [Constructible] - public HeartOfTheLion() - { - Hue = 0x501; - Attributes.Luck = 95; - Attributes.DefendChance = 15; - ArmorAttributes.LowerStatReq = 100; - ArmorAttributes.MageArmor = 1; - } - - public HeartOfTheLion(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070817; // Heart of the Lion - - public override int BasePhysicalResistance => 15; - public override int BaseFireResistance => 10; - public override int BaseColdResistance => 10; - public override int BasePoisonResistance => 10; - public override int BaseEnergyResistance => 10; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class HeartOfTheLion : PlateChest + { + [Constructible] + public HeartOfTheLion() + { + Hue = 0x501; + Attributes.Luck = 95; + Attributes.DefendChance = 15; + ArmorAttributes.LowerStatReq = 100; + ArmorAttributes.MageArmor = 1; + } + + public HeartOfTheLion(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070817; // Heart of the Lion + + public override int BasePhysicalResistance => 15; + public override int BaseFireResistance => 10; + public override int BaseColdResistance => 10; + public override int BasePoisonResistance => 10; + public override int BaseEnergyResistance => 10; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/IolosLute.cs b/Projects/UOContent/Items/Minor Artifacts/IolosLute.cs index f2789a8ed..270522579 100644 --- a/Projects/UOContent/Items/Minor Artifacts/IolosLute.cs +++ b/Projects/UOContent/Items/Minor Artifacts/IolosLute.cs @@ -1,37 +1,37 @@ -namespace Server.Items -{ - public class IolosLute : Lute - { - [Constructible] - public IolosLute() - { - Hue = 0x47E; - Slayer = SlayerName.Silver; - // Slayer2 = SlayerName.DaemonDismissal; - Slayer2 = SlayerName.Exorcism; - } - - public IolosLute(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1063479; - - public override int InitMinUses => 1600; - public override int InitMaxUses => 1600; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class IolosLute : Lute + { + [Constructible] + public IolosLute() + { + Hue = 0x47E; + Slayer = SlayerName.Silver; + // Slayer2 = SlayerName.DaemonDismissal; + Slayer2 = SlayerName.Exorcism; + } + + public IolosLute(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1063479; + + public override int InitMinUses => 1600; + public override int InitMaxUses => 1600; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/LunaLance.cs b/Projects/UOContent/Items/Minor Artifacts/LunaLance.cs index ba6bdb45f..fa4f08e3c 100644 --- a/Projects/UOContent/Items/Minor Artifacts/LunaLance.cs +++ b/Projects/UOContent/Items/Minor Artifacts/LunaLance.cs @@ -1,39 +1,39 @@ -namespace Server.Items -{ - public class LunaLance : Lance - { - [Constructible] - public LunaLance() - { - Hue = 0x47E; - SkillBonuses.SetValues(0, SkillName.Chivalry, 10.0); - Attributes.BonusStr = 5; - Attributes.WeaponSpeed = 20; - Attributes.WeaponDamage = 35; - WeaponAttributes.UseBestSkill = 1; - } - - public LunaLance(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1063469; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LunaLance : Lance + { + [Constructible] + public LunaLance() + { + Hue = 0x47E; + SkillBonuses.SetValues(0, SkillName.Chivalry, 10.0); + Attributes.BonusStr = 5; + Attributes.WeaponSpeed = 20; + Attributes.WeaponDamage = 35; + WeaponAttributes.UseBestSkill = 1; + } + + public LunaLance(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1063469; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ML/AegisOfGrace.cs b/Projects/UOContent/Items/Minor Artifacts/ML/AegisOfGrace.cs index a11c01003..fae25eca5 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ML/AegisOfGrace.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ML/AegisOfGrace.cs @@ -1,49 +1,49 @@ -namespace Server.Items -{ - public class AegisOfGrace : DragonHelm - { - [Constructible] - public AegisOfGrace() - { - SkillBonuses.SetValues(0, SkillName.MagicResist, 10.0); - - Attributes.DefendChance = 20; - - ArmorAttributes.SelfRepair = 2; - } - - public AegisOfGrace(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075047; // Aegis of Grace - - public override int BasePhysicalResistance => 10; - public override int BaseFireResistance => 9; - public override int BaseColdResistance => 7; - public override int BasePoisonResistance => 7; - public override int BaseEnergyResistance => 15; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Dragon; - public override CraftResource DefaultResource => CraftResource.Iron; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override Race RequiredRace => Race.Elf; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AegisOfGrace : DragonHelm + { + [Constructible] + public AegisOfGrace() + { + SkillBonuses.SetValues(0, SkillName.MagicResist, 10.0); + + Attributes.DefendChance = 20; + + ArmorAttributes.SelfRepair = 2; + } + + public AegisOfGrace(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075047; // Aegis of Grace + + public override int BasePhysicalResistance => 10; + public override int BaseFireResistance => 9; + public override int BaseColdResistance => 7; + public override int BasePoisonResistance => 7; + public override int BaseEnergyResistance => 15; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Dragon; + public override CraftResource DefaultResource => CraftResource.Iron; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override Race RequiredRace => Race.Elf; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ML/BladeDance.cs b/Projects/UOContent/Items/Minor Artifacts/ML/BladeDance.cs index e950cc120..2770ca7a0 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ML/BladeDance.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ML/BladeDance.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class BladeDance : RuneBlade - { - [Constructible] - public BladeDance() - { - Hue = 0x66C; - - Attributes.BonusMana = 8; - Attributes.SpellChanneling = 1; - Attributes.WeaponDamage = 30; - WeaponAttributes.HitLeechMana = 20; - WeaponAttributes.UseBestSkill = 1; - } - - public BladeDance(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075033; // Blade Dance - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class BladeDance : RuneBlade + { + [Constructible] + public BladeDance() + { + Hue = 0x66C; + + Attributes.BonusMana = 8; + Attributes.SpellChanneling = 1; + Attributes.WeaponDamage = 30; + WeaponAttributes.HitLeechMana = 20; + WeaponAttributes.UseBestSkill = 1; + } + + public BladeDance(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075033; // Blade Dance + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ML/BloodwoodSpirit.cs b/Projects/UOContent/Items/Minor Artifacts/ML/BloodwoodSpirit.cs index ba82a5bfe..2c677446d 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ML/BloodwoodSpirit.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ML/BloodwoodSpirit.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - public class BloodwoodSpirit : BaseTalisman - { - [Constructible] - public BloodwoodSpirit() : base(0x2F5A) - { - Hue = 0x27; - MaxChargeTime = 1200; - - Removal = TalismanRemoval.Damage; - Blessed = GetRandomBlessed(); - Protection = GetRandomProtection(false); - - SkillBonuses.SetValues(0, SkillName.SpiritSpeak, 10.0); - SkillBonuses.SetValues(1, SkillName.Necromancy, 5.0); - } - - public BloodwoodSpirit(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075034; // Bloodwood Spirit - public override bool ForceShowName => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version == 0 && Protection?.IsEmpty != false) - Protection = GetRandomProtection(false); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class BloodwoodSpirit : BaseTalisman + { + [Constructible] + public BloodwoodSpirit() : base(0x2F5A) + { + Hue = 0x27; + MaxChargeTime = 1200; + + Removal = TalismanRemoval.Damage; + Blessed = GetRandomBlessed(); + Protection = GetRandomProtection(false); + + SkillBonuses.SetValues(0, SkillName.SpiritSpeak, 10.0); + SkillBonuses.SetValues(1, SkillName.Necromancy, 5.0); + } + + public BloodwoodSpirit(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075034; // Bloodwood Spirit + public override bool ForceShowName => true; + + 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 && Protection?.IsEmpty != false) + Protection = GetRandomProtection(false); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ML/Bonesmasher.cs b/Projects/UOContent/Items/Minor Artifacts/ML/Bonesmasher.cs index 10474b84b..d9af7a661 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ML/Bonesmasher.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ML/Bonesmasher.cs @@ -1,40 +1,40 @@ -namespace Server.Items -{ - public class Bonesmasher : DiamondMace - { - [Constructible] - public Bonesmasher() - { - ItemID = 0x2D30; - Hue = 0x482; - - SkillBonuses.SetValues(0, SkillName.Macing, 10.0); - - WeaponAttributes.HitLeechMana = 40; - WeaponAttributes.SelfRepair = 2; - } - - public Bonesmasher(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075030; // Bonesmasher - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Bonesmasher : DiamondMace + { + [Constructible] + public Bonesmasher() + { + ItemID = 0x2D30; + Hue = 0x482; + + SkillBonuses.SetValues(0, SkillName.Macing, 10.0); + + WeaponAttributes.HitLeechMana = 40; + WeaponAttributes.SelfRepair = 2; + } + + public Bonesmasher(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075030; // Bonesmasher + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ML/Boomstick.cs b/Projects/UOContent/Items/Minor Artifacts/ML/Boomstick.cs index cef4b0819..b119c6dcd 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ML/Boomstick.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ML/Boomstick.cs @@ -1,46 +1,48 @@ -namespace Server.Items -{ - public class Boomstick : WildStaff - { - [Constructible] - public Boomstick() - { - Hue = 0x25; - - Attributes.SpellChanneling = 1; - Attributes.RegenMana = 3; - Attributes.CastSpeed = 1; - Attributes.LowerRegCost = 20; - } - - public Boomstick(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075032; // Boomstick - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - phys = fire = cold = pois = nrgy = direct = 0; - chaos = 100; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Boomstick : WildStaff + { + [Constructible] + public Boomstick() + { + Hue = 0x25; + + Attributes.SpellChanneling = 1; + Attributes.RegenMana = 3; + Attributes.CastSpeed = 1; + Attributes.LowerRegCost = 20; + } + + public Boomstick(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075032; // Boomstick + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + phys = fire = cold = pois = nrgy = direct = 0; + chaos = 100; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ML/BrightsightLenses.cs b/Projects/UOContent/Items/Minor Artifacts/ML/BrightsightLenses.cs index 15c5fc842..1471e50ee 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ML/BrightsightLenses.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ML/BrightsightLenses.cs @@ -1,51 +1,51 @@ -namespace Server.Items -{ - public class BrightsightLenses : ElvenGlasses - { - [Constructible] - public BrightsightLenses() - { - Hue = 0x501; - - Attributes.NightSight = 1; - Attributes.RegenMana = 3; - - ArmorAttributes.SelfRepair = 3; - } - - public BrightsightLenses(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075039; // Brightsight Lenses - - public override int BasePhysicalResistance => 9; - public override int BaseFireResistance => 29; - public override int BaseColdResistance => 7; - public override int BasePoisonResistance => 8; - public override int BaseEnergyResistance => 7; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1) - { - WeaponAttributes.SelfRepair = 0; - ArmorAttributes.SelfRepair = 3; - } - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class BrightsightLenses : ElvenGlasses + { + [Constructible] + public BrightsightLenses() + { + Hue = 0x501; + + Attributes.NightSight = 1; + Attributes.RegenMana = 3; + + ArmorAttributes.SelfRepair = 3; + } + + public BrightsightLenses(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075039; // Brightsight Lenses + + public override int BasePhysicalResistance => 9; + public override int BaseFireResistance => 29; + public override int BaseColdResistance => 7; + public override int BasePoisonResistance => 8; + public override int BaseEnergyResistance => 7; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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 < 1) + { + WeaponAttributes.SelfRepair = 0; + ArmorAttributes.SelfRepair = 3; + } + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ML/FeyLeggings.cs b/Projects/UOContent/Items/Minor Artifacts/ML/FeyLeggings.cs index c9422cc71..16f78d7e7 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ML/FeyLeggings.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ML/FeyLeggings.cs @@ -1,45 +1,45 @@ -namespace Server.Items -{ - public class FeyLeggings : ChainLegs - { - [Constructible] - public FeyLeggings() - { - Attributes.BonusHits = 6; - Attributes.DefendChance = 20; - - ArmorAttributes.MageArmor = 1; - } - - public FeyLeggings(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075041; // Fey Leggings - - public override int BasePhysicalResistance => 12; - public override int BaseFireResistance => 8; - public override int BaseColdResistance => 7; - public override int BasePoisonResistance => 4; - public override int BaseEnergyResistance => 19; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override Race RequiredRace => Race.Elf; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FeyLeggings : ChainLegs + { + [Constructible] + public FeyLeggings() + { + Attributes.BonusHits = 6; + Attributes.DefendChance = 20; + + ArmorAttributes.MageArmor = 1; + } + + public FeyLeggings(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075041; // Fey Leggings + + public override int BasePhysicalResistance => 12; + public override int BaseFireResistance => 8; + public override int BaseColdResistance => 7; + public override int BasePoisonResistance => 4; + public override int BaseEnergyResistance => 19; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override Race RequiredRace => Race.Elf; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ML/FleshRipper.cs b/Projects/UOContent/Items/Minor Artifacts/ML/FleshRipper.cs index ca2fb2272..f501588b7 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ML/FleshRipper.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ML/FleshRipper.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - public class FleshRipper : AssassinSpike - { - [Constructible] - public FleshRipper() - { - Hue = 0x341; - - SkillBonuses.SetValues(0, SkillName.Anatomy, 10.0); - - Attributes.BonusStr = 5; - Attributes.AttackChance = 15; - Attributes.WeaponSpeed = 40; - - WeaponAttributes.UseBestSkill = 1; - // TODO: Mage Slayer - } - - public FleshRipper(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075045; // Flesh Ripper - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class FleshRipper : AssassinSpike + { + [Constructible] + public FleshRipper() + { + Hue = 0x341; + + SkillBonuses.SetValues(0, SkillName.Anatomy, 10.0); + + Attributes.BonusStr = 5; + Attributes.AttackChance = 15; + Attributes.WeaponSpeed = 40; + + WeaponAttributes.UseBestSkill = 1; + // TODO: Mage Slayer + } + + public FleshRipper(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075045; // Flesh Ripper + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ML/HelmOfSwiftness.cs b/Projects/UOContent/Items/Minor Artifacts/ML/HelmOfSwiftness.cs index 88ad1b8e3..4ebec7f8d 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ML/HelmOfSwiftness.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ML/HelmOfSwiftness.cs @@ -1,45 +1,45 @@ -namespace Server.Items -{ - public class HelmOfSwiftness : WingedHelm - { - [Constructible] - public HelmOfSwiftness() - { - Hue = 0x592; - - Attributes.BonusInt = 5; - Attributes.CastSpeed = 1; - Attributes.CastRecovery = 2; - ArmorAttributes.MageArmor = 1; - } - - public HelmOfSwiftness(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075037; // Helm of Swiftness - - public override int BasePhysicalResistance => 6; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 6; - public override int BasePoisonResistance => 6; - public override int BaseEnergyResistance => 8; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class HelmOfSwiftness : WingedHelm + { + [Constructible] + public HelmOfSwiftness() + { + Hue = 0x592; + + Attributes.BonusInt = 5; + Attributes.CastSpeed = 1; + Attributes.CastRecovery = 2; + ArmorAttributes.MageArmor = 1; + } + + public HelmOfSwiftness(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075037; // Helm of Swiftness + + public override int BasePhysicalResistance => 6; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 6; + public override int BasePoisonResistance => 6; + public override int BaseEnergyResistance => 8; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ML/MelisandesCorrodedHatchet.cs b/Projects/UOContent/Items/Minor Artifacts/ML/MelisandesCorrodedHatchet.cs index 11eb14b8e..bedd36d85 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ML/MelisandesCorrodedHatchet.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ML/MelisandesCorrodedHatchet.cs @@ -1,39 +1,39 @@ -namespace Server.Items -{ - public class MelisandesCorrodedHatchet : Hatchet - { - [Constructible] - public MelisandesCorrodedHatchet() - { - Hue = 0x494; - - SkillBonuses.SetValues(0, SkillName.Lumberjacking, 5.0); - - Attributes.SpellChanneling = 1; - Attributes.WeaponSpeed = 15; - Attributes.WeaponDamage = -50; - - WeaponAttributes.SelfRepair = 4; - } - - public MelisandesCorrodedHatchet(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072115; // Melisande's Corroded Hatchet - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class MelisandesCorrodedHatchet : Hatchet + { + [Constructible] + public MelisandesCorrodedHatchet() + { + Hue = 0x494; + + SkillBonuses.SetValues(0, SkillName.Lumberjacking, 5.0); + + Attributes.SpellChanneling = 1; + Attributes.WeaponSpeed = 15; + Attributes.WeaponDamage = -50; + + WeaponAttributes.SelfRepair = 4; + } + + public MelisandesCorrodedHatchet(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072115; // Melisande's Corroded Hatchet + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ML/PadsOfTheCuSidhe.cs b/Projects/UOContent/Items/Minor Artifacts/ML/PadsOfTheCuSidhe.cs index de04fbd40..46cb3a6c8 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ML/PadsOfTheCuSidhe.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ML/PadsOfTheCuSidhe.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class PadsOfTheCuSidhe : FurBoots - { - [Constructible] - public PadsOfTheCuSidhe() : base(0x47E) - { - } - - public PadsOfTheCuSidhe(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075048; // Pads of the Cu Sidhe - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PadsOfTheCuSidhe : FurBoots + { + [Constructible] + public PadsOfTheCuSidhe() : base(0x47E) + { + } + + public PadsOfTheCuSidhe(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075048; // Pads of the Cu Sidhe + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ML/QuiverOfElements.cs b/Projects/UOContent/Items/Minor Artifacts/ML/QuiverOfElements.cs index 0dad57a97..abc834acc 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ML/QuiverOfElements.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ML/QuiverOfElements.cs @@ -1,39 +1,41 @@ -namespace Server.Items -{ - public class QuiverOfElements : BaseQuiver - { - [Constructible] - public QuiverOfElements() - { - Hue = 0xEB; - WeightReduction = 50; - } - - public QuiverOfElements(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075040; // Quiver of the Elements - - public override void AlterBowDamage(ref int phys, ref int fire, ref int cold, ref int pois, ref int nrgy, - ref int chaos, ref int direct) - { - phys = fire = cold = pois = nrgy = direct = 0; - chaos = 100; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class QuiverOfElements : BaseQuiver + { + [Constructible] + public QuiverOfElements() + { + Hue = 0xEB; + WeightReduction = 50; + } + + public QuiverOfElements(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075040; // Quiver of the Elements + + public override void AlterBowDamage( + ref int phys, ref int fire, ref int cold, ref int pois, ref int nrgy, + ref int chaos, ref int direct + ) + { + phys = fire = cold = pois = nrgy = direct = 0; + chaos = 100; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ML/QuiverOfRage.cs b/Projects/UOContent/Items/Minor Artifacts/ML/QuiverOfRage.cs index 0a6892b04..1e654961c 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ML/QuiverOfRage.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ML/QuiverOfRage.cs @@ -1,41 +1,43 @@ -namespace Server.Items -{ - public class QuiverOfRage : BaseQuiver - { - [Constructible] - public QuiverOfRage() - { - Hue = 0x24C; - - WeightReduction = 25; - DamageIncrease = 10; - } - - public QuiverOfRage(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075038; // Quiver of Rage - - public override void AlterBowDamage(ref int phys, ref int fire, ref int cold, ref int pois, ref int nrgy, - ref int chaos, ref int direct) - { - chaos = direct = 0; - phys = fire = cold = pois = nrgy = 20; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class QuiverOfRage : BaseQuiver + { + [Constructible] + public QuiverOfRage() + { + Hue = 0x24C; + + WeightReduction = 25; + DamageIncrease = 10; + } + + public QuiverOfRage(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075038; // Quiver of Rage + + public override void AlterBowDamage( + ref int phys, ref int fire, ref int cold, ref int pois, ref int nrgy, + ref int chaos, ref int direct + ) + { + chaos = direct = 0; + phys = fire = cold = pois = nrgy = 20; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ML/RaedsGlory.cs b/Projects/UOContent/Items/Minor Artifacts/ML/RaedsGlory.cs index dd643ef66..97d98be4d 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ML/RaedsGlory.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ML/RaedsGlory.cs @@ -1,41 +1,41 @@ -namespace Server.Items -{ - public class RaedsGlory : WarCleaver - { - [Constructible] - public RaedsGlory() - { - ItemID = 0x2D23; - Hue = 0x1E6; - - Attributes.BonusMana = 8; - Attributes.SpellChanneling = 1; - Attributes.WeaponSpeed = 20; - - WeaponAttributes.HitLeechHits = 40; - } - - public RaedsGlory(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075036; // Raed's Glory - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class RaedsGlory : WarCleaver + { + [Constructible] + public RaedsGlory() + { + ItemID = 0x2D23; + Hue = 0x1E6; + + Attributes.BonusMana = 8; + Attributes.SpellChanneling = 1; + Attributes.WeaponSpeed = 20; + + WeaponAttributes.HitLeechHits = 40; + } + + public RaedsGlory(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075036; // Raed's Glory + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ML/RighteousAnger.cs b/Projects/UOContent/Items/Minor Artifacts/ML/RighteousAnger.cs index 0117ca588..12ebf0311 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ML/RighteousAnger.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ML/RighteousAnger.cs @@ -1,39 +1,39 @@ -namespace Server.Items -{ - public class RighteousAnger : ElvenMachete - { - [Constructible] - public RighteousAnger() - { - Hue = 0x284; - - Attributes.AttackChance = 15; - Attributes.DefendChance = 5; - Attributes.WeaponSpeed = 35; - Attributes.WeaponDamage = 40; - } - - public RighteousAnger(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075049; // Righteous Anger - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class RighteousAnger : ElvenMachete + { + [Constructible] + public RighteousAnger() + { + Hue = 0x284; + + Attributes.AttackChance = 15; + Attributes.DefendChance = 5; + Attributes.WeaponSpeed = 35; + Attributes.WeaponDamage = 40; + } + + public RighteousAnger(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075049; // Righteous Anger + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ML/RobeOfTheEclipse.cs b/Projects/UOContent/Items/Minor Artifacts/ML/RobeOfTheEclipse.cs index 6033c636b..f23d1e591 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ML/RobeOfTheEclipse.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ML/RobeOfTheEclipse.cs @@ -1,36 +1,36 @@ -namespace Server.Items -{ - [Flippable(0x1F03, 0x1F04)] - public class RobeOfTheEclipse : BaseOuterTorso - { - [Constructible] - public RobeOfTheEclipse() : base(0x1F03, 0x486) - { - Weight = 3.0; - - Attributes.Luck = 95; - - // TODO: Supports arcane? - } - - public RobeOfTheEclipse(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075082; // Robe of the Eclipse - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1F03, 0x1F04)] + public class RobeOfTheEclipse : BaseOuterTorso + { + [Constructible] + public RobeOfTheEclipse() : base(0x1F03, 0x486) + { + Weight = 3.0; + + Attributes.Luck = 95; + + // TODO: Supports arcane? + } + + public RobeOfTheEclipse(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075082; // Robe of the Eclipse + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ML/RobeOfTheEquinox.cs b/Projects/UOContent/Items/Minor Artifacts/ML/RobeOfTheEquinox.cs index 9d1c24da6..4cc9487c8 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ML/RobeOfTheEquinox.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ML/RobeOfTheEquinox.cs @@ -1,37 +1,37 @@ -namespace Server.Items -{ - [Flippable(0x1F03, 0x1F04)] - public class RobeOfTheEquinox : BaseOuterTorso - { - [Constructible] - public RobeOfTheEquinox() : base(0x1F04, 0xD6) - { - Weight = 3.0; - - Attributes.Luck = 95; - - // TODO: Supports arcane? - // TODO: Elves Only - } - - public RobeOfTheEquinox(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075042; // Robe of the Equinox - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x1F03, 0x1F04)] + public class RobeOfTheEquinox : BaseOuterTorso + { + [Constructible] + public RobeOfTheEquinox() : base(0x1F04, 0xD6) + { + Weight = 3.0; + + Attributes.Luck = 95; + + // TODO: Supports arcane? + // TODO: Elves Only + } + + public RobeOfTheEquinox(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075042; // Robe of the Equinox + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ML/SoulSeeker.cs b/Projects/UOContent/Items/Minor Artifacts/ML/SoulSeeker.cs index ca9d72a2b..90bb38f13 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ML/SoulSeeker.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ML/SoulSeeker.cs @@ -1,48 +1,50 @@ -namespace Server.Items -{ - public class SoulSeeker : RadiantScimitar - { - [Constructible] - public SoulSeeker() - { - Hue = 0x38C; - - WeaponAttributes.HitLeechStam = 40; - WeaponAttributes.HitLeechMana = 40; - WeaponAttributes.HitLeechHits = 40; - Attributes.WeaponSpeed = 60; - Slayer = SlayerName.Repond; - } - - public SoulSeeker(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075046; // Soul Seeker - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - cold = 100; - - pois = fire = phys = nrgy = chaos = direct = 0; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SoulSeeker : RadiantScimitar + { + [Constructible] + public SoulSeeker() + { + Hue = 0x38C; + + WeaponAttributes.HitLeechStam = 40; + WeaponAttributes.HitLeechMana = 40; + WeaponAttributes.HitLeechHits = 40; + Attributes.WeaponSpeed = 60; + Slayer = SlayerName.Repond; + } + + public SoulSeeker(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075046; // Soul Seeker + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + cold = 100; + + pois = fire = phys = nrgy = chaos = direct = 0; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ML/TalonBite.cs b/Projects/UOContent/Items/Minor Artifacts/ML/TalonBite.cs index c0c958500..42595e8d5 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ML/TalonBite.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ML/TalonBite.cs @@ -1,44 +1,44 @@ -namespace Server.Items -{ - public class TalonBite : OrnateAxe - { - [Constructible] - public TalonBite() - { - ItemID = 0x2D34; - Hue = 0x47E; - - SkillBonuses.SetValues(0, SkillName.Tactics, 10.0); - - Attributes.BonusDex = 8; - Attributes.WeaponSpeed = 20; - Attributes.WeaponDamage = 35; - - WeaponAttributes.HitHarm = 33; - WeaponAttributes.UseBestSkill = 1; - } - - public TalonBite(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075029; // Talon Bite - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TalonBite : OrnateAxe + { + [Constructible] + public TalonBite() + { + ItemID = 0x2D34; + Hue = 0x47E; + + SkillBonuses.SetValues(0, SkillName.Tactics, 10.0); + + Attributes.BonusDex = 8; + Attributes.WeaponSpeed = 20; + Attributes.WeaponDamage = 35; + + WeaponAttributes.HitHarm = 33; + WeaponAttributes.UseBestSkill = 1; + } + + public TalonBite(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075029; // Talon Bite + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ML/TotemOfVoid.cs b/Projects/UOContent/Items/Minor Artifacts/ML/TotemOfVoid.cs index dfda3d168..bf972d20f 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ML/TotemOfVoid.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ML/TotemOfVoid.cs @@ -1,47 +1,47 @@ -using System; -using Server.Mobiles; - -namespace Server.Items -{ - public class TotemOfVoid : BaseTalisman - { - [Constructible] - public TotemOfVoid() : base(0x2F5B) - { - Hue = 0x2D0; - MaxChargeTime = 1800; - - Blessed = GetRandomBlessed(); - Protection = GetRandomProtection(false); - - Attributes.RegenHits = 2; - Attributes.LowerManaCost = 10; - } - - public TotemOfVoid(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075035; // Totem of the Void - public override bool ForceShowName => true; - - public override Type GetSummoner() => Utility.RandomBool() ? typeof(SummonedSkeletalKnight) : typeof(SummonedSheep); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version == 0 && Protection?.IsEmpty != false) - Protection = GetRandomProtection(false); - } - } -} \ No newline at end of file +using System; +using Server.Mobiles; + +namespace Server.Items +{ + public class TotemOfVoid : BaseTalisman + { + [Constructible] + public TotemOfVoid() : base(0x2F5B) + { + Hue = 0x2D0; + MaxChargeTime = 1800; + + Blessed = GetRandomBlessed(); + Protection = GetRandomProtection(false); + + Attributes.RegenHits = 2; + Attributes.LowerManaCost = 10; + } + + public TotemOfVoid(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075035; // Totem of the Void + public override bool ForceShowName => true; + + public override Type GetSummoner() => Utility.RandomBool() ? typeof(SummonedSkeletalKnight) : typeof(SummonedSheep); + + 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 && Protection?.IsEmpty != false) + Protection = GetRandomProtection(false); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ML/WildfireBow.cs b/Projects/UOContent/Items/Minor Artifacts/ML/WildfireBow.cs index ab38f026b..2126a202f 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ML/WildfireBow.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ML/WildfireBow.cs @@ -1,46 +1,48 @@ -namespace Server.Items -{ - public class WildfireBow : ElvenCompositeLongbow - { - [Constructible] - public WildfireBow() - { - Hue = 0x489; - - SkillBonuses.SetValues(0, SkillName.Archery, 10); - WeaponAttributes.ResistFireBonus = 25; - - Velocity = 15; - } - - public WildfireBow(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075044; // Wildfire Bow - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - phys = cold = pois = nrgy = chaos = direct = 0; - fire = 100; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class WildfireBow : ElvenCompositeLongbow + { + [Constructible] + public WildfireBow() + { + Hue = 0x489; + + SkillBonuses.SetValues(0, SkillName.Archery, 10); + WeaponAttributes.ResistFireBonus = 25; + + Velocity = 15; + } + + public WildfireBow(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075044; // Wildfire Bow + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + phys = cold = pois = nrgy = chaos = direct = 0; + fire = 100; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ML/Windsong.cs b/Projects/UOContent/Items/Minor Artifacts/ML/Windsong.cs index 65d267f9e..073232c1a 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ML/Windsong.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ML/Windsong.cs @@ -1,39 +1,39 @@ -namespace Server.Items -{ - public class Windsong : MagicalShortbow - { - [Constructible] - public Windsong() - { - Hue = 0xF7; - - Attributes.WeaponDamage = 35; - WeaponAttributes.SelfRepair = 3; - - Velocity = 25; - } - - public Windsong(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075031; // Windsong - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class Windsong : MagicalShortbow + { + [Constructible] + public Windsong() + { + Hue = 0xF7; + + Attributes.WeaponDamage = 35; + WeaponAttributes.SelfRepair = 3; + + Velocity = 25; + } + + public Windsong(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075031; // Windsong + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/NightsKiss.cs b/Projects/UOContent/Items/Minor Artifacts/NightsKiss.cs index 66d35e6e5..afbd0e2a5 100644 --- a/Projects/UOContent/Items/Minor Artifacts/NightsKiss.cs +++ b/Projects/UOContent/Items/Minor Artifacts/NightsKiss.cs @@ -1,39 +1,39 @@ -namespace Server.Items -{ - public class NightsKiss : Dagger - { - [Constructible] - public NightsKiss() - { - ItemID = 0xF51; - Hue = 0x455; - WeaponAttributes.HitLeechHits = 40; - Slayer = SlayerName.Repond; - Attributes.WeaponSpeed = 30; - Attributes.WeaponDamage = 35; - } - - public NightsKiss(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1063475; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class NightsKiss : Dagger + { + [Constructible] + public NightsKiss() + { + ItemID = 0xF51; + Hue = 0x455; + WeaponAttributes.HitLeechHits = 40; + Slayer = SlayerName.Repond; + Attributes.WeaponSpeed = 30; + Attributes.WeaponDamage = 35; + } + + public NightsKiss(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1063475; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/NoxRangersHeavyCrossbow.cs b/Projects/UOContent/Items/Minor Artifacts/NoxRangersHeavyCrossbow.cs index 6689c8631..8f182ddfc 100644 --- a/Projects/UOContent/Items/Minor Artifacts/NoxRangersHeavyCrossbow.cs +++ b/Projects/UOContent/Items/Minor Artifacts/NoxRangersHeavyCrossbow.cs @@ -1,48 +1,50 @@ -namespace Server.Items -{ - public class NoxRangersHeavyCrossbow : HeavyCrossbow - { - [Constructible] - public NoxRangersHeavyCrossbow() - { - Hue = 0x58C; - WeaponAttributes.HitLeechStam = 40; - Attributes.SpellChanneling = 1; - Attributes.WeaponSpeed = 30; - Attributes.WeaponDamage = 20; - WeaponAttributes.ResistPoisonBonus = 10; - } - - public NoxRangersHeavyCrossbow(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1063485; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - pois = 50; - phys = 50; - - fire = cold = nrgy = chaos = direct = 0; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class NoxRangersHeavyCrossbow : HeavyCrossbow + { + [Constructible] + public NoxRangersHeavyCrossbow() + { + Hue = 0x58C; + WeaponAttributes.HitLeechStam = 40; + Attributes.SpellChanneling = 1; + Attributes.WeaponSpeed = 30; + Attributes.WeaponDamage = 20; + WeaponAttributes.ResistPoisonBonus = 10; + } + + public NoxRangersHeavyCrossbow(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1063485; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + pois = 50; + phys = 50; + + fire = cold = nrgy = chaos = direct = 0; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/OrcishVisage.cs b/Projects/UOContent/Items/Minor Artifacts/OrcishVisage.cs index 55eefd7eb..afd90eb59 100644 --- a/Projects/UOContent/Items/Minor Artifacts/OrcishVisage.cs +++ b/Projects/UOContent/Items/Minor Artifacts/OrcishVisage.cs @@ -1,43 +1,43 @@ -namespace Server.Items -{ - public class OrcishVisage : OrcHelm - { - [Constructible] - public OrcishVisage() - { - Hue = 0x592; - ArmorAttributes.SelfRepair = 3; - Attributes.BonusStr = 10; - Attributes.BonusStam = 5; - } - - public OrcishVisage(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070691; - - public override int BasePhysicalResistance => 8; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 5; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class OrcishVisage : OrcHelm + { + [Constructible] + public OrcishVisage() + { + Hue = 0x592; + ArmorAttributes.SelfRepair = 3; + Attributes.BonusStr = 10; + Attributes.BonusStam = 5; + } + + public OrcishVisage(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070691; + + public override int BasePhysicalResistance => 8; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 5; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/PhillipsWoodenSteed.cs b/Projects/UOContent/Items/Minor Artifacts/PhillipsWoodenSteed.cs index c56c5e699..4237f4a39 100644 --- a/Projects/UOContent/Items/Minor Artifacts/PhillipsWoodenSteed.cs +++ b/Projects/UOContent/Items/Minor Artifacts/PhillipsWoodenSteed.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class PhillipsWoodenSteed : MonsterStatuette - { - [Constructible] - public PhillipsWoodenSteed() : base(MonsterStatuetteType.PhillipsWoodenSteed) => LootType = LootType.Regular; - - public PhillipsWoodenSteed(Serial serial) : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PhillipsWoodenSteed : MonsterStatuette + { + [Constructible] + public PhillipsWoodenSteed() : base(MonsterStatuetteType.PhillipsWoodenSteed) => LootType = LootType.Regular; + + public PhillipsWoodenSteed(Serial serial) : base(serial) + { + } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/PixieSwatter.cs b/Projects/UOContent/Items/Minor Artifacts/PixieSwatter.cs index 9a7427b14..0e3edf819 100644 --- a/Projects/UOContent/Items/Minor Artifacts/PixieSwatter.cs +++ b/Projects/UOContent/Items/Minor Artifacts/PixieSwatter.cs @@ -1,50 +1,52 @@ -namespace Server.Items -{ - public class PixieSwatter : Scepter - { - [Constructible] - public PixieSwatter() - { - Hue = 0x8A; - WeaponAttributes.HitPoisonArea = 75; - Attributes.WeaponSpeed = 30; - - WeaponAttributes.UseBestSkill = 1; - WeaponAttributes.ResistFireBonus = 12; - WeaponAttributes.ResistEnergyBonus = 12; - - Slayer = SlayerName.Fey; - } - - public PixieSwatter(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070854; // Pixie Swatter - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - fire = 100; - - cold = pois = phys = nrgy = chaos = direct = 0; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PixieSwatter : Scepter + { + [Constructible] + public PixieSwatter() + { + Hue = 0x8A; + WeaponAttributes.HitPoisonArea = 75; + Attributes.WeaponSpeed = 30; + + WeaponAttributes.UseBestSkill = 1; + WeaponAttributes.ResistFireBonus = 12; + WeaponAttributes.ResistEnergyBonus = 12; + + Slayer = SlayerName.Fey; + } + + public PixieSwatter(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070854; // Pixie Swatter + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + fire = 100; + + cold = pois = phys = nrgy = chaos = direct = 0; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/PolarBearMask.cs b/Projects/UOContent/Items/Minor Artifacts/PolarBearMask.cs index 54f7e1588..a52118574 100644 --- a/Projects/UOContent/Items/Minor Artifacts/PolarBearMask.cs +++ b/Projects/UOContent/Items/Minor Artifacts/PolarBearMask.cs @@ -1,51 +1,51 @@ -namespace Server.Items -{ - public class PolarBearMask : BearMask - { - [Constructible] - public PolarBearMask() - { - Hue = 0x481; - - ClothingAttributes.SelfRepair = 3; - - Attributes.RegenHits = 2; - Attributes.NightSight = 1; - } - - public PolarBearMask(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070637; - - public override int BasePhysicalResistance => 15; - public override int BaseColdResistance => 21; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(2); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 2) - { - Resistances.Physical = 0; - Resistances.Cold = 0; - } - - if (Attributes.NightSight == 0) - Attributes.NightSight = 1; - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PolarBearMask : BearMask + { + [Constructible] + public PolarBearMask() + { + Hue = 0x481; + + ClothingAttributes.SelfRepair = 3; + + Attributes.RegenHits = 2; + Attributes.NightSight = 1; + } + + public PolarBearMask(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070637; + + public override int BasePhysicalResistance => 15; + public override int BaseColdResistance => 21; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(2); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version < 2) + { + Resistances.Physical = 0; + Resistances.Cold = 0; + } + + if (Attributes.NightSight == 0) + Attributes.NightSight = 1; + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/SeahorseStatuette.cs b/Projects/UOContent/Items/Minor Artifacts/SeahorseStatuette.cs index b52b963c6..b46363fee 100644 --- a/Projects/UOContent/Items/Minor Artifacts/SeahorseStatuette.cs +++ b/Projects/UOContent/Items/Minor Artifacts/SeahorseStatuette.cs @@ -1,31 +1,31 @@ -namespace Server.Items -{ - public class SeahorseStatuette : MonsterStatuette - { - [Constructible] - public SeahorseStatuette() : base(MonsterStatuetteType.Seahorse) - { - LootType = LootType.Regular; - - Hue = Utility.RandomList(0, 0x482, 0x489, 0x495, 0x4F2); - } - - public SeahorseStatuette(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SeahorseStatuette : MonsterStatuette + { + [Constructible] + public SeahorseStatuette() : base(MonsterStatuetteType.Seahorse) + { + LootType = LootType.Regular; + + Hue = Utility.RandomList(0, 0x482, 0x489, 0x495, 0x4F2); + } + + public SeahorseStatuette(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ShieldOfInvulnerability.cs b/Projects/UOContent/Items/Minor Artifacts/ShieldOfInvulnerability.cs index daa409b47..c36896391 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ShieldOfInvulnerability.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ShieldOfInvulnerability.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - public class ShieldOfInvulnerability : OrderShield - { - [Constructible] - public ShieldOfInvulnerability() - { - Hue = 0x4F2; - - Attributes.SpellChanneling = 1; - Attributes.ReflectPhysical = 10; - Attributes.DefendChance = 15; - ArmorAttributes.LowerStatReq = 100; - } - - public ShieldOfInvulnerability(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070693; - - public override int BasePhysicalResistance => 8; - public override int BaseFireResistance => 0; - public override int BaseColdResistance => 0; - public override int BasePoisonResistance => 0; - public override int BaseEnergyResistance => 0; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override bool Validate(Mobile m) => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ShieldOfInvulnerability : OrderShield + { + [Constructible] + public ShieldOfInvulnerability() + { + Hue = 0x4F2; + + Attributes.SpellChanneling = 1; + Attributes.ReflectPhysical = 10; + Attributes.DefendChance = 15; + ArmorAttributes.LowerStatReq = 100; + } + + public ShieldOfInvulnerability(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070693; + + public override int BasePhysicalResistance => 8; + public override int BaseFireResistance => 0; + public override int BaseColdResistance => 0; + public override int BasePoisonResistance => 0; + public override int BaseEnergyResistance => 0; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override bool Validate(Mobile m) => true; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/ShipModelOfTheHMSCape.cs b/Projects/UOContent/Items/Minor Artifacts/ShipModelOfTheHMSCape.cs index 72f45f7c3..323d29eff 100644 --- a/Projects/UOContent/Items/Minor Artifacts/ShipModelOfTheHMSCape.cs +++ b/Projects/UOContent/Items/Minor Artifacts/ShipModelOfTheHMSCape.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class ShipModelOfTheHMSCape : Item - { - [Constructible] - public ShipModelOfTheHMSCape() : base(0x14F3) => Hue = 0x37B; - - public ShipModelOfTheHMSCape(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1063476; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ShipModelOfTheHMSCape : Item + { + [Constructible] + public ShipModelOfTheHMSCape() : base(0x14F3) => Hue = 0x37B; + + public ShipModelOfTheHMSCape(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1063476; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/StaffOfPower.cs b/Projects/UOContent/Items/Minor Artifacts/StaffOfPower.cs index a3c9d62d0..d616f1bac 100644 --- a/Projects/UOContent/Items/Minor Artifacts/StaffOfPower.cs +++ b/Projects/UOContent/Items/Minor Artifacts/StaffOfPower.cs @@ -1,39 +1,39 @@ -namespace Server.Items -{ - public class StaffOfPower : BlackStaff - { - [Constructible] - public StaffOfPower() - { - Hue = 0x4F2; - WeaponAttributes.MageWeapon = 15; - Attributes.SpellChanneling = 1; - Attributes.SpellDamage = 5; - Attributes.CastRecovery = 2; - Attributes.LowerManaCost = 5; - } - - public StaffOfPower(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070692; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class StaffOfPower : BlackStaff + { + [Constructible] + public StaffOfPower() + { + Hue = 0x4F2; + WeaponAttributes.MageWeapon = 15; + Attributes.SpellChanneling = 1; + Attributes.SpellDamage = 5; + Attributes.CastRecovery = 2; + Attributes.LowerManaCost = 5; + } + + public StaffOfPower(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070692; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/VioletCourage.cs b/Projects/UOContent/Items/Minor Artifacts/VioletCourage.cs index 1ef6aa32a..b9cb00479 100644 --- a/Projects/UOContent/Items/Minor Artifacts/VioletCourage.cs +++ b/Projects/UOContent/Items/Minor Artifacts/VioletCourage.cs @@ -1,44 +1,44 @@ -namespace Server.Items -{ - public class VioletCourage : FemalePlateChest - { - [Constructible] - public VioletCourage() - { - Hue = 0x486; - Attributes.Luck = 95; - Attributes.DefendChance = 15; - ArmorAttributes.LowerStatReq = 100; - ArmorAttributes.MageArmor = 1; - } - - public VioletCourage(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1063471; - - public override int BasePhysicalResistance => 14; - public override int BaseFireResistance => 12; - public override int BaseColdResistance => 12; - public override int BasePoisonResistance => 8; - public override int BaseEnergyResistance => 9; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class VioletCourage : FemalePlateChest + { + [Constructible] + public VioletCourage() + { + Hue = 0x486; + Attributes.Luck = 95; + Attributes.DefendChance = 15; + ArmorAttributes.LowerStatReq = 100; + ArmorAttributes.MageArmor = 1; + } + + public VioletCourage(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1063471; + + public override int BasePhysicalResistance => 14; + public override int BaseFireResistance => 12; + public override int BaseColdResistance => 12; + public override int BasePoisonResistance => 8; + public override int BaseEnergyResistance => 9; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Minor Artifacts/WrathOfTheDryad.cs b/Projects/UOContent/Items/Minor Artifacts/WrathOfTheDryad.cs index 62aa29414..9c65c840b 100644 --- a/Projects/UOContent/Items/Minor Artifacts/WrathOfTheDryad.cs +++ b/Projects/UOContent/Items/Minor Artifacts/WrathOfTheDryad.cs @@ -1,46 +1,48 @@ -namespace Server.Items -{ - public class WrathOfTheDryad : GnarledStaff - { - [Constructible] - public WrathOfTheDryad() - { - Hue = 0x29C; - WeaponAttributes.HitLeechMana = 50; - WeaponAttributes.HitLightning = 33; - Attributes.AttackChance = 15; - Attributes.WeaponDamage = 40; - } - - public WrathOfTheDryad(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070853; // Wrath of the Dryad - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - pois = 100; - - cold = fire = phys = nrgy = chaos = direct = 0; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class WrathOfTheDryad : GnarledStaff + { + [Constructible] + public WrathOfTheDryad() + { + Hue = 0x29C; + WeaponAttributes.HitLeechMana = 50; + WeaponAttributes.HitLightning = 33; + Attributes.AttackChance = 15; + Attributes.WeaponDamage = 40; + } + + public WrathOfTheDryad(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070853; // Wrath of the Dryad + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + pois = 100; + + cold = fire = phys = nrgy = chaos = direct = 0; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/AcidSlime.cs b/Projects/UOContent/Items/Misc/AcidSlime.cs index 158c8ada3..363ac49e3 100644 --- a/Projects/UOContent/Items/Misc/AcidSlime.cs +++ b/Projects/UOContent/Items/Misc/AcidSlime.cs @@ -1,96 +1,96 @@ -using System; -using System.Collections.Generic; -using Server.Mobiles; - -namespace Server.Items -{ - public class AcidSlime : Item - { - private readonly DateTime m_Created; - private bool m_Drying; - private readonly TimeSpan m_Duration; - private readonly int m_MaxDamage; - private readonly int m_MinDamage; - private readonly Timer m_Timer; - - [Constructible] - public AcidSlime() : this(TimeSpan.FromSeconds(10.0), 5, 10) - { - } - - [Constructible] - public AcidSlime(TimeSpan duration, int minDamage, int maxDamage) - : base(0x122A) - { - Hue = 0x3F; - Movable = false; - m_MinDamage = minDamage; - m_MaxDamage = maxDamage; - m_Created = DateTime.UtcNow; - m_Duration = duration; - m_Timer = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromSeconds(1), OnTick); - } - - public AcidSlime(Serial serial) : base(serial) - { - } - - public override string DefaultName => "slime"; - - public override void OnAfterDelete() - { - m_Timer?.Stop(); - } - - private void OnTick() - { - DateTime now = DateTime.UtcNow; - TimeSpan age = now - m_Created; - - if (age > m_Duration) - { - Delete(); - } - else - { - if (!m_Drying && age > m_Duration - age) - { - m_Drying = true; - ItemID = 0x122B; - } - - List toDamage = new List(); - - foreach (Mobile m in GetMobilesInRange(0)) - if (m.Alive && !m.IsDeadBondedPet && (!(m is BaseCreature bc) || bc.Controlled || bc.Summoned)) - toDamage.Add(m); - - for (int i = 0; i < toDamage.Count; i++) - Damage(toDamage[i]); - } - } - - public override bool OnMoveOver(Mobile m) - { - Damage(m); - return true; - } - - public void Damage(Mobile m) - { - int damage = Utility.RandomMinMax(m_MinDamage, m_MaxDamage); - if (Core.AOS) - AOS.Damage(m, damage, 0, 0, 0, 100, 0); - else - m.Damage(damage); - } - - public override void Serialize(IGenericWriter writer) - { - } - - public override void Deserialize(IGenericReader reader) - { - } - } -} \ No newline at end of file +using System; +using System.Collections.Generic; +using Server.Mobiles; + +namespace Server.Items +{ + public class AcidSlime : Item + { + private readonly DateTime m_Created; + private readonly TimeSpan m_Duration; + private readonly int m_MaxDamage; + private readonly int m_MinDamage; + private readonly Timer m_Timer; + private bool m_Drying; + + [Constructible] + public AcidSlime() : this(TimeSpan.FromSeconds(10.0), 5, 10) + { + } + + [Constructible] + public AcidSlime(TimeSpan duration, int minDamage, int maxDamage) + : base(0x122A) + { + Hue = 0x3F; + Movable = false; + m_MinDamage = minDamage; + m_MaxDamage = maxDamage; + m_Created = DateTime.UtcNow; + m_Duration = duration; + m_Timer = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromSeconds(1), OnTick); + } + + public AcidSlime(Serial serial) : base(serial) + { + } + + public override string DefaultName => "slime"; + + public override void OnAfterDelete() + { + m_Timer?.Stop(); + } + + private void OnTick() + { + var now = DateTime.UtcNow; + var age = now - m_Created; + + if (age > m_Duration) + { + Delete(); + } + else + { + if (!m_Drying && age > m_Duration - age) + { + m_Drying = true; + ItemID = 0x122B; + } + + var toDamage = new List(); + + foreach (var m in GetMobilesInRange(0)) + if (m.Alive && !m.IsDeadBondedPet && (!(m is BaseCreature bc) || bc.Controlled || bc.Summoned)) + toDamage.Add(m); + + for (var i = 0; i < toDamage.Count; i++) + Damage(toDamage[i]); + } + } + + public override bool OnMoveOver(Mobile m) + { + Damage(m); + return true; + } + + public void Damage(Mobile m) + { + var damage = Utility.RandomMinMax(m_MinDamage, m_MaxDamage); + if (Core.AOS) + AOS.Damage(m, damage, 0, 0, 0, 100, 0); + else + m.Damage(damage); + } + + public override void Serialize(IGenericWriter writer) + { + } + + public override void Deserialize(IGenericReader reader) + { + } + } +} diff --git a/Projects/UOContent/Items/Misc/ArcaneGem.cs b/Projects/UOContent/Items/Misc/ArcaneGem.cs index f27f80ac2..0f1769cb0 100644 --- a/Projects/UOContent/Items/Misc/ArcaneGem.cs +++ b/Projects/UOContent/Items/Misc/ArcaneGem.cs @@ -1,211 +1,212 @@ -using System.Collections.Generic; -using Server.Targeting; - -namespace Server.Items -{ - public class ArcaneGem : Item - { - public const int DefaultArcaneHue = 2117; - - [Constructible] - public ArcaneGem() : base(0x1EA7) - { - Stackable = Core.ML; - Weight = 1.0; - } - - public ArcaneGem(Serial serial) : base(serial) - { - } - - public override string DefaultName => "arcane gem"; - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else - { - from.BeginTarget(2, false, TargetFlags.None, OnTarget); - from.SendMessage("What do you wish to use the gem on?"); - } - } - - public int GetChargesFor(Mobile m) - { - int v = (int)(m.Skills.Tailoring.Value / 5); - - if (v < 16) - return 16; - if (v > 24) - return 24; - - return v; - } - - public void OnTarget(Mobile from, object obj) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - return; - } - - if (obj is IArcaneEquip eq && eq is Item item) - { - BaseClothing clothing = item as BaseClothing; - BaseArmor armor = item as BaseArmor; - BaseWeapon weapon = item as BaseWeapon; - - CraftResource resource = clothing?.Resource ?? armor?.Resource ?? weapon?.Resource ?? CraftResource.None; - - if (!item.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - return; - } - - if (item.LootType == LootType.Blessed) - { - from.SendMessage( - "You can only use this on exceptionally crafted robes, thigh boots, cloaks, or leather gloves."); - return; - } - - if (resource != CraftResource.None && resource != CraftResource.RegularLeather) - { - from.SendLocalizedMessage(1049690); // Arcane gems can not be used on that type of leather. - return; - } - - int charges = GetChargesFor(from); - - if (eq.IsArcane) - { - if (eq.CurArcaneCharges >= eq.MaxArcaneCharges) - { - from.SendMessage("That item is already fully charged."); - } - else - { - if (eq.CurArcaneCharges <= 0) - item.Hue = DefaultArcaneHue; - - if (eq.CurArcaneCharges + charges > eq.MaxArcaneCharges) - eq.CurArcaneCharges = eq.MaxArcaneCharges; - else - eq.CurArcaneCharges += charges; - - from.SendMessage("You recharge the item."); - if (Amount <= 1) - Delete(); - else Amount--; - } - } - else if (from.Skills.Tailoring.Value >= 80.0) - { - bool isExceptional = clothing?.Quality == ClothingQuality.Exceptional || - armor?.Quality == ArmorQuality.Exceptional || - weapon?.Quality == WeaponQuality.Exceptional; - - if (isExceptional) - { - if (clothing != null) - { - clothing.Quality = ClothingQuality.Regular; - clothing.Crafter = from; - } - else if (armor != null) - { - armor.Quality = ArmorQuality.Regular; - armor.Crafter = from; - armor.PhysicalBonus = - armor.FireBonus = - armor.ColdBonus = - armor.PoisonBonus = armor.EnergyBonus = 0; // Is there a method to remove bonuses? - } - else - { - weapon.Quality = WeaponQuality.Regular; - weapon.Crafter = from; - } - - eq.CurArcaneCharges = eq.MaxArcaneCharges = charges; - - item.Hue = DefaultArcaneHue; - - from.SendMessage("You enhance the item with your gem."); - if (Amount <= 1) - Delete(); - else Amount--; - } - else - { - from.SendMessage("Only exceptional items can be enhanced with the gem."); - } - } - else - { - from.SendMessage("You do not have enough skill in tailoring to enhance the item."); - } - } - else - { - from.SendMessage( - "You can only use this on exceptionally crafted robes, thigh boots, cloaks, or leather gloves."); - } - } - - public static bool ConsumeCharges(Mobile from, int amount) - { - List items = from.Items; - int avail = 0; - - for (int i = 0; i < items.Count; ++i) - { - Item obj = items[i]; - - if (obj is IArcaneEquip eq && eq.IsArcane) - avail += eq.CurArcaneCharges; - } - - if (avail < amount) - return false; - - for (int i = 0; i < items.Count; ++i) - { - Item obj = items[i]; - - if (obj is IArcaneEquip eq && eq.IsArcane) - { - if (eq.CurArcaneCharges > amount) - { - eq.CurArcaneCharges -= amount; - break; - } - - amount -= eq.CurArcaneCharges; - eq.CurArcaneCharges = 0; - } - } - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Targeting; + +namespace Server.Items +{ + public class ArcaneGem : Item + { + public const int DefaultArcaneHue = 2117; + + [Constructible] + public ArcaneGem() : base(0x1EA7) + { + Stackable = Core.ML; + Weight = 1.0; + } + + public ArcaneGem(Serial serial) : base(serial) + { + } + + public override string DefaultName => "arcane gem"; + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else + { + from.BeginTarget(2, false, TargetFlags.None, OnTarget); + from.SendMessage("What do you wish to use the gem on?"); + } + } + + public int GetChargesFor(Mobile m) + { + var v = (int)(m.Skills.Tailoring.Value / 5); + + if (v < 16) + return 16; + if (v > 24) + return 24; + + return v; + } + + public void OnTarget(Mobile from, object obj) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + return; + } + + if (obj is IArcaneEquip eq && eq is Item item) + { + var clothing = item as BaseClothing; + var armor = item as BaseArmor; + var weapon = item as BaseWeapon; + + var resource = clothing?.Resource ?? armor?.Resource ?? weapon?.Resource ?? CraftResource.None; + + if (!item.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + return; + } + + if (item.LootType == LootType.Blessed) + { + from.SendMessage( + "You can only use this on exceptionally crafted robes, thigh boots, cloaks, or leather gloves." + ); + return; + } + + if (resource != CraftResource.None && resource != CraftResource.RegularLeather) + { + from.SendLocalizedMessage(1049690); // Arcane gems can not be used on that type of leather. + return; + } + + var charges = GetChargesFor(from); + + if (eq.IsArcane) + { + if (eq.CurArcaneCharges >= eq.MaxArcaneCharges) + { + from.SendMessage("That item is already fully charged."); + } + else + { + if (eq.CurArcaneCharges <= 0) + item.Hue = DefaultArcaneHue; + + if (eq.CurArcaneCharges + charges > eq.MaxArcaneCharges) + eq.CurArcaneCharges = eq.MaxArcaneCharges; + else + eq.CurArcaneCharges += charges; + + from.SendMessage("You recharge the item."); + if (Amount <= 1) + Delete(); + else Amount--; + } + } + else if (from.Skills.Tailoring.Value >= 80.0) + { + var isExceptional = clothing?.Quality == ClothingQuality.Exceptional || + armor?.Quality == ArmorQuality.Exceptional || + weapon?.Quality == WeaponQuality.Exceptional; + + if (isExceptional) + { + if (clothing != null) + { + clothing.Quality = ClothingQuality.Regular; + clothing.Crafter = from; + } + else if (armor != null) + { + armor.Quality = ArmorQuality.Regular; + armor.Crafter = from; + armor.PhysicalBonus = + armor.FireBonus = + armor.ColdBonus = + armor.PoisonBonus = armor.EnergyBonus = 0; // Is there a method to remove bonuses? + } + else + { + weapon.Quality = WeaponQuality.Regular; + weapon.Crafter = from; + } + + eq.CurArcaneCharges = eq.MaxArcaneCharges = charges; + + item.Hue = DefaultArcaneHue; + + from.SendMessage("You enhance the item with your gem."); + if (Amount <= 1) + Delete(); + else Amount--; + } + else + { + from.SendMessage("Only exceptional items can be enhanced with the gem."); + } + } + else + { + from.SendMessage("You do not have enough skill in tailoring to enhance the item."); + } + } + else + { + from.SendMessage( + "You can only use this on exceptionally crafted robes, thigh boots, cloaks, or leather gloves." + ); + } + } + + public static bool ConsumeCharges(Mobile from, int amount) + { + var items = from.Items; + var avail = 0; + + for (var i = 0; i < items.Count; ++i) + { + var obj = items[i]; + + if (obj is IArcaneEquip eq && eq.IsArcane) + avail += eq.CurArcaneCharges; + } + + if (avail < amount) + return false; + + for (var i = 0; i < items.Count; ++i) + { + var obj = items[i]; + + if (obj is IArcaneEquip eq && eq.IsArcane) + { + if (eq.CurArcaneCharges > amount) + { + eq.CurArcaneCharges -= amount; + break; + } + + amount -= eq.CurArcaneCharges; + eq.CurArcaneCharges = 0; + } + } + + return true; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/BankCheck.cs b/Projects/UOContent/Items/Misc/BankCheck.cs index e57040b9b..7ad316356 100644 --- a/Projects/UOContent/Items/Misc/BankCheck.cs +++ b/Projects/UOContent/Items/Misc/BankCheck.cs @@ -1,247 +1,249 @@ -using System; -using System.Globalization; -using Server.Accounting; -using Server.Engines.Quests; -using Server.Engines.Quests.Haven; -using Server.Engines.Quests.Necro; -using Server.Mobiles; -using Server.Network; -using CashBankCheckObjective = Server.Engines.Quests.Necro.CashBankCheckObjective; - -namespace Server.Items -{ - public class BankCheck : Item - { - private int m_Worth; - - public BankCheck(Serial serial) : base(serial) - { - } - - [Constructible] - public BankCheck(int worth) : base(0x14F0) - { - Weight = 1.0; - Hue = 0x34; - LootType = LootType.Blessed; - - m_Worth = worth; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Worth - { - get => m_Worth; - set - { - m_Worth = value; - InvalidateProperties(); - } - } - - public override bool DisplayLootType => Core.AOS; - - public override int LabelNumber => 1041361; // A bank check - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Worth); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - LootType = LootType.Blessed; - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Worth = reader.ReadInt(); - break; - } - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - string worth; - - if (Core.ML) - worth = m_Worth.ToString("N0", CultureInfo.GetCultureInfo("en-US")); - else - worth = m_Worth.ToString(); - - list.Add(1060738, worth); // value: ~1_val~ - } - - public override void OnAdded(IEntity parent) - { - base.OnAdded(parent); - - if (!AccountGold.Enabled) return; - - Mobile owner = null; - SecureTradeInfo tradeInfo = null; - - Container root = parent as Container; - - while (root?.Parent is Container container) - root = container; - - parent = root ?? parent; - - if (parent is SecureTradeContainer trade && AccountGold.ConvertOnTrade) - { - if (trade.Trade.From.Container == trade) - { - tradeInfo = trade.Trade.From; - owner = tradeInfo.Mobile; - } - else if (trade.Trade.To.Container == trade) - { - tradeInfo = trade.Trade.To; - owner = tradeInfo.Mobile; - } - } - else if (parent is BankBox box && AccountGold.ConvertOnBank) - { - owner = box.Owner; - } - - if (owner?.Account?.DepositGold(Worth) != true) return; - - if (tradeInfo != null) - { - if (owner.NetState?.NewSecureTrading == false) - { - int plat = Math.DivRem(Worth, AccountGold.CurrencyThreshold, out int gold); - - tradeInfo.Plat += plat; - tradeInfo.Gold += gold; - } - - tradeInfo.VirtualCheck?.UpdateTrade(tradeInfo.Mobile); - } - - owner.SendLocalizedMessage(1042763, Worth.ToString("#,0")); - - Delete(); - - ((Container)parent).UpdateTotals(); - } - - public override void OnSingleClick(Mobile from) - { - from.Send( - new MessageLocalizedAffix( - Serial, - ItemID, - MessageType.Label, - 0x3B2, - 3, - 1041361, - "", - AffixType.Append, - $" {m_Worth}", - "")); // A bank check: - } - - public override void OnDoubleClick(Mobile from) - { - // This probably isn't OSI accurate, but we can't just make the quests redundant. - // Double-clicking the BankCheck in your pack will now credit your account. - - Container box = AccountGold.Enabled ? from.Backpack : from.FindBankNoCreate(); - - if (box == null || !IsChildOf(box)) - { - from.SendLocalizedMessage(AccountGold.Enabled ? 1080058 : 1047026); - // This must be in your backpack to use it. : That must be in your bank box to use it. - return; - } - - Delete(); - - int deposited = 0; - int toAdd = m_Worth; - - if (AccountGold.Enabled && from.Account?.DepositGold(toAdd) == true) - { - deposited = toAdd; - toAdd = 0; - } - - if (toAdd > 0) - { - Gold gold; - - while (toAdd > 60000) - { - gold = new Gold(60000); - - if (box.TryDropItem(from, gold, false)) - { - toAdd -= 60000; - deposited += 60000; - } - else - { - gold.Delete(); - - from.AddToBackpack(new BankCheck(toAdd)); - toAdd = 0; - - break; - } - } - - if (toAdd > 0) - { - gold = new Gold(toAdd); - - if (box.TryDropItem(from, gold, false)) - { - deposited += toAdd; - } - else - { - gold.Delete(); - - from.AddToBackpack(new BankCheck(toAdd)); - } - } - } - - // Gold was deposited in your account: - from.SendLocalizedMessage(1042672, true, deposited.ToString("#,0")); - - if (from is PlayerMobile pm) - { - QuestSystem qs = pm.Quest; - - if (qs is DarkTidesQuest) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) obj.Complete(); - } - - if (qs is UzeraanTurmoilQuest) - { - QuestObjective obj = qs.FindObjective(typeof(Engines.Quests.Haven.CashBankCheckObjective)); - - if (obj?.Completed == false) obj.Complete(); - } - } - } - } -} +using System; +using System.Globalization; +using Server.Accounting; +using Server.Engines.Quests; +using Server.Engines.Quests.Haven; +using Server.Engines.Quests.Necro; +using Server.Mobiles; +using Server.Network; +using CashBankCheckObjective = Server.Engines.Quests.Necro.CashBankCheckObjective; + +namespace Server.Items +{ + public class BankCheck : Item + { + private int m_Worth; + + public BankCheck(Serial serial) : base(serial) + { + } + + [Constructible] + public BankCheck(int worth) : base(0x14F0) + { + Weight = 1.0; + Hue = 0x34; + LootType = LootType.Blessed; + + m_Worth = worth; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Worth + { + get => m_Worth; + set + { + m_Worth = value; + InvalidateProperties(); + } + } + + public override bool DisplayLootType => Core.AOS; + + public override int LabelNumber => 1041361; // A bank check + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Worth); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + LootType = LootType.Blessed; + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Worth = reader.ReadInt(); + break; + } + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + string worth; + + if (Core.ML) + worth = m_Worth.ToString("N0", CultureInfo.GetCultureInfo("en-US")); + else + worth = m_Worth.ToString(); + + list.Add(1060738, worth); // value: ~1_val~ + } + + public override void OnAdded(IEntity parent) + { + base.OnAdded(parent); + + if (!AccountGold.Enabled) return; + + Mobile owner = null; + SecureTradeInfo tradeInfo = null; + + var root = parent as Container; + + while (root?.Parent is Container container) + root = container; + + parent = root ?? parent; + + if (parent is SecureTradeContainer trade && AccountGold.ConvertOnTrade) + { + if (trade.Trade.From.Container == trade) + { + tradeInfo = trade.Trade.From; + owner = tradeInfo.Mobile; + } + else if (trade.Trade.To.Container == trade) + { + tradeInfo = trade.Trade.To; + owner = tradeInfo.Mobile; + } + } + else if (parent is BankBox box && AccountGold.ConvertOnBank) + { + owner = box.Owner; + } + + if (owner?.Account?.DepositGold(Worth) != true) return; + + if (tradeInfo != null) + { + if (owner.NetState?.NewSecureTrading == false) + { + var plat = Math.DivRem(Worth, AccountGold.CurrencyThreshold, out var gold); + + tradeInfo.Plat += plat; + tradeInfo.Gold += gold; + } + + tradeInfo.VirtualCheck?.UpdateTrade(tradeInfo.Mobile); + } + + owner.SendLocalizedMessage(1042763, Worth.ToString("#,0")); + + Delete(); + + ((Container)parent).UpdateTotals(); + } + + public override void OnSingleClick(Mobile from) + { + from.Send( + new MessageLocalizedAffix( + Serial, + ItemID, + MessageType.Label, + 0x3B2, + 3, + 1041361, + "", + AffixType.Append, + $" {m_Worth}", + "" + ) + ); // A bank check: + } + + public override void OnDoubleClick(Mobile from) + { + // This probably isn't OSI accurate, but we can't just make the quests redundant. + // Double-clicking the BankCheck in your pack will now credit your account. + + var box = AccountGold.Enabled ? from.Backpack : from.FindBankNoCreate(); + + if (box == null || !IsChildOf(box)) + { + from.SendLocalizedMessage(AccountGold.Enabled ? 1080058 : 1047026); + // This must be in your backpack to use it. : That must be in your bank box to use it. + return; + } + + Delete(); + + var deposited = 0; + var toAdd = m_Worth; + + if (AccountGold.Enabled && from.Account?.DepositGold(toAdd) == true) + { + deposited = toAdd; + toAdd = 0; + } + + if (toAdd > 0) + { + Gold gold; + + while (toAdd > 60000) + { + gold = new Gold(60000); + + if (box.TryDropItem(from, gold, false)) + { + toAdd -= 60000; + deposited += 60000; + } + else + { + gold.Delete(); + + from.AddToBackpack(new BankCheck(toAdd)); + toAdd = 0; + + break; + } + } + + if (toAdd > 0) + { + gold = new Gold(toAdd); + + if (box.TryDropItem(from, gold, false)) + { + deposited += toAdd; + } + else + { + gold.Delete(); + + from.AddToBackpack(new BankCheck(toAdd)); + } + } + } + + // Gold was deposited in your account: + from.SendLocalizedMessage(1042672, true, deposited.ToString("#,0")); + + if (from is PlayerMobile pm) + { + var qs = pm.Quest; + + if (qs is DarkTidesQuest) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) obj.Complete(); + } + + if (qs is UzeraanTurmoilQuest) + { + var obj = qs.FindObjective(typeof(Engines.Quests.Haven.CashBankCheckObjective)); + + if (obj?.Completed == false) obj.Complete(); + } + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/Bedlam/GlobOfMonstreousInterredGrizzle.cs b/Projects/UOContent/Items/Misc/Bedlam/GlobOfMonstreousInterredGrizzle.cs index 1c5ec4ec2..530e9f1e8 100644 --- a/Projects/UOContent/Items/Misc/Bedlam/GlobOfMonstreousInterredGrizzle.cs +++ b/Projects/UOContent/Items/Misc/Bedlam/GlobOfMonstreousInterredGrizzle.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class GlobOfMonstreousInterredGrizzle : Item - { - [Constructible] - public GlobOfMonstreousInterredGrizzle() : base(0x2F3) - { - } - - public GlobOfMonstreousInterredGrizzle(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072117; // Glob of Monsterous Interred Grizzle - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class GlobOfMonstreousInterredGrizzle : Item + { + [Constructible] + public GlobOfMonstreousInterredGrizzle() : base(0x2F3) + { + } + + public GlobOfMonstreousInterredGrizzle(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072117; // Glob of Monsterous Interred Grizzle + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Bedlam/GrizzledSkullCollection.cs b/Projects/UOContent/Items/Misc/Bedlam/GrizzledSkullCollection.cs index 770993710..d73710b23 100644 --- a/Projects/UOContent/Items/Misc/Bedlam/GrizzledSkullCollection.cs +++ b/Projects/UOContent/Items/Misc/Bedlam/GrizzledSkullCollection.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class GrizzledSkullCollection : Item - { - [Constructible] - public GrizzledSkullCollection() : base(0x21FC) - { - } - - public GrizzledSkullCollection(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072116; // Grizzled Skull collection - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class GrizzledSkullCollection : Item + { + [Constructible] + public GrizzledSkullCollection() : base(0x21FC) + { + } + + public GrizzledSkullCollection(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072116; // Grizzled Skull collection + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Bedlam/MonsterousInterredGrizzleMaggots.cs b/Projects/UOContent/Items/Misc/Bedlam/MonsterousInterredGrizzleMaggots.cs index 9550fcfa5..646a39e82 100644 --- a/Projects/UOContent/Items/Misc/Bedlam/MonsterousInterredGrizzleMaggots.cs +++ b/Projects/UOContent/Items/Misc/Bedlam/MonsterousInterredGrizzleMaggots.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class MonsterousInterredGrizzleMaggots : Item - { - [Constructible] - public MonsterousInterredGrizzleMaggots() : base(0x2633) - { - } - - public MonsterousInterredGrizzleMaggots(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075090; // Monsterous Interred Grizzle Maggots - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class MonsterousInterredGrizzleMaggots : Item + { + [Constructible] + public MonsterousInterredGrizzleMaggots() : base(0x2633) + { + } + + public MonsterousInterredGrizzleMaggots(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075090; // Monsterous Interred Grizzle Maggots + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Bedlam/ResolvesBridle.cs b/Projects/UOContent/Items/Misc/Bedlam/ResolvesBridle.cs index 73904d6a7..423f81159 100644 --- a/Projects/UOContent/Items/Misc/Bedlam/ResolvesBridle.cs +++ b/Projects/UOContent/Items/Misc/Bedlam/ResolvesBridle.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class ResolvesBridle : Item - { - [Constructible] - public ResolvesBridle() : base(0x1374) - { - } - - public ResolvesBridle(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074761; // Resolve's Bridle - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ResolvesBridle : Item + { + [Constructible] + public ResolvesBridle() : base(0x1374) + { + } + + public ResolvesBridle(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074761; // Resolve's Bridle + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Bedlam/TombstoneOfTheDamned.cs b/Projects/UOContent/Items/Misc/Bedlam/TombstoneOfTheDamned.cs index 6e7e06d76..ee08d77d8 100644 --- a/Projects/UOContent/Items/Misc/Bedlam/TombstoneOfTheDamned.cs +++ b/Projects/UOContent/Items/Misc/Bedlam/TombstoneOfTheDamned.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class TombstoneOfTheDamned : Item - { - [Constructible] - public TombstoneOfTheDamned() : base(Utility.RandomMinMax(0xED7, 0xEDE)) - { - } - - public TombstoneOfTheDamned(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072123; // Tombstone of the Damned - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TombstoneOfTheDamned : Item + { + [Constructible] + public TombstoneOfTheDamned() : base(Utility.RandomMinMax(0xED7, 0xEDE)) + { + } + + public TombstoneOfTheDamned(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072123; // Tombstone of the Damned + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Beeswax.cs b/Projects/UOContent/Items/Misc/Beeswax.cs index 4b9a7411a..83898190f 100644 --- a/Projects/UOContent/Items/Misc/Beeswax.cs +++ b/Projects/UOContent/Items/Misc/Beeswax.cs @@ -1,31 +1,31 @@ -namespace Server.Items -{ - public class Beeswax : Item - { - [Constructible] - public Beeswax(int amount = 1) : base(0x1422) - { - Weight = 1.0; - Stackable = true; - Amount = amount; - } - - public Beeswax(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class Beeswax : Item + { + [Constructible] + public Beeswax(int amount = 1) : base(0x1422) + { + Weight = 1.0; + Stackable = true; + Amount = amount; + } + + public Beeswax(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Blighted Grove/AbscessTail.cs b/Projects/UOContent/Items/Misc/Blighted Grove/AbscessTail.cs index 44927ed2a..0e201533f 100644 --- a/Projects/UOContent/Items/Misc/Blighted Grove/AbscessTail.cs +++ b/Projects/UOContent/Items/Misc/Blighted Grove/AbscessTail.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class AbscessTail : Item - { - [Constructible] - public AbscessTail() : base(0x1A9D) - { - LootType = LootType.Blessed; - Hue = 0x51D; // TODO check - } - - public AbscessTail(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074231; // Abscess' Tail - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AbscessTail : Item + { + [Constructible] + public AbscessTail() : base(0x1A9D) + { + LootType = LootType.Blessed; + Hue = 0x51D; // TODO check + } + + public AbscessTail(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074231; // Abscess' Tail + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Blighted Grove/CoilsFang.cs b/Projects/UOContent/Items/Misc/Blighted Grove/CoilsFang.cs index be317458d..49a12ee8a 100644 --- a/Projects/UOContent/Items/Misc/Blighted Grove/CoilsFang.cs +++ b/Projects/UOContent/Items/Misc/Blighted Grove/CoilsFang.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class CoilsFang : Item - { - [Constructible] - public CoilsFang() : base(0x10E8) - { - LootType = LootType.Blessed; - Hue = 0x487; - } - - public CoilsFang(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074229; // Coil's Fang - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class CoilsFang : Item + { + [Constructible] + public CoilsFang() : base(0x10E8) + { + LootType = LootType.Blessed; + Hue = 0x487; + } + + public CoilsFang(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074229; // Coil's Fang + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Blighted Grove/EternallyCorruptTree.cs b/Projects/UOContent/Items/Misc/Blighted Grove/EternallyCorruptTree.cs index 2516b2794..9430d4503 100644 --- a/Projects/UOContent/Items/Misc/Blighted Grove/EternallyCorruptTree.cs +++ b/Projects/UOContent/Items/Misc/Blighted Grove/EternallyCorruptTree.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class EternallyCorruptTree : Item - { - [Constructible] - public EternallyCorruptTree() : base(0x20FA) => Hue = Utility.RandomMinMax(0x899, 0x8B0); - - public EternallyCorruptTree(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072093; // Eternally Corrupt Tree - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class EternallyCorruptTree : Item + { + [Constructible] + public EternallyCorruptTree() : base(0x20FA) => Hue = Utility.RandomMinMax(0x899, 0x8B0); + + public EternallyCorruptTree(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072093; // Eternally Corrupt Tree + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Blighted Grove/HydraScale.cs b/Projects/UOContent/Items/Misc/Blighted Grove/HydraScale.cs index 782410348..17be77ead 100644 --- a/Projects/UOContent/Items/Misc/Blighted Grove/HydraScale.cs +++ b/Projects/UOContent/Items/Misc/Blighted Grove/HydraScale.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class HydraScale : Item - { - [Constructible] - public HydraScale() : base(0x26B4) - { - LootType = LootType.Blessed; - Hue = 0xC2; // TODO check - } - - public HydraScale(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074760; // A hydra scale. - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class HydraScale : Item + { + [Constructible] + public HydraScale() : base(0x26B4) + { + LootType = LootType.Blessed; + Hue = 0xC2; // TODO check + } + + public HydraScale(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074760; // A hydra scale. + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Blighted Grove/MelisandesFermentedWine.cs b/Projects/UOContent/Items/Misc/Blighted Grove/MelisandesFermentedWine.cs index 24087f9c9..0bb4ed972 100644 --- a/Projects/UOContent/Items/Misc/Blighted Grove/MelisandesFermentedWine.cs +++ b/Projects/UOContent/Items/Misc/Blighted Grove/MelisandesFermentedWine.cs @@ -1,47 +1,47 @@ -namespace Server.Items -{ - public class MelisandesFermentedWine : GreaterExplosionPotion - { - [Constructible] - public MelisandesFermentedWine() - { - Stackable = false; - ItemID = 0x99B; - Hue = Utility.RandomList(0xB, 0xF, 0x48D); // TODO update - } - - public MelisandesFermentedWine(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072114; // Melisande's Fermented Wine - - public override void Drink(Mobile from) - { - if (MondainsLegacy.CheckML(from)) - base.Drink(from); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1074502); // It looks explosive. - list.Add(1075085); // Requirement: Mondain's Legacy - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class MelisandesFermentedWine : GreaterExplosionPotion + { + [Constructible] + public MelisandesFermentedWine() + { + Stackable = false; + ItemID = 0x99B; + Hue = Utility.RandomList(0xB, 0xF, 0x48D); // TODO update + } + + public MelisandesFermentedWine(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072114; // Melisande's Fermented Wine + + public override void Drink(Mobile from) + { + if (MondainsLegacy.CheckML(from)) + base.Drink(from); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1074502); // It looks explosive. + list.Add(1075085); // Requirement: Mondain's Legacy + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Blighted Grove/MelisandesHairDye.cs b/Projects/UOContent/Items/Misc/Blighted Grove/MelisandesHairDye.cs index 0266a9682..f1c04b797 100644 --- a/Projects/UOContent/Items/Misc/Blighted Grove/MelisandesHairDye.cs +++ b/Projects/UOContent/Items/Misc/Blighted Grove/MelisandesHairDye.cs @@ -1,89 +1,89 @@ -using Server.Gumps; - -namespace Server.Items -{ - public class MelisandesHairDye : Item - { - [Constructible] - public MelisandesHairDye() : base(0xEFF) => Hue = Utility.RandomMinMax(0x47E, 0x499); - - public MelisandesHairDye(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041088; // Hair Dye - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - if (MondainsLegacy.CheckML(from)) - from.SendGump(new ConfirmGump(this)); - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1075085); // Requirement: Mondain's Legacy - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private class ConfirmGump : BaseConfirmGump - { - private readonly Item m_Item; - - public ConfirmGump(Item item) => m_Item = item; - - public override int TitleNumber => 1074395; //
Use Permanent Hair Dye
- - public override int LabelNumber => - 1074396; // This special hair dye is made of a unique mixture of leaves, permanently changing one's hair color until another dye is used. - - public override void Confirm(Mobile from) - { - if (m_Item?.Deleted == false && m_Item.IsChildOf(from.Backpack)) - { - if (from.HairItemID != 0) - { - from.HairHue = m_Item.Hue; - from.PlaySound(0x240); - from.SendLocalizedMessage(502622); // You dye your hair. - m_Item.Delete(); - } - else - { - from.SendLocalizedMessage(502623); // You have no hair to dye and you cannot use this. - } - } - else - { - from.SendLocalizedMessage(1073461); // You don't have enough dye. - } - } - - public override void Refuse(Mobile from) - { - from.SendLocalizedMessage(502620); // You decide not to dye your hair. - } - } - } -} +using Server.Gumps; + +namespace Server.Items +{ + public class MelisandesHairDye : Item + { + [Constructible] + public MelisandesHairDye() : base(0xEFF) => Hue = Utility.RandomMinMax(0x47E, 0x499); + + public MelisandesHairDye(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041088; // Hair Dye + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + if (MondainsLegacy.CheckML(from)) + from.SendGump(new ConfirmGump(this)); + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1075085); // Requirement: Mondain's Legacy + } + + 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(); + } + + private class ConfirmGump : BaseConfirmGump + { + private readonly Item m_Item; + + public ConfirmGump(Item item) => m_Item = item; + + public override int TitleNumber => 1074395; //
Use Permanent Hair Dye
+ + public override int LabelNumber => + 1074396; // This special hair dye is made of a unique mixture of leaves, permanently changing one's hair color until another dye is used. + + public override void Confirm(Mobile from) + { + if (m_Item?.Deleted == false && m_Item.IsChildOf(from.Backpack)) + { + if (from.HairItemID != 0) + { + from.HairHue = m_Item.Hue; + from.PlaySound(0x240); + from.SendLocalizedMessage(502622); // You dye your hair. + m_Item.Delete(); + } + else + { + from.SendLocalizedMessage(502623); // You have no hair to dye and you cannot use this. + } + } + else + { + from.SendLocalizedMessage(1073461); // You don't have enough dye. + } + } + + public override void Refuse(Mobile from) + { + from.SendLocalizedMessage(502620); // You decide not to dye your hair. + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/Blighted Grove/SalivasFeather.cs b/Projects/UOContent/Items/Misc/Blighted Grove/SalivasFeather.cs index fb58edc70..250b89406 100644 --- a/Projects/UOContent/Items/Misc/Blighted Grove/SalivasFeather.cs +++ b/Projects/UOContent/Items/Misc/Blighted Grove/SalivasFeather.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class SalivasFeather : Item - { - [Constructible] - public SalivasFeather() : base(0x1020) - { - LootType = LootType.Blessed; - Hue = 0x5C; - } - - public SalivasFeather(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074234; // Saliva's Feather - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SalivasFeather : Item + { + [Constructible] + public SalivasFeather() : base(0x1020) + { + LootType = LootType.Blessed; + Hue = 0x5C; + } + + public SalivasFeather(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074234; // Saliva's Feather + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Blighted Grove/SamplesOfCorruptedWater.cs b/Projects/UOContent/Items/Misc/Blighted Grove/SamplesOfCorruptedWater.cs index f4478aed4..6da47d10b 100644 --- a/Projects/UOContent/Items/Misc/Blighted Grove/SamplesOfCorruptedWater.cs +++ b/Projects/UOContent/Items/Misc/Blighted Grove/SamplesOfCorruptedWater.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class SamplesOfCorruptedWater : Item - { - [Constructible] - public SamplesOfCorruptedWater() : base(0xEFE) => LootType = LootType.Blessed; - - public SamplesOfCorruptedWater(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074999; // samples of corrupted water - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SamplesOfCorruptedWater : Item + { + [Constructible] + public SamplesOfCorruptedWater() : base(0xEFE) => LootType = LootType.Blessed; + + public SamplesOfCorruptedWater(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074999; // samples of corrupted water + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Blighted Grove/TaintedSeeds.cs b/Projects/UOContent/Items/Misc/Blighted Grove/TaintedSeeds.cs index 285dfe665..3e068fb5f 100644 --- a/Projects/UOContent/Items/Misc/Blighted Grove/TaintedSeeds.cs +++ b/Projects/UOContent/Items/Misc/Blighted Grove/TaintedSeeds.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class TaintedSeeds : Item - { - [Constructible] - public TaintedSeeds() : base(0xDFA) - { - LootType = LootType.Blessed; - Hue = 0x48; // TODO check - } - - public TaintedSeeds(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074233; // Tainted Seeds - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TaintedSeeds : Item + { + [Constructible] + public TaintedSeeds() : base(0xDFA) + { + LootType = LootType.Blessed; + Hue = 0x48; // TODO check + } + + public TaintedSeeds(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074233; // Tainted Seeds + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Blighted Grove/ThorvaldsMedallion.cs b/Projects/UOContent/Items/Misc/Blighted Grove/ThorvaldsMedallion.cs index 57cccfa4c..bdba9ebc8 100644 --- a/Projects/UOContent/Items/Misc/Blighted Grove/ThorvaldsMedallion.cs +++ b/Projects/UOContent/Items/Misc/Blighted Grove/ThorvaldsMedallion.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class ThorvaldsMedallion : Item - { - [Constructible] - public ThorvaldsMedallion() : base(0x2AAA) - { - LootType = LootType.Blessed; - Hue = 0x47F; // TODO check - } - - public ThorvaldsMedallion(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074232; // Thorvald's Medallion - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ThorvaldsMedallion : Item + { + [Constructible] + public ThorvaldsMedallion() : base(0x2AAA) + { + LootType = LootType.Blessed; + Hue = 0x47F; // TODO check + } + + public ThorvaldsMedallion(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074232; // Thorvald's Medallion + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Blighted Grove/ThrashersTail.cs b/Projects/UOContent/Items/Misc/Blighted Grove/ThrashersTail.cs index 84147bec8..e77dbc5ee 100644 --- a/Projects/UOContent/Items/Misc/Blighted Grove/ThrashersTail.cs +++ b/Projects/UOContent/Items/Misc/Blighted Grove/ThrashersTail.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class ThrashersTail : Item - { - [Constructible] - public ThrashersTail() : base(0x1A9D) - { - LootType = LootType.Blessed; - Hue = 0x455; - } - - public ThrashersTail(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074230; // Thrasher's Tail - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ThrashersTail : Item + { + [Constructible] + public ThrashersTail() : base(0x1A9D) + { + LootType = LootType.Blessed; + Hue = 0x455; + } + + public ThrashersTail(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074230; // Thrasher's Tail + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Blocker.cs b/Projects/UOContent/Items/Misc/Blocker.cs index a1b07b0d3..5f95fbe33 100644 --- a/Projects/UOContent/Items/Misc/Blocker.cs +++ b/Projects/UOContent/Items/Misc/Blocker.cs @@ -1,102 +1,102 @@ -using Server.Network; - -namespace Server.Items -{ - public class Blocker : Item - { - [Constructible] - public Blocker() : base(0x21A4) => Movable = false; - - public Blocker(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 503057; // Impassable! - - protected override Packet GetWorldPacketFor(NetState state) - { - Mobile mob = state.Mobile; - - if (mob?.AccessLevel >= AccessLevel.GameMaster) - return new GMItemPacket(this); - - return base.GetWorldPacketFor(state); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public sealed class GMItemPacket : Packet - { - public GMItemPacket(Item item) : base(0x1A) - { - EnsureCapacity(20); - - // 14 base length - // +2 - Amount - // +2 - Hue - // +1 - Flags - - uint serial = item.Serial.Value; - int itemID = 0x1183; - int amount = item.Amount; - Point3D loc = item.Location; - int x = loc.X; - int y = loc.Y; - int hue = item.Hue; - int flags = item.GetPacketFlags(); - int direction = (int)item.Direction; - - if (amount != 0) - serial |= 0x80000000; - else - serial &= 0x7FFFFFFF; - - Stream.Write(serial); - Stream.Write((short)(itemID & 0x7FFF)); - - if (amount != 0) - Stream.Write((short)amount); - - x &= 0x7FFF; - - if (direction != 0) - x |= 0x8000; - - Stream.Write((short)x); - - y &= 0x3FFF; - - if (hue != 0) - y |= 0x8000; - - if (flags != 0) - y |= 0x4000; - - Stream.Write((short)y); - - if (direction != 0) - Stream.Write((byte)direction); - - Stream.Write((sbyte)loc.Z); - - if (hue != 0) - Stream.Write((ushort)hue); - - if (flags != 0) - Stream.Write((byte)flags); - } - } - } -} +using Server.Network; + +namespace Server.Items +{ + public class Blocker : Item + { + [Constructible] + public Blocker() : base(0x21A4) => Movable = false; + + public Blocker(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 503057; // Impassable! + + protected override Packet GetWorldPacketFor(NetState state) + { + var mob = state.Mobile; + + if (mob?.AccessLevel >= AccessLevel.GameMaster) + return new GMItemPacket(this); + + return base.GetWorldPacketFor(state); + } + + 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(); + } + + public sealed class GMItemPacket : Packet + { + public GMItemPacket(Item item) : base(0x1A) + { + EnsureCapacity(20); + + // 14 base length + // +2 - Amount + // +2 - Hue + // +1 - Flags + + var serial = item.Serial.Value; + var itemID = 0x1183; + var amount = item.Amount; + var loc = item.Location; + var x = loc.X; + var y = loc.Y; + var hue = item.Hue; + var flags = item.GetPacketFlags(); + var direction = (int)item.Direction; + + if (amount != 0) + serial |= 0x80000000; + else + serial &= 0x7FFFFFFF; + + Stream.Write(serial); + Stream.Write((short)(itemID & 0x7FFF)); + + if (amount != 0) + Stream.Write((short)amount); + + x &= 0x7FFF; + + if (direction != 0) + x |= 0x8000; + + Stream.Write((short)x); + + y &= 0x3FFF; + + if (hue != 0) + y |= 0x8000; + + if (flags != 0) + y |= 0x4000; + + Stream.Write((short)y); + + if (direction != 0) + Stream.Write((byte)direction); + + Stream.Write((sbyte)loc.Z); + + if (hue != 0) + Stream.Write((ushort)hue); + + if (flags != 0) + Stream.Write((byte)flags); + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/Blood.cs b/Projects/UOContent/Items/Misc/Blood.cs index cae0cb1c6..e551fc5e6 100644 --- a/Projects/UOContent/Items/Misc/Blood.cs +++ b/Projects/UOContent/Items/Misc/Blood.cs @@ -1,56 +1,56 @@ -using System; - -namespace Server.Items -{ - public class Blood : Item - { - [Constructible] - public Blood() : this(Utility.RandomList(0x1645, 0x122A, 0x122B, 0x122C, 0x122D, 0x122E, 0x122F)) - { - } - - [Constructible] - public Blood(int itemID) : base(itemID) - { - Movable = false; - - new InternalTimer(this).Start(); - } - - public Blood(Serial serial) : base(serial) - { - new InternalTimer(this).Start(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private class InternalTimer : Timer - { - private readonly Item m_Blood; - - public InternalTimer(Item blood) : base(TimeSpan.FromSeconds(5.0)) - { - Priority = TimerPriority.OneSecond; - - m_Blood = blood; - } - - protected override void OnTick() - { - m_Blood.Delete(); - } - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class Blood : Item + { + [Constructible] + public Blood() : this(Utility.RandomList(0x1645, 0x122A, 0x122B, 0x122C, 0x122D, 0x122E, 0x122F)) + { + } + + [Constructible] + public Blood(int itemID) : base(itemID) + { + Movable = false; + + new InternalTimer(this).Start(); + } + + public Blood(Serial serial) : base(serial) + { + new InternalTimer(this).Start(); + } + + 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(); + } + + private class InternalTimer : Timer + { + private readonly Item m_Blood; + + public InternalTimer(Item blood) : base(TimeSpan.FromSeconds(5.0)) + { + Priority = TimerPriority.OneSecond; + + m_Blood = blood; + } + + protected override void OnTick() + { + m_Blood.Delete(); + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/Bola.cs b/Projects/UOContent/Items/Misc/Bola.cs index bd4f7d0d0..37b108b31 100644 --- a/Projects/UOContent/Items/Misc/Bola.cs +++ b/Projects/UOContent/Items/Misc/Bola.cs @@ -1,209 +1,217 @@ -using System; -using Server.Mobiles; -using Server.Network; -using Server.Spells.Ninjitsu; -using Server.Targeting; - -namespace Server.Items -{ - public class Bola : Item - { - [Constructible] - public Bola(int amount = 1) : base(0x26AC) - { - Weight = 4.0; - Stackable = true; - Amount = amount; - } - - public Bola(Serial serial) : base(serial) - { - } - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1040019); // The bola must be in your pack to use it. - } - else if (!from.CanBeginAction()) - { - from.SendLocalizedMessage(1049624); // You have to wait a few moments before you can use another bola! - } - else if (from.Target is BolaTarget) - { - from.SendLocalizedMessage(1049631); // This bola is already being used. - } - else if (!HasFreeHands(from)) - { - from.SendLocalizedMessage(1040015); // Your hands must be free to use this - } - else if (from.Mounted) - { - from.SendLocalizedMessage(1040016); // You cannot use this while riding a mount - } - else if (AnimalForm.UnderTransformation(from)) - { - from.SendLocalizedMessage(1070902); // You can't use this while in an animal form! - } - else - { - EtherealMount.StopMounting(from); - - from.Target = new BolaTarget(this); - from.LocalOverheadMessage(MessageType.Emote, 0x3B2, 1049632); // * You begin to swing the bola...* - from.NonlocalOverheadMessage(MessageType.Emote, 0x3B2, 1049633, - from.Name); // ~1_NAME~ begins to menacingly swing a bola... - } - } - - private static void FinishThrow(Mobile from, Mobile to) - { - if (Core.AOS) - new Bola().MoveToWorld(to.Location, to.Map); - - if (to is ChaosDragoon || to is ChaosDragoonElite) - from.SendLocalizedMessage(1042047); // You fail to knock the rider from its mount. - - IMount mt = to.Mount; - if (mt != null && !(to is ChaosDragoon || to is ChaosDragoonElite)) - mt.Rider = null; - - if (to is PlayerMobile mobile) - { - if (AnimalForm.UnderTransformation(mobile)) - mobile.SendLocalizedMessage(1114066, from.Name); // ~1_NAME~ knocked you out of animal form! - else if (mobile.Mounted) mobile.SendLocalizedMessage(1040023); // You have been knocked off of your mount! - - mobile.SetMountBlock(BlockMountType.Dazed, TimeSpan.FromSeconds(Core.ML ? 10 : 3), true); - } - - if (Core.AOS) /* only failsafe, attacker should already be dismounted */ - (from as PlayerMobile)?.SetMountBlock(BlockMountType.BolaRecovery, TimeSpan.FromSeconds(Core.ML ? 10 : 3), - true); - - to.Damage(1); - - Timer.DelayCall(TimeSpan.FromSeconds(2.0), from.EndAction); - } - - private static bool HasFreeHands(Mobile from) - { - Item one = from.FindItemOnLayer(Layer.OneHanded); - Item two = from.FindItemOnLayer(Layer.TwoHanded); - - if (Core.SE) - { - Container pack = from.Backpack; - - if (pack != null) - { - if (one?.Movable == true) - { - pack.DropItem(one); - one = null; - } - - if (two?.Movable == true) - { - pack.DropItem(two); - two = null; - } - } - } - else if (Core.AOS) - { - if (one?.Movable == true) - { - from.AddToBackpack(one); - one = null; - } - - if (two?.Movable == true) - { - from.AddToBackpack(two); - two = null; - } - } - - return one == null && two == null; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public class BolaTarget : Target - { - private readonly Bola m_Bola; - - public BolaTarget(Bola bola) : base(8, false, TargetFlags.Harmful) => m_Bola = bola; - - protected override void OnTarget(Mobile from, object obj) - { - if (m_Bola.Deleted) - return; - - if (obj is Mobile to) - { - if (!m_Bola.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1040019); // The bola must be in your pack to use it. - } - else if (!HasFreeHands(from)) - { - from.SendLocalizedMessage(1040015); // Your hands must be free to use this - } - else if (from.Mounted) - { - from.SendLocalizedMessage(1040016); // You cannot use this while riding a mount - } - else if (AnimalForm.UnderTransformation(from)) - { - from.SendLocalizedMessage(1070902); // You can't use this while in an animal form! - } - else if (!to.Mounted && !AnimalForm.UnderTransformation(to)) - { - from.SendLocalizedMessage(1049628); // You have no reason to throw a bola at that. - } - else if (!from.CanBeHarmful(to)) - { - } - else if (from.BeginAction()) - { - EtherealMount.StopMounting(from); - - from.DoHarmful(to); - - m_Bola.Consume(); - - from.Direction = from.GetDirectionTo(to); - from.Animate(11, 5, 1, true, false, 0); - from.MovingEffect(to, 0x26AC, 10, 0, false, false); - - Timer.DelayCall(TimeSpan.FromSeconds(0.5), FinishThrow, from, to); - } - else - { - from.SendLocalizedMessage( - 1049624); // You have to wait a few moments before you can use another bola! - } - } - else - { - from.SendLocalizedMessage(1049629); // You cannot throw a bola at that. - } - } - } - } -} +using System; +using Server.Mobiles; +using Server.Network; +using Server.Spells.Ninjitsu; +using Server.Targeting; + +namespace Server.Items +{ + public class Bola : Item + { + [Constructible] + public Bola(int amount = 1) : base(0x26AC) + { + Weight = 4.0; + Stackable = true; + Amount = amount; + } + + public Bola(Serial serial) : base(serial) + { + } + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1040019); // The bola must be in your pack to use it. + } + else if (!from.CanBeginAction()) + { + from.SendLocalizedMessage(1049624); // You have to wait a few moments before you can use another bola! + } + else if (from.Target is BolaTarget) + { + from.SendLocalizedMessage(1049631); // This bola is already being used. + } + else if (!HasFreeHands(from)) + { + from.SendLocalizedMessage(1040015); // Your hands must be free to use this + } + else if (from.Mounted) + { + from.SendLocalizedMessage(1040016); // You cannot use this while riding a mount + } + else if (AnimalForm.UnderTransformation(from)) + { + from.SendLocalizedMessage(1070902); // You can't use this while in an animal form! + } + else + { + EtherealMount.StopMounting(from); + + from.Target = new BolaTarget(this); + from.LocalOverheadMessage(MessageType.Emote, 0x3B2, 1049632); // * You begin to swing the bola...* + from.NonlocalOverheadMessage( + MessageType.Emote, + 0x3B2, + 1049633, + from.Name + ); // ~1_NAME~ begins to menacingly swing a bola... + } + } + + private static void FinishThrow(Mobile from, Mobile to) + { + if (Core.AOS) + new Bola().MoveToWorld(to.Location, to.Map); + + if (to is ChaosDragoon || to is ChaosDragoonElite) + from.SendLocalizedMessage(1042047); // You fail to knock the rider from its mount. + + var mt = to.Mount; + if (mt != null && !(to is ChaosDragoon || to is ChaosDragoonElite)) + mt.Rider = null; + + if (to is PlayerMobile mobile) + { + if (AnimalForm.UnderTransformation(mobile)) + mobile.SendLocalizedMessage(1114066, from.Name); // ~1_NAME~ knocked you out of animal form! + else if (mobile.Mounted) mobile.SendLocalizedMessage(1040023); // You have been knocked off of your mount! + + mobile.SetMountBlock(BlockMountType.Dazed, TimeSpan.FromSeconds(Core.ML ? 10 : 3), true); + } + + if (Core.AOS) /* only failsafe, attacker should already be dismounted */ + (from as PlayerMobile)?.SetMountBlock( + BlockMountType.BolaRecovery, + TimeSpan.FromSeconds(Core.ML ? 10 : 3), + true + ); + + to.Damage(1); + + Timer.DelayCall(TimeSpan.FromSeconds(2.0), from.EndAction); + } + + private static bool HasFreeHands(Mobile from) + { + var one = from.FindItemOnLayer(Layer.OneHanded); + var two = from.FindItemOnLayer(Layer.TwoHanded); + + if (Core.SE) + { + var pack = from.Backpack; + + if (pack != null) + { + if (one?.Movable == true) + { + pack.DropItem(one); + one = null; + } + + if (two?.Movable == true) + { + pack.DropItem(two); + two = null; + } + } + } + else if (Core.AOS) + { + if (one?.Movable == true) + { + from.AddToBackpack(one); + one = null; + } + + if (two?.Movable == true) + { + from.AddToBackpack(two); + two = null; + } + } + + return one == null && two == null; + } + + 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(); + } + + public class BolaTarget : Target + { + private readonly Bola m_Bola; + + public BolaTarget(Bola bola) : base(8, false, TargetFlags.Harmful) => m_Bola = bola; + + protected override void OnTarget(Mobile from, object obj) + { + if (m_Bola.Deleted) + return; + + if (obj is Mobile to) + { + if (!m_Bola.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1040019); // The bola must be in your pack to use it. + } + else if (!HasFreeHands(from)) + { + from.SendLocalizedMessage(1040015); // Your hands must be free to use this + } + else if (from.Mounted) + { + from.SendLocalizedMessage(1040016); // You cannot use this while riding a mount + } + else if (AnimalForm.UnderTransformation(from)) + { + from.SendLocalizedMessage(1070902); // You can't use this while in an animal form! + } + else if (!to.Mounted && !AnimalForm.UnderTransformation(to)) + { + from.SendLocalizedMessage(1049628); // You have no reason to throw a bola at that. + } + else if (!from.CanBeHarmful(to)) + { + } + else if (from.BeginAction()) + { + EtherealMount.StopMounting(from); + + from.DoHarmful(to); + + m_Bola.Consume(); + + from.Direction = from.GetDirectionTo(to); + from.Animate(11, 5, 1, true, false, 0); + from.MovingEffect(to, 0x26AC, 10, 0, false, false); + + Timer.DelayCall(TimeSpan.FromSeconds(0.5), FinishThrow, from, to); + } + else + { + from.SendLocalizedMessage( + 1049624 + ); // You have to wait a few moments before you can use another bola! + } + } + else + { + from.SendLocalizedMessage(1049629); // You cannot throw a bola at that. + } + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/BolaBall.cs b/Projects/UOContent/Items/Misc/BolaBall.cs index af41364d6..b790a8f58 100644 --- a/Projects/UOContent/Items/Misc/BolaBall.cs +++ b/Projects/UOContent/Items/Misc/BolaBall.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class BolaBall : Item - { - [Constructible] - public BolaBall(int amount = 1) : base(0xE73) - { - Weight = 4.0; - Stackable = true; - Amount = amount; - Hue = 0x8AC; - } - - public BolaBall(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class BolaBall : Item + { + [Constructible] + public BolaBall(int amount = 1) : base(0xE73) + { + Weight = 4.0; + Stackable = true; + Amount = amount; + Hue = 0x8AC; + } + + public BolaBall(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/BulletinBoards.cs b/Projects/UOContent/Items/Misc/BulletinBoards.cs index a83adc79f..68eb99b37 100644 --- a/Projects/UOContent/Items/Misc/BulletinBoards.cs +++ b/Projects/UOContent/Items/Misc/BulletinBoards.cs @@ -1,600 +1,600 @@ -using System; -using System.Collections.Generic; -using Server.Network; -using Server.Targeting; - -namespace Server.Items -{ - [Flippable(0x1E5E, 0x1E5F)] - public class BulletinBoard : BaseBulletinBoard - { - [Constructible] - public BulletinBoard() : base(0x1E5E) - { - } - - public BulletinBoard(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public abstract class BaseBulletinBoard : Item - { - // Threads will be removed six hours after the last post was made - private static readonly TimeSpan ThreadDeletionTime = TimeSpan.FromHours(6.0); - - // A player may only create a thread once every two minutes - private static readonly TimeSpan ThreadCreateTime = TimeSpan.FromMinutes(2.0); - - // A player may only reply once every thirty seconds - private static readonly TimeSpan ThreadReplyTime = TimeSpan.FromSeconds(30.0); - - public BaseBulletinBoard(int itemID) : base(itemID) - { - BoardName = "bulletin board"; - Movable = false; - } - - public BaseBulletinBoard(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public string BoardName { get; set; } - - public static bool CheckTime(DateTime time, TimeSpan range) => time + range < DateTime.UtcNow; - - public static string FormatTS(TimeSpan ts) - { - int totalSeconds = (int)ts.TotalSeconds; - int seconds = totalSeconds % 60; - int minutes = totalSeconds / 60; - - if (minutes != 0 && seconds != 0) - return $"{minutes} minute{(minutes == 1 ? "" : "s")} and {seconds} second{(seconds == 1 ? "" : "s")}"; - if (minutes != 0) - return $"{minutes} minute{(minutes == 1 ? "" : "s")}"; - return $"{seconds} second{(seconds == 1 ? "" : "s")}"; - } - - public virtual void Cleanup() - { - List items = Items; - - for (int i = items.Count - 1; i >= 0; --i) - { - if (i >= items.Count) - continue; - - if (!(items[i] is BulletinMessage msg)) - continue; - - if (msg.Thread == null && CheckTime(msg.LastPostTime, ThreadDeletionTime)) - { - msg.Delete(); - RecurseDelete(msg); // A root-level thread has expired - } - } - } - - private void RecurseDelete(BulletinMessage msg) - { - List found = new List(); - List items = Items; - - for (int i = items.Count - 1; i >= 0; --i) - { - if (i >= items.Count) - continue; - - if (!(items[i] is BulletinMessage check)) - continue; - - if (check.Thread == msg) - { - check.Delete(); - found.Add(check); - } - } - - for (int i = 0; i < found.Count; ++i) - RecurseDelete((BulletinMessage)found[i]); - } - - public virtual bool GetLastPostTime(Mobile poster, bool onlyCheckRoot, ref DateTime lastPostTime) - { - List items = Items; - bool wasSet = false; - - for (int i = 0; i < items.Count; ++i) - { - if (!(items[i] is BulletinMessage msg) || msg.Poster != poster) - continue; - - if (onlyCheckRoot && msg.Thread != null) - continue; - - if (msg.Time > lastPostTime) - { - wasSet = true; - lastPostTime = msg.Time; - } - } - - return wasSet; - } - - public override void OnDoubleClick(Mobile from) - { - if (CheckRange(from)) - { - Cleanup(); - - NetState state = from.NetState; - - state.Send(new BBDisplayBoard(this)); - if (state.ContainerGridLines) - state.Send(new ContainerContent6017(from, this)); - else - state.Send(new ContainerContent(from, this)); - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - } - - public virtual bool CheckRange(Mobile from) - { - if (from.AccessLevel >= AccessLevel.GameMaster) - return true; - - return from.Map == Map && from.InRange(GetWorldLocation(), 2); - } - - public void PostMessage(Mobile from, BulletinMessage thread, string subject, string[] lines) - { - if (thread != null) - thread.LastPostTime = DateTime.UtcNow; - - AddItem(new BulletinMessage(from, thread, subject, lines)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(BoardName); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - BoardName = reader.ReadString(); - break; - } - } - } - - public static void Initialize() - { - PacketHandlers.Register(0x71, 0, true, BBClientRequest); - } - - public static void BBClientRequest(NetState state, PacketReader pvSrc) - { - Mobile from = state.Mobile; - - int packetID = pvSrc.ReadByte(); - - if (!(World.FindItem(pvSrc.ReadUInt32()) is BaseBulletinBoard board) || !board.CheckRange(from)) - return; - - switch (packetID) - { - case 3: - BBRequestContent(from, board, pvSrc); - break; - case 4: - BBRequestHeader(from, board, pvSrc); - break; - case 5: - BBPostMessage(from, board, pvSrc); - break; - case 6: - BBRemoveMessage(from, board, pvSrc); - break; - } - } - - public static void BBRequestContent(Mobile from, BaseBulletinBoard board, PacketReader pvSrc) - { - if (!(World.FindItem(pvSrc.ReadUInt32()) is BulletinMessage msg) || msg.Parent != board) - return; - - from.Send(new BBMessageContent(board, msg)); - } - - public static void BBRequestHeader(Mobile from, BaseBulletinBoard board, PacketReader pvSrc) - { - if (!(World.FindItem(pvSrc.ReadUInt32()) is BulletinMessage msg) || msg.Parent != board) - return; - - from.Send(new BBMessageHeader(board, msg)); - } - - public static void BBPostMessage(Mobile from, BaseBulletinBoard board, PacketReader pvSrc) - { - BulletinMessage thread = World.FindItem(pvSrc.ReadUInt32()) as BulletinMessage; - - if (thread != null && thread.Parent != board) - thread = null; - - int breakout = 0; - - while (thread?.Thread != null && breakout++ < 10) - thread = thread.Thread; - - DateTime lastPostTime = DateTime.MinValue; - - if (board.GetLastPostTime(from, thread == null, ref lastPostTime)) - if (!CheckTime(lastPostTime, thread == null ? ThreadCreateTime : ThreadReplyTime)) - { - if (thread == null) - from.SendMessage("You must wait {0} before creating a new thread.", FormatTS(ThreadCreateTime)); - else - from.SendMessage("You must wait {0} before replying to another thread.", FormatTS(ThreadReplyTime)); - - return; - } - - string subject = pvSrc.ReadUTF8StringSafe(pvSrc.ReadByte()); - - if (subject.Length == 0) - return; - - string[] lines = new string[pvSrc.ReadByte()]; - - if (lines.Length == 0) - return; - - for (int i = 0; i < lines.Length; ++i) - lines[i] = pvSrc.ReadUTF8StringSafe(pvSrc.ReadByte()); - - board.PostMessage(from, thread, subject, lines); - } - - public static void BBRemoveMessage(Mobile from, BaseBulletinBoard board, PacketReader pvSrc) - { - if (!(World.FindItem(pvSrc.ReadUInt32()) is BulletinMessage msg) || msg.Parent != board) - return; - - if (from.AccessLevel < AccessLevel.GameMaster && msg.Poster != from) - return; - - msg.Delete(); - } - } - - public struct BulletinEquip - { - public int itemID; - public int hue; - - public BulletinEquip(int itemID, int hue) - { - this.itemID = itemID; - this.hue = hue; - } - } - - public class BulletinMessage : Item - { - public BulletinMessage(Mobile poster, BulletinMessage thread, string subject, string[] lines) : base(0xEB0) - { - Movable = false; - - Poster = poster; - Subject = subject; - Time = DateTime.UtcNow; - LastPostTime = Time; - Thread = thread; - PostedName = Poster.Name; - PostedBody = Poster.Body; - PostedHue = Poster.Hue; - Lines = lines; - - List list = new List(); - - for (int i = 0; i < poster.Items.Count; ++i) - { - Item item = poster.Items[i]; - - if (item.Layer >= Layer.OneHanded && item.Layer <= Layer.Mount) - list.Add(new BulletinEquip(item.ItemID, item.Hue)); - } - - PostedEquip = list.ToArray(); - } - - public BulletinMessage(Serial serial) : base(serial) - { - } - - public Mobile Poster { get; private set; } - - public BulletinMessage Thread { get; private set; } - - public string Subject { get; private set; } - - public DateTime Time { get; private set; } - - public DateTime LastPostTime { get; set; } - - public string PostedName { get; private set; } - - public int PostedBody { get; private set; } - - public int PostedHue { get; private set; } - - public BulletinEquip[] PostedEquip { get; private set; } - - public string[] Lines { get; private set; } - - public string GetTimeAsString() => Time.ToString("MMM dd, yyyy"); - - public override bool CheckTarget(Mobile from, Target targ, object targeted) => false; - - public override bool IsAccessibleTo(Mobile check) => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(Poster); - writer.Write(Subject); - writer.Write(Time); - writer.Write(LastPostTime); - writer.Write(Thread != null); - writer.Write(Thread); - writer.Write(PostedName); - writer.Write(PostedBody); - writer.Write(PostedHue); - - writer.Write(PostedEquip.Length); - - for (int i = 0; i < PostedEquip.Length; ++i) - { - writer.Write(PostedEquip[i].itemID); - writer.Write(PostedEquip[i].hue); - } - - writer.Write(Lines.Length); - - for (int i = 0; i < Lines.Length; ++i) - writer.Write(Lines[i]); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - case 0: - { - Poster = reader.ReadMobile(); - Subject = reader.ReadString(); - Time = reader.ReadDateTime(); - LastPostTime = reader.ReadDateTime(); - bool hasThread = reader.ReadBool(); - Thread = reader.ReadItem() as BulletinMessage; - PostedName = reader.ReadString(); - PostedBody = reader.ReadInt(); - PostedHue = reader.ReadInt(); - - PostedEquip = new BulletinEquip[reader.ReadInt()]; - - for (int i = 0; i < PostedEquip.Length; ++i) - { - PostedEquip[i].itemID = reader.ReadInt(); - PostedEquip[i].hue = reader.ReadInt(); - } - - Lines = new string[reader.ReadInt()]; - - for (int i = 0; i < Lines.Length; ++i) - Lines[i] = reader.ReadString(); - - if (hasThread && Thread == null) - Delete(); - - if (version == 0) - ValidationQueue.Add(this); - - break; - } - } - } - - public void Validate() - { - if ((Parent as BulletinBoard)?.Items.Contains(this) == false) - Delete(); - } - } - - public class BBDisplayBoard : Packet - { - public BBDisplayBoard(BaseBulletinBoard board) : base(0x71) - { - EnsureCapacity(38); - - byte[] buffer = Utility.UTF8.GetBytes(board.BoardName ?? ""); - - Stream.Write((byte)0x00); // PacketID - Stream.Write(board.Serial); // Bulletin board serial - - // Bulletin board name - if (buffer.Length >= 29) - { - Stream.Write(buffer, 0, 29); - Stream.Write((byte)0); - } - else - { - Stream.Write(buffer, 0, buffer.Length); - Stream.Fill(30 - buffer.Length); - } - } - } - - public class BBMessageHeader : Packet - { - public BBMessageHeader(BaseBulletinBoard board, BulletinMessage msg) : base(0x71) - { - string poster = SafeString(msg.PostedName); - string subject = SafeString(msg.Subject); - string time = SafeString(msg.GetTimeAsString()); - - EnsureCapacity(22 + poster.Length + subject.Length + time.Length); - - Stream.Write((byte)0x01); // PacketID - Stream.Write(board.Serial); // Bulletin board serial - Stream.Write(msg.Serial); // Message serial - - BulletinMessage thread = msg.Thread; - - if (thread == null) - Stream.Write(0); // Thread serial--root - else - Stream.Write(thread.Serial); // Thread serial--parent - - WriteString(poster); - WriteString(subject); - WriteString(time); - } - - public void WriteString(string v) - { - byte[] buffer = Utility.UTF8.GetBytes(v); - int len = buffer.Length + 1; - - if (len > 255) - len = 255; - - Stream.Write((byte)len); - Stream.Write(buffer, 0, len - 1); - Stream.Write((byte)0); - } - - public string SafeString(string v) => v ?? string.Empty; - } - - public class BBMessageContent : Packet - { - public BBMessageContent(BaseBulletinBoard board, BulletinMessage msg) : base(0x71) - { - string poster = SafeString(msg.PostedName); - string subject = SafeString(msg.Subject); - string time = SafeString(msg.GetTimeAsString()); - - EnsureCapacity(22 + poster.Length + subject.Length + time.Length); - - Stream.Write((byte)0x02); // PacketID - Stream.Write(board.Serial); // Bulletin board serial - Stream.Write(msg.Serial); // Message serial - - WriteString(poster); - WriteString(subject); - WriteString(time); - - Stream.Write((short)msg.PostedBody); - Stream.Write((short)msg.PostedHue); - - int len = msg.PostedEquip.Length; - - if (len > 255) - len = 255; - - Stream.Write((byte)len); - - for (int i = 0; i < len; ++i) - { - BulletinEquip eq = msg.PostedEquip[i]; - - Stream.Write((short)eq.itemID); - Stream.Write((short)eq.hue); - } - - len = msg.Lines.Length; - - if (len > 255) - len = 255; - - Stream.Write((byte)len); - - for (int i = 0; i < len; ++i) - WriteString(msg.Lines[i], true); - } - - public void WriteString(string v) - { - WriteString(v, false); - } - - public void WriteString(string v, bool padding) - { - byte[] buffer = Utility.UTF8.GetBytes(v); - int tail = padding ? 2 : 1; - int len = buffer.Length + tail; - - if (len > 255) - len = 255; - - Stream.Write((byte)len); - Stream.Write(buffer, 0, len - tail); - - if (padding) - Stream.Write((short)0); // padding compensates for a client bug - else - Stream.Write((byte)0); - } - - public string SafeString(string v) - { - if (v == null) - return string.Empty; - - return v; - } - } -} +using System; +using System.Collections.Generic; +using Server.Network; +using Server.Targeting; + +namespace Server.Items +{ + [Flippable(0x1E5E, 0x1E5F)] + public class BulletinBoard : BaseBulletinBoard + { + [Constructible] + public BulletinBoard() : base(0x1E5E) + { + } + + public BulletinBoard(Serial serial) : base(serial) + { + } + + 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 abstract class BaseBulletinBoard : Item + { + // Threads will be removed six hours after the last post was made + private static readonly TimeSpan ThreadDeletionTime = TimeSpan.FromHours(6.0); + + // A player may only create a thread once every two minutes + private static readonly TimeSpan ThreadCreateTime = TimeSpan.FromMinutes(2.0); + + // A player may only reply once every thirty seconds + private static readonly TimeSpan ThreadReplyTime = TimeSpan.FromSeconds(30.0); + + public BaseBulletinBoard(int itemID) : base(itemID) + { + BoardName = "bulletin board"; + Movable = false; + } + + public BaseBulletinBoard(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public string BoardName { get; set; } + + public static bool CheckTime(DateTime time, TimeSpan range) => time + range < DateTime.UtcNow; + + public static string FormatTS(TimeSpan ts) + { + var totalSeconds = (int)ts.TotalSeconds; + var seconds = totalSeconds % 60; + var minutes = totalSeconds / 60; + + if (minutes != 0 && seconds != 0) + return $"{minutes} minute{(minutes == 1 ? "" : "s")} and {seconds} second{(seconds == 1 ? "" : "s")}"; + if (minutes != 0) + return $"{minutes} minute{(minutes == 1 ? "" : "s")}"; + return $"{seconds} second{(seconds == 1 ? "" : "s")}"; + } + + public virtual void Cleanup() + { + var items = Items; + + for (var i = items.Count - 1; i >= 0; --i) + { + if (i >= items.Count) + continue; + + if (!(items[i] is BulletinMessage msg)) + continue; + + if (msg.Thread == null && CheckTime(msg.LastPostTime, ThreadDeletionTime)) + { + msg.Delete(); + RecurseDelete(msg); // A root-level thread has expired + } + } + } + + private void RecurseDelete(BulletinMessage msg) + { + var found = new List(); + var items = Items; + + for (var i = items.Count - 1; i >= 0; --i) + { + if (i >= items.Count) + continue; + + if (!(items[i] is BulletinMessage check)) + continue; + + if (check.Thread == msg) + { + check.Delete(); + found.Add(check); + } + } + + for (var i = 0; i < found.Count; ++i) + RecurseDelete((BulletinMessage)found[i]); + } + + public virtual bool GetLastPostTime(Mobile poster, bool onlyCheckRoot, ref DateTime lastPostTime) + { + var items = Items; + var wasSet = false; + + for (var i = 0; i < items.Count; ++i) + { + if (!(items[i] is BulletinMessage msg) || msg.Poster != poster) + continue; + + if (onlyCheckRoot && msg.Thread != null) + continue; + + if (msg.Time > lastPostTime) + { + wasSet = true; + lastPostTime = msg.Time; + } + } + + return wasSet; + } + + public override void OnDoubleClick(Mobile from) + { + if (CheckRange(from)) + { + Cleanup(); + + var state = from.NetState; + + state.Send(new BBDisplayBoard(this)); + if (state.ContainerGridLines) + state.Send(new ContainerContent6017(from, this)); + else + state.Send(new ContainerContent(from, this)); + } + else + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + } + + public virtual bool CheckRange(Mobile from) + { + if (from.AccessLevel >= AccessLevel.GameMaster) + return true; + + return from.Map == Map && from.InRange(GetWorldLocation(), 2); + } + + public void PostMessage(Mobile from, BulletinMessage thread, string subject, string[] lines) + { + if (thread != null) + thread.LastPostTime = DateTime.UtcNow; + + AddItem(new BulletinMessage(from, thread, subject, lines)); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(BoardName); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + BoardName = reader.ReadString(); + break; + } + } + } + + public static void Initialize() + { + PacketHandlers.Register(0x71, 0, true, BBClientRequest); + } + + public static void BBClientRequest(NetState state, PacketReader pvSrc) + { + var from = state.Mobile; + + int packetID = pvSrc.ReadByte(); + + if (!(World.FindItem(pvSrc.ReadUInt32()) is BaseBulletinBoard board) || !board.CheckRange(from)) + return; + + switch (packetID) + { + case 3: + BBRequestContent(from, board, pvSrc); + break; + case 4: + BBRequestHeader(from, board, pvSrc); + break; + case 5: + BBPostMessage(from, board, pvSrc); + break; + case 6: + BBRemoveMessage(from, board, pvSrc); + break; + } + } + + public static void BBRequestContent(Mobile from, BaseBulletinBoard board, PacketReader pvSrc) + { + if (!(World.FindItem(pvSrc.ReadUInt32()) is BulletinMessage msg) || msg.Parent != board) + return; + + from.Send(new BBMessageContent(board, msg)); + } + + public static void BBRequestHeader(Mobile from, BaseBulletinBoard board, PacketReader pvSrc) + { + if (!(World.FindItem(pvSrc.ReadUInt32()) is BulletinMessage msg) || msg.Parent != board) + return; + + from.Send(new BBMessageHeader(board, msg)); + } + + public static void BBPostMessage(Mobile from, BaseBulletinBoard board, PacketReader pvSrc) + { + var thread = World.FindItem(pvSrc.ReadUInt32()) as BulletinMessage; + + if (thread != null && thread.Parent != board) + thread = null; + + var breakout = 0; + + while (thread?.Thread != null && breakout++ < 10) + thread = thread.Thread; + + var lastPostTime = DateTime.MinValue; + + if (board.GetLastPostTime(from, thread == null, ref lastPostTime)) + if (!CheckTime(lastPostTime, thread == null ? ThreadCreateTime : ThreadReplyTime)) + { + if (thread == null) + from.SendMessage("You must wait {0} before creating a new thread.", FormatTS(ThreadCreateTime)); + else + from.SendMessage("You must wait {0} before replying to another thread.", FormatTS(ThreadReplyTime)); + + return; + } + + var subject = pvSrc.ReadUTF8StringSafe(pvSrc.ReadByte()); + + if (subject.Length == 0) + return; + + var lines = new string[pvSrc.ReadByte()]; + + if (lines.Length == 0) + return; + + for (var i = 0; i < lines.Length; ++i) + lines[i] = pvSrc.ReadUTF8StringSafe(pvSrc.ReadByte()); + + board.PostMessage(from, thread, subject, lines); + } + + public static void BBRemoveMessage(Mobile from, BaseBulletinBoard board, PacketReader pvSrc) + { + if (!(World.FindItem(pvSrc.ReadUInt32()) is BulletinMessage msg) || msg.Parent != board) + return; + + if (from.AccessLevel < AccessLevel.GameMaster && msg.Poster != from) + return; + + msg.Delete(); + } + } + + public struct BulletinEquip + { + public int itemID; + public int hue; + + public BulletinEquip(int itemID, int hue) + { + this.itemID = itemID; + this.hue = hue; + } + } + + public class BulletinMessage : Item + { + public BulletinMessage(Mobile poster, BulletinMessage thread, string subject, string[] lines) : base(0xEB0) + { + Movable = false; + + Poster = poster; + Subject = subject; + Time = DateTime.UtcNow; + LastPostTime = Time; + Thread = thread; + PostedName = Poster.Name; + PostedBody = Poster.Body; + PostedHue = Poster.Hue; + Lines = lines; + + var list = new List(); + + for (var i = 0; i < poster.Items.Count; ++i) + { + var item = poster.Items[i]; + + if (item.Layer >= Layer.OneHanded && item.Layer <= Layer.Mount) + list.Add(new BulletinEquip(item.ItemID, item.Hue)); + } + + PostedEquip = list.ToArray(); + } + + public BulletinMessage(Serial serial) : base(serial) + { + } + + public Mobile Poster { get; private set; } + + public BulletinMessage Thread { get; private set; } + + public string Subject { get; private set; } + + public DateTime Time { get; private set; } + + public DateTime LastPostTime { get; set; } + + public string PostedName { get; private set; } + + public int PostedBody { get; private set; } + + public int PostedHue { get; private set; } + + public BulletinEquip[] PostedEquip { get; private set; } + + public string[] Lines { get; private set; } + + public string GetTimeAsString() => Time.ToString("MMM dd, yyyy"); + + public override bool CheckTarget(Mobile from, Target targ, object targeted) => false; + + public override bool IsAccessibleTo(Mobile check) => false; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(Poster); + writer.Write(Subject); + writer.Write(Time); + writer.Write(LastPostTime); + writer.Write(Thread != null); + writer.Write(Thread); + writer.Write(PostedName); + writer.Write(PostedBody); + writer.Write(PostedHue); + + writer.Write(PostedEquip.Length); + + for (var i = 0; i < PostedEquip.Length; ++i) + { + writer.Write(PostedEquip[i].itemID); + writer.Write(PostedEquip[i].hue); + } + + writer.Write(Lines.Length); + + for (var i = 0; i < Lines.Length; ++i) + writer.Write(Lines[i]); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + case 0: + { + Poster = reader.ReadMobile(); + Subject = reader.ReadString(); + Time = reader.ReadDateTime(); + LastPostTime = reader.ReadDateTime(); + var hasThread = reader.ReadBool(); + Thread = reader.ReadItem() as BulletinMessage; + PostedName = reader.ReadString(); + PostedBody = reader.ReadInt(); + PostedHue = reader.ReadInt(); + + PostedEquip = new BulletinEquip[reader.ReadInt()]; + + for (var i = 0; i < PostedEquip.Length; ++i) + { + PostedEquip[i].itemID = reader.ReadInt(); + PostedEquip[i].hue = reader.ReadInt(); + } + + Lines = new string[reader.ReadInt()]; + + for (var i = 0; i < Lines.Length; ++i) + Lines[i] = reader.ReadString(); + + if (hasThread && Thread == null) + Delete(); + + if (version == 0) + ValidationQueue.Add(this); + + break; + } + } + } + + public void Validate() + { + if ((Parent as BulletinBoard)?.Items.Contains(this) == false) + Delete(); + } + } + + public class BBDisplayBoard : Packet + { + public BBDisplayBoard(BaseBulletinBoard board) : base(0x71) + { + EnsureCapacity(38); + + var buffer = Utility.UTF8.GetBytes(board.BoardName ?? ""); + + Stream.Write((byte)0x00); // PacketID + Stream.Write(board.Serial); // Bulletin board serial + + // Bulletin board name + if (buffer.Length >= 29) + { + Stream.Write(buffer, 0, 29); + Stream.Write((byte)0); + } + else + { + Stream.Write(buffer, 0, buffer.Length); + Stream.Fill(30 - buffer.Length); + } + } + } + + public class BBMessageHeader : Packet + { + public BBMessageHeader(BaseBulletinBoard board, BulletinMessage msg) : base(0x71) + { + var poster = SafeString(msg.PostedName); + var subject = SafeString(msg.Subject); + var time = SafeString(msg.GetTimeAsString()); + + EnsureCapacity(22 + poster.Length + subject.Length + time.Length); + + Stream.Write((byte)0x01); // PacketID + Stream.Write(board.Serial); // Bulletin board serial + Stream.Write(msg.Serial); // Message serial + + var thread = msg.Thread; + + if (thread == null) + Stream.Write(0); // Thread serial--root + else + Stream.Write(thread.Serial); // Thread serial--parent + + WriteString(poster); + WriteString(subject); + WriteString(time); + } + + public void WriteString(string v) + { + var buffer = Utility.UTF8.GetBytes(v); + var len = buffer.Length + 1; + + if (len > 255) + len = 255; + + Stream.Write((byte)len); + Stream.Write(buffer, 0, len - 1); + Stream.Write((byte)0); + } + + public string SafeString(string v) => v ?? string.Empty; + } + + public class BBMessageContent : Packet + { + public BBMessageContent(BaseBulletinBoard board, BulletinMessage msg) : base(0x71) + { + var poster = SafeString(msg.PostedName); + var subject = SafeString(msg.Subject); + var time = SafeString(msg.GetTimeAsString()); + + EnsureCapacity(22 + poster.Length + subject.Length + time.Length); + + Stream.Write((byte)0x02); // PacketID + Stream.Write(board.Serial); // Bulletin board serial + Stream.Write(msg.Serial); // Message serial + + WriteString(poster); + WriteString(subject); + WriteString(time); + + Stream.Write((short)msg.PostedBody); + Stream.Write((short)msg.PostedHue); + + var len = msg.PostedEquip.Length; + + if (len > 255) + len = 255; + + Stream.Write((byte)len); + + for (var i = 0; i < len; ++i) + { + var eq = msg.PostedEquip[i]; + + Stream.Write((short)eq.itemID); + Stream.Write((short)eq.hue); + } + + len = msg.Lines.Length; + + if (len > 255) + len = 255; + + Stream.Write((byte)len); + + for (var i = 0; i < len; ++i) + WriteString(msg.Lines[i], true); + } + + public void WriteString(string v) + { + WriteString(v, false); + } + + public void WriteString(string v, bool padding) + { + var buffer = Utility.UTF8.GetBytes(v); + var tail = padding ? 2 : 1; + var len = buffer.Length + tail; + + if (len > 255) + len = 255; + + Stream.Write((byte)len); + Stream.Write(buffer, 0, len - tail); + + if (padding) + Stream.Write((short)0); // padding compensates for a client bug + else + Stream.Write((byte)0); + } + + public string SafeString(string v) + { + if (v == null) + return string.Empty; + + return v; + } + } +} diff --git a/Projects/UOContent/Items/Misc/ClockworkAssembly.cs b/Projects/UOContent/Items/Misc/ClockworkAssembly.cs index fba6d3c02..a43ebb6dd 100644 --- a/Projects/UOContent/Items/Misc/ClockworkAssembly.cs +++ b/Projects/UOContent/Items/Misc/ClockworkAssembly.cs @@ -1,129 +1,130 @@ -using Server.Mobiles; - -namespace Server.Items -{ - public class ClockworkAssembly : Item - { - [Constructible] - public ClockworkAssembly() : base(0x1EA8) - { - Weight = 5.0; - Hue = 1102; - } - - public ClockworkAssembly(Serial serial) : base(serial) - { - } - - public override string DefaultName => "clockwork assembly"; - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - return; - } - - double tinkerSkill = from.Skills.Tinkering.Value; - - if (tinkerSkill < 60.0) - { - from.SendMessage("You must have at least 60.0 skill in tinkering to construct a golem."); - return; - } - - if (from.Followers + 4 > from.FollowersMax) - { - from.SendLocalizedMessage(1049607); // You have too many followers to control that creature. - return; - } - - double scalar; - - if (tinkerSkill >= 100.0) - scalar = 1.0; - else if (tinkerSkill >= 90.0) - scalar = 0.9; - else if (tinkerSkill >= 80.0) - scalar = 0.8; - else if (tinkerSkill >= 70.0) - scalar = 0.7; - else - scalar = 0.6; - - Container pack = from.Backpack; - - if (pack == null) - return; - - int res = pack.ConsumeTotal( - new[] - { - typeof(PowerCrystal), - typeof(IronIngot), - typeof(BronzeIngot), - typeof(Gears) - }, - new[] - { - 1, - 50, - 50, - 5 - }); - - switch (res) - { - case 0: - { - from.SendMessage("You must have a power crystal to construct the golem."); - break; - } - case 1: - { - from.SendMessage("You must have 50 iron ingots to construct the golem."); - break; - } - case 2: - { - from.SendMessage("You must have 50 bronze ingots to construct the golem."); - break; - } - case 3: - { - from.SendMessage("You must have 5 gears to construct the golem."); - break; - } - default: - { - Golem g = new Golem(true, scalar); - - if (g.SetControlMaster(from)) - { - Delete(); - - g.MoveToWorld(from.Location, from.Map); - from.PlaySound(0x241); - } - - break; - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Mobiles; + +namespace Server.Items +{ + public class ClockworkAssembly : Item + { + [Constructible] + public ClockworkAssembly() : base(0x1EA8) + { + Weight = 5.0; + Hue = 1102; + } + + public ClockworkAssembly(Serial serial) : base(serial) + { + } + + public override string DefaultName => "clockwork assembly"; + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + return; + } + + var tinkerSkill = from.Skills.Tinkering.Value; + + if (tinkerSkill < 60.0) + { + from.SendMessage("You must have at least 60.0 skill in tinkering to construct a golem."); + return; + } + + if (from.Followers + 4 > from.FollowersMax) + { + from.SendLocalizedMessage(1049607); // You have too many followers to control that creature. + return; + } + + double scalar; + + if (tinkerSkill >= 100.0) + scalar = 1.0; + else if (tinkerSkill >= 90.0) + scalar = 0.9; + else if (tinkerSkill >= 80.0) + scalar = 0.8; + else if (tinkerSkill >= 70.0) + scalar = 0.7; + else + scalar = 0.6; + + var pack = from.Backpack; + + if (pack == null) + return; + + var res = pack.ConsumeTotal( + new[] + { + typeof(PowerCrystal), + typeof(IronIngot), + typeof(BronzeIngot), + typeof(Gears) + }, + new[] + { + 1, + 50, + 50, + 5 + } + ); + + switch (res) + { + case 0: + { + from.SendMessage("You must have a power crystal to construct the golem."); + break; + } + case 1: + { + from.SendMessage("You must have 50 iron ingots to construct the golem."); + break; + } + case 2: + { + from.SendMessage("You must have 50 bronze ingots to construct the golem."); + break; + } + case 3: + { + from.SendMessage("You must have 5 gears to construct the golem."); + break; + } + default: + { + var g = new Golem(true, scalar); + + if (g.SetControlMaster(from)) + { + Delete(); + + g.MoveToWorld(from.Location, from.Map); + from.PlaySound(0x241); + } + + break; + } + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/CommunicationCrystals.cs b/Projects/UOContent/Items/Misc/CommunicationCrystals.cs index e9abc8b90..3f03798ab 100644 --- a/Projects/UOContent/Items/Misc/CommunicationCrystals.cs +++ b/Projects/UOContent/Items/Misc/CommunicationCrystals.cs @@ -1,441 +1,442 @@ -using System; -using System.Collections.Generic; -using Server.Network; -using Server.Targeting; - -namespace Server.Items -{ - public class CrystalRechargeInfo - { - public static readonly CrystalRechargeInfo[] Table = - { - new CrystalRechargeInfo(typeof(Citrine), 500), - new CrystalRechargeInfo(typeof(Amber), 500), - new CrystalRechargeInfo(typeof(Tourmaline), 750), - new CrystalRechargeInfo(typeof(Emerald), 1000), - new CrystalRechargeInfo(typeof(Sapphire), 1000), - new CrystalRechargeInfo(typeof(Amethyst), 1000), - new CrystalRechargeInfo(typeof(StarSapphire), 1250), - new CrystalRechargeInfo(typeof(Diamond), 2000) - }; - - private CrystalRechargeInfo(Type type, int amount) - { - Type = type; - Amount = amount; - } - - public Type Type { get; } - - public int Amount { get; } - - public static CrystalRechargeInfo Get(Type type) - { - foreach (CrystalRechargeInfo info in Table) - if (info.Type == type) - return info; - - return null; - } - } - - public class BroadcastCrystal : Item - { - public static readonly int MaxCharges = 2000; - - private int m_Charges; - - [Constructible] - public BroadcastCrystal(int charges = 2000) : base(0x1ED0) - { - Light = LightType.Circle150; - - m_Charges = charges; - - Receivers = new List(); - } - - public BroadcastCrystal(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1060740; // communication crystal - - [CommandProperty(AccessLevel.GameMaster)] - public bool Active - { - get => ItemID == 0x1ECD; - set - { - ItemID = value ? 0x1ECD : 0x1ED0; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Charges - { - get => m_Charges; - set - { - m_Charges = value; - InvalidateProperties(); - } - } - - public List Receivers { get; private set; } - - public override bool HandlesOnSpeech => true; - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(Active ? 1060742 : 1060743); // active / inactive - list.Add(1060745); // broadcast - list.Add(1060741, Charges.ToString()); // charges: ~1_val~ - - if (Receivers.Count > 0) - list.Add(1060746, Receivers.Count.ToString()); // links: ~1_val~ - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - LabelTo(from, Active ? 1060742 : 1060743); // active / inactive - LabelTo(from, 1060745); // broadcast - LabelTo(from, 1060741, Charges.ToString()); // charges: ~1_val~ - - if (Receivers.Count > 0) - LabelTo(from, 1060746, Receivers.Count.ToString()); // links: ~1_val~ - } - - public override void OnSpeech(SpeechEventArgs e) - { - if (!Active || Receivers.Count == 0 || (RootParent != null && !(RootParent is Mobile))) - return; - - if (e.Type == MessageType.Emote) - return; - - Mobile from = e.Mobile; - string speech = e.Speech; - - foreach (ReceiverCrystal receiver in new List(Receivers)) - if (receiver.Deleted) - { - Receivers.Remove(receiver); - } - else if (Charges > 0) - { - receiver.TransmitMessage(from, speech); - Charges--; - } - else - { - Active = false; - break; - } - } - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return; - } - - from.Target = new InternalTarget(this); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.WriteEncodedInt(m_Charges); - writer.WriteItemList(Receivers); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_Charges = reader.ReadEncodedInt(); - Receivers = reader.ReadStrongItemList(); - } - - private class InternalTarget : Target - { - private readonly BroadcastCrystal m_Crystal; - - public InternalTarget(BroadcastCrystal crystal) : base(2, false, TargetFlags.None) => m_Crystal = crystal; - - protected override void OnTarget(Mobile from, object targeted) - { - if (!m_Crystal.IsAccessibleTo(from)) - return; - - if (from.Map != m_Crystal.Map || !from.InRange(m_Crystal.GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return; - } - - if (targeted == m_Crystal) - { - if (m_Crystal.Active) - { - m_Crystal.Active = false; - from.SendLocalizedMessage(500672); // You turn the crystal off. - } - else - { - if (m_Crystal.Charges > 0) - { - m_Crystal.Active = true; - from.SendLocalizedMessage(500673); // You turn the crystal on. - } - else - { - from.SendLocalizedMessage(500676); // This crystal is out of charges. - } - } - } - else if (targeted is ReceiverCrystal receiver) - { - if (m_Crystal.Receivers.Count >= 10) - { - from.SendLocalizedMessage(1010042); // This broadcast crystal is already linked to 10 receivers. - } - else if (receiver.Sender == m_Crystal) - { - from.SendLocalizedMessage(500674); // This crystal is already linked with that crystal. - } - else if (receiver.Sender != null) - { - from.SendLocalizedMessage( - 1010043); // That receiver crystal is already linked to another broadcast crystal. - } - else - { - receiver.Sender = m_Crystal; - from.SendLocalizedMessage(500675); // That crystal has been linked to this crystal. - } - } - else if (targeted == from) - { - foreach (ReceiverCrystal rc in new List(m_Crystal.Receivers)) rc.Sender = null; - - from.SendLocalizedMessage(1010046); // You unlink the broadcast crystal from all of its receivers. - } - else - { - if (targeted is Item targItem && targItem.VerifyMove(from)) - { - CrystalRechargeInfo info = CrystalRechargeInfo.Get(targItem.GetType()); - - if (info != null) - { - if (m_Crystal.Charges >= MaxCharges) - { - from.SendLocalizedMessage(500678); // This crystal is already fully charged. - } - else - { - targItem.Consume(); - - if (m_Crystal.Charges + info.Amount >= MaxCharges) - { - m_Crystal.Charges = MaxCharges; - from.SendLocalizedMessage(500679); // You completely recharge the crystal. - } - else - { - m_Crystal.Charges += info.Amount; - from.SendLocalizedMessage(500680); // You recharge the crystal. - } - } - - return; - } - } - - from.SendLocalizedMessage(500681); // You cannot use this crystal on that. - } - } - } - } - - public class ReceiverCrystal : Item - { - private BroadcastCrystal m_Sender; - - [Constructible] - public ReceiverCrystal() : base(0x1ED0) => Light = LightType.Circle150; - - public ReceiverCrystal(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1060740; // communication crystal - - [CommandProperty(AccessLevel.GameMaster)] - public bool Active - { - get => ItemID == 0x1ED1; - set - { - ItemID = value ? 0x1ED1 : 0x1ED0; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public BroadcastCrystal Sender - { - get => m_Sender; - set - { - if (m_Sender != null) - { - m_Sender.Receivers.Remove(this); - m_Sender.InvalidateProperties(); - } - - m_Sender = value; - - if (value != null) - { - value.Receivers.Add(this); - value.InvalidateProperties(); - } - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(Active ? 1060742 : 1060743); // active / inactive - list.Add(1060744); // receiver - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - LabelTo(from, Active ? 1060742 : 1060743); // active / inactive - LabelTo(from, 1060744); // receiver - } - - public void TransmitMessage(Mobile from, string message) - { - if (!Active) - return; - - string text = $"{from.Name} says {message}"; - - if (RootParent is Mobile mobile) - mobile.SendMessage(0x2B2, $"Crystal: {text}"); - else if (RootParent is Item item) - item.PublicOverheadMessage(MessageType.Regular, 0x2B2, false, $"Crystal: {text}"); - else - PublicOverheadMessage(MessageType.Regular, 0x2B2, false, text); - } - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return; - } - - from.Target = new InternalTarget(this); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.WriteItem(m_Sender); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_Sender = reader.ReadItem(); - } - - private class InternalTarget : Target - { - private readonly ReceiverCrystal m_Crystal; - - public InternalTarget(ReceiverCrystal crystal) : base(-1, false, TargetFlags.None) => m_Crystal = crystal; - - protected override void OnTarget(Mobile from, object targeted) - { - if (!m_Crystal.IsAccessibleTo(from)) - return; - - if (from.Map != m_Crystal.Map || !from.InRange(m_Crystal.GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return; - } - - if (targeted == m_Crystal) - { - if (m_Crystal.Active) - { - m_Crystal.Active = false; - from.SendLocalizedMessage(500672); // You turn the crystal off. - } - else - { - m_Crystal.Active = true; - from.SendLocalizedMessage(500673); // You turn the crystal on. - } - } - else if (targeted == from) - { - if (m_Crystal.Sender != null) - { - m_Crystal.Sender = null; - from.SendLocalizedMessage(1010044); // You unlink the receiver crystal. - } - else - { - from.SendLocalizedMessage(1010045); // That receiver crystal is not linked. - } - } - else - { - if (targeted is Item targItem && targItem.VerifyMove(from)) - { - CrystalRechargeInfo info = CrystalRechargeInfo.Get(targItem.GetType()); - - if (info != null) - { - from.SendLocalizedMessage(500677); // This crystal cannot be recharged. - return; - } - } - - from.SendLocalizedMessage(1010045); // That receiver crystal is not linked. - } - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Network; +using Server.Targeting; + +namespace Server.Items +{ + public class CrystalRechargeInfo + { + public static readonly CrystalRechargeInfo[] Table = + { + new CrystalRechargeInfo(typeof(Citrine), 500), + new CrystalRechargeInfo(typeof(Amber), 500), + new CrystalRechargeInfo(typeof(Tourmaline), 750), + new CrystalRechargeInfo(typeof(Emerald), 1000), + new CrystalRechargeInfo(typeof(Sapphire), 1000), + new CrystalRechargeInfo(typeof(Amethyst), 1000), + new CrystalRechargeInfo(typeof(StarSapphire), 1250), + new CrystalRechargeInfo(typeof(Diamond), 2000) + }; + + private CrystalRechargeInfo(Type type, int amount) + { + Type = type; + Amount = amount; + } + + public Type Type { get; } + + public int Amount { get; } + + public static CrystalRechargeInfo Get(Type type) + { + foreach (var info in Table) + if (info.Type == type) + return info; + + return null; + } + } + + public class BroadcastCrystal : Item + { + public static readonly int MaxCharges = 2000; + + private int m_Charges; + + [Constructible] + public BroadcastCrystal(int charges = 2000) : base(0x1ED0) + { + Light = LightType.Circle150; + + m_Charges = charges; + + Receivers = new List(); + } + + public BroadcastCrystal(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1060740; // communication crystal + + [CommandProperty(AccessLevel.GameMaster)] + public bool Active + { + get => ItemID == 0x1ECD; + set + { + ItemID = value ? 0x1ECD : 0x1ED0; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Charges + { + get => m_Charges; + set + { + m_Charges = value; + InvalidateProperties(); + } + } + + public List Receivers { get; private set; } + + public override bool HandlesOnSpeech => true; + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(Active ? 1060742 : 1060743); // active / inactive + list.Add(1060745); // broadcast + list.Add(1060741, Charges.ToString()); // charges: ~1_val~ + + if (Receivers.Count > 0) + list.Add(1060746, Receivers.Count.ToString()); // links: ~1_val~ + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + LabelTo(from, Active ? 1060742 : 1060743); // active / inactive + LabelTo(from, 1060745); // broadcast + LabelTo(from, 1060741, Charges.ToString()); // charges: ~1_val~ + + if (Receivers.Count > 0) + LabelTo(from, 1060746, Receivers.Count.ToString()); // links: ~1_val~ + } + + public override void OnSpeech(SpeechEventArgs e) + { + if (!Active || Receivers.Count == 0 || RootParent != null && !(RootParent is Mobile)) + return; + + if (e.Type == MessageType.Emote) + return; + + var from = e.Mobile; + var speech = e.Speech; + + foreach (var receiver in new List(Receivers)) + if (receiver.Deleted) + { + Receivers.Remove(receiver); + } + else if (Charges > 0) + { + receiver.TransmitMessage(from, speech); + Charges--; + } + else + { + Active = false; + break; + } + } + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return; + } + + from.Target = new InternalTarget(this); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.WriteEncodedInt(m_Charges); + writer.WriteItemList(Receivers); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_Charges = reader.ReadEncodedInt(); + Receivers = reader.ReadStrongItemList(); + } + + private class InternalTarget : Target + { + private readonly BroadcastCrystal m_Crystal; + + public InternalTarget(BroadcastCrystal crystal) : base(2, false, TargetFlags.None) => m_Crystal = crystal; + + protected override void OnTarget(Mobile from, object targeted) + { + if (!m_Crystal.IsAccessibleTo(from)) + return; + + if (from.Map != m_Crystal.Map || !from.InRange(m_Crystal.GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return; + } + + if (targeted == m_Crystal) + { + if (m_Crystal.Active) + { + m_Crystal.Active = false; + from.SendLocalizedMessage(500672); // You turn the crystal off. + } + else + { + if (m_Crystal.Charges > 0) + { + m_Crystal.Active = true; + from.SendLocalizedMessage(500673); // You turn the crystal on. + } + else + { + from.SendLocalizedMessage(500676); // This crystal is out of charges. + } + } + } + else if (targeted is ReceiverCrystal receiver) + { + if (m_Crystal.Receivers.Count >= 10) + { + from.SendLocalizedMessage(1010042); // This broadcast crystal is already linked to 10 receivers. + } + else if (receiver.Sender == m_Crystal) + { + from.SendLocalizedMessage(500674); // This crystal is already linked with that crystal. + } + else if (receiver.Sender != null) + { + from.SendLocalizedMessage( + 1010043 + ); // That receiver crystal is already linked to another broadcast crystal. + } + else + { + receiver.Sender = m_Crystal; + from.SendLocalizedMessage(500675); // That crystal has been linked to this crystal. + } + } + else if (targeted == from) + { + foreach (var rc in new List(m_Crystal.Receivers)) rc.Sender = null; + + from.SendLocalizedMessage(1010046); // You unlink the broadcast crystal from all of its receivers. + } + else + { + if (targeted is Item targItem && targItem.VerifyMove(from)) + { + var info = CrystalRechargeInfo.Get(targItem.GetType()); + + if (info != null) + { + if (m_Crystal.Charges >= MaxCharges) + { + from.SendLocalizedMessage(500678); // This crystal is already fully charged. + } + else + { + targItem.Consume(); + + if (m_Crystal.Charges + info.Amount >= MaxCharges) + { + m_Crystal.Charges = MaxCharges; + from.SendLocalizedMessage(500679); // You completely recharge the crystal. + } + else + { + m_Crystal.Charges += info.Amount; + from.SendLocalizedMessage(500680); // You recharge the crystal. + } + } + + return; + } + } + + from.SendLocalizedMessage(500681); // You cannot use this crystal on that. + } + } + } + } + + public class ReceiverCrystal : Item + { + private BroadcastCrystal m_Sender; + + [Constructible] + public ReceiverCrystal() : base(0x1ED0) => Light = LightType.Circle150; + + public ReceiverCrystal(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1060740; // communication crystal + + [CommandProperty(AccessLevel.GameMaster)] + public bool Active + { + get => ItemID == 0x1ED1; + set + { + ItemID = value ? 0x1ED1 : 0x1ED0; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public BroadcastCrystal Sender + { + get => m_Sender; + set + { + if (m_Sender != null) + { + m_Sender.Receivers.Remove(this); + m_Sender.InvalidateProperties(); + } + + m_Sender = value; + + if (value != null) + { + value.Receivers.Add(this); + value.InvalidateProperties(); + } + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(Active ? 1060742 : 1060743); // active / inactive + list.Add(1060744); // receiver + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + LabelTo(from, Active ? 1060742 : 1060743); // active / inactive + LabelTo(from, 1060744); // receiver + } + + public void TransmitMessage(Mobile from, string message) + { + if (!Active) + return; + + var text = $"{from.Name} says {message}"; + + if (RootParent is Mobile mobile) + mobile.SendMessage(0x2B2, $"Crystal: {text}"); + else if (RootParent is Item item) + item.PublicOverheadMessage(MessageType.Regular, 0x2B2, false, $"Crystal: {text}"); + else + PublicOverheadMessage(MessageType.Regular, 0x2B2, false, text); + } + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return; + } + + from.Target = new InternalTarget(this); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.WriteItem(m_Sender); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_Sender = reader.ReadItem(); + } + + private class InternalTarget : Target + { + private readonly ReceiverCrystal m_Crystal; + + public InternalTarget(ReceiverCrystal crystal) : base(-1, false, TargetFlags.None) => m_Crystal = crystal; + + protected override void OnTarget(Mobile from, object targeted) + { + if (!m_Crystal.IsAccessibleTo(from)) + return; + + if (from.Map != m_Crystal.Map || !from.InRange(m_Crystal.GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return; + } + + if (targeted == m_Crystal) + { + if (m_Crystal.Active) + { + m_Crystal.Active = false; + from.SendLocalizedMessage(500672); // You turn the crystal off. + } + else + { + m_Crystal.Active = true; + from.SendLocalizedMessage(500673); // You turn the crystal on. + } + } + else if (targeted == from) + { + if (m_Crystal.Sender != null) + { + m_Crystal.Sender = null; + from.SendLocalizedMessage(1010044); // You unlink the receiver crystal. + } + else + { + from.SendLocalizedMessage(1010045); // That receiver crystal is not linked. + } + } + else + { + if (targeted is Item targItem && targItem.VerifyMove(from)) + { + var info = CrystalRechargeInfo.Get(targItem.GetType()); + + if (info != null) + { + from.SendLocalizedMessage(500677); // This crystal cannot be recharged. + return; + } + } + + from.SendLocalizedMessage(1010045); // That receiver crystal is not linked. + } + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/Corpses/Corpse.cs b/Projects/UOContent/Items/Misc/Corpses/Corpse.cs index 278a1feff..375556546 100644 --- a/Projects/UOContent/Items/Misc/Corpses/Corpse.cs +++ b/Projects/UOContent/Items/Misc/Corpses/Corpse.cs @@ -1,1117 +1,1134 @@ -using System; -using System.Collections.Generic; -using Server.ContextMenus; -using Server.Engines.PartySystem; -using Server.Engines.Quests; -using Server.Engines.Quests.Doom; -using Server.Engines.Quests.Haven; -using Server.Guilds; -using Server.Misc; -using Server.Mobiles; -using Server.Network; - -namespace Server.Items -{ - public interface IDevourer - { - bool Devour(Corpse corpse); - } - - [Flags] - public enum CorpseFlag - { - None = 0x00000000, - - /// - /// Has this corpse been carved? - /// - Carved = 0x00000001, - - /// - /// If true, this corpse will not turn into bones - /// - NoBones = 0x00000002, - - /// - /// If true, the corpse has turned into bones - /// - IsBones = 0x00000004, - - /// - /// Has this corpse yet been visited by a taxidermist? - /// - VisitedByTaxidermist = 0x00000008, - - /// - /// Has this corpse yet been used to channel spiritual energy? (AOS Spirit Speak) - /// - Channeled = 0x00000010, - - /// - /// Was the owner criminal when he died? - /// - Criminal = 0x00000020, - - /// - /// Has this corpse been animated? - /// - Animated = 0x00000040, - - /// - /// Has this corpse been self looted? - /// - SelfLooted = 0x00000080 - } - - public class Corpse : Container, ICarvable - { - public static readonly TimeSpan MonsterLootRightSacrifice = TimeSpan.FromMinutes(2.0); - - public static readonly TimeSpan InstancedCorpseTime = TimeSpan.FromMinutes(3.0); - - private static readonly TimeSpan m_DefaultDecayTime = TimeSpan.FromMinutes(7.0); - private static readonly TimeSpan m_BoneDecayTime = TimeSpan.FromMinutes(7.0); - - private string - m_CorpseName; // Value of the CorpseNameAttribute attached to the owner when he died -or- null if the owner had no CorpseNameAttribute; use "the remains of ~name~" - - private DateTime m_DecayTime; - - private Timer m_DecayTimer; - private IDevourer m_Devourer; // The creature that devoured this corpse - private CorpseFlag m_Flags; // @see CorpseFlag - - // For notoriety: - - // For Forensics Evaluation - public string m_Forensicist; // Name of the first PlayerMobile who used Forensic Evaluation on the corpse - - private Dictionary m_InstancedItems; - - private Dictionary m_RestoreTable; - - // Why was this public? - // public override bool IsPublicContainer => true; - - public Corpse(Mobile owner, List equipItems) : this(owner, null, null, equipItems) - { - } - - public Corpse(Mobile owner, HairInfo hair, FacialHairInfo facialhair, List equipItems) - : base(0x2006) - { - // To suppress console warnings, stackable must be true - Stackable = true; - Amount = owner.Body; // protocol defines that for itemid 0x2006, amount=body - Stackable = false; - - Movable = false; - Hue = owner.Hue; - Direction = owner.Direction; - Name = owner.Name; - - Owner = owner; - - m_CorpseName = GetCorpseName(owner); - - TimeOfDeath = DateTime.UtcNow; - - AccessLevel = owner.AccessLevel; - Guild = owner.Guild as Guild; - Kills = owner.Kills; - SetFlag(CorpseFlag.Criminal, owner.Criminal); - - Hair = hair; - FacialHair = facialhair; - - // This corpse does not turn to bones if: the owner is not a player - SetFlag(CorpseFlag.NoBones, !owner.Player); - - Looters = new List(); - EquipItems = equipItems; - - Aggressors = new List(owner.Aggressors.Count + owner.Aggressed.Count); - // bool addToAggressors = !( owner is BaseCreature ); - - bool isBaseCreature = owner is BaseCreature; - - TimeSpan lastTime = TimeSpan.MaxValue; - - for (int i = 0; i < owner.Aggressors.Count; ++i) - { - AggressorInfo info = owner.Aggressors[i]; - - if (DateTime.UtcNow - info.LastCombatTime < lastTime) - { - Killer = info.Attacker; - lastTime = DateTime.UtcNow - info.LastCombatTime; - } - - if (!isBaseCreature && !info.CriminalAggression) - Aggressors.Add(info.Attacker); - } - - for (int i = 0; i < owner.Aggressed.Count; ++i) - { - AggressorInfo info = owner.Aggressed[i]; - - if (DateTime.UtcNow - info.LastCombatTime < lastTime) - { - Killer = info.Defender; - lastTime = DateTime.UtcNow - info.LastCombatTime; - } - - if (!isBaseCreature) - Aggressors.Add(info.Defender); - } - - if (isBaseCreature) - { - BaseCreature bc = (BaseCreature)owner; - - Mobile master = bc.GetMaster(); - if (master != null) - Aggressors.Add(master); - - List rights = BaseCreature.GetLootingRights(bc.DamageEntries, bc.HitsMax); - for (int i = 0; i < rights.Count; ++i) - { - DamageStore ds = rights[i]; - - if (ds.m_HasRight) - Aggressors.Add(ds.m_Mobile); - } - } - - BeginDecay(m_DefaultDecayTime); - - DevourCorpse(); - } - - public Corpse(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public virtual bool InstancedCorpse => Core.SE && DateTime.UtcNow < TimeOfDeath + InstancedCorpseTime; - - public override bool IsDecoContainer => false; - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime TimeOfDeath { get; set; } - - public override bool DisplayWeight => false; - - public HairInfo Hair { get; } - - public FacialHairInfo FacialHair { get; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsBones => GetFlag(CorpseFlag.IsBones); - - [CommandProperty(AccessLevel.GameMaster)] - public bool Devoured => m_Devourer != null; - - [CommandProperty(AccessLevel.GameMaster)] - public bool Carved - { - get => GetFlag(CorpseFlag.Carved); - set => SetFlag(CorpseFlag.Carved, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool VisitedByTaxidermist - { - get => GetFlag(CorpseFlag.VisitedByTaxidermist); - set => SetFlag(CorpseFlag.VisitedByTaxidermist, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Channeled - { - get => GetFlag(CorpseFlag.Channeled); - set => SetFlag(CorpseFlag.Channeled, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Animated - { - get => GetFlag(CorpseFlag.Animated); - set => SetFlag(CorpseFlag.Animated, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool SelfLooted - { - get => GetFlag(CorpseFlag.SelfLooted); - set => SetFlag(CorpseFlag.SelfLooted, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public AccessLevel AccessLevel { get; private set; } - - public List Aggressors { get; private set; } - - public List Looters { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Killer { get; private set; } - - public List EquipItems { get; private set; } - - public List RestoreEquip { get; set; } - - public Guild Guild { get; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Kills { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Criminal - { - get => GetFlag(CorpseFlag.Criminal); - set => SetFlag(CorpseFlag.Criminal, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Owner { get; private set; } - - public override bool DisplaysContent => false; - - public void Carve(Mobile from, Item item) - { - if (IsCriminalAction(from) && (Map?.Rules & MapRules.HarmfulRestrictions) != 0) - { - if (Owner?.Player != true) - from.SendLocalizedMessage(1005035); // You did not earn the right to loot this creature! - else - from.SendLocalizedMessage(1010049); // You may not loot this corpse. - - return; - } - - Mobile dead = Owner; - - if (GetFlag(CorpseFlag.Carved) || dead == null) - { - from.SendLocalizedMessage(500485); // You see nothing useful to carve from the corpse. - } - else if (((Body)Amount).IsHuman && ItemID == 0x2006) - { - new Blood(0x122D).MoveToWorld(Location, Map); - - new Torso().MoveToWorld(Location, Map); - new LeftLeg().MoveToWorld(Location, Map); - new LeftArm().MoveToWorld(Location, Map); - new RightLeg().MoveToWorld(Location, Map); - new RightArm().MoveToWorld(Location, Map); - new Head(dead.Name).MoveToWorld(Location, Map); - - SetFlag(CorpseFlag.Carved, true); - - ProcessDelta(); - SendRemovePacket(); - ItemID = Utility.Random(0xECA, 9); // bone graphic - Hue = 0; - ProcessDelta(); - - if (IsCriminalAction(from)) - from.CriminalAction(true); - } - else if (dead is BaseCreature creature) - { - creature.OnCarve(from, this, item); - } - else - { - from.SendLocalizedMessage(500485); // You see nothing useful to carve from the corpse. - } - } - - public override bool IsChildVisibleTo(Mobile m, Item child) => - !m.Player || m.AccessLevel > AccessLevel.Player || m_InstancedItems == null || - !m_InstancedItems.TryGetValue(child, out InstancedItemInfo info) || (!InstancedCorpse && !info.Perpetual) - || info.IsOwner(m); - - private void AssignInstancedLoot() - { - if (Aggressors.Count == 0 || Items.Count == 0) - return; - - m_InstancedItems ??= new Dictionary(); - - List m_Stackables = new List(); - List m_Unstackables = new List(); - - for (int i = 0; i < Items.Count; i++) - { - Item item = Items[i]; - - if (item.LootType != LootType.Cursed) // Don't have cursed items take up someone's item spot.. (?) - { - if (item.Stackable) - m_Stackables.Add(item); - else - m_Unstackables.Add(item); - } - } - - List attackers = new List(Aggressors); - - for (int i = 1; i < attackers.Count - 1; i++) // randomize - { - int rand = Utility.Random(i + 1); - - Mobile temp = attackers[rand]; - attackers[rand] = attackers[i]; - attackers[i] = temp; - } - - // stackables first, for the remaining stackables, have those be randomly added after - - for (int i = 0; i < m_Stackables.Count; i++) - { - Item item = m_Stackables[i]; - - if (item.Amount >= attackers.Count) - { - int amountPerAttacker = item.Amount / attackers.Count; - int remainder = item.Amount % attackers.Count; - - for (int j = 0; j < (remainder == 0 ? attackers.Count - 1 : attackers.Count); j++) - { - Item splitItem = - Mobile.LiftItemDupe(item, - item.Amount - - amountPerAttacker); // LiftItemDupe automagically adds it as a child item to the corpse - - m_InstancedItems.Add(splitItem, new InstancedItemInfo(splitItem, attackers[j])); - - // What happens to the remaining portion? TEMP FOR NOW UNTIL OSI VERIFICATION: Treat as Single Item. - } - - if (remainder == 0) - m_InstancedItems.Add(item, new InstancedItemInfo(item, attackers[^1])); - else - m_Unstackables.Add(item); - } - else - { - // What happens in this case? TEMP FOR NOW UNTIL OSI VERIFICATION: Treat as Single Item. - m_Unstackables.Add(item); - } - } - - for (int i = 0; i < m_Unstackables.Count; i++) - { - Mobile m = attackers[i % attackers.Count]; - Item item = m_Unstackables[i]; - - m_InstancedItems.Add(item, new InstancedItemInfo(item, m)); - } - } - - public void AddCarvedItem(Item carved, Mobile carver) - { - DropItem(carved); - - if (InstancedCorpse) - { - m_InstancedItems ??= new Dictionary(); - - m_InstancedItems.Add(carved, new InstancedItemInfo(carved, carver)); - } - } - - public void TurnToBones() - { - if (Deleted) - return; - - ProcessDelta(); - SendRemovePacket(); - ItemID = Utility.Random(0xECA, 9); // bone graphic - Hue = 0; - ProcessDelta(); - - SetFlag(CorpseFlag.NoBones, true); - SetFlag(CorpseFlag.IsBones, true); - - BeginDecay(m_BoneDecayTime); - } - - public void BeginDecay(TimeSpan delay) - { - m_DecayTimer?.Stop(); - - m_DecayTime = DateTime.UtcNow + delay; - - m_DecayTimer = new InternalTimer(this, delay); - m_DecayTimer.Start(); - } - - public override void OnAfterDelete() - { - m_DecayTimer?.Stop(); - - m_DecayTimer = null; - } - - public static string GetCorpseName(Mobile m) => m is BaseCreature bc ? bc.CorpseNameOverride ?? bc.CorpseName : null; - - public static void Initialize() - { - Mobile.CreateCorpseHandler += Mobile_CreateCorpseHandler; - } - - public static Container Mobile_CreateCorpseHandler(Mobile owner, HairInfo hair, FacialHairInfo facialhair, - List initialContent, List equipItems) - { - Corpse c = owner is MilitiaFighter ? - new MilitiaFighterCorpse(owner, hair, facialhair, equipItems) : - new Corpse(owner, hair, facialhair, equipItems); - - owner.Corpse = c; - - for (int i = 0; i < initialContent.Count; ++i) - { - Item item = initialContent[i]; - - if (Core.AOS && owner.Player && item.Parent == owner.Backpack) - c.AddItem(item); - else - c.DropItem(item); - - if (owner.Player && Core.AOS) - c.SetRestoreInfo(item, item.Location); - } - - if (Core.SE && !owner.Player) - c.AssignInstancedLoot(); - else if (Core.AOS && owner is PlayerMobile pm) - c.RestoreEquip = pm.EquipSnapshot; - - Point3D loc = owner.Location; - Map map = owner.Map; - - if (map == null || map == Map.Internal) - { - loc = owner.LogoutLocation; - map = owner.LogoutMap; - } - - c.MoveToWorld(loc, map); - - return c; - } - - protected bool GetFlag(CorpseFlag flag) => (m_Flags & flag) != 0; - - protected void SetFlag(CorpseFlag flag, bool on) - { - m_Flags = on ? m_Flags | flag : m_Flags & ~flag; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(12); // version - - if (RestoreEquip == null) - { - writer.Write(false); - } - else - { - writer.Write(true); - writer.Write(RestoreEquip); - } - - writer.Write((int)m_Flags); - - writer.WriteDeltaTime(TimeOfDeath); - - int count = m_RestoreTable?.Count ?? 0; - writer.Write(count); - - if (m_RestoreTable != null) - foreach (var (item, loc) in m_RestoreTable) - { - writer.Write(item); - - if (item.Location == loc) - writer.Write(false); - else - { - writer.Write(true); - writer.Write(loc); - } - } - - writer.Write(m_DecayTimer != null); - - if (m_DecayTimer != null) - writer.WriteDeltaTime(m_DecayTime); - - writer.Write(Looters); - writer.Write(Killer); - - writer.Write(Aggressors); - - writer.Write(Owner); - - writer.Write(m_CorpseName); - - writer.Write((int)AccessLevel); - writer.Write(Guild); - writer.Write(Kills); - - writer.Write(EquipItems); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 12: - { - if (reader.ReadBool()) - RestoreEquip = reader.ReadStrongItemList(); - - goto case 11; - } - case 11: - { - // Version 11, we move all bools to a CorpseFlag - m_Flags = (CorpseFlag)reader.ReadInt(); - - TimeOfDeath = reader.ReadDeltaTime(); - - int count = reader.ReadInt(); - - for (int i = 0; i < count; ++i) - { - Item item = reader.ReadItem(); - - if (reader.ReadBool()) - SetRestoreInfo(item, reader.ReadPoint3D()); - else if (item != null) - SetRestoreInfo(item, item.Location); - } - - if (reader.ReadBool()) - BeginDecay(reader.ReadDeltaTime() - DateTime.UtcNow); - - Looters = reader.ReadStrongMobileList(); - Killer = reader.ReadMobile(); - - Aggressors = reader.ReadStrongMobileList(); - Owner = reader.ReadMobile(); - - m_CorpseName = reader.ReadString(); - - AccessLevel = (AccessLevel)reader.ReadInt(); - reader.ReadInt(); // guild reserve - Kills = reader.ReadInt(); - - EquipItems = reader.ReadStrongItemList(); - break; - } - case 10: - { - TimeOfDeath = reader.ReadDeltaTime(); - - goto case 9; - } - case 9: - { - int count = reader.ReadInt(); - - for (int i = 0; i < count; ++i) - { - Item item = reader.ReadItem(); - - if (reader.ReadBool()) - SetRestoreInfo(item, reader.ReadPoint3D()); - else if (item != null) - SetRestoreInfo(item, item.Location); - } - - goto case 8; - } - case 8: - { - SetFlag(CorpseFlag.VisitedByTaxidermist, reader.ReadBool()); - - goto case 7; - } - case 7: - { - if (reader.ReadBool()) - BeginDecay(reader.ReadDeltaTime() - DateTime.UtcNow); - - goto case 6; - } - case 6: - { - Looters = reader.ReadStrongMobileList(); - Killer = reader.ReadMobile(); - - goto case 5; - } - case 5: - { - SetFlag(CorpseFlag.Carved, reader.ReadBool()); - - goto case 4; - } - case 4: - { - Aggressors = reader.ReadStrongMobileList(); - - goto case 3; - } - case 3: - { - Owner = reader.ReadMobile(); - - goto case 2; - } - case 2: - { - SetFlag(CorpseFlag.NoBones, reader.ReadBool()); - - goto case 1; - } - case 1: - { - m_CorpseName = reader.ReadString(); - - goto case 0; - } - case 0: - { - if (version < 10) - TimeOfDeath = DateTime.UtcNow; - - if (version < 7) - BeginDecay(m_DefaultDecayTime); - - if (version < 6) - Looters = new List(); - - if (version < 4) - Aggressors = new List(); - - AccessLevel = (AccessLevel)reader.ReadInt(); - reader.ReadInt(); // guild reserve - Kills = reader.ReadInt(); - SetFlag(CorpseFlag.Criminal, reader.ReadBool()); - - EquipItems = reader.ReadStrongItemList(); - - break; - } - } - } - - public bool DevourCorpse() - { - if (Devoured || Deleted || Killer?.Deleted != false || !Killer.Alive || !(Killer is IDevourer devourer) || - Owner?.Deleted != false) - return false; - - m_Devourer = devourer; // Set the devourer the killer - return m_Devourer.Devour(this); // Devour the corpse if it hasn't - } - - public override void SendInfoTo(NetState state, bool sendOplPacket) - { - base.SendInfoTo(state, sendOplPacket); - - if (!(((Body)Amount).IsHuman && ItemID == 0x2006)) - return; - - if (state.ContainerGridLines) - state.Send(new CorpseContent6017(state.Mobile, this)); - else - state.Send(new CorpseContent(state.Mobile, this)); - - state.Send(new CorpseEquip(state.Mobile, this)); - } - - public bool IsCriminalAction(Mobile from) - { - if (from == Owner || from.AccessLevel >= AccessLevel.GameMaster) - return false; - - Party p = Party.Get(Owner); - - if (p?.Contains(from) == true) - { - PartyMemberInfo pmi = p[Owner]; - - if (pmi?.CanLoot == true) - return false; - } - - return NotorietyHandlers.CorpseNotoriety(from, this) == Notoriety.Innocent; - } - - public override bool CheckItemUse(Mobile from, Item item) => base.CheckItemUse(from, item) && (item == this || CanLoot(from, item)); - - public override bool CheckLift(Mobile from, Item item, ref LRReason reject) => base.CheckLift(from, item, ref reject) && CanLoot(from, item); - - public override void OnItemUsed(Mobile from, Item item) - { - base.OnItemUsed(from, item); - - if (item is Food) - from.RevealingAction(); - - if (item != this && IsCriminalAction(from)) - from.CriminalAction(true); - - if (!Looters.Contains(from)) - Looters.Add(from); - - if (m_InstancedItems?.ContainsKey(item) == true) - m_InstancedItems.Remove(item); - } - - public override void OnItemLifted(Mobile from, Item item) - { - base.OnItemLifted(from, item); - - if (item != this && from != Owner) - from.RevealingAction(); - - if (item != this && IsCriminalAction(from)) - from.CriminalAction(true); - - if (!Looters.Contains(from)) - Looters.Add(from); - - if (m_InstancedItems?.ContainsKey(item) == true) - m_InstancedItems.Remove(item); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (Core.AOS && Owner == from && from.Alive) - list.Add(new OpenCorpseEntry()); - } - - public bool GetRestoreInfo(Item item, ref Point3D loc) => item != null && m_RestoreTable?.TryGetValue(item, out loc) == true; - - public void SetRestoreInfo(Item item, Point3D loc) - { - if (item == null) - return; - - m_RestoreTable ??= new Dictionary(); - - m_RestoreTable[item] = loc; - } - - public void ClearRestoreInfo(Item item) - { - if (m_RestoreTable == null || item == null) - return; - - m_RestoreTable.Remove(item); - - if (m_RestoreTable.Count == 0) - m_RestoreTable = null; - } - - public bool CanLoot(Mobile from, Item item) => !IsCriminalAction(from) || (Map.Rules & MapRules.HarmfulRestrictions) == 0; - - public bool CheckLoot(Mobile from, Item item) - { - if (!CanLoot(from, item)) - { - if (Owner?.Player != true) - from.SendLocalizedMessage(1005035); // You did not earn the right to loot this creature! - else - from.SendLocalizedMessage(1010049); // You may not loot this corpse. - - return false; - } - - if (IsCriminalAction(from)) - { - if (Owner?.Player != true) - from.SendLocalizedMessage(1005036); // Looting this monster corpse will be a criminal act! - else - from.SendLocalizedMessage(1005038); // Looting this corpse will be a criminal act! - } - - return true; - } - - public virtual void Open(Mobile from, bool checkSelfLoot) - { - if (from.AccessLevel <= AccessLevel.Player && !from.InRange(GetWorldLocation(), 2)) - { - from.SendLocalizedMessage(500446); // That is too far away. - return; - } - - if (checkSelfLoot && from == Owner && !GetFlag(CorpseFlag.SelfLooted) && Items.Count != 0) - { - if (from.FindItemOnLayer(Layer.OuterTorso) is DeathRobe robe) - { - Map map = from.Map; - - if (map != null && map != Map.Internal) - { - robe.MoveToWorld(from.Location, map); - robe.BeginDecay(); - } - } - - Container pack = from.Backpack; - - if (RestoreEquip != null && pack != null) - { - List packItems = new List(pack.Items); // Only items in the top-level pack are re-equipped - - for (int i = 0; i < packItems.Count; i++) - { - Item packItem = packItems[i]; - - if (RestoreEquip.Contains(packItem) && packItem.Movable) - from.EquipItem(packItem); - } - } - - List items = new List(Items); - - bool didntFit = false; - - for (int i = 0; !didntFit && i < items.Count; ++i) - { - Item item = items[i]; - Point3D loc = item.Location; - - if (item.Layer == Layer.Hair || item.Layer == Layer.FacialHair || !item.Movable || - !GetRestoreInfo(item, ref loc)) - continue; - - if (pack?.CheckHold(from, item, false, true) == true) - { - item.Location = loc; - pack.AddItem(item); - - if (RestoreEquip?.Contains(item) == true) - from.EquipItem(item); - } - else - { - didntFit = true; - } - } - - from.PlaySound(0x3E3); - - if (Items.Count != 0) - { - from.SendLocalizedMessage(1062472); // You gather some of your belongings. The rest remain on the corpse. - } - else - { - SetFlag(CorpseFlag.Carved, true); - - if (ItemID == 0x2006) - { - ProcessDelta(); - SendRemovePacket(); - ItemID = Utility.Random(0xECA, 9); // bone graphic - Hue = 0; - ProcessDelta(); - } - - from.SendLocalizedMessage(1062471); // You quickly gather all of your belongings. - } - - SetFlag(CorpseFlag.SelfLooted, true); - } - - if (!CheckLoot(from, null)) - return; - - if (!(from is PlayerMobile player)) return; - - QuestSystem qs = player.Quest; - - if (qs is UzeraanTurmoilQuest) - { - GetDaemonBoneObjective obj = qs.FindObjective(); - if (obj?.CorpseWithBone == this && (!obj.Completed || UzeraanTurmoilQuest.HasLostDaemonBone(player))) - { - Item bone = new QuestDaemonBone(); - - if (player.PlaceInBackpack(bone)) - { - obj.CorpseWithBone = null; - player.SendLocalizedMessage(1049341, "", - 0x22); // You rummage through the bones and find a Daemon Bone! You quickly place the item in your pack. - - if (!obj.Completed) - obj.Complete(); - } - else - { - bone.Delete(); - player.SendLocalizedMessage(1049342, "", - 0x22); // Rummaging through the bones you find a Daemon Bone, but can't pick it up because your pack is too full. Come back when you have more room in your pack. - } - - return; - } - } - else if (qs is TheSummoningQuest) - { - VanquishDaemonObjective obj = qs.FindObjective(); - if (obj?.Completed == true && obj.CorpseWithSkull == this) - { - GoldenSkull sk = new GoldenSkull(); - - if (player.PlaceInBackpack(sk)) - { - obj.CorpseWithSkull = null; - player.SendLocalizedMessage( - 1050022); // For your valor in combating the devourer, you have been awarded a golden skull. - qs.Complete(); - } - else - { - sk.Delete(); - player.SendLocalizedMessage( - 1050023); // You find a golden skull, but your backpack is too full to carry it. - } - } - } - - base.OnDoubleClick(from); - } - - public override void OnDoubleClick(Mobile from) - { - Open(from, Core.AOS); - } - - public override bool CheckContentDisplay(Mobile from) => false; - - public override void AddNameProperty(ObjectPropertyList list) - { - if (ItemID == 0x2006) // Corpse form - { - if (m_CorpseName != null) - list.Add(m_CorpseName); - else - list.Add(1046414, Name); // the remains of ~1_NAME~ - } - else // Bone form - { - list.Add(1046414, Name); // the remains of ~1_NAME~ - } - } - - public override void OnAosSingleClick(Mobile from) - { - int hue = Notoriety.GetHue(NotorietyHandlers.CorpseNotoriety(from, this)); - ObjectPropertyList opl = PropertyList; - - if (opl.Header > 0) - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, hue, 3, opl.Header, Name, opl.HeaderArgs)); - } - - public override void OnSingleClick(Mobile from) - { - int hue = Notoriety.GetHue(NotorietyHandlers.CorpseNotoriety(from, this)); - - if (ItemID == 0x2006) // Corpse form - { - if (m_CorpseName != null) - from.Send(new AsciiMessage(Serial, ItemID, MessageType.Label, hue, 3, "", m_CorpseName)); - else - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, hue, 3, 1046414, "", Name)); - } - else // Bone form - { - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, hue, 3, 1046414, "", Name)); - } - } - - private class InstancedItemInfo - { - private readonly Item m_Item; - private readonly Mobile m_Mobile; - - public InstancedItemInfo(Item i, Mobile m) - { - m_Item = i; - m_Mobile = m; - } - - public bool Perpetual { get; set; } - - public bool IsOwner(Mobile m) - { - if (m_Item.LootType == LootType.Cursed) // Cursed Items are part of everyone's instanced corpse... (?) - return true; - - if (m == null) - return false; // sanity - - if (m_Mobile == m) - return true; - - Party myParty = Party.Get(m_Mobile); - - return myParty != null && myParty == Party.Get(m); - } - } - - private class InternalTimer : Timer - { - private readonly Corpse m_Corpse; - - public InternalTimer(Corpse c, TimeSpan delay) : base(delay) - { - m_Corpse = c; - Priority = TimerPriority.FiveSeconds; - } - - protected override void OnTick() - { - if (!m_Corpse.GetFlag(CorpseFlag.NoBones)) - m_Corpse.TurnToBones(); - else - m_Corpse.Delete(); - } - } - - private class OpenCorpseEntry : ContextMenuEntry - { - public OpenCorpseEntry() : base(6215, 2) - { - } - - public override void OnClick() - { - if (Owner.Target is Corpse corpse && Owner.From.CheckAlive()) - corpse.Open(Owner.From, false); - } - } - } -} +using System; +using System.Collections.Generic; +using Server.ContextMenus; +using Server.Engines.PartySystem; +using Server.Engines.Quests.Doom; +using Server.Engines.Quests.Haven; +using Server.Guilds; +using Server.Misc; +using Server.Mobiles; +using Server.Network; + +namespace Server.Items +{ + public interface IDevourer + { + bool Devour(Corpse corpse); + } + + [Flags] + public enum CorpseFlag + { + None = 0x00000000, + + /// + /// Has this corpse been carved? + /// + Carved = 0x00000001, + + /// + /// If true, this corpse will not turn into bones + /// + NoBones = 0x00000002, + + /// + /// If true, the corpse has turned into bones + /// + IsBones = 0x00000004, + + /// + /// Has this corpse yet been visited by a taxidermist? + /// + VisitedByTaxidermist = 0x00000008, + + /// + /// Has this corpse yet been used to channel spiritual energy? (AOS Spirit Speak) + /// + Channeled = 0x00000010, + + /// + /// Was the owner criminal when he died? + /// + Criminal = 0x00000020, + + /// + /// Has this corpse been animated? + /// + Animated = 0x00000040, + + /// + /// Has this corpse been self looted? + /// + SelfLooted = 0x00000080 + } + + public class Corpse : Container, ICarvable + { + public static readonly TimeSpan MonsterLootRightSacrifice = TimeSpan.FromMinutes(2.0); + + public static readonly TimeSpan InstancedCorpseTime = TimeSpan.FromMinutes(3.0); + + private static readonly TimeSpan m_DefaultDecayTime = TimeSpan.FromMinutes(7.0); + private static readonly TimeSpan m_BoneDecayTime = TimeSpan.FromMinutes(7.0); + + private string + m_CorpseName; // Value of the CorpseNameAttribute attached to the owner when he died -or- null if the owner had no CorpseNameAttribute; use "the remains of ~name~" + + private DateTime m_DecayTime; + + private Timer m_DecayTimer; + private IDevourer m_Devourer; // The creature that devoured this corpse + private CorpseFlag m_Flags; // @see CorpseFlag + + // For notoriety: + + // For Forensics Evaluation + public string m_Forensicist; // Name of the first PlayerMobile who used Forensic Evaluation on the corpse + + private Dictionary m_InstancedItems; + + private Dictionary m_RestoreTable; + + // Why was this public? + // public override bool IsPublicContainer => true; + + public Corpse(Mobile owner, List equipItems) : this(owner, null, null, equipItems) + { + } + + public Corpse(Mobile owner, HairInfo hair, FacialHairInfo facialhair, List equipItems) + : base(0x2006) + { + // To suppress console warnings, stackable must be true + Stackable = true; + Amount = owner.Body; // protocol defines that for itemid 0x2006, amount=body + Stackable = false; + + Movable = false; + Hue = owner.Hue; + Direction = owner.Direction; + Name = owner.Name; + + Owner = owner; + + m_CorpseName = GetCorpseName(owner); + + TimeOfDeath = DateTime.UtcNow; + + AccessLevel = owner.AccessLevel; + Guild = owner.Guild as Guild; + Kills = owner.Kills; + SetFlag(CorpseFlag.Criminal, owner.Criminal); + + Hair = hair; + FacialHair = facialhair; + + // This corpse does not turn to bones if: the owner is not a player + SetFlag(CorpseFlag.NoBones, !owner.Player); + + Looters = new List(); + EquipItems = equipItems; + + Aggressors = new List(owner.Aggressors.Count + owner.Aggressed.Count); + // bool addToAggressors = !( owner is BaseCreature ); + + var isBaseCreature = owner is BaseCreature; + + var lastTime = TimeSpan.MaxValue; + + for (var i = 0; i < owner.Aggressors.Count; ++i) + { + var info = owner.Aggressors[i]; + + if (DateTime.UtcNow - info.LastCombatTime < lastTime) + { + Killer = info.Attacker; + lastTime = DateTime.UtcNow - info.LastCombatTime; + } + + if (!isBaseCreature && !info.CriminalAggression) + Aggressors.Add(info.Attacker); + } + + for (var i = 0; i < owner.Aggressed.Count; ++i) + { + var info = owner.Aggressed[i]; + + if (DateTime.UtcNow - info.LastCombatTime < lastTime) + { + Killer = info.Defender; + lastTime = DateTime.UtcNow - info.LastCombatTime; + } + + if (!isBaseCreature) + Aggressors.Add(info.Defender); + } + + if (isBaseCreature) + { + var bc = (BaseCreature)owner; + + var master = bc.GetMaster(); + if (master != null) + Aggressors.Add(master); + + var rights = BaseCreature.GetLootingRights(bc.DamageEntries, bc.HitsMax); + for (var i = 0; i < rights.Count; ++i) + { + var ds = rights[i]; + + if (ds.m_HasRight) + Aggressors.Add(ds.m_Mobile); + } + } + + BeginDecay(m_DefaultDecayTime); + + DevourCorpse(); + } + + public Corpse(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public virtual bool InstancedCorpse => Core.SE && DateTime.UtcNow < TimeOfDeath + InstancedCorpseTime; + + public override bool IsDecoContainer => false; + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime TimeOfDeath { get; set; } + + public override bool DisplayWeight => false; + + public HairInfo Hair { get; } + + public FacialHairInfo FacialHair { get; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsBones => GetFlag(CorpseFlag.IsBones); + + [CommandProperty(AccessLevel.GameMaster)] + public bool Devoured => m_Devourer != null; + + [CommandProperty(AccessLevel.GameMaster)] + public bool Carved + { + get => GetFlag(CorpseFlag.Carved); + set => SetFlag(CorpseFlag.Carved, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool VisitedByTaxidermist + { + get => GetFlag(CorpseFlag.VisitedByTaxidermist); + set => SetFlag(CorpseFlag.VisitedByTaxidermist, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Channeled + { + get => GetFlag(CorpseFlag.Channeled); + set => SetFlag(CorpseFlag.Channeled, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Animated + { + get => GetFlag(CorpseFlag.Animated); + set => SetFlag(CorpseFlag.Animated, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool SelfLooted + { + get => GetFlag(CorpseFlag.SelfLooted); + set => SetFlag(CorpseFlag.SelfLooted, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public AccessLevel AccessLevel { get; private set; } + + public List Aggressors { get; private set; } + + public List Looters { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Killer { get; private set; } + + public List EquipItems { get; private set; } + + public List RestoreEquip { get; set; } + + public Guild Guild { get; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Kills { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Criminal + { + get => GetFlag(CorpseFlag.Criminal); + set => SetFlag(CorpseFlag.Criminal, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Owner { get; private set; } + + public override bool DisplaysContent => false; + + public void Carve(Mobile from, Item item) + { + if (IsCriminalAction(from) && (Map?.Rules & MapRules.HarmfulRestrictions) != 0) + { + if (Owner?.Player != true) + from.SendLocalizedMessage(1005035); // You did not earn the right to loot this creature! + else + from.SendLocalizedMessage(1010049); // You may not loot this corpse. + + return; + } + + var dead = Owner; + + if (GetFlag(CorpseFlag.Carved) || dead == null) + { + from.SendLocalizedMessage(500485); // You see nothing useful to carve from the corpse. + } + else if (((Body)Amount).IsHuman && ItemID == 0x2006) + { + new Blood(0x122D).MoveToWorld(Location, Map); + + new Torso().MoveToWorld(Location, Map); + new LeftLeg().MoveToWorld(Location, Map); + new LeftArm().MoveToWorld(Location, Map); + new RightLeg().MoveToWorld(Location, Map); + new RightArm().MoveToWorld(Location, Map); + new Head(dead.Name).MoveToWorld(Location, Map); + + SetFlag(CorpseFlag.Carved, true); + + ProcessDelta(); + SendRemovePacket(); + ItemID = Utility.Random(0xECA, 9); // bone graphic + Hue = 0; + ProcessDelta(); + + if (IsCriminalAction(from)) + from.CriminalAction(true); + } + else if (dead is BaseCreature creature) + { + creature.OnCarve(from, this, item); + } + else + { + from.SendLocalizedMessage(500485); // You see nothing useful to carve from the corpse. + } + } + + public override bool IsChildVisibleTo(Mobile m, Item child) => + !m.Player || m.AccessLevel > AccessLevel.Player || m_InstancedItems == null || + !m_InstancedItems.TryGetValue(child, out var info) || !InstancedCorpse && !info.Perpetual + || info.IsOwner(m); + + private void AssignInstancedLoot() + { + if (Aggressors.Count == 0 || Items.Count == 0) + return; + + m_InstancedItems ??= new Dictionary(); + + var m_Stackables = new List(); + var m_Unstackables = new List(); + + for (var i = 0; i < Items.Count; i++) + { + var item = Items[i]; + + if (item.LootType != LootType.Cursed) // Don't have cursed items take up someone's item spot.. (?) + { + if (item.Stackable) + m_Stackables.Add(item); + else + m_Unstackables.Add(item); + } + } + + var attackers = new List(Aggressors); + + for (var i = 1; i < attackers.Count - 1; i++) // randomize + { + var rand = Utility.Random(i + 1); + + var temp = attackers[rand]; + attackers[rand] = attackers[i]; + attackers[i] = temp; + } + + // stackables first, for the remaining stackables, have those be randomly added after + + for (var i = 0; i < m_Stackables.Count; i++) + { + var item = m_Stackables[i]; + + if (item.Amount >= attackers.Count) + { + var amountPerAttacker = item.Amount / attackers.Count; + var remainder = item.Amount % attackers.Count; + + for (var j = 0; j < (remainder == 0 ? attackers.Count - 1 : attackers.Count); j++) + { + var splitItem = + Mobile.LiftItemDupe( + item, + item.Amount - + amountPerAttacker + ); // LiftItemDupe automagically adds it as a child item to the corpse + + m_InstancedItems.Add(splitItem, new InstancedItemInfo(splitItem, attackers[j])); + + // What happens to the remaining portion? TEMP FOR NOW UNTIL OSI VERIFICATION: Treat as Single Item. + } + + if (remainder == 0) + m_InstancedItems.Add(item, new InstancedItemInfo(item, attackers[^1])); + else + m_Unstackables.Add(item); + } + else + { + // What happens in this case? TEMP FOR NOW UNTIL OSI VERIFICATION: Treat as Single Item. + m_Unstackables.Add(item); + } + } + + for (var i = 0; i < m_Unstackables.Count; i++) + { + var m = attackers[i % attackers.Count]; + var item = m_Unstackables[i]; + + m_InstancedItems.Add(item, new InstancedItemInfo(item, m)); + } + } + + public void AddCarvedItem(Item carved, Mobile carver) + { + DropItem(carved); + + if (InstancedCorpse) + { + m_InstancedItems ??= new Dictionary(); + + m_InstancedItems.Add(carved, new InstancedItemInfo(carved, carver)); + } + } + + public void TurnToBones() + { + if (Deleted) + return; + + ProcessDelta(); + SendRemovePacket(); + ItemID = Utility.Random(0xECA, 9); // bone graphic + Hue = 0; + ProcessDelta(); + + SetFlag(CorpseFlag.NoBones, true); + SetFlag(CorpseFlag.IsBones, true); + + BeginDecay(m_BoneDecayTime); + } + + public void BeginDecay(TimeSpan delay) + { + m_DecayTimer?.Stop(); + + m_DecayTime = DateTime.UtcNow + delay; + + m_DecayTimer = new InternalTimer(this, delay); + m_DecayTimer.Start(); + } + + public override void OnAfterDelete() + { + m_DecayTimer?.Stop(); + + m_DecayTimer = null; + } + + public static string GetCorpseName(Mobile m) => m is BaseCreature bc ? bc.CorpseNameOverride ?? bc.CorpseName : null; + + public static void Initialize() + { + Mobile.CreateCorpseHandler += Mobile_CreateCorpseHandler; + } + + public static Container Mobile_CreateCorpseHandler( + Mobile owner, HairInfo hair, FacialHairInfo facialhair, + List initialContent, List equipItems + ) + { + var c = owner is MilitiaFighter + ? new MilitiaFighterCorpse(owner, hair, facialhair, equipItems) + : new Corpse(owner, hair, facialhair, equipItems); + + owner.Corpse = c; + + for (var i = 0; i < initialContent.Count; ++i) + { + var item = initialContent[i]; + + if (Core.AOS && owner.Player && item.Parent == owner.Backpack) + c.AddItem(item); + else + c.DropItem(item); + + if (owner.Player && Core.AOS) + c.SetRestoreInfo(item, item.Location); + } + + if (Core.SE && !owner.Player) + c.AssignInstancedLoot(); + else if (Core.AOS && owner is PlayerMobile pm) + c.RestoreEquip = pm.EquipSnapshot; + + var loc = owner.Location; + var map = owner.Map; + + if (map == null || map == Map.Internal) + { + loc = owner.LogoutLocation; + map = owner.LogoutMap; + } + + c.MoveToWorld(loc, map); + + return c; + } + + protected bool GetFlag(CorpseFlag flag) => (m_Flags & flag) != 0; + + protected void SetFlag(CorpseFlag flag, bool on) + { + m_Flags = on ? m_Flags | flag : m_Flags & ~flag; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(12); // version + + if (RestoreEquip == null) + { + writer.Write(false); + } + else + { + writer.Write(true); + writer.Write(RestoreEquip); + } + + writer.Write((int)m_Flags); + + writer.WriteDeltaTime(TimeOfDeath); + + var count = m_RestoreTable?.Count ?? 0; + writer.Write(count); + + if (m_RestoreTable != null) + foreach (var (item, loc) in m_RestoreTable) + { + writer.Write(item); + + if (item.Location == loc) + { + writer.Write(false); + } + else + { + writer.Write(true); + writer.Write(loc); + } + } + + writer.Write(m_DecayTimer != null); + + if (m_DecayTimer != null) + writer.WriteDeltaTime(m_DecayTime); + + writer.Write(Looters); + writer.Write(Killer); + + writer.Write(Aggressors); + + writer.Write(Owner); + + writer.Write(m_CorpseName); + + writer.Write((int)AccessLevel); + writer.Write(Guild); + writer.Write(Kills); + + writer.Write(EquipItems); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 12: + { + if (reader.ReadBool()) + RestoreEquip = reader.ReadStrongItemList(); + + goto case 11; + } + case 11: + { + // Version 11, we move all bools to a CorpseFlag + m_Flags = (CorpseFlag)reader.ReadInt(); + + TimeOfDeath = reader.ReadDeltaTime(); + + var count = reader.ReadInt(); + + for (var i = 0; i < count; ++i) + { + var item = reader.ReadItem(); + + if (reader.ReadBool()) + SetRestoreInfo(item, reader.ReadPoint3D()); + else if (item != null) + SetRestoreInfo(item, item.Location); + } + + if (reader.ReadBool()) + BeginDecay(reader.ReadDeltaTime() - DateTime.UtcNow); + + Looters = reader.ReadStrongMobileList(); + Killer = reader.ReadMobile(); + + Aggressors = reader.ReadStrongMobileList(); + Owner = reader.ReadMobile(); + + m_CorpseName = reader.ReadString(); + + AccessLevel = (AccessLevel)reader.ReadInt(); + reader.ReadInt(); // guild reserve + Kills = reader.ReadInt(); + + EquipItems = reader.ReadStrongItemList(); + break; + } + case 10: + { + TimeOfDeath = reader.ReadDeltaTime(); + + goto case 9; + } + case 9: + { + var count = reader.ReadInt(); + + for (var i = 0; i < count; ++i) + { + var item = reader.ReadItem(); + + if (reader.ReadBool()) + SetRestoreInfo(item, reader.ReadPoint3D()); + else if (item != null) + SetRestoreInfo(item, item.Location); + } + + goto case 8; + } + case 8: + { + SetFlag(CorpseFlag.VisitedByTaxidermist, reader.ReadBool()); + + goto case 7; + } + case 7: + { + if (reader.ReadBool()) + BeginDecay(reader.ReadDeltaTime() - DateTime.UtcNow); + + goto case 6; + } + case 6: + { + Looters = reader.ReadStrongMobileList(); + Killer = reader.ReadMobile(); + + goto case 5; + } + case 5: + { + SetFlag(CorpseFlag.Carved, reader.ReadBool()); + + goto case 4; + } + case 4: + { + Aggressors = reader.ReadStrongMobileList(); + + goto case 3; + } + case 3: + { + Owner = reader.ReadMobile(); + + goto case 2; + } + case 2: + { + SetFlag(CorpseFlag.NoBones, reader.ReadBool()); + + goto case 1; + } + case 1: + { + m_CorpseName = reader.ReadString(); + + goto case 0; + } + case 0: + { + if (version < 10) + TimeOfDeath = DateTime.UtcNow; + + if (version < 7) + BeginDecay(m_DefaultDecayTime); + + if (version < 6) + Looters = new List(); + + if (version < 4) + Aggressors = new List(); + + AccessLevel = (AccessLevel)reader.ReadInt(); + reader.ReadInt(); // guild reserve + Kills = reader.ReadInt(); + SetFlag(CorpseFlag.Criminal, reader.ReadBool()); + + EquipItems = reader.ReadStrongItemList(); + + break; + } + } + } + + public bool DevourCorpse() + { + if (Devoured || Deleted || Killer?.Deleted != false || !Killer.Alive || !(Killer is IDevourer devourer) || + Owner?.Deleted != false) + return false; + + m_Devourer = devourer; // Set the devourer the killer + return m_Devourer.Devour(this); // Devour the corpse if it hasn't + } + + public override void SendInfoTo(NetState state, bool sendOplPacket) + { + base.SendInfoTo(state, sendOplPacket); + + if (!(((Body)Amount).IsHuman && ItemID == 0x2006)) + return; + + if (state.ContainerGridLines) + state.Send(new CorpseContent6017(state.Mobile, this)); + else + state.Send(new CorpseContent(state.Mobile, this)); + + state.Send(new CorpseEquip(state.Mobile, this)); + } + + public bool IsCriminalAction(Mobile from) + { + if (from == Owner || from.AccessLevel >= AccessLevel.GameMaster) + return false; + + var p = Party.Get(Owner); + + if (p?.Contains(from) == true) + { + var pmi = p[Owner]; + + if (pmi?.CanLoot == true) + return false; + } + + return NotorietyHandlers.CorpseNotoriety(from, this) == Notoriety.Innocent; + } + + public override bool CheckItemUse(Mobile from, Item item) => + base.CheckItemUse(from, item) && (item == this || CanLoot(from, item)); + + public override bool CheckLift(Mobile from, Item item, ref LRReason reject) => + base.CheckLift(from, item, ref reject) && CanLoot(from, item); + + public override void OnItemUsed(Mobile from, Item item) + { + base.OnItemUsed(from, item); + + if (item is Food) + from.RevealingAction(); + + if (item != this && IsCriminalAction(from)) + from.CriminalAction(true); + + if (!Looters.Contains(from)) + Looters.Add(from); + + if (m_InstancedItems?.ContainsKey(item) == true) + m_InstancedItems.Remove(item); + } + + public override void OnItemLifted(Mobile from, Item item) + { + base.OnItemLifted(from, item); + + if (item != this && from != Owner) + from.RevealingAction(); + + if (item != this && IsCriminalAction(from)) + from.CriminalAction(true); + + if (!Looters.Contains(from)) + Looters.Add(from); + + if (m_InstancedItems?.ContainsKey(item) == true) + m_InstancedItems.Remove(item); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (Core.AOS && Owner == from && from.Alive) + list.Add(new OpenCorpseEntry()); + } + + public bool GetRestoreInfo(Item item, ref Point3D loc) => + item != null && m_RestoreTable?.TryGetValue(item, out loc) == true; + + public void SetRestoreInfo(Item item, Point3D loc) + { + if (item == null) + return; + + m_RestoreTable ??= new Dictionary(); + + m_RestoreTable[item] = loc; + } + + public void ClearRestoreInfo(Item item) + { + if (m_RestoreTable == null || item == null) + return; + + m_RestoreTable.Remove(item); + + if (m_RestoreTable.Count == 0) + m_RestoreTable = null; + } + + public bool CanLoot(Mobile from, Item item) => + !IsCriminalAction(from) || (Map.Rules & MapRules.HarmfulRestrictions) == 0; + + public bool CheckLoot(Mobile from, Item item) + { + if (!CanLoot(from, item)) + { + if (Owner?.Player != true) + from.SendLocalizedMessage(1005035); // You did not earn the right to loot this creature! + else + from.SendLocalizedMessage(1010049); // You may not loot this corpse. + + return false; + } + + if (IsCriminalAction(from)) + { + if (Owner?.Player != true) + from.SendLocalizedMessage(1005036); // Looting this monster corpse will be a criminal act! + else + from.SendLocalizedMessage(1005038); // Looting this corpse will be a criminal act! + } + + return true; + } + + public virtual void Open(Mobile from, bool checkSelfLoot) + { + if (from.AccessLevel <= AccessLevel.Player && !from.InRange(GetWorldLocation(), 2)) + { + from.SendLocalizedMessage(500446); // That is too far away. + return; + } + + if (checkSelfLoot && from == Owner && !GetFlag(CorpseFlag.SelfLooted) && Items.Count != 0) + { + if (from.FindItemOnLayer(Layer.OuterTorso) is DeathRobe robe) + { + var map = from.Map; + + if (map != null && map != Map.Internal) + { + robe.MoveToWorld(from.Location, map); + robe.BeginDecay(); + } + } + + var pack = from.Backpack; + + if (RestoreEquip != null && pack != null) + { + var packItems = new List(pack.Items); // Only items in the top-level pack are re-equipped + + for (var i = 0; i < packItems.Count; i++) + { + var packItem = packItems[i]; + + if (RestoreEquip.Contains(packItem) && packItem.Movable) + from.EquipItem(packItem); + } + } + + var items = new List(Items); + + var didntFit = false; + + for (var i = 0; !didntFit && i < items.Count; ++i) + { + var item = items[i]; + var loc = item.Location; + + if (item.Layer == Layer.Hair || item.Layer == Layer.FacialHair || !item.Movable || + !GetRestoreInfo(item, ref loc)) + continue; + + if (pack?.CheckHold(from, item, false, true) == true) + { + item.Location = loc; + pack.AddItem(item); + + if (RestoreEquip?.Contains(item) == true) + from.EquipItem(item); + } + else + { + didntFit = true; + } + } + + from.PlaySound(0x3E3); + + if (Items.Count != 0) + { + from.SendLocalizedMessage(1062472); // You gather some of your belongings. The rest remain on the corpse. + } + else + { + SetFlag(CorpseFlag.Carved, true); + + if (ItemID == 0x2006) + { + ProcessDelta(); + SendRemovePacket(); + ItemID = Utility.Random(0xECA, 9); // bone graphic + Hue = 0; + ProcessDelta(); + } + + from.SendLocalizedMessage(1062471); // You quickly gather all of your belongings. + } + + SetFlag(CorpseFlag.SelfLooted, true); + } + + if (!CheckLoot(from, null)) + return; + + if (!(from is PlayerMobile player)) return; + + var qs = player.Quest; + + if (qs is UzeraanTurmoilQuest) + { + var obj = qs.FindObjective(); + if (obj?.CorpseWithBone == this && (!obj.Completed || UzeraanTurmoilQuest.HasLostDaemonBone(player))) + { + Item bone = new QuestDaemonBone(); + + if (player.PlaceInBackpack(bone)) + { + obj.CorpseWithBone = null; + player.SendLocalizedMessage( + 1049341, + "", + 0x22 + ); // You rummage through the bones and find a Daemon Bone! You quickly place the item in your pack. + + if (!obj.Completed) + obj.Complete(); + } + else + { + bone.Delete(); + player.SendLocalizedMessage( + 1049342, + "", + 0x22 + ); // Rummaging through the bones you find a Daemon Bone, but can't pick it up because your pack is too full. Come back when you have more room in your pack. + } + + return; + } + } + else if (qs is TheSummoningQuest) + { + var obj = qs.FindObjective(); + if (obj?.Completed == true && obj.CorpseWithSkull == this) + { + var sk = new GoldenSkull(); + + if (player.PlaceInBackpack(sk)) + { + obj.CorpseWithSkull = null; + player.SendLocalizedMessage( + 1050022 + ); // For your valor in combating the devourer, you have been awarded a golden skull. + qs.Complete(); + } + else + { + sk.Delete(); + player.SendLocalizedMessage( + 1050023 + ); // You find a golden skull, but your backpack is too full to carry it. + } + } + } + + base.OnDoubleClick(from); + } + + public override void OnDoubleClick(Mobile from) + { + Open(from, Core.AOS); + } + + public override bool CheckContentDisplay(Mobile from) => false; + + public override void AddNameProperty(ObjectPropertyList list) + { + if (ItemID == 0x2006) // Corpse form + { + if (m_CorpseName != null) + list.Add(m_CorpseName); + else + list.Add(1046414, Name); // the remains of ~1_NAME~ + } + else // Bone form + { + list.Add(1046414, Name); // the remains of ~1_NAME~ + } + } + + public override void OnAosSingleClick(Mobile from) + { + var hue = Notoriety.GetHue(NotorietyHandlers.CorpseNotoriety(from, this)); + var opl = PropertyList; + + if (opl.Header > 0) + from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, hue, 3, opl.Header, Name, opl.HeaderArgs)); + } + + public override void OnSingleClick(Mobile from) + { + var hue = Notoriety.GetHue(NotorietyHandlers.CorpseNotoriety(from, this)); + + if (ItemID == 0x2006) // Corpse form + { + if (m_CorpseName != null) + from.Send(new AsciiMessage(Serial, ItemID, MessageType.Label, hue, 3, "", m_CorpseName)); + else + from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, hue, 3, 1046414, "", Name)); + } + else // Bone form + { + from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, hue, 3, 1046414, "", Name)); + } + } + + private class InstancedItemInfo + { + private readonly Item m_Item; + private readonly Mobile m_Mobile; + + public InstancedItemInfo(Item i, Mobile m) + { + m_Item = i; + m_Mobile = m; + } + + public bool Perpetual { get; set; } + + public bool IsOwner(Mobile m) + { + if (m_Item.LootType == LootType.Cursed) // Cursed Items are part of everyone's instanced corpse... (?) + return true; + + if (m == null) + return false; // sanity + + if (m_Mobile == m) + return true; + + var myParty = Party.Get(m_Mobile); + + return myParty != null && myParty == Party.Get(m); + } + } + + private class InternalTimer : Timer + { + private readonly Corpse m_Corpse; + + public InternalTimer(Corpse c, TimeSpan delay) : base(delay) + { + m_Corpse = c; + Priority = TimerPriority.FiveSeconds; + } + + protected override void OnTick() + { + if (!m_Corpse.GetFlag(CorpseFlag.NoBones)) + m_Corpse.TurnToBones(); + else + m_Corpse.Delete(); + } + } + + private class OpenCorpseEntry : ContextMenuEntry + { + public OpenCorpseEntry() : base(6215, 2) + { + } + + public override void OnClick() + { + if (Owner.Target is Corpse corpse && Owner.From.CheckAlive()) + corpse.Open(Owner.From, false); + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/Corpses/CorpseNameAttribute.cs b/Projects/UOContent/Items/Misc/Corpses/CorpseNameAttribute.cs index 412d473a5..a923345fd 100644 --- a/Projects/UOContent/Items/Misc/Corpses/CorpseNameAttribute.cs +++ b/Projects/UOContent/Items/Misc/Corpses/CorpseNameAttribute.cs @@ -1,12 +1,12 @@ -using System; - -namespace Server -{ - [AttributeUsage(AttributeTargets.Class)] - public class CorpseNameAttribute : Attribute - { - public CorpseNameAttribute(string name) => Name = name; - - public string Name { get; } - } -} \ No newline at end of file +using System; + +namespace Server +{ + [AttributeUsage(AttributeTargets.Class)] + public class CorpseNameAttribute : Attribute + { + public CorpseNameAttribute(string name) => Name = name; + + public string Name { get; } + } +} diff --git a/Projects/UOContent/Items/Misc/Corpses/DecayedCorpse.cs b/Projects/UOContent/Items/Misc/Corpses/DecayedCorpse.cs index ad2192868..f3267c8b9 100644 --- a/Projects/UOContent/Items/Misc/Corpses/DecayedCorpse.cs +++ b/Projects/UOContent/Items/Misc/Corpses/DecayedCorpse.cs @@ -1,108 +1,108 @@ -using System; - -namespace Server.Items -{ - public class DecayedCorpse : Container - { - private static readonly TimeSpan m_DefaultDecayTime = TimeSpan.FromMinutes(7.0); - private DateTime m_DecayTime; - private Timer m_DecayTimer; - - public DecayedCorpse(string name) : base(Utility.Random(0xECA, 9)) - { - Movable = false; - Name = name; - - BeginDecay(m_DefaultDecayTime); - } - - public DecayedCorpse(Serial serial) : base(serial) - { - } - - // Do not display (x items, y stones) - public override bool DisplaysContent => false; - - public void BeginDecay(TimeSpan delay) - { - m_DecayTimer?.Stop(); - - m_DecayTime = DateTime.UtcNow + delay; - - m_DecayTimer = new InternalTimer(this, delay); - m_DecayTimer.Start(); - } - - public override void OnAfterDelete() - { - m_DecayTimer?.Stop(); - - m_DecayTimer = null; - } - - // Do not display (x items, y stones) - public override bool CheckContentDisplay(Mobile from) => false; - - public override void AddNameProperty(ObjectPropertyList list) - { - list.Add(1046414, Name); // the remains of ~1_NAME~ - } - - public override void OnSingleClick(Mobile from) - { - LabelTo(from, 1046414, Name); // the remains of ~1_NAME~ - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(m_DecayTimer != null); - - if (m_DecayTimer != null) - writer.WriteDeltaTime(m_DecayTime); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - BeginDecay(m_DefaultDecayTime); - - break; - } - case 1: - { - if (reader.ReadBool()) - BeginDecay(reader.ReadDeltaTime() - DateTime.UtcNow); - - break; - } - } - } - - private class InternalTimer : Timer - { - private readonly DecayedCorpse m_Corpse; - - public InternalTimer(DecayedCorpse c, TimeSpan delay) : base(delay) - { - m_Corpse = c; - Priority = TimerPriority.FiveSeconds; - } - - protected override void OnTick() - { - m_Corpse.Delete(); - } - } - } -} \ No newline at end of file +using System; + +namespace Server.Items +{ + public class DecayedCorpse : Container + { + private static readonly TimeSpan m_DefaultDecayTime = TimeSpan.FromMinutes(7.0); + private DateTime m_DecayTime; + private Timer m_DecayTimer; + + public DecayedCorpse(string name) : base(Utility.Random(0xECA, 9)) + { + Movable = false; + Name = name; + + BeginDecay(m_DefaultDecayTime); + } + + public DecayedCorpse(Serial serial) : base(serial) + { + } + + // Do not display (x items, y stones) + public override bool DisplaysContent => false; + + public void BeginDecay(TimeSpan delay) + { + m_DecayTimer?.Stop(); + + m_DecayTime = DateTime.UtcNow + delay; + + m_DecayTimer = new InternalTimer(this, delay); + m_DecayTimer.Start(); + } + + public override void OnAfterDelete() + { + m_DecayTimer?.Stop(); + + m_DecayTimer = null; + } + + // Do not display (x items, y stones) + public override bool CheckContentDisplay(Mobile from) => false; + + public override void AddNameProperty(ObjectPropertyList list) + { + list.Add(1046414, Name); // the remains of ~1_NAME~ + } + + public override void OnSingleClick(Mobile from) + { + LabelTo(from, 1046414, Name); // the remains of ~1_NAME~ + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(m_DecayTimer != null); + + if (m_DecayTimer != null) + writer.WriteDeltaTime(m_DecayTime); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + BeginDecay(m_DefaultDecayTime); + + break; + } + case 1: + { + if (reader.ReadBool()) + BeginDecay(reader.ReadDeltaTime() - DateTime.UtcNow); + + break; + } + } + } + + private class InternalTimer : Timer + { + private readonly DecayedCorpse m_Corpse; + + public InternalTimer(DecayedCorpse c, TimeSpan delay) : base(delay) + { + m_Corpse = c; + Priority = TimerPriority.FiveSeconds; + } + + protected override void OnTick() + { + m_Corpse.Delete(); + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/Corpses/Packets.cs b/Projects/UOContent/Items/Misc/Corpses/Packets.cs index e36c4630e..10cf3197e 100644 --- a/Projects/UOContent/Items/Misc/Corpses/Packets.cs +++ b/Projects/UOContent/Items/Misc/Corpses/Packets.cs @@ -1,198 +1,197 @@ -using System.Collections.Generic; -using System.IO; -using Server.Items; - -namespace Server.Network -{ - public sealed class CorpseEquip : Packet - { - public CorpseEquip(Mobile beholder, Corpse beheld) : base(0x89) - { - List list = beheld.EquipItems; - - int count = list.Count; - if (beheld.Hair?.ItemID > 0) - count++; - if (beheld.FacialHair?.ItemID > 0) - count++; - - EnsureCapacity(8 + count * 5); - - Stream.Write(beheld.Serial); - - for (int i = 0; i < list.Count; ++i) - { - Item item = list[i]; - - if (!item.Deleted && beholder.CanSee(item) && item.Parent == beheld) - { - Stream.Write((byte)(item.Layer + 1)); - Stream.Write(item.Serial); - } - } - - if (beheld.Hair?.ItemID > 0) - { - Stream.Write((byte)(Layer.Hair + 1)); - Stream.Write(HairInfo.FakeSerial(beheld.Owner) - 2); - } - - if (beheld.FacialHair?.ItemID > 0) - { - Stream.Write((byte)(Layer.FacialHair + 1)); - Stream.Write(FacialHairInfo.FakeSerial(beheld.Owner) - 2); - } - - Stream.Write((byte)Layer.Invalid); - } - } - - public sealed class CorpseContent : Packet - { - public CorpseContent(Mobile beholder, Corpse beheld) - : base(0x3C) - { - List items = beheld.EquipItems; - int count = items.Count; - - if (beheld.Hair?.ItemID > 0) - count++; - if (beheld.FacialHair != null && beheld.FacialHair.ItemID > 0) - count++; - - EnsureCapacity(5 + count * 19); - - long pos = Stream.Position; - - int written = 0; - - Stream.Write((ushort)0); - - for (int i = 0; i < items.Count; ++i) - { - Item child = items[i]; - - if (!child.Deleted && child.Parent == beheld && beholder.CanSee(child)) - { - Stream.Write(child.Serial); - Stream.Write((ushort)child.ItemID); - Stream.Write((byte)0); // signed, itemID offset - Stream.Write((ushort)child.Amount); - Stream.Write((short)child.X); - Stream.Write((short)child.Y); - Stream.Write(beheld.Serial); - Stream.Write((ushort)child.Hue); - - ++written; - } - } - - if (beheld.Hair?.ItemID > 0) - { - Stream.Write(HairInfo.FakeSerial(beheld.Owner) - 2); - Stream.Write((ushort)beheld.Hair.ItemID); - Stream.Write((byte)0); // signed, itemID offset - Stream.Write((ushort)1); - Stream.Write((short)0); - Stream.Write((short)0); - Stream.Write(beheld.Serial); - Stream.Write((ushort)beheld.Hair.Hue); - - ++written; - } - - if (beheld.FacialHair != null && beheld.FacialHair.ItemID > 0) - { - Stream.Write(FacialHairInfo.FakeSerial(beheld.Owner) - 2); - Stream.Write((ushort)beheld.FacialHair.ItemID); - Stream.Write((byte)0); // signed, itemID offset - Stream.Write((ushort)1); - Stream.Write((short)0); - Stream.Write((short)0); - Stream.Write(beheld.Serial); - Stream.Write((ushort)beheld.FacialHair.Hue); - - ++written; - } - - Stream.Seek(pos, SeekOrigin.Begin); - Stream.Write((ushort)written); - } - } - - public sealed class CorpseContent6017 : Packet - { - public CorpseContent6017(Mobile beholder, Corpse beheld) - : base(0x3C) - { - List items = beheld.EquipItems; - int count = items.Count; - - if (beheld.Hair?.ItemID > 0) - count++; - if (beheld.FacialHair?.ItemID > 0) - count++; - - EnsureCapacity(5 + count * 20); - - long pos = Stream.Position; - - int written = 0; - - Stream.Write((ushort)0); - - for (int i = 0; i < items.Count; ++i) - { - Item child = items[i]; - - if (!child.Deleted && child.Parent == beheld && beholder.CanSee(child)) - { - Stream.Write(child.Serial); - Stream.Write((ushort)child.ItemID); - Stream.Write((byte)0); // signed, itemID offset - Stream.Write((ushort)child.Amount); - Stream.Write((short)child.X); - Stream.Write((short)child.Y); - Stream.Write((byte)0); // Grid Location? - Stream.Write(beheld.Serial); - Stream.Write((ushort)child.Hue); - - ++written; - } - } - - if (beheld.Hair?.ItemID > 0) - { - Stream.Write(HairInfo.FakeSerial(beheld.Owner) - 2); - Stream.Write((ushort)beheld.Hair.ItemID); - Stream.Write((byte)0); // signed, itemID offset - Stream.Write((ushort)1); - Stream.Write((short)0); - Stream.Write((short)0); - Stream.Write((byte)0); // Grid Location? - Stream.Write(beheld.Serial); - Stream.Write((ushort)beheld.Hair.Hue); - - ++written; - } - - if (beheld.FacialHair?.ItemID > 0) - { - Stream.Write(FacialHairInfo.FakeSerial(beheld.Owner) - 2); - Stream.Write((ushort)beheld.FacialHair.ItemID); - Stream.Write((byte)0); // signed, itemID offset - Stream.Write((ushort)1); - Stream.Write((short)0); - Stream.Write((short)0); - Stream.Write((byte)0); // Grid Location? - Stream.Write(beheld.Serial); - Stream.Write((ushort)beheld.FacialHair.Hue); - - ++written; - } - - Stream.Seek(pos, SeekOrigin.Begin); - Stream.Write((ushort)written); - } - } -} +using System.IO; +using Server.Items; + +namespace Server.Network +{ + public sealed class CorpseEquip : Packet + { + public CorpseEquip(Mobile beholder, Corpse beheld) : base(0x89) + { + var list = beheld.EquipItems; + + var count = list.Count; + if (beheld.Hair?.ItemID > 0) + count++; + if (beheld.FacialHair?.ItemID > 0) + count++; + + EnsureCapacity(8 + count * 5); + + Stream.Write(beheld.Serial); + + for (var i = 0; i < list.Count; ++i) + { + var item = list[i]; + + if (!item.Deleted && beholder.CanSee(item) && item.Parent == beheld) + { + Stream.Write((byte)(item.Layer + 1)); + Stream.Write(item.Serial); + } + } + + if (beheld.Hair?.ItemID > 0) + { + Stream.Write((byte)(Layer.Hair + 1)); + Stream.Write(HairInfo.FakeSerial(beheld.Owner) - 2); + } + + if (beheld.FacialHair?.ItemID > 0) + { + Stream.Write((byte)(Layer.FacialHair + 1)); + Stream.Write(FacialHairInfo.FakeSerial(beheld.Owner) - 2); + } + + Stream.Write((byte)Layer.Invalid); + } + } + + public sealed class CorpseContent : Packet + { + public CorpseContent(Mobile beholder, Corpse beheld) + : base(0x3C) + { + var items = beheld.EquipItems; + var count = items.Count; + + if (beheld.Hair?.ItemID > 0) + count++; + if (beheld.FacialHair != null && beheld.FacialHair.ItemID > 0) + count++; + + EnsureCapacity(5 + count * 19); + + var pos = Stream.Position; + + var written = 0; + + Stream.Write((ushort)0); + + for (var i = 0; i < items.Count; ++i) + { + var child = items[i]; + + if (!child.Deleted && child.Parent == beheld && beholder.CanSee(child)) + { + Stream.Write(child.Serial); + Stream.Write((ushort)child.ItemID); + Stream.Write((byte)0); // signed, itemID offset + Stream.Write((ushort)child.Amount); + Stream.Write((short)child.X); + Stream.Write((short)child.Y); + Stream.Write(beheld.Serial); + Stream.Write((ushort)child.Hue); + + ++written; + } + } + + if (beheld.Hair?.ItemID > 0) + { + Stream.Write(HairInfo.FakeSerial(beheld.Owner) - 2); + Stream.Write((ushort)beheld.Hair.ItemID); + Stream.Write((byte)0); // signed, itemID offset + Stream.Write((ushort)1); + Stream.Write((short)0); + Stream.Write((short)0); + Stream.Write(beheld.Serial); + Stream.Write((ushort)beheld.Hair.Hue); + + ++written; + } + + if (beheld.FacialHair != null && beheld.FacialHair.ItemID > 0) + { + Stream.Write(FacialHairInfo.FakeSerial(beheld.Owner) - 2); + Stream.Write((ushort)beheld.FacialHair.ItemID); + Stream.Write((byte)0); // signed, itemID offset + Stream.Write((ushort)1); + Stream.Write((short)0); + Stream.Write((short)0); + Stream.Write(beheld.Serial); + Stream.Write((ushort)beheld.FacialHair.Hue); + + ++written; + } + + Stream.Seek(pos, SeekOrigin.Begin); + Stream.Write((ushort)written); + } + } + + public sealed class CorpseContent6017 : Packet + { + public CorpseContent6017(Mobile beholder, Corpse beheld) + : base(0x3C) + { + var items = beheld.EquipItems; + var count = items.Count; + + if (beheld.Hair?.ItemID > 0) + count++; + if (beheld.FacialHair?.ItemID > 0) + count++; + + EnsureCapacity(5 + count * 20); + + var pos = Stream.Position; + + var written = 0; + + Stream.Write((ushort)0); + + for (var i = 0; i < items.Count; ++i) + { + var child = items[i]; + + if (!child.Deleted && child.Parent == beheld && beholder.CanSee(child)) + { + Stream.Write(child.Serial); + Stream.Write((ushort)child.ItemID); + Stream.Write((byte)0); // signed, itemID offset + Stream.Write((ushort)child.Amount); + Stream.Write((short)child.X); + Stream.Write((short)child.Y); + Stream.Write((byte)0); // Grid Location? + Stream.Write(beheld.Serial); + Stream.Write((ushort)child.Hue); + + ++written; + } + } + + if (beheld.Hair?.ItemID > 0) + { + Stream.Write(HairInfo.FakeSerial(beheld.Owner) - 2); + Stream.Write((ushort)beheld.Hair.ItemID); + Stream.Write((byte)0); // signed, itemID offset + Stream.Write((ushort)1); + Stream.Write((short)0); + Stream.Write((short)0); + Stream.Write((byte)0); // Grid Location? + Stream.Write(beheld.Serial); + Stream.Write((ushort)beheld.Hair.Hue); + + ++written; + } + + if (beheld.FacialHair?.ItemID > 0) + { + Stream.Write(FacialHairInfo.FakeSerial(beheld.Owner) - 2); + Stream.Write((ushort)beheld.FacialHair.ItemID); + Stream.Write((byte)0); // signed, itemID offset + Stream.Write((ushort)1); + Stream.Write((short)0); + Stream.Write((short)0); + Stream.Write((byte)0); // Grid Location? + Stream.Write(beheld.Serial); + Stream.Write((ushort)beheld.FacialHair.Hue); + + ++written; + } + + Stream.Seek(pos, SeekOrigin.Begin); + Stream.Write((ushort)written); + } + } +} diff --git a/Projects/UOContent/Items/Misc/DeceitBrazier.cs b/Projects/UOContent/Items/Misc/DeceitBrazier.cs index ff83c6764..95077d219 100644 --- a/Projects/UOContent/Items/Misc/DeceitBrazier.cs +++ b/Projects/UOContent/Items/Misc/DeceitBrazier.cs @@ -1,180 +1,191 @@ -using System; -using Server.Mobiles; -using Server.Network; -using Server.Utilities; - -namespace Server.Items -{ - public class DeceitBrazier : Item - { - private Timer m_Timer; - - [Constructible] - public DeceitBrazier() : base(0xE31) - { - Movable = false; - Light = LightType.Circle225; - NextSpawn = DateTime.UtcNow; - NextSpawnDelay = TimeSpan.FromMinutes(15.0); - SpawnRange = 5; - } - - public DeceitBrazier(Serial serial) : base(serial) - { - } - - public static Type[] Creatures { get; } = - { - typeof(FireSteed), // Set the tents up people! - - typeof(Skeleton), typeof(SkeletalKnight), typeof(SkeletalMage), typeof(Mummy), - typeof(BoneKnight), typeof(Lich), typeof(LichLord), typeof(BoneMagi), - typeof(Wraith), typeof(Shade), typeof(Spectre), typeof(Zombie), - typeof(RottingCorpse), typeof(Ghoul), typeof(Balron), typeof(Daemon), typeof(Imp), typeof(GreaterMongbat), - typeof(Mongbat), typeof(IceFiend), typeof(Gargoyle), typeof(StoneGargoyle), - typeof(FireGargoyle), typeof(HordeMinion), typeof(Gazer), typeof(ElderGazer), typeof(GazerLarva), typeof(Harpy), typeof(StoneHarpy), typeof(HeadlessOne), typeof(HellHound), - typeof(HellCat), typeof(Phoenix), typeof(LavaLizard), typeof(SandVortex), - typeof(ShadowWisp), typeof(SwampTentacle), typeof(PredatorHellCat), typeof(Wisp), typeof(GiantSpider), typeof(DreadSpider), typeof(FrostSpider), typeof(Scorpion), typeof(ArcticOgreLord), typeof(Cyclops), typeof(Ettin), typeof(EvilMage), - typeof(FrostTroll), typeof(Ogre), typeof(OgreLord), typeof(Orc), - typeof(OrcishLord), typeof(OrcishMage), typeof(OrcBrute), typeof(Ratman), - typeof(RatmanMage), typeof(OrcCaptain), typeof(Troll), typeof(Titan), - typeof(EvilMageLord), typeof(OrcBomber), typeof(RatmanArcher), typeof(Dragon), typeof(Drake), typeof(Snake), typeof(GreaterDragon), - typeof(IceSerpent), typeof(GiantSerpent), typeof(IceSnake), typeof(LavaSerpent), - typeof(Lizardman), typeof(Wyvern), typeof(WhiteWyrm), - typeof(ShadowWyrm), typeof(SilverSerpent), typeof(LavaSnake), typeof(EarthElemental), typeof(PoisonElemental), typeof(FireElemental), typeof(SnowElemental), - typeof(IceElemental), typeof(AcidElemental), typeof(WaterElemental), typeof(Efreet), - typeof(AirElemental), typeof(Golem), typeof(SewerRat), typeof(GiantRat), typeof(DireWolf), typeof(TimberWolf), - typeof(Cougar), typeof(Alligator) - }; - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime NextSpawn { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int SpawnRange { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan NextSpawnDelay { get; set; } - - public override int LabelNumber => 1023633; // Brazier - - public override bool HandlesOnMovement => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(SpawnRange); - writer.Write(NextSpawnDelay); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version >= 0) - { - SpawnRange = reader.ReadInt(); - NextSpawnDelay = reader.ReadTimeSpan(); - } - - NextSpawn = DateTime.UtcNow; - } - - public virtual void HeedWarning() - { - PublicOverheadMessage(MessageType.Regular, 0x3B2, - 500761); // Heed this warning well, and use this brazier at your own peril. - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (NextSpawn < DateTime.UtcNow) // means we haven't spawned anything if the next spawn is below - if (Utility.InRange(m.Location, Location, 1) && !Utility.InRange(oldLocation, Location, 1) && m.Player && - !(m.AccessLevel > AccessLevel.Player || m.Hidden)) - if (m_Timer?.Running != true) - m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(2), HeedWarning); - - base.OnMovement(m, oldLocation); - } - - public Point3D GetSpawnPosition() - { - Map map = Map; - - if (map == null) - return Location; - - // Try 10 times to find a Spawnable location. - for (int i = 0; i < 10; i++) - { - int x = Location.X + (Utility.Random(SpawnRange * 2 + 1) - SpawnRange); - int y = Location.Y + (Utility.Random(SpawnRange * 2 + 1) - SpawnRange); - int z = Map.GetAverageZ(x, y); - - if (Map.CanSpawnMobile(new Point2D(x, y), Z)) - return new Point3D(x, y, Z); - if (Map.CanSpawnMobile(new Point2D(x, y), z)) - return new Point3D(x, y, z); - } - - return Location; - } - - public virtual void DoEffect(Point3D loc, Map map) - { - Effects.SendLocationParticles(EffectItem.Create(loc, map, EffectItem.DefaultDuration), 0x3709, 10, 30, 5052); - Effects.PlaySound(loc, map, 0x225); - } - - private void SummonCreatureToWorld(BaseCreature bc, Point3D spawnLoc, Map map) - { - bc.Home = Location; - bc.RangeHome = SpawnRange; - bc.FightMode = FightMode.Closest; - - bc.MoveToWorld(spawnLoc, map); - - DoEffect(spawnLoc, map); - - bc.ForceReacquire(); - } - - public override void OnDoubleClick(Mobile from) - { - if (Utility.InRange(from.Location, Location, 2)) - try - { - if (NextSpawn < DateTime.UtcNow) - { - Map map = Map; - BaseCreature bc = - (BaseCreature)ActivatorUtil.CreateInstance(Creatures.RandomElement()); - - Point3D spawnLoc = GetSpawnPosition(); - - DoEffect(spawnLoc, map); - - Timer.DelayCall(TimeSpan.FromSeconds(1), SummonCreatureToWorld, bc, spawnLoc, map); - - NextSpawn = DateTime.UtcNow + NextSpawnDelay; - } - else - { - PublicOverheadMessage(MessageType.Regular, 0x3B2, - 500760); // The brazier fizzes and pops, but nothing seems to happen. - } - } - catch - { - // ignored - } - else - from.SendLocalizedMessage(500446); // That is too far away. - } - } -} +using System; +using Server.Mobiles; +using Server.Network; +using Server.Utilities; + +namespace Server.Items +{ + public class DeceitBrazier : Item + { + private Timer m_Timer; + + [Constructible] + public DeceitBrazier() : base(0xE31) + { + Movable = false; + Light = LightType.Circle225; + NextSpawn = DateTime.UtcNow; + NextSpawnDelay = TimeSpan.FromMinutes(15.0); + SpawnRange = 5; + } + + public DeceitBrazier(Serial serial) : base(serial) + { + } + + public static Type[] Creatures { get; } = + { + typeof(FireSteed), // Set the tents up people! + + typeof(Skeleton), typeof(SkeletalKnight), typeof(SkeletalMage), typeof(Mummy), + typeof(BoneKnight), typeof(Lich), typeof(LichLord), typeof(BoneMagi), + typeof(Wraith), typeof(Shade), typeof(Spectre), typeof(Zombie), + typeof(RottingCorpse), typeof(Ghoul), typeof(Balron), typeof(Daemon), typeof(Imp), typeof(GreaterMongbat), + typeof(Mongbat), typeof(IceFiend), typeof(Gargoyle), typeof(StoneGargoyle), + typeof(FireGargoyle), typeof(HordeMinion), typeof(Gazer), typeof(ElderGazer), typeof(GazerLarva), typeof(Harpy), + typeof(StoneHarpy), typeof(HeadlessOne), typeof(HellHound), + typeof(HellCat), typeof(Phoenix), typeof(LavaLizard), typeof(SandVortex), + typeof(ShadowWisp), typeof(SwampTentacle), typeof(PredatorHellCat), typeof(Wisp), typeof(GiantSpider), + typeof(DreadSpider), typeof(FrostSpider), typeof(Scorpion), typeof(ArcticOgreLord), typeof(Cyclops), + typeof(Ettin), typeof(EvilMage), + typeof(FrostTroll), typeof(Ogre), typeof(OgreLord), typeof(Orc), + typeof(OrcishLord), typeof(OrcishMage), typeof(OrcBrute), typeof(Ratman), + typeof(RatmanMage), typeof(OrcCaptain), typeof(Troll), typeof(Titan), + typeof(EvilMageLord), typeof(OrcBomber), typeof(RatmanArcher), typeof(Dragon), typeof(Drake), typeof(Snake), + typeof(GreaterDragon), + typeof(IceSerpent), typeof(GiantSerpent), typeof(IceSnake), typeof(LavaSerpent), + typeof(Lizardman), typeof(Wyvern), typeof(WhiteWyrm), + typeof(ShadowWyrm), typeof(SilverSerpent), typeof(LavaSnake), typeof(EarthElemental), typeof(PoisonElemental), + typeof(FireElemental), typeof(SnowElemental), + typeof(IceElemental), typeof(AcidElemental), typeof(WaterElemental), typeof(Efreet), + typeof(AirElemental), typeof(Golem), typeof(SewerRat), typeof(GiantRat), typeof(DireWolf), typeof(TimberWolf), + typeof(Cougar), typeof(Alligator) + }; + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime NextSpawn { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int SpawnRange { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan NextSpawnDelay { get; set; } + + public override int LabelNumber => 1023633; // Brazier + + public override bool HandlesOnMovement => true; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(SpawnRange); + writer.Write(NextSpawnDelay); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version >= 0) + { + SpawnRange = reader.ReadInt(); + NextSpawnDelay = reader.ReadTimeSpan(); + } + + NextSpawn = DateTime.UtcNow; + } + + public virtual void HeedWarning() + { + PublicOverheadMessage( + MessageType.Regular, + 0x3B2, + 500761 + ); // Heed this warning well, and use this brazier at your own peril. + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (NextSpawn < DateTime.UtcNow) // means we haven't spawned anything if the next spawn is below + if (Utility.InRange(m.Location, Location, 1) && !Utility.InRange(oldLocation, Location, 1) && m.Player && + !(m.AccessLevel > AccessLevel.Player || m.Hidden)) + if (m_Timer?.Running != true) + m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(2), HeedWarning); + + base.OnMovement(m, oldLocation); + } + + public Point3D GetSpawnPosition() + { + var map = Map; + + if (map == null) + return Location; + + // Try 10 times to find a Spawnable location. + for (var i = 0; i < 10; i++) + { + var x = Location.X + (Utility.Random(SpawnRange * 2 + 1) - SpawnRange); + var y = Location.Y + (Utility.Random(SpawnRange * 2 + 1) - SpawnRange); + var z = Map.GetAverageZ(x, y); + + if (Map.CanSpawnMobile(new Point2D(x, y), Z)) + return new Point3D(x, y, Z); + if (Map.CanSpawnMobile(new Point2D(x, y), z)) + return new Point3D(x, y, z); + } + + return Location; + } + + public virtual void DoEffect(Point3D loc, Map map) + { + Effects.SendLocationParticles(EffectItem.Create(loc, map, EffectItem.DefaultDuration), 0x3709, 10, 30, 5052); + Effects.PlaySound(loc, map, 0x225); + } + + private void SummonCreatureToWorld(BaseCreature bc, Point3D spawnLoc, Map map) + { + bc.Home = Location; + bc.RangeHome = SpawnRange; + bc.FightMode = FightMode.Closest; + + bc.MoveToWorld(spawnLoc, map); + + DoEffect(spawnLoc, map); + + bc.ForceReacquire(); + } + + public override void OnDoubleClick(Mobile from) + { + if (Utility.InRange(from.Location, Location, 2)) + try + { + if (NextSpawn < DateTime.UtcNow) + { + var map = Map; + var bc = + (BaseCreature)ActivatorUtil.CreateInstance(Creatures.RandomElement()); + + var spawnLoc = GetSpawnPosition(); + + DoEffect(spawnLoc, map); + + Timer.DelayCall(TimeSpan.FromSeconds(1), SummonCreatureToWorld, bc, spawnLoc, map); + + NextSpawn = DateTime.UtcNow + NextSpawnDelay; + } + else + { + PublicOverheadMessage( + MessageType.Regular, + 0x3B2, + 500760 + ); // The brazier fizzes and pops, but nothing seems to happen. + } + } + catch + { + // ignored + } + else + from.SendLocalizedMessage(500446); // That is too far away. + } + } +} diff --git a/Projects/UOContent/Items/Misc/EffectController.cs b/Projects/UOContent/Items/Misc/EffectController.cs index 621d72c54..a0bfe05eb 100644 --- a/Projects/UOContent/Items/Misc/EffectController.cs +++ b/Projects/UOContent/Items/Misc/EffectController.cs @@ -1,321 +1,352 @@ -using System; - -namespace Server.Items -{ - public enum ECEffectType - { - None, - Moving, - Location, - Target, - Lightning - } - - public enum EffectTriggerType - { - None, - Sequenced, - DoubleClick, - InRange - } - - public class EffectController : Item - { - private IEntity m_Source; - private IEntity m_Target; - - [Constructible] - public EffectController() : base(0x1B72) - { - Movable = false; - Visible = false; - TriggerType = EffectTriggerType.Sequenced; - EffectLayer = (EffectLayer)255; - } - - public EffectController(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public ECEffectType EffectType { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public EffectTriggerType TriggerType { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public EffectLayer EffectLayer { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan EffectDelay { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan TriggerDelay { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan SoundDelay { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Item SourceItem - { - get => m_Source as Item; - set => m_Source = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile SourceMobile - { - get => m_Source as Mobile; - set => m_Source = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool SourceNull - { - get => m_Source == null; - set - { - if (value) m_Source = null; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Item TargetItem - { - get => m_Target as Item; - set => m_Target = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile TargetMobile - { - get => m_Target as Mobile; - set => m_Target = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool TargetNull - { - get => m_Target == null; - set - { - if (value) m_Target = null; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public EffectController Sequence { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - private bool FixedDirection { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - private bool Explodes { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - private bool PlaySoundAtTrigger { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int EffectItemID { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int EffectHue { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int RenderMode { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Speed { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Duration { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int ParticleEffect { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int ExplodeParticleEffect { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int ExplodeSound { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Unknown { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int SoundID { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int TriggerRange { get; set; } - - public override string DefaultName => "Effect Controller"; - - public override bool HandlesOnMovement => TriggerType == EffectTriggerType.InRange; - - public override void OnDoubleClick(Mobile from) - { - if (TriggerType == EffectTriggerType.DoubleClick) - DoEffect(from); - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (m.Location != oldLocation && TriggerType == EffectTriggerType.InRange && - Utility.InRange(GetWorldLocation(), m.Location, TriggerRange) && - !Utility.InRange(GetWorldLocation(), oldLocation, TriggerRange)) - DoEffect(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(EffectDelay); - writer.Write(TriggerDelay); - writer.Write(SoundDelay); - - if (m_Source is Item srcItem) - writer.Write(srcItem); - else - writer.Write(m_Source as Mobile); - - if (m_Target is Item targItem) - writer.Write(targItem); - else - writer.Write(m_Target as Mobile); - - writer.Write(Sequence); - - writer.Write(FixedDirection); - writer.Write(Explodes); - writer.Write(PlaySoundAtTrigger); - - writer.WriteEncodedInt((int)EffectType); - writer.WriteEncodedInt((int)EffectLayer); - writer.WriteEncodedInt((int)TriggerType); - - writer.WriteEncodedInt(EffectItemID); - writer.WriteEncodedInt(EffectHue); - writer.WriteEncodedInt(RenderMode); - writer.WriteEncodedInt(Speed); - writer.WriteEncodedInt(Duration); - writer.WriteEncodedInt(ParticleEffect); - writer.WriteEncodedInt(ExplodeParticleEffect); - writer.WriteEncodedInt(ExplodeSound); - writer.WriteEncodedInt(Unknown); - writer.WriteEncodedInt(SoundID); - writer.WriteEncodedInt(TriggerRange); - } - - private IEntity ReadEntity(IGenericReader reader) => World.FindEntity(reader.ReadUInt()); - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - EffectDelay = reader.ReadTimeSpan(); - TriggerDelay = reader.ReadTimeSpan(); - SoundDelay = reader.ReadTimeSpan(); - - m_Source = ReadEntity(reader); - m_Target = ReadEntity(reader); - Sequence = reader.ReadItem() as EffectController; - - FixedDirection = reader.ReadBool(); - Explodes = reader.ReadBool(); - PlaySoundAtTrigger = reader.ReadBool(); - - EffectType = (ECEffectType)reader.ReadEncodedInt(); - EffectLayer = (EffectLayer)reader.ReadEncodedInt(); - TriggerType = (EffectTriggerType)reader.ReadEncodedInt(); - - EffectItemID = reader.ReadEncodedInt(); - EffectHue = reader.ReadEncodedInt(); - RenderMode = reader.ReadEncodedInt(); - Speed = reader.ReadEncodedInt(); - Duration = reader.ReadEncodedInt(); - ParticleEffect = reader.ReadEncodedInt(); - ExplodeParticleEffect = reader.ReadEncodedInt(); - ExplodeSound = reader.ReadEncodedInt(); - Unknown = reader.ReadEncodedInt(); - SoundID = reader.ReadEncodedInt(); - TriggerRange = reader.ReadEncodedInt(); - - break; - } - } - } - - public void PlaySound(IEntity trigger) - { - IEntity ent = PlaySoundAtTrigger ? trigger : this; - - Effects.PlaySound((ent as Item)?.GetWorldLocation() ?? ent.Location, ent.Map, SoundID); - } - - public void DoEffect(IEntity trigger) - { - if (Deleted || TriggerType == EffectTriggerType.None) - return; - - if (trigger is Mobile mobile && mobile.Hidden && mobile.AccessLevel > AccessLevel.Player) - return; - - if (SoundID > 0) - Timer.DelayCall(SoundDelay, PlaySound, trigger); - - if (Sequence != null) - Timer.DelayCall(TriggerDelay, Sequence.DoEffect, trigger); - - if (EffectType != ECEffectType.None) - Timer.DelayCall(EffectDelay, InternalDoEffect, trigger); - } - - public void InternalDoEffect(IEntity trigger) - { - IEntity from = m_Source ?? trigger; - IEntity to = m_Target ?? trigger; - - switch (EffectType) - { - case ECEffectType.Lightning: - { - Effects.SendBoltEffect(from, false, EffectHue); - break; - } - case ECEffectType.Location: - { - Effects.SendLocationParticles(EffectItem.Create(from.Location, from.Map, EffectItem.DefaultDuration), - EffectItemID, Speed, Duration, EffectHue, RenderMode, ParticleEffect, Unknown); - break; - } - case ECEffectType.Moving: - { - if (from == this) - from = EffectItem.Create(from.Location, from.Map, EffectItem.DefaultDuration); - - if (to == this) - to = EffectItem.Create(to.Location, to.Map, EffectItem.DefaultDuration); - - Effects.SendMovingParticles(from, to, EffectItemID, Speed, Duration, FixedDirection, Explodes, EffectHue, - RenderMode, ParticleEffect, ExplodeParticleEffect, ExplodeSound, EffectLayer, Unknown); - break; - } - case ECEffectType.Target: - { - Effects.SendTargetParticles(from, EffectItemID, Speed, Duration, EffectHue, RenderMode, ParticleEffect, - EffectLayer, Unknown); - break; - } - } - } - } -} +using System; + +namespace Server.Items +{ + public enum ECEffectType + { + None, + Moving, + Location, + Target, + Lightning + } + + public enum EffectTriggerType + { + None, + Sequenced, + DoubleClick, + InRange + } + + public class EffectController : Item + { + private IEntity m_Source; + private IEntity m_Target; + + [Constructible] + public EffectController() : base(0x1B72) + { + Movable = false; + Visible = false; + TriggerType = EffectTriggerType.Sequenced; + EffectLayer = (EffectLayer)255; + } + + public EffectController(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public ECEffectType EffectType { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public EffectTriggerType TriggerType { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public EffectLayer EffectLayer { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan EffectDelay { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan TriggerDelay { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan SoundDelay { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Item SourceItem + { + get => m_Source as Item; + set => m_Source = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile SourceMobile + { + get => m_Source as Mobile; + set => m_Source = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool SourceNull + { + get => m_Source == null; + set + { + if (value) m_Source = null; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Item TargetItem + { + get => m_Target as Item; + set => m_Target = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile TargetMobile + { + get => m_Target as Mobile; + set => m_Target = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool TargetNull + { + get => m_Target == null; + set + { + if (value) m_Target = null; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public EffectController Sequence { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + private bool FixedDirection { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + private bool Explodes { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + private bool PlaySoundAtTrigger { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int EffectItemID { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int EffectHue { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int RenderMode { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Speed { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Duration { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int ParticleEffect { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int ExplodeParticleEffect { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int ExplodeSound { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Unknown { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int SoundID { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int TriggerRange { get; set; } + + public override string DefaultName => "Effect Controller"; + + public override bool HandlesOnMovement => TriggerType == EffectTriggerType.InRange; + + public override void OnDoubleClick(Mobile from) + { + if (TriggerType == EffectTriggerType.DoubleClick) + DoEffect(from); + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (m.Location != oldLocation && TriggerType == EffectTriggerType.InRange && + Utility.InRange(GetWorldLocation(), m.Location, TriggerRange) && + !Utility.InRange(GetWorldLocation(), oldLocation, TriggerRange)) + DoEffect(m); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(EffectDelay); + writer.Write(TriggerDelay); + writer.Write(SoundDelay); + + if (m_Source is Item srcItem) + writer.Write(srcItem); + else + writer.Write(m_Source as Mobile); + + if (m_Target is Item targItem) + writer.Write(targItem); + else + writer.Write(m_Target as Mobile); + + writer.Write(Sequence); + + writer.Write(FixedDirection); + writer.Write(Explodes); + writer.Write(PlaySoundAtTrigger); + + writer.WriteEncodedInt((int)EffectType); + writer.WriteEncodedInt((int)EffectLayer); + writer.WriteEncodedInt((int)TriggerType); + + writer.WriteEncodedInt(EffectItemID); + writer.WriteEncodedInt(EffectHue); + writer.WriteEncodedInt(RenderMode); + writer.WriteEncodedInt(Speed); + writer.WriteEncodedInt(Duration); + writer.WriteEncodedInt(ParticleEffect); + writer.WriteEncodedInt(ExplodeParticleEffect); + writer.WriteEncodedInt(ExplodeSound); + writer.WriteEncodedInt(Unknown); + writer.WriteEncodedInt(SoundID); + writer.WriteEncodedInt(TriggerRange); + } + + private IEntity ReadEntity(IGenericReader reader) => World.FindEntity(reader.ReadUInt()); + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + EffectDelay = reader.ReadTimeSpan(); + TriggerDelay = reader.ReadTimeSpan(); + SoundDelay = reader.ReadTimeSpan(); + + m_Source = ReadEntity(reader); + m_Target = ReadEntity(reader); + Sequence = reader.ReadItem() as EffectController; + + FixedDirection = reader.ReadBool(); + Explodes = reader.ReadBool(); + PlaySoundAtTrigger = reader.ReadBool(); + + EffectType = (ECEffectType)reader.ReadEncodedInt(); + EffectLayer = (EffectLayer)reader.ReadEncodedInt(); + TriggerType = (EffectTriggerType)reader.ReadEncodedInt(); + + EffectItemID = reader.ReadEncodedInt(); + EffectHue = reader.ReadEncodedInt(); + RenderMode = reader.ReadEncodedInt(); + Speed = reader.ReadEncodedInt(); + Duration = reader.ReadEncodedInt(); + ParticleEffect = reader.ReadEncodedInt(); + ExplodeParticleEffect = reader.ReadEncodedInt(); + ExplodeSound = reader.ReadEncodedInt(); + Unknown = reader.ReadEncodedInt(); + SoundID = reader.ReadEncodedInt(); + TriggerRange = reader.ReadEncodedInt(); + + break; + } + } + } + + public void PlaySound(IEntity trigger) + { + var ent = PlaySoundAtTrigger ? trigger : this; + + Effects.PlaySound((ent as Item)?.GetWorldLocation() ?? ent.Location, ent.Map, SoundID); + } + + public void DoEffect(IEntity trigger) + { + if (Deleted || TriggerType == EffectTriggerType.None) + return; + + if (trigger is Mobile mobile && mobile.Hidden && mobile.AccessLevel > AccessLevel.Player) + return; + + if (SoundID > 0) + Timer.DelayCall(SoundDelay, PlaySound, trigger); + + if (Sequence != null) + Timer.DelayCall(TriggerDelay, Sequence.DoEffect, trigger); + + if (EffectType != ECEffectType.None) + Timer.DelayCall(EffectDelay, InternalDoEffect, trigger); + } + + public void InternalDoEffect(IEntity trigger) + { + var from = m_Source ?? trigger; + var to = m_Target ?? trigger; + + switch (EffectType) + { + case ECEffectType.Lightning: + { + Effects.SendBoltEffect(from, false, EffectHue); + break; + } + case ECEffectType.Location: + { + Effects.SendLocationParticles( + EffectItem.Create(from.Location, from.Map, EffectItem.DefaultDuration), + EffectItemID, + Speed, + Duration, + EffectHue, + RenderMode, + ParticleEffect, + Unknown + ); + break; + } + case ECEffectType.Moving: + { + if (from == this) + from = EffectItem.Create(from.Location, from.Map, EffectItem.DefaultDuration); + + if (to == this) + to = EffectItem.Create(to.Location, to.Map, EffectItem.DefaultDuration); + + Effects.SendMovingParticles( + from, + to, + EffectItemID, + Speed, + Duration, + FixedDirection, + Explodes, + EffectHue, + RenderMode, + ParticleEffect, + ExplodeParticleEffect, + ExplodeSound, + EffectLayer, + Unknown + ); + break; + } + case ECEffectType.Target: + { + Effects.SendTargetParticles( + from, + EffectItemID, + Speed, + Duration, + EffectHue, + RenderMode, + ParticleEffect, + EffectLayer, + Unknown + ); + break; + } + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/EffectItem.cs b/Projects/UOContent/Items/Misc/EffectItem.cs index 475931025..434e7ebfe 100644 --- a/Projects/UOContent/Items/Misc/EffectItem.cs +++ b/Projects/UOContent/Items/Misc/EffectItem.cs @@ -1,86 +1,86 @@ -using System; -using System.Collections.Generic; - -namespace Server.Items -{ - public class EffectItem : Item - { - private static readonly List m_Free = new List(); // List of available EffectItems - - public static readonly TimeSpan DefaultDuration = TimeSpan.FromSeconds(5.0); - - private EffectItem() : base(1) // nodraw - => - Movable = false; - - public EffectItem(Serial serial) : base(serial) - { - } - - public override bool Decays => true; - - public static EffectItem Create(Point3D p, Map map, TimeSpan duration) - { - EffectItem item = null; - - for (int i = m_Free.Count - 1; item == null && i >= 0; --i) // We reuse new entries first so decay works better - { - EffectItem free = m_Free[i]; - - m_Free.RemoveAt(i); - - if (!free.Deleted && free.Map == Map.Internal) - item = free; - } - - if (item == null) - item = new EffectItem(); - else - item.ItemID = 1; - - item.MoveToWorld(p, map); - item.BeginFree(duration); - - return item; - } - - public void BeginFree(TimeSpan duration) - { - new FreeTimer(this, duration).Start(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Delete(); - } - - private class FreeTimer : Timer - { - private readonly EffectItem m_Item; - - public FreeTimer(EffectItem item, TimeSpan delay) : base(delay) - { - m_Item = item; - Priority = TimerPriority.OneSecond; - } - - protected override void OnTick() - { - m_Item.Internalize(); - - m_Free.Add(m_Item); - } - } - } -} \ No newline at end of file +using System; +using System.Collections.Generic; + +namespace Server.Items +{ + public class EffectItem : Item + { + private static readonly List m_Free = new List(); // List of available EffectItems + + public static readonly TimeSpan DefaultDuration = TimeSpan.FromSeconds(5.0); + + private EffectItem() : base(1) // nodraw + => + Movable = false; + + public EffectItem(Serial serial) : base(serial) + { + } + + public override bool Decays => true; + + public static EffectItem Create(Point3D p, Map map, TimeSpan duration) + { + EffectItem item = null; + + for (var i = m_Free.Count - 1; item == null && i >= 0; --i) // We reuse new entries first so decay works better + { + var free = m_Free[i]; + + m_Free.RemoveAt(i); + + if (!free.Deleted && free.Map == Map.Internal) + item = free; + } + + if (item == null) + item = new EffectItem(); + else + item.ItemID = 1; + + item.MoveToWorld(p, map); + item.BeginFree(duration); + + return item; + } + + public void BeginFree(TimeSpan duration) + { + new FreeTimer(this, duration).Start(); + } + + 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(); + + Delete(); + } + + private class FreeTimer : Timer + { + private readonly EffectItem m_Item; + + public FreeTimer(EffectItem item, TimeSpan delay) : base(delay) + { + m_Item = item; + Priority = TimerPriority.OneSecond; + } + + protected override void OnTick() + { + m_Item.Internalize(); + + m_Free.Add(m_Item); + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/ExecutionersCap.cs b/Projects/UOContent/Items/Misc/ExecutionersCap.cs index 75c138fe8..6848c3da4 100644 --- a/Projects/UOContent/Items/Misc/ExecutionersCap.cs +++ b/Projects/UOContent/Items/Misc/ExecutionersCap.cs @@ -1,26 +1,26 @@ -namespace Server.Items -{ - public class ExecutionersCap : Item - { - [Constructible] - public ExecutionersCap() : base(0xF83) => Weight = 1.0; - - public ExecutionersCap(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ExecutionersCap : Item + { + [Constructible] + public ExecutionersCap() : base(0xF83) => Weight = 1.0; + + public ExecutionersCap(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Firebomb.cs b/Projects/UOContent/Items/Misc/Firebomb.cs index 9d79f6c70..ecf821903 100644 --- a/Projects/UOContent/Items/Misc/Firebomb.cs +++ b/Projects/UOContent/Items/Misc/Firebomb.cs @@ -1,283 +1,283 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Server.Network; -using Server.Spells; -using Server.Targeting; - -namespace Server.Items -{ - public class Firebomb : Item - { - private Mobile m_LitBy; - private int m_Ticks; - private Timer m_Timer; - private List m_Users; - - [Constructible] - public Firebomb(int itemID = 0x99B) : base(itemID) - { - // Name = "a firebomb"; - Weight = 2.0; - Hue = 1260; - } - - public Firebomb(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - return; - } - - if (Core.AOS && (from.Paralyzed || from.Frozen || from.Spell?.IsCasting == true)) - { - // to prevent exploiting for pvp - from.SendLocalizedMessage(1075857); // You cannot use that while paralyzed. - return; - } - - if (m_Timer == null) - { - m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), OnFirebombTimerTick); - m_LitBy = from; - from.SendLocalizedMessage(1060582); // You light the firebomb. Throw it now! - } - else - { - from.SendLocalizedMessage(1060581); // You've already lit it! Better throw it now! - } - - m_Users ??= new List(); - - if (!m_Users.Contains(from)) - m_Users.Add(from); - - from.Target = new ThrowTarget(this); - } - - private void OnFirebombTimerTick() - { - if (Deleted) - { - m_Timer.Stop(); - return; - } - - if (Map == Map.Internal && HeldBy == null) - return; - - switch (m_Ticks) - { - case 0: - case 1: - case 2: - { - ++m_Ticks; - - if (HeldBy != null) - HeldBy.PublicOverheadMessage(MessageType.Regular, 957, false, m_Ticks.ToString()); - else if (RootParent == null) - PublicOverheadMessage(MessageType.Regular, 957, false, m_Ticks.ToString()); - else if (RootParent is Mobile mobile) - mobile.PublicOverheadMessage(MessageType.Regular, 957, false, m_Ticks.ToString()); - - break; - } - default: - { - HeldBy?.DropHolding(); - - if (m_Users != null) - { - foreach (Mobile m in m_Users) - if (m.Target is ThrowTarget targ && targ.Bomb == this) - Target.Cancel(m); - - m_Users.Clear(); - m_Users = null; - } - - if (RootParent is Mobile parent) - { - parent.SendLocalizedMessage(1060583); // The firebomb explodes in your hand! - AOS.Damage(parent, Utility.Random(3) + 4, 0, 100, 0, 0, 0); - } - else if (RootParent == null) - { - IPooledEnumerable eable = Map.GetMobilesInRange(Location, 1); - List toDamage = eable.ToList(); - - eable.Free(); - - for (int i = 0; i < toDamage.Count; ++i) - { - Mobile victim = toDamage[i]; - - if (m_LitBy == null || (SpellHelper.ValidIndirectTarget(m_LitBy, victim) && - m_LitBy.CanBeHarmful(victim, false))) - { - m_LitBy?.DoHarmful(victim); - - AOS.Damage(victim, m_LitBy, Utility.Random(3) + 4, 0, 100, 0, 0, 0); - } - } - - new FirebombField(m_LitBy, toDamage).MoveToWorld(Location, Map); - } - - m_Timer.Stop(); - Delete(); - break; - } - } - } - - private void OnFirebombTarget(Mobile from, object obj) - { - if (Deleted || Map == Map.Internal || !IsChildOf(from.Backpack)) - return; - - if (!(obj is IPoint3D p)) - return; - - SpellHelper.GetSurfaceTop(ref p); - - from.RevealingAction(); - - IEntity to = p as IEntity ?? new Entity(Serial.Zero, new Point3D(p), Map); - - Effects.SendMovingEffect(from, to, ItemID, 7, 0, false, false, Hue); - - Timer.DelayCall(TimeSpan.FromSeconds(1.0), FirebombReposition_OnTick, p, Map); - Internalize(); - } - - private void FirebombReposition_OnTick(IPoint3D p, Map map) - { - if (Deleted) - return; - - MoveToWorld(new Point3D(p), map); - } - - private class ThrowTarget : Target - { - public ThrowTarget(Firebomb bomb) - : base(12, true, TargetFlags.None) => - Bomb = bomb; - - public Firebomb Bomb { get; } - - protected override void OnTarget(Mobile from, object targeted) - { - Bomb.OnFirebombTarget(from, targeted); - } - } - } - - public class FirebombField : Item - { - private readonly List m_Burning; - private readonly DateTime m_Expire; - private readonly Mobile m_LitBy; - private readonly Timer m_Timer; - - public FirebombField(Mobile litBy, List toDamage) : base(0x376A) - { - Movable = false; - m_LitBy = litBy; - m_Expire = DateTime.UtcNow + TimeSpan.FromSeconds(10); - m_Burning = toDamage; - m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0), OnFirebombFieldTimerTick); - } - - public FirebombField(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - // Don't serialize these... - } - - public override void Deserialize(IGenericReader reader) - { - } - - public override bool OnMoveOver(Mobile m) - { - if ((ItemID == 0x398C && m_LitBy == null) || - (SpellHelper.ValidIndirectTarget(m_LitBy, m) && m_LitBy.CanBeHarmful(m, false))) - { - m_LitBy?.DoHarmful(m); - - AOS.Damage(m, m_LitBy, 2, 0, 100, 0, 0, 0); - m.PlaySound(0x208); - - if (!m_Burning.Contains(m)) - m_Burning.Add(m); - } - - return true; - } - - private void OnFirebombFieldTimerTick() - { - if (Deleted) - { - m_Timer.Stop(); - return; - } - - if (ItemID == 0x376A) - { - ItemID = 0x398C; - return; - } - - for (int i = 0; i < m_Burning.Count;) - { - Mobile victim = m_Burning[i]; - - if (victim.Location == Location && victim.Map == Map && - (m_LitBy == null || (SpellHelper.ValidIndirectTarget(m_LitBy, victim) && - m_LitBy.CanBeHarmful(victim, false)))) - { - m_LitBy?.DoHarmful(victim); - - AOS.Damage(victim, m_LitBy, Utility.Random(3) + 4, 0, 100, 0, 0, 0); - ++i; - } - else - { - m_Burning.RemoveAt(i); - } - } - - if (DateTime.UtcNow >= m_Expire) - { - m_Timer.Stop(); - Delete(); - } - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using Server.Network; +using Server.Spells; +using Server.Targeting; + +namespace Server.Items +{ + public class Firebomb : Item + { + private Mobile m_LitBy; + private int m_Ticks; + private Timer m_Timer; + private List m_Users; + + [Constructible] + public Firebomb(int itemID = 0x99B) : base(itemID) + { + // Name = "a firebomb"; + Weight = 2.0; + Hue = 1260; + } + + public Firebomb(Serial serial) : base(serial) + { + } + + 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(); + } + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + return; + } + + if (Core.AOS && (from.Paralyzed || from.Frozen || from.Spell?.IsCasting == true)) + { + // to prevent exploiting for pvp + from.SendLocalizedMessage(1075857); // You cannot use that while paralyzed. + return; + } + + if (m_Timer == null) + { + m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), OnFirebombTimerTick); + m_LitBy = from; + from.SendLocalizedMessage(1060582); // You light the firebomb. Throw it now! + } + else + { + from.SendLocalizedMessage(1060581); // You've already lit it! Better throw it now! + } + + m_Users ??= new List(); + + if (!m_Users.Contains(from)) + m_Users.Add(from); + + from.Target = new ThrowTarget(this); + } + + private void OnFirebombTimerTick() + { + if (Deleted) + { + m_Timer.Stop(); + return; + } + + if (Map == Map.Internal && HeldBy == null) + return; + + switch (m_Ticks) + { + case 0: + case 1: + case 2: + { + ++m_Ticks; + + if (HeldBy != null) + HeldBy.PublicOverheadMessage(MessageType.Regular, 957, false, m_Ticks.ToString()); + else if (RootParent == null) + PublicOverheadMessage(MessageType.Regular, 957, false, m_Ticks.ToString()); + else if (RootParent is Mobile mobile) + mobile.PublicOverheadMessage(MessageType.Regular, 957, false, m_Ticks.ToString()); + + break; + } + default: + { + HeldBy?.DropHolding(); + + if (m_Users != null) + { + foreach (var m in m_Users) + if (m.Target is ThrowTarget targ && targ.Bomb == this) + Target.Cancel(m); + + m_Users.Clear(); + m_Users = null; + } + + if (RootParent is Mobile parent) + { + parent.SendLocalizedMessage(1060583); // The firebomb explodes in your hand! + AOS.Damage(parent, Utility.Random(3) + 4, 0, 100, 0, 0, 0); + } + else if (RootParent == null) + { + var eable = Map.GetMobilesInRange(Location, 1); + var toDamage = eable.ToList(); + + eable.Free(); + + for (var i = 0; i < toDamage.Count; ++i) + { + var victim = toDamage[i]; + + if (m_LitBy == null || SpellHelper.ValidIndirectTarget(m_LitBy, victim) && + m_LitBy.CanBeHarmful(victim, false)) + { + m_LitBy?.DoHarmful(victim); + + AOS.Damage(victim, m_LitBy, Utility.Random(3) + 4, 0, 100, 0, 0, 0); + } + } + + new FirebombField(m_LitBy, toDamage).MoveToWorld(Location, Map); + } + + m_Timer.Stop(); + Delete(); + break; + } + } + } + + private void OnFirebombTarget(Mobile from, object obj) + { + if (Deleted || Map == Map.Internal || !IsChildOf(from.Backpack)) + return; + + if (!(obj is IPoint3D p)) + return; + + SpellHelper.GetSurfaceTop(ref p); + + from.RevealingAction(); + + var to = p as IEntity ?? new Entity(Serial.Zero, new Point3D(p), Map); + + Effects.SendMovingEffect(from, to, ItemID, 7, 0, false, false, Hue); + + Timer.DelayCall(TimeSpan.FromSeconds(1.0), FirebombReposition_OnTick, p, Map); + Internalize(); + } + + private void FirebombReposition_OnTick(IPoint3D p, Map map) + { + if (Deleted) + return; + + MoveToWorld(new Point3D(p), map); + } + + private class ThrowTarget : Target + { + public ThrowTarget(Firebomb bomb) + : base(12, true, TargetFlags.None) => + Bomb = bomb; + + public Firebomb Bomb { get; } + + protected override void OnTarget(Mobile from, object targeted) + { + Bomb.OnFirebombTarget(from, targeted); + } + } + } + + public class FirebombField : Item + { + private readonly List m_Burning; + private readonly DateTime m_Expire; + private readonly Mobile m_LitBy; + private readonly Timer m_Timer; + + public FirebombField(Mobile litBy, List toDamage) : base(0x376A) + { + Movable = false; + m_LitBy = litBy; + m_Expire = DateTime.UtcNow + TimeSpan.FromSeconds(10); + m_Burning = toDamage; + m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0), OnFirebombFieldTimerTick); + } + + public FirebombField(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + // Don't serialize these... + } + + public override void Deserialize(IGenericReader reader) + { + } + + public override bool OnMoveOver(Mobile m) + { + if (ItemID == 0x398C && m_LitBy == null || + SpellHelper.ValidIndirectTarget(m_LitBy, m) && m_LitBy.CanBeHarmful(m, false)) + { + m_LitBy?.DoHarmful(m); + + AOS.Damage(m, m_LitBy, 2, 0, 100, 0, 0, 0); + m.PlaySound(0x208); + + if (!m_Burning.Contains(m)) + m_Burning.Add(m); + } + + return true; + } + + private void OnFirebombFieldTimerTick() + { + if (Deleted) + { + m_Timer.Stop(); + return; + } + + if (ItemID == 0x376A) + { + ItemID = 0x398C; + return; + } + + for (var i = 0; i < m_Burning.Count;) + { + var victim = m_Burning[i]; + + if (victim.Location == Location && victim.Map == Map && + (m_LitBy == null || SpellHelper.ValidIndirectTarget(m_LitBy, victim) && + m_LitBy.CanBeHarmful(victim, false))) + { + m_LitBy?.DoHarmful(victim); + + AOS.Damage(victim, m_LitBy, Utility.Random(3) + 4, 0, 100, 0, 0, 0); + ++i; + } + else + { + m_Burning.RemoveAt(i); + } + } + + if (DateTime.UtcNow >= m_Expire) + { + m_Timer.Stop(); + Delete(); + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/FlippableAddonAttribute.cs b/Projects/UOContent/Items/Misc/FlippableAddonAttribute.cs index 1f83e24ca..934a95ba3 100644 --- a/Projects/UOContent/Items/Misc/FlippableAddonAttribute.cs +++ b/Projects/UOContent/Items/Misc/FlippableAddonAttribute.cs @@ -1,114 +1,113 @@ -using System; -using System.Reflection; -using Server.Multis; - -namespace Server.Items -{ - [AttributeUsage(AttributeTargets.Class)] - public class FlippableAddonAttribute : Attribute - { - private static readonly string m_MethodName = "Flip"; - - private static readonly Type[] m_Params = - { - typeof(Mobile), typeof(Direction) - }; - - public FlippableAddonAttribute(params Direction[] directions) => Directions = directions; - - public Direction[] Directions { get; } - - public virtual void Flip(Mobile from, Item addon) - { - if (Directions?.Length > 1) - try - { - MethodInfo flipMethod = addon.GetType().GetMethod(m_MethodName, m_Params); - - if (flipMethod != null) - { - int index = 0; - - for (int i = 0; i < Directions.Length; i++) - if (addon.Direction == Directions[i]) - { - index = i + 1; - break; - } - - if (index >= Directions.Length) - index = 0; - - ClearComponents(addon); - - flipMethod.Invoke(addon, new object[] { from, Directions[index] }); - - BaseHouse house = null; - AddonFitResult result = AddonFitResult.Valid; - - addon.Map = Map.Internal; - - if (addon is BaseAddon baseAddon) - result = baseAddon.CouldFit(baseAddon.Location, from.Map, from, ref house); - else if (addon is BaseAddonContainer container) - result = container.CouldFit(container.Location, from.Map, from, ref house); - - addon.Map = from.Map; - - if (result != AddonFitResult.Valid) - { - if (index == 0) - index = Directions.Length - 1; - else - index -= 1; - - ClearComponents(addon); - - flipMethod.Invoke(addon, new object[2] { from, Directions[index] }); - - if (result == AddonFitResult.Blocked) - from.SendLocalizedMessage(500269); // You cannot build that there. - else if (result == AddonFitResult.NotInHouse) - from.SendLocalizedMessage(500274); // You can only place this in a house that you own! - else if (result == AddonFitResult.DoorsNotClosed) - from.SendMessage("You must close all house doors before placing this."); - else if (result == AddonFitResult.DoorTooClose) - from.SendLocalizedMessage(500271); // You cannot build near the door. - else if (result == AddonFitResult.NoWall) - from.SendLocalizedMessage(500268); // This object needs to be mounted on something. - } - - addon.Direction = Directions[index]; - } - } - catch - { - // ignored - } - } - - private void ClearComponents(Item item) - { - if (item is BaseAddon addon) - { - foreach (AddonComponent c in addon.Components) - { - c.Addon = null; - c.Delete(); - } - - addon.Components.Clear(); - } - else if (item is BaseAddonContainer addonContainer) - { - foreach (AddonContainerComponent c in addonContainer.Components) - { - c.Addon = null; - c.Delete(); - } - - addonContainer.Components.Clear(); - } - } - } -} +using System; +using Server.Multis; + +namespace Server.Items +{ + [AttributeUsage(AttributeTargets.Class)] + public class FlippableAddonAttribute : Attribute + { + private static readonly string m_MethodName = "Flip"; + + private static readonly Type[] m_Params = + { + typeof(Mobile), typeof(Direction) + }; + + public FlippableAddonAttribute(params Direction[] directions) => Directions = directions; + + public Direction[] Directions { get; } + + public virtual void Flip(Mobile from, Item addon) + { + if (Directions?.Length > 1) + try + { + var flipMethod = addon.GetType().GetMethod(m_MethodName, m_Params); + + if (flipMethod != null) + { + var index = 0; + + for (var i = 0; i < Directions.Length; i++) + if (addon.Direction == Directions[i]) + { + index = i + 1; + break; + } + + if (index >= Directions.Length) + index = 0; + + ClearComponents(addon); + + flipMethod.Invoke(addon, new object[] { from, Directions[index] }); + + BaseHouse house = null; + var result = AddonFitResult.Valid; + + addon.Map = Map.Internal; + + if (addon is BaseAddon baseAddon) + result = baseAddon.CouldFit(baseAddon.Location, from.Map, from, ref house); + else if (addon is BaseAddonContainer container) + result = container.CouldFit(container.Location, from.Map, from, ref house); + + addon.Map = from.Map; + + if (result != AddonFitResult.Valid) + { + if (index == 0) + index = Directions.Length - 1; + else + index -= 1; + + ClearComponents(addon); + + flipMethod.Invoke(addon, new object[2] { from, Directions[index] }); + + if (result == AddonFitResult.Blocked) + from.SendLocalizedMessage(500269); // You cannot build that there. + else if (result == AddonFitResult.NotInHouse) + from.SendLocalizedMessage(500274); // You can only place this in a house that you own! + else if (result == AddonFitResult.DoorsNotClosed) + from.SendMessage("You must close all house doors before placing this."); + else if (result == AddonFitResult.DoorTooClose) + from.SendLocalizedMessage(500271); // You cannot build near the door. + else if (result == AddonFitResult.NoWall) + from.SendLocalizedMessage(500268); // This object needs to be mounted on something. + } + + addon.Direction = Directions[index]; + } + } + catch + { + // ignored + } + } + + private void ClearComponents(Item item) + { + if (item is BaseAddon addon) + { + foreach (var c in addon.Components) + { + c.Addon = null; + c.Delete(); + } + + addon.Components.Clear(); + } + else if (item is BaseAddonContainer addonContainer) + { + foreach (var c in addonContainer.Components) + { + c.Addon = null; + c.Delete(); + } + + addonContainer.Components.Clear(); + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/FlippableAttribute.cs b/Projects/UOContent/Items/Misc/FlippableAttribute.cs index 364883443..1b7686308 100644 --- a/Projects/UOContent/Items/Misc/FlippableAttribute.cs +++ b/Projects/UOContent/Items/Misc/FlippableAttribute.cs @@ -1,91 +1,91 @@ -using System; -using Server.Targeting; - -namespace Server.Items -{ - public class FlipCommandHandlers - { - public static void Initialize() - { - CommandSystem.Register("Flip", AccessLevel.GameMaster, Flip_OnCommand); - } - - [Usage("Flip")] - [Description("Turns an item.")] - public static void Flip_OnCommand(CommandEventArgs e) - { - e.Mobile.Target = new FlipTarget(); - } - - private class FlipTarget : Target - { - public FlipTarget() - : base(-1, false, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is Item item) - { - if (item.Movable == false && from.AccessLevel == AccessLevel.Player) - return; - - Type type = item.GetType(); - - FlippableAttribute[] AttributeArray = - (FlippableAttribute[])type.GetCustomAttributes(typeof(FlippableAttribute), false); - - if (AttributeArray.Length == 0) return; - - FlippableAttribute fa = AttributeArray[0]; - - fa.Flip(item); - } - } - } - } - - [AttributeUsage(AttributeTargets.Class)] - public class DynamicFlipingAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Class)] - public class FlippableAttribute : Attribute - { - public FlippableAttribute(params int[] itemIDs) => ItemIDs = itemIDs; - - public int[] ItemIDs { get; } - - public virtual void Flip(Item item) - { - if (ItemIDs == null) - { - try - { - item.GetType().GetMethod("Flip", Type.EmptyTypes)?.Invoke(item, Array.Empty()); - } - catch - { - // ignored - } - } - else - { - int index = 0; - for (int i = 0; i < ItemIDs.Length; i++) - if (item.ItemID == ItemIDs[i]) - { - index = i + 1; - break; - } - - if (index > ItemIDs.Length - 1) - index = 0; - - item.ItemID = ItemIDs[index]; - } - } - } -} +using System; +using Server.Targeting; + +namespace Server.Items +{ + public class FlipCommandHandlers + { + public static void Initialize() + { + CommandSystem.Register("Flip", AccessLevel.GameMaster, Flip_OnCommand); + } + + [Usage("Flip")] + [Description("Turns an item.")] + public static void Flip_OnCommand(CommandEventArgs e) + { + e.Mobile.Target = new FlipTarget(); + } + + private class FlipTarget : Target + { + public FlipTarget() + : base(-1, false, TargetFlags.None) + { + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted is Item item) + { + if (item.Movable == false && from.AccessLevel == AccessLevel.Player) + return; + + var type = item.GetType(); + + var AttributeArray = + (FlippableAttribute[])type.GetCustomAttributes(typeof(FlippableAttribute), false); + + if (AttributeArray.Length == 0) return; + + var fa = AttributeArray[0]; + + fa.Flip(item); + } + } + } + } + + [AttributeUsage(AttributeTargets.Class)] + public class DynamicFlipingAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Class)] + public class FlippableAttribute : Attribute + { + public FlippableAttribute(params int[] itemIDs) => ItemIDs = itemIDs; + + public int[] ItemIDs { get; } + + public virtual void Flip(Item item) + { + if (ItemIDs == null) + { + try + { + item.GetType().GetMethod("Flip", Type.EmptyTypes)?.Invoke(item, Array.Empty()); + } + catch + { + // ignored + } + } + else + { + var index = 0; + for (var i = 0; i < ItemIDs.Length; i++) + if (item.ItemID == ItemIDs[i]) + { + index = i + 1; + break; + } + + if (index > ItemIDs.Length - 1) + index = 0; + + item.ItemID = ItemIDs[index]; + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/GlassItems.cs b/Projects/UOContent/Items/Misc/GlassItems.cs index ec831f641..86e3a7471 100644 --- a/Projects/UOContent/Items/Misc/GlassItems.cs +++ b/Projects/UOContent/Items/Misc/GlassItems.cs @@ -1,1215 +1,1215 @@ -namespace Server.Items -{ - [Flippable(0x182E, 0x182F, 0x1830, 0x1831)] - public class SmallFlask : Item - { - [Constructible] - public SmallFlask() : base(0x182E) - { - Weight = 1.0; - Movable = true; - } - - public SmallFlask(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x182A, 0x182B, 0x182C, 0x182D)] - public class MediumFlask : Item - { - [Constructible] - public MediumFlask() : base(0x182A) - { - Weight = 1.0; - Movable = true; - } - - public MediumFlask(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x183B, 0x183C, 0x183D)] - public class LargeFlask : Item - { - [Constructible] - public LargeFlask() : base(0x183B) - { - Weight = 1.0; - Movable = true; - } - - public LargeFlask(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1832, 0x1833, 0x1834, 0x1835, 0x1836, 0x1837)] - public class CurvedFlask : Item - { - [Constructible] - public CurvedFlask() : base(0x1832) - { - Weight = 1.0; - Movable = true; - } - - public CurvedFlask(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1838, 0x1839, 0x183A)] - public class LongFlask : Item - { - [Constructible] - public LongFlask() : base(0x1838) - { - Weight = 1.0; - Movable = true; - } - - public LongFlask(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1810, 0x1811)] - public class SpinningHourglass : Item - { - [Constructible] - public SpinningHourglass() : base(0x1810) - { - Weight = 1.0; - Movable = true; - } - - public SpinningHourglass(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GreenBottle : Item - { - [Constructible] - public GreenBottle() : base(0x0EFB) - { - Weight = 1.0; - Movable = true; - } - - public GreenBottle(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class RedBottle : Item - { - [Constructible] - public RedBottle() : base(0x0EFC) - { - Weight = 1.0; - Movable = true; - } - - public RedBottle(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SmallBrownBottle : Item - { - [Constructible] - public SmallBrownBottle() : base(0x0EFD) - { - Weight = 1.0; - Movable = true; - } - - public SmallBrownBottle(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SmallGreenBottle : Item - { - [Constructible] - public SmallGreenBottle() : base(0x0F01) - { - Weight = 1.0; - Movable = true; - } - - public SmallGreenBottle(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SmallVioletBottle : Item - { - [Constructible] - public SmallVioletBottle() : base(0x0F02) - { - Weight = 1.0; - Movable = true; - } - - public SmallVioletBottle(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class TinyYellowBottle : Item - { - [Constructible] - public TinyYellowBottle() : base(0x0F03) - { - Weight = 1.0; - Movable = true; - } - - public TinyYellowBottle(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - // remove - public class SmallBlueFlask : Item - { - [Constructible] - public SmallBlueFlask() : base(0x182A) - { - Weight = 1.0; - Movable = true; - } - - public SmallBlueFlask(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SmallYellowFlask : Item - { - [Constructible] - public SmallYellowFlask() : base(0x182B) - { - Weight = 1.0; - Movable = true; - } - - public SmallYellowFlask(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SmallRedFlask : Item - { - [Constructible] - public SmallRedFlask() : base(0x182C) - { - Weight = 1.0; - Movable = true; - } - - public SmallRedFlask(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SmallEmptyFlask : Item - { - [Constructible] - public SmallEmptyFlask() : base(0x182D) - { - Weight = 1.0; - Movable = true; - } - - public SmallEmptyFlask(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class YellowBeaker : Item - { - [Constructible] - public YellowBeaker() : base(0x182E) - { - Weight = 1.0; - Movable = true; - } - - public YellowBeaker(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class RedBeaker : Item - { - [Constructible] - public RedBeaker() : base(0x182F) - { - Weight = 1.0; - Movable = true; - } - - public RedBeaker(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BlueBeaker : Item - { - [Constructible] - public BlueBeaker() : base(0x1830) - { - Weight = 1.0; - Movable = true; - } - - public BlueBeaker(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GreenBeaker : Item - { - [Constructible] - public GreenBeaker() : base(0x1831) - { - Weight = 1.0; - Movable = true; - } - - public GreenBeaker(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class EmptyCurvedFlaskW : Item - { - [Constructible] - public EmptyCurvedFlaskW() : base(0x1832) - { - Weight = 1.0; - Movable = true; - } - - public EmptyCurvedFlaskW(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class RedCurvedFlask : Item - { - [Constructible] - public RedCurvedFlask() : base(0x1833) - { - Weight = 1.0; - Movable = true; - } - - public RedCurvedFlask(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LtBlueCurvedFlask : Item - { - [Constructible] - public LtBlueCurvedFlask() : base(0x1834) - { - Weight = 1.0; - Movable = true; - } - - public LtBlueCurvedFlask(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class EmptyCurvedFlaskE : Item - { - [Constructible] - public EmptyCurvedFlaskE() : base(0x1835) - { - Weight = 1.0; - Movable = true; - } - - public EmptyCurvedFlaskE(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BlueCurvedFlask : Item - { - [Constructible] - public BlueCurvedFlask() : base(0x1836) - { - Weight = 1.0; - Movable = true; - } - - public BlueCurvedFlask(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GreenCurvedFlask : Item - { - [Constructible] - public GreenCurvedFlask() : base(0x1837) - { - Weight = 1.0; - Movable = true; - } - - public GreenCurvedFlask(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class RedRibbedFlask : Item - { - [Constructible] - public RedRibbedFlask() : base(0x1838) - { - Weight = 1.0; - Movable = true; - } - - public RedRibbedFlask(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class VioletRibbedFlask : Item - { - [Constructible] - public VioletRibbedFlask() : base(0x1839) - { - Weight = 1.0; - Movable = true; - } - - public VioletRibbedFlask(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class EmptyRibbedFlask : Item - { - [Constructible] - public EmptyRibbedFlask() : base(0x183A) - { - Weight = 1.0; - Movable = true; - } - - public EmptyRibbedFlask(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LargeYellowFlask : Item - { - [Constructible] - public LargeYellowFlask() : base(0x183B) - { - Weight = 1.0; - Movable = true; - } - - public LargeYellowFlask(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LargeVioletFlask : Item - { - [Constructible] - public LargeVioletFlask() : base(0x183C) - { - Weight = 1.0; - Movable = true; - } - - public LargeVioletFlask(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LargeEmptyFlask : Item - { - [Constructible] - public LargeEmptyFlask() : base(0x183D) - { - Weight = 1.0; - Movable = true; - } - - public LargeEmptyFlask(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class AniRedRibbedFlask : Item - { - [Constructible] - public AniRedRibbedFlask() : base(0x183E) - { - Weight = 1.0; - Movable = true; - } - - public AniRedRibbedFlask(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class AniLargeVioletFlask : Item - { - [Constructible] - public AniLargeVioletFlask() : base(0x1841) - { - Weight = 1.0; - Movable = true; - } - - public AniLargeVioletFlask(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class AniSmallBlueFlask : Item - { - [Constructible] - public AniSmallBlueFlask() : base(0x1844) - { - Weight = 1.0; - Movable = true; - } - - public AniSmallBlueFlask(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SmallBlueBottle : Item - { - [Constructible] - public SmallBlueBottle() : base(0x1847) - { - Weight = 1.0; - Movable = true; - } - - public SmallBlueBottle(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SmallGreenBottle2 : Item - { - [Constructible] - public SmallGreenBottle2() : base(0x1848) - { - Weight = 1.0; - Movable = true; - } - - public SmallGreenBottle2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x185B, 0x185C)] - public class EmptyVialsWRack : Item - { - [Constructible] - public EmptyVialsWRack() : base(0x185B) - { - Weight = 1.0; - Movable = true; - } - - public EmptyVialsWRack(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x185D, 0x185E)] - public class FullVialsWRack : Item - { - [Constructible] - public FullVialsWRack() : base(0x185D) - { - Weight = 1.0; - Movable = true; - } - - public FullVialsWRack(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class EmptyVial : Item - { - [Constructible] - public EmptyVial() : base(0x0E24) - { - Weight = 1.0; - Movable = true; - } - - public EmptyVial(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class HourglassAni : Item - { - [Constructible] - public HourglassAni() : base(0x1811) - { - Weight = 1.0; - Movable = true; - } - - public HourglassAni(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Hourglass : Item - { - [Constructible] - public Hourglass() : base(0x1810) - { - Weight = 1.0; - Movable = true; - } - - public Hourglass(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class TinyRedBottle : Item - { - [Constructible] - public TinyRedBottle() : base(0x0F04) - { - Weight = 1.0; - Movable = true; - } - - public TinyRedBottle(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x182E, 0x182F, 0x1830, 0x1831)] + public class SmallFlask : Item + { + [Constructible] + public SmallFlask() : base(0x182E) + { + Weight = 1.0; + Movable = true; + } + + public SmallFlask(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x182A, 0x182B, 0x182C, 0x182D)] + public class MediumFlask : Item + { + [Constructible] + public MediumFlask() : base(0x182A) + { + Weight = 1.0; + Movable = true; + } + + public MediumFlask(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x183B, 0x183C, 0x183D)] + public class LargeFlask : Item + { + [Constructible] + public LargeFlask() : base(0x183B) + { + Weight = 1.0; + Movable = true; + } + + public LargeFlask(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1832, 0x1833, 0x1834, 0x1835, 0x1836, 0x1837)] + public class CurvedFlask : Item + { + [Constructible] + public CurvedFlask() : base(0x1832) + { + Weight = 1.0; + Movable = true; + } + + public CurvedFlask(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1838, 0x1839, 0x183A)] + public class LongFlask : Item + { + [Constructible] + public LongFlask() : base(0x1838) + { + Weight = 1.0; + Movable = true; + } + + public LongFlask(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x1810, 0x1811)] + public class SpinningHourglass : Item + { + [Constructible] + public SpinningHourglass() : base(0x1810) + { + Weight = 1.0; + Movable = true; + } + + public SpinningHourglass(Serial serial) : base(serial) + { + } + + 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 class GreenBottle : Item + { + [Constructible] + public GreenBottle() : base(0x0EFB) + { + Weight = 1.0; + Movable = true; + } + + public GreenBottle(Serial serial) : base(serial) + { + } + + 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 class RedBottle : Item + { + [Constructible] + public RedBottle() : base(0x0EFC) + { + Weight = 1.0; + Movable = true; + } + + public RedBottle(Serial serial) : base(serial) + { + } + + 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 class SmallBrownBottle : Item + { + [Constructible] + public SmallBrownBottle() : base(0x0EFD) + { + Weight = 1.0; + Movable = true; + } + + public SmallBrownBottle(Serial serial) : base(serial) + { + } + + 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 class SmallGreenBottle : Item + { + [Constructible] + public SmallGreenBottle() : base(0x0F01) + { + Weight = 1.0; + Movable = true; + } + + public SmallGreenBottle(Serial serial) : base(serial) + { + } + + 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 class SmallVioletBottle : Item + { + [Constructible] + public SmallVioletBottle() : base(0x0F02) + { + Weight = 1.0; + Movable = true; + } + + public SmallVioletBottle(Serial serial) : base(serial) + { + } + + 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 class TinyYellowBottle : Item + { + [Constructible] + public TinyYellowBottle() : base(0x0F03) + { + Weight = 1.0; + Movable = true; + } + + public TinyYellowBottle(Serial serial) : base(serial) + { + } + + 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(); + } + } + + // remove + public class SmallBlueFlask : Item + { + [Constructible] + public SmallBlueFlask() : base(0x182A) + { + Weight = 1.0; + Movable = true; + } + + public SmallBlueFlask(Serial serial) : base(serial) + { + } + + 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 class SmallYellowFlask : Item + { + [Constructible] + public SmallYellowFlask() : base(0x182B) + { + Weight = 1.0; + Movable = true; + } + + public SmallYellowFlask(Serial serial) : base(serial) + { + } + + 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 class SmallRedFlask : Item + { + [Constructible] + public SmallRedFlask() : base(0x182C) + { + Weight = 1.0; + Movable = true; + } + + public SmallRedFlask(Serial serial) : base(serial) + { + } + + 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 class SmallEmptyFlask : Item + { + [Constructible] + public SmallEmptyFlask() : base(0x182D) + { + Weight = 1.0; + Movable = true; + } + + public SmallEmptyFlask(Serial serial) : base(serial) + { + } + + 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 class YellowBeaker : Item + { + [Constructible] + public YellowBeaker() : base(0x182E) + { + Weight = 1.0; + Movable = true; + } + + public YellowBeaker(Serial serial) : base(serial) + { + } + + 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 class RedBeaker : Item + { + [Constructible] + public RedBeaker() : base(0x182F) + { + Weight = 1.0; + Movable = true; + } + + public RedBeaker(Serial serial) : base(serial) + { + } + + 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 class BlueBeaker : Item + { + [Constructible] + public BlueBeaker() : base(0x1830) + { + Weight = 1.0; + Movable = true; + } + + public BlueBeaker(Serial serial) : base(serial) + { + } + + 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 class GreenBeaker : Item + { + [Constructible] + public GreenBeaker() : base(0x1831) + { + Weight = 1.0; + Movable = true; + } + + public GreenBeaker(Serial serial) : base(serial) + { + } + + 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 class EmptyCurvedFlaskW : Item + { + [Constructible] + public EmptyCurvedFlaskW() : base(0x1832) + { + Weight = 1.0; + Movable = true; + } + + public EmptyCurvedFlaskW(Serial serial) : base(serial) + { + } + + 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 class RedCurvedFlask : Item + { + [Constructible] + public RedCurvedFlask() : base(0x1833) + { + Weight = 1.0; + Movable = true; + } + + public RedCurvedFlask(Serial serial) : base(serial) + { + } + + 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 class LtBlueCurvedFlask : Item + { + [Constructible] + public LtBlueCurvedFlask() : base(0x1834) + { + Weight = 1.0; + Movable = true; + } + + public LtBlueCurvedFlask(Serial serial) : base(serial) + { + } + + 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 class EmptyCurvedFlaskE : Item + { + [Constructible] + public EmptyCurvedFlaskE() : base(0x1835) + { + Weight = 1.0; + Movable = true; + } + + public EmptyCurvedFlaskE(Serial serial) : base(serial) + { + } + + 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 class BlueCurvedFlask : Item + { + [Constructible] + public BlueCurvedFlask() : base(0x1836) + { + Weight = 1.0; + Movable = true; + } + + public BlueCurvedFlask(Serial serial) : base(serial) + { + } + + 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 class GreenCurvedFlask : Item + { + [Constructible] + public GreenCurvedFlask() : base(0x1837) + { + Weight = 1.0; + Movable = true; + } + + public GreenCurvedFlask(Serial serial) : base(serial) + { + } + + 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 class RedRibbedFlask : Item + { + [Constructible] + public RedRibbedFlask() : base(0x1838) + { + Weight = 1.0; + Movable = true; + } + + public RedRibbedFlask(Serial serial) : base(serial) + { + } + + 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 class VioletRibbedFlask : Item + { + [Constructible] + public VioletRibbedFlask() : base(0x1839) + { + Weight = 1.0; + Movable = true; + } + + public VioletRibbedFlask(Serial serial) : base(serial) + { + } + + 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 class EmptyRibbedFlask : Item + { + [Constructible] + public EmptyRibbedFlask() : base(0x183A) + { + Weight = 1.0; + Movable = true; + } + + public EmptyRibbedFlask(Serial serial) : base(serial) + { + } + + 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 class LargeYellowFlask : Item + { + [Constructible] + public LargeYellowFlask() : base(0x183B) + { + Weight = 1.0; + Movable = true; + } + + public LargeYellowFlask(Serial serial) : base(serial) + { + } + + 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 class LargeVioletFlask : Item + { + [Constructible] + public LargeVioletFlask() : base(0x183C) + { + Weight = 1.0; + Movable = true; + } + + public LargeVioletFlask(Serial serial) : base(serial) + { + } + + 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 class LargeEmptyFlask : Item + { + [Constructible] + public LargeEmptyFlask() : base(0x183D) + { + Weight = 1.0; + Movable = true; + } + + public LargeEmptyFlask(Serial serial) : base(serial) + { + } + + 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 class AniRedRibbedFlask : Item + { + [Constructible] + public AniRedRibbedFlask() : base(0x183E) + { + Weight = 1.0; + Movable = true; + } + + public AniRedRibbedFlask(Serial serial) : base(serial) + { + } + + 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 class AniLargeVioletFlask : Item + { + [Constructible] + public AniLargeVioletFlask() : base(0x1841) + { + Weight = 1.0; + Movable = true; + } + + public AniLargeVioletFlask(Serial serial) : base(serial) + { + } + + 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 class AniSmallBlueFlask : Item + { + [Constructible] + public AniSmallBlueFlask() : base(0x1844) + { + Weight = 1.0; + Movable = true; + } + + public AniSmallBlueFlask(Serial serial) : base(serial) + { + } + + 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 class SmallBlueBottle : Item + { + [Constructible] + public SmallBlueBottle() : base(0x1847) + { + Weight = 1.0; + Movable = true; + } + + public SmallBlueBottle(Serial serial) : base(serial) + { + } + + 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 class SmallGreenBottle2 : Item + { + [Constructible] + public SmallGreenBottle2() : base(0x1848) + { + Weight = 1.0; + Movable = true; + } + + public SmallGreenBottle2(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x185B, 0x185C)] + public class EmptyVialsWRack : Item + { + [Constructible] + public EmptyVialsWRack() : base(0x185B) + { + Weight = 1.0; + Movable = true; + } + + public EmptyVialsWRack(Serial serial) : base(serial) + { + } + + 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(); + } + } + + [Flippable(0x185D, 0x185E)] + public class FullVialsWRack : Item + { + [Constructible] + public FullVialsWRack() : base(0x185D) + { + Weight = 1.0; + Movable = true; + } + + public FullVialsWRack(Serial serial) : base(serial) + { + } + + 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 class EmptyVial : Item + { + [Constructible] + public EmptyVial() : base(0x0E24) + { + Weight = 1.0; + Movable = true; + } + + public EmptyVial(Serial serial) : base(serial) + { + } + + 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 class HourglassAni : Item + { + [Constructible] + public HourglassAni() : base(0x1811) + { + Weight = 1.0; + Movable = true; + } + + public HourglassAni(Serial serial) : base(serial) + { + } + + 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 class Hourglass : Item + { + [Constructible] + public Hourglass() : base(0x1810) + { + Weight = 1.0; + Movable = true; + } + + public Hourglass(Serial serial) : base(serial) + { + } + + 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 class TinyRedBottle : Item + { + [Constructible] + public TinyRedBottle() : base(0x0F04) + { + Weight = 1.0; + Movable = true; + } + + public TinyRedBottle(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Gold.cs b/Projects/UOContent/Items/Misc/Gold.cs index 718cbd91b..a920a1c70 100644 --- a/Projects/UOContent/Items/Misc/Gold.cs +++ b/Projects/UOContent/Items/Misc/Gold.cs @@ -1,122 +1,122 @@ -using System; -using Server.Accounting; - -namespace Server.Items -{ - public class Gold : Item - { - [Constructible] - public Gold(int amountFrom, int amountTo) : this(Utility.RandomMinMax(amountFrom, amountTo)) - { - } - - [Constructible] - public Gold(int amount = 1) : base(0xEED) - { - Stackable = true; - Amount = amount; - } - - public Gold(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => Core.ML ? 0.02 / 3 : 0.02; - - public override int GetDropSound() - { - if (Amount <= 1) - return 0x2E4; - if (Amount <= 5) - return 0x2E5; - return 0x2E6; - } - - protected override void OnAmountChange(int oldValue) - { - int newValue = Amount; - - UpdateTotal(this, TotalType.Gold, newValue - oldValue); - } - - public override void OnAdded(IEntity parent) - { - base.OnAdded(parent); - - if (!AccountGold.Enabled) return; - - Mobile owner = null; - SecureTradeInfo tradeInfo = null; - - Container root = parent as Container; - - while (root?.Parent is Container container) - root = container; - - parent = root ?? parent; - - if (parent is SecureTradeContainer trade && AccountGold.ConvertOnTrade) - { - if (trade.Trade.From.Container == trade) - { - tradeInfo = trade.Trade.From; - owner = tradeInfo.Mobile; - } - else if (trade.Trade.To.Container == trade) - { - tradeInfo = trade.Trade.To; - owner = tradeInfo.Mobile; - } - } - else if (parent is BankBox box && AccountGold.ConvertOnBank) - { - owner = box.Owner; - } - - if (owner?.Account?.DepositGold(Amount) != true) return; - - if (tradeInfo != null) - { - if (owner.NetState?.NewSecureTrading == false) - { - int plat = Math.DivRem(Amount, AccountGold.CurrencyThreshold, out int gold); - - tradeInfo.Plat += plat; - tradeInfo.Gold += gold; - } - - tradeInfo.VirtualCheck?.UpdateTrade(tradeInfo.Mobile); - } - - owner.SendLocalizedMessage(1042763, Amount.ToString("#,0")); - - Delete(); - - ((Container)parent).UpdateTotals(); - } - - public override int GetTotal(TotalType type) - { - int baseTotal = base.GetTotal(type); - - if (type == TotalType.Gold) - baseTotal += Amount; - - return baseTotal; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using Server.Accounting; + +namespace Server.Items +{ + public class Gold : Item + { + [Constructible] + public Gold(int amountFrom, int amountTo) : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } + + [Constructible] + public Gold(int amount = 1) : base(0xEED) + { + Stackable = true; + Amount = amount; + } + + public Gold(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => Core.ML ? 0.02 / 3 : 0.02; + + public override int GetDropSound() + { + if (Amount <= 1) + return 0x2E4; + if (Amount <= 5) + return 0x2E5; + return 0x2E6; + } + + protected override void OnAmountChange(int oldValue) + { + var newValue = Amount; + + UpdateTotal(this, TotalType.Gold, newValue - oldValue); + } + + public override void OnAdded(IEntity parent) + { + base.OnAdded(parent); + + if (!AccountGold.Enabled) return; + + Mobile owner = null; + SecureTradeInfo tradeInfo = null; + + var root = parent as Container; + + while (root?.Parent is Container container) + root = container; + + parent = root ?? parent; + + if (parent is SecureTradeContainer trade && AccountGold.ConvertOnTrade) + { + if (trade.Trade.From.Container == trade) + { + tradeInfo = trade.Trade.From; + owner = tradeInfo.Mobile; + } + else if (trade.Trade.To.Container == trade) + { + tradeInfo = trade.Trade.To; + owner = tradeInfo.Mobile; + } + } + else if (parent is BankBox box && AccountGold.ConvertOnBank) + { + owner = box.Owner; + } + + if (owner?.Account?.DepositGold(Amount) != true) return; + + if (tradeInfo != null) + { + if (owner.NetState?.NewSecureTrading == false) + { + var plat = Math.DivRem(Amount, AccountGold.CurrencyThreshold, out var gold); + + tradeInfo.Plat += plat; + tradeInfo.Gold += gold; + } + + tradeInfo.VirtualCheck?.UpdateTrade(tradeInfo.Mobile); + } + + owner.SendLocalizedMessage(1042763, Amount.ToString("#,0")); + + Delete(); + + ((Container)parent).UpdateTotals(); + } + + public override int GetTotal(TotalType type) + { + var baseTotal = base.GetTotal(type); + + if (type == TotalType.Gold) + baseTotal += Amount; + + return baseTotal; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Guillotine.cs b/Projects/UOContent/Items/Misc/Guillotine.cs index dfdf87b0b..6d73e1a64 100644 --- a/Projects/UOContent/Items/Misc/Guillotine.cs +++ b/Projects/UOContent/Items/Misc/Guillotine.cs @@ -1,113 +1,113 @@ -using System; -using Server.Network; -using Server.Spells; - -namespace Server.Items -{ - public class Guillotine : Item - { - private DateTime m_NextUse; - - [Constructible] - public Guillotine() - : base(4656) => - Movable = false; - - public Guillotine(Serial serial) - : base(serial) - { - } - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 2) || !from.InLOS(this)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that - } - else if (Visible && (ItemID == 4656 || ItemID == 4702) && DateTime.UtcNow >= m_NextUse) - { - Point3D p = GetWorldLocation(); - - if (Utility.Random(Math.Max(Math.Abs(from.X - p.X), Math.Abs(from.Y - p.Y))) < 1) - { - Effects.PlaySound(from.Location, from.Map, from.GetHurtSound()); - from.PublicOverheadMessage(MessageType.Regular, from.SpeechHue, true, "Ouch!"); - SpellHelper.Damage(TimeSpan.FromSeconds(0.5), from, Utility.Dice(2, 10, 5)); - } - - Effects.PlaySound(GetWorldLocation(), Map, 0x387); - - Timer.DelayCall(TimeSpan.FromSeconds(0.25), Down1); - Timer.DelayCall(TimeSpan.FromSeconds(0.50), Down2); - - Timer.DelayCall(TimeSpan.FromSeconds(5.00), BackUp); - - m_NextUse = DateTime.UtcNow + TimeSpan.FromSeconds(10.0); - } - } - - private void Down1() - { - ItemID = ItemID == 4656 ? 4678 : 4712; - } - - private void Down2() - { - ItemID = ItemID == 4678 ? 4679 : 4713; - - Point3D p = GetWorldLocation(); - Map f = Map; - - if (f == null) - return; - - new Blood(4650).MoveToWorld(p, f); - - for (int i = 0; i < 4; ++i) - { - int x = p.X - 2 + Utility.Random(5); - int y = p.Y - 2 + Utility.Random(5); - int z = p.Z; - - if (!f.CanFit(x, y, z, 1, false, false)) - { - z = f.GetAverageZ(x, y); - - if (!f.CanFit(x, y, z, 1, false, false)) - continue; - } - - Point3D loc = f.GetRandomNearbyLocation(p, 2, -2, 4, 1); - - new Blood().MoveToWorld(loc, f); - } - } - - private void BackUp() - { - if (ItemID == 4678 || ItemID == 4679) - ItemID = 4656; - else if (ItemID == 4712 || ItemID == 4713) - ItemID = 4702; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write((byte)0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadByte(); - - if (ItemID == 4678 || ItemID == 4679) - ItemID = 4656; - else if (ItemID == 4712 || ItemID == 4713) - ItemID = 4702; - } - } -} +using System; +using Server.Network; +using Server.Spells; + +namespace Server.Items +{ + public class Guillotine : Item + { + private DateTime m_NextUse; + + [Constructible] + public Guillotine() + : base(4656) => + Movable = false; + + public Guillotine(Serial serial) + : base(serial) + { + } + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 2) || !from.InLOS(this)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that + } + else if (Visible && (ItemID == 4656 || ItemID == 4702) && DateTime.UtcNow >= m_NextUse) + { + var p = GetWorldLocation(); + + if (Utility.Random(Math.Max(Math.Abs(from.X - p.X), Math.Abs(from.Y - p.Y))) < 1) + { + Effects.PlaySound(from.Location, from.Map, from.GetHurtSound()); + from.PublicOverheadMessage(MessageType.Regular, from.SpeechHue, true, "Ouch!"); + SpellHelper.Damage(TimeSpan.FromSeconds(0.5), from, Utility.Dice(2, 10, 5)); + } + + Effects.PlaySound(GetWorldLocation(), Map, 0x387); + + Timer.DelayCall(TimeSpan.FromSeconds(0.25), Down1); + Timer.DelayCall(TimeSpan.FromSeconds(0.50), Down2); + + Timer.DelayCall(TimeSpan.FromSeconds(5.00), BackUp); + + m_NextUse = DateTime.UtcNow + TimeSpan.FromSeconds(10.0); + } + } + + private void Down1() + { + ItemID = ItemID == 4656 ? 4678 : 4712; + } + + private void Down2() + { + ItemID = ItemID == 4678 ? 4679 : 4713; + + var p = GetWorldLocation(); + var f = Map; + + if (f == null) + return; + + new Blood(4650).MoveToWorld(p, f); + + for (var i = 0; i < 4; ++i) + { + var x = p.X - 2 + Utility.Random(5); + var y = p.Y - 2 + Utility.Random(5); + var z = p.Z; + + if (!f.CanFit(x, y, z, 1, false, false)) + { + z = f.GetAverageZ(x, y); + + if (!f.CanFit(x, y, z, 1, false, false)) + continue; + } + + var loc = f.GetRandomNearbyLocation(p, 2, -2, 4, 1); + + new Blood().MoveToWorld(loc, f); + } + } + + private void BackUp() + { + if (ItemID == 4678 || ItemID == 4679) + ItemID = 4656; + else if (ItemID == 4712 || ItemID == 4713) + ItemID = 4702; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write((byte)0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + int version = reader.ReadByte(); + + if (ItemID == 4678 || ItemID == 4679) + ItemID = 4656; + else if (ItemID == 4712 || ItemID == 4713) + ItemID = 4702; + } + } +} diff --git a/Projects/UOContent/Items/Misc/HairDye.cs b/Projects/UOContent/Items/Misc/HairDye.cs index 07dace4b5..b1615becb 100644 --- a/Projects/UOContent/Items/Misc/HairDye.cs +++ b/Projects/UOContent/Items/Misc/HairDye.cs @@ -1,166 +1,166 @@ -using Server.Gumps; -using Server.Network; - -namespace Server.Items -{ - public class HairDye : Item - { - [Constructible] - public HairDye() : base(0xEFF) => Weight = 1.0; - - public HairDye(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041060; // Hair Dye - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(GetWorldLocation(), 1)) - { - from.CloseGump(); - from.SendGump(new HairDyeGump(this)); - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 906, 1019045); // I can't reach that. - } - } - } - - public class HairDyeGump : Gump - { - private static readonly HairDyeEntry[] m_Entries = - { - new HairDyeEntry("*****", 1602, 26), - new HairDyeEntry("*****", 1628, 27), - new HairDyeEntry("*****", 1502, 32), - new HairDyeEntry("*****", 1302, 32), - new HairDyeEntry("*****", 1402, 32), - new HairDyeEntry("*****", 1202, 24), - new HairDyeEntry("*****", 2402, 29), - new HairDyeEntry("*****", 2213, 6), - new HairDyeEntry("*****", 1102, 8), - new HairDyeEntry("*****", 1110, 8), - new HairDyeEntry("*****", 1118, 16), - new HairDyeEntry("*****", 1134, 16) - }; - - private readonly HairDye m_HairDye; - - public HairDyeGump(HairDye dye) : base(50, 50) - { - m_HairDye = dye; - - AddPage(0); - - AddBackground(100, 10, 350, 355, 2600); - AddBackground(120, 54, 110, 270, 5100); - - AddHtmlLocalized(70, 25, 400, 35, 1011013); //
Hair Color Selection Menu
- - AddButton(149, 328, 4005, 4007, 1); - AddHtmlLocalized(185, 329, 250, 35, 1011014); // Dye my hair this color! - - for (int i = 0; i < m_Entries.Length; ++i) - { - AddLabel(130, 59 + i * 22, m_Entries[i].HueStart - 1, m_Entries[i].Name); - AddButton(207, 60 + i * 22, 5224, 5224, 0, GumpButtonType.Page, i + 1); - } - - for (int i = 0; i < m_Entries.Length; ++i) - { - HairDyeEntry e = m_Entries[i]; - - AddPage(i + 1); - - for (int j = 0; j < e.HueCount; ++j) - { - AddLabel(278 + j / 16 * 80, 52 + j % 16 * 17, e.HueStart + j - 1, "*****"); - AddRadio(260 + j / 16 * 80, 52 + j % 16 * 17, 210, 211, false, i * 100 + j); - } - } - } - - public override void OnResponse(NetState from, RelayInfo info) - { - if (m_HairDye.Deleted) - return; - - Mobile m = from.Mobile; - int[] switches = info.Switches; - - if (!m_HairDye.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.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 - - int entryIndex = switches[0] / 100; - int hueOffset = switches[0] % 100; - - if (entryIndex >= 0 && entryIndex < m_Entries.Length) - { - HairDyeEntry e = m_Entries[entryIndex]; - - if (hueOffset >= 0 && hueOffset < e.HueCount) - { - int hue = e.HueStart + hueOffset; - - m.HairHue = hue; - m.FacialHairHue = hue; - - m.SendLocalizedMessage(501199); // You dye your hair - m_HairDye.Delete(); - m.PlaySound(0x4E); - } - } - } - } - else - { - m.SendLocalizedMessage(501200); // You decide not to dye your hair - } - } - - private class HairDyeEntry - { - public HairDyeEntry(string name, int hueStart, int hueCount) - { - Name = name; - HueStart = hueStart; - HueCount = hueCount; - } - - public string Name { get; } - - public int HueStart { get; } - - public int HueCount { get; } - } - } -} +using Server.Gumps; +using Server.Network; + +namespace Server.Items +{ + public class HairDye : Item + { + [Constructible] + public HairDye() : base(0xEFF) => Weight = 1.0; + + public HairDye(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041060; // 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 HairDyeGump(this)); + } + else + { + from.LocalOverheadMessage(MessageType.Regular, 906, 1019045); // I can't reach that. + } + } + } + + public class HairDyeGump : Gump + { + private static readonly HairDyeEntry[] m_Entries = + { + new HairDyeEntry("*****", 1602, 26), + new HairDyeEntry("*****", 1628, 27), + new HairDyeEntry("*****", 1502, 32), + new HairDyeEntry("*****", 1302, 32), + new HairDyeEntry("*****", 1402, 32), + new HairDyeEntry("*****", 1202, 24), + new HairDyeEntry("*****", 2402, 29), + new HairDyeEntry("*****", 2213, 6), + new HairDyeEntry("*****", 1102, 8), + new HairDyeEntry("*****", 1110, 8), + new HairDyeEntry("*****", 1118, 16), + new HairDyeEntry("*****", 1134, 16) + }; + + private readonly HairDye m_HairDye; + + public HairDyeGump(HairDye dye) : base(50, 50) + { + m_HairDye = dye; + + AddPage(0); + + AddBackground(100, 10, 350, 355, 2600); + AddBackground(120, 54, 110, 270, 5100); + + AddHtmlLocalized(70, 25, 400, 35, 1011013); //
Hair Color Selection Menu
+ + AddButton(149, 328, 4005, 4007, 1); + AddHtmlLocalized(185, 329, 250, 35, 1011014); // Dye my hair this color! + + for (var i = 0; i < m_Entries.Length; ++i) + { + AddLabel(130, 59 + i * 22, m_Entries[i].HueStart - 1, m_Entries[i].Name); + AddButton(207, 60 + 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(278 + j / 16 * 80, 52 + j % 16 * 17, e.HueStart + j - 1, "*****"); + AddRadio(260 + j / 16 * 80, 52 + j % 16 * 17, 210, 211, false, i * 100 + j); + } + } + } + + public override void OnResponse(NetState from, RelayInfo info) + { + if (m_HairDye.Deleted) + return; + + var m = from.Mobile; + var switches = info.Switches; + + if (!m_HairDye.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.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.HairHue = hue; + m.FacialHairHue = hue; + + m.SendLocalizedMessage(501199); // You dye your hair + m_HairDye.Delete(); + m.PlaySound(0x4E); + } + } + } + } + else + { + m.SendLocalizedMessage(501200); // You decide not to dye your hair + } + } + + private class HairDyeEntry + { + public HairDyeEntry(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/HoveringWisp.cs b/Projects/UOContent/Items/Misc/HoveringWisp.cs index ef3a818c5..aacabb593 100644 --- a/Projects/UOContent/Items/Misc/HoveringWisp.cs +++ b/Projects/UOContent/Items/Misc/HoveringWisp.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class HoveringWisp : Item - { - [Constructible] - public HoveringWisp() : base(0x2100) - { - } - - public HoveringWisp(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072881; // hovering wisp - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class HoveringWisp : Item + { + [Constructible] + public HoveringWisp() : base(0x2100) + { + } + + public HoveringWisp(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072881; // hovering wisp + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/IDurability.cs b/Projects/UOContent/Items/Misc/IDurability.cs index bbd9fbb21..a3f49be21 100644 --- a/Projects/UOContent/Items/Misc/IDurability.cs +++ b/Projects/UOContent/Items/Misc/IDurability.cs @@ -1,21 +1,21 @@ -namespace Server.Items -{ - internal interface IDurability - { - bool CanFortify { get; } - - int InitMinHits { get; } - int InitMaxHits { get; } - - int HitPoints { get; set; } - int MaxHitPoints { get; set; } - - void ScaleDurability(); - void UnscaleDurability(); - } - - internal interface IWearableDurability : IDurability - { - int OnHit(BaseWeapon weapon, int damageTaken); - } -} \ No newline at end of file +namespace Server.Items +{ + internal interface IDurability + { + bool CanFortify { get; } + + int InitMinHits { get; } + int InitMaxHits { get; } + + int HitPoints { get; set; } + int MaxHitPoints { get; set; } + + void ScaleDurability(); + void UnscaleDurability(); + } + + internal interface IWearableDurability : IDurability + { + int OnHit(BaseWeapon weapon, int damageTaken); + } +} diff --git a/Projects/UOContent/Items/Misc/InteriorDecorator.cs b/Projects/UOContent/Items/Misc/InteriorDecorator.cs index 83c69930e..f1cd3483a 100644 --- a/Projects/UOContent/Items/Misc/InteriorDecorator.cs +++ b/Projects/UOContent/Items/Misc/InteriorDecorator.cs @@ -1,329 +1,329 @@ -using Server.Gumps; -using Server.Multis; -using Server.Network; -using Server.Targeting; - -namespace Server.Items -{ - public enum DecorateCommand - { - None, - Turn, - Up, - Down - } - - public class InteriorDecorator : Item - { - private DecorateCommand m_Command; - - [Constructible] - public InteriorDecorator() : base(0xFC1) - { - Weight = 1.0; - LootType = LootType.Blessed; - } - - public InteriorDecorator(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public DecorateCommand Command - { - get => m_Command; - set - { - m_Command = value; - InvalidateProperties(); - } - } - - public override int LabelNumber => 1041280; // an interior decorator - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_Command != DecorateCommand.None) - list.Add(1018322 + (int)m_Command); // Turn/Up/Down - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - if (!CheckUse(this, from)) - return; - - if (!from.HasGump()) - from.SendGump(new InternalGump(this)); - - if (m_Command != DecorateCommand.None) - from.Target = new InternalTarget(this); - } - - public static bool InHouse(Mobile from) - { - BaseHouse house = BaseHouse.FindHouseAt(from); - - return house?.IsCoOwner(from) == true; - } - - public static bool CheckUse(InteriorDecorator tool, Mobile from) - { - /*if (tool.Deleted || !tool.IsChildOf( from.Backpack )) - from.SendLocalizedMessage( 1042001 ); // That must be in your pack for you to use it. - else*/ - if (!InHouse(from)) - from.SendLocalizedMessage(502092); // You must be in your house to do this. - else - return true; - - return false; - } - - private class InternalGump : Gump - { - private readonly InteriorDecorator m_Decorator; - - public InternalGump(InteriorDecorator decorator) : base(150, 50) - { - m_Decorator = decorator; - - AddBackground(0, 0, 200, 200, 2600); - - AddButton(50, 45, decorator.Command == DecorateCommand.Turn ? 2154 : 2152, 2154, 1); - AddHtmlLocalized(90, 50, 70, 40, 1018323); // Turn - - AddButton(50, 95, decorator.Command == DecorateCommand.Up ? 2154 : 2152, 2154, 2); - AddHtmlLocalized(90, 100, 70, 40, 1018324); // Up - - AddButton(50, 145, decorator.Command == DecorateCommand.Down ? 2154 : 2152, 2154, 3); - AddHtmlLocalized(90, 150, 70, 40, 1018325); // Down - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - var command = info.ButtonID switch - { - 1 => DecorateCommand.Turn, - 2 => DecorateCommand.Up, - 3 => DecorateCommand.Down, - _ => DecorateCommand.None - }; - - if (command != DecorateCommand.None) - { - m_Decorator.Command = command; - sender.Mobile.SendGump(new InternalGump(m_Decorator)); - sender.Mobile.Target = new InternalTarget(m_Decorator); - } - else - { - Target.Cancel(sender.Mobile); - } - } - } - - private class InternalTarget : Target - { - private readonly InteriorDecorator m_Decorator; - - public InternalTarget(InteriorDecorator decorator) : base(-1, false, TargetFlags.None) - { - CheckLOS = false; - - m_Decorator = decorator; - } - - protected override void OnTargetNotAccessible(Mobile from, object targeted) - { - OnTarget(from, targeted); - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is Item item && CheckUse(m_Decorator, from)) - { - BaseHouse house = BaseHouse.FindHouseAt(from); - - bool isDecorableComponent = false; - object addon = null; - int count = 0; - - if (item is AddonComponent component) - { - count = component.Addon.Components.Count; - addon = component.Addon; - } - else if (item is AddonContainerComponent containerComponent) - { - count = containerComponent.Addon.Components.Count; - addon = containerComponent.Addon; - } - else if (item is BaseAddonContainer container) - { - count = container.Components.Count; - addon = container; - } - - if (addon != null) - { - if (count == 1 && Core.SE) - isDecorableComponent = true; - - if (m_Decorator.Command == DecorateCommand.Turn) - { - FlippableAddonAttribute[] attributes = - (FlippableAddonAttribute[])addon.GetType() - .GetCustomAttributes(typeof(FlippableAddonAttribute), false); - - if (attributes.Length > 0) - isDecorableComponent = true; - } - } - - if (house?.IsCoOwner(from) != true) - { - from.SendLocalizedMessage(502092); // You must be in your house to do this. - } - else if (item.Parent != null || !house.IsInside(item)) - { - from.SendLocalizedMessage(1042270); // That is not in your house. - } - else if (!house.HasLockedDownItem(item) && !house.HasSecureItem(item) && !isDecorableComponent) - { - if (item is AddonComponent && m_Decorator.Command == DecorateCommand.Up) - from.SendLocalizedMessage(1042274); // You cannot raise it up any higher. - else if (item is AddonComponent && m_Decorator.Command == DecorateCommand.Down) - from.SendLocalizedMessage(1042275); // You cannot lower it down any further. - else - from.SendLocalizedMessage(1042271); // That is not locked down. - } - else if (item is VendorRentalContract) - { - from.SendLocalizedMessage(1062491); // You cannot use the house decorator on that object. - } - else if (item.TotalWeight + item.PileWeight > 100) - { - from.SendLocalizedMessage(1042272); // That is too heavy. - } - else - { - switch (m_Decorator.Command) - { - case DecorateCommand.Up: - Up(item, from); - break; - case DecorateCommand.Down: - Down(item, from); - break; - case DecorateCommand.Turn: - Turn(item, from); - break; - } - } - } - - from.Target = new InternalTarget(m_Decorator); - } - - protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType) - { - if (cancelType == TargetCancelType.Canceled) - from.CloseGump(); - } - - private static void Turn(Item item, Mobile from) - { - object addon = null; - - if (item is AddonComponent component) - addon = component.Addon; - else if (item is AddonContainerComponent containerComponent) - addon = containerComponent.Addon; - else if (item is BaseAddonContainer container) - addon = container; - - if (addon != null) - { - FlippableAddonAttribute[] aAttributes = - (FlippableAddonAttribute[])addon.GetType() - .GetCustomAttributes(typeof(FlippableAddonAttribute), false); - - if (aAttributes.Length > 0) - { - aAttributes[0].Flip(from, (Item)addon); - return; - } - } - - FlippableAttribute[] attributes = - (FlippableAttribute[])item.GetType().GetCustomAttributes(typeof(FlippableAttribute), false); - - if (attributes.Length > 0) - attributes[0].Flip(item); - else - from.SendLocalizedMessage(1042273); // You cannot turn that. - } - - private static void Up(Item item, Mobile from) - { - int floorZ = GetFloorZ(item); - - if (floorZ > int.MinValue && item.Z < floorZ + 15) // Confirmed : no height checks here - item.Location = new Point3D(item.Location, item.Z + 1); - else - from.SendLocalizedMessage(1042274); // You cannot raise it up any higher. - } - - private static void Down(Item item, Mobile from) - { - int floorZ = GetFloorZ(item); - - if (floorZ > int.MinValue && item.Z > GetFloorZ(item)) - item.Location = new Point3D(item.Location, item.Z - 1); - else - from.SendLocalizedMessage(1042275); // You cannot lower it down any further. - } - - private static int GetFloorZ(Item item) - { - Map map = item.Map; - - if (map == null) - return int.MinValue; - - StaticTile[] tiles = map.Tiles.GetStaticTiles(item.X, item.Y, true); - - int z = int.MinValue; - - for (int i = 0; i < tiles.Length; ++i) - { - StaticTile tile = tiles[i]; - ItemData id = TileData.ItemTable[tile.ID & TileData.MaxItemValue]; - - int top = tile.Z; // Confirmed : no height checks here - - if (id.Surface && !id.Impassable && top > z && top <= item.Z) - z = top; - } - - return z; - } - } - } -} +using Server.Gumps; +using Server.Multis; +using Server.Network; +using Server.Targeting; + +namespace Server.Items +{ + public enum DecorateCommand + { + None, + Turn, + Up, + Down + } + + public class InteriorDecorator : Item + { + private DecorateCommand m_Command; + + [Constructible] + public InteriorDecorator() : base(0xFC1) + { + Weight = 1.0; + LootType = LootType.Blessed; + } + + public InteriorDecorator(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public DecorateCommand Command + { + get => m_Command; + set + { + m_Command = value; + InvalidateProperties(); + } + } + + public override int LabelNumber => 1041280; // an interior decorator + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_Command != DecorateCommand.None) + list.Add(1018322 + (int)m_Command); // Turn/Up/Down + } + + 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 (!CheckUse(this, from)) + return; + + if (!from.HasGump()) + from.SendGump(new InternalGump(this)); + + if (m_Command != DecorateCommand.None) + from.Target = new InternalTarget(this); + } + + public static bool InHouse(Mobile from) + { + var house = BaseHouse.FindHouseAt(from); + + return house?.IsCoOwner(from) == true; + } + + public static bool CheckUse(InteriorDecorator tool, Mobile from) + { + /*if (tool.Deleted || !tool.IsChildOf( from.Backpack )) + from.SendLocalizedMessage( 1042001 ); // That must be in your pack for you to use it. + else*/ + if (!InHouse(from)) + from.SendLocalizedMessage(502092); // You must be in your house to do this. + else + return true; + + return false; + } + + private class InternalGump : Gump + { + private readonly InteriorDecorator m_Decorator; + + public InternalGump(InteriorDecorator decorator) : base(150, 50) + { + m_Decorator = decorator; + + AddBackground(0, 0, 200, 200, 2600); + + AddButton(50, 45, decorator.Command == DecorateCommand.Turn ? 2154 : 2152, 2154, 1); + AddHtmlLocalized(90, 50, 70, 40, 1018323); // Turn + + AddButton(50, 95, decorator.Command == DecorateCommand.Up ? 2154 : 2152, 2154, 2); + AddHtmlLocalized(90, 100, 70, 40, 1018324); // Up + + AddButton(50, 145, decorator.Command == DecorateCommand.Down ? 2154 : 2152, 2154, 3); + AddHtmlLocalized(90, 150, 70, 40, 1018325); // Down + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var command = info.ButtonID switch + { + 1 => DecorateCommand.Turn, + 2 => DecorateCommand.Up, + 3 => DecorateCommand.Down, + _ => DecorateCommand.None + }; + + if (command != DecorateCommand.None) + { + m_Decorator.Command = command; + sender.Mobile.SendGump(new InternalGump(m_Decorator)); + sender.Mobile.Target = new InternalTarget(m_Decorator); + } + else + { + Target.Cancel(sender.Mobile); + } + } + } + + private class InternalTarget : Target + { + private readonly InteriorDecorator m_Decorator; + + public InternalTarget(InteriorDecorator decorator) : base(-1, false, TargetFlags.None) + { + CheckLOS = false; + + m_Decorator = decorator; + } + + protected override void OnTargetNotAccessible(Mobile from, object targeted) + { + OnTarget(from, targeted); + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted is Item item && CheckUse(m_Decorator, from)) + { + var house = BaseHouse.FindHouseAt(from); + + var isDecorableComponent = false; + object addon = null; + var count = 0; + + if (item is AddonComponent component) + { + count = component.Addon.Components.Count; + addon = component.Addon; + } + else if (item is AddonContainerComponent containerComponent) + { + count = containerComponent.Addon.Components.Count; + addon = containerComponent.Addon; + } + else if (item is BaseAddonContainer container) + { + count = container.Components.Count; + addon = container; + } + + if (addon != null) + { + if (count == 1 && Core.SE) + isDecorableComponent = true; + + if (m_Decorator.Command == DecorateCommand.Turn) + { + var attributes = + (FlippableAddonAttribute[])addon.GetType() + .GetCustomAttributes(typeof(FlippableAddonAttribute), false); + + if (attributes.Length > 0) + isDecorableComponent = true; + } + } + + if (house?.IsCoOwner(from) != true) + { + from.SendLocalizedMessage(502092); // You must be in your house to do this. + } + else if (item.Parent != null || !house.IsInside(item)) + { + from.SendLocalizedMessage(1042270); // That is not in your house. + } + else if (!house.HasLockedDownItem(item) && !house.HasSecureItem(item) && !isDecorableComponent) + { + if (item is AddonComponent && m_Decorator.Command == DecorateCommand.Up) + from.SendLocalizedMessage(1042274); // You cannot raise it up any higher. + else if (item is AddonComponent && m_Decorator.Command == DecorateCommand.Down) + from.SendLocalizedMessage(1042275); // You cannot lower it down any further. + else + from.SendLocalizedMessage(1042271); // That is not locked down. + } + else if (item is VendorRentalContract) + { + from.SendLocalizedMessage(1062491); // You cannot use the house decorator on that object. + } + else if (item.TotalWeight + item.PileWeight > 100) + { + from.SendLocalizedMessage(1042272); // That is too heavy. + } + else + { + switch (m_Decorator.Command) + { + case DecorateCommand.Up: + Up(item, from); + break; + case DecorateCommand.Down: + Down(item, from); + break; + case DecorateCommand.Turn: + Turn(item, from); + break; + } + } + } + + from.Target = new InternalTarget(m_Decorator); + } + + protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType) + { + if (cancelType == TargetCancelType.Canceled) + from.CloseGump(); + } + + private static void Turn(Item item, Mobile from) + { + object addon = null; + + if (item is AddonComponent component) + addon = component.Addon; + else if (item is AddonContainerComponent containerComponent) + addon = containerComponent.Addon; + else if (item is BaseAddonContainer container) + addon = container; + + if (addon != null) + { + var aAttributes = + (FlippableAddonAttribute[])addon.GetType() + .GetCustomAttributes(typeof(FlippableAddonAttribute), false); + + if (aAttributes.Length > 0) + { + aAttributes[0].Flip(from, (Item)addon); + return; + } + } + + var attributes = + (FlippableAttribute[])item.GetType().GetCustomAttributes(typeof(FlippableAttribute), false); + + if (attributes.Length > 0) + attributes[0].Flip(item); + else + from.SendLocalizedMessage(1042273); // You cannot turn that. + } + + private static void Up(Item item, Mobile from) + { + var floorZ = GetFloorZ(item); + + if (floorZ > int.MinValue && item.Z < floorZ + 15) // Confirmed : no height checks here + item.Location = new Point3D(item.Location, item.Z + 1); + else + from.SendLocalizedMessage(1042274); // You cannot raise it up any higher. + } + + private static void Down(Item item, Mobile from) + { + var floorZ = GetFloorZ(item); + + if (floorZ > int.MinValue && item.Z > GetFloorZ(item)) + item.Location = new Point3D(item.Location, item.Z - 1); + else + from.SendLocalizedMessage(1042275); // You cannot lower it down any further. + } + + private static int GetFloorZ(Item item) + { + var map = item.Map; + + if (map == null) + return int.MinValue; + + var tiles = map.Tiles.GetStaticTiles(item.X, item.Y, true); + + var z = int.MinValue; + + for (var i = 0; i < tiles.Length; ++i) + { + var tile = tiles[i]; + var id = TileData.ItemTable[tile.ID & TileData.MaxItemValue]; + + var top = tile.Z; // Confirmed : no height checks here + + if (id.Surface && !id.Impassable && top > z && top <= item.Z) + z = top; + } + + return z; + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/Key.cs b/Projects/UOContent/Items/Misc/Key.cs index 4c07b471d..8c2fc3566 100644 --- a/Projects/UOContent/Items/Misc/Key.cs +++ b/Projects/UOContent/Items/Misc/Key.cs @@ -1,382 +1,384 @@ -using Server.Network; -using Server.Prompts; -using Server.Targeting; - -namespace Server.Items -{ - public enum KeyType - { - Copper = 0x100E, - Gold = 0x100F, - Iron = 0x1010, - Rusty = 0x1013 - } - - public interface ILockable - { - bool Locked { get; set; } - uint KeyValue { get; set; } - } - - public class Key : Item - { - private string m_Description; - private uint m_KeyVal; - - [Constructible] - public Key(uint val = 0) : this(KeyType.Iron, val) - { - } - - public Key(KeyType type, uint val = 0, Item link = null) : base((int)type) - { - Weight = 1.0; - - MaxRange = 3; - m_KeyVal = val; - Link = link; - } - - public Key(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public string Description - { - get => m_Description; - set - { - m_Description = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxRange { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public uint KeyValue - { - get => m_KeyVal; - - set - { - m_KeyVal = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Item Link { get; set; } - - public static uint RandomValue() => (uint)(0xFFFFFFFE * Utility.RandomDouble()) + 1; - - public static void RemoveKeys(Mobile m, uint keyValue) - { - if (keyValue == 0) - return; - - RemoveKeys(m.Backpack, keyValue); - RemoveKeys(m.BankBox, keyValue); - } - - public static void RemoveKeys(Container cont, uint keyValue) - { - if (cont == null || keyValue == 0) - return; - - Item[] items = cont.FindItemsByType(new[] { typeof(Key), typeof(KeyRing) }); - - foreach (Item item in items) - if (item is Key key) - { - if (key.KeyValue == keyValue) - key.Delete(); - } - else - { - KeyRing keyRing = (KeyRing)item; - - keyRing.RemoveKeys(keyValue); - } - } - - public static bool ContainsKey(Container cont, uint keyValue) - { - if (cont == null) - return false; - - Item[] items = cont.FindItemsByType(new[] { typeof(Key), typeof(KeyRing) }); - - foreach (Item item in items) - if (item is Key key) - { - if (key.KeyValue == keyValue) - return true; - } - else - { - KeyRing keyRing = (KeyRing)item; - - if (keyRing.ContainsKey(keyValue)) - return true; - } - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(2); // version - - writer.Write(MaxRange); - - writer.Write(Link); - - writer.Write(m_Description); - writer.Write(m_KeyVal); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 2: - { - MaxRange = reader.ReadInt(); - - goto case 1; - } - case 1: - { - Link = reader.ReadItem(); - - goto case 0; - } - case 0: - { - if (version < 2 || MaxRange == 0) - MaxRange = 3; - - m_Description = reader.ReadString(); - - m_KeyVal = reader.ReadUInt(); - - break; - } - } - } - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(501661); // That key is unreachable. - return; - } - - Target t; - int number; - - if (m_KeyVal != 0) - { - number = 501662; // What shall I use this key on? - t = new UnlockTarget(this); - } - else - { - number = 501663; // This key is a key blank. Which key would you like to make a copy of? - t = new CopyTarget(this); - } - - from.SendLocalizedMessage(number); - from.Target = t; - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - string desc; - - if (m_KeyVal == 0) - desc = "(blank)"; - else if ((desc = m_Description) == null || (desc = desc.Trim()).Length <= 0) - desc = null; - - if (desc != null) - list.Add(desc); - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - string desc; - - if (m_KeyVal == 0) - desc = "(blank)"; - else if ((desc = m_Description) == null || (desc = desc.Trim()).Length <= 0) - desc = ""; - - if (desc.Length > 0) - from.Send(new UnicodeMessage(Serial, ItemID, MessageType.Regular, 0x3B2, 3, "ENU", "", desc)); - } - - public bool UseOn(Mobile from, ILockable o) - { - if (o.KeyValue == KeyValue) - { - if (o is BaseDoor door && !door.UseLocks()) - return false; - - o.Locked = !o.Locked; - - if (o is LockableContainer cont1) - if (cont1.LockLevel == -255) - cont1.LockLevel = cont1.RequiredSkill - 10; - - if (o is Item item) - { - if (o.Locked) - item.SendLocalizedMessageTo(from, 1048000); // You lock it. - else - item.SendLocalizedMessageTo(from, 1048001); // You unlock it. - - if (item is LockableContainer cont && cont.TrapType != TrapType.None && cont.TrapOnLockpick) - { - if (o.Locked) - cont.SendLocalizedMessageTo(from, 501673); // You re-enable the trap. - else - cont.SendLocalizedMessageTo(from, - 501672); // You disable the trap temporarily. Lock it again to re-enable it. - } - } - - return true; - } - - return false; - } - - private class RenamePrompt : Prompt - { - private readonly Key m_Key; - - public RenamePrompt(Key key) => m_Key = key; - - public override void OnResponse(Mobile from, string text) - { - if (m_Key.Deleted || !m_Key.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(501661); // That key is unreachable. - return; - } - - m_Key.Description = Utility.FixHtml(text); - } - } - - private class UnlockTarget : Target - { - private readonly Key m_Key; - - public UnlockTarget(Key key) : base(key.MaxRange, false, TargetFlags.None) - { - m_Key = key; - CheckLOS = false; - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Key.Deleted || !m_Key.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(501661); // That key is unreachable. - return; - } - - int number; - - if (targeted == m_Key) - { - number = 501665; // Enter a description for this key. - - from.Prompt = new RenamePrompt(m_Key); - } - else if (targeted is ILockable lockable) - { - if (m_Key.UseOn(from, lockable)) - number = -1; - else - number = 501668; // This key doesn't seem to unlock that. - } - else - { - number = 501666; // You can't unlock that! - } - - if (number != -1) from.SendLocalizedMessage(number); - } - } - - private class CopyTarget : Target - { - private readonly Key m_Key; - - public CopyTarget(Key key) : base(3, false, TargetFlags.None) => m_Key = key; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Key.Deleted || !m_Key.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(501661); // That key is unreachable. - return; - } - - int number; - - if (targeted is Key k) - { - if (k.m_KeyVal == 0) - { - number = 501675; // This key is also blank. - } - else if (from.CheckTargetSkill(SkillName.Tinkering, k, 0, 75.0)) - { - number = 501676; // You make a copy of the key. - - m_Key.Description = k.Description; - m_Key.KeyValue = k.KeyValue; - m_Key.Link = k.Link; - m_Key.MaxRange = k.MaxRange; - } - else if (Utility.RandomDouble() <= 0.1) // 10% chance to destroy the key - { - from.SendLocalizedMessage(501677); // You fail to make a copy of the key. - - number = 501678; // The key was destroyed in the attempt. - - m_Key.Delete(); - } - else - { - number = 501677; // You fail to make a copy of the key. - } - } - else - { - number = 501688; // Not a key. - } - - from.SendLocalizedMessage(number); - } - } - } -} +using Server.Network; +using Server.Prompts; +using Server.Targeting; + +namespace Server.Items +{ + public enum KeyType + { + Copper = 0x100E, + Gold = 0x100F, + Iron = 0x1010, + Rusty = 0x1013 + } + + public interface ILockable + { + bool Locked { get; set; } + uint KeyValue { get; set; } + } + + public class Key : Item + { + private string m_Description; + private uint m_KeyVal; + + [Constructible] + public Key(uint val = 0) : this(KeyType.Iron, val) + { + } + + public Key(KeyType type, uint val = 0, Item link = null) : base((int)type) + { + Weight = 1.0; + + MaxRange = 3; + m_KeyVal = val; + Link = link; + } + + public Key(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public string Description + { + get => m_Description; + set + { + m_Description = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxRange { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public uint KeyValue + { + get => m_KeyVal; + + set + { + m_KeyVal = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Item Link { get; set; } + + public static uint RandomValue() => (uint)(0xFFFFFFFE * Utility.RandomDouble()) + 1; + + public static void RemoveKeys(Mobile m, uint keyValue) + { + if (keyValue == 0) + return; + + RemoveKeys(m.Backpack, keyValue); + RemoveKeys(m.BankBox, keyValue); + } + + public static void RemoveKeys(Container cont, uint keyValue) + { + if (cont == null || keyValue == 0) + return; + + var items = cont.FindItemsByType(new[] { typeof(Key), typeof(KeyRing) }); + + foreach (var item in items) + if (item is Key key) + { + if (key.KeyValue == keyValue) + key.Delete(); + } + else + { + var keyRing = (KeyRing)item; + + keyRing.RemoveKeys(keyValue); + } + } + + public static bool ContainsKey(Container cont, uint keyValue) + { + if (cont == null) + return false; + + var items = cont.FindItemsByType(new[] { typeof(Key), typeof(KeyRing) }); + + foreach (var item in items) + if (item is Key key) + { + if (key.KeyValue == keyValue) + return true; + } + else + { + var keyRing = (KeyRing)item; + + if (keyRing.ContainsKey(keyValue)) + return true; + } + + return false; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(2); // version + + writer.Write(MaxRange); + + writer.Write(Link); + + writer.Write(m_Description); + writer.Write(m_KeyVal); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 2: + { + MaxRange = reader.ReadInt(); + + goto case 1; + } + case 1: + { + Link = reader.ReadItem(); + + goto case 0; + } + case 0: + { + if (version < 2 || MaxRange == 0) + MaxRange = 3; + + m_Description = reader.ReadString(); + + m_KeyVal = reader.ReadUInt(); + + break; + } + } + } + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(501661); // That key is unreachable. + return; + } + + Target t; + int number; + + if (m_KeyVal != 0) + { + number = 501662; // What shall I use this key on? + t = new UnlockTarget(this); + } + else + { + number = 501663; // This key is a key blank. Which key would you like to make a copy of? + t = new CopyTarget(this); + } + + from.SendLocalizedMessage(number); + from.Target = t; + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + string desc; + + if (m_KeyVal == 0) + desc = "(blank)"; + else if ((desc = m_Description) == null || (desc = desc.Trim()).Length <= 0) + desc = null; + + if (desc != null) + list.Add(desc); + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + string desc; + + if (m_KeyVal == 0) + desc = "(blank)"; + else if ((desc = m_Description) == null || (desc = desc.Trim()).Length <= 0) + desc = ""; + + if (desc.Length > 0) + from.Send(new UnicodeMessage(Serial, ItemID, MessageType.Regular, 0x3B2, 3, "ENU", "", desc)); + } + + public bool UseOn(Mobile from, ILockable o) + { + if (o.KeyValue == KeyValue) + { + if (o is BaseDoor door && !door.UseLocks()) + return false; + + o.Locked = !o.Locked; + + if (o is LockableContainer cont1) + if (cont1.LockLevel == -255) + cont1.LockLevel = cont1.RequiredSkill - 10; + + if (o is Item item) + { + if (o.Locked) + item.SendLocalizedMessageTo(from, 1048000); // You lock it. + else + item.SendLocalizedMessageTo(from, 1048001); // You unlock it. + + if (item is LockableContainer cont && cont.TrapType != TrapType.None && cont.TrapOnLockpick) + { + if (o.Locked) + cont.SendLocalizedMessageTo(from, 501673); // You re-enable the trap. + else + cont.SendLocalizedMessageTo( + from, + 501672 + ); // You disable the trap temporarily. Lock it again to re-enable it. + } + } + + return true; + } + + return false; + } + + private class RenamePrompt : Prompt + { + private readonly Key m_Key; + + public RenamePrompt(Key key) => m_Key = key; + + public override void OnResponse(Mobile from, string text) + { + if (m_Key.Deleted || !m_Key.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(501661); // That key is unreachable. + return; + } + + m_Key.Description = Utility.FixHtml(text); + } + } + + private class UnlockTarget : Target + { + private readonly Key m_Key; + + public UnlockTarget(Key key) : base(key.MaxRange, false, TargetFlags.None) + { + m_Key = key; + CheckLOS = false; + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Key.Deleted || !m_Key.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(501661); // That key is unreachable. + return; + } + + int number; + + if (targeted == m_Key) + { + number = 501665; // Enter a description for this key. + + from.Prompt = new RenamePrompt(m_Key); + } + else if (targeted is ILockable lockable) + { + if (m_Key.UseOn(from, lockable)) + number = -1; + else + number = 501668; // This key doesn't seem to unlock that. + } + else + { + number = 501666; // You can't unlock that! + } + + if (number != -1) from.SendLocalizedMessage(number); + } + } + + private class CopyTarget : Target + { + private readonly Key m_Key; + + public CopyTarget(Key key) : base(3, false, TargetFlags.None) => m_Key = key; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Key.Deleted || !m_Key.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(501661); // That key is unreachable. + return; + } + + int number; + + if (targeted is Key k) + { + if (k.m_KeyVal == 0) + { + number = 501675; // This key is also blank. + } + else if (from.CheckTargetSkill(SkillName.Tinkering, k, 0, 75.0)) + { + number = 501676; // You make a copy of the key. + + m_Key.Description = k.Description; + m_Key.KeyValue = k.KeyValue; + m_Key.Link = k.Link; + m_Key.MaxRange = k.MaxRange; + } + else if (Utility.RandomDouble() <= 0.1) // 10% chance to destroy the key + { + from.SendLocalizedMessage(501677); // You fail to make a copy of the key. + + number = 501678; // The key was destroyed in the attempt. + + m_Key.Delete(); + } + else + { + number = 501677; // You fail to make a copy of the key. + } + } + else + { + number = 501688; // Not a key. + } + + from.SendLocalizedMessage(number); + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/KeyRing.cs b/Projects/UOContent/Items/Misc/KeyRing.cs index db53727a8..3b1946410 100644 --- a/Projects/UOContent/Items/Misc/KeyRing.cs +++ b/Projects/UOContent/Items/Misc/KeyRing.cs @@ -1,185 +1,185 @@ -using System.Collections.Generic; -using Server.Targeting; - -namespace Server.Items -{ - public class KeyRing : Item - { - public static readonly int MaxKeys = 20; - - [Constructible] - public KeyRing() : base(0x1011) - { - Weight = 1.0; // They seem to have no weight on OSI ?! - - Keys = new List(); - } - - public KeyRing(Serial serial) : base(serial) - { - } - - public List Keys { get; private set; } - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1060640); // The item must be in your backpack to use it. - return false; - } - - if (!(dropped is Key key) || key.KeyValue == 0) - { - from.SendLocalizedMessage(501689); // Only non-blank keys can be put on a keyring. - return false; - } - - if (Keys.Count >= MaxKeys) - { - from.SendLocalizedMessage(1008138); // This keyring is full. - return false; - } - - Add(key); - from.SendLocalizedMessage(501691); // You put the key on the keyring. - return true; - } - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1060640); // The item must be in your backpack to use it. - return; - } - - from.SendLocalizedMessage(501680); // What do you want to unlock? - from.Target = new InternalTarget(this); - } - - public override void OnDelete() - { - base.OnDelete(); - - foreach (Key key in Keys) key.Delete(); - - Keys.Clear(); - } - - public void Add(Key key) - { - key.Internalize(); - Keys.Add(key); - - UpdateItemID(); - } - - public void Open(Mobile from) - { - if (!(Parent is Container cont)) - return; - - for (int i = Keys.Count - 1; i >= 0; i--) - { - Key key = Keys[i]; - - if (!key.Deleted && !cont.TryDropItem(from, key, true)) - break; - - Keys.RemoveAt(i); - } - - UpdateItemID(); - } - - public void RemoveKeys(uint keyValue) - { - for (int i = Keys.Count - 1; i >= 0; i--) - { - Key key = Keys[i]; - - if (key.KeyValue == keyValue) - { - key.Delete(); - Keys.RemoveAt(i); - } - } - - UpdateItemID(); - } - - public bool ContainsKey(uint keyValue) - { - foreach (Key key in Keys) - if (key.KeyValue == keyValue) - return true; - - return false; - } - - private void UpdateItemID() - { - if (Keys.Count < 1) - ItemID = 0x1011; - else if (Keys.Count < 3) - ItemID = 0x1769; - else if (Keys.Count < 5) - ItemID = 0x176A; - else - ItemID = 0x176B; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.WriteItemList(Keys); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - Keys = reader.ReadStrongItemList(); - } - - private class InternalTarget : Target - { - private readonly KeyRing m_KeyRing; - - public InternalTarget(KeyRing keyRing) : base(-1, false, TargetFlags.None) => m_KeyRing = keyRing; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_KeyRing.Deleted || !m_KeyRing.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1060640); // The item must be in your backpack to use it. - return; - } - - if (m_KeyRing == targeted) - { - m_KeyRing.Open(from); - from.SendLocalizedMessage(501685); // You open the keyring. - } - else if (targeted is ILockable o) - { - foreach (Key key in m_KeyRing.Keys) - if (key.UseOn(from, o)) - return; - - from.SendLocalizedMessage(1008140); // You do not have a key for that. - } - else - { - from.SendLocalizedMessage(501666); // You can't unlock that! - } - } - } - } -} \ No newline at end of file +using System.Collections.Generic; +using Server.Targeting; + +namespace Server.Items +{ + public class KeyRing : Item + { + public static readonly int MaxKeys = 20; + + [Constructible] + public KeyRing() : base(0x1011) + { + Weight = 1.0; // They seem to have no weight on OSI ?! + + Keys = new List(); + } + + public KeyRing(Serial serial) : base(serial) + { + } + + public List Keys { get; private set; } + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1060640); // The item must be in your backpack to use it. + return false; + } + + if (!(dropped is Key key) || key.KeyValue == 0) + { + from.SendLocalizedMessage(501689); // Only non-blank keys can be put on a keyring. + return false; + } + + if (Keys.Count >= MaxKeys) + { + from.SendLocalizedMessage(1008138); // This keyring is full. + return false; + } + + Add(key); + from.SendLocalizedMessage(501691); // You put the key on the keyring. + return true; + } + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1060640); // The item must be in your backpack to use it. + return; + } + + from.SendLocalizedMessage(501680); // What do you want to unlock? + from.Target = new InternalTarget(this); + } + + public override void OnDelete() + { + base.OnDelete(); + + foreach (var key in Keys) key.Delete(); + + Keys.Clear(); + } + + public void Add(Key key) + { + key.Internalize(); + Keys.Add(key); + + UpdateItemID(); + } + + public void Open(Mobile from) + { + if (!(Parent is Container cont)) + return; + + for (var i = Keys.Count - 1; i >= 0; i--) + { + var key = Keys[i]; + + if (!key.Deleted && !cont.TryDropItem(from, key, true)) + break; + + Keys.RemoveAt(i); + } + + UpdateItemID(); + } + + public void RemoveKeys(uint keyValue) + { + for (var i = Keys.Count - 1; i >= 0; i--) + { + var key = Keys[i]; + + if (key.KeyValue == keyValue) + { + key.Delete(); + Keys.RemoveAt(i); + } + } + + UpdateItemID(); + } + + public bool ContainsKey(uint keyValue) + { + foreach (var key in Keys) + if (key.KeyValue == keyValue) + return true; + + return false; + } + + private void UpdateItemID() + { + if (Keys.Count < 1) + ItemID = 0x1011; + else if (Keys.Count < 3) + ItemID = 0x1769; + else if (Keys.Count < 5) + ItemID = 0x176A; + else + ItemID = 0x176B; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.WriteItemList(Keys); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + Keys = reader.ReadStrongItemList(); + } + + private class InternalTarget : Target + { + private readonly KeyRing m_KeyRing; + + public InternalTarget(KeyRing keyRing) : base(-1, false, TargetFlags.None) => m_KeyRing = keyRing; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_KeyRing.Deleted || !m_KeyRing.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1060640); // The item must be in your backpack to use it. + return; + } + + if (m_KeyRing == targeted) + { + m_KeyRing.Open(from); + from.SendLocalizedMessage(501685); // You open the keyring. + } + else if (targeted is ILockable o) + { + foreach (var key in m_KeyRing.Keys) + if (key.UseOn(from, o)) + return; + + from.SendLocalizedMessage(1008140); // You do not have a key for that. + } + else + { + from.SendLocalizedMessage(501666); // You can't unlock that! + } + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/LOSBlocker.cs b/Projects/UOContent/Items/Misc/LOSBlocker.cs index d501a3513..0c3dc1ed0 100644 --- a/Projects/UOContent/Items/Misc/LOSBlocker.cs +++ b/Projects/UOContent/Items/Misc/LOSBlocker.cs @@ -1,110 +1,110 @@ -using Server.Network; - -namespace Server.Items -{ - public class LOSBlocker : Item - { - [Constructible] - public LOSBlocker() : base(0x21A2) => Movable = false; - - public LOSBlocker(Serial serial) : base(serial) - { - } - - public override string DefaultName => "no line of sight"; - - public static void Initialize() - { - TileData.ItemTable[0x21A2].Flags = TileFlag.Wall | TileFlag.NoShoot; - TileData.ItemTable[0x21A2].Height = 20; - } - - protected override Packet GetWorldPacketFor(NetState state) - { - Mobile mob = state.Mobile; - - if (mob?.AccessLevel >= AccessLevel.GameMaster) return new GMItemPacket(this); - - return base.GetWorldPacketFor(state); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1 && ItemID == 0x2199) - ItemID = 0x21A2; - } - - public sealed class GMItemPacket : Packet - { - public GMItemPacket(Item item) : base(0x1A) - { - EnsureCapacity(20); - - // 14 base length - // +2 - Amount - // +2 - Hue - // +1 - Flags - - uint serial = item.Serial.Value; - int itemID = 0x36FF; - int amount = item.Amount; - Point3D loc = item.Location; - int x = loc.X; - int y = loc.Y; - int hue = item.Hue; - int flags = item.GetPacketFlags(); - int direction = (int)item.Direction; - - if (amount != 0) - serial |= 0x80000000; - else - serial &= 0x7FFFFFFF; - - Stream.Write(serial); - Stream.Write((short)(itemID & 0x7FFF)); - - if (amount != 0) - Stream.Write((short)amount); - - x &= 0x7FFF; - - if (direction != 0) - x |= 0x8000; - - Stream.Write((short)x); - - y &= 0x3FFF; - - if (hue != 0) - y |= 0x8000; - - if (flags != 0) - y |= 0x4000; - - Stream.Write((short)y); - - if (direction != 0) - Stream.Write((byte)direction); - - Stream.Write((sbyte)loc.Z); - - if (hue != 0) - Stream.Write((ushort)hue); - - if (flags != 0) - Stream.Write((byte)flags); - } - } - } -} +using Server.Network; + +namespace Server.Items +{ + public class LOSBlocker : Item + { + [Constructible] + public LOSBlocker() : base(0x21A2) => Movable = false; + + public LOSBlocker(Serial serial) : base(serial) + { + } + + public override string DefaultName => "no line of sight"; + + public static void Initialize() + { + TileData.ItemTable[0x21A2].Flags = TileFlag.Wall | TileFlag.NoShoot; + TileData.ItemTable[0x21A2].Height = 20; + } + + protected override Packet GetWorldPacketFor(NetState state) + { + var mob = state.Mobile; + + if (mob?.AccessLevel >= AccessLevel.GameMaster) return new GMItemPacket(this); + + return base.GetWorldPacketFor(state); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version < 1 && ItemID == 0x2199) + ItemID = 0x21A2; + } + + public sealed class GMItemPacket : Packet + { + public GMItemPacket(Item item) : base(0x1A) + { + EnsureCapacity(20); + + // 14 base length + // +2 - Amount + // +2 - Hue + // +1 - Flags + + var serial = item.Serial.Value; + var itemID = 0x36FF; + var amount = item.Amount; + var loc = item.Location; + var x = loc.X; + var y = loc.Y; + var hue = item.Hue; + var flags = item.GetPacketFlags(); + var direction = (int)item.Direction; + + if (amount != 0) + serial |= 0x80000000; + else + serial &= 0x7FFFFFFF; + + Stream.Write(serial); + Stream.Write((short)(itemID & 0x7FFF)); + + if (amount != 0) + Stream.Write((short)amount); + + x &= 0x7FFF; + + if (direction != 0) + x |= 0x8000; + + Stream.Write((short)x); + + y &= 0x3FFF; + + if (hue != 0) + y |= 0x8000; + + if (flags != 0) + y |= 0x4000; + + Stream.Write((short)y); + + if (direction != 0) + Stream.Write((byte)direction); + + Stream.Write((sbyte)loc.Z); + + if (hue != 0) + Stream.Write((ushort)hue); + + if (flags != 0) + Stream.Write((byte)flags); + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/Labyrinth/MinotaurArtifact.cs b/Projects/UOContent/Items/Misc/Labyrinth/MinotaurArtifact.cs index 22dda9a0e..05831c3e4 100644 --- a/Projects/UOContent/Items/Misc/Labyrinth/MinotaurArtifact.cs +++ b/Projects/UOContent/Items/Misc/Labyrinth/MinotaurArtifact.cs @@ -1,36 +1,36 @@ -namespace Server.Items -{ - public class MinotaurArtifact : Item - { - [Constructible] - public MinotaurArtifact() : base(Utility.RandomList(0xB46, 0xB48, 0x9ED)) - { - if (ItemID == 0x9ED) - Weight = 30; - - LootType = LootType.Blessed; - Hue = 0x100; - } - - public MinotaurArtifact(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074826; // Minotaur Artifact - public override double DefaultWeight => 5.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class MinotaurArtifact : Item + { + [Constructible] + public MinotaurArtifact() : base(Utility.RandomList(0xB46, 0xB48, 0x9ED)) + { + if (ItemID == 0x9ED) + Weight = 30; + + LootType = LootType.Blessed; + Hue = 0x100; + } + + public MinotaurArtifact(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074826; // Minotaur Artifact + public override double DefaultWeight => 5.0; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Moonstone.cs b/Projects/UOContent/Items/Misc/Moonstone.cs index cb3c1f4da..15a1740f7 100644 --- a/Projects/UOContent/Items/Misc/Moonstone.cs +++ b/Projects/UOContent/Items/Misc/Moonstone.cs @@ -1,203 +1,206 @@ -using System; -using Server.Factions; -using Server.Mobiles; -using Server.Network; - -namespace Server.Items -{ - public enum MoonstoneType - { - Felucca, - Trammel - } - - public class Moonstone : Item - { - private MoonstoneType m_Type; - - [Constructible] - public Moonstone(MoonstoneType type) : base(0xF8B) - { - Weight = 1.0; - m_Type = type; - } - - public Moonstone(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public MoonstoneType Type - { - get => m_Type; - set - { - m_Type = value; - InvalidateProperties(); - } - } - - public override int LabelNumber => 1041490 + (int)m_Type; - - public override void OnSingleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - Hue = Utility.RandomBirdHue(); - ProcessDelta(); - from.SendLocalizedMessage(1005398); // The stone's substance shifts as you examine it. - } - - base.OnSingleClick(from); - } - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (from.Mounted) - { - from.SendLocalizedMessage(1005399); // You can not bury a stone while you sit on a mount. - } - else if (!from.Body.IsHuman) - { - from.SendLocalizedMessage(1005400); // You can not bury a stone in this form. - } - else if (Sigil.ExistsOn(from)) - { - from.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. - } - else if (from.Map == GetTargetMap() || (from.Map != Map.Trammel && from.Map != Map.Felucca)) - { - from.SendLocalizedMessage(1005401); // You cannot bury the stone here. - } - else if (from is PlayerMobile mobile && mobile.Young) - { - mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young. - } - else if (from.Kills >= 5) - { - from.SendLocalizedMessage( - 1005402); // The magic of the stone cannot be evoked by someone with blood on their hands. - } - else if (from.Criminal) - { - from.SendLocalizedMessage(1005403); // The magic of the stone cannot be evoked by the lawless. - } - else if (!Region.Find(from.Location, from.Map).IsDefault || - !Region.Find(from.Location, GetTargetMap()).IsDefault) - { - from.SendLocalizedMessage(1005401); // You cannot bury the stone here. - } - else if (!GetTargetMap().CanFit(from.Location, 16)) - { - from.SendLocalizedMessage(1005408); // Something is blocking the facet gate exit. - } - else - { - Movable = false; - MoveToWorld(from.Location, from.Map); - - from.Animate(32, 5, 1, true, false, 0); - - new SettleTimer(this, from.Location, from.Map, GetTargetMap(), from).Start(); - } - } - - public Map GetTargetMap() => m_Type == MoonstoneType.Felucca ? Map.Felucca : Map.Trammel; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write((int)m_Type); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Type = (MoonstoneType)reader.ReadInt(); - - break; - } - } - } - - private class SettleTimer : Timer - { - private readonly Mobile m_Caster; - private int m_Count; - private readonly Point3D m_Location; - private readonly Map m_Map; - private readonly Map m_TargetMap; - private readonly Item m_Stone; - - public SettleTimer(Item stone, Point3D loc, Map map, Map targetMap, Mobile caster) : base( - TimeSpan.FromSeconds(2.5), TimeSpan.FromSeconds(1.0)) - { - m_Stone = stone; - - m_Location = loc; - m_Map = map; - m_TargetMap = targetMap; - - m_Caster = caster; - } - - protected override void OnTick() - { - ++m_Count; - - if (m_Count == 1) - { - m_Stone.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1005414); // The stone settles into the ground. - } - else if (m_Count >= 10) - { - m_Stone.Location = new Point3D(m_Stone.X, m_Stone.Y, m_Stone.Z - 1); - - if (m_Count == 16) - { - if (!Region.Find(m_Location, m_Map).IsDefault || !Region.Find(m_Location, m_TargetMap).IsDefault) - { - m_Stone.Movable = true; - m_Caster.AddToBackpack(m_Stone); - Stop(); - return; - } - - if (!m_TargetMap.CanFit(m_Location, 16)) - { - m_Stone.Movable = true; - m_Caster.AddToBackpack(m_Stone); - Stop(); - return; - } - - int hue = m_Stone.Hue; - - if (hue == 0) - hue = Utility.RandomBirdHue(); - - new MoonstoneGate(m_Location, m_TargetMap, m_Map, m_Caster, hue); - new MoonstoneGate(m_Location, m_Map, m_TargetMap, m_Caster, hue); - - m_Stone.Delete(); - Stop(); - } - } - } - } - } -} \ No newline at end of file +using System; +using Server.Factions; +using Server.Mobiles; +using Server.Network; + +namespace Server.Items +{ + public enum MoonstoneType + { + Felucca, + Trammel + } + + public class Moonstone : Item + { + private MoonstoneType m_Type; + + [Constructible] + public Moonstone(MoonstoneType type) : base(0xF8B) + { + Weight = 1.0; + m_Type = type; + } + + public Moonstone(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public MoonstoneType Type + { + get => m_Type; + set + { + m_Type = value; + InvalidateProperties(); + } + } + + public override int LabelNumber => 1041490 + (int)m_Type; + + public override void OnSingleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + Hue = Utility.RandomBirdHue(); + ProcessDelta(); + from.SendLocalizedMessage(1005398); // The stone's substance shifts as you examine it. + } + + base.OnSingleClick(from); + } + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else if (from.Mounted) + { + from.SendLocalizedMessage(1005399); // You can not bury a stone while you sit on a mount. + } + else if (!from.Body.IsHuman) + { + from.SendLocalizedMessage(1005400); // You can not bury a stone in this form. + } + else if (Sigil.ExistsOn(from)) + { + from.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. + } + else if (from.Map == GetTargetMap() || @from.Map != Map.Trammel && @from.Map != Map.Felucca) + { + from.SendLocalizedMessage(1005401); // You cannot bury the stone here. + } + else if (from is PlayerMobile mobile && mobile.Young) + { + mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young. + } + else if (from.Kills >= 5) + { + from.SendLocalizedMessage( + 1005402 + ); // The magic of the stone cannot be evoked by someone with blood on their hands. + } + else if (from.Criminal) + { + from.SendLocalizedMessage(1005403); // The magic of the stone cannot be evoked by the lawless. + } + else if (!Region.Find(from.Location, from.Map).IsDefault || + !Region.Find(from.Location, GetTargetMap()).IsDefault) + { + from.SendLocalizedMessage(1005401); // You cannot bury the stone here. + } + else if (!GetTargetMap().CanFit(from.Location, 16)) + { + from.SendLocalizedMessage(1005408); // Something is blocking the facet gate exit. + } + else + { + Movable = false; + MoveToWorld(from.Location, from.Map); + + from.Animate(32, 5, 1, true, false, 0); + + new SettleTimer(this, from.Location, from.Map, GetTargetMap(), from).Start(); + } + } + + public Map GetTargetMap() => m_Type == MoonstoneType.Felucca ? Map.Felucca : Map.Trammel; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write((int)m_Type); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Type = (MoonstoneType)reader.ReadInt(); + + break; + } + } + } + + private class SettleTimer : Timer + { + private readonly Mobile m_Caster; + private readonly Point3D m_Location; + private readonly Map m_Map; + private readonly Item m_Stone; + private readonly Map m_TargetMap; + private int m_Count; + + public SettleTimer(Item stone, Point3D loc, Map map, Map targetMap, Mobile caster) : base( + TimeSpan.FromSeconds(2.5), + TimeSpan.FromSeconds(1.0) + ) + { + m_Stone = stone; + + m_Location = loc; + m_Map = map; + m_TargetMap = targetMap; + + m_Caster = caster; + } + + protected override void OnTick() + { + ++m_Count; + + if (m_Count == 1) + { + m_Stone.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1005414); // The stone settles into the ground. + } + else if (m_Count >= 10) + { + m_Stone.Location = new Point3D(m_Stone.X, m_Stone.Y, m_Stone.Z - 1); + + if (m_Count == 16) + { + if (!Region.Find(m_Location, m_Map).IsDefault || !Region.Find(m_Location, m_TargetMap).IsDefault) + { + m_Stone.Movable = true; + m_Caster.AddToBackpack(m_Stone); + Stop(); + return; + } + + if (!m_TargetMap.CanFit(m_Location, 16)) + { + m_Stone.Movable = true; + m_Caster.AddToBackpack(m_Stone); + Stop(); + return; + } + + var hue = m_Stone.Hue; + + if (hue == 0) + hue = Utility.RandomBirdHue(); + + new MoonstoneGate(m_Location, m_TargetMap, m_Map, m_Caster, hue); + new MoonstoneGate(m_Location, m_Map, m_TargetMap, m_Caster, hue); + + m_Stone.Delete(); + Stop(); + } + } + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/MoonstoneGate.cs b/Projects/UOContent/Items/Misc/MoonstoneGate.cs index dab0b5896..d384679e9 100644 --- a/Projects/UOContent/Items/Misc/MoonstoneGate.cs +++ b/Projects/UOContent/Items/Misc/MoonstoneGate.cs @@ -1,83 +1,83 @@ -using System; -using Server.Engines.PartySystem; - -namespace Server.Items -{ - public class MoonstoneGate : Moongate - { - private readonly Mobile m_Caster; - - public MoonstoneGate(Point3D loc, Map map, Map targetMap, Mobile caster, int hue) : base(loc, targetMap) - { - MoveToWorld(loc, map); - Dispellable = false; - Hue = hue; - - m_Caster = caster; - - new InternalTimer(this).Start(); - - Effects.PlaySound(loc, map, 0x20E); - } - - public MoonstoneGate(Serial serial) : base(serial) - { - } - - public override void CheckGate(Mobile m, int range) - { - if (m.Kills >= 5) - return; - - Party casterParty = Party.Get(m_Caster); - Party userParty = Party.Get(m); - - if (m == m_Caster || (casterParty != null && userParty == casterParty)) - base.CheckGate(m, range); - } - - public override void UseGate(Mobile m) - { - if (m.Kills >= 5) - return; - - Party casterParty = Party.Get(m_Caster); - Party userParty = Party.Get(m); - - if (m == m_Caster || (casterParty != null && userParty == casterParty)) - base.UseGate(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Delete(); - } - - private class InternalTimer : Timer - { - private readonly Item m_Item; - - public InternalTimer(Item item) : base(TimeSpan.FromSeconds(30.0)) - { - m_Item = item; - Priority = TimerPriority.OneSecond; - } - - protected override void OnTick() - { - m_Item.Delete(); - } - } - } -} \ No newline at end of file +using System; +using Server.Engines.PartySystem; + +namespace Server.Items +{ + public class MoonstoneGate : Moongate + { + private readonly Mobile m_Caster; + + public MoonstoneGate(Point3D loc, Map map, Map targetMap, Mobile caster, int hue) : base(loc, targetMap) + { + MoveToWorld(loc, map); + Dispellable = false; + Hue = hue; + + m_Caster = caster; + + new InternalTimer(this).Start(); + + Effects.PlaySound(loc, map, 0x20E); + } + + public MoonstoneGate(Serial serial) : base(serial) + { + } + + public override void CheckGate(Mobile m, int range) + { + if (m.Kills >= 5) + return; + + var casterParty = Party.Get(m_Caster); + var userParty = Party.Get(m); + + if (m == m_Caster || casterParty != null && userParty == casterParty) + base.CheckGate(m, range); + } + + public override void UseGate(Mobile m) + { + if (m.Kills >= 5) + return; + + var casterParty = Party.Get(m_Caster); + var userParty = Party.Get(m); + + if (m == m_Caster || casterParty != null && userParty == casterParty) + base.UseGate(m); + } + + 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(); + + Delete(); + } + + private class InternalTimer : Timer + { + private readonly Item m_Item; + + public InternalTimer(Item item) : base(TimeSpan.FromSeconds(30.0)) + { + m_Item = item; + Priority = TimerPriority.OneSecond; + } + + protected override void OnTick() + { + m_Item.Delete(); + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/MorphItem.cs b/Projects/UOContent/Items/Misc/MorphItem.cs index 9efe00c4d..a6f012ab9 100644 --- a/Projects/UOContent/Items/Misc/MorphItem.cs +++ b/Projects/UOContent/Items/Misc/MorphItem.cs @@ -1,123 +1,125 @@ -using System.Linq; - -namespace Server.Items -{ - public class MorphItem : Item - { - private int m_InsideRange; - private int m_OutsideRange; - - [Constructible] - public MorphItem(int inactiveItemID, int activeItemID, int range) : this(inactiveItemID, activeItemID, range, range) - { - } - - [Constructible] - public MorphItem(int inactiveItemID, int activeItemID, int inRange, int outRange) : base(inactiveItemID) - { - Movable = false; - - InactiveItemID = inactiveItemID; - ActiveItemID = activeItemID; - InsideRange = inRange; - OutsideRange = outRange; - } - - public MorphItem(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int InactiveItemID { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int ActiveItemID { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int InsideRange - { - get => m_InsideRange; - set => m_InsideRange = value > 18 ? 18 : value < 0 ? 0 : value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int OutsideRange - { - get => m_OutsideRange; - set => m_OutsideRange = value > 18 ? 18 : value < 0 ? 0 : value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int CurrentRange => ItemID == InactiveItemID ? InsideRange : OutsideRange; - - public override bool HandlesOnMovement => true; - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (Utility.InRange(m.Location, Location, CurrentRange) || Utility.InRange(oldLocation, Location, CurrentRange)) - Refresh(); - } - - public override void OnMapChange() - { - if (!Deleted) - Refresh(); - } - - public override void OnLocationChange(Point3D oldLoc) - { - if (!Deleted) - Refresh(); - } - - public void Refresh() - { - bool found = GetMobilesInRange(CurrentRange).Any(mob => !mob.Hidden || mob.AccessLevel <= AccessLevel.Player); - ItemID = found ? ActiveItemID : InactiveItemID; - - Visible = ItemID != 0x1; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(m_OutsideRange); - - writer.Write(InactiveItemID); - writer.Write(ActiveItemID); - writer.Write(m_InsideRange); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_OutsideRange = reader.ReadInt(); - goto case 0; - } - case 0: - { - InactiveItemID = reader.ReadInt(); - ActiveItemID = reader.ReadInt(); - m_InsideRange = reader.ReadInt(); - - if (version < 1) - m_OutsideRange = m_InsideRange; - - break; - } - } - - Timer.DelayCall(Refresh); - } - } -} +using System.Linq; + +namespace Server.Items +{ + public class MorphItem : Item + { + private int m_InsideRange; + private int m_OutsideRange; + + [Constructible] + public MorphItem(int inactiveItemID, int activeItemID, int range) : this(inactiveItemID, activeItemID, range, range) + { + } + + [Constructible] + public MorphItem(int inactiveItemID, int activeItemID, int inRange, int outRange) : base(inactiveItemID) + { + Movable = false; + + InactiveItemID = inactiveItemID; + ActiveItemID = activeItemID; + InsideRange = inRange; + OutsideRange = outRange; + } + + public MorphItem(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int InactiveItemID { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int ActiveItemID { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int InsideRange + { + get => m_InsideRange; + set => m_InsideRange = value > 18 ? 18 : + value < 0 ? 0 : value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int OutsideRange + { + get => m_OutsideRange; + set => m_OutsideRange = value > 18 ? 18 : + value < 0 ? 0 : value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int CurrentRange => ItemID == InactiveItemID ? InsideRange : OutsideRange; + + public override bool HandlesOnMovement => true; + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (Utility.InRange(m.Location, Location, CurrentRange) || Utility.InRange(oldLocation, Location, CurrentRange)) + Refresh(); + } + + public override void OnMapChange() + { + if (!Deleted) + Refresh(); + } + + public override void OnLocationChange(Point3D oldLoc) + { + if (!Deleted) + Refresh(); + } + + public void Refresh() + { + var found = GetMobilesInRange(CurrentRange).Any(mob => !mob.Hidden || mob.AccessLevel <= AccessLevel.Player); + ItemID = found ? ActiveItemID : InactiveItemID; + + Visible = ItemID != 0x1; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(m_OutsideRange); + + writer.Write(InactiveItemID); + writer.Write(ActiveItemID); + writer.Write(m_InsideRange); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_OutsideRange = reader.ReadInt(); + goto case 0; + } + case 0: + { + InactiveItemID = reader.ReadInt(); + ActiveItemID = reader.ReadInt(); + m_InsideRange = reader.ReadInt(); + + if (version < 1) + m_OutsideRange = m_InsideRange; + + break; + } + } + + Timer.DelayCall(Refresh); + } + } +} diff --git a/Projects/UOContent/Items/Misc/OilCloth.cs b/Projects/UOContent/Items/Misc/OilCloth.cs index ded7ae2ac..7f39aa840 100644 --- a/Projects/UOContent/Items/Misc/OilCloth.cs +++ b/Projects/UOContent/Items/Misc/OilCloth.cs @@ -1,142 +1,148 @@ -using System; -using Server.Mobiles; -using Server.Network; -using Server.Targeting; - -namespace Server.Items -{ - public class OilCloth : Item, IScissorable, IDyable - { - [Constructible] - public OilCloth() : base(0x175D) => Hue = 2001; - - public OilCloth(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041498; // oil cloth - - public override double DefaultWeight => 1.0; - - public bool Dye(Mobile from, DyeTub sender) - { - if (Deleted) - return false; - - Hue = sender.DyedHue; - - return true; - } - - public bool Scissor(Mobile from, Scissors scissors) - { - if (Deleted || !from.CanSee(this)) - return false; - - ScissorHelper(from, new Bandage(), 1); - - return true; - } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - from.BeginTarget(-1, false, TargetFlags.None, OnTarget); - from.SendLocalizedMessage(1005424); // Select the weapon or armor you wish to use the cloth on. - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - - public void OnTarget(Mobile from, object obj) - { - // TODO: Need details on how oil cloths should get consumed here - - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (obj is Item item && item.RootParent != from) - { - from.SendLocalizedMessage(1005425); // You may only wipe down items you are holding or carrying. - } - else if (obj is BaseWeapon weapon) - { - if (weapon.Poison == null || weapon.PoisonCharges <= 0) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1005422); // Hmmmm... this does not need to be cleaned. - } - else - { - if (weapon.PoisonCharges < 2) - weapon.PoisonCharges = 0; - else - weapon.PoisonCharges -= 2; - - if (weapon.PoisonCharges > 0) - from.SendLocalizedMessage(1005423); // You have removed some of the caustic substance, but not all. - else - from.SendLocalizedMessage(1010497); // You have cleaned the item. - } - } - else if (obj == from && obj is PlayerMobile pm) - { - if (pm.BodyMod == 183 || pm.BodyMod == 184) - { - pm.SavagePaintExpiration = TimeSpan.Zero; - - pm.BodyMod = 0; - pm.HueMod = -1; - - from.SendLocalizedMessage(1040006); // You wipe away all of your body paint. - - Consume(); - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1005422); // Hmmmm... this does not need to be cleaned. - } - } - else if (obj is BaseBeverage beverage) - { - if (beverage.Content == BeverageType.Liquor) - { - Firebomb bomb = new Firebomb(beverage.ItemID); - bomb.Name = beverage.Name; - - beverage.ReplaceWith(bomb); - - from.SendLocalizedMessage(1060580); // You prepare a firebomb. - Consume(); - } - } - else if (obj is Firebomb) - { - from.SendLocalizedMessage(1060579); // That is already a firebomb! - } - else - { - from.SendLocalizedMessage(1005426); // The cloth will not work on that. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using System; +using Server.Mobiles; +using Server.Network; +using Server.Targeting; + +namespace Server.Items +{ + public class OilCloth : Item, IScissorable, IDyable + { + [Constructible] + public OilCloth() : base(0x175D) => Hue = 2001; + + public OilCloth(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041498; // oil cloth + + public override double DefaultWeight => 1.0; + + public bool Dye(Mobile from, DyeTub sender) + { + if (Deleted) + return false; + + Hue = sender.DyedHue; + + return true; + } + + public bool Scissor(Mobile from, Scissors scissors) + { + if (Deleted || !from.CanSee(this)) + return false; + + ScissorHelper(from, new Bandage(), 1); + + return true; + } + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + from.BeginTarget(-1, false, TargetFlags.None, OnTarget); + from.SendLocalizedMessage(1005424); // Select the weapon or armor you wish to use the cloth on. + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + + public void OnTarget(Mobile from, object obj) + { + // TODO: Need details on how oil cloths should get consumed here + + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else if (obj is Item item && item.RootParent != from) + { + from.SendLocalizedMessage(1005425); // You may only wipe down items you are holding or carrying. + } + else if (obj is BaseWeapon weapon) + { + if (weapon.Poison == null || weapon.PoisonCharges <= 0) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1005422 + ); // Hmmmm... this does not need to be cleaned. + } + else + { + if (weapon.PoisonCharges < 2) + weapon.PoisonCharges = 0; + else + weapon.PoisonCharges -= 2; + + if (weapon.PoisonCharges > 0) + from.SendLocalizedMessage(1005423); // You have removed some of the caustic substance, but not all. + else + from.SendLocalizedMessage(1010497); // You have cleaned the item. + } + } + else if (obj == from && obj is PlayerMobile pm) + { + if (pm.BodyMod == 183 || pm.BodyMod == 184) + { + pm.SavagePaintExpiration = TimeSpan.Zero; + + pm.BodyMod = 0; + pm.HueMod = -1; + + from.SendLocalizedMessage(1040006); // You wipe away all of your body paint. + + Consume(); + } + else + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1005422 + ); // Hmmmm... this does not need to be cleaned. + } + } + else if (obj is BaseBeverage beverage) + { + if (beverage.Content == BeverageType.Liquor) + { + var bomb = new Firebomb(beverage.ItemID); + bomb.Name = beverage.Name; + + beverage.ReplaceWith(bomb); + + from.SendLocalizedMessage(1060580); // You prepare a firebomb. + Consume(); + } + } + else if (obj is Firebomb) + { + from.SendLocalizedMessage(1060579); // That is already a firebomb! + } + else + { + from.SendLocalizedMessage(1005426); // The cloth will not work on that. + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Origami.cs b/Projects/UOContent/Items/Misc/Origami.cs index a62876a2d..1a2ad546f 100644 --- a/Projects/UOContent/Items/Misc/Origami.cs +++ b/Projects/UOContent/Items/Misc/Origami.cs @@ -1,214 +1,214 @@ -namespace Server.Items -{ - public class OrigamiPaper : Item - { - [Constructible] - public OrigamiPaper() : base(0x2830) - { - } - - public OrigamiPaper(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1030288; // origami paper - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else - { - Delete(); - - Item i = Utility.Random(from.BAC >= 5 ? 6 : 5) switch - { - 0 => new OrigamiButterfly(), - 1 => new OrigamiSwan(), - 2 => new OrigamiFrog(), - 3 => new OrigamiShape(), - 4 => new OrigamiSongbird(), - 5 => new OrigamiFish(), - _ => null - }; - - if (i != null) - from.AddToBackpack(i); - - from.SendLocalizedMessage(1070822); // You fold the paper into an interesting shape. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class OrigamiButterfly : Item - { - [Constructible] - public OrigamiButterfly() : base(0x2838) => LootType = LootType.Blessed; - - public OrigamiButterfly(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1030296; // a delicate origami butterfly - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class OrigamiSwan : Item - { - [Constructible] - public OrigamiSwan() : base(0x2839) => LootType = LootType.Blessed; - - public OrigamiSwan(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1030297; // a delicate origami swan - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class OrigamiFrog : Item - { - [Constructible] - public OrigamiFrog() : base(0x283A) => LootType = LootType.Blessed; - - public OrigamiFrog(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1030298; // a delicate origami frog - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class OrigamiShape : Item - { - [Constructible] - public OrigamiShape() : base(0x283B) => LootType = LootType.Blessed; - - public OrigamiShape(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1030299; // an intricate geometric origami shape - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class OrigamiSongbird : Item - { - [Constructible] - public OrigamiSongbird() : base(0x283C) => LootType = LootType.Blessed; - - public OrigamiSongbird(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1030300; // a delicate origami songbird - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class OrigamiFish : Item - { - [Constructible] - public OrigamiFish() : base(0x283D) => LootType = LootType.Blessed; - - public OrigamiFish(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1030301; // a delicate origami fish - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} +namespace Server.Items +{ + public class OrigamiPaper : Item + { + [Constructible] + public OrigamiPaper() : base(0x2830) + { + } + + public OrigamiPaper(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1030288; // origami paper + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else + { + Delete(); + + Item i = Utility.Random(from.BAC >= 5 ? 6 : 5) switch + { + 0 => new OrigamiButterfly(), + 1 => new OrigamiSwan(), + 2 => new OrigamiFrog(), + 3 => new OrigamiShape(), + 4 => new OrigamiSongbird(), + 5 => new OrigamiFish(), + _ => null + }; + + if (i != null) + from.AddToBackpack(i); + + from.SendLocalizedMessage(1070822); // You fold the paper into an interesting shape. + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } + + public class OrigamiButterfly : Item + { + [Constructible] + public OrigamiButterfly() : base(0x2838) => LootType = LootType.Blessed; + + public OrigamiButterfly(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1030296; // a delicate origami butterfly + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } + + public class OrigamiSwan : Item + { + [Constructible] + public OrigamiSwan() : base(0x2839) => LootType = LootType.Blessed; + + public OrigamiSwan(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1030297; // a delicate origami swan + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } + + public class OrigamiFrog : Item + { + [Constructible] + public OrigamiFrog() : base(0x283A) => LootType = LootType.Blessed; + + public OrigamiFrog(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1030298; // a delicate origami frog + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } + + public class OrigamiShape : Item + { + [Constructible] + public OrigamiShape() : base(0x283B) => LootType = LootType.Blessed; + + public OrigamiShape(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1030299; // an intricate geometric origami shape + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } + + public class OrigamiSongbird : Item + { + [Constructible] + public OrigamiSongbird() : base(0x283C) => LootType = LootType.Blessed; + + public OrigamiSongbird(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1030300; // a delicate origami songbird + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } + + public class OrigamiFish : Item + { + [Constructible] + public OrigamiFish() : base(0x283D) => LootType = LootType.Blessed; + + public OrigamiFish(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1030301; // a delicate origami fish + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Painted Caves/GrobusFur.cs b/Projects/UOContent/Items/Misc/Painted Caves/GrobusFur.cs index 2e72f1f37..793b7cc9f 100644 --- a/Projects/UOContent/Items/Misc/Painted Caves/GrobusFur.cs +++ b/Projects/UOContent/Items/Misc/Painted Caves/GrobusFur.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class GrobusFur : Item - { - [Constructible] - public GrobusFur() : base(0x11F4) - { - LootType = LootType.Blessed; - Hue = 0x455; - } - - public GrobusFur(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074676; // Grobu's Fur - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class GrobusFur : Item + { + [Constructible] + public GrobusFur() : base(0x11F4) + { + LootType = LootType.Blessed; + Hue = 0x455; + } + + public GrobusFur(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074676; // Grobu's Fur + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Painted Caves/PrimitiveFetish.cs b/Projects/UOContent/Items/Misc/Painted Caves/PrimitiveFetish.cs index ad16b3545..5e448d32e 100644 --- a/Projects/UOContent/Items/Misc/Painted Caves/PrimitiveFetish.cs +++ b/Projects/UOContent/Items/Misc/Painted Caves/PrimitiveFetish.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class PrimitiveFetish : Item - { - [Constructible] - public PrimitiveFetish() : base(0x23F) - { - LootType = LootType.Blessed; - Hue = 0x244; - } - - public PrimitiveFetish(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074675; // Primitive Fetish - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class PrimitiveFetish : Item + { + [Constructible] + public PrimitiveFetish() : base(0x23F) + { + LootType = LootType.Blessed; + Hue = 0x244; + } + + public PrimitiveFetish(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074675; // Primitive Fetish + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Palace of Paroxysmus/AcidProofRope.cs b/Projects/UOContent/Items/Misc/Palace of Paroxysmus/AcidProofRope.cs index 49d047093..131a23cbc 100644 --- a/Projects/UOContent/Items/Misc/Palace of Paroxysmus/AcidProofRope.cs +++ b/Projects/UOContent/Items/Misc/Palace of Paroxysmus/AcidProofRope.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class AcidProofRope : Item - { - [Constructible] - public AcidProofRope() : base(0x20D) => Hue = 0x3D1; - - public AcidProofRope(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074886; // Acid Proof Rope - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class AcidProofRope : Item + { + [Constructible] + public AcidProofRope() : base(0x20D) => Hue = 0x3D1; + + public AcidProofRope(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074886; // Acid Proof Rope + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Palace of Paroxysmus/ParoxysmusCorrodedStein.cs b/Projects/UOContent/Items/Misc/Palace of Paroxysmus/ParoxysmusCorrodedStein.cs index 65d4b339a..66af50a40 100644 --- a/Projects/UOContent/Items/Misc/Palace of Paroxysmus/ParoxysmusCorrodedStein.cs +++ b/Projects/UOContent/Items/Misc/Palace of Paroxysmus/ParoxysmusCorrodedStein.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class ParoxysmusCorrodedStein : Item - { - [Constructible] - public ParoxysmusCorrodedStein() : base(0x9D6) - { - } - - public ParoxysmusCorrodedStein(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072083; // Paroxysmus' Corroded Stein - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ParoxysmusCorrodedStein : Item + { + [Constructible] + public ParoxysmusCorrodedStein() : base(0x9D6) + { + } + + public ParoxysmusCorrodedStein(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072083; // Paroxysmus' Corroded Stein + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Palace of Paroxysmus/ParoxysmusDinner.cs b/Projects/UOContent/Items/Misc/Palace of Paroxysmus/ParoxysmusDinner.cs index c8ea43ff4..39d45486b 100644 --- a/Projects/UOContent/Items/Misc/Palace of Paroxysmus/ParoxysmusDinner.cs +++ b/Projects/UOContent/Items/Misc/Palace of Paroxysmus/ParoxysmusDinner.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class ParoxysmusDinner : Item - { - [Constructible] - public ParoxysmusDinner() : base(0x1E95) - { - } - - public ParoxysmusDinner(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072086; // Paroxysmus' Dinner - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ParoxysmusDinner : Item + { + [Constructible] + public ParoxysmusDinner() : base(0x1E95) + { + } + + public ParoxysmusDinner(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072086; // Paroxysmus' Dinner + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Palace of Paroxysmus/StringOfPartsOfParoxysmusVictims.cs b/Projects/UOContent/Items/Misc/Palace of Paroxysmus/StringOfPartsOfParoxysmusVictims.cs index 21aad260e..a32a38cbe 100644 --- a/Projects/UOContent/Items/Misc/Palace of Paroxysmus/StringOfPartsOfParoxysmusVictims.cs +++ b/Projects/UOContent/Items/Misc/Palace of Paroxysmus/StringOfPartsOfParoxysmusVictims.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class StringOfPartsOfParoxysmusVictims : Item - { - [Constructible] - public StringOfPartsOfParoxysmusVictims() : base(0xFD2) - { - } - - public StringOfPartsOfParoxysmusVictims(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072082; // String of Parts of Paroxysmus' Victims - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class StringOfPartsOfParoxysmusVictims : Item + { + [Constructible] + public StringOfPartsOfParoxysmusVictims() : base(0xFD2) + { + } + + public StringOfPartsOfParoxysmusVictims(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072082; // String of Parts of Paroxysmus' Victims + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Palace of Paroxysmus/SweatOfParoxysmus.cs b/Projects/UOContent/Items/Misc/Palace of Paroxysmus/SweatOfParoxysmus.cs index 49c96694b..e7f370faf 100644 --- a/Projects/UOContent/Items/Misc/Palace of Paroxysmus/SweatOfParoxysmus.cs +++ b/Projects/UOContent/Items/Misc/Palace of Paroxysmus/SweatOfParoxysmus.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class SweatOfParoxysmus : Item - { - [Constructible] - public SweatOfParoxysmus() : base(0xF01) - { - } - - public SweatOfParoxysmus(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072081; // Sweat of Paroxysmus - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SweatOfParoxysmus : Item + { + [Constructible] + public SweatOfParoxysmus() : base(0xF01) + { + } + + public SweatOfParoxysmus(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072081; // Sweat of Paroxysmus + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/PlayerBulletinBoards.cs b/Projects/UOContent/Items/Misc/PlayerBulletinBoards.cs index ad3ac3271..b8936229c 100644 --- a/Projects/UOContent/Items/Misc/PlayerBulletinBoards.cs +++ b/Projects/UOContent/Items/Misc/PlayerBulletinBoards.cs @@ -1,588 +1,593 @@ -using System; -using System.Collections.Generic; -using Server.Gumps; -using Server.Multis; -using Server.Prompts; -using Server.Mobiles; -using Server.Network; -using Server.ContextMenus; - -namespace Server.Items -{ - public class PlayerBBSouth : BasePlayerBB - { - public override int LabelNumber => 1062421; // bulletin board (south) - - [Constructible] - public PlayerBBSouth() : base(0x2311) => Weight = 15.0; - - public PlayerBBSouth(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PlayerBBEast : BasePlayerBB - { - public override int LabelNumber => 1062420; // bulletin board (east) - - [Constructible] - public PlayerBBEast() : base(0x2312) => Weight = 15.0; - - public PlayerBBEast(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public abstract class BasePlayerBB : Item, ISecurable - { - public List Messages { get; private set; } - - public PlayerBBMessage Greeting { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public string Title { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public SecureLevel Level { get; set; } - - public BasePlayerBB(int itemID) : base(itemID) - { - Messages = new List(); - Level = SecureLevel.Anyone; - } - - public BasePlayerBB(Serial serial) : base(serial) - { - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - SetSecureLevelEntry.AddTo(from, this, list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - - writer.Write((int)Level); - - writer.Write(Title); - - if (Greeting != null) - { - writer.Write(true); - Greeting.Serialize(writer); - } - else - { - writer.Write(false); - } - - writer.WriteEncodedInt(Messages.Count); - - for (int i = 0; i < Messages.Count; ++i) - Messages[i].Serialize(writer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - Level = (SecureLevel)reader.ReadInt(); - goto case 0; - } - case 0: - { - if (version < 1) - Level = SecureLevel.Anyone; - - Title = reader.ReadString(); - - if (reader.ReadBool()) - Greeting = new PlayerBBMessage(reader); - - int count = reader.ReadEncodedInt(); - - Messages = new List(count); - - for (int i = 0; i < count; ++i) - Messages.Add(new PlayerBBMessage(reader)); - - break; - } - } - } - - public static bool CheckAccess(BaseHouse house, Mobile from) - { - if (house.Public || !house.IsAosRules) - return !house.IsBanned(from); - - return house.HasAccess(from); - } - - public override void OnDoubleClick(Mobile from) - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (house?.HasLockedDownItem(this) != true) - from.SendLocalizedMessage(1062396); // This bulletin board must be locked down in a house to be usable. - else if (!from.InRange(GetWorldLocation(), 2) || !from.InLOS(this)) - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - else if (CheckAccess(house, from)) - from.SendGump(new PlayerBBGump(from, house, this, 0)); - } - - public class PostPrompt : Prompt - { - private readonly int m_Page; - private readonly BaseHouse m_House; - private readonly BasePlayerBB m_Board; - private readonly bool m_Greeting; - - public PostPrompt(int page, BaseHouse house, BasePlayerBB board, bool greeting) - { - m_Page = page; - m_House = house; - m_Board = board; - m_Greeting = greeting; - } - - public override void OnCancel(Mobile from) - { - OnResponse(from, ""); - } - - public override void OnResponse(Mobile from, string text) - { - int page = m_Page; - BaseHouse house = m_House; - BasePlayerBB board = m_Board; - - if (house?.HasLockedDownItem(board) != true) - { - from.SendLocalizedMessage(1062396); // This bulletin board must be locked down in a house to be usable. - return; - } - - if (!from.InRange(board.GetWorldLocation(), 2) || !from.InLOS(board)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return; - } - if (!CheckAccess(house, from)) - { - from.SendLocalizedMessage(1062398); // You are not allowed to post to this bulletin board. - return; - } - if (m_Greeting && !house.IsOwner(from)) return; - - text = text.Trim(); - - if (text.Length > 255) - text = text.Substring(0, 255); - - if (text.Length > 0) - { - PlayerBBMessage message = new PlayerBBMessage(DateTime.UtcNow, from, text); - - if (m_Greeting) - { - board.Greeting = message; - } - else - { - board.Messages.Add(message); - - if (board.Messages.Count > 50) - { - board.Messages.RemoveAt(0); - - if (page > 0) - --page; - } - } - } - - from.SendGump(new PlayerBBGump(from, house, board, page)); - } - } - - public class SetTitlePrompt : Prompt - { - private readonly int m_Page; - private readonly BaseHouse m_House; - private readonly BasePlayerBB m_Board; - - public SetTitlePrompt(int page, BaseHouse house, BasePlayerBB board) - { - m_Page = page; - m_House = house; - m_Board = board; - } - - public override void OnCancel(Mobile from) - { - OnResponse(from, ""); - } - - public override void OnResponse(Mobile from, string text) - { - int page = m_Page; - BaseHouse house = m_House; - BasePlayerBB board = m_Board; - - if (house?.HasLockedDownItem(board) != true) - { - from.SendLocalizedMessage(1062396); // This bulletin board must be locked down in a house to be usable. - return; - } - - if (!from.InRange(board.GetWorldLocation(), 2) || !from.InLOS(board)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return; - } - if (!CheckAccess(house, from)) - { - from.SendLocalizedMessage(1062398); // You are not allowed to post to this bulletin board. - return; - } - - text = text.Trim(); - - if (text.Length > 255) - text = text.Substring(0, 255); - - if (text.Length > 0) - board.Title = text; - - from.SendGump(new PlayerBBGump(from, house, board, page)); - } - } - } - - public class PlayerBBMessage - { - [CommandProperty(AccessLevel.GameMaster)] - public DateTime Time { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Poster { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public string Message { get; set; } - - public PlayerBBMessage(DateTime time, Mobile poster, string message) - { - Time = time; - Poster = poster; - Message = message; - } - - public PlayerBBMessage(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 0: - { - Time = reader.ReadDateTime(); - Poster = reader.ReadMobile(); - Message = reader.ReadString(); - break; - } - } - } - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(Time); - writer.Write(Poster); - writer.Write(Message); - } - } - - public class PlayerBBGump : Gump - { - private readonly int m_Page; - private readonly Mobile m_From; - private readonly BaseHouse m_House; - private readonly BasePlayerBB m_Board; - - private const int LabelColor = 0x7FFF; - private const int LabelHue = 1153; - - public override void OnResponse(NetState sender, RelayInfo info) - { - int page = m_Page; - Mobile from = m_From; - BaseHouse house = m_House; - BasePlayerBB board = m_Board; - - if (house?.HasLockedDownItem(board) != true) - { - from.SendLocalizedMessage(1062396); // This bulletin board must be locked down in a house to be usable. - return; - } - - if (!from.InRange(board.GetWorldLocation(), 2) || !from.InLOS(board)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return; - } - if (!BasePlayerBB.CheckAccess(house, from)) - { - from.SendLocalizedMessage(1062398); // You are not allowed to post to this bulletin board. - return; - } - - switch (info.ButtonID) - { - case 1: // Post message - { - from.Prompt = new BasePlayerBB.PostPrompt(page, house, board, false); - from.SendLocalizedMessage(1062397); // Please enter your message: - - break; - } - case 2: // Set title - { - if (house.IsOwner(from)) - { - from.Prompt = new BasePlayerBB.SetTitlePrompt(page, house, board); - from.SendLocalizedMessage(1062402); // Enter new title: - } - - break; - } - case 3: // Post greeting - { - if (house.IsOwner(from)) - { - from.Prompt = new BasePlayerBB.PostPrompt(page, house, board, true); - from.SendLocalizedMessage(1062404); // Enter new greeting (this will always be the first post): - } - - break; - } - case 4: // Scroll up - { - if (page == 0) - page = board.Messages.Count; - else - page -= 1; - - from.SendGump(new PlayerBBGump(from, house, board, page)); - - break; - } - case 5: // Scroll down - { - page += 1; - page %= board.Messages.Count + 1; - - from.SendGump(new PlayerBBGump(from, house, board, page)); - - break; - } - case 6: // Banish poster - { - if (house.IsOwner(from)) - { - if (page >= 1 && page <= board.Messages.Count) - { - PlayerBBMessage message = board.Messages[page - 1]; - Mobile poster = message.Poster; - - if (poster == null) - { - from.SendGump(new PlayerBBGump(from, house, board, page)); - return; - } - - if (poster.AccessLevel > AccessLevel.Player && from.AccessLevel <= poster.AccessLevel) - { - from.SendLocalizedMessage(501354); // Uh oh...a bigger boot may be required. - } - else if (house.IsFriend(poster)) - { - from.SendLocalizedMessage(1060750); // That person is a friend, co-owner, or owner of this house, and therefore cannot be banished! - } - else if (poster is PlayerVendor) - { - from.SendLocalizedMessage(501351); // You cannot eject a vendor. - } - else if (house.Bans.Count >= BaseHouse.MaxBans) - { - from.SendLocalizedMessage(501355); // The ban limit for this house has been reached! - } - else if (house.IsBanned(poster)) - { - from.SendLocalizedMessage(501356); // This person is already banned! - } - else if (poster is BaseCreature creature && creature.NoHouseRestrictions) - { - from.SendLocalizedMessage(1062040); // You cannot ban that. - } - else - { - if (!house.Bans.Contains(poster)) - house.Bans.Add(poster); - - from.SendLocalizedMessage(1062417); // That person has been banned from this house. - - if (house.IsInside(poster) && !BasePlayerBB.CheckAccess(house, poster)) - poster.MoveToWorld(house.BanLocation, house.Map); - } - } - - from.SendGump(new PlayerBBGump(from, house, board, page)); - } - - break; - } - case 7: // Delete message - { - if (house.IsOwner(from)) - { - if (page >= 1 && page <= board.Messages.Count) - board.Messages.RemoveAt(page - 1); - - from.SendGump(new PlayerBBGump(from, house, board, 0)); - } - - break; - } - case 8: // Post props - { - if (from.AccessLevel >= AccessLevel.GameMaster) - { - PlayerBBMessage message = board.Greeting; - - if (page >= 1 && page <= board.Messages.Count) - message = board.Messages[page - 1]; - - from.SendGump(new PlayerBBGump(from, house, board, page)); - from.SendGump(new PropertiesGump(from, message)); - } - - break; - } - } - } - - public PlayerBBGump(Mobile from, BaseHouse house, BasePlayerBB board, int page) : base(50, 10) - { - from.CloseGump(); - - m_Page = page; - m_From = from; - m_House = house; - m_Board = board; - - AddPage(0); - - AddImage(30, 30, 5400); - - AddButton(393, 145, 2084, 2084, 4); // Scroll up - AddButton(390, 371, 2085, 2085, 5); // Scroll down - - AddButton(32, 183, 5412, 5413, 1); // Post message - - if (house.IsOwner(from)) - { - AddButton(63, 90, 5601, 5605, 2); - AddHtmlLocalized(81, 89, 230, 20, 1062400, LabelColor); // Set title - - AddButton(63, 109, 5601, 5605, 3); - AddHtmlLocalized(81, 108, 230, 20, 1062401, LabelColor); // Post greeting - } - - string title = board.Title; - - if (title != null) - AddHtml(183, 68, 180, 23, title); - - AddHtmlLocalized(385, 89, 60, 20, 1062409, LabelColor); // Post - - AddLabel(440, 89, LabelHue, page.ToString()); - AddLabel(455, 89, LabelHue, "/"); - AddLabel(470, 89, LabelHue, board.Messages.Count.ToString()); - - PlayerBBMessage message = board.Greeting; - - if (page >= 1 && page <= board.Messages.Count) - message = board.Messages[page - 1]; - - AddImageTiled(150, 220, 240, 1, 2700); // Separator - - AddHtmlLocalized(150, 180, 100, 20, 1062405, 16715); // Posted On: - AddHtmlLocalized(150, 200, 100, 20, 1062406, 16715); // Posted By: - - if (message != null) - { - AddHtml(255, 180, 150, 20, message.Time.ToString("yyyy-MM-dd HH:mm:ss")); - - Mobile poster = message.Poster; - string name = poster?.Name?.Trim().IsNullOrDefault("Someone"); - - AddHtml(255, 200, 150, 20, name); - - AddHtml(150, 240, 250, 100, message.Message ?? ""); - - if (message != board.Greeting && house.IsOwner(from)) - { - AddButton(130, 395, 1209, 1210, 6); - AddHtmlLocalized(150, 393, 150, 20, 1062410, LabelColor); // Banish Poster - - AddButton(310, 395, 1209, 1210, 7); - AddHtmlLocalized(330, 393, 150, 20, 1062411, LabelColor); // Delete Message - } - - if (from.AccessLevel >= AccessLevel.GameMaster) - AddButton(135, 242, 1209, 1210, 8); // Post props - } - } - } -} +using System; +using System.Collections.Generic; +using Server.ContextMenus; +using Server.Gumps; +using Server.Mobiles; +using Server.Multis; +using Server.Network; +using Server.Prompts; + +namespace Server.Items +{ + public class PlayerBBSouth : BasePlayerBB + { + [Constructible] + public PlayerBBSouth() : base(0x2311) => Weight = 15.0; + + public PlayerBBSouth(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1062421; // bulletin board (south) + + 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 class PlayerBBEast : BasePlayerBB + { + [Constructible] + public PlayerBBEast() : base(0x2312) => Weight = 15.0; + + public PlayerBBEast(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1062420; // bulletin board (east) + + 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 abstract class BasePlayerBB : Item, ISecurable + { + public BasePlayerBB(int itemID) : base(itemID) + { + Messages = new List(); + Level = SecureLevel.Anyone; + } + + public BasePlayerBB(Serial serial) : base(serial) + { + } + + public List Messages { get; private set; } + + public PlayerBBMessage Greeting { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public string Title { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public SecureLevel Level { get; set; } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + SetSecureLevelEntry.AddTo(from, this, list); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + + writer.Write((int)Level); + + writer.Write(Title); + + if (Greeting != null) + { + writer.Write(true); + Greeting.Serialize(writer); + } + else + { + writer.Write(false); + } + + writer.WriteEncodedInt(Messages.Count); + + for (var i = 0; i < Messages.Count; ++i) + Messages[i].Serialize(writer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + Level = (SecureLevel)reader.ReadInt(); + goto case 0; + } + case 0: + { + if (version < 1) + Level = SecureLevel.Anyone; + + Title = reader.ReadString(); + + if (reader.ReadBool()) + Greeting = new PlayerBBMessage(reader); + + var count = reader.ReadEncodedInt(); + + Messages = new List(count); + + for (var i = 0; i < count; ++i) + Messages.Add(new PlayerBBMessage(reader)); + + break; + } + } + } + + public static bool CheckAccess(BaseHouse house, Mobile from) + { + if (house.Public || !house.IsAosRules) + return !house.IsBanned(from); + + return house.HasAccess(from); + } + + public override void OnDoubleClick(Mobile from) + { + var house = BaseHouse.FindHouseAt(this); + + if (house?.HasLockedDownItem(this) != true) + from.SendLocalizedMessage(1062396); // This bulletin board must be locked down in a house to be usable. + else if (!from.InRange(GetWorldLocation(), 2) || !from.InLOS(this)) + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + else if (CheckAccess(house, from)) + from.SendGump(new PlayerBBGump(from, house, this, 0)); + } + + public class PostPrompt : Prompt + { + private readonly BasePlayerBB m_Board; + private readonly bool m_Greeting; + private readonly BaseHouse m_House; + private readonly int m_Page; + + public PostPrompt(int page, BaseHouse house, BasePlayerBB board, bool greeting) + { + m_Page = page; + m_House = house; + m_Board = board; + m_Greeting = greeting; + } + + public override void OnCancel(Mobile from) + { + OnResponse(from, ""); + } + + public override void OnResponse(Mobile from, string text) + { + var page = m_Page; + var house = m_House; + var board = m_Board; + + if (house?.HasLockedDownItem(board) != true) + { + from.SendLocalizedMessage(1062396); // This bulletin board must be locked down in a house to be usable. + return; + } + + if (!from.InRange(board.GetWorldLocation(), 2) || !from.InLOS(board)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return; + } + + if (!CheckAccess(house, from)) + { + from.SendLocalizedMessage(1062398); // You are not allowed to post to this bulletin board. + return; + } + + if (m_Greeting && !house.IsOwner(from)) return; + + text = text.Trim(); + + if (text.Length > 255) + text = text.Substring(0, 255); + + if (text.Length > 0) + { + var message = new PlayerBBMessage(DateTime.UtcNow, from, text); + + if (m_Greeting) + { + board.Greeting = message; + } + else + { + board.Messages.Add(message); + + if (board.Messages.Count > 50) + { + board.Messages.RemoveAt(0); + + if (page > 0) + --page; + } + } + } + + from.SendGump(new PlayerBBGump(from, house, board, page)); + } + } + + public class SetTitlePrompt : Prompt + { + private readonly BasePlayerBB m_Board; + private readonly BaseHouse m_House; + private readonly int m_Page; + + public SetTitlePrompt(int page, BaseHouse house, BasePlayerBB board) + { + m_Page = page; + m_House = house; + m_Board = board; + } + + public override void OnCancel(Mobile from) + { + OnResponse(from, ""); + } + + public override void OnResponse(Mobile from, string text) + { + var page = m_Page; + var house = m_House; + var board = m_Board; + + if (house?.HasLockedDownItem(board) != true) + { + from.SendLocalizedMessage(1062396); // This bulletin board must be locked down in a house to be usable. + return; + } + + if (!from.InRange(board.GetWorldLocation(), 2) || !from.InLOS(board)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return; + } + + if (!CheckAccess(house, from)) + { + from.SendLocalizedMessage(1062398); // You are not allowed to post to this bulletin board. + return; + } + + text = text.Trim(); + + if (text.Length > 255) + text = text.Substring(0, 255); + + if (text.Length > 0) + board.Title = text; + + from.SendGump(new PlayerBBGump(from, house, board, page)); + } + } + } + + public class PlayerBBMessage + { + public PlayerBBMessage(DateTime time, Mobile poster, string message) + { + Time = time; + Poster = poster; + Message = message; + } + + public PlayerBBMessage(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 0: + { + Time = reader.ReadDateTime(); + Poster = reader.ReadMobile(); + Message = reader.ReadString(); + break; + } + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime Time { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Poster { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public string Message { get; set; } + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(Time); + writer.Write(Poster); + writer.Write(Message); + } + } + + public class PlayerBBGump : Gump + { + private const int LabelColor = 0x7FFF; + private const int LabelHue = 1153; + private readonly BasePlayerBB m_Board; + private readonly Mobile m_From; + private readonly BaseHouse m_House; + private readonly int m_Page; + + public PlayerBBGump(Mobile from, BaseHouse house, BasePlayerBB board, int page) : base(50, 10) + { + from.CloseGump(); + + m_Page = page; + m_From = from; + m_House = house; + m_Board = board; + + AddPage(0); + + AddImage(30, 30, 5400); + + AddButton(393, 145, 2084, 2084, 4); // Scroll up + AddButton(390, 371, 2085, 2085, 5); // Scroll down + + AddButton(32, 183, 5412, 5413, 1); // Post message + + if (house.IsOwner(from)) + { + AddButton(63, 90, 5601, 5605, 2); + AddHtmlLocalized(81, 89, 230, 20, 1062400, LabelColor); // Set title + + AddButton(63, 109, 5601, 5605, 3); + AddHtmlLocalized(81, 108, 230, 20, 1062401, LabelColor); // Post greeting + } + + var title = board.Title; + + if (title != null) + AddHtml(183, 68, 180, 23, title); + + AddHtmlLocalized(385, 89, 60, 20, 1062409, LabelColor); // Post + + AddLabel(440, 89, LabelHue, page.ToString()); + AddLabel(455, 89, LabelHue, "/"); + AddLabel(470, 89, LabelHue, board.Messages.Count.ToString()); + + var message = board.Greeting; + + if (page >= 1 && page <= board.Messages.Count) + message = board.Messages[page - 1]; + + AddImageTiled(150, 220, 240, 1, 2700); // Separator + + AddHtmlLocalized(150, 180, 100, 20, 1062405, 16715); // Posted On: + AddHtmlLocalized(150, 200, 100, 20, 1062406, 16715); // Posted By: + + if (message != null) + { + AddHtml(255, 180, 150, 20, message.Time.ToString("yyyy-MM-dd HH:mm:ss")); + + var poster = message.Poster; + var name = poster?.Name?.Trim().IsNullOrDefault("Someone"); + + AddHtml(255, 200, 150, 20, name); + + AddHtml(150, 240, 250, 100, message.Message ?? ""); + + if (message != board.Greeting && house.IsOwner(from)) + { + AddButton(130, 395, 1209, 1210, 6); + AddHtmlLocalized(150, 393, 150, 20, 1062410, LabelColor); // Banish Poster + + AddButton(310, 395, 1209, 1210, 7); + AddHtmlLocalized(330, 393, 150, 20, 1062411, LabelColor); // Delete Message + } + + if (from.AccessLevel >= AccessLevel.GameMaster) + AddButton(135, 242, 1209, 1210, 8); // Post props + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var page = m_Page; + var from = m_From; + var house = m_House; + var board = m_Board; + + if (house?.HasLockedDownItem(board) != true) + { + from.SendLocalizedMessage(1062396); // This bulletin board must be locked down in a house to be usable. + return; + } + + if (!from.InRange(board.GetWorldLocation(), 2) || !from.InLOS(board)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return; + } + + if (!BasePlayerBB.CheckAccess(house, from)) + { + from.SendLocalizedMessage(1062398); // You are not allowed to post to this bulletin board. + return; + } + + switch (info.ButtonID) + { + case 1: // Post message + { + from.Prompt = new BasePlayerBB.PostPrompt(page, house, board, false); + from.SendLocalizedMessage(1062397); // Please enter your message: + + break; + } + case 2: // Set title + { + if (house.IsOwner(from)) + { + from.Prompt = new BasePlayerBB.SetTitlePrompt(page, house, board); + from.SendLocalizedMessage(1062402); // Enter new title: + } + + break; + } + case 3: // Post greeting + { + if (house.IsOwner(from)) + { + from.Prompt = new BasePlayerBB.PostPrompt(page, house, board, true); + from.SendLocalizedMessage(1062404); // Enter new greeting (this will always be the first post): + } + + break; + } + case 4: // Scroll up + { + if (page == 0) + page = board.Messages.Count; + else + page -= 1; + + from.SendGump(new PlayerBBGump(from, house, board, page)); + + break; + } + case 5: // Scroll down + { + page += 1; + page %= board.Messages.Count + 1; + + from.SendGump(new PlayerBBGump(from, house, board, page)); + + break; + } + case 6: // Banish poster + { + if (house.IsOwner(from)) + { + if (page >= 1 && page <= board.Messages.Count) + { + var message = board.Messages[page - 1]; + var poster = message.Poster; + + if (poster == null) + { + from.SendGump(new PlayerBBGump(from, house, board, page)); + return; + } + + if (poster.AccessLevel > AccessLevel.Player && from.AccessLevel <= poster.AccessLevel) + { + from.SendLocalizedMessage(501354); // Uh oh...a bigger boot may be required. + } + else if (house.IsFriend(poster)) + { + from.SendLocalizedMessage( + 1060750 + ); // That person is a friend, co-owner, or owner of this house, and therefore cannot be banished! + } + else if (poster is PlayerVendor) + { + from.SendLocalizedMessage(501351); // You cannot eject a vendor. + } + else if (house.Bans.Count >= BaseHouse.MaxBans) + { + from.SendLocalizedMessage(501355); // The ban limit for this house has been reached! + } + else if (house.IsBanned(poster)) + { + from.SendLocalizedMessage(501356); // This person is already banned! + } + else if (poster is BaseCreature creature && creature.NoHouseRestrictions) + { + from.SendLocalizedMessage(1062040); // You cannot ban that. + } + else + { + if (!house.Bans.Contains(poster)) + house.Bans.Add(poster); + + from.SendLocalizedMessage(1062417); // That person has been banned from this house. + + if (house.IsInside(poster) && !BasePlayerBB.CheckAccess(house, poster)) + poster.MoveToWorld(house.BanLocation, house.Map); + } + } + + from.SendGump(new PlayerBBGump(from, house, board, page)); + } + + break; + } + case 7: // Delete message + { + if (house.IsOwner(from)) + { + if (page >= 1 && page <= board.Messages.Count) + board.Messages.RemoveAt(page - 1); + + from.SendGump(new PlayerBBGump(from, house, board, 0)); + } + + break; + } + case 8: // Post props + { + if (from.AccessLevel >= AccessLevel.GameMaster) + { + var message = board.Greeting; + + if (page >= 1 && page <= board.Messages.Count) + message = board.Messages[page - 1]; + + from.SendGump(new PlayerBBGump(from, house, board, page)); + from.SendGump(new PropertiesGump(from, message)); + } + + break; + } + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/PlayerVendorDeed.cs b/Projects/UOContent/Items/Misc/PlayerVendorDeed.cs index d1d964159..d14b5e526 100644 --- a/Projects/UOContent/Items/Misc/PlayerVendorDeed.cs +++ b/Projects/UOContent/Items/Misc/PlayerVendorDeed.cs @@ -1,101 +1,105 @@ -using Server.Mobiles; -using Server.Multis; - -namespace Server.Items -{ - public class ContractOfEmployment : Item - { - [Constructible] - public ContractOfEmployment() : base(0x14F0) => Weight = 1.0; - - public ContractOfEmployment(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041243; // a contract of employment - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (from.AccessLevel >= AccessLevel.GameMaster) - { - from.SendLocalizedMessage(503248); // Your godly powers allow you to place this vendor whereever you wish. - - Mobile v = new PlayerVendor(from, BaseHouse.FindHouseAt(from)); - - v.Direction = from.Direction & Direction.Mask; - v.MoveToWorld(from.Location, from.Map); - - v.SayTo(from, 503246); // Ah! it feels good to be working again. - - Delete(); - } - else - { - BaseHouse house = BaseHouse.FindHouseAt(from); - - if (house == null) - { - from.SendLocalizedMessage(503240); // Vendors can only be placed in houses. - } - else if (!BaseHouse.NewVendorSystem && !house.IsFriend(from)) - { - from.SendLocalizedMessage( - 503242); // You must ask the owner of this building to name you a friend of the household in order to place a vendor here. - } - else if (BaseHouse.NewVendorSystem && !house.IsOwner(from)) - { - from.SendLocalizedMessage( - 1062423); // Only the house owner can directly place vendors. Please ask the house owner to offer you a vendor contract so that you may place a vendor in this house. - } - else if (!house.Public || !house.CanPlaceNewVendor()) - { - from.SendLocalizedMessage( - 503241); // You cannot place this vendor or barkeep. Make sure the house is public and has sufficient storage available. - } - else - { - BaseHouse.IsThereVendor(from.Location, from.Map, out bool vendor, out bool contract); - - if (vendor) - { - from.SendLocalizedMessage(1062677); // You cannot place a vendor or barkeep at this location. - } - else if (contract) - { - from.SendLocalizedMessage( - 1062678); // You cannot place a vendor or barkeep on top of a rental contract! - } - else - { - Mobile v = new PlayerVendor(from, house); - - v.Direction = from.Direction & Direction.Mask; - v.MoveToWorld(from.Location, from.Map); - - v.SayTo(from, 503246); // Ah! it feels good to be working again. - - Delete(); - } - } - } - } - } -} \ No newline at end of file +using Server.Mobiles; +using Server.Multis; + +namespace Server.Items +{ + public class ContractOfEmployment : Item + { + [Constructible] + public ContractOfEmployment() : base(0x14F0) => Weight = 1.0; + + public ContractOfEmployment(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041243; // a contract of employment + + 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 (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else if (from.AccessLevel >= AccessLevel.GameMaster) + { + from.SendLocalizedMessage(503248); // Your godly powers allow you to place this vendor whereever you wish. + + Mobile v = new PlayerVendor(from, BaseHouse.FindHouseAt(from)); + + v.Direction = from.Direction & Direction.Mask; + v.MoveToWorld(from.Location, from.Map); + + v.SayTo(from, 503246); // Ah! it feels good to be working again. + + Delete(); + } + else + { + var house = BaseHouse.FindHouseAt(from); + + if (house == null) + { + from.SendLocalizedMessage(503240); // Vendors can only be placed in houses. + } + else if (!BaseHouse.NewVendorSystem && !house.IsFriend(from)) + { + from.SendLocalizedMessage( + 503242 + ); // You must ask the owner of this building to name you a friend of the household in order to place a vendor here. + } + else if (BaseHouse.NewVendorSystem && !house.IsOwner(from)) + { + from.SendLocalizedMessage( + 1062423 + ); // Only the house owner can directly place vendors. Please ask the house owner to offer you a vendor contract so that you may place a vendor in this house. + } + else if (!house.Public || !house.CanPlaceNewVendor()) + { + from.SendLocalizedMessage( + 503241 + ); // You cannot place this vendor or barkeep. Make sure the house is public and has sufficient storage available. + } + else + { + BaseHouse.IsThereVendor(from.Location, from.Map, out var vendor, out var contract); + + if (vendor) + { + from.SendLocalizedMessage(1062677); // You cannot place a vendor or barkeep at this location. + } + else if (contract) + { + from.SendLocalizedMessage( + 1062678 + ); // You cannot place a vendor or barkeep on top of a rental contract! + } + else + { + Mobile v = new PlayerVendor(from, house); + + v.Direction = from.Direction & Direction.Mask; + v.MoveToWorld(from.Location, from.Map); + + v.SayTo(from, 503246); // Ah! it feels good to be working again. + + Delete(); + } + } + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/PoolOfAcid.cs b/Projects/UOContent/Items/Misc/PoolOfAcid.cs index e12156ecb..6f98fc6c6 100644 --- a/Projects/UOContent/Items/Misc/PoolOfAcid.cs +++ b/Projects/UOContent/Items/Misc/PoolOfAcid.cs @@ -1,94 +1,95 @@ -using System; -using System.Collections.Generic; -using Server.Mobiles; - -namespace Server.Items -{ - public class PoolOfAcid : Item - { - private readonly TimeSpan m_Duration; - private readonly int m_MinDamage; - private readonly int m_MaxDamage; - private readonly DateTime m_Created; - private bool m_Drying; - private readonly Timer m_Timer; - - [Constructible] - public PoolOfAcid() : this(TimeSpan.FromSeconds(10.0), 2, 5) - { - } - - public override string DefaultName => "a pool of acid"; - - [Constructible] - public PoolOfAcid(TimeSpan duration, int minDamage, int maxDamage) - : base(0x122A) - { - Hue = 0x3F; - Movable = false; - - m_MinDamage = minDamage; - m_MaxDamage = maxDamage; - m_Created = DateTime.UtcNow; - m_Duration = duration; - - m_Timer = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromSeconds(1), OnTick); - } - - public override void OnAfterDelete() - { - m_Timer?.Stop(); - } - - private void OnTick() - { - DateTime now = DateTime.UtcNow; - TimeSpan age = now - m_Created; - - if (age > m_Duration) - { - Delete(); - } - else - { - if (!m_Drying && age > m_Duration - age) - { - m_Drying = true; - ItemID = 0x122B; - } - - List toDamage = new List(); - - foreach (Mobile m in GetMobilesInRange(0)) - if (m.Alive && !m.IsDeadBondedPet && (!(m is BaseCreature bc) || bc.Controlled || bc.Summoned)) - toDamage.Add(m); - - for (int i = 0; i < toDamage.Count; i++) - Damage(toDamage[i]); - } - } - public override bool OnMoveOver(Mobile m) - { - Damage(m); - return true; - } - - public void Damage(Mobile m) - { - m.Damage(Utility.RandomMinMax(m_MinDamage, m_MaxDamage)); - } - - public PoolOfAcid(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - // Don't serialize these - } - - public override void Deserialize(IGenericReader reader) - { - } - } -} +using System; +using System.Collections.Generic; +using Server.Mobiles; + +namespace Server.Items +{ + public class PoolOfAcid : Item + { + private readonly DateTime m_Created; + private readonly TimeSpan m_Duration; + private readonly int m_MaxDamage; + private readonly int m_MinDamage; + private readonly Timer m_Timer; + private bool m_Drying; + + [Constructible] + public PoolOfAcid() : this(TimeSpan.FromSeconds(10.0), 2, 5) + { + } + + [Constructible] + public PoolOfAcid(TimeSpan duration, int minDamage, int maxDamage) + : base(0x122A) + { + Hue = 0x3F; + Movable = false; + + m_MinDamage = minDamage; + m_MaxDamage = maxDamage; + m_Created = DateTime.UtcNow; + m_Duration = duration; + + m_Timer = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromSeconds(1), OnTick); + } + + public PoolOfAcid(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a pool of acid"; + + public override void OnAfterDelete() + { + m_Timer?.Stop(); + } + + private void OnTick() + { + var now = DateTime.UtcNow; + var age = now - m_Created; + + if (age > m_Duration) + { + Delete(); + } + else + { + if (!m_Drying && age > m_Duration - age) + { + m_Drying = true; + ItemID = 0x122B; + } + + var toDamage = new List(); + + foreach (var m in GetMobilesInRange(0)) + if (m.Alive && !m.IsDeadBondedPet && (!(m is BaseCreature bc) || bc.Controlled || bc.Summoned)) + toDamage.Add(m); + + for (var i = 0; i < toDamage.Count; i++) + Damage(toDamage[i]); + } + } + + public override bool OnMoveOver(Mobile m) + { + Damage(m); + return true; + } + + public void Damage(Mobile m) + { + m.Damage(Utility.RandomMinMax(m_MinDamage, m_MaxDamage)); + } + + public override void Serialize(IGenericWriter writer) + { + // Don't serialize these + } + + public override void Deserialize(IGenericReader reader) + { + } + } +} diff --git a/Projects/UOContent/Items/Misc/PowerCrystal.cs b/Projects/UOContent/Items/Misc/PowerCrystal.cs index 59e6a0fb1..fcb337581 100644 --- a/Projects/UOContent/Items/Misc/PowerCrystal.cs +++ b/Projects/UOContent/Items/Misc/PowerCrystal.cs @@ -1,38 +1,38 @@ -using Server.Network; - -namespace Server.Items -{ - public class PowerCrystal : Item - { - [Constructible] - public PowerCrystal() : base(0x1F1C) => Weight = 1.0; - - public PowerCrystal(Serial serial) : base(serial) - { - } - - public override string DefaultName => "power crystal"; - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 3)) - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - else - from.SendAsciiMessage("This looks like part of a larger contraption."); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using Server.Network; + +namespace Server.Items +{ + public class PowerCrystal : Item + { + [Constructible] + public PowerCrystal() : base(0x1F1C) => Weight = 1.0; + + public PowerCrystal(Serial serial) : base(serial) + { + } + + public override string DefaultName => "power crystal"; + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 3)) + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + else + from.SendAsciiMessage("This looks like part of a larger contraption."); + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/PowerGenerator.cs b/Projects/UOContent/Items/Misc/PowerGenerator.cs index 513e5a32d..1b562dfb9 100644 --- a/Projects/UOContent/Items/Misc/PowerGenerator.cs +++ b/Projects/UOContent/Items/Misc/PowerGenerator.cs @@ -1,534 +1,548 @@ -using System; -using System.Collections.Generic; -using Server.Gumps; -using Server.Network; - -namespace Server.Items -{ - public class PowerGenerator : BaseAddon - { - [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 PowerGenerator(Serial serial) : base(serial) - { - } - - public override bool ShareHue => false; - - private void AddGeneratorComponent(int itemID, int x, int y, int z) - { - AddonComponent 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); - - int version = reader.ReadEncodedInt(); - } - } - - public class ControlPanel : AddonComponent - { - private static readonly TimeSpan m_UseTimeout = TimeSpan.FromMinutes(2.0); - - private readonly HashSet m_DamageTable = new HashSet(); - private DateTime m_LastUse; - - private int m_SideLength; - - private Mobile m_User; - - public ControlPanel(int sideLength) : base(0xBDC) - { - Hue = 0x835; - - SideLength = sideLength; - } - - public ControlPanel(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int SideLength - { - get => m_SideLength; - set - { - 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 - - int totalNodes = SideLength * SideLength; - - Node[] stack = new Node[totalNodes]; - Node current = stack[0] = new Node(0, 0); - int stackSize = 1; - - bool[,] visited = new bool[SideLength, SideLength]; - visited[0, 0] = true; - - while (true) - { - PathDirection[] choices = new PathDirection[4]; - int 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) - { - PathDirection 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]; - } - } - - Path = new Node[stackSize]; - - for (int 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; - - if (m_User.Deleted || m_User.Map != Map || !m_User.InRange(this, 3) - || m_User.NetState == null || DateTime.UtcNow - m_LastUse >= m_UseTimeout) - { - m_User.CloseGump(); - } - else - { - from.SendMessage("Someone is currently using the control panel."); - return; - } - } - - m_User = from; - m_LastUse = DateTime.UtcNow; - - from.SendGump(new GameGump(this, from, 0, false)); - } - - public void DoDamage(Mobile to) - { - to.Send(new UnicodeMessage(Serial, ItemID, MessageType.Regular, 0x3B2, 3, "", "", - "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; - - DamageTimer 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 (int 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 (int i = 0; i < Path.Length; i++) - { - Node cur = Path[i]; - - writer.WriteEncodedInt(cur.X); - writer.WriteEncodedInt(cur.Y); - } - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_SideLength = reader.ReadEncodedInt(); - - Path = new Node[reader.ReadEncodedInt()]; - for (int 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; - - int 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 (int i = 0; i < sideLength; i++) - for (int j = 0; j < sideLength - 1; j++) - AddImage(120 + 40 * i, 162 + 40 * j, 0x13F9); - - for (int i = 0; i < sideLength - 1; i++) - for (int j = 0; j < sideLength; j++) - AddImage(138 + 40 * i, 147 + 40 * j, 0x13FD); - - Node[] path = panel.Path; - - NodeHue[,] hues = new NodeHue[sideLength, sideLength]; - - for (int i = 0; i <= step; i++) - { - Node n = path[i]; - hues[n.X, n.Y] = NodeHue.Blue; - } - - Node lastNode = path[^1]; - hues[lastNode.X, lastNode.Y] = NodeHue.Red; - - for (int i = 0; i < sideLength; i++) - for (int j = 0; j < sideLength; j++) - AddNode(110 + 40 * i, 135 + 40 * j, hues[i, j]); - - Node curNode = path[step]; - AddImage(118 + 40 * curNode.X, 143 + 40 * curNode.Y, 0x13A8); - - if (hint) - { - Node 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; - } - - Node nextNode = m_Panel.Path[m_Step + 1]; - - if (info.ButtonID == 5) // Attempt to Decipher - { - double lockpicking = m_From.Skills.Lockpicking.Value; - - if (lockpicking < 65.0) - 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 = DateTime.UtcNow; - } - else - { - m_Panel.DoDamage(m_From); - m_Panel.m_User = null; - } - } - else - { - Node 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 = DateTime.UtcNow; - } - } - else - { - m_Panel.DoDamage(m_From); - m_Panel.m_User = null; - } - } - } - - private enum NodeHue - { - Gray, - Blue, - Red - } - } - - private class DamageTimer : Timer - { - private readonly ControlPanel m_Panel; - private int m_Step; - private readonly Mobile m_To; - - public DamageTimer(ControlPanel panel, Mobile to) : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0)) - { - m_Panel = panel; - m_To = to; - m_Step = 0; - - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - 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(); - } - - private void End() - { - m_Panel.m_DamageTable.Remove(m_To); - m_To.Frozen = false; - - Stop(); - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Gumps; +using Server.Network; + +namespace Server.Items +{ + public class PowerGenerator : BaseAddon + { + [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 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(); + } + } + + public class ControlPanel : AddonComponent + { + private static readonly TimeSpan m_UseTimeout = TimeSpan.FromMinutes(2.0); + + private readonly HashSet m_DamageTable = new HashSet(); + private DateTime m_LastUse; + + private int m_SideLength; + + private Mobile m_User; + + public ControlPanel(int sideLength) : base(0xBDC) + { + Hue = 0x835; + + SideLength = sideLength; + } + + public ControlPanel(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int SideLength + { + get => m_SideLength; + set + { + 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]; + } + } + + Path = new Node[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; + + if (m_User.Deleted || m_User.Map != Map || !m_User.InRange(this, 3) + || m_User.NetState == null || DateTime.UtcNow - m_LastUse >= m_UseTimeout) + { + m_User.CloseGump(); + } + else + { + from.SendMessage("Someone is currently using the control panel."); + return; + } + } + + m_User = from; + m_LastUse = DateTime.UtcNow; + + from.SendGump(new GameGump(this, from, 0, false)); + } + + public void DoDamage(Mobile to) + { + to.Send( + new UnicodeMessage( + Serial, + ItemID, + MessageType.Regular, + 0x3B2, + 3, + "", + "", + "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 + }; + + 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) + 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 = DateTime.UtcNow; + } + else + { + m_Panel.DoDamage(m_From); + m_Panel.m_User = null; + } + } + 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 = DateTime.UtcNow; + } + } + else + { + m_Panel.DoDamage(m_From); + m_Panel.m_User = null; + } + } + } + + private enum NodeHue + { + Gray, + Blue, + Red + } + } + + 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; + + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + 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(); + } + + private void End() + { + m_Panel.m_DamageTable.Remove(m_To); + m_To.Frozen = false; + + Stop(); + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/Prism of Light/CrystallineFragments.cs b/Projects/UOContent/Items/Misc/Prism of Light/CrystallineFragments.cs index f7da229fe..6a8bf5091 100644 --- a/Projects/UOContent/Items/Misc/Prism of Light/CrystallineFragments.cs +++ b/Projects/UOContent/Items/Misc/Prism of Light/CrystallineFragments.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class CrystallineFragments : Item - { - [Constructible] - public CrystallineFragments() : base(0x223B) - { - LootType = LootType.Blessed; - Hue = 0x47E; - } - - public CrystallineFragments(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073160; // Crystalline Fragments - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class CrystallineFragments : Item + { + [Constructible] + public CrystallineFragments() : base(0x223B) + { + LootType = LootType.Blessed; + Hue = 0x47E; + } + + public CrystallineFragments(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073160; // Crystalline Fragments + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Prism of Light/IcyHeart.cs b/Projects/UOContent/Items/Misc/Prism of Light/IcyHeart.cs index c4ff08f6b..4a292ee7b 100644 --- a/Projects/UOContent/Items/Misc/Prism of Light/IcyHeart.cs +++ b/Projects/UOContent/Items/Misc/Prism of Light/IcyHeart.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class IcyHeart : Item - { - [Constructible] - public IcyHeart() : base(0x24B) - { - } - - public IcyHeart(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073162; // Icy Heart - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class IcyHeart : Item + { + [Constructible] + public IcyHeart() : base(0x24B) + { + } + + public IcyHeart(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073162; // Icy Heart + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Prism of Light/LuckyDagger.cs b/Projects/UOContent/Items/Misc/Prism of Light/LuckyDagger.cs index 26a4c2794..254c08aed 100644 --- a/Projects/UOContent/Items/Misc/Prism of Light/LuckyDagger.cs +++ b/Projects/UOContent/Items/Misc/Prism of Light/LuckyDagger.cs @@ -1,26 +1,26 @@ -namespace Server.Items -{ - public class LuckyDagger : Item - { - [Constructible] - public LuckyDagger() : base(0xF52) => Hue = 0x8A5; - - public LuckyDagger(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class LuckyDagger : Item + { + [Constructible] + public LuckyDagger() : base(0xF52) => Hue = 0x8A5; + + public LuckyDagger(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Prism of Light/ProtectorsEssence.cs b/Projects/UOContent/Items/Misc/Prism of Light/ProtectorsEssence.cs index 186b35516..d841d3520 100644 --- a/Projects/UOContent/Items/Misc/Prism of Light/ProtectorsEssence.cs +++ b/Projects/UOContent/Items/Misc/Prism of Light/ProtectorsEssence.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class ProtectorsEssence : Item - { - [Constructible] - public ProtectorsEssence() : base(0x23F) - { - } - - public ProtectorsEssence(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073159; // Protector's Essence - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class ProtectorsEssence : Item + { + [Constructible] + public ProtectorsEssence() : base(0x23F) + { + } + + public ProtectorsEssence(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073159; // Protector's Essence + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Prism of Light/ShimmeringCrystal.cs b/Projects/UOContent/Items/Misc/Prism of Light/ShimmeringCrystal.cs index 31f3604f8..cd42a14ed 100644 --- a/Projects/UOContent/Items/Misc/Prism of Light/ShimmeringCrystal.cs +++ b/Projects/UOContent/Items/Misc/Prism of Light/ShimmeringCrystal.cs @@ -1,39 +1,39 @@ -namespace Server.Items -{ - public class ShimmeringCrystals : Item - { - private static readonly int[] m_ItemIDs = - { - 0x2206, 0x2207, 0x2208, 0x2209, 0x220A, 0x220B, 0x220C, 0x220D, 0x220E, - 0x2210, 0x2211, 0x2212, 0x2213, 0x2214, 0x2215, 0x2216, 0x2217, 0x2218, - 0x221A, 0x221B, 0x221C, 0x221D, 0x221E, 0x221F, 0x2220, 0x2221, 0x2222, - 0x2224, 0x2225, 0x2226, 0x2227, 0x2228, 0x2229, 0x222A, 0x222B, 0x222C - }; - - [Constructible] - public ShimmeringCrystals() : base(m_ItemIDs.RandomElement()) - { - } - - public ShimmeringCrystals(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075095; // Shimmering Crystals - public override bool ForceShowProperties => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +namespace Server.Items +{ + public class ShimmeringCrystals : Item + { + private static readonly int[] m_ItemIDs = + { + 0x2206, 0x2207, 0x2208, 0x2209, 0x220A, 0x220B, 0x220C, 0x220D, 0x220E, + 0x2210, 0x2211, 0x2212, 0x2213, 0x2214, 0x2215, 0x2216, 0x2217, 0x2218, + 0x221A, 0x221B, 0x221C, 0x221D, 0x221E, 0x221F, 0x2220, 0x2221, 0x2222, + 0x2224, 0x2225, 0x2226, 0x2227, 0x2228, 0x2229, 0x222A, 0x222B, 0x222C + }; + + [Constructible] + public ShimmeringCrystals() : base(m_ItemIDs.RandomElement()) + { + } + + public ShimmeringCrystals(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075095; // Shimmering Crystals + public override bool ForceShowProperties => true; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/PromotionalToken.cs b/Projects/UOContent/Items/Misc/PromotionalToken.cs index 858b75ced..ee1ff943d 100644 --- a/Projects/UOContent/Items/Misc/PromotionalToken.cs +++ b/Projects/UOContent/Items/Misc/PromotionalToken.cs @@ -1,154 +1,163 @@ -using Server.Gumps; -using Server.Network; - -namespace Server.Items -{ - public abstract class PromotionalToken : Item - { - public abstract Item CreateItemFor(Mobile from); - - public abstract TextDefinition ItemName { get; } - public abstract TextDefinition ItemReceiveMessage { get; } - public abstract TextDefinition ItemGumpName { get; } - - public PromotionalToken() : base(0x2AAA) - { - LootType = LootType.Blessed; - Light = LightType.Circle300; - Weight = 5.0; - } - - public PromotionalToken(Serial serial) : base(serial) - { - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1070998, ItemName.ToString()); // Use this to redeem
your ~1_PROMO~ - } - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. - } - else - { - from.CloseGump(); - from.SendGump(new PromotionalTokenGump(this)); - } - } - - public override void OnRemoved(IEntity parent) - { - Mobile m = null; - - if (parent is Item item) - m = item.RootParent as Mobile; - else if (parent is Mobile mobile) - m = mobile; - - m?.CloseGump(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override int LabelNumber => 1070997; // A promotional token - - private class PromotionalTokenGump : Gump - { - private readonly PromotionalToken m_Token; - - public PromotionalTokenGump(PromotionalToken token) : base(10, 10) - { - m_Token = token; - - AddPage(0); - - AddBackground(0, 0, 240, 135, 0x2422); - AddHtmlLocalized(15, 15, 210, 75, 1070972, 0x0, true); // Click "OKAY" to redeem the following promotional item: - TextDefinition.AddHtmlText(this, 15, 60, 210, 75, m_Token.ItemGumpName, false, false); - - AddButton(160, 95, 0xF7, 0xF8, 1); // Okay - AddButton(90, 95, 0xF2, 0xF1, 0); // Cancel - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID != 1) - return; - - Mobile from = sender.Mobile; - - if (!m_Token.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. - } - else - { - Item i = m_Token.CreateItemFor(from); - - if (i != null) - { - from.BankBox.AddItem(i); - TextDefinition.SendMessageTo(from, m_Token.ItemReceiveMessage); - m_Token.Delete(); - } - } - } - } - } - - public class SoulstoneFragmentToken : PromotionalToken - { -public override Item CreateItemFor(Mobile from) - { - if (from?.Account != null) - return new SoulstoneFragment(from.Account.ToString()); - - return null; - } - - public override TextDefinition ItemGumpName => 1070999;//
Soulstone Fragment
- public override TextDefinition ItemName => 1071000;// soulstone fragment - public override TextDefinition ItemReceiveMessage => 1070976; // A soulstone fragment has been created in your bank box. - - [Constructible] - public SoulstoneFragmentToken() - { - } - - public SoulstoneFragmentToken(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} +using Server.Gumps; +using Server.Network; + +namespace Server.Items +{ + public abstract class PromotionalToken : Item + { + public PromotionalToken() : base(0x2AAA) + { + LootType = LootType.Blessed; + Light = LightType.Circle300; + Weight = 5.0; + } + + public PromotionalToken(Serial serial) : base(serial) + { + } + + public abstract TextDefinition ItemName { get; } + public abstract TextDefinition ItemReceiveMessage { get; } + public abstract TextDefinition ItemGumpName { get; } + + public override int LabelNumber => 1070997; // A promotional token + public abstract Item CreateItemFor(Mobile from); + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1070998, ItemName.ToString()); // Use this to redeem
your ~1_PROMO~ + } + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. + } + else + { + from.CloseGump(); + from.SendGump(new PromotionalTokenGump(this)); + } + } + + public override void OnRemoved(IEntity parent) + { + Mobile m = null; + + if (parent is Item item) + m = item.RootParent as Mobile; + else if (parent is Mobile mobile) + m = mobile; + + m?.CloseGump(); + } + + 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(); + } + + private class PromotionalTokenGump : Gump + { + private readonly PromotionalToken m_Token; + + public PromotionalTokenGump(PromotionalToken token) : base(10, 10) + { + m_Token = token; + + AddPage(0); + + AddBackground(0, 0, 240, 135, 0x2422); + AddHtmlLocalized( + 15, + 15, + 210, + 75, + 1070972, + 0x0, + true + ); // Click "OKAY" to redeem the following promotional item: + TextDefinition.AddHtmlText(this, 15, 60, 210, 75, m_Token.ItemGumpName, false, false); + + AddButton(160, 95, 0xF7, 0xF8, 1); // Okay + AddButton(90, 95, 0xF2, 0xF1, 0); // Cancel + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID != 1) + return; + + var from = sender.Mobile; + + if (!m_Token.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. + } + else + { + var i = m_Token.CreateItemFor(from); + + if (i != null) + { + from.BankBox.AddItem(i); + TextDefinition.SendMessageTo(from, m_Token.ItemReceiveMessage); + m_Token.Delete(); + } + } + } + } + } + + public class SoulstoneFragmentToken : PromotionalToken + { + [Constructible] + public SoulstoneFragmentToken() + { + } + + public SoulstoneFragmentToken(Serial serial) : base(serial) + { + } + + public override TextDefinition ItemGumpName => 1070999; //
Soulstone Fragment
+ public override TextDefinition ItemName => 1071000; // soulstone fragment + + public override TextDefinition ItemReceiveMessage => + 1070976; // A soulstone fragment has been created in your bank box. + + public override Item CreateItemFor(Mobile from) + { + if (from?.Account != null) + return new SoulstoneFragment(from.Account.ToString()); + + return null; + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/PublicMoongate.cs b/Projects/UOContent/Items/Misc/PublicMoongate.cs index 7ddb7c86b..cc95fa4fe 100644 --- a/Projects/UOContent/Items/Misc/PublicMoongate.cs +++ b/Projects/UOContent/Items/Misc/PublicMoongate.cs @@ -1,420 +1,445 @@ -using System; -using System.Collections.Generic; -using Server.Factions; -using Server.Gumps; -using Server.Mobiles; -using Server.Network; -using Server.Spells; - -namespace Server.Items -{ - public class PublicMoongate : Item - { - [Constructible] - public PublicMoongate() : base(0xF6C) - { - Movable = false; - Light = LightType.Circle300; - } - - public PublicMoongate(Serial serial) : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public override bool HandlesOnMovement => true; - - public override void OnDoubleClick(Mobile from) - { - if (!from.Player) - return; - - if (from.InRange(GetWorldLocation(), 1)) - UseGate(from); - else - from.SendLocalizedMessage(500446); // That is too far away. - } - - public override bool OnMoveOver(Mobile m) - { - // Changed so criminals are not blocked by it. - if (m.Player) - UseGate(m); - - return true; - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (m is PlayerMobile) - if (!Utility.InRange(m.Location, Location, 1) && Utility.InRange(oldLocation, Location, 1)) - m.CloseGump(); - } - - public bool UseGate(Mobile m) - { - if (m.Criminal) - { - m.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily. - return false; - } - - if (SpellHelper.CheckCombat(m)) - { - m.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle?? - return false; - } - - if (m.Spell != null) - { - m.SendLocalizedMessage(1049616); // You are too busy to do that at the moment. - return false; - } - - m.CloseGump(); - m.SendGump(new MoongateGump(m, this)); - - if (!m.Hidden || m.AccessLevel == AccessLevel.Player) - Effects.PlaySound(m.Location, m.Map, 0x20E); - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public static void Initialize() - { - CommandSystem.Register("MoonGen", AccessLevel.Administrator, MoonGen_OnCommand); - } - - [Usage("MoonGen")] - [Description("Generates public moongates. Removes all old moongates.")] - public static void MoonGen_OnCommand(CommandEventArgs e) - { - DeleteAll(); - - int count = 0; - - count += MoonGen(PMList.Trammel); - count += MoonGen(PMList.Felucca); - count += MoonGen(PMList.Ilshenar); - count += MoonGen(PMList.Malas); - count += MoonGen(PMList.Tokuno); - - World.Broadcast(0x35, true, "{0} moongates generated.", count); - } - - private static void DeleteAll() - { - List list = new List(); - - foreach (Item item in World.Items.Values) - if (item is PublicMoongate) - list.Add(item); - - foreach (Item item in list) - item.Delete(); - - if (list.Count > 0) - World.Broadcast(0x35, true, "{0} moongates removed.", list.Count); - } - - private static int MoonGen(PMList list) - { - foreach (PMEntry entry in list.Entries) - { - Item item = new PublicMoongate(); - - item.MoveToWorld(entry.Location, list.Map); - - if (entry.Number == 1060642) // Umbra - item.Hue = 0x497; - } - - return list.Entries.Length; - } - } - - public class PMEntry - { - public PMEntry(Point3D loc, int number) - { - Location = loc; - Number = number; - } - - public Point3D Location { get; } - - public int Number { get; } - } - - public class PMList - { - public static readonly PMList Trammel = - new PMList(1012000, 1012012, Map.Trammel, new[] - { - new PMEntry(new Point3D(4467, 1283, 5), 1012003), // Moonglow - new PMEntry(new Point3D(1336, 1997, 5), 1012004), // Britain - new PMEntry(new Point3D(1499, 3771, 5), 1012005), // Jhelom - new PMEntry(new Point3D(771, 752, 5), 1012006), // Yew - new PMEntry(new Point3D(2701, 692, 5), 1012007), // Minoc - new PMEntry(new Point3D(1828, 2948, -20), 1012008), // Trinsic - new PMEntry(new Point3D(643, 2067, 5), 1012009), // Skara Brae - /* Dynamic Z for Magincia to support both old and new maps. */ - new PMEntry(new Point3D(3563, 2139, Map.Trammel.GetAverageZ(3563, 2139)), 1012010), // (New) Magincia - new PMEntry(new Point3D(3450, 2677, 25), 1078098) // New Haven - }); - - public static readonly PMList Felucca = - new PMList(1012001, 1012013, Map.Felucca, new[] - { - new PMEntry(new Point3D(4467, 1283, 5), 1012003), // Moonglow - new PMEntry(new Point3D(1336, 1997, 5), 1012004), // Britain - new PMEntry(new Point3D(1499, 3771, 5), 1012005), // Jhelom - new PMEntry(new Point3D(771, 752, 5), 1012006), // Yew - new PMEntry(new Point3D(2701, 692, 5), 1012007), // Minoc - new PMEntry(new Point3D(1828, 2948, -20), 1012008), // Trinsic - new PMEntry(new Point3D(643, 2067, 5), 1012009), // Skara Brae - /* Dynamic Z for Magincia to support both old and new maps. */ - new PMEntry(new Point3D(3563, 2139, Map.Felucca.GetAverageZ(3563, 2139)), 1012010), // (New) Magincia - new PMEntry(new Point3D(2711, 2234, 0), 1019001) // Buccaneer's Den - }); - - public static readonly PMList Ilshenar = - new PMList(1012002, 1012014, Map.Ilshenar, new[] - { - new PMEntry(new Point3D(1215, 467, -13), 1012015), // Compassion - new PMEntry(new Point3D(722, 1366, -60), 1012016), // Honesty - new PMEntry(new Point3D(744, 724, -28), 1012017), // Honor - new PMEntry(new Point3D(281, 1016, 0), 1012018), // Humility - new PMEntry(new Point3D(987, 1011, -32), 1012019), // Justice - new PMEntry(new Point3D(1174, 1286, -30), 1012020), // Sacrifice - new PMEntry(new Point3D(1532, 1340, -3), 1012021), // Spirituality - new PMEntry(new Point3D(528, 216, -45), 1012022), // Valor - new PMEntry(new Point3D(1721, 218, 96), 1019000) // Chaos - }); - - public static readonly PMList Malas = - new PMList(1060643, 1062039, Map.Malas, new[] - { - new PMEntry(new Point3D(1015, 527, -65), 1060641), // Luna - new PMEntry(new Point3D(1997, 1386, -85), 1060642) // Umbra - }); - - public static readonly PMList Tokuno = - new PMList(1063258, 1063415, Map.Tokuno, new[] - { - new PMEntry(new Point3D(1169, 998, 41), 1063412), // Isamu-Jima - new PMEntry(new Point3D(802, 1204, 25), 1063413), // Makoto-Jima - new PMEntry(new Point3D(270, 628, 15), 1063414) // Homare-Jima - }); - - public static readonly PMList[] UORLists = { Trammel, Felucca }; - public static readonly PMList[] UORListsYoung = { Trammel }; - public static readonly PMList[] LBRLists = { Trammel, Felucca, Ilshenar }; - public static readonly PMList[] LBRListsYoung = { Trammel, Ilshenar }; - public static readonly PMList[] AOSLists = { Trammel, Felucca, Ilshenar, Malas }; - public static readonly PMList[] AOSListsYoung = { Trammel, Ilshenar, Malas }; - public static readonly PMList[] SELists = { Trammel, Felucca, Ilshenar, Malas, Tokuno }; - public static readonly PMList[] SEListsYoung = { Trammel, Ilshenar, Malas, Tokuno }; - public static readonly PMList[] RedLists = { Felucca }; - public static readonly PMList[] SigilLists = { Felucca }; - - public PMList(int number, int selNumber, Map map, PMEntry[] entries) - { - Number = number; - SelNumber = selNumber; - Map = map; - Entries = entries; - } - - public int Number { get; } - - public int SelNumber { get; } - - public Map Map { get; } - - public PMEntry[] Entries { get; } - } - - public class MoongateGump : Gump - { - private readonly PMList[] m_Lists; - private readonly Mobile m_Mobile; - private readonly Item m_Moongate; - - public MoongateGump(Mobile mobile, Item moongate) : base(100, 100) - { - m_Mobile = mobile; - m_Moongate = moongate; - - PMList[] checkLists; - - if (mobile.Player) - { - if (Sigil.ExistsOn(mobile)) - { - checkLists = PMList.SigilLists; - } - else if (mobile.Kills >= 5) - { - checkLists = PMList.RedLists; - } - else - { - ClientFlags flags = mobile.NetState?.Flags ?? ClientFlags.None; - bool young = mobile is PlayerMobile playerMobile && playerMobile.Young; - - if (Core.SE && (flags & ClientFlags.Tokuno) != 0) - checkLists = young ? PMList.SEListsYoung : PMList.SELists; - else if (Core.AOS && (flags & ClientFlags.Malas) != 0) - checkLists = young ? PMList.AOSListsYoung : PMList.AOSLists; - else if ((flags & ClientFlags.Ilshenar) != 0) - checkLists = young ? PMList.LBRListsYoung : PMList.LBRLists; - else - checkLists = young ? PMList.UORListsYoung : PMList.UORLists; - } - } - else - { - checkLists = PMList.SELists; - } - - m_Lists = new PMList[checkLists.Length]; - - for (int i = 0; i < m_Lists.Length; ++i) - m_Lists[i] = checkLists[i]; - - for (int i = 0; i < m_Lists.Length; ++i) - if (m_Lists[i].Map == mobile.Map) - { - PMList temp = m_Lists[i]; - - m_Lists[i] = m_Lists[0]; - m_Lists[0] = temp; - - break; - } - - AddPage(0); - - AddBackground(0, 0, 380, 280, 5054); - - AddButton(10, 210, 4005, 4007, 1); - AddHtmlLocalized(45, 210, 140, 25, 1011036); // OKAY - - AddButton(10, 235, 4005, 4007, 0); - AddHtmlLocalized(45, 235, 140, 25, 1011012); // CANCEL - - AddHtmlLocalized(5, 5, 200, 20, 1012011); // Pick your destination: - - for (int i = 0; i < checkLists.Length; ++i) - { - AddButton(10, 35 + i * 25, 2117, 2118, 0, GumpButtonType.Page, Array.IndexOf(m_Lists, checkLists[i]) + 1); - AddHtmlLocalized(30, 35 + i * 25, 150, 20, checkLists[i].Number); - } - - for (int i = 0; i < m_Lists.Length; ++i) - RenderPage(i, Array.IndexOf(checkLists, m_Lists[i])); - } - - private void RenderPage(int index, int offset) - { - PMList list = m_Lists[index]; - - AddPage(index + 1); - - AddButton(10, 35 + offset * 25, 2117, 2118, 0, GumpButtonType.Page, index + 1); - AddHtmlLocalized(30, 35 + offset * 25, 150, 20, list.SelNumber); - - PMEntry[] entries = list.Entries; - - for (int i = 0; i < entries.Length; ++i) - { - AddRadio(200, 35 + i * 25, 210, 211, false, index * 100 + i); - AddHtmlLocalized(225, 35 + i * 25, 150, 20, entries[i].Number); - } - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (info.ButtonID == 0) // Cancel - return; - if (m_Mobile.Deleted || m_Moongate.Deleted || m_Mobile.Map == null) - return; - - int[] switches = info.Switches; - - if (switches.Length == 0) - return; - - int switchID = switches[0]; - int listIndex = switchID / 100; - int listEntry = switchID % 100; - - if (listIndex < 0 || listIndex >= m_Lists.Length) - return; - - PMList list = m_Lists[listIndex]; - - if (listEntry < 0 || listEntry >= list.Entries.Length) - return; - - PMEntry entry = list.Entries[listEntry]; - - if (!m_Mobile.InRange(m_Moongate.GetWorldLocation(), 1) || m_Mobile.Map != m_Moongate.Map) - { - m_Mobile.SendLocalizedMessage(1019002); // You are too far away to use the gate. - } - else if (m_Mobile.Player && m_Mobile.Kills >= 5 && list.Map != Map.Felucca) - { - m_Mobile.SendLocalizedMessage(1019004); // You are not allowed to travel there. - } - else if (Sigil.ExistsOn(m_Mobile) && list.Map != Faction.Facet) - { - m_Mobile.SendLocalizedMessage(1019004); // You are not allowed to travel there. - } - else if (m_Mobile.Criminal) - { - m_Mobile.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily. - } - else if (SpellHelper.CheckCombat(m_Mobile)) - { - m_Mobile.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle?? - } - else if (m_Mobile.Spell != null) - { - m_Mobile.SendLocalizedMessage(1049616); // You are too busy to do that at the moment. - } - else if (m_Mobile.Map == list.Map && m_Mobile.InRange(entry.Location, 1)) - { - m_Mobile.SendLocalizedMessage(1019003); // You are already there. - } - else - { - BaseCreature.TeleportPets(m_Mobile, entry.Location, list.Map); - - m_Mobile.Combatant = null; - m_Mobile.Warmode = false; - m_Mobile.Hidden = true; - - m_Mobile.MoveToWorld(entry.Location, list.Map); - - Effects.PlaySound(entry.Location, list.Map, 0x1FE); - } - } - } -} +using System; +using System.Collections.Generic; +using Server.Factions; +using Server.Gumps; +using Server.Mobiles; +using Server.Network; +using Server.Spells; + +namespace Server.Items +{ + public class PublicMoongate : Item + { + [Constructible] + public PublicMoongate() : base(0xF6C) + { + Movable = false; + Light = LightType.Circle300; + } + + public PublicMoongate(Serial serial) : base(serial) + { + } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + public override bool HandlesOnMovement => true; + + public override void OnDoubleClick(Mobile from) + { + if (!from.Player) + return; + + if (from.InRange(GetWorldLocation(), 1)) + UseGate(from); + else + from.SendLocalizedMessage(500446); // That is too far away. + } + + public override bool OnMoveOver(Mobile m) + { + // Changed so criminals are not blocked by it. + if (m.Player) + UseGate(m); + + return true; + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (m is PlayerMobile) + if (!Utility.InRange(m.Location, Location, 1) && Utility.InRange(oldLocation, Location, 1)) + m.CloseGump(); + } + + public bool UseGate(Mobile m) + { + if (m.Criminal) + { + m.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily. + return false; + } + + if (SpellHelper.CheckCombat(m)) + { + m.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle?? + return false; + } + + if (m.Spell != null) + { + m.SendLocalizedMessage(1049616); // You are too busy to do that at the moment. + return false; + } + + m.CloseGump(); + m.SendGump(new MoongateGump(m, this)); + + if (!m.Hidden || m.AccessLevel == AccessLevel.Player) + Effects.PlaySound(m.Location, m.Map, 0x20E); + + return true; + } + + 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 static void Initialize() + { + CommandSystem.Register("MoonGen", AccessLevel.Administrator, MoonGen_OnCommand); + } + + [Usage("MoonGen")] + [Description("Generates public moongates. Removes all old moongates.")] + public static void MoonGen_OnCommand(CommandEventArgs e) + { + DeleteAll(); + + var count = 0; + + count += MoonGen(PMList.Trammel); + count += MoonGen(PMList.Felucca); + count += MoonGen(PMList.Ilshenar); + count += MoonGen(PMList.Malas); + count += MoonGen(PMList.Tokuno); + + World.Broadcast(0x35, true, "{0} moongates generated.", count); + } + + private static void DeleteAll() + { + var list = new List(); + + foreach (var item in World.Items.Values) + if (item is PublicMoongate) + list.Add(item); + + foreach (var item in list) + item.Delete(); + + if (list.Count > 0) + World.Broadcast(0x35, true, "{0} moongates removed.", list.Count); + } + + private static int MoonGen(PMList list) + { + foreach (var entry in list.Entries) + { + Item item = new PublicMoongate(); + + item.MoveToWorld(entry.Location, list.Map); + + if (entry.Number == 1060642) // Umbra + item.Hue = 0x497; + } + + return list.Entries.Length; + } + } + + public class PMEntry + { + public PMEntry(Point3D loc, int number) + { + Location = loc; + Number = number; + } + + public Point3D Location { get; } + + public int Number { get; } + } + + public class PMList + { + public static readonly PMList Trammel = + new PMList( + 1012000, + 1012012, + Map.Trammel, + new[] + { + new PMEntry(new Point3D(4467, 1283, 5), 1012003), // Moonglow + new PMEntry(new Point3D(1336, 1997, 5), 1012004), // Britain + new PMEntry(new Point3D(1499, 3771, 5), 1012005), // Jhelom + new PMEntry(new Point3D(771, 752, 5), 1012006), // Yew + new PMEntry(new Point3D(2701, 692, 5), 1012007), // Minoc + new PMEntry(new Point3D(1828, 2948, -20), 1012008), // Trinsic + new PMEntry(new Point3D(643, 2067, 5), 1012009), // Skara Brae + /* Dynamic Z for Magincia to support both old and new maps. */ + new PMEntry(new Point3D(3563, 2139, Map.Trammel.GetAverageZ(3563, 2139)), 1012010), // (New) Magincia + new PMEntry(new Point3D(3450, 2677, 25), 1078098) // New Haven + } + ); + + public static readonly PMList Felucca = + new PMList( + 1012001, + 1012013, + Map.Felucca, + new[] + { + new PMEntry(new Point3D(4467, 1283, 5), 1012003), // Moonglow + new PMEntry(new Point3D(1336, 1997, 5), 1012004), // Britain + new PMEntry(new Point3D(1499, 3771, 5), 1012005), // Jhelom + new PMEntry(new Point3D(771, 752, 5), 1012006), // Yew + new PMEntry(new Point3D(2701, 692, 5), 1012007), // Minoc + new PMEntry(new Point3D(1828, 2948, -20), 1012008), // Trinsic + new PMEntry(new Point3D(643, 2067, 5), 1012009), // Skara Brae + /* Dynamic Z for Magincia to support both old and new maps. */ + new PMEntry(new Point3D(3563, 2139, Map.Felucca.GetAverageZ(3563, 2139)), 1012010), // (New) Magincia + new PMEntry(new Point3D(2711, 2234, 0), 1019001) // Buccaneer's Den + } + ); + + public static readonly PMList Ilshenar = + new PMList( + 1012002, + 1012014, + Map.Ilshenar, + new[] + { + new PMEntry(new Point3D(1215, 467, -13), 1012015), // Compassion + new PMEntry(new Point3D(722, 1366, -60), 1012016), // Honesty + new PMEntry(new Point3D(744, 724, -28), 1012017), // Honor + new PMEntry(new Point3D(281, 1016, 0), 1012018), // Humility + new PMEntry(new Point3D(987, 1011, -32), 1012019), // Justice + new PMEntry(new Point3D(1174, 1286, -30), 1012020), // Sacrifice + new PMEntry(new Point3D(1532, 1340, -3), 1012021), // Spirituality + new PMEntry(new Point3D(528, 216, -45), 1012022), // Valor + new PMEntry(new Point3D(1721, 218, 96), 1019000) // Chaos + } + ); + + public static readonly PMList Malas = + new PMList( + 1060643, + 1062039, + Map.Malas, + new[] + { + new PMEntry(new Point3D(1015, 527, -65), 1060641), // Luna + new PMEntry(new Point3D(1997, 1386, -85), 1060642) // Umbra + } + ); + + public static readonly PMList Tokuno = + new PMList( + 1063258, + 1063415, + Map.Tokuno, + new[] + { + new PMEntry(new Point3D(1169, 998, 41), 1063412), // Isamu-Jima + new PMEntry(new Point3D(802, 1204, 25), 1063413), // Makoto-Jima + new PMEntry(new Point3D(270, 628, 15), 1063414) // Homare-Jima + } + ); + + public static readonly PMList[] UORLists = { Trammel, Felucca }; + public static readonly PMList[] UORListsYoung = { Trammel }; + public static readonly PMList[] LBRLists = { Trammel, Felucca, Ilshenar }; + public static readonly PMList[] LBRListsYoung = { Trammel, Ilshenar }; + public static readonly PMList[] AOSLists = { Trammel, Felucca, Ilshenar, Malas }; + public static readonly PMList[] AOSListsYoung = { Trammel, Ilshenar, Malas }; + public static readonly PMList[] SELists = { Trammel, Felucca, Ilshenar, Malas, Tokuno }; + public static readonly PMList[] SEListsYoung = { Trammel, Ilshenar, Malas, Tokuno }; + public static readonly PMList[] RedLists = { Felucca }; + public static readonly PMList[] SigilLists = { Felucca }; + + public PMList(int number, int selNumber, Map map, PMEntry[] entries) + { + Number = number; + SelNumber = selNumber; + Map = map; + Entries = entries; + } + + public int Number { get; } + + public int SelNumber { get; } + + public Map Map { get; } + + public PMEntry[] Entries { get; } + } + + public class MoongateGump : Gump + { + private readonly PMList[] m_Lists; + private readonly Mobile m_Mobile; + private readonly Item m_Moongate; + + public MoongateGump(Mobile mobile, Item moongate) : base(100, 100) + { + m_Mobile = mobile; + m_Moongate = moongate; + + PMList[] checkLists; + + if (mobile.Player) + { + if (Sigil.ExistsOn(mobile)) + { + checkLists = PMList.SigilLists; + } + else if (mobile.Kills >= 5) + { + checkLists = PMList.RedLists; + } + else + { + var flags = mobile.NetState?.Flags ?? ClientFlags.None; + var young = mobile is PlayerMobile playerMobile && playerMobile.Young; + + if (Core.SE && (flags & ClientFlags.Tokuno) != 0) + checkLists = young ? PMList.SEListsYoung : PMList.SELists; + else if (Core.AOS && (flags & ClientFlags.Malas) != 0) + checkLists = young ? PMList.AOSListsYoung : PMList.AOSLists; + else if ((flags & ClientFlags.Ilshenar) != 0) + checkLists = young ? PMList.LBRListsYoung : PMList.LBRLists; + else + checkLists = young ? PMList.UORListsYoung : PMList.UORLists; + } + } + else + { + checkLists = PMList.SELists; + } + + m_Lists = new PMList[checkLists.Length]; + + for (var i = 0; i < m_Lists.Length; ++i) + m_Lists[i] = checkLists[i]; + + for (var i = 0; i < m_Lists.Length; ++i) + if (m_Lists[i].Map == mobile.Map) + { + var temp = m_Lists[i]; + + m_Lists[i] = m_Lists[0]; + m_Lists[0] = temp; + + break; + } + + AddPage(0); + + AddBackground(0, 0, 380, 280, 5054); + + AddButton(10, 210, 4005, 4007, 1); + AddHtmlLocalized(45, 210, 140, 25, 1011036); // OKAY + + AddButton(10, 235, 4005, 4007, 0); + AddHtmlLocalized(45, 235, 140, 25, 1011012); // CANCEL + + AddHtmlLocalized(5, 5, 200, 20, 1012011); // Pick your destination: + + for (var i = 0; i < checkLists.Length; ++i) + { + AddButton(10, 35 + i * 25, 2117, 2118, 0, GumpButtonType.Page, Array.IndexOf(m_Lists, checkLists[i]) + 1); + AddHtmlLocalized(30, 35 + i * 25, 150, 20, checkLists[i].Number); + } + + for (var i = 0; i < m_Lists.Length; ++i) + RenderPage(i, Array.IndexOf(checkLists, m_Lists[i])); + } + + private void RenderPage(int index, int offset) + { + var list = m_Lists[index]; + + AddPage(index + 1); + + AddButton(10, 35 + offset * 25, 2117, 2118, 0, GumpButtonType.Page, index + 1); + AddHtmlLocalized(30, 35 + offset * 25, 150, 20, list.SelNumber); + + var entries = list.Entries; + + for (var i = 0; i < entries.Length; ++i) + { + AddRadio(200, 35 + i * 25, 210, 211, false, index * 100 + i); + AddHtmlLocalized(225, 35 + i * 25, 150, 20, entries[i].Number); + } + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (info.ButtonID == 0) // Cancel + return; + if (m_Mobile.Deleted || m_Moongate.Deleted || m_Mobile.Map == null) + return; + + var switches = info.Switches; + + if (switches.Length == 0) + return; + + var switchID = switches[0]; + var listIndex = switchID / 100; + var listEntry = switchID % 100; + + if (listIndex < 0 || listIndex >= m_Lists.Length) + return; + + var list = m_Lists[listIndex]; + + if (listEntry < 0 || listEntry >= list.Entries.Length) + return; + + var entry = list.Entries[listEntry]; + + if (!m_Mobile.InRange(m_Moongate.GetWorldLocation(), 1) || m_Mobile.Map != m_Moongate.Map) + { + m_Mobile.SendLocalizedMessage(1019002); // You are too far away to use the gate. + } + else if (m_Mobile.Player && m_Mobile.Kills >= 5 && list.Map != Map.Felucca) + { + m_Mobile.SendLocalizedMessage(1019004); // You are not allowed to travel there. + } + else if (Sigil.ExistsOn(m_Mobile) && list.Map != Faction.Facet) + { + m_Mobile.SendLocalizedMessage(1019004); // You are not allowed to travel there. + } + else if (m_Mobile.Criminal) + { + m_Mobile.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily. + } + else if (SpellHelper.CheckCombat(m_Mobile)) + { + m_Mobile.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle?? + } + else if (m_Mobile.Spell != null) + { + m_Mobile.SendLocalizedMessage(1049616); // You are too busy to do that at the moment. + } + else if (m_Mobile.Map == list.Map && m_Mobile.InRange(entry.Location, 1)) + { + m_Mobile.SendLocalizedMessage(1019003); // You are already there. + } + else + { + BaseCreature.TeleportPets(m_Mobile, entry.Location, list.Map); + + m_Mobile.Combatant = null; + m_Mobile.Warmode = false; + m_Mobile.Hidden = true; + + m_Mobile.MoveToWorld(entry.Location, list.Map); + + Effects.PlaySound(entry.Location, list.Map, 0x1FE); + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/Rares.cs b/Projects/UOContent/Items/Misc/Rares.cs index 16fddbffd..a9a970ad6 100644 --- a/Projects/UOContent/Items/Misc/Rares.cs +++ b/Projects/UOContent/Items/Misc/Rares.cs @@ -1,611 +1,611 @@ -namespace Server.Items -{ - public class Rope : Item - { - [Constructible] - public Rope(int amount = 1) : base(0x14F8) - { - Stackable = true; - Weight = 1.0; - Amount = amount; - } - - public Rope(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class IronWire : Item - { - [Constructible] - public IronWire(int amount = 1) : base(0x1876) - { - Stackable = true; - Weight = 5.0; - Amount = amount; - } - - public IronWire(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1 && Weight == 2.0) - Weight = 5.0; - } - } - - public class SilverWire : Item - { - [Constructible] - public SilverWire(int amount = 1) : base(0x1877) - { - Stackable = true; - Weight = 5.0; - Amount = amount; - } - - public SilverWire(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1 && Weight == 2.0) - Weight = 5.0; - } - } - - public class GoldWire : Item - { - [Constructible] - public GoldWire(int amount = 1) : base(0x1878) - { - Stackable = true; - Weight = 5.0; - Amount = amount; - } - - public GoldWire(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1 && Weight == 2.0) - Weight = 5.0; - } - } - - public class CopperWire : Item - { - [Constructible] - public CopperWire(int amount = 1) : base(0x1879) - { - Stackable = true; - Weight = 5.0; - Amount = amount; - } - - public CopperWire(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1 && Weight == 2.0) - Weight = 5.0; - } - } - - public class WhiteDriedFlowers : Item - { - [Constructible] - public WhiteDriedFlowers(int amount = 1) : base(0xC3C) - { - Stackable = true; - Weight = 1.0; - Amount = amount; - } - - public WhiteDriedFlowers(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GreenDriedFlowers : Item - { - [Constructible] - public GreenDriedFlowers(int amount = 1) : base(0xC3E) - { - Stackable = true; - Weight = 1.0; - Amount = amount; - } - - public GreenDriedFlowers(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DriedOnions : Item - { - [Constructible] - public DriedOnions(int amount = 1) : base(0xC40) - { - Stackable = true; - Weight = 1.0; - Amount = amount; - } - - public DriedOnions(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DriedHerbs : Item - { - [Constructible] - public DriedHerbs(int amount = 1) : base(0xC42) - { - Stackable = true; - Weight = 1.0; - Amount = amount; - } - - public DriedHerbs(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class HorseShoes : Item - { - [Constructible] - public HorseShoes() : base(0xFB6) => Weight = 3.0; - - public HorseShoes(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class ForgedMetal : Item - { - [Constructible] - public ForgedMetal() : base(0xFB8) => Weight = 5.0; - - public ForgedMetal(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Whip : Item - { - [Constructible] - public Whip() : base(0x166E) => Weight = 1.0; - - public Whip(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PaintsAndBrush : Item - { - [Constructible] - public PaintsAndBrush() : base(0xFC1) => Weight = 1.0; - - public PaintsAndBrush(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PenAndInk : Item - { - [Constructible] - public PenAndInk() : base(0xFBF) => Weight = 1.0; - - public PenAndInk(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class ChiselsNorth : Item - { - [Constructible] - public ChiselsNorth() : base(0x1026) => Weight = 1.0; - - public ChiselsNorth(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ChiselsWest : Item - { - [Constructible] - public ChiselsWest() : base(0x1027) => Weight = 1.0; - - public ChiselsWest(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class DirtyPan : Item - { - [Constructible] - public DirtyPan() : base(0x9E8) => Weight = 1.0; - - public DirtyPan(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class DirtySmallRoundPot : Item - { - [Constructible] - public DirtySmallRoundPot() : base(0x9E7) => Weight = 1.0; - - public DirtySmallRoundPot(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class DirtyPot : Item - { - [Constructible] - public DirtyPot() : base(0x9E6) => Weight = 1.0; - - public DirtyPot(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class DirtyRoundPot : Item - { - [Constructible] - public DirtyRoundPot() : base(0x9DF) => Weight = 1.0; - - public DirtyRoundPot(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class DirtyFrypan : Item - { - [Constructible] - public DirtyFrypan() : base(0x9DE) => Weight = 1.0; - - public DirtyFrypan(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class DirtySmallPot : Item - { - [Constructible] - public DirtySmallPot() : base(0x9DD) => Weight = 1.0; - - public DirtySmallPot(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class DirtyKettle : Item - { - [Constructible] - public DirtyKettle() : base(0x9DC) => Weight = 1.0; - - public DirtyKettle(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} +namespace Server.Items +{ + public class Rope : Item + { + [Constructible] + public Rope(int amount = 1) : base(0x14F8) + { + Stackable = true; + Weight = 1.0; + Amount = amount; + } + + public Rope(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class IronWire : Item + { + [Constructible] + public IronWire(int amount = 1) : base(0x1876) + { + Stackable = true; + Weight = 5.0; + Amount = amount; + } + + public IronWire(Serial serial) : base(serial) + { + } + + 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 (version < 1 && Weight == 2.0) + Weight = 5.0; + } + } + + public class SilverWire : Item + { + [Constructible] + public SilverWire(int amount = 1) : base(0x1877) + { + Stackable = true; + Weight = 5.0; + Amount = amount; + } + + public SilverWire(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version < 1 && Weight == 2.0) + Weight = 5.0; + } + } + + public class GoldWire : Item + { + [Constructible] + public GoldWire(int amount = 1) : base(0x1878) + { + Stackable = true; + Weight = 5.0; + Amount = amount; + } + + public GoldWire(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version < 1 && Weight == 2.0) + Weight = 5.0; + } + } + + public class CopperWire : Item + { + [Constructible] + public CopperWire(int amount = 1) : base(0x1879) + { + Stackable = true; + Weight = 5.0; + Amount = amount; + } + + public CopperWire(Serial serial) : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version < 1 && Weight == 2.0) + Weight = 5.0; + } + } + + public class WhiteDriedFlowers : Item + { + [Constructible] + public WhiteDriedFlowers(int amount = 1) : base(0xC3C) + { + Stackable = true; + Weight = 1.0; + Amount = amount; + } + + public WhiteDriedFlowers(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class GreenDriedFlowers : Item + { + [Constructible] + public GreenDriedFlowers(int amount = 1) : base(0xC3E) + { + Stackable = true; + Weight = 1.0; + Amount = amount; + } + + public GreenDriedFlowers(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class DriedOnions : Item + { + [Constructible] + public DriedOnions(int amount = 1) : base(0xC40) + { + Stackable = true; + Weight = 1.0; + Amount = amount; + } + + public DriedOnions(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class DriedHerbs : Item + { + [Constructible] + public DriedHerbs(int amount = 1) : base(0xC42) + { + Stackable = true; + Weight = 1.0; + Amount = amount; + } + + public DriedHerbs(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class HorseShoes : Item + { + [Constructible] + public HorseShoes() : base(0xFB6) => Weight = 3.0; + + public HorseShoes(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class ForgedMetal : Item + { + [Constructible] + public ForgedMetal() : base(0xFB8) => Weight = 5.0; + + public ForgedMetal(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class Whip : Item + { + [Constructible] + public Whip() : base(0x166E) => Weight = 1.0; + + public Whip(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class PaintsAndBrush : Item + { + [Constructible] + public PaintsAndBrush() : base(0xFC1) => Weight = 1.0; + + public PaintsAndBrush(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class PenAndInk : Item + { + [Constructible] + public PenAndInk() : base(0xFBF) => Weight = 1.0; + + public PenAndInk(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class ChiselsNorth : Item + { + [Constructible] + public ChiselsNorth() : base(0x1026) => Weight = 1.0; + + public ChiselsNorth(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class ChiselsWest : Item + { + [Constructible] + public ChiselsWest() : base(0x1027) => Weight = 1.0; + + public ChiselsWest(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class DirtyPan : Item + { + [Constructible] + public DirtyPan() : base(0x9E8) => Weight = 1.0; + + public DirtyPan(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class DirtySmallRoundPot : Item + { + [Constructible] + public DirtySmallRoundPot() : base(0x9E7) => Weight = 1.0; + + public DirtySmallRoundPot(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class DirtyPot : Item + { + [Constructible] + public DirtyPot() : base(0x9E6) => Weight = 1.0; + + public DirtyPot(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class DirtyRoundPot : Item + { + [Constructible] + public DirtyRoundPot() : base(0x9DF) => Weight = 1.0; + + public DirtyRoundPot(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class DirtyFrypan : Item + { + [Constructible] + public DirtyFrypan() : base(0x9DE) => Weight = 1.0; + + public DirtyFrypan(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class DirtySmallPot : Item + { + [Constructible] + public DirtySmallPot() : base(0x9DD) => Weight = 1.0; + + public DirtySmallPot(Serial serial) : base(serial) + { + } + + 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(); + } + } + + public class DirtyKettle : Item + { + [Constructible] + public DirtyKettle() : base(0x9DC) => Weight = 1.0; + + public DirtyKettle(Serial serial) : base(serial) + { + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Scales.cs b/Projects/UOContent/Items/Misc/Scales.cs index 75ec10342..b66fe1e8a 100644 --- a/Projects/UOContent/Items/Misc/Scales.cs +++ b/Projects/UOContent/Items/Misc/Scales.cs @@ -1,81 +1,83 @@ -using Server.Targeting; - -namespace Server.Items -{ - public class Scales : Item - { - [Constructible] - public Scales() : base(0x1852) => Weight = 4.0; - - public Scales(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int 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) - { - string message; - - if (targeted == m_Item) - { - message = "It cannot weight itself."; - } - else if (targeted is Item item) - { - IEntity root = item.RootParent; - - 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. "; - - double weight = item.Weight; - - 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."; - } - - from.SendMessage(message); - } - } - } -} \ No newline at end of file +using Server.Targeting; + +namespace Server.Items +{ + public class Scales : Item + { + [Constructible] + public Scales() : base(0x1852) => Weight = 4.0; + + public Scales(Serial serial) : base(serial) + { + } + + 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) + { + string message; + + if (targeted == m_Item) + { + message = "It cannot weight itself."; + } + else if (targeted is Item item) + { + var root = item.RootParent; + + 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. "; + + var weight = item.Weight; + + 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."; + } + + from.SendMessage(message); + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/SerpentPillar.cs b/Projects/UOContent/Items/Misc/SerpentPillar.cs index 7e66f60f4..a52ff980d 100644 --- a/Projects/UOContent/Items/Misc/SerpentPillar.cs +++ b/Projects/UOContent/Items/Misc/SerpentPillar.cs @@ -1,103 +1,105 @@ -using Server.Multis; - -namespace Server.Items -{ - public class SerpentPillar : Item - { - [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 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) - { - Mobile from = e.Mobile; - - if (!e.Handled && from.InRange(this, 10) && e.Speech.ToLower() == Word) - { - BaseBoat boat = BaseBoat.FindBoatAt(from, 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; - } - - Map map = from.Map; - - for (int i = 0; i < 5; i++) // Try 5 times - { - int x = Utility.Random(Destination.X, Destination.Width); - int y = Utility.Random(Destination.Y, Destination.Height); - int z = map.GetAverageZ(x, y); - - Point3D dest = new Point3D(x, y, z); - - if (boat.CanFit(dest, map, boat.ItemID)) - { - int xOffset = x - boat.X; - int yOffset = y - boat.Y; - int zOffset = z - boat.Z; - - boat.Teleport(xOffset, yOffset, zOffset); - - return; - } - } - - boat.TillerMan?.Say(502508); // Ar, I refuse to take that matey through here! - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(Active); - writer.Write(Word); - writer.Write(Destination); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - Active = reader.ReadBool(); - Word = reader.ReadString(); - Destination = reader.ReadRect2D(); - } - } -} \ No newline at end of file +using Server.Multis; + +namespace Server.Items +{ + public class SerpentPillar : Item + { + [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 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) + { + var boat = BaseBoat.FindBoatAt(from, 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! + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(Active); + writer.Write(Word); + writer.Write(Destination); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + Active = reader.ReadBool(); + Word = reader.ReadString(); + Destination = reader.ReadRect2D(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/SpecialBeardDye.cs b/Projects/UOContent/Items/Misc/SpecialBeardDye.cs index 338ca14d7..d82d36951 100644 --- a/Projects/UOContent/Items/Misc/SpecialBeardDye.cs +++ b/Projects/UOContent/Items/Misc/SpecialBeardDye.cs @@ -1,162 +1,162 @@ -using Server.Gumps; -using Server.Network; - -namespace Server.Items -{ - public class SpecialBeardDye : Item - { - [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); - - int 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. - } - } - } - - public class SpecialBeardDyeGump : Gump - { - private static readonly SpecialBeardDyeEntry[] m_Entries = - { - new SpecialBeardDyeEntry("*****", 12, 10), - new SpecialBeardDyeEntry("*****", 32, 5), - new SpecialBeardDyeEntry("*****", 38, 8), - new SpecialBeardDyeEntry("*****", 54, 3), - new SpecialBeardDyeEntry("*****", 62, 10), - new SpecialBeardDyeEntry("*****", 81, 2), - new SpecialBeardDyeEntry("*****", 89, 2), - new SpecialBeardDyeEntry("*****", 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 (int 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 (int i = 0; i < m_Entries.Length; ++i) - { - SpecialBeardDyeEntry e = m_Entries[i]; - - AddPage(i + 1); - - for (int 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 (m_SpecialBeardDye.Deleted) - return; - - Mobile m = from.Mobile; - int[] 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 - - int entryIndex = switches[0] / 100; - int hueOffset = switches[0] % 100; - - if (entryIndex >= 0 && entryIndex < m_Entries.Length) - { - SpecialBeardDyeEntry e = m_Entries[entryIndex]; - - if (hueOffset >= 0 && hueOffset < e.HueCount) - { - int 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; } - } - } -} +using Server.Gumps; +using Server.Network; + +namespace Server.Items +{ + public class SpecialBeardDye : Item + { + [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. + } + } + } + + public class SpecialBeardDyeGump : Gump + { + private static readonly SpecialBeardDyeEntry[] m_Entries = + { + new SpecialBeardDyeEntry("*****", 12, 10), + new SpecialBeardDyeEntry("*****", 32, 5), + new SpecialBeardDyeEntry("*****", 38, 8), + new SpecialBeardDyeEntry("*****", 54, 3), + new SpecialBeardDyeEntry("*****", 62, 10), + new SpecialBeardDyeEntry("*****", 81, 2), + new SpecialBeardDyeEntry("*****", 89, 2), + new SpecialBeardDyeEntry("*****", 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); + } + } + } + + public override void OnResponse(NetState from, RelayInfo info) + { + 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; } + } + } +} diff --git a/Projects/UOContent/Items/Misc/SpecialHairDye.cs b/Projects/UOContent/Items/Misc/SpecialHairDye.cs index 643e6d2ad..b89386e74 100644 --- a/Projects/UOContent/Items/Misc/SpecialHairDye.cs +++ b/Projects/UOContent/Items/Misc/SpecialHairDye.cs @@ -1,163 +1,163 @@ -using Server.Gumps; -using Server.Network; - -namespace Server.Items -{ - public class SpecialHairDye : Item - { - [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); - - int 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. - } - } - } - - public class SpecialHairDyeGump : Gump - { - private static readonly SpecialHairDyeEntry[] m_Entries = - { - new SpecialHairDyeEntry("*****", 12, 10), - new SpecialHairDyeEntry("*****", 32, 5), - new SpecialHairDyeEntry("*****", 38, 8), - new SpecialHairDyeEntry("*****", 54, 3), - new SpecialHairDyeEntry("*****", 62, 10), - new SpecialHairDyeEntry("*****", 81, 2), - new SpecialHairDyeEntry("*****", 89, 2), - new SpecialHairDyeEntry("*****", 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 (int 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 (int i = 0; i < m_Entries.Length; ++i) - { - SpecialHairDyeEntry e = m_Entries[i]; - - AddPage(i + 1); - - for (int 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 (m_SpecialHairDye.Deleted) - return; - - Mobile m = from.Mobile; - int[] 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 - - int entryIndex = switches[0] / 100; - int hueOffset = switches[0] % 100; - - if (entryIndex >= 0 && entryIndex < m_Entries.Length) - { - SpecialHairDyeEntry e = m_Entries[entryIndex]; - - if (hueOffset >= 0 && hueOffset < e.HueCount) - { - m_SpecialHairDye.Delete(); - - int 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; } - } - } -} +using Server.Gumps; +using Server.Network; + +namespace Server.Items +{ + public class SpecialHairDye : Item + { + [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. + } + } + } + + public class SpecialHairDyeGump : Gump + { + private static readonly SpecialHairDyeEntry[] m_Entries = + { + new SpecialHairDyeEntry("*****", 12, 10), + new SpecialHairDyeEntry("*****", 32, 5), + new SpecialHairDyeEntry("*****", 38, 8), + new SpecialHairDyeEntry("*****", 54, 3), + new SpecialHairDyeEntry("*****", 62, 10), + new SpecialHairDyeEntry("*****", 81, 2), + new SpecialHairDyeEntry("*****", 89, 2), + new SpecialHairDyeEntry("*****", 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); + } + } + } + + public override void OnResponse(NetState from, RelayInfo info) + { + 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; } + } + } +} diff --git a/Projects/UOContent/Items/Misc/Static.cs b/Projects/UOContent/Items/Misc/Static.cs index 0472d7b82..8f352daad 100644 --- a/Projects/UOContent/Items/Misc/Static.cs +++ b/Projects/UOContent/Items/Misc/Static.cs @@ -1,90 +1,90 @@ -namespace Server.Items -{ - 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(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); - - int 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; - } - } - } - } -} \ No newline at end of file +namespace Server.Items +{ + 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(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; + } + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/SwarmOfFlies.cs b/Projects/UOContent/Items/Misc/SwarmOfFlies.cs index 0dfaf67e4..5bd68c62d 100644 --- a/Projects/UOContent/Items/Misc/SwarmOfFlies.cs +++ b/Projects/UOContent/Items/Misc/SwarmOfFlies.cs @@ -1,32 +1,32 @@ -namespace Server.Items -{ - public class SwarmOfFlies : Item - { - [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); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SwarmOfFlies : Item + { + [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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Teleporter.cs b/Projects/UOContent/Items/Misc/Teleporter.cs index 808ce6f74..c4bfe95b5 100644 --- a/Projects/UOContent/Items/Misc/Teleporter.cs +++ b/Projects/UOContent/Items/Misc/Teleporter.cs @@ -1,1172 +1,1192 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Server.Mobiles; -using Server.Network; -using Server.Spells; - -namespace Server.Items -{ - public class Teleporter : Item - { - 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; - - m_Active = true; - m_PointDest = pointDest; - m_MapDest = mapDest; - m_Creatures = creatures; - - m_CombatCheck = false; - m_CriminalCheck = false; - } - - public Teleporter(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool SourceEffect - { - get => m_SourceEffect; - set - { - m_SourceEffect = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool DestEffect - { - get => m_DestEffect; - set - { - m_DestEffect = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int SoundID - { - 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(ObjectPropertyList 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{0}", m_MapDest); - - if (m_PointDest != Point3D.Zero) - list.Add(1060659, "Coords\t{0}", m_PointDest); - - list.Add(1060660, "Creatures\t{0}", 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.DelayCall(m_Delay, DoTeleport, m); - } - - public virtual void DoTeleport(Mobile m) - { - Map map = m_MapDest; - - if (map == null || map == Map.Internal) - map = m.Map; - - Point3D p = m_PointDest; - - if (p == Point3D.Zero) - p = m.Location; - - BaseCreature.TeleportPets(m, p, map); - - bool sendEffect = !m.Hidden || m.AccessLevel == AccessLevel.Player; - - if (m_SourceEffect && sendEffect) - Effects.SendLocationEffect(m.Location, m.Map, 0x3728, 10, 10); - - m.MoveToWorld(p, map); - - if (m_DestEffect && sendEffect) - Effects.SendLocationEffect(m.Location, m.Map, 0x3728, 10, 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); - - int 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; - } - } - } - } - - public class SkillTeleporter : Teleporter - { - private int m_MessageNumber; - private string m_MessageString; - private double m_Required; - private SkillName m_Skill; - - [Constructible] - public SkillTeleporter() - { - } - - public SkillTeleporter(Serial serial) - : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public SkillName Skill - { - get => m_Skill; - set - { - m_Skill = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public double Required - { - get => m_Required; - set - { - m_Required = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public string MessageString - { - 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; - - Skill sk = m.Skills[m_Skill]; - - if (sk == null || sk.Base < m_Required) - { - if (m.BeginAction(this)) - { - if (m_MessageString != null) - m.Send(new UnicodeMessage(Serial, ItemID, MessageType.Regular, 0x3B2, 3, "ENU", null, - m_MessageString)); - else if (m_MessageNumber != 0) - m.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, 0x3B2, 3, m_MessageNumber, null, - "")); - - Timer.DelayCall(TimeSpan.FromSeconds(5.0), m.EndAction, this); - } - - return false; - } - - return true; - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - int skillIndex = (int)m_Skill; - string skillName; - - if (skillIndex >= 0 && skillIndex < SkillInfo.Table.Length) - skillName = SkillInfo.Table[skillIndex].Name; - else - skillName = "(Invalid)"; - - list.Add(1060661, "{0}\t{1:F1}", skillName, m_Required); - - if (m_MessageString != null) - list.Add(1060662, "Message\t{0}", m_MessageString); - else if (m_MessageNumber != 0) - list.Add(1060662, "Message\t#{0}", 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); - - int 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; - } - } - } - } - - public class KeywordTeleporter : Teleporter - { - private int m_Keyword; - private int m_Range; - private string m_Substring; - - [Constructible] - public KeywordTeleporter() - { - m_Keyword = -1; - m_Substring = null; - } - - public KeywordTeleporter(Serial serial) - : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public string Substring - { - get => m_Substring; - set - { - m_Substring = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Keyword - { - get => m_Keyword; - set - { - m_Keyword = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Range - { - get => m_Range; - set - { - m_Range = value; - InvalidateProperties(); - } - } - - public override bool HandlesOnSpeech => true; - - public override void OnSpeech(SpeechEventArgs e) - { - if (!e.Handled && Active) - { - Mobile m = e.Mobile; - - if (!m.InRange(GetWorldLocation(), m_Range)) - return; - - bool isMatch = false; - - if (m_Keyword >= 0 && e.HasKeyword(m_Keyword)) - isMatch = true; - else if (m_Substring != null && e.Speech.ToLower().IndexOf(m_Substring.ToLower()) >= 0) - isMatch = true; - - if (!isMatch || !CanTeleport(m)) - return; - - e.Handled = true; - StartTeleport(m); - } - } - - public override void DoTeleport(Mobile m) - { - if (!m.InRange(GetWorldLocation(), m_Range) || m.Map != Map) - return; - - base.DoTeleport(m); - } - - public override bool OnMoveOver(Mobile m) => true; - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1060661, "Range\t{0}", m_Range); - - if (m_Keyword >= 0) - list.Add(1060662, "Keyword\t{0}", m_Keyword); - - if (m_Substring != null) - list.Add(1060663, "Substring\t{0}", m_Substring); - } - - 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); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Substring = reader.ReadString(); - m_Keyword = reader.ReadInt(); - m_Range = reader.ReadInt(); - - break; - } - } - } - } - - public class WaitTeleporter : KeywordTeleporter - { - private static Dictionary m_Table; - - [Constructible] - public WaitTeleporter() - { - } - - 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() - { - m_Table = new Dictionary(); - - EventSink.Logout += EventSink_Logout; - } - - public static void EventSink_Logout(Mobile from) - { - if (from == null || !m_Table.TryGetValue(from, out TeleportingInfo info)) - return; - - info.Timer.Stop(); - m_Table.Remove(from); - } - - public static string FormatTime(TimeSpan ts) - { - if (ts.TotalHours >= 1) - { - int h = (int)Math.Round(ts.TotalHours); - return $"{h} hour{(h == 1 ? "" : "s")}"; - } - - if (ts.TotalMinutes >= 1) - { - int m = (int)Math.Round(ts.TotalMinutes); - return $"{m} minute{(m == 1 ? "" : "s")}"; - } - - int s = Math.Max((int)Math.Round(ts.TotalSeconds), 0); - return $"{s} second{(s == 1 ? "" : "s")}"; - } - - private void EndLock(Mobile m) - { - m.EndAction(this); - } - - public override void StartTeleport(Mobile m) - { - if (m_Table.TryGetValue(m, out TeleportingInfo 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.Timer.Next - DateTime.UtcNow)); - - Timer.DelayCall(TimeSpan.FromSeconds(5), EndLock, m); - } - - return; - } - - info.Timer.Stop(); - } - - if (StartMessage != null) - m.SendMessage(StartMessage); - else if (StartNumber != 0) - m.SendLocalizedMessage(StartNumber); - - if (Delay == TimeSpan.Zero) - DoTeleport(m); - else - m_Table[m] = new TeleportingInfo(this, Timer.DelayCall(Delay, DoTeleport, m)); - } - - 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); - - int 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, Timer t) - { - Teleporter = tele; - Timer = t; - } - - public WaitTeleporter Teleporter { get; } - - public Timer Timer { 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) - { - if (m_Teleporting.TryGetValue(m, out Timer t)) - t.Stop(); - - m_Teleporting[m] = Timer.DelayCall(delay, StartTeleport, m); - } - - public void StopTimer(Mobile m) - { - if (m_Teleporting.TryGetValue(m, out Timer t)) - { - t.Stop(); - m_Teleporting.Remove(m); - } - } - - 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 (KeyValuePair kvp in m_Teleporting) - { - writer.Write(kvp.Key); - writer.Write(kvp.Value.Next); - } - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - TimeoutDelay = reader.ReadTimeSpan(); - m_Teleporting = new Dictionary(); - - int count = reader.ReadInt(); - - for (int i = 0; i < count; ++i) - { - Mobile m = reader.ReadMobile(); - DateTime end = reader.ReadDateTime(); - - StartTimer(m, end - DateTime.UtcNow); - } - } - } - - 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.WriteItem(Teleporter); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Teleporter = reader.ReadItem(); - } - } - - 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; - } - - Container 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 (Item 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(ObjectPropertyList list) - { - base.GetProperties(list); - - StringBuilder props = new StringBuilder(); - - 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); - - int 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 - } - } -} +using System; +using System.Collections.Generic; +using System.Text; +using Server.Mobiles; +using Server.Network; +using Server.Spells; + +namespace Server.Items +{ + public class Teleporter : Item + { + 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; + + m_Active = true; + m_PointDest = pointDest; + m_MapDest = mapDest; + m_Creatures = creatures; + + m_CombatCheck = false; + m_CriminalCheck = false; + } + + public Teleporter(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool SourceEffect + { + get => m_SourceEffect; + set + { + m_SourceEffect = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool DestEffect + { + get => m_DestEffect; + set + { + m_DestEffect = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int SoundID + { + 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(ObjectPropertyList 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{0}", m_MapDest); + + if (m_PointDest != Point3D.Zero) + list.Add(1060659, "Coords\t{0}", m_PointDest); + + list.Add(1060660, "Creatures\t{0}", 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.DelayCall(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, 10); + + m.MoveToWorld(p, map); + + if (m_DestEffect && sendEffect) + Effects.SendLocationEffect(m.Location, m.Map, 0x3728, 10, 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; + } + } + } + } + + public class SkillTeleporter : Teleporter + { + private int m_MessageNumber; + private string m_MessageString; + private double m_Required; + private SkillName m_Skill; + + [Constructible] + public SkillTeleporter() + { + } + + public SkillTeleporter(Serial serial) + : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public SkillName Skill + { + get => m_Skill; + set + { + m_Skill = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public double Required + { + get => m_Required; + set + { + m_Required = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public string MessageString + { + 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.Send( + new UnicodeMessage( + Serial, + ItemID, + MessageType.Regular, + 0x3B2, + 3, + "ENU", + null, + m_MessageString + ) + ); + else if (m_MessageNumber != 0) + m.Send( + new MessageLocalized( + Serial, + ItemID, + MessageType.Regular, + 0x3B2, + 3, + m_MessageNumber, + null, + "" + ) + ); + + Timer.DelayCall(TimeSpan.FromSeconds(5.0), m.EndAction, this); + } + + return false; + } + + return true; + } + + public override void GetProperties(ObjectPropertyList 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, "{0}\t{1:F1}", skillName, m_Required); + + if (m_MessageString != null) + list.Add(1060662, "Message\t{0}", m_MessageString); + else if (m_MessageNumber != 0) + list.Add(1060662, "Message\t#{0}", 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; + } + } + } + } + + public class KeywordTeleporter : Teleporter + { + private int m_Keyword; + private int m_Range; + private string m_Substring; + + [Constructible] + public KeywordTeleporter() + { + m_Keyword = -1; + m_Substring = null; + } + + public KeywordTeleporter(Serial serial) + : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public string Substring + { + get => m_Substring; + set + { + m_Substring = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Keyword + { + get => m_Keyword; + set + { + m_Keyword = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Range + { + get => m_Range; + set + { + m_Range = value; + InvalidateProperties(); + } + } + + public override bool HandlesOnSpeech => true; + + public override void OnSpeech(SpeechEventArgs e) + { + 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.ToLower().IndexOf(m_Substring.ToLower()) >= 0) + isMatch = true; + + if (!isMatch || !CanTeleport(m)) + return; + + e.Handled = true; + StartTeleport(m); + } + } + + public override void DoTeleport(Mobile m) + { + if (!m.InRange(GetWorldLocation(), m_Range) || m.Map != Map) + return; + + base.DoTeleport(m); + } + + public override bool OnMoveOver(Mobile m) => true; + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1060661, "Range\t{0}", m_Range); + + if (m_Keyword >= 0) + list.Add(1060662, "Keyword\t{0}", m_Keyword); + + if (m_Substring != null) + list.Add(1060663, "Substring\t{0}", m_Substring); + } + + 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; + } + } + } + } + + public class WaitTeleporter : KeywordTeleporter + { + private static Dictionary m_Table; + + [Constructible] + public WaitTeleporter() + { + } + + 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() + { + m_Table = new Dictionary(); + + EventSink.Logout += EventSink_Logout; + } + + public static void EventSink_Logout(Mobile from) + { + if (from == null || !m_Table.TryGetValue(from, out var info)) + return; + + info.Timer.Stop(); + m_Table.Remove(from); + } + + 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")}"; + } + + private void EndLock(Mobile m) + { + m.EndAction(this); + } + + 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.Timer.Next - DateTime.UtcNow)); + + Timer.DelayCall(TimeSpan.FromSeconds(5), EndLock, m); + } + + return; + } + + info.Timer.Stop(); + } + + if (StartMessage != null) + m.SendMessage(StartMessage); + else if (StartNumber != 0) + m.SendLocalizedMessage(StartNumber); + + if (Delay == TimeSpan.Zero) + DoTeleport(m); + else + m_Table[m] = new TeleportingInfo(this, Timer.DelayCall(Delay, DoTeleport, m)); + } + + 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, Timer t) + { + Teleporter = tele; + Timer = t; + } + + public WaitTeleporter Teleporter { get; } + + public Timer Timer { 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) + { + if (m_Teleporting.TryGetValue(m, out var t)) + t.Stop(); + + m_Teleporting[m] = Timer.DelayCall(delay, StartTeleport, m); + } + + public void StopTimer(Mobile m) + { + if (m_Teleporting.TryGetValue(m, out var t)) + { + t.Stop(); + m_Teleporting.Remove(m); + } + } + + 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.ReadMobile(); + var end = reader.ReadDateTime(); + + StartTimer(m, end - DateTime.UtcNow); + } + } + } + + 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.WriteItem(Teleporter); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + Teleporter = reader.ReadItem(); + } + } + + 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(ObjectPropertyList list) + { + base.GetProperties(list); + + var props = new StringBuilder(); + + 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/The Citadel/DragonFlameSectBadge.cs b/Projects/UOContent/Items/Misc/The Citadel/DragonFlameSectBadge.cs index e33946895..6ebeccaa6 100644 --- a/Projects/UOContent/Items/Misc/The Citadel/DragonFlameSectBadge.cs +++ b/Projects/UOContent/Items/Misc/The Citadel/DragonFlameSectBadge.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class DragonFlameSectBadge : Item - { - [Constructible] - public DragonFlameSectBadge() : base(0x23E) => LootType = LootType.Blessed; - - public DragonFlameSectBadge(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073141; // A Dragon Flame Sect Badge - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class DragonFlameSectBadge : Item + { + [Constructible] + public DragonFlameSectBadge() : base(0x23E) => LootType = LootType.Blessed; + + public DragonFlameSectBadge(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073141; // A Dragon Flame Sect Badge + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/The Citadel/OrdersFromMinax.cs b/Projects/UOContent/Items/Misc/The Citadel/OrdersFromMinax.cs index 1a10279de..8db10348b 100644 --- a/Projects/UOContent/Items/Misc/The Citadel/OrdersFromMinax.cs +++ b/Projects/UOContent/Items/Misc/The Citadel/OrdersFromMinax.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class OrdersFromMinax : Item - { - [Constructible] - public OrdersFromMinax() : base(0x2279) => LootType = LootType.Blessed; - - public OrdersFromMinax(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074639; // Orders from Minax - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class OrdersFromMinax : Item + { + [Constructible] + public OrdersFromMinax() : base(0x2279) => LootType = LootType.Blessed; + + public OrdersFromMinax(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074639; // Orders from Minax + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/The Citadel/SerpentFangSectBadge.cs b/Projects/UOContent/Items/Misc/The Citadel/SerpentFangSectBadge.cs index 3ddcfb6f8..ebb121421 100644 --- a/Projects/UOContent/Items/Misc/The Citadel/SerpentFangSectBadge.cs +++ b/Projects/UOContent/Items/Misc/The Citadel/SerpentFangSectBadge.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class SerpentFangSectBadge : Item - { - [Constructible] - public SerpentFangSectBadge() : base(0x23C) => LootType = LootType.Blessed; - - public SerpentFangSectBadge(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073139; // A Serpent Fang Sect Badge - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class SerpentFangSectBadge : Item + { + [Constructible] + public SerpentFangSectBadge() : base(0x23C) => LootType = LootType.Blessed; + + public SerpentFangSectBadge(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073139; // A Serpent Fang Sect Badge + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/The Citadel/TigerClawSectBadge.cs b/Projects/UOContent/Items/Misc/The Citadel/TigerClawSectBadge.cs index 6d71d39fb..0d8e1c2a9 100644 --- a/Projects/UOContent/Items/Misc/The Citadel/TigerClawSectBadge.cs +++ b/Projects/UOContent/Items/Misc/The Citadel/TigerClawSectBadge.cs @@ -1,28 +1,28 @@ -namespace Server.Items -{ - public class TigerClawSectBadge : Item - { - [Constructible] - public TigerClawSectBadge() : base(0x23D) => LootType = LootType.Blessed; - - public TigerClawSectBadge(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073140; // A Tiger Claw Sect Badge - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TigerClawSectBadge : Item + { + [Constructible] + public TigerClawSectBadge() : base(0x23D) => LootType = LootType.Blessed; + + public TigerClawSectBadge(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073140; // A Tiger Claw Sect Badge + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/The Citadel/TravestysCollectionOfShells.cs b/Projects/UOContent/Items/Misc/The Citadel/TravestysCollectionOfShells.cs index 4126c4fbc..fe053a7bf 100644 --- a/Projects/UOContent/Items/Misc/The Citadel/TravestysCollectionOfShells.cs +++ b/Projects/UOContent/Items/Misc/The Citadel/TravestysCollectionOfShells.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class TravestysCollectionOfShells : Item - { - [Constructible] - public TravestysCollectionOfShells() : base(0xFD3) - { - } - - public TravestysCollectionOfShells(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072090; // Travesty's Collection of Shells - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TravestysCollectionOfShells : Item + { + [Constructible] + public TravestysCollectionOfShells() : base(0xFD3) + { + } + + public TravestysCollectionOfShells(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072090; // Travesty's Collection of Shells + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/The Citadel/TravestysFineTeakwoodTray.cs b/Projects/UOContent/Items/Misc/The Citadel/TravestysFineTeakwoodTray.cs index cf40dc2b2..793383f0f 100644 --- a/Projects/UOContent/Items/Misc/The Citadel/TravestysFineTeakwoodTray.cs +++ b/Projects/UOContent/Items/Misc/The Citadel/TravestysFineTeakwoodTray.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class TravestysFineTeakwoodTray : Item - { - [Constructible] - public TravestysFineTeakwoodTray() : base(Utility.Random(0x991, 2)) - { - } - - public TravestysFineTeakwoodTray(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075094; // Travesty's Fine Teakwood Tray - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TravestysFineTeakwoodTray : Item + { + [Constructible] + public TravestysFineTeakwoodTray() : base(Utility.Random(0x991, 2)) + { + } + + public TravestysFineTeakwoodTray(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075094; // Travesty's Fine Teakwood Tray + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/The Citadel/TravestysSushiPreparations.cs b/Projects/UOContent/Items/Misc/The Citadel/TravestysSushiPreparations.cs index 08a491543..44633c7af 100644 --- a/Projects/UOContent/Items/Misc/The Citadel/TravestysSushiPreparations.cs +++ b/Projects/UOContent/Items/Misc/The Citadel/TravestysSushiPreparations.cs @@ -1,30 +1,30 @@ -namespace Server.Items -{ - public class TravestysSushiPreparations : Item - { - [Constructible] - public TravestysSushiPreparations() : base(Utility.Random(0x1E15, 2)) - { - } - - public TravestysSushiPreparations(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075093; // Travesty's Sushi Preparations - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TravestysSushiPreparations : Item + { + [Constructible] + public TravestysSushiPreparations() : base(Utility.Random(0x1E15, 2)) + { + } + + public TravestysSushiPreparations(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075093; // Travesty's Sushi Preparations + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/TrashBarrel.cs b/Projects/UOContent/Items/Misc/TrashBarrel.cs index bac195841..6b6144d06 100644 --- a/Projects/UOContent/Items/Misc/TrashBarrel.cs +++ b/Projects/UOContent/Items/Misc/TrashBarrel.cs @@ -1,147 +1,146 @@ -using System; -using System.Collections.Generic; -using Server.Multis; -using Server.Network; - -namespace Server.Items -{ - public class TrashBarrel : Container, IChoppable - { - private Timer m_Timer; - - [Constructible] - public TrashBarrel() : base(0xE77) - { - Hue = 0x3B2; - Movable = false; - } - - public TrashBarrel(Serial serial) : base(serial) - { - } - - 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) - { - BaseHouse house = BaseHouse.FindHouseAt(from); - - if (house?.IsCoOwner(from) == true) - { - Effects.PlaySound(Location, Map, 0x3B3); - from.SendLocalizedMessage(500461); // You destroy the item. - Destroy(); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Items.Count > 0) - { - m_Timer = new EmptyTimer(this); - m_Timer.Start(); - } - } - - public override bool OnDragDrop(Mobile from, Item 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(); - } - - return true; - } - - public override bool OnDragDropInto(Mobile from, Item item, Point3D 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(); - } - - return true; - } - - public void Empty(int message) - { - List items = Items; - - if (items.Count > 0) - { - PublicOverheadMessage(MessageType.Regular, 0x3B2, message, ""); - - for (int i = items.Count - 1; i >= 0; --i) - { - if (i >= items.Count) - continue; - - items[i].Delete(); - } - } - - m_Timer?.Stop(); - - m_Timer = null; - } - - private class EmptyTimer : Timer - { - private readonly TrashBarrel m_Barrel; - - public EmptyTimer(TrashBarrel barrel) : base(TimeSpan.FromMinutes(3.0)) - { - m_Barrel = barrel; - Priority = TimerPriority.FiveSeconds; - } - - protected override void OnTick() - { - m_Barrel.Empty(501479); // Emptying the trashcan! - } - } - } -} +using System; +using Server.Multis; +using Server.Network; + +namespace Server.Items +{ + public class TrashBarrel : Container, IChoppable + { + private Timer m_Timer; + + [Constructible] + public TrashBarrel() : base(0xE77) + { + Hue = 0x3B2; + Movable = false; + } + + public TrashBarrel(Serial serial) : base(serial) + { + } + + 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) + { + Effects.PlaySound(Location, Map, 0x3B3); + from.SendLocalizedMessage(500461); // You destroy the item. + Destroy(); + } + } + + 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) + { + m_Timer = new EmptyTimer(this); + m_Timer.Start(); + } + } + + public override bool OnDragDrop(Mobile from, Item 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(); + } + + return true; + } + + public override bool OnDragDropInto(Mobile from, Item item, Point3D 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(); + } + + return true; + } + + public void Empty(int message) + { + var items = Items; + + if (items.Count > 0) + { + PublicOverheadMessage(MessageType.Regular, 0x3B2, message, ""); + + for (var i = items.Count - 1; i >= 0; --i) + { + if (i >= items.Count) + continue; + + items[i].Delete(); + } + } + + m_Timer?.Stop(); + + m_Timer = null; + } + + private class EmptyTimer : Timer + { + private readonly TrashBarrel m_Barrel; + + public EmptyTimer(TrashBarrel barrel) : base(TimeSpan.FromMinutes(3.0)) + { + m_Barrel = barrel; + Priority = TimerPriority.FiveSeconds; + } + + protected override void OnTick() + { + m_Barrel.Empty(501479); // Emptying the trashcan! + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/TrashChest.cs b/Projects/UOContent/Items/Misc/TrashChest.cs index 2f2beff4b..f42ff7beb 100644 --- a/Projects/UOContent/Items/Misc/TrashChest.cs +++ b/Projects/UOContent/Items/Misc/TrashChest.cs @@ -1,55 +1,55 @@ -using Server.Network; - -namespace Server.Items -{ - [Flippable(0xE41, 0xE40)] - public class TrashChest : Container - { - [Constructible] - public TrashChest() : base(0xE41) => Movable = false; - - public TrashChest(Serial serial) : base(serial) - { - } - - 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); - - int 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; - - PublicOverheadMessage(MessageType.Regular, 0x3B2, Utility.Random(1042891, 8)); - item.Delete(); - - return true; - } - } -} \ No newline at end of file +using Server.Network; + +namespace Server.Items +{ + [Flippable(0xE41, 0xE40)] + public class TrashChest : Container + { + [Constructible] + public TrashChest() : base(0xE41) => Movable = false; + + public TrashChest(Serial serial) : base(serial) + { + } + + 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; + + PublicOverheadMessage(MessageType.Regular, 0x3B2, Utility.Random(1042891, 8)); + item.Delete(); + + return true; + } + } +} diff --git a/Projects/UOContent/Items/Misc/TribalBerry.cs b/Projects/UOContent/Items/Misc/TribalBerry.cs index 5517d6a8a..79e052b34 100644 --- a/Projects/UOContent/Items/Misc/TribalBerry.cs +++ b/Projects/UOContent/Items/Misc/TribalBerry.cs @@ -1,37 +1,37 @@ -namespace Server.Items -{ - public class TribalBerry : Item - { - [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); - - int version = reader.ReadInt(); - - if (Hue == 4) - Hue = 6; - } - } -} +namespace Server.Items +{ + public class TribalBerry : Item + { + [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; + } + } +} diff --git a/Projects/UOContent/Items/Misc/TribalPaint.cs b/Projects/UOContent/Items/Misc/TribalPaint.cs index c4991ee6a..eea4f7f8b 100644 --- a/Projects/UOContent/Items/Misc/TribalPaint.cs +++ b/Projects/UOContent/Items/Misc/TribalPaint.cs @@ -1,89 +1,90 @@ -using System; -using Server.Factions; -using Server.Mobiles; -using Server.Spells; -using Server.Spells.Fifth; -using Server.Spells.Ninjitsu; -using Server.Spells.Seventh; - -namespace Server.Items -{ - public class TribalPaint : Item - { - [Constructible] - public TribalPaint() : base(0x9EC) - { - Hue = 2101; - Weight = 2.0; - Stackable = Core.ML; - } - - public TribalPaint(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1040000; // savage kin paint - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - 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(); - } - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +using System; +using Server.Factions; +using Server.Mobiles; +using Server.Spells; +using Server.Spells.Fifth; +using Server.Spells.Ninjitsu; +using Server.Spells.Seventh; + +namespace Server.Items +{ + public class TribalPaint : Item + { + [Constructible] + public TribalPaint() : base(0x9EC) + { + Hue = 2101; + Weight = 2.0; + Stackable = Core.ML; + } + + public TribalPaint(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1040000; // savage kin paint + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + 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(); + } + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Twisted Weald/HornOfTheDreadhorn.cs b/Projects/UOContent/Items/Misc/Twisted Weald/HornOfTheDreadhorn.cs index f07dd9274..8a30e0fe3 100644 --- a/Projects/UOContent/Items/Misc/Twisted Weald/HornOfTheDreadhorn.cs +++ b/Projects/UOContent/Items/Misc/Twisted Weald/HornOfTheDreadhorn.cs @@ -1,31 +1,31 @@ -namespace Server.Items -{ - [Flippable(0x315C, 0x315D)] - public class HornOfTheDreadhorn : Item - { - [Constructible] - public HornOfTheDreadhorn() : base(0x315C) - { - } - - public HornOfTheDreadhorn(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072089; // Horn of the Dread - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x315C, 0x315D)] + public class HornOfTheDreadhorn : Item + { + [Constructible] + public HornOfTheDreadhorn() : base(0x315C) + { + } + + public HornOfTheDreadhorn(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072089; // Horn of the Dread + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Twisted Weald/MangledHeadOfDreadhorn.cs b/Projects/UOContent/Items/Misc/Twisted Weald/MangledHeadOfDreadhorn.cs index e635ef4dd..7f2e6e396 100644 --- a/Projects/UOContent/Items/Misc/Twisted Weald/MangledHeadOfDreadhorn.cs +++ b/Projects/UOContent/Items/Misc/Twisted Weald/MangledHeadOfDreadhorn.cs @@ -1,31 +1,31 @@ -namespace Server.Items -{ - [Flippable(0x3156, 0x3157)] - public class MangledHeadOfDreadhorn : Item - { - [Constructible] - public MangledHeadOfDreadhorn() : base(0x3156) - { - } - - public MangledHeadOfDreadhorn(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072088; // The Mangled Head of Dread Horn - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + [Flippable(0x3156, 0x3157)] + public class MangledHeadOfDreadhorn : Item + { + [Constructible] + public MangledHeadOfDreadhorn() : base(0x3156) + { + } + + public MangledHeadOfDreadhorn(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072088; // The Mangled Head of Dread Horn + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/Twisted Weald/TaintedMushroom.cs b/Projects/UOContent/Items/Misc/Twisted Weald/TaintedMushroom.cs index 110913775..bc45aab08 100644 --- a/Projects/UOContent/Items/Misc/Twisted Weald/TaintedMushroom.cs +++ b/Projects/UOContent/Items/Misc/Twisted Weald/TaintedMushroom.cs @@ -1,31 +1,31 @@ -namespace Server.Items -{ - public class TaintedMushroom : Item - { - [Constructible] - public TaintedMushroom() : base(Utility.RandomMinMax(0x222E, 0x2231)) - { - } - - public TaintedMushroom(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075088; // Dread Horn Tainted Mushroom - public override bool ForceShowProperties => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +namespace Server.Items +{ + public class TaintedMushroom : Item + { + [Constructible] + public TaintedMushroom() : base(Utility.RandomMinMax(0x222E, 0x2231)) + { + } + + public TaintedMushroom(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075088; // Dread Horn Tainted Mushroom + public override bool ForceShowProperties => true; + + 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(); + } + } +} diff --git a/Projects/UOContent/Items/Misc/UnholyBone.cs b/Projects/UOContent/Items/Misc/UnholyBone.cs index e792efff8..80af85d0e 100644 --- a/Projects/UOContent/Items/Misc/UnholyBone.cs +++ b/Projects/UOContent/Items/Misc/UnholyBone.cs @@ -1,111 +1,111 @@ -using System; -using Server.Mobiles; - -namespace Server.Items -{ - public class UnholyBone : Item, ICarvable - { - private SpawnTimer m_Timer; - - [Constructible] - public UnholyBone() : base(0xF7E) - { - 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, 10, 0, 0); - - if (Utility.RandomDouble() < 0.3) - { - if (ItemID == 0xF7E) - from.SendMessage("You destroy the bone."); - else - from.SendMessage("You destroy the bone pile."); - - Gold gold = new Gold(25, 100); - - gold.MoveToWorld(GetWorldLocation(), Map); - - Delete(); - - m_Timer.Stop(); - } - else - { - if (ItemID == 0xF7E) - from.SendMessage("You damage the bone."); - else - from.SendMessage("You damage the bone pile."); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Timer = new SpawnTimer(this); - m_Timer.Start(); - } - - private class SpawnTimer : Timer - { - private readonly Item m_Item; - - public SpawnTimer(Item item) : base(TimeSpan.FromSeconds(Utility.RandomMinMax(5, 10))) - { - Priority = TimerPriority.FiftyMS; - - m_Item = item; - } - - protected override void OnTick() - { - 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(); - } - } - } -} \ No newline at end of file +using System; +using Server.Mobiles; + +namespace Server.Items +{ + public class UnholyBone : Item, ICarvable + { + private SpawnTimer m_Timer; + + [Constructible] + public UnholyBone() : base(0xF7E) + { + 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, 10, 0, 0); + + if (Utility.RandomDouble() < 0.3) + { + 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(); + } + else + { + if (ItemID == 0xF7E) + from.SendMessage("You damage the bone."); + else + from.SendMessage("You damage the bone pile."); + } + } + + 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(); + + m_Timer = new SpawnTimer(this); + m_Timer.Start(); + } + + private class SpawnTimer : Timer + { + private readonly Item m_Item; + + public SpawnTimer(Item item) : base(TimeSpan.FromSeconds(Utility.RandomMinMax(5, 10))) + { + Priority = TimerPriority.FiftyMS; + + m_Item = item; + } + + protected override void OnTick() + { + 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(); + } + } + } +} diff --git a/Projects/UOContent/Items/Misc/WarningItem.cs b/Projects/UOContent/Items/Misc/WarningItem.cs index beaab3f8b..c7f706bad 100644 --- a/Projects/UOContent/Items/Misc/WarningItem.cs +++ b/Projects/UOContent/Items/Misc/WarningItem.cs @@ -4,207 +4,208 @@ using Server.Network; namespace Server.Items { - public class WarningItem : Item - { - private bool m_Broadcasting; - - private DateTime m_LastBroadcast; - private int m_Range; - - [Constructible] - public WarningItem(int itemID, int range, int warning) : base(itemID) + public class WarningItem : Item { - if (range > 18) - range = 18; + private bool m_Broadcasting; - Movable = false; + private DateTime m_LastBroadcast; + private int m_Range; - WarningNumber = warning; - m_Range = range; + [Constructible] + public WarningItem(int itemID, int range, int warning) : base(itemID) + { + 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 || DateTime.UtcNow < m_LastBroadcast + ResetDelay) + return; + + m_LastBroadcast = DateTime.UtcNow; + + 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.DelayCall(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; + } + } + } } - [Constructible] - public WarningItem(int itemID, int range, string warning) : base(itemID) + public class HintItem : WarningItem { - if (range > 18) - range = 18; + [Constructible] + public HintItem(int itemID, int range, int warning, int hint) : base(itemID, range, warning) => HintNumber = hint; - Movable = false; + [Constructible] + public HintItem(int itemID, int range, string warning, string hint) : base(itemID, range, warning) => + HintString = hint; - WarningString = warning; - m_Range = range; + public HintItem(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public string HintString { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int HintNumber { get; set; } + + public override bool OnlyToTriggerer => true; + + public override void OnDoubleClick(Mobile from) + { + SendMessage(from, true, HintString, HintNumber); + } + + 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) + { + case 0: + { + HintString = reader.ReadString(); + HintNumber = reader.ReadInt(); + + break; + } + } + } } - - 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 || DateTime.UtcNow < m_LastBroadcast + ResetDelay) - return; - - m_LastBroadcast = DateTime.UtcNow; - - m_Broadcasting = true; - - SendMessage(triggerer, OnlyToTriggerer, WarningString, WarningNumber); - - if (NeighborRange >= 0) - { - List list = new List(); - - foreach (Item item in GetItemsInRange(NeighborRange)) - if (item != this && item is WarningItem warningItem) - list.Add(warningItem); - - for (int i = 0; i < list.Count; i++) - list[i].Broadcast(triggerer); - } - - Timer.DelayCall(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); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - WarningString = reader.ReadString(); - WarningNumber = reader.ReadInt(); - m_Range = reader.ReadInt(); - ResetDelay = reader.ReadTimeSpan(); - - break; - } - } - } - } - - public class HintItem : WarningItem - { - [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) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public string HintString { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int HintNumber { get; set; } - - public override bool OnlyToTriggerer => true; - - public override void OnDoubleClick(Mobile from) - { - SendMessage(from, true, HintString, HintNumber); - } - - 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); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - HintString = reader.ReadString(); - HintNumber = reader.ReadInt(); - - break; - } - } - } - } } diff --git a/Projects/UOContent/Items/Misc/Waypoint.cs b/Projects/UOContent/Items/Misc/Waypoint.cs index 0ef7e1919..171ccca40 100644 --- a/Projects/UOContent/Items/Misc/Waypoint.cs +++ b/Projects/UOContent/Items/Misc/Waypoint.cs @@ -2,138 +2,139 @@ using Server.Targeting; namespace Server.Items { - [Flippable(0x1f14, 0x1f15, 0x1f16, 0x1f17)] - public class WayPoint : Item - { - private WayPoint m_Next; - - [Constructible] - public WayPoint(WayPoint prev = null) : base(0x1f14) + [Flippable(0x1f14, 0x1f15, 0x1f16, 0x1f17)] + public class WayPoint : Item { - Hue = 0x498; - Visible = false; - // this.Movable = false; - if (prev != null) - prev.NextPoint = this; + private WayPoint m_Next; + + [Constructible] + public WayPoint(WayPoint prev = null) : base(0x1f14) + { + 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.ReadItem() as WayPoint; + break; + } + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + writer.Write(m_Next); + } } - public WayPoint(Serial serial) : base(serial) + public class NextPointTarget : Target { + private readonly WayPoint m_Point; + + public NextPointTarget(WayPoint pt) : base(-1, false, TargetFlags.None) => m_Point = pt; + + protected override void OnTarget(Mobile from, object target) + { + if (target is WayPoint point && m_Point != null) + m_Point.NextPoint = point; + else + from.SendMessage("Target a way point."); + } } - public override string DefaultName => "AI Way Point"; - - [CommandProperty(AccessLevel.GameMaster)] - public WayPoint NextPoint + public class WayPointSeqTarget : Target { - get => m_Next; - set - { - if (m_Next != this) - m_Next = value; - } + private readonly WayPoint m_Last; + + public WayPointSeqTarget(WayPoint last) : base(-1, true, TargetFlags.None) => m_Last = last; + + protected override void OnTarget(Mobile from, object targeted) + { + 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."); + } + } } - - 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); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Next = reader.ReadItem() as WayPoint; - break; - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(m_Next); - } - } - - public class NextPointTarget : Target - { - private readonly WayPoint m_Point; - - public NextPointTarget(WayPoint pt) : base(-1, false, TargetFlags.None) => m_Point = pt; - - protected override void OnTarget(Mobile from, object target) - { - if (target is WayPoint point && m_Point != null) - m_Point.NextPoint = point; - else - from.SendMessage("Target a way point."); - } - } - - public class WayPointSeqTarget : Target - { - private readonly WayPoint m_Last; - - public WayPointSeqTarget(WayPoint last) : base(-1, true, TargetFlags.None) => m_Last = last; - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is WayPoint wayPoint) - { - if (m_Last != null) - m_Last.NextPoint = wayPoint; - } - else if (targeted is IPoint3D d) - { - Point3D p = new Point3D(d); - - WayPoint 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."); - } - } - } } diff --git a/Projects/UOContent/Items/Misc/WindChimes.cs b/Projects/UOContent/Items/Misc/WindChimes.cs index 69ece9807..56604fb27 100644 --- a/Projects/UOContent/Items/Misc/WindChimes.cs +++ b/Projects/UOContent/Items/Misc/WindChimes.cs @@ -4,173 +4,173 @@ using Server.Network; namespace Server.Items { - public abstract class BaseWindChimes : Item - { - private bool m_TurnedOn; - - public BaseWindChimes(int itemID) : base(itemID) + public abstract class BaseWindChimes : Item { - } + private bool m_TurnedOn; - public BaseWindChimes(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool TurnedOn - { - 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(ObjectPropertyList 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); - - int 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) - { - Mobile from = sender.Mobile; - - if (info.ButtonID == 1) + public BaseWindChimes(int itemID) : base(itemID) { - bool newValue = !m_Chimes.TurnedOn; - - m_Chimes.TurnedOn = newValue; - - if (newValue && !m_Chimes.IsLockedDown) - from.SendLocalizedMessage(502693); // Remember, this only works when locked down. } - else + + public BaseWindChimes(Serial serial) : base(serial) { - from.SendLocalizedMessage(502694); // Cancelled action. } - } - } - } - public class WindChimes : BaseWindChimes - { - [Constructible] - public WindChimes() : base(0x2832) + [CommandProperty(AccessLevel.GameMaster)] + public bool TurnedOn + { + 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(ObjectPropertyList 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. + } + } + } + } + + public class WindChimes : BaseWindChimes { + [Constructible] + public WindChimes() : base(0x2832) + { + } + + public WindChimes(Serial serial) : base(serial) + { + } + + 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(); + } } - public WindChimes(Serial serial) : base(serial) + public class FancyWindChimes : BaseWindChimes { + [Constructible] + public FancyWindChimes() : base(0x2833) + { + } + + public FancyWindChimes(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1030291; + + 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 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); - int version = reader.ReadInt(); - } - } - - public class FancyWindChimes : BaseWindChimes - { - [Constructible] - public FancyWindChimes() : base(0x2833) - { - } - - public FancyWindChimes(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1030291; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/AmeliasToolbox.cs b/Projects/UOContent/Items/New Haven Quest Rewards/AmeliasToolbox.cs index 6d0920157..0d48c4b87 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/AmeliasToolbox.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/AmeliasToolbox.cs @@ -1,32 +1,32 @@ namespace Server.Items { - public class AmeliasToolbox : TinkerTools - { - [Constructible] - public AmeliasToolbox() : base(500) + public class AmeliasToolbox : TinkerTools { - LootType = LootType.Blessed; - Hue = 1895; // TODO check + [Constructible] + public AmeliasToolbox() : base(500) + { + LootType = LootType.Blessed; + Hue = 1895; // TODO check + } + + public AmeliasToolbox(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1077749; // Amelias Toolbox + + 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(); + } } - - public AmeliasToolbox(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1077749; // Amelias Toolbox - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/ArmsOfArmstrong.cs b/Projects/UOContent/Items/New Haven Quest Rewards/ArmsOfArmstrong.cs index 70bac1a80..16709a5ca 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/ArmsOfArmstrong.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/ArmsOfArmstrong.cs @@ -1,40 +1,40 @@ namespace Server.Items { - public class ArmsOfArmstrong : LeatherArms - { - [Constructible] - public ArmsOfArmstrong() + public class ArmsOfArmstrong : LeatherArms { - LootType = LootType.Blessed; + [Constructible] + public ArmsOfArmstrong() + { + LootType = LootType.Blessed; - Attributes.BonusStr = 3; - Attributes.RegenHits = 1; + Attributes.BonusStr = 3; + Attributes.RegenHits = 1; + } + + public ArmsOfArmstrong(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1077675; // Arms of Armstrong + + public override int BasePhysicalResistance => 6; + public override int BaseFireResistance => 6; + public override int BaseColdResistance => 5; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 5; + + 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(); + } } - - public ArmsOfArmstrong(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1077675; // Arms of Armstrong - - public override int BasePhysicalResistance => 6; - public override int BaseFireResistance => 6; - public override int BaseColdResistance => 5; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 5; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/BagOfNecromancerReagents.cs b/Projects/UOContent/Items/New Haven Quest Rewards/BagOfNecromancerReagents.cs index 08d8b54aa..61b4d9df1 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/BagOfNecromancerReagents.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/BagOfNecromancerReagents.cs @@ -1,33 +1,33 @@ namespace Server.Items { - public class BagOfNecromancerReagents : Bag - { - [Constructible] - public BagOfNecromancerReagents(int amount = 50) + public class BagOfNecromancerReagents : Bag { - DropItem(new BatWing(amount)); - DropItem(new GraveDust(amount)); - DropItem(new DaemonBlood(amount)); - DropItem(new NoxCrystal(amount)); - DropItem(new PigIron(amount)); + [Constructible] + public BagOfNecromancerReagents(int amount = 50) + { + DropItem(new BatWing(amount)); + DropItem(new GraveDust(amount)); + DropItem(new DaemonBlood(amount)); + DropItem(new NoxCrystal(amount)); + DropItem(new PigIron(amount)); + } + + public BagOfNecromancerReagents(Serial serial) : base(serial) + { + } + + 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(); + } } - - public BagOfNecromancerReagents(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } } diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/BagOfSmokeBombs.cs b/Projects/UOContent/Items/New Haven Quest Rewards/BagOfSmokeBombs.cs index 079a2db26..250b61ae9 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/BagOfSmokeBombs.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/BagOfSmokeBombs.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class BagOfSmokeBombs : Bag - { - [Constructible] - public BagOfSmokeBombs(int amount = 20) + public class BagOfSmokeBombs : Bag { - for (int i = 0; i < amount; ++i) - DropItem(new SmokeBomb()); + [Constructible] + public BagOfSmokeBombs(int amount = 20) + { + for (var i = 0; i < amount; ++i) + DropItem(new SmokeBomb()); + } + + public BagOfSmokeBombs(Serial serial) : base(serial) + { + } + + 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(); + } } - - public BagOfSmokeBombs(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } } diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/BraceletOfResilience.cs b/Projects/UOContent/Items/New Haven Quest Rewards/BraceletOfResilience.cs index 42e26ad40..c9429d70c 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/BraceletOfResilience.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/BraceletOfResilience.cs @@ -1,37 +1,37 @@ namespace Server.Items { - public class BraceletOfResilience : GoldBracelet - { - [Constructible] - public BraceletOfResilience() + public class BraceletOfResilience : GoldBracelet { - LootType = LootType.Blessed; + [Constructible] + public BraceletOfResilience() + { + LootType = LootType.Blessed; - Attributes.DefendChance = 5; - Resistances.Fire = 5; - Resistances.Cold = 5; - Resistances.Poison = 5; - Resistances.Energy = 5; + Attributes.DefendChance = 5; + Resistances.Fire = 5; + Resistances.Cold = 5; + Resistances.Poison = 5; + Resistances.Energy = 5; + } + + public BraceletOfResilience(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1077627; // Bracelet of Resilience + + 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(); + } } - - public BraceletOfResilience(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1077627; // Bracelet of Resilience - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/BulwarkLeggings.cs b/Projects/UOContent/Items/New Haven Quest Rewards/BulwarkLeggings.cs index 1e543c0d9..610011379 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/BulwarkLeggings.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/BulwarkLeggings.cs @@ -1,40 +1,40 @@ namespace Server.Items { - public class BulwarkLeggings : RingmailLegs - { - [Constructible] - public BulwarkLeggings() + public class BulwarkLeggings : RingmailLegs { - LootType = LootType.Blessed; + [Constructible] + public BulwarkLeggings() + { + LootType = LootType.Blessed; - Attributes.RegenStam = 1; - Attributes.RegenMana = 1; + Attributes.RegenStam = 1; + Attributes.RegenMana = 1; + } + + public BulwarkLeggings(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1077727; // Bulwark Leggings + + public override int BasePhysicalResistance => 9; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 5; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 3; + + 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(); + } } - - public BulwarkLeggings(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1077727; // Bulwark Leggings - - public override int BasePhysicalResistance => 9; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 5; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 3; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/ChurchillsWarMace.cs b/Projects/UOContent/Items/New Haven Quest Rewards/ChurchillsWarMace.cs index efa9bc64e..bc26f585d 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/ChurchillsWarMace.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/ChurchillsWarMace.cs @@ -1,36 +1,36 @@ namespace Server.Items { - public class ChurchillsWarMace : WarMace - { - [Constructible] - public ChurchillsWarMace() + public class ChurchillsWarMace : WarMace { - LootType = LootType.Blessed; + [Constructible] + public ChurchillsWarMace() + { + LootType = LootType.Blessed; - Attributes.AttackChance = 5; - Attributes.WeaponSpeed = 10; - Attributes.WeaponDamage = 25; - WeaponAttributes.LowerStatReq = 70; + Attributes.AttackChance = 5; + Attributes.WeaponSpeed = 10; + Attributes.WeaponDamage = 25; + WeaponAttributes.LowerStatReq = 70; + } + + public ChurchillsWarMace(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1078062; // Churchill's War Mace + + 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(); + } } - - public ChurchillsWarMace(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1078062; // Churchill's War Mace - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/ClaspOfConcentration.cs b/Projects/UOContent/Items/New Haven Quest Rewards/ClaspOfConcentration.cs index 2df24cbaa..9e3e6c118 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/ClaspOfConcentration.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/ClaspOfConcentration.cs @@ -1,36 +1,36 @@ namespace Server.Items { - public class ClaspOfConcentration : SilverBracelet - { - [Constructible] - public ClaspOfConcentration() + public class ClaspOfConcentration : SilverBracelet { - LootType = LootType.Blessed; + [Constructible] + public ClaspOfConcentration() + { + LootType = LootType.Blessed; - Attributes.RegenStam = 2; - Attributes.RegenMana = 1; - Resistances.Fire = 5; - Resistances.Cold = 5; + Attributes.RegenStam = 2; + Attributes.RegenMana = 1; + Resistances.Fire = 5; + Resistances.Cold = 5; + } + + public ClaspOfConcentration(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1077695; // Clasp of Concentration + + 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(); + } } - - public ClaspOfConcentration(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1077695; // Clasp of Concentration - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/EmberStaff.cs b/Projects/UOContent/Items/New Haven Quest Rewards/EmberStaff.cs index 13ccd2d38..b72db9fab 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/EmberStaff.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/EmberStaff.cs @@ -1,37 +1,37 @@ namespace Server.Items { - public class EmberStaff : QuarterStaff - { - [Constructible] - public EmberStaff() + public class EmberStaff : QuarterStaff { - LootType = LootType.Blessed; + [Constructible] + public EmberStaff() + { + LootType = LootType.Blessed; - WeaponAttributes.HitFireball = 15; - WeaponAttributes.MageWeapon = 10; - Attributes.SpellChanneling = 1; - Attributes.CastSpeed = -1; - WeaponAttributes.LowerStatReq = 50; + WeaponAttributes.HitFireball = 15; + WeaponAttributes.MageWeapon = 10; + Attributes.SpellChanneling = 1; + Attributes.CastSpeed = -1; + WeaponAttributes.LowerStatReq = 50; + } + + public EmberStaff(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1077582; // Ember Staff + + 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(); + } } - - public EmberStaff(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1077582; // Ember Staff - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/EscutcheonDeAriadne.cs b/Projects/UOContent/Items/New Haven Quest Rewards/EscutcheonDeAriadne.cs index 39a24ae83..39d3099e7 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/EscutcheonDeAriadne.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/EscutcheonDeAriadne.cs @@ -1,41 +1,41 @@ namespace Server.Items { - public class EscutcheonDeAriadne : MetalKiteShield - { - [Constructible] - public EscutcheonDeAriadne() + public class EscutcheonDeAriadne : MetalKiteShield { - LootType = LootType.Blessed; - Hue = 0x8A5; + [Constructible] + public EscutcheonDeAriadne() + { + LootType = LootType.Blessed; + Hue = 0x8A5; - ArmorAttributes.DurabilityBonus = 49; - Attributes.ReflectPhysical = 5; - Attributes.DefendChance = 5; + ArmorAttributes.DurabilityBonus = 49; + Attributes.ReflectPhysical = 5; + Attributes.DefendChance = 5; + } + + public EscutcheonDeAriadne(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1077694; // Escutcheon de Ariadne + + public override int BasePhysicalResistance => 5; + public override int BaseEnergyResistance => 1; + + public override int AosStrReq => 14; + + 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(); + } } - - public EscutcheonDeAriadne(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1077694; // Escutcheon de Ariadne - - public override int BasePhysicalResistance => 5; - public override int BaseEnergyResistance => 1; - - public override int AosStrReq => 14; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/GlovesOfSafeguarding.cs b/Projects/UOContent/Items/New Haven Quest Rewards/GlovesOfSafeguarding.cs index 9707ec7c5..73c9303b8 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/GlovesOfSafeguarding.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/GlovesOfSafeguarding.cs @@ -1,40 +1,40 @@ namespace Server.Items { - public class GlovesOfSafeguarding : LeatherGloves - { - [Constructible] - public GlovesOfSafeguarding() + public class GlovesOfSafeguarding : LeatherGloves { - LootType = LootType.Blessed; + [Constructible] + public GlovesOfSafeguarding() + { + LootType = LootType.Blessed; - Attributes.BonusStam = 3; - Attributes.RegenHits = 1; + Attributes.BonusStam = 3; + Attributes.RegenHits = 1; + } + + public GlovesOfSafeguarding(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1077614; // Gloves of Safeguarding + + public override int BasePhysicalResistance => 6; + public override int BaseFireResistance => 6; + public override int BaseColdResistance => 5; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 5; + + 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(); + } } - - public GlovesOfSafeguarding(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1077614; // Gloves of Safeguarding - - public override int BasePhysicalResistance => 6; - public override int BaseFireResistance => 6; - public override int BaseColdResistance => 5; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 5; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/HallowedSpellbook.cs b/Projects/UOContent/Items/New Haven Quest Rewards/HallowedSpellbook.cs index 8472b16e8..ac6131ea5 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/HallowedSpellbook.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/HallowedSpellbook.cs @@ -1,33 +1,33 @@ namespace Server.Items { - public class HallowedSpellbook : Spellbook - { - [Constructible] - public HallowedSpellbook() : base(0x3FFFFFFFF) + public class HallowedSpellbook : Spellbook { - LootType = LootType.Blessed; + [Constructible] + public HallowedSpellbook() : base(0x3FFFFFFFF) + { + LootType = LootType.Blessed; - Slayer = SlayerName.Silver; + Slayer = SlayerName.Silver; + } + + public HallowedSpellbook(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1077620; // Hallowed Spellbook + + 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(); + } } - - public HallowedSpellbook(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1077620; // Hallowed Spellbook - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/HammerOfHephaestus.cs b/Projects/UOContent/Items/New Haven Quest Rewards/HammerOfHephaestus.cs index 04dcee264..4cb37e286 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/HammerOfHephaestus.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/HammerOfHephaestus.cs @@ -2,72 +2,73 @@ using System; namespace Server.Items { - [Flippable(0x13E3, 0x13E4)] - public class HammerOfHephaestus : SmithHammer - { - public static readonly TimeSpan RechargeDelay = TimeSpan.FromMinutes(5); - - [Constructible] - public HammerOfHephaestus() + [Flippable(0x13E3, 0x13E4)] + public class HammerOfHephaestus : SmithHammer { - UsesRemaining = 20; - LootType = LootType.Blessed; + public static readonly TimeSpan RechargeDelay = TimeSpan.FromMinutes(5); - // TODO: Blacksmith +10 bonus when equipped + [Constructible] + public HammerOfHephaestus() + { + UsesRemaining = 20; + LootType = LootType.Blessed; - StartRechargeTimer(); + // TODO: Blacksmith +10 bonus when equipped + + StartRechargeTimer(); + } + + public HammerOfHephaestus(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1077740; // Hammer of Hephaestus + + public override bool BreakOnDepletion => false; + /* Note: + * On EA, it also leaves the crafting gump open when it reaches 0 charges. + * When crafting again, only then the crafting gump closes with the 1072306 system message. + */ + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack) && Parent != from + ) // TODO: These checks don't match EA, but they match BaseTool for now + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + else if (UsesRemaining <= 0) + from.SendLocalizedMessage(1072306); // You must wait a moment for it to recharge. + else + base.OnDoubleClick(from); + } + + private void StartRechargeTimer() + { + // TODO: Needs work + // Timer.DelayCall( RechargeDelay, RechargeDelay, new TimerCallback( Recharge ) ); + } + + public void Recharge() + { + // TODO: Stop timer at 20? Count downtime? Something more generic so we can use it for JacobsPickaxe too (both are IUsesRemaining)? + if (UsesRemaining < 20) + ++UsesRemaining; + } + + 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(); + + StartRechargeTimer(); + } } - - public HammerOfHephaestus(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1077740; // Hammer of Hephaestus - - public override bool BreakOnDepletion => false; - /* Note: - * On EA, it also leaves the crafting gump open when it reaches 0 charges. - * When crafting again, only then the crafting gump closes with the 1072306 system message. - */ - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack) && Parent != from) // TODO: These checks don't match EA, but they match BaseTool for now - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - else if (UsesRemaining <= 0) - from.SendLocalizedMessage(1072306); // You must wait a moment for it to recharge. - else - base.OnDoubleClick(from); - } - - private void StartRechargeTimer() - { - // TODO: Needs work - // Timer.DelayCall( RechargeDelay, RechargeDelay, new TimerCallback( Recharge ) ); - } - - public void Recharge() - { - // TODO: Stop timer at 20? Count downtime? Something more generic so we can use it for JacobsPickaxe too (both are IUsesRemaining)? - if (UsesRemaining < 20) - ++UsesRemaining; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - StartRechargeTimer(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/HealersTouch.cs b/Projects/UOContent/Items/New Haven Quest Rewards/HealersTouch.cs index 143ba68a9..c638f60df 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/HealersTouch.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/HealersTouch.cs @@ -1,40 +1,40 @@ namespace Server.Items { - public class HealersTouch : LeatherGloves - { - [Constructible] - public HealersTouch() + public class HealersTouch : LeatherGloves { - LootType = LootType.Blessed; + [Constructible] + public HealersTouch() + { + LootType = LootType.Blessed; - Attributes.BonusStam = 3; - Attributes.ReflectPhysical = 5; + Attributes.BonusStam = 3; + Attributes.ReflectPhysical = 5; + } + + public HealersTouch(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1077684; // Healer's Touch + + public override int BasePhysicalResistance => 6; + public override int BaseFireResistance => 6; + public override int BaseColdResistance => 5; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 5; + + 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(); + } } - - public HealersTouch(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1077684; // Healer's Touch - - public override int BasePhysicalResistance => 6; - public override int BaseFireResistance => 6; - public override int BaseColdResistance => 5; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 5; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/Heartseeker.cs b/Projects/UOContent/Items/New Haven Quest Rewards/Heartseeker.cs index b0af24072..5c6ff58c6 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/Heartseeker.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/Heartseeker.cs @@ -1,36 +1,36 @@ namespace Server.Items { - public class Heartseeker : CompositeBow - { - [Constructible] - public Heartseeker() + public class Heartseeker : CompositeBow { - LootType = LootType.Blessed; + [Constructible] + public Heartseeker() + { + LootType = LootType.Blessed; - Attributes.AttackChance = 5; - Attributes.WeaponSpeed = 10; - Attributes.WeaponDamage = 25; - WeaponAttributes.LowerStatReq = 70; + Attributes.AttackChance = 5; + Attributes.WeaponSpeed = 10; + Attributes.WeaponDamage = 25; + WeaponAttributes.LowerStatReq = 70; + } + + public Heartseeker(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1078210; // Heartseeker + + 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(); + } } - - public Heartseeker(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1078210; // Heartseeker - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/JacobsPickaxe.cs b/Projects/UOContent/Items/New Haven Quest Rewards/JacobsPickaxe.cs index 7ddf3597f..f88bd0137 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/JacobsPickaxe.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/JacobsPickaxe.cs @@ -1,37 +1,37 @@ namespace Server.Items { - public class JacobsPickaxe : Pickaxe - { - // TODO: Recharges 1 use every 5 minutes. Doesn't break when it reaches 0, you get a system message "You must wait a moment for it to recharge" 1072306 if you attempt to use it with no uses remaining. - - [Constructible] - public JacobsPickaxe() + public class JacobsPickaxe : Pickaxe { - UsesRemaining = 20; - LootType = LootType.Blessed; + // TODO: Recharges 1 use every 5 minutes. Doesn't break when it reaches 0, you get a system message "You must wait a moment for it to recharge" 1072306 if you attempt to use it with no uses remaining. - SkillBonuses.SetValues(0, SkillName.Mining, 10.0); + [Constructible] + public JacobsPickaxe() + { + UsesRemaining = 20; + LootType = LootType.Blessed; + + SkillBonuses.SetValues(0, SkillName.Mining, 10.0); + } + + public JacobsPickaxe(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1077758; // Jacob's Pickaxe + + 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(); + } } - - public JacobsPickaxe(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1077758; // Jacob's Pickaxe - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/JocklesQuicksword.cs b/Projects/UOContent/Items/New Haven Quest Rewards/JocklesQuicksword.cs index 6d94ff815..675cc773c 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/JocklesQuicksword.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/JocklesQuicksword.cs @@ -1,35 +1,35 @@ namespace Server.Items { - public class JocklesQuicksword : Longsword - { - [Constructible] - public JocklesQuicksword() + public class JocklesQuicksword : Longsword { - LootType = LootType.Blessed; + [Constructible] + public JocklesQuicksword() + { + LootType = LootType.Blessed; - Attributes.AttackChance = 5; - Attributes.WeaponSpeed = 10; - Attributes.WeaponDamage = 25; + Attributes.AttackChance = 5; + Attributes.WeaponSpeed = 10; + Attributes.WeaponDamage = 25; + } + + public JocklesQuicksword(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1077666; // Jockles' Quicksword + + 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(); + } } - - public JocklesQuicksword(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1077666; // Jockles' Quicksword - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/PhilosophersHat.cs b/Projects/UOContent/Items/New Haven Quest Rewards/PhilosophersHat.cs index 6780e8d24..0d1c551bc 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/PhilosophersHat.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/PhilosophersHat.cs @@ -1,40 +1,40 @@ namespace Server.Items { - public class PhilosophersHat : WizardsHat - { - [Constructible] - public PhilosophersHat() + public class PhilosophersHat : WizardsHat { - LootType = LootType.Blessed; + [Constructible] + public PhilosophersHat() + { + LootType = LootType.Blessed; - Attributes.RegenMana = 1; - Attributes.LowerRegCost = 7; + Attributes.RegenMana = 1; + Attributes.LowerRegCost = 7; + } + + public PhilosophersHat(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1077602; // Philosopher's Hat + + public override int BasePhysicalResistance => 5; + public override int BaseFireResistance => 5; + public override int BaseColdResistance => 9; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 5; + + 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(); + } } - - public PhilosophersHat(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1077602; // Philosopher's Hat - - public override int BasePhysicalResistance => 5; - public override int BaseFireResistance => 5; - public override int BaseColdResistance => 9; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 5; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/RecarosRiposte.cs b/Projects/UOContent/Items/New Haven Quest Rewards/RecarosRiposte.cs index 2c34d0c66..e3fd25f91 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/RecarosRiposte.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/RecarosRiposte.cs @@ -1,35 +1,35 @@ namespace Server.Items { - public class RecarosRiposte : WarFork - { - [Constructible] - public RecarosRiposte() + public class RecarosRiposte : WarFork { - LootType = LootType.Blessed; + [Constructible] + public RecarosRiposte() + { + LootType = LootType.Blessed; - Attributes.AttackChance = 5; - Attributes.WeaponSpeed = 10; - Attributes.WeaponDamage = 25; + Attributes.AttackChance = 5; + Attributes.WeaponSpeed = 10; + Attributes.WeaponDamage = 25; + } + + public RecarosRiposte(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1078195; // Recaro's Riposte + + 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(); + } } - - public RecarosRiposte(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1078195; // Recaro's Riposte - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/RingOfTheSavant.cs b/Projects/UOContent/Items/New Haven Quest Rewards/RingOfTheSavant.cs index 028c46b8f..17ad72f86 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/RingOfTheSavant.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/RingOfTheSavant.cs @@ -1,35 +1,35 @@ namespace Server.Items { - public class RingOfTheSavant : GoldRing - { - [Constructible] - public RingOfTheSavant() + public class RingOfTheSavant : GoldRing { - LootType = LootType.Blessed; + [Constructible] + public RingOfTheSavant() + { + LootType = LootType.Blessed; - Attributes.BonusInt = 3; - Attributes.CastRecovery = 1; - Attributes.CastSpeed = 1; + Attributes.BonusInt = 3; + Attributes.CastRecovery = 1; + Attributes.CastSpeed = 1; + } + + public RingOfTheSavant(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1077608; // Ring of the Savant + + 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(); + } } - - public RingOfTheSavant(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1077608; // Ring of the Savant - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/SilverSerpentBlade.cs b/Projects/UOContent/Items/New Haven Quest Rewards/SilverSerpentBlade.cs index 7b8825397..ff7508eed 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/SilverSerpentBlade.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/SilverSerpentBlade.cs @@ -1,35 +1,35 @@ namespace Server.Items { - public class SilverSerpentBlade : Kryss - { - [Constructible] - public SilverSerpentBlade() + public class SilverSerpentBlade : Kryss { - LootType = LootType.Blessed; + [Constructible] + public SilverSerpentBlade() + { + LootType = LootType.Blessed; - Attributes.AttackChance = 5; - Attributes.WeaponSpeed = 10; - Attributes.WeaponDamage = 25; + Attributes.AttackChance = 5; + Attributes.WeaponSpeed = 10; + Attributes.WeaponDamage = 25; + } + + public SilverSerpentBlade(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1078163; // Silver Serpent Blade + + 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(); + } } - - public SilverSerpentBlade(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1078163; // Silver Serpent Blade - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/TheDragonsTail.cs b/Projects/UOContent/Items/New Haven Quest Rewards/TheDragonsTail.cs index 76e96b3aa..ac600cc53 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/TheDragonsTail.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/TheDragonsTail.cs @@ -1,38 +1,38 @@ namespace Server.Items { - public class TheDragonsTail : NoDachi - { - [Constructible] - public TheDragonsTail() + public class TheDragonsTail : NoDachi { - LootType = LootType.Blessed; + [Constructible] + public TheDragonsTail() + { + LootType = LootType.Blessed; - WeaponAttributes.HitLeechStam = 16; - Attributes.WeaponSpeed = 10; - Attributes.WeaponDamage = 25; + WeaponAttributes.HitLeechStam = 16; + Attributes.WeaponSpeed = 10; + Attributes.WeaponDamage = 25; + } + + public TheDragonsTail(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1078015; // The Dragon's Tail + + public override int InitMinHits => 80; + public override int InitMaxHits => 80; + + 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(); + } } - - public TheDragonsTail(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1078015; // The Dragon's Tail - - public override int InitMinHits => 80; - public override int InitMaxHits => 80; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/TunicOfGuarding.cs b/Projects/UOContent/Items/New Haven Quest Rewards/TunicOfGuarding.cs index 5a2a21bd4..860becb49 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/TunicOfGuarding.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/TunicOfGuarding.cs @@ -1,40 +1,40 @@ namespace Server.Items { - public class TunicOfGuarding : LeatherChest - { - [Constructible] - public TunicOfGuarding() + public class TunicOfGuarding : LeatherChest { - LootType = LootType.Blessed; + [Constructible] + public TunicOfGuarding() + { + LootType = LootType.Blessed; - Attributes.BonusHits = 2; - Attributes.ReflectPhysical = 5; + Attributes.BonusHits = 2; + Attributes.ReflectPhysical = 5; + } + + public TunicOfGuarding(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1077693; // Tunic of Guarding + + public override int BasePhysicalResistance => 6; + public override int BaseFireResistance => 6; + public override int BaseColdResistance => 5; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 5; + + 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(); + } } - - public TunicOfGuarding(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1077693; // Tunic of Guarding - - public override int BasePhysicalResistance => 6; - public override int BaseFireResistance => 6; - public override int BaseColdResistance => 5; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 5; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/TwilightJacket.cs b/Projects/UOContent/Items/New Haven Quest Rewards/TwilightJacket.cs index c3c1ab934..17a4d2e83 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/TwilightJacket.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/TwilightJacket.cs @@ -1,39 +1,39 @@ namespace Server.Items { - public class TwilightJacket : LeatherNinjaJacket - { - [Constructible] - public TwilightJacket() + public class TwilightJacket : LeatherNinjaJacket { - LootType = LootType.Blessed; + [Constructible] + public TwilightJacket() + { + LootType = LootType.Blessed; - Attributes.ReflectPhysical = 5; + Attributes.ReflectPhysical = 5; + } + + public TwilightJacket(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1078183; // Twilight Jacket + + public override int BasePhysicalResistance => 6; + public override int BaseFireResistance => 12; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + 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(); + } } - - public TwilightJacket(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1078183; // Twilight Jacket - - public override int BasePhysicalResistance => 6; - public override int BaseFireResistance => 12; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/New Haven Quest Rewards/WalkersLeggings.cs b/Projects/UOContent/Items/New Haven Quest Rewards/WalkersLeggings.cs index 87d4fc8ca..ba87ab741 100644 --- a/Projects/UOContent/Items/New Haven Quest Rewards/WalkersLeggings.cs +++ b/Projects/UOContent/Items/New Haven Quest Rewards/WalkersLeggings.cs @@ -1,34 +1,34 @@ namespace Server.Items { - public class WalkersLeggings : LeatherNinjaPants - { - [Constructible] - public WalkersLeggings() => LootType = LootType.Blessed; - - public WalkersLeggings(Serial serial) : base(serial) + public class WalkersLeggings : LeatherNinjaPants { + [Constructible] + public WalkersLeggings() => LootType = LootType.Blessed; + + public WalkersLeggings(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1078222; // Walker's Leggings + + public override int BasePhysicalResistance => 10; + public override int BaseFireResistance => 6; + public override int BaseColdResistance => 6; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + 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(); + } } - - public override int LabelNumber => 1078222; // Walker's Leggings - - public override int BasePhysicalResistance => 10; - public override int BaseFireResistance => 6; - public override int BaseColdResistance => 6; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/PlantsFlowers/Potted/EmptyPots.cs b/Projects/UOContent/Items/PlantsFlowers/Potted/EmptyPots.cs index 8743c056d..739317fb9 100644 --- a/Projects/UOContent/Items/PlantsFlowers/Potted/EmptyPots.cs +++ b/Projects/UOContent/Items/PlantsFlowers/Potted/EmptyPots.cs @@ -1,50 +1,50 @@ namespace Server.Items { - public class SmallEmptyPot : Item - { - [Constructible] - public SmallEmptyPot() : base(0x11C6) => Weight = 100; - - public SmallEmptyPot(Serial serial) : base(serial) + public class SmallEmptyPot : Item { + [Constructible] + public SmallEmptyPot() : base(0x11C6) => Weight = 100; + + public SmallEmptyPot(Serial serial) : base(serial) + { + } + + 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(); + } } - public override void Serialize(IGenericWriter writer) + public class LargeEmptyPot : Item { - base.Serialize(writer); + [Constructible] + public LargeEmptyPot() : base(0x11C7) => Weight = 6; - writer.Write(0); + public LargeEmptyPot(Serial serial) : base(serial) + { + } + + 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(); + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LargeEmptyPot : Item - { - [Constructible] - public LargeEmptyPot() : base(0x11C7) => Weight = 6; - - public LargeEmptyPot(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/PlantsFlowers/Potted/PottedCactus.cs b/Projects/UOContent/Items/PlantsFlowers/Potted/PottedCactus.cs index b70b0c1c6..96ffaa2f2 100644 --- a/Projects/UOContent/Items/PlantsFlowers/Potted/PottedCactus.cs +++ b/Projects/UOContent/Items/PlantsFlowers/Potted/PottedCactus.cs @@ -1,146 +1,146 @@ namespace Server.Items { - public class PottedCactus : Item - { - [Constructible] - public PottedCactus() : base(0x1E0F) => Weight = 100; - - public PottedCactus(Serial serial) : base(serial) + public class PottedCactus : Item { + [Constructible] + public PottedCactus() : base(0x1E0F) => Weight = 100; + + public PottedCactus(Serial serial) : base(serial) + { + } + + 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(); + } } - public override void Serialize(IGenericWriter writer) + public class PottedCactus1 : Item { - base.Serialize(writer); + [Constructible] + public PottedCactus1() : base(0x1E10) => Weight = 100; - writer.Write(0); + public PottedCactus1(Serial serial) : base(serial) + { + } + + 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(); + } } - public override void Deserialize(IGenericReader reader) + public class PottedCactus2 : Item { - base.Deserialize(reader); + [Constructible] + public PottedCactus2() : base(0x1E11) => Weight = 100; - int version = reader.ReadInt(); - } - } + public PottedCactus2(Serial serial) : base(serial) + { + } - public class PottedCactus1 : Item - { - [Constructible] - public PottedCactus1() : base(0x1E10) => Weight = 100; + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public PottedCactus1(Serial serial) : base(serial) - { + writer.Write(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } } - public override void Serialize(IGenericWriter writer) + public class PottedCactus3 : Item { - base.Serialize(writer); + [Constructible] + public PottedCactus3() : base(0x1E12) => Weight = 100; - writer.Write(0); + public PottedCactus3(Serial serial) : base(serial) + { + } + + 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(); + } } - public override void Deserialize(IGenericReader reader) + public class PottedCactus4 : Item { - base.Deserialize(reader); + [Constructible] + public PottedCactus4() : base(0x1E13) => Weight = 100; - int version = reader.ReadInt(); - } - } + public PottedCactus4(Serial serial) : base(serial) + { + } - public class PottedCactus2 : Item - { - [Constructible] - public PottedCactus2() : base(0x1E11) => Weight = 100; + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public PottedCactus2(Serial serial) : base(serial) - { + writer.Write(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } } - public override void Serialize(IGenericWriter writer) + public class PottedCactus5 : Item { - base.Serialize(writer); + [Constructible] + public PottedCactus5() : base(0x1E14) => Weight = 100; - writer.Write(0); + public PottedCactus5(Serial serial) : base(serial) + { + } + + 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(); + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PottedCactus3 : Item - { - [Constructible] - public PottedCactus3() : base(0x1E12) => Weight = 100; - - public PottedCactus3(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PottedCactus4 : Item - { - [Constructible] - public PottedCactus4() : base(0x1E13) => Weight = 100; - - public PottedCactus4(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PottedCactus5 : Item - { - [Constructible] - public PottedCactus5() : base(0x1E14) => Weight = 100; - - public PottedCactus5(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/PlantsFlowers/Potted/PottedPlants.cs b/Projects/UOContent/Items/PlantsFlowers/Potted/PottedPlants.cs index c188388b2..88830bbfb 100644 --- a/Projects/UOContent/Items/PlantsFlowers/Potted/PottedPlants.cs +++ b/Projects/UOContent/Items/PlantsFlowers/Potted/PottedPlants.cs @@ -1,74 +1,74 @@ namespace Server.Items { - public class PottedPlant : Item - { - [Constructible] - public PottedPlant() : base(0x11CA) => Weight = 100; - - public PottedPlant(Serial serial) : base(serial) + public class PottedPlant : Item { + [Constructible] + public PottedPlant() : base(0x11CA) => Weight = 100; + + public PottedPlant(Serial serial) : base(serial) + { + } + + 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(); + } } - public override void Serialize(IGenericWriter writer) + public class PottedPlant1 : Item { - base.Serialize(writer); + [Constructible] + public PottedPlant1() : base(0x11CB) => Weight = 100; - writer.Write(0); + public PottedPlant1(Serial serial) : base(serial) + { + } + + 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(); + } } - public override void Deserialize(IGenericReader reader) + public class PottedPlant2 : Item { - base.Deserialize(reader); + [Constructible] + public PottedPlant2() : base(0x11CC) => Weight = 100; - int version = reader.ReadInt(); + public PottedPlant2(Serial serial) : base(serial) + { + } + + 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(); + } } - } - - public class PottedPlant1 : Item - { - [Constructible] - public PottedPlant1() : base(0x11CB) => Weight = 100; - - public PottedPlant1(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PottedPlant2 : Item - { - [Constructible] - public PottedPlant2() : base(0x11CC) => Weight = 100; - - public PottedPlant2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/PlantsFlowers/Potted/PottedTrees.cs b/Projects/UOContent/Items/PlantsFlowers/Potted/PottedTrees.cs index 2282021c3..1e37c2e92 100644 --- a/Projects/UOContent/Items/PlantsFlowers/Potted/PottedTrees.cs +++ b/Projects/UOContent/Items/PlantsFlowers/Potted/PottedTrees.cs @@ -1,50 +1,50 @@ namespace Server.Items { - public class PottedTree : Item - { - [Constructible] - public PottedTree() : base(0x11C8) => Weight = 100; - - public PottedTree(Serial serial) : base(serial) + public class PottedTree : Item { + [Constructible] + public PottedTree() : base(0x11C8) => Weight = 100; + + public PottedTree(Serial serial) : base(serial) + { + } + + 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(); + } } - public override void Serialize(IGenericWriter writer) + public class PottedTree1 : Item { - base.Serialize(writer); + [Constructible] + public PottedTree1() : base(0x11C9) => Weight = 100; - writer.Write(0); + public PottedTree1(Serial serial) : base(serial) + { + } + + 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(); + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class PottedTree1 : Item - { - [Constructible] - public PottedTree1() : base(0x11C9) => Weight = 100; - - public PottedTree1(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Quivers/BaseQuiver.cs b/Projects/UOContent/Items/Quivers/BaseQuiver.cs index e751a2057..b93adcc98 100644 --- a/Projects/UOContent/Items/Quivers/BaseQuiver.cs +++ b/Projects/UOContent/Items/Quivers/BaseQuiver.cs @@ -3,439 +3,449 @@ using Server.Engines.Craft; namespace Server.Items { - public class BaseQuiver : Container, ICraftable - { - private static readonly Type[] m_Ammo = + public class BaseQuiver : Container, ICraftable { - typeof(Arrow), typeof(Bolt) - }; + private static readonly Type[] m_Ammo = + { + typeof(Arrow), typeof(Bolt) + }; - private int m_Capacity; + private int m_Capacity; - private Mobile m_Crafter; - private int m_DamageIncrease; - private int m_LowerAmmoCost; - private ClothingQuality m_Quality; - private int m_WeightReduction; + private Mobile m_Crafter; + private int m_DamageIncrease; + private int m_LowerAmmoCost; + private ClothingQuality m_Quality; + private int m_WeightReduction; - public BaseQuiver(int itemID = 0x2FB7) : base(itemID) - { - Weight = 2.0; - Capacity = 500; - Layer = Layer.Cloak; + public BaseQuiver(int itemID = 0x2FB7) : base(itemID) + { + Weight = 2.0; + Capacity = 500; + Layer = Layer.Cloak; - Attributes = new AosAttributes(this); + Attributes = new AosAttributes(this); - DamageIncrease = 10; + DamageIncrease = 10; + } + + public BaseQuiver(Serial serial) : base(serial) + { + } + + public override int DefaultGumpID => 0x108; + public override int DefaultMaxItems => 1; + public override int DefaultMaxWeight => 50; + public override double DefaultWeight => 2.0; + + [CommandProperty(AccessLevel.GameMaster)] + public AosAttributes Attributes { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Capacity + { + get => m_Capacity; + set + { + m_Capacity = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int LowerAmmoCost + { + get => m_LowerAmmoCost; + set + { + m_LowerAmmoCost = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int WeightReduction + { + get => m_WeightReduction; + set + { + m_WeightReduction = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int DamageIncrease + { + get => m_DamageIncrease; + set + { + m_DamageIncrease = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Crafter + { + get => m_Crafter; + set + { + m_Crafter = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public ClothingQuality Quality + { + get => m_Quality; + set + { + m_Quality = value; + InvalidateProperties(); + } + } + + public Item Ammo => Items.Count > 0 ? Items[0] : null; + + public virtual int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, + BaseTool tool, CraftItem craftItem, int resHue + ) + { + Quality = (ClothingQuality)quality; + + if (makersMark) + Crafter = from; + + return quality; + } + + public override void OnAfterDuped(Item newItem) + { + if (!(newItem is BaseQuiver quiver)) + return; + + quiver.Attributes = new AosAttributes(newItem, Attributes); + } + + public override void UpdateTotal(Item sender, TotalType type, int delta) + { + InvalidateProperties(); + + base.UpdateTotal(sender, type, delta); + } + + public override int GetTotal(TotalType type) + { + var total = base.GetTotal(type); + + if (type == TotalType.Weight) + total -= total * m_WeightReduction / 100; + + return total; + } + + public bool CheckType(Item item) + { + var type = item.GetType(); + var ammo = Ammo; + + if (ammo != null) + { + if (ammo.GetType() == type) + return true; + } + else + { + for (var i = 0; i < m_Ammo.Length; i++) + if (type == m_Ammo[i]) + return true; + } + + return false; + } + + public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight) + { + if (CheckType(item)) + return Items.Count >= DefaultMaxItems && !checkItems && Ammo?.Deleted == false && + Ammo.Amount + item.Amount <= m_Capacity || item.Amount <= m_Capacity && + base.CheckHold(m, item, message, checkItems, plusItems, plusWeight); + + if (message) + m.SendLocalizedMessage(1074836); // The container can not hold that type of object. + + return false; + } + + public override void AddItem(Item dropped) + { + base.AddItem(dropped); + + InvalidateWeight(); + } + + public override void RemoveItem(Item dropped) + { + base.RemoveItem(dropped); + + InvalidateWeight(); + } + + public override void OnAdded(IEntity parent) + { + if (parent is Mobile mob) Attributes.AddStatBonuses(mob); + } + + public override void OnRemoved(IEntity parent) + { + if (parent is Mobile mob) Attributes.RemoveStatBonuses(mob); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_Crafter != null) + list.Add(1050043, m_Crafter.Name); // crafted by ~1_NAME~ + + if (m_Quality == ClothingQuality.Exceptional) + list.Add(1063341); // exceptional + + var ammo = Ammo; + + if (ammo != null) + { + if (ammo is Arrow) + list.Add(1075265, "{0}\t{1}", ammo.Amount, Capacity); // Ammo: ~1_QUANTITY~/~2_CAPACITY~ arrows + else if (ammo is Bolt) + list.Add(1075266, "{0}\t{1}", ammo.Amount, Capacity); // Ammo: ~1_QUANTITY~/~2_CAPACITY~ bolts + } + else + { + list.Add(1075265, "{0}\t{1}", 0, Capacity); // Ammo: ~1_QUANTITY~/~2_CAPACITY~ arrows + } + + int prop; + + if ((prop = m_DamageIncrease) != 0) + list.Add(1074762, prop.ToString()); // Damage modifier: ~1_PERCENT~% + + int phys, fire, cold, pois, nrgy, chaos, direct; + phys = fire = cold = pois = nrgy = chaos = direct = 0; + + AlterBowDamage(ref phys, ref fire, ref cold, ref pois, ref nrgy, ref chaos, ref direct); + + if (phys != 0) + list.Add(1060403, phys.ToString()); // physical damage ~1_val~% + + if (fire != 0) + list.Add(1060405, fire.ToString()); // fire damage ~1_val~% + + if (cold != 0) + list.Add(1060404, cold.ToString()); // cold damage ~1_val~% + + if (pois != 0) + list.Add(1060406, pois.ToString()); // poison damage ~1_val~% + + if (nrgy != 0) + list.Add(1060407, nrgy.ToString()); // energy damage ~1_val + + if (chaos != 0) + list.Add(1072846, chaos.ToString()); // chaos damage ~1_val~% + + if (direct != 0) + list.Add(1079978, direct.ToString()); // Direct Damage: ~1_PERCENT~% + + list.Add(1075085); // Requirement: Mondain's Legacy + + if ((prop = Attributes.DefendChance) != 0) + list.Add(1060408, prop.ToString()); // defense chance increase ~1_val~% + + if ((prop = Attributes.BonusDex) != 0) + list.Add(1060409, prop.ToString()); // dexterity bonus ~1_val~ + + if ((prop = Attributes.EnhancePotions) != 0) + list.Add(1060411, prop.ToString()); // enhance potions ~1_val~% + + if ((prop = Attributes.CastRecovery) != 0) + list.Add(1060412, prop.ToString()); // faster cast recovery ~1_val~ + + if ((prop = Attributes.CastSpeed) != 0) + list.Add(1060413, prop.ToString()); // faster casting ~1_val~ + + if ((prop = Attributes.AttackChance) != 0) + list.Add(1060415, prop.ToString()); // hit chance increase ~1_val~% + + if ((prop = Attributes.BonusHits) != 0) + list.Add(1060431, prop.ToString()); // hit point increase ~1_val~ + + if ((prop = Attributes.BonusInt) != 0) + list.Add(1060432, prop.ToString()); // intelligence bonus ~1_val~ + + if ((prop = Attributes.LowerManaCost) != 0) + list.Add(1060433, prop.ToString()); // lower mana cost ~1_val~% + + if ((prop = Attributes.LowerRegCost) != 0) + list.Add(1060434, prop.ToString()); // lower reagent cost ~1_val~% + + if ((prop = Attributes.Luck) != 0) + list.Add(1060436, prop.ToString()); // luck ~1_val~ + + if ((prop = Attributes.BonusMana) != 0) + list.Add(1060439, prop.ToString()); // mana increase ~1_val~ + + if ((prop = Attributes.RegenMana) != 0) + list.Add(1060440, prop.ToString()); // mana regeneration ~1_val~ + + if ((prop = Attributes.NightSight) != 0) + list.Add(1060441); // night sight + + if ((prop = Attributes.ReflectPhysical) != 0) + list.Add(1060442, prop.ToString()); // reflect physical damage ~1_val~% + + if ((prop = Attributes.RegenStam) != 0) + list.Add(1060443, prop.ToString()); // stamina regeneration ~1_val~ + + if ((prop = Attributes.RegenHits) != 0) + list.Add(1060444, prop.ToString()); // hit point regeneration ~1_val~ + + if ((prop = Attributes.SpellDamage) != 0) + list.Add(1060483, prop.ToString()); // spell damage increase ~1_val~% + + if ((prop = Attributes.BonusStam) != 0) + list.Add(1060484, prop.ToString()); // stamina increase ~1_val~ + + if ((prop = Attributes.BonusStr) != 0) + list.Add(1060485, prop.ToString()); // strength bonus ~1_val~ + + if ((prop = Attributes.WeaponSpeed) != 0) + list.Add(1060486, prop.ToString()); // swing speed increase ~1_val~% + + if ((prop = m_LowerAmmoCost) > 0) + list.Add(1075208, prop.ToString()); // Lower Ammo Cost ~1_Percentage~% + + var weight = ammo != null ? ammo.Weight + ammo.Amount : 0; + + list.Add( + 1072241, + "{0}\t{1}\t{2}\t{3}", + Items.Count, + DefaultMaxItems, + (int)weight, + DefaultMaxWeight + ); // Contents: ~1_COUNT~/~2_MAXCOUNT items, ~3_WEIGHT~/~4_MAXWEIGHT~ stones + + if ((prop = m_WeightReduction) != 0) + list.Add(1072210, prop.ToString()); // Weight reduction: ~1_PERCENTAGE~% + } + + private static void SetSaveFlag(ref SaveFlag flags, SaveFlag toSet, bool setIf) + { + if (setIf) + flags |= toSet; + } + + private static bool GetSaveFlag(SaveFlag flags, SaveFlag toGet) => (flags & toGet) != 0; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + var flags = SaveFlag.None; + + SetSaveFlag(ref flags, SaveFlag.Attributes, !Attributes.IsEmpty); + SetSaveFlag(ref flags, SaveFlag.LowerAmmoCost, m_LowerAmmoCost != 0); + SetSaveFlag(ref flags, SaveFlag.WeightReduction, m_WeightReduction != 0); + SetSaveFlag(ref flags, SaveFlag.DamageIncrease, m_DamageIncrease != 0); + SetSaveFlag(ref flags, SaveFlag.Crafter, m_Crafter != null); + SetSaveFlag(ref flags, SaveFlag.Quality, true); + SetSaveFlag(ref flags, SaveFlag.Capacity, m_Capacity > 0); + + writer.WriteEncodedInt((int)flags); + + if (GetSaveFlag(flags, SaveFlag.Attributes)) + Attributes.Serialize(writer); + + if (GetSaveFlag(flags, SaveFlag.LowerAmmoCost)) + writer.Write(m_LowerAmmoCost); + + if (GetSaveFlag(flags, SaveFlag.WeightReduction)) + writer.Write(m_WeightReduction); + + if (GetSaveFlag(flags, SaveFlag.DamageIncrease)) + writer.Write(m_DamageIncrease); + + if (GetSaveFlag(flags, SaveFlag.Crafter)) + writer.Write(m_Crafter); + + if (GetSaveFlag(flags, SaveFlag.Quality)) + writer.Write((int)m_Quality); + + if (GetSaveFlag(flags, SaveFlag.Capacity)) + writer.Write(m_Capacity); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + var flags = (SaveFlag)reader.ReadEncodedInt(); + + if (GetSaveFlag(flags, SaveFlag.Attributes)) + Attributes = new AosAttributes(this, reader); + else + Attributes = new AosAttributes(this); + + if (GetSaveFlag(flags, SaveFlag.LowerAmmoCost)) + m_LowerAmmoCost = reader.ReadInt(); + + if (GetSaveFlag(flags, SaveFlag.WeightReduction)) + m_WeightReduction = reader.ReadInt(); + + if (GetSaveFlag(flags, SaveFlag.DamageIncrease)) + m_DamageIncrease = reader.ReadInt(); + + if (GetSaveFlag(flags, SaveFlag.Crafter)) + m_Crafter = reader.ReadMobile(); + + if (GetSaveFlag(flags, SaveFlag.Quality)) + m_Quality = (ClothingQuality)reader.ReadInt(); + + if (GetSaveFlag(flags, SaveFlag.Capacity)) + m_Capacity = reader.ReadInt(); + } + + public virtual void AlterBowDamage( + ref int phys, ref int fire, ref int cold, ref int pois, ref int nrgy, + ref int chaos, ref int direct + ) + { + } + + public void InvalidateWeight() + { + if (RootParent is Mobile m) m.UpdateTotals(); + } + + [Flags] + private enum SaveFlag + { + None = 0x00000000, + Attributes = 0x00000001, + DamageModifier = 0x00000002, + LowerAmmoCost = 0x00000004, + WeightReduction = 0x00000008, + Crafter = 0x00000010, + Quality = 0x00000020, + Capacity = 0x00000040, + DamageIncrease = 0x00000080 + } } - - public BaseQuiver(Serial serial) : base(serial) - { - } - - public override int DefaultGumpID => 0x108; - public override int DefaultMaxItems => 1; - public override int DefaultMaxWeight => 50; - public override double DefaultWeight => 2.0; - - [CommandProperty(AccessLevel.GameMaster)] - public AosAttributes Attributes { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Capacity - { - get => m_Capacity; - set - { - m_Capacity = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int LowerAmmoCost - { - get => m_LowerAmmoCost; - set - { - m_LowerAmmoCost = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int WeightReduction - { - get => m_WeightReduction; - set - { - m_WeightReduction = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int DamageIncrease - { - get => m_DamageIncrease; - set - { - m_DamageIncrease = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Crafter - { - get => m_Crafter; - set - { - m_Crafter = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public ClothingQuality Quality - { - get => m_Quality; - set - { - m_Quality = value; - InvalidateProperties(); - } - } - - public Item Ammo => Items.Count > 0 ? Items[0] : null; - - public virtual int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, - BaseTool tool, CraftItem craftItem, int resHue) - { - Quality = (ClothingQuality)quality; - - if (makersMark) - Crafter = from; - - return quality; - } - - public override void OnAfterDuped(Item newItem) - { - if (!(newItem is BaseQuiver quiver)) - return; - - quiver.Attributes = new AosAttributes(newItem, Attributes); - } - - public override void UpdateTotal(Item sender, TotalType type, int delta) - { - InvalidateProperties(); - - base.UpdateTotal(sender, type, delta); - } - - public override int GetTotal(TotalType type) - { - int total = base.GetTotal(type); - - if (type == TotalType.Weight) - total -= total * m_WeightReduction / 100; - - return total; - } - - public bool CheckType(Item item) - { - Type type = item.GetType(); - Item ammo = Ammo; - - if (ammo != null) - { - if (ammo.GetType() == type) - return true; - } - else - { - for (int i = 0; i < m_Ammo.Length; i++) - if (type == m_Ammo[i]) - return true; - } - - return false; - } - - public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight) - { - if (CheckType(item)) - return (Items.Count >= DefaultMaxItems && !checkItems && Ammo?.Deleted == false && - Ammo.Amount + item.Amount <= m_Capacity) || (item.Amount <= m_Capacity && - base.CheckHold(m, item, message, checkItems, plusItems, plusWeight)); - - if (message) - m.SendLocalizedMessage(1074836); // The container can not hold that type of object. - - return false; - } - - public override void AddItem(Item dropped) - { - base.AddItem(dropped); - - InvalidateWeight(); - } - - public override void RemoveItem(Item dropped) - { - base.RemoveItem(dropped); - - InvalidateWeight(); - } - - public override void OnAdded(IEntity parent) - { - if (parent is Mobile mob) Attributes.AddStatBonuses(mob); - } - - public override void OnRemoved(IEntity parent) - { - if (parent is Mobile mob) Attributes.RemoveStatBonuses(mob); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_Crafter != null) - list.Add(1050043, m_Crafter.Name); // crafted by ~1_NAME~ - - if (m_Quality == ClothingQuality.Exceptional) - list.Add(1063341); // exceptional - - Item ammo = Ammo; - - if (ammo != null) - { - if (ammo is Arrow) - list.Add(1075265, "{0}\t{1}", ammo.Amount, Capacity); // Ammo: ~1_QUANTITY~/~2_CAPACITY~ arrows - else if (ammo is Bolt) - list.Add(1075266, "{0}\t{1}", ammo.Amount, Capacity); // Ammo: ~1_QUANTITY~/~2_CAPACITY~ bolts - } - else - { - list.Add(1075265, "{0}\t{1}", 0, Capacity); // Ammo: ~1_QUANTITY~/~2_CAPACITY~ arrows - } - - int prop; - - if ((prop = m_DamageIncrease) != 0) - list.Add(1074762, prop.ToString()); // Damage modifier: ~1_PERCENT~% - - int phys, fire, cold, pois, nrgy, chaos, direct; - phys = fire = cold = pois = nrgy = chaos = direct = 0; - - AlterBowDamage(ref phys, ref fire, ref cold, ref pois, ref nrgy, ref chaos, ref direct); - - if (phys != 0) - list.Add(1060403, phys.ToString()); // physical damage ~1_val~% - - if (fire != 0) - list.Add(1060405, fire.ToString()); // fire damage ~1_val~% - - if (cold != 0) - list.Add(1060404, cold.ToString()); // cold damage ~1_val~% - - if (pois != 0) - list.Add(1060406, pois.ToString()); // poison damage ~1_val~% - - if (nrgy != 0) - list.Add(1060407, nrgy.ToString()); // energy damage ~1_val - - if (chaos != 0) - list.Add(1072846, chaos.ToString()); // chaos damage ~1_val~% - - if (direct != 0) - list.Add(1079978, direct.ToString()); // Direct Damage: ~1_PERCENT~% - - list.Add(1075085); // Requirement: Mondain's Legacy - - if ((prop = Attributes.DefendChance) != 0) - list.Add(1060408, prop.ToString()); // defense chance increase ~1_val~% - - if ((prop = Attributes.BonusDex) != 0) - list.Add(1060409, prop.ToString()); // dexterity bonus ~1_val~ - - if ((prop = Attributes.EnhancePotions) != 0) - list.Add(1060411, prop.ToString()); // enhance potions ~1_val~% - - if ((prop = Attributes.CastRecovery) != 0) - list.Add(1060412, prop.ToString()); // faster cast recovery ~1_val~ - - if ((prop = Attributes.CastSpeed) != 0) - list.Add(1060413, prop.ToString()); // faster casting ~1_val~ - - if ((prop = Attributes.AttackChance) != 0) - list.Add(1060415, prop.ToString()); // hit chance increase ~1_val~% - - if ((prop = Attributes.BonusHits) != 0) - list.Add(1060431, prop.ToString()); // hit point increase ~1_val~ - - if ((prop = Attributes.BonusInt) != 0) - list.Add(1060432, prop.ToString()); // intelligence bonus ~1_val~ - - if ((prop = Attributes.LowerManaCost) != 0) - list.Add(1060433, prop.ToString()); // lower mana cost ~1_val~% - - if ((prop = Attributes.LowerRegCost) != 0) - list.Add(1060434, prop.ToString()); // lower reagent cost ~1_val~% - - if ((prop = Attributes.Luck) != 0) - list.Add(1060436, prop.ToString()); // luck ~1_val~ - - if ((prop = Attributes.BonusMana) != 0) - list.Add(1060439, prop.ToString()); // mana increase ~1_val~ - - if ((prop = Attributes.RegenMana) != 0) - list.Add(1060440, prop.ToString()); // mana regeneration ~1_val~ - - if ((prop = Attributes.NightSight) != 0) - list.Add(1060441); // night sight - - if ((prop = Attributes.ReflectPhysical) != 0) - list.Add(1060442, prop.ToString()); // reflect physical damage ~1_val~% - - if ((prop = Attributes.RegenStam) != 0) - list.Add(1060443, prop.ToString()); // stamina regeneration ~1_val~ - - if ((prop = Attributes.RegenHits) != 0) - list.Add(1060444, prop.ToString()); // hit point regeneration ~1_val~ - - if ((prop = Attributes.SpellDamage) != 0) - list.Add(1060483, prop.ToString()); // spell damage increase ~1_val~% - - if ((prop = Attributes.BonusStam) != 0) - list.Add(1060484, prop.ToString()); // stamina increase ~1_val~ - - if ((prop = Attributes.BonusStr) != 0) - list.Add(1060485, prop.ToString()); // strength bonus ~1_val~ - - if ((prop = Attributes.WeaponSpeed) != 0) - list.Add(1060486, prop.ToString()); // swing speed increase ~1_val~% - - if ((prop = m_LowerAmmoCost) > 0) - list.Add(1075208, prop.ToString()); // Lower Ammo Cost ~1_Percentage~% - - double weight = ammo != null ? ammo.Weight + ammo.Amount : 0; - - list.Add(1072241, "{0}\t{1}\t{2}\t{3}", Items.Count, DefaultMaxItems, (int)weight, - DefaultMaxWeight); // Contents: ~1_COUNT~/~2_MAXCOUNT items, ~3_WEIGHT~/~4_MAXWEIGHT~ stones - - if ((prop = m_WeightReduction) != 0) - list.Add(1072210, prop.ToString()); // Weight reduction: ~1_PERCENTAGE~% - } - - private static void SetSaveFlag(ref SaveFlag flags, SaveFlag toSet, bool setIf) - { - if (setIf) - flags |= toSet; - } - - private static bool GetSaveFlag(SaveFlag flags, SaveFlag toGet) => (flags & toGet) != 0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - SaveFlag flags = SaveFlag.None; - - SetSaveFlag(ref flags, SaveFlag.Attributes, !Attributes.IsEmpty); - SetSaveFlag(ref flags, SaveFlag.LowerAmmoCost, m_LowerAmmoCost != 0); - SetSaveFlag(ref flags, SaveFlag.WeightReduction, m_WeightReduction != 0); - SetSaveFlag(ref flags, SaveFlag.DamageIncrease, m_DamageIncrease != 0); - SetSaveFlag(ref flags, SaveFlag.Crafter, m_Crafter != null); - SetSaveFlag(ref flags, SaveFlag.Quality, true); - SetSaveFlag(ref flags, SaveFlag.Capacity, m_Capacity > 0); - - writer.WriteEncodedInt((int)flags); - - if (GetSaveFlag(flags, SaveFlag.Attributes)) - Attributes.Serialize(writer); - - if (GetSaveFlag(flags, SaveFlag.LowerAmmoCost)) - writer.Write(m_LowerAmmoCost); - - if (GetSaveFlag(flags, SaveFlag.WeightReduction)) - writer.Write(m_WeightReduction); - - if (GetSaveFlag(flags, SaveFlag.DamageIncrease)) - writer.Write(m_DamageIncrease); - - if (GetSaveFlag(flags, SaveFlag.Crafter)) - writer.Write(m_Crafter); - - if (GetSaveFlag(flags, SaveFlag.Quality)) - writer.Write((int)m_Quality); - - if (GetSaveFlag(flags, SaveFlag.Capacity)) - writer.Write(m_Capacity); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - SaveFlag flags = (SaveFlag)reader.ReadEncodedInt(); - - if (GetSaveFlag(flags, SaveFlag.Attributes)) - Attributes = new AosAttributes(this, reader); - else - Attributes = new AosAttributes(this); - - if (GetSaveFlag(flags, SaveFlag.LowerAmmoCost)) - m_LowerAmmoCost = reader.ReadInt(); - - if (GetSaveFlag(flags, SaveFlag.WeightReduction)) - m_WeightReduction = reader.ReadInt(); - - if (GetSaveFlag(flags, SaveFlag.DamageIncrease)) - m_DamageIncrease = reader.ReadInt(); - - if (GetSaveFlag(flags, SaveFlag.Crafter)) - m_Crafter = reader.ReadMobile(); - - if (GetSaveFlag(flags, SaveFlag.Quality)) - m_Quality = (ClothingQuality)reader.ReadInt(); - - if (GetSaveFlag(flags, SaveFlag.Capacity)) - m_Capacity = reader.ReadInt(); - } - - public virtual void AlterBowDamage(ref int phys, ref int fire, ref int cold, ref int pois, ref int nrgy, - ref int chaos, ref int direct) - { - } - - public void InvalidateWeight() - { - if (RootParent is Mobile m) m.UpdateTotals(); - } - - [Flags] - private enum SaveFlag - { - None = 0x00000000, - Attributes = 0x00000001, - DamageModifier = 0x00000002, - LowerAmmoCost = 0x00000004, - WeightReduction = 0x00000008, - Crafter = 0x00000010, - Quality = 0x00000020, - Capacity = 0x00000040, - DamageIncrease = 0x00000080 - } - } } diff --git a/Projects/UOContent/Items/Quivers/ElvenQuiver.cs b/Projects/UOContent/Items/Quivers/ElvenQuiver.cs index b02776ddf..fe51e2256 100644 --- a/Projects/UOContent/Items/Quivers/ElvenQuiver.cs +++ b/Projects/UOContent/Items/Quivers/ElvenQuiver.cs @@ -1,29 +1,29 @@ namespace Server.Items { - [Flippable(0x2FB7, 0x3171)] - public class ElvenQuiver : BaseQuiver - { - [Constructible] - public ElvenQuiver() => WeightReduction = 30; - - public ElvenQuiver(Serial serial) : base(serial) + [Flippable(0x2FB7, 0x3171)] + public class ElvenQuiver : BaseQuiver { + [Constructible] + public ElvenQuiver() => WeightReduction = 30; + + public ElvenQuiver(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1032657; // elven quiver + + 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(); + } } - - public override int LabelNumber => 1032657; // elven quiver - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Quivers/QuiverOfBlight.cs b/Projects/UOContent/Items/Quivers/QuiverOfBlight.cs index 0ff971e32..c0ed1bd11 100644 --- a/Projects/UOContent/Items/Quivers/QuiverOfBlight.cs +++ b/Projects/UOContent/Items/Quivers/QuiverOfBlight.cs @@ -1,35 +1,37 @@ namespace Server.Items { - public class QuiverOfBlight : ElvenQuiver - { - [Constructible] - public QuiverOfBlight() => Hue = 0x4F3; - - public QuiverOfBlight(Serial serial) : base(serial) + public class QuiverOfBlight : ElvenQuiver { + [Constructible] + public QuiverOfBlight() => Hue = 0x4F3; + + public QuiverOfBlight(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073111; // Quiver of Blight + + public override void AlterBowDamage( + ref int phys, ref int fire, ref int cold, ref int pois, ref int nrgy, + ref int chaos, ref int direct + ) + { + phys = fire = nrgy = chaos = direct = 0; + cold = pois = 50; + } + + 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(); + } } - - public override int LabelNumber => 1073111; // Quiver of Blight - - public override void AlterBowDamage(ref int phys, ref int fire, ref int cold, ref int pois, ref int nrgy, - ref int chaos, ref int direct) - { - phys = fire = nrgy = chaos = direct = 0; - cold = pois = 50; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Quivers/QuiverOfFire.cs b/Projects/UOContent/Items/Quivers/QuiverOfFire.cs index c4b16098e..8caf6aa2a 100644 --- a/Projects/UOContent/Items/Quivers/QuiverOfFire.cs +++ b/Projects/UOContent/Items/Quivers/QuiverOfFire.cs @@ -1,35 +1,37 @@ namespace Server.Items { - public class QuiverOfFire : ElvenQuiver - { - [Constructible] - public QuiverOfFire() => Hue = 0x4E7; - - public QuiverOfFire(Serial serial) : base(serial) + public class QuiverOfFire : ElvenQuiver { + [Constructible] + public QuiverOfFire() => Hue = 0x4E7; + + public QuiverOfFire(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073109; // quiver of fire + + public override void AlterBowDamage( + ref int phys, ref int fire, ref int cold, ref int pois, ref int nrgy, + ref int chaos, ref int direct + ) + { + cold = pois = nrgy = chaos = direct = 0; + phys = fire = 50; + } + + 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(); + } } - - public override int LabelNumber => 1073109; // quiver of fire - - public override void AlterBowDamage(ref int phys, ref int fire, ref int cold, ref int pois, ref int nrgy, - ref int chaos, ref int direct) - { - cold = pois = nrgy = chaos = direct = 0; - phys = fire = 50; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Quivers/QuiverOfIce.cs b/Projects/UOContent/Items/Quivers/QuiverOfIce.cs index 04dfe509f..281519a7a 100644 --- a/Projects/UOContent/Items/Quivers/QuiverOfIce.cs +++ b/Projects/UOContent/Items/Quivers/QuiverOfIce.cs @@ -1,35 +1,37 @@ namespace Server.Items { - public class QuiverOfIce : ElvenQuiver - { - [Constructible] - public QuiverOfIce() => Hue = 0x4ED; - - public QuiverOfIce(Serial serial) : base(serial) + public class QuiverOfIce : ElvenQuiver { + [Constructible] + public QuiverOfIce() => Hue = 0x4ED; + + public QuiverOfIce(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073110; // quiver of ice + + public override void AlterBowDamage( + ref int phys, ref int fire, ref int cold, ref int pois, ref int nrgy, + ref int chaos, ref int direct + ) + { + fire = pois = nrgy = chaos = direct = 0; + phys = cold = 50; + } + + 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(); + } } - - public override int LabelNumber => 1073110; // quiver of ice - - public override void AlterBowDamage(ref int phys, ref int fire, ref int cold, ref int pois, ref int nrgy, - ref int chaos, ref int direct) - { - fire = pois = nrgy = chaos = direct = 0; - phys = cold = 50; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Quivers/QuiverOfLightning.cs b/Projects/UOContent/Items/Quivers/QuiverOfLightning.cs index 80e1adff9..d00563ab0 100644 --- a/Projects/UOContent/Items/Quivers/QuiverOfLightning.cs +++ b/Projects/UOContent/Items/Quivers/QuiverOfLightning.cs @@ -1,35 +1,37 @@ namespace Server.Items { - public class QuiverOfLightning : ElvenQuiver - { - [Constructible] - public QuiverOfLightning() => Hue = 0x4F9; - - public QuiverOfLightning(Serial serial) : base(serial) + public class QuiverOfLightning : ElvenQuiver { + [Constructible] + public QuiverOfLightning() => Hue = 0x4F9; + + public QuiverOfLightning(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073112; // Quiver of Lightning + + public override void AlterBowDamage( + ref int phys, ref int fire, ref int cold, ref int pois, ref int nrgy, + ref int chaos, ref int direct + ) + { + fire = cold = pois = chaos = direct = 0; + phys = nrgy = 50; + } + + 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(); + } } - - public override int LabelNumber => 1073112; // Quiver of Lightning - - public override void AlterBowDamage(ref int phys, ref int fire, ref int cold, ref int pois, ref int nrgy, - ref int chaos, ref int direct) - { - fire = cold = pois = chaos = direct = 0; - phys = nrgy = 50; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Resources/Arrows/Arrow.cs b/Projects/UOContent/Items/Resources/Arrows/Arrow.cs index 677f386bc..404d0a652 100644 --- a/Projects/UOContent/Items/Resources/Arrows/Arrow.cs +++ b/Projects/UOContent/Items/Resources/Arrows/Arrow.cs @@ -1,34 +1,34 @@ namespace Server.Items { - public class Arrow : Item, ICommodity - { - [Constructible] - public Arrow(int amount = 1) : base(0xF3F) + public class Arrow : Item, ICommodity { - Stackable = true; - Amount = amount; + [Constructible] + public Arrow(int amount = 1) : base(0xF3F) + { + Stackable = true; + Amount = amount; + } + + public Arrow(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0.1; + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + 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 Arrow(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.1; - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Arrows/Bolt.cs b/Projects/UOContent/Items/Resources/Arrows/Bolt.cs index 9ca227b1f..e10125a05 100644 --- a/Projects/UOContent/Items/Resources/Arrows/Bolt.cs +++ b/Projects/UOContent/Items/Resources/Arrows/Bolt.cs @@ -1,34 +1,34 @@ namespace Server.Items { - public class Bolt : Item, ICommodity - { - [Constructible] - public Bolt(int amount = 1) : base(0x1BFB) + public class Bolt : Item, ICommodity { - Stackable = true; - Amount = amount; + [Constructible] + public Bolt(int amount = 1) : base(0x1BFB) + { + Stackable = true; + Amount = amount; + } + + public Bolt(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0.1; + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + 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 Bolt(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.1; - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Arrows/Feather.cs b/Projects/UOContent/Items/Resources/Arrows/Feather.cs index a017d5130..7dcafa12e 100644 --- a/Projects/UOContent/Items/Resources/Arrows/Feather.cs +++ b/Projects/UOContent/Items/Resources/Arrows/Feather.cs @@ -1,34 +1,34 @@ namespace Server.Items { - public class Feather : Item, ICommodity - { - [Constructible] - public Feather(int amount = 1) : base(0x1BD1) + public class Feather : Item, ICommodity { - Stackable = true; - Amount = amount; + [Constructible] + public Feather(int amount = 1) : base(0x1BD1) + { + Stackable = true; + Amount = amount; + } + + public Feather(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0.1; + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + 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 Feather(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.1; - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Arrows/Shaft.cs b/Projects/UOContent/Items/Resources/Arrows/Shaft.cs index 04498c1f0..d8ef6ba2e 100644 --- a/Projects/UOContent/Items/Resources/Arrows/Shaft.cs +++ b/Projects/UOContent/Items/Resources/Arrows/Shaft.cs @@ -1,34 +1,34 @@ namespace Server.Items { - public class Shaft : Item, ICommodity - { - [Constructible] - public Shaft(int amount = 1) : base(0x1BD4) + public class Shaft : Item, ICommodity { - Stackable = true; - Amount = amount; + [Constructible] + public Shaft(int amount = 1) : base(0x1BD4) + { + Stackable = true; + Amount = amount; + } + + public Shaft(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0.1; + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + 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 Shaft(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.1; - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Blacksmithing/Ingots.cs b/Projects/UOContent/Items/Resources/Blacksmithing/Ingots.cs index bd90dc813..23a37bd2e 100644 --- a/Projects/UOContent/Items/Resources/Blacksmithing/Ingots.cs +++ b/Projects/UOContent/Items/Resources/Blacksmithing/Ingots.cs @@ -1,357 +1,357 @@ namespace Server.Items { - public abstract class BaseIngot : Item, ICommodity - { - private CraftResource m_Resource; - - public BaseIngot(CraftResource resource, int amount = 1) : base(0x1BF2) + public abstract class BaseIngot : Item, ICommodity { - Stackable = true; - Amount = amount; - Hue = CraftResources.GetHue(resource); + private CraftResource m_Resource; - m_Resource = resource; - } + public BaseIngot(CraftResource resource, int amount = 1) : base(0x1BF2) + { + Stackable = true; + Amount = amount; + Hue = CraftResources.GetHue(resource); - public BaseIngot(Serial serial) : base(serial) - { - } + m_Resource = resource; + } - [CommandProperty(AccessLevel.GameMaster)] - public CraftResource Resource - { - get => m_Resource; - set - { - m_Resource = value; - InvalidateProperties(); - } - } + public BaseIngot(Serial serial) : base(serial) + { + } - public override double DefaultWeight => 0.1; - - public override int LabelNumber - { - get - { - if (m_Resource >= CraftResource.DullCopper && m_Resource <= CraftResource.Valorite) - return 1042684 + (m_Resource - CraftResource.DullCopper); - - return 1042692; - } - } - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write((int)m_Resource); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_Resource = (CraftResource)reader.ReadInt(); - break; - } - case 0: - { - var info = reader.ReadInt() switch + [CommandProperty(AccessLevel.GameMaster)] + public CraftResource Resource + { + get => m_Resource; + set { - 0 => OreInfo.Iron, - 1 => OreInfo.DullCopper, - 2 => OreInfo.ShadowIron, - 3 => OreInfo.Copper, - 4 => OreInfo.Bronze, - 5 => OreInfo.Gold, - 6 => OreInfo.Agapite, - 7 => OreInfo.Verite, - 8 => OreInfo.Valorite, - _ => null - }; + m_Resource = value; + InvalidateProperties(); + } + } - m_Resource = CraftResources.GetFromOreInfo(info); - break; - } - } + public override double DefaultWeight => 0.1; + + public override int LabelNumber + { + get + { + if (m_Resource >= CraftResource.DullCopper && m_Resource <= CraftResource.Valorite) + return 1042684 + (m_Resource - CraftResource.DullCopper); + + return 1042692; + } + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write((int)m_Resource); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_Resource = (CraftResource)reader.ReadInt(); + break; + } + case 0: + { + var info = reader.ReadInt() switch + { + 0 => OreInfo.Iron, + 1 => OreInfo.DullCopper, + 2 => OreInfo.ShadowIron, + 3 => OreInfo.Copper, + 4 => OreInfo.Bronze, + 5 => OreInfo.Gold, + 6 => OreInfo.Agapite, + 7 => OreInfo.Verite, + 8 => OreInfo.Valorite, + _ => null + }; + + m_Resource = CraftResources.GetFromOreInfo(info); + break; + } + } + } + + public override void AddNameProperty(ObjectPropertyList list) + { + if (Amount > 1) + list.Add(1050039, "{0}\t#{1}", Amount, 1027154); // ~1_NUMBER~ ~2_ITEMNAME~ + else + list.Add(1027154); // ingots + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (!CraftResources.IsStandard(m_Resource)) + { + var num = CraftResources.GetLocalizationNumber(m_Resource); + + if (num > 0) + list.Add(num); + else + list.Add(CraftResources.GetName(m_Resource)); + } + } } - public override void AddNameProperty(ObjectPropertyList list) + [Flippable(0x1BF2, 0x1BEF)] + public class IronIngot : BaseIngot { - if (Amount > 1) - list.Add(1050039, "{0}\t#{1}", Amount, 1027154); // ~1_NUMBER~ ~2_ITEMNAME~ - else - list.Add(1027154); // ingots + [Constructible] + public IronIngot(int amount = 1) : base(CraftResource.Iron, amount) + { + } + + public IronIngot(Serial serial) : base(serial) + { + } + + 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 GetProperties(ObjectPropertyList list) + [Flippable(0x1BF2, 0x1BEF)] + public class DullCopperIngot : BaseIngot { - base.GetProperties(list); + [Constructible] + public DullCopperIngot(int amount = 1) : base(CraftResource.DullCopper, amount) + { + } - if (!CraftResources.IsStandard(m_Resource)) - { - int num = CraftResources.GetLocalizationNumber(m_Resource); + public DullCopperIngot(Serial serial) : base(serial) + { + } - if (num > 0) - list.Add(num); - else - list.Add(CraftResources.GetName(m_Resource)); - } + 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(); + } } - } - [Flippable(0x1BF2, 0x1BEF)] - public class IronIngot : BaseIngot - { - [Constructible] - public IronIngot(int amount = 1) : base(CraftResource.Iron, amount) + [Flippable(0x1BF2, 0x1BEF)] + public class ShadowIronIngot : BaseIngot { + [Constructible] + public ShadowIronIngot(int amount = 1) : base(CraftResource.ShadowIron, amount) + { + } + + public ShadowIronIngot(Serial serial) : base(serial) + { + } + + 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 IronIngot(Serial serial) : base(serial) + [Flippable(0x1BF2, 0x1BEF)] + public class CopperIngot : BaseIngot { + [Constructible] + public CopperIngot(int amount = 1) : base(CraftResource.Copper, amount) + { + } + + public CopperIngot(Serial serial) : base(serial) + { + } + + 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 Serialize(IGenericWriter writer) + [Flippable(0x1BF2, 0x1BEF)] + public class BronzeIngot : BaseIngot { - base.Serialize(writer); + [Constructible] + public BronzeIngot(int amount = 1) : base(CraftResource.Bronze, amount) + { + } - writer.Write(0); // version + public BronzeIngot(Serial serial) : base(serial) + { + } + + 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 Deserialize(IGenericReader reader) + [Flippable(0x1BF2, 0x1BEF)] + public class GoldIngot : BaseIngot { - base.Deserialize(reader); + [Constructible] + public GoldIngot(int amount = 1) : base(CraftResource.Gold, amount) + { + } - int version = reader.ReadInt(); + public GoldIngot(Serial serial) : base(serial) + { + } + + 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(); + } } - } - [Flippable(0x1BF2, 0x1BEF)] - public class DullCopperIngot : BaseIngot - { - [Constructible] - public DullCopperIngot(int amount = 1) : base(CraftResource.DullCopper, amount) + [Flippable(0x1BF2, 0x1BEF)] + public class AgapiteIngot : BaseIngot { + [Constructible] + public AgapiteIngot(int amount = 1) : base(CraftResource.Agapite, amount) + { + } + + public AgapiteIngot(Serial serial) : base(serial) + { + } + + 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 DullCopperIngot(Serial serial) : base(serial) + [Flippable(0x1BF2, 0x1BEF)] + public class VeriteIngot : BaseIngot { + [Constructible] + public VeriteIngot(int amount = 1) : base(CraftResource.Verite, amount) + { + } + + public VeriteIngot(Serial serial) : base(serial) + { + } + + 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 Serialize(IGenericWriter writer) + [Flippable(0x1BF2, 0x1BEF)] + public class ValoriteIngot : BaseIngot { - base.Serialize(writer); + [Constructible] + public ValoriteIngot(int amount = 1) : base(CraftResource.Valorite, amount) + { + } - writer.Write(0); // version + public ValoriteIngot(Serial serial) : base(serial) + { + } + + 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 Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1BF2, 0x1BEF)] - public class ShadowIronIngot : BaseIngot - { - [Constructible] - public ShadowIronIngot(int amount = 1) : base(CraftResource.ShadowIron, amount) - { - } - - public ShadowIronIngot(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1BF2, 0x1BEF)] - public class CopperIngot : BaseIngot - { - [Constructible] - public CopperIngot(int amount = 1) : base(CraftResource.Copper, amount) - { - } - - public CopperIngot(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1BF2, 0x1BEF)] - public class BronzeIngot : BaseIngot - { - [Constructible] - public BronzeIngot(int amount = 1) : base(CraftResource.Bronze, amount) - { - } - - public BronzeIngot(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1BF2, 0x1BEF)] - public class GoldIngot : BaseIngot - { - [Constructible] - public GoldIngot(int amount = 1) : base(CraftResource.Gold, amount) - { - } - - public GoldIngot(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1BF2, 0x1BEF)] - public class AgapiteIngot : BaseIngot - { - [Constructible] - public AgapiteIngot(int amount = 1) : base(CraftResource.Agapite, amount) - { - } - - public AgapiteIngot(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1BF2, 0x1BEF)] - public class VeriteIngot : BaseIngot - { - [Constructible] - public VeriteIngot(int amount = 1) : base(CraftResource.Verite, amount) - { - } - - public VeriteIngot(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1BF2, 0x1BEF)] - public class ValoriteIngot : BaseIngot - { - [Constructible] - public ValoriteIngot(int amount = 1) : base(CraftResource.Valorite, amount) - { - } - - public ValoriteIngot(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Blacksmithing/Ore.cs b/Projects/UOContent/Items/Resources/Blacksmithing/Ore.cs index d1aaf6654..445bf5d77 100644 --- a/Projects/UOContent/Items/Resources/Blacksmithing/Ore.cs +++ b/Projects/UOContent/Items/Resources/Blacksmithing/Ore.cs @@ -4,622 +4,627 @@ using Server.Targeting; namespace Server.Items { - public abstract class BaseOre : Item - { - private CraftResource m_Resource; - - public BaseOre(CraftResource resource, int amount = 1) : base(RandomSize()) + public abstract class BaseOre : Item { - Stackable = true; - Amount = amount; - Hue = CraftResources.GetHue(resource); + private CraftResource m_Resource; - m_Resource = resource; - } - - public BaseOre(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public CraftResource Resource - { - get => m_Resource; - set - { - m_Resource = value; - InvalidateProperties(); - } - } - - public override int LabelNumber - { - get - { - if (m_Resource >= CraftResource.DullCopper && m_Resource <= CraftResource.Valorite) - return 1042845 + (m_Resource - CraftResource.DullCopper); - - return 1042853; // iron ore; - } - } - - public abstract BaseIngot GetIngot(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write((int)m_Resource); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_Resource = (CraftResource)reader.ReadInt(); - break; - } - case 0: - { - var info = reader.ReadInt() switch - { - 0 => OreInfo.Iron, - 1 => OreInfo.DullCopper, - 2 => OreInfo.ShadowIron, - 3 => OreInfo.Copper, - 4 => OreInfo.Bronze, - 5 => OreInfo.Gold, - 6 => OreInfo.Agapite, - 7 => OreInfo.Verite, - 8 => OreInfo.Valorite, - _ => null - }; - - m_Resource = CraftResources.GetFromOreInfo(info); - break; - } - } - } - - private static int RandomSize() - { - double rand = Utility.RandomDouble(); - - if (rand < 0.12) - return 0x19B7; - if (rand < 0.18) - return 0x19B8; - if (rand < 0.25) - return 0x19BA; - return 0x19B9; - } - - public override bool CanStackWith(Item dropped) => - dropped.Stackable && Stackable && dropped.GetType() == GetType() && dropped.Hue == Hue && - dropped.Name == Name && dropped.Amount + Amount <= 60000 && dropped != this; - - public override void AddNameProperty(ObjectPropertyList list) - { - if (Amount > 1) - list.Add(1050039, "{0}\t#{1}", Amount, 1026583); // ~1_NUMBER~ ~2_ITEMNAME~ - else - list.Add(1026583); // ore - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (!CraftResources.IsStandard(m_Resource)) - { - int num = CraftResources.GetLocalizationNumber(m_Resource); - - if (num > 0) - list.Add(num); - else - list.Add(CraftResources.GetName(m_Resource)); - } - } - - public override void OnDoubleClick(Mobile from) - { - if (!Movable) - return; - - if (RootParent is BaseCreature) - { - from.SendLocalizedMessage(500447); // That is not accessible - } - else if (from.InRange(GetWorldLocation(), 2)) - { - from.SendLocalizedMessage( - 501971); // Select the forge on which to smelt the ore, or another pile of ore with which to combine it. - from.Target = new InternalTarget(this); - } - else - { - from.SendLocalizedMessage(501976); // The ore is too far away. - } - } - - private class InternalTarget : Target - { - private readonly BaseOre m_Ore; - - public InternalTarget(BaseOre ore) : base(2, false, TargetFlags.None) => m_Ore = ore; - - private bool IsForge(object obj) - { - if (Core.ML && obj is Mobile mobile && mobile.IsDeadBondedPet) - return false; - - if (obj.GetType().IsDefined(typeof(ForgeAttribute), false)) - return true; - - int itemID = 0; - - if (obj is Item item) - itemID = item.ItemID; - else if (obj is StaticTarget target) - itemID = target.ItemID; - - return itemID == 4017 || (itemID >= 6522 && itemID <= 6569); - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Ore.Deleted) - return; - - if (!from.InRange(m_Ore.GetWorldLocation(), 2)) + public BaseOre(CraftResource resource, int amount = 1) : base(RandomSize()) { - from.SendLocalizedMessage(501976); // The ore is too far away. - return; + Stackable = true; + Amount = amount; + Hue = CraftResources.GetHue(resource); + + m_Resource = resource; } - if (targeted is BaseOre ore) + public BaseOre(Serial serial) : base(serial) { - if (!ore.Movable) return; - if (m_Ore == ore) - { - from.SendLocalizedMessage(501972); // Select another pile or ore with which to combine this. - from.Target = new InternalTarget(ore); - return; - } + } - if (ore.Resource != m_Ore.Resource) - { - from.SendLocalizedMessage(501979); // You cannot combine ores of different metals. - return; - } - - int worth = ore.Amount; - - if (ore.ItemID == 0x19B9) - worth *= 8; - else if (ore.ItemID == 0x19B7) - worth *= 2; - else - worth *= 4; - - int sourceWorth = m_Ore.Amount; - - if (m_Ore.ItemID == 0x19B9) - sourceWorth *= 8; - else if (m_Ore.ItemID == 0x19B7) - sourceWorth *= 2; - else - sourceWorth *= 4; - - worth += sourceWorth; - - int plusWeight = 0; - int newID = ore.ItemID; - - if (ore.DefaultWeight != m_Ore.DefaultWeight) - { - if (ore.ItemID == 0x19B7 || m_Ore.ItemID == 0x19B7) + [CommandProperty(AccessLevel.GameMaster)] + public CraftResource Resource + { + get => m_Resource; + set { - newID = 0x19B7; + m_Resource = value; + InvalidateProperties(); } - else if (ore.ItemID == 0x19B9) + } + + public override int LabelNumber + { + get { - newID = m_Ore.ItemID; - plusWeight = ore.Amount * 2; + if (m_Resource >= CraftResource.DullCopper && m_Resource <= CraftResource.Valorite) + return 1042845 + (m_Resource - CraftResource.DullCopper); + + return 1042853; // iron ore; + } + } + + public abstract BaseIngot GetIngot(); + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write((int)m_Resource); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_Resource = (CraftResource)reader.ReadInt(); + break; + } + case 0: + { + var info = reader.ReadInt() switch + { + 0 => OreInfo.Iron, + 1 => OreInfo.DullCopper, + 2 => OreInfo.ShadowIron, + 3 => OreInfo.Copper, + 4 => OreInfo.Bronze, + 5 => OreInfo.Gold, + 6 => OreInfo.Agapite, + 7 => OreInfo.Verite, + 8 => OreInfo.Valorite, + _ => null + }; + + m_Resource = CraftResources.GetFromOreInfo(info); + break; + } + } + } + + private static int RandomSize() + { + var rand = Utility.RandomDouble(); + + if (rand < 0.12) + return 0x19B7; + if (rand < 0.18) + return 0x19B8; + if (rand < 0.25) + return 0x19BA; + return 0x19B9; + } + + public override bool CanStackWith(Item dropped) => + dropped.Stackable && Stackable && dropped.GetType() == GetType() && dropped.Hue == Hue && + dropped.Name == Name && dropped.Amount + Amount <= 60000 && dropped != this; + + public override void AddNameProperty(ObjectPropertyList list) + { + if (Amount > 1) + list.Add(1050039, "{0}\t#{1}", Amount, 1026583); // ~1_NUMBER~ ~2_ITEMNAME~ + else + list.Add(1026583); // ore + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (!CraftResources.IsStandard(m_Resource)) + { + var num = CraftResources.GetLocalizationNumber(m_Resource); + + if (num > 0) + list.Add(num); + else + list.Add(CraftResources.GetName(m_Resource)); + } + } + + public override void OnDoubleClick(Mobile from) + { + if (!Movable) + return; + + if (RootParent is BaseCreature) + { + from.SendLocalizedMessage(500447); // That is not accessible + } + else if (from.InRange(GetWorldLocation(), 2)) + { + from.SendLocalizedMessage( + 501971 + ); // Select the forge on which to smelt the ore, or another pile of ore with which to combine it. + from.Target = new InternalTarget(this); } else { - plusWeight = m_Ore.Amount * 2; + from.SendLocalizedMessage(501976); // The ore is too far away. } - } - - if ((ore.ItemID == 0x19B9 && worth > 120000) || - ((ore.ItemID == 0x19B8 || ore.ItemID == 0x19BA) && worth > 60000) || - (ore.ItemID == 0x19B7 && worth > 30000)) - { - from.SendLocalizedMessage(1062844); // There is too much ore to combine. - return; - } - - if (ore.RootParent is Mobile mobile && - plusWeight + mobile.Backpack.TotalWeight > mobile.Backpack.MaxWeight) - { - from.SendLocalizedMessage(501978); // The weight is too great to combine in a container. - return; - } - - ore.ItemID = newID; - - if (ore.ItemID == 0x19B9) - ore.Amount = worth / 8; - else if (ore.ItemID == 0x19B7) - ore.Amount = worth / 2; - else - ore.Amount = worth / 4; - - m_Ore.Delete(); - return; } - if (IsForge(targeted)) + private class InternalTarget : Target { - var difficulty = m_Ore.Resource switch - { - CraftResource.DullCopper => 65.0, - CraftResource.ShadowIron => 70.0, - CraftResource.Copper => 75.0, - CraftResource.Bronze => 80.0, - CraftResource.Gold => 85.0, - CraftResource.Agapite => 90.0, - CraftResource.Verite => 95.0, - CraftResource.Valorite => 99.0, - _ => 50.0 - }; + private readonly BaseOre m_Ore; - double minSkill = difficulty - 25.0; - double maxSkill = difficulty + 25.0; + public InternalTarget(BaseOre ore) : base(2, false, TargetFlags.None) => m_Ore = ore; - if (difficulty > 50.0 && difficulty > from.Skills.Mining.Value) - { - from.SendLocalizedMessage(501986); // You have no idea how to smelt this strange ore! - return; - } - - if (m_Ore.ItemID == 0x19B7 && m_Ore.Amount < 2) - { - from.SendLocalizedMessage( - 501987); // There is not enough metal-bearing ore in this pile to make an ingot. - return; - } - - if (from.CheckTargetSkill(SkillName.Mining, targeted, minSkill, maxSkill)) - { - int toConsume = m_Ore.Amount; - - if (toConsume <= 0) + private bool IsForge(object obj) { - from.SendLocalizedMessage( - 501987); // There is not enough metal-bearing ore in this pile to make an ingot. - } - else - { - if (toConsume > 30000) - toConsume = 30000; + if (Core.ML && obj is Mobile mobile && mobile.IsDeadBondedPet) + return false; - int ingotAmount; + if (obj.GetType().IsDefined(typeof(ForgeAttribute), false)) + return true; - if (m_Ore.ItemID == 0x19B7) - { - ingotAmount = toConsume / 2; + var itemID = 0; - if (toConsume % 2 != 0) - --toConsume; - } - else if (m_Ore.ItemID == 0x19B9) - { - ingotAmount = toConsume * 2; - } - else - { - ingotAmount = toConsume; - } + if (obj is Item item) + itemID = item.ItemID; + else if (obj is StaticTarget target) + itemID = target.ItemID; - BaseIngot ingot = m_Ore.GetIngot(); - ingot.Amount = ingotAmount; - - m_Ore.Consume(toConsume); - from.AddToBackpack(ingot); - // from.PlaySound( 0x57 ); - - from.SendLocalizedMessage( - 501988); // You smelt the ore removing the impurities and put the metal in your backpack. - } - } - else - { - if (m_Ore.Amount < 2) - { - if (m_Ore.ItemID == 0x19B9) - m_Ore.ItemID = 0x19B8; - else - m_Ore.ItemID = 0x19B7; - } - else - { - m_Ore.Amount /= 2; + return itemID == 4017 || itemID >= 6522 && itemID <= 6569; } - from.SendLocalizedMessage( - 501990); // You burn away the impurities but are left with less useable metal. - } + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Ore.Deleted) + return; + + if (!from.InRange(m_Ore.GetWorldLocation(), 2)) + { + from.SendLocalizedMessage(501976); // The ore is too far away. + return; + } + + if (targeted is BaseOre ore) + { + if (!ore.Movable) return; + if (m_Ore == ore) + { + from.SendLocalizedMessage(501972); // Select another pile or ore with which to combine this. + from.Target = new InternalTarget(ore); + return; + } + + if (ore.Resource != m_Ore.Resource) + { + from.SendLocalizedMessage(501979); // You cannot combine ores of different metals. + return; + } + + var worth = ore.Amount; + + if (ore.ItemID == 0x19B9) + worth *= 8; + else if (ore.ItemID == 0x19B7) + worth *= 2; + else + worth *= 4; + + var sourceWorth = m_Ore.Amount; + + if (m_Ore.ItemID == 0x19B9) + sourceWorth *= 8; + else if (m_Ore.ItemID == 0x19B7) + sourceWorth *= 2; + else + sourceWorth *= 4; + + worth += sourceWorth; + + var plusWeight = 0; + var newID = ore.ItemID; + + if (ore.DefaultWeight != m_Ore.DefaultWeight) + { + if (ore.ItemID == 0x19B7 || m_Ore.ItemID == 0x19B7) + { + newID = 0x19B7; + } + else if (ore.ItemID == 0x19B9) + { + newID = m_Ore.ItemID; + plusWeight = ore.Amount * 2; + } + else + { + plusWeight = m_Ore.Amount * 2; + } + } + + if (ore.ItemID == 0x19B9 && worth > 120000 || + (ore.ItemID == 0x19B8 || ore.ItemID == 0x19BA) && worth > 60000 || + ore.ItemID == 0x19B7 && worth > 30000) + { + from.SendLocalizedMessage(1062844); // There is too much ore to combine. + return; + } + + if (ore.RootParent is Mobile mobile && + plusWeight + mobile.Backpack.TotalWeight > mobile.Backpack.MaxWeight) + { + from.SendLocalizedMessage(501978); // The weight is too great to combine in a container. + return; + } + + ore.ItemID = newID; + + if (ore.ItemID == 0x19B9) + ore.Amount = worth / 8; + else if (ore.ItemID == 0x19B7) + ore.Amount = worth / 2; + else + ore.Amount = worth / 4; + + m_Ore.Delete(); + return; + } + + if (IsForge(targeted)) + { + var difficulty = m_Ore.Resource switch + { + CraftResource.DullCopper => 65.0, + CraftResource.ShadowIron => 70.0, + CraftResource.Copper => 75.0, + CraftResource.Bronze => 80.0, + CraftResource.Gold => 85.0, + CraftResource.Agapite => 90.0, + CraftResource.Verite => 95.0, + CraftResource.Valorite => 99.0, + _ => 50.0 + }; + + var minSkill = difficulty - 25.0; + var maxSkill = difficulty + 25.0; + + if (difficulty > 50.0 && difficulty > from.Skills.Mining.Value) + { + from.SendLocalizedMessage(501986); // You have no idea how to smelt this strange ore! + return; + } + + if (m_Ore.ItemID == 0x19B7 && m_Ore.Amount < 2) + { + from.SendLocalizedMessage( + 501987 + ); // There is not enough metal-bearing ore in this pile to make an ingot. + return; + } + + if (from.CheckTargetSkill(SkillName.Mining, targeted, minSkill, maxSkill)) + { + var toConsume = m_Ore.Amount; + + if (toConsume <= 0) + { + from.SendLocalizedMessage( + 501987 + ); // There is not enough metal-bearing ore in this pile to make an ingot. + } + else + { + if (toConsume > 30000) + toConsume = 30000; + + int ingotAmount; + + if (m_Ore.ItemID == 0x19B7) + { + ingotAmount = toConsume / 2; + + if (toConsume % 2 != 0) + --toConsume; + } + else if (m_Ore.ItemID == 0x19B9) + { + ingotAmount = toConsume * 2; + } + else + { + ingotAmount = toConsume; + } + + var ingot = m_Ore.GetIngot(); + ingot.Amount = ingotAmount; + + m_Ore.Consume(toConsume); + from.AddToBackpack(ingot); + // from.PlaySound( 0x57 ); + + from.SendLocalizedMessage( + 501988 + ); // You smelt the ore removing the impurities and put the metal in your backpack. + } + } + else + { + if (m_Ore.Amount < 2) + { + if (m_Ore.ItemID == 0x19B9) + m_Ore.ItemID = 0x19B8; + else + m_Ore.ItemID = 0x19B7; + } + else + { + m_Ore.Amount /= 2; + } + + from.SendLocalizedMessage( + 501990 + ); // You burn away the impurities but are left with less useable metal. + } + } + } } - } } - } - public class IronOre : BaseOre - { - [Constructible] - public IronOre(int amount = 1) : base(CraftResource.Iron, amount) + public class IronOre : BaseOre { + [Constructible] + public IronOre(int amount = 1) : base(CraftResource.Iron, amount) + { + } + + public IronOre(bool fixedSize) : this() + { + if (fixedSize) + ItemID = 0x19B8; + } + + public IronOre(Serial serial) : base(serial) + { + } + + 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 BaseIngot GetIngot() => new IronIngot(); } - public IronOre(bool fixedSize) : this() + public class DullCopperOre : BaseOre { - if (fixedSize) - ItemID = 0x19B8; + [Constructible] + public DullCopperOre(int amount = 1) : base(CraftResource.DullCopper, amount) + { + } + + public DullCopperOre(Serial serial) : base(serial) + { + } + + 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 BaseIngot GetIngot() => new DullCopperIngot(); } - public IronOre(Serial serial) : base(serial) + public class ShadowIronOre : BaseOre { + [Constructible] + public ShadowIronOre(int amount = 1) : base(CraftResource.ShadowIron, amount) + { + } + + public ShadowIronOre(Serial serial) : base(serial) + { + } + + 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 BaseIngot GetIngot() => new ShadowIronIngot(); } - public override void Serialize(IGenericWriter writer) + public class CopperOre : BaseOre { - base.Serialize(writer); + [Constructible] + public CopperOre(int amount = 1) : base(CraftResource.Copper, amount) + { + } - writer.Write(0); // version + public CopperOre(Serial serial) : base(serial) + { + } + + 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 BaseIngot GetIngot() => new CopperIngot(); } - public override void Deserialize(IGenericReader reader) + public class BronzeOre : BaseOre { - base.Deserialize(reader); + [Constructible] + public BronzeOre(int amount = 1) : base(CraftResource.Bronze, amount) + { + } - int version = reader.ReadInt(); + public BronzeOre(Serial serial) : base(serial) + { + } + + 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 BaseIngot GetIngot() => new BronzeIngot(); } - public override BaseIngot GetIngot() => new IronIngot(); - } - - public class DullCopperOre : BaseOre - { - [Constructible] - public DullCopperOre(int amount = 1) : base(CraftResource.DullCopper, amount) + public class GoldOre : BaseOre { + [Constructible] + public GoldOre(int amount = 1) : base(CraftResource.Gold, amount) + { + } + + public GoldOre(Serial serial) : base(serial) + { + } + + 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 BaseIngot GetIngot() => new GoldIngot(); } - public DullCopperOre(Serial serial) : base(serial) + public class AgapiteOre : BaseOre { + [Constructible] + public AgapiteOre(int amount = 1) : base(CraftResource.Agapite, amount) + { + } + + public AgapiteOre(Serial serial) : base(serial) + { + } + + 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 BaseIngot GetIngot() => new AgapiteIngot(); } - public override void Serialize(IGenericWriter writer) + public class VeriteOre : BaseOre { - base.Serialize(writer); + [Constructible] + public VeriteOre(int amount = 1) : base(CraftResource.Verite, amount) + { + } - writer.Write(0); // version + public VeriteOre(Serial serial) : base(serial) + { + } + + 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 BaseIngot GetIngot() => new VeriteIngot(); } - public override void Deserialize(IGenericReader reader) + public class ValoriteOre : BaseOre { - base.Deserialize(reader); + [Constructible] + public ValoriteOre(int amount = 1) : base(CraftResource.Valorite, amount) + { + } - int version = reader.ReadInt(); + public ValoriteOre(Serial serial) : base(serial) + { + } + + 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 BaseIngot GetIngot() => new ValoriteIngot(); } - - public override BaseIngot GetIngot() => new DullCopperIngot(); - } - - public class ShadowIronOre : BaseOre - { - [Constructible] - public ShadowIronOre(int amount = 1) : base(CraftResource.ShadowIron, amount) - { - } - - public ShadowIronOre(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override BaseIngot GetIngot() => new ShadowIronIngot(); - } - - public class CopperOre : BaseOre - { - [Constructible] - public CopperOre(int amount = 1) : base(CraftResource.Copper, amount) - { - } - - public CopperOre(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override BaseIngot GetIngot() => new CopperIngot(); - } - - public class BronzeOre : BaseOre - { - [Constructible] - public BronzeOre(int amount = 1) : base(CraftResource.Bronze, amount) - { - } - - public BronzeOre(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override BaseIngot GetIngot() => new BronzeIngot(); - } - - public class GoldOre : BaseOre - { - [Constructible] - public GoldOre(int amount = 1) : base(CraftResource.Gold, amount) - { - } - - public GoldOre(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override BaseIngot GetIngot() => new GoldIngot(); - } - - public class AgapiteOre : BaseOre - { - [Constructible] - public AgapiteOre(int amount = 1) : base(CraftResource.Agapite, amount) - { - } - - public AgapiteOre(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override BaseIngot GetIngot() => new AgapiteIngot(); - } - - public class VeriteOre : BaseOre - { - [Constructible] - public VeriteOre(int amount = 1) : base(CraftResource.Verite, amount) - { - } - - public VeriteOre(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override BaseIngot GetIngot() => new VeriteIngot(); - } - - public class ValoriteOre : BaseOre - { - [Constructible] - public ValoriteOre(int amount = 1) : base(CraftResource.Valorite, amount) - { - } - - public ValoriteOre(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override BaseIngot GetIngot() => new ValoriteIngot(); - } } diff --git a/Projects/UOContent/Items/Resources/Blacksmithing/Scales.cs b/Projects/UOContent/Items/Resources/Blacksmithing/Scales.cs index b04401d25..130370adc 100644 --- a/Projects/UOContent/Items/Resources/Blacksmithing/Scales.cs +++ b/Projects/UOContent/Items/Resources/Blacksmithing/Scales.cs @@ -1,221 +1,221 @@ namespace Server.Items { - public abstract class BaseScales : Item, ICommodity - { - private CraftResource m_Resource; - - public BaseScales(CraftResource resource, int amount = 1) : base(0x26B4) + public abstract class BaseScales : Item, ICommodity { - Stackable = true; - Amount = amount; - Hue = CraftResources.GetHue(resource); + private CraftResource m_Resource; - m_Resource = resource; + public BaseScales(CraftResource resource, int amount = 1) : base(0x26B4) + { + Stackable = true; + Amount = amount; + Hue = CraftResources.GetHue(resource); + + m_Resource = resource; + } + + public BaseScales(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1053139; // dragon scales + + [CommandProperty(AccessLevel.GameMaster)] + public CraftResource Resource + { + get => m_Resource; + set + { + m_Resource = value; + InvalidateProperties(); + } + } + + public override double DefaultWeight => 0.1; + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write((int)m_Resource); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Resource = (CraftResource)reader.ReadInt(); + break; + } + } + } } - public BaseScales(Serial serial) : base(serial) + public class RedScales : BaseScales { + [Constructible] + public RedScales(int amount = 1) : base(CraftResource.RedScales, amount) + { + } + + public RedScales(Serial serial) : base(serial) + { + } + + 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 int LabelNumber => 1053139; // dragon scales - - [CommandProperty(AccessLevel.GameMaster)] - public CraftResource Resource + public class YellowScales : BaseScales { - get => m_Resource; - set - { - m_Resource = value; - InvalidateProperties(); - } + [Constructible] + public YellowScales(int amount = 1) : base(CraftResource.YellowScales, amount) + { + } + + public YellowScales(Serial serial) : base(serial) + { + } + + 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 double DefaultWeight => 0.1; - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) + public class BlackScales : BaseScales { - base.Serialize(writer); + [Constructible] + public BlackScales(int amount = 1) : base(CraftResource.BlackScales, amount) + { + } - writer.Write(0); // version + public BlackScales(Serial serial) : base(serial) + { + } - writer.Write((int)m_Resource); + 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 Deserialize(IGenericReader reader) + public class GreenScales : BaseScales { - base.Deserialize(reader); + [Constructible] + public GreenScales(int amount = 1) : base(CraftResource.GreenScales, amount) + { + } - int version = reader.ReadInt(); + public GreenScales(Serial serial) : base(serial) + { + } - switch (version) - { - case 0: - { - m_Resource = (CraftResource)reader.ReadInt(); - break; - } - } - } - } + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public class RedScales : BaseScales - { - [Constructible] - public RedScales(int amount = 1) : base(CraftResource.RedScales, amount) - { + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } } - public RedScales(Serial serial) : base(serial) + public class WhiteScales : BaseScales { + [Constructible] + public WhiteScales(int amount = 1) : base(CraftResource.WhiteScales, amount) + { + } + + public WhiteScales(Serial serial) : base(serial) + { + } + + 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 Serialize(IGenericWriter writer) + public class BlueScales : BaseScales { - base.Serialize(writer); + [Constructible] + public BlueScales(int amount = 1) : base(CraftResource.BlueScales, amount) + { + } - writer.Write(0); // version + public BlueScales(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1053140; // sea serpent scales + + 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 Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class YellowScales : BaseScales - { - [Constructible] - public YellowScales(int amount = 1) : base(CraftResource.YellowScales, amount) - { - } - - public YellowScales(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BlackScales : BaseScales - { - [Constructible] - public BlackScales(int amount = 1) : base(CraftResource.BlackScales, amount) - { - } - - public BlackScales(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GreenScales : BaseScales - { - [Constructible] - public GreenScales(int amount = 1) : base(CraftResource.GreenScales, amount) - { - } - - public GreenScales(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class WhiteScales : BaseScales - { - [Constructible] - public WhiteScales(int amount = 1) : base(CraftResource.WhiteScales, amount) - { - } - - public WhiteScales(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BlueScales : BaseScales - { - [Constructible] - public BlueScales(int amount = 1) : base(CraftResource.BlueScales, amount) - { - } - - public BlueScales(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1053140; // sea serpent scales - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Fishing/BigFish.cs b/Projects/UOContent/Items/Resources/Fishing/BigFish.cs index 7a71b6993..33c5f5806 100644 --- a/Projects/UOContent/Items/Resources/Fishing/BigFish.cs +++ b/Projects/UOContent/Items/Resources/Fishing/BigFish.cs @@ -2,81 +2,83 @@ using System; namespace Server.Items { - public class BigFish : Item, ICarvable - { - private Mobile m_Fisher; - - [Constructible] - public BigFish() : base(0x09CC) + public class BigFish : Item, ICarvable { - Weight = Utility.RandomMinMax(3, - 200); // TODO: Find correct formula. max on OSI currently 200, OSI dev says it's not 200 as max, and ~ 1/1,000,000 chance to get highest - Hue = Utility.RandomBool() ? 0x847 : 0x58C; + private Mobile m_Fisher; + + [Constructible] + public BigFish() : base(0x09CC) + { + Weight = Utility.RandomMinMax( + 3, + 200 + ); // TODO: Find correct formula. max on OSI currently 200, OSI dev says it's not 200 as max, and ~ 1/1,000,000 chance to get highest + Hue = Utility.RandomBool() ? 0x847 : 0x58C; + } + + public BigFish(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Fisher + { + get => m_Fisher; + set + { + m_Fisher = value; + InvalidateProperties(); + } + } + + public override int LabelNumber => 1041112; // a big fish + + public void Carve(Mobile from, Item item) + { + ScissorHelper(from, new RawFishSteak(), Math.Max(16, (int)Weight) / 4, false); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (Weight >= 20) + { + if (m_Fisher != null) + list.Add(1070857, m_Fisher.Name); // Caught by ~1_fisherman~ + + list.Add(1070858, ((int)Weight).ToString()); // ~1_weight~ stones + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(m_Fisher); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_Fisher = reader.ReadMobile(); + break; + } + case 0: + { + Weight = Utility.RandomMinMax(3, 200); + break; + } + } + } } - - public BigFish(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Fisher - { - get => m_Fisher; - set - { - m_Fisher = value; - InvalidateProperties(); - } - } - - public override int LabelNumber => 1041112; // a big fish - - public void Carve(Mobile from, Item item) - { - ScissorHelper(from, new RawFishSteak(), Math.Max(16, (int)Weight) / 4, false); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Weight >= 20) - { - if (m_Fisher != null) - list.Add(1070857, m_Fisher.Name); // Caught by ~1_fisherman~ - - list.Add(1070858, ((int)Weight).ToString()); // ~1_weight~ stones - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(m_Fisher); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_Fisher = reader.ReadMobile(); - break; - } - case 0: - { - Weight = Utility.RandomMinMax(3, 200); - break; - } - } - } - } } diff --git a/Projects/UOContent/Items/Resources/Fishing/Fish.cs b/Projects/UOContent/Items/Resources/Fishing/Fish.cs index 7e51b8cd0..ac359bac8 100644 --- a/Projects/UOContent/Items/Resources/Fishing/Fish.cs +++ b/Projects/UOContent/Items/Resources/Fishing/Fish.cs @@ -1,36 +1,36 @@ namespace Server.Items { - public class Fish : Item, ICarvable - { - [Constructible] - public Fish(int amount = 1) : base(Utility.Random(0x09CC, 4)) + public class Fish : Item, ICarvable { - Stackable = true; - Weight = 1.0; - Amount = amount; + [Constructible] + public Fish(int amount = 1) : base(Utility.Random(0x09CC, 4)) + { + Stackable = true; + Weight = 1.0; + Amount = amount; + } + + public Fish(Serial serial) : base(serial) + { + } + + public void Carve(Mobile from, Item item) + { + ScissorHelper(from, new RawFishSteak(), 4); + } + + 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 Fish(Serial serial) : base(serial) - { - } - - public void Carve(Mobile from, Item item) - { - ScissorHelper(from, new RawFishSteak(), 4); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Fishing/MagicFish.cs b/Projects/UOContent/Items/Resources/Fishing/MagicFish.cs index 98154a223..1413bedf2 100644 --- a/Projects/UOContent/Items/Resources/Fishing/MagicFish.cs +++ b/Projects/UOContent/Items/Resources/Fishing/MagicFish.cs @@ -4,195 +4,195 @@ using Server.Spells; namespace Server.Items { - public abstract class BaseMagicFish : Item - { - public BaseMagicFish(int hue) : base(0xDD6) => Hue = hue; - - public BaseMagicFish(Serial serial) : base(serial) + public abstract class BaseMagicFish : Item { + public BaseMagicFish(int hue) : base(0xDD6) => Hue = hue; + + public BaseMagicFish(Serial serial) : base(serial) + { + } + + public virtual int Bonus => 0; + public virtual StatType Type => StatType.Str; + + public override double DefaultWeight => 1.0; + + public virtual bool Apply(Mobile from) + { + var applied = SpellHelper.AddStatOffset(from, Type, Bonus, TimeSpan.FromMinutes(1.0)); + + if (!applied) + from.SendLocalizedMessage(502173); // You are already under a similar effect. + + return applied; + } + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else if (Apply(from)) + { + from.FixedEffect(0x375A, 10, 15); + from.PlaySound(0x1E7); + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 501774); // You swallow the fish whole! + Delete(); + } + } + + 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 virtual int Bonus => 0; - public virtual StatType Type => StatType.Str; - - public override double DefaultWeight => 1.0; - - public virtual bool Apply(Mobile from) + public class PrizedFish : BaseMagicFish { - bool applied = SpellHelper.AddStatOffset(from, Type, Bonus, TimeSpan.FromMinutes(1.0)); + [Constructible] + public PrizedFish() : base(51) + { + } - if (!applied) - from.SendLocalizedMessage(502173); // You are already under a similar effect. + public PrizedFish(Serial serial) : base(serial) + { + } - return applied; + public override int Bonus => 5; + public override StatType Type => StatType.Int; + + public override int LabelNumber => 1041073; // prized fish + + 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 (Hue == 151) + Hue = 51; + } } - public override void OnDoubleClick(Mobile from) + public class WondrousFish : BaseMagicFish { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (Apply(from)) - { - from.FixedEffect(0x375A, 10, 15); - from.PlaySound(0x1E7); - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 501774); // You swallow the fish whole! - Delete(); - } + [Constructible] + public WondrousFish() : base(86) + { + } + + public WondrousFish(Serial serial) : base(serial) + { + } + + public override int Bonus => 5; + public override StatType Type => StatType.Dex; + + public override int LabelNumber => 1041074; // wondrous fish + + 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 (Hue == 286) + Hue = 86; + } } - public override void Serialize(IGenericWriter writer) + public class TrulyRareFish : BaseMagicFish { - base.Serialize(writer); + [Constructible] + public TrulyRareFish() : base(76) + { + } - writer.Write(0); // version + public TrulyRareFish(Serial serial) : base(serial) + { + } + + public override int Bonus => 5; + public override StatType Type => StatType.Str; + + public override int LabelNumber => 1041075; // truly rare fish + + 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 (Hue == 376) + Hue = 76; + } } - public override void Deserialize(IGenericReader reader) + public class PeculiarFish : BaseMagicFish { - base.Deserialize(reader); + [Constructible] + public PeculiarFish() : base(66) + { + } - int version = reader.ReadInt(); + public PeculiarFish(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041076; // highly peculiar fish + + public override bool Apply(Mobile from) + { + from.Stam += 10; + return true; + } + + 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 (Hue == 266) + Hue = 66; + } } - } - - public class PrizedFish : BaseMagicFish - { - [Constructible] - public PrizedFish() : base(51) - { - } - - public PrizedFish(Serial serial) : base(serial) - { - } - - public override int Bonus => 5; - public override StatType Type => StatType.Int; - - public override int LabelNumber => 1041073; // prized fish - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Hue == 151) - Hue = 51; - } - } - - public class WondrousFish : BaseMagicFish - { - [Constructible] - public WondrousFish() : base(86) - { - } - - public WondrousFish(Serial serial) : base(serial) - { - } - - public override int Bonus => 5; - public override StatType Type => StatType.Dex; - - public override int LabelNumber => 1041074; // wondrous fish - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Hue == 286) - Hue = 86; - } - } - - public class TrulyRareFish : BaseMagicFish - { - [Constructible] - public TrulyRareFish() : base(76) - { - } - - public TrulyRareFish(Serial serial) : base(serial) - { - } - - public override int Bonus => 5; - public override StatType Type => StatType.Str; - - public override int LabelNumber => 1041075; // truly rare fish - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Hue == 376) - Hue = 76; - } - } - - public class PeculiarFish : BaseMagicFish - { - [Constructible] - public PeculiarFish() : base(66) - { - } - - public PeculiarFish(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041076; // highly peculiar fish - - public override bool Apply(Mobile from) - { - from.Stam += 10; - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Hue == 266) - Hue = 66; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Resources/Masonry/Granite.cs b/Projects/UOContent/Items/Resources/Masonry/Granite.cs index 95ceea954..340270e05 100644 --- a/Projects/UOContent/Items/Resources/Masonry/Granite.cs +++ b/Projects/UOContent/Items/Resources/Masonry/Granite.cs @@ -1,312 +1,312 @@ namespace Server.Items { - public abstract class BaseGranite : Item - { - private CraftResource m_Resource; - - public BaseGranite(CraftResource resource) : base(0x1779) + public abstract class BaseGranite : Item { - Hue = CraftResources.GetHue(resource); - Stackable = Core.ML; + private CraftResource m_Resource; - m_Resource = resource; + public BaseGranite(CraftResource resource) : base(0x1779) + { + Hue = CraftResources.GetHue(resource); + Stackable = Core.ML; + + m_Resource = resource; + } + + public BaseGranite(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public CraftResource Resource + { + get => m_Resource; + set + { + m_Resource = value; + InvalidateProperties(); + } + } + + public override double DefaultWeight => Core.ML ? 1.0 : 10.0; + + public override int LabelNumber => 1044607; // high quality granite + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write((int)m_Resource); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + case 0: + { + m_Resource = (CraftResource)reader.ReadInt(); + break; + } + } + + if (version < 1) + Stackable = Core.ML; + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (!CraftResources.IsStandard(m_Resource)) + { + var num = CraftResources.GetLocalizationNumber(m_Resource); + + if (num > 0) + list.Add(num); + else + list.Add(CraftResources.GetName(m_Resource)); + } + } } - public BaseGranite(Serial serial) : base(serial) + public class Granite : BaseGranite { + [Constructible] + public Granite() : base(CraftResource.Iron) + { + } + + public Granite(Serial serial) : base(serial) + { + } + + 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(); + } } - [CommandProperty(AccessLevel.GameMaster)] - public CraftResource Resource + public class DullCopperGranite : BaseGranite { - get => m_Resource; - set - { - m_Resource = value; - InvalidateProperties(); - } + [Constructible] + public DullCopperGranite() : base(CraftResource.DullCopper) + { + } + + public DullCopperGranite(Serial serial) : base(serial) + { + } + + 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 double DefaultWeight => Core.ML ? 1.0 : 10.0; - - public override int LabelNumber => 1044607; // high quality granite - - public override void Serialize(IGenericWriter writer) + public class ShadowIronGranite : BaseGranite { - base.Serialize(writer); + [Constructible] + public ShadowIronGranite() : base(CraftResource.ShadowIron) + { + } - writer.Write(1); // version + public ShadowIronGranite(Serial serial) : base(serial) + { + } - writer.Write((int)m_Resource); + 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 Deserialize(IGenericReader reader) + public class CopperGranite : BaseGranite { - base.Deserialize(reader); + [Constructible] + public CopperGranite() : base(CraftResource.Copper) + { + } - int version = reader.ReadInt(); + public CopperGranite(Serial serial) : base(serial) + { + } - switch (version) - { - case 1: - case 0: - { - m_Resource = (CraftResource)reader.ReadInt(); - break; - } - } + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - if (version < 1) - Stackable = Core.ML; + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } } - public override void GetProperties(ObjectPropertyList list) + public class BronzeGranite : BaseGranite { - base.GetProperties(list); + [Constructible] + public BronzeGranite() : base(CraftResource.Bronze) + { + } - if (!CraftResources.IsStandard(m_Resource)) - { - int num = CraftResources.GetLocalizationNumber(m_Resource); + public BronzeGranite(Serial serial) : base(serial) + { + } - if (num > 0) - list.Add(num); - else - list.Add(CraftResources.GetName(m_Resource)); - } - } - } + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public class Granite : BaseGranite - { - [Constructible] - public Granite() : base(CraftResource.Iron) - { + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } } - public Granite(Serial serial) : base(serial) + public class GoldGranite : BaseGranite { + [Constructible] + public GoldGranite() : base(CraftResource.Gold) + { + } + + public GoldGranite(Serial serial) : base(serial) + { + } + + 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 Serialize(IGenericWriter writer) + public class AgapiteGranite : BaseGranite { - base.Serialize(writer); + [Constructible] + public AgapiteGranite() : base(CraftResource.Agapite) + { + } - writer.Write(0); // version + public AgapiteGranite(Serial serial) : base(serial) + { + } + + 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 Deserialize(IGenericReader reader) + public class VeriteGranite : BaseGranite { - base.Deserialize(reader); + [Constructible] + public VeriteGranite() : base(CraftResource.Verite) + { + } - int version = reader.ReadInt(); - } - } + public VeriteGranite(Serial serial) : base(serial) + { + } - public class DullCopperGranite : BaseGranite - { - [Constructible] - public DullCopperGranite() : base(CraftResource.DullCopper) - { + 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 DullCopperGranite(Serial serial) : base(serial) + public class ValoriteGranite : BaseGranite { + [Constructible] + public ValoriteGranite() : base(CraftResource.Valorite) + { + } + + public ValoriteGranite(Serial serial) : base(serial) + { + } + + 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 Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class ShadowIronGranite : BaseGranite - { - [Constructible] - public ShadowIronGranite() : base(CraftResource.ShadowIron) - { - } - - public ShadowIronGranite(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class CopperGranite : BaseGranite - { - [Constructible] - public CopperGranite() : base(CraftResource.Copper) - { - } - - public CopperGranite(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BronzeGranite : BaseGranite - { - [Constructible] - public BronzeGranite() : base(CraftResource.Bronze) - { - } - - public BronzeGranite(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GoldGranite : BaseGranite - { - [Constructible] - public GoldGranite() : base(CraftResource.Gold) - { - } - - public GoldGranite(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class AgapiteGranite : BaseGranite - { - [Constructible] - public AgapiteGranite() : base(CraftResource.Agapite) - { - } - - public AgapiteGranite(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class VeriteGranite : BaseGranite - { - [Constructible] - public VeriteGranite() : base(CraftResource.Verite) - { - } - - public VeriteGranite(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class ValoriteGranite : BaseGranite - { - [Constructible] - public ValoriteGranite() : base(CraftResource.Valorite) - { - } - - public ValoriteGranite(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Resources/MiscMLResources.cs b/Projects/UOContent/Items/Resources/MiscMLResources.cs index 4019e4dcc..b64e5ad1d 100644 --- a/Projects/UOContent/Items/Resources/MiscMLResources.cs +++ b/Projects/UOContent/Items/Resources/MiscMLResources.cs @@ -1,883 +1,883 @@ namespace Server.Items { - public class Blight : Item - { - [Constructible] - public Blight(int amount = 1) - : base(0x3183) + public class Blight : Item { - Stackable = true; - Amount = amount; - } + [Constructible] + public Blight(int amount = 1) + : base(0x3183) + { + Stackable = true; + Amount = amount; + } - public Blight(Serial serial) - : base(serial) - { - } + public Blight(Serial serial) + : base(serial) + { + } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); + } } - } - public class LuminescentFungi : Item - { - [Constructible] - public LuminescentFungi(int amount = 1) - : base(0x3191) + public class LuminescentFungi : Item { - Stackable = true; - Amount = amount; - } + [Constructible] + public LuminescentFungi(int amount = 1) + : base(0x3191) + { + Stackable = true; + Amount = amount; + } - public LuminescentFungi(Serial serial) - : base(serial) - { - } + public LuminescentFungi(Serial serial) + : base(serial) + { + } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - int version = reader.ReadInt(); - } - } + writer.Write(0); // version + } - public class CapturedEssence : Item - { - [Constructible] - public CapturedEssence(int amount = 1) - : base(0x318E) - { - Stackable = true; - Amount = amount; - } - - public CapturedEssence(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class EyeOfTheTravesty : Item - { - [Constructible] - public EyeOfTheTravesty(int amountFrom, int amountTo) - : this(Utility.RandomMinMax(amountFrom, amountTo)) - { - } - - [Constructible] - public EyeOfTheTravesty(int amount = 1) - : base(0x318D) - { - Stackable = true; - Amount = amount; - } + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - public EyeOfTheTravesty(Serial serial) - : base(serial) - { + var version = reader.ReadInt(); + } } - public override void Serialize(IGenericWriter writer) + public class CapturedEssence : Item { - base.Serialize(writer); + [Constructible] + public CapturedEssence(int amount = 1) + : base(0x318E) + { + Stackable = true; + Amount = amount; + } - writer.Write(0); // version - } + public CapturedEssence(Serial serial) + : base(serial) + { + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - int version = reader.ReadInt(); - } - } + writer.Write(0); // version + } - public class Corruption : Item - { - [Constructible] - public Corruption(int amountFrom, int amountTo) - : this(Utility.RandomMinMax(amountFrom, amountTo)) - { - } + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - [Constructible] - public Corruption(int amount = 1) - : base(0x3184) - { - Stackable = true; - Amount = amount; + var version = reader.ReadInt(); + } } - public Corruption(Serial serial) - : base(serial) + public class EyeOfTheTravesty : Item { - } + [Constructible] + public EyeOfTheTravesty(int amountFrom, int amountTo) + : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + [Constructible] + public EyeOfTheTravesty(int amount = 1) + : base(0x318D) + { + Stackable = true; + Amount = amount; + } - writer.Write(0); // version - } + public EyeOfTheTravesty(Serial serial) + : base(serial) + { + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - int version = reader.ReadInt(); - } - } + writer.Write(0); // version + } - public class DreadHornMane : Item - { - [Constructible] - public DreadHornMane(int amountFrom, int amountTo) - : this(Utility.RandomMinMax(amountFrom, amountTo)) - { - } + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - [Constructible] - public DreadHornMane(int amount = 1) - : base(0x318A) - { - Stackable = true; - Amount = amount; + var version = reader.ReadInt(); + } } - public DreadHornMane(Serial serial) - : base(serial) + public class Corruption : Item { - } + [Constructible] + public Corruption(int amountFrom, int amountTo) + : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + [Constructible] + public Corruption(int amount = 1) + : base(0x3184) + { + Stackable = true; + Amount = amount; + } - writer.Write(0); // version - } + public Corruption(Serial serial) + : base(serial) + { + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - int version = reader.ReadInt(); - } - } + writer.Write(0); // version + } - public class ParasiticPlant : Item - { - [Constructible] - public ParasiticPlant(int amountFrom, int amountTo) - : this(Utility.RandomMinMax(amountFrom, amountTo)) - { - } + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - [Constructible] - public ParasiticPlant(int amount = 1) - : base(0x3190) - { - Stackable = true; - Amount = amount; - } + var version = reader.ReadInt(); + } + } - public ParasiticPlant(Serial serial) - : base(serial) - { - } + public class DreadHornMane : Item + { + [Constructible] + public DreadHornMane(int amountFrom, int amountTo) + : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + [Constructible] + public DreadHornMane(int amount = 1) + : base(0x318A) + { + Stackable = true; + Amount = amount; + } - writer.Write(0); // version - } + public DreadHornMane(Serial serial) + : base(serial) + { + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - int version = reader.ReadInt(); - } - } + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } - public class Muculent : Item - { - [Constructible] - public Muculent(int amountFrom, int amountTo) - : this(Utility.RandomMinMax(amountFrom, amountTo)) - { - } + public class ParasiticPlant : Item + { + [Constructible] + public ParasiticPlant(int amountFrom, int amountTo) + : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } - [Constructible] - public Muculent(int amount = 1) - : base(0x3188) - { - Stackable = true; - Amount = amount; - } - - public Muculent(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DiseasedBark : Item - { - [Constructible] - public DiseasedBark(int amountFrom, int amountTo) - : this(Utility.RandomMinMax(amountFrom, amountTo)) - { - } - - [Constructible] - public DiseasedBark(int amount = 1) - : base(0x318B) - { - Stackable = true; - Amount = amount; - } - - public DiseasedBark(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BarkFragment : Item - { - [Constructible] - public BarkFragment(int amountFrom, int amountTo) - : this(Utility.RandomMinMax(amountFrom, amountTo)) - { - } - - [Constructible] - public BarkFragment(int amount = 1) - : base(0x318F) - { - Stackable = true; - Amount = amount; - } - - public BarkFragment(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GrizzledBones : Item - { - [Constructible] - public GrizzledBones(int amountFrom, int amountTo) - : this(Utility.RandomMinMax(amountFrom, amountTo)) - { - } - - [Constructible] - public GrizzledBones(int amount = 1) - : base(0x318C) - { - Stackable = true; - Amount = amount; - } - - public GrizzledBones(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); - - int version = reader.ReadInt(); - - if (version <= 0 && ItemID == 0x318F) - ItemID = 0x318C; - } - } + [Constructible] + public ParasiticPlant(int amount = 1) + : base(0x3190) + { + Stackable = true; + Amount = amount; + } - public class LardOfParoxysmus : Item - { - [Constructible] - public LardOfParoxysmus(int amountFrom, int amountTo) - : this(Utility.RandomMinMax(amountFrom, amountTo)) - { - } + public ParasiticPlant(Serial serial) + : base(serial) + { + } - [Constructible] - public LardOfParoxysmus(int amount = 1) - : base(0x3189) - { - Stackable = true; - Amount = amount; - } + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public LardOfParoxysmus(Serial serial) - : base(serial) - { - } + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public class Muculent : Item + { + [Constructible] + public Muculent(int amountFrom, int amountTo) + : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } - writer.Write(0); // version - } + [Constructible] + public Muculent(int amount = 1) + : base(0x3188) + { + Stackable = true; + Amount = amount; + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public Muculent(Serial serial) + : base(serial) + { + } - int version = reader.ReadInt(); - } - } + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public class PerfectEmerald : Item - { - [Constructible] - public PerfectEmerald(int amountFrom, int amountTo) - : this(Utility.RandomMinMax(amountFrom, amountTo)) - { - } + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } - [Constructible] - public PerfectEmerald(int amount = 1) - : base(0x3194) - { - Stackable = true; - Amount = amount; - } + public class DiseasedBark : Item + { + [Constructible] + public DiseasedBark(int amountFrom, int amountTo) + : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } - public PerfectEmerald(Serial serial) - : base(serial) - { - } + [Constructible] + public DiseasedBark(int amount = 1) + : base(0x318B) + { + Stackable = true; + Amount = amount; + } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public DiseasedBark(Serial serial) + : base(serial) + { + } - writer.Write(0); // version - } + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + writer.Write(0); // version + } - int version = reader.ReadInt(); - } - } + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } - public class DarkSapphire : Item - { - [Constructible] - public DarkSapphire(int amountFrom, int amountTo) - : this(Utility.RandomMinMax(amountFrom, amountTo)) - { - } + public class BarkFragment : Item + { + [Constructible] + public BarkFragment(int amountFrom, int amountTo) + : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } - [Constructible] - public DarkSapphire(int amount = 1) - : base(0x3192) - { - Stackable = true; - Amount = amount; - } + [Constructible] + public BarkFragment(int amount = 1) + : base(0x318F) + { + Stackable = true; + Amount = amount; + } - public DarkSapphire(Serial serial) - : base(serial) - { - } + public BarkFragment(Serial serial) + : base(serial) + { + } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } - int version = reader.ReadInt(); - } - } + public class GrizzledBones : Item + { + [Constructible] + public GrizzledBones(int amountFrom, int amountTo) + : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } - public class Turquoise : Item - { - [Constructible] - public Turquoise(int amountFrom, int amountTo) - : this(Utility.RandomMinMax(amountFrom, amountTo)) - { - } + [Constructible] + public GrizzledBones(int amount = 1) + : base(0x318C) + { + Stackable = true; + Amount = amount; + } - [Constructible] - public Turquoise(int amount = 1) - : base(0x3193) - { - Stackable = true; - Amount = amount; - } + public GrizzledBones(Serial serial) + : base(serial) + { + } - public Turquoise(Serial serial) - : base(serial) - { - } + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + writer.Write(1); // version + } - writer.Write(0); // version - } + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version <= 0 && ItemID == 0x318F) + ItemID = 0x318C; + } + } - public override void Deserialize(IGenericReader reader) + public class LardOfParoxysmus : Item { - base.Deserialize(reader); + [Constructible] + public LardOfParoxysmus(int amountFrom, int amountTo) + : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } - int version = reader.ReadInt(); - } - } + [Constructible] + public LardOfParoxysmus(int amount = 1) + : base(0x3189) + { + Stackable = true; + Amount = amount; + } - public class EcruCitrine : Item - { - [Constructible] - public EcruCitrine(int amountFrom, int amountTo) - : this(Utility.RandomMinMax(amountFrom, amountTo)) - { - } + public LardOfParoxysmus(Serial serial) + : base(serial) + { + } - [Constructible] - public EcruCitrine(int amount = 1) - : base(0x3195) - { - Stackable = true; - Amount = amount; - } + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public EcruCitrine(Serial serial) - : base(serial) - { - } + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } - public override void Serialize(IGenericWriter writer) + public class PerfectEmerald : Item { - base.Serialize(writer); + [Constructible] + public PerfectEmerald(int amountFrom, int amountTo) + : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } - writer.Write(0); // version - } + [Constructible] + public PerfectEmerald(int amount = 1) + : base(0x3194) + { + Stackable = true; + Amount = amount; + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public PerfectEmerald(Serial serial) + : base(serial) + { + } - int version = reader.ReadInt(); - } - } + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public class WhitePearl : Item - { - [Constructible] - public WhitePearl(int amountFrom, int amountTo) - : this(Utility.RandomMinMax(amountFrom, amountTo)) - { - } + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } - [Constructible] - public WhitePearl(int amount = 1) - : base(0x3196) + public class DarkSapphire : Item { - Stackable = true; - Amount = amount; - } + [Constructible] + public DarkSapphire(int amountFrom, int amountTo) + : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } - public WhitePearl(Serial serial) - : base(serial) - { - } + [Constructible] + public DarkSapphire(int amount = 1) + : base(0x3192) + { + Stackable = true; + Amount = amount; + } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public DarkSapphire(Serial serial) + : base(serial) + { + } - writer.Write(0); // version - } + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } - int version = reader.ReadInt(); - } - } + public class Turquoise : Item + { + [Constructible] + public Turquoise(int amountFrom, int amountTo) + : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } - public class FireRuby : Item - { - [Constructible] - public FireRuby(int amountFrom, int amountTo) - : this(Utility.RandomMinMax(amountFrom, amountTo)) - { - } + [Constructible] + public Turquoise(int amount = 1) + : base(0x3193) + { + Stackable = true; + Amount = amount; + } - [Constructible] - public FireRuby(int amount = 1) - : base(0x3197) - { - Stackable = true; - Amount = amount; - } + public Turquoise(Serial serial) + : base(serial) + { + } - public FireRuby(Serial serial) - : base(serial) - { - } + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - 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(); + } + } - writer.Write(0); // version - } + public class EcruCitrine : Item + { + [Constructible] + public EcruCitrine(int amountFrom, int amountTo) + : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + [Constructible] + public EcruCitrine(int amount = 1) + : base(0x3195) + { + Stackable = true; + Amount = amount; + } - int version = reader.ReadInt(); - } - } + public EcruCitrine(Serial serial) + : base(serial) + { + } - public class BlueDiamond : Item - { - [Constructible] - public BlueDiamond(int amountFrom, int amountTo) - : this(Utility.RandomMinMax(amountFrom, amountTo)) - { - } + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - [Constructible] - public BlueDiamond(int amount = 1) - : base(0x3198) - { - Stackable = true; - Amount = amount; - } + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } - public BlueDiamond(Serial serial) - : base(serial) - { - } + public class WhitePearl : Item + { + [Constructible] + public WhitePearl(int amountFrom, int amountTo) + : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + [Constructible] + public WhitePearl(int amount = 1) + : base(0x3196) + { + Stackable = true; + Amount = amount; + } - writer.Write(0); // version - } + public WhitePearl(Serial serial) + : base(serial) + { + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - int version = reader.ReadInt(); - } - } + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } - public class BrilliantAmber : Item - { - [Constructible] - public BrilliantAmber(int amountFrom, int amountTo) - : this(Utility.RandomMinMax(amountFrom, amountTo)) - { - } + public class FireRuby : Item + { + [Constructible] + public FireRuby(int amountFrom, int amountTo) + : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } - [Constructible] - public BrilliantAmber(int amount = 1) - : base(0x3199) - { - Stackable = true; - Amount = amount; - } + [Constructible] + public FireRuby(int amount = 1) + : base(0x3197) + { + Stackable = true; + Amount = amount; + } - public BrilliantAmber(Serial serial) - : base(serial) - { - } + public FireRuby(Serial serial) + : base(serial) + { + } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public class BlueDiamond : Item + { + [Constructible] + public BlueDiamond(int amountFrom, int amountTo) + : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + [Constructible] + public BlueDiamond(int amount = 1) + : base(0x3198) + { + Stackable = true; + Amount = amount; + } - int version = reader.ReadInt(); - } - } + public BlueDiamond(Serial serial) + : base(serial) + { + } - public class Scourge : Item - { - [Constructible] - public Scourge(int amountFrom, int amountTo) - : this(Utility.RandomMinMax(amountFrom, amountTo)) - { - } + 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 class BrilliantAmber : Item + { + [Constructible] + public BrilliantAmber(int amountFrom, int amountTo) + : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } - [Constructible] - public Scourge(int amount = 1) - : base(0x3185) - { - Stackable = true; - Amount = amount; - Hue = 150; - } + [Constructible] + public BrilliantAmber(int amount = 1) + : base(0x3199) + { + Stackable = true; + Amount = amount; + } - public Scourge(Serial serial) - : base(serial) - { - } + public BrilliantAmber(Serial serial) + : base(serial) + { + } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + 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 class Scourge : Item + { + [Constructible] + public Scourge(int amountFrom, int amountTo) + : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } - writer.Write(0); // version - } + [Constructible] + public Scourge(int amount = 1) + : base(0x3185) + { + Stackable = true; + Amount = amount; + Hue = 150; + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public Scourge(Serial serial) + : base(serial) + { + } - int version = reader.ReadInt(); - } - } + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public class Putrefication : Item - { - [Constructible] - public Putrefication(int amountFrom, int amountTo) - : this(Utility.RandomMinMax(amountFrom, amountTo)) - { + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } } - - [Constructible] - public Putrefication(int amount = 1) - : base(0x3186) + + public class Putrefication : Item { - Stackable = true; - Amount = amount; - Hue = 883; - } + [Constructible] + public Putrefication(int amountFrom, int amountTo) + : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } - public Putrefication(Serial serial) - : base(serial) - { - } + [Constructible] + public Putrefication(int amount = 1) + : base(0x3186) + { + Stackable = true; + Amount = amount; + Hue = 883; + } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public Putrefication(Serial serial) + : base(serial) + { + } - writer.Write(0); // version - } + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public override void Deserialize(IGenericReader reader) + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public class Taint : Item { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } + [Constructible] + public Taint(int amountFrom, int amountTo) + : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } - public class Taint : Item - { - [Constructible] - public Taint(int amountFrom, int amountTo) - : this(Utility.RandomMinMax(amountFrom, amountTo)) - { - } + [Constructible] + public Taint(int amount = 1) + : base(0x3187) + { + Stackable = true; + Amount = amount; + Hue = 731; + } - [Constructible] - public Taint(int amount = 1) - : base(0x3187) - { - Stackable = true; - Amount = amount; - Hue = 731; - } + public Taint(Serial serial) + : base(serial) + { + } - public Taint(Serial serial) - : base(serial) - { - } + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - writer.Write(0); // version + var version = reader.ReadInt(); + } } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x315A, 0x315B)] - public class PristineDreadHorn : Item - { - [Constructible] - public PristineDreadHorn() - : base(0x315A) + [Flippable(0x315A, 0x315B)] + public class PristineDreadHorn : Item { - } + [Constructible] + public PristineDreadHorn() + : base(0x315A) + { + } - public PristineDreadHorn(Serial serial) - : base(serial) - { - } + public PristineDreadHorn(Serial serial) + : base(serial) + { + } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); + } } - } - - public class SwitchItem : Item - { - [Constructible] - public SwitchItem(int amountFrom, int amountTo) - : this(Utility.RandomMinMax(amountFrom, amountTo)) + + public class SwitchItem : Item { - } + [Constructible] + public SwitchItem(int amountFrom, int amountTo) + : this(Utility.RandomMinMax(amountFrom, amountTo)) + { + } - [Constructible] - public SwitchItem(int amount = 1) - : base(0x2F5F) - { - Stackable = true; - Amount = amount; - } + [Constructible] + public SwitchItem(int amount = 1) + : base(0x2F5F) + { + Stackable = true; + Amount = amount; + } - public SwitchItem(Serial serial) - : base(serial) - { - } + public SwitchItem(Serial serial) + : base(serial) + { + } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); + } } - } } diff --git a/Projects/UOContent/Items/Resources/Reagents/BagOfAllReagents.cs b/Projects/UOContent/Items/Resources/Reagents/BagOfAllReagents.cs index b15b38f8d..95c8e28e2 100644 --- a/Projects/UOContent/Items/Resources/Reagents/BagOfAllReagents.cs +++ b/Projects/UOContent/Items/Resources/Reagents/BagOfAllReagents.cs @@ -1,41 +1,41 @@ namespace Server.Items { - public class BagOfAllReagents : Bag - { - [Constructible] - public BagOfAllReagents(int amount = 50) + public class BagOfAllReagents : Bag { - DropItem(new BlackPearl(amount)); - DropItem(new Bloodmoss(amount)); - DropItem(new Garlic(amount)); - DropItem(new Ginseng(amount)); - DropItem(new MandrakeRoot(amount)); - DropItem(new Nightshade(amount)); - DropItem(new SulfurousAsh(amount)); - DropItem(new SpidersSilk(amount)); - DropItem(new BatWing(amount)); - DropItem(new GraveDust(amount)); - DropItem(new DaemonBlood(amount)); - DropItem(new NoxCrystal(amount)); - DropItem(new PigIron(amount)); + [Constructible] + public BagOfAllReagents(int amount = 50) + { + DropItem(new BlackPearl(amount)); + DropItem(new Bloodmoss(amount)); + DropItem(new Garlic(amount)); + DropItem(new Ginseng(amount)); + DropItem(new MandrakeRoot(amount)); + DropItem(new Nightshade(amount)); + DropItem(new SulfurousAsh(amount)); + DropItem(new SpidersSilk(amount)); + DropItem(new BatWing(amount)); + DropItem(new GraveDust(amount)); + DropItem(new DaemonBlood(amount)); + DropItem(new NoxCrystal(amount)); + DropItem(new PigIron(amount)); + } + + public BagOfAllReagents(Serial serial) : base(serial) + { + } + + 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 BagOfAllReagents(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Reagents/BagOfNecroReagents.cs b/Projects/UOContent/Items/Resources/Reagents/BagOfNecroReagents.cs index b973d857f..8ae93d53d 100644 --- a/Projects/UOContent/Items/Resources/Reagents/BagOfNecroReagents.cs +++ b/Projects/UOContent/Items/Resources/Reagents/BagOfNecroReagents.cs @@ -1,33 +1,33 @@ namespace Server.Items { - public class BagOfNecroReagents : Bag - { - [Constructible] - public BagOfNecroReagents(int amount = 50) + public class BagOfNecroReagents : Bag { - DropItem(new BatWing(amount)); - DropItem(new GraveDust(amount)); - DropItem(new DaemonBlood(amount)); - DropItem(new NoxCrystal(amount)); - DropItem(new PigIron(amount)); + [Constructible] + public BagOfNecroReagents(int amount = 50) + { + DropItem(new BatWing(amount)); + DropItem(new GraveDust(amount)); + DropItem(new DaemonBlood(amount)); + DropItem(new NoxCrystal(amount)); + DropItem(new PigIron(amount)); + } + + public BagOfNecroReagents(Serial serial) : base(serial) + { + } + + 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 BagOfNecroReagents(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Reagents/BagOfReagents.cs b/Projects/UOContent/Items/Resources/Reagents/BagOfReagents.cs index 8133dfea3..30cd467f8 100644 --- a/Projects/UOContent/Items/Resources/Reagents/BagOfReagents.cs +++ b/Projects/UOContent/Items/Resources/Reagents/BagOfReagents.cs @@ -1,36 +1,36 @@ namespace Server.Items { - public class BagOfReagents : Bag - { - [Constructible] - public BagOfReagents(int amount = 50) + public class BagOfReagents : Bag { - DropItem(new BlackPearl(amount)); - DropItem(new Bloodmoss(amount)); - DropItem(new Garlic(amount)); - DropItem(new Ginseng(amount)); - DropItem(new MandrakeRoot(amount)); - DropItem(new Nightshade(amount)); - DropItem(new SulfurousAsh(amount)); - DropItem(new SpidersSilk(amount)); + [Constructible] + public BagOfReagents(int amount = 50) + { + DropItem(new BlackPearl(amount)); + DropItem(new Bloodmoss(amount)); + DropItem(new Garlic(amount)); + DropItem(new Ginseng(amount)); + DropItem(new MandrakeRoot(amount)); + DropItem(new Nightshade(amount)); + DropItem(new SulfurousAsh(amount)); + DropItem(new SpidersSilk(amount)); + } + + public BagOfReagents(Serial serial) : base(serial) + { + } + + 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 BagOfReagents(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Reagents/BaseReagent.cs b/Projects/UOContent/Items/Resources/Reagents/BaseReagent.cs index cd7651a74..e858e3532 100644 --- a/Projects/UOContent/Items/Resources/Reagents/BaseReagent.cs +++ b/Projects/UOContent/Items/Resources/Reagents/BaseReagent.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public abstract class BaseReagent : Item - { - public BaseReagent(int itemID, int amount = 1) : base(itemID) + public abstract class BaseReagent : Item { - Stackable = true; - Amount = amount; + public BaseReagent(int itemID, int amount = 1) : base(itemID) + { + Stackable = true; + Amount = amount; + } + + public BaseReagent(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0.1; + + 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 BaseReagent(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Resources/Reagents/BatWing.cs b/Projects/UOContent/Items/Resources/Reagents/BatWing.cs index e3d60bbee..8b1893d2d 100644 --- a/Projects/UOContent/Items/Resources/Reagents/BatWing.cs +++ b/Projects/UOContent/Items/Resources/Reagents/BatWing.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class BatWing : BaseReagent, ICommodity - { - [Constructible] - public BatWing(int amount = 1) : base(0xF78, amount) + public class BatWing : BaseReagent, ICommodity { + [Constructible] + public BatWing(int amount = 1) : base(0xF78, amount) + { + } + + public BatWing(Serial serial) : base(serial) + { + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + 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 BatWing(Serial serial) : base(serial) - { - } - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Reagents/BlackPearl.cs b/Projects/UOContent/Items/Resources/Reagents/BlackPearl.cs index 17a73c80c..c462c3cf0 100644 --- a/Projects/UOContent/Items/Resources/Reagents/BlackPearl.cs +++ b/Projects/UOContent/Items/Resources/Reagents/BlackPearl.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class BlackPearl : BaseReagent, ICommodity - { - [Constructible] - public BlackPearl(int amount = 1) : base(0xF7A, amount) + public class BlackPearl : BaseReagent, ICommodity { + [Constructible] + public BlackPearl(int amount = 1) : base(0xF7A, amount) + { + } + + public BlackPearl(Serial serial) : base(serial) + { + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + 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 BlackPearl(Serial serial) : base(serial) - { - } - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Reagents/Bloodmoss.cs b/Projects/UOContent/Items/Resources/Reagents/Bloodmoss.cs index b458f2b3d..74d3ec81f 100644 --- a/Projects/UOContent/Items/Resources/Reagents/Bloodmoss.cs +++ b/Projects/UOContent/Items/Resources/Reagents/Bloodmoss.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class Bloodmoss : BaseReagent, ICommodity - { - [Constructible] - public Bloodmoss(int amount = 1) : base(0xF7B, amount) + public class Bloodmoss : BaseReagent, ICommodity { + [Constructible] + public Bloodmoss(int amount = 1) : base(0xF7B, amount) + { + } + + public Bloodmoss(Serial serial) : base(serial) + { + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + 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 Bloodmoss(Serial serial) : base(serial) - { - } - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Reagents/DaemonBlood.cs b/Projects/UOContent/Items/Resources/Reagents/DaemonBlood.cs index 7a8e06e52..3ccc1d810 100644 --- a/Projects/UOContent/Items/Resources/Reagents/DaemonBlood.cs +++ b/Projects/UOContent/Items/Resources/Reagents/DaemonBlood.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class DaemonBlood : BaseReagent, ICommodity - { - [Constructible] - public DaemonBlood(int amount = 1) : base(0xF7D, amount) + public class DaemonBlood : BaseReagent, ICommodity { + [Constructible] + public DaemonBlood(int amount = 1) : base(0xF7D, amount) + { + } + + public DaemonBlood(Serial serial) : base(serial) + { + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + 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 DaemonBlood(Serial serial) : base(serial) - { - } - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Reagents/DaemonBone.cs b/Projects/UOContent/Items/Resources/Reagents/DaemonBone.cs index 811836a3a..614fb4b2d 100644 --- a/Projects/UOContent/Items/Resources/Reagents/DaemonBone.cs +++ b/Projects/UOContent/Items/Resources/Reagents/DaemonBone.cs @@ -1,31 +1,31 @@ namespace Server.Items { - // TODO: Commodity? - public class DaemonBone : BaseReagent - { - [Constructible] - public DaemonBone(int amount = 1) : base(0xF80, amount) + // TODO: Commodity? + public class DaemonBone : BaseReagent { + [Constructible] + public DaemonBone(int amount = 1) : base(0xF80, amount) + { + } + + public DaemonBone(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 1.0; + + 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 DaemonBone(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 1.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Reagents/DeadWood.cs b/Projects/UOContent/Items/Resources/Reagents/DeadWood.cs index bf3467528..c7127bb02 100644 --- a/Projects/UOContent/Items/Resources/Reagents/DeadWood.cs +++ b/Projects/UOContent/Items/Resources/Reagents/DeadWood.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class DeadWood : BaseReagent, ICommodity - { - [Constructible] - public DeadWood(int amount = 1) : base(0xF90, amount) + public class DeadWood : BaseReagent, ICommodity { + [Constructible] + public DeadWood(int amount = 1) : base(0xF90, amount) + { + } + + public DeadWood(Serial serial) : base(serial) + { + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + 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 DeadWood(Serial serial) : base(serial) - { - } - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Reagents/DragonsBlood.cs b/Projects/UOContent/Items/Resources/Reagents/DragonsBlood.cs index e133a088d..b951df59c 100644 --- a/Projects/UOContent/Items/Resources/Reagents/DragonsBlood.cs +++ b/Projects/UOContent/Items/Resources/Reagents/DragonsBlood.cs @@ -1,33 +1,33 @@ namespace Server.Items { - public class DragonsBlood : BaseReagent, ICommodity - { - [Constructible] - public DragonsBlood(int amount = 1) - : base(0x4077, amount) + public class DragonsBlood : BaseReagent, ICommodity { + [Constructible] + public DragonsBlood(int amount = 1) + : base(0x4077, amount) + { + } + + public DragonsBlood(Serial serial) + : base(serial) + { + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => Core.ML; + + 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 DragonsBlood(Serial serial) - : base(serial) - { - } - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => Core.ML; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Reagents/Garlic.cs b/Projects/UOContent/Items/Resources/Reagents/Garlic.cs index 3b56081f8..ef91a6d60 100644 --- a/Projects/UOContent/Items/Resources/Reagents/Garlic.cs +++ b/Projects/UOContent/Items/Resources/Reagents/Garlic.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class Garlic : BaseReagent, ICommodity - { - [Constructible] - public Garlic(int amount = 1) : base(0xF84, amount) + public class Garlic : BaseReagent, ICommodity { + [Constructible] + public Garlic(int amount = 1) : base(0xF84, amount) + { + } + + public Garlic(Serial serial) : base(serial) + { + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + 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 Garlic(Serial serial) : base(serial) - { - } - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Reagents/Ginseng.cs b/Projects/UOContent/Items/Resources/Reagents/Ginseng.cs index 752bf4a55..d4dc2b09a 100644 --- a/Projects/UOContent/Items/Resources/Reagents/Ginseng.cs +++ b/Projects/UOContent/Items/Resources/Reagents/Ginseng.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class Ginseng : BaseReagent, ICommodity - { - [Constructible] - public Ginseng(int amount = 1) : base(0xF85, amount) + public class Ginseng : BaseReagent, ICommodity { + [Constructible] + public Ginseng(int amount = 1) : base(0xF85, amount) + { + } + + public Ginseng(Serial serial) : base(serial) + { + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + 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 Ginseng(Serial serial) : base(serial) - { - } - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Reagents/GraveDust.cs b/Projects/UOContent/Items/Resources/Reagents/GraveDust.cs index 303303207..814545f96 100644 --- a/Projects/UOContent/Items/Resources/Reagents/GraveDust.cs +++ b/Projects/UOContent/Items/Resources/Reagents/GraveDust.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class GraveDust : BaseReagent, ICommodity - { - [Constructible] - public GraveDust(int amount = 1) : base(0xF8F, amount) + public class GraveDust : BaseReagent, ICommodity { + [Constructible] + public GraveDust(int amount = 1) : base(0xF8F, amount) + { + } + + public GraveDust(Serial serial) : base(serial) + { + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + 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 GraveDust(Serial serial) : base(serial) - { - } - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Reagents/MandrakeRoot.cs b/Projects/UOContent/Items/Resources/Reagents/MandrakeRoot.cs index efd5f77e1..d4ce9fdff 100644 --- a/Projects/UOContent/Items/Resources/Reagents/MandrakeRoot.cs +++ b/Projects/UOContent/Items/Resources/Reagents/MandrakeRoot.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class MandrakeRoot : BaseReagent, ICommodity - { - [Constructible] - public MandrakeRoot(int amount = 1) : base(0xF86, amount) + public class MandrakeRoot : BaseReagent, ICommodity { + [Constructible] + public MandrakeRoot(int amount = 1) : base(0xF86, amount) + { + } + + public MandrakeRoot(Serial serial) : base(serial) + { + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + 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 MandrakeRoot(Serial serial) : base(serial) - { - } - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Reagents/Nightshade.cs b/Projects/UOContent/Items/Resources/Reagents/Nightshade.cs index cf1272575..55990693b 100644 --- a/Projects/UOContent/Items/Resources/Reagents/Nightshade.cs +++ b/Projects/UOContent/Items/Resources/Reagents/Nightshade.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class Nightshade : BaseReagent, ICommodity - { - [Constructible] - public Nightshade(int amount = 1) : base(0xF88, amount) + public class Nightshade : BaseReagent, ICommodity { + [Constructible] + public Nightshade(int amount = 1) : base(0xF88, amount) + { + } + + public Nightshade(Serial serial) : base(serial) + { + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + 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 Nightshade(Serial serial) : base(serial) - { - } - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Reagents/NoxCrystal.cs b/Projects/UOContent/Items/Resources/Reagents/NoxCrystal.cs index 69e9f2545..5a948d2d4 100644 --- a/Projects/UOContent/Items/Resources/Reagents/NoxCrystal.cs +++ b/Projects/UOContent/Items/Resources/Reagents/NoxCrystal.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class NoxCrystal : BaseReagent, ICommodity - { - [Constructible] - public NoxCrystal(int amount = 1) : base(0xF8E, amount) + public class NoxCrystal : BaseReagent, ICommodity { + [Constructible] + public NoxCrystal(int amount = 1) : base(0xF8E, amount) + { + } + + public NoxCrystal(Serial serial) : base(serial) + { + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + 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 NoxCrystal(Serial serial) : base(serial) - { - } - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Reagents/PigIron.cs b/Projects/UOContent/Items/Resources/Reagents/PigIron.cs index a0c620e2b..f5e570e99 100644 --- a/Projects/UOContent/Items/Resources/Reagents/PigIron.cs +++ b/Projects/UOContent/Items/Resources/Reagents/PigIron.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class PigIron : BaseReagent, ICommodity - { - [Constructible] - public PigIron(int amount = 1) : base(0xF8A, amount) + public class PigIron : BaseReagent, ICommodity { + [Constructible] + public PigIron(int amount = 1) : base(0xF8A, amount) + { + } + + public PigIron(Serial serial) : base(serial) + { + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + 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 PigIron(Serial serial) : base(serial) - { - } - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Reagents/SpidersSilk.cs b/Projects/UOContent/Items/Resources/Reagents/SpidersSilk.cs index c02d0ddd4..c4dd8ea4b 100644 --- a/Projects/UOContent/Items/Resources/Reagents/SpidersSilk.cs +++ b/Projects/UOContent/Items/Resources/Reagents/SpidersSilk.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class SpidersSilk : BaseReagent, ICommodity - { - [Constructible] - public SpidersSilk(int amount = 1) : base(0xF8D, amount) + public class SpidersSilk : BaseReagent, ICommodity { + [Constructible] + public SpidersSilk(int amount = 1) : base(0xF8D, amount) + { + } + + public SpidersSilk(Serial serial) : base(serial) + { + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + 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 SpidersSilk(Serial serial) : base(serial) - { - } - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Reagents/SulfurousAsh.cs b/Projects/UOContent/Items/Resources/Reagents/SulfurousAsh.cs index 69385f275..4cceb2a87 100644 --- a/Projects/UOContent/Items/Resources/Reagents/SulfurousAsh.cs +++ b/Projects/UOContent/Items/Resources/Reagents/SulfurousAsh.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class SulfurousAsh : BaseReagent, ICommodity - { - [Constructible] - public SulfurousAsh(int amount = 1) : base(0xF8C, amount) + public class SulfurousAsh : BaseReagent, ICommodity { + [Constructible] + public SulfurousAsh(int amount = 1) : base(0xF8C, amount) + { + } + + public SulfurousAsh(Serial serial) : base(serial) + { + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + 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 SulfurousAsh(Serial serial) : base(serial) - { - } - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Tailor/BoltOfCloth.cs b/Projects/UOContent/Items/Resources/Tailor/BoltOfCloth.cs index 62a2e8d25..f8ad88024 100644 --- a/Projects/UOContent/Items/Resources/Tailor/BoltOfCloth.cs +++ b/Projects/UOContent/Items/Resources/Tailor/BoltOfCloth.cs @@ -2,62 +2,63 @@ using Server.Network; namespace Server.Items { - [Flippable(0xF95, 0xF96, 0xF97, 0xF98, 0xF99, 0xF9A, 0xF9B, 0xF9C)] - public class BoltOfCloth : Item, IScissorable, IDyable, ICommodity - { - [Constructible] - public BoltOfCloth(int amount = 1) : base(0xF95) + [Flippable(0xF95, 0xF96, 0xF97, 0xF98, 0xF99, 0xF9A, 0xF9B, 0xF9C)] + public class BoltOfCloth : Item, IScissorable, IDyable, ICommodity { - Stackable = true; - Weight = 5.0; - Amount = amount; + [Constructible] + public BoltOfCloth(int amount = 1) : base(0xF95) + { + Stackable = true; + Weight = 5.0; + Amount = amount; + } + + public BoltOfCloth(Serial serial) : base(serial) + { + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + public bool Dye(Mobile from, DyeTub sender) + { + if (Deleted) return false; + + Hue = sender.DyedHue; + + return true; + } + + public bool Scissor(Mobile from, Scissors scissors) + { + if (Deleted || !from.CanSee(this)) return false; + + ScissorHelper(from, new Cloth(), 50); + + return true; + } + + 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 OnSingleClick(Mobile from) + { + var number = Amount == 1 ? 1049122 : 1049121; + + from.Send( + new MessageLocalized(Serial, ItemID, MessageType.Label, 0x3B2, 3, number, "", (Amount * 50).ToString()) + ); + } } - - public BoltOfCloth(Serial serial) : base(serial) - { - } - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public bool Dye(Mobile from, DyeTub sender) - { - if (Deleted) return false; - - Hue = sender.DyedHue; - - return true; - } - - public bool Scissor(Mobile from, Scissors scissors) - { - if (Deleted || !from.CanSee(this)) return false; - - ScissorHelper(from, new Cloth(), 50); - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnSingleClick(Mobile from) - { - int number = Amount == 1 ? 1049122 : 1049121; - - from.Send( - new MessageLocalized(Serial, ItemID, MessageType.Label, 0x3B2, 3, number, "", (Amount * 50).ToString())); - } - } } diff --git a/Projects/UOContent/Items/Resources/Tailor/Bone.cs b/Projects/UOContent/Items/Resources/Tailor/Bone.cs index 3003e4209..7abd07173 100644 --- a/Projects/UOContent/Items/Resources/Tailor/Bone.cs +++ b/Projects/UOContent/Items/Resources/Tailor/Bone.cs @@ -1,34 +1,34 @@ namespace Server.Items { - public class Bone : Item, ICommodity - { - [Constructible] - public Bone(int amount = 1) : base(0xf7e) + public class Bone : Item, ICommodity { - Stackable = true; - Amount = amount; - Weight = 1.0; + [Constructible] + public Bone(int amount = 1) : base(0xf7e) + { + Stackable = true; + Amount = amount; + Weight = 1.0; + } + + public Bone(Serial serial) : base(serial) + { + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + 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 Bone(Serial serial) : base(serial) - { - } - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Tailor/Cloth.cs b/Projects/UOContent/Items/Resources/Tailor/Cloth.cs index 14b30f78f..bd1d5f3d3 100644 --- a/Projects/UOContent/Items/Resources/Tailor/Cloth.cs +++ b/Projects/UOContent/Items/Resources/Tailor/Cloth.cs @@ -2,62 +2,62 @@ using Server.Network; namespace Server.Items { - [Flippable(0x1766, 0x1768)] - public class Cloth : Item, IScissorable, IDyable, ICommodity - { - [Constructible] - public Cloth(int amount = 1) : base(0x1766) + [Flippable(0x1766, 0x1768)] + public class Cloth : Item, IScissorable, IDyable, ICommodity { - Stackable = true; - Amount = amount; + [Constructible] + public Cloth(int amount = 1) : base(0x1766) + { + Stackable = true; + Amount = amount; + } + + public Cloth(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0.1; + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + public bool Dye(Mobile from, DyeTub sender) + { + if (Deleted) + return false; + + Hue = sender.DyedHue; + + return true; + } + + public bool Scissor(Mobile from, Scissors scissors) + { + if (Deleted || !from.CanSee(this)) return false; + + ScissorHelper(from, new Bandage(), 1); + + return true; + } + + 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 OnSingleClick(Mobile from) + { + var number = Amount == 1 ? 1049124 : 1049123; + + from.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, 0x3B2, 3, number, "", Amount.ToString())); + } } - - public Cloth(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.1; - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public bool Dye(Mobile from, DyeTub sender) - { - if (Deleted) - return false; - - Hue = sender.DyedHue; - - return true; - } - - public bool Scissor(Mobile from, Scissors scissors) - { - if (Deleted || !from.CanSee(this)) return false; - - ScissorHelper(from, new Bandage(), 1); - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnSingleClick(Mobile from) - { - int number = Amount == 1 ? 1049124 : 1049123; - - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, 0x3B2, 3, number, "", Amount.ToString())); - } - } } diff --git a/Projects/UOContent/Items/Resources/Tailor/Cotton.cs b/Projects/UOContent/Items/Resources/Tailor/Cotton.cs index 1df44396b..ba3fc8c4c 100644 --- a/Projects/UOContent/Items/Resources/Tailor/Cotton.cs +++ b/Projects/UOContent/Items/Resources/Tailor/Cotton.cs @@ -2,103 +2,103 @@ using Server.Targeting; namespace Server.Items { - public class Cotton : Item, IDyable - { - [Constructible] - public Cotton(int amount = 1) : base(0xDF9) + public class Cotton : Item, IDyable { - Stackable = true; - Weight = 4.0; - Amount = amount; - } - - public Cotton(Serial serial) : base(serial) - { - } - - public bool Dye(Mobile from, DyeTub sender) - { - if (Deleted) - return false; - - Hue = sender.DyedHue; - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(502655); // What spinning wheel do you wish to spin this on? - from.Target = new PickWheelTarget(this); - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - - public virtual void OnSpun(ISpinningWheel wheel, Mobile from, int hue) - { - Item item = new SpoolOfThread(6); - item.Hue = hue; - - from.AddToBackpack(item); - from.SendLocalizedMessage(1010577); // You put the spools of thread in your backpack. - } - - private class PickWheelTarget : Target - { - private readonly Cotton m_Cotton; - - public PickWheelTarget(Cotton cotton) : base(3, false, TargetFlags.None) => m_Cotton = cotton; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Cotton.Deleted) - return; - - ISpinningWheel wheel = targeted as ISpinningWheel; - - if (wheel == null && targeted is AddonComponent component) - wheel = component.Addon as ISpinningWheel; - - if (wheel is Item) + [Constructible] + public Cotton(int amount = 1) : base(0xDF9) { - if (!m_Cotton.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (wheel.Spinning) - { - from.SendLocalizedMessage(502656); // That spinning wheel is being used. - } - else - { - m_Cotton.Consume(); - wheel.BeginSpin(m_Cotton.OnSpun, from, m_Cotton.Hue); - } + Stackable = true; + Weight = 4.0; + Amount = amount; } - else + + public Cotton(Serial serial) : base(serial) { - from.SendLocalizedMessage(502658); // Use that on a spinning wheel. } - } + + public bool Dye(Mobile from, DyeTub sender) + { + if (Deleted) + return false; + + Hue = sender.DyedHue; + + return true; + } + + 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 (IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(502655); // What spinning wheel do you wish to spin this on? + from.Target = new PickWheelTarget(this); + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + + public virtual void OnSpun(ISpinningWheel wheel, Mobile from, int hue) + { + Item item = new SpoolOfThread(6); + item.Hue = hue; + + from.AddToBackpack(item); + from.SendLocalizedMessage(1010577); // You put the spools of thread in your backpack. + } + + private class PickWheelTarget : Target + { + private readonly Cotton m_Cotton; + + public PickWheelTarget(Cotton cotton) : base(3, false, TargetFlags.None) => m_Cotton = cotton; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Cotton.Deleted) + return; + + var wheel = targeted as ISpinningWheel; + + if (wheel == null && targeted is AddonComponent component) + wheel = component.Addon as ISpinningWheel; + + if (wheel is Item) + { + if (!m_Cotton.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else if (wheel.Spinning) + { + from.SendLocalizedMessage(502656); // That spinning wheel is being used. + } + else + { + m_Cotton.Consume(); + wheel.BeginSpin(m_Cotton.OnSpun, from, m_Cotton.Hue); + } + } + else + { + from.SendLocalizedMessage(502658); // Use that on a spinning wheel. + } + } + } } - } } diff --git a/Projects/UOContent/Items/Resources/Tailor/Flax.cs b/Projects/UOContent/Items/Resources/Tailor/Flax.cs index 8bb2e4ff7..55278b0e2 100644 --- a/Projects/UOContent/Items/Resources/Tailor/Flax.cs +++ b/Projects/UOContent/Items/Resources/Tailor/Flax.cs @@ -2,93 +2,93 @@ using Server.Targeting; namespace Server.Items { - public class Flax : Item - { - [Constructible] - public Flax(int amount = 1) : base(0x1A9C) + public class Flax : Item { - Stackable = true; - Weight = 1.0; - Amount = amount; - } - - public Flax(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(502655); // What spinning wheel do you wish to spin this on? - from.Target = new PickWheelTarget(this); - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - - public virtual void OnSpun(ISpinningWheel wheel, Mobile from, int hue) - { - Item item = new SpoolOfThread(6); - item.Hue = hue; - - from.AddToBackpack(item); - from.SendLocalizedMessage(1010577); // You put the spools of thread in your backpack. - } - - private class PickWheelTarget : Target - { - private readonly Flax m_Flax; - - public PickWheelTarget(Flax flax) : base(3, false, TargetFlags.None) => m_Flax = flax; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Flax.Deleted) - return; - - ISpinningWheel wheel = targeted as ISpinningWheel; - - if (wheel == null && targeted is AddonComponent component) - wheel = component.Addon as ISpinningWheel; - - if (wheel is Item) + [Constructible] + public Flax(int amount = 1) : base(0x1A9C) { - if (!m_Flax.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (wheel.Spinning) - { - from.SendLocalizedMessage(502656); // That spinning wheel is being used. - } - else - { - m_Flax.Consume(); - wheel.BeginSpin(m_Flax.OnSpun, from, m_Flax.Hue); - } + Stackable = true; + Weight = 1.0; + Amount = amount; } - else + + public Flax(Serial serial) : base(serial) { - from.SendLocalizedMessage(502658); // Use that on a spinning wheel. } - } + + 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 (IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(502655); // What spinning wheel do you wish to spin this on? + from.Target = new PickWheelTarget(this); + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + + public virtual void OnSpun(ISpinningWheel wheel, Mobile from, int hue) + { + Item item = new SpoolOfThread(6); + item.Hue = hue; + + from.AddToBackpack(item); + from.SendLocalizedMessage(1010577); // You put the spools of thread in your backpack. + } + + private class PickWheelTarget : Target + { + private readonly Flax m_Flax; + + public PickWheelTarget(Flax flax) : base(3, false, TargetFlags.None) => m_Flax = flax; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Flax.Deleted) + return; + + var wheel = targeted as ISpinningWheel; + + if (wheel == null && targeted is AddonComponent component) + wheel = component.Addon as ISpinningWheel; + + if (wheel is Item) + { + if (!m_Flax.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else if (wheel.Spinning) + { + from.SendLocalizedMessage(502656); // That spinning wheel is being used. + } + else + { + m_Flax.Consume(); + wheel.BeginSpin(m_Flax.OnSpun, from, m_Flax.Hue); + } + } + else + { + from.SendLocalizedMessage(502658); // Use that on a spinning wheel. + } + } + } } - } } diff --git a/Projects/UOContent/Items/Resources/Tailor/Hides.cs b/Projects/UOContent/Items/Resources/Tailor/Hides.cs index be5e9956b..877eb1d9f 100644 --- a/Projects/UOContent/Items/Resources/Tailor/Hides.cs +++ b/Projects/UOContent/Items/Resources/Tailor/Hides.cs @@ -1,269 +1,269 @@ namespace Server.Items { - public abstract class BaseHides : Item, ICommodity - { - private CraftResource m_Resource; - - public BaseHides(CraftResource resource, int amount = 1) : base(0x1079) + public abstract class BaseHides : Item, ICommodity { - Stackable = true; - Weight = 5.0; - Amount = amount; - Hue = CraftResources.GetHue(resource); + private CraftResource m_Resource; - m_Resource = resource; + public BaseHides(CraftResource resource, int amount = 1) : base(0x1079) + { + Stackable = true; + Weight = 5.0; + Amount = amount; + Hue = CraftResources.GetHue(resource); + + m_Resource = resource; + } + + public BaseHides(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public CraftResource Resource + { + get => m_Resource; + set + { + m_Resource = value; + InvalidateProperties(); + } + } + + public override int LabelNumber + { + get + { + if (m_Resource >= CraftResource.SpinedLeather && m_Resource <= CraftResource.BarbedLeather) + return 1049687 + (m_Resource - CraftResource.SpinedLeather); + + return 1047023; + } + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write((int)m_Resource); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_Resource = (CraftResource)reader.ReadInt(); + break; + } + case 0: + { + var info = new OreInfo(reader.ReadInt(), reader.ReadInt(), reader.ReadString()); + + m_Resource = CraftResources.GetFromOreInfo(info); + break; + } + } + } + + public override void AddNameProperty(ObjectPropertyList list) + { + if (Amount > 1) + list.Add(1050039, "{0}\t#{1}", Amount, 1024216); // ~1_NUMBER~ ~2_ITEMNAME~ + else + list.Add(1024216); // pile of hides + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (!CraftResources.IsStandard(m_Resource)) + { + var num = CraftResources.GetLocalizationNumber(m_Resource); + + if (num > 0) + list.Add(num); + else + list.Add(CraftResources.GetName(m_Resource)); + } + } } - public BaseHides(Serial serial) : base(serial) + [Flippable(0x1079, 0x1078)] + public class Hides : BaseHides, IScissorable { + [Constructible] + public Hides(int amount = 1) : base(CraftResource.RegularLeather, amount) + { + } + + public Hides(Serial serial) : base(serial) + { + } + + public bool Scissor(Mobile from, Scissors scissors) + { + if (Deleted || !from.CanSee(this)) return false; + + if (Core.AOS && !IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(502437); // Items you wish to cut must be in your backpack + return false; + } + + ScissorHelper(from, new Leather(), 1); + + return true; + } + + 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(); + } } - [CommandProperty(AccessLevel.GameMaster)] - public CraftResource Resource + [Flippable(0x1079, 0x1078)] + public class SpinedHides : BaseHides, IScissorable { - get => m_Resource; - set - { - m_Resource = value; - InvalidateProperties(); - } + [Constructible] + public SpinedHides(int amount = 1) : base(CraftResource.SpinedLeather, amount) + { + } + + public SpinedHides(Serial serial) : base(serial) + { + } + + public bool Scissor(Mobile from, Scissors scissors) + { + if (Deleted || !from.CanSee(this)) return false; + + if (Core.AOS && !IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(502437); // Items you wish to cut must be in your backpack + return false; + } + + ScissorHelper(from, new SpinedLeather(), 1); + + return true; + } + + 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 int LabelNumber + [Flippable(0x1079, 0x1078)] + public class HornedHides : BaseHides, IScissorable { - get - { - if (m_Resource >= CraftResource.SpinedLeather && m_Resource <= CraftResource.BarbedLeather) - return 1049687 + (m_Resource - CraftResource.SpinedLeather); + [Constructible] + public HornedHides(int amount = 1) : base(CraftResource.HornedLeather, amount) + { + } - return 1047023; - } + public HornedHides(Serial serial) : base(serial) + { + } + + public bool Scissor(Mobile from, Scissors scissors) + { + if (Deleted || !from.CanSee(this)) return false; + + if (Core.AOS && !IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(502437); // Items you wish to cut must be in your backpack + return false; + } + + ScissorHelper(from, new HornedLeather(), 1); + + return true; + } + + 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(); + } } - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) + [Flippable(0x1079, 0x1078)] + public class BarbedHides : BaseHides, IScissorable { - base.Serialize(writer); + [Constructible] + public BarbedHides(int amount = 1) : base(CraftResource.BarbedLeather, amount) + { + } - writer.Write(1); // version + public BarbedHides(Serial serial) : base(serial) + { + } - writer.Write((int)m_Resource); + public bool Scissor(Mobile from, Scissors scissors) + { + if (Deleted || !from.CanSee(this)) return false; + + if (Core.AOS && !IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(502437); // Items you wish to cut must be in your backpack + return false; + } + + ScissorHelper(from, new BarbedLeather(), 1); + + return true; + } + + 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 Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_Resource = (CraftResource)reader.ReadInt(); - break; - } - case 0: - { - OreInfo info = new OreInfo(reader.ReadInt(), reader.ReadInt(), reader.ReadString()); - - m_Resource = CraftResources.GetFromOreInfo(info); - break; - } - } - } - - public override void AddNameProperty(ObjectPropertyList list) - { - if (Amount > 1) - list.Add(1050039, "{0}\t#{1}", Amount, 1024216); // ~1_NUMBER~ ~2_ITEMNAME~ - else - list.Add(1024216); // pile of hides - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (!CraftResources.IsStandard(m_Resource)) - { - int num = CraftResources.GetLocalizationNumber(m_Resource); - - if (num > 0) - list.Add(num); - else - list.Add(CraftResources.GetName(m_Resource)); - } - } - } - - [Flippable(0x1079, 0x1078)] - public class Hides : BaseHides, IScissorable - { - [Constructible] - public Hides(int amount = 1) : base(CraftResource.RegularLeather, amount) - { - } - - public Hides(Serial serial) : base(serial) - { - } - - public bool Scissor(Mobile from, Scissors scissors) - { - if (Deleted || !from.CanSee(this)) return false; - - if (Core.AOS && !IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(502437); // Items you wish to cut must be in your backpack - return false; - } - - ScissorHelper(from, new Leather(), 1); - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1079, 0x1078)] - public class SpinedHides : BaseHides, IScissorable - { - [Constructible] - public SpinedHides(int amount = 1) : base(CraftResource.SpinedLeather, amount) - { - } - - public SpinedHides(Serial serial) : base(serial) - { - } - - public bool Scissor(Mobile from, Scissors scissors) - { - if (Deleted || !from.CanSee(this)) return false; - - if (Core.AOS && !IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(502437); // Items you wish to cut must be in your backpack - return false; - } - - ScissorHelper(from, new SpinedLeather(), 1); - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1079, 0x1078)] - public class HornedHides : BaseHides, IScissorable - { - [Constructible] - public HornedHides(int amount = 1) : base(CraftResource.HornedLeather, amount) - { - } - - public HornedHides(Serial serial) : base(serial) - { - } - - public bool Scissor(Mobile from, Scissors scissors) - { - if (Deleted || !from.CanSee(this)) return false; - - if (Core.AOS && !IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(502437); // Items you wish to cut must be in your backpack - return false; - } - - ScissorHelper(from, new HornedLeather(), 1); - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1079, 0x1078)] - public class BarbedHides : BaseHides, IScissorable - { - [Constructible] - public BarbedHides(int amount = 1) : base(CraftResource.BarbedLeather, amount) - { - } - - public BarbedHides(Serial serial) : base(serial) - { - } - - public bool Scissor(Mobile from, Scissors scissors) - { - if (Deleted || !from.CanSee(this)) return false; - - if (Core.AOS && !IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(502437); // Items you wish to cut must be in your backpack - return false; - } - - ScissorHelper(from, new BarbedLeather(), 1); - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Tailor/Leathers.cs b/Projects/UOContent/Items/Resources/Tailor/Leathers.cs index dddbf3aa9..8200bb2f5 100644 --- a/Projects/UOContent/Items/Resources/Tailor/Leathers.cs +++ b/Projects/UOContent/Items/Resources/Tailor/Leathers.cs @@ -1,209 +1,209 @@ namespace Server.Items { - public abstract class BaseLeather : Item, ICommodity - { - private CraftResource m_Resource; - - public BaseLeather(CraftResource resource, int amount = 1) : base(0x1081) + public abstract class BaseLeather : Item, ICommodity { - Stackable = true; - Weight = 1.0; - Amount = amount; - Hue = CraftResources.GetHue(resource); + private CraftResource m_Resource; - m_Resource = resource; + public BaseLeather(CraftResource resource, int amount = 1) : base(0x1081) + { + Stackable = true; + Weight = 1.0; + Amount = amount; + Hue = CraftResources.GetHue(resource); + + m_Resource = resource; + } + + public BaseLeather(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public CraftResource Resource + { + get => m_Resource; + set + { + m_Resource = value; + InvalidateProperties(); + } + } + + public override int LabelNumber + { + get + { + if (m_Resource >= CraftResource.SpinedLeather && m_Resource <= CraftResource.BarbedLeather) + return 1049684 + (m_Resource - CraftResource.SpinedLeather); + + return 1047022; + } + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write((int)m_Resource); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_Resource = (CraftResource)reader.ReadInt(); + break; + } + case 0: + { + var info = new OreInfo(reader.ReadInt(), reader.ReadInt(), reader.ReadString()); + + m_Resource = CraftResources.GetFromOreInfo(info); + break; + } + } + } + + public override void AddNameProperty(ObjectPropertyList list) + { + if (Amount > 1) + list.Add(1050039, "{0}\t#{1}", Amount, 1024199); // ~1_NUMBER~ ~2_ITEMNAME~ + else + list.Add(1024199); // cut leather + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (!CraftResources.IsStandard(m_Resource)) + { + var num = CraftResources.GetLocalizationNumber(m_Resource); + + if (num > 0) + list.Add(num); + else + list.Add(CraftResources.GetName(m_Resource)); + } + } } - public BaseLeather(Serial serial) : base(serial) + [Flippable(0x1081, 0x1082)] + public class Leather : BaseLeather { + [Constructible] + public Leather(int amount = 1) : base(CraftResource.RegularLeather, amount) + { + } + + public Leather(Serial serial) : base(serial) + { + } + + 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(); + } } - [CommandProperty(AccessLevel.GameMaster)] - public CraftResource Resource + [Flippable(0x1081, 0x1082)] + public class SpinedLeather : BaseLeather { - get => m_Resource; - set - { - m_Resource = value; - InvalidateProperties(); - } + [Constructible] + public SpinedLeather(int amount = 1) : base(CraftResource.SpinedLeather, amount) + { + } + + public SpinedLeather(Serial serial) : base(serial) + { + } + + 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 int LabelNumber + [Flippable(0x1081, 0x1082)] + public class HornedLeather : BaseLeather { - get - { - if (m_Resource >= CraftResource.SpinedLeather && m_Resource <= CraftResource.BarbedLeather) - return 1049684 + (m_Resource - CraftResource.SpinedLeather); + [Constructible] + public HornedLeather(int amount = 1) : base(CraftResource.HornedLeather, amount) + { + } - return 1047022; - } + public HornedLeather(Serial serial) : base(serial) + { + } + + 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(); + } } - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) + [Flippable(0x1081, 0x1082)] + public class BarbedLeather : BaseLeather { - base.Serialize(writer); + [Constructible] + public BarbedLeather(int amount = 1) : base(CraftResource.BarbedLeather, amount) + { + } - writer.Write(1); // version + public BarbedLeather(Serial serial) : base(serial) + { + } - writer.Write((int)m_Resource); + 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 Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_Resource = (CraftResource)reader.ReadInt(); - break; - } - case 0: - { - OreInfo info = new OreInfo(reader.ReadInt(), reader.ReadInt(), reader.ReadString()); - - m_Resource = CraftResources.GetFromOreInfo(info); - break; - } - } - } - - public override void AddNameProperty(ObjectPropertyList list) - { - if (Amount > 1) - list.Add(1050039, "{0}\t#{1}", Amount, 1024199); // ~1_NUMBER~ ~2_ITEMNAME~ - else - list.Add(1024199); // cut leather - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (!CraftResources.IsStandard(m_Resource)) - { - int num = CraftResources.GetLocalizationNumber(m_Resource); - - if (num > 0) - list.Add(num); - else - list.Add(CraftResources.GetName(m_Resource)); - } - } - } - - [Flippable(0x1081, 0x1082)] - public class Leather : BaseLeather - { - [Constructible] - public Leather(int amount = 1) : base(CraftResource.RegularLeather, amount) - { - } - - public Leather(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1081, 0x1082)] - public class SpinedLeather : BaseLeather - { - [Constructible] - public SpinedLeather(int amount = 1) : base(CraftResource.SpinedLeather, amount) - { - } - - public SpinedLeather(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1081, 0x1082)] - public class HornedLeather : BaseLeather - { - [Constructible] - public HornedLeather(int amount = 1) : base(CraftResource.HornedLeather, amount) - { - } - - public HornedLeather(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x1081, 0x1082)] - public class BarbedLeather : BaseLeather - { - [Constructible] - public BarbedLeather(int amount = 1) : base(CraftResource.BarbedLeather, amount) - { - } - - public BarbedLeather(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Resources/Tailor/UncutCloth.cs b/Projects/UOContent/Items/Resources/Tailor/UncutCloth.cs index dc22770cf..60f0e8b3f 100644 --- a/Projects/UOContent/Items/Resources/Tailor/UncutCloth.cs +++ b/Projects/UOContent/Items/Resources/Tailor/UncutCloth.cs @@ -2,62 +2,62 @@ using Server.Network; namespace Server.Items { - [Flippable(0x1765, 0x1767)] - public class UncutCloth : Item, IScissorable, IDyable, ICommodity - { - [Constructible] - public UncutCloth(int amount = 1) : base(0x1767) + [Flippable(0x1765, 0x1767)] + public class UncutCloth : Item, IScissorable, IDyable, ICommodity { - Stackable = true; - Amount = amount; + [Constructible] + public UncutCloth(int amount = 1) : base(0x1767) + { + Stackable = true; + Amount = amount; + } + + public UncutCloth(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0.1; + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + public bool Dye(Mobile from, DyeTub sender) + { + if (Deleted) + return false; + + Hue = sender.DyedHue; + + return true; + } + + public bool Scissor(Mobile from, Scissors scissors) + { + if (Deleted || !from.CanSee(this)) return false; + + ScissorHelper(from, new Bandage(), 1); + + return true; + } + + 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 OnSingleClick(Mobile from) + { + var number = Amount == 1 ? 1049124 : 1049123; + + from.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, 0x3B2, 3, number, "", Amount.ToString())); + } } - - public UncutCloth(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.1; - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public bool Dye(Mobile from, DyeTub sender) - { - if (Deleted) - return false; - - Hue = sender.DyedHue; - - return true; - } - - public bool Scissor(Mobile from, Scissors scissors) - { - if (Deleted || !from.CanSee(this)) return false; - - ScissorHelper(from, new Bandage(), 1); - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnSingleClick(Mobile from) - { - int number = Amount == 1 ? 1049124 : 1049123; - - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, 0x3B2, 3, number, "", Amount.ToString())); - } - } } diff --git a/Projects/UOContent/Items/Resources/Tailor/Wool.cs b/Projects/UOContent/Items/Resources/Tailor/Wool.cs index 8a8340500..e6e50e178 100644 --- a/Projects/UOContent/Items/Resources/Tailor/Wool.cs +++ b/Projects/UOContent/Items/Resources/Tailor/Wool.cs @@ -2,141 +2,141 @@ using Server.Targeting; namespace Server.Items { - public class Wool : Item, IDyable - { - [Constructible] - public Wool(int amount = 1) : base(0xDF8) + public class Wool : Item, IDyable { - Stackable = true; - Weight = 4.0; - Amount = amount; - } - - public Wool(Serial serial) : base(serial) - { - } - - public bool Dye(Mobile from, DyeTub sender) - { - if (Deleted) - return false; - - Hue = sender.DyedHue; - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(502655); // What spinning wheel do you wish to spin this on? - from.Target = new PickWheelTarget(this); - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - - public virtual void OnSpun(ISpinningWheel wheel, Mobile from, int hue) - { - Item item = new DarkYarn(3); - item.Hue = hue; - - from.AddToBackpack(item); - from.SendLocalizedMessage(1010576); // You put the balls of yarn in your backpack. - } - - private class PickWheelTarget : Target - { - private readonly Wool m_Wool; - - public PickWheelTarget(Wool wool) : base(3, false, TargetFlags.None) => m_Wool = wool; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Wool.Deleted) - return; - - ISpinningWheel wheel = targeted as ISpinningWheel; - - if (wheel == null && targeted is AddonComponent component) - wheel = component.Addon as ISpinningWheel; - - if (wheel is Item) + [Constructible] + public Wool(int amount = 1) : base(0xDF8) { - if (!m_Wool.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (wheel.Spinning) - { - from.SendLocalizedMessage(502656); // That spinning wheel is being used. - } - else - { - m_Wool.Consume(); - wheel.BeginSpin(m_Wool.OnSpun, from, m_Wool.Hue); - } + Stackable = true; + Weight = 4.0; + Amount = amount; } - else + + public Wool(Serial serial) : base(serial) { - from.SendLocalizedMessage(502658); // Use that on a spinning wheel. } - } - } - } - public class TaintedWool : Wool - { - [Constructible] - public TaintedWool(int amount = 1) : base(0x101F) + public bool Dye(Mobile from, DyeTub sender) + { + if (Deleted) + return false; + + Hue = sender.DyedHue; + + return true; + } + + 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 (IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(502655); // What spinning wheel do you wish to spin this on? + from.Target = new PickWheelTarget(this); + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + + public virtual void OnSpun(ISpinningWheel wheel, Mobile from, int hue) + { + Item item = new DarkYarn(3); + item.Hue = hue; + + from.AddToBackpack(item); + from.SendLocalizedMessage(1010576); // You put the balls of yarn in your backpack. + } + + private class PickWheelTarget : Target + { + private readonly Wool m_Wool; + + public PickWheelTarget(Wool wool) : base(3, false, TargetFlags.None) => m_Wool = wool; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Wool.Deleted) + return; + + var wheel = targeted as ISpinningWheel; + + if (wheel == null && targeted is AddonComponent component) + wheel = component.Addon as ISpinningWheel; + + if (wheel is Item) + { + if (!m_Wool.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else if (wheel.Spinning) + { + from.SendLocalizedMessage(502656); // That spinning wheel is being used. + } + else + { + m_Wool.Consume(); + wheel.BeginSpin(m_Wool.OnSpun, from, m_Wool.Hue); + } + } + else + { + from.SendLocalizedMessage(502658); // Use that on a spinning wheel. + } + } + } + } + + public class TaintedWool : Wool { - Stackable = true; - Weight = 4.0; - Amount = amount; + [Constructible] + public TaintedWool(int amount = 1) : base(0x101F) + { + Stackable = true; + Weight = 4.0; + Amount = amount; + } + + public TaintedWool(Serial serial) : base(serial) + { + } + + 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 OnSpun(ISpinningWheel wheel, Mobile from, int hue) + { + Item item = new DarkYarn(); + item.Hue = hue; + + from.AddToBackpack(item); + from.SendLocalizedMessage(1010574); // You put a ball of yarn in your backpack. + } } - - public TaintedWool(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnSpun(ISpinningWheel wheel, Mobile from, int hue) - { - Item item = new DarkYarn(); - item.Hue = hue; - - from.AddToBackpack(item); - from.SendLocalizedMessage(1010574); // You put a ball of yarn in your backpack. - } - } } diff --git a/Projects/UOContent/Items/Resources/Tailor/YarnsAndThreads.cs b/Projects/UOContent/Items/Resources/Tailor/YarnsAndThreads.cs index 0e58b44a6..3f9b1cfcc 100644 --- a/Projects/UOContent/Items/Resources/Tailor/YarnsAndThreads.cs +++ b/Projects/UOContent/Items/Resources/Tailor/YarnsAndThreads.cs @@ -2,205 +2,205 @@ using Server.Targeting; namespace Server.Items { - public abstract class BaseClothMaterial : Item, IDyable - { - public BaseClothMaterial(int itemID, int amount = 1) : base(itemID) + public abstract class BaseClothMaterial : Item, IDyable { - Stackable = true; - Weight = 1.0; - Amount = amount; - } - - public BaseClothMaterial(Serial serial) : base(serial) - { - } - - public bool Dye(Mobile from, DyeTub sender) - { - if (Deleted) - return false; - - Hue = sender.DyedHue; - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(500366); // Select a loom to use that on. - from.Target = new PickLoomTarget(this); - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - - private class PickLoomTarget : Target - { - private readonly BaseClothMaterial m_Material; - - public PickLoomTarget(BaseClothMaterial material) : base(3, false, TargetFlags.None) => m_Material = material; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Material.Deleted) - return; - - ILoom loom = targeted as ILoom; - - if (loom == null && targeted is AddonComponent component) - loom = component.Addon as ILoom; - - if (loom != null) + public BaseClothMaterial(int itemID, int amount = 1) : base(itemID) { - if (!m_Material.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (loom.Phase < 4) - { - m_Material.Consume(); - - if (targeted is Item item) - item.SendLocalizedMessageTo(from, 1010001 + loom.Phase++); - } - else - { - Item create = new BoltOfCloth(); - create.Hue = m_Material.Hue; - - m_Material.Consume(); - loom.Phase = 0; - from.SendLocalizedMessage(500368); // You create some cloth and put it in your backpack. - from.AddToBackpack(create); - } + Stackable = true; + Weight = 1.0; + Amount = amount; } - else + + public BaseClothMaterial(Serial serial) : base(serial) { - from.SendLocalizedMessage(500367); // Try using that on a loom. } - } - } - } - public class DarkYarn : BaseClothMaterial - { - [Constructible] - public DarkYarn(int amount = 1) : base(0xE1D, amount) + public bool Dye(Mobile from, DyeTub sender) + { + if (Deleted) + return false; + + Hue = sender.DyedHue; + + return true; + } + + 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 (IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(500366); // Select a loom to use that on. + from.Target = new PickLoomTarget(this); + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + + private class PickLoomTarget : Target + { + private readonly BaseClothMaterial m_Material; + + public PickLoomTarget(BaseClothMaterial material) : base(3, false, TargetFlags.None) => m_Material = material; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Material.Deleted) + return; + + var loom = targeted as ILoom; + + if (loom == null && targeted is AddonComponent component) + loom = component.Addon as ILoom; + + if (loom != null) + { + if (!m_Material.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else if (loom.Phase < 4) + { + m_Material.Consume(); + + if (targeted is Item item) + item.SendLocalizedMessageTo(from, 1010001 + loom.Phase++); + } + else + { + Item create = new BoltOfCloth(); + create.Hue = m_Material.Hue; + + m_Material.Consume(); + loom.Phase = 0; + from.SendLocalizedMessage(500368); // You create some cloth and put it in your backpack. + from.AddToBackpack(create); + } + } + else + { + from.SendLocalizedMessage(500367); // Try using that on a loom. + } + } + } + } + + public class DarkYarn : BaseClothMaterial { + [Constructible] + public DarkYarn(int amount = 1) : base(0xE1D, amount) + { + } + + public DarkYarn(Serial serial) : base(serial) + { + } + + 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 DarkYarn(Serial serial) : base(serial) + public class LightYarn : BaseClothMaterial { + [Constructible] + public LightYarn(int amount = 1) : base(0xE1E, amount) + { + } + + public LightYarn(Serial serial) : base(serial) + { + } + + 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 Serialize(IGenericWriter writer) + public class LightYarnUnraveled : BaseClothMaterial { - base.Serialize(writer); + [Constructible] + public LightYarnUnraveled(int amount = 1) : base(0xE1F, amount) + { + } - writer.Write(0); // version + public LightYarnUnraveled(Serial serial) : base(serial) + { + } + + 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 Deserialize(IGenericReader reader) + public class SpoolOfThread : BaseClothMaterial { - base.Deserialize(reader); + [Constructible] + public SpoolOfThread(int amount = 1) : base(0xFA0, amount) + { + } - int version = reader.ReadInt(); + public SpoolOfThread(Serial serial) : base(serial) + { + } + + 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 class LightYarn : BaseClothMaterial - { - [Constructible] - public LightYarn(int amount = 1) : base(0xE1E, amount) - { - } - - public LightYarn(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class LightYarnUnraveled : BaseClothMaterial - { - [Constructible] - public LightYarnUnraveled(int amount = 1) : base(0xE1F, amount) - { - } - - public LightYarnUnraveled(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SpoolOfThread : BaseClothMaterial - { - [Constructible] - public SpoolOfThread(int amount = 1) : base(0xFA0, amount) - { - } - - public SpoolOfThread(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Shields/Artifacts/Aegis.cs b/Projects/UOContent/Items/Shields/Artifacts/Aegis.cs index 2e886ad02..0625c3c7a 100644 --- a/Projects/UOContent/Items/Shields/Artifacts/Aegis.cs +++ b/Projects/UOContent/Items/Shields/Artifacts/Aegis.cs @@ -1,44 +1,44 @@ namespace Server.Items { - public class Aegis : HeaterShield - { - [Constructible] - public Aegis() + public class Aegis : HeaterShield { - Hue = 0x47E; - ArmorAttributes.SelfRepair = 5; - Attributes.ReflectPhysical = 15; - Attributes.DefendChance = 15; - Attributes.LowerManaCost = 8; + [Constructible] + public Aegis() + { + Hue = 0x47E; + ArmorAttributes.SelfRepair = 5; + Attributes.ReflectPhysical = 15; + Attributes.DefendChance = 15; + Attributes.LowerManaCost = 8; + } + + public Aegis(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061602; // �gis + public override int ArtifactRarity => 11; + + public override int BasePhysicalResistance => 15; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version < 1) + PhysicalBonus = 0; + } } - - public Aegis(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061602; // �gis - public override int ArtifactRarity => 11; - - public override int BasePhysicalResistance => 15; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1) - PhysicalBonus = 0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Shields/Artifacts/ArcaneShield.cs b/Projects/UOContent/Items/Shields/Artifacts/ArcaneShield.cs index d877de6ea..17ce858cc 100644 --- a/Projects/UOContent/Items/Shields/Artifacts/ArcaneShield.cs +++ b/Projects/UOContent/Items/Shields/Artifacts/ArcaneShield.cs @@ -1,43 +1,43 @@ namespace Server.Items { - public class ArcaneShield : WoodenKiteShield - { - [Constructible] - public ArcaneShield() + public class ArcaneShield : WoodenKiteShield { - ItemID = 0x1B78; - Hue = 0x556; - Attributes.NightSight = 1; - Attributes.SpellChanneling = 1; - Attributes.DefendChance = 15; - Attributes.CastSpeed = 1; + [Constructible] + public ArcaneShield() + { + ItemID = 0x1B78; + Hue = 0x556; + Attributes.NightSight = 1; + Attributes.SpellChanneling = 1; + Attributes.DefendChance = 15; + Attributes.CastSpeed = 1; + } + + public ArcaneShield(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061101; // Arcane Shield + public override int ArtifactRarity => 11; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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 (Attributes.NightSight == 0) + Attributes.NightSight = 1; + } } - - public ArcaneShield(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061101; // Arcane Shield - public override int ArtifactRarity => 11; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Attributes.NightSight == 0) - Attributes.NightSight = 1; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Shields/BaseShield.cs b/Projects/UOContent/Items/Shields/BaseShield.cs index d26e01ac1..da3afdbce 100644 --- a/Projects/UOContent/Items/Shields/BaseShield.cs +++ b/Projects/UOContent/Items/Shields/BaseShield.cs @@ -2,178 +2,184 @@ using Server.Network; namespace Server.Items { - public class BaseShield : BaseArmor - { - public BaseShield(int itemID) : base(itemID) + public class BaseShield : BaseArmor { - } - - public BaseShield(Serial serial) : base(serial) - { - } - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override double ArmorRating - { - get - { - Mobile m = Parent as Mobile; - double ar = base.ArmorRating; - - if (m != null) - return m.Skills.Parry.Value * ar / 200.0 + 1.0; - return ar; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1) - { - if (this is Aegis) - return; - - // The 15 bonus points to resistances are not applied to shields on OSI. - PhysicalBonus = 0; - FireBonus = 0; - ColdBonus = 0; - PoisonBonus = 0; - EnergyBonus = 0; - } - } - - public override int OnHit(BaseWeapon weapon, int damage) - { - if (Core.AOS) - { - if (ArmorAttributes.SelfRepair > Utility.Random(10)) + public BaseShield(int itemID) : base(itemID) { - HitPoints += 2; - } - else - { - double halfArmor = ArmorRating / 2.0; - int absorbed = (int)(halfArmor + halfArmor * Utility.RandomDouble()); - - if (absorbed < 2) - absorbed = 2; - - int wear; - - if (weapon.Type == WeaponType.Bashing) - wear = absorbed / 2; - else - wear = Utility.Random(2); - - if (wear > 0 && MaxHitPoints > 0) - { - if (HitPoints >= wear) - { - HitPoints -= wear; - wear = 0; - } - else - { - wear -= HitPoints; - HitPoints = 0; - } - - if (wear > 0) - { - if (MaxHitPoints > wear) - { - MaxHitPoints -= wear; - - if (Parent is Mobile mobile) - mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1061121); // Your equipment is severely damaged. - } - else - { - Delete(); - } - } - } } - return 0; - } - - if (!(Parent is Mobile owner)) - return damage; - - double ar = ArmorRating; - double chance = (owner.Skills.Parry.Value - ar * 2.0) / 100.0; - - if (chance < 0.01) - chance = 0.01; - /* - FORMULA: Displayed AR = ((Parrying Skill * Base AR of Shield) � 200) + 1 - - FORMULA: % Chance of Blocking = parry skill - (shieldAR * 2) - - FORMULA: Melee Damage Absorbed = (AR of Shield) / 2 | Archery Damage Absorbed = AR of Shield - */ - if (owner.CheckSkill(SkillName.Parry, chance)) - { - if (weapon.Skill == SkillName.Archery) - damage -= (int)ar; - else - damage -= (int)(ar / 2.0); - - if (damage < 0) - damage = 0; - - owner.FixedEffect(0x37B9, 10, 16); - - if (Utility.Random(100) < 25) // 25% chance to lower durability + public BaseShield(Serial serial) : base(serial) { - int wear = Utility.Random(2); - - if (wear > 0 && MaxHitPoints > 0) - { - if (HitPoints >= wear) - { - HitPoints -= wear; - wear = 0; - } - else - { - wear -= HitPoints; - HitPoints = 0; - } - - if (wear > 0) - { - if (MaxHitPoints > wear) - { - MaxHitPoints -= wear; - - ((Mobile)Parent).LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1061121); // Your equipment is severely damaged. - } - else - { - Delete(); - } - } - } } - } - return damage; + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + public override double ArmorRating + { + get + { + var m = Parent as Mobile; + var ar = base.ArmorRating; + + if (m != null) + return m.Skills.Parry.Value * ar / 200.0 + 1.0; + return ar; + } + } + + 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 < 1) + { + if (this is Aegis) + return; + + // The 15 bonus points to resistances are not applied to shields on OSI. + PhysicalBonus = 0; + FireBonus = 0; + ColdBonus = 0; + PoisonBonus = 0; + EnergyBonus = 0; + } + } + + public override int OnHit(BaseWeapon weapon, int damage) + { + if (Core.AOS) + { + if (ArmorAttributes.SelfRepair > Utility.Random(10)) + { + HitPoints += 2; + } + else + { + var halfArmor = ArmorRating / 2.0; + var absorbed = (int)(halfArmor + halfArmor * Utility.RandomDouble()); + + if (absorbed < 2) + absorbed = 2; + + int wear; + + if (weapon.Type == WeaponType.Bashing) + wear = absorbed / 2; + else + wear = Utility.Random(2); + + if (wear > 0 && MaxHitPoints > 0) + { + if (HitPoints >= wear) + { + HitPoints -= wear; + wear = 0; + } + else + { + wear -= HitPoints; + HitPoints = 0; + } + + if (wear > 0) + { + if (MaxHitPoints > wear) + { + MaxHitPoints -= wear; + + if (Parent is Mobile mobile) + mobile.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1061121 + ); // Your equipment is severely damaged. + } + else + { + Delete(); + } + } + } + } + + return 0; + } + + if (!(Parent is Mobile owner)) + return damage; + + var ar = ArmorRating; + var chance = (owner.Skills.Parry.Value - ar * 2.0) / 100.0; + + if (chance < 0.01) + chance = 0.01; + /* + FORMULA: Displayed AR = ((Parrying Skill * Base AR of Shield) � 200) + 1 + + FORMULA: % Chance of Blocking = parry skill - (shieldAR * 2) + + FORMULA: Melee Damage Absorbed = (AR of Shield) / 2 | Archery Damage Absorbed = AR of Shield + */ + if (owner.CheckSkill(SkillName.Parry, chance)) + { + if (weapon.Skill == SkillName.Archery) + damage -= (int)ar; + else + damage -= (int)(ar / 2.0); + + if (damage < 0) + damage = 0; + + owner.FixedEffect(0x37B9, 10, 16); + + if (Utility.Random(100) < 25) // 25% chance to lower durability + { + var wear = Utility.Random(2); + + if (wear > 0 && MaxHitPoints > 0) + { + if (HitPoints >= wear) + { + HitPoints -= wear; + wear = 0; + } + else + { + wear -= HitPoints; + HitPoints = 0; + } + + if (wear > 0) + { + if (MaxHitPoints > wear) + { + MaxHitPoints -= wear; + + ((Mobile)Parent).LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1061121 + ); // Your equipment is severely damaged. + } + else + { + Delete(); + } + } + } + } + } + + return damage; + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Shields/BronzeShield.cs b/Projects/UOContent/Items/Shields/BronzeShield.cs index fbfb4a6db..c1e0dd85e 100644 --- a/Projects/UOContent/Items/Shields/BronzeShield.cs +++ b/Projects/UOContent/Items/Shields/BronzeShield.cs @@ -1,39 +1,39 @@ namespace Server.Items { - public class BronzeShield : BaseShield - { - [Constructible] - public BronzeShield() : base(0x1B72) => Weight = 6.0; - - public BronzeShield(Serial serial) : base(serial) + public class BronzeShield : BaseShield { + [Constructible] + public BronzeShield() : base(0x1B72) => Weight = 6.0; + + public BronzeShield(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 0; + public override int BaseColdResistance => 1; + public override int BasePoisonResistance => 0; + public override int BaseEnergyResistance => 0; + + public override int InitMinHits => 25; + public override int InitMaxHits => 30; + + public override int AosStrReq => 35; + + public override int ArmorBase => 10; + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } } - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 0; - public override int BaseColdResistance => 1; - public override int BasePoisonResistance => 0; - public override int BaseEnergyResistance => 0; - - public override int InitMinHits => 25; - public override int InitMaxHits => 30; - - public override int AosStrReq => 35; - - public override int ArmorBase => 10; - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Shields/Buckler.cs b/Projects/UOContent/Items/Shields/Buckler.cs index 76c775409..1db820691 100644 --- a/Projects/UOContent/Items/Shields/Buckler.cs +++ b/Projects/UOContent/Items/Shields/Buckler.cs @@ -1,39 +1,39 @@ namespace Server.Items { - public class Buckler : BaseShield - { - [Constructible] - public Buckler() : base(0x1B73) => Weight = 5.0; - - public Buckler(Serial serial) : base(serial) + public class Buckler : BaseShield { + [Constructible] + public Buckler() : base(0x1B73) => Weight = 5.0; + + public Buckler(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 0; + public override int BaseColdResistance => 0; + public override int BasePoisonResistance => 1; + public override int BaseEnergyResistance => 0; + + public override int InitMinHits => 40; + public override int InitMaxHits => 50; + + public override int AosStrReq => 20; + + public override int ArmorBase => 7; + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } } - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 0; - public override int BaseColdResistance => 0; - public override int BasePoisonResistance => 1; - public override int BaseEnergyResistance => 0; - - public override int InitMinHits => 40; - public override int InitMaxHits => 50; - - public override int AosStrReq => 20; - - public override int ArmorBase => 7; - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Shields/ChaosShield.cs b/Projects/UOContent/Items/Shields/ChaosShield.cs index b9bb6104a..9de7f7a68 100644 --- a/Projects/UOContent/Items/Shields/ChaosShield.cs +++ b/Projects/UOContent/Items/Shields/ChaosShield.cs @@ -2,70 +2,70 @@ using Server.Guilds; namespace Server.Items { - public class ChaosShield : BaseShield - { - [Constructible] - public ChaosShield() : base(0x1BC3) + public class ChaosShield : BaseShield { - if (!Core.AOS) - LootType = LootType.Newbied; + [Constructible] + public ChaosShield() : base(0x1BC3) + { + if (!Core.AOS) + LootType = LootType.Newbied; - Weight = 5.0; + Weight = 5.0; + } + + public ChaosShield(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 1; + public override int BaseFireResistance => 0; + public override int BaseColdResistance => 0; + public override int BasePoisonResistance => 0; + public override int BaseEnergyResistance => 0; + + public override int InitMinHits => 100; + public override int InitMaxHits => 125; + + public override int AosStrReq => 95; + + public override int ArmorBase => 32; + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override bool OnEquip(Mobile from) => Validate(from) && base.OnEquip(from); + + public override void OnSingleClick(Mobile from) + { + if (Validate(Parent as Mobile)) + base.OnSingleClick(from); + } + + public virtual bool Validate(Mobile m) + { + if (m?.Player != true || m.AccessLevel != AccessLevel.Player || Core.AOS) + return true; + + if (!(m.Guild is Guild g) || g.Type != GuildType.Chaos) + { + m.FixedEffect(0x3728, 10, 13); + Delete(); + + return false; + } + + return true; + } } - - public ChaosShield(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 1; - public override int BaseFireResistance => 0; - public override int BaseColdResistance => 0; - public override int BasePoisonResistance => 0; - public override int BaseEnergyResistance => 0; - - public override int InitMinHits => 100; - public override int InitMaxHits => 125; - - public override int AosStrReq => 95; - - public override int ArmorBase => 32; - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override bool OnEquip(Mobile from) => Validate(from) && base.OnEquip(from); - - public override void OnSingleClick(Mobile from) - { - if (Validate(Parent as Mobile)) - base.OnSingleClick(from); - } - - public virtual bool Validate(Mobile m) - { - if (m?.Player != true || m.AccessLevel != AccessLevel.Player || Core.AOS) - return true; - - if (!(m.Guild is Guild g) || g.Type != GuildType.Chaos) - { - m.FixedEffect(0x3728, 10, 13); - Delete(); - - return false; - } - - return true; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Shields/HeaterShield.cs b/Projects/UOContent/Items/Shields/HeaterShield.cs index 5739a4d45..d627456da 100644 --- a/Projects/UOContent/Items/Shields/HeaterShield.cs +++ b/Projects/UOContent/Items/Shields/HeaterShield.cs @@ -1,39 +1,39 @@ namespace Server.Items { - public class HeaterShield : BaseShield - { - [Constructible] - public HeaterShield() : base(0x1B76) => Weight = 8.0; - - public HeaterShield(Serial serial) : base(serial) + public class HeaterShield : BaseShield { + [Constructible] + public HeaterShield() : base(0x1B76) => Weight = 8.0; + + public HeaterShield(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 1; + public override int BaseColdResistance => 0; + public override int BasePoisonResistance => 0; + public override int BaseEnergyResistance => 0; + + public override int InitMinHits => 50; + public override int InitMaxHits => 65; + + public override int AosStrReq => 90; + + public override int ArmorBase => 23; + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } } - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 1; - public override int BaseColdResistance => 0; - public override int BasePoisonResistance => 0; - public override int BaseEnergyResistance => 0; - - public override int InitMinHits => 50; - public override int InitMaxHits => 65; - - public override int AosStrReq => 90; - - public override int ArmorBase => 23; - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Shields/MetalKiteShield.cs b/Projects/UOContent/Items/Shields/MetalKiteShield.cs index 0c67ccb4f..cd44bfb97 100644 --- a/Projects/UOContent/Items/Shields/MetalKiteShield.cs +++ b/Projects/UOContent/Items/Shields/MetalKiteShield.cs @@ -1,52 +1,52 @@ namespace Server.Items { - public class MetalKiteShield : BaseShield, IDyable - { - [Constructible] - public MetalKiteShield() : base(0x1B74) => Weight = 7.0; - - public MetalKiteShield(Serial serial) : base(serial) + public class MetalKiteShield : BaseShield, IDyable { + [Constructible] + public MetalKiteShield() : base(0x1B74) => Weight = 7.0; + + public MetalKiteShield(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 0; + public override int BaseColdResistance => 0; + public override int BasePoisonResistance => 0; + public override int BaseEnergyResistance => 1; + + public override int InitMinHits => 45; + public override int InitMaxHits => 60; + + public override int AosStrReq => 45; + + public override int ArmorBase => 16; + + public bool Dye(Mobile from, DyeTub sender) + { + if (Deleted) + return false; + + Hue = sender.DyedHue; + + return true; + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (Weight == 5.0) + Weight = 7.0; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } } - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 0; - public override int BaseColdResistance => 0; - public override int BasePoisonResistance => 0; - public override int BaseEnergyResistance => 1; - - public override int InitMinHits => 45; - public override int InitMaxHits => 60; - - public override int AosStrReq => 45; - - public override int ArmorBase => 16; - - public bool Dye(Mobile from, DyeTub sender) - { - if (Deleted) - return false; - - Hue = sender.DyedHue; - - return true; - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 5.0) - Weight = 7.0; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Shields/MetalShield.cs b/Projects/UOContent/Items/Shields/MetalShield.cs index 70ea813b3..a44a1b4ce 100644 --- a/Projects/UOContent/Items/Shields/MetalShield.cs +++ b/Projects/UOContent/Items/Shields/MetalShield.cs @@ -1,39 +1,39 @@ namespace Server.Items { - public class MetalShield : BaseShield - { - [Constructible] - public MetalShield() : base(0x1B7B) => Weight = 6.0; - - public MetalShield(Serial serial) : base(serial) + public class MetalShield : BaseShield { + [Constructible] + public MetalShield() : base(0x1B7B) => Weight = 6.0; + + public MetalShield(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 1; + public override int BaseColdResistance => 0; + public override int BasePoisonResistance => 0; + public override int BaseEnergyResistance => 0; + + public override int InitMinHits => 50; + public override int InitMaxHits => 65; + + public override int AosStrReq => 45; + + public override int ArmorBase => 11; + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } } - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 1; - public override int BaseColdResistance => 0; - public override int BasePoisonResistance => 0; - public override int BaseEnergyResistance => 0; - - public override int InitMinHits => 50; - public override int InitMaxHits => 65; - - public override int AosStrReq => 45; - - public override int ArmorBase => 11; - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Shields/OrderShield.cs b/Projects/UOContent/Items/Shields/OrderShield.cs index 4186a3281..2eb290196 100644 --- a/Projects/UOContent/Items/Shields/OrderShield.cs +++ b/Projects/UOContent/Items/Shields/OrderShield.cs @@ -2,73 +2,73 @@ using Server.Guilds; namespace Server.Items { - public class OrderShield : BaseShield - { - [Constructible] - public OrderShield() : base(0x1BC4) + public class OrderShield : BaseShield { - if (!Core.AOS) - LootType = LootType.Newbied; + [Constructible] + public OrderShield() : base(0x1BC4) + { + if (!Core.AOS) + LootType = LootType.Newbied; - Weight = 7.0; + Weight = 7.0; + } + + public OrderShield(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 1; + public override int BaseFireResistance => 0; + public override int BaseColdResistance => 0; + public override int BasePoisonResistance => 0; + public override int BaseEnergyResistance => 0; + + public override int InitMinHits => 100; + public override int InitMaxHits => 125; + + public override int AosStrReq => 95; + + public override int ArmorBase => 30; + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (Weight == 6.0) + Weight = 7.0; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override bool OnEquip(Mobile from) => Validate(from) && base.OnEquip(from); + + public override void OnSingleClick(Mobile from) + { + if (Validate(Parent as Mobile)) + base.OnSingleClick(from); + } + + public virtual bool Validate(Mobile m) + { + if (Core.AOS || m?.Player != true || m.AccessLevel != AccessLevel.Player) + return true; + + if (!(m.Guild is Guild g) || g.Type != GuildType.Order) + { + m.FixedEffect(0x3728, 10, 13); + Delete(); + + return false; + } + + return true; + } } - - public OrderShield(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 1; - public override int BaseFireResistance => 0; - public override int BaseColdResistance => 0; - public override int BasePoisonResistance => 0; - public override int BaseEnergyResistance => 0; - - public override int InitMinHits => 100; - public override int InitMaxHits => 125; - - public override int AosStrReq => 95; - - public override int ArmorBase => 30; - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 6.0) - Weight = 7.0; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override bool OnEquip(Mobile from) => Validate(from) && base.OnEquip(from); - - public override void OnSingleClick(Mobile from) - { - if (Validate(Parent as Mobile)) - base.OnSingleClick(from); - } - - public virtual bool Validate(Mobile m) - { - if (Core.AOS || m?.Player != true || m.AccessLevel != AccessLevel.Player) - return true; - - if (!(m.Guild is Guild g) || g.Type != GuildType.Order) - { - m.FixedEffect(0x3728, 10, 13); - Delete(); - - return false; - } - - return true; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Shields/WoodenKiteShield.cs b/Projects/UOContent/Items/Shields/WoodenKiteShield.cs index 70e3e25fc..7c9cc1a5c 100644 --- a/Projects/UOContent/Items/Shields/WoodenKiteShield.cs +++ b/Projects/UOContent/Items/Shields/WoodenKiteShield.cs @@ -1,42 +1,42 @@ namespace Server.Items { - public class WoodenKiteShield : BaseShield - { - [Constructible] - public WoodenKiteShield() : base(0x1B79) => Weight = 5.0; - - public WoodenKiteShield(Serial serial) : base(serial) + public class WoodenKiteShield : BaseShield { + [Constructible] + public WoodenKiteShield() : base(0x1B79) => Weight = 5.0; + + public WoodenKiteShield(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 0; + public override int BaseColdResistance => 0; + public override int BasePoisonResistance => 0; + public override int BaseEnergyResistance => 1; + + public override int InitMinHits => 50; + public override int InitMaxHits => 65; + + public override int AosStrReq => 20; + + public override int ArmorBase => 12; + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (Weight == 7.0) + Weight = 5.0; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } } - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 0; - public override int BaseColdResistance => 0; - public override int BasePoisonResistance => 0; - public override int BaseEnergyResistance => 1; - - public override int InitMinHits => 50; - public override int InitMaxHits => 65; - - public override int AosStrReq => 20; - - public override int ArmorBase => 12; - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 7.0) - Weight = 5.0; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Shields/WoodenShield.cs b/Projects/UOContent/Items/Shields/WoodenShield.cs index 8b602e5aa..5dd8ae7d0 100644 --- a/Projects/UOContent/Items/Shields/WoodenShield.cs +++ b/Projects/UOContent/Items/Shields/WoodenShield.cs @@ -1,39 +1,39 @@ namespace Server.Items { - public class WoodenShield : BaseShield - { - [Constructible] - public WoodenShield() : base(0x1B7A) => Weight = 5.0; - - public WoodenShield(Serial serial) : base(serial) + public class WoodenShield : BaseShield { + [Constructible] + public WoodenShield() : base(0x1B7A) => Weight = 5.0; + + public WoodenShield(Serial serial) : base(serial) + { + } + + public override int BasePhysicalResistance => 0; + public override int BaseFireResistance => 0; + public override int BaseColdResistance => 0; + public override int BasePoisonResistance => 0; + public override int BaseEnergyResistance => 1; + + public override int InitMinHits => 20; + public override int InitMaxHits => 25; + + public override int AosStrReq => 20; + + public override int ArmorBase => 8; + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } } - - public override int BasePhysicalResistance => 0; - public override int BaseFireResistance => 0; - public override int BaseColdResistance => 0; - public override int BasePoisonResistance => 0; - public override int BaseEnergyResistance => 1; - - public override int InitMinHits => 20; - public override int InitMaxHits => 25; - - public override int AosStrReq => 20; - - public override int ArmorBase => 8; - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Blacksmith Items/Misc/AnvilForge.cs b/Projects/UOContent/Items/Skill Items/Blacksmith Items/Misc/AnvilForge.cs index 2b377d05d..685f74fd7 100644 --- a/Projects/UOContent/Items/Skill Items/Blacksmith Items/Misc/AnvilForge.cs +++ b/Projects/UOContent/Items/Skill Items/Blacksmith Items/Misc/AnvilForge.cs @@ -2,54 +2,54 @@ using Server.Engines.Craft; namespace Server.Items { - [Flippable(0xFAF, 0xFB0)] - [Anvil] - public class Anvil : Item - { - [Constructible] - public Anvil() : base(0xFAF) => Movable = false; - - public Anvil(Serial serial) : base(serial) + [Flippable(0xFAF, 0xFB0)] + [Anvil] + public class Anvil : Item { + [Constructible] + public Anvil() : base(0xFAF) => Movable = false; + + public Anvil(Serial serial) : base(serial) + { + } + + 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 Serialize(IGenericWriter writer) + [Forge] + public class Forge : Item { - base.Serialize(writer); + [Constructible] + public Forge() : base(0xFB1) => Movable = false; - writer.Write(0); // version + public Forge(Serial serial) : base(serial) + { + } + + 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 Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Forge] - public class Forge : Item - { - [Constructible] - public Forge() : base(0xFB1) => Movable = false; - - public Forge(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Blacksmith Items/Misc/LargeForge.cs b/Projects/UOContent/Items/Skill Items/Blacksmith Items/Misc/LargeForge.cs index 40d25143c..8a7bc92b8 100644 --- a/Projects/UOContent/Items/Skill Items/Blacksmith Items/Misc/LargeForge.cs +++ b/Projects/UOContent/Items/Skill Items/Blacksmith Items/Misc/LargeForge.cs @@ -2,347 +2,347 @@ using Server.Engines.Craft; namespace Server.Items { - [Forge] - public class LargeForgeWest : Item - { - private InternalItem m_Item; - private InternalItem2 m_Item2; - - [Constructible] - public LargeForgeWest() : base(0x199A) + [Forge] + public class LargeForgeWest : Item { - Movable = false; + private InternalItem m_Item; + private InternalItem2 m_Item2; - m_Item = new InternalItem(this); - m_Item2 = new InternalItem2(this); - } + [Constructible] + public LargeForgeWest() : base(0x199A) + { + Movable = false; - public LargeForgeWest(Serial serial) : base(serial) - { - } + m_Item = new InternalItem(this); + m_Item2 = new InternalItem2(this); + } - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X, Y + 1, Z); - if (m_Item2 != null) - m_Item2.Location = new Point3D(X, Y + 2, Z); - } + public LargeForgeWest(Serial serial) : base(serial) + { + } - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - if (m_Item2 != null) - m_Item2.Map = Map; - } + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X, Y + 1, Z); + if (m_Item2 != null) + m_Item2.Location = new Point3D(X, Y + 2, Z); + } - public override void OnAfterDelete() - { - base.OnAfterDelete(); + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + if (m_Item2 != null) + m_Item2.Map = Map; + } - m_Item?.Delete(); - m_Item2?.Delete(); - } + public override void OnAfterDelete() + { + base.OnAfterDelete(); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + m_Item?.Delete(); + m_Item2?.Delete(); + } - writer.Write(0); // version + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(m_Item); - writer.Write(m_Item2); - } + writer.Write(0); // version - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + writer.Write(m_Item); + writer.Write(m_Item2); + } - int version = reader.ReadInt(); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - m_Item = reader.ReadItem() as InternalItem; - m_Item2 = reader.ReadItem() as InternalItem2; + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as InternalItem; + m_Item2 = reader.ReadItem() as InternalItem2; + } + + [Forge] + private class InternalItem : Item + { + private LargeForgeWest m_Item; + + public InternalItem(LargeForgeWest item) : base(0x1996) + { + Movable = false; + + m_Item = item; + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X, Y - 1, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as LargeForgeWest; + } + } + + [Forge] + private class InternalItem2 : Item + { + private LargeForgeWest m_Item; + + public InternalItem2(LargeForgeWest item) : base(0x1992) + { + Movable = false; + + m_Item = item; + } + + public InternalItem2(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X, Y - 2, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as LargeForgeWest; + } + } } [Forge] - private class InternalItem : Item + public class LargeForgeEast : Item { - private LargeForgeWest m_Item; + private InternalItem m_Item; + private InternalItem2 m_Item2; - public InternalItem(LargeForgeWest item) : base(0x1996) - { - Movable = false; + [Constructible] + public LargeForgeEast() : base(0x197A) + { + Movable = false; - m_Item = item; - } + m_Item = new InternalItem(this); + m_Item2 = new InternalItem2(this); + } - public InternalItem(Serial serial) : base(serial) - { - } + public LargeForgeEast(Serial serial) : base(serial) + { + } - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X, Y - 1, Z); - } + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X + 1, Y, Z); + if (m_Item2 != null) + m_Item2.Location = new Point3D(X + 2, Y, Z); + } - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + if (m_Item2 != null) + m_Item2.Map = Map; + } - public override void OnAfterDelete() - { - base.OnAfterDelete(); + public override void OnAfterDelete() + { + base.OnAfterDelete(); - m_Item?.Delete(); - } + m_Item?.Delete(); + m_Item2?.Delete(); + } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version + writer.Write(0); // version - writer.Write(m_Item); - } + writer.Write(m_Item); + writer.Write(m_Item2); + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); - m_Item = reader.ReadItem() as LargeForgeWest; - } + m_Item = reader.ReadItem() as InternalItem; + m_Item2 = reader.ReadItem() as InternalItem2; + } + + [Forge] + private class InternalItem : Item + { + private LargeForgeEast m_Item; + + public InternalItem(LargeForgeEast item) : base(0x197E) + { + Movable = false; + + m_Item = item; + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X - 1, Y, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as LargeForgeEast; + } + } + + [Forge] + private class InternalItem2 : Item + { + private LargeForgeEast m_Item; + + public InternalItem2(LargeForgeEast item) : base(0x1982) + { + Movable = false; + + m_Item = item; + } + + public InternalItem2(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (m_Item != null) + m_Item.Location = new Point3D(X - 2, Y, Z); + } + + public override void OnMapChange() + { + if (m_Item != null) + m_Item.Map = Map; + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Item?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Item); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Item = reader.ReadItem() as LargeForgeEast; + } + } } - - [Forge] - private class InternalItem2 : Item - { - private LargeForgeWest m_Item; - - public InternalItem2(LargeForgeWest item) : base(0x1992) - { - Movable = false; - - m_Item = item; - } - - public InternalItem2(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X, Y - 2, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as LargeForgeWest; - } - } - } - - [Forge] - public class LargeForgeEast : Item - { - private InternalItem m_Item; - private InternalItem2 m_Item2; - - [Constructible] - public LargeForgeEast() : base(0x197A) - { - Movable = false; - - m_Item = new InternalItem(this); - m_Item2 = new InternalItem2(this); - } - - public LargeForgeEast(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X + 1, Y, Z); - if (m_Item2 != null) - m_Item2.Location = new Point3D(X + 2, Y, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - if (m_Item2 != null) - m_Item2.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - m_Item2?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - writer.Write(m_Item2); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as InternalItem; - m_Item2 = reader.ReadItem() as InternalItem2; - } - - [Forge] - private class InternalItem : Item - { - private LargeForgeEast m_Item; - - public InternalItem(LargeForgeEast item) : base(0x197E) - { - Movable = false; - - m_Item = item; - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X - 1, Y, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as LargeForgeEast; - } - } - - [Forge] - private class InternalItem2 : Item - { - private LargeForgeEast m_Item; - - public InternalItem2(LargeForgeEast item) : base(0x1982) - { - Movable = false; - - m_Item = item; - } - - public InternalItem2(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (m_Item != null) - m_Item.Location = new Point3D(X - 2, Y, Z); - } - - public override void OnMapChange() - { - if (m_Item != null) - m_Item.Map = Map; - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Item?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Item); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Item = reader.ReadItem() as LargeForgeEast; - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Camping/Bedroll.cs b/Projects/UOContent/Items/Skill Items/Camping/Bedroll.cs index 3de092267..15bdd89ad 100644 --- a/Projects/UOContent/Items/Skill Items/Camping/Bedroll.cs +++ b/Projects/UOContent/Items/Skill Items/Camping/Bedroll.cs @@ -5,123 +5,123 @@ using Server.Network; namespace Server.Items { - [Flippable(0xA57, 0xA58, 0xA59)] - public class Bedroll : Item - { - [Constructible] - public Bedroll() : base(0xA57) => Weight = 5.0; - - public Bedroll(Serial serial) : base(serial) + [Flippable(0xA57, 0xA58, 0xA59)] + public class Bedroll : Item { - } + [Constructible] + public Bedroll() : base(0xA57) => Weight = 5.0; - public override void OnDoubleClick(Mobile from) - { - if (Parent != null || !VerifyMove(from)) - return; - - if (!from.InRange(this, 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return; - } - - if (ItemID == 0xA57) // rolled - { - Direction dir = PlayerMobile.GetDirection4(from.Location, Location); - - if (dir == Direction.North || dir == Direction.South) - ItemID = 0xA55; - else - ItemID = 0xA56; - } - else // unrolled - { - ItemID = 0xA57; - - if (!from.HasGump()) + public Bedroll(Serial serial) : base(serial) { - CampfireEntry entry = Campfire.GetEntry(from); - - if (entry?.Safe == true) - from.SendGump(new LogoutGump(entry, this)); - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - private class LogoutGump : Gump - { - private readonly Bedroll m_Bedroll; - private readonly Timer m_CloseTimer; - - private readonly CampfireEntry m_Entry; - - public LogoutGump(CampfireEntry entry, Bedroll bedroll) : base(100, 0) - { - m_Entry = entry; - m_Bedroll = bedroll; - - m_CloseTimer = Timer.DelayCall(TimeSpan.FromSeconds(10.0), CloseGump); - - AddBackground(0, 0, 400, 350, 0xA28); - - AddHtmlLocalized(100, 20, 200, 35, 1011015); //
Logging out via camping
- - /* Using a bedroll in the safety of a camp will log you out of the game safely. - * If this is what you wish to do choose CONTINUE and you will be logged out. - * Otherwise, select the CANCEL button to avoid logging out at this time. - * The camp will remain secure for 10 seconds at which time this window will close - * and you not be logged out. - */ - AddHtmlLocalized(50, 55, 300, 140, 1011016, true, true); - - AddButton(45, 298, 0xFA5, 0xFA7, 1); - AddHtmlLocalized(80, 300, 110, 35, 1011011); // CONTINUE - - AddButton(200, 298, 0xFA5, 0xFA7, 0); - AddHtmlLocalized(235, 300, 110, 35, 1011012); // CANCEL - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - PlayerMobile pm = m_Entry.Player; - - m_CloseTimer.Stop(); - - if (Campfire.GetEntry(pm) != m_Entry) - return; - - if (info.ButtonID == 1 && m_Entry.Safe && m_Bedroll.Parent == null && m_Bedroll.IsAccessibleTo(pm) - && m_Bedroll.VerifyMove(pm) && m_Bedroll.Map == pm.Map && pm.InRange(m_Bedroll, 2)) - { - pm.PlaceInBackpack(m_Bedroll); - - pm.BedrollLogout = true; - sender.Dispose(); } - Campfire.RemoveEntry(m_Entry); - } + public override void OnDoubleClick(Mobile from) + { + if (Parent != null || !VerifyMove(from)) + return; - private void CloseGump() - { - Campfire.RemoveEntry(m_Entry); - m_Entry.Player.CloseGump(); - } + if (!from.InRange(this, 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return; + } + + if (ItemID == 0xA57) // rolled + { + var dir = PlayerMobile.GetDirection4(from.Location, Location); + + if (dir == Direction.North || dir == Direction.South) + ItemID = 0xA55; + else + ItemID = 0xA56; + } + else // unrolled + { + ItemID = 0xA57; + + if (!from.HasGump()) + { + var entry = Campfire.GetEntry(from); + + if (entry?.Safe == true) + from.SendGump(new LogoutGump(entry, this)); + } + } + } + + 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(); + } + + private class LogoutGump : Gump + { + private readonly Bedroll m_Bedroll; + private readonly Timer m_CloseTimer; + + private readonly CampfireEntry m_Entry; + + public LogoutGump(CampfireEntry entry, Bedroll bedroll) : base(100, 0) + { + m_Entry = entry; + m_Bedroll = bedroll; + + m_CloseTimer = Timer.DelayCall(TimeSpan.FromSeconds(10.0), CloseGump); + + AddBackground(0, 0, 400, 350, 0xA28); + + AddHtmlLocalized(100, 20, 200, 35, 1011015); //
Logging out via camping
+ + /* Using a bedroll in the safety of a camp will log you out of the game safely. + * If this is what you wish to do choose CONTINUE and you will be logged out. + * Otherwise, select the CANCEL button to avoid logging out at this time. + * The camp will remain secure for 10 seconds at which time this window will close + * and you not be logged out. + */ + AddHtmlLocalized(50, 55, 300, 140, 1011016, true, true); + + AddButton(45, 298, 0xFA5, 0xFA7, 1); + AddHtmlLocalized(80, 300, 110, 35, 1011011); // CONTINUE + + AddButton(200, 298, 0xFA5, 0xFA7, 0); + AddHtmlLocalized(235, 300, 110, 35, 1011012); // CANCEL + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var pm = m_Entry.Player; + + m_CloseTimer.Stop(); + + if (Campfire.GetEntry(pm) != m_Entry) + return; + + if (info.ButtonID == 1 && m_Entry.Safe && m_Bedroll.Parent == null && m_Bedroll.IsAccessibleTo(pm) + && m_Bedroll.VerifyMove(pm) && m_Bedroll.Map == pm.Map && pm.InRange(m_Bedroll, 2)) + { + pm.PlaceInBackpack(m_Bedroll); + + pm.BedrollLogout = true; + sender.Dispose(); + } + + Campfire.RemoveEntry(m_Entry); + } + + private void CloseGump() + { + Campfire.RemoveEntry(m_Entry); + m_Entry.Player.CloseGump(); + } + } } - } } diff --git a/Projects/UOContent/Items/Skill Items/Camping/Campfire.cs b/Projects/UOContent/Items/Skill Items/Camping/Campfire.cs index e35554d1f..d39684feb 100644 --- a/Projects/UOContent/Items/Skill Items/Camping/Campfire.cs +++ b/Projects/UOContent/Items/Skill Items/Camping/Campfire.cs @@ -2,193 +2,194 @@ using System; using System.Collections.Generic; using System.Linq; using Server.Mobiles; -using Server.Network; namespace Server.Items { - public enum CampfireStatus - { - Burning, - Extinguishing, - Off - } - - public class Campfire : Item - { - public static readonly int SecureRange = 7; - - private static readonly Dictionary m_Table = new Dictionary(); - - private readonly List m_Entries; - - private readonly Timer m_Timer; - - public Campfire() : base(0xDE3) + public enum CampfireStatus { - Movable = false; - Light = LightType.Circle300; - - m_Entries = new List(); - - Created = DateTime.UtcNow; - m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0), OnTick); + Burning, + Extinguishing, + Off } - public Campfire(Serial serial) : base(serial) + public class Campfire : Item { - } + public static readonly int SecureRange = 7; - [CommandProperty(AccessLevel.GameMaster)] - public DateTime Created { get; } + private static readonly Dictionary m_Table = new Dictionary(); - [CommandProperty(AccessLevel.GameMaster)] - public CampfireStatus Status - { - get - { - return ItemID switch + private readonly List m_Entries; + + private readonly Timer m_Timer; + + public Campfire() : base(0xDE3) { - 0xDE3 => CampfireStatus.Burning, - 0xDE9 => CampfireStatus.Extinguishing, - _ => CampfireStatus.Off - }; - } - set - { - if (Status == value) - return; - - switch (value) - { - case CampfireStatus.Burning: - ItemID = 0xDE3; + Movable = false; Light = LightType.Circle300; - break; - case CampfireStatus.Extinguishing: - ItemID = 0xDE9; - Light = LightType.Circle150; - break; + m_Entries = new List(); + + Created = DateTime.UtcNow; + m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0), OnTick); + } + + public Campfire(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime Created { get; } + + [CommandProperty(AccessLevel.GameMaster)] + public CampfireStatus Status + { + get + { + return ItemID switch + { + 0xDE3 => CampfireStatus.Burning, + 0xDE9 => CampfireStatus.Extinguishing, + _ => CampfireStatus.Off + }; + } + set + { + if (Status == value) + return; + + switch (value) + { + case CampfireStatus.Burning: + ItemID = 0xDE3; + Light = LightType.Circle300; + break; + + case CampfireStatus.Extinguishing: + ItemID = 0xDE9; + Light = LightType.Circle150; + break; + + default: + ItemID = 0xDEA; + Light = LightType.ArchedWindowEast; + ClearEntries(); + break; + } + } + } + + public static CampfireEntry GetEntry(Mobile player) + { + m_Table.TryGetValue(player, out var value); + return value; + } + + public static void RemoveEntry(CampfireEntry entry) + { + m_Table.Remove(entry.Player); + entry.Fire.m_Entries.Remove(entry); + } + + private void OnTick() + { + var now = DateTime.UtcNow; + var age = now - Created; + + if (age >= TimeSpan.FromSeconds(100.0)) + Delete(); + else if (age >= TimeSpan.FromSeconds(90.0)) + Status = CampfireStatus.Off; + else if (age >= TimeSpan.FromSeconds(60.0)) + Status = CampfireStatus.Extinguishing; + + if (Status == CampfireStatus.Off || Deleted) + return; + + foreach (var entry in m_Entries.ToList()) + if (!entry.Valid || entry.Player.NetState == null) + { + RemoveEntry(entry); + } + else if (!entry.Safe && now - entry.Start >= TimeSpan.FromSeconds(30.0)) + { + entry.Safe = true; + entry.Player.SendLocalizedMessage(500621); // The camp is now secure. + } + + var eable = GetClientsInRange(SecureRange); + + foreach (var state in eable) + if (state.Mobile is PlayerMobile pm && GetEntry(pm) == null) + { + var entry = new CampfireEntry(pm, this); + + m_Table[pm] = entry; + m_Entries.Add(entry); + + pm.SendLocalizedMessage(500620); // You feel it would take a few moments to secure your camp. + } + + eable.Free(); + } + + private void ClearEntries() + { + if (m_Entries == null) + return; + + foreach (var entry in m_Entries.ToList()) + RemoveEntry(entry); + } + + public override void OnAfterDelete() + { + m_Timer?.Stop(); - default: - ItemID = 0xDEA; - Light = LightType.ArchedWindowEast; ClearEntries(); - break; } - } - } - public static CampfireEntry GetEntry(Mobile player) - { - m_Table.TryGetValue(player, out CampfireEntry value); - return value; - } - - public static void RemoveEntry(CampfireEntry entry) - { - m_Table.Remove(entry.Player); - entry.Fire.m_Entries.Remove(entry); - } - - private void OnTick() - { - DateTime now = DateTime.UtcNow; - TimeSpan age = now - Created; - - if (age >= TimeSpan.FromSeconds(100.0)) - Delete(); - else if (age >= TimeSpan.FromSeconds(90.0)) - Status = CampfireStatus.Off; - else if (age >= TimeSpan.FromSeconds(60.0)) - Status = CampfireStatus.Extinguishing; - - if (Status == CampfireStatus.Off || Deleted) - return; - - foreach (CampfireEntry entry in m_Entries.ToList()) - if (!entry.Valid || entry.Player.NetState == null) - RemoveEntry(entry); - else if (!entry.Safe && now - entry.Start >= TimeSpan.FromSeconds(30.0)) + public override void Serialize(IGenericWriter writer) { - entry.Safe = true; - entry.Player.SendLocalizedMessage(500621); // The camp is now secure. + base.Serialize(writer); + + writer.Write(0); // version } - IPooledEnumerable eable = GetClientsInRange(SecureRange); - - foreach (NetState state in eable) - if (state.Mobile is PlayerMobile pm && GetEntry(pm) == null) + public override void Deserialize(IGenericReader reader) { - CampfireEntry entry = new CampfireEntry(pm, this); + base.Deserialize(reader); - m_Table[pm] = entry; - m_Entries.Add(entry); + var version = reader.ReadInt(); - pm.SendLocalizedMessage(500620); // You feel it would take a few moments to secure your camp. + Delete(); + } + } + + public class CampfireEntry + { + private bool m_Safe; + + public CampfireEntry(PlayerMobile player, Campfire fire) + { + Player = player; + Fire = fire; + Start = DateTime.UtcNow; + m_Safe = false; } - eable.Free(); + public PlayerMobile Player { get; } + + public Campfire Fire { get; } + + public DateTime Start { get; } + + public bool Valid => !Fire.Deleted && Fire.Status != CampfireStatus.Off && Player.Map == Fire.Map && + Player.InRange(Fire, Campfire.SecureRange); + + public bool Safe + { + get => Valid && m_Safe; + set => m_Safe = value; + } } - - private void ClearEntries() - { - if (m_Entries == null) - return; - - foreach (CampfireEntry entry in m_Entries.ToList()) - RemoveEntry(entry); - } - - public override void OnAfterDelete() - { - m_Timer?.Stop(); - - ClearEntries(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Delete(); - } - } - - public class CampfireEntry - { - private bool m_Safe; - - public CampfireEntry(PlayerMobile player, Campfire fire) - { - Player = player; - Fire = fire; - Start = DateTime.UtcNow; - m_Safe = false; - } - - public PlayerMobile Player { get; } - - public Campfire Fire { get; } - - public DateTime Start { get; } - - public bool Valid => !Fire.Deleted && Fire.Status != CampfireStatus.Off && Player.Map == Fire.Map && - Player.InRange(Fire, Campfire.SecureRange); - - public bool Safe - { - get => Valid && m_Safe; - set => m_Safe = value; - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Camping/Kindling.cs b/Projects/UOContent/Items/Skill Items/Camping/Kindling.cs index 35be1b984..a3d6454b4 100644 --- a/Projects/UOContent/Items/Skill Items/Camping/Kindling.cs +++ b/Projects/UOContent/Items/Skill Items/Camping/Kindling.cs @@ -4,107 +4,107 @@ using Server.Regions; namespace Server.Items { - public class Kindling : Item - { - [Constructible] - public Kindling(int amount = 1) : base(0xDE1) + public class Kindling : Item { - Stackable = true; - Weight = 5.0; - Amount = amount; + [Constructible] + public Kindling(int amount = 1) : base(0xDE1) + { + Stackable = true; + Weight = 5.0; + Amount = amount; + } + + public Kindling(Serial serial) : base(serial) + { + } + + 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 (!VerifyMove(from)) + return; + + if (!from.InRange(GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return; + } + + var fireLocation = GetFireLocation(from); + + if (fireLocation == Point3D.Zero) + { + from.SendLocalizedMessage(501695); // There is not a spot nearby to place your campfire. + } + else if (!from.CheckSkill(SkillName.Camping, 0.0, 100.0)) + { + from.SendLocalizedMessage(501696); // You fail to ignite the campfire. + } + else + { + Consume(); + + if (!Deleted && Parent == null) + from.PlaceInBackpack(this); + + new Campfire().MoveToWorld(fireLocation, from.Map); + } + } + + private Point3D GetFireLocation(Mobile from) + { + if (from.Region.IsPartOf()) + return Point3D.Zero; + + if (Parent == null) + return Location; + + var list = new List(4); + + AddOffsetLocation(from, 0, -1, list); + AddOffsetLocation(from, -1, 0, list); + AddOffsetLocation(from, 0, 1, list); + AddOffsetLocation(from, 1, 0, list); + + if (list.Count == 0) + return Point3D.Zero; + + return list.RandomElement(); + } + + private void AddOffsetLocation(Mobile from, int offsetX, int offsetY, List list) + { + var map = from.Map; + + var x = from.X + offsetX; + var y = from.Y + offsetY; + + var loc = new Point3D(x, y, from.Z); + + if (map.CanFit(loc, 1) && from.InLOS(loc)) + { + list.Add(loc); + } + else + { + loc = new Point3D(x, y, map.GetAverageZ(x, y)); + + if (map.CanFit(loc, 1) && from.InLOS(loc)) + list.Add(loc); + } + } } - - public Kindling(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - if (!VerifyMove(from)) - return; - - if (!from.InRange(GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return; - } - - Point3D fireLocation = GetFireLocation(from); - - if (fireLocation == Point3D.Zero) - { - from.SendLocalizedMessage(501695); // There is not a spot nearby to place your campfire. - } - else if (!from.CheckSkill(SkillName.Camping, 0.0, 100.0)) - { - from.SendLocalizedMessage(501696); // You fail to ignite the campfire. - } - else - { - Consume(); - - if (!Deleted && Parent == null) - from.PlaceInBackpack(this); - - new Campfire().MoveToWorld(fireLocation, from.Map); - } - } - - private Point3D GetFireLocation(Mobile from) - { - if (from.Region.IsPartOf()) - return Point3D.Zero; - - if (Parent == null) - return Location; - - List list = new List(4); - - AddOffsetLocation(from, 0, -1, list); - AddOffsetLocation(from, -1, 0, list); - AddOffsetLocation(from, 0, 1, list); - AddOffsetLocation(from, 1, 0, list); - - if (list.Count == 0) - return Point3D.Zero; - - return list.RandomElement(); - } - - private void AddOffsetLocation(Mobile from, int offsetX, int offsetY, List list) - { - Map map = from.Map; - - int x = from.X + offsetX; - int y = from.Y + offsetY; - - Point3D loc = new Point3D(x, y, from.Z); - - if (map.CanFit(loc, 1) && from.InLOS(loc)) - { - list.Add(loc); - } - else - { - loc = new Point3D(x, y, map.GetAverageZ(x, y)); - - if (map.CanFit(loc, 1) && from.InLOS(loc)) - list.Add(loc); - } - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Carpenter Items/Board.cs b/Projects/UOContent/Items/Skill Items/Carpenter Items/Board.cs index f2d2c16cc..3dede79ee 100644 --- a/Projects/UOContent/Items/Skill Items/Carpenter Items/Board.cs +++ b/Projects/UOContent/Items/Skill Items/Carpenter Items/Board.cs @@ -1,275 +1,275 @@ namespace Server.Items { - [Flippable(0x1BD7, 0x1BDA)] - public class Board : Item, ICommodity - { - private CraftResource m_Resource; - - [Constructible] - public Board(int amount = 1) - : this(CraftResource.RegularWood, amount) + [Flippable(0x1BD7, 0x1BDA)] + public class Board : Item, ICommodity { - } + private CraftResource m_Resource; - public Board(Serial serial) - : base(serial) - { - } - - [Constructible] - public Board(CraftResource resource, int amount = 1) - : base(0x1BD7) - { - Stackable = true; - Amount = amount; - - m_Resource = resource; - Hue = CraftResources.GetHue(resource); - } - - [CommandProperty(AccessLevel.GameMaster)] - public CraftResource Resource - { - get => m_Resource; - set - { - m_Resource = value; - InvalidateProperties(); - } - } - - int ICommodity.DescriptionNumber - { - get - { - if (m_Resource >= CraftResource.OakWood && m_Resource <= CraftResource.YewWood) - return 1075052 + ((int)m_Resource - (int)CraftResource.OakWood); - - return m_Resource switch + [Constructible] + public Board(int amount = 1) + : this(CraftResource.RegularWood, amount) { - CraftResource.Bloodwood => 1075055, - CraftResource.Frostwood => 1075056, - CraftResource.Heartwood => 1075062, // WHY Osi. Why? - _ => LabelNumber - }; - } + } + + public Board(Serial serial) + : base(serial) + { + } + + [Constructible] + public Board(CraftResource resource, int amount = 1) + : base(0x1BD7) + { + Stackable = true; + Amount = amount; + + m_Resource = resource; + Hue = CraftResources.GetHue(resource); + } + + [CommandProperty(AccessLevel.GameMaster)] + public CraftResource Resource + { + get => m_Resource; + set + { + m_Resource = value; + InvalidateProperties(); + } + } + + int ICommodity.DescriptionNumber + { + get + { + if (m_Resource >= CraftResource.OakWood && m_Resource <= CraftResource.YewWood) + return 1075052 + ((int)m_Resource - (int)CraftResource.OakWood); + + return m_Resource switch + { + CraftResource.Bloodwood => 1075055, + CraftResource.Frostwood => 1075056, + CraftResource.Heartwood => 1075062, // WHY Osi. Why? + _ => LabelNumber + }; + } + } + + bool ICommodity.IsDeedable => true; + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (!CraftResources.IsStandard(m_Resource)) + { + var num = CraftResources.GetLocalizationNumber(m_Resource); + + if (num > 0) + list.Add(num); + else + list.Add(CraftResources.GetName(m_Resource)); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(3); + + writer.Write((int)m_Resource); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 3: + case 2: + { + m_Resource = (CraftResource)reader.ReadInt(); + break; + } + } + + if (version == 0 && Weight == 0.1 || version <= 2 && Weight == 2) + Weight = -1; + + if (version <= 1) + m_Resource = CraftResource.RegularWood; + } } - bool ICommodity.IsDeedable => true; - - public override void GetProperties(ObjectPropertyList list) + public class HeartwoodBoard : Board { - base.GetProperties(list); + [Constructible] + public HeartwoodBoard(int amount = 1) + : base(CraftResource.Heartwood, amount) + { + } - if (!CraftResources.IsStandard(m_Resource)) - { - int num = CraftResources.GetLocalizationNumber(m_Resource); + public HeartwoodBoard(Serial serial) + : base(serial) + { + } - if (num > 0) - list.Add(num); - else - list.Add(CraftResources.GetName(m_Resource)); - } + 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 Serialize(IGenericWriter writer) + public class BloodwoodBoard : Board { - base.Serialize(writer); + [Constructible] + public BloodwoodBoard(int amount = 1) + : base(CraftResource.Bloodwood, amount) + { + } - writer.Write(3); + public BloodwoodBoard(Serial serial) + : base(serial) + { + } - writer.Write((int)m_Resource); + 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 Deserialize(IGenericReader reader) + public class FrostwoodBoard : Board { - base.Deserialize(reader); + [Constructible] + public FrostwoodBoard(int amount = 1) + : base(CraftResource.Frostwood, amount) + { + } - int version = reader.ReadInt(); + public FrostwoodBoard(Serial serial) + : base(serial) + { + } - switch (version) - { - case 3: - case 2: - { - m_Resource = (CraftResource)reader.ReadInt(); - break; - } - } + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - if ((version == 0 && Weight == 0.1) || (version <= 2 && Weight == 2)) - Weight = -1; + writer.Write(0); // version + } - if (version <= 1) - m_Resource = CraftResource.RegularWood; + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } } - } - public class HeartwoodBoard : Board - { - [Constructible] - public HeartwoodBoard(int amount = 1) - : base(CraftResource.Heartwood, amount) + public class OakBoard : Board { + [Constructible] + public OakBoard(int amount = 1) + : base(CraftResource.OakWood, amount) + { + } + + public OakBoard(Serial serial) + : base(serial) + { + } + + 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 HeartwoodBoard(Serial serial) - : base(serial) + public class AshBoard : Board { + [Constructible] + public AshBoard(int amount = 1) + : base(CraftResource.AshWood, amount) + { + } + + public AshBoard(Serial serial) + : base(serial) + { + } + + 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 Serialize(IGenericWriter writer) + public class YewBoard : Board { - base.Serialize(writer); + [Constructible] + public YewBoard(int amount = 1) + : base(CraftResource.YewWood, amount) + { + } - writer.Write(0); // version + public YewBoard(Serial serial) + : base(serial) + { + } + + 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 Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class BloodwoodBoard : Board - { - [Constructible] - public BloodwoodBoard(int amount = 1) - : base(CraftResource.Bloodwood, amount) - { - } - - public BloodwoodBoard(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class FrostwoodBoard : Board - { - [Constructible] - public FrostwoodBoard(int amount = 1) - : base(CraftResource.Frostwood, amount) - { - } - - public FrostwoodBoard(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class OakBoard : Board - { - [Constructible] - public OakBoard(int amount = 1) - : base(CraftResource.OakWood, amount) - { - } - - public OakBoard(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class AshBoard : Board - { - [Constructible] - public AshBoard(int amount = 1) - : base(CraftResource.AshWood, amount) - { - } - - public AshBoard(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class YewBoard : Board - { - [Constructible] - public YewBoard(int amount = 1) - : base(CraftResource.YewWood, amount) - { - } - - public YewBoard(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Carpenter Items/TaxidermyKit.cs b/Projects/UOContent/Items/Skill Items/Carpenter Items/TaxidermyKit.cs index 85075cd69..b010c1bc0 100644 --- a/Projects/UOContent/Items/Skill Items/Carpenter Items/TaxidermyKit.cs +++ b/Projects/UOContent/Items/Skill Items/Carpenter Items/TaxidermyKit.cs @@ -5,516 +5,531 @@ using Server.Targeting; namespace Server.Items { - [Flippable(0x1EBA, 0x1EBB)] - public class TaxidermyKit : Item - { - private static readonly TrophyInfo[] m_Table = + [Flippable(0x1EBA, 0x1EBB)] + public class TaxidermyKit : Item { - new TrophyInfo(typeof(BrownBear), 0x1E60, 1041093, 1041107), - new TrophyInfo(typeof(GreatHart), 0x1E61, 1041095, 1041109), - new TrophyInfo(typeof(BigFish), 0x1E62, 1041096, 1041110), - new TrophyInfo(typeof(Gorilla), 0x1E63, 1041091, 1041105), - new TrophyInfo(typeof(Orc), 0x1E64, 1041090, 1041104), - new TrophyInfo(typeof(PolarBear), 0x1E65, 1041094, 1041108), - new TrophyInfo(typeof(Troll), 0x1E66, 1041092, 1041106) - }; - - [Constructible] - public TaxidermyKit() : base(0x1EBA) => Weight = 1.0; - - public TaxidermyKit(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041279; // a taxidermy kit - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (from.Skills.Carpentry.Base < 90.0) - { - from.SendLocalizedMessage(1042594); // You do not understand how to use this. - } - else - { - from.SendLocalizedMessage(1042595); // Target the corpse to make a trophy out of. - from.Target = new CorpseTarget(this); - } - } - - public class TrophyInfo - { - public TrophyInfo(Type type, int id, int deedNum, int addonNum) - { - CreatureType = type; - NorthID = id; - DeedNumber = deedNum; - AddonNumber = addonNum; - } - - public Type CreatureType { get; } - - public int NorthID { get; } - - public int DeedNumber { get; } - - public int AddonNumber { get; } - } - - private class CorpseTarget : Target - { - private readonly TaxidermyKit m_Kit; - - public CorpseTarget(TaxidermyKit kit) : base(3, false, TargetFlags.None) => m_Kit = kit; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Kit.Deleted) - return; - - Corpse corpse = targeted as Corpse; - - if (!(corpse != null || targeted is BigFish)) + private static readonly TrophyInfo[] m_Table = + { + new TrophyInfo(typeof(BrownBear), 0x1E60, 1041093, 1041107), + new TrophyInfo(typeof(GreatHart), 0x1E61, 1041095, 1041109), + new TrophyInfo(typeof(BigFish), 0x1E62, 1041096, 1041110), + new TrophyInfo(typeof(Gorilla), 0x1E63, 1041091, 1041105), + new TrophyInfo(typeof(Orc), 0x1E64, 1041090, 1041104), + new TrophyInfo(typeof(PolarBear), 0x1E65, 1041094, 1041108), + new TrophyInfo(typeof(Troll), 0x1E66, 1041092, 1041106) + }; + + [Constructible] + public TaxidermyKit() : base(0x1EBA) => Weight = 1.0; + + public TaxidermyKit(Serial serial) : base(serial) { - from.SendLocalizedMessage(1042600); // That is not a corpse! } - else if (corpse?.VisitedByTaxidermist == true) - { - from.SendLocalizedMessage(1042596); // That corpse seems to have been visited by a taxidermist already. - } - else if (!m_Kit.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (from.Skills.Carpentry.Base < 90.0) - { - from.SendLocalizedMessage(1042603); // You would not understand how to use the kit. - } - else - { - object obj = corpse?.Owner ?? targeted; - foreach (TrophyInfo t in m_Table) - { - if (t.CreatureType != obj.GetType()) - continue; + public override int LabelNumber => 1041279; // a taxidermy kit - Container pack = from.Backpack; + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - if (pack?.ConsumeTotal(typeof(Board), 10) == true) + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) { - from.SendLocalizedMessage( - 1042278); // You review the corpse and find it worthy of a trophy. - from.SendLocalizedMessage(1042602); // You use your kit up making the trophy. + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else if (from.Skills.Carpentry.Base < 90.0) + { + from.SendLocalizedMessage(1042594); // You do not understand how to use this. + } + else + { + from.SendLocalizedMessage(1042595); // Target the corpse to make a trophy out of. + from.Target = new CorpseTarget(this); + } + } - Mobile hunter = null; - int weight = 0; - - if (targeted is BigFish fish) - { - hunter = fish.Fisher; - weight = (int)fish.Weight; - - fish.Consume(); - } - - from.AddToBackpack(new TrophyDeed(t, hunter, weight)); - - if (corpse != null) - corpse.VisitedByTaxidermist = true; - - m_Kit.Delete(); - return; + public class TrophyInfo + { + public TrophyInfo(Type type, int id, int deedNum, int addonNum) + { + CreatureType = type; + NorthID = id; + DeedNumber = deedNum; + AddonNumber = addonNum; } - from.SendLocalizedMessage(1042598); // You do not have enough boards. - return; - } + public Type CreatureType { get; } - from.SendLocalizedMessage(1042599); // That does not look like something you want hanging on a wall. - } - } - } - } + public int NorthID { get; } - public class TrophyAddon : Item, IAddon - { - private int m_AddonNumber; - private int m_AnimalWeight; + public int DeedNumber { get; } - private Mobile m_Hunter; - - public TrophyAddon(Mobile from, int itemID, int westID, int northID, int deedNumber, - int addonNumber, Mobile hunter = null, int animalWeight = 0) : base(itemID) - { - WestID = westID; - NorthID = northID; - DeedNumber = deedNumber; - m_AddonNumber = addonNumber; - - m_Hunter = hunter; - m_AnimalWeight = animalWeight; - - Movable = false; - - MoveToWorld(from.Location, from.Map); - } - - public TrophyAddon(Serial serial) : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - [CommandProperty(AccessLevel.GameMaster)] - public int WestID { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int NorthID { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int DeedNumber { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int AddonNumber - { - get => m_AddonNumber; - set - { - m_AddonNumber = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Hunter - { - get => m_Hunter; - set - { - m_Hunter = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int AnimalWeight - { - get => m_AnimalWeight; - set - { - m_AnimalWeight = value; - InvalidateProperties(); - } - } - - public override int LabelNumber => m_AddonNumber; - - public bool CouldFit(IPoint3D p, Map map) - { - if (!map.CanFit(p.X, p.Y, p.Z, ItemData.Height)) - return false; - - if (ItemID == NorthID) - return BaseAddon.IsWall(p.X, p.Y - 1, p.Z, map); // North wall - return BaseAddon.IsWall(p.X - 1, p.Y, p.Z, map); // West wall - } - - public Item Deed => new TrophyDeed(WestID, NorthID, DeedNumber, m_AddonNumber, m_Hunter, m_AnimalWeight); - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_AnimalWeight >= 20) - { - if (m_Hunter != null) - list.Add(1070857, m_Hunter.Name); // Caught by ~1_fisherman~ - - list.Add(1070858, m_AnimalWeight.ToString()); // ~1_weight~ stones - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(m_Hunter); - writer.Write(m_AnimalWeight); - - writer.Write(WestID); - writer.Write(NorthID); - writer.Write(DeedNumber); - writer.Write(m_AddonNumber); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_Hunter = reader.ReadMobile(); - m_AnimalWeight = reader.ReadInt(); - goto case 0; - } - case 0: - { - WestID = reader.ReadInt(); - NorthID = reader.ReadInt(); - DeedNumber = reader.ReadInt(); - m_AddonNumber = reader.ReadInt(); - break; - } - } - - Timer.DelayCall(FixMovingCrate); - } - - private void FixMovingCrate() - { - if (Deleted) - return; - - if (Movable || IsLockedDown) - { - Item deed = Deed; - - if (Parent is Item item) - { - item.AddItem(deed); - deed.Location = Location; - } - else - { - deed.MoveToWorld(Location, Map); + public int AddonNumber { get; } } - Delete(); - } - } - - public override void OnDoubleClick(Mobile from) - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (house?.IsCoOwner(from) == true) - { - if (from.InRange(GetWorldLocation(), 1)) + private class CorpseTarget : Target { - from.AddToBackpack(Deed); - Delete(); - } - else - { - from.SendLocalizedMessage(500295); // You are too far away to do that. - } - } - } - } + private readonly TaxidermyKit m_Kit; - [Flippable(0x14F0, 0x14EF)] - public class TrophyDeed : Item - { - private int m_AnimalWeight; - private int m_DeedNumber; + public CorpseTarget(TaxidermyKit kit) : base(3, false, TargetFlags.None) => m_Kit = kit; - private Mobile m_Hunter; - - public TrophyDeed(int westID, int northID, int deedNumber, int addonNumber, - Mobile hunter = null, int animalWeight = 0) : base(0x14F0) - { - WestID = westID; - NorthID = northID; - m_DeedNumber = deedNumber; - AddonNumber = addonNumber; - m_Hunter = hunter; - m_AnimalWeight = animalWeight; - } - - public TrophyDeed(TaxidermyKit.TrophyInfo info, Mobile hunter, int animalWeight) - : this(info.NorthID + 7, info.NorthID, info.DeedNumber, info.AddonNumber, hunter, animalWeight) - { - } - - public TrophyDeed(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int WestID { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int NorthID { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int DeedNumber - { - get => m_DeedNumber; - set - { - m_DeedNumber = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int AddonNumber { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Hunter - { - get => m_Hunter; - set - { - m_Hunter = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int AnimalWeight - { - get => m_AnimalWeight; - set - { - m_AnimalWeight = value; - InvalidateProperties(); - } - } - - public override int LabelNumber => m_DeedNumber; - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_AnimalWeight >= 20) - { - if (m_Hunter != null) - list.Add(1070857, m_Hunter.Name); // Caught by ~1_fisherman~ - - list.Add(1070858, m_AnimalWeight.ToString()); // ~1_weight~ stones - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(m_Hunter); - writer.Write(m_AnimalWeight); - - writer.Write(WestID); - writer.Write(NorthID); - writer.Write(m_DeedNumber); - writer.Write(AddonNumber); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_Hunter = reader.ReadMobile(); - m_AnimalWeight = reader.ReadInt(); - goto case 0; - } - case 0: - { - WestID = reader.ReadInt(); - NorthID = reader.ReadInt(); - m_DeedNumber = reader.ReadInt(); - AddonNumber = reader.ReadInt(); - break; - } - } - } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - BaseHouse house = BaseHouse.FindHouseAt(from); - - if (house?.IsCoOwner(from) == true) - { - bool northWall = BaseAddon.IsWall(from.X, from.Y - 1, from.Z, from.Map); - bool westWall = BaseAddon.IsWall(from.X - 1, from.Y, from.Z, from.Map); - - if (northWall && westWall) - switch (from.Direction & Direction.Mask) + protected override void OnTarget(Mobile from, object targeted) { - case Direction.North: - case Direction.South: - westWall = false; - break; + if (m_Kit.Deleted) + return; - case Direction.East: - case Direction.West: - northWall = false; - break; + var corpse = targeted as Corpse; - default: - from.SendMessage("Turn to face the wall on which to hang this trophy."); + if (!(corpse != null || targeted is BigFish)) + { + from.SendLocalizedMessage(1042600); // That is not a corpse! + } + else if (corpse?.VisitedByTaxidermist == true) + { + from.SendLocalizedMessage(1042596); // That corpse seems to have been visited by a taxidermist already. + } + else if (!m_Kit.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else if (from.Skills.Carpentry.Base < 90.0) + { + from.SendLocalizedMessage(1042603); // You would not understand how to use the kit. + } + else + { + var obj = corpse?.Owner ?? targeted; + + foreach (var t in m_Table) + { + if (t.CreatureType != obj.GetType()) + continue; + + var pack = from.Backpack; + + if (pack?.ConsumeTotal(typeof(Board), 10) == true) + { + from.SendLocalizedMessage( + 1042278 + ); // You review the corpse and find it worthy of a trophy. + from.SendLocalizedMessage(1042602); // You use your kit up making the trophy. + + Mobile hunter = null; + var weight = 0; + + if (targeted is BigFish fish) + { + hunter = fish.Fisher; + weight = (int)fish.Weight; + + fish.Consume(); + } + + from.AddToBackpack(new TrophyDeed(t, hunter, weight)); + + if (corpse != null) + corpse.VisitedByTaxidermist = true; + + m_Kit.Delete(); + return; + } + + from.SendLocalizedMessage(1042598); // You do not have enough boards. + return; + } + + from.SendLocalizedMessage(1042599); // That does not look like something you want hanging on a wall. + } + } + } + } + + public class TrophyAddon : Item, IAddon + { + private int m_AddonNumber; + private int m_AnimalWeight; + + private Mobile m_Hunter; + + public TrophyAddon( + Mobile from, int itemID, int westID, int northID, int deedNumber, + int addonNumber, Mobile hunter = null, int animalWeight = 0 + ) : base(itemID) + { + WestID = westID; + NorthID = northID; + DeedNumber = deedNumber; + m_AddonNumber = addonNumber; + + m_Hunter = hunter; + m_AnimalWeight = animalWeight; + + Movable = false; + + MoveToWorld(from.Location, from.Map); + } + + public TrophyAddon(Serial serial) : base(serial) + { + } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + [CommandProperty(AccessLevel.GameMaster)] + public int WestID { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int NorthID { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int DeedNumber { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int AddonNumber + { + get => m_AddonNumber; + set + { + m_AddonNumber = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Hunter + { + get => m_Hunter; + set + { + m_Hunter = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int AnimalWeight + { + get => m_AnimalWeight; + set + { + m_AnimalWeight = value; + InvalidateProperties(); + } + } + + public override int LabelNumber => m_AddonNumber; + + public bool CouldFit(IPoint3D p, Map map) + { + if (!map.CanFit(p.X, p.Y, p.Z, ItemData.Height)) + return false; + + if (ItemID == NorthID) + return BaseAddon.IsWall(p.X, p.Y - 1, p.Z, map); // North wall + return BaseAddon.IsWall(p.X - 1, p.Y, p.Z, map); // West wall + } + + public Item Deed => new TrophyDeed(WestID, NorthID, DeedNumber, m_AddonNumber, m_Hunter, m_AnimalWeight); + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_AnimalWeight >= 20) + { + if (m_Hunter != null) + list.Add(1070857, m_Hunter.Name); // Caught by ~1_fisherman~ + + list.Add(1070858, m_AnimalWeight.ToString()); // ~1_weight~ stones + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(m_Hunter); + writer.Write(m_AnimalWeight); + + writer.Write(WestID); + writer.Write(NorthID); + writer.Write(DeedNumber); + writer.Write(m_AddonNumber); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_Hunter = reader.ReadMobile(); + m_AnimalWeight = reader.ReadInt(); + goto case 0; + } + case 0: + { + WestID = reader.ReadInt(); + NorthID = reader.ReadInt(); + DeedNumber = reader.ReadInt(); + m_AddonNumber = reader.ReadInt(); + break; + } + } + + Timer.DelayCall(FixMovingCrate); + } + + private void FixMovingCrate() + { + if (Deleted) return; + + if (Movable || IsLockedDown) + { + var deed = Deed; + + if (Parent is Item item) + { + item.AddItem(deed); + deed.Location = Location; + } + else + { + deed.MoveToWorld(Location, Map); + } + + Delete(); } - - int itemID = 0; - - if (northWall) - itemID = NorthID; - else if (westWall) - itemID = WestID; - else - from.SendLocalizedMessage(1042626); // The trophy must be placed next to a wall. - - if (itemID > 0) - { - house.Addons.Add(new TrophyAddon(from, itemID, WestID, NorthID, m_DeedNumber, AddonNumber, m_Hunter, - m_AnimalWeight)); - Delete(); - } } - else + + public override void OnDoubleClick(Mobile from) { - from.SendLocalizedMessage(502092); // You must be in your house to do this. + var house = BaseHouse.FindHouseAt(this); + + if (house?.IsCoOwner(from) == true) + { + if (from.InRange(GetWorldLocation(), 1)) + { + from.AddToBackpack(Deed); + Delete(); + } + else + { + from.SendLocalizedMessage(500295); // You are too far away to do that. + } + } + } + } + + [Flippable(0x14F0, 0x14EF)] + public class TrophyDeed : Item + { + private int m_AnimalWeight; + private int m_DeedNumber; + + private Mobile m_Hunter; + + public TrophyDeed( + int westID, int northID, int deedNumber, int addonNumber, + Mobile hunter = null, int animalWeight = 0 + ) : base(0x14F0) + { + WestID = westID; + NorthID = northID; + m_DeedNumber = deedNumber; + AddonNumber = addonNumber; + m_Hunter = hunter; + m_AnimalWeight = animalWeight; + } + + public TrophyDeed(TaxidermyKit.TrophyInfo info, Mobile hunter, int animalWeight) + : this(info.NorthID + 7, info.NorthID, info.DeedNumber, info.AddonNumber, hunter, animalWeight) + { + } + + public TrophyDeed(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int WestID { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int NorthID { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int DeedNumber + { + get => m_DeedNumber; + set + { + m_DeedNumber = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int AddonNumber { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Hunter + { + get => m_Hunter; + set + { + m_Hunter = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int AnimalWeight + { + get => m_AnimalWeight; + set + { + m_AnimalWeight = value; + InvalidateProperties(); + } + } + + public override int LabelNumber => m_DeedNumber; + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_AnimalWeight >= 20) + { + if (m_Hunter != null) + list.Add(1070857, m_Hunter.Name); // Caught by ~1_fisherman~ + + list.Add(1070858, m_AnimalWeight.ToString()); // ~1_weight~ stones + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(m_Hunter); + writer.Write(m_AnimalWeight); + + writer.Write(WestID); + writer.Write(NorthID); + writer.Write(m_DeedNumber); + writer.Write(AddonNumber); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_Hunter = reader.ReadMobile(); + m_AnimalWeight = reader.ReadInt(); + goto case 0; + } + case 0: + { + WestID = reader.ReadInt(); + NorthID = reader.ReadInt(); + m_DeedNumber = reader.ReadInt(); + AddonNumber = reader.ReadInt(); + break; + } + } + } + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + var house = BaseHouse.FindHouseAt(from); + + if (house?.IsCoOwner(from) == true) + { + var northWall = BaseAddon.IsWall(from.X, from.Y - 1, from.Z, from.Map); + var westWall = BaseAddon.IsWall(from.X - 1, from.Y, from.Z, from.Map); + + if (northWall && westWall) + switch (from.Direction & Direction.Mask) + { + case Direction.North: + case Direction.South: + westWall = false; + break; + + case Direction.East: + case Direction.West: + northWall = false; + break; + + default: + from.SendMessage("Turn to face the wall on which to hang this trophy."); + return; + } + + var itemID = 0; + + if (northWall) + itemID = NorthID; + else if (westWall) + itemID = WestID; + else + from.SendLocalizedMessage(1042626); // The trophy must be placed next to a wall. + + if (itemID > 0) + { + house.Addons.Add( + new TrophyAddon( + from, + itemID, + WestID, + NorthID, + m_DeedNumber, + AddonNumber, + m_Hunter, + m_AnimalWeight + ) + ); + Delete(); + } + } + else + { + from.SendLocalizedMessage(502092); // You must be in your house to do this. + } + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } } - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } } - } } diff --git a/Projects/UOContent/Items/Skill Items/Fishing/FishingPole.cs b/Projects/UOContent/Items/Skill Items/Fishing/FishingPole.cs index f23192dc2..391dee5e2 100644 --- a/Projects/UOContent/Items/Skill Items/Fishing/FishingPole.cs +++ b/Projects/UOContent/Items/Skill Items/Fishing/FishingPole.cs @@ -5,65 +5,65 @@ using Server.Network; namespace Server.Items { - public class FishingPole : Item - { - [Constructible] - public FishingPole() : base(0x0DC0) + public class FishingPole : Item { - Layer = Layer.TwoHanded; - Weight = 8.0; + [Constructible] + public FishingPole() : base(0x0DC0) + { + Layer = Layer.TwoHanded; + Weight = 8.0; + } + + public FishingPole(Serial serial) : base(serial) + { + } + + public override void OnDoubleClick(Mobile from) + { + var loc = GetWorldLocation(); + + if (!from.InLOS(loc) || !from.InRange(loc, 2)) + from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 1019045); // I can't reach that + else + Fishing.System.BeginHarvesting(from, this); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + BaseHarvestTool.AddContextMenuEntries(from, this, list, Fishing.System); + } + + public override bool CheckConflictingLayer(Mobile m, Item item, Layer layer) + { + if (base.CheckConflictingLayer(m, item, layer)) + return true; + + if (layer == Layer.OneHanded) + { + m.SendLocalizedMessage(500214); // You already have something in both hands. + return true; + } + + return false; + } + + 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 < 1 && Layer == Layer.OneHanded) + Layer = Layer.TwoHanded; + } } - - public FishingPole(Serial serial) : base(serial) - { - } - - public override void OnDoubleClick(Mobile from) - { - Point3D loc = GetWorldLocation(); - - if (!from.InLOS(loc) || !from.InRange(loc, 2)) - from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 1019045); // I can't reach that - else - Fishing.System.BeginHarvesting(from, this); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - BaseHarvestTool.AddContextMenuEntries(from, this, list, Fishing.System); - } - - public override bool CheckConflictingLayer(Mobile m, Item item, Layer layer) - { - if (base.CheckConflictingLayer(m, item, layer)) - return true; - - if (layer == Layer.OneHanded) - { - m.SendLocalizedMessage(500214); // You already have something in both hands. - return true; - } - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1 && Layer == Layer.OneHanded) - Layer = Layer.TwoHanded; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Fishing/Misc/MessageInABottle.cs b/Projects/UOContent/Items/Skill Items/Fishing/Misc/MessageInABottle.cs index cffd942cd..228cbb160 100644 --- a/Projects/UOContent/Items/Skill Items/Fishing/Misc/MessageInABottle.cs +++ b/Projects/UOContent/Items/Skill Items/Fishing/Misc/MessageInABottle.cs @@ -3,102 +3,102 @@ using Server.Network; namespace Server.Items { - public class MessageInABottle : Item - { - private int m_Level; - - [Constructible] - public MessageInABottle(Map map = null) : this(map, GetRandomLevel()) + public class MessageInABottle : Item { + private int m_Level; + + [Constructible] + public MessageInABottle(Map map = null) : this(map, GetRandomLevel()) + { + } + + [Constructible] + public MessageInABottle(Map map, int level) : base(0x099F) + { + Weight = 1.0; + TargetMap = map ?? Map.Trammel; + m_Level = level; + } + + public MessageInABottle(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041080; // a message in a bottle + + [CommandProperty(AccessLevel.GameMaster)] + public Map TargetMap { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Level + { + get => m_Level; + set => m_Level = Math.Max(1, Math.Min(value, 4)); + } + + public static int GetRandomLevel() + { + if (Core.AOS && Utility.Random(25) < 1) + return 4; // ancient + + return Utility.RandomMinMax(1, 3); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(3); // version + + writer.Write(m_Level); + + writer.Write(TargetMap); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 3: + case 2: + { + m_Level = reader.ReadInt(); + goto case 1; + } + case 1: + { + TargetMap = reader.ReadMap(); + break; + } + case 0: + { + TargetMap = Map.Trammel; + break; + } + } + + if (version < 2) + m_Level = GetRandomLevel(); + + if (version < 3 && TargetMap == Map.Tokuno) + TargetMap = Map.Trammel; + } + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + ReplaceWith(new SOS(TargetMap, m_Level)); + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 501891); // You extract the message from the bottle. + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } } - - [Constructible] - public MessageInABottle(Map map, int level) : base(0x099F) - { - Weight = 1.0; - TargetMap = map ?? Map.Trammel; - m_Level = level; - } - - public MessageInABottle(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041080; // a message in a bottle - - [CommandProperty(AccessLevel.GameMaster)] - public Map TargetMap { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Level - { - get => m_Level; - set => m_Level = Math.Max(1, Math.Min(value, 4)); - } - - public static int GetRandomLevel() - { - if (Core.AOS && Utility.Random(25) < 1) - return 4; // ancient - - return Utility.RandomMinMax(1, 3); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(3); // version - - writer.Write(m_Level); - - writer.Write(TargetMap); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 3: - case 2: - { - m_Level = reader.ReadInt(); - goto case 1; - } - case 1: - { - TargetMap = reader.ReadMap(); - break; - } - case 0: - { - TargetMap = Map.Trammel; - break; - } - } - - if (version < 2) - m_Level = GetRandomLevel(); - - if (version < 3 && TargetMap == Map.Tokuno) - TargetMap = Map.Trammel; - } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - ReplaceWith(new SOS(TargetMap, m_Level)); - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 501891); // You extract the message from the bottle. - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Fishing/Misc/SOS.cs b/Projects/UOContent/Items/Skill Items/Fishing/Misc/SOS.cs index bfe3fe2ca..b744654c3 100644 --- a/Projects/UOContent/Items/Skill Items/Fishing/Misc/SOS.cs +++ b/Projects/UOContent/Items/Skill Items/Fishing/Misc/SOS.cs @@ -3,302 +3,345 @@ using Server.Gumps; namespace Server.Items { - [Flippable(0x14ED, 0x14EE)] - public class SOS : Item - { - public override int LabelNumber + [Flippable(0x14ED, 0x14EE)] + public class SOS : Item { - get - { - if (IsAncient) - return 1063450; // an ancient SOS + private static readonly int[] m_WaterTiles = + { + 0x00A8, 0x00AB, + 0x0136, 0x0137 + }; - return 1041081; // a waterstained SOS - } - } + private static readonly Rectangle2D[] m_BritRegions = { new Rectangle2D(0, 0, 5120, 4096) }; - private int m_Level; + private static readonly Rectangle2D[] m_IlshRegions = + { new Rectangle2D(1472, 272, 304, 240), new Rectangle2D(1240, 1000, 312, 160) }; - [CommandProperty(AccessLevel.GameMaster)] - public bool IsAncient => m_Level >= 4; + private static readonly Rectangle2D[] m_MalasRegions = { new Rectangle2D(1376, 1520, 464, 280) }; - [CommandProperty(AccessLevel.GameMaster)] - public int Level - { - get => m_Level; - set - { - m_Level = Math.Max(1, Math.Min(value, 4)); - UpdateHue(); - InvalidateProperties(); - } - } + private int m_Level; - [CommandProperty(AccessLevel.GameMaster)] - public Map TargetMap { get; set; } + [Constructible] + public SOS(Map map = null) : this(map, MessageInABottle.GetRandomLevel()) + { + } - [CommandProperty(AccessLevel.GameMaster)] - public Point3D TargetLocation { get; set; } + [Constructible] + public SOS(Map map, int level) : base(0x14EE) + { + Weight = 1.0; - [CommandProperty(AccessLevel.GameMaster)] - public int MessageIndex { get; set; } - - public void UpdateHue() - { - if (IsAncient) - Hue = 0x481; - else - Hue = 0; - } - - [Constructible] - public SOS(Map map = null) : this(map, MessageInABottle.GetRandomLevel()) - { - } - - [Constructible] - public SOS(Map map, int level) : base(0x14EE) - { - Weight = 1.0; - - m_Level = level; - MessageIndex = Utility.Random(MessageEntry.Entries.Length); - TargetMap = map ?? Map.Trammel; - TargetLocation = FindLocation(TargetMap); - - UpdateHue(); - } - - public SOS(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(4); // version - - writer.Write(m_Level); - - writer.Write(TargetMap); - writer.Write(TargetLocation); - writer.Write(MessageIndex); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 4: - case 3: - case 2: - { - m_Level = reader.ReadInt(); - goto case 1; - } - case 1: - { - TargetMap = reader.ReadMap(); - TargetLocation = reader.ReadPoint3D(); - MessageIndex = reader.ReadInt(); - - break; - } - case 0: - { - TargetMap = Map; - - if (TargetMap == null || TargetMap == Map.Internal) - TargetMap = Map.Trammel; - - TargetLocation = FindLocation(TargetMap); + m_Level = level; MessageIndex = Utility.Random(MessageEntry.Entries.Length); + TargetMap = map ?? Map.Trammel; + TargetLocation = FindLocation(TargetMap); - break; - } - } + UpdateHue(); + } - if (version < 2) - m_Level = MessageInABottle.GetRandomLevel(); + public SOS(Serial serial) : base(serial) + { + } - if (version < 3) - UpdateHue(); + public override int LabelNumber + { + get + { + if (IsAncient) + return 1063450; // an ancient SOS - if (version < 4 && TargetMap == Map.Tokuno) - TargetMap = Map.Trammel; + return 1041081; // a waterstained SOS + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsAncient => m_Level >= 4; + + [CommandProperty(AccessLevel.GameMaster)] + public int Level + { + get => m_Level; + set + { + m_Level = Math.Max(1, Math.Min(value, 4)); + UpdateHue(); + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Map TargetMap { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D TargetLocation { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int MessageIndex { get; set; } + + public void UpdateHue() + { + if (IsAncient) + Hue = 0x481; + else + Hue = 0; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(4); // version + + writer.Write(m_Level); + + writer.Write(TargetMap); + writer.Write(TargetLocation); + writer.Write(MessageIndex); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 4: + case 3: + case 2: + { + m_Level = reader.ReadInt(); + goto case 1; + } + case 1: + { + TargetMap = reader.ReadMap(); + TargetLocation = reader.ReadPoint3D(); + MessageIndex = reader.ReadInt(); + + break; + } + case 0: + { + TargetMap = Map; + + if (TargetMap == null || TargetMap == Map.Internal) + TargetMap = Map.Trammel; + + TargetLocation = FindLocation(TargetMap); + MessageIndex = Utility.Random(MessageEntry.Entries.Length); + + break; + } + } + + if (version < 2) + m_Level = MessageInABottle.GetRandomLevel(); + + if (version < 3) + UpdateHue(); + + if (version < 4 && TargetMap == Map.Tokuno) + TargetMap = Map.Trammel; + } + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + MessageEntry entry; + + if (MessageIndex >= 0 && MessageIndex < MessageEntry.Entries.Length) + entry = MessageEntry.Entries[MessageIndex]; + else + entry = MessageEntry.Entries[MessageIndex = Utility.Random(MessageEntry.Entries.Length)]; + + // from.CloseGump( typeof( MessageGump ) ); + from.SendGump(new MessageGump(entry, TargetMap, TargetLocation)); + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + + public static Point3D FindLocation(Map map) + { + if (map == null || map == Map.Internal) + return Point3D.Zero; + + Rectangle2D[] regions; + + if (map == Map.Felucca || map == Map.Trammel) + regions = m_BritRegions; + else if (map == Map.Ilshenar) + regions = m_IlshRegions; + else if (map == Map.Malas) + regions = m_MalasRegions; + else + regions = new[] { new Rectangle2D(0, 0, map.Width, map.Height) }; + + if (regions.Length == 0) + return Point3D.Zero; + + for (var i = 0; i < 50; ++i) + { + var reg = regions.RandomElement(); + var x = Utility.Random(reg.X, reg.Width); + var y = Utility.Random(reg.Y, reg.Height); + + if (!ValidateDeepWater(map, x, y)) + continue; + + var valid = true; + + for (int j = 1, offset = 5; valid && j <= 5; ++j, offset += 5) + if (!ValidateDeepWater(map, x + offset, y + offset)) + valid = false; + else if (!ValidateDeepWater(map, x + offset, y - offset)) + valid = false; + else if (!ValidateDeepWater(map, x - offset, y + offset)) + valid = false; + else if (!ValidateDeepWater(map, x - offset, y - offset)) + valid = false; + + if (valid) + return new Point3D(x, y, 0); + } + + return Point3D.Zero; + } + + private static bool ValidateDeepWater(Map map, int x, int y) + { + var tileID = map.Tiles.GetLandTile(x, y).ID; + var water = false; + + for (var i = 0; !water && i < m_WaterTiles.Length; i += 2) + water = tileID >= m_WaterTiles[i] && tileID <= m_WaterTiles[i + 1]; + + return water; + } + + private class MessageGump : Gump + { + public MessageGump(MessageEntry entry, Map map, Point3D loc) : base(150, 50) + { + int xLong = 0, yLat = 0; + int xMins = 0, yMins = 0; + bool xEast = false, ySouth = false; + string fmt; + + if (Sextant.Format(loc, map, ref xLong, ref yLat, ref xMins, ref yMins, ref xEast, ref ySouth)) + fmt = $"{yLat}°{yMins}'{(ySouth ? "S" : "N")},{xLong}°{xMins}'{(xEast ? "E" : "W")}"; + else + fmt = "?????"; + + AddPage(0); + + AddBackground(0, 40, 350, 300, 2520); + + /* This is a message hastily scribbled by a passenger aboard a sinking ship. + * While it is probably too late to save the passengers and crew, + * perhaps some treasure went down with the ship! + * The message gives the ship's last known sextant co-ordinates. + */ + AddHtmlLocalized( + 30, + 80, + 285, + 160, + 1018326, + true, + true + ); + + AddHtml(35, 240, 230, 20, fmt); + + AddButton(35, 265, 4005, 4007, 0); + AddHtmlLocalized(70, 265, 100, 20, 1011036); // OKAY + } + } + + private class MessageEntry + { + public MessageEntry(int width, int height, string message) + { + Width = width; + Height = height; + Message = message; + } + + public int Width { get; } + + public int Height { get; } + + public string Message { get; } + + public static MessageEntry[] Entries { get; } = + { + new MessageEntry( + 280, + 180, + "...Ar! {0} and a fair wind! No chance... storms, though--ar! Is that a sea serp...

uh oh." + ), + new MessageEntry( + 280, + 215, + "...been inside this whale for three days now. I've run out of food I can pick out of his teeth. I took a sextant reading through the blowhole: {0}. I'll never see my treasure again..." + ), + new MessageEntry( + 280, + 285, + "...grand adventure! Captain Quacklebush had me swab down the decks daily...
...pirates came, I was in the rigging practicing with my sextant. {0} if I am not mistaken...
....scuttled the ship, and our precious cargo went with her and the screaming pirates, down to the bottom of the sea..." + ), + new MessageEntry( + 280, + 180, + "Help! Ship going dow...n heavy storms...precious cargo...st reach dest...current coordinates {0}...ve any survivors... ease!" + ), + new MessageEntry( + 280, + 215, + "...know that the wreck is near {0} but have not found it. Could the message passed down in my family for generations be wrong? No... I swear on the soul of my grandfather, I will find..." + ), + new MessageEntry( + 280, + 195, + "...never expected an iceberg...silly woman on bow crushed instantly...send help to {0}...ey'll never forget the tragedy of the sinking of the Miniscule..." + ), + new MessageEntry( + 280, + 265, + "...nobody knew I was a girl. They just assumed I was another sailor...then we met the undine. {0}. It was demanded sacrifice...I was youngset, they figured...
...grabbed the captain's treasure, screamed, 'It'll go down with me!'
...they took me up on it." + ), + new MessageEntry( + 280, + 230, + "...so I threw the treasure overboard, before the curse could get me too. But I was too late. Now I am doomed to wander these seas, a ghost forever. Join me: seek ye at {0} if thou wishest my company..." + ), + new MessageEntry( + 280, + 285, + "...then the ship exploded. A dragon swooped by. The slime swallowed Bertie whole--he screamed, it was amazing. The sky glowed orange. A sextant reading put us at {0}. Norma was chattering about sailing over the edge of the world. I looked at my hands and saw through them..." + ), + new MessageEntry( + 280, + 285, + "...trapped on a deserted island, with a magic fountain supplying wood, fresh water springs, gorgeous scenery, and my lovely young wife. I know the ship with all our life's earnings sank at {0} but I don't know what our coordinates are... someone has GOT to rescue me before Sunday's finals game or I'll go mad..." + ), + new MessageEntry( + 280, + 160, + "WANTED: divers exp...d in shipwre...overy. Must have own vess...pply at {0}
...good benefits, flexible hours..." + ), + new MessageEntry( + 280, + 250, + "...was a cad and a boor, no matter what momma s...rew him overboard! Oh, Anna, 'twas so exciting!
Unfort...y he grabbe...est, and all his riches went with him!
...sked the captain, and he says we're at {0}
...so maybe..." + ) + }; + } } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - MessageEntry entry; - - if (MessageIndex >= 0 && MessageIndex < MessageEntry.Entries.Length) - entry = MessageEntry.Entries[MessageIndex]; - else - entry = MessageEntry.Entries[MessageIndex = Utility.Random(MessageEntry.Entries.Length)]; - - // from.CloseGump( typeof( MessageGump ) ); - from.SendGump(new MessageGump(entry, TargetMap, TargetLocation)); - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - - private static readonly int[] m_WaterTiles = - { - 0x00A8, 0x00AB, - 0x0136, 0x0137 - }; - - private static readonly Rectangle2D[] m_BritRegions = { new Rectangle2D(0, 0, 5120, 4096) }; - - private static readonly Rectangle2D[] m_IlshRegions = - { new Rectangle2D(1472, 272, 304, 240), new Rectangle2D(1240, 1000, 312, 160) }; - - private static readonly Rectangle2D[] m_MalasRegions = { new Rectangle2D(1376, 1520, 464, 280) }; - - public static Point3D FindLocation(Map map) - { - if (map == null || map == Map.Internal) - return Point3D.Zero; - - Rectangle2D[] regions; - - if (map == Map.Felucca || map == Map.Trammel) - regions = m_BritRegions; - else if (map == Map.Ilshenar) - regions = m_IlshRegions; - else if (map == Map.Malas) - regions = m_MalasRegions; - else - regions = new[] { new Rectangle2D(0, 0, map.Width, map.Height) }; - - if (regions.Length == 0) - return Point3D.Zero; - - for (int i = 0; i < 50; ++i) - { - Rectangle2D reg = regions.RandomElement(); - int x = Utility.Random(reg.X, reg.Width); - int y = Utility.Random(reg.Y, reg.Height); - - if (!ValidateDeepWater(map, x, y)) - continue; - - bool valid = true; - - for (int j = 1, offset = 5; valid && j <= 5; ++j, offset += 5) - if (!ValidateDeepWater(map, x + offset, y + offset)) - valid = false; - else if (!ValidateDeepWater(map, x + offset, y - offset)) - valid = false; - else if (!ValidateDeepWater(map, x - offset, y + offset)) - valid = false; - else if (!ValidateDeepWater(map, x - offset, y - offset)) - valid = false; - - if (valid) - return new Point3D(x, y, 0); - } - - return Point3D.Zero; - } - - private static bool ValidateDeepWater(Map map, int x, int y) - { - int tileID = map.Tiles.GetLandTile(x, y).ID; - bool water = false; - - for (int i = 0; !water && i < m_WaterTiles.Length; i += 2) - water = tileID >= m_WaterTiles[i] && tileID <= m_WaterTiles[i + 1]; - - return water; - } - - private class MessageGump : Gump - { - public MessageGump(MessageEntry entry, Map map, Point3D loc) : base(150, 50) - { - int xLong = 0, yLat = 0; - int xMins = 0, yMins = 0; - bool xEast = false, ySouth = false; - string fmt; - - if (Sextant.Format(loc, map, ref xLong, ref yLat, ref xMins, ref yMins, ref xEast, ref ySouth)) - fmt = $"{yLat}°{yMins}'{(ySouth ? "S" : "N")},{xLong}°{xMins}'{(xEast ? "E" : "W")}"; - else - fmt = "?????"; - - AddPage(0); - - AddBackground(0, 40, 350, 300, 2520); - - /* This is a message hastily scribbled by a passenger aboard a sinking ship. - * While it is probably too late to save the passengers and crew, - * perhaps some treasure went down with the ship! - * The message gives the ship's last known sextant co-ordinates. - */ - AddHtmlLocalized(30, 80, 285, 160, 1018326, true, - true); - - AddHtml(35, 240, 230, 20, fmt); - - AddButton(35, 265, 4005, 4007, 0); - AddHtmlLocalized(70, 265, 100, 20, 1011036); // OKAY - } - } - - private class MessageEntry - { - public MessageEntry(int width, int height, string message) - { - Width = width; - Height = height; - Message = message; - } - - public int Width { get; } - - public int Height { get; } - - public string Message { get; } - - public static MessageEntry[] Entries { get; } = - { - new MessageEntry(280, 180, - "...Ar! {0} and a fair wind! No chance... storms, though--ar! Is that a sea serp...

uh oh."), - new MessageEntry(280, 215, - "...been inside this whale for three days now. I've run out of food I can pick out of his teeth. I took a sextant reading through the blowhole: {0}. I'll never see my treasure again..."), - new MessageEntry(280, 285, - "...grand adventure! Captain Quacklebush had me swab down the decks daily...
...pirates came, I was in the rigging practicing with my sextant. {0} if I am not mistaken...
....scuttled the ship, and our precious cargo went with her and the screaming pirates, down to the bottom of the sea..."), - new MessageEntry(280, 180, - "Help! Ship going dow...n heavy storms...precious cargo...st reach dest...current coordinates {0}...ve any survivors... ease!"), - new MessageEntry(280, 215, - "...know that the wreck is near {0} but have not found it. Could the message passed down in my family for generations be wrong? No... I swear on the soul of my grandfather, I will find..."), - new MessageEntry(280, 195, - "...never expected an iceberg...silly woman on bow crushed instantly...send help to {0}...ey'll never forget the tragedy of the sinking of the Miniscule..."), - new MessageEntry(280, 265, - "...nobody knew I was a girl. They just assumed I was another sailor...then we met the undine. {0}. It was demanded sacrifice...I was youngset, they figured...
...grabbed the captain's treasure, screamed, 'It'll go down with me!'
...they took me up on it."), - new MessageEntry(280, 230, - "...so I threw the treasure overboard, before the curse could get me too. But I was too late. Now I am doomed to wander these seas, a ghost forever. Join me: seek ye at {0} if thou wishest my company..."), - new MessageEntry(280, 285, - "...then the ship exploded. A dragon swooped by. The slime swallowed Bertie whole--he screamed, it was amazing. The sky glowed orange. A sextant reading put us at {0}. Norma was chattering about sailing over the edge of the world. I looked at my hands and saw through them..."), - new MessageEntry(280, 285, - "...trapped on a deserted island, with a magic fountain supplying wood, fresh water springs, gorgeous scenery, and my lovely young wife. I know the ship with all our life's earnings sank at {0} but I don't know what our coordinates are... someone has GOT to rescue me before Sunday's finals game or I'll go mad..."), - new MessageEntry(280, 160, - "WANTED: divers exp...d in shipwre...overy. Must have own vess...pply at {0}
...good benefits, flexible hours..."), - new MessageEntry(280, 250, - "...was a cad and a boor, no matter what momma s...rew him overboard! Oh, Anna, 'twas so exciting!
Unfort...y he grabbe...est, and all his riches went with him!
...sked the captain, and he says we're at {0}
...so maybe...") - }; - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Fishing/Misc/Sextant.cs b/Projects/UOContent/Items/Skill Items/Fishing/Misc/Sextant.cs index 5a8b1528d..6bf027831 100644 --- a/Projects/UOContent/Items/Skill Items/Fishing/Misc/Sextant.cs +++ b/Projects/UOContent/Items/Skill Items/Fishing/Misc/Sextant.cs @@ -2,155 +2,159 @@ using Server.Network; namespace Server.Items { - public class Sextant : Item - { - [Constructible] - public Sextant() : base(0x1058) => Weight = 2.0; - - public Sextant(Serial serial) : base(serial) + public class Sextant : Item { - } + [Constructible] + public Sextant() : base(0x1058) => Weight = 2.0; - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - int xLong = 0, yLat = 0; - int xMins = 0, yMins = 0; - bool xEast = false, ySouth = false; - - if (Format(from.Location, from.Map, ref xLong, ref yLat, ref xMins, ref yMins, ref xEast, ref ySouth)) - { - string location = $"{yLat}� {yMins}'{(ySouth ? "S" : "N")}, {xLong}� {xMins}'{(xEast ? "E" : "W")}"; - from.LocalOverheadMessage(MessageType.Regular, from.SpeechHue, false, location); - } - } - - public static bool ComputeMapDetails(Map map, int x, int y, out int xCenter, out int yCenter, out int xWidth, - out int yHeight) - { - xWidth = 5120; - yHeight = 4096; - - if (map == Map.Trammel || map == Map.Felucca) - { - if (x >= 0 && y >= 0 && x < 5120 && y < 4096) + public Sextant(Serial serial) : base(serial) { - xCenter = 1323; - yCenter = 1624; } - else if (x >= 5120 && y >= 2304 && x < 6144 && y < 4096) + + public override void Serialize(IGenericWriter writer) { - xCenter = 5936; - yCenter = 3112; + base.Serialize(writer); + + writer.Write(0); // version } - else + + public override void Deserialize(IGenericReader reader) { - xCenter = 0; - yCenter = 0; - return false; + base.Deserialize(reader); + + var version = reader.ReadInt(); } - } - else if (x >= 0 && y >= 0 && x < map.Width && y < map.Height) - { - xCenter = 1323; - yCenter = 1624; - } - else - { - xCenter = 0; - yCenter = 0; - return false; - } - return true; + public override void OnDoubleClick(Mobile from) + { + int xLong = 0, yLat = 0; + int xMins = 0, yMins = 0; + bool xEast = false, ySouth = false; + + if (Format(from.Location, from.Map, ref xLong, ref yLat, ref xMins, ref yMins, ref xEast, ref ySouth)) + { + var location = $"{yLat}� {yMins}'{(ySouth ? "S" : "N")}, {xLong}� {xMins}'{(xEast ? "E" : "W")}"; + from.LocalOverheadMessage(MessageType.Regular, from.SpeechHue, false, location); + } + } + + public static bool ComputeMapDetails( + Map map, int x, int y, out int xCenter, out int yCenter, out int xWidth, + out int yHeight + ) + { + xWidth = 5120; + yHeight = 4096; + + if (map == Map.Trammel || map == Map.Felucca) + { + if (x >= 0 && y >= 0 && x < 5120 && y < 4096) + { + xCenter = 1323; + yCenter = 1624; + } + else if (x >= 5120 && y >= 2304 && x < 6144 && y < 4096) + { + xCenter = 5936; + yCenter = 3112; + } + else + { + xCenter = 0; + yCenter = 0; + return false; + } + } + else if (x >= 0 && y >= 0 && x < map.Width && y < map.Height) + { + xCenter = 1323; + yCenter = 1624; + } + else + { + xCenter = 0; + yCenter = 0; + return false; + } + + return true; + } + + public static Point3D ReverseLookup(Map map, int xLong, int yLat, int xMins, int yMins, bool xEast, bool ySouth) + { + if (map == null || map == Map.Internal) + return Point3D.Zero; + + if (!ComputeMapDetails(map, 0, 0, out var xCenter, out var yCenter, out var xWidth, out var yHeight)) + return Point3D.Zero; + + var absLong = xLong + (double)xMins / 60; + var absLat = yLat + (double)yMins / 60; + + if (!xEast) + absLong = 360.0 - absLong; + + if (!ySouth) + absLat = 360.0 - absLat; + + var x = xCenter + (int)(absLong * xWidth / 360); + var y = yCenter + (int)(absLat * yHeight / 360); + + if (x < 0) + x += xWidth; + else if (x >= xWidth) + x -= xWidth; + + if (y < 0) + y += yHeight; + else if (y >= yHeight) + y -= yHeight; + + var z = map.GetAverageZ(x, y); + + return new Point3D(x, y, z); + } + + public static bool Format( + Point3D p, Map map, ref int xLong, ref int yLat, ref int xMins, ref int yMins, + ref bool xEast, ref bool ySouth + ) + { + if (map == null || map == Map.Internal) + return false; + + int x = p.X, y = p.Y; + + if (!ComputeMapDetails(map, x, y, out var xCenter, out var yCenter, out var xWidth, out var yHeight)) + return false; + + var absLong = (double)((x - xCenter) * 360) / xWidth; + var absLat = (double)((y - yCenter) * 360) / yHeight; + + if (absLong > 180.0) + absLong = -180.0 + absLong % 180.0; + + if (absLat > 180.0) + absLat = -180.0 + absLat % 180.0; + + bool east = absLong >= 0, south = absLat >= 0; + + if (absLong < 0.0) + absLong = -absLong; + + if (absLat < 0.0) + absLat = -absLat; + + xLong = (int)absLong; + yLat = (int)absLat; + + xMins = (int)(absLong % 1.0 * 60); + yMins = (int)(absLat % 1.0 * 60); + + xEast = east; + ySouth = south; + + return true; + } } - - public static Point3D ReverseLookup(Map map, int xLong, int yLat, int xMins, int yMins, bool xEast, bool ySouth) - { - if (map == null || map == Map.Internal) - return Point3D.Zero; - - if (!ComputeMapDetails(map, 0, 0, out int xCenter, out int yCenter, out int xWidth, out int yHeight)) - return Point3D.Zero; - - double absLong = xLong + (double)xMins / 60; - double absLat = yLat + (double)yMins / 60; - - if (!xEast) - absLong = 360.0 - absLong; - - if (!ySouth) - absLat = 360.0 - absLat; - - int x = xCenter + (int)(absLong * xWidth / 360); - int y = yCenter + (int)(absLat * yHeight / 360); - - if (x < 0) - x += xWidth; - else if (x >= xWidth) - x -= xWidth; - - if (y < 0) - y += yHeight; - else if (y >= yHeight) - y -= yHeight; - - int z = map.GetAverageZ(x, y); - - return new Point3D(x, y, z); - } - - public static bool Format(Point3D p, Map map, ref int xLong, ref int yLat, ref int xMins, ref int yMins, - ref bool xEast, ref bool ySouth) - { - if (map == null || map == Map.Internal) - return false; - - int x = p.X, y = p.Y; - - if (!ComputeMapDetails(map, x, y, out int xCenter, out int yCenter, out int xWidth, out int yHeight)) - return false; - - double absLong = (double)((x - xCenter) * 360) / xWidth; - double absLat = (double)((y - yCenter) * 360) / yHeight; - - if (absLong > 180.0) - absLong = -180.0 + absLong % 180.0; - - if (absLat > 180.0) - absLat = -180.0 + absLat % 180.0; - - bool east = absLong >= 0, south = absLat >= 0; - - if (absLong < 0.0) - absLong = -absLong; - - if (absLat < 0.0) - absLat = -absLat; - - xLong = (int)absLong; - yLat = (int)absLat; - - xMins = (int)(absLong % 1.0 * 60); - yMins = (int)(absLat % 1.0 * 60); - - xEast = east; - ySouth = south; - - return true; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Fishing/Misc/ShipwreckedItem.cs b/Projects/UOContent/Items/Skill Items/Fishing/Misc/ShipwreckedItem.cs index 74cd8c96e..ab255f22d 100644 --- a/Projects/UOContent/Items/Skill Items/Fishing/Misc/ShipwreckedItem.cs +++ b/Projects/UOContent/Items/Skill Items/Fishing/Misc/ShipwreckedItem.cs @@ -1,70 +1,70 @@ namespace Server.Items { - public interface IShipwreckedItem - { - bool IsShipwreckedItem { get; set; } - } - - public class ShipwreckedItem : Item, IDyable, IShipwreckedItem - { - public ShipwreckedItem(int itemID) : base(itemID) + public interface IShipwreckedItem { - int weight = ItemData.Weight; - - if (weight >= 255) - weight = 1; - - Weight = weight; + bool IsShipwreckedItem { get; set; } } - public ShipwreckedItem(Serial serial) : base(serial) + public class ShipwreckedItem : Item, IDyable, IShipwreckedItem { + public ShipwreckedItem(int itemID) : base(itemID) + { + var weight = ItemData.Weight; + + if (weight >= 255) + weight = 1; + + Weight = weight; + } + + public ShipwreckedItem(Serial serial) : base(serial) + { + } + + public bool Dye(Mobile from, DyeTub sender) + { + if (Deleted) + return false; + + if (ItemID >= 0x13A4 && ItemID <= 0x13AE) + { + Hue = sender.DyedHue; + return true; + } + + from.SendLocalizedMessage(sender.FailMessage); + return false; + } + + bool IShipwreckedItem.IsShipwreckedItem + { + get => true; + set { } + } + + public override void OnSingleClick(Mobile from) + { + LabelTo(from, 1050039, $"#{LabelNumber}\t#1041645"); + } + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + list.Add(1041645); // recovered from a shipwreck + } + + 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 bool Dye(Mobile from, DyeTub sender) - { - if (Deleted) - return false; - - if (ItemID >= 0x13A4 && ItemID <= 0x13AE) - { - Hue = sender.DyedHue; - return true; - } - - from.SendLocalizedMessage(sender.FailMessage); - return false; - } - - bool IShipwreckedItem.IsShipwreckedItem - { - get => true; - set { } - } - - public override void OnSingleClick(Mobile from) - { - LabelTo(from, 1050039, $"#{LabelNumber}\t#1041645"); - } - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - list.Add(1041645); // recovered from a shipwreck - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Fishing/Misc/SpecialFishingNet.cs b/Projects/UOContent/Items/Skill Items/Fishing/Misc/SpecialFishingNet.cs index ac8f785bd..d5555df45 100644 --- a/Projects/UOContent/Items/Skill Items/Fishing/Misc/SpecialFishingNet.cs +++ b/Projects/UOContent/Items/Skill Items/Fishing/Misc/SpecialFishingNet.cs @@ -6,403 +6,411 @@ using Server.Targeting; namespace Server.Items { - public class SpecialFishingNet : Item - { - private static readonly int[] m_Hues = + public class SpecialFishingNet : Item { - 0x09B, - 0x0CD, - 0x0D3, - 0x14D, - 0x1DD, - 0x1E9, - 0x1F4, - 0x373, - 0x451, - 0x47F, - 0x489, - 0x492, - 0x4B5, - 0x8AA - }; - - private static readonly int[] m_WaterTiles = - { - 0x00A8, 0x00AB, - 0x0136, 0x0137 - }; - - private static readonly int[] m_UndeepWaterTiles = - { - 0x1797, 0x179C - }; - - [Constructible] - public SpecialFishingNet() : base(0x0DCA) - { - Weight = 1.0; - - if (Utility.RandomDouble() < 0.01) - Hue = m_Hues.RandomElement(); - else - Hue = 0x8A0; - } - - public SpecialFishingNet(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041079; // a special fishing net - - [CommandProperty(AccessLevel.GameMaster)] - public bool InUse { get; set; } - - public virtual bool RequireDeepWater => true; - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - AddNetProperties(list); - } - - protected virtual void AddNetProperties(ObjectPropertyList list) - { - // as if the name wasn't enough.. - list.Add(1017410); // Special Fishing Net - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(InUse); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - InUse = reader.ReadBool(); - - if (InUse) - Delete(); - - break; - } - } - - Stackable = false; - } - - public override void OnDoubleClick(Mobile from) - { - if (InUse) - { - from.SendLocalizedMessage(1010483); // Someone is already using that net! - } - else if (IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1010484); // Where do you wish to use the net? - from.BeginTarget(-1, true, TargetFlags.None, OnTarget); - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - - public void OnTarget(Mobile from, object obj) - { - if (Deleted || InUse) - return; - - if (!(obj is IPoint3D p3D)) - return; - - Map map = from.Map; - - if (map == null || map == Map.Internal) - return; - - int x = p3D.X, y = p3D.Y, z = map.GetAverageZ(x, y); // OSI just takes the targeted Z - - if (!from.InRange(p3D, 6)) - { - from.SendLocalizedMessage(500976); // You need to be closer to the water to fish! - } - else if (!from.InLOS(obj)) - { - from.SendLocalizedMessage(500979); // You cannot see that location. - } - else if (RequireDeepWater - ? FullValidation(map, x, y) - : ValidateDeepWater(map, x, y) || ValidateUndeepWater(map, obj, ref z)) - { - Point3D p = new Point3D(x, y, z); - - if (GetType() == typeof(SpecialFishingNet)) - for (int i = 1; i < Amount; ++i) // these were stackable before, doh - from.AddToBackpack(new SpecialFishingNet()); - - InUse = true; - Movable = false; - MoveToWorld(p, map); - - SpellHelper.Turn(from, p); - from.Animate(12, 5, 1, true, false, 0); - - Effects.SendLocationEffect(p, map, 0x352D, 16, 4); - Effects.PlaySound(p, map, 0x364); - - int index = 0; - - Timer.DelayCall(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.25), 14, - () => DoEffect(from, p, index++)); - - from.SendLocalizedMessage(RequireDeepWater - ? 1010487 - : 1074492); // You plunge the net into the sea... / You plunge the net into the water... - } - else - { - from.SendLocalizedMessage(RequireDeepWater - ? 1010485 - : 1074491); // You can only use this net in deep water! / You can only use this net in water! - } - } - - private void DoEffect(Mobile from, Point3D p, int index) - { - if (Deleted) - return; - - if (index == 1) - { - Effects.SendLocationEffect(p, Map, 0x352D, 16, 4); - Effects.PlaySound(p, Map, 0x364); - } - else if (index <= 7 || index == 14) - { - if (RequireDeepWater) - for (int i = 0; i < 3; ++i) - { - int x, y; - - switch (Utility.Random(8)) - { - default: - case 0: - x = -1; - y = -1; - break; - case 1: - x = -1; - y = 0; - break; - case 2: - x = -1; - y = +1; - break; - case 3: - x = 0; - y = -1; - break; - case 4: - x = 0; - y = +1; - break; - case 5: - x = +1; - y = -1; - break; - case 6: - x = +1; - y = 0; - break; - case 7: - x = +1; - y = +1; - break; - } - - Effects.SendLocationEffect(new Point3D(p.X + x, p.Y + y, p.Z), Map, 0x352D, 16, 4); - } - else - Effects.SendLocationEffect(p, Map, 0x352D, 16, 4); - - if (Utility.RandomBool()) - Effects.PlaySound(p, Map, 0x364); - - if (index == 14) - FinishEffect(p, Map, from); - else - Z -= 1; - } - } - - protected virtual int GetSpawnCount() - { - int count = Utility.RandomMinMax(1, 3); - - if (Hue != 0x8A0) - count += Utility.RandomMinMax(1, 2); - - return count; - } - - protected void Spawn(Point3D p, Map map, BaseCreature spawn) - { - if (map == null) - { - spawn.Delete(); - return; - } - - int x = p.X, y = p.Y; - - for (int j = 0; j < 20; ++j) - { - int tx = p.X - 2 + Utility.Random(5); - int ty = p.Y - 2 + Utility.Random(5); - - LandTile t = map.Tiles.GetLandTile(tx, ty); - - if (t.Z == p.Z && ((t.ID >= 0xA8 && t.ID <= 0xAB) || (t.ID >= 0x136 && t.ID <= 0x137)) && - !SpellHelper.CheckMulti(new Point3D(tx, ty, p.Z), map)) + private static readonly int[] m_Hues = { - x = tx; - y = ty; - break; - } - } - - spawn.MoveToWorld(new Point3D(x, y, p.Z), map); - - if (spawn is Kraken && Utility.RandomDouble() < 0.2) - spawn.PackItem(new MessageInABottle(map == Map.Felucca ? Map.Felucca : Map.Trammel)); - } - - protected virtual void FinishEffect(Point3D p, Map map, Mobile from) - { - from.RevealingAction(); - - int count = GetSpawnCount(); - - for (int i = 0; map != null && i < count; ++i) - { - var spawn = Utility.Random(4) switch - { - 0 => (BaseCreature)new SeaSerpent(), - 1 => new DeepSeaSerpent(), - 2 => new WaterElemental(), - 3 => new Kraken(), - _ => new SeaSerpent() + 0x09B, + 0x0CD, + 0x0D3, + 0x14D, + 0x1DD, + 0x1E9, + 0x1F4, + 0x373, + 0x451, + 0x47F, + 0x489, + 0x492, + 0x4B5, + 0x8AA }; - Spawn(p, map, spawn); - - spawn.Combatant = from; - } - - Delete(); - } - - public static bool FullValidation(Map map, int x, int y) - { - bool valid = ValidateDeepWater(map, x, y); - - for (int j = 1, offset = 5; valid && j <= 5; ++j, offset += 5) - if (!ValidateDeepWater(map, x + offset, y + offset)) - valid = false; - else if (!ValidateDeepWater(map, x + offset, y - offset)) - valid = false; - else if (!ValidateDeepWater(map, x - offset, y + offset)) - valid = false; - else if (!ValidateDeepWater(map, x - offset, y - offset)) - valid = false; - - return valid; - } - - private static bool ValidateDeepWater(Map map, int x, int y) - { - int tileID = map.Tiles.GetLandTile(x, y).ID; - bool water = false; - - for (int i = 0; !water && i < m_WaterTiles.Length; i += 2) - water = tileID >= m_WaterTiles[i] && tileID <= m_WaterTiles[i + 1]; - - return water; - } - - private static bool ValidateUndeepWater(Map map, object obj, ref int z) - { - if (!(obj is StaticTarget)) - return false; - - StaticTarget target = (StaticTarget)obj; - - if (BaseHouse.FindHouseAt(target.Location, map, 0) != null) - return false; - - int itemID = target.ItemID; - - for (int i = 0; i < m_UndeepWaterTiles.Length; i += 2) - if (itemID >= m_UndeepWaterTiles[i] && itemID <= m_UndeepWaterTiles[i + 1]) + private static readonly int[] m_WaterTiles = { - z = target.Z; - return true; + 0x00A8, 0x00AB, + 0x0136, 0x0137 + }; + + private static readonly int[] m_UndeepWaterTiles = + { + 0x1797, 0x179C + }; + + [Constructible] + public SpecialFishingNet() : base(0x0DCA) + { + Weight = 1.0; + + if (Utility.RandomDouble() < 0.01) + Hue = m_Hues.RandomElement(); + else + Hue = 0x8A0; } - return false; + public SpecialFishingNet(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041079; // a special fishing net + + [CommandProperty(AccessLevel.GameMaster)] + public bool InUse { get; set; } + + public virtual bool RequireDeepWater => true; + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + AddNetProperties(list); + } + + protected virtual void AddNetProperties(ObjectPropertyList list) + { + // as if the name wasn't enough.. + list.Add(1017410); // Special Fishing Net + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(InUse); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + InUse = reader.ReadBool(); + + if (InUse) + Delete(); + + break; + } + } + + Stackable = false; + } + + public override void OnDoubleClick(Mobile from) + { + if (InUse) + { + from.SendLocalizedMessage(1010483); // Someone is already using that net! + } + else if (IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1010484); // Where do you wish to use the net? + from.BeginTarget(-1, true, TargetFlags.None, OnTarget); + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + + public void OnTarget(Mobile from, object obj) + { + if (Deleted || InUse) + return; + + if (!(obj is IPoint3D p3D)) + return; + + var map = from.Map; + + if (map == null || map == Map.Internal) + return; + + int x = p3D.X, y = p3D.Y, z = map.GetAverageZ(x, y); // OSI just takes the targeted Z + + if (!from.InRange(p3D, 6)) + { + from.SendLocalizedMessage(500976); // You need to be closer to the water to fish! + } + else if (!from.InLOS(obj)) + { + from.SendLocalizedMessage(500979); // You cannot see that location. + } + else if (RequireDeepWater + ? FullValidation(map, x, y) + : ValidateDeepWater(map, x, y) || ValidateUndeepWater(map, obj, ref z)) + { + var p = new Point3D(x, y, z); + + if (GetType() == typeof(SpecialFishingNet)) + for (var i = 1; i < Amount; ++i) // these were stackable before, doh + from.AddToBackpack(new SpecialFishingNet()); + + InUse = true; + Movable = false; + MoveToWorld(p, map); + + SpellHelper.Turn(from, p); + from.Animate(12, 5, 1, true, false, 0); + + Effects.SendLocationEffect(p, map, 0x352D, 16, 4); + Effects.PlaySound(p, map, 0x364); + + var index = 0; + + Timer.DelayCall( + TimeSpan.FromSeconds(1.0), + TimeSpan.FromSeconds(1.25), + 14, + () => DoEffect(from, p, index++) + ); + + from.SendLocalizedMessage( + RequireDeepWater + ? 1010487 + : 1074492 + ); // You plunge the net into the sea... / You plunge the net into the water... + } + else + { + from.SendLocalizedMessage( + RequireDeepWater + ? 1010485 + : 1074491 + ); // You can only use this net in deep water! / You can only use this net in water! + } + } + + private void DoEffect(Mobile from, Point3D p, int index) + { + if (Deleted) + return; + + if (index == 1) + { + Effects.SendLocationEffect(p, Map, 0x352D, 16, 4); + Effects.PlaySound(p, Map, 0x364); + } + else if (index <= 7 || index == 14) + { + if (RequireDeepWater) + for (var i = 0; i < 3; ++i) + { + int x, y; + + switch (Utility.Random(8)) + { + default: + case 0: + x = -1; + y = -1; + break; + case 1: + x = -1; + y = 0; + break; + case 2: + x = -1; + y = +1; + break; + case 3: + x = 0; + y = -1; + break; + case 4: + x = 0; + y = +1; + break; + case 5: + x = +1; + y = -1; + break; + case 6: + x = +1; + y = 0; + break; + case 7: + x = +1; + y = +1; + break; + } + + Effects.SendLocationEffect(new Point3D(p.X + x, p.Y + y, p.Z), Map, 0x352D, 16, 4); + } + else + Effects.SendLocationEffect(p, Map, 0x352D, 16, 4); + + if (Utility.RandomBool()) + Effects.PlaySound(p, Map, 0x364); + + if (index == 14) + FinishEffect(p, Map, from); + else + Z -= 1; + } + } + + protected virtual int GetSpawnCount() + { + var count = Utility.RandomMinMax(1, 3); + + if (Hue != 0x8A0) + count += Utility.RandomMinMax(1, 2); + + return count; + } + + protected void Spawn(Point3D p, Map map, BaseCreature spawn) + { + if (map == null) + { + spawn.Delete(); + return; + } + + int x = p.X, y = p.Y; + + for (var j = 0; j < 20; ++j) + { + var tx = p.X - 2 + Utility.Random(5); + var ty = p.Y - 2 + Utility.Random(5); + + var t = map.Tiles.GetLandTile(tx, ty); + + if (t.Z == p.Z && (t.ID >= 0xA8 && t.ID <= 0xAB || t.ID >= 0x136 && t.ID <= 0x137) && + !SpellHelper.CheckMulti(new Point3D(tx, ty, p.Z), map)) + { + x = tx; + y = ty; + break; + } + } + + spawn.MoveToWorld(new Point3D(x, y, p.Z), map); + + if (spawn is Kraken && Utility.RandomDouble() < 0.2) + spawn.PackItem(new MessageInABottle(map == Map.Felucca ? Map.Felucca : Map.Trammel)); + } + + protected virtual void FinishEffect(Point3D p, Map map, Mobile from) + { + from.RevealingAction(); + + var count = GetSpawnCount(); + + for (var i = 0; map != null && i < count; ++i) + { + var spawn = Utility.Random(4) switch + { + 0 => (BaseCreature)new SeaSerpent(), + 1 => new DeepSeaSerpent(), + 2 => new WaterElemental(), + 3 => new Kraken(), + _ => new SeaSerpent() + }; + + Spawn(p, map, spawn); + + spawn.Combatant = from; + } + + Delete(); + } + + public static bool FullValidation(Map map, int x, int y) + { + var valid = ValidateDeepWater(map, x, y); + + for (int j = 1, offset = 5; valid && j <= 5; ++j, offset += 5) + if (!ValidateDeepWater(map, x + offset, y + offset)) + valid = false; + else if (!ValidateDeepWater(map, x + offset, y - offset)) + valid = false; + else if (!ValidateDeepWater(map, x - offset, y + offset)) + valid = false; + else if (!ValidateDeepWater(map, x - offset, y - offset)) + valid = false; + + return valid; + } + + private static bool ValidateDeepWater(Map map, int x, int y) + { + var tileID = map.Tiles.GetLandTile(x, y).ID; + var water = false; + + for (var i = 0; !water && i < m_WaterTiles.Length; i += 2) + water = tileID >= m_WaterTiles[i] && tileID <= m_WaterTiles[i + 1]; + + return water; + } + + private static bool ValidateUndeepWater(Map map, object obj, ref int z) + { + if (!(obj is StaticTarget)) + return false; + + var target = (StaticTarget)obj; + + if (BaseHouse.FindHouseAt(target.Location, map, 0) != null) + return false; + + var itemID = target.ItemID; + + for (var i = 0; i < m_UndeepWaterTiles.Length; i += 2) + if (itemID >= m_UndeepWaterTiles[i] && itemID <= m_UndeepWaterTiles[i + 1]) + { + z = target.Z; + return true; + } + + return false; + } } - } - public class FabledFishingNet : SpecialFishingNet - { - [Constructible] - public FabledFishingNet() => Hue = 0x481; - - public FabledFishingNet(Serial serial) : base(serial) + public class FabledFishingNet : SpecialFishingNet { + [Constructible] + public FabledFishingNet() => Hue = 0x481; + + public FabledFishingNet(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1063451; // a fabled fishing net + + protected override void AddNetProperties(ObjectPropertyList list) + { + } + + protected override int GetSpawnCount() => base.GetSpawnCount() + 4; + + protected override void FinishEffect(Point3D p, Map map, Mobile from) + { + Spawn(p, map, new Leviathan(from)); + + base.FinishEffect(p, map, from); + } + + 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 int LabelNumber => 1063451; // a fabled fishing net - - protected override void AddNetProperties(ObjectPropertyList list) - { - } - - protected override int GetSpawnCount() => base.GetSpawnCount() + 4; - - protected override void FinishEffect(Point3D p, Map map, Mobile from) - { - Spawn(p, map, new Leviathan(from)); - - base.FinishEffect(p, map, from); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Harvest Tools/BaseHarvestTool.cs b/Projects/UOContent/Items/Skill Items/Harvest Tools/BaseHarvestTool.cs index 3c4dc8248..18fbcf58c 100644 --- a/Projects/UOContent/Items/Skill Items/Harvest Tools/BaseHarvestTool.cs +++ b/Projects/UOContent/Items/Skill Items/Harvest Tools/BaseHarvestTool.cs @@ -8,245 +8,248 @@ using Server.Network; namespace Server.Items { - public interface IUsesRemaining - { - int UsesRemaining { get; set; } - bool ShowUsesRemaining { get; set; } - } - - public abstract class BaseHarvestTool : Item, IUsesRemaining, ICraftable - { - private Mobile m_Crafter; - private ToolQuality m_Quality; - private int m_UsesRemaining; - - public BaseHarvestTool(int itemID, int usesRemaining = 50) : base(itemID) + public interface IUsesRemaining { - m_UsesRemaining = usesRemaining; - m_Quality = ToolQuality.Regular; + int UsesRemaining { get; set; } + bool ShowUsesRemaining { get; set; } } - public BaseHarvestTool(Serial serial) : base(serial) + public abstract class BaseHarvestTool : Item, IUsesRemaining, ICraftable { - } + private Mobile m_Crafter; + private ToolQuality m_Quality; + private int m_UsesRemaining; - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Crafter - { - get => m_Crafter; - set - { - m_Crafter = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public ToolQuality Quality - { - get => m_Quality; - set - { - UnscaleUses(); - m_Quality = value; - InvalidateProperties(); - ScaleUses(); - } - } - - public abstract HarvestSystem HarvestSystem { get; } - - public int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, - CraftItem craftItem, int resHue) - { - Quality = (ToolQuality)quality; - - if (makersMark) - Crafter = from; - - return quality; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int UsesRemaining - { - get => m_UsesRemaining; - set - { - m_UsesRemaining = value; - InvalidateProperties(); - } - } - - bool IUsesRemaining.ShowUsesRemaining - { - get => true; - set { } - } - - public void ScaleUses() - { - m_UsesRemaining = m_UsesRemaining * GetUsesScalar() / 100; - InvalidateProperties(); - } - - public void UnscaleUses() - { - m_UsesRemaining = m_UsesRemaining * 100 / GetUsesScalar(); - } - - public int GetUsesScalar() - { - if (m_Quality == ToolQuality.Exceptional) - return 200; - - return 100; - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - // Makers mark not displayed on OSI - // if (m_Crafter != null) - // list.Add( 1050043, m_Crafter.Name ); // crafted by ~1_NAME~ - - if (m_Quality == ToolQuality.Exceptional) - list.Add(1060636); // exceptional - - list.Add(1060584, m_UsesRemaining.ToString()); // uses remaining: ~1_val~ - } - - public virtual void DisplayDurabilityTo(Mobile m) - { - LabelToAffix(m, 1017323, AffixType.Append, $": {m_UsesRemaining}"); // Durability - } - - public override void OnSingleClick(Mobile from) - { - DisplayDurabilityTo(from); - - base.OnSingleClick(from); - } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack) || Parent == from) - HarvestSystem.BeginHarvesting(from, this); - else - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - AddContextMenuEntries(from, this, list, HarvestSystem); - } - - public static void AddContextMenuEntries(Mobile from, Item item, List list, HarvestSystem system) - { - if (system != Mining.System) - return; - - if (!item.IsChildOf(from.Backpack) && item.Parent != from) - return; - - if (!(from is PlayerMobile pm)) - return; - - ContextMenuEntry miningEntry = new ContextMenuEntry(pm.ToggleMiningStone ? 6179 : 6178); - miningEntry.Color = 0x421F; - list.Add(miningEntry); - - list.Add(new ToggleMiningStoneEntry(pm, false, 6176)); - list.Add(new ToggleMiningStoneEntry(pm, true, 6177)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(m_Crafter); - writer.Write((int)m_Quality); - - writer.Write(m_UsesRemaining); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_Crafter = reader.ReadMobile(); - m_Quality = (ToolQuality)reader.ReadInt(); - goto case 0; - } - case 0: - { - m_UsesRemaining = reader.ReadInt(); - break; - } - } - } - - private class ToggleMiningStoneEntry : ContextMenuEntry - { - private readonly PlayerMobile m_Mobile; - private readonly bool m_Value; - - public ToggleMiningStoneEntry(PlayerMobile mobile, bool value, int number) : base(number) - { - m_Mobile = mobile; - m_Value = value; - - bool stoneMining = mobile.StoneMining && mobile.Skills.Mining.Base >= 100.0; - - if (mobile.ToggleMiningStone == value || (value && !stoneMining)) - Flags |= CMEFlags.Disabled; - } - - public override void OnClick() - { - bool oldValue = m_Mobile.ToggleMiningStone; - - if (m_Value) + public BaseHarvestTool(int itemID, int usesRemaining = 50) : base(itemID) { - if (oldValue) - { - m_Mobile.SendLocalizedMessage(1054023); // You are already set to mine both ore and stone! - } - else if (!m_Mobile.StoneMining || m_Mobile.Skills.Mining.Base < 100.0) - { - m_Mobile.SendLocalizedMessage( - 1054024); // You have not learned how to mine stone or you do not have enough skill! - } - else - { - m_Mobile.ToggleMiningStone = true; - m_Mobile.SendLocalizedMessage(1054022); // You are now set to mine both ore and stone. - } + m_UsesRemaining = usesRemaining; + m_Quality = ToolQuality.Regular; } - else + + public BaseHarvestTool(Serial serial) : base(serial) { - if (oldValue) - { - m_Mobile.ToggleMiningStone = false; - m_Mobile.SendLocalizedMessage(1054020); // You are now set to mine only ore. - } - else - { - m_Mobile.SendLocalizedMessage(1054021); // You are already set to mine only ore! - } } - } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Crafter + { + get => m_Crafter; + set + { + m_Crafter = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public ToolQuality Quality + { + get => m_Quality; + set + { + UnscaleUses(); + m_Quality = value; + InvalidateProperties(); + ScaleUses(); + } + } + + public abstract HarvestSystem HarvestSystem { get; } + + public int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, + CraftItem craftItem, int resHue + ) + { + Quality = (ToolQuality)quality; + + if (makersMark) + Crafter = from; + + return quality; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int UsesRemaining + { + get => m_UsesRemaining; + set + { + m_UsesRemaining = value; + InvalidateProperties(); + } + } + + bool IUsesRemaining.ShowUsesRemaining + { + get => true; + set { } + } + + public void ScaleUses() + { + m_UsesRemaining = m_UsesRemaining * GetUsesScalar() / 100; + InvalidateProperties(); + } + + public void UnscaleUses() + { + m_UsesRemaining = m_UsesRemaining * 100 / GetUsesScalar(); + } + + public int GetUsesScalar() + { + if (m_Quality == ToolQuality.Exceptional) + return 200; + + return 100; + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + // Makers mark not displayed on OSI + // if (m_Crafter != null) + // list.Add( 1050043, m_Crafter.Name ); // crafted by ~1_NAME~ + + if (m_Quality == ToolQuality.Exceptional) + list.Add(1060636); // exceptional + + list.Add(1060584, m_UsesRemaining.ToString()); // uses remaining: ~1_val~ + } + + public virtual void DisplayDurabilityTo(Mobile m) + { + LabelToAffix(m, 1017323, AffixType.Append, $": {m_UsesRemaining}"); // Durability + } + + public override void OnSingleClick(Mobile from) + { + DisplayDurabilityTo(from); + + base.OnSingleClick(from); + } + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack) || Parent == from) + HarvestSystem.BeginHarvesting(from, this); + else + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + AddContextMenuEntries(from, this, list, HarvestSystem); + } + + public static void AddContextMenuEntries(Mobile from, Item item, List list, HarvestSystem system) + { + if (system != Mining.System) + return; + + if (!item.IsChildOf(from.Backpack) && item.Parent != from) + return; + + if (!(from is PlayerMobile pm)) + return; + + var miningEntry = new ContextMenuEntry(pm.ToggleMiningStone ? 6179 : 6178); + miningEntry.Color = 0x421F; + list.Add(miningEntry); + + list.Add(new ToggleMiningStoneEntry(pm, false, 6176)); + list.Add(new ToggleMiningStoneEntry(pm, true, 6177)); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(m_Crafter); + writer.Write((int)m_Quality); + + writer.Write(m_UsesRemaining); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_Crafter = reader.ReadMobile(); + m_Quality = (ToolQuality)reader.ReadInt(); + goto case 0; + } + case 0: + { + m_UsesRemaining = reader.ReadInt(); + break; + } + } + } + + private class ToggleMiningStoneEntry : ContextMenuEntry + { + private readonly PlayerMobile m_Mobile; + private readonly bool m_Value; + + public ToggleMiningStoneEntry(PlayerMobile mobile, bool value, int number) : base(number) + { + m_Mobile = mobile; + m_Value = value; + + var stoneMining = mobile.StoneMining && mobile.Skills.Mining.Base >= 100.0; + + if (mobile.ToggleMiningStone == value || value && !stoneMining) + Flags |= CMEFlags.Disabled; + } + + public override void OnClick() + { + var oldValue = m_Mobile.ToggleMiningStone; + + if (m_Value) + { + if (oldValue) + { + m_Mobile.SendLocalizedMessage(1054023); // You are already set to mine both ore and stone! + } + else if (!m_Mobile.StoneMining || m_Mobile.Skills.Mining.Base < 100.0) + { + m_Mobile.SendLocalizedMessage( + 1054024 + ); // You have not learned how to mine stone or you do not have enough skill! + } + else + { + m_Mobile.ToggleMiningStone = true; + m_Mobile.SendLocalizedMessage(1054022); // You are now set to mine both ore and stone. + } + } + else + { + if (oldValue) + { + m_Mobile.ToggleMiningStone = false; + m_Mobile.SendLocalizedMessage(1054020); // You are now set to mine only ore. + } + else + { + m_Mobile.SendLocalizedMessage(1054021); // You are already set to mine only ore! + } + } + } + } } - } } diff --git a/Projects/UOContent/Items/Skill Items/Harvest Tools/GargoylesPickaxe.cs b/Projects/UOContent/Items/Skill Items/Harvest Tools/GargoylesPickaxe.cs index c052c8022..fe405c4db 100644 --- a/Projects/UOContent/Items/Skill Items/Harvest Tools/GargoylesPickaxe.cs +++ b/Projects/UOContent/Items/Skill Items/Harvest Tools/GargoylesPickaxe.cs @@ -2,62 +2,62 @@ using Server.Engines.Harvest; namespace Server.Items { - public class GargoylesPickaxe : BaseAxe, IUsesRemaining - { - [Constructible] - public GargoylesPickaxe() : this(Utility.RandomMinMax(101, 125)) + public class GargoylesPickaxe : BaseAxe, IUsesRemaining { + [Constructible] + public GargoylesPickaxe() : this(Utility.RandomMinMax(101, 125)) + { + } + + [Constructible] + public GargoylesPickaxe(int uses) : base(0xE85 + Utility.Random(2)) + { + Weight = 11.0; + UsesRemaining = uses; + ShowUsesRemaining = true; + } + + public GargoylesPickaxe(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041281; // a gargoyle's pickaxe + public override HarvestSystem HarvestSystem => Mining.System; + + public override WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike; + public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm; + + public override int AosStrengthReq => 50; + public override int AosMinDamage => 13; + public override int AosMaxDamage => 15; + public override int AosSpeed => 35; + public override float MlSpeed => 3.00f; + + public override int OldStrengthReq => 25; + public override int OldMinDamage => 1; + public override int OldMaxDamage => 15; + public override int OldSpeed => 35; + + public override int InitMinHits => 31; + public override int InitMaxHits => 60; + + public override WeaponAnimation DefAnimation => WeaponAnimation.Slash1H; + + 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 (Hue == 0x973) + Hue = 0x0; + } } - - [Constructible] - public GargoylesPickaxe(int uses) : base(0xE85 + Utility.Random(2)) - { - Weight = 11.0; - UsesRemaining = uses; - ShowUsesRemaining = true; - } - - public GargoylesPickaxe(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041281; // a gargoyle's pickaxe - public override HarvestSystem HarvestSystem => Mining.System; - - public override WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike; - public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm; - - public override int AosStrengthReq => 50; - public override int AosMinDamage => 13; - public override int AosMaxDamage => 15; - public override int AosSpeed => 35; - public override float MlSpeed => 3.00f; - - public override int OldStrengthReq => 25; - public override int OldMinDamage => 1; - public override int OldMaxDamage => 15; - public override int OldSpeed => 35; - - public override int InitMinHits => 31; - public override int InitMaxHits => 60; - - public override WeaponAnimation DefAnimation => WeaponAnimation.Slash1H; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Hue == 0x973) - Hue = 0x0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Harvest Tools/ProspectorsTool.cs b/Projects/UOContent/Items/Skill Items/Harvest Tools/ProspectorsTool.cs index 4fa2baee0..8406445c7 100644 --- a/Projects/UOContent/Items/Skill Items/Harvest Tools/ProspectorsTool.cs +++ b/Projects/UOContent/Items/Skill Items/Harvest Tools/ProspectorsTool.cs @@ -4,171 +4,171 @@ using Server.Targeting; namespace Server.Items { - public class ProspectorsTool : BaseBashing, IUsesRemaining - { - private int m_UsesRemaining; - - [Constructible] - public ProspectorsTool() : base(0xFB4) + public class ProspectorsTool : BaseBashing, IUsesRemaining { - Weight = 9.0; - UsesRemaining = 50; - } + private int m_UsesRemaining; - public ProspectorsTool(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1049065; // prospector's tool - - public override WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow; - public override WeaponAbility SecondaryAbility => WeaponAbility.ShadowStrike; - - public override int AosStrengthReq => 40; - public override int AosMinDamage => 13; - public override int AosMaxDamage => 15; - public override int AosSpeed => 33; - - public override int OldStrengthReq => 10; - public override int OldMinDamage => 6; - public override int OldMaxDamage => 8; - public override int OldSpeed => 33; - - [CommandProperty(AccessLevel.GameMaster)] - public int UsesRemaining - { - get => m_UsesRemaining; - set - { - m_UsesRemaining = value; - InvalidateProperties(); - } - } - - bool IUsesRemaining.ShowUsesRemaining - { - get => true; - set { } - } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack) || Parent == from) - from.Target = new InternalTarget(this); - else - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - - public void Prospect(Mobile from, object toProspect) - { - if (!IsChildOf(from.Backpack) && Parent != from) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - return; - } - - HarvestSystem system = Mining.System; - - if (!system.GetHarvestDetails(from, this, toProspect, out int tileID, out Map map, out Point3D loc)) - { - from.SendLocalizedMessage(1049048); // You cannot use your prospector tool on that. - return; - } - - HarvestDefinition def = system.GetDefinition(tileID); - - if (def == null || def.Veins.Length <= 1) - { - from.SendLocalizedMessage(1049048); // You cannot use your prospector tool on that. - return; - } - - HarvestBank bank = def.GetBank(map, loc.X, loc.Y); - - if (bank == null) - { - from.SendLocalizedMessage(1049048); // You cannot use your prospector tool on that. - return; - } - - HarvestVein vein = bank.Vein, defaultVein = bank.DefaultVein; - - if (vein == null || defaultVein == null) - { - from.SendLocalizedMessage(1049048); // You cannot use your prospector tool on that. - return; - } - - if (vein != defaultVein) - { - from.SendLocalizedMessage(1049049); // That ore looks to be prospected already. - return; - } - - int veinIndex = Array.IndexOf(def.Veins, vein); - - if (veinIndex < 0) - { - from.SendLocalizedMessage(1049048); // You cannot use your prospector tool on that. - } - else if (veinIndex >= def.Veins.Length - 1) - { - from.SendLocalizedMessage(1049061); // You cannot improve valorite ore through prospecting. - } - else - { - bank.Vein = def.Veins[veinIndex + 1]; - from.SendLocalizedMessage(1049050 + veinIndex); - - --UsesRemaining; - - if (UsesRemaining <= 0) + [Constructible] + public ProspectorsTool() : base(0xFB4) { - from.SendLocalizedMessage(1049062); // You have used up your prospector's tool. - Delete(); + Weight = 9.0; + UsesRemaining = 50; + } + + public ProspectorsTool(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1049065; // prospector's tool + + public override WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow; + public override WeaponAbility SecondaryAbility => WeaponAbility.ShadowStrike; + + public override int AosStrengthReq => 40; + public override int AosMinDamage => 13; + public override int AosMaxDamage => 15; + public override int AosSpeed => 33; + + public override int OldStrengthReq => 10; + public override int OldMinDamage => 6; + public override int OldMaxDamage => 8; + public override int OldSpeed => 33; + + [CommandProperty(AccessLevel.GameMaster)] + public int UsesRemaining + { + get => m_UsesRemaining; + set + { + m_UsesRemaining = value; + InvalidateProperties(); + } + } + + bool IUsesRemaining.ShowUsesRemaining + { + get => true; + set { } + } + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack) || Parent == from) + from.Target = new InternalTarget(this); + else + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + + public void Prospect(Mobile from, object toProspect) + { + if (!IsChildOf(from.Backpack) && Parent != from) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + return; + } + + HarvestSystem system = Mining.System; + + if (!system.GetHarvestDetails(from, this, toProspect, out var tileID, out var map, out var loc)) + { + from.SendLocalizedMessage(1049048); // You cannot use your prospector tool on that. + return; + } + + var def = system.GetDefinition(tileID); + + if (def == null || def.Veins.Length <= 1) + { + from.SendLocalizedMessage(1049048); // You cannot use your prospector tool on that. + return; + } + + var bank = def.GetBank(map, loc.X, loc.Y); + + if (bank == null) + { + from.SendLocalizedMessage(1049048); // You cannot use your prospector tool on that. + return; + } + + HarvestVein vein = bank.Vein, defaultVein = bank.DefaultVein; + + if (vein == null || defaultVein == null) + { + from.SendLocalizedMessage(1049048); // You cannot use your prospector tool on that. + return; + } + + if (vein != defaultVein) + { + from.SendLocalizedMessage(1049049); // That ore looks to be prospected already. + return; + } + + var veinIndex = Array.IndexOf(def.Veins, vein); + + if (veinIndex < 0) + { + from.SendLocalizedMessage(1049048); // You cannot use your prospector tool on that. + } + else if (veinIndex >= def.Veins.Length - 1) + { + from.SendLocalizedMessage(1049061); // You cannot improve valorite ore through prospecting. + } + else + { + bank.Vein = def.Veins[veinIndex + 1]; + from.SendLocalizedMessage(1049050 + veinIndex); + + --UsesRemaining; + + if (UsesRemaining <= 0) + { + from.SendLocalizedMessage(1049062); // You have used up your prospector's tool. + Delete(); + } + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + writer.Write(m_UsesRemaining); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_UsesRemaining = reader.ReadInt(); + break; + } + case 0: + { + m_UsesRemaining = 50; + break; + } + } + } + + private class InternalTarget : Target + { + private readonly ProspectorsTool m_Tool; + + public InternalTarget(ProspectorsTool tool) : base(2, true, TargetFlags.None) => m_Tool = tool; + + protected override void OnTarget(Mobile from, object targeted) + { + m_Tool.Prospect(from, targeted); + } } - } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - writer.Write(m_UsesRemaining); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_UsesRemaining = reader.ReadInt(); - break; - } - case 0: - { - m_UsesRemaining = 50; - break; - } - } - } - - private class InternalTarget : Target - { - private readonly ProspectorsTool m_Tool; - - public InternalTarget(ProspectorsTool tool) : base(2, true, TargetFlags.None) => m_Tool = tool; - - protected override void OnTarget(Mobile from, object targeted) - { - m_Tool.Prospect(from, targeted); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Harvest Tools/Shovel.cs b/Projects/UOContent/Items/Skill Items/Harvest Tools/Shovel.cs index 0495b2137..956d34ad3 100644 --- a/Projects/UOContent/Items/Skill Items/Harvest Tools/Shovel.cs +++ b/Projects/UOContent/Items/Skill Items/Harvest Tools/Shovel.cs @@ -2,29 +2,29 @@ using Server.Engines.Harvest; namespace Server.Items { - public class Shovel : BaseHarvestTool - { - [Constructible] - public Shovel(int uses = 50) : base(0xF39, uses) => Weight = 5.0; - - public Shovel(Serial serial) : base(serial) + public class Shovel : BaseHarvestTool { + [Constructible] + public Shovel(int uses = 50) : base(0xF39, uses) => Weight = 5.0; + + public Shovel(Serial serial) : base(serial) + { + } + + public override HarvestSystem HarvestSystem => Mining.System; + + 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 HarvestSystem HarvestSystem => Mining.System; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Harvest Tools/SturdyPickaxe.cs b/Projects/UOContent/Items/Skill Items/Harvest Tools/SturdyPickaxe.cs index 436cda03b..03d7d2c08 100644 --- a/Projects/UOContent/Items/Skill Items/Harvest Tools/SturdyPickaxe.cs +++ b/Projects/UOContent/Items/Skill Items/Harvest Tools/SturdyPickaxe.cs @@ -2,52 +2,52 @@ using Server.Engines.Harvest; namespace Server.Items { - public class SturdyPickaxe : BaseAxe, IUsesRemaining - { - [Constructible] - public SturdyPickaxe(int uses = 180) : base(0xE86) + public class SturdyPickaxe : BaseAxe, IUsesRemaining { - Weight = 11.0; - Hue = 0x973; - UsesRemaining = uses; - ShowUsesRemaining = true; + [Constructible] + public SturdyPickaxe(int uses = 180) : base(0xE86) + { + Weight = 11.0; + Hue = 0x973; + UsesRemaining = uses; + ShowUsesRemaining = true; + } + + public SturdyPickaxe(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1045126; // sturdy pickaxe + public override HarvestSystem HarvestSystem => Mining.System; + + public override WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike; + public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm; + + public override int AosStrengthReq => 50; + public override int AosMinDamage => 13; + public override int AosMaxDamage => 15; + public override int AosSpeed => 35; + public override float MlSpeed => 3.00f; + + public override int OldStrengthReq => 25; + public override int OldMinDamage => 1; + public override int OldMaxDamage => 15; + public override int OldSpeed => 35; + + public override WeaponAnimation DefAnimation => WeaponAnimation.Slash1H; + + 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 SturdyPickaxe(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1045126; // sturdy pickaxe - public override HarvestSystem HarvestSystem => Mining.System; - - public override WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike; - public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm; - - public override int AosStrengthReq => 50; - public override int AosMinDamage => 13; - public override int AosMaxDamage => 15; - public override int AosSpeed => 35; - public override float MlSpeed => 3.00f; - - public override int OldStrengthReq => 25; - public override int OldMinDamage => 1; - public override int OldMaxDamage => 15; - public override int OldSpeed => 35; - - public override WeaponAnimation DefAnimation => WeaponAnimation.Slash1H; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Harvest Tools/SturdyShovel.cs b/Projects/UOContent/Items/Skill Items/Harvest Tools/SturdyShovel.cs index 27ca76cdc..398035917 100644 --- a/Projects/UOContent/Items/Skill Items/Harvest Tools/SturdyShovel.cs +++ b/Projects/UOContent/Items/Skill Items/Harvest Tools/SturdyShovel.cs @@ -2,34 +2,34 @@ using Server.Engines.Harvest; namespace Server.Items { - public class SturdyShovel : BaseHarvestTool - { - [Constructible] - public SturdyShovel(int uses = 180) : base(0xF39, uses) + public class SturdyShovel : BaseHarvestTool { - Weight = 5.0; - Hue = 0x973; + [Constructible] + public SturdyShovel(int uses = 180) : base(0xF39, uses) + { + Weight = 5.0; + Hue = 0x973; + } + + public SturdyShovel(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1045125; // sturdy shovel + public override HarvestSystem HarvestSystem => Mining.System; + + 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 SturdyShovel(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1045125; // sturdy shovel - public override HarvestSystem HarvestSystem => Mining.System; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Lumberjack/Log.cs b/Projects/UOContent/Items/Skill Items/Lumberjack/Log.cs index 4614869c5..423aedb23 100644 --- a/Projects/UOContent/Items/Skill Items/Lumberjack/Log.cs +++ b/Projects/UOContent/Items/Skill Items/Lumberjack/Log.cs @@ -1,334 +1,334 @@ namespace Server.Items { - [Flippable(0x1bdd, 0x1be0)] - public class Log : Item, ICommodity, IAxe - { - private CraftResource m_Resource; - - [Constructible] - public Log(int amount = 1) : this(CraftResource.RegularWood, amount) + [Flippable(0x1bdd, 0x1be0)] + public class Log : Item, ICommodity, IAxe { + private CraftResource m_Resource; + + [Constructible] + public Log(int amount = 1) : this(CraftResource.RegularWood, amount) + { + } + + [Constructible] + public Log(CraftResource resource) + : this(resource, 1) + { + } + + [Constructible] + public Log(CraftResource resource, int amount) + : base(0x1BDD) + { + Stackable = true; + Weight = 2.0; + Amount = amount; + + m_Resource = resource; + Hue = CraftResources.GetHue(resource); + } + + public Log(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public CraftResource Resource + { + get => m_Resource; + set + { + m_Resource = value; + InvalidateProperties(); + } + } + + public virtual bool Axe(Mobile from, BaseAxe axe) + { + if (!TryCreateBoards(from, 0, new Board())) + return false; + + return true; + } + + int ICommodity.DescriptionNumber => CraftResources.IsStandard(m_Resource) + ? LabelNumber + : 1075062 + ((int)m_Resource - (int)CraftResource.RegularWood); + + bool ICommodity.IsDeedable => true; + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (!CraftResources.IsStandard(m_Resource)) + { + var num = CraftResources.GetLocalizationNumber(m_Resource); + + if (num > 0) + list.Add(num); + else + list.Add(CraftResources.GetName(m_Resource)); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write((int)m_Resource); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_Resource = (CraftResource)reader.ReadInt(); + break; + } + } + + if (version == 0) + m_Resource = CraftResource.RegularWood; + } + + public virtual bool TryCreateBoards(Mobile from, double skill, Item item) + { + if (Deleted || !from.CanSee(this)) + return false; + if (from.Skills.Carpentry.Value < skill && + from.Skills.Lumberjacking.Value < skill) + { + item.Delete(); + from.SendLocalizedMessage(1072652); // You cannot work this strange and unusual wood. + return false; + } + + ScissorHelper(from, item, 1, false); + return true; + } } - [Constructible] - public Log(CraftResource resource) - : this(resource, 1) + public class HeartwoodLog : Log { + [Constructible] + public HeartwoodLog(int amount = 1) + : base(CraftResource.Heartwood, amount) + { + } + + public HeartwoodLog(Serial serial) : base(serial) + { + } + + 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 Axe(Mobile from, BaseAxe axe) + { + if (!TryCreateBoards(from, 100, new HeartwoodBoard())) + return false; + + return true; + } } - [Constructible] - public Log(CraftResource resource, int amount) - : base(0x1BDD) + public class BloodwoodLog : Log { - Stackable = true; - Weight = 2.0; - Amount = amount; + [Constructible] + public BloodwoodLog(int amount = 1) + : base(CraftResource.Bloodwood, amount) + { + } - m_Resource = resource; - Hue = CraftResources.GetHue(resource); + public BloodwoodLog(Serial serial) + : base(serial) + { + } + + 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 Axe(Mobile from, BaseAxe axe) + { + if (!TryCreateBoards(from, 100, new BloodwoodBoard())) + return false; + + return true; + } } - public Log(Serial serial) : base(serial) + public class FrostwoodLog : Log { + [Constructible] + public FrostwoodLog(int amount = 1) + : base(CraftResource.Frostwood, amount) + { + } + + public FrostwoodLog(Serial serial) + : base(serial) + { + } + + 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 Axe(Mobile from, BaseAxe axe) + { + if (!TryCreateBoards(from, 100, new FrostwoodBoard())) + return false; + + return true; + } } - [CommandProperty(AccessLevel.GameMaster)] - public CraftResource Resource + public class OakLog : Log { - get => m_Resource; - set - { - m_Resource = value; - InvalidateProperties(); - } + [Constructible] + public OakLog(int amount = 1) + : base(CraftResource.OakWood, amount) + { + } + + public OakLog(Serial serial) + : base(serial) + { + } + + 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 Axe(Mobile from, BaseAxe axe) + { + if (!TryCreateBoards(from, 65, new OakBoard())) + return false; + + return true; + } } - public virtual bool Axe(Mobile from, BaseAxe axe) + public class AshLog : Log { - if (!TryCreateBoards(from, 0, new Board())) - return false; + [Constructible] + public AshLog(int amount = 1) + : base(CraftResource.AshWood, amount) + { + } - return true; + public AshLog(Serial serial) + : base(serial) + { + } + + 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 Axe(Mobile from, BaseAxe axe) + { + if (!TryCreateBoards(from, 80, new AshBoard())) + return false; + + return true; + } } - int ICommodity.DescriptionNumber => CraftResources.IsStandard(m_Resource) - ? LabelNumber - : 1075062 + ((int)m_Resource - (int)CraftResource.RegularWood); - - bool ICommodity.IsDeedable => true; - - public override void GetProperties(ObjectPropertyList list) + public class YewLog : Log { - base.GetProperties(list); + [Constructible] + public YewLog(int amount = 1) + : base(CraftResource.YewWood, amount) + { + } - if (!CraftResources.IsStandard(m_Resource)) - { - int num = CraftResources.GetLocalizationNumber(m_Resource); + public YewLog(Serial serial) + : base(serial) + { + } - if (num > 0) - list.Add(num); - else - list.Add(CraftResources.GetName(m_Resource)); - } + 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 Axe(Mobile from, BaseAxe axe) + { + if (!TryCreateBoards(from, 95, new YewBoard())) + return false; + + return true; + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write((int)m_Resource); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_Resource = (CraftResource)reader.ReadInt(); - break; - } - } - - if (version == 0) - m_Resource = CraftResource.RegularWood; - } - - public virtual bool TryCreateBoards(Mobile from, double skill, Item item) - { - if (Deleted || !from.CanSee(this)) - return false; - if (from.Skills.Carpentry.Value < skill && - from.Skills.Lumberjacking.Value < skill) - { - item.Delete(); - from.SendLocalizedMessage(1072652); // You cannot work this strange and unusual wood. - return false; - } - - ScissorHelper(from, item, 1, false); - return true; - } - } - - public class HeartwoodLog : Log - { - [Constructible] - public HeartwoodLog(int amount = 1) - : base(CraftResource.Heartwood, amount) - { - } - - public HeartwoodLog(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override bool Axe(Mobile from, BaseAxe axe) - { - if (!TryCreateBoards(from, 100, new HeartwoodBoard())) - return false; - - return true; - } - } - - public class BloodwoodLog : Log - { - [Constructible] - public BloodwoodLog(int amount = 1) - : base(CraftResource.Bloodwood, amount) - { - } - - public BloodwoodLog(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override bool Axe(Mobile from, BaseAxe axe) - { - if (!TryCreateBoards(from, 100, new BloodwoodBoard())) - return false; - - return true; - } - } - - public class FrostwoodLog : Log - { - [Constructible] - public FrostwoodLog(int amount = 1) - : base(CraftResource.Frostwood, amount) - { - } - - public FrostwoodLog(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override bool Axe(Mobile from, BaseAxe axe) - { - if (!TryCreateBoards(from, 100, new FrostwoodBoard())) - return false; - - return true; - } - } - - public class OakLog : Log - { - [Constructible] - public OakLog(int amount = 1) - : base(CraftResource.OakWood, amount) - { - } - - public OakLog(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override bool Axe(Mobile from, BaseAxe axe) - { - if (!TryCreateBoards(from, 65, new OakBoard())) - return false; - - return true; - } - } - - public class AshLog : Log - { - [Constructible] - public AshLog(int amount = 1) - : base(CraftResource.AshWood, amount) - { - } - - public AshLog(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override bool Axe(Mobile from, BaseAxe axe) - { - if (!TryCreateBoards(from, 80, new AshBoard())) - return false; - - return true; - } - } - - public class YewLog : Log - { - [Constructible] - public YewLog(int amount = 1) - : base(CraftResource.YewWood, amount) - { - } - - public YewLog(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override bool Axe(Mobile from, BaseAxe axe) - { - if (!TryCreateBoards(from, 95, new YewBoard())) - return false; - - return true; - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/BookOfBushido.cs b/Projects/UOContent/Items/Skill Items/Magical/BookOfBushido.cs index 72eb8438f..6256ab228 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/BookOfBushido.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/BookOfBushido.cs @@ -1,33 +1,34 @@ namespace Server.Items { - public class BookOfBushido : Spellbook - { - [Constructible] - public BookOfBushido(ulong content = 0x3F) : base(content, 0x238C) => Layer = Core.ML ? Layer.OneHanded : Layer.Invalid; - - public BookOfBushido(Serial serial) : base(serial) + public class BookOfBushido : Spellbook { + [Constructible] + public BookOfBushido(ulong content = 0x3F) : base(content, 0x238C) => + Layer = Core.ML ? Layer.OneHanded : Layer.Invalid; + + public BookOfBushido(Serial serial) : base(serial) + { + } + + public override SpellbookType SpellbookType => SpellbookType.Samurai; + public override int BookOffset => 400; + public override int BookCount => 6; + + 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 && Core.ML) + Layer = Layer.OneHanded; + } } - - public override SpellbookType SpellbookType => SpellbookType.Samurai; - public override int BookOffset => 400; - public override int BookCount => 6; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version == 0 && Core.ML) - Layer = Layer.OneHanded; - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/BookOfChivalry.cs b/Projects/UOContent/Items/Skill Items/Magical/BookOfChivalry.cs index c050a0153..652d61caa 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/BookOfChivalry.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/BookOfChivalry.cs @@ -1,33 +1,34 @@ namespace Server.Items { - public class BookOfChivalry : Spellbook - { - [Constructible] - public BookOfChivalry(ulong content = 0x3FF) : base(content, 0x2252) => Layer = Core.ML ? Layer.OneHanded : Layer.Invalid; - - public BookOfChivalry(Serial serial) : base(serial) + public class BookOfChivalry : Spellbook { + [Constructible] + public BookOfChivalry(ulong content = 0x3FF) : base(content, 0x2252) => + Layer = Core.ML ? Layer.OneHanded : Layer.Invalid; + + public BookOfChivalry(Serial serial) : base(serial) + { + } + + public override SpellbookType SpellbookType => SpellbookType.Paladin; + public override int BookOffset => 200; + public override int BookCount => 10; + + 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 && Core.ML) + Layer = Layer.OneHanded; + } } - - public override SpellbookType SpellbookType => SpellbookType.Paladin; - public override int BookOffset => 200; - public override int BookCount => 10; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version == 0 && Core.ML) - Layer = Layer.OneHanded; - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/BookOfNinjitsu.cs b/Projects/UOContent/Items/Skill Items/Magical/BookOfNinjitsu.cs index 71350e7d6..7cac60f36 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/BookOfNinjitsu.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/BookOfNinjitsu.cs @@ -1,33 +1,34 @@ namespace Server.Items { - public class BookOfNinjitsu : Spellbook - { - [Constructible] - public BookOfNinjitsu(ulong content = 0xFF) : base(content, 0x23A0) => Layer = Core.ML ? Layer.OneHanded : Layer.Invalid; - - public BookOfNinjitsu(Serial serial) : base(serial) + public class BookOfNinjitsu : Spellbook { + [Constructible] + public BookOfNinjitsu(ulong content = 0xFF) : base(content, 0x23A0) => + Layer = Core.ML ? Layer.OneHanded : Layer.Invalid; + + public BookOfNinjitsu(Serial serial) : base(serial) + { + } + + public override SpellbookType SpellbookType => SpellbookType.Ninja; + public override int BookOffset => 500; + public override int BookCount => 8; + + 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 && Core.ML) + Layer = Layer.OneHanded; + } } - - public override SpellbookType SpellbookType => SpellbookType.Ninja; - public override int BookOffset => 500; - public override int BookCount => 8; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version == 0 && Core.ML) - Layer = Layer.OneHanded; - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Misc/BlankScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Misc/BlankScroll.cs index 5e5b5c813..07f5db4d8 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Misc/BlankScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Misc/BlankScroll.cs @@ -1,34 +1,34 @@ namespace Server.Items { - public class BlankScroll : Item, ICommodity - { - [Constructible] - public BlankScroll(int amount = 1) : base(0xEF3) + public class BlankScroll : Item, ICommodity { - Stackable = true; - Weight = 1.0; - Amount = amount; + [Constructible] + public BlankScroll(int amount = 1) : base(0xEF3) + { + Stackable = true; + Weight = 1.0; + Amount = amount; + } + + public BlankScroll(Serial serial) : base(serial) + { + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => Core.ML; + + 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 BlankScroll(Serial serial) : base(serial) - { - } - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => Core.ML; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Misc/Bottle.cs b/Projects/UOContent/Items/Skill Items/Magical/Misc/Bottle.cs index 1959603b4..ca66258a4 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Misc/Bottle.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Misc/Bottle.cs @@ -1,34 +1,34 @@ namespace Server.Items { - public class Bottle : Item, ICommodity - { - [Constructible] - public Bottle(int amount = 1) : base(0xF0E) + public class Bottle : Item, ICommodity { - Stackable = true; - Weight = 1.0; - Amount = amount; + [Constructible] + public Bottle(int amount = 1) : base(0xF0E) + { + Stackable = true; + Weight = 1.0; + Amount = amount; + } + + public Bottle(Serial serial) : base(serial) + { + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => Core.ML; + + 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 Bottle(Serial serial) : base(serial) - { - } - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => Core.ML; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Misc/Moongate.cs b/Projects/UOContent/Items/Skill Items/Magical/Misc/Moongate.cs index 9da6f2ea4..611570c87 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Misc/Moongate.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Misc/Moongate.cs @@ -8,377 +8,407 @@ using Server.Regions; namespace Server.Items { - [DispellableField] - public class Moongate : Item - { -[Constructible] - public Moongate(bool dispellable = true) : this(Point3D.Zero, null, dispellable) + [DispellableField] + public class Moongate : Item { + [Constructible] + public Moongate(bool dispellable = true) : this(Point3D.Zero, null, dispellable) + { + } + + [Constructible] + public Moongate(Point3D target, Map targetMap = null, bool dispellable = true) : base(0xF6C) + { + Movable = false; + Light = LightType.Circle300; + + Target = target; + TargetMap = targetMap; + Dispellable = dispellable; + } + + public Moongate(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D Target { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Map TargetMap { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Dispellable { get; set; } + + public virtual bool ShowFeluccaWarning => false; + + public override void OnDoubleClick(Mobile from) + { + if (!from.Player) + return; + + if (from.InRange(GetWorldLocation(), 1)) + CheckGate(from, 1); + else + from.SendLocalizedMessage(500446); // That is too far away. + } + + public override bool OnMoveOver(Mobile m) + { + if (m.Player) + CheckGate(m, 0); + + return true; + } + + public virtual void CheckGate(Mobile m, int range) + { + if (m.Hidden && m.AccessLevel == AccessLevel.Player && Core.ML) + m.RevealingAction(); + + new DelayTimer(m, this, range).Start(); + } + + public virtual void OnGateUsed(Mobile m) + { + } + + public virtual void UseGate(Mobile m) + { + var flags = m.NetState?.Flags ?? ClientFlags.None; + + if (Sigil.ExistsOn(m)) + { + m.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. + } + else if (TargetMap == Map.Felucca && m is PlayerMobile mobile && mobile.Young) + { + mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young. + } + else if (m.Kills >= 5 && TargetMap != Map.Felucca || + TargetMap == Map.Tokuno && (flags & ClientFlags.Tokuno) == 0 || + TargetMap == Map.Malas && (flags & ClientFlags.Malas) == 0 || + TargetMap == Map.Ilshenar && (flags & ClientFlags.Ilshenar) == 0) + { + m.SendLocalizedMessage(1019004); // You are not allowed to travel there. + } + else if (m.Spell != null) + { + m.SendLocalizedMessage(1049616); // You are too busy to do that at the moment. + } + else if (TargetMap != null && TargetMap != Map.Internal) + { + BaseCreature.TeleportPets(m, Target, TargetMap); + + m.MoveToWorld(Target, TargetMap); + + if (m.AccessLevel == AccessLevel.Player || !m.Hidden) + m.PlaySound(0x1FE); + + OnGateUsed(m); + } + else + { + m.SendMessage("This moongate does not seem to go anywhere."); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(Target); + writer.Write(TargetMap); + + // Version 1 + writer.Write(Dispellable); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + Target = reader.ReadPoint3D(); + TargetMap = reader.ReadMap(); + + if (version >= 1) + Dispellable = reader.ReadBool(); + } + + public virtual bool ValidateUse(Mobile from, bool message) + { + if (from.Deleted || Deleted) + return false; + + if (from.Map != Map || !from.InRange(this, 1)) + { + if (message) + from.SendLocalizedMessage(500446); // That is too far away. + + return false; + } + + return true; + } + + public virtual void BeginConfirmation(Mobile from) + { + if (IsInTown(@from.Location, @from.Map) && !IsInTown(Target, TargetMap) || + @from.Map != Map.Felucca && TargetMap == Map.Felucca && ShowFeluccaWarning) + { + if (from.AccessLevel == AccessLevel.Player || !from.Hidden) + from.Send(new PlaySound(0x20E, from.Location)); + from.CloseGump(); + from.SendGump(new MoongateConfirmGump(from, this)); + } + else + { + EndConfirmation(from); + } + } + + public virtual void EndConfirmation(Mobile from) + { + if (!ValidateUse(from, true)) + return; + + UseGate(from); + } + + public virtual void DelayCallback(Mobile from, int range) + { + if (!ValidateUse(from, false) || !from.InRange(this, range)) + return; + + if (TargetMap != null) + BeginConfirmation(from); + else + from.SendMessage("This moongate does not seem to go anywhere."); + } + + public static bool IsInTown(Point3D p, Map map) => + map != null && Region.Find(p, map).GetRegion()?.IsDisabled() == false; + + private class DelayTimer : Timer + { + private readonly Mobile m_From; + private readonly Moongate m_Gate; + private readonly int m_Range; + + public DelayTimer(Mobile from, Moongate gate, int range) : base(TimeSpan.FromSeconds(1.0)) + { + m_From = from; + m_Gate = gate; + m_Range = range; + } + + protected override void OnTick() + { + m_Gate.DelayCallback(m_From, m_Range); + } + } } - [Constructible] - public Moongate(Point3D target, Map targetMap = null, bool dispellable = true) : base(0xF6C) + public class ConfirmationMoongate : Moongate { - Movable = false; - Light = LightType.Circle300; + [Constructible] + public ConfirmationMoongate() : this(Point3D.Zero) + { + } - Target = target; - TargetMap = targetMap; - Dispellable = dispellable; + [Constructible] + public ConfirmationMoongate(Point3D target, Map targetMap = null) : base(target, targetMap) + { + } + + public ConfirmationMoongate(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int GumpWidth { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int GumpHeight { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int TitleColor { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int MessageColor { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int TitleNumber { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int MessageNumber { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public string MessageString { get; set; } + + public virtual void Warning_Callback(Mobile from, bool okay) + { + if (okay) + EndConfirmation(from); + } + + public override void BeginConfirmation(Mobile from) + { + if (GumpWidth > 0 && GumpHeight > 0 && TitleNumber > 0 && (MessageNumber > 0 || MessageString != null)) + { + from.CloseGump(); + from.SendGump( + new WarningGump( + TitleNumber, + TitleColor, + MessageString ?? (object)MessageNumber, + MessageColor, + GumpWidth, + GumpHeight, + okay => Warning_Callback(from, okay) + ) + ); + } + else + { + base.BeginConfirmation(from); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.WriteEncodedInt(GumpWidth); + writer.WriteEncodedInt(GumpHeight); + + writer.WriteEncodedInt(TitleColor); + writer.WriteEncodedInt(MessageColor); + + writer.WriteEncodedInt(TitleNumber); + writer.WriteEncodedInt(MessageNumber); + + writer.Write(MessageString); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + GumpWidth = reader.ReadEncodedInt(); + GumpHeight = reader.ReadEncodedInt(); + + TitleColor = reader.ReadEncodedInt(); + MessageColor = reader.ReadEncodedInt(); + + TitleNumber = reader.ReadEncodedInt(); + MessageNumber = reader.ReadEncodedInt(); + + MessageString = reader.ReadString(); + + break; + } + } + } } - public Moongate(Serial serial) : base(serial) + public class MoongateConfirmGump : Gump { + private readonly Mobile m_From; + private readonly Moongate m_Gate; + + public MoongateConfirmGump(Mobile from, Moongate gate) : base(Core.AOS ? 110 : 20, Core.AOS ? 100 : 30) + { + m_From = from; + m_Gate = gate; + + if (Core.AOS) + { + Closable = false; + + AddPage(0); + + AddBackground(0, 0, 420, 280, 5054); + + AddImageTiled(10, 10, 400, 20, 2624); + AddAlphaRegion(10, 10, 400, 20); + + AddHtmlLocalized(10, 10, 400, 20, 1062051, 30720); // Gate Warning + + AddImageTiled(10, 40, 400, 200, 2624); + AddAlphaRegion(10, 40, 400, 200); + + if (from.Map != Map.Felucca && gate.TargetMap == Map.Felucca && gate.ShowFeluccaWarning) + AddHtmlLocalized( + 10, + 40, + 400, + 200, + 1062050, + 32512, + false, + true + ); // This Gate goes to Felucca... Continue to enter the gate, Cancel to stay here + else + AddHtmlLocalized( + 10, + 40, + 400, + 200, + 1062049, + 32512, + false, + true + ); // Dost thou wish to step into the moongate? Continue to enter the gate, Cancel to stay here + + AddImageTiled(10, 250, 400, 20, 2624); + AddAlphaRegion(10, 250, 400, 20); + + AddButton(10, 250, 4005, 4007, 1); + AddHtmlLocalized(40, 250, 170, 20, 1011036, 32767); // OKAY + + AddButton(210, 250, 4005, 4007, 0); + AddHtmlLocalized(240, 250, 170, 20, 1011012, 32767); // CANCEL + } + else + { + AddPage(0); + + AddBackground(0, 0, 420, 400, 5054); + AddBackground(10, 10, 400, 380, 3000); + + AddHtml( + 20, + 40, + 380, + 60, + @"Dost thou wish to step into the moongate? Continue to enter the gate, Cancel to stay here" + ); + + AddHtmlLocalized(55, 110, 290, 20, 1011012); // CANCEL + AddButton(20, 110, 4005, 4007, 0); + + AddHtmlLocalized(55, 140, 290, 40, 1011011); // CONTINUE + AddButton(20, 140, 4005, 4007, 1); + } + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (info.ButtonID == 1) + m_Gate.EndConfirmation(m_From); + } } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D Target { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Map TargetMap { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Dispellable { get; set; } - - public virtual bool ShowFeluccaWarning => false; - - public override void OnDoubleClick(Mobile from) - { - if (!from.Player) - return; - - if (from.InRange(GetWorldLocation(), 1)) - CheckGate(from, 1); - else - from.SendLocalizedMessage(500446); // That is too far away. - } - - public override bool OnMoveOver(Mobile m) - { - if (m.Player) - CheckGate(m, 0); - - return true; - } - - public virtual void CheckGate(Mobile m, int range) - { - if (m.Hidden && m.AccessLevel == AccessLevel.Player && Core.ML) - m.RevealingAction(); - - new DelayTimer(m, this, range).Start(); - } - - public virtual void OnGateUsed(Mobile m) - { - } - - public virtual void UseGate(Mobile m) - { - ClientFlags flags = m.NetState?.Flags ?? ClientFlags.None; - - if (Sigil.ExistsOn(m)) - { - m.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. - } - else if (TargetMap == Map.Felucca && m is PlayerMobile mobile && mobile.Young) - { - mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young. - } - else if ((m.Kills >= 5 && TargetMap != Map.Felucca) || - (TargetMap == Map.Tokuno && (flags & ClientFlags.Tokuno) == 0) || - (TargetMap == Map.Malas && (flags & ClientFlags.Malas) == 0) || - (TargetMap == Map.Ilshenar && (flags & ClientFlags.Ilshenar) == 0)) - { - m.SendLocalizedMessage(1019004); // You are not allowed to travel there. - } - else if (m.Spell != null) - { - m.SendLocalizedMessage(1049616); // You are too busy to do that at the moment. - } - else if (TargetMap != null && TargetMap != Map.Internal) - { - BaseCreature.TeleportPets(m, Target, TargetMap); - - m.MoveToWorld(Target, TargetMap); - - if (m.AccessLevel == AccessLevel.Player || !m.Hidden) - m.PlaySound(0x1FE); - - OnGateUsed(m); - } - else - { - m.SendMessage("This moongate does not seem to go anywhere."); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(Target); - writer.Write(TargetMap); - - // Version 1 - writer.Write(Dispellable); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Target = reader.ReadPoint3D(); - TargetMap = reader.ReadMap(); - - if (version >= 1) - Dispellable = reader.ReadBool(); - } - - public virtual bool ValidateUse(Mobile from, bool message) - { - if (from.Deleted || Deleted) - return false; - - if (from.Map != Map || !from.InRange(this, 1)) - { - if (message) - from.SendLocalizedMessage(500446); // That is too far away. - - return false; - } - - return true; - } - - public virtual void BeginConfirmation(Mobile from) - { - if ((IsInTown(from.Location, from.Map) && !IsInTown(Target, TargetMap)) || - (from.Map != Map.Felucca && TargetMap == Map.Felucca && ShowFeluccaWarning)) - { - if (from.AccessLevel == AccessLevel.Player || !from.Hidden) - from.Send(new PlaySound(0x20E, from.Location)); - from.CloseGump(); - from.SendGump(new MoongateConfirmGump(from, this)); - } - else - { - EndConfirmation(from); - } - } - - public virtual void EndConfirmation(Mobile from) - { - if (!ValidateUse(from, true)) - return; - - UseGate(from); - } - - public virtual void DelayCallback(Mobile from, int range) - { - if (!ValidateUse(from, false) || !from.InRange(this, range)) - return; - - if (TargetMap != null) - BeginConfirmation(from); - else - from.SendMessage("This moongate does not seem to go anywhere."); - } - - public static bool IsInTown(Point3D p, Map map) => map != null && Region.Find(p, map).GetRegion()?.IsDisabled() == false; - - private class DelayTimer : Timer - { - private readonly Mobile m_From; - private readonly Moongate m_Gate; - private readonly int m_Range; - - public DelayTimer(Mobile from, Moongate gate, int range) : base(TimeSpan.FromSeconds(1.0)) - { - m_From = from; - m_Gate = gate; - m_Range = range; - } - - protected override void OnTick() - { - m_Gate.DelayCallback(m_From, m_Range); - } - } - } - - public class ConfirmationMoongate : Moongate - { - [Constructible] - public ConfirmationMoongate() : this(Point3D.Zero) - { - } - - [Constructible] - public ConfirmationMoongate(Point3D target, Map targetMap = null) : base(target, targetMap) - { - } - - public ConfirmationMoongate(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int GumpWidth { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int GumpHeight { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int TitleColor { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int MessageColor { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int TitleNumber { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int MessageNumber { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public string MessageString { get; set; } - - public virtual void Warning_Callback(Mobile from, bool okay) - { - if (okay) - EndConfirmation(from); - } - - public override void BeginConfirmation(Mobile from) - { - if (GumpWidth > 0 && GumpHeight > 0 && TitleNumber > 0 && (MessageNumber > 0 || MessageString != null)) - { - from.CloseGump(); - from.SendGump(new WarningGump(TitleNumber, TitleColor, - MessageString ?? (object)MessageNumber, MessageColor, GumpWidth, GumpHeight, - okay => Warning_Callback(from, okay))); - } - else - { - base.BeginConfirmation(from); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.WriteEncodedInt(GumpWidth); - writer.WriteEncodedInt(GumpHeight); - - writer.WriteEncodedInt(TitleColor); - writer.WriteEncodedInt(MessageColor); - - writer.WriteEncodedInt(TitleNumber); - writer.WriteEncodedInt(MessageNumber); - - writer.Write(MessageString); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - GumpWidth = reader.ReadEncodedInt(); - GumpHeight = reader.ReadEncodedInt(); - - TitleColor = reader.ReadEncodedInt(); - MessageColor = reader.ReadEncodedInt(); - - TitleNumber = reader.ReadEncodedInt(); - MessageNumber = reader.ReadEncodedInt(); - - MessageString = reader.ReadString(); - - break; - } - } - } - } - - public class MoongateConfirmGump : Gump - { - private readonly Mobile m_From; - private readonly Moongate m_Gate; - - public MoongateConfirmGump(Mobile from, Moongate gate) : base(Core.AOS ? 110 : 20, Core.AOS ? 100 : 30) - { - m_From = from; - m_Gate = gate; - - if (Core.AOS) - { - Closable = false; - - AddPage(0); - - AddBackground(0, 0, 420, 280, 5054); - - AddImageTiled(10, 10, 400, 20, 2624); - AddAlphaRegion(10, 10, 400, 20); - - AddHtmlLocalized(10, 10, 400, 20, 1062051, 30720); // Gate Warning - - AddImageTiled(10, 40, 400, 200, 2624); - AddAlphaRegion(10, 40, 400, 200); - - if (from.Map != Map.Felucca && gate.TargetMap == Map.Felucca && gate.ShowFeluccaWarning) - AddHtmlLocalized(10, 40, 400, 200, 1062050, 32512, false, - true); // This Gate goes to Felucca... Continue to enter the gate, Cancel to stay here - else - AddHtmlLocalized(10, 40, 400, 200, 1062049, 32512, false, - true); // Dost thou wish to step into the moongate? Continue to enter the gate, Cancel to stay here - - AddImageTiled(10, 250, 400, 20, 2624); - AddAlphaRegion(10, 250, 400, 20); - - AddButton(10, 250, 4005, 4007, 1); - AddHtmlLocalized(40, 250, 170, 20, 1011036, 32767); // OKAY - - AddButton(210, 250, 4005, 4007, 0); - AddHtmlLocalized(240, 250, 170, 20, 1011012, 32767); // CANCEL - } - else - { - AddPage(0); - - AddBackground(0, 0, 420, 400, 5054); - AddBackground(10, 10, 400, 380, 3000); - - AddHtml(20, 40, 380, 60, - @"Dost thou wish to step into the moongate? Continue to enter the gate, Cancel to stay here"); - - AddHtmlLocalized(55, 110, 290, 20, 1011012); // CANCEL - AddButton(20, 110, 4005, 4007, 0); - - AddHtmlLocalized(55, 140, 290, 40, 1011011); // CONTINUE - AddButton(20, 140, 4005, 4007, 1); - } - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (info.ButtonID == 1) - m_Gate.EndConfirmation(m_From); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Misc/PotionKeg.cs b/Projects/UOContent/Items/Skill Items/Magical/Misc/PotionKeg.cs index 7d8fd5fa9..5a728530f 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Misc/PotionKeg.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Misc/PotionKeg.cs @@ -3,327 +3,328 @@ using Server.Network; namespace Server.Items { - public class PotionKeg : Item - { - private int m_Held; - private PotionEffect m_Type; - - [Constructible] - public PotionKeg() : base(0x1940) + public class PotionKeg : Item { - UpdateWeight(); - } + private int m_Held; + private PotionEffect m_Type; - public PotionKeg(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Held - { - get => m_Held; - set - { - if (m_Held != value) + [Constructible] + public PotionKeg() : base(0x1940) { - m_Held = value; - UpdateWeight(); - InvalidateProperties(); + UpdateWeight(); } - } - } - [CommandProperty(AccessLevel.GameMaster)] - public PotionEffect Type - { - get => m_Type; - set - { - m_Type = value; - InvalidateProperties(); - } - } - - public override int LabelNumber - { - get - { - if (m_Held > 0 && (int)m_Type >= (int)PotionEffect.Conflagration) - return 1072658 + (int)m_Type - (int)PotionEffect.Conflagration; - - return m_Held > 0 ? 1041620 + (int)m_Type : 1041641; - } - } - - public virtual void UpdateWeight() - { - int held = Math.Max(0, Math.Min(m_Held, 100)); - - Weight = 20 + held * 80 / 100; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write((int)m_Type); - writer.Write(m_Held); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - case 0: - { - m_Type = (PotionEffect)reader.ReadInt(); - m_Held = reader.ReadInt(); - - break; - } - } - - if (version < 1) - Timer.DelayCall(UpdateWeight); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - int number; - - if (m_Held <= 0) - number = 502246; // The keg is empty. - else if (m_Held < 5) - number = 502248; // The keg is nearly empty. - else if (m_Held < 20) - number = 502249; // The keg is not very full. - else if (m_Held < 30) - number = 502250; // The keg is about one quarter full. - else if (m_Held < 40) - number = 502251; // The keg is about one third full. - else if (m_Held < 47) - number = 502252; // The keg is almost half full. - else if (m_Held < 54) - number = 502254; // The keg is approximately half full. - else if (m_Held < 70) - number = 502253; // The keg is more than half full. - else if (m_Held < 80) - number = 502255; // The keg is about three quarters full. - else if (m_Held < 96) - number = 502256; // The keg is very full. - else if (m_Held < 100) - number = 502257; // The liquid is almost to the top of the keg. - else - number = 502258; // The keg is completely full. - - list.Add(number); - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - int number; - - if (m_Held <= 0) - number = 502246; // The keg is empty. - else if (m_Held < 5) - number = 502248; // The keg is nearly empty. - else if (m_Held < 20) - number = 502249; // The keg is not very full. - else if (m_Held < 30) - number = 502250; // The keg is about one quarter full. - else if (m_Held < 40) - number = 502251; // The keg is about one third full. - else if (m_Held < 47) - number = 502252; // The keg is almost half full. - else if (m_Held < 54) - number = 502254; // The keg is approximately half full. - else if (m_Held < 70) - number = 502253; // The keg is more than half full. - else if (m_Held < 80) - number = 502255; // The keg is about three quarters full. - else if (m_Held < 96) - number = 502256; // The keg is very full. - else if (m_Held < 100) - number = 502257; // The liquid is almost to the top of the keg. - else - number = 502258; // The keg is completely full. - - LabelTo(from, number); - } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(GetWorldLocation(), 2)) - { - if (m_Held > 0) + public PotionKeg(Serial serial) : base(serial) { - Container pack = from.Backpack; + } - if (pack?.ConsumeTotal(typeof(Bottle)) == true) - { - from.SendLocalizedMessage(502242); // You pour some of the keg's contents into an empty bottle... - - BasePotion pot = FillBottle(); - - if (pack.TryDropItem(from, pot, false)) + [CommandProperty(AccessLevel.GameMaster)] + public int Held + { + get => m_Held; + set { - from.SendLocalizedMessage(502243); // ...and place it into your backpack. - from.PlaySound(0x240); + if (m_Held != value) + { + m_Held = value; + UpdateWeight(); + InvalidateProperties(); + } + } + } - if (--Held == 0) - from.SendLocalizedMessage(502245); // The keg is now empty. + [CommandProperty(AccessLevel.GameMaster)] + public PotionEffect Type + { + get => m_Type; + set + { + m_Type = value; + InvalidateProperties(); + } + } + + public override int LabelNumber + { + get + { + if (m_Held > 0 && (int)m_Type >= (int)PotionEffect.Conflagration) + return 1072658 + (int)m_Type - (int)PotionEffect.Conflagration; + + return m_Held > 0 ? 1041620 + (int)m_Type : 1041641; + } + } + + public virtual void UpdateWeight() + { + var held = Math.Max(0, Math.Min(m_Held, 100)); + + Weight = 20 + held * 80 / 100; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write((int)m_Type); + writer.Write(m_Held); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + case 0: + { + m_Type = (PotionEffect)reader.ReadInt(); + m_Held = reader.ReadInt(); + + break; + } + } + + if (version < 1) + Timer.DelayCall(UpdateWeight); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + int number; + + if (m_Held <= 0) + number = 502246; // The keg is empty. + else if (m_Held < 5) + number = 502248; // The keg is nearly empty. + else if (m_Held < 20) + number = 502249; // The keg is not very full. + else if (m_Held < 30) + number = 502250; // The keg is about one quarter full. + else if (m_Held < 40) + number = 502251; // The keg is about one third full. + else if (m_Held < 47) + number = 502252; // The keg is almost half full. + else if (m_Held < 54) + number = 502254; // The keg is approximately half full. + else if (m_Held < 70) + number = 502253; // The keg is more than half full. + else if (m_Held < 80) + number = 502255; // The keg is about three quarters full. + else if (m_Held < 96) + number = 502256; // The keg is very full. + else if (m_Held < 100) + number = 502257; // The liquid is almost to the top of the keg. + else + number = 502258; // The keg is completely full. + + list.Add(number); + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + int number; + + if (m_Held <= 0) + number = 502246; // The keg is empty. + else if (m_Held < 5) + number = 502248; // The keg is nearly empty. + else if (m_Held < 20) + number = 502249; // The keg is not very full. + else if (m_Held < 30) + number = 502250; // The keg is about one quarter full. + else if (m_Held < 40) + number = 502251; // The keg is about one third full. + else if (m_Held < 47) + number = 502252; // The keg is almost half full. + else if (m_Held < 54) + number = 502254; // The keg is approximately half full. + else if (m_Held < 70) + number = 502253; // The keg is more than half full. + else if (m_Held < 80) + number = 502255; // The keg is about three quarters full. + else if (m_Held < 96) + number = 502256; // The keg is very full. + else if (m_Held < 100) + number = 502257; // The liquid is almost to the top of the keg. + else + number = 502258; // The keg is completely full. + + LabelTo(from, number); + } + + public override void OnDoubleClick(Mobile from) + { + if (from.InRange(GetWorldLocation(), 2)) + { + if (m_Held > 0) + { + var pack = from.Backpack; + + if (pack?.ConsumeTotal(typeof(Bottle)) == true) + { + from.SendLocalizedMessage(502242); // You pour some of the keg's contents into an empty bottle... + + var pot = FillBottle(); + + if (pack.TryDropItem(from, pot, false)) + { + from.SendLocalizedMessage(502243); // ...and place it into your backpack. + from.PlaySound(0x240); + + if (--Held == 0) + from.SendLocalizedMessage(502245); // The keg is now empty. + } + else + { + from.SendLocalizedMessage(502244); // ...but there is no room for the bottle in your backpack. + pot.Delete(); + } + } + } + else + { + from.SendLocalizedMessage(502246); // The keg is empty. + } } else { - from.SendLocalizedMessage(502244); // ...but there is no room for the bottle in your backpack. - pot.Delete(); + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. } - } } - else + + public override bool OnDragDrop(Mobile from, Item item) { - from.SendLocalizedMessage(502246); // The keg is empty. + if (!(item is BasePotion pot)) + { + from.SendLocalizedMessage(502232); // The keg is not designed to hold that type of object. + return false; + } + + var toHold = Math.Min(100 - m_Held, pot.Amount); + + if (toHold <= 0) + { + from.SendLocalizedMessage(502233); // The keg will not hold any more! + return false; + } + + if (m_Held == 0) + { + if ((int)pot.PotionEffect >= (int)PotionEffect.Invisibility) + { + from.SendLocalizedMessage(502232); // The keg is not designed to hold that type of object. + return false; + } + + if (GiveBottle(from, toHold)) + { + m_Type = pot.PotionEffect; + Held = toHold; + + from.PlaySound(0x240); + + from.SendLocalizedMessage(502237); // You place the empty bottle in your backpack. + + pot.Consume(toHold); + + if (!pot.Deleted) + pot.Bounce(from); + + return true; + } + + from.SendLocalizedMessage(502238); // You don't have room for the empty bottle in your backpack. + return false; + } + + if (pot.PotionEffect != m_Type) + { + from.SendLocalizedMessage( + 502236 + ); // You decide that it would be a bad idea to mix different types of potions. + return false; + } + + if (GiveBottle(from, toHold)) + { + Held += toHold; + + from.PlaySound(0x240); + + from.SendLocalizedMessage(502237); // You place the empty bottle in your backpack. + + pot.Consume(toHold); + + if (!pot.Deleted) + pot.Bounce(from); + + return true; + } + + from.SendLocalizedMessage(502238); // You don't have room for the empty bottle in your backpack. + return false; } - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - } - public override bool OnDragDrop(Mobile from, Item item) - { - if (!(item is BasePotion pot)) - { - from.SendLocalizedMessage(502232); // The keg is not designed to hold that type of object. - return false; - } - - int toHold = Math.Min(100 - m_Held, pot.Amount); - - if (toHold <= 0) - { - from.SendLocalizedMessage(502233); // The keg will not hold any more! - return false; - } - - if (m_Held == 0) - { - if ((int)pot.PotionEffect >= (int)PotionEffect.Invisibility) + public bool GiveBottle(Mobile m, int amount) { - from.SendLocalizedMessage(502232); // The keg is not designed to hold that type of object. - return false; + var pack = m.Backpack; + + var bottle = new Bottle(amount); + + if (pack?.TryDropItem(m, bottle, false) != true) + { + bottle.Delete(); + return false; + } + + return true; } - if (GiveBottle(from, toHold)) + public BasePotion FillBottle() { - m_Type = pot.PotionEffect; - Held = toHold; - - from.PlaySound(0x240); - - from.SendLocalizedMessage(502237); // You place the empty bottle in your backpack. - - pot.Consume(toHold); - - if (!pot.Deleted) - pot.Bounce(from); - - return true; + return m_Type switch + { + PotionEffect.Nightsight => new NightSightPotion(), + PotionEffect.CureLesser => new LesserCurePotion(), + PotionEffect.Cure => new CurePotion(), + PotionEffect.CureGreater => new GreaterCurePotion(), + PotionEffect.Agility => new AgilityPotion(), + PotionEffect.AgilityGreater => new GreaterAgilityPotion(), + PotionEffect.Strength => new StrengthPotion(), + PotionEffect.StrengthGreater => new GreaterStrengthPotion(), + PotionEffect.PoisonLesser => new LesserPoisonPotion(), + PotionEffect.Poison => new PoisonPotion(), + PotionEffect.PoisonGreater => new GreaterPoisonPotion(), + PotionEffect.PoisonDeadly => new DeadlyPoisonPotion(), + PotionEffect.Refresh => new RefreshPotion(), + PotionEffect.RefreshTotal => new TotalRefreshPotion(), + PotionEffect.HealLesser => new LesserHealPotion(), + PotionEffect.Heal => new HealPotion(), + PotionEffect.HealGreater => new GreaterHealPotion(), + PotionEffect.ExplosionLesser => new LesserExplosionPotion(), + PotionEffect.Explosion => new ExplosionPotion(), + PotionEffect.ExplosionGreater => new GreaterExplosionPotion(), + PotionEffect.Conflagration => new ConflagrationPotion(), + PotionEffect.ConflagrationGreater => new GreaterConflagrationPotion(), + PotionEffect.ConfusionBlast => new ConfusionBlastPotion(), + PotionEffect.ConfusionBlastGreater => new GreaterConfusionBlastPotion(), + _ => new NightSightPotion() + }; } - from.SendLocalizedMessage(502238); // You don't have room for the empty bottle in your backpack. - return false; - } - - if (pot.PotionEffect != m_Type) - { - from.SendLocalizedMessage( - 502236); // You decide that it would be a bad idea to mix different types of potions. - return false; - } - - if (GiveBottle(from, toHold)) - { - Held += toHold; - - from.PlaySound(0x240); - - from.SendLocalizedMessage(502237); // You place the empty bottle in your backpack. - - pot.Consume(toHold); - - if (!pot.Deleted) - pot.Bounce(from); - - return true; - } - - from.SendLocalizedMessage(502238); // You don't have room for the empty bottle in your backpack. - return false; + public static void Initialize() + { + TileData.ItemTable[0x1940].Height = 4; + } } - - public bool GiveBottle(Mobile m, int amount) - { - Container pack = m.Backpack; - - Bottle bottle = new Bottle(amount); - - if (pack?.TryDropItem(m, bottle, false) != true) - { - bottle.Delete(); - return false; - } - - return true; - } - - public BasePotion FillBottle() - { - return m_Type switch - { - PotionEffect.Nightsight => (BasePotion)new NightSightPotion(), - PotionEffect.CureLesser => new LesserCurePotion(), - PotionEffect.Cure => new CurePotion(), - PotionEffect.CureGreater => new GreaterCurePotion(), - PotionEffect.Agility => new AgilityPotion(), - PotionEffect.AgilityGreater => new GreaterAgilityPotion(), - PotionEffect.Strength => new StrengthPotion(), - PotionEffect.StrengthGreater => new GreaterStrengthPotion(), - PotionEffect.PoisonLesser => new LesserPoisonPotion(), - PotionEffect.Poison => new PoisonPotion(), - PotionEffect.PoisonGreater => new GreaterPoisonPotion(), - PotionEffect.PoisonDeadly => new DeadlyPoisonPotion(), - PotionEffect.Refresh => new RefreshPotion(), - PotionEffect.RefreshTotal => new TotalRefreshPotion(), - PotionEffect.HealLesser => new LesserHealPotion(), - PotionEffect.Heal => new HealPotion(), - PotionEffect.HealGreater => new GreaterHealPotion(), - PotionEffect.ExplosionLesser => new LesserExplosionPotion(), - PotionEffect.Explosion => new ExplosionPotion(), - PotionEffect.ExplosionGreater => new GreaterExplosionPotion(), - PotionEffect.Conflagration => new ConflagrationPotion(), - PotionEffect.ConflagrationGreater => new GreaterConflagrationPotion(), - PotionEffect.ConfusionBlast => new ConfusionBlastPotion(), - PotionEffect.ConfusionBlastGreater => new GreaterConfusionBlastPotion(), - _ => new NightSightPotion() - }; - } - - public static void Initialize() - { - TileData.ItemTable[0x1940].Height = 4; - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Misc/RecallRune.cs b/Projects/UOContent/Items/Skill Items/Magical/Misc/RecallRune.cs index f1ed83c64..ba4bc469a 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Misc/RecallRune.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Misc/RecallRune.cs @@ -4,293 +4,309 @@ using Server.Regions; namespace Server.Items { - [Flippable(0x1f14, 0x1f15, 0x1f16, 0x1f17)] - public class RecallRune : Item - { - private const string RuneFormat = "a recall rune for {0}"; - private string m_Description; - private BaseHouse m_House; - private bool m_Marked; - private Map m_TargetMap; - - [Constructible] - public RecallRune() : base(0x1F14) + [Flippable(0x1f14, 0x1f15, 0x1f16, 0x1f17)] + public class RecallRune : Item { - Weight = 1.0; - CalculateHue(); - } + private const string RuneFormat = "a recall rune for {0}"; + private string m_Description; + private BaseHouse m_House; + private bool m_Marked; + private Map m_TargetMap; - public RecallRune(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)] - public BaseHouse House - { - get - { - if (m_House?.Deleted == true) - House = null; - - return m_House; - } - set - { - m_House = value; - CalculateHue(); - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)] - public string Description - { - get => m_Description; - set - { - m_Description = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)] - public bool Marked - { - get => m_Marked; - set - { - if (m_Marked != value) + [Constructible] + public RecallRune() : base(0x1F14) { - m_Marked = value; - CalculateHue(); - InvalidateProperties(); + Weight = 1.0; + CalculateHue(); } - } - } - [CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)] - public Point3D Target { get; set; } - - [CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)] - public Map TargetMap - { - get => m_TargetMap; - set - { - if (m_TargetMap != value) + public RecallRune(Serial serial) : base(serial) { - m_TargetMap = value; - CalculateHue(); - InvalidateProperties(); } - } - } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + [CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)] + public BaseHouse House + { + get + { + if (m_House?.Deleted == true) + House = null; - if (m_House?.Deleted == false) - { - writer.Write(1); // version + return m_House; + } + set + { + m_House = value; + CalculateHue(); + InvalidateProperties(); + } + } - writer.Write(m_House); - } - else - { - writer.Write(0); // version - } + [CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)] + public string Description + { + get => m_Description; + set + { + m_Description = value; + InvalidateProperties(); + } + } - writer.Write(m_Description); - writer.Write(m_Marked); - writer.Write(Target); - writer.Write(m_TargetMap); - } + [CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)] + public bool Marked + { + get => m_Marked; + set + { + if (m_Marked != value) + { + m_Marked = value; + CalculateHue(); + InvalidateProperties(); + } + } + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + [CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)] + public Point3D Target { get; set; } - int version = reader.ReadInt(); + [CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)] + public Map TargetMap + { + get => m_TargetMap; + set + { + if (m_TargetMap != value) + { + m_TargetMap = value; + CalculateHue(); + InvalidateProperties(); + } + } + } - switch (version) - { - case 1: - { - m_House = reader.ReadItem() as BaseHouse; - goto case 0; - } - case 0: - { - m_Description = reader.ReadString(); - m_Marked = reader.ReadBool(); - Target = reader.ReadPoint3D(); - m_TargetMap = reader.ReadMap(); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + if (m_House?.Deleted == false) + { + writer.Write(1); // version + + writer.Write(m_House); + } + else + { + writer.Write(0); // version + } + + writer.Write(m_Description); + writer.Write(m_Marked); + writer.Write(Target); + writer.Write(m_TargetMap); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_House = reader.ReadItem() as BaseHouse; + goto case 0; + } + case 0: + { + m_Description = reader.ReadString(); + m_Marked = reader.ReadBool(); + Target = reader.ReadPoint3D(); + m_TargetMap = reader.ReadMap(); + + CalculateHue(); + + break; + } + } + } + + private void CalculateHue() + { + if (!m_Marked) + Hue = 0; + else if (m_TargetMap == Map.Trammel) + Hue = House != null ? 0x47F : 50; + else if (m_TargetMap == Map.Felucca) + Hue = House != null ? 0x66D : 0; + else if (m_TargetMap == Map.Ilshenar) + Hue = House != null ? 0x55F : 1102; + else if (m_TargetMap == Map.Malas) + Hue = House != null ? 0x55F : 1102; + else if (m_TargetMap == Map.Tokuno) + Hue = House != null ? 0x47F : 1154; + } + + public void Mark(Mobile m) + { + m_Marked = true; + + var setDesc = false; + if (Core.AOS) + { + m_House = BaseHouse.FindHouseAt(m); + + if (m_House == null) + { + Target = m.Location; + m_TargetMap = m.Map; + } + else + { + var sign = m_House.Sign; + + m_Description = sign?.Name?.Trim().IsNullOrDefault("an unnamed house"); + + setDesc = true; + + var x = m_House.BanLocation.X; + var y = m_House.BanLocation.Y + 2; + var z = m_House.BanLocation.Z; + + var map = m_House.Map; + + if (map?.CanFit(x, y, z, 16, false, false) == false) + z = map.GetAverageZ(x, y); + + Target = new Point3D(x, y, z); + m_TargetMap = map; + } + } + else + { + m_House = null; + Target = m.Location; + m_TargetMap = m.Map; + } + + if (!setDesc) + m_Description = BaseRegion.GetRuneNameFor(Region.Find(Target, m_TargetMap)); CalculateHue(); - - break; - } - } - } - - private void CalculateHue() - { - if (!m_Marked) - Hue = 0; - else if (m_TargetMap == Map.Trammel) - Hue = House != null ? 0x47F : 50; - else if (m_TargetMap == Map.Felucca) - Hue = House != null ? 0x66D : 0; - else if (m_TargetMap == Map.Ilshenar) - Hue = House != null ? 0x55F : 1102; - else if (m_TargetMap == Map.Malas) - Hue = House != null ? 0x55F : 1102; - else if (m_TargetMap == Map.Tokuno) - Hue = House != null ? 0x47F : 1154; - } - - public void Mark(Mobile m) - { - m_Marked = true; - - bool setDesc = false; - if (Core.AOS) - { - m_House = BaseHouse.FindHouseAt(m); - - if (m_House == null) - { - Target = m.Location; - m_TargetMap = m.Map; + InvalidateProperties(); } - else + + public override void GetProperties(ObjectPropertyList list) { - HouseSign sign = m_House.Sign; + base.GetProperties(list); - m_Description = sign?.Name?.Trim().IsNullOrDefault("an unnamed house"); + if (m_Marked) + { + string desc; - setDesc = true; + if ((desc = m_Description) == null || (desc = desc.Trim()).Length == 0) + desc = "an unknown location"; - int x = m_House.BanLocation.X; - int y = m_House.BanLocation.Y + 2; - int z = m_House.BanLocation.Z; - - Map map = m_House.Map; - - if (map?.CanFit(x, y, z, 16, false, false) == false) - z = map.GetAverageZ(x, y); - - Target = new Point3D(x, y, z); - m_TargetMap = map; + if (m_TargetMap == Map.Tokuno) + list.Add(House != null ? 1063260 : 1063259, RuneFormat, desc); // ~1_val~ (Tokuno Islands)[(House)] + else if (m_TargetMap == Map.Malas) + list.Add(House != null ? 1062454 : 1060804, RuneFormat, desc); // ~1_val~ (Malas)[(House)] + else if (m_TargetMap == Map.Felucca) + list.Add(House != null ? 1062452 : 1060805, RuneFormat, desc); // ~1_val~ (Felucca)[(House)] + else if (m_TargetMap == Map.Trammel) + list.Add(House != null ? 1062453 : 1060806, RuneFormat, desc); // ~1_val~ (Trammel)[(House)] + else + list.Add(House != null ? "{0} ({1})(House)" : "{0} ({1})", string.Format(RuneFormat, desc), m_TargetMap); + } } - } - else - { - m_House = null; - Target = m.Location; - m_TargetMap = m.Map; - } - if (!setDesc) - m_Description = BaseRegion.GetRuneNameFor(Region.Find(Target, m_TargetMap)); - - CalculateHue(); - InvalidateProperties(); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_Marked) - { - string desc; - - if ((desc = m_Description) == null || (desc = desc.Trim()).Length == 0) - desc = "an unknown location"; - - if (m_TargetMap == Map.Tokuno) - list.Add(House != null ? 1063260 : 1063259, RuneFormat, desc); // ~1_val~ (Tokuno Islands)[(House)] - else if (m_TargetMap == Map.Malas) - list.Add(House != null ? 1062454 : 1060804, RuneFormat, desc); // ~1_val~ (Malas)[(House)] - else if (m_TargetMap == Map.Felucca) - list.Add(House != null ? 1062452 : 1060805, RuneFormat, desc); // ~1_val~ (Felucca)[(House)] - else if (m_TargetMap == Map.Trammel) - list.Add(House != null ? 1062453 : 1060806, RuneFormat, desc); // ~1_val~ (Trammel)[(House)] - else - list.Add(House != null ? "{0} ({1})(House)" : "{0} ({1})", string.Format(RuneFormat, desc), m_TargetMap); - } - } - - public override void OnSingleClick(Mobile from) - { - if (m_Marked) - { - string desc = m_Description?.Trim().IsNullOrDefault("an unknown location"); - - if (m_TargetMap == Map.Tokuno) - LabelTo(from, House != null ? 1063260 : 1063259, - string.Format(RuneFormat, desc)); // ~1_val~ (Tokuno Islands)[(House)] - else if (m_TargetMap == Map.Malas) - LabelTo(from, House != null ? 1062454 : 1060804, - string.Format(RuneFormat, desc)); // ~1_val~ (Malas)[(House)] - else if (m_TargetMap == Map.Felucca) - LabelTo(from, House != null ? 1062452 : 1060805, - string.Format(RuneFormat, desc)); // ~1_val~ (Felucca)[(House)] - else if (m_TargetMap == Map.Trammel) - LabelTo(from, House != null ? 1062453 : 1060806, - string.Format(RuneFormat, desc)); // ~1_val~ (Trammel)[(House)] - else - LabelTo(from, House != null ? "{0} ({1})(House)" : "{0} ({1})", string.Format(RuneFormat, desc), - m_TargetMap); - } - else - { - LabelTo(from, "an unmarked recall rune"); - } - } - - public override void OnDoubleClick(Mobile from) - { - int number; - - if (!IsChildOf(from.Backpack)) - { - number = 1042001; // That must be in your pack for you to use it. - } - else if (House != null) - { - number = 1062399; // You cannot edit the description for this rune. - } - else if (m_Marked) - { - number = 501804; // Please enter a description for this marked object. - - from.Prompt = new RenamePrompt(this); - } - else - { - number = 501805; // That rune is not yet marked. - } - - from.SendLocalizedMessage(number); - } - - private class RenamePrompt : Prompt - { - private readonly RecallRune m_Rune; - - public RenamePrompt(RecallRune rune) => m_Rune = rune; - - public override void OnResponse(Mobile from, string text) - { - if (m_Rune.House == null && m_Rune.Marked) + public override void OnSingleClick(Mobile from) { - m_Rune.Description = text; - from.SendLocalizedMessage(1010474); // The etching on the rune has been changed. + if (m_Marked) + { + var desc = m_Description?.Trim().IsNullOrDefault("an unknown location"); + + if (m_TargetMap == Map.Tokuno) + LabelTo( + from, + House != null ? 1063260 : 1063259, + string.Format(RuneFormat, desc) + ); // ~1_val~ (Tokuno Islands)[(House)] + else if (m_TargetMap == Map.Malas) + LabelTo( + from, + House != null ? 1062454 : 1060804, + string.Format(RuneFormat, desc) + ); // ~1_val~ (Malas)[(House)] + else if (m_TargetMap == Map.Felucca) + LabelTo( + from, + House != null ? 1062452 : 1060805, + string.Format(RuneFormat, desc) + ); // ~1_val~ (Felucca)[(House)] + else if (m_TargetMap == Map.Trammel) + LabelTo( + from, + House != null ? 1062453 : 1060806, + string.Format(RuneFormat, desc) + ); // ~1_val~ (Trammel)[(House)] + else + LabelTo( + from, + House != null ? "{0} ({1})(House)" : "{0} ({1})", + string.Format(RuneFormat, desc), + m_TargetMap + ); + } + else + { + LabelTo(from, "an unmarked recall rune"); + } + } + + public override void OnDoubleClick(Mobile from) + { + int number; + + if (!IsChildOf(from.Backpack)) + { + number = 1042001; // That must be in your pack for you to use it. + } + else if (House != null) + { + number = 1062399; // You cannot edit the description for this rune. + } + else if (m_Marked) + { + number = 501804; // Please enter a description for this marked object. + + from.Prompt = new RenamePrompt(this); + } + else + { + number = 501805; // That rune is not yet marked. + } + + from.SendLocalizedMessage(number); + } + + private class RenamePrompt : Prompt + { + private readonly RecallRune m_Rune; + + public RenamePrompt(RecallRune rune) => m_Rune = rune; + + public override void OnResponse(Mobile from, string text) + { + if (m_Rune.House == null && m_Rune.Marked) + { + m_Rune.Description = text; + from.SendLocalizedMessage(1010474); // The etching on the rune has been changed. + } + } } - } } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/MysticSpellbook.cs b/Projects/UOContent/Items/Skill Items/Magical/MysticSpellbook.cs index 8c2fc9c1e..4f979fc5c 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/MysticSpellbook.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/MysticSpellbook.cs @@ -1,35 +1,35 @@ namespace Server.Items { - public class MysticSpellbook : Spellbook - { - [Constructible] - public MysticSpellbook(ulong content = 0) - : base(content, 0x2D9D) => - Layer = Layer.OneHanded; - - public MysticSpellbook(Serial serial) - : base(serial) + public class MysticSpellbook : Spellbook { + [Constructible] + public MysticSpellbook(ulong content = 0) + : base(content, 0x2D9D) => + Layer = Layer.OneHanded; + + public MysticSpellbook(Serial serial) + : base(serial) + { + } + + public override SpellbookType SpellbookType => SpellbookType.Mystic; + + public override int BookOffset => 677; + public override int BookCount => 16; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + /*int version = */ + reader.ReadInt(); + } } - - public override SpellbookType SpellbookType => SpellbookType.Mystic; - - public override int BookOffset => 677; - public override int BookCount => 16; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - /*int version = */ - reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/NecromancerSpellbook.cs b/Projects/UOContent/Items/Skill Items/Magical/NecromancerSpellbook.cs index 0ea0e5fc1..0db4ebc43 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/NecromancerSpellbook.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/NecromancerSpellbook.cs @@ -1,33 +1,34 @@ namespace Server.Items { - public class NecromancerSpellbook : Spellbook - { - [Constructible] - public NecromancerSpellbook(ulong content = 0) : base(content, 0x2253) => Layer = Core.ML ? Layer.OneHanded : Layer.Invalid; - - public NecromancerSpellbook(Serial serial) : base(serial) + public class NecromancerSpellbook : Spellbook { + [Constructible] + public NecromancerSpellbook(ulong content = 0) : base(content, 0x2253) => + Layer = Core.ML ? Layer.OneHanded : Layer.Invalid; + + public NecromancerSpellbook(Serial serial) : base(serial) + { + } + + public override SpellbookType SpellbookType => SpellbookType.Necromancer; + public override int BookOffset => 100; + public override int BookCount => Core.SE ? 17 : 16; + + 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 && Core.ML) + Layer = Layer.OneHanded; + } } - - public override SpellbookType SpellbookType => SpellbookType.Necromancer; - public override int BookOffset => 100; - public override int BookCount => Core.SE ? 17 : 16; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version == 0 && Core.ML) - Layer = Layer.OneHanded; - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Agility Potions/AgilityPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Agility Potions/AgilityPotion.cs index f045b4b63..ba30bb8ee 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Agility Potions/AgilityPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Agility Potions/AgilityPotion.cs @@ -2,32 +2,32 @@ using System; namespace Server.Items { - public class AgilityPotion : BaseAgilityPotion - { - [Constructible] - public AgilityPotion() : base(PotionEffect.Agility) + public class AgilityPotion : BaseAgilityPotion { + [Constructible] + public AgilityPotion() : base(PotionEffect.Agility) + { + } + + public AgilityPotion(Serial serial) : base(serial) + { + } + + public override int DexOffset => 10; + public override TimeSpan Duration => TimeSpan.FromMinutes(2.0); + + 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 AgilityPotion(Serial serial) : base(serial) - { - } - - public override int DexOffset => 10; - public override TimeSpan Duration => TimeSpan.FromMinutes(2.0); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Agility Potions/BaseAgilityPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Agility Potions/BaseAgilityPotion.cs index c2cbafb3b..4b31fe2d5 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Agility Potions/BaseAgilityPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Agility Potions/BaseAgilityPotion.cs @@ -4,56 +4,56 @@ using Server.Spells; namespace Server.Items { - public abstract class BaseAgilityPotion : BasePotion - { - public BaseAgilityPotion(PotionEffect effect) : base(0xF08, effect) + public abstract class BaseAgilityPotion : BasePotion { + public BaseAgilityPotion(PotionEffect effect) : base(0xF08, effect) + { + } + + public BaseAgilityPotion(Serial serial) : base(serial) + { + } + + public abstract int DexOffset { get; } + public abstract TimeSpan Duration { get; } + + 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 bool DoAgility(Mobile from) + { + // TODO: Verify scaled; is it offset, duration, or both? + if (SpellHelper.AddStatOffset(from, StatType.Dex, Scale(from, DexOffset), Duration)) + { + from.FixedEffect(0x375A, 10, 15); + from.PlaySound(0x1E7); + return true; + } + + from.SendLocalizedMessage(502173); // You are already under a similar effect. + return false; + } + + public override void Drink(Mobile from) + { + if (DoAgility(from)) + { + PlayDrinkEffect(from); + + if (!DuelContext.IsFreeConsume(from)) + Consume(); + } + } } - - public BaseAgilityPotion(Serial serial) : base(serial) - { - } - - public abstract int DexOffset { get; } - public abstract TimeSpan Duration { get; } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public bool DoAgility(Mobile from) - { - // TODO: Verify scaled; is it offset, duration, or both? - if (SpellHelper.AddStatOffset(from, StatType.Dex, Scale(from, DexOffset), Duration)) - { - from.FixedEffect(0x375A, 10, 15); - from.PlaySound(0x1E7); - return true; - } - - from.SendLocalizedMessage(502173); // You are already under a similar effect. - return false; - } - - public override void Drink(Mobile from) - { - if (DoAgility(from)) - { - PlayDrinkEffect(from); - - if (!DuelContext.IsFreeConsume(from)) - Consume(); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Agility Potions/GreaterAgilityPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Agility Potions/GreaterAgilityPotion.cs index 9c0e2f90e..ea47617dc 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Agility Potions/GreaterAgilityPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Agility Potions/GreaterAgilityPotion.cs @@ -2,32 +2,32 @@ using System; namespace Server.Items { - public class GreaterAgilityPotion : BaseAgilityPotion - { - [Constructible] - public GreaterAgilityPotion() : base(PotionEffect.AgilityGreater) + public class GreaterAgilityPotion : BaseAgilityPotion { + [Constructible] + public GreaterAgilityPotion() : base(PotionEffect.AgilityGreater) + { + } + + public GreaterAgilityPotion(Serial serial) : base(serial) + { + } + + public override int DexOffset => 20; + public override TimeSpan Duration => TimeSpan.FromMinutes(2.0); + + 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 GreaterAgilityPotion(Serial serial) : base(serial) - { - } - - public override int DexOffset => 20; - public override TimeSpan Duration => TimeSpan.FromMinutes(2.0); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/BasePotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/BasePotion.cs index 6e38ab942..09f6439f5 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/BasePotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/BasePotion.cs @@ -1,254 +1,255 @@ using System; -using System.Collections.Generic; using Server.Engines.ConPVP; using Server.Engines.Craft; using Server.Utilities; namespace Server.Items { - public enum PotionEffect - { - Nightsight, - CureLesser, - Cure, - CureGreater, - Agility, - AgilityGreater, - Strength, - StrengthGreater, - PoisonLesser, - Poison, - PoisonGreater, - PoisonDeadly, - Refresh, - RefreshTotal, - HealLesser, - Heal, - HealGreater, - ExplosionLesser, - Explosion, - ExplosionGreater, - Conflagration, - ConflagrationGreater, - MaskOfDeath, // Mask of Death is not available in OSI but does exist in cliloc files - MaskOfDeathGreater, // included in enumeration for compatibility if later enabled by OSI - ConfusionBlast, - ConfusionBlastGreater, - Invisibility, - Parasitic, - Darkglow - } - - public abstract class BasePotion : Item, ICraftable, ICommodity - { - private PotionEffect m_PotionEffect; - - public BasePotion(int itemID, PotionEffect effect) : base(itemID) + public enum PotionEffect { - m_PotionEffect = effect; - - Stackable = Core.ML; - Weight = 1.0; + Nightsight, + CureLesser, + Cure, + CureGreater, + Agility, + AgilityGreater, + Strength, + StrengthGreater, + PoisonLesser, + Poison, + PoisonGreater, + PoisonDeadly, + Refresh, + RefreshTotal, + HealLesser, + Heal, + HealGreater, + ExplosionLesser, + Explosion, + ExplosionGreater, + Conflagration, + ConflagrationGreater, + MaskOfDeath, // Mask of Death is not available in OSI but does exist in cliloc files + MaskOfDeathGreater, // included in enumeration for compatibility if later enabled by OSI + ConfusionBlast, + ConfusionBlastGreater, + Invisibility, + Parasitic, + Darkglow } - public BasePotion(Serial serial) : base(serial) + public abstract class BasePotion : Item, ICraftable, ICommodity { - } + private PotionEffect m_PotionEffect; - public PotionEffect PotionEffect - { - get => m_PotionEffect; - set - { - m_PotionEffect = value; - InvalidateProperties(); - } - } - - public override int LabelNumber => 1041314 + (int)m_PotionEffect; - - public virtual bool RequireFreeHand => true; - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => Core.ML; - - public int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, - CraftItem craftItem, int resHue) - { - if (craftSystem is DefAlchemy) - { - Container pack = from.Backpack; - - if (pack != null) + public BasePotion(int itemID, PotionEffect effect) : base(itemID) { - if ((int)PotionEffect >= (int)PotionEffect.Invisibility) + m_PotionEffect = effect; + + Stackable = Core.ML; + Weight = 1.0; + } + + public BasePotion(Serial serial) : base(serial) + { + } + + public PotionEffect PotionEffect + { + get => m_PotionEffect; + set + { + m_PotionEffect = value; + InvalidateProperties(); + } + } + + public override int LabelNumber => 1041314 + (int)m_PotionEffect; + + public virtual bool RequireFreeHand => true; + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => Core.ML; + + public int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, + CraftItem craftItem, int resHue + ) + { + if (craftSystem is DefAlchemy) + { + var pack = from.Backpack; + + if (pack != null) + { + if ((int)PotionEffect >= (int)PotionEffect.Invisibility) + return 1; + + var kegs = pack.FindItemsByType(); + + for (var i = 0; i < kegs.Count; ++i) + { + var keg = kegs[i]; + + // Should never happen + // if (keg == null) + // continue; + + if (keg.Held <= 0 || keg.Held >= 100) + continue; + + if (keg.Type != PotionEffect) + continue; + + ++keg.Held; + + Consume(); + from.AddToBackpack(new Bottle()); + + return -1; // signal placed in keg + } + } + } + return 1; - - List kegs = pack.FindItemsByType(); - - for (int i = 0; i < kegs.Count; ++i) - { - PotionKeg keg = kegs[i]; - - // Should never happen - // if (keg == null) - // continue; - - if (keg.Held <= 0 || keg.Held >= 100) - continue; - - if (keg.Type != PotionEffect) - continue; - - ++keg.Held; - - Consume(); - from.AddToBackpack(new Bottle()); - - return -1; // signal placed in keg - } } - } - return 1; - } - - public static bool HasFreeHand(Mobile m) - { - Item handOne = m.FindItemOnLayer(Layer.OneHanded); - Item handTwo = m.FindItemOnLayer(Layer.TwoHanded); - - if (handTwo is BaseWeapon) - handOne = handTwo; - - if (handTwo is BaseRanged ranged && ranged.Balanced) - return true; - - return handOne == null || handTwo == null; - } - - public override void OnDoubleClick(Mobile from) - { - if (!Movable) - return; - - if (from.InRange(GetWorldLocation(), 1)) - { - if (!RequireFreeHand || HasFreeHand(from)) + public static bool HasFreeHand(Mobile m) { - if (this is BaseExplosionPotion && Amount > 1) - { - BasePotion pot = (BasePotion)ActivatorUtil.CreateInstance(GetType()); + var handOne = m.FindItemOnLayer(Layer.OneHanded); + var handTwo = m.FindItemOnLayer(Layer.TwoHanded); - Amount--; + if (handTwo is BaseWeapon) + handOne = handTwo; - if (from.Backpack?.Deleted != false) - from.Backpack.DropItem(pot); + if (handTwo is BaseRanged ranged && ranged.Balanced) + return true; + + return handOne == null || handTwo == null; + } + + public override void OnDoubleClick(Mobile from) + { + if (!Movable) + return; + + if (from.InRange(GetWorldLocation(), 1)) + { + if (!RequireFreeHand || HasFreeHand(from)) + { + if (this is BaseExplosionPotion && Amount > 1) + { + var pot = (BasePotion)ActivatorUtil.CreateInstance(GetType()); + + Amount--; + + if (from.Backpack?.Deleted != false) + from.Backpack.DropItem(pot); + else + pot.MoveToWorld(from.Location, from.Map); + pot.Drink(from); + } + else + { + Drink(from); + } + } + else + { + from.SendLocalizedMessage(502172); // You must have a free hand to drink a potion. + } + } else - pot.MoveToWorld(from.Location, from.Map); - pot.Drink(from); - } - else - { - Drink(from); - } + { + from.SendLocalizedMessage(502138); // That is too far away for you to use + } } - else + + public override void Serialize(IGenericWriter writer) { - from.SendLocalizedMessage(502172); // You must have a free hand to drink a potion. + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write((int)m_PotionEffect); } - } - else - { - from.SendLocalizedMessage(502138); // That is too far away for you to use - } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + case 0: + { + m_PotionEffect = (PotionEffect)reader.ReadInt(); + break; + } + } + + if (version == 0) + Stackable = Core.ML; + } + + public abstract void Drink(Mobile from); + + public static void PlayDrinkEffect(Mobile m) + { + m.RevealingAction(); + + m.PlaySound(0x2D6); + + if (!DuelContext.IsFreeConsume(m)) + m.AddToBackpack(new Bottle()); + + if (m.Body.IsHuman && !m.Mounted) + m.Animate(34, 5, 1, true, false, 0); + } + + public static int EnhancePotions(Mobile m) + { + var EP = AosAttributes.GetValue(m, AosAttribute.EnhancePotions); + var skillBonus = m.Skills.Alchemy.Fixed / 330 * 10; + + if (Core.ML && EP > 50 && m.AccessLevel <= AccessLevel.Player) + EP = 50; + + return EP + skillBonus; + } + + public static TimeSpan Scale(Mobile m, TimeSpan v) + { + if (!Core.AOS) + return v; + + var scalar = 1.0 + 0.01 * EnhancePotions(m); + + return TimeSpan.FromSeconds(v.TotalSeconds * scalar); + } + + public static double Scale(Mobile m, double v) + { + if (!Core.AOS) + return v; + + var scalar = 1.0 + 0.01 * EnhancePotions(m); + + return v * scalar; + } + + public static int Scale(Mobile m, int v) + { + if (!Core.AOS) + return v; + + return AOS.Scale(v, 100 + EnhancePotions(m)); + } + + public override bool StackWith(Mobile from, Item dropped, bool playSound) => + dropped is BasePotion potion && potion.m_PotionEffect == m_PotionEffect && + base.StackWith(from, potion, playSound); } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write((int)m_PotionEffect); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - case 0: - { - m_PotionEffect = (PotionEffect)reader.ReadInt(); - break; - } - } - - if (version == 0) - Stackable = Core.ML; - } - - public abstract void Drink(Mobile from); - - public static void PlayDrinkEffect(Mobile m) - { - m.RevealingAction(); - - m.PlaySound(0x2D6); - - if (!DuelContext.IsFreeConsume(m)) - m.AddToBackpack(new Bottle()); - - if (m.Body.IsHuman && !m.Mounted) - m.Animate(34, 5, 1, true, false, 0); - } - - public static int EnhancePotions(Mobile m) - { - int EP = AosAttributes.GetValue(m, AosAttribute.EnhancePotions); - int skillBonus = m.Skills.Alchemy.Fixed / 330 * 10; - - if (Core.ML && EP > 50 && m.AccessLevel <= AccessLevel.Player) - EP = 50; - - return EP + skillBonus; - } - - public static TimeSpan Scale(Mobile m, TimeSpan v) - { - if (!Core.AOS) - return v; - - double scalar = 1.0 + 0.01 * EnhancePotions(m); - - return TimeSpan.FromSeconds(v.TotalSeconds * scalar); - } - - public static double Scale(Mobile m, double v) - { - if (!Core.AOS) - return v; - - double scalar = 1.0 + 0.01 * EnhancePotions(m); - - return v * scalar; - } - - public static int Scale(Mobile m, int v) - { - if (!Core.AOS) - return v; - - return AOS.Scale(v, 100 + EnhancePotions(m)); - } - - public override bool StackWith(Mobile from, Item dropped, bool playSound) => - dropped is BasePotion potion && potion.m_PotionEffect == m_PotionEffect && - base.StackWith(from, potion, playSound); - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Conflagration Potions/BaseConflagrationPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Conflagration Potions/BaseConflagrationPotion.cs index 4a25ce011..48dee863d 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Conflagration Potions/BaseConflagrationPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Conflagration Potions/BaseConflagrationPotion.cs @@ -5,288 +5,289 @@ using Server.Targeting; namespace Server.Items { - public abstract class BaseConflagrationPotion : BasePotion - { - private readonly List m_Users = new List(); - - public BaseConflagrationPotion(PotionEffect effect) : base(0xF06, effect) => Hue = 0x489; - - public BaseConflagrationPotion(Serial serial) : base(serial) + public abstract class BaseConflagrationPotion : BasePotion { - } + private static readonly Dictionary m_Delay = new Dictionary(); + private readonly List m_Users = new List(); - public abstract int MinDamage { get; } - public abstract int MaxDamage { get; } + public BaseConflagrationPotion(PotionEffect effect) : base(0xF06, effect) => Hue = 0x489; - public override bool RequireFreeHand => false; - - public override void Drink(Mobile from) - { - if (Core.AOS && (from.Paralyzed || from.Frozen || from.Spell?.IsCasting == true)) - { - from.SendLocalizedMessage(1062725); // You can not use that potion while paralyzed. - return; - } - - int delay = GetDelay(from); - - if (delay > 0) - { - from.SendLocalizedMessage(1072529, - $"{delay}\t{(delay > 1 ? "seconds." : "second.")}"); // You cannot use that for another ~1_NUM~ ~2_TIMEUNITS~ - return; - } - - if (from.Target is ThrowTarget targ && targ.Potion == this) - return; - - from.RevealingAction(); - - if (!m_Users.Contains(from)) - m_Users.Add(from); - - from.Target = new ThrowTarget(this); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public virtual void Explode(Mobile from, Point3D loc, Map map) - { - if (Deleted || map == null) - return; - - Consume(); - - // Check if any other players are using this potion - for (int i = 0; i < m_Users.Count; i++) - if (m_Users[i].Target is ThrowTarget targ && targ.Potion == this) - Target.Cancel(from); - - // Effects - Effects.PlaySound(loc, map, 0x20C); - - for (int i = -2; i <= 2; i++) - for (int j = -2; j <= 2; j++) + public BaseConflagrationPotion(Serial serial) : base(serial) { - Point3D p = new Point3D(loc.X + i, loc.Y + j, loc.Z); - - if (map.CanFit(p, 12, true, false) && from.InLOS(p)) - new InternalItem(from, p, map, MinDamage, MaxDamage); - } - } - - private class ThrowTarget : Target - { - public ThrowTarget(BaseConflagrationPotion potion) : base(12, true, TargetFlags.None) => Potion = potion; - - public BaseConflagrationPotion Potion { get; } - - protected override void OnTarget(Mobile from, object targeted) - { - if (Potion.Deleted || Potion.Map == Map.Internal) - return; - - if (!(targeted is IPoint3D p) || from.Map == null) - return; - - // Add delay - AddDelay(from); - - SpellHelper.GetSurfaceTop(ref p); - - from.RevealingAction(); - - IEntity to; - - if (p is Mobile mobile) - to = mobile; - else - to = new Entity(Serial.Zero, new Point3D(p), from.Map); - - Effects.SendMovingEffect(from, to, 0xF0D, 7, 0, false, false, Potion.Hue); - Timer.DelayCall(TimeSpan.FromSeconds(1.5), Potion.Explode, from, new Point3D(p), from.Map); - } - } - - public class InternalItem : Item - { - private DateTime m_End; - private int m_MaxDamage; - private int m_MinDamage; - private Timer m_Timer; - - public InternalItem(Mobile from, Point3D loc, Map map, int min, int max) : base(0x398C) - { - Movable = false; - Light = LightType.Circle300; - - MoveToWorld(loc, map); - - From = from; - m_End = DateTime.UtcNow + TimeSpan.FromSeconds(10); - - SetDamage(min, max); - - m_Timer = new InternalTimer(this, m_End); - m_Timer.Start(); - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public Mobile From { get; private set; } - - public override bool BlocksFit => true; - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Timer?.Stop(); - } - - public int GetDamage() => Utility.RandomMinMax(m_MinDamage, m_MaxDamage); - - private void SetDamage(int min, int max) - { - /* new way to apply alchemy bonus according to Stratics' calculator. - this gives a mean to values 25, 50, 75 and 100. Stratics' calculator is outdated. - Those goals will give 2 to alchemy bonus. It's not really OSI-like but it's an approximation. */ - - m_MinDamage = min; - m_MaxDamage = max; - - if (From == null) - return; - - int alchemySkill = From.Skills.Alchemy.Fixed; - int alchemyBonus = alchemySkill / 125 + alchemySkill / 250; - - m_MinDamage = Scale(From, m_MinDamage + alchemyBonus); - m_MaxDamage = Scale(From, m_MaxDamage + alchemyBonus); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(From); - writer.Write(m_End); - writer.Write(m_MinDamage); - writer.Write(m_MaxDamage); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - From = reader.ReadMobile(); - m_End = reader.ReadDateTime(); - m_MinDamage = reader.ReadInt(); - m_MaxDamage = reader.ReadInt(); - - m_Timer = new InternalTimer(this, m_End); - m_Timer.Start(); - } - - public override bool OnMoveOver(Mobile m) - { - if (Visible && From != null && (!Core.AOS || m != From) && SpellHelper.ValidIndirectTarget(From, m) && - From.CanBeHarmful(m, false)) - { - From.DoHarmful(m); - - AOS.Damage(m, From, GetDamage(), 0, 100, 0, 0, 0); - m.PlaySound(0x208); } - return true; - } + public abstract int MinDamage { get; } + public abstract int MaxDamage { get; } - private class InternalTimer : Timer - { - private readonly DateTime m_End; - private readonly InternalItem m_Item; + public override bool RequireFreeHand => false; - public InternalTimer(InternalItem item, DateTime end) : base(TimeSpan.Zero, TimeSpan.FromSeconds(1.0)) + public override void Drink(Mobile from) { - m_Item = item; - m_End = end; - - Priority = TimerPriority.FiftyMS; - } - - protected override void OnTick() - { - if (m_Item.Deleted) - return; - - if (DateTime.UtcNow > m_End) - { - m_Item.Delete(); - Stop(); - return; - } - - Mobile from = m_Item.From; - - if (m_Item.Map == null || from == null) - return; - - foreach (Mobile m in m_Item.GetMobilesInRange(0)) - if (m.Z + 16 > m_Item.Z && m_Item.Z + 12 > m.Z && (!Core.AOS || m != from) && - SpellHelper.ValidIndirectTarget(from, m) && from.CanBeHarmful(m, false)) + if (Core.AOS && (from.Paralyzed || from.Frozen || from.Spell?.IsCasting == true)) { - from.DoHarmful(m); + from.SendLocalizedMessage(1062725); // You can not use that potion while paralyzed. + return; + } - AOS.Damage(m, from, m_Item.GetDamage(), 0, 100, 0, 0, 0); - m.PlaySound(0x208); + var delay = GetDelay(from); + + if (delay > 0) + { + from.SendLocalizedMessage( + 1072529, + $"{delay}\t{(delay > 1 ? "seconds." : "second.")}" + ); // You cannot use that for another ~1_NUM~ ~2_TIMEUNITS~ + return; + } + + if (from.Target is ThrowTarget targ && targ.Potion == this) + return; + + from.RevealingAction(); + + if (!m_Users.Contains(from)) + m_Users.Add(from); + + from.Target = new ThrowTarget(this); + } + + 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 virtual void Explode(Mobile from, Point3D loc, Map map) + { + if (Deleted || map == null) + return; + + Consume(); + + // Check if any other players are using this potion + for (var i = 0; i < m_Users.Count; i++) + if (m_Users[i].Target is ThrowTarget targ && targ.Potion == this) + Target.Cancel(from); + + // Effects + Effects.PlaySound(loc, map, 0x20C); + + for (var i = -2; i <= 2; i++) + for (var j = -2; j <= 2; j++) + { + var p = new Point3D(loc.X + i, loc.Y + j, loc.Z); + + if (map.CanFit(p, 12, true, false) && from.InLOS(p)) + new InternalItem(from, p, map, MinDamage, MaxDamage); + } + } + + public static void AddDelay(Mobile m) + { + m_Delay.TryGetValue(m, out var timer); + timer?.Stop(); + m_Delay[m] = Timer.DelayCall(TimeSpan.FromSeconds(30), EndDelay, m); + } + + public static int GetDelay(Mobile m) + { + if (m_Delay.TryGetValue(m, out var timer) && timer.Next > DateTime.UtcNow) + return (int)(timer.Next - DateTime.UtcNow).TotalSeconds; + + return 0; + } + + public static void EndDelay(Mobile m) + { + if (m_Delay.TryGetValue(m, out var timer)) + { + timer.Stop(); + m_Delay.Remove(m); + } + } + + private class ThrowTarget : Target + { + public ThrowTarget(BaseConflagrationPotion potion) : base(12, true, TargetFlags.None) => Potion = potion; + + public BaseConflagrationPotion Potion { get; } + + protected override void OnTarget(Mobile from, object targeted) + { + if (Potion.Deleted || Potion.Map == Map.Internal) + return; + + if (!(targeted is IPoint3D p) || from.Map == null) + return; + + // Add delay + AddDelay(from); + + SpellHelper.GetSurfaceTop(ref p); + + from.RevealingAction(); + + IEntity to; + + if (p is Mobile mobile) + to = mobile; + else + to = new Entity(Serial.Zero, new Point3D(p), from.Map); + + Effects.SendMovingEffect(from, to, 0xF0D, 7, 0, false, false, Potion.Hue); + Timer.DelayCall(TimeSpan.FromSeconds(1.5), Potion.Explode, from, new Point3D(p), from.Map); + } + } + + public class InternalItem : Item + { + private DateTime m_End; + private int m_MaxDamage; + private int m_MinDamage; + private Timer m_Timer; + + public InternalItem(Mobile from, Point3D loc, Map map, int min, int max) : base(0x398C) + { + Movable = false; + Light = LightType.Circle300; + + MoveToWorld(loc, map); + + From = from; + m_End = DateTime.UtcNow + TimeSpan.FromSeconds(10); + + SetDamage(min, max); + + m_Timer = new InternalTimer(this, m_End); + m_Timer.Start(); + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public Mobile From { get; private set; } + + public override bool BlocksFit => true; + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Timer?.Stop(); + } + + public int GetDamage() => Utility.RandomMinMax(m_MinDamage, m_MaxDamage); + + private void SetDamage(int min, int max) + { + /* new way to apply alchemy bonus according to Stratics' calculator. + this gives a mean to values 25, 50, 75 and 100. Stratics' calculator is outdated. + Those goals will give 2 to alchemy bonus. It's not really OSI-like but it's an approximation. */ + + m_MinDamage = min; + m_MaxDamage = max; + + if (From == null) + return; + + var alchemySkill = From.Skills.Alchemy.Fixed; + var alchemyBonus = alchemySkill / 125 + alchemySkill / 250; + + m_MinDamage = Scale(From, m_MinDamage + alchemyBonus); + m_MaxDamage = Scale(From, m_MaxDamage + alchemyBonus); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(From); + writer.Write(m_End); + writer.Write(m_MinDamage); + writer.Write(m_MaxDamage); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + From = reader.ReadMobile(); + m_End = reader.ReadDateTime(); + m_MinDamage = reader.ReadInt(); + m_MaxDamage = reader.ReadInt(); + + m_Timer = new InternalTimer(this, m_End); + m_Timer.Start(); + } + + public override bool OnMoveOver(Mobile m) + { + if (Visible && From != null && (!Core.AOS || m != From) && SpellHelper.ValidIndirectTarget(From, m) && + From.CanBeHarmful(m, false)) + { + From.DoHarmful(m); + + AOS.Damage(m, From, GetDamage(), 0, 100, 0, 0, 0); + m.PlaySound(0x208); + } + + return true; + } + + private class InternalTimer : Timer + { + private readonly DateTime m_End; + private readonly InternalItem m_Item; + + public InternalTimer(InternalItem item, DateTime end) : base(TimeSpan.Zero, TimeSpan.FromSeconds(1.0)) + { + m_Item = item; + m_End = end; + + Priority = TimerPriority.FiftyMS; + } + + protected override void OnTick() + { + if (m_Item.Deleted) + return; + + if (DateTime.UtcNow > m_End) + { + m_Item.Delete(); + Stop(); + return; + } + + var from = m_Item.From; + + if (m_Item.Map == null || from == null) + return; + + foreach (var m in m_Item.GetMobilesInRange(0)) + if (m.Z + 16 > m_Item.Z && m_Item.Z + 12 > m.Z && (!Core.AOS || m != from) && + SpellHelper.ValidIndirectTarget(from, m) && from.CanBeHarmful(m, false)) + { + from.DoHarmful(m); + + AOS.Damage(m, from, m_Item.GetDamage(), 0, 100, 0, 0, 0); + m.PlaySound(0x208); + } + } } } - } } - - private static readonly Dictionary m_Delay = new Dictionary(); - - public static void AddDelay(Mobile m) - { - m_Delay.TryGetValue(m, out Timer timer); - timer?.Stop(); - m_Delay[m] = Timer.DelayCall(TimeSpan.FromSeconds(30), EndDelay, m); - } - - public static int GetDelay(Mobile m) - { - if (m_Delay.TryGetValue(m, out Timer timer) && timer.Next > DateTime.UtcNow) - return (int)(timer.Next - DateTime.UtcNow).TotalSeconds; - - return 0; - } - - public static void EndDelay(Mobile m) - { - if (m_Delay.TryGetValue(m, out Timer timer)) - { - timer.Stop(); - m_Delay.Remove(m); - } - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Conflagration Potions/ConflagrationPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Conflagration Potions/ConflagrationPotion.cs index 89154a4cf..aafa1bfd1 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Conflagration Potions/ConflagrationPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Conflagration Potions/ConflagrationPotion.cs @@ -1,33 +1,33 @@ namespace Server.Items { - public class ConflagrationPotion : BaseConflagrationPotion - { - [Constructible] - public ConflagrationPotion() : base(PotionEffect.Conflagration) + public class ConflagrationPotion : BaseConflagrationPotion { + [Constructible] + public ConflagrationPotion() : base(PotionEffect.Conflagration) + { + } + + public ConflagrationPotion(Serial serial) : base(serial) + { + } + + public override int MinDamage => 2; + public override int MaxDamage => 4; + + public override int LabelNumber => 1072095; // a Conflagration potion + + 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 ConflagrationPotion(Serial serial) : base(serial) - { - } - - public override int MinDamage => 2; - public override int MaxDamage => 4; - - public override int LabelNumber => 1072095; // a Conflagration potion - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Conflagration Potions/GreaterConflagrationPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Conflagration Potions/GreaterConflagrationPotion.cs index f17113c04..3bea53f11 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Conflagration Potions/GreaterConflagrationPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Conflagration Potions/GreaterConflagrationPotion.cs @@ -1,33 +1,33 @@ namespace Server.Items { - public class GreaterConflagrationPotion : BaseConflagrationPotion - { - [Constructible] - public GreaterConflagrationPotion() : base(PotionEffect.ConflagrationGreater) + public class GreaterConflagrationPotion : BaseConflagrationPotion { + [Constructible] + public GreaterConflagrationPotion() : base(PotionEffect.ConflagrationGreater) + { + } + + public GreaterConflagrationPotion(Serial serial) : base(serial) + { + } + + public override int MinDamage => 4; + public override int MaxDamage => 8; + + public override int LabelNumber => 1072098; // a Greater Conflagration potion + + 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 GreaterConflagrationPotion(Serial serial) : base(serial) - { - } - - public override int MinDamage => 4; - public override int MaxDamage => 8; - - public override int LabelNumber => 1072098; // a Greater Conflagration potion - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Confusion Blast Potions/BaseConfusionBlastPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Confusion Blast Potions/BaseConfusionBlastPotion.cs index eaabe6925..4eb6efeee 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Confusion Blast Potions/BaseConfusionBlastPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Confusion Blast Potions/BaseConfusionBlastPotion.cs @@ -7,159 +7,160 @@ using Server.Targeting; namespace Server.Items { - public abstract class BaseConfusionBlastPotion : BasePotion - { - private readonly List m_Users = new List(); - - public BaseConfusionBlastPotion(PotionEffect effect) : base(0xF06, effect) => Hue = 0x48D; - - public BaseConfusionBlastPotion(Serial serial) : base(serial) + public abstract class BaseConfusionBlastPotion : BasePotion { - } + private static readonly Dictionary m_Delay = new Dictionary(); + private readonly List m_Users = new List(); - public abstract int Radius { get; } + public BaseConfusionBlastPotion(PotionEffect effect) : base(0xF06, effect) => Hue = 0x48D; - public override bool RequireFreeHand => false; - - public override void Drink(Mobile from) - { - if (Core.AOS && (from.Paralyzed || from.Frozen || from.Spell?.IsCasting == true)) - { - from.SendLocalizedMessage(1062725); // You can not use that potion while paralyzed. - return; - } - - int delay = GetDelay(from); - - if (delay > 0) - { - from.SendLocalizedMessage(1072529, - $"{delay}\t{(delay > 1 ? "seconds." : "second.")}"); // You cannot use that for another ~1_NUM~ ~2_TIMEUNITS~ - return; - } - - if (from.Target is ThrowTarget targ && targ.Potion == this) - return; - - from.RevealingAction(); - - if (!m_Users.Contains(from)) - m_Users.Add(from); - - from.Target = new ThrowTarget(this); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public virtual void Explode(Mobile from, Point3D loc, Map map) - { - if (Deleted || map == null) - return; - - Consume(); - - // Check if any other players are using this potion - for (int i = 0; i < m_Users.Count; i++) - if (m_Users[i].Target is ThrowTarget targ && targ.Potion == this) - Target.Cancel(from); - - // Effects - Effects.PlaySound(loc, map, 0x207); - - Geometry.Circle2D(loc, map, Radius, BlastEffect, 270, 90); - - Timer.DelayCall(TimeSpan.FromSeconds(0.3), CircleEffect2, loc, map); - - foreach (Mobile mobile in map.GetMobilesInRange(loc, Radius)) - if (mobile is BaseCreature mon) + public BaseConfusionBlastPotion(Serial serial) : base(serial) { - if (mon.Controlled || mon.Summoned) - continue; + } - mon.Pacify(from, DateTime.UtcNow + TimeSpan.FromSeconds(5.0)); // TODO check + public abstract int Radius { get; } + + public override bool RequireFreeHand => false; + + public override void Drink(Mobile from) + { + if (Core.AOS && (from.Paralyzed || from.Frozen || from.Spell?.IsCasting == true)) + { + from.SendLocalizedMessage(1062725); // You can not use that potion while paralyzed. + return; + } + + var delay = GetDelay(from); + + if (delay > 0) + { + from.SendLocalizedMessage( + 1072529, + $"{delay}\t{(delay > 1 ? "seconds." : "second.")}" + ); // You cannot use that for another ~1_NUM~ ~2_TIMEUNITS~ + return; + } + + if (from.Target is ThrowTarget targ && targ.Potion == this) + return; + + from.RevealingAction(); + + if (!m_Users.Contains(from)) + m_Users.Add(from); + + from.Target = new ThrowTarget(this); + } + + 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 virtual void Explode(Mobile from, Point3D loc, Map map) + { + if (Deleted || map == null) + return; + + Consume(); + + // Check if any other players are using this potion + for (var i = 0; i < m_Users.Count; i++) + if (m_Users[i].Target is ThrowTarget targ && targ.Potion == this) + Target.Cancel(from); + + // Effects + Effects.PlaySound(loc, map, 0x207); + + Geometry.Circle2D(loc, map, Radius, BlastEffect, 270, 90); + + Timer.DelayCall(TimeSpan.FromSeconds(0.3), CircleEffect2, loc, map); + + foreach (var mobile in map.GetMobilesInRange(loc, Radius)) + if (mobile is BaseCreature mon) + { + if (mon.Controlled || mon.Summoned) + continue; + + mon.Pacify(from, DateTime.UtcNow + TimeSpan.FromSeconds(5.0)); // TODO check + } + } + + public virtual void BlastEffect(Point3D p, Map map) + { + if (map.CanFit(p, 12, true, false)) + Effects.SendLocationEffect(p, map, 0x376A, 4, 9); + } + + public void CircleEffect2(Point3D p, Map m) + { + Geometry.Circle2D(p, m, Radius, BlastEffect, 90, 270); + } + + public static void AddDelay(Mobile m) + { + m_Delay.TryGetValue(m, out var timer); + timer?.Stop(); + m_Delay[m] = Timer.DelayCall(TimeSpan.FromSeconds(60), EndDelay, m); + } + + public static int GetDelay(Mobile m) + { + if (m_Delay.TryGetValue(m, out var timer) && timer.Next > DateTime.UtcNow) + return (int)(timer.Next - DateTime.UtcNow).TotalSeconds; + + return 0; + } + + public static void EndDelay(Mobile m) + { + if (m_Delay.TryGetValue(m, out var timer)) + { + timer.Stop(); + m_Delay.Remove(m); + } + } + + private class ThrowTarget : Target + { + public ThrowTarget(BaseConfusionBlastPotion potion) : base(12, true, TargetFlags.None) => Potion = potion; + + public BaseConfusionBlastPotion Potion { get; } + + protected override void OnTarget(Mobile from, object targeted) + { + if (Potion.Deleted || Potion.Map == Map.Internal) + return; + + if (!(targeted is IPoint3D p) || from.Map == null) + return; + + // Add delay + AddDelay(from); + + SpellHelper.GetSurfaceTop(ref p); + + from.RevealingAction(); + + IEntity to; + + if (p is Mobile mobile) + to = mobile; + else + to = new Entity(Serial.Zero, new Point3D(p), from.Map); + + Effects.SendMovingEffect(from, to, 0xF0D, 7, 0, false, false, Potion.Hue); + Timer.DelayCall(TimeSpan.FromSeconds(1.0), Potion.Explode, from, new Point3D(p), from.Map); + } } } - - private class ThrowTarget : Target - { - public ThrowTarget(BaseConfusionBlastPotion potion) : base(12, true, TargetFlags.None) => Potion = potion; - - public BaseConfusionBlastPotion Potion { get; } - - protected override void OnTarget(Mobile from, object targeted) - { - if (Potion.Deleted || Potion.Map == Map.Internal) - return; - - if (!(targeted is IPoint3D p) || from.Map == null) - return; - - // Add delay - AddDelay(from); - - SpellHelper.GetSurfaceTop(ref p); - - from.RevealingAction(); - - IEntity to; - - if (p is Mobile mobile) - to = mobile; - else - to = new Entity(Serial.Zero, new Point3D(p), from.Map); - - Effects.SendMovingEffect(from, to, 0xF0D, 7, 0, false, false, Potion.Hue); - Timer.DelayCall(TimeSpan.FromSeconds(1.0), Potion.Explode, from, new Point3D(p), from.Map); - } - } - - public virtual void BlastEffect(Point3D p, Map map) - { - if (map.CanFit(p, 12, true, false)) - Effects.SendLocationEffect(p, map, 0x376A, 4, 9); - } - - public void CircleEffect2(Point3D p, Map m) - { - Geometry.Circle2D(p, m, Radius, BlastEffect, 90, 270); - } - - private static readonly Dictionary m_Delay = new Dictionary(); - - public static void AddDelay(Mobile m) - { - m_Delay.TryGetValue(m, out Timer timer); - timer?.Stop(); - m_Delay[m] = Timer.DelayCall(TimeSpan.FromSeconds(60), EndDelay, m); - } - - public static int GetDelay(Mobile m) - { - if (m_Delay.TryGetValue(m, out Timer timer) && timer.Next > DateTime.UtcNow) - return (int)(timer.Next - DateTime.UtcNow).TotalSeconds; - - return 0; - } - - public static void EndDelay(Mobile m) - { - if (m_Delay.TryGetValue(m, out Timer timer)) - { - timer.Stop(); - m_Delay.Remove(m); - } - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Confusion Blast Potions/ConfusionBlastPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Confusion Blast Potions/ConfusionBlastPotion.cs index 5270c4c6c..42b3da6a8 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Confusion Blast Potions/ConfusionBlastPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Confusion Blast Potions/ConfusionBlastPotion.cs @@ -1,32 +1,32 @@ namespace Server.Items { - public class ConfusionBlastPotion : BaseConfusionBlastPotion - { - [Constructible] - public ConfusionBlastPotion() : base(PotionEffect.ConfusionBlast) + public class ConfusionBlastPotion : BaseConfusionBlastPotion { + [Constructible] + public ConfusionBlastPotion() : base(PotionEffect.ConfusionBlast) + { + } + + public ConfusionBlastPotion(Serial serial) : base(serial) + { + } + + public override int Radius => 5; + + public override int LabelNumber => 1072105; // a Confusion Blast potion + + 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 ConfusionBlastPotion(Serial serial) : base(serial) - { - } - - public override int Radius => 5; - - public override int LabelNumber => 1072105; // a Confusion Blast potion - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Confusion Blast Potions/GreaterConfusionBlastPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Confusion Blast Potions/GreaterConfusionBlastPotion.cs index 3c75e7f9c..01ca7d629 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Confusion Blast Potions/GreaterConfusionBlastPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Confusion Blast Potions/GreaterConfusionBlastPotion.cs @@ -1,32 +1,32 @@ namespace Server.Items { - public class GreaterConfusionBlastPotion : BaseConfusionBlastPotion - { - [Constructible] - public GreaterConfusionBlastPotion() : base(PotionEffect.ConfusionBlastGreater) + public class GreaterConfusionBlastPotion : BaseConfusionBlastPotion { + [Constructible] + public GreaterConfusionBlastPotion() : base(PotionEffect.ConfusionBlastGreater) + { + } + + public GreaterConfusionBlastPotion(Serial serial) : base(serial) + { + } + + public override int Radius => 7; + + public override int LabelNumber => 1072108; // a Greater Confusion Blast potion + + 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 GreaterConfusionBlastPotion(Serial serial) : base(serial) - { - } - - public override int Radius => 7; - - public override int LabelNumber => 1072108; // a Greater Confusion Blast potion - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Cure Potions/BaseCurePotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Cure Potions/BaseCurePotion.cs index 43f56ccd5..7b8b7c7f2 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Cure Potions/BaseCurePotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Cure Potions/BaseCurePotion.cs @@ -4,97 +4,97 @@ using Server.Spells.Necromancy; namespace Server.Items { - public class CureLevelInfo - { - public CureLevelInfo(Poison poison, double chance) + public class CureLevelInfo { - Poison = poison; - Chance = chance; - } - - public Poison Poison { get; } - - public double Chance { get; } - } - - public abstract class BaseCurePotion : BasePotion - { - public BaseCurePotion(PotionEffect effect) : base(0xF07, effect) - { - } - - public BaseCurePotion(Serial serial) : base(serial) - { - } - - public abstract CureLevelInfo[] LevelInfo { get; } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public void DoCure(Mobile from) - { - bool cure = false; - - CureLevelInfo[] info = LevelInfo; - - for (int i = 0; i < info.Length; ++i) - { - CureLevelInfo li = info[i]; - - if (li.Poison == from.Poison && Scale(from, li.Chance) > Utility.RandomDouble()) + public CureLevelInfo(Poison poison, double chance) { - cure = true; - break; + Poison = poison; + Chance = chance; } - } - if (cure && from.CurePoison(from)) - { - from.SendLocalizedMessage(500231); // You feel cured of poison! + public Poison Poison { get; } - from.FixedEffect(0x373A, 10, 15); - from.PlaySound(0x1E0); - } - else if (!cure) - { - from.SendLocalizedMessage(500232); // That potion was not strong enough to cure your ailment! - } + public double Chance { get; } } - public override void Drink(Mobile from) + public abstract class BaseCurePotion : BasePotion { - if (TransformationSpellHelper.UnderTransformation(from, typeof(VampiricEmbraceSpell))) - { - from.SendLocalizedMessage(1061652); // The garlic in the potion would surely kill you. - } - else if (from.Poisoned) - { - DoCure(from); + public BaseCurePotion(PotionEffect effect) : base(0xF07, effect) + { + } - PlayDrinkEffect(from); + public BaseCurePotion(Serial serial) : base(serial) + { + } - from.FixedParticles(0x373A, 10, 15, 5012, EffectLayer.Waist); - from.PlaySound(0x1E0); + public abstract CureLevelInfo[] LevelInfo { get; } - if (!DuelContext.IsFreeConsume(from)) - Consume(); - } - else - { - from.SendLocalizedMessage(1042000); // You are not poisoned. - } + 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 void DoCure(Mobile from) + { + var cure = false; + + var info = LevelInfo; + + for (var i = 0; i < info.Length; ++i) + { + var li = info[i]; + + if (li.Poison == from.Poison && Scale(from, li.Chance) > Utility.RandomDouble()) + { + cure = true; + break; + } + } + + if (cure && from.CurePoison(from)) + { + from.SendLocalizedMessage(500231); // You feel cured of poison! + + from.FixedEffect(0x373A, 10, 15); + from.PlaySound(0x1E0); + } + else if (!cure) + { + from.SendLocalizedMessage(500232); // That potion was not strong enough to cure your ailment! + } + } + + public override void Drink(Mobile from) + { + if (TransformationSpellHelper.UnderTransformation(from, typeof(VampiricEmbraceSpell))) + { + from.SendLocalizedMessage(1061652); // The garlic in the potion would surely kill you. + } + else if (from.Poisoned) + { + DoCure(from); + + PlayDrinkEffect(from); + + from.FixedParticles(0x373A, 10, 15, 5012, EffectLayer.Waist); + from.PlaySound(0x1E0); + + if (!DuelContext.IsFreeConsume(from)) + Consume(); + } + else + { + from.SendLocalizedMessage(1042000); // You are not poisoned. + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Cure Potions/CurePotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Cure Potions/CurePotion.cs index 8431e85bf..64e378b4d 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Cure Potions/CurePotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Cure Potions/CurePotion.cs @@ -1,47 +1,47 @@ namespace Server.Items { - public class CurePotion : BaseCurePotion - { - private static readonly CureLevelInfo[] m_OldLevelInfo = + public class CurePotion : BaseCurePotion { - new CureLevelInfo(Poison.Lesser, 1.00), // 100% chance to cure lesser poison - new CureLevelInfo(Poison.Regular, 0.75), // 75% chance to cure regular poison - new CureLevelInfo(Poison.Greater, 0.50), // 50% chance to cure greater poison - new CureLevelInfo(Poison.Deadly, 0.15) // 15% chance to cure deadly poison - }; + private static readonly CureLevelInfo[] m_OldLevelInfo = + { + new CureLevelInfo(Poison.Lesser, 1.00), // 100% chance to cure lesser poison + new CureLevelInfo(Poison.Regular, 0.75), // 75% chance to cure regular poison + new CureLevelInfo(Poison.Greater, 0.50), // 50% chance to cure greater poison + new CureLevelInfo(Poison.Deadly, 0.15) // 15% chance to cure deadly poison + }; - private static readonly CureLevelInfo[] m_AosLevelInfo = - { - new CureLevelInfo(Poison.Lesser, 1.00), - new CureLevelInfo(Poison.Regular, 0.95), - new CureLevelInfo(Poison.Greater, 0.75), - new CureLevelInfo(Poison.Deadly, 0.50), - new CureLevelInfo(Poison.Lethal, 0.25) - }; + private static readonly CureLevelInfo[] m_AosLevelInfo = + { + new CureLevelInfo(Poison.Lesser, 1.00), + new CureLevelInfo(Poison.Regular, 0.95), + new CureLevelInfo(Poison.Greater, 0.75), + new CureLevelInfo(Poison.Deadly, 0.50), + new CureLevelInfo(Poison.Lethal, 0.25) + }; - [Constructible] - public CurePotion() : base(PotionEffect.Cure) - { + [Constructible] + public CurePotion() : base(PotionEffect.Cure) + { + } + + public CurePotion(Serial serial) : base(serial) + { + } + + public override CureLevelInfo[] LevelInfo => Core.AOS ? m_AosLevelInfo : m_OldLevelInfo; + + 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 CurePotion(Serial serial) : base(serial) - { - } - - public override CureLevelInfo[] LevelInfo => Core.AOS ? m_AosLevelInfo : m_OldLevelInfo; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Cure Potions/GreaterCurePotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Cure Potions/GreaterCurePotion.cs index d2513e31f..0801f8743 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Cure Potions/GreaterCurePotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Cure Potions/GreaterCurePotion.cs @@ -1,48 +1,48 @@ namespace Server.Items { - public class GreaterCurePotion : BaseCurePotion - { - private static readonly CureLevelInfo[] m_OldLevelInfo = + public class GreaterCurePotion : BaseCurePotion { - new CureLevelInfo(Poison.Lesser, 1.00), // 100% chance to cure lesser poison - new CureLevelInfo(Poison.Regular, 1.00), // 100% chance to cure regular poison - new CureLevelInfo(Poison.Greater, 1.00), // 100% chance to cure greater poison - new CureLevelInfo(Poison.Deadly, 0.75), // 75% chance to cure deadly poison - new CureLevelInfo(Poison.Lethal, 0.25) // 25% chance to cure lethal poison - }; + private static readonly CureLevelInfo[] m_OldLevelInfo = + { + new CureLevelInfo(Poison.Lesser, 1.00), // 100% chance to cure lesser poison + new CureLevelInfo(Poison.Regular, 1.00), // 100% chance to cure regular poison + new CureLevelInfo(Poison.Greater, 1.00), // 100% chance to cure greater poison + new CureLevelInfo(Poison.Deadly, 0.75), // 75% chance to cure deadly poison + new CureLevelInfo(Poison.Lethal, 0.25) // 25% chance to cure lethal poison + }; - private static readonly CureLevelInfo[] m_AosLevelInfo = - { - new CureLevelInfo(Poison.Lesser, 1.00), - new CureLevelInfo(Poison.Regular, 1.00), - new CureLevelInfo(Poison.Greater, 1.00), - new CureLevelInfo(Poison.Deadly, 0.95), - new CureLevelInfo(Poison.Lethal, 0.75) - }; + private static readonly CureLevelInfo[] m_AosLevelInfo = + { + new CureLevelInfo(Poison.Lesser, 1.00), + new CureLevelInfo(Poison.Regular, 1.00), + new CureLevelInfo(Poison.Greater, 1.00), + new CureLevelInfo(Poison.Deadly, 0.95), + new CureLevelInfo(Poison.Lethal, 0.75) + }; - [Constructible] - public GreaterCurePotion() : base(PotionEffect.CureGreater) - { + [Constructible] + public GreaterCurePotion() : base(PotionEffect.CureGreater) + { + } + + public GreaterCurePotion(Serial serial) : base(serial) + { + } + + public override CureLevelInfo[] LevelInfo => Core.AOS ? m_AosLevelInfo : m_OldLevelInfo; + + 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 GreaterCurePotion(Serial serial) : base(serial) - { - } - - public override CureLevelInfo[] LevelInfo => Core.AOS ? m_AosLevelInfo : m_OldLevelInfo; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Cure Potions/LesserCurePotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Cure Potions/LesserCurePotion.cs index 2758a8dd2..fb7d65a9b 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Cure Potions/LesserCurePotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Cure Potions/LesserCurePotion.cs @@ -1,44 +1,44 @@ namespace Server.Items { - public class LesserCurePotion : BaseCurePotion - { - private static readonly CureLevelInfo[] m_OldLevelInfo = + public class LesserCurePotion : BaseCurePotion { - new CureLevelInfo(Poison.Lesser, 0.75), // 75% chance to cure lesser poison - new CureLevelInfo(Poison.Regular, 0.50), // 50% chance to cure regular poison - new CureLevelInfo(Poison.Greater, 0.15) // 15% chance to cure greater poison - }; + private static readonly CureLevelInfo[] m_OldLevelInfo = + { + new CureLevelInfo(Poison.Lesser, 0.75), // 75% chance to cure lesser poison + new CureLevelInfo(Poison.Regular, 0.50), // 50% chance to cure regular poison + new CureLevelInfo(Poison.Greater, 0.15) // 15% chance to cure greater poison + }; - private static readonly CureLevelInfo[] m_AosLevelInfo = - { - new CureLevelInfo(Poison.Lesser, 0.75), - new CureLevelInfo(Poison.Regular, 0.50), - new CureLevelInfo(Poison.Greater, 0.25) - }; + private static readonly CureLevelInfo[] m_AosLevelInfo = + { + new CureLevelInfo(Poison.Lesser, 0.75), + new CureLevelInfo(Poison.Regular, 0.50), + new CureLevelInfo(Poison.Greater, 0.25) + }; - [Constructible] - public LesserCurePotion() : base(PotionEffect.CureLesser) - { + [Constructible] + public LesserCurePotion() : base(PotionEffect.CureLesser) + { + } + + public LesserCurePotion(Serial serial) : base(serial) + { + } + + public override CureLevelInfo[] LevelInfo => Core.AOS ? m_AosLevelInfo : m_OldLevelInfo; + + 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 LesserCurePotion(Serial serial) : base(serial) - { - } - - public override CureLevelInfo[] LevelInfo => Core.AOS ? m_AosLevelInfo : m_OldLevelInfo; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/DarkglowPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/DarkglowPotion.cs index 1ef5b8fe9..de576f4c2 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/DarkglowPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/DarkglowPotion.cs @@ -1,33 +1,33 @@ namespace Server.Items { - public class DarkglowPotion : BasePoisonPotion - { - [Constructible] - public DarkglowPotion() : base(PotionEffect.Darkglow) => Hue = 0x96; - - public DarkglowPotion(Serial serial) : base(serial) + public class DarkglowPotion : BasePoisonPotion { + [Constructible] + public DarkglowPotion() : base(PotionEffect.Darkglow) => Hue = 0x96; + + public DarkglowPotion(Serial serial) : base(serial) + { + } + + public override Poison Poison => Poison.Greater; /* MUST be restored when prerequisites are done */ + + public override double MinPoisoningSkill => 95.0; + public override double MaxPoisoningSkill => 100.0; + + public override int LabelNumber => 1072849; // Darkglow Poison + + 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 Poison Poison => Poison.Greater; /* MUST be restored when prerequisites are done */ - - public override double MinPoisoningSkill => 95.0; - public override double MaxPoisoningSkill => 100.0; - - public override int LabelNumber => 1072849; // Darkglow Poison - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/BaseExplosionPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/BaseExplosionPotion.cs index 64994e105..c3b35b6cd 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/BaseExplosionPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/BaseExplosionPotion.cs @@ -7,257 +7,268 @@ using Server.Targeting; namespace Server.Items { - public abstract class BaseExplosionPotion : BasePotion - { - private const int ExplosionRange = 2; // How long is the blast radius? - - private static readonly bool LeveledExplosion = false; // Should explosion potions explode other nearby potions? - private static readonly bool InstantExplosion = false; // Should explosion potions explode on impact? - private static readonly bool RelativeLocation = false; // Is the explosion target location relative for mobiles? - - private Timer m_Timer; - - public BaseExplosionPotion(PotionEffect effect) : base(0xF0D, effect) + public abstract class BaseExplosionPotion : BasePotion { - } + private const int ExplosionRange = 2; // How long is the blast radius? - public BaseExplosionPotion(Serial serial) : base(serial) - { - } + private static readonly bool LeveledExplosion = false; // Should explosion potions explode other nearby potions? + private static readonly bool InstantExplosion = false; // Should explosion potions explode on impact? + private static readonly bool RelativeLocation = false; // Is the explosion target location relative for mobiles? - public abstract int MinDamage { get; } - public abstract int MaxDamage { get; } + private Timer m_Timer; - public override bool RequireFreeHand => false; - - public List Users { get; private set; } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public virtual IEntity FindParent(Mobile from) - { - if (HeldBy?.Holding == this) - return HeldBy; - - if (RootParent != null) - return RootParent; - - if (Map == Map.Internal) - return from; - - return this; - } - - public override void Drink(Mobile from) - { - if (Core.AOS && (from.Paralyzed || from.Frozen || from.Spell?.IsCasting == true)) - { - from.SendLocalizedMessage(1062725); // You can not use a purple potion while paralyzed. - return; - } - - ThrowTarget targ = from.Target as ThrowTarget; - Stackable = false; // Scavenged explosion potions won't stack with those ones in backpack, and still will explode. - - if (targ?.Potion == this) - return; - - from.RevealingAction(); - - Users ??= new List(); - - if (!Users.Contains(from)) - Users.Add(from); - - from.Target = new ThrowTarget(this); - - if (m_Timer == null) - { - from.SendLocalizedMessage(500236); // You should throw it now! - - int timer = 3; - - if (Core.ML) - m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.25), 5, - () => Detonate_OnTick(from, timer--)); // 3.6 seconds explosion delay - else - m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(0.75), TimeSpan.FromSeconds(1.0), 4, - () => Detonate_OnTick(from, timer--)); // 2.6 seconds explosion delay - } - } - - private void Detonate_OnTick(Mobile from, int timer) - { - if (Deleted) - return; - - IEntity parent = FindParent(from); - - if (timer == 0) - { - Point3D loc; - Map map; - - if (parent is Item item) + public BaseExplosionPotion(PotionEffect effect) : base(0xF0D, effect) { - loc = item.GetWorldLocation(); - map = item.Map; - } - else if (parent is Mobile m) - { - loc = m.Location; - map = m.Map; - } - else - { - return; } - Explode(from, true, loc, map); - m_Timer = null; - } - else - { - if (parent is Item item) - item.PublicOverheadMessage(MessageType.Regular, 0x22, false, timer.ToString()); - else if (parent is Mobile mobile) - mobile.PublicOverheadMessage(MessageType.Regular, 0x22, false, timer.ToString()); - } - } - - private void Reposition_OnTick(Mobile from, Point3D loc, Map map) - { - if (Deleted) - return; - - if (InstantExplosion) - Explode(from, true, loc, map); - else - MoveToWorld(loc, map); - } - - public void Explode(Mobile from, bool direct, Point3D loc, Map map) - { - if (Deleted) - return; - - Consume(); - - for (int i = 0; Users != null && i < Users.Count; ++i) - { - Mobile m = Users[i]; - - if (m.Target is ThrowTarget targ && targ.Potion == this) - Target.Cancel(m); - } - - if (map == null) - return; - - Effects.PlaySound(loc, map, 0x307); - - Effects.SendLocationEffect(loc, map, 0x36B0, 9, 10, 0, 0); - int alchemyBonus = 0; - - if (direct) - alchemyBonus = (int)(from.Skills.Alchemy.Value / (Core.AOS ? 5 : 10)); - - IPooledEnumerable eable = map.GetObjectsInRange(loc, ExplosionRange, LeveledExplosion); - int toDamage = 0; - - List toExplode = eable.Where(o => - { - if (!(o is Mobile mobile) || (from != null && - (!SpellHelper.ValidIndirectTarget(from, mobile) || !from.CanBeHarmful(mobile, false)))) - return o is BaseExplosionPotion && o != this; - - ++toDamage; - return true; - }).ToList(); - - eable.Free(); - - int min = Scale(from, MinDamage); - int max = Scale(from, MaxDamage); - - for (int i = 0; i < toExplode.Count; ++i) - { - IEntity o = toExplode[i]; - - if (o is Mobile m) + public BaseExplosionPotion(Serial serial) : base(serial) { - from?.DoHarmful(m); - - int damage = Utility.RandomMinMax(min, max); - - damage += alchemyBonus; - - if (!Core.AOS && damage > 40) - damage = 40; - else if (Core.AOS && toDamage > 2) - damage /= toDamage - 1; - - AOS.Damage(m, from, damage, 0, 100, 0, 0, 0); - } - else if (o is BaseExplosionPotion pot) - { - pot.Explode(from, false, pot.GetWorldLocation(), pot.Map); - } - } - } - - private class ThrowTarget : Target - { - public ThrowTarget(BaseExplosionPotion potion) : base(12, true, TargetFlags.None) => Potion = potion; - - public BaseExplosionPotion Potion { get; } - - protected override void OnTarget(Mobile from, object targeted) - { - if (Potion.Deleted || Potion.Map == Map.Internal) - return; - - if (!(targeted is IPoint3D p)) - return; - - Map map = from.Map; - - if (map == null) - return; - - SpellHelper.GetSurfaceTop(ref p); - - from.RevealingAction(); - - IEntity to = new Entity(Serial.Zero, new Point3D(p), map); - - if (p is Mobile m) - { - if (!RelativeLocation) // explosion location = current mob location. - p = m.Location; - else - to = m; } - Effects.SendMovingEffect(from, to, Potion.ItemID, 7, 0, false, false, Potion.Hue); + public abstract int MinDamage { get; } + public abstract int MaxDamage { get; } - if (Potion.Amount > 1) Mobile.LiftItemDupe(Potion, 1); + public override bool RequireFreeHand => false; - Potion.Internalize(); - Timer.DelayCall(TimeSpan.FromSeconds(1.0), Potion.Reposition_OnTick, from, new Point3D(p), map); - } + public List Users { get; private set; } + + 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 virtual IEntity FindParent(Mobile from) + { + if (HeldBy?.Holding == this) + return HeldBy; + + if (RootParent != null) + return RootParent; + + if (Map == Map.Internal) + return from; + + return this; + } + + public override void Drink(Mobile from) + { + if (Core.AOS && (from.Paralyzed || from.Frozen || from.Spell?.IsCasting == true)) + { + from.SendLocalizedMessage(1062725); // You can not use a purple potion while paralyzed. + return; + } + + var targ = from.Target as ThrowTarget; + Stackable = false; // Scavenged explosion potions won't stack with those ones in backpack, and still will explode. + + if (targ?.Potion == this) + return; + + from.RevealingAction(); + + Users ??= new List(); + + if (!Users.Contains(from)) + Users.Add(from); + + from.Target = new ThrowTarget(this); + + if (m_Timer == null) + { + from.SendLocalizedMessage(500236); // You should throw it now! + + var timer = 3; + + if (Core.ML) + m_Timer = Timer.DelayCall( + TimeSpan.FromSeconds(1.0), + TimeSpan.FromSeconds(1.25), + 5, + () => Detonate_OnTick(from, timer--) + ); // 3.6 seconds explosion delay + else + m_Timer = Timer.DelayCall( + TimeSpan.FromSeconds(0.75), + TimeSpan.FromSeconds(1.0), + 4, + () => Detonate_OnTick(from, timer--) + ); // 2.6 seconds explosion delay + } + } + + private void Detonate_OnTick(Mobile from, int timer) + { + if (Deleted) + return; + + var parent = FindParent(from); + + if (timer == 0) + { + Point3D loc; + Map map; + + if (parent is Item item) + { + loc = item.GetWorldLocation(); + map = item.Map; + } + else if (parent is Mobile m) + { + loc = m.Location; + map = m.Map; + } + else + { + return; + } + + Explode(from, true, loc, map); + m_Timer = null; + } + else + { + if (parent is Item item) + item.PublicOverheadMessage(MessageType.Regular, 0x22, false, timer.ToString()); + else if (parent is Mobile mobile) + mobile.PublicOverheadMessage(MessageType.Regular, 0x22, false, timer.ToString()); + } + } + + private void Reposition_OnTick(Mobile from, Point3D loc, Map map) + { + if (Deleted) + return; + + if (InstantExplosion) + Explode(from, true, loc, map); + else + MoveToWorld(loc, map); + } + + public void Explode(Mobile from, bool direct, Point3D loc, Map map) + { + if (Deleted) + return; + + Consume(); + + for (var i = 0; Users != null && i < Users.Count; ++i) + { + var m = Users[i]; + + if (m.Target is ThrowTarget targ && targ.Potion == this) + Target.Cancel(m); + } + + if (map == null) + return; + + Effects.PlaySound(loc, map, 0x307); + + Effects.SendLocationEffect(loc, map, 0x36B0, 9, 10, 0, 0); + var alchemyBonus = 0; + + if (direct) + alchemyBonus = (int)(from.Skills.Alchemy.Value / (Core.AOS ? 5 : 10)); + + var eable = map.GetObjectsInRange(loc, ExplosionRange, LeveledExplosion); + var toDamage = 0; + + var toExplode = eable.Where( + o => + { + if (!(o is Mobile mobile) || @from != null && + (!SpellHelper.ValidIndirectTarget(@from, mobile) || !@from.CanBeHarmful(mobile, false))) + return o is BaseExplosionPotion && o != this; + + ++toDamage; + return true; + } + ) + .ToList(); + + eable.Free(); + + var min = Scale(from, MinDamage); + var max = Scale(from, MaxDamage); + + for (var i = 0; i < toExplode.Count; ++i) + { + var o = toExplode[i]; + + if (o is Mobile m) + { + from?.DoHarmful(m); + + var damage = Utility.RandomMinMax(min, max); + + damage += alchemyBonus; + + if (!Core.AOS && damage > 40) + damage = 40; + else if (Core.AOS && toDamage > 2) + damage /= toDamage - 1; + + AOS.Damage(m, from, damage, 0, 100, 0, 0, 0); + } + else if (o is BaseExplosionPotion pot) + { + pot.Explode(from, false, pot.GetWorldLocation(), pot.Map); + } + } + } + + private class ThrowTarget : Target + { + public ThrowTarget(BaseExplosionPotion potion) : base(12, true, TargetFlags.None) => Potion = potion; + + public BaseExplosionPotion Potion { get; } + + protected override void OnTarget(Mobile from, object targeted) + { + if (Potion.Deleted || Potion.Map == Map.Internal) + return; + + if (!(targeted is IPoint3D p)) + return; + + var map = from.Map; + + if (map == null) + return; + + SpellHelper.GetSurfaceTop(ref p); + + from.RevealingAction(); + + IEntity to = new Entity(Serial.Zero, new Point3D(p), map); + + if (p is Mobile m) + { + if (!RelativeLocation) // explosion location = current mob location. + p = m.Location; + else + to = m; + } + + Effects.SendMovingEffect(from, to, Potion.ItemID, 7, 0, false, false, Potion.Hue); + + if (Potion.Amount > 1) Mobile.LiftItemDupe(Potion, 1); + + Potion.Internalize(); + Timer.DelayCall(TimeSpan.FromSeconds(1.0), Potion.Reposition_OnTick, from, new Point3D(p), map); + } + } } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/ExplosionPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/ExplosionPotion.cs index af1d142d5..c11fd7d1f 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/ExplosionPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/ExplosionPotion.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class ExplosionPotion : BaseExplosionPotion - { - [Constructible] - public ExplosionPotion() : base(PotionEffect.Explosion) + public class ExplosionPotion : BaseExplosionPotion { + [Constructible] + public ExplosionPotion() : base(PotionEffect.Explosion) + { + } + + public ExplosionPotion(Serial serial) : base(serial) + { + } + + public override int MinDamage => 10; + public override int MaxDamage => 20; + + 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 ExplosionPotion(Serial serial) : base(serial) - { - } - - public override int MinDamage => 10; - public override int MaxDamage => 20; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/GreaterExplosionPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/GreaterExplosionPotion.cs index 03f9390dc..1f3a2b392 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/GreaterExplosionPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/GreaterExplosionPotion.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class GreaterExplosionPotion : BaseExplosionPotion - { - [Constructible] - public GreaterExplosionPotion() : base(PotionEffect.ExplosionGreater) + public class GreaterExplosionPotion : BaseExplosionPotion { + [Constructible] + public GreaterExplosionPotion() : base(PotionEffect.ExplosionGreater) + { + } + + public GreaterExplosionPotion(Serial serial) : base(serial) + { + } + + public override int MinDamage => Core.AOS ? 20 : 15; + public override int MaxDamage => Core.AOS ? 40 : 30; + + 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 GreaterExplosionPotion(Serial serial) : base(serial) - { - } - - public override int MinDamage => Core.AOS ? 20 : 15; - public override int MaxDamage => Core.AOS ? 40 : 30; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/LesserExplosionPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/LesserExplosionPotion.cs index 1d727887f..865aa23f1 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/LesserExplosionPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Explosion Potions/LesserExplosionPotion.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class LesserExplosionPotion : BaseExplosionPotion - { - [Constructible] - public LesserExplosionPotion() : base(PotionEffect.ExplosionLesser) + public class LesserExplosionPotion : BaseExplosionPotion { + [Constructible] + public LesserExplosionPotion() : base(PotionEffect.ExplosionLesser) + { + } + + public LesserExplosionPotion(Serial serial) : base(serial) + { + } + + public override int MinDamage => 5; + public override int MaxDamage => 10; + + 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 LesserExplosionPotion(Serial serial) : base(serial) - { - } - - public override int MinDamage => 5; - public override int MaxDamage => 10; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Heal Potions/BaseHealPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Heal Potions/BaseHealPotion.cs index 0792552e6..adf8b670a 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Heal Potions/BaseHealPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Heal Potions/BaseHealPotion.cs @@ -4,76 +4,83 @@ using Server.Network; namespace Server.Items { - public abstract class BaseHealPotion : BasePotion - { - public BaseHealPotion(PotionEffect effect) : base(0xF0C, effect) + public abstract class BaseHealPotion : BasePotion { - } - - public BaseHealPotion(Serial serial) : base(serial) - { - } - - public abstract int MinHeal { get; } - public abstract int MaxHeal { get; } - public abstract double Delay { get; } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public void DoHeal(Mobile from) - { - int min = Scale(from, MinHeal); - int max = Scale(from, MaxHeal); - - from.Heal(Utility.RandomMinMax(min, max)); - } - - public override void Drink(Mobile from) - { - if (from.Hits < from.HitsMax) - { - if (from.Poisoned || MortalStrike.IsWounded(from)) + public BaseHealPotion(PotionEffect effect) : base(0xF0C, effect) { - from.LocalOverheadMessage(MessageType.Regular, 0x22, - 1005000); // You can not heal yourself in your current state. } - else + + public BaseHealPotion(Serial serial) : base(serial) { - if (from.BeginAction()) - { - DoHeal(from); - - PlayDrinkEffect(from); - - if (!DuelContext.IsFreeConsume(from)) - Consume(); - - Timer.DelayCall(TimeSpan.FromSeconds(Delay), from.EndAction); - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x22, - 500235); // You must wait 10 seconds before using another healing potion. - } } - } - else - { - from.SendLocalizedMessage( - 1049547); // You decide against drinking this potion, as you are already at full health. - } + + public abstract int MinHeal { get; } + public abstract int MaxHeal { get; } + public abstract double Delay { get; } + + 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 void DoHeal(Mobile from) + { + var min = Scale(from, MinHeal); + var max = Scale(from, MaxHeal); + + from.Heal(Utility.RandomMinMax(min, max)); + } + + public override void Drink(Mobile from) + { + if (from.Hits < from.HitsMax) + { + if (from.Poisoned || MortalStrike.IsWounded(from)) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x22, + 1005000 + ); // You can not heal yourself in your current state. + } + else + { + if (from.BeginAction()) + { + DoHeal(from); + + PlayDrinkEffect(from); + + if (!DuelContext.IsFreeConsume(from)) + Consume(); + + Timer.DelayCall(TimeSpan.FromSeconds(Delay), from.EndAction); + } + else + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x22, + 500235 + ); // You must wait 10 seconds before using another healing potion. + } + } + } + else + { + from.SendLocalizedMessage( + 1049547 + ); // You decide against drinking this potion, as you are already at full health. + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Heal Potions/GreaterHealPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Heal Potions/GreaterHealPotion.cs index 0b63ebd5d..d10cd3b54 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Heal Potions/GreaterHealPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Heal Potions/GreaterHealPotion.cs @@ -1,32 +1,32 @@ namespace Server.Items { - public class GreaterHealPotion : BaseHealPotion - { - [Constructible] - public GreaterHealPotion() : base(PotionEffect.HealGreater) + public class GreaterHealPotion : BaseHealPotion { + [Constructible] + public GreaterHealPotion() : base(PotionEffect.HealGreater) + { + } + + public GreaterHealPotion(Serial serial) : base(serial) + { + } + + public override int MinHeal => Core.AOS ? 20 : 9; + public override int MaxHeal => Core.AOS ? 25 : 30; + public override double Delay => 10.0; + + 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 GreaterHealPotion(Serial serial) : base(serial) - { - } - - public override int MinHeal => Core.AOS ? 20 : 9; - public override int MaxHeal => Core.AOS ? 25 : 30; - public override double Delay => 10.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Heal Potions/HealPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Heal Potions/HealPotion.cs index 787077973..c0a84fc02 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Heal Potions/HealPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Heal Potions/HealPotion.cs @@ -1,32 +1,32 @@ namespace Server.Items { - public class HealPotion : BaseHealPotion - { - [Constructible] - public HealPotion() : base(PotionEffect.Heal) + public class HealPotion : BaseHealPotion { + [Constructible] + public HealPotion() : base(PotionEffect.Heal) + { + } + + public HealPotion(Serial serial) : base(serial) + { + } + + public override int MinHeal => Core.AOS ? 13 : 6; + public override int MaxHeal => Core.AOS ? 16 : 20; + public override double Delay => Core.AOS ? 8.0 : 10.0; + + 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 HealPotion(Serial serial) : base(serial) - { - } - - public override int MinHeal => Core.AOS ? 13 : 6; - public override int MaxHeal => Core.AOS ? 16 : 20; - public override double Delay => Core.AOS ? 8.0 : 10.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Heal Potions/LesserHealPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Heal Potions/LesserHealPotion.cs index 9aa705bee..fa0df768a 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Heal Potions/LesserHealPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Heal Potions/LesserHealPotion.cs @@ -1,32 +1,32 @@ namespace Server.Items { - public class LesserHealPotion : BaseHealPotion - { - [Constructible] - public LesserHealPotion() : base(PotionEffect.HealLesser) + public class LesserHealPotion : BaseHealPotion { + [Constructible] + public LesserHealPotion() : base(PotionEffect.HealLesser) + { + } + + public LesserHealPotion(Serial serial) : base(serial) + { + } + + public override int MinHeal => Core.AOS ? 6 : 3; + public override int MaxHeal => Core.AOS ? 8 : 10; + public override double Delay => Core.AOS ? 3.0 : 10.0; + + 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 LesserHealPotion(Serial serial) : base(serial) - { - } - - public override int MinHeal => Core.AOS ? 6 : 3; - public override int MaxHeal => Core.AOS ? 8 : 10; - public override double Delay => Core.AOS ? 3.0 : 10.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/InvisibilityPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/InvisibilityPotion.cs index 53bc97fa3..97f588dc3 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/InvisibilityPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/InvisibilityPotion.cs @@ -3,85 +3,90 @@ using System.Collections.Generic; namespace Server.Items { - public class InvisibilityPotion : BasePotion - { - private static readonly Dictionary m_Table = new Dictionary(); - - [Constructible] - public InvisibilityPotion() : base(0xF0A, PotionEffect.Invisibility) => Hue = 0x48D; - - public InvisibilityPotion(Serial serial) : base(serial) + public class InvisibilityPotion : BasePotion { + private static readonly Dictionary m_Table = new Dictionary(); + + [Constructible] + public InvisibilityPotion() : base(0xF0A, PotionEffect.Invisibility) => Hue = 0x48D; + + public InvisibilityPotion(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072941; // Potion of Invisibility + + public override void Drink(Mobile from) + { + if (from.Hidden) + { + from.SendLocalizedMessage(1073185); // You are already unseen. + return; + } + + if (HasTimer(from)) + { + from.SendLocalizedMessage(1073186); // An invisibility potion is already taking effect on your person. + return; + } + + Consume(); + m_Table[from] = Timer.DelayCall(TimeSpan.FromSeconds(2), Hide, from); + PlayDrinkEffect(from); + } + + public static void Hide(Mobile m) + { + Effects.SendLocationParticles( + EffectItem.Create(new Point3D(m.X, m.Y, m.Z + 16), m.Map, EffectItem.DefaultDuration), + 0x376A, + 10, + 15, + 5045 + ); + m.PlaySound(0x3C4); + + m.Hidden = true; + + BuffInfo.RemoveBuff(m, BuffIcon.HidingAndOrStealth); + BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Invisibility, 1075825)); // Invisibility/Invisible + + RemoveTimer(m); + + Timer.DelayCall(TimeSpan.FromSeconds(30), EndHide, m); + } + + public static void EndHide(Mobile m) + { + m.RevealingAction(); + RemoveTimer(m); + } + + public static bool HasTimer(Mobile m) => m_Table.ContainsKey(m); + + public static void RemoveTimer(Mobile m, bool interrupted = false) + { + if (m_Table.TryGetValue(m, out var timer)) + { + if (interrupted) + m.SendLocalizedMessage(1073187); // The invisibility effect is interrupted. + timer.Stop(); + m_Table.Remove(m); + } + } + + 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 int LabelNumber => 1072941; // Potion of Invisibility - - public override void Drink(Mobile from) - { - if (from.Hidden) - { - from.SendLocalizedMessage(1073185); // You are already unseen. - return; - } - - if (HasTimer(from)) - { - from.SendLocalizedMessage(1073186); // An invisibility potion is already taking effect on your person. - return; - } - - Consume(); - m_Table[from] = Timer.DelayCall(TimeSpan.FromSeconds(2), Hide, from); - PlayDrinkEffect(from); - } - - public static void Hide(Mobile m) - { - Effects.SendLocationParticles( - EffectItem.Create(new Point3D(m.X, m.Y, m.Z + 16), m.Map, EffectItem.DefaultDuration), 0x376A, 10, 15, 5045); - m.PlaySound(0x3C4); - - m.Hidden = true; - - BuffInfo.RemoveBuff(m, BuffIcon.HidingAndOrStealth); - BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Invisibility, 1075825)); // Invisibility/Invisible - - RemoveTimer(m); - - Timer.DelayCall(TimeSpan.FromSeconds(30), EndHide, m); - } - - public static void EndHide(Mobile m) - { - m.RevealingAction(); - RemoveTimer(m); - } - - public static bool HasTimer(Mobile m) => m_Table.ContainsKey(m); - - public static void RemoveTimer(Mobile m, bool interrupted = false) - { - if (m_Table.TryGetValue(m, out Timer timer)) - { - if (interrupted) - m.SendLocalizedMessage(1073187); // The invisibility effect is interrupted. - timer.Stop(); - m_Table.Remove(m); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/NightSight.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/NightSight.cs index 4a40f35a9..9ef046df1 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/NightSight.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/NightSight.cs @@ -2,50 +2,50 @@ using Server.Engines.ConPVP; namespace Server.Items { - public class NightSightPotion : BasePotion - { - [Constructible] - public NightSightPotion() : base(0xF06, PotionEffect.Nightsight) + public class NightSightPotion : BasePotion { + [Constructible] + public NightSightPotion() : base(0xF06, PotionEffect.Nightsight) + { + } + + public NightSightPotion(Serial serial) : base(serial) + { + } + + 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 Drink(Mobile from) + { + if (from.BeginAction()) + { + new LightCycle.NightSightTimer(from).Start(); + from.LightLevel = LightCycle.DungeonLevel / 2; + + from.FixedParticles(0x376A, 9, 32, 5007, EffectLayer.Waist); + from.PlaySound(0x1E3); + + PlayDrinkEffect(from); + + if (!DuelContext.IsFreeConsume(from)) + Consume(); + } + else + { + from.SendMessage("You already have nightsight."); + } + } } - - public NightSightPotion(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Drink(Mobile from) - { - if (from.BeginAction()) - { - new LightCycle.NightSightTimer(from).Start(); - from.LightLevel = LightCycle.DungeonLevel / 2; - - from.FixedParticles(0x376A, 9, 32, 5007, EffectLayer.Waist); - from.PlaySound(0x1E3); - - PlayDrinkEffect(from); - - if (!DuelContext.IsFreeConsume(from)) - Consume(); - } - else - { - from.SendMessage("You already have nightsight."); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/ParasiticPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/ParasiticPotion.cs index df870e104..455ea3eaf 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/ParasiticPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/ParasiticPotion.cs @@ -1,34 +1,34 @@ namespace Server.Items { - public class ParasiticPotion : BasePoisonPotion - { - [Constructible] - public ParasiticPotion() : base(PotionEffect.Parasitic) => Hue = 0x17C; - - public ParasiticPotion(Serial serial) : base(serial) + public class ParasiticPotion : BasePoisonPotion { + [Constructible] + public ParasiticPotion() : base(PotionEffect.Parasitic) => Hue = 0x17C; + + public ParasiticPotion(Serial serial) : base(serial) + { + } + + /* public override Poison Poison => Poison.Darkglow; MUST be restored when prerequisites are done */ + public override Poison Poison => Poison.Greater; + + public override double MinPoisoningSkill => 95.0; + public override double MaxPoisoningSkill => 100.0; + + public override int LabelNumber => 1072848; // Parasitic Poison + + 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 Poison Poison => Poison.Darkglow; MUST be restored when prerequisites are done */ - public override Poison Poison => Poison.Greater; - - public override double MinPoisoningSkill => 95.0; - public override double MaxPoisoningSkill => 100.0; - - public override int LabelNumber => 1072848; // Parasitic Poison - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Poison Potions/BasePoisonPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Poison Potions/BasePoisonPotion.cs index 645ca93b8..6fd8f1882 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Poison Potions/BasePoisonPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Poison Potions/BasePoisonPotion.cs @@ -2,48 +2,48 @@ using Server.Engines.ConPVP; namespace Server.Items { - public abstract class BasePoisonPotion : BasePotion - { - public BasePoisonPotion(PotionEffect effect) : base(0xF0A, effect) + public abstract class BasePoisonPotion : BasePotion { + public BasePoisonPotion(PotionEffect effect) : base(0xF0A, effect) + { + } + + public BasePoisonPotion(Serial serial) : base(serial) + { + } + + public abstract Poison Poison { get; } + + public abstract double MinPoisoningSkill { get; } + public abstract double MaxPoisoningSkill { get; } + + 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 void DoPoison(Mobile from) + { + from.ApplyPoison(from, Poison); + } + + public override void Drink(Mobile from) + { + DoPoison(from); + + PlayDrinkEffect(from); + + if (!DuelContext.IsFreeConsume(from)) + Consume(); + } } - - public BasePoisonPotion(Serial serial) : base(serial) - { - } - - public abstract Poison Poison { get; } - - public abstract double MinPoisoningSkill { get; } - public abstract double MaxPoisoningSkill { get; } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public void DoPoison(Mobile from) - { - from.ApplyPoison(from, Poison); - } - - public override void Drink(Mobile from) - { - DoPoison(from); - - PlayDrinkEffect(from); - - if (!DuelContext.IsFreeConsume(from)) - Consume(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Poison Potions/DeadlyPoisonPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Poison Potions/DeadlyPoisonPotion.cs index 736b30e93..3ebfc356c 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Poison Potions/DeadlyPoisonPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Poison Potions/DeadlyPoisonPotion.cs @@ -1,33 +1,33 @@ namespace Server.Items { - public class DeadlyPoisonPotion : BasePoisonPotion - { - [Constructible] - public DeadlyPoisonPotion() : base(PotionEffect.PoisonDeadly) + public class DeadlyPoisonPotion : BasePoisonPotion { + [Constructible] + public DeadlyPoisonPotion() : base(PotionEffect.PoisonDeadly) + { + } + + public DeadlyPoisonPotion(Serial serial) : base(serial) + { + } + + public override Poison Poison => Poison.Deadly; + + public override double MinPoisoningSkill => 95.0; + public override double MaxPoisoningSkill => 100.0; + + 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 DeadlyPoisonPotion(Serial serial) : base(serial) - { - } - - public override Poison Poison => Poison.Deadly; - - public override double MinPoisoningSkill => 95.0; - public override double MaxPoisoningSkill => 100.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Poison Potions/GreaterPoisonPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Poison Potions/GreaterPoisonPotion.cs index 9ea6722ac..ac7eca634 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Poison Potions/GreaterPoisonPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Poison Potions/GreaterPoisonPotion.cs @@ -1,33 +1,33 @@ namespace Server.Items { - public class GreaterPoisonPotion : BasePoisonPotion - { - [Constructible] - public GreaterPoisonPotion() : base(PotionEffect.PoisonGreater) + public class GreaterPoisonPotion : BasePoisonPotion { + [Constructible] + public GreaterPoisonPotion() : base(PotionEffect.PoisonGreater) + { + } + + public GreaterPoisonPotion(Serial serial) : base(serial) + { + } + + public override Poison Poison => Poison.Greater; + + public override double MinPoisoningSkill => 60.0; + public override double MaxPoisoningSkill => 100.0; + + 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 GreaterPoisonPotion(Serial serial) : base(serial) - { - } - - public override Poison Poison => Poison.Greater; - - public override double MinPoisoningSkill => 60.0; - public override double MaxPoisoningSkill => 100.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Poison Potions/LesserPoisonPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Poison Potions/LesserPoisonPotion.cs index 8f966ab0a..63df6f97c 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Poison Potions/LesserPoisonPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Poison Potions/LesserPoisonPotion.cs @@ -1,33 +1,33 @@ namespace Server.Items { - public class LesserPoisonPotion : BasePoisonPotion - { - [Constructible] - public LesserPoisonPotion() : base(PotionEffect.PoisonLesser) + public class LesserPoisonPotion : BasePoisonPotion { + [Constructible] + public LesserPoisonPotion() : base(PotionEffect.PoisonLesser) + { + } + + public LesserPoisonPotion(Serial serial) : base(serial) + { + } + + public override Poison Poison => Poison.Lesser; + + public override double MinPoisoningSkill => 0.0; + public override double MaxPoisoningSkill => 60.0; + + 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 LesserPoisonPotion(Serial serial) : base(serial) - { - } - - public override Poison Poison => Poison.Lesser; - - public override double MinPoisoningSkill => 0.0; - public override double MaxPoisoningSkill => 60.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Poison Potions/PoisonPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Poison Potions/PoisonPotion.cs index 8b687d118..6643b05a3 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Poison Potions/PoisonPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Poison Potions/PoisonPotion.cs @@ -1,33 +1,33 @@ namespace Server.Items { - public class PoisonPotion : BasePoisonPotion - { - [Constructible] - public PoisonPotion() : base(PotionEffect.Poison) + public class PoisonPotion : BasePoisonPotion { + [Constructible] + public PoisonPotion() : base(PotionEffect.Poison) + { + } + + public PoisonPotion(Serial serial) : base(serial) + { + } + + public override Poison Poison => Poison.Regular; + + public override double MinPoisoningSkill => 30.0; + public override double MaxPoisoningSkill => 70.0; + + 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 PoisonPotion(Serial serial) : base(serial) - { - } - - public override Poison Poison => Poison.Regular; - - public override double MinPoisoningSkill => 30.0; - public override double MaxPoisoningSkill => 70.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Refresh Potions/BaseRefreshPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Refresh Potions/BaseRefreshPotion.cs index 9006f98ff..8e4a03d01 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Refresh Potions/BaseRefreshPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Refresh Potions/BaseRefreshPotion.cs @@ -2,47 +2,47 @@ using Server.Engines.ConPVP; namespace Server.Items { - public abstract class BaseRefreshPotion : BasePotion - { - public BaseRefreshPotion(PotionEffect effect) : base(0xF0B, effect) + public abstract class BaseRefreshPotion : BasePotion { + public BaseRefreshPotion(PotionEffect effect) : base(0xF0B, effect) + { + } + + public BaseRefreshPotion(Serial serial) : base(serial) + { + } + + public abstract double Refresh { get; } + + 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 Drink(Mobile from) + { + if (from.Stam < from.StamMax) + { + from.Stam += Scale(from, (int)(Refresh * from.StamMax)); + + PlayDrinkEffect(from); + + if (!DuelContext.IsFreeConsume(from)) + Consume(); + } + else + { + from.SendMessage("You decide against drinking this potion, as you are already at full stamina."); + } + } } - - public BaseRefreshPotion(Serial serial) : base(serial) - { - } - - public abstract double Refresh { get; } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Drink(Mobile from) - { - if (from.Stam < from.StamMax) - { - from.Stam += Scale(from, (int)(Refresh * from.StamMax)); - - PlayDrinkEffect(from); - - if (!DuelContext.IsFreeConsume(from)) - Consume(); - } - else - { - from.SendMessage("You decide against drinking this potion, as you are already at full stamina."); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Refresh Potions/RefreshPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Refresh Potions/RefreshPotion.cs index 8a01c6857..69045a167 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Refresh Potions/RefreshPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Refresh Potions/RefreshPotion.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class RefreshPotion : BaseRefreshPotion - { - [Constructible] - public RefreshPotion() : base(PotionEffect.Refresh) + public class RefreshPotion : BaseRefreshPotion { + [Constructible] + public RefreshPotion() : base(PotionEffect.Refresh) + { + } + + public RefreshPotion(Serial serial) : base(serial) + { + } + + public override double Refresh => 0.25; + + 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 RefreshPotion(Serial serial) : base(serial) - { - } - - public override double Refresh => 0.25; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Refresh Potions/TotalRefreshPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Refresh Potions/TotalRefreshPotion.cs index 2fba59e2b..b87b124f5 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Refresh Potions/TotalRefreshPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Refresh Potions/TotalRefreshPotion.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class TotalRefreshPotion : BaseRefreshPotion - { - [Constructible] - public TotalRefreshPotion() : base(PotionEffect.RefreshTotal) + public class TotalRefreshPotion : BaseRefreshPotion { + [Constructible] + public TotalRefreshPotion() : base(PotionEffect.RefreshTotal) + { + } + + public TotalRefreshPotion(Serial serial) : base(serial) + { + } + + public override double Refresh => 1.0; + + 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 TotalRefreshPotion(Serial serial) : base(serial) - { - } - - public override double Refresh => 1.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Strength Potions/BaseStrengthPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Strength Potions/BaseStrengthPotion.cs index d96c0e5cd..f4cbf128b 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Strength Potions/BaseStrengthPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Strength Potions/BaseStrengthPotion.cs @@ -4,56 +4,56 @@ using Server.Spells; namespace Server.Items { - public abstract class BaseStrengthPotion : BasePotion - { - public BaseStrengthPotion(PotionEffect effect) : base(0xF09, effect) + public abstract class BaseStrengthPotion : BasePotion { + public BaseStrengthPotion(PotionEffect effect) : base(0xF09, effect) + { + } + + public BaseStrengthPotion(Serial serial) : base(serial) + { + } + + public abstract int StrOffset { get; } + public abstract TimeSpan Duration { get; } + + 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 bool DoStrength(Mobile from) + { + // TODO: Verify scaled; is it offset, duration, or both? + if (SpellHelper.AddStatOffset(from, StatType.Str, Scale(from, StrOffset), Duration)) + { + from.FixedEffect(0x375A, 10, 15); + from.PlaySound(0x1E7); + return true; + } + + from.SendLocalizedMessage(502173); // You are already under a similar effect. + return false; + } + + public override void Drink(Mobile from) + { + if (DoStrength(from)) + { + PlayDrinkEffect(from); + + if (!DuelContext.IsFreeConsume(from)) + Consume(); + } + } } - - public BaseStrengthPotion(Serial serial) : base(serial) - { - } - - public abstract int StrOffset { get; } - public abstract TimeSpan Duration { get; } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public bool DoStrength(Mobile from) - { - // TODO: Verify scaled; is it offset, duration, or both? - if (SpellHelper.AddStatOffset(from, StatType.Str, Scale(from, StrOffset), Duration)) - { - from.FixedEffect(0x375A, 10, 15); - from.PlaySound(0x1E7); - return true; - } - - from.SendLocalizedMessage(502173); // You are already under a similar effect. - return false; - } - - public override void Drink(Mobile from) - { - if (DoStrength(from)) - { - PlayDrinkEffect(from); - - if (!DuelContext.IsFreeConsume(from)) - Consume(); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Strength Potions/GreaterStrengthPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Strength Potions/GreaterStrengthPotion.cs index db1a4e1eb..2dc250429 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Strength Potions/GreaterStrengthPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Strength Potions/GreaterStrengthPotion.cs @@ -2,32 +2,32 @@ using System; namespace Server.Items { - public class GreaterStrengthPotion : BaseStrengthPotion - { - [Constructible] - public GreaterStrengthPotion() : base(PotionEffect.StrengthGreater) + public class GreaterStrengthPotion : BaseStrengthPotion { + [Constructible] + public GreaterStrengthPotion() : base(PotionEffect.StrengthGreater) + { + } + + public GreaterStrengthPotion(Serial serial) : base(serial) + { + } + + public override int StrOffset => 20; + public override TimeSpan Duration => TimeSpan.FromMinutes(2.0); + + 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 GreaterStrengthPotion(Serial serial) : base(serial) - { - } - - public override int StrOffset => 20; - public override TimeSpan Duration => TimeSpan.FromMinutes(2.0); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Potions/Strength Potions/StrengthPotion.cs b/Projects/UOContent/Items/Skill Items/Magical/Potions/Strength Potions/StrengthPotion.cs index 25a976881..50ba010a5 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Potions/Strength Potions/StrengthPotion.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Potions/Strength Potions/StrengthPotion.cs @@ -2,32 +2,32 @@ using System; namespace Server.Items { - public class StrengthPotion : BaseStrengthPotion - { - [Constructible] - public StrengthPotion() : base(PotionEffect.Strength) + public class StrengthPotion : BaseStrengthPotion { + [Constructible] + public StrengthPotion() : base(PotionEffect.Strength) + { + } + + public StrengthPotion(Serial serial) : base(serial) + { + } + + public override int StrOffset => 10; + public override TimeSpan Duration => TimeSpan.FromMinutes(2.0); + + 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 StrengthPotion(Serial serial) : base(serial) - { - } - - public override int StrOffset => 10; - public override TimeSpan Duration => TimeSpan.FromMinutes(2.0); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Magical/Runebook.cs b/Projects/UOContent/Items/Skill Items/Magical/Runebook.cs index 35c5cc158..26256b3f0 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Runebook.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Runebook.cs @@ -9,464 +9,466 @@ using Server.Network; namespace Server.Items { - public class Runebook : Item, ISecurable, ICraftable - { - public static readonly TimeSpan UseDelay = TimeSpan.FromSeconds(7.0); - private Mobile m_Crafter; - private int m_DefaultIndex; - - private string m_Description; - - private BookQuality m_Quality; - - [Constructible] - public Runebook() : this(Core.SE ? 12 : 6) + public class Runebook : Item, ISecurable, ICraftable { - } + public static readonly TimeSpan UseDelay = TimeSpan.FromSeconds(7.0); + private Mobile m_Crafter; + private int m_DefaultIndex; - [Constructible] - public Runebook(int maxCharges) : base(Core.AOS ? 0x22C5 : 0xEFA) - { - Weight = Core.SE ? 1.0 : 3.0; - LootType = LootType.Blessed; - Hue = 0x461; + private string m_Description; - Layer = Core.AOS ? Layer.Invalid : Layer.OneHanded; + private BookQuality m_Quality; - Entries = new List(); - - MaxCharges = maxCharges; - - m_DefaultIndex = -1; - - Level = SecureLevel.CoOwners; - } - - public Runebook(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public BookQuality Quality - { - get => m_Quality; - set - { - m_Quality = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime NextUse { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Crafter - { - get => m_Crafter; - set - { - m_Crafter = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public string Description - { - get => m_Description; - set - { - m_Description = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int CurCharges { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxCharges { get; set; } - - public List Openers { get; set; } = new List(); - - public override int LabelNumber => 1041267; // runebook - - public List Entries { get; private set; } - - public RunebookEntry Default - { - get - { - if (m_DefaultIndex >= 0 && m_DefaultIndex < Entries.Count) - return Entries[m_DefaultIndex]; - - return null; - } - set - { - if (value == null) - m_DefaultIndex = -1; - else - m_DefaultIndex = Entries.IndexOf(value); - } - } - - public override bool DisplayLootType => Core.AOS; - - public int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, - CraftItem craftItem, int resHue) - { - int charges = 5 + quality + (int)(from.Skills.Inscribe.Value / 30); - - if (charges > 10) - charges = 10; - - MaxCharges = Core.SE ? charges * 2 : charges; - - if (makersMark) - Crafter = from; - - m_Quality = (BookQuality)(quality - 1); - - return quality; - } - - [CommandProperty(AccessLevel.GameMaster)] - public SecureLevel Level { get; set; } - - public override bool AllowEquippedCast(Mobile from) => true; - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - SetSecureLevelEntry.AddTo(from, this, list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(3); - - writer.Write((byte)m_Quality); - - writer.Write(m_Crafter); - - writer.Write((int)Level); - - writer.Write(Entries.Count); - - for (int i = 0; i < Entries.Count; ++i) - Entries[i].Serialize(writer); - - writer.Write(m_Description); - writer.Write(CurCharges); - writer.Write(MaxCharges); - writer.Write(m_DefaultIndex); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - LootType = LootType.Blessed; - - if (Core.SE && Weight == 3.0) - Weight = 1.0; - - int version = reader.ReadInt(); - - switch (version) - { - case 3: - { - m_Quality = (BookQuality)reader.ReadByte(); - goto case 2; - } - case 2: - { - m_Crafter = reader.ReadMobile(); - goto case 1; - } - case 1: - { - Level = (SecureLevel)reader.ReadInt(); - goto case 0; - } - case 0: - { - int count = reader.ReadInt(); - - Entries = new List(count); - - for (int i = 0; i < count; ++i) - Entries.Add(new RunebookEntry(reader)); - - m_Description = reader.ReadString(); - CurCharges = reader.ReadInt(); - MaxCharges = reader.ReadInt(); - m_DefaultIndex = reader.ReadInt(); - - break; - } - } - } - - public void DropRune(Mobile from, RunebookEntry e, int index) - { - if (m_DefaultIndex > index) - m_DefaultIndex -= 1; - else if (m_DefaultIndex == index) - m_DefaultIndex = -1; - - Entries.RemoveAt(index); - - RecallRune rune = new RecallRune(); - - rune.Target = e.Location; - rune.TargetMap = e.Map; - rune.Description = e.Description; - rune.House = e.House; - rune.Marked = true; - - from.AddToBackpack(rune); - - from.SendLocalizedMessage(502421); // You have removed the rune. - } - - public bool IsOpen(Mobile toCheck) - { - NetState ns = toCheck.NetState; - - if (ns == null) - return false; - - foreach (Gump gump in ns.Gumps) - if (gump is RunebookGump bookGump && bookGump.Book == this) - return true; - - return false; - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_Quality == BookQuality.Exceptional) - list.Add(1063341); // exceptional - - if (m_Crafter != null) - list.Add(1050043, m_Crafter.Name); // crafted by ~1_NAME~ - - if (!string.IsNullOrEmpty(m_Description)) - list.Add(m_Description); - } - - public override bool OnDragLift(Mobile from) - { - if (from.HasGump()) - { - from.SendLocalizedMessage(500169); // You cannot pick that up. - return false; - } - - foreach (Mobile m in Openers) - if (IsOpen(m)) - m.CloseGump(); - - Openers.Clear(); - - return true; - } - - public override void OnSingleClick(Mobile from) - { - if (m_Description?.Length > 0) - LabelTo(from, m_Description); - - base.OnSingleClick(from); - - if (m_Crafter != null) - LabelTo(from, 1050043, m_Crafter.Name); - } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(GetWorldLocation(), Core.ML ? 3 : 1) && CheckAccess(from)) - { - if (RootParent is BaseCreature) + [Constructible] + public Runebook() : this(Core.SE ? 12 : 6) { - from.SendLocalizedMessage(502402); // That is inaccessible. - return; } - if (DateTime.UtcNow < NextUse) + [Constructible] + public Runebook(int maxCharges) : base(Core.AOS ? 0x22C5 : 0xEFA) { - from.SendLocalizedMessage(502406); // This book needs time to recharge. - return; + Weight = Core.SE ? 1.0 : 3.0; + LootType = LootType.Blessed; + Hue = 0x461; + + Layer = Core.AOS ? Layer.Invalid : Layer.OneHanded; + + Entries = new List(); + + MaxCharges = maxCharges; + + m_DefaultIndex = -1; + + Level = SecureLevel.CoOwners; } - from.CloseGump(); - from.SendGump(new RunebookGump(from, this)); - - Openers.Add(from); - } - } - - public virtual void OnTravel() - { - if (!Core.SA) - NextUse = DateTime.UtcNow + UseDelay; - } - - public override void OnAfterDuped(Item newItem) - { - if (!(newItem is Runebook book)) - return; - - book.Entries = new List(); - - for (int i = 0; i < Entries.Count; i++) - { - RunebookEntry entry = Entries[i]; - - book.Entries.Add(new RunebookEntry(entry.Location, entry.Map, entry.Description, entry.House)); - } - } - - public bool CheckAccess(Mobile m) - { - if (!IsLockedDown || m.AccessLevel >= AccessLevel.GameMaster) - return true; - - BaseHouse house = BaseHouse.FindHouseAt(this); - - return (house?.IsAosRules != true || (house.Public && !house.IsBanned(m)) || house.HasAccess(m)) && - house?.HasSecureAccess(m, Level) == true; - } - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (dropped is RecallRune rune) - { - if (IsLockedDown && from.AccessLevel < AccessLevel.GameMaster) + public Runebook(Serial serial) : base(serial) { - from.SendLocalizedMessage(502413, null, 0x35); // That cannot be done while the book is locked down. } - else if (IsOpen(from)) + + [CommandProperty(AccessLevel.GameMaster)] + public BookQuality Quality { - from.SendLocalizedMessage(1005571); // You cannot place objects in the book while viewing the contents. + get => m_Quality; + set + { + m_Quality = value; + InvalidateProperties(); + } } - else if (Entries.Count < 16) + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime NextUse { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Crafter { - if (rune.Marked && rune.TargetMap != null) - { - Entries.Add(new RunebookEntry(rune.Target, rune.TargetMap, rune.Description, rune.House)); + get => m_Crafter; + set + { + m_Crafter = value; + InvalidateProperties(); + } + } - rune.Delete(); + [CommandProperty(AccessLevel.GameMaster)] + public string Description + { + get => m_Description; + set + { + m_Description = value; + InvalidateProperties(); + } + } - from.Send(new PlaySound(0x42, GetWorldLocation())); + [CommandProperty(AccessLevel.GameMaster)] + public int CurCharges { get; set; } - from.SendMessage(rune.Description?.Trim().IsNullOrDefault("(indescript)")); + [CommandProperty(AccessLevel.GameMaster)] + public int MaxCharges { get; set; } + + public List Openers { get; set; } = new List(); + + public override int LabelNumber => 1041267; // runebook + + public List Entries { get; private set; } + + public RunebookEntry Default + { + get + { + if (m_DefaultIndex >= 0 && m_DefaultIndex < Entries.Count) + return Entries[m_DefaultIndex]; + + return null; + } + set + { + if (value == null) + m_DefaultIndex = -1; + else + m_DefaultIndex = Entries.IndexOf(value); + } + } + + public override bool DisplayLootType => Core.AOS; + + public int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, + CraftItem craftItem, int resHue + ) + { + var charges = 5 + quality + (int)(from.Skills.Inscribe.Value / 30); + + if (charges > 10) + charges = 10; + + MaxCharges = Core.SE ? charges * 2 : charges; + + if (makersMark) + Crafter = from; + + m_Quality = (BookQuality)(quality - 1); + + return quality; + } + + [CommandProperty(AccessLevel.GameMaster)] + public SecureLevel Level { get; set; } + + public override bool AllowEquippedCast(Mobile from) => true; + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + SetSecureLevelEntry.AddTo(from, this, list); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(3); + + writer.Write((byte)m_Quality); + + writer.Write(m_Crafter); + + writer.Write((int)Level); + + writer.Write(Entries.Count); + + for (var i = 0; i < Entries.Count; ++i) + Entries[i].Serialize(writer); + + writer.Write(m_Description); + writer.Write(CurCharges); + writer.Write(MaxCharges); + writer.Write(m_DefaultIndex); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + LootType = LootType.Blessed; + + if (Core.SE && Weight == 3.0) + Weight = 1.0; + + var version = reader.ReadInt(); + + switch (version) + { + case 3: + { + m_Quality = (BookQuality)reader.ReadByte(); + goto case 2; + } + case 2: + { + m_Crafter = reader.ReadMobile(); + goto case 1; + } + case 1: + { + Level = (SecureLevel)reader.ReadInt(); + goto case 0; + } + case 0: + { + var count = reader.ReadInt(); + + Entries = new List(count); + + for (var i = 0; i < count; ++i) + Entries.Add(new RunebookEntry(reader)); + + m_Description = reader.ReadString(); + CurCharges = reader.ReadInt(); + MaxCharges = reader.ReadInt(); + m_DefaultIndex = reader.ReadInt(); + + break; + } + } + } + + public void DropRune(Mobile from, RunebookEntry e, int index) + { + if (m_DefaultIndex > index) + m_DefaultIndex -= 1; + else if (m_DefaultIndex == index) + m_DefaultIndex = -1; + + Entries.RemoveAt(index); + + var rune = new RecallRune(); + + rune.Target = e.Location; + rune.TargetMap = e.Map; + rune.Description = e.Description; + rune.House = e.House; + rune.Marked = true; + + from.AddToBackpack(rune); + + from.SendLocalizedMessage(502421); // You have removed the rune. + } + + public bool IsOpen(Mobile toCheck) + { + var ns = toCheck.NetState; + + if (ns == null) + return false; + + foreach (var gump in ns.Gumps) + if (gump is RunebookGump bookGump && bookGump.Book == this) + return true; + + return false; + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_Quality == BookQuality.Exceptional) + list.Add(1063341); // exceptional + + if (m_Crafter != null) + list.Add(1050043, m_Crafter.Name); // crafted by ~1_NAME~ + + if (!string.IsNullOrEmpty(m_Description)) + list.Add(m_Description); + } + + public override bool OnDragLift(Mobile from) + { + if (from.HasGump()) + { + from.SendLocalizedMessage(500169); // You cannot pick that up. + return false; + } + + foreach (var m in Openers) + if (IsOpen(m)) + m.CloseGump(); + + Openers.Clear(); return true; - } - - from.SendLocalizedMessage(502409); // This rune does not have a marked location. } - else + + public override void OnSingleClick(Mobile from) { - from.SendLocalizedMessage(502401); // This runebook is full. + if (m_Description?.Length > 0) + LabelTo(from, m_Description); + + base.OnSingleClick(from); + + if (m_Crafter != null) + LabelTo(from, 1050043, m_Crafter.Name); } - } - else if (dropped is RecallScroll) - { - if (CurCharges < MaxCharges) + + public override void OnDoubleClick(Mobile from) { - from.Send(new PlaySound(0x249, GetWorldLocation())); + if (from.InRange(GetWorldLocation(), Core.ML ? 3 : 1) && CheckAccess(from)) + { + if (RootParent is BaseCreature) + { + from.SendLocalizedMessage(502402); // That is inaccessible. + return; + } - int amount = dropped.Amount; + if (DateTime.UtcNow < NextUse) + { + from.SendLocalizedMessage(502406); // This book needs time to recharge. + return; + } - if (amount > MaxCharges - CurCharges) - { - dropped.Consume(MaxCharges - CurCharges); - CurCharges = MaxCharges; - } - else - { - CurCharges += amount; - dropped.Delete(); + from.CloseGump(); + from.SendGump(new RunebookGump(from, this)); - return true; - } + Openers.Add(from); + } } - else + + public virtual void OnTravel() { - from.SendLocalizedMessage(502410); // This book already has the maximum amount of charges. + if (!Core.SA) + NextUse = DateTime.UtcNow + UseDelay; } - } - return false; + public override void OnAfterDuped(Item newItem) + { + if (!(newItem is Runebook book)) + return; + + book.Entries = new List(); + + for (var i = 0; i < Entries.Count; i++) + { + var entry = Entries[i]; + + book.Entries.Add(new RunebookEntry(entry.Location, entry.Map, entry.Description, entry.House)); + } + } + + public bool CheckAccess(Mobile m) + { + if (!IsLockedDown || m.AccessLevel >= AccessLevel.GameMaster) + return true; + + var house = BaseHouse.FindHouseAt(this); + + return (house?.IsAosRules != true || house.Public && !house.IsBanned(m) || house.HasAccess(m)) && + house?.HasSecureAccess(m, Level) == true; + } + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (dropped is RecallRune rune) + { + if (IsLockedDown && from.AccessLevel < AccessLevel.GameMaster) + { + from.SendLocalizedMessage(502413, null, 0x35); // That cannot be done while the book is locked down. + } + else if (IsOpen(from)) + { + from.SendLocalizedMessage(1005571); // You cannot place objects in the book while viewing the contents. + } + else if (Entries.Count < 16) + { + if (rune.Marked && rune.TargetMap != null) + { + Entries.Add(new RunebookEntry(rune.Target, rune.TargetMap, rune.Description, rune.House)); + + rune.Delete(); + + from.Send(new PlaySound(0x42, GetWorldLocation())); + + from.SendMessage(rune.Description?.Trim().IsNullOrDefault("(indescript)")); + + return true; + } + + from.SendLocalizedMessage(502409); // This rune does not have a marked location. + } + else + { + from.SendLocalizedMessage(502401); // This runebook is full. + } + } + else if (dropped is RecallScroll) + { + if (CurCharges < MaxCharges) + { + from.Send(new PlaySound(0x249, GetWorldLocation())); + + var amount = dropped.Amount; + + if (amount > MaxCharges - CurCharges) + { + dropped.Consume(MaxCharges - CurCharges); + CurCharges = MaxCharges; + } + else + { + CurCharges += amount; + dropped.Delete(); + + return true; + } + } + else + { + from.SendLocalizedMessage(502410); // This book already has the maximum amount of charges. + } + } + + return false; + } } - } - public class RunebookEntry - { - public RunebookEntry(Point3D loc, Map map, string desc, BaseHouse house = null) + public class RunebookEntry { - Location = loc; - Map = map; - Description = desc; - House = house; + public RunebookEntry(Point3D loc, Map map, string desc, BaseHouse house = null) + { + Location = loc; + Map = map; + Description = desc; + House = house; + } + + public RunebookEntry(IGenericReader reader) + { + int version = reader.ReadByte(); + + switch (version) + { + case 1: + { + House = reader.ReadItem() as BaseHouse; + goto case 0; + } + case 0: + { + Location = reader.ReadPoint3D(); + Map = reader.ReadMap(); + Description = reader.ReadString(); + + break; + } + } + } + + public Point3D Location { get; } + + public Map Map { get; } + + public string Description { get; } + + public BaseHouse House { get; } + + public void Serialize(IGenericWriter writer) + { + if (House?.Deleted == false) + { + writer.Write((byte)1); // version + + writer.Write(House); + } + else + { + writer.Write((byte)0); // version + } + + writer.Write(Location); + writer.Write(Map); + writer.Write(Description); + } } - - public RunebookEntry(IGenericReader reader) - { - int version = reader.ReadByte(); - - switch (version) - { - case 1: - { - House = reader.ReadItem() as BaseHouse; - goto case 0; - } - case 0: - { - Location = reader.ReadPoint3D(); - Map = reader.ReadMap(); - Description = reader.ReadString(); - - break; - } - } - } - - public Point3D Location { get; } - - public Map Map { get; } - - public string Description { get; } - - public BaseHouse House { get; } - - public void Serialize(IGenericWriter writer) - { - if (House?.Deleted == false) - { - writer.Write((byte)1); // version - - writer.Write(House); - } - else - { - writer.Write((byte)0); // version - } - - writer.Write(Location); - writer.Write(Map); - writer.Write(Description); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/EarthquakeScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/EarthquakeScroll.cs index f6d03d3f5..68233dcd1 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/EarthquakeScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/EarthquakeScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class EarthquakeScroll : SpellScroll - { - [Constructible] - public EarthquakeScroll(int amount = 1) : base(56, 0x1F65, amount) + public class EarthquakeScroll : SpellScroll { + [Constructible] + public EarthquakeScroll(int amount = 1) : base(56, 0x1F65, amount) + { + } + + public EarthquakeScroll(Serial serial) : base(serial) + { + } + + 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 EarthquakeScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/EnergyVortexScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/EnergyVortexScroll.cs index 3edcd887b..143d94105 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/EnergyVortexScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/EnergyVortexScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class EnergyVortexScroll : SpellScroll - { - [Constructible] - public EnergyVortexScroll(int amount = 1) : base(57, 0x1F66, amount) + public class EnergyVortexScroll : SpellScroll { + [Constructible] + public EnergyVortexScroll(int amount = 1) : base(57, 0x1F66, amount) + { + } + + public EnergyVortexScroll(Serial serial) : base(serial) + { + } + + 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 EnergyVortexScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/ResurrectionScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/ResurrectionScroll.cs index 9d65e4f58..26d7d07a8 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/ResurrectionScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/ResurrectionScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class ResurrectionScroll : SpellScroll - { - [Constructible] - public ResurrectionScroll(int amount = 1) : base(58, 0x1F67, amount) + public class ResurrectionScroll : SpellScroll { + [Constructible] + public ResurrectionScroll(int amount = 1) : base(58, 0x1F67, amount) + { + } + + public ResurrectionScroll(Serial serial) : base(serial) + { + } + + 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 ResurrectionScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/SummonAirElementalScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/SummonAirElementalScroll.cs index 4e1c601f5..398e78007 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/SummonAirElementalScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/SummonAirElementalScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class SummonAirElementalScroll : SpellScroll - { - [Constructible] - public SummonAirElementalScroll(int amount = 1) : base(59, 0x1F68, amount) + public class SummonAirElementalScroll : SpellScroll { + [Constructible] + public SummonAirElementalScroll(int amount = 1) : base(59, 0x1F68, amount) + { + } + + public SummonAirElementalScroll(Serial serial) : base(serial) + { + } + + 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 SummonAirElementalScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/SummonDaemonScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/SummonDaemonScroll.cs index cfd3da6d6..43f7fcece 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/SummonDaemonScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/SummonDaemonScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class SummonDaemonScroll : SpellScroll - { - [Constructible] - public SummonDaemonScroll(int amount = 1) : base(60, 0x1F69, amount) + public class SummonDaemonScroll : SpellScroll { + [Constructible] + public SummonDaemonScroll(int amount = 1) : base(60, 0x1F69, amount) + { + } + + public SummonDaemonScroll(Serial serial) : base(serial) + { + } + + 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 SummonDaemonScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/SummonEarthElementalScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/SummonEarthElementalScroll.cs index a2c1c4230..3175ce43c 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/SummonEarthElementalScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/SummonEarthElementalScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class SummonEarthElementalScroll : SpellScroll - { - [Constructible] - public SummonEarthElementalScroll(int amount = 1) : base(61, 0x1F6A, amount) + public class SummonEarthElementalScroll : SpellScroll { + [Constructible] + public SummonEarthElementalScroll(int amount = 1) : base(61, 0x1F6A, amount) + { + } + + public SummonEarthElementalScroll(Serial serial) : base(serial) + { + } + + 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 SummonEarthElementalScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/SummonFireElementalScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/SummonFireElementalScroll.cs index 3b858b25c..54338b4ec 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/SummonFireElementalScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/SummonFireElementalScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class SummonFireElementalScroll : SpellScroll - { - [Constructible] - public SummonFireElementalScroll(int amount = 1) : base(62, 0x1F6B, amount) + public class SummonFireElementalScroll : SpellScroll { + [Constructible] + public SummonFireElementalScroll(int amount = 1) : base(62, 0x1F6B, amount) + { + } + + public SummonFireElementalScroll(Serial serial) : base(serial) + { + } + + 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 SummonFireElementalScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/SummonWaterElementalScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/SummonWaterElementalScroll.cs index e1ea9d030..8209df4e2 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/SummonWaterElementalScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Eighth Circle/SummonWaterElementalScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class SummonWaterElementalScroll : SpellScroll - { - [Constructible] - public SummonWaterElementalScroll(int amount = 1) : base(63, 0x1F6C, amount) + public class SummonWaterElementalScroll : SpellScroll { + [Constructible] + public SummonWaterElementalScroll(int amount = 1) : base(63, 0x1F6C, amount) + { + } + + public SummonWaterElementalScroll(Serial serial) : base(serial) + { + } + + 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 SummonWaterElementalScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/BladeSpiritsScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/BladeSpiritsScroll.cs index c259fdb0f..aa54b5240 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/BladeSpiritsScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/BladeSpiritsScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class BladeSpiritsScroll : SpellScroll - { - [Constructible] - public BladeSpiritsScroll(int amount = 1) : base(32, 0x1F4D, amount) + public class BladeSpiritsScroll : SpellScroll { + [Constructible] + public BladeSpiritsScroll(int amount = 1) : base(32, 0x1F4D, amount) + { + } + + public BladeSpiritsScroll(Serial serial) : base(serial) + { + } + + 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 BladeSpiritsScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/DispelFieldScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/DispelFieldScroll.cs index 47f170dda..8288a2bcb 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/DispelFieldScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/DispelFieldScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class DispelFieldScroll : SpellScroll - { - [Constructible] - public DispelFieldScroll(int amount = 1) : base(33, 0x1F4E, amount) + public class DispelFieldScroll : SpellScroll { + [Constructible] + public DispelFieldScroll(int amount = 1) : base(33, 0x1F4E, amount) + { + } + + public DispelFieldScroll(Serial serial) : base(serial) + { + } + + 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 DispelFieldScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/IncognitoScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/IncognitoScroll.cs index 06ad92040..a6b6a48f3 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/IncognitoScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/IncognitoScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class IncognitoScroll : SpellScroll - { - [Constructible] - public IncognitoScroll(int amount = 1) : base(34, 0x1F4F, amount) + public class IncognitoScroll : SpellScroll { + [Constructible] + public IncognitoScroll(int amount = 1) : base(34, 0x1F4F, amount) + { + } + + public IncognitoScroll(Serial serial) : base(serial) + { + } + + 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 IncognitoScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/MagicReflectScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/MagicReflectScroll.cs index 21f5890d0..099acb7ff 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/MagicReflectScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/MagicReflectScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class MagicReflectScroll : SpellScroll - { - [Constructible] - public MagicReflectScroll(int amount = 1) : base(35, 0x1F50, amount) + public class MagicReflectScroll : SpellScroll { + [Constructible] + public MagicReflectScroll(int amount = 1) : base(35, 0x1F50, amount) + { + } + + public MagicReflectScroll(Serial serial) : base(serial) + { + } + + 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 MagicReflectScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/MindBlastScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/MindBlastScroll.cs index 0710c1ea1..251cb4cdd 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/MindBlastScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/MindBlastScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class MindBlastScroll : SpellScroll - { - [Constructible] - public MindBlastScroll(int amount = 1) : base(36, 0x1F51, amount) + public class MindBlastScroll : SpellScroll { + [Constructible] + public MindBlastScroll(int amount = 1) : base(36, 0x1F51, amount) + { + } + + public MindBlastScroll(Serial serial) : base(serial) + { + } + + 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 MindBlastScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/ParalyzeScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/ParalyzeScroll.cs index 53d5483ad..71478e485 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/ParalyzeScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/ParalyzeScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class ParalyzeScroll : SpellScroll - { - [Constructible] - public ParalyzeScroll(int amount = 1) : base(37, 0x1F52, amount) + public class ParalyzeScroll : SpellScroll { + [Constructible] + public ParalyzeScroll(int amount = 1) : base(37, 0x1F52, amount) + { + } + + public ParalyzeScroll(Serial serial) : base(serial) + { + } + + 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 ParalyzeScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/PoisonFieldScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/PoisonFieldScroll.cs index 7d5b23d43..c8559cde6 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/PoisonFieldScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/PoisonFieldScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class PoisonFieldScroll : SpellScroll - { - [Constructible] - public PoisonFieldScroll(int amount = 1) : base(38, 0x1F53, amount) + public class PoisonFieldScroll : SpellScroll { + [Constructible] + public PoisonFieldScroll(int amount = 1) : base(38, 0x1F53, amount) + { + } + + public PoisonFieldScroll(Serial serial) : base(serial) + { + } + + 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 PoisonFieldScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/SummonCreatureScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/SummonCreatureScroll.cs index 081070afb..54c2407e7 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/SummonCreatureScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fifth Circle/SummonCreatureScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class SummonCreatureScroll : SpellScroll - { - [Constructible] - public SummonCreatureScroll(int amount = 1) : base(39, 0x1F54, amount) + public class SummonCreatureScroll : SpellScroll { + [Constructible] + public SummonCreatureScroll(int amount = 1) : base(39, 0x1F54, amount) + { + } + + public SummonCreatureScroll(Serial serial) : base(serial) + { + } + + 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 SummonCreatureScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/ClumsyScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/ClumsyScroll.cs index 6393906d1..40a168dcf 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/ClumsyScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/ClumsyScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class ClumsyScroll : SpellScroll - { - [Constructible] - public ClumsyScroll(int amount = 1) : base(0, 0x1F2E, amount) + public class ClumsyScroll : SpellScroll { + [Constructible] + public ClumsyScroll(int amount = 1) : base(0, 0x1F2E, amount) + { + } + + public ClumsyScroll(Serial serial) : base(serial) + { + } + + 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 ClumsyScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/CreateFoodScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/CreateFoodScroll.cs index 7495b9a59..df1b28b02 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/CreateFoodScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/CreateFoodScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class CreateFoodScroll : SpellScroll - { - [Constructible] - public CreateFoodScroll(int amount = 1) : base(1, 0x1F2F, amount) + public class CreateFoodScroll : SpellScroll { + [Constructible] + public CreateFoodScroll(int amount = 1) : base(1, 0x1F2F, amount) + { + } + + public CreateFoodScroll(Serial serial) : base(serial) + { + } + + 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 CreateFoodScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/FeeblemindScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/FeeblemindScroll.cs index 89db72392..1c0cb620c 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/FeeblemindScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/FeeblemindScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class FeeblemindScroll : SpellScroll - { - [Constructible] - public FeeblemindScroll(int amount = 1) : base(2, 0x1F30, amount) + public class FeeblemindScroll : SpellScroll { + [Constructible] + public FeeblemindScroll(int amount = 1) : base(2, 0x1F30, amount) + { + } + + public FeeblemindScroll(Serial serial) : base(serial) + { + } + + 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 FeeblemindScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/HealScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/HealScroll.cs index e2fe67852..4f5ef8ad5 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/HealScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/HealScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class HealScroll : SpellScroll - { - [Constructible] - public HealScroll(int amount = 1) : base(3, 0x1F31, amount) + public class HealScroll : SpellScroll { + [Constructible] + public HealScroll(int amount = 1) : base(3, 0x1F31, amount) + { + } + + public HealScroll(Serial serial) : base(serial) + { + } + + 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 HealScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/MagicArrowScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/MagicArrowScroll.cs index 3a4a39924..d64b5d021 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/MagicArrowScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/MagicArrowScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class MagicArrowScroll : SpellScroll - { - [Constructible] - public MagicArrowScroll(int amount = 1) : base(4, 0x1F32, amount) + public class MagicArrowScroll : SpellScroll { + [Constructible] + public MagicArrowScroll(int amount = 1) : base(4, 0x1F32, amount) + { + } + + public MagicArrowScroll(Serial serial) : base(serial) + { + } + + 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 MagicArrowScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/NightSightScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/NightSightScroll.cs index 63d134999..5e5157d14 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/NightSightScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/NightSightScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class NightSightScroll : SpellScroll - { - [Constructible] - public NightSightScroll(int amount = 1) : base(5, 0x1F33, amount) + public class NightSightScroll : SpellScroll { + [Constructible] + public NightSightScroll(int amount = 1) : base(5, 0x1F33, amount) + { + } + + public NightSightScroll(Serial ser) : base(ser) + { + } + + 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 NightSightScroll(Serial ser) : base(ser) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/ReactiveArmorScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/ReactiveArmorScroll.cs index 100ca186b..37aa76115 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/ReactiveArmorScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/ReactiveArmorScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class ReactiveArmorScroll : SpellScroll - { - [Constructible] - public ReactiveArmorScroll(int amount = 1) : base(6, 0x1F2D, amount) + public class ReactiveArmorScroll : SpellScroll { + [Constructible] + public ReactiveArmorScroll(int amount = 1) : base(6, 0x1F2D, amount) + { + } + + public ReactiveArmorScroll(Serial ser) : base(ser) + { + } + + 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 ReactiveArmorScroll(Serial ser) : base(ser) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/WeakenScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/WeakenScroll.cs index 95053a810..329a24e92 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/WeakenScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/First Circle/WeakenScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class WeakenScroll : SpellScroll - { - [Constructible] - public WeakenScroll(int amount = 1) : base(7, 0x1F34, amount) + public class WeakenScroll : SpellScroll { + [Constructible] + public WeakenScroll(int amount = 1) : base(7, 0x1F34, amount) + { + } + + public WeakenScroll(Serial serial) : base(serial) + { + } + + 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 WeakenScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/ArchProtectionScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/ArchProtectionScroll.cs index 2addcef70..a8d5e0561 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/ArchProtectionScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/ArchProtectionScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class ArchProtectionScroll : SpellScroll - { - [Constructible] - public ArchProtectionScroll(int amount = 1) : base(25, 0x1F46, amount) + public class ArchProtectionScroll : SpellScroll { + [Constructible] + public ArchProtectionScroll(int amount = 1) : base(25, 0x1F46, amount) + { + } + + public ArchProtectionScroll(Serial serial) : base(serial) + { + } + + 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 ArchProtectionScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/ArchcureScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/ArchcureScroll.cs index 2c3af4e81..9cd24ae09 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/ArchcureScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/ArchcureScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class ArchCureScroll : SpellScroll - { - [Constructible] - public ArchCureScroll(int amount = 1) : base(24, 0x1F45, amount) + public class ArchCureScroll : SpellScroll { + [Constructible] + public ArchCureScroll(int amount = 1) : base(24, 0x1F45, amount) + { + } + + public ArchCureScroll(Serial serial) : base(serial) + { + } + + 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 ArchCureScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/CurseScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/CurseScroll.cs index 500c58625..3ffadeb1e 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/CurseScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/CurseScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class CurseScroll : SpellScroll - { - [Constructible] - public CurseScroll(int amount = 1) : base(26, 0x1F47, amount) + public class CurseScroll : SpellScroll { + [Constructible] + public CurseScroll(int amount = 1) : base(26, 0x1F47, amount) + { + } + + public CurseScroll(Serial serial) : base(serial) + { + } + + 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 CurseScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/FireFieldScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/FireFieldScroll.cs index 7d9ed95e9..b20d2b237 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/FireFieldScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/FireFieldScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class FireFieldScroll : SpellScroll - { - [Constructible] - public FireFieldScroll(int amount = 1) : base(27, 0x1F48, amount) + public class FireFieldScroll : SpellScroll { + [Constructible] + public FireFieldScroll(int amount = 1) : base(27, 0x1F48, amount) + { + } + + public FireFieldScroll(Serial serial) : base(serial) + { + } + + 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 FireFieldScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/GreaterHealScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/GreaterHealScroll.cs index 96d4c6aed..69287bf26 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/GreaterHealScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/GreaterHealScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class GreaterHealScroll : SpellScroll - { - [Constructible] - public GreaterHealScroll(int amount = 1) : base(28, 0x1F49, amount) + public class GreaterHealScroll : SpellScroll { + [Constructible] + public GreaterHealScroll(int amount = 1) : base(28, 0x1F49, amount) + { + } + + public GreaterHealScroll(Serial serial) : base(serial) + { + } + + 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 GreaterHealScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/LightningScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/LightningScroll.cs index 01b180bf6..a65876f66 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/LightningScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/LightningScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class LightningScroll : SpellScroll - { - [Constructible] - public LightningScroll(int amount = 1) : base(29, 0x1F4A, amount) + public class LightningScroll : SpellScroll { + [Constructible] + public LightningScroll(int amount = 1) : base(29, 0x1F4A, amount) + { + } + + public LightningScroll(Serial serial) : base(serial) + { + } + + 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 LightningScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/ManaDrainScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/ManaDrainScroll.cs index 817e8756c..9c359eecf 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/ManaDrainScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/ManaDrainScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class ManaDrainScroll : SpellScroll - { - [Constructible] - public ManaDrainScroll(int amount = 1) : base(30, 0x1F4B, amount) + public class ManaDrainScroll : SpellScroll { + [Constructible] + public ManaDrainScroll(int amount = 1) : base(30, 0x1F4B, amount) + { + } + + public ManaDrainScroll(Serial serial) : base(serial) + { + } + + 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 ManaDrainScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/RecallScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/RecallScroll.cs index aca7bd7d1..8acbe7c96 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/RecallScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Fourth Circle/RecallScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class RecallScroll : SpellScroll - { - [Constructible] - public RecallScroll(int amount = 1) : base(31, 0x1F4C, amount) + public class RecallScroll : SpellScroll { + [Constructible] + public RecallScroll(int amount = 1) : base(31, 0x1F4C, amount) + { + } + + public RecallScroll(Serial serial) : base(serial) + { + } + + 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 RecallScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/AnimatedWeaponScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/AnimatedWeaponScroll.cs index c6e708978..f19f9bece 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/AnimatedWeaponScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/AnimatedWeaponScroll.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class AnimatedWeaponScroll : SpellScroll - { - [Constructible] - public AnimatedWeaponScroll(int amount = 1) - : base(683, 0x2DA4, amount) + public class AnimatedWeaponScroll : SpellScroll { + [Constructible] + public AnimatedWeaponScroll(int amount = 1) + : base(683, 0x2DA4, amount) + { + } + + public AnimatedWeaponScroll(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + /*int version = */ + reader.ReadInt(); + } } - - public AnimatedWeaponScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - /*int version = */ - reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/BombardScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/BombardScroll.cs index 518bd547f..b871cdf3d 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/BombardScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/BombardScroll.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class BombardScroll : SpellScroll - { - [Constructible] - public BombardScroll(int amount = 1) - : base(688, 0x2DA9, amount) + public class BombardScroll : SpellScroll { + [Constructible] + public BombardScroll(int amount = 1) + : base(688, 0x2DA9, amount) + { + } + + public BombardScroll(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + /*int version = */ + reader.ReadInt(); + } } - - public BombardScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - /*int version = */ - reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/CleansingWindsScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/CleansingWindsScroll.cs index 0e0e45b12..20d898789 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/CleansingWindsScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/CleansingWindsScroll.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class CleansingWindsScroll : SpellScroll - { - [Constructible] - public CleansingWindsScroll(int amount = 1) - : base(687, 0x2DA8, amount) + public class CleansingWindsScroll : SpellScroll { + [Constructible] + public CleansingWindsScroll(int amount = 1) + : base(687, 0x2DA8, amount) + { + } + + public CleansingWindsScroll(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + /*int version = */ + reader.ReadInt(); + } } - - public CleansingWindsScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - /*int version = */ - reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/EagleStrikeScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/EagleStrikeScroll.cs index 3c2313be9..2c67a2dbf 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/EagleStrikeScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/EagleStrikeScroll.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class EagleStrikeScroll : SpellScroll - { - [Constructible] - public EagleStrikeScroll(int amount = 1) - : base(682, 0x2DA3, amount) + public class EagleStrikeScroll : SpellScroll { + [Constructible] + public EagleStrikeScroll(int amount = 1) + : base(682, 0x2DA3, amount) + { + } + + public EagleStrikeScroll(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + /*int version = */ + reader.ReadInt(); + } } - - public EagleStrikeScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - /*int version = */ - reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/EnchantScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/EnchantScroll.cs index baee4b8b2..f71da570c 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/EnchantScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/EnchantScroll.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class EnchantScroll : SpellScroll - { - [Constructible] - public EnchantScroll(int amount = 1) - : base(680, 0x2DA1, amount) + public class EnchantScroll : SpellScroll { + [Constructible] + public EnchantScroll(int amount = 1) + : base(680, 0x2DA1, amount) + { + } + + public EnchantScroll(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + /*int version = */ + reader.ReadInt(); + } } - - public EnchantScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - /*int version = */ - reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/HailStormScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/HailStormScroll.cs index e835457f2..6bbd1cff9 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/HailStormScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/HailStormScroll.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class HailStormScroll : SpellScroll - { - [Constructible] - public HailStormScroll(int amount = 1) - : base(690, 0x2DAB, amount) + public class HailStormScroll : SpellScroll { + [Constructible] + public HailStormScroll(int amount = 1) + : base(690, 0x2DAB, amount) + { + } + + public HailStormScroll(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + /*int version = */ + reader.ReadInt(); + } } - - public HailStormScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - /*int version = */ - reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/HealingStoneScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/HealingStoneScroll.cs index b641bcbb1..8df4b4d17 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/HealingStoneScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/HealingStoneScroll.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class HealingStoneScroll : SpellScroll - { - [Constructible] - public HealingStoneScroll(int amount = 1) - : base(678, 0x2D9F, amount) + public class HealingStoneScroll : SpellScroll { + [Constructible] + public HealingStoneScroll(int amount = 1) + : base(678, 0x2D9F, amount) + { + } + + public HealingStoneScroll(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + /*int version = */ + reader.ReadInt(); + } } - - public HealingStoneScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - /*int version = */ - reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/MassSleepScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/MassSleepScroll.cs index a5c4f4fef..d1277fe4e 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/MassSleepScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/MassSleepScroll.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class MassSleepScroll : SpellScroll - { - [Constructible] - public MassSleepScroll(int amount = 1) - : base(686, 0x2DA7, amount) + public class MassSleepScroll : SpellScroll { + [Constructible] + public MassSleepScroll(int amount = 1) + : base(686, 0x2DA7, amount) + { + } + + public MassSleepScroll(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + /*int version = */ + reader.ReadInt(); + } } - - public MassSleepScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - /*int version = */ - reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/NetherBoltScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/NetherBoltScroll.cs index c2eac4c2f..e40a29cae 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/NetherBoltScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/NetherBoltScroll.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class NetherBoltScroll : SpellScroll - { - [Constructible] - public NetherBoltScroll(int amount = 1) - : base(677, 0x2D9E, amount) + public class NetherBoltScroll : SpellScroll { + [Constructible] + public NetherBoltScroll(int amount = 1) + : base(677, 0x2D9E, amount) + { + } + + public NetherBoltScroll(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + /*int version = */ + reader.ReadInt(); + } } - - public NetherBoltScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - /*int version = */ - reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/NetherCycloneScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/NetherCycloneScroll.cs index 8954429e3..5c67dd5bf 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/NetherCycloneScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/NetherCycloneScroll.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class NetherCycloneScroll : SpellScroll - { - [Constructible] - public NetherCycloneScroll(int amount = 1) - : base(691, 0x2DAC, amount) + public class NetherCycloneScroll : SpellScroll { + [Constructible] + public NetherCycloneScroll(int amount = 1) + : base(691, 0x2DAC, amount) + { + } + + public NetherCycloneScroll(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + /*int version = */ + reader.ReadInt(); + } } - - public NetherCycloneScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - /*int version = */ - reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/PurgeMagicScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/PurgeMagicScroll.cs index 5687801d4..3bdf54a72 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/PurgeMagicScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/PurgeMagicScroll.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class PurgeMagicScroll : SpellScroll - { - [Constructible] - public PurgeMagicScroll(int amount = 1) - : base(679, 0x2DA0, amount) + public class PurgeMagicScroll : SpellScroll { + [Constructible] + public PurgeMagicScroll(int amount = 1) + : base(679, 0x2DA0, amount) + { + } + + public PurgeMagicScroll(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + /*int version = */ + reader.ReadInt(); + } } - - public PurgeMagicScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - /*int version = */ - reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/RisingColossusScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/RisingColossusScroll.cs index 4018dfd0d..0960f79dc 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/RisingColossusScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/RisingColossusScroll.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class RisingColossusScroll : SpellScroll - { - [Constructible] - public RisingColossusScroll(int amount = 1) - : base(692, 0x2DAD, amount) + public class RisingColossusScroll : SpellScroll { + [Constructible] + public RisingColossusScroll(int amount = 1) + : base(692, 0x2DAD, amount) + { + } + + public RisingColossusScroll(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + /*int version = */ + reader.ReadInt(); + } } - - public RisingColossusScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - /*int version = */ - reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/SleepScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/SleepScroll.cs index b6f6ad889..de8515717 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/SleepScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/SleepScroll.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class SleepScroll : SpellScroll - { - [Constructible] - public SleepScroll(int amount = 1) - : base(681, 0x2DA2, amount) + public class SleepScroll : SpellScroll { + [Constructible] + public SleepScroll(int amount = 1) + : base(681, 0x2DA2, amount) + { + } + + public SleepScroll(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + /*int version = */ + reader.ReadInt(); + } } - - public SleepScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - /*int version = */ - reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/SpellPlagueScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/SpellPlagueScroll.cs index 3f7a28844..0ac427625 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/SpellPlagueScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/SpellPlagueScroll.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class SpellPlagueScroll : SpellScroll - { - [Constructible] - public SpellPlagueScroll(int amount = 1) - : base(689, 0x2DAA, amount) + public class SpellPlagueScroll : SpellScroll { + [Constructible] + public SpellPlagueScroll(int amount = 1) + : base(689, 0x2DAA, amount) + { + } + + public SpellPlagueScroll(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + /*int version = */ + reader.ReadInt(); + } } - - public SpellPlagueScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - /*int version = */ - reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/SpellTriggerScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/SpellTriggerScroll.cs index 64f4ddca6..a91ca0944 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/SpellTriggerScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/SpellTriggerScroll.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class SpellTriggerScroll : SpellScroll - { - [Constructible] - public SpellTriggerScroll(int amount = 1) - : base(685, 0x2DA6, amount) + public class SpellTriggerScroll : SpellScroll { + [Constructible] + public SpellTriggerScroll(int amount = 1) + : base(685, 0x2DA6, amount) + { + } + + public SpellTriggerScroll(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + /*int version = */ + reader.ReadInt(); + } } - - public SpellTriggerScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - /*int version = */ - reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/StoneFormScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/StoneFormScroll.cs index c942a77c2..fd6abfbe8 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/StoneFormScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Mysticism/StoneFormScroll.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class StoneFormScroll : SpellScroll - { - [Constructible] - public StoneFormScroll(int amount = 1) - : base(684, 0x2DA5, amount) + public class StoneFormScroll : SpellScroll { + [Constructible] + public StoneFormScroll(int amount = 1) + : base(684, 0x2DA5, amount) + { + } + + public StoneFormScroll(Serial serial) + : base(serial) + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + /*int version = */ + reader.ReadInt(); + } } - - public StoneFormScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - /*int version = */ - reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/AnimateDeadScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/AnimateDeadScroll.cs index 5fb741e8f..52dd3b89e 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/AnimateDeadScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/AnimateDeadScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class AnimateDeadScroll : SpellScroll - { - [Constructible] - public AnimateDeadScroll(int amount = 1) : base(100, 0x2260, amount) + public class AnimateDeadScroll : SpellScroll { + [Constructible] + public AnimateDeadScroll(int amount = 1) : base(100, 0x2260, amount) + { + } + + public AnimateDeadScroll(Serial serial) : base(serial) + { + } + + 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 AnimateDeadScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/BloodOathScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/BloodOathScroll.cs index 8c4e05bc8..fb52aacc8 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/BloodOathScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/BloodOathScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class BloodOathScroll : SpellScroll - { - [Constructible] - public BloodOathScroll(int amount = 1) : base(101, 0x2261, amount) + public class BloodOathScroll : SpellScroll { + [Constructible] + public BloodOathScroll(int amount = 1) : base(101, 0x2261, amount) + { + } + + public BloodOathScroll(Serial serial) : base(serial) + { + } + + 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 BloodOathScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/CorpseSkinScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/CorpseSkinScroll.cs index 6c2ab4009..d571007ab 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/CorpseSkinScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/CorpseSkinScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class CorpseSkinScroll : SpellScroll - { - [Constructible] - public CorpseSkinScroll(int amount = 1) : base(102, 0x2262, amount) + public class CorpseSkinScroll : SpellScroll { + [Constructible] + public CorpseSkinScroll(int amount = 1) : base(102, 0x2262, amount) + { + } + + public CorpseSkinScroll(Serial serial) : base(serial) + { + } + + 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 CorpseSkinScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/CurseWeaponScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/CurseWeaponScroll.cs index 24a55bbee..a06c18f18 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/CurseWeaponScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/CurseWeaponScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class CurseWeaponScroll : SpellScroll - { - [Constructible] - public CurseWeaponScroll(int amount = 1) : base(103, 0x2263, amount) + public class CurseWeaponScroll : SpellScroll { + [Constructible] + public CurseWeaponScroll(int amount = 1) : base(103, 0x2263, amount) + { + } + + public CurseWeaponScroll(Serial serial) : base(serial) + { + } + + 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 CurseWeaponScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/EvilOmenScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/EvilOmenScroll.cs index 2c6a3c650..b0bd5824e 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/EvilOmenScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/EvilOmenScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class EvilOmenScroll : SpellScroll - { - [Constructible] - public EvilOmenScroll(int amount = 1) : base(104, 0x2264, amount) + public class EvilOmenScroll : SpellScroll { + [Constructible] + public EvilOmenScroll(int amount = 1) : base(104, 0x2264, amount) + { + } + + public EvilOmenScroll(Serial serial) : base(serial) + { + } + + 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 EvilOmenScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/ExorcismScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/ExorcismScroll.cs index e2b1c7f40..b84cb87e2 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/ExorcismScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/ExorcismScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class ExorcismScroll : SpellScroll - { - [Constructible] - public ExorcismScroll(int amount = 1) : base(116, 0x2270, amount) + public class ExorcismScroll : SpellScroll { + [Constructible] + public ExorcismScroll(int amount = 1) : base(116, 0x2270, amount) + { + } + + public ExorcismScroll(Serial serial) : base(serial) + { + } + + 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 ExorcismScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/HorrificBeastScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/HorrificBeastScroll.cs index 37d4c423d..de6f9f1a7 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/HorrificBeastScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/HorrificBeastScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class HorrificBeastScroll : SpellScroll - { - [Constructible] - public HorrificBeastScroll(int amount = 1) : base(105, 0x2265, amount) + public class HorrificBeastScroll : SpellScroll { + [Constructible] + public HorrificBeastScroll(int amount = 1) : base(105, 0x2265, amount) + { + } + + public HorrificBeastScroll(Serial serial) : base(serial) + { + } + + 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 HorrificBeastScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/LichFormScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/LichFormScroll.cs index 2b719af60..e4a2bd556 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/LichFormScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/LichFormScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class LichFormScroll : SpellScroll - { - [Constructible] - public LichFormScroll(int amount = 1) : base(106, 0x2266, amount) + public class LichFormScroll : SpellScroll { + [Constructible] + public LichFormScroll(int amount = 1) : base(106, 0x2266, amount) + { + } + + public LichFormScroll(Serial serial) : base(serial) + { + } + + 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 LichFormScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/MindRotScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/MindRotScroll.cs index de5f6b942..2f3141016 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/MindRotScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/MindRotScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class MindRotScroll : SpellScroll - { - [Constructible] - public MindRotScroll(int amount = 1) : base(107, 0x2267, amount) + public class MindRotScroll : SpellScroll { + [Constructible] + public MindRotScroll(int amount = 1) : base(107, 0x2267, amount) + { + } + + public MindRotScroll(Serial serial) : base(serial) + { + } + + 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 MindRotScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/PainSpikeScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/PainSpikeScroll.cs index 04b1af65c..36c151b56 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/PainSpikeScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/PainSpikeScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class PainSpikeScroll : SpellScroll - { - [Constructible] - public PainSpikeScroll(int amount = 1) : base(108, 0x2268, amount) + public class PainSpikeScroll : SpellScroll { + [Constructible] + public PainSpikeScroll(int amount = 1) : base(108, 0x2268, amount) + { + } + + public PainSpikeScroll(Serial serial) : base(serial) + { + } + + 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 PainSpikeScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/PoisonStrikeScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/PoisonStrikeScroll.cs index 968225c83..df44559d3 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/PoisonStrikeScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/PoisonStrikeScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class PoisonStrikeScroll : SpellScroll - { - [Constructible] - public PoisonStrikeScroll(int amount = 1) : base(109, 0x2269, amount) + public class PoisonStrikeScroll : SpellScroll { + [Constructible] + public PoisonStrikeScroll(int amount = 1) : base(109, 0x2269, amount) + { + } + + public PoisonStrikeScroll(Serial serial) : base(serial) + { + } + + 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 PoisonStrikeScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/StrangleScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/StrangleScroll.cs index d51fd0706..b53cc68d1 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/StrangleScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/StrangleScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class StrangleScroll : SpellScroll - { - [Constructible] - public StrangleScroll(int amount = 1) : base(110, 0x226A, amount) + public class StrangleScroll : SpellScroll { + [Constructible] + public StrangleScroll(int amount = 1) : base(110, 0x226A, amount) + { + } + + public StrangleScroll(Serial serial) : base(serial) + { + } + + 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 StrangleScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/SummonFamiliarScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/SummonFamiliarScroll.cs index cc086a2da..0ea71dda1 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/SummonFamiliarScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/SummonFamiliarScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class SummonFamiliarScroll : SpellScroll - { - [Constructible] - public SummonFamiliarScroll(int amount = 1) : base(111, 0x226B, amount) + public class SummonFamiliarScroll : SpellScroll { + [Constructible] + public SummonFamiliarScroll(int amount = 1) : base(111, 0x226B, amount) + { + } + + public SummonFamiliarScroll(Serial serial) : base(serial) + { + } + + 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 SummonFamiliarScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/VampiricEmbraceScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/VampiricEmbraceScroll.cs index 5fdc7712e..200288675 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/VampiricEmbraceScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/VampiricEmbraceScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class VampiricEmbraceScroll : SpellScroll - { - [Constructible] - public VampiricEmbraceScroll(int amount = 1) : base(112, 0x226C, amount) + public class VampiricEmbraceScroll : SpellScroll { + [Constructible] + public VampiricEmbraceScroll(int amount = 1) : base(112, 0x226C, amount) + { + } + + public VampiricEmbraceScroll(Serial serial) : base(serial) + { + } + + 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 VampiricEmbraceScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/VengefulSpiritScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/VengefulSpiritScroll.cs index 5d1578b29..2b6169420 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/VengefulSpiritScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/VengefulSpiritScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class VengefulSpiritScroll : SpellScroll - { - [Constructible] - public VengefulSpiritScroll(int amount = 1) : base(113, 0x226D, amount) + public class VengefulSpiritScroll : SpellScroll { + [Constructible] + public VengefulSpiritScroll(int amount = 1) : base(113, 0x226D, amount) + { + } + + public VengefulSpiritScroll(Serial serial) : base(serial) + { + } + + 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 VengefulSpiritScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/WitherScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/WitherScroll.cs index 75542d832..4b904e3d1 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/WitherScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/WitherScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class WitherScroll : SpellScroll - { - [Constructible] - public WitherScroll(int amount = 1) : base(114, 0x226E, amount) + public class WitherScroll : SpellScroll { + [Constructible] + public WitherScroll(int amount = 1) : base(114, 0x226E, amount) + { + } + + public WitherScroll(Serial serial) : base(serial) + { + } + + 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 WitherScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/WraithFormScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/WraithFormScroll.cs index f0745f3ee..19d8044d3 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/WraithFormScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Necromancy/WraithFormScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class WraithFormScroll : SpellScroll - { - [Constructible] - public WraithFormScroll(int amount = 1) : base(115, 0x226F, amount) + public class WraithFormScroll : SpellScroll { + [Constructible] + public WraithFormScroll(int amount = 1) : base(115, 0x226F, amount) + { + } + + public WraithFormScroll(Serial serial) : base(serial) + { + } + + 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 WraithFormScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/AgilityScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/AgilityScroll.cs index 18f55d42d..e3a553442 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/AgilityScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/AgilityScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class AgilityScroll : SpellScroll - { - [Constructible] - public AgilityScroll(int amount = 1) : base(8, 0x1F35, amount) + public class AgilityScroll : SpellScroll { + [Constructible] + public AgilityScroll(int amount = 1) : base(8, 0x1F35, amount) + { + } + + public AgilityScroll(Serial serial) : base(serial) + { + } + + 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 AgilityScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/CunningScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/CunningScroll.cs index 4a32656b8..d82d39c81 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/CunningScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/CunningScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class CunningScroll : SpellScroll - { - [Constructible] - public CunningScroll(int amount = 1) : base(9, 0x1F36, amount) + public class CunningScroll : SpellScroll { + [Constructible] + public CunningScroll(int amount = 1) : base(9, 0x1F36, amount) + { + } + + public CunningScroll(Serial serial) : base(serial) + { + } + + 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 CunningScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/CureScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/CureScroll.cs index 22ae0049c..bc15d4c97 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/CureScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/CureScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class CureScroll : SpellScroll - { - [Constructible] - public CureScroll(int amount = 1) : base(10, 0x1F37, amount) + public class CureScroll : SpellScroll { + [Constructible] + public CureScroll(int amount = 1) : base(10, 0x1F37, amount) + { + } + + public CureScroll(Serial serial) : base(serial) + { + } + + 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 CureScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/HarmScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/HarmScroll.cs index 18cfa7e49..89ba45016 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/HarmScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/HarmScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class HarmScroll : SpellScroll - { - [Constructible] - public HarmScroll(int amount = 1) : base(11, 0x1F38, amount) + public class HarmScroll : SpellScroll { + [Constructible] + public HarmScroll(int amount = 1) : base(11, 0x1F38, amount) + { + } + + public HarmScroll(Serial serial) : base(serial) + { + } + + 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 HarmScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/MagicTrapScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/MagicTrapScroll.cs index f1e0a7306..74d5a145d 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/MagicTrapScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/MagicTrapScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class MagicTrapScroll : SpellScroll - { - [Constructible] - public MagicTrapScroll(int amount = 1) : base(12, 0x1F39, amount) + public class MagicTrapScroll : SpellScroll { + [Constructible] + public MagicTrapScroll(int amount = 1) : base(12, 0x1F39, amount) + { + } + + public MagicTrapScroll(Serial serial) : base(serial) + { + } + + 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 MagicTrapScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/MagicUnTrapScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/MagicUnTrapScroll.cs index f73902519..5810527a6 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/MagicUnTrapScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/MagicUnTrapScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class MagicUnTrapScroll : SpellScroll - { - [Constructible] - public MagicUnTrapScroll(int amount = 1) : base(13, 0x1F3A, amount) + public class MagicUnTrapScroll : SpellScroll { + [Constructible] + public MagicUnTrapScroll(int amount = 1) : base(13, 0x1F3A, amount) + { + } + + public MagicUnTrapScroll(Serial serial) : base(serial) + { + } + + 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 MagicUnTrapScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/ProtectionScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/ProtectionScroll.cs index cee720001..37fe8ab3d 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/ProtectionScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/ProtectionScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class ProtectionScroll : SpellScroll - { - [Constructible] - public ProtectionScroll(int amount = 1) : base(14, 0x1F3B, amount) + public class ProtectionScroll : SpellScroll { + [Constructible] + public ProtectionScroll(int amount = 1) : base(14, 0x1F3B, amount) + { + } + + public ProtectionScroll(Serial serial) : base(serial) + { + } + + 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 ProtectionScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/StrengthScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/StrengthScroll.cs index 5a3841e32..c0fb13db0 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/StrengthScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Second Circle/StrengthScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class StrengthScroll : SpellScroll - { - [Constructible] - public StrengthScroll(int amount = 1) : base(15, 0x1F3C, amount) + public class StrengthScroll : SpellScroll { + [Constructible] + public StrengthScroll(int amount = 1) : base(15, 0x1F3C, amount) + { + } + + public StrengthScroll(Serial serial) : base(serial) + { + } + + 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 StrengthScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/ChainLightningScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/ChainLightningScroll.cs index 02ea8fc2f..0affdbb3c 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/ChainLightningScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/ChainLightningScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class ChainLightningScroll : SpellScroll - { - [Constructible] - public ChainLightningScroll(int amount = 1) : base(48, 0x1F5D, amount) + public class ChainLightningScroll : SpellScroll { + [Constructible] + public ChainLightningScroll(int amount = 1) : base(48, 0x1F5D, amount) + { + } + + public ChainLightningScroll(Serial serial) : base(serial) + { + } + + 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 ChainLightningScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/EnergyFieldScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/EnergyFieldScroll.cs index 59c74bbbe..bdd11bc27 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/EnergyFieldScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/EnergyFieldScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class EnergyFieldScroll : SpellScroll - { - [Constructible] - public EnergyFieldScroll(int amount = 1) : base(49, 0x1F5E, amount) + public class EnergyFieldScroll : SpellScroll { + [Constructible] + public EnergyFieldScroll(int amount = 1) : base(49, 0x1F5E, amount) + { + } + + public EnergyFieldScroll(Serial serial) : base(serial) + { + } + + 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 EnergyFieldScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/FlamestrikeScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/FlamestrikeScroll.cs index 8fd7df8b9..2b84afc48 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/FlamestrikeScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/FlamestrikeScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class FlamestrikeScroll : SpellScroll - { - [Constructible] - public FlamestrikeScroll(int amount = 1) : base(50, 0x1F5F, amount) + public class FlamestrikeScroll : SpellScroll { + [Constructible] + public FlamestrikeScroll(int amount = 1) : base(50, 0x1F5F, amount) + { + } + + public FlamestrikeScroll(Serial serial) : base(serial) + { + } + + 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 FlamestrikeScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/GateTravelScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/GateTravelScroll.cs index 620594174..aa3cb8a23 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/GateTravelScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/GateTravelScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class GateTravelScroll : SpellScroll - { - [Constructible] - public GateTravelScroll(int amount = 1) : base(51, 0x1F60, amount) + public class GateTravelScroll : SpellScroll { + [Constructible] + public GateTravelScroll(int amount = 1) : base(51, 0x1F60, amount) + { + } + + public GateTravelScroll(Serial serial) : base(serial) + { + } + + 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 GateTravelScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/ManaVampireScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/ManaVampireScroll.cs index 523748157..152bd9136 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/ManaVampireScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/ManaVampireScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class ManaVampireScroll : SpellScroll - { - [Constructible] - public ManaVampireScroll(int amount = 1) : base(52, 0x1F61, amount) + public class ManaVampireScroll : SpellScroll { + [Constructible] + public ManaVampireScroll(int amount = 1) : base(52, 0x1F61, amount) + { + } + + public ManaVampireScroll(Serial serial) : base(serial) + { + } + + 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 ManaVampireScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/MassDispelScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/MassDispelScroll.cs index dfc01b114..9ed9de24d 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/MassDispelScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/MassDispelScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class MassDispelScroll : SpellScroll - { - [Constructible] - public MassDispelScroll(int amount = 1) : base(53, 0x1F62, amount) + public class MassDispelScroll : SpellScroll { + [Constructible] + public MassDispelScroll(int amount = 1) : base(53, 0x1F62, amount) + { + } + + public MassDispelScroll(Serial serial) : base(serial) + { + } + + 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 MassDispelScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/MeteorStormScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/MeteorStormScroll.cs index 4c0397aff..f9b8c616a 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/MeteorStormScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/MeteorStormScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class MeteorSwarmScroll : SpellScroll - { - [Constructible] - public MeteorSwarmScroll(int amount = 1) : base(54, 0x1F63, amount) + public class MeteorSwarmScroll : SpellScroll { + [Constructible] + public MeteorSwarmScroll(int amount = 1) : base(54, 0x1F63, amount) + { + } + + public MeteorSwarmScroll(Serial serial) : base(serial) + { + } + + 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 MeteorSwarmScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/PolymorphScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/PolymorphScroll.cs index 0c7d8d0e5..2bc34f10d 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/PolymorphScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Seventh Circle/PolymorphScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class PolymorphScroll : SpellScroll - { - [Constructible] - public PolymorphScroll(int amount = 1) : base(55, 0x1F64, amount) + public class PolymorphScroll : SpellScroll { + [Constructible] + public PolymorphScroll(int amount = 1) : base(55, 0x1F64, amount) + { + } + + public PolymorphScroll(Serial serial) : base(serial) + { + } + + 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 PolymorphScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/DispelScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/DispelScroll.cs index d7c4a3441..88f0e0d02 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/DispelScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/DispelScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class DispelScroll : SpellScroll - { - [Constructible] - public DispelScroll(int amount = 1) : base(40, 0x1F55, amount) + public class DispelScroll : SpellScroll { + [Constructible] + public DispelScroll(int amount = 1) : base(40, 0x1F55, amount) + { + } + + public DispelScroll(Serial serial) : base(serial) + { + } + + 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 DispelScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/EnergyBoltScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/EnergyBoltScroll.cs index 25e0b9054..136f05e19 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/EnergyBoltScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/EnergyBoltScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class EnergyBoltScroll : SpellScroll - { - [Constructible] - public EnergyBoltScroll(int amount = 1) : base(41, 0x1F56, amount) + public class EnergyBoltScroll : SpellScroll { + [Constructible] + public EnergyBoltScroll(int amount = 1) : base(41, 0x1F56, amount) + { + } + + public EnergyBoltScroll(Serial serial) : base(serial) + { + } + + 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 EnergyBoltScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/ExplosionScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/ExplosionScroll.cs index 9ad3c13a5..fb455bd22 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/ExplosionScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/ExplosionScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class ExplosionScroll : SpellScroll - { - [Constructible] - public ExplosionScroll(int amount = 1) : base(42, 0x1F57, amount) + public class ExplosionScroll : SpellScroll { + [Constructible] + public ExplosionScroll(int amount = 1) : base(42, 0x1F57, amount) + { + } + + public ExplosionScroll(Serial serial) : base(serial) + { + } + + 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 ExplosionScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/InvisibilityScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/InvisibilityScroll.cs index 0248ce936..6aea33717 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/InvisibilityScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/InvisibilityScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class InvisibilityScroll : SpellScroll - { - [Constructible] - public InvisibilityScroll(int amount = 1) : base(43, 0x1F58, amount) + public class InvisibilityScroll : SpellScroll { + [Constructible] + public InvisibilityScroll(int amount = 1) : base(43, 0x1F58, amount) + { + } + + public InvisibilityScroll(Serial serial) : base(serial) + { + } + + 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 InvisibilityScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/MarkScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/MarkScroll.cs index d782e4cf9..b0f71a6ac 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/MarkScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/MarkScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class MarkScroll : SpellScroll - { - [Constructible] - public MarkScroll(int amount = 1) : base(44, 0x1F59, amount) + public class MarkScroll : SpellScroll { + [Constructible] + public MarkScroll(int amount = 1) : base(44, 0x1F59, amount) + { + } + + public MarkScroll(Serial serial) : base(serial) + { + } + + 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 MarkScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/MassCurseScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/MassCurseScroll.cs index d4d5f1d64..8ba8399b7 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/MassCurseScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/MassCurseScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class MassCurseScroll : SpellScroll - { - [Constructible] - public MassCurseScroll(int amount = 1) : base(45, 0x1F5A, amount) + public class MassCurseScroll : SpellScroll { + [Constructible] + public MassCurseScroll(int amount = 1) : base(45, 0x1F5A, amount) + { + } + + public MassCurseScroll(Serial serial) : base(serial) + { + } + + 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 MassCurseScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/ParalyzeFieldSpell.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/ParalyzeFieldSpell.cs index 85f6247d6..948c0c51b 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/ParalyzeFieldSpell.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/ParalyzeFieldSpell.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class ParalyzeFieldScroll : SpellScroll - { - [Constructible] - public ParalyzeFieldScroll(int amount = 1) : base(46, 0x1F5B, amount) + public class ParalyzeFieldScroll : SpellScroll { + [Constructible] + public ParalyzeFieldScroll(int amount = 1) : base(46, 0x1F5B, amount) + { + } + + public ParalyzeFieldScroll(Serial serial) : base(serial) + { + } + + 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 ParalyzeFieldScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/RevealScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/RevealScroll.cs index 9a8b604a0..dd37444d6 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/RevealScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Sixth Circle/RevealScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class RevealScroll : SpellScroll - { - [Constructible] - public RevealScroll(int amount = 1) : base(47, 0x1F5C, amount) + public class RevealScroll : SpellScroll { + [Constructible] + public RevealScroll(int amount = 1) : base(47, 0x1F5C, amount) + { + } + + public RevealScroll(Serial serial) : base(serial) + { + } + + 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 RevealScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/SpellScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/SpellScroll.cs index 4395d5b02..16c5e8d2c 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/SpellScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/SpellScroll.cs @@ -5,78 +5,78 @@ using Server.Spells; namespace Server.Items { - public class SpellScroll : Item, ICommodity - { - [Constructible] - public SpellScroll(int spellID, int itemID, int amount = 1) : base(itemID) + public class SpellScroll : Item, ICommodity { - Stackable = true; - Weight = 1.0; - Amount = amount; + [Constructible] + public SpellScroll(int spellID, int itemID, int amount = 1) : base(itemID) + { + Stackable = true; + Weight = 1.0; + Amount = amount; - SpellID = spellID; + SpellID = spellID; + } + + public SpellScroll(Serial serial) : base(serial) + { + } + + public int SpellID { get; private set; } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => Core.ML; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(SpellID); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + SpellID = reader.ReadInt(); + + break; + } + } + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (from.Alive && Movable) + list.Add(new AddToSpellbookEntry()); + } + + public override void OnDoubleClick(Mobile from) + { + if (!DesignContext.Check(from)) + return; // They are customizing + + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + return; + } + + var spell = SpellRegistry.NewSpell(SpellID, from, this); + + if (spell != null) + spell.Cast(); + else + from.SendLocalizedMessage(502345); // This spell has been temporarily disabled. + } } - - public SpellScroll(Serial serial) : base(serial) - { - } - - public int SpellID { get; private set; } - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => Core.ML; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(SpellID); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - SpellID = reader.ReadInt(); - - break; - } - } - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (from.Alive && Movable) - list.Add(new AddToSpellbookEntry()); - } - - public override void OnDoubleClick(Mobile from) - { - if (!DesignContext.Check(from)) - return; // They are customizing - - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - return; - } - - Spell spell = SpellRegistry.NewSpell(SpellID, from, this); - - if (spell != null) - spell.Cast(); - else - from.SendLocalizedMessage(502345); // This spell has been temporarily disabled. - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/SpellweavingScrolls.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/SpellweavingScrolls.cs index 903f7307b..776ce4e2e 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/SpellweavingScrolls.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/SpellweavingScrolls.cs @@ -1,434 +1,434 @@ namespace Server.Items { - public class ArcaneCircleScroll : SpellScroll - { - [Constructible] - public ArcaneCircleScroll(int amount = 1) - : base(600, 0x2D51, amount) => - Hue = 0x8FD; - - public ArcaneCircleScroll(Serial serial) - : base(serial) + public class ArcaneCircleScroll : SpellScroll { + [Constructible] + public ArcaneCircleScroll(int amount = 1) + : base(600, 0x2D51, amount) => + Hue = 0x8FD; + + public ArcaneCircleScroll(Serial serial) + : base(serial) + { + } + + 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 Serialize(IGenericWriter writer) + public class GiftOfRenewalScroll : SpellScroll { - base.Serialize(writer); + [Constructible] + public GiftOfRenewalScroll(int amount = 1) + : base(601, 0x2D52, amount) => + Hue = 0x8FD; - writer.Write(0); // version + public GiftOfRenewalScroll(Serial serial) + : base(serial) + { + } + + 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 Deserialize(IGenericReader reader) + public class ImmolatingWeaponScroll : SpellScroll { - base.Deserialize(reader); + [Constructible] + public ImmolatingWeaponScroll(int amount = 1) + : base(602, 0x2D53, amount) => + Hue = 0x8FD; - int version = reader.ReadInt(); - } - } + public ImmolatingWeaponScroll(Serial serial) + : base(serial) + { + } - public class GiftOfRenewalScroll : SpellScroll - { - [Constructible] - public GiftOfRenewalScroll(int amount = 1) - : base(601, 0x2D52, amount) => - Hue = 0x8FD; + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public GiftOfRenewalScroll(Serial serial) - : base(serial) - { + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } } - public override void Serialize(IGenericWriter writer) + public class AttuneWeaponScroll : SpellScroll { - base.Serialize(writer); + [Constructible] + public AttuneWeaponScroll(int amount = 1) + : base(603, 0x2D54, amount) => + Hue = 0x8FD; - writer.Write(0); // version + public AttuneWeaponScroll(Serial serial) + : base(serial) + { + } + + 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 Deserialize(IGenericReader reader) + public class ThunderstormScroll : SpellScroll { - base.Deserialize(reader); + [Constructible] + public ThunderstormScroll(int amount = 1) + : base(604, 0x2D55, amount) => + Hue = 0x8FD; - int version = reader.ReadInt(); - } - } + public ThunderstormScroll(Serial serial) + : base(serial) + { + } - public class ImmolatingWeaponScroll : SpellScroll - { - [Constructible] - public ImmolatingWeaponScroll(int amount = 1) - : base(602, 0x2D53, amount) => - Hue = 0x8FD; + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public ImmolatingWeaponScroll(Serial serial) - : base(serial) - { + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } } - public override void Serialize(IGenericWriter writer) + public class NatureFuryScroll : SpellScroll { - base.Serialize(writer); + [Constructible] + public NatureFuryScroll(int amount = 1) + : base(605, 0x2D56, amount) => + Hue = 0x8FD; - writer.Write(0); // version + public NatureFuryScroll(Serial serial) + : base(serial) + { + } + + 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 Deserialize(IGenericReader reader) + public class SummonFeyScroll : SpellScroll { - base.Deserialize(reader); + [Constructible] + public SummonFeyScroll(int amount = 1) + : base(606, 0x2D57, amount) => + Hue = 0x8FD; - int version = reader.ReadInt(); - } - } + public SummonFeyScroll(Serial serial) + : base(serial) + { + } - public class AttuneWeaponScroll : SpellScroll - { - [Constructible] - public AttuneWeaponScroll(int amount = 1) - : base(603, 0x2D54, amount) => - Hue = 0x8FD; + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public AttuneWeaponScroll(Serial serial) - : base(serial) - { + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } } - public override void Serialize(IGenericWriter writer) + public class SummonFiendScroll : SpellScroll { - base.Serialize(writer); + [Constructible] + public SummonFiendScroll(int amount = 1) + : base(607, 0x2D58, amount) => + Hue = 0x8FD; - writer.Write(0); // version + public SummonFiendScroll(Serial serial) + : base(serial) + { + } + + 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 Deserialize(IGenericReader reader) + public class ReaperFormScroll : SpellScroll { - base.Deserialize(reader); + [Constructible] + public ReaperFormScroll(int amount = 1) + : base(608, 0x2D59, amount) => + Hue = 0x8FD; - int version = reader.ReadInt(); - } - } + public ReaperFormScroll(Serial serial) + : base(serial) + { + } - public class ThunderstormScroll : SpellScroll - { - [Constructible] - public ThunderstormScroll(int amount = 1) - : base(604, 0x2D55, amount) => - Hue = 0x8FD; + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public ThunderstormScroll(Serial serial) - : base(serial) - { + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } } - public override void Serialize(IGenericWriter writer) + public class WildfireScroll : SpellScroll { - base.Serialize(writer); + [Constructible] + public WildfireScroll(int amount = 1) + : base(609, 0x2D5A, amount) => + Hue = 0x8FD; - writer.Write(0); // version + public WildfireScroll(Serial serial) + : base(serial) + { + } + + 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 Deserialize(IGenericReader reader) + public class EssenceOfWindScroll : SpellScroll { - base.Deserialize(reader); + [Constructible] + public EssenceOfWindScroll(int amount = 1) + : base(610, 0x2D5B, amount) => + Hue = 0x8FD; - int version = reader.ReadInt(); - } - } + public EssenceOfWindScroll(Serial serial) + : base(serial) + { + } - public class NatureFuryScroll : SpellScroll - { - [Constructible] - public NatureFuryScroll(int amount = 1) - : base(605, 0x2D56, amount) => - Hue = 0x8FD; + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public NatureFuryScroll(Serial serial) - : base(serial) - { + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } } - public override void Serialize(IGenericWriter writer) + public class DryadAllureScroll : SpellScroll { - base.Serialize(writer); + [Constructible] + public DryadAllureScroll(int amount = 1) + : base(611, 0x2D5C, amount) => + Hue = 0x8FD; - writer.Write(0); // version + public DryadAllureScroll(Serial serial) + : base(serial) + { + } + + 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 Deserialize(IGenericReader reader) + public class EtherealVoyageScroll : SpellScroll { - base.Deserialize(reader); + [Constructible] + public EtherealVoyageScroll(int amount = 1) + : base(612, 0x2D5D, amount) => + Hue = 0x8FD; - int version = reader.ReadInt(); - } - } + public EtherealVoyageScroll(Serial serial) + : base(serial) + { + } - public class SummonFeyScroll : SpellScroll - { - [Constructible] - public SummonFeyScroll(int amount = 1) - : base(606, 0x2D57, amount) => - Hue = 0x8FD; + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public SummonFeyScroll(Serial serial) - : base(serial) - { + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } } - public override void Serialize(IGenericWriter writer) + public class WordOfDeathScroll : SpellScroll { - base.Serialize(writer); + [Constructible] + public WordOfDeathScroll(int amount = 1) + : base(613, 0x2D5E, amount) => + Hue = 0x8FD; - writer.Write(0); // version + public WordOfDeathScroll(Serial serial) + : base(serial) + { + } + + 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 Deserialize(IGenericReader reader) + public class GiftOfLifeScroll : SpellScroll { - base.Deserialize(reader); + [Constructible] + public GiftOfLifeScroll(int amount = 1) + : base(614, 0x2D5F, amount) => + Hue = 0x8FD; - int version = reader.ReadInt(); - } - } + public GiftOfLifeScroll(Serial serial) + : base(serial) + { + } - public class SummonFiendScroll : SpellScroll - { - [Constructible] - public SummonFiendScroll(int amount = 1) - : base(607, 0x2D58, amount) => - Hue = 0x8FD; + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public SummonFiendScroll(Serial serial) - : base(serial) - { + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } } - public override void Serialize(IGenericWriter writer) + public class ArcaneEmpowermentScroll : SpellScroll { - base.Serialize(writer); + [Constructible] + public ArcaneEmpowermentScroll(int amount = 1) + : base(615, 0x2D60, amount) => + Hue = 0x8FD; - writer.Write(0); // version + public ArcaneEmpowermentScroll(Serial serial) + : base(serial) + { + } + + 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 Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class ReaperFormScroll : SpellScroll - { - [Constructible] - public ReaperFormScroll(int amount = 1) - : base(608, 0x2D59, amount) => - Hue = 0x8FD; - - public ReaperFormScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class WildfireScroll : SpellScroll - { - [Constructible] - public WildfireScroll(int amount = 1) - : base(609, 0x2D5A, amount) => - Hue = 0x8FD; - - public WildfireScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class EssenceOfWindScroll : SpellScroll - { - [Constructible] - public EssenceOfWindScroll(int amount = 1) - : base(610, 0x2D5B, amount) => - Hue = 0x8FD; - - public EssenceOfWindScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DryadAllureScroll : SpellScroll - { - [Constructible] - public DryadAllureScroll(int amount = 1) - : base(611, 0x2D5C, amount) => - Hue = 0x8FD; - - public DryadAllureScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class EtherealVoyageScroll : SpellScroll - { - [Constructible] - public EtherealVoyageScroll(int amount = 1) - : base(612, 0x2D5D, amount) => - Hue = 0x8FD; - - public EtherealVoyageScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class WordOfDeathScroll : SpellScroll - { - [Constructible] - public WordOfDeathScroll(int amount = 1) - : base(613, 0x2D5E, amount) => - Hue = 0x8FD; - - public WordOfDeathScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class GiftOfLifeScroll : SpellScroll - { - [Constructible] - public GiftOfLifeScroll(int amount = 1) - : base(614, 0x2D5F, amount) => - Hue = 0x8FD; - - public GiftOfLifeScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class ArcaneEmpowermentScroll : SpellScroll - { - [Constructible] - public ArcaneEmpowermentScroll(int amount = 1) - : base(615, 0x2D60, amount) => - Hue = 0x8FD; - - public ArcaneEmpowermentScroll(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/BlessScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/BlessScroll.cs index a01d191aa..4378ae710 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/BlessScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/BlessScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class BlessScroll : SpellScroll - { - [Constructible] - public BlessScroll(int amount = 1) : base(16, 0x1F3D, amount) + public class BlessScroll : SpellScroll { + [Constructible] + public BlessScroll(int amount = 1) : base(16, 0x1F3D, amount) + { + } + + public BlessScroll(Serial serial) : base(serial) + { + } + + 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 BlessScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/FireballScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/FireballScroll.cs index f93965561..833084ed5 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/FireballScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/FireballScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class FireballScroll : SpellScroll - { - [Constructible] - public FireballScroll(int amount = 1) : base(17, 0x1F3E, amount) + public class FireballScroll : SpellScroll { + [Constructible] + public FireballScroll(int amount = 1) : base(17, 0x1F3E, amount) + { + } + + public FireballScroll(Serial serial) : base(serial) + { + } + + 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 FireballScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/MagicLockScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/MagicLockScroll.cs index f9991fe73..ccca0f9b9 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/MagicLockScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/MagicLockScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class MagicLockScroll : SpellScroll - { - [Constructible] - public MagicLockScroll(int amount = 1) : base(18, 0x1F3F, amount) + public class MagicLockScroll : SpellScroll { + [Constructible] + public MagicLockScroll(int amount = 1) : base(18, 0x1F3F, amount) + { + } + + public MagicLockScroll(Serial serial) : base(serial) + { + } + + 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 MagicLockScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/PoisonScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/PoisonScroll.cs index 158a7a43b..20aff3a2e 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/PoisonScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/PoisonScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class PoisonScroll : SpellScroll - { - [Constructible] - public PoisonScroll(int amount = 1) : base(19, 0x1F40, amount) + public class PoisonScroll : SpellScroll { + [Constructible] + public PoisonScroll(int amount = 1) : base(19, 0x1F40, amount) + { + } + + public PoisonScroll(Serial serial) : base(serial) + { + } + + 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 PoisonScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/TelekinesisScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/TelekinesisScroll.cs index d75a89775..5984a25c3 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/TelekinesisScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/TelekinesisScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class TelekinesisScroll : SpellScroll - { - [Constructible] - public TelekinesisScroll(int amount = 1) : base(20, 0x1F41, amount) + public class TelekinesisScroll : SpellScroll { + [Constructible] + public TelekinesisScroll(int amount = 1) : base(20, 0x1F41, amount) + { + } + + public TelekinesisScroll(Serial serial) : base(serial) + { + } + + 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 TelekinesisScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/TeleportScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/TeleportScroll.cs index b7035cf41..a09bf97b4 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/TeleportScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/TeleportScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class TeleportScroll : SpellScroll - { - [Constructible] - public TeleportScroll(int amount = 1) : base(21, 0x1F42, amount) + public class TeleportScroll : SpellScroll { + [Constructible] + public TeleportScroll(int amount = 1) : base(21, 0x1F42, amount) + { + } + + public TeleportScroll(Serial serial) : base(serial) + { + } + + 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 TeleportScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/UnlockScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/UnlockScroll.cs index 9a061480f..f3584dc96 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/UnlockScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/UnlockScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class UnlockScroll : SpellScroll - { - [Constructible] - public UnlockScroll(int amount = 1) : base(22, 0x1F43, amount) + public class UnlockScroll : SpellScroll { + [Constructible] + public UnlockScroll(int amount = 1) : base(22, 0x1F43, amount) + { + } + + public UnlockScroll(Serial serial) : base(serial) + { + } + + 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 UnlockScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/WallOfStoneScroll.cs b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/WallOfStoneScroll.cs index e61cc6436..39a4ba945 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/WallOfStoneScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Scrolls/Third Circle/WallOfStoneScroll.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class WallOfStoneScroll : SpellScroll - { - [Constructible] - public WallOfStoneScroll(int amount = 1) : base(23, 0x1F44, amount) + public class WallOfStoneScroll : SpellScroll { + [Constructible] + public WallOfStoneScroll(int amount = 1) : base(23, 0x1F44, amount) + { + } + + public WallOfStoneScroll(Serial serial) : base(serial) + { + } + + 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 WallOfStoneScroll(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Spellbook.cs b/Projects/UOContent/Items/Skill Items/Magical/Spellbook.cs index 1b2a4cd2f..ad4999ff7 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Spellbook.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Spellbook.cs @@ -10,850 +10,859 @@ using Server.Targeting; namespace Server.Items { - public enum SpellbookType - { - Invalid = -1, - Regular, - Necromancer, - Paladin, - Ninja, - Samurai, - Arcanist, - Mystic - } - - public enum BookQuality - { - Regular, - Exceptional - } - - public class Spellbook : Item, ICraftable, ISlayer - { - private static readonly Dictionary> m_Table = new Dictionary>(); - - private static readonly int[] m_LegendPropertyCounts = + public enum SpellbookType { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 properties : 21/52 : 40% - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 property : 15/52 : 29% - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 2 properties : 10/52 : 19% - 3, 3, 3, 3, 3, 3 // 3 properties : 6/52 : 12% - }; - - private static readonly int[] m_ElderPropertyCounts = - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 properties : 15/34 : 44% - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 property : 10/34 : 29% - 2, 2, 2, 2, 2, 2, // 2 properties : 6/34 : 18% - 3, 3, 3 // 3 properties : 3/34 : 9% - }; - - private static readonly int[] m_GrandPropertyCounts = - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 properties : 10/20 : 50% - 1, 1, 1, 1, 1, 1, // 1 property : 6/20 : 30% - 2, 2, 2, // 2 properties : 3/20 : 15% - 3 // 3 properties : 1/20 : 5% - }; - - private static readonly int[] m_MasterPropertyCounts = - { - 0, 0, 0, 0, 0, 0, // 0 properties : 6/10 : 60% - 1, 1, 1, // 1 property : 3/10 : 30% - 2 // 2 properties : 1/10 : 10% - }; - - private static readonly int[] m_AdeptPropertyCounts = - { - 0, 0, 0, // 0 properties : 3/4 : 75% - 1 // 1 property : 1/4 : 25% - }; - - private ulong m_Content; - - private Mobile m_Crafter; - private string m_EngravedText; - private BookQuality m_Quality; - - private SlayerName m_Slayer; - private SlayerName m_Slayer2; - - [Constructible] - public Spellbook(ulong content = 0, int itemID = 0xEFA) : base(itemID) - { - Attributes = new AosAttributes(this); - SkillBonuses = new AosSkillBonuses(this); - - Weight = 3.0; - Layer = Layer.OneHanded; - LootType = LootType.Blessed; - - Content = content; + Invalid = -1, + Regular, + Necromancer, + Paladin, + Ninja, + Samurai, + Arcanist, + Mystic } - public Spellbook(Serial serial) : base(serial) + public enum BookQuality { + Regular, + Exceptional } - [CommandProperty(AccessLevel.GameMaster)] - public string EngravedText + public class Spellbook : Item, ICraftable, ISlayer { - get => m_EngravedText; - set - { - m_EngravedText = value; - InvalidateProperties(); - } - } + private static readonly Dictionary> m_Table = new Dictionary>(); - [CommandProperty(AccessLevel.GameMaster)] - public BookQuality Quality - { - get => m_Quality; - set - { - m_Quality = value; - InvalidateProperties(); - } - } - - public override bool DisplayWeight => false; - - [CommandProperty(AccessLevel.GameMaster)] - public AosAttributes Attributes { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public AosSkillBonuses SkillBonuses { get; private set; } - - public virtual SpellbookType SpellbookType => SpellbookType.Regular; - public virtual int BookOffset => 0; - public virtual int BookCount => 64; - - [CommandProperty(AccessLevel.GameMaster)] - public ulong Content - { - get => m_Content; - set - { - if (m_Content != value) + private static readonly int[] m_LegendPropertyCounts = { - m_Content = value; + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 properties : 21/52 : 40% + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 property : 15/52 : 29% + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 2 properties : 10/52 : 19% + 3, 3, 3, 3, 3, 3 // 3 properties : 6/52 : 12% + }; - SpellCount = 0; - - while (value > 0) - { - SpellCount += (int)(value & 0x1); - value >>= 1; - } - - InvalidateProperties(); - } - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int SpellCount { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Crafter - { - get => m_Crafter; - set - { - m_Crafter = value; - InvalidateProperties(); - } - } - - public override bool DisplayLootType => Core.AOS; - - public virtual int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, - BaseTool tool, CraftItem craftItem, int resHue) - { - int magery = from.Skills.Magery.BaseFixedPoint; - - if (magery >= 800) - { - int[] propertyCounts; - int minIntensity; - int maxIntensity; - - if (magery >= 1000) + private static readonly int[] m_ElderPropertyCounts = { - if (magery >= 1200) - propertyCounts = m_LegendPropertyCounts; - else if (magery >= 1100) - propertyCounts = m_ElderPropertyCounts; - else - propertyCounts = m_GrandPropertyCounts; + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 properties : 15/34 : 44% + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 property : 10/34 : 29% + 2, 2, 2, 2, 2, 2, // 2 properties : 6/34 : 18% + 3, 3, 3 // 3 properties : 3/34 : 9% + }; - minIntensity = 55; - maxIntensity = 75; - } - else if (magery >= 900) + private static readonly int[] m_GrandPropertyCounts = { - propertyCounts = m_MasterPropertyCounts; - minIntensity = 25; - maxIntensity = 45; - } - else + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 properties : 10/20 : 50% + 1, 1, 1, 1, 1, 1, // 1 property : 6/20 : 30% + 2, 2, 2, // 2 properties : 3/20 : 15% + 3 // 3 properties : 1/20 : 5% + }; + + private static readonly int[] m_MasterPropertyCounts = { - propertyCounts = m_AdeptPropertyCounts; - minIntensity = 0; - maxIntensity = 15; + 0, 0, 0, 0, 0, 0, // 0 properties : 6/10 : 60% + 1, 1, 1, // 1 property : 3/10 : 30% + 2 // 2 properties : 1/10 : 10% + }; + + private static readonly int[] m_AdeptPropertyCounts = + { + 0, 0, 0, // 0 properties : 3/4 : 75% + 1 // 1 property : 1/4 : 25% + }; + + private ulong m_Content; + + private Mobile m_Crafter; + private string m_EngravedText; + private BookQuality m_Quality; + + private SlayerName m_Slayer; + private SlayerName m_Slayer2; + + [Constructible] + public Spellbook(ulong content = 0, int itemID = 0xEFA) : base(itemID) + { + Attributes = new AosAttributes(this); + SkillBonuses = new AosSkillBonuses(this); + + Weight = 3.0; + Layer = Layer.OneHanded; + LootType = LootType.Blessed; + + Content = content; } - int propertyCount = propertyCounts.RandomElement(); - - BaseRunicTool.ApplyAttributesTo(this, true, 0, propertyCount, minIntensity, maxIntensity); - } - - if (makersMark) - Crafter = from; - - m_Quality = (BookQuality)(quality - 1); - - return quality; - } - // Currently though there are no dual slayer spellbooks, OSI has a habit of putting dual slayer stuff in later - - [CommandProperty(AccessLevel.GameMaster)] - public SlayerName Slayer - { - get => m_Slayer; - set - { - m_Slayer = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public SlayerName Slayer2 - { - get => m_Slayer2; - set - { - m_Slayer2 = value; - InvalidateProperties(); - } - } - - public static void Initialize() - { - EventSink.OpenSpellbookRequest += EventSink_OpenSpellbookRequest; - EventSink.CastSpellRequest += EventSink_CastSpellRequest; - EventSink.TargetedSpell += EventSink_TargetedSpell; - - CommandSystem.Register("AllSpells", AccessLevel.GameMaster, AllSpells_OnCommand); - } - - [Usage("AllSpells")] - [Description("Completely fills a targeted spellbook with scrolls.")] - private static void AllSpells_OnCommand(CommandEventArgs e) - { - e.Mobile.BeginTarget(-1, false, TargetFlags.None, AllSpells_OnTarget); - e.Mobile.SendMessage("Target the spellbook to fill."); - } - - private static void AllSpells_OnTarget(Mobile from, object obj) - { - if (obj is Spellbook book) - { - if (book.BookCount == 64) - book.Content = ulong.MaxValue; - else - book.Content = (1ul << book.BookCount) - 1; - - from.SendMessage("The spellbook has been filled."); - - CommandLogging.WriteLine(from, "{0} {1} filling spellbook {2}", from.AccessLevel, - CommandLogging.Format(from), CommandLogging.Format(book)); - } - else - { - from.BeginTarget(-1, false, TargetFlags.None, AllSpells_OnTarget); - from.SendMessage("That is not a spellbook. Try again."); - } - } - - private static void EventSink_OpenSpellbookRequest(Mobile from, int typeID) - { - if (!DesignContext.Check(from)) - return; // They are customizing - - var type = typeID switch - { - 1 => SpellbookType.Regular, - 2 => SpellbookType.Necromancer, - 3 => SpellbookType.Paladin, - 4 => SpellbookType.Ninja, - 5 => SpellbookType.Samurai, - 6 => SpellbookType.Arcanist, - 7 => SpellbookType.Mystic, - _ => SpellbookType.Regular - }; - - Spellbook book = Find(from, -1, type); - - book?.DisplayTo(from); - } - - private static void EventSink_TargetedSpell(Mobile from, IEntity target, int spellId) - { - if (!DesignContext.Check(from)) return; // They are customizing - - Spellbook book = Find(from, spellId); - - if (book?.HasSpell(spellId) != true) - { - from.SendLocalizedMessage(500015); // You do not have that spell! - return; - } - - SpecialMove move = SpellRegistry.GetSpecialMove(spellId); - - if (move != null) - SpecialMove.SetCurrentMove(from, move); - else - SpellRegistry.NewSpell(spellId, from, null)?.Cast(); - } - - private static void EventSink_CastSpellRequest(Mobile from, int spellID, Item item) - { - if (!DesignContext.Check(from)) - return; // They are customizing - - Spellbook book = item as Spellbook; - - if (book?.HasSpell(spellID) != true) - book = Find(from, spellID); - - if (book?.HasSpell(spellID) == true) - { - SpecialMove move = SpellRegistry.GetSpecialMove(spellID); - - if (move != null) + public Spellbook(Serial serial) : base(serial) { - SpecialMove.SetCurrentMove(from, move); - } - else - { - Spell spell = SpellRegistry.NewSpell(spellID, from, null); - - if (spell != null) - spell.Cast(); - else - from.SendLocalizedMessage(502345); // This spell has been temporarily disabled. - } - } - else - { - from.SendLocalizedMessage(500015); // You do not have that spell! - } - } - - public static SpellbookType GetTypeForSpell(int spellID) - { - if (spellID >= 0 && spellID < 64) - return SpellbookType.Regular; - if (spellID >= 100 && spellID < 117) - return SpellbookType.Necromancer; - if (spellID >= 200 && spellID < 210) - return SpellbookType.Paladin; - if (spellID >= 400 && spellID < 406) - return SpellbookType.Samurai; - if (spellID >= 500 && spellID < 508) - return SpellbookType.Ninja; - if (spellID >= 600 && spellID < 617) - return SpellbookType.Arcanist; - if (spellID >= 677 && spellID < 693) - return SpellbookType.Mystic; - - return SpellbookType.Invalid; - } - - public static Spellbook FindRegular(Mobile from) => Find(from, -1, SpellbookType.Regular); - - public static Spellbook FindNecromancer(Mobile from) => Find(from, -1, SpellbookType.Necromancer); - - public static Spellbook FindPaladin(Mobile from) => Find(from, -1, SpellbookType.Paladin); - - public static Spellbook FindSamurai(Mobile from) => Find(from, -1, SpellbookType.Samurai); - - public static Spellbook FindNinja(Mobile from) => Find(from, -1, SpellbookType.Ninja); - - public static Spellbook FindArcanist(Mobile from) => Find(from, -1, SpellbookType.Arcanist); - - public static Spellbook FindMystic(Mobile from) => Find(from, -1, SpellbookType.Mystic); - - public static Spellbook Find(Mobile from, int spellID) => Find(from, spellID, GetTypeForSpell(spellID)); - - public static Spellbook Find(Mobile from, int spellID, SpellbookType type) - { - if (from == null) - return null; - - if (from.Deleted) - { - m_Table.Remove(from); - return null; - } - - bool searchAgain = false; - - if (!m_Table.TryGetValue(from, out List list)) - m_Table[from] = list = FindAllSpellbooks(from); - else - searchAgain = true; - - Spellbook book = FindSpellbookInList(list, from, spellID, type); - - if (book == null && searchAgain) - { - m_Table[from] = list = FindAllSpellbooks(from); - - book = FindSpellbookInList(list, from, spellID, type); - } - - return book; - } - - public static Spellbook FindSpellbookInList(List list, Mobile from, int spellID, SpellbookType type) - { - Container pack = from.Backpack; - - for (int i = list.Count - 1; i >= 0; --i) - { - if (i >= list.Count) - continue; - - Spellbook book = list[i]; - - if (!book.Deleted && (book.Parent == from || (pack != null && book.Parent == pack)) && - ValidateSpellbook(book, spellID, type)) - return book; - - list.RemoveAt(i); - } - - return null; - } - - public static List FindAllSpellbooks(Mobile from) - { - List list = new List(); - - Spellbook spellbook = FindEquippedSpellbook(from); - - if (spellbook != null) - list.Add(spellbook); - - Container pack = from.Backpack; - - for (int i = 0; i < pack?.Items.Count; ++i) - if (pack.Items[i] is Spellbook sp) - list.Add(sp); - - return list; - } - - public static Spellbook FindEquippedSpellbook(Mobile from) => from.FindItemOnLayer(Layer.OneHanded) as Spellbook; - - public static bool ValidateSpellbook(Spellbook book, int spellID, SpellbookType type) => book.SpellbookType == type && (spellID == -1 || book.HasSpell(spellID)); - - public override bool AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted) - { - if (!Ethic.CheckTrade(from, to, newOwner, this)) - return false; - - return base.AllowSecureTrade(from, to, newOwner, accepted); - } - - public override bool CanEquip(Mobile from) - { - if (!Ethic.CheckEquip(from, this)) return false; - - if (!from.CanBeginAction()) return false; - - return base.CanEquip(from); - } - - public override bool AllowEquippedCast(Mobile from) => true; - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (dropped is SpellScroll scroll && scroll.Amount == 1) - { - SpellbookType type = GetTypeForSpell(scroll.SpellID); - - if (type != SpellbookType) return false; - - if (HasSpell(scroll.SpellID)) - { - from.SendLocalizedMessage(500179); // That spell is already present in that spellbook. - return false; } - int val = scroll.SpellID - BookOffset; - - if (val >= 0 && val < BookCount) + [CommandProperty(AccessLevel.GameMaster)] + public string EngravedText { - m_Content |= (ulong)1 << val; - ++SpellCount; - - InvalidateProperties(); - - scroll.Delete(); - - from.Send(new PlaySound(0x249, GetWorldLocation())); - return true; - } - } - - return false; - } - - public override void OnAfterDuped(Item newItem) - { - if (!(newItem is Spellbook book)) - return; - - book.Attributes = new AosAttributes(newItem, Attributes); - book.SkillBonuses = new AosSkillBonuses(newItem, SkillBonuses); - } - - public override void OnAdded(IEntity parent) - { - if (Core.AOS && parent is Mobile from) - { - SkillBonuses.AddTo(from); - - int strBonus = Attributes.BonusStr; - int dexBonus = Attributes.BonusDex; - int intBonus = Attributes.BonusInt; - - if (strBonus != 0 || dexBonus != 0 || intBonus != 0) - { - string modName = Serial.ToString(); - - if (strBonus != 0) - from.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero)); - - if (dexBonus != 0) - from.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero)); - - if (intBonus != 0) - from.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero)); + get => m_EngravedText; + set + { + m_EngravedText = value; + InvalidateProperties(); + } } - from.CheckStatTimers(); - } - } - - public override void OnRemoved(IEntity parent) - { - if (Core.AOS && parent is Mobile from) - { - SkillBonuses.Remove(); - - string modName = Serial.ToString(); - - from.RemoveStatMod($"{modName}Str"); - from.RemoveStatMod($"{modName}Dex"); - from.RemoveStatMod($"{modName}Int"); - - from.CheckStatTimers(); - } - } - - public bool HasSpell(int spellID) - { - spellID -= BookOffset; - - return spellID >= 0 && spellID < BookCount && (m_Content & (ulong)1 << spellID) != 0; - } - - public void DisplayTo(Mobile to) - { - // The client must know about the spellbook or it will crash! - - NetState ns = to.NetState; - - if (ns == null) - return; - - if (Parent == null) - { - to.Send(WorldPacket); - } - else if (Parent is Item) - { - // What will happen if the client doesn't know about our parent? - if (ns.ContainerGridLines) - to.Send(new ContainerContentUpdate6017(this)); - else - to.Send(new ContainerContentUpdate(this)); - } - else if (Parent is Mobile) - { - // What will happen if the client doesn't know about our parent? - to.Send(new EquipUpdate(this)); - } - - if (ns.HighSeas) - to.Send(new DisplaySpellbookHS(Serial)); - else - to.Send(new DisplaySpellbook(Serial)); - - if (ObjectPropertyList.Enabled) - { - if (ns.NewSpellbook) + [CommandProperty(AccessLevel.GameMaster)] + public BookQuality Quality { - to.Send(new NewSpellbookContent(Serial, ItemID, BookOffset + 1, m_Content)); - } - else - { - if (ns.ContainerGridLines) - to.Send(new SpellbookContent6017(Serial, BookOffset + 1, m_Content)); - else - to.Send(new SpellbookContent(Serial, BookOffset + 1, m_Content)); - } - } - else - { - if (ns.ContainerGridLines) - to.Send(new SpellbookContent6017(Serial, BookOffset + 1, m_Content)); - else - to.Send(new SpellbookContent(Serial, BookOffset + 1, m_Content)); - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_Quality == BookQuality.Exceptional) - list.Add(1063341); // exceptional - - if (m_EngravedText != null) - list.Add(1072305, m_EngravedText); // Engraved: ~1_INSCRIPTION~ - - if (m_Crafter != null) - list.Add(1050043, m_Crafter.Name); // crafted by ~1_NAME~ - - SkillBonuses.GetProperties(list); - - if (m_Slayer != SlayerName.None) - { - SlayerEntry entry = SlayerGroup.GetEntryByName(m_Slayer); - if (entry != null) - list.Add(entry.Title); - } - - if (m_Slayer2 != SlayerName.None) - { - SlayerEntry entry = SlayerGroup.GetEntryByName(m_Slayer2); - if (entry != null) - list.Add(entry.Title); - } - - int prop; - - if ((prop = Attributes.WeaponDamage) != 0) - list.Add(1060401, prop.ToString()); // damage increase ~1_val~% - - if ((prop = Attributes.DefendChance) != 0) - list.Add(1060408, prop.ToString()); // defense chance increase ~1_val~% - - if ((prop = Attributes.BonusDex) != 0) - list.Add(1060409, prop.ToString()); // dexterity bonus ~1_val~ - - if ((prop = Attributes.EnhancePotions) != 0) - list.Add(1060411, prop.ToString()); // enhance potions ~1_val~% - - if ((prop = Attributes.CastRecovery) != 0) - list.Add(1060412, prop.ToString()); // faster cast recovery ~1_val~ - - if ((prop = Attributes.CastSpeed) != 0) - list.Add(1060413, prop.ToString()); // faster casting ~1_val~ - - if ((prop = Attributes.AttackChance) != 0) - list.Add(1060415, prop.ToString()); // hit chance increase ~1_val~% - - if ((prop = Attributes.BonusHits) != 0) - list.Add(1060431, prop.ToString()); // hit point increase ~1_val~ - - if ((prop = Attributes.BonusInt) != 0) - list.Add(1060432, prop.ToString()); // intelligence bonus ~1_val~ - - if ((prop = Attributes.LowerManaCost) != 0) - list.Add(1060433, prop.ToString()); // lower mana cost ~1_val~% - - if ((prop = Attributes.LowerRegCost) != 0) - list.Add(1060434, prop.ToString()); // lower reagent cost ~1_val~% - - if ((prop = Attributes.Luck) != 0) - list.Add(1060436, prop.ToString()); // luck ~1_val~ - - if ((prop = Attributes.BonusMana) != 0) - list.Add(1060439, prop.ToString()); // mana increase ~1_val~ - - if ((prop = Attributes.RegenMana) != 0) - list.Add(1060440, prop.ToString()); // mana regeneration ~1_val~ - - if (Attributes.NightSight != 0) - list.Add(1060441); // night sight - - if ((prop = Attributes.ReflectPhysical) != 0) - list.Add(1060442, prop.ToString()); // reflect physical damage ~1_val~% - - if ((prop = Attributes.RegenStam) != 0) - list.Add(1060443, prop.ToString()); // stamina regeneration ~1_val~ - - if ((prop = Attributes.RegenHits) != 0) - list.Add(1060444, prop.ToString()); // hit point regeneration ~1_val~ - - if (Attributes.SpellChanneling != 0) - list.Add(1060482); // spell channeling - - if ((prop = Attributes.SpellDamage) != 0) - list.Add(1060483, prop.ToString()); // spell damage increase ~1_val~% - - if ((prop = Attributes.BonusStam) != 0) - list.Add(1060484, prop.ToString()); // stamina increase ~1_val~ - - if ((prop = Attributes.BonusStr) != 0) - list.Add(1060485, prop.ToString()); // strength bonus ~1_val~ - - if ((prop = Attributes.WeaponSpeed) != 0) - list.Add(1060486, prop.ToString()); // swing speed increase ~1_val~% - - if (Core.ML && (prop = Attributes.IncreasedKarmaLoss) != 0) - list.Add(1075210, prop.ToString()); // Increased Karma Loss ~1val~% - - list.Add(1042886, SpellCount.ToString()); // ~1_NUMBERS_OF_SPELLS~ Spells - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - if (m_Crafter != null) - LabelTo(from, 1050043, m_Crafter.Name); // crafted by ~1_NAME~ - - LabelTo(from, 1042886, SpellCount.ToString()); - } - - public override void OnDoubleClick(Mobile from) - { - Container pack = from.Backpack; - - if (Parent == from || (pack != null && Parent == pack)) - DisplayTo(from); - else - from.SendLocalizedMessage( - 500207); // The spellbook must be in your backpack (and not in a container within) to open. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(5); // version - - writer.Write((byte)m_Quality); - - writer.Write(m_EngravedText); - - writer.Write(m_Crafter); - - writer.Write((int)m_Slayer); - writer.Write((int)m_Slayer2); - - Attributes.Serialize(writer); - SkillBonuses.Serialize(writer); - - writer.Write(m_Content); - writer.Write(SpellCount); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 5: - { - m_Quality = (BookQuality)reader.ReadByte(); - - goto case 4; - } - case 4: - { - m_EngravedText = reader.ReadString(); - - goto case 3; - } - case 3: - { - m_Crafter = reader.ReadMobile(); - goto case 2; - } - case 2: - { - m_Slayer = (SlayerName)reader.ReadInt(); - m_Slayer2 = (SlayerName)reader.ReadInt(); - goto case 1; - } - case 1: - { - Attributes = new AosAttributes(this, reader); - SkillBonuses = new AosSkillBonuses(this, reader); - - goto case 0; - } - case 0: - { - m_Content = reader.ReadULong(); - SpellCount = reader.ReadInt(); - - break; - } - } - - Attributes ??= new AosAttributes(this); - SkillBonuses ??= new AosSkillBonuses(this); - - if (Core.AOS && Parent is Mobile mobile) - SkillBonuses.AddTo(mobile); - - int strBonus = Attributes.BonusStr; - int dexBonus = Attributes.BonusDex; - int intBonus = Attributes.BonusInt; - - if (Parent is Mobile m) - { - if (strBonus != 0 || dexBonus != 0 || intBonus != 0) - { - string modName = Serial.ToString(); - - if (strBonus != 0) - m.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero)); - - if (dexBonus != 0) - m.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero)); - - if (intBonus != 0) - m.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero)); + get => m_Quality; + set + { + m_Quality = value; + InvalidateProperties(); + } } - m.CheckStatTimers(); - } + public override bool DisplayWeight => false; + + [CommandProperty(AccessLevel.GameMaster)] + public AosAttributes Attributes { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public AosSkillBonuses SkillBonuses { get; private set; } + + public virtual SpellbookType SpellbookType => SpellbookType.Regular; + public virtual int BookOffset => 0; + public virtual int BookCount => 64; + + [CommandProperty(AccessLevel.GameMaster)] + public ulong Content + { + get => m_Content; + set + { + if (m_Content != value) + { + m_Content = value; + + SpellCount = 0; + + while (value > 0) + { + SpellCount += (int)(value & 0x1); + value >>= 1; + } + + InvalidateProperties(); + } + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int SpellCount { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Crafter + { + get => m_Crafter; + set + { + m_Crafter = value; + InvalidateProperties(); + } + } + + public override bool DisplayLootType => Core.AOS; + + public virtual int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, + BaseTool tool, CraftItem craftItem, int resHue + ) + { + var magery = from.Skills.Magery.BaseFixedPoint; + + if (magery >= 800) + { + int[] propertyCounts; + int minIntensity; + int maxIntensity; + + if (magery >= 1000) + { + if (magery >= 1200) + propertyCounts = m_LegendPropertyCounts; + else if (magery >= 1100) + propertyCounts = m_ElderPropertyCounts; + else + propertyCounts = m_GrandPropertyCounts; + + minIntensity = 55; + maxIntensity = 75; + } + else if (magery >= 900) + { + propertyCounts = m_MasterPropertyCounts; + minIntensity = 25; + maxIntensity = 45; + } + else + { + propertyCounts = m_AdeptPropertyCounts; + minIntensity = 0; + maxIntensity = 15; + } + + var propertyCount = propertyCounts.RandomElement(); + + BaseRunicTool.ApplyAttributesTo(this, true, 0, propertyCount, minIntensity, maxIntensity); + } + + if (makersMark) + Crafter = from; + + m_Quality = (BookQuality)(quality - 1); + + return quality; + } + // Currently though there are no dual slayer spellbooks, OSI has a habit of putting dual slayer stuff in later + + [CommandProperty(AccessLevel.GameMaster)] + public SlayerName Slayer + { + get => m_Slayer; + set + { + m_Slayer = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public SlayerName Slayer2 + { + get => m_Slayer2; + set + { + m_Slayer2 = value; + InvalidateProperties(); + } + } + + public static void Initialize() + { + EventSink.OpenSpellbookRequest += EventSink_OpenSpellbookRequest; + EventSink.CastSpellRequest += EventSink_CastSpellRequest; + EventSink.TargetedSpell += EventSink_TargetedSpell; + + CommandSystem.Register("AllSpells", AccessLevel.GameMaster, AllSpells_OnCommand); + } + + [Usage("AllSpells")] + [Description("Completely fills a targeted spellbook with scrolls.")] + private static void AllSpells_OnCommand(CommandEventArgs e) + { + e.Mobile.BeginTarget(-1, false, TargetFlags.None, AllSpells_OnTarget); + e.Mobile.SendMessage("Target the spellbook to fill."); + } + + private static void AllSpells_OnTarget(Mobile from, object obj) + { + if (obj is Spellbook book) + { + if (book.BookCount == 64) + book.Content = ulong.MaxValue; + else + book.Content = (1ul << book.BookCount) - 1; + + from.SendMessage("The spellbook has been filled."); + + CommandLogging.WriteLine( + from, + "{0} {1} filling spellbook {2}", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(book) + ); + } + else + { + from.BeginTarget(-1, false, TargetFlags.None, AllSpells_OnTarget); + from.SendMessage("That is not a spellbook. Try again."); + } + } + + private static void EventSink_OpenSpellbookRequest(Mobile from, int typeID) + { + if (!DesignContext.Check(from)) + return; // They are customizing + + var type = typeID switch + { + 1 => SpellbookType.Regular, + 2 => SpellbookType.Necromancer, + 3 => SpellbookType.Paladin, + 4 => SpellbookType.Ninja, + 5 => SpellbookType.Samurai, + 6 => SpellbookType.Arcanist, + 7 => SpellbookType.Mystic, + _ => SpellbookType.Regular + }; + + var book = Find(from, -1, type); + + book?.DisplayTo(from); + } + + private static void EventSink_TargetedSpell(Mobile from, IEntity target, int spellId) + { + if (!DesignContext.Check(from)) return; // They are customizing + + var book = Find(from, spellId); + + if (book?.HasSpell(spellId) != true) + { + from.SendLocalizedMessage(500015); // You do not have that spell! + return; + } + + var move = SpellRegistry.GetSpecialMove(spellId); + + if (move != null) + SpecialMove.SetCurrentMove(from, move); + else + SpellRegistry.NewSpell(spellId, from, null)?.Cast(); + } + + private static void EventSink_CastSpellRequest(Mobile from, int spellID, Item item) + { + if (!DesignContext.Check(from)) + return; // They are customizing + + var book = item as Spellbook; + + if (book?.HasSpell(spellID) != true) + book = Find(from, spellID); + + if (book?.HasSpell(spellID) == true) + { + var move = SpellRegistry.GetSpecialMove(spellID); + + if (move != null) + { + SpecialMove.SetCurrentMove(from, move); + } + else + { + var spell = SpellRegistry.NewSpell(spellID, from, null); + + if (spell != null) + spell.Cast(); + else + from.SendLocalizedMessage(502345); // This spell has been temporarily disabled. + } + } + else + { + from.SendLocalizedMessage(500015); // You do not have that spell! + } + } + + public static SpellbookType GetTypeForSpell(int spellID) + { + if (spellID >= 0 && spellID < 64) + return SpellbookType.Regular; + if (spellID >= 100 && spellID < 117) + return SpellbookType.Necromancer; + if (spellID >= 200 && spellID < 210) + return SpellbookType.Paladin; + if (spellID >= 400 && spellID < 406) + return SpellbookType.Samurai; + if (spellID >= 500 && spellID < 508) + return SpellbookType.Ninja; + if (spellID >= 600 && spellID < 617) + return SpellbookType.Arcanist; + if (spellID >= 677 && spellID < 693) + return SpellbookType.Mystic; + + return SpellbookType.Invalid; + } + + public static Spellbook FindRegular(Mobile from) => Find(from, -1, SpellbookType.Regular); + + public static Spellbook FindNecromancer(Mobile from) => Find(from, -1, SpellbookType.Necromancer); + + public static Spellbook FindPaladin(Mobile from) => Find(from, -1, SpellbookType.Paladin); + + public static Spellbook FindSamurai(Mobile from) => Find(from, -1, SpellbookType.Samurai); + + public static Spellbook FindNinja(Mobile from) => Find(from, -1, SpellbookType.Ninja); + + public static Spellbook FindArcanist(Mobile from) => Find(from, -1, SpellbookType.Arcanist); + + public static Spellbook FindMystic(Mobile from) => Find(from, -1, SpellbookType.Mystic); + + public static Spellbook Find(Mobile from, int spellID) => Find(from, spellID, GetTypeForSpell(spellID)); + + public static Spellbook Find(Mobile from, int spellID, SpellbookType type) + { + if (from == null) + return null; + + if (from.Deleted) + { + m_Table.Remove(from); + return null; + } + + var searchAgain = false; + + if (!m_Table.TryGetValue(from, out var list)) + m_Table[from] = list = FindAllSpellbooks(from); + else + searchAgain = true; + + var book = FindSpellbookInList(list, from, spellID, type); + + if (book == null && searchAgain) + { + m_Table[from] = list = FindAllSpellbooks(from); + + book = FindSpellbookInList(list, from, spellID, type); + } + + return book; + } + + public static Spellbook FindSpellbookInList(List list, Mobile from, int spellID, SpellbookType type) + { + var pack = from.Backpack; + + for (var i = list.Count - 1; i >= 0; --i) + { + if (i >= list.Count) + continue; + + var book = list[i]; + + if (!book.Deleted && (book.Parent == from || pack != null && book.Parent == pack) && + ValidateSpellbook(book, spellID, type)) + return book; + + list.RemoveAt(i); + } + + return null; + } + + public static List FindAllSpellbooks(Mobile from) + { + var list = new List(); + + var spellbook = FindEquippedSpellbook(from); + + if (spellbook != null) + list.Add(spellbook); + + var pack = from.Backpack; + + for (var i = 0; i < pack?.Items.Count; ++i) + if (pack.Items[i] is Spellbook sp) + list.Add(sp); + + return list; + } + + public static Spellbook FindEquippedSpellbook(Mobile from) => from.FindItemOnLayer(Layer.OneHanded) as Spellbook; + + public static bool ValidateSpellbook(Spellbook book, int spellID, SpellbookType type) => + book.SpellbookType == type && (spellID == -1 || book.HasSpell(spellID)); + + public override bool AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted) + { + if (!Ethic.CheckTrade(from, to, newOwner, this)) + return false; + + return base.AllowSecureTrade(from, to, newOwner, accepted); + } + + public override bool CanEquip(Mobile from) + { + if (!Ethic.CheckEquip(from, this)) return false; + + if (!from.CanBeginAction()) return false; + + return base.CanEquip(from); + } + + public override bool AllowEquippedCast(Mobile from) => true; + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (dropped is SpellScroll scroll && scroll.Amount == 1) + { + var type = GetTypeForSpell(scroll.SpellID); + + if (type != SpellbookType) return false; + + if (HasSpell(scroll.SpellID)) + { + from.SendLocalizedMessage(500179); // That spell is already present in that spellbook. + return false; + } + + var val = scroll.SpellID - BookOffset; + + if (val >= 0 && val < BookCount) + { + m_Content |= (ulong)1 << val; + ++SpellCount; + + InvalidateProperties(); + + scroll.Delete(); + + from.Send(new PlaySound(0x249, GetWorldLocation())); + return true; + } + } + + return false; + } + + public override void OnAfterDuped(Item newItem) + { + if (!(newItem is Spellbook book)) + return; + + book.Attributes = new AosAttributes(newItem, Attributes); + book.SkillBonuses = new AosSkillBonuses(newItem, SkillBonuses); + } + + public override void OnAdded(IEntity parent) + { + if (Core.AOS && parent is Mobile from) + { + SkillBonuses.AddTo(from); + + var strBonus = Attributes.BonusStr; + var dexBonus = Attributes.BonusDex; + var intBonus = Attributes.BonusInt; + + if (strBonus != 0 || dexBonus != 0 || intBonus != 0) + { + var modName = Serial.ToString(); + + if (strBonus != 0) + from.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero)); + + if (dexBonus != 0) + from.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero)); + + if (intBonus != 0) + from.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero)); + } + + from.CheckStatTimers(); + } + } + + public override void OnRemoved(IEntity parent) + { + if (Core.AOS && parent is Mobile from) + { + SkillBonuses.Remove(); + + var modName = Serial.ToString(); + + from.RemoveStatMod($"{modName}Str"); + from.RemoveStatMod($"{modName}Dex"); + from.RemoveStatMod($"{modName}Int"); + + from.CheckStatTimers(); + } + } + + public bool HasSpell(int spellID) + { + spellID -= BookOffset; + + return spellID >= 0 && spellID < BookCount && (m_Content & ((ulong)1 << spellID)) != 0; + } + + public void DisplayTo(Mobile to) + { + // The client must know about the spellbook or it will crash! + + var ns = to.NetState; + + if (ns == null) + return; + + if (Parent == null) + { + to.Send(WorldPacket); + } + else if (Parent is Item) + { + // What will happen if the client doesn't know about our parent? + if (ns.ContainerGridLines) + to.Send(new ContainerContentUpdate6017(this)); + else + to.Send(new ContainerContentUpdate(this)); + } + else if (Parent is Mobile) + { + // What will happen if the client doesn't know about our parent? + to.Send(new EquipUpdate(this)); + } + + if (ns.HighSeas) + to.Send(new DisplaySpellbookHS(Serial)); + else + to.Send(new DisplaySpellbook(Serial)); + + if (ObjectPropertyList.Enabled) + { + if (ns.NewSpellbook) + { + to.Send(new NewSpellbookContent(Serial, ItemID, BookOffset + 1, m_Content)); + } + else + { + if (ns.ContainerGridLines) + to.Send(new SpellbookContent6017(Serial, BookOffset + 1, m_Content)); + else + to.Send(new SpellbookContent(Serial, BookOffset + 1, m_Content)); + } + } + else + { + if (ns.ContainerGridLines) + to.Send(new SpellbookContent6017(Serial, BookOffset + 1, m_Content)); + else + to.Send(new SpellbookContent(Serial, BookOffset + 1, m_Content)); + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_Quality == BookQuality.Exceptional) + list.Add(1063341); // exceptional + + if (m_EngravedText != null) + list.Add(1072305, m_EngravedText); // Engraved: ~1_INSCRIPTION~ + + if (m_Crafter != null) + list.Add(1050043, m_Crafter.Name); // crafted by ~1_NAME~ + + SkillBonuses.GetProperties(list); + + if (m_Slayer != SlayerName.None) + { + var entry = SlayerGroup.GetEntryByName(m_Slayer); + if (entry != null) + list.Add(entry.Title); + } + + if (m_Slayer2 != SlayerName.None) + { + var entry = SlayerGroup.GetEntryByName(m_Slayer2); + if (entry != null) + list.Add(entry.Title); + } + + int prop; + + if ((prop = Attributes.WeaponDamage) != 0) + list.Add(1060401, prop.ToString()); // damage increase ~1_val~% + + if ((prop = Attributes.DefendChance) != 0) + list.Add(1060408, prop.ToString()); // defense chance increase ~1_val~% + + if ((prop = Attributes.BonusDex) != 0) + list.Add(1060409, prop.ToString()); // dexterity bonus ~1_val~ + + if ((prop = Attributes.EnhancePotions) != 0) + list.Add(1060411, prop.ToString()); // enhance potions ~1_val~% + + if ((prop = Attributes.CastRecovery) != 0) + list.Add(1060412, prop.ToString()); // faster cast recovery ~1_val~ + + if ((prop = Attributes.CastSpeed) != 0) + list.Add(1060413, prop.ToString()); // faster casting ~1_val~ + + if ((prop = Attributes.AttackChance) != 0) + list.Add(1060415, prop.ToString()); // hit chance increase ~1_val~% + + if ((prop = Attributes.BonusHits) != 0) + list.Add(1060431, prop.ToString()); // hit point increase ~1_val~ + + if ((prop = Attributes.BonusInt) != 0) + list.Add(1060432, prop.ToString()); // intelligence bonus ~1_val~ + + if ((prop = Attributes.LowerManaCost) != 0) + list.Add(1060433, prop.ToString()); // lower mana cost ~1_val~% + + if ((prop = Attributes.LowerRegCost) != 0) + list.Add(1060434, prop.ToString()); // lower reagent cost ~1_val~% + + if ((prop = Attributes.Luck) != 0) + list.Add(1060436, prop.ToString()); // luck ~1_val~ + + if ((prop = Attributes.BonusMana) != 0) + list.Add(1060439, prop.ToString()); // mana increase ~1_val~ + + if ((prop = Attributes.RegenMana) != 0) + list.Add(1060440, prop.ToString()); // mana regeneration ~1_val~ + + if (Attributes.NightSight != 0) + list.Add(1060441); // night sight + + if ((prop = Attributes.ReflectPhysical) != 0) + list.Add(1060442, prop.ToString()); // reflect physical damage ~1_val~% + + if ((prop = Attributes.RegenStam) != 0) + list.Add(1060443, prop.ToString()); // stamina regeneration ~1_val~ + + if ((prop = Attributes.RegenHits) != 0) + list.Add(1060444, prop.ToString()); // hit point regeneration ~1_val~ + + if (Attributes.SpellChanneling != 0) + list.Add(1060482); // spell channeling + + if ((prop = Attributes.SpellDamage) != 0) + list.Add(1060483, prop.ToString()); // spell damage increase ~1_val~% + + if ((prop = Attributes.BonusStam) != 0) + list.Add(1060484, prop.ToString()); // stamina increase ~1_val~ + + if ((prop = Attributes.BonusStr) != 0) + list.Add(1060485, prop.ToString()); // strength bonus ~1_val~ + + if ((prop = Attributes.WeaponSpeed) != 0) + list.Add(1060486, prop.ToString()); // swing speed increase ~1_val~% + + if (Core.ML && (prop = Attributes.IncreasedKarmaLoss) != 0) + list.Add(1075210, prop.ToString()); // Increased Karma Loss ~1val~% + + list.Add(1042886, SpellCount.ToString()); // ~1_NUMBERS_OF_SPELLS~ Spells + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + if (m_Crafter != null) + LabelTo(from, 1050043, m_Crafter.Name); // crafted by ~1_NAME~ + + LabelTo(from, 1042886, SpellCount.ToString()); + } + + public override void OnDoubleClick(Mobile from) + { + var pack = from.Backpack; + + if (Parent == from || pack != null && Parent == pack) + DisplayTo(from); + else + from.SendLocalizedMessage( + 500207 + ); // The spellbook must be in your backpack (and not in a container within) to open. + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(5); // version + + writer.Write((byte)m_Quality); + + writer.Write(m_EngravedText); + + writer.Write(m_Crafter); + + writer.Write((int)m_Slayer); + writer.Write((int)m_Slayer2); + + Attributes.Serialize(writer); + SkillBonuses.Serialize(writer); + + writer.Write(m_Content); + writer.Write(SpellCount); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 5: + { + m_Quality = (BookQuality)reader.ReadByte(); + + goto case 4; + } + case 4: + { + m_EngravedText = reader.ReadString(); + + goto case 3; + } + case 3: + { + m_Crafter = reader.ReadMobile(); + goto case 2; + } + case 2: + { + m_Slayer = (SlayerName)reader.ReadInt(); + m_Slayer2 = (SlayerName)reader.ReadInt(); + goto case 1; + } + case 1: + { + Attributes = new AosAttributes(this, reader); + SkillBonuses = new AosSkillBonuses(this, reader); + + goto case 0; + } + case 0: + { + m_Content = reader.ReadULong(); + SpellCount = reader.ReadInt(); + + break; + } + } + + Attributes ??= new AosAttributes(this); + SkillBonuses ??= new AosSkillBonuses(this); + + if (Core.AOS && Parent is Mobile mobile) + SkillBonuses.AddTo(mobile); + + var strBonus = Attributes.BonusStr; + var dexBonus = Attributes.BonusDex; + var intBonus = Attributes.BonusInt; + + if (Parent is Mobile m) + { + if (strBonus != 0 || dexBonus != 0 || intBonus != 0) + { + var modName = Serial.ToString(); + + if (strBonus != 0) + m.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero)); + + if (dexBonus != 0) + m.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero)); + + if (intBonus != 0) + m.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero)); + } + + m.CheckStatTimers(); + } + } } - } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/SpellweavingBook.cs b/Projects/UOContent/Items/Skill Items/Magical/SpellweavingBook.cs index 930dfbf2a..bc81fb368 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/SpellweavingBook.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/SpellweavingBook.cs @@ -1,35 +1,35 @@ namespace Server.Items { - public class SpellweavingBook : Spellbook - { - [Constructible] - public SpellweavingBook(ulong content = 0) : base(content, 0x2D50) + public class SpellweavingBook : Spellbook { - Hue = 0x8A2; + [Constructible] + public SpellweavingBook(ulong content = 0) : base(content, 0x2D50) + { + Hue = 0x8A2; - Layer = Layer.OneHanded; + Layer = Layer.OneHanded; + } + + public SpellweavingBook(Serial serial) : base(serial) + { + } + + public override SpellbookType SpellbookType => SpellbookType.Arcanist; + public override int BookOffset => 600; + public override int BookCount => 16; + + 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(); + } } - - public SpellweavingBook(Serial serial) : base(serial) - { - } - - public override SpellbookType SpellbookType => SpellbookType.Arcanist; - public override int BookOffset => 600; - public override int BookCount => 16; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Misc/Bandage.cs b/Projects/UOContent/Items/Skill Items/Misc/Bandage.cs index 470fce1c6..743af79eb 100644 --- a/Projects/UOContent/Items/Skill Items/Misc/Bandage.cs +++ b/Projects/UOContent/Items/Skill Items/Misc/Bandage.cs @@ -8,514 +8,516 @@ using Server.Targeting; namespace Server.Items { - public class Bandage : Item, IDyable - { - public static int Range = Core.AOS ? 2 : 1; - - [Constructible] - public Bandage(int amount = 1) : base(0xE21) + public class Bandage : Item, IDyable { - Stackable = true; - Amount = amount; - } + public static int Range = Core.AOS ? 2 : 1; - public Bandage(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0.1; - - public virtual bool Dye(Mobile from, DyeTub sender) - { - if (Deleted) - return false; - - Hue = sender.DyedHue; - - return true; - } - - public static void Initialize() - { - EventSink.BandageTargetRequest += EventSink_BandageTargetRequest; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(GetWorldLocation(), Range)) - { - from.RevealingAction(); - - from.SendLocalizedMessage(500948); // Who will you use the bandages on? - - from.Target = new InternalTarget(this); - } - else - { - from.SendLocalizedMessage(500295); // You are too far away to do that. - } - } - - private static void EventSink_BandageTargetRequest(Mobile from, Item item, Mobile target) - { - if (!(item is Bandage b) || b.Deleted) - return; - - if (!from.InRange(b.GetWorldLocation(), Range)) - { - from.SendLocalizedMessage(500295); // You are too far away to do that. - return; - } - - if (from.Target != null) - { - Target.Cancel(from); - from.Target = null; - } - - from.RevealingAction(); - from.SendLocalizedMessage(500948); // Who will you use the bandages on? - - new InternalTarget(b).Invoke(from, target); - } - - private class InternalTarget : Target - { - private readonly Bandage m_Bandage; - - public InternalTarget(Bandage bandage) : base(Bandage.Range, false, TargetFlags.Beneficial) => m_Bandage = bandage; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Bandage.Deleted) - return; - - if (targeted is Mobile mobile) + [Constructible] + public Bandage(int amount = 1) : base(0xE21) { - if (from.InRange(m_Bandage.GetWorldLocation(), Bandage.Range)) - { - if (!(BandageContext.BeginHeal(from, mobile) == null || DuelContext.IsFreeConsume(from))) - m_Bandage.Consume(); - } - else - { - from.SendLocalizedMessage(500295); // You are too far away to do that. - } + Stackable = true; + Amount = amount; } - else if (targeted is PlagueBeastInnard innard) + + public Bandage(Serial serial) : base(serial) { - if (innard.OnBandage(from)) - m_Bandage.Consume(); } - else + + public override double DefaultWeight => 0.1; + + public virtual bool Dye(Mobile from, DyeTub sender) { - from.SendLocalizedMessage(500970); // Bandages can not be used on that. + if (Deleted) + return false; + + Hue = sender.DyedHue; + + return true; } - } - protected override void OnNonlocalTarget(Mobile from, object targeted) - { - if (targeted is PlagueBeastInnard innard) + public static void Initialize() { - if (innard.OnBandage(from)) - m_Bandage.Consume(); + EventSink.BandageTargetRequest += EventSink_BandageTargetRequest; } - else + + public override void Serialize(IGenericWriter writer) { - base.OnNonlocalTarget(from, targeted); + base.Serialize(writer); + + writer.Write(0); // version } - } - } - } - public class BandageContext - { - private static readonly Dictionary m_Table = new Dictionary(); - - public BandageContext(Mobile healer, Mobile patient, TimeSpan delay) - { - Healer = healer; - Patient = patient; - - Timer = new InternalTimer(this, delay); - Timer.Start(); - } - - public Mobile Healer { get; } - - public Mobile Patient { get; } - - public int Slips { get; set; } - - public Timer Timer { get; private set; } - - public void Slip() - { - Healer.SendLocalizedMessage(500961); // Your fingers slip! - ++Slips; - } - - public void StopHeal() - { - m_Table.Remove(Healer); - Timer?.Stop(); - Timer = null; - } - - public static BandageContext GetContext(Mobile healer) - { - m_Table.TryGetValue(healer, out BandageContext bc); - return bc; - } - - public static SkillName GetPrimarySkill(Mobile m) - { - if (!m.Player && (m.Body.IsMonster || m.Body.IsAnimal)) - return SkillName.Veterinary; - return SkillName.Healing; - } - - public static SkillName GetSecondarySkill(Mobile m) - { - if (!m.Player && (m.Body.IsMonster || m.Body.IsAnimal)) - return SkillName.AnimalLore; - return SkillName.Anatomy; - } - - public void EndHeal() - { - StopHeal(); - - int healerNumber, patientNumber; - bool playSound = true; - bool checkSkills = false; - - SkillName primarySkill = GetPrimarySkill(Patient); - SkillName secondarySkill = GetSecondarySkill(Patient); - - BaseCreature petPatient = Patient as BaseCreature; - - if (!Healer.Alive) - { - healerNumber = 500962; // You were unable to finish your work before you died. - patientNumber = -1; - playSound = false; - } - else if (!Healer.InRange(Patient, Bandage.Range)) - { - healerNumber = 500963; // You did not stay close enough to heal your target. - patientNumber = -1; - playSound = false; - } - else if (!Patient.Alive || petPatient?.IsDeadPet == true) - { - double healing = Healer.Skills[primarySkill].Value; - double anatomy = Healer.Skills[secondarySkill].Value; - double chance = (healing - 68.0) / 50.0 - Slips * 0.02; - - if (((checkSkills = healing >= 80.0 && anatomy >= 80.0) && chance > Utility.RandomDouble()) - || (Core.SE && petPatient is FactionWarHorse && petPatient.ControlMaster == Healer)) // TODO: Dbl check doesn't check for faction of the horse here? + public override void Deserialize(IGenericReader reader) { - if (Patient.Map?.CanFit(Patient.Location, 16, false, false) != true) - { - healerNumber = 501042; // Target can not be resurrected at that location. - patientNumber = 502391; // Thou can not be resurrected there! - } - else if (Patient.Region?.IsPartOf("Khaldun") == true) - { - healerNumber = - 1010395; // The veil of death in this area is too strong and resists thy efforts to restore life. - patientNumber = -1; - } - else - { - healerNumber = 500965; // You are able to resurrect your patient. - patientNumber = -1; + base.Deserialize(reader); - Patient.PlaySound(0x214); - Patient.FixedEffect(0x376A, 10, 16); + var version = reader.ReadInt(); + } - if (petPatient?.IsDeadPet == true) + public override void OnDoubleClick(Mobile from) + { + if (from.InRange(GetWorldLocation(), Range)) { - Mobile master = petPatient.ControlMaster; + from.RevealingAction(); - if (master != null && Healer == master) - { - petPatient.ResurrectPet(); + from.SendLocalizedMessage(500948); // Who will you use the bandages on? - for (int i = 0; i < petPatient.Skills.Length; ++i) petPatient.Skills[i].Base -= 0.1; - } - else if (master?.InRange(petPatient, 3) == true) - { - healerNumber = 503255; // You are able to resurrect the creature. + from.Target = new InternalTarget(this); + } + else + { + from.SendLocalizedMessage(500295); // You are too far away to do that. + } + } - master.CloseGump(); - master.SendGump(new PetResurrectGump(Healer, petPatient)); - } - else - { - bool found = false; + private static void EventSink_BandageTargetRequest(Mobile from, Item item, Mobile target) + { + if (!(item is Bandage b) || b.Deleted) + return; - List friends = petPatient.Friends; + if (!from.InRange(b.GetWorldLocation(), Range)) + { + from.SendLocalizedMessage(500295); // You are too far away to do that. + return; + } - for (int i = 0; friends != null && i < friends.Count; ++i) + if (from.Target != null) + { + Target.Cancel(from); + from.Target = null; + } + + from.RevealingAction(); + from.SendLocalizedMessage(500948); // Who will you use the bandages on? + + new InternalTarget(b).Invoke(from, target); + } + + private class InternalTarget : Target + { + private readonly Bandage m_Bandage; + + public InternalTarget(Bandage bandage) : base(Bandage.Range, false, TargetFlags.Beneficial) => + m_Bandage = bandage; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Bandage.Deleted) + return; + + if (targeted is Mobile mobile) { - Mobile friend = friends[i]; + if (from.InRange(m_Bandage.GetWorldLocation(), Bandage.Range)) + { + if (!(BandageContext.BeginHeal(from, mobile) == null || DuelContext.IsFreeConsume(from))) + m_Bandage.Consume(); + } + else + { + from.SendLocalizedMessage(500295); // You are too far away to do that. + } + } + else if (targeted is PlagueBeastInnard innard) + { + if (innard.OnBandage(from)) + m_Bandage.Consume(); + } + else + { + from.SendLocalizedMessage(500970); // Bandages can not be used on that. + } + } - if (friend.InRange(petPatient, 3)) - { - healerNumber = 503255; // You are able to resurrect the creature. + protected override void OnNonlocalTarget(Mobile from, object targeted) + { + if (targeted is PlagueBeastInnard innard) + { + if (innard.OnBandage(from)) + m_Bandage.Consume(); + } + else + { + base.OnNonlocalTarget(from, targeted); + } + } + } + } - friend.CloseGump(); - friend.SendGump(new PetResurrectGump(Healer, petPatient)); + public class BandageContext + { + private static readonly Dictionary m_Table = new Dictionary(); - found = true; - break; - } + public BandageContext(Mobile healer, Mobile patient, TimeSpan delay) + { + Healer = healer; + Patient = patient; + + Timer = new InternalTimer(this, delay); + Timer.Start(); + } + + public Mobile Healer { get; } + + public Mobile Patient { get; } + + public int Slips { get; set; } + + public Timer Timer { get; private set; } + + public void Slip() + { + Healer.SendLocalizedMessage(500961); // Your fingers slip! + ++Slips; + } + + public void StopHeal() + { + m_Table.Remove(Healer); + Timer?.Stop(); + Timer = null; + } + + public static BandageContext GetContext(Mobile healer) + { + m_Table.TryGetValue(healer, out var bc); + return bc; + } + + public static SkillName GetPrimarySkill(Mobile m) + { + if (!m.Player && (m.Body.IsMonster || m.Body.IsAnimal)) + return SkillName.Veterinary; + return SkillName.Healing; + } + + public static SkillName GetSecondarySkill(Mobile m) + { + if (!m.Player && (m.Body.IsMonster || m.Body.IsAnimal)) + return SkillName.AnimalLore; + return SkillName.Anatomy; + } + + public void EndHeal() + { + StopHeal(); + + int healerNumber, patientNumber; + var playSound = true; + var checkSkills = false; + + var primarySkill = GetPrimarySkill(Patient); + var secondarySkill = GetSecondarySkill(Patient); + + var petPatient = Patient as BaseCreature; + + if (!Healer.Alive) + { + healerNumber = 500962; // You were unable to finish your work before you died. + patientNumber = -1; + playSound = false; + } + else if (!Healer.InRange(Patient, Bandage.Range)) + { + healerNumber = 500963; // You did not stay close enough to heal your target. + patientNumber = -1; + playSound = false; + } + else if (!Patient.Alive || petPatient?.IsDeadPet == true) + { + var healing = Healer.Skills[primarySkill].Value; + var anatomy = Healer.Skills[secondarySkill].Value; + var chance = (healing - 68.0) / 50.0 - Slips * 0.02; + + if ((checkSkills = healing >= 80.0 && anatomy >= 80.0) && chance > Utility.RandomDouble() + || Core.SE && petPatient is FactionWarHorse && petPatient.ControlMaster == Healer + ) // TODO: Dbl check doesn't check for faction of the horse here? + { + if (Patient.Map?.CanFit(Patient.Location, 16, false, false) != true) + { + healerNumber = 501042; // Target can not be resurrected at that location. + patientNumber = 502391; // Thou can not be resurrected there! + } + else if (Patient.Region?.IsPartOf("Khaldun") == true) + { + healerNumber = + 1010395; // The veil of death in this area is too strong and resists thy efforts to restore life. + patientNumber = -1; + } + else + { + healerNumber = 500965; // You are able to resurrect your patient. + patientNumber = -1; + + Patient.PlaySound(0x214); + Patient.FixedEffect(0x376A, 10, 16); + + if (petPatient?.IsDeadPet == true) + { + var master = petPatient.ControlMaster; + + if (master != null && Healer == master) + { + petPatient.ResurrectPet(); + + for (var i = 0; i < petPatient.Skills.Length; ++i) petPatient.Skills[i].Base -= 0.1; + } + else if (master?.InRange(petPatient, 3) == true) + { + healerNumber = 503255; // You are able to resurrect the creature. + + master.CloseGump(); + master.SendGump(new PetResurrectGump(Healer, petPatient)); + } + else + { + var found = false; + + var friends = petPatient.Friends; + + for (var i = 0; friends != null && i < friends.Count; ++i) + { + var friend = friends[i]; + + if (friend.InRange(petPatient, 3)) + { + healerNumber = 503255; // You are able to resurrect the creature. + + friend.CloseGump(); + friend.SendGump(new PetResurrectGump(Healer, petPatient)); + + found = true; + break; + } + } + + if (!found) + healerNumber = 1049670; // The pet's owner must be nearby to attempt resurrection. + } + } + else + { + Patient.CloseGump(); + Patient.SendGump(new ResurrectGump(Patient, Healer)); + } + } + } + else + { + if (petPatient?.IsDeadPet == true) + healerNumber = 503256; // You fail to resurrect the creature. + else + healerNumber = 500966; // You are unable to resurrect your patient. + + patientNumber = -1; + } + } + else if (Patient.Poisoned) + { + Healer.SendLocalizedMessage(500969); // You finish applying the bandages. + + var healing = Healer.Skills[primarySkill].Value; + var anatomy = Healer.Skills[secondarySkill].Value; + var chance = (healing - 30.0) / 50.0 - Patient.Poison.Level * 0.1 - Slips * 0.02; + + if ((checkSkills = healing >= 60.0 && anatomy >= 60.0) && chance > Utility.RandomDouble()) + { + if (Patient.CurePoison(Healer)) + { + healerNumber = Healer == Patient ? -1 : 1010058; // You have cured the target of all poisons. + patientNumber = 1010059; // You have been cured of all poisons. + } + else + { + healerNumber = -1; + patientNumber = -1; + } + } + else + { + healerNumber = 1010060; // You have failed to cure your target! + patientNumber = -1; + } + } + else if (BleedAttack.IsBleeding(Patient)) + { + healerNumber = 1060088; // You bind the wound and stop the bleeding + patientNumber = 1060167; // The bleeding wounds have healed, you are no longer bleeding! + + BleedAttack.EndBleed(Patient, false); + } + else if (MortalStrike.IsWounded(Patient)) + { + healerNumber = Healer == Patient ? 1005000 : 1010398; + patientNumber = -1; + playSound = false; + } + else if (Patient.Hits == Patient.HitsMax) + { + healerNumber = 500967; // You heal what little damage your patient had. + patientNumber = -1; + } + else + { + checkSkills = true; + patientNumber = -1; + + var healing = Healer.Skills[primarySkill].Value; + var anatomy = Healer.Skills[secondarySkill].Value; + var chance = (healing + 10.0) / 100.0 - Slips * 0.02; + + if (chance > Utility.RandomDouble()) + { + healerNumber = 500969; // You finish applying the bandages. + + double min, max; + + if (Core.AOS) + { + min = anatomy / 8.0 + healing / 5.0 + 4.0; + max = anatomy / 6.0 + healing / 2.5 + 4.0; + } + else + { + min = anatomy / 5.0 + healing / 5.0 + 3.0; + max = anatomy / 5.0 + healing / 2.0 + 10.0; + } + + var toHeal = min + Utility.RandomDouble() * (max - min); + + if (Patient.Body.IsMonster || Patient.Body.IsAnimal) + toHeal += Patient.HitsMax / 100.0; + + if (Core.AOS) + toHeal -= toHeal * Slips * 0.35; // TODO: Verify algorithm + else + toHeal -= Slips * 4; + + if (toHeal < 1) + { + toHeal = 1; + healerNumber = 500968; // You apply the bandages, but they barely help. + } + + Patient.Heal((int)toHeal, Healer, false); + } + else + { + healerNumber = 500968; // You apply the bandages, but they barely help. + playSound = false; + } + } + + if (healerNumber != -1) + Healer.SendLocalizedMessage(healerNumber); + + if (patientNumber != -1) + Patient.SendLocalizedMessage(patientNumber); + + if (playSound) + Patient.PlaySound(0x57); + + if (checkSkills) + { + Healer.CheckSkill(secondarySkill, 0.0, 120.0); + Healer.CheckSkill(primarySkill, 0.0, 120.0); + } + } + + public static BandageContext BeginHeal(Mobile healer, Mobile patient) + { + var creature = patient as BaseCreature; + + if (patient is Golem) + { + healer.SendLocalizedMessage(500970); // Bandages cannot be used on that. + } + else if (creature?.IsAnimatedDead == true) + { + healer.SendLocalizedMessage(500951); // You cannot heal that. + } + else if (!patient.Poisoned && patient.Hits == patient.HitsMax && !BleedAttack.IsBleeding(patient) && + creature?.IsDeadPet != true) + { + healer.SendLocalizedMessage(500955); // That being is not damaged! + } + else if (!patient.Alive && patient.Map?.CanFit(patient.Location, 16, false, false) != true) + { + healer.SendLocalizedMessage(501042); // Target cannot be resurrected at that location. + } + else if (healer.CanBeBeneficial(patient, true, true)) + { + healer.DoBeneficial(patient); + + var onSelf = healer == patient; + var dex = healer.Dex; + + double seconds; + var resDelay = patient.Alive ? 0.0 : 5.0; + + if (onSelf) + { + if (Core.AOS) + seconds = 5.0 + 0.5 * ((double)(120 - dex) / 10); // TODO: Verify algorithm + else + seconds = 9.4 + 0.6 * ((double)(120 - dex) / 10); + } + else + { + if (Core.AOS && GetPrimarySkill(patient) == SkillName.Veterinary) + { + seconds = 2.0; + } + else if (Core.AOS) + { + if (dex < 204) + seconds = 3.2 - Math.Sin((double)dex / 130) * 2.5 + resDelay; + else + seconds = 0.7 + resDelay; + } + else + { + if (dex >= 100) + seconds = 3.0 + resDelay; + else if (dex >= 40) + seconds = 4.0 + resDelay; + else + seconds = 5.0 + resDelay; + } } - if (!found) - healerNumber = 1049670; // The pet's owner must be nearby to attempt resurrection. - } + var context = GetContext(healer); + + context?.StopHeal(); + seconds *= 1000; + + context = new BandageContext(healer, patient, TimeSpan.FromMilliseconds(seconds)); + + m_Table[healer] = context; + + if (!onSelf) + patient.SendLocalizedMessage(1008078, false, healer.Name); // : Attempting to heal you. + + healer.SendLocalizedMessage(500956); // You begin applying the bandages. + return context; } - else + + return null; + } + + private class InternalTimer : Timer + { + private readonly BandageContext m_Context; + + public InternalTimer(BandageContext context, TimeSpan delay) : base(delay) { - Patient.CloseGump(); - Patient.SendGump(new ResurrectGump(Patient, Healer)); + m_Context = context; + Priority = TimerPriority.FiftyMS; + } + + protected override void OnTick() + { + m_Context.EndHeal(); } - } } - else - { - if (petPatient?.IsDeadPet == true) - healerNumber = 503256; // You fail to resurrect the creature. - else - healerNumber = 500966; // You are unable to resurrect your patient. - - patientNumber = -1; - } - } - else if (Patient.Poisoned) - { - Healer.SendLocalizedMessage(500969); // You finish applying the bandages. - - double healing = Healer.Skills[primarySkill].Value; - double anatomy = Healer.Skills[secondarySkill].Value; - double chance = (healing - 30.0) / 50.0 - Patient.Poison.Level * 0.1 - Slips * 0.02; - - if ((checkSkills = healing >= 60.0 && anatomy >= 60.0) && chance > Utility.RandomDouble()) - { - if (Patient.CurePoison(Healer)) - { - healerNumber = Healer == Patient ? -1 : 1010058; // You have cured the target of all poisons. - patientNumber = 1010059; // You have been cured of all poisons. - } - else - { - healerNumber = -1; - patientNumber = -1; - } - } - else - { - healerNumber = 1010060; // You have failed to cure your target! - patientNumber = -1; - } - } - else if (BleedAttack.IsBleeding(Patient)) - { - healerNumber = 1060088; // You bind the wound and stop the bleeding - patientNumber = 1060167; // The bleeding wounds have healed, you are no longer bleeding! - - BleedAttack.EndBleed(Patient, false); - } - else if (MortalStrike.IsWounded(Patient)) - { - healerNumber = Healer == Patient ? 1005000 : 1010398; - patientNumber = -1; - playSound = false; - } - else if (Patient.Hits == Patient.HitsMax) - { - healerNumber = 500967; // You heal what little damage your patient had. - patientNumber = -1; - } - else - { - checkSkills = true; - patientNumber = -1; - - double healing = Healer.Skills[primarySkill].Value; - double anatomy = Healer.Skills[secondarySkill].Value; - double chance = (healing + 10.0) / 100.0 - Slips * 0.02; - - if (chance > Utility.RandomDouble()) - { - healerNumber = 500969; // You finish applying the bandages. - - double min, max; - - if (Core.AOS) - { - min = anatomy / 8.0 + healing / 5.0 + 4.0; - max = anatomy / 6.0 + healing / 2.5 + 4.0; - } - else - { - min = anatomy / 5.0 + healing / 5.0 + 3.0; - max = anatomy / 5.0 + healing / 2.0 + 10.0; - } - - double toHeal = min + Utility.RandomDouble() * (max - min); - - if (Patient.Body.IsMonster || Patient.Body.IsAnimal) - toHeal += Patient.HitsMax / 100.0; - - if (Core.AOS) - toHeal -= toHeal * Slips * 0.35; // TODO: Verify algorithm - else - toHeal -= Slips * 4; - - if (toHeal < 1) - { - toHeal = 1; - healerNumber = 500968; // You apply the bandages, but they barely help. - } - - Patient.Heal((int)toHeal, Healer, false); - } - else - { - healerNumber = 500968; // You apply the bandages, but they barely help. - playSound = false; - } - } - - if (healerNumber != -1) - Healer.SendLocalizedMessage(healerNumber); - - if (patientNumber != -1) - Patient.SendLocalizedMessage(patientNumber); - - if (playSound) - Patient.PlaySound(0x57); - - if (checkSkills) - { - Healer.CheckSkill(secondarySkill, 0.0, 120.0); - Healer.CheckSkill(primarySkill, 0.0, 120.0); - } } - - public static BandageContext BeginHeal(Mobile healer, Mobile patient) - { - BaseCreature creature = patient as BaseCreature; - - if (patient is Golem) - { - healer.SendLocalizedMessage(500970); // Bandages cannot be used on that. - } - else if (creature?.IsAnimatedDead == true) - { - healer.SendLocalizedMessage(500951); // You cannot heal that. - } - else if (!patient.Poisoned && patient.Hits == patient.HitsMax && !BleedAttack.IsBleeding(patient) && - creature?.IsDeadPet != true) - { - healer.SendLocalizedMessage(500955); // That being is not damaged! - } - else if (!patient.Alive && patient.Map?.CanFit(patient.Location, 16, false, false) != true) - { - healer.SendLocalizedMessage(501042); // Target cannot be resurrected at that location. - } - else if (healer.CanBeBeneficial(patient, true, true)) - { - healer.DoBeneficial(patient); - - bool onSelf = healer == patient; - int dex = healer.Dex; - - double seconds; - double resDelay = patient.Alive ? 0.0 : 5.0; - - if (onSelf) - { - if (Core.AOS) - seconds = 5.0 + 0.5 * ((double)(120 - dex) / 10); // TODO: Verify algorithm - else - seconds = 9.4 + 0.6 * ((double)(120 - dex) / 10); - } - else - { - if (Core.AOS && GetPrimarySkill(patient) == SkillName.Veterinary) - { - seconds = 2.0; - } - else if (Core.AOS) - { - if (dex < 204) - seconds = 3.2 - Math.Sin((double)dex / 130) * 2.5 + resDelay; - else - seconds = 0.7 + resDelay; - } - else - { - if (dex >= 100) - seconds = 3.0 + resDelay; - else if (dex >= 40) - seconds = 4.0 + resDelay; - else - seconds = 5.0 + resDelay; - } - } - - BandageContext context = GetContext(healer); - - context?.StopHeal(); - seconds *= 1000; - - context = new BandageContext(healer, patient, TimeSpan.FromMilliseconds(seconds)); - - m_Table[healer] = context; - - if (!onSelf) - patient.SendLocalizedMessage(1008078, false, healer.Name); // : Attempting to heal you. - - healer.SendLocalizedMessage(500956); // You begin applying the bandages. - return context; - } - - return null; - } - - private class InternalTimer : Timer - { - private readonly BandageContext m_Context; - - public InternalTimer(BandageContext context, TimeSpan delay) : base(delay) - { - m_Context = context; - Priority = TimerPriority.FiftyMS; - } - - protected override void OnTick() - { - m_Context.EndHeal(); - } - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Misc/FireHorn.cs b/Projects/UOContent/Items/Skill Items/Misc/FireHorn.cs index e0b356e48..ed550fc8a 100644 --- a/Projects/UOContent/Items/Skill Items/Misc/FireHorn.cs +++ b/Projects/UOContent/Items/Skill Items/Misc/FireHorn.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using Server.Network; using Server.Spells; @@ -7,209 +6,227 @@ using Server.Targeting; namespace Server.Items { - public class FireHorn : Item - { - [Constructible] - public FireHorn() : base(0xFC7) + public class FireHorn : Item { - Hue = 0x466; - Weight = 1.0; - } - - public FireHorn(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1060456; // fire horn - - private bool CheckUse(Mobile from) - { - if (!IsAccessibleTo(from)) - return false; - - if (from.Map != Map || !from.InRange(GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return false; - } - - if (!from.CanBeginAction()) - { - from.SendLocalizedMessage(1049615); // You must take a moment to catch your breath. - return false; - } - - if (from.Backpack?.GetAmount(typeof(SulfurousAsh)) >= (Core.AOS ? 4 : 15)) - return true; - - from.SendLocalizedMessage(1049617); // You do not have enough sulfurous ash. - return false; - } - - public override void OnDoubleClick(Mobile from) - { - if (CheckUse(from)) - { - from.SendLocalizedMessage(1049620); // Select an area to incinerate. - from.Target = new InternalTarget(this); - } - } - - public void Use(Mobile from, IPoint3D loc) - { - if (!CheckUse(from)) - return; - - from.BeginAction(); - Timer.DelayCall(Core.AOS ? TimeSpan.FromSeconds(6.0) : TimeSpan.FromSeconds(12.0), EndAction, from); - - int music = from.Skills.Musicianship.Fixed; - - int sucChance = 500 + (music - 775) * 2; - double dSucChance = sucChance / 1000.0; - - if (!from.CheckSkill(SkillName.Musicianship, dSucChance)) - { - from.SendLocalizedMessage(1049618); // The horn emits a pathetic squeak. - from.PlaySound(0x18A); - return; - } - - int sulfAsh = Core.AOS ? 4 : 15; - from.Backpack.ConsumeUpTo(typeof(SulfurousAsh), sulfAsh); - - from.PlaySound(0x15F); - Effects.SendPacket(from, from.Map, - new HuedEffect(EffectType.Moving, from.Serial, Serial.Zero, 0x36D4, from.Location, loc, 5, 0, false, true, 0, - 0)); - - IPooledEnumerable eable = from.Map.GetMobilesInRange(new Point3D(loc), 2); - - bool playerVsPlayer = false; - List targets = eable.Where(m => - { - if (from == m || !SpellHelper.ValidIndirectTarget(from, m) || !from.CanBeHarmful(m, false) - || (Core.AOS && !from.InLOS(m))) - return false; - - if (m.Player) - playerVsPlayer = true; - - return true; - }).ToList(); - - eable.Free(); - - if (targets.Count > 0) - { - int prov = from.Skills.Provocation.Fixed; - int disc = from.Skills.Discordance.Fixed; - int peace = from.Skills.Peacemaking.Fixed; - - int minDamage, maxDamage; - - if (Core.AOS) + [Constructible] + public FireHorn() : base(0xFC7) { - int musicScaled = music + Math.Max(0, music - 900) * 2; - int provScaled = prov + Math.Max(0, prov - 900) * 2; - int discScaled = disc + Math.Max(0, disc - 900) * 2; - int peaceScaled = peace + Math.Max(0, peace - 900) * 2; - - int weightAvg = (musicScaled + provScaled * 3 + discScaled * 3 + peaceScaled) / 80; - - int avgDamage; - if (playerVsPlayer) - avgDamage = weightAvg / 3; - else - avgDamage = weightAvg / 2; - - minDamage = avgDamage * 9 / 10; - maxDamage = avgDamage * 10 / 9; - } - else - { - int total = prov + disc / 5 + peace / 5; - - if (playerVsPlayer) - total /= 3; - - maxDamage = total * 2 / 30; - minDamage = maxDamage * 7 / 10; + Hue = 0x466; + Weight = 1.0; } - double damage = Utility.RandomMinMax(minDamage, maxDamage); - - if (Core.AOS && targets.Count > 1) - damage = damage * 2 / targets.Count; - else if (!Core.AOS) - damage /= targets.Count; - - for (int i = 0; i < targets.Count; ++i) + public FireHorn(Serial serial) : base(serial) { - Mobile m = targets[i]; - - double toDeal = damage; - - if (!Core.AOS && m.CheckSkill(SkillName.MagicResist, 0.0, 120.0)) - { - toDeal *= 0.5; - m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. - } - - from.DoHarmful(m); - SpellHelper.Damage(TimeSpan.Zero, m, from, toDeal, 0, 100, 0, 0, 0); - - Effects.SendTargetEffect(m, 0x3709, 10, 30); } - } - double breakChance = Core.AOS ? 0.01 : 0.16; - if (Utility.RandomDouble() < breakChance) - { - from.SendLocalizedMessage(1049619); // The fire horn crumbles in your hands. - Delete(); - } + public override int LabelNumber => 1060456; // fire horn + + private bool CheckUse(Mobile from) + { + if (!IsAccessibleTo(from)) + return false; + + if (from.Map != Map || !from.InRange(GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return false; + } + + if (!from.CanBeginAction()) + { + from.SendLocalizedMessage(1049615); // You must take a moment to catch your breath. + return false; + } + + if (from.Backpack?.GetAmount(typeof(SulfurousAsh)) >= (Core.AOS ? 4 : 15)) + return true; + + from.SendLocalizedMessage(1049617); // You do not have enough sulfurous ash. + return false; + } + + public override void OnDoubleClick(Mobile from) + { + if (CheckUse(from)) + { + from.SendLocalizedMessage(1049620); // Select an area to incinerate. + from.Target = new InternalTarget(this); + } + } + + public void Use(Mobile from, IPoint3D loc) + { + if (!CheckUse(from)) + return; + + from.BeginAction(); + Timer.DelayCall(Core.AOS ? TimeSpan.FromSeconds(6.0) : TimeSpan.FromSeconds(12.0), EndAction, from); + + var music = from.Skills.Musicianship.Fixed; + + var sucChance = 500 + (music - 775) * 2; + var dSucChance = sucChance / 1000.0; + + if (!from.CheckSkill(SkillName.Musicianship, dSucChance)) + { + from.SendLocalizedMessage(1049618); // The horn emits a pathetic squeak. + from.PlaySound(0x18A); + return; + } + + var sulfAsh = Core.AOS ? 4 : 15; + from.Backpack.ConsumeUpTo(typeof(SulfurousAsh), sulfAsh); + + from.PlaySound(0x15F); + Effects.SendPacket( + from, + from.Map, + new HuedEffect( + EffectType.Moving, + from.Serial, + Serial.Zero, + 0x36D4, + from.Location, + loc, + 5, + 0, + false, + true, + 0, + 0 + ) + ); + + var eable = from.Map.GetMobilesInRange(new Point3D(loc), 2); + + var playerVsPlayer = false; + var targets = eable.Where( + m => + { + if (from == m || !SpellHelper.ValidIndirectTarget(from, m) || !from.CanBeHarmful(m, false) + || Core.AOS && !@from.InLOS(m)) + return false; + + if (m.Player) + playerVsPlayer = true; + + return true; + } + ) + .ToList(); + + eable.Free(); + + if (targets.Count > 0) + { + var prov = from.Skills.Provocation.Fixed; + var disc = from.Skills.Discordance.Fixed; + var peace = from.Skills.Peacemaking.Fixed; + + int minDamage, maxDamage; + + if (Core.AOS) + { + var musicScaled = music + Math.Max(0, music - 900) * 2; + var provScaled = prov + Math.Max(0, prov - 900) * 2; + var discScaled = disc + Math.Max(0, disc - 900) * 2; + var peaceScaled = peace + Math.Max(0, peace - 900) * 2; + + var weightAvg = (musicScaled + provScaled * 3 + discScaled * 3 + peaceScaled) / 80; + + int avgDamage; + if (playerVsPlayer) + avgDamage = weightAvg / 3; + else + avgDamage = weightAvg / 2; + + minDamage = avgDamage * 9 / 10; + maxDamage = avgDamage * 10 / 9; + } + else + { + var total = prov + disc / 5 + peace / 5; + + if (playerVsPlayer) + total /= 3; + + maxDamage = total * 2 / 30; + minDamage = maxDamage * 7 / 10; + } + + double damage = Utility.RandomMinMax(minDamage, maxDamage); + + if (Core.AOS && targets.Count > 1) + damage = damage * 2 / targets.Count; + else if (!Core.AOS) + damage /= targets.Count; + + for (var i = 0; i < targets.Count; ++i) + { + var m = targets[i]; + + var toDeal = damage; + + if (!Core.AOS && m.CheckSkill(SkillName.MagicResist, 0.0, 120.0)) + { + toDeal *= 0.5; + m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + } + + from.DoHarmful(m); + SpellHelper.Damage(TimeSpan.Zero, m, from, toDeal, 0, 100, 0, 0, 0); + + Effects.SendTargetEffect(m, 0x3709, 10, 30); + } + } + + var breakChance = Core.AOS ? 0.01 : 0.16; + if (Utility.RandomDouble() < breakChance) + { + from.SendLocalizedMessage(1049619); // The fire horn crumbles in your hands. + Delete(); + } + } + + private static void EndAction(Mobile m) + { + m?.EndAction(); + m?.SendLocalizedMessage(1049621); // You catch your breath. + } + + 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(); + } + + private class InternalTarget : Target + { + private readonly FireHorn m_Horn; + + public InternalTarget(FireHorn horn) : base(Core.AOS ? 3 : 2, true, TargetFlags.Harmful) => m_Horn = horn; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Horn.Deleted) + return; + + IPoint3D loc; + if (targeted is Item item) + loc = item.GetWorldLocation(); + else + loc = targeted as IPoint3D; + + m_Horn.Use(from, loc); + } + } } - - private static void EndAction(Mobile m) - { - m?.EndAction(); - m?.SendLocalizedMessage(1049621); // You catch your breath. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - private class InternalTarget : Target - { - private readonly FireHorn m_Horn; - - public InternalTarget(FireHorn horn) : base(Core.AOS ? 3 : 2, true, TargetFlags.Harmful) => m_Horn = horn; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Horn.Deleted) - return; - - IPoint3D loc; - if (targeted is Item item) - loc = item.GetWorldLocation(); - else - loc = targeted as IPoint3D; - - m_Horn.Use(from, loc); - } - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Misc/RecipeScroll.cs b/Projects/UOContent/Items/Skill Items/Misc/RecipeScroll.cs index 502200270..f4ee8d554 100644 --- a/Projects/UOContent/Items/Skill Items/Misc/RecipeScroll.cs +++ b/Projects/UOContent/Items/Skill Items/Misc/RecipeScroll.cs @@ -4,113 +4,115 @@ using Server.Network; namespace Server.Items { - public class RecipeScroll : Item - { - private int m_RecipeID; - - public RecipeScroll(Recipe r) : this(r.ID) + public class RecipeScroll : Item { - } + private int m_RecipeID; - [Constructible] - public RecipeScroll(int recipeID) : base(0x2831) => m_RecipeID = recipeID; - - public RecipeScroll(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1074560; // recipe scroll - - [CommandProperty(AccessLevel.GameMaster)] - public int RecipeID - { - get => m_RecipeID; - set - { - m_RecipeID = value; - InvalidateProperties(); - } - } - - public Recipe Recipe - { - get - { - Recipe.Recipes.TryGetValue(m_RecipeID, out Recipe recipe); - return recipe; - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - Recipe r = Recipe; - - if (r != null) - list.Add(1049644, r.TextDefinition.ToString()); // [~1_stuff~] - } - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return; - } - - Recipe r = Recipe; - - if (r != null && from is PlayerMobile pm) - { - if (!pm.HasRecipe(r)) + public RecipeScroll(Recipe r) : this(r.ID) { - double chance = r.CraftItem.GetSuccessChance(pm, null, r.CraftSystem, false, out var allRequiredSkills); - - if (allRequiredSkills && chance >= 0.0) - { - pm.SendLocalizedMessage(1073451, - r.TextDefinition.ToString()); // You have learned a new recipe: ~1_RECIPE~ - pm.AcquireRecipe(r); - Delete(); - } - else - { - pm.SendLocalizedMessage(1044153); // You don't have the required skills to attempt this item. - } } - else + + [Constructible] + public RecipeScroll(int recipeID) : base(0x2831) => m_RecipeID = recipeID; + + public RecipeScroll(Serial serial) + : base(serial) { - pm.SendLocalizedMessage(1073427); // You already know this recipe. } - } + + public override int LabelNumber => 1074560; // recipe scroll + + [CommandProperty(AccessLevel.GameMaster)] + public int RecipeID + { + get => m_RecipeID; + set + { + m_RecipeID = value; + InvalidateProperties(); + } + } + + public Recipe Recipe + { + get + { + Recipe.Recipes.TryGetValue(m_RecipeID, out var recipe); + return recipe; + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + var r = Recipe; + + if (r != null) + list.Add(1049644, r.TextDefinition.ToString()); // [~1_stuff~] + } + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return; + } + + var r = Recipe; + + if (r != null && from is PlayerMobile pm) + { + if (!pm.HasRecipe(r)) + { + var chance = r.CraftItem.GetSuccessChance(pm, null, r.CraftSystem, false, out var allRequiredSkills); + + if (allRequiredSkills && chance >= 0.0) + { + pm.SendLocalizedMessage( + 1073451, + r.TextDefinition.ToString() + ); // You have learned a new recipe: ~1_RECIPE~ + pm.AcquireRecipe(r); + Delete(); + } + else + { + pm.SendLocalizedMessage(1044153); // You don't have the required skills to attempt this item. + } + } + else + { + pm.SendLocalizedMessage(1073427); // You already know this recipe. + } + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_RecipeID); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_RecipeID = reader.ReadInt(); + + break; + } + } + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_RecipeID); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_RecipeID = reader.ReadInt(); - - break; - } - } - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Misc/RepairDeed.cs b/Projects/UOContent/Items/Skill Items/Misc/RepairDeed.cs index f88beec51..912498f25 100644 --- a/Projects/UOContent/Items/Skill Items/Misc/RepairDeed.cs +++ b/Projects/UOContent/Items/Skill Items/Misc/RepairDeed.cs @@ -6,227 +6,242 @@ using Server.Regions; namespace Server.Items { - public class RepairDeed : Item - { - public enum RepairSkillType + public class RepairDeed : Item { - Smithing, - Tailoring, - Tinkering, - Carpentry, - Fletching + public enum RepairSkillType + { + Smithing, + Tailoring, + Tinkering, + Carpentry, + Fletching + } + + private Mobile m_Crafter; + + private RepairSkillType m_Skill; + private double m_SkillLevel; + + [Constructible] + public RepairDeed(RepairSkillType skill, double level, bool normalizeLevel) : this( + skill, + level, + null, + normalizeLevel + ) + { + } + + [Constructible] + public RepairDeed( + RepairSkillType skill = RepairSkillType.Smithing, double level = 100.0, + Mobile crafter = null, bool normalizeLevel = true + ) : base(0x14F0) + { + if (normalizeLevel) + SkillLevel = (int)(level / 10) * 10; + else + SkillLevel = level; + + m_Skill = skill; + m_Crafter = crafter; + Hue = 0x1BC; + LootType = LootType.Blessed; + } + + public RepairDeed(Serial serial) : base(serial) + { + } + + public override bool DisplayLootType => false; + + [CommandProperty(AccessLevel.GameMaster)] + public RepairSkillType RepairSkill + { + get => m_Skill; + set + { + m_Skill = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public double SkillLevel + { + get => m_SkillLevel; + set + { + m_SkillLevel = Math.Clamp(value, 0, 120.0); + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Crafter + { + get => m_Crafter; + set + { + m_Crafter = value; + InvalidateProperties(); + } + } + + public override void AddNameProperty(ObjectPropertyList list) + { + list.Add( + 1061133, + $"{GetSkillTitle(m_SkillLevel)}\t{RepairSkillInfo.GetInfo(m_Skill).Name}" + ); // A repair service contract from ~1_SKILL_TITLE~ ~2_SKILL_NAME~. + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_Crafter != null) + list.Add(1050043, m_Crafter.Name); // crafted by ~1_NAME~ + + // On OSI it says it's exceptional. Intentional difference. + } + + public override void OnSingleClick(Mobile from) + { + if (Deleted || !from.CanSee(this)) + return; + + LabelTo( + from, + 1061133, + $"{GetSkillTitle(m_SkillLevel)}\t{RepairSkillInfo.GetInfo(m_Skill).Name}" + ); // A repair service contract from ~1_SKILL_TITLE~ ~2_SKILL_NAME~. + + if (m_Crafter != null) + LabelTo(from, 1050043, m_Crafter.Name); // crafted by ~1_NAME~ + } + + private static TextDefinition GetSkillTitle(double skillLevel) + { + var skill = (int)(skillLevel / 10); + + if (skill >= 11) + return 1062008 + skill - 11; + if (skill >= 5) + return 1061123 + skill - 5; + + return skill switch + { + 4 => "a Novice", + 3 => "a Neophyte", + _ => "a Newbie" + }; + } + + public static RepairSkillType GetTypeFor(CraftSystem s) + { + for (var i = 0; i < RepairSkillInfo.Table.Length; i++) + if (RepairSkillInfo.Table[i].System == s) + return (RepairSkillType)i; + + return RepairSkillType.Smithing; + } + + public override void OnDoubleClick(Mobile from) + { + if (Check(from)) + Repair.Do(from, RepairSkillInfo.GetInfo(m_Skill).System, this); + } + + public bool Check(Mobile from) + { + if (!IsChildOf(from.Backpack)) + from.SendLocalizedMessage(1047012); // The contract must be in your backpack to use it. + else if (!VerifyRegion(from)) + TextDefinition.SendMessageTo(from, RepairSkillInfo.GetInfo(m_Skill).NotNearbyMessage); + else + return true; + + return false; + } + + public bool VerifyRegion(Mobile m) => m.Region.IsPartOf() && + Faction.IsNearType(m, RepairSkillInfo.GetInfo(m_Skill).NearbyTypes, 6); + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write((int)m_Skill); + writer.Write(m_SkillLevel); + writer.Write(m_Crafter); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Skill = (RepairSkillType)reader.ReadInt(); + m_SkillLevel = reader.ReadDouble(); + m_Crafter = reader.ReadMobile(); + + break; + } + } + } + + private class RepairSkillInfo + { + public RepairSkillInfo( + CraftSystem system, Type[] nearbyTypes, TextDefinition notNearbyMessage, + TextDefinition name + ) + { + System = system; + NearbyTypes = nearbyTypes; + NotNearbyMessage = notNearbyMessage; + Name = name; + } + + public RepairSkillInfo(CraftSystem system, Type nearbyType, TextDefinition notNearbyMessage, TextDefinition name) + : this(system, new[] { nearbyType }, notNearbyMessage, name) + { + } + + public TextDefinition NotNearbyMessage { get; } + + public TextDefinition Name { get; } + + public CraftSystem System { get; } + + public Type[] NearbyTypes { get; } + + public static RepairSkillInfo[] Table { get; } = + { + new RepairSkillInfo(DefBlacksmithy.CraftSystem, typeof(Blacksmith), 1047013, 1023015), + new RepairSkillInfo(DefTailoring.CraftSystem, typeof(Tailor), 1061132, 1022981), + new RepairSkillInfo(DefTinkering.CraftSystem, typeof(Tinker), 1061166, 1022983), + new RepairSkillInfo(DefCarpentry.CraftSystem, typeof(Carpenter), 1061135, 1060774), + new RepairSkillInfo(DefBowFletching.CraftSystem, typeof(Bowyer), 1061134, 1023005) + }; + + public static RepairSkillInfo GetInfo(RepairSkillType type) + { + var v = (int)type; + + if (v < 0 || v >= Table.Length) + v = 0; + + return Table[v]; + } + } } - - private Mobile m_Crafter; - - private RepairSkillType m_Skill; - private double m_SkillLevel; - - [Constructible] - public RepairDeed(RepairSkillType skill, double level, bool normalizeLevel) : this(skill, level, null, normalizeLevel) - { - } - - [Constructible] - public RepairDeed(RepairSkillType skill = RepairSkillType.Smithing, double level = 100.0, - Mobile crafter = null, bool normalizeLevel = true) : base(0x14F0) - { - if (normalizeLevel) - SkillLevel = (int)(level / 10) * 10; - else - SkillLevel = level; - - m_Skill = skill; - m_Crafter = crafter; - Hue = 0x1BC; - LootType = LootType.Blessed; - } - - public RepairDeed(Serial serial) : base(serial) - { - } - - public override bool DisplayLootType => false; - - [CommandProperty(AccessLevel.GameMaster)] - public RepairSkillType RepairSkill - { - get => m_Skill; - set - { - m_Skill = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public double SkillLevel - { - get => m_SkillLevel; - set - { - m_SkillLevel = Math.Clamp(value, 0, 120.0); - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Crafter - { - get => m_Crafter; - set - { - m_Crafter = value; - InvalidateProperties(); - } - } - - public override void AddNameProperty(ObjectPropertyList list) - { - list.Add(1061133, - $"{GetSkillTitle(m_SkillLevel)}\t{RepairSkillInfo.GetInfo(m_Skill).Name}"); // A repair service contract from ~1_SKILL_TITLE~ ~2_SKILL_NAME~. - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_Crafter != null) - list.Add(1050043, m_Crafter.Name); // crafted by ~1_NAME~ - - // On OSI it says it's exceptional. Intentional difference. - } - - public override void OnSingleClick(Mobile from) - { - if (Deleted || !from.CanSee(this)) - return; - - LabelTo(from, 1061133, - $"{GetSkillTitle(m_SkillLevel)}\t{RepairSkillInfo.GetInfo(m_Skill).Name}"); // A repair service contract from ~1_SKILL_TITLE~ ~2_SKILL_NAME~. - - if (m_Crafter != null) - LabelTo(from, 1050043, m_Crafter.Name); // crafted by ~1_NAME~ - } - - private static TextDefinition GetSkillTitle(double skillLevel) - { - int skill = (int)(skillLevel / 10); - - if (skill >= 11) - return 1062008 + skill - 11; - if (skill >= 5) - return 1061123 + skill - 5; - - return skill switch - { - 4 => "a Novice", - 3 => "a Neophyte", - _ => "a Newbie" - }; - } - - public static RepairSkillType GetTypeFor(CraftSystem s) - { - for (int i = 0; i < RepairSkillInfo.Table.Length; i++) - if (RepairSkillInfo.Table[i].System == s) - return (RepairSkillType)i; - - return RepairSkillType.Smithing; - } - - public override void OnDoubleClick(Mobile from) - { - if (Check(from)) - Repair.Do(from, RepairSkillInfo.GetInfo(m_Skill).System, this); - } - - public bool Check(Mobile from) - { - if (!IsChildOf(from.Backpack)) - from.SendLocalizedMessage(1047012); // The contract must be in your backpack to use it. - else if (!VerifyRegion(from)) - TextDefinition.SendMessageTo(from, RepairSkillInfo.GetInfo(m_Skill).NotNearbyMessage); - else - return true; - - return false; - } - - public bool VerifyRegion(Mobile m) => m.Region.IsPartOf() && Faction.IsNearType(m, RepairSkillInfo.GetInfo(m_Skill).NearbyTypes, 6); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write((int)m_Skill); - writer.Write(m_SkillLevel); - writer.Write(m_Crafter); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Skill = (RepairSkillType)reader.ReadInt(); - m_SkillLevel = reader.ReadDouble(); - m_Crafter = reader.ReadMobile(); - - break; - } - } - } - - private class RepairSkillInfo - { - public RepairSkillInfo(CraftSystem system, Type[] nearbyTypes, TextDefinition notNearbyMessage, - TextDefinition name) - { - System = system; - NearbyTypes = nearbyTypes; - NotNearbyMessage = notNearbyMessage; - Name = name; - } - - public RepairSkillInfo(CraftSystem system, Type nearbyType, TextDefinition notNearbyMessage, TextDefinition name) - : this(system, new[] { nearbyType }, notNearbyMessage, name) - { - } - - public TextDefinition NotNearbyMessage { get; } - - public TextDefinition Name { get; } - - public CraftSystem System { get; } - - public Type[] NearbyTypes { get; } - - public static RepairSkillInfo[] Table { get; } = - { - new RepairSkillInfo(DefBlacksmithy.CraftSystem, typeof(Blacksmith), 1047013, 1023015), - new RepairSkillInfo(DefTailoring.CraftSystem, typeof(Tailor), 1061132, 1022981), - new RepairSkillInfo(DefTinkering.CraftSystem, typeof(Tinker), 1061166, 1022983), - new RepairSkillInfo(DefCarpentry.CraftSystem, typeof(Carpenter), 1061135, 1060774), - new RepairSkillInfo(DefBowFletching.CraftSystem, typeof(Bowyer), 1061134, 1023005) - }; - - public static RepairSkillInfo GetInfo(RepairSkillType type) - { - int v = (int)type; - - if (v < 0 || v >= Table.Length) - v = 0; - - return Table[v]; - } - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Musical Instruments/BambooFlute.cs b/Projects/UOContent/Items/Skill Items/Musical Instruments/BambooFlute.cs index df53261a8..6a4b7cc07 100644 --- a/Projects/UOContent/Items/Skill Items/Musical Instruments/BambooFlute.cs +++ b/Projects/UOContent/Items/Skill Items/Musical Instruments/BambooFlute.cs @@ -1,29 +1,29 @@ namespace Server.Items { - public class BambooFlute : BaseInstrument - { - [Constructible] - public BambooFlute() : base(0x2805, 0x504, 0x503) => Weight = 2.0; - - public BambooFlute(Serial serial) : base(serial) + public class BambooFlute : BaseInstrument { + [Constructible] + public BambooFlute() : base(0x2805, 0x504, 0x503) => Weight = 2.0; + + public BambooFlute(Serial serial) : base(serial) + { + } + + 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 (Weight == 3.0) + Weight = 2.0; + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 3.0) - Weight = 2.0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Musical Instruments/BaseInstrument.cs b/Projects/UOContent/Items/Skill Items/Musical Instruments/BaseInstrument.cs index f3eeac970..248e1ea03 100644 --- a/Projects/UOContent/Items/Skill Items/Musical Instruments/BaseInstrument.cs +++ b/Projects/UOContent/Items/Skill Items/Musical Instruments/BaseInstrument.cs @@ -7,546 +7,554 @@ using Server.Targeting; namespace Server.Items { - public delegate void InstrumentPickedCallback(Mobile from, BaseInstrument instrument); + public delegate void InstrumentPickedCallback(Mobile from, BaseInstrument instrument); - public enum InstrumentQuality - { - Low, - Regular, - Exceptional - } - - public abstract class BaseInstrument : Item, ICraftable, ISlayer - { - private static readonly Dictionary m_Instruments = new Dictionary(); - private Mobile m_Crafter; - - private DateTime m_LastReplenished; - private InstrumentQuality m_Quality; - - private bool m_ReplenishesCharges; - private SlayerName m_Slayer, m_Slayer2; - private int m_UsesRemaining; - - public BaseInstrument(int itemID, int wellSound, int badlySound) : base(itemID) + public enum InstrumentQuality { - SuccessSound = wellSound; - FailureSound = badlySound; - UsesRemaining = Utility.RandomMinMax(InitMinUses, InitMaxUses); + Low, + Regular, + Exceptional } - public BaseInstrument(Serial serial) : base(serial) + public abstract class BaseInstrument : Item, ICraftable, ISlayer { - } + private static readonly Dictionary m_Instruments = new Dictionary(); + private Mobile m_Crafter; - [CommandProperty(AccessLevel.GameMaster)] - public int SuccessSound { get; set; } + private DateTime m_LastReplenished; + private InstrumentQuality m_Quality; - [CommandProperty(AccessLevel.GameMaster)] - public int FailureSound { get; set; } + private bool m_ReplenishesCharges; + private SlayerName m_Slayer, m_Slayer2; + private int m_UsesRemaining; - [CommandProperty(AccessLevel.GameMaster)] - public InstrumentQuality Quality - { - get => m_Quality; - set - { - UnscaleUses(); - m_Quality = value; - InvalidateProperties(); - ScaleUses(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Crafter - { - get => m_Crafter; - set - { - m_Crafter = value; - InvalidateProperties(); - } - } - - public virtual int InitMinUses => 350; - public virtual int InitMaxUses => 450; - - public virtual TimeSpan ChargeReplenishRate => TimeSpan.FromMinutes(5.0); - - [CommandProperty(AccessLevel.GameMaster)] - public int UsesRemaining - { - get - { - CheckReplenishUses(); - return m_UsesRemaining; - } - set - { - m_UsesRemaining = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime LastReplenished - { - get => m_LastReplenished; - set - { - m_LastReplenished = value; - CheckReplenishUses(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool ReplenishesCharges - { - get => m_ReplenishesCharges; - set - { - if (value != m_ReplenishesCharges && value) - m_LastReplenished = DateTime.UtcNow; - - m_ReplenishesCharges = value; - } - } - - public int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, - CraftItem craftItem, int resHue) - { - Quality = (InstrumentQuality)quality; - - if (makersMark) - Crafter = from; - - return quality; - } - - [CommandProperty(AccessLevel.GameMaster)] - public SlayerName Slayer - { - get => m_Slayer; - set - { - m_Slayer = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public SlayerName Slayer2 - { - get => m_Slayer2; - set - { - m_Slayer2 = value; - InvalidateProperties(); - } - } - - public void CheckReplenishUses(bool invalidate = true) - { - if (!m_ReplenishesCharges || m_UsesRemaining >= InitMaxUses) - return; - - if (m_LastReplenished + ChargeReplenishRate < DateTime.UtcNow) - { - TimeSpan timeDifference = DateTime.UtcNow - m_LastReplenished; - - m_UsesRemaining = Math.Min(m_UsesRemaining + (int)(timeDifference.Ticks / ChargeReplenishRate.Ticks), - InitMaxUses); // How rude of TimeSpan to not allow timespan division. - m_LastReplenished = DateTime.UtcNow; - - if (invalidate) - InvalidateProperties(); - } - } - - public void ScaleUses() - { - UsesRemaining = UsesRemaining * GetUsesScalar() / 100; - // InvalidateProperties(); - } - - public void UnscaleUses() - { - UsesRemaining = UsesRemaining * 100 / GetUsesScalar(); - } - - public int GetUsesScalar() => m_Quality == InstrumentQuality.Exceptional ? 200 : 100; - - public void ConsumeUse(Mobile from) - { - // TODO: Confirm what must happen here? - - if (UsesRemaining > 1) - { - --UsesRemaining; - } - else - { - from?.SendLocalizedMessage(502079); // The instrument played its last tune. - - Delete(); - } - } - - public static BaseInstrument GetInstrument(Mobile from) - { - if (m_Instruments.TryGetValue(from, out BaseInstrument instrument) && instrument.IsChildOf(from.Backpack)) - return instrument; - - m_Instruments.Remove(from); - return null; - } - - public static int GetBardRange(Mobile bard, SkillName skill) => 8 + (int)(bard.Skills[skill].Value / 15); - - public static void PickInstrument(Mobile from, InstrumentPickedCallback callback) - { - BaseInstrument instrument = GetInstrument(from); - if (instrument != null) - { - callback?.Invoke(from, instrument); - } - else - { - from.SendLocalizedMessage(500617); // What instrument shall you play? - from.BeginTarget(1, false, TargetFlags.None, OnPickedInstrument, callback); - } - } - - public static void OnPickedInstrument(Mobile from, object targeted, InstrumentPickedCallback callback) - { - if (!(targeted is BaseInstrument instrument)) - { - from.SendLocalizedMessage(500619); // That is not a musical instrument. - } - else - { - SetInstrument(from, instrument); - callback?.Invoke(from, instrument); - } - } - - public static bool IsMageryCreature(BaseCreature bc) => bc?.AI == AIType.AI_Mage && bc.Skills.Magery.Base > 5.0; - - public static bool IsFireBreathingCreature(BaseCreature bc) => bc?.HasBreath == true; - - public static bool IsPoisonImmune(BaseCreature bc) => bc?.PoisonImmune != null; - - public static int GetPoisonLevel(BaseCreature bc) => (bc?.HitPoison?.Level ?? -1) + 1; - - public static double GetBaseDifficulty(Mobile targ) - { - /* Difficulty TODO: Add another 100 points for each of the following abilities: - - Radiation or Aura Damage (Heat, Cold etc.) - - Summoning Undead - */ - - double val = targ.HitsMax * 1.6 + targ.StamMax + targ.ManaMax; - - val += targ.SkillsTotal / 10.0; - - if (val > 700) - val = 700 + (int)((val - 700) * (3.0 / 11)); - - BaseCreature bc = targ as BaseCreature; - - if (IsMageryCreature(bc)) - val += 100; - - if (IsFireBreathingCreature(bc)) - val += 100; - - if (IsPoisonImmune(bc)) - val += 100; - - if (targ is VampireBat || targ is VampireBatFamiliar) - val += 100; - - val += GetPoisonLevel(bc) * 20; - - val /= 10; - - if (bc?.IsParagon == true) - val += 40.0; - - if (Core.SE && val > 160.0) - val = 160.0; - - return val; - } - - public double GetDifficultyFor(Mobile targ) - { - double val = GetBaseDifficulty(targ); - - if (m_Quality == InstrumentQuality.Exceptional) - val -= 5.0; // 10% - - if (m_Slayer != SlayerName.None) - { - SlayerEntry entry = SlayerGroup.GetEntryByName(m_Slayer); - - if (entry != null) + public BaseInstrument(int itemID, int wellSound, int badlySound) : base(itemID) { - if (entry.Slays(targ)) - val -= 10.0; // 20% - else if (entry.Group.OppositionSuperSlays(targ)) - val += 10.0; // -20% + SuccessSound = wellSound; + FailureSound = badlySound; + UsesRemaining = Utility.RandomMinMax(InitMinUses, InitMaxUses); } - } - if (m_Slayer2 != SlayerName.None) - { - SlayerEntry entry = SlayerGroup.GetEntryByName(m_Slayer2); - - if (entry != null) + public BaseInstrument(Serial serial) : base(serial) { - if (entry.Slays(targ)) - val -= 10.0; // 20% - else if (entry.Group.OppositionSuperSlays(targ)) - val += 10.0; // -20% } - } - return val; - } + [CommandProperty(AccessLevel.GameMaster)] + public int SuccessSound { get; set; } - public static void SetInstrument(Mobile from, BaseInstrument item) - { - m_Instruments[from] = item; - } + [CommandProperty(AccessLevel.GameMaster)] + public int FailureSound { get; set; } - public override void GetProperties(ObjectPropertyList list) - { - int oldUses = m_UsesRemaining; - CheckReplenishUses(false); + [CommandProperty(AccessLevel.GameMaster)] + public InstrumentQuality Quality + { + get => m_Quality; + set + { + UnscaleUses(); + m_Quality = value; + InvalidateProperties(); + ScaleUses(); + } + } - base.GetProperties(list); + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Crafter + { + get => m_Crafter; + set + { + m_Crafter = value; + InvalidateProperties(); + } + } - if (m_Crafter != null) - list.Add(1050043, m_Crafter.Name); // crafted by ~1_NAME~ + public virtual int InitMinUses => 350; + public virtual int InitMaxUses => 450; - if (m_Quality == InstrumentQuality.Exceptional) - list.Add(1060636); // exceptional + public virtual TimeSpan ChargeReplenishRate => TimeSpan.FromMinutes(5.0); - list.Add(1060584, m_UsesRemaining.ToString()); // uses remaining: ~1_val~ + [CommandProperty(AccessLevel.GameMaster)] + public int UsesRemaining + { + get + { + CheckReplenishUses(); + return m_UsesRemaining; + } + set + { + m_UsesRemaining = value; + InvalidateProperties(); + } + } - if (m_ReplenishesCharges) - list.Add(1070928); // Replenish Charges + [CommandProperty(AccessLevel.GameMaster)] + public DateTime LastReplenished + { + get => m_LastReplenished; + set + { + m_LastReplenished = value; + CheckReplenishUses(); + } + } - if (m_Slayer != SlayerName.None) - { - SlayerEntry entry = SlayerGroup.GetEntryByName(m_Slayer); - if (entry != null) - list.Add(entry.Title); - } + [CommandProperty(AccessLevel.GameMaster)] + public bool ReplenishesCharges + { + get => m_ReplenishesCharges; + set + { + if (value != m_ReplenishesCharges && value) + m_LastReplenished = DateTime.UtcNow; - if (m_Slayer2 != SlayerName.None) - { - SlayerEntry entry = SlayerGroup.GetEntryByName(m_Slayer2); - if (entry != null) - list.Add(entry.Title); - } + m_ReplenishesCharges = value; + } + } - if (m_UsesRemaining != oldUses) - Timer.DelayCall(InvalidateProperties); - } + public int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, + CraftItem craftItem, int resHue + ) + { + Quality = (InstrumentQuality)quality; - public override void OnSingleClick(Mobile from) - { - List attrs = new List(); + if (makersMark) + Crafter = from; - if (DisplayLootType) - { - if (LootType == LootType.Blessed) - attrs.Add(new EquipInfoAttribute(1038021)); // blessed - else if (LootType == LootType.Cursed) - attrs.Add(new EquipInfoAttribute(1049643)); // cursed - } + return quality; + } - if (m_Quality == InstrumentQuality.Exceptional) - attrs.Add(new EquipInfoAttribute(1018305 - (int)m_Quality)); + [CommandProperty(AccessLevel.GameMaster)] + public SlayerName Slayer + { + get => m_Slayer; + set + { + m_Slayer = value; + InvalidateProperties(); + } + } - if (m_ReplenishesCharges) - attrs.Add(new EquipInfoAttribute(1070928)); // Replenish Charges + [CommandProperty(AccessLevel.GameMaster)] + public SlayerName Slayer2 + { + get => m_Slayer2; + set + { + m_Slayer2 = value; + InvalidateProperties(); + } + } - // TODO: Must this support item identification? - if (m_Slayer != SlayerName.None) - { - SlayerEntry entry = SlayerGroup.GetEntryByName(m_Slayer); - if (entry != null) - attrs.Add(new EquipInfoAttribute(entry.Title)); - } + public void CheckReplenishUses(bool invalidate = true) + { + if (!m_ReplenishesCharges || m_UsesRemaining >= InitMaxUses) + return; - if (m_Slayer2 != SlayerName.None) - { - SlayerEntry entry = SlayerGroup.GetEntryByName(m_Slayer2); - if (entry != null) - attrs.Add(new EquipInfoAttribute(entry.Title)); - } + if (m_LastReplenished + ChargeReplenishRate < DateTime.UtcNow) + { + var timeDifference = DateTime.UtcNow - m_LastReplenished; - int number; + m_UsesRemaining = Math.Min( + m_UsesRemaining + (int)(timeDifference.Ticks / ChargeReplenishRate.Ticks), + InitMaxUses + ); // How rude of TimeSpan to not allow timespan division. + m_LastReplenished = DateTime.UtcNow; - if (Name == null) - { - number = LabelNumber; - } - else - { - LabelTo(from, Name); - number = 1041000; - } + if (invalidate) + InvalidateProperties(); + } + } - if (attrs.Count == 0 && Crafter == null && Name != null) - return; + public void ScaleUses() + { + UsesRemaining = UsesRemaining * GetUsesScalar() / 100; + // InvalidateProperties(); + } - EquipmentInfo eqInfo = new EquipmentInfo(number, m_Crafter, false, - attrs.ToArray()); + public void UnscaleUses() + { + UsesRemaining = UsesRemaining * 100 / GetUsesScalar(); + } - from.Send(new DisplayEquipmentInfo(this, eqInfo)); - } + public int GetUsesScalar() => m_Quality == InstrumentQuality.Exceptional ? 200 : 100; - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public void ConsumeUse(Mobile from) + { + // TODO: Confirm what must happen here? - writer.Write(3); // version + if (UsesRemaining > 1) + { + --UsesRemaining; + } + else + { + from?.SendLocalizedMessage(502079); // The instrument played its last tune. - writer.Write(m_ReplenishesCharges); - if (m_ReplenishesCharges) - writer.Write(m_LastReplenished); + Delete(); + } + } - writer.Write(m_Crafter); + public static BaseInstrument GetInstrument(Mobile from) + { + if (m_Instruments.TryGetValue(from, out var instrument) && instrument.IsChildOf(from.Backpack)) + return instrument; - writer.WriteEncodedInt((int)m_Quality); - writer.WriteEncodedInt((int)m_Slayer); - writer.WriteEncodedInt((int)m_Slayer2); + m_Instruments.Remove(from); + return null; + } - writer.WriteEncodedInt(UsesRemaining); + public static int GetBardRange(Mobile bard, SkillName skill) => 8 + (int)(bard.Skills[skill].Value / 15); - writer.WriteEncodedInt(SuccessSound); - writer.WriteEncodedInt(FailureSound); - } + public static void PickInstrument(Mobile from, InstrumentPickedCallback callback) + { + var instrument = GetInstrument(from); + if (instrument != null) + { + callback?.Invoke(from, instrument); + } + else + { + from.SendLocalizedMessage(500617); // What instrument shall you play? + from.BeginTarget(1, false, TargetFlags.None, OnPickedInstrument, callback); + } + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public static void OnPickedInstrument(Mobile from, object targeted, InstrumentPickedCallback callback) + { + if (!(targeted is BaseInstrument instrument)) + { + from.SendLocalizedMessage(500619); // That is not a musical instrument. + } + else + { + SetInstrument(from, instrument); + callback?.Invoke(from, instrument); + } + } - int version = reader.ReadInt(); + public static bool IsMageryCreature(BaseCreature bc) => bc?.AI == AIType.AI_Mage && bc.Skills.Magery.Base > 5.0; - switch (version) - { - case 3: - { - m_ReplenishesCharges = reader.ReadBool(); + public static bool IsFireBreathingCreature(BaseCreature bc) => bc?.HasBreath == true; + + public static bool IsPoisonImmune(BaseCreature bc) => bc?.PoisonImmune != null; + + public static int GetPoisonLevel(BaseCreature bc) => (bc?.HitPoison?.Level ?? -1) + 1; + + public static double GetBaseDifficulty(Mobile targ) + { + /* Difficulty TODO: Add another 100 points for each of the following abilities: + - Radiation or Aura Damage (Heat, Cold etc.) + - Summoning Undead + */ + + var val = targ.HitsMax * 1.6 + targ.StamMax + targ.ManaMax; + + val += targ.SkillsTotal / 10.0; + + if (val > 700) + val = 700 + (int)((val - 700) * (3.0 / 11)); + + var bc = targ as BaseCreature; + + if (IsMageryCreature(bc)) + val += 100; + + if (IsFireBreathingCreature(bc)) + val += 100; + + if (IsPoisonImmune(bc)) + val += 100; + + if (targ is VampireBat || targ is VampireBatFamiliar) + val += 100; + + val += GetPoisonLevel(bc) * 20; + + val /= 10; + + if (bc?.IsParagon == true) + val += 40.0; + + if (Core.SE && val > 160.0) + val = 160.0; + + return val; + } + + public double GetDifficultyFor(Mobile targ) + { + var val = GetBaseDifficulty(targ); + + if (m_Quality == InstrumentQuality.Exceptional) + val -= 5.0; // 10% + + if (m_Slayer != SlayerName.None) + { + var entry = SlayerGroup.GetEntryByName(m_Slayer); + + if (entry != null) + { + if (entry.Slays(targ)) + val -= 10.0; // 20% + else if (entry.Group.OppositionSuperSlays(targ)) + val += 10.0; // -20% + } + } + + if (m_Slayer2 != SlayerName.None) + { + var entry = SlayerGroup.GetEntryByName(m_Slayer2); + + if (entry != null) + { + if (entry.Slays(targ)) + val -= 10.0; // 20% + else if (entry.Group.OppositionSuperSlays(targ)) + val += 10.0; // -20% + } + } + + return val; + } + + public static void SetInstrument(Mobile from, BaseInstrument item) + { + m_Instruments[from] = item; + } + + public override void GetProperties(ObjectPropertyList list) + { + var oldUses = m_UsesRemaining; + CheckReplenishUses(false); + + base.GetProperties(list); + + if (m_Crafter != null) + list.Add(1050043, m_Crafter.Name); // crafted by ~1_NAME~ + + if (m_Quality == InstrumentQuality.Exceptional) + list.Add(1060636); // exceptional + + list.Add(1060584, m_UsesRemaining.ToString()); // uses remaining: ~1_val~ if (m_ReplenishesCharges) - m_LastReplenished = reader.ReadDateTime(); + list.Add(1070928); // Replenish Charges - goto case 2; - } - case 2: - { - m_Crafter = reader.ReadMobile(); + if (m_Slayer != SlayerName.None) + { + var entry = SlayerGroup.GetEntryByName(m_Slayer); + if (entry != null) + list.Add(entry.Title); + } - m_Quality = (InstrumentQuality)reader.ReadEncodedInt(); - m_Slayer = (SlayerName)reader.ReadEncodedInt(); - m_Slayer2 = (SlayerName)reader.ReadEncodedInt(); + if (m_Slayer2 != SlayerName.None) + { + var entry = SlayerGroup.GetEntryByName(m_Slayer2); + if (entry != null) + list.Add(entry.Title); + } - UsesRemaining = reader.ReadEncodedInt(); + if (m_UsesRemaining != oldUses) + Timer.DelayCall(InvalidateProperties); + } - SuccessSound = reader.ReadEncodedInt(); - FailureSound = reader.ReadEncodedInt(); + public override void OnSingleClick(Mobile from) + { + var attrs = new List(); - break; - } - case 1: - { - m_Crafter = reader.ReadMobile(); + if (DisplayLootType) + { + if (LootType == LootType.Blessed) + attrs.Add(new EquipInfoAttribute(1038021)); // blessed + else if (LootType == LootType.Cursed) + attrs.Add(new EquipInfoAttribute(1049643)); // cursed + } - m_Quality = (InstrumentQuality)reader.ReadEncodedInt(); - m_Slayer = (SlayerName)reader.ReadEncodedInt(); + if (m_Quality == InstrumentQuality.Exceptional) + attrs.Add(new EquipInfoAttribute(1018305 - (int)m_Quality)); - UsesRemaining = reader.ReadEncodedInt(); + if (m_ReplenishesCharges) + attrs.Add(new EquipInfoAttribute(1070928)); // Replenish Charges - SuccessSound = reader.ReadEncodedInt(); - FailureSound = reader.ReadEncodedInt(); + // TODO: Must this support item identification? + if (m_Slayer != SlayerName.None) + { + var entry = SlayerGroup.GetEntryByName(m_Slayer); + if (entry != null) + attrs.Add(new EquipInfoAttribute(entry.Title)); + } - break; - } - case 0: - { - SuccessSound = reader.ReadInt(); - FailureSound = reader.ReadInt(); - UsesRemaining = Utility.RandomMinMax(InitMinUses, InitMaxUses); + if (m_Slayer2 != SlayerName.None) + { + var entry = SlayerGroup.GetEntryByName(m_Slayer2); + if (entry != null) + attrs.Add(new EquipInfoAttribute(entry.Title)); + } - break; - } - } + int number; - CheckReplenishUses(); + if (Name == null) + { + number = LabelNumber; + } + else + { + LabelTo(from, Name); + number = 1041000; + } + + if (attrs.Count == 0 && Crafter == null && Name != null) + return; + + var eqInfo = new EquipmentInfo( + number, + m_Crafter, + false, + attrs.ToArray() + ); + + from.Send(new DisplayEquipmentInfo(this, eqInfo)); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(3); // version + + writer.Write(m_ReplenishesCharges); + if (m_ReplenishesCharges) + writer.Write(m_LastReplenished); + + writer.Write(m_Crafter); + + writer.WriteEncodedInt((int)m_Quality); + writer.WriteEncodedInt((int)m_Slayer); + writer.WriteEncodedInt((int)m_Slayer2); + + writer.WriteEncodedInt(UsesRemaining); + + writer.WriteEncodedInt(SuccessSound); + writer.WriteEncodedInt(FailureSound); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 3: + { + m_ReplenishesCharges = reader.ReadBool(); + + if (m_ReplenishesCharges) + m_LastReplenished = reader.ReadDateTime(); + + goto case 2; + } + case 2: + { + m_Crafter = reader.ReadMobile(); + + m_Quality = (InstrumentQuality)reader.ReadEncodedInt(); + m_Slayer = (SlayerName)reader.ReadEncodedInt(); + m_Slayer2 = (SlayerName)reader.ReadEncodedInt(); + + UsesRemaining = reader.ReadEncodedInt(); + + SuccessSound = reader.ReadEncodedInt(); + FailureSound = reader.ReadEncodedInt(); + + break; + } + case 1: + { + m_Crafter = reader.ReadMobile(); + + m_Quality = (InstrumentQuality)reader.ReadEncodedInt(); + m_Slayer = (SlayerName)reader.ReadEncodedInt(); + + UsesRemaining = reader.ReadEncodedInt(); + + SuccessSound = reader.ReadEncodedInt(); + FailureSound = reader.ReadEncodedInt(); + + break; + } + case 0: + { + SuccessSound = reader.ReadInt(); + FailureSound = reader.ReadInt(); + UsesRemaining = Utility.RandomMinMax(InitMinUses, InitMaxUses); + + break; + } + } + + CheckReplenishUses(); + } + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 1)) + { + from.SendLocalizedMessage(500446); // That is too far away. + } + else if (from.BeginAction()) + { + SetInstrument(from, this); + + // Delay of 7 second before being able to play another instrument again + new InternalTimer(from).Start(); + + if (CheckMusicianship(from)) + PlayInstrumentWell(from); + else + PlayInstrumentBadly(from); + } + else + { + from.SendLocalizedMessage(500119); // You must wait to perform another action + } + } + + public static bool CheckMusicianship(Mobile m) + { + m.CheckSkill(SkillName.Musicianship, 0.0, 120.0); + + return m.Skills.Musicianship.Value / 100 > Utility.RandomDouble(); + } + + public void PlayInstrumentWell(Mobile from) + { + from.PlaySound(SuccessSound); + } + + public void PlayInstrumentBadly(Mobile from) + { + from.PlaySound(FailureSound); + } + + private class InternalTimer : Timer + { + private readonly Mobile m_From; + + public InternalTimer(Mobile from) : base(TimeSpan.FromSeconds(6.0)) + { + m_From = from; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + m_From.EndAction(); + } + } } - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 1)) - { - from.SendLocalizedMessage(500446); // That is too far away. - } - else if (from.BeginAction()) - { - SetInstrument(from, this); - - // Delay of 7 second before being able to play another instrument again - new InternalTimer(from).Start(); - - if (CheckMusicianship(from)) - PlayInstrumentWell(from); - else - PlayInstrumentBadly(from); - } - else - { - from.SendLocalizedMessage(500119); // You must wait to perform another action - } - } - - public static bool CheckMusicianship(Mobile m) - { - m.CheckSkill(SkillName.Musicianship, 0.0, 120.0); - - return m.Skills.Musicianship.Value / 100 > Utility.RandomDouble(); - } - - public void PlayInstrumentWell(Mobile from) - { - from.PlaySound(SuccessSound); - } - - public void PlayInstrumentBadly(Mobile from) - { - from.PlaySound(FailureSound); - } - - private class InternalTimer : Timer - { - private readonly Mobile m_From; - - public InternalTimer(Mobile from) : base(TimeSpan.FromSeconds(6.0)) - { - m_From = from; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - m_From.EndAction(); - } - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Musical Instruments/Drums.cs b/Projects/UOContent/Items/Skill Items/Musical Instruments/Drums.cs index 83ce443d9..8f2c76c92 100644 --- a/Projects/UOContent/Items/Skill Items/Musical Instruments/Drums.cs +++ b/Projects/UOContent/Items/Skill Items/Musical Instruments/Drums.cs @@ -1,29 +1,29 @@ namespace Server.Items { - public class Drums : BaseInstrument - { - [Constructible] - public Drums() : base(0xE9C, 0x38, 0x39) => Weight = 4.0; - - public Drums(Serial serial) : base(serial) + public class Drums : BaseInstrument { + [Constructible] + public Drums() : base(0xE9C, 0x38, 0x39) => Weight = 4.0; + + public Drums(Serial serial) : base(serial) + { + } + + 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 (Weight == 3.0) + Weight = 4.0; + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 3.0) - Weight = 4.0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Musical Instruments/Harp.cs b/Projects/UOContent/Items/Skill Items/Musical Instruments/Harp.cs index 0811198ea..35feb2e5a 100644 --- a/Projects/UOContent/Items/Skill Items/Musical Instruments/Harp.cs +++ b/Projects/UOContent/Items/Skill Items/Musical Instruments/Harp.cs @@ -1,29 +1,29 @@ namespace Server.Items { - public class Harp : BaseInstrument - { - [Constructible] - public Harp() : base(0xEB1, 0x43, 0x44) => Weight = 35.0; - - public Harp(Serial serial) : base(serial) + public class Harp : BaseInstrument { + [Constructible] + public Harp() : base(0xEB1, 0x43, 0x44) => Weight = 35.0; + + public Harp(Serial serial) : base(serial) + { + } + + 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 (Weight == 3.0) + Weight = 35.0; + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 3.0) - Weight = 35.0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Musical Instruments/LapHarp.cs b/Projects/UOContent/Items/Skill Items/Musical Instruments/LapHarp.cs index deb3066ff..532a66f83 100644 --- a/Projects/UOContent/Items/Skill Items/Musical Instruments/LapHarp.cs +++ b/Projects/UOContent/Items/Skill Items/Musical Instruments/LapHarp.cs @@ -1,29 +1,29 @@ namespace Server.Items { - public class LapHarp : BaseInstrument - { - [Constructible] - public LapHarp() : base(0xEB2, 0x45, 0x46) => Weight = 10.0; - - public LapHarp(Serial serial) : base(serial) + public class LapHarp : BaseInstrument { + [Constructible] + public LapHarp() : base(0xEB2, 0x45, 0x46) => Weight = 10.0; + + public LapHarp(Serial serial) : base(serial) + { + } + + 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 (Weight == 3.0) + Weight = 10.0; + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 3.0) - Weight = 10.0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Musical Instruments/Lute.cs b/Projects/UOContent/Items/Skill Items/Musical Instruments/Lute.cs index fb6b13f2d..db56ecf93 100644 --- a/Projects/UOContent/Items/Skill Items/Musical Instruments/Lute.cs +++ b/Projects/UOContent/Items/Skill Items/Musical Instruments/Lute.cs @@ -1,29 +1,29 @@ namespace Server.Items { - public class Lute : BaseInstrument - { - [Constructible] - public Lute() : base(0xEB3, 0x4C, 0x4D) => Weight = 5.0; - - public Lute(Serial serial) : base(serial) + public class Lute : BaseInstrument { + [Constructible] + public Lute() : base(0xEB3, 0x4C, 0x4D) => Weight = 5.0; + + public Lute(Serial serial) : base(serial) + { + } + + 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 (Weight == 3.0) + Weight = 5.0; + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 3.0) - Weight = 5.0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Musical Instruments/Tambourine.cs b/Projects/UOContent/Items/Skill Items/Musical Instruments/Tambourine.cs index 20bfda8dd..45137fa85 100644 --- a/Projects/UOContent/Items/Skill Items/Musical Instruments/Tambourine.cs +++ b/Projects/UOContent/Items/Skill Items/Musical Instruments/Tambourine.cs @@ -1,29 +1,29 @@ namespace Server.Items { - public class Tambourine : BaseInstrument - { - [Constructible] - public Tambourine() : base(0xE9D, 0x52, 0x53) => Weight = 1.0; - - public Tambourine(Serial serial) : base(serial) + public class Tambourine : BaseInstrument { + [Constructible] + public Tambourine() : base(0xE9D, 0x52, 0x53) => Weight = 1.0; + + public Tambourine(Serial serial) : base(serial) + { + } + + 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 (Weight == 2.0) + Weight = 1.0; + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 2.0) - Weight = 1.0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Musical Instruments/TambourineTassel.cs b/Projects/UOContent/Items/Skill Items/Musical Instruments/TambourineTassel.cs index 2b348d858..7f36f0745 100644 --- a/Projects/UOContent/Items/Skill Items/Musical Instruments/TambourineTassel.cs +++ b/Projects/UOContent/Items/Skill Items/Musical Instruments/TambourineTassel.cs @@ -1,29 +1,29 @@ namespace Server.Items { - public class TambourineTassel : BaseInstrument - { - [Constructible] - public TambourineTassel() : base(0xE9E, 0x52, 0x53) => Weight = 1.0; - - public TambourineTassel(Serial serial) : base(serial) + public class TambourineTassel : BaseInstrument { + [Constructible] + public TambourineTassel() : base(0xE9E, 0x52, 0x53) => Weight = 1.0; + + public TambourineTassel(Serial serial) : base(serial) + { + } + + 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 (Weight == 2.0) + Weight = 1.0; + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 2.0) - Weight = 1.0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Ninjitsu/EggBomb.cs b/Projects/UOContent/Items/Skill Items/Ninjitsu/EggBomb.cs index 4cd3aa3d9..bb835721f 100644 --- a/Projects/UOContent/Items/Skill Items/Ninjitsu/EggBomb.cs +++ b/Projects/UOContent/Items/Skill Items/Ninjitsu/EggBomb.cs @@ -2,77 +2,77 @@ using Server.SkillHandlers; namespace Server.Items { - public class EggBomb : Item - { - [Constructible] - public EggBomb() : base(0x2808) + public class EggBomb : Item { - // Item ID should be 0x2809 - Temporary solution for clients 7.0.0.0 and up - Stackable = Core.ML; - Weight = 1.0; - } - - public EggBomb(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1030249; - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - // The item must be in your backpack to use it. - from.SendLocalizedMessage(1060640); - } - else if (from.Skills.Ninjitsu.Value < 50.0) - { - // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability. - from.SendLocalizedMessage(1063013, "50\tNinjitsu"); - } - else if (Core.TickCount - from.NextSkillTime < 0) - { - // You must wait a few seconds before you can use that item. - from.SendLocalizedMessage(1070772); - } - else if (from.Mana < 10) - { - // You don't have enough mana to do that. - from.SendLocalizedMessage(1049456); - } - else - { - Hiding.CombatOverride = true; - - if (from.UseSkill(SkillName.Hiding)) + [Constructible] + public EggBomb() : base(0x2808) { - from.Mana -= 10; - - from.FixedParticles(0x3709, 1, 30, 9904, 1108, 6, EffectLayer.RightFoot); - from.PlaySound(0x22F); - - Consume(); + // Item ID should be 0x2809 - Temporary solution for clients 7.0.0.0 and up + Stackable = Core.ML; + Weight = 1.0; } - Hiding.CombatOverride = false; - } + public EggBomb(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1030249; + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + // The item must be in your backpack to use it. + from.SendLocalizedMessage(1060640); + } + else if (from.Skills.Ninjitsu.Value < 50.0) + { + // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability. + from.SendLocalizedMessage(1063013, "50\tNinjitsu"); + } + else if (Core.TickCount - from.NextSkillTime < 0) + { + // You must wait a few seconds before you can use that item. + from.SendLocalizedMessage(1070772); + } + else if (from.Mana < 10) + { + // You don't have enough mana to do that. + from.SendLocalizedMessage(1049456); + } + else + { + Hiding.CombatOverride = true; + + if (from.UseSkill(SkillName.Hiding)) + { + from.Mana -= 10; + + from.FixedParticles(0x3709, 1, 30, 9904, 1108, 6, EffectLayer.RightFoot); + from.PlaySound(0x22F); + + Consume(); + } + + Hiding.CombatOverride = false; + } + } + + 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 (ItemID == 0x2809) // Temporary solution for clients 7.0.0.0 and up + ItemID = 0x2808; + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (ItemID == 0x2809) // Temporary solution for clients 7.0.0.0 and up - ItemID = 0x2808; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Ninjitsu/Fukiya.cs b/Projects/UOContent/Items/Skill Items/Ninjitsu/Fukiya.cs index 369dc671a..10cd2eb85 100644 --- a/Projects/UOContent/Items/Skill Items/Ninjitsu/Fukiya.cs +++ b/Projects/UOContent/Items/Skill Items/Ninjitsu/Fukiya.cs @@ -5,141 +5,141 @@ using Server.Mobiles; namespace Server.Items { - [Flippable(0x27AA, 0x27F5)] - public class Fukiya : Item, INinjaWeapon - { - private Poison m_Poison; - private int m_PoisonCharges; - - private int m_UsesRemaining; - - [Constructible] - public Fukiya() : base(0x27AA) + [Flippable(0x27AA, 0x27F5)] + public class Fukiya : Item, INinjaWeapon { - Weight = 4.0; - Layer = Layer.OneHanded; + private Poison m_Poison; + private int m_PoisonCharges; + + private int m_UsesRemaining; + + [Constructible] + public Fukiya() : base(0x27AA) + { + Weight = 4.0; + Layer = Layer.OneHanded; + } + + public Fukiya(Serial serial) : base(serial) + { + } + + public virtual int WrongAmmoMessage => 1063329; // You can only load fukiya darts + public virtual int NoFreeHandMessage => 1063327; // You must have a free hand to use a fukiya. + public virtual int EmptyWeaponMessage => 1063325; // You have no fukiya darts! + public virtual int RecentlyUsedMessage => 1063326; // You are already using that fukiya. + public virtual int FullWeaponMessage => 1063330; // You can only load fukiya darts + + public virtual int WeaponMinRange => 0; + public virtual int WeaponMaxRange => 6; + + public virtual int WeaponDamage => Utility.RandomMinMax(4, 6); + + public Type AmmoType => typeof(FukiyaDarts); + + [CommandProperty(AccessLevel.GameMaster)] + public int UsesRemaining + { + get => m_UsesRemaining; + set + { + m_UsesRemaining = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Poison Poison + { + get => m_Poison; + set + { + m_Poison = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int PoisonCharges + { + get => m_PoisonCharges; + set + { + m_PoisonCharges = value; + InvalidateProperties(); + } + } + + bool IUsesRemaining.ShowUsesRemaining + { + get => true; + set { } + } + + public void AttackAnimation(Mobile from, Mobile to) + { + if (from.Body.IsHuman && !from.Mounted) from.Animate(33, 2, 1, true, true, 0); + + from.PlaySound(0x223); + from.MovingEffect(to, 0x2804, 5, 0, false, false); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1060584, m_UsesRemaining.ToString()); // uses remaining: ~1_val~ + + if (m_Poison != null && m_PoisonCharges > 0) + list.Add(1062412 + m_Poison.Level, m_PoisonCharges.ToString()); + } + + public override void OnDoubleClick(Mobile from) + { + NinjaWeapon.AttemptShoot((PlayerMobile)from, this); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (IsChildOf(from)) + { + list.Add(new NinjaWeapon.LoadEntry(this, 6224)); + list.Add(new NinjaWeapon.UnloadEntry(this, 6225)); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + writer.Write(m_UsesRemaining); + + Poison.Serialize(m_Poison, writer); + writer.Write(m_PoisonCharges); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_UsesRemaining = reader.ReadInt(); + + m_Poison = Poison.Deserialize(reader); + m_PoisonCharges = reader.ReadInt(); + + break; + } + } + } } - - public Fukiya(Serial serial) : base(serial) - { - } - - public virtual int WrongAmmoMessage => 1063329; // You can only load fukiya darts - public virtual int NoFreeHandMessage => 1063327; // You must have a free hand to use a fukiya. - public virtual int EmptyWeaponMessage => 1063325; // You have no fukiya darts! - public virtual int RecentlyUsedMessage => 1063326; // You are already using that fukiya. - public virtual int FullWeaponMessage => 1063330; // You can only load fukiya darts - - public virtual int WeaponMinRange => 0; - public virtual int WeaponMaxRange => 6; - - public virtual int WeaponDamage => Utility.RandomMinMax(4, 6); - - public Type AmmoType => typeof(FukiyaDarts); - - [CommandProperty(AccessLevel.GameMaster)] - public int UsesRemaining - { - get => m_UsesRemaining; - set - { - m_UsesRemaining = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Poison Poison - { - get => m_Poison; - set - { - m_Poison = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int PoisonCharges - { - get => m_PoisonCharges; - set - { - m_PoisonCharges = value; - InvalidateProperties(); - } - } - - bool IUsesRemaining.ShowUsesRemaining - { - get => true; - set { } - } - - public void AttackAnimation(Mobile from, Mobile to) - { - if (from.Body.IsHuman && !from.Mounted) from.Animate(33, 2, 1, true, true, 0); - - from.PlaySound(0x223); - from.MovingEffect(to, 0x2804, 5, 0, false, false); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1060584, m_UsesRemaining.ToString()); // uses remaining: ~1_val~ - - if (m_Poison != null && m_PoisonCharges > 0) - list.Add(1062412 + m_Poison.Level, m_PoisonCharges.ToString()); - } - - public override void OnDoubleClick(Mobile from) - { - NinjaWeapon.AttemptShoot((PlayerMobile)from, this); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (IsChildOf(from)) - { - list.Add(new NinjaWeapon.LoadEntry(this, 6224)); - list.Add(new NinjaWeapon.UnloadEntry(this, 6225)); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(m_UsesRemaining); - - Poison.Serialize(m_Poison, writer); - writer.Write(m_PoisonCharges); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_UsesRemaining = reader.ReadInt(); - - m_Poison = Poison.Deserialize(reader); - m_PoisonCharges = reader.ReadInt(); - - break; - } - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Ninjitsu/FukiyaDarts.cs b/Projects/UOContent/Items/Skill Items/Ninjitsu/FukiyaDarts.cs index 5e58d1fe9..6423a25ea 100644 --- a/Projects/UOContent/Items/Skill Items/Ninjitsu/FukiyaDarts.cs +++ b/Projects/UOContent/Items/Skill Items/Ninjitsu/FukiyaDarts.cs @@ -3,112 +3,114 @@ using Server.Engines.Craft; namespace Server.Items { - public class FukiyaDarts : Item, ICraftable, INinjaAmmo - { - private Poison m_Poison; - private int m_PoisonCharges; - private int m_UsesRemaining; - - [Constructible] - public FukiyaDarts(int amount = 1) : base(0x2806) + public class FukiyaDarts : Item, ICraftable, INinjaAmmo { - Weight = 1.0; + private Poison m_Poison; + private int m_PoisonCharges; + private int m_UsesRemaining; - m_UsesRemaining = amount; + [Constructible] + public FukiyaDarts(int amount = 1) : base(0x2806) + { + Weight = 1.0; + + m_UsesRemaining = amount; + } + + public FukiyaDarts(Serial serial) : base(serial) + { + } + + public int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, + CraftItem craftItem, int resHue + ) + { + if (quality == 2) + UsesRemaining *= 2; + + return quality; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int UsesRemaining + { + get => m_UsesRemaining; + set + { + m_UsesRemaining = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Poison Poison + { + get => m_Poison; + set + { + m_Poison = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int PoisonCharges + { + get => m_PoisonCharges; + set + { + m_PoisonCharges = value; + InvalidateProperties(); + } + } + + bool IUsesRemaining.ShowUsesRemaining + { + get => true; + set { } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1060584, m_UsesRemaining.ToString()); // uses remaining: ~1_val~ + + if (m_Poison != null && m_PoisonCharges > 0) + list.Add(1062412 + m_Poison.Level, m_PoisonCharges.ToString()); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_UsesRemaining); + + Poison.Serialize(m_Poison, writer); + writer.Write(m_PoisonCharges); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_UsesRemaining = reader.ReadInt(); + + m_Poison = Poison.Deserialize(reader); + m_PoisonCharges = reader.ReadInt(); + + break; + } + } + } } - - public FukiyaDarts(Serial serial) : base(serial) - { - } - - public int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, - CraftItem craftItem, int resHue) - { - if (quality == 2) - UsesRemaining *= 2; - - return quality; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int UsesRemaining - { - get => m_UsesRemaining; - set - { - m_UsesRemaining = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Poison Poison - { - get => m_Poison; - set - { - m_Poison = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int PoisonCharges - { - get => m_PoisonCharges; - set - { - m_PoisonCharges = value; - InvalidateProperties(); - } - } - - bool IUsesRemaining.ShowUsesRemaining - { - get => true; - set { } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1060584, m_UsesRemaining.ToString()); // uses remaining: ~1_val~ - - if (m_Poison != null && m_PoisonCharges > 0) - list.Add(1062412 + m_Poison.Level, m_PoisonCharges.ToString()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_UsesRemaining); - - Poison.Serialize(m_Poison, writer); - writer.Write(m_PoisonCharges); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_UsesRemaining = reader.ReadInt(); - - m_Poison = Poison.Deserialize(reader); - m_PoisonCharges = reader.ReadInt(); - - break; - } - } - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Ninjitsu/LeatherNinjaBelt.cs b/Projects/UOContent/Items/Skill Items/Ninjitsu/LeatherNinjaBelt.cs index 9caba05e1..d0b8e3756 100644 --- a/Projects/UOContent/Items/Skill Items/Ninjitsu/LeatherNinjaBelt.cs +++ b/Projects/UOContent/Items/Skill Items/Ninjitsu/LeatherNinjaBelt.cs @@ -5,154 +5,154 @@ using Server.Mobiles; namespace Server.Items { - [Flippable(0x2790, 0x27DB)] - public class LeatherNinjaBelt : BaseWaist, IDyable, INinjaWeapon - { - private Poison m_Poison; - private int m_PoisonCharges; - - private int m_UsesRemaining; - - [Constructible] - public LeatherNinjaBelt() : base(0x2790) + [Flippable(0x2790, 0x27DB)] + public class LeatherNinjaBelt : BaseWaist, IDyable, INinjaWeapon { - Weight = 1.0; - Layer = Layer.Waist; + private Poison m_Poison; + private int m_PoisonCharges; + + private int m_UsesRemaining; + + [Constructible] + public LeatherNinjaBelt() : base(0x2790) + { + Weight = 1.0; + Layer = Layer.Waist; + } + + public LeatherNinjaBelt(Serial serial) : base(serial) + { + } + + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public virtual int WrongAmmoMessage => 1063301; // You can only place shuriken in a ninja belt. + public virtual int NoFreeHandMessage => 1063299; // You must have a free hand to throw shuriken. + public virtual int EmptyWeaponMessage => 1063297; // You have no shuriken in your ninja belt! + public virtual int RecentlyUsedMessage => 1063298; // You cannot throw another shuriken yet. + public virtual int FullWeaponMessage => 1063302; // You cannot add any more shuriken. + + public virtual int WeaponMinRange => 2; + public virtual int WeaponMaxRange => 10; + + public virtual int WeaponDamage => Utility.RandomMinMax(3, 5); + + public virtual Type AmmoType => typeof(Shuriken); + + [CommandProperty(AccessLevel.GameMaster)] + public int UsesRemaining + { + get => m_UsesRemaining; + set + { + m_UsesRemaining = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Poison Poison + { + get => m_Poison; + set + { + m_Poison = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int PoisonCharges + { + get => m_PoisonCharges; + set + { + m_PoisonCharges = value; + InvalidateProperties(); + } + } + + public bool ShowUsesRemaining + { + get => true; + set { } + } + + public void AttackAnimation(Mobile from, Mobile to) + { + if (from.Body.IsHuman) from.Animate(from.Mounted ? 26 : 9, 7, 1, true, false, 0); + + from.PlaySound(0x23A); + from.MovingEffect(to, 0x27AC, 1, 0, false, false); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1060584, m_UsesRemaining.ToString()); // uses remaining: ~1_val~ + + if (m_Poison != null && m_PoisonCharges > 0) + list.Add(1062412 + m_Poison.Level, m_PoisonCharges.ToString()); + } + + public override bool OnEquip(Mobile from) + { + if (base.OnEquip(from)) + { + from.SendLocalizedMessage(1070785); // Double click this item each time you wish to throw a shuriken. + return true; + } + + return false; + } + + public override void OnDoubleClick(Mobile from) + { + NinjaWeapon.AttemptShoot((PlayerMobile)from, this); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (IsChildOf(from)) + { + list.Add(new NinjaWeapon.LoadEntry(this, 6222)); + list.Add(new NinjaWeapon.UnloadEntry(this, 6223)); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + writer.Write(m_UsesRemaining); + + Poison.Serialize(m_Poison, writer); + writer.Write(m_PoisonCharges); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_UsesRemaining = reader.ReadInt(); + + m_Poison = Poison.Deserialize(reader); + m_PoisonCharges = reader.ReadInt(); + + break; + } + } + } } - - public LeatherNinjaBelt(Serial serial) : base(serial) - { - } - - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public virtual int WrongAmmoMessage => 1063301; // You can only place shuriken in a ninja belt. - public virtual int NoFreeHandMessage => 1063299; // You must have a free hand to throw shuriken. - public virtual int EmptyWeaponMessage => 1063297; // You have no shuriken in your ninja belt! - public virtual int RecentlyUsedMessage => 1063298; // You cannot throw another shuriken yet. - public virtual int FullWeaponMessage => 1063302; // You cannot add any more shuriken. - - public virtual int WeaponMinRange => 2; - public virtual int WeaponMaxRange => 10; - - public virtual int WeaponDamage => Utility.RandomMinMax(3, 5); - - public virtual Type AmmoType => typeof(Shuriken); - - [CommandProperty(AccessLevel.GameMaster)] - public int UsesRemaining - { - get => m_UsesRemaining; - set - { - m_UsesRemaining = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Poison Poison - { - get => m_Poison; - set - { - m_Poison = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int PoisonCharges - { - get => m_PoisonCharges; - set - { - m_PoisonCharges = value; - InvalidateProperties(); - } - } - - public bool ShowUsesRemaining - { - get => true; - set { } - } - - public void AttackAnimation(Mobile from, Mobile to) - { - if (from.Body.IsHuman) from.Animate(from.Mounted ? 26 : 9, 7, 1, true, false, 0); - - from.PlaySound(0x23A); - from.MovingEffect(to, 0x27AC, 1, 0, false, false); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1060584, m_UsesRemaining.ToString()); // uses remaining: ~1_val~ - - if (m_Poison != null && m_PoisonCharges > 0) - list.Add(1062412 + m_Poison.Level, m_PoisonCharges.ToString()); - } - - public override bool OnEquip(Mobile from) - { - if (base.OnEquip(from)) - { - from.SendLocalizedMessage(1070785); // Double click this item each time you wish to throw a shuriken. - return true; - } - - return false; - } - - public override void OnDoubleClick(Mobile from) - { - NinjaWeapon.AttemptShoot((PlayerMobile)from, this); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (IsChildOf(from)) - { - list.Add(new NinjaWeapon.LoadEntry(this, 6222)); - list.Add(new NinjaWeapon.UnloadEntry(this, 6223)); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(m_UsesRemaining); - - Poison.Serialize(m_Poison, writer); - writer.Write(m_PoisonCharges); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_UsesRemaining = reader.ReadInt(); - - m_Poison = Poison.Deserialize(reader); - m_PoisonCharges = reader.ReadInt(); - - break; - } - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Ninjitsu/NinjaWeapons.cs b/Projects/UOContent/Items/Skill Items/Ninjitsu/NinjaWeapons.cs index 1147d9d48..8b9682d67 100644 --- a/Projects/UOContent/Items/Skill Items/Ninjitsu/NinjaWeapons.cs +++ b/Projects/UOContent/Items/Skill Items/Ninjitsu/NinjaWeapons.cs @@ -16,292 +16,292 @@ using Server.Utilities; namespace Server.Items { - public interface INinjaAmmo : IUsesRemaining - { - int PoisonCharges { get; set; } - Poison Poison { get; set; } - } - - public interface INinjaWeapon : IUsesRemaining - { - int NoFreeHandMessage { get; } - int EmptyWeaponMessage { get; } - int RecentlyUsedMessage { get; } - int FullWeaponMessage { get; } - int WrongAmmoMessage { get; } - Type AmmoType { get; } - int PoisonCharges { get; set; } - Poison Poison { get; set; } - int WeaponDamage { get; } - int WeaponMinRange { get; } - int WeaponMaxRange { get; } - - void AttackAnimation(Mobile from, Mobile to); - } - - public class NinjaWeapon - { - private const int MaxUses = 10; - - public static void AttemptShoot(PlayerMobile from, INinjaWeapon weapon) + public interface INinjaAmmo : IUsesRemaining { - if (CanUseWeapon(from, weapon)) - from.BeginTarget(weapon.WeaponMaxRange, false, TargetFlags.Harmful, OnTarget, weapon); + int PoisonCharges { get; set; } + Poison Poison { get; set; } } - private static void Shoot(PlayerMobile from, Mobile target, INinjaWeapon weapon) + public interface INinjaWeapon : IUsesRemaining { - if (from != target && CanUseWeapon(from, weapon) && from.CanBeHarmful(target)) - { - if (weapon.WeaponMinRange == 0 || !from.InRange(target, weapon.WeaponMinRange)) - { - from.NinjaWepCooldown = true; + int NoFreeHandMessage { get; } + int EmptyWeaponMessage { get; } + int RecentlyUsedMessage { get; } + int FullWeaponMessage { get; } + int WrongAmmoMessage { get; } + Type AmmoType { get; } + int PoisonCharges { get; set; } + Poison Poison { get; set; } + int WeaponDamage { get; } + int WeaponMinRange { get; } + int WeaponMaxRange { get; } - from.Direction = from.GetDirectionTo(target); - - from.RevealingAction(); - - weapon.AttackAnimation(from, target); - - ConsumeUse(weapon); - - if (CombatCheck(from, target)) - Timer.DelayCall(TimeSpan.FromSeconds(1.0), OnHit, from, target, weapon); - - Timer.DelayCall(TimeSpan.FromSeconds(2.5), ResetUsing, from); - } - else - { - from.SendLocalizedMessage(1063303); // Your target is too close! - } - } + void AttackAnimation(Mobile from, Mobile to); } - private static void ResetUsing(PlayerMobile from) + public class NinjaWeapon { - from.NinjaWepCooldown = false; - } + private const int MaxUses = 10; - private static void Unload(Mobile from, INinjaWeapon weapon) - { - if (weapon.UsesRemaining > 0) - { - Item ammo = ActivatorUtil.CreateInstance(weapon.AmmoType, weapon.UsesRemaining) as Item; - - if (ammo is INinjaAmmo ninaAmmo) + public static void AttemptShoot(PlayerMobile from, INinjaWeapon weapon) { - ninaAmmo.Poison = weapon.Poison; - ninaAmmo.PoisonCharges = weapon.PoisonCharges; + if (CanUseWeapon(from, weapon)) + from.BeginTarget(weapon.WeaponMaxRange, false, TargetFlags.Harmful, OnTarget, weapon); } - from.AddToBackpack(ammo); - - weapon.UsesRemaining = 0; - weapon.PoisonCharges = 0; - weapon.Poison = null; - } - } - - private static void Reload(PlayerMobile from, INinjaWeapon weapon, INinjaAmmo ammo) - { - if (weapon.UsesRemaining < MaxUses) - { - int need = Math.Min(MaxUses - weapon.UsesRemaining, ammo.UsesRemaining); - - if (need > 0) + private static void Shoot(PlayerMobile from, Mobile target, INinjaWeapon weapon) + { + if (from != target && CanUseWeapon(from, weapon) && from.CanBeHarmful(target)) + { + if (weapon.WeaponMinRange == 0 || !from.InRange(target, weapon.WeaponMinRange)) + { + from.NinjaWepCooldown = true; + + from.Direction = from.GetDirectionTo(target); + + from.RevealingAction(); + + weapon.AttackAnimation(from, target); + + ConsumeUse(weapon); + + if (CombatCheck(from, target)) + Timer.DelayCall(TimeSpan.FromSeconds(1.0), OnHit, from, target, weapon); + + Timer.DelayCall(TimeSpan.FromSeconds(2.5), ResetUsing, from); + } + else + { + from.SendLocalizedMessage(1063303); // Your target is too close! + } + } + } + + private static void ResetUsing(PlayerMobile from) + { + from.NinjaWepCooldown = false; + } + + private static void Unload(Mobile from, INinjaWeapon weapon) { - if (weapon.Poison != null && (ammo.Poison == null || weapon.Poison.Level > ammo.Poison.Level)) - { - from.SendLocalizedMessage(1070767); // Loaded projectile is stronger, unload it first - } - else - { if (weapon.UsesRemaining > 0) - if ((weapon.Poison == null && ammo.Poison != null) - || (weapon.Poison != null && ammo.Poison != null && weapon.Poison.Level != ammo.Poison.Level)) - { - Unload(from, weapon); - need = Math.Min(MaxUses, ammo.UsesRemaining); - } + { + var ammo = ActivatorUtil.CreateInstance(weapon.AmmoType, weapon.UsesRemaining) as Item; - int poisonneeded = Math.Min(MaxUses - weapon.PoisonCharges, ammo.PoisonCharges); + if (ammo is INinjaAmmo ninaAmmo) + { + ninaAmmo.Poison = weapon.Poison; + ninaAmmo.PoisonCharges = weapon.PoisonCharges; + } - weapon.UsesRemaining += need; - weapon.PoisonCharges += poisonneeded; + from.AddToBackpack(ammo); - if (weapon.PoisonCharges > 0) weapon.Poison = ammo.Poison; - - ammo.PoisonCharges -= poisonneeded; - ammo.UsesRemaining -= need; - - if (ammo.UsesRemaining < 1) - ((Item)ammo).Delete(); - else if (ammo.PoisonCharges < 1) ammo.Poison = null; - } - } // "else" here would mean they targeted "ammo" with 0 uses. undefined behavior. - } - else - { - from.SendLocalizedMessage(weapon.FullWeaponMessage); - } - } - - private static void ConsumeUse(INinjaWeapon weapon) - { - if (weapon.UsesRemaining > 0) - { - weapon.UsesRemaining--; - - if (weapon.UsesRemaining < 1) - { - weapon.PoisonCharges = 0; - weapon.Poison = null; + weapon.UsesRemaining = 0; + weapon.PoisonCharges = 0; + weapon.Poison = null; + } } - } - } - private static bool CanUseWeapon(PlayerMobile from, INinjaWeapon weapon) - { - if (WeaponIsValid(weapon, from)) - { - if (weapon.UsesRemaining > 0) + private static void Reload(PlayerMobile from, INinjaWeapon weapon, INinjaAmmo ammo) { - if (!from.NinjaWepCooldown) - { - if (BasePotion.HasFreeHand(from)) return true; + if (weapon.UsesRemaining < MaxUses) + { + var need = Math.Min(MaxUses - weapon.UsesRemaining, ammo.UsesRemaining); - from.SendLocalizedMessage(weapon.NoFreeHandMessage); - } - else - { - from.SendLocalizedMessage(weapon.RecentlyUsedMessage); - } + if (need > 0) + { + if (weapon.Poison != null && (ammo.Poison == null || weapon.Poison.Level > ammo.Poison.Level)) + { + from.SendLocalizedMessage(1070767); // Loaded projectile is stronger, unload it first + } + else + { + if (weapon.UsesRemaining > 0) + if (weapon.Poison == null && ammo.Poison != null + || weapon.Poison != null && ammo.Poison != null && weapon.Poison.Level != ammo.Poison.Level) + { + Unload(from, weapon); + need = Math.Min(MaxUses, ammo.UsesRemaining); + } + + var poisonneeded = Math.Min(MaxUses - weapon.PoisonCharges, ammo.PoisonCharges); + + weapon.UsesRemaining += need; + weapon.PoisonCharges += poisonneeded; + + if (weapon.PoisonCharges > 0) weapon.Poison = ammo.Poison; + + ammo.PoisonCharges -= poisonneeded; + ammo.UsesRemaining -= need; + + if (ammo.UsesRemaining < 1) + ((Item)ammo).Delete(); + else if (ammo.PoisonCharges < 1) ammo.Poison = null; + } + } // "else" here would mean they targeted "ammo" with 0 uses. undefined behavior. + } + else + { + from.SendLocalizedMessage(weapon.FullWeaponMessage); + } } - else + + private static void ConsumeUse(INinjaWeapon weapon) { - from.SendLocalizedMessage(weapon.EmptyWeaponMessage); + if (weapon.UsesRemaining > 0) + { + weapon.UsesRemaining--; + + if (weapon.UsesRemaining < 1) + { + weapon.PoisonCharges = 0; + weapon.Poison = null; + } + } } - } - return false; + private static bool CanUseWeapon(PlayerMobile from, INinjaWeapon weapon) + { + if (WeaponIsValid(weapon, from)) + { + if (weapon.UsesRemaining > 0) + { + if (!from.NinjaWepCooldown) + { + if (BasePotion.HasFreeHand(from)) return true; + + from.SendLocalizedMessage(weapon.NoFreeHandMessage); + } + else + { + from.SendLocalizedMessage(weapon.RecentlyUsedMessage); + } + } + else + { + from.SendLocalizedMessage(weapon.EmptyWeaponMessage); + } + } + + return false; + } + + private static bool CombatCheck(Mobile attacker, Mobile defender) /* mod'd from baseweapon */ + { + var defWeapon = defender.Weapon as BaseWeapon; + + var atkSkill = defender.Skills.Ninjitsu; + // Skill defSkill = defender.Skills[defWeapon.Skill]; + + var atSkillValue = attacker.Skills.Ninjitsu.Value; + var defSkillValue = defWeapon?.GetDefendSkillValue(attacker, defender) ?? 0.0; + + if (defSkillValue <= -20.0) defSkillValue = -19.9; + + double attackValue = AosAttributes.GetValue(attacker, AosAttribute.AttackChance); + + if (DivineFurySpell.UnderEffect(attacker)) attackValue += 10; + + if (AnimalForm.UnderTransformation(attacker, typeof(GreyWolf)) || + AnimalForm.UnderTransformation(attacker, typeof(BakeKitsune))) attackValue += 20; + + if (HitLower.IsUnderAttackEffect(attacker)) attackValue -= 25; + + if (attackValue > 45) attackValue = 45; + + attackValue = (atSkillValue + 20.0) * (100 + attackValue); + + double defenseValue = AosAttributes.GetValue(defender, AosAttribute.DefendChance); + + if (DivineFurySpell.UnderEffect(defender)) defenseValue -= 20; + + if (HitLower.IsUnderDefenseEffect(defender)) defenseValue -= 25; + + var refBonus = 0; + + if (Block.GetBonus(defender, ref refBonus)) defenseValue += refBonus; + + if (Discordance.GetEffect(attacker, ref refBonus)) defenseValue -= refBonus; + + if (defenseValue > 45) defenseValue = 45; + + defenseValue = (defSkillValue + 20.0) * (100 + defenseValue); + + var chance = attackValue / (defenseValue * 2.0); + + if (chance < 0.02) chance = 0.02; + + return attacker.CheckSkill(atkSkill.SkillName, chance); + } + + private static void OnHit(Mobile from, Mobile target, INinjaWeapon weapon) + { + if (!from.CanBeHarmful(target)) + return; + from.DoHarmful(target); + + AOS.Damage(target, from, weapon.WeaponDamage, 100, 0, 0, 0, 0); + + if (weapon.Poison != null && weapon.PoisonCharges > 0) + { + if (EvilOmenSpell.TryEndEffect(target)) + target.ApplyPoison(from, Poison.GetPoison(weapon.Poison.Level + 1)); + else + target.ApplyPoison(from, weapon.Poison); + + weapon.PoisonCharges--; + + if (weapon.PoisonCharges < 1) weapon.Poison = null; + } + } + + private static void OnTarget(Mobile from, object targeted, INinjaWeapon weapon) + { + if (from is PlayerMobile player && WeaponIsValid(weapon, from)) + { + if (targeted is Mobile mobile) + Shoot(player, mobile, weapon); + else if (targeted.GetType() == weapon.AmmoType) + Reload(player, weapon, (INinjaAmmo)targeted); + else + player.SendLocalizedMessage(weapon.WrongAmmoMessage); + } + } + + private static bool WeaponIsValid(INinjaWeapon weapon, Mobile from) => + weapon is Item item && !item.Deleted && item.RootParent == from; + + public class LoadEntry : ContextMenuEntry + { + private readonly INinjaWeapon weapon; + + public LoadEntry(INinjaWeapon wep, int entry) + : base(entry, 0) => + weapon = wep; + + public override void OnClick() + { + if (WeaponIsValid(weapon, Owner.From)) + Owner.From.BeginTarget(10, false, TargetFlags.Harmful, OnTarget, weapon); + } + } + + public class UnloadEntry : ContextMenuEntry + { + private readonly INinjaWeapon weapon; + + public UnloadEntry(INinjaWeapon wep, int entry) + : base(entry, 0) + { + weapon = wep; + + Enabled = weapon.UsesRemaining > 0; + } + + public override void OnClick() + { + if (WeaponIsValid(weapon, Owner.From)) Unload(Owner.From, weapon); + } + } } - - private static bool CombatCheck(Mobile attacker, Mobile defender) /* mod'd from baseweapon */ - { - BaseWeapon defWeapon = defender.Weapon as BaseWeapon; - - Skill atkSkill = defender.Skills.Ninjitsu; - // Skill defSkill = defender.Skills[defWeapon.Skill]; - - double atSkillValue = attacker.Skills.Ninjitsu.Value; - double defSkillValue = defWeapon?.GetDefendSkillValue(attacker, defender) ?? 0.0; - - if (defSkillValue <= -20.0) defSkillValue = -19.9; - - double attackValue = AosAttributes.GetValue(attacker, AosAttribute.AttackChance); - - if (DivineFurySpell.UnderEffect(attacker)) attackValue += 10; - - if (AnimalForm.UnderTransformation(attacker, typeof(GreyWolf)) || - AnimalForm.UnderTransformation(attacker, typeof(BakeKitsune))) attackValue += 20; - - if (HitLower.IsUnderAttackEffect(attacker)) attackValue -= 25; - - if (attackValue > 45) attackValue = 45; - - attackValue = (atSkillValue + 20.0) * (100 + attackValue); - - double defenseValue = AosAttributes.GetValue(defender, AosAttribute.DefendChance); - - if (DivineFurySpell.UnderEffect(defender)) defenseValue -= 20; - - if (HitLower.IsUnderDefenseEffect(defender)) defenseValue -= 25; - - int refBonus = 0; - - if (Block.GetBonus(defender, ref refBonus)) defenseValue += refBonus; - - if (Discordance.GetEffect(attacker, ref refBonus)) defenseValue -= refBonus; - - if (defenseValue > 45) defenseValue = 45; - - defenseValue = (defSkillValue + 20.0) * (100 + defenseValue); - - double chance = attackValue / (defenseValue * 2.0); - - if (chance < 0.02) chance = 0.02; - - return attacker.CheckSkill(atkSkill.SkillName, chance); - } - - private static void OnHit(Mobile from, Mobile target, INinjaWeapon weapon) - { - if (!from.CanBeHarmful(target)) - return; - from.DoHarmful(target); - - AOS.Damage(target, from, weapon.WeaponDamage, 100, 0, 0, 0, 0); - - if (weapon.Poison != null && weapon.PoisonCharges > 0) - { - if (EvilOmenSpell.TryEndEffect(target)) - target.ApplyPoison(from, Poison.GetPoison(weapon.Poison.Level + 1)); - else - target.ApplyPoison(from, weapon.Poison); - - weapon.PoisonCharges--; - - if (weapon.PoisonCharges < 1) weapon.Poison = null; - } - } - - private static void OnTarget(Mobile from, object targeted, INinjaWeapon weapon) - { - if (from is PlayerMobile player && WeaponIsValid(weapon, from)) - { - if (targeted is Mobile mobile) - Shoot(player, mobile, weapon); - else if (targeted.GetType() == weapon.AmmoType) - Reload(player, weapon, (INinjaAmmo)targeted); - else - player.SendLocalizedMessage(weapon.WrongAmmoMessage); - } - } - - private static bool WeaponIsValid(INinjaWeapon weapon, Mobile from) => - weapon is Item item && !item.Deleted && item.RootParent == from; - - public class LoadEntry : ContextMenuEntry - { - private readonly INinjaWeapon weapon; - - public LoadEntry(INinjaWeapon wep, int entry) - : base(entry, 0) => - weapon = wep; - - public override void OnClick() - { - if (WeaponIsValid(weapon, Owner.From)) - Owner.From.BeginTarget(10, false, TargetFlags.Harmful, OnTarget, weapon); - } - } - - public class UnloadEntry : ContextMenuEntry - { - private readonly INinjaWeapon weapon; - - public UnloadEntry(INinjaWeapon wep, int entry) - : base(entry, 0) - { - weapon = wep; - - Enabled = weapon.UsesRemaining > 0; - } - - public override void OnClick() - { - if (WeaponIsValid(weapon, Owner.From)) Unload(Owner.From, weapon); - } - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Ninjitsu/Shuriken.cs b/Projects/UOContent/Items/Skill Items/Ninjitsu/Shuriken.cs index 3b64a3d28..c83e06d36 100644 --- a/Projects/UOContent/Items/Skill Items/Ninjitsu/Shuriken.cs +++ b/Projects/UOContent/Items/Skill Items/Ninjitsu/Shuriken.cs @@ -3,113 +3,115 @@ using Server.Engines.Craft; namespace Server.Items { - [Flippable(0x27AC, 0x27F7)] - public class Shuriken : Item, ICraftable, INinjaAmmo - { - private Poison m_Poison; - private int m_PoisonCharges; - private int m_UsesRemaining; - - [Constructible] - public Shuriken(int amount = 1) : base(0x27AC) + [Flippable(0x27AC, 0x27F7)] + public class Shuriken : Item, ICraftable, INinjaAmmo { - Weight = 1.0; + private Poison m_Poison; + private int m_PoisonCharges; + private int m_UsesRemaining; - m_UsesRemaining = amount; + [Constructible] + public Shuriken(int amount = 1) : base(0x27AC) + { + Weight = 1.0; + + m_UsesRemaining = amount; + } + + public Shuriken(Serial serial) : base(serial) + { + } + + public int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, + CraftItem craftItem, int resHue + ) + { + if (quality == 2) + UsesRemaining *= 2; + + return quality; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int UsesRemaining + { + get => m_UsesRemaining; + set + { + m_UsesRemaining = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Poison Poison + { + get => m_Poison; + set + { + m_Poison = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int PoisonCharges + { + get => m_PoisonCharges; + set + { + m_PoisonCharges = value; + InvalidateProperties(); + } + } + + bool IUsesRemaining.ShowUsesRemaining + { + get => true; + set { } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1060584, m_UsesRemaining.ToString()); // uses remaining: ~1_val~ + + if (m_Poison != null && m_PoisonCharges > 0) + list.Add(1062412 + m_Poison.Level, m_PoisonCharges.ToString()); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_UsesRemaining); + + Poison.Serialize(m_Poison, writer); + writer.Write(m_PoisonCharges); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_UsesRemaining = reader.ReadInt(); + + m_Poison = Poison.Deserialize(reader); + m_PoisonCharges = reader.ReadInt(); + + break; + } + } + } } - - public Shuriken(Serial serial) : base(serial) - { - } - - public int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, - CraftItem craftItem, int resHue) - { - if (quality == 2) - UsesRemaining *= 2; - - return quality; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int UsesRemaining - { - get => m_UsesRemaining; - set - { - m_UsesRemaining = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Poison Poison - { - get => m_Poison; - set - { - m_Poison = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int PoisonCharges - { - get => m_PoisonCharges; - set - { - m_PoisonCharges = value; - InvalidateProperties(); - } - } - - bool IUsesRemaining.ShowUsesRemaining - { - get => true; - set { } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1060584, m_UsesRemaining.ToString()); // uses remaining: ~1_val~ - - if (m_Poison != null && m_PoisonCharges > 0) - list.Add(1062412 + m_Poison.Level, m_PoisonCharges.ToString()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_UsesRemaining); - - Poison.Serialize(m_Poison, writer); - writer.Write(m_PoisonCharges); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_UsesRemaining = reader.ReadInt(); - - m_Poison = Poison.Deserialize(reader); - m_PoisonCharges = reader.ReadInt(); - - break; - } - } - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Ninjitsu/SmokeBomb.cs b/Projects/UOContent/Items/Skill Items/Ninjitsu/SmokeBomb.cs index e389ce942..9405d915a 100644 --- a/Projects/UOContent/Items/Skill Items/Ninjitsu/SmokeBomb.cs +++ b/Projects/UOContent/Items/Skill Items/Ninjitsu/SmokeBomb.cs @@ -2,71 +2,71 @@ using Server.SkillHandlers; namespace Server.Items { - public class SmokeBomb : Item - { - [Constructible] - public SmokeBomb() : base(0x2808) + public class SmokeBomb : Item { - Stackable = Core.ML; - Weight = 1.0; - } - - public SmokeBomb(Serial serial) : base(serial) - { - } - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - // The item must be in your backpack to use it. - from.SendLocalizedMessage(1060640); - } - else if (from.Skills.Ninjitsu.Value < 50.0) - { - // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability. - from.SendLocalizedMessage(1063013, "50\tNinjitsu"); - } - else if (Core.TickCount - from.NextSkillTime < 0) - { - // You must wait a few seconds before you can use that item. - from.SendLocalizedMessage(1070772); - } - else if (from.Mana < 10) - { - // You don't have enough mana to do that. - from.SendLocalizedMessage(1049456); - } - else - { - Hiding.CombatOverride = true; - - if (from.UseSkill(SkillName.Hiding)) + [Constructible] + public SmokeBomb() : base(0x2808) { - from.Mana -= 10; - - from.FixedParticles(0x3709, 1, 30, 9904, 1108, 6, EffectLayer.RightFoot); - from.PlaySound(0x22F); - - Consume(); + Stackable = Core.ML; + Weight = 1.0; } - Hiding.CombatOverride = false; - } + public SmokeBomb(Serial serial) : base(serial) + { + } + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + // The item must be in your backpack to use it. + from.SendLocalizedMessage(1060640); + } + else if (from.Skills.Ninjitsu.Value < 50.0) + { + // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability. + from.SendLocalizedMessage(1063013, "50\tNinjitsu"); + } + else if (Core.TickCount - from.NextSkillTime < 0) + { + // You must wait a few seconds before you can use that item. + from.SendLocalizedMessage(1070772); + } + else if (from.Mana < 10) + { + // You don't have enough mana to do that. + from.SendLocalizedMessage(1049456); + } + else + { + Hiding.CombatOverride = true; + + if (from.UseSkill(SkillName.Hiding)) + { + from.Mana -= 10; + + from.FixedParticles(0x3709, 1, 30, 9904, 1108, 6, EffectLayer.RightFoot); + from.PlaySound(0x22F); + + Consume(); + } + + Hiding.CombatOverride = false; + } + } + + 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(); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Specialized/GlassblowingBook.cs b/Projects/UOContent/Items/Skill Items/Specialized/GlassblowingBook.cs index adb7895aa..7a5b0fda0 100644 --- a/Projects/UOContent/Items/Skill Items/Specialized/GlassblowingBook.cs +++ b/Projects/UOContent/Items/Skill Items/Specialized/GlassblowingBook.cs @@ -2,54 +2,55 @@ using Server.Mobiles; namespace Server.Items { - public class GlassblowingBook : Item - { - [Constructible] - public GlassblowingBook() : base(0xFF4) => Weight = 1.0; - - public GlassblowingBook(Serial serial) : base(serial) + public class GlassblowingBook : Item { + [Constructible] + public GlassblowingBook() : base(0xFF4) => Weight = 1.0; + + public GlassblowingBook(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Crafting Glass With Glassblowing"; + + 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) + { + var pm = from as PlayerMobile; + + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else if (pm == null || from.Skills.Alchemy.Base < 100.0) + { + pm.SendMessage("Only a Grandmaster Alchemist can learn from this book."); + } + else if (pm.Glassblowing) + { + pm.SendMessage("You have already learned this information."); + } + else + { + pm.Glassblowing = true; + pm.SendMessage( + "You have learned to make items from glass. You will need to find miners to mine find sand for you to make these items." + ); + Delete(); + } + } } - - public override string DefaultName => "Crafting Glass With Glassblowing"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - PlayerMobile pm = from as PlayerMobile; - - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (pm == null || from.Skills.Alchemy.Base < 100.0) - { - pm.SendMessage("Only a Grandmaster Alchemist can learn from this book."); - } - else if (pm.Glassblowing) - { - pm.SendMessage("You have already learned this information."); - } - else - { - pm.Glassblowing = true; - pm.SendMessage( - "You have learned to make items from glass. You will need to find miners to mine find sand for you to make these items."); - Delete(); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Specialized/MasonryBook.cs b/Projects/UOContent/Items/Skill Items/Specialized/MasonryBook.cs index 45e1db6b5..ee337d1c8 100644 --- a/Projects/UOContent/Items/Skill Items/Specialized/MasonryBook.cs +++ b/Projects/UOContent/Items/Skill Items/Specialized/MasonryBook.cs @@ -2,54 +2,55 @@ using Server.Mobiles; namespace Server.Items { - public class MasonryBook : Item - { - [Constructible] - public MasonryBook() : base(0xFBE) => Weight = 1.0; - - public MasonryBook(Serial serial) : base(serial) + public class MasonryBook : Item { + [Constructible] + public MasonryBook() : base(0xFBE) => Weight = 1.0; + + public MasonryBook(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Making Valuables With Stonecrafting"; + + 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) + { + var pm = from as PlayerMobile; + + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else if (pm == null || from.Skills.Carpentry.Base < 100.0) + { + pm.SendMessage("Only a Grandmaster Carpenter can learn from this book."); + } + else if (pm.Masonry) + { + pm.SendMessage("You have already learned this information."); + } + else + { + pm.Masonry = true; + pm.SendMessage( + "You have learned to make items from stone. You will need miners to gather stones for you to make these items." + ); + Delete(); + } + } } - - public override string DefaultName => "Making Valuables With Stonecrafting"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - PlayerMobile pm = from as PlayerMobile; - - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (pm == null || from.Skills.Carpentry.Base < 100.0) - { - pm.SendMessage("Only a Grandmaster Carpenter can learn from this book."); - } - else if (pm.Masonry) - { - pm.SendMessage("You have already learned this information."); - } - else - { - pm.Masonry = true; - pm.SendMessage( - "You have learned to make items from stone. You will need miners to gather stones for you to make these items."); - Delete(); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Specialized/Sand.cs b/Projects/UOContent/Items/Skill Items/Specialized/Sand.cs index 45250ff2b..7c5e3eefa 100644 --- a/Projects/UOContent/Items/Skill Items/Specialized/Sand.cs +++ b/Projects/UOContent/Items/Skill Items/Specialized/Sand.cs @@ -1,38 +1,38 @@ namespace Server.Items { - [Flippable(0x11EA, 0x11EB)] - public class Sand : Item, ICommodity - { - [Constructible] - public Sand(int amount = 1) : base(0x11EA) + [Flippable(0x11EA, 0x11EB)] + public class Sand : Item, ICommodity { - Stackable = Core.ML; - Weight = 1.0; + [Constructible] + public Sand(int amount = 1) : base(0x11EA) + { + Stackable = Core.ML; + Weight = 1.0; + } + + public Sand(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1044626; // sand + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => true; + + 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 && Name == "sand") + Name = null; + } } - - public Sand(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1044626; // sand - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version == 0 && Name == "sand") - Name = null; - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Specialized/SandMiningBook.cs b/Projects/UOContent/Items/Skill Items/Specialized/SandMiningBook.cs index c7e473886..04099b6a3 100644 --- a/Projects/UOContent/Items/Skill Items/Specialized/SandMiningBook.cs +++ b/Projects/UOContent/Items/Skill Items/Specialized/SandMiningBook.cs @@ -2,54 +2,55 @@ using Server.Mobiles; namespace Server.Items { - public class SandMiningBook : Item - { - [Constructible] - public SandMiningBook() : base(0xFF4) => Weight = 1.0; - - public SandMiningBook(Serial serial) : base(serial) + public class SandMiningBook : Item { + [Constructible] + public SandMiningBook() : base(0xFF4) => Weight = 1.0; + + public SandMiningBook(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Find Glass-Quality Sand"; + + 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) + { + var pm = from as PlayerMobile; + + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else if (pm == null || from.Skills.Mining.Base < 100.0) + { + pm.SendMessage("Only a Grandmaster Miner can learn from this book."); + } + else if (pm.SandMining) + { + pm.SendMessage("You have already learned this information."); + } + else + { + pm.SandMining = true; + pm.SendMessage( + "You have learned how to mine fine sand. Target sand areas when mining to look for fine sand." + ); + Delete(); + } + } } - - public override string DefaultName => "Find Glass-Quality Sand"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - PlayerMobile pm = from as PlayerMobile; - - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (pm == null || from.Skills.Mining.Base < 100.0) - { - pm.SendMessage("Only a Grandmaster Miner can learn from this book."); - } - else if (pm.SandMining) - { - pm.SendMessage("You have already learned this information."); - } - else - { - pm.SandMining = true; - pm.SendMessage( - "You have learned how to mine fine sand. Target sand areas when mining to look for fine sand."); - Delete(); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Specialized/StoneMiningBook.cs b/Projects/UOContent/Items/Skill Items/Specialized/StoneMiningBook.cs index 1a5e33fe2..9ee89fc85 100644 --- a/Projects/UOContent/Items/Skill Items/Specialized/StoneMiningBook.cs +++ b/Projects/UOContent/Items/Skill Items/Specialized/StoneMiningBook.cs @@ -2,53 +2,53 @@ using Server.Mobiles; namespace Server.Items { - public class StoneMiningBook : Item - { - [Constructible] - public StoneMiningBook() : base(0xFBE) => Weight = 1.0; - - public StoneMiningBook(Serial serial) : base(serial) + public class StoneMiningBook : Item { + [Constructible] + public StoneMiningBook() : base(0xFBE) => Weight = 1.0; + + public StoneMiningBook(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Mining For Quality Stone"; + + 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) + { + var pm = from as PlayerMobile; + + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else if (pm == null || from.Skills.Mining.Base < 100.0) + { + from.SendMessage("Only a Grandmaster Miner can learn from this book."); + } + else if (pm.StoneMining) + { + pm.SendMessage("You have already learned this knowledge."); + } + else + { + pm.StoneMining = true; + pm.SendMessage("You have learned to mine for stones. Target mountains when mining to find stones."); + Delete(); + } + } } - - public override string DefaultName => "Mining For Quality Stone"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - PlayerMobile pm = from as PlayerMobile; - - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (pm == null || from.Skills.Mining.Base < 100.0) - { - from.SendMessage("Only a Grandmaster Miner can learn from this book."); - } - else if (pm.StoneMining) - { - pm.SendMessage("You have already learned this knowledge."); - } - else - { - pm.StoneMining = true; - pm.SendMessage("You have learned to mine for stones. Target mountains when mining to find stones."); - Delete(); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/BlackDyeTub.cs b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/BlackDyeTub.cs index 91e0316a5..b966ced74 100644 --- a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/BlackDyeTub.cs +++ b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/BlackDyeTub.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class BlackDyeTub : DyeTub - { - [Constructible] - public BlackDyeTub() + public class BlackDyeTub : DyeTub { - Hue = DyedHue = 0x0001; - Redyable = false; + [Constructible] + public BlackDyeTub() + { + Hue = DyedHue = 0x0001; + Redyable = false; + } + + public BlackDyeTub(Serial serial) : base(serial) + { + } + + 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 BlackDyeTub(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/BlazeDyeTub.cs b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/BlazeDyeTub.cs index edfeaa418..d91430113 100644 --- a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/BlazeDyeTub.cs +++ b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/BlazeDyeTub.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class BlazeDyeTub : DyeTub - { - [Constructible] - public BlazeDyeTub() + public class BlazeDyeTub : DyeTub { - Hue = DyedHue = 0x489; - Redyable = false; + [Constructible] + public BlazeDyeTub() + { + Hue = DyedHue = 0x489; + Redyable = false; + } + + public BlazeDyeTub(Serial serial) : base(serial) + { + } + + 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 BlazeDyeTub(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/CustomHuePicker.cs b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/CustomHuePicker.cs index 310120ff0..5ff8509cd 100644 --- a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/CustomHuePicker.cs +++ b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/CustomHuePicker.cs @@ -3,212 +3,221 @@ using Server.Network; namespace Server.Items { - public class CustomHueGroup - { - public CustomHueGroup(int name, int[] hues) + public class CustomHueGroup { - Name = name; - Hues = hues; - } - - public CustomHueGroup(string name, int[] hues) - { - NameString = name; - Hues = hues; - } - - public int Name { get; } - - public string NameString { get; } - - public int[] Hues { get; } - } - - public class CustomHuePicker - { - public static readonly CustomHuePicker SpecialDyeTub = new CustomHuePicker(new[] - { - /* Violet */ - new CustomHueGroup(1018345, new[] { 1230, 1231, 1232, 1233, 1234, 1235 }), - /* Tan */ - new CustomHueGroup(1018346, new[] { 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508 }), - /* Brown */ - new CustomHueGroup(1018347, new[] { 2012, 2013, 2014, 2015, 2016, 2017 }), - /* Dark Blue */ - new CustomHueGroup(1018348, new[] { 1303, 1304, 1305, 1306, 1307, 1308 }), - /* Forest Green */ - new CustomHueGroup(1018349, new[] { 1420, 1421, 1422, 1423, 1424, 1425, 1426 }), - /* Pink */ - new CustomHueGroup(1018350, new[] { 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626 }), - /* Red */ - new CustomHueGroup(1018351, new[] { 1640, 1641, 1642, 1643, 1644 }), - /* Olive */ - new CustomHueGroup(1018352, new[] { 2001, 2002, 2003, 2004, 2005 }) - }, false, 1018344); - - public static readonly CustomHuePicker LeatherDyeTub = new CustomHuePicker(new[] - { - /* Dull Copper */ - new CustomHueGroup(1018332, new[] { 2419, 2420, 2421, 2422, 2423, 2424 }), - /* Shadow Iron */ - new CustomHueGroup(1018333, new[] { 2406, 2407, 2408, 2409, 2410, 2411, 2412 }), - /* Copper */ - new CustomHueGroup(1018334, new[] { 2413, 2414, 2415, 2416, 2417, 2418 }), - /* Bronze */ - new CustomHueGroup(1018335, new[] { 2414, 2415, 2416, 2417, 2418 }), - /* Glden */ - new CustomHueGroup(1018336, new[] { 2213, 2214, 2215, 2216, 2217, 2218 }), - /* Agapite */ - new CustomHueGroup(1018337, new[] { 2425, 2426, 2427, 2428, 2429, 2430 }), - /* Verite */ - new CustomHueGroup(1018338, new[] { 2207, 2208, 2209, 2210, 2211, 2212 }), - /* Valorite */ - new CustomHueGroup(1018339, new[] { 2219, 2220, 2221, 2222, 2223, 2224 }), - /* Reds */ - new CustomHueGroup(1018340, new[] { 2113, 2114, 2115, 2116, 2117, 2118 }), - /* Blues */ - new CustomHueGroup(1018341, new[] { 2119, 2120, 2121, 2122, 2123, 2124 }), - /* Greens */ - new CustomHueGroup(1018342, new[] { 2126, 2127, 2128, 2129, 2130 }), - /* Yellows */ - new CustomHueGroup(1018343, new[] { 2213, 2214, 2215, 2216, 2217, 2218 }) - }, true); - - public CustomHuePicker(CustomHueGroup[] groups, bool defaultSupported) - { - Groups = groups; - DefaultSupported = defaultSupported; - } - - public CustomHuePicker(CustomHueGroup[] groups, bool defaultSupported, int title) - { - Groups = groups; - DefaultSupported = defaultSupported; - Title = title; - } - - public CustomHuePicker(CustomHueGroup[] groups, bool defaultSupported, string title) - { - Groups = groups; - DefaultSupported = defaultSupported; - TitleString = title; - } - - public bool DefaultSupported { get; } - - public CustomHueGroup[] Groups { get; } - - public int Title { get; } - - public string TitleString { get; } - } - - public delegate void CustomHuePickerCallback(Mobile from, T state, int hue); - - public class CustomHuePickerGump : Gump - { - private readonly CustomHuePickerCallback m_Callback; - private readonly CustomHuePicker m_Definition; - private readonly Mobile m_From; - private readonly T m_State; - - public CustomHuePickerGump(Mobile from, CustomHuePicker definition, CustomHuePickerCallback callback, T state) : base(50, 50) - { - m_From = from; - m_Definition = definition; - m_Callback = callback; - m_State = state; - - RenderBackground(); - RenderCategories(); - } - - private int GetRadioID(int group, int index) => index * m_Definition.Groups.Length + group; - - private void RenderBackground() - { - AddPage(0); - - AddBackground(0, 0, 450, 450, 5054); - AddBackground(10, 10, 430, 430, 3000); - - if (m_Definition.TitleString != null) - AddHtml(20, 30, 400, 25, m_Definition.TitleString); - else if (m_Definition.Title > 0) - AddHtmlLocalized(20, 30, 400, 25, m_Definition.Title); - - AddButton(20, 400, 4005, 4007, 1); - AddHtmlLocalized(55, 400, 200, 25, 1011036); // OKAY - - if (m_Definition.DefaultSupported) - { - AddButton(200, 400, 4005, 4007, 2); - AddLabel(235, 400, 0, "DEFAULT"); - } - } - - private void RenderCategories() - { - CustomHueGroup[] groups = m_Definition.Groups; - - for (int i = 0; i < groups.Length; ++i) - { - AddButton(30, 85 + i * 25, 5224, 5224, 0, GumpButtonType.Page, 1 + i); - - if (groups[i].NameString != null) - AddHtml(55, 85 + i * 25, 200, 25, groups[i].NameString); - else - AddHtmlLocalized(55, 85 + i * 25, 200, 25, groups[i].Name); - } - - for (int i = 0; i < groups.Length; ++i) - { - AddPage(1 + i); - - int[] hues = groups[i].Hues; - - for (int j = 0; j < hues.Length; ++j) + public CustomHueGroup(int name, int[] hues) { - AddRadio(260, 90 + j * 25, 210, 211, false, GetRadioID(i, j)); - AddLabel(278, 90 + j * 25, hues[j] - 1, "*****"); + Name = name; + Hues = hues; } - } + + public CustomHueGroup(string name, int[] hues) + { + NameString = name; + Hues = hues; + } + + public int Name { get; } + + public string NameString { get; } + + public int[] Hues { get; } } - public override void OnResponse(NetState sender, RelayInfo info) + public class CustomHuePicker { - switch (info.ButtonID) - { - case 1: // Okay - { - int[] switches = info.Switches; - - if (switches.Length > 0) + public static readonly CustomHuePicker SpecialDyeTub = new CustomHuePicker( + new[] { - int index = switches[0]; + /* Violet */ + new CustomHueGroup(1018345, new[] { 1230, 1231, 1232, 1233, 1234, 1235 }), + /* Tan */ + new CustomHueGroup(1018346, new[] { 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508 }), + /* Brown */ + new CustomHueGroup(1018347, new[] { 2012, 2013, 2014, 2015, 2016, 2017 }), + /* Dark Blue */ + new CustomHueGroup(1018348, new[] { 1303, 1304, 1305, 1306, 1307, 1308 }), + /* Forest Green */ + new CustomHueGroup(1018349, new[] { 1420, 1421, 1422, 1423, 1424, 1425, 1426 }), + /* Pink */ + new CustomHueGroup(1018350, new[] { 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626 }), + /* Red */ + new CustomHueGroup(1018351, new[] { 1640, 1641, 1642, 1643, 1644 }), + /* Olive */ + new CustomHueGroup(1018352, new[] { 2001, 2002, 2003, 2004, 2005 }) + }, + false, + 1018344 + ); - int group = index % m_Definition.Groups.Length; - index /= m_Definition.Groups.Length; + public static readonly CustomHuePicker LeatherDyeTub = new CustomHuePicker( + new[] + { + /* Dull Copper */ + new CustomHueGroup(1018332, new[] { 2419, 2420, 2421, 2422, 2423, 2424 }), + /* Shadow Iron */ + new CustomHueGroup(1018333, new[] { 2406, 2407, 2408, 2409, 2410, 2411, 2412 }), + /* Copper */ + new CustomHueGroup(1018334, new[] { 2413, 2414, 2415, 2416, 2417, 2418 }), + /* Bronze */ + new CustomHueGroup(1018335, new[] { 2414, 2415, 2416, 2417, 2418 }), + /* Glden */ + new CustomHueGroup(1018336, new[] { 2213, 2214, 2215, 2216, 2217, 2218 }), + /* Agapite */ + new CustomHueGroup(1018337, new[] { 2425, 2426, 2427, 2428, 2429, 2430 }), + /* Verite */ + new CustomHueGroup(1018338, new[] { 2207, 2208, 2209, 2210, 2211, 2212 }), + /* Valorite */ + new CustomHueGroup(1018339, new[] { 2219, 2220, 2221, 2222, 2223, 2224 }), + /* Reds */ + new CustomHueGroup(1018340, new[] { 2113, 2114, 2115, 2116, 2117, 2118 }), + /* Blues */ + new CustomHueGroup(1018341, new[] { 2119, 2120, 2121, 2122, 2123, 2124 }), + /* Greens */ + new CustomHueGroup(1018342, new[] { 2126, 2127, 2128, 2129, 2130 }), + /* Yellows */ + new CustomHueGroup(1018343, new[] { 2213, 2214, 2215, 2216, 2217, 2218 }) + }, + true + ); - if (group >= 0 && group < m_Definition.Groups.Length) - { - int[] hues = m_Definition.Groups[group].Hues; + public CustomHuePicker(CustomHueGroup[] groups, bool defaultSupported) + { + Groups = groups; + DefaultSupported = defaultSupported; + } - if (index >= 0 && index < hues.Length) - m_Callback(m_From, m_State, hues[index]); - } + public CustomHuePicker(CustomHueGroup[] groups, bool defaultSupported, int title) + { + Groups = groups; + DefaultSupported = defaultSupported; + Title = title; + } + + public CustomHuePicker(CustomHueGroup[] groups, bool defaultSupported, string title) + { + Groups = groups; + DefaultSupported = defaultSupported; + TitleString = title; + } + + public bool DefaultSupported { get; } + + public CustomHueGroup[] Groups { get; } + + public int Title { get; } + + public string TitleString { get; } + } + + public delegate void CustomHuePickerCallback(Mobile from, T state, int hue); + + public class CustomHuePickerGump : Gump + { + private readonly CustomHuePickerCallback m_Callback; + private readonly CustomHuePicker m_Definition; + private readonly Mobile m_From; + private readonly T m_State; + + public CustomHuePickerGump( + Mobile from, CustomHuePicker definition, CustomHuePickerCallback callback, T state + ) : base(50, 50) + { + m_From = from; + m_Definition = definition; + m_Callback = callback; + m_State = state; + + RenderBackground(); + RenderCategories(); + } + + private int GetRadioID(int group, int index) => index * m_Definition.Groups.Length + group; + + private void RenderBackground() + { + AddPage(0); + + AddBackground(0, 0, 450, 450, 5054); + AddBackground(10, 10, 430, 430, 3000); + + if (m_Definition.TitleString != null) + AddHtml(20, 30, 400, 25, m_Definition.TitleString); + else if (m_Definition.Title > 0) + AddHtmlLocalized(20, 30, 400, 25, m_Definition.Title); + + AddButton(20, 400, 4005, 4007, 1); + AddHtmlLocalized(55, 400, 200, 25, 1011036); // OKAY + + if (m_Definition.DefaultSupported) + { + AddButton(200, 400, 4005, 4007, 2); + AddLabel(235, 400, 0, "DEFAULT"); + } + } + + private void RenderCategories() + { + var groups = m_Definition.Groups; + + for (var i = 0; i < groups.Length; ++i) + { + AddButton(30, 85 + i * 25, 5224, 5224, 0, GumpButtonType.Page, 1 + i); + + if (groups[i].NameString != null) + AddHtml(55, 85 + i * 25, 200, 25, groups[i].NameString); + else + AddHtmlLocalized(55, 85 + i * 25, 200, 25, groups[i].Name); } - break; - } - case 2: // Default - { - if (m_Definition.DefaultSupported) - m_Callback(m_From, m_State, 0); + for (var i = 0; i < groups.Length; ++i) + { + AddPage(1 + i); - break; - } - } + var hues = groups[i].Hues; + + for (var j = 0; j < hues.Length; ++j) + { + AddRadio(260, 90 + j * 25, 210, 211, false, GetRadioID(i, j)); + AddLabel(278, 90 + j * 25, hues[j] - 1, "*****"); + } + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + switch (info.ButtonID) + { + case 1: // Okay + { + var switches = info.Switches; + + if (switches.Length > 0) + { + var index = switches[0]; + + var group = index % m_Definition.Groups.Length; + index /= m_Definition.Groups.Length; + + if (group >= 0 && group < m_Definition.Groups.Length) + { + var hues = m_Definition.Groups[group].Hues; + + if (index >= 0 && index < hues.Length) + m_Callback(m_From, m_State, hues[index]); + } + } + + break; + } + case 2: // Default + { + if (m_Definition.DefaultSupported) + m_Callback(m_From, m_State, 0); + + break; + } + } + } } - } } diff --git a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/DyeTub.cs b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/DyeTub.cs index 3f2526411..18db1f49a 100644 --- a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/DyeTub.cs +++ b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/DyeTub.cs @@ -6,250 +6,251 @@ using Server.Targeting; namespace Server.Items { - public interface IDyable - { - bool Dye(Mobile from, DyeTub sender); - } - - public class DyeTub : Item, ISecurable - { - private int m_DyedHue; - private bool m_Redyable; - - [Constructible] - public DyeTub() : base(0xFAB) + public interface IDyable { - Weight = 10.0; - m_Redyable = true; + bool Dye(Mobile from, DyeTub sender); } - public DyeTub(Serial serial) : base(serial) + public class DyeTub : Item, ISecurable { - } + private int m_DyedHue; + private bool m_Redyable; - public virtual CustomHuePicker CustomHuePicker => null; - - public virtual bool AllowRunebooks => false; - - public virtual bool AllowFurniture => false; - - public virtual bool AllowStatuettes => false; - - public virtual bool AllowLeather => false; - - public virtual bool AllowDyables => true; - - [CommandProperty(AccessLevel.GameMaster)] - public virtual bool Redyable - { - get => m_Redyable; - set => m_Redyable = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int DyedHue - { - get => m_DyedHue; - set - { - if (m_Redyable) + [Constructible] + public DyeTub() : base(0xFAB) { - m_DyedHue = value; - Hue = value; + Weight = 10.0; + m_Redyable = true; } - } - } - // Three metallic tubs now. - public virtual bool MetallicHues => false; - - // Select the clothing to dye. - public virtual int TargetMessage => 500859; - - // You can not dye that. - public virtual int FailMessage => 1042083; - - [CommandProperty(AccessLevel.GameMaster)] - public SecureLevel Level { get; set; } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write((int)Level); - writer.Write(m_Redyable); - writer.Write(m_DyedHue); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - Level = (SecureLevel)reader.ReadInt(); - goto case 0; - } - case 0: - { - m_Redyable = reader.ReadBool(); - m_DyedHue = reader.ReadInt(); - - break; - } - } - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - SetSecureLevelEntry.AddTo(from, this, list); - } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(GetWorldLocation(), 1)) - { - from.SendLocalizedMessage(TargetMessage); - from.Target = new InternalTarget(this); - } - else - { - from.SendLocalizedMessage(500446); // That is too far away. - } - } - - private class InternalTarget : Target - { - private readonly DyeTub m_Tub; - - public InternalTarget(DyeTub tub) : base(1, false, TargetFlags.None) => m_Tub = tub; - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is Item item) + public DyeTub(Serial serial) : base(serial) { - if (item.QuestItem) - { - from.SendLocalizedMessage(1151836); // You may not dye toggled quest items. - } - else if (item is IDyable dyable && m_Tub.AllowDyables) - { - if (!from.InRange(m_Tub.GetWorldLocation(), 1) || !from.InRange(item.GetWorldLocation(), 1)) - from.SendLocalizedMessage(500446); // That is too far away. - else if (item.Parent is Mobile) - from.SendLocalizedMessage(500861); // Can't Dye clothing that is being worn. - else if (dyable.Dye(from, m_Tub)) - from.PlaySound(0x23E); - } - else if ((FurnitureAttribute.Check(item) || item is PotionKeg) && m_Tub.AllowFurniture) - { - if (!from.InRange(m_Tub.GetWorldLocation(), 1) || !from.InRange(item.GetWorldLocation(), 1)) + } + + public virtual CustomHuePicker CustomHuePicker => null; + + public virtual bool AllowRunebooks => false; + + public virtual bool AllowFurniture => false; + + public virtual bool AllowStatuettes => false; + + public virtual bool AllowLeather => false; + + public virtual bool AllowDyables => true; + + [CommandProperty(AccessLevel.GameMaster)] + public virtual bool Redyable + { + get => m_Redyable; + set => m_Redyable = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int DyedHue + { + get => m_DyedHue; + set { - from.SendLocalizedMessage(500446); // That is too far away. + if (m_Redyable) + { + m_DyedHue = value; + Hue = value; + } + } + } + + // Three metallic tubs now. + public virtual bool MetallicHues => false; + + // Select the clothing to dye. + public virtual int TargetMessage => 500859; + + // You can not dye that. + public virtual int FailMessage => 1042083; + + [CommandProperty(AccessLevel.GameMaster)] + public SecureLevel Level { get; set; } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write((int)Level); + writer.Write(m_Redyable); + writer.Write(m_DyedHue); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + Level = (SecureLevel)reader.ReadInt(); + goto case 0; + } + case 0: + { + m_Redyable = reader.ReadBool(); + m_DyedHue = reader.ReadInt(); + + break; + } + } + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + SetSecureLevelEntry.AddTo(from, this, list); + } + + public override void OnDoubleClick(Mobile from) + { + if (from.InRange(GetWorldLocation(), 1)) + { + from.SendLocalizedMessage(TargetMessage); + from.Target = new InternalTarget(this); } else { - bool okay = item.IsChildOf(from.Backpack); + from.SendLocalizedMessage(500446); // That is too far away. + } + } - if (!okay) - { - if (item.Parent == null) + private class InternalTarget : Target + { + private readonly DyeTub m_Tub; + + public InternalTarget(DyeTub tub) : base(1, false, TargetFlags.None) => m_Tub = tub; + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted is Item item) { - BaseHouse house = BaseHouse.FindHouseAt(item); + if (item.QuestItem) + { + from.SendLocalizedMessage(1151836); // You may not dye toggled quest items. + } + else if (item is IDyable dyable && m_Tub.AllowDyables) + { + if (!from.InRange(m_Tub.GetWorldLocation(), 1) || !from.InRange(item.GetWorldLocation(), 1)) + from.SendLocalizedMessage(500446); // That is too far away. + else if (item.Parent is Mobile) + from.SendLocalizedMessage(500861); // Can't Dye clothing that is being worn. + else if (dyable.Dye(from, m_Tub)) + from.PlaySound(0x23E); + } + else if ((FurnitureAttribute.Check(item) || item is PotionKeg) && m_Tub.AllowFurniture) + { + if (!from.InRange(m_Tub.GetWorldLocation(), 1) || !from.InRange(item.GetWorldLocation(), 1)) + { + from.SendLocalizedMessage(500446); // That is too far away. + } + else + { + var okay = item.IsChildOf(from.Backpack); - if (house == null || (!house.HasLockedDownItem(item) && !house.HasSecureItem(item))) - from.SendLocalizedMessage(501022); // Furniture must be locked down to paint it. - else if (!house.IsCoOwner(from)) - from.SendLocalizedMessage(501023); // You must be the owner to use this item. - else - okay = true; + if (!okay) + { + if (item.Parent == null) + { + var house = BaseHouse.FindHouseAt(item); + + if (house == null || !house.HasLockedDownItem(item) && !house.HasSecureItem(item)) + from.SendLocalizedMessage(501022); // Furniture must be locked down to paint it. + else if (!house.IsCoOwner(from)) + from.SendLocalizedMessage(501023); // You must be the owner to use this item. + else + okay = true; + } + else + { + from.SendLocalizedMessage( + 1048135 + ); // The furniture must be in your backpack to be painted. + } + } + + if (okay) + { + item.Hue = m_Tub.DyedHue; + from.PlaySound(0x23E); + } + } + } + else if ((item is Runebook || item is RecallRune) && m_Tub.AllowRunebooks) + { + if (!from.InRange(m_Tub.GetWorldLocation(), 1) || !from.InRange(item.GetWorldLocation(), 1)) + { + from.SendLocalizedMessage(500446); // That is too far away. + } + else if (!item.Movable) + { + from.SendLocalizedMessage(1049776); // You cannot dye runes or runebooks that are locked down. + } + else + { + item.Hue = m_Tub.DyedHue; + from.PlaySound(0x23E); + } + } + else if (item is MonsterStatuette && m_Tub.AllowStatuettes) + { + if (!from.InRange(m_Tub.GetWorldLocation(), 1) || !from.InRange(item.GetWorldLocation(), 1)) + { + from.SendLocalizedMessage(500446); // That is too far away. + } + else if (!item.Movable) + { + from.SendLocalizedMessage(1049779); // You cannot dye statuettes that are locked down. + } + else + { + item.Hue = m_Tub.DyedHue; + from.PlaySound(0x23E); + } + } + else if ((item is BaseArmor armor && + (armor.MaterialType == ArmorMaterialType.Leather || + armor.MaterialType == ArmorMaterialType.Studded) || item is ElvenBoots || + item is WoodlandBelt) && m_Tub.AllowLeather) + { + if (!from.InRange(m_Tub.GetWorldLocation(), 1) || !from.InRange(item.GetWorldLocation(), 1)) + { + from.SendLocalizedMessage(500446); // That is too far away. + } + else if (!item.Movable) + { + from.SendLocalizedMessage(1042419); // You may not dye leather items which are locked down. + } + else if (item.Parent is Mobile) + { + from.SendLocalizedMessage(500861); // Can't Dye clothing that is being worn. + } + else + { + item.Hue = m_Tub.DyedHue; + from.PlaySound(0x23E); + } + } + else + { + from.SendLocalizedMessage(m_Tub.FailMessage); + } } else { - from.SendLocalizedMessage( - 1048135); // The furniture must be in your backpack to be painted. + from.SendLocalizedMessage(m_Tub.FailMessage); } - } - - if (okay) - { - item.Hue = m_Tub.DyedHue; - from.PlaySound(0x23E); - } } - } - else if ((item is Runebook || item is RecallRune) && m_Tub.AllowRunebooks) - { - if (!from.InRange(m_Tub.GetWorldLocation(), 1) || !from.InRange(item.GetWorldLocation(), 1)) - { - from.SendLocalizedMessage(500446); // That is too far away. - } - else if (!item.Movable) - { - from.SendLocalizedMessage(1049776); // You cannot dye runes or runebooks that are locked down. - } - else - { - item.Hue = m_Tub.DyedHue; - from.PlaySound(0x23E); - } - } - else if (item is MonsterStatuette && m_Tub.AllowStatuettes) - { - if (!from.InRange(m_Tub.GetWorldLocation(), 1) || !from.InRange(item.GetWorldLocation(), 1)) - { - from.SendLocalizedMessage(500446); // That is too far away. - } - else if (!item.Movable) - { - from.SendLocalizedMessage(1049779); // You cannot dye statuettes that are locked down. - } - else - { - item.Hue = m_Tub.DyedHue; - from.PlaySound(0x23E); - } - } - else if (((item is BaseArmor armor && - (armor.MaterialType == ArmorMaterialType.Leather || - armor.MaterialType == ArmorMaterialType.Studded)) || item is ElvenBoots || - item is WoodlandBelt) && m_Tub.AllowLeather) - { - if (!from.InRange(m_Tub.GetWorldLocation(), 1) || !from.InRange(item.GetWorldLocation(), 1)) - { - from.SendLocalizedMessage(500446); // That is too far away. - } - else if (!item.Movable) - { - from.SendLocalizedMessage(1042419); // You may not dye leather items which are locked down. - } - else if (item.Parent is Mobile) - { - from.SendLocalizedMessage(500861); // Can't Dye clothing that is being worn. - } - else - { - item.Hue = m_Tub.DyedHue; - from.PlaySound(0x23E); - } - } - else - { - from.SendLocalizedMessage(m_Tub.FailMessage); - } } - else - { - from.SendLocalizedMessage(m_Tub.FailMessage); - } - } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/FurnitureDyeTub.cs b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/FurnitureDyeTub.cs index ead7e137b..7b6188790 100644 --- a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/FurnitureDyeTub.cs +++ b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/FurnitureDyeTub.cs @@ -2,66 +2,66 @@ using Server.Engines.VeteranRewards; namespace Server.Items { - public class FurnitureDyeTub : DyeTub, IRewardItem - { - [Constructible] - public FurnitureDyeTub() => LootType = LootType.Blessed; - - public FurnitureDyeTub(Serial serial) : base(serial) + public class FurnitureDyeTub : DyeTub, IRewardItem { + [Constructible] + public FurnitureDyeTub() => LootType = LootType.Blessed; + + public FurnitureDyeTub(Serial serial) : base(serial) + { + } + + public override bool AllowDyables => false; + public override bool AllowFurniture => true; + public override int TargetMessage => 501019; // Select the furniture to dye. + public override int FailMessage => 501021; // That is not a piece of furniture. + public override int LabelNumber => 1041246; // Furniture Dye Tub + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem { get; set; } + + public override void OnDoubleClick(Mobile from) + { + if (IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) + return; + + base.OnDoubleClick(from); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (Core.ML && IsRewardItem) + list.Add(1076217); // 1st Year Veteran Reward + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + IsRewardItem = reader.ReadBool(); + break; + } + } + + if (LootType == LootType.Regular) + LootType = LootType.Blessed; + } } - - public override bool AllowDyables => false; - public override bool AllowFurniture => true; - public override int TargetMessage => 501019; // Select the furniture to dye. - public override int FailMessage => 501021; // That is not a piece of furniture. - public override int LabelNumber => 1041246; // Furniture Dye Tub - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem { get; set; } - - public override void OnDoubleClick(Mobile from) - { - if (IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) - return; - - base.OnDoubleClick(from); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Core.ML && IsRewardItem) - list.Add(1076217); // 1st Year Veteran Reward - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - IsRewardItem = reader.ReadBool(); - break; - } - } - - if (LootType == LootType.Regular) - LootType = LootType.Blessed; - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/LeatherDyeTub.cs b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/LeatherDyeTub.cs index a5c9f78e9..3d7f7b724 100644 --- a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/LeatherDyeTub.cs +++ b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/LeatherDyeTub.cs @@ -2,64 +2,64 @@ using Server.Engines.VeteranRewards; namespace Server.Items { - public class LeatherDyeTub : DyeTub, IRewardItem - { - [Constructible] - public LeatherDyeTub() => LootType = LootType.Blessed; - - public LeatherDyeTub(Serial serial) : base(serial) + public class LeatherDyeTub : DyeTub, IRewardItem { + [Constructible] + public LeatherDyeTub() => LootType = LootType.Blessed; + + public LeatherDyeTub(Serial serial) : base(serial) + { + } + + public override bool AllowDyables => false; + public override bool AllowLeather => true; + public override int TargetMessage => 1042416; // Select the leather item to dye. + public override int FailMessage => 1042418; // You can only dye leather with this tub. + public override int LabelNumber => 1041284; // Leather Dye Tub + public override CustomHuePicker CustomHuePicker => CustomHuePicker.LeatherDyeTub; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem { get; set; } + + public override void OnDoubleClick(Mobile from) + { + if (IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) + return; + + base.OnDoubleClick(from); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (Core.ML && IsRewardItem) + list.Add(1076218); // 2nd Year Veteran Reward + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + IsRewardItem = reader.ReadBool(); + break; + } + } + } } - - public override bool AllowDyables => false; - public override bool AllowLeather => true; - public override int TargetMessage => 1042416; // Select the leather item to dye. - public override int FailMessage => 1042418; // You can only dye leather with this tub. - public override int LabelNumber => 1041284; // Leather Dye Tub - public override CustomHuePicker CustomHuePicker => CustomHuePicker.LeatherDyeTub; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem { get; set; } - - public override void OnDoubleClick(Mobile from) - { - if (IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) - return; - - base.OnDoubleClick(from); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Core.ML && IsRewardItem) - list.Add(1076218); // 2nd Year Veteran Reward - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - IsRewardItem = reader.ReadBool(); - break; - } - } - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/MetallicClothDyetub.cs b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/MetallicClothDyetub.cs index ebdf14dd8..1bab8dc79 100644 --- a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/MetallicClothDyetub.cs +++ b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/MetallicClothDyetub.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class MetallicClothDyetub : DyeTub - { - [Constructible] - public MetallicClothDyetub() => LootType = LootType.Blessed; - - public MetallicClothDyetub(Serial serial) - : base(serial) + public class MetallicClothDyetub : DyeTub { + [Constructible] + public MetallicClothDyetub() => LootType = LootType.Blessed; + + public MetallicClothDyetub(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1152920; // Metallic Cloth ... + + public override bool MetallicHues => true; + + 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 int LabelNumber => 1152920; // Metallic Cloth ... - - public override bool MetallicHues => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/MetallicHuePicker.cs b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/MetallicHuePicker.cs index c80bac2a5..ac24e675e 100644 --- a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/MetallicHuePicker.cs +++ b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/MetallicHuePicker.cs @@ -3,75 +3,75 @@ using Server.Network; namespace Server.Items { - public class MetallicHuePicker : Gump - { - private readonly CustomHuePickerCallback m_Callback; - - private readonly Mobile m_From; - private readonly T m_State; - - public MetallicHuePicker(Mobile from, CustomHuePickerCallback callback, T state) - : base(450, 450) + public class MetallicHuePicker : Gump { - m_From = from; - m_Callback = callback; - m_State = state; + private readonly CustomHuePickerCallback m_Callback; - Render(); - } + private readonly Mobile m_From; + private readonly T m_State; - public void Render() - { - AddPage(0); - - AddBackground(0, 0, 450, 450, 0x13BE); - AddBackground(10, 10, 430, 430, 0xBB8); - - AddHtmlLocalized(55, 400, 200, 25, 1011036); // OKAY - - AddButton(20, 400, 4005, 4007, 1); - AddButton(200, 400, 4005, 4007, 2); - AddLabel(235, 400, 0, "DEFAULT"); - - AddHtmlLocalized(55, 25, 200, 25, 1150063); // Base/Shadow Color - AddHtmlLocalized(260, 25, 200, 25, 1150064); // Highlight Color - - for (int row = 0; row < 13; row++) - { - AddButton(30, 65 + row * 25, 0x1467, 0x1468, row + 1, GumpButtonType.Page, row + 1); - AddItem(50, 65 + row * 25, 0x1412, 2501 + row * 12 + (row == 12 ? 6 : 0)); - } - - for (int page = 1; page < 14; page++) - { - AddPage(page); - - for (int row = 0; row < 12; row++) + public MetallicHuePicker(Mobile from, CustomHuePickerCallback callback, T state) + : base(450, 450) { - int hue = 2501 + (page == 13 ? 6 : 0) + row + - 12 * (page - 1); /* OSI just had to skip 6 unused hues, didnt they */ - AddRadio(260, 65 + row * 25, 0xd2, 0xd3, false, hue); - AddItem(280, 65 + row * 25, 0x1412, hue); + m_From = from; + m_Callback = callback; + m_State = state; + + Render(); } - } - } - public override void OnResponse(NetState sender, RelayInfo info) - { - switch (info.ButtonID) - { - case 1: // Okay - { - if (info.Switches.Length > 0) m_Callback(m_From, m_State, info.Switches[0]); - break; - } - case 2: // Default - { - m_Callback(m_From, m_State, 0); + public void Render() + { + AddPage(0); - break; - } - } + AddBackground(0, 0, 450, 450, 0x13BE); + AddBackground(10, 10, 430, 430, 0xBB8); + + AddHtmlLocalized(55, 400, 200, 25, 1011036); // OKAY + + AddButton(20, 400, 4005, 4007, 1); + AddButton(200, 400, 4005, 4007, 2); + AddLabel(235, 400, 0, "DEFAULT"); + + AddHtmlLocalized(55, 25, 200, 25, 1150063); // Base/Shadow Color + AddHtmlLocalized(260, 25, 200, 25, 1150064); // Highlight Color + + for (var row = 0; row < 13; row++) + { + AddButton(30, 65 + row * 25, 0x1467, 0x1468, row + 1, GumpButtonType.Page, row + 1); + AddItem(50, 65 + row * 25, 0x1412, 2501 + row * 12 + (row == 12 ? 6 : 0)); + } + + for (var page = 1; page < 14; page++) + { + AddPage(page); + + for (var row = 0; row < 12; row++) + { + var hue = 2501 + (page == 13 ? 6 : 0) + row + + 12 * (page - 1); /* OSI just had to skip 6 unused hues, didnt they */ + AddRadio(260, 65 + row * 25, 0xd2, 0xd3, false, hue); + AddItem(280, 65 + row * 25, 0x1412, hue); + } + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + switch (info.ButtonID) + { + case 1: // Okay + { + if (info.Switches.Length > 0) m_Callback(m_From, m_State, info.Switches[0]); + break; + } + case 2: // Default + { + m_Callback(m_From, m_State, 0); + + break; + } + } + } } - } } diff --git a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/MetallicLeatherDyeTub.cs b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/MetallicLeatherDyeTub.cs index 1bca13eb3..20e60a0dd 100644 --- a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/MetallicLeatherDyeTub.cs +++ b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/MetallicLeatherDyeTub.cs @@ -1,41 +1,41 @@ namespace Server.Items { - public class MetallicLeatherDyeTub : LeatherDyeTub - { - [Constructible] - public MetallicLeatherDyeTub() => LootType = LootType.Blessed; - - public MetallicLeatherDyeTub(Serial serial) - : base(serial) + public class MetallicLeatherDyeTub : LeatherDyeTub { + [Constructible] + public MetallicLeatherDyeTub() => LootType = LootType.Blessed; + + public MetallicLeatherDyeTub(Serial serial) + : base(serial) + { + } + + public override CustomHuePicker CustomHuePicker => null; + + public override int LabelNumber => 1153495; // Metallic Leather ... + + public override bool MetallicHues => true; + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (Core.ML && IsRewardItem) + list.Add(1076221); // 5th Year Veteran Reward + } + + 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 CustomHuePicker CustomHuePicker => null; - - public override int LabelNumber => 1153495; // Metallic Leather ... - - public override bool MetallicHues => true; - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Core.ML && IsRewardItem) - list.Add(1076221); // 5th Year Veteran Reward - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/RewardBlackDyeTub.cs b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/RewardBlackDyeTub.cs index cffdc9307..92daa61d1 100644 --- a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/RewardBlackDyeTub.cs +++ b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/RewardBlackDyeTub.cs @@ -2,64 +2,64 @@ using Server.Engines.VeteranRewards; namespace Server.Items { - public class RewardBlackDyeTub : DyeTub, IRewardItem - { - [Constructible] - public RewardBlackDyeTub() + public class RewardBlackDyeTub : DyeTub, IRewardItem { - Hue = DyedHue = 0x0001; - Redyable = false; - LootType = LootType.Blessed; + [Constructible] + public RewardBlackDyeTub() + { + Hue = DyedHue = 0x0001; + Redyable = false; + LootType = LootType.Blessed; + } + + public RewardBlackDyeTub(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1006008; // Black Dye Tub + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem { get; set; } + + public override void OnDoubleClick(Mobile from) + { + if (IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) + return; + + base.OnDoubleClick(from); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (Core.ML && IsRewardItem) + list.Add(1076217); // 1st Year Veteran Reward + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + IsRewardItem = reader.ReadBool(); + break; + } + } + } } - - public RewardBlackDyeTub(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1006008; // Black Dye Tub - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem { get; set; } - - public override void OnDoubleClick(Mobile from) - { - if (IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) - return; - - base.OnDoubleClick(from); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Core.ML && IsRewardItem) - list.Add(1076217); // 1st Year Veteran Reward - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - IsRewardItem = reader.ReadBool(); - break; - } - } - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/RunebookDyeTub.cs b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/RunebookDyeTub.cs index 7f0e5bf9a..590d39904 100644 --- a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/RunebookDyeTub.cs +++ b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/RunebookDyeTub.cs @@ -2,64 +2,64 @@ using Server.Engines.VeteranRewards; namespace Server.Items { - public class RunebookDyeTub : DyeTub, IRewardItem - { - [Constructible] - public RunebookDyeTub() => LootType = LootType.Blessed; - - public RunebookDyeTub(Serial serial) : base(serial) + public class RunebookDyeTub : DyeTub, IRewardItem { + [Constructible] + public RunebookDyeTub() => LootType = LootType.Blessed; + + public RunebookDyeTub(Serial serial) : base(serial) + { + } + + public override bool AllowDyables => false; + public override bool AllowRunebooks => true; + public override int TargetMessage => 1049774; // Target the runebook or runestone to dye + public override int FailMessage => 1049775; // You can only dye runestones or runebooks with this tub. + public override int LabelNumber => 1049740; // Runebook Dye Tub + public override CustomHuePicker CustomHuePicker => CustomHuePicker.LeatherDyeTub; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem { get; set; } + + public override void OnDoubleClick(Mobile from) + { + if (IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) + return; + + base.OnDoubleClick(from); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (Core.ML && IsRewardItem) + list.Add(1076220); // 4th Year Veteran Reward + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + IsRewardItem = reader.ReadBool(); + break; + } + } + } } - - public override bool AllowDyables => false; - public override bool AllowRunebooks => true; - public override int TargetMessage => 1049774; // Target the runebook or runestone to dye - public override int FailMessage => 1049775; // You can only dye runestones or runebooks with this tub. - public override int LabelNumber => 1049740; // Runebook Dye Tub - public override CustomHuePicker CustomHuePicker => CustomHuePicker.LeatherDyeTub; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem { get; set; } - - public override void OnDoubleClick(Mobile from) - { - if (IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) - return; - - base.OnDoubleClick(from); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Core.ML && IsRewardItem) - list.Add(1076220); // 4th Year Veteran Reward - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - IsRewardItem = reader.ReadBool(); - break; - } - } - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/SpecialDyeTub.cs b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/SpecialDyeTub.cs index 790b8070c..cb4187105 100644 --- a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/SpecialDyeTub.cs +++ b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/SpecialDyeTub.cs @@ -2,60 +2,60 @@ using Server.Engines.VeteranRewards; namespace Server.Items { - public class SpecialDyeTub : DyeTub, IRewardItem - { - [Constructible] - public SpecialDyeTub() => LootType = LootType.Blessed; - - public SpecialDyeTub(Serial serial) : base(serial) + public class SpecialDyeTub : DyeTub, IRewardItem { + [Constructible] + public SpecialDyeTub() => LootType = LootType.Blessed; + + public SpecialDyeTub(Serial serial) : base(serial) + { + } + + public override CustomHuePicker CustomHuePicker => CustomHuePicker.SpecialDyeTub; + public override int LabelNumber => 1041285; // Special Dye Tub + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem { get; set; } + + public override void OnDoubleClick(Mobile from) + { + if (IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) + return; + + base.OnDoubleClick(from); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (Core.ML && IsRewardItem) + list.Add(1076217); // 1st Year Veteran Reward + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + IsRewardItem = reader.ReadBool(); + break; + } + } + } } - - public override CustomHuePicker CustomHuePicker => CustomHuePicker.SpecialDyeTub; - public override int LabelNumber => 1041285; // Special Dye Tub - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem { get; set; } - - public override void OnDoubleClick(Mobile from) - { - if (IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) - return; - - base.OnDoubleClick(from); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Core.ML && IsRewardItem) - list.Add(1076217); // 1st Year Veteran Reward - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - IsRewardItem = reader.ReadBool(); - break; - } - } - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/StatuetteDyeTub.cs b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/StatuetteDyeTub.cs index 1105b625e..8b7b6ff15 100644 --- a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/StatuetteDyeTub.cs +++ b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/StatuetteDyeTub.cs @@ -2,64 +2,64 @@ using Server.Engines.VeteranRewards; namespace Server.Items { - public class StatuetteDyeTub : DyeTub, IRewardItem - { - [Constructible] - public StatuetteDyeTub() => LootType = LootType.Blessed; - - public StatuetteDyeTub(Serial serial) : base(serial) + public class StatuetteDyeTub : DyeTub, IRewardItem { + [Constructible] + public StatuetteDyeTub() => LootType = LootType.Blessed; + + public StatuetteDyeTub(Serial serial) : base(serial) + { + } + + public override bool AllowDyables => false; + public override bool AllowStatuettes => true; + public override int TargetMessage => 1049777; // Target the statuette to dye + public override int FailMessage => 1049778; // You can only dye veteran reward statuettes with this tub. + public override int LabelNumber => 1049741; // Reward Statuette Dye Tub + public override CustomHuePicker CustomHuePicker => CustomHuePicker.LeatherDyeTub; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem { get; set; } + + public override void OnDoubleClick(Mobile from) + { + if (IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) + return; + + base.OnDoubleClick(from); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (Core.ML && IsRewardItem) + list.Add(1076221); // 5th Year Veteran Reward + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + IsRewardItem = reader.ReadBool(); + break; + } + } + } } - - public override bool AllowDyables => false; - public override bool AllowStatuettes => true; - public override int TargetMessage => 1049777; // Target the statuette to dye - public override int FailMessage => 1049778; // You can only dye veteran reward statuettes with this tub. - public override int LabelNumber => 1049741; // Reward Statuette Dye Tub - public override CustomHuePicker CustomHuePicker => CustomHuePicker.LeatherDyeTub; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem { get; set; } - - public override void OnDoubleClick(Mobile from) - { - if (IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) - return; - - base.OnDoubleClick(from); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Core.ML && IsRewardItem) - list.Add(1076221); // 5th Year Veteran Reward - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - IsRewardItem = reader.ReadBool(); - break; - } - } - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/WhiteClothDyeTub.cs b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/WhiteClothDyeTub.cs index d704f817e..401d431c8 100644 --- a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/WhiteClothDyeTub.cs +++ b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/WhiteClothDyeTub.cs @@ -1,31 +1,31 @@ namespace Server.Items /* High seas, loot from merchant ship's hold, also a "uncommon" loot item */ { - public class WhiteClothDyeTub : DyeTub - { - [Constructible] - public WhiteClothDyeTub() => DyedHue = Hue = 0x9C2; - - public WhiteClothDyeTub(Serial serial) - : base(serial) + public class WhiteClothDyeTub : DyeTub { + [Constructible] + public WhiteClothDyeTub() => DyedHue = Hue = 0x9C2; + + public WhiteClothDyeTub(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1149984; // White Cloth Dye Tub + + public override bool Redyable => 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 int LabelNumber => 1149984; // White Cloth Dye Tub - - public override bool Redyable => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/WhiteLeatherDyeTub.cs b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/WhiteLeatherDyeTub.cs index 5861a0a20..992da9822 100644 --- a/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/WhiteLeatherDyeTub.cs +++ b/Projects/UOContent/Items/Skill Items/Tailor Items/Dyetubs/WhiteLeatherDyeTub.cs @@ -1,35 +1,35 @@ namespace Server.Items { - public class WhiteLeatherDyeTub : LeatherDyeTub /* OSI UO 13th anniv gift, from redeemable gift tickets */ - { - [Constructible] - public WhiteLeatherDyeTub() + public class WhiteLeatherDyeTub : LeatherDyeTub /* OSI UO 13th anniv gift, from redeemable gift tickets */ { - DyedHue = Hue = 0x9C2; - LootType = LootType.Blessed; + [Constructible] + public WhiteLeatherDyeTub() + { + DyedHue = Hue = 0x9C2; + LootType = LootType.Blessed; + } + + public WhiteLeatherDyeTub(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1149900; // White Leather Dye Tub + + public override bool Redyable => false; + + 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(); + } } - - public WhiteLeatherDyeTub(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1149900; // White Leather Dye Tub - - public override bool Redyable => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tailor Items/Misc/Dressform.cs b/Projects/UOContent/Items/Skill Items/Tailor Items/Misc/Dressform.cs index 62626440b..91e7b1a71 100644 --- a/Projects/UOContent/Items/Skill Items/Tailor Items/Misc/Dressform.cs +++ b/Projects/UOContent/Items/Skill Items/Tailor Items/Misc/Dressform.cs @@ -1,27 +1,27 @@ namespace Server.Items { - [Flippable(0xec6, 0xec7)] - public class Dressform : Item - { - [Constructible] - public Dressform() : base(0xec6) => Weight = 10; - - public Dressform(Serial serial) : base(serial) + [Flippable(0xec6, 0xec7)] + public class Dressform : Item { + [Constructible] + public Dressform() : base(0xec6) => Weight = 10; + + public Dressform(Serial serial) : base(serial) + { + } + + 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(); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tailor Items/Misc/Dyes.cs b/Projects/UOContent/Items/Skill Items/Tailor Items/Misc/Dyes.cs index 8ccfc6666..f5054ffb6 100644 --- a/Projects/UOContent/Items/Skill Items/Tailor Items/Misc/Dyes.cs +++ b/Projects/UOContent/Items/Skill Items/Tailor Items/Misc/Dyes.cs @@ -3,101 +3,101 @@ using Server.Targeting; namespace Server.Items { - public class Dyes : Item /* , IUsesRemaining */ /* TODO complete usesremaing */ - { - /* - public bool ShowUsesRemaining { get { return false; } set { } } - - [CommandProperty( AccessLevel.GameMaster )] - public virtual int UsesRemaining { get { return m_UsesRemaining; } set { m_UsesRemaining = value; } } - - private int m_UsesRemaining; - */ - - [Constructible] - public Dyes() : base(0xFA9) => Weight = 3.0; - - public Dyes(Serial serial) : base(serial) + public class Dyes : Item /* , IUsesRemaining */ /* TODO complete usesremaing */ { - } + /* + public bool ShowUsesRemaining { get { return false; } set { } } + + [CommandProperty( AccessLevel.GameMaster )] + public virtual int UsesRemaining { get { return m_UsesRemaining; } set { m_UsesRemaining = value; } } + + private int m_UsesRemaining; + */ - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + [Constructible] + public Dyes() : base(0xFA9) => Weight = 3.0; - writer.Write(1); // version - - /* writer.Write( ( int )m_UsesRemaining ); */ - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 0.0) - Weight = 3.0; - - /* m_UsesRemaining = ( version == 0 ) ? 25 : reader.ReadInt(); */ - } - - public override void OnDoubleClick(Mobile from) - { - from.SendLocalizedMessage(500856); // Select the dye tub to use the dyes on. - from.Target = new InternalTarget(); - } - - private class InternalTarget : Target - { - public InternalTarget() : base(1, false, TargetFlags.None) - { - } - - public virtual void SetTubHue(Mobile from, DyeTub tub, int hue) - { - tub.DyedHue = hue; - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is DyeTub tub) + public Dyes(Serial serial) : base(serial) { - if (tub.Redyable) - { - if (tub.MetallicHues) /* OSI has three metallic tubs now */ - from.SendGump(new MetallicHuePicker(from, SetTubHue, tub)); - else if (tub.CustomHuePicker != null) - from.SendGump(new CustomHuePickerGump(from, tub.CustomHuePicker, SetTubHue, tub)); - else - from.SendHuePicker(new InternalPicker(tub)); - } - else if (tub is BlackDyeTub) - { - from.SendLocalizedMessage(1010092); // You can not use this on a black dye tub. - } - else - { - from.SendMessage("That dye tub may not be redyed."); - } } - else + + public override void Serialize(IGenericWriter writer) { - from.SendLocalizedMessage(500857); // Use this on a dye tub. + base.Serialize(writer); + + writer.Write(1); // version + + /* writer.Write( ( int )m_UsesRemaining ); */ } - } - private class InternalPicker : HuePicker - { - private readonly DyeTub m_Tub; - - public InternalPicker(DyeTub tub) : base(tub.ItemID) => m_Tub = tub; - - public override void OnResponse(int hue) + public override void Deserialize(IGenericReader reader) { - m_Tub.DyedHue = hue; + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (Weight == 0.0) + Weight = 3.0; + + /* m_UsesRemaining = ( version == 0 ) ? 25 : reader.ReadInt(); */ + } + + public override void OnDoubleClick(Mobile from) + { + from.SendLocalizedMessage(500856); // Select the dye tub to use the dyes on. + from.Target = new InternalTarget(); + } + + private class InternalTarget : Target + { + public InternalTarget() : base(1, false, TargetFlags.None) + { + } + + public virtual void SetTubHue(Mobile from, DyeTub tub, int hue) + { + tub.DyedHue = hue; + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted is DyeTub tub) + { + if (tub.Redyable) + { + if (tub.MetallicHues) /* OSI has three metallic tubs now */ + from.SendGump(new MetallicHuePicker(from, SetTubHue, tub)); + else if (tub.CustomHuePicker != null) + from.SendGump(new CustomHuePickerGump(from, tub.CustomHuePicker, SetTubHue, tub)); + else + from.SendHuePicker(new InternalPicker(tub)); + } + else if (tub is BlackDyeTub) + { + from.SendLocalizedMessage(1010092); // You can not use this on a black dye tub. + } + else + { + from.SendMessage("That dye tub may not be redyed."); + } + } + else + { + from.SendLocalizedMessage(500857); // Use this on a dye tub. + } + } + + private class InternalPicker : HuePicker + { + private readonly DyeTub m_Tub; + + public InternalPicker(DyeTub tub) : base(tub.ItemID) => m_Tub = tub; + + public override void OnResponse(int hue) + { + m_Tub.DyedHue = hue; + } + } } - } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tailor Items/Misc/Scissors.cs b/Projects/UOContent/Items/Skill Items/Tailor Items/Misc/Scissors.cs index 91cbc6e78..540d6e226 100644 --- a/Projects/UOContent/Items/Skill Items/Tailor Items/Misc/Scissors.cs +++ b/Projects/UOContent/Items/Skill Items/Tailor Items/Misc/Scissors.cs @@ -2,112 +2,114 @@ using Server.Targeting; namespace Server.Items { - public interface IScissorable - { - bool Scissor(Mobile from, Scissors scissors); - } - - [Flippable(0xf9f, 0xf9e)] - public class Scissors : Item - { - [Constructible] - public Scissors() : base(0xF9F) => Weight = 1.0; - - public Scissors(Serial serial) : base(serial) + public interface IScissorable { + bool Scissor(Mobile from, Scissors scissors); } - public override void Serialize(IGenericWriter writer) + [Flippable(0xf9f, 0xf9e)] + public class Scissors : Item { - base.Serialize(writer); + [Constructible] + public Scissors() : base(0xF9F) => Weight = 1.0; - writer.Write(0); // version + public Scissors(Serial serial) : base(serial) + { + } + + 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(502434); // What should I use these scissors on? + + from.Target = new InternalTarget(this); + } + + public static bool CanScissor(Mobile from, IScissorable obj) + { + if (obj is Item item && item.Nontransferable) + { + from.SendLocalizedMessage(502440); // Scissors can not be used on that to produce anything. + return false; + } + + // TODO: Move other general checks from the different implementations here + + return true; + } + + private class InternalTarget : Target + { + private readonly Scissors m_Item; + + public InternalTarget(Scissors item) : base(2, false, TargetFlags.None) => m_Item = item; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Item.Deleted) + return; + + /*if (targeted is Item && !((Item)targeted).IsStandardLoot()) + { + from.SendLocalizedMessage( 502440 ); // Scissors can not be used on that to produce anything. + } + else */ + if (Core.AOS && targeted == from) + { + from.SendLocalizedMessage( + 1062845 + Utility + .Random(3) + ); // "That doesn't seem like the smartest thing to do." / "That was an encounter you don't wish to repeat." / "Ha! You missed!" + } + else if (Core.SE && Utility.RandomDouble() > .20 && (from.Direction & Direction.Running) != 0 && + Core.TickCount - from.LastMoveTime < from.ComputeMovementSpeed(from.Direction)) + { + from.SendLocalizedMessage( + 1063305 + ); // Didn't your parents ever tell you not to run with scissors in your hand?! + } + else if (targeted is Item item && !item.Movable) + { + if (item is IScissorable obj && (obj is PlagueBeastInnard || obj is PlagueBeastMutationCore)) + if (CanScissor(from, obj) && obj.Scissor(from, m_Item)) + from.PlaySound(0x248); + } + else if (targeted is IScissorable obj) + { + if (CanScissor(from, obj) && obj.Scissor(from, m_Item)) + from.PlaySound(0x248); + } + else + { + from.SendLocalizedMessage(502440); // Scissors can not be used on that to produce anything. + } + } + + protected override void OnNonlocalTarget(Mobile from, object targeted) + { + if (targeted is IScissorable obj && (obj is PlagueBeastInnard || obj is PlagueBeastMutationCore)) + { + if (CanScissor(from, obj) && obj.Scissor(from, m_Item)) + from.PlaySound(0x248); + } + else + { + base.OnNonlocalTarget(from, targeted); + } + } + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - from.SendLocalizedMessage(502434); // What should I use these scissors on? - - from.Target = new InternalTarget(this); - } - - public static bool CanScissor(Mobile from, IScissorable obj) - { - if (obj is Item item && item.Nontransferable) - { - from.SendLocalizedMessage(502440); // Scissors can not be used on that to produce anything. - return false; - } - - // TODO: Move other general checks from the different implementations here - - return true; - } - - private class InternalTarget : Target - { - private readonly Scissors m_Item; - - public InternalTarget(Scissors item) : base(2, false, TargetFlags.None) => m_Item = item; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Item.Deleted) - return; - - /*if (targeted is Item && !((Item)targeted).IsStandardLoot()) - { - from.SendLocalizedMessage( 502440 ); // Scissors can not be used on that to produce anything. - } - else */ - if (Core.AOS && targeted == from) - { - from.SendLocalizedMessage( - 1062845 + Utility - .Random(3)); // "That doesn't seem like the smartest thing to do." / "That was an encounter you don't wish to repeat." / "Ha! You missed!" - } - else if (Core.SE && Utility.RandomDouble() > .20 && (from.Direction & Direction.Running) != 0 && - Core.TickCount - from.LastMoveTime < from.ComputeMovementSpeed(from.Direction)) - { - from.SendLocalizedMessage( - 1063305); // Didn't your parents ever tell you not to run with scissors in your hand?! - } - else if (targeted is Item item && !item.Movable) - { - if (item is IScissorable obj && (obj is PlagueBeastInnard || obj is PlagueBeastMutationCore)) - if (CanScissor(from, obj) && obj.Scissor(from, m_Item)) - from.PlaySound(0x248); - } - else if (targeted is IScissorable obj) - { - if (CanScissor(from, obj) && obj.Scissor(from, m_Item)) - from.PlaySound(0x248); - } - else - { - from.SendLocalizedMessage(502440); // Scissors can not be used on that to produce anything. - } - } - - protected override void OnNonlocalTarget(Mobile from, object targeted) - { - if (targeted is IScissorable obj && (obj is PlagueBeastInnard || obj is PlagueBeastMutationCore)) - { - if (CanScissor(from, obj) && obj.Scissor(from, m_Item)) - from.PlaySound(0x248); - } - else - { - base.OnNonlocalTarget(from, targeted); - } - } - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Thief/DisguiseKit.cs b/Projects/UOContent/Items/Skill Items/Thief/DisguiseKit.cs index d503a5c01..376d4f6cc 100644 --- a/Projects/UOContent/Items/Skill Items/Thief/DisguiseKit.cs +++ b/Projects/UOContent/Items/Skill Items/Thief/DisguiseKit.cs @@ -11,306 +11,307 @@ using Server.Spells.Seventh; namespace Server.Items { - public class DisguiseKit : Item - { - [Constructible] - public DisguiseKit() : base(0xE05) => Weight = 1.0; - - public DisguiseKit(Serial serial) : base(serial) + public class DisguiseKit : Item { - } + [Constructible] + public DisguiseKit() : base(0xE05) => Weight = 1.0; - public override int LabelNumber => 1041078; // a disguise kit - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public bool ValidateUse(Mobile from) - { - PlayerMobile pm = from as PlayerMobile; - - if (!IsChildOf(from.Backpack)) - from.SendLocalizedMessage(1042001); - else if (pm == null || pm.NpcGuild != NpcGuild.ThievesGuild) - from.SendLocalizedMessage(501702); - else if (Stealing.SuspendOnMurder && pm.Kills > 0) - from.SendLocalizedMessage(501703); - else if (!from.CanBeginAction()) - from.SendLocalizedMessage(501704); - else if (Sigil.ExistsOn(from)) - from.SendLocalizedMessage(1010465); // You cannot disguise yourself while holding a sigil - else if (TransformationSpellHelper.UnderTransformation(from)) - from.SendLocalizedMessage(1061634); - else if (from.BodyMod == 183 || from.BodyMod == 184) - from.SendLocalizedMessage(1040002); - else if (!from.CanBeginAction() || from.IsBodyMod) - from.SendLocalizedMessage(501705); - else - return true; - - return false; - } - - public override void OnDoubleClick(Mobile from) - { - if (ValidateUse(from)) - from.SendGump(new DisguiseGump(from, this, true, false)); - } - } - - public class DisguiseGump : Gump - { - private static readonly DisguiseEntry[] m_HairEntries = - { - new DisguiseEntry(8251, 50700, 0, 5, 1011052), // Short - new DisguiseEntry(8261, 60710, 0, 3, 1011047), // Pageboy - new DisguiseEntry(8252, 60708, 0, -5, 1011053), // Long - new DisguiseEntry(8264, 60901, 0, 5, 1011048), // Receding - new DisguiseEntry(8253, 60702, 0, -5, 1011054), // Ponytail - new DisguiseEntry(8265, 60707, 0, -5, 1011049), // 2-tails - new DisguiseEntry(8260, 50703, 0, 5, 1011055), // Mohawk - new DisguiseEntry(8266, 60713, 0, 10, 1011050), // Topknot - null, - new DisguiseEntry(0, 0, 0, 0, 1011051) // None - }; - - private static readonly DisguiseEntry[] m_BeardEntries = - { - new DisguiseEntry(8269, 50906, 0, 0, 1011401), // Vandyke - new DisguiseEntry(8257, 50808, 0, -2, 1011062), // Mustache - new DisguiseEntry(8255, 50802, 0, 0, 1011060), // Short beard - new DisguiseEntry(8268, 50905, 0, -10, 1011061), // Long beard - new DisguiseEntry(8267, 50904, 0, 0, 1011060), // Short beard - new DisguiseEntry(8254, 50801, 0, -10, 1011061), // Long beard - null, - new DisguiseEntry(0, 0, 0, 0, 1011051) // None - }; - - private readonly Mobile m_From; - private readonly DisguiseKit m_Kit; - private readonly bool m_Used; - - public DisguiseGump(Mobile from, DisguiseKit kit, bool startAtHair, bool used) : base(50, 50) - { - m_From = from; - m_Kit = kit; - m_Used = used; - - from.CloseGump(); - - AddPage(0); - - AddBackground(100, 10, 400, 385, 2600); - - //
THIEF DISGUISE KIT
- AddHtmlLocalized(100, 25, 400, 35, 1011045); - - AddButton(140, 353, 4005, 4007, 0); - AddHtmlLocalized(172, 355, 90, 35, 1011036); // OKAY - - AddButton(257, 353, 4005, 4007, 1); - AddHtmlLocalized(289, 355, 90, 35, 1011046); // APPLY - - if (from.Female || from.Body.IsFemale) - { - DrawEntries(0, 1, -1, m_HairEntries, -1); - } - else if (startAtHair) - { - DrawEntries(0, 1, 2, m_HairEntries, 1011056); - DrawEntries(1, 2, 1, m_BeardEntries, 1011059); - } - else - { - DrawEntries(1, 1, 2, m_BeardEntries, 1011059); - DrawEntries(0, 2, 1, m_HairEntries, 1011056); - } - } - - private void DrawEntries(int index, int page, int nextPage, DisguiseEntry[] entries, int nextNumber) - { - AddPage(page); - - if (nextPage != -1) - { - AddButton(155, 320, 250 + index * 2, 251 + index * 2, 0, GumpButtonType.Page, nextPage); - AddHtmlLocalized(180, 320, 150, 35, nextNumber); - } - - for (int i = 0; i < entries.Length; ++i) - { - DisguiseEntry entry = entries[i]; - - if (entry == null) - continue; - - int x = i % 2 * 205; - int y = i / 2 * 55; - - if (entry.m_GumpID != 0) + public DisguiseKit(Serial serial) : base(serial) { - AddBackground(220 + x, 60 + y, 50, 50, 2620); - AddImage(153 + x + entry.m_OffsetX, 15 + y + entry.m_OffsetY, entry.m_GumpID); } - AddHtmlLocalized(140 + x, 72 + y, 80, 35, entry.m_Number); - AddRadio(118 + x, 73 + y, 208, 209, false, i * 2 + index); - } - } + public override int LabelNumber => 1041078; // a disguise kit - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 0) - { - if (m_Used) - m_From.SendLocalizedMessage(501706); // Disguises wear off after 2 hours. - else - m_From.SendLocalizedMessage(501707); // You're looking good. - - return; - } - - int[] switches = info.Switches; - - if (switches.Length == 0) - return; - - int switched = switches[0]; - int type = switched % 2; - int index = switched / 2; - - bool hair = type == 0; - - DisguiseEntry[] entries = hair ? m_HairEntries : m_BeardEntries; - - if (index >= 0 && index < entries.Length) - { - DisguiseEntry entry = entries[index]; - - if (entry == null) - return; - - if (!m_Kit.ValidateUse(m_From)) - return; - - if (!hair && (m_From.Female || m_From.Body.IsFemale)) - return; - - m_From.NameMod = NameList.RandomName(m_From.Female ? "female" : "male"); - - if (m_From is PlayerMobile pm) + public override void Serialize(IGenericWriter writer) { - if (hair) - pm.SetHairMods(entry.m_ItemID, -2); - else - pm.SetHairMods(-2, entry.m_ItemID); + base.Serialize(writer); + + writer.Write(0); // version } - m_From.SendGump(new DisguiseGump(m_From, m_Kit, hair, true)); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - DisguiseTimers.RemoveTimer(m_From); + var version = reader.ReadInt(); + } - DisguiseTimers.CreateTimer(m_From, TimeSpan.FromHours(2.0)); - DisguiseTimers.StartTimer(m_From); - } + public bool ValidateUse(Mobile from) + { + var pm = from as PlayerMobile; + + if (!IsChildOf(from.Backpack)) + from.SendLocalizedMessage(1042001); + else if (pm == null || pm.NpcGuild != NpcGuild.ThievesGuild) + from.SendLocalizedMessage(501702); + else if (Stealing.SuspendOnMurder && pm.Kills > 0) + from.SendLocalizedMessage(501703); + else if (!from.CanBeginAction()) + from.SendLocalizedMessage(501704); + else if (Sigil.ExistsOn(from)) + from.SendLocalizedMessage(1010465); // You cannot disguise yourself while holding a sigil + else if (TransformationSpellHelper.UnderTransformation(from)) + from.SendLocalizedMessage(1061634); + else if (from.BodyMod == 183 || from.BodyMod == 184) + from.SendLocalizedMessage(1040002); + else if (!from.CanBeginAction() || from.IsBodyMod) + from.SendLocalizedMessage(501705); + else + return true; + + return false; + } + + public override void OnDoubleClick(Mobile from) + { + if (ValidateUse(from)) + from.SendGump(new DisguiseGump(from, this, true, false)); + } } - private class DisguiseEntry + public class DisguiseGump : Gump { - public readonly int m_GumpID; - public readonly int m_ItemID; - public readonly int m_Number; - public readonly int m_OffsetX; - public readonly int m_OffsetY; + private static readonly DisguiseEntry[] m_HairEntries = + { + new DisguiseEntry(8251, 50700, 0, 5, 1011052), // Short + new DisguiseEntry(8261, 60710, 0, 3, 1011047), // Pageboy + new DisguiseEntry(8252, 60708, 0, -5, 1011053), // Long + new DisguiseEntry(8264, 60901, 0, 5, 1011048), // Receding + new DisguiseEntry(8253, 60702, 0, -5, 1011054), // Ponytail + new DisguiseEntry(8265, 60707, 0, -5, 1011049), // 2-tails + new DisguiseEntry(8260, 50703, 0, 5, 1011055), // Mohawk + new DisguiseEntry(8266, 60713, 0, 10, 1011050), // Topknot + null, + new DisguiseEntry(0, 0, 0, 0, 1011051) // None + }; - public DisguiseEntry(int itemID, int gumpID, int ox, int oy, int name) - { - m_ItemID = itemID; - m_GumpID = gumpID; - m_OffsetX = ox; - m_OffsetY = oy; - m_Number = name; - } + private static readonly DisguiseEntry[] m_BeardEntries = + { + new DisguiseEntry(8269, 50906, 0, 0, 1011401), // Vandyke + new DisguiseEntry(8257, 50808, 0, -2, 1011062), // Mustache + new DisguiseEntry(8255, 50802, 0, 0, 1011060), // Short beard + new DisguiseEntry(8268, 50905, 0, -10, 1011061), // Long beard + new DisguiseEntry(8267, 50904, 0, 0, 1011060), // Short beard + new DisguiseEntry(8254, 50801, 0, -10, 1011061), // Long beard + null, + new DisguiseEntry(0, 0, 0, 0, 1011051) // None + }; + + private readonly Mobile m_From; + private readonly DisguiseKit m_Kit; + private readonly bool m_Used; + + public DisguiseGump(Mobile from, DisguiseKit kit, bool startAtHair, bool used) : base(50, 50) + { + m_From = from; + m_Kit = kit; + m_Used = used; + + from.CloseGump(); + + AddPage(0); + + AddBackground(100, 10, 400, 385, 2600); + + //
THIEF DISGUISE KIT
+ AddHtmlLocalized(100, 25, 400, 35, 1011045); + + AddButton(140, 353, 4005, 4007, 0); + AddHtmlLocalized(172, 355, 90, 35, 1011036); // OKAY + + AddButton(257, 353, 4005, 4007, 1); + AddHtmlLocalized(289, 355, 90, 35, 1011046); // APPLY + + if (from.Female || from.Body.IsFemale) + { + DrawEntries(0, 1, -1, m_HairEntries, -1); + } + else if (startAtHair) + { + DrawEntries(0, 1, 2, m_HairEntries, 1011056); + DrawEntries(1, 2, 1, m_BeardEntries, 1011059); + } + else + { + DrawEntries(1, 1, 2, m_BeardEntries, 1011059); + DrawEntries(0, 2, 1, m_HairEntries, 1011056); + } + } + + private void DrawEntries(int index, int page, int nextPage, DisguiseEntry[] entries, int nextNumber) + { + AddPage(page); + + if (nextPage != -1) + { + AddButton(155, 320, 250 + index * 2, 251 + index * 2, 0, GumpButtonType.Page, nextPage); + AddHtmlLocalized(180, 320, 150, 35, nextNumber); + } + + for (var i = 0; i < entries.Length; ++i) + { + var entry = entries[i]; + + if (entry == null) + continue; + + var x = i % 2 * 205; + var y = i / 2 * 55; + + if (entry.m_GumpID != 0) + { + AddBackground(220 + x, 60 + y, 50, 50, 2620); + AddImage(153 + x + entry.m_OffsetX, 15 + y + entry.m_OffsetY, entry.m_GumpID); + } + + AddHtmlLocalized(140 + x, 72 + y, 80, 35, entry.m_Number); + AddRadio(118 + x, 73 + y, 208, 209, false, i * 2 + index); + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 0) + { + if (m_Used) + m_From.SendLocalizedMessage(501706); // Disguises wear off after 2 hours. + else + m_From.SendLocalizedMessage(501707); // You're looking good. + + return; + } + + var switches = info.Switches; + + if (switches.Length == 0) + return; + + var switched = switches[0]; + var type = switched % 2; + var index = switched / 2; + + var hair = type == 0; + + var entries = hair ? m_HairEntries : m_BeardEntries; + + if (index >= 0 && index < entries.Length) + { + var entry = entries[index]; + + if (entry == null) + return; + + if (!m_Kit.ValidateUse(m_From)) + return; + + if (!hair && (m_From.Female || m_From.Body.IsFemale)) + return; + + m_From.NameMod = NameList.RandomName(m_From.Female ? "female" : "male"); + + if (m_From is PlayerMobile pm) + { + if (hair) + pm.SetHairMods(entry.m_ItemID, -2); + else + pm.SetHairMods(-2, entry.m_ItemID); + } + + m_From.SendGump(new DisguiseGump(m_From, m_Kit, hair, true)); + + DisguiseTimers.RemoveTimer(m_From); + + DisguiseTimers.CreateTimer(m_From, TimeSpan.FromHours(2.0)); + DisguiseTimers.StartTimer(m_From); + } + } + + private class DisguiseEntry + { + public readonly int m_GumpID; + public readonly int m_ItemID; + public readonly int m_Number; + public readonly int m_OffsetX; + public readonly int m_OffsetY; + + public DisguiseEntry(int itemID, int gumpID, int ox, int oy, int name) + { + m_ItemID = itemID; + m_GumpID = gumpID; + m_OffsetX = ox; + m_OffsetY = oy; + m_Number = name; + } + } } - } - public class DisguiseTimers - { - public static Dictionary Timers { get; } = new Dictionary(); - - public static void Initialize() + public class DisguiseTimers { - new DisguisePersistance(); + public static Dictionary Timers { get; } = new Dictionary(); + + public static void Initialize() + { + new DisguisePersistance(); + } + + public static void CreateTimer(Mobile m, TimeSpan delay) + { + if (m != null && !IsDisguised(m)) + Timers[m] = new InternalTimer(m, delay); + } + + public static void StartTimer(Mobile m) + { + Timers.TryGetValue(m, out var t); + t?.Start(); + } + + public static bool IsDisguised(Mobile m) => Timers.ContainsKey(m); + + public static void StopTimer(Mobile m) + { + if (!Timers.TryGetValue(m, out var t)) + return; + + var ts = t.Next - DateTime.UtcNow; + if (ts < TimeSpan.Zero) + ts = TimeSpan.Zero; + + t.Delay = ts; + t.Stop(); + } + + public static void RemoveTimer(Mobile m) + { + if (Timers.TryGetValue(m, out var t)) + { + t.Stop(); + Timers.Remove(m); + } + } + + public static TimeSpan TimeRemaining(Mobile m) => + Timers.TryGetValue(m, out var t) ? t.Next - DateTime.UtcNow : TimeSpan.Zero; + + private class InternalTimer : Timer + { + private readonly Mobile m_Player; + + public InternalTimer(Mobile m, TimeSpan delay) : base(delay) + { + m_Player = m; + Priority = TimerPriority.OneMinute; + } + + protected override void OnTick() + { + m_Player.NameMod = null; + + if (m_Player is PlayerMobile mobile) + mobile.SetHairMods(-1, -1); + + RemoveTimer(m_Player); + } + } } - - public static void CreateTimer(Mobile m, TimeSpan delay) - { - if (m != null && !IsDisguised(m)) - Timers[m] = new InternalTimer(m, delay); - } - - public static void StartTimer(Mobile m) - { - Timers.TryGetValue(m, out Timer t); - t?.Start(); - } - - public static bool IsDisguised(Mobile m) => Timers.ContainsKey(m); - - public static void StopTimer(Mobile m) - { - if (!Timers.TryGetValue(m, out Timer t)) - return; - - TimeSpan ts = t.Next - DateTime.UtcNow; - if (ts < TimeSpan.Zero) - ts = TimeSpan.Zero; - - t.Delay = ts; - t.Stop(); - } - - public static void RemoveTimer(Mobile m) - { - if (Timers.TryGetValue(m, out Timer t)) - { - t.Stop(); - Timers.Remove(m); - } - } - - public static TimeSpan TimeRemaining(Mobile m) => Timers.TryGetValue(m, out Timer t) ? t.Next - DateTime.UtcNow : TimeSpan.Zero; - - private class InternalTimer : Timer - { - private readonly Mobile m_Player; - - public InternalTimer(Mobile m, TimeSpan delay) : base(delay) - { - m_Player = m; - Priority = TimerPriority.OneMinute; - } - - protected override void OnTick() - { - m_Player.NameMod = null; - - if (m_Player is PlayerMobile mobile) - mobile.SetHairMods(-1, -1); - - RemoveTimer(m_Player); - } - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Thief/DisguisePersistance.cs b/Projects/UOContent/Items/Skill Items/Thief/DisguisePersistance.cs index d562bf5a5..6cb2d6b94 100644 --- a/Projects/UOContent/Items/Skill Items/Thief/DisguisePersistance.cs +++ b/Projects/UOContent/Items/Skill Items/Thief/DisguisePersistance.cs @@ -1,72 +1,71 @@ using System; -using System.Collections.Generic; namespace Server.Items { - public class DisguisePersistance : Item - { - public DisguisePersistance() : base(1) + public class DisguisePersistance : Item { - Movable = false; + public DisguisePersistance() : base(1) + { + Movable = false; - if (Instance?.Deleted != false) - Instance = this; - else - base.Delete(); - } + if (Instance?.Deleted != false) + Instance = this; + else + base.Delete(); + } - public DisguisePersistance(Serial serial) : base(serial) => Instance = this; + public DisguisePersistance(Serial serial) : base(serial) => Instance = this; - public static DisguisePersistance Instance { get; private set; } + public static DisguisePersistance Instance { get; private set; } - public override string DefaultName => "Disguise Persistance - Internal"; + public override string DefaultName => "Disguise Persistance - Internal"; - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version + writer.Write(0); // version - int timerCount = DisguiseTimers.Timers.Count; + var timerCount = DisguiseTimers.Timers.Count; - writer.Write(timerCount); + writer.Write(timerCount); - foreach (KeyValuePair entry in DisguiseTimers.Timers) - { - Mobile m = entry.Key; - - writer.Write(m); - writer.Write(entry.Value.Next - DateTime.UtcNow); - writer.Write(m.NameMod); - } - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - int count = reader.ReadInt(); - - for (int i = 0; i < count; ++i) + foreach (var entry in DisguiseTimers.Timers) { - Mobile m = reader.ReadMobile(); - DisguiseTimers.CreateTimer(m, reader.ReadTimeSpan()); - m.NameMod = reader.ReadString(); + var m = entry.Key; + + writer.Write(m); + writer.Write(entry.Value.Next - DateTime.UtcNow); + writer.Write(m.NameMod); } + } - break; - } - } - } + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - public override void Delete() - { + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + var count = reader.ReadInt(); + + for (var i = 0; i < count; ++i) + { + var m = reader.ReadMobile(); + DisguiseTimers.CreateTimer(m, reader.ReadTimeSpan()); + m.NameMod = reader.ReadString(); + } + + break; + } + } + } + + public override void Delete() + { + } } - } } diff --git a/Projects/UOContent/Items/Skill Items/Thief/LockPick.cs b/Projects/UOContent/Items/Skill Items/Thief/LockPick.cs index 6e98fe01d..48dcf8170 100644 --- a/Projects/UOContent/Items/Skill Items/Thief/LockPick.cs +++ b/Projects/UOContent/Items/Skill Items/Thief/LockPick.cs @@ -3,158 +3,158 @@ using Server.Targeting; namespace Server.Items { - public interface ILockpickable : IPoint2D - { - int LockLevel { get; set; } - bool Locked { get; set; } - Mobile Picker { get; set; } - int MaxLockLevel { get; set; } - int RequiredSkill { get; set; } - - void LockPick(Mobile from); - } - - [Flippable(0x14fc, 0x14fb)] - public class Lockpick : Item - { - [Constructible] - public Lockpick(int amount = 1) : base(0x14FC) + public interface ILockpickable : IPoint2D { - Stackable = true; - Amount = amount; + int LockLevel { get; set; } + bool Locked { get; set; } + Mobile Picker { get; set; } + int MaxLockLevel { get; set; } + int RequiredSkill { get; set; } + + void LockPick(Mobile from); } - public Lockpick(Serial serial) : base(serial) + [Flippable(0x14fc, 0x14fb)] + public class Lockpick : Item { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version == 0 && Weight == 0.1) - Weight = -1; - } - - public override void OnDoubleClick(Mobile from) - { - from.SendLocalizedMessage(502068); // What do you want to pick? - from.Target = new InternalTarget(this); - } - - private class InternalTarget : Target - { - private readonly Lockpick m_Item; - - public InternalTarget(Lockpick item) : base(1, false, TargetFlags.None) => m_Item = item; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Item.Deleted) - return; - - if (targeted is ILockpickable lockpickable) + [Constructible] + public Lockpick(int amount = 1) : base(0x14FC) { - Item item = lockpickable as Item; - from.Direction = from.GetDirectionTo(item); - - if (lockpickable.Locked) - { - from.PlaySound(0x241); - - new InternalTimer(from, lockpickable, m_Item).Start(); - } - else - { - // The door is not locked - from.SendLocalizedMessage(502069); // This does not appear to be locked - } - } - else - { - from.SendLocalizedMessage(501666); // You can't unlock that! - } - } - - private class InternalTimer : Timer - { - private readonly Mobile m_From; - private readonly ILockpickable m_Item; - private readonly Lockpick m_Lockpick; - - public InternalTimer(Mobile from, ILockpickable item, Lockpick lockpick) : base(TimeSpan.FromSeconds(3.0)) - { - m_From = from; - m_Item = item; - m_Lockpick = lockpick; - Priority = TimerPriority.TwoFiftyMS; + Stackable = true; + Amount = amount; } - protected void BrokeLockPickTest() + public Lockpick(Serial serial) : base(serial) { - // When failed, a 25% chance to break the lockpick - if (Utility.Random(4) == 0) - { - Item item = (Item)m_Item; - - // You broke the lockpick. - item.SendLocalizedMessageTo(m_From, 502074); - - m_From.PlaySound(0x3A4); - m_Lockpick.Consume(); - } } - protected override void OnTick() + public override void Serialize(IGenericWriter writer) { - Item item = (Item)m_Item; + base.Serialize(writer); - if (!m_From.InRange(item.GetWorldLocation(), 1)) - return; - - if (m_Item.LockLevel == 0 || m_Item.LockLevel == -255) - { - // LockLevel of 0 means that the door can't be picklocked - // LockLevel of -255 means it's magic locked - item.SendLocalizedMessageTo(m_From, 502073); // This lock cannot be picked by normal means - return; - } - - if (m_From.Skills.Lockpicking.Value < m_Item.RequiredSkill) - { - /* - // Do some training to gain skills - m_From.CheckSkill( SkillName.Lockpicking, 0, m_Item.LockLevel );*/ - - // The LockLevel is higher thant the LockPicking of the player - item.SendLocalizedMessageTo(m_From, 502072); // You don't see how that lock can be manipulated. - return; - } - - if (m_From.CheckTargetSkill(SkillName.Lockpicking, m_Item, m_Item.LockLevel, m_Item.MaxLockLevel)) - { - // Success! Pick the lock! - item.SendLocalizedMessageTo(m_From, 502076); // The lock quickly yields to your skill. - m_From.PlaySound(0x4A); - m_Item.LockPick(m_From); - } - else - { - // The player failed to pick the lock - BrokeLockPickTest(); - item.SendLocalizedMessageTo(m_From, 502075); // You are unable to pick the lock. - } + writer.Write(1); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version == 0 && Weight == 0.1) + Weight = -1; + } + + public override void OnDoubleClick(Mobile from) + { + from.SendLocalizedMessage(502068); // What do you want to pick? + from.Target = new InternalTarget(this); + } + + private class InternalTarget : Target + { + private readonly Lockpick m_Item; + + public InternalTarget(Lockpick item) : base(1, false, TargetFlags.None) => m_Item = item; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Item.Deleted) + return; + + if (targeted is ILockpickable lockpickable) + { + var item = lockpickable as Item; + from.Direction = from.GetDirectionTo(item); + + if (lockpickable.Locked) + { + from.PlaySound(0x241); + + new InternalTimer(from, lockpickable, m_Item).Start(); + } + else + { + // The door is not locked + from.SendLocalizedMessage(502069); // This does not appear to be locked + } + } + else + { + from.SendLocalizedMessage(501666); // You can't unlock that! + } + } + + private class InternalTimer : Timer + { + private readonly Mobile m_From; + private readonly ILockpickable m_Item; + private readonly Lockpick m_Lockpick; + + public InternalTimer(Mobile from, ILockpickable item, Lockpick lockpick) : base(TimeSpan.FromSeconds(3.0)) + { + m_From = from; + m_Item = item; + m_Lockpick = lockpick; + Priority = TimerPriority.TwoFiftyMS; + } + + protected void BrokeLockPickTest() + { + // When failed, a 25% chance to break the lockpick + if (Utility.Random(4) == 0) + { + var item = (Item)m_Item; + + // You broke the lockpick. + item.SendLocalizedMessageTo(m_From, 502074); + + m_From.PlaySound(0x3A4); + m_Lockpick.Consume(); + } + } + + protected override void OnTick() + { + var item = (Item)m_Item; + + if (!m_From.InRange(item.GetWorldLocation(), 1)) + return; + + if (m_Item.LockLevel == 0 || m_Item.LockLevel == -255) + { + // LockLevel of 0 means that the door can't be picklocked + // LockLevel of -255 means it's magic locked + item.SendLocalizedMessageTo(m_From, 502073); // This lock cannot be picked by normal means + return; + } + + if (m_From.Skills.Lockpicking.Value < m_Item.RequiredSkill) + { + /* + // Do some training to gain skills + m_From.CheckSkill( SkillName.Lockpicking, 0, m_Item.LockLevel );*/ + + // The LockLevel is higher thant the LockPicking of the player + item.SendLocalizedMessageTo(m_From, 502072); // You don't see how that lock can be manipulated. + return; + } + + if (m_From.CheckTargetSkill(SkillName.Lockpicking, m_Item, m_Item.LockLevel, m_Item.MaxLockLevel)) + { + // Success! Pick the lock! + item.SendLocalizedMessageTo(m_From, 502076); // The lock quickly yields to your skill. + m_From.PlaySound(0x4A); + m_Item.LockPick(m_From); + } + else + { + // The player failed to pick the lock + BrokeLockPickTest(); + item.SendLocalizedMessageTo(m_From, 502075); // You are unable to pick the lock. + } + } + } } - } } - } } diff --git a/Projects/UOContent/Items/Skill Items/Tinkering/Axle.cs b/Projects/UOContent/Items/Skill Items/Tinkering/Axle.cs index 05c8ad244..2daee8916 100644 --- a/Projects/UOContent/Items/Skill Items/Tinkering/Axle.cs +++ b/Projects/UOContent/Items/Skill Items/Tinkering/Axle.cs @@ -1,32 +1,32 @@ namespace Server.Items { - [Flippable(0x105B, 0x105C)] - public class Axle : Item - { - [Constructible] - public Axle(int amount = 1) : base(0x105B) + [Flippable(0x105B, 0x105C)] + public class Axle : Item { - Stackable = true; - Amount = amount; - Weight = 1.0; + [Constructible] + public Axle(int amount = 1) : base(0x105B) + { + Stackable = true; + Amount = amount; + Weight = 1.0; + } + + public Axle(Serial serial) : base(serial) + { + } + + 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 Axle(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Tinkering/AxleGears.cs b/Projects/UOContent/Items/Skill Items/Tinkering/AxleGears.cs index 429499544..0ccf367ce 100644 --- a/Projects/UOContent/Items/Skill Items/Tinkering/AxleGears.cs +++ b/Projects/UOContent/Items/Skill Items/Tinkering/AxleGears.cs @@ -1,32 +1,32 @@ namespace Server.Items { - [Flippable(0x1051, 0x1052)] - public class AxleGears : Item - { - [Constructible] - public AxleGears(int amount = 1) : base(0x1051) + [Flippable(0x1051, 0x1052)] + public class AxleGears : Item { - Stackable = true; - Amount = amount; - Weight = 1.0; + [Constructible] + public AxleGears(int amount = 1) : base(0x1051) + { + Stackable = true; + Amount = amount; + Weight = 1.0; + } + + public AxleGears(Serial serial) : base(serial) + { + } + + 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 AxleGears(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Tinkering/ClockFrame.cs b/Projects/UOContent/Items/Skill Items/Tinkering/ClockFrame.cs index a129b852c..263ee4057 100644 --- a/Projects/UOContent/Items/Skill Items/Tinkering/ClockFrame.cs +++ b/Projects/UOContent/Items/Skill Items/Tinkering/ClockFrame.cs @@ -1,32 +1,32 @@ namespace Server.Items { - [Flippable(0x104D, 0x104E)] - public class ClockFrame : Item - { - [Constructible] - public ClockFrame(int amount = 1) : base(0x104D) + [Flippable(0x104D, 0x104E)] + public class ClockFrame : Item { - Stackable = true; - Amount = amount; - Weight = 2.0; + [Constructible] + public ClockFrame(int amount = 1) : base(0x104D) + { + Stackable = true; + Amount = amount; + Weight = 2.0; + } + + public ClockFrame(Serial serial) : base(serial) + { + } + + 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 ClockFrame(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Tinkering/ClockParts.cs b/Projects/UOContent/Items/Skill Items/Tinkering/ClockParts.cs index 8827b584a..f55b90831 100644 --- a/Projects/UOContent/Items/Skill Items/Tinkering/ClockParts.cs +++ b/Projects/UOContent/Items/Skill Items/Tinkering/ClockParts.cs @@ -1,32 +1,32 @@ namespace Server.Items { - [Flippable(0x104F, 0x1050)] - public class ClockParts : Item - { - [Constructible] - public ClockParts(int amount = 1) : base(0x104F) + [Flippable(0x104F, 0x1050)] + public class ClockParts : Item { - Stackable = true; - Amount = amount; - Weight = 1.0; + [Constructible] + public ClockParts(int amount = 1) : base(0x104F) + { + Stackable = true; + Amount = amount; + Weight = 1.0; + } + + public ClockParts(Serial serial) : base(serial) + { + } + + 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 ClockParts(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Tinkering/Clocks.cs b/Projects/UOContent/Items/Skill Items/Tinkering/Clocks.cs index 75d8f04da..e2bdb2744 100644 --- a/Projects/UOContent/Items/Skill Items/Tinkering/Clocks.cs +++ b/Projects/UOContent/Items/Skill Items/Tinkering/Clocks.cs @@ -2,193 +2,193 @@ using System; namespace Server.Items { - public enum MoonPhase - { - NewMoon, - WaxingCrescentMoon, - FirstQuarter, - WaxingGibbous, - FullMoon, - WaningGibbous, - LastQuarter, - WaningCrescent - } - - [Flippable(0x104B, 0x104C)] - public class Clock : Item - { - public const double SecondsPerUOMinute = 5.0; - public const double MinutesPerUODay = SecondsPerUOMinute * 24; - - private static readonly DateTime WorldStart = new DateTime(1997, 9, 1); - - [Constructible] - public Clock(int itemID = 0x104B) : base(itemID) => Weight = 3.0; - - public Clock(Serial serial) : base(serial) + public enum MoonPhase { + NewMoon, + WaxingCrescentMoon, + FirstQuarter, + WaxingGibbous, + FullMoon, + WaningGibbous, + LastQuarter, + WaningCrescent } - public static DateTime ServerStart { get; private set; } - - public static void Initialize() + [Flippable(0x104B, 0x104C)] + public class Clock : Item { - ServerStart = DateTime.UtcNow; + public const double SecondsPerUOMinute = 5.0; + public const double MinutesPerUODay = SecondsPerUOMinute * 24; + + private static readonly DateTime WorldStart = new DateTime(1997, 9, 1); + + [Constructible] + public Clock(int itemID = 0x104B) : base(itemID) => Weight = 3.0; + + public Clock(Serial serial) : base(serial) + { + } + + public static DateTime ServerStart { get; private set; } + + public static void Initialize() + { + ServerStart = DateTime.UtcNow; + } + + public static MoonPhase GetMoonPhase(Map map, int x, int y) + { + GetTime(map, x, y, out _, out _, out var totalMinutes); + + if (map != null) + totalMinutes /= 10 + map.MapIndex * 20; + + return (MoonPhase)(totalMinutes % 8); + } + + public static void GetTime(Map map, int x, int y, out int hours, out int minutes) + { + GetTime(map, x, y, out hours, out minutes, out _); + } + + public static void GetTime(Map map, int x, int y, out int hours, out int minutes, out int totalMinutes) + { + var timeSpan = DateTime.UtcNow - WorldStart; + + totalMinutes = (int)(timeSpan.TotalSeconds / SecondsPerUOMinute); + + if (map != null) + totalMinutes += map.MapIndex * 320; + + // Really on OSI this must be by subserver + totalMinutes += x / 16; + + hours = totalMinutes / 60 % 24; + minutes = totalMinutes % 60; + } + + public static void GetTime(out int generalNumber, out string exactTime) + { + GetTime(null, 0, 0, out generalNumber, out exactTime); + } + + public static void GetTime(Mobile from, out int generalNumber, out string exactTime) + { + GetTime(from.Map, from.X, from.Y, out generalNumber, out exactTime); + } + + public static void GetTime(Map map, int x, int y, out int generalNumber, out string exactTime) + { + GetTime(map, x, y, out var hours, out int minutes); + + // 00:00 AM - 00:59 AM : Witching hour + // 01:00 AM - 03:59 AM : Middle of night + // 04:00 AM - 07:59 AM : Early morning + // 08:00 AM - 11:59 AM : Late morning + // 12:00 PM - 12:59 PM : Noon + // 01:00 PM - 03:59 PM : Afternoon + // 04:00 PM - 07:59 PM : Early evening + // 08:00 PM - 11:59 AM : Late at night + + if (hours >= 20) + generalNumber = 1042957; // It's late at night + else if (hours >= 16) + generalNumber = 1042956; // It's early in the evening + else if (hours >= 13) + generalNumber = 1042955; // It's the afternoon + else if (hours >= 12) + generalNumber = 1042954; // It's around noon + else if (hours >= 08) + generalNumber = 1042953; // It's late in the morning + else if (hours >= 04) + generalNumber = 1042952; // It's early in the morning + else if (hours >= 01) + generalNumber = 1042951; // It's the middle of the night + else + generalNumber = 1042950; // 'Tis the witching hour. 12 Midnight. + + hours %= 12; + + if (hours == 0) + hours = 12; + + exactTime = $"{hours}:{minutes:D2}"; + } + + public override void OnDoubleClick(Mobile from) + { + GetTime(from, out var genericNumber, out var exactTime); + + SendLocalizedMessageTo(from, genericNumber); + SendLocalizedMessageTo(from, 1042958, exactTime); // ~1_TIME~ to be exact + } + + 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 static MoonPhase GetMoonPhase(Map map, int x, int y) + [Flippable(0x104B, 0x104C)] + public class ClockRight : Clock { - GetTime(map, x, y, out _, out _, out int totalMinutes); + [Constructible] + public ClockRight() + { + } - if (map != null) - totalMinutes /= 10 + map.MapIndex * 20; + public ClockRight(Serial serial) : base(serial) + { + } - return (MoonPhase)(totalMinutes % 8); + 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 static void GetTime(Map map, int x, int y, out int hours, out int minutes) + [Flippable(0x104B, 0x104C)] + public class ClockLeft : Clock { - GetTime(map, x, y, out hours, out minutes, out _); + [Constructible] + public ClockLeft() : base(0x104C) + { + } + + public ClockLeft(Serial serial) : base(serial) + { + } + + 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 static void GetTime(Map map, int x, int y, out int hours, out int minutes, out int totalMinutes) - { - TimeSpan timeSpan = DateTime.UtcNow - WorldStart; - - totalMinutes = (int)(timeSpan.TotalSeconds / SecondsPerUOMinute); - - if (map != null) - totalMinutes += map.MapIndex * 320; - - // Really on OSI this must be by subserver - totalMinutes += x / 16; - - hours = totalMinutes / 60 % 24; - minutes = totalMinutes % 60; - } - - public static void GetTime(out int generalNumber, out string exactTime) - { - GetTime(null, 0, 0, out generalNumber, out exactTime); - } - - public static void GetTime(Mobile from, out int generalNumber, out string exactTime) - { - GetTime(from.Map, from.X, from.Y, out generalNumber, out exactTime); - } - - public static void GetTime(Map map, int x, int y, out int generalNumber, out string exactTime) - { - GetTime(map, x, y, out int hours, out int minutes); - - // 00:00 AM - 00:59 AM : Witching hour - // 01:00 AM - 03:59 AM : Middle of night - // 04:00 AM - 07:59 AM : Early morning - // 08:00 AM - 11:59 AM : Late morning - // 12:00 PM - 12:59 PM : Noon - // 01:00 PM - 03:59 PM : Afternoon - // 04:00 PM - 07:59 PM : Early evening - // 08:00 PM - 11:59 AM : Late at night - - if (hours >= 20) - generalNumber = 1042957; // It's late at night - else if (hours >= 16) - generalNumber = 1042956; // It's early in the evening - else if (hours >= 13) - generalNumber = 1042955; // It's the afternoon - else if (hours >= 12) - generalNumber = 1042954; // It's around noon - else if (hours >= 08) - generalNumber = 1042953; // It's late in the morning - else if (hours >= 04) - generalNumber = 1042952; // It's early in the morning - else if (hours >= 01) - generalNumber = 1042951; // It's the middle of the night - else - generalNumber = 1042950; // 'Tis the witching hour. 12 Midnight. - - hours %= 12; - - if (hours == 0) - hours = 12; - - exactTime = $"{hours}:{minutes:D2}"; - } - - public override void OnDoubleClick(Mobile from) - { - GetTime(from, out int genericNumber, out string exactTime); - - SendLocalizedMessageTo(from, genericNumber); - SendLocalizedMessageTo(from, 1042958, exactTime); // ~1_TIME~ to be exact - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x104B, 0x104C)] - public class ClockRight : Clock - { - [Constructible] - public ClockRight() : base(0x104B) - { - } - - public ClockRight(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x104B, 0x104C)] - public class ClockLeft : Clock - { - [Constructible] - public ClockLeft() : base(0x104C) - { - } - - public ClockLeft(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Tinkering/Gears.cs b/Projects/UOContent/Items/Skill Items/Tinkering/Gears.cs index 91e618877..72c57e9d5 100644 --- a/Projects/UOContent/Items/Skill Items/Tinkering/Gears.cs +++ b/Projects/UOContent/Items/Skill Items/Tinkering/Gears.cs @@ -1,32 +1,32 @@ namespace Server.Items { - [Flippable(0x1053, 0x1054)] - public class Gears : Item - { - [Constructible] - public Gears(int amount = 1) : base(0x1053) + [Flippable(0x1053, 0x1054)] + public class Gears : Item { - Stackable = true; - Amount = amount; - Weight = 1.0; + [Constructible] + public Gears(int amount = 1) : base(0x1053) + { + Stackable = true; + Amount = amount; + Weight = 1.0; + } + + public Gears(Serial serial) : base(serial) + { + } + + 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 Gears(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Tinkering/Globe.cs b/Projects/UOContent/Items/Skill Items/Tinkering/Globe.cs index 54f24673f..80290a8f2 100644 --- a/Projects/UOContent/Items/Skill Items/Tinkering/Globe.cs +++ b/Projects/UOContent/Items/Skill Items/Tinkering/Globe.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class Globe : Item - { - [Constructible] - public Globe() : base(0x1047) // It isn't flippable - => - Weight = 3.0; - - public Globe(Serial serial) : base(serial) + public class Globe : Item { + [Constructible] + public Globe() : base(0x1047) // It isn't flippable + => + Weight = 3.0; + + public Globe(Serial serial) : base(serial) + { + } + + 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(); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tinkering/Hinge.cs b/Projects/UOContent/Items/Skill Items/Tinkering/Hinge.cs index bbf8171b6..ae22ce999 100644 --- a/Projects/UOContent/Items/Skill Items/Tinkering/Hinge.cs +++ b/Projects/UOContent/Items/Skill Items/Tinkering/Hinge.cs @@ -1,32 +1,32 @@ namespace Server.Items { - [Flippable(0x1055, 0x1056)] - public class Hinge : Item - { - [Constructible] - public Hinge(int amount = 1) : base(0x1055) + [Flippable(0x1055, 0x1056)] + public class Hinge : Item { - Stackable = true; - Amount = amount; - Weight = 1.0; + [Constructible] + public Hinge(int amount = 1) : base(0x1055) + { + Stackable = true; + Amount = amount; + Weight = 1.0; + } + + public Hinge(Serial serial) : base(serial) + { + } + + 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 Hinge(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Tinkering/SextantParts.cs b/Projects/UOContent/Items/Skill Items/Tinkering/SextantParts.cs index 4ba60da71..f1653394c 100644 --- a/Projects/UOContent/Items/Skill Items/Tinkering/SextantParts.cs +++ b/Projects/UOContent/Items/Skill Items/Tinkering/SextantParts.cs @@ -1,32 +1,32 @@ namespace Server.Items { - [Flippable(0x1059, 0x105A)] - public class SextantParts : Item - { - [Constructible] - public SextantParts(int amount = 1) : base(0x1059) + [Flippable(0x1059, 0x105A)] + public class SextantParts : Item { - Stackable = true; - Amount = amount; - Weight = 2.0; + [Constructible] + public SextantParts(int amount = 1) : base(0x1059) + { + Stackable = true; + Amount = amount; + Weight = 2.0; + } + + public SextantParts(Serial serial) : base(serial) + { + } + + 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 SextantParts(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Tinkering/Springs.cs b/Projects/UOContent/Items/Skill Items/Tinkering/Springs.cs index 628901102..6faf9b76d 100644 --- a/Projects/UOContent/Items/Skill Items/Tinkering/Springs.cs +++ b/Projects/UOContent/Items/Skill Items/Tinkering/Springs.cs @@ -1,32 +1,32 @@ namespace Server.Items { - [Flippable(0x105D, 0x105E)] - public class Springs : Item - { - [Constructible] - public Springs(int amount = 1) : base(0x105D) + [Flippable(0x105D, 0x105E)] + public class Springs : Item { - Stackable = true; - Amount = amount; - Weight = 1.0; + [Constructible] + public Springs(int amount = 1) : base(0x105D) + { + Stackable = true; + Amount = amount; + Weight = 1.0; + } + + public Springs(Serial serial) : base(serial) + { + } + + 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 Springs(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Tinkering/Spyglass.cs b/Projects/UOContent/Items/Skill Items/Tinkering/Spyglass.cs index 95b0d320a..4781225c0 100644 --- a/Projects/UOContent/Items/Skill Items/Tinkering/Spyglass.cs +++ b/Projects/UOContent/Items/Skill Items/Tinkering/Spyglass.cs @@ -1,71 +1,99 @@ -using Server.Engines.Quests; using Server.Engines.Quests.Hag; using Server.Mobiles; using Server.Network; namespace Server.Items { - [Flippable(0x14F5, 0x14F6)] - public class Spyglass : Item - { - [Constructible] - public Spyglass() : base(0x14F5) => Weight = 3.0; - - public Spyglass(Serial serial) : base(serial) + [Flippable(0x14F5, 0x14F6)] + public class Spyglass : Item { - } + [Constructible] + public Spyglass() : base(0x14F5) => Weight = 3.0; - public override void OnDoubleClick(Mobile from) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1008155); // You peer into the heavens, seeking the moons... - - from.Send(new MessageLocalizedAffix(from.Serial, from.Body, MessageType.Regular, 0x3B2, 3, - 1008146 + (int)Clock.GetMoonPhase(Map.Trammel, from.X, from.Y), "", AffixType.Prepend, "Trammel : ", "")); - from.Send(new MessageLocalizedAffix(from.Serial, from.Body, MessageType.Regular, 0x3B2, 3, - 1008146 + (int)Clock.GetMoonPhase(Map.Felucca, from.X, from.Y), "", AffixType.Prepend, "Felucca : ", "")); - - if (from is PlayerMobile player) - { - QuestSystem qs = player.Quest; - - if (!(qs is WitchApprenticeQuest)) - return; - - FindIngredientObjective obj = qs.FindObjective(); - - if (obj?.Completed == false && obj.Ingredient == Ingredient.StarChart) + public Spyglass(Serial serial) : base(serial) { - Clock.GetTime(from.Map, from.X, from.Y, out int hours, out int _); - - if (hours < 5 || hours > 17) - { - player.SendLocalizedMessage( - 1055040); // You gaze up into the glittering night sky. With great care, you compose a chart of the most prominent star patterns. - - obj.Complete(); - } - else - { - player.SendLocalizedMessage( - 1055039); // You gaze up into the sky, but it is not dark enough to see any stars. - } } - } + + public override void OnDoubleClick(Mobile from) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1008155 + ); // You peer into the heavens, seeking the moons... + + from.Send( + new MessageLocalizedAffix( + from.Serial, + from.Body, + MessageType.Regular, + 0x3B2, + 3, + 1008146 + (int)Clock.GetMoonPhase(Map.Trammel, from.X, from.Y), + "", + AffixType.Prepend, + "Trammel : ", + "" + ) + ); + from.Send( + new MessageLocalizedAffix( + from.Serial, + from.Body, + MessageType.Regular, + 0x3B2, + 3, + 1008146 + (int)Clock.GetMoonPhase(Map.Felucca, from.X, from.Y), + "", + AffixType.Prepend, + "Felucca : ", + "" + ) + ); + + if (from is PlayerMobile player) + { + var qs = player.Quest; + + if (!(qs is WitchApprenticeQuest)) + return; + + var obj = qs.FindObjective(); + + if (obj?.Completed == false && obj.Ingredient == Ingredient.StarChart) + { + Clock.GetTime(from.Map, from.X, from.Y, out var hours, out int _); + + if (hours < 5 || hours > 17) + { + player.SendLocalizedMessage( + 1055040 + ); // You gaze up into the glittering night sky. With great care, you compose a chart of the most prominent star patterns. + + obj.Complete(); + } + else + { + player.SendLocalizedMessage( + 1055039 + ); // You gaze up into the sky, but it is not dark enough to see any stars. + } + } + } + } + + 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 Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tinkering/Utensils.cs b/Projects/UOContent/Items/Skill Items/Tinkering/Utensils.cs index 96c437b34..7c0fd70c1 100644 --- a/Projects/UOContent/Items/Skill Items/Tinkering/Utensils.cs +++ b/Projects/UOContent/Items/Skill Items/Tinkering/Utensils.cs @@ -1,245 +1,245 @@ namespace Server.Items { - [Flippable(0x9F4, 0x9F5, 0x9A3, 0x9A4)] - public class Fork : Item - { - [Constructible] - public Fork() : base(0x9F4) => Weight = 1.0; - - public Fork(Serial serial) : base(serial) + [Flippable(0x9F4, 0x9F5, 0x9A3, 0x9A4)] + public class Fork : Item { + [Constructible] + public Fork() : base(0x9F4) => Weight = 1.0; + + public Fork(Serial serial) : base(serial) + { + } + + 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 Serialize(IGenericWriter writer) + public class ForkLeft : Item { - base.Serialize(writer); + [Constructible] + public ForkLeft() : base(0x9F4) => Weight = 1.0; - writer.Write(0); // version + public ForkLeft(Serial serial) : base(serial) + { + } + + 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 Deserialize(IGenericReader reader) + public class ForkRight : Item { - base.Deserialize(reader); + [Constructible] + public ForkRight() : base(0x9F5) => Weight = 1.0; - int version = reader.ReadInt(); - } - } + public ForkRight(Serial serial) : base(serial) + { + } - public class ForkLeft : Item - { - [Constructible] - public ForkLeft() : base(0x9F4) => Weight = 1.0; + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public ForkLeft(Serial serial) : base(serial) - { + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } } - public override void Serialize(IGenericWriter writer) + [Flippable(0x9F8, 0x9F9, 0x9C2, 0x9C3)] + public class Spoon : Item { - base.Serialize(writer); + [Constructible] + public Spoon() : base(0x9F8) => Weight = 1.0; - writer.Write(0); // version + public Spoon(Serial serial) : base(serial) + { + } + + 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 Deserialize(IGenericReader reader) + public class SpoonLeft : Item { - base.Deserialize(reader); + [Constructible] + public SpoonLeft() : base(0x9F8) => Weight = 1.0; - int version = reader.ReadInt(); - } - } + public SpoonLeft(Serial serial) : base(serial) + { + } - public class ForkRight : Item - { - [Constructible] - public ForkRight() : base(0x9F5) => Weight = 1.0; + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public ForkRight(Serial serial) : base(serial) - { + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } } - public override void Serialize(IGenericWriter writer) + public class SpoonRight : Item { - base.Serialize(writer); + [Constructible] + public SpoonRight() : base(0x9F9) => Weight = 1.0; - writer.Write(0); // version + public SpoonRight(Serial serial) : base(serial) + { + } + + 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 Deserialize(IGenericReader reader) + [Flippable(0x9F6, 0x9F7, 0x9A5, 0x9A6)] + public class Knife : Item { - base.Deserialize(reader); + [Constructible] + public Knife() : base(0x9F6) => Weight = 1.0; - int version = reader.ReadInt(); - } - } + public Knife(Serial serial) : base(serial) + { + } - [Flippable(0x9F8, 0x9F9, 0x9C2, 0x9C3)] - public class Spoon : Item - { - [Constructible] - public Spoon() : base(0x9F8) => Weight = 1.0; + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public Spoon(Serial serial) : base(serial) - { + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } } - public override void Serialize(IGenericWriter writer) + public class KnifeLeft : Item { - base.Serialize(writer); + [Constructible] + public KnifeLeft() : base(0x9F6) => Weight = 1.0; - writer.Write(0); // version + public KnifeLeft(Serial serial) : base(serial) + { + } + + 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 Deserialize(IGenericReader reader) + public class KnifeRight : Item { - base.Deserialize(reader); + [Constructible] + public KnifeRight() : base(0x9F7) => Weight = 1.0; - int version = reader.ReadInt(); - } - } + public KnifeRight(Serial serial) : base(serial) + { + } - public class SpoonLeft : Item - { - [Constructible] - public SpoonLeft() : base(0x9F8) => Weight = 1.0; + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public SpoonLeft(Serial serial) : base(serial) - { + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } } - public override void Serialize(IGenericWriter writer) + public class Plate : Item { - base.Serialize(writer); + [Constructible] + public Plate() : base(0x9D7) => Weight = 1.0; - writer.Write(0); // version + public Plate(Serial serial) : base(serial) + { + } + + 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 Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class SpoonRight : Item - { - [Constructible] - public SpoonRight() : base(0x9F9) => Weight = 1.0; - - public SpoonRight(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [Flippable(0x9F6, 0x9F7, 0x9A5, 0x9A6)] - public class Knife : Item - { - [Constructible] - public Knife() : base(0x9F6) => Weight = 1.0; - - public Knife(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class KnifeLeft : Item - { - [Constructible] - public KnifeLeft() : base(0x9F6) => Weight = 1.0; - - public KnifeLeft(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class KnifeRight : Item - { - [Constructible] - public KnifeRight() : base(0x9F7) => Weight = 1.0; - - public KnifeRight(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Plate : Item - { - [Constructible] - public Plate() : base(0x9D7) => Weight = 1.0; - - public Plate(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/BaseRunicTool.cs b/Projects/UOContent/Items/Skill Items/Tools/BaseRunicTool.cs index 573b644b1..6c44dde66 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/BaseRunicTool.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/BaseRunicTool.cs @@ -4,915 +4,943 @@ using System.Collections.Generic; namespace Server.Items { - public abstract class BaseRunicTool : BaseTool - { - private const int MaxProperties = 32; - - private static bool m_IsRunicTool; - private static int m_LuckChance; - - private static readonly SkillName[] m_PossibleBonusSkills = + public abstract class BaseRunicTool : BaseTool { - SkillName.Swords, - SkillName.Fencing, - SkillName.Macing, - SkillName.Archery, - SkillName.Wrestling, - SkillName.Parry, - SkillName.Tactics, - SkillName.Anatomy, - SkillName.Healing, - SkillName.Magery, - SkillName.Meditation, - SkillName.EvalInt, - SkillName.MagicResist, - SkillName.AnimalTaming, - SkillName.AnimalLore, - SkillName.Veterinary, - SkillName.Musicianship, - SkillName.Provocation, - SkillName.Discordance, - SkillName.Peacemaking, - SkillName.Chivalry, - SkillName.Focus, - SkillName.Necromancy, - SkillName.Stealing, - SkillName.Stealth, - SkillName.SpiritSpeak, - SkillName.Bushido, - SkillName.Ninjitsu - }; + private const int MaxProperties = 32; - private static readonly SkillName[] m_PossibleSpellbookSkills = - { - SkillName.Magery, - SkillName.Meditation, - SkillName.EvalInt, - SkillName.MagicResist - }; + private static bool m_IsRunicTool; + private static int m_LuckChance; - private static readonly BitArray m_Props = new BitArray(MaxProperties); - private static readonly int[] m_Possible = new int[MaxProperties]; - private CraftResource m_Resource; - - public BaseRunicTool(CraftResource resource, int itemID) : base(itemID) => m_Resource = resource; - - public BaseRunicTool(CraftResource resource, int uses, int itemID) : base(uses, itemID) => m_Resource = resource; - - public BaseRunicTool(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public CraftResource Resource - { - get => m_Resource; - set - { - m_Resource = value; - Hue = CraftResources.GetHue(m_Resource); - InvalidateProperties(); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - writer.Write((int)m_Resource); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Resource = (CraftResource)reader.ReadInt(); - break; - } - } - } - - private static int Scale(int min, int max, int low, int high) - { - int percent; - - if (m_IsRunicTool) - { - percent = Utility.RandomMinMax(min, max); - } - else - { - // Behold, the worst system ever! - int v = Utility.RandomMinMax(0, 10000); - - v = (int)Math.Sqrt(v); - v = 100 - v; - - if (LootPack.CheckLuck(m_LuckChance)) - v += 10; - - if (v < min) - v = min; - else if (v > max) - v = max; - - percent = v; - } - - int scaledBy = Math.Abs(high - low) + 1; - - if (scaledBy != 0) - scaledBy = 10000 / scaledBy; - - percent *= 10000 + scaledBy; - - return low + (high - low) * percent / 1000001; - } - - private static void ApplyAttribute(AosAttributes attrs, int min, int max, AosAttribute attr, int low, int high, - int scale = 1) - { - if (attr == AosAttribute.CastSpeed) - attrs[attr] += Scale(min, max, low / scale, high / scale) * scale; - else - attrs[attr] = Scale(min, max, low / scale, high / scale) * scale; - - if (attr == AosAttribute.SpellChanneling) - attrs[AosAttribute.CastSpeed] -= 1; - } - - private static void ApplyAttribute(AosArmorAttributes attrs, int min, int max, AosArmorAttribute attr, int low, - int high) - { - attrs[attr] = Scale(min, max, low, high); - } - - private static void ApplyAttribute(AosArmorAttributes attrs, int min, int max, AosArmorAttribute attr, int low, - int high, int scale) - { - attrs[attr] = Scale(min, max, low / scale, high / scale) * scale; - } - - private static void ApplyAttribute(AosWeaponAttributes attrs, int min, int max, AosWeaponAttribute attr, int low, - int high) - { - attrs[attr] = Scale(min, max, low, high); - } - - private static void ApplyAttribute(AosWeaponAttributes attrs, int min, int max, AosWeaponAttribute attr, int low, - int high, int scale) - { - attrs[attr] = Scale(min, max, low / scale, high / scale) * scale; - } - - private static void ApplyAttribute(AosElementAttributes attrs, int min, int max, AosElementAttribute attr, int low, - int high) - { - attrs[attr] = Scale(min, max, low, high); - } - - private static void ApplyAttribute(AosElementAttributes attrs, int min, int max, AosElementAttribute attr, int low, - int high, int scale) - { - attrs[attr] = Scale(min, max, low / scale, high / scale) * scale; - } - - private static void ApplySkillBonus(AosSkillBonuses attrs, int min, int max, int index, int low, int high) - { - List possibleSkills = - new List(attrs.Owner is Spellbook ? m_PossibleSpellbookSkills : m_PossibleBonusSkills); - int count = Core.SE ? possibleSkills.Count : possibleSkills.Count - 2; - - SkillName sk; - bool found; - - do - { - found = false; - sk = possibleSkills[Utility.Random(count--)]; - possibleSkills.Remove(sk); - - for (int i = 0; !found && i < 5; ++i) - found = attrs.GetValues(i, out SkillName check, out _) && check == sk; - } while (found && count > 0); - - attrs.SetValues(index, sk, Scale(min, max, low, high)); - } - - private static void ApplyResistance(BaseArmor ar, int min, int max, ResistanceType res, int low, int high) - { - switch (res) - { - case ResistanceType.Physical: - ar.PhysicalBonus += Scale(min, max, low, high); - break; - case ResistanceType.Fire: - ar.FireBonus += Scale(min, max, low, high); - break; - case ResistanceType.Cold: - ar.ColdBonus += Scale(min, max, low, high); - break; - case ResistanceType.Poison: - ar.PoisonBonus += Scale(min, max, low, high); - break; - case ResistanceType.Energy: - ar.EnergyBonus += Scale(min, max, low, high); - break; - } - } - - public static int GetUniqueRandom(int count) - { - int avail = 0; - - for (int i = 0; i < count; ++i) - if (!m_Props[i]) - m_Possible[avail++] = i; - - if (avail == 0) - return -1; - - int v = m_Possible[Utility.Random(avail)]; - - m_Props.Set(v, true); - - return v; - } - - public void ApplyAttributesTo(BaseWeapon weapon) - { - CraftResourceInfo resInfo = CraftResources.GetInfo(m_Resource); - - CraftAttributeInfo attrs = resInfo?.AttributeInfo; - - if (attrs == null) - return; - - int attributeCount = Utility.RandomMinMax(attrs.RunicMinAttributes, attrs.RunicMaxAttributes); - int min = attrs.RunicMinIntensity; - int max = attrs.RunicMaxIntensity; - - ApplyAttributesTo(weapon, true, 0, attributeCount, min, max); - } - - public static void ApplyAttributesTo(BaseWeapon weapon, int attributeCount, int min, int max) - { - ApplyAttributesTo(weapon, false, 0, attributeCount, min, max); - } - - public static void ApplyAttributesTo(BaseWeapon weapon, bool isRunicTool, int luckChance, int attributeCount, - int min, int max) - { - m_IsRunicTool = isRunicTool; - m_LuckChance = luckChance; - - AosAttributes primary = weapon.Attributes; - AosWeaponAttributes secondary = weapon.WeaponAttributes; - - m_Props.SetAll(false); - - if (weapon is BaseRanged) - m_Props.Set(2, true); // ranged weapons cannot be ubws or mageweapon - - for (int i = 0; i < attributeCount; ++i) - { - int random = GetUniqueRandom(25); - - if (random == -1) - break; - - switch (random) + private static readonly SkillName[] m_PossibleBonusSkills = { - case 0: - { - switch (Utility.Random(5)) - { - case 0: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitPhysicalArea, 2, 50, 2); - break; - case 1: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitFireArea, 2, 50, 2); - break; - case 2: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitColdArea, 2, 50, 2); - break; - case 3: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitPoisonArea, 2, 50, 2); - break; - case 4: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitEnergyArea, 2, 50, 2); - break; - } + SkillName.Swords, + SkillName.Fencing, + SkillName.Macing, + SkillName.Archery, + SkillName.Wrestling, + SkillName.Parry, + SkillName.Tactics, + SkillName.Anatomy, + SkillName.Healing, + SkillName.Magery, + SkillName.Meditation, + SkillName.EvalInt, + SkillName.MagicResist, + SkillName.AnimalTaming, + SkillName.AnimalLore, + SkillName.Veterinary, + SkillName.Musicianship, + SkillName.Provocation, + SkillName.Discordance, + SkillName.Peacemaking, + SkillName.Chivalry, + SkillName.Focus, + SkillName.Necromancy, + SkillName.Stealing, + SkillName.Stealth, + SkillName.SpiritSpeak, + SkillName.Bushido, + SkillName.Ninjitsu + }; - break; - } - case 1: - { - switch (Utility.Random(4)) - { - case 0: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitMagicArrow, 2, 50, 2); - break; - case 1: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitHarm, 2, 50, 2); - break; - case 2: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitFireball, 2, 50, 2); - break; - case 3: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitLightning, 2, 50, 2); - break; - } - - break; - } - case 2: - { - switch (Utility.Random(2)) - { - case 0: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.UseBestSkill, 1, 1); - break; - case 1: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.MageWeapon, 1, 10); - break; - } - - break; - } - case 3: - ApplyAttribute(primary, min, max, AosAttribute.WeaponDamage, 1, 50); - break; - case 4: - ApplyAttribute(primary, min, max, AosAttribute.DefendChance, 1, 15); - break; - case 5: - ApplyAttribute(primary, min, max, AosAttribute.CastSpeed, 1, 1); - break; - case 6: - ApplyAttribute(primary, min, max, AosAttribute.AttackChance, 1, 15); - break; - case 7: - ApplyAttribute(primary, min, max, AosAttribute.Luck, 1, 100); - break; - case 8: - ApplyAttribute(primary, min, max, AosAttribute.WeaponSpeed, 5, 30, 5); - break; - case 9: - ApplyAttribute(primary, min, max, AosAttribute.SpellChanneling, 1, 1); - break; - case 10: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitDispel, 2, 50, 2); - break; - case 11: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitLeechHits, 2, 50, 2); - break; - case 12: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitLowerAttack, 2, 50, 2); - break; - case 13: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitLowerDefend, 2, 50, 2); - break; - case 14: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitLeechMana, 2, 50, 2); - break; - case 15: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitLeechStam, 2, 50, 2); - break; - case 16: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.LowerStatReq, 10, 100, 10); - break; - case 17: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.ResistPhysicalBonus, 1, 15); - break; - case 18: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.ResistFireBonus, 1, 15); - break; - case 19: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.ResistColdBonus, 1, 15); - break; - case 20: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.ResistPoisonBonus, 1, 15); - break; - case 21: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.ResistEnergyBonus, 1, 15); - break; - case 22: - ApplyAttribute(secondary, min, max, AosWeaponAttribute.DurabilityBonus, 10, 100, 10); - break; - case 23: - weapon.Slayer = GetRandomSlayer(); - break; - case 24: - GetElementalDamages(weapon); - break; - } - } - } - - public static void GetElementalDamages(BaseWeapon weapon) - { - GetElementalDamages(weapon, true); - } - - public static void GetElementalDamages(BaseWeapon weapon, bool randomizeOrder) - { - weapon.GetDamageTypes(null, out int phys, out _, out _, out _, out _, out _, out _); - - int totalDamage = phys; - - AosElementAttribute[] attrs = - { - AosElementAttribute.Cold, - AosElementAttribute.Energy, - AosElementAttribute.Fire, - AosElementAttribute.Poison - }; - - if (randomizeOrder) - for (int i = 0; i < attrs.Length; i++) + private static readonly SkillName[] m_PossibleSpellbookSkills = { - AosElementAttribute temp = attrs[i]; - int rand = Utility.Random(attrs.Length); + SkillName.Magery, + SkillName.Meditation, + SkillName.EvalInt, + SkillName.MagicResist + }; - attrs[i] = attrs[rand]; - attrs[rand] = temp; + private static readonly BitArray m_Props = new BitArray(MaxProperties); + private static readonly int[] m_Possible = new int[MaxProperties]; + private CraftResource m_Resource; + + public BaseRunicTool(CraftResource resource, int itemID) : base(itemID) => m_Resource = resource; + + public BaseRunicTool(CraftResource resource, int uses, int itemID) : base(uses, itemID) => m_Resource = resource; + + public BaseRunicTool(Serial serial) : base(serial) + { } - /* - totalDamage = AssignElementalDamage( weapon, AosElementAttribute.Cold, totalDamage ); - totalDamage = AssignElementalDamage( weapon, AosElementAttribute.Energy, totalDamage ); - totalDamage = AssignElementalDamage( weapon, AosElementAttribute.Fire, totalDamage ); - totalDamage = AssignElementalDamage( weapon, AosElementAttribute.Poison, totalDamage ); - - weapon.AosElementDamages[AosElementAttribute.Physical] = 100 - totalDamage; - * */ - - for (int i = 0; i < attrs.Length; i++) - totalDamage = AssignElementalDamage(weapon, attrs[i], totalDamage); - - // Order is Cold, Energy, Fire, Poison -> Physical left - // Cannot be looped, AoselementAttribute is 'out of order' - - weapon.Hue = weapon.GetElementalDamageHue(); - } - - private static int AssignElementalDamage(BaseWeapon weapon, AosElementAttribute attr, int totalDamage) - { - if (totalDamage <= 0) - return 0; - - int random = Utility.Random(totalDamage / 10 + 1) * 10; - weapon.AosElementDamages[attr] = random; - - return totalDamage - random; - } - - public static SlayerName GetRandomSlayer() - { - // TODO: Check random algorithm on OSI - - SlayerGroup[] groups = SlayerGroup.Groups; - - if (groups.Length == 0) - return SlayerName.None; - - SlayerGroup - group = groups[ - Utility.Random(groups.Length - - 1)]; // -1 To Exclude the Fey Slayer which appears ONLY on a certain artifact. - SlayerEntry entry; - - if (Utility.Random(100) < 10) // 10% chance to do super slayer - { - entry = group.Super; - } - else - { - SlayerEntry[] entries = group.Entries; - - if (entries.Length == 0) - return SlayerName.None; - - entry = entries.RandomElement(); - } - - return entry.Name; - } - - public void ApplyAttributesTo(BaseArmor armor) - { - CraftResourceInfo resInfo = CraftResources.GetInfo(m_Resource); - - CraftAttributeInfo attrs = resInfo?.AttributeInfo; - - if (attrs == null) - return; - - int attributeCount = Utility.RandomMinMax(attrs.RunicMinAttributes, attrs.RunicMaxAttributes); - int min = attrs.RunicMinIntensity; - int max = attrs.RunicMaxIntensity; - - ApplyAttributesTo(armor, true, 0, attributeCount, min, max); - } - - public static void ApplyAttributesTo(BaseArmor armor, int attributeCount, int min, int max) - { - ApplyAttributesTo(armor, false, 0, attributeCount, min, max); - } - - public static void ApplyAttributesTo(BaseArmor armor, bool isRunicTool, int luckChance, int attributeCount, int min, - int max) - { - m_IsRunicTool = isRunicTool; - m_LuckChance = luckChance; - - AosAttributes primary = armor.Attributes; - AosArmorAttributes secondary = armor.ArmorAttributes; - - m_Props.SetAll(false); - - bool isShield = armor is BaseShield; - int baseCount = isShield ? 7 : 20; - int baseOffset = isShield ? 0 : 4; - - if (!isShield && armor.MeditationAllowance == ArmorMeditationAllowance.All) - m_Props.Set(3, true); // remove mage armor from possible properties - if (armor.Resource >= CraftResource.RegularLeather && armor.Resource <= CraftResource.BarbedLeather) - { - m_Props.Set(0, true); // remove lower requirements from possible properties for leather armor - m_Props.Set(2, true); // remove durability bonus from possible properties - } - - if (armor.RequiredRace == Race.Elf) - m_Props.Set(7, - true); // elves inherently have night sight and elf only armor doesn't get night sight as a mod - - for (int i = 0; i < attributeCount; ++i) - { - int random = GetUniqueRandom(baseCount); - - if (random == -1) - break; - - random += baseOffset; - - switch (random) + [CommandProperty(AccessLevel.GameMaster)] + public CraftResource Resource { - /* Begin Sheilds */ - case 0: - ApplyAttribute(primary, min, max, AosAttribute.SpellChanneling, 1, 1); - break; - case 1: - ApplyAttribute(primary, min, max, AosAttribute.DefendChance, 1, 15); - break; - case 2: - if (Core.ML) - ApplyAttribute(primary, min, max, AosAttribute.ReflectPhysical, 1, 15); + get => m_Resource; + set + { + m_Resource = value; + Hue = CraftResources.GetHue(m_Resource); + InvalidateProperties(); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + writer.Write((int)m_Resource); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Resource = (CraftResource)reader.ReadInt(); + break; + } + } + } + + private static int Scale(int min, int max, int low, int high) + { + int percent; + + if (m_IsRunicTool) + { + percent = Utility.RandomMinMax(min, max); + } else - ApplyAttribute(primary, min, max, AosAttribute.AttackChance, 1, 15); - break; - case 3: - ApplyAttribute(primary, min, max, AosAttribute.CastSpeed, 1, 1); - break; - /* Begin Armor */ - case 4: - ApplyAttribute(secondary, min, max, AosArmorAttribute.LowerStatReq, 10, 100, 10); - break; - case 5: - ApplyAttribute(secondary, min, max, AosArmorAttribute.SelfRepair, 1, 5); - break; - case 6: - ApplyAttribute(secondary, min, max, AosArmorAttribute.DurabilityBonus, 10, 100, 10); - break; - /* End Shields */ - case 7: - ApplyAttribute(secondary, min, max, AosArmorAttribute.MageArmor, 1, 1); - break; - case 8: - ApplyAttribute(primary, min, max, AosAttribute.RegenHits, 1, 2); - break; - case 9: - ApplyAttribute(primary, min, max, AosAttribute.RegenStam, 1, 3); - break; - case 10: - ApplyAttribute(primary, min, max, AosAttribute.RegenMana, 1, 2); - break; - case 11: - ApplyAttribute(primary, min, max, AosAttribute.NightSight, 1, 1); - break; - case 12: - ApplyAttribute(primary, min, max, AosAttribute.BonusHits, 1, 5); - break; - case 13: - ApplyAttribute(primary, min, max, AosAttribute.BonusStam, 1, 8); - break; - case 14: - ApplyAttribute(primary, min, max, AosAttribute.BonusMana, 1, 8); - break; - case 15: - ApplyAttribute(primary, min, max, AosAttribute.LowerManaCost, 1, 8); - break; - case 16: - ApplyAttribute(primary, min, max, AosAttribute.LowerRegCost, 1, 20); - break; - case 17: - ApplyAttribute(primary, min, max, AosAttribute.Luck, 1, 100); - break; - case 18: - ApplyAttribute(primary, min, max, AosAttribute.ReflectPhysical, 1, 15); - break; - case 19: - ApplyResistance(armor, min, max, ResistanceType.Physical, 1, 15); - break; - case 20: - ApplyResistance(armor, min, max, ResistanceType.Fire, 1, 15); - break; - case 21: - ApplyResistance(armor, min, max, ResistanceType.Cold, 1, 15); - break; - case 22: - ApplyResistance(armor, min, max, ResistanceType.Poison, 1, 15); - break; - case 23: - ApplyResistance(armor, min, max, ResistanceType.Energy, 1, 15); - break; - /* End Armor */ - } - } - } - - public static void ApplyAttributesTo(BaseHat hat, int attributeCount, int min, int max) - { - ApplyAttributesTo(hat, false, 0, attributeCount, min, max); - } - - public static void ApplyAttributesTo(BaseHat hat, bool isRunicTool, int luckChance, int attributeCount, int min, - int max) - { - m_IsRunicTool = isRunicTool; - m_LuckChance = luckChance; - - AosAttributes primary = hat.Attributes; - AosArmorAttributes secondary = hat.ClothingAttributes; - AosElementAttributes resists = hat.Resistances; - - m_Props.SetAll(false); - - for (int i = 0; i < attributeCount; ++i) - { - int random = GetUniqueRandom(19); - - if (random == -1) - break; - - switch (random) - { - case 0: - ApplyAttribute(primary, min, max, AosAttribute.ReflectPhysical, 1, 15); - break; - case 1: - ApplyAttribute(primary, min, max, AosAttribute.RegenHits, 1, 2); - break; - case 2: - ApplyAttribute(primary, min, max, AosAttribute.RegenStam, 1, 3); - break; - case 3: - ApplyAttribute(primary, min, max, AosAttribute.RegenMana, 1, 2); - break; - case 4: - ApplyAttribute(primary, min, max, AosAttribute.NightSight, 1, 1); - break; - case 5: - ApplyAttribute(primary, min, max, AosAttribute.BonusHits, 1, 5); - break; - case 6: - ApplyAttribute(primary, min, max, AosAttribute.BonusStam, 1, 8); - break; - case 7: - ApplyAttribute(primary, min, max, AosAttribute.BonusMana, 1, 8); - break; - case 8: - ApplyAttribute(primary, min, max, AosAttribute.LowerManaCost, 1, 8); - break; - case 9: - ApplyAttribute(primary, min, max, AosAttribute.LowerRegCost, 1, 20); - break; - case 10: - ApplyAttribute(primary, min, max, AosAttribute.Luck, 1, 100); - break; - case 11: - ApplyAttribute(secondary, min, max, AosArmorAttribute.LowerStatReq, 10, 100, 10); - break; - case 12: - ApplyAttribute(secondary, min, max, AosArmorAttribute.SelfRepair, 1, 5); - break; - case 13: - ApplyAttribute(secondary, min, max, AosArmorAttribute.DurabilityBonus, 10, 100, 10); - break; - case 14: - ApplyAttribute(resists, min, max, AosElementAttribute.Physical, 1, 15); - break; - case 15: - ApplyAttribute(resists, min, max, AosElementAttribute.Fire, 1, 15); - break; - case 16: - ApplyAttribute(resists, min, max, AosElementAttribute.Cold, 1, 15); - break; - case 17: - ApplyAttribute(resists, min, max, AosElementAttribute.Poison, 1, 15); - break; - case 18: - ApplyAttribute(resists, min, max, AosElementAttribute.Energy, 1, 15); - break; - } - } - } - - public static void ApplyAttributesTo(BaseJewel jewelry, int attributeCount, int min, int max) - { - ApplyAttributesTo(jewelry, false, 0, attributeCount, min, max); - } - - public static void ApplyAttributesTo(BaseJewel jewelry, bool isRunicTool, int luckChance, int attributeCount, - int min, int max) - { - m_IsRunicTool = isRunicTool; - m_LuckChance = luckChance; - - AosAttributes primary = jewelry.Attributes; - AosElementAttributes resists = jewelry.Resistances; - AosSkillBonuses skills = jewelry.SkillBonuses; - - m_Props.SetAll(false); - - for (int i = 0; i < attributeCount; ++i) - { - int random = GetUniqueRandom(24); - - if (random == -1) - break; - - switch (random) - { - case 0: - ApplyAttribute(resists, min, max, AosElementAttribute.Physical, 1, 15); - break; - case 1: - ApplyAttribute(resists, min, max, AosElementAttribute.Fire, 1, 15); - break; - case 2: - ApplyAttribute(resists, min, max, AosElementAttribute.Cold, 1, 15); - break; - case 3: - ApplyAttribute(resists, min, max, AosElementAttribute.Poison, 1, 15); - break; - case 4: - ApplyAttribute(resists, min, max, AosElementAttribute.Energy, 1, 15); - break; - case 5: - ApplyAttribute(primary, min, max, AosAttribute.WeaponDamage, 1, 25); - break; - case 6: - ApplyAttribute(primary, min, max, AosAttribute.DefendChance, 1, 15); - break; - case 7: - ApplyAttribute(primary, min, max, AosAttribute.AttackChance, 1, 15); - break; - case 8: - ApplyAttribute(primary, min, max, AosAttribute.BonusStr, 1, 8); - break; - case 9: - ApplyAttribute(primary, min, max, AosAttribute.BonusDex, 1, 8); - break; - case 10: - ApplyAttribute(primary, min, max, AosAttribute.BonusInt, 1, 8); - break; - case 11: - ApplyAttribute(primary, min, max, AosAttribute.EnhancePotions, 5, 25, 5); - break; - case 12: - ApplyAttribute(primary, min, max, AosAttribute.CastSpeed, 1, 1); - break; - case 13: - ApplyAttribute(primary, min, max, AosAttribute.CastRecovery, 1, 3); - break; - case 14: - ApplyAttribute(primary, min, max, AosAttribute.LowerManaCost, 1, 8); - break; - case 15: - ApplyAttribute(primary, min, max, AosAttribute.LowerRegCost, 1, 20); - break; - case 16: - ApplyAttribute(primary, min, max, AosAttribute.Luck, 1, 100); - break; - case 17: - ApplyAttribute(primary, min, max, AosAttribute.SpellDamage, 1, 12); - break; - case 18: - ApplyAttribute(primary, min, max, AosAttribute.NightSight, 1, 1); - break; - case 19: - ApplySkillBonus(skills, min, max, 0, 1, 15); - break; - case 20: - ApplySkillBonus(skills, min, max, 1, 1, 15); - break; - case 21: - ApplySkillBonus(skills, min, max, 2, 1, 15); - break; - case 22: - ApplySkillBonus(skills, min, max, 3, 1, 15); - break; - case 23: - ApplySkillBonus(skills, min, max, 4, 1, 15); - break; - } - } - } - - public static void ApplyAttributesTo(Spellbook spellbook, int attributeCount, int min, int max) - { - ApplyAttributesTo(spellbook, false, 0, attributeCount, min, max); - } - - public static void ApplyAttributesTo(Spellbook spellbook, bool isRunicTool, int luckChance, int attributeCount, - int min, int max) - { - m_IsRunicTool = isRunicTool; - m_LuckChance = luckChance; - - AosAttributes primary = spellbook.Attributes; - AosSkillBonuses skills = spellbook.SkillBonuses; - - m_Props.SetAll(false); - - for (int i = 0; i < attributeCount; ++i) - { - int random = GetUniqueRandom(16); - - if (random == -1) - break; - - switch (random) - { - case 0: - case 1: - case 2: - case 3: { - ApplyAttribute(primary, min, max, AosAttribute.BonusInt, 1, 8); + // Behold, the worst system ever! + var v = Utility.RandomMinMax(0, 10000); - for (int j = 0; j < 4; ++j) - m_Props.Set(j, true); + v = (int)Math.Sqrt(v); + v = 100 - v; - break; + if (LootPack.CheckLuck(m_LuckChance)) + v += 10; + + if (v < min) + v = min; + else if (v > max) + v = max; + + percent = v; + } + + var scaledBy = Math.Abs(high - low) + 1; + + if (scaledBy != 0) + scaledBy = 10000 / scaledBy; + + percent *= 10000 + scaledBy; + + return low + (high - low) * percent / 1000001; + } + + private static void ApplyAttribute( + AosAttributes attrs, int min, int max, AosAttribute attr, int low, int high, + int scale = 1 + ) + { + if (attr == AosAttribute.CastSpeed) + attrs[attr] += Scale(min, max, low / scale, high / scale) * scale; + else + attrs[attr] = Scale(min, max, low / scale, high / scale) * scale; + + if (attr == AosAttribute.SpellChanneling) + attrs[AosAttribute.CastSpeed] -= 1; + } + + private static void ApplyAttribute( + AosArmorAttributes attrs, int min, int max, AosArmorAttribute attr, int low, + int high + ) + { + attrs[attr] = Scale(min, max, low, high); + } + + private static void ApplyAttribute( + AosArmorAttributes attrs, int min, int max, AosArmorAttribute attr, int low, + int high, int scale + ) + { + attrs[attr] = Scale(min, max, low / scale, high / scale) * scale; + } + + private static void ApplyAttribute( + AosWeaponAttributes attrs, int min, int max, AosWeaponAttribute attr, int low, + int high + ) + { + attrs[attr] = Scale(min, max, low, high); + } + + private static void ApplyAttribute( + AosWeaponAttributes attrs, int min, int max, AosWeaponAttribute attr, int low, + int high, int scale + ) + { + attrs[attr] = Scale(min, max, low / scale, high / scale) * scale; + } + + private static void ApplyAttribute( + AosElementAttributes attrs, int min, int max, AosElementAttribute attr, int low, + int high + ) + { + attrs[attr] = Scale(min, max, low, high); + } + + private static void ApplyAttribute( + AosElementAttributes attrs, int min, int max, AosElementAttribute attr, int low, + int high, int scale + ) + { + attrs[attr] = Scale(min, max, low / scale, high / scale) * scale; + } + + private static void ApplySkillBonus(AosSkillBonuses attrs, int min, int max, int index, int low, int high) + { + var possibleSkills = + new List(attrs.Owner is Spellbook ? m_PossibleSpellbookSkills : m_PossibleBonusSkills); + var count = Core.SE ? possibleSkills.Count : possibleSkills.Count - 2; + + SkillName sk; + bool found; + + do + { + found = false; + sk = possibleSkills[Utility.Random(count--)]; + possibleSkills.Remove(sk); + + for (var i = 0; !found && i < 5; ++i) + found = attrs.GetValues(i, out var check, out _) && check == sk; + } while (found && count > 0); + + attrs.SetValues(index, sk, Scale(min, max, low, high)); + } + + private static void ApplyResistance(BaseArmor ar, int min, int max, ResistanceType res, int low, int high) + { + switch (res) + { + case ResistanceType.Physical: + ar.PhysicalBonus += Scale(min, max, low, high); + break; + case ResistanceType.Fire: + ar.FireBonus += Scale(min, max, low, high); + break; + case ResistanceType.Cold: + ar.ColdBonus += Scale(min, max, low, high); + break; + case ResistanceType.Poison: + ar.PoisonBonus += Scale(min, max, low, high); + break; + case ResistanceType.Energy: + ar.EnergyBonus += Scale(min, max, low, high); + break; + } + } + + public static int GetUniqueRandom(int count) + { + var avail = 0; + + for (var i = 0; i < count; ++i) + if (!m_Props[i]) + m_Possible[avail++] = i; + + if (avail == 0) + return -1; + + var v = m_Possible[Utility.Random(avail)]; + + m_Props.Set(v, true); + + return v; + } + + public void ApplyAttributesTo(BaseWeapon weapon) + { + var resInfo = CraftResources.GetInfo(m_Resource); + + var attrs = resInfo?.AttributeInfo; + + if (attrs == null) + return; + + var attributeCount = Utility.RandomMinMax(attrs.RunicMinAttributes, attrs.RunicMaxAttributes); + var min = attrs.RunicMinIntensity; + var max = attrs.RunicMaxIntensity; + + ApplyAttributesTo(weapon, true, 0, attributeCount, min, max); + } + + public static void ApplyAttributesTo(BaseWeapon weapon, int attributeCount, int min, int max) + { + ApplyAttributesTo(weapon, false, 0, attributeCount, min, max); + } + + public static void ApplyAttributesTo( + BaseWeapon weapon, bool isRunicTool, int luckChance, int attributeCount, + int min, int max + ) + { + m_IsRunicTool = isRunicTool; + m_LuckChance = luckChance; + + var primary = weapon.Attributes; + var secondary = weapon.WeaponAttributes; + + m_Props.SetAll(false); + + if (weapon is BaseRanged) + m_Props.Set(2, true); // ranged weapons cannot be ubws or mageweapon + + for (var i = 0; i < attributeCount; ++i) + { + var random = GetUniqueRandom(25); + + if (random == -1) + break; + + switch (random) + { + case 0: + { + switch (Utility.Random(5)) + { + case 0: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitPhysicalArea, 2, 50, 2); + break; + case 1: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitFireArea, 2, 50, 2); + break; + case 2: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitColdArea, 2, 50, 2); + break; + case 3: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitPoisonArea, 2, 50, 2); + break; + case 4: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitEnergyArea, 2, 50, 2); + break; + } + + break; + } + case 1: + { + switch (Utility.Random(4)) + { + case 0: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitMagicArrow, 2, 50, 2); + break; + case 1: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitHarm, 2, 50, 2); + break; + case 2: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitFireball, 2, 50, 2); + break; + case 3: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitLightning, 2, 50, 2); + break; + } + + break; + } + case 2: + { + switch (Utility.Random(2)) + { + case 0: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.UseBestSkill, 1, 1); + break; + case 1: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.MageWeapon, 1, 10); + break; + } + + break; + } + case 3: + ApplyAttribute(primary, min, max, AosAttribute.WeaponDamage, 1, 50); + break; + case 4: + ApplyAttribute(primary, min, max, AosAttribute.DefendChance, 1, 15); + break; + case 5: + ApplyAttribute(primary, min, max, AosAttribute.CastSpeed, 1, 1); + break; + case 6: + ApplyAttribute(primary, min, max, AosAttribute.AttackChance, 1, 15); + break; + case 7: + ApplyAttribute(primary, min, max, AosAttribute.Luck, 1, 100); + break; + case 8: + ApplyAttribute(primary, min, max, AosAttribute.WeaponSpeed, 5, 30, 5); + break; + case 9: + ApplyAttribute(primary, min, max, AosAttribute.SpellChanneling, 1, 1); + break; + case 10: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitDispel, 2, 50, 2); + break; + case 11: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitLeechHits, 2, 50, 2); + break; + case 12: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitLowerAttack, 2, 50, 2); + break; + case 13: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitLowerDefend, 2, 50, 2); + break; + case 14: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitLeechMana, 2, 50, 2); + break; + case 15: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.HitLeechStam, 2, 50, 2); + break; + case 16: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.LowerStatReq, 10, 100, 10); + break; + case 17: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.ResistPhysicalBonus, 1, 15); + break; + case 18: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.ResistFireBonus, 1, 15); + break; + case 19: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.ResistColdBonus, 1, 15); + break; + case 20: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.ResistPoisonBonus, 1, 15); + break; + case 21: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.ResistEnergyBonus, 1, 15); + break; + case 22: + ApplyAttribute(secondary, min, max, AosWeaponAttribute.DurabilityBonus, 10, 100, 10); + break; + case 23: + weapon.Slayer = GetRandomSlayer(); + break; + case 24: + GetElementalDamages(weapon); + break; + } + } + } + + public static void GetElementalDamages(BaseWeapon weapon) + { + GetElementalDamages(weapon, true); + } + + public static void GetElementalDamages(BaseWeapon weapon, bool randomizeOrder) + { + weapon.GetDamageTypes(null, out var phys, out _, out _, out _, out _, out _, out _); + + var totalDamage = phys; + + AosElementAttribute[] attrs = + { + AosElementAttribute.Cold, + AosElementAttribute.Energy, + AosElementAttribute.Fire, + AosElementAttribute.Poison + }; + + if (randomizeOrder) + for (var i = 0; i < attrs.Length; i++) + { + var temp = attrs[i]; + var rand = Utility.Random(attrs.Length); + + attrs[i] = attrs[rand]; + attrs[rand] = temp; + } + + /* + totalDamage = AssignElementalDamage( weapon, AosElementAttribute.Cold, totalDamage ); + totalDamage = AssignElementalDamage( weapon, AosElementAttribute.Energy, totalDamage ); + totalDamage = AssignElementalDamage( weapon, AosElementAttribute.Fire, totalDamage ); + totalDamage = AssignElementalDamage( weapon, AosElementAttribute.Poison, totalDamage ); + + weapon.AosElementDamages[AosElementAttribute.Physical] = 100 - totalDamage; + * */ + + for (var i = 0; i < attrs.Length; i++) + totalDamage = AssignElementalDamage(weapon, attrs[i], totalDamage); + + // Order is Cold, Energy, Fire, Poison -> Physical left + // Cannot be looped, AoselementAttribute is 'out of order' + + weapon.Hue = weapon.GetElementalDamageHue(); + } + + private static int AssignElementalDamage(BaseWeapon weapon, AosElementAttribute attr, int totalDamage) + { + if (totalDamage <= 0) + return 0; + + var random = Utility.Random(totalDamage / 10 + 1) * 10; + weapon.AosElementDamages[attr] = random; + + return totalDamage - random; + } + + public static SlayerName GetRandomSlayer() + { + // TODO: Check random algorithm on OSI + + var groups = SlayerGroup.Groups; + + if (groups.Length == 0) + return SlayerName.None; + + var + group = groups[ + Utility.Random( + groups.Length - + 1 + )]; // -1 To Exclude the Fey Slayer which appears ONLY on a certain artifact. + SlayerEntry entry; + + if (Utility.Random(100) < 10) // 10% chance to do super slayer + { + entry = group.Super; + } + else + { + var entries = group.Entries; + + if (entries.Length == 0) + return SlayerName.None; + + entry = entries.RandomElement(); + } + + return entry.Name; + } + + public void ApplyAttributesTo(BaseArmor armor) + { + var resInfo = CraftResources.GetInfo(m_Resource); + + var attrs = resInfo?.AttributeInfo; + + if (attrs == null) + return; + + var attributeCount = Utility.RandomMinMax(attrs.RunicMinAttributes, attrs.RunicMaxAttributes); + var min = attrs.RunicMinIntensity; + var max = attrs.RunicMaxIntensity; + + ApplyAttributesTo(armor, true, 0, attributeCount, min, max); + } + + public static void ApplyAttributesTo(BaseArmor armor, int attributeCount, int min, int max) + { + ApplyAttributesTo(armor, false, 0, attributeCount, min, max); + } + + public static void ApplyAttributesTo( + BaseArmor armor, bool isRunicTool, int luckChance, int attributeCount, int min, + int max + ) + { + m_IsRunicTool = isRunicTool; + m_LuckChance = luckChance; + + var primary = armor.Attributes; + var secondary = armor.ArmorAttributes; + + m_Props.SetAll(false); + + var isShield = armor is BaseShield; + var baseCount = isShield ? 7 : 20; + var baseOffset = isShield ? 0 : 4; + + if (!isShield && armor.MeditationAllowance == ArmorMeditationAllowance.All) + m_Props.Set(3, true); // remove mage armor from possible properties + if (armor.Resource >= CraftResource.RegularLeather && armor.Resource <= CraftResource.BarbedLeather) + { + m_Props.Set(0, true); // remove lower requirements from possible properties for leather armor + m_Props.Set(2, true); // remove durability bonus from possible properties + } + + if (armor.RequiredRace == Race.Elf) + m_Props.Set( + 7, + true + ); // elves inherently have night sight and elf only armor doesn't get night sight as a mod + + for (var i = 0; i < attributeCount; ++i) + { + var random = GetUniqueRandom(baseCount); + + if (random == -1) + break; + + random += baseOffset; + + switch (random) + { + /* Begin Sheilds */ + case 0: + ApplyAttribute(primary, min, max, AosAttribute.SpellChanneling, 1, 1); + break; + case 1: + ApplyAttribute(primary, min, max, AosAttribute.DefendChance, 1, 15); + break; + case 2: + if (Core.ML) + ApplyAttribute(primary, min, max, AosAttribute.ReflectPhysical, 1, 15); + else + ApplyAttribute(primary, min, max, AosAttribute.AttackChance, 1, 15); + break; + case 3: + ApplyAttribute(primary, min, max, AosAttribute.CastSpeed, 1, 1); + break; + /* Begin Armor */ + case 4: + ApplyAttribute(secondary, min, max, AosArmorAttribute.LowerStatReq, 10, 100, 10); + break; + case 5: + ApplyAttribute(secondary, min, max, AosArmorAttribute.SelfRepair, 1, 5); + break; + case 6: + ApplyAttribute(secondary, min, max, AosArmorAttribute.DurabilityBonus, 10, 100, 10); + break; + /* End Shields */ + case 7: + ApplyAttribute(secondary, min, max, AosArmorAttribute.MageArmor, 1, 1); + break; + case 8: + ApplyAttribute(primary, min, max, AosAttribute.RegenHits, 1, 2); + break; + case 9: + ApplyAttribute(primary, min, max, AosAttribute.RegenStam, 1, 3); + break; + case 10: + ApplyAttribute(primary, min, max, AosAttribute.RegenMana, 1, 2); + break; + case 11: + ApplyAttribute(primary, min, max, AosAttribute.NightSight, 1, 1); + break; + case 12: + ApplyAttribute(primary, min, max, AosAttribute.BonusHits, 1, 5); + break; + case 13: + ApplyAttribute(primary, min, max, AosAttribute.BonusStam, 1, 8); + break; + case 14: + ApplyAttribute(primary, min, max, AosAttribute.BonusMana, 1, 8); + break; + case 15: + ApplyAttribute(primary, min, max, AosAttribute.LowerManaCost, 1, 8); + break; + case 16: + ApplyAttribute(primary, min, max, AosAttribute.LowerRegCost, 1, 20); + break; + case 17: + ApplyAttribute(primary, min, max, AosAttribute.Luck, 1, 100); + break; + case 18: + ApplyAttribute(primary, min, max, AosAttribute.ReflectPhysical, 1, 15); + break; + case 19: + ApplyResistance(armor, min, max, ResistanceType.Physical, 1, 15); + break; + case 20: + ApplyResistance(armor, min, max, ResistanceType.Fire, 1, 15); + break; + case 21: + ApplyResistance(armor, min, max, ResistanceType.Cold, 1, 15); + break; + case 22: + ApplyResistance(armor, min, max, ResistanceType.Poison, 1, 15); + break; + case 23: + ApplyResistance(armor, min, max, ResistanceType.Energy, 1, 15); + break; + /* End Armor */ + } + } + } + + public static void ApplyAttributesTo(BaseHat hat, int attributeCount, int min, int max) + { + ApplyAttributesTo(hat, false, 0, attributeCount, min, max); + } + + public static void ApplyAttributesTo( + BaseHat hat, bool isRunicTool, int luckChance, int attributeCount, int min, + int max + ) + { + m_IsRunicTool = isRunicTool; + m_LuckChance = luckChance; + + var primary = hat.Attributes; + var secondary = hat.ClothingAttributes; + var resists = hat.Resistances; + + m_Props.SetAll(false); + + for (var i = 0; i < attributeCount; ++i) + { + var random = GetUniqueRandom(19); + + if (random == -1) + break; + + switch (random) + { + case 0: + ApplyAttribute(primary, min, max, AosAttribute.ReflectPhysical, 1, 15); + break; + case 1: + ApplyAttribute(primary, min, max, AosAttribute.RegenHits, 1, 2); + break; + case 2: + ApplyAttribute(primary, min, max, AosAttribute.RegenStam, 1, 3); + break; + case 3: + ApplyAttribute(primary, min, max, AosAttribute.RegenMana, 1, 2); + break; + case 4: + ApplyAttribute(primary, min, max, AosAttribute.NightSight, 1, 1); + break; + case 5: + ApplyAttribute(primary, min, max, AosAttribute.BonusHits, 1, 5); + break; + case 6: + ApplyAttribute(primary, min, max, AosAttribute.BonusStam, 1, 8); + break; + case 7: + ApplyAttribute(primary, min, max, AosAttribute.BonusMana, 1, 8); + break; + case 8: + ApplyAttribute(primary, min, max, AosAttribute.LowerManaCost, 1, 8); + break; + case 9: + ApplyAttribute(primary, min, max, AosAttribute.LowerRegCost, 1, 20); + break; + case 10: + ApplyAttribute(primary, min, max, AosAttribute.Luck, 1, 100); + break; + case 11: + ApplyAttribute(secondary, min, max, AosArmorAttribute.LowerStatReq, 10, 100, 10); + break; + case 12: + ApplyAttribute(secondary, min, max, AosArmorAttribute.SelfRepair, 1, 5); + break; + case 13: + ApplyAttribute(secondary, min, max, AosArmorAttribute.DurabilityBonus, 10, 100, 10); + break; + case 14: + ApplyAttribute(resists, min, max, AosElementAttribute.Physical, 1, 15); + break; + case 15: + ApplyAttribute(resists, min, max, AosElementAttribute.Fire, 1, 15); + break; + case 16: + ApplyAttribute(resists, min, max, AosElementAttribute.Cold, 1, 15); + break; + case 17: + ApplyAttribute(resists, min, max, AosElementAttribute.Poison, 1, 15); + break; + case 18: + ApplyAttribute(resists, min, max, AosElementAttribute.Energy, 1, 15); + break; + } + } + } + + public static void ApplyAttributesTo(BaseJewel jewelry, int attributeCount, int min, int max) + { + ApplyAttributesTo(jewelry, false, 0, attributeCount, min, max); + } + + public static void ApplyAttributesTo( + BaseJewel jewelry, bool isRunicTool, int luckChance, int attributeCount, + int min, int max + ) + { + m_IsRunicTool = isRunicTool; + m_LuckChance = luckChance; + + var primary = jewelry.Attributes; + var resists = jewelry.Resistances; + var skills = jewelry.SkillBonuses; + + m_Props.SetAll(false); + + for (var i = 0; i < attributeCount; ++i) + { + var random = GetUniqueRandom(24); + + if (random == -1) + break; + + switch (random) + { + case 0: + ApplyAttribute(resists, min, max, AosElementAttribute.Physical, 1, 15); + break; + case 1: + ApplyAttribute(resists, min, max, AosElementAttribute.Fire, 1, 15); + break; + case 2: + ApplyAttribute(resists, min, max, AosElementAttribute.Cold, 1, 15); + break; + case 3: + ApplyAttribute(resists, min, max, AosElementAttribute.Poison, 1, 15); + break; + case 4: + ApplyAttribute(resists, min, max, AosElementAttribute.Energy, 1, 15); + break; + case 5: + ApplyAttribute(primary, min, max, AosAttribute.WeaponDamage, 1, 25); + break; + case 6: + ApplyAttribute(primary, min, max, AosAttribute.DefendChance, 1, 15); + break; + case 7: + ApplyAttribute(primary, min, max, AosAttribute.AttackChance, 1, 15); + break; + case 8: + ApplyAttribute(primary, min, max, AosAttribute.BonusStr, 1, 8); + break; + case 9: + ApplyAttribute(primary, min, max, AosAttribute.BonusDex, 1, 8); + break; + case 10: + ApplyAttribute(primary, min, max, AosAttribute.BonusInt, 1, 8); + break; + case 11: + ApplyAttribute(primary, min, max, AosAttribute.EnhancePotions, 5, 25, 5); + break; + case 12: + ApplyAttribute(primary, min, max, AosAttribute.CastSpeed, 1, 1); + break; + case 13: + ApplyAttribute(primary, min, max, AosAttribute.CastRecovery, 1, 3); + break; + case 14: + ApplyAttribute(primary, min, max, AosAttribute.LowerManaCost, 1, 8); + break; + case 15: + ApplyAttribute(primary, min, max, AosAttribute.LowerRegCost, 1, 20); + break; + case 16: + ApplyAttribute(primary, min, max, AosAttribute.Luck, 1, 100); + break; + case 17: + ApplyAttribute(primary, min, max, AosAttribute.SpellDamage, 1, 12); + break; + case 18: + ApplyAttribute(primary, min, max, AosAttribute.NightSight, 1, 1); + break; + case 19: + ApplySkillBonus(skills, min, max, 0, 1, 15); + break; + case 20: + ApplySkillBonus(skills, min, max, 1, 1, 15); + break; + case 21: + ApplySkillBonus(skills, min, max, 2, 1, 15); + break; + case 22: + ApplySkillBonus(skills, min, max, 3, 1, 15); + break; + case 23: + ApplySkillBonus(skills, min, max, 4, 1, 15); + break; + } + } + } + + public static void ApplyAttributesTo(Spellbook spellbook, int attributeCount, int min, int max) + { + ApplyAttributesTo(spellbook, false, 0, attributeCount, min, max); + } + + public static void ApplyAttributesTo( + Spellbook spellbook, bool isRunicTool, int luckChance, int attributeCount, + int min, int max + ) + { + m_IsRunicTool = isRunicTool; + m_LuckChance = luckChance; + + var primary = spellbook.Attributes; + var skills = spellbook.SkillBonuses; + + m_Props.SetAll(false); + + for (var i = 0; i < attributeCount; ++i) + { + var random = GetUniqueRandom(16); + + if (random == -1) + break; + + switch (random) + { + case 0: + case 1: + case 2: + case 3: + { + ApplyAttribute(primary, min, max, AosAttribute.BonusInt, 1, 8); + + for (var j = 0; j < 4; ++j) + m_Props.Set(j, true); + + break; + } + case 4: + ApplyAttribute(primary, min, max, AosAttribute.BonusMana, 1, 8); + break; + case 5: + ApplyAttribute(primary, min, max, AosAttribute.CastSpeed, 1, 1); + break; + case 6: + ApplyAttribute(primary, min, max, AosAttribute.CastRecovery, 1, 3); + break; + case 7: + ApplyAttribute(primary, min, max, AosAttribute.SpellDamage, 1, 12); + break; + case 8: + ApplySkillBonus(skills, min, max, 0, 1, 15); + break; + case 9: + ApplySkillBonus(skills, min, max, 1, 1, 15); + break; + case 10: + ApplySkillBonus(skills, min, max, 2, 1, 15); + break; + case 11: + ApplySkillBonus(skills, min, max, 3, 1, 15); + break; + case 12: + ApplyAttribute(primary, min, max, AosAttribute.LowerRegCost, 1, 20); + break; + case 13: + ApplyAttribute(primary, min, max, AosAttribute.LowerManaCost, 1, 8); + break; + case 14: + ApplyAttribute(primary, min, max, AosAttribute.RegenMana, 1, 2); + break; + case 15: + spellbook.Slayer = GetRandomSlayer(); + break; + } } - case 4: - ApplyAttribute(primary, min, max, AosAttribute.BonusMana, 1, 8); - break; - case 5: - ApplyAttribute(primary, min, max, AosAttribute.CastSpeed, 1, 1); - break; - case 6: - ApplyAttribute(primary, min, max, AosAttribute.CastRecovery, 1, 3); - break; - case 7: - ApplyAttribute(primary, min, max, AosAttribute.SpellDamage, 1, 12); - break; - case 8: - ApplySkillBonus(skills, min, max, 0, 1, 15); - break; - case 9: - ApplySkillBonus(skills, min, max, 1, 1, 15); - break; - case 10: - ApplySkillBonus(skills, min, max, 2, 1, 15); - break; - case 11: - ApplySkillBonus(skills, min, max, 3, 1, 15); - break; - case 12: - ApplyAttribute(primary, min, max, AosAttribute.LowerRegCost, 1, 20); - break; - case 13: - ApplyAttribute(primary, min, max, AosAttribute.LowerManaCost, 1, 8); - break; - case 14: - ApplyAttribute(primary, min, max, AosAttribute.RegenMana, 1, 2); - break; - case 15: - spellbook.Slayer = GetRandomSlayer(); - break; } - } } - } } diff --git a/Projects/UOContent/Items/Skill Items/Tools/BaseTool.cs b/Projects/UOContent/Items/Skill Items/Tools/BaseTool.cs index 3b5db4eae..df136fa8c 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/BaseTool.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/BaseTool.cs @@ -4,202 +4,204 @@ using Server.Network; namespace Server.Items { - public enum ToolQuality - { - Low, - Regular, - Exceptional - } - - public abstract class BaseTool : Item, IUsesRemaining, ICraftable - { - private Mobile m_Crafter; - private ToolQuality m_Quality; - private int m_UsesRemaining; - - public BaseTool(int itemID) : this(Utility.RandomMinMax(25, 75), itemID) + public enum ToolQuality { + Low, + Regular, + Exceptional } - public BaseTool(int uses, int itemID) : base(itemID) + public abstract class BaseTool : Item, IUsesRemaining, ICraftable { - m_UsesRemaining = uses; - m_Quality = ToolQuality.Regular; + private Mobile m_Crafter; + private ToolQuality m_Quality; + private int m_UsesRemaining; + + public BaseTool(int itemID) : this(Utility.RandomMinMax(25, 75), itemID) + { + } + + public BaseTool(int uses, int itemID) : base(itemID) + { + m_UsesRemaining = uses; + m_Quality = ToolQuality.Regular; + } + + public BaseTool(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Crafter + { + get => m_Crafter; + set + { + m_Crafter = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public ToolQuality Quality + { + get => m_Quality; + set + { + UnscaleUses(); + m_Quality = value; + InvalidateProperties(); + ScaleUses(); + } + } + + public virtual bool BreakOnDepletion => true; + + public abstract CraftSystem CraftSystem { get; } + + private bool ShowUsesRemaining { get; set; } = true; + + public int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, + CraftItem craftItem, int resHue + ) + { + Quality = (ToolQuality)quality; + + if (makersMark) + Crafter = from; + + return quality; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int UsesRemaining + { + get => m_UsesRemaining; + set + { + m_UsesRemaining = value; + InvalidateProperties(); + } + } + + bool IUsesRemaining.ShowUsesRemaining + { + get => ShowUsesRemaining; + set => ShowUsesRemaining = value; + } + + public void ScaleUses() + { + m_UsesRemaining = m_UsesRemaining * GetUsesScalar() / 100; + InvalidateProperties(); + } + + public void UnscaleUses() + { + m_UsesRemaining = m_UsesRemaining * 100 / GetUsesScalar(); + } + + public int GetUsesScalar() + { + if (m_Quality == ToolQuality.Exceptional) + return 200; + + return 100; + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + // Makers mark not displayed on OSI + // if (m_Crafter != null) + // list.Add( 1050043, m_Crafter.Name ); // crafted by ~1_NAME~ + + if (m_Quality == ToolQuality.Exceptional) + list.Add(1060636); // exceptional + + list.Add(1060584, m_UsesRemaining.ToString()); // uses remaining: ~1_val~ + } + + public virtual void DisplayDurabilityTo(Mobile m) + { + LabelToAffix(m, 1017323, AffixType.Append, $": {m_UsesRemaining}"); // Durability + } + + public static bool CheckAccessible(Item tool, Mobile m) => tool.IsChildOf(m) || tool.Parent == m; + + public static bool CheckTool(Item tool, Mobile m) + { + var check = m.FindItemOnLayer(Layer.OneHanded); + + if (check is BaseTool && check != tool && !(check is AncientSmithyHammer)) + return false; + + check = m.FindItemOnLayer(Layer.TwoHanded); + + return !(check is BaseTool) || check == tool || check is AncientSmithyHammer; + } + + public override void OnSingleClick(Mobile from) + { + DisplayDurabilityTo(from); + + base.OnSingleClick(from); + } + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack) || Parent == from) + { + var system = CraftSystem; + + var num = system.CanCraft(from, this, null); + + // Blacksmithing shows the gump regardless of proximity of an anvil and forge after SE + if (num > 0 && (num != 1044267 || !Core.SE)) + from.SendLocalizedMessage(num); + else + from.SendGump(new CraftGump(from, system, this, null)); + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(m_Crafter); + writer.Write((int)m_Quality); + + writer.Write(m_UsesRemaining); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_Crafter = reader.ReadMobile(); + m_Quality = (ToolQuality)reader.ReadInt(); + goto case 0; + } + case 0: + { + m_UsesRemaining = reader.ReadInt(); + break; + } + } + } } - - public BaseTool(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Crafter - { - get => m_Crafter; - set - { - m_Crafter = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public ToolQuality Quality - { - get => m_Quality; - set - { - UnscaleUses(); - m_Quality = value; - InvalidateProperties(); - ScaleUses(); - } - } - - public virtual bool BreakOnDepletion => true; - - public abstract CraftSystem CraftSystem { get; } - - public int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, - CraftItem craftItem, int resHue) - { - Quality = (ToolQuality)quality; - - if (makersMark) - Crafter = from; - - return quality; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int UsesRemaining - { - get => m_UsesRemaining; - set - { - m_UsesRemaining = value; - InvalidateProperties(); - } - } - - private bool ShowUsesRemaining { get; set; } = true; - - bool IUsesRemaining.ShowUsesRemaining - { - get => ShowUsesRemaining; - set => ShowUsesRemaining = value; - } - - public void ScaleUses() - { - m_UsesRemaining = m_UsesRemaining * GetUsesScalar() / 100; - InvalidateProperties(); - } - - public void UnscaleUses() - { - m_UsesRemaining = m_UsesRemaining * 100 / GetUsesScalar(); - } - - public int GetUsesScalar() - { - if (m_Quality == ToolQuality.Exceptional) - return 200; - - return 100; - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - // Makers mark not displayed on OSI - // if (m_Crafter != null) - // list.Add( 1050043, m_Crafter.Name ); // crafted by ~1_NAME~ - - if (m_Quality == ToolQuality.Exceptional) - list.Add(1060636); // exceptional - - list.Add(1060584, m_UsesRemaining.ToString()); // uses remaining: ~1_val~ - } - - public virtual void DisplayDurabilityTo(Mobile m) - { - LabelToAffix(m, 1017323, AffixType.Append, $": {m_UsesRemaining}"); // Durability - } - - public static bool CheckAccessible(Item tool, Mobile m) => tool.IsChildOf(m) || tool.Parent == m; - - public static bool CheckTool(Item tool, Mobile m) - { - Item check = m.FindItemOnLayer(Layer.OneHanded); - - if (check is BaseTool && check != tool && !(check is AncientSmithyHammer)) - return false; - - check = m.FindItemOnLayer(Layer.TwoHanded); - - return !(check is BaseTool) || check == tool || check is AncientSmithyHammer; - } - - public override void OnSingleClick(Mobile from) - { - DisplayDurabilityTo(from); - - base.OnSingleClick(from); - } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack) || Parent == from) - { - CraftSystem system = CraftSystem; - - int num = system.CanCraft(from, this, null); - - // Blacksmithing shows the gump regardless of proximity of an anvil and forge after SE - if (num > 0 && (num != 1044267 || !Core.SE)) - from.SendLocalizedMessage(num); - else - from.SendGump(new CraftGump(from, system, this, null)); - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(m_Crafter); - writer.Write((int)m_Quality); - - writer.Write(m_UsesRemaining); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_Crafter = reader.ReadMobile(); - m_Quality = (ToolQuality)reader.ReadInt(); - goto case 0; - } - case 0: - { - m_UsesRemaining = reader.ReadInt(); - break; - } - } - } - } } diff --git a/Projects/UOContent/Items/Skill Items/Tools/Blowpipe.cs b/Projects/UOContent/Items/Skill Items/Tools/Blowpipe.cs index b6a962c60..a12635218 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/Blowpipe.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/Blowpipe.cs @@ -2,46 +2,46 @@ using Server.Engines.Craft; namespace Server.Items { - [Flippable(0xE8A, 0xE89)] - public class Blowpipe : BaseTool - { - [Constructible] - public Blowpipe() : base(0xE8A) + [Flippable(0xE8A, 0xE89)] + public class Blowpipe : BaseTool { - Weight = 4.0; - Hue = 0x3B9; + [Constructible] + public Blowpipe() : base(0xE8A) + { + Weight = 4.0; + Hue = 0x3B9; + } + + [Constructible] + public Blowpipe(int uses) : base(uses, 0xE8A) + { + Weight = 4.0; + Hue = 0x3B9; + } + + public Blowpipe(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefGlassblowing.CraftSystem; + + public override int LabelNumber => 1044608; // blow pipe + + 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 (Weight == 2.0) + Weight = 4.0; + } } - - [Constructible] - public Blowpipe(int uses) : base(uses, 0xE8A) - { - Weight = 4.0; - Hue = 0x3B9; - } - - public Blowpipe(Serial serial) : base(serial) - { - } - - public override CraftSystem CraftSystem => DefGlassblowing.CraftSystem; - - public override int LabelNumber => 1044608; // blow pipe - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 2.0) - Weight = 4.0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/DovetailSaw.cs b/Projects/UOContent/Items/Skill Items/Tools/DovetailSaw.cs index e5a69ca10..ace0e56da 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/DovetailSaw.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/DovetailSaw.cs @@ -2,36 +2,36 @@ using Server.Engines.Craft; namespace Server.Items { - [Flippable(0x1028, 0x1029)] - public class DovetailSaw : BaseTool - { - [Constructible] - public DovetailSaw() : base(0x1028) => Weight = 2.0; - - [Constructible] - public DovetailSaw(int uses) : base(uses, 0x1028) => Weight = 2.0; - - public DovetailSaw(Serial serial) : base(serial) + [Flippable(0x1028, 0x1029)] + public class DovetailSaw : BaseTool { + [Constructible] + public DovetailSaw() : base(0x1028) => Weight = 2.0; + + [Constructible] + public DovetailSaw(int uses) : base(uses, 0x1028) => Weight = 2.0; + + public DovetailSaw(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefCarpentry.CraftSystem; + + 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 (Weight == 1.0) + Weight = 2.0; + } } - - public override CraftSystem CraftSystem => DefCarpentry.CraftSystem; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 2.0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/DrawKnife.cs b/Projects/UOContent/Items/Skill Items/Tools/DrawKnife.cs index 13f9275cc..ad1fc9530 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/DrawKnife.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/DrawKnife.cs @@ -2,32 +2,32 @@ using Server.Engines.Craft; namespace Server.Items { - public class DrawKnife : BaseTool - { - [Constructible] - public DrawKnife() : base(0x10E4) => Weight = 1.0; - - [Constructible] - public DrawKnife(int uses) : base(uses, 0x10E4) => Weight = 1.0; - - public DrawKnife(Serial serial) : base(serial) + public class DrawKnife : BaseTool { + [Constructible] + public DrawKnife() : base(0x10E4) => Weight = 1.0; + + [Constructible] + public DrawKnife(int uses) : base(uses, 0x10E4) => Weight = 1.0; + + public DrawKnife(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefCarpentry.CraftSystem; + + 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 CraftSystem CraftSystem => DefCarpentry.CraftSystem; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/FletcherTools.cs b/Projects/UOContent/Items/Skill Items/Tools/FletcherTools.cs index 48f077fbe..5fb1f0470 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/FletcherTools.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/FletcherTools.cs @@ -2,36 +2,36 @@ using Server.Engines.Craft; namespace Server.Items { - [Flippable(0x1022, 0x1023)] - public class FletcherTools : BaseTool - { - [Constructible] - public FletcherTools() : base(0x1022) => Weight = 2.0; - - [Constructible] - public FletcherTools(int uses) : base(uses, 0x1022) => Weight = 2.0; - - public FletcherTools(Serial serial) : base(serial) + [Flippable(0x1022, 0x1023)] + public class FletcherTools : BaseTool { + [Constructible] + public FletcherTools() : base(0x1022) => Weight = 2.0; + + [Constructible] + public FletcherTools(int uses) : base(uses, 0x1022) => Weight = 2.0; + + public FletcherTools(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefBowFletching.CraftSystem; + + 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 (Weight == 1.0) + Weight = 2.0; + } } - - public override CraftSystem CraftSystem => DefBowFletching.CraftSystem; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 2.0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/FlourSifter.cs b/Projects/UOContent/Items/Skill Items/Tools/FlourSifter.cs index 524810a2e..a90eb6666 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/FlourSifter.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/FlourSifter.cs @@ -2,32 +2,32 @@ using Server.Engines.Craft; namespace Server.Items { - public class FlourSifter : BaseTool - { - [Constructible] - public FlourSifter() : base(0x103E) => Weight = 1.0; - - [Constructible] - public FlourSifter(int uses) : base(uses, 0x103E) => Weight = 1.0; - - public FlourSifter(Serial serial) : base(serial) + public class FlourSifter : BaseTool { + [Constructible] + public FlourSifter() : base(0x103E) => Weight = 1.0; + + [Constructible] + public FlourSifter(int uses) : base(uses, 0x103E) => Weight = 1.0; + + public FlourSifter(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefCooking.CraftSystem; + + 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 CraftSystem CraftSystem => DefCooking.CraftSystem; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/Froe.cs b/Projects/UOContent/Items/Skill Items/Tools/Froe.cs index b21692746..a5712d873 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/Froe.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/Froe.cs @@ -2,32 +2,32 @@ using Server.Engines.Craft; namespace Server.Items { - public class Froe : BaseTool - { - [Constructible] - public Froe() : base(0x10E5) => Weight = 1.0; - - [Constructible] - public Froe(int uses) : base(uses, 0x10E5) => Weight = 1.0; - - public Froe(Serial serial) : base(serial) + public class Froe : BaseTool { + [Constructible] + public Froe() : base(0x10E5) => Weight = 1.0; + + [Constructible] + public Froe(int uses) : base(uses, 0x10E5) => Weight = 1.0; + + public Froe(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefCarpentry.CraftSystem; + + 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 CraftSystem CraftSystem => DefCarpentry.CraftSystem; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/Hammer.cs b/Projects/UOContent/Items/Skill Items/Tools/Hammer.cs index 457e0b4c7..07677e822 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/Hammer.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/Hammer.cs @@ -2,32 +2,32 @@ using Server.Engines.Craft; namespace Server.Items { - public class Hammer : BaseTool - { - [Constructible] - public Hammer() : base(0x102A) => Weight = 2.0; - - [Constructible] - public Hammer(int uses) : base(uses, 0x102A) => Weight = 2.0; - - public Hammer(Serial serial) : base(serial) + public class Hammer : BaseTool { + [Constructible] + public Hammer() : base(0x102A) => Weight = 2.0; + + [Constructible] + public Hammer(int uses) : base(uses, 0x102A) => Weight = 2.0; + + public Hammer(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefCarpentry.CraftSystem; + + 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 CraftSystem CraftSystem => DefCarpentry.CraftSystem; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/Inshave.cs b/Projects/UOContent/Items/Skill Items/Tools/Inshave.cs index 71bd64358..7f57af098 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/Inshave.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/Inshave.cs @@ -2,32 +2,32 @@ using Server.Engines.Craft; namespace Server.Items { - public class Inshave : BaseTool - { - [Constructible] - public Inshave() : base(0x10E6) => Weight = 1.0; - - [Constructible] - public Inshave(int uses) : base(uses, 0x10E6) => Weight = 1.0; - - public Inshave(Serial serial) : base(serial) + public class Inshave : BaseTool { + [Constructible] + public Inshave() : base(0x10E6) => Weight = 1.0; + + [Constructible] + public Inshave(int uses) : base(uses, 0x10E6) => Weight = 1.0; + + public Inshave(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefCarpentry.CraftSystem; + + 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 CraftSystem CraftSystem => DefCarpentry.CraftSystem; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/JointingPlane.cs b/Projects/UOContent/Items/Skill Items/Tools/JointingPlane.cs index 5797c7d13..eb738294a 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/JointingPlane.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/JointingPlane.cs @@ -2,36 +2,36 @@ using Server.Engines.Craft; namespace Server.Items { - [Flippable(0x1030, 0x1031)] - public class JointingPlane : BaseTool - { - [Constructible] - public JointingPlane() : base(0x1030) => Weight = 2.0; - - [Constructible] - public JointingPlane(int uses) : base(uses, 0x1030) => Weight = 2.0; - - public JointingPlane(Serial serial) : base(serial) + [Flippable(0x1030, 0x1031)] + public class JointingPlane : BaseTool { + [Constructible] + public JointingPlane() : base(0x1030) => Weight = 2.0; + + [Constructible] + public JointingPlane(int uses) : base(uses, 0x1030) => Weight = 2.0; + + public JointingPlane(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefCarpentry.CraftSystem; + + 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 (Weight == 1.0) + Weight = 2.0; + } } - - public override CraftSystem CraftSystem => DefCarpentry.CraftSystem; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 2.0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/MalletAndChisel.cs b/Projects/UOContent/Items/Skill Items/Tools/MalletAndChisel.cs index 7363dd5a5..d0e7d7721 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/MalletAndChisel.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/MalletAndChisel.cs @@ -2,32 +2,32 @@ using Server.Engines.Craft; namespace Server.Items { - public class MalletAndChisel : BaseTool - { - [Constructible] - public MalletAndChisel() : base(0x12B3) => Weight = 1.0; - - [Constructible] - public MalletAndChisel(int uses) : base(uses, 0x12B3) => Weight = 1.0; - - public MalletAndChisel(Serial serial) : base(serial) + public class MalletAndChisel : BaseTool { + [Constructible] + public MalletAndChisel() : base(0x12B3) => Weight = 1.0; + + [Constructible] + public MalletAndChisel(int uses) : base(uses, 0x12B3) => Weight = 1.0; + + public MalletAndChisel(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefMasonry.CraftSystem; + + 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 CraftSystem CraftSystem => DefMasonry.CraftSystem; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/MapmakersPen.cs b/Projects/UOContent/Items/Skill Items/Tools/MapmakersPen.cs index 9ece16636..b5457b37a 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/MapmakersPen.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/MapmakersPen.cs @@ -2,38 +2,38 @@ using Server.Engines.Craft; namespace Server.Items { - [Flippable(0x0FBF, 0x0FC0)] - public class MapmakersPen : BaseTool - { - [Constructible] - public MapmakersPen() : base(0x0FBF) => Weight = 1.0; - - [Constructible] - public MapmakersPen(int uses) : base(uses, 0x0FBF) => Weight = 1.0; - - public MapmakersPen(Serial serial) : base(serial) + [Flippable(0x0FBF, 0x0FC0)] + public class MapmakersPen : BaseTool { + [Constructible] + public MapmakersPen() : base(0x0FBF) => Weight = 1.0; + + [Constructible] + public MapmakersPen(int uses) : base(uses, 0x0FBF) => Weight = 1.0; + + public MapmakersPen(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefCartography.CraftSystem; + + public override int LabelNumber => 1044167; // mapmaker's pen + + 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 (Weight == 2.0) + Weight = 1.0; + } } - - public override CraftSystem CraftSystem => DefCartography.CraftSystem; - - public override int LabelNumber => 1044167; // mapmaker's pen - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 2.0) - Weight = 1.0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/MortarPestle.cs b/Projects/UOContent/Items/Skill Items/Tools/MortarPestle.cs index 32f0f2f2c..646bd2e89 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/MortarPestle.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/MortarPestle.cs @@ -2,32 +2,32 @@ using Server.Engines.Craft; namespace Server.Items { - public class MortarPestle : BaseTool - { - [Constructible] - public MortarPestle() : base(0xE9B) => Weight = 1.0; - - [Constructible] - public MortarPestle(int uses) : base(uses, 0xE9B) => Weight = 1.0; - - public MortarPestle(Serial serial) : base(serial) + public class MortarPestle : BaseTool { + [Constructible] + public MortarPestle() : base(0xE9B) => Weight = 1.0; + + [Constructible] + public MortarPestle(int uses) : base(uses, 0xE9B) => Weight = 1.0; + + public MortarPestle(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefAlchemy.CraftSystem; + + 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 CraftSystem CraftSystem => DefAlchemy.CraftSystem; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/MouldingPlane.cs b/Projects/UOContent/Items/Skill Items/Tools/MouldingPlane.cs index a5b573b0c..cf3415bb0 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/MouldingPlane.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/MouldingPlane.cs @@ -2,33 +2,33 @@ using Server.Engines.Craft; namespace Server.Items { - [Flippable(0x102C, 0x102D)] - public class MouldingPlane : BaseTool - { - [Constructible] - public MouldingPlane() : base(0x102C) => Weight = 2.0; - - [Constructible] - public MouldingPlane(int uses) : base(uses, 0x102C) => Weight = 2.0; - - public MouldingPlane(Serial serial) : base(serial) + [Flippable(0x102C, 0x102D)] + public class MouldingPlane : BaseTool { + [Constructible] + public MouldingPlane() : base(0x102C) => Weight = 2.0; + + [Constructible] + public MouldingPlane(int uses) : base(uses, 0x102C) => Weight = 2.0; + + public MouldingPlane(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefCarpentry.CraftSystem; + + 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 CraftSystem CraftSystem => DefCarpentry.CraftSystem; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/Nails.cs b/Projects/UOContent/Items/Skill Items/Tools/Nails.cs index 15f43f2d6..667514953 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/Nails.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/Nails.cs @@ -2,33 +2,33 @@ using Server.Engines.Craft; namespace Server.Items { - [Flippable(0x102E, 0x102F)] - public class Nails : BaseTool - { - [Constructible] - public Nails() : base(0x102E) => Weight = 2.0; - - [Constructible] - public Nails(int uses) : base(uses, 0x102C) => Weight = 2.0; - - public Nails(Serial serial) : base(serial) + [Flippable(0x102E, 0x102F)] + public class Nails : BaseTool { + [Constructible] + public Nails() : base(0x102E) => Weight = 2.0; + + [Constructible] + public Nails(int uses) : base(uses, 0x102C) => Weight = 2.0; + + public Nails(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefCarpentry.CraftSystem; + + 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 CraftSystem CraftSystem => DefCarpentry.CraftSystem; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/RollingPin.cs b/Projects/UOContent/Items/Skill Items/Tools/RollingPin.cs index 029a9afff..4d75f15a8 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/RollingPin.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/RollingPin.cs @@ -2,32 +2,32 @@ using Server.Engines.Craft; namespace Server.Items { - public class RollingPin : BaseTool - { - [Constructible] - public RollingPin() : base(0x1043) => Weight = 1.0; - - [Constructible] - public RollingPin(int uses) : base(uses, 0x1043) => Weight = 1.0; - - public RollingPin(Serial serial) : base(serial) + public class RollingPin : BaseTool { + [Constructible] + public RollingPin() : base(0x1043) => Weight = 1.0; + + [Constructible] + public RollingPin(int uses) : base(uses, 0x1043) => Weight = 1.0; + + public RollingPin(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefCooking.CraftSystem; + + 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 CraftSystem CraftSystem => DefCooking.CraftSystem; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/RunicDovetailSaw.cs b/Projects/UOContent/Items/Skill Items/Tools/RunicDovetailSaw.cs index 83861b832..a55a30e79 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/RunicDovetailSaw.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/RunicDovetailSaw.cs @@ -2,53 +2,53 @@ using Server.Engines.Craft; namespace Server.Items { - public class RunicDovetailSaw : BaseRunicTool - { - [Constructible] - public RunicDovetailSaw(CraftResource resource) : base(resource, 0x1028) + public class RunicDovetailSaw : BaseRunicTool { - Weight = 2.0; - Hue = CraftResources.GetHue(resource); + [Constructible] + public RunicDovetailSaw(CraftResource resource) : base(resource, 0x1028) + { + Weight = 2.0; + Hue = CraftResources.GetHue(resource); + } + + [Constructible] + public RunicDovetailSaw(CraftResource resource, int uses) : base(resource, uses, 0x1028) + { + Weight = 2.0; + Hue = CraftResources.GetHue(resource); + } + + public RunicDovetailSaw(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefCarpentry.CraftSystem; + + public override int LabelNumber + { + get + { + var index = CraftResources.GetIndex(Resource); + + if (index >= 1 && index <= 6) + return 1072633 + index; + + return 1024137; // dovetail saw + } + } + + 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(); + } } - - [Constructible] - public RunicDovetailSaw(CraftResource resource, int uses) : base(resource, uses, 0x1028) - { - Weight = 2.0; - Hue = CraftResources.GetHue(resource); - } - - public RunicDovetailSaw(Serial serial) : base(serial) - { - } - - public override CraftSystem CraftSystem => DefCarpentry.CraftSystem; - - public override int LabelNumber - { - get - { - int index = CraftResources.GetIndex(Resource); - - if (index >= 1 && index <= 6) - return 1072633 + index; - - return 1024137; // dovetail saw - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/RunicFletcherTool.cs b/Projects/UOContent/Items/Skill Items/Tools/RunicFletcherTool.cs index d346214ca..6c0da7872 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/RunicFletcherTool.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/RunicFletcherTool.cs @@ -2,53 +2,53 @@ using Server.Engines.Craft; namespace Server.Items { - public class RunicFletcherTool : BaseRunicTool - { - [Constructible] - public RunicFletcherTool(CraftResource resource) : base(resource, 0x1022) + public class RunicFletcherTool : BaseRunicTool { - Weight = 2.0; - Hue = CraftResources.GetHue(resource); + [Constructible] + public RunicFletcherTool(CraftResource resource) : base(resource, 0x1022) + { + Weight = 2.0; + Hue = CraftResources.GetHue(resource); + } + + [Constructible] + public RunicFletcherTool(CraftResource resource, int uses) : base(resource, uses, 0x1022) + { + Weight = 2.0; + Hue = CraftResources.GetHue(resource); + } + + public RunicFletcherTool(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefBowFletching.CraftSystem; + + public override int LabelNumber + { + get + { + var index = CraftResources.GetIndex(Resource); + + if (index >= 1 && index <= 6) + return 1072627 + index; + + return 1044559; // Fletcher's Tools + } + } + + 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(); + } } - - [Constructible] - public RunicFletcherTool(CraftResource resource, int uses) : base(resource, uses, 0x1022) - { - Weight = 2.0; - Hue = CraftResources.GetHue(resource); - } - - public RunicFletcherTool(Serial serial) : base(serial) - { - } - - public override CraftSystem CraftSystem => DefBowFletching.CraftSystem; - - public override int LabelNumber - { - get - { - int index = CraftResources.GetIndex(Resource); - - if (index >= 1 && index <= 6) - return 1072627 + index; - - return 1044559; // Fletcher's Tools - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/RunicHammer.cs b/Projects/UOContent/Items/Skill Items/Tools/RunicHammer.cs index 648f523aa..9316816de 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/RunicHammer.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/RunicHammer.cs @@ -2,76 +2,76 @@ using Server.Engines.Craft; namespace Server.Items { - [Flippable(0x13E4, 0x13E3)] - public class RunicHammer : BaseRunicTool - { - [Constructible] - public RunicHammer(CraftResource resource) : base(resource, 0x13E3) + [Flippable(0x13E4, 0x13E3)] + public class RunicHammer : BaseRunicTool { - Weight = 8.0; - Layer = Layer.OneHanded; - Hue = CraftResources.GetHue(resource); + [Constructible] + public RunicHammer(CraftResource resource) : base(resource, 0x13E3) + { + Weight = 8.0; + Layer = Layer.OneHanded; + Hue = CraftResources.GetHue(resource); + } + + [Constructible] + public RunicHammer(CraftResource resource, int uses) : base(resource, uses, 0x13E3) + { + Weight = 8.0; + Layer = Layer.OneHanded; + Hue = CraftResources.GetHue(resource); + } + + public RunicHammer(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefBlacksmithy.CraftSystem; + + public override int LabelNumber + { + get + { + var index = CraftResources.GetIndex(Resource); + + if (index >= 1 && index <= 8) + return 1049019 + index; + + return 1045128; // runic smithy hammer + } + } + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + var index = CraftResources.GetIndex(Resource); + + if (index >= 1 && index <= 8) + return; + + if (!CraftResources.IsStandard(Resource)) + { + var num = CraftResources.GetLocalizationNumber(Resource); + + if (num > 0) + list.Add(num); + else + list.Add(CraftResources.GetName(Resource)); + } + } + + 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(); + } } - - [Constructible] - public RunicHammer(CraftResource resource, int uses) : base(resource, uses, 0x13E3) - { - Weight = 8.0; - Layer = Layer.OneHanded; - Hue = CraftResources.GetHue(resource); - } - - public RunicHammer(Serial serial) : base(serial) - { - } - - public override CraftSystem CraftSystem => DefBlacksmithy.CraftSystem; - - public override int LabelNumber - { - get - { - int index = CraftResources.GetIndex(Resource); - - if (index >= 1 && index <= 8) - return 1049019 + index; - - return 1045128; // runic smithy hammer - } - } - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - int index = CraftResources.GetIndex(Resource); - - if (index >= 1 && index <= 8) - return; - - if (!CraftResources.IsStandard(Resource)) - { - int num = CraftResources.GetLocalizationNumber(Resource); - - if (num > 0) - list.Add(num); - else - list.Add(CraftResources.GetName(Resource)); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/RunicSewingKit.cs b/Projects/UOContent/Items/Skill Items/Tools/RunicSewingKit.cs index 586104e58..fad8d69f8 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/RunicSewingKit.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/RunicSewingKit.cs @@ -2,77 +2,77 @@ using Server.Engines.Craft; namespace Server.Items { - public class RunicSewingKit : BaseRunicTool - { - [Constructible] - public RunicSewingKit(CraftResource resource) : base(resource, 0xF9D) + public class RunicSewingKit : BaseRunicTool { - Weight = 2.0; - Hue = CraftResources.GetHue(resource); + [Constructible] + public RunicSewingKit(CraftResource resource) : base(resource, 0xF9D) + { + Weight = 2.0; + Hue = CraftResources.GetHue(resource); + } + + [Constructible] + public RunicSewingKit(CraftResource resource, int uses) : base(resource, uses, 0xF9D) + { + Weight = 2.0; + Hue = CraftResources.GetHue(resource); + } + + public RunicSewingKit(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefTailoring.CraftSystem; + + public override void AddNameProperty(ObjectPropertyList list) + { + var v = " "; + + if (!CraftResources.IsStandard(Resource)) + { + var num = CraftResources.GetLocalizationNumber(Resource); + + if (num > 0) + v = $"#{num}"; + else + v = CraftResources.GetName(Resource); + } + + list.Add(1061119, v); // ~1_LEATHER_TYPE~ runic sewing kit + } + + public override void OnSingleClick(Mobile from) + { + var v = " "; + + if (!CraftResources.IsStandard(Resource)) + { + var num = CraftResources.GetLocalizationNumber(Resource); + + if (num > 0) + v = $"#{num}"; + else + v = CraftResources.GetName(Resource); + } + + LabelTo(from, 1061119, v); // ~1_LEATHER_TYPE~ runic sewing kit + } + + 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 (ItemID == 0x13E4 || ItemID == 0x13E3) + ItemID = 0xF9D; + } } - - [Constructible] - public RunicSewingKit(CraftResource resource, int uses) : base(resource, uses, 0xF9D) - { - Weight = 2.0; - Hue = CraftResources.GetHue(resource); - } - - public RunicSewingKit(Serial serial) : base(serial) - { - } - - public override CraftSystem CraftSystem => DefTailoring.CraftSystem; - - public override void AddNameProperty(ObjectPropertyList list) - { - string v = " "; - - if (!CraftResources.IsStandard(Resource)) - { - int num = CraftResources.GetLocalizationNumber(Resource); - - if (num > 0) - v = $"#{num}"; - else - v = CraftResources.GetName(Resource); - } - - list.Add(1061119, v); // ~1_LEATHER_TYPE~ runic sewing kit - } - - public override void OnSingleClick(Mobile from) - { - string v = " "; - - if (!CraftResources.IsStandard(Resource)) - { - int num = CraftResources.GetLocalizationNumber(Resource); - - if (num > 0) - v = $"#{num}"; - else - v = CraftResources.GetName(Resource); - } - - LabelTo(from, 1061119, v); // ~1_LEATHER_TYPE~ runic sewing kit - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (ItemID == 0x13E4 || ItemID == 0x13E3) - ItemID = 0xF9D; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/Saw.cs b/Projects/UOContent/Items/Skill Items/Tools/Saw.cs index 4c3998652..959361537 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/Saw.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/Saw.cs @@ -2,33 +2,33 @@ using Server.Engines.Craft; namespace Server.Items { - [Flippable(0x1034, 0x1035)] - public class Saw : BaseTool - { - [Constructible] - public Saw() : base(0x1034) => Weight = 2.0; - - [Constructible] - public Saw(int uses) : base(uses, 0x1034) => Weight = 2.0; - - public Saw(Serial serial) : base(serial) + [Flippable(0x1034, 0x1035)] + public class Saw : BaseTool { + [Constructible] + public Saw() : base(0x1034) => Weight = 2.0; + + [Constructible] + public Saw(int uses) : base(uses, 0x1034) => Weight = 2.0; + + public Saw(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefCarpentry.CraftSystem; + + 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 CraftSystem CraftSystem => DefCarpentry.CraftSystem; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/Scorp.cs b/Projects/UOContent/Items/Skill Items/Tools/Scorp.cs index c338ee92b..30b0ba37f 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/Scorp.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/Scorp.cs @@ -2,32 +2,32 @@ using Server.Engines.Craft; namespace Server.Items { - public class Scorp : BaseTool - { - [Constructible] - public Scorp() : base(0x10E7) => Weight = 1.0; - - [Constructible] - public Scorp(int uses) : base(uses, 0x10E7) => Weight = 1.0; - - public Scorp(Serial serial) : base(serial) + public class Scorp : BaseTool { + [Constructible] + public Scorp() : base(0x10E7) => Weight = 1.0; + + [Constructible] + public Scorp(int uses) : base(uses, 0x10E7) => Weight = 1.0; + + public Scorp(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefCarpentry.CraftSystem; + + 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 CraftSystem CraftSystem => DefCarpentry.CraftSystem; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/ScribesPen.cs b/Projects/UOContent/Items/Skill Items/Tools/ScribesPen.cs index e1a77d53f..ebc392657 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/ScribesPen.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/ScribesPen.cs @@ -2,38 +2,38 @@ using Server.Engines.Craft; namespace Server.Items { - [Flippable(0x0FBF, 0x0FC0)] - public class ScribesPen : BaseTool - { - [Constructible] - public ScribesPen() : base(0x0FBF) => Weight = 1.0; - - [Constructible] - public ScribesPen(int uses) : base(uses, 0x0FBF) => Weight = 1.0; - - public ScribesPen(Serial serial) : base(serial) + [Flippable(0x0FBF, 0x0FC0)] + public class ScribesPen : BaseTool { + [Constructible] + public ScribesPen() : base(0x0FBF) => Weight = 1.0; + + [Constructible] + public ScribesPen(int uses) : base(uses, 0x0FBF) => Weight = 1.0; + + public ScribesPen(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefInscription.CraftSystem; + + public override int LabelNumber => 1044168; // scribe's pen + + 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 (Weight == 2.0) + Weight = 1.0; + } } - - public override CraftSystem CraftSystem => DefInscription.CraftSystem; - - public override int LabelNumber => 1044168; // scribe's pen - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 2.0) - Weight = 1.0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/SewingKit.cs b/Projects/UOContent/Items/Skill Items/Tools/SewingKit.cs index 0035a484b..2925c422a 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/SewingKit.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/SewingKit.cs @@ -2,32 +2,32 @@ using Server.Engines.Craft; namespace Server.Items { - public class SewingKit : BaseTool - { - [Constructible] - public SewingKit() : base(0xF9D) => Weight = 2.0; - - [Constructible] - public SewingKit(int uses) : base(uses, 0xF9D) => Weight = 2.0; - - public SewingKit(Serial serial) : base(serial) + public class SewingKit : BaseTool { + [Constructible] + public SewingKit() : base(0xF9D) => Weight = 2.0; + + [Constructible] + public SewingKit(int uses) : base(uses, 0xF9D) => Weight = 2.0; + + public SewingKit(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefTailoring.CraftSystem; + + 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 CraftSystem CraftSystem => DefTailoring.CraftSystem; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/Skillet.cs b/Projects/UOContent/Items/Skill Items/Tools/Skillet.cs index b513a5939..042d5b2c9 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/Skillet.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/Skillet.cs @@ -2,34 +2,34 @@ using Server.Engines.Craft; namespace Server.Items { - public class Skillet : BaseTool - { - [Constructible] - public Skillet() : base(0x97F) => Weight = 1.0; - - [Constructible] - public Skillet(int uses) : base(uses, 0x97F) => Weight = 1.0; - - public Skillet(Serial serial) : base(serial) + public class Skillet : BaseTool { + [Constructible] + public Skillet() : base(0x97F) => Weight = 1.0; + + [Constructible] + public Skillet(int uses) : base(uses, 0x97F) => Weight = 1.0; + + public Skillet(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1044567; // skillet + + public override CraftSystem CraftSystem => DefCooking.CraftSystem; + + 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 int LabelNumber => 1044567; // skillet - - public override CraftSystem CraftSystem => DefCooking.CraftSystem; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/SledgeHammer.cs b/Projects/UOContent/Items/Skill Items/Tools/SledgeHammer.cs index 79a8af497..e068aec0b 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/SledgeHammer.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/SledgeHammer.cs @@ -2,33 +2,33 @@ using Server.Engines.Craft; namespace Server.Items { - [Flippable(0xFB5, 0xFB4)] - public class SledgeHammer : BaseTool - { - [Constructible] - public SledgeHammer() : base(0xFB5) => Layer = Layer.OneHanded; - - [Constructible] - public SledgeHammer(int uses) : base(uses, 0xFB5) => Layer = Layer.OneHanded; - - public SledgeHammer(Serial serial) : base(serial) + [Flippable(0xFB5, 0xFB4)] + public class SledgeHammer : BaseTool { + [Constructible] + public SledgeHammer() : base(0xFB5) => Layer = Layer.OneHanded; + + [Constructible] + public SledgeHammer(int uses) : base(uses, 0xFB5) => Layer = Layer.OneHanded; + + public SledgeHammer(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefBlacksmithy.CraftSystem; + + 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 CraftSystem CraftSystem => DefBlacksmithy.CraftSystem; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/SmithHammer.cs b/Projects/UOContent/Items/Skill Items/Tools/SmithHammer.cs index 2cd18d53c..e796d167e 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/SmithHammer.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/SmithHammer.cs @@ -2,41 +2,41 @@ using Server.Engines.Craft; namespace Server.Items { - [Flippable(0x13E3, 0x13E4)] - public class SmithHammer : BaseTool - { - [Constructible] - public SmithHammer() : base(0x13E3) + [Flippable(0x13E3, 0x13E4)] + public class SmithHammer : BaseTool { - Weight = 8.0; - Layer = Layer.OneHanded; + [Constructible] + public SmithHammer() : base(0x13E3) + { + Weight = 8.0; + Layer = Layer.OneHanded; + } + + [Constructible] + public SmithHammer(int uses) : base(uses, 0x13E3) + { + Weight = 8.0; + Layer = Layer.OneHanded; + } + + public SmithHammer(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefBlacksmithy.CraftSystem; + + 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(); + } } - - [Constructible] - public SmithHammer(int uses) : base(uses, 0x13E3) - { - Weight = 8.0; - Layer = Layer.OneHanded; - } - - public SmithHammer(Serial serial) : base(serial) - { - } - - public override CraftSystem CraftSystem => DefBlacksmithy.CraftSystem; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/SmoothingPlane.cs b/Projects/UOContent/Items/Skill Items/Tools/SmoothingPlane.cs index ec48034eb..49d29de42 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/SmoothingPlane.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/SmoothingPlane.cs @@ -2,33 +2,33 @@ using Server.Engines.Craft; namespace Server.Items { - [Flippable(0x1032, 0x1033)] - public class SmoothingPlane : BaseTool - { - [Constructible] - public SmoothingPlane() : base(0x1032) => Weight = 1.0; - - [Constructible] - public SmoothingPlane(int uses) : base(uses, 0x1032) => Weight = 1.0; - - public SmoothingPlane(Serial serial) : base(serial) + [Flippable(0x1032, 0x1033)] + public class SmoothingPlane : BaseTool { + [Constructible] + public SmoothingPlane() : base(0x1032) => Weight = 1.0; + + [Constructible] + public SmoothingPlane(int uses) : base(uses, 0x1032) => Weight = 1.0; + + public SmoothingPlane(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefCarpentry.CraftSystem; + + 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 CraftSystem CraftSystem => DefCarpentry.CraftSystem; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/TinkerTools.cs b/Projects/UOContent/Items/Skill Items/Tools/TinkerTools.cs index e0f5d9fc2..4a9b35add 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/TinkerTools.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/TinkerTools.cs @@ -2,67 +2,67 @@ using Server.Engines.Craft; namespace Server.Items { - [Flippable(0x1EB8, 0x1EB9)] - public class TinkerTools : BaseTool - { - [Constructible] - public TinkerTools() : base(0x1EB8) => Weight = 1.0; - - [Constructible] - public TinkerTools(int uses) : base(uses, 0x1EB8) => Weight = 1.0; - - public TinkerTools(Serial serial) : base(serial) + [Flippable(0x1EB8, 0x1EB9)] + public class TinkerTools : BaseTool { + [Constructible] + public TinkerTools() : base(0x1EB8) => Weight = 1.0; + + [Constructible] + public TinkerTools(int uses) : base(uses, 0x1EB8) => Weight = 1.0; + + public TinkerTools(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefTinkering.CraftSystem; + + 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 CraftSystem CraftSystem => DefTinkering.CraftSystem; - - public override void Serialize(IGenericWriter writer) + public class TinkersTools : BaseTool { - base.Serialize(writer); + [Constructible] + public TinkersTools() + : base(0x1EBC) => + Weight = 1.0; - writer.Write(0); // version + [Constructible] + public TinkersTools(int uses) + : base(uses, 0x1EBC) => + Weight = 1.0; + + public TinkersTools(Serial serial) + : base(serial) + { + } + + public override CraftSystem CraftSystem => DefTinkering.CraftSystem; + + 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 Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class TinkersTools : BaseTool - { - [Constructible] - public TinkersTools() - : base(0x1EBC) => - Weight = 1.0; - - [Constructible] - public TinkersTools(int uses) - : base(uses, 0x1EBC) => - Weight = 1.0; - - public TinkersTools(Serial serial) - : base(serial) - { - } - - public override CraftSystem CraftSystem => DefTinkering.CraftSystem; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Skill Items/Tools/Tongs.cs b/Projects/UOContent/Items/Skill Items/Tools/Tongs.cs index 39747705a..7724cf599 100644 --- a/Projects/UOContent/Items/Skill Items/Tools/Tongs.cs +++ b/Projects/UOContent/Items/Skill Items/Tools/Tongs.cs @@ -2,33 +2,33 @@ using Server.Engines.Craft; namespace Server.Items { - [Flippable(0xfbb, 0xfbc)] - public class Tongs : BaseTool - { - [Constructible] - public Tongs() : base(0xFBB) => Weight = 2.0; - - [Constructible] - public Tongs(int uses) : base(uses, 0xFBB) => Weight = 2.0; - - public Tongs(Serial serial) : base(serial) + [Flippable(0xfbb, 0xfbc)] + public class Tongs : BaseTool { + [Constructible] + public Tongs() : base(0xFBB) => Weight = 2.0; + + [Constructible] + public Tongs(int uses) : base(uses, 0xFBB) => Weight = 2.0; + + public Tongs(Serial serial) : base(serial) + { + } + + public override CraftSystem CraftSystem => DefBlacksmithy.CraftSystem; + + 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 CraftSystem CraftSystem => DefBlacksmithy.CraftSystem; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/11th Year promo/EarringsOfProtection.cs b/Projects/UOContent/Items/Special/11th Year promo/EarringsOfProtection.cs index 5d3c86aed..df4fc1540 100644 --- a/Projects/UOContent/Items/Special/11th Year promo/EarringsOfProtection.cs +++ b/Projects/UOContent/Items/Special/11th Year promo/EarringsOfProtection.cs @@ -1,109 +1,109 @@ namespace Server.Items { - public class EarringBoxSet : RedVelvetGiftBox - { - [Constructible] - public EarringBoxSet() + public class EarringBoxSet : RedVelvetGiftBox { - DropItem(new EarringsOfProtection(AosElementAttribute.Physical)); - DropItem(new EarringsOfProtection(AosElementAttribute.Fire)); - DropItem(new EarringsOfProtection(AosElementAttribute.Cold)); - DropItem(new EarringsOfProtection(AosElementAttribute.Poison)); - DropItem(new EarringsOfProtection(AosElementAttribute.Energy)); + [Constructible] + public EarringBoxSet() + { + DropItem(new EarringsOfProtection(AosElementAttribute.Physical)); + DropItem(new EarringsOfProtection(AosElementAttribute.Fire)); + DropItem(new EarringsOfProtection(AosElementAttribute.Cold)); + DropItem(new EarringsOfProtection(AosElementAttribute.Poison)); + DropItem(new EarringsOfProtection(AosElementAttribute.Energy)); + } + + public EarringBoxSet(Serial serial) + : base(serial) + { + } + + 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 EarringBoxSet(Serial serial) - : base(serial) + public class EarringsOfProtection : BaseJewel { + private AosElementAttribute m_Attribute; + + [Constructible] + public EarringsOfProtection() : this(RandomType()) + { + } + + [Constructible] + public EarringsOfProtection(AosElementAttribute element) + : base(0x1087, Layer.Earrings) + { + Resistances[element] = 2; + + m_Attribute = element; + LootType = LootType.Blessed; + } + + public EarringsOfProtection(Serial serial) + : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public virtual AosElementAttribute Attribute => m_Attribute; + + public override int LabelNumber => GetItemData(m_Attribute, true); + + public override int Hue => GetItemData(m_Attribute, false); + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + writer.Write((int)m_Attribute); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + m_Attribute = (AosElementAttribute)reader.ReadInt(); + } + + public static AosElementAttribute RandomType() => GetTypes(Utility.Random(5)); + + public static AosElementAttribute GetTypes(int value) + { + return value switch + { + 0 => AosElementAttribute.Physical, + 1 => AosElementAttribute.Fire, + 2 => AosElementAttribute.Cold, + 3 => AosElementAttribute.Poison, + _ => AosElementAttribute.Energy + }; + } + + public static int GetItemData(AosElementAttribute element, bool label) + { + return element switch + { + AosElementAttribute.Physical => label ? 1071091 : 0, // Earring of Protection (Physical) 1071091 + AosElementAttribute.Fire => label ? 1071092 : 0x4ec, // Earring of Protection (Fire) 1071092 + AosElementAttribute.Cold => label ? 1071093 : 0x4f2, // Earring of Protection (Cold) 1071093 + AosElementAttribute.Poison => label ? 1071094 : 0x4f8, // Earring of Protection (Poison) 1071094 + AosElementAttribute.Energy => label ? 1071095 : 0x4fe, // Earring of Protection (Energy) 1071095 + _ => -1 + }; + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class EarringsOfProtection : BaseJewel - { - private AosElementAttribute m_Attribute; - - [Constructible] - public EarringsOfProtection() : this(RandomType()) - { - } - - [Constructible] - public EarringsOfProtection(AosElementAttribute element) - : base(0x1087, Layer.Earrings) - { - Resistances[element] = 2; - - m_Attribute = element; - LootType = LootType.Blessed; - } - - public EarringsOfProtection(Serial serial) - : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public virtual AosElementAttribute Attribute => m_Attribute; - - public override int LabelNumber => GetItemData(m_Attribute, true); - - public override int Hue => GetItemData(m_Attribute, false); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - writer.Write((int)m_Attribute); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - m_Attribute = (AosElementAttribute)reader.ReadInt(); - } - - public static AosElementAttribute RandomType() => GetTypes(Utility.Random(5)); - - public static AosElementAttribute GetTypes(int value) - { - return value switch - { - 0 => AosElementAttribute.Physical, - 1 => AosElementAttribute.Fire, - 2 => AosElementAttribute.Cold, - 3 => AosElementAttribute.Poison, - _ => AosElementAttribute.Energy - }; - } - - public static int GetItemData(AosElementAttribute element, bool label) - { - return element switch - { - AosElementAttribute.Physical => label ? 1071091 : 0, // Earring of Protection (Physical) 1071091 - AosElementAttribute.Fire => label ? 1071092 : 0x4ec, // Earring of Protection (Fire) 1071092 - AosElementAttribute.Cold => label ? 1071093 : 0x4f2, // Earring of Protection (Cold) 1071093 - AosElementAttribute.Poison => label ? 1071094 : 0x4f8, // Earring of Protection (Poison) 1071094 - AosElementAttribute.Energy => label ? 1071095 : 0x4fe, // Earring of Protection (Energy) 1071095 - _ => -1 - }; - } - } } diff --git a/Projects/UOContent/Items/Special/8th Anniversary Items/Dawn's Music Box/DawnsMusicBox.cs b/Projects/UOContent/Items/Special/8th Anniversary Items/Dawn's Music Box/DawnsMusicBox.cs index 7922d6a36..03b96762e 100644 --- a/Projects/UOContent/Items/Special/8th Anniversary Items/Dawn's Music Box/DawnsMusicBox.cs +++ b/Projects/UOContent/Items/Special/8th Anniversary Items/Dawn's Music Box/DawnsMusicBox.cs @@ -7,302 +7,304 @@ using Server.Network; namespace Server.Items { - public sealed class StopMusic : Packet - { - public static readonly Packet Instance = SetStatic(new StopMusic()); - - public StopMusic() : base(0x6D, 3) + public sealed class StopMusic : Packet { - Stream.Write((short)0x1FFF); - } - } + public static readonly Packet Instance = SetStatic(new StopMusic()); - [Flippable(0x2AF9, 0x2AFD)] - public class DawnsMusicBox : Item, ISecurable - { - private static Dictionary m_Info; - - public static MusicName[] m_CommonTracks = - { - MusicName.Samlethe, MusicName.Sailing, MusicName.Britain2, MusicName.Britain1, - MusicName.Bucsden, MusicName.Forest_a, MusicName.Cove, MusicName.Death, - MusicName.Dungeon9, MusicName.Dungeon2, MusicName.Cave01, MusicName.Combat3, - MusicName.Combat1, MusicName.Combat2, MusicName.Jhelom, MusicName.Linelle, - MusicName.LBCastle, MusicName.Minoc, MusicName.Moonglow, MusicName.Magincia, - MusicName.Nujelm, MusicName.BTCastle, MusicName.Tavern04, MusicName.Skarabra, - MusicName.Stones2, MusicName.Serpents, MusicName.Taiko, MusicName.Tavern01, - MusicName.Tavern02, MusicName.Tavern03, MusicName.TokunoDungeon, MusicName.Trinsic, - MusicName.OldUlt01, MusicName.Ocllo, MusicName.Vesper, MusicName.Victory, - MusicName.Mountn_a, MusicName.Wind, MusicName.Yew, MusicName.Zento - }; - - public static MusicName[] m_UncommonTracks = - { - MusicName.GwennoConversation, MusicName.DreadHornArea, MusicName.ElfCity, - MusicName.GoodEndGame, MusicName.GoodVsEvil, MusicName.GreatEarthSerpents, - MusicName.GrizzleDungeon, MusicName.Humanoids_U9, MusicName.MelisandesLair, - MusicName.MinocNegative, MusicName.ParoxysmusLair, MusicName.Paws - }; - - public static MusicName[] m_RareTracks = - { - MusicName.SelimsBar, MusicName.SerpentIsleCombat_U7, MusicName.ValoriaShips - }; - - private int m_Count; - private int m_ItemID; - - private Timer m_Timer; - - [Constructible] - public DawnsMusicBox() : base(0x2AF9) - { - Weight = 1.0; - - Tracks = new List(); - - while (Tracks.Count < 4) - { - MusicName name = RandomTrack(DawnsMusicRarity.Common); - - if (!Tracks.Contains(name)) - Tracks.Add(name); - } - } - - public DawnsMusicBox(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075198; // Dawn�s Music Box - - public List Tracks { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public SecureLevel Level { get; set; } - - public override void OnAfterDuped(Item newItem) - { - if (!(newItem is DawnsMusicBox box)) - return; - - box.Tracks = new List(); - box.Tracks.AddRange(Tracks); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - int commonSongs = 0; - int uncommonSongs = 0; - int rareSongs = 0; - - for (int i = 0; i < Tracks.Count; i++) - { - DawnsMusicInfo info = GetInfo(Tracks[i]); - - switch (info.Rarity) + public StopMusic() : base(0x6D, 3) { - case DawnsMusicRarity.Common: - commonSongs++; - break; - case DawnsMusicRarity.Uncommon: - uncommonSongs++; - break; - case DawnsMusicRarity.Rare: - rareSongs++; - break; + Stream.Write((short)0x1FFF); } - } - - if (commonSongs > 0) - list.Add(1075234, commonSongs.ToString()); // ~1_NUMBER~ Common Tracks - if (uncommonSongs > 0) - list.Add(1075235, uncommonSongs.ToString()); // ~1_NUMBER~ Uncommon Tracks - if (rareSongs > 0) - list.Add(1075236, rareSongs.ToString()); // ~1_NUMBER~ Rare Tracks } - public override void GetContextMenuEntries(Mobile from, List list) + [Flippable(0x2AF9, 0x2AFD)] + public class DawnsMusicBox : Item, ISecurable { - base.GetContextMenuEntries(from, list); + private static Dictionary m_Info; - SetSecureLevelEntry.AddTo(from, this, list); // Set secure level + public static MusicName[] m_CommonTracks = + { + MusicName.Samlethe, MusicName.Sailing, MusicName.Britain2, MusicName.Britain1, + MusicName.Bucsden, MusicName.Forest_a, MusicName.Cove, MusicName.Death, + MusicName.Dungeon9, MusicName.Dungeon2, MusicName.Cave01, MusicName.Combat3, + MusicName.Combat1, MusicName.Combat2, MusicName.Jhelom, MusicName.Linelle, + MusicName.LBCastle, MusicName.Minoc, MusicName.Moonglow, MusicName.Magincia, + MusicName.Nujelm, MusicName.BTCastle, MusicName.Tavern04, MusicName.Skarabra, + MusicName.Stones2, MusicName.Serpents, MusicName.Taiko, MusicName.Tavern01, + MusicName.Tavern02, MusicName.Tavern03, MusicName.TokunoDungeon, MusicName.Trinsic, + MusicName.OldUlt01, MusicName.Ocllo, MusicName.Vesper, MusicName.Victory, + MusicName.Mountn_a, MusicName.Wind, MusicName.Yew, MusicName.Zento + }; + + public static MusicName[] m_UncommonTracks = + { + MusicName.GwennoConversation, MusicName.DreadHornArea, MusicName.ElfCity, + MusicName.GoodEndGame, MusicName.GoodVsEvil, MusicName.GreatEarthSerpents, + MusicName.GrizzleDungeon, MusicName.Humanoids_U9, MusicName.MelisandesLair, + MusicName.MinocNegative, MusicName.ParoxysmusLair, MusicName.Paws + }; + + public static MusicName[] m_RareTracks = + { + MusicName.SelimsBar, MusicName.SerpentIsleCombat_U7, MusicName.ValoriaShips + }; + + private int m_Count; + private int m_ItemID; + + private Timer m_Timer; + + [Constructible] + public DawnsMusicBox() : base(0x2AF9) + { + Weight = 1.0; + + Tracks = new List(); + + while (Tracks.Count < 4) + { + var name = RandomTrack(DawnsMusicRarity.Common); + + if (!Tracks.Contains(name)) + Tracks.Add(name); + } + } + + public DawnsMusicBox(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075198; // Dawn�s Music Box + + public List Tracks { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public SecureLevel Level { get; set; } + + public override void OnAfterDuped(Item newItem) + { + if (!(newItem is DawnsMusicBox box)) + return; + + box.Tracks = new List(); + box.Tracks.AddRange(Tracks); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + var commonSongs = 0; + var uncommonSongs = 0; + var rareSongs = 0; + + for (var i = 0; i < Tracks.Count; i++) + { + var info = GetInfo(Tracks[i]); + + switch (info.Rarity) + { + case DawnsMusicRarity.Common: + commonSongs++; + break; + case DawnsMusicRarity.Uncommon: + uncommonSongs++; + break; + case DawnsMusicRarity.Rare: + rareSongs++; + break; + } + } + + if (commonSongs > 0) + list.Add(1075234, commonSongs.ToString()); // ~1_NUMBER~ Common Tracks + if (uncommonSongs > 0) + list.Add(1075235, uncommonSongs.ToString()); // ~1_NUMBER~ Uncommon Tracks + if (rareSongs > 0) + list.Add(1075236, rareSongs.ToString()); // ~1_NUMBER~ Rare Tracks + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + SetSecureLevelEntry.AddTo(from, this, list); // Set secure level + } + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack) && !IsLockedDown) + { + from.SendLocalizedMessage( + 1061856 + ); // You must have the item in your backpack or locked down in order to use it. + } + else if (IsLockedDown && !HasAccces(from)) + { + from.SendLocalizedMessage(502436); // That is not accessible. + } + else + { + from.CloseGump(); + from.SendGump(new DawnsMusicBoxGump(this)); + } + } + + public bool HasAccces(Mobile m) => + m.AccessLevel >= AccessLevel.GameMaster || BaseHouse.FindHouseAt(this)?.HasAccess(m) == true; + + public void PlayMusic(Mobile m, MusicName music) + { + if (m_Timer?.Running == true) + EndMusic(m); + else + m_ItemID = ItemID; + + m.Send(new PlayMusic(music)); + m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(0.5), TimeSpan.FromSeconds(0.5), 4, Animate); + } + + public void EndMusic(Mobile m) + { + if (m_Timer?.Running == true) + m_Timer.Stop(); + + m.Send(StopMusic.Instance); + + if (m_Count > 0) + ItemID = m_ItemID; + + m_Count = 0; + } + + private void Animate() + { + m_Count++; + + if (m_Count >= 4) + { + m_Count = 0; + ItemID = m_ItemID; + } + else + { + ItemID++; + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(Tracks.Count); + + for (var i = 0; i < Tracks.Count; i++) + writer.Write((int)Tracks[i]); + + writer.Write((int)Level); + writer.Write(m_ItemID); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + var count = reader.ReadInt(); + Tracks = new List(); + + for (var i = 0; i < count; i++) + Tracks.Add((MusicName)reader.ReadInt()); + + Level = (SecureLevel)reader.ReadInt(); + m_ItemID = reader.ReadInt(); + } + + public static void Initialize() + { + m_Info = new Dictionary + { + { MusicName.Samlethe, new DawnsMusicInfo(1075152, DawnsMusicRarity.Common) }, + { MusicName.Sailing, new DawnsMusicInfo(1075163, DawnsMusicRarity.Common) }, + { MusicName.Britain2, new DawnsMusicInfo(1075145, DawnsMusicRarity.Common) }, + { MusicName.Britain1, new DawnsMusicInfo(1075144, DawnsMusicRarity.Common) }, + { MusicName.Bucsden, new DawnsMusicInfo(1075146, DawnsMusicRarity.Common) }, + { MusicName.Forest_a, new DawnsMusicInfo(1075161, DawnsMusicRarity.Common) }, + { MusicName.Cove, new DawnsMusicInfo(1075176, DawnsMusicRarity.Common) }, + { MusicName.Death, new DawnsMusicInfo(1075171, DawnsMusicRarity.Common) }, + { MusicName.Dungeon9, new DawnsMusicInfo(1075160, DawnsMusicRarity.Common) }, + { MusicName.Dungeon2, new DawnsMusicInfo(1075175, DawnsMusicRarity.Common) }, + { MusicName.Cave01, new DawnsMusicInfo(1075159, DawnsMusicRarity.Common) }, + { MusicName.Combat3, new DawnsMusicInfo(1075170, DawnsMusicRarity.Common) }, + { MusicName.Combat1, new DawnsMusicInfo(1075168, DawnsMusicRarity.Common) }, + { MusicName.Combat2, new DawnsMusicInfo(1075169, DawnsMusicRarity.Common) }, + { MusicName.Jhelom, new DawnsMusicInfo(1075147, DawnsMusicRarity.Common) }, + { MusicName.Linelle, new DawnsMusicInfo(1075185, DawnsMusicRarity.Common) }, + { MusicName.LBCastle, new DawnsMusicInfo(1075148, DawnsMusicRarity.Common) }, + { MusicName.Minoc, new DawnsMusicInfo(1075150, DawnsMusicRarity.Common) }, + { MusicName.Moonglow, new DawnsMusicInfo(1075177, DawnsMusicRarity.Common) }, + { MusicName.Magincia, new DawnsMusicInfo(1075149, DawnsMusicRarity.Common) }, + { MusicName.Nujelm, new DawnsMusicInfo(1075174, DawnsMusicRarity.Common) }, + { MusicName.BTCastle, new DawnsMusicInfo(1075173, DawnsMusicRarity.Common) }, + { MusicName.Tavern04, new DawnsMusicInfo(1075167, DawnsMusicRarity.Common) }, + { MusicName.Skarabra, new DawnsMusicInfo(1075154, DawnsMusicRarity.Common) }, + { MusicName.Stones2, new DawnsMusicInfo(1075143, DawnsMusicRarity.Common) }, + { MusicName.Serpents, new DawnsMusicInfo(1075153, DawnsMusicRarity.Common) }, + { MusicName.Taiko, new DawnsMusicInfo(1075180, DawnsMusicRarity.Common) }, + { MusicName.Tavern01, new DawnsMusicInfo(1075164, DawnsMusicRarity.Common) }, + { MusicName.Tavern02, new DawnsMusicInfo(1075165, DawnsMusicRarity.Common) }, + { MusicName.Tavern03, new DawnsMusicInfo(1075166, DawnsMusicRarity.Common) }, + { MusicName.TokunoDungeon, new DawnsMusicInfo(1075179, DawnsMusicRarity.Common) }, + { MusicName.Trinsic, new DawnsMusicInfo(1075155, DawnsMusicRarity.Common) }, + { MusicName.OldUlt01, new DawnsMusicInfo(1075142, DawnsMusicRarity.Common) }, + { MusicName.Ocllo, new DawnsMusicInfo(1075151, DawnsMusicRarity.Common) }, + { MusicName.Vesper, new DawnsMusicInfo(1075156, DawnsMusicRarity.Common) }, + { MusicName.Victory, new DawnsMusicInfo(1075172, DawnsMusicRarity.Common) }, + { MusicName.Mountn_a, new DawnsMusicInfo(1075162, DawnsMusicRarity.Common) }, + { MusicName.Wind, new DawnsMusicInfo(1075157, DawnsMusicRarity.Common) }, + { MusicName.Yew, new DawnsMusicInfo(1075158, DawnsMusicRarity.Common) }, + { MusicName.Zento, new DawnsMusicInfo(1075178, DawnsMusicRarity.Common) }, + { MusicName.GwennoConversation, new DawnsMusicInfo(1075131, DawnsMusicRarity.Uncommon) }, + { MusicName.DreadHornArea, new DawnsMusicInfo(1075181, DawnsMusicRarity.Uncommon) }, + { MusicName.ElfCity, new DawnsMusicInfo(1075182, DawnsMusicRarity.Uncommon) }, + { MusicName.GoodEndGame, new DawnsMusicInfo(1075132, DawnsMusicRarity.Uncommon) }, + { MusicName.GoodVsEvil, new DawnsMusicInfo(1075133, DawnsMusicRarity.Uncommon) }, + { MusicName.GreatEarthSerpents, new DawnsMusicInfo(1075134, DawnsMusicRarity.Uncommon) }, + { MusicName.GrizzleDungeon, new DawnsMusicInfo(1075186, DawnsMusicRarity.Uncommon) }, + { MusicName.Humanoids_U9, new DawnsMusicInfo(1075135, DawnsMusicRarity.Uncommon) }, + { MusicName.MelisandesLair, new DawnsMusicInfo(1075183, DawnsMusicRarity.Uncommon) }, + { MusicName.MinocNegative, new DawnsMusicInfo(1075136, DawnsMusicRarity.Uncommon) }, + { MusicName.ParoxysmusLair, new DawnsMusicInfo(1075184, DawnsMusicRarity.Uncommon) }, + { MusicName.Paws, new DawnsMusicInfo(1075137, DawnsMusicRarity.Uncommon) }, + { MusicName.SelimsBar, new DawnsMusicInfo(1075138, DawnsMusicRarity.Rare) }, + { MusicName.SerpentIsleCombat_U7, new DawnsMusicInfo(1075139, DawnsMusicRarity.Rare) }, + { MusicName.ValoriaShips, new DawnsMusicInfo(1075140, DawnsMusicRarity.Rare) } + }; + } + + public static DawnsMusicInfo GetInfo(MusicName name) + { + if (m_Info == null) // sanity + return null; + + m_Info.TryGetValue(name, out var info); + return info; + } + + public static MusicName RandomTrack(DawnsMusicRarity rarity) + { + var list = rarity switch + { + DawnsMusicRarity.Common => m_CommonTracks, + DawnsMusicRarity.Uncommon => m_UncommonTracks, + DawnsMusicRarity.Rare => m_RareTracks, + _ => m_CommonTracks + }; + + return list.RandomElement(); + } } - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack) && !IsLockedDown) - { - from.SendLocalizedMessage( - 1061856); // You must have the item in your backpack or locked down in order to use it. - } - else if (IsLockedDown && !HasAccces(from)) - { - from.SendLocalizedMessage(502436); // That is not accessible. - } - else - { - from.CloseGump(); - from.SendGump(new DawnsMusicBoxGump(this)); - } - } - - public bool HasAccces(Mobile m) => m.AccessLevel >= AccessLevel.GameMaster || BaseHouse.FindHouseAt(this)?.HasAccess(m) == true; - - public void PlayMusic(Mobile m, MusicName music) - { - if (m_Timer?.Running == true) - EndMusic(m); - else - m_ItemID = ItemID; - - m.Send(new PlayMusic(music)); - m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(0.5), TimeSpan.FromSeconds(0.5), 4, Animate); - } - - public void EndMusic(Mobile m) - { - if (m_Timer?.Running == true) - m_Timer.Stop(); - - m.Send(StopMusic.Instance); - - if (m_Count > 0) - ItemID = m_ItemID; - - m_Count = 0; - } - - private void Animate() - { - m_Count++; - - if (m_Count >= 4) - { - m_Count = 0; - ItemID = m_ItemID; - } - else - { - ItemID++; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(Tracks.Count); - - for (int i = 0; i < Tracks.Count; i++) - writer.Write((int)Tracks[i]); - - writer.Write((int)Level); - writer.Write(m_ItemID); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - int count = reader.ReadInt(); - Tracks = new List(); - - for (int i = 0; i < count; i++) - Tracks.Add((MusicName)reader.ReadInt()); - - Level = (SecureLevel)reader.ReadInt(); - m_ItemID = reader.ReadInt(); - } - - public static void Initialize() - { - m_Info = new Dictionary - { - { MusicName.Samlethe, new DawnsMusicInfo(1075152, DawnsMusicRarity.Common) }, - { MusicName.Sailing, new DawnsMusicInfo(1075163, DawnsMusicRarity.Common) }, - { MusicName.Britain2, new DawnsMusicInfo(1075145, DawnsMusicRarity.Common) }, - { MusicName.Britain1, new DawnsMusicInfo(1075144, DawnsMusicRarity.Common) }, - { MusicName.Bucsden, new DawnsMusicInfo(1075146, DawnsMusicRarity.Common) }, - { MusicName.Forest_a, new DawnsMusicInfo(1075161, DawnsMusicRarity.Common) }, - { MusicName.Cove, new DawnsMusicInfo(1075176, DawnsMusicRarity.Common) }, - { MusicName.Death, new DawnsMusicInfo(1075171, DawnsMusicRarity.Common) }, - { MusicName.Dungeon9, new DawnsMusicInfo(1075160, DawnsMusicRarity.Common) }, - { MusicName.Dungeon2, new DawnsMusicInfo(1075175, DawnsMusicRarity.Common) }, - { MusicName.Cave01, new DawnsMusicInfo(1075159, DawnsMusicRarity.Common) }, - { MusicName.Combat3, new DawnsMusicInfo(1075170, DawnsMusicRarity.Common) }, - { MusicName.Combat1, new DawnsMusicInfo(1075168, DawnsMusicRarity.Common) }, - { MusicName.Combat2, new DawnsMusicInfo(1075169, DawnsMusicRarity.Common) }, - { MusicName.Jhelom, new DawnsMusicInfo(1075147, DawnsMusicRarity.Common) }, - { MusicName.Linelle, new DawnsMusicInfo(1075185, DawnsMusicRarity.Common) }, - { MusicName.LBCastle, new DawnsMusicInfo(1075148, DawnsMusicRarity.Common) }, - { MusicName.Minoc, new DawnsMusicInfo(1075150, DawnsMusicRarity.Common) }, - { MusicName.Moonglow, new DawnsMusicInfo(1075177, DawnsMusicRarity.Common) }, - { MusicName.Magincia, new DawnsMusicInfo(1075149, DawnsMusicRarity.Common) }, - { MusicName.Nujelm, new DawnsMusicInfo(1075174, DawnsMusicRarity.Common) }, - { MusicName.BTCastle, new DawnsMusicInfo(1075173, DawnsMusicRarity.Common) }, - { MusicName.Tavern04, new DawnsMusicInfo(1075167, DawnsMusicRarity.Common) }, - { MusicName.Skarabra, new DawnsMusicInfo(1075154, DawnsMusicRarity.Common) }, - { MusicName.Stones2, new DawnsMusicInfo(1075143, DawnsMusicRarity.Common) }, - { MusicName.Serpents, new DawnsMusicInfo(1075153, DawnsMusicRarity.Common) }, - { MusicName.Taiko, new DawnsMusicInfo(1075180, DawnsMusicRarity.Common) }, - { MusicName.Tavern01, new DawnsMusicInfo(1075164, DawnsMusicRarity.Common) }, - { MusicName.Tavern02, new DawnsMusicInfo(1075165, DawnsMusicRarity.Common) }, - { MusicName.Tavern03, new DawnsMusicInfo(1075166, DawnsMusicRarity.Common) }, - { MusicName.TokunoDungeon, new DawnsMusicInfo(1075179, DawnsMusicRarity.Common) }, - { MusicName.Trinsic, new DawnsMusicInfo(1075155, DawnsMusicRarity.Common) }, - { MusicName.OldUlt01, new DawnsMusicInfo(1075142, DawnsMusicRarity.Common) }, - { MusicName.Ocllo, new DawnsMusicInfo(1075151, DawnsMusicRarity.Common) }, - { MusicName.Vesper, new DawnsMusicInfo(1075156, DawnsMusicRarity.Common) }, - { MusicName.Victory, new DawnsMusicInfo(1075172, DawnsMusicRarity.Common) }, - { MusicName.Mountn_a, new DawnsMusicInfo(1075162, DawnsMusicRarity.Common) }, - { MusicName.Wind, new DawnsMusicInfo(1075157, DawnsMusicRarity.Common) }, - { MusicName.Yew, new DawnsMusicInfo(1075158, DawnsMusicRarity.Common) }, - { MusicName.Zento, new DawnsMusicInfo(1075178, DawnsMusicRarity.Common) }, - { MusicName.GwennoConversation, new DawnsMusicInfo(1075131, DawnsMusicRarity.Uncommon) }, - { MusicName.DreadHornArea, new DawnsMusicInfo(1075181, DawnsMusicRarity.Uncommon) }, - { MusicName.ElfCity, new DawnsMusicInfo(1075182, DawnsMusicRarity.Uncommon) }, - { MusicName.GoodEndGame, new DawnsMusicInfo(1075132, DawnsMusicRarity.Uncommon) }, - { MusicName.GoodVsEvil, new DawnsMusicInfo(1075133, DawnsMusicRarity.Uncommon) }, - { MusicName.GreatEarthSerpents, new DawnsMusicInfo(1075134, DawnsMusicRarity.Uncommon) }, - { MusicName.GrizzleDungeon, new DawnsMusicInfo(1075186, DawnsMusicRarity.Uncommon) }, - { MusicName.Humanoids_U9, new DawnsMusicInfo(1075135, DawnsMusicRarity.Uncommon) }, - { MusicName.MelisandesLair, new DawnsMusicInfo(1075183, DawnsMusicRarity.Uncommon) }, - { MusicName.MinocNegative, new DawnsMusicInfo(1075136, DawnsMusicRarity.Uncommon) }, - { MusicName.ParoxysmusLair, new DawnsMusicInfo(1075184, DawnsMusicRarity.Uncommon) }, - { MusicName.Paws, new DawnsMusicInfo(1075137, DawnsMusicRarity.Uncommon) }, - { MusicName.SelimsBar, new DawnsMusicInfo(1075138, DawnsMusicRarity.Rare) }, - { MusicName.SerpentIsleCombat_U7, new DawnsMusicInfo(1075139, DawnsMusicRarity.Rare) }, - { MusicName.ValoriaShips, new DawnsMusicInfo(1075140, DawnsMusicRarity.Rare) } - }; - } - - public static DawnsMusicInfo GetInfo(MusicName name) - { - if (m_Info == null) // sanity - return null; - - m_Info.TryGetValue(name, out DawnsMusicInfo info); - return info; - } - - public static MusicName RandomTrack(DawnsMusicRarity rarity) - { - var list = rarity switch - { - DawnsMusicRarity.Common => m_CommonTracks, - DawnsMusicRarity.Uncommon => m_UncommonTracks, - DawnsMusicRarity.Rare => m_RareTracks, - _ => m_CommonTracks - }; - - return list.RandomElement(); - } - } } diff --git a/Projects/UOContent/Items/Special/8th Anniversary Items/Dawn's Music Box/DawnsMusicGear.cs b/Projects/UOContent/Items/Special/8th Anniversary Items/Dawn's Music Box/DawnsMusicGear.cs index be4be6cd7..d71faf015 100644 --- a/Projects/UOContent/Items/Special/8th Anniversary Items/Dawn's Music Box/DawnsMusicGear.cs +++ b/Projects/UOContent/Items/Special/8th Anniversary Items/Dawn's Music Box/DawnsMusicGear.cs @@ -2,134 +2,134 @@ namespace Server.Items { - [Flippable(0x1053, 0x1054)] - public class DawnsMusicGear : Item - { - [Constructible] - public DawnsMusicGear() : this(DawnsMusicBox.RandomTrack(DawnsMusicRarity.Common)) + [Flippable(0x1053, 0x1054)] + public class DawnsMusicGear : Item { - } - - [Constructible] - public DawnsMusicGear(MusicName music) : base(0x1053) - { - Music = music; - - Weight = 1.0; - } - - public DawnsMusicGear(Serial serial) : base(serial) - { - } - - public static DawnsMusicGear RandomCommon => new DawnsMusicGear(DawnsMusicBox.RandomTrack(DawnsMusicRarity.Common)); - - public static DawnsMusicGear RandomUncommon => - new DawnsMusicGear(DawnsMusicBox.RandomTrack(DawnsMusicRarity.Uncommon)); - - public static DawnsMusicGear RandomRare => new DawnsMusicGear(DawnsMusicBox.RandomTrack(DawnsMusicRarity.Rare)); - - [CommandProperty(AccessLevel.GameMaster)] - public MusicName Music { get; set; } - - public override void AddNameProperty(ObjectPropertyList list) - { - DawnsMusicInfo info = DawnsMusicBox.GetInfo(Music); - - if (info != null) - { - if (info.Rarity == DawnsMusicRarity.Common) - list.Add(1075204); // Gear for Dawn's Music Box (Common) - else if (info.Rarity == DawnsMusicRarity.Uncommon) - list.Add(1075205); // Gear for Dawn's Music Box (Uncommon) - else if (info.Rarity == DawnsMusicRarity.Rare) - list.Add(1075206); // Gear for Dawn's Music Box (Rare) - - list.Add(info.Name); - } - else - { - base.AddNameProperty(list); - } - } - - public override void OnDoubleClick(Mobile from) - { - from.Target = new InternalTarget(this); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(1); // version - - writer.Write((int)Music); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 1: - { - Music = (MusicName)reader.ReadInt(); - break; - } - } - - if (version == 0) // Music wasn't serialized in version 0, pick a new track of random rarity - { - DawnsMusicRarity rarity; - double rand = Utility.RandomDouble(); - - if (rand < 0.025) - rarity = DawnsMusicRarity.Rare; - else if (rand < 0.225) - rarity = DawnsMusicRarity.Uncommon; - else - rarity = DawnsMusicRarity.Common; - - Music = DawnsMusicBox.RandomTrack(rarity); - } - } - - public class InternalTarget : Target - { - private readonly DawnsMusicGear m_Gear; - - public InternalTarget(DawnsMusicGear gear) : base(2, false, TargetFlags.None) => m_Gear = gear; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Gear?.Deleted != false) - return; - - if (targeted is DawnsMusicBox box) + [Constructible] + public DawnsMusicGear() : this(DawnsMusicBox.RandomTrack(DawnsMusicRarity.Common)) { - if (!box.Tracks.Contains(m_Gear.Music)) - { - box.Tracks.Add(m_Gear.Music); - box.InvalidateProperties(); - - m_Gear.Delete(); - - from.SendLocalizedMessage(1071961); // This song has been added to the musicbox. - } - else - { - from.SendLocalizedMessage(1071962); // This song track is already in the musicbox. - } } - else + + [Constructible] + public DawnsMusicGear(MusicName music) : base(0x1053) { - from.SendLocalizedMessage(1071964); // Gears can only be put into a musicbox. + Music = music; + + Weight = 1.0; + } + + public DawnsMusicGear(Serial serial) : base(serial) + { + } + + public static DawnsMusicGear RandomCommon => new DawnsMusicGear(DawnsMusicBox.RandomTrack(DawnsMusicRarity.Common)); + + public static DawnsMusicGear RandomUncommon => + new DawnsMusicGear(DawnsMusicBox.RandomTrack(DawnsMusicRarity.Uncommon)); + + public static DawnsMusicGear RandomRare => new DawnsMusicGear(DawnsMusicBox.RandomTrack(DawnsMusicRarity.Rare)); + + [CommandProperty(AccessLevel.GameMaster)] + public MusicName Music { get; set; } + + public override void AddNameProperty(ObjectPropertyList list) + { + var info = DawnsMusicBox.GetInfo(Music); + + if (info != null) + { + if (info.Rarity == DawnsMusicRarity.Common) + list.Add(1075204); // Gear for Dawn's Music Box (Common) + else if (info.Rarity == DawnsMusicRarity.Uncommon) + list.Add(1075205); // Gear for Dawn's Music Box (Uncommon) + else if (info.Rarity == DawnsMusicRarity.Rare) + list.Add(1075206); // Gear for Dawn's Music Box (Rare) + + list.Add(info.Name); + } + else + { + base.AddNameProperty(list); + } + } + + public override void OnDoubleClick(Mobile from) + { + from.Target = new InternalTarget(this); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(1); // version + + writer.Write((int)Music); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 1: + { + Music = (MusicName)reader.ReadInt(); + break; + } + } + + if (version == 0) // Music wasn't serialized in version 0, pick a new track of random rarity + { + DawnsMusicRarity rarity; + var rand = Utility.RandomDouble(); + + if (rand < 0.025) + rarity = DawnsMusicRarity.Rare; + else if (rand < 0.225) + rarity = DawnsMusicRarity.Uncommon; + else + rarity = DawnsMusicRarity.Common; + + Music = DawnsMusicBox.RandomTrack(rarity); + } + } + + public class InternalTarget : Target + { + private readonly DawnsMusicGear m_Gear; + + public InternalTarget(DawnsMusicGear gear) : base(2, false, TargetFlags.None) => m_Gear = gear; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Gear?.Deleted != false) + return; + + if (targeted is DawnsMusicBox box) + { + if (!box.Tracks.Contains(m_Gear.Music)) + { + box.Tracks.Add(m_Gear.Music); + box.InvalidateProperties(); + + m_Gear.Delete(); + + from.SendLocalizedMessage(1071961); // This song has been added to the musicbox. + } + else + { + from.SendLocalizedMessage(1071962); // This song track is already in the musicbox. + } + } + else + { + from.SendLocalizedMessage(1071964); // Gears can only be put into a musicbox. + } + } } - } } - } } diff --git a/Projects/UOContent/Items/Special/8th Anniversary Items/Dawn's Music Box/DawnsMusicInfo.cs b/Projects/UOContent/Items/Special/8th Anniversary Items/Dawn's Music Box/DawnsMusicInfo.cs index ba95bcbd6..a01bfb88a 100644 --- a/Projects/UOContent/Items/Special/8th Anniversary Items/Dawn's Music Box/DawnsMusicInfo.cs +++ b/Projects/UOContent/Items/Special/8th Anniversary Items/Dawn's Music Box/DawnsMusicInfo.cs @@ -1,22 +1,22 @@ namespace Server.Items { - public enum DawnsMusicRarity - { - Common, - Uncommon, - Rare - } - - public class DawnsMusicInfo - { - public DawnsMusicInfo(int name, DawnsMusicRarity rarity) + public enum DawnsMusicRarity { - Name = name; - Rarity = rarity; + Common, + Uncommon, + Rare } - public int Name { get; } + public class DawnsMusicInfo + { + public DawnsMusicInfo(int name, DawnsMusicRarity rarity) + { + Name = name; + Rarity = rarity; + } - public DawnsMusicRarity Rarity { get; } - } -} \ No newline at end of file + public int Name { get; } + + public DawnsMusicRarity Rarity { get; } + } +} diff --git a/Projects/UOContent/Items/Special/8th Anniversary Items/DupresShield.cs b/Projects/UOContent/Items/Special/8th Anniversary Items/DupresShield.cs index 6bc6dd48a..40947de60 100644 --- a/Projects/UOContent/Items/Special/8th Anniversary Items/DupresShield.cs +++ b/Projects/UOContent/Items/Special/8th Anniversary Items/DupresShield.cs @@ -1,50 +1,50 @@ namespace Server.Items { - public class DupresShield : BaseShield, ITokunoDyable - { - [Constructible] - public DupresShield() : base(0x2B01) + public class DupresShield : BaseShield, ITokunoDyable { - LootType = LootType.Blessed; - Weight = 6.0; + [Constructible] + public DupresShield() : base(0x2B01) + { + LootType = LootType.Blessed; + Weight = 6.0; - Attributes.BonusHits = 5; - Attributes.RegenHits = 1; + Attributes.BonusHits = 5; + Attributes.RegenHits = 1; - SkillBonuses.SetValues(0, SkillName.Parry, 5); + SkillBonuses.SetValues(0, SkillName.Parry, 5); + } + + public DupresShield(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075196; // Dupre�s Shield + + public override int BasePhysicalResistance => 1; + public override int BaseFireResistance => 0; + public override int BaseColdResistance => 0; + public override int BasePoisonResistance => 0; + public override int BaseEnergyResistance => 1; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override int AosStrReq => 50; + + public override int ArmorBase => 15; + + 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(); + } } - - public DupresShield(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075196; // Dupre�s Shield - - public override int BasePhysicalResistance => 1; - public override int BaseFireResistance => 0; - public override int BaseColdResistance => 0; - public override int BasePoisonResistance => 0; - public override int BaseEnergyResistance => 1; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override int AosStrReq => 50; - - public override int ArmorBase => 15; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/8th Anniversary Items/FountainOfLife.cs b/Projects/UOContent/Items/Special/8th Anniversary Items/FountainOfLife.cs index a677c9392..89d9fb161 100644 --- a/Projects/UOContent/Items/Special/8th Anniversary Items/FountainOfLife.cs +++ b/Projects/UOContent/Items/Special/8th Anniversary Items/FountainOfLife.cs @@ -2,249 +2,249 @@ using System; namespace Server.Items { - public class EnhancedBandage : Bandage - { - [Constructible] - public EnhancedBandage(int amount = 1) - : base(amount) => - Hue = 0x8A5; - - public EnhancedBandage(Serial serial) - : base(serial) + public class EnhancedBandage : Bandage { - } + [Constructible] + public EnhancedBandage(int amount = 1) + : base(amount) => + Hue = 0x8A5; - public static int HealingBonus => 10; - - public override int LabelNumber => 1152441; // enhanced bandage - - public override bool Dye(Mobile from, DyeTub sender) => false; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - list.Add(1075216); // these bandages have been enhanced - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - [Flippable(0x2AC0, 0x2AC3)] - public class FountainOfLife : BaseAddonContainer - { - private int m_Charges; - - private Timer m_Timer; - - [Constructible] - public FountainOfLife(int charges = 10) - : base(0x2AC0) - { - m_Charges = charges; - - m_Timer = Timer.DelayCall(RechargeTime, RechargeTime, Recharge); - } - - public FountainOfLife(Serial serial) - : base(serial) - { - } - - public override BaseAddonContainerDeed Deed => new FountainOfLifeDeed(m_Charges); - - public virtual TimeSpan RechargeTime => TimeSpan.FromDays(1); - - public override int LabelNumber => 1075197; // Fountain of Life - public override int DefaultGumpID => 0x484; - public override int DefaultDropSound => 66; - public override int DefaultMaxItems => 125; - - [CommandProperty(AccessLevel.GameMaster)] - public int Charges - { - get => m_Charges; - set - { - m_Charges = Math.Min(value, 10); - InvalidateProperties(); - } - } - - public override bool OnDragLift(Mobile from) => false; - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (dropped is Bandage) - { - bool allow = base.OnDragDrop(from, dropped); - - if (allow) - Enhance(from); - - return allow; - } - - from.SendLocalizedMessage(1075209); // Only bandages may be dropped into the fountain. - return false; - } - - public override bool OnDragDropInto(Mobile from, Item item, Point3D p) - { - if (item is Bandage) - { - bool allow = base.OnDragDropInto(from, item, p); - - if (allow) - Enhance(from); - - return allow; - } - - from.SendLocalizedMessage(1075209); // Only bandages may be dropped into the fountain. - return false; - } - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - list.Add(1075217, m_Charges.ToString()); // ~1_val~ charges remaining - } - - public override void OnDelete() - { - m_Timer?.Stop(); - - base.OnDelete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_Charges); - writer.Write(m_Timer.Next); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_Charges = reader.ReadInt(); - - DateTime next = reader.ReadDateTime(); - - var now = DateTime.UtcNow; - - if (next < now) - m_Timer = Timer.DelayCall(RechargeTime, Recharge); - else - m_Timer = Timer.DelayCall(next - now, RechargeTime, Recharge); - } - - public void Recharge() - { - m_Charges = 10; - - Enhance(null); - } - - public void Enhance(Mobile from) - { - for (int i = Items.Count - 1; i >= 0 && m_Charges > 0; --i) - { - if (Items[i] is EnhancedBandage) - continue; - - if (Items[i] is Bandage bandage) + public EnhancedBandage(Serial serial) + : base(serial) { - Item enhanced; - - if (bandage.Amount > m_Charges) - { - bandage.Amount -= m_Charges; - enhanced = new EnhancedBandage(m_Charges); - m_Charges = 0; - } - else - { - enhanced = new EnhancedBandage(bandage.Amount); - m_Charges -= bandage.Amount; - bandage.Delete(); - } - - if (from == null || !TryDropItem(from, enhanced, false)) // try stacking first - DropItem(enhanced); } - } - InvalidateProperties(); + public static int HealingBonus => 10; + + public override int LabelNumber => 1152441; // enhanced bandage + + public override bool Dye(Mobile from, DyeTub sender) => false; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + list.Add(1075216); // these bandages have been enhanced + } + + 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(); + } } - } - public class FountainOfLifeDeed : BaseAddonContainerDeed - { - private int m_Charges; - - [Constructible] - public FountainOfLifeDeed(int charges = 10) + [Flippable(0x2AC0, 0x2AC3)] + public class FountainOfLife : BaseAddonContainer { - LootType = LootType.Blessed; - m_Charges = charges; + private int m_Charges; + + private Timer m_Timer; + + [Constructible] + public FountainOfLife(int charges = 10) + : base(0x2AC0) + { + m_Charges = charges; + + m_Timer = Timer.DelayCall(RechargeTime, RechargeTime, Recharge); + } + + public FountainOfLife(Serial serial) + : base(serial) + { + } + + public override BaseAddonContainerDeed Deed => new FountainOfLifeDeed(m_Charges); + + public virtual TimeSpan RechargeTime => TimeSpan.FromDays(1); + + public override int LabelNumber => 1075197; // Fountain of Life + public override int DefaultGumpID => 0x484; + public override int DefaultDropSound => 66; + public override int DefaultMaxItems => 125; + + [CommandProperty(AccessLevel.GameMaster)] + public int Charges + { + get => m_Charges; + set + { + m_Charges = Math.Min(value, 10); + InvalidateProperties(); + } + } + + public override bool OnDragLift(Mobile from) => false; + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (dropped is Bandage) + { + var allow = base.OnDragDrop(from, dropped); + + if (allow) + Enhance(from); + + return allow; + } + + from.SendLocalizedMessage(1075209); // Only bandages may be dropped into the fountain. + return false; + } + + public override bool OnDragDropInto(Mobile from, Item item, Point3D p) + { + if (item is Bandage) + { + var allow = base.OnDragDropInto(from, item, p); + + if (allow) + Enhance(from); + + return allow; + } + + from.SendLocalizedMessage(1075209); // Only bandages may be dropped into the fountain. + return false; + } + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + list.Add(1075217, m_Charges.ToString()); // ~1_val~ charges remaining + } + + public override void OnDelete() + { + m_Timer?.Stop(); + + base.OnDelete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_Charges); + writer.Write(m_Timer.Next); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_Charges = reader.ReadInt(); + + var next = reader.ReadDateTime(); + + var now = DateTime.UtcNow; + + if (next < now) + m_Timer = Timer.DelayCall(RechargeTime, Recharge); + else + m_Timer = Timer.DelayCall(next - now, RechargeTime, Recharge); + } + + public void Recharge() + { + m_Charges = 10; + + Enhance(null); + } + + public void Enhance(Mobile from) + { + for (var i = Items.Count - 1; i >= 0 && m_Charges > 0; --i) + { + if (Items[i] is EnhancedBandage) + continue; + + if (Items[i] is Bandage bandage) + { + Item enhanced; + + if (bandage.Amount > m_Charges) + { + bandage.Amount -= m_Charges; + enhanced = new EnhancedBandage(m_Charges); + m_Charges = 0; + } + else + { + enhanced = new EnhancedBandage(bandage.Amount); + m_Charges -= bandage.Amount; + bandage.Delete(); + } + + if (from == null || !TryDropItem(from, enhanced, false)) // try stacking first + DropItem(enhanced); + } + } + + InvalidateProperties(); + } } - public FountainOfLifeDeed(Serial serial) - : base(serial) + public class FountainOfLifeDeed : BaseAddonContainerDeed { + private int m_Charges; + + [Constructible] + public FountainOfLifeDeed(int charges = 10) + { + LootType = LootType.Blessed; + m_Charges = charges; + } + + public FountainOfLifeDeed(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1075197; // Fountain of Life + public override BaseAddonContainer Addon => new FountainOfLife(m_Charges); + + [CommandProperty(AccessLevel.GameMaster)] + public int Charges + { + get => m_Charges; + set + { + m_Charges = Math.Min(value, 10); + InvalidateProperties(); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_Charges); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_Charges = reader.ReadInt(); + } } - - public override int LabelNumber => 1075197; // Fountain of Life - public override BaseAddonContainer Addon => new FountainOfLife(m_Charges); - - [CommandProperty(AccessLevel.GameMaster)] - public int Charges - { - get => m_Charges; - set - { - m_Charges = Math.Min(value, 10); - InvalidateProperties(); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_Charges); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_Charges = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/8th Anniversary Items/OssianGrimoire.cs b/Projects/UOContent/Items/Special/8th Anniversary Items/OssianGrimoire.cs index 94269b1bf..2e27e1de0 100644 --- a/Projects/UOContent/Items/Special/8th Anniversary Items/OssianGrimoire.cs +++ b/Projects/UOContent/Items/Special/8th Anniversary Items/OssianGrimoire.cs @@ -1,39 +1,39 @@ namespace Server.Items { - public class OssianGrimoire : NecromancerSpellbook, ITokunoDyable - { - [Constructible] - public OssianGrimoire() + public class OssianGrimoire : NecromancerSpellbook, ITokunoDyable { - LootType = LootType.Blessed; + [Constructible] + public OssianGrimoire() + { + LootType = LootType.Blessed; - SkillBonuses.SetValues(0, SkillName.Necromancy, 10.0); - Attributes.RegenMana = 1; - Attributes.CastSpeed = 1; - Attributes.IncreasedKarmaLoss = 5; + SkillBonuses.SetValues(0, SkillName.Necromancy, 10.0); + Attributes.RegenMana = 1; + Attributes.CastSpeed = 1; + Attributes.IncreasedKarmaLoss = 5; + } + + public OssianGrimoire(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1078148; // Ossian Grimoire + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(1); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + if (version == 0) + Attributes.IncreasedKarmaLoss = 5; + } } - - public OssianGrimoire(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1078148; // Ossian Grimoire - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - if (version == 0) - Attributes.IncreasedKarmaLoss = 5; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/8th Anniversary Items/QuiverOfInfinity.cs b/Projects/UOContent/Items/Special/8th Anniversary Items/QuiverOfInfinity.cs index 7d54a3cb5..5dcec732c 100644 --- a/Projects/UOContent/Items/Special/8th Anniversary Items/QuiverOfInfinity.cs +++ b/Projects/UOContent/Items/Special/8th Anniversary Items/QuiverOfInfinity.cs @@ -1,43 +1,43 @@ namespace Server.Items { - public class QuiverOfInfinity : BaseQuiver, ITokunoDyable - { - [Constructible] - public QuiverOfInfinity() : base(0x2B02) + public class QuiverOfInfinity : BaseQuiver, ITokunoDyable { - LootType = LootType.Blessed; - Weight = 8.0; + [Constructible] + public QuiverOfInfinity() : base(0x2B02) + { + LootType = LootType.Blessed; + Weight = 8.0; - WeightReduction = 30; - LowerAmmoCost = 20; + WeightReduction = 30; + LowerAmmoCost = 20; - Attributes.DefendChance = 5; + Attributes.DefendChance = 5; + } + + public QuiverOfInfinity(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1075201; // Quiver of Infinity + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(2); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + if (version < 1 && DamageIncrease == 0) + DamageIncrease = 10; + + if (version < 2 && Attributes.WeaponDamage == 10) + Attributes.WeaponDamage = 0; + } } - - public QuiverOfInfinity(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1075201; // Quiver of Infinity - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(2); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - if (version < 1 && DamageIncrease == 0) - DamageIncrease = 10; - - if (version < 2 && Attributes.WeaponDamage == 10) - Attributes.WeaponDamage = 0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/8th Anniversary Items/Talismans.cs b/Projects/UOContent/Items/Special/8th Anniversary Items/Talismans.cs index 86c25a90e..2fbd9b39e 100644 --- a/Projects/UOContent/Items/Special/8th Anniversary Items/Talismans.cs +++ b/Projects/UOContent/Items/Special/8th Anniversary Items/Talismans.cs @@ -4,179 +4,179 @@ using Server.Spells.Ninjitsu; namespace Server.Items { - public enum TalismanForm - { - Ferret = 1031672, - Squirrel = 1031671, - CuSidhe = 1031670, - Reptalon = 1075202 - } - - public class BaseFormTalisman : Item, ITokunoDyable - { - public BaseFormTalisman() : base(0x2F59) + public enum TalismanForm { - LootType = LootType.Blessed; - Layer = Layer.Talisman; - Weight = 1.0; + Ferret = 1031672, + Squirrel = 1031671, + CuSidhe = 1031670, + Reptalon = 1075202 } - public BaseFormTalisman(Serial serial) : base(serial) + public class BaseFormTalisman : Item, ITokunoDyable { + public BaseFormTalisman() : base(0x2F59) + { + LootType = LootType.Blessed; + Layer = Layer.Talisman; + Weight = 1.0; + } + + public BaseFormTalisman(Serial serial) : base(serial) + { + } + + public virtual TalismanForm Form => TalismanForm.Squirrel; + + public override void AddNameProperty(ObjectPropertyList list) + { + list.Add(1075200, $"#{(int)Form}"); + } + + 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(); + } + + public override void OnRemoved(IEntity parent) + { + base.OnRemoved(parent); + + if (parent is Mobile m) AnimalForm.RemoveContext(m, true); + } + + public static bool EntryEnabled(Mobile m, Type type) + { + if (type == typeof(Squirrel)) + return m.Talisman is SquirrelFormTalisman; + if (type == typeof(Ferret)) + return m.Talisman is FerretFormTalisman; + if (type == typeof(CuSidhe)) + return m.Talisman is CuSidheFormTalisman; + if (type == typeof(Reptalon)) + return m.Talisman is ReptalonFormTalisman; + + return true; + } } - public virtual TalismanForm Form => TalismanForm.Squirrel; - - public override void AddNameProperty(ObjectPropertyList list) + public class FerretFormTalisman : BaseFormTalisman { - list.Add(1075200, $"#{(int)Form}"); + [Constructible] + public FerretFormTalisman() + { + } + + public FerretFormTalisman(Serial serial) : base(serial) + { + } + + public override TalismanForm Form => TalismanForm.Ferret; + + 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(); + } } - public override void Serialize(IGenericWriter writer) + public class SquirrelFormTalisman : BaseFormTalisman { - base.Serialize(writer); + [Constructible] + public SquirrelFormTalisman() + { + } - writer.WriteEncodedInt(0); // version + public SquirrelFormTalisman(Serial serial) : base(serial) + { + } + + public override TalismanForm Form => TalismanForm.Squirrel; + + 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(); + } } - public override void Deserialize(IGenericReader reader) + public class CuSidheFormTalisman : BaseFormTalisman { - base.Deserialize(reader); + [Constructible] + public CuSidheFormTalisman() + { + } - int version = reader.ReadEncodedInt(); + public CuSidheFormTalisman(Serial serial) : base(serial) + { + } + + public override TalismanForm Form => TalismanForm.CuSidhe; + + 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(); + } } - public override void OnRemoved(IEntity parent) + public class ReptalonFormTalisman : BaseFormTalisman { - base.OnRemoved(parent); + [Constructible] + public ReptalonFormTalisman() + { + } - if (parent is Mobile m) AnimalForm.RemoveContext(m, true); + public ReptalonFormTalisman(Serial serial) : base(serial) + { + } + + public override TalismanForm Form => TalismanForm.Reptalon; + + 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(); + } } - - public static bool EntryEnabled(Mobile m, Type type) - { - if (type == typeof(Squirrel)) - return m.Talisman is SquirrelFormTalisman; - if (type == typeof(Ferret)) - return m.Talisman is FerretFormTalisman; - if (type == typeof(CuSidhe)) - return m.Talisman is CuSidheFormTalisman; - if (type == typeof(Reptalon)) - return m.Talisman is ReptalonFormTalisman; - - return true; - } - } - - public class FerretFormTalisman : BaseFormTalisman - { - [Constructible] - public FerretFormTalisman() - { - } - - public FerretFormTalisman(Serial serial) : base(serial) - { - } - - public override TalismanForm Form => TalismanForm.Ferret; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SquirrelFormTalisman : BaseFormTalisman - { - [Constructible] - public SquirrelFormTalisman() - { - } - - public SquirrelFormTalisman(Serial serial) : base(serial) - { - } - - public override TalismanForm Form => TalismanForm.Squirrel; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class CuSidheFormTalisman : BaseFormTalisman - { - [Constructible] - public CuSidheFormTalisman() - { - } - - public CuSidheFormTalisman(Serial serial) : base(serial) - { - } - - public override TalismanForm Form => TalismanForm.CuSidhe; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ReptalonFormTalisman : BaseFormTalisman - { - [Constructible] - public ReptalonFormTalisman() - { - } - - public ReptalonFormTalisman(Serial serial) : base(serial) - { - } - - public override TalismanForm Form => TalismanForm.Reptalon; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/AoS Promotional/HoodedShroudOfShadows.cs b/Projects/UOContent/Items/Special/AoS Promotional/HoodedShroudOfShadows.cs index 5dd1fae5f..6fd872d46 100644 --- a/Projects/UOContent/Items/Special/AoS Promotional/HoodedShroudOfShadows.cs +++ b/Projects/UOContent/Items/Special/AoS Promotional/HoodedShroudOfShadows.cs @@ -1,37 +1,37 @@ namespace Server.Items { - [Flippable(0x2684, 0x2683)] - public class HoodedShroudOfShadows : BaseOuterTorso - { - [Constructible] - public HoodedShroudOfShadows(int hue = 0x455) : base(0x2684, hue) + [Flippable(0x2684, 0x2683)] + public class HoodedShroudOfShadows : BaseOuterTorso { - LootType = LootType.Blessed; - Weight = 3.0; + [Constructible] + public HoodedShroudOfShadows(int hue = 0x455) : base(0x2684, hue) + { + LootType = LootType.Blessed; + Weight = 3.0; + } + + public HoodedShroudOfShadows(Serial serial) : base(serial) + { + } + + public override bool Dye(Mobile from, DyeTub sender) + { + from.SendLocalizedMessage(sender.FailMessage); + return 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 HoodedShroudOfShadows(Serial serial) : base(serial) - { - } - - public override bool Dye(Mobile from, DyeTub sender) - { - from.SendLocalizedMessage(sender.FailMessage); - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/AoS Promotional/LuckyNecklace.cs b/Projects/UOContent/Items/Special/AoS Promotional/LuckyNecklace.cs index 253bfe1c6..dfbf05b36 100644 --- a/Projects/UOContent/Items/Special/AoS Promotional/LuckyNecklace.cs +++ b/Projects/UOContent/Items/Special/AoS Promotional/LuckyNecklace.cs @@ -1,34 +1,34 @@ namespace Server.Items { - public class LuckyNecklace : BaseJewel - { - [Constructible] - public LuckyNecklace() - : base(0x1088, Layer.Neck) + public class LuckyNecklace : BaseJewel { - Attributes.Luck = 200; - LootType = LootType.Blessed; + [Constructible] + public LuckyNecklace() + : base(0x1088, Layer.Neck) + { + Attributes.Luck = 200; + LootType = LootType.Blessed; + } + + public LuckyNecklace(Serial serial) : base(serial) + { + } + + public override int Hue => 1150; + public override int LabelNumber => 1075239; // Lucky Necklace 1075239 + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + reader.ReadInt(); /* int version = reader.ReadInt(); Why? Just to have an unused var? */ + } } - - public LuckyNecklace(Serial serial) : base(serial) - { - } - - public override int Hue => 1150; - public override int LabelNumber => 1075239; // Lucky Necklace 1075239 - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - reader.ReadInt(); /* int version = reader.ReadInt(); Why? Just to have an unused var? */ - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenArmoire.cs b/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenArmoire.cs index 0bff7fe56..5ba8d6d55 100644 --- a/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenArmoire.cs +++ b/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenArmoire.cs @@ -1,86 +1,86 @@ namespace Server.Items { - [Flippable(0xC12, 0xC13)] - public class BrokenArmoireComponent : AddonComponent - { - public BrokenArmoireComponent() : base(0xC12) + [Flippable(0xC12, 0xC13)] + public class BrokenArmoireComponent : AddonComponent { + public BrokenArmoireComponent() : base(0xC12) + { + } + + public BrokenArmoireComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1076262; // Broken Armoire + + 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(); + } } - public BrokenArmoireComponent(Serial serial) : base(serial) + public class BrokenArmoireAddon : BaseAddon { + [Constructible] + public BrokenArmoireAddon() + { + AddComponent(new BrokenArmoireComponent(), 0, 0, 0); + } + + public BrokenArmoireAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new BrokenArmoireDeed(); + + 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(); + } } - public override int LabelNumber => 1076262; // Broken Armoire - - public override void Serialize(IGenericWriter writer) + public class BrokenArmoireDeed : BaseAddonDeed { - base.Serialize(writer); + [Constructible] + public BrokenArmoireDeed() => LootType = LootType.Blessed; - writer.WriteEncodedInt(0); // version + public BrokenArmoireDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new BrokenArmoireAddon(); + public override int LabelNumber => 1076262; // Broken Armoire + + 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(); + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BrokenArmoireAddon : BaseAddon - { - [Constructible] - public BrokenArmoireAddon() - { - AddComponent(new BrokenArmoireComponent(), 0, 0, 0); - } - - public BrokenArmoireAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new BrokenArmoireDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BrokenArmoireDeed : BaseAddonDeed - { - [Constructible] - public BrokenArmoireDeed() => LootType = LootType.Blessed; - - public BrokenArmoireDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new BrokenArmoireAddon(); - public override int LabelNumber => 1076262; // Broken Armoire - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenBed.cs b/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenBed.cs index 7742776be..d3217db5b 100644 --- a/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenBed.cs +++ b/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenBed.cs @@ -3,129 +3,129 @@ using Server.Network; namespace Server.Items { - public class BrokenBedAddon : BaseAddon - { - [Constructible] - public BrokenBedAddon(bool east) + public class BrokenBedAddon : BaseAddon { - if (east) // east - { - AddComponent(new LocalizedAddonComponent(0x1895, 1076263), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0x1894, 1076263), 0, 1, 0); - AddComponent(new LocalizedAddonComponent(0x1897, 1076263), 1, 0, 0); - AddComponent(new LocalizedAddonComponent(0x1896, 1076263), 1, 1, 0); - } - else // south - { - AddComponent(new LocalizedAddonComponent(0x1899, 1076263), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0x1898, 1076263), 1, 0, 0); - AddComponent(new LocalizedAddonComponent(0x189B, 1076263), 0, 1, 0); - AddComponent(new LocalizedAddonComponent(0x189A, 1076263), 1, 1, 0); - } + [Constructible] + public BrokenBedAddon(bool east) + { + if (east) // east + { + AddComponent(new LocalizedAddonComponent(0x1895, 1076263), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0x1894, 1076263), 0, 1, 0); + AddComponent(new LocalizedAddonComponent(0x1897, 1076263), 1, 0, 0); + AddComponent(new LocalizedAddonComponent(0x1896, 1076263), 1, 1, 0); + } + else // south + { + AddComponent(new LocalizedAddonComponent(0x1899, 1076263), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0x1898, 1076263), 1, 0, 0); + AddComponent(new LocalizedAddonComponent(0x189B, 1076263), 0, 1, 0); + AddComponent(new LocalizedAddonComponent(0x189A, 1076263), 1, 1, 0); + } + } + + public BrokenBedAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new BrokenBedDeed(); + + 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(); + } } - public BrokenBedAddon(Serial serial) : base(serial) + public class BrokenBedDeed : BaseAddonDeed { + private bool m_East; + + [Constructible] + public BrokenBedDeed() => LootType = LootType.Blessed; + + public BrokenBedDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new BrokenBedAddon(m_East); + public override int LabelNumber => 1076263; // Broken Bed + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new InternalGump(this)); + } + else + { + from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. + } + } + + private void SendTarget(Mobile m) + { + base.OnDoubleClick(m); + } + + 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(); + } + + private class InternalGump : Gump + { + private readonly BrokenBedDeed m_Deed; + + public InternalGump(BrokenBedDeed deed) : base(60, 36) + { + m_Deed = deed; + + AddPage(0); + + AddBackground(0, 0, 273, 324, 0x13BE); + AddImageTiled(10, 10, 253, 20, 0xA40); + AddImageTiled(10, 40, 253, 244, 0xA40); + AddImageTiled(10, 294, 253, 20, 0xA40); + AddAlphaRegion(10, 10, 253, 304); + AddButton(10, 294, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL + AddHtmlLocalized(14, 12, 273, 20, 1076749, 0x7FFF); // Please select your broken bed position + + AddPage(1); + + AddButton(19, 49, 0x845, 0x846, 1); + AddHtmlLocalized(44, 47, 213, 20, 1075386, 0x7FFF); // South + AddButton(19, 73, 0x845, 0x846, 2); + AddHtmlLocalized(44, 71, 213, 20, 1075387, 0x7FFF); // East + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Deed?.Deleted != false || info.ButtonID == 0) + return; + + m_Deed.m_East = info.ButtonID != 1; + m_Deed.SendTarget(sender.Mobile); + } + } } - - public override BaseAddonDeed Deed => new BrokenBedDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BrokenBedDeed : BaseAddonDeed - { - private bool m_East; - - [Constructible] - public BrokenBedDeed() => LootType = LootType.Blessed; - - public BrokenBedDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new BrokenBedAddon(m_East); - public override int LabelNumber => 1076263; // Broken Bed - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new InternalGump(this)); - } - else - { - from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. - } - } - - private void SendTarget(Mobile m) - { - base.OnDoubleClick(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - private class InternalGump : Gump - { - private readonly BrokenBedDeed m_Deed; - - public InternalGump(BrokenBedDeed deed) : base(60, 36) - { - m_Deed = deed; - - AddPage(0); - - AddBackground(0, 0, 273, 324, 0x13BE); - AddImageTiled(10, 10, 253, 20, 0xA40); - AddImageTiled(10, 40, 253, 244, 0xA40); - AddImageTiled(10, 294, 253, 20, 0xA40); - AddAlphaRegion(10, 10, 253, 304); - AddButton(10, 294, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL - AddHtmlLocalized(14, 12, 273, 20, 1076749, 0x7FFF); // Please select your broken bed position - - AddPage(1); - - AddButton(19, 49, 0x845, 0x846, 1); - AddHtmlLocalized(44, 47, 213, 20, 1075386, 0x7FFF); // South - AddButton(19, 73, 0x845, 0x846, 2); - AddHtmlLocalized(44, 71, 213, 20, 1075387, 0x7FFF); // East - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Deed?.Deleted != false || info.ButtonID == 0) - return; - - m_Deed.m_East = info.ButtonID != 1; - m_Deed.SendTarget(sender.Mobile); - } - } - } } diff --git a/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenBookcase.cs b/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenBookcase.cs index 34d970a1a..97a9909dd 100644 --- a/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenBookcase.cs +++ b/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenBookcase.cs @@ -1,86 +1,86 @@ namespace Server.Items { - [Flippable(0xC14, 0xC15)] - public class BrokenBookcaseComponent : AddonComponent - { - public BrokenBookcaseComponent() : base(0xC14) + [Flippable(0xC14, 0xC15)] + public class BrokenBookcaseComponent : AddonComponent { + public BrokenBookcaseComponent() : base(0xC14) + { + } + + public BrokenBookcaseComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1076258; // Broken Bookcase + + 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(); + } } - public BrokenBookcaseComponent(Serial serial) : base(serial) + public class BrokenBookcaseAddon : BaseAddon { + [Constructible] + public BrokenBookcaseAddon() + { + AddComponent(new BrokenBookcaseComponent(), 0, 0, 0); + } + + public BrokenBookcaseAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new BrokenBookcaseDeed(); + + 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(); + } } - public override int LabelNumber => 1076258; // Broken Bookcase - - public override void Serialize(IGenericWriter writer) + public class BrokenBookcaseDeed : BaseAddonDeed { - base.Serialize(writer); + [Constructible] + public BrokenBookcaseDeed() => LootType = LootType.Blessed; - writer.WriteEncodedInt(0); // version + public BrokenBookcaseDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new BrokenBookcaseAddon(); + public override int LabelNumber => 1076258; // Broken Bookcase + + 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(); + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BrokenBookcaseAddon : BaseAddon - { - [Constructible] - public BrokenBookcaseAddon() - { - AddComponent(new BrokenBookcaseComponent(), 0, 0, 0); - } - - public BrokenBookcaseAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new BrokenBookcaseDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BrokenBookcaseDeed : BaseAddonDeed - { - [Constructible] - public BrokenBookcaseDeed() => LootType = LootType.Blessed; - - public BrokenBookcaseDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new BrokenBookcaseAddon(); - public override int LabelNumber => 1076258; // Broken Bookcase - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenChestOfDrawers.cs b/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenChestOfDrawers.cs index 51a08b47b..8140513b7 100644 --- a/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenChestOfDrawers.cs +++ b/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenChestOfDrawers.cs @@ -1,86 +1,86 @@ namespace Server.Items { - [Flippable(0xC24, 0xC25)] - public class BrokenChestOfDrawersComponent : AddonComponent - { - public BrokenChestOfDrawersComponent() : base(0xC24) + [Flippable(0xC24, 0xC25)] + public class BrokenChestOfDrawersComponent : AddonComponent { + public BrokenChestOfDrawersComponent() : base(0xC24) + { + } + + public BrokenChestOfDrawersComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1076261; // Broken Chest of Drawers + + 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(); + } } - public BrokenChestOfDrawersComponent(Serial serial) : base(serial) + public class BrokenChestOfDrawersAddon : BaseAddon { + [Constructible] + public BrokenChestOfDrawersAddon() + { + AddComponent(new BrokenChestOfDrawersComponent(), 0, 0, 0); + } + + public BrokenChestOfDrawersAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new BrokenChestOfDrawersDeed(); + + 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(); + } } - public override int LabelNumber => 1076261; // Broken Chest of Drawers - - public override void Serialize(IGenericWriter writer) + public class BrokenChestOfDrawersDeed : BaseAddonDeed { - base.Serialize(writer); + [Constructible] + public BrokenChestOfDrawersDeed() => LootType = LootType.Blessed; - writer.WriteEncodedInt(0); // version + public BrokenChestOfDrawersDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new BrokenChestOfDrawersAddon(); + public override int LabelNumber => 1076261; // Broken Chest of Drawers + + 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(); + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BrokenChestOfDrawersAddon : BaseAddon - { - [Constructible] - public BrokenChestOfDrawersAddon() - { - AddComponent(new BrokenChestOfDrawersComponent(), 0, 0, 0); - } - - public BrokenChestOfDrawersAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new BrokenChestOfDrawersDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BrokenChestOfDrawersDeed : BaseAddonDeed - { - [Constructible] - public BrokenChestOfDrawersDeed() => LootType = LootType.Blessed; - - public BrokenChestOfDrawersDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new BrokenChestOfDrawersAddon(); - public override int LabelNumber => 1076261; // Broken Chest of Drawers - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenCoveredChair.cs b/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenCoveredChair.cs index 67466d6d6..eed754113 100644 --- a/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenCoveredChair.cs +++ b/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenCoveredChair.cs @@ -1,86 +1,86 @@ namespace Server.Items { - [Flippable(0xC17, 0xC18)] - public class BrokenCoveredChairComponent : AddonComponent - { - public BrokenCoveredChairComponent() : base(0xC17) + [Flippable(0xC17, 0xC18)] + public class BrokenCoveredChairComponent : AddonComponent { + public BrokenCoveredChairComponent() : base(0xC17) + { + } + + public BrokenCoveredChairComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1076257; // Broken Covered Chair + + 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(); + } } - public BrokenCoveredChairComponent(Serial serial) : base(serial) + public class BrokenCoveredChairAddon : BaseAddon { + [Constructible] + public BrokenCoveredChairAddon() + { + AddComponent(new BrokenCoveredChairComponent(), 0, 0, 0); + } + + public BrokenCoveredChairAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new BrokenCoveredChairDeed(); + + 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(); + } } - public override int LabelNumber => 1076257; // Broken Covered Chair - - public override void Serialize(IGenericWriter writer) + public class BrokenCoveredChairDeed : BaseAddonDeed { - base.Serialize(writer); + [Constructible] + public BrokenCoveredChairDeed() => LootType = LootType.Blessed; - writer.WriteEncodedInt(0); // version + public BrokenCoveredChairDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new BrokenCoveredChairAddon(); + public override int LabelNumber => 1076257; // Broken Covered Chair + + 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(); + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BrokenCoveredChairAddon : BaseAddon - { - [Constructible] - public BrokenCoveredChairAddon() - { - AddComponent(new BrokenCoveredChairComponent(), 0, 0, 0); - } - - public BrokenCoveredChairAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new BrokenCoveredChairDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BrokenCoveredChairDeed : BaseAddonDeed - { - [Constructible] - public BrokenCoveredChairDeed() => LootType = LootType.Blessed; - - public BrokenCoveredChairDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new BrokenCoveredChairAddon(); - public override int LabelNumber => 1076257; // Broken Covered Chair - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenFallenChair.cs b/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenFallenChair.cs index 33fcaa0c2..35fa64e9c 100644 --- a/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenFallenChair.cs +++ b/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenFallenChair.cs @@ -1,89 +1,89 @@ namespace Server.Items { - [Flippable(0xC19, 0xC1A)] - public class BrokenFallenChairComponent : AddonComponent - { - public BrokenFallenChairComponent() : base(0xC19) + [Flippable(0xC19, 0xC1A)] + public class BrokenFallenChairComponent : AddonComponent { + public BrokenFallenChairComponent() : base(0xC19) + { + } + + public BrokenFallenChairComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1076264; // Broken Fallen Chair + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(1); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + if (version < 1 && ItemID == 0xC17) + ItemID = 0xC19; + } } - public BrokenFallenChairComponent(Serial serial) : base(serial) + public class BrokenFallenChairAddon : BaseAddon { + [Constructible] + public BrokenFallenChairAddon() + { + AddComponent(new BrokenFallenChairComponent(), 0, 0, 0); + } + + public BrokenFallenChairAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new BrokenFallenChairDeed(); + + 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(); + } } - public override int LabelNumber => 1076264; // Broken Fallen Chair - - public override void Serialize(IGenericWriter writer) + public class BrokenFallenChairDeed : BaseAddonDeed { - base.Serialize(writer); + [Constructible] + public BrokenFallenChairDeed() => LootType = LootType.Blessed; - writer.WriteEncodedInt(1); // version + public BrokenFallenChairDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new BrokenFallenChairAddon(); + public override int LabelNumber => 1076264; // Broken Fallen Chair + + 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(); + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - if (version < 1 && ItemID == 0xC17) - ItemID = 0xC19; - } - } - - public class BrokenFallenChairAddon : BaseAddon - { - [Constructible] - public BrokenFallenChairAddon() - { - AddComponent(new BrokenFallenChairComponent(), 0, 0, 0); - } - - public BrokenFallenChairAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new BrokenFallenChairDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BrokenFallenChairDeed : BaseAddonDeed - { - [Constructible] - public BrokenFallenChairDeed() => LootType = LootType.Blessed; - - public BrokenFallenChairDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new BrokenFallenChairAddon(); - public override int LabelNumber => 1076264; // Broken Fallen Chair - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenVanity.cs b/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenVanity.cs index f90c3de05..c85ae547d 100644 --- a/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenVanity.cs +++ b/Projects/UOContent/Items/Special/Broken Furniture Collection/BrokenVanity.cs @@ -3,125 +3,125 @@ using Server.Network; namespace Server.Items { - public class BrokenVanityAddon : BaseAddon - { - [Constructible] - public BrokenVanityAddon(bool east) + public class BrokenVanityAddon : BaseAddon { - if (east) // east - { - AddComponent(new LocalizedAddonComponent(0xC20, 1076260), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0xC21, 1076260), 0, -1, 0); - } - else // south - { - AddComponent(new LocalizedAddonComponent(0xC22, 1076260), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0xC23, 1076260), -1, 0, 0); - } + [Constructible] + public BrokenVanityAddon(bool east) + { + if (east) // east + { + AddComponent(new LocalizedAddonComponent(0xC20, 1076260), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0xC21, 1076260), 0, -1, 0); + } + else // south + { + AddComponent(new LocalizedAddonComponent(0xC22, 1076260), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0xC23, 1076260), -1, 0, 0); + } + } + + public BrokenVanityAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new BrokenVanityDeed(); + + 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(); + } } - public BrokenVanityAddon(Serial serial) : base(serial) + public class BrokenVanityDeed : BaseAddonDeed { + private bool m_East; + + [Constructible] + public BrokenVanityDeed() => LootType = LootType.Blessed; + + public BrokenVanityDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new BrokenVanityAddon(m_East); + public override int LabelNumber => 1076260; // Broken Vanity + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new InternalGump(this)); + } + else + { + from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. + } + } + + private void SendTarget(Mobile m) + { + base.OnDoubleClick(m); + } + + 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(); + } + + private class InternalGump : Gump + { + private readonly BrokenVanityDeed m_Deed; + + public InternalGump(BrokenVanityDeed deed) : base(60, 63) + { + m_Deed = deed; + + AddPage(0); + + AddBackground(0, 0, 273, 324, 0x13BE); + AddImageTiled(10, 10, 253, 20, 0xA40); + AddImageTiled(10, 40, 253, 244, 0xA40); + AddImageTiled(10, 294, 253, 20, 0xA40); + AddAlphaRegion(10, 10, 253, 304); + AddButton(10, 294, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL + AddHtmlLocalized(14, 12, 273, 20, 1076747, 0x7FFF); // Please select your broken vanity position + + AddPage(1); + + AddButton(19, 49, 0x845, 0x846, 1); + AddHtmlLocalized(44, 47, 213, 20, 1075386, 0x7FFF); // South + AddButton(19, 73, 0x845, 0x846, 2); + AddHtmlLocalized(44, 71, 213, 20, 1075387, 0x7FFF); // East + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Deed?.Deleted != false || info.ButtonID == 0) + return; + + m_Deed.m_East = info.ButtonID != 1; + m_Deed.SendTarget(sender.Mobile); + } + } } - - public override BaseAddonDeed Deed => new BrokenVanityDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BrokenVanityDeed : BaseAddonDeed - { - private bool m_East; - - [Constructible] - public BrokenVanityDeed() => LootType = LootType.Blessed; - - public BrokenVanityDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new BrokenVanityAddon(m_East); - public override int LabelNumber => 1076260; // Broken Vanity - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new InternalGump(this)); - } - else - { - from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. - } - } - - private void SendTarget(Mobile m) - { - base.OnDoubleClick(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - private class InternalGump : Gump - { - private readonly BrokenVanityDeed m_Deed; - - public InternalGump(BrokenVanityDeed deed) : base(60, 63) - { - m_Deed = deed; - - AddPage(0); - - AddBackground(0, 0, 273, 324, 0x13BE); - AddImageTiled(10, 10, 253, 20, 0xA40); - AddImageTiled(10, 40, 253, 244, 0xA40); - AddImageTiled(10, 294, 253, 20, 0xA40); - AddAlphaRegion(10, 10, 253, 304); - AddButton(10, 294, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL - AddHtmlLocalized(14, 12, 273, 20, 1076747, 0x7FFF); // Please select your broken vanity position - - AddPage(1); - - AddButton(19, 49, 0x845, 0x846, 1); - AddHtmlLocalized(44, 47, 213, 20, 1075386, 0x7FFF); // South - AddButton(19, 73, 0x845, 0x846, 2); - AddHtmlLocalized(44, 71, 213, 20, 1075387, 0x7FFF); // East - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Deed?.Deleted != false || info.ButtonID == 0) - return; - - m_Deed.m_East = info.ButtonID != 1; - m_Deed.SendTarget(sender.Mobile); - } - } - } } diff --git a/Projects/UOContent/Items/Special/Broken Furniture Collection/StandingBrokenChair.cs b/Projects/UOContent/Items/Special/Broken Furniture Collection/StandingBrokenChair.cs index ffb257716..2b38c2ed8 100644 --- a/Projects/UOContent/Items/Special/Broken Furniture Collection/StandingBrokenChair.cs +++ b/Projects/UOContent/Items/Special/Broken Furniture Collection/StandingBrokenChair.cs @@ -1,86 +1,86 @@ namespace Server.Items { - [Flippable(0xC1B, 0xC1C, 0xC1E, 0xC1D)] - public class StandingBrokenChairComponent : AddonComponent - { - public StandingBrokenChairComponent() : base(0xC1B) + [Flippable(0xC1B, 0xC1C, 0xC1E, 0xC1D)] + public class StandingBrokenChairComponent : AddonComponent { + public StandingBrokenChairComponent() : base(0xC1B) + { + } + + public StandingBrokenChairComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1076259; // Standing Broken Chair + + 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(); + } } - public StandingBrokenChairComponent(Serial serial) : base(serial) + public class StandingBrokenChairAddon : BaseAddon { + [Constructible] + public StandingBrokenChairAddon() + { + AddComponent(new StandingBrokenChairComponent(), 0, 0, 0); + } + + public StandingBrokenChairAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new StandingBrokenChairDeed(); + + 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(); + } } - public override int LabelNumber => 1076259; // Standing Broken Chair - - public override void Serialize(IGenericWriter writer) + public class StandingBrokenChairDeed : BaseAddonDeed { - base.Serialize(writer); + [Constructible] + public StandingBrokenChairDeed() => LootType = LootType.Blessed; - writer.WriteEncodedInt(0); // version + public StandingBrokenChairDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new StandingBrokenChairAddon(); + public override int LabelNumber => 1076259; // Standing Broken Chair + + 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(); + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class StandingBrokenChairAddon : BaseAddon - { - [Constructible] - public StandingBrokenChairAddon() - { - AddComponent(new StandingBrokenChairComponent(), 0, 0, 0); - } - - public StandingBrokenChairAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new StandingBrokenChairDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class StandingBrokenChairDeed : BaseAddonDeed - { - [Constructible] - public StandingBrokenChairDeed() => LootType = LootType.Blessed; - - public StandingBrokenChairDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new StandingBrokenChairAddon(); - public override int LabelNumber => 1076259; // Standing Broken Chair - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Bulk Order Rewards/Blacksmithy/AncientSmithyHammer.cs b/Projects/UOContent/Items/Special/Bulk Order Rewards/Blacksmithy/AncientSmithyHammer.cs index e573706eb..5b322324c 100644 --- a/Projects/UOContent/Items/Special/Bulk Order Rewards/Blacksmithy/AncientSmithyHammer.cs +++ b/Projects/UOContent/Items/Special/Bulk Order Rewards/Blacksmithy/AncientSmithyHammer.cs @@ -2,119 +2,119 @@ using Server.Engines.Craft; namespace Server.Items { - [Flippable(0x13E4, 0x13E3)] - public class AncientSmithyHammer : BaseTool - { - private int m_Bonus; - private SkillMod m_SkillMod; - - [Constructible] - public AncientSmithyHammer(int bonus, int uses = 600) : base(uses, 0x13E4) + [Flippable(0x13E4, 0x13E3)] + public class AncientSmithyHammer : BaseTool { - m_Bonus = bonus; - Weight = 8.0; - Layer = Layer.OneHanded; - Hue = 0x482; - } + private int m_Bonus; + private SkillMod m_SkillMod; - public AncientSmithyHammer(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Bonus - { - get => m_Bonus; - set - { - m_Bonus = value; - InvalidateProperties(); - - if (m_Bonus == 0) + [Constructible] + public AncientSmithyHammer(int bonus, int uses = 600) : base(uses, 0x13E4) { - m_SkillMod?.Remove(); - - m_SkillMod = null; + m_Bonus = bonus; + Weight = 8.0; + Layer = Layer.OneHanded; + Hue = 0x482; } - else if (m_SkillMod == null && Parent is Mobile mobile) + + public AncientSmithyHammer(Serial serial) : base(serial) { - m_SkillMod = new DefaultSkillMod(SkillName.Blacksmith, true, m_Bonus); - mobile.AddSkillMod(m_SkillMod); } - else if (m_SkillMod != null) + + [CommandProperty(AccessLevel.GameMaster)] + public int Bonus { - m_SkillMod.Value = m_Bonus; + get => m_Bonus; + set + { + m_Bonus = value; + InvalidateProperties(); + + if (m_Bonus == 0) + { + m_SkillMod?.Remove(); + + m_SkillMod = null; + } + else if (m_SkillMod == null && Parent is Mobile mobile) + { + m_SkillMod = new DefaultSkillMod(SkillName.Blacksmith, true, m_Bonus); + mobile.AddSkillMod(m_SkillMod); + } + else if (m_SkillMod != null) + { + m_SkillMod.Value = m_Bonus; + } + } + } + + public override CraftSystem CraftSystem => DefBlacksmithy.CraftSystem; + public override int LabelNumber => 1045127; // ancient smithy hammer + + public override void OnAdded(IEntity parent) + { + base.OnAdded(parent); + + if (m_Bonus != 0 && parent is Mobile mobile) + { + m_SkillMod?.Remove(); + + m_SkillMod = new DefaultSkillMod(SkillName.Blacksmith, true, m_Bonus); + mobile.AddSkillMod(m_SkillMod); + } + } + + public override void OnRemoved(IEntity parent) + { + base.OnRemoved(parent); + + m_SkillMod?.Remove(); + + m_SkillMod = null; + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_Bonus != 0) + list.Add(1060451, "#1042354\t{0}", m_Bonus.ToString()); // ~1_skillname~ +~2_val~ + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Bonus); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Bonus = reader.ReadInt(); + break; + } + } + + if (m_Bonus != 0 && Parent is Mobile mobile) + { + m_SkillMod?.Remove(); + + m_SkillMod = new DefaultSkillMod(SkillName.Blacksmith, true, m_Bonus); + mobile.AddSkillMod(m_SkillMod); + } + + if (Hue == 0) + Hue = 0x482; } - } } - - public override CraftSystem CraftSystem => DefBlacksmithy.CraftSystem; - public override int LabelNumber => 1045127; // ancient smithy hammer - - public override void OnAdded(IEntity parent) - { - base.OnAdded(parent); - - if (m_Bonus != 0 && parent is Mobile mobile) - { - m_SkillMod?.Remove(); - - m_SkillMod = new DefaultSkillMod(SkillName.Blacksmith, true, m_Bonus); - mobile.AddSkillMod(m_SkillMod); - } - } - - public override void OnRemoved(IEntity parent) - { - base.OnRemoved(parent); - - m_SkillMod?.Remove(); - - m_SkillMod = null; - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_Bonus != 0) - list.Add(1060451, "#1042354\t{0}", m_Bonus.ToString()); // ~1_skillname~ +~2_val~ - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Bonus); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Bonus = reader.ReadInt(); - break; - } - } - - if (m_Bonus != 0 && Parent is Mobile mobile) - { - m_SkillMod?.Remove(); - - m_SkillMod = new DefaultSkillMod(SkillName.Blacksmith, true, m_Bonus); - mobile.AddSkillMod(m_SkillMod); - } - - if (Hue == 0) - Hue = 0x482; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Bulk Order Rewards/Blacksmithy/ColoredAnvil.cs b/Projects/UOContent/Items/Special/Bulk Order Rewards/Blacksmithy/ColoredAnvil.cs index 4ba405cf9..3924fa683 100644 --- a/Projects/UOContent/Items/Special/Bulk Order Rewards/Blacksmithy/ColoredAnvil.cs +++ b/Projects/UOContent/Items/Special/Bulk Order Rewards/Blacksmithy/ColoredAnvil.cs @@ -2,37 +2,40 @@ using Server.Engines.Craft; namespace Server.Items { - [Anvil] - [Flippable(0xFAF, 0xFB0)] - public class ColoredAnvil : Item - { - [Constructible] - public ColoredAnvil() : this(CraftResources.GetHue( - (CraftResource)Utility.RandomMinMax((int)CraftResource.DullCopper, (int)CraftResource.Valorite))) + [Anvil] + [Flippable(0xFAF, 0xFB0)] + public class ColoredAnvil : Item { - } + [Constructible] + public ColoredAnvil() : this( + CraftResources.GetHue( + (CraftResource)Utility.RandomMinMax((int)CraftResource.DullCopper, (int)CraftResource.Valorite) + ) + ) + { + } - [Constructible] - public ColoredAnvil(int hue) : base(0xFAF) - { - Hue = hue; - Weight = 20; - } + [Constructible] + public ColoredAnvil(int hue) : base(0xFAF) + { + Hue = hue; + Weight = 20; + } - public ColoredAnvil(Serial serial) : base(serial) - { - } + public ColoredAnvil(Serial serial) : base(serial) + { + } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(0); + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Bulk Order Rewards/Blacksmithy/GlovesOfMining.cs b/Projects/UOContent/Items/Special/Bulk Order Rewards/Blacksmithy/GlovesOfMining.cs index 81d52455b..237d52d15 100644 --- a/Projects/UOContent/Items/Special/Bulk Order Rewards/Blacksmithy/GlovesOfMining.cs +++ b/Projects/UOContent/Items/Special/Bulk Order Rewards/Blacksmithy/GlovesOfMining.cs @@ -1,239 +1,240 @@ namespace Server.Items { - [Flippable(0x13c6, 0x13ce)] - public class LeatherGlovesOfMining : BaseGlovesOfMining - { - [Constructible] - public LeatherGlovesOfMining(int bonus) : base(bonus, 0x13C6) => Weight = 1; - - public LeatherGlovesOfMining(Serial serial) : base(serial) + [Flippable(0x13c6, 0x13ce)] + public class LeatherGlovesOfMining : BaseGlovesOfMining { - } + [Constructible] + public LeatherGlovesOfMining(int bonus) : base(bonus, 0x13C6) => Weight = 1; - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 30; - public override int InitMaxHits => 40; - - public override int AosStrReq => 20; - public override int OldStrReq => 10; - - public override int ArmorBase => 13; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; - - public override int LabelNumber => 1045122; // leather blacksmith gloves of mining - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - [Flippable(0x13d5, 0x13dd)] - public class StuddedGlovesOfMining : BaseGlovesOfMining - { - [Constructible] - public StuddedGlovesOfMining(int bonus) : base(bonus, 0x13D5) => Weight = 2; - - public StuddedGlovesOfMining(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 2; - public override int BaseFireResistance => 4; - public override int BaseColdResistance => 3; - public override int BasePoisonResistance => 3; - public override int BaseEnergyResistance => 4; - - public override int InitMinHits => 35; - public override int InitMaxHits => 45; - - public override int AosStrReq => 25; - public override int OldStrReq => 25; - - public override int ArmorBase => 16; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; - public override CraftResource DefaultResource => CraftResource.RegularLeather; - - public override int LabelNumber => 1045123; // studded leather blacksmith gloves of mining - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - [Flippable(0x13eb, 0x13f2)] - public class RingmailGlovesOfMining : BaseGlovesOfMining - { - [Constructible] - public RingmailGlovesOfMining(int bonus) : base(bonus, 0x13EB) => Weight = 1; - - public RingmailGlovesOfMining(Serial serial) : base(serial) - { - } - - public override int BasePhysicalResistance => 3; - public override int BaseFireResistance => 3; - public override int BaseColdResistance => 1; - public override int BasePoisonResistance => 5; - public override int BaseEnergyResistance => 3; - - public override int InitMinHits => 40; - public override int InitMaxHits => 50; - - public override int AosStrReq => 40; - public override int OldStrReq => 20; - - public override int OldDexBonus => -1; - - public override int ArmorBase => 22; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Ringmail; - - public override int LabelNumber => 1045124; // ringmail blacksmith gloves of mining - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public abstract class BaseGlovesOfMining : BaseArmor - { - private int m_Bonus; - private SkillMod m_SkillMod; - - public BaseGlovesOfMining(int bonus, int itemID) : base(itemID) - { - m_Bonus = bonus; - - Hue = CraftResources.GetHue( - (CraftResource)Utility.RandomMinMax((int)CraftResource.DullCopper, (int)CraftResource.Valorite)); - } - - public BaseGlovesOfMining(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Bonus - { - get => m_Bonus; - set - { - m_Bonus = value; - InvalidateProperties(); - - if (m_Bonus == 0) + public LeatherGlovesOfMining(Serial serial) : base(serial) { - m_SkillMod?.Remove(); - - m_SkillMod = null; } - else if (m_SkillMod == null && Parent is Mobile mobile) + + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 30; + public override int InitMaxHits => 40; + + public override int AosStrReq => 20; + public override int OldStrReq => 10; + + public override int ArmorBase => 13; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Leather; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override ArmorMeditationAllowance DefMedAllowance => ArmorMeditationAllowance.All; + + public override int LabelNumber => 1045122; // leather blacksmith gloves of mining + + public override void Serialize(IGenericWriter writer) { - m_SkillMod = new DefaultSkillMod(SkillName.Mining, true, m_Bonus); - mobile.AddSkillMod(m_SkillMod); + base.Serialize(writer); + writer.Write(0); } - else if (m_SkillMod != null) + + public override void Deserialize(IGenericReader reader) { - m_SkillMod.Value = m_Bonus; + base.Deserialize(reader); + var version = reader.ReadInt(); } - } } - public override void OnAdded(IEntity parent) + [Flippable(0x13d5, 0x13dd)] + public class StuddedGlovesOfMining : BaseGlovesOfMining { - base.OnAdded(parent); + [Constructible] + public StuddedGlovesOfMining(int bonus) : base(bonus, 0x13D5) => Weight = 2; - if (m_Bonus != 0 && parent is Mobile mobile) - { - m_SkillMod?.Remove(); + public StuddedGlovesOfMining(Serial serial) : base(serial) + { + } - m_SkillMod = new DefaultSkillMod(SkillName.Mining, true, m_Bonus); - mobile.AddSkillMod(m_SkillMod); - } + public override int BasePhysicalResistance => 2; + public override int BaseFireResistance => 4; + public override int BaseColdResistance => 3; + public override int BasePoisonResistance => 3; + public override int BaseEnergyResistance => 4; + + public override int InitMinHits => 35; + public override int InitMaxHits => 45; + + public override int AosStrReq => 25; + public override int OldStrReq => 25; + + public override int ArmorBase => 16; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Studded; + public override CraftResource DefaultResource => CraftResource.RegularLeather; + + public override int LabelNumber => 1045123; // studded leather blacksmith gloves of mining + + 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(); + } } - public override void OnRemoved(IEntity parent) + [Flippable(0x13eb, 0x13f2)] + public class RingmailGlovesOfMining : BaseGlovesOfMining { - base.OnRemoved(parent); + [Constructible] + public RingmailGlovesOfMining(int bonus) : base(bonus, 0x13EB) => Weight = 1; - m_SkillMod?.Remove(); + public RingmailGlovesOfMining(Serial serial) : base(serial) + { + } - m_SkillMod = null; + public override int BasePhysicalResistance => 3; + public override int BaseFireResistance => 3; + public override int BaseColdResistance => 1; + public override int BasePoisonResistance => 5; + public override int BaseEnergyResistance => 3; + + public override int InitMinHits => 40; + public override int InitMaxHits => 50; + + public override int AosStrReq => 40; + public override int OldStrReq => 20; + + public override int OldDexBonus => -1; + + public override int ArmorBase => 22; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Ringmail; + + public override int LabelNumber => 1045124; // ringmail blacksmith gloves of mining + + 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(); + } } - public override void GetProperties(ObjectPropertyList list) + public abstract class BaseGlovesOfMining : BaseArmor { - base.GetProperties(list); + private int m_Bonus; + private SkillMod m_SkillMod; - if (m_Bonus != 0) - list.Add(1062005, m_Bonus.ToString()); // mining bonus +~1_val~ + public BaseGlovesOfMining(int bonus, int itemID) : base(itemID) + { + m_Bonus = bonus; + + Hue = CraftResources.GetHue( + (CraftResource)Utility.RandomMinMax((int)CraftResource.DullCopper, (int)CraftResource.Valorite) + ); + } + + public BaseGlovesOfMining(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Bonus + { + get => m_Bonus; + set + { + m_Bonus = value; + InvalidateProperties(); + + if (m_Bonus == 0) + { + m_SkillMod?.Remove(); + + m_SkillMod = null; + } + else if (m_SkillMod == null && Parent is Mobile mobile) + { + m_SkillMod = new DefaultSkillMod(SkillName.Mining, true, m_Bonus); + mobile.AddSkillMod(m_SkillMod); + } + else if (m_SkillMod != null) + { + m_SkillMod.Value = m_Bonus; + } + } + } + + public override void OnAdded(IEntity parent) + { + base.OnAdded(parent); + + if (m_Bonus != 0 && parent is Mobile mobile) + { + m_SkillMod?.Remove(); + + m_SkillMod = new DefaultSkillMod(SkillName.Mining, true, m_Bonus); + mobile.AddSkillMod(m_SkillMod); + } + } + + public override void OnRemoved(IEntity parent) + { + base.OnRemoved(parent); + + m_SkillMod?.Remove(); + + m_SkillMod = null; + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_Bonus != 0) + list.Add(1062005, m_Bonus.ToString()); // mining bonus +~1_val~ + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Bonus); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Bonus = reader.ReadInt(); + break; + } + } + + if (m_Bonus != 0 && Parent is Mobile mobile) + { + m_SkillMod?.Remove(); + + m_SkillMod = new DefaultSkillMod(SkillName.Mining, true, m_Bonus); + mobile.AddSkillMod(m_SkillMod); + } + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Bonus); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Bonus = reader.ReadInt(); - break; - } - } - - if (m_Bonus != 0 && Parent is Mobile mobile) - { - m_SkillMod?.Remove(); - - m_SkillMod = new DefaultSkillMod(SkillName.Mining, true, m_Bonus); - mobile.AddSkillMod(m_SkillMod); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Bulk Order Rewards/Blacksmithy/PowderOfTemperament.cs b/Projects/UOContent/Items/Special/Bulk Order Rewards/Blacksmithy/PowderOfTemperament.cs index c84833380..68a59c605 100644 --- a/Projects/UOContent/Items/Special/Bulk Order Rewards/Blacksmithy/PowderOfTemperament.cs +++ b/Projects/UOContent/Items/Special/Bulk Order Rewards/Blacksmithy/PowderOfTemperament.cs @@ -3,182 +3,182 @@ using Server.Targeting; namespace Server.Items { - public class PowderOfTemperament : Item, IUsesRemaining - { - private int m_UsesRemaining; - - [Constructible] - public PowderOfTemperament(int charges = 10) : base(4102) + public class PowderOfTemperament : Item, IUsesRemaining { - Weight = 1.0; - Hue = 2419; - UsesRemaining = charges; - } + private int m_UsesRemaining; - public PowderOfTemperament(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1049082; // powder of fortifying - - [CommandProperty(AccessLevel.GameMaster)] - public int UsesRemaining - { - get => m_UsesRemaining; - set - { - m_UsesRemaining = value; - InvalidateProperties(); - } - } - - bool IUsesRemaining.ShowUsesRemaining - { - get => true; - set { } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - writer.Write(m_UsesRemaining); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_UsesRemaining = reader.ReadInt(); - break; - } - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1060584, m_UsesRemaining.ToString()); // uses remaining: ~1_val~ - } - - public virtual void DisplayDurabilityTo(Mobile m) - { - LabelToAffix(m, 1017323, AffixType.Append, $": {m_UsesRemaining}"); // Durability - } - - public override void OnSingleClick(Mobile from) - { - DisplayDurabilityTo(from); - - base.OnSingleClick(from); - } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - from.Target = new InternalTarget(this); - else - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - - private class InternalTarget : Target - { - private readonly PowderOfTemperament m_Powder; - - public InternalTarget(PowderOfTemperament powder) : base(2, false, TargetFlags.None) => m_Powder = powder; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Powder?.Deleted != false || m_Powder.UsesRemaining <= 0) + [Constructible] + public PowderOfTemperament(int charges = 10) : base(4102) { - from.SendLocalizedMessage(1049086); // You have used up your powder of temperament. - return; + Weight = 1.0; + Hue = 2419; + UsesRemaining = charges; } - if (targeted is Item item && item is IDurability wearable) + public PowderOfTemperament(Serial serial) : base(serial) { - if (!wearable.CanFortify) - { - from.SendLocalizedMessage(1049083); // You cannot use the powder on that item. - return; - } + } - if ((item.IsChildOf(from.Backpack) || (Core.ML && item.Parent == from)) && - m_Powder.IsChildOf(from.Backpack)) - { - int origMaxHP = wearable.MaxHitPoints; - int origCurHP = wearable.HitPoints; + public override int LabelNumber => 1049082; // powder of fortifying - if (origMaxHP > 0) + [CommandProperty(AccessLevel.GameMaster)] + public int UsesRemaining + { + get => m_UsesRemaining; + set { - int initMaxHP = Core.AOS ? 255 : wearable.InitMaxHits; + m_UsesRemaining = value; + InvalidateProperties(); + } + } - wearable.UnscaleDurability(); + bool IUsesRemaining.ShowUsesRemaining + { + get => true; + set { } + } - if (wearable.MaxHitPoints < initMaxHP) - { - int bonus = initMaxHP - wearable.MaxHitPoints; + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - if (bonus > 10) - bonus = 10; + writer.Write(0); + writer.Write(m_UsesRemaining); + } - wearable.MaxHitPoints += bonus; - wearable.HitPoints += bonus; + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - wearable.ScaleDurability(); + var version = reader.ReadInt(); - if (wearable.MaxHitPoints > 255) wearable.MaxHitPoints = 255; - if (wearable.HitPoints > 255) wearable.HitPoints = 255; + switch (version) + { + case 0: + { + m_UsesRemaining = reader.ReadInt(); + break; + } + } + } - if (wearable.MaxHitPoints > origMaxHP) + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1060584, m_UsesRemaining.ToString()); // uses remaining: ~1_val~ + } + + public virtual void DisplayDurabilityTo(Mobile m) + { + LabelToAffix(m, 1017323, AffixType.Append, $": {m_UsesRemaining}"); // Durability + } + + public override void OnSingleClick(Mobile from) + { + DisplayDurabilityTo(from); + + base.OnSingleClick(from); + } + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + from.Target = new InternalTarget(this); + else + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + + private class InternalTarget : Target + { + private readonly PowderOfTemperament m_Powder; + + public InternalTarget(PowderOfTemperament powder) : base(2, false, TargetFlags.None) => m_Powder = powder; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Powder?.Deleted != false || m_Powder.UsesRemaining <= 0) { - from.SendLocalizedMessage(1049084); // You successfully use the powder on the item. - from.PlaySound(0x247); + from.SendLocalizedMessage(1049086); // You have used up your powder of temperament. + return; + } - --m_Powder.UsesRemaining; + if (targeted is Item item && item is IDurability wearable) + { + if (!wearable.CanFortify) + { + from.SendLocalizedMessage(1049083); // You cannot use the powder on that item. + return; + } - if (m_Powder.UsesRemaining <= 0) - { - from.SendLocalizedMessage(1049086); // You have used up your powder of fortifying. - m_Powder.Delete(); - } + if ((item.IsChildOf(from.Backpack) || Core.ML && item.Parent == @from) && + m_Powder.IsChildOf(from.Backpack)) + { + var origMaxHP = wearable.MaxHitPoints; + var origCurHP = wearable.HitPoints; + + if (origMaxHP > 0) + { + var initMaxHP = Core.AOS ? 255 : wearable.InitMaxHits; + + wearable.UnscaleDurability(); + + if (wearable.MaxHitPoints < initMaxHP) + { + var bonus = initMaxHP - wearable.MaxHitPoints; + + if (bonus > 10) + bonus = 10; + + wearable.MaxHitPoints += bonus; + wearable.HitPoints += bonus; + + wearable.ScaleDurability(); + + if (wearable.MaxHitPoints > 255) wearable.MaxHitPoints = 255; + if (wearable.HitPoints > 255) wearable.HitPoints = 255; + + if (wearable.MaxHitPoints > origMaxHP) + { + from.SendLocalizedMessage(1049084); // You successfully use the powder on the item. + from.PlaySound(0x247); + + --m_Powder.UsesRemaining; + + if (m_Powder.UsesRemaining <= 0) + { + from.SendLocalizedMessage(1049086); // You have used up your powder of fortifying. + m_Powder.Delete(); + } + } + else + { + wearable.MaxHitPoints = origMaxHP; + wearable.HitPoints = origCurHP; + from.SendLocalizedMessage(1049085); // The item cannot be improved any further. + } + } + else + { + from.SendLocalizedMessage(1049085); // The item cannot be improved any further. + wearable.ScaleDurability(); + } + } + else + { + from.SendLocalizedMessage(1049083); // You cannot use the powder on that item. + } + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } } else { - wearable.MaxHitPoints = origMaxHP; - wearable.HitPoints = origCurHP; - from.SendLocalizedMessage(1049085); // The item cannot be improved any further. + from.SendLocalizedMessage(1049083); // You cannot use the powder on that item. } - } - else - { - from.SendLocalizedMessage(1049085); // The item cannot be improved any further. - wearable.ScaleDurability(); - } } - else - { - from.SendLocalizedMessage(1049083); // You cannot use the powder on that item. - } - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } } - else - { - from.SendLocalizedMessage(1049083); // You cannot use the powder on that item. - } - } } - } } diff --git a/Projects/UOContent/Items/Special/Community Collection/JesterHatofChuckles.cs b/Projects/UOContent/Items/Special/Community Collection/JesterHatofChuckles.cs index 47337766f..24ee2f5e6 100644 --- a/Projects/UOContent/Items/Special/Community Collection/JesterHatofChuckles.cs +++ b/Projects/UOContent/Items/Special/Community Collection/JesterHatofChuckles.cs @@ -1,46 +1,46 @@ namespace Server.Items { - public class JesterHatofChuckles : BaseHat, ITokunoDyable - { - [Constructible] - public JesterHatofChuckles() : this(Utility.RandomList(0x13e, 0x03, 0x172, 0x3f)) + public class JesterHatofChuckles : BaseHat, ITokunoDyable { + [Constructible] + public JesterHatofChuckles() : this(Utility.RandomList(0x13e, 0x03, 0x172, 0x3f)) + { + } + + [Constructible] + public JesterHatofChuckles(int hue) : base(0x171C, hue) + { + Attributes.Luck = 150; + Weight = 1.0; + } + + public JesterHatofChuckles(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073256; // Jester Hat of Chuckles - Museum of Vesper Replica 1073256 + + public override int BasePhysicalResistance => 12; + public override int BaseFireResistance => 12; + public override int BaseColdResistance => 12; + public override int BasePoisonResistance => 12; + public override int BaseEnergyResistance => 12; + + public override int InitMinHits => 100; + public override int InitMaxHits => 100; + + 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(); + } } - - [Constructible] - public JesterHatofChuckles(int hue) : base(0x171C, hue) - { - Attributes.Luck = 150; - Weight = 1.0; - } - - public JesterHatofChuckles(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073256; // Jester Hat of Chuckles - Museum of Vesper Replica 1073256 - - public override int BasePhysicalResistance => 12; - public override int BaseFireResistance => 12; - public override int BaseColdResistance => 12; - public override int BasePoisonResistance => 12; - public override int BaseEnergyResistance => 12; - - public override int InitMinHits => 100; - public override int InitMaxHits => 100; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Evil Home Decor Collection/AwesomeDisturbingPortrait.cs b/Projects/UOContent/Items/Special/Evil Home Decor Collection/AwesomeDisturbingPortrait.cs index 8f1e5b3dc..1fc687dca 100644 --- a/Projects/UOContent/Items/Special/Evil Home Decor Collection/AwesomeDisturbingPortrait.cs +++ b/Projects/UOContent/Items/Special/Evil Home Decor Collection/AwesomeDisturbingPortrait.cs @@ -3,179 +3,181 @@ using Server.Network; namespace Server.Items { - [Flippable(0x2A5D, 0x2A61)] - public class AwesomeDisturbingPortraitComponent : AddonComponent - { - private InternalTimer m_Timer; - - public AwesomeDisturbingPortraitComponent() : base(0x2A5D) + [Flippable(0x2A5D, 0x2A61)] + public class AwesomeDisturbingPortraitComponent : AddonComponent { - m_Timer = new InternalTimer(this, TimeSpan.FromSeconds(1)); - m_Timer.Start(); + private InternalTimer m_Timer; + + public AwesomeDisturbingPortraitComponent() : base(0x2A5D) + { + m_Timer = new InternalTimer(this, TimeSpan.FromSeconds(1)); + m_Timer.Start(); + } + + public AwesomeDisturbingPortraitComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074479; // Disturbing portrait + public bool FacingSouth => ItemID < 0x2A61; + + public override void OnDoubleClick(Mobile from) + { + if (Utility.InRange(Location, from.Location, 2)) + { + Clock.GetTime(Map, X, Y, out var hours, out int _); + + if (hours < 4 || hours > 20) + Effects.PlaySound(Location, Map, 0x569); + + UpdateImage(); + } + else + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + if (m_Timer?.Running == true) + m_Timer.Stop(); + } + + 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(); + + m_Timer = new InternalTimer(this, TimeSpan.Zero); + m_Timer.Start(); + } + + private void UpdateImage() + { + Clock.GetTime(Map, X, Y, out var hours, out int _); + + if (FacingSouth) + { + if (hours < 4) + ItemID = 0x2A60; + else if (hours < 6) + ItemID = 0x2A5F; + else if (hours < 8) + ItemID = 0x2A5E; + else if (hours < 16) + ItemID = 0x2A5D; + else if (hours < 18) + ItemID = 0x2A5E; + else if (hours < 20) + ItemID = 0x2A5F; + else + ItemID = 0x2A60; + } + else + { + if (hours < 4) + ItemID = 0x2A64; + else if (hours < 6) + ItemID = 0x2A63; + else if (hours < 8) + ItemID = 0x2A62; + else if (hours < 16) + ItemID = 0x2A61; + else if (hours < 18) + ItemID = 0x2A62; + else if (hours < 20) + ItemID = 0x2A63; + else + ItemID = 0x2A64; + } + } + + private class InternalTimer : Timer + { + private readonly AwesomeDisturbingPortraitComponent m_Component; + + public InternalTimer(AwesomeDisturbingPortraitComponent c, TimeSpan delay) : base( + delay, + TimeSpan.FromMinutes(10) + ) + { + m_Component = c; + + Priority = TimerPriority.OneMinute; + } + + protected override void OnTick() + { + if (m_Component?.Deleted == false) + m_Component.UpdateImage(); + } + } } - public AwesomeDisturbingPortraitComponent(Serial serial) : base(serial) + public class AwesomeDisturbingPortraitAddon : BaseAddon { + [Constructible] + public AwesomeDisturbingPortraitAddon() + { + AddComponent(new AwesomeDisturbingPortraitComponent(), 0, 0, 0); + } + + public AwesomeDisturbingPortraitAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new AwesomeDisturbingPortraitDeed(); + + 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(); + } } - public override int LabelNumber => 1074479; // Disturbing portrait - public bool FacingSouth => ItemID < 0x2A61; - - public override void OnDoubleClick(Mobile from) + public class AwesomeDisturbingPortraitDeed : BaseAddonDeed { - if (Utility.InRange(Location, from.Location, 2)) - { - Clock.GetTime(Map, X, Y, out int hours, out int _); + [Constructible] + public AwesomeDisturbingPortraitDeed() => LootType = LootType.Blessed; - if (hours < 4 || hours > 20) - Effects.PlaySound(Location, Map, 0x569); + public AwesomeDisturbingPortraitDeed(Serial serial) : base(serial) + { + } - UpdateImage(); - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } + public override BaseAddon Addon => new AwesomeDisturbingPortraitAddon(); + public override int LabelNumber => 1074479; // Disturbing portrait + + 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(); + } } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - if (m_Timer?.Running == true) - m_Timer.Stop(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_Timer = new InternalTimer(this, TimeSpan.Zero); - m_Timer.Start(); - } - - private void UpdateImage() - { - Clock.GetTime(Map, X, Y, out int hours, out int _); - - if (FacingSouth) - { - if (hours < 4) - ItemID = 0x2A60; - else if (hours < 6) - ItemID = 0x2A5F; - else if (hours < 8) - ItemID = 0x2A5E; - else if (hours < 16) - ItemID = 0x2A5D; - else if (hours < 18) - ItemID = 0x2A5E; - else if (hours < 20) - ItemID = 0x2A5F; - else - ItemID = 0x2A60; - } - else - { - if (hours < 4) - ItemID = 0x2A64; - else if (hours < 6) - ItemID = 0x2A63; - else if (hours < 8) - ItemID = 0x2A62; - else if (hours < 16) - ItemID = 0x2A61; - else if (hours < 18) - ItemID = 0x2A62; - else if (hours < 20) - ItemID = 0x2A63; - else - ItemID = 0x2A64; - } - } - - private class InternalTimer : Timer - { - private readonly AwesomeDisturbingPortraitComponent m_Component; - - public InternalTimer(AwesomeDisturbingPortraitComponent c, TimeSpan delay) : base(delay, - TimeSpan.FromMinutes(10)) - { - m_Component = c; - - Priority = TimerPriority.OneMinute; - } - - protected override void OnTick() - { - if (m_Component?.Deleted == false) - m_Component.UpdateImage(); - } - } - } - - public class AwesomeDisturbingPortraitAddon : BaseAddon - { - [Constructible] - public AwesomeDisturbingPortraitAddon() - { - AddComponent(new AwesomeDisturbingPortraitComponent(), 0, 0, 0); - } - - public AwesomeDisturbingPortraitAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new AwesomeDisturbingPortraitDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class AwesomeDisturbingPortraitDeed : BaseAddonDeed - { - [Constructible] - public AwesomeDisturbingPortraitDeed() => LootType = LootType.Blessed; - - public AwesomeDisturbingPortraitDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new AwesomeDisturbingPortraitAddon(); - public override int LabelNumber => 1074479; // Disturbing portrait - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/Evil Home Decor Collection/BedOfNails.cs b/Projects/UOContent/Items/Special/Evil Home Decor Collection/BedOfNails.cs index c7213ebd9..3fcda6d44 100644 --- a/Projects/UOContent/Items/Special/Evil Home Decor Collection/BedOfNails.cs +++ b/Projects/UOContent/Items/Special/Evil Home Decor Collection/BedOfNails.cs @@ -2,185 +2,185 @@ using System; namespace Server.Items { - public class BedOfNailsComponent : AddonComponent - { - public BedOfNailsComponent(int itemID) - : base(itemID) + public class BedOfNailsComponent : AddonComponent { - } - - public BedOfNailsComponent(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1074801; // Bed of Nails - - public override bool OnMoveOver(Mobile m) - { - bool allow = base.OnMoveOver(m); - - if (allow && Addon is BedOfNailsAddon addon) - addon.OnMoveOver(m); - - return allow; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - [FlippableAddon(Direction.South, Direction.East)] - public class BedOfNailsAddon : BaseAddon - { - private InternalTimer m_Timer; - - [Constructible] - public BedOfNailsAddon() - { - Direction = Direction.South; - - AddComponent(new BedOfNailsComponent(0x2A81), 0, 0, 0); - AddComponent(new BedOfNailsComponent(0x2A82), 0, -1, 0); - } - - public BedOfNailsAddon(Serial serial) - : base(serial) - { - } - - public override BaseAddonDeed Deed => new BedOfNailsDeed(); - - public override bool OnMoveOver(Mobile m) - { - if (m.Alive && (m.AccessLevel == AccessLevel.Player || !m.Hidden)) - { - if (m.Player) + public BedOfNailsComponent(int itemID) + : base(itemID) { - if (m.Female) - Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x53B, 0x53D)); - else - Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x53E, 0x540)); } - if (m_Timer?.Running != true) - (m_Timer = new InternalTimer(m)).Start(); - } - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - public virtual void Flip(Mobile from, Direction direction) - { - switch (direction) - { - case Direction.East: - AddComponent(new BedOfNailsComponent(0x2A89), 0, 0, 0); - AddComponent(new BedOfNailsComponent(0x2A8A), -1, 0, 0); - break; - case Direction.South: - AddComponent(new BedOfNailsComponent(0x2A81), 0, 0, 0); - AddComponent(new BedOfNailsComponent(0x2A82), 0, -1, 0); - break; - } - } - - private class InternalTimer : Timer - { - private Point3D m_Location; - private readonly Mobile m_Mobile; - - public InternalTimer(Mobile m) - : base(TimeSpan.Zero, TimeSpan.FromSeconds(1), 5) - { - m_Mobile = m; - m_Location = Point3D.Zero; - } - - protected override void OnTick() - { - if (m_Mobile?.Map == null || m_Mobile.Deleted || !m_Mobile.Alive || m_Mobile.Map == Map.Internal) + public BedOfNailsComponent(Serial serial) + : base(serial) { - Stop(); } - else if (m_Location != m_Mobile.Location) + + public override int LabelNumber => 1074801; // Bed of Nails + + public override bool OnMoveOver(Mobile m) { - int amount = Utility.RandomMinMax(0, 7); + var allow = base.OnMoveOver(m); - for (int i = 0; i < amount; i++) - { - int x = m_Mobile.X + Utility.RandomMinMax(-1, 1); - int y = m_Mobile.Y + Utility.RandomMinMax(-1, 1); - int z = m_Mobile.Z; + if (allow && Addon is BedOfNailsAddon addon) + addon.OnMoveOver(m); - if (!m_Mobile.Map.CanFit(x, y, z, 1, false, false)) + return allow; + } + + 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(); + } + } + + [FlippableAddon(Direction.South, Direction.East)] + public class BedOfNailsAddon : BaseAddon + { + private InternalTimer m_Timer; + + [Constructible] + public BedOfNailsAddon() + { + Direction = Direction.South; + + AddComponent(new BedOfNailsComponent(0x2A81), 0, 0, 0); + AddComponent(new BedOfNailsComponent(0x2A82), 0, -1, 0); + } + + public BedOfNailsAddon(Serial serial) + : base(serial) + { + } + + public override BaseAddonDeed Deed => new BedOfNailsDeed(); + + public override bool OnMoveOver(Mobile m) + { + if (m.Alive && (m.AccessLevel == AccessLevel.Player || !m.Hidden)) { - z = m_Mobile.Map.GetAverageZ(x, y); + if (m.Player) + { + if (m.Female) + Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x53B, 0x53D)); + else + Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x53E, 0x540)); + } - if (!m_Mobile.Map.CanFit(x, y, z, 1, false, false)) - continue; + if (m_Timer?.Running != true) + (m_Timer = new InternalTimer(m)).Start(); } - Blood blood = new Blood(Utility.RandomMinMax(0x122C, 0x122F)); - blood.MoveToWorld(new Point3D(x, y, z), m_Mobile.Map); - } - - m_Location = m_Mobile.Location; + return true; + } + + 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(); + } + + public virtual void Flip(Mobile from, Direction direction) + { + switch (direction) + { + case Direction.East: + AddComponent(new BedOfNailsComponent(0x2A89), 0, 0, 0); + AddComponent(new BedOfNailsComponent(0x2A8A), -1, 0, 0); + break; + case Direction.South: + AddComponent(new BedOfNailsComponent(0x2A81), 0, 0, 0); + AddComponent(new BedOfNailsComponent(0x2A82), 0, -1, 0); + break; + } + } + + private class InternalTimer : Timer + { + private readonly Mobile m_Mobile; + private Point3D m_Location; + + public InternalTimer(Mobile m) + : base(TimeSpan.Zero, TimeSpan.FromSeconds(1), 5) + { + m_Mobile = m; + m_Location = Point3D.Zero; + } + + protected override void OnTick() + { + if (m_Mobile?.Map == null || m_Mobile.Deleted || !m_Mobile.Alive || m_Mobile.Map == Map.Internal) + { + Stop(); + } + else if (m_Location != m_Mobile.Location) + { + var amount = Utility.RandomMinMax(0, 7); + + for (var i = 0; i < amount; i++) + { + var x = m_Mobile.X + Utility.RandomMinMax(-1, 1); + var y = m_Mobile.Y + Utility.RandomMinMax(-1, 1); + var z = m_Mobile.Z; + + if (!m_Mobile.Map.CanFit(x, y, z, 1, false, false)) + { + z = m_Mobile.Map.GetAverageZ(x, y); + + if (!m_Mobile.Map.CanFit(x, y, z, 1, false, false)) + continue; + } + + var blood = new Blood(Utility.RandomMinMax(0x122C, 0x122F)); + blood.MoveToWorld(new Point3D(x, y, z), m_Mobile.Map); + } + + m_Location = m_Mobile.Location; + } + } } - } } - } - public class BedOfNailsDeed : BaseAddonDeed - { - [Constructible] - public BedOfNailsDeed() => LootType = LootType.Blessed; - - public BedOfNailsDeed(Serial serial) - : base(serial) + public class BedOfNailsDeed : BaseAddonDeed { + [Constructible] + public BedOfNailsDeed() => LootType = LootType.Blessed; + + public BedOfNailsDeed(Serial serial) + : base(serial) + { + } + + public override BaseAddon Addon => new BedOfNailsAddon(); + public override int LabelNumber => 1074801; // Bed of Nails + + 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(); + } } - - public override BaseAddon Addon => new BedOfNailsAddon(); - public override int LabelNumber => 1074801; // Bed of Nails - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/Evil Home Decor Collection/BoneCouch.cs b/Projects/UOContent/Items/Special/Evil Home Decor Collection/BoneCouch.cs index ecb9da8cc..7623cfb9a 100644 --- a/Projects/UOContent/Items/Special/Evil Home Decor Collection/BoneCouch.cs +++ b/Projects/UOContent/Items/Special/Evil Home Decor Collection/BoneCouch.cs @@ -1,114 +1,114 @@ namespace Server.Items { - public class BoneCouchComponent : AddonComponent - { - public BoneCouchComponent(int itemID) : base(itemID) + public class BoneCouchComponent : AddonComponent { + public BoneCouchComponent(int itemID) : base(itemID) + { + } + + public BoneCouchComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074477; // Bone couch + + public override bool OnMoveOver(Mobile m) + { + var allow = base.OnMoveOver(m); + + if (allow && m.Alive && m.Player && (m.AccessLevel == AccessLevel.Player || !m.Hidden)) + Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x547, 0x54A)); + + return allow; + } + + 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(); + } } - public BoneCouchComponent(Serial serial) : base(serial) + [FlippableAddon(Direction.South, Direction.East)] + public class BoneCouchAddon : BaseAddon { + [Constructible] + public BoneCouchAddon() + { + Direction = Direction.South; + + AddComponent(new BoneCouchComponent(0x2A5A), 0, 0, 0); + AddComponent(new BoneCouchComponent(0x2A5B), -1, 0, 0); + } + + public BoneCouchAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new BoneCouchDeed(); + + 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(); + } + + public virtual void Flip(Mobile from, Direction direction) + { + switch (direction) + { + case Direction.East: + AddComponent(new BoneCouchComponent(0x2A80), 0, 0, 0); + AddComponent(new BoneCouchComponent(0x2A7F), 0, 1, 0); + break; + case Direction.South: + AddComponent(new BoneCouchComponent(0x2A5A), 0, 0, 0); + AddComponent(new BoneCouchComponent(0x2A5B), -1, 0, 0); + break; + } + } } - public override int LabelNumber => 1074477; // Bone couch - - public override bool OnMoveOver(Mobile m) + public class BoneCouchDeed : BaseAddonDeed { - bool allow = base.OnMoveOver(m); + [Constructible] + public BoneCouchDeed() => LootType = LootType.Blessed; - if (allow && m.Alive && m.Player && (m.AccessLevel == AccessLevel.Player || !m.Hidden)) - Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x547, 0x54A)); + public BoneCouchDeed(Serial serial) : base(serial) + { + } - return allow; + public override BaseAddon Addon => new BoneCouchAddon(); + public override int LabelNumber => 1074477; // Bone couch + + 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(); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - [FlippableAddon(Direction.South, Direction.East)] - public class BoneCouchAddon : BaseAddon - { - [Constructible] - public BoneCouchAddon() - { - Direction = Direction.South; - - AddComponent(new BoneCouchComponent(0x2A5A), 0, 0, 0); - AddComponent(new BoneCouchComponent(0x2A5B), -1, 0, 0); - } - - public BoneCouchAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new BoneCouchDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - public virtual void Flip(Mobile from, Direction direction) - { - switch (direction) - { - case Direction.East: - AddComponent(new BoneCouchComponent(0x2A80), 0, 0, 0); - AddComponent(new BoneCouchComponent(0x2A7F), 0, 1, 0); - break; - case Direction.South: - AddComponent(new BoneCouchComponent(0x2A5A), 0, 0, 0); - AddComponent(new BoneCouchComponent(0x2A5B), -1, 0, 0); - break; - } - } - } - - public class BoneCouchDeed : BaseAddonDeed - { - [Constructible] - public BoneCouchDeed() => LootType = LootType.Blessed; - - public BoneCouchDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new BoneCouchAddon(); - public override int LabelNumber => 1074477; // Bone couch - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Evil Home Decor Collection/BoneTable.cs b/Projects/UOContent/Items/Special/Evil Home Decor Collection/BoneTable.cs index 0ada9869e..64acb6baf 100644 --- a/Projects/UOContent/Items/Special/Evil Home Decor Collection/BoneTable.cs +++ b/Projects/UOContent/Items/Special/Evil Home Decor Collection/BoneTable.cs @@ -1,58 +1,58 @@ namespace Server.Items { - public class BoneTableAddon : BaseAddon - { - [Constructible] - public BoneTableAddon() + public class BoneTableAddon : BaseAddon { - AddComponent(new LocalizedAddonComponent(0x2A5C, 1074478), 0, 0, 0); + [Constructible] + public BoneTableAddon() + { + AddComponent(new LocalizedAddonComponent(0x2A5C, 1074478), 0, 0, 0); + } + + public BoneTableAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new BoneTableDeed(); + + 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(); + } } - public BoneTableAddon(Serial serial) : base(serial) + public class BoneTableDeed : BaseAddonDeed { + [Constructible] + public BoneTableDeed() => LootType = LootType.Blessed; + + public BoneTableDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new BoneTableAddon(); + public override int LabelNumber => 1074478; // Bone table + + 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(); + } } - - public override BaseAddonDeed Deed => new BoneTableDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BoneTableDeed : BaseAddonDeed - { - [Constructible] - public BoneTableDeed() => LootType = LootType.Blessed; - - public BoneTableDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new BoneTableAddon(); - public override int LabelNumber => 1074478; // Bone table - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Evil Home Decor Collection/BoneThrone.cs b/Projects/UOContent/Items/Special/Evil Home Decor Collection/BoneThrone.cs index 39497c6c3..b26a3d2cb 100644 --- a/Projects/UOContent/Items/Special/Evil Home Decor Collection/BoneThrone.cs +++ b/Projects/UOContent/Items/Special/Evil Home Decor Collection/BoneThrone.cs @@ -1,96 +1,96 @@ namespace Server.Items { - [Flippable(0x2A58, 0x2A59)] - public class BoneThroneComponent : AddonComponent - { - public BoneThroneComponent() : base(0x2A58) + [Flippable(0x2A58, 0x2A59)] + public class BoneThroneComponent : AddonComponent { + public BoneThroneComponent() : base(0x2A58) + { + } + + public BoneThroneComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074476; // Bone throne + + public override bool OnMoveOver(Mobile m) + { + var allow = base.OnMoveOver(m); + + if (allow && m.Alive && m.Player && (m.AccessLevel == AccessLevel.Player || !m.Hidden)) + Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x54B, 0x54D)); + + return allow; + } + + 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(); + } } - public BoneThroneComponent(Serial serial) : base(serial) + public class BoneThroneAddon : BaseAddon { + [Constructible] + public BoneThroneAddon() + { + AddComponent(new BoneThroneComponent(), 0, 0, 0); + } + + public BoneThroneAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new BoneThroneDeed(); + + 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(); + } } - public override int LabelNumber => 1074476; // Bone throne - - public override bool OnMoveOver(Mobile m) + public class BoneThroneDeed : BaseAddonDeed { - bool allow = base.OnMoveOver(m); + [Constructible] + public BoneThroneDeed() => LootType = LootType.Blessed; - if (allow && m.Alive && m.Player && (m.AccessLevel == AccessLevel.Player || !m.Hidden)) - Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x54B, 0x54D)); + public BoneThroneDeed(Serial serial) : base(serial) + { + } - return allow; + public override BaseAddon Addon => new BoneThroneAddon(); + public override int LabelNumber => 1074476; // Bone throne + + 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(); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BoneThroneAddon : BaseAddon - { - [Constructible] - public BoneThroneAddon() - { - AddComponent(new BoneThroneComponent(), 0, 0, 0); - } - - public BoneThroneAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new BoneThroneDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BoneThroneDeed : BaseAddonDeed - { - [Constructible] - public BoneThroneDeed() => LootType = LootType.Blessed; - - public BoneThroneDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new BoneThroneAddon(); - public override int LabelNumber => 1074476; // Bone throne - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Evil Home Decor Collection/CreepyPortrait.cs b/Projects/UOContent/Items/Special/Evil Home Decor Collection/CreepyPortrait.cs index b906c26ee..c9e7a15da 100644 --- a/Projects/UOContent/Items/Special/Evil Home Decor Collection/CreepyPortrait.cs +++ b/Projects/UOContent/Items/Special/Evil Home Decor Collection/CreepyPortrait.cs @@ -3,132 +3,132 @@ using Server.Network; namespace Server.Items { - [Flippable(0x2A69, 0x2A6D)] - public class CreepyPortraitComponent : AddonComponent - { - public CreepyPortraitComponent() : base(0x2A69) + [Flippable(0x2A69, 0x2A6D)] + public class CreepyPortraitComponent : AddonComponent { - } - - public CreepyPortraitComponent(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074481; // Creepy portrait - public override bool HandlesOnMovement => true; - - public override void OnDoubleClick(Mobile from) - { - if (Utility.InRange(Location, from.Location, 2)) - Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x565, 0x566)); - else - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - - public override void OnMovement(Mobile m, Point3D old) - { - if (m.Alive && m.Player && (m.AccessLevel == AccessLevel.Player || !m.Hidden)) - { - if (!Utility.InRange(old, Location, 2) && Utility.InRange(m.Location, Location, 2)) + public CreepyPortraitComponent() : base(0x2A69) { - if (ItemID == 0x2A69 || ItemID == 0x2A6D) - { - Up(); - Timer.DelayCall(TimeSpan.FromSeconds(0.5), TimeSpan.FromSeconds(0.5), 2, Up); - } } - else if (Utility.InRange(old, Location, 2) && !Utility.InRange(m.Location, Location, 2)) + + public CreepyPortraitComponent(Serial serial) : base(serial) { - if (ItemID == 0x2A6C || ItemID == 0x2A70) - { - Down(); - Timer.DelayCall(TimeSpan.FromSeconds(0.5), TimeSpan.FromSeconds(0.5), 2, Down); - } } - } + + public override int LabelNumber => 1074481; // Creepy portrait + public override bool HandlesOnMovement => true; + + public override void OnDoubleClick(Mobile from) + { + if (Utility.InRange(Location, from.Location, 2)) + Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x565, 0x566)); + else + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + + public override void OnMovement(Mobile m, Point3D old) + { + if (m.Alive && m.Player && (m.AccessLevel == AccessLevel.Player || !m.Hidden)) + { + if (!Utility.InRange(old, Location, 2) && Utility.InRange(m.Location, Location, 2)) + { + if (ItemID == 0x2A69 || ItemID == 0x2A6D) + { + Up(); + Timer.DelayCall(TimeSpan.FromSeconds(0.5), TimeSpan.FromSeconds(0.5), 2, Up); + } + } + else if (Utility.InRange(old, Location, 2) && !Utility.InRange(m.Location, Location, 2)) + { + if (ItemID == 0x2A6C || ItemID == 0x2A70) + { + Down(); + Timer.DelayCall(TimeSpan.FromSeconds(0.5), TimeSpan.FromSeconds(0.5), 2, Down); + } + } + } + } + + private void Up() + { + ItemID += 1; + } + + private void Down() + { + ItemID -= 1; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(1); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + if (version == 0 && ItemID != 0x2A69 && ItemID != 0x2A6D) + ItemID = 0x2A69; + } } - private void Up() + public class CreepyPortraitAddon : BaseAddon { - ItemID += 1; + [Constructible] + public CreepyPortraitAddon() + { + AddComponent(new CreepyPortraitComponent(), 0, 0, 0); + } + + public CreepyPortraitAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new CreepyPortraitDeed(); + + 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(); + } } - private void Down() + public class CreepyPortraitDeed : BaseAddonDeed { - ItemID -= 1; + [Constructible] + public CreepyPortraitDeed() => LootType = LootType.Blessed; + + public CreepyPortraitDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new CreepyPortraitAddon(); + public override int LabelNumber => 1074481; // Creepy portrait + + 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(); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - if (version == 0 && ItemID != 0x2A69 && ItemID != 0x2A6D) - ItemID = 0x2A69; - } - } - - public class CreepyPortraitAddon : BaseAddon - { - [Constructible] - public CreepyPortraitAddon() - { - AddComponent(new CreepyPortraitComponent(), 0, 0, 0); - } - - public CreepyPortraitAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new CreepyPortraitDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class CreepyPortraitDeed : BaseAddonDeed - { - [Constructible] - public CreepyPortraitDeed() => LootType = LootType.Blessed; - - public CreepyPortraitDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new CreepyPortraitAddon(); - public override int LabelNumber => 1074481; // Creepy portrait - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Evil Home Decor Collection/DisturbingPortrait.cs b/Projects/UOContent/Items/Special/Evil Home Decor Collection/DisturbingPortrait.cs index 7847926a1..41a6f5f3c 100644 --- a/Projects/UOContent/Items/Special/Evil Home Decor Collection/DisturbingPortrait.cs +++ b/Projects/UOContent/Items/Special/Evil Home Decor Collection/DisturbingPortrait.cs @@ -3,113 +3,117 @@ using Server.Network; namespace Server.Items { - [Flippable(0x2A5D, 0x2A61)] - public class DisturbingPortraitComponent : AddonComponent - { - private Timer m_Timer; - - public DisturbingPortraitComponent() : base(0x2A5D) => m_Timer = Timer.DelayCall(TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(3), Change); - - public DisturbingPortraitComponent(Serial serial) : base(serial) + [Flippable(0x2A5D, 0x2A61)] + public class DisturbingPortraitComponent : AddonComponent { + private Timer m_Timer; + + public DisturbingPortraitComponent() : base(0x2A5D) => m_Timer = Timer.DelayCall( + TimeSpan.FromMinutes(3), + TimeSpan.FromMinutes(3), + Change + ); + + public DisturbingPortraitComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074479; // Disturbing portrait + + public override void OnDoubleClick(Mobile from) + { + if (Utility.InRange(Location, from.Location, 2)) + Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x567, 0x568)); + else + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + if (m_Timer?.Running == true) + m_Timer.Stop(); + } + + 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(); + + m_Timer = Timer.DelayCall(TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(3), Change); + } + + private void Change() + { + if (ItemID < 0x2A61) + ItemID = Utility.RandomMinMax(0x2A5D, 0x2A60); + else + ItemID = Utility.RandomMinMax(0x2A61, 0x2A64); + } } - public override int LabelNumber => 1074479; // Disturbing portrait - - public override void OnDoubleClick(Mobile from) + public class DisturbingPortraitAddon : BaseAddon { - if (Utility.InRange(Location, from.Location, 2)) - Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x567, 0x568)); - else - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + [Constructible] + public DisturbingPortraitAddon() + { + AddComponent(new DisturbingPortraitComponent(), 0, 0, 0); + } + + public DisturbingPortraitAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new DisturbingPortraitDeed(); + + 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(); + } } - public override void OnAfterDelete() + public class DisturbingPortraitDeed : BaseAddonDeed { - base.OnAfterDelete(); + [Constructible] + public DisturbingPortraitDeed() => LootType = LootType.Blessed; - if (m_Timer?.Running == true) - m_Timer.Stop(); + public DisturbingPortraitDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new DisturbingPortraitAddon(); + public override int LabelNumber => 1074479; // Disturbing portrait + + 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(); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_Timer = Timer.DelayCall(TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(3), Change); - } - - private void Change() - { - if (ItemID < 0x2A61) - ItemID = Utility.RandomMinMax(0x2A5D, 0x2A60); - else - ItemID = Utility.RandomMinMax(0x2A61, 0x2A64); - } - } - - public class DisturbingPortraitAddon : BaseAddon - { - [Constructible] - public DisturbingPortraitAddon() - { - AddComponent(new DisturbingPortraitComponent(), 0, 0, 0); - } - - public DisturbingPortraitAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new DisturbingPortraitDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class DisturbingPortraitDeed : BaseAddonDeed - { - [Constructible] - public DisturbingPortraitDeed() => LootType = LootType.Blessed; - - public DisturbingPortraitDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new DisturbingPortraitAddon(); - public override int LabelNumber => 1074479; // Disturbing portrait - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/Evil Home Decor Collection/HauntedMirror.cs b/Projects/UOContent/Items/Special/Evil Home Decor Collection/HauntedMirror.cs index ad02b866d..0f8e16679 100644 --- a/Projects/UOContent/Items/Special/Evil Home Decor Collection/HauntedMirror.cs +++ b/Projects/UOContent/Items/Special/Evil Home Decor Collection/HauntedMirror.cs @@ -1,109 +1,109 @@ namespace Server.Items { - [Flippable(0x2A7B, 0x2A7D)] - public class HaunterMirrorComponent : AddonComponent - { - public HaunterMirrorComponent() : base(0x2A7B) + [Flippable(0x2A7B, 0x2A7D)] + public class HaunterMirrorComponent : AddonComponent { - } - - public HaunterMirrorComponent(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1074800; // Haunted Mirror - public override bool HandlesOnMovement => true; - - public override void OnMovement(Mobile m, Point3D old) - { - base.OnMovement(m, old); - - if (m.Alive && m.Player && (m.AccessLevel == AccessLevel.Player || !m.Hidden)) - { - if (!Utility.InRange(old, Location, 2) && Utility.InRange(m.Location, Location, 2)) + public HaunterMirrorComponent() : base(0x2A7B) { - if (ItemID == 0x2A7B || ItemID == 0x2A7D) - { - Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x551, 0x553)); - ItemID += 1; - } } - else if (Utility.InRange(old, Location, 2) && !Utility.InRange(m.Location, Location, 2)) + + public HaunterMirrorComponent(Serial serial) : base(serial) { - if (ItemID == 0x2A7C || ItemID == 0x2A7E) - ItemID -= 1; } - } + + public override int LabelNumber => 1074800; // Haunted Mirror + public override bool HandlesOnMovement => true; + + public override void OnMovement(Mobile m, Point3D old) + { + base.OnMovement(m, old); + + if (m.Alive && m.Player && (m.AccessLevel == AccessLevel.Player || !m.Hidden)) + { + if (!Utility.InRange(old, Location, 2) && Utility.InRange(m.Location, Location, 2)) + { + if (ItemID == 0x2A7B || ItemID == 0x2A7D) + { + Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x551, 0x553)); + ItemID += 1; + } + } + else if (Utility.InRange(old, Location, 2) && !Utility.InRange(m.Location, Location, 2)) + { + if (ItemID == 0x2A7C || ItemID == 0x2A7E) + ItemID -= 1; + } + } + } + + 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(); + } } - public override void Serialize(IGenericWriter writer) + public class HaunterMirrorAddon : BaseAddon { - base.Serialize(writer); + [Constructible] + public HaunterMirrorAddon() + { + AddComponent(new HaunterMirrorComponent(), 0, 0, 0); + } - writer.WriteEncodedInt(0); // version + public HaunterMirrorAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new HaunterMirrorDeed(); + + 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(); + } } - public override void Deserialize(IGenericReader reader) + public class HaunterMirrorDeed : BaseAddonDeed { - base.Deserialize(reader); + [Constructible] + public HaunterMirrorDeed() => LootType = LootType.Blessed; - int version = reader.ReadEncodedInt(); + public HaunterMirrorDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new HaunterMirrorAddon(); + public override int LabelNumber => 1074800; // Haunted Mirror + + 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(); + } } - } - - public class HaunterMirrorAddon : BaseAddon - { - [Constructible] - public HaunterMirrorAddon() - { - AddComponent(new HaunterMirrorComponent(), 0, 0, 0); - } - - public HaunterMirrorAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new HaunterMirrorDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class HaunterMirrorDeed : BaseAddonDeed - { - [Constructible] - public HaunterMirrorDeed() => LootType = LootType.Blessed; - - public HaunterMirrorDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new HaunterMirrorAddon(); - public override int LabelNumber => 1074800; // Haunted Mirror - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Evil Home Decor Collection/MountedPixieBlue.cs b/Projects/UOContent/Items/Special/Evil Home Decor Collection/MountedPixieBlue.cs index afc0ea5d1..eaad33507 100644 --- a/Projects/UOContent/Items/Special/Evil Home Decor Collection/MountedPixieBlue.cs +++ b/Projects/UOContent/Items/Special/Evil Home Decor Collection/MountedPixieBlue.cs @@ -2,94 +2,94 @@ using Server.Network; namespace Server.Items { - [Flippable(0x2A75, 0x2A76)] - public class MountedPixieBlueComponent : AddonComponent - { - public MountedPixieBlueComponent() : base(0x2A75) + [Flippable(0x2A75, 0x2A76)] + public class MountedPixieBlueComponent : AddonComponent { + public MountedPixieBlueComponent() : base(0x2A75) + { + } + + public MountedPixieBlueComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074482; // Mounted pixie + + public override void OnDoubleClick(Mobile from) + { + if (Utility.InRange(Location, from.Location, 2)) + Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x55C, 0x55E)); + else + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + + 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(); + } } - public MountedPixieBlueComponent(Serial serial) : base(serial) + public class MountedPixieBlueAddon : BaseAddon { + public MountedPixieBlueAddon() + { + AddComponent(new MountedPixieBlueComponent(), 0, 0, 0); + } + + public MountedPixieBlueAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new MountedPixieBlueDeed(); + + 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(); + } } - public override int LabelNumber => 1074482; // Mounted pixie - - public override void OnDoubleClick(Mobile from) + public class MountedPixieBlueDeed : BaseAddonDeed { - if (Utility.InRange(Location, from.Location, 2)) - Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x55C, 0x55E)); - else - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + [Constructible] + public MountedPixieBlueDeed() => LootType = LootType.Blessed; + + public MountedPixieBlueDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new MountedPixieBlueAddon(); + public override int LabelNumber => 1074482; // Mounted pixie + + 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(); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class MountedPixieBlueAddon : BaseAddon - { - public MountedPixieBlueAddon() - { - AddComponent(new MountedPixieBlueComponent(), 0, 0, 0); - } - - public MountedPixieBlueAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new MountedPixieBlueDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class MountedPixieBlueDeed : BaseAddonDeed - { - [Constructible] - public MountedPixieBlueDeed() => LootType = LootType.Blessed; - - public MountedPixieBlueDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new MountedPixieBlueAddon(); - public override int LabelNumber => 1074482; // Mounted pixie - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Evil Home Decor Collection/MountedPixieGreen.cs b/Projects/UOContent/Items/Special/Evil Home Decor Collection/MountedPixieGreen.cs index 277106854..03fa6f1e8 100644 --- a/Projects/UOContent/Items/Special/Evil Home Decor Collection/MountedPixieGreen.cs +++ b/Projects/UOContent/Items/Special/Evil Home Decor Collection/MountedPixieGreen.cs @@ -2,94 +2,94 @@ using Server.Network; namespace Server.Items { - [Flippable(0x2A71, 0x2A72)] - public class MountedPixieGreenComponent : AddonComponent - { - public MountedPixieGreenComponent() : base(0x2A71) + [Flippable(0x2A71, 0x2A72)] + public class MountedPixieGreenComponent : AddonComponent { + public MountedPixieGreenComponent() : base(0x2A71) + { + } + + public MountedPixieGreenComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074482; // Mounted pixie + + public override void OnDoubleClick(Mobile from) + { + if (Utility.InRange(Location, from.Location, 2)) + Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x554, 0x557)); + else + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + + 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(); + } } - public MountedPixieGreenComponent(Serial serial) : base(serial) + public class MountedPixieGreenAddon : BaseAddon { + public MountedPixieGreenAddon() + { + AddComponent(new MountedPixieGreenComponent(), 0, 0, 0); + } + + public MountedPixieGreenAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new MountedPixieGreenDeed(); + + 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(); + } } - public override int LabelNumber => 1074482; // Mounted pixie - - public override void OnDoubleClick(Mobile from) + public class MountedPixieGreenDeed : BaseAddonDeed { - if (Utility.InRange(Location, from.Location, 2)) - Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x554, 0x557)); - else - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + [Constructible] + public MountedPixieGreenDeed() => LootType = LootType.Blessed; + + public MountedPixieGreenDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new MountedPixieGreenAddon(); + public override int LabelNumber => 1074482; // Mounted pixie + + 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(); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class MountedPixieGreenAddon : BaseAddon - { - public MountedPixieGreenAddon() - { - AddComponent(new MountedPixieGreenComponent(), 0, 0, 0); - } - - public MountedPixieGreenAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new MountedPixieGreenDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class MountedPixieGreenDeed : BaseAddonDeed - { - [Constructible] - public MountedPixieGreenDeed() => LootType = LootType.Blessed; - - public MountedPixieGreenDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new MountedPixieGreenAddon(); - public override int LabelNumber => 1074482; // Mounted pixie - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Evil Home Decor Collection/MountedPixieLime.cs b/Projects/UOContent/Items/Special/Evil Home Decor Collection/MountedPixieLime.cs index 5b99ccbfe..ebdb0ac1f 100644 --- a/Projects/UOContent/Items/Special/Evil Home Decor Collection/MountedPixieLime.cs +++ b/Projects/UOContent/Items/Special/Evil Home Decor Collection/MountedPixieLime.cs @@ -2,94 +2,94 @@ using Server.Network; namespace Server.Items { - [Flippable(0x2A77, 0x2A78)] - public class MountedPixieLimeComponent : AddonComponent - { - public MountedPixieLimeComponent() : base(0x2A77) + [Flippable(0x2A77, 0x2A78)] + public class MountedPixieLimeComponent : AddonComponent { + public MountedPixieLimeComponent() : base(0x2A77) + { + } + + public MountedPixieLimeComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074482; // Mounted pixie + + public override void OnDoubleClick(Mobile from) + { + if (Utility.InRange(Location, from.Location, 2)) + Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x55F, 0x561)); + else + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + + 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(); + } } - public MountedPixieLimeComponent(Serial serial) : base(serial) + public class MountedPixieLimeAddon : BaseAddon { + public MountedPixieLimeAddon() + { + AddComponent(new MountedPixieLimeComponent(), 0, 0, 0); + } + + public MountedPixieLimeAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new MountedPixieLimeDeed(); + + 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(); + } } - public override int LabelNumber => 1074482; // Mounted pixie - - public override void OnDoubleClick(Mobile from) + public class MountedPixieLimeDeed : BaseAddonDeed { - if (Utility.InRange(Location, from.Location, 2)) - Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x55F, 0x561)); - else - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + [Constructible] + public MountedPixieLimeDeed() => LootType = LootType.Blessed; + + public MountedPixieLimeDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new MountedPixieLimeAddon(); + public override int LabelNumber => 1074482; // Mounted pixie + + 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(); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class MountedPixieLimeAddon : BaseAddon - { - public MountedPixieLimeAddon() - { - AddComponent(new MountedPixieLimeComponent(), 0, 0, 0); - } - - public MountedPixieLimeAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new MountedPixieLimeDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class MountedPixieLimeDeed : BaseAddonDeed - { - [Constructible] - public MountedPixieLimeDeed() => LootType = LootType.Blessed; - - public MountedPixieLimeDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new MountedPixieLimeAddon(); - public override int LabelNumber => 1074482; // Mounted pixie - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Evil Home Decor Collection/MountedPixieOrange.cs b/Projects/UOContent/Items/Special/Evil Home Decor Collection/MountedPixieOrange.cs index 0f63ad74a..073d36d70 100644 --- a/Projects/UOContent/Items/Special/Evil Home Decor Collection/MountedPixieOrange.cs +++ b/Projects/UOContent/Items/Special/Evil Home Decor Collection/MountedPixieOrange.cs @@ -2,94 +2,94 @@ using Server.Network; namespace Server.Items { - [Flippable(0x2A73, 0x2A74)] - public class MountedPixieOrangeComponent : AddonComponent - { - public MountedPixieOrangeComponent() : base(0x2A73) + [Flippable(0x2A73, 0x2A74)] + public class MountedPixieOrangeComponent : AddonComponent { + public MountedPixieOrangeComponent() : base(0x2A73) + { + } + + public MountedPixieOrangeComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074482; // Mounted pixie + + public override void OnDoubleClick(Mobile from) + { + if (Utility.InRange(Location, from.Location, 2)) + Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x558, 0x55B)); + else + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + + 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(); + } } - public MountedPixieOrangeComponent(Serial serial) : base(serial) + public class MountedPixieOrangeAddon : BaseAddon { + public MountedPixieOrangeAddon() + { + AddComponent(new MountedPixieOrangeComponent(), 0, 0, 0); + } + + public MountedPixieOrangeAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new MountedPixieOrangeDeed(); + + 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(); + } } - public override int LabelNumber => 1074482; // Mounted pixie - - public override void OnDoubleClick(Mobile from) + public class MountedPixieOrangeDeed : BaseAddonDeed { - if (Utility.InRange(Location, from.Location, 2)) - Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x558, 0x55B)); - else - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + [Constructible] + public MountedPixieOrangeDeed() => LootType = LootType.Blessed; + + public MountedPixieOrangeDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new MountedPixieOrangeAddon(); + public override int LabelNumber => 1074482; // Mounted pixie + + 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(); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class MountedPixieOrangeAddon : BaseAddon - { - public MountedPixieOrangeAddon() - { - AddComponent(new MountedPixieOrangeComponent(), 0, 0, 0); - } - - public MountedPixieOrangeAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new MountedPixieOrangeDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class MountedPixieOrangeDeed : BaseAddonDeed - { - [Constructible] - public MountedPixieOrangeDeed() => LootType = LootType.Blessed; - - public MountedPixieOrangeDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new MountedPixieOrangeAddon(); - public override int LabelNumber => 1074482; // Mounted pixie - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Evil Home Decor Collection/MountedPixieWhite.cs b/Projects/UOContent/Items/Special/Evil Home Decor Collection/MountedPixieWhite.cs index 7b2809d96..65541a645 100644 --- a/Projects/UOContent/Items/Special/Evil Home Decor Collection/MountedPixieWhite.cs +++ b/Projects/UOContent/Items/Special/Evil Home Decor Collection/MountedPixieWhite.cs @@ -2,94 +2,94 @@ using Server.Network; namespace Server.Items { - [Flippable(0x2A79, 0x2A7A)] - public class MountedPixieWhiteComponent : AddonComponent - { - public MountedPixieWhiteComponent() : base(0x2A79) + [Flippable(0x2A79, 0x2A7A)] + public class MountedPixieWhiteComponent : AddonComponent { + public MountedPixieWhiteComponent() : base(0x2A79) + { + } + + public MountedPixieWhiteComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074482; // Mounted pixie + + public override void OnDoubleClick(Mobile from) + { + if (Utility.InRange(Location, from.Location, 2)) + Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x562, 0x564)); + else + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + + 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(); + } } - public MountedPixieWhiteComponent(Serial serial) : base(serial) + public class MountedPixieWhiteAddon : BaseAddon { + public MountedPixieWhiteAddon() + { + AddComponent(new MountedPixieWhiteComponent(), 0, 0, 0); + } + + public MountedPixieWhiteAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new MountedPixieWhiteDeed(); + + 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(); + } } - public override int LabelNumber => 1074482; // Mounted pixie - - public override void OnDoubleClick(Mobile from) + public class MountedPixieWhiteDeed : BaseAddonDeed { - if (Utility.InRange(Location, from.Location, 2)) - Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x562, 0x564)); - else - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + [Constructible] + public MountedPixieWhiteDeed() => LootType = LootType.Blessed; + + public MountedPixieWhiteDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new MountedPixieWhiteAddon(); + public override int LabelNumber => 1074482; // Mounted pixie + + 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(); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class MountedPixieWhiteAddon : BaseAddon - { - public MountedPixieWhiteAddon() - { - AddComponent(new MountedPixieWhiteComponent(), 0, 0, 0); - } - - public MountedPixieWhiteAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new MountedPixieWhiteDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class MountedPixieWhiteDeed : BaseAddonDeed - { - [Constructible] - public MountedPixieWhiteDeed() => LootType = LootType.Blessed; - - public MountedPixieWhiteDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new MountedPixieWhiteAddon(); - public override int LabelNumber => 1074482; // Mounted pixie - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Evil Home Decor Collection/SacrificialAltar.cs b/Projects/UOContent/Items/Special/Evil Home Decor Collection/SacrificialAltar.cs index 3f4dae829..cdde23388 100644 --- a/Projects/UOContent/Items/Special/Evil Home Decor Collection/SacrificialAltar.cs +++ b/Projects/UOContent/Items/Special/Evil Home Decor Collection/SacrificialAltar.cs @@ -2,155 +2,155 @@ using System; namespace Server.Items { - [FlippableAddon(Direction.South, Direction.East)] - public class SacrificialAltarAddon : BaseAddonContainer - { - private Timer m_Timer; - - [Constructible] - public SacrificialAltarAddon() : base(0x2A9B) + [FlippableAddon(Direction.South, Direction.East)] + public class SacrificialAltarAddon : BaseAddonContainer { - Direction = Direction.South; + private Timer m_Timer; - AddComponent(new LocalizedContainerComponent(0x2A9A, 1074818), 1, 0, 0); + [Constructible] + public SacrificialAltarAddon() : base(0x2A9B) + { + Direction = Direction.South; + + AddComponent(new LocalizedContainerComponent(0x2A9A, 1074818), 1, 0, 0); + } + + public SacrificialAltarAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonContainerDeed Deed => new SacrificialAltarDeed(); + public override int LabelNumber => 1074818; // Sacrificial Altar + public override int DefaultMaxWeight => 0; + public override int DefaultGumpID => 0x107; + public override int DefaultDropSound => 0x42; + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (!base.OnDragDrop(from, dropped)) + return false; + + if (TotalItems >= 50) + { + SendLocalizedMessageTo(from, 501478); // The trash is full! Emptying! + Empty(); + } + else + { + SendLocalizedMessageTo(from, 1010442); // The item will be deleted in three minutes + + m_Timer?.Stop(); + + m_Timer = Timer.DelayCall(TimeSpan.FromMinutes(3), Empty); + } + + return true; + } + + public override bool OnDragDropInto(Mobile from, Item item, Point3D p) + { + if (!base.OnDragDropInto(from, item, p)) + return false; + + if (TotalItems >= 50) + { + SendLocalizedMessageTo(from, 501478); // The trash is full! Emptying! + Empty(); + } + else + { + SendLocalizedMessageTo(from, 1010442); // The item will be deleted in three minutes + + m_Timer?.Stop(); + + m_Timer = Timer.DelayCall(TimeSpan.FromMinutes(3), Empty); + } + + return true; + } + + 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 (Items.Count > 0) + m_Timer = Timer.DelayCall(TimeSpan.FromMinutes(3), Empty); + } + + public virtual void Flip(Mobile from, Direction direction) + { + switch (direction) + { + case Direction.East: + ItemID = 0x2A9C; + AddComponent(new LocalizedContainerComponent(0x2A9D, 1074818), 0, -1, 0); + break; + case Direction.South: + ItemID = 0x2A9B; + AddComponent(new LocalizedContainerComponent(0x2A9A, 1074818), 1, 0, 0); + break; + } + } + + public virtual void Empty() + { + if (Items.Count > 0) + { + var location = Location; + location.Z += 10; + + Effects.SendLocationEffect(location, Map, 0x3709, 10, 10, 0x356, 0); + Effects.PlaySound(location, Map, 0x32E); + + if (Items.Count > 0) + for (var i = Items.Count - 1; i >= 0; --i) + { + if (i >= Items.Count) + continue; + + Items[i].Delete(); + } + } + + m_Timer?.Stop(); + + m_Timer = null; + } } - public SacrificialAltarAddon(Serial serial) : base(serial) + public class SacrificialAltarDeed : BaseAddonContainerDeed { + [Constructible] + public SacrificialAltarDeed() => LootType = LootType.Blessed; + + public SacrificialAltarDeed(Serial serial) : base(serial) + { + } + + public override BaseAddonContainer Addon => new SacrificialAltarAddon(); + public override int LabelNumber => 1074818; // Sacrificial Altar + + 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(); + } } - - public override BaseAddonContainerDeed Deed => new SacrificialAltarDeed(); - public override int LabelNumber => 1074818; // Sacrificial Altar - public override int DefaultMaxWeight => 0; - public override int DefaultGumpID => 0x107; - public override int DefaultDropSound => 0x42; - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (!base.OnDragDrop(from, dropped)) - return false; - - if (TotalItems >= 50) - { - SendLocalizedMessageTo(from, 501478); // The trash is full! Emptying! - Empty(); - } - else - { - SendLocalizedMessageTo(from, 1010442); // The item will be deleted in three minutes - - m_Timer?.Stop(); - - m_Timer = Timer.DelayCall(TimeSpan.FromMinutes(3), Empty); - } - - return true; - } - - public override bool OnDragDropInto(Mobile from, Item item, Point3D p) - { - if (!base.OnDragDropInto(from, item, p)) - return false; - - if (TotalItems >= 50) - { - SendLocalizedMessageTo(from, 501478); // The trash is full! Emptying! - Empty(); - } - else - { - SendLocalizedMessageTo(from, 1010442); // The item will be deleted in three minutes - - m_Timer?.Stop(); - - m_Timer = Timer.DelayCall(TimeSpan.FromMinutes(3), Empty); - } - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - if (Items.Count > 0) - m_Timer = Timer.DelayCall(TimeSpan.FromMinutes(3), Empty); - } - - public virtual void Flip(Mobile from, Direction direction) - { - switch (direction) - { - case Direction.East: - ItemID = 0x2A9C; - AddComponent(new LocalizedContainerComponent(0x2A9D, 1074818), 0, -1, 0); - break; - case Direction.South: - ItemID = 0x2A9B; - AddComponent(new LocalizedContainerComponent(0x2A9A, 1074818), 1, 0, 0); - break; - } - } - - public virtual void Empty() - { - if (Items.Count > 0) - { - Point3D location = Location; - location.Z += 10; - - Effects.SendLocationEffect(location, Map, 0x3709, 10, 10, 0x356, 0); - Effects.PlaySound(location, Map, 0x32E); - - if (Items.Count > 0) - for (int i = Items.Count - 1; i >= 0; --i) - { - if (i >= Items.Count) - continue; - - Items[i].Delete(); - } - } - - m_Timer?.Stop(); - - m_Timer = null; - } - } - - public class SacrificialAltarDeed : BaseAddonContainerDeed - { - [Constructible] - public SacrificialAltarDeed() => LootType = LootType.Blessed; - - public SacrificialAltarDeed(Serial serial) : base(serial) - { - } - - public override BaseAddonContainer Addon => new SacrificialAltarAddon(); - public override int LabelNumber => 1074818; // Sacrificial Altar - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Evil Home Decor Collection/UnsettlingPortrait.cs b/Projects/UOContent/Items/Special/Evil Home Decor Collection/UnsettlingPortrait.cs index 9b231b16d..2aab1ab62 100644 --- a/Projects/UOContent/Items/Special/Evil Home Decor Collection/UnsettlingPortrait.cs +++ b/Projects/UOContent/Items/Special/Evil Home Decor Collection/UnsettlingPortrait.cs @@ -3,116 +3,120 @@ using Server.Network; namespace Server.Items { - [Flippable(0x2A65, 0x2A67)] - public class UnsettlingPortraitComponent : AddonComponent - { - private Timer m_Timer; - - public UnsettlingPortraitComponent() : base(0x2A65) => m_Timer = Timer.DelayCall(TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(3), ChangeDirection); - - public UnsettlingPortraitComponent(Serial serial) : base(serial) + [Flippable(0x2A65, 0x2A67)] + public class UnsettlingPortraitComponent : AddonComponent { + private Timer m_Timer; + + public UnsettlingPortraitComponent() : base(0x2A65) => m_Timer = Timer.DelayCall( + TimeSpan.FromMinutes(3), + TimeSpan.FromMinutes(3), + ChangeDirection + ); + + public UnsettlingPortraitComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074480; // Unsettling portrait + + public override void OnDoubleClick(Mobile from) + { + if (Utility.InRange(Location, from.Location, 2)) + Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x567, 0x568)); + else + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Timer?.Stop(); + } + + 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(); + + m_Timer = Timer.DelayCall(TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(3), ChangeDirection); + } + + private void ChangeDirection() + { + if (ItemID == 0x2A65) + ItemID += 1; + else if (ItemID == 0x2A66) + ItemID -= 1; + else if (ItemID == 0x2A67) + ItemID += 1; + else if (ItemID == 0x2A68) + ItemID -= 1; + } } - public override int LabelNumber => 1074480; // Unsettling portrait - - public override void OnDoubleClick(Mobile from) + public class UnsettlingPortraitAddon : BaseAddon { - if (Utility.InRange(Location, from.Location, 2)) - Effects.PlaySound(Location, Map, Utility.RandomMinMax(0x567, 0x568)); - else - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + [Constructible] + public UnsettlingPortraitAddon() + { + AddComponent(new UnsettlingPortraitComponent(), 0, 0, 0); + } + + public UnsettlingPortraitAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new UnsettlingPortraitDeed(); + + 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(); + } } - public override void OnAfterDelete() + public class UnsettlingPortraitDeed : BaseAddonDeed { - base.OnAfterDelete(); + [Constructible] + public UnsettlingPortraitDeed() => LootType = LootType.Blessed; - m_Timer?.Stop(); + public UnsettlingPortraitDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new UnsettlingPortraitAddon(); + public override int LabelNumber => 1074480; // Unsettling portrait + + 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(); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_Timer = Timer.DelayCall(TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(3), ChangeDirection); - } - - private void ChangeDirection() - { - if (ItemID == 0x2A65) - ItemID += 1; - else if (ItemID == 0x2A66) - ItemID -= 1; - else if (ItemID == 0x2A67) - ItemID += 1; - else if (ItemID == 0x2A68) - ItemID -= 1; - } - } - - public class UnsettlingPortraitAddon : BaseAddon - { - [Constructible] - public UnsettlingPortraitAddon() - { - AddComponent(new UnsettlingPortraitComponent(), 0, 0, 0); - } - - public UnsettlingPortraitAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new UnsettlingPortraitDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class UnsettlingPortraitDeed : BaseAddonDeed - { - [Constructible] - public UnsettlingPortraitDeed() => LootType = LootType.Blessed; - - public UnsettlingPortraitDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new UnsettlingPortraitAddon(); - public override int LabelNumber => 1074480; // Unsettling portrait - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Gifts/HearthOfHomeFire.cs b/Projects/UOContent/Items/Special/Gifts/HearthOfHomeFire.cs index 41cc1bd8b..c72bef809 100644 --- a/Projects/UOContent/Items/Special/Gifts/HearthOfHomeFire.cs +++ b/Projects/UOContent/Items/Special/Gifts/HearthOfHomeFire.cs @@ -3,125 +3,125 @@ using Server.Network; namespace Server.Items { - public class HearthOfHomeFire : BaseAddon - { - [Constructible] - public HearthOfHomeFire(bool east) + public class HearthOfHomeFire : BaseAddon { - if (east) - { - AddLightComponent(new AddonComponent(0x2352), 0, 0, 0); - AddLightComponent(new AddonComponent(0x2358), 0, -1, 0); - } - else - { - AddLightComponent(new AddonComponent(0x2360), 0, 0, 0); - AddLightComponent(new AddonComponent(0x2366), -1, 0, 0); - } + [Constructible] + public HearthOfHomeFire(bool east) + { + if (east) + { + AddLightComponent(new AddonComponent(0x2352), 0, 0, 0); + AddLightComponent(new AddonComponent(0x2358), 0, -1, 0); + } + else + { + AddLightComponent(new AddonComponent(0x2360), 0, 0, 0); + AddLightComponent(new AddonComponent(0x2366), -1, 0, 0); + } + } + + public HearthOfHomeFire(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new HearthOfHomeFireDeed(); + + private void AddLightComponent(AddonComponent component, int x, int y, int z) + { + component.Light = LightType.Circle150; + + 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(); + } } - public HearthOfHomeFire(Serial serial) : base(serial) + public class HearthOfHomeFireDeed : BaseAddonDeed { + private bool m_East; + + [Constructible] + public HearthOfHomeFireDeed() => LootType = LootType.Blessed; + + public HearthOfHomeFireDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new HearthOfHomeFire(m_East); + + public override int LabelNumber => 1062919; // Hearth of the Home Fire + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new InternalGump(this)); + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + + private void SendTarget(Mobile m) + { + base.OnDoubleClick(m); + } + + 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(); + } + + private class InternalGump : Gump + { + private readonly HearthOfHomeFireDeed m_Deed; + + public InternalGump(HearthOfHomeFireDeed deed) : base(150, 50) + { + m_Deed = deed; + + AddBackground(0, 0, 350, 250, 0xA28); + + AddItem(90, 52, 0x2367); + AddItem(112, 35, 0x2360); + AddButton(70, 35, 0x868, 0x869, 1); // South + + AddItem(220, 35, 0x2352); + AddItem(242, 52, 0x2358); + AddButton(185, 35, 0x868, 0x869, 2); // East + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Deed.Deleted || info.ButtonID == 0) + return; + + m_Deed.m_East = info.ButtonID != 1; + m_Deed.SendTarget(sender.Mobile); + } + } } - - public override BaseAddonDeed Deed => new HearthOfHomeFireDeed(); - - private void AddLightComponent(AddonComponent component, int x, int y, int z) - { - component.Light = LightType.Circle150; - - 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); - - int version = reader.ReadEncodedInt(); - } - } - - public class HearthOfHomeFireDeed : BaseAddonDeed - { - private bool m_East; - - [Constructible] - public HearthOfHomeFireDeed() => LootType = LootType.Blessed; - - public HearthOfHomeFireDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new HearthOfHomeFire(m_East); - - public override int LabelNumber => 1062919; // Hearth of the Home Fire - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new InternalGump(this)); - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - - private void SendTarget(Mobile m) - { - base.OnDoubleClick(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - private class InternalGump : Gump - { - private readonly HearthOfHomeFireDeed m_Deed; - - public InternalGump(HearthOfHomeFireDeed deed) : base(150, 50) - { - m_Deed = deed; - - AddBackground(0, 0, 350, 250, 0xA28); - - AddItem(90, 52, 0x2367); - AddItem(112, 35, 0x2360); - AddButton(70, 35, 0x868, 0x869, 1); // South - - AddItem(220, 35, 0x2352); - AddItem(242, 52, 0x2358); - AddButton(185, 35, 0x868, 0x869, 2); // East - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Deed.Deleted || info.ButtonID == 0) - return; - - m_Deed.m_East = info.ButtonID != 1; - m_Deed.SendTarget(sender.Mobile); - } - } - } } diff --git a/Projects/UOContent/Items/Special/Gifts/HolySword.cs b/Projects/UOContent/Items/Special/Gifts/HolySword.cs index aff9d2ac2..bdc7b655c 100644 --- a/Projects/UOContent/Items/Special/Gifts/HolySword.cs +++ b/Projects/UOContent/Items/Special/Gifts/HolySword.cs @@ -1,42 +1,42 @@ namespace Server.Items { - public class HolySword : Longsword - { - [Constructible] - public HolySword() + public class HolySword : Longsword { - Hue = 0x482; - LootType = LootType.Blessed; + [Constructible] + public HolySword() + { + Hue = 0x482; + LootType = LootType.Blessed; - Slayer = SlayerName.Silver; + Slayer = SlayerName.Silver; - Attributes.WeaponDamage = 40; - WeaponAttributes.SelfRepair = 10; - WeaponAttributes.LowerStatReq = 100; - WeaponAttributes.UseBestSkill = 1; + Attributes.WeaponDamage = 40; + WeaponAttributes.SelfRepair = 10; + WeaponAttributes.LowerStatReq = 100; + WeaponAttributes.UseBestSkill = 1; + } + + public HolySword(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1062921; // The Holy Sword + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } } - - public HolySword(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1062921; // The Holy Sword - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Gifts/LeggingsOfEmbers.cs b/Projects/UOContent/Items/Special/Gifts/LeggingsOfEmbers.cs index 0bb8efe2b..4780107c8 100644 --- a/Projects/UOContent/Items/Special/Gifts/LeggingsOfEmbers.cs +++ b/Projects/UOContent/Items/Special/Gifts/LeggingsOfEmbers.cs @@ -1,45 +1,45 @@ namespace Server.Items { - public class LeggingsOfEmbers : PlateLegs - { - [Constructible] - public LeggingsOfEmbers() + public class LeggingsOfEmbers : PlateLegs { - Hue = 0x2C; - LootType = LootType.Blessed; + [Constructible] + public LeggingsOfEmbers() + { + Hue = 0x2C; + LootType = LootType.Blessed; - ArmorAttributes.SelfRepair = 10; - ArmorAttributes.MageArmor = 1; - ArmorAttributes.LowerStatReq = 100; + ArmorAttributes.SelfRepair = 10; + ArmorAttributes.MageArmor = 1; + ArmorAttributes.LowerStatReq = 100; + } + + public LeggingsOfEmbers(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1062911; // Royal Leggings of Embers + + public override int BasePhysicalResistance => 15; + public override int BaseFireResistance => 25; + public override int BaseColdResistance => 0; + public override int BasePoisonResistance => 15; + public override int BaseEnergyResistance => 15; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } } - - public LeggingsOfEmbers(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1062911; // Royal Leggings of Embers - - public override int BasePhysicalResistance => 15; - public override int BaseFireResistance => 25; - public override int BaseColdResistance => 0; - public override int BasePoisonResistance => 15; - public override int BaseEnergyResistance => 15; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Gifts/RoseOfTrinsic.cs b/Projects/UOContent/Items/Special/Gifts/RoseOfTrinsic.cs index 40762dcfd..62969ba7d 100644 --- a/Projects/UOContent/Items/Special/Gifts/RoseOfTrinsic.cs +++ b/Projects/UOContent/Items/Special/Gifts/RoseOfTrinsic.cs @@ -7,203 +7,204 @@ using Server.Network; namespace Server.Items { - [Flippable(0x234C, 0x234D)] - public class RoseOfTrinsic : Item, ISecurable - { - private static readonly TimeSpan m_SpawnTime = TimeSpan.FromHours(4.0); - private DateTime m_NextSpawnTime; - - private int m_Petals; - private SpawnTimer m_SpawnTimer; - - [Constructible] - public RoseOfTrinsic() : base(0x234D) + [Flippable(0x234C, 0x234D)] + public class RoseOfTrinsic : Item, ISecurable { - Weight = 1.0; - LootType = LootType.Blessed; + private static readonly TimeSpan m_SpawnTime = TimeSpan.FromHours(4.0); + private DateTime m_NextSpawnTime; - m_Petals = 0; - StartSpawnTimer(TimeSpan.FromMinutes(1.0)); - } + private int m_Petals; + private SpawnTimer m_SpawnTimer; - public RoseOfTrinsic(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1062913; // Rose of Trinsic - - [CommandProperty(AccessLevel.GameMaster)] - public int Petals - { - get => m_Petals; - set - { - if (value >= 10) + [Constructible] + public RoseOfTrinsic() : base(0x234D) { - m_Petals = 10; + Weight = 1.0; + LootType = LootType.Blessed; - StopSpawnTimer(); - } - else - { - if (value <= 0) m_Petals = 0; - else - m_Petals = value; - - StartSpawnTimer(m_SpawnTime); + StartSpawnTimer(TimeSpan.FromMinutes(1.0)); } - InvalidateProperties(); - } + public RoseOfTrinsic(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1062913; // Rose of Trinsic + + [CommandProperty(AccessLevel.GameMaster)] + public int Petals + { + get => m_Petals; + set + { + if (value >= 10) + { + m_Petals = 10; + + StopSpawnTimer(); + } + else + { + if (value <= 0) + m_Petals = 0; + else + m_Petals = value; + + StartSpawnTimer(m_SpawnTime); + } + + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public SecureLevel Level { get; set; } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1062925, Petals.ToString()); // Petals: ~1_COUNT~ + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + SetSecureLevelEntry.AddTo(from, this, list); + } + + private void StartSpawnTimer(TimeSpan delay) + { + StopSpawnTimer(); + + m_SpawnTimer = new SpawnTimer(this, delay); + m_SpawnTimer.Start(); + + m_NextSpawnTime = DateTime.UtcNow + delay; + } + + private void StopSpawnTimer() + { + if (m_SpawnTimer != null) + { + m_SpawnTimer.Stop(); + m_SpawnTimer = null; + } + } + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + else if (Petals > 0) + { + from.AddToBackpack(new RoseOfTrinsicPetal(Petals)); + Petals = 0; + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.WriteEncodedInt(m_Petals); + writer.WriteDeltaTime(m_NextSpawnTime); + writer.WriteEncodedInt((int)Level); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_Petals = reader.ReadEncodedInt(); + m_NextSpawnTime = reader.ReadDeltaTime(); + Level = (SecureLevel)reader.ReadEncodedInt(); + + if (m_Petals < 10) + StartSpawnTimer(m_NextSpawnTime - DateTime.UtcNow); + } + + private class SpawnTimer : Timer + { + private readonly RoseOfTrinsic m_Rose; + + public SpawnTimer(RoseOfTrinsic rose, TimeSpan delay) : base(delay) + { + m_Rose = rose; + + Priority = TimerPriority.OneMinute; + } + + protected override void OnTick() + { + if (m_Rose.Deleted) + return; + + m_Rose.m_SpawnTimer = null; + m_Rose.Petals++; + } + } } - [CommandProperty(AccessLevel.GameMaster)] - public SecureLevel Level { get; set; } - - public override void GetProperties(ObjectPropertyList list) + public class RoseOfTrinsicPetal : Item { - base.GetProperties(list); + [Constructible] + public RoseOfTrinsicPetal(int amount = 1) : base(0x1021) + { + Stackable = true; + Amount = amount; - list.Add(1062925, Petals.ToString()); // Petals: ~1_COUNT~ + Weight = 1.0; + Hue = 0xE; + } + + public RoseOfTrinsicPetal(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1062926; // Petal of the Rose of Trinsic + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. + } + else if (from.GetStatMod("RoseOfTrinsicPetal") != null) + { + from.SendLocalizedMessage( + 1062927 + ); // You have eaten one of these recently and eating another would provide no benefit. + } + else + { + from.PlaySound(0x1EE); + from.AddStatMod(new StatMod(StatType.Str, "RoseOfTrinsicPetal", 5, TimeSpan.FromMinutes(5.0))); + + Consume(); + } + } + + 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(); + } } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - SetSecureLevelEntry.AddTo(from, this, list); - } - - private void StartSpawnTimer(TimeSpan delay) - { - StopSpawnTimer(); - - m_SpawnTimer = new SpawnTimer(this, delay); - m_SpawnTimer.Start(); - - m_NextSpawnTime = DateTime.UtcNow + delay; - } - - private void StopSpawnTimer() - { - if (m_SpawnTimer != null) - { - m_SpawnTimer.Stop(); - m_SpawnTimer = null; - } - } - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - else if (Petals > 0) - { - from.AddToBackpack(new RoseOfTrinsicPetal(Petals)); - Petals = 0; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.WriteEncodedInt(m_Petals); - writer.WriteDeltaTime(m_NextSpawnTime); - writer.WriteEncodedInt((int)Level); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_Petals = reader.ReadEncodedInt(); - m_NextSpawnTime = reader.ReadDeltaTime(); - Level = (SecureLevel)reader.ReadEncodedInt(); - - if (m_Petals < 10) - StartSpawnTimer(m_NextSpawnTime - DateTime.UtcNow); - } - - private class SpawnTimer : Timer - { - private readonly RoseOfTrinsic m_Rose; - - public SpawnTimer(RoseOfTrinsic rose, TimeSpan delay) : base(delay) - { - m_Rose = rose; - - Priority = TimerPriority.OneMinute; - } - - protected override void OnTick() - { - if (m_Rose.Deleted) - return; - - m_Rose.m_SpawnTimer = null; - m_Rose.Petals++; - } - } - } - - public class RoseOfTrinsicPetal : Item - { - [Constructible] - public RoseOfTrinsicPetal(int amount = 1) : base(0x1021) - { - Stackable = true; - Amount = amount; - - Weight = 1.0; - Hue = 0xE; - } - - public RoseOfTrinsicPetal(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1062926; // Petal of the Rose of Trinsic - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. - } - else if (from.GetStatMod("RoseOfTrinsicPetal") != null) - { - from.SendLocalizedMessage( - 1062927); // You have eaten one of these recently and eating another would provide no benefit. - } - else - { - from.PlaySound(0x1EE); - from.AddStatMod(new StatMod(StatType.Str, "RoseOfTrinsicPetal", 5, TimeSpan.FromMinutes(5.0))); - - Consume(); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/Gifts/SamuraiHelm.cs b/Projects/UOContent/Items/Special/Gifts/SamuraiHelm.cs index f9478b7a1..684f37223 100644 --- a/Projects/UOContent/Items/Special/Gifts/SamuraiHelm.cs +++ b/Projects/UOContent/Items/Special/Gifts/SamuraiHelm.cs @@ -1,49 +1,49 @@ namespace Server.Items { - [Flippable(0x236C, 0x236D)] - public class SamuraiHelm : BaseArmor - { - [Constructible] - public SamuraiHelm() : base(0x236C) + [Flippable(0x236C, 0x236D)] + public class SamuraiHelm : BaseArmor { - Weight = 5.0; - LootType = LootType.Blessed; + [Constructible] + public SamuraiHelm() : base(0x236C) + { + Weight = 5.0; + LootType = LootType.Blessed; - Attributes.DefendChance = 15; - ArmorAttributes.SelfRepair = 10; - ArmorAttributes.LowerStatReq = 100; - ArmorAttributes.MageArmor = 1; + Attributes.DefendChance = 15; + ArmorAttributes.SelfRepair = 10; + ArmorAttributes.LowerStatReq = 100; + ArmorAttributes.MageArmor = 1; + } + + public SamuraiHelm(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1062923; // Ancient Samurai Helm + + public override int BasePhysicalResistance => 15; + public override int BaseFireResistance => 10; + public override int BaseColdResistance => 10; + public override int BasePoisonResistance => 15; + public override int BaseEnergyResistance => 10; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; + + 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(); + } } - - public SamuraiHelm(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1062923; // Ancient Samurai Helm - - public override int BasePhysicalResistance => 15; - public override int BaseFireResistance => 10; - public override int BaseColdResistance => 10; - public override int BasePoisonResistance => 15; - public override int BaseEnergyResistance => 10; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override ArmorMaterialType MaterialType => ArmorMaterialType.Plate; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Gifts/ShaminoCrossbow.cs b/Projects/UOContent/Items/Special/Gifts/ShaminoCrossbow.cs index 30a458a18..3589cad06 100644 --- a/Projects/UOContent/Items/Special/Gifts/ShaminoCrossbow.cs +++ b/Projects/UOContent/Items/Special/Gifts/ShaminoCrossbow.cs @@ -1,40 +1,40 @@ namespace Server.Items { - public class ShaminoCrossbow : RepeatingCrossbow - { - [Constructible] - public ShaminoCrossbow() + public class ShaminoCrossbow : RepeatingCrossbow { - Hue = 0x504; - LootType = LootType.Blessed; + [Constructible] + public ShaminoCrossbow() + { + Hue = 0x504; + LootType = LootType.Blessed; - Attributes.AttackChance = 15; - Attributes.WeaponDamage = 40; - WeaponAttributes.SelfRepair = 10; - WeaponAttributes.LowerStatReq = 100; + Attributes.AttackChance = 15; + Attributes.WeaponDamage = 40; + WeaponAttributes.SelfRepair = 10; + WeaponAttributes.LowerStatReq = 100; + } + + public ShaminoCrossbow(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1062915; // Shamino�s Best Crossbow + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } } - - public ShaminoCrossbow(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1062915; // Shamino�s Best Crossbow - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Gifts/TapestryOfSosaria.cs b/Projects/UOContent/Items/Special/Gifts/TapestryOfSosaria.cs index 34e78a500..9718693ac 100644 --- a/Projects/UOContent/Items/Special/Gifts/TapestryOfSosaria.cs +++ b/Projects/UOContent/Items/Special/Gifts/TapestryOfSosaria.cs @@ -6,69 +6,69 @@ using Server.Network; namespace Server.Items { - [Flippable(0x234E, 0x234F)] - public class TapestryOfSosaria : Item, ISecurable - { - [Constructible] - public TapestryOfSosaria() : base(0x234E) + [Flippable(0x234E, 0x234F)] + public class TapestryOfSosaria : Item, ISecurable { - Weight = 1.0; - LootType = LootType.Blessed; + [Constructible] + public TapestryOfSosaria() : base(0x234E) + { + Weight = 1.0; + LootType = LootType.Blessed; + } + + public TapestryOfSosaria(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1062917; // The Tapestry of Sosaria + + [CommandProperty(AccessLevel.GameMaster)] + public SecureLevel Level { get; set; } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + SetSecureLevelEntry.AddTo(from, this, list); + } + + public override void OnDoubleClick(Mobile from) + { + if (from.InRange(GetWorldLocation(), 2)) + { + from.CloseGump(); + from.SendGump(new InternalGump()); + } + else + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.WriteEncodedInt((int)Level); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + Level = (SecureLevel)reader.ReadEncodedInt(); + } + + private class InternalGump : Gump + { + public InternalGump() : base(50, 50) + { + AddImage(0, 0, 0x2C95); + } + } } - - public TapestryOfSosaria(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1062917; // The Tapestry of Sosaria - - [CommandProperty(AccessLevel.GameMaster)] - public SecureLevel Level { get; set; } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - SetSecureLevelEntry.AddTo(from, this, list); - } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(GetWorldLocation(), 2)) - { - from.CloseGump(); - from.SendGump(new InternalGump()); - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.WriteEncodedInt((int)Level); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - Level = (SecureLevel)reader.ReadEncodedInt(); - } - - private class InternalGump : Gump - { - public InternalGump() : base(50, 50) - { - AddImage(0, 0, 0x2C95); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/AppleTrunk.cs b/Projects/UOContent/Items/Special/Heritage Items/AppleTrunk.cs index 3a67b67ee..546f3486c 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/AppleTrunk.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/AppleTrunk.cs @@ -1,58 +1,58 @@ namespace Server.Items { - public class AppleTrunkAddon : BaseAddon - { - [Constructible] - public AppleTrunkAddon() + public class AppleTrunkAddon : BaseAddon { - AddComponent(new LocalizedAddonComponent(0xD98, 1076785), 0, 0, 0); + [Constructible] + public AppleTrunkAddon() + { + AddComponent(new LocalizedAddonComponent(0xD98, 1076785), 0, 0, 0); + } + + public AppleTrunkAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new AppleTrunkDeed(); + + 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(); + } } - public AppleTrunkAddon(Serial serial) : base(serial) + public class AppleTrunkDeed : BaseAddonDeed { + [Constructible] + public AppleTrunkDeed() => LootType = LootType.Blessed; + + public AppleTrunkDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new AppleTrunkAddon(); + public override int LabelNumber => 1076785; // Apple Trunk + + 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(); + } } - - public override BaseAddonDeed Deed => new AppleTrunkDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class AppleTrunkDeed : BaseAddonDeed - { - [Constructible] - public AppleTrunkDeed() => LootType = LootType.Blessed; - - public AppleTrunkDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new AppleTrunkAddon(); - public override int LabelNumber => 1076785; // Apple Trunk - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/BlueDecorativeRug.cs b/Projects/UOContent/Items/Special/Heritage Items/BlueDecorativeRug.cs index 83fdb0ab8..7b7e0f428 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/BlueDecorativeRug.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/BlueDecorativeRug.cs @@ -1,66 +1,66 @@ namespace Server.Items { - public class BlueDecorativeRugAddon : BaseAddon - { - [Constructible] - public BlueDecorativeRugAddon() + public class BlueDecorativeRugAddon : BaseAddon { - AddComponent(new LocalizedAddonComponent(0xAD2, 1076589), 1, 1, 0); - AddComponent(new LocalizedAddonComponent(0xAD3, 1076589), -1, -1, 0); - AddComponent(new LocalizedAddonComponent(0xAD4, 1076589), -1, 1, 0); - AddComponent(new LocalizedAddonComponent(0xAD5, 1076589), 1, -1, 0); - AddComponent(new LocalizedAddonComponent(0xAD6, 1076589), -1, 0, 0); - AddComponent(new LocalizedAddonComponent(0xAD7, 1076589), 0, -1, 0); - AddComponent(new LocalizedAddonComponent(0xAD8, 1076589), 1, 0, 0); - AddComponent(new LocalizedAddonComponent(0xAD9, 1076589), 0, 1, 0); - AddComponent(new LocalizedAddonComponent(0xAD1, 1076589), 0, 0, 0); + [Constructible] + public BlueDecorativeRugAddon() + { + AddComponent(new LocalizedAddonComponent(0xAD2, 1076589), 1, 1, 0); + AddComponent(new LocalizedAddonComponent(0xAD3, 1076589), -1, -1, 0); + AddComponent(new LocalizedAddonComponent(0xAD4, 1076589), -1, 1, 0); + AddComponent(new LocalizedAddonComponent(0xAD5, 1076589), 1, -1, 0); + AddComponent(new LocalizedAddonComponent(0xAD6, 1076589), -1, 0, 0); + AddComponent(new LocalizedAddonComponent(0xAD7, 1076589), 0, -1, 0); + AddComponent(new LocalizedAddonComponent(0xAD8, 1076589), 1, 0, 0); + AddComponent(new LocalizedAddonComponent(0xAD9, 1076589), 0, 1, 0); + AddComponent(new LocalizedAddonComponent(0xAD1, 1076589), 0, 0, 0); + } + + public BlueDecorativeRugAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new BlueDecorativeRugDeed(); + + 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(); + } } - public BlueDecorativeRugAddon(Serial serial) : base(serial) + public class BlueDecorativeRugDeed : BaseAddonDeed { + [Constructible] + public BlueDecorativeRugDeed() => LootType = LootType.Blessed; + + public BlueDecorativeRugDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new BlueDecorativeRugAddon(); + public override int LabelNumber => 1076589; // Blue decorative rug + + 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(); + } } - - public override BaseAddonDeed Deed => new BlueDecorativeRugDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BlueDecorativeRugDeed : BaseAddonDeed - { - [Constructible] - public BlueDecorativeRugDeed() => LootType = LootType.Blessed; - - public BlueDecorativeRugDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new BlueDecorativeRugAddon(); - public override int LabelNumber => 1076589; // Blue decorative rug - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/BlueFancyRug.cs b/Projects/UOContent/Items/Special/Heritage Items/BlueFancyRug.cs index dd86d261a..49f657973 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/BlueFancyRug.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/BlueFancyRug.cs @@ -1,66 +1,66 @@ namespace Server.Items { - public class BlueFancyRugAddon : BaseAddon - { - [Constructible] - public BlueFancyRugAddon() + public class BlueFancyRugAddon : BaseAddon { - AddComponent(new LocalizedAddonComponent(0xAC2, 1076273), 1, 1, 0); - AddComponent(new LocalizedAddonComponent(0xAC3, 1076273), -1, -1, 0); - AddComponent(new LocalizedAddonComponent(0xAC4, 1076273), -1, 1, 0); - AddComponent(new LocalizedAddonComponent(0xAC5, 1076273), 1, -1, 0); - AddComponent(new LocalizedAddonComponent(0xAF6, 1076273), -1, 0, 0); - AddComponent(new LocalizedAddonComponent(0xAF7, 1076273), 0, -1, 0); - AddComponent(new LocalizedAddonComponent(0xAF8, 1076273), 1, 0, 0); - AddComponent(new LocalizedAddonComponent(0xAF9, 1076273), 0, 1, 0); - AddComponent(new LocalizedAddonComponent(0xAFA, 1076273), 0, 0, 0); + [Constructible] + public BlueFancyRugAddon() + { + AddComponent(new LocalizedAddonComponent(0xAC2, 1076273), 1, 1, 0); + AddComponent(new LocalizedAddonComponent(0xAC3, 1076273), -1, -1, 0); + AddComponent(new LocalizedAddonComponent(0xAC4, 1076273), -1, 1, 0); + AddComponent(new LocalizedAddonComponent(0xAC5, 1076273), 1, -1, 0); + AddComponent(new LocalizedAddonComponent(0xAF6, 1076273), -1, 0, 0); + AddComponent(new LocalizedAddonComponent(0xAF7, 1076273), 0, -1, 0); + AddComponent(new LocalizedAddonComponent(0xAF8, 1076273), 1, 0, 0); + AddComponent(new LocalizedAddonComponent(0xAF9, 1076273), 0, 1, 0); + AddComponent(new LocalizedAddonComponent(0xAFA, 1076273), 0, 0, 0); + } + + public BlueFancyRugAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new BlueFancyRugDeed(); + + 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(); + } } - public BlueFancyRugAddon(Serial serial) : base(serial) + public class BlueFancyRugDeed : BaseAddonDeed { + [Constructible] + public BlueFancyRugDeed() => LootType = LootType.Blessed; + + public BlueFancyRugDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new BlueFancyRugAddon(); + public override int LabelNumber => 1076273; // Blue fancy rug + + 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(); + } } - - public override BaseAddonDeed Deed => new BlueFancyRugDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BlueFancyRugDeed : BaseAddonDeed - { - [Constructible] - public BlueFancyRugDeed() => LootType = LootType.Blessed; - - public BlueFancyRugDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new BlueFancyRugAddon(); - public override int LabelNumber => 1076273; // Blue fancy rug - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/BluePlainRug.cs b/Projects/UOContent/Items/Special/Heritage Items/BluePlainRug.cs index 671077f8b..0e23d1d5f 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/BluePlainRug.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/BluePlainRug.cs @@ -1,66 +1,66 @@ namespace Server.Items { - public class BluePlainRugAddon : BaseAddon - { - [Constructible] - public BluePlainRugAddon() + public class BluePlainRugAddon : BaseAddon { - AddComponent(new LocalizedAddonComponent(0xAC2, 1076585), 1, 1, 0); - AddComponent(new LocalizedAddonComponent(0xAC3, 1076585), -1, -1, 0); - AddComponent(new LocalizedAddonComponent(0xAC4, 1076585), -1, 1, 0); - AddComponent(new LocalizedAddonComponent(0xAC5, 1076585), 1, -1, 0); - AddComponent(new LocalizedAddonComponent(0xAF6, 1076585), -1, 0, 0); - AddComponent(new LocalizedAddonComponent(0xAF7, 1076585), 0, -1, 0); - AddComponent(new LocalizedAddonComponent(0xAF8, 1076585), 1, 0, 0); - AddComponent(new LocalizedAddonComponent(0xAF9, 1076585), 0, 1, 0); - AddComponent(new LocalizedAddonComponent(0xAC0, 1076585), 0, 0, 0); + [Constructible] + public BluePlainRugAddon() + { + AddComponent(new LocalizedAddonComponent(0xAC2, 1076585), 1, 1, 0); + AddComponent(new LocalizedAddonComponent(0xAC3, 1076585), -1, -1, 0); + AddComponent(new LocalizedAddonComponent(0xAC4, 1076585), -1, 1, 0); + AddComponent(new LocalizedAddonComponent(0xAC5, 1076585), 1, -1, 0); + AddComponent(new LocalizedAddonComponent(0xAF6, 1076585), -1, 0, 0); + AddComponent(new LocalizedAddonComponent(0xAF7, 1076585), 0, -1, 0); + AddComponent(new LocalizedAddonComponent(0xAF8, 1076585), 1, 0, 0); + AddComponent(new LocalizedAddonComponent(0xAF9, 1076585), 0, 1, 0); + AddComponent(new LocalizedAddonComponent(0xAC0, 1076585), 0, 0, 0); + } + + public BluePlainRugAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new BluePlainRugDeed(); + + 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(); + } } - public BluePlainRugAddon(Serial serial) : base(serial) + public class BluePlainRugDeed : BaseAddonDeed { + [Constructible] + public BluePlainRugDeed() => LootType = LootType.Blessed; + + public BluePlainRugDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new BluePlainRugAddon(); + public override int LabelNumber => 1076585; // Blue plain rug + + 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(); + } } - - public override BaseAddonDeed Deed => new BluePlainRugDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BluePlainRugDeed : BaseAddonDeed - { - [Constructible] - public BluePlainRugDeed() => LootType = LootType.Blessed; - - public BluePlainRugDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new BluePlainRugAddon(); - public override int LabelNumber => 1076585; // Blue plain rug - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/BoilingCauldron.cs b/Projects/UOContent/Items/Special/Heritage Items/BoilingCauldron.cs index cf825584a..395aedf03 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/BoilingCauldron.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/BoilingCauldron.cs @@ -1,63 +1,63 @@ namespace Server.Items { - [Flippable(0x2068, 0x207A)] - public class BoilingCauldronAddon : BaseAddonContainer - { - [Constructible] - public BoilingCauldronAddon() : base(0x2068) + [Flippable(0x2068, 0x207A)] + public class BoilingCauldronAddon : BaseAddonContainer { - AddComponent(new LocalizedContainerComponent(0xFAC, 1076267), 0, 0, 0); - AddComponent(new LocalizedContainerComponent(0x970, 1076267), 0, 0, 8); + [Constructible] + public BoilingCauldronAddon() : base(0x2068) + { + AddComponent(new LocalizedContainerComponent(0xFAC, 1076267), 0, 0, 0); + AddComponent(new LocalizedContainerComponent(0x970, 1076267), 0, 0, 8); + } + + public BoilingCauldronAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonContainerDeed Deed => new BoilingCauldronDeed(); + public override int LabelNumber => 1076267; // Boiling Cauldron + public override int DefaultGumpID => 0x9; + public override int DefaultDropSound => 0x42; + + 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(); + } } - public BoilingCauldronAddon(Serial serial) : base(serial) + public class BoilingCauldronDeed : BaseAddonContainerDeed { + [Constructible] + public BoilingCauldronDeed() => LootType = LootType.Blessed; + + public BoilingCauldronDeed(Serial serial) : base(serial) + { + } + + public override BaseAddonContainer Addon => new BoilingCauldronAddon(); + public override int LabelNumber => 1076267; // Boiling Cauldron + + 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(); + } } - - public override BaseAddonContainerDeed Deed => new BoilingCauldronDeed(); - public override int LabelNumber => 1076267; // Boiling Cauldron - public override int DefaultGumpID => 0x9; - public override int DefaultDropSound => 0x42; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BoilingCauldronDeed : BaseAddonContainerDeed - { - [Constructible] - public BoilingCauldronDeed() => LootType = LootType.Blessed; - - public BoilingCauldronDeed(Serial serial) : base(serial) - { - } - - public override BaseAddonContainer Addon => new BoilingCauldronAddon(); - public override int LabelNumber => 1076267; // Boiling Cauldron - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/CherryBlossomTree.cs b/Projects/UOContent/Items/Special/Heritage Items/CherryBlossomTree.cs index 16c5c9a93..059897ddd 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/CherryBlossomTree.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/CherryBlossomTree.cs @@ -1,59 +1,59 @@ namespace Server.Items { - public class CherryBlossomTreeAddon : BaseAddon - { - [Constructible] - public CherryBlossomTreeAddon() + public class CherryBlossomTreeAddon : BaseAddon { - AddComponent(new LocalizedAddonComponent(0x26EE, 1076268), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0x3122, 1076268), 0, 0, 0); + [Constructible] + public CherryBlossomTreeAddon() + { + AddComponent(new LocalizedAddonComponent(0x26EE, 1076268), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0x3122, 1076268), 0, 0, 0); + } + + public CherryBlossomTreeAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new CherryBlossomTreeDeed(); + + 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(); + } } - public CherryBlossomTreeAddon(Serial serial) : base(serial) + public class CherryBlossomTreeDeed : BaseAddonDeed { + [Constructible] + public CherryBlossomTreeDeed() => LootType = LootType.Blessed; + + public CherryBlossomTreeDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new CherryBlossomTreeAddon(); + public override int LabelNumber => 1076268; // Cherry Blossom Tree + + 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(); + } } - - public override BaseAddonDeed Deed => new CherryBlossomTreeDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class CherryBlossomTreeDeed : BaseAddonDeed - { - [Constructible] - public CherryBlossomTreeDeed() => LootType = LootType.Blessed; - - public CherryBlossomTreeDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new CherryBlossomTreeAddon(); - public override int LabelNumber => 1076268; // Cherry Blossom Tree - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/CherryBlossomTrunk.cs b/Projects/UOContent/Items/Special/Heritage Items/CherryBlossomTrunk.cs index 2c737ae71..09b2e73bf 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/CherryBlossomTrunk.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/CherryBlossomTrunk.cs @@ -1,58 +1,58 @@ namespace Server.Items { - public class CherryBlossomTrunkAddon : BaseAddon - { - [Constructible] - public CherryBlossomTrunkAddon() + public class CherryBlossomTrunkAddon : BaseAddon { - AddComponent(new LocalizedAddonComponent(0x26EE, 1076784), 0, 0, 0); + [Constructible] + public CherryBlossomTrunkAddon() + { + AddComponent(new LocalizedAddonComponent(0x26EE, 1076784), 0, 0, 0); + } + + public CherryBlossomTrunkAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new CherryBlossomTrunkDeed(); + + 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(); + } } - public CherryBlossomTrunkAddon(Serial serial) : base(serial) + public class CherryBlossomTrunkDeed : BaseAddonDeed { + [Constructible] + public CherryBlossomTrunkDeed() => LootType = LootType.Blessed; + + public CherryBlossomTrunkDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new CherryBlossomTrunkAddon(); + public override int LabelNumber => 1076784; // Cherry Blossom Trunk + + 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(); + } } - - public override BaseAddonDeed Deed => new CherryBlossomTrunkDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class CherryBlossomTrunkDeed : BaseAddonDeed - { - [Constructible] - public CherryBlossomTrunkDeed() => LootType = LootType.Blessed; - - public CherryBlossomTrunkDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new CherryBlossomTrunkAddon(); - public override int LabelNumber => 1076784; // Cherry Blossom Trunk - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/CinnamonFancyRug.cs b/Projects/UOContent/Items/Special/Heritage Items/CinnamonFancyRug.cs index e5f1b3eb8..ab593cac6 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/CinnamonFancyRug.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/CinnamonFancyRug.cs @@ -1,66 +1,66 @@ namespace Server.Items { - public class CinnamonFancyRugAddon : BaseAddon - { - [Constructible] - public CinnamonFancyRugAddon() + public class CinnamonFancyRugAddon : BaseAddon { - AddComponent(new LocalizedAddonComponent(0xAE3, 1076587), 1, 1, 0); - AddComponent(new LocalizedAddonComponent(0xAE4, 1076587), -1, -1, 0); - AddComponent(new LocalizedAddonComponent(0xAE5, 1076587), -1, 1, 0); - AddComponent(new LocalizedAddonComponent(0xAE6, 1076587), 1, -1, 0); - AddComponent(new LocalizedAddonComponent(0xAE7, 1076587), -1, 0, 0); - AddComponent(new LocalizedAddonComponent(0xAE8, 1076587), 0, -1, 0); - AddComponent(new LocalizedAddonComponent(0xAE9, 1076587), 1, 0, 0); - AddComponent(new LocalizedAddonComponent(0xAEA, 1076587), 0, 1, 0); - AddComponent(new LocalizedAddonComponent(0xAEB, 1076587), 0, 0, 0); + [Constructible] + public CinnamonFancyRugAddon() + { + AddComponent(new LocalizedAddonComponent(0xAE3, 1076587), 1, 1, 0); + AddComponent(new LocalizedAddonComponent(0xAE4, 1076587), -1, -1, 0); + AddComponent(new LocalizedAddonComponent(0xAE5, 1076587), -1, 1, 0); + AddComponent(new LocalizedAddonComponent(0xAE6, 1076587), 1, -1, 0); + AddComponent(new LocalizedAddonComponent(0xAE7, 1076587), -1, 0, 0); + AddComponent(new LocalizedAddonComponent(0xAE8, 1076587), 0, -1, 0); + AddComponent(new LocalizedAddonComponent(0xAE9, 1076587), 1, 0, 0); + AddComponent(new LocalizedAddonComponent(0xAEA, 1076587), 0, 1, 0); + AddComponent(new LocalizedAddonComponent(0xAEB, 1076587), 0, 0, 0); + } + + public CinnamonFancyRugAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new CinnamonFancyRugDeed(); + + 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(); + } } - public CinnamonFancyRugAddon(Serial serial) : base(serial) + public class CinnamonFancyRugDeed : BaseAddonDeed { + [Constructible] + public CinnamonFancyRugDeed() => LootType = LootType.Blessed; + + public CinnamonFancyRugDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new CinnamonFancyRugAddon(); + public override int LabelNumber => 1076587; // Cinnamon fancy rug + + 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(); + } } - - public override BaseAddonDeed Deed => new CinnamonFancyRugDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class CinnamonFancyRugDeed : BaseAddonDeed - { - [Constructible] - public CinnamonFancyRugDeed() => LootType = LootType.Blessed; - - public CinnamonFancyRugDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new CinnamonFancyRugAddon(); - public override int LabelNumber => 1076587; // Cinnamon fancy rug - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/Curtains.cs b/Projects/UOContent/Items/Special/Heritage Items/Curtains.cs index e5b2263ae..eb34691eb 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/Curtains.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/Curtains.cs @@ -3,191 +3,191 @@ using Server.Network; namespace Server.Items { - public class CurtainsComponent : AddonComponent, IDyable - { - public CurtainsComponent(int itemID, int closedID) : base(itemID) => ClosedID = closedID; - - public CurtainsComponent(Serial serial) : base(serial) + public class CurtainsComponent : AddonComponent, IDyable { + public CurtainsComponent(int itemID, int closedID) : base(itemID) => ClosedID = closedID; + + public CurtainsComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1076280; // Curtains + public override bool DisplayWeight => false; + + [CommandProperty(AccessLevel.GameMaster)] + public int ClosedID { get; set; } + + public virtual bool Dye(Mobile from, DyeTub sender) + { + if (Deleted) + return false; + + Hue = sender.DyedHue; + return true; + } + + public override void OnDoubleClick(Mobile from) + { + base.OnDoubleClick(from); + + if (Addon != null) + if (from.InRange(Location, 1)) + foreach (var c in Addon.Components) + if (c is CurtainsComponent curtain) + { + var temp = curtain.ItemID; + curtain.ItemID = curtain.ClosedID; + curtain.ClosedID = temp; + } + else + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(ClosedID); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + ClosedID = reader.ReadInt(); + } } - public override int LabelNumber => 1076280; // Curtains - public override bool DisplayWeight => false; - - [CommandProperty(AccessLevel.GameMaster)] - public int ClosedID { get; set; } - - public virtual bool Dye(Mobile from, DyeTub sender) + public class CurtainsAddon : BaseAddon { - if (Deleted) - return false; - - Hue = sender.DyedHue; - return true; - } - - public override void OnDoubleClick(Mobile from) - { - base.OnDoubleClick(from); - - if (Addon != null) - if (from.InRange(Location, 1)) - foreach (AddonComponent c in Addon.Components) - if (c is CurtainsComponent curtain) + [Constructible] + public CurtainsAddon(bool east) + { + if (east) // east { - int temp = curtain.ItemID; - curtain.ItemID = curtain.ClosedID; - curtain.ClosedID = temp; + AddComponent(new CurtainsComponent(0x3D9E, 0x3DA8), 0, -1, 0); + AddComponent(new CurtainsComponent(0x3DAC, 0x3DAE), 0, 0, 0); + AddComponent(new CurtainsComponent(0x3DA0, 0x3DA6), 0, 2, 0); + AddComponent(new CurtainsComponent(0x3D9F, 0x3DA7), 0, 1, 0); + } + else // south + { + AddComponent(new CurtainsComponent(0x3D9C, 0x3DAD), 0, 0, 0); + AddComponent(new CurtainsComponent(0x3D9D, 0x3DA3), -1, 0, 0); + AddComponent(new CurtainsComponent(0x3DA1, 0x3DA5), 2, 0, 0); + AddComponent(new CurtainsComponent(0x3DAB, 0x3DA4), 1, 0, 0); + } + } + + public CurtainsAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new CurtainsDeed(); + public override bool RetainDeedHue => true; + + 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(); + } + } + + public class CurtainsDeed : BaseAddonDeed + { + private bool m_East; + + [Constructible] + public CurtainsDeed() => LootType = LootType.Blessed; + + public CurtainsDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new CurtainsAddon(m_East); + public override int LabelNumber => 1076280; // Curtains + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new InternalGump(this)); } else { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. } + } + + private void SendTarget(Mobile m) + { + base.OnDoubleClick(m); + } + + 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(); + } + + private class InternalGump : Gump + { + private readonly CurtainsDeed m_Deed; + + public InternalGump(CurtainsDeed deed) : base(60, 36) + { + m_Deed = deed; + + AddPage(0); + + AddBackground(0, 0, 273, 324, 0x13BE); + AddImageTiled(10, 10, 253, 20, 0xA40); + AddImageTiled(10, 40, 253, 244, 0xA40); + AddImageTiled(10, 294, 253, 20, 0xA40); + AddAlphaRegion(10, 10, 253, 304); + AddButton(10, 294, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL + AddHtmlLocalized(14, 12, 273, 20, 1076581, 0x7FFF); // Please select your curtain position + + AddPage(1); + + AddButton(19, 49, 0x845, 0x846, 1); + AddHtmlLocalized(44, 47, 213, 20, 1075386, 0x7FFF); // South + AddButton(19, 73, 0x845, 0x846, 2); + AddHtmlLocalized(44, 71, 213, 20, 1075387, 0x7FFF); // East + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Deed?.Deleted != false || info.ButtonID == 0) + return; + + m_Deed.m_East = info.ButtonID != 1; + m_Deed.SendTarget(sender.Mobile); + } + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(ClosedID); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - ClosedID = reader.ReadInt(); - } - } - - public class CurtainsAddon : BaseAddon - { - [Constructible] - public CurtainsAddon(bool east) - { - if (east) // east - { - AddComponent(new CurtainsComponent(0x3D9E, 0x3DA8), 0, -1, 0); - AddComponent(new CurtainsComponent(0x3DAC, 0x3DAE), 0, 0, 0); - AddComponent(new CurtainsComponent(0x3DA0, 0x3DA6), 0, 2, 0); - AddComponent(new CurtainsComponent(0x3D9F, 0x3DA7), 0, 1, 0); - } - else // south - { - AddComponent(new CurtainsComponent(0x3D9C, 0x3DAD), 0, 0, 0); - AddComponent(new CurtainsComponent(0x3D9D, 0x3DA3), -1, 0, 0); - AddComponent(new CurtainsComponent(0x3DA1, 0x3DA5), 2, 0, 0); - AddComponent(new CurtainsComponent(0x3DAB, 0x3DA4), 1, 0, 0); - } - } - - public CurtainsAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new CurtainsDeed(); - public override bool RetainDeedHue => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class CurtainsDeed : BaseAddonDeed - { - private bool m_East; - - [Constructible] - public CurtainsDeed() => LootType = LootType.Blessed; - - public CurtainsDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new CurtainsAddon(m_East); - public override int LabelNumber => 1076280; // Curtains - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new InternalGump(this)); - } - else - { - from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. - } - } - - private void SendTarget(Mobile m) - { - base.OnDoubleClick(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - private class InternalGump : Gump - { - private readonly CurtainsDeed m_Deed; - - public InternalGump(CurtainsDeed deed) : base(60, 36) - { - m_Deed = deed; - - AddPage(0); - - AddBackground(0, 0, 273, 324, 0x13BE); - AddImageTiled(10, 10, 253, 20, 0xA40); - AddImageTiled(10, 40, 253, 244, 0xA40); - AddImageTiled(10, 294, 253, 20, 0xA40); - AddAlphaRegion(10, 10, 253, 304); - AddButton(10, 294, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL - AddHtmlLocalized(14, 12, 273, 20, 1076581, 0x7FFF); // Please select your curtain position - - AddPage(1); - - AddButton(19, 49, 0x845, 0x846, 1); - AddHtmlLocalized(44, 47, 213, 20, 1075386, 0x7FFF); // South - AddButton(19, 73, 0x845, 0x846, 2); - AddHtmlLocalized(44, 71, 213, 20, 1075387, 0x7FFF); // East - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Deed?.Deleted != false || info.ButtonID == 0) - return; - - m_Deed.m_East = info.ButtonID != 1; - m_Deed.SendTarget(sender.Mobile); - } - } - } } diff --git a/Projects/UOContent/Items/Special/Heritage Items/Fountain.cs b/Projects/UOContent/Items/Special/Heritage Items/Fountain.cs index b90bd499b..aa5f8b340 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/Fountain.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/Fountain.cs @@ -1,57 +1,57 @@ namespace Server.Items { - public class FountainAddon : StoneFountainAddon - { - [Constructible] - public FountainAddon() + public class FountainAddon : StoneFountainAddon { + [Constructible] + public FountainAddon() + { + } + + public FountainAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new FountainDeed(); + + 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(); + } } - public FountainAddon(Serial serial) : base(serial) + public class FountainDeed : BaseAddonDeed { + [Constructible] + public FountainDeed() => LootType = LootType.Blessed; + + public FountainDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new FountainAddon(); + public override int LabelNumber => 1076283; // Fountain + + 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(); + } } - - public override BaseAddonDeed Deed => new FountainDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class FountainDeed : BaseAddonDeed - { - [Constructible] - public FountainDeed() => LootType = LootType.Blessed; - - public FountainDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new FountainAddon(); - public override int LabelNumber => 1076283; // Fountain - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/FruitTrees.cs b/Projects/UOContent/Items/Special/Heritage Items/FruitTrees.cs index 447084354..9e32c8f95 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/FruitTrees.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/FruitTrees.cs @@ -3,204 +3,204 @@ using Server.Network; namespace Server.Items { - public abstract class BaseFruitTreeAddon : BaseAddon - { - private int m_Fruits; - - public BaseFruitTreeAddon() + public abstract class BaseFruitTreeAddon : BaseAddon { - Timer.DelayCall(TimeSpan.FromMinutes(5), Respawn); - } + private int m_Fruits; - public BaseFruitTreeAddon(Serial serial) : base(serial) - { - } - - public abstract override BaseAddonDeed Deed { get; } - public abstract Item Fruit { get; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Fruits - { - get => m_Fruits; - set => m_Fruits = Math.Max(value, 0); - } - - public override void OnComponentUsed(AddonComponent c, Mobile from) - { - if (from.InRange(c.Location, 2)) - { - if (m_Fruits > 0) + public BaseFruitTreeAddon() { - Item fruit = Fruit; - - if (fruit == null) - return; - - if (!from.PlaceInBackpack(fruit)) - { - fruit.Delete(); - from.SendLocalizedMessage(501015); // There is no room in your backpack for the fruit. - } - else - { - if (--m_Fruits == 0) - Timer.DelayCall(TimeSpan.FromMinutes(30), Respawn); - - from.SendLocalizedMessage(501016); // You pick some fruit and put it in your backpack. - } + Timer.DelayCall(TimeSpan.FromMinutes(5), Respawn); } - else + + public BaseFruitTreeAddon(Serial serial) : base(serial) { - from.SendLocalizedMessage(501017); // There is no more fruit on this tree } - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } + + public abstract override BaseAddonDeed Deed { get; } + public abstract Item Fruit { get; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Fruits + { + get => m_Fruits; + set => m_Fruits = Math.Max(value, 0); + } + + public override void OnComponentUsed(AddonComponent c, Mobile from) + { + if (from.InRange(c.Location, 2)) + { + if (m_Fruits > 0) + { + var fruit = Fruit; + + if (fruit == null) + return; + + if (!from.PlaceInBackpack(fruit)) + { + fruit.Delete(); + from.SendLocalizedMessage(501015); // There is no room in your backpack for the fruit. + } + else + { + if (--m_Fruits == 0) + Timer.DelayCall(TimeSpan.FromMinutes(30), Respawn); + + from.SendLocalizedMessage(501016); // You pick some fruit and put it in your backpack. + } + } + else + { + from.SendLocalizedMessage(501017); // There is no more fruit on this tree + } + } + else + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + } + + private void Respawn() + { + m_Fruits = Utility.RandomMinMax(1, 4); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_Fruits); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_Fruits = reader.ReadInt(); + + if (m_Fruits == 0) + Respawn(); + } } - private void Respawn() + public class AppleTreeAddon : BaseFruitTreeAddon { - m_Fruits = Utility.RandomMinMax(1, 4); + [Constructible] + public AppleTreeAddon() + { + AddComponent(new LocalizedAddonComponent(0xD98, 1076269), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0x3124, 1076269), 0, 0, 0); + } + + public AppleTreeAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new AppleTreeDeed(); + public override Item Fruit => new Apple(); + + 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(); + } } - public override void Serialize(IGenericWriter writer) + public class AppleTreeDeed : BaseAddonDeed { - base.Serialize(writer); + [Constructible] + public AppleTreeDeed() => LootType = LootType.Blessed; - writer.WriteEncodedInt(0); // version + public AppleTreeDeed(Serial serial) : base(serial) + { + } - writer.Write(m_Fruits); + public override BaseAddon Addon => new AppleTreeAddon(); + public override int LabelNumber => 1076269; // Apple Tree + + 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(); + } } - public override void Deserialize(IGenericReader reader) + public class PeachTreeAddon : BaseFruitTreeAddon { - base.Deserialize(reader); + [Constructible] + public PeachTreeAddon() + { + AddComponent(new LocalizedAddonComponent(0xD9C, 1076270), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0x3123, 1076270), 0, 0, 0); + } - int version = reader.ReadEncodedInt(); + public PeachTreeAddon(Serial serial) : base(serial) + { + } - m_Fruits = reader.ReadInt(); + public override BaseAddonDeed Deed => new PeachTreeDeed(); + public override Item Fruit => new Peach(); - if (m_Fruits == 0) - Respawn(); + 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(); + } } - } - public class AppleTreeAddon : BaseFruitTreeAddon - { - [Constructible] - public AppleTreeAddon() + public class PeachTreeDeed : BaseAddonDeed { - AddComponent(new LocalizedAddonComponent(0xD98, 1076269), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0x3124, 1076269), 0, 0, 0); + [Constructible] + public PeachTreeDeed() => LootType = LootType.Blessed; + + public PeachTreeDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new PeachTreeAddon(); + public override int LabelNumber => 1076270; // Peach Tree + + 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(); + } } - - public AppleTreeAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new AppleTreeDeed(); - public override Item Fruit => new Apple(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class AppleTreeDeed : BaseAddonDeed - { - [Constructible] - public AppleTreeDeed() => LootType = LootType.Blessed; - - public AppleTreeDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new AppleTreeAddon(); - public override int LabelNumber => 1076269; // Apple Tree - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class PeachTreeAddon : BaseFruitTreeAddon - { - [Constructible] - public PeachTreeAddon() - { - AddComponent(new LocalizedAddonComponent(0xD9C, 1076270), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0x3123, 1076270), 0, 0, 0); - } - - public PeachTreeAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new PeachTreeDeed(); - public override Item Fruit => new Peach(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class PeachTreeDeed : BaseAddonDeed - { - [Constructible] - public PeachTreeDeed() => LootType = LootType.Blessed; - - public PeachTreeDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new PeachTreeAddon(); - public override int LabelNumber => 1076270; // Peach Tree - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/Heritage Items/GoldenDecorativeRug.cs b/Projects/UOContent/Items/Special/Heritage Items/GoldenDecorativeRug.cs index fdeb571ec..835a49725 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/GoldenDecorativeRug.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/GoldenDecorativeRug.cs @@ -1,66 +1,66 @@ namespace Server.Items { - public class GoldenDecorativeRugAddon : BaseAddon - { - [Constructible] - public GoldenDecorativeRugAddon() + public class GoldenDecorativeRugAddon : BaseAddon { - AddComponent(new LocalizedAddonComponent(0xADB, 1076586), 1, 1, 0); - AddComponent(new LocalizedAddonComponent(0xADC, 1076586), -1, -1, 0); - AddComponent(new LocalizedAddonComponent(0xADD, 1076586), -1, 1, 0); - AddComponent(new LocalizedAddonComponent(0xADE, 1076586), 1, -1, 0); - AddComponent(new LocalizedAddonComponent(0xADF, 1076586), -1, 0, 0); - AddComponent(new LocalizedAddonComponent(0xAE0, 1076586), 0, -1, 0); - AddComponent(new LocalizedAddonComponent(0xAE1, 1076586), 1, 0, 0); - AddComponent(new LocalizedAddonComponent(0xAE2, 1076586), 0, 1, 0); - AddComponent(new LocalizedAddonComponent(0xADA, 1076586), 0, 0, 0); + [Constructible] + public GoldenDecorativeRugAddon() + { + AddComponent(new LocalizedAddonComponent(0xADB, 1076586), 1, 1, 0); + AddComponent(new LocalizedAddonComponent(0xADC, 1076586), -1, -1, 0); + AddComponent(new LocalizedAddonComponent(0xADD, 1076586), -1, 1, 0); + AddComponent(new LocalizedAddonComponent(0xADE, 1076586), 1, -1, 0); + AddComponent(new LocalizedAddonComponent(0xADF, 1076586), -1, 0, 0); + AddComponent(new LocalizedAddonComponent(0xAE0, 1076586), 0, -1, 0); + AddComponent(new LocalizedAddonComponent(0xAE1, 1076586), 1, 0, 0); + AddComponent(new LocalizedAddonComponent(0xAE2, 1076586), 0, 1, 0); + AddComponent(new LocalizedAddonComponent(0xADA, 1076586), 0, 0, 0); + } + + public GoldenDecorativeRugAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new GoldenDecorativeRugDeed(); + + 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(); + } } - public GoldenDecorativeRugAddon(Serial serial) : base(serial) + public class GoldenDecorativeRugDeed : BaseAddonDeed { + [Constructible] + public GoldenDecorativeRugDeed() => LootType = LootType.Blessed; + + public GoldenDecorativeRugDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new GoldenDecorativeRugAddon(); + public override int LabelNumber => 1076586; // Golden decorative rug + + 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(); + } } - - public override BaseAddonDeed Deed => new GoldenDecorativeRugDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class GoldenDecorativeRugDeed : BaseAddonDeed - { - [Constructible] - public GoldenDecorativeRugDeed() => LootType = LootType.Blessed; - - public GoldenDecorativeRugDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new GoldenDecorativeRugAddon(); - public override int LabelNumber => 1076586; // Golden decorative rug - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/Guillotine.cs b/Projects/UOContent/Items/Special/Heritage Items/Guillotine.cs index 1feb0022d..4eb9cdff4 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/Guillotine.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/Guillotine.cs @@ -4,161 +4,167 @@ using Server.Spells; namespace Server.Items { - [Flippable(0x125E, 0x1230)] - public class GuillotineComponent : AddonComponent - { - public GuillotineComponent() : base(0x125E) + [Flippable(0x125E, 0x1230)] + public class GuillotineComponent : AddonComponent { - } - - public GuillotineComponent(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1024656; // Guillotine - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class GuillotineAddon : BaseAddon - { - [Constructible] - public GuillotineAddon() - { - AddComponent(new GuillotineComponent(), 0, 0, 0); - } - - public GuillotineAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new GuillotineDeed(); - - public override void OnComponentUsed(AddonComponent c, Mobile from) - { - if (from.InRange(Location, 2)) - { - if (Utility.RandomBool()) + public GuillotineComponent() : base(0x125E) { - from.Location = Location; - - Timer.DelayCall(TimeSpan.FromSeconds(0.5), Activate, c, from); - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0, - 501777); // Hmm... you suspect that if you used this again, it might hurt. - } - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - public virtual void Activate(AddonComponent c, Mobile from) - { - if (c.ItemID == 0x125E || c.ItemID == 0x1269 || c.ItemID == 0x1260) - c.ItemID = 0x1269; - else - c.ItemID = 0x1247; - - // blood - int amount = Utility.RandomMinMax(3, 7); - - for (int i = 0; i < amount; i++) - { - int x = c.X + Utility.RandomMinMax(-1, 1); - int y = c.Y + Utility.RandomMinMax(-1, 1); - int z = c.Z; - - if (!c.Map.CanFit(x, y, z, 1, false, false)) - { - z = c.Map.GetAverageZ(x, y); - - if (!c.Map.CanFit(x, y, z, 1, false, false)) - continue; } - Blood blood = new Blood(Utility.RandomMinMax(0x122C, 0x122F)); - blood.MoveToWorld(new Point3D(x, y, z), c.Map); - } + public GuillotineComponent(Serial serial) : base(serial) + { + } - if (from.Female) - from.PlaySound(Utility.RandomMinMax(0x150, 0x153)); - else - from.PlaySound(Utility.RandomMinMax(0x15A, 0x15D)); + public override int LabelNumber => 1024656; // Guillotine - from.LocalOverheadMessage(MessageType.Regular, 0, - 501777); // Hmm... you suspect that if you used this again, it might hurt. - SpellHelper.Damage(TimeSpan.Zero, from, Utility.Dice(2, 10, 5)); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - Timer.DelayCall(TimeSpan.FromSeconds(0.5), TimeSpan.FromSeconds(0.5), 2, Deactivate, c); + writer.WriteEncodedInt(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } } - private void Deactivate(AddonComponent c) + public class GuillotineAddon : BaseAddon { - if (c.ItemID == 0x1269) - c.ItemID = 0x1260; - else if (c.ItemID == 0x1260) - c.ItemID = 0x125E; - else if (c.ItemID == 0x1247) - c.ItemID = 0x1246; - else if (c.ItemID == 0x1246) - c.ItemID = 0x1230; + [Constructible] + public GuillotineAddon() + { + AddComponent(new GuillotineComponent(), 0, 0, 0); + } + + public GuillotineAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new GuillotineDeed(); + + public override void OnComponentUsed(AddonComponent c, Mobile from) + { + if (from.InRange(Location, 2)) + { + if (Utility.RandomBool()) + { + from.Location = Location; + + Timer.DelayCall(TimeSpan.FromSeconds(0.5), Activate, c, from); + } + else + { + from.LocalOverheadMessage( + MessageType.Regular, + 0, + 501777 + ); // Hmm... you suspect that if you used this again, it might hurt. + } + } + else + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + } + + 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(); + } + + public virtual void Activate(AddonComponent c, Mobile from) + { + if (c.ItemID == 0x125E || c.ItemID == 0x1269 || c.ItemID == 0x1260) + c.ItemID = 0x1269; + else + c.ItemID = 0x1247; + + // blood + var amount = Utility.RandomMinMax(3, 7); + + for (var i = 0; i < amount; i++) + { + var x = c.X + Utility.RandomMinMax(-1, 1); + var y = c.Y + Utility.RandomMinMax(-1, 1); + var z = c.Z; + + if (!c.Map.CanFit(x, y, z, 1, false, false)) + { + z = c.Map.GetAverageZ(x, y); + + if (!c.Map.CanFit(x, y, z, 1, false, false)) + continue; + } + + var blood = new Blood(Utility.RandomMinMax(0x122C, 0x122F)); + blood.MoveToWorld(new Point3D(x, y, z), c.Map); + } + + if (from.Female) + from.PlaySound(Utility.RandomMinMax(0x150, 0x153)); + else + from.PlaySound(Utility.RandomMinMax(0x15A, 0x15D)); + + from.LocalOverheadMessage( + MessageType.Regular, + 0, + 501777 + ); // Hmm... you suspect that if you used this again, it might hurt. + SpellHelper.Damage(TimeSpan.Zero, from, Utility.Dice(2, 10, 5)); + + Timer.DelayCall(TimeSpan.FromSeconds(0.5), TimeSpan.FromSeconds(0.5), 2, Deactivate, c); + } + + private void Deactivate(AddonComponent c) + { + if (c.ItemID == 0x1269) + c.ItemID = 0x1260; + else if (c.ItemID == 0x1260) + c.ItemID = 0x125E; + else if (c.ItemID == 0x1247) + c.ItemID = 0x1246; + else if (c.ItemID == 0x1246) + c.ItemID = 0x1230; + } } - } - public class GuillotineDeed : BaseAddonDeed - { - [Constructible] - public GuillotineDeed() => LootType = LootType.Blessed; - - public GuillotineDeed(Serial serial) : base(serial) + public class GuillotineDeed : BaseAddonDeed { + [Constructible] + public GuillotineDeed() => LootType = LootType.Blessed; + + public GuillotineDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new GuillotineAddon(); + public override int LabelNumber => 1024656; // Guillotine + + 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(); + } } - - public override BaseAddon Addon => new GuillotineAddon(); - public override int LabelNumber => 1024656; // Guillotine - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/Heritage Items/HangingAxes.cs b/Projects/UOContent/Items/Special/Heritage Items/HangingAxes.cs index 1c1820b6f..64e81aa22 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/HangingAxes.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/HangingAxes.cs @@ -3,125 +3,125 @@ using Server.Network; namespace Server.Items { - public class HangingAxesAddon : BaseAddon - { - [Constructible] - public HangingAxesAddon(bool east) + public class HangingAxesAddon : BaseAddon { - if (east) // east - { - AddComponent(new LocalizedAddonComponent(0x156A, 1076271), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0x156B, 1076271), 0, -1, 0); - } - else // south - { - AddComponent(new LocalizedAddonComponent(0x1568, 1076271), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0x1569, 1076271), 1, 0, 0); - } + [Constructible] + public HangingAxesAddon(bool east) + { + if (east) // east + { + AddComponent(new LocalizedAddonComponent(0x156A, 1076271), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0x156B, 1076271), 0, -1, 0); + } + else // south + { + AddComponent(new LocalizedAddonComponent(0x1568, 1076271), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0x1569, 1076271), 1, 0, 0); + } + } + + public HangingAxesAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new HangingAxesDeed(); + + 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(); + } } - public HangingAxesAddon(Serial serial) : base(serial) + public class HangingAxesDeed : BaseAddonDeed { + private bool m_East; + + [Constructible] + public HangingAxesDeed() => LootType = LootType.Blessed; + + public HangingAxesDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new HangingAxesAddon(m_East); + public override int LabelNumber => 1076271; // Hanging Axes + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new InternalGump(this)); + } + else + { + from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. + } + } + + private void SendTarget(Mobile m) + { + base.OnDoubleClick(m); + } + + 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(); + } + + private class InternalGump : Gump + { + private readonly HangingAxesDeed m_Deed; + + public InternalGump(HangingAxesDeed deed) : base(60, 36) + { + m_Deed = deed; + + AddPage(0); + + AddBackground(0, 0, 273, 324, 0x13BE); + AddImageTiled(10, 10, 253, 20, 0xA40); + AddImageTiled(10, 40, 253, 244, 0xA40); + AddImageTiled(10, 294, 253, 20, 0xA40); + AddAlphaRegion(10, 10, 253, 304); + AddButton(10, 294, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL + AddHtmlLocalized(14, 12, 273, 20, 1076745, 0x7FFF); // Please select your hanging axe position + + AddPage(1); + + AddButton(19, 49, 0x845, 0x846, 1); + AddHtmlLocalized(44, 47, 213, 20, 1075386, 0x7FFF); // South + AddButton(19, 73, 0x845, 0x846, 2); + AddHtmlLocalized(44, 71, 213, 20, 1075387, 0x7FFF); // East + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Deed?.Deleted != false || info.ButtonID == 0) + return; + + m_Deed.m_East = info.ButtonID != 1; + m_Deed.SendTarget(sender.Mobile); + } + } } - - public override BaseAddonDeed Deed => new HangingAxesDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class HangingAxesDeed : BaseAddonDeed - { - private bool m_East; - - [Constructible] - public HangingAxesDeed() => LootType = LootType.Blessed; - - public HangingAxesDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new HangingAxesAddon(m_East); - public override int LabelNumber => 1076271; // Hanging Axes - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new InternalGump(this)); - } - else - { - from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. - } - } - - private void SendTarget(Mobile m) - { - base.OnDoubleClick(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - private class InternalGump : Gump - { - private readonly HangingAxesDeed m_Deed; - - public InternalGump(HangingAxesDeed deed) : base(60, 36) - { - m_Deed = deed; - - AddPage(0); - - AddBackground(0, 0, 273, 324, 0x13BE); - AddImageTiled(10, 10, 253, 20, 0xA40); - AddImageTiled(10, 40, 253, 244, 0xA40); - AddImageTiled(10, 294, 253, 20, 0xA40); - AddAlphaRegion(10, 10, 253, 304); - AddButton(10, 294, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL - AddHtmlLocalized(14, 12, 273, 20, 1076745, 0x7FFF); // Please select your hanging axe position - - AddPage(1); - - AddButton(19, 49, 0x845, 0x846, 1); - AddHtmlLocalized(44, 47, 213, 20, 1075386, 0x7FFF); // South - AddButton(19, 73, 0x845, 0x846, 2); - AddHtmlLocalized(44, 71, 213, 20, 1075387, 0x7FFF); // East - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Deed?.Deleted != false || info.ButtonID == 0) - return; - - m_Deed.m_East = info.ButtonID != 1; - m_Deed.SendTarget(sender.Mobile); - } - } - } } diff --git a/Projects/UOContent/Items/Special/Heritage Items/HangingSwords.cs b/Projects/UOContent/Items/Special/Heritage Items/HangingSwords.cs index 26aff5311..145c982e7 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/HangingSwords.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/HangingSwords.cs @@ -3,125 +3,125 @@ using Server.Network; namespace Server.Items { - public class HangingSwordsAddon : BaseAddon - { - [Constructible] - public HangingSwordsAddon(bool east) + public class HangingSwordsAddon : BaseAddon { - if (east) // east - { - AddComponent(new LocalizedAddonComponent(0x1566, 1076272), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0x1567, 1076272), 0, -1, 0); - } - else // south - { - AddComponent(new LocalizedAddonComponent(0x1564, 1076272), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0x1565, 1076272), 1, 0, 0); - } + [Constructible] + public HangingSwordsAddon(bool east) + { + if (east) // east + { + AddComponent(new LocalizedAddonComponent(0x1566, 1076272), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0x1567, 1076272), 0, -1, 0); + } + else // south + { + AddComponent(new LocalizedAddonComponent(0x1564, 1076272), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0x1565, 1076272), 1, 0, 0); + } + } + + public HangingSwordsAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new HangingSwordsDeed(); + + 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(); + } } - public HangingSwordsAddon(Serial serial) : base(serial) + public class HangingSwordsDeed : BaseAddonDeed { + private bool m_East; + + [Constructible] + public HangingSwordsDeed() => LootType = LootType.Blessed; + + public HangingSwordsDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new HangingSwordsAddon(m_East); + public override int LabelNumber => 1076272; // Hanging Swords + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new InternalGump(this)); + } + else + { + from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. + } + } + + private void SendTarget(Mobile m) + { + base.OnDoubleClick(m); + } + + 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(); + } + + private class InternalGump : Gump + { + private readonly HangingSwordsDeed m_Deed; + + public InternalGump(HangingSwordsDeed deed) : base(60, 36) + { + m_Deed = deed; + + AddPage(0); + + AddBackground(0, 0, 273, 324, 0x13BE); + AddImageTiled(10, 10, 253, 20, 0xA40); + AddImageTiled(10, 40, 253, 244, 0xA40); + AddImageTiled(10, 294, 253, 20, 0xA40); + AddAlphaRegion(10, 10, 253, 304); + AddButton(10, 294, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL + AddHtmlLocalized(14, 12, 273, 20, 1076746, 0x7FFF); // Please select your hanging sword position + + AddPage(1); + + AddButton(19, 49, 0x845, 0x846, 1); + AddHtmlLocalized(44, 47, 213, 20, 1075386, 0x7FFF); // South + AddButton(19, 73, 0x845, 0x846, 2); + AddHtmlLocalized(44, 71, 213, 20, 1075387, 0x7FFF); // East + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Deed?.Deleted != false || info.ButtonID == 0) + return; + + m_Deed.m_East = info.ButtonID != 1; + m_Deed.SendTarget(sender.Mobile); + } + } } - - public override BaseAddonDeed Deed => new HangingSwordsDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class HangingSwordsDeed : BaseAddonDeed - { - private bool m_East; - - [Constructible] - public HangingSwordsDeed() => LootType = LootType.Blessed; - - public HangingSwordsDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new HangingSwordsAddon(m_East); - public override int LabelNumber => 1076272; // Hanging Swords - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new InternalGump(this)); - } - else - { - from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. - } - } - - private void SendTarget(Mobile m) - { - base.OnDoubleClick(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - private class InternalGump : Gump - { - private readonly HangingSwordsDeed m_Deed; - - public InternalGump(HangingSwordsDeed deed) : base(60, 36) - { - m_Deed = deed; - - AddPage(0); - - AddBackground(0, 0, 273, 324, 0x13BE); - AddImageTiled(10, 10, 253, 20, 0xA40); - AddImageTiled(10, 40, 253, 244, 0xA40); - AddImageTiled(10, 294, 253, 20, 0xA40); - AddAlphaRegion(10, 10, 253, 304); - AddButton(10, 294, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL - AddHtmlLocalized(14, 12, 273, 20, 1076746, 0x7FFF); // Please select your hanging sword position - - AddPage(1); - - AddButton(19, 49, 0x845, 0x846, 1); - AddHtmlLocalized(44, 47, 213, 20, 1075386, 0x7FFF); // South - AddButton(19, 73, 0x845, 0x846, 2); - AddHtmlLocalized(44, 71, 213, 20, 1075387, 0x7FFF); // East - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Deed?.Deleted != false || info.ButtonID == 0) - return; - - m_Deed.m_East = info.ButtonID != 1; - m_Deed.SendTarget(sender.Mobile); - } - } - } } diff --git a/Projects/UOContent/Items/Special/Heritage Items/HouseLadder.cs b/Projects/UOContent/Items/Special/Heritage Items/HouseLadder.cs index b99582e46..5d7684033 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/HouseLadder.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/HouseLadder.cs @@ -3,162 +3,169 @@ using Server.Network; namespace Server.Items { - public class HouseLadderAddon : BaseAddon - { - [Constructible] - public HouseLadderAddon(int type) + public class HouseLadderAddon : BaseAddon { - switch (type) - { - case 0: // castle south - AddComponent(new LocalizedAddonComponent(0x3DB2, 1076791), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0x3F28, 1076791), 0, 1, 28); - AddComponent(new LocalizedAddonComponent(0x3DB4, 1076791), 0, 2, 20); - break; - case 1: // castle east - AddComponent(new LocalizedAddonComponent(0x3DB3, 1076791), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0x3F28, 1076791), 1, 0, 28); - AddComponent(new LocalizedAddonComponent(0x3DB5, 1076791), 2, 0, 20); - break; - case 2: // castle north - AddComponent(new LocalizedAddonComponent(0x2FDF, 1076791), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0x3F28, 1076791), 0, -1, 28); - AddComponent(new LocalizedAddonComponent(0x3DB6, 1076791), 0, -2, 20); - break; - case 3: // castle west - AddComponent(new LocalizedAddonComponent(0x2FDE, 1076791), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0x3F28, 1076791), -1, 0, 28); - AddComponent(new LocalizedAddonComponent(0x3DB7, 1076791), -2, 0, 20); - break; - case 4: // south - AddComponent(new LocalizedAddonComponent(0x3DB2, 1076287), 0, 0, 0); - break; - case 5: // east - AddComponent(new LocalizedAddonComponent(0x3DB3, 1076287), 0, 0, 0); - break; - case 6: // north - AddComponent(new LocalizedAddonComponent(0x2FDF, 1076287), 0, 0, 0); - break; - case 7: // west - AddComponent(new LocalizedAddonComponent(0x2FDE, 1076287), 0, 0, 0); - break; - } + [Constructible] + public HouseLadderAddon(int type) + { + switch (type) + { + case 0: // castle south + AddComponent(new LocalizedAddonComponent(0x3DB2, 1076791), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0x3F28, 1076791), 0, 1, 28); + AddComponent(new LocalizedAddonComponent(0x3DB4, 1076791), 0, 2, 20); + break; + case 1: // castle east + AddComponent(new LocalizedAddonComponent(0x3DB3, 1076791), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0x3F28, 1076791), 1, 0, 28); + AddComponent(new LocalizedAddonComponent(0x3DB5, 1076791), 2, 0, 20); + break; + case 2: // castle north + AddComponent(new LocalizedAddonComponent(0x2FDF, 1076791), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0x3F28, 1076791), 0, -1, 28); + AddComponent(new LocalizedAddonComponent(0x3DB6, 1076791), 0, -2, 20); + break; + case 3: // castle west + AddComponent(new LocalizedAddonComponent(0x2FDE, 1076791), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0x3F28, 1076791), -1, 0, 28); + AddComponent(new LocalizedAddonComponent(0x3DB7, 1076791), -2, 0, 20); + break; + case 4: // south + AddComponent(new LocalizedAddonComponent(0x3DB2, 1076287), 0, 0, 0); + break; + case 5: // east + AddComponent(new LocalizedAddonComponent(0x3DB3, 1076287), 0, 0, 0); + break; + case 6: // north + AddComponent(new LocalizedAddonComponent(0x2FDF, 1076287), 0, 0, 0); + break; + case 7: // west + AddComponent(new LocalizedAddonComponent(0x2FDE, 1076287), 0, 0, 0); + break; + } + } + + public HouseLadderAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new HouseLadderDeed(); + + 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(); + } } - public HouseLadderAddon(Serial serial) : base(serial) + public class HouseLadderDeed : BaseAddonDeed { + private int m_Type; + + [Constructible] + public HouseLadderDeed() => LootType = LootType.Blessed; + + public HouseLadderDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new HouseLadderAddon(m_Type); + public override int LabelNumber => 1076287; // Ladder + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new InternalGump(this)); + } + else + { + from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. + } + } + + private void SendTarget(Mobile m) + { + base.OnDoubleClick(m); + } + + 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(); + } + + private class InternalGump : Gump + { + private readonly HouseLadderDeed m_Deed; + + public InternalGump(HouseLadderDeed deed) : base(60, 36) + { + m_Deed = deed; + + AddPage(0); + + AddBackground(0, 0, 273, 324, 0x13BE); + AddImageTiled(10, 10, 253, 20, 0xA40); + AddImageTiled(10, 40, 253, 244, 0xA40); + AddImageTiled(10, 294, 253, 20, 0xA40); + AddAlphaRegion(10, 10, 253, 304); + AddButton(10, 294, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL + AddHtmlLocalized( + 14, + 12, + 273, + 20, + 1076780, + 0x7FFF + ); // Please select your ladder position.
Use the ladders marked (castle)
for accessing the tops of keeps
and castles. + + AddPage(1); + + AddButton(19, 49, 0x845, 0x846, 1); + AddHtmlLocalized(44, 47, 213, 20, 1076794, 0x7FFF); // South (Castle) + AddButton(19, 73, 0x845, 0x846, 2); + AddHtmlLocalized(44, 71, 213, 20, 1076795, 0x7FFF); // East (Castle) + AddButton(19, 97, 0x845, 0x846, 3); + AddHtmlLocalized(44, 95, 213, 20, 1076792, 0x7FFF); // North (Castle) + AddButton(19, 121, 0x845, 0x846, 4); + AddHtmlLocalized(44, 119, 213, 20, 1076793, 0x7FFF); // West (Castle) + AddButton(19, 145, 0x845, 0x846, 5); + AddHtmlLocalized(44, 143, 213, 20, 1075386, 0x7FFF); // South + AddButton(19, 169, 0x845, 0x846, 6); + AddHtmlLocalized(44, 167, 213, 20, 1075387, 0x7FFF); // East + AddButton(19, 193, 0x845, 0x846, 7); + AddHtmlLocalized(44, 191, 213, 20, 1075389, 0x7FFF); // North + AddButton(19, 217, 0x845, 0x846, 8); + AddHtmlLocalized(44, 215, 213, 20, 1075390, 0x7FFF); // West + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Deed?.Deleted != false || info.ButtonID == 0 || info.ButtonID < 1 || info.ButtonID > 8) + return; + + m_Deed.m_Type = info.ButtonID - 1; + m_Deed.SendTarget(sender.Mobile); + } + } } - - public override BaseAddonDeed Deed => new HouseLadderDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class HouseLadderDeed : BaseAddonDeed - { - private int m_Type; - - [Constructible] - public HouseLadderDeed() => LootType = LootType.Blessed; - - public HouseLadderDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new HouseLadderAddon(m_Type); - public override int LabelNumber => 1076287; // Ladder - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new InternalGump(this)); - } - else - { - from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. - } - } - - private void SendTarget(Mobile m) - { - base.OnDoubleClick(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - private class InternalGump : Gump - { - private readonly HouseLadderDeed m_Deed; - - public InternalGump(HouseLadderDeed deed) : base(60, 36) - { - m_Deed = deed; - - AddPage(0); - - AddBackground(0, 0, 273, 324, 0x13BE); - AddImageTiled(10, 10, 253, 20, 0xA40); - AddImageTiled(10, 40, 253, 244, 0xA40); - AddImageTiled(10, 294, 253, 20, 0xA40); - AddAlphaRegion(10, 10, 253, 304); - AddButton(10, 294, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL - AddHtmlLocalized(14, 12, 273, 20, 1076780, 0x7FFF); // Please select your ladder position.
Use the ladders marked (castle)
for accessing the tops of keeps
and castles. - - AddPage(1); - - AddButton(19, 49, 0x845, 0x846, 1); - AddHtmlLocalized(44, 47, 213, 20, 1076794, 0x7FFF); // South (Castle) - AddButton(19, 73, 0x845, 0x846, 2); - AddHtmlLocalized(44, 71, 213, 20, 1076795, 0x7FFF); // East (Castle) - AddButton(19, 97, 0x845, 0x846, 3); - AddHtmlLocalized(44, 95, 213, 20, 1076792, 0x7FFF); // North (Castle) - AddButton(19, 121, 0x845, 0x846, 4); - AddHtmlLocalized(44, 119, 213, 20, 1076793, 0x7FFF); // West (Castle) - AddButton(19, 145, 0x845, 0x846, 5); - AddHtmlLocalized(44, 143, 213, 20, 1075386, 0x7FFF); // South - AddButton(19, 169, 0x845, 0x846, 6); - AddHtmlLocalized(44, 167, 213, 20, 1075387, 0x7FFF); // East - AddButton(19, 193, 0x845, 0x846, 7); - AddHtmlLocalized(44, 191, 213, 20, 1075389, 0x7FFF); // North - AddButton(19, 217, 0x845, 0x846, 8); - AddHtmlLocalized(44, 215, 213, 20, 1075390, 0x7FFF); // West - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Deed?.Deleted != false || info.ButtonID == 0 || info.ButtonID < 1 || info.ButtonID > 8) - return; - - m_Deed.m_Type = info.ButtonID - 1; - m_Deed.SendTarget(sender.Mobile); - } - } - } } diff --git a/Projects/UOContent/Items/Special/Heritage Items/IronMaiden.cs b/Projects/UOContent/Items/Special/Heritage Items/IronMaiden.cs index 11d5a619d..13b09def8 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/IronMaiden.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/IronMaiden.cs @@ -4,123 +4,129 @@ using Server.Spells; namespace Server.Items { - public class IronMaidenAddon : BaseAddon - { - public IronMaidenAddon() + public class IronMaidenAddon : BaseAddon { - AddComponent(new LocalizedAddonComponent(0x1249, 1076288), 0, 0, 0); - } - - public IronMaidenAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new IronMaidenDeed(); - - public override void OnComponentUsed(AddonComponent c, Mobile from) - { - if (from.InRange(GetWorldLocation(), 2) && from.InLOS(GetWorldLocation())) - { - if (Utility.RandomBool()) + public IronMaidenAddon() { - from.Location = Location; - c.ItemID = 0x124A; - - Timer.DelayCall(TimeSpan.FromSeconds(0.5), TimeSpan.FromSeconds(0.5), 3, Activate, c, from); - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0, - 501777); // Hmm... you suspect that if you used this again, it might hurt. - } - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - public virtual void Activate(AddonComponent c, Mobile from) - { - c.ItemID += 1; - - if (c.ItemID < 0x124D) - return; - - // blood - int amount = Utility.RandomMinMax(3, 7); - - for (int i = 0; i < amount; i++) - { - int x = c.X + Utility.RandomMinMax(-1, 1); - int y = c.Y + Utility.RandomMinMax(-1, 1); - int z = c.Z; - - if (!c.Map.CanFit(x, y, z, 1, false, false)) - { - z = c.Map.GetAverageZ(x, y); - - if (!c.Map.CanFit(x, y, z, 1, false, false)) - continue; + AddComponent(new LocalizedAddonComponent(0x1249, 1076288), 0, 0, 0); } - Blood blood = new Blood(Utility.RandomMinMax(0x122C, 0x122F)); - blood.MoveToWorld(new Point3D(x, y, z), c.Map); - } + public IronMaidenAddon(Serial serial) : base(serial) + { + } - from.PlaySound(from.Female ? Utility.RandomMinMax(0x150, 0x153) : Utility.RandomMinMax(0x15A, 0x15D)); + public override BaseAddonDeed Deed => new IronMaidenDeed(); - from.LocalOverheadMessage(MessageType.Regular, 0, - 501777); // Hmm... you suspect that if you used this again, it might hurt. - SpellHelper.Damage(TimeSpan.Zero, from, Utility.Dice(2, 10, 5)); + public override void OnComponentUsed(AddonComponent c, Mobile from) + { + if (from.InRange(GetWorldLocation(), 2) && from.InLOS(GetWorldLocation())) + { + if (Utility.RandomBool()) + { + from.Location = Location; + c.ItemID = 0x124A; - Timer.DelayCall(TimeSpan.FromSeconds(1), Deactivate, c); + Timer.DelayCall(TimeSpan.FromSeconds(0.5), TimeSpan.FromSeconds(0.5), 3, Activate, c, from); + } + else + { + from.LocalOverheadMessage( + MessageType.Regular, + 0, + 501777 + ); // Hmm... you suspect that if you used this again, it might hurt. + } + } + else + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + } + + 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(); + } + + public virtual void Activate(AddonComponent c, Mobile from) + { + c.ItemID += 1; + + if (c.ItemID < 0x124D) + return; + + // blood + var amount = Utility.RandomMinMax(3, 7); + + for (var i = 0; i < amount; i++) + { + var x = c.X + Utility.RandomMinMax(-1, 1); + var y = c.Y + Utility.RandomMinMax(-1, 1); + var z = c.Z; + + if (!c.Map.CanFit(x, y, z, 1, false, false)) + { + z = c.Map.GetAverageZ(x, y); + + if (!c.Map.CanFit(x, y, z, 1, false, false)) + continue; + } + + var blood = new Blood(Utility.RandomMinMax(0x122C, 0x122F)); + blood.MoveToWorld(new Point3D(x, y, z), c.Map); + } + + from.PlaySound(from.Female ? Utility.RandomMinMax(0x150, 0x153) : Utility.RandomMinMax(0x15A, 0x15D)); + + from.LocalOverheadMessage( + MessageType.Regular, + 0, + 501777 + ); // Hmm... you suspect that if you used this again, it might hurt. + SpellHelper.Damage(TimeSpan.Zero, from, Utility.Dice(2, 10, 5)); + + Timer.DelayCall(TimeSpan.FromSeconds(1), Deactivate, c); + } + + private void Deactivate(AddonComponent c) + { + c.ItemID = 0x1249; + } } - private void Deactivate(AddonComponent c) + public class IronMaidenDeed : BaseAddonDeed { - c.ItemID = 0x1249; + [Constructible] + public IronMaidenDeed() => LootType = LootType.Blessed; + + public IronMaidenDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new IronMaidenAddon(); + public override int LabelNumber => 1076288; // Iron Maiden + + 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(); + } } - } - - public class IronMaidenDeed : BaseAddonDeed - { - [Constructible] - public IronMaidenDeed() => LootType = LootType.Blessed; - - public IronMaidenDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new IronMaidenAddon(); - public override int LabelNumber => 1076288; // Iron Maiden - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/Heritage Items/LargeFishingNet.cs b/Projects/UOContent/Items/Special/Heritage Items/LargeFishingNet.cs index cc1c9c814..4cb969fe0 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/LargeFishingNet.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/LargeFishingNet.cs @@ -1,86 +1,86 @@ namespace Server.Items { - [Flippable(0x3D8E, 0x3D8F)] - public class LargeFishingNetComponent : AddonComponent - { - public LargeFishingNetComponent() : base(0x3D8E) + [Flippable(0x3D8E, 0x3D8F)] + public class LargeFishingNetComponent : AddonComponent { + public LargeFishingNetComponent() : base(0x3D8E) + { + } + + public LargeFishingNetComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1076285; // Large Fish Net + + 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(); + } } - public LargeFishingNetComponent(Serial serial) : base(serial) + public class LargeFishingNetAddon : BaseAddon { + [Constructible] + public LargeFishingNetAddon() + { + AddComponent(new LargeFishingNetComponent(), 0, 0, 0); + } + + public LargeFishingNetAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new LargeFishingNetDeed(); + + 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(); + } } - public override int LabelNumber => 1076285; // Large Fish Net - - public override void Serialize(IGenericWriter writer) + public class LargeFishingNetDeed : BaseAddonDeed { - base.Serialize(writer); + [Constructible] + public LargeFishingNetDeed() => LootType = LootType.Blessed; - writer.WriteEncodedInt(0); // version + public LargeFishingNetDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new LargeFishingNetAddon(); + public override int LabelNumber => 1076285; // Large Fish Net + + 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(); + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class LargeFishingNetAddon : BaseAddon - { - [Constructible] - public LargeFishingNetAddon() - { - AddComponent(new LargeFishingNetComponent(), 0, 0, 0); - } - - public LargeFishingNetAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new LargeFishingNetDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class LargeFishingNetDeed : BaseAddonDeed - { - [Constructible] - public LargeFishingNetDeed() => LootType = LootType.Blessed; - - public LargeFishingNetDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new LargeFishingNetAddon(); - public override int LabelNumber => 1076285; // Large Fish Net - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/PeachTrunk.cs b/Projects/UOContent/Items/Special/Heritage Items/PeachTrunk.cs index cbfd09639..8ca1414cc 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/PeachTrunk.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/PeachTrunk.cs @@ -1,58 +1,58 @@ namespace Server.Items { - public class PeachTrunkAddon : BaseAddon - { - [Constructible] - public PeachTrunkAddon() + public class PeachTrunkAddon : BaseAddon { - AddComponent(new LocalizedAddonComponent(0xD9C, 1076786), 0, 0, 0); + [Constructible] + public PeachTrunkAddon() + { + AddComponent(new LocalizedAddonComponent(0xD9C, 1076786), 0, 0, 0); + } + + public PeachTrunkAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new PeachTrunkDeed(); + + 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(); + } } - public PeachTrunkAddon(Serial serial) : base(serial) + public class PeachTrunkDeed : BaseAddonDeed { + [Constructible] + public PeachTrunkDeed() => LootType = LootType.Blessed; + + public PeachTrunkDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new PeachTrunkAddon(); + public override int LabelNumber => 1076786; // Peach Trunk + + 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(); + } } - - public override BaseAddonDeed Deed => new PeachTrunkDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class PeachTrunkDeed : BaseAddonDeed - { - [Constructible] - public PeachTrunkDeed() => LootType = LootType.Blessed; - - public PeachTrunkDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new PeachTrunkAddon(); - public override int LabelNumber => 1076786; // Peach Trunk - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/PinkFancyRug.cs b/Projects/UOContent/Items/Special/Heritage Items/PinkFancyRug.cs index 9f4a0930f..7fe2005d2 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/PinkFancyRug.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/PinkFancyRug.cs @@ -1,66 +1,66 @@ namespace Server.Items { - public class PinkFancyRugAddon : BaseAddon - { - [Constructible] - public PinkFancyRugAddon() + public class PinkFancyRugAddon : BaseAddon { - AddComponent(new LocalizedAddonComponent(0xAEE, 1076590), 1, 1, 0); - AddComponent(new LocalizedAddonComponent(0xAEF, 1076590), -1, -1, 0); - AddComponent(new LocalizedAddonComponent(0xAF0, 1076590), -1, 1, 0); - AddComponent(new LocalizedAddonComponent(0xAF1, 1076590), 1, -1, 0); - AddComponent(new LocalizedAddonComponent(0xAF2, 1076590), -1, 0, 0); - AddComponent(new LocalizedAddonComponent(0xAF3, 1076590), 0, -1, 0); - AddComponent(new LocalizedAddonComponent(0xAF4, 1076590), 1, 0, 0); - AddComponent(new LocalizedAddonComponent(0xAF5, 1076590), 0, 1, 0); - AddComponent(new LocalizedAddonComponent(0xAEC, 1076590), 0, 0, 0); + [Constructible] + public PinkFancyRugAddon() + { + AddComponent(new LocalizedAddonComponent(0xAEE, 1076590), 1, 1, 0); + AddComponent(new LocalizedAddonComponent(0xAEF, 1076590), -1, -1, 0); + AddComponent(new LocalizedAddonComponent(0xAF0, 1076590), -1, 1, 0); + AddComponent(new LocalizedAddonComponent(0xAF1, 1076590), 1, -1, 0); + AddComponent(new LocalizedAddonComponent(0xAF2, 1076590), -1, 0, 0); + AddComponent(new LocalizedAddonComponent(0xAF3, 1076590), 0, -1, 0); + AddComponent(new LocalizedAddonComponent(0xAF4, 1076590), 1, 0, 0); + AddComponent(new LocalizedAddonComponent(0xAF5, 1076590), 0, 1, 0); + AddComponent(new LocalizedAddonComponent(0xAEC, 1076590), 0, 0, 0); + } + + public PinkFancyRugAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new PinkFancyRugDeed(); + + 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(); + } } - public PinkFancyRugAddon(Serial serial) : base(serial) + public class PinkFancyRugDeed : BaseAddonDeed { + [Constructible] + public PinkFancyRugDeed() => LootType = LootType.Blessed; + + public PinkFancyRugDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new PinkFancyRugAddon(); + public override int LabelNumber => 1076590; // Pink fancy rug + + 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(); + } } - - public override BaseAddonDeed Deed => new PinkFancyRugDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class PinkFancyRugDeed : BaseAddonDeed - { - [Constructible] - public PinkFancyRugDeed() => LootType = LootType.Blessed; - - public PinkFancyRugDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new PinkFancyRugAddon(); - public override int LabelNumber => 1076590; // Pink fancy rug - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/RedPlainRug.cs b/Projects/UOContent/Items/Special/Heritage Items/RedPlainRug.cs index fb84993f9..50ea1fcc4 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/RedPlainRug.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/RedPlainRug.cs @@ -1,66 +1,66 @@ namespace Server.Items { - public class RedPlainRugAddon : BaseAddon - { - [Constructible] - public RedPlainRugAddon() + public class RedPlainRugAddon : BaseAddon { - AddComponent(new LocalizedAddonComponent(0xAC9, 1076588), 1, 1, 0); - AddComponent(new LocalizedAddonComponent(0xACA, 1076588), -1, -1, 0); - AddComponent(new LocalizedAddonComponent(0xACB, 1076588), -1, 1, 0); - AddComponent(new LocalizedAddonComponent(0xACC, 1076588), 1, -1, 0); - AddComponent(new LocalizedAddonComponent(0xACD, 1076588), -1, 0, 0); - AddComponent(new LocalizedAddonComponent(0xACE, 1076588), 0, -1, 0); - AddComponent(new LocalizedAddonComponent(0xACF, 1076588), 1, 0, 0); - AddComponent(new LocalizedAddonComponent(0xAD0, 1076588), 0, 1, 0); - AddComponent(new LocalizedAddonComponent(0xAC6, 1076588), 0, 0, 0); + [Constructible] + public RedPlainRugAddon() + { + AddComponent(new LocalizedAddonComponent(0xAC9, 1076588), 1, 1, 0); + AddComponent(new LocalizedAddonComponent(0xACA, 1076588), -1, -1, 0); + AddComponent(new LocalizedAddonComponent(0xACB, 1076588), -1, 1, 0); + AddComponent(new LocalizedAddonComponent(0xACC, 1076588), 1, -1, 0); + AddComponent(new LocalizedAddonComponent(0xACD, 1076588), -1, 0, 0); + AddComponent(new LocalizedAddonComponent(0xACE, 1076588), 0, -1, 0); + AddComponent(new LocalizedAddonComponent(0xACF, 1076588), 1, 0, 0); + AddComponent(new LocalizedAddonComponent(0xAD0, 1076588), 0, 1, 0); + AddComponent(new LocalizedAddonComponent(0xAC6, 1076588), 0, 0, 0); + } + + public RedPlainRugAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new RedPlainRugDeed(); + + 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(); + } } - public RedPlainRugAddon(Serial serial) : base(serial) + public class RedPlainRugDeed : BaseAddonDeed { + [Constructible] + public RedPlainRugDeed() => LootType = LootType.Blessed; + + public RedPlainRugDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new RedPlainRugAddon(); + public override int LabelNumber => 1076588; // Red plain rug + + 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(); + } } - - public override BaseAddonDeed Deed => new RedPlainRugDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class RedPlainRugDeed : BaseAddonDeed - { - [Constructible] - public RedPlainRugDeed() => LootType = LootType.Blessed; - - public RedPlainRugDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new RedPlainRugAddon(); - public override int LabelNumber => 1076588; // Red plain rug - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/Scarecrow.cs b/Projects/UOContent/Items/Special/Heritage Items/Scarecrow.cs index 1a3ed9a3f..6f5d6da4b 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/Scarecrow.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/Scarecrow.cs @@ -1,86 +1,86 @@ namespace Server.Items { - [Flippable(0x1E34, 0x1E35)] - public class ScarecrowComponent : AddonComponent - { - public ScarecrowComponent() : base(0x1E34) + [Flippable(0x1E34, 0x1E35)] + public class ScarecrowComponent : AddonComponent { + public ScarecrowComponent() : base(0x1E34) + { + } + + public ScarecrowComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1076608; // Scarecrow + + 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(); + } } - public ScarecrowComponent(Serial serial) : base(serial) + public class ScarecrowAddon : BaseAddon { + [Constructible] + public ScarecrowAddon() + { + AddComponent(new ScarecrowComponent(), 0, 0, 0); + } + + public ScarecrowAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new ScarecrowDeed(); + + 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(); + } } - public override int LabelNumber => 1076608; // Scarecrow - - public override void Serialize(IGenericWriter writer) + public class ScarecrowDeed : BaseAddonDeed { - base.Serialize(writer); + [Constructible] + public ScarecrowDeed() => LootType = LootType.Blessed; - writer.WriteEncodedInt(0); // version + public ScarecrowDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new ScarecrowAddon(); + public override int LabelNumber => 1076608; // Scarecrow + + 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(); + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ScarecrowAddon : BaseAddon - { - [Constructible] - public ScarecrowAddon() - { - AddComponent(new ScarecrowComponent(), 0, 0, 0); - } - - public ScarecrowAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new ScarecrowDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ScarecrowDeed : BaseAddonDeed - { - [Constructible] - public ScarecrowDeed() => LootType = LootType.Blessed; - - public ScarecrowDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new ScarecrowAddon(); - public override int LabelNumber => 1076608; // Scarecrow - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/SmallFishingNet.cs b/Projects/UOContent/Items/Special/Heritage Items/SmallFishingNet.cs index 9a7a2d639..b21949cb3 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/SmallFishingNet.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/SmallFishingNet.cs @@ -1,86 +1,86 @@ namespace Server.Items { - [Flippable(0x1EA3, 0x1EA4)] - public class SmallFishingNetComponent : AddonComponent - { - public SmallFishingNetComponent() : base(0x1EA3) + [Flippable(0x1EA3, 0x1EA4)] + public class SmallFishingNetComponent : AddonComponent { + public SmallFishingNetComponent() : base(0x1EA3) + { + } + + public SmallFishingNetComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1076286; // Small Fish Net + + 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(); + } } - public SmallFishingNetComponent(Serial serial) : base(serial) + public class SmallFishingNetAddon : BaseAddon { + [Constructible] + public SmallFishingNetAddon() + { + AddComponent(new SmallFishingNetComponent(), 0, 0, 0); + } + + public SmallFishingNetAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new SmallFishingNetDeed(); + + 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(); + } } - public override int LabelNumber => 1076286; // Small Fish Net - - public override void Serialize(IGenericWriter writer) + public class SmallFishingNetDeed : BaseAddonDeed { - base.Serialize(writer); + [Constructible] + public SmallFishingNetDeed() => LootType = LootType.Blessed; - writer.WriteEncodedInt(0); // version + public SmallFishingNetDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new SmallFishingNetAddon(); + public override int LabelNumber => 1076286; // Small Fish Net + + 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(); + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SmallFishingNetAddon : BaseAddon - { - [Constructible] - public SmallFishingNetAddon() - { - AddComponent(new SmallFishingNetComponent(), 0, 0, 0); - } - - public SmallFishingNetAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new SmallFishingNetDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SmallFishingNetDeed : BaseAddonDeed - { - [Constructible] - public SmallFishingNetDeed() => LootType = LootType.Blessed; - - public SmallFishingNetDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new SmallFishingNetAddon(); - public override int LabelNumber => 1076286; // Small Fish Net - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/Statue.cs b/Projects/UOContent/Items/Special/Heritage Items/Statue.cs index 86bcdf60c..5569fd7a6 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/Statue.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/Statue.cs @@ -3,127 +3,127 @@ using Server.Network; namespace Server.Items { - public class StoneStatueAddon : BaseAddon - { - [Constructible] - public StoneStatueAddon(bool east) + public class StoneStatueAddon : BaseAddon { - if (east) // east - { - AddComponent(new LocalizedAddonComponent(0x139E, 1076284), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0x139F, 1076284), -1, 0, 0); - AddComponent(new LocalizedAddonComponent(0x13A0, 1076284), 0, -1, 0); - } - else // south - { - AddComponent(new LocalizedAddonComponent(0x129F, 1076284), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0x12A0, 1076284), 0, -1, 0); - AddComponent(new LocalizedAddonComponent(0x12A1, 1076284), -1, 0, 0); - } + [Constructible] + public StoneStatueAddon(bool east) + { + if (east) // east + { + AddComponent(new LocalizedAddonComponent(0x139E, 1076284), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0x139F, 1076284), -1, 0, 0); + AddComponent(new LocalizedAddonComponent(0x13A0, 1076284), 0, -1, 0); + } + else // south + { + AddComponent(new LocalizedAddonComponent(0x129F, 1076284), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0x12A0, 1076284), 0, -1, 0); + AddComponent(new LocalizedAddonComponent(0x12A1, 1076284), -1, 0, 0); + } + } + + public StoneStatueAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new StoneStatueDeed(); + + 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(); + } } - public StoneStatueAddon(Serial serial) : base(serial) + public class StoneStatueDeed : BaseAddonDeed { + private bool m_East; + + [Constructible] + public StoneStatueDeed() => LootType = LootType.Blessed; + + public StoneStatueDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new StoneStatueAddon(m_East); + public override int LabelNumber => 1076284; // Statue + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new InternalGump(this)); + } + else + { + from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. + } + } + + private void SendTarget(Mobile m) + { + base.OnDoubleClick(m); + } + + 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(); + } + + private class InternalGump : Gump + { + private readonly StoneStatueDeed m_Deed; + + public InternalGump(StoneStatueDeed deed) : base(60, 36) + { + m_Deed = deed; + + AddPage(0); + + AddBackground(0, 0, 273, 324, 0x13BE); + AddImageTiled(10, 10, 253, 20, 0xA40); + AddImageTiled(10, 40, 253, 244, 0xA40); + AddImageTiled(10, 294, 253, 20, 0xA40); + AddAlphaRegion(10, 10, 253, 304); + AddButton(10, 294, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL + AddHtmlLocalized(14, 12, 273, 20, 1076579, 0x7FFF); // Please select your statue position + + AddPage(1); + + AddButton(19, 49, 0x845, 0x846, 1); + AddHtmlLocalized(44, 47, 213, 20, 1075386, 0x7FFF); // South + AddButton(19, 73, 0x845, 0x846, 2); + AddHtmlLocalized(44, 71, 213, 20, 1075387, 0x7FFF); // East + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Deed?.Deleted != false || info.ButtonID == 0) + return; + + m_Deed.m_East = info.ButtonID != 1; + m_Deed.SendTarget(sender.Mobile); + } + } } - - public override BaseAddonDeed Deed => new StoneStatueDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class StoneStatueDeed : BaseAddonDeed - { - private bool m_East; - - [Constructible] - public StoneStatueDeed() => LootType = LootType.Blessed; - - public StoneStatueDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new StoneStatueAddon(m_East); - public override int LabelNumber => 1076284; // Statue - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new InternalGump(this)); - } - else - { - from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. - } - } - - private void SendTarget(Mobile m) - { - base.OnDoubleClick(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - private class InternalGump : Gump - { - private readonly StoneStatueDeed m_Deed; - - public InternalGump(StoneStatueDeed deed) : base(60, 36) - { - m_Deed = deed; - - AddPage(0); - - AddBackground(0, 0, 273, 324, 0x13BE); - AddImageTiled(10, 10, 253, 20, 0xA40); - AddImageTiled(10, 40, 253, 244, 0xA40); - AddImageTiled(10, 294, 253, 20, 0xA40); - AddAlphaRegion(10, 10, 253, 304); - AddButton(10, 294, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL - AddHtmlLocalized(14, 12, 273, 20, 1076579, 0x7FFF); // Please select your statue position - - AddPage(1); - - AddButton(19, 49, 0x845, 0x846, 1); - AddHtmlLocalized(44, 47, 213, 20, 1075386, 0x7FFF); // South - AddButton(19, 73, 0x845, 0x846, 2); - AddHtmlLocalized(44, 71, 213, 20, 1075387, 0x7FFF); // East - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Deed?.Deleted != false || info.ButtonID == 0) - return; - - m_Deed.m_East = info.ButtonID != 1; - m_Deed.SendTarget(sender.Mobile); - } - } - } } diff --git a/Projects/UOContent/Items/Special/Heritage Items/SuitOfGoldArmor.cs b/Projects/UOContent/Items/Special/Heritage Items/SuitOfGoldArmor.cs index 404479c52..73ec1eab5 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/SuitOfGoldArmor.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/SuitOfGoldArmor.cs @@ -1,86 +1,86 @@ namespace Server.Items { - [Flippable(0x3DAA, 0x3DA9)] - public class SuitOfGoldArmorComponent : AddonComponent - { - public SuitOfGoldArmorComponent() : base(0x3DAA) + [Flippable(0x3DAA, 0x3DA9)] + public class SuitOfGoldArmorComponent : AddonComponent { + public SuitOfGoldArmorComponent() : base(0x3DAA) + { + } + + public SuitOfGoldArmorComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1076265; // Suit of Gold Armor + + 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(); + } } - public SuitOfGoldArmorComponent(Serial serial) : base(serial) + public class SuitOfGoldArmorAddon : BaseAddon { + [Constructible] + public SuitOfGoldArmorAddon() + { + AddComponent(new SuitOfGoldArmorComponent(), 0, 0, 0); + } + + public SuitOfGoldArmorAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new SuitOfGoldArmorDeed(); + + 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(); + } } - public override int LabelNumber => 1076265; // Suit of Gold Armor - - public override void Serialize(IGenericWriter writer) + public class SuitOfGoldArmorDeed : BaseAddonDeed { - base.Serialize(writer); + [Constructible] + public SuitOfGoldArmorDeed() => LootType = LootType.Blessed; - writer.WriteEncodedInt(0); // version + public SuitOfGoldArmorDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new SuitOfGoldArmorAddon(); + public override int LabelNumber => 1076265; // Suit of Gold Armor + + 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(); + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SuitOfGoldArmorAddon : BaseAddon - { - [Constructible] - public SuitOfGoldArmorAddon() - { - AddComponent(new SuitOfGoldArmorComponent(), 0, 0, 0); - } - - public SuitOfGoldArmorAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new SuitOfGoldArmorDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SuitOfGoldArmorDeed : BaseAddonDeed - { - [Constructible] - public SuitOfGoldArmorDeed() => LootType = LootType.Blessed; - - public SuitOfGoldArmorDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new SuitOfGoldArmorAddon(); - public override int LabelNumber => 1076265; // Suit of Gold Armor - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/SuitOfSilverArmor.cs b/Projects/UOContent/Items/Special/Heritage Items/SuitOfSilverArmor.cs index 4964c86d3..a67f5a986 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/SuitOfSilverArmor.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/SuitOfSilverArmor.cs @@ -1,86 +1,86 @@ namespace Server.Items { - [Flippable(0x3D86, 0x3D87)] - public class SuitOfSilverArmorComponent : AddonComponent - { - public SuitOfSilverArmorComponent() : base(0x3D86) + [Flippable(0x3D86, 0x3D87)] + public class SuitOfSilverArmorComponent : AddonComponent { + public SuitOfSilverArmorComponent() : base(0x3D86) + { + } + + public SuitOfSilverArmorComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1076266; // Suit of Silver Armor + + 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(); + } } - public SuitOfSilverArmorComponent(Serial serial) : base(serial) + public class SuitOfSilverArmorAddon : BaseAddon { + [Constructible] + public SuitOfSilverArmorAddon() + { + AddComponent(new SuitOfSilverArmorComponent(), 0, 0, 0); + } + + public SuitOfSilverArmorAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new SuitOfSilverArmorDeed(); + + 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(); + } } - public override int LabelNumber => 1076266; // Suit of Silver Armor - - public override void Serialize(IGenericWriter writer) + public class SuitOfSilverArmorDeed : BaseAddonDeed { - base.Serialize(writer); + [Constructible] + public SuitOfSilverArmorDeed() => LootType = LootType.Blessed; - writer.WriteEncodedInt(0); // version + public SuitOfSilverArmorDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new SuitOfSilverArmorAddon(); + public override int LabelNumber => 1076266; // Suit of Silver Armor + + 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(); + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SuitOfSilverArmorAddon : BaseAddon - { - [Constructible] - public SuitOfSilverArmorAddon() - { - AddComponent(new SuitOfSilverArmorComponent(), 0, 0, 0); - } - - public SuitOfSilverArmorAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new SuitOfSilverArmorDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SuitOfSilverArmorDeed : BaseAddonDeed - { - [Constructible] - public SuitOfSilverArmorDeed() => LootType = LootType.Blessed; - - public SuitOfSilverArmorDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new SuitOfSilverArmorAddon(); - public override int LabelNumber => 1076266; // Suit of Silver Armor - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/TableWithBlueCloth.cs b/Projects/UOContent/Items/Special/Heritage Items/TableWithBlueCloth.cs index 111b2b8c1..b13a299c3 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/TableWithBlueCloth.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/TableWithBlueCloth.cs @@ -1,58 +1,58 @@ namespace Server.Items { - public class TableWithBlueClothAddon : BaseAddon - { - [Constructible] - public TableWithBlueClothAddon() + public class TableWithBlueClothAddon : BaseAddon { - AddComponent(new LocalizedAddonComponent(0x118C, 1076276), 0, 0, 0); + [Constructible] + public TableWithBlueClothAddon() + { + AddComponent(new LocalizedAddonComponent(0x118C, 1076276), 0, 0, 0); + } + + public TableWithBlueClothAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new TableWithBlueClothDeed(); + + 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(); + } } - public TableWithBlueClothAddon(Serial serial) : base(serial) + public class TableWithBlueClothDeed : BaseAddonDeed { + [Constructible] + public TableWithBlueClothDeed() => LootType = LootType.Blessed; + + public TableWithBlueClothDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new TableWithBlueClothAddon(); + public override int LabelNumber => 1076276; // Table With A Blue Tablecloth + + 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(); + } } - - public override BaseAddonDeed Deed => new TableWithBlueClothDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TableWithBlueClothDeed : BaseAddonDeed - { - [Constructible] - public TableWithBlueClothDeed() => LootType = LootType.Blessed; - - public TableWithBlueClothDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new TableWithBlueClothAddon(); - public override int LabelNumber => 1076276; // Table With A Blue Tablecloth - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/TableWithOrangeCloth.cs b/Projects/UOContent/Items/Special/Heritage Items/TableWithOrangeCloth.cs index 69b4e906d..a3c9d028d 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/TableWithOrangeCloth.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/TableWithOrangeCloth.cs @@ -1,58 +1,58 @@ namespace Server.Items { - public class TableWithOrangeClothAddon : BaseAddon - { - [Constructible] - public TableWithOrangeClothAddon() + public class TableWithOrangeClothAddon : BaseAddon { - AddComponent(new LocalizedAddonComponent(0x118E, 1076278), 0, 0, 0); + [Constructible] + public TableWithOrangeClothAddon() + { + AddComponent(new LocalizedAddonComponent(0x118E, 1076278), 0, 0, 0); + } + + public TableWithOrangeClothAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new TableWithOrangeClothDeed(); + + 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(); + } } - public TableWithOrangeClothAddon(Serial serial) : base(serial) + public class TableWithOrangeClothDeed : BaseAddonDeed { + [Constructible] + public TableWithOrangeClothDeed() => LootType = LootType.Blessed; + + public TableWithOrangeClothDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new TableWithOrangeClothAddon(); + public override int LabelNumber => 1076278; // Table With An Orange Tablecloth + + 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(); + } } - - public override BaseAddonDeed Deed => new TableWithOrangeClothDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TableWithOrangeClothDeed : BaseAddonDeed - { - [Constructible] - public TableWithOrangeClothDeed() => LootType = LootType.Blessed; - - public TableWithOrangeClothDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new TableWithOrangeClothAddon(); - public override int LabelNumber => 1076278; // Table With An Orange Tablecloth - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/TableWithPurpleCloth.cs b/Projects/UOContent/Items/Special/Heritage Items/TableWithPurpleCloth.cs index 684bd9ccc..e6b128c34 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/TableWithPurpleCloth.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/TableWithPurpleCloth.cs @@ -1,58 +1,58 @@ namespace Server.Items { - public class TableWithPurpleClothAddon : BaseAddon - { - [Constructible] - public TableWithPurpleClothAddon() + public class TableWithPurpleClothAddon : BaseAddon { - AddComponent(new LocalizedAddonComponent(0x118B, 1076275), 0, 0, 0); + [Constructible] + public TableWithPurpleClothAddon() + { + AddComponent(new LocalizedAddonComponent(0x118B, 1076275), 0, 0, 0); + } + + public TableWithPurpleClothAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new TableWithPurpleClothDeed(); + + 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(); + } } - public TableWithPurpleClothAddon(Serial serial) : base(serial) + public class TableWithPurpleClothDeed : BaseAddonDeed { + [Constructible] + public TableWithPurpleClothDeed() => LootType = LootType.Blessed; + + public TableWithPurpleClothDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new TableWithPurpleClothAddon(); + public override int LabelNumber => 1076275; // Table With A Purple Tablecloth + + 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(); + } } - - public override BaseAddonDeed Deed => new TableWithPurpleClothDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TableWithPurpleClothDeed : BaseAddonDeed - { - [Constructible] - public TableWithPurpleClothDeed() => LootType = LootType.Blessed; - - public TableWithPurpleClothDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new TableWithPurpleClothAddon(); - public override int LabelNumber => 1076275; // Table With A Purple Tablecloth - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/TableWithRedCloth.cs b/Projects/UOContent/Items/Special/Heritage Items/TableWithRedCloth.cs index 0c49060b3..db997efea 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/TableWithRedCloth.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/TableWithRedCloth.cs @@ -1,58 +1,58 @@ namespace Server.Items { - public class TableWithRedClothAddon : BaseAddon - { - [Constructible] - public TableWithRedClothAddon() + public class TableWithRedClothAddon : BaseAddon { - AddComponent(new LocalizedAddonComponent(0x118D, 1076277), 0, 0, 0); + [Constructible] + public TableWithRedClothAddon() + { + AddComponent(new LocalizedAddonComponent(0x118D, 1076277), 0, 0, 0); + } + + public TableWithRedClothAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new TableWithRedClothDeed(); + + 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(); + } } - public TableWithRedClothAddon(Serial serial) : base(serial) + public class TableWithRedClothDeed : BaseAddonDeed { + [Constructible] + public TableWithRedClothDeed() => LootType = LootType.Blessed; + + public TableWithRedClothDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new TableWithRedClothAddon(); + public override int LabelNumber => 1076277; // Table With A Red Tablecloth + + 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(); + } } - - public override BaseAddonDeed Deed => new TableWithRedClothDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class TableWithRedClothDeed : BaseAddonDeed - { - [Constructible] - public TableWithRedClothDeed() => LootType = LootType.Blessed; - - public TableWithRedClothDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new TableWithRedClothAddon(); - public override int LabelNumber => 1076277; // Table With A Red Tablecloth - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/UnmadeBed.cs b/Projects/UOContent/Items/Special/Heritage Items/UnmadeBed.cs index 62fbcceae..96848bba9 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/UnmadeBed.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/UnmadeBed.cs @@ -3,129 +3,129 @@ using Server.Network; namespace Server.Items { - public class UnmadeBedAddon : BaseAddon - { - [Constructible] - public UnmadeBedAddon(bool east) + public class UnmadeBedAddon : BaseAddon { - if (east) // east - { - AddComponent(new LocalizedAddonComponent(0xA8C, 1076279), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0xA8D, 1076279), 0, -1, 0); - AddComponent(new LocalizedAddonComponent(0xA90, 1076279), -1, 0, 0); - AddComponent(new LocalizedAddonComponent(0xA91, 1076279), -1, -1, 0); - } - else // south - { - AddComponent(new LocalizedAddonComponent(0xDB0, 1076279), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0xDB1, 1076279), -1, 0, 0); - AddComponent(new LocalizedAddonComponent(0xDB4, 1076279), 0, -1, 0); - AddComponent(new LocalizedAddonComponent(0xDB5, 1076279), -1, -1, 0); - } + [Constructible] + public UnmadeBedAddon(bool east) + { + if (east) // east + { + AddComponent(new LocalizedAddonComponent(0xA8C, 1076279), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0xA8D, 1076279), 0, -1, 0); + AddComponent(new LocalizedAddonComponent(0xA90, 1076279), -1, 0, 0); + AddComponent(new LocalizedAddonComponent(0xA91, 1076279), -1, -1, 0); + } + else // south + { + AddComponent(new LocalizedAddonComponent(0xDB0, 1076279), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0xDB1, 1076279), -1, 0, 0); + AddComponent(new LocalizedAddonComponent(0xDB4, 1076279), 0, -1, 0); + AddComponent(new LocalizedAddonComponent(0xDB5, 1076279), -1, -1, 0); + } + } + + public UnmadeBedAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new UnmadeBedDeed(); + + 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(); + } } - public UnmadeBedAddon(Serial serial) : base(serial) + public class UnmadeBedDeed : BaseAddonDeed { + private bool m_East; + + [Constructible] + public UnmadeBedDeed() => LootType = LootType.Blessed; + + public UnmadeBedDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new UnmadeBedAddon(m_East); + public override int LabelNumber => 1076279; // Unmade Bed + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new InternalGump(this)); + } + else + { + from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. + } + } + + private void SendTarget(Mobile m) + { + base.OnDoubleClick(m); + } + + 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(); + } + + private class InternalGump : Gump + { + private readonly UnmadeBedDeed m_Deed; + + public InternalGump(UnmadeBedDeed deed) : base(60, 36) + { + m_Deed = deed; + + AddPage(0); + + AddBackground(0, 0, 273, 324, 0x13BE); + AddImageTiled(10, 10, 253, 20, 0xA40); + AddImageTiled(10, 40, 253, 244, 0xA40); + AddImageTiled(10, 294, 253, 20, 0xA40); + AddAlphaRegion(10, 10, 253, 304); + AddButton(10, 294, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL + AddHtmlLocalized(14, 12, 273, 20, 1076580, 0x7FFF); // Pleae select your unmade bed position + + AddPage(1); + + AddButton(19, 49, 0x845, 0x846, 1); + AddHtmlLocalized(44, 47, 213, 20, 1075386, 0x7FFF); // South + AddButton(19, 73, 0x845, 0x846, 2); + AddHtmlLocalized(44, 71, 213, 20, 1075387, 0x7FFF); // East + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Deed?.Deleted != false || info.ButtonID == 0) + return; + + m_Deed.m_East = info.ButtonID != 1; + m_Deed.SendTarget(sender.Mobile); + } + } } - - public override BaseAddonDeed Deed => new UnmadeBedDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class UnmadeBedDeed : BaseAddonDeed - { - private bool m_East; - - [Constructible] - public UnmadeBedDeed() => LootType = LootType.Blessed; - - public UnmadeBedDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new UnmadeBedAddon(m_East); - public override int LabelNumber => 1076279; // Unmade Bed - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new InternalGump(this)); - } - else - { - from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. - } - } - - private void SendTarget(Mobile m) - { - base.OnDoubleClick(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - private class InternalGump : Gump - { - private readonly UnmadeBedDeed m_Deed; - - public InternalGump(UnmadeBedDeed deed) : base(60, 36) - { - m_Deed = deed; - - AddPage(0); - - AddBackground(0, 0, 273, 324, 0x13BE); - AddImageTiled(10, 10, 253, 20, 0xA40); - AddImageTiled(10, 40, 253, 244, 0xA40); - AddImageTiled(10, 294, 253, 20, 0xA40); - AddAlphaRegion(10, 10, 253, 304); - AddButton(10, 294, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL - AddHtmlLocalized(14, 12, 273, 20, 1076580, 0x7FFF); // Pleae select your unmade bed position - - AddPage(1); - - AddButton(19, 49, 0x845, 0x846, 1); - AddHtmlLocalized(44, 47, 213, 20, 1075386, 0x7FFF); // South - AddButton(19, 73, 0x845, 0x846, 2); - AddHtmlLocalized(44, 71, 213, 20, 1075387, 0x7FFF); // East - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Deed?.Deleted != false || info.ButtonID == 0) - return; - - m_Deed.m_East = info.ButtonID != 1; - m_Deed.SendTarget(sender.Mobile); - } - } - } } diff --git a/Projects/UOContent/Items/Special/Heritage Items/Vanity.cs b/Projects/UOContent/Items/Special/Heritage Items/Vanity.cs index 377104399..f0c52da9b 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/Vanity.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/Vanity.cs @@ -3,122 +3,122 @@ using Server.Network; namespace Server.Items { - public class VanityAddon : BaseAddonContainer - { - [Constructible] - public VanityAddon(bool east) : base(east ? 0xA44 : 0xA3C) + public class VanityAddon : BaseAddonContainer { - if (east) // east - AddComponent(new AddonContainerComponent(0xA45), 0, -1, 0); - else // south - AddComponent(new AddonContainerComponent(0xA3D), -1, 0, 0); + [Constructible] + public VanityAddon(bool east) : base(east ? 0xA44 : 0xA3C) + { + if (east) // east + AddComponent(new AddonContainerComponent(0xA45), 0, -1, 0); + else // south + AddComponent(new AddonContainerComponent(0xA3D), -1, 0, 0); + } + + public VanityAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonContainerDeed Deed => new VanityDeed(); + public override int LabelNumber => 1074027; // Vanity + public override int DefaultGumpID => 0x51; + public override int DefaultDropSound => 0x42; + + 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(); + } } - public VanityAddon(Serial serial) : base(serial) + public class VanityDeed : BaseAddonContainerDeed { + private bool m_East; + + [Constructible] + public VanityDeed() => LootType = LootType.Blessed; + + public VanityDeed(Serial serial) : base(serial) + { + } + + public override BaseAddonContainer Addon => new VanityAddon(m_East); + public override int LabelNumber => 1074027; // Vanity + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new InternalGump(this)); + } + else + { + from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. + } + } + + private void SendTarget(Mobile m) + { + base.OnDoubleClick(m); + } + + 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(); + } + + private class InternalGump : Gump + { + private readonly VanityDeed m_Deed; + + public InternalGump(VanityDeed deed) : base(60, 36) + { + m_Deed = deed; + + AddPage(0); + + AddBackground(0, 0, 273, 324, 0x13BE); + AddImageTiled(10, 10, 253, 20, 0xA40); + AddImageTiled(10, 40, 253, 244, 0xA40); + AddImageTiled(10, 294, 253, 20, 0xA40); + AddAlphaRegion(10, 10, 253, 304); + AddButton(10, 294, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL + AddHtmlLocalized(14, 12, 273, 20, 1076744, 0x7FFF); // Please select your vanity position. + + AddPage(1); + + AddButton(19, 49, 0x845, 0x846, 1); + AddHtmlLocalized(44, 47, 213, 20, 1075386, 0x7FFF); // South + AddButton(19, 73, 0x845, 0x846, 2); + AddHtmlLocalized(44, 71, 213, 20, 1075387, 0x7FFF); // East + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Deed?.Deleted != false || info.ButtonID == 0) + return; + + m_Deed.m_East = info.ButtonID != 1; + m_Deed.SendTarget(sender.Mobile); + } + } } - - public override BaseAddonContainerDeed Deed => new VanityDeed(); - public override int LabelNumber => 1074027; // Vanity - public override int DefaultGumpID => 0x51; - public override int DefaultDropSound => 0x42; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class VanityDeed : BaseAddonContainerDeed - { - private bool m_East; - - [Constructible] - public VanityDeed() => LootType = LootType.Blessed; - - public VanityDeed(Serial serial) : base(serial) - { - } - - public override BaseAddonContainer Addon => new VanityAddon(m_East); - public override int LabelNumber => 1074027; // Vanity - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new InternalGump(this)); - } - else - { - from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. - } - } - - private void SendTarget(Mobile m) - { - base.OnDoubleClick(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - private class InternalGump : Gump - { - private readonly VanityDeed m_Deed; - - public InternalGump(VanityDeed deed) : base(60, 36) - { - m_Deed = deed; - - AddPage(0); - - AddBackground(0, 0, 273, 324, 0x13BE); - AddImageTiled(10, 10, 253, 20, 0xA40); - AddImageTiled(10, 40, 253, 244, 0xA40); - AddImageTiled(10, 294, 253, 20, 0xA40); - AddAlphaRegion(10, 10, 253, 304); - AddButton(10, 294, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL - AddHtmlLocalized(14, 12, 273, 20, 1076744, 0x7FFF); // Please select your vanity position. - - AddPage(1); - - AddButton(19, 49, 0x845, 0x846, 1); - AddHtmlLocalized(44, 47, 213, 20, 1075386, 0x7FFF); // South - AddButton(19, 73, 0x845, 0x846, 2); - AddHtmlLocalized(44, 71, 213, 20, 1075387, 0x7FFF); // East - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Deed?.Deleted != false || info.ButtonID == 0) - return; - - m_Deed.m_East = info.ButtonID != 1; - m_Deed.SendTarget(sender.Mobile); - } - } - } } diff --git a/Projects/UOContent/Items/Special/Heritage Items/WallTorch.cs b/Projects/UOContent/Items/Special/Heritage Items/WallTorch.cs index eb3d6d56f..27fd61809 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/WallTorch.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/WallTorch.cs @@ -2,107 +2,107 @@ using Server.Network; namespace Server.Items { - [Flippable(0x3D98, 0x3D94)] - public class WallTorchComponent : AddonComponent - { - public WallTorchComponent() : base(0x3D98) + [Flippable(0x3D98, 0x3D94)] + public class WallTorchComponent : AddonComponent { - } - - public WallTorchComponent(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1076282; // Wall Torch - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(Location, 2)) - { - ItemID = ItemID switch + public WallTorchComponent() : base(0x3D98) { - 0x3D98 => 0x3D9B, - 0x3D9B => 0x3D98, - 0x3D94 => 0x3D97, - 0x3D97 => 0x3D94, - _ => ItemID - }; + } - Effects.PlaySound(Location, Map, 0x3BE); - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } + public WallTorchComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1076282; // Wall Torch + + public override void OnDoubleClick(Mobile from) + { + if (from.InRange(Location, 2)) + { + ItemID = ItemID switch + { + 0x3D98 => 0x3D9B, + 0x3D9B => 0x3D98, + 0x3D94 => 0x3D97, + 0x3D97 => 0x3D94, + _ => ItemID + }; + + Effects.PlaySound(Location, Map, 0x3BE); + } + else + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + } + + 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(); + } } - public override void Serialize(IGenericWriter writer) + public class WallTorchAddon : BaseAddon { - base.Serialize(writer); + public WallTorchAddon() + { + AddComponent(new WallTorchComponent(), 0, 0, 0); + } - writer.WriteEncodedInt(0); // version + public WallTorchAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new WallTorchDeed(); + + 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(); + } } - public override void Deserialize(IGenericReader reader) + public class WallTorchDeed : BaseAddonDeed { - base.Deserialize(reader); + [Constructible] + public WallTorchDeed() => LootType = LootType.Blessed; - int version = reader.ReadEncodedInt(); + public WallTorchDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new WallTorchAddon(); + public override int LabelNumber => 1076282; // Wall Torch + + 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(); + } } - } - - public class WallTorchAddon : BaseAddon - { - public WallTorchAddon() - { - AddComponent(new WallTorchComponent(), 0, 0, 0); - } - - public WallTorchAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new WallTorchDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class WallTorchDeed : BaseAddonDeed - { - [Constructible] - public WallTorchDeed() => LootType = LootType.Blessed; - - public WallTorchDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new WallTorchAddon(); - public override int LabelNumber => 1076282; // Wall Torch - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Heritage Items/WoodenCoffin.cs b/Projects/UOContent/Items/Special/Heritage Items/WoodenCoffin.cs index 90a82ae3a..d92d80b7f 100644 --- a/Projects/UOContent/Items/Special/Heritage Items/WoodenCoffin.cs +++ b/Projects/UOContent/Items/Special/Heritage Items/WoodenCoffin.cs @@ -3,154 +3,154 @@ using Server.Network; namespace Server.Items { - public class WoodenCoffinComponent : AddonComponent - { - public WoodenCoffinComponent(int itemID) : base(itemID) + public class WoodenCoffinComponent : AddonComponent { + public WoodenCoffinComponent(int itemID) : base(itemID) + { + } + + public WoodenCoffinComponent(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1076274; // Coffin + + 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(); + } } - public WoodenCoffinComponent(Serial serial) : base(serial) + public class WoodenCoffinAddon : BaseAddon { + [Constructible] + public WoodenCoffinAddon(bool east) + { + if (east) // east + { + AddComponent(new WoodenCoffinComponent(0x1C41), 0, 0, 0); + AddComponent(new WoodenCoffinComponent(0x1C42), 1, 0, 0); + AddComponent(new WoodenCoffinComponent(0x1C43), 2, 0, 0); + } + else // south + { + AddComponent(new WoodenCoffinComponent(0x1C4F), 0, 0, 0); + AddComponent(new WoodenCoffinComponent(0x1C50), 0, 1, 0); + AddComponent(new WoodenCoffinComponent(0x1C51), 0, 2, 0); + } + } + + public WoodenCoffinAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new WoodenCoffinDeed(); + + 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(); + } } - public override int LabelNumber => 1076274; // Coffin - - public override void Serialize(IGenericWriter writer) + public class WoodenCoffinDeed : BaseAddonDeed { - base.Serialize(writer); + private bool m_East; - writer.WriteEncodedInt(0); // version + [Constructible] + public WoodenCoffinDeed() => LootType = LootType.Blessed; + + public WoodenCoffinDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon => new WoodenCoffinAddon(m_East); + public override int LabelNumber => 1076274; // Coffin + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new InternalGump(this)); + } + else + { + from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. + } + } + + private void SendTarget(Mobile m) + { + base.OnDoubleClick(m); + } + + 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(); + } + + private class InternalGump : Gump + { + private readonly WoodenCoffinDeed m_Deed; + + public InternalGump(WoodenCoffinDeed deed) : base(60, 36) + { + m_Deed = deed; + + AddPage(0); + + AddBackground(0, 0, 273, 324, 0x13BE); + AddImageTiled(10, 10, 253, 20, 0xA40); + AddImageTiled(10, 40, 253, 244, 0xA40); + AddImageTiled(10, 294, 253, 20, 0xA40); + AddAlphaRegion(10, 10, 253, 304); + AddButton(10, 294, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL + AddHtmlLocalized(14, 12, 273, 20, 1076748, 0x7FFF); // Please select your coffin position + + AddPage(1); + + AddButton(19, 49, 0x845, 0x846, 1); + AddHtmlLocalized(44, 47, 213, 20, 1075386, 0x7FFF); // South + AddButton(19, 73, 0x845, 0x846, 2); + AddHtmlLocalized(44, 71, 213, 20, 1075387, 0x7FFF); // East + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Deed?.Deleted != false || info.ButtonID == 0) + return; + + m_Deed.m_East = info.ButtonID != 1; + m_Deed.SendTarget(sender.Mobile); + } + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class WoodenCoffinAddon : BaseAddon - { - [Constructible] - public WoodenCoffinAddon(bool east) - { - if (east) // east - { - AddComponent(new WoodenCoffinComponent(0x1C41), 0, 0, 0); - AddComponent(new WoodenCoffinComponent(0x1C42), 1, 0, 0); - AddComponent(new WoodenCoffinComponent(0x1C43), 2, 0, 0); - } - else // south - { - AddComponent(new WoodenCoffinComponent(0x1C4F), 0, 0, 0); - AddComponent(new WoodenCoffinComponent(0x1C50), 0, 1, 0); - AddComponent(new WoodenCoffinComponent(0x1C51), 0, 2, 0); - } - } - - public WoodenCoffinAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed => new WoodenCoffinDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class WoodenCoffinDeed : BaseAddonDeed - { - private bool m_East; - - [Constructible] - public WoodenCoffinDeed() => LootType = LootType.Blessed; - - public WoodenCoffinDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon => new WoodenCoffinAddon(m_East); - public override int LabelNumber => 1076274; // Coffin - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new InternalGump(this)); - } - else - { - from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. - } - } - - private void SendTarget(Mobile m) - { - base.OnDoubleClick(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - private class InternalGump : Gump - { - private readonly WoodenCoffinDeed m_Deed; - - public InternalGump(WoodenCoffinDeed deed) : base(60, 36) - { - m_Deed = deed; - - AddPage(0); - - AddBackground(0, 0, 273, 324, 0x13BE); - AddImageTiled(10, 10, 253, 20, 0xA40); - AddImageTiled(10, 40, 253, 244, 0xA40); - AddImageTiled(10, 294, 253, 20, 0xA40); - AddAlphaRegion(10, 10, 253, 304); - AddButton(10, 294, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(45, 296, 450, 20, 1060051, 0x7FFF); // CANCEL - AddHtmlLocalized(14, 12, 273, 20, 1076748, 0x7FFF); // Please select your coffin position - - AddPage(1); - - AddButton(19, 49, 0x845, 0x846, 1); - AddHtmlLocalized(44, 47, 213, 20, 1075386, 0x7FFF); // South - AddButton(19, 73, 0x845, 0x846, 2); - AddHtmlLocalized(44, 71, 213, 20, 1075387, 0x7FFF); // East - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Deed?.Deleted != false || info.ButtonID == 0) - return; - - m_Deed.m_East = info.ButtonID != 1; - m_Deed.SendTarget(sender.Mobile); - } - } - } } diff --git a/Projects/UOContent/Items/Special/HeritageToken.cs b/Projects/UOContent/Items/Special/HeritageToken.cs index e5fddd7f8..89f9c55e1 100644 --- a/Projects/UOContent/Items/Special/HeritageToken.cs +++ b/Projects/UOContent/Items/Special/HeritageToken.cs @@ -2,57 +2,57 @@ namespace Server.Items { - public interface ITokunoDyable - { - } - - public class HeritageToken : Item - { - [Constructible] - public HeritageToken() : base(0x367A) - { - LootType = LootType.Blessed; - Weight = 5.0; - } - - public HeritageToken(Serial serial) : base(serial) + public interface ITokunoDyable { } - public override int LabelNumber => 1076596; // A Heritage Token - - public override void OnDoubleClick(Mobile from) + public class HeritageToken : Item { - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new HeritageTokenGump(this)); - } - else - { - from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. - } + [Constructible] + public HeritageToken() : base(0x367A) + { + LootType = LootType.Blessed; + Weight = 5.0; + } + + public HeritageToken(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1076596; // A Heritage Token + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new HeritageTokenGump(this)); + } + else + { + from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1070998, $"#{1076595}"); // Use this to redeem
Your Heritage Items + } + + 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(); + } } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1070998, $"#{1076595}"); // Use this to redeem
Your Heritage Items - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Holiday/Christmas/HolidayTree.cs b/Projects/UOContent/Items/Special/Holiday/Christmas/HolidayTree.cs index ca3401a8a..682d8124d 100644 --- a/Projects/UOContent/Items/Special/Holiday/Christmas/HolidayTree.cs +++ b/Projects/UOContent/Items/Special/Holiday/Christmas/HolidayTree.cs @@ -3,290 +3,290 @@ using Server.Multis; namespace Server.Items { - public enum HolidayTreeType - { - Classic, - Modern - } - - public class HolidayTree : Item, IAddon - { - private List m_Components; - - public HolidayTree(Mobile from, HolidayTreeType type, Point3D loc) : base(1) + public enum HolidayTreeType { - Movable = false; - MoveToWorld(loc, from.Map); - - Placer = from; - m_Components = new List(); - - switch (type) - { - case HolidayTreeType.Classic: - { - ItemID = 0xCD7; - - AddItem(0, 0, 0, new TreeTrunk(this, 0xCD6)); - - AddOrnament(0, 0, 2, 0xF22); - AddOrnament(0, 0, 9, 0xF18); - AddOrnament(0, 0, 15, 0xF20); - AddOrnament(0, 0, 19, 0xF17); - AddOrnament(0, 0, 20, 0xF24); - AddOrnament(0, 0, 20, 0xF1F); - AddOrnament(0, 0, 20, 0xF19); - AddOrnament(0, 0, 21, 0xF1B); - AddOrnament(0, 0, 28, 0xF2F); - AddOrnament(0, 0, 30, 0xF23); - AddOrnament(0, 0, 32, 0xF2A); - AddOrnament(0, 0, 33, 0xF30); - AddOrnament(0, 0, 34, 0xF29); - AddOrnament(0, 1, 7, 0xF16); - AddOrnament(0, 1, 7, 0xF1E); - AddOrnament(0, 1, 12, 0xF0F); - AddOrnament(0, 1, 13, 0xF13); - AddOrnament(0, 1, 18, 0xF12); - AddOrnament(0, 1, 19, 0xF15); - AddOrnament(0, 1, 25, 0xF28); - AddOrnament(0, 1, 29, 0xF1A); - AddOrnament(0, 1, 37, 0xF2B); - AddOrnament(1, 0, 13, 0xF10); - AddOrnament(1, 0, 14, 0xF1C); - AddOrnament(1, 0, 16, 0xF14); - AddOrnament(1, 0, 17, 0xF26); - AddOrnament(1, 0, 22, 0xF27); - - break; - } - case HolidayTreeType.Modern: - { - ItemID = 0x1B7E; - - AddOrnament(0, 0, 2, 0xF2F); - AddOrnament(0, 0, 2, 0xF20); - AddOrnament(0, 0, 2, 0xF22); - AddOrnament(0, 0, 5, 0xF30); - AddOrnament(0, 0, 5, 0xF15); - AddOrnament(0, 0, 5, 0xF1F); - AddOrnament(0, 0, 5, 0xF2B); - AddOrnament(0, 0, 6, 0xF0F); - AddOrnament(0, 0, 7, 0xF1E); - AddOrnament(0, 0, 7, 0xF24); - AddOrnament(0, 0, 8, 0xF29); - AddOrnament(0, 0, 9, 0xF18); - AddOrnament(0, 0, 14, 0xF1C); - AddOrnament(0, 0, 15, 0xF13); - AddOrnament(0, 0, 15, 0xF20); - AddOrnament(0, 0, 16, 0xF26); - AddOrnament(0, 0, 17, 0xF12); - AddOrnament(0, 0, 18, 0xF17); - AddOrnament(0, 0, 20, 0xF1B); - AddOrnament(0, 0, 23, 0xF28); - AddOrnament(0, 0, 25, 0xF18); - AddOrnament(0, 0, 25, 0xF2A); - AddOrnament(0, 1, 7, 0xF16); - - break; - } - } + Classic, + Modern } - public HolidayTree(Serial serial) : base(serial) + public class HolidayTree : Item, IAddon { - } + private List m_Components; - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Placer { get; set; } + public HolidayTree(Mobile from, HolidayTreeType type, Point3D loc) : base(1) + { + Movable = false; + MoveToWorld(loc, from.Map); - public override int LabelNumber => 1041117; // a tree for the holidays + Placer = from; + m_Components = new List(); - public bool CouldFit(IPoint3D p, Map map) => map.CanFit((Point3D)p, 20); - - Item IAddon.Deed => new HolidayTreeDeed(); - - public override void OnAfterDelete() - { - for (int i = 0; i < m_Components.Count; ++i) - m_Components[i].Delete(); - } - - private void AddOrnament(int x, int y, int z, int itemID) - { - AddItem(x + 1, y + 1, z + 11, new Ornament(itemID)); - } - - private void AddItem(int x, int y, int z, Item item) - { - item.MoveToWorld(new Point3D(Location.X + x, Location.Y + y, Location.Z + z), Map); - - m_Components.Add(item); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(Placer); - - writer.Write(m_Components.Count); - - for (int i = 0; i < m_Components.Count; ++i) - writer.Write(m_Components[i]); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - Placer = reader.ReadMobile(); - - goto case 0; - } - case 0: - { - int count = reader.ReadInt(); - - m_Components = new List(count); - - for (int i = 0; i < count; ++i) + switch (type) { - Item item = reader.ReadItem(); + case HolidayTreeType.Classic: + { + ItemID = 0xCD7; - if (item != null) - m_Components.Add(item); + AddItem(0, 0, 0, new TreeTrunk(this, 0xCD6)); + + AddOrnament(0, 0, 2, 0xF22); + AddOrnament(0, 0, 9, 0xF18); + AddOrnament(0, 0, 15, 0xF20); + AddOrnament(0, 0, 19, 0xF17); + AddOrnament(0, 0, 20, 0xF24); + AddOrnament(0, 0, 20, 0xF1F); + AddOrnament(0, 0, 20, 0xF19); + AddOrnament(0, 0, 21, 0xF1B); + AddOrnament(0, 0, 28, 0xF2F); + AddOrnament(0, 0, 30, 0xF23); + AddOrnament(0, 0, 32, 0xF2A); + AddOrnament(0, 0, 33, 0xF30); + AddOrnament(0, 0, 34, 0xF29); + AddOrnament(0, 1, 7, 0xF16); + AddOrnament(0, 1, 7, 0xF1E); + AddOrnament(0, 1, 12, 0xF0F); + AddOrnament(0, 1, 13, 0xF13); + AddOrnament(0, 1, 18, 0xF12); + AddOrnament(0, 1, 19, 0xF15); + AddOrnament(0, 1, 25, 0xF28); + AddOrnament(0, 1, 29, 0xF1A); + AddOrnament(0, 1, 37, 0xF2B); + AddOrnament(1, 0, 13, 0xF10); + AddOrnament(1, 0, 14, 0xF1C); + AddOrnament(1, 0, 16, 0xF14); + AddOrnament(1, 0, 17, 0xF26); + AddOrnament(1, 0, 22, 0xF27); + + break; + } + case HolidayTreeType.Modern: + { + ItemID = 0x1B7E; + + AddOrnament(0, 0, 2, 0xF2F); + AddOrnament(0, 0, 2, 0xF20); + AddOrnament(0, 0, 2, 0xF22); + AddOrnament(0, 0, 5, 0xF30); + AddOrnament(0, 0, 5, 0xF15); + AddOrnament(0, 0, 5, 0xF1F); + AddOrnament(0, 0, 5, 0xF2B); + AddOrnament(0, 0, 6, 0xF0F); + AddOrnament(0, 0, 7, 0xF1E); + AddOrnament(0, 0, 7, 0xF24); + AddOrnament(0, 0, 8, 0xF29); + AddOrnament(0, 0, 9, 0xF18); + AddOrnament(0, 0, 14, 0xF1C); + AddOrnament(0, 0, 15, 0xF13); + AddOrnament(0, 0, 15, 0xF20); + AddOrnament(0, 0, 16, 0xF26); + AddOrnament(0, 0, 17, 0xF12); + AddOrnament(0, 0, 18, 0xF17); + AddOrnament(0, 0, 20, 0xF1B); + AddOrnament(0, 0, 23, 0xF28); + AddOrnament(0, 0, 25, 0xF18); + AddOrnament(0, 0, 25, 0xF2A); + AddOrnament(0, 1, 7, 0xF16); + + break; + } + } + } + + public HolidayTree(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Placer { get; set; } + + public override int LabelNumber => 1041117; // a tree for the holidays + + public bool CouldFit(IPoint3D p, Map map) => map.CanFit((Point3D)p, 20); + + Item IAddon.Deed => new HolidayTreeDeed(); + + public override void OnAfterDelete() + { + for (var i = 0; i < m_Components.Count; ++i) + m_Components[i].Delete(); + } + + private void AddOrnament(int x, int y, int z, int itemID) + { + AddItem(x + 1, y + 1, z + 11, new Ornament(itemID)); + } + + private void AddItem(int x, int y, int z, Item item) + { + item.MoveToWorld(new Point3D(Location.X + x, Location.Y + y, Location.Z + z), Map); + + m_Components.Add(item); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(Placer); + + writer.Write(m_Components.Count); + + for (var i = 0; i < m_Components.Count; ++i) + writer.Write(m_Components[i]); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + Placer = reader.ReadMobile(); + + goto case 0; + } + case 0: + { + var count = reader.ReadInt(); + + m_Components = new List(count); + + for (var i = 0; i < count; ++i) + { + var item = reader.ReadItem(); + + if (item != null) + m_Components.Add(item); + } + + break; + } } - break; - } - } - - Timer.DelayCall(ValidatePlacement); - } - - public void ValidatePlacement() - { - if (BaseHouse.FindHouseAt(this) == null) - { - HolidayTreeDeed deed = new HolidayTreeDeed(); - deed.MoveToWorld(Location, Map); - Delete(); - } - } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(GetWorldLocation(), 1)) - { - if (Placer == null || from == Placer || from.AccessLevel >= AccessLevel.GameMaster) - { - from.AddToBackpack(new HolidayTreeDeed()); - - Delete(); - - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (house?.Addons.Contains(this) == true) - house.Addons.Remove(this); - - from.SendLocalizedMessage(503393); // A deed for the tree has been placed in your backpack. + Timer.DelayCall(ValidatePlacement); } - else + + public void ValidatePlacement() { - from.SendLocalizedMessage(503396); // You cannot take this tree down. - } - } - else - { - from.SendLocalizedMessage(500446); // That is too far away. - } - } - - private class Ornament : Item - { - public Ornament(int itemID) : base(itemID) => Movable = false; - - public Ornament(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041118; // a tree ornament - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - private class TreeTrunk : Item - { - private HolidayTree m_Tree; - - public TreeTrunk(HolidayTree tree, int itemID) : base(itemID) - { - Movable = false; - MoveToWorld(tree.Location, tree.Map); - - m_Tree = tree; - } - - public TreeTrunk(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041117; // a tree for the holidays - - public override void OnDoubleClick(Mobile from) - { - if (m_Tree?.Deleted == false) - m_Tree.OnDoubleClick(from); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Tree); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: + if (BaseHouse.FindHouseAt(this) == null) { - m_Tree = reader.ReadItem() as HolidayTree; - - if (m_Tree == null) + var deed = new HolidayTreeDeed(); + deed.MoveToWorld(Location, Map); Delete(); - - break; } } - } + + public override void OnDoubleClick(Mobile from) + { + if (from.InRange(GetWorldLocation(), 1)) + { + if (Placer == null || from == Placer || from.AccessLevel >= AccessLevel.GameMaster) + { + from.AddToBackpack(new HolidayTreeDeed()); + + Delete(); + + var house = BaseHouse.FindHouseAt(this); + + if (house?.Addons.Contains(this) == true) + house.Addons.Remove(this); + + from.SendLocalizedMessage(503393); // A deed for the tree has been placed in your backpack. + } + else + { + from.SendLocalizedMessage(503396); // You cannot take this tree down. + } + } + else + { + from.SendLocalizedMessage(500446); // That is too far away. + } + } + + private class Ornament : Item + { + public Ornament(int itemID) : base(itemID) => Movable = false; + + public Ornament(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041118; // a tree ornament + + 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(); + } + } + + private class TreeTrunk : Item + { + private HolidayTree m_Tree; + + public TreeTrunk(HolidayTree tree, int itemID) : base(itemID) + { + Movable = false; + MoveToWorld(tree.Location, tree.Map); + + m_Tree = tree; + } + + public TreeTrunk(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041117; // a tree for the holidays + + public override void OnDoubleClick(Mobile from) + { + if (m_Tree?.Deleted == false) + m_Tree.OnDoubleClick(from); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Tree); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Tree = reader.ReadItem() as HolidayTree; + + if (m_Tree == null) + Delete(); + + break; + } + } + } + } } - } } diff --git a/Projects/UOContent/Items/Special/Holiday/GiftBox.cs b/Projects/UOContent/Items/Special/Holiday/GiftBox.cs index 7f4842344..c790ee3d4 100644 --- a/Projects/UOContent/Items/Special/Holiday/GiftBox.cs +++ b/Projects/UOContent/Items/Special/Holiday/GiftBox.cs @@ -1,37 +1,37 @@ namespace Server.Items { - [Furniture] - [Flippable(0x232A, 0x232B)] - public class GiftBox : BaseContainer - { - [Constructible] - public GiftBox() : this(Utility.RandomDyedHue()) + [Furniture] + [Flippable(0x232A, 0x232B)] + public class GiftBox : BaseContainer { + [Constructible] + public GiftBox() : this(Utility.RandomDyedHue()) + { + } + + [Constructible] + public GiftBox(int hue) : base(Utility.Random(0x232A, 2)) + { + Weight = 2.0; + Hue = hue; + } + + public GiftBox(Serial serial) : base(serial) + { + } + + 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(); + } } - - [Constructible] - public GiftBox(int hue) : base(Utility.Random(0x232A, 2)) - { - Weight = 2.0; - Hue = hue; - } - - public GiftBox(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Holiday/GingerBreadHouseDeed.cs b/Projects/UOContent/Items/Special/Holiday/GingerBreadHouseDeed.cs index aac2c8c3e..6cd666fba 100644 --- a/Projects/UOContent/Items/Special/Holiday/GingerBreadHouseDeed.cs +++ b/Projects/UOContent/Items/Special/Holiday/GingerBreadHouseDeed.cs @@ -1,62 +1,62 @@ namespace Server.Items { - public class GingerBreadHouseAddon : BaseAddon - { - public GingerBreadHouseAddon() + public class GingerBreadHouseAddon : BaseAddon { - for (int i = 0x2be5; i < 0x2be8; i++) - { - LocalizedAddonComponent laoc = new LocalizedAddonComponent(i, 1077395); // Gingerbread House - laoc.Light = LightType.SouthSmall; - AddComponent(laoc, i == 0x2be5 ? -1 : 0, i == 0x2be7 ? -1 : 0, 0); - } + public GingerBreadHouseAddon() + { + for (var i = 0x2be5; i < 0x2be8; i++) + { + var laoc = new LocalizedAddonComponent(i, 1077395); // Gingerbread House + laoc.Light = LightType.SouthSmall; + AddComponent(laoc, i == 0x2be5 ? -1 : 0, i == 0x2be7 ? -1 : 0, 0); + } + } + + public GingerBreadHouseAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed => new GingerBreadHouseDeed(); + + 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 GingerBreadHouseAddon(Serial serial) : base(serial) + public class GingerBreadHouseDeed : BaseAddonDeed { + [Constructible] + public GingerBreadHouseDeed() + { + Weight = 1.0; + LootType = LootType.Blessed; + } + + public GingerBreadHouseDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1077394; // a Gingerbread House Deed + public override BaseAddon Addon => new GingerBreadHouseAddon(); + + 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 BaseAddonDeed Deed => new GingerBreadHouseDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class GingerBreadHouseDeed : BaseAddonDeed - { - [Constructible] - public GingerBreadHouseDeed() - { - Weight = 1.0; - LootType = LootType.Blessed; - } - - public GingerBreadHouseDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1077394; // a Gingerbread House Deed - public override BaseAddon Addon => new GingerBreadHouseAddon(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Holiday/HolidayBell.cs b/Projects/UOContent/Items/Special/Holiday/HolidayBell.cs index 261d2f3f9..17aa63433 100644 --- a/Projects/UOContent/Items/Special/Holiday/HolidayBell.cs +++ b/Projects/UOContent/Items/Special/Holiday/HolidayBell.cs @@ -1,111 +1,111 @@ namespace Server.Items { - public class HolidayBell : Item - { - private static readonly string[] m_StaffNames = + public class HolidayBell : Item { - "Adrick", - "Alai", - "Bulldoz", - "Evocare", - "FierY-iCe", - "Greyburn", - "Hanse", - "Ignatz", - "Jalek", - "LadyMOI", - "Lord Krum", - "Malantus", - "Nimrond", - "Oaks", - "Prophet", - "Runesabre", - "Sage", - "Stellerex", - "T-Bone", - "Tajima", - "Tyrant", - "Vex" - }; + private static readonly string[] m_StaffNames = + { + "Adrick", + "Alai", + "Bulldoz", + "Evocare", + "FierY-iCe", + "Greyburn", + "Hanse", + "Ignatz", + "Jalek", + "LadyMOI", + "Lord Krum", + "Malantus", + "Nimrond", + "Oaks", + "Prophet", + "Runesabre", + "Sage", + "Stellerex", + "T-Bone", + "Tajima", + "Tyrant", + "Vex" + }; - private static readonly int[] m_Hues = - { - 0xA, 0x24, 0x42, 0x56, 0x1A, 0x4C, 0x3C, 0x60, 0x2E, 0x55, 0x23, 0x38, 0x482, 0x6, 0x10 - }; + private static readonly int[] m_Hues = + { + 0xA, 0x24, 0x42, 0x56, 0x1A, 0x4C, 0x3C, 0x60, 0x2E, 0x55, 0x23, 0x38, 0x482, 0x6, 0x10 + }; - private string m_Maker; - private int m_SoundID; + private string m_Maker; + private int m_SoundID; - [Constructible] - public HolidayBell() - : this(m_StaffNames.RandomElement()) - { + [Constructible] + public HolidayBell() + : this(m_StaffNames.RandomElement()) + { + } + + [Constructible] + public HolidayBell(string maker) + : base(0x1C12) + { + m_Maker = maker; + + LootType = LootType.Blessed; + Hue = m_Hues.RandomElement(); + SoundID = 0x0F5 + Utility.Random(14); + } + + public HolidayBell(Serial serial) + : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int SoundID + { + get => m_SoundID; + set + { + m_SoundID = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public string Giver + { + get => m_Maker; + set => m_Maker = value; + } + + public override string DefaultName => $"A Holiday Bell From {Giver}"; + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 2)) + from.SendLocalizedMessage(500446); // That is too far away. + else from.PlaySound(m_SoundID); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Maker); + + writer.WriteEncodedInt(m_SoundID); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Maker = reader.ReadString(); + m_SoundID = reader.ReadEncodedInt(); + + Utility.Intern(ref m_Maker); + } } - - [Constructible] - public HolidayBell(string maker) - : base(0x1C12) - { - m_Maker = maker; - - LootType = LootType.Blessed; - Hue = m_Hues.RandomElement(); - SoundID = 0x0F5 + Utility.Random(14); - } - - public HolidayBell(Serial serial) - : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int SoundID - { - get => m_SoundID; - set - { - m_SoundID = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public string Giver - { - get => m_Maker; - set => m_Maker = value; - } - - public override string DefaultName => $"A Holiday Bell From {Giver}"; - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 2)) - from.SendLocalizedMessage(500446); // That is too far away. - else from.PlaySound(m_SoundID); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Maker); - - writer.WriteEncodedInt(m_SoundID); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_Maker = reader.ReadString(); - m_SoundID = reader.ReadEncodedInt(); - - Utility.Intern(ref m_Maker); - } - } } diff --git a/Projects/UOContent/Items/Special/Holiday/HolidayFoods.cs b/Projects/UOContent/Items/Special/Holiday/HolidayFoods.cs index 23e122cd0..b256d62d4 100644 --- a/Projects/UOContent/Items/Special/Holiday/HolidayFoods.cs +++ b/Projects/UOContent/Items/Special/Holiday/HolidayFoods.cs @@ -3,160 +3,160 @@ using System.Collections.Generic; namespace Server.Items { - public class CandyCane : Food - { - [Constructible] - public CandyCane() - : this(0x2bdd + Utility.Random(4)) + public class CandyCane : Food { - } + private static readonly Dictionary m_ToothAches = new Dictionary(); - public CandyCane(int itemID) : base(itemID, 1) - { - Stackable = false; - LootType = LootType.Blessed; - } - - public CandyCane(Serial serial) - : base(serial) - { - } - - private static readonly Dictionary m_ToothAches = new Dictionary(); - - private static CandyCaneTimer EnsureTimer(Mobile from) - { - if (!m_ToothAches.TryGetValue(from, out CandyCaneTimer timer)) - m_ToothAches[from] = timer = new CandyCaneTimer(from); - - return timer; - } - - public static int GetToothAche(Mobile from) => m_ToothAches.TryGetValue(from, out CandyCaneTimer timer) ? timer.Eaten : 0; - - public static void SetToothAche(Mobile from, int value) - { - EnsureTimer(from).Eaten = value; - } - - public override bool CheckHunger(Mobile from) - { - EnsureTimer(from).Eaten += 32; - - from.SendLocalizedMessage(1077387); // You feel as if you could eat as much as you wanted! - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - - public class CandyCaneTimer : Timer - { - public CandyCaneTimer(Mobile eater) - : base(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(30)) - { - Eater = eater; - Priority = TimerPriority.FiveSeconds; - Start(); - } - - public Mobile Eater { get; } - - public int Eaten { get; set; } - - protected override void OnTick() - { - --Eaten; - - if (Eater?.Deleted != false || Eaten <= 0) + [Constructible] + public CandyCane() + : this(0x2bdd + Utility.Random(4)) { - Stop(); - m_ToothAches.Remove(Eater); } - else if (Eater.Map != Map.Internal && Eater.Alive) + + public CandyCane(int itemID) : base(itemID, 1) { - if (Eaten > 60) - { - Eater.Say(1077388 + Utility.Random(5)); - - /* ARRGH! My tooth hurts sooo much! - * You just can't find a good Britannian dentist these days... - * My teeth! - * MAKE IT STOP! - * AAAH! It feels like someone kicked me in the teeth! - */ - - if (Utility.RandomBool() && Eater.Body.IsHuman && !Eater.Mounted) - Eater.Animate(32, 5, 1, true, false, 0); - } - else if (Eaten == 60) - { - Eater.SendLocalizedMessage(1077393); // The extreme pain in your teeth subsides. - } + Stackable = false; + LootType = LootType.Blessed; } - } - } - } - public class GingerBreadCookie : Food - { - private readonly int[] m_Messages = - { - 0, - 1077396, // Noooo! - 1077397, // Please don't eat me... *whimper* - 1077405, // Not the face! - 1077406, // Ahhhhhh! My foot�s gone! - 1077407, // Please. No! I have gingerkids! - 1077408, // No, no! I�m really made of poison. Really. - 1077409 // Run, run as fast as you can! You can't catch me! I'm the gingerbread man! - }; + public CandyCane(Serial serial) + : base(serial) + { + } - [Constructible] - public GingerBreadCookie() - : base(Utility.RandomBool() ? 0x2be1 : 0x2be2, 1) - { - Stackable = false; - LootType = LootType.Blessed; + private static CandyCaneTimer EnsureTimer(Mobile from) + { + if (!m_ToothAches.TryGetValue(from, out var timer)) + m_ToothAches[from] = timer = new CandyCaneTimer(from); + + return timer; + } + + public static int GetToothAche(Mobile from) => m_ToothAches.TryGetValue(from, out var timer) ? timer.Eaten : 0; + + public static void SetToothAche(Mobile from, int value) + { + EnsureTimer(from).Eaten = value; + } + + public override bool CheckHunger(Mobile from) + { + EnsureTimer(from).Eaten += 32; + + from.SendLocalizedMessage(1077387); // You feel as if you could eat as much as you wanted! + return true; + } + + 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 class CandyCaneTimer : Timer + { + public CandyCaneTimer(Mobile eater) + : base(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(30)) + { + Eater = eater; + Priority = TimerPriority.FiveSeconds; + Start(); + } + + public Mobile Eater { get; } + + public int Eaten { get; set; } + + protected override void OnTick() + { + --Eaten; + + if (Eater?.Deleted != false || Eaten <= 0) + { + Stop(); + m_ToothAches.Remove(Eater); + } + else if (Eater.Map != Map.Internal && Eater.Alive) + { + if (Eaten > 60) + { + Eater.Say(1077388 + Utility.Random(5)); + + /* ARRGH! My tooth hurts sooo much! + * You just can't find a good Britannian dentist these days... + * My teeth! + * MAKE IT STOP! + * AAAH! It feels like someone kicked me in the teeth! + */ + + if (Utility.RandomBool() && Eater.Body.IsHuman && !Eater.Mounted) + Eater.Animate(32, 5, 1, true, false, 0); + } + else if (Eaten == 60) + { + Eater.SendLocalizedMessage(1077393); // The extreme pain in your teeth subsides. + } + } + } + } } - public GingerBreadCookie(Serial serial) - : base(serial) + public class GingerBreadCookie : Food { + private readonly int[] m_Messages = + { + 0, + 1077396, // Noooo! + 1077397, // Please don't eat me... *whimper* + 1077405, // Not the face! + 1077406, // Ahhhhhh! My foot�s gone! + 1077407, // Please. No! I have gingerkids! + 1077408, // No, no! I�m really made of poison. Really. + 1077409 // Run, run as fast as you can! You can't catch me! I'm the gingerbread man! + }; + + [Constructible] + public GingerBreadCookie() + : base(Utility.RandomBool() ? 0x2be1 : 0x2be2, 1) + { + Stackable = false; + LootType = LootType.Blessed; + } + + public GingerBreadCookie(Serial serial) + : base(serial) + { + } + + public override bool Eat(Mobile from) + { + var message = m_Messages.RandomElement(); + + if (message != 0) + { + SendLocalizedMessageTo(from, message); + return false; + } + + return base.Eat(from); + } + + 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 Eat(Mobile from) - { - int message = m_Messages.RandomElement(); - - if (message != 0) - { - SendLocalizedMessageTo(from, message); - return false; - } - - return base.Eat(from); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/Holiday/HolidayGiftBoxes.cs b/Projects/UOContent/Items/Special/Holiday/HolidayGiftBoxes.cs index fff1301de..2586f222c 100644 --- a/Projects/UOContent/Items/Special/Holiday/HolidayGiftBoxes.cs +++ b/Projects/UOContent/Items/Special/Holiday/HolidayGiftBoxes.cs @@ -1,208 +1,208 @@ namespace Server.Items { - public class GiftBoxHues - { - /* there's possibly a couple more, but this is what we could verify on OSI */ - - private static readonly int[] m_NormalHues = + public class GiftBoxHues { - 0x672, - 0x454, - 0x507, - 0x4ac, - 0x504, - 0x84b, - 0x495, - 0x97c, - 0x493, - 0x4a8, - 0x494, - 0x4aa, - 0xb8b, - 0x84f, - 0x491, - 0x851, - 0x503, - 0xb8c, - 0x4ab, - 0x84B - }; + /* there's possibly a couple more, but this is what we could verify on OSI */ - private static readonly int[] m_NeonHues = - { - 0x438, - 0x424, - 0x433, - 0x445, - 0x42b, - 0x448 - }; + private static readonly int[] m_NormalHues = + { + 0x672, + 0x454, + 0x507, + 0x4ac, + 0x504, + 0x84b, + 0x495, + 0x97c, + 0x493, + 0x4a8, + 0x494, + 0x4aa, + 0xb8b, + 0x84f, + 0x491, + 0x851, + 0x503, + 0xb8c, + 0x4ab, + 0x84B + }; - public static int RandomGiftBoxHue => m_NormalHues.RandomElement(); - public static int RandomNeonBoxHue => m_NeonHues.RandomElement(); - } + private static readonly int[] m_NeonHues = + { + 0x438, + 0x424, + 0x433, + 0x445, + 0x42b, + 0x448 + }; - [Flippable(0x46A5, 0x46A6)] - public class GiftBoxRectangle : BaseContainer - { - [Constructible] - public GiftBoxRectangle() - : base(Utility.RandomBool() ? 0x46A5 : 0x46A6) => - Hue = GiftBoxHues.RandomGiftBoxHue; - - public GiftBoxRectangle(Serial serial) - : base(serial) - { + public static int RandomGiftBoxHue => m_NormalHues.RandomElement(); + public static int RandomNeonBoxHue => m_NeonHues.RandomElement(); } - public override int DefaultGumpID => 0x11E; - - public override void Serialize(IGenericWriter writer) + [Flippable(0x46A5, 0x46A6)] + public class GiftBoxRectangle : BaseContainer { - base.Serialize(writer); - writer.Write(0); // version + [Constructible] + public GiftBoxRectangle() + : base(Utility.RandomBool() ? 0x46A5 : 0x46A6) => + Hue = GiftBoxHues.RandomGiftBoxHue; + + public GiftBoxRectangle(Serial serial) + : base(serial) + { + } + + public override int DefaultGumpID => 0x11E; + + 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 Deserialize(IGenericReader reader) + public class GiftBoxCube : BaseContainer { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } + [Constructible] + public GiftBoxCube() + : base(0x46A2) => + Hue = GiftBoxHues.RandomGiftBoxHue; - public class GiftBoxCube : BaseContainer - { - [Constructible] - public GiftBoxCube() - : base(0x46A2) => - Hue = GiftBoxHues.RandomGiftBoxHue; + public GiftBoxCube(Serial serial) + : base(serial) + { + } - public GiftBoxCube(Serial serial) - : base(serial) - { + public override int DefaultGumpID => 0x11B; + + 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 int DefaultGumpID => 0x11B; - - public override void Serialize(IGenericWriter writer) + public class GiftBoxCylinder : BaseContainer { - base.Serialize(writer); - writer.Write(0); // version + [Constructible] + public GiftBoxCylinder() + : base(0x46A3) => + Hue = GiftBoxHues.RandomGiftBoxHue; + + public GiftBoxCylinder(Serial serial) + : base(serial) + { + } + + public override int DefaultGumpID => 0x11C; + + 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 Deserialize(IGenericReader reader) + public class GiftBoxOctogon : BaseContainer { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } + [Constructible] + public GiftBoxOctogon() + : base(0x46A4) => + Hue = GiftBoxHues.RandomGiftBoxHue; - public class GiftBoxCylinder : BaseContainer - { - [Constructible] - public GiftBoxCylinder() - : base(0x46A3) => - Hue = GiftBoxHues.RandomGiftBoxHue; + public GiftBoxOctogon(Serial serial) + : base(serial) + { + } - public GiftBoxCylinder(Serial serial) - : base(serial) - { + public override int DefaultGumpID => 0x11D; + + 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 int DefaultGumpID => 0x11C; - - public override void Serialize(IGenericWriter writer) + public class GiftBoxAngel : BaseContainer { - base.Serialize(writer); - writer.Write(0); // version + [Constructible] + public GiftBoxAngel() + : base(0x46A7) => + Hue = GiftBoxHues.RandomGiftBoxHue; + + public GiftBoxAngel(Serial serial) + : base(serial) + { + } + + public override int DefaultGumpID => 0x11F; + + 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 Deserialize(IGenericReader reader) + [Flippable(0x232A, 0x232B)] + public class GiftBoxNeon : BaseContainer { - base.Deserialize(reader); - int version = reader.ReadInt(); + [Constructible] + public GiftBoxNeon() + : base(Utility.RandomBool() ? 0x232A : 0x232B) => + Hue = GiftBoxHues.RandomNeonBoxHue; + + public GiftBoxNeon(Serial serial) + : base(serial) + { + } + + 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 class GiftBoxOctogon : BaseContainer - { - [Constructible] - public GiftBoxOctogon() - : base(0x46A4) => - Hue = GiftBoxHues.RandomGiftBoxHue; - - public GiftBoxOctogon(Serial serial) - : base(serial) - { - } - - public override int DefaultGumpID => 0x11D; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class GiftBoxAngel : BaseContainer - { - [Constructible] - public GiftBoxAngel() - : base(0x46A7) => - Hue = GiftBoxHues.RandomGiftBoxHue; - - public GiftBoxAngel(Serial serial) - : base(serial) - { - } - - public override int DefaultGumpID => 0x11F; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - [Flippable(0x232A, 0x232B)] - public class GiftBoxNeon : BaseContainer - { - [Constructible] - public GiftBoxNeon() - : base(Utility.RandomBool() ? 0x232A : 0x232B) => - Hue = GiftBoxHues.RandomNeonBoxHue; - - public GiftBoxNeon(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/Holiday/HolidayPottedPlant.cs b/Projects/UOContent/Items/Special/Holiday/HolidayPottedPlant.cs index 228370329..252bf670d 100644 --- a/Projects/UOContent/Items/Special/Holiday/HolidayPottedPlant.cs +++ b/Projects/UOContent/Items/Special/Holiday/HolidayPottedPlant.cs @@ -3,149 +3,149 @@ using Server.Network; namespace Server.Items { - public class HolidayPottedPlant : Item - { - [Constructible] - public HolidayPottedPlant() - : this(Utility.RandomMinMax(0x11C8, 0x11CC)) + public class HolidayPottedPlant : Item { - } - - [Constructible] - public HolidayPottedPlant(int itemID) - : base(itemID) - { - } - - public HolidayPottedPlant(Serial serial) - : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class PottedPlantDeed : Item - { - [Constructible] - public PottedPlantDeed() - : base(0x14F0) => - LootType = LootType.Blessed; - - public PottedPlantDeed(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1041114; // A deed for a potted plant. - public override double DefaultWeight => 1.0; - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new InternalGump(this)); - } - else - { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - private class InternalGump : Gump - { - private readonly PottedPlantDeed m_Deed; - - public InternalGump(PottedPlantDeed deed) : base(100, 200) - { - m_Deed = deed; - - Closable = true; - Disposable = true; - Draggable = true; - Resizable = false; - - AddPage(0); - AddBackground(0, 0, 360, 195, 0xA28); - - AddPage(1); - AddLabel(45, 15, 0, "Choose a Potted Plant:"); - - AddItem(45, 75, 0x11C8); - AddButton(55, 50, 0x845, 0x846, 1); - - AddItem(100, 75, 0x11C9); - AddButton(115, 50, 0x845, 0x846, 2); - - AddItem(160, 75, 0x11CA); - AddButton(175, 50, 0x845, 0x846, 3); - - AddItem(225, 75, 0x11CB); - AddButton(235, 50, 0x845, 0x846, 4); - - AddItem(280, 75, 0x11CC); - AddButton(295, 50, 0x845, 0x846, 5); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Deed?.Deleted != false) - return; - - Mobile from = sender.Mobile; - - if (!m_Deed.IsChildOf(from.Backpack)) + [Constructible] + public HolidayPottedPlant() + : this(Utility.RandomMinMax(0x11C8, 0x11CC)) { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it - return; } - int index = info.ButtonID - 1; - - if (index >= 0 && index <= 4) + [Constructible] + public HolidayPottedPlant(int itemID) + : base(itemID) { - HolidayPottedPlant plant = new HolidayPottedPlant(0x11C8 + index); - - if (!from.PlaceInBackpack(plant)) - { - plant.Delete(); - from.SendLocalizedMessage(1078837); // Your backpack is full! Please make room and try again. - } - else - { - m_Deed.Delete(); - } } - } + + public HolidayPottedPlant(Serial serial) + : base(serial) + { + } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + 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(); + } + } + + public class PottedPlantDeed : Item + { + [Constructible] + public PottedPlantDeed() + : base(0x14F0) => + LootType = LootType.Blessed; + + public PottedPlantDeed(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1041114; // A deed for a potted plant. + public override double DefaultWeight => 1.0; + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new InternalGump(this)); + } + else + { + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. + } + } + + 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(); + } + + private class InternalGump : Gump + { + private readonly PottedPlantDeed m_Deed; + + public InternalGump(PottedPlantDeed deed) : base(100, 200) + { + m_Deed = deed; + + Closable = true; + Disposable = true; + Draggable = true; + Resizable = false; + + AddPage(0); + AddBackground(0, 0, 360, 195, 0xA28); + + AddPage(1); + AddLabel(45, 15, 0, "Choose a Potted Plant:"); + + AddItem(45, 75, 0x11C8); + AddButton(55, 50, 0x845, 0x846, 1); + + AddItem(100, 75, 0x11C9); + AddButton(115, 50, 0x845, 0x846, 2); + + AddItem(160, 75, 0x11CA); + AddButton(175, 50, 0x845, 0x846, 3); + + AddItem(225, 75, 0x11CB); + AddButton(235, 50, 0x845, 0x846, 4); + + AddItem(280, 75, 0x11CC); + AddButton(295, 50, 0x845, 0x846, 5); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Deed?.Deleted != false) + return; + + var from = sender.Mobile; + + if (!m_Deed.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it + return; + } + + var index = info.ButtonID - 1; + + if (index >= 0 && index <= 4) + { + var plant = new HolidayPottedPlant(0x11C8 + index); + + if (!from.PlaceInBackpack(plant)) + { + plant.Delete(); + from.SendLocalizedMessage(1078837); // Your backpack is full! Please make room and try again. + } + else + { + m_Deed.Delete(); + } + } + } + } } - } } diff --git a/Projects/UOContent/Items/Special/Holiday/HolidayTimepiece.cs b/Projects/UOContent/Items/Special/Holiday/HolidayTimepiece.cs index 33899c151..8632394a3 100644 --- a/Projects/UOContent/Items/Special/Holiday/HolidayTimepiece.cs +++ b/Projects/UOContent/Items/Special/Holiday/HolidayTimepiece.cs @@ -1,36 +1,36 @@ namespace Server.Items { - public class HolidayTimepiece : Clock - { - [Constructible] - public HolidayTimepiece() - : base(0x1086) + public class HolidayTimepiece : Clock { - Weight = DefaultWeight; - LootType = LootType.Blessed; - Layer = Layer.Bracelet; + [Constructible] + public HolidayTimepiece() + : base(0x1086) + { + Weight = DefaultWeight; + LootType = LootType.Blessed; + Layer = Layer.Bracelet; + } + + public HolidayTimepiece(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1041113; // a holiday timepiece + public override double DefaultWeight => 1.0; + + 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 HolidayTimepiece(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1041113; // a holiday timepiece - public override double DefaultWeight => 1.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Holiday/Icecicles.cs b/Projects/UOContent/Items/Special/Holiday/Icecicles.cs index 54dc4cbf0..6366ae2f8 100644 --- a/Projects/UOContent/Items/Special/Holiday/Icecicles.cs +++ b/Projects/UOContent/Items/Special/Holiday/Icecicles.cs @@ -1,170 +1,170 @@ namespace Server.Items { - public class IcicleLargeSouth : Item - { - [Constructible] - public IcicleLargeSouth() - : base(0x4572) + public class IcicleLargeSouth : Item { + [Constructible] + public IcicleLargeSouth() + : base(0x4572) + { + } + + public IcicleLargeSouth(Serial serial) + : base(serial) + { + } + + 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(); + } } - public IcicleLargeSouth(Serial serial) - : base(serial) + public class IcicleMedSouth : Item { + [Constructible] + public IcicleMedSouth() + : base(0x4573) + { + } + + public IcicleMedSouth(Serial serial) + : base(serial) + { + } + + 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(); + } } - public override void Serialize(IGenericWriter writer) + public class IcicleSmallSouth : Item { - base.Serialize(writer); + [Constructible] + public IcicleSmallSouth() + : base(0x4574) + { + } - writer.Write(0); + public IcicleSmallSouth(Serial serial) + : base(serial) + { + } + + 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(); + } } - public override void Deserialize(IGenericReader reader) + public class IcicleLargeEast : Item { - base.Deserialize(reader); + [Constructible] + public IcicleLargeEast() + : base(0x4575) + { + } - int version = reader.ReadInt(); - } - } + public IcicleLargeEast(Serial serial) + : base(serial) + { + } - public class IcicleMedSouth : Item - { - [Constructible] - public IcicleMedSouth() - : base(0x4573) - { + 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(); + } } - public IcicleMedSouth(Serial serial) - : base(serial) + public class IcicleMedEast : Item { + [Constructible] + public IcicleMedEast() + : base(0x4576) + { + } + + public IcicleMedEast(Serial serial) + : base(serial) + { + } + + 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(); + } } - public override void Serialize(IGenericWriter writer) + public class IcicleSmallEast : Item { - base.Serialize(writer); + [Constructible] + public IcicleSmallEast() + : base(0x4577) + { + } - writer.Write(0); + public IcicleSmallEast(Serial serial) + : base(serial) + { + } + + 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(); + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class IcicleSmallSouth : Item - { - [Constructible] - public IcicleSmallSouth() - : base(0x4574) - { - } - - public IcicleSmallSouth(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class IcicleLargeEast : Item - { - [Constructible] - public IcicleLargeEast() - : base(0x4575) - { - } - - public IcicleLargeEast(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class IcicleMedEast : Item - { - [Constructible] - public IcicleMedEast() - : base(0x4576) - { - } - - public IcicleMedEast(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class IcicleSmallEast : Item - { - [Constructible] - public IcicleSmallEast() - : base(0x4577) - { - } - - public IcicleSmallEast(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Holiday/IcyPatch.cs b/Projects/UOContent/Items/Special/Holiday/IcyPatch.cs index c22a8a57a..6debe2a2c 100644 --- a/Projects/UOContent/Items/Special/Holiday/IcyPatch.cs +++ b/Projects/UOContent/Items/Special/Holiday/IcyPatch.cs @@ -4,107 +4,108 @@ using Server.Spells; namespace Server.Items { - public class IcyPatch : Item - { - /* On OSI, the iceypatch with itemid 0x122a is "rarer", so we will give it 1:10 chance of creating it that way */ - - [Constructible] - public IcyPatch() - : this(Utility.Random(10) == 0 ? 0x122A : 0x122F) + public class IcyPatch : Item { - } + /* On OSI, the iceypatch with itemid 0x122a is "rarer", so we will give it 1:10 chance of creating it that way */ - public IcyPatch(int itemid) - : base(itemid) => - Hue = 0x481; - - public IcyPatch(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1095159; // An Icy Patch - public override double DefaultWeight => 5.0; - - public override bool OnMoveOver(Mobile m) - { - if (m is PlayerMobile && m.Alive && m.AccessLevel == AccessLevel.Player) - switch (Utility.Random(3)) + [Constructible] + public IcyPatch() + : this(Utility.Random(10) == 0 ? 0x122A : 0x122F) { - case 0: - RunSequence(m, 1095160, false); - break; // You steadily walk over the slippery surface. - case 1: - RunSequence(m, 1095161, true); - break; // You skillfully manage to maintain your balance. - default: - RunSequence(m, 1095162, true); - break; // You lose your footing and ungracefully splatter on the ground. } - return base.OnMoveOver(m); + + public IcyPatch(int itemid) + : base(itemid) => + Hue = 0x481; + + public IcyPatch(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1095159; // An Icy Patch + public override double DefaultWeight => 5.0; + + public override bool OnMoveOver(Mobile m) + { + if (m is PlayerMobile && m.Alive && m.AccessLevel == AccessLevel.Player) + switch (Utility.Random(3)) + { + case 0: + RunSequence(m, 1095160, false); + break; // You steadily walk over the slippery surface. + case 1: + RunSequence(m, 1095161, true); + break; // You skillfully manage to maintain your balance. + default: + RunSequence(m, 1095162, true); + break; // You lose your footing and ungracefully splatter on the ground. + } + + return base.OnMoveOver(m); + } + + public virtual void RunSequence(Mobile m, int message, bool freeze) + { + if (freeze) + { + m.Frozen = true; + Timer.DelayCall(TimeSpan.FromSeconds(message == 1095162 ? 2.0 : 1.25), EndFall_Callback, m); + } + + m.SendLocalizedMessage(message); + + var action = 0; + var sound = 0; + + if (message == 1095162) + { + if (m.Mounted) + m.Mount.Rider = null; + + var p = new Point3D(Location); + + if (SpellHelper.FindValidSpawnLocation(Map, ref p, true)) + Timer.DelayCall(TimeSpan.FromSeconds(0), m.MoveToWorld, p, m.Map); + + action = 21 + Utility.Random(2); + sound = m.Female ? 0x317 : 0x426; + } + else if (message == 1095161) + { + action = 17; + sound = m.Female ? 0x319 : 0x429; + } + + if (action > 0) + Timer.DelayCall(TimeSpan.FromSeconds(0.4), BeginFall_Callback, m, action, sound); + } + + private static void BeginFall_Callback(Mobile m, int action, int sound) + { + if (!m.Mounted) + m.Animate(action, 1, 1, false, true, 0); + + m.PlaySound(sound); + } + + private static void EndFall_Callback(Mobile m) + { + m.Frozen = false; + } + + 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(); + } } - - public virtual void RunSequence(Mobile m, int message, bool freeze) - { - if (freeze) - { - m.Frozen = true; - Timer.DelayCall(TimeSpan.FromSeconds(message == 1095162 ? 2.0 : 1.25), EndFall_Callback, m); - } - - m.SendLocalizedMessage(message); - - int action = 0; - int sound = 0; - - if (message == 1095162) - { - if (m.Mounted) - m.Mount.Rider = null; - - Point3D p = new Point3D(Location); - - if (SpellHelper.FindValidSpawnLocation(Map, ref p, true)) - Timer.DelayCall(TimeSpan.FromSeconds(0), m.MoveToWorld, p, m.Map); - - action = 21 + Utility.Random(2); - sound = m.Female ? 0x317 : 0x426; - } - else if (message == 1095161) - { - action = 17; - sound = m.Female ? 0x319 : 0x429; - } - - if (action > 0) - Timer.DelayCall(TimeSpan.FromSeconds(0.4), BeginFall_Callback, m, action, sound); - } - - private static void BeginFall_Callback(Mobile m, int action, int sound) - { - if (!m.Mounted) - m.Animate(action, 1, 1, false, true, 0); - - m.PlaySound(sound); - } - - private static void EndFall_Callback(Mobile m) - { - m.Frozen = false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/Holiday/PKHolidayStuff.cs b/Projects/UOContent/Items/Special/Holiday/PKHolidayStuff.cs index b432bf170..c772739cb 100644 --- a/Projects/UOContent/Items/Special/Holiday/PKHolidayStuff.cs +++ b/Projects/UOContent/Items/Special/Holiday/PKHolidayStuff.cs @@ -1,90 +1,90 @@ namespace Server.Items { - public class Coal : Item - { - [Constructible] - public Coal() : base(0x19b9) + public class Coal : Item { - Stackable = false; - LootType = LootType.Blessed; - Hue = 0x965; + [Constructible] + public Coal() : base(0x19b9) + { + Stackable = false; + LootType = LootType.Blessed; + Hue = 0x965; + } + + public Coal(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Coal"; + + 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 Coal(Serial serial) : base(serial) + public class BadCard : Item { + private static readonly int[] m_CardHues = { 0x45, 0x27, 0x3d0 }; + + [Constructible] + public BadCard() : base(0x14ef) + { + Hue = m_CardHues.RandomElement(); + Stackable = false; + LootType = LootType.Blessed; + Movable = true; + } + + public BadCard(Serial serial) : base(serial) + { + } + + public override int LabelNumber // Maybe next year youll get a better... + => 1041428; + + 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 string DefaultName => "Coal"; - - public override void Serialize(IGenericWriter writer) + public class Spam : Food { - base.Serialize(writer); - writer.Write(0); // version + [Constructible] + public Spam() : base(0x1044, 1) + { + Stackable = false; + LootType = LootType.Blessed; + } + + public Spam(Serial serial) : base(serial) + { + } + + 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 Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class BadCard : Item - { - private static readonly int[] m_CardHues = { 0x45, 0x27, 0x3d0 }; - - [Constructible] - public BadCard() : base(0x14ef) - { - Hue = m_CardHues.RandomElement(); - Stackable = false; - LootType = LootType.Blessed; - Movable = true; - } - - public BadCard(Serial serial) : base(serial) - { - } - - public override int LabelNumber // Maybe next year youll get a better... - => 1041428; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class Spam : Food - { - [Constructible] - public Spam() : base(0x1044, 1) - { - Stackable = false; - LootType = LootType.Blessed; - } - - public Spam(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/Holiday/Poinsettias.cs b/Projects/UOContent/Items/Special/Holiday/Poinsettias.cs index dc8227ac5..07ec3012b 100644 --- a/Projects/UOContent/Items/Special/Holiday/Poinsettias.cs +++ b/Projects/UOContent/Items/Special/Holiday/Poinsettias.cs @@ -1,58 +1,58 @@ namespace Server.Items { - public class RedPoinsettia : Item - { - [Constructible] - public RedPoinsettia() : base(0x2330) + public class RedPoinsettia : Item { - Weight = 1.0; - LootType = LootType.Blessed; + [Constructible] + public RedPoinsettia() : base(0x2330) + { + Weight = 1.0; + LootType = LootType.Blessed; + } + + public RedPoinsettia(Serial serial) : base(serial) + { + } + + 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 RedPoinsettia(Serial serial) : base(serial) + public class WhitePoinsettia : Item { + [Constructible] + public WhitePoinsettia() : base(0x2331) + { + Weight = 1.0; + LootType = LootType.Blessed; + } + + public WhitePoinsettia(Serial serial) : base(serial) + { + } + + 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 Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class WhitePoinsettia : Item - { - [Constructible] - public WhitePoinsettia() : base(0x2331) - { - Weight = 1.0; - LootType = LootType.Blessed; - } - - public WhitePoinsettia(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Holiday/SnowGlobes.cs b/Projects/UOContent/Items/Special/Holiday/SnowGlobes.cs index bf9b571c4..f2135702e 100644 --- a/Projects/UOContent/Items/Special/Holiday/SnowGlobes.cs +++ b/Projects/UOContent/Items/Special/Holiday/SnowGlobes.cs @@ -1,311 +1,311 @@ namespace Server.Items { - public class SnowGlobe : Item - { - public SnowGlobe() - : base(0xE2F) + public class SnowGlobe : Item { - LootType = LootType.Blessed; - Light = LightType.Circle150; + public SnowGlobe() + : base(0xE2F) + { + LootType = LootType.Blessed; + Light = LightType.Circle150; + } + + public SnowGlobe(Serial serial) + : base(serial) + { + } + + public override double DefaultWeight => 1.0; + + 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 SnowGlobe(Serial serial) - : base(serial) + public enum SnowGlobeTypeOne { + Britain, + Moonglow, + Minoc, + Magincia, + BuccaneersDen, + Trinsic, + Yew, + SkaraBrae, + Jhelom, + Nujelm, + Papua, + Delucia, + Cove, + Ocllo, + SerpentsHold, + EmpathAbbey, + TheLycaeum, + Vesper, + Wind } - public override double DefaultWeight => 1.0; - - public override void Serialize(IGenericWriter writer) + public class SnowGlobeOne : SnowGlobe { - base.Serialize(writer); + private SnowGlobeTypeOne m_Type; - writer.Write(0); // version + [Constructible] + public SnowGlobeOne() + : this((SnowGlobeTypeOne)Utility.Random(19)) + { + } + + [Constructible] + public SnowGlobeOne(SnowGlobeTypeOne type) => m_Type = type; + + public SnowGlobeOne(Serial serial) + : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public SnowGlobeTypeOne Place + { + get => m_Type; + set + { + m_Type = value; + InvalidateProperties(); + } + } + + public override int LabelNumber => 1041454 + (int)m_Type; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + writer.WriteEncodedInt((int)m_Type); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Type = (SnowGlobeTypeOne)reader.ReadEncodedInt(); + break; + } + } + } } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public enum SnowGlobeTypeOne - { - Britain, - Moonglow, - Minoc, - Magincia, - BuccaneersDen, - Trinsic, - Yew, - SkaraBrae, - Jhelom, - Nujelm, - Papua, - Delucia, - Cove, - Ocllo, - SerpentsHold, - EmpathAbbey, - TheLycaeum, - Vesper, - Wind - } - - public class SnowGlobeOne : SnowGlobe - { - private SnowGlobeTypeOne m_Type; - - [Constructible] - public SnowGlobeOne() - : this((SnowGlobeTypeOne)Utility.Random(19)) + public enum SnowGlobeTypeTwo { + AncientCitadel, + BlackthornesCastle, + CityofMontor, + CityofMistas, + ExodusLair, + LakeofFire, + Lakeshire, + PassofKarnaugh, + TheEtherealFortress, + TwinOaksTavern, + ChaosShrine, + ShrineofHumility, + ShrineofSacrifice, + ShrineofCompassion, + ShrineofHonor, + ShrineofHonesty, + ShrineofSpirituality, + ShrineofJustice, + ShrineofValor } - [Constructible] - public SnowGlobeOne(SnowGlobeTypeOne type) => m_Type = type; - - public SnowGlobeOne(Serial serial) - : base(serial) + public class SnowGlobeTwo : SnowGlobe { + /* Oddly, these are not localized. */ + private static readonly string[] m_PlaceNames = + { + /* AncientCitadel */ "Ancient Citadel", + /* BlackthornesCastle */ "Blackthorne's Castle", + /* CityofMontor */ "City of Montor", + /* CityofMistas */ "City of Mistas", + /* ExodusLair */ "Exodus' Lair", + /* LakeofFire */ "Lake of Fire", + /* Lakeshire */ "Lakeshire", + /* PassofKarnaugh */ "Pass of Karnaugh", + /* TheEtherealFortress */ "The Etheral Fortress", + /* TwinOaksTavern */ "Twin Oaks Tavern", + /* ChaosShrine */ "Chaos Shrine", + /* ShrineofHumility */ "Shrine of Humility", + /* ShrineofSacrifice */ "Shrine of Sacrifice", + /* ShrineofCompassion */ "Shrine of Compassion", + /* ShrineofHonor */ "Shrine of Honor", + /* ShrineofHonesty */ "Shrine of Honesty", + /* ShrineofSpirituality */ "Shrine of Spirituality", + /* ShrineofJustice */ "Shrine of Justice", + /* ShrineofValor */ "Shrine of Valor" + }; + + private SnowGlobeTypeTwo m_Type; + + [Constructible] + public SnowGlobeTwo() + : this((SnowGlobeTypeTwo)Utility.Random(19)) + { + } + + [Constructible] + public SnowGlobeTwo(SnowGlobeTypeTwo type) => m_Type = type; + + public SnowGlobeTwo(Serial serial) + : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public SnowGlobeTypeTwo Place + { + get => m_Type; + set + { + m_Type = value; + InvalidateProperties(); + } + } + + public override string DefaultName + { + get + { + var idx = (int)m_Type; + + if (idx < 0 || idx >= m_PlaceNames.Length) + return "a snowy scene"; + + return $"a snowy scene of {m_PlaceNames[idx]}"; + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + writer.WriteEncodedInt((int)m_Type); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Type = (SnowGlobeTypeTwo)reader.ReadEncodedInt(); + break; + } + } + } } - [CommandProperty(AccessLevel.GameMaster)] - public SnowGlobeTypeOne Place + public enum SnowGlobeTypeThree { - get => m_Type; - set - { - m_Type = value; - InvalidateProperties(); - } + Luna, + Umbra, + Zento, + Heartwood, + Covetous, + Deceit, + Destard, + Hythloth, + Khaldun, + Shame, + Wrong, + Doom, + TheCitadel, + ThePalaceofParoxysmus, + TheBlightedGrove, + ThePrismofLight } - public override int LabelNumber => 1041454 + (int)m_Type; - - public override void Serialize(IGenericWriter writer) + public class SnowGlobeThree : SnowGlobe { - base.Serialize(writer); + private SnowGlobeTypeThree m_Type; - writer.Write(0); // version - writer.WriteEncodedInt((int)m_Type); + [Constructible] + public SnowGlobeThree() + : this((SnowGlobeTypeThree)Utility.Random(16)) + { + } + + [Constructible] + public SnowGlobeThree(SnowGlobeTypeThree type) => m_Type = type; + + public SnowGlobeThree(Serial serial) + : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public SnowGlobeTypeThree Place + { + get => m_Type; + set + { + m_Type = value; + InvalidateProperties(); + } + } + + public override int LabelNumber + { + get + { + if (m_Type >= SnowGlobeTypeThree.Covetous) + return 1075440 + ((int)m_Type - 4); + + return 1075294 + (int)m_Type; + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + writer.WriteEncodedInt((int)m_Type); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Type = (SnowGlobeTypeThree)reader.ReadEncodedInt(); + break; + } + } + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Type = (SnowGlobeTypeOne)reader.ReadEncodedInt(); - break; - } - } - } - } - - public enum SnowGlobeTypeTwo - { - AncientCitadel, - BlackthornesCastle, - CityofMontor, - CityofMistas, - ExodusLair, - LakeofFire, - Lakeshire, - PassofKarnaugh, - TheEtherealFortress, - TwinOaksTavern, - ChaosShrine, - ShrineofHumility, - ShrineofSacrifice, - ShrineofCompassion, - ShrineofHonor, - ShrineofHonesty, - ShrineofSpirituality, - ShrineofJustice, - ShrineofValor - } - - public class SnowGlobeTwo : SnowGlobe - { - /* Oddly, these are not localized. */ - private static readonly string[] m_PlaceNames = - { - /* AncientCitadel */ "Ancient Citadel", - /* BlackthornesCastle */ "Blackthorne's Castle", - /* CityofMontor */ "City of Montor", - /* CityofMistas */ "City of Mistas", - /* ExodusLair */ "Exodus' Lair", - /* LakeofFire */ "Lake of Fire", - /* Lakeshire */ "Lakeshire", - /* PassofKarnaugh */ "Pass of Karnaugh", - /* TheEtherealFortress */ "The Etheral Fortress", - /* TwinOaksTavern */ "Twin Oaks Tavern", - /* ChaosShrine */ "Chaos Shrine", - /* ShrineofHumility */ "Shrine of Humility", - /* ShrineofSacrifice */ "Shrine of Sacrifice", - /* ShrineofCompassion */ "Shrine of Compassion", - /* ShrineofHonor */ "Shrine of Honor", - /* ShrineofHonesty */ "Shrine of Honesty", - /* ShrineofSpirituality */ "Shrine of Spirituality", - /* ShrineofJustice */ "Shrine of Justice", - /* ShrineofValor */ "Shrine of Valor" - }; - - private SnowGlobeTypeTwo m_Type; - - [Constructible] - public SnowGlobeTwo() - : this((SnowGlobeTypeTwo)Utility.Random(19)) - { - } - - [Constructible] - public SnowGlobeTwo(SnowGlobeTypeTwo type) => m_Type = type; - - public SnowGlobeTwo(Serial serial) - : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public SnowGlobeTypeTwo Place - { - get => m_Type; - set - { - m_Type = value; - InvalidateProperties(); - } - } - - public override string DefaultName - { - get - { - int idx = (int)m_Type; - - if (idx < 0 || idx >= m_PlaceNames.Length) - return "a snowy scene"; - - return $"a snowy scene of {m_PlaceNames[idx]}"; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - writer.WriteEncodedInt((int)m_Type); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Type = (SnowGlobeTypeTwo)reader.ReadEncodedInt(); - break; - } - } - } - } - - public enum SnowGlobeTypeThree - { - Luna, - Umbra, - Zento, - Heartwood, - Covetous, - Deceit, - Destard, - Hythloth, - Khaldun, - Shame, - Wrong, - Doom, - TheCitadel, - ThePalaceofParoxysmus, - TheBlightedGrove, - ThePrismofLight - } - - public class SnowGlobeThree : SnowGlobe - { - private SnowGlobeTypeThree m_Type; - - [Constructible] - public SnowGlobeThree() - : this((SnowGlobeTypeThree)Utility.Random(16)) - { - } - - [Constructible] - public SnowGlobeThree(SnowGlobeTypeThree type) => m_Type = type; - - public SnowGlobeThree(Serial serial) - : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public SnowGlobeTypeThree Place - { - get => m_Type; - set - { - m_Type = value; - InvalidateProperties(); - } - } - - public override int LabelNumber - { - get - { - if (m_Type >= SnowGlobeTypeThree.Covetous) - return 1075440 + ((int)m_Type - 4); - - return 1075294 + (int)m_Type; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - writer.WriteEncodedInt((int)m_Type); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Type = (SnowGlobeTypeThree)reader.ReadEncodedInt(); - break; - } - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Holiday/SnowPiles.cs b/Projects/UOContent/Items/Special/Holiday/SnowPiles.cs index 9181bd87d..1533196a3 100644 --- a/Projects/UOContent/Items/Special/Holiday/SnowPiles.cs +++ b/Projects/UOContent/Items/Special/Holiday/SnowPiles.cs @@ -1,40 +1,40 @@ namespace Server.Items { - public class SnowPileDeco : Item - { - private static readonly int[] m_Types = { 0x8E2, 0x8E0, 0x8E6, 0x8E5, 0x8E3 }; - - [Constructible] - public SnowPileDeco() - : this(m_Types.RandomElement()) + public class SnowPileDeco : Item { + private static readonly int[] m_Types = { 0x8E2, 0x8E0, 0x8E6, 0x8E5, 0x8E3 }; + + [Constructible] + public SnowPileDeco() + : this(m_Types.RandomElement()) + { + } + + [Constructible] + public SnowPileDeco(int itemid) + : base(itemid) => + Hue = 0x481; + + public SnowPileDeco(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "Snow Pile"; + public override double DefaultWeight => 2.0; + + 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(); + } } - - [Constructible] - public SnowPileDeco(int itemid) - : base(itemid) => - Hue = 0x481; - - public SnowPileDeco(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "Snow Pile"; - public override double DefaultWeight => 2.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/Holiday/SnowStatue.cs b/Projects/UOContent/Items/Special/Holiday/SnowStatue.cs index 50d0ac3d9..d84883f75 100644 --- a/Projects/UOContent/Items/Special/Holiday/SnowStatue.cs +++ b/Projects/UOContent/Items/Special/Holiday/SnowStatue.cs @@ -3,247 +3,247 @@ using Server.Network; namespace Server.Items { - [Flippable(0x456E, 0x456F)] - public class SnowStatuePegasus : Item - { - [Constructible] - public SnowStatuePegasus() - : base(0x456E) + [Flippable(0x456E, 0x456F)] + public class SnowStatuePegasus : Item { - } - - public SnowStatuePegasus(Serial serial) - : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - [Flippable(0x4578, 0x4579)] - public class SnowStatueSeahorse : Item - { - [Constructible] - public SnowStatueSeahorse() - : base(0x4578) - { - } - - public SnowStatueSeahorse(Serial serial) - : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - [Flippable(0x457A, 0x457B)] - public class SnowStatueMermaid : Item - { - [Constructible] - public SnowStatueMermaid() - : base(0x457A) - { - } - - public SnowStatueMermaid(Serial serial) - : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - [Flippable(0x457C, 0x457D)] - public class SnowStatueGriffon : Item - { - [Constructible] - public SnowStatueGriffon() - : base(0x457C) - { - } - - public SnowStatueGriffon(Serial serial) - : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SnowStatueDeed : Item - { - [Constructible] - public SnowStatueDeed() - : base(0x14F0) => - LootType = LootType.Blessed; - - public SnowStatueDeed(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1114296; // snow statue deed - public override double DefaultWeight => 1.0; - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new InternalGump(this)); - } - else - { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - private class InternalGump : Gump - { - private readonly SnowStatueDeed m_Deed; - - public InternalGump(SnowStatueDeed deed) : base(100, 200) - { - m_Deed = deed; - - Closable = true; - Disposable = true; - Draggable = true; - Resizable = false; - - AddPage(0); - AddBackground(0, 0, 360, 225, 0xA28); - - AddPage(1); - AddLabel(45, 15, 0, "Select One:"); - - AddItem(35, 75, 0x456E); - AddButton(65, 50, 0x845, 0x846, 1); - - AddItem(120, 75, 0x4578); - AddButton(135, 50, 0x845, 0x846, 2); - - AddItem(190, 75, 0x457A); - AddButton(205, 50, 0x845, 0x846, 3); - - AddItem(250, 75, 0x457C); - AddButton(275, 50, 0x845, 0x846, 4); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Deed?.Deleted != false) - return; - - Mobile from = sender.Mobile; - - if (!m_Deed.IsChildOf(from.Backpack)) + [Constructible] + public SnowStatuePegasus() + : base(0x456E) { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it - return; } - Item statue; - - switch (info.ButtonID) + public SnowStatuePegasus(Serial serial) + : base(serial) { - default: - return; - case 1: - statue = new SnowStatuePegasus(); - break; - case 2: - statue = new SnowStatueSeahorse(); - break; - case 3: - statue = new SnowStatueMermaid(); - break; - case 4: - statue = new SnowStatueGriffon(); - break; } - if (!from.PlaceInBackpack(statue)) + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + public override void Serialize(IGenericWriter writer) { - statue.Delete(); - from.SendLocalizedMessage(1078837); // Your backpack is full! Please make room and try again. + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version } - else + + public override void Deserialize(IGenericReader reader) { - m_Deed.Delete(); + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + } + + [Flippable(0x4578, 0x4579)] + public class SnowStatueSeahorse : Item + { + [Constructible] + public SnowStatueSeahorse() + : base(0x4578) + { + } + + public SnowStatueSeahorse(Serial serial) + : base(serial) + { + } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + 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(); + } + } + + [Flippable(0x457A, 0x457B)] + public class SnowStatueMermaid : Item + { + [Constructible] + public SnowStatueMermaid() + : base(0x457A) + { + } + + public SnowStatueMermaid(Serial serial) + : base(serial) + { + } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + 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(); + } + } + + [Flippable(0x457C, 0x457D)] + public class SnowStatueGriffon : Item + { + [Constructible] + public SnowStatueGriffon() + : base(0x457C) + { + } + + public SnowStatueGriffon(Serial serial) + : base(serial) + { + } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + 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(); + } + } + + public class SnowStatueDeed : Item + { + [Constructible] + public SnowStatueDeed() + : base(0x14F0) => + LootType = LootType.Blessed; + + public SnowStatueDeed(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1114296; // snow statue deed + public override double DefaultWeight => 1.0; + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new InternalGump(this)); + } + else + { + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. + } + } + + 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(); + } + + private class InternalGump : Gump + { + private readonly SnowStatueDeed m_Deed; + + public InternalGump(SnowStatueDeed deed) : base(100, 200) + { + m_Deed = deed; + + Closable = true; + Disposable = true; + Draggable = true; + Resizable = false; + + AddPage(0); + AddBackground(0, 0, 360, 225, 0xA28); + + AddPage(1); + AddLabel(45, 15, 0, "Select One:"); + + AddItem(35, 75, 0x456E); + AddButton(65, 50, 0x845, 0x846, 1); + + AddItem(120, 75, 0x4578); + AddButton(135, 50, 0x845, 0x846, 2); + + AddItem(190, 75, 0x457A); + AddButton(205, 50, 0x845, 0x846, 3); + + AddItem(250, 75, 0x457C); + AddButton(275, 50, 0x845, 0x846, 4); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Deed?.Deleted != false) + return; + + var from = sender.Mobile; + + if (!m_Deed.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it + return; + } + + Item statue; + + switch (info.ButtonID) + { + default: + return; + case 1: + statue = new SnowStatuePegasus(); + break; + case 2: + statue = new SnowStatueSeahorse(); + break; + case 3: + statue = new SnowStatueMermaid(); + break; + case 4: + statue = new SnowStatueGriffon(); + break; + } + + if (!from.PlaceInBackpack(statue)) + { + statue.Delete(); + from.SendLocalizedMessage(1078837); // Your backpack is full! Please make room and try again. + } + else + { + m_Deed.Delete(); + } + } } - } } - } } diff --git a/Projects/UOContent/Items/Special/Holiday/Snowflakes.cs b/Projects/UOContent/Items/Special/Holiday/Snowflakes.cs index 6d1f0cc3d..693101f86 100644 --- a/Projects/UOContent/Items/Special/Holiday/Snowflakes.cs +++ b/Projects/UOContent/Items/Special/Holiday/Snowflakes.cs @@ -1,58 +1,58 @@ namespace Server.Items { - public class BlueSnowflake : Item - { - [Constructible] - public BlueSnowflake() : base(0x232E) + public class BlueSnowflake : Item { - Weight = 1.0; - LootType = LootType.Blessed; + [Constructible] + public BlueSnowflake() : base(0x232E) + { + Weight = 1.0; + LootType = LootType.Blessed; + } + + public BlueSnowflake(Serial serial) : base(serial) + { + } + + 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 BlueSnowflake(Serial serial) : base(serial) + public class WhiteSnowflake : Item { + [Constructible] + public WhiteSnowflake() : base(0x232F) + { + Weight = 1.0; + LootType = LootType.Blessed; + } + + public WhiteSnowflake(Serial serial) : base(serial) + { + } + + 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 Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class WhiteSnowflake : Item - { - [Constructible] - public WhiteSnowflake() : base(0x232F) - { - Weight = 1.0; - LootType = LootType.Blessed; - } - - public WhiteSnowflake(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Holiday/Snowman.cs b/Projects/UOContent/Items/Special/Holiday/Snowman.cs index cebc2a053..c5dc35dd1 100644 --- a/Projects/UOContent/Items/Special/Holiday/Snowman.cs +++ b/Projects/UOContent/Items/Special/Holiday/Snowman.cs @@ -1,153 +1,153 @@ namespace Server.Items { - [Flippable(0x2328, 0x2329)] - public class Snowman : Item, IDyable - { - private string m_Title; - - [Constructible] - public Snowman() : this(Utility.RandomDyedHue()) + [Flippable(0x2328, 0x2329)] + public class Snowman : Item, IDyable { + // All hail OSI staff + private static readonly string[] titles = + { + /* 1 */ "Backflash", + /* 2 */ "Carbon", + /* 3 */ "Colbalistic", + /* 4 */ "Comforl", + /* 5 */ "Coppacchia", + /* 6 */ "Cyrus", + /* 7 */ "DannyB", + /* 8 */ "DJSoul", + /* 9 */ "DraconisRex", + /* 10 */ "Earia", + /* 11 */ "Foster", + /* 12 */ "Gonzo", + /* 13 */ "Haan", + /* 14 */ "Halona", + /* 15 */ "Hugo", + /* 16 */ "Hyacinth", + /* 17 */ "Imirian", + /* 18 */ "Jinsol", + /* 19 */ "Liciatia", + /* 20 */ "Loewen", + /* 21 */ "Loke", + /* 22 */ "Magnus", + /* 23 */ "Maleki", + /* 24 */ "Morpheus", + /* 25 */ "Obberron", + /* 26 */ "Odee", + /* 27 */ "Orbeus", + /* 28 */ "Pax", + /* 29 */ "Phields", + /* 30 */ "Pigpen", + /* 31 */ "Platinum", + /* 32 */ "Polpol", + /* 33 */ "Prume", + /* 34 */ "Quinnly", + /* 35 */ "Ragnarok", + /* 36 */ "Rend", + /* 37 */ "Roland", + /* 38 */ "RyanM", + /* 39 */ "Screach", + /* 40 */ "Seraph", + /* 41 */ "Silvani", + /* 42 */ "Sherbear", + /* 43 */ "SkyWalker", + /* 44 */ "Snark", + /* 45 */ "Sowl", + /* 46 */ "Spada", + /* 47 */ "Starblade", + /* 48 */ "Tenacious", + /* 49 */ "Tnez", + /* 50 */ "Wasia", + /* 51 */ "Zilo", + /* 52 */ "Zippy", + /* 53 */ "Zoer" + }; + + private string m_Title; + + [Constructible] + public Snowman() : this(Utility.RandomDyedHue()) + { + } + + [Constructible] + public Snowman(int hue) : this(hue, GetRandomTitle()) + { + } + + [Constructible] + public Snowman(string title) : this(Utility.RandomDyedHue(), title) + { + } + + [Constructible] + public Snowman(int hue, string title) : base(Utility.Random(0x2328, 2)) + { + Weight = 10.0; + Hue = hue; + LootType = LootType.Blessed; + + m_Title = title; + } + + public Snowman(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public string Title + { + get => m_Title; + set + { + m_Title = value; + InvalidateProperties(); + } + } + + public bool Dye(Mobile from, DyeTub sender) + { + if (Deleted) + return false; + + Hue = sender.DyedHue; + + return true; + } + + public static string GetRandomTitle() => titles.RandomElement(); + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_Title != null) + list.Add(1062841, m_Title); // ~1_NAME~ the Snowman + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(m_Title); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_Title = reader.ReadString(); + break; + } + } + + Utility.Intern(ref m_Title); + } } - - [Constructible] - public Snowman(int hue) : this(hue, GetRandomTitle()) - { - } - - [Constructible] - public Snowman(string title) : this(Utility.RandomDyedHue(), title) - { - } - - [Constructible] - public Snowman(int hue, string title) : base(Utility.Random(0x2328, 2)) - { - Weight = 10.0; - Hue = hue; - LootType = LootType.Blessed; - - m_Title = title; - } - - public Snowman(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public string Title - { - get => m_Title; - set - { - m_Title = value; - InvalidateProperties(); - } - } - - public bool Dye(Mobile from, DyeTub sender) - { - if (Deleted) - return false; - - Hue = sender.DyedHue; - - return true; - } - - // All hail OSI staff - private static readonly string[] titles = - { - /* 1 */ "Backflash", - /* 2 */ "Carbon", - /* 3 */ "Colbalistic", - /* 4 */ "Comforl", - /* 5 */ "Coppacchia", - /* 6 */ "Cyrus", - /* 7 */ "DannyB", - /* 8 */ "DJSoul", - /* 9 */ "DraconisRex", - /* 10 */ "Earia", - /* 11 */ "Foster", - /* 12 */ "Gonzo", - /* 13 */ "Haan", - /* 14 */ "Halona", - /* 15 */ "Hugo", - /* 16 */ "Hyacinth", - /* 17 */ "Imirian", - /* 18 */ "Jinsol", - /* 19 */ "Liciatia", - /* 20 */ "Loewen", - /* 21 */ "Loke", - /* 22 */ "Magnus", - /* 23 */ "Maleki", - /* 24 */ "Morpheus", - /* 25 */ "Obberron", - /* 26 */ "Odee", - /* 27 */ "Orbeus", - /* 28 */ "Pax", - /* 29 */ "Phields", - /* 30 */ "Pigpen", - /* 31 */ "Platinum", - /* 32 */ "Polpol", - /* 33 */ "Prume", - /* 34 */ "Quinnly", - /* 35 */ "Ragnarok", - /* 36 */ "Rend", - /* 37 */ "Roland", - /* 38 */ "RyanM", - /* 39 */ "Screach", - /* 40 */ "Seraph", - /* 41 */ "Silvani", - /* 42 */ "Sherbear", - /* 43 */ "SkyWalker", - /* 44 */ "Snark", - /* 45 */ "Sowl", - /* 46 */ "Spada", - /* 47 */ "Starblade", - /* 48 */ "Tenacious", - /* 49 */ "Tnez", - /* 50 */ "Wasia", - /* 51 */ "Zilo", - /* 52 */ "Zippy", - /* 53 */ "Zoer" - }; - - public static string GetRandomTitle() => titles.RandomElement(); - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_Title != null) - list.Add(1062841, m_Title); // ~1_NAME~ the Snowman - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(m_Title); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_Title = reader.ReadString(); - break; - } - } - - Utility.Intern(ref m_Title); - } - } } diff --git a/Projects/UOContent/Items/Special/Holiday/Stockings.cs b/Projects/UOContent/Items/Special/Holiday/Stockings.cs index 7b843dd3b..eed708dac 100644 --- a/Projects/UOContent/Items/Special/Holiday/Stockings.cs +++ b/Projects/UOContent/Items/Special/Holiday/Stockings.cs @@ -1,60 +1,60 @@ namespace Server.Items { - [Furniture] - [Flippable(0x2bd9, 0x2bda)] - public class GreenStocking : BaseContainer - { - [Constructible] - public GreenStocking() : base(Utility.Random(0x2BD9, 2)) + [Furniture] + [Flippable(0x2bd9, 0x2bda)] + public class GreenStocking : BaseContainer { + [Constructible] + public GreenStocking() : base(Utility.Random(0x2BD9, 2)) + { + } + + public GreenStocking(Serial serial) : base(serial) + { + } + + public override int DefaultGumpID => 0x103; + public override int DefaultDropSound => 0x42; + + 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 GreenStocking(Serial serial) : base(serial) + [Furniture] + [Flippable(0x2bdb, 0x2bdc)] + public class RedStocking : BaseContainer { + [Constructible] + public RedStocking() : base(Utility.Random(0x2BDB, 2)) + { + } + + public RedStocking(Serial serial) : base(serial) + { + } + + public override int DefaultGumpID => 0x103; + public override int DefaultDropSound => 0x42; + + 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 int DefaultGumpID => 0x103; - public override int DefaultDropSound => 0x42; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - [Furniture] - [Flippable(0x2bdb, 0x2bdc)] - public class RedStocking : BaseContainer - { - [Constructible] - public RedStocking() : base(Utility.Random(0x2BDB, 2)) - { - } - - public RedStocking(Serial serial) : base(serial) - { - } - - public override int DefaultGumpID => 0x103; - public override int DefaultDropSound => 0x42; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Holiday/WinterGiftPackage2003.cs b/Projects/UOContent/Items/Special/Holiday/WinterGiftPackage2003.cs index fc12a7010..4e29076c2 100644 --- a/Projects/UOContent/Items/Special/Holiday/WinterGiftPackage2003.cs +++ b/Projects/UOContent/Items/Special/Holiday/WinterGiftPackage2003.cs @@ -1,33 +1,33 @@ namespace Server.Items { - [Flippable(0x232A, 0x232B)] - public class WinterGiftPackage2003 : GiftBox - { - [Constructible] - public WinterGiftPackage2003() + [Flippable(0x232A, 0x232B)] + public class WinterGiftPackage2003 : GiftBox { - DropItem(new Snowman()); - DropItem(new WreathDeed()); - DropItem(new BlueSnowflake()); - DropItem(new RedPoinsettia()); + [Constructible] + public WinterGiftPackage2003() + { + DropItem(new Snowman()); + DropItem(new WreathDeed()); + DropItem(new BlueSnowflake()); + DropItem(new RedPoinsettia()); + } + + public WinterGiftPackage2003(Serial serial) : base(serial) + { + } + + 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 WinterGiftPackage2003(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Holiday/Wreath.cs b/Projects/UOContent/Items/Special/Holiday/Wreath.cs index d664c2521..f04bc87d9 100644 --- a/Projects/UOContent/Items/Special/Holiday/Wreath.cs +++ b/Projects/UOContent/Items/Special/Holiday/Wreath.cs @@ -5,311 +5,311 @@ using Server.Targeting; namespace Server.Items { - public class WreathAddon : Item, IDyable, IAddon - { - [Constructible] - public WreathAddon() : this(Utility.RandomDyedHue()) + public class WreathAddon : Item, IDyable, IAddon { - } - - [Constructible] - public WreathAddon(int hue) : base(0x232C) - { - Hue = hue; - Movable = false; - } - - public WreathAddon(Serial serial) : base(serial) - { - } - - public bool CouldFit(IPoint3D p, Map map) - { - if (!map.CanFit(p.X, p.Y, p.Z, ItemData.Height)) - return false; - - if (ItemID == 0x232C) - return BaseAddon.IsWall(p.X, p.Y - 1, p.Z, map); // North wall - return BaseAddon.IsWall(p.X - 1, p.Y, p.Z, map); // West wall - } - - public Item Deed => new WreathDeed(Hue); - - public virtual bool Dye(Mobile from, DyeTub sender) - { - if (Deleted) - return false; - - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (house?.IsCoOwner(from) == true) - { - if (from.InRange(GetWorldLocation(), 1)) + [Constructible] + public WreathAddon() : this(Utility.RandomDyedHue()) { - Hue = sender.DyedHue; - return true; } - from.SendLocalizedMessage(500295); // You are too far away to do that. - return false; - } - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Timer.DelayCall(FixMovingCrate); - } - - private void FixMovingCrate() - { - if (Deleted) - return; - - if (Movable || IsLockedDown) - { - Item deed = Deed; - - if (Parent is Item item) + [Constructible] + public WreathAddon(int hue) : base(0x232C) { - item.AddItem(deed); - deed.Location = Location; - } - else - { - deed.MoveToWorld(Location, Map); + Hue = hue; + Movable = false; } - Delete(); - } - } - - public override void OnDoubleClick(Mobile from) - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (house?.IsCoOwner(from) == true) - { - if (from.InRange(GetWorldLocation(), 3)) + public WreathAddon(Serial serial) : base(serial) { - from.CloseGump(); - from.SendGump(new WreathAddonGump(from, this)); } - else + + public bool CouldFit(IPoint3D p, Map map) { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + if (!map.CanFit(p.X, p.Y, p.Z, ItemData.Height)) + return false; + + if (ItemID == 0x232C) + return BaseAddon.IsWall(p.X, p.Y - 1, p.Z, map); // North wall + return BaseAddon.IsWall(p.X - 1, p.Y, p.Z, map); // West wall } - } - } - private class WreathAddonGump : Gump - { - private readonly WreathAddon m_Addon; - private readonly Mobile m_From; + public Item Deed => new WreathDeed(Hue); - public WreathAddonGump(Mobile from, WreathAddon addon) : base(150, 50) - { - m_From = from; - m_Addon = addon; - - AddPage(0); - - AddBackground(0, 0, 220, 170, 0x13BE); - AddBackground(10, 10, 200, 150, 0xBB8); - AddHtmlLocalized(20, 30, 180, 60, 1062839); // Do you wish to re-deed this decoration? - AddHtmlLocalized(55, 100, 160, 25, 1011011); // CONTINUE - AddButton(20, 100, 0xFA5, 0xFA7, 1); - AddHtmlLocalized(55, 125, 160, 25, 1011012); // CANCEL - AddButton(20, 125, 0xFA5, 0xFA7, 0); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Addon.Deleted) - return; - - if (info.ButtonID == 1) + public virtual bool Dye(Mobile from, DyeTub sender) { - if (m_From.InRange(m_Addon.GetWorldLocation(), 3)) - { - m_From.AddToBackpack(m_Addon.Deed); - m_Addon.Delete(); - } - else - { - m_From.SendLocalizedMessage(500295); // You are too far away to do that. - } + if (Deleted) + return false; + + var house = BaseHouse.FindHouseAt(this); + + if (house?.IsCoOwner(from) == true) + { + if (from.InRange(GetWorldLocation(), 1)) + { + Hue = sender.DyedHue; + return true; + } + + from.SendLocalizedMessage(500295); // You are too far away to do that. + return false; + } + + return false; } - } - } - } - [Flippable(0x14F0, 0x14EF)] - public class WreathDeed : Item - { - [Constructible] - public WreathDeed() : this(Utility.RandomDyedHue()) - { - } - - [Constructible] - public WreathDeed(int hue) : base(0x14F0) - { - Weight = 1.0; - Hue = hue; - LootType = LootType.Blessed; - } - - public WreathDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1062837; // holiday wreath deed - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - BaseHouse house = BaseHouse.FindHouseAt(from); - - if (house?.IsCoOwner(from) == true) + public override void Serialize(IGenericWriter writer) { - from.SendLocalizedMessage(1062838); // Where would you like to place this decoration? - from.BeginTarget(-1, true, TargetFlags.None, Placement_OnTarget); + base.Serialize(writer); + + writer.Write(0); // version } - else + + public override void Deserialize(IGenericReader reader) { - from.SendLocalizedMessage(502092); // You must be in your house to do this. + base.Deserialize(reader); + + var version = reader.ReadInt(); + + Timer.DelayCall(FixMovingCrate); } - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - public void Placement_OnTarget(Mobile from, object targeted) - { - if (!(targeted is IPoint3D p)) - return; - - Point3D loc = new Point3D(p); - - BaseHouse house = BaseHouse.FindHouseAt(loc, from.Map, 16); - - if (house?.IsCoOwner(from) == true) - { - bool northWall = BaseAddon.IsWall(loc.X, loc.Y - 1, loc.Z, from.Map); - bool westWall = BaseAddon.IsWall(loc.X - 1, loc.Y, loc.Z, from.Map); - - if (northWall && westWall) - from.SendGump(new WreathDeedGump(from, loc, this)); - else - PlaceAddon(from, loc, northWall, westWall); - } - else - { - from.SendLocalizedMessage(1042036); // That location is not in your house. - } - } - - private void PlaceAddon(Mobile from, Point3D loc, bool northWall, bool westWall) - { - if (Deleted) - return; - - BaseHouse house = BaseHouse.FindHouseAt(loc, from.Map, 16); - - if (house?.IsCoOwner(from) != true) - { - from.SendLocalizedMessage(1042036); // That location is not in your house. - return; - } - - int itemID = 0; - - if (northWall) - itemID = 0x232C; - else if (westWall) - itemID = 0x232D; - else - from.SendLocalizedMessage(1062840); // The decoration must be placed next to a wall. - - if (itemID > 0) - { - Item addon = new WreathAddon(Hue); - - addon.ItemID = itemID; - addon.MoveToWorld(loc, from.Map); - - house.Addons.Add(addon); - Delete(); - } - } - - private class WreathDeedGump : Gump - { - private readonly WreathDeed m_Deed; - private readonly Mobile m_From; - private readonly Point3D m_Loc; - - public WreathDeedGump(Mobile from, Point3D loc, WreathDeed deed) : base(150, 50) - { - m_From = from; - m_Loc = loc; - m_Deed = deed; - - AddBackground(0, 0, 300, 150, 0xA28); - - AddPage(0); - - AddItem(90, 30, 0x232D); - AddItem(180, 30, 0x232C); - AddButton(50, 35, 0x868, 0x869, 1); - AddButton(145, 35, 0x868, 0x869, 2); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Deed.Deleted) - return; - - switch (info.ButtonID) + private void FixMovingCrate() { - case 1: - m_Deed.PlaceAddon(m_From, m_Loc, false, true); - break; - case 2: - m_Deed.PlaceAddon(m_From, m_Loc, true, false); - break; + if (Deleted) + return; + + if (Movable || IsLockedDown) + { + var deed = Deed; + + if (Parent is Item item) + { + item.AddItem(deed); + deed.Location = Location; + } + else + { + deed.MoveToWorld(Location, Map); + } + + Delete(); + } + } + + public override void OnDoubleClick(Mobile from) + { + var house = BaseHouse.FindHouseAt(this); + + if (house?.IsCoOwner(from) == true) + { + if (from.InRange(GetWorldLocation(), 3)) + { + from.CloseGump(); + from.SendGump(new WreathAddonGump(from, this)); + } + else + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + } + } + + private class WreathAddonGump : Gump + { + private readonly WreathAddon m_Addon; + private readonly Mobile m_From; + + public WreathAddonGump(Mobile from, WreathAddon addon) : base(150, 50) + { + m_From = from; + m_Addon = addon; + + AddPage(0); + + AddBackground(0, 0, 220, 170, 0x13BE); + AddBackground(10, 10, 200, 150, 0xBB8); + AddHtmlLocalized(20, 30, 180, 60, 1062839); // Do you wish to re-deed this decoration? + AddHtmlLocalized(55, 100, 160, 25, 1011011); // CONTINUE + AddButton(20, 100, 0xFA5, 0xFA7, 1); + AddHtmlLocalized(55, 125, 160, 25, 1011012); // CANCEL + AddButton(20, 125, 0xFA5, 0xFA7, 0); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Addon.Deleted) + return; + + if (info.ButtonID == 1) + { + if (m_From.InRange(m_Addon.GetWorldLocation(), 3)) + { + m_From.AddToBackpack(m_Addon.Deed); + m_Addon.Delete(); + } + else + { + m_From.SendLocalizedMessage(500295); // You are too far away to do that. + } + } + } + } + } + + [Flippable(0x14F0, 0x14EF)] + public class WreathDeed : Item + { + [Constructible] + public WreathDeed() : this(Utility.RandomDyedHue()) + { + } + + [Constructible] + public WreathDeed(int hue) : base(0x14F0) + { + Weight = 1.0; + Hue = hue; + LootType = LootType.Blessed; + } + + public WreathDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1062837; // holiday wreath deed + + 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 (IsChildOf(from.Backpack)) + { + var house = BaseHouse.FindHouseAt(from); + + if (house?.IsCoOwner(from) == true) + { + from.SendLocalizedMessage(1062838); // Where would you like to place this decoration? + from.BeginTarget(-1, true, TargetFlags.None, Placement_OnTarget); + } + else + { + from.SendLocalizedMessage(502092); // You must be in your house to do this. + } + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + + public void Placement_OnTarget(Mobile from, object targeted) + { + if (!(targeted is IPoint3D p)) + return; + + var loc = new Point3D(p); + + var house = BaseHouse.FindHouseAt(loc, from.Map, 16); + + if (house?.IsCoOwner(from) == true) + { + var northWall = BaseAddon.IsWall(loc.X, loc.Y - 1, loc.Z, from.Map); + var westWall = BaseAddon.IsWall(loc.X - 1, loc.Y, loc.Z, from.Map); + + if (northWall && westWall) + from.SendGump(new WreathDeedGump(from, loc, this)); + else + PlaceAddon(from, loc, northWall, westWall); + } + else + { + from.SendLocalizedMessage(1042036); // That location is not in your house. + } + } + + private void PlaceAddon(Mobile from, Point3D loc, bool northWall, bool westWall) + { + if (Deleted) + return; + + var house = BaseHouse.FindHouseAt(loc, from.Map, 16); + + if (house?.IsCoOwner(from) != true) + { + from.SendLocalizedMessage(1042036); // That location is not in your house. + return; + } + + var itemID = 0; + + if (northWall) + itemID = 0x232C; + else if (westWall) + itemID = 0x232D; + else + from.SendLocalizedMessage(1062840); // The decoration must be placed next to a wall. + + if (itemID > 0) + { + Item addon = new WreathAddon(Hue); + + addon.ItemID = itemID; + addon.MoveToWorld(loc, from.Map); + + house.Addons.Add(addon); + Delete(); + } + } + + private class WreathDeedGump : Gump + { + private readonly WreathDeed m_Deed; + private readonly Mobile m_From; + private readonly Point3D m_Loc; + + public WreathDeedGump(Mobile from, Point3D loc, WreathDeed deed) : base(150, 50) + { + m_From = from; + m_Loc = loc; + m_Deed = deed; + + AddBackground(0, 0, 300, 150, 0xA28); + + AddPage(0); + + AddItem(90, 30, 0x232D); + AddItem(180, 30, 0x232C); + AddButton(50, 35, 0x868, 0x869, 1); + AddButton(145, 35, 0x868, 0x869, 2); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Deed.Deleted) + return; + + switch (info.ButtonID) + { + case 1: + m_Deed.PlaceAddon(m_From, m_Loc, false, true); + break; + case 2: + m_Deed.PlaceAddon(m_From, m_Loc, true, false); + break; + } + } } - } } - } } diff --git a/Projects/UOContent/Items/Special/Holiday/WristWatch.cs b/Projects/UOContent/Items/Special/Holiday/WristWatch.cs index 7bc205b19..da2014b44 100644 --- a/Projects/UOContent/Items/Special/Holiday/WristWatch.cs +++ b/Projects/UOContent/Items/Special/Holiday/WristWatch.cs @@ -1,36 +1,36 @@ namespace Server.Items { - public class WristWatch : Clock - { - [Constructible] - public WristWatch() - : base(0x1086) + public class WristWatch : Clock { - Weight = DefaultWeight; - LootType = LootType.Blessed; - Layer = Layer.Bracelet; + [Constructible] + public WristWatch() + : base(0x1086) + { + Weight = DefaultWeight; + LootType = LootType.Blessed; + Layer = Layer.Bracelet; + } + + public WristWatch(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1041421; // a wrist watch + public override double DefaultWeight => 1.0; + + 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 WristWatch(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1041421; // a wrist watch - public override double DefaultWeight => 1.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/House Raffle/HouseRaffleDeed.cs b/Projects/UOContent/Items/Special/House Raffle/HouseRaffleDeed.cs index 95dee26e8..80c7bf888 100644 --- a/Projects/UOContent/Items/Special/House Raffle/HouseRaffleDeed.cs +++ b/Projects/UOContent/Items/Special/House Raffle/HouseRaffleDeed.cs @@ -3,200 +3,205 @@ using Server.Gumps; namespace Server.Items { - public class HouseRaffleDeed : Item - { - private Mobile m_AwardedTo; - private Map m_Facet; - private Point3D m_PlotLocation; - private HouseRaffleStone m_Stone; - - [Constructible] - public HouseRaffleDeed(HouseRaffleStone stone = null, Mobile m = null) : base(0x2830) + public class HouseRaffleDeed : Item { - m_Stone = stone; + private Mobile m_AwardedTo; + private Map m_Facet; + private Point3D m_PlotLocation; + private HouseRaffleStone m_Stone; - if (stone != null) - { - m_PlotLocation = stone.GetPlotCenter(); - m_Facet = stone.PlotFacet; - } + [Constructible] + public HouseRaffleDeed(HouseRaffleStone stone = null, Mobile m = null) : base(0x2830) + { + m_Stone = stone; - m_AwardedTo = m; + if (stone != null) + { + m_PlotLocation = stone.GetPlotCenter(); + m_Facet = stone.PlotFacet; + } - LootType = LootType.Blessed; - Hue = 0x501; + m_AwardedTo = m; + + LootType = LootType.Blessed; + Hue = 0x501; + } + + public HouseRaffleDeed(Serial serial) + : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] + public HouseRaffleStone Stone + { + get => m_Stone; + set + { + m_Stone = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] + public Point3D PlotLocation + { + get => m_PlotLocation; + set + { + m_PlotLocation = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] + public Map PlotFacet + { + get => m_Facet; + set + { + m_Facet = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] + public Mobile AwardedTo + { + get => m_AwardedTo; + set + { + m_AwardedTo = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] + public bool IsExpired => m_Stone?.Deleted != false || m_Stone.IsExpired; + + public override string DefaultName => "a writ of lease"; + + public override double DefaultWeight => 1.0; + + public bool ValidLocation() => m_PlotLocation != Point3D.Zero && m_Facet != null && m_Facet != Map.Internal; + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (ValidLocation()) + { + list.Add( + 1060658, + "location\t{0}", + HouseRaffleStone.FormatLocation(m_PlotLocation, m_Facet, false) + ); // ~1_val~: ~2_val~ + list.Add(1060659, "facet\t{0}", m_Facet); // ~1_val~: ~2_val~ + list.Add(1150486); // [Marked Item] + } + + if (IsExpired) + list.Add(1150487); // [Expired] + + // list.Add( 1060660, "shard\t{0}", ServerList.ServerName ); // ~1_val~: ~2_val~ + } + + public override void OnDoubleClick(Mobile from) + { + if (!ValidLocation()) + return; + + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new WritOfLeaseGump(this)); + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(m_Stone); + writer.Write(m_PlotLocation); + writer.Write(m_Facet); + writer.Write(m_AwardedTo); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_Stone = reader.ReadItem(); + + goto case 0; + } + case 0: + { + m_PlotLocation = reader.ReadPoint3D(); + m_Facet = reader.ReadMap(); + m_AwardedTo = reader.ReadMobile(); + + break; + } + } + } + + private class WritOfLeaseGump : Gump + { + public WritOfLeaseGump(HouseRaffleDeed deed) : base(150, 50) + { + AddPage(0); + + AddImage(0, 0, 9380); + AddImage(114, 0, 9381); + AddImage(171, 0, 9382); + AddImage(0, 140, 9383); + AddImage(114, 140, 9384); + AddImage(171, 140, 9385); + AddImage(0, 182, 9383); + AddImage(114, 182, 9384); + AddImage(171, 182, 9385); + AddImage(0, 224, 9383); + AddImage(114, 224, 9384); + AddImage(171, 224, 9385); + AddImage(0, 266, 9386); + AddImage(114, 266, 9387); + AddImage(171, 266, 9388); + + AddHtmlLocalized(30, 48, 229, 20, 1150484, 200); // WRIT OF LEASE + AddHtml(28, 75, 231, 280, FormatDescription(deed), false, true); + } + + private static string FormatDescription(HouseRaffleDeed deed) + { + if (deed == null) + return string.Empty; + + if (deed.IsExpired) + return + $"This deed once entitled the bearer to build a house on the plot of land located at {HouseRaffleStone.FormatLocation(deed.PlotLocation, deed.PlotFacet, false)} on the {deed.PlotFacet} facet.

The deed has expired, and now the indicated plot of land is subject to normal house construction rules.

This deed functions as a recall rune marked for the location of the plot it represents.
"; + + var daysLeft = (int)Math.Ceiling( + (deed.Stone.Started + deed.Stone.Duration + + HouseRaffleStone.ExpirationTime - DateTime.UtcNow).TotalDays + ); + + return + $"This deed entitles the bearer to build a house on the plot of land located at {HouseRaffleStone.FormatLocation(deed.PlotLocation, deed.PlotFacet, false)} on the {deed.PlotFacet} facet.

The deed will expire after {daysLeft} more day{(daysLeft == 1 ? "" : "s")} have passed, and at that time the right to place a house reverts to normal house construction rules.

This deed functions as a recall rune marked for the location of the plot it represents.

To place a house on the deeded plot, you must simply have this deed in your backpack or bank box when using a House Placement Tool there.
"; + } + } } - - public HouseRaffleDeed(Serial serial) - : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] - public HouseRaffleStone Stone - { - get => m_Stone; - set - { - m_Stone = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] - public Point3D PlotLocation - { - get => m_PlotLocation; - set - { - m_PlotLocation = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] - public Map PlotFacet - { - get => m_Facet; - set - { - m_Facet = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] - public Mobile AwardedTo - { - get => m_AwardedTo; - set - { - m_AwardedTo = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] - public bool IsExpired => m_Stone?.Deleted != false || m_Stone.IsExpired; - - public override string DefaultName => "a writ of lease"; - - public override double DefaultWeight => 1.0; - - public bool ValidLocation() => m_PlotLocation != Point3D.Zero && m_Facet != null && m_Facet != Map.Internal; - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (ValidLocation()) - { - list.Add(1060658, "location\t{0}", - HouseRaffleStone.FormatLocation(m_PlotLocation, m_Facet, false)); // ~1_val~: ~2_val~ - list.Add(1060659, "facet\t{0}", m_Facet); // ~1_val~: ~2_val~ - list.Add(1150486); // [Marked Item] - } - - if (IsExpired) - list.Add(1150487); // [Expired] - - // list.Add( 1060660, "shard\t{0}", ServerList.ServerName ); // ~1_val~: ~2_val~ - } - - public override void OnDoubleClick(Mobile from) - { - if (!ValidLocation()) - return; - - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new WritOfLeaseGump(this)); - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(m_Stone); - writer.Write(m_PlotLocation); - writer.Write(m_Facet); - writer.Write(m_AwardedTo); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_Stone = reader.ReadItem(); - - goto case 0; - } - case 0: - { - m_PlotLocation = reader.ReadPoint3D(); - m_Facet = reader.ReadMap(); - m_AwardedTo = reader.ReadMobile(); - - break; - } - } - } - - private class WritOfLeaseGump : Gump - { - public WritOfLeaseGump(HouseRaffleDeed deed) : base(150, 50) - { - AddPage(0); - - AddImage(0, 0, 9380); - AddImage(114, 0, 9381); - AddImage(171, 0, 9382); - AddImage(0, 140, 9383); - AddImage(114, 140, 9384); - AddImage(171, 140, 9385); - AddImage(0, 182, 9383); - AddImage(114, 182, 9384); - AddImage(171, 182, 9385); - AddImage(0, 224, 9383); - AddImage(114, 224, 9384); - AddImage(171, 224, 9385); - AddImage(0, 266, 9386); - AddImage(114, 266, 9387); - AddImage(171, 266, 9388); - - AddHtmlLocalized(30, 48, 229, 20, 1150484, 200); // WRIT OF LEASE - AddHtml(28, 75, 231, 280, FormatDescription(deed), false, true); - } - - private static string FormatDescription(HouseRaffleDeed deed) - { - if (deed == null) - return string.Empty; - - if (deed.IsExpired) - return - $"This deed once entitled the bearer to build a house on the plot of land located at {HouseRaffleStone.FormatLocation(deed.PlotLocation, deed.PlotFacet, false)} on the {deed.PlotFacet} facet.

The deed has expired, and now the indicated plot of land is subject to normal house construction rules.

This deed functions as a recall rune marked for the location of the plot it represents.
"; - - int daysLeft = (int)Math.Ceiling((deed.Stone.Started + deed.Stone.Duration + - HouseRaffleStone.ExpirationTime - DateTime.UtcNow).TotalDays); - - return - $"This deed entitles the bearer to build a house on the plot of land located at {HouseRaffleStone.FormatLocation(deed.PlotLocation, deed.PlotFacet, false)} on the {deed.PlotFacet} facet.

The deed will expire after {daysLeft} more day{(daysLeft == 1 ? "" : "s")} have passed, and at that time the right to place a house reverts to normal house construction rules.

This deed functions as a recall rune marked for the location of the plot it represents.

To place a house on the deeded plot, you must simply have this deed in your backpack or bank box when using a House Placement Tool there.
"; - } - } - } } diff --git a/Projects/UOContent/Items/Special/House Raffle/HouseRaffleManagementGump.cs b/Projects/UOContent/Items/Special/House Raffle/HouseRaffleManagementGump.cs index f9dee4eb0..5e30a5dc9 100644 --- a/Projects/UOContent/Items/Special/House Raffle/HouseRaffleManagementGump.cs +++ b/Projects/UOContent/Items/Special/House Raffle/HouseRaffleManagementGump.cs @@ -5,296 +5,298 @@ using Server.Network; namespace Server.Gumps { - public class HouseRaffleManagementGump : Gump - { - public enum SortMethod + public class HouseRaffleManagementGump : Gump { - Default, - Name, - Account, - Address - } - - public const int LabelColor = 0xFFFFFF; - public const int HighlightColor = 0x11EE11; - private readonly List m_List; - private int m_Page; - private readonly SortMethod m_Sort; - - private readonly HouseRaffleStone m_Stone; - - public HouseRaffleManagementGump(HouseRaffleStone stone, SortMethod sort = SortMethod.Default, - int page = 0) : base(40, 40) - { - m_Stone = stone; - m_Page = page; - - m_List = new List(m_Stone.Entries); - m_Sort = sort; - - switch (m_Sort) - { - case SortMethod.Name: - { - m_List.Sort(NameComparer.Instance); - - break; - } - case SortMethod.Account: - { - m_List.Sort(AccountComparer.Instance); - - break; - } - case SortMethod.Address: - { - m_List.Sort(AddressComparer.Instance); - - break; - } - } - - AddPage(0); - - AddBackground(0, 0, 618, 354, 9270); - AddAlphaRegion(10, 10, 598, 334); - - AddHtml(10, 10, 598, 20, Color(Center("Raffle Management"), LabelColor)); - - AddHtml(45, 35, 100, 20, Color("Location:", LabelColor)); - AddHtml(145, 35, 250, 20, Color(m_Stone.FormatLocation(), LabelColor)); - - AddHtml(45, 55, 100, 20, Color("Ticket Price:", LabelColor)); - AddHtml(145, 55, 250, 20, Color(m_Stone.FormatPrice(), LabelColor)); - - AddHtml(45, 75, 100, 20, Color("Total Entries:", LabelColor)); - AddHtml(145, 75, 250, 20, Color(m_Stone.Entries.Count.ToString(), LabelColor)); - - AddButton(440, 33, 0xFA5, 0xFA7, 3); - AddHtml(474, 35, 120, 20, Color("Sort by name", LabelColor)); - - AddButton(440, 53, 0xFA5, 0xFA7, 4); - AddHtml(474, 55, 120, 20, Color("Sort by account", LabelColor)); - - AddButton(440, 73, 0xFA5, 0xFA7, 5); - AddHtml(474, 75, 120, 20, Color("Sort by address", LabelColor)); - - AddImageTiled(13, 99, 592, 242, 9264); - AddImageTiled(14, 100, 590, 240, 9274); - AddAlphaRegion(14, 100, 590, 240); - - AddHtml(14, 100, 590, 20, Color(Center("Entries"), LabelColor)); - - if (page > 0) - AddButton(567, 104, 0x15E3, 0x15E7, 1); - else - AddImage(567, 104, 0x25EA); - - if ((page + 1) * 10 < m_List.Count) - AddButton(584, 104, 0x15E1, 0x15E5, 2); - else - AddImage(584, 104, 0x25E6); - - AddHtml(14, 120, 30, 20, Color(Center("DEL"), LabelColor)); - AddHtml(47, 120, 250, 20, Color("Name", LabelColor)); - AddHtml(295, 120, 100, 20, Color(Center("Address"), LabelColor)); - AddHtml(395, 120, 150, 20, Color(Center("Date"), LabelColor)); - AddHtml(545, 120, 60, 20, Color(Center("Num"), LabelColor)); - - int idx = 0; - Mobile winner = m_Stone.Winner; - - for (int i = page * 10; i >= 0 && i < m_List.Count && i < (page + 1) * 10; ++i, ++idx) - { - RaffleEntry entry = m_List[i]; - - if (entry == null) - continue; - - AddButton(13, 138 + idx * 20, 4002, 4004, 6 + i); - - int x = 45; - int color = winner != null && entry.From == winner ? HighlightColor : LabelColor; - - string name = null; - - if (entry.From != null) + public enum SortMethod { - if (entry.From.Account is Account acc) - name = $"{entry.From.Name} ({acc})"; - else - name = entry.From.Name; + Default, + Name, + Account, + Address } - if (name != null) - AddHtml(x + 2, 140 + idx * 20, 250, 20, Color(name, color)); + public const int LabelColor = 0xFFFFFF; + public const int HighlightColor = 0x11EE11; + private readonly List m_List; + private readonly SortMethod m_Sort; - x += 250; + private readonly HouseRaffleStone m_Stone; + private int m_Page; - if (entry.Address != null) - AddHtml(x, 140 + idx * 20, 100, 20, Color(Center(entry.Address.ToString()), color)); + public HouseRaffleManagementGump( + HouseRaffleStone stone, SortMethod sort = SortMethod.Default, + int page = 0 + ) : base(40, 40) + { + m_Stone = stone; + m_Page = page; - x += 100; + m_List = new List(m_Stone.Entries); + m_Sort = sort; - AddHtml(x, 140 + idx * 20, 150, 20, Color(Center(entry.Date.ToString()), color)); - x += 150; - - AddHtml(x, 140 + idx * 20, 60, 20, Color(Center("1"), color)); - x += 60; - } - } - - public string Right(string text) => $"
{text}
"; - - public string Center(string text) => $"
{text}
"; - - public string Color(string text, int color) => $"{text}"; - - public override void OnResponse(NetState sender, RelayInfo info) - { - Mobile from = sender.Mobile; - int buttonId = info.ButtonID; - - switch (buttonId) - { - case 1: // Previous - { - if (m_Page > 0) - m_Page--; - - from.SendGump(new HouseRaffleManagementGump(m_Stone, m_Sort, m_Page)); - - break; - } - case 2: // Next - { - if ((m_Page + 1) * 10 < m_Stone.Entries.Count) - m_Page++; - - from.SendGump(new HouseRaffleManagementGump(m_Stone, m_Sort, m_Page)); - - break; - } - case 3: // Sort by name - { - from.SendGump(new HouseRaffleManagementGump(m_Stone, SortMethod.Name)); - - break; - } - case 4: // Sort by account - { - from.SendGump(new HouseRaffleManagementGump(m_Stone, SortMethod.Account)); - - break; - } - case 5: // Sort by address - { - from.SendGump(new HouseRaffleManagementGump(m_Stone, SortMethod.Address)); - - break; - } - default: // Delete - { - buttonId -= 6; - - if (buttonId >= 0 && buttonId < m_List.Count) + switch (m_Sort) { - m_Stone.Entries.Remove(m_List[buttonId]); + case SortMethod.Name: + { + m_List.Sort(NameComparer.Instance); - if (m_Page > 0 && m_Page * 10 >= m_List.Count - 1) - m_Page--; + break; + } + case SortMethod.Account: + { + m_List.Sort(AccountComparer.Instance); - from.SendGump(new HouseRaffleManagementGump(m_Stone, m_Sort, m_Page)); + break; + } + case SortMethod.Address: + { + m_List.Sort(AddressComparer.Instance); + + break; + } } - break; - } - } - } + AddPage(0); - private class NameComparer : IComparer - { - public static readonly IComparer Instance = new NameComparer(); + AddBackground(0, 0, 618, 354, 9270); + AddAlphaRegion(10, 10, 598, 334); - public int Compare(RaffleEntry x, RaffleEntry y) - { - bool xIsNull = x?.From == null; - bool yIsNull = y?.From == null; + AddHtml(10, 10, 598, 20, Color(Center("Raffle Management"), LabelColor)); - if (xIsNull && yIsNull) - return 0; - if (xIsNull) - return -1; - if (yIsNull) - return 1; + AddHtml(45, 35, 100, 20, Color("Location:", LabelColor)); + AddHtml(145, 35, 250, 20, Color(m_Stone.FormatLocation(), LabelColor)); - int result = Insensitive.Compare(x.From.Name, y.From.Name); + AddHtml(45, 55, 100, 20, Color("Ticket Price:", LabelColor)); + AddHtml(145, 55, 250, 20, Color(m_Stone.FormatPrice(), LabelColor)); - return result == 0 ? x.Date.CompareTo(y.Date) : result; - } - } + AddHtml(45, 75, 100, 20, Color("Total Entries:", LabelColor)); + AddHtml(145, 75, 250, 20, Color(m_Stone.Entries.Count.ToString(), LabelColor)); - private class AccountComparer : IComparer - { - public static readonly IComparer Instance = new AccountComparer(); + AddButton(440, 33, 0xFA5, 0xFA7, 3); + AddHtml(474, 35, 120, 20, Color("Sort by name", LabelColor)); - public int Compare(RaffleEntry x, RaffleEntry y) - { - bool xIsNull = x?.From == null; - bool yIsNull = y?.From == null; + AddButton(440, 53, 0xFA5, 0xFA7, 4); + AddHtml(474, 55, 120, 20, Color("Sort by account", LabelColor)); - if (xIsNull && yIsNull) - return 0; - if (xIsNull) - return -1; - if (yIsNull) - return 1; + AddButton(440, 73, 0xFA5, 0xFA7, 5); + AddHtml(474, 75, 120, 20, Color("Sort by address", LabelColor)); - Account a = x.From.Account as Account; - Account b = y.From.Account as Account; + AddImageTiled(13, 99, 592, 242, 9264); + AddImageTiled(14, 100, 590, 240, 9274); + AddAlphaRegion(14, 100, 590, 240); - if (a == null && b == null) - return 0; - if (a == null) - return -1; - if (b == null) - return 1; + AddHtml(14, 100, 590, 20, Color(Center("Entries"), LabelColor)); - int result = Insensitive.Compare(a.Username, b.Username); + if (page > 0) + AddButton(567, 104, 0x15E3, 0x15E7, 1); + else + AddImage(567, 104, 0x25EA); - return result == 0 ? x.Date.CompareTo(y.Date) : result; - } - } + if ((page + 1) * 10 < m_List.Count) + AddButton(584, 104, 0x15E1, 0x15E5, 2); + else + AddImage(584, 104, 0x25E6); - private class AddressComparer : IComparer - { - public static readonly IComparer Instance = new AddressComparer(); + AddHtml(14, 120, 30, 20, Color(Center("DEL"), LabelColor)); + AddHtml(47, 120, 250, 20, Color("Name", LabelColor)); + AddHtml(295, 120, 100, 20, Color(Center("Address"), LabelColor)); + AddHtml(395, 120, 150, 20, Color(Center("Date"), LabelColor)); + AddHtml(545, 120, 60, 20, Color(Center("Num"), LabelColor)); - public int Compare(RaffleEntry x, RaffleEntry y) - { - bool xIsNull = x?.Address == null; - bool yIsNull = y?.Address == null; + var idx = 0; + var winner = m_Stone.Winner; - if (xIsNull && yIsNull) - return 0; - if (xIsNull) - return -1; - if (yIsNull) - return 1; + for (var i = page * 10; i >= 0 && i < m_List.Count && i < (page + 1) * 10; ++i, ++idx) + { + var entry = m_List[i]; - byte[] a = x.Address.GetAddressBytes(); - byte[] b = y.Address.GetAddressBytes(); + if (entry == null) + continue; - for (int i = 0; i < a.Length && i < b.Length; i++) - { - int compare = a[i].CompareTo(b[i]); + AddButton(13, 138 + idx * 20, 4002, 4004, 6 + i); - if (compare != 0) - return compare; + var x = 45; + var color = winner != null && entry.From == winner ? HighlightColor : LabelColor; + + string name = null; + + if (entry.From != null) + { + if (entry.From.Account is Account acc) + name = $"{entry.From.Name} ({acc})"; + else + name = entry.From.Name; + } + + if (name != null) + AddHtml(x + 2, 140 + idx * 20, 250, 20, Color(name, color)); + + x += 250; + + if (entry.Address != null) + AddHtml(x, 140 + idx * 20, 100, 20, Color(Center(entry.Address.ToString()), color)); + + x += 100; + + AddHtml(x, 140 + idx * 20, 150, 20, Color(Center(entry.Date.ToString()), color)); + x += 150; + + AddHtml(x, 140 + idx * 20, 60, 20, Color(Center("1"), color)); + x += 60; + } } - return x.Date.CompareTo(y.Date); - } + public string Right(string text) => $"
{text}
"; + + public string Center(string text) => $"
{text}
"; + + public string Color(string text, int color) => $"{text}"; + + public override void OnResponse(NetState sender, RelayInfo info) + { + var from = sender.Mobile; + var buttonId = info.ButtonID; + + switch (buttonId) + { + case 1: // Previous + { + if (m_Page > 0) + m_Page--; + + from.SendGump(new HouseRaffleManagementGump(m_Stone, m_Sort, m_Page)); + + break; + } + case 2: // Next + { + if ((m_Page + 1) * 10 < m_Stone.Entries.Count) + m_Page++; + + from.SendGump(new HouseRaffleManagementGump(m_Stone, m_Sort, m_Page)); + + break; + } + case 3: // Sort by name + { + from.SendGump(new HouseRaffleManagementGump(m_Stone, SortMethod.Name)); + + break; + } + case 4: // Sort by account + { + from.SendGump(new HouseRaffleManagementGump(m_Stone, SortMethod.Account)); + + break; + } + case 5: // Sort by address + { + from.SendGump(new HouseRaffleManagementGump(m_Stone, SortMethod.Address)); + + break; + } + default: // Delete + { + buttonId -= 6; + + if (buttonId >= 0 && buttonId < m_List.Count) + { + m_Stone.Entries.Remove(m_List[buttonId]); + + if (m_Page > 0 && m_Page * 10 >= m_List.Count - 1) + m_Page--; + + from.SendGump(new HouseRaffleManagementGump(m_Stone, m_Sort, m_Page)); + } + + break; + } + } + } + + private class NameComparer : IComparer + { + public static readonly IComparer Instance = new NameComparer(); + + public int Compare(RaffleEntry x, RaffleEntry y) + { + var xIsNull = x?.From == null; + var yIsNull = y?.From == null; + + if (xIsNull && yIsNull) + return 0; + if (xIsNull) + return -1; + if (yIsNull) + return 1; + + var result = Insensitive.Compare(x.From.Name, y.From.Name); + + return result == 0 ? x.Date.CompareTo(y.Date) : result; + } + } + + private class AccountComparer : IComparer + { + public static readonly IComparer Instance = new AccountComparer(); + + public int Compare(RaffleEntry x, RaffleEntry y) + { + var xIsNull = x?.From == null; + var yIsNull = y?.From == null; + + if (xIsNull && yIsNull) + return 0; + if (xIsNull) + return -1; + if (yIsNull) + return 1; + + var a = x.From.Account as Account; + var b = y.From.Account as Account; + + if (a == null && b == null) + return 0; + if (a == null) + return -1; + if (b == null) + return 1; + + var result = Insensitive.Compare(a.Username, b.Username); + + return result == 0 ? x.Date.CompareTo(y.Date) : result; + } + } + + private class AddressComparer : IComparer + { + public static readonly IComparer Instance = new AddressComparer(); + + public int Compare(RaffleEntry x, RaffleEntry y) + { + var xIsNull = x?.Address == null; + var yIsNull = y?.Address == null; + + if (xIsNull && yIsNull) + return 0; + if (xIsNull) + return -1; + if (yIsNull) + return 1; + + var a = x.Address.GetAddressBytes(); + var b = y.Address.GetAddressBytes(); + + for (var i = 0; i < a.Length && i < b.Length; i++) + { + var compare = a[i].CompareTo(b[i]); + + if (compare != 0) + return compare; + } + + return x.Date.CompareTo(y.Date); + } + } } - } } diff --git a/Projects/UOContent/Items/Special/House Raffle/HouseRaffleRegion.cs b/Projects/UOContent/Items/Special/House Raffle/HouseRaffleRegion.cs index 2af3b9096..5cde8b8c9 100644 --- a/Projects/UOContent/Items/Special/House Raffle/HouseRaffleRegion.cs +++ b/Projects/UOContent/Items/Special/House Raffle/HouseRaffleRegion.cs @@ -5,49 +5,49 @@ using Server.Targeting; namespace Server.Regions { - public class HouseRaffleRegion : BaseRegion - { - private readonly HouseRaffleStone m_Stone; - - public HouseRaffleRegion(HouseRaffleStone stone) - : base(null, stone.PlotFacet, DefaultPriority, stone.PlotBounds) => - m_Stone = stone; - - public override bool AllowHousing(Mobile from, Point3D p) + public class HouseRaffleRegion : BaseRegion { - if (m_Stone == null) - return false; + private readonly HouseRaffleStone m_Stone; - if (m_Stone.IsExpired) - return true; + public HouseRaffleRegion(HouseRaffleStone stone) + : base(null, stone.PlotFacet, DefaultPriority, stone.PlotBounds) => + m_Stone = stone; - if (m_Stone.Deed == null) - return false; + public override bool AllowHousing(Mobile from, Point3D p) + { + if (m_Stone == null) + return false; - Container pack = from.Backpack; + if (m_Stone.IsExpired) + return true; - if (pack != null && ContainsDeed(pack)) - return true; + if (m_Stone.Deed == null) + return false; - BankBox bank = from.FindBankNoCreate(); + var pack = from.Backpack; - return bank != null && ContainsDeed(bank); + if (pack != null && ContainsDeed(pack)) + return true; + + var bank = from.FindBankNoCreate(); + + return bank != null && ContainsDeed(bank); + } + + private bool ContainsDeed(Container cont) + { + return cont.FindItemsByType().Any(deed => deed == m_Stone.Deed); + } + + public override bool OnTarget(Mobile m, Target t, object o) + { + if (m.Spell is MarkSpell && m.AccessLevel == AccessLevel.Player) + { + m.SendLocalizedMessage(501800); // You cannot mark an object at that location. + return false; + } + + return base.OnTarget(m, t, o); + } } - - private bool ContainsDeed(Container cont) - { - return cont.FindItemsByType().Any(deed => deed == m_Stone.Deed); - } - - public override bool OnTarget(Mobile m, Target t, object o) - { - if (m.Spell is MarkSpell && m.AccessLevel == AccessLevel.Player) - { - m.SendLocalizedMessage(501800); // You cannot mark an object at that location. - return false; - } - - return base.OnTarget(m, t, o); - } - } } diff --git a/Projects/UOContent/Items/Special/House Raffle/HouseRaffleStone.cs b/Projects/UOContent/Items/Special/House Raffle/HouseRaffleStone.cs index f1e19e969..973df50c9 100644 --- a/Projects/UOContent/Items/Special/House Raffle/HouseRaffleStone.cs +++ b/Projects/UOContent/Items/Special/House Raffle/HouseRaffleStone.cs @@ -10,672 +10,696 @@ using Server.Regions; namespace Server.Items { - public class RaffleEntry - { - public RaffleEntry(Mobile from) + public class RaffleEntry { - From = from; - - Address = From.NetState?.Address ?? IPAddress.None; - - Date = DateTime.UtcNow; - } - - public RaffleEntry(IGenericReader reader, int version) - { - switch (version) - { - case 3: // HouseRaffleStone version changes - case 2: - case 1: - case 0: - { - From = reader.ReadMobile(); - Address = Utility.Intern(reader.ReadIPAddress()); - Date = reader.ReadDateTime(); - - break; - } - } - } - - public Mobile From { get; } - - public IPAddress Address { get; } - - public DateTime Date { get; } - - public void Serialize(IGenericWriter writer) - { - writer.Write(From); - writer.Write(Address); - writer.Write(Date); - } - } - - public enum HouseRaffleState - { - Inactive, - Active, - Completed - } - - public enum HouseRaffleExpireAction - { - None, - HideStone, - DeleteStone - } - - [Flippable(0xEDD, 0xEDE)] - public class HouseRaffleStone : Item - { - private const int EntryLimitPerIP = 4; - private const int DefaultTicketPrice = 5000; - private const int MessageHue = 1153; - - public static readonly TimeSpan DefaultDuration = TimeSpan.FromDays(7.0); - public static readonly TimeSpan ExpirationTime = TimeSpan.FromDays(30.0); - - private static readonly List m_AllStones = new List(); - private Rectangle2D m_Bounds; - private TimeSpan m_Duration; - private Map m_Facet; - - private HouseRaffleRegion m_Region; - private DateTime m_Started; - - private HouseRaffleState m_State; - private int m_TicketPrice; - - private Mobile m_Winner; - - [Constructible] - public HouseRaffleStone() - : base(0xEDD) - { - m_Region = null; - m_Bounds = new Rectangle2D(); - m_Facet = null; - - m_Winner = null; - Deed = null; - - m_State = HouseRaffleState.Inactive; - m_Started = DateTime.MinValue; - m_Duration = DefaultDuration; - ExpireAction = HouseRaffleExpireAction.None; - m_TicketPrice = DefaultTicketPrice; - - Entries = new List(); - - Movable = false; - - m_AllStones.Add(this); - } - - public HouseRaffleStone(Serial serial) - : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] - public HouseRaffleState CurrentState - { - get => m_State; - set - { - if (m_State != value) + public RaffleEntry(Mobile from) { - if (value == HouseRaffleState.Active) - { - Entries.Clear(); + From = from; + + Address = From.NetState?.Address ?? IPAddress.None; + + Date = DateTime.UtcNow; + } + + public RaffleEntry(IGenericReader reader, int version) + { + switch (version) + { + case 3: // HouseRaffleStone version changes + case 2: + case 1: + case 0: + { + From = reader.ReadMobile(); + Address = Utility.Intern(reader.ReadIPAddress()); + Date = reader.ReadDateTime(); + + break; + } + } + } + + public Mobile From { get; } + + public IPAddress Address { get; } + + public DateTime Date { get; } + + public void Serialize(IGenericWriter writer) + { + writer.Write(From); + writer.Write(Address); + writer.Write(Date); + } + } + + public enum HouseRaffleState + { + Inactive, + Active, + Completed + } + + public enum HouseRaffleExpireAction + { + None, + HideStone, + DeleteStone + } + + [Flippable(0xEDD, 0xEDE)] + public class HouseRaffleStone : Item + { + private const int EntryLimitPerIP = 4; + private const int DefaultTicketPrice = 5000; + private const int MessageHue = 1153; + + public static readonly TimeSpan DefaultDuration = TimeSpan.FromDays(7.0); + public static readonly TimeSpan ExpirationTime = TimeSpan.FromDays(30.0); + + private static readonly List m_AllStones = new List(); + private Rectangle2D m_Bounds; + private TimeSpan m_Duration; + private Map m_Facet; + + private HouseRaffleRegion m_Region; + private DateTime m_Started; + + private HouseRaffleState m_State; + private int m_TicketPrice; + + private Mobile m_Winner; + + [Constructible] + public HouseRaffleStone() + : base(0xEDD) + { + m_Region = null; + m_Bounds = new Rectangle2D(); + m_Facet = null; + m_Winner = null; Deed = null; - m_Started = DateTime.UtcNow; - } - m_State = value; - InvalidateProperties(); - } - } - } + m_State = HouseRaffleState.Inactive; + m_Started = DateTime.MinValue; + m_Duration = DefaultDuration; + ExpireAction = HouseRaffleExpireAction.None; + m_TicketPrice = DefaultTicketPrice; - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] - public Rectangle2D PlotBounds - { - get => m_Bounds; - set - { - m_Bounds = value; + Entries = new List(); - InvalidateRegion(); - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] - public Map PlotFacet - { - get => m_Facet; - set - { - m_Facet = value; - - InvalidateRegion(); - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] - public Mobile Winner - { - get => m_Winner; - set - { - m_Winner = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] - public HouseRaffleDeed Deed { get; set; } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] - public DateTime Started - { - get => m_Started; - set - { - m_Started = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] - public TimeSpan Duration - { - get => m_Duration; - set - { - m_Duration = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsExpired - { - get - { - if (m_State != HouseRaffleState.Completed) - return false; - - return m_Started + m_Duration + ExpirationTime <= DateTime.UtcNow; - } - } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] - public HouseRaffleExpireAction ExpireAction { get; set; } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] - public int TicketPrice - { - get => m_TicketPrice; - set - { - m_TicketPrice = Math.Max(0, value); - InvalidateProperties(); - } - } - - public List Entries { get; private set; } - - public override string DefaultName => "a house raffle stone"; - - public override bool DisplayWeight => false; - - public static void CheckEnd_OnTick() - { - for (int i = 0; i < m_AllStones.Count; i++) - m_AllStones[i].CheckEnd(); - } - - public static void Initialize() - { - for (int i = m_AllStones.Count - 1; i >= 0; i--) - { - HouseRaffleStone stone = m_AllStones[i]; - - if (stone.IsExpired) - switch (stone.ExpireAction) - { - case HouseRaffleExpireAction.HideStone: - { - if (stone.Visible) - { - stone.Visible = false; - stone.ItemID = 0x1B7B; // Non-blocking ItemID - } - - break; - } - case HouseRaffleExpireAction.DeleteStone: - { - stone.Delete(); - break; - } - } - } - - Timer.DelayCall(TimeSpan.FromMinutes(1.0), TimeSpan.FromMinutes(1.0), CheckEnd_OnTick); - } - - public bool ValidLocation() => - m_Bounds.Start != Point2D.Zero && m_Bounds.End != Point2D.Zero && m_Facet != null && - m_Facet != Map.Internal; - - private void InvalidateRegion() - { - if (m_Region != null) - { - m_Region.Unregister(); - m_Region = null; - } - - if (ValidLocation()) - { - m_Region = new HouseRaffleRegion(this); - m_Region.Register(); - } - } - - private bool HasEntered(Mobile from) - { - if (!(from.Account is Account acc)) - return false; - - foreach (RaffleEntry entry in Entries) - if (entry.From != null) - { - Account entryAcc = entry.From.Account as Account; - - if (entryAcc == acc) - return true; - } - - return false; - } - - private bool IsAtIPLimit(Mobile from) - { - if (from.NetState == null) - return false; - - IPAddress address = from.NetState.Address; - int tickets = 0; - - foreach (RaffleEntry entry in Entries) - if (Utility.IPMatchClassC(entry.Address, address)) - if (++tickets >= EntryLimitPerIP) - return true; - - return false; - } - - public static string FormatLocation(Point3D loc, Map map, bool displayMap) - { - StringBuilder result = new StringBuilder(); - - int xLong = 0, yLat = 0; - int xMins = 0, yMins = 0; - bool xEast = false, ySouth = false; - - if (Sextant.Format(loc, map, ref xLong, ref yLat, ref xMins, ref yMins, ref xEast, ref ySouth)) - result.AppendFormat("{0}°{1}'{2},{3}°{4}'{5}", yLat, yMins, ySouth ? "S" : "N", xLong, xMins, - xEast ? "E" : "W"); - else - result.AppendFormat("{0},{1}", loc.X, loc.Y); - - if (displayMap) - result.AppendFormat(" ({0})", map); - - return result.ToString(); - } - - public Point3D GetPlotCenter() - { - int x = m_Bounds.X + m_Bounds.Width / 2; - int y = m_Bounds.Y + m_Bounds.Height / 2; - int z = m_Facet?.GetAverageZ(x, y) ?? 0; - - return new Point3D(x, y, z); - } - - public string FormatLocation() - { - if (!ValidLocation()) - return "no location set"; - - return FormatLocation(GetPlotCenter(), m_Facet, true); - } - - public string FormatPrice() => m_TicketPrice == 0 ? "FREE" : $"{m_TicketPrice} gold"; - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (ValidLocation()) - list.Add(FormatLocation()); - - switch (m_State) - { - case HouseRaffleState.Active: - { - list.Add(1060658, "ticket price\t{0}", FormatPrice()); // ~1_val~: ~2_val~ - list.Add(1060659, "ends\t{0}", m_Started + m_Duration); // ~1_val~: ~2_val~ - break; - } - case HouseRaffleState.Completed: - { - list.Add(1060658, "winner\t{0}", m_Winner == null ? "unknown" : m_Winner.Name); // ~1_val~: ~2_val~ - break; - } - } - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - switch (m_State) - { - case HouseRaffleState.Active: - { - LabelTo(from, 1060658, $"Ends\t{m_Started + m_Duration}"); // ~1_val~: ~2_val~ - break; - } - case HouseRaffleState.Completed: - { - LabelTo(from, 1060658, $"Winner\t{(m_Winner == null ? "Unknown" : m_Winner.Name)}"); // ~1_val~: ~2_val~ - break; - } - } - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (from.AccessLevel >= AccessLevel.Seer) - { - list.Add(new EditEntry(from, this)); - - if (m_State == HouseRaffleState.Inactive) - list.Add(new ActivateEntry(from, this)); - else - list.Add(new ManagementEntry(from, this)); - } - } - - public override void OnDoubleClick(Mobile from) - { - if (m_State != HouseRaffleState.Active || !from.CheckAlive()) - return; - - if (!from.InRange(GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return; - } - - if (HasEntered(from)) - from.SendMessage(MessageHue, "You have already entered this plot's raffle."); - else if (IsAtIPLimit(from)) - from.SendMessage(MessageHue, "You may not enter this plot's raffle."); - else - from.SendGump(new WarningGump(1150470, 0x7F00, - $"You are about to purchase a raffle ticket for the house plot located at {FormatLocation()}. The ticket price is {FormatPrice()}. Tickets are non-refundable and you can only purchase one ticket per account. Do you wish to continue?", - 0xFFFFFF, 420, 280, okay => Purchase_Callback(from, okay))); // CONFIRM TICKET PURCHASE - } - - public void Purchase_Callback(Mobile from, bool okay) - { - if (Deleted || m_State != HouseRaffleState.Active || !from.CheckAlive() || HasEntered(from) || IsAtIPLimit(from)) - return; - - if (!(from.Account is Account)) - return; - - if (okay) - { - Container bank = from.FindBankNoCreate(); - - if (m_TicketPrice == 0 || from.Backpack?.ConsumeTotal(typeof(Gold), m_TicketPrice) == true || - bank?.ConsumeTotal(typeof(Gold), m_TicketPrice) == true) - { - Entries.Add(new RaffleEntry(from)); - - from.SendMessage(MessageHue, "You have successfully entered the plot's raffle."); - } - else - { - from.SendMessage(MessageHue, "You do not have the {0} required to enter the raffle.", FormatPrice()); - } - } - else - { - from.SendMessage(MessageHue, "You have chosen not to enter the raffle."); - } - } - - public void CheckEnd() - { - if (m_State != HouseRaffleState.Active || m_Started + m_Duration > DateTime.UtcNow) - return; - - m_State = HouseRaffleState.Completed; - - if (m_Region != null && Entries.Count != 0) - { - m_Winner = Entries.RandomElement().From; - - if (m_Winner != null) - { - Deed = new HouseRaffleDeed(this, m_Winner); - - m_Winner.SendMessage(MessageHue, - "Congratulations, {0}! You have won the raffle for the plot located at {1}.", m_Winner.Name, - FormatLocation()); - - if (m_Winner.AddToBackpack(Deed)) - { - m_Winner.SendMessage(MessageHue, "The writ of lease has been placed in your backpack."); - } - else - { - m_Winner.BankBox.DropItem(Deed); - m_Winner.SendMessage(MessageHue, - "As your backpack is full, the writ of lease has been placed in your bank box."); - } - } - } - - InvalidateProperties(); - } - - public override void OnDelete() - { - if (m_Region != null) - { - m_Region.Unregister(); - m_Region = null; - } - - m_AllStones.Remove(this); - - base.OnDelete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(3); // version - - writer.WriteEncodedInt((int)m_State); - writer.WriteEncodedInt((int)ExpireAction); - - writer.Write(Deed); - - writer.Write(m_Bounds); - writer.Write(m_Facet); - - writer.Write(m_Winner); - - writer.Write(m_TicketPrice); - writer.Write(m_Started); - writer.Write(m_Duration); - - writer.Write(Entries.Count); - - foreach (RaffleEntry entry in Entries) - entry.Serialize(writer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 3: - { - m_State = (HouseRaffleState)reader.ReadEncodedInt(); - - goto case 2; - } - case 2: - { - ExpireAction = (HouseRaffleExpireAction)reader.ReadEncodedInt(); - - goto case 1; - } - case 1: - { - Deed = reader.ReadItem(); - - goto case 0; - } - case 0: - { - bool oldActive = version < 3 && reader.ReadBool(); - - m_Bounds = reader.ReadRect2D(); - m_Facet = reader.ReadMap(); - - m_Winner = reader.ReadMobile(); - - m_TicketPrice = reader.ReadInt(); - m_Started = reader.ReadDateTime(); - m_Duration = reader.ReadTimeSpan(); - - int entryCount = reader.ReadInt(); - Entries = new List(entryCount); - - for (int i = 0; i < entryCount; i++) - { - RaffleEntry entry = new RaffleEntry(reader, version); - - if (entry.From == null) - continue; // Character was deleted - - Entries.Add(entry); - } - - InvalidateRegion(); + Movable = false; m_AllStones.Add(this); + } - if (version < 3) + public HouseRaffleStone(Serial serial) + : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] + public HouseRaffleState CurrentState + { + get => m_State; + set { - if (oldActive) - m_State = HouseRaffleState.Active; - else if (m_Winner != null) - m_State = HouseRaffleState.Completed; - else - m_State = HouseRaffleState.Inactive; + if (m_State != value) + { + if (value == HouseRaffleState.Active) + { + Entries.Clear(); + m_Winner = null; + Deed = null; + m_Started = DateTime.UtcNow; + } + + m_State = value; + InvalidateProperties(); + } + } + } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] + public Rectangle2D PlotBounds + { + get => m_Bounds; + set + { + m_Bounds = value; + + InvalidateRegion(); + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] + public Map PlotFacet + { + get => m_Facet; + set + { + m_Facet = value; + + InvalidateRegion(); + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] + public Mobile Winner + { + get => m_Winner; + set + { + m_Winner = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] + public HouseRaffleDeed Deed { get; set; } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] + public DateTime Started + { + get => m_Started; + set + { + m_Started = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] + public TimeSpan Duration + { + get => m_Duration; + set + { + m_Duration = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsExpired + { + get + { + if (m_State != HouseRaffleState.Completed) + return false; + + return m_Started + m_Duration + ExpirationTime <= DateTime.UtcNow; + } + } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] + public HouseRaffleExpireAction ExpireAction { get; set; } + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Seer)] + public int TicketPrice + { + get => m_TicketPrice; + set + { + m_TicketPrice = Math.Max(0, value); + InvalidateProperties(); + } + } + + public List Entries { get; private set; } + + public override string DefaultName => "a house raffle stone"; + + public override bool DisplayWeight => false; + + public static void CheckEnd_OnTick() + { + for (var i = 0; i < m_AllStones.Count; i++) + m_AllStones[i].CheckEnd(); + } + + public static void Initialize() + { + for (var i = m_AllStones.Count - 1; i >= 0; i--) + { + var stone = m_AllStones[i]; + + if (stone.IsExpired) + switch (stone.ExpireAction) + { + case HouseRaffleExpireAction.HideStone: + { + if (stone.Visible) + { + stone.Visible = false; + stone.ItemID = 0x1B7B; // Non-blocking ItemID + } + + break; + } + case HouseRaffleExpireAction.DeleteStone: + { + stone.Delete(); + break; + } + } } - break; - } - } + Timer.DelayCall(TimeSpan.FromMinutes(1.0), TimeSpan.FromMinutes(1.0), CheckEnd_OnTick); + } + + public bool ValidLocation() => + m_Bounds.Start != Point2D.Zero && m_Bounds.End != Point2D.Zero && m_Facet != null && + m_Facet != Map.Internal; + + private void InvalidateRegion() + { + if (m_Region != null) + { + m_Region.Unregister(); + m_Region = null; + } + + if (ValidLocation()) + { + m_Region = new HouseRaffleRegion(this); + m_Region.Register(); + } + } + + private bool HasEntered(Mobile from) + { + if (!(from.Account is Account acc)) + return false; + + foreach (var entry in Entries) + if (entry.From != null) + { + var entryAcc = entry.From.Account as Account; + + if (entryAcc == acc) + return true; + } + + return false; + } + + private bool IsAtIPLimit(Mobile from) + { + if (from.NetState == null) + return false; + + var address = from.NetState.Address; + var tickets = 0; + + foreach (var entry in Entries) + if (Utility.IPMatchClassC(entry.Address, address)) + if (++tickets >= EntryLimitPerIP) + return true; + + return false; + } + + public static string FormatLocation(Point3D loc, Map map, bool displayMap) + { + var result = new StringBuilder(); + + int xLong = 0, yLat = 0; + int xMins = 0, yMins = 0; + bool xEast = false, ySouth = false; + + if (Sextant.Format(loc, map, ref xLong, ref yLat, ref xMins, ref yMins, ref xEast, ref ySouth)) + result.AppendFormat( + "{0}°{1}'{2},{3}°{4}'{5}", + yLat, + yMins, + ySouth ? "S" : "N", + xLong, + xMins, + xEast ? "E" : "W" + ); + else + result.AppendFormat("{0},{1}", loc.X, loc.Y); + + if (displayMap) + result.AppendFormat(" ({0})", map); + + return result.ToString(); + } + + public Point3D GetPlotCenter() + { + var x = m_Bounds.X + m_Bounds.Width / 2; + var y = m_Bounds.Y + m_Bounds.Height / 2; + var z = m_Facet?.GetAverageZ(x, y) ?? 0; + + return new Point3D(x, y, z); + } + + public string FormatLocation() + { + if (!ValidLocation()) + return "no location set"; + + return FormatLocation(GetPlotCenter(), m_Facet, true); + } + + public string FormatPrice() => m_TicketPrice == 0 ? "FREE" : $"{m_TicketPrice} gold"; + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (ValidLocation()) + list.Add(FormatLocation()); + + switch (m_State) + { + case HouseRaffleState.Active: + { + list.Add(1060658, "ticket price\t{0}", FormatPrice()); // ~1_val~: ~2_val~ + list.Add(1060659, "ends\t{0}", m_Started + m_Duration); // ~1_val~: ~2_val~ + break; + } + case HouseRaffleState.Completed: + { + list.Add(1060658, "winner\t{0}", m_Winner == null ? "unknown" : m_Winner.Name); // ~1_val~: ~2_val~ + break; + } + } + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + switch (m_State) + { + case HouseRaffleState.Active: + { + LabelTo(from, 1060658, $"Ends\t{m_Started + m_Duration}"); // ~1_val~: ~2_val~ + break; + } + case HouseRaffleState.Completed: + { + LabelTo( + from, + 1060658, + $"Winner\t{(m_Winner == null ? "Unknown" : m_Winner.Name)}" + ); // ~1_val~: ~2_val~ + break; + } + } + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (from.AccessLevel >= AccessLevel.Seer) + { + list.Add(new EditEntry(from, this)); + + if (m_State == HouseRaffleState.Inactive) + list.Add(new ActivateEntry(from, this)); + else + list.Add(new ManagementEntry(from, this)); + } + } + + public override void OnDoubleClick(Mobile from) + { + if (m_State != HouseRaffleState.Active || !from.CheckAlive()) + return; + + if (!from.InRange(GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return; + } + + if (HasEntered(from)) + from.SendMessage(MessageHue, "You have already entered this plot's raffle."); + else if (IsAtIPLimit(from)) + from.SendMessage(MessageHue, "You may not enter this plot's raffle."); + else + from.SendGump( + new WarningGump( + 1150470, + 0x7F00, + $"You are about to purchase a raffle ticket for the house plot located at {FormatLocation()}. The ticket price is {FormatPrice()}. Tickets are non-refundable and you can only purchase one ticket per account. Do you wish to continue?", + 0xFFFFFF, + 420, + 280, + okay => Purchase_Callback(from, okay) + ) + ); // CONFIRM TICKET PURCHASE + } + + public void Purchase_Callback(Mobile from, bool okay) + { + if (Deleted || m_State != HouseRaffleState.Active || !from.CheckAlive() || HasEntered(from) || IsAtIPLimit(from)) + return; + + if (!(from.Account is Account)) + return; + + if (okay) + { + Container bank = from.FindBankNoCreate(); + + if (m_TicketPrice == 0 || from.Backpack?.ConsumeTotal(typeof(Gold), m_TicketPrice) == true || + bank?.ConsumeTotal(typeof(Gold), m_TicketPrice) == true) + { + Entries.Add(new RaffleEntry(from)); + + from.SendMessage(MessageHue, "You have successfully entered the plot's raffle."); + } + else + { + from.SendMessage(MessageHue, "You do not have the {0} required to enter the raffle.", FormatPrice()); + } + } + else + { + from.SendMessage(MessageHue, "You have chosen not to enter the raffle."); + } + } + + public void CheckEnd() + { + if (m_State != HouseRaffleState.Active || m_Started + m_Duration > DateTime.UtcNow) + return; + + m_State = HouseRaffleState.Completed; + + if (m_Region != null && Entries.Count != 0) + { + m_Winner = Entries.RandomElement().From; + + if (m_Winner != null) + { + Deed = new HouseRaffleDeed(this, m_Winner); + + m_Winner.SendMessage( + MessageHue, + "Congratulations, {0}! You have won the raffle for the plot located at {1}.", + m_Winner.Name, + FormatLocation() + ); + + if (m_Winner.AddToBackpack(Deed)) + { + m_Winner.SendMessage(MessageHue, "The writ of lease has been placed in your backpack."); + } + else + { + m_Winner.BankBox.DropItem(Deed); + m_Winner.SendMessage( + MessageHue, + "As your backpack is full, the writ of lease has been placed in your bank box." + ); + } + } + } + + InvalidateProperties(); + } + + public override void OnDelete() + { + if (m_Region != null) + { + m_Region.Unregister(); + m_Region = null; + } + + m_AllStones.Remove(this); + + base.OnDelete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(3); // version + + writer.WriteEncodedInt((int)m_State); + writer.WriteEncodedInt((int)ExpireAction); + + writer.Write(Deed); + + writer.Write(m_Bounds); + writer.Write(m_Facet); + + writer.Write(m_Winner); + + writer.Write(m_TicketPrice); + writer.Write(m_Started); + writer.Write(m_Duration); + + writer.Write(Entries.Count); + + foreach (var entry in Entries) + entry.Serialize(writer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 3: + { + m_State = (HouseRaffleState)reader.ReadEncodedInt(); + + goto case 2; + } + case 2: + { + ExpireAction = (HouseRaffleExpireAction)reader.ReadEncodedInt(); + + goto case 1; + } + case 1: + { + Deed = reader.ReadItem(); + + goto case 0; + } + case 0: + { + var oldActive = version < 3 && reader.ReadBool(); + + m_Bounds = reader.ReadRect2D(); + m_Facet = reader.ReadMap(); + + m_Winner = reader.ReadMobile(); + + m_TicketPrice = reader.ReadInt(); + m_Started = reader.ReadDateTime(); + m_Duration = reader.ReadTimeSpan(); + + var entryCount = reader.ReadInt(); + Entries = new List(entryCount); + + for (var i = 0; i < entryCount; i++) + { + var entry = new RaffleEntry(reader, version); + + if (entry.From == null) + continue; // Character was deleted + + Entries.Add(entry); + } + + InvalidateRegion(); + + m_AllStones.Add(this); + + if (version < 3) + { + if (oldActive) + m_State = HouseRaffleState.Active; + else if (m_Winner != null) + m_State = HouseRaffleState.Completed; + else + m_State = HouseRaffleState.Inactive; + } + + break; + } + } + } + + private class RaffleContextMenuEntry : ContextMenuEntry + { + protected readonly Mobile m_From; + protected readonly HouseRaffleStone m_Stone; + + public RaffleContextMenuEntry(Mobile from, HouseRaffleStone stone, int label) + : base(label) + { + m_From = from; + m_Stone = stone; + } + } + + private class EditEntry : RaffleContextMenuEntry + { + public EditEntry(Mobile from, HouseRaffleStone stone) + : base(from, stone, 5101) // Edit + { + } + + public override void OnClick() + { + if (m_Stone.Deleted || m_From.AccessLevel < AccessLevel.Seer) + return; + + m_From.SendGump(new PropertiesGump(m_From, m_Stone)); + } + } + + private class ActivateEntry : RaffleContextMenuEntry + { + public ActivateEntry(Mobile from, HouseRaffleStone stone) + : base(from, stone, 5113) // Start + { + if (!stone.ValidLocation()) + Flags |= CMEFlags.Disabled; + } + + public override void OnClick() + { + if (m_Stone.Deleted || m_From.AccessLevel < AccessLevel.Seer || !m_Stone.ValidLocation()) + return; + + m_Stone.CurrentState = HouseRaffleState.Active; + } + } + + private class ManagementEntry : RaffleContextMenuEntry + { + public ManagementEntry(Mobile from, HouseRaffleStone stone) + : base(from, stone, 5032) // Game Monitor + { + } + + public override void OnClick() + { + if (m_Stone.Deleted || m_From.AccessLevel < AccessLevel.Seer) + return; + + m_From.SendGump(new HouseRaffleManagementGump(m_Stone)); + } + } } - - private class RaffleContextMenuEntry : ContextMenuEntry - { - protected readonly Mobile m_From; - protected readonly HouseRaffleStone m_Stone; - - public RaffleContextMenuEntry(Mobile from, HouseRaffleStone stone, int label) - : base(label) - { - m_From = from; - m_Stone = stone; - } - } - - private class EditEntry : RaffleContextMenuEntry - { - public EditEntry(Mobile from, HouseRaffleStone stone) - : base(from, stone, 5101) // Edit - { - } - - public override void OnClick() - { - if (m_Stone.Deleted || m_From.AccessLevel < AccessLevel.Seer) - return; - - m_From.SendGump(new PropertiesGump(m_From, m_Stone)); - } - } - - private class ActivateEntry : RaffleContextMenuEntry - { - public ActivateEntry(Mobile from, HouseRaffleStone stone) - : base(from, stone, 5113) // Start - { - if (!stone.ValidLocation()) - Flags |= CMEFlags.Disabled; - } - - public override void OnClick() - { - if (m_Stone.Deleted || m_From.AccessLevel < AccessLevel.Seer || !m_Stone.ValidLocation()) - return; - - m_Stone.CurrentState = HouseRaffleState.Active; - } - } - - private class ManagementEntry : RaffleContextMenuEntry - { - public ManagementEntry(Mobile from, HouseRaffleStone stone) - : base(from, stone, 5032) // Game Monitor - { - } - - public override void OnClick() - { - if (m_Stone.Deleted || m_From.AccessLevel < AccessLevel.Seer) - return; - - m_From.SendGump(new HouseRaffleManagementGump(m_Stone)); - } - } - } } diff --git a/Projects/UOContent/Items/Special/ML/BaseImprisonedMobile.cs b/Projects/UOContent/Items/Special/ML/BaseImprisonedMobile.cs index 7dc1420f2..1b8476dbb 100644 --- a/Projects/UOContent/Items/Special/ML/BaseImprisonedMobile.cs +++ b/Projects/UOContent/Items/Special/ML/BaseImprisonedMobile.cs @@ -3,43 +3,43 @@ using Server.Mobiles; namespace Server.Items { - public abstract class BaseImprisonedMobile : Item - { - [Constructible] - public BaseImprisonedMobile(int itemID) : base(itemID) + public abstract class BaseImprisonedMobile : Item { + [Constructible] + public BaseImprisonedMobile(int itemID) : base(itemID) + { + } + + public BaseImprisonedMobile(Serial serial) : base(serial) + { + } + + public abstract BaseCreature Summon { get; } + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + from.SendGump(new ConfirmBreakCrystalGump(this)); + else + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + + 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 virtual void Release(Mobile from, BaseCreature summon) + { + } } - - public BaseImprisonedMobile(Serial serial) : base(serial) - { - } - - public abstract BaseCreature Summon { get; } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - from.SendGump(new ConfirmBreakCrystalGump(this)); - else - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public virtual void Release(Mobile from, BaseCreature summon) - { - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/ML/GrizzledMareStatuette.cs b/Projects/UOContent/Items/Special/ML/GrizzledMareStatuette.cs index a474db749..441435c05 100644 --- a/Projects/UOContent/Items/Special/ML/GrizzledMareStatuette.cs +++ b/Projects/UOContent/Items/Special/ML/GrizzledMareStatuette.cs @@ -3,73 +3,73 @@ using Server.Mobiles; namespace Server.Items { - public class GrizzledMareStatuette : BaseImprisonedMobile - { - [Constructible] - public GrizzledMareStatuette() : base(0x2617) => Weight = 1.0; - - public GrizzledMareStatuette(Serial serial) : base(serial) + public class GrizzledMareStatuette : BaseImprisonedMobile { + [Constructible] + public GrizzledMareStatuette() : base(0x2617) => Weight = 1.0; + + public GrizzledMareStatuette(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1074475; // Grizzled Mare Statuette + public override BaseCreature Summon => new GrizzledMare(); + + 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 int LabelNumber => 1074475; // Grizzled Mare Statuette - public override BaseCreature Summon => new GrizzledMare(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } namespace Server.Mobiles { - public class GrizzledMare : HellSteed - { - private static readonly string m_Myname = "a grizzled mare"; - - [Constructible] - public GrizzledMare() - : base(m_Myname) + public class GrizzledMare : HellSteed { + private static readonly string m_Myname = "a grizzled mare"; + + [Constructible] + public GrizzledMare() + : base(m_Myname) + { + } + + public GrizzledMare(Serial serial) : base(serial) + { + } + + public override bool DeleteOnRelease => true; + + public virtual void OnAfterDeserialize_Callback() + { + SetStats(this); + + Name = m_Myname; + } + + 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 < 1) Timer.DelayCall(TimeSpan.FromSeconds(0), OnAfterDeserialize_Callback); + } } - - public GrizzledMare(Serial serial) : base(serial) - { - } - - public override bool DeleteOnRelease => true; - - public virtual void OnAfterDeserialize_Callback() - { - SetStats(this); - - Name = m_Myname; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1) Timer.DelayCall(TimeSpan.FromSeconds(0), OnAfterDeserialize_Callback); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/ML/MinotaurHedge.cs b/Projects/UOContent/Items/Special/ML/MinotaurHedge.cs index 05fab2bea..da021df44 100644 --- a/Projects/UOContent/Items/Special/ML/MinotaurHedge.cs +++ b/Projects/UOContent/Items/Special/ML/MinotaurHedge.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class MinotaurHedge : Item - { - [Constructible] - public MinotaurHedge() : base(Utility.Random(3215, 4)) => Weight = 1.0; - - public MinotaurHedge(Serial serial) : base(serial) + public class MinotaurHedge : Item { + [Constructible] + public MinotaurHedge() : base(Utility.Random(3215, 4)) => Weight = 1.0; + + public MinotaurHedge(Serial serial) : base(serial) + { + } + + public override string DefaultName => "minotaur hedge"; + + 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 string DefaultName => "minotaur hedge"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/ML/TormentedChains.cs b/Projects/UOContent/Items/Special/ML/TormentedChains.cs index 628d7e5b4..59da38055 100644 --- a/Projects/UOContent/Items/Special/ML/TormentedChains.cs +++ b/Projects/UOContent/Items/Special/ML/TormentedChains.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class TormentedChains : Item - { - [Constructible] - public TormentedChains() : base(Utility.Random(6663, 2)) => Weight = 1.0; - - public TormentedChains(Serial serial) : base(serial) + public class TormentedChains : Item { + [Constructible] + public TormentedChains() : base(Utility.Random(6663, 2)) => Weight = 1.0; + + public TormentedChains(Serial serial) : base(serial) + { + } + + public override string DefaultName => "chains of the tormented"; + + 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 string DefaultName => "chains of the tormented"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/MiniHouses.cs b/Projects/UOContent/Items/Special/MiniHouses.cs index 724cfa0cf..72e8e933b 100644 --- a/Projects/UOContent/Items/Special/MiniHouses.cs +++ b/Projects/UOContent/Items/Special/MiniHouses.cs @@ -2,233 +2,250 @@ using System; namespace Server.Items { - public class MiniHouseAddon : BaseAddon - { - private MiniHouseType m_Type; - - [Constructible] - public MiniHouseAddon(MiniHouseType type = MiniHouseType.StoneAndPlaster) + public class MiniHouseAddon : BaseAddon { - m_Type = type; + private MiniHouseType m_Type; - Construct(); + [Constructible] + public MiniHouseAddon(MiniHouseType type = MiniHouseType.StoneAndPlaster) + { + m_Type = type; + + Construct(); + } + + public MiniHouseAddon(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public MiniHouseType Type + { + get => m_Type; + set + { + m_Type = value; + Construct(); + } + } + + public override BaseAddonDeed Deed => new MiniHouseDeed(m_Type); + + public void Construct() + { + foreach (var c in Components) + { + c.Addon = null; + c.Delete(); + } + + Components.Clear(); + + var info = MiniHouseInfo.GetInfo(m_Type); + + var size = (int)Math.Sqrt(info.Graphics.Length); + var num = 0; + + for (var y = 0; y < size; ++y) + for (var x = 0; x < size; ++x) + if (info.Graphics[num] != 0x1) // Veteran Rewards Mod + AddComponent(new AddonComponent(info.Graphics[num++]), size - x - 1, size - y - 1, 0); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write((int)m_Type); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Type = (MiniHouseType)reader.ReadInt(); + break; + } + } + } } - public MiniHouseAddon(Serial serial) : base(serial) + public class MiniHouseDeed : BaseAddonDeed { + private MiniHouseType m_Type; + + [Constructible] + public MiniHouseDeed(MiniHouseType type = MiniHouseType.StoneAndPlaster) + { + m_Type = type; + + Weight = 1.0; + LootType = LootType.Blessed; + } + + public MiniHouseDeed(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public MiniHouseType Type + { + get => m_Type; + set + { + m_Type = value; + InvalidateProperties(); + } + } + + public override BaseAddon Addon => new MiniHouseAddon(m_Type); + public override int LabelNumber => 1062096; // a mini house deed + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(MiniHouseInfo.GetInfo(m_Type).LabelNumber); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write((int)m_Type); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Type = (MiniHouseType)reader.ReadInt(); + break; + } + } + + if (Weight == 0.0) + Weight = 1.0; + } } - [CommandProperty(AccessLevel.GameMaster)] - public MiniHouseType Type + public enum MiniHouseType { - get => m_Type; - set - { - m_Type = value; - Construct(); - } + StoneAndPlaster, + FieldStone, + SmallBrick, + Wooden, + WoodAndPlaster, + ThatchedRoof, + Brick, + TwoStoryWoodAndPlaster, + TwoStoryStoneAndPlaster, + Tower, + SmallStoneKeep, + Castle, + LargeHouseWithPatio, + MarbleHouseWithPatio, + SmallStoneTower, + TwoStoryLogCabin, + TwoStoryVilla, + SandstoneHouseWithPatio, + SmallStoneWorkshop, + SmallMarbleWorkshop, + MalasMountainPass, // Veteran reward house + ChurchAtNight // Veteran reward house } - public override BaseAddonDeed Deed => new MiniHouseDeed(m_Type); - - public void Construct() + public class MiniHouseInfo { - foreach (AddonComponent c in Components) - { - c.Addon = null; - c.Delete(); - } + private static readonly MiniHouseInfo[] m_Info = + { + /* Stone and plaster house */ new MiniHouseInfo(0x22C4, 1, 1011303), + /* Field stone house */ new MiniHouseInfo(0x22DE, 1, 1011304), + /* Small brick house */ new MiniHouseInfo(0x22DF, 1, 1011305), + /* Wooden house */ new MiniHouseInfo(0x22C9, 1, 1011306), + /* Wood and plaster house */ new MiniHouseInfo(0x22E0, 1, 1011307), + /* Thatched-roof cottage */ new MiniHouseInfo(0x22E1, 1, 1011308), + /* Brick house */ new MiniHouseInfo(1011309, 0x22CD, 0x22CB, 0x22CC, 0x22CA), + /* Two-story wood and plaster house */ new MiniHouseInfo(1011310, 0x2301, 0x2302, 0x2304, 0x2303), + /* Two-story stone and plaster house */ new MiniHouseInfo(1011311, 0x22FC, 0x22FD, 0x22FF, 0x22FE), + /* Tower */ new MiniHouseInfo(1011312, 0x22F7, 0x22F8, 0x22FA, 0x22F9), + /* Small stone keep */ new MiniHouseInfo(0x22E6, 9, 1011313), + /* Castle */ + new MiniHouseInfo( + 1011314, + 0x22CE, + 0x22D0, + 0x22D2, + 0x22D7, + 0x22CF, + 0x22D1, + 0x22D4, + 0x22D9, + 0x22D3, + 0x22D5, + 0x22D6, + 0x22DB, + 0x22D8, + 0x22DA, + 0x22DC, + 0x22DD + ), + /* Large house with patio */ new MiniHouseInfo(0x22E2, 4, 1011315), + /* Marble house with patio */ new MiniHouseInfo(0x22EF, 4, 1011316), + /* Small stone tower */ new MiniHouseInfo(0x22F5, 1, 1011317), + /* Two-story log cabin */ new MiniHouseInfo(0x22FB, 1, 1011318), + /* Two-story villa */ new MiniHouseInfo(0x2300, 1, 1011319), + /* Sandstone house with patio */ new MiniHouseInfo(0x22F3, 1, 1011320), + /* Small stone workshop */ new MiniHouseInfo(0x22F6, 1, 1011321), + /* Small marble workshop */ new MiniHouseInfo(0x22F4, 1, 1011322), + /* Malas Mountain Pass */ new MiniHouseInfo(1062692, 0x2316, 0x2315, 0x2314, 0x2313), + /* Church At Night */ new MiniHouseInfo(1072215, 0x2318, 0x2317, 0x2319, 0x1) + }; - Components.Clear(); + public MiniHouseInfo(int start, int count, int labelNumber) + { + Graphics = new int[count]; - MiniHouseInfo info = MiniHouseInfo.GetInfo(m_Type); + for (var i = 0; i < count; ++i) + Graphics[i] = start + i; - int size = (int)Math.Sqrt(info.Graphics.Length); - int num = 0; + LabelNumber = labelNumber; + } - for (int y = 0; y < size; ++y) - for (int x = 0; x < size; ++x) - if (info.Graphics[num] != 0x1) // Veteran Rewards Mod - AddComponent(new AddonComponent(info.Graphics[num++]), size - x - 1, size - y - 1, 0); + public MiniHouseInfo(int labelNumber, params int[] graphics) + { + LabelNumber = labelNumber; + Graphics = graphics; + } + + public int[] Graphics { get; } + + public int LabelNumber { get; } + + public static MiniHouseInfo GetInfo(MiniHouseType type) + { + var v = (int)type; + + if (v < 0 || v >= m_Info.Length) + v = 0; + + return m_Info[v]; + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write((int)m_Type); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Type = (MiniHouseType)reader.ReadInt(); - break; - } - } - } - } - - public class MiniHouseDeed : BaseAddonDeed - { - private MiniHouseType m_Type; - - [Constructible] - public MiniHouseDeed(MiniHouseType type = MiniHouseType.StoneAndPlaster) - { - m_Type = type; - - Weight = 1.0; - LootType = LootType.Blessed; - } - - public MiniHouseDeed(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public MiniHouseType Type - { - get => m_Type; - set - { - m_Type = value; - InvalidateProperties(); - } - } - - public override BaseAddon Addon => new MiniHouseAddon(m_Type); - public override int LabelNumber => 1062096; // a mini house deed - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(MiniHouseInfo.GetInfo(m_Type).LabelNumber); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write((int)m_Type); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Type = (MiniHouseType)reader.ReadInt(); - break; - } - } - - if (Weight == 0.0) - Weight = 1.0; - } - } - - public enum MiniHouseType - { - StoneAndPlaster, - FieldStone, - SmallBrick, - Wooden, - WoodAndPlaster, - ThatchedRoof, - Brick, - TwoStoryWoodAndPlaster, - TwoStoryStoneAndPlaster, - Tower, - SmallStoneKeep, - Castle, - LargeHouseWithPatio, - MarbleHouseWithPatio, - SmallStoneTower, - TwoStoryLogCabin, - TwoStoryVilla, - SandstoneHouseWithPatio, - SmallStoneWorkshop, - SmallMarbleWorkshop, - MalasMountainPass, // Veteran reward house - ChurchAtNight // Veteran reward house - } - - public class MiniHouseInfo - { - private static readonly MiniHouseInfo[] m_Info = - { - /* Stone and plaster house */ new MiniHouseInfo(0x22C4, 1, 1011303), - /* Field stone house */ new MiniHouseInfo(0x22DE, 1, 1011304), - /* Small brick house */ new MiniHouseInfo(0x22DF, 1, 1011305), - /* Wooden house */ new MiniHouseInfo(0x22C9, 1, 1011306), - /* Wood and plaster house */ new MiniHouseInfo(0x22E0, 1, 1011307), - /* Thatched-roof cottage */ new MiniHouseInfo(0x22E1, 1, 1011308), - /* Brick house */ new MiniHouseInfo(1011309, 0x22CD, 0x22CB, 0x22CC, 0x22CA), - /* Two-story wood and plaster house */ new MiniHouseInfo(1011310, 0x2301, 0x2302, 0x2304, 0x2303), - /* Two-story stone and plaster house */ new MiniHouseInfo(1011311, 0x22FC, 0x22FD, 0x22FF, 0x22FE), - /* Tower */ new MiniHouseInfo(1011312, 0x22F7, 0x22F8, 0x22FA, 0x22F9), - /* Small stone keep */ new MiniHouseInfo(0x22E6, 9, 1011313), - /* Castle */ - new MiniHouseInfo(1011314, 0x22CE, 0x22D0, 0x22D2, 0x22D7, 0x22CF, 0x22D1, 0x22D4, 0x22D9, 0x22D3, 0x22D5, - 0x22D6, 0x22DB, 0x22D8, 0x22DA, 0x22DC, 0x22DD), - /* Large house with patio */ new MiniHouseInfo(0x22E2, 4, 1011315), - /* Marble house with patio */ new MiniHouseInfo(0x22EF, 4, 1011316), - /* Small stone tower */ new MiniHouseInfo(0x22F5, 1, 1011317), - /* Two-story log cabin */ new MiniHouseInfo(0x22FB, 1, 1011318), - /* Two-story villa */ new MiniHouseInfo(0x2300, 1, 1011319), - /* Sandstone house with patio */ new MiniHouseInfo(0x22F3, 1, 1011320), - /* Small stone workshop */ new MiniHouseInfo(0x22F6, 1, 1011321), - /* Small marble workshop */ new MiniHouseInfo(0x22F4, 1, 1011322), - /* Malas Mountain Pass */ new MiniHouseInfo(1062692, 0x2316, 0x2315, 0x2314, 0x2313), - /* Church At Night */ new MiniHouseInfo(1072215, 0x2318, 0x2317, 0x2319, 0x1) - }; - - public MiniHouseInfo(int start, int count, int labelNumber) - { - Graphics = new int[count]; - - for (int i = 0; i < count; ++i) - Graphics[i] = start + i; - - LabelNumber = labelNumber; - } - - public MiniHouseInfo(int labelNumber, params int[] graphics) - { - LabelNumber = labelNumber; - Graphics = graphics; - } - - public int[] Graphics { get; } - - public int LabelNumber { get; } - - public static MiniHouseInfo GetInfo(MiniHouseType type) - { - int v = (int)type; - - if (v < 0 || v >= m_Info.Length) - v = 0; - - return m_Info[v]; - } - } } diff --git a/Projects/UOContent/Items/Special/MonsterStatuette.cs b/Projects/UOContent/Items/Special/MonsterStatuette.cs index 20834a74e..39a697c70 100644 --- a/Projects/UOContent/Items/Special/MonsterStatuette.cs +++ b/Projects/UOContent/Items/Special/MonsterStatuette.cs @@ -5,300 +5,302 @@ using Server.Network; namespace Server.Items { - public enum MonsterStatuetteType - { - Crocodile, - Daemon, - Dragon, - EarthElemental, - Ettin, - Gargoyle, - Gorilla, - Lich, - Lizardman, - Ogre, - Orc, - Ratman, - Skeleton, - Troll, - Cow, - Zombie, - Llama, - Ophidian, - Reaper, - Mongbat, - Gazer, - FireElemental, - Wolf, - PhillipsWoodenSteed, - Seahorse, - Harrower, - Efreet, - Slime, - PlagueBeast, - RedDeath, - Spider, - OphidianArchMage, - OphidianWarrior, - OphidianKnight, - OphidianMage, - DreadHorn, - Minotaur, - BlackCat, - HalloweenGhoul, - Santa - } - - public class MonsterStatuetteInfo - { - private static readonly MonsterStatuetteInfo[] m_Table = + public enum MonsterStatuetteType { - /* Crocodile */ new MonsterStatuetteInfo(1041249, 0x20DA, 660), - /* Daemon */ new MonsterStatuetteInfo(1041250, 0x20D3, 357), - /* Dragon */ new MonsterStatuetteInfo(1041251, 0x20D6, 362), - /* EarthElemental */ new MonsterStatuetteInfo(1041252, 0x20D7, 268), - /* Ettin */ new MonsterStatuetteInfo(1041253, 0x20D8, 367), - /* Gargoyle */ new MonsterStatuetteInfo(1041254, 0x20D9, 372), - /* Gorilla */ new MonsterStatuetteInfo(1041255, 0x20F5, 158), - /* Lich */ new MonsterStatuetteInfo(1041256, 0x20F8, 1001), - /* Lizardman */ new MonsterStatuetteInfo(1041257, 0x20DE, 417), - /* Ogre */ new MonsterStatuetteInfo(1041258, 0x20DF, 427), - /* Orc */ new MonsterStatuetteInfo(1041259, 0x20E0, 1114), - /* Ratman */ new MonsterStatuetteInfo(1041260, 0x20E3, 437), - /* Skeleton */ new MonsterStatuetteInfo(1041261, 0x20E7, 1165), - /* Troll */ new MonsterStatuetteInfo(1041262, 0x20E9, 461), - /* Cow */ new MonsterStatuetteInfo(1041263, 0x2103, 120), - /* Zombie */ new MonsterStatuetteInfo(1041264, 0x20EC, 471), - /* Llama */ new MonsterStatuetteInfo(1041265, 0x20F6, 1011), - /* Ophidian */ new MonsterStatuetteInfo(1049742, 0x2133, 634), - /* Reaper */ new MonsterStatuetteInfo(1049743, 0x20FA, 442), - /* Mongbat */ new MonsterStatuetteInfo(1049744, 0x20F9, 422), - /* Gazer */ new MonsterStatuetteInfo(1049768, 0x20F4, 377), - /* FireElemental */ new MonsterStatuetteInfo(1049769, 0x20F3, 838), - /* Wolf */ new MonsterStatuetteInfo(1049770, 0x2122, 229), - /* Phillip's Steed */ new MonsterStatuetteInfo(1063488, 0x3FFE, 168), - /* Seahorse */ new MonsterStatuetteInfo(1070819, 0x25BA, 138), - /* Harrower */ new MonsterStatuetteInfo(1080520, 0x25BB, new[] { 0x289, 0x28A, 0x28B }), - /* Efreet */ new MonsterStatuetteInfo(1080521, 0x2590, 0x300), - /* Slime */ new MonsterStatuetteInfo(1015246, 0x20E8, 456), - /* PlagueBeast */ new MonsterStatuetteInfo(1029747, 0x2613, 0x1BF), - /* RedDeath */ new MonsterStatuetteInfo(1094932, 0x2617, new int[] { }), - /* Spider */ new MonsterStatuetteInfo(1029668, 0x25C4, 1170), - /* OphidianArchMage */ new MonsterStatuetteInfo(1029641, 0x25A9, 639), - /* OphidianWarrior */ new MonsterStatuetteInfo(1029645, 0x25AD, 634), - /* OphidianKnight */ new MonsterStatuetteInfo(1029642, 0x25aa, 634), - /* OphidianMage */ new MonsterStatuetteInfo(1029643, 0x25ab, 639), - /* DreadHorn */ new MonsterStatuetteInfo(1031651, 0x2D83, 0xA8), - /* Minotaur */ new MonsterStatuetteInfo(1031657, 0x2D89, 0x596), - /* Black Cat */ new MonsterStatuetteInfo(1096928, 0x4688, 0x69), - /* HalloweenGhoul */ new MonsterStatuetteInfo(1076782, 0x2109, 0x482), - /* Santa */ new MonsterStatuetteInfo(1097968, 0x4A98, 0x669) - }; - - public MonsterStatuetteInfo(int labelNumber, int itemID, int baseSoundID) - { - LabelNumber = labelNumber; - ItemID = itemID; - Sounds = new[] { baseSoundID, baseSoundID + 1, baseSoundID + 2, baseSoundID + 3, baseSoundID + 4 }; + Crocodile, + Daemon, + Dragon, + EarthElemental, + Ettin, + Gargoyle, + Gorilla, + Lich, + Lizardman, + Ogre, + Orc, + Ratman, + Skeleton, + Troll, + Cow, + Zombie, + Llama, + Ophidian, + Reaper, + Mongbat, + Gazer, + FireElemental, + Wolf, + PhillipsWoodenSteed, + Seahorse, + Harrower, + Efreet, + Slime, + PlagueBeast, + RedDeath, + Spider, + OphidianArchMage, + OphidianWarrior, + OphidianKnight, + OphidianMage, + DreadHorn, + Minotaur, + BlackCat, + HalloweenGhoul, + Santa } - public MonsterStatuetteInfo(int labelNumber, int itemID, int[] sounds) + public class MonsterStatuetteInfo { - LabelNumber = labelNumber; - ItemID = itemID; - Sounds = sounds; - } - - public int LabelNumber { get; } - - public int ItemID { get; } - - public int[] Sounds { get; } - - public static MonsterStatuetteInfo GetInfo(MonsterStatuetteType type) - { - int v = (int)type; - - if (v < 0 || v >= m_Table.Length) - v = 0; - - return m_Table[v]; - } - } - - public class MonsterStatuette : Item, IRewardItem - { - private bool m_TurnedOn; - private MonsterStatuetteType m_Type; - - [Constructible] - public MonsterStatuette(MonsterStatuetteType type = MonsterStatuetteType.Crocodile) : base(MonsterStatuetteInfo.GetInfo(type).ItemID) - { - LootType = LootType.Blessed; - - m_Type = type; - - if (m_Type == MonsterStatuetteType.Slime) - Hue = Utility.RandomSlimeHue(); - else if (m_Type == MonsterStatuetteType.RedDeath) - Hue = 0x21; - else if (m_Type == MonsterStatuetteType.HalloweenGhoul) - Hue = 0xF4; - } - - public MonsterStatuette(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool TurnedOn - { - get => m_TurnedOn; - set - { - m_TurnedOn = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public MonsterStatuetteType Type - { - get => m_Type; - set - { - m_Type = value; - ItemID = MonsterStatuetteInfo.GetInfo(m_Type).ItemID; - - if (m_Type == MonsterStatuetteType.Slime) - Hue = Utility.RandomSlimeHue(); - else if (m_Type == MonsterStatuetteType.RedDeath) - Hue = 0x21; - else if (m_Type == MonsterStatuetteType.HalloweenGhoul) - Hue = 0xF4; - else - Hue = 0; - - InvalidateProperties(); - } - } - - public override int LabelNumber => MonsterStatuetteInfo.GetInfo(m_Type).LabelNumber; - - public override double DefaultWeight => 1.0; - - public override bool HandlesOnMovement => m_TurnedOn && IsLockedDown; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem { get; set; } - - 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)) - { - int[] sounds = MonsterStatuetteInfo.GetInfo(m_Type).Sounds; - - if (sounds.Length > 0) - Effects.PlaySound(Location, Map, sounds.RandomElement()); - } - - base.OnMovement(m, oldLocation); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Core.ML && IsRewardItem) - list.Add(RewardSystem.GetRewardYearLabel(this, new object[] { m_Type })); // X Year Veteran Reward - - 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)) - { - OnOffGump onOffGump = new OnOffGump(this); - from.SendGump(onOffGump); - } - 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.WriteEncodedInt((int)m_Type); - writer.Write(m_TurnedOn); - writer.Write(IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Type = (MonsterStatuetteType)reader.ReadEncodedInt(); - m_TurnedOn = reader.ReadBool(); - IsRewardItem = reader.ReadBool(); - break; - } - } - } - - private class OnOffGump : Gump - { - private readonly MonsterStatuette m_Statuette; - - public OnOffGump(MonsterStatuette statuette) : base(150, 200) - { - m_Statuette = statuette; - - AddBackground(0, 0, 300, 150, 0xA28); - - AddHtmlLocalized(45, 20, 300, 35, statuette.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) - { - Mobile from = sender.Mobile; - - if (info.ButtonID == 1) + private static readonly MonsterStatuetteInfo[] m_Table = { - bool newValue = !m_Statuette.TurnedOn; - m_Statuette.TurnedOn = newValue; + /* Crocodile */ new MonsterStatuetteInfo(1041249, 0x20DA, 660), + /* Daemon */ new MonsterStatuetteInfo(1041250, 0x20D3, 357), + /* Dragon */ new MonsterStatuetteInfo(1041251, 0x20D6, 362), + /* EarthElemental */ new MonsterStatuetteInfo(1041252, 0x20D7, 268), + /* Ettin */ new MonsterStatuetteInfo(1041253, 0x20D8, 367), + /* Gargoyle */ new MonsterStatuetteInfo(1041254, 0x20D9, 372), + /* Gorilla */ new MonsterStatuetteInfo(1041255, 0x20F5, 158), + /* Lich */ new MonsterStatuetteInfo(1041256, 0x20F8, 1001), + /* Lizardman */ new MonsterStatuetteInfo(1041257, 0x20DE, 417), + /* Ogre */ new MonsterStatuetteInfo(1041258, 0x20DF, 427), + /* Orc */ new MonsterStatuetteInfo(1041259, 0x20E0, 1114), + /* Ratman */ new MonsterStatuetteInfo(1041260, 0x20E3, 437), + /* Skeleton */ new MonsterStatuetteInfo(1041261, 0x20E7, 1165), + /* Troll */ new MonsterStatuetteInfo(1041262, 0x20E9, 461), + /* Cow */ new MonsterStatuetteInfo(1041263, 0x2103, 120), + /* Zombie */ new MonsterStatuetteInfo(1041264, 0x20EC, 471), + /* Llama */ new MonsterStatuetteInfo(1041265, 0x20F6, 1011), + /* Ophidian */ new MonsterStatuetteInfo(1049742, 0x2133, 634), + /* Reaper */ new MonsterStatuetteInfo(1049743, 0x20FA, 442), + /* Mongbat */ new MonsterStatuetteInfo(1049744, 0x20F9, 422), + /* Gazer */ new MonsterStatuetteInfo(1049768, 0x20F4, 377), + /* FireElemental */ new MonsterStatuetteInfo(1049769, 0x20F3, 838), + /* Wolf */ new MonsterStatuetteInfo(1049770, 0x2122, 229), + /* Phillip's Steed */ new MonsterStatuetteInfo(1063488, 0x3FFE, 168), + /* Seahorse */ new MonsterStatuetteInfo(1070819, 0x25BA, 138), + /* Harrower */ new MonsterStatuetteInfo(1080520, 0x25BB, new[] { 0x289, 0x28A, 0x28B }), + /* Efreet */ new MonsterStatuetteInfo(1080521, 0x2590, 0x300), + /* Slime */ new MonsterStatuetteInfo(1015246, 0x20E8, 456), + /* PlagueBeast */ new MonsterStatuetteInfo(1029747, 0x2613, 0x1BF), + /* RedDeath */ new MonsterStatuetteInfo(1094932, 0x2617, new int[] { }), + /* Spider */ new MonsterStatuetteInfo(1029668, 0x25C4, 1170), + /* OphidianArchMage */ new MonsterStatuetteInfo(1029641, 0x25A9, 639), + /* OphidianWarrior */ new MonsterStatuetteInfo(1029645, 0x25AD, 634), + /* OphidianKnight */ new MonsterStatuetteInfo(1029642, 0x25aa, 634), + /* OphidianMage */ new MonsterStatuetteInfo(1029643, 0x25ab, 639), + /* DreadHorn */ new MonsterStatuetteInfo(1031651, 0x2D83, 0xA8), + /* Minotaur */ new MonsterStatuetteInfo(1031657, 0x2D89, 0x596), + /* Black Cat */ new MonsterStatuetteInfo(1096928, 0x4688, 0x69), + /* HalloweenGhoul */ new MonsterStatuetteInfo(1076782, 0x2109, 0x482), + /* Santa */ new MonsterStatuetteInfo(1097968, 0x4A98, 0x669) + }; - if (newValue && !m_Statuette.IsLockedDown) - from.SendLocalizedMessage(502693); // Remember, this only works when locked down. - } - else + public MonsterStatuetteInfo(int labelNumber, int itemID, int baseSoundID) { - from.SendLocalizedMessage(502694); // Cancelled action. + LabelNumber = labelNumber; + ItemID = itemID; + Sounds = new[] { baseSoundID, baseSoundID + 1, baseSoundID + 2, baseSoundID + 3, baseSoundID + 4 }; + } + + public MonsterStatuetteInfo(int labelNumber, int itemID, int[] sounds) + { + LabelNumber = labelNumber; + ItemID = itemID; + Sounds = sounds; + } + + public int LabelNumber { get; } + + public int ItemID { get; } + + public int[] Sounds { get; } + + public static MonsterStatuetteInfo GetInfo(MonsterStatuetteType type) + { + var v = (int)type; + + if (v < 0 || v >= m_Table.Length) + v = 0; + + return m_Table[v]; + } + } + + public class MonsterStatuette : Item, IRewardItem + { + private bool m_TurnedOn; + private MonsterStatuetteType m_Type; + + [Constructible] + public MonsterStatuette(MonsterStatuetteType type = MonsterStatuetteType.Crocodile) : base( + MonsterStatuetteInfo.GetInfo(type).ItemID + ) + { + LootType = LootType.Blessed; + + m_Type = type; + + if (m_Type == MonsterStatuetteType.Slime) + Hue = Utility.RandomSlimeHue(); + else if (m_Type == MonsterStatuetteType.RedDeath) + Hue = 0x21; + else if (m_Type == MonsterStatuetteType.HalloweenGhoul) + Hue = 0xF4; + } + + public MonsterStatuette(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool TurnedOn + { + get => m_TurnedOn; + set + { + m_TurnedOn = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public MonsterStatuetteType Type + { + get => m_Type; + set + { + m_Type = value; + ItemID = MonsterStatuetteInfo.GetInfo(m_Type).ItemID; + + if (m_Type == MonsterStatuetteType.Slime) + Hue = Utility.RandomSlimeHue(); + else if (m_Type == MonsterStatuetteType.RedDeath) + Hue = 0x21; + else if (m_Type == MonsterStatuetteType.HalloweenGhoul) + Hue = 0xF4; + else + Hue = 0; + + InvalidateProperties(); + } + } + + public override int LabelNumber => MonsterStatuetteInfo.GetInfo(m_Type).LabelNumber; + + public override double DefaultWeight => 1.0; + + public override bool HandlesOnMovement => m_TurnedOn && IsLockedDown; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem { get; set; } + + 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)) + { + var sounds = MonsterStatuetteInfo.GetInfo(m_Type).Sounds; + + if (sounds.Length > 0) + Effects.PlaySound(Location, Map, sounds.RandomElement()); + } + + base.OnMovement(m, oldLocation); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (Core.ML && IsRewardItem) + list.Add(RewardSystem.GetRewardYearLabel(this, new object[] { m_Type })); // X Year Veteran Reward + + 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)) + { + var onOffGump = new OnOffGump(this); + from.SendGump(onOffGump); + } + 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.WriteEncodedInt((int)m_Type); + writer.Write(m_TurnedOn); + writer.Write(IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Type = (MonsterStatuetteType)reader.ReadEncodedInt(); + m_TurnedOn = reader.ReadBool(); + IsRewardItem = reader.ReadBool(); + break; + } + } + } + + private class OnOffGump : Gump + { + private readonly MonsterStatuette m_Statuette; + + public OnOffGump(MonsterStatuette statuette) : base(150, 200) + { + m_Statuette = statuette; + + AddBackground(0, 0, 300, 150, 0xA28); + + AddHtmlLocalized(45, 20, 300, 35, statuette.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_Statuette.TurnedOn; + m_Statuette.TurnedOn = newValue; + + if (newValue && !m_Statuette.IsLockedDown) + from.SendLocalizedMessage(502693); // Remember, this only works when locked down. + } + else + { + from.SendLocalizedMessage(502694); // Cancelled action. + } + } } - } } - } } diff --git a/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastBackpack.cs b/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastBackpack.cs index 398c3ffb3..f9e6a6368 100644 --- a/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastBackpack.cs +++ b/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastBackpack.cs @@ -2,175 +2,175 @@ using System.Collections.Generic; namespace Server.Items { - public class PlagueBeastBackpack : BaseContainer - { - private static readonly int[,,] m_Positions = + public class PlagueBeastBackpack : BaseContainer { - { { 275, 85 }, { 360, 111 }, { 375, 184 }, { 332, 228 }, { 141, 105 }, { 189, 75 } }, - { { 274, 34 }, { 327, 89 }, { 354, 168 }, { 304, 225 }, { 113, 86 }, { 189, 75 } }, - { { 276, 79 }, { 369, 117 }, { 372, 192 }, { 336, 230 }, { 141, 116 }, { 189, 75 } } - }; - - private static readonly int[] m_BrainHues = - { - 0x2B, 0x42, 0x54, 0x60 - }; - - public PlagueBeastBackpack() : base(0x261B) => Layer = Layer.Backpack; - - public PlagueBeastBackpack(Serial serial) : base(serial) - { - } - - public override int DefaultMaxWeight => 0; - public override int DefaultMaxItems => 0; - public override int DefaultGumpID => 0x2A63; - public override int DefaultDropSound => 0x23F; - - public void Initialize() - { - AddInnard(0x1CF6, 0x0, 227, 128); - AddInnard(0x1D10, 0x0, 251, 128); - AddInnard(0x1FBE, 0x21, 240, 83); - - AddInnard(new PlagueBeastHeart(), 229, 104); - - AddInnard(0x1D06, 0x0, 283, 91); - AddInnard(0x1FAF, 0x21, 315, 107); - AddInnard(0x1FB9, 0x21, 289, 87); - AddInnard(0x9E7, 0x21, 304, 96); - AddInnard(0x1B1A, 0x66D, 335, 102); - AddInnard(0x1D10, 0x0, 338, 146); - AddInnard(0x1FB3, 0x21, 358, 167); - AddInnard(0x1D0B, 0x0, 357, 155); - AddInnard(0x9E7, 0x21, 339, 184); - AddInnard(0x1B1A, 0x66D, 157, 172); - AddInnard(0x1D11, 0x0, 147, 157); - AddInnard(0x1FB9, 0x21, 121, 131); - AddInnard(0x9E7, 0x21, 166, 176); - AddInnard(0x1D0B, 0x0, 122, 138); - AddInnard(0x1D0D, 0x0, 118, 150); - AddInnard(0x1FB3, 0x21, 97, 123); - AddInnard(0x1D08, 0x0, 115, 113); - AddInnard(0x9E7, 0x21, 109, 109); - AddInnard(0x9E7, 0x21, 91, 122); - AddInnard(0x9E7, 0x21, 94, 160); - AddInnard(0x1B19, 0x66D, 170, 121); - AddInnard(0x1FAF, 0x21, 161, 111); - AddInnard(0x1D0B, 0x0, 158, 112); - AddInnard(0x9E7, 0x21, 159, 101); - AddInnard(0x1D10, 0x0, 132, 177); - AddInnard(0x1D0E, 0x0, 110, 178); - AddInnard(0x1FB3, 0x21, 95, 194); - AddInnard(0x1FAF, 0x21, 154, 203); - AddInnard(0x1B1A, 0x66D, 110, 237); - AddInnard(0x9E7, 0x21, 111, 171); - AddInnard(0x9E7, 0x21, 90, 197); - AddInnard(0x9E7, 0x21, 166, 205); - AddInnard(0x9E7, 0x21, 96, 242); - AddInnard(0x1D10, 0x0, 334, 196); - AddInnard(0x1D0B, 0x0, 322, 270); - - List organs = new List(); - PlagueBeastOrgan organ; - - for (int i = 0; i < 6; i++) - { - int random = Utility.Random(3); - - if (i == 5) - random = 0; - - organ = random switch + private static readonly int[,,] m_Positions = { - 0 => new PlagueBeastRockOrgan(), - 1 => new PlagueBeastMaidenOrgan(), - 2 => new PlagueBeastRubbleOrgan(), - _ => new PlagueBeastRockOrgan() + { { 275, 85 }, { 360, 111 }, { 375, 184 }, { 332, 228 }, { 141, 105 }, { 189, 75 } }, + { { 274, 34 }, { 327, 89 }, { 354, 168 }, { 304, 225 }, { 113, 86 }, { 189, 75 } }, + { { 276, 79 }, { 369, 117 }, { 372, 192 }, { 336, 230 }, { 141, 116 }, { 189, 75 } } }; - organs.Add(organ); - AddInnard(organ, m_Positions[random, i, 0], m_Positions[random, i, 1]); - } + private static readonly int[] m_BrainHues = + { + 0x2B, 0x42, 0x54, 0x60 + }; - organ = new PlagueBeastBackupOrgan(); - organs.Add(organ); - AddInnard(organ, 129, 214); + public PlagueBeastBackpack() : base(0x261B) => Layer = Layer.Backpack; - for (int i = 0; i < m_BrainHues.Length; i++) - { - organ = organs.RandomElement(); - organ.BrainHue = m_BrainHues[i]; - organs.Remove(organ); - } + public PlagueBeastBackpack(Serial serial) : base(serial) + { + } - organs.Clear(); + public override int DefaultMaxWeight => 0; + public override int DefaultMaxItems => 0; + public override int DefaultGumpID => 0x2A63; + public override int DefaultDropSound => 0x23F; - AddInnard(new PlagueBeastMainOrgan(), 240, 161); - } + public void Initialize() + { + AddInnard(0x1CF6, 0x0, 227, 128); + AddInnard(0x1D10, 0x0, 251, 128); + AddInnard(0x1FBE, 0x21, 240, 83); - public override bool TryDropItem(Mobile from, Item dropped, bool sendFullMessage) - { - if (dropped is PlagueBeastInnard || dropped is PlagueBeastGland) - return base.TryDropItem(from, dropped, sendFullMessage); + AddInnard(new PlagueBeastHeart(), 229, 104); - return false; - } + AddInnard(0x1D06, 0x0, 283, 91); + AddInnard(0x1FAF, 0x21, 315, 107); + AddInnard(0x1FB9, 0x21, 289, 87); + AddInnard(0x9E7, 0x21, 304, 96); + AddInnard(0x1B1A, 0x66D, 335, 102); + AddInnard(0x1D10, 0x0, 338, 146); + AddInnard(0x1FB3, 0x21, 358, 167); + AddInnard(0x1D0B, 0x0, 357, 155); + AddInnard(0x9E7, 0x21, 339, 184); + AddInnard(0x1B1A, 0x66D, 157, 172); + AddInnard(0x1D11, 0x0, 147, 157); + AddInnard(0x1FB9, 0x21, 121, 131); + AddInnard(0x9E7, 0x21, 166, 176); + AddInnard(0x1D0B, 0x0, 122, 138); + AddInnard(0x1D0D, 0x0, 118, 150); + AddInnard(0x1FB3, 0x21, 97, 123); + AddInnard(0x1D08, 0x0, 115, 113); + AddInnard(0x9E7, 0x21, 109, 109); + AddInnard(0x9E7, 0x21, 91, 122); + AddInnard(0x9E7, 0x21, 94, 160); + AddInnard(0x1B19, 0x66D, 170, 121); + AddInnard(0x1FAF, 0x21, 161, 111); + AddInnard(0x1D0B, 0x0, 158, 112); + AddInnard(0x9E7, 0x21, 159, 101); + AddInnard(0x1D10, 0x0, 132, 177); + AddInnard(0x1D0E, 0x0, 110, 178); + AddInnard(0x1FB3, 0x21, 95, 194); + AddInnard(0x1FAF, 0x21, 154, 203); + AddInnard(0x1B1A, 0x66D, 110, 237); + AddInnard(0x9E7, 0x21, 111, 171); + AddInnard(0x9E7, 0x21, 90, 197); + AddInnard(0x9E7, 0x21, 166, 205); + AddInnard(0x9E7, 0x21, 96, 242); + AddInnard(0x1D10, 0x0, 334, 196); + AddInnard(0x1D0B, 0x0, 322, 270); - public override bool OnDragDropInto(Mobile from, Item item, Point3D p) - { - if (IsAccessibleTo(from) && (item is PlagueBeastInnard || item is PlagueBeastGland)) - { - Rectangle2D ir = ItemBounds.Table[item.ItemID]; - int x, y; - int cx = p.X + ir.X + ir.Width / 2; - int cy = p.Y + ir.Y + ir.Height / 2; + var organs = new List(); + PlagueBeastOrgan organ; - for (int i = Items.Count - 1; i >= 0; i--) - if (Items[i] is PlagueBeastComponent innard) - { - Rectangle2D r = ItemBounds.Table[innard.ItemID]; - - x = innard.X + r.X; - y = innard.Y + r.Y; - - if (cx >= x && cx <= x + r.Width && cy >= y && cy <= y + r.Height) + for (var i = 0; i < 6; i++) { - innard.OnDragDrop(from, item); - break; + var random = Utility.Random(3); + + if (i == 5) + random = 0; + + organ = random switch + { + 0 => new PlagueBeastRockOrgan(), + 1 => new PlagueBeastMaidenOrgan(), + 2 => new PlagueBeastRubbleOrgan(), + _ => new PlagueBeastRockOrgan() + }; + + organs.Add(organ); + AddInnard(organ, m_Positions[random, i, 0], m_Positions[random, i, 1]); } - } - return base.OnDragDropInto(from, item, p); - } + organ = new PlagueBeastBackupOrgan(); + organs.Add(organ); + AddInnard(organ, 129, 214); - return false; + for (var i = 0; i < m_BrainHues.Length; i++) + { + organ = organs.RandomElement(); + organ.BrainHue = m_BrainHues[i]; + organs.Remove(organ); + } + + organs.Clear(); + + AddInnard(new PlagueBeastMainOrgan(), 240, 161); + } + + public override bool TryDropItem(Mobile from, Item dropped, bool sendFullMessage) + { + if (dropped is PlagueBeastInnard || dropped is PlagueBeastGland) + return base.TryDropItem(from, dropped, sendFullMessage); + + return false; + } + + public override bool OnDragDropInto(Mobile from, Item item, Point3D p) + { + if (IsAccessibleTo(from) && (item is PlagueBeastInnard || item is PlagueBeastGland)) + { + var ir = ItemBounds.Table[item.ItemID]; + int x, y; + var cx = p.X + ir.X + ir.Width / 2; + var cy = p.Y + ir.Y + ir.Height / 2; + + for (var i = Items.Count - 1; i >= 0; i--) + if (Items[i] is PlagueBeastComponent innard) + { + var r = ItemBounds.Table[innard.ItemID]; + + x = innard.X + r.X; + y = innard.Y + r.Y; + + if (cx >= x && cx <= x + r.Width && cy >= y && cy <= y + r.Height) + { + innard.OnDragDrop(from, item); + break; + } + } + + return base.OnDragDropInto(from, item, p); + } + + return false; + } + + public void AddInnard(int itemID, int hue, int x, int y) + { + AddInnard(new PlagueBeastInnard(itemID, hue), x, y); + } + + public void AddInnard(PlagueBeastInnard innard, int x, int y) + { + AddItem(innard); + innard.Location = new Point3D(x, y, 0); + innard.Map = Map; + } + + 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(); + } } - - public void AddInnard(int itemID, int hue, int x, int y) - { - AddInnard(new PlagueBeastInnard(itemID, hue), x, y); - } - - public void AddInnard(PlagueBeastInnard innard, int x, int y) - { - AddItem(innard); - innard.Location = new Point3D(x, y, 0); - innard.Map = Map; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastBlood.cs b/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastBlood.cs index bf61c632d..89f667533 100644 --- a/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastBlood.cs +++ b/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastBlood.cs @@ -3,105 +3,110 @@ using Server.Network; namespace Server.Items { - public class PlagueBeastBlood : PlagueBeastComponent - { - private readonly Timer m_Timer; - - public PlagueBeastBlood() : base(0x122C, 0) => m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(1.5), TimeSpan.FromSeconds(1.5), 3, Hemorrhage); - - public PlagueBeastBlood(Serial serial) : base(serial) + public class PlagueBeastBlood : PlagueBeastComponent { - } + private readonly Timer m_Timer; - public bool Patched => ItemID == 0x1765; + public PlagueBeastBlood() : base(0x122C, 0) => m_Timer = Timer.DelayCall( + TimeSpan.FromSeconds(1.5), + TimeSpan.FromSeconds(1.5), + 3, + Hemorrhage + ); - public bool Starting => ItemID == 0x122C; - - public override void OnAfterDelete() - { - if (m_Timer?.Running == true) - m_Timer.Stop(); - } - - public override bool OnBandage(Mobile from) - { - if (IsAccessibleTo(from) && !Patched) - { - if (m_Timer?.Running == true) - m_Timer.Stop(); - - if (Starting) + public PlagueBeastBlood(Serial serial) : base(serial) { - X += 2; - Y -= 9; - - if (Organ is PlagueBeastRubbleOrgan) - Y -= 5; - else if (Organ is PlagueBeastBackupOrgan) - X += 7; - } - else - { - X -= 4; - Y -= 2; } - ItemID = 0x1765; + public bool Patched => ItemID == 0x1765; - Container pack = Owner?.Backpack; + public bool Starting => ItemID == 0x122C; - if (pack != null) - for (int i = 0; i < pack.Items.Count; i++) - if (pack.Items[i] is PlagueBeastMainOrgan main && main.Complete) - main.FinishOpening(from); - - PublicOverheadMessage(MessageType.Regular, 0x3B2, 1071916); // * You patch up the wound with a bandage * - - return true; - } - - return false; - } - - private void Hemorrhage() - { - if (Patched) - return; - - Owner?.PlaySound(0x25); - - if (ItemID == 0x122A) - { - if (Owner != null) + public override void OnAfterDelete() { - Owner.Unfreeze(); - Owner.Kill(); - } - } - else - { - if (Starting) - { - X += 8; - Y -= 10; + if (m_Timer?.Running == true) + m_Timer.Stop(); } - ItemID--; - } + public override bool OnBandage(Mobile from) + { + if (IsAccessibleTo(from) && !Patched) + { + if (m_Timer?.Running == true) + m_Timer.Stop(); + + if (Starting) + { + X += 2; + Y -= 9; + + if (Organ is PlagueBeastRubbleOrgan) + Y -= 5; + else if (Organ is PlagueBeastBackupOrgan) + X += 7; + } + else + { + X -= 4; + Y -= 2; + } + + ItemID = 0x1765; + + var pack = Owner?.Backpack; + + if (pack != null) + for (var i = 0; i < pack.Items.Count; i++) + if (pack.Items[i] is PlagueBeastMainOrgan main && main.Complete) + main.FinishOpening(from); + + PublicOverheadMessage(MessageType.Regular, 0x3B2, 1071916); // * You patch up the wound with a bandage * + + return true; + } + + return false; + } + + private void Hemorrhage() + { + if (Patched) + return; + + Owner?.PlaySound(0x25); + + if (ItemID == 0x122A) + { + if (Owner != null) + { + Owner.Unfreeze(); + Owner.Kill(); + } + } + else + { + if (Starting) + { + X += 8; + Y -= 10; + } + + ItemID--; + } + } + + 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(); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastGland.cs b/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastGland.cs index dc84fdd01..ba21f2d1d 100644 --- a/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastGland.cs +++ b/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastGland.cs @@ -1,32 +1,32 @@ namespace Server.Items { - public class PlagueBeastGland : Item - { - [Constructible] - public PlagueBeastGland() : base(0x1CEF) + public class PlagueBeastGland : Item { - Weight = 1.0; - Hue = 0x6; + [Constructible] + public PlagueBeastGland() : base(0x1CEF) + { + Weight = 1.0; + Hue = 0x6; + } + + public PlagueBeastGland(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a healthy gland"; + + 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(); + } } - - public PlagueBeastGland(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a healthy gland"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastHeart.cs b/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastHeart.cs index 0b0427e05..af32640e0 100644 --- a/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastHeart.cs +++ b/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastHeart.cs @@ -2,75 +2,76 @@ using System; namespace Server.Items { - public class PlagueBeastHeart : PlagueBeastInnard - { - private Timer m_Timer; - - public PlagueBeastHeart() : base(0x1363, 0x21) + public class PlagueBeastHeart : PlagueBeastInnard { - m_Timer = new InternalTimer(this); - m_Timer.Start(); - } + private Timer m_Timer; - public PlagueBeastHeart(Serial serial) : base(serial) - { - } - - public override void OnAfterDelete() - { - if (m_Timer?.Running == true) - m_Timer.Stop(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_Timer = new InternalTimer(this); - m_Timer.Start(); - } - - private class InternalTimer : Timer - { - private bool m_Delay; - private readonly PlagueBeastHeart m_Heart; - - public InternalTimer(PlagueBeastHeart heart) : base(TimeSpan.FromSeconds(0.5), TimeSpan.FromSeconds(0.5)) => m_Heart = heart; - - protected override void OnTick() - { - if (m_Heart?.Deleted != false || m_Heart.Owner?.Alive != true) + public PlagueBeastHeart() : base(0x1363, 0x21) { - Stop(); - return; + m_Timer = new InternalTimer(this); + m_Timer.Start(); } - if (m_Heart.ItemID == 0x1363) + public PlagueBeastHeart(Serial serial) : base(serial) { - if (m_Delay) - { - m_Heart.ItemID = 0x1367; - m_Heart.Owner.PlaySound(0x11F); - } + } - m_Delay = !m_Delay; - } - else + public override void OnAfterDelete() { - m_Heart.ItemID = 0x1363; - m_Heart.Owner.PlaySound(0x120); - m_Delay = false; + if (m_Timer?.Running == true) + m_Timer.Stop(); + } + + 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(); + + m_Timer = new InternalTimer(this); + m_Timer.Start(); + } + + private class InternalTimer : Timer + { + private readonly PlagueBeastHeart m_Heart; + private bool m_Delay; + + public InternalTimer(PlagueBeastHeart heart) : base(TimeSpan.FromSeconds(0.5), TimeSpan.FromSeconds(0.5)) => + m_Heart = heart; + + protected override void OnTick() + { + if (m_Heart?.Deleted != false || m_Heart.Owner?.Alive != true) + { + Stop(); + return; + } + + if (m_Heart.ItemID == 0x1363) + { + if (m_Delay) + { + m_Heart.ItemID = 0x1367; + m_Heart.Owner.PlaySound(0x11F); + } + + m_Delay = !m_Delay; + } + else + { + m_Heart.ItemID = 0x1363; + m_Heart.Owner.PlaySound(0x120); + m_Delay = false; + } + } } - } } - } } diff --git a/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastInnard.cs b/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastInnard.cs index dccf5690c..ae32a24b1 100644 --- a/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastInnard.cs +++ b/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastInnard.cs @@ -3,140 +3,148 @@ using Server.Network; namespace Server.Items { - public class PlagueBeastInnard : Item, IScissorable, ICarvable - { - public PlagueBeastInnard(int itemID, int hue) : base(itemID) + public class PlagueBeastInnard : Item, IScissorable, ICarvable { - Hue = hue; - Movable = false; - Weight = 1.0; - } - - public PlagueBeastInnard(Serial serial) : base(serial) - { - } - - public PlagueBeastLord Owner => RootParent as PlagueBeastLord; - public override string DefaultName => "plague beast innards"; - - public virtual void Carve(Mobile from, Item with) - { - } - - public virtual bool Scissor(Mobile from, Scissors scissors) => false; - - public virtual bool OnBandage(Mobile from) => false; - - public override bool IsAccessibleTo(Mobile check) - { - if ((int)check.AccessLevel >= (int)AccessLevel.GameMaster) - return true; - - PlagueBeastLord owner = Owner; - - if (owner == null) - return false; - - if (!owner.InRange(check, 2)) - owner.PrivateOverheadMessage(MessageType.Label, 0x3B2, 500446, check.NetState); // That is too far away. - else if (owner.OpenedBy != null && owner.OpenedBy != check) // TODO check - owner.PrivateOverheadMessage(MessageType.Label, 0x3B2, 500365, - check.NetState); // That is being used by someone else - else if (owner.Frozen) - return true; - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - PlagueBeastLord owner = Owner; - - if (owner?.Alive != true) - Delete(); - } - } - - public class PlagueBeastComponent : PlagueBeastInnard - { - public PlagueBeastComponent(int itemID, int hue, bool movable = false) : base(itemID, hue) => Movable = movable; - - public PlagueBeastComponent(Serial serial) : base(serial) - { - } - - public PlagueBeastOrgan Organ { get; set; } - - public bool IsBrain => ItemID == 0x1CF0; - - public bool IsGland => ItemID == 0x1CEF; - - public bool IsReceptacle => ItemID == 0x9DF; - - public override bool DropToItem(Mobile from, Item target, Point3D p) => target is PlagueBeastBackpack && base.DropToItem(from, target, p); - - public override bool AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted) => false; - - public override bool DropToMobile(Mobile from, Mobile target, Point3D p) => false; - - public override bool DropToWorld(Mobile from, Point3D p) => false; - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (Organ?.OnDropped(from, dropped, this) == true && dropped is PlagueBeastComponent component) - Organ.Components.Add(component); - - return true; - } - - public override bool OnDragLift(Mobile from) - { - if (IsAccessibleTo(from)) - { - if (Organ?.OnLifted(from, this) == true) + public PlagueBeastInnard(int itemID, int hue) : base(itemID) { - from.SendLocalizedMessage(IsGland ? 1071895 : 1071914, null); // * You rip the organ out of the plague beast's flesh * - - if (Organ.Components.Contains(this)) - Organ.Components.Remove(this); - - Organ = null; - from.PlaySound(0x1CA); + Hue = hue; + Movable = false; + Weight = 1.0; } - return true; - } + public PlagueBeastInnard(Serial serial) : base(serial) + { + } - return false; + public PlagueBeastLord Owner => RootParent as PlagueBeastLord; + public override string DefaultName => "plague beast innards"; + + public virtual void Carve(Mobile from, Item with) + { + } + + public virtual bool Scissor(Mobile from, Scissors scissors) => false; + + public virtual bool OnBandage(Mobile from) => false; + + public override bool IsAccessibleTo(Mobile check) + { + if ((int)check.AccessLevel >= (int)AccessLevel.GameMaster) + return true; + + var owner = Owner; + + if (owner == null) + return false; + + if (!owner.InRange(check, 2)) + owner.PrivateOverheadMessage(MessageType.Label, 0x3B2, 500446, check.NetState); // That is too far away. + else if (owner.OpenedBy != null && owner.OpenedBy != check) // TODO check + owner.PrivateOverheadMessage( + MessageType.Label, + 0x3B2, + 500365, + check.NetState + ); // That is being used by someone else + else if (owner.Frozen) + return true; + + return false; + } + + 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(); + + var owner = Owner; + + if (owner?.Alive != true) + Delete(); + } } - public override void Serialize(IGenericWriter writer) + public class PlagueBeastComponent : PlagueBeastInnard { - base.Serialize(writer); + public PlagueBeastComponent(int itemID, int hue, bool movable = false) : base(itemID, hue) => Movable = movable; - writer.WriteEncodedInt(0); // version + public PlagueBeastComponent(Serial serial) : base(serial) + { + } - writer.WriteItem(Organ); + public PlagueBeastOrgan Organ { get; set; } + + public bool IsBrain => ItemID == 0x1CF0; + + public bool IsGland => ItemID == 0x1CEF; + + public bool IsReceptacle => ItemID == 0x9DF; + + public override bool DropToItem(Mobile from, Item target, Point3D p) => + target is PlagueBeastBackpack && base.DropToItem(from, target, p); + + public override bool AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted) => false; + + public override bool DropToMobile(Mobile from, Mobile target, Point3D p) => false; + + public override bool DropToWorld(Mobile from, Point3D p) => false; + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (Organ?.OnDropped(from, dropped, this) == true && dropped is PlagueBeastComponent component) + Organ.Components.Add(component); + + return true; + } + + public override bool OnDragLift(Mobile from) + { + if (IsAccessibleTo(from)) + { + if (Organ?.OnLifted(from, this) == true) + { + from.SendLocalizedMessage( + IsGland ? 1071895 : 1071914, + null + ); // * You rip the organ out of the plague beast's flesh * + + if (Organ.Components.Contains(this)) + Organ.Components.Remove(this); + + Organ = null; + from.PlaySound(0x1CA); + } + + return true; + } + + return false; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.WriteItem(Organ); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + Organ = reader.ReadItem(); + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - Organ = reader.ReadItem(); - } - } } diff --git a/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastMutationCore.cs b/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastMutationCore.cs index 3cac9bfb4..f1a0c8a2a 100644 --- a/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastMutationCore.cs +++ b/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastMutationCore.cs @@ -4,69 +4,72 @@ using Server.Network; namespace Server.Items { - public class PlagueBeastMutationCore : Item, IScissorable - { - [Constructible] - public PlagueBeastMutationCore() : base(0x1CF0) + public class PlagueBeastMutationCore : Item, IScissorable { - Cut = true; - Weight = 1.0; - Hue = 0x480; + [Constructible] + public PlagueBeastMutationCore() : base(0x1CF0) + { + Cut = true; + Weight = 1.0; + Hue = 0x480; + } + + public PlagueBeastMutationCore(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Cut { get; set; } + + public override string DefaultName => "a plague beast mutation core"; + + public virtual bool Scissor(Mobile from, Scissors scissors) + { + if (!Cut) + { + var owner = RootParent as PlagueBeastLord; + + Cut = true; + Movable = true; + + from.AddToBackpack(this); + from.LocalOverheadMessage( + MessageType.Regular, + 0x34, + 1071906 + ); // * You remove the plague mutation core from the plague beast, causing it to dissolve into a pile of goo * + + if (owner != null) + Timer.DelayCall(TimeSpan.FromSeconds(1), KillParent, owner); + + return true; + } + + return false; + } + + private void KillParent(PlagueBeastLord parent) + { + parent.Unfreeze(); + parent.Kill(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(Cut); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + Cut = reader.ReadBool(); + } } - - public PlagueBeastMutationCore(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Cut { get; set; } - - public override string DefaultName => "a plague beast mutation core"; - - public virtual bool Scissor(Mobile from, Scissors scissors) - { - if (!Cut) - { - PlagueBeastLord owner = RootParent as PlagueBeastLord; - - Cut = true; - Movable = true; - - from.AddToBackpack(this); - from.LocalOverheadMessage(MessageType.Regular, 0x34, - 1071906); // * You remove the plague mutation core from the plague beast, causing it to dissolve into a pile of goo * - - if (owner != null) - Timer.DelayCall(TimeSpan.FromSeconds(1), KillParent, owner); - - return true; - } - - return false; - } - - private void KillParent(PlagueBeastLord parent) - { - parent.Unfreeze(); - parent.Kill(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(Cut); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - Cut = reader.ReadBool(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastOrgans.cs b/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastOrgans.cs index c8d8264a3..a77104e26 100644 --- a/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastOrgans.cs +++ b/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastOrgans.cs @@ -4,547 +4,562 @@ using Server.Network; namespace Server.Items { - public class PlagueBeastOrgan : PlagueBeastInnard - { - private Timer m_Timer; - - public PlagueBeastOrgan(int itemID = 1, int hue = 0) : base(itemID, hue) + public class PlagueBeastOrgan : PlagueBeastInnard { - Components = new List(); - Opened = false; - Movable = false; - Visible = itemID <= 1; + private Timer m_Timer; - Timer.DelayCall(Initialize); - } - - public PlagueBeastOrgan(Serial serial) : base(serial) - { - } - - public virtual bool IsCuttable => false; - - public List Components { get; private set; } - - public int BrainHue { get; set; } - - public bool Opened { get; set; } - - public virtual void Initialize() - { - } - - public void AddComponent(PlagueBeastComponent c, int x, int y) - { - if (Parent is Container pack) - pack.DropItem(c); - - c.Organ = this; - c.Location = new Point3D(X + x, Y + y, Z); - c.Map = Map; - - Components.Add(c); - } - - public override bool Scissor(Mobile from, Scissors scissors) - { - if (IsCuttable && IsAccessibleTo(from)) - { - if (!Opened && m_Timer == null) + public PlagueBeastOrgan(int itemID = 1, int hue = 0) : base(itemID, hue) { - m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(3), FinishOpening, from); - scissors.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1071897); // You carefully cut into the organ. - return true; + Components = new List(); + Opened = false; + Movable = false; + Visible = itemID <= 1; + + Timer.DelayCall(Initialize); } - scissors.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1071898); // You have already cut this organ open. - } - - return false; - } - - public override void OnAfterDelete() - { - if (m_Timer?.Running == true) - m_Timer.Stop(); - } - - public virtual bool OnLifted(Mobile from, PlagueBeastComponent c) => c.IsGland || c.IsBrain; - - public virtual bool OnDropped(Mobile from, Item item, PlagueBeastComponent to) => false; - - public virtual void FinishOpening(Mobile from) - { - Opened = true; - - Owner?.PlaySound(0x50); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.WriteItemList(Components); - writer.Write(BrainHue); - writer.Write(Opened); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - Components = reader.ReadStrongItemList(); - BrainHue = reader.ReadInt(); - Opened = reader.ReadBool(); - } - } - - public class PlagueBeastMaidenOrgan : PlagueBeastOrgan - { - public PlagueBeastMaidenOrgan() : base(0x124D) - { - } - - public PlagueBeastMaidenOrgan(Serial serial) : base(serial) - { - } - - public override void OnDoubleClick(Mobile from) - { - if (!Opened) - FinishOpening(from); - } - - public override void FinishOpening(Mobile from) - { - ItemID = 0x1249; - - Owner?.PlaySound(0x187); - - AddComponent(new PlagueBeastComponent(0x1D0D, 0x0), 22, 3); - AddComponent(new PlagueBeastComponent(0x1D12, 0x0), 15, 18); - AddComponent(new PlagueBeastComponent(0x1DA3, 0x21), 26, 46); - - if (BrainHue > 0) - AddComponent(new PlagueBeastComponent(0x1CF0, BrainHue, true), 22, 29); - - Opened = true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class PlagueBeastRockOrgan : PlagueBeastOrgan - { - public PlagueBeastRockOrgan() : base(0x177A, 0x60) - { - } - - public PlagueBeastRockOrgan(Serial serial) : base(serial) - { - } - - public override bool IsCuttable => true; - - public override void Carve(Mobile from, Item with) - { - if (IsAccessibleTo(from)) - with.PublicOverheadMessage(MessageType.Regular, 0x3B2, - 1071896); // This is too crude an implement for such a procedure. - } - - public override bool OnLifted(Mobile from, PlagueBeastComponent c) - { - base.OnLifted(from, c); - - if (c.IsBrain) - { - AddComponent(new PlagueBeastBlood(), -7, 24); - return true; - } - - return false; - } - - public override void FinishOpening(Mobile from) - { - base.FinishOpening(from); - - AddComponent(new PlagueBeastComponent(0x1775, 0x60), 3, 5); - AddComponent(new PlagueBeastComponent(0x1777, 0x1), 10, 14); - - if (BrainHue > 0) - AddComponent(new PlagueBeastComponent(0x1CF0, BrainHue, true), 1, 24); // 22, 29 - else - AddComponent(new PlagueBeastBlood(), -7, 24); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class PlagueBeastRubbleOrgan : PlagueBeastOrgan - { - private static readonly int[] m_Hues = - { - 0xD, 0x17, 0x2B, 0x42, 0x54, 0x5D - }; - - private int m_Veins; - - public PlagueBeastRubbleOrgan() => m_Veins = 3; - - public PlagueBeastRubbleOrgan(Serial serial) : base(serial) - { - } - - public override void Initialize() - { - Hue = m_Hues.RandomElement(); - - AddComponent(new PlagueBeastComponent(0x3BB, Hue), 0, 0); - AddComponent(new PlagueBeastComponent(0x3BA, Hue), 4, 6); - AddComponent(new PlagueBeastComponent(0x3BA, Hue), -6, 17); - - int v = Utility.Random(4); - - AddComponent(new PlagueBeastVein(0x1B1B, v == 0 ? Hue : RandomHue(Hue)), -23, -3); - AddComponent(new PlagueBeastVein(0x1B1C, v == 1 ? Hue : RandomHue(Hue)), 19, 4); - AddComponent(new PlagueBeastVein(0x1B1B, v == 2 ? Hue : RandomHue(Hue)), 21, 27); - AddComponent(new PlagueBeastVein(0x1B1B, v == 3 ? Hue : RandomHue(Hue)), 10, 40); - } - - public override bool OnLifted(Mobile from, PlagueBeastComponent c) - { - if (c.IsBrain) - { - AddComponent(new PlagueBeastBlood(), -13, 25); - return true; - } - - return false; - } - - public override void FinishOpening(Mobile from) - { - AddComponent(new PlagueBeastComponent(0x1777, 0x1), 5, 14); - - if (BrainHue > 0) - AddComponent(new PlagueBeastComponent(0x1CF0, BrainHue, true), -5, 22); - else - AddComponent(new PlagueBeastBlood(), -13, 25); - - Opened = true; - } - - private static int RandomHue(int exclude) - { - for (int i = 0; i < 20; i++) - { - int hue = m_Hues.RandomElement(); - - if (hue != exclude) - return hue; - } - - return 0xD; - } - - public virtual void OnVeinCut(Mobile from, PlagueBeastVein vein) - { - if (vein.Hue != Hue) - { - if (!Opened && m_Veins > 0 && --m_Veins == 0) - FinishOpening(from); - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1071901); // * As you cut the vein, a cloud of poison is expelled from the plague beast's organ, and the plague beast dissolves into a puddle of goo * - from.ApplyPoison(from, Poison.Greater); - from.PlaySound(0x22F); - - if (Owner != null) + public PlagueBeastOrgan(Serial serial) : base(serial) { - Owner.Unfreeze(); - Owner.Kill(); } - } - } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public virtual bool IsCuttable => false; - writer.WriteEncodedInt(0); // version + public List Components { get; private set; } - writer.Write(m_Veins); - } + public int BrainHue { get; set; } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public bool Opened { get; set; } - int version = reader.ReadEncodedInt(); - - m_Veins = reader.ReadInt(); - } - } - - public class PlagueBeastBackupOrgan : PlagueBeastOrgan - { - private Item m_Gland; - - private Timer m_Timer; - - public PlagueBeastBackupOrgan() : base(0x1362, 0x6) - { - } - - public PlagueBeastBackupOrgan(Serial serial) : base(serial) - { - } - - public override bool IsCuttable => true; - - public override void Initialize() - { - AddComponent(new PlagueBeastComponent(0x1B1B, 0x42), 16, 39); - AddComponent(new PlagueBeastComponent(0x1B1B, 0x42), 39, 49); - AddComponent(new PlagueBeastComponent(0x1B1B, 0x42), 39, 48); - AddComponent(new PlagueBeastComponent(0x1B1B, 0x42), 44, 42); - AddComponent(new PlagueBeastComponent(0x1CF2, 0x42), 20, 34); - AddComponent(new PlagueBeastComponent(0x135F, 0x42), 47, 58); - AddComponent(new PlagueBeastComponent(0x1360, 0x42), 70, 68); - } - - public override void Carve(Mobile from, Item with) - { - if (IsAccessibleTo(from)) - with.PublicOverheadMessage(MessageType.Regular, 0x3B2, - 1071896); // This is too crude an implement for such a procedure. - } - - public override bool OnLifted(Mobile from, PlagueBeastComponent c) - { - if (c.IsBrain) - { - AddComponent(new PlagueBeastBlood(), 47, 72); - return true; - } - - if (c.IsGland) - { - m_Gland = null; - return true; - } - - return c.IsGland; - } - - public override bool OnDropped(Mobile from, Item item, PlagueBeastComponent to) - { - if (to.Hue == 0x1 && m_Gland == null && item is PlagueBeastGland) - { - m_Gland = item; - m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(3), FinishHealing); - from.SendAsciiMessage(0x3B2, "* You place the healthy gland inside the organ sac *"); - item.Movable = false; - - Owner?.PlaySound(0x20); - - return true; - } - - return false; - } - - public override void FinishOpening(Mobile from) - { - base.FinishOpening(from); - - AddComponent(new PlagueBeastComponent(0x1363, 0xF), -3, 3); - AddComponent(new PlagueBeastComponent(0x1365, 0x1), -3, 10); - - m_Gland = new PlagueBeastComponent(0x1CEF, 0x3F, true); - AddComponent((PlagueBeastComponent)m_Gland, -4, 16); - } - - public void FinishHealing() - { - for (int i = 0; i < 7 && i < Components.Count; i++) - Components[i].Hue = 0x6; - - m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(2), OpenOrgan); - } - - public void OpenOrgan() - { - AddComponent(new PlagueBeastComponent(0x1367, 0xF), 55, 61); - AddComponent(new PlagueBeastComponent(0x1366, 0x1), 57, 66); - - if (BrainHue > 0) - AddComponent(new PlagueBeastComponent(0x1CF0, BrainHue, true), 55, 69); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_Gland); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_Gland = reader.ReadItem(); - } - } - - public class PlagueBeastMainOrgan : PlagueBeastOrgan - { - private int m_Brains; - - public PlagueBeastMainOrgan() => m_Brains = 0; - - public PlagueBeastMainOrgan(Serial serial) : base(serial) - { - } - - public bool Complete => m_Brains >= 4; - - public override void Initialize() - { - // receptacles - AddComponent(new PlagueBeastComponent(0x1B1B, 0x42), -36, -2); - AddComponent(new PlagueBeastComponent(0x1FB3, 0x42), -42, 0); - AddComponent(new PlagueBeastComponent(0x9DF, 0x42), -53, -7); - - AddComponent(new PlagueBeastComponent(0x1B1C, 0x54), 29, 9); - AddComponent(new PlagueBeastComponent(0x1D06, 0x54), 18, -2); - AddComponent(new PlagueBeastComponent(0x9DF, 0x54), 36, -1); - - AddComponent(new PlagueBeastComponent(0x1D10, 0x2B), -36, 47); - AddComponent(new PlagueBeastComponent(0x1B1C, 0x2B), -24, 62); - AddComponent(new PlagueBeastComponent(0x9DF, 0x2B), -41, 74); - - AddComponent(new PlagueBeastComponent(0x1B1B, 0x60), 39, 56); - AddComponent(new PlagueBeastComponent(0x1FB4, 0x60), 34, 52); - AddComponent(new PlagueBeastComponent(0x9DF, 0x60), 45, 71); - - // main part - AddComponent(new PlagueBeastComponent(0x1351, 0x15), 23, 0); - AddComponent(new PlagueBeastComponent(0x134F, 0x15), -22, 0); - AddComponent(new PlagueBeastComponent(0x1350, 0x15), 0, 0); - } - - public override bool OnLifted(Mobile from, PlagueBeastComponent c) - { - if (c.IsBrain) - m_Brains--; - - return true; - } - - public override bool OnDropped(Mobile from, Item item, PlagueBeastComponent to) - { - if (!Opened && to.IsReceptacle && item.Hue == to.Hue) - { - to.Organ = this; - m_Brains++; - from.LocalOverheadMessage(MessageType.Regular, 0x34, - 1071913); // You place the organ in the fleshy receptacle near the core. - - if (Owner != null) + public virtual void Initialize() { - Owner.PlaySound(0x1BA); + } + + public void AddComponent(PlagueBeastComponent c, int x, int y) + { + if (Parent is Container pack) + pack.DropItem(c); + + c.Organ = this; + c.Location = new Point3D(X + x, Y + y, Z); + c.Map = Map; + + Components.Add(c); + } + + public override bool Scissor(Mobile from, Scissors scissors) + { + if (IsCuttable && IsAccessibleTo(from)) + { + if (!Opened && m_Timer == null) + { + m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(3), FinishOpening, from); + scissors.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1071897); // You carefully cut into the organ. + return true; + } + + scissors.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1071898); // You have already cut this organ open. + } + + return false; + } + + public override void OnAfterDelete() + { + if (m_Timer?.Running == true) + m_Timer.Stop(); + } + + public virtual bool OnLifted(Mobile from, PlagueBeastComponent c) => c.IsGland || c.IsBrain; + + public virtual bool OnDropped(Mobile from, Item item, PlagueBeastComponent to) => false; + + public virtual void FinishOpening(Mobile from) + { + Opened = true; + + Owner?.PlaySound(0x50); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.WriteItemList(Components); + writer.Write(BrainHue); + writer.Write(Opened); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + Components = reader.ReadStrongItemList(); + BrainHue = reader.ReadInt(); + Opened = reader.ReadBool(); + } + } + + public class PlagueBeastMaidenOrgan : PlagueBeastOrgan + { + public PlagueBeastMaidenOrgan() : base(0x124D) + { + } + + public PlagueBeastMaidenOrgan(Serial serial) : base(serial) + { + } + + public override void OnDoubleClick(Mobile from) + { + if (!Opened) + FinishOpening(from); + } + + public override void FinishOpening(Mobile from) + { + ItemID = 0x1249; + + Owner?.PlaySound(0x187); + + AddComponent(new PlagueBeastComponent(0x1D0D, 0x0), 22, 3); + AddComponent(new PlagueBeastComponent(0x1D12, 0x0), 15, 18); + AddComponent(new PlagueBeastComponent(0x1DA3, 0x21), 26, 46); + + if (BrainHue > 0) + AddComponent(new PlagueBeastComponent(0x1CF0, BrainHue, true), 22, 29); + + Opened = true; + } + + 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(); + } + } + + public class PlagueBeastRockOrgan : PlagueBeastOrgan + { + public PlagueBeastRockOrgan() : base(0x177A, 0x60) + { + } + + public PlagueBeastRockOrgan(Serial serial) : base(serial) + { + } + + public override bool IsCuttable => true; + + public override void Carve(Mobile from, Item with) + { + if (IsAccessibleTo(from)) + with.PublicOverheadMessage( + MessageType.Regular, + 0x3B2, + 1071896 + ); // This is too crude an implement for such a procedure. + } + + public override bool OnLifted(Mobile from, PlagueBeastComponent c) + { + base.OnLifted(from, c); + + if (c.IsBrain) + { + AddComponent(new PlagueBeastBlood(), -7, 24); + return true; + } + + return false; + } + + public override void FinishOpening(Mobile from) + { + base.FinishOpening(from); + + AddComponent(new PlagueBeastComponent(0x1775, 0x60), 3, 5); + AddComponent(new PlagueBeastComponent(0x1777, 0x1), 10, 14); + + if (BrainHue > 0) + AddComponent(new PlagueBeastComponent(0x1CF0, BrainHue, true), 1, 24); // 22, 29 + else + AddComponent(new PlagueBeastBlood(), -7, 24); + } + + 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(); + } + } + + public class PlagueBeastRubbleOrgan : PlagueBeastOrgan + { + private static readonly int[] m_Hues = + { + 0xD, 0x17, 0x2B, 0x42, 0x54, 0x5D + }; + + private int m_Veins; + + public PlagueBeastRubbleOrgan() => m_Veins = 3; + + public PlagueBeastRubbleOrgan(Serial serial) : base(serial) + { + } + + public override void Initialize() + { + Hue = m_Hues.RandomElement(); + + AddComponent(new PlagueBeastComponent(0x3BB, Hue), 0, 0); + AddComponent(new PlagueBeastComponent(0x3BA, Hue), 4, 6); + AddComponent(new PlagueBeastComponent(0x3BA, Hue), -6, 17); + + var v = Utility.Random(4); + + AddComponent(new PlagueBeastVein(0x1B1B, v == 0 ? Hue : RandomHue(Hue)), -23, -3); + AddComponent(new PlagueBeastVein(0x1B1C, v == 1 ? Hue : RandomHue(Hue)), 19, 4); + AddComponent(new PlagueBeastVein(0x1B1B, v == 2 ? Hue : RandomHue(Hue)), 21, 27); + AddComponent(new PlagueBeastVein(0x1B1B, v == 3 ? Hue : RandomHue(Hue)), 10, 40); + } + + public override bool OnLifted(Mobile from, PlagueBeastComponent c) + { + if (c.IsBrain) + { + AddComponent(new PlagueBeastBlood(), -13, 25); + return true; + } + + return false; + } + + public override void FinishOpening(Mobile from) + { + AddComponent(new PlagueBeastComponent(0x1777, 0x1), 5, 14); + + if (BrainHue > 0) + AddComponent(new PlagueBeastComponent(0x1CF0, BrainHue, true), -5, 22); + else + AddComponent(new PlagueBeastBlood(), -13, 25); + + Opened = true; + } + + private static int RandomHue(int exclude) + { + for (var i = 0; i < 20; i++) + { + var hue = m_Hues.RandomElement(); + + if (hue != exclude) + return hue; + } + + return 0xD; + } + + public virtual void OnVeinCut(Mobile from, PlagueBeastVein vein) + { + if (vein.Hue != Hue) + { + if (!Opened && m_Veins > 0 && --m_Veins == 0) + FinishOpening(from); + } + else + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1071901 + ); // * As you cut the vein, a cloud of poison is expelled from the plague beast's organ, and the plague beast dissolves into a puddle of goo * + from.ApplyPoison(from, Poison.Greater); + from.PlaySound(0x22F); + + if (Owner != null) + { + Owner.Unfreeze(); + Owner.Kill(); + } + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_Veins); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_Veins = reader.ReadInt(); + } + } + + public class PlagueBeastBackupOrgan : PlagueBeastOrgan + { + private Item m_Gland; + + private Timer m_Timer; + + public PlagueBeastBackupOrgan() : base(0x1362, 0x6) + { + } + + public PlagueBeastBackupOrgan(Serial serial) : base(serial) + { + } + + public override bool IsCuttable => true; + + public override void Initialize() + { + AddComponent(new PlagueBeastComponent(0x1B1B, 0x42), 16, 39); + AddComponent(new PlagueBeastComponent(0x1B1B, 0x42), 39, 49); + AddComponent(new PlagueBeastComponent(0x1B1B, 0x42), 39, 48); + AddComponent(new PlagueBeastComponent(0x1B1B, 0x42), 44, 42); + AddComponent(new PlagueBeastComponent(0x1CF2, 0x42), 20, 34); + AddComponent(new PlagueBeastComponent(0x135F, 0x42), 47, 58); + AddComponent(new PlagueBeastComponent(0x1360, 0x42), 70, 68); + } + + public override void Carve(Mobile from, Item with) + { + if (IsAccessibleTo(from)) + with.PublicOverheadMessage( + MessageType.Regular, + 0x3B2, + 1071896 + ); // This is too crude an implement for such a procedure. + } + + public override bool OnLifted(Mobile from, PlagueBeastComponent c) + { + if (c.IsBrain) + { + AddComponent(new PlagueBeastBlood(), 47, 72); + return true; + } + + if (c.IsGland) + { + m_Gland = null; + return true; + } + + return c.IsGland; + } + + public override bool OnDropped(Mobile from, Item item, PlagueBeastComponent to) + { + if (to.Hue == 0x1 && m_Gland == null && item is PlagueBeastGland) + { + m_Gland = item; + m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(3), FinishHealing); + from.SendAsciiMessage(0x3B2, "* You place the healthy gland inside the organ sac *"); + item.Movable = false; + + Owner?.PlaySound(0x20); + + return true; + } + + return false; + } + + public override void FinishOpening(Mobile from) + { + base.FinishOpening(from); + + AddComponent(new PlagueBeastComponent(0x1363, 0xF), -3, 3); + AddComponent(new PlagueBeastComponent(0x1365, 0x1), -3, 10); + + m_Gland = new PlagueBeastComponent(0x1CEF, 0x3F, true); + AddComponent((PlagueBeastComponent)m_Gland, -4, 16); + } + + public void FinishHealing() + { + for (var i = 0; i < 7 && i < Components.Count; i++) + Components[i].Hue = 0x6; + + m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(2), OpenOrgan); + } + + public void OpenOrgan() + { + AddComponent(new PlagueBeastComponent(0x1367, 0xF), 55, 61); + AddComponent(new PlagueBeastComponent(0x1366, 0x1), 57, 66); + + if (BrainHue > 0) + AddComponent(new PlagueBeastComponent(0x1CF0, BrainHue, true), 55, 69); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_Gland); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_Gland = reader.ReadItem(); + } + } + + public class PlagueBeastMainOrgan : PlagueBeastOrgan + { + private int m_Brains; + + public PlagueBeastMainOrgan() => m_Brains = 0; + + public PlagueBeastMainOrgan(Serial serial) : base(serial) + { + } + + public bool Complete => m_Brains >= 4; + + public override void Initialize() + { + // receptacles + AddComponent(new PlagueBeastComponent(0x1B1B, 0x42), -36, -2); + AddComponent(new PlagueBeastComponent(0x1FB3, 0x42), -42, 0); + AddComponent(new PlagueBeastComponent(0x9DF, 0x42), -53, -7); + + AddComponent(new PlagueBeastComponent(0x1B1C, 0x54), 29, 9); + AddComponent(new PlagueBeastComponent(0x1D06, 0x54), 18, -2); + AddComponent(new PlagueBeastComponent(0x9DF, 0x54), 36, -1); + + AddComponent(new PlagueBeastComponent(0x1D10, 0x2B), -36, 47); + AddComponent(new PlagueBeastComponent(0x1B1C, 0x2B), -24, 62); + AddComponent(new PlagueBeastComponent(0x9DF, 0x2B), -41, 74); + + AddComponent(new PlagueBeastComponent(0x1B1B, 0x60), 39, 56); + AddComponent(new PlagueBeastComponent(0x1FB4, 0x60), 34, 52); + AddComponent(new PlagueBeastComponent(0x9DF, 0x60), 45, 71); + + // main part + AddComponent(new PlagueBeastComponent(0x1351, 0x15), 23, 0); + AddComponent(new PlagueBeastComponent(0x134F, 0x15), -22, 0); + AddComponent(new PlagueBeastComponent(0x1350, 0x15), 0, 0); + } + + public override bool OnLifted(Mobile from, PlagueBeastComponent c) + { + if (c.IsBrain) + m_Brains--; - if (Owner.IsBleeding) - { - from.LocalOverheadMessage(MessageType.Regular, 0x34, - 1071922); // The plague beast is still bleeding from open wounds. You must seal any bleeding wounds before the core will open! return true; - } } - if (m_Brains == 4) - FinishOpening(from); + public override bool OnDropped(Mobile from, Item item, PlagueBeastComponent to) + { + if (!Opened && to.IsReceptacle && item.Hue == to.Hue) + { + to.Organ = this; + m_Brains++; + from.LocalOverheadMessage( + MessageType.Regular, + 0x34, + 1071913 + ); // You place the organ in the fleshy receptacle near the core. - return true; - } + if (Owner != null) + { + Owner.PlaySound(0x1BA); - return false; + if (Owner.IsBleeding) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x34, + 1071922 + ); // The plague beast is still bleeding from open wounds. You must seal any bleeding wounds before the core will open! + return true; + } + } + + if (m_Brains == 4) + FinishOpening(from); + + return true; + } + + return false; + } + + public override void FinishOpening(Mobile from) + { + AddComponent(new PlagueBeastComponent(0x1363, 0x1), 0, 22); + AddComponent(new PlagueBeastComponent(0x1D04, 0xD), 0, 22); + + if (Owner?.Backpack != null) + { + var core = new PlagueBeastMutationCore(); + Owner.Backpack.AddItem(core); + core.Movable = false; + core.Cut = false; + core.X = X; + core.Y = Y + 34; + + Owner.PlaySound(0x21); + Owner.PlaySound(0x166); + } + + Opened = true; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_Brains); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_Brains = reader.ReadInt(); + } } - - public override void FinishOpening(Mobile from) - { - AddComponent(new PlagueBeastComponent(0x1363, 0x1), 0, 22); - AddComponent(new PlagueBeastComponent(0x1D04, 0xD), 0, 22); - - if (Owner?.Backpack != null) - { - PlagueBeastMutationCore core = new PlagueBeastMutationCore(); - Owner.Backpack.AddItem(core); - core.Movable = false; - core.Cut = false; - core.X = X; - core.Y = Y + 34; - - Owner.PlaySound(0x21); - Owner.PlaySound(0x166); - } - - Opened = true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_Brains); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_Brains = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastVein.cs b/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastVein.cs index c5bb02c86..2a4d3dd53 100644 --- a/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastVein.cs +++ b/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastVein.cs @@ -3,73 +3,76 @@ using Server.Network; namespace Server.Items { - public class PlagueBeastVein : PlagueBeastComponent - { - private Timer m_Timer; - - public PlagueBeastVein(int itemID, int hue) : base(itemID, hue) => Cut = false; - - public PlagueBeastVein(Serial serial) : base(serial) + public class PlagueBeastVein : PlagueBeastComponent { - } + private Timer m_Timer; - public bool Cut { get; private set; } + public PlagueBeastVein(int itemID, int hue) : base(itemID, hue) => Cut = false; - public override bool Scissor(Mobile from, Scissors scissors) - { - if (IsAccessibleTo(from)) - { - if (!Cut && m_Timer == null) + public PlagueBeastVein(Serial serial) : base(serial) { - m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(3), CuttingDone, from); - scissors.PublicOverheadMessage(MessageType.Regular, 0x3B2, - 1071899); // You begin cutting through the vein. - return true; } - scissors.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1071900); // // This vein has already been cut. - } + public bool Cut { get; private set; } - return false; + public override bool Scissor(Mobile from, Scissors scissors) + { + if (IsAccessibleTo(from)) + { + if (!Cut && m_Timer == null) + { + m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(3), CuttingDone, from); + scissors.PublicOverheadMessage( + MessageType.Regular, + 0x3B2, + 1071899 + ); // You begin cutting through the vein. + return true; + } + + scissors.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1071900); // // This vein has already been cut. + } + + return false; + } + + public override void OnAfterDelete() + { + if (m_Timer?.Running == true) + m_Timer.Stop(); + } + + private void CuttingDone(Mobile from) + { + Cut = true; + + if (ItemID == 0x1B1C) + ItemID = 0x1B1B; + else + ItemID = 0x1B1C; + + Owner?.PlaySound(0x199); + + if (Organ is PlagueBeastRubbleOrgan organ) + organ.OnVeinCut(from, this); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(Cut); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + Cut = reader.ReadBool(); + } } - - public override void OnAfterDelete() - { - if (m_Timer?.Running == true) - m_Timer.Stop(); - } - - private void CuttingDone(Mobile from) - { - Cut = true; - - if (ItemID == 0x1B1C) - ItemID = 0x1B1B; - else - ItemID = 0x1B1C; - - Owner?.PlaySound(0x199); - - if (Organ is PlagueBeastRubbleOrgan organ) - organ.OnVeinCut(from, this); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(Cut); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - Cut = reader.ReadBool(); - } - } } diff --git a/Projects/UOContent/Items/Special/Rares/Containers/BaseWaterContainer.cs b/Projects/UOContent/Items/Special/Rares/Containers/BaseWaterContainer.cs index 37c1e3b6d..b6ba77dfe 100644 --- a/Projects/UOContent/Items/Special/Rares/Containers/BaseWaterContainer.cs +++ b/Projects/UOContent/Items/Special/Rares/Containers/BaseWaterContainer.cs @@ -1,118 +1,119 @@ namespace Server.Items { - public abstract class BaseWaterContainer : Container, IHasQuantity - { - private int m_Quantity; - - public BaseWaterContainer(int item_Id, bool filled) - : base(item_Id) => - m_Quantity = filled ? MaxQuantity : 0; - - public BaseWaterContainer(Serial serial) - : base(serial) + public abstract class BaseWaterContainer : Container, IHasQuantity { - } + private int m_Quantity; - public abstract int voidItem_ID { get; } - public abstract int fullItem_ID { get; } - public abstract int MaxQuantity { get; } + public BaseWaterContainer(int item_Id, bool filled) + : base(item_Id) => + m_Quantity = filled ? MaxQuantity : 0; - public override int DefaultGumpID => 0x3e; - - [CommandProperty(AccessLevel.GameMaster)] - public virtual bool IsEmpty => m_Quantity <= 0; - - [CommandProperty(AccessLevel.GameMaster)] - public virtual bool IsFull => m_Quantity >= MaxQuantity; - - [CommandProperty(AccessLevel.GameMaster)] - public virtual int Quantity - { - get => m_Quantity; - set - { - if (value != m_Quantity) + public BaseWaterContainer(Serial serial) + : base(serial) { - m_Quantity = value < 1 ? 0 : value > MaxQuantity ? MaxQuantity : value; - - Movable = !IsLockedDown ? IsEmpty : false; - - ItemID = IsEmpty ? voidItem_ID : fullItem_ID; - - if (!IsEmpty) - { - IEntity rootParent = RootParent; - - if (rootParent?.Map != null && rootParent.Map != Map.Internal) - MoveToWorld(rootParent.Location, rootParent.Map); - } - - InvalidateProperties(); } - } + + public abstract int voidItem_ID { get; } + public abstract int fullItem_ID { get; } + public abstract int MaxQuantity { get; } + + public override int DefaultGumpID => 0x3e; + + [CommandProperty(AccessLevel.GameMaster)] + public virtual bool IsEmpty => m_Quantity <= 0; + + [CommandProperty(AccessLevel.GameMaster)] + public virtual bool IsFull => m_Quantity >= MaxQuantity; + + [CommandProperty(AccessLevel.GameMaster)] + public virtual int Quantity + { + get => m_Quantity; + set + { + if (value != m_Quantity) + { + m_Quantity = value < 1 ? 0 : + value > MaxQuantity ? MaxQuantity : value; + + Movable = !IsLockedDown ? IsEmpty : false; + + ItemID = IsEmpty ? voidItem_ID : fullItem_ID; + + if (!IsEmpty) + { + var rootParent = RootParent; + + if (rootParent?.Map != null && rootParent.Map != Map.Internal) + MoveToWorld(rootParent.Location, rootParent.Map); + } + + InvalidateProperties(); + } + } + } + + public override void OnDoubleClick(Mobile from) + { + if (IsEmpty) base.OnDoubleClick(from); + } + + public override void OnSingleClick(Mobile from) + { + if (IsEmpty) + { + base.OnSingleClick(from); + } + else + { + if (Name == null) + LabelTo(from, LabelNumber); + else + LabelTo(from, Name); + } + } + + public override void OnAosSingleClick(Mobile from) + { + if (IsEmpty) + { + base.OnAosSingleClick(from); + } + else + { + if (Name == null) + LabelTo(from, LabelNumber); + else + LabelTo(from, Name); + } + } + + public override void GetProperties(ObjectPropertyList list) + { + if (IsEmpty) base.GetProperties(list); + } + + public override bool OnDragDropInto(Mobile from, Item item, Point3D p) + { + if (!IsEmpty) return false; + + return base.OnDragDropInto(from, item, p); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + writer.Write(m_Quantity); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + m_Quantity = reader.ReadInt(); + } } - - public override void OnDoubleClick(Mobile from) - { - if (IsEmpty) base.OnDoubleClick(from); - } - - public override void OnSingleClick(Mobile from) - { - if (IsEmpty) - { - base.OnSingleClick(from); - } - else - { - if (Name == null) - LabelTo(from, LabelNumber); - else - LabelTo(from, Name); - } - } - - public override void OnAosSingleClick(Mobile from) - { - if (IsEmpty) - { - base.OnAosSingleClick(from); - } - else - { - if (Name == null) - LabelTo(from, LabelNumber); - else - LabelTo(from, Name); - } - } - - public override void GetProperties(ObjectPropertyList list) - { - if (IsEmpty) base.GetProperties(list); - } - - public override bool OnDragDropInto(Mobile from, Item item, Point3D p) - { - if (!IsEmpty) return false; - - return base.OnDragDropInto(from, item, p); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - writer.Write(m_Quantity); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - m_Quantity = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Containers/Bucket.cs b/Projects/UOContent/Items/Special/Rares/Containers/Bucket.cs index 2ead76984..c39416d39 100644 --- a/Projects/UOContent/Items/Special/Rares/Containers/Bucket.cs +++ b/Projects/UOContent/Items/Special/Rares/Containers/Bucket.cs @@ -1,37 +1,37 @@ namespace Server.Items { - internal class Bucket : BaseWaterContainer - { - private static readonly int vItemID = 0x14e0; - private static readonly int fItemID = 0x2004; - - [Constructible] - public Bucket(bool filled = false) - : base(filled ? fItemID : vItemID, filled) + internal class Bucket : BaseWaterContainer { + private static readonly int vItemID = 0x14e0; + private static readonly int fItemID = 0x2004; + + [Constructible] + public Bucket(bool filled = false) + : base(filled ? fItemID : vItemID, filled) + { + } + + public Bucket(Serial serial) + : base(serial) + { + } + + public override int voidItem_ID => vItemID; + public override int fullItem_ID => fItemID; + public override int MaxQuantity => 25; + + 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 Bucket(Serial serial) - : base(serial) - { - } - - public override int voidItem_ID => vItemID; - public override int fullItem_ID => fItemID; - public override int MaxQuantity => 25; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/Rares/Containers/ClosedBarrel.cs b/Projects/UOContent/Items/Special/Rares/Containers/ClosedBarrel.cs index 832576e85..3f90eb9c5 100644 --- a/Projects/UOContent/Items/Special/Rares/Containers/ClosedBarrel.cs +++ b/Projects/UOContent/Items/Special/Rares/Containers/ClosedBarrel.cs @@ -1,32 +1,32 @@ namespace Server.Items { - internal class ClosedBarrel : TrappableContainer - { - [Constructible] - public ClosedBarrel() - : base(0x0FAE) + internal class ClosedBarrel : TrappableContainer { + [Constructible] + public ClosedBarrel() + : base(0x0FAE) + { + } + + public ClosedBarrel(Serial serial) + : base(serial) + { + } + + public override int DefaultGumpID => 0x3e; + + 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 ClosedBarrel(Serial serial) - : base(serial) - { - } - - public override int DefaultGumpID => 0x3e; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Containers/UnfinishedBarrel.cs b/Projects/UOContent/Items/Special/Rares/Containers/UnfinishedBarrel.cs index 9889ff85f..975196416 100644 --- a/Projects/UOContent/Items/Special/Rares/Containers/UnfinishedBarrel.cs +++ b/Projects/UOContent/Items/Special/Rares/Containers/UnfinishedBarrel.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class UnfinishedBarrel : Item - { - [Constructible] - public UnfinishedBarrel() : base(0x1EB5) + public class UnfinishedBarrel : Item { - Movable = true; - Stackable = false; + [Constructible] + public UnfinishedBarrel() : base(0x1EB5) + { + Movable = true; + Stackable = false; + } + + public UnfinishedBarrel(Serial serial) : base(serial) + { + } + + 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(); + } } - - public UnfinishedBarrel(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Containers/WaterBarrel.cs b/Projects/UOContent/Items/Special/Rares/Containers/WaterBarrel.cs index 2d8a6767a..c24bbe39a 100644 --- a/Projects/UOContent/Items/Special/Rares/Containers/WaterBarrel.cs +++ b/Projects/UOContent/Items/Special/Rares/Containers/WaterBarrel.cs @@ -1,39 +1,39 @@ namespace Server.Items { - internal class WaterBarrel : BaseWaterContainer - { - private static readonly int vItemID = 0xe77; - private static readonly int fItemID = 0x154d; - - [Constructible] - public WaterBarrel(bool filled = false) - : base(filled ? fItemID : vItemID, filled) + internal class WaterBarrel : BaseWaterContainer { + private static readonly int vItemID = 0xe77; + private static readonly int fItemID = 0x154d; + + [Constructible] + public WaterBarrel(bool filled = false) + : base(filled ? fItemID : vItemID, filled) + { + } + + public WaterBarrel(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1025453; /* water barrel */ + + public override int voidItem_ID => vItemID; + public override int fullItem_ID => fItemID; + public override int MaxQuantity => 100; + + 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 WaterBarrel(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1025453; /* water barrel */ - - public override int voidItem_ID => vItemID; - public override int fullItem_ID => fItemID; - public override int MaxQuantity => 100; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/Rares/Containers/WaterTub.cs b/Projects/UOContent/Items/Special/Rares/Containers/WaterTub.cs index 7b8913a15..1ed6286eb 100644 --- a/Projects/UOContent/Items/Special/Rares/Containers/WaterTub.cs +++ b/Projects/UOContent/Items/Special/Rares/Containers/WaterTub.cs @@ -1,37 +1,37 @@ namespace Server.Items { - internal class Tub : BaseWaterContainer - { - private static readonly int vItemID = 0xe83; - private static readonly int fItemID = 0xe7b; - - [Constructible] - public Tub(bool filled = false) - : base(filled ? fItemID : vItemID, filled) + internal class Tub : BaseWaterContainer { + private static readonly int vItemID = 0xe83; + private static readonly int fItemID = 0xe7b; + + [Constructible] + public Tub(bool filled = false) + : base(filled ? fItemID : vItemID, filled) + { + } + + public Tub(Serial serial) + : base(serial) + { + } + + public override int voidItem_ID => vItemID; + public override int fullItem_ID => fItemID; + public override int MaxQuantity => 50; + + 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 Tub(Serial serial) - : base(serial) - { - } - - public override int voidItem_ID => vItemID; - public override int fullItem_ID => fItemID; - public override int MaxQuantity => 50; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/Rares/Daily/DecoRock.cs b/Projects/UOContent/Items/Special/Rares/Daily/DecoRock.cs index d050ab9aa..8e4e24da6 100644 --- a/Projects/UOContent/Items/Special/Rares/Daily/DecoRock.cs +++ b/Projects/UOContent/Items/Special/Rares/Daily/DecoRock.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoRock : Item - { - [Constructible] - public DecoRock() : base(0x1778) + public class DecoRock : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoRock() : base(0x1778) + { + Movable = true; + Stackable = false; + } + + public DecoRock(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoRock(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Daily/DecoRock2.cs b/Projects/UOContent/Items/Special/Rares/Daily/DecoRock2.cs index 4e554c0ed..10ab65782 100644 --- a/Projects/UOContent/Items/Special/Rares/Daily/DecoRock2.cs +++ b/Projects/UOContent/Items/Special/Rares/Daily/DecoRock2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoRock2 : Item - { - [Constructible] - public DecoRock2() : base(0x1363) + public class DecoRock2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoRock2() : base(0x1363) + { + Movable = true; + Stackable = false; + } + + public DecoRock2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoRock2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Daily/DecoRocks.cs b/Projects/UOContent/Items/Special/Rares/Daily/DecoRocks.cs index 13f5d6b54..d1ed1fa22 100644 --- a/Projects/UOContent/Items/Special/Rares/Daily/DecoRocks.cs +++ b/Projects/UOContent/Items/Special/Rares/Daily/DecoRocks.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoRocks : Item - { - [Constructible] - public DecoRocks() : base(0x1367) + public class DecoRocks : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoRocks() : base(0x1367) + { + Movable = true; + Stackable = false; + } + + public DecoRocks(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoRocks(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Daily/DecoRocks2.cs b/Projects/UOContent/Items/Special/Rares/Daily/DecoRocks2.cs index 5012489f2..37d112fab 100644 --- a/Projects/UOContent/Items/Special/Rares/Daily/DecoRocks2.cs +++ b/Projects/UOContent/Items/Special/Rares/Daily/DecoRocks2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoRocks2 : Item - { - [Constructible] - public DecoRocks2() : base(0x136D) + public class DecoRocks2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoRocks2() : base(0x136D) + { + Movable = true; + Stackable = false; + } + + public DecoRocks2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoRocks2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Flowers/DecoFlower.cs b/Projects/UOContent/Items/Special/Rares/Flowers/DecoFlower.cs index bd4f13081..d7224ec47 100644 --- a/Projects/UOContent/Items/Special/Rares/Flowers/DecoFlower.cs +++ b/Projects/UOContent/Items/Special/Rares/Flowers/DecoFlower.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoFlower : Item - { - [Constructible] - public DecoFlower() : base(0x18DA) + public class DecoFlower : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoFlower() : base(0x18DA) + { + Movable = true; + Stackable = false; + } + + public DecoFlower(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoFlower(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Flowers/DecoFlower2.cs b/Projects/UOContent/Items/Special/Rares/Flowers/DecoFlower2.cs index 10a4c578e..3ec6f0e6d 100644 --- a/Projects/UOContent/Items/Special/Rares/Flowers/DecoFlower2.cs +++ b/Projects/UOContent/Items/Special/Rares/Flowers/DecoFlower2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoFlower2 : Item - { - [Constructible] - public DecoFlower2() : base(0x18D9) + public class DecoFlower2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoFlower2() : base(0x18D9) + { + Movable = true; + Stackable = false; + } + + public DecoFlower2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoFlower2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Flowers/DecoRoseOfTrinsic.cs b/Projects/UOContent/Items/Special/Rares/Flowers/DecoRoseOfTrinsic.cs index 93ada537b..12da0db1d 100644 --- a/Projects/UOContent/Items/Special/Rares/Flowers/DecoRoseOfTrinsic.cs +++ b/Projects/UOContent/Items/Special/Rares/Flowers/DecoRoseOfTrinsic.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoRoseOfTrinsic : Item - { - [Constructible] - public DecoRoseOfTrinsic() : base(0x234C) + public class DecoRoseOfTrinsic : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoRoseOfTrinsic() : base(0x234C) + { + Movable = true; + Stackable = false; + } + + public DecoRoseOfTrinsic(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoRoseOfTrinsic(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Flowers/DecoRoseOfTrinsic2.cs b/Projects/UOContent/Items/Special/Rares/Flowers/DecoRoseOfTrinsic2.cs index 2190dbd03..77a20b0f2 100644 --- a/Projects/UOContent/Items/Special/Rares/Flowers/DecoRoseOfTrinsic2.cs +++ b/Projects/UOContent/Items/Special/Rares/Flowers/DecoRoseOfTrinsic2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoRoseOfTrinsic2 : Item - { - [Constructible] - public DecoRoseOfTrinsic2() : base(0x234D) + public class DecoRoseOfTrinsic2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoRoseOfTrinsic2() : base(0x234D) + { + Movable = true; + Stackable = false; + } + + public DecoRoseOfTrinsic2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoRoseOfTrinsic2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Flowers/DecoRoseOfTrinsic3.cs b/Projects/UOContent/Items/Special/Rares/Flowers/DecoRoseOfTrinsic3.cs index f06e1f47f..8a48db446 100644 --- a/Projects/UOContent/Items/Special/Rares/Flowers/DecoRoseOfTrinsic3.cs +++ b/Projects/UOContent/Items/Special/Rares/Flowers/DecoRoseOfTrinsic3.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoRoseOfTrinsic3 : Item - { - [Constructible] - public DecoRoseOfTrinsic3() : base(0x234B) + public class DecoRoseOfTrinsic3 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoRoseOfTrinsic3() : base(0x234B) + { + Movable = true; + Stackable = false; + } + + public DecoRoseOfTrinsic3(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoRoseOfTrinsic3(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Food/BottlesOfLiquor.cs b/Projects/UOContent/Items/Special/Rares/Food/BottlesOfLiquor.cs index f51554d7d..dfb23c4d1 100644 --- a/Projects/UOContent/Items/Special/Rares/Food/BottlesOfLiquor.cs +++ b/Projects/UOContent/Items/Special/Rares/Food/BottlesOfLiquor.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoBottlesOfLiquor : Item - { - [Constructible] - public DecoBottlesOfLiquor() : base(0x99E) + public class DecoBottlesOfLiquor : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoBottlesOfLiquor() : base(0x99E) + { + Movable = true; + Stackable = false; + } + + public DecoBottlesOfLiquor(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoBottlesOfLiquor(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Food/Tray2.cs b/Projects/UOContent/Items/Special/Rares/Food/Tray2.cs index 5f6afed72..f68935acf 100644 --- a/Projects/UOContent/Items/Special/Rares/Food/Tray2.cs +++ b/Projects/UOContent/Items/Special/Rares/Food/Tray2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoTray2 : Item - { - [Constructible] - public DecoTray2() : base(0x991) + public class DecoTray2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoTray2() : base(0x991) + { + Movable = true; + Stackable = false; + } + + public DecoTray2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoTray2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Food/Trays.cs b/Projects/UOContent/Items/Special/Rares/Food/Trays.cs index 179e5edab..97da135a4 100644 --- a/Projects/UOContent/Items/Special/Rares/Food/Trays.cs +++ b/Projects/UOContent/Items/Special/Rares/Food/Trays.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoTray : Item - { - [Constructible] - public DecoTray() : base(Utility.Random(2) + 0x991) + public class DecoTray : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoTray() : base(Utility.Random(2) + 0x991) + { + Movable = true; + Stackable = false; + } + + public DecoTray(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoTray(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Furniture/BrokenChair.cs b/Projects/UOContent/Items/Special/Rares/Furniture/BrokenChair.cs index f0b86cf1f..30aa8acb3 100644 --- a/Projects/UOContent/Items/Special/Rares/Furniture/BrokenChair.cs +++ b/Projects/UOContent/Items/Special/Rares/Furniture/BrokenChair.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class BrokenChair : Item - { - [Constructible] - public BrokenChair() : base(Utility.Random(2) + 0xC19) + public class BrokenChair : Item { - Movable = true; - Stackable = false; + [Constructible] + public BrokenChair() : base(Utility.Random(2) + 0xC19) + { + Movable = true; + Stackable = false; + } + + public BrokenChair(Serial serial) : base(serial) + { + } + + 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(); + } } - - public BrokenChair(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/GamePieces/Checkers.cs b/Projects/UOContent/Items/Special/Rares/GamePieces/Checkers.cs index b95ca3433..a648139fb 100644 --- a/Projects/UOContent/Items/Special/Rares/GamePieces/Checkers.cs +++ b/Projects/UOContent/Items/Special/Rares/GamePieces/Checkers.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class Checkers : Item - { - [Constructible] - public Checkers() : base(0xE1A) + public class Checkers : Item { - Movable = true; - Stackable = false; + [Constructible] + public Checkers() : base(0xE1A) + { + Movable = true; + Stackable = false; + } + + public Checkers(Serial serial) : base(serial) + { + } + + 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(); + } } - - public Checkers(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/GamePieces/Checkers2.cs b/Projects/UOContent/Items/Special/Rares/GamePieces/Checkers2.cs index 059b6ff24..ae950fdfe 100644 --- a/Projects/UOContent/Items/Special/Rares/GamePieces/Checkers2.cs +++ b/Projects/UOContent/Items/Special/Rares/GamePieces/Checkers2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class Checkers2 : Item - { - [Constructible] - public Checkers2() : base(0xE1B) + public class Checkers2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public Checkers2() : base(0xE1B) + { + Movable = true; + Stackable = false; + } + + public Checkers2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public Checkers2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/GamePieces/Chessmen.cs b/Projects/UOContent/Items/Special/Rares/GamePieces/Chessmen.cs index 761d756fc..b1f089cb9 100644 --- a/Projects/UOContent/Items/Special/Rares/GamePieces/Chessmen.cs +++ b/Projects/UOContent/Items/Special/Rares/GamePieces/Chessmen.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class Chessmen : Item - { - [Constructible] - public Chessmen() : base(0xE13) + public class Chessmen : Item { - Movable = true; - Stackable = false; + [Constructible] + public Chessmen() : base(0xE13) + { + Movable = true; + Stackable = false; + } + + public Chessmen(Serial serial) : base(serial) + { + } + + 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(); + } } - - public Chessmen(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/GamePieces/Chessmen2.cs b/Projects/UOContent/Items/Special/Rares/GamePieces/Chessmen2.cs index 9d3d10f1c..7a2e772f0 100644 --- a/Projects/UOContent/Items/Special/Rares/GamePieces/Chessmen2.cs +++ b/Projects/UOContent/Items/Special/Rares/GamePieces/Chessmen2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class Chessmen2 : Item - { - [Constructible] - public Chessmen2() : base(0xE12) + public class Chessmen2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public Chessmen2() : base(0xE12) + { + Movable = true; + Stackable = false; + } + + public Chessmen2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public Chessmen2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/GamePieces/Chessmen3.cs b/Projects/UOContent/Items/Special/Rares/GamePieces/Chessmen3.cs index 09c8dc8d0..ec6a3f3b2 100644 --- a/Projects/UOContent/Items/Special/Rares/GamePieces/Chessmen3.cs +++ b/Projects/UOContent/Items/Special/Rares/GamePieces/Chessmen3.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class Chessmen3 : Item - { - [Constructible] - public Chessmen3() : base(0xE14) + public class Chessmen3 : Item { - Movable = true; - Stackable = false; + [Constructible] + public Chessmen3() : base(0xE14) + { + Movable = true; + Stackable = false; + } + + public Chessmen3(Serial serial) : base(serial) + { + } + + 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(); + } } - - public Chessmen3(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngot.cs b/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngot.cs index 30b3cff47..c9eed7157 100644 --- a/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngot.cs +++ b/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngot.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoGoldIngot : Item - { - [Constructible] - public DecoGoldIngot() : base(0x1BE9) + public class DecoGoldIngot : Item { - Movable = true; - Stackable = true; + [Constructible] + public DecoGoldIngot() : base(0x1BE9) + { + Movable = true; + Stackable = true; + } + + public DecoGoldIngot(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoGoldIngot(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngot2.cs b/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngot2.cs index 5f6b7296f..021a84bf9 100644 --- a/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngot2.cs +++ b/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngot2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoGoldIngot2 : Item - { - [Constructible] - public DecoGoldIngot2() : base(0x1BEC) + public class DecoGoldIngot2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoGoldIngot2() : base(0x1BEC) + { + Movable = true; + Stackable = false; + } + + public DecoGoldIngot2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoGoldIngot2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngots.cs b/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngots.cs index 1438dc29f..8ab1b91a2 100644 --- a/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngots.cs +++ b/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngots.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoGoldIngots : Item - { - [Constructible] - public DecoGoldIngots() : base(0x1BEA) + public class DecoGoldIngots : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoGoldIngots() : base(0x1BEA) + { + Movable = true; + Stackable = false; + } + + public DecoGoldIngots(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoGoldIngots(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngots2.cs b/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngots2.cs index a05da9ca6..0827ab01f 100644 --- a/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngots2.cs +++ b/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngots2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoGoldIngots2 : Item - { - [Constructible] - public DecoGoldIngots2() : base(0x1BEB) + public class DecoGoldIngots2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoGoldIngots2() : base(0x1BEB) + { + Movable = true; + Stackable = false; + } + + public DecoGoldIngots2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoGoldIngots2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngots3.cs b/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngots3.cs index c0bedae0b..8b971a48f 100644 --- a/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngots3.cs +++ b/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngots3.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoGoldIngots3 : Item - { - [Constructible] - public DecoGoldIngots3() : base(0x1BED) + public class DecoGoldIngots3 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoGoldIngots3() : base(0x1BED) + { + Movable = true; + Stackable = false; + } + + public DecoGoldIngots3(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoGoldIngots3(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngots4.cs b/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngots4.cs index be913c34a..59097f68e 100644 --- a/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngots4.cs +++ b/Projects/UOContent/Items/Special/Rares/Ingots/DecoGoldIngots4.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoGoldIngots4 : Item - { - [Constructible] - public DecoGoldIngots4() : base(0x1BEE) + public class DecoGoldIngots4 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoGoldIngots4() : base(0x1BEE) + { + Movable = true; + Stackable = false; + } + + public DecoGoldIngots4(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoGoldIngots4(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngot.cs b/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngot.cs index f6a9427ff..7b97348bb 100644 --- a/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngot.cs +++ b/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngot.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoIronIngot : Item - { - [Constructible] - public DecoIronIngot() : base(0x1BEF) + public class DecoIronIngot : Item { - Movable = true; - Stackable = true; + [Constructible] + public DecoIronIngot() : base(0x1BEF) + { + Movable = true; + Stackable = true; + } + + public DecoIronIngot(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoIronIngot(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngot2.cs b/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngot2.cs index ec54195c9..d6395a818 100644 --- a/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngot2.cs +++ b/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngot2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoIronIngot2 : Item - { - [Constructible] - public DecoIronIngot2() : base(0x1BEF) + public class DecoIronIngot2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoIronIngot2() : base(0x1BEF) + { + Movable = true; + Stackable = false; + } + + public DecoIronIngot2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoIronIngot2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots.cs b/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots.cs index e94c7e0f4..df480bb37 100644 --- a/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots.cs +++ b/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoIronIngots : Item - { - [Constructible] - public DecoIronIngots() : base(0x1BF1) + public class DecoIronIngots : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoIronIngots() : base(0x1BF1) + { + Movable = true; + Stackable = false; + } + + public DecoIronIngots(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoIronIngots(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots2.cs b/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots2.cs index ed39847e7..8d81aff46 100644 --- a/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots2.cs +++ b/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoIronIngots2 : Item - { - [Constructible] - public DecoIronIngots2() : base(0x1BF0) + public class DecoIronIngots2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoIronIngots2() : base(0x1BF0) + { + Movable = true; + Stackable = false; + } + + public DecoIronIngots2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoIronIngots2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots3.cs b/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots3.cs index 320ec2587..7a214992b 100644 --- a/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots3.cs +++ b/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots3.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoIronIngots3 : Item - { - [Constructible] - public DecoIronIngots3() : base(0x1BF0) + public class DecoIronIngots3 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoIronIngots3() : base(0x1BF0) + { + Movable = true; + Stackable = false; + } + + public DecoIronIngots3(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoIronIngots3(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots4.cs b/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots4.cs index 8a6c7b722..69c3b22df 100644 --- a/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots4.cs +++ b/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots4.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoIronIngots4 : Item - { - [Constructible] - public DecoIronIngots4() : base(0x1BF1) + public class DecoIronIngots4 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoIronIngots4() : base(0x1BF1) + { + Movable = true; + Stackable = false; + } + + public DecoIronIngots4(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoIronIngots4(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots5.cs b/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots5.cs index 0358d51bd..84c0f80dd 100644 --- a/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots5.cs +++ b/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots5.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoIronIngots5 : Item - { - [Constructible] - public DecoIronIngots5() : base(0x1BF3) + public class DecoIronIngots5 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoIronIngots5() : base(0x1BF3) + { + Movable = true; + Stackable = false; + } + + public DecoIronIngots5(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoIronIngots5(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots6.cs b/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots6.cs index 94b196b84..93b2045c3 100644 --- a/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots6.cs +++ b/Projects/UOContent/Items/Special/Rares/Ingots/DecoIronIngots6.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoIronIngots6 : Item - { - [Constructible] - public DecoIronIngots6() : base(0x1BF4) + public class DecoIronIngots6 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoIronIngots6() : base(0x1BF4) + { + Movable = true; + Stackable = false; + } + + public DecoIronIngots6(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoIronIngots6(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngot.cs b/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngot.cs index c4043c9aa..aa64d768b 100644 --- a/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngot.cs +++ b/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngot.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoSilverIngot : Item - { - [Constructible] - public DecoSilverIngot() : base(0x1BF5) + public class DecoSilverIngot : Item { - Movable = true; - Stackable = true; + [Constructible] + public DecoSilverIngot() : base(0x1BF5) + { + Movable = true; + Stackable = true; + } + + public DecoSilverIngot(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoSilverIngot(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngot2.cs b/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngot2.cs index 34eeddc34..c3a428a4a 100644 --- a/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngot2.cs +++ b/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngot2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoSilverIngot2 : Item - { - [Constructible] - public DecoSilverIngot2() : base(0x1BF8) + public class DecoSilverIngot2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoSilverIngot2() : base(0x1BF8) + { + Movable = true; + Stackable = false; + } + + public DecoSilverIngot2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoSilverIngot2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngots.cs b/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngots.cs index 149dfc565..bba7879c3 100644 --- a/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngots.cs +++ b/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngots.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoSilverIngots : Item - { - [Constructible] - public DecoSilverIngots() : base(0x1BFA) + public class DecoSilverIngots : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoSilverIngots() : base(0x1BFA) + { + Movable = true; + Stackable = false; + } + + public DecoSilverIngots(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoSilverIngots(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngots2.cs b/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngots2.cs index f868ec147..923a189f1 100644 --- a/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngots2.cs +++ b/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngots2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoSilverIngots2 : Item - { - [Constructible] - public DecoSilverIngots2() : base(0x1BF6) + public class DecoSilverIngots2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoSilverIngots2() : base(0x1BF6) + { + Movable = true; + Stackable = false; + } + + public DecoSilverIngots2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoSilverIngots2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngots3.cs b/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngots3.cs index 4185b7738..df089aac2 100644 --- a/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngots3.cs +++ b/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngots3.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoSilverIngots3 : Item - { - [Constructible] - public DecoSilverIngots3() : base(0x1BF7) + public class DecoSilverIngots3 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoSilverIngots3() : base(0x1BF7) + { + Movable = true; + Stackable = false; + } + + public DecoSilverIngots3(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoSilverIngots3(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngots4.cs b/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngots4.cs index 579ec9e3a..3fd0baead 100644 --- a/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngots4.cs +++ b/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngots4.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoSilverIngots4 : Item - { - [Constructible] - public DecoSilverIngots4() : base(0x1BF9) + public class DecoSilverIngots4 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoSilverIngots4() : base(0x1BF9) + { + Movable = true; + Stackable = false; + } + + public DecoSilverIngots4(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoSilverIngots4(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngots5.cs b/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngots5.cs index d2cb6705b..4c1233465 100644 --- a/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngots5.cs +++ b/Projects/UOContent/Items/Special/Rares/Ingots/DecoSilverIngots5.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoSilverIngots5 : Item - { - [Constructible] - public DecoSilverIngots5() : base(0x1BFA) + public class DecoSilverIngots5 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoSilverIngots5() : base(0x1BFA) + { + Movable = true; + Stackable = false; + } + + public DecoSilverIngots5(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoSilverIngots5(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Jars/EmptyJars.cs b/Projects/UOContent/Items/Special/Rares/Jars/EmptyJars.cs index 2986c1f29..690c3abad 100644 --- a/Projects/UOContent/Items/Special/Rares/Jars/EmptyJars.cs +++ b/Projects/UOContent/Items/Special/Rares/Jars/EmptyJars.cs @@ -1,152 +1,152 @@ namespace Server.Items { - public class EmptyJar : Item - { - [Constructible] - public EmptyJar() - : base(0x1005) + public class EmptyJar : Item { - Movable = true; - Stackable = false; + [Constructible] + public EmptyJar() + : base(0x1005) + { + Movable = true; + Stackable = false; + } + + public EmptyJar(Serial serial) + : base(serial) + { + } + + 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(); + } } - public EmptyJar(Serial serial) - : base(serial) + public class EmptyJars : Item { + [Constructible] + public EmptyJars() + : base(0xe44) + { + Movable = true; + Stackable = false; + } + + public EmptyJars(Serial serial) + : base(serial) + { + } + + 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(); + } } - public override void Serialize(IGenericWriter writer) + public class EmptyJars2 : Item { - base.Serialize(writer); + [Constructible] + public EmptyJars2() + : base(0xe45) + { + Movable = true; + Stackable = false; + } - writer.Write(0); + public EmptyJars2(Serial serial) + : base(serial) + { + } + + 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(); + } } - public override void Deserialize(IGenericReader reader) + public class EmptyJars3 : Item { - base.Deserialize(reader); + [Constructible] + public EmptyJars3() + : base(0xe46) + { + Movable = true; + Stackable = false; + } - int version = reader.ReadInt(); - } - } + public EmptyJars3(Serial serial) + : base(serial) + { + } - public class EmptyJars : Item - { - [Constructible] - public EmptyJars() - : base(0xe44) - { - Movable = true; - Stackable = false; + 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(); + } } - public EmptyJars(Serial serial) - : base(serial) + public class EmptyJars4 : Item { + [Constructible] + public EmptyJars4() + : base(0xe47) + { + Movable = true; + Stackable = false; + } + + public EmptyJars4(Serial serial) + : base(serial) + { + } + + 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(); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class EmptyJars2 : Item - { - [Constructible] - public EmptyJars2() - : base(0xe45) - { - Movable = true; - Stackable = false; - } - - public EmptyJars2(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class EmptyJars3 : Item - { - [Constructible] - public EmptyJars3() - : base(0xe46) - { - Movable = true; - Stackable = false; - } - - public EmptyJars3(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class EmptyJars4 : Item - { - [Constructible] - public EmptyJars4() - : base(0xe47) - { - Movable = true; - Stackable = false; - } - - public EmptyJars4(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Jars/FullJars.cs b/Projects/UOContent/Items/Special/Rares/Jars/FullJars.cs index 0aeecee2e..448eb7838 100644 --- a/Projects/UOContent/Items/Special/Rares/Jars/FullJars.cs +++ b/Projects/UOContent/Items/Special/Rares/Jars/FullJars.cs @@ -1,92 +1,92 @@ namespace Server.Items { - public class DecoFullJar : Item - { - [Constructible] - public DecoFullJar() - : base(0x1006) + public class DecoFullJar : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoFullJar() + : base(0x1006) + { + Movable = true; + Stackable = false; + } + + public DecoFullJar(Serial serial) + : base(serial) + { + } + + 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(); + } } - public DecoFullJar(Serial serial) - : base(serial) + public class DecoFullJars3 : Item { + [Constructible] + public DecoFullJars3() + : base(0xE4a) + { + Movable = true; + Stackable = false; + } + + public DecoFullJars3(Serial serial) + : base(serial) + { + } + + 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(); + } } - public override void Serialize(IGenericWriter writer) + public class DecoFullJars4 : Item { - base.Serialize(writer); + [Constructible] + public DecoFullJars4() + : base(0xE4b) + { + Movable = true; + Stackable = false; + } - writer.Write(0); + public DecoFullJars4(Serial serial) + : base(serial) + { + } + + 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(); + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DecoFullJars3 : Item - { - [Constructible] - public DecoFullJars3() - : base(0xE4a) - { - Movable = true; - Stackable = false; - } - - public DecoFullJars3(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DecoFullJars4 : Item - { - [Constructible] - public DecoFullJars4() - : base(0xE4b) - { - Movable = true; - Stackable = false; - } - - public DecoFullJars4(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Jars/HalfEmptyJars.cs b/Projects/UOContent/Items/Special/Rares/Jars/HalfEmptyJars.cs index 4929e0602..d61254c67 100644 --- a/Projects/UOContent/Items/Special/Rares/Jars/HalfEmptyJars.cs +++ b/Projects/UOContent/Items/Special/Rares/Jars/HalfEmptyJars.cs @@ -1,152 +1,152 @@ namespace Server.Items { - public class HalfEmptyJar : Item - { - [Constructible] - public HalfEmptyJar() - : base(0x1007) + public class HalfEmptyJar : Item { - Movable = true; - Stackable = false; + [Constructible] + public HalfEmptyJar() + : base(0x1007) + { + Movable = true; + Stackable = false; + } + + public HalfEmptyJar(Serial serial) + : base(serial) + { + } + + 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(); + } } - public HalfEmptyJar(Serial serial) - : base(serial) + public class HalfEmptyJars : Item { + [Constructible] + public HalfEmptyJars() + : base(0xe4c) + { + Movable = true; + Stackable = false; + } + + public HalfEmptyJars(Serial serial) + : base(serial) + { + } + + 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(); + } } - public override void Serialize(IGenericWriter writer) + public class Jars2 : Item { - base.Serialize(writer); + [Constructible] + public Jars2() + : base(0xE4d) + { + Movable = true; + Stackable = false; + } - writer.Write(0); + public Jars2(Serial serial) + : base(serial) + { + } + + 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(); + } } - public override void Deserialize(IGenericReader reader) + public class Jars3 : Item { - base.Deserialize(reader); + [Constructible] + public Jars3() + : base(0xE4e) + { + Movable = true; + Stackable = false; + } - int version = reader.ReadInt(); - } - } + public Jars3(Serial serial) + : base(serial) + { + } - public class HalfEmptyJars : Item - { - [Constructible] - public HalfEmptyJars() - : base(0xe4c) - { - Movable = true; - Stackable = false; + 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(); + } } - public HalfEmptyJars(Serial serial) - : base(serial) + public class Jars4 : Item { + [Constructible] + public Jars4() + : base(0xE4f) + { + Movable = true; + Stackable = false; + } + + public Jars4(Serial serial) + : base(serial) + { + } + + 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(); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Jars2 : Item - { - [Constructible] - public Jars2() - : base(0xE4d) - { - Movable = true; - Stackable = false; - } - - public Jars2(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Jars3 : Item - { - [Constructible] - public Jars3() - : base(0xE4e) - { - Movable = true; - Stackable = false; - } - - public Jars3(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class Jars4 : Item - { - [Constructible] - public Jars4() - : base(0xE4f) - { - Movable = true; - Stackable = false; - } - - public Jars4(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Magic/DecoCrystalBall.cs b/Projects/UOContent/Items/Special/Rares/Magic/DecoCrystalBall.cs index c3e4da61e..241240438 100644 --- a/Projects/UOContent/Items/Special/Rares/Magic/DecoCrystalBall.cs +++ b/Projects/UOContent/Items/Special/Rares/Magic/DecoCrystalBall.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoCrystalBall : Item - { - [Constructible] - public DecoCrystalBall() : base(0xE2E) + public class DecoCrystalBall : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoCrystalBall() : base(0xE2E) + { + Movable = true; + Stackable = false; + } + + public DecoCrystalBall(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoCrystalBall(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Magic/DecoMagicalCrystal.cs b/Projects/UOContent/Items/Special/Rares/Magic/DecoMagicalCrystal.cs index dd48d63f9..878f37828 100644 --- a/Projects/UOContent/Items/Special/Rares/Magic/DecoMagicalCrystal.cs +++ b/Projects/UOContent/Items/Special/Rares/Magic/DecoMagicalCrystal.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoMagicalCrystal : Item - { - [Constructible] - public DecoMagicalCrystal() : base(0x1F19) + public class DecoMagicalCrystal : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoMagicalCrystal() : base(0x1F19) + { + Movable = true; + Stackable = false; + } + + public DecoMagicalCrystal(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoMagicalCrystal(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Misc/DecoSpittoon.cs b/Projects/UOContent/Items/Special/Rares/Misc/DecoSpittoon.cs index cc664b1fb..2474a0a8c 100644 --- a/Projects/UOContent/Items/Special/Rares/Misc/DecoSpittoon.cs +++ b/Projects/UOContent/Items/Special/Rares/Misc/DecoSpittoon.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoSpittoon : Item - { - [Constructible] - public DecoSpittoon() : base(0x1003) + public class DecoSpittoon : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoSpittoon() : base(0x1003) + { + Movable = true; + Stackable = false; + } + + public DecoSpittoon(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoSpittoon(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoBlackmoor.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoBlackmoor.cs index 49f9d5c8f..bf4ae6708 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoBlackmoor.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoBlackmoor.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoBlackmoor : Item - { - [Constructible] - public DecoBlackmoor() : base(0xF79) + public class DecoBlackmoor : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoBlackmoor() : base(0xF79) + { + Movable = true; + Stackable = false; + } + + public DecoBlackmoor(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoBlackmoor(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoBloodspawn.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoBloodspawn.cs index 1d65d7432..e131849ab 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoBloodspawn.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoBloodspawn.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoBloodspawn : Item - { - [Constructible] - public DecoBloodspawn() : base(0xF7C) + public class DecoBloodspawn : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoBloodspawn() : base(0xF7C) + { + Movable = true; + Stackable = false; + } + + public DecoBloodspawn(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoBloodspawn(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoBrimstone.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoBrimstone.cs index 7d0000b4f..fdda36752 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoBrimstone.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoBrimstone.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoBrimstone : Item - { - [Constructible] - public DecoBrimstone() : base(0xF7F) + public class DecoBrimstone : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoBrimstone() : base(0xF7F) + { + Movable = true; + Stackable = false; + } + + public DecoBrimstone(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoBrimstone(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoDragonsBlood.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoDragonsBlood.cs index cc43ea643..7ff1c3cd9 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoDragonsBlood.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoDragonsBlood.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoDragonsBlood : Item - { - [Constructible] - public DecoDragonsBlood() : base(0x4077) + public class DecoDragonsBlood : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoDragonsBlood() : base(0x4077) + { + Movable = true; + Stackable = false; + } + + public DecoDragonsBlood(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoDragonsBlood(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoDragonsBlood2.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoDragonsBlood2.cs index 15c1dcac2..4983bedf7 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoDragonsBlood2.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoDragonsBlood2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoDragonsBlood2 : Item - { - [Constructible] - public DecoDragonsBlood2() : base(0xF82) + public class DecoDragonsBlood2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoDragonsBlood2() : base(0xF82) + { + Movable = true; + Stackable = false; + } + + public DecoDragonsBlood2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoDragonsBlood2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoEyeOfNewt.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoEyeOfNewt.cs index b9a5c3c70..47bad726c 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoEyeOfNewt.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoEyeOfNewt.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoEyeOfNewt : Item - { - [Constructible] - public DecoEyeOfNewt() : base(0xF87) + public class DecoEyeOfNewt : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoEyeOfNewt() : base(0xF87) + { + Movable = true; + Stackable = false; + } + + public DecoEyeOfNewt(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoEyeOfNewt(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGarlic.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGarlic.cs index f7ff7746b..47924a230 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGarlic.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGarlic.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoGarlic : Item - { - [Constructible] - public DecoGarlic() : base(0x18E1) + public class DecoGarlic : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoGarlic() : base(0x18E1) + { + Movable = true; + Stackable = false; + } + + public DecoGarlic(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoGarlic(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGarlic2.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGarlic2.cs index 008f8e870..2eccb8a97 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGarlic2.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGarlic2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoGarlic2 : Item - { - [Constructible] - public DecoGarlic2() : base(0x18E2) + public class DecoGarlic2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoGarlic2() : base(0x18E2) + { + Movable = true; + Stackable = false; + } + + public DecoGarlic2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoGarlic2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGarlicBulb.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGarlicBulb.cs index ac14ea8ae..0d0a9b8db 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGarlicBulb.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGarlicBulb.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoGarlicBulb : Item - { - [Constructible] - public DecoGarlicBulb() : base(0x18E3) + public class DecoGarlicBulb : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoGarlicBulb() : base(0x18E3) + { + Movable = true; + Stackable = false; + } + + public DecoGarlicBulb(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoGarlicBulb(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGarlicBulb2.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGarlicBulb2.cs index bfc910e21..de66835eb 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGarlicBulb2.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGarlicBulb2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoGarlicBulb2 : Item - { - [Constructible] - public DecoGarlicBulb2() : base(0x18E4) + public class DecoGarlicBulb2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoGarlicBulb2() : base(0x18E4) + { + Movable = true; + Stackable = false; + } + + public DecoGarlicBulb2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoGarlicBulb2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGinseng.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGinseng.cs index 59e9a9cd7..51930f23e 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGinseng.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGinseng.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoGinseng : Item - { - [Constructible] - public DecoGinseng() : base(0x18E9) + public class DecoGinseng : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoGinseng() : base(0x18E9) + { + Movable = true; + Stackable = false; + } + + public DecoGinseng(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoGinseng(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGinseng2.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGinseng2.cs index c318c13e0..1871dfe74 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGinseng2.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGinseng2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoGinseng2 : Item - { - [Constructible] - public DecoGinseng2() : base(0x18EA) + public class DecoGinseng2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoGinseng2() : base(0x18EA) + { + Movable = true; + Stackable = false; + } + + public DecoGinseng2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoGinseng2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGinsengRoot.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGinsengRoot.cs index 3ac641cb5..c23e1970a 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGinsengRoot.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGinsengRoot.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoGinsengRoot : Item - { - [Constructible] - public DecoGinsengRoot() : base(0x18EB) + public class DecoGinsengRoot : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoGinsengRoot() : base(0x18EB) + { + Movable = true; + Stackable = false; + } + + public DecoGinsengRoot(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoGinsengRoot(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGinsengRoot2.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGinsengRoot2.cs index ca1af06a8..e0a423c42 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGinsengRoot2.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoGinsengRoot2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoGinsengRoot2 : Item - { - [Constructible] - public DecoGinsengRoot2() : base(0x18EC) + public class DecoGinsengRoot2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoGinsengRoot2() : base(0x18EC) + { + Movable = true; + Stackable = false; + } + + public DecoGinsengRoot2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoGinsengRoot2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoMandrake.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoMandrake.cs index 46ed0c120..eed57bbe0 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoMandrake.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoMandrake.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoMandrake : Item - { - [Constructible] - public DecoMandrake() : base(0x18DF) + public class DecoMandrake : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoMandrake() : base(0x18DF) + { + Movable = true; + Stackable = false; + } + + public DecoMandrake(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoMandrake(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoMandrake2.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoMandrake2.cs index 5bd50b757..932eadc92 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoMandrake2.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoMandrake2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoMandrake2 : Item - { - [Constructible] - public DecoMandrake2() : base(0x18E0) + public class DecoMandrake2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoMandrake2() : base(0x18E0) + { + Movable = true; + Stackable = false; + } + + public DecoMandrake2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoMandrake2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoMandrake3.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoMandrake3.cs index 30f714b6d..0880a994e 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoMandrake3.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoMandrake3.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoMandrake3 : Item - { - [Constructible] - public DecoMandrake3() : base(0x18DF) + public class DecoMandrake3 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoMandrake3() : base(0x18DF) + { + Movable = true; + Stackable = false; + } + + public DecoMandrake3(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoMandrake3(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoMandrakeRoot.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoMandrakeRoot.cs index 8e67cc33a..5ef477854 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoMandrakeRoot.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoMandrakeRoot.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoMandrakeRoot : Item - { - [Constructible] - public DecoMandrakeRoot() : base(0x18DE) + public class DecoMandrakeRoot : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoMandrakeRoot() : base(0x18DE) + { + Movable = true; + Stackable = false; + } + + public DecoMandrakeRoot(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoMandrakeRoot(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoMandrakeRoot2.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoMandrakeRoot2.cs index 888fecbe2..9dc5e5404 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoMandrakeRoot2.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoMandrakeRoot2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoMandrakeRoot2 : Item - { - [Constructible] - public DecoMandrakeRoot2() : base(0x18DD) + public class DecoMandrakeRoot2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoMandrakeRoot2() : base(0x18DD) + { + Movable = true; + Stackable = false; + } + + public DecoMandrakeRoot2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoMandrakeRoot2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoNightshade.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoNightshade.cs index fe5409768..3e269fd80 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoNightshade.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoNightshade.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoNightshade : Item - { - [Constructible] - public DecoNightshade() : base(0x18E7) + public class DecoNightshade : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoNightshade() : base(0x18E7) + { + Movable = true; + Stackable = false; + } + + public DecoNightshade(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoNightshade(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoNightshade2.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoNightshade2.cs index 50a6c83f2..2ac9f2e0d 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoNightshade2.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoNightshade2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoNightshade2 : Item - { - [Constructible] - public DecoNightshade2() : base(0x18E5) + public class DecoNightshade2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoNightshade2() : base(0x18E5) + { + Movable = true; + Stackable = false; + } + + public DecoNightshade2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoNightshade2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoNightshade3.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoNightshade3.cs index 694a67200..18f8a30fd 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoNightshade3.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoNightshade3.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoNightshade3 : Item - { - [Constructible] - public DecoNightshade3() : base(0x18E6) + public class DecoNightshade3 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoNightshade3() : base(0x18E6) + { + Movable = true; + Stackable = false; + } + + public DecoNightshade3(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoNightshade3(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoObsidian.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoObsidian.cs index fda4fba33..9411e5bdf 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoObsidian.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoObsidian.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoObsidian : Item - { - [Constructible] - public DecoObsidian() : base(0xF89) + public class DecoObsidian : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoObsidian() : base(0xF89) + { + Movable = true; + Stackable = false; + } + + public DecoObsidian(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoObsidian(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoPumice.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoPumice.cs index a42f33971..aea4661cd 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoPumice.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoPumice.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoPumice : Item - { - [Constructible] - public DecoPumice() : base(0xF8B) + public class DecoPumice : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoPumice() : base(0xF8B) + { + Movable = true; + Stackable = false; + } + + public DecoPumice(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoPumice(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoWyrmsHeart.cs b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoWyrmsHeart.cs index 5526491eb..60760c1e5 100644 --- a/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoWyrmsHeart.cs +++ b/Projects/UOContent/Items/Special/Rares/PaganReagents/DecoWyrmsHeart.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoWyrmsHeart : Item - { - [Constructible] - public DecoWyrmsHeart() : base(0xF91) + public class DecoWyrmsHeart : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoWyrmsHeart() : base(0xF91) + { + Movable = true; + Stackable = false; + } + + public DecoWyrmsHeart(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoWyrmsHeart(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PlayingCards/Cards.cs b/Projects/UOContent/Items/Special/Rares/PlayingCards/Cards.cs index 797fabc57..c680aa73b 100644 --- a/Projects/UOContent/Items/Special/Rares/PlayingCards/Cards.cs +++ b/Projects/UOContent/Items/Special/Rares/PlayingCards/Cards.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class Cards : Item - { - [Constructible] - public Cards() : base(0xE19) + public class Cards : Item { - Movable = true; - Stackable = false; + [Constructible] + public Cards() : base(0xE19) + { + Movable = true; + Stackable = false; + } + + public Cards(Serial serial) : base(serial) + { + } + + 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(); + } } - - public Cards(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PlayingCards/Cards2.cs b/Projects/UOContent/Items/Special/Rares/PlayingCards/Cards2.cs index f32711f22..855cc6ae4 100644 --- a/Projects/UOContent/Items/Special/Rares/PlayingCards/Cards2.cs +++ b/Projects/UOContent/Items/Special/Rares/PlayingCards/Cards2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class Cards2 : Item - { - [Constructible] - public Cards2() : base(0xE16) + public class Cards2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public Cards2() : base(0xE16) + { + Movable = true; + Stackable = false; + } + + public Cards2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public Cards2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PlayingCards/Cards3.cs b/Projects/UOContent/Items/Special/Rares/PlayingCards/Cards3.cs index fdb081457..580706ac2 100644 --- a/Projects/UOContent/Items/Special/Rares/PlayingCards/Cards3.cs +++ b/Projects/UOContent/Items/Special/Rares/PlayingCards/Cards3.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class Cards3 : Item - { - [Constructible] - public Cards3() : base(0xE15) + public class Cards3 : Item { - Movable = true; - Stackable = false; + [Constructible] + public Cards3() : base(0xE15) + { + Movable = true; + Stackable = false; + } + + public Cards3(Serial serial) : base(serial) + { + } + + 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(); + } } - - public Cards3(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PlayingCards/Cards4.cs b/Projects/UOContent/Items/Special/Rares/PlayingCards/Cards4.cs index bf76673ec..f90dc3a09 100644 --- a/Projects/UOContent/Items/Special/Rares/PlayingCards/Cards4.cs +++ b/Projects/UOContent/Items/Special/Rares/PlayingCards/Cards4.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class Cards4 : Item - { - [Constructible] - public Cards4() : base(0xE17) + public class Cards4 : Item { - Movable = true; - Stackable = false; + [Constructible] + public Cards4() : base(0xE17) + { + Movable = true; + Stackable = false; + } + + public Cards4(Serial serial) : base(serial) + { + } + + 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(); + } } - - public Cards4(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PlayingCards/Cards5.cs b/Projects/UOContent/Items/Special/Rares/PlayingCards/Cards5.cs index 2d333f769..4ce618b6f 100644 --- a/Projects/UOContent/Items/Special/Rares/PlayingCards/Cards5.cs +++ b/Projects/UOContent/Items/Special/Rares/PlayingCards/Cards5.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoCards5 : Item - { - [Constructible] - public DecoCards5() : base(0xE18) + public class DecoCards5 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoCards5() : base(0xE18) + { + Movable = true; + Stackable = false; + } + + public DecoCards5(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoCards5(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PlayingCards/PlayingCards.cs b/Projects/UOContent/Items/Special/Rares/PlayingCards/PlayingCards.cs index ea6d8aa36..c6b5dcd29 100644 --- a/Projects/UOContent/Items/Special/Rares/PlayingCards/PlayingCards.cs +++ b/Projects/UOContent/Items/Special/Rares/PlayingCards/PlayingCards.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class PlayingCards : Item - { - [Constructible] - public PlayingCards() : base(0xFA3) + public class PlayingCards : Item { - Movable = true; - Stackable = false; + [Constructible] + public PlayingCards() : base(0xFA3) + { + Movable = true; + Stackable = false; + } + + public PlayingCards(Serial serial) : base(serial) + { + } + + 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(); + } } - - public PlayingCards(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/PlayingCards/PlayingCards2.cs b/Projects/UOContent/Items/Special/Rares/PlayingCards/PlayingCards2.cs index 29e83897d..81eedcd1c 100644 --- a/Projects/UOContent/Items/Special/Rares/PlayingCards/PlayingCards2.cs +++ b/Projects/UOContent/Items/Special/Rares/PlayingCards/PlayingCards2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class PlayingCards2 : Item - { - [Constructible] - public PlayingCards2() : base(0xFA2) + public class PlayingCards2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public PlayingCards2() : base(0xFA2) + { + Movable = true; + Stackable = false; + } + + public PlayingCards2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public PlayingCards2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Stables/Bridle.cs b/Projects/UOContent/Items/Special/Rares/Stables/Bridle.cs index 6b6de974b..17d67e58e 100644 --- a/Projects/UOContent/Items/Special/Rares/Stables/Bridle.cs +++ b/Projects/UOContent/Items/Special/Rares/Stables/Bridle.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoBridle : Item - { - [Constructible] - public DecoBridle() : base(0x1374) + public class DecoBridle : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoBridle() : base(0x1374) + { + Movable = true; + Stackable = false; + } + + public DecoBridle(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoBridle(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Stables/Bridle2.cs b/Projects/UOContent/Items/Special/Rares/Stables/Bridle2.cs index e11d9f933..2b81e4ad1 100644 --- a/Projects/UOContent/Items/Special/Rares/Stables/Bridle2.cs +++ b/Projects/UOContent/Items/Special/Rares/Stables/Bridle2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoBridle2 : Item - { - [Constructible] - public DecoBridle2() : base(0x1375) + public class DecoBridle2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoBridle2() : base(0x1375) + { + Movable = true; + Stackable = false; + } + + public DecoBridle2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoBridle2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Stables/DecoHay.cs b/Projects/UOContent/Items/Special/Rares/Stables/DecoHay.cs index 00a5f54a0..1004f2027 100644 --- a/Projects/UOContent/Items/Special/Rares/Stables/DecoHay.cs +++ b/Projects/UOContent/Items/Special/Rares/Stables/DecoHay.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoHay : Item - { - [Constructible] - public DecoHay() : base(0xF35) + public class DecoHay : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoHay() : base(0xF35) + { + Movable = true; + Stackable = false; + } + + public DecoHay(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoHay(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Stables/DecoHay2.cs b/Projects/UOContent/Items/Special/Rares/Stables/DecoHay2.cs index 19019e737..b101f6786 100644 --- a/Projects/UOContent/Items/Special/Rares/Stables/DecoHay2.cs +++ b/Projects/UOContent/Items/Special/Rares/Stables/DecoHay2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoHay2 : Item - { - [Constructible] - public DecoHay2() : base(0xF34) + public class DecoHay2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoHay2() : base(0xF34) + { + Movable = true; + Stackable = false; + } + + public DecoHay2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoHay2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Stables/DecoHorseDung.cs b/Projects/UOContent/Items/Special/Rares/Stables/DecoHorseDung.cs index fe73f27a3..a50eb7af2 100644 --- a/Projects/UOContent/Items/Special/Rares/Stables/DecoHorseDung.cs +++ b/Projects/UOContent/Items/Special/Rares/Stables/DecoHorseDung.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoHorseDung : Item - { - [Constructible] - public DecoHorseDung() : base(0xF3B) + public class DecoHorseDung : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoHorseDung() : base(0xF3B) + { + Movable = true; + Stackable = false; + } + + public DecoHorseDung(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoHorseDung(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/TarotCards/DecoDeckOfTarot.cs b/Projects/UOContent/Items/Special/Rares/TarotCards/DecoDeckOfTarot.cs index 7d00d087b..77e29fe64 100644 --- a/Projects/UOContent/Items/Special/Rares/TarotCards/DecoDeckOfTarot.cs +++ b/Projects/UOContent/Items/Special/Rares/TarotCards/DecoDeckOfTarot.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoDeckOfTarot : Item - { - [Constructible] - public DecoDeckOfTarot() : base(0x12AB) + public class DecoDeckOfTarot : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoDeckOfTarot() : base(0x12AB) + { + Movable = true; + Stackable = false; + } + + public DecoDeckOfTarot(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoDeckOfTarot(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/TarotCards/DecoDeckOfTarot2.cs b/Projects/UOContent/Items/Special/Rares/TarotCards/DecoDeckOfTarot2.cs index 086cebc52..cbf7fe0f2 100644 --- a/Projects/UOContent/Items/Special/Rares/TarotCards/DecoDeckOfTarot2.cs +++ b/Projects/UOContent/Items/Special/Rares/TarotCards/DecoDeckOfTarot2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoDeckOfTarot2 : Item - { - [Constructible] - public DecoDeckOfTarot2() : base(0x12Ac) + public class DecoDeckOfTarot2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoDeckOfTarot2() : base(0x12Ac) + { + Movable = true; + Stackable = false; + } + + public DecoDeckOfTarot2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoDeckOfTarot2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot.cs b/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot.cs index 088846240..ab972c1a4 100644 --- a/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot.cs +++ b/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoTarot : Item - { - [Constructible] - public DecoTarot() : base(0x12A5) + public class DecoTarot : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoTarot() : base(0x12A5) + { + Movable = true; + Stackable = false; + } + + public DecoTarot(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoTarot(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot2.cs b/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot2.cs index f78de7241..c27b65765 100644 --- a/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot2.cs +++ b/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoTarot2 : Item - { - [Constructible] - public DecoTarot2() : base(0x12A6) + public class DecoTarot2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoTarot2() : base(0x12A6) + { + Movable = true; + Stackable = false; + } + + public DecoTarot2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoTarot2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot3.cs b/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot3.cs index 372f59e56..7514975b2 100644 --- a/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot3.cs +++ b/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot3.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoTarot3 : Item - { - [Constructible] - public DecoTarot3() : base(0x12A7) + public class DecoTarot3 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoTarot3() : base(0x12A7) + { + Movable = true; + Stackable = false; + } + + public DecoTarot3(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoTarot3(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot4.cs b/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot4.cs index 25f6eb050..23ea244fc 100644 --- a/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot4.cs +++ b/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot4.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoTarot4 : Item - { - [Constructible] - public DecoTarot4() : base(0x12A8) + public class DecoTarot4 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoTarot4() : base(0x12A8) + { + Movable = true; + Stackable = false; + } + + public DecoTarot4(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoTarot4(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot5.cs b/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot5.cs index bf89f0375..8c88a95b4 100644 --- a/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot5.cs +++ b/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot5.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoTarot5 : Item - { - [Constructible] - public DecoTarot5() : base(0x12A9) + public class DecoTarot5 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoTarot5() : base(0x12A9) + { + Movable = true; + Stackable = false; + } + + public DecoTarot5(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoTarot5(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot6.cs b/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot6.cs index af088da50..0759fe0ad 100644 --- a/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot6.cs +++ b/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot6.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoTarot6 : Item - { - [Constructible] - public DecoTarot6() : base(0x12AA) + public class DecoTarot6 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoTarot6() : base(0x12AA) + { + Movable = true; + Stackable = false; + } + + public DecoTarot6(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoTarot6(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot7.cs b/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot7.cs index d22ea88c6..4416782c6 100644 --- a/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot7.cs +++ b/Projects/UOContent/Items/Special/Rares/TarotCards/DecoTarot7.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoTarot7 : Item - { - [Constructible] - public DecoTarot7() : base(0x12A5) + public class DecoTarot7 : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoTarot7() : base(0x12A5) + { + Movable = true; + Stackable = false; + } + + public DecoTarot7(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoTarot7(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Tinker/ArrowShafts.cs b/Projects/UOContent/Items/Special/Rares/Tinker/ArrowShafts.cs index 107b853d6..be8360cab 100644 --- a/Projects/UOContent/Items/Special/Rares/Tinker/ArrowShafts.cs +++ b/Projects/UOContent/Items/Special/Rares/Tinker/ArrowShafts.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class DecoArrowShafts : Item - { - [Constructible] - public DecoArrowShafts() : base(Utility.Random(2) + 0x1024) + public class DecoArrowShafts : Item { - Movable = true; - Stackable = false; + [Constructible] + public DecoArrowShafts() : base(Utility.Random(2) + 0x1024) + { + Movable = true; + Stackable = false; + } + + public DecoArrowShafts(Serial serial) : base(serial) + { + } + + 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(); + } } - - public DecoArrowShafts(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Tinker/CrossbowBolts.cs b/Projects/UOContent/Items/Special/Rares/Tinker/CrossbowBolts.cs index 510a449c3..35ffd866e 100644 --- a/Projects/UOContent/Items/Special/Rares/Tinker/CrossbowBolts.cs +++ b/Projects/UOContent/Items/Special/Rares/Tinker/CrossbowBolts.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class CrossbowBolts : Item - { - [Constructible] - public CrossbowBolts() : base(0x1BFC) + public class CrossbowBolts : Item { - Movable = true; - Stackable = false; + [Constructible] + public CrossbowBolts() : base(0x1BFC) + { + Movable = true; + Stackable = false; + } + + public CrossbowBolts(Serial serial) : base(serial) + { + } + + 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(); + } } - - public CrossbowBolts(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Tinker/EmptyToolKit.cs b/Projects/UOContent/Items/Special/Rares/Tinker/EmptyToolKit.cs index 8a96900cf..bc352d571 100644 --- a/Projects/UOContent/Items/Special/Rares/Tinker/EmptyToolKit.cs +++ b/Projects/UOContent/Items/Special/Rares/Tinker/EmptyToolKit.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class EmptyToolKit : Item - { - [Constructible] - public EmptyToolKit() : base(0x1EB6) + public class EmptyToolKit : Item { - Movable = true; - Stackable = false; + [Constructible] + public EmptyToolKit() : base(0x1EB6) + { + Movable = true; + Stackable = false; + } + + public EmptyToolKit(Serial serial) : base(serial) + { + } + + 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(); + } } - - public EmptyToolKit(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Tinker/EmptyToolKit2.cs b/Projects/UOContent/Items/Special/Rares/Tinker/EmptyToolKit2.cs index 2d564f19c..69c93a46d 100644 --- a/Projects/UOContent/Items/Special/Rares/Tinker/EmptyToolKit2.cs +++ b/Projects/UOContent/Items/Special/Rares/Tinker/EmptyToolKit2.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class EmptyToolKit2 : Item - { - [Constructible] - public EmptyToolKit2() : base(0x1EB7) + public class EmptyToolKit2 : Item { - Movable = true; - Stackable = false; + [Constructible] + public EmptyToolKit2() : base(0x1EB7) + { + Movable = true; + Stackable = false; + } + + public EmptyToolKit2(Serial serial) : base(serial) + { + } + + 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(); + } } - - public EmptyToolKit2(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Tinker/Lockpicks.cs b/Projects/UOContent/Items/Special/Rares/Tinker/Lockpicks.cs index 2437152d7..abfb0dd6b 100644 --- a/Projects/UOContent/Items/Special/Rares/Tinker/Lockpicks.cs +++ b/Projects/UOContent/Items/Special/Rares/Tinker/Lockpicks.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class Lockpicks : Item - { - [Constructible] - public Lockpicks() : base(Utility.Random(2) + 0x14FD) + public class Lockpicks : Item { - Movable = true; - Stackable = false; + [Constructible] + public Lockpicks() : base(Utility.Random(2) + 0x14FD) + { + Movable = true; + Stackable = false; + } + + public Lockpicks(Serial serial) : base(serial) + { + } + + 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(); + } } - - public Lockpicks(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Rares/Tinker/ToolKit.cs b/Projects/UOContent/Items/Special/Rares/Tinker/ToolKit.cs index 51c6ccf16..fab40ff82 100644 --- a/Projects/UOContent/Items/Special/Rares/Tinker/ToolKit.cs +++ b/Projects/UOContent/Items/Special/Rares/Tinker/ToolKit.cs @@ -1,30 +1,30 @@ namespace Server.Items { - public class ToolKit : Item - { - [Constructible] - public ToolKit() : base(Utility.Random(2) + 0x1EBA) + public class ToolKit : Item { - Movable = true; - Stackable = false; + [Constructible] + public ToolKit() : base(Utility.Random(2) + 0x1EBA) + { + Movable = true; + Stackable = false; + } + + public ToolKit(Serial serial) : base(serial) + { + } + + 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(); + } } - - public ToolKit(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/RewardCake.cs b/Projects/UOContent/Items/Special/RewardCake.cs index de6c283ef..bcfbcf6bc 100644 --- a/Projects/UOContent/Items/Special/RewardCake.cs +++ b/Projects/UOContent/Items/Special/RewardCake.cs @@ -2,45 +2,61 @@ using Server.Network; namespace Server.Items { - public class RewardCake : Item - { - [Constructible] - public RewardCake() : base(0x9e9) + public class RewardCake : Item { - Stackable = false; - Weight = 1.0; - Hue = Utility.RandomList(0x135, 0xcd, 0x38, 0x3b, 0x42, 0x4f, 0x11e, 0x60, 0x317, 0x10, 0x136, 0x1f9, 0x1a, 0xeb, - 0x86, 0x2e); - LootType = LootType.Blessed; + [Constructible] + public RewardCake() : base(0x9e9) + { + Stackable = false; + Weight = 1.0; + Hue = Utility.RandomList( + 0x135, + 0xcd, + 0x38, + 0x3b, + 0x42, + 0x4f, + 0x11e, + 0x60, + 0x317, + 0x10, + 0x136, + 0x1f9, + 0x1a, + 0xeb, + 0x86, + 0x2e + ); + LootType = LootType.Blessed; + } + + public RewardCake(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1049786; // Happy Birthday! ... + + public override bool DisplayLootType => false; + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 1)) + from.LocalOverheadMessage(MessageType.Regular, 906, 1019045); // I can't reach that. + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + LootType = LootType.Blessed; + + var version = reader.ReadInt(); + } } - - public RewardCake(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1049786; // Happy Birthday! ... - - public override bool DisplayLootType => false; - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 1)) - from.LocalOverheadMessage(MessageType.Regular, 906, 1019045); // I can't reach that. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - LootType = LootType.Blessed; - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Solen Items/BagOfSending.cs b/Projects/UOContent/Items/Special/Solen Items/BagOfSending.cs index edf52fafd..51f2a96d7 100644 --- a/Projects/UOContent/Items/Special/Solen Items/BagOfSending.cs +++ b/Projects/UOContent/Items/Special/Solen Items/BagOfSending.cs @@ -9,261 +9,294 @@ using Server.Targeting; namespace Server.Items { - public enum BagOfSendingHue - { - Yellow, - Blue, - Red - } - - public class BagOfSending : Item, TranslocationItem - { - private BagOfSendingHue m_BagOfSendingHue; - - private int m_Charges; - private int m_Recharges; - - [Constructible] - public BagOfSending() : this(RandomHue()) + public enum BagOfSendingHue { + Yellow, + Blue, + Red } - [Constructible] - public BagOfSending(BagOfSendingHue hue) : base(0xE76) + public class BagOfSending : Item, TranslocationItem { - Weight = 2.0; + private BagOfSendingHue m_BagOfSendingHue; - BagOfSendingHue = hue; + private int m_Charges; + private int m_Recharges; - m_Charges = Utility.RandomMinMax(3, 9); - } - - public BagOfSending(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1054104; // a bag of sending - - [CommandProperty(AccessLevel.GameMaster)] - public BagOfSendingHue BagOfSendingHue - { - get => m_BagOfSendingHue; - set - { - m_BagOfSendingHue = value; - - Hue = value switch + [Constructible] + public BagOfSending() : this(RandomHue()) { - BagOfSendingHue.Yellow => 0x8A5, - BagOfSendingHue.Blue => 0x8AD, - BagOfSendingHue.Red => 0x89B, - _ => Hue - }; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Charges - { - get => m_Charges; - set - { - m_Charges = Math.Clamp(value, 0, MaxCharges); - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Recharges - { - get => m_Recharges; - set - { - m_Recharges = Math.Clamp(value, 0, MaxRecharges); - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxCharges => 30; - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxRecharges => 255; - - public string TranslocationItemName => "bag of sending"; - - public static BagOfSendingHue RandomHue() - { - return Utility.Random(3) switch - { - 0 => BagOfSendingHue.Yellow, - 1 => BagOfSendingHue.Blue, - _ => BagOfSendingHue.Red - }; - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1060741, m_Charges.ToString()); // charges: ~1_val~ - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - LabelTo(from, 1060741, m_Charges.ToString()); // charges: ~1_val~ - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (from.Alive) - list.Add(new UseBagEntry(this, Charges > 0 && IsChildOf(from.Backpack))); - } - - public override void OnDoubleClick(Mobile from) - { - if (from.Region.IsPartOf()) - from.SendMessage("You may not do that in jail."); - else if (!IsChildOf(from.Backpack)) - MessageHelper.SendLocalizedMessageTo(this, from, 1062334, - 0x59); // The bag of sending must be in your backpack. - else if (Charges == 0) - MessageHelper.SendLocalizedMessageTo(this, from, 1042544, 0x59); // This item is out of charges. - else - from.Target = new SendTarget(this); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(1); // version - - writer.WriteEncodedInt(m_Recharges); - - writer.WriteEncodedInt(m_Charges); - writer.WriteEncodedInt((int)m_BagOfSendingHue); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 1: - { - m_Recharges = reader.ReadEncodedInt(); - goto case 0; - } - case 0: - { - m_Charges = Math.Min(reader.ReadEncodedInt(), MaxCharges); - m_BagOfSendingHue = (BagOfSendingHue)reader.ReadEncodedInt(); - break; - } - } - } - - private class UseBagEntry : ContextMenuEntry - { - private readonly BagOfSending m_Bag; - - public UseBagEntry(BagOfSending bag, bool enabled) : base(6189) - { - m_Bag = bag; - - if (!enabled) - Flags |= CMEFlags.Disabled; - } - - public override void OnClick() - { - if (m_Bag.Deleted) - return; - - Mobile from = Owner.From; - - if (from.CheckAlive()) - m_Bag.OnDoubleClick(from); - } - } - - private class SendTarget : Target - { - private readonly BagOfSending m_Bag; - - public SendTarget(BagOfSending bag) : base(-1, false, TargetFlags.None) => m_Bag = bag; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Bag.Deleted) - return; - - if (from.Region.IsPartOf()) - { - from.SendMessage("You may not do that in jail."); } - else if (!m_Bag.IsChildOf(from.Backpack)) - { - MessageHelper.SendLocalizedMessageTo(m_Bag, from, 1062334, - 0x59); // The bag of sending must be in your backpack. 1054107 is gone from client, using generic response - } - else if (m_Bag.Charges == 0) - { - MessageHelper.SendLocalizedMessageTo(m_Bag, from, 1042544, 0x59); // This item is out of charges. - } - else if (targeted is Item item) - { - int reqCharges = (int)Math.Max(1, Math.Ceiling(item.TotalWeight / 10.0)); - if (!item.IsChildOf(from.Backpack)) - { - MessageHelper.SendLocalizedMessageTo(m_Bag, from, 1054152, - 0x59); // You may only send items from your backpack to your bank box. - } - else if (item is BagOfSending || item is Container) - { - from.Send(new AsciiMessage(m_Bag.Serial, m_Bag.ItemID, MessageType.Regular, 0x3B2, 3, "", - "You cannot send a container through the bag of sending.")); - } - else if (item.LootType == LootType.Cursed) - { - MessageHelper.SendLocalizedMessageTo(m_Bag, from, 1054108, - 0x59); // The bag of sending rejects the cursed item. - } - else if (!item.VerifyMove(from) || item is QuestItem || item.Nontransferable) - { - MessageHelper.SendLocalizedMessageTo(m_Bag, from, 1054109, - 0x59); // The bag of sending rejects that item. - } - else if (SpellHelper.IsDoomGauntlet(from.Map, from.Location)) - { - from.SendLocalizedMessage(1062089); // You cannot use that here. - } - else if (!from.BankBox.TryDropItem(from, item, false)) - { - MessageHelper.SendLocalizedMessageTo(m_Bag, from, 1054110, 0x59); // Your bank box is full. - } - else if (Core.ML && reqCharges > m_Bag.Charges) - { - from.SendLocalizedMessage(1079932); // You don't have enough charges to send that much weight - } - else - { - m_Bag.Charges -= Core.ML ? reqCharges : 1; + [Constructible] + public BagOfSending(BagOfSendingHue hue) : base(0xE76) + { + Weight = 2.0; - MessageHelper.SendLocalizedMessageTo(m_Bag, from, 1054150, - 0x59); // The item was placed in your bank box. - } + BagOfSendingHue = hue; + + m_Charges = Utility.RandomMinMax(3, 9); + } + + public BagOfSending(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1054104; // a bag of sending + + [CommandProperty(AccessLevel.GameMaster)] + public BagOfSendingHue BagOfSendingHue + { + get => m_BagOfSendingHue; + set + { + m_BagOfSendingHue = value; + + Hue = value switch + { + BagOfSendingHue.Yellow => 0x8A5, + BagOfSendingHue.Blue => 0x8AD, + BagOfSendingHue.Red => 0x89B, + _ => Hue + }; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Charges + { + get => m_Charges; + set + { + m_Charges = Math.Clamp(value, 0, MaxCharges); + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Recharges + { + get => m_Recharges; + set + { + m_Recharges = Math.Clamp(value, 0, MaxRecharges); + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxCharges => 30; + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxRecharges => 255; + + public string TranslocationItemName => "bag of sending"; + + public static BagOfSendingHue RandomHue() + { + return Utility.Random(3) switch + { + 0 => BagOfSendingHue.Yellow, + 1 => BagOfSendingHue.Blue, + _ => BagOfSendingHue.Red + }; + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1060741, m_Charges.ToString()); // charges: ~1_val~ + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + LabelTo(from, 1060741, m_Charges.ToString()); // charges: ~1_val~ + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (from.Alive) + list.Add(new UseBagEntry(this, Charges > 0 && IsChildOf(from.Backpack))); + } + + public override void OnDoubleClick(Mobile from) + { + if (from.Region.IsPartOf()) + from.SendMessage("You may not do that in jail."); + else if (!IsChildOf(from.Backpack)) + MessageHelper.SendLocalizedMessageTo( + this, + from, + 1062334, + 0x59 + ); // The bag of sending must be in your backpack. + else if (Charges == 0) + MessageHelper.SendLocalizedMessageTo(this, from, 1042544, 0x59); // This item is out of charges. + else + from.Target = new SendTarget(this); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(1); // version + + writer.WriteEncodedInt(m_Recharges); + + writer.WriteEncodedInt(m_Charges); + writer.WriteEncodedInt((int)m_BagOfSendingHue); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 1: + { + m_Recharges = reader.ReadEncodedInt(); + goto case 0; + } + case 0: + { + m_Charges = Math.Min(reader.ReadEncodedInt(), MaxCharges); + m_BagOfSendingHue = (BagOfSendingHue)reader.ReadEncodedInt(); + break; + } + } + } + + private class UseBagEntry : ContextMenuEntry + { + private readonly BagOfSending m_Bag; + + public UseBagEntry(BagOfSending bag, bool enabled) : base(6189) + { + m_Bag = bag; + + if (!enabled) + Flags |= CMEFlags.Disabled; + } + + public override void OnClick() + { + if (m_Bag.Deleted) + return; + + var from = Owner.From; + + if (from.CheckAlive()) + m_Bag.OnDoubleClick(from); + } + } + + private class SendTarget : Target + { + private readonly BagOfSending m_Bag; + + public SendTarget(BagOfSending bag) : base(-1, false, TargetFlags.None) => m_Bag = bag; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Bag.Deleted) + return; + + if (from.Region.IsPartOf()) + { + from.SendMessage("You may not do that in jail."); + } + else if (!m_Bag.IsChildOf(from.Backpack)) + { + MessageHelper.SendLocalizedMessageTo( + m_Bag, + from, + 1062334, + 0x59 + ); // The bag of sending must be in your backpack. 1054107 is gone from client, using generic response + } + else if (m_Bag.Charges == 0) + { + MessageHelper.SendLocalizedMessageTo(m_Bag, from, 1042544, 0x59); // This item is out of charges. + } + else if (targeted is Item item) + { + var reqCharges = (int)Math.Max(1, Math.Ceiling(item.TotalWeight / 10.0)); + + if (!item.IsChildOf(from.Backpack)) + { + MessageHelper.SendLocalizedMessageTo( + m_Bag, + from, + 1054152, + 0x59 + ); // You may only send items from your backpack to your bank box. + } + else if (item is BagOfSending || item is Container) + { + from.Send( + new AsciiMessage( + m_Bag.Serial, + m_Bag.ItemID, + MessageType.Regular, + 0x3B2, + 3, + "", + "You cannot send a container through the bag of sending." + ) + ); + } + else if (item.LootType == LootType.Cursed) + { + MessageHelper.SendLocalizedMessageTo( + m_Bag, + from, + 1054108, + 0x59 + ); // The bag of sending rejects the cursed item. + } + else if (!item.VerifyMove(from) || item is QuestItem || item.Nontransferable) + { + MessageHelper.SendLocalizedMessageTo( + m_Bag, + from, + 1054109, + 0x59 + ); // The bag of sending rejects that item. + } + else if (SpellHelper.IsDoomGauntlet(from.Map, from.Location)) + { + from.SendLocalizedMessage(1062089); // You cannot use that here. + } + else if (!from.BankBox.TryDropItem(from, item, false)) + { + MessageHelper.SendLocalizedMessageTo(m_Bag, from, 1054110, 0x59); // Your bank box is full. + } + else if (Core.ML && reqCharges > m_Bag.Charges) + { + from.SendLocalizedMessage(1079932); // You don't have enough charges to send that much weight + } + else + { + m_Bag.Charges -= Core.ML ? reqCharges : 1; + + MessageHelper.SendLocalizedMessageTo( + m_Bag, + from, + 1054150, + 0x59 + ); // The item was placed in your bank box. + } + } + } } - } } - } } diff --git a/Projects/UOContent/Items/Special/Solen Items/BallOfSummoning.cs b/Projects/UOContent/Items/Special/Solen Items/BallOfSummoning.cs index aab0e4df4..da3b36b5d 100644 --- a/Projects/UOContent/Items/Special/Solen Items/BallOfSummoning.cs +++ b/Projects/UOContent/Items/Special/Solen Items/BallOfSummoning.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Runtime.CompilerServices; using Server.ContextMenus; using Server.Engines.ConPVP; using Server.Mobiles; @@ -12,421 +11,492 @@ using Server.Targeting; namespace Server.Items { - public class BallOfSummoning : Item, TranslocationItem - { - private int m_Charges; - private BaseCreature m_Pet; - private int m_Recharges; - - [Constructible] - public BallOfSummoning() : base(0xE2E) + public class BallOfSummoning : Item, TranslocationItem { - Weight = 10.0; - Light = LightType.Circle150; + private int m_Charges; + private BaseCreature m_Pet; + private int m_Recharges; - m_Charges = Utility.RandomMinMax(3, 9); - - PetName = ""; - } - - public BallOfSummoning(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public BaseCreature Pet - { - get - { - if (m_Pet?.Deleted == true) + [Constructible] + public BallOfSummoning() : base(0xE2E) { - m_Pet = null; - InternalUpdatePetName(); + Weight = 10.0; + Light = LightType.Circle150; + + m_Charges = Utility.RandomMinMax(3, 9); + + PetName = ""; } - return m_Pet; - } - set - { - m_Pet = value; - InternalUpdatePetName(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public string PetName { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Charges - { - get => m_Charges; - set - { - m_Charges = Math.Clamp(value, 0, MaxCharges); - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Recharges - { - get => m_Recharges; - set - { - m_Recharges = Math.Clamp(value, 0, MaxRecharges); - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxCharges => 20; - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxRecharges => 255; - - public string TranslocationItemName => "crystal ball of pet summoning"; - - public override void AddNameProperty(ObjectPropertyList list) - { - list.Add(1054131, - $"{m_Charges}\t{PetName.IsNullOrDefault(" ")}"); // a crystal ball of pet summoning: [charges: ~1_charges~] : [linked pet: ~2_petName~] - } - - public override void OnSingleClick(Mobile from) - { - LabelTo(from, 1054131, - $"{m_Charges}\t{PetName.IsNullOrDefault(" ")}"); // a crystal ball of pet summoning: [charges: ~1_charges~] : [linked pet: ~2_petName~] - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (from.Alive && RootParent == from) - { - if (Pet == null) + public BallOfSummoning(Serial serial) : base(serial) { - list.Add(new BallEntry(LinkPet, 6180)); } - else + + [CommandProperty(AccessLevel.GameMaster)] + public BaseCreature Pet { - list.Add(new BallEntry(CastSummonPet, 6181)); - list.Add(new BallEntry(UpdatePetName, 6183)); - list.Add(new BallEntry(UnlinkPet, 6182)); + get + { + if (m_Pet?.Deleted == true) + { + m_Pet = null; + InternalUpdatePetName(); + } + + return m_Pet; + } + set + { + m_Pet = value; + InternalUpdatePetName(); + } } - } - } - public override void OnDoubleClick(Mobile from) - { - if (RootParent != from) // TODO: Previous implementation allowed use on ground, without house protection checks. What is the correct behavior? - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1042001); // That must be in your pack for you to use it. - return; - } + [CommandProperty(AccessLevel.GameMaster)] + public string PetName { get; private set; } - AnimalFormContext animalContext = AnimalForm.GetContext(from); - - if (Core.ML && animalContext != null) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1080073); // You cannot use a Crystal Ball of Pet Summoning while in animal form. - return; - } - - if (Pet == null) - LinkPet(from); - else - CastSummonPet(from); - } - - public void LinkPet(Mobile from) - { - BaseCreature pet = Pet; - - if (Deleted || pet != null || RootParent != from) - return; - - from.SendLocalizedMessage( - 1054114); // Target your pet that you wish to link to this Crystal Ball of Pet Summoning. - from.Target = new PetLinkTarget(this); - } - - public void CastSummonPet(Mobile from) - { - BaseCreature pet = Pet; - - if (Deleted || pet == null || RootParent != from) - return; - - if (Charges == 0) - { - SendLocalizedMessageTo(from, - 1054122); // The Crystal Ball darkens. It must be charged before it can be used again. - } - else if (pet is BaseMount mount && mount.Rider == from) - { - MessageHelper.SendLocalizedMessageTo(this, from, 1054124, - 0x36); // The Crystal Ball fills with a yellow mist. Why would you summon your pet while riding it? - } - else if (pet.Map == Map.Internal && (!pet.IsStabled || from.Followers + pet.ControlSlots > from.FollowersMax)) - { - MessageHelper.SendLocalizedMessageTo(this, from, 1054125, - 0x5); // The Crystal Ball fills with a blue mist. Your pet is not responding to the summons. - } - else if ((!pet.Controlled || pet.ControlMaster != from) && !from.Stabled.Contains(pet)) - { - MessageHelper.SendLocalizedMessageTo(this, from, 1054126, - 0x8FD); // The Crystal Ball fills with a grey mist. You are not the owner of the pet you are attempting to summon. - } - else if (!pet.IsBonded) - { - MessageHelper.SendLocalizedMessageTo(this, from, 1054127, - 0x22); // The Crystal Ball fills with a red mist. You appear to have let your bond to your pet deteriorate. - } - else if (from.Map == Map.Ilshenar || from.Region.IsPartOf() || - from.Region.IsPartOf() || from.Region.IsPartOf()) - { - from.Send(new AsciiMessage(Serial, ItemID, MessageType.Regular, 0x22, 3, "", - "You cannot summon your pet to this location.")); - } - else if (Core.ML && from is PlayerMobile mobile && DateTime.UtcNow < mobile.LastPetBallTime.AddSeconds(15.0)) - { - MessageHelper.SendLocalizedMessageTo(this, mobile, 1080072, - 0x22); // You must wait a few seconds before you can summon your pet. - } - else - { - if (Core.ML) - new PetSummoningSpell(this, from).Cast(); - else - SummonPet(from); - } - } - - public void SummonPet(Mobile from) - { - BaseCreature pet = Pet; - - if (pet == null) - return; - - Charges--; - - if (pet.IsStabled) - { - pet.SetControlMaster(from); - - if (pet.Summoned) - pet.SummonMaster = from; - - pet.ControlTarget = from; - pet.ControlOrder = OrderType.Follow; - - pet.IsStabled = false; - pet.StabledBy = null; - from.Stabled.Remove(pet); - - if (from is PlayerMobile mobile) - mobile.AutoStabled.Remove(pet); - } - - pet.MoveToWorld(from.Location, from.Map); - - MessageHelper.SendLocalizedMessageTo(this, from, 1054128, - 0x43); // The Crystal Ball fills with a green mist. Your pet has been summoned. - - if (from is PlayerMobile playerMobile) playerMobile.LastPetBallTime = DateTime.UtcNow; - } - - public void UnlinkPet(Mobile from) - { - if (!Deleted && Pet != null && RootParent == from) - { - Pet = null; - - SendLocalizedMessageTo(from, 1054120); // This crystal ball is no longer linked to a pet. - } - } - - public void UpdatePetName(Mobile from) - { - InternalUpdatePetName(); - } - - private void InternalUpdatePetName() - { - PetName = Pet?.Name ?? ""; - InvalidateProperties(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(1); // version - - writer.WriteEncodedInt(m_Recharges); - - writer.WriteEncodedInt(m_Charges); - writer.Write(Pet); - writer.Write(PetName); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 1: - { - m_Recharges = reader.ReadEncodedInt(); - goto case 0; - } - case 0: - { - m_Charges = Math.Min(reader.ReadEncodedInt(), MaxCharges); - Pet = (BaseCreature)reader.ReadMobile(); - PetName = reader.ReadString(); - break; - } - } - } - - private delegate void BallCallback(Mobile from); - - private class BallEntry : ContextMenuEntry - { - private readonly BallCallback m_Callback; - - public BallEntry(BallCallback callback, int number) : base(number, 2) => m_Callback = callback; - - public override void OnClick() - { - Mobile from = Owner.From; - - if (from.CheckAlive()) - m_Callback(from); - } - } - - private class PetLinkTarget : Target - { - private readonly BallOfSummoning m_Ball; - - public PetLinkTarget(BallOfSummoning ball) : base(-1, false, TargetFlags.None) => m_Ball = ball; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Ball.Deleted || m_Ball.Pet != null) - return; - - if (m_Ball.RootParent != from) + [CommandProperty(AccessLevel.GameMaster)] + public int Charges { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1042001); // That must be in your pack for you to use it. + get => m_Charges; + set + { + m_Charges = Math.Clamp(value, 0, MaxCharges); + InvalidateProperties(); + } } - else if (targeted is BaseCreature creature) - { - if (!creature.Controlled || creature.ControlMaster != from) - { - MessageHelper.SendLocalizedMessageTo(m_Ball, from, 1054117, - 0x59); // You may only link your own pets to a Crystal Ball of Pet Summoning. - } - else if (!creature.IsBonded) - { - MessageHelper.SendLocalizedMessageTo(m_Ball, from, 1054118, - 0x59); // You must bond with your pet before it can be linked to a Crystal Ball of Pet Summoning. - } - else - { - MessageHelper.SendLocalizedMessageTo(m_Ball, from, 1054119, - 0x59); // Your pet is now linked to this Crystal Ball of Pet Summoning. - m_Ball.Pet = creature; - } - } - else if (targeted == m_Ball) + [CommandProperty(AccessLevel.GameMaster)] + public int Recharges { - MessageHelper.SendLocalizedMessageTo(m_Ball, from, 1054115, - 0x59); // The Crystal Ball of Pet Summoning cannot summon itself. + get => m_Recharges; + set + { + m_Recharges = Math.Clamp(value, 0, MaxRecharges); + InvalidateProperties(); + } } - else + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxCharges => 20; + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxRecharges => 255; + + public string TranslocationItemName => "crystal ball of pet summoning"; + + public override void AddNameProperty(ObjectPropertyList list) { - MessageHelper.SendLocalizedMessageTo(m_Ball, from, 1054116, - 0x59); // Only pets can be linked to this Crystal Ball of Pet Summoning. + list.Add( + 1054131, + $"{m_Charges}\t{PetName.IsNullOrDefault(" ")}" + ); // a crystal ball of pet summoning: [charges: ~1_charges~] : [linked pet: ~2_petName~] + } + + public override void OnSingleClick(Mobile from) + { + LabelTo( + from, + 1054131, + $"{m_Charges}\t{PetName.IsNullOrDefault(" ")}" + ); // a crystal ball of pet summoning: [charges: ~1_charges~] : [linked pet: ~2_petName~] + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (from.Alive && RootParent == from) + { + if (Pet == null) + { + list.Add(new BallEntry(LinkPet, 6180)); + } + else + { + list.Add(new BallEntry(CastSummonPet, 6181)); + list.Add(new BallEntry(UpdatePetName, 6183)); + list.Add(new BallEntry(UnlinkPet, 6182)); + } + } + } + + public override void OnDoubleClick(Mobile from) + { + if (RootParent != from + ) // TODO: Previous implementation allowed use on ground, without house protection checks. What is the correct behavior? + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1042001 + ); // That must be in your pack for you to use it. + return; + } + + var animalContext = AnimalForm.GetContext(from); + + if (Core.ML && animalContext != null) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1080073 + ); // You cannot use a Crystal Ball of Pet Summoning while in animal form. + return; + } + + if (Pet == null) + LinkPet(from); + else + CastSummonPet(from); + } + + public void LinkPet(Mobile from) + { + var pet = Pet; + + if (Deleted || pet != null || RootParent != from) + return; + + from.SendLocalizedMessage( + 1054114 + ); // Target your pet that you wish to link to this Crystal Ball of Pet Summoning. + from.Target = new PetLinkTarget(this); + } + + public void CastSummonPet(Mobile from) + { + var pet = Pet; + + if (Deleted || pet == null || RootParent != from) + return; + + if (Charges == 0) + { + SendLocalizedMessageTo( + from, + 1054122 + ); // The Crystal Ball darkens. It must be charged before it can be used again. + } + else if (pet is BaseMount mount && mount.Rider == from) + { + MessageHelper.SendLocalizedMessageTo( + this, + from, + 1054124, + 0x36 + ); // The Crystal Ball fills with a yellow mist. Why would you summon your pet while riding it? + } + else if (pet.Map == Map.Internal && (!pet.IsStabled || from.Followers + pet.ControlSlots > from.FollowersMax)) + { + MessageHelper.SendLocalizedMessageTo( + this, + from, + 1054125, + 0x5 + ); // The Crystal Ball fills with a blue mist. Your pet is not responding to the summons. + } + else if ((!pet.Controlled || pet.ControlMaster != from) && !from.Stabled.Contains(pet)) + { + MessageHelper.SendLocalizedMessageTo( + this, + from, + 1054126, + 0x8FD + ); // The Crystal Ball fills with a grey mist. You are not the owner of the pet you are attempting to summon. + } + else if (!pet.IsBonded) + { + MessageHelper.SendLocalizedMessageTo( + this, + from, + 1054127, + 0x22 + ); // The Crystal Ball fills with a red mist. You appear to have let your bond to your pet deteriorate. + } + else if (from.Map == Map.Ilshenar || from.Region.IsPartOf() || + from.Region.IsPartOf() || from.Region.IsPartOf()) + { + from.Send( + new AsciiMessage( + Serial, + ItemID, + MessageType.Regular, + 0x22, + 3, + "", + "You cannot summon your pet to this location." + ) + ); + } + else if (Core.ML && from is PlayerMobile mobile && DateTime.UtcNow < mobile.LastPetBallTime.AddSeconds(15.0)) + { + MessageHelper.SendLocalizedMessageTo( + this, + mobile, + 1080072, + 0x22 + ); // You must wait a few seconds before you can summon your pet. + } + else + { + if (Core.ML) + new PetSummoningSpell(this, from).Cast(); + else + SummonPet(from); + } + } + + public void SummonPet(Mobile from) + { + var pet = Pet; + + if (pet == null) + return; + + Charges--; + + if (pet.IsStabled) + { + pet.SetControlMaster(from); + + if (pet.Summoned) + pet.SummonMaster = from; + + pet.ControlTarget = from; + pet.ControlOrder = OrderType.Follow; + + pet.IsStabled = false; + pet.StabledBy = null; + from.Stabled.Remove(pet); + + if (from is PlayerMobile mobile) + mobile.AutoStabled.Remove(pet); + } + + pet.MoveToWorld(from.Location, from.Map); + + MessageHelper.SendLocalizedMessageTo( + this, + from, + 1054128, + 0x43 + ); // The Crystal Ball fills with a green mist. Your pet has been summoned. + + if (from is PlayerMobile playerMobile) playerMobile.LastPetBallTime = DateTime.UtcNow; + } + + public void UnlinkPet(Mobile from) + { + if (!Deleted && Pet != null && RootParent == from) + { + Pet = null; + + SendLocalizedMessageTo(from, 1054120); // This crystal ball is no longer linked to a pet. + } + } + + public void UpdatePetName(Mobile from) + { + InternalUpdatePetName(); + } + + private void InternalUpdatePetName() + { + PetName = Pet?.Name ?? ""; + InvalidateProperties(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(1); // version + + writer.WriteEncodedInt(m_Recharges); + + writer.WriteEncodedInt(m_Charges); + writer.Write(Pet); + writer.Write(PetName); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 1: + { + m_Recharges = reader.ReadEncodedInt(); + goto case 0; + } + case 0: + { + m_Charges = Math.Min(reader.ReadEncodedInt(), MaxCharges); + Pet = (BaseCreature)reader.ReadMobile(); + PetName = reader.ReadString(); + break; + } + } + } + + private delegate void BallCallback(Mobile from); + + private class BallEntry : ContextMenuEntry + { + private readonly BallCallback m_Callback; + + public BallEntry(BallCallback callback, int number) : base(number, 2) => m_Callback = callback; + + public override void OnClick() + { + var from = Owner.From; + + if (from.CheckAlive()) + m_Callback(from); + } + } + + private class PetLinkTarget : Target + { + private readonly BallOfSummoning m_Ball; + + public PetLinkTarget(BallOfSummoning ball) : base(-1, false, TargetFlags.None) => m_Ball = ball; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Ball.Deleted || m_Ball.Pet != null) + return; + + if (m_Ball.RootParent != from) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1042001 + ); // That must be in your pack for you to use it. + } + else if (targeted is BaseCreature creature) + { + if (!creature.Controlled || creature.ControlMaster != from) + { + MessageHelper.SendLocalizedMessageTo( + m_Ball, + from, + 1054117, + 0x59 + ); // You may only link your own pets to a Crystal Ball of Pet Summoning. + } + else if (!creature.IsBonded) + { + MessageHelper.SendLocalizedMessageTo( + m_Ball, + from, + 1054118, + 0x59 + ); // You must bond with your pet before it can be linked to a Crystal Ball of Pet Summoning. + } + else + { + MessageHelper.SendLocalizedMessageTo( + m_Ball, + from, + 1054119, + 0x59 + ); // Your pet is now linked to this Crystal Ball of Pet Summoning. + + m_Ball.Pet = creature; + } + } + else if (targeted == m_Ball) + { + MessageHelper.SendLocalizedMessageTo( + m_Ball, + from, + 1054115, + 0x59 + ); // The Crystal Ball of Pet Summoning cannot summon itself. + } + else + { + MessageHelper.SendLocalizedMessageTo( + m_Ball, + from, + 1054116, + 0x59 + ); // Only pets can be linked to this Crystal Ball of Pet Summoning. + } + } + } + + private class PetSummoningSpell : Spell + { + private static readonly SpellInfo m_Info = new SpellInfo("Ball Of Summoning", "", 230); + + private readonly BallOfSummoning m_Ball; + private readonly Mobile m_Caster; + + private bool m_Stop; + + public PetSummoningSpell(BallOfSummoning ball, Mobile caster) + : base(caster, null, m_Info) + { + m_Caster = caster; + m_Ball = ball; + } + + public override bool ClearHandsOnCast => false; + public override bool RevealOnCast => true; + + public override double CastDelayFastScalar => 0; + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.0); + + public override TimeSpan GetCastRecovery() => TimeSpan.Zero; + + public override int GetMana() => 0; + + public override bool ConsumeReagents() => true; + + public override bool CheckFizzle() => true; + + public void Stop() + { + m_Stop = true; + Disturb(DisturbType.Hurt, false); + } + + public override bool CheckDisturb(DisturbType type, bool checkFirst, bool resistable) => + type != DisturbType.EquipRequest && type != DisturbType.UseRequest; + + public override void DoHurtFizzle() + { + if (!m_Stop) + base.DoHurtFizzle(); + } + + public override void DoFizzle() + { + if (!m_Stop) + base.DoFizzle(); + } + + public override void OnDisturb(DisturbType type, bool message) + { + if (message && !m_Stop) + Caster.SendLocalizedMessage(1080074); // You have been disrupted while attempting to summon your pet! + } + + public override void OnCast() + { + m_Ball.SummonPet(m_Caster); + + FinishSequence(); + } } - } } - - private class PetSummoningSpell : Spell - { - private static readonly SpellInfo m_Info = new SpellInfo("Ball Of Summoning", "", 230); - - private readonly BallOfSummoning m_Ball; - private readonly Mobile m_Caster; - - private bool m_Stop; - - public PetSummoningSpell(BallOfSummoning ball, Mobile caster) - : base(caster, null, m_Info) - { - m_Caster = caster; - m_Ball = ball; - } - - public override bool ClearHandsOnCast => false; - public override bool RevealOnCast => true; - - public override double CastDelayFastScalar => 0; - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.0); - - public override TimeSpan GetCastRecovery() => TimeSpan.Zero; - - public override int GetMana() => 0; - - public override bool ConsumeReagents() => true; - - public override bool CheckFizzle() => true; - - public void Stop() - { - m_Stop = true; - Disturb(DisturbType.Hurt, false); - } - - public override bool CheckDisturb(DisturbType type, bool checkFirst, bool resistable) => - type != DisturbType.EquipRequest && type != DisturbType.UseRequest; - - public override void DoHurtFizzle() - { - if (!m_Stop) - base.DoHurtFizzle(); - } - - public override void DoFizzle() - { - if (!m_Stop) - base.DoFizzle(); - } - - public override void OnDisturb(DisturbType type, bool message) - { - if (message && !m_Stop) - Caster.SendLocalizedMessage(1080074); // You have been disrupted while attempting to summon your pet! - } - - public override void OnCast() - { - m_Ball.SummonPet(m_Caster); - - FinishSequence(); - } - } - } } diff --git a/Projects/UOContent/Items/Special/Solen Items/BraceletOfBinding.cs b/Projects/UOContent/Items/Special/Solen Items/BraceletOfBinding.cs index 2798b4d55..81c26f234 100644 --- a/Projects/UOContent/Items/Special/Solen Items/BraceletOfBinding.cs +++ b/Projects/UOContent/Items/Special/Solen Items/BraceletOfBinding.cs @@ -12,440 +12,453 @@ using Server.Targeting; namespace Server.Items { - public class BraceletOfBinding : BaseBracelet, TranslocationItem - { - private BraceletOfBinding m_Bound; - private int m_Charges; - private string m_Inscription; - private int m_Recharges; - private TransportTimer m_Timer; - - [Constructible] - public BraceletOfBinding() : base(0x1086) + public class BraceletOfBinding : BaseBracelet, TranslocationItem { - Hue = 0x489; - Weight = 1.0; - - m_Inscription = ""; - } - - public BraceletOfBinding(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public string Inscription - { - get => m_Inscription; - set - { - m_Inscription = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public BraceletOfBinding Bound - { - get - { - if (m_Bound?.Deleted == true) - m_Bound = null; - - return m_Bound; - } - set => m_Bound = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Charges - { - get => m_Charges; - set - { - m_Charges = Math.Clamp(value, 0, MaxCharges); - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Recharges - { - get => m_Recharges; - set - { - m_Recharges = Math.Clamp(value, 0, MaxRecharges); - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxCharges => 20; - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxRecharges => 255; - - public string TranslocationItemName => "bracelet of binding"; - - public override void AddNameProperty(ObjectPropertyList list) - { - list.Add(1054000, - $"{m_Charges}\t{m_Inscription.IsNullOrDefault(" ")}"); // a bracelet of binding : ~1_val~ ~2_val~ - } - - public override void OnSingleClick(Mobile from) - { - LabelTo(from, 1054000, - $"{m_Charges}\t{m_Inscription.IsNullOrDefault(" ")}"); // a bracelet of binding : ~1_val~ ~2_val~ - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (from.Alive && IsChildOf(from)) - { - BraceletOfBinding bound = Bound; - - list.Add(new BraceletEntry(Activate, 6170, bound != null)); - list.Add(new BraceletEntry(Search, 6171, bound != null)); - list.Add(new BraceletEntry(Bind, bound == null ? 6173 : 6174, true)); - list.Add(new BraceletEntry(Inscribe, 6175, true)); - } - } - - public override void OnDoubleClick(Mobile from) - { - BraceletOfBinding bound = Bound; - - if (Bound == null) - Bind(from); - else - Activate(from); - } - - public void Activate(Mobile from) - { - BraceletOfBinding bound = Bound; - - if (Deleted || bound == null) - return; - - if (!IsChildOf(from)) - { - from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - } - else if (m_Timer != null) - { - from.SendLocalizedMessage( - 1054013); // The bracelet is already attempting contact. You decide to wait a moment. - } - else - { - from.PlaySound(0xF9); - from.LocalOverheadMessage(MessageType.Regular, 0x5D, true, - "* You concentrate on the bracelet to summon its power *"); - - from.Frozen = true; - - m_Timer = new TransportTimer(this, from); - m_Timer.Start(); - } - } - - public void Search(Mobile from) - { - BraceletOfBinding bound = Bound; - - if (Deleted || bound == null) - return; - - if (!IsChildOf(from)) - from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - else - CheckUse(from, true); - } - - private bool CheckUse(Mobile from, bool successMessage) - { - BraceletOfBinding bound = Bound; - - if (bound == null) - return false; - - Mobile boundRoot = bound.RootParent as Mobile; - - if (Charges == 0) - { - from.SendLocalizedMessage( - 1054005); // The bracelet glows black. It must be charged before it can be used again. - return false; - } - - if (from.FindItemOnLayer(Layer.Bracelet) != this) - { - from.SendLocalizedMessage(1054004); // You must equip the bracelet in order to use its power. - return false; - } - - if (boundRoot?.NetState == null || boundRoot.FindItemOnLayer(Layer.Bracelet) != bound) - { - from.SendLocalizedMessage( - 1054006); // The bracelet emits a red glow. The bracelet's twin is not available for transport. - return false; - } - - if (!Core.AOS && from.Map != boundRoot.Map) - { - from.SendLocalizedMessage(1054014); // The bracelet glows black. The bracelet's target is on another facet. - return false; - } - - if (Sigil.ExistsOn(from)) - { - from.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. - return false; - } - - if (!SpellHelper.CheckTravel(from, TravelCheckType.RecallFrom)) return false; - if (!SpellHelper.CheckTravel(from, boundRoot.Map, boundRoot.Location, TravelCheckType.RecallTo)) return false; - if (boundRoot.Map == Map.Felucca && from is PlayerMobile mobile && mobile.Young) - { - mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young. - return false; - } - - if (from.Kills >= 5 && boundRoot.Map != Map.Felucca) - { - from.SendLocalizedMessage(1019004); // You are not allowed to travel there. - return false; - } - - if (from.Criminal) - { - from.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily. - return false; - } - - if (SpellHelper.CheckCombat(from)) - { - from.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle?? - return false; - } - - if (WeightOverloading.IsOverloaded(from)) - { - from.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move. - return false; - } - - if (from.Region.IsPartOf()) - { - from.SendLocalizedMessage(1114345, "", 0x35); // You'll need a better jailbreak plan than that! - return false; - } - - if (boundRoot.Region.IsPartOf()) - { - from.SendLocalizedMessage(1019004); // You are not allowed to travel there. - return false; - } - - if (successMessage) - from.SendLocalizedMessage(1054015); // The bracelet's twin is available for transport. - - return true; - } - - public void Bind(Mobile from) - { - if (Deleted) - return; - - if (!IsChildOf(from)) - { - from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - } - else - { - from.SendLocalizedMessage(1054001); // Target the bracelet of binding you wish to bind this bracelet to. - from.Target = new BindTarget(this); - } - } - - public void Inscribe(Mobile from) - { - if (Deleted) - return; - - if (!IsChildOf(from)) - { - from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - } - else - { - from.SendLocalizedMessage(1054009); // Enter the text to inscribe upon the bracelet : - from.Prompt = new InscribePrompt(this); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(1); // version - - writer.WriteEncodedInt(m_Recharges); - - writer.WriteEncodedInt(m_Charges); - writer.Write(m_Inscription); - writer.Write(Bound); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 1: - { - m_Recharges = reader.ReadEncodedInt(); - goto case 0; - } - case 0: - { - m_Charges = Math.Min(reader.ReadEncodedInt(), MaxCharges); - m_Inscription = reader.ReadString(); - Bound = (BraceletOfBinding)reader.ReadItem(); - break; - } - } - } - - private delegate void BraceletCallback(Mobile from); - - private class BraceletEntry : ContextMenuEntry - { - private readonly BraceletCallback m_Callback; - - public BraceletEntry(BraceletCallback callback, int number, bool enabled) : base(number) - { - m_Callback = callback; - - if (!enabled) - Flags |= CMEFlags.Disabled; - } - - public override void OnClick() - { - Mobile from = Owner.From; - - if (from.CheckAlive()) - m_Callback(from); - } - } - - private class TransportTimer : Timer - { - private readonly BraceletOfBinding m_Bracelet; - private readonly Mobile m_From; - - public TransportTimer(BraceletOfBinding bracelet, Mobile from) : base(TimeSpan.FromSeconds(2.0)) - { - m_Bracelet = bracelet; - m_From = from; - } - - protected override void OnTick() - { - m_Bracelet.m_Timer = null; - m_From.Frozen = false; - - if (m_Bracelet.Deleted || m_From.Deleted || - !m_Bracelet.CheckUse(m_From, false) || - !(m_Bracelet.Bound.RootParent is Mobile boundRoot)) - return; - - m_Bracelet.Charges--; - - BaseCreature.TeleportPets(m_From, boundRoot.Location, boundRoot.Map, true); - - m_From.PlaySound(0x1FC); - m_From.MoveToWorld(boundRoot.Location, boundRoot.Map); - m_From.PlaySound(0x1FC); - } - } - - private class BindTarget : Target - { - private readonly BraceletOfBinding m_Bracelet; - - public BindTarget(BraceletOfBinding bracelet) : base(-1, false, TargetFlags.None) => m_Bracelet = bracelet; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Bracelet.Deleted) - return; - - if (!m_Bracelet.IsChildOf(from)) + private BraceletOfBinding m_Bound; + private int m_Charges; + private string m_Inscription; + private int m_Recharges; + private TransportTimer m_Timer; + + [Constructible] + public BraceletOfBinding() : base(0x1086) { - from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - } - else if (targeted is BraceletOfBinding bindBracelet) - { - if (bindBracelet == m_Bracelet) - { - from.SendLocalizedMessage(1054012); // You cannot bind a bracelet of binding to itself! - } - else if (!bindBracelet.IsChildOf(from)) - { - from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - } - else - { - from.SendLocalizedMessage( - 1054003); // You bind the bracelet to its counterpart. The bracelets glow with power. - from.PlaySound(0x1FA); + Hue = 0x489; + Weight = 1.0; - m_Bracelet.Bound = bindBracelet; - } + m_Inscription = ""; } - else + + public BraceletOfBinding(Serial serial) : base(serial) { - from.SendLocalizedMessage(1054002); // You can only bind this bracelet to another bracelet of binding! } - } + + [CommandProperty(AccessLevel.GameMaster)] + public string Inscription + { + get => m_Inscription; + set + { + m_Inscription = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public BraceletOfBinding Bound + { + get + { + if (m_Bound?.Deleted == true) + m_Bound = null; + + return m_Bound; + } + set => m_Bound = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Charges + { + get => m_Charges; + set + { + m_Charges = Math.Clamp(value, 0, MaxCharges); + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Recharges + { + get => m_Recharges; + set + { + m_Recharges = Math.Clamp(value, 0, MaxRecharges); + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxCharges => 20; + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxRecharges => 255; + + public string TranslocationItemName => "bracelet of binding"; + + public override void AddNameProperty(ObjectPropertyList list) + { + list.Add( + 1054000, + $"{m_Charges}\t{m_Inscription.IsNullOrDefault(" ")}" + ); // a bracelet of binding : ~1_val~ ~2_val~ + } + + public override void OnSingleClick(Mobile from) + { + LabelTo( + from, + 1054000, + $"{m_Charges}\t{m_Inscription.IsNullOrDefault(" ")}" + ); // a bracelet of binding : ~1_val~ ~2_val~ + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (from.Alive && IsChildOf(from)) + { + var bound = Bound; + + list.Add(new BraceletEntry(Activate, 6170, bound != null)); + list.Add(new BraceletEntry(Search, 6171, bound != null)); + list.Add(new BraceletEntry(Bind, bound == null ? 6173 : 6174, true)); + list.Add(new BraceletEntry(Inscribe, 6175, true)); + } + } + + public override void OnDoubleClick(Mobile from) + { + var bound = Bound; + + if (Bound == null) + Bind(from); + else + Activate(from); + } + + public void Activate(Mobile from) + { + var bound = Bound; + + if (Deleted || bound == null) + return; + + if (!IsChildOf(from)) + { + from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. + } + else if (m_Timer != null) + { + from.SendLocalizedMessage( + 1054013 + ); // The bracelet is already attempting contact. You decide to wait a moment. + } + else + { + from.PlaySound(0xF9); + from.LocalOverheadMessage( + MessageType.Regular, + 0x5D, + true, + "* You concentrate on the bracelet to summon its power *" + ); + + from.Frozen = true; + + m_Timer = new TransportTimer(this, from); + m_Timer.Start(); + } + } + + public void Search(Mobile from) + { + var bound = Bound; + + if (Deleted || bound == null) + return; + + if (!IsChildOf(from)) + from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. + else + CheckUse(from, true); + } + + private bool CheckUse(Mobile from, bool successMessage) + { + var bound = Bound; + + if (bound == null) + return false; + + var boundRoot = bound.RootParent as Mobile; + + if (Charges == 0) + { + from.SendLocalizedMessage( + 1054005 + ); // The bracelet glows black. It must be charged before it can be used again. + return false; + } + + if (from.FindItemOnLayer(Layer.Bracelet) != this) + { + from.SendLocalizedMessage(1054004); // You must equip the bracelet in order to use its power. + return false; + } + + if (boundRoot?.NetState == null || boundRoot.FindItemOnLayer(Layer.Bracelet) != bound) + { + from.SendLocalizedMessage( + 1054006 + ); // The bracelet emits a red glow. The bracelet's twin is not available for transport. + return false; + } + + if (!Core.AOS && from.Map != boundRoot.Map) + { + from.SendLocalizedMessage(1054014); // The bracelet glows black. The bracelet's target is on another facet. + return false; + } + + if (Sigil.ExistsOn(from)) + { + from.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. + return false; + } + + if (!SpellHelper.CheckTravel(from, TravelCheckType.RecallFrom)) return false; + if (!SpellHelper.CheckTravel(from, boundRoot.Map, boundRoot.Location, TravelCheckType.RecallTo)) return false; + if (boundRoot.Map == Map.Felucca && from is PlayerMobile mobile && mobile.Young) + { + mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young. + return false; + } + + if (from.Kills >= 5 && boundRoot.Map != Map.Felucca) + { + from.SendLocalizedMessage(1019004); // You are not allowed to travel there. + return false; + } + + if (from.Criminal) + { + from.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily. + return false; + } + + if (SpellHelper.CheckCombat(from)) + { + from.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle?? + return false; + } + + if (WeightOverloading.IsOverloaded(from)) + { + from.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move. + return false; + } + + if (from.Region.IsPartOf()) + { + from.SendLocalizedMessage(1114345, "", 0x35); // You'll need a better jailbreak plan than that! + return false; + } + + if (boundRoot.Region.IsPartOf()) + { + from.SendLocalizedMessage(1019004); // You are not allowed to travel there. + return false; + } + + if (successMessage) + from.SendLocalizedMessage(1054015); // The bracelet's twin is available for transport. + + return true; + } + + public void Bind(Mobile from) + { + if (Deleted) + return; + + if (!IsChildOf(from)) + { + from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. + } + else + { + from.SendLocalizedMessage(1054001); // Target the bracelet of binding you wish to bind this bracelet to. + from.Target = new BindTarget(this); + } + } + + public void Inscribe(Mobile from) + { + if (Deleted) + return; + + if (!IsChildOf(from)) + { + from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. + } + else + { + from.SendLocalizedMessage(1054009); // Enter the text to inscribe upon the bracelet : + from.Prompt = new InscribePrompt(this); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(1); // version + + writer.WriteEncodedInt(m_Recharges); + + writer.WriteEncodedInt(m_Charges); + writer.Write(m_Inscription); + writer.Write(Bound); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 1: + { + m_Recharges = reader.ReadEncodedInt(); + goto case 0; + } + case 0: + { + m_Charges = Math.Min(reader.ReadEncodedInt(), MaxCharges); + m_Inscription = reader.ReadString(); + Bound = (BraceletOfBinding)reader.ReadItem(); + break; + } + } + } + + private delegate void BraceletCallback(Mobile from); + + private class BraceletEntry : ContextMenuEntry + { + private readonly BraceletCallback m_Callback; + + public BraceletEntry(BraceletCallback callback, int number, bool enabled) : base(number) + { + m_Callback = callback; + + if (!enabled) + Flags |= CMEFlags.Disabled; + } + + public override void OnClick() + { + var from = Owner.From; + + if (from.CheckAlive()) + m_Callback(from); + } + } + + private class TransportTimer : Timer + { + private readonly BraceletOfBinding m_Bracelet; + private readonly Mobile m_From; + + public TransportTimer(BraceletOfBinding bracelet, Mobile from) : base(TimeSpan.FromSeconds(2.0)) + { + m_Bracelet = bracelet; + m_From = from; + } + + protected override void OnTick() + { + m_Bracelet.m_Timer = null; + m_From.Frozen = false; + + if (m_Bracelet.Deleted || m_From.Deleted || + !m_Bracelet.CheckUse(m_From, false) || + !(m_Bracelet.Bound.RootParent is Mobile boundRoot)) + return; + + m_Bracelet.Charges--; + + BaseCreature.TeleportPets(m_From, boundRoot.Location, boundRoot.Map, true); + + m_From.PlaySound(0x1FC); + m_From.MoveToWorld(boundRoot.Location, boundRoot.Map); + m_From.PlaySound(0x1FC); + } + } + + private class BindTarget : Target + { + private readonly BraceletOfBinding m_Bracelet; + + public BindTarget(BraceletOfBinding bracelet) : base(-1, false, TargetFlags.None) => m_Bracelet = bracelet; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Bracelet.Deleted) + return; + + if (!m_Bracelet.IsChildOf(from)) + { + from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. + } + else if (targeted is BraceletOfBinding bindBracelet) + { + if (bindBracelet == m_Bracelet) + { + from.SendLocalizedMessage(1054012); // You cannot bind a bracelet of binding to itself! + } + else if (!bindBracelet.IsChildOf(from)) + { + from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. + } + else + { + from.SendLocalizedMessage( + 1054003 + ); // You bind the bracelet to its counterpart. The bracelets glow with power. + from.PlaySound(0x1FA); + + m_Bracelet.Bound = bindBracelet; + } + } + else + { + from.SendLocalizedMessage(1054002); // You can only bind this bracelet to another bracelet of binding! + } + } + } + + private class InscribePrompt : Prompt + { + private readonly BraceletOfBinding m_Bracelet; + + public InscribePrompt(BraceletOfBinding bracelet) => m_Bracelet = bracelet; + + public override void OnResponse(Mobile from, string text) + { + if (m_Bracelet.Deleted) + return; + + if (!m_Bracelet.IsChildOf(from)) + { + from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. + } + else + { + from.SendLocalizedMessage(1054011); // You mark the bracelet with your inscription. + m_Bracelet.Inscription = text; + } + } + + public override void OnCancel(Mobile from) + { + from.SendLocalizedMessage(1054010); // You decide not to inscribe the bracelet at this time. + } + } } - - private class InscribePrompt : Prompt - { - private readonly BraceletOfBinding m_Bracelet; - - public InscribePrompt(BraceletOfBinding bracelet) => m_Bracelet = bracelet; - - public override void OnResponse(Mobile from, string text) - { - if (m_Bracelet.Deleted) - return; - - if (!m_Bracelet.IsChildOf(from)) - { - from.SendLocalizedMessage(1042664); // You must have the object in your backpack to use it. - } - else - { - from.SendLocalizedMessage(1054011); // You mark the bracelet with your inscription. - m_Bracelet.Inscription = text; - } - } - - public override void OnCancel(Mobile from) - { - from.SendLocalizedMessage(1054010); // You decide not to inscribe the bracelet at this time. - } - } - } } diff --git a/Projects/UOContent/Items/Special/Solen Items/MessageHelper.cs b/Projects/UOContent/Items/Special/Solen Items/MessageHelper.cs index 15c7f22b2..e2efcebe5 100644 --- a/Projects/UOContent/Items/Special/Solen Items/MessageHelper.cs +++ b/Projects/UOContent/Items/Special/Solen Items/MessageHelper.cs @@ -2,21 +2,21 @@ using Server.Network; namespace Server { - public class MessageHelper - { - public static void SendLocalizedMessageTo(Item from, Mobile to, int number, int hue) + public class MessageHelper { - SendLocalizedMessageTo(from, to, number, "", hue); - } + public static void SendLocalizedMessageTo(Item from, Mobile to, int number, int hue) + { + SendLocalizedMessageTo(from, to, number, "", hue); + } - public static void SendLocalizedMessageTo(Item from, Mobile to, int number, string args, int hue) - { - to.Send(new MessageLocalized(from.Serial, from.ItemID, MessageType.Regular, hue, 3, number, "", args)); - } + public static void SendLocalizedMessageTo(Item from, Mobile to, int number, string args, int hue) + { + to.Send(new MessageLocalized(from.Serial, from.ItemID, MessageType.Regular, hue, 3, number, "", args)); + } - public static void SendMessageTo(Item from, Mobile to, string text, int hue) - { - to.Send(new UnicodeMessage(from.Serial, from.ItemID, MessageType.Regular, hue, 3, "ENU", "", text)); + public static void SendMessageTo(Item from, Mobile to, string text, int hue) + { + to.Send(new UnicodeMessage(from.Serial, from.ItemID, MessageType.Regular, hue, 3, "ENU", "", text)); + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Solen Items/PowderOfTranslocation.cs b/Projects/UOContent/Items/Special/Solen Items/PowderOfTranslocation.cs index 199063bef..da8d399af 100644 --- a/Projects/UOContent/Items/Special/Solen Items/PowderOfTranslocation.cs +++ b/Projects/UOContent/Items/Special/Solen Items/PowderOfTranslocation.cs @@ -3,105 +3,117 @@ using Server.Targeting; namespace Server.Items { - public interface TranslocationItem - { - int Charges { get; set; } - int Recharges { get; set; } - int MaxCharges { get; } - int MaxRecharges { get; } - string TranslocationItemName { get; } - } - - public class PowderOfTranslocation : Item - { - [Constructible] - public PowderOfTranslocation(int amount = 1) : base(0x26B8) + public interface TranslocationItem { - Stackable = true; - Weight = 0.1; - Amount = amount; + int Charges { get; set; } + int Recharges { get; set; } + int MaxCharges { get; } + int MaxRecharges { get; } + string TranslocationItemName { get; } } - public PowderOfTranslocation(Serial serial) : base(serial) + public class PowderOfTranslocation : Item { - } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(GetWorldLocation(), 2)) - from.Target = new InternalTarget(this); - else - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - private class InternalTarget : Target - { - private readonly PowderOfTranslocation m_Powder; - - public InternalTarget(PowderOfTranslocation powder) : base(-1, false, TargetFlags.None) => m_Powder = powder; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Powder.Deleted) - return; - - if (!from.InRange(m_Powder.GetWorldLocation(), 2)) + [Constructible] + public PowderOfTranslocation(int amount = 1) : base(0x26B8) { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + Stackable = true; + Weight = 0.1; + Amount = amount; } - else if (targeted is TranslocationItem transItem) - { - if (transItem.Charges >= transItem.MaxCharges) - { - MessageHelper.SendLocalizedMessageTo(m_Powder, from, 1054137, - 0x59); // This item cannot absorb any more powder of translocation. - } - else if (transItem.Recharges >= transItem.MaxRecharges) - { - MessageHelper.SendLocalizedMessageTo(m_Powder, from, 1054138, - 0x59); // This item has been oversaturated with powder of translocation and can no longer be recharged. - } - else - { - if (transItem.Charges + m_Powder.Amount > transItem.MaxCharges) - { - int delta = transItem.MaxCharges - transItem.Charges; - m_Powder.Amount -= delta; - transItem.Charges = transItem.MaxCharges; - transItem.Recharges += delta; - } + public PowderOfTranslocation(Serial serial) : base(serial) + { + } + + public override void OnDoubleClick(Mobile from) + { + if (from.InRange(GetWorldLocation(), 2)) + from.Target = new InternalTarget(this); else - { - transItem.Charges += m_Powder.Amount; - transItem.Recharges += m_Powder.Amount; - m_Powder.Delete(); - } + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } - if (transItem is Item item) - MessageHelper.SendLocalizedMessageTo(item, from, 1054139, transItem.TranslocationItemName, 0x43); - } - } - else + public override void Serialize(IGenericWriter writer) { - MessageHelper.SendLocalizedMessageTo(m_Powder, from, 1054140, - 0x59); // Powder of translocation has no effect on this item. + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + } + + private class InternalTarget : Target + { + private readonly PowderOfTranslocation m_Powder; + + public InternalTarget(PowderOfTranslocation powder) : base(-1, false, TargetFlags.None) => m_Powder = powder; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Powder.Deleted) + return; + + if (!from.InRange(m_Powder.GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + else if (targeted is TranslocationItem transItem) + { + if (transItem.Charges >= transItem.MaxCharges) + { + MessageHelper.SendLocalizedMessageTo( + m_Powder, + from, + 1054137, + 0x59 + ); // This item cannot absorb any more powder of translocation. + } + else if (transItem.Recharges >= transItem.MaxRecharges) + { + MessageHelper.SendLocalizedMessageTo( + m_Powder, + from, + 1054138, + 0x59 + ); // This item has been oversaturated with powder of translocation and can no longer be recharged. + } + else + { + if (transItem.Charges + m_Powder.Amount > transItem.MaxCharges) + { + var delta = transItem.MaxCharges - transItem.Charges; + + m_Powder.Amount -= delta; + transItem.Charges = transItem.MaxCharges; + transItem.Recharges += delta; + } + else + { + transItem.Charges += m_Powder.Amount; + transItem.Recharges += m_Powder.Amount; + m_Powder.Delete(); + } + + if (transItem is Item item) + MessageHelper.SendLocalizedMessageTo(item, from, 1054139, transItem.TranslocationItemName, 0x43); + } + } + else + { + MessageHelper.SendLocalizedMessageTo( + m_Powder, + from, + 1054140, + 0x59 + ); // Powder of translocation has no effect on this item. + } + } } - } } - } } diff --git a/Projects/UOContent/Items/Special/Solen Items/ZoogiFungus.cs b/Projects/UOContent/Items/Special/Solen Items/ZoogiFungus.cs index cad361e8e..ebaaf2d1e 100644 --- a/Projects/UOContent/Items/Special/Solen Items/ZoogiFungus.cs +++ b/Projects/UOContent/Items/Special/Solen Items/ZoogiFungus.cs @@ -1,34 +1,34 @@ namespace Server.Items { - public class ZoogiFungus : Item, ICommodity - { - [Constructible] - public ZoogiFungus(int amount = 1) : base(0x26B7) + public class ZoogiFungus : Item, ICommodity { - Stackable = true; - Weight = 0.1; - Amount = amount; + [Constructible] + public ZoogiFungus(int amount = 1) : base(0x26B7) + { + Stackable = true; + Weight = 0.1; + Amount = amount; + } + + public ZoogiFungus(Serial serial) : base(serial) + { + } + + int ICommodity.DescriptionNumber => LabelNumber; + bool ICommodity.IsDeedable => Core.ML; + + 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(); + } } - - public ZoogiFungus(Serial serial) : base(serial) - { - } - - int ICommodity.DescriptionNumber => LabelNumber; - bool ICommodity.IsDeedable => Core.ML; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/SoulStone.cs b/Projects/UOContent/Items/Special/SoulStone.cs index 19520dd3e..de14a1c60 100644 --- a/Projects/UOContent/Items/Special/SoulStone.cs +++ b/Projects/UOContent/Items/Special/SoulStone.cs @@ -9,982 +9,1058 @@ using Server.Network; namespace Server.Items { - public class SoulStone : Item, ISecurable - { - private int m_ActiveItemID; - private int m_InactiveItemID; - - private string m_LastUserName; - private DateTime m_NextUse; // TODO: unused, it's here not to break serialize/deserialize - - private SkillName m_Skill; - private double m_SkillValue; - - [Constructible] - public SoulStone(string account = null, int inactiveItemID = 0x2A93, int activeItemID = 0x2A94) : base(inactiveItemID) + public class SoulStone : Item, ISecurable { - Light = LightType.Circle300; - LootType = LootType.Blessed; + private int m_ActiveItemID; + private int m_InactiveItemID; - m_InactiveItemID = inactiveItemID; - m_ActiveItemID = activeItemID; + private string m_LastUserName; + private DateTime m_NextUse; // TODO: unused, it's here not to break serialize/deserialize - Account = account; - } + private SkillName m_Skill; + private double m_SkillValue; - public SoulStone(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1030899; // soulstone - - [CommandProperty(AccessLevel.GameMaster)] - public virtual int ActiveItemID - { - get => m_ActiveItemID; - set - { - m_ActiveItemID = value; - - if (!IsEmpty) - ItemID = m_ActiveItemID; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public virtual int InactiveItemID - { - get => m_InactiveItemID; - set - { - m_InactiveItemID = value; - - if (IsEmpty) - ItemID = m_InactiveItemID; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public string Account { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public string LastUserName - { - get => m_LastUserName; - set - { - m_LastUserName = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public SkillName Skill - { - get => m_Skill; - set - { - m_Skill = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public double SkillValue - { - get => m_SkillValue; - set - { - m_SkillValue = value; - - if (!IsEmpty) - ItemID = m_ActiveItemID; - else - ItemID = m_InactiveItemID; - - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsEmpty => m_SkillValue <= 0.0; - - [CommandProperty(AccessLevel.GameMaster)] - public SecureLevel Level { get; set; } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (!IsEmpty) - list.Add(1070721, "#{0}\t{1:0.0}", AosSkillBonuses.GetLabel(Skill), - SkillValue); // Skill stored: ~1_skillname~ ~2_skillamount~ - - list.Add(1041602, "{0}", LastUserName ?? $"#{1074235}"); // Owner: ~1_val~ - } - - private static bool CheckCombat(Mobile m, TimeSpan time) - { - for (int i = 0; i < m.Aggressed.Count; ++i) - { - AggressorInfo info = m.Aggressed[i]; - - if (DateTime.UtcNow - info.LastCombatTime < time) - return true; - } - - return false; - } - - protected virtual bool CheckUse(Mobile from) - { - // DateTime now = DateTime.UtcNow; - - PlayerMobile pm = from as PlayerMobile; - - if (Deleted || !IsAccessibleTo(from)) return false; - - if (from.Map != Map || !from.InRange(GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - return false; - } - - if (Account != null && (!(from.Account is Account) || from.Account.Username != Account)) - { - from.SendLocalizedMessage( - 1070714); // This is an Account Bound Soulstone, and your character is not bound to it. You cannot use this Soulstone. - return false; - } - - if (CheckCombat(from, TimeSpan.FromMinutes(2.0))) - { - from.SendLocalizedMessage( - 1070727); // You must wait two minutes after engaging in combat before you can use a Soulstone. - return false; - } - - if (from.Criminal) - { - from.SendLocalizedMessage( - 1070728); // You must wait two minutes after committing a criminal act before you can use a Soulstone. - return false; - } - - if (from.Region.GetLogoutDelay(from) > TimeSpan.Zero) - { - from.SendLocalizedMessage( - 1070729); // In order to use your Soulstone, you must be in a safe log-out location. - return false; - } - - if (!from.Alive) - { - from.SendLocalizedMessage(1070730); // You may not use a Soulstone while your character is dead. - return false; - } - - if (Sigil.ExistsOn(from)) - { - from.SendLocalizedMessage( - 1070731); // You may not use a Soulstone while your character has a faction town sigil. - return false; - } - - if (from.Spell?.IsCasting == true) - { - from.SendLocalizedMessage(1070733); // You may not use a Soulstone while your character is casting a spell. - return false; - } - - if (from.Poisoned) - { - from.SendLocalizedMessage(1070734); // You may not use a Soulstone while your character is poisoned. - return false; - } - - if (from.Paralyzed) - { - from.SendLocalizedMessage(1070735); // You may not use a Soulstone while your character is paralyzed. - return false; - } - - if (pm.AcceleratedStart > DateTime.UtcNow) - { - from.SendLocalizedMessage( - 1078115); // You may not use a soulstone while your character is under the effects of a Scroll of Alacrity. - return false; - } - - return true; - } - - public override void OnDoubleClick(Mobile from) - { - if (!CheckUse(from)) - return; - - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - - if (IsEmpty) - from.SendGump(new SelectSkillGump(this, from)); - else - from.SendGump(new ConfirmTransferGump(this, from)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(3); // version - - // version 3 - writer.Write(m_LastUserName); - - // version 2 - writer.Write((int)Level); - - writer.Write(m_ActiveItemID); - writer.Write(m_InactiveItemID); - - writer.Write(Account); - writer.Write(m_NextUse); // TODO: delete it in a harmless way - - writer.WriteEncodedInt((int)m_Skill); - writer.Write(m_SkillValue); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 3: - { - m_LastUserName = reader.ReadString(); - goto case 2; - } - case 2: - { - Level = (SecureLevel)reader.ReadInt(); - goto case 1; - } - case 1: - { - m_ActiveItemID = reader.ReadInt(); - m_InactiveItemID = reader.ReadInt(); - - goto case 0; - } - case 0: - { - Account = reader.ReadString(); - m_NextUse = reader.ReadDateTime(); // TODO: delete it in a harmless way - - m_Skill = (SkillName)reader.ReadEncodedInt(); - m_SkillValue = reader.ReadDouble(); - break; - } - } - - if (version == 0) - { - m_ActiveItemID = 0x2A94; - m_InactiveItemID = 0x2A93; - } - } - - private class SelectSkillGump : Gump - { - private readonly SoulStone m_Stone; - - public SelectSkillGump(SoulStone stone, Mobile from) : base(50, 50) - { - m_Stone = stone; - - AddPage(0); - - AddBackground(0, 0, 520, 440, 0x13BE); - - AddImageTiled(10, 10, 500, 20, 0xA40); - AddImageTiled(10, 40, 500, 360, 0xA40); - AddImageTiled(10, 410, 500, 20, 0xA40); - - AddAlphaRegion(10, 10, 500, 420); - - AddHtmlLocalized(10, 12, 500, 20, 1061087, 0x7FFF); // Which skill do you wish to transfer to the Soulstone? - - AddButton(10, 410, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(45, 412, 450, 20, 1060051, 0x7FFF); // CANCEL - - for (int i = 0, n = 0; i < from.Skills.Length; i++) + [Constructible] + public SoulStone(string account = null, int inactiveItemID = 0x2A93, int activeItemID = 0x2A94) : base( + inactiveItemID + ) { - Skill skill = from.Skills[i]; + Light = LightType.Circle300; + LootType = LootType.Blessed; - if (skill.Base > 0.0) - { - int p = n % 30; + m_InactiveItemID = inactiveItemID; + m_ActiveItemID = activeItemID; - if (p == 0) + Account = account; + } + + public SoulStone(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1030899; // soulstone + + [CommandProperty(AccessLevel.GameMaster)] + public virtual int ActiveItemID + { + get => m_ActiveItemID; + set { - int page = n / 30; + m_ActiveItemID = value; - if (page > 0) - { - AddButton(260, 380, 0xFA5, 0xFA6, 0, GumpButtonType.Page, page + 1); - AddHtmlLocalized(305, 382, 200, 20, 1011066, 0x7FFF); // Next page - } + if (!IsEmpty) + ItemID = m_ActiveItemID; + } + } - AddPage(page + 1); + [CommandProperty(AccessLevel.GameMaster)] + public virtual int InactiveItemID + { + get => m_InactiveItemID; + set + { + m_InactiveItemID = value; - if (page > 0) - { - AddButton(10, 380, 0xFAE, 0xFAF, 0, GumpButtonType.Page, page); - AddHtmlLocalized(55, 382, 200, 20, 1011067, 0x7FFF); // Previous page - } + if (IsEmpty) + ItemID = m_InactiveItemID; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public string Account { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public string LastUserName + { + get => m_LastUserName; + set + { + m_LastUserName = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public SkillName Skill + { + get => m_Skill; + set + { + m_Skill = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public double SkillValue + { + get => m_SkillValue; + set + { + m_SkillValue = value; + + if (!IsEmpty) + ItemID = m_ActiveItemID; + else + ItemID = m_InactiveItemID; + + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsEmpty => m_SkillValue <= 0.0; + + [CommandProperty(AccessLevel.GameMaster)] + public SecureLevel Level { get; set; } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (!IsEmpty) + list.Add( + 1070721, + "#{0}\t{1:0.0}", + AosSkillBonuses.GetLabel(Skill), + SkillValue + ); // Skill stored: ~1_skillname~ ~2_skillamount~ + + list.Add(1041602, "{0}", LastUserName ?? $"#{1074235}"); // Owner: ~1_val~ + } + + private static bool CheckCombat(Mobile m, TimeSpan time) + { + for (var i = 0; i < m.Aggressed.Count; ++i) + { + var info = m.Aggressed[i]; + + if (DateTime.UtcNow - info.LastCombatTime < time) + return true; } - int x = p % 2 == 0 ? 10 : 260; - int y = p / 2 * 20 + 40; - - AddButton(x, y, 0xFA5, 0xFA6, i + 1); - AddHtmlLocalized(x + 45, y + 2, 200, 20, AosSkillBonuses.GetLabel(skill.SkillName), 0x7FFF); - - n++; - } + return false; } - } - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 0 || !m_Stone.IsEmpty) - return; - - Mobile from = sender.Mobile; - - int iSkill = info.ButtonID - 1; - if (iSkill < 0 || iSkill >= from.Skills.Length) - return; - - Skill skill = from.Skills[iSkill]; - if (skill.Base <= 0.0) - return; - - if (!m_Stone.CheckUse(from)) - return; - - from.SendGump(new ConfirmSkillGump(m_Stone, skill)); - } - } - - private class ConfirmSkillGump : Gump - { - private readonly Skill m_Skill; - private readonly SoulStone m_Stone; - - public ConfirmSkillGump(SoulStone stone, Skill skill) : base(50, 50) - { - m_Stone = stone; - m_Skill = skill; - - AddBackground(0, 0, 520, 440, 0x13BE); - - AddImageTiled(10, 10, 500, 20, 0xA40); - AddImageTiled(10, 40, 500, 360, 0xA40); - AddImageTiled(10, 410, 500, 20, 0xA40); - - AddAlphaRegion(10, 10, 500, 420); - - AddHtmlLocalized(10, 12, 500, 20, 1070709, 0x7FFF); //
Confirm Soulstone Transfer
- - /*
Soulstone

- * You are using a Soulstone. This powerful artifact allows you to remove skill points - * from your character and store them in the stone for later retrieval. In order to use - * the stone, you must make sure your Skill Lock for the indicated skill is pointed downward. - * Click the "Skills" button on your Paperdoll to access the Skill List, and double-check - * your skill lock.

- * - * Once you activate the stone, all skill points in the indicated skill will be removed from - * your character. These skill points can later be retrieved. IMPORTANT: When retrieving - * skill points from a Soulstone, the Soulstone WILL REPLACE any existing skill points - * already on your character!

- * - * This is an Account Bound Soulstone. Skill pointsstored inside can be retrieved by any - * character on the same account as the character who placed them into the stone. - */ - AddHtmlLocalized(10, 42, 500, 110, 1061067, 0x7FFF, false, true); - - AddHtmlLocalized(10, 200, 390, 20, 1062297, 0x7FFF); // Skill Chosen: - AddHtmlLocalized(210, 200, 390, 20, AosSkillBonuses.GetLabel(skill.SkillName), 0x7FFF); - - AddHtmlLocalized(10, 220, 390, 20, 1062298, 0x7FFF); // Current Value: - AddLabel(210, 220, 0x481, skill.Base.ToString("0.0")); - - AddHtmlLocalized(10, 240, 390, 20, 1062299, 0x7FFF); // Current Cap: - AddLabel(210, 240, 0x481, skill.Cap.ToString("0.0")); - - AddHtmlLocalized(10, 260, 390, 20, 1062300, 0x7FFF); // New Value: - AddLabel(210, 260, 0x481, "0.0"); - - AddButton(10, 360, 0xFA5, 0xFA6, 2); - AddHtmlLocalized(45, 362, 450, 20, 1070720, 0x7FFF); // Activate the stone. I am ready to transfer the skill points to it. - - AddButton(10, 380, 0xFA5, 0xFA6, 1); - AddHtmlLocalized(45, 382, 450, 20, 1062279, 0x7FFF); // No, let me make another selection. - - AddButton(10, 410, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(45, 412, 450, 20, 1060051, 0x7FFF); // CANCEL - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 0 || !m_Stone.IsEmpty) - return; - - Mobile from = sender.Mobile; - - if (!m_Stone.CheckUse(from)) - return; - - if (info.ButtonID == 1) // Is asking for another selection + protected virtual bool CheckUse(Mobile from) { - from.SendGump(new SelectSkillGump(m_Stone, from)); - return; - } + // DateTime now = DateTime.UtcNow; - if (m_Skill.Base <= 0.0) - return; + var pm = from as PlayerMobile; - if (m_Skill.Lock != SkillLock.Down) - { - //
Unable to Transfer Selected Skill to Soulstone
+ if (Deleted || !IsAccessibleTo(from)) return false; - /* You cannot transfer the selected skill to the Soulstone at this time. The selected - * skill may be locked or set to raise in your skill menu. Click on "Skills" in your - * paperdoll menu to check your raise/locked/lower settings and your total skills. - * Make any needed adjustments, then click "Continue". If you do not wish to transfer - * the selected skill at this time, click "Cancel". - */ - - from.SendGump(new ErrorGump(m_Stone, 1070710, 1070711)); - return; - } - - m_Stone.Skill = m_Skill.SkillName; - m_Stone.SkillValue = m_Skill.Base; - - m_Skill.Base = 0.0; - - from.SendLocalizedMessage( - 1070712); // You have successfully transferred your skill points into the Soulstone. - - m_Stone.LastUserName = from.Name; - - Effects.SendLocationParticles(EffectItem.Create(from.Location, from.Map, EffectItem.DefaultDuration), 0, 0, - 0, 0, 0, 5060, 0); - Effects.PlaySound(from.Location, from.Map, 0x243); - - Effects.SendMovingParticles( - new Entity(Server.Serial.Zero, new Point3D(from.X - 6, from.Y - 6, from.Z + 15), from.Map), from, 0x36D4, - 7, 0, false, true, 0x497, 0, 9502, 1, 0, (EffectLayer)255, 0x100); - - Effects.SendTargetParticles(from, 0x375A, 35, 90, 0x00, 0x00, 9502, (EffectLayer)255, 0x100); - } - } - - private class ConfirmTransferGump : Gump - { - private readonly SoulStone m_Stone; - - public ConfirmTransferGump(SoulStone stone, Mobile from) : base(50, 50) - { - m_Stone = stone; - - AddBackground(0, 0, 520, 440, 0x13BE); - - AddImageTiled(10, 10, 500, 20, 0xA40); - AddImageTiled(10, 40, 500, 360, 0xA40); - AddImageTiled(10, 410, 500, 20, 0xA40); - - AddAlphaRegion(10, 10, 500, 420); - - AddHtmlLocalized(10, 12, 500, 20, 1070709, 0x7FFF); //
Confirm Soulstone Transfer
- - /*
Soulstone

- * You are using a Soulstone. This powerful artifact allows you to remove skill points - * from your character and store them in the stone for later retrieval. In order to use - * the stone, you must make sure your Skill Lock for the indicated skill is pointed downward. - * Click the "Skills" button on your Paperdoll to access the Skill List, and double-check - * your skill lock.

- * - * Once you activate the stone, all skill points in the indicated skill will be removed from - * your character. These skill points can later be retrieved. IMPORTANT: When retrieving - * skill points from a Soulstone, the Soulstone WILL REPLACE any existing skill points - * already on your character!

- * - * This is an Account Bound Soulstone. Skill pointsstored inside can be retrieved by any - * character on the same account as the character who placed them into the stone. - */ - AddHtmlLocalized(10, 42, 500, 110, 1061067, 0x7FFF, false, true); - - AddHtmlLocalized(10, 200, 390, 20, 1070718, 0x7FFF); // Skill Stored: - AddHtmlLocalized(210, 200, 390, 20, AosSkillBonuses.GetLabel(stone.Skill), 0x7FFF); - - Skill fromSkill = from.Skills[stone.Skill]; - - AddHtmlLocalized(10, 220, 390, 20, 1062298, 0x7FFF); // Current Value: - AddLabel(210, 220, 0x481, fromSkill.Base.ToString("0.0")); - - AddHtmlLocalized(10, 240, 390, 20, 1062299, 0x7FFF); // Current Cap: - AddLabel(210, 240, 0x481, fromSkill.Cap.ToString("0.0")); - - AddHtmlLocalized(10, 260, 390, 20, 1062300, 0x7FFF); // New Value: - AddLabel(210, 260, 0x481, stone.SkillValue.ToString("0.0")); - - AddButton(10, 360, 0xFA5, 0xFA6, 2); - AddHtmlLocalized(45, 362, 450, 20, 1070719, 0x7FFF); // Activate the stone. I am ready to retrieve the skill points from it. - - AddButton(10, 380, 0xFA5, 0xFA6, 1); - AddHtmlLocalized(45, 382, 450, 20, 1070723, 0x7FFF); // Remove all skill points from this stone and DO NOT absorb them. - - AddButton(10, 410, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(45, 412, 450, 20, 1060051, 0x7FFF); // CANCEL - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 0 || m_Stone.IsEmpty) - return; - - Mobile from = sender.Mobile; - - if (!m_Stone.CheckUse(from)) - return; - - if (info.ButtonID == 1) // Remove skill points - { - from.SendGump(new ConfirmRemovalGump(m_Stone)); - return; - } - - SkillName skill = m_Stone.Skill; - double skillValue = m_Stone.SkillValue; - Skill fromSkill = from.Skills[m_Stone.Skill]; - - /* If we have, say, 88.4 in our skill and the stone holds 100, we need - * 11.6 free points. Also, if we're below our skillcap by, say, 8.2 points, - * we only need 11.6 - 8.2 = 3.4 points. - */ - int requiredAmount = (int)(skillValue * 10) - fromSkill.BaseFixedPoint - (from.SkillsCap - from.SkillsTotal); - - bool cannotAbsorb = false; - - if (fromSkill.Lock != SkillLock.Up) - { - cannotAbsorb = true; - } - else if (requiredAmount > 0) - { - int available = 0; - - for (int i = 0; i < from.Skills.Length; ++i) - { - if (from.Skills[i].Lock != SkillLock.Down) - continue; - - available += from.Skills[i].BaseFixedPoint; - } - - if (requiredAmount > available) - cannotAbsorb = true; - } - - if (cannotAbsorb) - { - //
Unable to Absorb Selected Skill from Soulstone
- - /* You cannot absorb the selected skill from the Soulstone at this time. The selected - * skill may be locked or set to lower in your skill menu. You may also be at your - * total skill cap. Click on "Skills" in your paperdoll menu to check your - * raise/locked/lower settings and your total skills. Make any needed adjustments, - * then click "Continue". If you do not wish to transfer the selected skill at this - * time, click "Cancel". - */ - - from.SendGump(new ErrorGump(m_Stone, 1070717, 1070716)); - return; - } - - if (skillValue > fromSkill.Cap) - { - //
Unable to Absorb Selected Skill from Soulstone
- - /* The amount of skill stored in this stone exceeds your individual skill cap for - * that skill. In order to retrieve the skill points stored in this stone, you must - * obtain a Power Scroll of the appropriate type and level in order to increase your - * skill cap. You cannot currently retrieve the skill points stored in this stone. - */ - - from.SendGump(new ErrorGump(m_Stone, 1070717, 1070715)); - return; - } - - if (fromSkill.Base >= skillValue) - { - //
Unable to Absorb Selected Skill from Soulstone
- - /* You cannot transfer the selected skill to the Soulstone at this time. The selected - * skill has a skill level higher than what is stored in the Soulstone. - */ - - // Wrong message?! - - from.SendGump(new ErrorGump(m_Stone, 1070717, 1070802)); - return; - } - - PlayerMobile pm = from as PlayerMobile; - if (pm.AcceleratedStart > DateTime.UtcNow) - { - //
Unable to Absorb Selected Skill from Soulstone
- - /*You may not use a soulstone while your character is under the effects of a Scroll of Alacrity.*/ - - // Wrong message?! - - from.SendGump(new ErrorGump(m_Stone, 1070717, 1078115)); - return; - } - - if (requiredAmount > 0) - for (int i = 0; i < from.Skills.Length; ++i) - { - if (from.Skills[i].Lock != SkillLock.Down) - continue; - - if (requiredAmount >= from.Skills[i].BaseFixedPoint) + if (from.Map != Map || !from.InRange(GetWorldLocation(), 2)) { - requiredAmount -= from.Skills[i].BaseFixedPoint; - from.Skills[i].Base = 0.0; + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return false; } + + if (Account != null && (!(from.Account is Account) || from.Account.Username != Account)) + { + from.SendLocalizedMessage( + 1070714 + ); // This is an Account Bound Soulstone, and your character is not bound to it. You cannot use this Soulstone. + return false; + } + + if (CheckCombat(from, TimeSpan.FromMinutes(2.0))) + { + from.SendLocalizedMessage( + 1070727 + ); // You must wait two minutes after engaging in combat before you can use a Soulstone. + return false; + } + + if (from.Criminal) + { + from.SendLocalizedMessage( + 1070728 + ); // You must wait two minutes after committing a criminal act before you can use a Soulstone. + return false; + } + + if (from.Region.GetLogoutDelay(from) > TimeSpan.Zero) + { + from.SendLocalizedMessage( + 1070729 + ); // In order to use your Soulstone, you must be in a safe log-out location. + return false; + } + + if (!from.Alive) + { + from.SendLocalizedMessage(1070730); // You may not use a Soulstone while your character is dead. + return false; + } + + if (Sigil.ExistsOn(from)) + { + from.SendLocalizedMessage( + 1070731 + ); // You may not use a Soulstone while your character has a faction town sigil. + return false; + } + + if (from.Spell?.IsCasting == true) + { + from.SendLocalizedMessage(1070733); // You may not use a Soulstone while your character is casting a spell. + return false; + } + + if (from.Poisoned) + { + from.SendLocalizedMessage(1070734); // You may not use a Soulstone while your character is poisoned. + return false; + } + + if (from.Paralyzed) + { + from.SendLocalizedMessage(1070735); // You may not use a Soulstone while your character is paralyzed. + return false; + } + + if (pm.AcceleratedStart > DateTime.UtcNow) + { + from.SendLocalizedMessage( + 1078115 + ); // You may not use a soulstone while your character is under the effects of a Scroll of Alacrity. + return false; + } + + return true; + } + + public override void OnDoubleClick(Mobile from) + { + if (!CheckUse(from)) + return; + + from.CloseGump(); + from.CloseGump(); + from.CloseGump(); + from.CloseGump(); + from.CloseGump(); + + if (IsEmpty) + from.SendGump(new SelectSkillGump(this, from)); else - { - from.Skills[i].BaseFixedPoint -= requiredAmount; - break; - } - } - - fromSkill.Base = skillValue; - m_Stone.SkillValue = 0.0; - - from.SendLocalizedMessage(1070713); // You have successfully absorbed the Soulstone's skill points. - - m_Stone.LastUserName = from.Name; - - Effects.SendLocationParticles(EffectItem.Create(from.Location, from.Map, EffectItem.DefaultDuration), 0, 0, - 0, 0, 0, 5060, 0); - Effects.PlaySound(from.Location, from.Map, 0x243); - - Effects.SendMovingParticles( - new Entity(Server.Serial.Zero, new Point3D(from.X - 6, from.Y - 6, from.Z + 15), from.Map), from, 0x36D4, - 7, 0, false, true, 0x497, 0, 9502, 1, 0, (EffectLayer)255, 0x100); - - Effects.SendTargetParticles(from, 0x375A, 35, 90, 0x00, 0x00, 9502, (EffectLayer)255, 0x100); - - if (m_Stone is SoulstoneFragment frag) - if (--frag.UsesRemaining <= 0) - from.SendLocalizedMessage(1070974); // You have used up your soulstone fragment. - } - } - - private class ConfirmRemovalGump : Gump - { - private readonly SoulStone m_Stone; - - public ConfirmRemovalGump(SoulStone stone) : base(50, 50) - { - m_Stone = stone; - - AddBackground(0, 0, 520, 440, 0x13BE); - - AddImageTiled(10, 10, 500, 20, 0xA40); - AddImageTiled(10, 40, 500, 360, 0xA40); - AddImageTiled(10, 410, 500, 20, 0xA40); - - AddAlphaRegion(10, 10, 500, 420); - - AddHtmlLocalized(10, 12, 500, 20, 1070725, 0x7FFF); //
Confirm Soulstone Skill Removal
- - /* WARNING!

- * - * You are about to permanently remove all skill points stored in this Soulstone. - * You WILL NOT absorb these skill points. They will be DELETED.

- * - * Are you sure you wish to do this? If not, press the Cancel button. - */ - AddHtmlLocalized(10, 42, 500, 110, 1070724, 0x7FFF, false, true); - - AddButton(10, 380, 0xFA5, 0xFA6, 1); - AddHtmlLocalized(45, 382, 450, 20, 1052072, 0x7FFF); // Continue - - AddButton(10, 410, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(45, 412, 450, 20, 1060051, 0x7FFF); // CANCEL - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 0 || m_Stone.IsEmpty) - return; - - Mobile from = sender.Mobile; - - if (!m_Stone.CheckUse(from)) - return; - - m_Stone.SkillValue = 0.0; - from.SendLocalizedMessage(1070726); // You have successfully deleted the Soulstone's skill points. - } - } - - private class ErrorGump : Gump - { - private readonly SoulStone m_Stone; - - public ErrorGump(SoulStone stone, int title, int message) : base(50, 50) - { - m_Stone = stone; - - AddBackground(0, 0, 520, 440, 0x13BE); - - AddImageTiled(10, 10, 500, 20, 0xA40); - AddImageTiled(10, 40, 500, 360, 0xA40); - AddImageTiled(10, 410, 500, 20, 0xA40); - - AddAlphaRegion(10, 10, 500, 420); - - AddHtmlLocalized(10, 12, 500, 20, title, 0x7FFF); - - AddHtmlLocalized(10, 42, 500, 110, message, 0x7FFF, false, true); - - AddButton(10, 380, 0xFA5, 0xFA6, 1); - AddHtmlLocalized(45, 382, 450, 20, 1052072, 0x7FFF); // Continue - - AddButton(10, 410, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(45, 412, 450, 20, 1060051, 0x7FFF); // CANCEL - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 0) - return; - - Mobile from = sender.Mobile; - - if (!m_Stone.CheckUse(from)) - return; - - if (m_Stone.IsEmpty) - from.SendGump(new SelectSkillGump(m_Stone, from)); - else - from.SendGump(new ConfirmTransferGump(m_Stone, from)); - } - } - } - - public class SoulstoneFragment : SoulStone, IUsesRemaining - { - private int m_UsesRemaining; - - [Constructible] - public SoulstoneFragment(string account) : this(5, account) - { - } - - [Constructible] - public SoulstoneFragment(int usesRemaining = 5, string account = null) : base(account, Utility.Random(0x2AA1, 9)) => - m_UsesRemaining = usesRemaining; - - public SoulstoneFragment(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1071000; // soulstone fragment - - [CommandProperty(AccessLevel.GameMaster)] - public int UsesRemaining - { - get => m_UsesRemaining; - set - { - m_UsesRemaining = value; - InvalidateProperties(); - } - } - - bool IUsesRemaining.ShowUsesRemaining - { - get => true; - set { } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1060584, m_UsesRemaining.ToString()); // uses remaining: ~1_val~ - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(2); // version - - writer.WriteEncodedInt(m_UsesRemaining); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_UsesRemaining = reader.ReadEncodedInt(); - - if (version <= 1) - { - if (ItemID == 0x2A93 || ItemID == 0x2A94) - ActiveItemID = Utility.Random(0x2AA1, 9); - else - ActiveItemID = ItemID; - - InactiveItemID = ActiveItemID; - } - - if (version == 0 && Weight == 1) - Weight = -1; - } - - protected override bool CheckUse(Mobile from) - { - bool canUse = base.CheckUse(from); - - if (canUse) - if (m_UsesRemaining <= 0) - { - from.SendLocalizedMessage(1070975); // That soulstone fragment has no more uses. - return false; + from.SendGump(new ConfirmTransferGump(this, from)); } - return canUse; - } - } + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - [Flippable] - public class BlueSoulstone : SoulStone - { - [Constructible] - public BlueSoulstone(string account = null) - : base(account, 0x2ADC, 0x2ADD) + writer.WriteEncodedInt(3); // version + + // version 3 + writer.Write(m_LastUserName); + + // version 2 + writer.Write((int)Level); + + writer.Write(m_ActiveItemID); + writer.Write(m_InactiveItemID); + + writer.Write(Account); + writer.Write(m_NextUse); // TODO: delete it in a harmless way + + writer.WriteEncodedInt((int)m_Skill); + writer.Write(m_SkillValue); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 3: + { + m_LastUserName = reader.ReadString(); + goto case 2; + } + case 2: + { + Level = (SecureLevel)reader.ReadInt(); + goto case 1; + } + case 1: + { + m_ActiveItemID = reader.ReadInt(); + m_InactiveItemID = reader.ReadInt(); + + goto case 0; + } + case 0: + { + Account = reader.ReadString(); + m_NextUse = reader.ReadDateTime(); // TODO: delete it in a harmless way + + m_Skill = (SkillName)reader.ReadEncodedInt(); + m_SkillValue = reader.ReadDouble(); + break; + } + } + + if (version == 0) + { + m_ActiveItemID = 0x2A94; + m_InactiveItemID = 0x2A93; + } + } + + private class SelectSkillGump : Gump + { + private readonly SoulStone m_Stone; + + public SelectSkillGump(SoulStone stone, Mobile from) : base(50, 50) + { + m_Stone = stone; + + AddPage(0); + + AddBackground(0, 0, 520, 440, 0x13BE); + + AddImageTiled(10, 10, 500, 20, 0xA40); + AddImageTiled(10, 40, 500, 360, 0xA40); + AddImageTiled(10, 410, 500, 20, 0xA40); + + AddAlphaRegion(10, 10, 500, 420); + + AddHtmlLocalized(10, 12, 500, 20, 1061087, 0x7FFF); // Which skill do you wish to transfer to the Soulstone? + + AddButton(10, 410, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(45, 412, 450, 20, 1060051, 0x7FFF); // CANCEL + + for (int i = 0, n = 0; i < from.Skills.Length; i++) + { + var skill = from.Skills[i]; + + if (skill.Base > 0.0) + { + var p = n % 30; + + if (p == 0) + { + var page = n / 30; + + if (page > 0) + { + AddButton(260, 380, 0xFA5, 0xFA6, 0, GumpButtonType.Page, page + 1); + AddHtmlLocalized(305, 382, 200, 20, 1011066, 0x7FFF); // Next page + } + + AddPage(page + 1); + + if (page > 0) + { + AddButton(10, 380, 0xFAE, 0xFAF, 0, GumpButtonType.Page, page); + AddHtmlLocalized(55, 382, 200, 20, 1011067, 0x7FFF); // Previous page + } + } + + var x = p % 2 == 0 ? 10 : 260; + var y = p / 2 * 20 + 40; + + AddButton(x, y, 0xFA5, 0xFA6, i + 1); + AddHtmlLocalized(x + 45, y + 2, 200, 20, AosSkillBonuses.GetLabel(skill.SkillName), 0x7FFF); + + n++; + } + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 0 || !m_Stone.IsEmpty) + return; + + var from = sender.Mobile; + + var iSkill = info.ButtonID - 1; + if (iSkill < 0 || iSkill >= from.Skills.Length) + return; + + var skill = from.Skills[iSkill]; + if (skill.Base <= 0.0) + return; + + if (!m_Stone.CheckUse(from)) + return; + + from.SendGump(new ConfirmSkillGump(m_Stone, skill)); + } + } + + private class ConfirmSkillGump : Gump + { + private readonly Skill m_Skill; + private readonly SoulStone m_Stone; + + public ConfirmSkillGump(SoulStone stone, Skill skill) : base(50, 50) + { + m_Stone = stone; + m_Skill = skill; + + AddBackground(0, 0, 520, 440, 0x13BE); + + AddImageTiled(10, 10, 500, 20, 0xA40); + AddImageTiled(10, 40, 500, 360, 0xA40); + AddImageTiled(10, 410, 500, 20, 0xA40); + + AddAlphaRegion(10, 10, 500, 420); + + AddHtmlLocalized(10, 12, 500, 20, 1070709, 0x7FFF); //
Confirm Soulstone Transfer
+ + /*
Soulstone

+ * You are using a Soulstone. This powerful artifact allows you to remove skill points + * from your character and store them in the stone for later retrieval. In order to use + * the stone, you must make sure your Skill Lock for the indicated skill is pointed downward. + * Click the "Skills" button on your Paperdoll to access the Skill List, and double-check + * your skill lock.

+ * + * Once you activate the stone, all skill points in the indicated skill will be removed from + * your character. These skill points can later be retrieved. IMPORTANT: When retrieving + * skill points from a Soulstone, the Soulstone WILL REPLACE any existing skill points + * already on your character!

+ * + * This is an Account Bound Soulstone. Skill pointsstored inside can be retrieved by any + * character on the same account as the character who placed them into the stone. + */ + AddHtmlLocalized(10, 42, 500, 110, 1061067, 0x7FFF, false, true); + + AddHtmlLocalized(10, 200, 390, 20, 1062297, 0x7FFF); // Skill Chosen: + AddHtmlLocalized(210, 200, 390, 20, AosSkillBonuses.GetLabel(skill.SkillName), 0x7FFF); + + AddHtmlLocalized(10, 220, 390, 20, 1062298, 0x7FFF); // Current Value: + AddLabel(210, 220, 0x481, skill.Base.ToString("0.0")); + + AddHtmlLocalized(10, 240, 390, 20, 1062299, 0x7FFF); // Current Cap: + AddLabel(210, 240, 0x481, skill.Cap.ToString("0.0")); + + AddHtmlLocalized(10, 260, 390, 20, 1062300, 0x7FFF); // New Value: + AddLabel(210, 260, 0x481, "0.0"); + + AddButton(10, 360, 0xFA5, 0xFA6, 2); + AddHtmlLocalized( + 45, + 362, + 450, + 20, + 1070720, + 0x7FFF + ); // Activate the stone. I am ready to transfer the skill points to it. + + AddButton(10, 380, 0xFA5, 0xFA6, 1); + AddHtmlLocalized(45, 382, 450, 20, 1062279, 0x7FFF); // No, let me make another selection. + + AddButton(10, 410, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(45, 412, 450, 20, 1060051, 0x7FFF); // CANCEL + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 0 || !m_Stone.IsEmpty) + return; + + var from = sender.Mobile; + + if (!m_Stone.CheckUse(from)) + return; + + if (info.ButtonID == 1) // Is asking for another selection + { + from.SendGump(new SelectSkillGump(m_Stone, from)); + return; + } + + if (m_Skill.Base <= 0.0) + return; + + if (m_Skill.Lock != SkillLock.Down) + { + //
Unable to Transfer Selected Skill to Soulstone
+ + /* You cannot transfer the selected skill to the Soulstone at this time. The selected + * skill may be locked or set to raise in your skill menu. Click on "Skills" in your + * paperdoll menu to check your raise/locked/lower settings and your total skills. + * Make any needed adjustments, then click "Continue". If you do not wish to transfer + * the selected skill at this time, click "Cancel". + */ + + from.SendGump(new ErrorGump(m_Stone, 1070710, 1070711)); + return; + } + + m_Stone.Skill = m_Skill.SkillName; + m_Stone.SkillValue = m_Skill.Base; + + m_Skill.Base = 0.0; + + from.SendLocalizedMessage( + 1070712 + ); // You have successfully transferred your skill points into the Soulstone. + + m_Stone.LastUserName = from.Name; + + Effects.SendLocationParticles( + EffectItem.Create(from.Location, from.Map, EffectItem.DefaultDuration), + 0, + 0, + 0, + 0, + 0, + 5060, + 0 + ); + Effects.PlaySound(from.Location, from.Map, 0x243); + + Effects.SendMovingParticles( + new Entity(Server.Serial.Zero, new Point3D(from.X - 6, from.Y - 6, from.Z + 15), from.Map), + from, + 0x36D4, + 7, + 0, + false, + true, + 0x497, + 0, + 9502, + 1, + 0, + (EffectLayer)255, + 0x100 + ); + + Effects.SendTargetParticles(from, 0x375A, 35, 90, 0x00, 0x00, 9502, (EffectLayer)255, 0x100); + } + } + + private class ConfirmTransferGump : Gump + { + private readonly SoulStone m_Stone; + + public ConfirmTransferGump(SoulStone stone, Mobile from) : base(50, 50) + { + m_Stone = stone; + + AddBackground(0, 0, 520, 440, 0x13BE); + + AddImageTiled(10, 10, 500, 20, 0xA40); + AddImageTiled(10, 40, 500, 360, 0xA40); + AddImageTiled(10, 410, 500, 20, 0xA40); + + AddAlphaRegion(10, 10, 500, 420); + + AddHtmlLocalized(10, 12, 500, 20, 1070709, 0x7FFF); //
Confirm Soulstone Transfer
+ + /*
Soulstone

+ * You are using a Soulstone. This powerful artifact allows you to remove skill points + * from your character and store them in the stone for later retrieval. In order to use + * the stone, you must make sure your Skill Lock for the indicated skill is pointed downward. + * Click the "Skills" button on your Paperdoll to access the Skill List, and double-check + * your skill lock.

+ * + * Once you activate the stone, all skill points in the indicated skill will be removed from + * your character. These skill points can later be retrieved. IMPORTANT: When retrieving + * skill points from a Soulstone, the Soulstone WILL REPLACE any existing skill points + * already on your character!

+ * + * This is an Account Bound Soulstone. Skill pointsstored inside can be retrieved by any + * character on the same account as the character who placed them into the stone. + */ + AddHtmlLocalized(10, 42, 500, 110, 1061067, 0x7FFF, false, true); + + AddHtmlLocalized(10, 200, 390, 20, 1070718, 0x7FFF); // Skill Stored: + AddHtmlLocalized(210, 200, 390, 20, AosSkillBonuses.GetLabel(stone.Skill), 0x7FFF); + + var fromSkill = from.Skills[stone.Skill]; + + AddHtmlLocalized(10, 220, 390, 20, 1062298, 0x7FFF); // Current Value: + AddLabel(210, 220, 0x481, fromSkill.Base.ToString("0.0")); + + AddHtmlLocalized(10, 240, 390, 20, 1062299, 0x7FFF); // Current Cap: + AddLabel(210, 240, 0x481, fromSkill.Cap.ToString("0.0")); + + AddHtmlLocalized(10, 260, 390, 20, 1062300, 0x7FFF); // New Value: + AddLabel(210, 260, 0x481, stone.SkillValue.ToString("0.0")); + + AddButton(10, 360, 0xFA5, 0xFA6, 2); + AddHtmlLocalized( + 45, + 362, + 450, + 20, + 1070719, + 0x7FFF + ); // Activate the stone. I am ready to retrieve the skill points from it. + + AddButton(10, 380, 0xFA5, 0xFA6, 1); + AddHtmlLocalized( + 45, + 382, + 450, + 20, + 1070723, + 0x7FFF + ); // Remove all skill points from this stone and DO NOT absorb them. + + AddButton(10, 410, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(45, 412, 450, 20, 1060051, 0x7FFF); // CANCEL + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 0 || m_Stone.IsEmpty) + return; + + var from = sender.Mobile; + + if (!m_Stone.CheckUse(from)) + return; + + if (info.ButtonID == 1) // Remove skill points + { + from.SendGump(new ConfirmRemovalGump(m_Stone)); + return; + } + + var skill = m_Stone.Skill; + var skillValue = m_Stone.SkillValue; + var fromSkill = from.Skills[m_Stone.Skill]; + + /* If we have, say, 88.4 in our skill and the stone holds 100, we need + * 11.6 free points. Also, if we're below our skillcap by, say, 8.2 points, + * we only need 11.6 - 8.2 = 3.4 points. + */ + var requiredAmount = (int)(skillValue * 10) - fromSkill.BaseFixedPoint - (from.SkillsCap - from.SkillsTotal); + + var cannotAbsorb = false; + + if (fromSkill.Lock != SkillLock.Up) + { + cannotAbsorb = true; + } + else if (requiredAmount > 0) + { + var available = 0; + + for (var i = 0; i < from.Skills.Length; ++i) + { + if (from.Skills[i].Lock != SkillLock.Down) + continue; + + available += from.Skills[i].BaseFixedPoint; + } + + if (requiredAmount > available) + cannotAbsorb = true; + } + + if (cannotAbsorb) + { + //
Unable to Absorb Selected Skill from Soulstone
+ + /* You cannot absorb the selected skill from the Soulstone at this time. The selected + * skill may be locked or set to lower in your skill menu. You may also be at your + * total skill cap. Click on "Skills" in your paperdoll menu to check your + * raise/locked/lower settings and your total skills. Make any needed adjustments, + * then click "Continue". If you do not wish to transfer the selected skill at this + * time, click "Cancel". + */ + + from.SendGump(new ErrorGump(m_Stone, 1070717, 1070716)); + return; + } + + if (skillValue > fromSkill.Cap) + { + //
Unable to Absorb Selected Skill from Soulstone
+ + /* The amount of skill stored in this stone exceeds your individual skill cap for + * that skill. In order to retrieve the skill points stored in this stone, you must + * obtain a Power Scroll of the appropriate type and level in order to increase your + * skill cap. You cannot currently retrieve the skill points stored in this stone. + */ + + from.SendGump(new ErrorGump(m_Stone, 1070717, 1070715)); + return; + } + + if (fromSkill.Base >= skillValue) + { + //
Unable to Absorb Selected Skill from Soulstone
+ + /* You cannot transfer the selected skill to the Soulstone at this time. The selected + * skill has a skill level higher than what is stored in the Soulstone. + */ + + // Wrong message?! + + from.SendGump(new ErrorGump(m_Stone, 1070717, 1070802)); + return; + } + + var pm = from as PlayerMobile; + if (pm.AcceleratedStart > DateTime.UtcNow) + { + //
Unable to Absorb Selected Skill from Soulstone
+ + /*You may not use a soulstone while your character is under the effects of a Scroll of Alacrity.*/ + + // Wrong message?! + + from.SendGump(new ErrorGump(m_Stone, 1070717, 1078115)); + return; + } + + if (requiredAmount > 0) + for (var i = 0; i < from.Skills.Length; ++i) + { + if (from.Skills[i].Lock != SkillLock.Down) + continue; + + if (requiredAmount >= from.Skills[i].BaseFixedPoint) + { + requiredAmount -= from.Skills[i].BaseFixedPoint; + from.Skills[i].Base = 0.0; + } + else + { + from.Skills[i].BaseFixedPoint -= requiredAmount; + break; + } + } + + fromSkill.Base = skillValue; + m_Stone.SkillValue = 0.0; + + from.SendLocalizedMessage(1070713); // You have successfully absorbed the Soulstone's skill points. + + m_Stone.LastUserName = from.Name; + + Effects.SendLocationParticles( + EffectItem.Create(from.Location, from.Map, EffectItem.DefaultDuration), + 0, + 0, + 0, + 0, + 0, + 5060, + 0 + ); + Effects.PlaySound(from.Location, from.Map, 0x243); + + Effects.SendMovingParticles( + new Entity(Server.Serial.Zero, new Point3D(from.X - 6, from.Y - 6, from.Z + 15), from.Map), + from, + 0x36D4, + 7, + 0, + false, + true, + 0x497, + 0, + 9502, + 1, + 0, + (EffectLayer)255, + 0x100 + ); + + Effects.SendTargetParticles(from, 0x375A, 35, 90, 0x00, 0x00, 9502, (EffectLayer)255, 0x100); + + if (m_Stone is SoulstoneFragment frag) + if (--frag.UsesRemaining <= 0) + from.SendLocalizedMessage(1070974); // You have used up your soulstone fragment. + } + } + + private class ConfirmRemovalGump : Gump + { + private readonly SoulStone m_Stone; + + public ConfirmRemovalGump(SoulStone stone) : base(50, 50) + { + m_Stone = stone; + + AddBackground(0, 0, 520, 440, 0x13BE); + + AddImageTiled(10, 10, 500, 20, 0xA40); + AddImageTiled(10, 40, 500, 360, 0xA40); + AddImageTiled(10, 410, 500, 20, 0xA40); + + AddAlphaRegion(10, 10, 500, 420); + + AddHtmlLocalized(10, 12, 500, 20, 1070725, 0x7FFF); //
Confirm Soulstone Skill Removal
+ + /* WARNING!

+ * + * You are about to permanently remove all skill points stored in this Soulstone. + * You WILL NOT absorb these skill points. They will be DELETED.

+ * + * Are you sure you wish to do this? If not, press the Cancel button. + */ + AddHtmlLocalized(10, 42, 500, 110, 1070724, 0x7FFF, false, true); + + AddButton(10, 380, 0xFA5, 0xFA6, 1); + AddHtmlLocalized(45, 382, 450, 20, 1052072, 0x7FFF); // Continue + + AddButton(10, 410, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(45, 412, 450, 20, 1060051, 0x7FFF); // CANCEL + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 0 || m_Stone.IsEmpty) + return; + + var from = sender.Mobile; + + if (!m_Stone.CheckUse(from)) + return; + + m_Stone.SkillValue = 0.0; + from.SendLocalizedMessage(1070726); // You have successfully deleted the Soulstone's skill points. + } + } + + private class ErrorGump : Gump + { + private readonly SoulStone m_Stone; + + public ErrorGump(SoulStone stone, int title, int message) : base(50, 50) + { + m_Stone = stone; + + AddBackground(0, 0, 520, 440, 0x13BE); + + AddImageTiled(10, 10, 500, 20, 0xA40); + AddImageTiled(10, 40, 500, 360, 0xA40); + AddImageTiled(10, 410, 500, 20, 0xA40); + + AddAlphaRegion(10, 10, 500, 420); + + AddHtmlLocalized(10, 12, 500, 20, title, 0x7FFF); + + AddHtmlLocalized(10, 42, 500, 110, message, 0x7FFF, false, true); + + AddButton(10, 380, 0xFA5, 0xFA6, 1); + AddHtmlLocalized(45, 382, 450, 20, 1052072, 0x7FFF); // Continue + + AddButton(10, 410, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(45, 412, 450, 20, 1060051, 0x7FFF); // CANCEL + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 0) + return; + + var from = sender.Mobile; + + if (!m_Stone.CheckUse(from)) + return; + + if (m_Stone.IsEmpty) + from.SendGump(new SelectSkillGump(m_Stone, from)); + else + from.SendGump(new ConfirmTransferGump(m_Stone, from)); + } + } + } + + public class SoulstoneFragment : SoulStone, IUsesRemaining { + private int m_UsesRemaining; + + [Constructible] + public SoulstoneFragment(string account) : this(5, account) + { + } + + [Constructible] + public SoulstoneFragment(int usesRemaining = 5, string account = null) : base(account, Utility.Random(0x2AA1, 9)) => + m_UsesRemaining = usesRemaining; + + public SoulstoneFragment(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1071000; // soulstone fragment + + [CommandProperty(AccessLevel.GameMaster)] + public int UsesRemaining + { + get => m_UsesRemaining; + set + { + m_UsesRemaining = value; + InvalidateProperties(); + } + } + + bool IUsesRemaining.ShowUsesRemaining + { + get => true; + set { } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1060584, m_UsesRemaining.ToString()); // uses remaining: ~1_val~ + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(2); // version + + writer.WriteEncodedInt(m_UsesRemaining); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_UsesRemaining = reader.ReadEncodedInt(); + + if (version <= 1) + { + if (ItemID == 0x2A93 || ItemID == 0x2A94) + ActiveItemID = Utility.Random(0x2AA1, 9); + else + ActiveItemID = ItemID; + + InactiveItemID = ActiveItemID; + } + + if (version == 0 && Weight == 1) + Weight = -1; + } + + protected override bool CheckUse(Mobile from) + { + var canUse = base.CheckUse(from); + + if (canUse) + if (m_UsesRemaining <= 0) + { + from.SendLocalizedMessage(1070975); // That soulstone fragment has no more uses. + return false; + } + + return canUse; + } } - public BlueSoulstone(Serial serial) - : base(serial) + [Flippable] + public class BlueSoulstone : SoulStone { + [Constructible] + public BlueSoulstone(string account = null) + : base(account, 0x2ADC, 0x2ADD) + { + } + + public BlueSoulstone(Serial serial) + : base(serial) + { + } + + public void Flip() + { + ItemID = ItemID switch + { + 0x2ADC => 0x2AEC, + 0x2ADD => 0x2AED, + 0x2AEC => 0x2ADC, + 0x2AED => 0x2ADD, + _ => ItemID + }; + } + + 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 void Flip() + public class RedSoulstone : SoulStone, IRewardItem { - ItemID = ItemID switch - { - 0x2ADC => 0x2AEC, - 0x2ADD => 0x2AED, - 0x2AEC => 0x2ADC, - 0x2AED => 0x2ADD, - _ => ItemID - }; + private bool m_IsRewardItem; + + [Constructible] + public RedSoulstone(string account = null) + : base(account, 0x32F3, 0x32F4) + { + } + + public RedSoulstone(Serial serial) + : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_IsRewardItem) + list.Add(1076217); // 1st Year Veteran Reward + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_IsRewardItem = reader.ReadBool(); + break; + } + } + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class RedSoulstone : SoulStone, IRewardItem - { - private bool m_IsRewardItem; - - [Constructible] - public RedSoulstone(string account = null) - : base(account, 0x32F3, 0x32F4) - { - } - - public RedSoulstone(Serial serial) - : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_IsRewardItem) - list.Add(1076217); // 1st Year Veteran Reward - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_IsRewardItem = reader.ReadBool(); - break; - } - } - } - } } diff --git a/Projects/UOContent/Items/Special/Special Scrolls/PowerScroll.cs b/Projects/UOContent/Items/Special/Special Scrolls/PowerScroll.cs index 44439a745..19003863d 100644 --- a/Projects/UOContent/Items/Special/Special Scrolls/PowerScroll.cs +++ b/Projects/UOContent/Items/Special/Special Scrolls/PowerScroll.cs @@ -2,249 +2,304 @@ using System.Collections.Generic; namespace Server.Items { - public class PowerScroll : SpecialScroll - { - private static readonly SkillName[] m_Skills = + public class PowerScroll : SpecialScroll { - SkillName.Blacksmith, - SkillName.Tailoring, - SkillName.Swords, - SkillName.Fencing, - SkillName.Macing, - SkillName.Archery, - SkillName.Wrestling, - SkillName.Parry, - SkillName.Tactics, - SkillName.Anatomy, - SkillName.Healing, - SkillName.Magery, - SkillName.Meditation, - SkillName.EvalInt, - SkillName.MagicResist, - SkillName.AnimalTaming, - SkillName.AnimalLore, - SkillName.Veterinary, - SkillName.Musicianship, - SkillName.Provocation, - SkillName.Discordance, - SkillName.Peacemaking - }; - - private static readonly SkillName[] m_AOSSkills = - { - SkillName.Chivalry, - SkillName.Focus, - SkillName.Necromancy, - SkillName.Stealing, - SkillName.Stealth, - SkillName.SpiritSpeak - }; - - private static readonly SkillName[] m_SESkills = - { - SkillName.Ninjitsu, - SkillName.Bushido - }; - - private static readonly SkillName[] m_MLSkills = - { - SkillName.Spellweaving - }; - - /* - private static SkillName[] m_SASkills = new SkillName[] - { - SkillName.Throwing, - SkillName.Mysticism, - SkillName.Imbuing - }; - - private static SkillName[] m_HSSkills = new SkillName[] - { - SkillName.Fishing - }; - */ - - private static readonly List _Skills = new List(); - - [Constructible] - public PowerScroll(SkillName skill = SkillName.Alchemy, double value = 0.0) : base(skill, value) - { - Hue = 0x481; - - if (Value == 105.0 || skill == SkillName.Blacksmith || skill == SkillName.Tailoring) - LootType = LootType.Regular; - } - - public PowerScroll(Serial serial) : base(serial) - { - } - - /* Using a scroll increases the maximum amount of a specific skill or your maximum statistics. - * When used, the effect is not immediately seen without a gain of points with that skill or statistics. - * You can view your maximum skill values in your skills window. - * You can view your maximum statistic value in your statistics window. - */ - public override int Message => - 1049469; - - public override int Title - { - get - { - double level = (Value - 105.0) / 5.0; - - /* Wonderous Scroll (105 Skill): OR - * Exalted Scroll (110 Skill): OR - * Mythical Scroll (115 Skill): OR - * Legendary Scroll (120 Skill): - */ - if (level >= 0.0 && level <= 3.0 && Value % 5.0 == 0.0) - return 1049635 + (int)level; - - return 0; - } - } - - public override string DefaultTitle => $"Power Scroll ({Value} Skill):"; - - public static List Skills - { - get - { - if (_Skills.Count == 0) + private static readonly SkillName[] m_Skills = { - _Skills.AddRange(m_Skills); - if (Core.AOS) + SkillName.Blacksmith, + SkillName.Tailoring, + SkillName.Swords, + SkillName.Fencing, + SkillName.Macing, + SkillName.Archery, + SkillName.Wrestling, + SkillName.Parry, + SkillName.Tactics, + SkillName.Anatomy, + SkillName.Healing, + SkillName.Magery, + SkillName.Meditation, + SkillName.EvalInt, + SkillName.MagicResist, + SkillName.AnimalTaming, + SkillName.AnimalLore, + SkillName.Veterinary, + SkillName.Musicianship, + SkillName.Provocation, + SkillName.Discordance, + SkillName.Peacemaking + }; + + private static readonly SkillName[] m_AOSSkills = + { + SkillName.Chivalry, + SkillName.Focus, + SkillName.Necromancy, + SkillName.Stealing, + SkillName.Stealth, + SkillName.SpiritSpeak + }; + + private static readonly SkillName[] m_SESkills = + { + SkillName.Ninjitsu, + SkillName.Bushido + }; + + private static readonly SkillName[] m_MLSkills = + { + SkillName.Spellweaving + }; + + /* + private static SkillName[] m_SASkills = new SkillName[] { - _Skills.AddRange(m_AOSSkills); - if (Core.SE) - { - _Skills.AddRange(m_SESkills); - if (Core.ML) _Skills.AddRange(m_MLSkills); - } - } + SkillName.Throwing, + SkillName.Mysticism, + SkillName.Imbuing + }; + + private static SkillName[] m_HSSkills = new SkillName[] + { + SkillName.Fishing + }; + */ + + private static readonly List _Skills = new List(); + + [Constructible] + public PowerScroll(SkillName skill = SkillName.Alchemy, double value = 0.0) : base(skill, value) + { + Hue = 0x481; + + if (Value == 105.0 || skill == SkillName.Blacksmith || skill == SkillName.Tailoring) + LootType = LootType.Regular; } - return _Skills; - } - } + public PowerScroll(Serial serial) : base(serial) + { + } - public static PowerScroll CreateRandom(int min, int max) - { - min /= 5; - max /= 5; - - return new PowerScroll(Skills.RandomElement(), 100 + Utility.RandomMinMax(min, max) * 5); - } - - public static PowerScroll CreateRandomNoCraft(int min, int max) - { - min /= 5; - max /= 5; - - SkillName skillName; - - do - { - skillName = Skills.RandomElement(); - } while (skillName == SkillName.Blacksmith || skillName == SkillName.Tailoring); - - return new PowerScroll(skillName, 100 + Utility.RandomMinMax(min, max) * 5); - } - - public override void AddNameProperty(ObjectPropertyList list) - { - double level = (Value - 105.0) / 5.0; - - if (level >= 0.0 && level <= 3.0 && Value % 5.0 == 0.0) - /* a wonderous scroll of ~1_type~ (105 Skill) OR - * an exalted scroll of ~1_type~ (110 Skill) OR - * a mythical scroll of ~1_type~ (115 Skill) OR - * a legendary scroll of ~1_type~ (120 Skill) + /* Using a scroll increases the maximum amount of a specific skill or your maximum statistics. + * When used, the effect is not immediately seen without a gain of points with that skill or statistics. + * You can view your maximum skill values in your skills window. + * You can view your maximum statistic value in your statistics window. */ - list.Add(1049639 + (int)level, GetNameLocalized()); - else - list.Add("a power scroll of {0} ({1} Skill)", GetName(), Value); + public override int Message => + 1049469; + + public override int Title + { + get + { + var level = (Value - 105.0) / 5.0; + + /* Wonderous Scroll (105 Skill): OR + * Exalted Scroll (110 Skill): OR + * Mythical Scroll (115 Skill): OR + * Legendary Scroll (120 Skill): + */ + if (level >= 0.0 && level <= 3.0 && Value % 5.0 == 0.0) + return 1049635 + (int)level; + + return 0; + } + } + + public override string DefaultTitle => $"Power Scroll ({Value} Skill):"; + + public static List Skills + { + get + { + if (_Skills.Count == 0) + { + _Skills.AddRange(m_Skills); + if (Core.AOS) + { + _Skills.AddRange(m_AOSSkills); + if (Core.SE) + { + _Skills.AddRange(m_SESkills); + if (Core.ML) _Skills.AddRange(m_MLSkills); + } + } + } + + return _Skills; + } + } + + public static PowerScroll CreateRandom(int min, int max) + { + min /= 5; + max /= 5; + + return new PowerScroll(Skills.RandomElement(), 100 + Utility.RandomMinMax(min, max) * 5); + } + + public static PowerScroll CreateRandomNoCraft(int min, int max) + { + min /= 5; + max /= 5; + + SkillName skillName; + + do + { + skillName = Skills.RandomElement(); + } while (skillName == SkillName.Blacksmith || skillName == SkillName.Tailoring); + + return new PowerScroll(skillName, 100 + Utility.RandomMinMax(min, max) * 5); + } + + public override void AddNameProperty(ObjectPropertyList list) + { + var level = (Value - 105.0) / 5.0; + + if (level >= 0.0 && level <= 3.0 && Value % 5.0 == 0.0) + /* a wonderous scroll of ~1_type~ (105 Skill) OR + * an exalted scroll of ~1_type~ (110 Skill) OR + * a mythical scroll of ~1_type~ (115 Skill) OR + * a legendary scroll of ~1_type~ (120 Skill) + */ + list.Add(1049639 + (int)level, GetNameLocalized()); + else + list.Add("a power scroll of {0} ({1} Skill)", GetName(), Value); + } + + public override void OnSingleClick(Mobile from) + { + var level = (Value - 105.0) / 5.0; + + if (level >= 0.0 && level <= 3.0 && Value % 5.0 == 0.0) + LabelTo(from, 1049639 + (int)level, GetNameLocalized()); + else + LabelTo(from, "a power scroll of {0} ({1} Skill)", GetName(), Value); + } + + public override bool CanUse(Mobile from) + { + if (!base.CanUse(from)) + return false; + + var skill = from.Skills[Skill]; + + if (skill == null) + return false; + + if (skill.Cap >= Value) + { + from.SendLocalizedMessage( + 1049511, + GetNameLocalized() + ); // Your ~1_type~ is too high for this power scroll. + return false; + } + + return true; + } + + public override void Use(Mobile from) + { + if (!CanUse(from)) + return; + + from.SendLocalizedMessage( + 1049513, + GetNameLocalized() + ); // You feel a surge of magic as the scroll enhances your ~1_type~! + + from.Skills[Skill].Cap = Value; + + Effects.SendLocationParticles( + EffectItem.Create(from.Location, from.Map, EffectItem.DefaultDuration), + 0, + 0, + 0, + 0, + 0, + 5060, + 0 + ); + Effects.PlaySound(from.Location, from.Map, 0x243); + + Effects.SendMovingParticles( + new Entity(Serial.Zero, new Point3D(from.X - 6, from.Y - 6, from.Z + 15), from.Map), + from, + 0x36D4, + 7, + 0, + false, + true, + 0x497, + 0, + 9502, + 1, + 0, + (EffectLayer)255, + 0x100 + ); + Effects.SendMovingParticles( + new Entity(Serial.Zero, new Point3D(from.X - 4, from.Y - 6, from.Z + 15), from.Map), + from, + 0x36D4, + 7, + 0, + false, + true, + 0x497, + 0, + 9502, + 1, + 0, + (EffectLayer)255, + 0x100 + ); + Effects.SendMovingParticles( + new Entity(Serial.Zero, new Point3D(from.X - 6, from.Y - 4, from.Z + 15), from.Map), + from, + 0x36D4, + 7, + 0, + false, + true, + 0x497, + 0, + 9502, + 1, + 0, + (EffectLayer)255, + 0x100 + ); + + Effects.SendTargetParticles(from, 0x375A, 35, 90, 0x00, 0x00, 9502, (EffectLayer)255, 0x100); + + Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = InheritsItem ? 0 : reader.ReadInt(); // Required for SpecialScroll insertion + + if (Value == 105.0 || Skill == SkillName.Blacksmith || Skill == SkillName.Tailoring) + { + LootType = LootType.Regular; + } + else + { + LootType = LootType.Cursed; + Insured = false; + } + } } - - public override void OnSingleClick(Mobile from) - { - double level = (Value - 105.0) / 5.0; - - if (level >= 0.0 && level <= 3.0 && Value % 5.0 == 0.0) - LabelTo(from, 1049639 + (int)level, GetNameLocalized()); - else - LabelTo(from, "a power scroll of {0} ({1} Skill)", GetName(), Value); - } - - public override bool CanUse(Mobile from) - { - if (!base.CanUse(from)) - return false; - - Skill skill = from.Skills[Skill]; - - if (skill == null) - return false; - - if (skill.Cap >= Value) - { - from.SendLocalizedMessage(1049511, GetNameLocalized()); // Your ~1_type~ is too high for this power scroll. - return false; - } - - return true; - } - - public override void Use(Mobile from) - { - if (!CanUse(from)) - return; - - from.SendLocalizedMessage(1049513, - GetNameLocalized()); // You feel a surge of magic as the scroll enhances your ~1_type~! - - from.Skills[Skill].Cap = Value; - - Effects.SendLocationParticles(EffectItem.Create(from.Location, from.Map, EffectItem.DefaultDuration), 0, 0, 0, 0, - 0, 5060, 0); - Effects.PlaySound(from.Location, from.Map, 0x243); - - Effects.SendMovingParticles(new Entity(Serial.Zero, new Point3D(from.X - 6, from.Y - 6, from.Z + 15), from.Map), - from, 0x36D4, 7, 0, false, true, 0x497, 0, 9502, 1, 0, (EffectLayer)255, 0x100); - Effects.SendMovingParticles(new Entity(Serial.Zero, new Point3D(from.X - 4, from.Y - 6, from.Z + 15), from.Map), - from, 0x36D4, 7, 0, false, true, 0x497, 0, 9502, 1, 0, (EffectLayer)255, 0x100); - Effects.SendMovingParticles(new Entity(Serial.Zero, new Point3D(from.X - 6, from.Y - 4, from.Z + 15), from.Map), - from, 0x36D4, 7, 0, false, true, 0x497, 0, 9502, 1, 0, (EffectLayer)255, 0x100); - - Effects.SendTargetParticles(from, 0x375A, 35, 90, 0x00, 0x00, 9502, (EffectLayer)255, 0x100); - - Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = InheritsItem ? 0 : reader.ReadInt(); // Required for SpecialScroll insertion - - if (Value == 105.0 || Skill == SkillName.Blacksmith || Skill == SkillName.Tailoring) - { - LootType = LootType.Regular; - } - else - { - LootType = LootType.Cursed; - Insured = false; - } - } - } } diff --git a/Projects/UOContent/Items/Special/Special Scrolls/ScrollofAlacrity.cs b/Projects/UOContent/Items/Special/Special Scrolls/ScrollofAlacrity.cs index 2dcb6042e..72dacc06c 100644 --- a/Projects/UOContent/Items/Special/Special Scrolls/ScrollofAlacrity.cs +++ b/Projects/UOContent/Items/Special/Special Scrolls/ScrollofAlacrity.cs @@ -5,117 +5,119 @@ using Server.Mobiles; namespace Server.Items { - public class ScrollofAlacrity : SpecialScroll - { - [Constructible] - public ScrollofAlacrity(SkillName skill = SkillName.Alchemy) : base(skill, 0.0) + public class ScrollofAlacrity : SpecialScroll { - ItemID = 0x14EF; - Hue = 0x4AB; - } + [Constructible] + public ScrollofAlacrity(SkillName skill = SkillName.Alchemy) : base(skill, 0.0) + { + ItemID = 0x14EF; + Hue = 0x4AB; + } - public ScrollofAlacrity(Serial serial) : base(serial) - { - } + public ScrollofAlacrity(Serial serial) : base(serial) + { + } - public override int LabelNumber => 1078604; // Scroll of Alacrity + public override int LabelNumber => 1078604; // Scroll of Alacrity - /* Using a Scroll of Transcendence for a given skill will permanently increase your current - * level in that skill by the amount of points displayed on the scroll. - * As you may not gain skills beyond your maximum skill cap, any excess points will be lost. - */ - public override int Message => - 1078602; + /* Using a Scroll of Transcendence for a given skill will permanently increase your current + * level in that skill by the amount of points displayed on the scroll. + * As you may not gain skills beyond your maximum skill cap, any excess points will be lost. + */ + public override int Message => + 1078602; - public override string DefaultTitle => "Scroll of Alacrity:"; + public override string DefaultTitle => "Scroll of Alacrity:"; - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); - list.Add(1071345, "{0} 15 Minutes", GetName()); // Skill: ~1_val~ - } + list.Add(1071345, "{0} 15 Minutes", GetName()); // Skill: ~1_val~ + } - public override bool CanUse(Mobile from) - { - if (!(base.CanUse(from) && from is PlayerMobile pm)) - return false; + public override bool CanUse(Mobile from) + { + if (!(base.CanUse(from) && from is PlayerMobile pm)) + return false; - MLQuestContext context = MLQuestSystem.GetContext(pm); + var context = MLQuestSystem.GetContext(pm); - if (context != null) - foreach (MLQuestInstance instance in context.QuestInstances) - foreach (BaseObjectiveInstance objective in instance.Objectives) - if (!objective.Expired && objective is GainSkillObjectiveInstance objectiveInstance && - objectiveInstance.Handles(Skill)) + if (context != null) + foreach (var instance in context.QuestInstances) + foreach (var objective in instance.Objectives) + if (!objective.Expired && objective is GainSkillObjectiveInstance objectiveInstance && + objectiveInstance.Handles(Skill)) + { + from.SendMessage("You are already under the effect of an enhanced skillgain quest."); + return false; + } + + if (pm.AcceleratedStart > DateTime.UtcNow) { - from.SendMessage("You are already under the effect of an enhanced skillgain quest."); - return false; + from.SendLocalizedMessage(1077951); // You are already under the effect of an accelerated skillgain scroll. + return false; } - if (pm.AcceleratedStart > DateTime.UtcNow) - { - from.SendLocalizedMessage(1077951); // You are already under the effect of an accelerated skillgain scroll. - return false; - } + return true; + } - return true; + public override void Use(Mobile from) + { + if (!(CanUse(from) && from is PlayerMobile pm)) + return; + + var tskill = from.Skills[Skill].Base; + var tcap = from.Skills[Skill].Cap; + + if (tskill >= tcap || from.Skills[Skill].Lock != SkillLock.Up) + { + /* You cannot increase this skill at this time. The skill may be locked or set to lower in your skill menu. + * If you are at your total skill cap, you must use a Powerscroll to increase your current skill cap. + */ + from.SendLocalizedMessage(1094935); + return; + } + + from.SendLocalizedMessage( + 1077956 + ); // You are infused with intense energy. You are under the effects of an accelerated skillgain scroll. + + Effects.PlaySound(from.Location, from.Map, 0x1E9); + Effects.SendTargetParticles(from, 0x373A, 35, 45, 0x00, 0x00, 9502, (EffectLayer)255, 0x100); + + pm.AcceleratedStart = DateTime.UtcNow + TimeSpan.FromMinutes(15); + Timer.DelayCall(TimeSpan.FromMinutes(15), Expire_Callback, from); + + pm.AcceleratedSkill = Skill; + + Delete(); + } + + // TODO: Handle this upon deserialization. Create Dictionary and serialize Mobile/Timers? + private static void Expire_Callback(Mobile m) + { + m.PlaySound(0x1F8); + m.SendLocalizedMessage( + 1077957 + ); // The intense energy dissipates. You are no longer under the effects of an accelerated skillgain scroll. + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = InheritsItem ? 0 : reader.ReadInt(); // Required for SpecialScroll insertion + + LootType = LootType.Cursed; + Insured = false; + } } - - public override void Use(Mobile from) - { - if (!(CanUse(from) && from is PlayerMobile pm)) - return; - - double tskill = from.Skills[Skill].Base; - double tcap = from.Skills[Skill].Cap; - - if (tskill >= tcap || from.Skills[Skill].Lock != SkillLock.Up) - { - /* You cannot increase this skill at this time. The skill may be locked or set to lower in your skill menu. - * If you are at your total skill cap, you must use a Powerscroll to increase your current skill cap. - */ - from.SendLocalizedMessage(1094935); - return; - } - - from.SendLocalizedMessage( - 1077956); // You are infused with intense energy. You are under the effects of an accelerated skillgain scroll. - - Effects.PlaySound(from.Location, from.Map, 0x1E9); - Effects.SendTargetParticles(from, 0x373A, 35, 45, 0x00, 0x00, 9502, (EffectLayer)255, 0x100); - - pm.AcceleratedStart = DateTime.UtcNow + TimeSpan.FromMinutes(15); - Timer.DelayCall(TimeSpan.FromMinutes(15), Expire_Callback, from); - - pm.AcceleratedSkill = Skill; - - Delete(); - } - - // TODO: Handle this upon deserialization. Create Dictionary and serialize Mobile/Timers? - private static void Expire_Callback(Mobile m) - { - m.PlaySound(0x1F8); - m.SendLocalizedMessage( - 1077957); // The intense energy dissipates. You are no longer under the effects of an accelerated skillgain scroll. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = InheritsItem ? 0 : reader.ReadInt(); // Required for SpecialScroll insertion - - LootType = LootType.Cursed; - Insured = false; - } - } } diff --git a/Projects/UOContent/Items/Special/Special Scrolls/ScrollofTranscendence.cs b/Projects/UOContent/Items/Special/Special Scrolls/ScrollofTranscendence.cs index 1375dabf7..0f91628cb 100644 --- a/Projects/UOContent/Items/Special/Special Scrolls/ScrollofTranscendence.cs +++ b/Projects/UOContent/Items/Special/Special Scrolls/ScrollofTranscendence.cs @@ -5,145 +5,148 @@ using Server.Mobiles; namespace Server.Items { - public class ScrollofTranscendence : SpecialScroll - { - [Constructible] - public ScrollofTranscendence(SkillName skill = SkillName.Alchemy, double value = 0.0) : base(skill, value) + public class ScrollofTranscendence : SpecialScroll { - ItemID = 0x14EF; - Hue = 0x490; - } - - public ScrollofTranscendence(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1094934; // Scroll of Transcendence - - /* Using a Scroll of Transcendence for a given skill will permanently increase your current - * level in that skill by the amount of points displayed on the scroll. - * As you may not gain skills beyond your maximum skill cap, any excess points will be lost. - */ - public override int Message => - 1094933; - - public override string DefaultTitle => - $"Scroll of Transcendence ({Value} Skill):"; - - public static ScrollofTranscendence CreateRandom(int min, int max) => - new ScrollofTranscendence(Utility.RandomSkill(), Utility.RandomMinMax(min, max) * 0.1); - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Value == 1) - list.Add(1076759, "{0}\t{1}.0 Skill Points", GetName(), Value); - else - list.Add(1076759, "{0}\t{1} Skill Points", GetName(), Value); - } - - public override bool CanUse(Mobile from) - { - if (!(base.CanUse(from) && from is PlayerMobile pm)) - return false; - - MLQuestContext context = MLQuestSystem.GetContext(pm); - - if (context != null) - foreach (MLQuestInstance instance in context.QuestInstances) - foreach (BaseObjectiveInstance objective in instance.Objectives) - if (!objective.Expired && objective is GainSkillObjectiveInstance objectiveInstance && - objectiveInstance.Handles(Skill)) - { - from.SendMessage("You are already under the effect of an enhanced skillgain quest."); - return false; - } - - if (pm.AcceleratedStart > DateTime.UtcNow) - { - from.SendLocalizedMessage(1077951); // You are already under the effect of an accelerated skillgain scroll. - return false; - } - - return true; - } - - public override void Use(Mobile from) - { - if (!CanUse(from)) - return; - - double tskill = from.Skills[Skill].Base; // value of skill without item bonuses etc - double tcap = from.Skills[Skill].Cap; // maximum value permitted - bool canGain = false; - - double newValue = Value; - - if (tskill + newValue > tcap) - newValue = tcap - tskill; - - if (tskill < tcap && from.Skills[Skill].Lock == SkillLock.Up) - { - if (from.SkillsTotal + newValue * 10 > from.SkillsCap) + [Constructible] + public ScrollofTranscendence(SkillName skill = SkillName.Alchemy, double value = 0.0) : base(skill, value) { - int ns = from.Skills.Length; // number of items in from.Skills[] - - for (int i = 0; i < ns; i++) - // skill must point down and its value must be enough - if (from.Skills[i].Lock == SkillLock.Down && from.Skills[i].Base >= newValue) - { - from.Skills[i].Base -= newValue; - canGain = true; - break; - } + ItemID = 0x14EF; + Hue = 0x490; } - else + + public ScrollofTranscendence(Serial serial) : base(serial) { - canGain = true; } - } - if (!canGain) - { - /* You cannot increase this skill at this time. The skill may be locked or set to lower in your skill menu. - * If you are at your total skill cap, you must use a Powerscroll to increase your current skill cap. + public override int LabelNumber => 1094934; // Scroll of Transcendence + + /* Using a Scroll of Transcendence for a given skill will permanently increase your current + * level in that skill by the amount of points displayed on the scroll. + * As you may not gain skills beyond your maximum skill cap, any excess points will be lost. */ - from.SendLocalizedMessage( - 1094935); - return; - } + public override int Message => + 1094933; - from.SendLocalizedMessage(1049513, - GetNameLocalized()); // You feel a surge of magic as the scroll enhances your ~1_type~! + public override string DefaultTitle => + $"Scroll of Transcendence ({Value} Skill):"; - from.Skills[Skill].Base += newValue; + public static ScrollofTranscendence CreateRandom(int min, int max) => + new ScrollofTranscendence(Utility.RandomSkill(), Utility.RandomMinMax(min, max) * 0.1); - Effects.PlaySound(from.Location, from.Map, 0x1F7); - Effects.SendTargetParticles(from, 0x373A, 35, 45, 0x00, 0x00, 9502, (EffectLayer)255, 0x100); - Effects.SendTargetParticles(from, 0x376A, 35, 45, 0x00, 0x00, 9502, (EffectLayer)255, 0x100); + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); - Delete(); + if (Value == 1) + list.Add(1076759, "{0}\t{1}.0 Skill Points", GetName(), Value); + else + list.Add(1076759, "{0}\t{1} Skill Points", GetName(), Value); + } + + public override bool CanUse(Mobile from) + { + if (!(base.CanUse(from) && from is PlayerMobile pm)) + return false; + + var context = MLQuestSystem.GetContext(pm); + + if (context != null) + foreach (var instance in context.QuestInstances) + foreach (var objective in instance.Objectives) + if (!objective.Expired && objective is GainSkillObjectiveInstance objectiveInstance && + objectiveInstance.Handles(Skill)) + { + from.SendMessage("You are already under the effect of an enhanced skillgain quest."); + return false; + } + + if (pm.AcceleratedStart > DateTime.UtcNow) + { + from.SendLocalizedMessage(1077951); // You are already under the effect of an accelerated skillgain scroll. + return false; + } + + return true; + } + + public override void Use(Mobile from) + { + if (!CanUse(from)) + return; + + var tskill = from.Skills[Skill].Base; // value of skill without item bonuses etc + var tcap = from.Skills[Skill].Cap; // maximum value permitted + var canGain = false; + + var newValue = Value; + + if (tskill + newValue > tcap) + newValue = tcap - tskill; + + if (tskill < tcap && from.Skills[Skill].Lock == SkillLock.Up) + { + if (from.SkillsTotal + newValue * 10 > from.SkillsCap) + { + var ns = from.Skills.Length; // number of items in from.Skills[] + + for (var i = 0; i < ns; i++) + // skill must point down and its value must be enough + if (from.Skills[i].Lock == SkillLock.Down && from.Skills[i].Base >= newValue) + { + from.Skills[i].Base -= newValue; + canGain = true; + break; + } + } + else + { + canGain = true; + } + } + + if (!canGain) + { + /* You cannot increase this skill at this time. The skill may be locked or set to lower in your skill menu. + * If you are at your total skill cap, you must use a Powerscroll to increase your current skill cap. + */ + from.SendLocalizedMessage( + 1094935 + ); + return; + } + + from.SendLocalizedMessage( + 1049513, + GetNameLocalized() + ); // You feel a surge of magic as the scroll enhances your ~1_type~! + + from.Skills[Skill].Base += newValue; + + Effects.PlaySound(from.Location, from.Map, 0x1F7); + Effects.SendTargetParticles(from, 0x373A, 35, 45, 0x00, 0x00, 9502, (EffectLayer)255, 0x100); + Effects.SendTargetParticles(from, 0x376A, 35, 45, 0x00, 0x00, 9502, (EffectLayer)255, 0x100); + + Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = InheritsItem ? 0 : reader.ReadInt(); // Required for SpecialScroll insertion + + LootType = LootType.Cursed; + Insured = false; + + if (Hue == 0x7E) + Hue = 0x490; + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = InheritsItem ? 0 : reader.ReadInt(); // Required for SpecialScroll insertion - - LootType = LootType.Cursed; - Insured = false; - - if (Hue == 0x7E) - Hue = 0x490; - } - } } diff --git a/Projects/UOContent/Items/Special/Special Scrolls/SpecialScroll.cs b/Projects/UOContent/Items/Special/Special Scrolls/SpecialScroll.cs index 0a7ec54c4..de388a49c 100644 --- a/Projects/UOContent/Items/Special/Special Scrolls/SpecialScroll.cs +++ b/Projects/UOContent/Items/Special/Special Scrolls/SpecialScroll.cs @@ -3,162 +3,162 @@ using Server.Network; namespace Server.Items { - public abstract class SpecialScroll : Item - { - public SpecialScroll(SkillName skill, double value) : base(0x14F0) + public abstract class SpecialScroll : Item { - LootType = LootType.Cursed; - Weight = 1.0; + public SpecialScroll(SkillName skill, double value) : base(0x14F0) + { + LootType = LootType.Cursed; + Weight = 1.0; - Skill = skill; - Value = value; + Skill = skill; + Value = value; + } + + public SpecialScroll(Serial serial) : base(serial) + { + } + + /* DO NOT USE! Only used in serialization of special scrolls that originally derived from Item */ + + protected bool InheritsItem { get; private set; } + + public abstract int Message { get; } + public virtual int Title => 0; + public abstract string DefaultTitle { get; } + + [CommandProperty(AccessLevel.GameMaster)] + public SkillName Skill { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public double Value { get; set; } + + public virtual string GetNameLocalized() => $"#{AosSkillBonuses.GetLabel(Skill)}"; + + public virtual string GetName() + { + var index = (int)Skill; + var table = SkillInfo.Table; + + if (index >= 0 && index < table.Length) + return table[index].Name.ToLower(); + return "???"; + } + + public virtual bool CanUse(Mobile from) + { + if (Deleted) + return false; + + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + return false; + } + + return true; + } + + public virtual void Use(Mobile from) + { + } + + public override void OnDoubleClick(Mobile from) + { + if (!CanUse(from)) + return; + + from.CloseGump(); + from.SendGump(new InternalGump(from, this)); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write((int)Skill); + writer.Write(Value); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + Skill = (SkillName)reader.ReadInt(); + Value = reader.ReadDouble(); + break; + } + case 0: + { + InheritsItem = true; + + if (!(this is StatCapScroll)) + Skill = (SkillName)reader.ReadInt(); + else + Skill = SkillName.Alchemy; + + if (this is ScrollofAlacrity) + Value = 0.0; + else if (this is StatCapScroll) + Value = reader.ReadInt(); + else + Value = reader.ReadDouble(); + + break; + } + } + } + + public class InternalGump : Gump + { + private readonly Mobile m_Mobile; + private readonly SpecialScroll m_Scroll; + + public InternalGump(Mobile mobile, SpecialScroll scroll) : base(25, 50) + { + m_Mobile = mobile; + m_Scroll = scroll; + + AddPage(0); + + AddBackground(25, 10, 420, 200, 5054); + + AddImageTiled(33, 20, 401, 181, 2624); + AddAlphaRegion(33, 20, 401, 181); + + AddHtmlLocalized(40, 48, 387, 100, m_Scroll.Message, true, true); + + AddHtmlLocalized(125, 148, 200, 20, 1049478, 0xFFFFFF); // Do you wish to use this scroll? + + AddButton(100, 172, 4005, 4007, 1); + AddHtmlLocalized(135, 172, 120, 20, 1046362, 0xFFFFFF); // Yes + + AddButton(275, 172, 4005, 4007, 0); + AddHtmlLocalized(310, 172, 120, 20, 1046363, 0xFFFFFF); // No + + if (m_Scroll.Title != 0) + AddHtmlLocalized(40, 20, 260, 20, m_Scroll.Title, 0xFFFFFF); + else + AddHtml(40, 20, 260, 20, m_Scroll.DefaultTitle); + + if (m_Scroll is StatCapScroll) + AddHtmlLocalized(310, 20, 120, 20, 1038019, 0xFFFFFF); // Power + else + AddHtmlLocalized(310, 20, 120, 20, AosSkillBonuses.GetLabel(m_Scroll.Skill), 0xFFFFFF); + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (info.ButtonID == 1) + m_Scroll.Use(m_Mobile); + } + } } - - public SpecialScroll(Serial serial) : base(serial) - { - } - - /* DO NOT USE! Only used in serialization of special scrolls that originally derived from Item */ - - protected bool InheritsItem { get; private set; } - - public abstract int Message { get; } - public virtual int Title => 0; - public abstract string DefaultTitle { get; } - - [CommandProperty(AccessLevel.GameMaster)] - public SkillName Skill { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public double Value { get; set; } - - public virtual string GetNameLocalized() => $"#{AosSkillBonuses.GetLabel(Skill)}"; - - public virtual string GetName() - { - int index = (int)Skill; - SkillInfo[] table = SkillInfo.Table; - - if (index >= 0 && index < table.Length) - return table[index].Name.ToLower(); - return "???"; - } - - public virtual bool CanUse(Mobile from) - { - if (Deleted) - return false; - - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - return false; - } - - return true; - } - - public virtual void Use(Mobile from) - { - } - - public override void OnDoubleClick(Mobile from) - { - if (!CanUse(from)) - return; - - from.CloseGump(); - from.SendGump(new InternalGump(from, this)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write((int)Skill); - writer.Write(Value); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - Skill = (SkillName)reader.ReadInt(); - Value = reader.ReadDouble(); - break; - } - case 0: - { - InheritsItem = true; - - if (!(this is StatCapScroll)) - Skill = (SkillName)reader.ReadInt(); - else - Skill = SkillName.Alchemy; - - if (this is ScrollofAlacrity) - Value = 0.0; - else if (this is StatCapScroll) - Value = reader.ReadInt(); - else - Value = reader.ReadDouble(); - - break; - } - } - } - - public class InternalGump : Gump - { - private readonly Mobile m_Mobile; - private readonly SpecialScroll m_Scroll; - - public InternalGump(Mobile mobile, SpecialScroll scroll) : base(25, 50) - { - m_Mobile = mobile; - m_Scroll = scroll; - - AddPage(0); - - AddBackground(25, 10, 420, 200, 5054); - - AddImageTiled(33, 20, 401, 181, 2624); - AddAlphaRegion(33, 20, 401, 181); - - AddHtmlLocalized(40, 48, 387, 100, m_Scroll.Message, true, true); - - AddHtmlLocalized(125, 148, 200, 20, 1049478, 0xFFFFFF); // Do you wish to use this scroll? - - AddButton(100, 172, 4005, 4007, 1); - AddHtmlLocalized(135, 172, 120, 20, 1046362, 0xFFFFFF); // Yes - - AddButton(275, 172, 4005, 4007, 0); - AddHtmlLocalized(310, 172, 120, 20, 1046363, 0xFFFFFF); // No - - if (m_Scroll.Title != 0) - AddHtmlLocalized(40, 20, 260, 20, m_Scroll.Title, 0xFFFFFF); - else - AddHtml(40, 20, 260, 20, m_Scroll.DefaultTitle); - - if (m_Scroll is StatCapScroll) - AddHtmlLocalized(310, 20, 120, 20, 1038019, 0xFFFFFF); // Power - else - AddHtmlLocalized(310, 20, 120, 20, AosSkillBonuses.GetLabel(m_Scroll.Skill), 0xFFFFFF); - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (info.ButtonID == 1) - m_Scroll.Use(m_Mobile); - } - } - } } diff --git a/Projects/UOContent/Items/Special/Special Scrolls/StatScroll.cs b/Projects/UOContent/Items/Special/Special Scrolls/StatScroll.cs index b82cffda2..6d547d4ff 100644 --- a/Projects/UOContent/Items/Special/Special Scrolls/StatScroll.cs +++ b/Projects/UOContent/Items/Special/Special Scrolls/StatScroll.cs @@ -2,133 +2,183 @@ using Server.Mobiles; namespace Server.Items { - public class StatCapScroll : SpecialScroll - { - [Constructible] - public StatCapScroll(int value = 105) : base(SkillName.Alchemy, value) => Hue = 0x481; - - public StatCapScroll(Serial serial) : base(serial) + public class StatCapScroll : SpecialScroll { - } + [Constructible] + public StatCapScroll(int value = 105) : base(SkillName.Alchemy, value) => Hue = 0x481; - /* Using a scroll increases the maximum amount of a specific skill or your maximum statistics. - * When used, the effect is not immediately seen without a gain of points with that skill or statistics. - * You can view your maximum skill values in your skills window. - * You can view your maximum statistic value in your statistics window. - */ - public override int Message => - 1049469; + public StatCapScroll(Serial serial) : base(serial) + { + } - public override int Title - { - get - { - int level = ((int)Value - 230) / 5; - - /* Wonderous Scroll (+5 Maximum Stats): OR - * Exalted Scroll (+10 Maximum Stats): OR - * Mythical Scroll (+15 Maximum Stats): OR - * Legendary Scroll (+20 Maximum Stats): OR - * Ultimate Scroll (+25 Maximum Stats): + /* Using a scroll increases the maximum amount of a specific skill or your maximum statistics. + * When used, the effect is not immediately seen without a gain of points with that skill or statistics. + * You can view your maximum skill values in your skills window. + * You can view your maximum statistic value in your statistics window. */ - if (level >= 0 && level <= 4 && Value % 5 == 0) - return 1049458 + level; + public override int Message => + 1049469; - return 0; - } + public override int Title + { + get + { + var level = ((int)Value - 230) / 5; + + /* Wonderous Scroll (+5 Maximum Stats): OR + * Exalted Scroll (+10 Maximum Stats): OR + * Mythical Scroll (+15 Maximum Stats): OR + * Legendary Scroll (+20 Maximum Stats): OR + * Ultimate Scroll (+25 Maximum Stats): + */ + if (level >= 0 && level <= 4 && Value % 5 == 0) + return 1049458 + level; + + return 0; + } + } + + public override string DefaultTitle => + $"Power Scroll ({((int)Value - 225 >= 0 ? "+" : "")}{(int)Value - 225} Maximum Stats):"; + + public override void AddNameProperty(ObjectPropertyList list) + { + var level = ((int)Value - 230) / 5; + + if (level >= 0 && level <= 4 && (int)Value % 5 == 0) + /* a wonderous scroll of ~1_type~ (+5 Maximum Stats) OR + * an exalted scroll of ~1_type~ (+10 Maximum Stats) OR + * a mythical scroll of ~1_type~ (+15 Maximum Stats) OR + * a legendary scroll of ~1_type~ (+20 Maximum Stats) OR + * an ultimate scroll of ~1_type~ (+25 Maximum Stats) + */ + list.Add(1049463 + level, "#1049476"); + else + list.Add("a scroll of power ({0}{1} Maximum Stats)", Value - 225 >= 0 ? "+" : "", Value - 225); + } + + public override void OnSingleClick(Mobile from) + { + var level = ((int)Value - 230) / 5; + + if (level >= 0 && level <= 4 && (int)Value % 5 == 0) + LabelTo(from, 1049463 + level, "#1049476"); + else + LabelTo(from, "a scroll of power ({0}{1} Maximum Stats)", Value - 225 >= 0 ? "+" : "", Value - 225); + } + + public override bool CanUse(Mobile from) + { + if (!base.CanUse(from)) + return false; + + var newValue = (int)Value; + + if (from is PlayerMobile mobile && mobile.HasStatReward) + newValue += 5; + + if (from.StatCap >= newValue) + { + from.SendLocalizedMessage(1049510); // Your stats are too high for this power scroll. + return false; + } + + return true; + } + + public override void Use(Mobile from) + { + if (!CanUse(from)) + return; + + from.SendLocalizedMessage(1049512); // You feel a surge of magic as the scroll enhances your powers! + + if (from is PlayerMobile mobile && mobile.HasStatReward) + mobile.StatCap = (int)Value + 5; + else + from.StatCap = (int)Value; + + Effects.SendLocationParticles( + EffectItem.Create(from.Location, from.Map, EffectItem.DefaultDuration), + 0, + 0, + 0, + 0, + 0, + 5060, + 0 + ); + Effects.PlaySound(from.Location, from.Map, 0x243); + + Effects.SendMovingParticles( + new Entity(Serial.Zero, new Point3D(from.X - 6, from.Y - 6, from.Z + 15), from.Map), + from, + 0x36D4, + 7, + 0, + false, + true, + 0x497, + 0, + 9502, + 1, + 0, + (EffectLayer)255, + 0x100 + ); + Effects.SendMovingParticles( + new Entity(Serial.Zero, new Point3D(from.X - 4, from.Y - 6, from.Z + 15), from.Map), + from, + 0x36D4, + 7, + 0, + false, + true, + 0x497, + 0, + 9502, + 1, + 0, + (EffectLayer)255, + 0x100 + ); + Effects.SendMovingParticles( + new Entity(Serial.Zero, new Point3D(from.X - 6, from.Y - 4, from.Z + 15), from.Map), + from, + 0x36D4, + 7, + 0, + false, + true, + 0x497, + 0, + 9502, + 1, + 0, + (EffectLayer)255, + 0x100 + ); + + Effects.SendTargetParticles(from, 0x375A, 35, 90, 0x00, 0x00, 9502, (EffectLayer)255, 0x100); + + Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = InheritsItem ? 0 : reader.ReadInt(); // Required for SpecialScroll insertion + + LootType = LootType.Cursed; + Insured = false; + } } - - public override string DefaultTitle => - $"Power Scroll ({((int)Value - 225 >= 0 ? "+" : "")}{(int)Value - 225} Maximum Stats):"; - - public override void AddNameProperty(ObjectPropertyList list) - { - int level = ((int)Value - 230) / 5; - - if (level >= 0 && level <= 4 && (int)Value % 5 == 0) - /* a wonderous scroll of ~1_type~ (+5 Maximum Stats) OR - * an exalted scroll of ~1_type~ (+10 Maximum Stats) OR - * a mythical scroll of ~1_type~ (+15 Maximum Stats) OR - * a legendary scroll of ~1_type~ (+20 Maximum Stats) OR - * an ultimate scroll of ~1_type~ (+25 Maximum Stats) - */ - list.Add(1049463 + level, "#1049476"); - else - list.Add("a scroll of power ({0}{1} Maximum Stats)", Value - 225 >= 0 ? "+" : "", Value - 225); - } - - public override void OnSingleClick(Mobile from) - { - int level = ((int)Value - 230) / 5; - - if (level >= 0 && level <= 4 && (int)Value % 5 == 0) - LabelTo(from, 1049463 + level, "#1049476"); - else - LabelTo(from, "a scroll of power ({0}{1} Maximum Stats)", Value - 225 >= 0 ? "+" : "", Value - 225); - } - - public override bool CanUse(Mobile from) - { - if (!base.CanUse(from)) - return false; - - int newValue = (int)Value; - - if (from is PlayerMobile mobile && mobile.HasStatReward) - newValue += 5; - - if (from.StatCap >= newValue) - { - from.SendLocalizedMessage(1049510); // Your stats are too high for this power scroll. - return false; - } - - return true; - } - - public override void Use(Mobile from) - { - if (!CanUse(from)) - return; - - from.SendLocalizedMessage(1049512); // You feel a surge of magic as the scroll enhances your powers! - - if (from is PlayerMobile mobile && mobile.HasStatReward) - mobile.StatCap = (int)Value + 5; - else - from.StatCap = (int)Value; - - Effects.SendLocationParticles(EffectItem.Create(from.Location, from.Map, EffectItem.DefaultDuration), 0, 0, 0, 0, - 0, 5060, 0); - Effects.PlaySound(from.Location, from.Map, 0x243); - - Effects.SendMovingParticles(new Entity(Serial.Zero, new Point3D(from.X - 6, from.Y - 6, from.Z + 15), from.Map), - from, 0x36D4, 7, 0, false, true, 0x497, 0, 9502, 1, 0, (EffectLayer)255, 0x100); - Effects.SendMovingParticles(new Entity(Serial.Zero, new Point3D(from.X - 4, from.Y - 6, from.Z + 15), from.Map), - from, 0x36D4, 7, 0, false, true, 0x497, 0, 9502, 1, 0, (EffectLayer)255, 0x100); - Effects.SendMovingParticles(new Entity(Serial.Zero, new Point3D(from.X - 6, from.Y - 4, from.Z + 15), from.Map), - from, 0x36D4, 7, 0, false, true, 0x497, 0, 9502, 1, 0, (EffectLayer)255, 0x100); - - Effects.SendTargetParticles(from, 0x375A, 35, 90, 0x00, 0x00, 9502, (EffectLayer)255, 0x100); - - Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = InheritsItem ? 0 : reader.ReadInt(); // Required for SpecialScroll insertion - - LootType = LootType.Cursed; - Insured = false; - } - } } diff --git a/Projects/UOContent/Items/Special/Valentines/2007/RedVelvetGiftBox.cs b/Projects/UOContent/Items/Special/Valentines/2007/RedVelvetGiftBox.cs index 487d2048a..c16a400de 100644 --- a/Projects/UOContent/Items/Special/Valentines/2007/RedVelvetGiftBox.cs +++ b/Projects/UOContent/Items/Special/Valentines/2007/RedVelvetGiftBox.cs @@ -5,53 +5,53 @@ namespace Server.Items { - public class RedVelvetGiftBox : BaseContainer - { - [Constructible] - public RedVelvetGiftBox(bool fill = false) - : base(0xE7A) + public class RedVelvetGiftBox : BaseContainer { - Hue = 0x20; - - if (fill) - { - for (int i = 0; i < 5; i++) + [Constructible] + public RedVelvetGiftBox(bool fill = false) + : base(0xE7A) { - AddToBox(new ValentinesCardSouth(), new Point3D(60 + i * 10, 47, 0)); - AddToBox(new ValentinesCardEast(), new Point3D(20 + i * 10, 72, 0)); + Hue = 0x20; + + if (fill) + { + for (var i = 0; i < 5; i++) + { + AddToBox(new ValentinesCardSouth(), new Point3D(60 + i * 10, 47, 0)); + AddToBox(new ValentinesCardEast(), new Point3D(20 + i * 10, 72, 0)); + } + + AddToBox(new Bacon(), new Point3D(90, 85, 0)); + AddToBox(new RoseInAVase(), new Point3D(130, 55, 0)); + } } - AddToBox(new Bacon(), new Point3D(90, 85, 0)); - AddToBox(new RoseInAVase(), new Point3D(130, 55, 0)); - } + public RedVelvetGiftBox(Serial serial) + : base(serial) + { + } + + public override int DefaultGumpID => 0x3f; + public override int LabelNumber => 1077596; // A Red Velvet Box + + public virtual void AddToBox(Item item, Point3D loc) + { + DropItem(item); + item.Location = loc; + } + + 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 RedVelvetGiftBox(Serial serial) - : base(serial) - { - } - - public override int DefaultGumpID => 0x3f; - public override int LabelNumber => 1077596; // A Red Velvet Box - - public virtual void AddToBox(Item item, Point3D loc) - { - DropItem(item); - item.Location = loc; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/Valentines/2007/RoseInAVase.cs b/Projects/UOContent/Items/Special/Valentines/2007/RoseInAVase.cs index 68d66cefd..5b44bd7b9 100644 --- a/Projects/UOContent/Items/Special/Valentines/2007/RoseInAVase.cs +++ b/Projects/UOContent/Items/Special/Valentines/2007/RoseInAVase.cs @@ -1,34 +1,34 @@ namespace Server.Items { - public class RoseInAVase : Item /* TODO: when dye tub changes are implemented, furny dyable this */ - { - [Constructible] - public RoseInAVase() - : base(0x0EB0) + public class RoseInAVase : Item /* TODO: when dye tub changes are implemented, furny dyable this */ { - Hue = 0x20; - LootType = LootType.Blessed; + [Constructible] + public RoseInAVase() + : base(0x0EB0) + { + Hue = 0x20; + LootType = LootType.Blessed; + } + + public RoseInAVase(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1023760; // A Rose in a Vase 1023760 + + 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 RoseInAVase(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1023760; // A Rose in a Vase 1023760 - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Valentines/2007/ValentinesCard.cs b/Projects/UOContent/Items/Special/Valentines/2007/ValentinesCard.cs index 4a3316296..dba0fbedf 100644 --- a/Projects/UOContent/Items/Special/Valentines/2007/ValentinesCard.cs +++ b/Projects/UOContent/Items/Special/Valentines/2007/ValentinesCard.cs @@ -3,195 +3,199 @@ using Server.Targeting; namespace Server.Items { - public class ValentinesCard : Item - { - private static readonly string Unsigned = "___"; - private string m_From; - - private int m_LabelNumber; - private string m_To; - - [Constructible] - public ValentinesCard(int itemid) - : base(itemid) + public class ValentinesCard : Item { - LootType = LootType.Blessed; - Hue = Utility.RandomDouble() < .001 ? 0x47E : 0xE8; - m_LabelNumber = Utility.Random(1077589, 5); - } + private static readonly string Unsigned = "___"; + private string m_From; - public ValentinesCard(Serial serial) - : base(serial) - { - } + private int m_LabelNumber; + private string m_To; - public override string DefaultName => "a Valentine's card"; - - [CommandProperty(AccessLevel.GameMaster)] - public virtual string From - { - get => m_From; - set => m_From = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public virtual string To - { - get => m_To; - set => m_To = value; - } - - /* - * Five possible messages to be signed: - * - * To my one true love, ~1_target_player~. Signed: ~2_player~ 1077589 - * You’ve pwnd my heart, ~1_target_player~. Signed: ~2_player~ 1077590 - * Happy Valentine’s Day, ~1_target_player~. Signed: ~2_player~ 1077591 - * Blackrock has driven me crazy... for ~1_target_player~! Signed: ~2_player~ 1077592 - * You light my Candle of Love, ~1_target_player~! Signed: ~2_player~ 1077593 - * - */ - - public override void AddNameProperty(ObjectPropertyList list) - { - list.Add(m_LabelNumber, $"{m_To ?? Unsigned}\t{m_From ?? Unsigned}"); - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - LabelTo(from, m_LabelNumber, - $"{m_To ?? Unsigned}\t{m_From ?? Unsigned}"); - } - - public override void OnDoubleClick(Mobile from) - { - if (m_To == null) - { - if (IsChildOf(from)) + [Constructible] + public ValentinesCard(int itemid) + : base(itemid) { - from.BeginTarget(10, false, TargetFlags.None, OnTarget); - - from.SendLocalizedMessage(1077497); // To whom do you wish to give this card? + LootType = LootType.Blessed; + Hue = Utility.RandomDouble() < .001 ? 0x47E : 0xE8; + m_LabelNumber = Utility.Random(1077589, 5); } - else - { - from.SendLocalizedMessage(1080063); // This must be in your backpack to use it. - } - } - } - public virtual void OnTarget(Mobile from, object targeted) - { - if (!Deleted) - { - if (targeted != null && targeted is Mobile to) + public ValentinesCard(Serial serial) + : base(serial) { - if (to is PlayerMobile) - { - if (to != from) + } + + public override string DefaultName => "a Valentine's card"; + + [CommandProperty(AccessLevel.GameMaster)] + public virtual string From + { + get => m_From; + set => m_From = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public virtual string To + { + get => m_To; + set => m_To = value; + } + + /* + * Five possible messages to be signed: + * + * To my one true love, ~1_target_player~. Signed: ~2_player~ 1077589 + * You’ve pwnd my heart, ~1_target_player~. Signed: ~2_player~ 1077590 + * Happy Valentine’s Day, ~1_target_player~. Signed: ~2_player~ 1077591 + * Blackrock has driven me crazy... for ~1_target_player~! Signed: ~2_player~ 1077592 + * You light my Candle of Love, ~1_target_player~! Signed: ~2_player~ 1077593 + * + */ + + public override void AddNameProperty(ObjectPropertyList list) + { + list.Add(m_LabelNumber, $"{m_To ?? Unsigned}\t{m_From ?? Unsigned}"); + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + LabelTo( + from, + m_LabelNumber, + $"{m_To ?? Unsigned}\t{m_From ?? Unsigned}" + ); + } + + public override void OnDoubleClick(Mobile from) + { + if (m_To == null) { - m_From = from.Name; - m_To = to.Name; - from.SendLocalizedMessage( - 1077498); // You fill out the card. Hopefully the other person actually likes you... - InvalidateProperties(); + if (IsChildOf(from)) + { + from.BeginTarget(10, false, TargetFlags.None, OnTarget); + + from.SendLocalizedMessage(1077497); // To whom do you wish to give this card? + } + else + { + from.SendLocalizedMessage(1080063); // This must be in your backpack to use it. + } } - else - { - from.SendLocalizedMessage(1077495); // You can't give yourself a card, silly! - } - } - else - { - from.SendLocalizedMessage(1077496); // You can't possibly be THAT lonely! - } } - else + + public virtual void OnTarget(Mobile from, object targeted) { - from.SendLocalizedMessage(1077488); // That's not another player! + if (!Deleted) + { + if (targeted != null && targeted is Mobile to) + { + if (to is PlayerMobile) + { + if (to != from) + { + m_From = from.Name; + m_To = to.Name; + from.SendLocalizedMessage( + 1077498 + ); // You fill out the card. Hopefully the other person actually likes you... + InvalidateProperties(); + } + else + { + from.SendLocalizedMessage(1077495); // You can't give yourself a card, silly! + } + } + else + { + from.SendLocalizedMessage(1077496); // You can't possibly be THAT lonely! + } + } + else + { + from.SendLocalizedMessage(1077488); // That's not another player! + } + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + writer.Write(m_LabelNumber); + writer.Write(m_From); + writer.Write(m_To); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + m_LabelNumber = reader.ReadInt(); + m_From = reader.ReadString(); + m_To = reader.ReadString(); + + Utility.Intern(ref m_From); + Utility.Intern(ref m_To); } - } } - public override void Serialize(IGenericWriter writer) + public class ValentinesCardSouth : ValentinesCard { - base.Serialize(writer); + [Constructible] + public ValentinesCardSouth() + : base(0x0EBD) + { + } - writer.Write(0); // version - writer.Write(m_LabelNumber); - writer.Write(m_From); - writer.Write(m_To); + public ValentinesCardSouth(Serial serial) + : base(serial) + { + } + + 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 Deserialize(IGenericReader reader) + public class ValentinesCardEast : ValentinesCard { - base.Deserialize(reader); + [Constructible] + public ValentinesCardEast() + : base(0x0EBE) + { + } - int version = reader.ReadInt(); - m_LabelNumber = reader.ReadInt(); - m_From = reader.ReadString(); - m_To = reader.ReadString(); + public ValentinesCardEast(Serial serial) + : base(serial) + { + } - Utility.Intern(ref m_From); - Utility.Intern(ref m_To); + 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 class ValentinesCardSouth : ValentinesCard - { - [Constructible] - public ValentinesCardSouth() - : base(0x0EBD) - { - } - - public ValentinesCardSouth(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class ValentinesCardEast : ValentinesCard - { - [Constructible] - public ValentinesCardEast() - : base(0x0EBE) - { - } - - public ValentinesCardEast(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/AnkhOfSacrifice.cs b/Projects/UOContent/Items/Special/Veteran Rewards/AnkhOfSacrifice.cs index 930a54941..035fbdaa8 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/AnkhOfSacrifice.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/AnkhOfSacrifice.cs @@ -8,333 +8,339 @@ using Server.Network; namespace Server.Items { - public class AnkhOfSacrificeComponent : AddonComponent - { - public AnkhOfSacrificeComponent(int itemID) : base(itemID) + public class AnkhOfSacrificeComponent : AddonComponent { - } - - public AnkhOfSacrificeComponent(Serial serial) : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - public override int LabelNumber => 1027772; // Ankh of Sacrifice - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (from is PlayerMobile mobile) - list.Add(new LockKarmaEntry(mobile, Addon as AnkhOfSacrificeAddon)); - - list.Add(new ResurrectEntry(from, Addon as AnkhOfSacrificeAddon)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public static void Resurrect(PlayerMobile m, AnkhOfSacrificeAddon ankh) - { - if (m == null) - { - } - else if (!m.InRange(ankh.GetWorldLocation(), 2)) - { - m.SendLocalizedMessage(500446); // That is too far away. - } - else if (m.Alive) - { - m.SendLocalizedMessage(1060197); // You are not dead, and thus cannot be resurrected! - } - else if (m.AnkhNextUse > DateTime.UtcNow) - { - TimeSpan delay = m.AnkhNextUse - DateTime.UtcNow; - - if (delay.TotalMinutes > 0) - m.SendLocalizedMessage(1079265, - Math.Round(delay.TotalMinutes) - .ToString()); // You must wait ~1_minutes~ minutes before you can use this item. - else - m.SendLocalizedMessage(1079263, - Math.Round(delay.TotalSeconds) - .ToString()); // You must wait ~1_seconds~ seconds before you can use this item. - } - else - { - m.CloseGump(); - m.SendGump(new AnkhResurrectGump(m, ResurrectMessage.VirtueShrine)); - } - } - - private class ResurrectEntry : ContextMenuEntry - { - private readonly AnkhOfSacrificeAddon m_Ankh; - private readonly Mobile m_Mobile; - - public ResurrectEntry(Mobile mobile, AnkhOfSacrificeAddon ankh) : base(6195, 2) - { - m_Mobile = mobile; - m_Ankh = ankh; - } - - public override void OnClick() - { - if (m_Ankh?.Deleted != false) - return; - - Resurrect(m_Mobile as PlayerMobile, m_Ankh); - } - } - - private class LockKarmaEntry : ContextMenuEntry - { - private readonly AnkhOfSacrificeAddon m_Ankh; - private readonly PlayerMobile m_Mobile; - - public LockKarmaEntry(PlayerMobile mobile, AnkhOfSacrificeAddon ankh) : base(mobile.KarmaLocked ? 6197 : 6196, 2) - { - m_Mobile = mobile; - m_Ankh = ankh; - } - - public override void OnClick() - { - if (!m_Mobile.InRange(m_Ankh.GetWorldLocation(), 2)) + public AnkhOfSacrificeComponent(int itemID) : base(itemID) { - m_Mobile.SendLocalizedMessage(500446); // That is too far away. } - else + + public AnkhOfSacrificeComponent(Serial serial) : base(serial) { - m_Mobile.KarmaLocked = !m_Mobile.KarmaLocked; - - if (m_Mobile.KarmaLocked) - m_Mobile.SendLocalizedMessage( - 1060192); // Your karma has been locked. Your karma can no longer be raised. - else - m_Mobile.SendLocalizedMessage( - 1060191); // Your karma has been unlocked. Your karma can be raised again. } - } - } - private class AnkhResurrectGump : ResurrectGump - { - public AnkhResurrectGump(Mobile owner, ResurrectMessage msg) : base(owner, owner, msg) - { - } + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + public override int LabelNumber => 1027772; // Ankh of Sacrifice - public override void OnResponse(NetState state, RelayInfo info) - { - Mobile from = state.Mobile; - - if (info.ButtonID == 1 || info.ButtonID == 2) + public override void GetContextMenuEntries(Mobile from, List list) { - if (from.Map?.CanFit(from.Location, 16, false, false) != true) - { - from.SendLocalizedMessage(502391); // Thou can not be resurrected there! - return; - } + base.GetContextMenuEntries(from, list); - if (from is PlayerMobile mobile) mobile.AnkhNextUse = DateTime.UtcNow + TimeSpan.FromHours(1); + if (from is PlayerMobile mobile) + list.Add(new LockKarmaEntry(mobile, Addon as AnkhOfSacrificeAddon)); - base.OnResponse(state, info); + list.Add(new ResurrectEntry(from, Addon as AnkhOfSacrificeAddon)); + } + + 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 static void Resurrect(PlayerMobile m, AnkhOfSacrificeAddon ankh) + { + if (m == null) + { + } + else if (!m.InRange(ankh.GetWorldLocation(), 2)) + { + m.SendLocalizedMessage(500446); // That is too far away. + } + else if (m.Alive) + { + m.SendLocalizedMessage(1060197); // You are not dead, and thus cannot be resurrected! + } + else if (m.AnkhNextUse > DateTime.UtcNow) + { + var delay = m.AnkhNextUse - DateTime.UtcNow; + + if (delay.TotalMinutes > 0) + m.SendLocalizedMessage( + 1079265, + Math.Round(delay.TotalMinutes) + .ToString() + ); // You must wait ~1_minutes~ minutes before you can use this item. + else + m.SendLocalizedMessage( + 1079263, + Math.Round(delay.TotalSeconds) + .ToString() + ); // You must wait ~1_seconds~ seconds before you can use this item. + } + else + { + m.CloseGump(); + m.SendGump(new AnkhResurrectGump(m, ResurrectMessage.VirtueShrine)); + } + } + + private class ResurrectEntry : ContextMenuEntry + { + private readonly AnkhOfSacrificeAddon m_Ankh; + private readonly Mobile m_Mobile; + + public ResurrectEntry(Mobile mobile, AnkhOfSacrificeAddon ankh) : base(6195, 2) + { + m_Mobile = mobile; + m_Ankh = ankh; + } + + public override void OnClick() + { + if (m_Ankh?.Deleted != false) + return; + + Resurrect(m_Mobile as PlayerMobile, m_Ankh); + } + } + + private class LockKarmaEntry : ContextMenuEntry + { + private readonly AnkhOfSacrificeAddon m_Ankh; + private readonly PlayerMobile m_Mobile; + + public LockKarmaEntry(PlayerMobile mobile, AnkhOfSacrificeAddon ankh) : base(mobile.KarmaLocked ? 6197 : 6196, 2) + { + m_Mobile = mobile; + m_Ankh = ankh; + } + + public override void OnClick() + { + if (!m_Mobile.InRange(m_Ankh.GetWorldLocation(), 2)) + { + m_Mobile.SendLocalizedMessage(500446); // That is too far away. + } + else + { + m_Mobile.KarmaLocked = !m_Mobile.KarmaLocked; + + if (m_Mobile.KarmaLocked) + m_Mobile.SendLocalizedMessage( + 1060192 + ); // Your karma has been locked. Your karma can no longer be raised. + else + m_Mobile.SendLocalizedMessage( + 1060191 + ); // Your karma has been unlocked. Your karma can be raised again. + } + } + } + + private class AnkhResurrectGump : ResurrectGump + { + public AnkhResurrectGump(Mobile owner, ResurrectMessage msg) : base(owner, owner, msg) + { + } + + public override void OnResponse(NetState state, RelayInfo info) + { + var from = state.Mobile; + + if (info.ButtonID == 1 || info.ButtonID == 2) + { + if (from.Map?.CanFit(from.Location, 16, false, false) != true) + { + from.SendLocalizedMessage(502391); // Thou can not be resurrected there! + return; + } + + if (from is PlayerMobile mobile) mobile.AnkhNextUse = DateTime.UtcNow + TimeSpan.FromHours(1); + + base.OnResponse(state, info); + } + } } - } } - } - public class AnkhOfSacrificeAddon : BaseAddon, IRewardItem - { - private bool m_IsRewardItem; - - [Constructible] - public AnkhOfSacrificeAddon(bool east) + public class AnkhOfSacrificeAddon : BaseAddon, IRewardItem { - if (east) - { - AddComponent(new AnkhOfSacrificeComponent(0x1D98), 0, 0, 0); - AddComponent(new AnkhOfSacrificeComponent(0x1D97), 0, 1, 0); - AddComponent(new AnkhOfSacrificeComponent(0x1CD6), 1, 0, 0); - AddComponent(new AnkhOfSacrificeComponent(0x1CD4), 1, 1, 0); - AddComponent(new AnkhOfSacrificeComponent(0x1CD0), 2, 0, 0); - AddComponent(new AnkhOfSacrificeComponent(0x1CCE), 2, 1, 0); - } - else - { - AddComponent(new AnkhOfSacrificeComponent(0x1E5D), 0, 0, 0); - AddComponent(new AnkhOfSacrificeComponent(0x1E5C), 1, 0, 0); - AddComponent(new AnkhOfSacrificeComponent(0x1CD2), 0, 1, 0); - AddComponent(new AnkhOfSacrificeComponent(0x1CD8), 1, 1, 0); - AddComponent(new AnkhOfSacrificeComponent(0x1CCD), 0, 2, 0); - AddComponent(new AnkhOfSacrificeComponent(0x1CCE), 1, 2, 0); - } + private bool m_IsRewardItem; + + [Constructible] + public AnkhOfSacrificeAddon(bool east) + { + if (east) + { + AddComponent(new AnkhOfSacrificeComponent(0x1D98), 0, 0, 0); + AddComponent(new AnkhOfSacrificeComponent(0x1D97), 0, 1, 0); + AddComponent(new AnkhOfSacrificeComponent(0x1CD6), 1, 0, 0); + AddComponent(new AnkhOfSacrificeComponent(0x1CD4), 1, 1, 0); + AddComponent(new AnkhOfSacrificeComponent(0x1CD0), 2, 0, 0); + AddComponent(new AnkhOfSacrificeComponent(0x1CCE), 2, 1, 0); + } + else + { + AddComponent(new AnkhOfSacrificeComponent(0x1E5D), 0, 0, 0); + AddComponent(new AnkhOfSacrificeComponent(0x1E5C), 1, 0, 0); + AddComponent(new AnkhOfSacrificeComponent(0x1CD2), 0, 1, 0); + AddComponent(new AnkhOfSacrificeComponent(0x1CD8), 1, 1, 0); + AddComponent(new AnkhOfSacrificeComponent(0x1CCD), 0, 2, 0); + AddComponent(new AnkhOfSacrificeComponent(0x1CCE), 1, 2, 0); + } + } + + public AnkhOfSacrificeAddon(Serial serial) : base(serial) + { + } + + public override bool HandlesOnMovement => true; + + public override BaseAddonDeed Deed + { + get + { + var deed = new AnkhOfSacrificeDeed(); + deed.IsRewardItem = m_IsRewardItem; + + return deed; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (!m.Alive && Utility.InRange(Location, m.Location, 1) && !Utility.InRange(Location, oldLocation, 1)) + AnkhOfSacrificeComponent.Resurrect(m as PlayerMobile, this); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + } } - public AnkhOfSacrificeAddon(Serial serial) : base(serial) + public class AnkhOfSacrificeDeed : BaseAddonDeed, IRewardItem, IRewardOption { + private bool m_East; + private bool m_IsRewardItem; + + [Constructible] + public AnkhOfSacrificeDeed(bool isRewardItem = false) + { + LootType = LootType.Blessed; + + m_IsRewardItem = isRewardItem; + } + + public AnkhOfSacrificeDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1080397; // Deed For An Ankh Of Sacrifice + + public override BaseAddon Addon + { + get + { + var addon = new AnkhOfSacrificeAddon(m_East); + addon.IsRewardItem = m_IsRewardItem; + + return addon; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public void GetOptions(RewardOptionList list) + { + list.Add(1, 1080398); // Ankh of Sacrifice South + list.Add(2, 1080399); // Ankh of Sacrifice East + } + + public void OnOptionSelected(Mobile from, int option) + { + m_East = option switch + { + 1 => false, + 2 => true, + _ => m_East + }; + + if (!Deleted) + base.OnDoubleClick(from); + } + + public override void OnDoubleClick(Mobile from) + { + if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) + return; + + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new RewardOptionGump(this)); + } + else + { + from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_IsRewardItem) + list.Add(1080457); // 10th Year Veteran Reward + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + } } - - public override bool HandlesOnMovement => true; - - public override BaseAddonDeed Deed - { - get - { - AnkhOfSacrificeDeed deed = new AnkhOfSacrificeDeed(); - deed.IsRewardItem = m_IsRewardItem; - - return deed; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (!m.Alive && Utility.InRange(Location, m.Location, 1) && !Utility.InRange(Location, oldLocation, 1)) - AnkhOfSacrificeComponent.Resurrect(m as PlayerMobile, this); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - } - } - - public class AnkhOfSacrificeDeed : BaseAddonDeed, IRewardItem, IRewardOption - { - private bool m_East; - private bool m_IsRewardItem; - - [Constructible] - public AnkhOfSacrificeDeed(bool isRewardItem = false) - { - LootType = LootType.Blessed; - - m_IsRewardItem = isRewardItem; - } - - public AnkhOfSacrificeDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1080397; // Deed For An Ankh Of Sacrifice - - public override BaseAddon Addon - { - get - { - AnkhOfSacrificeAddon addon = new AnkhOfSacrificeAddon(m_East); - addon.IsRewardItem = m_IsRewardItem; - - return addon; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public void GetOptions(RewardOptionList list) - { - list.Add(1, 1080398); // Ankh of Sacrifice South - list.Add(2, 1080399); // Ankh of Sacrifice East - } - - public void OnOptionSelected(Mobile from, int option) - { - m_East = option switch - { - 1 => false, - 2 => true, - _ => m_East - }; - - if (!Deleted) - base.OnDoubleClick(from); - } - - public override void OnDoubleClick(Mobile from) - { - if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) - return; - - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new RewardOptionGump(this)); - } - else - { - from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_IsRewardItem) - list.Add(1080457); // 10th Year Veteran Reward - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - } - } } diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/Banner.cs b/Projects/UOContent/Items/Special/Veteran Rewards/Banner.cs index c03093e4b..e02b37d8f 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/Banner.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/Banner.cs @@ -6,393 +6,394 @@ using Server.Targeting; namespace Server.Items { - public class Banner : Item, IAddon, IDyable, IRewardItem - { - private bool m_IsRewardItem; - - [Constructible] - public Banner(int itemID) : base(itemID) + public class Banner : Item, IAddon, IDyable, IRewardItem { - LootType = LootType.Blessed; - Movable = false; - } + private bool m_IsRewardItem; - public Banner(Serial serial) : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public bool FacingSouth => (ItemID & 0x1) == 0; - - public Item Deed - { - get - { - BannerDeed deed = new BannerDeed(); - deed.IsRewardItem = m_IsRewardItem; - - return deed; - } - } - - public bool CouldFit(IPoint3D p, Map map) - { - if (map?.CanFit(p.X, p.Y, p.Z, ItemData.Height) != true) - return false; - - if (FacingSouth) - return BaseAddon.IsWall(p.X, p.Y - 1, p.Z, map); // north wall - return BaseAddon.IsWall(p.X - 1, p.Y, p.Z, map); // west wall - } - - public bool Dye(Mobile from, DyeTub sender) - { - if (Deleted) - return false; - - Hue = sender.DyedHue; - - return true; - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Core.ML && m_IsRewardItem) - list.Add(1076218); // 2nd Year Veteran Reward - } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(Location, 2)) - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (house?.IsOwner(from) == true) + [Constructible] + public Banner(int itemID) : base(itemID) { - from.CloseGump(); - from.SendGump(new RewardDemolitionGump(this, 1018318)); // Do you wish to re-deed this banner? + LootType = LootType.Blessed; + Movable = false; } - else + + public Banner(Serial serial) : base(serial) { - from.SendLocalizedMessage( - 1018330); // You can only re-deed a banner if you placed it or you are the owner of the house. } - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override bool ForceShowProperties => ObjectPropertyList.Enabled; - writer.WriteEncodedInt(0); // version + public bool FacingSouth => (ItemID & 0x1) == 0; - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - } - } - - public class BannerDeed : Item, IRewardItem - { - private bool m_IsRewardItem; - - [Constructible] - public BannerDeed() : base(0x14F0) - { - LootType = LootType.Blessed; - Weight = 1.0; - } - - public BannerDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041007; // a banner deed - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_IsRewardItem) - list.Add(1076218); // 2nd Year Veteran Reward - } - - public override void OnDoubleClick(Mobile from) - { - if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) - return; - - if (IsChildOf(from.Backpack)) - { - BaseHouse house = BaseHouse.FindHouseAt(from); - - if (house?.IsOwner(from) == true) + public Item Deed { - from.CloseGump(); - from.SendGump(new InternalGump(this)); - } - else - { - from.SendLocalizedMessage(502092); // You must be in your house to do this. - } - } - else - { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - } - - private class InternalGump : Gump - { - public const int Start = 0x15AE; - public const int End = 0x15F4; - - private readonly BannerDeed m_Banner; - - public InternalGump(BannerDeed banner) : base(100, 200) - { - m_Banner = banner; - - Closable = true; - Disposable = true; - Draggable = true; - Resizable = false; - - AddPage(0); - - AddBackground(25, 0, 520, 230, 0xA28); - AddLabel(70, 12, 0x3E3, "Choose a Banner:"); - - int itemID = Start; - - for (int i = 1; i <= 4; i++) - { - AddPage(i); - - for (int j = 0; j < 8; j++, itemID += 2) - { - AddItem(50 + 60 * j, 70, itemID); - AddButton(50 + 60 * j, 50, 0x845, 0x846, itemID); - } - - if (i > 1) - AddButton(75, 198, 0x8AF, 0x8AF, 0, GumpButtonType.Page, i - 1); - - if (i < 4) - AddButton(475, 198, 0x8B0, 0x8B0, 0, GumpButtonType.Page, i + 1); - } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Banner?.Deleted != false) - return; - - Mobile m = sender.Mobile; - - if (info.ButtonID < Start || info.ButtonID > End || (info.ButtonID & 0x1) != 0) return; - - m.SendLocalizedMessage(1042037); // Where would you like to place this banner? - m.Target = new InternalTarget(m_Banner, info.ButtonID); - } - } - - private class InternalTarget : Target - { - private readonly BannerDeed m_Banner; - private readonly int m_ItemID; - - public InternalTarget(BannerDeed banner, int itemID) : base(-1, true, TargetFlags.None) - { - m_Banner = banner; - m_ItemID = itemID; - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Banner?.Deleted != false) - return; - - if (m_Banner.IsChildOf(from.Backpack)) - { - BaseHouse house = BaseHouse.FindHouseAt(from); - - if (house?.IsOwner(from) == true) - { - IPoint3D p = targeted as IPoint3D; - Map map = from.Map; - - if (p == null || map == null) - return; - - Point3D p3d = new Point3D(p); - ItemData id = TileData.ItemTable[m_ItemID & TileData.MaxItemValue]; - - if (map.CanFit(p3d, id.Height)) + get { - house = BaseHouse.FindHouseAt(p3d, map, id.Height); + var deed = new BannerDeed(); + deed.IsRewardItem = m_IsRewardItem; - if (house?.IsOwner(from) == true) - { - bool north = BaseAddon.IsWall(p3d.X, p3d.Y - 1, p3d.Z, map); - bool west = BaseAddon.IsWall(p3d.X - 1, p3d.Y, p3d.Z, map); + return deed; + } + } - if (north && west) + public bool CouldFit(IPoint3D p, Map map) + { + if (map?.CanFit(p.X, p.Y, p.Z, ItemData.Height) != true) + return false; + + if (FacingSouth) + return BaseAddon.IsWall(p.X, p.Y - 1, p.Z, map); // north wall + return BaseAddon.IsWall(p.X - 1, p.Y, p.Z, map); // west wall + } + + public bool Dye(Mobile from, DyeTub sender) + { + if (Deleted) + return false; + + Hue = sender.DyedHue; + + return true; + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (Core.ML && m_IsRewardItem) + list.Add(1076218); // 2nd Year Veteran Reward + } + + public override void OnDoubleClick(Mobile from) + { + if (from.InRange(Location, 2)) + { + var house = BaseHouse.FindHouseAt(this); + + if (house?.IsOwner(from) == true) { - from.CloseGump(); - from.SendGump(new FacingGump(m_Banner, m_ItemID, p3d, house)); - } - else if (north || west) - { - Banner banner = new Banner(m_ItemID + (west ? 0 : 1)); - - house.Addons.Add(banner); - - banner.IsRewardItem = m_Banner.IsRewardItem; - banner.MoveToWorld(p3d, map); - - m_Banner.Delete(); + from.CloseGump(); + from.SendGump(new RewardDemolitionGump(this, 1018318)); // Do you wish to re-deed this banner? } else { - from.SendLocalizedMessage(1042039); // The banner must be placed next to a wall. + from.SendLocalizedMessage( + 1018330 + ); // You can only re-deed a banner if you placed it or you are the owner of the house. } - } - else - { - from.SendLocalizedMessage(1042036); // That location is not in your house. - } } else { - from.SendLocalizedMessage(500269); // You cannot build that there. + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. } - } - else - { - from.SendLocalizedMessage(502092); // You must be in your house to do this. - } } - else + + public override void Serialize(IGenericWriter writer) { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); } - } - private class FacingGump : Gump - { - private readonly BannerDeed m_Banner; - private readonly BaseHouse m_House; - private readonly int m_ItemID; - private readonly Point3D m_Location; - - public FacingGump(BannerDeed banner, int itemID, Point3D location, BaseHouse house) : base(150, 50) + public override void Deserialize(IGenericReader reader) { - m_Banner = banner; - m_ItemID = itemID; - m_Location = location; - m_House = house; + base.Deserialize(reader); - Closable = true; - Disposable = true; - Draggable = true; - Resizable = false; + var version = reader.ReadEncodedInt(); - AddPage(0); - - AddBackground(0, 0, 300, 150, 0xA28); - - AddItem(90, 30, itemID + 1); - AddItem(180, 30, itemID); - - AddButton(50, 35, 0x868, 0x869, (int)Buttons.East); - AddButton(145, 35, 0x868, 0x869, (int)Buttons.South); + m_IsRewardItem = reader.ReadBool(); + } + } + + public class BannerDeed : Item, IRewardItem + { + private bool m_IsRewardItem; + + [Constructible] + public BannerDeed() : base(0x14F0) + { + LootType = LootType.Blessed; + Weight = 1.0; + } + + public BannerDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041007; // a banner deed + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_IsRewardItem) + list.Add(1076218); // 2nd Year Veteran Reward + } + + public override void OnDoubleClick(Mobile from) + { + if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) + return; + + if (IsChildOf(from.Backpack)) + { + var house = BaseHouse.FindHouseAt(from); + + if (house?.IsOwner(from) == true) + { + from.CloseGump(); + from.SendGump(new InternalGump(this)); + } + else + { + from.SendLocalizedMessage(502092); // You must be in your house to do this. + } + } + else + { + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + } + + private class InternalGump : Gump + { + public const int Start = 0x15AE; + public const int End = 0x15F4; + + private readonly BannerDeed m_Banner; + + public InternalGump(BannerDeed banner) : base(100, 200) + { + m_Banner = banner; + + Closable = true; + Disposable = true; + Draggable = true; + Resizable = false; + + AddPage(0); + + AddBackground(25, 0, 520, 230, 0xA28); + AddLabel(70, 12, 0x3E3, "Choose a Banner:"); + + var itemID = Start; + + for (var i = 1; i <= 4; i++) + { + AddPage(i); + + for (var j = 0; j < 8; j++, itemID += 2) + { + AddItem(50 + 60 * j, 70, itemID); + AddButton(50 + 60 * j, 50, 0x845, 0x846, itemID); + } + + if (i > 1) + AddButton(75, 198, 0x8AF, 0x8AF, 0, GumpButtonType.Page, i - 1); + + if (i < 4) + AddButton(475, 198, 0x8B0, 0x8B0, 0, GumpButtonType.Page, i + 1); + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Banner?.Deleted != false) + return; + + var m = sender.Mobile; + + if (info.ButtonID < Start || info.ButtonID > End || (info.ButtonID & 0x1) != 0) return; + + m.SendLocalizedMessage(1042037); // Where would you like to place this banner? + m.Target = new InternalTarget(m_Banner, info.ButtonID); + } + } + + private class InternalTarget : Target + { + private readonly BannerDeed m_Banner; + private readonly int m_ItemID; + + public InternalTarget(BannerDeed banner, int itemID) : base(-1, true, TargetFlags.None) + { + m_Banner = banner; + m_ItemID = itemID; + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Banner?.Deleted != false) + return; + + if (m_Banner.IsChildOf(from.Backpack)) + { + var house = BaseHouse.FindHouseAt(from); + + if (house?.IsOwner(from) == true) + { + var p = targeted as IPoint3D; + var map = from.Map; + + if (p == null || map == null) + return; + + var p3d = new Point3D(p); + var id = TileData.ItemTable[m_ItemID & TileData.MaxItemValue]; + + if (map.CanFit(p3d, id.Height)) + { + house = BaseHouse.FindHouseAt(p3d, map, id.Height); + + if (house?.IsOwner(from) == true) + { + var north = BaseAddon.IsWall(p3d.X, p3d.Y - 1, p3d.Z, map); + var west = BaseAddon.IsWall(p3d.X - 1, p3d.Y, p3d.Z, map); + + if (north && west) + { + from.CloseGump(); + from.SendGump(new FacingGump(m_Banner, m_ItemID, p3d, house)); + } + else if (north || west) + { + var banner = new Banner(m_ItemID + (west ? 0 : 1)); + + house.Addons.Add(banner); + + banner.IsRewardItem = m_Banner.IsRewardItem; + banner.MoveToWorld(p3d, map); + + m_Banner.Delete(); + } + else + { + from.SendLocalizedMessage(1042039); // The banner must be placed next to a wall. + } + } + else + { + from.SendLocalizedMessage(1042036); // That location is not in your house. + } + } + else + { + from.SendLocalizedMessage(500269); // You cannot build that there. + } + } + else + { + from.SendLocalizedMessage(502092); // You must be in your house to do this. + } + } + else + { + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. + } + } + + private class FacingGump : Gump + { + private readonly BannerDeed m_Banner; + private readonly BaseHouse m_House; + private readonly int m_ItemID; + private readonly Point3D m_Location; + + public FacingGump(BannerDeed banner, int itemID, Point3D location, BaseHouse house) : base(150, 50) + { + m_Banner = banner; + m_ItemID = itemID; + m_Location = location; + m_House = house; + + Closable = true; + Disposable = true; + Draggable = true; + Resizable = false; + + AddPage(0); + + AddBackground(0, 0, 300, 150, 0xA28); + + AddItem(90, 30, itemID + 1); + AddItem(180, 30, itemID); + + AddButton(50, 35, 0x868, 0x869, (int)Buttons.East); + AddButton(145, 35, 0x868, 0x869, (int)Buttons.South); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Banner?.Deleted != false || m_House == null) + return; + + Banner banner = null; + + if (info.ButtonID == (int)Buttons.East) + banner = new Banner(m_ItemID + 1); + else if (info.ButtonID == (int)Buttons.South) + banner = new Banner(m_ItemID); + + if (banner != null) + { + m_House.Addons.Add(banner); + + banner.IsRewardItem = m_Banner.IsRewardItem; + banner.MoveToWorld(m_Location, sender.Mobile.Map); + + m_Banner.Delete(); + } + } + + private enum Buttons + { + Cancel, + East, + South + } + } } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Banner?.Deleted != false || m_House == null) - return; - - Banner banner = null; - - if (info.ButtonID == (int)Buttons.East) - banner = new Banner(m_ItemID + 1); - else if (info.ButtonID == (int)Buttons.South) - banner = new Banner(m_ItemID); - - if (banner != null) - { - m_House.Addons.Add(banner); - - banner.IsRewardItem = m_Banner.IsRewardItem; - banner.MoveToWorld(m_Location, sender.Mobile.Map); - - m_Banner.Delete(); - } - } - - private enum Buttons - { - Cancel, - East, - South - } - } } - } } diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/BloodyPentagram.cs b/Projects/UOContent/Items/Special/Veteran Rewards/BloodyPentagram.cs index 92ba6c6ca..8cf6436dd 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/BloodyPentagram.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/BloodyPentagram.cs @@ -2,194 +2,194 @@ using Server.Engines.VeteranRewards; namespace Server.Items { - public class BloodyPentagramComponent : AddonComponent - { - public BloodyPentagramComponent(int itemID) : base(itemID) + public class BloodyPentagramComponent : AddonComponent { + public BloodyPentagramComponent(int itemID) : base(itemID) + { + } + + public BloodyPentagramComponent(Serial serial) : base(serial) + { + } + + public override bool DisplayWeight => false; + public override int LabelNumber => 1080279; // Bloody Pentagram + + 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(); + } } - public BloodyPentagramComponent(Serial serial) : base(serial) + public class BloodyPentagramAddon : BaseAddon, IRewardItem { + private bool m_IsRewardItem; + + [Constructible] + public BloodyPentagramAddon() + { + AddComponent(new BloodyPentagramComponent(0x1CF9), 0, 1, 0); + AddComponent(new BloodyPentagramComponent(0x1CF8), 0, 2, 0); + AddComponent(new BloodyPentagramComponent(0x1CF7), 0, 3, 0); + AddComponent(new BloodyPentagramComponent(0x1CF6), 0, 4, 0); + AddComponent(new BloodyPentagramComponent(0x1CF5), 0, 5, 0); + + AddComponent(new BloodyPentagramComponent(0x1CFB), 1, 0, 0); + AddComponent(new BloodyPentagramComponent(0x1CFA), 1, 1, 0); + AddComponent(new BloodyPentagramComponent(0x1D09), 1, 2, 0); + AddComponent(new BloodyPentagramComponent(0x1D08), 1, 3, 0); + AddComponent(new BloodyPentagramComponent(0x1D07), 1, 4, 0); + AddComponent(new BloodyPentagramComponent(0x1CF4), 1, 5, 0); + + AddComponent(new BloodyPentagramComponent(0x1CFC), 2, 0, 0); + AddComponent(new BloodyPentagramComponent(0x1D0A), 2, 1, 0); + AddComponent(new BloodyPentagramComponent(0x1D11), 2, 2, 0); + AddComponent(new BloodyPentagramComponent(0x1D10), 2, 3, 0); + AddComponent(new BloodyPentagramComponent(0x1D06), 2, 4, 0); + AddComponent(new BloodyPentagramComponent(0x1CF3), 2, 5, 0); + + AddComponent(new BloodyPentagramComponent(0x1CFD), 3, 0, 0); + AddComponent(new BloodyPentagramComponent(0x1D0B), 3, 1, 0); + AddComponent(new BloodyPentagramComponent(0x1D12), 3, 2, 0); + AddComponent(new BloodyPentagramComponent(0x1D0F), 3, 3, 0); + AddComponent(new BloodyPentagramComponent(0x1D05), 3, 4, 0); + AddComponent(new BloodyPentagramComponent(0x1CF2), 3, 5, 0); + + AddComponent(new BloodyPentagramComponent(0x1CFE), 4, 0, 0); + AddComponent(new BloodyPentagramComponent(0x1D0C), 4, 1, 0); + AddComponent(new BloodyPentagramComponent(0x1D0D), 4, 2, 0); + AddComponent(new BloodyPentagramComponent(0x1D0E), 4, 3, 0); + AddComponent(new BloodyPentagramComponent(0x1D04), 4, 4, 0); + AddComponent(new BloodyPentagramComponent(0x1CF1), 4, 5, 0); + + AddComponent(new BloodyPentagramComponent(0x1CFF), 5, 0, 0); + AddComponent(new BloodyPentagramComponent(0x1D00), 5, 1, 0); + AddComponent(new BloodyPentagramComponent(0x1D01), 5, 2, 0); + AddComponent(new BloodyPentagramComponent(0x1D02), 5, 3, 0); + AddComponent(new BloodyPentagramComponent(0x1D03), 5, 4, 0); + } + + public BloodyPentagramAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed + { + get + { + var deed = new BloodyPentagramDeed(); + deed.IsRewardItem = m_IsRewardItem; + + return deed; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + } } - public override bool DisplayWeight => false; - public override int LabelNumber => 1080279; // Bloody Pentagram - - public override void Serialize(IGenericWriter writer) + public class BloodyPentagramDeed : BaseAddonDeed, IRewardItem { - base.Serialize(writer); + private bool m_IsRewardItem; - writer.WriteEncodedInt(0); // version + [Constructible] + public BloodyPentagramDeed() => LootType = LootType.Blessed; + + public BloodyPentagramDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1080384; // Bloody Pentagram + + public override BaseAddon Addon + { + get + { + var addon = new BloodyPentagramAddon(); + addon.IsRewardItem = m_IsRewardItem; + + return addon; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void OnDoubleClick(Mobile from) + { + if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) + return; + + base.OnDoubleClick(from); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_IsRewardItem) + list.Add(1076221); // 5th Year Veteran Reward + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class BloodyPentagramAddon : BaseAddon, IRewardItem - { - private bool m_IsRewardItem; - - [Constructible] - public BloodyPentagramAddon() - { - AddComponent(new BloodyPentagramComponent(0x1CF9), 0, 1, 0); - AddComponent(new BloodyPentagramComponent(0x1CF8), 0, 2, 0); - AddComponent(new BloodyPentagramComponent(0x1CF7), 0, 3, 0); - AddComponent(new BloodyPentagramComponent(0x1CF6), 0, 4, 0); - AddComponent(new BloodyPentagramComponent(0x1CF5), 0, 5, 0); - - AddComponent(new BloodyPentagramComponent(0x1CFB), 1, 0, 0); - AddComponent(new BloodyPentagramComponent(0x1CFA), 1, 1, 0); - AddComponent(new BloodyPentagramComponent(0x1D09), 1, 2, 0); - AddComponent(new BloodyPentagramComponent(0x1D08), 1, 3, 0); - AddComponent(new BloodyPentagramComponent(0x1D07), 1, 4, 0); - AddComponent(new BloodyPentagramComponent(0x1CF4), 1, 5, 0); - - AddComponent(new BloodyPentagramComponent(0x1CFC), 2, 0, 0); - AddComponent(new BloodyPentagramComponent(0x1D0A), 2, 1, 0); - AddComponent(new BloodyPentagramComponent(0x1D11), 2, 2, 0); - AddComponent(new BloodyPentagramComponent(0x1D10), 2, 3, 0); - AddComponent(new BloodyPentagramComponent(0x1D06), 2, 4, 0); - AddComponent(new BloodyPentagramComponent(0x1CF3), 2, 5, 0); - - AddComponent(new BloodyPentagramComponent(0x1CFD), 3, 0, 0); - AddComponent(new BloodyPentagramComponent(0x1D0B), 3, 1, 0); - AddComponent(new BloodyPentagramComponent(0x1D12), 3, 2, 0); - AddComponent(new BloodyPentagramComponent(0x1D0F), 3, 3, 0); - AddComponent(new BloodyPentagramComponent(0x1D05), 3, 4, 0); - AddComponent(new BloodyPentagramComponent(0x1CF2), 3, 5, 0); - - AddComponent(new BloodyPentagramComponent(0x1CFE), 4, 0, 0); - AddComponent(new BloodyPentagramComponent(0x1D0C), 4, 1, 0); - AddComponent(new BloodyPentagramComponent(0x1D0D), 4, 2, 0); - AddComponent(new BloodyPentagramComponent(0x1D0E), 4, 3, 0); - AddComponent(new BloodyPentagramComponent(0x1D04), 4, 4, 0); - AddComponent(new BloodyPentagramComponent(0x1CF1), 4, 5, 0); - - AddComponent(new BloodyPentagramComponent(0x1CFF), 5, 0, 0); - AddComponent(new BloodyPentagramComponent(0x1D00), 5, 1, 0); - AddComponent(new BloodyPentagramComponent(0x1D01), 5, 2, 0); - AddComponent(new BloodyPentagramComponent(0x1D02), 5, 3, 0); - AddComponent(new BloodyPentagramComponent(0x1D03), 5, 4, 0); - } - - public BloodyPentagramAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed - { - get - { - BloodyPentagramDeed deed = new BloodyPentagramDeed(); - deed.IsRewardItem = m_IsRewardItem; - - return deed; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - } - } - - public class BloodyPentagramDeed : BaseAddonDeed, IRewardItem - { - private bool m_IsRewardItem; - - [Constructible] - public BloodyPentagramDeed() => LootType = LootType.Blessed; - - public BloodyPentagramDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1080384; // Bloody Pentagram - - public override BaseAddon Addon - { - get - { - BloodyPentagramAddon addon = new BloodyPentagramAddon(); - addon.IsRewardItem = m_IsRewardItem; - - return addon; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void OnDoubleClick(Mobile from) - { - if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) - return; - - base.OnDoubleClick(from); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_IsRewardItem) - list.Add(1076221); // 5th Year Veteran Reward - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - } - } } diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/Brazier.cs b/Projects/UOContent/Items/Special/Veteran Rewards/Brazier.cs index 56a49bc75..fa21830e1 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/Brazier.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/Brazier.cs @@ -5,251 +5,251 @@ using Server.Network; namespace Server.Items { - public class RewardBrazier : Item, IRewardItem - { - private static readonly int[] m_Art = + public class RewardBrazier : Item, IRewardItem { - 0x19AA, 0x19BB - }; - - private Item m_Fire; - - private bool m_IsRewardItem; - - [Constructible] - public RewardBrazier() : this(m_Art.RandomElement()) - { - } - - [Constructible] - public RewardBrazier(int itemID) : base(itemID) - { - LootType = LootType.Blessed; - Weight = 10.0; - } - - public RewardBrazier(Serial serial) : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void OnDelete() - { - TurnOff(); - - base.OnDelete(); - } - - public void TurnOff() - { - if (m_Fire != null) - { - m_Fire.Delete(); - m_Fire = null; - } - } - - public void TurnOn() - { - m_Fire ??= new Item(); - - m_Fire.ItemID = 0x19AB; - m_Fire.Movable = false; - m_Fire.MoveToWorld(new Point3D(X, Y, Z + ItemData.Height + 2), Map); - } - - public override void OnDoubleClick(Mobile from) - { - if (!from.InRange(GetWorldLocation(), 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - else if (IsLockedDown) - { - BaseHouse house = BaseHouse.FindHouseAt(from); - - if (house?.IsCoOwner(from) == true) + private static readonly int[] m_Art = + { + 0x19AA, 0x19BB + }; + + private Item m_Fire; + + private bool m_IsRewardItem; + + [Constructible] + public RewardBrazier() : this(m_Art.RandomElement()) + { + } + + [Constructible] + public RewardBrazier(int itemID) : base(itemID) + { + LootType = LootType.Blessed; + Weight = 10.0; + } + + public RewardBrazier(Serial serial) : base(serial) + { + } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void OnDelete() { - if (m_Fire != null) TurnOff(); - else - TurnOn(); + + base.OnDelete(); } - else + + public void TurnOff() { - from.SendLocalizedMessage(502436); // That is not accessible. + if (m_Fire != null) + { + m_Fire.Delete(); + m_Fire = null; + } } - } - else - { - from.SendLocalizedMessage(502692); // This must be in a house and be locked down to work. - } - } - public override void OnLocationChange(Point3D old) - { - m_Fire?.MoveToWorld(new Point3D(X, Y, Z + ItemData.Height), Map); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_IsRewardItem) - list.Add(1076222); // 6th Year Veteran Reward - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - writer.Write(m_Fire); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - m_Fire = reader.ReadItem(); - } - } - - public class RewardBrazierDeed : Item, IRewardItem - { - private bool m_IsRewardItem; - - [Constructible] - public RewardBrazierDeed() : base(0x14F0) - { - LootType = LootType.Blessed; - Weight = 1.0; - } - - public RewardBrazierDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1080527; // Brazier Deed - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void OnDoubleClick(Mobile from) - { - if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) - return; - - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new InternalGump(this)); - } - else - { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_IsRewardItem) - list.Add(1076222); // 6th Year Veteran Reward - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - } - - private class InternalGump : Gump - { - private readonly RewardBrazierDeed m_Brazier; - - public InternalGump(RewardBrazierDeed brazier) : base(100, 200) - { - m_Brazier = brazier; - - Closable = true; - Disposable = true; - Draggable = true; - Resizable = false; - - AddPage(0); - AddBackground(0, 0, 200, 200, 2600); - - AddPage(1); - AddLabel(45, 15, 0, "Choose a Brazier:"); - - AddItem(40, 75, 0x19AA); - AddButton(55, 50, 0x845, 0x846, 0x19AA); - - AddItem(100, 75, 0x19BB); - AddButton(115, 50, 0x845, 0x846, 0x19BB); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Brazier?.Deleted != false) - return; - - Mobile m = sender.Mobile; - - if (info.ButtonID != 0x19AA && info.ButtonID != 0x19BB) - return; - - RewardBrazier brazier = new RewardBrazier(info.ButtonID) { IsRewardItem = m_Brazier.IsRewardItem }; - - if (!m.PlaceInBackpack(brazier)) + public void TurnOn() { - brazier.Delete(); - m.SendLocalizedMessage(1078837); // Your backpack is full! Please make room and try again. + m_Fire ??= new Item(); + + m_Fire.ItemID = 0x19AB; + m_Fire.Movable = false; + m_Fire.MoveToWorld(new Point3D(X, Y, Z + ItemData.Height + 2), Map); } - else + + public override void OnDoubleClick(Mobile from) { - m_Brazier.Delete(); + if (!from.InRange(GetWorldLocation(), 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + else if (IsLockedDown) + { + var house = BaseHouse.FindHouseAt(from); + + if (house?.IsCoOwner(from) == true) + { + if (m_Fire != null) + TurnOff(); + else + TurnOn(); + } + else + { + from.SendLocalizedMessage(502436); // That is not accessible. + } + } + else + { + from.SendLocalizedMessage(502692); // This must be in a house and be locked down to work. + } + } + + public override void OnLocationChange(Point3D old) + { + m_Fire?.MoveToWorld(new Point3D(X, Y, Z + ItemData.Height), Map); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_IsRewardItem) + list.Add(1076222); // 6th Year Veteran Reward + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + writer.Write(m_Fire); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + m_Fire = reader.ReadItem(); + } + } + + public class RewardBrazierDeed : Item, IRewardItem + { + private bool m_IsRewardItem; + + [Constructible] + public RewardBrazierDeed() : base(0x14F0) + { + LootType = LootType.Blessed; + Weight = 1.0; + } + + public RewardBrazierDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1080527; // Brazier Deed + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void OnDoubleClick(Mobile from) + { + if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) + return; + + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new InternalGump(this)); + } + else + { + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_IsRewardItem) + list.Add(1076222); // 6th Year Veteran Reward + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + } + + private class InternalGump : Gump + { + private readonly RewardBrazierDeed m_Brazier; + + public InternalGump(RewardBrazierDeed brazier) : base(100, 200) + { + m_Brazier = brazier; + + Closable = true; + Disposable = true; + Draggable = true; + Resizable = false; + + AddPage(0); + AddBackground(0, 0, 200, 200, 2600); + + AddPage(1); + AddLabel(45, 15, 0, "Choose a Brazier:"); + + AddItem(40, 75, 0x19AA); + AddButton(55, 50, 0x845, 0x846, 0x19AA); + + AddItem(100, 75, 0x19BB); + AddButton(115, 50, 0x845, 0x846, 0x19BB); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Brazier?.Deleted != false) + return; + + var m = sender.Mobile; + + if (info.ButtonID != 0x19AA && info.ButtonID != 0x19BB) + return; + + var brazier = new RewardBrazier(info.ButtonID) { IsRewardItem = m_Brazier.IsRewardItem }; + + if (!m.PlaceInBackpack(brazier)) + { + brazier.Delete(); + m.SendLocalizedMessage(1078837); // Your backpack is full! Please make room and try again. + } + else + { + m_Brazier.Delete(); + } + } } - } } - } } diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/Cannon.cs b/Projects/UOContent/Items/Special/Veteran Rewards/Cannon.cs index 775422968..62332260c 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/Cannon.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/Cannon.cs @@ -7,457 +7,470 @@ using Server.Targeting; namespace Server.Items { - public class CannonAddonComponent : AddonComponent - { - public CannonAddonComponent(int itemID) : base(itemID) => LootType = LootType.Blessed; - - public CannonAddonComponent(Serial serial) : base(serial) + public class CannonAddonComponent : AddonComponent { - } + public CannonAddonComponent(int itemID) : base(itemID) => LootType = LootType.Blessed; - public override int LabelNumber => 1076157; // Decorative Cannon - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Addon is CannonAddon addon) - { - if (addon.IsRewardItem) - list.Add(1076223); // 7th Year Veteran Reward - - list.Add(1076207, addon.Charges.ToString()); // Remaining Charges: ~1_val~ - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class CannonAddon : BaseAddon - { - private static readonly int[] m_Effects = - { - 0x36B0, 0x3728, 0x3709, 0x36FE - }; - - private int m_Charges; - private bool m_IsRewardItem; - - [Constructible] - public CannonAddon(CannonDirection direction) - { - CannonDirection = direction; - - switch (direction) - { - case CannonDirection.North: - { - AddComponent(new CannonAddonComponent(0xE8D), 0, 0, 0); - AddComponent(new CannonAddonComponent(0xE8C), 0, 1, 0); - AddComponent(new CannonAddonComponent(0xE8B), 0, 2, 0); - - break; - } - case CannonDirection.East: - { - AddComponent(new CannonAddonComponent(0xE96), 0, 0, 0); - AddComponent(new CannonAddonComponent(0xE95), -1, 0, 0); - AddComponent(new CannonAddonComponent(0xE94), -2, 0, 0); - - break; - } - case CannonDirection.South: - { - AddComponent(new CannonAddonComponent(0xE91), 0, 0, 0); - AddComponent(new CannonAddonComponent(0xE92), 0, -1, 0); - AddComponent(new CannonAddonComponent(0xE93), 0, -2, 0); - - break; - } - default: - { - AddComponent(new CannonAddonComponent(0xE8E), 0, 0, 0); - AddComponent(new CannonAddonComponent(0xE8F), 1, 0, 0); - AddComponent(new CannonAddonComponent(0xE90), 2, 0, 0); - - break; - } - } - } - - public CannonAddon(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed - { - get - { - CannonDeed deed = new CannonDeed(); - deed.Charges = m_Charges; - deed.IsRewardItem = m_IsRewardItem; - - return deed; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public CannonDirection CannonDirection { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Charges - { - get => m_Charges; - set - { - m_Charges = value; - - foreach (AddonComponent c in Components) - c.InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - - foreach (AddonComponent c in Components) - c.InvalidateProperties(); - } - } - - public override void OnComponentUsed(AddonComponent c, Mobile from) - { - if (from.InRange(Location, 2)) - { - if (m_Charges > 0) + public CannonAddonComponent(Serial serial) : base(serial) { - from.Target = new InternalTarget(this); } - else + + public override int LabelNumber => 1076157; // Decorative Cannon + + public override void GetProperties(ObjectPropertyList list) { - if (from.Backpack != null) - { - PotionKeg keg = from.Backpack.FindItemByType(); + base.GetProperties(list); - if (Validate(keg) > 0) - from.SendGump(new InternalGump(this, keg)); - else - from.SendLocalizedMessage( - 1076198); // You do not have a full keg of explosion potions needed to recharge the cannon. - } - } - } - else - { - from.SendLocalizedMessage(1076766); // That is too far away. - } - } - - public int Validate(PotionKeg keg) - { - if (keg?.Deleted != false || keg.Held != 100) - return 0; - - return keg.Type switch - { - PotionEffect.ExplosionLesser => 5, - PotionEffect.Explosion => 10, - PotionEffect.ExplosionGreater => 15, - _ => 0 - }; - } - - public void Fill(Mobile from, PotionKeg keg) - { - Charges = Validate(keg); - - if (Charges > 0) - { - keg.Delete(); - from.SendLocalizedMessage(1076199); // Your cannon is recharged. - } - else - { - from.SendLocalizedMessage( - 1076198); // You do not have a full keg of explosion potions needed to recharge the cannon. - } - } - - public void DoFireEffect(IPoint3D target) - { - Map map = Map; - - if (target == null || map == null) - return; - - Effects.PlaySound(target, map, Utility.RandomList(0x11B, 0x11C, 0x11D)); - Effects.SendLocationEffect(target, map, m_Effects.RandomElement(), 16, 1); - - for (int count = Utility.Random(3); count > 0; count--) - { - IPoint3D location = new Point3D(target.X + Utility.RandomMinMax(-1, 1), - target.Y + Utility.RandomMinMax(-1, 1), target.Z); - Effects.SendLocationEffect(location, map, m_Effects.RandomElement(), 16, 1); - } - - Charges -= 1; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write((int)CannonDirection); - writer.Write(m_Charges); - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - CannonDirection = (CannonDirection)reader.ReadInt(); - m_Charges = reader.ReadInt(); - m_IsRewardItem = reader.ReadBool(); - } - - private class InternalTarget : Target - { - private readonly CannonAddon m_Cannon; - - public InternalTarget(CannonAddon cannon) : base(12, true, TargetFlags.None) => m_Cannon = cannon; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Cannon?.Deleted != false) - return; - - if (!(targeted is IPoint3D p)) - return; - - if (from.InLOS(new Point3D(p))) - { - if (!Utility.InRange(new Point3D(p), m_Cannon.Location, 2)) - { - bool allow = false; - - int x = p.X - m_Cannon.X; - int y = p.Y - m_Cannon.Y; - - switch (m_Cannon.CannonDirection) + if (Addon is CannonAddon addon) { - case CannonDirection.North: - if (y < 0 && Math.Abs(x) <= -y / 3) - allow = true; + if (addon.IsRewardItem) + list.Add(1076223); // 7th Year Veteran Reward - break; - case CannonDirection.East: - if (x > 0 && Math.Abs(y) <= x / 3) - allow = true; + list.Add(1076207, addon.Charges.ToString()); // Remaining Charges: ~1_val~ + } + } - break; - case CannonDirection.South: - if (y > 0 && Math.Abs(x) <= y / 3) - allow = true; + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - break; - case CannonDirection.West: - if (x < 0 && Math.Abs(y) <= -x / 3) - allow = true; + writer.Write(0); // version + } - break; + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + } + + public class CannonAddon : BaseAddon + { + private static readonly int[] m_Effects = + { + 0x36B0, 0x3728, 0x3709, 0x36FE + }; + + private int m_Charges; + private bool m_IsRewardItem; + + [Constructible] + public CannonAddon(CannonDirection direction) + { + CannonDirection = direction; + + switch (direction) + { + case CannonDirection.North: + { + AddComponent(new CannonAddonComponent(0xE8D), 0, 0, 0); + AddComponent(new CannonAddonComponent(0xE8C), 0, 1, 0); + AddComponent(new CannonAddonComponent(0xE8B), 0, 2, 0); + + break; + } + case CannonDirection.East: + { + AddComponent(new CannonAddonComponent(0xE96), 0, 0, 0); + AddComponent(new CannonAddonComponent(0xE95), -1, 0, 0); + AddComponent(new CannonAddonComponent(0xE94), -2, 0, 0); + + break; + } + case CannonDirection.South: + { + AddComponent(new CannonAddonComponent(0xE91), 0, 0, 0); + AddComponent(new CannonAddonComponent(0xE92), 0, -1, 0); + AddComponent(new CannonAddonComponent(0xE93), 0, -2, 0); + + break; + } + default: + { + AddComponent(new CannonAddonComponent(0xE8E), 0, 0, 0); + AddComponent(new CannonAddonComponent(0xE8F), 1, 0, 0); + AddComponent(new CannonAddonComponent(0xE90), 2, 0, 0); + + break; + } + } + } + + public CannonAddon(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed + { + get + { + var deed = new CannonDeed(); + deed.Charges = m_Charges; + deed.IsRewardItem = m_IsRewardItem; + + return deed; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public CannonDirection CannonDirection { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Charges + { + get => m_Charges; + set + { + m_Charges = value; + + foreach (var c in Components) + c.InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + + foreach (var c in Components) + c.InvalidateProperties(); + } + } + + public override void OnComponentUsed(AddonComponent c, Mobile from) + { + if (from.InRange(Location, 2)) + { + if (m_Charges > 0) + { + from.Target = new InternalTarget(this); + } + else + { + if (from.Backpack != null) + { + var keg = from.Backpack.FindItemByType(); + + if (Validate(keg) > 0) + from.SendGump(new InternalGump(this, keg)); + else + from.SendLocalizedMessage( + 1076198 + ); // You do not have a full keg of explosion potions needed to recharge the cannon. + } + } + } + else + { + from.SendLocalizedMessage(1076766); // That is too far away. + } + } + + public int Validate(PotionKeg keg) + { + if (keg?.Deleted != false || keg.Held != 100) + return 0; + + return keg.Type switch + { + PotionEffect.ExplosionLesser => 5, + PotionEffect.Explosion => 10, + PotionEffect.ExplosionGreater => 15, + _ => 0 + }; + } + + public void Fill(Mobile from, PotionKeg keg) + { + Charges = Validate(keg); + + if (Charges > 0) + { + keg.Delete(); + from.SendLocalizedMessage(1076199); // Your cannon is recharged. + } + else + { + from.SendLocalizedMessage( + 1076198 + ); // You do not have a full keg of explosion potions needed to recharge the cannon. + } + } + + public void DoFireEffect(IPoint3D target) + { + var map = Map; + + if (target == null || map == null) + return; + + Effects.PlaySound(target, map, Utility.RandomList(0x11B, 0x11C, 0x11D)); + Effects.SendLocationEffect(target, map, m_Effects.RandomElement(), 16, 1); + + for (var count = Utility.Random(3); count > 0; count--) + { + IPoint3D location = new Point3D( + target.X + Utility.RandomMinMax(-1, 1), + target.Y + Utility.RandomMinMax(-1, 1), + target.Z + ); + Effects.SendLocationEffect(location, map, m_Effects.RandomElement(), 16, 1); } - if (allow && Utility.InRange(new Point3D(p), m_Cannon.Location, 14)) - m_Cannon.DoFireEffect(p); - else - from.SendLocalizedMessage(1076203); // Target out of range. - } - else - { - from.SendLocalizedMessage(1076215); // Cannon must be aimed farther away. - } + Charges -= 1; } - else + + public override void Serialize(IGenericWriter writer) { - from.SendLocalizedMessage(1049630); // You cannot see that target! + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write((int)CannonDirection); + writer.Write(m_Charges); + writer.Write(m_IsRewardItem); } - } - protected override void OnTargetOutOfRange(Mobile from, object targeted) - { - from.SendLocalizedMessage(1076203); // Target out of range. - } + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + CannonDirection = (CannonDirection)reader.ReadInt(); + m_Charges = reader.ReadInt(); + m_IsRewardItem = reader.ReadBool(); + } + + private class InternalTarget : Target + { + private readonly CannonAddon m_Cannon; + + public InternalTarget(CannonAddon cannon) : base(12, true, TargetFlags.None) => m_Cannon = cannon; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Cannon?.Deleted != false) + return; + + if (!(targeted is IPoint3D p)) + return; + + if (from.InLOS(new Point3D(p))) + { + if (!Utility.InRange(new Point3D(p), m_Cannon.Location, 2)) + { + var allow = false; + + var x = p.X - m_Cannon.X; + var y = p.Y - m_Cannon.Y; + + switch (m_Cannon.CannonDirection) + { + case CannonDirection.North: + if (y < 0 && Math.Abs(x) <= -y / 3) + allow = true; + + break; + case CannonDirection.East: + if (x > 0 && Math.Abs(y) <= x / 3) + allow = true; + + break; + case CannonDirection.South: + if (y > 0 && Math.Abs(x) <= y / 3) + allow = true; + + break; + case CannonDirection.West: + if (x < 0 && Math.Abs(y) <= -x / 3) + allow = true; + + break; + } + + if (allow && Utility.InRange(new Point3D(p), m_Cannon.Location, 14)) + m_Cannon.DoFireEffect(p); + else + from.SendLocalizedMessage(1076203); // Target out of range. + } + else + { + from.SendLocalizedMessage(1076215); // Cannon must be aimed farther away. + } + } + else + { + from.SendLocalizedMessage(1049630); // You cannot see that target! + } + } + + protected override void OnTargetOutOfRange(Mobile from, object targeted) + { + from.SendLocalizedMessage(1076203); // Target out of range. + } + } + + private class InternalGump : Gump + { + private readonly CannonAddon m_Cannon; + private readonly PotionKeg m_Keg; + + public InternalGump(CannonAddon cannon, PotionKeg keg) : base(50, 50) + { + m_Cannon = cannon; + m_Keg = keg; + + Closable = true; + Disposable = true; + Draggable = true; + Resizable = false; + + AddPage(0); + + AddBackground(0, 0, 291, 133, 0x13BE); + AddImageTiled(5, 5, 280, 100, 0xA40); + + AddHtmlLocalized( + 9, + 9, + 272, + 100, + 1076196, + cannon.Validate(keg).ToString(), + 0x7FFF + ); // You will need a full keg of explosion potions to recharge the cannon. Your keg will provide ~1_CHARGES~ charges. + + AddButton(5, 107, 0xFB1, 0xFB2, (int)Buttons.Cancel); + AddHtmlLocalized(40, 109, 100, 20, 1060051, 0x7FFF); // CANCEL + + AddButton(160, 107, 0xFB7, 0xFB8, (int)Buttons.Recharge); + AddHtmlLocalized(195, 109, 120, 20, 1076197, 0x7FFF); // Recharge + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (m_Cannon?.Deleted == false && info.ButtonID == (int)Buttons.Recharge) + m_Cannon.Fill(state.Mobile, m_Keg); + } + + private enum Buttons + { + Cancel, + Recharge + } + } } - private class InternalGump : Gump + public class CannonDeed : BaseAddonDeed, IRewardItem, IRewardOption { - private readonly CannonAddon m_Cannon; - private readonly PotionKeg m_Keg; + private int m_Charges; - public InternalGump(CannonAddon cannon, PotionKeg keg) : base(50, 50) - { - m_Cannon = cannon; - m_Keg = keg; + private CannonDirection m_Direction; + private bool m_IsRewardItem; - Closable = true; - Disposable = true; - Draggable = true; - Resizable = false; + [Constructible] + public CannonDeed() => LootType = LootType.Blessed; - AddPage(0); + public CannonDeed(Serial serial) : base(serial) + { + } - AddBackground(0, 0, 291, 133, 0x13BE); - AddImageTiled(5, 5, 280, 100, 0xA40); + public override int LabelNumber => 1076195; // A deed for a cannon - AddHtmlLocalized(9, 9, 272, 100, 1076196, cannon.Validate(keg).ToString(), 0x7FFF); // You will need a full keg of explosion potions to recharge the cannon. Your keg will provide ~1_CHARGES~ charges. + public override BaseAddon Addon => new CannonAddon(m_Direction) + { + Charges = m_Charges, + IsRewardItem = m_IsRewardItem + }; - AddButton(5, 107, 0xFB1, 0xFB2, (int)Buttons.Cancel); - AddHtmlLocalized(40, 109, 100, 20, 1060051, 0x7FFF); // CANCEL + [CommandProperty(AccessLevel.GameMaster)] + public int Charges + { + get => m_Charges; + set + { + m_Charges = value; + InvalidateProperties(); + } + } - AddButton(160, 107, 0xFB7, 0xFB8, (int)Buttons.Recharge); - AddHtmlLocalized(195, 109, 120, 20, 1076197, 0x7FFF); // Recharge - } + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } - public override void OnResponse(NetState state, RelayInfo info) - { - if (m_Cannon?.Deleted == false && info.ButtonID == (int)Buttons.Recharge) - m_Cannon.Fill(state.Mobile, m_Keg); - } + public void GetOptions(RewardOptionList list) + { + list.Add((int)CannonDirection.South, 1075386); // South + list.Add((int)CannonDirection.East, 1075387); // East + list.Add((int)CannonDirection.North, 1075389); // North + list.Add((int)CannonDirection.West, 1075390); // West + } - private enum Buttons - { - Cancel, - Recharge - } + public void OnOptionSelected(Mobile from, int option) + { + m_Direction = (CannonDirection)option; + + if (!Deleted) + base.OnDoubleClick(from); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_IsRewardItem) + list.Add(1076223); // 7th Year Veteran Reward + + list.Add(1076207, m_Charges.ToString()); // Remaining Charges: ~1_val~ + } + + public override void OnDoubleClick(Mobile from) + { + if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) + return; + + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new RewardOptionGump(this)); + } + else + { + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_Charges); + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_Charges = reader.ReadInt(); + m_IsRewardItem = reader.ReadBool(); + } } - } - - public class CannonDeed : BaseAddonDeed, IRewardItem, IRewardOption - { - private int m_Charges; - - private CannonDirection m_Direction; - private bool m_IsRewardItem; - - [Constructible] - public CannonDeed() => LootType = LootType.Blessed; - - public CannonDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1076195; // A deed for a cannon - - public override BaseAddon Addon => new CannonAddon(m_Direction) - { - Charges = m_Charges, - IsRewardItem = m_IsRewardItem - }; - - [CommandProperty(AccessLevel.GameMaster)] - public int Charges - { - get => m_Charges; - set - { - m_Charges = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public void GetOptions(RewardOptionList list) - { - list.Add((int)CannonDirection.South, 1075386); // South - list.Add((int)CannonDirection.East, 1075387); // East - list.Add((int)CannonDirection.North, 1075389); // North - list.Add((int)CannonDirection.West, 1075390); // West - } - - public void OnOptionSelected(Mobile from, int option) - { - m_Direction = (CannonDirection)option; - - if (!Deleted) - base.OnDoubleClick(from); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_IsRewardItem) - list.Add(1076223); // 7th Year Veteran Reward - - list.Add(1076207, m_Charges.ToString()); // Remaining Charges: ~1_val~ - } - - public override void OnDoubleClick(Mobile from) - { - if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) - return; - - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new RewardOptionGump(this)); - } - else - { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_Charges); - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_Charges = reader.ReadInt(); - m_IsRewardItem = reader.ReadBool(); - } - } } diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/CommodityDeedBox.cs b/Projects/UOContent/Items/Special/Veteran Rewards/CommodityDeedBox.cs index 5431a0bb3..2d58f99d9 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/CommodityDeedBox.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/CommodityDeedBox.cs @@ -2,70 +2,70 @@ using Server.Engines.VeteranRewards; namespace Server.Items { - [Furniture] - public class CommodityDeedBox : BaseContainer, IRewardItem - { - private bool m_IsRewardItem; - - [Constructible] - public CommodityDeedBox() : base(0x9AA) + [Furniture] + public class CommodityDeedBox : BaseContainer, IRewardItem { - Hue = 0x47; - Weight = 4.0; + private bool m_IsRewardItem; + + [Constructible] + public CommodityDeedBox() : base(0x9AA) + { + Hue = 0x47; + Weight = 4.0; + } + + public CommodityDeedBox(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1080523; // Commodity Deed Box + public override int DefaultGumpID => 0x43; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_IsRewardItem) + list.Add(1076217); // 1st Year Veteran Reward + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + } + + public static CommodityDeedBox Find(Item deed) + { + var parent = deed; + + while (parent != null && !(parent is CommodityDeedBox)) + parent = parent.Parent as Item; + + return parent as CommodityDeedBox; + } } - - public CommodityDeedBox(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1080523; // Commodity Deed Box - public override int DefaultGumpID => 0x43; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_IsRewardItem) - list.Add(1076217); // 1st Year Veteran Reward - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - } - - public static CommodityDeedBox Find(Item deed) - { - Item parent = deed; - - while (parent != null && !(parent is CommodityDeedBox)) - parent = parent.Parent as Item; - - return parent as CommodityDeedBox; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/ContestMiniHouse.cs b/Projects/UOContent/Items/Special/Veteran Rewards/ContestMiniHouse.cs index 586249b13..335e8a7d6 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/ContestMiniHouse.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/ContestMiniHouse.cs @@ -2,137 +2,137 @@ using Server.Engines.VeteranRewards; namespace Server.Items { - public class ContestMiniHouse : MiniHouseAddon - { - private bool m_IsRewardItem; - - [Constructible] - public ContestMiniHouse() : base(MiniHouseType.MalasMountainPass) + public class ContestMiniHouse : MiniHouseAddon { + private bool m_IsRewardItem; + + [Constructible] + public ContestMiniHouse() : base(MiniHouseType.MalasMountainPass) + { + } + + [Constructible] + public ContestMiniHouse(MiniHouseType type) : base(type) + { + } + + public ContestMiniHouse(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed + { + get + { + var deed = new ContestMiniHouseDeed(Type); + deed.IsRewardItem = m_IsRewardItem; + + return deed; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + } } - [Constructible] - public ContestMiniHouse(MiniHouseType type) : base(type) + public class ContestMiniHouseDeed : MiniHouseDeed, IRewardItem { + private bool m_IsRewardItem; + + [Constructible] + public ContestMiniHouseDeed() : base(MiniHouseType.MalasMountainPass) + { + } + + [Constructible] + public ContestMiniHouseDeed(MiniHouseType type) : base(type) + { + } + + public ContestMiniHouseDeed(Serial serial) : base(serial) + { + } + + public override BaseAddon Addon + { + get + { + var addon = new ContestMiniHouse(Type); + addon.IsRewardItem = m_IsRewardItem; + + return addon; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void OnDoubleClick(Mobile from) + { + if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this, new object[] { Type })) + return; + + base.OnDoubleClick(from); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (Core.ML && m_IsRewardItem) + list.Add(1076217); // 1st Year Veteran Reward + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + } } - - public ContestMiniHouse(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed - { - get - { - ContestMiniHouseDeed deed = new ContestMiniHouseDeed(Type); - deed.IsRewardItem = m_IsRewardItem; - - return deed; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - } - } - - public class ContestMiniHouseDeed : MiniHouseDeed, IRewardItem - { - private bool m_IsRewardItem; - - [Constructible] - public ContestMiniHouseDeed() : base(MiniHouseType.MalasMountainPass) - { - } - - [Constructible] - public ContestMiniHouseDeed(MiniHouseType type) : base(type) - { - } - - public ContestMiniHouseDeed(Serial serial) : base(serial) - { - } - - public override BaseAddon Addon - { - get - { - ContestMiniHouse addon = new ContestMiniHouse(Type); - addon.IsRewardItem = m_IsRewardItem; - - return addon; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void OnDoubleClick(Mobile from) - { - if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this, new object[] { Type })) - return; - - base.OnDoubleClick(from); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Core.ML && m_IsRewardItem) - list.Add(1076217); // 1st Year Veteran Reward - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/DecorativeShield.cs b/Projects/UOContent/Items/Special/Veteran Rewards/DecorativeShield.cs index d3eda5087..6c9baab91 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/DecorativeShield.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/DecorativeShield.cs @@ -6,389 +6,390 @@ using Server.Targeting; namespace Server.Items { - public class DecorativeShield : Item, IAddon, IRewardItem - { - private bool m_IsRewardItem; - - [Constructible] - public DecorativeShield(int itemID = 0x156C) : base(itemID) => Movable = false; - - public DecorativeShield(Serial serial) : base(serial) + public class DecorativeShield : Item, IAddon, IRewardItem { - } + private bool m_IsRewardItem; - public override bool ForceShowProperties => ObjectPropertyList.Enabled; + [Constructible] + public DecorativeShield(int itemID = 0x156C) : base(itemID) => Movable = false; - public bool FacingSouth - { - get - { - if (ItemID < 0x1582) - return (ItemID & 0x1) == 0; - - return ItemID <= 0x1585; - } - } - - public Item Deed - { - get - { - DecorativeShieldDeed deed = new DecorativeShieldDeed(); - deed.IsRewardItem = m_IsRewardItem; - - return deed; - } - } - - public bool CouldFit(IPoint3D p, Map map) => - map?.CanFit(p.X, p.Y, p.Z, ItemData.Height) == true && ((FacingSouth - && BaseAddon.IsWall(p.X, p.Y - 1, p.Z, map)) - || BaseAddon.IsWall(p.X - 1, p.Y, p.Z, map)); - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Core.ML && m_IsRewardItem) - list.Add(1076220); // 4th Year Veteran Reward - } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(Location, 2)) - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (house?.IsOwner(from) == true) + public DecorativeShield(Serial serial) : base(serial) { - from.CloseGump(); - from.SendGump(new RewardDemolitionGump(this, 1049783)); // Do you wish to re-deed this decoration? } - else + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + public bool FacingSouth { - from.SendLocalizedMessage( - 1049784); // You can only re-deed this decoration if you are the house owner or originally placed the decoration. + get + { + if (ItemID < 0x1582) + return (ItemID & 0x1) == 0; + + return ItemID <= 0x1585; + } } - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - } - } - - public class DecorativeShieldDeed : Item, IRewardItem - { - private bool m_IsRewardItem; - - [Constructible] - public DecorativeShieldDeed() : base(0x14F0) - { - LootType = LootType.Blessed; - Weight = 1.0; - } - - public DecorativeShieldDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1049771; // deed for a decorative shield wall hanging - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_IsRewardItem) - list.Add(1076220); // 4th Year Veteran Reward - } - - public override void OnDoubleClick(Mobile from) - { - if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) - return; - - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new InternalGump(this)); - } - else - { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - } - - public static int GetWestItemID(int east) - { - return east switch - { - 0x1582 => 0x1635, - 0x1583 => 0x1634, - 0x1584 => 0x1637, - 0x1585 => 0x1636, - _ => east + 1 - }; - } - - private class InternalGump : Gump - { - public const int Start = 0x156C; - public const int End = 0x1585; - private int m_Page; - - private readonly DecorativeShieldDeed m_Shield; - - public InternalGump(DecorativeShieldDeed shield, int page = 1) : base(150, 50) - { - m_Shield = shield; - m_Page = page; - - Closable = true; - Disposable = true; - Draggable = true; - Resizable = false; - - AddPage(0); - - AddBackground(25, 0, 500, 230, 0xA28); - - int itemID = Start; - - for (int i = 1; i <= 2; i++) + public Item Deed { - AddPage(i); + get + { + var deed = new DecorativeShieldDeed(); + deed.IsRewardItem = m_IsRewardItem; - for (int j = 0; j < 9 - i; j++) - { - AddItem(40 + j * 60, 70, itemID); - AddButton(60 + j * 60, 50, 0x845, 0x846, itemID); + return deed; + } + } - if (itemID < 0x1582) - itemID += 2; + public bool CouldFit(IPoint3D p, Map map) => + map?.CanFit(p.X, p.Y, p.Z, ItemData.Height) == true && (FacingSouth + && BaseAddon.IsWall(p.X, p.Y - 1, p.Z, map) + || BaseAddon.IsWall(p.X - 1, p.Y, p.Z, map)); + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (Core.ML && m_IsRewardItem) + list.Add(1076220); // 4th Year Veteran Reward + } + + public override void OnDoubleClick(Mobile from) + { + if (from.InRange(Location, 2)) + { + var house = BaseHouse.FindHouseAt(this); + + if (house?.IsOwner(from) == true) + { + from.CloseGump(); + from.SendGump(new RewardDemolitionGump(this, 1049783)); // Do you wish to re-deed this decoration? + } + else + { + from.SendLocalizedMessage( + 1049784 + ); // You can only re-deed this decoration if you are the house owner or originally placed the decoration. + } + } else - itemID += 1; - } - - switch (i) - { - case 1: - AddButton(455, 198, 0x8B0, 0x8B0, 0, GumpButtonType.Page, 2); - break; - case 2: - AddButton(70, 198, 0x8AF, 0x8AF, 0, GumpButtonType.Page, 1); - break; - } + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } } - } - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Shield?.Deleted != false || info.ButtonID < Start || info.ButtonID > End || - (((info.ButtonID & 0x1) != 0 || info.ButtonID >= 0x1582) && - (info.ButtonID < 0x1582 || info.ButtonID > 0x1585))) - return; + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - sender.Mobile.SendLocalizedMessage(1049780); // Where would you like to place this decoration? - sender.Mobile.Target = new InternalTarget(m_Shield, info.ButtonID); - } + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + } } - private class InternalTarget : Target + public class DecorativeShieldDeed : Item, IRewardItem { - private readonly int m_ItemID; - private readonly DecorativeShieldDeed m_Shield; + private bool m_IsRewardItem; - public InternalTarget(DecorativeShieldDeed shield, int itemID) : base(-1, true, TargetFlags.None) - { - m_Shield = shield; - m_ItemID = itemID; - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Shield?.Deleted != false) - return; - - if (!m_Shield.IsChildOf(from.Backpack)) + [Constructible] + public DecorativeShieldDeed() : base(0x14F0) { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. - return; + LootType = LootType.Blessed; + Weight = 1.0; } - BaseHouse house = BaseHouse.FindHouseAt(from); - - if (house?.IsOwner(from) != true) + public DecorativeShieldDeed(Serial serial) : base(serial) { - from.SendLocalizedMessage(502092); // You must be in your house to do this. - return; } - IPoint3D p = targeted as IPoint3D; - Map map = from.Map; + public override int LabelNumber => 1049771; // deed for a decorative shield wall hanging - if (p == null || map == null) - return; - - Point3D p3d = new Point3D(p); - ItemData id = TileData.ItemTable[m_ItemID & TileData.MaxItemValue]; - - if (!map.CanFit(p3d, id.Height)) + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem { - from.SendLocalizedMessage(500269); // You cannot build that there. - return; + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } } - house = BaseHouse.FindHouseAt(p3d, map, id.Height); - - if (house?.IsOwner(from) != true) + public override void GetProperties(ObjectPropertyList list) { - from.SendLocalizedMessage(1042036); // That location is not in your house. - return; + base.GetProperties(list); + + if (m_IsRewardItem) + list.Add(1076220); // 4th Year Veteran Reward } - bool north = BaseAddon.IsWall(p3d.X, p3d.Y - 1, p3d.Z, map); - bool west = BaseAddon.IsWall(p3d.X - 1, p3d.Y, p3d.Z, map); - - if (north && west) + public override void OnDoubleClick(Mobile from) { - from.CloseGump(); - from.SendGump(new FacingGump(m_Shield, m_ItemID, p3d, house)); - } - else if (north || west) - { - DecorativeShield shield = new DecorativeShield(west ? GetWestItemID(m_ItemID) : m_ItemID); + if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) + return; - house.Addons.Add(shield); - - shield.IsRewardItem = m_Shield.IsRewardItem; - shield.MoveToWorld(p3d, map); - - m_Shield.Delete(); - } - else - { - from.SendLocalizedMessage(1049781); // This decoration must be placed next to a wall. - } - } - - private class FacingGump : Gump - { - private readonly BaseHouse m_House; - private readonly int m_ItemID; - private readonly Point3D m_Location; - private readonly DecorativeShieldDeed m_Shield; - - public FacingGump(DecorativeShieldDeed shield, int itemID, Point3D location, BaseHouse house) : base(150, 50) - { - m_Shield = shield; - m_ItemID = itemID; - m_Location = location; - m_House = house; - - Closable = true; - Disposable = true; - Draggable = true; - Resizable = false; - - AddPage(0); - AddBackground(0, 0, 300, 150, 0xA28); - - AddItem(90, 30, GetWestItemID(itemID)); - AddItem(180, 30, itemID); - - AddButton(50, 35, 0x867, 0x869, (int)Buttons.East); - AddButton(145, 35, 0x867, 0x869, (int)Buttons.South); + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new InternalGump(this)); + } + else + { + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. + } } - public override void OnResponse(NetState sender, RelayInfo info) + public override void Serialize(IGenericWriter writer) { - if (m_Shield?.Deleted != false || m_House == null) - return; + base.Serialize(writer); - DecorativeShield shield = null; + writer.WriteEncodedInt(0); // version - if (info.ButtonID == (int)Buttons.East) - shield = new DecorativeShield(GetWestItemID(m_ItemID)); - if (info.ButtonID == (int)Buttons.South) - shield = new DecorativeShield(m_ItemID); - - if (shield != null) - { - m_House.Addons.Add(shield); - - shield.IsRewardItem = m_Shield.IsRewardItem; - shield.MoveToWorld(m_Location, sender.Mobile.Map); - - m_Shield.Delete(); - } + writer.Write(m_IsRewardItem); } - private enum Buttons + public override void Deserialize(IGenericReader reader) { - Cancel, - South, - East + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + } + + public static int GetWestItemID(int east) + { + return east switch + { + 0x1582 => 0x1635, + 0x1583 => 0x1634, + 0x1584 => 0x1637, + 0x1585 => 0x1636, + _ => east + 1 + }; + } + + private class InternalGump : Gump + { + public const int Start = 0x156C; + public const int End = 0x1585; + + private readonly DecorativeShieldDeed m_Shield; + private int m_Page; + + public InternalGump(DecorativeShieldDeed shield, int page = 1) : base(150, 50) + { + m_Shield = shield; + m_Page = page; + + Closable = true; + Disposable = true; + Draggable = true; + Resizable = false; + + AddPage(0); + + AddBackground(25, 0, 500, 230, 0xA28); + + var itemID = Start; + + for (var i = 1; i <= 2; i++) + { + AddPage(i); + + for (var j = 0; j < 9 - i; j++) + { + AddItem(40 + j * 60, 70, itemID); + AddButton(60 + j * 60, 50, 0x845, 0x846, itemID); + + if (itemID < 0x1582) + itemID += 2; + else + itemID += 1; + } + + switch (i) + { + case 1: + AddButton(455, 198, 0x8B0, 0x8B0, 0, GumpButtonType.Page, 2); + break; + case 2: + AddButton(70, 198, 0x8AF, 0x8AF, 0, GumpButtonType.Page, 1); + break; + } + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Shield?.Deleted != false || info.ButtonID < Start || info.ButtonID > End || + ((info.ButtonID & 0x1) != 0 || info.ButtonID >= 0x1582) && + (info.ButtonID < 0x1582 || info.ButtonID > 0x1585)) + return; + + sender.Mobile.SendLocalizedMessage(1049780); // Where would you like to place this decoration? + sender.Mobile.Target = new InternalTarget(m_Shield, info.ButtonID); + } + } + + private class InternalTarget : Target + { + private readonly int m_ItemID; + private readonly DecorativeShieldDeed m_Shield; + + public InternalTarget(DecorativeShieldDeed shield, int itemID) : base(-1, true, TargetFlags.None) + { + m_Shield = shield; + m_ItemID = itemID; + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Shield?.Deleted != false) + return; + + if (!m_Shield.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. + return; + } + + var house = BaseHouse.FindHouseAt(from); + + if (house?.IsOwner(from) != true) + { + from.SendLocalizedMessage(502092); // You must be in your house to do this. + return; + } + + var p = targeted as IPoint3D; + var map = from.Map; + + if (p == null || map == null) + return; + + var p3d = new Point3D(p); + var id = TileData.ItemTable[m_ItemID & TileData.MaxItemValue]; + + if (!map.CanFit(p3d, id.Height)) + { + from.SendLocalizedMessage(500269); // You cannot build that there. + return; + } + + house = BaseHouse.FindHouseAt(p3d, map, id.Height); + + if (house?.IsOwner(from) != true) + { + from.SendLocalizedMessage(1042036); // That location is not in your house. + return; + } + + var north = BaseAddon.IsWall(p3d.X, p3d.Y - 1, p3d.Z, map); + var west = BaseAddon.IsWall(p3d.X - 1, p3d.Y, p3d.Z, map); + + if (north && west) + { + from.CloseGump(); + from.SendGump(new FacingGump(m_Shield, m_ItemID, p3d, house)); + } + else if (north || west) + { + var shield = new DecorativeShield(west ? GetWestItemID(m_ItemID) : m_ItemID); + + house.Addons.Add(shield); + + shield.IsRewardItem = m_Shield.IsRewardItem; + shield.MoveToWorld(p3d, map); + + m_Shield.Delete(); + } + else + { + from.SendLocalizedMessage(1049781); // This decoration must be placed next to a wall. + } + } + + private class FacingGump : Gump + { + private readonly BaseHouse m_House; + private readonly int m_ItemID; + private readonly Point3D m_Location; + private readonly DecorativeShieldDeed m_Shield; + + public FacingGump(DecorativeShieldDeed shield, int itemID, Point3D location, BaseHouse house) : base(150, 50) + { + m_Shield = shield; + m_ItemID = itemID; + m_Location = location; + m_House = house; + + Closable = true; + Disposable = true; + Draggable = true; + Resizable = false; + + AddPage(0); + AddBackground(0, 0, 300, 150, 0xA28); + + AddItem(90, 30, GetWestItemID(itemID)); + AddItem(180, 30, itemID); + + AddButton(50, 35, 0x867, 0x869, (int)Buttons.East); + AddButton(145, 35, 0x867, 0x869, (int)Buttons.South); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Shield?.Deleted != false || m_House == null) + return; + + DecorativeShield shield = null; + + if (info.ButtonID == (int)Buttons.East) + shield = new DecorativeShield(GetWestItemID(m_ItemID)); + if (info.ButtonID == (int)Buttons.South) + shield = new DecorativeShield(m_ItemID); + + if (shield != null) + { + m_House.Addons.Add(shield); + + shield.IsRewardItem = m_Shield.IsRewardItem; + shield.MoveToWorld(m_Location, sender.Mobile.Map); + + m_Shield.Delete(); + } + } + + private enum Buttons + { + Cancel, + South, + East + } + } } - } } - } } diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/FlamingHead.cs b/Projects/UOContent/Items/Special/Veteran Rewards/FlamingHead.cs index f7b24f741..13108e55f 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/FlamingHead.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/FlamingHead.cs @@ -6,266 +6,267 @@ using Server.Targeting; namespace Server.Items { - public class FlamingHead : StoneFaceTrapNoDamage, IAddon, IRewardItem - { - private bool m_IsRewardItem; - - [Constructible] - public FlamingHead(StoneFaceTrapType type = StoneFaceTrapType.NorthWall) + public class FlamingHead : StoneFaceTrapNoDamage, IAddon, IRewardItem { - LootType = LootType.Blessed; - Movable = false; - Type = type; - } + private bool m_IsRewardItem; - public FlamingHead(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041266; // Flaming Head - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public Item Deed - { - get - { - FlamingHeadDeed deed = new FlamingHeadDeed(); - deed.IsRewardItem = m_IsRewardItem; - - return deed; - } - } - - public bool CouldFit(IPoint3D p, Map map) - { - if (map?.CanFit(p.X, p.Y, p.Z, ItemData.Height) != true) - return false; - - if (Type == StoneFaceTrapType.NorthWestWall) - return BaseAddon.IsWall(p.X, p.Y - 1, p.Z, map) && - BaseAddon.IsWall(p.X - 1, p.Y, p.Z, map); // north and west wall - if (Type == StoneFaceTrapType.NorthWall) - return BaseAddon.IsWall(p.X, p.Y - 1, p.Z, map); // north wall - if (Type == StoneFaceTrapType.WestWall) - return BaseAddon.IsWall(p.X - 1, p.Y, p.Z, map); // west wall - - return false; - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Core.ML && m_IsRewardItem) - list.Add(1076218); // 2nd Year Veteran Reward - } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(Location, 2)) - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (house?.IsOwner(from) == true) + [Constructible] + public FlamingHead(StoneFaceTrapType type = StoneFaceTrapType.NorthWall) { - from.CloseGump(); - from.SendGump(new RewardDemolitionGump(this, 1018329)); // Do you wish to re-deed this skull? - } - else - { - from.SendLocalizedMessage( - 1018328); // You can only re-deed a skull if you placed it or you are the owner of the house. - } - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - } - } - - public class FlamingHeadDeed : Item, IRewardItem - { - private bool m_IsRewardItem; - - [Constructible] - public FlamingHeadDeed() : base(0x14F0) - { - LootType = LootType.Blessed; - Weight = 1.0; - } - - public FlamingHeadDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041050; // a flaming head deed - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_IsRewardItem) - list.Add(1076218); // 2nd Year Veteran Reward - } - - public override void OnDoubleClick(Mobile from) - { - if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) - return; - - if (IsChildOf(from.Backpack)) - { - BaseHouse house = BaseHouse.FindHouseAt(from); - - if (house?.IsOwner(from) == true) - { - from.SendLocalizedMessage(1042264); // Where would you like to place this head? - from.Target = new InternalTarget(this); - } - else - { - from.SendLocalizedMessage(502115); // You must be in your house to do this. - } - } - else - { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - } - - private class InternalTarget : Target - { - private readonly FlamingHeadDeed m_Head; - - public InternalTarget(FlamingHeadDeed head) : base(-1, true, TargetFlags.None) => m_Head = head; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Head?.Deleted != false) - return; - - if (!m_Head.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. - return; + LootType = LootType.Blessed; + Movable = false; + Type = type; } - BaseHouse house = BaseHouse.FindHouseAt(from); - - if (house?.IsOwner(from) != true) + public FlamingHead(Serial serial) : base(serial) { - from.SendLocalizedMessage(502115); // You must be in your house to do this. - return; } - IPoint3D p = targeted as IPoint3D; - Map map = from.Map; + public override int LabelNumber => 1041266; // Flaming Head + public override bool ForceShowProperties => ObjectPropertyList.Enabled; - if (p == null || map == null) - return; - - Point3D p3d = new Point3D(p); - ItemData id = TileData.ItemTable[0x10F5]; - - house = BaseHouse.FindHouseAt(p3d, map, id.Height); - - if (house?.IsOwner(from) != true) + public Item Deed { - from.SendLocalizedMessage(1042036); // That location is not in your house. - return; + get + { + var deed = new FlamingHeadDeed(); + deed.IsRewardItem = m_IsRewardItem; + + return deed; + } } - if (!map.CanFit(p3d, id.Height)) + public bool CouldFit(IPoint3D p, Map map) { - from.SendLocalizedMessage(1042266); // The head must be placed next to a wall. - return; + if (map?.CanFit(p.X, p.Y, p.Z, ItemData.Height) != true) + return false; + + if (Type == StoneFaceTrapType.NorthWestWall) + return BaseAddon.IsWall(p.X, p.Y - 1, p.Z, map) && + BaseAddon.IsWall(p.X - 1, p.Y, p.Z, map); // north and west wall + if (Type == StoneFaceTrapType.NorthWall) + return BaseAddon.IsWall(p.X, p.Y - 1, p.Z, map); // north wall + if (Type == StoneFaceTrapType.WestWall) + return BaseAddon.IsWall(p.X - 1, p.Y, p.Z, map); // west wall + + return false; } - bool north = BaseAddon.IsWall(p3d.X, p3d.Y - 1, p3d.Z, map); - bool west = BaseAddon.IsWall(p3d.X - 1, p3d.Y, p3d.Z, map); - - FlamingHead head = null; - - if (north && west) - head = new FlamingHead(StoneFaceTrapType.NorthWestWall); - else if (north) - head = new FlamingHead(); - else if (west) - head = new FlamingHead(StoneFaceTrapType.WestWall); - - if (north || west) + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem { - house.Addons.Add(head); - - head.IsRewardItem = m_Head.IsRewardItem; - head.MoveToWorld(p3d, map); - - m_Head.Delete(); + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } } - else + + public override void GetProperties(ObjectPropertyList list) { - from.SendLocalizedMessage(1042266); // The head must be placed next to a wall. + base.GetProperties(list); + + if (Core.ML && m_IsRewardItem) + list.Add(1076218); // 2nd Year Veteran Reward + } + + public override void OnDoubleClick(Mobile from) + { + if (from.InRange(Location, 2)) + { + var house = BaseHouse.FindHouseAt(this); + + if (house?.IsOwner(from) == true) + { + from.CloseGump(); + from.SendGump(new RewardDemolitionGump(this, 1018329)); // Do you wish to re-deed this skull? + } + else + { + from.SendLocalizedMessage( + 1018328 + ); // You can only re-deed a skull if you placed it or you are the owner of the house. + } + } + else + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + } + } + + public class FlamingHeadDeed : Item, IRewardItem + { + private bool m_IsRewardItem; + + [Constructible] + public FlamingHeadDeed() : base(0x14F0) + { + LootType = LootType.Blessed; + Weight = 1.0; + } + + public FlamingHeadDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041050; // a flaming head deed + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_IsRewardItem) + list.Add(1076218); // 2nd Year Veteran Reward + } + + public override void OnDoubleClick(Mobile from) + { + if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) + return; + + if (IsChildOf(from.Backpack)) + { + var house = BaseHouse.FindHouseAt(from); + + if (house?.IsOwner(from) == true) + { + from.SendLocalizedMessage(1042264); // Where would you like to place this head? + from.Target = new InternalTarget(this); + } + else + { + from.SendLocalizedMessage(502115); // You must be in your house to do this. + } + } + else + { + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + } + + private class InternalTarget : Target + { + private readonly FlamingHeadDeed m_Head; + + public InternalTarget(FlamingHeadDeed head) : base(-1, true, TargetFlags.None) => m_Head = head; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Head?.Deleted != false) + return; + + if (!m_Head.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. + return; + } + + var house = BaseHouse.FindHouseAt(from); + + if (house?.IsOwner(from) != true) + { + from.SendLocalizedMessage(502115); // You must be in your house to do this. + return; + } + + var p = targeted as IPoint3D; + var map = from.Map; + + if (p == null || map == null) + return; + + var p3d = new Point3D(p); + var id = TileData.ItemTable[0x10F5]; + + house = BaseHouse.FindHouseAt(p3d, map, id.Height); + + if (house?.IsOwner(from) != true) + { + from.SendLocalizedMessage(1042036); // That location is not in your house. + return; + } + + if (!map.CanFit(p3d, id.Height)) + { + from.SendLocalizedMessage(1042266); // The head must be placed next to a wall. + return; + } + + var north = BaseAddon.IsWall(p3d.X, p3d.Y - 1, p3d.Z, map); + var west = BaseAddon.IsWall(p3d.X - 1, p3d.Y, p3d.Z, map); + + FlamingHead head = null; + + if (north && west) + head = new FlamingHead(StoneFaceTrapType.NorthWestWall); + else if (north) + head = new FlamingHead(); + else if (west) + head = new FlamingHead(StoneFaceTrapType.WestWall); + + if (north || west) + { + house.Addons.Add(head); + + head.IsRewardItem = m_Head.IsRewardItem; + head.MoveToWorld(p3d, map); + + m_Head.Delete(); + } + else + { + from.SendLocalizedMessage(1042266); // The head must be placed next to a wall. + } + } } - } } - } } diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/HangingSkeleton.cs b/Projects/UOContent/Items/Special/Veteran Rewards/HangingSkeleton.cs index ac03699f9..b3e48da98 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/HangingSkeleton.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/HangingSkeleton.cs @@ -6,390 +6,391 @@ using Server.Targeting; namespace Server.Items { - public class HangingSkeleton : Item, IAddon, IRewardItem - { - private bool m_IsRewardItem; - - [Constructible] - public HangingSkeleton(int itemID = 0x1596) : base(itemID) + public class HangingSkeleton : Item, IAddon, IRewardItem { - LootType = LootType.Blessed; - Movable = false; - } + private bool m_IsRewardItem; - public HangingSkeleton(Serial serial) : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public bool FacingSouth - { - get - { - if (ItemID == 0x1A03 || ItemID == 0x1A05 || ItemID == 0x1A09 || - ItemID == 0x1B1E || ItemID == 0x1B7F) - return true; - - return false; - } - } - - public Item Deed - { - get - { - HangingSkeletonDeed deed = new HangingSkeletonDeed(); - deed.IsRewardItem = m_IsRewardItem; - - return deed; - } - } - - public bool CouldFit(IPoint3D p, Map map) - { - if (map?.CanFit(p.X, p.Y, p.Z, ItemData.Height) != true) - return false; - - if (FacingSouth) - return BaseAddon.IsWall(p.X, p.Y - 1, p.Z, map); // north wall - return BaseAddon.IsWall(p.X - 1, p.Y, p.Z, map); // west wall - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Core.ML && m_IsRewardItem) - list.Add(1076220); // 4th Year Veteran Reward - } - - public override void OnDoubleClick(Mobile from) - { - if (from.InRange(Location, 3)) - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (house?.IsOwner(from) == true) + [Constructible] + public HangingSkeleton(int itemID = 0x1596) : base(itemID) { - from.CloseGump(); - from.SendGump(new RewardDemolitionGump(this, 1049783)); // Do you wish to re-deed this decoration? - } - else - { - from.SendLocalizedMessage( - 1049784); // You can only re-deed this decoration if you are the house owner or originally placed the decoration. - } - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - } - } - - public class HangingSkeletonDeed : Item, IRewardItem - { - private bool m_IsRewardItem; - - [Constructible] - public HangingSkeletonDeed() : base(0x14F0) - { - LootType = LootType.Blessed; - Weight = 1.0; - } - - public HangingSkeletonDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1049772; // deed for a hanging skeleton decoration - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_IsRewardItem) - list.Add(1076220); // 4th Year Veteran Reward - } - - public override void OnDoubleClick(Mobile from) - { - if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) - return; - - if (IsChildOf(from.Backpack)) - { - BaseHouse house = BaseHouse.FindHouseAt(from); - - if (house?.IsOwner(from) == true) - { - from.CloseGump(); - from.SendGump(new InternalGump(this)); - } - else - { - from.SendLocalizedMessage(502092); // You must be in your house to do this. - } - } - else - { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - } - - public static int GetWestItemID(int south) - { - return south switch - { - 0x1B1E => 0x1B1D, - 0x1B7F => 0x1B7C, - _ => south + 1 - }; - } - - private class InternalGump : Gump - { - private readonly HangingSkeletonDeed m_Skeleton; - - public InternalGump(HangingSkeletonDeed skeleton) : base(100, 200) - { - m_Skeleton = skeleton; - - Closable = true; - Disposable = true; - Draggable = true; - Resizable = false; - - AddPage(0); - - AddBackground(25, 0, 500, 230, 0xA28); - - AddPage(1); - - AddItem(130, 70, 0x1A03); - AddButton(150, 50, 0x845, 0x846, 0x1A03); - - AddItem(190, 70, 0x1A05); - AddButton(210, 50, 0x845, 0x846, 0x1A05); - - AddItem(250, 70, 0x1A09); - AddButton(270, 50, 0x845, 0x846, 0x1A09); - - AddItem(310, 70, 0x1B1E); - AddButton(330, 50, 0x845, 0x846, 0x1B1E); - - AddItem(370, 70, 0x1B7F); - AddButton(390, 50, 0x845, 0x846, 0x1B7F); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Skeleton?.Deleted != false || (info.ButtonID != 0x1A03 && info.ButtonID != 0x1A05 && - info.ButtonID != 0x1A09 && info.ButtonID != 0x1B1E && info.ButtonID != 0x1B7F)) - return; - - sender.Mobile.SendLocalizedMessage(1049780); // Where would you like to place this decoration? - sender.Mobile.Target = new InternalTarget(m_Skeleton, info.ButtonID); - } - } - - private class InternalTarget : Target - { - private readonly int m_ItemID; - private readonly HangingSkeletonDeed m_Skeleton; - - public InternalTarget(HangingSkeletonDeed banner, int itemID) : base(-1, true, TargetFlags.None) - { - m_Skeleton = banner; - m_ItemID = itemID; - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Skeleton?.Deleted != false) - return; - - if (!m_Skeleton.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. - return; + LootType = LootType.Blessed; + Movable = false; } - BaseHouse house = BaseHouse.FindHouseAt(from); - - if (house?.IsOwner(from) != true) + public HangingSkeleton(Serial serial) : base(serial) { - from.SendLocalizedMessage(502092); // You must be in your house to do this. - return; } - IPoint3D p = targeted as IPoint3D; - Map map = from.Map; + public override bool ForceShowProperties => ObjectPropertyList.Enabled; - if (p == null || map == null) - return; - - Point3D p3d = new Point3D(p); - ItemData id = TileData.ItemTable[m_ItemID & TileData.MaxItemValue]; - - if (!map.CanFit(p3d, id.Height)) + public bool FacingSouth { - from.SendLocalizedMessage(500269); // You cannot build that there. - return; + get + { + if (ItemID == 0x1A03 || ItemID == 0x1A05 || ItemID == 0x1A09 || + ItemID == 0x1B1E || ItemID == 0x1B7F) + return true; + + return false; + } } - house = BaseHouse.FindHouseAt(p3d, map, id.Height); - - if (house?.IsOwner(from) != true) + public Item Deed { - from.SendLocalizedMessage(1042036); // That location is not in your house. - return; + get + { + var deed = new HangingSkeletonDeed(); + deed.IsRewardItem = m_IsRewardItem; + + return deed; + } } - bool north = BaseAddon.IsWall(p3d.X, p3d.Y - 1, p3d.Z, map); - bool west = BaseAddon.IsWall(p3d.X - 1, p3d.Y, p3d.Z, map); - - if (north && west) + public bool CouldFit(IPoint3D p, Map map) { - from.CloseGump(); - from.SendGump(new FacingGump(m_Skeleton, m_ItemID, p3d, house)); - } - else if (north || west) - { - HangingSkeleton banner = new HangingSkeleton(west ? GetWestItemID(m_ItemID) : m_ItemID); + if (map?.CanFit(p.X, p.Y, p.Z, ItemData.Height) != true) + return false; - house.Addons.Add(banner); - - banner.IsRewardItem = m_Skeleton.IsRewardItem; - banner.MoveToWorld(p3d, map); - - m_Skeleton.Delete(); - } - else - { - from.SendLocalizedMessage(1042039); // The banner must be placed next to a wall. - } - } - - private class FacingGump : Gump - { - private readonly BaseHouse m_House; - private readonly int m_ItemID; - private readonly Point3D m_Location; - private readonly HangingSkeletonDeed m_Skeleton; - - public FacingGump(HangingSkeletonDeed banner, int itemID, Point3D location, BaseHouse house) : base(150, 50) - { - m_Skeleton = banner; - m_ItemID = itemID; - m_Location = location; - m_House = house; - - Closable = true; - Disposable = true; - Draggable = true; - Resizable = false; - - AddPage(0); - - AddBackground(0, 0, 300, 150, 0xA28); - - AddItem(90, 30, GetWestItemID(itemID)); - AddItem(180, 30, itemID); - - AddButton(50, 35, 0x868, 0x869, (int)Buttons.East); - AddButton(145, 35, 0x868, 0x869, (int)Buttons.South); + if (FacingSouth) + return BaseAddon.IsWall(p.X, p.Y - 1, p.Z, map); // north wall + return BaseAddon.IsWall(p.X - 1, p.Y, p.Z, map); // west wall } - public override void OnResponse(NetState sender, RelayInfo info) + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem { - if (m_Skeleton?.Deleted != false || m_House == null) - return; - - HangingSkeleton banner = null; - - if (info.ButtonID == (int)Buttons.East) - banner = new HangingSkeleton(GetWestItemID(m_ItemID)); - if (info.ButtonID == (int)Buttons.South) - banner = new HangingSkeleton(m_ItemID); - - if (banner != null) - { - m_House.Addons.Add(banner); - - banner.IsRewardItem = m_Skeleton.IsRewardItem; - banner.MoveToWorld(m_Location, sender.Mobile.Map); - - m_Skeleton.Delete(); - } + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } } - private enum Buttons + public override void GetProperties(ObjectPropertyList list) { - Cancel, - South, - East + base.GetProperties(list); + + if (Core.ML && m_IsRewardItem) + list.Add(1076220); // 4th Year Veteran Reward + } + + public override void OnDoubleClick(Mobile from) + { + if (from.InRange(Location, 3)) + { + var house = BaseHouse.FindHouseAt(this); + + if (house?.IsOwner(from) == true) + { + from.CloseGump(); + from.SendGump(new RewardDemolitionGump(this, 1049783)); // Do you wish to re-deed this decoration? + } + else + { + from.SendLocalizedMessage( + 1049784 + ); // You can only re-deed this decoration if you are the house owner or originally placed the decoration. + } + } + else + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + } + } + + public class HangingSkeletonDeed : Item, IRewardItem + { + private bool m_IsRewardItem; + + [Constructible] + public HangingSkeletonDeed() : base(0x14F0) + { + LootType = LootType.Blessed; + Weight = 1.0; + } + + public HangingSkeletonDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1049772; // deed for a hanging skeleton decoration + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_IsRewardItem) + list.Add(1076220); // 4th Year Veteran Reward + } + + public override void OnDoubleClick(Mobile from) + { + if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) + return; + + if (IsChildOf(from.Backpack)) + { + var house = BaseHouse.FindHouseAt(from); + + if (house?.IsOwner(from) == true) + { + from.CloseGump(); + from.SendGump(new InternalGump(this)); + } + else + { + from.SendLocalizedMessage(502092); // You must be in your house to do this. + } + } + else + { + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + } + + public static int GetWestItemID(int south) + { + return south switch + { + 0x1B1E => 0x1B1D, + 0x1B7F => 0x1B7C, + _ => south + 1 + }; + } + + private class InternalGump : Gump + { + private readonly HangingSkeletonDeed m_Skeleton; + + public InternalGump(HangingSkeletonDeed skeleton) : base(100, 200) + { + m_Skeleton = skeleton; + + Closable = true; + Disposable = true; + Draggable = true; + Resizable = false; + + AddPage(0); + + AddBackground(25, 0, 500, 230, 0xA28); + + AddPage(1); + + AddItem(130, 70, 0x1A03); + AddButton(150, 50, 0x845, 0x846, 0x1A03); + + AddItem(190, 70, 0x1A05); + AddButton(210, 50, 0x845, 0x846, 0x1A05); + + AddItem(250, 70, 0x1A09); + AddButton(270, 50, 0x845, 0x846, 0x1A09); + + AddItem(310, 70, 0x1B1E); + AddButton(330, 50, 0x845, 0x846, 0x1B1E); + + AddItem(370, 70, 0x1B7F); + AddButton(390, 50, 0x845, 0x846, 0x1B7F); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Skeleton?.Deleted != false || info.ButtonID != 0x1A03 && info.ButtonID != 0x1A05 && + info.ButtonID != 0x1A09 && info.ButtonID != 0x1B1E && info.ButtonID != 0x1B7F) + return; + + sender.Mobile.SendLocalizedMessage(1049780); // Where would you like to place this decoration? + sender.Mobile.Target = new InternalTarget(m_Skeleton, info.ButtonID); + } + } + + private class InternalTarget : Target + { + private readonly int m_ItemID; + private readonly HangingSkeletonDeed m_Skeleton; + + public InternalTarget(HangingSkeletonDeed banner, int itemID) : base(-1, true, TargetFlags.None) + { + m_Skeleton = banner; + m_ItemID = itemID; + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Skeleton?.Deleted != false) + return; + + if (!m_Skeleton.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. + return; + } + + var house = BaseHouse.FindHouseAt(from); + + if (house?.IsOwner(from) != true) + { + from.SendLocalizedMessage(502092); // You must be in your house to do this. + return; + } + + var p = targeted as IPoint3D; + var map = from.Map; + + if (p == null || map == null) + return; + + var p3d = new Point3D(p); + var id = TileData.ItemTable[m_ItemID & TileData.MaxItemValue]; + + if (!map.CanFit(p3d, id.Height)) + { + from.SendLocalizedMessage(500269); // You cannot build that there. + return; + } + + house = BaseHouse.FindHouseAt(p3d, map, id.Height); + + if (house?.IsOwner(from) != true) + { + from.SendLocalizedMessage(1042036); // That location is not in your house. + return; + } + + var north = BaseAddon.IsWall(p3d.X, p3d.Y - 1, p3d.Z, map); + var west = BaseAddon.IsWall(p3d.X - 1, p3d.Y, p3d.Z, map); + + if (north && west) + { + from.CloseGump(); + from.SendGump(new FacingGump(m_Skeleton, m_ItemID, p3d, house)); + } + else if (north || west) + { + var banner = new HangingSkeleton(west ? GetWestItemID(m_ItemID) : m_ItemID); + + house.Addons.Add(banner); + + banner.IsRewardItem = m_Skeleton.IsRewardItem; + banner.MoveToWorld(p3d, map); + + m_Skeleton.Delete(); + } + else + { + from.SendLocalizedMessage(1042039); // The banner must be placed next to a wall. + } + } + + private class FacingGump : Gump + { + private readonly BaseHouse m_House; + private readonly int m_ItemID; + private readonly Point3D m_Location; + private readonly HangingSkeletonDeed m_Skeleton; + + public FacingGump(HangingSkeletonDeed banner, int itemID, Point3D location, BaseHouse house) : base(150, 50) + { + m_Skeleton = banner; + m_ItemID = itemID; + m_Location = location; + m_House = house; + + Closable = true; + Disposable = true; + Draggable = true; + Resizable = false; + + AddPage(0); + + AddBackground(0, 0, 300, 150, 0xA28); + + AddItem(90, 30, GetWestItemID(itemID)); + AddItem(180, 30, itemID); + + AddButton(50, 35, 0x868, 0x869, (int)Buttons.East); + AddButton(145, 35, 0x868, 0x869, (int)Buttons.South); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Skeleton?.Deleted != false || m_House == null) + return; + + HangingSkeleton banner = null; + + if (info.ButtonID == (int)Buttons.East) + banner = new HangingSkeleton(GetWestItemID(m_ItemID)); + if (info.ButtonID == (int)Buttons.South) + banner = new HangingSkeleton(m_ItemID); + + if (banner != null) + { + m_House.Addons.Add(banner); + + banner.IsRewardItem = m_Skeleton.IsRewardItem; + banner.MoveToWorld(m_Location, sender.Mobile.Map); + + m_Skeleton.Delete(); + } + } + + private enum Buttons + { + Cancel, + South, + East + } + } } - } } - } } diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/MiningCart.cs b/Projects/UOContent/Items/Special/Veteran Rewards/MiningCart.cs index eef200116..b6d660b01 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/MiningCart.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/MiningCart.cs @@ -6,381 +6,381 @@ using Server.Network; namespace Server.Items { - public enum MiningCartType - { - OreSouth = 100, - OreEast = 101, - GemSouth = 102, - GemEast = 103 - } - - public class MiningCart : BaseAddon, IRewardItem - { - private Timer m_Timer; - - [Constructible] - public MiningCart(MiningCartType type) + public enum MiningCartType { - CartType = type; - - switch (type) - { - case MiningCartType.OreSouth: - AddComponent(new AddonComponent(0x1A83), 0, 0, 0); - AddComponent(new AddonComponent(0x1A82), 0, 1, 0); - AddComponent(new AddonComponent(0x1A86), 0, -1, 0); - break; - case MiningCartType.OreEast: - AddComponent(new AddonComponent(0x1A88), 0, 0, 0); - AddComponent(new AddonComponent(0x1A87), 1, 0, 0); - AddComponent(new AddonComponent(0x1A8B), -1, 0, 0); - break; - case MiningCartType.GemSouth: - AddComponent(new LocalizedAddonComponent(0x1A83, 1080388), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0x1A82, 1080388), 0, 1, 0); - AddComponent(new LocalizedAddonComponent(0x1A86, 1080388), 0, -1, 0); - - AddComponent(new AddonComponent(0xF2C), 0, 0, 6); - AddComponent(new AddonComponent(0xF1D), 0, 0, 5); - AddComponent(new AddonComponent(0xF2B), 0, 0, 2); - AddComponent(new AddonComponent(0xF21), 0, 0, 1); - AddComponent(new AddonComponent(0xF22), 0, 0, 4); - AddComponent(new AddonComponent(0xF2F), 0, 0, 5); - AddComponent(new AddonComponent(0xF26), 0, 0, 6); - AddComponent(new AddonComponent(0xF27), 0, 0, 3); - AddComponent(new AddonComponent(0xF29), 0, 0, 0); - break; - case MiningCartType.GemEast: - AddComponent(new LocalizedAddonComponent(0x1A88, 1080388), 0, 0, 0); - AddComponent(new LocalizedAddonComponent(0x1A87, 1080388), 1, 0, 0); - AddComponent(new LocalizedAddonComponent(0x1A8B, 1080388), -1, 0, 0); - - AddComponent(new AddonComponent(0xF2E), 0, 0, 6); - AddComponent(new AddonComponent(0xF12), 0, 0, 3); - AddComponent(new AddonComponent(0xF29), 0, 0, 1); - AddComponent(new AddonComponent(0xF24), 0, 0, 5); - AddComponent(new AddonComponent(0xF21), 0, 0, 1); - AddComponent(new AddonComponent(0xF2B), 0, 0, 3); - AddComponent(new AddonComponent(0xF2F), 0, 0, 4); - AddComponent(new AddonComponent(0xF23), 0, 0, 3); - AddComponent(new AddonComponent(0xF27), 0, 0, 3); - break; - } - - m_Timer = Timer.DelayCall(TimeSpan.FromDays(1), TimeSpan.FromDays(1), GiveResources); + OreSouth = 100, + OreEast = 101, + GemSouth = 102, + GemEast = 103 } - public MiningCart(Serial serial) : base(serial) + public class MiningCart : BaseAddon, IRewardItem { - } + private Timer m_Timer; - public override BaseAddonDeed Deed - { - get - { - MiningCartDeed deed = new MiningCartDeed(); - deed.IsRewardItem = IsRewardItem; - deed.Gems = Gems; - deed.Ore = Ore; - - return deed; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public MiningCartType CartType { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Gems { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Ore { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem { get; set; } - - private void GiveResources() - { - switch (CartType) - { - case MiningCartType.OreSouth: - case MiningCartType.OreEast: - Ore = Math.Min(100, Ore + 10); - break; - case MiningCartType.GemSouth: - case MiningCartType.GemEast: - Gems = Math.Min(50, Gems + 5); - break; - } - } - - public override void OnComponentUsed(AddonComponent c, Mobile from) - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - /* - * Unique problems have unique solutions. OSI does not have a problem with 1000s of mining carts - * due to the fact that they have only a miniscule fraction of the number of 10 year vets that a - * typical RunUO shard will have (RunUO's scaled down account aging system makes this a unique problem), - * and the "freeness" of free accounts. We also dont have mitigating factors like inactive (unpaid) - * accounts not gaining veteran time. - * - * The lack of high end vets and vet rewards on OSI has made testing the *exact* ranging/stacking - * behavior of these things all but impossible, so either way its just an estimation. - * - * If youd like your shard's carts/stumps to work the way they did before, simply replace the check - * below with this line of code: - * - * if (!from.InRange(GetWorldLocation(), 2) - * - * However, I am sure these checks are more accurate to OSI than the former version was. - * - */ - - if (!from.InRange(GetWorldLocation(), 2) || !from.InLOS(this) || !(from.Z - Z > -3 && from.Z - Z < 3)) - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - else if (house?.HasSecureAccess(from, SecureLevel.Friends) == true) - switch (CartType) + [Constructible] + public MiningCart(MiningCartType type) { - case MiningCartType.OreSouth: - case MiningCartType.OreEast: - if (Ore > 0) - { - var ingots = Utility.Random(9) switch - { - 0 => (Item)new IronIngot(), - 1 => new DullCopperIngot(), - 2 => new ShadowIronIngot(), - 3 => new CopperIngot(), - 4 => new BronzeIngot(), - 5 => new GoldIngot(), - 6 => new AgapiteIngot(), - 7 => new VeriteIngot(), - 8 => new ValoriteIngot(), - _ => null - }; + CartType = type; - int amount = Math.Min(10, Ore); - // ReSharper disable once PossibleNullReferenceException - ingots.Amount = amount; - - if (!from.PlaceInBackpack(ingots)) - { - ingots.Delete(); - from.SendLocalizedMessage(1078837); // Your backpack is full! Please make room and try again. - } - else - { - PublicOverheadMessage(MessageType.Regular, 0, 1094724, amount.ToString()); // Ore: ~1_COUNT~ - Ore -= amount; - } - } - else + switch (type) { - from.SendLocalizedMessage(1094725); // There are no more resources available at this time. + case MiningCartType.OreSouth: + AddComponent(new AddonComponent(0x1A83), 0, 0, 0); + AddComponent(new AddonComponent(0x1A82), 0, 1, 0); + AddComponent(new AddonComponent(0x1A86), 0, -1, 0); + break; + case MiningCartType.OreEast: + AddComponent(new AddonComponent(0x1A88), 0, 0, 0); + AddComponent(new AddonComponent(0x1A87), 1, 0, 0); + AddComponent(new AddonComponent(0x1A8B), -1, 0, 0); + break; + case MiningCartType.GemSouth: + AddComponent(new LocalizedAddonComponent(0x1A83, 1080388), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0x1A82, 1080388), 0, 1, 0); + AddComponent(new LocalizedAddonComponent(0x1A86, 1080388), 0, -1, 0); + + AddComponent(new AddonComponent(0xF2C), 0, 0, 6); + AddComponent(new AddonComponent(0xF1D), 0, 0, 5); + AddComponent(new AddonComponent(0xF2B), 0, 0, 2); + AddComponent(new AddonComponent(0xF21), 0, 0, 1); + AddComponent(new AddonComponent(0xF22), 0, 0, 4); + AddComponent(new AddonComponent(0xF2F), 0, 0, 5); + AddComponent(new AddonComponent(0xF26), 0, 0, 6); + AddComponent(new AddonComponent(0xF27), 0, 0, 3); + AddComponent(new AddonComponent(0xF29), 0, 0, 0); + break; + case MiningCartType.GemEast: + AddComponent(new LocalizedAddonComponent(0x1A88, 1080388), 0, 0, 0); + AddComponent(new LocalizedAddonComponent(0x1A87, 1080388), 1, 0, 0); + AddComponent(new LocalizedAddonComponent(0x1A8B, 1080388), -1, 0, 0); + + AddComponent(new AddonComponent(0xF2E), 0, 0, 6); + AddComponent(new AddonComponent(0xF12), 0, 0, 3); + AddComponent(new AddonComponent(0xF29), 0, 0, 1); + AddComponent(new AddonComponent(0xF24), 0, 0, 5); + AddComponent(new AddonComponent(0xF21), 0, 0, 1); + AddComponent(new AddonComponent(0xF2B), 0, 0, 3); + AddComponent(new AddonComponent(0xF2F), 0, 0, 4); + AddComponent(new AddonComponent(0xF23), 0, 0, 3); + AddComponent(new AddonComponent(0xF27), 0, 0, 3); + break; } - break; - case MiningCartType.GemSouth: - case MiningCartType.GemEast: - if (Gems > 0) - { - var gems = Utility.Random(15) switch - { - 0 => (Item)new Amber(), - 1 => new Amethyst(), - 2 => new Citrine(), - 3 => new Diamond(), - 4 => new Emerald(), - 5 => new Ruby(), - 6 => new Sapphire(), - 7 => new StarSapphire(), - 8 => new Tourmaline(), - // Mondain's Legacy gems - 9 => new PerfectEmerald(), - 10 => new DarkSapphire(), - 11 => new Turquoise(), - 12 => new EcruCitrine(), - 13 => new FireRuby(), - 14 => new BlueDiamond(), - _ => null - }; - - int amount = Math.Min(5, Gems); - gems.Amount = amount; - - if (!from.PlaceInBackpack(gems)) - { - gems.Delete(); - from.SendLocalizedMessage(1078837); // Your backpack is full! Please make room and try again. - } - else - { - PublicOverheadMessage(MessageType.Regular, 0, 1094723, amount.ToString()); // Gems: ~1_COUNT~ - Gems -= amount; - } - } - else - { - from.SendLocalizedMessage(1094725); // There are no more resources available at this time. - } - - break; + m_Timer = Timer.DelayCall(TimeSpan.FromDays(1), TimeSpan.FromDays(1), GiveResources); + } + + public MiningCart(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed + { + get + { + var deed = new MiningCartDeed(); + deed.IsRewardItem = IsRewardItem; + deed.Gems = Gems; + deed.Ore = Ore; + + return deed; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public MiningCartType CartType { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Gems { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Ore { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem { get; set; } + + private void GiveResources() + { + switch (CartType) + { + case MiningCartType.OreSouth: + case MiningCartType.OreEast: + Ore = Math.Min(100, Ore + 10); + break; + case MiningCartType.GemSouth: + case MiningCartType.GemEast: + Gems = Math.Min(50, Gems + 5); + break; + } + } + + public override void OnComponentUsed(AddonComponent c, Mobile from) + { + var house = BaseHouse.FindHouseAt(this); + + /* + * Unique problems have unique solutions. OSI does not have a problem with 1000s of mining carts + * due to the fact that they have only a miniscule fraction of the number of 10 year vets that a + * typical RunUO shard will have (RunUO's scaled down account aging system makes this a unique problem), + * and the "freeness" of free accounts. We also dont have mitigating factors like inactive (unpaid) + * accounts not gaining veteran time. + * + * The lack of high end vets and vet rewards on OSI has made testing the *exact* ranging/stacking + * behavior of these things all but impossible, so either way its just an estimation. + * + * If youd like your shard's carts/stumps to work the way they did before, simply replace the check + * below with this line of code: + * + * if (!from.InRange(GetWorldLocation(), 2) + * + * However, I am sure these checks are more accurate to OSI than the former version was. + * + */ + + if (!from.InRange(GetWorldLocation(), 2) || !from.InLOS(this) || !(from.Z - Z > -3 && from.Z - Z < 3)) + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + else if (house?.HasSecureAccess(from, SecureLevel.Friends) == true) + switch (CartType) + { + case MiningCartType.OreSouth: + case MiningCartType.OreEast: + if (Ore > 0) + { + var ingots = Utility.Random(9) switch + { + 0 => (Item)new IronIngot(), + 1 => new DullCopperIngot(), + 2 => new ShadowIronIngot(), + 3 => new CopperIngot(), + 4 => new BronzeIngot(), + 5 => new GoldIngot(), + 6 => new AgapiteIngot(), + 7 => new VeriteIngot(), + 8 => new ValoriteIngot(), + _ => null + }; + + var amount = Math.Min(10, Ore); + // ReSharper disable once PossibleNullReferenceException + ingots.Amount = amount; + + if (!from.PlaceInBackpack(ingots)) + { + ingots.Delete(); + from.SendLocalizedMessage(1078837); // Your backpack is full! Please make room and try again. + } + else + { + PublicOverheadMessage(MessageType.Regular, 0, 1094724, amount.ToString()); // Ore: ~1_COUNT~ + Ore -= amount; + } + } + else + { + from.SendLocalizedMessage(1094725); // There are no more resources available at this time. + } + + break; + case MiningCartType.GemSouth: + case MiningCartType.GemEast: + if (Gems > 0) + { + var gems = Utility.Random(15) switch + { + 0 => (Item)new Amber(), + 1 => new Amethyst(), + 2 => new Citrine(), + 3 => new Diamond(), + 4 => new Emerald(), + 5 => new Ruby(), + 6 => new Sapphire(), + 7 => new StarSapphire(), + 8 => new Tourmaline(), + // Mondain's Legacy gems + 9 => new PerfectEmerald(), + 10 => new DarkSapphire(), + 11 => new Turquoise(), + 12 => new EcruCitrine(), + 13 => new FireRuby(), + 14 => new BlueDiamond(), + _ => null + }; + + var amount = Math.Min(5, Gems); + gems.Amount = amount; + + if (!from.PlaceInBackpack(gems)) + { + gems.Delete(); + from.SendLocalizedMessage(1078837); // Your backpack is full! Please make room and try again. + } + else + { + PublicOverheadMessage(MessageType.Regular, 0, 1094723, amount.ToString()); // Gems: ~1_COUNT~ + Gems -= amount; + } + } + else + { + from.SendLocalizedMessage(1094725); // There are no more resources available at this time. + } + + break; + } + else + from.SendLocalizedMessage(1061637); // You are not allowed to access this. + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(1); // version + + writer.Write((int)CartType); + + writer.Write(IsRewardItem); + writer.Write(Gems); + writer.Write(Ore); + + if (m_Timer != null) + writer.Write(m_Timer.Next); + else + writer.Write(DateTime.UtcNow + TimeSpan.FromDays(1)); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 1: + CartType = (MiningCartType)reader.ReadInt(); + goto case 0; + case 0: + IsRewardItem = reader.ReadBool(); + Gems = reader.ReadInt(); + Ore = reader.ReadInt(); + + var next = reader.ReadDateTime(); + + if (next < DateTime.UtcNow) + next = DateTime.UtcNow; + + m_Timer = Timer.DelayCall(next - DateTime.UtcNow, TimeSpan.FromDays(1), GiveResources); + break; + } } - else - from.SendLocalizedMessage(1061637); // You are not allowed to access this. } - public override void Serialize(IGenericWriter writer) + public class MiningCartDeed : BaseAddonDeed, IRewardItem, IRewardOption { - base.Serialize(writer); + private MiningCartType m_CartType; - writer.WriteEncodedInt(1); // version + private bool m_IsRewardItem; - writer.Write((int)CartType); + [Constructible] + public MiningCartDeed() => LootType = LootType.Blessed; - writer.Write(IsRewardItem); - writer.Write(Gems); - writer.Write(Ore); + public MiningCartDeed(Serial serial) : base(serial) + { + } - if (m_Timer != null) - writer.Write(m_Timer.Next); - else - writer.Write(DateTime.UtcNow + TimeSpan.FromDays(1)); + public override int LabelNumber => 1080385; // deed for a mining cart decoration + + public override BaseAddon Addon + { + get + { + var addon = new MiningCart(m_CartType); + addon.IsRewardItem = m_IsRewardItem; + addon.Gems = Gems; + addon.Ore = Ore; + + return addon; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Gems { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Ore { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public void GetOptions(RewardOptionList list) + { + list.Add((int)MiningCartType.OreSouth, 1080391); + list.Add((int)MiningCartType.OreEast, 1080390); + list.Add((int)MiningCartType.GemSouth, 1080500); + list.Add((int)MiningCartType.GemEast, 1080499); + } + + public void OnOptionSelected(Mobile from, int choice) + { + m_CartType = (MiningCartType)choice; + + if (!Deleted) + base.OnDoubleClick(from); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_IsRewardItem) + list.Add(1080457); // 10th Year Veteran Reward + } + + public override void OnDoubleClick(Mobile from) + { + if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) + return; + + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new RewardOptionGump(this)); + } + else + { + from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + writer.Write(Gems); + writer.Write(Ore); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + Gems = reader.ReadInt(); + Ore = reader.ReadInt(); + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 1: - CartType = (MiningCartType)reader.ReadInt(); - goto case 0; - case 0: - IsRewardItem = reader.ReadBool(); - Gems = reader.ReadInt(); - Ore = reader.ReadInt(); - - DateTime next = reader.ReadDateTime(); - - if (next < DateTime.UtcNow) - next = DateTime.UtcNow; - - m_Timer = Timer.DelayCall(next - DateTime.UtcNow, TimeSpan.FromDays(1), GiveResources); - break; - } - } - } - - public class MiningCartDeed : BaseAddonDeed, IRewardItem, IRewardOption - { - private MiningCartType m_CartType; - - private bool m_IsRewardItem; - - [Constructible] - public MiningCartDeed() => LootType = LootType.Blessed; - - public MiningCartDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1080385; // deed for a mining cart decoration - - public override BaseAddon Addon - { - get - { - MiningCart addon = new MiningCart(m_CartType); - addon.IsRewardItem = m_IsRewardItem; - addon.Gems = Gems; - addon.Ore = Ore; - - return addon; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Gems { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Ore { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public void GetOptions(RewardOptionList list) - { - list.Add((int)MiningCartType.OreSouth, 1080391); - list.Add((int)MiningCartType.OreEast, 1080390); - list.Add((int)MiningCartType.GemSouth, 1080500); - list.Add((int)MiningCartType.GemEast, 1080499); - } - - public void OnOptionSelected(Mobile from, int choice) - { - m_CartType = (MiningCartType)choice; - - if (!Deleted) - base.OnDoubleClick(from); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_IsRewardItem) - list.Add(1080457); // 10th Year Veteran Reward - } - - public override void OnDoubleClick(Mobile from) - { - if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) - return; - - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new RewardOptionGump(this)); - } - else - { - from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - writer.Write(Gems); - writer.Write(Ore); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - Gems = reader.ReadInt(); - Ore = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/MinotaurStatue.cs b/Projects/UOContent/Items/Special/Veteran Rewards/MinotaurStatue.cs index e72b9512b..8de4e14d9 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/MinotaurStatue.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/MinotaurStatue.cs @@ -3,183 +3,183 @@ using Server.Gumps; namespace Server.Items { - public enum MinotaurStatueType - { - AttackSouth = 100, - AttackEast = 101, - DefendSouth = 102, - DefendEast = 103 - } - - public class MinotaurStatue : BaseAddon, IRewardItem - { - private bool m_IsRewardItem; - - [Constructible] - public MinotaurStatue(MinotaurStatueType type) + public enum MinotaurStatueType { - switch (type) - { - case MinotaurStatueType.AttackSouth: - AddComponent(new AddonComponent(0x306C), 0, 0, 0); - AddComponent(new AddonComponent(0x306D), -1, 0, 0); - AddComponent(new AddonComponent(0x306E), 0, -1, 0); - break; - case MinotaurStatueType.AttackEast: - AddComponent(new AddonComponent(0x3074), 0, 0, 0); - AddComponent(new AddonComponent(0x3075), -1, 0, 0); - AddComponent(new AddonComponent(0x3076), 0, -1, 0); - break; - case MinotaurStatueType.DefendSouth: - AddComponent(new AddonComponent(0x3072), 0, 0, 0); - AddComponent(new AddonComponent(0x3073), 0, -1, 0); - break; - case MinotaurStatueType.DefendEast: - AddComponent(new AddonComponent(0x306F), 0, 0, 0); - AddComponent(new AddonComponent(0x3070), -1, 0, 0); - AddComponent(new AddonComponent(0x3071), 0, -1, 0); - break; - } + AttackSouth = 100, + AttackEast = 101, + DefendSouth = 102, + DefendEast = 103 } - public MinotaurStatue(Serial serial) : base(serial) + public class MinotaurStatue : BaseAddon, IRewardItem { + private bool m_IsRewardItem; + + [Constructible] + public MinotaurStatue(MinotaurStatueType type) + { + switch (type) + { + case MinotaurStatueType.AttackSouth: + AddComponent(new AddonComponent(0x306C), 0, 0, 0); + AddComponent(new AddonComponent(0x306D), -1, 0, 0); + AddComponent(new AddonComponent(0x306E), 0, -1, 0); + break; + case MinotaurStatueType.AttackEast: + AddComponent(new AddonComponent(0x3074), 0, 0, 0); + AddComponent(new AddonComponent(0x3075), -1, 0, 0); + AddComponent(new AddonComponent(0x3076), 0, -1, 0); + break; + case MinotaurStatueType.DefendSouth: + AddComponent(new AddonComponent(0x3072), 0, 0, 0); + AddComponent(new AddonComponent(0x3073), 0, -1, 0); + break; + case MinotaurStatueType.DefendEast: + AddComponent(new AddonComponent(0x306F), 0, 0, 0); + AddComponent(new AddonComponent(0x3070), -1, 0, 0); + AddComponent(new AddonComponent(0x3071), 0, -1, 0); + break; + } + } + + public MinotaurStatue(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed + { + get + { + var deed = new MinotaurStatueDeed(); + deed.IsRewardItem = m_IsRewardItem; + + return deed; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + } } - public override BaseAddonDeed Deed + public class MinotaurStatueDeed : BaseAddonDeed, IRewardItem, IRewardOption { - get - { - MinotaurStatueDeed deed = new MinotaurStatueDeed(); - deed.IsRewardItem = m_IsRewardItem; + private bool m_IsRewardItem; - return deed; - } + private MinotaurStatueType m_StatueType; + + [Constructible] + public MinotaurStatueDeed() => LootType = LootType.Blessed; + + public MinotaurStatueDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1080409; // Minotaur Statue Deed + + public override BaseAddon Addon + { + get + { + var addon = new MinotaurStatue(m_StatueType); + addon.IsRewardItem = m_IsRewardItem; + + return addon; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public void GetOptions(RewardOptionList list) + { + list.Add((int)MinotaurStatueType.AttackSouth, 1080410); // Minotaur Attack South + list.Add((int)MinotaurStatueType.AttackEast, 1080411); // Minotaur Attack East + list.Add((int)MinotaurStatueType.DefendSouth, 1080412); // Minotaur Defend South + list.Add((int)MinotaurStatueType.DefendEast, 1080413); // Minotaur Defend East + } + + public void OnOptionSelected(Mobile from, int option) + { + m_StatueType = (MinotaurStatueType)option; + + if (!Deleted) + base.OnDoubleClick(from); + } + + public override void OnDoubleClick(Mobile from) + { + if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) + return; + + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new RewardOptionGump(this)); + } + else + { + from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_IsRewardItem) + list.Add(1076218); // 2nd Year Veteran Reward + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + } } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - } - } - - public class MinotaurStatueDeed : BaseAddonDeed, IRewardItem, IRewardOption - { - private bool m_IsRewardItem; - - private MinotaurStatueType m_StatueType; - - [Constructible] - public MinotaurStatueDeed() => LootType = LootType.Blessed; - - public MinotaurStatueDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1080409; // Minotaur Statue Deed - - public override BaseAddon Addon - { - get - { - MinotaurStatue addon = new MinotaurStatue(m_StatueType); - addon.IsRewardItem = m_IsRewardItem; - - return addon; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public void GetOptions(RewardOptionList list) - { - list.Add((int)MinotaurStatueType.AttackSouth, 1080410); // Minotaur Attack South - list.Add((int)MinotaurStatueType.AttackEast, 1080411); // Minotaur Attack East - list.Add((int)MinotaurStatueType.DefendSouth, 1080412); // Minotaur Defend South - list.Add((int)MinotaurStatueType.DefendEast, 1080413); // Minotaur Defend East - } - - public void OnOptionSelected(Mobile from, int option) - { - m_StatueType = (MinotaurStatueType)option; - - if (!Deleted) - base.OnDoubleClick(from); - } - - public override void OnDoubleClick(Mobile from) - { - if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) - return; - - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new RewardOptionGump(this)); - } - else - { - from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_IsRewardItem) - list.Add(1076218); // 2nd Year Veteran Reward - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - } - } } diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/PottedCactus.cs b/Projects/UOContent/Items/Special/Veteran Rewards/PottedCactus.cs index b064bb668..444b648ef 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/PottedCactus.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/PottedCactus.cs @@ -4,186 +4,186 @@ using Server.Network; namespace Server.Items { - public class RewardPottedCactus : Item, IRewardItem - { - private bool m_IsRewardItem; - - [Constructible] - public RewardPottedCactus() : this(Utility.RandomMinMax(0x1E0F, 0x1E14)) + public class RewardPottedCactus : Item, IRewardItem { - } + private bool m_IsRewardItem; - [Constructible] - public RewardPottedCactus(int itemID) : base(itemID) => Weight = 5.0; - - public RewardPottedCactus(Serial serial) : base(serial) - { - } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(1); // version - - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = version switch - { - 1 => reader.ReadBool(), - _ => m_IsRewardItem - }; - } - } - - public class PottedCactusDeed : Item, IRewardItem - { - private bool m_IsRewardItem; - - [Constructible] - public PottedCactusDeed() : base(0x14F0) - { - LootType = LootType.Blessed; - Weight = 1.0; - } - - public PottedCactusDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1080407; // Potted Cactus Deed - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void OnDoubleClick(Mobile from) - { - if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) - return; - - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new InternalGump(this)); - } - else - { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_IsRewardItem) - list.Add(1076219); // 3rd Year Veteran Reward - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - } - - private class InternalGump : Gump - { - private readonly PottedCactusDeed m_Cactus; - - public InternalGump(PottedCactusDeed cactus) : base(100, 200) - { - m_Cactus = cactus; - - Closable = true; - Disposable = true; - Draggable = true; - Resizable = false; - - AddPage(0); - AddBackground(0, 0, 425, 250, 0xA28); - - AddPage(1); - AddLabel(45, 15, 0, "Choose a Potted Cactus:"); - - AddItem(45, 75, 0x1E0F); - AddButton(55, 50, 0x845, 0x846, 0x1E0F); - - AddItem(105, 75, 0x1E10); - AddButton(115, 50, 0x845, 0x846, 0x1E10); - - AddItem(160, 75, 0x1E14); - AddButton(175, 50, 0x845, 0x846, 0x1E14); - - AddItem(220, 75, 0x1E11); - AddButton(235, 50, 0x845, 0x846, 0x1E11); - - AddItem(280, 75, 0x1E12); - AddButton(295, 50, 0x845, 0x846, 0x1E12); - - AddItem(340, 75, 0x1E13); - AddButton(355, 50, 0x845, 0x846, 0x1E13); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Cactus?.Deleted != false || info.ButtonID < 0x1E0F || info.ButtonID > 0x1E14) - return; - - RewardPottedCactus cactus = new RewardPottedCactus(info.ButtonID) + [Constructible] + public RewardPottedCactus() : this(Utility.RandomMinMax(0x1E0F, 0x1E14)) { - IsRewardItem = m_Cactus.IsRewardItem - }; - - if (!sender.Mobile.PlaceInBackpack(cactus)) - { - cactus.Delete(); - sender.Mobile.SendLocalizedMessage(1078837); // Your backpack is full! Please make room and try again. } - else + + [Constructible] + public RewardPottedCactus(int itemID) : base(itemID) => Weight = 5.0; + + public RewardPottedCactus(Serial serial) : base(serial) { - m_Cactus.Delete(); } - } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(1); // version + + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = version switch + { + 1 => reader.ReadBool(), + _ => m_IsRewardItem + }; + } + } + + public class PottedCactusDeed : Item, IRewardItem + { + private bool m_IsRewardItem; + + [Constructible] + public PottedCactusDeed() : base(0x14F0) + { + LootType = LootType.Blessed; + Weight = 1.0; + } + + public PottedCactusDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1080407; // Potted Cactus Deed + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void OnDoubleClick(Mobile from) + { + if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) + return; + + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new InternalGump(this)); + } + else + { + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_IsRewardItem) + list.Add(1076219); // 3rd Year Veteran Reward + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + } + + private class InternalGump : Gump + { + private readonly PottedCactusDeed m_Cactus; + + public InternalGump(PottedCactusDeed cactus) : base(100, 200) + { + m_Cactus = cactus; + + Closable = true; + Disposable = true; + Draggable = true; + Resizable = false; + + AddPage(0); + AddBackground(0, 0, 425, 250, 0xA28); + + AddPage(1); + AddLabel(45, 15, 0, "Choose a Potted Cactus:"); + + AddItem(45, 75, 0x1E0F); + AddButton(55, 50, 0x845, 0x846, 0x1E0F); + + AddItem(105, 75, 0x1E10); + AddButton(115, 50, 0x845, 0x846, 0x1E10); + + AddItem(160, 75, 0x1E14); + AddButton(175, 50, 0x845, 0x846, 0x1E14); + + AddItem(220, 75, 0x1E11); + AddButton(235, 50, 0x845, 0x846, 0x1E11); + + AddItem(280, 75, 0x1E12); + AddButton(295, 50, 0x845, 0x846, 0x1E12); + + AddItem(340, 75, 0x1E13); + AddButton(355, 50, 0x845, 0x846, 0x1E13); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Cactus?.Deleted != false || info.ButtonID < 0x1E0F || info.ButtonID > 0x1E14) + return; + + var cactus = new RewardPottedCactus(info.ButtonID) + { + IsRewardItem = m_Cactus.IsRewardItem + }; + + if (!sender.Mobile.PlaceInBackpack(cactus)) + { + cactus.Delete(); + sender.Mobile.SendLocalizedMessage(1078837); // Your backpack is full! Please make room and try again. + } + else + { + m_Cactus.Delete(); + } + } + } } - } } diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/StoneAnkh.cs b/Projects/UOContent/Items/Special/Veteran Rewards/StoneAnkh.cs index fa869665b..cfae21f8b 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/StoneAnkh.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/StoneAnkh.cs @@ -5,263 +5,264 @@ using Server.Network; namespace Server.Items { - public class StoneAnkhComponent : AddonComponent - { - public StoneAnkhComponent(int itemID) : base(itemID) => Weight = 1.0; - - public StoneAnkhComponent(Serial serial) : base(serial) + public class StoneAnkhComponent : AddonComponent { - } + public StoneAnkhComponent(int itemID) : base(itemID) => Weight = 1.0; - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Addon is StoneAnkh ankh && ankh.IsRewardItem) - list.Add(1076221); // 5th Year Veteran Reward - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class StoneAnkh : BaseAddon, IRewardItem - { - private bool m_IsRewardItem; - - [Constructible] - public StoneAnkh(bool east = true) - { - if (east) - { - AddComponent(new StoneAnkhComponent(0x2), 0, 0, 0); - AddComponent(new StoneAnkhComponent(0x3), 0, -1, 0); - } - else - { - AddComponent(new StoneAnkhComponent(0x5), 0, 0, 0); - AddComponent(new StoneAnkhComponent(0x4), -1, 0, 0); - } - } - - public StoneAnkh(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed - { - get - { - StoneAnkhDeed deed = new StoneAnkhDeed(); - deed.IsRewardItem = m_IsRewardItem; - - return deed; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void OnChop(Mobile from) - { - from.SendLocalizedMessage(500489); // You can't use an axe on that. - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Core.ML && m_IsRewardItem) - list.Add(1076221); // 5th Year Veteran Reward - } - - public override void OnComponentUsed(AddonComponent c, Mobile from) - { - if (from.InRange(Location, 2)) - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (house?.IsOwner(from) == true) + public StoneAnkhComponent(Serial serial) : base(serial) { - from.CloseGump(); - from.SendGump(new RewardDemolitionGump(this, 1049783)); // Do you wish to re-deed this decoration? } - else + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + public override void GetProperties(ObjectPropertyList list) { - from.SendLocalizedMessage( - 1049784); // You can only re-deed this decoration if you are the house owner or originally placed the decoration. + base.GetProperties(list); + + if (Addon is StoneAnkh ankh && ankh.IsRewardItem) + list.Add(1076221); // 5th Year Veteran Reward + } + + 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(); } - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } } - public override void Serialize(IGenericWriter writer) + public class StoneAnkh : BaseAddon, IRewardItem { - base.Serialize(writer); + private bool m_IsRewardItem; - writer.WriteEncodedInt(0); // version + [Constructible] + public StoneAnkh(bool east = true) + { + if (east) + { + AddComponent(new StoneAnkhComponent(0x2), 0, 0, 0); + AddComponent(new StoneAnkhComponent(0x3), 0, -1, 0); + } + else + { + AddComponent(new StoneAnkhComponent(0x5), 0, 0, 0); + AddComponent(new StoneAnkhComponent(0x4), -1, 0, 0); + } + } - writer.Write(m_IsRewardItem); + public StoneAnkh(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed + { + get + { + var deed = new StoneAnkhDeed(); + deed.IsRewardItem = m_IsRewardItem; + + return deed; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void OnChop(Mobile from) + { + from.SendLocalizedMessage(500489); // You can't use an axe on that. + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (Core.ML && m_IsRewardItem) + list.Add(1076221); // 5th Year Veteran Reward + } + + public override void OnComponentUsed(AddonComponent c, Mobile from) + { + if (from.InRange(Location, 2)) + { + var house = BaseHouse.FindHouseAt(this); + + if (house?.IsOwner(from) == true) + { + from.CloseGump(); + from.SendGump(new RewardDemolitionGump(this, 1049783)); // Do you wish to re-deed this decoration? + } + else + { + from.SendLocalizedMessage( + 1049784 + ); // You can only re-deed this decoration if you are the house owner or originally placed the decoration. + } + } + else + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + } } - public override void Deserialize(IGenericReader reader) + public class StoneAnkhDeed : BaseAddonDeed, IRewardItem { - base.Deserialize(reader); + private bool m_East; + private bool m_IsRewardItem; - int version = reader.ReadEncodedInt(); + [Constructible] + public StoneAnkhDeed() => LootType = LootType.Blessed; - m_IsRewardItem = reader.ReadBool(); + public StoneAnkhDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1049773; // deed for a stone ankh + + public override BaseAddon Addon + { + get + { + var addon = new StoneAnkh(m_East); + addon.IsRewardItem = m_IsRewardItem; + + return addon; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void OnDoubleClick(Mobile from) + { + if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) + return; + + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new InternalGump(this)); + } + else + { + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. + } + } + + private void SendTarget(Mobile m) + { + base.OnDoubleClick(m); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_IsRewardItem) + list.Add(1076221); // 5th Year Veteran Reward + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + } + + private class InternalGump : Gump + { + private readonly StoneAnkhDeed m_Deed; + + public InternalGump(StoneAnkhDeed deed) : base(150, 50) + { + m_Deed = deed; + + Closable = true; + Disposable = true; + Draggable = true; + Resizable = false; + + AddPage(0); + + AddBackground(0, 0, 300, 150, 0xA28); + + AddItem(90, 30, 0x4); + AddItem(112, 30, 0x5); + AddButton(50, 35, 0x867, 0x869, (int)Buttons.South); // South + + AddItem(170, 30, 0x2); + AddItem(192, 30, 0x3); + AddButton(145, 35, 0x867, 0x869, (int)Buttons.East); // East + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Deed?.Deleted != false || info.ButtonID == (int)Buttons.Cancel) + return; + + m_Deed.m_East = info.ButtonID == (int)Buttons.East; + m_Deed.SendTarget(sender.Mobile); + } + + private enum Buttons + { + Cancel, + South, + East + } + } } - } - - public class StoneAnkhDeed : BaseAddonDeed, IRewardItem - { - private bool m_East; - private bool m_IsRewardItem; - - [Constructible] - public StoneAnkhDeed() => LootType = LootType.Blessed; - - public StoneAnkhDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1049773; // deed for a stone ankh - - public override BaseAddon Addon - { - get - { - StoneAnkh addon = new StoneAnkh(m_East); - addon.IsRewardItem = m_IsRewardItem; - - return addon; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void OnDoubleClick(Mobile from) - { - if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) - return; - - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new InternalGump(this)); - } - else - { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. - } - } - - private void SendTarget(Mobile m) - { - base.OnDoubleClick(m); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_IsRewardItem) - list.Add(1076221); // 5th Year Veteran Reward - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - } - - private class InternalGump : Gump - { - private readonly StoneAnkhDeed m_Deed; - - public InternalGump(StoneAnkhDeed deed) : base(150, 50) - { - m_Deed = deed; - - Closable = true; - Disposable = true; - Draggable = true; - Resizable = false; - - AddPage(0); - - AddBackground(0, 0, 300, 150, 0xA28); - - AddItem(90, 30, 0x4); - AddItem(112, 30, 0x5); - AddButton(50, 35, 0x867, 0x869, (int)Buttons.South); // South - - AddItem(170, 30, 0x2); - AddItem(192, 30, 0x3); - AddButton(145, 35, 0x867, 0x869, (int)Buttons.East); // East - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Deed?.Deleted != false || info.ButtonID == (int)Buttons.Cancel) - return; - - m_Deed.m_East = info.ButtonID == (int)Buttons.East; - m_Deed.SendTarget(sender.Mobile); - } - - private enum Buttons - { - Cancel, - South, - East - } - } - } } diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/TreeStump.cs b/Projects/UOContent/Items/Special/Veteran Rewards/TreeStump.cs index 28644738c..816c013d3 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/TreeStump.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/TreeStump.cs @@ -6,283 +6,283 @@ using Server.Network; namespace Server.Items { - public class TreeStump : BaseAddon, IRewardItem - { - private bool m_IsRewardItem; - - private int m_Logs; - - private Timer m_Timer; - - [Constructible] - public TreeStump(int itemID) + public class TreeStump : BaseAddon, IRewardItem { - AddComponent(new AddonComponent(itemID), 0, 0, 0); + private bool m_IsRewardItem; - m_Timer = Timer.DelayCall(TimeSpan.FromDays(1), TimeSpan.FromDays(1), GiveLogs); - } + private int m_Logs; - public TreeStump(Serial serial) : base(serial) - { - } + private Timer m_Timer; - public override BaseAddonDeed Deed - { - get - { - TreeStumpDeed deed = new TreeStumpDeed(); - deed.IsRewardItem = m_IsRewardItem; - deed.Logs = m_Logs; - - return deed; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Logs - { - get => m_Logs; - set - { - m_Logs = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - private void GiveLogs() - { - m_Logs = Math.Min(100, m_Logs + 10); - } - - public override void OnComponentUsed(AddonComponent c, Mobile from) - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - /* - * Unique problems have unique solutions. OSI does not have a problem with 1000s of mining carts - * due to the fact that they have only a miniscule fraction of the number of 10 year vets that a - * typical RunUO shard will have (RunUO's scaled down account aging system makes this a unique problem), - * and the "freeness" of free accounts. We also dont have mitigating factors like inactive (unpaid) - * accounts not gaining veteran time. - * - * The lack of high end vets and vet rewards on OSI has made testing the *exact* ranging/stacking - * behavior of these things all but impossible, so either way its just an estimation. - * - * If youd like your shard's carts/stumps to work the way they did before, simply replace the check - * below with this line of code: - * - * if (!from.InRange(GetWorldLocation(), 2) - * - * However, I am sure these checks are more accurate to OSI than the former version was. - * - */ - - if (!from.InRange(GetWorldLocation(), 2) || !from.InLOS(this) || !(from.Z - Z > -3 && from.Z - Z < 3)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. - } - else if (house?.HasSecureAccess(from, SecureLevel.Friends) == true) - { - if (m_Logs > 0) + [Constructible] + public TreeStump(int itemID) { - var logs = Utility.Random(7) switch - { - 0 => new Log(), - 1 => new AshLog(), - 2 => new OakLog(), - 3 => new YewLog(), - 4 => new HeartwoodLog(), - 5 => new BloodwoodLog(), - 6 => new FrostwoodLog(), - _ => null - }; + AddComponent(new AddonComponent(itemID), 0, 0, 0); - int amount = Math.Min(10, m_Logs); - // ReSharper disable once PossibleNullReferenceException - logs.Amount = amount; - - if (!from.PlaceInBackpack(logs)) - { - logs.Delete(); - from.SendLocalizedMessage(1078837); // Your backpack is full! Please make room and try again. - } - else - { - m_Logs -= amount; - PublicOverheadMessage(MessageType.Regular, 0, 1094719, m_Logs.ToString()); // Logs: ~1_COUNT~ - } + m_Timer = Timer.DelayCall(TimeSpan.FromDays(1), TimeSpan.FromDays(1), GiveLogs); } - else + + public TreeStump(Serial serial) : base(serial) { - from.SendLocalizedMessage(1094720); // There are no more logs available. } - } - else - { - from.SendLocalizedMessage(1061637); // You are not allowed to access this. - } + + public override BaseAddonDeed Deed + { + get + { + var deed = new TreeStumpDeed(); + deed.IsRewardItem = m_IsRewardItem; + deed.Logs = m_Logs; + + return deed; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Logs + { + get => m_Logs; + set + { + m_Logs = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + private void GiveLogs() + { + m_Logs = Math.Min(100, m_Logs + 10); + } + + public override void OnComponentUsed(AddonComponent c, Mobile from) + { + var house = BaseHouse.FindHouseAt(this); + + /* + * Unique problems have unique solutions. OSI does not have a problem with 1000s of mining carts + * due to the fact that they have only a miniscule fraction of the number of 10 year vets that a + * typical RunUO shard will have (RunUO's scaled down account aging system makes this a unique problem), + * and the "freeness" of free accounts. We also dont have mitigating factors like inactive (unpaid) + * accounts not gaining veteran time. + * + * The lack of high end vets and vet rewards on OSI has made testing the *exact* ranging/stacking + * behavior of these things all but impossible, so either way its just an estimation. + * + * If youd like your shard's carts/stumps to work the way they did before, simply replace the check + * below with this line of code: + * + * if (!from.InRange(GetWorldLocation(), 2) + * + * However, I am sure these checks are more accurate to OSI than the former version was. + * + */ + + if (!from.InRange(GetWorldLocation(), 2) || !from.InLOS(this) || !(from.Z - Z > -3 && from.Z - Z < 3)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + else if (house?.HasSecureAccess(from, SecureLevel.Friends) == true) + { + if (m_Logs > 0) + { + var logs = Utility.Random(7) switch + { + 0 => new Log(), + 1 => new AshLog(), + 2 => new OakLog(), + 3 => new YewLog(), + 4 => new HeartwoodLog(), + 5 => new BloodwoodLog(), + 6 => new FrostwoodLog(), + _ => null + }; + + var amount = Math.Min(10, m_Logs); + // ReSharper disable once PossibleNullReferenceException + logs.Amount = amount; + + if (!from.PlaceInBackpack(logs)) + { + logs.Delete(); + from.SendLocalizedMessage(1078837); // Your backpack is full! Please make room and try again. + } + else + { + m_Logs -= amount; + PublicOverheadMessage(MessageType.Regular, 0, 1094719, m_Logs.ToString()); // Logs: ~1_COUNT~ + } + } + else + { + from.SendLocalizedMessage(1094720); // There are no more logs available. + } + } + else + { + from.SendLocalizedMessage(1061637); // You are not allowed to access this. + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + writer.Write(m_Logs); + + if (m_Timer != null) + writer.Write(m_Timer.Next); + else + writer.Write(DateTime.UtcNow + TimeSpan.FromDays(1)); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + m_Logs = reader.ReadInt(); + + var next = reader.ReadDateTime(); + + if (next < DateTime.UtcNow) + next = DateTime.UtcNow; + + m_Timer = Timer.DelayCall(next - DateTime.UtcNow, TimeSpan.FromDays(1), GiveLogs); + } } - public override void Serialize(IGenericWriter writer) + public class TreeStumpDeed : BaseAddonDeed, IRewardItem, IRewardOption { - base.Serialize(writer); + private bool m_IsRewardItem; - writer.WriteEncodedInt(0); // version + private int m_ItemID; - writer.Write(m_IsRewardItem); - writer.Write(m_Logs); + private int m_Logs; - if (m_Timer != null) - writer.Write(m_Timer.Next); - else - writer.Write(DateTime.UtcNow + TimeSpan.FromDays(1)); + [Constructible] + public TreeStumpDeed() => LootType = LootType.Blessed; + + public TreeStumpDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1080406; // a deed for a tree stump decoration + + public override BaseAddon Addon + { + get + { + var addon = new TreeStump(m_ItemID); + addon.IsRewardItem = m_IsRewardItem; + addon.Logs = m_Logs; + + return addon; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Logs + { + get => m_Logs; + set + { + m_Logs = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public void GetOptions(RewardOptionList list) + { + list.Add(1, 1080403); // Tree Stump with Axe West + list.Add(2, 1080404); // Tree Stump with Axe North + list.Add(3, 1080401); // Tree Stump East + list.Add(4, 1080402); // Tree Stump South + } + + public void OnOptionSelected(Mobile from, int option) + { + m_ItemID = option switch + { + 1 => 0xE56, + 2 => 0xE58, + 3 => 0xE57, + 4 => 0xE59, + _ => m_ItemID + }; + + if (!Deleted) + base.OnDoubleClick(from); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_IsRewardItem) + list.Add(1076223); // 7th Year Veteran Reward + } + + public override void OnDoubleClick(Mobile from) + { + if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) + return; + + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new RewardOptionGump(this)); + } + else + { + from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + writer.Write(m_Logs); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + m_Logs = reader.ReadInt(); + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - m_Logs = reader.ReadInt(); - - DateTime next = reader.ReadDateTime(); - - if (next < DateTime.UtcNow) - next = DateTime.UtcNow; - - m_Timer = Timer.DelayCall(next - DateTime.UtcNow, TimeSpan.FromDays(1), GiveLogs); - } - } - - public class TreeStumpDeed : BaseAddonDeed, IRewardItem, IRewardOption - { - private bool m_IsRewardItem; - - private int m_ItemID; - - private int m_Logs; - - [Constructible] - public TreeStumpDeed() => LootType = LootType.Blessed; - - public TreeStumpDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1080406; // a deed for a tree stump decoration - - public override BaseAddon Addon - { - get - { - TreeStump addon = new TreeStump(m_ItemID); - addon.IsRewardItem = m_IsRewardItem; - addon.Logs = m_Logs; - - return addon; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Logs - { - get => m_Logs; - set - { - m_Logs = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public void GetOptions(RewardOptionList list) - { - list.Add(1, 1080403); // Tree Stump with Axe West - list.Add(2, 1080404); // Tree Stump with Axe North - list.Add(3, 1080401); // Tree Stump East - list.Add(4, 1080402); // Tree Stump South - } - - public void OnOptionSelected(Mobile from, int option) - { - m_ItemID = option switch - { - 1 => 0xE56, - 2 => 0xE58, - 3 => 0xE57, - 4 => 0xE59, - _ => m_ItemID - }; - - if (!Deleted) - base.OnDoubleClick(from); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_IsRewardItem) - list.Add(1076223); // 7th Year Veteran Reward - } - - public override void OnDoubleClick(Mobile from) - { - if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) - return; - - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new RewardOptionGump(this)); - } - else - { - from.SendLocalizedMessage(1062334); // This item must be in your backpack to be used. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - writer.Write(m_Logs); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - m_Logs = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/WallBanner.cs b/Projects/UOContent/Items/Special/Veteran Rewards/WallBanner.cs index 1f04e4c15..273f6fd14 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/WallBanner.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/WallBanner.cs @@ -4,502 +4,502 @@ using Server.Network; namespace Server.Items { - public class WallBannerComponent : AddonComponent, IDyable - { - public WallBannerComponent(int itemID) : base(itemID) + public class WallBannerComponent : AddonComponent, IDyable { + public WallBannerComponent(int itemID) : base(itemID) + { + } + + public WallBannerComponent(Serial serial) : base(serial) + { + } + + public override bool NeedsWall => true; + public override Point3D WallPosition => East ? new Point3D(-1, 0, 0) : new Point3D(0, -1, 0); + + public bool East => ((WallBanner)Addon).East; + + public bool Dye(Mobile from, DyeTub sender) + { + if (Deleted) + return false; + + if (Addon != null) + Addon.Hue = sender.DyedHue; + + return true; + } + + 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(); + } } - public WallBannerComponent(Serial serial) : base(serial) + public class WallBanner : BaseAddon, IRewardItem { + private bool m_East; + + private bool m_IsRewardItem; + + [Constructible] + public WallBanner(int bannerID) + { + m_East = bannerID % 2 == 1; + + switch (bannerID) + { + case 1: + AddComponent(new WallBannerComponent(0x161F), 0, 0, 0); + AddComponent(new WallBannerComponent(0x161E), 0, 1, 0); + AddComponent(new WallBannerComponent(0x161D), 0, 2, 0); + break; + case 2: + AddComponent(new WallBannerComponent(0x1586), 0, 0, 0); + AddComponent(new WallBannerComponent(0x1587), 1, 0, 0); + AddComponent(new WallBannerComponent(0x1588), 2, 0, 0); + break; + case 3: + AddComponent(new WallBannerComponent(0x1622), 0, 0, 0); + AddComponent(new WallBannerComponent(0x1621), 0, 1, 0); + AddComponent(new WallBannerComponent(0x1620), 0, 2, 0); + break; + case 4: + AddComponent(new WallBannerComponent(0x1589), 0, 0, 0); + AddComponent(new WallBannerComponent(0x158A), 1, 0, 0); + AddComponent(new WallBannerComponent(0x158B), 2, 0, 0); + break; + case 5: + AddComponent(new WallBannerComponent(0x1625), 0, 0, 0); + AddComponent(new WallBannerComponent(0x1624), 0, 1, 0); + AddComponent(new WallBannerComponent(0x1623), 0, 2, 0); + break; + case 6: + AddComponent(new WallBannerComponent(0x158C), 0, 0, 0); + AddComponent(new WallBannerComponent(0x158D), 1, 0, 0); + AddComponent(new WallBannerComponent(0x158E), 2, 0, 0); + break; + case 7: + AddComponent(new WallBannerComponent(0x1628), 0, 0, 0); + AddComponent(new WallBannerComponent(0x1627), 0, 1, 0); + AddComponent(new WallBannerComponent(0x1626), 0, 2, 0); + break; + case 8: + AddComponent(new WallBannerComponent(0x1590), 0, 0, 0); + AddComponent(new WallBannerComponent(0x1591), 1, 0, 0); + AddComponent(new WallBannerComponent(0x158F), 2, 0, 0); + break; + case 9: + AddComponent(new WallBannerComponent(0x162A), 0, 0, 0); + AddComponent(new WallBannerComponent(0x1629), 0, 1, 0); + AddComponent(new WallBannerComponent(0x1626), 0, 2, 0); + break; + case 10: + AddComponent(new WallBannerComponent(0x1592), 0, 0, 0); + AddComponent(new WallBannerComponent(0x1593), 1, 0, 0); + AddComponent(new WallBannerComponent(0x158F), 2, 0, 0); + break; + case 11: + AddComponent(new WallBannerComponent(0x162D), 0, 0, 0); + AddComponent(new WallBannerComponent(0x162C), 0, 1, 0); + AddComponent(new WallBannerComponent(0x162B), 0, 2, 0); + break; + case 12: + AddComponent(new WallBannerComponent(0x1594), 0, 0, 0); + AddComponent(new WallBannerComponent(0x1595), 1, 0, 0); + AddComponent(new WallBannerComponent(0x1596), 2, 0, 0); + break; + case 13: + AddComponent(new WallBannerComponent(0x1632), 0, 0, 0); + AddComponent(new WallBannerComponent(0x1631), 0, 1, 0); + AddComponent(new WallBannerComponent(0x162E), 0, 2, 0); + break; + case 14: + AddComponent(new WallBannerComponent(0x1598), 0, 0, 0); + AddComponent(new WallBannerComponent(0x159B), 1, 0, 0); + AddComponent(new WallBannerComponent(0x159C), 2, 0, 0); + break; + case 15: + AddComponent(new WallBannerComponent(0x1633), 0, 0, 0); + AddComponent(new WallBannerComponent(0x1630), 0, 1, 0); + AddComponent(new WallBannerComponent(0x162F), 0, 2, 0); + break; + case 16: + AddComponent(new WallBannerComponent(0x1599), 0, 0, 0); + AddComponent(new WallBannerComponent(0x159A), 1, 0, 0); + AddComponent(new WallBannerComponent(0x159D), 2, 0, 0); + break; + + case 17: + AddComponent(new WallBannerComponent(0x1610), 0, 0, 0); + AddComponent(new WallBannerComponent(0x160F), 0, 1, 0); + break; + case 18: + AddComponent(new WallBannerComponent(0x15A0), 0, 0, 0); + AddComponent(new WallBannerComponent(0x15A1), 1, 0, 0); + break; + + case 19: + AddComponent(new WallBannerComponent(0x1612), 0, 0, 0); + AddComponent(new WallBannerComponent(0x1611), 0, 1, 0); + break; + case 20: + AddComponent(new WallBannerComponent(0x15A2), 0, 0, 0); + AddComponent(new WallBannerComponent(0x15A3), 1, 0, 0); + break; + + case 21: + AddComponent(new WallBannerComponent(0x1614), 0, 0, 0); + AddComponent(new WallBannerComponent(0x1613), 0, 1, 0); + break; + case 22: + AddComponent(new WallBannerComponent(0x15A4), 0, 0, 0); + AddComponent(new WallBannerComponent(0x15A5), 1, 0, 0); + break; + + case 23: + AddComponent(new WallBannerComponent(0x1616), 0, 0, 0); + AddComponent(new WallBannerComponent(0x1615), 0, 1, 0); + break; + case 24: + AddComponent(new WallBannerComponent(0x15A6), 0, 0, 0); + AddComponent(new WallBannerComponent(0x15A7), 1, 0, 0); + break; + + case 25: + AddComponent(new WallBannerComponent(0x1618), 0, 0, 0); + AddComponent(new WallBannerComponent(0x1617), 0, 1, 0); + break; + case 26: + AddComponent(new WallBannerComponent(0x15A8), 0, 0, 0); + AddComponent(new WallBannerComponent(0x15A9), 1, 0, 0); + break; + + case 27: + AddComponent(new WallBannerComponent(0x161A), 0, 0, 0); + AddComponent(new WallBannerComponent(0x1619), 0, 1, 0); + break; + case 28: + AddComponent(new WallBannerComponent(0x15AA), 0, 0, 0); + AddComponent(new WallBannerComponent(0x15AB), 1, 0, 0); + break; + + case 29: + AddComponent(new WallBannerComponent(0x161C), 0, 0, 0); + AddComponent(new WallBannerComponent(0x161B), 0, 1, 0); + break; + case 30: + AddComponent(new WallBannerComponent(0x15AC), 0, 0, 0); + AddComponent(new WallBannerComponent(0x15AD), 1, 0, 0); + break; + } + } + + public WallBanner(Serial serial) : base(serial) + { + } + + public override BaseAddonDeed Deed + { + get + { + var deed = new WallBannerDeed(); + deed.IsRewardItem = m_IsRewardItem; + + return deed; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool East + { + get => m_East; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_East); + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_East = reader.ReadBool(); + m_IsRewardItem = reader.ReadBool(); + } } - public override bool NeedsWall => true; - public override Point3D WallPosition => East ? new Point3D(-1, 0, 0) : new Point3D(0, -1, 0); - - public bool East => ((WallBanner)Addon).East; - - public bool Dye(Mobile from, DyeTub sender) + public class WallBannerDeed : BaseAddonDeed, IRewardItem { - if (Deleted) - return false; + private int m_BannerID; + private bool m_IsRewardItem; - if (Addon != null) - Addon.Hue = sender.DyedHue; + [Constructible] + public WallBannerDeed() => LootType = LootType.Blessed; - return true; + public WallBannerDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1080549; // Wall Banner Deed + + public override BaseAddon Addon + { + get + { + var addon = new WallBanner(m_BannerID); + addon.IsRewardItem = m_IsRewardItem; + + return addon; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_IsRewardItem) + list.Add(1076225); // 9th Year Veteran Reward + } + + public override void OnDoubleClick(Mobile from) + { + if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) + return; + + if (IsChildOf(from.Backpack)) + { + from.CloseGump(); + from.SendGump(new InternalGump(this)); + } + else + { + from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. + } + } + + public void Use(Mobile m, int bannerID) + { + m_BannerID = bannerID; + + base.OnDoubleClick(m); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_IsRewardItem = reader.ReadBool(); + } + + private class InternalGump : Gump + { + private readonly WallBannerDeed m_WallBanner; + + public InternalGump(WallBannerDeed wallBanner) : base(150, 50) + { + m_WallBanner = wallBanner; + + Closable = true; + Disposable = true; + Draggable = true; + Resizable = false; + + AddBackground(25, 0, 500, 265, 0xA28); + AddLabel(70, 12, 0x3E3, "Choose a Wall Banner:"); + + AddPage(1); + + AddItem(55, 110, 0x161D); + AddItem(75, 90, 0x161E); + AddItem(95, 70, 0x161F); + AddButton(70, 50, 0x845, 0x846, 1); + AddItem(105, 70, 0x1586); + AddItem(125, 90, 0x1587); + AddItem(145, 110, 0x1588); + AddButton(145, 50, 0x845, 0x846, 2); + AddItem(200, 110, 0x1620); + AddItem(220, 90, 0x1621); + AddItem(240, 70, 0x1622); + AddButton(220, 50, 0x845, 0x846, 3); + AddItem(250, 70, 0x1589); + AddItem(270, 90, 0x158A); + AddItem(290, 110, 0x158B); + AddButton(300, 50, 0x845, 0x846, 4); + AddItem(350, 110, 0x1623); + AddItem(370, 90, 0x1624); + AddItem(390, 70, 0x1625); + AddButton(365, 50, 0x845, 0x846, 5); + AddItem(400, 70, 0x158C); + AddItem(420, 90, 0x158D); + AddItem(440, 110, 0x158E); + AddButton(445, 50, 0x845, 0x846, 6); + AddButton(455, 205, 0x8B0, 0x8B0, 0, GumpButtonType.Page, 2); + + AddPage(2); + + AddItem(52, 110, 0x1626); + AddItem(72, 90, 0x1627); + AddItem(95, 70, 0x1628); + AddButton(70, 50, 0x845, 0x846, 7); + AddItem(105, 70, 0x1590); + AddItem(125, 90, 0x1591); + AddItem(145, 110, 0x158F); + AddButton(145, 50, 0x845, 0x846, 8); + AddItem(197, 110, 0x1626); + AddItem(217, 90, 0x1629); + AddItem(240, 70, 0x162A); + AddButton(220, 50, 0x845, 0x846, 9); + AddItem(250, 70, 0x1592); + AddItem(270, 90, 0x1593); + AddItem(290, 110, 0x158F); + AddButton(300, 50, 0x845, 0x846, 10); + AddItem(340, 110, 0x162B); + AddItem(363, 90, 0x162C); + AddItem(385, 70, 0x162D); + AddButton(365, 50, 0x845, 0x846, 11); + AddItem(395, 70, 0x1594); + AddItem(417, 90, 0x1595); + AddItem(439, 111, 0x1596); + AddButton(445, 50, 0x845, 0x846, 12); + AddButton(70, 205, 0x8AF, 0x8AF, 0, GumpButtonType.Page, 1); + AddButton(455, 205, 0x8B0, 0x8B0, 0, GumpButtonType.Page, 3); + + AddPage(3); + + AddItem(55, 110, 0x162E); + AddItem(75, 93, 0x1631); + AddItem(95, 70, 0x1632); + AddButton(70, 50, 0x845, 0x846, 13); + AddItem(118, 70, 0x1598); + AddItem(138, 94, 0x159B); + AddItem(159, 113, 0x159C); + AddButton(160, 50, 0x845, 0x846, 14); + AddItem(219, 111, 0x162F); + AddItem(238, 94, 0x1630); + AddItem(258, 70, 0x1633); + AddButton(240, 50, 0x845, 0x846, 15); + AddItem(279, 70, 0x1599); + AddItem(298, 93, 0x159A); + AddItem(319, 113, 0x159D); + AddButton(320, 50, 0x845, 0x846, 16); + AddItem(380, 90, 0x160F); + AddItem(400, 70, 0x1610); + AddButton(390, 50, 0x845, 0x846, 17); + AddItem(420, 70, 0x15A0); + AddItem(440, 90, 0x15A1); + AddButton(455, 50, 0x845, 0x846, 18); + AddButton(70, 205, 0x8AF, 0x8AF, 0, GumpButtonType.Page, 2); + AddButton(455, 205, 0x8B0, 0x8B0, 0, GumpButtonType.Page, 4); + + AddPage(4); + + AddItem(55, 90, 0x1611); + AddItem(75, 70, 0x1612); + AddButton(70, 50, 0x845, 0x846, 19); + AddItem(105, 70, 0x15A2); + AddItem(125, 90, 0x15A3); + AddButton(145, 50, 0x845, 0x846, 20); + AddItem(200, 84, 0x1613); + AddItem(220, 70, 0x1614); + AddButton(215, 50, 0x845, 0x846, 21); + AddItem(250, 70, 0x15A4); + AddItem(270, 84, 0x15A5); + AddButton(290, 50, 0x845, 0x846, 22); + AddItem(350, 90, 0x1615); + AddItem(370, 70, 0x1616); + AddButton(365, 50, 0x845, 0x846, 23); + AddItem(400, 70, 0x15A6); + AddItem(420, 90, 0x15A7); + AddButton(445, 50, 0x845, 0x846, 24); + AddButton(70, 205, 0x8AF, 0x8AF, 0, GumpButtonType.Page, 3); + AddButton(455, 205, 0x8B0, 0x8B0, 0, GumpButtonType.Page, 5); + + AddPage(5); + + AddItem(55, 90, 0x1617); + AddItem(77, 70, 0x1618); + AddButton(70, 50, 0x845, 0x846, 25); + AddItem(105, 70, 0x15A8); + AddItem(127, 90, 0x15A9); + AddButton(145, 50, 0x845, 0x846, 26); + AddItem(200, 90, 0x1619); + AddItem(222, 70, 0x161A); + AddButton(220, 50, 0x845, 0x846, 27); + AddItem(250, 70, 0x15AA); + AddItem(272, 90, 0x15AB); + AddButton(300, 50, 0x845, 0x846, 28); + AddItem(350, 90, 0x161B); + AddItem(372, 70, 0x161C); + AddButton(365, 50, 0x845, 0x846, 29); + AddItem(400, 70, 0x15AC); + AddItem(422, 90, 0x15AD); + AddButton(445, 50, 0x845, 0x846, 30); + AddButton(70, 205, 0x8AF, 0x8AF, 0, GumpButtonType.Page, 4); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_WallBanner?.Deleted != false || info.ButtonID <= 0 || info.ButtonID >= 31) + return; + + m_WallBanner.Use(sender.Mobile, info.ButtonID); + } + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class WallBanner : BaseAddon, IRewardItem - { - private bool m_East; - - private bool m_IsRewardItem; - - [Constructible] - public WallBanner(int bannerID) - { - m_East = bannerID % 2 == 1; - - switch (bannerID) - { - case 1: - AddComponent(new WallBannerComponent(0x161F), 0, 0, 0); - AddComponent(new WallBannerComponent(0x161E), 0, 1, 0); - AddComponent(new WallBannerComponent(0x161D), 0, 2, 0); - break; - case 2: - AddComponent(new WallBannerComponent(0x1586), 0, 0, 0); - AddComponent(new WallBannerComponent(0x1587), 1, 0, 0); - AddComponent(new WallBannerComponent(0x1588), 2, 0, 0); - break; - case 3: - AddComponent(new WallBannerComponent(0x1622), 0, 0, 0); - AddComponent(new WallBannerComponent(0x1621), 0, 1, 0); - AddComponent(new WallBannerComponent(0x1620), 0, 2, 0); - break; - case 4: - AddComponent(new WallBannerComponent(0x1589), 0, 0, 0); - AddComponent(new WallBannerComponent(0x158A), 1, 0, 0); - AddComponent(new WallBannerComponent(0x158B), 2, 0, 0); - break; - case 5: - AddComponent(new WallBannerComponent(0x1625), 0, 0, 0); - AddComponent(new WallBannerComponent(0x1624), 0, 1, 0); - AddComponent(new WallBannerComponent(0x1623), 0, 2, 0); - break; - case 6: - AddComponent(new WallBannerComponent(0x158C), 0, 0, 0); - AddComponent(new WallBannerComponent(0x158D), 1, 0, 0); - AddComponent(new WallBannerComponent(0x158E), 2, 0, 0); - break; - case 7: - AddComponent(new WallBannerComponent(0x1628), 0, 0, 0); - AddComponent(new WallBannerComponent(0x1627), 0, 1, 0); - AddComponent(new WallBannerComponent(0x1626), 0, 2, 0); - break; - case 8: - AddComponent(new WallBannerComponent(0x1590), 0, 0, 0); - AddComponent(new WallBannerComponent(0x1591), 1, 0, 0); - AddComponent(new WallBannerComponent(0x158F), 2, 0, 0); - break; - case 9: - AddComponent(new WallBannerComponent(0x162A), 0, 0, 0); - AddComponent(new WallBannerComponent(0x1629), 0, 1, 0); - AddComponent(new WallBannerComponent(0x1626), 0, 2, 0); - break; - case 10: - AddComponent(new WallBannerComponent(0x1592), 0, 0, 0); - AddComponent(new WallBannerComponent(0x1593), 1, 0, 0); - AddComponent(new WallBannerComponent(0x158F), 2, 0, 0); - break; - case 11: - AddComponent(new WallBannerComponent(0x162D), 0, 0, 0); - AddComponent(new WallBannerComponent(0x162C), 0, 1, 0); - AddComponent(new WallBannerComponent(0x162B), 0, 2, 0); - break; - case 12: - AddComponent(new WallBannerComponent(0x1594), 0, 0, 0); - AddComponent(new WallBannerComponent(0x1595), 1, 0, 0); - AddComponent(new WallBannerComponent(0x1596), 2, 0, 0); - break; - case 13: - AddComponent(new WallBannerComponent(0x1632), 0, 0, 0); - AddComponent(new WallBannerComponent(0x1631), 0, 1, 0); - AddComponent(new WallBannerComponent(0x162E), 0, 2, 0); - break; - case 14: - AddComponent(new WallBannerComponent(0x1598), 0, 0, 0); - AddComponent(new WallBannerComponent(0x159B), 1, 0, 0); - AddComponent(new WallBannerComponent(0x159C), 2, 0, 0); - break; - case 15: - AddComponent(new WallBannerComponent(0x1633), 0, 0, 0); - AddComponent(new WallBannerComponent(0x1630), 0, 1, 0); - AddComponent(new WallBannerComponent(0x162F), 0, 2, 0); - break; - case 16: - AddComponent(new WallBannerComponent(0x1599), 0, 0, 0); - AddComponent(new WallBannerComponent(0x159A), 1, 0, 0); - AddComponent(new WallBannerComponent(0x159D), 2, 0, 0); - break; - - case 17: - AddComponent(new WallBannerComponent(0x1610), 0, 0, 0); - AddComponent(new WallBannerComponent(0x160F), 0, 1, 0); - break; - case 18: - AddComponent(new WallBannerComponent(0x15A0), 0, 0, 0); - AddComponent(new WallBannerComponent(0x15A1), 1, 0, 0); - break; - - case 19: - AddComponent(new WallBannerComponent(0x1612), 0, 0, 0); - AddComponent(new WallBannerComponent(0x1611), 0, 1, 0); - break; - case 20: - AddComponent(new WallBannerComponent(0x15A2), 0, 0, 0); - AddComponent(new WallBannerComponent(0x15A3), 1, 0, 0); - break; - - case 21: - AddComponent(new WallBannerComponent(0x1614), 0, 0, 0); - AddComponent(new WallBannerComponent(0x1613), 0, 1, 0); - break; - case 22: - AddComponent(new WallBannerComponent(0x15A4), 0, 0, 0); - AddComponent(new WallBannerComponent(0x15A5), 1, 0, 0); - break; - - case 23: - AddComponent(new WallBannerComponent(0x1616), 0, 0, 0); - AddComponent(new WallBannerComponent(0x1615), 0, 1, 0); - break; - case 24: - AddComponent(new WallBannerComponent(0x15A6), 0, 0, 0); - AddComponent(new WallBannerComponent(0x15A7), 1, 0, 0); - break; - - case 25: - AddComponent(new WallBannerComponent(0x1618), 0, 0, 0); - AddComponent(new WallBannerComponent(0x1617), 0, 1, 0); - break; - case 26: - AddComponent(new WallBannerComponent(0x15A8), 0, 0, 0); - AddComponent(new WallBannerComponent(0x15A9), 1, 0, 0); - break; - - case 27: - AddComponent(new WallBannerComponent(0x161A), 0, 0, 0); - AddComponent(new WallBannerComponent(0x1619), 0, 1, 0); - break; - case 28: - AddComponent(new WallBannerComponent(0x15AA), 0, 0, 0); - AddComponent(new WallBannerComponent(0x15AB), 1, 0, 0); - break; - - case 29: - AddComponent(new WallBannerComponent(0x161C), 0, 0, 0); - AddComponent(new WallBannerComponent(0x161B), 0, 1, 0); - break; - case 30: - AddComponent(new WallBannerComponent(0x15AC), 0, 0, 0); - AddComponent(new WallBannerComponent(0x15AD), 1, 0, 0); - break; - } - } - - public WallBanner(Serial serial) : base(serial) - { - } - - public override BaseAddonDeed Deed - { - get - { - WallBannerDeed deed = new WallBannerDeed(); - deed.IsRewardItem = m_IsRewardItem; - - return deed; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool East - { - get => m_East; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_East); - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_East = reader.ReadBool(); - m_IsRewardItem = reader.ReadBool(); - } - } - - public class WallBannerDeed : BaseAddonDeed, IRewardItem - { - private int m_BannerID; - private bool m_IsRewardItem; - - [Constructible] - public WallBannerDeed() => LootType = LootType.Blessed; - - public WallBannerDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1080549; // Wall Banner Deed - - public override BaseAddon Addon - { - get - { - WallBanner addon = new WallBanner(m_BannerID); - addon.IsRewardItem = m_IsRewardItem; - - return addon; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_IsRewardItem) - list.Add(1076225); // 9th Year Veteran Reward - } - - public override void OnDoubleClick(Mobile from) - { - if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) - return; - - if (IsChildOf(from.Backpack)) - { - from.CloseGump(); - from.SendGump(new InternalGump(this)); - } - else - { - from.SendLocalizedMessage(1042038); // You must have the object in your backpack to use it. - } - } - - public void Use(Mobile m, int bannerID) - { - m_BannerID = bannerID; - - base.OnDoubleClick(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_IsRewardItem = reader.ReadBool(); - } - - private class InternalGump : Gump - { - private readonly WallBannerDeed m_WallBanner; - - public InternalGump(WallBannerDeed wallBanner) : base(150, 50) - { - m_WallBanner = wallBanner; - - Closable = true; - Disposable = true; - Draggable = true; - Resizable = false; - - AddBackground(25, 0, 500, 265, 0xA28); - AddLabel(70, 12, 0x3E3, "Choose a Wall Banner:"); - - AddPage(1); - - AddItem(55, 110, 0x161D); - AddItem(75, 90, 0x161E); - AddItem(95, 70, 0x161F); - AddButton(70, 50, 0x845, 0x846, 1); - AddItem(105, 70, 0x1586); - AddItem(125, 90, 0x1587); - AddItem(145, 110, 0x1588); - AddButton(145, 50, 0x845, 0x846, 2); - AddItem(200, 110, 0x1620); - AddItem(220, 90, 0x1621); - AddItem(240, 70, 0x1622); - AddButton(220, 50, 0x845, 0x846, 3); - AddItem(250, 70, 0x1589); - AddItem(270, 90, 0x158A); - AddItem(290, 110, 0x158B); - AddButton(300, 50, 0x845, 0x846, 4); - AddItem(350, 110, 0x1623); - AddItem(370, 90, 0x1624); - AddItem(390, 70, 0x1625); - AddButton(365, 50, 0x845, 0x846, 5); - AddItem(400, 70, 0x158C); - AddItem(420, 90, 0x158D); - AddItem(440, 110, 0x158E); - AddButton(445, 50, 0x845, 0x846, 6); - AddButton(455, 205, 0x8B0, 0x8B0, 0, GumpButtonType.Page, 2); - - AddPage(2); - - AddItem(52, 110, 0x1626); - AddItem(72, 90, 0x1627); - AddItem(95, 70, 0x1628); - AddButton(70, 50, 0x845, 0x846, 7); - AddItem(105, 70, 0x1590); - AddItem(125, 90, 0x1591); - AddItem(145, 110, 0x158F); - AddButton(145, 50, 0x845, 0x846, 8); - AddItem(197, 110, 0x1626); - AddItem(217, 90, 0x1629); - AddItem(240, 70, 0x162A); - AddButton(220, 50, 0x845, 0x846, 9); - AddItem(250, 70, 0x1592); - AddItem(270, 90, 0x1593); - AddItem(290, 110, 0x158F); - AddButton(300, 50, 0x845, 0x846, 10); - AddItem(340, 110, 0x162B); - AddItem(363, 90, 0x162C); - AddItem(385, 70, 0x162D); - AddButton(365, 50, 0x845, 0x846, 11); - AddItem(395, 70, 0x1594); - AddItem(417, 90, 0x1595); - AddItem(439, 111, 0x1596); - AddButton(445, 50, 0x845, 0x846, 12); - AddButton(70, 205, 0x8AF, 0x8AF, 0, GumpButtonType.Page, 1); - AddButton(455, 205, 0x8B0, 0x8B0, 0, GumpButtonType.Page, 3); - - AddPage(3); - - AddItem(55, 110, 0x162E); - AddItem(75, 93, 0x1631); - AddItem(95, 70, 0x1632); - AddButton(70, 50, 0x845, 0x846, 13); - AddItem(118, 70, 0x1598); - AddItem(138, 94, 0x159B); - AddItem(159, 113, 0x159C); - AddButton(160, 50, 0x845, 0x846, 14); - AddItem(219, 111, 0x162F); - AddItem(238, 94, 0x1630); - AddItem(258, 70, 0x1633); - AddButton(240, 50, 0x845, 0x846, 15); - AddItem(279, 70, 0x1599); - AddItem(298, 93, 0x159A); - AddItem(319, 113, 0x159D); - AddButton(320, 50, 0x845, 0x846, 16); - AddItem(380, 90, 0x160F); - AddItem(400, 70, 0x1610); - AddButton(390, 50, 0x845, 0x846, 17); - AddItem(420, 70, 0x15A0); - AddItem(440, 90, 0x15A1); - AddButton(455, 50, 0x845, 0x846, 18); - AddButton(70, 205, 0x8AF, 0x8AF, 0, GumpButtonType.Page, 2); - AddButton(455, 205, 0x8B0, 0x8B0, 0, GumpButtonType.Page, 4); - - AddPage(4); - - AddItem(55, 90, 0x1611); - AddItem(75, 70, 0x1612); - AddButton(70, 50, 0x845, 0x846, 19); - AddItem(105, 70, 0x15A2); - AddItem(125, 90, 0x15A3); - AddButton(145, 50, 0x845, 0x846, 20); - AddItem(200, 84, 0x1613); - AddItem(220, 70, 0x1614); - AddButton(215, 50, 0x845, 0x846, 21); - AddItem(250, 70, 0x15A4); - AddItem(270, 84, 0x15A5); - AddButton(290, 50, 0x845, 0x846, 22); - AddItem(350, 90, 0x1615); - AddItem(370, 70, 0x1616); - AddButton(365, 50, 0x845, 0x846, 23); - AddItem(400, 70, 0x15A6); - AddItem(420, 90, 0x15A7); - AddButton(445, 50, 0x845, 0x846, 24); - AddButton(70, 205, 0x8AF, 0x8AF, 0, GumpButtonType.Page, 3); - AddButton(455, 205, 0x8B0, 0x8B0, 0, GumpButtonType.Page, 5); - - AddPage(5); - - AddItem(55, 90, 0x1617); - AddItem(77, 70, 0x1618); - AddButton(70, 50, 0x845, 0x846, 25); - AddItem(105, 70, 0x15A8); - AddItem(127, 90, 0x15A9); - AddButton(145, 50, 0x845, 0x846, 26); - AddItem(200, 90, 0x1619); - AddItem(222, 70, 0x161A); - AddButton(220, 50, 0x845, 0x846, 27); - AddItem(250, 70, 0x15AA); - AddItem(272, 90, 0x15AB); - AddButton(300, 50, 0x845, 0x846, 28); - AddItem(350, 90, 0x161B); - AddItem(372, 70, 0x161C); - AddButton(365, 50, 0x845, 0x846, 29); - AddItem(400, 70, 0x15AC); - AddItem(422, 90, 0x15AD); - AddButton(445, 50, 0x845, 0x846, 30); - AddButton(70, 205, 0x8AF, 0x8AF, 0, GumpButtonType.Page, 4); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_WallBanner?.Deleted != false || info.ButtonID <= 0 || info.ButtonID >= 31) - return; - - m_WallBanner.Use(sender.Mobile, info.ButtonID); - } - } - } } diff --git a/Projects/UOContent/Items/Special/Veteran Rewards/WeaponEngravingTool.cs b/Projects/UOContent/Items/Special/Veteran Rewards/WeaponEngravingTool.cs index d864d54ab..09219efaa 100644 --- a/Projects/UOContent/Items/Special/Veteran Rewards/WeaponEngravingTool.cs +++ b/Projects/UOContent/Items/Special/Veteran Rewards/WeaponEngravingTool.cs @@ -6,332 +6,363 @@ using Server.Targeting; namespace Server.Items { - public class WeaponEngravingTool : Item, IUsesRemaining, IRewardItem - { - private bool m_IsRewardItem; - - private int m_UsesRemaining; - - [Constructible] - public WeaponEngravingTool(int uses = 10) : base(0x32F8) + public class WeaponEngravingTool : Item, IUsesRemaining, IRewardItem { - LootType = LootType.Blessed; - Weight = 1.0; + private bool m_IsRewardItem; - m_UsesRemaining = uses; + private int m_UsesRemaining; + + [Constructible] + public WeaponEngravingTool(int uses = 10) : base(0x32F8) + { + LootType = LootType.Blessed; + Weight = 1.0; + + m_UsesRemaining = uses; + } + + public WeaponEngravingTool(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1076158; // Weapon Engraving Tool + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem + { + get => m_IsRewardItem; + set + { + m_IsRewardItem = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int UsesRemaining + { + get => m_UsesRemaining; + set + { + m_UsesRemaining = value; + InvalidateProperties(); + } + } + + public bool ShowUsesRemaining + { + get => true; + set { } + } + + public override void OnDoubleClick(Mobile from) + { + if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) + return; + + if (m_UsesRemaining > 0) + { + from.SendLocalizedMessage(1072357); // Select an object to engrave. + from.Target = new TargetWeapon(this); + } + else + { + if (from.Skills.Tinkering.Value == 0) + { + from.SendLocalizedMessage( + 1076179 + ); // Since you have no tinkering skill, you will need to find an NPC tinkerer to repair this for you. + } + else if (from.Skills.Tinkering.Value < 75.0) + { + from.SendLocalizedMessage( + 1076178 + ); // Your tinkering skill is too low to fix this yourself. An NPC tinkerer can help you repair this for a fee. + } + else + { + if (from.Backpack.FindItemByType() != null) + from.SendGump(new ConfirmGump(this, null)); + else + from.SendLocalizedMessage( + 1076166 + ); // You do not have a blue diamond needed to recharge the engraving tool. + } + + from.SendLocalizedMessage(1076163); // There are no charges left on this engraving tool. + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_IsRewardItem) + list.Add(1076224); // 8th Year Veteran Reward + + if (ShowUsesRemaining) + list.Add(1060584, m_UsesRemaining.ToString()); // uses remaining: ~1_val~ + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_UsesRemaining); + writer.Write(m_IsRewardItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_UsesRemaining = reader.ReadInt(); + m_IsRewardItem = reader.ReadBool(); + } + + public virtual void Recharge(Mobile from, Mobile guildmaster) + { + if (from.Backpack == null) + return; + + var diamond = from.Backpack.FindItemByType(); + + if (guildmaster != null) + { + if (m_UsesRemaining <= 0) + { + if (diamond != null && Banker.Withdraw(from, 100000)) + { + diamond.Consume(); + UsesRemaining = 10; + guildmaster.Say(1076165); // Your weapon engraver should be good as new! + } + else + { + guildmaster.Say( + 1076167 + ); // You need a 100,000 gold and a blue diamond to recharge the weapon engraver. + } + } + else + { + guildmaster.Say( + 1076164 + ); // I can only help with this if you are carrying an engraving tool that needs repair. + } + } + else + { + if (from.Skills.Tinkering.Value == 0) + { + from.SendLocalizedMessage( + 1076179 + ); // Since you have no tinkering skill, you will need to find an NPC tinkerer to repair this for you. + } + else if (from.Skills.Tinkering.Value < 75.0) + { + from.SendLocalizedMessage( + 1076178 + ); // Your tinkering skill is too low to fix this yourself. An NPC tinkerer can help you repair this for a fee. + } + else if (diamond != null) + { + diamond.Consume(); + + if (Utility.RandomDouble() < from.Skills.Tinkering.Value / 100) + { + UsesRemaining = 10; + from.SendLocalizedMessage(1076165); // Your weapon engraver should be good as new! ????? + } + else + { + from.SendLocalizedMessage( + 1076175 + ); // You cracked the diamond attempting to fix the weapon engraver. + } + } + else + { + from.SendLocalizedMessage( + 1076166 + ); // You do not have a blue diamond needed to recharge the engraving tool. + } + } + } + + public static WeaponEngravingTool Find(Mobile from) => from.Backpack?.FindItemByType(); + + private class TargetWeapon : Target + { + private readonly WeaponEngravingTool m_Tool; + + public TargetWeapon(WeaponEngravingTool tool) : base(-1, true, TargetFlags.None) => m_Tool = tool; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Tool?.Deleted != false) + return; + + if (targeted is BaseWeapon item) + { + from.CloseGump(); + from.SendGump(new InternalGump(m_Tool, item)); + } + else + { + from.SendLocalizedMessage(1072309); // The selected item cannot be engraved by this engraving tool. + } + } + } + + private class InternalGump : Gump + { + private readonly BaseWeapon m_Target; + private readonly WeaponEngravingTool m_Tool; + + public InternalGump(WeaponEngravingTool tool, BaseWeapon target) : base(0, 0) + { + m_Tool = tool; + m_Target = target; + + Closable = true; + Disposable = true; + Draggable = true; + Resizable = false; + + AddBackground(50, 50, 400, 300, 0xA28); + + AddPage(0); + + AddHtmlLocalized(50, 70, 400, 20, 1072359, 0x0); //
Engraving Tool
+ AddHtmlLocalized( + 75, + 95, + 350, + 145, + 1076229, + 0x0, + true, + true + ); // Please enter the text to add to the selected object. Leave the text area blank to remove any existing text. Removing text does not use a charge. + AddButton(125, 300, 0x81A, 0x81B, (int)Buttons.Okay); + AddButton(320, 300, 0x819, 0x818, (int)Buttons.Cancel); + AddImageTiled(75, 245, 350, 40, 0xDB0); + AddImageTiled(76, 245, 350, 2, 0x23C5); + AddImageTiled(75, 245, 2, 40, 0x23C3); + AddImageTiled(75, 285, 350, 2, 0x23C5); + AddImageTiled(425, 245, 2, 42, 0x23C3); + + AddTextEntry(75, 245, 350, 40, 0x0, (int)Buttons.Text, ""); + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (m_Tool?.Deleted != false || m_Target?.Deleted != false) + return; + + if (info.ButtonID != (int)Buttons.Okay) + { + state.Mobile.SendLocalizedMessage(1072363); // The object was not engraved. + return; + } + + var relay = info.GetTextEntry((int)Buttons.Text); + + if (relay == null) + return; + + if (string.IsNullOrEmpty(relay.Text)) + { + m_Target.EngravedText = null; + state.Mobile.SendLocalizedMessage(1072362); // You remove the engraving from the object. + } + else + { + m_Target.EngravedText = + Utility.FixHtml(relay.Text.Length > 64 ? relay.Text.Substring(0, 64) : relay.Text); + state.Mobile.SendLocalizedMessage(1072361); // You engraved the object. + m_Target.InvalidateProperties(); + m_Tool.UsesRemaining -= 1; + m_Tool.InvalidateProperties(); + } + } + + private enum Buttons + { + Cancel, + Okay, + Text + } + } + + public class ConfirmGump : Gump + { + private readonly WeaponEngravingTool m_Engraver; + private readonly Mobile m_Guildmaster; + + public ConfirmGump(WeaponEngravingTool engraver, Mobile guildmaster) : base(200, 200) + { + m_Engraver = engraver; + m_Guildmaster = guildmaster; + + Closable = false; + Disposable = true; + Draggable = true; + Resizable = false; + + AddPage(0); + + AddBackground(0, 0, 291, 133, 0x13BE); + AddImageTiled(5, 5, 280, 100, 0xA40); + + if (guildmaster != null) + { + AddHtmlLocalized( + 9, + 9, + 272, + 100, + 1076169, + 0x7FFF + ); // It will cost you 100,000 gold and a blue diamond to recharge your weapon engraver with 10 charges. + AddHtmlLocalized(195, 109, 120, 20, 1076172, 0x7FFF); // Recharge it + } + else + { + AddHtmlLocalized( + 9, + 9, + 272, + 100, + 1076176, + 0x7FFF + ); // You will need a blue diamond to repair the tip of the engraver. A successful repair will give the engraver 10 charges. + AddHtmlLocalized(195, 109, 120, 20, 1076177, 0x7FFF); // Replace the tip. + } + + AddButton(160, 107, 0xFB7, 0xFB8, (int)Buttons.Confirm); + AddButton(5, 107, 0xFB1, 0xFB2, (int)Buttons.Cancel); + AddHtmlLocalized(40, 109, 100, 20, 1060051, 0x7FFF); // CANCEL + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (m_Engraver?.Deleted != false || info.ButtonID != (int)Buttons.Confirm) + return; + + m_Engraver.Recharge(state.Mobile, m_Guildmaster); + } + + private enum Buttons + { + Cancel, + Confirm + } + } } - - public WeaponEngravingTool(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1076158; // Weapon Engraving Tool - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem - { - get => m_IsRewardItem; - set - { - m_IsRewardItem = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int UsesRemaining - { - get => m_UsesRemaining; - set - { - m_UsesRemaining = value; - InvalidateProperties(); - } - } - - public bool ShowUsesRemaining - { - get => true; - set { } - } - - public override void OnDoubleClick(Mobile from) - { - if (m_IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this)) - return; - - if (m_UsesRemaining > 0) - { - from.SendLocalizedMessage(1072357); // Select an object to engrave. - from.Target = new TargetWeapon(this); - } - else - { - if (from.Skills.Tinkering.Value == 0) - { - from.SendLocalizedMessage( - 1076179); // Since you have no tinkering skill, you will need to find an NPC tinkerer to repair this for you. - } - else if (from.Skills.Tinkering.Value < 75.0) - { - from.SendLocalizedMessage( - 1076178); // Your tinkering skill is too low to fix this yourself. An NPC tinkerer can help you repair this for a fee. - } - else - { - if (from.Backpack.FindItemByType() != null) - from.SendGump(new ConfirmGump(this, null)); - else - from.SendLocalizedMessage( - 1076166); // You do not have a blue diamond needed to recharge the engraving tool. - } - - from.SendLocalizedMessage(1076163); // There are no charges left on this engraving tool. - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_IsRewardItem) - list.Add(1076224); // 8th Year Veteran Reward - - if (ShowUsesRemaining) - list.Add(1060584, m_UsesRemaining.ToString()); // uses remaining: ~1_val~ - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_UsesRemaining); - writer.Write(m_IsRewardItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_UsesRemaining = reader.ReadInt(); - m_IsRewardItem = reader.ReadBool(); - } - - public virtual void Recharge(Mobile from, Mobile guildmaster) - { - if (from.Backpack == null) - return; - - BlueDiamond diamond = from.Backpack.FindItemByType(); - - if (guildmaster != null) - { - if (m_UsesRemaining <= 0) - { - if (diamond != null && Banker.Withdraw(from, 100000)) - { - diamond.Consume(); - UsesRemaining = 10; - guildmaster.Say(1076165); // Your weapon engraver should be good as new! - } - else - { - guildmaster.Say( - 1076167); // You need a 100,000 gold and a blue diamond to recharge the weapon engraver. - } - } - else - { - guildmaster.Say( - 1076164); // I can only help with this if you are carrying an engraving tool that needs repair. - } - } - else - { - if (from.Skills.Tinkering.Value == 0) - { - from.SendLocalizedMessage( - 1076179); // Since you have no tinkering skill, you will need to find an NPC tinkerer to repair this for you. - } - else if (from.Skills.Tinkering.Value < 75.0) - { - from.SendLocalizedMessage( - 1076178); // Your tinkering skill is too low to fix this yourself. An NPC tinkerer can help you repair this for a fee. - } - else if (diamond != null) - { - diamond.Consume(); - - if (Utility.RandomDouble() < from.Skills.Tinkering.Value / 100) - { - UsesRemaining = 10; - from.SendLocalizedMessage(1076165); // Your weapon engraver should be good as new! ????? - } - else - { - from.SendLocalizedMessage( - 1076175); // You cracked the diamond attempting to fix the weapon engraver. - } - } - else - { - from.SendLocalizedMessage( - 1076166); // You do not have a blue diamond needed to recharge the engraving tool. - } - } - } - - public static WeaponEngravingTool Find(Mobile from) => from.Backpack?.FindItemByType(); - - private class TargetWeapon : Target - { - private readonly WeaponEngravingTool m_Tool; - - public TargetWeapon(WeaponEngravingTool tool) : base(-1, true, TargetFlags.None) => m_Tool = tool; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Tool?.Deleted != false) - return; - - if (targeted is BaseWeapon item) - { - from.CloseGump(); - from.SendGump(new InternalGump(m_Tool, item)); - } - else - { - from.SendLocalizedMessage(1072309); // The selected item cannot be engraved by this engraving tool. - } - } - } - - private class InternalGump : Gump - { - private readonly BaseWeapon m_Target; - private readonly WeaponEngravingTool m_Tool; - - public InternalGump(WeaponEngravingTool tool, BaseWeapon target) : base(0, 0) - { - m_Tool = tool; - m_Target = target; - - Closable = true; - Disposable = true; - Draggable = true; - Resizable = false; - - AddBackground(50, 50, 400, 300, 0xA28); - - AddPage(0); - - AddHtmlLocalized(50, 70, 400, 20, 1072359, 0x0); //
Engraving Tool
- AddHtmlLocalized(75, 95, 350, 145, 1076229, 0x0, true, - true); // Please enter the text to add to the selected object. Leave the text area blank to remove any existing text. Removing text does not use a charge. - AddButton(125, 300, 0x81A, 0x81B, (int)Buttons.Okay); - AddButton(320, 300, 0x819, 0x818, (int)Buttons.Cancel); - AddImageTiled(75, 245, 350, 40, 0xDB0); - AddImageTiled(76, 245, 350, 2, 0x23C5); - AddImageTiled(75, 245, 2, 40, 0x23C3); - AddImageTiled(75, 285, 350, 2, 0x23C5); - AddImageTiled(425, 245, 2, 42, 0x23C3); - - AddTextEntry(75, 245, 350, 40, 0x0, (int)Buttons.Text, ""); - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (m_Tool?.Deleted != false || m_Target?.Deleted != false) - return; - - if (info.ButtonID != (int)Buttons.Okay) - { - state.Mobile.SendLocalizedMessage(1072363); // The object was not engraved. - return; - } - - TextRelay relay = info.GetTextEntry((int)Buttons.Text); - - if (relay == null) - return; - - if (string.IsNullOrEmpty(relay.Text)) - { - m_Target.EngravedText = null; - state.Mobile.SendLocalizedMessage(1072362); // You remove the engraving from the object. - } - else - { - m_Target.EngravedText = Utility.FixHtml(relay.Text.Length > 64 ? - relay.Text.Substring(0, 64) : relay.Text); - state.Mobile.SendLocalizedMessage(1072361); // You engraved the object. - m_Target.InvalidateProperties(); - m_Tool.UsesRemaining -= 1; - m_Tool.InvalidateProperties(); - } - } - - private enum Buttons - { - Cancel, - Okay, - Text - } - } - - public class ConfirmGump : Gump - { - private readonly WeaponEngravingTool m_Engraver; - private readonly Mobile m_Guildmaster; - - public ConfirmGump(WeaponEngravingTool engraver, Mobile guildmaster) : base(200, 200) - { - m_Engraver = engraver; - m_Guildmaster = guildmaster; - - Closable = false; - Disposable = true; - Draggable = true; - Resizable = false; - - AddPage(0); - - AddBackground(0, 0, 291, 133, 0x13BE); - AddImageTiled(5, 5, 280, 100, 0xA40); - - if (guildmaster != null) - { - AddHtmlLocalized(9, 9, 272, 100, 1076169, 0x7FFF); // It will cost you 100,000 gold and a blue diamond to recharge your weapon engraver with 10 charges. - AddHtmlLocalized(195, 109, 120, 20, 1076172, 0x7FFF); // Recharge it - } - else - { - AddHtmlLocalized(9, 9, 272, 100, 1076176, 0x7FFF); // You will need a blue diamond to repair the tip of the engraver. A successful repair will give the engraver 10 charges. - AddHtmlLocalized(195, 109, 120, 20, 1076177, 0x7FFF); // Replace the tip. - } - - AddButton(160, 107, 0xFB7, 0xFB8, (int)Buttons.Confirm); - AddButton(5, 107, 0xFB1, 0xFB2, (int)Buttons.Cancel); - AddHtmlLocalized(40, 109, 100, 20, 1060051, 0x7FFF); // CANCEL - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (m_Engraver?.Deleted != false || info.ButtonID != (int)Buttons.Confirm) - return; - - m_Engraver.Recharge(state.Mobile, m_Guildmaster); - } - - private enum Buttons - { - Cancel, - Confirm - } - } - } } diff --git a/Projects/UOContent/Items/Suits/AdminRobe.cs b/Projects/UOContent/Items/Suits/AdminRobe.cs index eddc22cb4..7becdf49b 100644 --- a/Projects/UOContent/Items/Suits/AdminRobe.cs +++ b/Projects/UOContent/Items/Suits/AdminRobe.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class AdminRobe : BaseSuit - { - [Constructible] - public AdminRobe() : base(AccessLevel.Administrator, 0x0, 0x204F) // Blank hue + public class AdminRobe : BaseSuit { + [Constructible] + public AdminRobe() : base(AccessLevel.Administrator, 0x0, 0x204F) // Blank hue + { + } + + public AdminRobe(Serial serial) : base(serial) + { + } + + 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 AdminRobe(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Suits/BaseSuit.cs b/Projects/UOContent/Items/Suits/BaseSuit.cs index 753679646..1cf5b2d11 100644 --- a/Projects/UOContent/Items/Suits/BaseSuit.cs +++ b/Projects/UOContent/Items/Suits/BaseSuit.cs @@ -1,79 +1,79 @@ namespace Server.Items { - public abstract class BaseSuit : Item - { - public BaseSuit(AccessLevel level, int hue, int itemID) : base(itemID) + public abstract class BaseSuit : Item { - Hue = hue; - Weight = 1.0; - Movable = false; - LootType = LootType.Newbied; - Layer = Layer.OuterTorso; + public BaseSuit(AccessLevel level, int hue, int itemID) : base(itemID) + { + Hue = hue; + Weight = 1.0; + Movable = false; + LootType = LootType.Newbied; + Layer = Layer.OuterTorso; - AccessLevel = level; + AccessLevel = level; + } + + public BaseSuit(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.Administrator)] + public AccessLevel AccessLevel { get; set; } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write((int)AccessLevel); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + AccessLevel = (AccessLevel)reader.ReadInt(); + break; + } + } + } + + public bool Validate() + { + if (!(RootParent is Mobile mobile) || mobile.AccessLevel >= AccessLevel) + return true; + + Delete(); + return false; + } + + public override void OnSingleClick(Mobile from) + { + if (Validate()) + base.OnSingleClick(from); + } + + public override void OnDoubleClick(Mobile from) + { + if (Validate()) + base.OnDoubleClick(from); + } + + public override bool VerifyMove(Mobile from) => from.AccessLevel >= AccessLevel; + + public override bool OnEquip(Mobile from) + { + if (from.AccessLevel < AccessLevel) + from.SendMessage("You may not wear this."); + + return from.AccessLevel >= AccessLevel; + } } - - public BaseSuit(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.Administrator)] - public AccessLevel AccessLevel { get; set; } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write((int)AccessLevel); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - AccessLevel = (AccessLevel)reader.ReadInt(); - break; - } - } - } - - public bool Validate() - { - if (!(RootParent is Mobile mobile) || mobile.AccessLevel >= AccessLevel) - return true; - - Delete(); - return false; - } - - public override void OnSingleClick(Mobile from) - { - if (Validate()) - base.OnSingleClick(from); - } - - public override void OnDoubleClick(Mobile from) - { - if (Validate()) - base.OnDoubleClick(from); - } - - public override bool VerifyMove(Mobile from) => from.AccessLevel >= AccessLevel; - - public override bool OnEquip(Mobile from) - { - if (from.AccessLevel < AccessLevel) - from.SendMessage("You may not wear this."); - - return from.AccessLevel >= AccessLevel; - } - } } diff --git a/Projects/UOContent/Items/Suits/CounselorRobe.cs b/Projects/UOContent/Items/Suits/CounselorRobe.cs index 052e70ac4..96992c4da 100644 --- a/Projects/UOContent/Items/Suits/CounselorRobe.cs +++ b/Projects/UOContent/Items/Suits/CounselorRobe.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class CounselorRobe : BaseSuit - { - [Constructible] - public CounselorRobe() : base(AccessLevel.Counselor, 0x3, 0x204F) + public class CounselorRobe : BaseSuit { + [Constructible] + public CounselorRobe() : base(AccessLevel.Counselor, 0x3, 0x204F) + { + } + + public CounselorRobe(Serial serial) : base(serial) + { + } + + 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 CounselorRobe(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Suits/DeathShroud.cs b/Projects/UOContent/Items/Suits/DeathShroud.cs index 2b18cab9b..82339e7bc 100644 --- a/Projects/UOContent/Items/Suits/DeathShroud.cs +++ b/Projects/UOContent/Items/Suits/DeathShroud.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class DeathShroud : BaseSuit - { - [Constructible] - public DeathShroud() : base(AccessLevel.GameMaster, 0x0, 0x204E) + public class DeathShroud : BaseSuit { + [Constructible] + public DeathShroud() : base(AccessLevel.GameMaster, 0x0, 0x204E) + { + } + + public DeathShroud(Serial serial) : base(serial) + { + } + + 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 DeathShroud(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Suits/DupreSuit.cs b/Projects/UOContent/Items/Suits/DupreSuit.cs index 9a546dcfe..6456925cf 100644 --- a/Projects/UOContent/Items/Suits/DupreSuit.cs +++ b/Projects/UOContent/Items/Suits/DupreSuit.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class DupreSuit : BaseSuit - { - [Constructible] - public DupreSuit() : base(AccessLevel.GameMaster, 0x0, 0x2050) + public class DupreSuit : BaseSuit { + [Constructible] + public DupreSuit() : base(AccessLevel.GameMaster, 0x0, 0x2050) + { + } + + public DupreSuit(Serial serial) : base(serial) + { + } + + 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 DupreSuit(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Suits/GMRobe.cs b/Projects/UOContent/Items/Suits/GMRobe.cs index 586dbf72e..efe07b3ef 100644 --- a/Projects/UOContent/Items/Suits/GMRobe.cs +++ b/Projects/UOContent/Items/Suits/GMRobe.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class GMRobe : BaseSuit - { - [Constructible] - public GMRobe() : base(AccessLevel.GameMaster, 0x26, 0x204F) + public class GMRobe : BaseSuit { + [Constructible] + public GMRobe() : base(AccessLevel.GameMaster, 0x26, 0x204F) + { + } + + public GMRobe(Serial serial) : base(serial) + { + } + + 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 GMRobe(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Suits/LordBlackthorneSuit.cs b/Projects/UOContent/Items/Suits/LordBlackthorneSuit.cs index b803678d4..06552fd17 100644 --- a/Projects/UOContent/Items/Suits/LordBlackthorneSuit.cs +++ b/Projects/UOContent/Items/Suits/LordBlackthorneSuit.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class LordBlackthorneSuit : BaseSuit - { - [Constructible] - public LordBlackthorneSuit() : base(AccessLevel.GameMaster, 0x0, 0x2043) + public class LordBlackthorneSuit : BaseSuit { + [Constructible] + public LordBlackthorneSuit() : base(AccessLevel.GameMaster, 0x0, 0x2043) + { + } + + public LordBlackthorneSuit(Serial serial) : base(serial) + { + } + + 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 LordBlackthorneSuit(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Suits/LordBritishSuit.cs b/Projects/UOContent/Items/Suits/LordBritishSuit.cs index 93749b05e..5404e341e 100644 --- a/Projects/UOContent/Items/Suits/LordBritishSuit.cs +++ b/Projects/UOContent/Items/Suits/LordBritishSuit.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class LordBritishSuit : BaseSuit - { - [Constructible] - public LordBritishSuit() : base(AccessLevel.GameMaster, 0x0, 0x2042) + public class LordBritishSuit : BaseSuit { + [Constructible] + public LordBritishSuit() : base(AccessLevel.GameMaster, 0x0, 0x2042) + { + } + + public LordBritishSuit(Serial serial) : base(serial) + { + } + + 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 LordBritishSuit(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Suits/SeerRobe.cs b/Projects/UOContent/Items/Suits/SeerRobe.cs index c2aad235f..72980d62b 100644 --- a/Projects/UOContent/Items/Suits/SeerRobe.cs +++ b/Projects/UOContent/Items/Suits/SeerRobe.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class SeerRobe : BaseSuit - { - [Constructible] - public SeerRobe() : base(AccessLevel.Seer, 0x1D3, 0x204F) + public class SeerRobe : BaseSuit { + [Constructible] + public SeerRobe() : base(AccessLevel.Seer, 0x1D3, 0x204F) + { + } + + public SeerRobe(Serial serial) : base(serial) + { + } + + 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 SeerRobe(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Talismans/BaseTalisman.cs b/Projects/UOContent/Items/Talismans/BaseTalisman.cs index ebae08fda..3927bff06 100644 --- a/Projects/UOContent/Items/Talismans/BaseTalisman.cs +++ b/Projects/UOContent/Items/Talismans/BaseTalisman.cs @@ -10,1075 +10,1149 @@ using Server.Utilities; namespace Server.Items { - public enum TalismanRemoval - { - None = 0, - Ward = 390, - Damage = 404, - Curse = 407, - Wildfire = 2843 - } - - public class BaseTalisman : Item - { - private bool m_Blessed; - private int m_Charges; - private int m_ChargeTime; - - private int m_MaxCharges; - private int m_MaxChargeTime; - - public BaseTalisman() - : this(GetRandomItemID()) + public enum TalismanRemoval { + None = 0, + Ward = 390, + Damage = 404, + Curse = 407, + Wildfire = 2843 } - public BaseTalisman(int itemID) - : base(itemID) + public class BaseTalisman : Item { - Layer = Layer.Talisman; - Weight = 1.0; - - m_Protection = new TalismanAttribute(); - m_Killer = new TalismanAttribute(); - m_Summoner = new TalismanAttribute(); - Attributes = new AosAttributes(this); - SkillBonuses = new AosSkillBonuses(this); - } - - public BaseTalisman(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1071023; // Talisman - public virtual bool ForceShowName => false; // used to override default summoner/removal name - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxCharges - { - get => m_MaxCharges; - set - { - m_MaxCharges = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Charges - { - get => m_Charges; - set - { - m_Charges = value; - - if (m_ChargeTime > 0) - StartTimer(); - - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxChargeTime - { - get => m_MaxChargeTime; - set - { - m_MaxChargeTime = value; - InvalidateProperties(); - } - } - - public int ChargeTime - { - get => m_ChargeTime; - set - { - m_ChargeTime = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Blessed - { - get => m_Blessed; - set - { - m_Blessed = value; - InvalidateProperties(); - } - } - - public static void Initialize() - { - CommandSystem.Register("RandomTalisman", AccessLevel.GameMaster, RandomTalisman_OnCommand); - } - - [Usage("RandomTalisman ")] - [Description("Generates random talismans in your backpack.")] - public static void RandomTalisman_OnCommand(CommandEventArgs e) - { - Mobile m = e.Mobile; - int count = e.GetInt32(0); - - for (int i = 0; i < count; i++) - m.AddToBackpack(Loot.RandomTalisman()); - } - - public override void OnAfterDuped(Item newItem) - { - if (!(newItem is BaseTalisman talisman)) - return; - - talisman.m_Summoner = new TalismanAttribute(m_Summoner); - talisman.m_Protection = new TalismanAttribute(m_Protection); - talisman.m_Killer = new TalismanAttribute(m_Killer); - talisman.Attributes = new AosAttributes(newItem, Attributes); - talisman.SkillBonuses = new AosSkillBonuses(newItem, SkillBonuses); - } - - public override bool CanEquip(Mobile from) - { - if (BlessedFor != null && BlessedFor != from) - { - from.SendLocalizedMessage(1010437); // You are not the owner. - return false; - } - - return base.CanEquip(from); - } - - public override void OnAdded(IEntity parent) - { - if (parent is Mobile from) - { - SkillBonuses.AddTo(from); - Attributes.AddStatBonuses(from); - - if (m_Blessed && BlessedFor == null) + private static readonly int[] m_ItemIDs = + { + 0x2F58, 0x2F59, 0x2F5A, 0x2F5B + }; + + private static readonly Type[] m_Summons = + { + typeof(SummonedAntLion), + typeof(SummonedCow), + typeof(SummonedLavaSerpent), + typeof(SummonedOrcBrute), + typeof(SummonedFrostSpider), + typeof(SummonedPanther), + typeof(SummonedDoppleganger), + typeof(SummonedGreatHart), + typeof(SummonedBullFrog), + typeof(SummonedArcticOgreLord), + typeof(SummonedBogling), + typeof(SummonedBakeKitsune), + typeof(SummonedSheep), + typeof(SummonedSkeletalKnight), + typeof(SummonedWailingBanshee), + typeof(SummonedChicken), + typeof(SummonedVorpalBunny), + + typeof(Board), + typeof(IronIngot), + typeof(Bandage) + }; + + private static readonly int[] m_SummonLabels = + { + 1075211, // Ant Lion + 1072494, // Cow + 1072434, // Lava Serpent + 1072414, // Orc Brute + 1072476, // Frost Spider + 1029653, // Panther + 1029741, // Doppleganger + 1018292, // great hart + 1028496, // bullfrog + 1018227, // arctic ogre lord + 1029735, // Bogling + 1030083, // bake-kitsune + 1018285, // sheep + 1018239, // skeletal knight + 1072399, // Wailing Banshee + 1072459, // Chicken + 1072401, // Vorpal Bunny + + 1015101, // Boards + 1044036, // Ingots + 1023817 // clean bandage + }; + + private static readonly Type[] m_Killers = + { + typeof(OrcBomber), typeof(OrcBrute), typeof(SewerRat), typeof(Rat), typeof(GiantRat), + typeof(Ratman), typeof(RatmanArcher), typeof(GiantSpider), typeof(FrostSpider), typeof(GiantBlackWidow), + typeof(DreadSpider), typeof(SilverSerpent), typeof(DeepSeaSerpent), typeof(GiantSerpent), typeof(Snake), + typeof(IceSnake), typeof(IceSerpent), typeof(LavaSerpent), typeof(LavaSnake), typeof(Yamandon), + typeof(StrongMongbat), typeof(Mongbat), typeof(VampireBat), typeof(Lich), typeof(EvilMage), + typeof(LichLord), typeof(EvilMageLord), typeof(SkeletalMage), typeof(KhaldunZealot), typeof(AncientLich), + typeof(JukaMage), typeof(MeerMage), typeof(Beetle), typeof(DeathwatchBeetle), typeof(RuneBeetle), + typeof(FireBeetle), typeof(DeathwatchBeetleHatchling), typeof(Bird), typeof(Chicken), typeof(Eagle), + typeof(TropicalBird), typeof(Phoenix), typeof(DesertOstard), typeof(FrenziedOstard), typeof(ForestOstard), + typeof(Crane), typeof(SnowLeopard), typeof(IceFiend), typeof(FrostOoze), typeof(FrostTroll), + typeof(IceElemental), typeof(SnowElemental), typeof(GiantIceWorm), typeof(LadyOfTheSnow), typeof(FireElemental), + typeof(FireSteed), typeof(HellHound), typeof(HellCat), typeof(PredatorHellCat), typeof(LavaLizard), + typeof(FireBeetle), typeof(Cow), typeof(Bull), typeof(Gaman) // , typeof( Minotaur) + // TODO Meraktus, Tormented Minotaur, Minotaur + }; + + private static readonly int[] m_KillerLabels = + { + 1072413, 1072414, 1072418, 1072419, 1072420, + 1072421, 1072423, 1072424, 1072425, 1072426, + 1072427, 1072428, 1072429, 1072430, 1072431, + 1072432, 1072433, 1072434, 1072435, 1072438, + 1072440, 1072441, 1072443, 1072444, 1072445, + 1072446, 1072447, 1072448, 1072449, 1072450, + 1072451, 1072452, 1072453, 1072454, 1072455, + 1072456, 1072457, 1072458, 1072459, 1072461, + 1072462, 1072465, 1072468, 1072469, 1072470, + 1072473, 1072474, 1072477, 1072478, 1072479, + 1072480, 1072481, 1072483, 1072485, 1072486, + 1072487, 1072489, 1072490, 1072491, 1072492, + 1072493, 1072494, 1072495, 1072498 + }; + + private static readonly SkillName[] m_Skills = + { + SkillName.Alchemy, + SkillName.Blacksmith, + SkillName.Carpentry, + SkillName.Cartography, + SkillName.Cooking, + SkillName.Fletching, + SkillName.Inscribe, + SkillName.Tailoring, + SkillName.Tinkering + }; + + private bool m_Blessed; + private int m_Charges; + private int m_ChargeTime; + private Mobile m_Creature; + private int m_ExceptionalBonus; + private TalismanAttribute m_Killer; + + private int m_MaxCharges; + private int m_MaxChargeTime; + + private TalismanAttribute m_Protection; + private TalismanRemoval m_Removal; + + private SkillName m_Skill; + + private TalismanSlayerName m_Slayer; + private int m_SuccessBonus; + + private TalismanAttribute m_Summoner; + + private Timer m_Timer; + + public BaseTalisman() + : this(GetRandomItemID()) { - BlessedFor = from; - LootType = LootType.Blessed; } - if (m_ChargeTime > 0) + public BaseTalisman(int itemID) + : base(itemID) { - m_ChargeTime = m_MaxChargeTime; - StartTimer(); - } - } + Layer = Layer.Talisman; + Weight = 1.0; - InvalidateProperties(); - } - - public override void OnRemoved(IEntity parent) - { - if (parent is Mobile from) - { - SkillBonuses.Remove(); - Attributes.RemoveStatBonuses(from); - - if (m_Creature?.Deleted == false) - { - Effects.SendLocationParticles( - EffectItem.Create(m_Creature.Location, m_Creature.Map, EffectItem.DefaultDuration), 0x3728, 8, 20, - 5042); - Effects.PlaySound(m_Creature, m_Creature.Map, 0x201); - - m_Creature.Delete(); + m_Protection = new TalismanAttribute(); + m_Killer = new TalismanAttribute(); + m_Summoner = new TalismanAttribute(); + Attributes = new AosAttributes(this); + SkillBonuses = new AosSkillBonuses(this); } - StopTimer(); - } - - InvalidateProperties(); - } - - public override void OnDoubleClick(Mobile from) - { - if (from.Talisman != this) - { - from.SendLocalizedMessage(502641); // You must equip this item to use it. - return; - } - - if (m_ChargeTime > 0) - { - from.SendLocalizedMessage(1074882, - m_ChargeTime.ToString()); // You must wait ~1_val~ seconds for this to recharge. - return; - } - - if (m_Charges == 0 && m_MaxCharges > 0) - { - from.SendLocalizedMessage(1042544); // This item is out of charges. - return; - } - - Type type = GetSummoner(); - - if (m_Summoner?.IsEmpty == false) - type = m_Summoner.Type; - - if (type != null) - { - object obj; - - try + public BaseTalisman(Serial serial) + : base(serial) { - obj = ActivatorUtil.CreateInstance(type); - } - catch - { - obj = null; } - if (obj is Item item) - { - int count = 1; + public override int LabelNumber => 1071023; // Talisman + public virtual bool ForceShowName => false; // used to override default summoner/removal name - if (m_Summoner?.Amount > 1) - { - if (item.Stackable) - item.Amount = m_Summoner.Amount; + [CommandProperty(AccessLevel.GameMaster)] + public int MaxCharges + { + get => m_MaxCharges; + set + { + m_MaxCharges = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Charges + { + get => m_Charges; + set + { + m_Charges = value; + + if (m_ChargeTime > 0) + StartTimer(); + + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxChargeTime + { + get => m_MaxChargeTime; + set + { + m_MaxChargeTime = value; + InvalidateProperties(); + } + } + + public int ChargeTime + { + get => m_ChargeTime; + set + { + m_ChargeTime = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Blessed + { + get => m_Blessed; + set + { + m_Blessed = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public TalismanSlayerName Slayer + { + get => m_Slayer; + set + { + m_Slayer = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public TalismanAttribute Summoner + { + get => m_Summoner; + set + { + m_Summoner = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public TalismanRemoval Removal + { + get => m_Removal; + set + { + m_Removal = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public TalismanAttribute Protection + { + get => m_Protection; + set + { + m_Protection = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public TalismanAttribute Killer + { + get => m_Killer; + set + { + m_Killer = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public SkillName Skill + { + get => m_Skill; + set + { + m_Skill = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int SuccessBonus + { + get => m_SuccessBonus; + set + { + m_SuccessBonus = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int ExceptionalBonus + { + get => m_ExceptionalBonus; + set + { + m_ExceptionalBonus = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public AosAttributes Attributes { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public AosSkillBonuses SkillBonuses { get; private set; } + + public static void Initialize() + { + CommandSystem.Register("RandomTalisman", AccessLevel.GameMaster, RandomTalisman_OnCommand); + } + + [Usage("RandomTalisman ")] + [Description("Generates random talismans in your backpack.")] + public static void RandomTalisman_OnCommand(CommandEventArgs e) + { + var m = e.Mobile; + var count = e.GetInt32(0); + + for (var i = 0; i < count; i++) + m.AddToBackpack(Loot.RandomTalisman()); + } + + public override void OnAfterDuped(Item newItem) + { + if (!(newItem is BaseTalisman talisman)) + return; + + talisman.m_Summoner = new TalismanAttribute(m_Summoner); + talisman.m_Protection = new TalismanAttribute(m_Protection); + talisman.m_Killer = new TalismanAttribute(m_Killer); + talisman.Attributes = new AosAttributes(newItem, Attributes); + talisman.SkillBonuses = new AosSkillBonuses(newItem, SkillBonuses); + } + + public override bool CanEquip(Mobile from) + { + if (BlessedFor != null && BlessedFor != from) + { + from.SendLocalizedMessage(1010437); // You are not the owner. + return false; + } + + return base.CanEquip(from); + } + + public override void OnAdded(IEntity parent) + { + if (parent is Mobile from) + { + SkillBonuses.AddTo(from); + Attributes.AddStatBonuses(from); + + if (m_Blessed && BlessedFor == null) + { + BlessedFor = from; + LootType = LootType.Blessed; + } + + if (m_ChargeTime > 0) + { + m_ChargeTime = m_MaxChargeTime; + StartTimer(); + } + } + + InvalidateProperties(); + } + + public override void OnRemoved(IEntity parent) + { + if (parent is Mobile from) + { + SkillBonuses.Remove(); + Attributes.RemoveStatBonuses(from); + + if (m_Creature?.Deleted == false) + { + Effects.SendLocationParticles( + EffectItem.Create(m_Creature.Location, m_Creature.Map, EffectItem.DefaultDuration), + 0x3728, + 8, + 20, + 5042 + ); + Effects.PlaySound(m_Creature, m_Creature.Map, 0x201); + + m_Creature.Delete(); + } + + StopTimer(); + } + + InvalidateProperties(); + } + + public override void OnDoubleClick(Mobile from) + { + if (from.Talisman != this) + { + from.SendLocalizedMessage(502641); // You must equip this item to use it. + return; + } + + if (m_ChargeTime > 0) + { + from.SendLocalizedMessage( + 1074882, + m_ChargeTime.ToString() + ); // You must wait ~1_val~ seconds for this to recharge. + return; + } + + if (m_Charges == 0 && m_MaxCharges > 0) + { + from.SendLocalizedMessage(1042544); // This item is out of charges. + return; + } + + var type = GetSummoner(); + + if (m_Summoner?.IsEmpty == false) + type = m_Summoner.Type; + + if (type != null) + { + object obj; + + try + { + obj = ActivatorUtil.CreateInstance(type); + } + catch + { + obj = null; + } + + if (obj is Item item) + { + var count = 1; + + if (m_Summoner?.Amount > 1) + { + if (item.Stackable) + item.Amount = m_Summoner.Amount; + else + count = m_Summoner.Amount; + } + + if (from.Backpack == null || count * item.Weight > from.Backpack.MaxWeight || + from.Backpack.Items.Count + count > from.Backpack.MaxItems) + { + from.SendLocalizedMessage(500720); // You don't have enough room in your backpack! + item.Delete(); + return; + } + + for (var i = 0; i < count; i++) + { + from.PlaceInBackpack(item); + + if (i + 1 < count) + item = ActivatorUtil.CreateInstance(type) as Item; + } + + if (item is Board) + from.SendLocalizedMessage(1075000); // You have been given some wooden boards. + else if (item is IronIngot) + from.SendLocalizedMessage(1075001); // You have been given some ingots. + else if (item is Bandage) + from.SendLocalizedMessage(1075002); // You have been given some clean bandages. + else if (m_Summoner?.Name != null) + from.SendLocalizedMessage(1074853, m_Summoner.Name.ToString()); // You have been given ~1_name~ + } + else if (obj is BaseCreature mob) + { + if (m_Creature?.Deleted == false || from.Followers + mob.ControlSlots > from.FollowersMax) + { + from.SendLocalizedMessage(1074270); // You have too many followers to summon another one. + mob.Delete(); + return; + } + + BaseCreature.Summon(mob, from, from.Location, mob.BaseSoundID, TimeSpan.FromMinutes(10)); + Effects.SendLocationParticles( + EffectItem.Create(mob.Location, mob.Map, EffectItem.DefaultDuration), + 0x3728, + 1, + 10, + 0x26B6 + ); + + mob.Summoned = false; + mob.ControlOrder = OrderType.Friend; + + m_Creature = mob; + } + + OnAfterUse(from); + } + + if (m_Removal != TalismanRemoval.None) + from.Target = new TalismanTarget(this); + } + + public override void AddNameProperty(ObjectPropertyList list) + { + if (ForceShowName) + base.AddNameProperty(list); + else if (m_Summoner?.IsEmpty == false) + list.Add( + 1072400, + m_Summoner?.Name ?? "Unknown" + ); // Talisman of ~1_name~ Summoning + else if (m_Removal != TalismanRemoval.None) + list.Add(1072389, $"#{1072000 + (int)m_Removal}"); // Talisman of ~1_name~ else - count = m_Summoner.Amount; - } - - if (from.Backpack == null || count * item.Weight > from.Backpack.MaxWeight || - from.Backpack.Items.Count + count > from.Backpack.MaxItems) - { - from.SendLocalizedMessage(500720); // You don't have enough room in your backpack! - item.Delete(); - return; - } - - for (int i = 0; i < count; i++) - { - from.PlaceInBackpack(item); - - if (i + 1 < count) - item = ActivatorUtil.CreateInstance(type) as Item; - } - - if (item is Board) - from.SendLocalizedMessage(1075000); // You have been given some wooden boards. - else if (item is IronIngot) - from.SendLocalizedMessage(1075001); // You have been given some ingots. - else if (item is Bandage) - from.SendLocalizedMessage(1075002); // You have been given some clean bandages. - else if (m_Summoner?.Name != null) - from.SendLocalizedMessage(1074853, m_Summoner.Name.ToString()); // You have been given ~1_name~ + base.AddNameProperty(list); } - else if (obj is BaseCreature mob) + + public override void GetProperties(ObjectPropertyList list) { - if (m_Creature?.Deleted == false || from.Followers + mob.ControlSlots > from.FollowersMax) - { - from.SendLocalizedMessage(1074270); // You have too many followers to summon another one. - mob.Delete(); - return; - } + base.GetProperties(list); - BaseCreature.Summon(mob, from, from.Location, mob.BaseSoundID, TimeSpan.FromMinutes(10)); - Effects.SendLocationParticles(EffectItem.Create(mob.Location, mob.Map, EffectItem.DefaultDuration), - 0x3728, 1, 10, 0x26B6); + if (Blessed) + { + if (BlessedFor != null) + list.Add( + 1072304, + !string.IsNullOrEmpty(BlessedFor.Name) ? BlessedFor.Name : "Unnamed Warrior" + ); // Owned by ~1_name~ + else + list.Add(1072304, "Nobody"); // Owned by ~1_name~ + } - mob.Summoned = false; - mob.ControlOrder = OrderType.Friend; + if (Parent is Mobile && m_MaxChargeTime > 0) + { + if (m_ChargeTime > 0) + list.Add(1074884, m_ChargeTime.ToString()); // Charge time left: ~1_val~ + else + list.Add(1074883); // Fully Charged + } - m_Creature = mob; + list.Add(1075085); // Requirement: Mondain's Legacy + + if (m_Killer?.IsEmpty == false && m_Killer.Amount > 0) + list.Add( + 1072388, + "{0}\t{1}", + m_Killer.Name?.ToString() ?? "Unknown", + m_Killer.Amount + ); // ~1_NAME~ Killer: +~2_val~% + + if (m_Protection?.IsEmpty == false && m_Protection.Amount > 0) + list.Add( + 1072387, + "{0}\t{1}", + m_Protection.Name?.ToString() ?? "Unknown", + m_Protection.Amount + ); // ~1_NAME~ Protection: +~2_val~% + + if (m_ExceptionalBonus != 0) + list.Add( + 1072395, + "#{0}\t{1}", + AosSkillBonuses.GetLabel(m_Skill), + m_ExceptionalBonus + ); // ~1_NAME~ Exceptional Bonus: ~2_val~% + + if (m_SuccessBonus != 0) + list.Add( + 1072394, + "#{0}\t{1}", + AosSkillBonuses.GetLabel(m_Skill), + m_SuccessBonus + ); // ~1_NAME~ Bonus: ~2_val~% + + SkillBonuses.GetProperties(list); + + int prop; + + if ((prop = Attributes.WeaponDamage) != 0) + list.Add(1060401, prop.ToString()); // damage increase ~1_val~% + + if ((prop = Attributes.DefendChance) != 0) + list.Add(1060408, prop.ToString()); // defense chance increase ~1_val~% + + if ((prop = Attributes.BonusDex) != 0) + list.Add(1060409, prop.ToString()); // dexterity bonus ~1_val~ + + if ((prop = Attributes.EnhancePotions) != 0) + list.Add(1060411, prop.ToString()); // enhance potions ~1_val~% + + if ((prop = Attributes.CastRecovery) != 0) + list.Add(1060412, prop.ToString()); // faster cast recovery ~1_val~ + + if ((prop = Attributes.CastSpeed) != 0) + list.Add(1060413, prop.ToString()); // faster casting ~1_val~ + + if ((prop = Attributes.AttackChance) != 0) + list.Add(1060415, prop.ToString()); // hit chance increase ~1_val~% + + if ((prop = Attributes.BonusHits) != 0) + list.Add(1060431, prop.ToString()); // hit point increase ~1_val~ + + if ((prop = Attributes.BonusInt) != 0) + list.Add(1060432, prop.ToString()); // intelligence bonus ~1_val~ + + if ((prop = Attributes.LowerManaCost) != 0) + list.Add(1060433, prop.ToString()); // lower mana cost ~1_val~% + + if ((prop = Attributes.LowerRegCost) != 0) + list.Add(1060434, prop.ToString()); // lower reagent cost ~1_val~% + + if ((prop = Attributes.Luck) != 0) + list.Add(1060436, prop.ToString()); // luck ~1_val~ + + if ((prop = Attributes.BonusMana) != 0) + list.Add(1060439, prop.ToString()); // mana increase ~1_val~ + + if ((prop = Attributes.RegenMana) != 0) + list.Add(1060440, prop.ToString()); // mana regeneration ~1_val~ + + if (Attributes.NightSight != 0) + list.Add(1060441); // night sight + + if ((prop = Attributes.ReflectPhysical) != 0) + list.Add(1060442, prop.ToString()); // reflect physical damage ~1_val~% + + if ((prop = Attributes.RegenStam) != 0) + list.Add(1060443, prop.ToString()); // stamina regeneration ~1_val~ + + if ((prop = Attributes.RegenHits) != 0) + list.Add(1060444, prop.ToString()); // hit point regeneration ~1_val~ + + if (Attributes.SpellChanneling != 0) + list.Add(1060482); // spell channeling + + if ((prop = Attributes.SpellDamage) != 0) + list.Add(1060483, prop.ToString()); // spell damage increase ~1_val~% + + if ((prop = Attributes.BonusStam) != 0) + list.Add(1060484, prop.ToString()); // stamina increase ~1_val~ + + if ((prop = Attributes.BonusStr) != 0) + list.Add(1060485, prop.ToString()); // strength bonus ~1_val~ + + if ((prop = Attributes.WeaponSpeed) != 0) + list.Add(1060486, prop.ToString()); // swing speed increase ~1_val~% + + if (Core.ML && (prop = Attributes.IncreasedKarmaLoss) != 0) + list.Add(1075210, prop.ToString()); // Increased Karma Loss ~1val~% + + if (m_MaxCharges > 0) + list.Add(1060741, m_Charges.ToString()); // charges: ~1_val~ + + if (m_Slayer != TalismanSlayerName.None) + list.Add(1072503 + (int)m_Slayer); } - OnAfterUse(from); - } - - if (m_Removal != TalismanRemoval.None) - from.Target = new TalismanTarget(this); - } - - public override void AddNameProperty(ObjectPropertyList list) - { - if (ForceShowName) - base.AddNameProperty(list); - else if (m_Summoner?.IsEmpty == false) - list.Add(1072400, - m_Summoner?.Name ?? "Unknown"); // Talisman of ~1_name~ Summoning - else if (m_Removal != TalismanRemoval.None) - list.Add(1072389, $"#{1072000 + (int)m_Removal}"); // Talisman of ~1_name~ - else - base.AddNameProperty(list); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Blessed) - { - if (BlessedFor != null) - list.Add(1072304, - !string.IsNullOrEmpty(BlessedFor.Name) ? BlessedFor.Name : "Unnamed Warrior"); // Owned by ~1_name~ - else - list.Add(1072304, "Nobody"); // Owned by ~1_name~ - } - - if (Parent is Mobile && m_MaxChargeTime > 0) - { - if (m_ChargeTime > 0) - list.Add(1074884, m_ChargeTime.ToString()); // Charge time left: ~1_val~ - else - list.Add(1074883); // Fully Charged - } - - list.Add(1075085); // Requirement: Mondain's Legacy - - if (m_Killer?.IsEmpty == false && m_Killer.Amount > 0) - list.Add(1072388, "{0}\t{1}", m_Killer.Name?.ToString() ?? "Unknown", - m_Killer.Amount); // ~1_NAME~ Killer: +~2_val~% - - if (m_Protection?.IsEmpty == false && m_Protection.Amount > 0) - list.Add(1072387, "{0}\t{1}", m_Protection.Name?.ToString() ?? "Unknown", - m_Protection.Amount); // ~1_NAME~ Protection: +~2_val~% - - if (m_ExceptionalBonus != 0) - list.Add(1072395, "#{0}\t{1}", AosSkillBonuses.GetLabel(m_Skill), - m_ExceptionalBonus); // ~1_NAME~ Exceptional Bonus: ~2_val~% - - if (m_SuccessBonus != 0) - list.Add(1072394, "#{0}\t{1}", AosSkillBonuses.GetLabel(m_Skill), - m_SuccessBonus); // ~1_NAME~ Bonus: ~2_val~% - - SkillBonuses.GetProperties(list); - - int prop; - - if ((prop = Attributes.WeaponDamage) != 0) - list.Add(1060401, prop.ToString()); // damage increase ~1_val~% - - if ((prop = Attributes.DefendChance) != 0) - list.Add(1060408, prop.ToString()); // defense chance increase ~1_val~% - - if ((prop = Attributes.BonusDex) != 0) - list.Add(1060409, prop.ToString()); // dexterity bonus ~1_val~ - - if ((prop = Attributes.EnhancePotions) != 0) - list.Add(1060411, prop.ToString()); // enhance potions ~1_val~% - - if ((prop = Attributes.CastRecovery) != 0) - list.Add(1060412, prop.ToString()); // faster cast recovery ~1_val~ - - if ((prop = Attributes.CastSpeed) != 0) - list.Add(1060413, prop.ToString()); // faster casting ~1_val~ - - if ((prop = Attributes.AttackChance) != 0) - list.Add(1060415, prop.ToString()); // hit chance increase ~1_val~% - - if ((prop = Attributes.BonusHits) != 0) - list.Add(1060431, prop.ToString()); // hit point increase ~1_val~ - - if ((prop = Attributes.BonusInt) != 0) - list.Add(1060432, prop.ToString()); // intelligence bonus ~1_val~ - - if ((prop = Attributes.LowerManaCost) != 0) - list.Add(1060433, prop.ToString()); // lower mana cost ~1_val~% - - if ((prop = Attributes.LowerRegCost) != 0) - list.Add(1060434, prop.ToString()); // lower reagent cost ~1_val~% - - if ((prop = Attributes.Luck) != 0) - list.Add(1060436, prop.ToString()); // luck ~1_val~ - - if ((prop = Attributes.BonusMana) != 0) - list.Add(1060439, prop.ToString()); // mana increase ~1_val~ - - if ((prop = Attributes.RegenMana) != 0) - list.Add(1060440, prop.ToString()); // mana regeneration ~1_val~ - - if (Attributes.NightSight != 0) - list.Add(1060441); // night sight - - if ((prop = Attributes.ReflectPhysical) != 0) - list.Add(1060442, prop.ToString()); // reflect physical damage ~1_val~% - - if ((prop = Attributes.RegenStam) != 0) - list.Add(1060443, prop.ToString()); // stamina regeneration ~1_val~ - - if ((prop = Attributes.RegenHits) != 0) - list.Add(1060444, prop.ToString()); // hit point regeneration ~1_val~ - - if (Attributes.SpellChanneling != 0) - list.Add(1060482); // spell channeling - - if ((prop = Attributes.SpellDamage) != 0) - list.Add(1060483, prop.ToString()); // spell damage increase ~1_val~% - - if ((prop = Attributes.BonusStam) != 0) - list.Add(1060484, prop.ToString()); // stamina increase ~1_val~ - - if ((prop = Attributes.BonusStr) != 0) - list.Add(1060485, prop.ToString()); // strength bonus ~1_val~ - - if ((prop = Attributes.WeaponSpeed) != 0) - list.Add(1060486, prop.ToString()); // swing speed increase ~1_val~% - - if (Core.ML && (prop = Attributes.IncreasedKarmaLoss) != 0) - list.Add(1075210, prop.ToString()); // Increased Karma Loss ~1val~% - - if (m_MaxCharges > 0) - list.Add(1060741, m_Charges.ToString()); // charges: ~1_val~ - - if (m_Slayer != TalismanSlayerName.None) - list.Add(1072503 + (int)m_Slayer); - } - - private static void SetSaveFlag(ref SaveFlag flags, SaveFlag toSet, bool setIf) - { - if (setIf) - flags |= toSet; - } - - private static bool GetSaveFlag(SaveFlag flags, SaveFlag toGet) => (flags & toGet) != 0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - SaveFlag flags = SaveFlag.None; - - SetSaveFlag(ref flags, SaveFlag.Attributes, !Attributes.IsEmpty); - SetSaveFlag(ref flags, SaveFlag.SkillBonuses, !SkillBonuses.IsEmpty); - SetSaveFlag(ref flags, SaveFlag.Protection, m_Protection?.IsEmpty == false); - SetSaveFlag(ref flags, SaveFlag.Killer, m_Killer?.IsEmpty == false); - SetSaveFlag(ref flags, SaveFlag.Summoner, m_Summoner?.IsEmpty == false); - SetSaveFlag(ref flags, SaveFlag.Removal, m_Removal != TalismanRemoval.None); - SetSaveFlag(ref flags, SaveFlag.Skill, (int)m_Skill != 0); - SetSaveFlag(ref flags, SaveFlag.SuccessBonus, m_SuccessBonus != 0); - SetSaveFlag(ref flags, SaveFlag.ExceptionalBonus, m_ExceptionalBonus != 0); - SetSaveFlag(ref flags, SaveFlag.MaxCharges, m_MaxCharges != 0); - SetSaveFlag(ref flags, SaveFlag.Charges, m_Charges != 0); - SetSaveFlag(ref flags, SaveFlag.MaxChargeTime, m_MaxChargeTime != 0); - SetSaveFlag(ref flags, SaveFlag.ChargeTime, m_ChargeTime != 0); - SetSaveFlag(ref flags, SaveFlag.Blessed, m_Blessed); - SetSaveFlag(ref flags, SaveFlag.Slayer, m_Slayer != TalismanSlayerName.None); - - writer.WriteEncodedInt((int)flags); - - if (GetSaveFlag(flags, SaveFlag.Attributes)) - Attributes.Serialize(writer); - - if (GetSaveFlag(flags, SaveFlag.SkillBonuses)) - SkillBonuses.Serialize(writer); - - if (GetSaveFlag(flags, SaveFlag.Protection)) - Protection.Serialize(writer); - - if (GetSaveFlag(flags, SaveFlag.Killer)) - Killer.Serialize(writer); - - if (GetSaveFlag(flags, SaveFlag.Summoner)) - Summoner.Serialize(writer); - - if (GetSaveFlag(flags, SaveFlag.Removal)) - writer.WriteEncodedInt((int)m_Removal); - - if (GetSaveFlag(flags, SaveFlag.Skill)) - writer.WriteEncodedInt((int)m_Skill); - - if (GetSaveFlag(flags, SaveFlag.SuccessBonus)) - writer.WriteEncodedInt(m_SuccessBonus); - - if (GetSaveFlag(flags, SaveFlag.ExceptionalBonus)) - writer.WriteEncodedInt(m_ExceptionalBonus); - - if (GetSaveFlag(flags, SaveFlag.MaxCharges)) - writer.WriteEncodedInt(m_MaxCharges); - - if (GetSaveFlag(flags, SaveFlag.Charges)) - writer.WriteEncodedInt(m_Charges); - - if (GetSaveFlag(flags, SaveFlag.MaxChargeTime)) - writer.WriteEncodedInt(m_MaxChargeTime); - - if (GetSaveFlag(flags, SaveFlag.ChargeTime)) - writer.WriteEncodedInt(m_ChargeTime); - - if (GetSaveFlag(flags, SaveFlag.Slayer)) - writer.WriteEncodedInt((int)m_Slayer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - SaveFlag flags = (SaveFlag)reader.ReadEncodedInt(); - - Attributes = GetSaveFlag(flags, SaveFlag.Attributes) ? new AosAttributes(this, reader) : new AosAttributes(this); - SkillBonuses = GetSaveFlag(flags, SaveFlag.SkillBonuses) - ? new AosSkillBonuses(this, reader) - : new AosSkillBonuses(this); - - // Backward compatibility - if (GetSaveFlag(flags, SaveFlag.Owner)) - BlessedFor = reader.ReadMobile(); - - m_Protection = GetSaveFlag(flags, SaveFlag.Protection) ? new TalismanAttribute(reader) : new TalismanAttribute(); - m_Killer = GetSaveFlag(flags, SaveFlag.Killer) ? new TalismanAttribute(reader) : new TalismanAttribute(); - m_Summoner = GetSaveFlag(flags, SaveFlag.Summoner) ? new TalismanAttribute(reader) : new TalismanAttribute(); + private static void SetSaveFlag(ref SaveFlag flags, SaveFlag toSet, bool setIf) + { + if (setIf) + flags |= toSet; + } + + private static bool GetSaveFlag(SaveFlag flags, SaveFlag toGet) => (flags & toGet) != 0; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + var flags = SaveFlag.None; + + SetSaveFlag(ref flags, SaveFlag.Attributes, !Attributes.IsEmpty); + SetSaveFlag(ref flags, SaveFlag.SkillBonuses, !SkillBonuses.IsEmpty); + SetSaveFlag(ref flags, SaveFlag.Protection, m_Protection?.IsEmpty == false); + SetSaveFlag(ref flags, SaveFlag.Killer, m_Killer?.IsEmpty == false); + SetSaveFlag(ref flags, SaveFlag.Summoner, m_Summoner?.IsEmpty == false); + SetSaveFlag(ref flags, SaveFlag.Removal, m_Removal != TalismanRemoval.None); + SetSaveFlag(ref flags, SaveFlag.Skill, (int)m_Skill != 0); + SetSaveFlag(ref flags, SaveFlag.SuccessBonus, m_SuccessBonus != 0); + SetSaveFlag(ref flags, SaveFlag.ExceptionalBonus, m_ExceptionalBonus != 0); + SetSaveFlag(ref flags, SaveFlag.MaxCharges, m_MaxCharges != 0); + SetSaveFlag(ref flags, SaveFlag.Charges, m_Charges != 0); + SetSaveFlag(ref flags, SaveFlag.MaxChargeTime, m_MaxChargeTime != 0); + SetSaveFlag(ref flags, SaveFlag.ChargeTime, m_ChargeTime != 0); + SetSaveFlag(ref flags, SaveFlag.Blessed, m_Blessed); + SetSaveFlag(ref flags, SaveFlag.Slayer, m_Slayer != TalismanSlayerName.None); + + writer.WriteEncodedInt((int)flags); + + if (GetSaveFlag(flags, SaveFlag.Attributes)) + Attributes.Serialize(writer); + + if (GetSaveFlag(flags, SaveFlag.SkillBonuses)) + SkillBonuses.Serialize(writer); + + if (GetSaveFlag(flags, SaveFlag.Protection)) + Protection.Serialize(writer); + + if (GetSaveFlag(flags, SaveFlag.Killer)) + Killer.Serialize(writer); + + if (GetSaveFlag(flags, SaveFlag.Summoner)) + Summoner.Serialize(writer); if (GetSaveFlag(flags, SaveFlag.Removal)) - m_Removal = (TalismanRemoval)reader.ReadEncodedInt(); - - if (GetSaveFlag(flags, SaveFlag.OldKarmaLoss)) - Attributes.IncreasedKarmaLoss = reader.ReadEncodedInt(); + writer.WriteEncodedInt((int)m_Removal); if (GetSaveFlag(flags, SaveFlag.Skill)) - m_Skill = (SkillName)reader.ReadEncodedInt(); + writer.WriteEncodedInt((int)m_Skill); if (GetSaveFlag(flags, SaveFlag.SuccessBonus)) - m_SuccessBonus = reader.ReadEncodedInt(); + writer.WriteEncodedInt(m_SuccessBonus); if (GetSaveFlag(flags, SaveFlag.ExceptionalBonus)) - m_ExceptionalBonus = reader.ReadEncodedInt(); + writer.WriteEncodedInt(m_ExceptionalBonus); if (GetSaveFlag(flags, SaveFlag.MaxCharges)) - m_MaxCharges = reader.ReadEncodedInt(); + writer.WriteEncodedInt(m_MaxCharges); if (GetSaveFlag(flags, SaveFlag.Charges)) - m_Charges = reader.ReadEncodedInt(); + writer.WriteEncodedInt(m_Charges); if (GetSaveFlag(flags, SaveFlag.MaxChargeTime)) - m_MaxChargeTime = reader.ReadEncodedInt(); + writer.WriteEncodedInt(m_MaxChargeTime); if (GetSaveFlag(flags, SaveFlag.ChargeTime)) - m_ChargeTime = reader.ReadEncodedInt(); + writer.WriteEncodedInt(m_ChargeTime); if (GetSaveFlag(flags, SaveFlag.Slayer)) - m_Slayer = (TalismanSlayerName)reader.ReadEncodedInt(); - - m_Blessed = GetSaveFlag(flags, SaveFlag.Blessed); - - break; - } - } - - if (Parent is Mobile m) - { - Attributes.AddStatBonuses(m); - SkillBonuses.AddTo(m); - - if (m_ChargeTime > 0) - StartTimer(); - } - } - - public virtual void OnAfterUse(Mobile m) - { - m_ChargeTime = m_MaxChargeTime; - - if (m_Charges > 0 && m_MaxCharges > 0) - m_Charges -= 1; - - if (m_ChargeTime > 0) - StartTimer(); - - InvalidateProperties(); - } - - public virtual Type GetSummoner() => null; - - public virtual void SetSummoner(Type type, TextDefinition name) - { - m_Summoner = new TalismanAttribute(type, name); - } - - public virtual void SetProtection(Type type, TextDefinition name, int amount) - { - m_Protection = new TalismanAttribute(type, name, amount); - } - - public virtual void SetKiller(Type type, TextDefinition name, int amount) - { - m_Killer = new TalismanAttribute(type, name, amount); - } - - [Flags] - private enum SaveFlag - { - None = 0x00000000, - Attributes = 0x00000001, - SkillBonuses = 0x00000002, - Owner = 0x00000004, - Protection = 0x00000008, - Killer = 0x00000010, - Summoner = 0x00000020, - Removal = 0x00000040, - OldKarmaLoss = 0x00000080, - Skill = 0x00000100, - SuccessBonus = 0x00000200, - ExceptionalBonus = 0x00000400, - MaxCharges = 0x00000800, - Charges = 0x00001000, - MaxChargeTime = 0x00002000, - ChargeTime = 0x00004000, - Blessed = 0x00008000, - Slayer = 0x00010000 - } - - private class TalismanTarget : Target - { - private readonly BaseTalisman m_Talisman; - - public TalismanTarget(BaseTalisman talisman) - : base(12, false, TargetFlags.Beneficial) => - m_Talisman = talisman; - - protected override void OnTarget(Mobile from, object o) - { - if (m_Talisman?.Deleted != false) - return; - - if (from.Talisman != m_Talisman) - { - from.SendLocalizedMessage(502641); // You must equip this item to use it. - return; + writer.WriteEncodedInt((int)m_Slayer); } - if (!(o is Mobile target)) + public override void Deserialize(IGenericReader reader) { - from.SendLocalizedMessage(1046439); // That is not a valid target. - return; + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + var flags = (SaveFlag)reader.ReadEncodedInt(); + + Attributes = GetSaveFlag(flags, SaveFlag.Attributes) + ? new AosAttributes(this, reader) + : new AosAttributes(this); + SkillBonuses = GetSaveFlag(flags, SaveFlag.SkillBonuses) + ? new AosSkillBonuses(this, reader) + : new AosSkillBonuses(this); + + // Backward compatibility + if (GetSaveFlag(flags, SaveFlag.Owner)) + BlessedFor = reader.ReadMobile(); + + m_Protection = GetSaveFlag(flags, SaveFlag.Protection) + ? new TalismanAttribute(reader) + : new TalismanAttribute(); + m_Killer = GetSaveFlag(flags, SaveFlag.Killer) + ? new TalismanAttribute(reader) + : new TalismanAttribute(); + m_Summoner = GetSaveFlag(flags, SaveFlag.Summoner) + ? new TalismanAttribute(reader) + : new TalismanAttribute(); + + if (GetSaveFlag(flags, SaveFlag.Removal)) + m_Removal = (TalismanRemoval)reader.ReadEncodedInt(); + + if (GetSaveFlag(flags, SaveFlag.OldKarmaLoss)) + Attributes.IncreasedKarmaLoss = reader.ReadEncodedInt(); + + if (GetSaveFlag(flags, SaveFlag.Skill)) + m_Skill = (SkillName)reader.ReadEncodedInt(); + + if (GetSaveFlag(flags, SaveFlag.SuccessBonus)) + m_SuccessBonus = reader.ReadEncodedInt(); + + if (GetSaveFlag(flags, SaveFlag.ExceptionalBonus)) + m_ExceptionalBonus = reader.ReadEncodedInt(); + + if (GetSaveFlag(flags, SaveFlag.MaxCharges)) + m_MaxCharges = reader.ReadEncodedInt(); + + if (GetSaveFlag(flags, SaveFlag.Charges)) + m_Charges = reader.ReadEncodedInt(); + + if (GetSaveFlag(flags, SaveFlag.MaxChargeTime)) + m_MaxChargeTime = reader.ReadEncodedInt(); + + if (GetSaveFlag(flags, SaveFlag.ChargeTime)) + m_ChargeTime = reader.ReadEncodedInt(); + + if (GetSaveFlag(flags, SaveFlag.Slayer)) + m_Slayer = (TalismanSlayerName)reader.ReadEncodedInt(); + + m_Blessed = GetSaveFlag(flags, SaveFlag.Blessed); + + break; + } + } + + if (Parent is Mobile m) + { + Attributes.AddStatBonuses(m); + SkillBonuses.AddTo(m); + + if (m_ChargeTime > 0) + StartTimer(); + } } - if (m_Talisman.ChargeTime > 0) + public virtual void OnAfterUse(Mobile m) { - from.SendLocalizedMessage(1074882, - m_Talisman.ChargeTime.ToString()); // You must wait ~1_val~ seconds for this to recharge. - return; + m_ChargeTime = m_MaxChargeTime; + + if (m_Charges > 0 && m_MaxCharges > 0) + m_Charges -= 1; + + if (m_ChargeTime > 0) + StartTimer(); + + InvalidateProperties(); } - if (m_Talisman.Charges == 0 && m_Talisman.MaxCharges > 0) + public virtual Type GetSummoner() => null; + + public virtual void SetSummoner(Type type, TextDefinition name) { - from.SendLocalizedMessage(1042544); // This item is out of charges. - return; + m_Summoner = new TalismanAttribute(type, name); } - switch (m_Talisman.Removal) + public virtual void SetProtection(Type type, TextDefinition name, int amount) { - case TalismanRemoval.Curse: - target.PlaySound(0xF6); - target.PlaySound(0x1F7); - target.FixedParticles(0x3709, 1, 30, 9963, 13, 3, EffectLayer.Head); - - IEntity mfrom = new Entity(Serial.Zero, new Point3D(target.X, target.Y, target.Z - 10), - from.Map); - IEntity mto = new Entity(Serial.Zero, new Point3D(target.X, target.Y, target.Z + 50), from.Map); - Effects.SendMovingParticles(mfrom, mto, 0x2255, 1, 0, false, false, 13, 3, 9501, 1, 0, - EffectLayer.Head, 0x100); - - StatMod mod; - - mod = target.GetStatMod("[Magic] Str Offset"); - if (mod?.Offset < 0) - target.RemoveStatMod("[Magic] Str Offset"); - - mod = target.GetStatMod("[Magic] Dex Offset"); - if (mod?.Offset < 0) - target.RemoveStatMod("[Magic] Dex Offset"); - - mod = target.GetStatMod("[Magic] Int Offset"); - if (mod?.Offset < 0) - target.RemoveStatMod("[Magic] Int Offset"); - - target.Paralyzed = false; - - EvilOmenSpell.TryEndEffect(target); - StrangleSpell.RemoveCurse(target); - CorpseSkinSpell.RemoveCurse(target); - CurseSpell.RemoveEffect(target); - - BuffInfo.RemoveBuff(target, BuffIcon.Clumsy); - BuffInfo.RemoveBuff(target, BuffIcon.FeebleMind); - BuffInfo.RemoveBuff(target, BuffIcon.Weaken); - BuffInfo.RemoveBuff(target, BuffIcon.MassCurse); - - target.SendLocalizedMessage(1072408); // Any curses on you have been lifted - - if (target != from) - from.SendLocalizedMessage(1072409); // Your targets curses have been lifted - - break; - case TalismanRemoval.Damage: - target.PlaySound(0x201); - Effects.SendLocationParticles( - EffectItem.Create(target.Location, target.Map, EffectItem.DefaultDuration), 0x3728, 1, 13, - 0x834, 0, 0x13B2, 0); - - BleedAttack.EndBleed(target, true); - MortalStrike.EndWound(target); - - BuffInfo.RemoveBuff(target, BuffIcon.Bleed); - BuffInfo.RemoveBuff(target, BuffIcon.MortalStrike); - - target.SendLocalizedMessage(1072405); // Your lasting damage effects have been removed! - - if (target != from) - from.SendLocalizedMessage(1072406); // Your Targets lasting damage effects have been removed! - - break; - case TalismanRemoval.Ward: - target.PlaySound(0x201); - Effects.SendLocationParticles( - EffectItem.Create(target.Location, target.Map, EffectItem.DefaultDuration), 0x3728, 1, 13, - 0x834, 0, 0x13B2, 0); - - MagicReflectSpell.EndReflect(target); - ReactiveArmorSpell.EndArmor(target); - ProtectionSpell.EndProtection(target); - - target.SendLocalizedMessage(1072402); // Your wards have been removed! - - if (target != from) - from.SendLocalizedMessage(1072403); // Your target's wards have been removed! - - break; - case TalismanRemoval.Wildfire: - // TODO - break; + m_Protection = new TalismanAttribute(type, name, amount); } - m_Talisman.OnAfterUse(from); - } + public virtual void SetKiller(Type type, TextDefinition name, int amount) + { + m_Killer = new TalismanAttribute(type, name, amount); + } + + public virtual void StartTimer() + { + if (m_Timer?.Running != true) + m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10), Slice); + } + + public virtual void StopTimer() + { + m_Timer?.Stop(); + m_Timer = null; + } + + public virtual void Slice() + { + if (m_ChargeTime - 10 > 0) + { + m_ChargeTime -= 10; + } + else + { + m_ChargeTime = 0; + + StopTimer(); + } + + InvalidateProperties(); + } + + public static int GetRandomItemID() => m_ItemIDs.RandomElement(); + + public static Type GetRandomSummonType() => m_Summons.RandomElement(); + + public static TalismanAttribute GetRandomSummoner() + { + if (Utility.RandomDouble() >= 0.025) + return new TalismanAttribute(); + + var num = Utility.Random(m_Summons.Length); + + return num > 14 + ? new TalismanAttribute(m_Summons[num], m_SummonLabels[num], 10) + : new TalismanAttribute(m_Summons[num], m_SummonLabels[num]); + } + + public static TalismanRemoval GetRandomRemoval() + { + if (Utility.RandomDouble() < 0.65) + return (TalismanRemoval)Utility.RandomList(390, 404, 407); + + return TalismanRemoval.None; + } + + public static TalismanAttribute GetRandomKiller() => GetRandomKiller(true); + + public static TalismanAttribute GetRandomKiller(bool includingNone) + { + if (includingNone && Utility.RandomBool()) + return new TalismanAttribute(); + + var num = Utility.Random(m_Killers.Length); + + return new TalismanAttribute(m_Killers[num], m_KillerLabels[num], Utility.RandomMinMax(10, 100)); + } + + public static TalismanAttribute GetRandomProtection() => GetRandomProtection(true); + + public static TalismanAttribute GetRandomProtection(bool includingNone) + { + if (includingNone && Utility.RandomBool()) + return new TalismanAttribute(); + + var num = Utility.Random(m_Killers.Length); + + return new TalismanAttribute(m_Killers[num], m_KillerLabels[num], Utility.RandomMinMax(5, 60)); + } + + public static SkillName GetRandomSkill() => m_Skills.RandomElement(); + + public static int GetRandomExceptional() + { + if (Utility.RandomDouble() < 0.3) + { + var num = 40 - Math.Log(Utility.RandomMinMax(7, 403)) * 5; + + return (int)Math.Round(num); + } + + return 0; + } + + public static int GetRandomSuccessful() + { + if (Utility.RandomDouble() < 0.75) + { + var num = 40 - Math.Log(Utility.RandomMinMax(7, 403)) * 5; + + return (int)Math.Round(num); + } + + return 0; + } + + public static bool GetRandomBlessed() => Utility.RandomDouble() < 0.02; + + public static TalismanSlayerName GetRandomSlayer() => Utility.RandomDouble() < 0.01 + ? (TalismanSlayerName)Utility.RandomMinMax(1, 9) + : TalismanSlayerName.None; + + public static int GetRandomCharges() => Utility.RandomDouble() < 0.5 ? Utility.RandomMinMax(10, 50) : 0; + + [Flags] + private enum SaveFlag + { + None = 0x00000000, + Attributes = 0x00000001, + SkillBonuses = 0x00000002, + Owner = 0x00000004, + Protection = 0x00000008, + Killer = 0x00000010, + Summoner = 0x00000020, + Removal = 0x00000040, + OldKarmaLoss = 0x00000080, + Skill = 0x00000100, + SuccessBonus = 0x00000200, + ExceptionalBonus = 0x00000400, + MaxCharges = 0x00000800, + Charges = 0x00001000, + MaxChargeTime = 0x00002000, + ChargeTime = 0x00004000, + Blessed = 0x00008000, + Slayer = 0x00010000 + } + + private class TalismanTarget : Target + { + private readonly BaseTalisman m_Talisman; + + public TalismanTarget(BaseTalisman talisman) + : base(12, false, TargetFlags.Beneficial) => + m_Talisman = talisman; + + protected override void OnTarget(Mobile from, object o) + { + if (m_Talisman?.Deleted != false) + return; + + if (from.Talisman != m_Talisman) + { + from.SendLocalizedMessage(502641); // You must equip this item to use it. + return; + } + + if (!(o is Mobile target)) + { + from.SendLocalizedMessage(1046439); // That is not a valid target. + return; + } + + if (m_Talisman.ChargeTime > 0) + { + from.SendLocalizedMessage( + 1074882, + m_Talisman.ChargeTime.ToString() + ); // You must wait ~1_val~ seconds for this to recharge. + return; + } + + if (m_Talisman.Charges == 0 && m_Talisman.MaxCharges > 0) + { + from.SendLocalizedMessage(1042544); // This item is out of charges. + return; + } + + switch (m_Talisman.Removal) + { + case TalismanRemoval.Curse: + target.PlaySound(0xF6); + target.PlaySound(0x1F7); + target.FixedParticles(0x3709, 1, 30, 9963, 13, 3, EffectLayer.Head); + + IEntity mfrom = new Entity( + Serial.Zero, + new Point3D(target.X, target.Y, target.Z - 10), + from.Map + ); + IEntity mto = new Entity(Serial.Zero, new Point3D(target.X, target.Y, target.Z + 50), from.Map); + Effects.SendMovingParticles( + mfrom, + mto, + 0x2255, + 1, + 0, + false, + false, + 13, + 3, + 9501, + 1, + 0, + EffectLayer.Head, + 0x100 + ); + + StatMod mod; + + mod = target.GetStatMod("[Magic] Str Offset"); + if (mod?.Offset < 0) + target.RemoveStatMod("[Magic] Str Offset"); + + mod = target.GetStatMod("[Magic] Dex Offset"); + if (mod?.Offset < 0) + target.RemoveStatMod("[Magic] Dex Offset"); + + mod = target.GetStatMod("[Magic] Int Offset"); + if (mod?.Offset < 0) + target.RemoveStatMod("[Magic] Int Offset"); + + target.Paralyzed = false; + + EvilOmenSpell.TryEndEffect(target); + StrangleSpell.RemoveCurse(target); + CorpseSkinSpell.RemoveCurse(target); + CurseSpell.RemoveEffect(target); + + BuffInfo.RemoveBuff(target, BuffIcon.Clumsy); + BuffInfo.RemoveBuff(target, BuffIcon.FeebleMind); + BuffInfo.RemoveBuff(target, BuffIcon.Weaken); + BuffInfo.RemoveBuff(target, BuffIcon.MassCurse); + + target.SendLocalizedMessage(1072408); // Any curses on you have been lifted + + if (target != from) + from.SendLocalizedMessage(1072409); // Your targets curses have been lifted + + break; + case TalismanRemoval.Damage: + target.PlaySound(0x201); + Effects.SendLocationParticles( + EffectItem.Create(target.Location, target.Map, EffectItem.DefaultDuration), + 0x3728, + 1, + 13, + 0x834, + 0, + 0x13B2, + 0 + ); + + BleedAttack.EndBleed(target, true); + MortalStrike.EndWound(target); + + BuffInfo.RemoveBuff(target, BuffIcon.Bleed); + BuffInfo.RemoveBuff(target, BuffIcon.MortalStrike); + + target.SendLocalizedMessage(1072405); // Your lasting damage effects have been removed! + + if (target != from) + from.SendLocalizedMessage(1072406); // Your Targets lasting damage effects have been removed! + + break; + case TalismanRemoval.Ward: + target.PlaySound(0x201); + Effects.SendLocationParticles( + EffectItem.Create(target.Location, target.Map, EffectItem.DefaultDuration), + 0x3728, + 1, + 13, + 0x834, + 0, + 0x13B2, + 0 + ); + + MagicReflectSpell.EndReflect(target); + ReactiveArmorSpell.EndArmor(target); + ProtectionSpell.EndProtection(target); + + target.SendLocalizedMessage(1072402); // Your wards have been removed! + + if (target != from) + from.SendLocalizedMessage(1072403); // Your target's wards have been removed! + + break; + case TalismanRemoval.Wildfire: + // TODO + break; + } + + m_Talisman.OnAfterUse(from); + } + } } - - private TalismanSlayerName m_Slayer; - - [CommandProperty(AccessLevel.GameMaster)] - public TalismanSlayerName Slayer - { - get => m_Slayer; - set - { - m_Slayer = value; - InvalidateProperties(); - } - } - - private TalismanAttribute m_Summoner; - private TalismanRemoval m_Removal; - private Mobile m_Creature; - - [CommandProperty(AccessLevel.GameMaster)] - public TalismanAttribute Summoner - { - get => m_Summoner; - set - { - m_Summoner = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public TalismanRemoval Removal - { - get => m_Removal; - set - { - m_Removal = value; - InvalidateProperties(); - } - } - - private TalismanAttribute m_Protection; - private TalismanAttribute m_Killer; - - [CommandProperty(AccessLevel.GameMaster)] - public TalismanAttribute Protection - { - get => m_Protection; - set - { - m_Protection = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public TalismanAttribute Killer - { - get => m_Killer; - set - { - m_Killer = value; - InvalidateProperties(); - } - } - - private SkillName m_Skill; - private int m_SuccessBonus; - private int m_ExceptionalBonus; - - [CommandProperty(AccessLevel.GameMaster)] - public SkillName Skill - { - get => m_Skill; - set - { - m_Skill = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int SuccessBonus - { - get => m_SuccessBonus; - set - { - m_SuccessBonus = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int ExceptionalBonus - { - get => m_ExceptionalBonus; - set - { - m_ExceptionalBonus = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public AosAttributes Attributes { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public AosSkillBonuses SkillBonuses { get; private set; } - - private Timer m_Timer; - - public virtual void StartTimer() - { - if (m_Timer?.Running != true) - m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10), Slice); - } - - public virtual void StopTimer() - { - m_Timer?.Stop(); - m_Timer = null; - } - - public virtual void Slice() - { - if (m_ChargeTime - 10 > 0) - { - m_ChargeTime -= 10; - } - else - { - m_ChargeTime = 0; - - StopTimer(); - } - - InvalidateProperties(); - } - - private static readonly int[] m_ItemIDs = - { - 0x2F58, 0x2F59, 0x2F5A, 0x2F5B - }; - - public static int GetRandomItemID() => m_ItemIDs.RandomElement(); - - private static readonly Type[] m_Summons = - { - typeof(SummonedAntLion), - typeof(SummonedCow), - typeof(SummonedLavaSerpent), - typeof(SummonedOrcBrute), - typeof(SummonedFrostSpider), - typeof(SummonedPanther), - typeof(SummonedDoppleganger), - typeof(SummonedGreatHart), - typeof(SummonedBullFrog), - typeof(SummonedArcticOgreLord), - typeof(SummonedBogling), - typeof(SummonedBakeKitsune), - typeof(SummonedSheep), - typeof(SummonedSkeletalKnight), - typeof(SummonedWailingBanshee), - typeof(SummonedChicken), - typeof(SummonedVorpalBunny), - - typeof(Board), - typeof(IronIngot), - typeof(Bandage) - }; - - private static readonly int[] m_SummonLabels = - { - 1075211, // Ant Lion - 1072494, // Cow - 1072434, // Lava Serpent - 1072414, // Orc Brute - 1072476, // Frost Spider - 1029653, // Panther - 1029741, // Doppleganger - 1018292, // great hart - 1028496, // bullfrog - 1018227, // arctic ogre lord - 1029735, // Bogling - 1030083, // bake-kitsune - 1018285, // sheep - 1018239, // skeletal knight - 1072399, // Wailing Banshee - 1072459, // Chicken - 1072401, // Vorpal Bunny - - 1015101, // Boards - 1044036, // Ingots - 1023817 // clean bandage - }; - - public static Type GetRandomSummonType() => m_Summons.RandomElement(); - - public static TalismanAttribute GetRandomSummoner() - { - if (Utility.RandomDouble() >= 0.025) - return new TalismanAttribute(); - - int num = Utility.Random(m_Summons.Length); - - return num > 14 - ? new TalismanAttribute(m_Summons[num], m_SummonLabels[num], 10) - : new TalismanAttribute(m_Summons[num], m_SummonLabels[num]); - } - - public static TalismanRemoval GetRandomRemoval() - { - if (Utility.RandomDouble() < 0.65) - return (TalismanRemoval)Utility.RandomList(390, 404, 407); - - return TalismanRemoval.None; - } - - private static readonly Type[] m_Killers = - { - typeof(OrcBomber), typeof(OrcBrute), typeof(SewerRat), typeof(Rat), typeof(GiantRat), - typeof(Ratman), typeof(RatmanArcher), typeof(GiantSpider), typeof(FrostSpider), typeof(GiantBlackWidow), - typeof(DreadSpider), typeof(SilverSerpent), typeof(DeepSeaSerpent), typeof(GiantSerpent), typeof(Snake), - typeof(IceSnake), typeof(IceSerpent), typeof(LavaSerpent), typeof(LavaSnake), typeof(Yamandon), - typeof(StrongMongbat), typeof(Mongbat), typeof(VampireBat), typeof(Lich), typeof(EvilMage), - typeof(LichLord), typeof(EvilMageLord), typeof(SkeletalMage), typeof(KhaldunZealot), typeof(AncientLich), - typeof(JukaMage), typeof(MeerMage), typeof(Beetle), typeof(DeathwatchBeetle), typeof(RuneBeetle), - typeof(FireBeetle), typeof(DeathwatchBeetleHatchling), typeof(Bird), typeof(Chicken), typeof(Eagle), - typeof(TropicalBird), typeof(Phoenix), typeof(DesertOstard), typeof(FrenziedOstard), typeof(ForestOstard), - typeof(Crane), typeof(SnowLeopard), typeof(IceFiend), typeof(FrostOoze), typeof(FrostTroll), - typeof(IceElemental), typeof(SnowElemental), typeof(GiantIceWorm), typeof(LadyOfTheSnow), typeof(FireElemental), - typeof(FireSteed), typeof(HellHound), typeof(HellCat), typeof(PredatorHellCat), typeof(LavaLizard), - typeof(FireBeetle), typeof(Cow), typeof(Bull), typeof(Gaman) // , typeof( Minotaur) - // TODO Meraktus, Tormented Minotaur, Minotaur - }; - - private static readonly int[] m_KillerLabels = - { - 1072413, 1072414, 1072418, 1072419, 1072420, - 1072421, 1072423, 1072424, 1072425, 1072426, - 1072427, 1072428, 1072429, 1072430, 1072431, - 1072432, 1072433, 1072434, 1072435, 1072438, - 1072440, 1072441, 1072443, 1072444, 1072445, - 1072446, 1072447, 1072448, 1072449, 1072450, - 1072451, 1072452, 1072453, 1072454, 1072455, - 1072456, 1072457, 1072458, 1072459, 1072461, - 1072462, 1072465, 1072468, 1072469, 1072470, - 1072473, 1072474, 1072477, 1072478, 1072479, - 1072480, 1072481, 1072483, 1072485, 1072486, - 1072487, 1072489, 1072490, 1072491, 1072492, - 1072493, 1072494, 1072495, 1072498 - }; - - public static TalismanAttribute GetRandomKiller() => GetRandomKiller(true); - - public static TalismanAttribute GetRandomKiller(bool includingNone) - { - if (includingNone && Utility.RandomBool()) - return new TalismanAttribute(); - - int num = Utility.Random(m_Killers.Length); - - return new TalismanAttribute(m_Killers[num], m_KillerLabels[num], Utility.RandomMinMax(10, 100)); - } - - public static TalismanAttribute GetRandomProtection() => GetRandomProtection(true); - - public static TalismanAttribute GetRandomProtection(bool includingNone) - { - if (includingNone && Utility.RandomBool()) - return new TalismanAttribute(); - - int num = Utility.Random(m_Killers.Length); - - return new TalismanAttribute(m_Killers[num], m_KillerLabels[num], Utility.RandomMinMax(5, 60)); - } - - private static readonly SkillName[] m_Skills = - { - SkillName.Alchemy, - SkillName.Blacksmith, - SkillName.Carpentry, - SkillName.Cartography, - SkillName.Cooking, - SkillName.Fletching, - SkillName.Inscribe, - SkillName.Tailoring, - SkillName.Tinkering - }; - - public static SkillName GetRandomSkill() => m_Skills.RandomElement(); - - public static int GetRandomExceptional() - { - if (Utility.RandomDouble() < 0.3) - { - double num = 40 - Math.Log(Utility.RandomMinMax(7, 403)) * 5; - - return (int)Math.Round(num); - } - - return 0; - } - - public static int GetRandomSuccessful() - { - if (Utility.RandomDouble() < 0.75) - { - double num = 40 - Math.Log(Utility.RandomMinMax(7, 403)) * 5; - - return (int)Math.Round(num); - } - - return 0; - } - - public static bool GetRandomBlessed() => Utility.RandomDouble() < 0.02; - - public static TalismanSlayerName GetRandomSlayer() => Utility.RandomDouble() < 0.01 ? (TalismanSlayerName)Utility.RandomMinMax(1, 9) : TalismanSlayerName.None; - - public static int GetRandomCharges() => Utility.RandomDouble() < 0.5 ? Utility.RandomMinMax(10, 50) : 0; - } } diff --git a/Projects/UOContent/Items/Talismans/Items/EnchantedSwitch.cs b/Projects/UOContent/Items/Talismans/Items/EnchantedSwitch.cs index c68be6f59..a012f8a29 100644 --- a/Projects/UOContent/Items/Talismans/Items/EnchantedSwitch.cs +++ b/Projects/UOContent/Items/Talismans/Items/EnchantedSwitch.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class EnchantedSwitch : Item - { - [Constructible] - public EnchantedSwitch() : base(0x2F5C) => Weight = 1.0; - - public EnchantedSwitch(Serial serial) : base(serial) + public class EnchantedSwitch : Item { + [Constructible] + public EnchantedSwitch() : base(0x2F5C) => Weight = 1.0; + + public EnchantedSwitch(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072893; // enchanted switch + + 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 int LabelNumber => 1072893; // enchanted switch - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Talismans/Items/HollowPrism.cs b/Projects/UOContent/Items/Talismans/Items/HollowPrism.cs index 3aef282c5..f073fb27e 100644 --- a/Projects/UOContent/Items/Talismans/Items/HollowPrism.cs +++ b/Projects/UOContent/Items/Talismans/Items/HollowPrism.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class HollowPrism : Item - { - [Constructible] - public HollowPrism() : base(0x2F5D) => Weight = 1.0; - - public HollowPrism(Serial serial) : base(serial) + public class HollowPrism : Item { + [Constructible] + public HollowPrism() : base(0x2F5D) => Weight = 1.0; + + public HollowPrism(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072895; // hollow prism + + 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 int LabelNumber => 1072895; // hollow prism - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Talismans/Items/JeweledFiligree.cs b/Projects/UOContent/Items/Talismans/Items/JeweledFiligree.cs index 9cef9adf2..ebfc68296 100644 --- a/Projects/UOContent/Items/Talismans/Items/JeweledFiligree.cs +++ b/Projects/UOContent/Items/Talismans/Items/JeweledFiligree.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class JeweledFiligree : Item - { - [Constructible] - public JeweledFiligree() : base(0x2F5E) => Weight = 1.0; - - public JeweledFiligree(Serial serial) : base(serial) + public class JeweledFiligree : Item { + [Constructible] + public JeweledFiligree() : base(0x2F5E) => Weight = 1.0; + + public JeweledFiligree(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072894; // jeweled filigree + + 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 int LabelNumber => 1072894; // jeweled filigree - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Talismans/Items/RunedPrism.cs b/Projects/UOContent/Items/Talismans/Items/RunedPrism.cs index e31aeef84..5dde27609 100644 --- a/Projects/UOContent/Items/Talismans/Items/RunedPrism.cs +++ b/Projects/UOContent/Items/Talismans/Items/RunedPrism.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class RunedPrism : Item - { - [Constructible] - public RunedPrism() : base(0x2F57) => Weight = 1.0; - - public RunedPrism(Serial serial) : base(serial) + public class RunedPrism : Item { + [Constructible] + public RunedPrism() : base(0x2F57) => Weight = 1.0; + + public RunedPrism(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073465; // runed prism + + 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 int LabelNumber => 1073465; // runed prism - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Talismans/Items/RunedSwitch.cs b/Projects/UOContent/Items/Talismans/Items/RunedSwitch.cs index 5b85a65d1..54069787e 100644 --- a/Projects/UOContent/Items/Talismans/Items/RunedSwitch.cs +++ b/Projects/UOContent/Items/Talismans/Items/RunedSwitch.cs @@ -2,74 +2,75 @@ using Server.Targeting; namespace Server.Items { - public class RunedSwitch : Item - { - [Constructible] - public RunedSwitch() : base(0x2F61) => Weight = 1.0; - - public RunedSwitch(Serial serial) : base(serial) + public class RunedSwitch : Item { - } + [Constructible] + public RunedSwitch() : base(0x2F61) => Weight = 1.0; - public override int LabelNumber => 1072896; // runed switch - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1075101); // Please select an item to recharge. - from.Target = new InternalTarget(this); - } - else - { - from.SendLocalizedMessage(1060640); // The item must be in your backpack to use it. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private class InternalTarget : Target - { - private readonly RunedSwitch m_Item; - - public InternalTarget(RunedSwitch item) : base(0, false, TargetFlags.None) => m_Item = item; - - protected override void OnTarget(Mobile from, object o) - { - if (m_Item?.Deleted != false) - return; - - if (o is BaseTalisman talisman) + public RunedSwitch(Serial serial) : base(serial) { - if (talisman.Charges == 0) - { - talisman.Charges = talisman.MaxCharges; - m_Item.Delete(); - from.SendLocalizedMessage(1075100); // The item has been recharged. - } - else - { - from.SendLocalizedMessage( - 1075099); // You cannot recharge that item until all of its current charges have been used. - } } - else + + public override int LabelNumber => 1072896; // runed switch + + public override void OnDoubleClick(Mobile from) { - from.SendLocalizedMessage(1046439); // That is not a valid target. + if (IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1075101); // Please select an item to recharge. + from.Target = new InternalTarget(this); + } + else + { + from.SendLocalizedMessage(1060640); // The item must be in your backpack to use it. + } + } + + 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(); + } + + private class InternalTarget : Target + { + private readonly RunedSwitch m_Item; + + public InternalTarget(RunedSwitch item) : base(0, false, TargetFlags.None) => m_Item = item; + + protected override void OnTarget(Mobile from, object o) + { + if (m_Item?.Deleted != false) + return; + + if (o is BaseTalisman talisman) + { + if (talisman.Charges == 0) + { + talisman.Charges = talisman.MaxCharges; + m_Item.Delete(); + from.SendLocalizedMessage(1075100); // The item has been recharged. + } + else + { + from.SendLocalizedMessage( + 1075099 + ); // You cannot recharge that item until all of its current charges have been used. + } + } + else + { + from.SendLocalizedMessage(1046439); // That is not a valid target. + } + } } - } } - } } diff --git a/Projects/UOContent/Items/Talismans/RandomTalisman.cs b/Projects/UOContent/Items/Talismans/RandomTalisman.cs index ca6c3a297..e201ac115 100644 --- a/Projects/UOContent/Items/Talismans/RandomTalisman.cs +++ b/Projects/UOContent/Items/Talismans/RandomTalisman.cs @@ -1,58 +1,58 @@ namespace Server.Items { - public class RandomTalisman : BaseTalisman - { - [Constructible] - public RandomTalisman() : base(GetRandomItemID()) + public class RandomTalisman : BaseTalisman { - Summoner = GetRandomSummoner(); - - if (Summoner.IsEmpty) - { - Removal = GetRandomRemoval(); - - if (Removal != TalismanRemoval.None) + [Constructible] + public RandomTalisman() : base(GetRandomItemID()) { - MaxCharges = GetRandomCharges(); - MaxChargeTime = 1200; + Summoner = GetRandomSummoner(); + + if (Summoner.IsEmpty) + { + Removal = GetRandomRemoval(); + + if (Removal != TalismanRemoval.None) + { + MaxCharges = GetRandomCharges(); + MaxChargeTime = 1200; + } + } + else + { + MaxCharges = Utility.RandomMinMax(10, 50); + + if (Summoner.IsItem) + MaxChargeTime = 60; + else + MaxChargeTime = 1800; + } + + Blessed = GetRandomBlessed(); + Slayer = GetRandomSlayer(); + Protection = GetRandomProtection(); + Killer = GetRandomKiller(); + Skill = GetRandomSkill(); + ExceptionalBonus = GetRandomExceptional(); + SuccessBonus = GetRandomSuccessful(); + Charges = MaxCharges; } - } - else - { - MaxCharges = Utility.RandomMinMax(10, 50); - if (Summoner.IsItem) - MaxChargeTime = 60; - else - MaxChargeTime = 1800; - } + public RandomTalisman(Serial serial) : base(serial) + { + } - Blessed = GetRandomBlessed(); - Slayer = GetRandomSlayer(); - Protection = GetRandomProtection(); - Killer = GetRandomKiller(); - Skill = GetRandomSkill(); - ExceptionalBonus = GetRandomExceptional(); - SuccessBonus = GetRandomSuccessful(); - Charges = MaxCharges; + 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 RandomTalisman(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Talismans/TalismanAttribute.cs b/Projects/UOContent/Items/Talismans/TalismanAttribute.cs index 1181c8da3..aea5cc8e1 100644 --- a/Projects/UOContent/Items/Talismans/TalismanAttribute.cs +++ b/Projects/UOContent/Items/Talismans/TalismanAttribute.cs @@ -2,102 +2,102 @@ using System; namespace Server.Items { - [PropertyObject] - public class TalismanAttribute - { - public TalismanAttribute() : this(null, 0) + [PropertyObject] + public class TalismanAttribute { + public TalismanAttribute() : this(null, 0) + { + } + + public TalismanAttribute(TalismanAttribute copy) + { + if (copy != null) + { + Type = copy.Type; + Name = copy.Name; + Amount = copy.Amount; + } + } + + public TalismanAttribute(Type type, TextDefinition name, int amount = 0) + { + Type = type; + Name = name; + Amount = amount; + } + + public TalismanAttribute(IGenericReader reader) + { + var version = reader.ReadInt(); + + var flags = (SaveFlag)reader.ReadEncodedInt(); + + if (GetSaveFlag(flags, SaveFlag.Type)) + Type = AssemblyHandler.FindFirstTypeForName(reader.ReadString()); + + if (GetSaveFlag(flags, SaveFlag.Name)) + Name = TextDefinition.Deserialize(reader); + + if (GetSaveFlag(flags, SaveFlag.Amount)) + Amount = reader.ReadEncodedInt(); + } + + [CommandProperty(AccessLevel.GameMaster)] + public Type Type { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public TextDefinition Name { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Amount { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsEmpty => Type == null; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsItem => Type?.Namespace.Equals("Server.Items") == true; + + public override string ToString() => Type?.Name ?? "None"; + + private static void SetSaveFlag(ref SaveFlag flags, SaveFlag toSet, bool setIf) + { + if (setIf) + flags |= toSet; + } + + private static bool GetSaveFlag(SaveFlag flags, SaveFlag toGet) => (flags & toGet) != 0; + + public virtual void Serialize(IGenericWriter writer) + { + writer.Write(0); // version + + var flags = SaveFlag.None; + + SetSaveFlag(ref flags, SaveFlag.Type, Type != null); + SetSaveFlag(ref flags, SaveFlag.Name, Name != null); + SetSaveFlag(ref flags, SaveFlag.Amount, Amount != 0); + + writer.WriteEncodedInt((int)flags); + + if (GetSaveFlag(flags, SaveFlag.Type)) + writer.Write(Type.FullName); + + if (GetSaveFlag(flags, SaveFlag.Name)) + TextDefinition.Serialize(writer, Name); + + if (GetSaveFlag(flags, SaveFlag.Amount)) + writer.WriteEncodedInt(Amount); + } + + public int DamageBonus(Mobile to) => to?.GetType() == Type ? Amount : 0; + + [Flags] + private enum SaveFlag + { + None = 0x00000000, + Type = 0x00000001, + Name = 0x00000002, + Amount = 0x00000004 + } } - - public TalismanAttribute(TalismanAttribute copy) - { - if (copy != null) - { - Type = copy.Type; - Name = copy.Name; - Amount = copy.Amount; - } - } - - public TalismanAttribute(Type type, TextDefinition name, int amount = 0) - { - Type = type; - Name = name; - Amount = amount; - } - - public TalismanAttribute(IGenericReader reader) - { - int version = reader.ReadInt(); - - SaveFlag flags = (SaveFlag)reader.ReadEncodedInt(); - - if (GetSaveFlag(flags, SaveFlag.Type)) - Type = AssemblyHandler.FindFirstTypeForName(reader.ReadString(), false); - - if (GetSaveFlag(flags, SaveFlag.Name)) - Name = TextDefinition.Deserialize(reader); - - if (GetSaveFlag(flags, SaveFlag.Amount)) - Amount = reader.ReadEncodedInt(); - } - - [CommandProperty(AccessLevel.GameMaster)] - public Type Type { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public TextDefinition Name { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Amount { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsEmpty => Type == null; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsItem => Type?.Namespace.Equals("Server.Items") == true; - - public override string ToString() => Type?.Name ?? "None"; - - private static void SetSaveFlag(ref SaveFlag flags, SaveFlag toSet, bool setIf) - { - if (setIf) - flags |= toSet; - } - - private static bool GetSaveFlag(SaveFlag flags, SaveFlag toGet) => (flags & toGet) != 0; - - public virtual void Serialize(IGenericWriter writer) - { - writer.Write(0); // version - - SaveFlag flags = SaveFlag.None; - - SetSaveFlag(ref flags, SaveFlag.Type, Type != null); - SetSaveFlag(ref flags, SaveFlag.Name, Name != null); - SetSaveFlag(ref flags, SaveFlag.Amount, Amount != 0); - - writer.WriteEncodedInt((int)flags); - - if (GetSaveFlag(flags, SaveFlag.Type)) - writer.Write(Type.FullName); - - if (GetSaveFlag(flags, SaveFlag.Name)) - TextDefinition.Serialize(writer, Name); - - if (GetSaveFlag(flags, SaveFlag.Amount)) - writer.WriteEncodedInt(Amount); - } - - public int DamageBonus(Mobile to) => to?.GetType() == Type ? Amount : 0; - - [Flags] - private enum SaveFlag - { - None = 0x00000000, - Type = 0x00000001, - Name = 0x00000002, - Amount = 0x00000004 - } - } } diff --git a/Projects/UOContent/Items/Talismans/TalismanSlayer.cs b/Projects/UOContent/Items/Talismans/TalismanSlayer.cs index be076ecba..b38b571c3 100644 --- a/Projects/UOContent/Items/Talismans/TalismanSlayer.cs +++ b/Projects/UOContent/Items/Talismans/TalismanSlayer.cs @@ -4,93 +4,98 @@ using Server.Mobiles; namespace Server.Items { - public enum TalismanSlayerName - { - None, - Bear, - Vermin, - Bat, - Mage, - Beetle, - Bird, - Ice, - Flame, - Bovine - } - - public static class TalismanSlayer - { - private static Dictionary m_Table; - - public static void Initialize() + public enum TalismanSlayerName { - m_Table = new Dictionary - { - [TalismanSlayerName.Bear] = new[] - { - typeof(GrizzlyBear), typeof(BlackBear), typeof(BrownBear), typeof(PolarBear) // , typeof( Grobu ) - }, - [TalismanSlayerName.Vermin] = new[] - { - typeof(RatmanMage), typeof(RatmanMage), typeof(RatmanArcher), typeof(Barracoon), typeof(Ratman), typeof(SewerRat), - typeof(Rat), typeof(GiantRat) // , typeof( Chiikkaha ) - }, - [TalismanSlayerName.Bat] = new[] { typeof(Mongbat), typeof(StrongMongbat), typeof(VampireBat) }, - [TalismanSlayerName.Mage] = - new[] - { - typeof(EvilMage), typeof(EvilMageLord), typeof(AncientLich), typeof(Lich), typeof(LichLord), - typeof(SkeletalMage), typeof(BoneMagi), typeof(OrcishMage), typeof(KhaldunZealot), typeof(JukaMage) - }, - [TalismanSlayerName.Beetle] = - new[] - { - typeof(Beetle), typeof(RuneBeetle), typeof(FireBeetle), typeof(DeathwatchBeetle), - typeof(DeathwatchBeetleHatchling) - }, - [TalismanSlayerName.Bird] = new[] - { - typeof(Bird), typeof(TropicalBird), typeof(Chicken), typeof(Crane), typeof(DesertOstard), typeof(Eagle), - typeof(ForestOstard), typeof(FrenziedOstard), - typeof(Phoenix), /*typeof( Pyre ), typeof( Swoop ), typeof( Saliva ),*/ typeof(Harpy), typeof(StoneHarpy) // ????? - }, - [TalismanSlayerName.Ice] = new[] - { - typeof(ArcticOgreLord), typeof(IceElemental), typeof(SnowElemental), typeof(FrostOoze), - typeof(IceFiend), /*typeof( UnfrozenMummy ),*/ typeof(FrostSpider), typeof(LadyOfTheSnow), typeof(FrostTroll), + None, + Bear, + Vermin, + Bat, + Mage, + Beetle, + Bird, + Ice, + Flame, + Bovine + } - // TODO WinterReaper, check - typeof(IceSnake), typeof(SnowLeopard), typeof(PolarBear), typeof(IceSerpent), typeof(GiantIceWorm) - }, - [TalismanSlayerName.Flame] = new[] - { - typeof(FireBeetle), typeof(HellHound), typeof(LavaSerpent), typeof(FireElemental), typeof(PredatorHellCat), - typeof(Phoenix), typeof(FireGargoyle), typeof(HellCat), - /*typeof( Pyre ),*/ typeof(FireSteed), typeof(LavaLizard), + public static class TalismanSlayer + { + private static Dictionary m_Table; - // TODO check - typeof(LavaSnake) - }, - [TalismanSlayerName.Bovine] = new[] + public static void Initialize() { - typeof(Cow), typeof(Bull), typeof(Gaman) /*, typeof( MinotaurCaptain ), typeof( MinotaurScout ), typeof( Minotaur ) */ - // TODO TormentedMinotaur + m_Table = new Dictionary + { + [TalismanSlayerName.Bear] = new[] + { + typeof(GrizzlyBear), typeof(BlackBear), typeof(BrownBear), typeof(PolarBear) // , typeof( Grobu ) + }, + [TalismanSlayerName.Vermin] = new[] + { + typeof(RatmanMage), typeof(RatmanMage), typeof(RatmanArcher), typeof(Barracoon), typeof(Ratman), + typeof(SewerRat), + typeof(Rat), typeof(GiantRat) // , typeof( Chiikkaha ) + }, + [TalismanSlayerName.Bat] = new[] { typeof(Mongbat), typeof(StrongMongbat), typeof(VampireBat) }, + [TalismanSlayerName.Mage] = + new[] + { + typeof(EvilMage), typeof(EvilMageLord), typeof(AncientLich), typeof(Lich), typeof(LichLord), + typeof(SkeletalMage), typeof(BoneMagi), typeof(OrcishMage), typeof(KhaldunZealot), typeof(JukaMage) + }, + [TalismanSlayerName.Beetle] = + new[] + { + typeof(Beetle), typeof(RuneBeetle), typeof(FireBeetle), typeof(DeathwatchBeetle), + typeof(DeathwatchBeetleHatchling) + }, + [TalismanSlayerName.Bird] = new[] + { + typeof(Bird), typeof(TropicalBird), typeof(Chicken), typeof(Crane), typeof(DesertOstard), typeof(Eagle), + typeof(ForestOstard), typeof(FrenziedOstard), + typeof(Phoenix), /*typeof( Pyre ), typeof( Swoop ), typeof( Saliva ),*/ typeof(Harpy), + typeof(StoneHarpy) // ????? + }, + [TalismanSlayerName.Ice] = new[] + { + typeof(ArcticOgreLord), typeof(IceElemental), typeof(SnowElemental), typeof(FrostOoze), + typeof(IceFiend), /*typeof( UnfrozenMummy ),*/ typeof(FrostSpider), typeof(LadyOfTheSnow), + typeof(FrostTroll), + + // TODO WinterReaper, check + typeof(IceSnake), typeof(SnowLeopard), typeof(PolarBear), typeof(IceSerpent), typeof(GiantIceWorm) + }, + [TalismanSlayerName.Flame] = new[] + { + typeof(FireBeetle), typeof(HellHound), typeof(LavaSerpent), typeof(FireElemental), + typeof(PredatorHellCat), + typeof(Phoenix), typeof(FireGargoyle), typeof(HellCat), + /*typeof( Pyre ),*/ typeof(FireSteed), typeof(LavaLizard), + + // TODO check + typeof(LavaSnake) + }, + [TalismanSlayerName.Bovine] = new[] + { + typeof(Cow), typeof(Bull), + typeof(Gaman) /*, typeof( MinotaurCaptain ), typeof( MinotaurScout ), typeof( Minotaur ) */ + // TODO TormentedMinotaur + } + }; + } + + public static bool Slays(TalismanSlayerName name, Mobile m) + { + if (m == null || !m_Table.TryGetValue(name, out var types) || types == null) + return false; + + var type = m.GetType(); + + for (var i = 0; i < types.Length; i++) + if (types[i].IsAssignableFrom(type)) + return true; + + return false; } - }; } - - public static bool Slays(TalismanSlayerName name, Mobile m) - { - if (m == null || !m_Table.TryGetValue(name, out Type[] types) || types == null) - return false; - - Type type = m.GetType(); - - for (int i = 0; i < types.Length; i++) - if (types[i].IsAssignableFrom(type)) - return true; - - return false; - } - } } diff --git a/Projects/UOContent/Items/Talismans/TalismanSummons.cs b/Projects/UOContent/Items/Talismans/TalismanSummons.cs index b0b3e1c45..f2be15c6f 100644 --- a/Projects/UOContent/Items/Talismans/TalismanSummons.cs +++ b/Projects/UOContent/Items/Talismans/TalismanSummons.cs @@ -5,629 +5,634 @@ using Server.Items; namespace Server.Mobiles { - public class BaseTalismanSummon : BaseCreature - { - // public override bool IsInvulnerable => true; // TODO: Wailing banshees are NOT invulnerable, are any of the others? - - public BaseTalismanSummon() : base(AIType.AI_Melee, FightMode.None, 10, 1, 0.2, 0.4) + public class BaseTalismanSummon : BaseCreature { - // TODO: Stats/skills - } + // public override bool IsInvulnerable => true; // TODO: Wailing banshees are NOT invulnerable, are any of the others? - public BaseTalismanSummon(Serial serial) : base(serial) - { - } - - public override bool Commandable => false; - public override bool InitialInnocent => true; - - public override void AddCustomContextEntries(Mobile from, List list) - { - if (from.Alive && ControlMaster == from) - list.Add(new TalismanReleaseEntry(this)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - private class TalismanReleaseEntry : ContextMenuEntry - { - private readonly Mobile m_Mobile; - - public TalismanReleaseEntry(Mobile m) : base(6118, 3) => m_Mobile = m; - - public override void OnClick() - { - Effects.SendLocationParticles(EffectItem.Create(m_Mobile.Location, m_Mobile.Map, EffectItem.DefaultDuration), - 0x3728, 8, 20, 5042); - Effects.PlaySound(m_Mobile, m_Mobile.Map, 0x201); - - m_Mobile.Delete(); - } - } - } - - public class SummonedAntLion : BaseTalismanSummon - { - [Constructible] - public SummonedAntLion() - { - Body = 787; - BaseSoundID = 1006; - } - - public SummonedAntLion(Serial serial) : base(serial) - { - } - - public override string DefaultName => "an ant lion"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SummonedArcticOgreLord : BaseTalismanSummon - { - [Constructible] - public SummonedArcticOgreLord() - { - Body = 135; - BaseSoundID = 427; - } - - public SummonedArcticOgreLord(Serial serial) : base(serial) - { - } - - public override string DefaultName => "an arctic ogre lord"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SummonedBakeKitsune : BaseTalismanSummon - { - [Constructible] - public SummonedBakeKitsune() - { - Body = 246; - BaseSoundID = 0x4DD; - } - - public SummonedBakeKitsune(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a bake kitsune"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SummonedBogling : BaseTalismanSummon - { - [Constructible] - public SummonedBogling() - { - Body = 779; - BaseSoundID = 422; - } - - public SummonedBogling(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a bogling"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SummonedBullFrog : BaseTalismanSummon - { - [Constructible] - public SummonedBullFrog() - { - Body = 81; - Hue = Utility.RandomList(0x5AC, 0x5A3, 0x59A, 0x591, 0x588, 0x57F); - BaseSoundID = 0x266; - } - - public SummonedBullFrog(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a bull frog"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SummonedChicken : BaseTalismanSummon - { - [Constructible] - public SummonedChicken() - { - Body = 0xD0; - BaseSoundID = 0x6E; - } - - public SummonedChicken(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a chicken"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SummonedCow : BaseTalismanSummon - { - [Constructible] - public SummonedCow() - { - Body = Utility.RandomList(0xD8, 0xE7); - BaseSoundID = 0x78; - } - - public SummonedCow(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a cow"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SummonedDoppleganger : BaseTalismanSummon - { - [Constructible] - public SummonedDoppleganger() - { - Body = 0x309; - BaseSoundID = 0x451; - } - - public SummonedDoppleganger(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a doppleganger"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SummonedFrostSpider : BaseTalismanSummon - { - [Constructible] - public SummonedFrostSpider() - { - Body = 20; - BaseSoundID = 0x388; - } - - public SummonedFrostSpider(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a frost spider"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SummonedGreatHart : BaseTalismanSummon - { - [Constructible] - public SummonedGreatHart() - { - Body = 0xEA; - BaseSoundID = 0x82; - } - - public SummonedGreatHart(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a great hart"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SummonedLavaSerpent : BaseTalismanSummon - { - [Constructible] - public SummonedLavaSerpent() - { - Body = 90; - BaseSoundID = 219; - } - - public SummonedLavaSerpent(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a lava serpent"; - - public override void OnThink() - { - /* - if (m_NextWave < DateTime.UtcNow) - AreaHeatDamage(); - */ - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - - /* - // An area attack that only damages staff, wtf? - - private DateTime m_NextWave; - - public void AreaHeatDamage() - { - Mobile mob = ControlMaster; - - if (mob != null) - { - if (mob.InRange( Location, 2 )) + public BaseTalismanSummon() : base(AIType.AI_Melee, FightMode.None, 10, 1, 0.2, 0.4) { - if (mob.AccessLevel != AccessLevel.Player) - { - AOS.Damage( mob, Utility.Random( 2, 3 ), 0, 100, 0, 0, 0 ); - mob.SendLocalizedMessage( 1008112 ); // The intense heat is damaging you! - } + // TODO: Stats/skills } - GuardedRegion r = Region as GuardedRegion; - - if (r != null && mob.Alive) + public BaseTalismanSummon(Serial serial) : base(serial) { - foreach ( Mobile m in GetMobilesInRange( 2 ) ) - { - if (!mob.CanBeHarmful( m )) - mob.CriminalAction( false ); - } } - } - m_NextWave = DateTime.UtcNow + TimeSpan.FromSeconds( 3 ); + public override bool Commandable => false; + public override bool InitialInnocent => true; + + public override void AddCustomContextEntries(Mobile from, List list) + { + if (from.Alive && ControlMaster == from) + list.Add(new TalismanReleaseEntry(this)); + } + + 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(); + } + + private class TalismanReleaseEntry : ContextMenuEntry + { + private readonly Mobile m_Mobile; + + public TalismanReleaseEntry(Mobile m) : base(6118, 3) => m_Mobile = m; + + public override void OnClick() + { + Effects.SendLocationParticles( + EffectItem.Create(m_Mobile.Location, m_Mobile.Map, EffectItem.DefaultDuration), + 0x3728, + 8, + 20, + 5042 + ); + Effects.PlaySound(m_Mobile, m_Mobile.Map, 0x201); + + m_Mobile.Delete(); + } + } } - */ - } - public class SummonedOrcBrute : BaseTalismanSummon - { - [Constructible] - public SummonedOrcBrute() + public class SummonedAntLion : BaseTalismanSummon { - Body = 189; - BaseSoundID = 0x45A; + [Constructible] + public SummonedAntLion() + { + Body = 787; + BaseSoundID = 1006; + } + + public SummonedAntLion(Serial serial) : base(serial) + { + } + + public override string DefaultName => "an ant lion"; + + 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(); + } } - public SummonedOrcBrute(Serial serial) : base(serial) + public class SummonedArcticOgreLord : BaseTalismanSummon { + [Constructible] + public SummonedArcticOgreLord() + { + Body = 135; + BaseSoundID = 427; + } + + public SummonedArcticOgreLord(Serial serial) : base(serial) + { + } + + public override string DefaultName => "an arctic ogre lord"; + + 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(); + } } - public override string DefaultName => "an orc brute"; - - public override void Serialize(IGenericWriter writer) + public class SummonedBakeKitsune : BaseTalismanSummon { - base.Serialize(writer); + [Constructible] + public SummonedBakeKitsune() + { + Body = 246; + BaseSoundID = 0x4DD; + } - writer.WriteEncodedInt(0); // version + public SummonedBakeKitsune(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a bake kitsune"; + + 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(); + } } - public override void Deserialize(IGenericReader reader) + public class SummonedBogling : BaseTalismanSummon { - base.Deserialize(reader); + [Constructible] + public SummonedBogling() + { + Body = 779; + BaseSoundID = 422; + } - int version = reader.ReadEncodedInt(); + public SummonedBogling(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a bogling"; + + 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(); + } } - } - public class SummonedPanther : BaseTalismanSummon - { - [Constructible] - public SummonedPanther() + public class SummonedBullFrog : BaseTalismanSummon { - Body = 0xD6; - Hue = 0x901; - BaseSoundID = 0x462; + [Constructible] + public SummonedBullFrog() + { + Body = 81; + Hue = Utility.RandomList(0x5AC, 0x5A3, 0x59A, 0x591, 0x588, 0x57F); + BaseSoundID = 0x266; + } + + public SummonedBullFrog(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a bull frog"; + + 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(); + } } - public SummonedPanther(Serial serial) : base(serial) + public class SummonedChicken : BaseTalismanSummon { + [Constructible] + public SummonedChicken() + { + Body = 0xD0; + BaseSoundID = 0x6E; + } + + public SummonedChicken(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a chicken"; + + 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(); + } } - public override string DefaultName => "a panther"; - - public override void Serialize(IGenericWriter writer) + public class SummonedCow : BaseTalismanSummon { - base.Serialize(writer); + [Constructible] + public SummonedCow() + { + Body = Utility.RandomList(0xD8, 0xE7); + BaseSoundID = 0x78; + } - writer.WriteEncodedInt(0); // version + public SummonedCow(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a cow"; + + 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(); + } } - public override void Deserialize(IGenericReader reader) + public class SummonedDoppleganger : BaseTalismanSummon { - base.Deserialize(reader); + [Constructible] + public SummonedDoppleganger() + { + Body = 0x309; + BaseSoundID = 0x451; + } - int version = reader.ReadEncodedInt(); + public SummonedDoppleganger(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a doppleganger"; + + 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(); + } } - } - public class SummonedSheep : BaseTalismanSummon - { - [Constructible] - public SummonedSheep() + public class SummonedFrostSpider : BaseTalismanSummon { - Body = 0xCF; - BaseSoundID = 0xD6; + [Constructible] + public SummonedFrostSpider() + { + Body = 20; + BaseSoundID = 0x388; + } + + public SummonedFrostSpider(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a frost spider"; + + 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(); + } } - public SummonedSheep(Serial serial) : base(serial) + public class SummonedGreatHart : BaseTalismanSummon { + [Constructible] + public SummonedGreatHart() + { + Body = 0xEA; + BaseSoundID = 0x82; + } + + public SummonedGreatHart(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a great hart"; + + 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(); + } } - public override string DefaultName => "a sheep"; - - public override void Serialize(IGenericWriter writer) + public class SummonedLavaSerpent : BaseTalismanSummon { - base.Serialize(writer); + [Constructible] + public SummonedLavaSerpent() + { + Body = 90; + BaseSoundID = 219; + } - writer.WriteEncodedInt(0); // version + public SummonedLavaSerpent(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a lava serpent"; + + public override void OnThink() + { + /* + if (m_NextWave < DateTime.UtcNow) + AreaHeatDamage(); + */ + } + + 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(); + } + + /* + // An area attack that only damages staff, wtf? + + private DateTime m_NextWave; + + public void AreaHeatDamage() + { + Mobile mob = ControlMaster; + + if (mob != null) + { + if (mob.InRange( Location, 2 )) + { + if (mob.AccessLevel != AccessLevel.Player) + { + AOS.Damage( mob, Utility.Random( 2, 3 ), 0, 100, 0, 0, 0 ); + mob.SendLocalizedMessage( 1008112 ); // The intense heat is damaging you! + } + } + + GuardedRegion r = Region as GuardedRegion; + + if (r != null && mob.Alive) + { + foreach ( Mobile m in GetMobilesInRange( 2 ) ) + { + if (!mob.CanBeHarmful( m )) + mob.CriminalAction( false ); + } + } + } + + m_NextWave = DateTime.UtcNow + TimeSpan.FromSeconds( 3 ); + } + */ } - public override void Deserialize(IGenericReader reader) + public class SummonedOrcBrute : BaseTalismanSummon { - base.Deserialize(reader); + [Constructible] + public SummonedOrcBrute() + { + Body = 189; + BaseSoundID = 0x45A; + } - int version = reader.ReadEncodedInt(); + public SummonedOrcBrute(Serial serial) : base(serial) + { + } + + public override string DefaultName => "an orc brute"; + + 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(); + } } - } - public class SummonedSkeletalKnight : BaseTalismanSummon - { - [Constructible] - public SummonedSkeletalKnight() + public class SummonedPanther : BaseTalismanSummon { - Body = 147; - BaseSoundID = 451; + [Constructible] + public SummonedPanther() + { + Body = 0xD6; + Hue = 0x901; + BaseSoundID = 0x462; + } + + public SummonedPanther(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a panther"; + + 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(); + } } - public SummonedSkeletalKnight(Serial serial) : base(serial) + public class SummonedSheep : BaseTalismanSummon { + [Constructible] + public SummonedSheep() + { + Body = 0xCF; + BaseSoundID = 0xD6; + } + + public SummonedSheep(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a sheep"; + + 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(); + } } - public override string DefaultName => "a skeletal knight"; - - public override void Serialize(IGenericWriter writer) + public class SummonedSkeletalKnight : BaseTalismanSummon { - base.Serialize(writer); + [Constructible] + public SummonedSkeletalKnight() + { + Body = 147; + BaseSoundID = 451; + } - writer.WriteEncodedInt(0); // version + public SummonedSkeletalKnight(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a skeletal knight"; + + 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(); + } } - public override void Deserialize(IGenericReader reader) + public class SummonedVorpalBunny : BaseTalismanSummon { - base.Deserialize(reader); + [Constructible] + public SummonedVorpalBunny() + { + Body = 205; + Hue = 0x480; + BaseSoundID = 0xC9; - int version = reader.ReadEncodedInt(); + Timer.DelayCall(TimeSpan.FromMinutes(30.0), BeginTunnel); + } + + public SummonedVorpalBunny(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a vorpal bunny"; + + public virtual void BeginTunnel() + { + if (Deleted) + return; + + new VorpalBunny.BunnyHole().MoveToWorld(Location, Map); + + Frozen = true; + Say("* The bunny begins to dig a tunnel back to its underground lair *"); + PlaySound(0x247); + + Timer.DelayCall(TimeSpan.FromSeconds(5.0), Delete); + } + + 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(); + } } - } - public class SummonedVorpalBunny : BaseTalismanSummon - { - [Constructible] - public SummonedVorpalBunny() + public class SummonedWailingBanshee : BaseTalismanSummon { - Body = 205; - Hue = 0x480; - BaseSoundID = 0xC9; + [Constructible] + public SummonedWailingBanshee() + { + Body = 310; + BaseSoundID = 0x482; + } - Timer.DelayCall(TimeSpan.FromMinutes(30.0), BeginTunnel); + public SummonedWailingBanshee(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a wailing banshee"; + + 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(); + } } - - public SummonedVorpalBunny(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a vorpal bunny"; - - public virtual void BeginTunnel() - { - if (Deleted) - return; - - new VorpalBunny.BunnyHole().MoveToWorld(Location, Map); - - Frozen = true; - Say("* The bunny begins to dig a tunnel back to its underground lair *"); - PlaySound(0x247); - - Timer.DelayCall(TimeSpan.FromSeconds(5.0), Delete); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class SummonedWailingBanshee : BaseTalismanSummon - { - [Constructible] - public SummonedWailingBanshee() - { - Body = 310; - BaseSoundID = 0x482; - } - - public SummonedWailingBanshee(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a wailing banshee"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } } diff --git a/Projects/UOContent/Items/Traps/BaseTrap.cs b/Projects/UOContent/Items/Traps/BaseTrap.cs index 82331eb3a..d53e40649 100644 --- a/Projects/UOContent/Items/Traps/BaseTrap.cs +++ b/Projects/UOContent/Items/Traps/BaseTrap.cs @@ -2,77 +2,78 @@ using System; namespace Server.Items { - public abstract class BaseTrap : Item - { - private DateTime m_NextPassiveTrigger, m_NextActiveTrigger; - - public BaseTrap(int itemID) : base(itemID) => Movable = false; - - public BaseTrap(Serial serial) : base(serial) + public abstract class BaseTrap : Item { + private DateTime m_NextPassiveTrigger, m_NextActiveTrigger; + + public BaseTrap(int itemID) : base(itemID) => Movable = false; + + public BaseTrap(Serial serial) : base(serial) + { + } + + public virtual bool PassivelyTriggered => false; + public virtual TimeSpan PassiveTriggerDelay => TimeSpan.Zero; + public virtual int PassiveTriggerRange => -1; + public virtual TimeSpan ResetDelay => TimeSpan.Zero; + + public override bool HandlesOnMovement => true; // Tell the core that we implement OnMovement + + public virtual void OnTrigger(Mobile from) + { + } + + public virtual int GetEffectHue() + { + var hue = Hue & 0x3FFF; + + if (hue < 2) + return 0; + + return hue - 1; + } + + public bool CheckRange(Point3D loc, Point3D oldLoc, int range) => + CheckRange(loc, range) && !CheckRange(oldLoc, range); + + public bool CheckRange(Point3D loc, int range) => + Z + 8 >= loc.Z && loc.Z + 16 > Z + && Utility.InRange(GetWorldLocation(), loc, range); + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + base.OnMovement(m, oldLocation); + + if (m.Location == oldLocation) + return; + + if (CheckRange(m.Location, oldLocation, 0) && DateTime.UtcNow >= m_NextActiveTrigger) + { + m_NextActiveTrigger = m_NextPassiveTrigger = DateTime.UtcNow + ResetDelay; + + OnTrigger(m); + } + else if (PassivelyTriggered && CheckRange(m.Location, oldLocation, PassiveTriggerRange) && + DateTime.UtcNow >= m_NextPassiveTrigger) + { + m_NextPassiveTrigger = DateTime.UtcNow + PassiveTriggerDelay; + + OnTrigger(m); + } + } + + 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 virtual bool PassivelyTriggered => false; - public virtual TimeSpan PassiveTriggerDelay => TimeSpan.Zero; - public virtual int PassiveTriggerRange => -1; - public virtual TimeSpan ResetDelay => TimeSpan.Zero; - - public override bool HandlesOnMovement => true; // Tell the core that we implement OnMovement - - public virtual void OnTrigger(Mobile from) - { - } - - public virtual int GetEffectHue() - { - int hue = Hue & 0x3FFF; - - if (hue < 2) - return 0; - - return hue - 1; - } - - public bool CheckRange(Point3D loc, Point3D oldLoc, int range) => CheckRange(loc, range) && !CheckRange(oldLoc, range); - - public bool CheckRange(Point3D loc, int range) => - Z + 8 >= loc.Z && loc.Z + 16 > Z - && Utility.InRange(GetWorldLocation(), loc, range); - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - base.OnMovement(m, oldLocation); - - if (m.Location == oldLocation) - return; - - if (CheckRange(m.Location, oldLocation, 0) && DateTime.UtcNow >= m_NextActiveTrigger) - { - m_NextActiveTrigger = m_NextPassiveTrigger = DateTime.UtcNow + ResetDelay; - - OnTrigger(m); - } - else if (PassivelyTriggered && CheckRange(m.Location, oldLocation, PassiveTriggerRange) && - DateTime.UtcNow >= m_NextPassiveTrigger) - { - m_NextPassiveTrigger = DateTime.UtcNow + PassiveTriggerDelay; - - OnTrigger(m); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Traps/FireColumnTrap.cs b/Projects/UOContent/Items/Traps/FireColumnTrap.cs index a5435db9c..eec1cff30 100644 --- a/Projects/UOContent/Items/Traps/FireColumnTrap.cs +++ b/Projects/UOContent/Items/Traps/FireColumnTrap.cs @@ -3,112 +3,126 @@ using Server.Spells; namespace Server.Items { - public class FireColumnTrap : BaseTrap - { - private int m_MaxDamage; - - private int m_MinDamage; - - private bool m_WarningFlame; - - [Constructible] - public FireColumnTrap() : base(0x1B71) + public class FireColumnTrap : BaseTrap { - m_MinDamage = 10; - m_MaxDamage = 40; + private int m_MaxDamage; - m_WarningFlame = true; + private int m_MinDamage; + + private bool m_WarningFlame; + + [Constructible] + public FireColumnTrap() : base(0x1B71) + { + m_MinDamage = 10; + m_MaxDamage = 40; + + m_WarningFlame = true; + } + + public FireColumnTrap(Serial serial) : base(serial) + { + } + + public override bool PassivelyTriggered => true; + public override TimeSpan PassiveTriggerDelay => TimeSpan.FromSeconds(2.0); + public override int PassiveTriggerRange => 3; + public override TimeSpan ResetDelay => TimeSpan.FromSeconds(0.5); + + [CommandProperty(AccessLevel.GameMaster)] + public virtual int MinDamage + { + get => m_MinDamage; + set => m_MinDamage = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public virtual int MaxDamage + { + get => m_MaxDamage; + set => m_MaxDamage = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public virtual bool WarningFlame + { + get => m_WarningFlame; + set => m_WarningFlame = value; + } + + public override void OnTrigger(Mobile from) + { + if (from.AccessLevel > AccessLevel.Player) + return; + + if (WarningFlame) + DoEffect(); + + if (from.Alive && CheckRange(from.Location, 0)) + { + SpellHelper.Damage( + TimeSpan.FromSeconds(0.5), + from, + from, + Utility.RandomMinMax(MinDamage, MaxDamage), + 0, + 100, + 0, + 0, + 0 + ); + + if (!WarningFlame) + DoEffect(); + } + } + + private void DoEffect() + { + Effects.SendLocationParticles( + EffectItem.Create(Location, Map, EffectItem.DefaultDuration), + 0x3709, + 10, + 30, + 5052 + ); + Effects.PlaySound(Location, Map, 0x225); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(m_WarningFlame); + writer.Write(m_MinDamage); + writer.Write(m_MaxDamage); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_WarningFlame = reader.ReadBool(); + m_MinDamage = reader.ReadInt(); + m_MaxDamage = reader.ReadInt(); + break; + } + } + + if (version == 0) + { + m_WarningFlame = true; + m_MinDamage = 10; + m_MaxDamage = 40; + } + } } - - public FireColumnTrap(Serial serial) : base(serial) - { - } - - public override bool PassivelyTriggered => true; - public override TimeSpan PassiveTriggerDelay => TimeSpan.FromSeconds(2.0); - public override int PassiveTriggerRange => 3; - public override TimeSpan ResetDelay => TimeSpan.FromSeconds(0.5); - - [CommandProperty(AccessLevel.GameMaster)] - public virtual int MinDamage - { - get => m_MinDamage; - set => m_MinDamage = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public virtual int MaxDamage - { - get => m_MaxDamage; - set => m_MaxDamage = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public virtual bool WarningFlame - { - get => m_WarningFlame; - set => m_WarningFlame = value; - } - - public override void OnTrigger(Mobile from) - { - if (from.AccessLevel > AccessLevel.Player) - return; - - if (WarningFlame) - DoEffect(); - - if (from.Alive && CheckRange(from.Location, 0)) - { - SpellHelper.Damage(TimeSpan.FromSeconds(0.5), from, from, Utility.RandomMinMax(MinDamage, MaxDamage), 0, 100, - 0, 0, 0); - - if (!WarningFlame) - DoEffect(); - } - } - - private void DoEffect() - { - Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x3709, 10, 30, - 5052); - Effects.PlaySound(Location, Map, 0x225); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(m_WarningFlame); - writer.Write(m_MinDamage); - writer.Write(m_MaxDamage); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_WarningFlame = reader.ReadBool(); - m_MinDamage = reader.ReadInt(); - m_MaxDamage = reader.ReadInt(); - break; - } - } - - if (version == 0) - { - m_WarningFlame = true; - m_MinDamage = 10; - m_MaxDamage = 40; - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Traps/FlameSpurtTrap.cs b/Projects/UOContent/Items/Traps/FlameSpurtTrap.cs index a4ec751de..fa59e535a 100644 --- a/Projects/UOContent/Items/Traps/FlameSpurtTrap.cs +++ b/Projects/UOContent/Items/Traps/FlameSpurtTrap.cs @@ -4,159 +4,159 @@ using Server.Spells; namespace Server.Items { - public class FlameSpurtTrap : BaseTrap - { - private Item m_Spurt; - private Timer m_Timer; - - [Constructible] - public FlameSpurtTrap() : base(0x1B71) => Visible = false; - - public FlameSpurtTrap(Serial serial) : base(serial) + public class FlameSpurtTrap : BaseTrap { - } + private Item m_Spurt; + private Timer m_Timer; - public virtual void StartTimer() - { - m_Timer ??= Timer.DelayCall(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0), Refresh); - } + [Constructible] + public FlameSpurtTrap() : base(0x1B71) => Visible = false; - public virtual void StopTimer() - { - m_Timer?.Stop(); + public FlameSpurtTrap(Serial serial) : base(serial) + { + } - m_Timer = null; - } + public virtual void StartTimer() + { + m_Timer ??= Timer.DelayCall(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0), Refresh); + } - public virtual void CheckTimer() - { - Map map = Map; + public virtual void StopTimer() + { + m_Timer?.Stop(); - if (map?.GetSector(GetWorldLocation()).Active == true) - StartTimer(); - else - StopTimer(); - } + m_Timer = null; + } - public override void OnLocationChange(Point3D oldLocation) - { - base.OnLocationChange(oldLocation); + public virtual void CheckTimer() + { + var map = Map; - CheckTimer(); - } + if (map?.GetSector(GetWorldLocation()).Active == true) + StartTimer(); + else + StopTimer(); + } - public override void OnMapChange() - { - base.OnMapChange(); + public override void OnLocationChange(Point3D oldLocation) + { + base.OnLocationChange(oldLocation); - CheckTimer(); - } + CheckTimer(); + } - public override void OnSectorActivate() - { - base.OnSectorActivate(); + public override void OnMapChange() + { + base.OnMapChange(); - StartTimer(); - } + CheckTimer(); + } - public override void OnSectorDeactivate() - { - base.OnSectorDeactivate(); + public override void OnSectorActivate() + { + base.OnSectorActivate(); - StopTimer(); - } + StartTimer(); + } - public override void OnDelete() - { - base.OnDelete(); + public override void OnSectorDeactivate() + { + base.OnSectorDeactivate(); - m_Spurt?.Delete(); - } + StopTimer(); + } - public virtual void Refresh() - { - if (Deleted) - return; + public override void OnDelete() + { + base.OnDelete(); - bool foundPlayer = GetMobilesInRange(3) - .Where(mob => mob.Player && mob.Alive && mob.AccessLevel <= AccessLevel.Player) - .Any(mob => Z + 8 >= mob.Z && mob.Z + 16 > Z); + m_Spurt?.Delete(); + } - if (!foundPlayer) - { - m_Spurt?.Delete(); - m_Spurt = null; - } - else if (m_Spurt?.Deleted != false) - { - m_Spurt = new Static(0x3709); - m_Spurt.MoveToWorld(Location, Map); + public virtual void Refresh() + { + if (Deleted) + return; - Effects.PlaySound(GetWorldLocation(), Map, 0x309); - } - } + var foundPlayer = GetMobilesInRange(3) + .Where(mob => mob.Player && mob.Alive && mob.AccessLevel <= AccessLevel.Player) + .Any(mob => Z + 8 >= mob.Z && mob.Z + 16 > Z); - public override bool OnMoveOver(Mobile m) - { - if (m.AccessLevel > AccessLevel.Player) - return true; + if (!foundPlayer) + { + m_Spurt?.Delete(); + m_Spurt = null; + } + else if (m_Spurt?.Deleted != false) + { + m_Spurt = new Static(0x3709); + m_Spurt.MoveToWorld(Location, Map); - if (!(m.Player && m.Alive)) - return false; + Effects.PlaySound(GetWorldLocation(), Map, 0x309); + } + } - CheckTimer(); + public override bool OnMoveOver(Mobile m) + { + if (m.AccessLevel > AccessLevel.Player) + return true; - SpellHelper.Damage(TimeSpan.FromTicks(1), m, m, Utility.RandomMinMax(1, 30)); - m.PlaySound(m.Female ? 0x327 : 0x437); - - return false; - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - base.OnMovement(m, oldLocation); - - if (m.Location == oldLocation || !m.Player || !m.Alive || m.AccessLevel > AccessLevel.Player - || !CheckRange(m.Location, oldLocation, 1)) - return; - - CheckTimer(); - - SpellHelper.Damage(TimeSpan.FromTicks(1), m, m, Utility.RandomMinMax(1, 10)); - m.PlaySound(m.Female ? 0x327 : 0x437); - - if (m.Body.IsHuman) - m.Animate(20, 1, 1, true, false, 0); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Spurt); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Item item = reader.ReadItem(); - - item?.Delete(); + if (!(m.Player && m.Alive)) + return false; CheckTimer(); - break; - } - } + SpellHelper.Damage(TimeSpan.FromTicks(1), m, m, Utility.RandomMinMax(1, 30)); + m.PlaySound(m.Female ? 0x327 : 0x437); + + return false; + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + base.OnMovement(m, oldLocation); + + if (m.Location == oldLocation || !m.Player || !m.Alive || m.AccessLevel > AccessLevel.Player + || !CheckRange(m.Location, oldLocation, 1)) + return; + + CheckTimer(); + + SpellHelper.Damage(TimeSpan.FromTicks(1), m, m, Utility.RandomMinMax(1, 10)); + m.PlaySound(m.Female ? 0x327 : 0x437); + + if (m.Body.IsHuman) + m.Animate(20, 1, 1, true, false, 0); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Spurt); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + var item = reader.ReadItem(); + + item?.Delete(); + + CheckTimer(); + + break; + } + } + } } - } } diff --git a/Projects/UOContent/Items/Traps/GasTrap.cs b/Projects/UOContent/Items/Traps/GasTrap.cs index 950427a7d..e0a35f741 100644 --- a/Projects/UOContent/Items/Traps/GasTrap.cs +++ b/Projects/UOContent/Items/Traps/GasTrap.cs @@ -3,103 +3,103 @@ using Server.Network; namespace Server.Items { - public enum GasTrapType - { - NorthWall, - WestWall, - Floor - } - - public class GasTrap : BaseTrap - { - [Constructible] - public GasTrap() : this(Poison.Lesser) + public enum GasTrapType { + NorthWall, + WestWall, + Floor } - [Constructible] - public GasTrap(Poison poison) : this(GasTrapType.Floor, poison) + public class GasTrap : BaseTrap { - } - - [Constructible] - public GasTrap(GasTrapType type, Poison poison = null) : base(GetBaseID(type)) => Poison = poison; - - public GasTrap(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public Poison Poison { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public GasTrapType Type - { - get - { - return ItemID switch + [Constructible] + public GasTrap() : this(Poison.Lesser) { - 0x113C => GasTrapType.NorthWall, - 0x1147 => GasTrapType.WestWall, - 0x11A8 => GasTrapType.Floor, - _ => GasTrapType.WestWall - }; - } - set => ItemID = GetBaseID(value); + } + + [Constructible] + public GasTrap(Poison poison) : this(GasTrapType.Floor, poison) + { + } + + [Constructible] + public GasTrap(GasTrapType type, Poison poison = null) : base(GetBaseID(type)) => Poison = poison; + + public GasTrap(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public Poison Poison { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public GasTrapType Type + { + get + { + return ItemID switch + { + 0x113C => GasTrapType.NorthWall, + 0x1147 => GasTrapType.WestWall, + 0x11A8 => GasTrapType.Floor, + _ => GasTrapType.WestWall + }; + } + set => ItemID = GetBaseID(value); + } + + public override bool PassivelyTriggered => false; + public override TimeSpan PassiveTriggerDelay => TimeSpan.Zero; + public override int PassiveTriggerRange => 0; + public override TimeSpan ResetDelay => TimeSpan.FromSeconds(0.0); + + public static int GetBaseID(GasTrapType type) + { + return type switch + { + GasTrapType.NorthWall => 0x113C, + GasTrapType.WestWall => 0x1147, + GasTrapType.Floor => 0x11A8, + _ => 0 + }; + } + + public override void OnTrigger(Mobile from) + { + if (Poison == null || !from.Player || !from.Alive || from.AccessLevel > AccessLevel.Player) + return; + + Effects.SendLocationEffect(Location, Map, GetBaseID(Type) - 2, 16, 3, GetEffectHue(), 0); + Effects.PlaySound(Location, Map, 0x231); + + from.ApplyPoison(from, Poison); + + from.LocalOverheadMessage(MessageType.Regular, 0x22, 500855); // You are enveloped by a noxious gas cloud! + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + Poison.Serialize(Poison, writer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Poison = Poison.Deserialize(reader); + break; + } + } + } } - - public override bool PassivelyTriggered => false; - public override TimeSpan PassiveTriggerDelay => TimeSpan.Zero; - public override int PassiveTriggerRange => 0; - public override TimeSpan ResetDelay => TimeSpan.FromSeconds(0.0); - - public static int GetBaseID(GasTrapType type) - { - return type switch - { - GasTrapType.NorthWall => 0x113C, - GasTrapType.WestWall => 0x1147, - GasTrapType.Floor => 0x11A8, - _ => 0 - }; - } - - public override void OnTrigger(Mobile from) - { - if (Poison == null || !from.Player || !from.Alive || from.AccessLevel > AccessLevel.Player) - return; - - Effects.SendLocationEffect(Location, Map, GetBaseID(Type) - 2, 16, 3, GetEffectHue(), 0); - Effects.PlaySound(Location, Map, 0x231); - - from.ApplyPoison(from, Poison); - - from.LocalOverheadMessage(MessageType.Regular, 0x22, 500855); // You are enveloped by a noxious gas cloud! - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - Poison.Serialize(Poison, writer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Poison = Poison.Deserialize(reader); - break; - } - } - } - } } diff --git a/Projects/UOContent/Items/Traps/GiantSpikeTrap.cs b/Projects/UOContent/Items/Traps/GiantSpikeTrap.cs index e55932121..72f085362 100644 --- a/Projects/UOContent/Items/Traps/GiantSpikeTrap.cs +++ b/Projects/UOContent/Items/Traps/GiantSpikeTrap.cs @@ -3,45 +3,45 @@ using Server.Spells; namespace Server.Items { - public class GiantSpikeTrap : BaseTrap - { - [Constructible] - public GiantSpikeTrap() : base(1) + public class GiantSpikeTrap : BaseTrap { + [Constructible] + public GiantSpikeTrap() : base(1) + { + } + + public GiantSpikeTrap(Serial serial) : base(serial) + { + } + + public override bool PassivelyTriggered => true; + public override TimeSpan PassiveTriggerDelay => TimeSpan.Zero; + public override int PassiveTriggerRange => 3; + public override TimeSpan ResetDelay => TimeSpan.FromSeconds(0.0); + + public override void OnTrigger(Mobile from) + { + if (from.AccessLevel > AccessLevel.Player) + return; + + Effects.SendLocationEffect(Location, Map, 0x1D99, 48, 2, GetEffectHue(), 0); + + if (from.Alive && CheckRange(from.Location, 0)) + SpellHelper.Damage(TimeSpan.FromTicks(1), from, from, Utility.Dice(10, 7, 0)); + } + + 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 GiantSpikeTrap(Serial serial) : base(serial) - { - } - - public override bool PassivelyTriggered => true; - public override TimeSpan PassiveTriggerDelay => TimeSpan.Zero; - public override int PassiveTriggerRange => 3; - public override TimeSpan ResetDelay => TimeSpan.FromSeconds(0.0); - - public override void OnTrigger(Mobile from) - { - if (from.AccessLevel > AccessLevel.Player) - return; - - Effects.SendLocationEffect(Location, Map, 0x1D99, 48, 2, GetEffectHue(), 0); - - if (from.Alive && CheckRange(from.Location, 0)) - SpellHelper.Damage(TimeSpan.FromTicks(1), from, from, Utility.Dice(10, 7, 0)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Traps/MushroomTrap.cs b/Projects/UOContent/Items/Traps/MushroomTrap.cs index f561179c6..228a46c45 100644 --- a/Projects/UOContent/Items/Traps/MushroomTrap.cs +++ b/Projects/UOContent/Items/Traps/MushroomTrap.cs @@ -4,58 +4,58 @@ using Server.Spells; namespace Server.Items { - public class MushroomTrap : BaseTrap - { - [Constructible] - public MushroomTrap() : base(0x1125) + public class MushroomTrap : BaseTrap { + [Constructible] + public MushroomTrap() : base(0x1125) + { + } + + public MushroomTrap(Serial serial) : base(serial) + { + } + + public override bool PassivelyTriggered => true; + public override TimeSpan PassiveTriggerDelay => TimeSpan.Zero; + public override int PassiveTriggerRange => 2; + public override TimeSpan ResetDelay => TimeSpan.Zero; + + public override void OnTrigger(Mobile from) + { + if (!from.Alive || ItemID != 0x1125 || from.AccessLevel > AccessLevel.Player) + return; + + ItemID = 0x1126; + Effects.PlaySound(Location, Map, 0x306); + + SpellHelper.Damage(TimeSpan.FromSeconds(0.5), from, from, Utility.Dice(2, 4, 0)); + + Timer.DelayCall(TimeSpan.FromSeconds(2.0), OnMushroomReset); + } + + public virtual void OnMushroomReset() + { + if (Region.Find(Location, Map).IsPartOf()) + ItemID = 0x1125; // reset + else + Delete(); + } + + 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 (ItemID == 0x1126) + OnMushroomReset(); + } } - - public MushroomTrap(Serial serial) : base(serial) - { - } - - public override bool PassivelyTriggered => true; - public override TimeSpan PassiveTriggerDelay => TimeSpan.Zero; - public override int PassiveTriggerRange => 2; - public override TimeSpan ResetDelay => TimeSpan.Zero; - - public override void OnTrigger(Mobile from) - { - if (!from.Alive || ItemID != 0x1125 || from.AccessLevel > AccessLevel.Player) - return; - - ItemID = 0x1126; - Effects.PlaySound(Location, Map, 0x306); - - SpellHelper.Damage(TimeSpan.FromSeconds(0.5), from, from, Utility.Dice(2, 4, 0)); - - Timer.DelayCall(TimeSpan.FromSeconds(2.0), OnMushroomReset); - } - - public virtual void OnMushroomReset() - { - if (Region.Find(Location, Map).IsPartOf()) - ItemID = 0x1125; // reset - else - Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (ItemID == 0x1126) - OnMushroomReset(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Traps/SawTrap.cs b/Projects/UOContent/Items/Traps/SawTrap.cs index 90b378e78..0a4f78c03 100644 --- a/Projects/UOContent/Items/Traps/SawTrap.cs +++ b/Projects/UOContent/Items/Traps/SawTrap.cs @@ -4,84 +4,84 @@ using Server.Spells; namespace Server.Items { - public enum SawTrapType - { - WestWall, - NorthWall, - WestFloor, - NorthFloor - } - - public class SawTrap : BaseTrap - { - [Constructible] - public SawTrap(SawTrapType type = SawTrapType.NorthFloor) : base(GetBaseID(type)) + public enum SawTrapType { + WestWall, + NorthWall, + WestFloor, + NorthFloor } - public SawTrap(Serial serial) : base(serial) + public class SawTrap : BaseTrap { - } - - [CommandProperty(AccessLevel.GameMaster)] - public SawTrapType Type - { - get - { - return ItemID switch + [Constructible] + public SawTrap(SawTrapType type = SawTrapType.NorthFloor) : base(GetBaseID(type)) { - 0x1103 => SawTrapType.NorthWall, - 0x1116 => SawTrapType.WestWall, - 0x11AC => SawTrapType.NorthFloor, - 0x11B1 => SawTrapType.WestFloor, - _ => SawTrapType.NorthWall - }; - } - set => ItemID = GetBaseID(value); + } + + public SawTrap(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public SawTrapType Type + { + get + { + return ItemID switch + { + 0x1103 => SawTrapType.NorthWall, + 0x1116 => SawTrapType.WestWall, + 0x11AC => SawTrapType.NorthFloor, + 0x11B1 => SawTrapType.WestFloor, + _ => SawTrapType.NorthWall + }; + } + set => ItemID = GetBaseID(value); + } + + public override bool PassivelyTriggered => false; + public override TimeSpan PassiveTriggerDelay => TimeSpan.Zero; + public override int PassiveTriggerRange => 0; + public override TimeSpan ResetDelay => TimeSpan.FromSeconds(0.0); + + public static int GetBaseID(SawTrapType type) + { + return type switch + { + SawTrapType.NorthWall => 0x1103, + SawTrapType.WestWall => 0x1116, + SawTrapType.NorthFloor => 0x11AC, + SawTrapType.WestFloor => 0x11B1, + _ => 0 + }; + } + + public override void OnTrigger(Mobile from) + { + if (!from.Alive || from.AccessLevel > AccessLevel.Player) + return; + + Effects.SendLocationEffect(Location, Map, GetBaseID(Type) + 1, 6, 3, GetEffectHue(), 0); + Effects.PlaySound(Location, Map, 0x21C); + + SpellHelper.Damage(TimeSpan.FromTicks(1), from, from, Utility.RandomMinMax(5, 15)); + + from.LocalOverheadMessage(MessageType.Regular, 0x22, 500853); // You stepped onto a blade trap! + } + + 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 PassivelyTriggered => false; - public override TimeSpan PassiveTriggerDelay => TimeSpan.Zero; - public override int PassiveTriggerRange => 0; - public override TimeSpan ResetDelay => TimeSpan.FromSeconds(0.0); - - public static int GetBaseID(SawTrapType type) - { - return type switch - { - SawTrapType.NorthWall => 0x1103, - SawTrapType.WestWall => 0x1116, - SawTrapType.NorthFloor => 0x11AC, - SawTrapType.WestFloor => 0x11B1, - _ => 0 - }; - } - - public override void OnTrigger(Mobile from) - { - if (!from.Alive || from.AccessLevel > AccessLevel.Player) - return; - - Effects.SendLocationEffect(Location, Map, GetBaseID(Type) + 1, 6, 3, GetEffectHue(), 0); - Effects.PlaySound(Location, Map, 0x21C); - - SpellHelper.Damage(TimeSpan.FromTicks(1), from, from, Utility.RandomMinMax(5, 15)); - - from.LocalOverheadMessage(MessageType.Regular, 0x22, 500853); // You stepped onto a blade trap! - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Traps/SpikeTrap.cs b/Projects/UOContent/Items/Traps/SpikeTrap.cs index 629cfab48..37ef1add1 100644 --- a/Projects/UOContent/Items/Traps/SpikeTrap.cs +++ b/Projects/UOContent/Items/Traps/SpikeTrap.cs @@ -4,141 +4,141 @@ using Server.Spells; namespace Server.Items { - public enum SpikeTrapType - { - WestWall, - NorthWall, - WestFloor, - NorthFloor - } - - public class SpikeTrap : BaseTrap - { - [Constructible] - public SpikeTrap(SpikeTrapType type = SpikeTrapType.WestFloor) : base(GetBaseID(type)) + public enum SpikeTrapType { + WestWall, + NorthWall, + WestFloor, + NorthFloor } - public SpikeTrap(Serial serial) : base(serial) + public class SpikeTrap : BaseTrap { - } - - [CommandProperty(AccessLevel.GameMaster)] - public SpikeTrapType Type - { - get - { - return ItemID switch + [Constructible] + public SpikeTrap(SpikeTrapType type = SpikeTrapType.WestFloor) : base(GetBaseID(type)) { - 4360 => SpikeTrapType.WestWall, - 4361 => SpikeTrapType.WestWall, - 4366 => SpikeTrapType.WestWall, - 4379 => SpikeTrapType.NorthWall, - 4380 => SpikeTrapType.NorthWall, - 4385 => SpikeTrapType.NorthWall, - 4506 => SpikeTrapType.WestFloor, - 4507 => SpikeTrapType.WestFloor, - 4511 => SpikeTrapType.WestFloor, - 4512 => SpikeTrapType.NorthFloor, - 4513 => SpikeTrapType.NorthFloor, - 4517 => SpikeTrapType.NorthFloor, - _ => SpikeTrapType.WestWall - }; - } - set - { - bool extended = Extended; + } - ItemID = extended ? GetExtendedID(value) : GetBaseID(value); - } + public SpikeTrap(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public SpikeTrapType Type + { + get + { + return ItemID switch + { + 4360 => SpikeTrapType.WestWall, + 4361 => SpikeTrapType.WestWall, + 4366 => SpikeTrapType.WestWall, + 4379 => SpikeTrapType.NorthWall, + 4380 => SpikeTrapType.NorthWall, + 4385 => SpikeTrapType.NorthWall, + 4506 => SpikeTrapType.WestFloor, + 4507 => SpikeTrapType.WestFloor, + 4511 => SpikeTrapType.WestFloor, + 4512 => SpikeTrapType.NorthFloor, + 4513 => SpikeTrapType.NorthFloor, + 4517 => SpikeTrapType.NorthFloor, + _ => SpikeTrapType.WestWall + }; + } + set + { + var extended = Extended; + + ItemID = extended ? GetExtendedID(value) : GetBaseID(value); + } + } + + public bool Extended + { + get => ItemID == GetExtendedID(Type); + set + { + if (value) + ItemID = GetExtendedID(Type); + else + ItemID = GetBaseID(Type); + } + } + + public override bool PassivelyTriggered => false; + public override TimeSpan PassiveTriggerDelay => TimeSpan.Zero; + public override int PassiveTriggerRange => 0; + public override TimeSpan ResetDelay => TimeSpan.FromSeconds(6.0); + + public static int GetBaseID(SpikeTrapType type) + { + return type switch + { + SpikeTrapType.WestWall => 4360, + SpikeTrapType.NorthWall => 4379, + SpikeTrapType.WestFloor => 4506, + SpikeTrapType.NorthFloor => 4512, + _ => 0 + }; + } + + public static int GetExtendedID(SpikeTrapType type) => GetBaseID(type) + GetExtendedOffset(type); + + public static int GetExtendedOffset(SpikeTrapType type) + { + return type switch + { + SpikeTrapType.WestWall => 6, + SpikeTrapType.NorthWall => 6, + SpikeTrapType.WestFloor => 5, + SpikeTrapType.NorthFloor => 5, + _ => 0 + }; + } + + public override void OnTrigger(Mobile from) + { + if (!from.Alive || from.AccessLevel > AccessLevel.Player) + return; + + Effects.SendLocationEffect(Location, Map, GetBaseID(Type) + 1, 18, 3, GetEffectHue(), 0); + Effects.PlaySound(Location, Map, 0x22C); + + foreach (var mob in GetMobilesInRange(0)) + if (mob.Alive && !mob.IsDeadBondedPet) + SpellHelper.Damage(TimeSpan.FromTicks(1), mob, mob, Utility.RandomMinMax(1, 6) * 6); + + Timer.DelayCall(TimeSpan.FromSeconds(1.0), OnSpikeExtended); + + from.LocalOverheadMessage(MessageType.Regular, 0x22, 500852); // You stepped onto a spike trap! + } + + public virtual void OnSpikeExtended() + { + Extended = true; + Timer.DelayCall(TimeSpan.FromSeconds(5.0), OnSpikeRetracted); + } + + public virtual void OnSpikeRetracted() + { + Extended = false; + Effects.SendLocationEffect(Location, Map, GetExtendedID(Type) - 1, 6, 3, GetEffectHue(), 0); + } + + 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(); + + Extended = false; + } } - - public bool Extended - { - get => ItemID == GetExtendedID(Type); - set - { - if (value) - ItemID = GetExtendedID(Type); - else - ItemID = GetBaseID(Type); - } - } - - public override bool PassivelyTriggered => false; - public override TimeSpan PassiveTriggerDelay => TimeSpan.Zero; - public override int PassiveTriggerRange => 0; - public override TimeSpan ResetDelay => TimeSpan.FromSeconds(6.0); - - public static int GetBaseID(SpikeTrapType type) - { - return type switch - { - SpikeTrapType.WestWall => 4360, - SpikeTrapType.NorthWall => 4379, - SpikeTrapType.WestFloor => 4506, - SpikeTrapType.NorthFloor => 4512, - _ => 0 - }; - } - - public static int GetExtendedID(SpikeTrapType type) => GetBaseID(type) + GetExtendedOffset(type); - - public static int GetExtendedOffset(SpikeTrapType type) - { - return type switch - { - SpikeTrapType.WestWall => 6, - SpikeTrapType.NorthWall => 6, - SpikeTrapType.WestFloor => 5, - SpikeTrapType.NorthFloor => 5, - _ => 0 - }; - } - - public override void OnTrigger(Mobile from) - { - if (!from.Alive || from.AccessLevel > AccessLevel.Player) - return; - - Effects.SendLocationEffect(Location, Map, GetBaseID(Type) + 1, 18, 3, GetEffectHue(), 0); - Effects.PlaySound(Location, Map, 0x22C); - - foreach (Mobile mob in GetMobilesInRange(0)) - if (mob.Alive && !mob.IsDeadBondedPet) - SpellHelper.Damage(TimeSpan.FromTicks(1), mob, mob, Utility.RandomMinMax(1, 6) * 6); - - Timer.DelayCall(TimeSpan.FromSeconds(1.0), OnSpikeExtended); - - from.LocalOverheadMessage(MessageType.Regular, 0x22, 500852); // You stepped onto a spike trap! - } - - public virtual void OnSpikeExtended() - { - Extended = true; - Timer.DelayCall(TimeSpan.FromSeconds(5.0), OnSpikeRetracted); - } - - public virtual void OnSpikeRetracted() - { - Extended = false; - Effects.SendLocationEffect(Location, Map, GetExtendedID(Type) - 1, 6, 3, GetEffectHue(), 0); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Extended = false; - } - } } diff --git a/Projects/UOContent/Items/Traps/StoneFaceTrap.cs b/Projects/UOContent/Items/Traps/StoneFaceTrap.cs index e638974e3..acdbd808e 100644 --- a/Projects/UOContent/Items/Traps/StoneFaceTrap.cs +++ b/Projects/UOContent/Items/Traps/StoneFaceTrap.cs @@ -3,158 +3,158 @@ using Server.Spells; namespace Server.Items { - public enum StoneFaceTrapType - { - NorthWestWall, - NorthWall, - WestWall - } - - public class StoneFaceTrap : BaseTrap - { - [Constructible] - public StoneFaceTrap() : base(0x10FC) => Light = LightType.Circle225; - - public StoneFaceTrap(Serial serial) : base(serial) + public enum StoneFaceTrapType { + NorthWestWall, + NorthWall, + WestWall } - [CommandProperty(AccessLevel.GameMaster)] - public StoneFaceTrapType Type + public class StoneFaceTrap : BaseTrap { - get - { - return ItemID switch + [Constructible] + public StoneFaceTrap() : base(0x10FC) => Light = LightType.Circle225; + + public StoneFaceTrap(Serial serial) : base(serial) { - 0x10F5 => StoneFaceTrapType.NorthWestWall, - 0x10F6 => StoneFaceTrapType.NorthWestWall, - 0x10F7 => StoneFaceTrapType.NorthWestWall, - 0x10FC => StoneFaceTrapType.NorthWall, - 0x10FD => StoneFaceTrapType.NorthWall, - 0x10FE => StoneFaceTrapType.NorthWall, - 0x110F => StoneFaceTrapType.WestWall, - 0x1110 => StoneFaceTrapType.WestWall, - 0x1111 => StoneFaceTrapType.WestWall, - _ => StoneFaceTrapType.NorthWestWall - }; - } - set - { - bool breathing = Breathing; + } - ItemID = breathing ? GetFireID(value) : GetBaseID(value); - } + [CommandProperty(AccessLevel.GameMaster)] + public StoneFaceTrapType Type + { + get + { + return ItemID switch + { + 0x10F5 => StoneFaceTrapType.NorthWestWall, + 0x10F6 => StoneFaceTrapType.NorthWestWall, + 0x10F7 => StoneFaceTrapType.NorthWestWall, + 0x10FC => StoneFaceTrapType.NorthWall, + 0x10FD => StoneFaceTrapType.NorthWall, + 0x10FE => StoneFaceTrapType.NorthWall, + 0x110F => StoneFaceTrapType.WestWall, + 0x1110 => StoneFaceTrapType.WestWall, + 0x1111 => StoneFaceTrapType.WestWall, + _ => StoneFaceTrapType.NorthWestWall + }; + } + set + { + var breathing = Breathing; + + ItemID = breathing ? GetFireID(value) : GetBaseID(value); + } + } + + public bool Breathing + { + get => ItemID == GetFireID(Type); + set + { + if (value) + ItemID = GetFireID(Type); + else + ItemID = GetBaseID(Type); + } + } + + public override bool PassivelyTriggered => true; + public override TimeSpan PassiveTriggerDelay => TimeSpan.Zero; + public override int PassiveTriggerRange => 2; + public override TimeSpan ResetDelay => TimeSpan.Zero; + + public static int GetBaseID(StoneFaceTrapType type) + { + return type switch + { + StoneFaceTrapType.NorthWestWall => 0x10F5, + StoneFaceTrapType.NorthWall => 0x10FC, + StoneFaceTrapType.WestWall => 0x110F, + _ => 0 + }; + } + + public static int GetFireID(StoneFaceTrapType type) + { + return type switch + { + StoneFaceTrapType.NorthWestWall => 0x10F7, + StoneFaceTrapType.NorthWall => 0x10FE, + StoneFaceTrapType.WestWall => 0x1111, + _ => 0 + }; + } + + public override void OnTrigger(Mobile from) + { + if (!from.Alive || from.AccessLevel > AccessLevel.Player) + return; + + Effects.PlaySound(Location, Map, 0x359); + + Breathing = true; + + Timer.DelayCall(TimeSpan.FromSeconds(2.0), FinishBreath); + Timer.DelayCall(TimeSpan.FromSeconds(1.0), TriggerDamage); + } + + public virtual void FinishBreath() + { + Breathing = false; + } + + public virtual void TriggerDamage() + { + foreach (var mob in GetMobilesInRange(1)) + if (mob.Alive && !mob.IsDeadBondedPet && mob.AccessLevel == AccessLevel.Player) + SpellHelper.Damage(TimeSpan.FromTicks(1), mob, mob, Utility.Dice(3, 15, 0)); + } + + 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(); + + Breathing = false; + } } - public bool Breathing + public class StoneFaceTrapNoDamage : StoneFaceTrap { - get => ItemID == GetFireID(Type); - set - { - if (value) - ItemID = GetFireID(Type); - else - ItemID = GetBaseID(Type); - } + [Constructible] + public StoneFaceTrapNoDamage() + { + } + + public StoneFaceTrapNoDamage(Serial serial) : base(serial) + { + } + + public override void TriggerDamage() + { + // nothing.. + } + + 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 PassivelyTriggered => true; - public override TimeSpan PassiveTriggerDelay => TimeSpan.Zero; - public override int PassiveTriggerRange => 2; - public override TimeSpan ResetDelay => TimeSpan.Zero; - - public static int GetBaseID(StoneFaceTrapType type) - { - return type switch - { - StoneFaceTrapType.NorthWestWall => 0x10F5, - StoneFaceTrapType.NorthWall => 0x10FC, - StoneFaceTrapType.WestWall => 0x110F, - _ => 0 - }; - } - - public static int GetFireID(StoneFaceTrapType type) - { - return type switch - { - StoneFaceTrapType.NorthWestWall => 0x10F7, - StoneFaceTrapType.NorthWall => 0x10FE, - StoneFaceTrapType.WestWall => 0x1111, - _ => 0 - }; - } - - public override void OnTrigger(Mobile from) - { - if (!from.Alive || from.AccessLevel > AccessLevel.Player) - return; - - Effects.PlaySound(Location, Map, 0x359); - - Breathing = true; - - Timer.DelayCall(TimeSpan.FromSeconds(2.0), FinishBreath); - Timer.DelayCall(TimeSpan.FromSeconds(1.0), TriggerDamage); - } - - public virtual void FinishBreath() - { - Breathing = false; - } - - public virtual void TriggerDamage() - { - foreach (Mobile mob in GetMobilesInRange(1)) - if (mob.Alive && !mob.IsDeadBondedPet && mob.AccessLevel == AccessLevel.Player) - SpellHelper.Damage(TimeSpan.FromTicks(1), mob, mob, Utility.Dice(3, 15, 0)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Breathing = false; - } - } - - public class StoneFaceTrapNoDamage : StoneFaceTrap - { - [Constructible] - public StoneFaceTrapNoDamage() - { - } - - public StoneFaceTrapNoDamage(Serial serial) : base(serial) - { - } - - public override void TriggerDamage() - { - // nothing.. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/TreasureChests/TreasureChestLevel1.cs b/Projects/UOContent/Items/TreasureChests/TreasureChestLevel1.cs index bd89489ef..aad769f5a 100644 --- a/Projects/UOContent/Items/TreasureChests/TreasureChestLevel1.cs +++ b/Projects/UOContent/Items/TreasureChests/TreasureChestLevel1.cs @@ -2,115 +2,115 @@ using System; namespace Server.Items { - public class TreasureChestLevel1 : LockableContainer - { - private const int m_Level = 1; - - [Constructible] - public TreasureChestLevel1() - : base(0xE41) + public class TreasureChestLevel1 : LockableContainer { - SetChestAppearance(); - Movable = false; + private const int m_Level = 1; - TrapType = TrapType.DartTrap; - TrapPower = m_Level * Utility.Random(1, 25); - Locked = true; + [Constructible] + public TreasureChestLevel1() + : base(0xE41) + { + SetChestAppearance(); + Movable = false; - RequiredSkill = 57; - LockLevel = RequiredSkill - Utility.Random(1, 10); - MaxLockLevel = RequiredSkill + Utility.Random(1, 10); + TrapType = TrapType.DartTrap; + TrapPower = m_Level * Utility.Random(1, 25); + Locked = true; - // According to OSI, loot in level 1 chest is: - // Gold 25 - 50 - // Bolts 10 - // Gems - // Normal weapon - // Normal armour - // Normal clothing - // Normal jewelry + RequiredSkill = 57; + LockLevel = RequiredSkill - Utility.Random(1, 10); + MaxLockLevel = RequiredSkill + Utility.Random(1, 10); - // Gold - DropItem(new Gold(Utility.Random(30, 100))); + // According to OSI, loot in level 1 chest is: + // Gold 25 - 50 + // Bolts 10 + // Gems + // Normal weapon + // Normal armour + // Normal clothing + // Normal jewelry - // Drop bolts - // DropItem( new Bolt( 10 ) ); + // Gold + DropItem(new Gold(Utility.Random(30, 100))); - // Gems - if (Utility.RandomBool()) - { - Item GemLoot = Loot.RandomGem(); - GemLoot.Amount = Utility.Random(1, 3); - DropItem(GemLoot); - } + // Drop bolts + // DropItem( new Bolt( 10 ) ); - // Weapon - if (Utility.RandomBool()) - DropItem(Loot.RandomWeapon()); + // Gems + if (Utility.RandomBool()) + { + var GemLoot = Loot.RandomGem(); + GemLoot.Amount = Utility.Random(1, 3); + DropItem(GemLoot); + } - // Armour - if (Utility.RandomBool()) - DropItem(Loot.RandomArmorOrShield()); + // Weapon + if (Utility.RandomBool()) + DropItem(Loot.RandomWeapon()); - // Clothing - if (Utility.RandomBool()) - DropItem(Loot.RandomClothing()); + // Armour + if (Utility.RandomBool()) + DropItem(Loot.RandomArmorOrShield()); - // Jewelry - if (Utility.RandomBool()) - DropItem(Loot.RandomJewelry()); + // Clothing + if (Utility.RandomBool()) + DropItem(Loot.RandomClothing()); + + // Jewelry + if (Utility.RandomBool()) + DropItem(Loot.RandomJewelry()); + } + + public TreasureChestLevel1(Serial serial) + : base(serial) + { + } + + public override bool Decays => true; + + public override bool IsDecoContainer => false; + + public override TimeSpan DecayTime => TimeSpan.FromMinutes(Utility.Random(15, 60)); + + public override int DefaultGumpID => 0x42; + + public override int DefaultDropSound => 0x42; + + public override Rectangle2D Bounds => new Rectangle2D(18, 105, 144, 73); + + private void SetChestAppearance() + { + var UseFirstItemId = Utility.RandomBool(); + + switch (Utility.RandomList(0, 1, 2)) + { + case 0: // Large Crate + ItemID = UseFirstItemId ? 0xe3c : 0xe3d; + GumpID = 0x44; + break; + + case 1: // Medium Crate + ItemID = UseFirstItemId ? 0xe3e : 0xe3f; + GumpID = 0x44; + break; + + case 2: // Small Crate + ItemID = UseFirstItemId ? 0x9a9 : 0xe7e; + GumpID = 0x44; + break; + } + } + + 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(); + } } - - public TreasureChestLevel1(Serial serial) - : base(serial) - { - } - - public override bool Decays => true; - - public override bool IsDecoContainer => false; - - public override TimeSpan DecayTime => TimeSpan.FromMinutes(Utility.Random(15, 60)); - - public override int DefaultGumpID => 0x42; - - public override int DefaultDropSound => 0x42; - - public override Rectangle2D Bounds => new Rectangle2D(18, 105, 144, 73); - - private void SetChestAppearance() - { - bool UseFirstItemId = Utility.RandomBool(); - - switch (Utility.RandomList(0, 1, 2)) - { - case 0: // Large Crate - ItemID = UseFirstItemId ? 0xe3c : 0xe3d; - GumpID = 0x44; - break; - - case 1: // Medium Crate - ItemID = UseFirstItemId ? 0xe3e : 0xe3f; - GumpID = 0x44; - break; - - case 2: // Small Crate - ItemID = UseFirstItemId ? 0x9a9 : 0xe7e; - GumpID = 0x44; - break; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/TreasureChests/TreasureChestLevel2.cs b/Projects/UOContent/Items/TreasureChests/TreasureChestLevel2.cs index b828e2085..6d887f64a 100644 --- a/Projects/UOContent/Items/TreasureChests/TreasureChestLevel2.cs +++ b/Projects/UOContent/Items/TreasureChests/TreasureChestLevel2.cs @@ -2,146 +2,146 @@ using System; namespace Server.Items { - public class TreasureChestLevel2 : LockableContainer - { - private const int m_Level = 2; - - [Constructible] - public TreasureChestLevel2() - : base(0xE41) + public class TreasureChestLevel2 : LockableContainer { - SetChestAppearance(); - Movable = false; + private const int m_Level = 2; - TrapType = TrapType.ExplosionTrap; - TrapPower = m_Level * Utility.Random(1, 25); - Locked = true; + [Constructible] + public TreasureChestLevel2() + : base(0xE41) + { + SetChestAppearance(); + Movable = false; - RequiredSkill = 72; - LockLevel = RequiredSkill - Utility.Random(1, 10); - MaxLockLevel = RequiredSkill + Utility.Random(1, 10); + TrapType = TrapType.ExplosionTrap; + TrapPower = m_Level * Utility.Random(1, 25); + Locked = true; - // According to OSI, loot in level 2 chest is: - // Gold 80 - 150 - // Arrows 10 - // Reagents - // Scrolls - // Potions - // Gems + RequiredSkill = 72; + LockLevel = RequiredSkill - Utility.Random(1, 10); + MaxLockLevel = RequiredSkill + Utility.Random(1, 10); - // Gold - DropItem(new Gold(Utility.Random(70, 100))); + // According to OSI, loot in level 2 chest is: + // Gold 80 - 150 + // Arrows 10 + // Reagents + // Scrolls + // Potions + // Gems - // Drop bolts - // DropItem( new Arrow( 10 ) ); + // Gold + DropItem(new Gold(Utility.Random(70, 100))); - // Reagents - for (int i = Utility.Random(1, m_Level); i > 1; i--) - { - Item ReagentLoot = Loot.RandomReagent(); - ReagentLoot.Amount = Utility.Random(1, m_Level); - DropItem(ReagentLoot); - } + // Drop bolts + // DropItem( new Arrow( 10 ) ); - // Scrolls - for (int i = Utility.Random(1, m_Level); i > 1; i--) - { - Item ScrollLoot = Loot.RandomScroll(0, 39, SpellbookType.Regular); - ScrollLoot.Amount = Utility.Random(1, 8); - DropItem(ScrollLoot); - } + // Reagents + for (var i = Utility.Random(1, m_Level); i > 1; i--) + { + var ReagentLoot = Loot.RandomReagent(); + ReagentLoot.Amount = Utility.Random(1, m_Level); + DropItem(ReagentLoot); + } - // Potions - for (int i = Utility.Random(1, m_Level); i > 1; i--) - { - Item PotionLoot = Loot.RandomPotion(); - DropItem(PotionLoot); - } + // Scrolls + for (var i = Utility.Random(1, m_Level); i > 1; i--) + { + Item ScrollLoot = Loot.RandomScroll(0, 39, SpellbookType.Regular); + ScrollLoot.Amount = Utility.Random(1, 8); + DropItem(ScrollLoot); + } - // Gems - for (int i = Utility.Random(1, m_Level); i > 1; i--) - { - Item GemLoot = Loot.RandomGem(); - GemLoot.Amount = Utility.Random(1, 6); - DropItem(GemLoot); - } + // Potions + for (var i = Utility.Random(1, m_Level); i > 1; i--) + { + var PotionLoot = Loot.RandomPotion(); + DropItem(PotionLoot); + } + + // Gems + for (var i = Utility.Random(1, m_Level); i > 1; i--) + { + var GemLoot = Loot.RandomGem(); + GemLoot.Amount = Utility.Random(1, 6); + DropItem(GemLoot); + } + } + + public TreasureChestLevel2(Serial serial) + : base(serial) + { + } + + public override bool Decays => true; + + public override bool IsDecoContainer => false; + + public override TimeSpan DecayTime => TimeSpan.FromMinutes(Utility.Random(15, 60)); + + public override int DefaultGumpID => 0x42; + + public override int DefaultDropSound => 0x42; + + public override Rectangle2D Bounds => new Rectangle2D(18, 105, 144, 73); + + private void SetChestAppearance() + { + var UseFirstItemId = Utility.RandomBool(); + + switch (Utility.RandomList(0, 1, 2, 3, 4, 5, 6, 7)) + { + case 0: // Large Crate + ItemID = UseFirstItemId ? 0xe3c : 0xe3d; + GumpID = 0x44; + break; + + case 1: // Medium Crate + ItemID = UseFirstItemId ? 0xe3e : 0xe3f; + GumpID = 0x44; + break; + + case 2: // Small Crate + ItemID = UseFirstItemId ? 0x9a9 : 0xe7e; + GumpID = 0x44; + break; + + case 3: // Wooden Chest + ItemID = UseFirstItemId ? 0xe42 : 0xe43; + GumpID = 0x49; + break; + + case 4: // Metal Chest + ItemID = UseFirstItemId ? 0x9ab : 0xe7c; + GumpID = 0x4A; + break; + + case 5: // Metal Golden Chest + ItemID = UseFirstItemId ? 0xe40 : 0xe41; + GumpID = 0x42; + break; + + case 6: // Keg + ItemID = 0xe7f; + GumpID = 0x3e; + break; + + case 7: // Barrel + ItemID = 0xe77; + GumpID = 0x3e; + break; + } + } + + 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(); + } } - - public TreasureChestLevel2(Serial serial) - : base(serial) - { - } - - public override bool Decays => true; - - public override bool IsDecoContainer => false; - - public override TimeSpan DecayTime => TimeSpan.FromMinutes(Utility.Random(15, 60)); - - public override int DefaultGumpID => 0x42; - - public override int DefaultDropSound => 0x42; - - public override Rectangle2D Bounds => new Rectangle2D(18, 105, 144, 73); - - private void SetChestAppearance() - { - bool UseFirstItemId = Utility.RandomBool(); - - switch (Utility.RandomList(0, 1, 2, 3, 4, 5, 6, 7)) - { - case 0: // Large Crate - ItemID = UseFirstItemId ? 0xe3c : 0xe3d; - GumpID = 0x44; - break; - - case 1: // Medium Crate - ItemID = UseFirstItemId ? 0xe3e : 0xe3f; - GumpID = 0x44; - break; - - case 2: // Small Crate - ItemID = UseFirstItemId ? 0x9a9 : 0xe7e; - GumpID = 0x44; - break; - - case 3: // Wooden Chest - ItemID = UseFirstItemId ? 0xe42 : 0xe43; - GumpID = 0x49; - break; - - case 4: // Metal Chest - ItemID = UseFirstItemId ? 0x9ab : 0xe7c; - GumpID = 0x4A; - break; - - case 5: // Metal Golden Chest - ItemID = UseFirstItemId ? 0xe40 : 0xe41; - GumpID = 0x42; - break; - - case 6: // Keg - ItemID = 0xe7f; - GumpID = 0x3e; - break; - - case 7: // Barrel - ItemID = 0xe77; - GumpID = 0x3e; - break; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/TreasureChests/TreasureChestLevel3.cs b/Projects/UOContent/Items/TreasureChests/TreasureChestLevel3.cs index 497d5286a..9cc656a05 100644 --- a/Projects/UOContent/Items/TreasureChests/TreasureChestLevel3.cs +++ b/Projects/UOContent/Items/TreasureChests/TreasureChestLevel3.cs @@ -2,159 +2,159 @@ using System; namespace Server.Items { - public class TreasureChestLevel3 : LockableContainer - { - private const int m_Level = 3; - - [Constructible] - public TreasureChestLevel3() - : base(0xE41) + public class TreasureChestLevel3 : LockableContainer { - SetChestAppearance(); - Movable = false; + private const int m_Level = 3; - TrapType = TrapType.PoisonTrap; - TrapPower = m_Level * Utility.Random(1, 25); - Locked = true; - - RequiredSkill = 84; - LockLevel = RequiredSkill - Utility.Random(1, 10); - MaxLockLevel = RequiredSkill + Utility.Random(1, 10); - - // According to OSI, loot in level 3 chest is: - // Gold 250 - 350 - // Arrows 10 - // Reagents - // Scrolls - // Potions - // Gems - // Magic Wand - // Magic weapon - // Magic armour - // Magic clothing (not implemented) - // Magic jewelry (not implemented) - - // Gold - DropItem(new Gold(Utility.Random(180, 240))); - - // Drop bolts - // DropItem( new Arrow( 10 ) ); - - // Reagents - for (int i = Utility.Random(1, m_Level); i > 1; i--) - { - Item ReagentLoot = Loot.RandomReagent(); - ReagentLoot.Amount = Utility.Random(1, 9); - DropItem(ReagentLoot); - } - - // Scrolls - for (int i = Utility.Random(1, m_Level); i > 1; i--) - { - Item ScrollLoot = Loot.RandomScroll(0, 47, SpellbookType.Regular); - ScrollLoot.Amount = Utility.Random(1, 12); - DropItem(ScrollLoot); - } - - // Potions - for (int i = Utility.Random(1, m_Level); i > 1; i--) - { - Item PotionLoot = Loot.RandomPotion(); - DropItem(PotionLoot); - } - - // Gems - for (int i = Utility.Random(1, m_Level); i > 1; i--) - { - Item GemLoot = Loot.RandomGem(); - GemLoot.Amount = Utility.Random(1, 9); - DropItem(GemLoot); - } - - // Magic Wand - for (int i = Utility.Random(1, m_Level); i > 1; i--) - DropItem(Loot.RandomWand()); - - // Equipment - for (int i = Utility.Random(1, m_Level); i > 1; i--) - { - Item item = Loot.RandomArmorOrShieldOrWeapon(); - - if (item is BaseWeapon weapon) + [Constructible] + public TreasureChestLevel3() + : base(0xE41) { - weapon.DamageLevel = (WeaponDamageLevel)Utility.Random(m_Level); - weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random(m_Level); - weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random(m_Level); - weapon.Quality = WeaponQuality.Regular; - } - else if (item is BaseArmor armor) - { - armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(m_Level); - armor.Durability = (ArmorDurabilityLevel)Utility.Random(m_Level); - armor.Quality = ArmorQuality.Regular; + SetChestAppearance(); + Movable = false; + + TrapType = TrapType.PoisonTrap; + TrapPower = m_Level * Utility.Random(1, 25); + Locked = true; + + RequiredSkill = 84; + LockLevel = RequiredSkill - Utility.Random(1, 10); + MaxLockLevel = RequiredSkill + Utility.Random(1, 10); + + // According to OSI, loot in level 3 chest is: + // Gold 250 - 350 + // Arrows 10 + // Reagents + // Scrolls + // Potions + // Gems + // Magic Wand + // Magic weapon + // Magic armour + // Magic clothing (not implemented) + // Magic jewelry (not implemented) + + // Gold + DropItem(new Gold(Utility.Random(180, 240))); + + // Drop bolts + // DropItem( new Arrow( 10 ) ); + + // Reagents + for (var i = Utility.Random(1, m_Level); i > 1; i--) + { + var ReagentLoot = Loot.RandomReagent(); + ReagentLoot.Amount = Utility.Random(1, 9); + DropItem(ReagentLoot); + } + + // Scrolls + for (var i = Utility.Random(1, m_Level); i > 1; i--) + { + Item ScrollLoot = Loot.RandomScroll(0, 47, SpellbookType.Regular); + ScrollLoot.Amount = Utility.Random(1, 12); + DropItem(ScrollLoot); + } + + // Potions + for (var i = Utility.Random(1, m_Level); i > 1; i--) + { + var PotionLoot = Loot.RandomPotion(); + DropItem(PotionLoot); + } + + // Gems + for (var i = Utility.Random(1, m_Level); i > 1; i--) + { + var GemLoot = Loot.RandomGem(); + GemLoot.Amount = Utility.Random(1, 9); + DropItem(GemLoot); + } + + // Magic Wand + for (var i = Utility.Random(1, m_Level); i > 1; i--) + DropItem(Loot.RandomWand()); + + // Equipment + for (var i = Utility.Random(1, m_Level); i > 1; i--) + { + var item = Loot.RandomArmorOrShieldOrWeapon(); + + if (item is BaseWeapon weapon) + { + weapon.DamageLevel = (WeaponDamageLevel)Utility.Random(m_Level); + weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random(m_Level); + weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random(m_Level); + weapon.Quality = WeaponQuality.Regular; + } + else if (item is BaseArmor armor) + { + armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(m_Level); + armor.Durability = (ArmorDurabilityLevel)Utility.Random(m_Level); + armor.Quality = ArmorQuality.Regular; + } + + DropItem(item); + } + + // Clothing + for (var i = Utility.Random(1, 2); i > 1; i--) + DropItem(Loot.RandomClothing()); + + // Jewelry + for (var i = Utility.Random(1, 2); i > 1; i--) + DropItem(Loot.RandomJewelry()); } - DropItem(item); - } + public TreasureChestLevel3(Serial serial) + : base(serial) + { + } - // Clothing - for (int i = Utility.Random(1, 2); i > 1; i--) - DropItem(Loot.RandomClothing()); + public override bool Decays => true; - // Jewelry - for (int i = Utility.Random(1, 2); i > 1; i--) - DropItem(Loot.RandomJewelry()); + public override bool IsDecoContainer => false; + + public override TimeSpan DecayTime => TimeSpan.FromMinutes(Utility.Random(15, 60)); + + public override int DefaultGumpID => 0x42; + + public override int DefaultDropSound => 0x42; + + public override Rectangle2D Bounds => new Rectangle2D(18, 105, 144, 73); + + private void SetChestAppearance() + { + var UseFirstItemId = Utility.RandomBool(); + switch (Utility.RandomList(0, 1, 2)) + { + case 0: // Wooden Chest + ItemID = UseFirstItemId ? 0xe42 : 0xe43; + GumpID = 0x49; + break; + + case 1: // Metal Chest + ItemID = UseFirstItemId ? 0x9ab : 0xe7c; + GumpID = 0x4A; + break; + + case 2: // Metal Golden Chest + ItemID = UseFirstItemId ? 0xe40 : 0xe41; + GumpID = 0x42; + break; + } + } + + 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(); + } } - - public TreasureChestLevel3(Serial serial) - : base(serial) - { - } - - public override bool Decays => true; - - public override bool IsDecoContainer => false; - - public override TimeSpan DecayTime => TimeSpan.FromMinutes(Utility.Random(15, 60)); - - public override int DefaultGumpID => 0x42; - - public override int DefaultDropSound => 0x42; - - public override Rectangle2D Bounds => new Rectangle2D(18, 105, 144, 73); - - private void SetChestAppearance() - { - bool UseFirstItemId = Utility.RandomBool(); - switch (Utility.RandomList(0, 1, 2)) - { - case 0: // Wooden Chest - ItemID = UseFirstItemId ? 0xe42 : 0xe43; - GumpID = 0x49; - break; - - case 1: // Metal Chest - ItemID = UseFirstItemId ? 0x9ab : 0xe7c; - GumpID = 0x4A; - break; - - case 2: // Metal Golden Chest - ItemID = UseFirstItemId ? 0xe40 : 0xe41; - GumpID = 0x42; - break; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/TreasureChests/TreasureChestLevel4.cs b/Projects/UOContent/Items/TreasureChests/TreasureChestLevel4.cs index 207d4ee35..fb338a206 100644 --- a/Projects/UOContent/Items/TreasureChests/TreasureChestLevel4.cs +++ b/Projects/UOContent/Items/TreasureChests/TreasureChestLevel4.cs @@ -2,168 +2,168 @@ using System; namespace Server.Items { - public class TreasureChestLevel4 : LockableContainer - { - private const int m_Level = 4; - - [Constructible] - public TreasureChestLevel4() - : base(0xE41) + public class TreasureChestLevel4 : LockableContainer { - SetChestAppearance(); - Movable = false; + private const int m_Level = 4; - TrapType = TrapType.ExplosionTrap; - TrapPower = m_Level * Utility.Random(10, 25); - Locked = true; - - RequiredSkill = 92; - LockLevel = RequiredSkill - Utility.Random(1, 10); - MaxLockLevel = RequiredSkill + Utility.Random(1, 10); - - // According to OSI, loot in level 4 chest is: - // Gold 500 - 900 - // Reagents - // Scrolls - // Blank scrolls - // Potions - // Gems - // Magic Wand - // Magic weapon - // Magic armour - // Magic clothing (not implemented) - // Magic jewelry (not implemented) - // Crystal ball (not implemented) - - // Gold - DropItem(new Gold(Utility.Random(200, 400))); - - // Reagents - for (int i = Utility.Random(1, m_Level); i > 1; i--) - { - Item ReagentLoot = Loot.RandomReagent(); - ReagentLoot.Amount = 12; - DropItem(ReagentLoot); - } - - // Scrolls - for (int i = Utility.Random(1, m_Level); i > 1; i--) - { - Item ScrollLoot = Loot.RandomScroll(0, 47, SpellbookType.Regular); - ScrollLoot.Amount = 16; - DropItem(ScrollLoot); - } - - // Drop blank scrolls - DropItem(new BlankScroll(Utility.Random(1, m_Level))); - - // Potions - for (int i = Utility.Random(1, m_Level); i > 1; i--) - { - Item PotionLoot = Loot.RandomPotion(); - DropItem(PotionLoot); - } - - // Gems - for (int i = Utility.Random(1, m_Level); i > 1; i--) - { - Item GemLoot = Loot.RandomGem(); - GemLoot.Amount = 12; - DropItem(GemLoot); - } - - // Magic Wand - for (int i = Utility.Random(1, m_Level); i > 1; i--) - DropItem(Loot.RandomWand()); - - // Equipment - for (int i = Utility.Random(1, m_Level); i > 1; i--) - { - Item item = Loot.RandomArmorOrShieldOrWeapon(); - - if (item is BaseWeapon weapon) + [Constructible] + public TreasureChestLevel4() + : base(0xE41) { - weapon.DamageLevel = (WeaponDamageLevel)Utility.Random(m_Level); - weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random(m_Level); - weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random(m_Level); - weapon.Quality = WeaponQuality.Regular; - } - else if (item is BaseArmor armor) - { - armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(m_Level); - armor.Durability = (ArmorDurabilityLevel)Utility.Random(m_Level); - armor.Quality = ArmorQuality.Regular; + SetChestAppearance(); + Movable = false; + + TrapType = TrapType.ExplosionTrap; + TrapPower = m_Level * Utility.Random(10, 25); + Locked = true; + + RequiredSkill = 92; + LockLevel = RequiredSkill - Utility.Random(1, 10); + MaxLockLevel = RequiredSkill + Utility.Random(1, 10); + + // According to OSI, loot in level 4 chest is: + // Gold 500 - 900 + // Reagents + // Scrolls + // Blank scrolls + // Potions + // Gems + // Magic Wand + // Magic weapon + // Magic armour + // Magic clothing (not implemented) + // Magic jewelry (not implemented) + // Crystal ball (not implemented) + + // Gold + DropItem(new Gold(Utility.Random(200, 400))); + + // Reagents + for (var i = Utility.Random(1, m_Level); i > 1; i--) + { + var ReagentLoot = Loot.RandomReagent(); + ReagentLoot.Amount = 12; + DropItem(ReagentLoot); + } + + // Scrolls + for (var i = Utility.Random(1, m_Level); i > 1; i--) + { + Item ScrollLoot = Loot.RandomScroll(0, 47, SpellbookType.Regular); + ScrollLoot.Amount = 16; + DropItem(ScrollLoot); + } + + // Drop blank scrolls + DropItem(new BlankScroll(Utility.Random(1, m_Level))); + + // Potions + for (var i = Utility.Random(1, m_Level); i > 1; i--) + { + var PotionLoot = Loot.RandomPotion(); + DropItem(PotionLoot); + } + + // Gems + for (var i = Utility.Random(1, m_Level); i > 1; i--) + { + var GemLoot = Loot.RandomGem(); + GemLoot.Amount = 12; + DropItem(GemLoot); + } + + // Magic Wand + for (var i = Utility.Random(1, m_Level); i > 1; i--) + DropItem(Loot.RandomWand()); + + // Equipment + for (var i = Utility.Random(1, m_Level); i > 1; i--) + { + var item = Loot.RandomArmorOrShieldOrWeapon(); + + if (item is BaseWeapon weapon) + { + weapon.DamageLevel = (WeaponDamageLevel)Utility.Random(m_Level); + weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random(m_Level); + weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random(m_Level); + weapon.Quality = WeaponQuality.Regular; + } + else if (item is BaseArmor armor) + { + armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(m_Level); + armor.Durability = (ArmorDurabilityLevel)Utility.Random(m_Level); + armor.Quality = ArmorQuality.Regular; + } + + DropItem(item); + } + + // Clothing + for (var i = Utility.Random(1, 2); i > 1; i--) + DropItem(Loot.RandomClothing()); + + // Jewelry + for (var i = Utility.Random(1, 2); i > 1; i--) + DropItem(Loot.RandomJewelry()); + + // Crystal ball (not implemented) } - DropItem(item); - } + public TreasureChestLevel4(Serial serial) + : base(serial) + { + } - // Clothing - for (int i = Utility.Random(1, 2); i > 1; i--) - DropItem(Loot.RandomClothing()); + public override bool Decays => true; - // Jewelry - for (int i = Utility.Random(1, 2); i > 1; i--) - DropItem(Loot.RandomJewelry()); + public override bool IsDecoContainer => false; - // Crystal ball (not implemented) + public override TimeSpan DecayTime => TimeSpan.FromMinutes(Utility.Random(15, 60)); + + public override int DefaultGumpID => 0x42; + + public override int DefaultDropSound => 0x42; + + public override Rectangle2D Bounds => new Rectangle2D(18, 105, 144, 73); + + private void SetChestAppearance() + { + var UseFirstItemId = Utility.RandomBool(); + + switch (Utility.Random(4)) + { + case 0: // Wooden Chest + ItemID = UseFirstItemId ? 0xe42 : 0xe43; + GumpID = 0x49; + break; + + case 1: // Metal Chest + ItemID = UseFirstItemId ? 0x9ab : 0xe7c; + GumpID = 0x4A; + break; + + case 2: // Metal Golden Chest + ItemID = UseFirstItemId ? 0xe40 : 0xe41; + GumpID = 0x42; + break; + + case 3: // Keg + ItemID = 0xe7f; + GumpID = 0x3e; + break; + } + } + + 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(); + } } - - public TreasureChestLevel4(Serial serial) - : base(serial) - { - } - - public override bool Decays => true; - - public override bool IsDecoContainer => false; - - public override TimeSpan DecayTime => TimeSpan.FromMinutes(Utility.Random(15, 60)); - - public override int DefaultGumpID => 0x42; - - public override int DefaultDropSound => 0x42; - - public override Rectangle2D Bounds => new Rectangle2D(18, 105, 144, 73); - - private void SetChestAppearance() - { - bool UseFirstItemId = Utility.RandomBool(); - - switch (Utility.Random(4)) - { - case 0: // Wooden Chest - ItemID = UseFirstItemId ? 0xe42 : 0xe43; - GumpID = 0x49; - break; - - case 1: // Metal Chest - ItemID = UseFirstItemId ? 0x9ab : 0xe7c; - GumpID = 0x4A; - break; - - case 2: // Metal Golden Chest - ItemID = UseFirstItemId ? 0xe40 : 0xe41; - GumpID = 0x42; - break; - - case 3: // Keg - ItemID = 0xe7f; - GumpID = 0x3e; - break; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Items/Wands/BaseWand.cs b/Projects/UOContent/Items/Wands/BaseWand.cs index 350ab980f..fdc6fe77a 100644 --- a/Projects/UOContent/Items/Wands/BaseWand.cs +++ b/Projects/UOContent/Items/Wands/BaseWand.cs @@ -6,277 +6,287 @@ using Server.Targeting; namespace Server.Items { - public enum WandEffect - { - Clumsiness, - Identification, - Healing, - Feeblemindedness, - Weakness, - MagicArrow, - Harming, - Fireball, - GreaterHealing, - Lightning, - ManaDraining - } - - public abstract class BaseWand : BaseBashing, ITokunoDyable - { - private int m_Charges; - - private WandEffect m_WandEffect; - - public BaseWand(WandEffect effect, int minCharges, int maxCharges) : base(Utility.RandomList(0xDF2, 0xDF3, 0xDF4, - 0xDF5)) + public enum WandEffect { - Weight = 1.0; - Effect = effect; - Charges = Utility.RandomMinMax(minCharges, maxCharges); - Attributes.SpellChanneling = 1; - Attributes.CastSpeed = -1; - WeaponAttributes.MageWeapon = Utility.RandomMinMax(1, 10); + Clumsiness, + Identification, + Healing, + Feeblemindedness, + Weakness, + MagicArrow, + Harming, + Fireball, + GreaterHealing, + Lightning, + ManaDraining } - public BaseWand(Serial serial) : base(serial) + public abstract class BaseWand : BaseBashing, ITokunoDyable { - } + private int m_Charges; - public override WeaponAbility PrimaryAbility => WeaponAbility.Dismount; - public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm; + private WandEffect m_WandEffect; - public override int AosStrengthReq => 5; - public override int AosMinDamage => 9; - public override int AosMaxDamage => 11; - public override int AosSpeed => 40; - public override float MlSpeed => 2.75f; - - public override int OldStrengthReq => 0; - public override int OldMinDamage => 2; - public override int OldMaxDamage => 6; - public override int OldSpeed => 35; - - public override int InitMinHits => 31; - public override int InitMaxHits => 110; - - public virtual TimeSpan GetUseDelay => TimeSpan.FromSeconds(4.0); - - [CommandProperty(AccessLevel.GameMaster)] - public WandEffect Effect - { - get => m_WandEffect; - set - { - m_WandEffect = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Charges - { - get => m_Charges; - set - { - m_Charges = value; - InvalidateProperties(); - } - } - - public void ConsumeCharge(Mobile from) - { - --Charges; - - if (Charges == 0) - from.SendLocalizedMessage(1019073); // This item is out of charges. - - ApplyDelayTo(from); - } - - public virtual void ApplyDelayTo(Mobile from) - { - from.BeginAction(); - Timer.DelayCall(GetUseDelay, ReleaseWandLock_Callback, from); - } - - public virtual void ReleaseWandLock_Callback(Mobile state) - { - state.EndAction(); - } - - public override void OnDoubleClick(Mobile from) - { - if (!from.CanBeginAction()) - { - from.SendLocalizedMessage(1070860); // You must wait a moment for the wand to recharge. - return; - } - - if (Parent == from) - { - if (Charges > 0) - OnWandUse(from); - else - from.SendLocalizedMessage(1019073); // This item is out of charges. - } - else - { - from.SendLocalizedMessage(502641); // You must equip this item to use it. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write((int)m_WandEffect); - writer.Write(m_Charges); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_WandEffect = (WandEffect)reader.ReadInt(); - m_Charges = reader.ReadInt(); - - break; - } - } - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - switch (m_WandEffect) - { - case WandEffect.Clumsiness: - list.Add(1017326, m_Charges.ToString()); - break; // clumsiness charges: ~1_val~ - case WandEffect.Identification: - list.Add(1017350, m_Charges.ToString()); - break; // identification charges: ~1_val~ - case WandEffect.Healing: - list.Add(1017329, m_Charges.ToString()); - break; // healing charges: ~1_val~ - case WandEffect.Feeblemindedness: - list.Add(1017327, m_Charges.ToString()); - break; // feeblemind charges: ~1_val~ - case WandEffect.Weakness: - list.Add(1017328, m_Charges.ToString()); - break; // weakness charges: ~1_val~ - case WandEffect.MagicArrow: - list.Add(1060492, m_Charges.ToString()); - break; // magic arrow charges: ~1_val~ - case WandEffect.Harming: - list.Add(1017334, m_Charges.ToString()); - break; // harm charges: ~1_val~ - case WandEffect.Fireball: - list.Add(1060487, m_Charges.ToString()); - break; // fireball charges: ~1_val~ - case WandEffect.GreaterHealing: - list.Add(1017330, m_Charges.ToString()); - break; // greater healing charges: ~1_val~ - case WandEffect.Lightning: - list.Add(1060491, m_Charges.ToString()); - break; // lightning charges: ~1_val~ - case WandEffect.ManaDraining: - list.Add(1017339, m_Charges.ToString()); - break; // mana drain charges: ~1_val~ - } - } - - public override void OnSingleClick(Mobile from) - { - List attrs = new List(); - - if (DisplayLootType) - { - if (LootType == LootType.Blessed) - attrs.Add(new EquipInfoAttribute(1038021)); // blessed - else if (LootType == LootType.Cursed) - attrs.Add(new EquipInfoAttribute(1049643)); // cursed - } - - if (!Identified) - { - attrs.Add(new EquipInfoAttribute(1038000)); // Unidentified - } - else - { - var num = m_WandEffect switch + public BaseWand(WandEffect effect, int minCharges, int maxCharges) : base( + Utility.RandomList( + 0xDF2, + 0xDF3, + 0xDF4, + 0xDF5 + ) + ) { - WandEffect.Clumsiness => 3002011, - WandEffect.Identification => 1044063, - WandEffect.Healing => 3002014, - WandEffect.Feeblemindedness => 3002013, - WandEffect.Weakness => 3002018, - WandEffect.MagicArrow => 3002015, - WandEffect.Harming => 3002022, - WandEffect.Fireball => 3002028, - WandEffect.GreaterHealing => 3002039, - WandEffect.Lightning => 3002040, - WandEffect.ManaDraining => 3002041, - _ => 0 - }; + Weight = 1.0; + Effect = effect; + Charges = Utility.RandomMinMax(minCharges, maxCharges); + Attributes.SpellChanneling = 1; + Attributes.CastSpeed = -1; + WeaponAttributes.MageWeapon = Utility.RandomMinMax(1, 10); + } - if (num > 0) - attrs.Add(new EquipInfoAttribute(num, m_Charges)); - } + public BaseWand(Serial serial) : base(serial) + { + } - int number; + public override WeaponAbility PrimaryAbility => WeaponAbility.Dismount; + public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm; - if (Name == null) - { - number = 1017085; - } - else - { - LabelTo(from, Name); - number = 1041000; - } + public override int AosStrengthReq => 5; + public override int AosMinDamage => 9; + public override int AosMaxDamage => 11; + public override int AosSpeed => 40; + public override float MlSpeed => 2.75f; - if (attrs.Count == 0 && Crafter == null && Name != null) - return; + public override int OldStrengthReq => 0; + public override int OldMinDamage => 2; + public override int OldMaxDamage => 6; + public override int OldSpeed => 35; - EquipmentInfo eqInfo = new EquipmentInfo(number, Crafter, false, - attrs.ToArray()); + public override int InitMinHits => 31; + public override int InitMaxHits => 110; - from.Send(new DisplayEquipmentInfo(this, eqInfo)); + public virtual TimeSpan GetUseDelay => TimeSpan.FromSeconds(4.0); + + [CommandProperty(AccessLevel.GameMaster)] + public WandEffect Effect + { + get => m_WandEffect; + set + { + m_WandEffect = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Charges + { + get => m_Charges; + set + { + m_Charges = value; + InvalidateProperties(); + } + } + + public void ConsumeCharge(Mobile from) + { + --Charges; + + if (Charges == 0) + from.SendLocalizedMessage(1019073); // This item is out of charges. + + ApplyDelayTo(from); + } + + public virtual void ApplyDelayTo(Mobile from) + { + from.BeginAction(); + Timer.DelayCall(GetUseDelay, ReleaseWandLock_Callback, from); + } + + public virtual void ReleaseWandLock_Callback(Mobile state) + { + state.EndAction(); + } + + public override void OnDoubleClick(Mobile from) + { + if (!from.CanBeginAction()) + { + from.SendLocalizedMessage(1070860); // You must wait a moment for the wand to recharge. + return; + } + + if (Parent == from) + { + if (Charges > 0) + OnWandUse(from); + else + from.SendLocalizedMessage(1019073); // This item is out of charges. + } + else + { + from.SendLocalizedMessage(502641); // You must equip this item to use it. + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write((int)m_WandEffect); + writer.Write(m_Charges); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_WandEffect = (WandEffect)reader.ReadInt(); + m_Charges = reader.ReadInt(); + + break; + } + } + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + switch (m_WandEffect) + { + case WandEffect.Clumsiness: + list.Add(1017326, m_Charges.ToString()); + break; // clumsiness charges: ~1_val~ + case WandEffect.Identification: + list.Add(1017350, m_Charges.ToString()); + break; // identification charges: ~1_val~ + case WandEffect.Healing: + list.Add(1017329, m_Charges.ToString()); + break; // healing charges: ~1_val~ + case WandEffect.Feeblemindedness: + list.Add(1017327, m_Charges.ToString()); + break; // feeblemind charges: ~1_val~ + case WandEffect.Weakness: + list.Add(1017328, m_Charges.ToString()); + break; // weakness charges: ~1_val~ + case WandEffect.MagicArrow: + list.Add(1060492, m_Charges.ToString()); + break; // magic arrow charges: ~1_val~ + case WandEffect.Harming: + list.Add(1017334, m_Charges.ToString()); + break; // harm charges: ~1_val~ + case WandEffect.Fireball: + list.Add(1060487, m_Charges.ToString()); + break; // fireball charges: ~1_val~ + case WandEffect.GreaterHealing: + list.Add(1017330, m_Charges.ToString()); + break; // greater healing charges: ~1_val~ + case WandEffect.Lightning: + list.Add(1060491, m_Charges.ToString()); + break; // lightning charges: ~1_val~ + case WandEffect.ManaDraining: + list.Add(1017339, m_Charges.ToString()); + break; // mana drain charges: ~1_val~ + } + } + + public override void OnSingleClick(Mobile from) + { + var attrs = new List(); + + if (DisplayLootType) + { + if (LootType == LootType.Blessed) + attrs.Add(new EquipInfoAttribute(1038021)); // blessed + else if (LootType == LootType.Cursed) + attrs.Add(new EquipInfoAttribute(1049643)); // cursed + } + + if (!Identified) + { + attrs.Add(new EquipInfoAttribute(1038000)); // Unidentified + } + else + { + var num = m_WandEffect switch + { + WandEffect.Clumsiness => 3002011, + WandEffect.Identification => 1044063, + WandEffect.Healing => 3002014, + WandEffect.Feeblemindedness => 3002013, + WandEffect.Weakness => 3002018, + WandEffect.MagicArrow => 3002015, + WandEffect.Harming => 3002022, + WandEffect.Fireball => 3002028, + WandEffect.GreaterHealing => 3002039, + WandEffect.Lightning => 3002040, + WandEffect.ManaDraining => 3002041, + _ => 0 + }; + + if (num > 0) + attrs.Add(new EquipInfoAttribute(num, m_Charges)); + } + + int number; + + if (Name == null) + { + number = 1017085; + } + else + { + LabelTo(from, Name); + number = 1041000; + } + + if (attrs.Count == 0 && Crafter == null && Name != null) + return; + + var eqInfo = new EquipmentInfo( + number, + Crafter, + false, + attrs.ToArray() + ); + + from.Send(new DisplayEquipmentInfo(this, eqInfo)); + } + + public void Cast(Spell spell) + { + var m = Movable; + + Movable = false; + spell.Cast(); + Movable = m; + } + + public virtual void OnWandUse(Mobile from) + { + from.Target = new WandTarget(this); + } + + public virtual void DoWandTarget(Mobile from, object o) + { + if (Deleted || Charges <= 0 || Parent != from || o is StaticTarget || o is LandTarget) + return; + + if (OnWandTarget(from, o)) + ConsumeCharge(from); + } + + public virtual bool OnWandTarget(Mobile from, object o) => true; } - - public void Cast(Spell spell) - { - bool m = Movable; - - Movable = false; - spell.Cast(); - Movable = m; - } - - public virtual void OnWandUse(Mobile from) - { - from.Target = new WandTarget(this); - } - - public virtual void DoWandTarget(Mobile from, object o) - { - if (Deleted || Charges <= 0 || Parent != from || o is StaticTarget || o is LandTarget) - return; - - if (OnWandTarget(from, o)) - ConsumeCharge(from); - } - - public virtual bool OnWandTarget(Mobile from, object o) => true; - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Wands/ClumsyWand.cs b/Projects/UOContent/Items/Wands/ClumsyWand.cs index b40947609..c0415c614 100644 --- a/Projects/UOContent/Items/Wands/ClumsyWand.cs +++ b/Projects/UOContent/Items/Wands/ClumsyWand.cs @@ -2,34 +2,34 @@ using Server.Spells.First; namespace Server.Items { - public class ClumsyWand : BaseWand - { - [Constructible] - public ClumsyWand() : base(WandEffect.Clumsiness, 5, 30) + public class ClumsyWand : BaseWand { + [Constructible] + public ClumsyWand() : base(WandEffect.Clumsiness, 5, 30) + { + } + + public ClumsyWand(Serial serial) : base(serial) + { + } + + 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 OnWandUse(Mobile from) + { + Cast(new ClumsySpell(from, this)); + } } - - public ClumsyWand(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnWandUse(Mobile from) - { - Cast(new ClumsySpell(from, this)); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Wands/FeebleWand.cs b/Projects/UOContent/Items/Wands/FeebleWand.cs index 15edd6c6b..2afa2e205 100644 --- a/Projects/UOContent/Items/Wands/FeebleWand.cs +++ b/Projects/UOContent/Items/Wands/FeebleWand.cs @@ -2,34 +2,34 @@ using Server.Spells.First; namespace Server.Items { - public class FeebleWand : BaseWand - { - [Constructible] - public FeebleWand() : base(WandEffect.Feeblemindedness, 5, 30) + public class FeebleWand : BaseWand { + [Constructible] + public FeebleWand() : base(WandEffect.Feeblemindedness, 5, 30) + { + } + + public FeebleWand(Serial serial) : base(serial) + { + } + + 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 OnWandUse(Mobile from) + { + Cast(new FeeblemindSpell(from, this)); + } } - - public FeebleWand(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnWandUse(Mobile from) - { - Cast(new FeeblemindSpell(from, this)); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Wands/FireballWand.cs b/Projects/UOContent/Items/Wands/FireballWand.cs index 9d154a1ff..ca59fff45 100644 --- a/Projects/UOContent/Items/Wands/FireballWand.cs +++ b/Projects/UOContent/Items/Wands/FireballWand.cs @@ -2,34 +2,34 @@ using Server.Spells.Third; namespace Server.Items { - public class FireballWand : BaseWand - { - [Constructible] - public FireballWand() : base(WandEffect.Fireball, 5, Core.ML ? 109 : 15) + public class FireballWand : BaseWand { + [Constructible] + public FireballWand() : base(WandEffect.Fireball, 5, Core.ML ? 109 : 15) + { + } + + public FireballWand(Serial serial) : base(serial) + { + } + + 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 OnWandUse(Mobile from) + { + Cast(new FireballSpell(from, this)); + } } - - public FireballWand(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnWandUse(Mobile from) - { - Cast(new FireballSpell(from, this)); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Wands/GreaterHealWand.cs b/Projects/UOContent/Items/Wands/GreaterHealWand.cs index 5821b8bed..0728b54bc 100644 --- a/Projects/UOContent/Items/Wands/GreaterHealWand.cs +++ b/Projects/UOContent/Items/Wands/GreaterHealWand.cs @@ -2,34 +2,34 @@ using Server.Spells.Fourth; namespace Server.Items { - public class GreaterHealWand : BaseWand - { - [Constructible] - public GreaterHealWand() : base(WandEffect.GreaterHealing, 1, Core.ML ? 109 : 5) + public class GreaterHealWand : BaseWand { + [Constructible] + public GreaterHealWand() : base(WandEffect.GreaterHealing, 1, Core.ML ? 109 : 5) + { + } + + public GreaterHealWand(Serial serial) : base(serial) + { + } + + 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 OnWandUse(Mobile from) + { + Cast(new GreaterHealSpell(from, this)); + } } - - public GreaterHealWand(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnWandUse(Mobile from) - { - Cast(new GreaterHealSpell(from, this)); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Wands/HarmWand.cs b/Projects/UOContent/Items/Wands/HarmWand.cs index 4f6891daa..00dabd1b9 100644 --- a/Projects/UOContent/Items/Wands/HarmWand.cs +++ b/Projects/UOContent/Items/Wands/HarmWand.cs @@ -2,34 +2,34 @@ using Server.Spells.Second; namespace Server.Items { - public class HarmWand : BaseWand - { - [Constructible] - public HarmWand() : base(WandEffect.Harming, 5, Core.ML ? 109 : 30) + public class HarmWand : BaseWand { + [Constructible] + public HarmWand() : base(WandEffect.Harming, 5, Core.ML ? 109 : 30) + { + } + + public HarmWand(Serial serial) : base(serial) + { + } + + 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 OnWandUse(Mobile from) + { + Cast(new HarmSpell(from, this)); + } } - - public HarmWand(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnWandUse(Mobile from) - { - Cast(new HarmSpell(from, this)); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Wands/HealWand.cs b/Projects/UOContent/Items/Wands/HealWand.cs index 62bb28fe7..d60ea6c24 100644 --- a/Projects/UOContent/Items/Wands/HealWand.cs +++ b/Projects/UOContent/Items/Wands/HealWand.cs @@ -2,34 +2,34 @@ using Server.Spells.First; namespace Server.Items { - public class HealWand : BaseWand - { - [Constructible] - public HealWand() : base(WandEffect.Healing, 10, Core.ML ? 109 : 25) + public class HealWand : BaseWand { + [Constructible] + public HealWand() : base(WandEffect.Healing, 10, Core.ML ? 109 : 25) + { + } + + public HealWand(Serial serial) : base(serial) + { + } + + 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 OnWandUse(Mobile from) + { + Cast(new HealSpell(from, this)); + } } - - public HealWand(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnWandUse(Mobile from) - { - Cast(new HealSpell(from, this)); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Wands/IDWand.cs b/Projects/UOContent/Items/Wands/IDWand.cs index b7b4c863e..8f530569b 100644 --- a/Projects/UOContent/Items/Wands/IDWand.cs +++ b/Projects/UOContent/Items/Wands/IDWand.cs @@ -2,49 +2,49 @@ using System; namespace Server.Items { - public class IDWand : BaseWand - { - [Constructible] - public IDWand() : base(WandEffect.Identification, 25, 175) + public class IDWand : BaseWand { + [Constructible] + public IDWand() : base(WandEffect.Identification, 25, 175) + { + } + + public IDWand(Serial serial) : base(serial) + { + } + + public override TimeSpan GetUseDelay => TimeSpan.Zero; + + 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 OnWandTarget(Mobile from, object o) + { + if (o is Item item) + { + if (item is BaseWeapon weapon) + weapon.Identified = true; + else if (item is BaseArmor armor) + armor.Identified = true; + + if (!Core.AOS) + item.OnSingleClick(from); + + return true; + } + + return false; + } } - - public IDWand(Serial serial) : base(serial) - { - } - - public override TimeSpan GetUseDelay => TimeSpan.Zero; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override bool OnWandTarget(Mobile from, object o) - { - if (o is Item item) - { - if (item is BaseWeapon weapon) - weapon.Identified = true; - else if (item is BaseArmor armor) - armor.Identified = true; - - if (!Core.AOS) - item.OnSingleClick(from); - - return true; - } - - return false; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Wands/LightningWand.cs b/Projects/UOContent/Items/Wands/LightningWand.cs index faa2b3c2a..40a4310f2 100644 --- a/Projects/UOContent/Items/Wands/LightningWand.cs +++ b/Projects/UOContent/Items/Wands/LightningWand.cs @@ -2,34 +2,34 @@ using Server.Spells.Fourth; namespace Server.Items { - public class LightningWand : BaseWand - { - [Constructible] - public LightningWand() : base(WandEffect.Lightning, 5, Core.ML ? 109 : 20) + public class LightningWand : BaseWand { + [Constructible] + public LightningWand() : base(WandEffect.Lightning, 5, Core.ML ? 109 : 20) + { + } + + public LightningWand(Serial serial) : base(serial) + { + } + + 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 OnWandUse(Mobile from) + { + Cast(new LightningSpell(from, this)); + } } - - public LightningWand(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnWandUse(Mobile from) - { - Cast(new LightningSpell(from, this)); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Wands/MagicArrowWand.cs b/Projects/UOContent/Items/Wands/MagicArrowWand.cs index 3ffc3208e..6be5aad47 100644 --- a/Projects/UOContent/Items/Wands/MagicArrowWand.cs +++ b/Projects/UOContent/Items/Wands/MagicArrowWand.cs @@ -2,34 +2,34 @@ using Server.Spells.First; namespace Server.Items { - public class MagicArrowWand : BaseWand - { - [Constructible] - public MagicArrowWand() : base(WandEffect.MagicArrow, 5, Core.ML ? 109 : 30) + public class MagicArrowWand : BaseWand { + [Constructible] + public MagicArrowWand() : base(WandEffect.MagicArrow, 5, Core.ML ? 109 : 30) + { + } + + public MagicArrowWand(Serial serial) : base(serial) + { + } + + 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 OnWandUse(Mobile from) + { + Cast(new MagicArrowSpell(from, this)); + } } - - public MagicArrowWand(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnWandUse(Mobile from) - { - Cast(new MagicArrowSpell(from, this)); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Wands/ManaDrainWand.cs b/Projects/UOContent/Items/Wands/ManaDrainWand.cs index 7151e9d88..c3ea2b0c3 100644 --- a/Projects/UOContent/Items/Wands/ManaDrainWand.cs +++ b/Projects/UOContent/Items/Wands/ManaDrainWand.cs @@ -2,34 +2,34 @@ using Server.Spells.Fourth; namespace Server.Items { - public class ManaDrainWand : BaseWand - { - [Constructible] - public ManaDrainWand() : base(WandEffect.ManaDraining, 5, 30) + public class ManaDrainWand : BaseWand { + [Constructible] + public ManaDrainWand() : base(WandEffect.ManaDraining, 5, 30) + { + } + + public ManaDrainWand(Serial serial) : base(serial) + { + } + + 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 OnWandUse(Mobile from) + { + Cast(new ManaDrainSpell(from, this)); + } } - - public ManaDrainWand(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnWandUse(Mobile from) - { - Cast(new ManaDrainSpell(from, this)); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Wands/RandomWand.cs b/Projects/UOContent/Items/Wands/RandomWand.cs index dfe2be27a..82e892ea3 100644 --- a/Projects/UOContent/Items/Wands/RandomWand.cs +++ b/Projects/UOContent/Items/Wands/RandomWand.cs @@ -1,9 +1,9 @@ namespace Server.Items { - public class RandomWand - { - public static BaseWand CreateWand() => CreateRandomWand(); + public class RandomWand + { + public static BaseWand CreateWand() => CreateRandomWand(); - public static BaseWand CreateRandomWand() => Loot.RandomWand(); - } -} \ No newline at end of file + public static BaseWand CreateRandomWand() => Loot.RandomWand(); + } +} diff --git a/Projects/UOContent/Items/Wands/WandTarget.cs b/Projects/UOContent/Items/Wands/WandTarget.cs index 3d5ac2874..fd15bc638 100644 --- a/Projects/UOContent/Items/Wands/WandTarget.cs +++ b/Projects/UOContent/Items/Wands/WandTarget.cs @@ -2,17 +2,17 @@ using Server.Items; namespace Server.Targeting { - public class WandTarget : Target - { - private readonly BaseWand m_Item; - - public WandTarget(BaseWand item) : base(6, false, TargetFlags.None) => m_Item = item; - - private static int GetOffset(Mobile caster) => 5 + (int)(caster.Skills.Magery.Value * 0.02); - - protected override void OnTarget(Mobile from, object targeted) + public class WandTarget : Target { - m_Item.DoWandTarget(from, targeted); + private readonly BaseWand m_Item; + + public WandTarget(BaseWand item) : base(6, false, TargetFlags.None) => m_Item = item; + + private static int GetOffset(Mobile caster) => 5 + (int)(caster.Skills.Magery.Value * 0.02); + + protected override void OnTarget(Mobile from, object targeted) + { + m_Item.DoWandTarget(from, targeted); + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Wands/WeaknessWand.cs b/Projects/UOContent/Items/Wands/WeaknessWand.cs index 18414228a..6ac6c4d17 100644 --- a/Projects/UOContent/Items/Wands/WeaknessWand.cs +++ b/Projects/UOContent/Items/Wands/WeaknessWand.cs @@ -2,34 +2,34 @@ using Server.Spells.First; namespace Server.Items { - public class WeaknessWand : BaseWand - { - [Constructible] - public WeaknessWand() : base(WandEffect.Weakness, 5, 30) + public class WeaknessWand : BaseWand { + [Constructible] + public WeaknessWand() : base(WandEffect.Weakness, 5, 30) + { + } + + public WeaknessWand(Serial serial) : base(serial) + { + } + + 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 OnWandUse(Mobile from) + { + Cast(new WeakenSpell(from, this)); + } } - - public WeaknessWand(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnWandUse(Mobile from) - { - Cast(new WeakenSpell(from, this)); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Abilities/ArmorIgnore.cs b/Projects/UOContent/Items/Weapons/Abilities/ArmorIgnore.cs index 014e3a2aa..b5cc3eec5 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/ArmorIgnore.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/ArmorIgnore.cs @@ -1,28 +1,29 @@ namespace Server.Items { - /// - /// This special move allows the skilled warrior to bypass his target's physical resistance, for one shot only. - /// The Armor Ignore shot does slightly less damage than normal. - /// Against a heavily armored opponent, this ability is a big win, but when used against a very lightly armored foe, it might - /// be better to use a standard strike! - /// - public class ArmorIgnore : WeaponAbility - { - public override int BaseMana => 30; - public override double DamageScalar => 0.9; - - public override void OnHit(Mobile attacker, Mobile defender, int damage) + /// + /// This special move allows the skilled warrior to bypass his target's physical resistance, for one shot only. + /// The Armor Ignore shot does slightly less damage than normal. + /// Against a heavily armored opponent, this ability is a big win, but when used against a very lightly armored foe, it + /// might + /// be better to use a standard strike! + /// + public class ArmorIgnore : WeaponAbility { - if (!Validate(attacker) || !CheckMana(attacker, true)) - return; + public override int BaseMana => 30; + public override double DamageScalar => 0.9; - ClearCurrentAbility(attacker); + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + if (!Validate(attacker) || !CheckMana(attacker, true)) + return; - attacker.SendLocalizedMessage(1060076); // Your attack penetrates their armor! - defender.SendLocalizedMessage(1060077); // The blow penetrated your armor! + ClearCurrentAbility(attacker); - defender.PlaySound(0x56); - defender.FixedParticles(0x3728, 200, 25, 9942, EffectLayer.Waist); + attacker.SendLocalizedMessage(1060076); // Your attack penetrates their armor! + defender.SendLocalizedMessage(1060077); // The blow penetrated your armor! + + defender.PlaySound(0x56); + defender.FixedParticles(0x3728, 200, 25, 9942, EffectLayer.Waist); + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Abilities/ArmorPierce.cs b/Projects/UOContent/Items/Weapons/Abilities/ArmorPierce.cs index 8f4ea4cdf..49d7fed6f 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/ArmorPierce.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/ArmorPierce.cs @@ -1,39 +1,41 @@ namespace Server.Items { - /// - /// Strike your opponent with great force, partially bypassing their armor and inflicting greater damage. Requires either - /// Bushido or Ninjitsu skill - /// - public class ArmorPierce : WeaponAbility - { - public override int BaseMana => 30; - public override double DamageScalar => 1.5; - - public override bool RequiresSE => true; - - public override bool CheckSkills(Mobile from) + /// + /// Strike your opponent with great force, partially bypassing their armor and inflicting greater damage. Requires either + /// Bushido or Ninjitsu skill + /// + public class ArmorPierce : WeaponAbility { - if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0) - { - from.SendLocalizedMessage(1063347, - "50"); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack! - return false; - } + public override int BaseMana => 30; + public override double DamageScalar => 1.5; - return base.CheckSkills(from); + public override bool RequiresSE => true; + + public override bool CheckSkills(Mobile from) + { + if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0) + { + from.SendLocalizedMessage( + 1063347, + "50" + ); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack! + return false; + } + + return base.CheckSkills(from); + } + + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + if (!Validate(attacker) || !CheckMana(attacker, true)) + return; + + ClearCurrentAbility(attacker); + + attacker.SendLocalizedMessage(1063350); // You pierce your opponent's armor! + defender.SendLocalizedMessage(1063351); // Your attacker pierced your armor! + + defender.FixedParticles(0x3728, 1, 26, 0x26D6, 0, 0, EffectLayer.Waist); + } } - - public override void OnHit(Mobile attacker, Mobile defender, int damage) - { - if (!Validate(attacker) || !CheckMana(attacker, true)) - return; - - ClearCurrentAbility(attacker); - - attacker.SendLocalizedMessage(1063350); // You pierce your opponent's armor! - defender.SendLocalizedMessage(1063351); // Your attacker pierced your armor! - - defender.FixedParticles(0x3728, 1, 26, 0x26D6, 0, 0, EffectLayer.Waist); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Abilities/BleedAttack.cs b/Projects/UOContent/Items/Weapons/Abilities/BleedAttack.cs index b2d1429af..8d0aaf2fc 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/BleedAttack.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/BleedAttack.cs @@ -7,114 +7,118 @@ using Server.Spells.Necromancy; namespace Server.Items { - /// - /// Make your opponent bleed profusely with this wicked use of your weapon. - /// When successful, the target will bleed for several seconds, taking damage as time passes for up to ten seconds. - /// The rate of damage slows down as time passes, and the blood loss can be completely staunched with the use of bandages. - /// - public class BleedAttack : WeaponAbility - { - private static readonly Dictionary m_Table = new Dictionary(); - - public override int BaseMana => 30; - - public override void OnHit(Mobile attacker, Mobile defender, int damage) + /// + /// Make your opponent bleed profusely with this wicked use of your weapon. + /// When successful, the target will bleed for several seconds, taking damage as time passes for up to ten seconds. + /// The rate of damage slows down as time passes, and the blood loss can be completely staunched with the use of bandages. + /// + public class BleedAttack : WeaponAbility { - if (!Validate(attacker) || !CheckMana(attacker, true)) - return; + private static readonly Dictionary m_Table = new Dictionary(); - ClearCurrentAbility(attacker); + public override int BaseMana => 30; - // Necromancers under Lich or Wraith Form are immune to Bleed Attacks. - TransformContext context = TransformationSpellHelper.GetContext(defender); + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + if (!Validate(attacker) || !CheckMana(attacker, true)) + return; - if ((context != null && (context.Type == typeof(LichFormSpell) || context.Type == typeof(WraithFormSpell))) || - (defender is BaseCreature creature && creature.BleedImmune)) - { - attacker.SendLocalizedMessage(1062052); // Your target is not affected by the bleed attack! - return; - } + ClearCurrentAbility(attacker); - attacker.SendLocalizedMessage(1060159); // Your target is bleeding! - defender.SendLocalizedMessage(1060160); // You are bleeding! + // Necromancers under Lich or Wraith Form are immune to Bleed Attacks. + var context = TransformationSpellHelper.GetContext(defender); - if (defender is PlayerMobile) - { - defender.LocalOverheadMessage(MessageType.Regular, 0x21, 1060757); // You are bleeding profusely - defender.NonlocalOverheadMessage(MessageType.Regular, 0x21, 1060758, - defender.Name); // ~1_NAME~ is bleeding profusely - } + if (context != null && (context.Type == typeof(LichFormSpell) || context.Type == typeof(WraithFormSpell)) || + defender is BaseCreature creature && creature.BleedImmune) + { + attacker.SendLocalizedMessage(1062052); // Your target is not affected by the bleed attack! + return; + } - defender.PlaySound(0x133); - defender.FixedParticles(0x377A, 244, 25, 9950, 31, 0, EffectLayer.Waist); + attacker.SendLocalizedMessage(1060159); // Your target is bleeding! + defender.SendLocalizedMessage(1060160); // You are bleeding! - BeginBleed(defender, attacker); + if (defender is PlayerMobile) + { + defender.LocalOverheadMessage(MessageType.Regular, 0x21, 1060757); // You are bleeding profusely + defender.NonlocalOverheadMessage( + MessageType.Regular, + 0x21, + 1060758, + defender.Name + ); // ~1_NAME~ is bleeding profusely + } + + defender.PlaySound(0x133); + defender.FixedParticles(0x377A, 244, 25, 9950, 31, 0, EffectLayer.Waist); + + BeginBleed(defender, attacker); + } + + public static bool IsBleeding(Mobile m) => m_Table.ContainsKey(m); + + public static void BeginBleed(Mobile m, Mobile from) + { + m_Table.TryGetValue(m, out var t); + t?.Stop(); + + m_Table[m] = t = new InternalTimer(from, m); + t.Start(); + } + + public static void DoBleed(Mobile m, Mobile from, int level) + { + if (m.Alive) + { + var damage = Utility.RandomMinMax(level, level * 2); + + if (!m.Player) + damage *= 2; + + m.PlaySound(0x133); + m.Damage(damage, from); + + var blood = new Blood { ItemID = Utility.Random(0x122A, 5) }; + blood.MoveToWorld(m.Location, m.Map); + } + else + { + EndBleed(m, false); + } + } + + public static void EndBleed(Mobile m, bool message) + { + if (!m_Table.TryGetValue(m, out var t)) + return; + + t.Stop(); + m_Table.Remove(m); + + if (message) + m.SendLocalizedMessage(1060167); // The bleeding wounds have healed, you are no longer bleeding! + } + + private class InternalTimer : Timer + { + private readonly Mobile m_From; + private readonly Mobile m_Mobile; + private int m_Count; + + public InternalTimer(Mobile from, Mobile m) : base(TimeSpan.FromSeconds(2.0), TimeSpan.FromSeconds(2.0)) + { + m_From = from; + m_Mobile = m; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + DoBleed(m_Mobile, m_From, 5 - m_Count); + + if (++m_Count == 5) + EndBleed(m_Mobile, true); + } + } } - - public static bool IsBleeding(Mobile m) => m_Table.ContainsKey(m); - - public static void BeginBleed(Mobile m, Mobile from) - { - m_Table.TryGetValue(m, out Timer t); - t?.Stop(); - - m_Table[m] = t = new InternalTimer(from, m); - t.Start(); - } - - public static void DoBleed(Mobile m, Mobile from, int level) - { - if (m.Alive) - { - int damage = Utility.RandomMinMax(level, level * 2); - - if (!m.Player) - damage *= 2; - - m.PlaySound(0x133); - m.Damage(damage, from); - - Blood blood = new Blood { ItemID = Utility.Random(0x122A, 5) }; - blood.MoveToWorld(m.Location, m.Map); - } - else - { - EndBleed(m, false); - } - } - - public static void EndBleed(Mobile m, bool message) - { - if (!m_Table.TryGetValue(m, out Timer t)) - return; - - t.Stop(); - m_Table.Remove(m); - - if (message) - m.SendLocalizedMessage(1060167); // The bleeding wounds have healed, you are no longer bleeding! - } - - private class InternalTimer : Timer - { - private int m_Count; - private readonly Mobile m_From; - private readonly Mobile m_Mobile; - - public InternalTimer(Mobile from, Mobile m) : base(TimeSpan.FromSeconds(2.0), TimeSpan.FromSeconds(2.0)) - { - m_From = from; - m_Mobile = m; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - DoBleed(m_Mobile, m_From, 5 - m_Count); - - if (++m_Count == 5) - EndBleed(m_Mobile, true); - } - } - } } diff --git a/Projects/UOContent/Items/Weapons/Abilities/Block.cs b/Projects/UOContent/Items/Weapons/Abilities/Block.cs index 28dd927f0..4647e9c54 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/Block.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/Block.cs @@ -3,95 +3,99 @@ using System.Collections.Generic; namespace Server.Items { - /// - /// Raises your defenses for a short time. Requires Bushido or Ninjitsu skill. - /// - public class Block : WeaponAbility - { - private static readonly Dictionary m_Table = new Dictionary(); - - public override int BaseMana => 30; - - public override bool CheckSkills(Mobile from) + /// + /// Raises your defenses for a short time. Requires Bushido or Ninjitsu skill. + /// + public class Block : WeaponAbility { - if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0) - { - from.SendLocalizedMessage(1063347, - "50"); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack! - return false; - } + private static readonly Dictionary m_Table = new Dictionary(); - return base.CheckSkills(from); + public override int BaseMana => 30; + + public override bool CheckSkills(Mobile from) + { + if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0) + { + from.SendLocalizedMessage( + 1063347, + "50" + ); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack! + return false; + } + + return base.CheckSkills(from); + } + + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + if (!Validate(attacker) || !CheckMana(attacker, true)) + return; + + ClearCurrentAbility(attacker); + + attacker.SendLocalizedMessage(1063345); // You block an attack! + defender.SendLocalizedMessage(1063346); // Your attack was blocked! + + attacker.FixedParticles(0x37C4, 1, 16, 0x251D, 0x39D, 0x3, EffectLayer.RightHand); + + var bonus = (int)(10.0 * ((Math.Max( + attacker.Skills.Bushido.Value, + attacker.Skills.Ninjitsu.Value + ) - 50.0) / 70.0 + 5)); + + BeginBlock(attacker, bonus); + } + + public static bool GetBonus(Mobile targ, ref int bonus) + { + if (!m_Table.TryGetValue(targ, out var info)) + return false; + + bonus = info.m_Bonus; + return true; + } + + public static void BeginBlock(Mobile m, int bonus) + { + EndBlock(m); + m_Table[m] = new BlockInfo(m, bonus); + } + + public static void EndBlock(Mobile m) + { + if (!m_Table.TryGetValue(m, out var info)) + return; + + info.m_Timer?.Stop(); + m_Table.Remove(m); + } + + private class BlockInfo + { + public readonly int m_Bonus; + public readonly Timer m_Timer; + + public BlockInfo(Mobile target, int bonus) + { + m_Bonus = bonus; + m_Timer = new InternalTimer(target); + } + } + + private class InternalTimer : Timer + { + private readonly Mobile m_Mobile; + + public InternalTimer(Mobile m) : base(TimeSpan.FromSeconds(6.0)) + { + m_Mobile = m; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + EndBlock(m_Mobile); + } + } } - - public override void OnHit(Mobile attacker, Mobile defender, int damage) - { - if (!Validate(attacker) || !CheckMana(attacker, true)) - return; - - ClearCurrentAbility(attacker); - - attacker.SendLocalizedMessage(1063345); // You block an attack! - defender.SendLocalizedMessage(1063346); // Your attack was blocked! - - attacker.FixedParticles(0x37C4, 1, 16, 0x251D, 0x39D, 0x3, EffectLayer.RightHand); - - int bonus = (int)(10.0 * ((Math.Max(attacker.Skills.Bushido.Value, - attacker.Skills.Ninjitsu.Value) - 50.0) / 70.0 + 5)); - - BeginBlock(attacker, bonus); - } - - public static bool GetBonus(Mobile targ, ref int bonus) - { - if (!m_Table.TryGetValue(targ, out BlockInfo info)) - return false; - - bonus = info.m_Bonus; - return true; - } - - public static void BeginBlock(Mobile m, int bonus) - { - EndBlock(m); - m_Table[m] = new BlockInfo(m, bonus); - } - - public static void EndBlock(Mobile m) - { - if (!m_Table.TryGetValue(m, out BlockInfo info)) - return; - - info.m_Timer?.Stop(); - m_Table.Remove(m); - } - - private class BlockInfo - { - public readonly int m_Bonus; - public readonly Timer m_Timer; - - public BlockInfo(Mobile target, int bonus) - { - m_Bonus = bonus; - m_Timer = new InternalTimer(target); - } - } - - private class InternalTimer : Timer - { - private readonly Mobile m_Mobile; - - public InternalTimer(Mobile m) : base(TimeSpan.FromSeconds(6.0)) - { - m_Mobile = m; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - EndBlock(m_Mobile); - } - } - } } diff --git a/Projects/UOContent/Items/Weapons/Abilities/ConcussionBlow.cs b/Projects/UOContent/Items/Weapons/Abilities/ConcussionBlow.cs index 3f9f7fba5..0f8844b94 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/ConcussionBlow.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/ConcussionBlow.cs @@ -2,51 +2,64 @@ using System; namespace Server.Items { - /// - /// This devastating strike is most effective against those who are in good health and whose reserves of mana are low, or vice - /// versa. - /// - public class ConcussionBlow : WeaponAbility - { - public override int BaseMana => 25; - - public override bool OnBeforeDamage(Mobile attacker, Mobile defender) + /// + /// This devastating strike is most effective against those who are in good health and whose reserves of mana are low, or + /// vice + /// versa. + /// + public class ConcussionBlow : WeaponAbility { - if (!Validate(attacker) || !CheckMana(attacker, true)) - return false; + public override int BaseMana => 25; - ClearCurrentAbility(attacker); + public override bool OnBeforeDamage(Mobile attacker, Mobile defender) + { + if (!Validate(attacker) || !CheckMana(attacker, true)) + return false; - attacker.SendLocalizedMessage(1060165); // You have delivered a concussion! - defender.SendLocalizedMessage(1060166); // You feel disoriented! + ClearCurrentAbility(attacker); - defender.PlaySound(0x213); - defender.FixedParticles(0x377A, 1, 32, 9949, 1153, 0, EffectLayer.Head); + attacker.SendLocalizedMessage(1060165); // You have delivered a concussion! + defender.SendLocalizedMessage(1060166); // You feel disoriented! - Effects.SendMovingParticles( - new Entity(Serial.Zero, new Point3D(defender.X, defender.Y, defender.Z + 10), defender.Map), - new Entity(Serial.Zero, new Point3D(defender.X, defender.Y, defender.Z + 20), defender.Map), 0x36FE, 1, 0, - false, false, 1133, 3, 9501, 1, 0, EffectLayer.Waist, 0x100); + defender.PlaySound(0x213); + defender.FixedParticles(0x377A, 1, 32, 9949, 1153, 0, EffectLayer.Head); - int damage = 10; // Base damage is 10. + Effects.SendMovingParticles( + new Entity(Serial.Zero, new Point3D(defender.X, defender.Y, defender.Z + 10), defender.Map), + new Entity(Serial.Zero, new Point3D(defender.X, defender.Y, defender.Z + 20), defender.Map), + 0x36FE, + 1, + 0, + false, + false, + 1133, + 3, + 9501, + 1, + 0, + EffectLayer.Waist, + 0x100 + ); - if (defender.HitsMax > 0) - { - double hitsPercent = defender.Hits / (double)defender.HitsMax * 100.0; + var damage = 10; // Base damage is 10. - double manaPercent = 0; + if (defender.HitsMax > 0) + { + var hitsPercent = defender.Hits / (double)defender.HitsMax * 100.0; - if (defender.ManaMax > 0) - manaPercent = defender.Mana / (double)defender.ManaMax * 100.0; + double manaPercent = 0; - damage += Math.Min((int)(Math.Abs(hitsPercent - manaPercent) / 4), 20); - } + if (defender.ManaMax > 0) + manaPercent = defender.Mana / (double)defender.ManaMax * 100.0; - // Total damage is 10 + (0~20) = 10~30, physical, non-resistable. + damage += Math.Min((int)(Math.Abs(hitsPercent - manaPercent) / 4), 20); + } - defender.Damage(damage, attacker); + // Total damage is 10 + (0~20) = 10~30, physical, non-resistable. - return true; + defender.Damage(damage, attacker); + + return true; + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Abilities/CrushingBlow.cs b/Projects/UOContent/Items/Weapons/Abilities/CrushingBlow.cs index fe32872da..5c5a2f482 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/CrushingBlow.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/CrushingBlow.cs @@ -1,30 +1,42 @@ namespace Server.Items { - /// - /// Also known as the Haymaker, this attack dramatically increases the damage done by a weapon reaching its mark. - /// - public class CrushingBlow : WeaponAbility - { - public override int BaseMana => 25; - public override double DamageScalar => 1.5; - - public override void OnHit(Mobile attacker, Mobile defender, int damage) + /// + /// Also known as the Haymaker, this attack dramatically increases the damage done by a weapon reaching its mark. + /// + public class CrushingBlow : WeaponAbility { - if (!Validate(attacker) || !CheckMana(attacker, true)) - return; + public override int BaseMana => 25; + public override double DamageScalar => 1.5; - ClearCurrentAbility(attacker); + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + if (!Validate(attacker) || !CheckMana(attacker, true)) + return; - attacker.SendLocalizedMessage(1060090); // You have delivered a crushing blow! - defender.SendLocalizedMessage(1060091); // You take extra damage from the crushing attack! + ClearCurrentAbility(attacker); - defender.PlaySound(0x1E1); - defender.FixedParticles(0, 1, 0, 9946, EffectLayer.Head); + attacker.SendLocalizedMessage(1060090); // You have delivered a crushing blow! + defender.SendLocalizedMessage(1060091); // You take extra damage from the crushing attack! - Effects.SendMovingParticles( - new Entity(Serial.Zero, new Point3D(defender.X, defender.Y, defender.Z + 50), defender.Map), - new Entity(Serial.Zero, new Point3D(defender.X, defender.Y, defender.Z + 20), defender.Map), 0xFB4, 1, 0, - false, false, 0, 3, 9501, 1, 0, EffectLayer.Head, 0x100); + defender.PlaySound(0x1E1); + defender.FixedParticles(0, 1, 0, 9946, EffectLayer.Head); + + Effects.SendMovingParticles( + new Entity(Serial.Zero, new Point3D(defender.X, defender.Y, defender.Z + 50), defender.Map), + new Entity(Serial.Zero, new Point3D(defender.X, defender.Y, defender.Z + 20), defender.Map), + 0xFB4, + 1, + 0, + false, + false, + 0, + 3, + 9501, + 1, + 0, + EffectLayer.Head, + 0x100 + ); + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Abilities/DefenseMastery.cs b/Projects/UOContent/Items/Weapons/Abilities/DefenseMastery.cs index 162370c41..c76a246d6 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/DefenseMastery.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/DefenseMastery.cs @@ -3,94 +3,97 @@ using System.Collections.Generic; namespace Server.Items { - /// - /// Raises your physical resistance for a short time while lowering your ability to inflict damage. Requires Bushido or - /// Ninjitsu skill. - /// - public class DefenseMastery : WeaponAbility - { - private static readonly Dictionary m_Table = new Dictionary(); - - public override int BaseMana => 30; - - public override bool CheckSkills(Mobile from) + /// + /// Raises your physical resistance for a short time while lowering your ability to inflict damage. Requires Bushido or + /// Ninjitsu skill. + /// + public class DefenseMastery : WeaponAbility { - if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0) - { - from.SendLocalizedMessage(1063347, - "50"); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack! - return false; - } + private static readonly Dictionary + m_Table = new Dictionary(); - return base.CheckSkills(from); + public override int BaseMana => 30; + + public override bool CheckSkills(Mobile from) + { + if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0) + { + from.SendLocalizedMessage( + 1063347, + "50" + ); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack! + return false; + } + + return base.CheckSkills(from); + } + + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + if (!Validate(attacker) || !CheckMana(attacker, true)) + return; + + ClearCurrentAbility(attacker); + + attacker.SendLocalizedMessage(1063353); // You perform a masterful defense! + + attacker.FixedParticles(0x375A, 1, 17, 0x7F2, 0x3E8, 0x3, EffectLayer.Waist); + + var modifier = + (int)(30.0 * + ((Math.Max(attacker.Skills.Bushido.Value, attacker.Skills.Ninjitsu.Value) - + 50.0) / 70.0)); + + if (m_Table.TryGetValue(attacker, out var info)) + EndDefense(info); + + var mod = new ResistanceMod(ResistanceType.Physical, 50 + modifier); + attacker.AddResistanceMod(mod); + + info = new DefenseMasteryInfo(attacker, 80 - modifier, mod); + info.m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(3.0), EndDefense, info); + + m_Table[attacker] = info; + + attacker.Delta(MobileDelta.WeaponDamage); + } + + public static bool GetMalus(Mobile targ, ref int damageMalus) + { + if (!m_Table.TryGetValue(targ, out var info)) + return false; + + damageMalus = info.m_DamageMalus; + return true; + } + + private static void EndDefense(DefenseMasteryInfo info) + { + if (info.m_Mod != null) + info.m_From.RemoveResistanceMod(info.m_Mod); + + info.m_Timer?.Stop(); + + // No message is sent to the player. + + m_Table.Remove(info.m_From); + + info.m_From.Delta(MobileDelta.WeaponDamage); + } + + private class DefenseMasteryInfo + { + public readonly int m_DamageMalus; + public readonly Mobile m_From; + public readonly ResistanceMod m_Mod; + public Timer m_Timer; + + public DefenseMasteryInfo(Mobile from, int damageMalus, ResistanceMod mod) + { + m_From = from; + m_DamageMalus = damageMalus; + m_Mod = mod; + } + } } - - public override void OnHit(Mobile attacker, Mobile defender, int damage) - { - if (!Validate(attacker) || !CheckMana(attacker, true)) - return; - - ClearCurrentAbility(attacker); - - attacker.SendLocalizedMessage(1063353); // You perform a masterful defense! - - attacker.FixedParticles(0x375A, 1, 17, 0x7F2, 0x3E8, 0x3, EffectLayer.Waist); - - int modifier = - (int)(30.0 * - ((Math.Max(attacker.Skills.Bushido.Value, attacker.Skills.Ninjitsu.Value) - - 50.0) / 70.0)); - - if (m_Table.TryGetValue(attacker, out DefenseMasteryInfo info)) - EndDefense(info); - - ResistanceMod mod = new ResistanceMod(ResistanceType.Physical, 50 + modifier); - attacker.AddResistanceMod(mod); - - info = new DefenseMasteryInfo(attacker, 80 - modifier, mod); - info.m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(3.0), EndDefense, info); - - m_Table[attacker] = info; - - attacker.Delta(MobileDelta.WeaponDamage); - } - - public static bool GetMalus(Mobile targ, ref int damageMalus) - { - if (!m_Table.TryGetValue(targ, out DefenseMasteryInfo info)) - return false; - - damageMalus = info.m_DamageMalus; - return true; - } - - private static void EndDefense(DefenseMasteryInfo info) - { - if (info.m_Mod != null) - info.m_From.RemoveResistanceMod(info.m_Mod); - - info.m_Timer?.Stop(); - - // No message is sent to the player. - - m_Table.Remove(info.m_From); - - info.m_From.Delta(MobileDelta.WeaponDamage); - } - - private class DefenseMasteryInfo - { - public readonly int m_DamageMalus; - public readonly Mobile m_From; - public readonly ResistanceMod m_Mod; - public Timer m_Timer; - - public DefenseMasteryInfo(Mobile from, int damageMalus, ResistanceMod mod) - { - m_From = from; - m_DamageMalus = damageMalus; - m_Mod = mod; - } - } - } } diff --git a/Projects/UOContent/Items/Weapons/Abilities/Disarm.cs b/Projects/UOContent/Items/Weapons/Abilities/Disarm.cs index bb0623545..75992cdd5 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/Disarm.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/Disarm.cs @@ -2,77 +2,77 @@ using System; namespace Server.Items { - /// - /// This attack allows you to disarm your foe. - /// Now in Age of Shadows, a successful Disarm leaves the victim unable to re-arm another weapon for several seconds. - /// - public class Disarm : WeaponAbility - { - public static readonly TimeSpan BlockEquipDuration = TimeSpan.FromSeconds(5.0); - - public override int BaseMana => 20; - - // No longer active in pub21: - /*public override bool CheckSkills( Mobile from ) + /// + /// This attack allows you to disarm your foe. + /// Now in Age of Shadows, a successful Disarm leaves the victim unable to re-arm another weapon for several seconds. + /// + public class Disarm : WeaponAbility { - if (!base.CheckSkills( from )) - return false; + public static readonly TimeSpan BlockEquipDuration = TimeSpan.FromSeconds(5.0); - if (!(from.Weapon is Fists)) - return true; + public override int BaseMana => 20; - Skill skill = from.Skills.ArmsLore; + // No longer active in pub21: + /*public override bool CheckSkills( Mobile from ) + { + if (!base.CheckSkills( from )) + return false; + + if (!(from.Weapon is Fists)) + return true; + + Skill skill = from.Skills.ArmsLore; + + if (skill?.Base >= 80.0) + return true; + + from.SendLocalizedMessage( 1061812 ); // You lack the required skill in armslore to perform that attack! + + return false; + }*/ - if (skill?.Base >= 80.0) - return true; + public override bool RequiresTactics(Mobile from) + { + if (!(from.Weapon is BaseWeapon weapon)) + return false; - from.SendLocalizedMessage( 1061812 ); // You lack the required skill in armslore to perform that attack! + return weapon.Skill != SkillName.Wrestling; + } - return false; - }*/ + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + if (!Validate(attacker)) + return; - public override bool RequiresTactics(Mobile from) - { - if (!(from.Weapon is BaseWeapon weapon)) - return false; + ClearCurrentAbility(attacker); - return weapon.Skill != SkillName.Wrestling; + var toDisarm = defender.FindItemOnLayer(Layer.OneHanded); + + if (toDisarm?.Movable == false) + toDisarm = defender.FindItemOnLayer(Layer.TwoHanded); + + var pack = defender.Backpack; + + if (pack == null || toDisarm?.Movable == false) + { + attacker.SendLocalizedMessage(1004001); // You cannot disarm your opponent. + } + else if (!Core.ML && toDisarm == null || toDisarm is BaseShield || toDisarm is Spellbook) + { + attacker.SendLocalizedMessage(1060849); // Your target is already unarmed! + } + else if (CheckMana(attacker, true)) + { + attacker.SendLocalizedMessage(1060092); // You disarm their weapon! + defender.SendLocalizedMessage(1060093); // Your weapon has been disarmed! + + defender.PlaySound(0x3B9); + defender.FixedParticles(0x37BE, 232, 25, 9948, EffectLayer.LeftHand); + + pack.DropItem(toDisarm); + + BaseWeapon.BlockEquip(defender, BlockEquipDuration); + } + } } - - public override void OnHit(Mobile attacker, Mobile defender, int damage) - { - if (!Validate(attacker)) - return; - - ClearCurrentAbility(attacker); - - Item toDisarm = defender.FindItemOnLayer(Layer.OneHanded); - - if (toDisarm?.Movable == false) - toDisarm = defender.FindItemOnLayer(Layer.TwoHanded); - - Container pack = defender.Backpack; - - if (pack == null || toDisarm?.Movable == false) - { - attacker.SendLocalizedMessage(1004001); // You cannot disarm your opponent. - } - else if ((!Core.ML && toDisarm == null) || toDisarm is BaseShield || toDisarm is Spellbook) - { - attacker.SendLocalizedMessage(1060849); // Your target is already unarmed! - } - else if (CheckMana(attacker, true)) - { - attacker.SendLocalizedMessage(1060092); // You disarm their weapon! - defender.SendLocalizedMessage(1060093); // Your weapon has been disarmed! - - defender.PlaySound(0x3B9); - defender.FixedParticles(0x37BE, 232, 25, 9948, EffectLayer.LeftHand); - - pack.DropItem(toDisarm); - - BaseWeapon.BlockEquip(defender, BlockEquipDuration); - } - } - } } diff --git a/Projects/UOContent/Items/Weapons/Abilities/Dismount.cs b/Projects/UOContent/Items/Weapons/Abilities/Dismount.cs index e69ddfe7e..cf71adf3b 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/Dismount.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/Dismount.cs @@ -4,90 +4,91 @@ using Server.Spells.Ninjitsu; namespace Server.Items { - /// - /// Perfect for the foot-soldier, the Dismount special attack can unseat a mounted opponent. - /// The fighter using this ability must be on his own two feet and not in the saddle of a steed - /// (with one exception: players may use a lance to dismount other players while mounted). - /// If it works, the target will be knocked off his own mount and will take some extra damage from the fall! - /// - public class Dismount : WeaponAbility - { - public static readonly TimeSpan RemountDelay = TimeSpan.FromSeconds(10.0); - - public override int BaseMana => 20; - - public override bool Validate(Mobile from) + /// + /// Perfect for the foot-soldier, the Dismount special attack can unseat a mounted opponent. + /// The fighter using this ability must be on his own two feet and not in the saddle of a steed + /// (with one exception: players may use a lance to dismount other players while mounted). + /// If it works, the target will be knocked off his own mount and will take some extra damage from the fall! + /// + public class Dismount : WeaponAbility { - if (!base.Validate(from)) - return false; + public static readonly TimeSpan RemountDelay = TimeSpan.FromSeconds(10.0); - if (from.Mounted && !(from.Weapon is Lance)) - { - from.SendLocalizedMessage(1061283); // You cannot perform that attack while mounted! - return false; - } + public override int BaseMana => 20; - return true; + public override bool Validate(Mobile from) + { + if (!base.Validate(from)) + return false; + + if (from.Mounted && !(from.Weapon is Lance)) + { + from.SendLocalizedMessage(1061283); // You cannot perform that attack while mounted! + return false; + } + + return true; + } + + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + if (!Validate(attacker)) + return; + + if (defender is ChaosDragoon || defender is ChaosDragoonElite) + return; + + if (attacker.Mounted && (!(attacker.Weapon is Lance) || !(defender.Weapon is Lance)) + ) // TODO: Should there be a message here? + return; + + ClearCurrentAbility(attacker); + + var mount = defender.Mount; + + if (mount == null && !AnimalForm.UnderTransformation(defender)) + { + attacker.SendLocalizedMessage(1060848); // This attack only works on mounted targets + return; + } + + if (!CheckMana(attacker, true)) + return; + + if (Core.ML && attacker is LesserHiryu && Utility.RandomDouble() <= 0.8) + return; // Lesser Hiryu have an 80% chance of missing this attack + + attacker.SendLocalizedMessage(1060082); // The force of your attack has dislodged them from their mount! + + if (attacker.Mounted) + defender.SendLocalizedMessage(1062315); // You fall off your mount! + else + defender.SendLocalizedMessage(1060083); // You fall off of your mount and take damage! + + defender.PlaySound(0x140); + defender.FixedParticles(0x3728, 10, 15, 9955, EffectLayer.Waist); + + if (defender is PlayerMobile mobile) + { + if (AnimalForm.UnderTransformation(mobile)) + mobile.SendLocalizedMessage(1114066, attacker.Name); // ~1_NAME~ knocked you out of animal form! + else if (mobile.Mounted) mobile.SendLocalizedMessage(1040023); // You have been knocked off of your mount! + + mobile.SetMountBlock(BlockMountType.Dazed, TimeSpan.FromSeconds(10), true); + } + else + { + defender.Mount.Rider = null; + } + + if (attacker is PlayerMobile playerMobile) + playerMobile.SetMountBlock(BlockMountType.DismountRecovery, RemountDelay, true); + else if (Core.ML && attacker is BaseCreature bc) + if (bc.ControlMaster is PlayerMobile pm) + pm.SetMountBlock(BlockMountType.DismountRecovery, RemountDelay, false); + + if (!attacker.Mounted) + AOS.Damage(defender, attacker, Utility.RandomMinMax(15, 25), 100, 0, 0, 0, 0); + } } - - public override void OnHit(Mobile attacker, Mobile defender, int damage) - { - if (!Validate(attacker)) - return; - - if (defender is ChaosDragoon || defender is ChaosDragoonElite) - return; - - if (attacker.Mounted && (!(attacker.Weapon is Lance) || !(defender.Weapon is Lance))) // TODO: Should there be a message here? - return; - - ClearCurrentAbility(attacker); - - IMount mount = defender.Mount; - - if (mount == null && !AnimalForm.UnderTransformation(defender)) - { - attacker.SendLocalizedMessage(1060848); // This attack only works on mounted targets - return; - } - - if (!CheckMana(attacker, true)) - return; - - if (Core.ML && attacker is LesserHiryu && Utility.RandomDouble() <= 0.8) - return; // Lesser Hiryu have an 80% chance of missing this attack - - attacker.SendLocalizedMessage(1060082); // The force of your attack has dislodged them from their mount! - - if (attacker.Mounted) - defender.SendLocalizedMessage(1062315); // You fall off your mount! - else - defender.SendLocalizedMessage(1060083); // You fall off of your mount and take damage! - - defender.PlaySound(0x140); - defender.FixedParticles(0x3728, 10, 15, 9955, EffectLayer.Waist); - - if (defender is PlayerMobile mobile) - { - if (AnimalForm.UnderTransformation(mobile)) - mobile.SendLocalizedMessage(1114066, attacker.Name); // ~1_NAME~ knocked you out of animal form! - else if (mobile.Mounted) mobile.SendLocalizedMessage(1040023); // You have been knocked off of your mount! - - mobile.SetMountBlock(BlockMountType.Dazed, TimeSpan.FromSeconds(10), true); - } - else - { - defender.Mount.Rider = null; - } - - if (attacker is PlayerMobile playerMobile) - playerMobile.SetMountBlock(BlockMountType.DismountRecovery, RemountDelay, true); - else if (Core.ML && attacker is BaseCreature bc) - if (bc.ControlMaster is PlayerMobile pm) - pm.SetMountBlock(BlockMountType.DismountRecovery, RemountDelay, false); - - if (!attacker.Mounted) - AOS.Damage(defender, attacker, Utility.RandomMinMax(15, 25), 100, 0, 0, 0, 0); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Abilities/Disrobe.cs b/Projects/UOContent/Items/Weapons/Abilities/Disrobe.cs index c411514f1..fc97c1f99 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/Disrobe.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/Disrobe.cs @@ -2,44 +2,44 @@ using System; namespace Server.Items { - /// - /// This attack allows you to disrobe your foe. - /// - public class Disrobe : WeaponAbility - { - public static readonly TimeSpan BlockEquipDuration = TimeSpan.FromSeconds(5.0); - - public override int BaseMana => 20; // Not Sure what amount of mana a creature uses. - - public override void OnHit(Mobile attacker, Mobile defender, int damage) + /// + /// This attack allows you to disrobe your foe. + /// + public class Disrobe : WeaponAbility { - if (!Validate(attacker)) - return; + public static readonly TimeSpan BlockEquipDuration = TimeSpan.FromSeconds(5.0); - ClearCurrentAbility(attacker); - Item toDisrobe = defender.FindItemOnLayer(Layer.InnerTorso); + public override int BaseMana => 20; // Not Sure what amount of mana a creature uses. - if (toDisrobe?.Movable == false) - toDisrobe = defender.FindItemOnLayer(Layer.OuterTorso); + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + if (!Validate(attacker)) + return; - Container pack = defender.Backpack; + ClearCurrentAbility(attacker); + var toDisrobe = defender.FindItemOnLayer(Layer.InnerTorso); - if (pack == null || toDisrobe?.Movable == false) - { - attacker.SendLocalizedMessage(1004001); // You cannot disarm your opponent. - } - else if (CheckMana(attacker, true)) - { - // attacker.SendLocalizedMessage( 1060092 ); // You disarm their weapon! - defender.SendLocalizedMessage(1062002); // You can no longer wear your ~1_ARMOR~ + if (toDisrobe?.Movable == false) + toDisrobe = defender.FindItemOnLayer(Layer.OuterTorso); - defender.PlaySound(0x3B9); - // defender.FixedParticles( 0x37BE, 232, 25, 9948, EffectLayer.InnerTorso ); + var pack = defender.Backpack; - pack.DropItem(toDisrobe); + if (pack == null || toDisrobe?.Movable == false) + { + attacker.SendLocalizedMessage(1004001); // You cannot disarm your opponent. + } + else if (CheckMana(attacker, true)) + { + // attacker.SendLocalizedMessage( 1060092 ); // You disarm their weapon! + defender.SendLocalizedMessage(1062002); // You can no longer wear your ~1_ARMOR~ - BaseWeapon.BlockEquip(defender, BlockEquipDuration); - } + defender.PlaySound(0x3B9); + // defender.FixedParticles( 0x37BE, 232, 25, 9948, EffectLayer.InnerTorso ); + + pack.DropItem(toDisrobe); + + BaseWeapon.BlockEquip(defender, BlockEquipDuration); + } + } } - } } diff --git a/Projects/UOContent/Items/Weapons/Abilities/DoubleShot.cs b/Projects/UOContent/Items/Weapons/Abilities/DoubleShot.cs index ef16b31bb..30b458dcb 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/DoubleShot.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/DoubleShot.cs @@ -1,60 +1,62 @@ namespace Server.Items { - /// - /// Send two arrows flying at your opponent if you're mounted. Requires Bushido or Ninjitsu skill. - /// - public class DoubleShot : WeaponAbility - { - public override int BaseMana => 30; - - public override bool CheckSkills(Mobile from) + /// + /// Send two arrows flying at your opponent if you're mounted. Requires Bushido or Ninjitsu skill. + /// + public class DoubleShot : WeaponAbility { - if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0) - { - from.SendLocalizedMessage(1063347, - "50"); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack! - return false; - } + public override int BaseMana => 30; - return base.CheckSkills(from); + public override bool CheckSkills(Mobile from) + { + if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0) + { + from.SendLocalizedMessage( + 1063347, + "50" + ); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack! + return false; + } + + return base.CheckSkills(from); + } + + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + Use(attacker, defender); + } + + public override void OnMiss(Mobile attacker, Mobile defender) + { + Use(attacker, defender); + } + + public override bool Validate(Mobile from) + { + if (base.Validate(from)) + { + if (from.Mounted) + return true; + from.SendLocalizedMessage(1070770); // You can only execute this attack while mounted! + ClearCurrentAbility(from); + } + + return false; + } + + public void Use(Mobile attacker, Mobile defender) + { + if (!Validate(attacker) || !CheckMana(attacker, true) || attacker.Weapon == null) // sanity + return; + + ClearCurrentAbility(attacker); + + attacker.SendLocalizedMessage(1063348); // You launch two shots at once! + defender.SendLocalizedMessage(1063349); // You're attacked with a barrage of shots! + + defender.FixedParticles(0x37B9, 1, 19, 0x251D, EffectLayer.Waist); + + attacker.Weapon.OnSwing(attacker, defender); + } } - - public override void OnHit(Mobile attacker, Mobile defender, int damage) - { - Use(attacker, defender); - } - - public override void OnMiss(Mobile attacker, Mobile defender) - { - Use(attacker, defender); - } - - public override bool Validate(Mobile from) - { - if (base.Validate(from)) - { - if (from.Mounted) - return true; - from.SendLocalizedMessage(1070770); // You can only execute this attack while mounted! - ClearCurrentAbility(from); - } - - return false; - } - - public void Use(Mobile attacker, Mobile defender) - { - if (!Validate(attacker) || !CheckMana(attacker, true) || attacker.Weapon == null) // sanity - return; - - ClearCurrentAbility(attacker); - - attacker.SendLocalizedMessage(1063348); // You launch two shots at once! - defender.SendLocalizedMessage(1063349); // You're attacked with a barrage of shots! - - defender.FixedParticles(0x37B9, 1, 19, 0x251D, EffectLayer.Waist); - - attacker.Weapon.OnSwing(attacker, defender); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Abilities/DoubleStrike.cs b/Projects/UOContent/Items/Weapons/Abilities/DoubleStrike.cs index 2378200ed..d3eebd94b 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/DoubleStrike.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/DoubleStrike.cs @@ -1,46 +1,46 @@ namespace Server.Items { - /// - /// The highly skilled warrior can use this special attack to make two quick swings in succession. - /// Landing both blows would be devastating! - /// - public class DoubleStrike : WeaponAbility - { - public override int BaseMana => 30; - public override double DamageScalar => 0.9; - - public override void OnHit(Mobile attacker, Mobile defender, int damage) + /// + /// The highly skilled warrior can use this special attack to make two quick swings in succession. + /// Landing both blows would be devastating! + /// + public class DoubleStrike : WeaponAbility { - if (!Validate(attacker) || !CheckMana(attacker, true)) - return; + public override int BaseMana => 30; + public override double DamageScalar => 0.9; - ClearCurrentAbility(attacker); + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + if (!Validate(attacker) || !CheckMana(attacker, true)) + return; - attacker.SendLocalizedMessage(1060084); // You attack with lightning speed! - defender.SendLocalizedMessage(1060085); // Your attacker strikes with lightning speed! + ClearCurrentAbility(attacker); - defender.PlaySound(0x3BB); - defender.FixedEffect(0x37B9, 244, 25); + attacker.SendLocalizedMessage(1060084); // You attack with lightning speed! + defender.SendLocalizedMessage(1060085); // Your attacker strikes with lightning speed! - // Swing again: + defender.PlaySound(0x3BB); + defender.FixedEffect(0x37B9, 244, 25); - // If no combatant, wrong map, one of us is a ghost, or cannot see, or deleted, then stop combat - if (defender.Deleted || attacker.Deleted || defender.Map != attacker.Map || - !defender.Alive || !attacker.Alive || !attacker.CanSee(defender)) - { - attacker.Combatant = null; - return; - } + // Swing again: - IWeapon weapon = attacker.Weapon; + // If no combatant, wrong map, one of us is a ghost, or cannot see, or deleted, then stop combat + if (defender.Deleted || attacker.Deleted || defender.Map != attacker.Map || + !defender.Alive || !attacker.Alive || !attacker.CanSee(defender)) + { + attacker.Combatant = null; + return; + } - if (!(weapon != null && attacker.InRange(defender, weapon.MaxRange) && attacker.InLOS(defender))) - return; + var weapon = attacker.Weapon; - BaseWeapon.InDoubleStrike = true; - attacker.RevealingAction(); - attacker.NextCombatTime = Core.TickCount + (int)weapon.OnSwing(attacker, defender).TotalMilliseconds; - BaseWeapon.InDoubleStrike = false; + if (!(weapon != null && attacker.InRange(defender, weapon.MaxRange) && attacker.InLOS(defender))) + return; + + BaseWeapon.InDoubleStrike = true; + attacker.RevealingAction(); + attacker.NextCombatTime = Core.TickCount + (int)weapon.OnSwing(attacker, defender).TotalMilliseconds; + BaseWeapon.InDoubleStrike = false; + } } - } } diff --git a/Projects/UOContent/Items/Weapons/Abilities/DualWield.cs b/Projects/UOContent/Items/Weapons/Abilities/DualWield.cs index b7923e8c7..5d22cb0ad 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/DualWield.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/DualWield.cs @@ -3,68 +3,72 @@ using System.Collections.Generic; namespace Server.Items { - /// - /// Attack faster as you swing with both weapons. - /// - public class DualWield : WeaponAbility - { - public static Dictionary Registry { get; } = new Dictionary(); - - public override int BaseMana => 30; - - public override bool CheckSkills(Mobile from) + /// + /// Attack faster as you swing with both weapons. + /// + public class DualWield : WeaponAbility { - if (GetSkill(from, SkillName.Ninjitsu) < 50.0) - { - from.SendLocalizedMessage(1063352, - "50"); // You need ~1_SKILL_REQUIREMENT~ Ninjitsu skill to perform that attack! - return false; - } + public static Dictionary Registry { get; } = new Dictionary(); - return base.CheckSkills(from); + public override int BaseMana => 30; + + public override bool CheckSkills(Mobile from) + { + if (GetSkill(from, SkillName.Ninjitsu) < 50.0) + { + from.SendLocalizedMessage( + 1063352, + "50" + ); // You need ~1_SKILL_REQUIREMENT~ Ninjitsu skill to perform that attack! + return false; + } + + return base.CheckSkills(from); + } + + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + if (!Validate(attacker) || !CheckMana(attacker, true)) + return; + + if (Registry.TryGetValue(attacker, out var timer)) + { + timer.Stop(); + Registry.Remove(attacker); + } + + ClearCurrentAbility(attacker); + + attacker.SendLocalizedMessage(1063362); // You dually wield for increased speed! + attacker.FixedParticles(0x3779, 1, 15, 0x7F6, 0x3E8, 3, EffectLayer.LeftHand); + + timer = new DualWieldTimer( + attacker, + (int)(20.0 + 3.0 * (attacker.Skills.Ninjitsu.Value - 50.0) / 7.0) + ); // 20-50 % increase + + timer.Start(); + Registry.Add(attacker, timer); + } + + public class DualWieldTimer : Timer + { + private readonly Mobile m_Owner; + + public DualWieldTimer(Mobile owner, int bonusSwingSpeed) + : base(TimeSpan.FromSeconds(6.0)) + { + m_Owner = owner; + BonusSwingSpeed = bonusSwingSpeed; + Priority = TimerPriority.FiftyMS; + } + + public int BonusSwingSpeed { get; } + + protected override void OnTick() + { + Registry.Remove(m_Owner); + } + } } - - public override void OnHit(Mobile attacker, Mobile defender, int damage) - { - if (!Validate(attacker) || !CheckMana(attacker, true)) - return; - - if (Registry.TryGetValue(attacker, out DualWieldTimer timer)) - { - timer.Stop(); - Registry.Remove(attacker); - } - - ClearCurrentAbility(attacker); - - attacker.SendLocalizedMessage(1063362); // You dually wield for increased speed! - attacker.FixedParticles(0x3779, 1, 15, 0x7F6, 0x3E8, 3, EffectLayer.LeftHand); - - timer = new DualWieldTimer(attacker, - (int)(20.0 + 3.0 * (attacker.Skills.Ninjitsu.Value - 50.0) / 7.0)); // 20-50 % increase - - timer.Start(); - Registry.Add(attacker, timer); - } - - public class DualWieldTimer : Timer - { - private readonly Mobile m_Owner; - - public DualWieldTimer(Mobile owner, int bonusSwingSpeed) - : base(TimeSpan.FromSeconds(6.0)) - { - m_Owner = owner; - BonusSwingSpeed = bonusSwingSpeed; - Priority = TimerPriority.FiftyMS; - } - - public int BonusSwingSpeed { get; } - - protected override void OnTick() - { - Registry.Remove(m_Owner); - } - } - } } diff --git a/Projects/UOContent/Items/Weapons/Abilities/Feint.cs b/Projects/UOContent/Items/Weapons/Abilities/Feint.cs index 8f625ab40..1a6678b33 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/Feint.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/Feint.cs @@ -3,71 +3,77 @@ using System.Collections.Generic; namespace Server.Items { - /// - /// Gain a defensive advantage over your primary opponent for a short time. - /// - public class Feint : WeaponAbility - { - public static Dictionary Registry { get; } = new Dictionary(); - - public override int BaseMana => 30; - - public override bool CheckSkills(Mobile from) + /// + /// Gain a defensive advantage over your primary opponent for a short time. + /// + public class Feint : WeaponAbility { - if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0) - { - from.SendLocalizedMessage(1063347, - "50"); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack! - return false; - } + public static Dictionary Registry { get; } = new Dictionary(); - return base.CheckSkills(from); + public override int BaseMana => 30; + + public override bool CheckSkills(Mobile from) + { + if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0) + { + from.SendLocalizedMessage( + 1063347, + "50" + ); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack! + return false; + } + + return base.CheckSkills(from); + } + + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + if (!Validate(attacker) || !CheckMana(attacker, true)) + return; + + if (Registry.TryGetValue(defender, out var timer)) + { + timer.Stop(); + Registry.Remove(defender); + } + + ClearCurrentAbility(attacker); + + attacker.SendLocalizedMessage(1063360); // You baffle your target with a feint! + defender.SendLocalizedMessage(1063361); // You were deceived by an attacker's feint! + + attacker.FixedParticles(0x3728, 1, 13, 0x7F3, 0x962, 0, EffectLayer.Waist); + + timer = new FeintTimer( + defender, + (int)(20.0 + 3.0 * (Math.Max( + attacker.Skills.Ninjitsu.Value, + attacker.Skills.Bushido.Value + ) - 50.0) / 7.0) + ); // 20-50 % decrease + + timer.Start(); + Registry.Add(defender, timer); + } + + public class FeintTimer : Timer + { + private readonly Mobile m_Defender; + + public FeintTimer(Mobile defender, int swingSpeedReduction) + : base(TimeSpan.FromSeconds(6.0)) + { + m_Defender = defender; + SwingSpeedReduction = swingSpeedReduction; + Priority = TimerPriority.FiftyMS; + } + + public int SwingSpeedReduction { get; } + + protected override void OnTick() + { + Registry.Remove(m_Defender); + } + } } - - public override void OnHit(Mobile attacker, Mobile defender, int damage) - { - if (!Validate(attacker) || !CheckMana(attacker, true)) - return; - - if (Registry.TryGetValue(defender, out FeintTimer timer)) - { - timer.Stop(); - Registry.Remove(defender); - } - - ClearCurrentAbility(attacker); - - attacker.SendLocalizedMessage(1063360); // You baffle your target with a feint! - defender.SendLocalizedMessage(1063361); // You were deceived by an attacker's feint! - - attacker.FixedParticles(0x3728, 1, 13, 0x7F3, 0x962, 0, EffectLayer.Waist); - - timer = new FeintTimer(defender, - (int)(20.0 + 3.0 * (Math.Max(attacker.Skills.Ninjitsu.Value, - attacker.Skills.Bushido.Value) - 50.0) / 7.0)); // 20-50 % decrease - - timer.Start(); - Registry.Add(defender, timer); - } - - public class FeintTimer : Timer - { - private readonly Mobile m_Defender; - - public FeintTimer(Mobile defender, int swingSpeedReduction) - : base(TimeSpan.FromSeconds(6.0)) - { - m_Defender = defender; - SwingSpeedReduction = swingSpeedReduction; - Priority = TimerPriority.FiftyMS; - } - - public int SwingSpeedReduction { get; } - - protected override void OnTick() - { - Registry.Remove(m_Defender); - } - } - } } diff --git a/Projects/UOContent/Items/Weapons/Abilities/FrenziedWhirlwind.cs b/Projects/UOContent/Items/Weapons/Abilities/FrenziedWhirlwind.cs index a52923743..42b005e61 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/FrenziedWhirlwind.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/FrenziedWhirlwind.cs @@ -5,129 +5,142 @@ using Server.Spells; namespace Server.Items { - /// - /// A quick attack to all enemies in range of your weapon that causes damage over time. Requires Bushido or Ninjitsu skill. - /// - public class FrenziedWhirlwind : WeaponAbility - { - public override int BaseMana => 30; - - public static Dictionary Registry { get; } = new Dictionary(); - - public override bool CheckSkills(Mobile from) + /// + /// A quick attack to all enemies in range of your weapon that causes damage over time. Requires Bushido or Ninjitsu skill. + /// + public class FrenziedWhirlwind : WeaponAbility { - if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0) - { - from.SendLocalizedMessage(1063347, - "50"); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack! - return false; - } + public override int BaseMana => 30; - return base.CheckSkills(from); - } + public static Dictionary Registry { get; } = + new Dictionary(); - public override void OnHit(Mobile attacker, Mobile defender, int damage) - { - if (!Validate(attacker)) // Mana check after check that there are targets - return; - - ClearCurrentAbility(attacker); - - Map map = attacker.Map; - - if (!(map != null && attacker.Weapon is BaseWeapon weapon)) - return; - - List targets = attacker.GetMobilesInRange(1).Where(m => - m?.Deleted == false && m != defender && m != attacker && SpellHelper.ValidIndirectTarget(attacker, m) && - m.Map == attacker.Map && m.Alive && attacker.CanSee(m) && attacker.CanBeHarmful(m) && - attacker.InRange(m, weapon.MaxRange) && attacker.InLOS(m)).ToList(); - - if (targets.Count == 0 || !CheckMana(attacker, true)) - return; - - attacker.FixedEffect(0x3728, 10, 15); - attacker.PlaySound(0x2A1); - - // 5-15 damage - int amount = (int)(10.0 * ((Math.Max(attacker.Skills.Bushido.Value, - attacker.Skills.Ninjitsu.Value) - 50.0) / 70.0 + 5)); - - for (int i = 0; i < targets.Count; ++i) - { - Mobile m = targets[i]; - attacker.DoHarmful(m, true); - - if (Registry.TryGetValue(m, out FrenziedWirlwindTimer timer)) + public override bool CheckSkills(Mobile from) { - timer.Stop(); - Registry.Remove(m); + if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0) + { + from.SendLocalizedMessage( + 1063347, + "50" + ); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack! + return false; + } + + return base.CheckSkills(from); } - timer = new FrenziedWirlwindTimer(attacker, m, amount); - timer.Start(); - Registry.Add(m, timer); - } - - Timer.DelayCall(TimeSpan.FromSeconds(2.0), RepeatEffect, attacker); - } - - private void RepeatEffect(Mobile attacker) - { - attacker.FixedEffect(0x3728, 10, 15); - attacker.PlaySound(0x2A1); - } - - public class FrenziedWirlwindTimer : Timer - { - private readonly double DamagePerTick; - private readonly Mobile m_Attacker; - private double m_DamageRemaining; - private double m_DamageToDo; - private readonly Mobile m_Defender; - - public FrenziedWirlwindTimer(Mobile attacker, Mobile defender, int totalDamage) - : base(TimeSpan.Zero, TimeSpan.FromSeconds(0.25), - 12) // 3 seconds at .25 seconds apart = 12. Confirm delay in between of .25 each. - { - m_Attacker = attacker; - m_Defender = defender; - - m_DamageRemaining = totalDamage; - DamagePerTick = (double)totalDamage / 12 + 0.01; - - Priority = TimerPriority.TwentyFiveMS; - } - - protected override void OnTick() - { - if (!m_Defender.Alive || m_DamageRemaining <= 0) + public override void OnHit(Mobile attacker, Mobile defender, int damage) { - Stop(); - Registry.Remove(m_Defender); - return; + if (!Validate(attacker)) // Mana check after check that there are targets + return; + + ClearCurrentAbility(attacker); + + var map = attacker.Map; + + if (!(map != null && attacker.Weapon is BaseWeapon weapon)) + return; + + var targets = attacker.GetMobilesInRange(1) + .Where( + m => + m?.Deleted == false && m != defender && m != attacker && + SpellHelper.ValidIndirectTarget(attacker, m) && + m.Map == attacker.Map && m.Alive && attacker.CanSee(m) && attacker.CanBeHarmful(m) && + attacker.InRange(m, weapon.MaxRange) && attacker.InLOS(m) + ) + .ToList(); + + if (targets.Count == 0 || !CheckMana(attacker, true)) + return; + + attacker.FixedEffect(0x3728, 10, 15); + attacker.PlaySound(0x2A1); + + // 5-15 damage + var amount = (int)(10.0 * ((Math.Max( + attacker.Skills.Bushido.Value, + attacker.Skills.Ninjitsu.Value + ) - 50.0) / 70.0 + 5)); + + for (var i = 0; i < targets.Count; ++i) + { + var m = targets[i]; + attacker.DoHarmful(m, true); + + if (Registry.TryGetValue(m, out var timer)) + { + timer.Stop(); + Registry.Remove(m); + } + + timer = new FrenziedWirlwindTimer(attacker, m, amount); + timer.Start(); + Registry.Add(m, timer); + } + + Timer.DelayCall(TimeSpan.FromSeconds(2.0), RepeatEffect, attacker); } - m_DamageRemaining -= DamagePerTick; - m_DamageToDo += DamagePerTick; - - if (m_DamageRemaining <= 0 && m_DamageToDo < 1) - m_DamageToDo = 1.0; // Confirm this 'round up' at the end - - int damage = (int)m_DamageToDo; - - if (damage > 0) + private void RepeatEffect(Mobile attacker) { - m_Defender.Damage(damage, m_Attacker); - m_DamageToDo -= damage; + attacker.FixedEffect(0x3728, 10, 15); + attacker.PlaySound(0x2A1); } - if (!m_Defender.Alive || m_DamageRemaining <= 0) + public class FrenziedWirlwindTimer : Timer { - Stop(); - Registry.Remove(m_Defender); + private readonly double DamagePerTick; + private readonly Mobile m_Attacker; + private readonly Mobile m_Defender; + private double m_DamageRemaining; + private double m_DamageToDo; + + public FrenziedWirlwindTimer(Mobile attacker, Mobile defender, int totalDamage) + : base( + TimeSpan.Zero, + TimeSpan.FromSeconds(0.25), + 12 + ) // 3 seconds at .25 seconds apart = 12. Confirm delay in between of .25 each. + { + m_Attacker = attacker; + m_Defender = defender; + + m_DamageRemaining = totalDamage; + DamagePerTick = (double)totalDamage / 12 + 0.01; + + Priority = TimerPriority.TwentyFiveMS; + } + + protected override void OnTick() + { + if (!m_Defender.Alive || m_DamageRemaining <= 0) + { + Stop(); + Registry.Remove(m_Defender); + return; + } + + m_DamageRemaining -= DamagePerTick; + m_DamageToDo += DamagePerTick; + + if (m_DamageRemaining <= 0 && m_DamageToDo < 1) + m_DamageToDo = 1.0; // Confirm this 'round up' at the end + + var damage = (int)m_DamageToDo; + + if (damage > 0) + { + m_Defender.Damage(damage, m_Attacker); + m_DamageToDo -= damage; + } + + if (!m_Defender.Alive || m_DamageRemaining <= 0) + { + Stop(); + Registry.Remove(m_Defender); + } + } } - } } - } } diff --git a/Projects/UOContent/Items/Weapons/Abilities/InfectiousStrike.cs b/Projects/UOContent/Items/Weapons/Abilities/InfectiousStrike.cs index e0c9c2ce0..20104f446 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/InfectiousStrike.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/InfectiousStrike.cs @@ -2,75 +2,76 @@ using System; namespace Server.Items { - /// - /// This special move represents a significant change to the use of poisons in Age of Shadows. - /// Now, only certain weapon types � those that have Infectious Strike as an available special move � will be able to be - /// poisoned. - /// Targets will no longer be poisoned at random when hit by poisoned weapons. - /// Instead, the wielder must use this ability to deliver the venom. - /// While no skill in Poisoning is directly required to use this ability, being knowledgeable in the application and use of - /// toxins - /// will allow a character to use Infectious Strike at reduced mana cost and with a chance to inflict more deadly poison on - /// his victim. - /// With this change, weapons will no longer be corroded by poison. - /// Level 5 poison will be possible when using this special move. - /// - public class InfectiousStrike : WeaponAbility - { - public override int BaseMana => 15; - - public override bool RequiresTactics(Mobile from) => false; - - public override void OnHit(Mobile attacker, Mobile defender, int damage) + /// + /// This special move represents a significant change to the use of poisons in Age of Shadows. + /// Now, only certain weapon types � those that have Infectious Strike as an available special move � will be able to be + /// poisoned. + /// Targets will no longer be poisoned at random when hit by poisoned weapons. + /// Instead, the wielder must use this ability to deliver the venom. + /// While no skill in Poisoning is directly required to use this ability, being knowledgeable in the application and use of + /// toxins + /// will allow a character to use Infectious Strike at reduced mana cost and with a chance to inflict more deadly poison on + /// his victim. + /// With this change, weapons will no longer be corroded by poison. + /// Level 5 poison will be possible when using this special move. + /// + public class InfectiousStrike : WeaponAbility { - if (!Validate(attacker)) - return; + public override int BaseMana => 15; - ClearCurrentAbility(attacker); + public override bool RequiresTactics(Mobile from) => false; - if (!(attacker.Weapon is BaseWeapon weapon)) - return; - - Poison p = weapon.Poison; - - if (p == null || weapon.PoisonCharges <= 0) - { - attacker.SendLocalizedMessage( - 1061141); // Your weapon must have a dose of poison to perform an infectious strike! - return; - } - - if (!CheckMana(attacker, true)) - return; - - --weapon.PoisonCharges; - - // Infectious strike special move now uses poisoning skill to help determine potency - int maxLevel = Math.Max(attacker.Skills.Poisoning.Fixed / 200, 0); - if (p.Level > maxLevel) p = Poison.GetPoison(maxLevel); - - if (attacker.Skills.Poisoning.Value / 100.0 > Utility.RandomDouble()) - { - int level = p.Level + 1; - Poison newPoison = Poison.GetPoison(level); - - if (newPoison != null) + public override void OnHit(Mobile attacker, Mobile defender, int damage) { - p = newPoison; + if (!Validate(attacker)) + return; - attacker.SendLocalizedMessage(1060080); // Your precise strike has increased the level of the poison by 1 - defender.SendLocalizedMessage(1060081); // The poison seems extra effective! + ClearCurrentAbility(attacker); + + if (!(attacker.Weapon is BaseWeapon weapon)) + return; + + var p = weapon.Poison; + + if (p == null || weapon.PoisonCharges <= 0) + { + attacker.SendLocalizedMessage( + 1061141 + ); // Your weapon must have a dose of poison to perform an infectious strike! + return; + } + + if (!CheckMana(attacker, true)) + return; + + --weapon.PoisonCharges; + + // Infectious strike special move now uses poisoning skill to help determine potency + var maxLevel = Math.Max(attacker.Skills.Poisoning.Fixed / 200, 0); + if (p.Level > maxLevel) p = Poison.GetPoison(maxLevel); + + if (attacker.Skills.Poisoning.Value / 100.0 > Utility.RandomDouble()) + { + var level = p.Level + 1; + var newPoison = Poison.GetPoison(level); + + if (newPoison != null) + { + p = newPoison; + + attacker.SendLocalizedMessage(1060080); // Your precise strike has increased the level of the poison by 1 + defender.SendLocalizedMessage(1060081); // The poison seems extra effective! + } + } + + defender.PlaySound(0xDD); + defender.FixedParticles(0x3728, 244, 25, 9941, 1266, 0, EffectLayer.Waist); + + if (defender.ApplyPoison(attacker, p) != ApplyPoisonResult.Immune) + { + attacker.SendLocalizedMessage(1008096, true, defender.Name); // You have poisoned your target : + defender.SendLocalizedMessage(1008097, false, attacker.Name); // : poisoned you! + } } - } - - defender.PlaySound(0xDD); - defender.FixedParticles(0x3728, 244, 25, 9941, 1266, 0, EffectLayer.Waist); - - if (defender.ApplyPoison(attacker, p) != ApplyPoisonResult.Immune) - { - attacker.SendLocalizedMessage(1008096, true, defender.Name); // You have poisoned your target : - defender.SendLocalizedMessage(1008097, false, attacker.Name); // : poisoned you! - } } - } } diff --git a/Projects/UOContent/Items/Weapons/Abilities/MortalStrike.cs b/Projects/UOContent/Items/Weapons/Abilities/MortalStrike.cs index 0d7ad9fa2..bcf82f46a 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/MortalStrike.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/MortalStrike.cs @@ -3,76 +3,76 @@ using System.Collections.Generic; namespace Server.Items { - /// - /// The assassin's friend. - /// A successful Mortal Strike will render its victim unable to heal any damage for several seconds. - /// Use a gruesome follow-up to finish off your foe. - /// - public class MortalStrike : WeaponAbility - { - public static readonly TimeSpan PlayerDuration = TimeSpan.FromSeconds(6.0); - public static readonly TimeSpan NPCDuration = TimeSpan.FromSeconds(12.0); - - private static readonly Dictionary m_Table = new Dictionary(); - - public override int BaseMana => 30; - - public override void OnHit(Mobile attacker, Mobile defender, int damage) + /// + /// The assassin's friend. + /// A successful Mortal Strike will render its victim unable to heal any damage for several seconds. + /// Use a gruesome follow-up to finish off your foe. + /// + public class MortalStrike : WeaponAbility { - if (!Validate(attacker) || !CheckMana(attacker, true)) return; + public static readonly TimeSpan PlayerDuration = TimeSpan.FromSeconds(6.0); + public static readonly TimeSpan NPCDuration = TimeSpan.FromSeconds(12.0); - ClearCurrentAbility(attacker); + private static readonly Dictionary m_Table = new Dictionary(); - attacker.SendLocalizedMessage(1060086); // You deliver a mortal wound! - defender.SendLocalizedMessage(1060087); // You have been mortally wounded! + public override int BaseMana => 30; - defender.PlaySound(0x1E1); - defender.FixedParticles(0x37B9, 244, 25, 9944, 31, 0, EffectLayer.Waist); + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + if (!Validate(attacker) || !CheckMana(attacker, true)) return; - // Do not reset timer if one is already in place. - if (!IsWounded(defender)) - BeginWound(defender, defender.Player ? PlayerDuration : NPCDuration); + ClearCurrentAbility(attacker); + + attacker.SendLocalizedMessage(1060086); // You deliver a mortal wound! + defender.SendLocalizedMessage(1060087); // You have been mortally wounded! + + defender.PlaySound(0x1E1); + defender.FixedParticles(0x37B9, 244, 25, 9944, 31, 0, EffectLayer.Waist); + + // Do not reset timer if one is already in place. + if (!IsWounded(defender)) + BeginWound(defender, defender.Player ? PlayerDuration : NPCDuration); + } + + public static bool IsWounded(Mobile m) => m_Table.ContainsKey(m); + + public static void BeginWound(Mobile m, TimeSpan duration) + { + if (m_Table.TryGetValue(m, out var timer)) + timer?.Stop(); + + m_Table[m] = timer = new InternalTimer(m, duration); + timer.Start(); + + m.YellowHealthbar = true; + } + + public static void EndWound(Mobile m) + { + if (m_Table.TryGetValue(m, out var timer)) + { + timer.Stop(); + m_Table.Remove(m); + } + + m.YellowHealthbar = false; + m.SendLocalizedMessage(1060208); // You are no longer mortally wounded. + } + + private class InternalTimer : Timer + { + private readonly Mobile m_Mobile; + + public InternalTimer(Mobile m, TimeSpan duration) : base(duration) + { + m_Mobile = m; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + EndWound(m_Mobile); + } + } } - - public static bool IsWounded(Mobile m) => m_Table.ContainsKey(m); - - public static void BeginWound(Mobile m, TimeSpan duration) - { - if (m_Table.TryGetValue(m, out InternalTimer timer)) - timer?.Stop(); - - m_Table[m] = timer = new InternalTimer(m, duration); - timer.Start(); - - m.YellowHealthbar = true; - } - - public static void EndWound(Mobile m) - { - if (m_Table.TryGetValue(m, out InternalTimer timer)) - { - timer.Stop(); - m_Table.Remove(m); - } - - m.YellowHealthbar = false; - m.SendLocalizedMessage(1060208); // You are no longer mortally wounded. - } - - private class InternalTimer : Timer - { - private readonly Mobile m_Mobile; - - public InternalTimer(Mobile m, TimeSpan duration) : base(duration) - { - m_Mobile = m; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - EndWound(m_Mobile); - } - } - } } diff --git a/Projects/UOContent/Items/Weapons/Abilities/MovingShot.cs b/Projects/UOContent/Items/Weapons/Abilities/MovingShot.cs index 96a21f5c6..43cb45472 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/MovingShot.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/MovingShot.cs @@ -1,34 +1,35 @@ namespace Server.Items { - /// - /// Available on some crossbows, this special move allows archers to fire while on the move. - /// This shot is somewhat less accurate than normal, but the ability to fire while running is a clear advantage. - /// - public class MovingShot : WeaponAbility - { - public override int BaseMana => 15; - public override int AccuracyBonus => -25; - - public override bool ValidatesDuringHit => false; - - public override bool OnBeforeSwing(Mobile attacker, Mobile defender) => Validate(attacker) && CheckMana(attacker, true); - - public override void OnMiss(Mobile attacker, Mobile defender) + /// + /// Available on some crossbows, this special move allows archers to fire while on the move. + /// This shot is somewhat less accurate than normal, but the ability to fire while running is a clear advantage. + /// + public class MovingShot : WeaponAbility { - // Validates in OnSwing for accuracy scalar + public override int BaseMana => 15; + public override int AccuracyBonus => -25; - ClearCurrentAbility(attacker); + public override bool ValidatesDuringHit => false; - attacker.SendLocalizedMessage(1060089); // You fail to execute your special move + public override bool OnBeforeSwing(Mobile attacker, Mobile defender) => + Validate(attacker) && CheckMana(attacker, true); + + public override void OnMiss(Mobile attacker, Mobile defender) + { + // Validates in OnSwing for accuracy scalar + + ClearCurrentAbility(attacker); + + attacker.SendLocalizedMessage(1060089); // You fail to execute your special move + } + + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + // Validates in OnSwing for accuracy scalar + + ClearCurrentAbility(attacker); + + attacker.SendLocalizedMessage(1060216); // Your shot was successful + } } - - public override void OnHit(Mobile attacker, Mobile defender, int damage) - { - // Validates in OnSwing for accuracy scalar - - ClearCurrentAbility(attacker); - - attacker.SendLocalizedMessage(1060216); // Your shot was successful - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Abilities/NerveStrike.cs b/Projects/UOContent/Items/Weapons/Abilities/NerveStrike.cs index c323647fb..7759c6900 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/NerveStrike.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/NerveStrike.cs @@ -2,80 +2,99 @@ using System; namespace Server.Items { - /// - /// Does damage and paralyses your opponent for a short time. - /// - public class NerveStrike : WeaponAbility - { - public override int BaseMana => 30; - - public override bool CheckSkills(Mobile from) + /// + /// Does damage and paralyses your opponent for a short time. + /// + public class NerveStrike : WeaponAbility { - if (GetSkill(from, SkillName.Bushido) < 50.0) - { - from.SendLocalizedMessage(1070768, - "50"); // You need ~1_SKILL_REQUIREMENT~ Bushido skill to perform that attack! - return false; - } + public override int BaseMana => 30; - return base.CheckSkills(from); - } - - public override bool OnBeforeSwing(Mobile attacker, Mobile defender) - { - if (defender.Paralyzed) - { - attacker.SendLocalizedMessage(1061923); // The target is already frozen. - return false; - } - - return true; - } - - public override void OnHit(Mobile attacker, Mobile defender, int damage) - { - if (!Validate(attacker) || !CheckMana(attacker, true)) - return; - - ClearCurrentAbility(attacker); - - bool cantpara = Items.ParalyzingBlow.IsImmune(defender); - - if (cantpara) - { - attacker.SendLocalizedMessage(1070804); // Your target resists paralysis. - defender.SendLocalizedMessage(1070813); // You resist paralysis. - } - else - { - attacker.SendLocalizedMessage(1063356); // You cripple your target with a nerve strike! - defender.SendLocalizedMessage(1063357); // Your attacker dealt a crippling nerve strike! - } - - attacker.PlaySound(0x204); - defender.FixedEffect(0x376A, 9, 32); - defender.FixedParticles(0x37C4, 1, 8, 0x13AF, 0, 0, EffectLayer.Waist); - - if (Core.ML) - { - AOS.Damage(defender, attacker, - (int)(15.0 * (attacker.Skills.Bushido.Value - 50.0) / 70.0 + Utility.Random(10)), true, 100, - 0, 0, 0, 0); // 0-25 - - if (!cantpara && (150.0 / 7.0 + 4.0 * attacker.Skills.Bushido.Value / 7.0) / 100.0 > - Utility.RandomDouble()) + public override bool CheckSkills(Mobile from) { - defender.Paralyze(TimeSpan.FromSeconds(2.0)); - Items.ParalyzingBlow.BeginImmunity(defender, Items.ParalyzingBlow.FreezeDelayDuration); + if (GetSkill(from, SkillName.Bushido) < 50.0) + { + from.SendLocalizedMessage( + 1070768, + "50" + ); // You need ~1_SKILL_REQUIREMENT~ Bushido skill to perform that attack! + return false; + } + + return base.CheckSkills(from); + } + + public override bool OnBeforeSwing(Mobile attacker, Mobile defender) + { + if (defender.Paralyzed) + { + attacker.SendLocalizedMessage(1061923); // The target is already frozen. + return false; + } + + return true; + } + + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + if (!Validate(attacker) || !CheckMana(attacker, true)) + return; + + ClearCurrentAbility(attacker); + + var cantpara = Items.ParalyzingBlow.IsImmune(defender); + + if (cantpara) + { + attacker.SendLocalizedMessage(1070804); // Your target resists paralysis. + defender.SendLocalizedMessage(1070813); // You resist paralysis. + } + else + { + attacker.SendLocalizedMessage(1063356); // You cripple your target with a nerve strike! + defender.SendLocalizedMessage(1063357); // Your attacker dealt a crippling nerve strike! + } + + attacker.PlaySound(0x204); + defender.FixedEffect(0x376A, 9, 32); + defender.FixedParticles(0x37C4, 1, 8, 0x13AF, 0, 0, EffectLayer.Waist); + + if (Core.ML) + { + AOS.Damage( + defender, + attacker, + (int)(15.0 * (attacker.Skills.Bushido.Value - 50.0) / 70.0 + Utility.Random(10)), + true, + 100, + 0, + 0, + 0, + 0 + ); // 0-25 + + if (!cantpara && (150.0 / 7.0 + 4.0 * attacker.Skills.Bushido.Value / 7.0) / 100.0 > + Utility.RandomDouble()) + { + defender.Paralyze(TimeSpan.FromSeconds(2.0)); + Items.ParalyzingBlow.BeginImmunity(defender, Items.ParalyzingBlow.FreezeDelayDuration); + } + } + else if (!cantpara) + { + AOS.Damage( + defender, + attacker, + (int)(15.0 * (attacker.Skills.Bushido.Value - 50.0) / 70.0 + 10), + true, + 100, + 0, + 0, + 0, + 0 + ); // 10-25 + defender.Freeze(TimeSpan.FromSeconds(2.0)); + Items.ParalyzingBlow.BeginImmunity(defender, Items.ParalyzingBlow.FreezeDelayDuration); + } } - } - else if (!cantpara) - { - AOS.Damage(defender, attacker, (int)(15.0 * (attacker.Skills.Bushido.Value - 50.0) / 70.0 + 10), - true, 100, 0, 0, 0, 0); // 10-25 - defender.Freeze(TimeSpan.FromSeconds(2.0)); - Items.ParalyzingBlow.BeginImmunity(defender, Items.ParalyzingBlow.FreezeDelayDuration); - } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Abilities/ParalyzingBlow.cs b/Projects/UOContent/Items/Weapons/Abilities/ParalyzingBlow.cs index 93f8ef2f8..305f653ac 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/ParalyzingBlow.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/ParalyzingBlow.cs @@ -3,114 +3,115 @@ using System.Collections.Generic; namespace Server.Items { - /// - /// A successful Paralyzing Blow will leave the target stunned, unable to move, attack, or cast spells, for a few seconds. - /// - public class ParalyzingBlow : WeaponAbility - { - public static readonly TimeSpan PlayerFreezeDuration = TimeSpan.FromSeconds(3.0); - public static readonly TimeSpan NPCFreezeDuration = TimeSpan.FromSeconds(6.0); - - public static readonly TimeSpan FreezeDelayDuration = TimeSpan.FromSeconds(8.0); - - private static readonly Dictionary m_Table = new Dictionary(); - - public override int BaseMana => 30; - - // No longer active in pub21: - /*public override bool CheckSkills( Mobile from ) + /// + /// A successful Paralyzing Blow will leave the target stunned, unable to move, attack, or cast spells, for a few seconds. + /// + public class ParalyzingBlow : WeaponAbility { - if (!base.CheckSkills( from )) - return false; + public static readonly TimeSpan PlayerFreezeDuration = TimeSpan.FromSeconds(3.0); + public static readonly TimeSpan NPCFreezeDuration = TimeSpan.FromSeconds(6.0); - if (!(from.Weapon is Fists)) - return true; + public static readonly TimeSpan FreezeDelayDuration = TimeSpan.FromSeconds(8.0); - Skill skill = from.Skills.Anatomy; + private static readonly Dictionary m_Table = new Dictionary(); - if (skill?.Base >= 80.0) - return true; + public override int BaseMana => 30; - from.SendLocalizedMessage( 1061811 ); // You lack the required anatomy skill to perform that attack! + // No longer active in pub21: + /*public override bool CheckSkills( Mobile from ) + { + if (!base.CheckSkills( from )) + return false; + + if (!(from.Weapon is Fists)) + return true; + + Skill skill = from.Skills.Anatomy; + + if (skill?.Base >= 80.0) + return true; + + from.SendLocalizedMessage( 1061811 ); // You lack the required anatomy skill to perform that attack! + + return false; + }*/ - return false; - }*/ + public override bool RequiresTactics(Mobile from) => + !(from.Weapon is BaseWeapon weapon && weapon.Skill == SkillName.Wrestling); - public override bool RequiresTactics(Mobile from) => !(from.Weapon is BaseWeapon weapon && weapon.Skill == SkillName.Wrestling); + public override bool OnBeforeSwing(Mobile attacker, Mobile defender) + { + if (defender.Paralyzed) + { + attacker.SendLocalizedMessage(1061923); // The target is already frozen. + return false; + } - public override bool OnBeforeSwing(Mobile attacker, Mobile defender) - { - if (defender.Paralyzed) - { - attacker.SendLocalizedMessage(1061923); // The target is already frozen. - return false; - } + return true; + } - return true; + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + if (!Validate(attacker) || !CheckMana(attacker, true)) + return; + + ClearCurrentAbility(attacker); + + if (IsImmune(defender)) // Intentionally going after Mana consumption + { + attacker.SendLocalizedMessage(1070804); // Your target resists paralysis. + defender.SendLocalizedMessage(1070813); // You resist paralysis. + return; + } + + defender.FixedEffect(0x376A, 9, 32); + defender.PlaySound(0x204); + + attacker.SendLocalizedMessage(1060163); // You deliver a paralyzing blow! + defender.SendLocalizedMessage(1060164); // The attack has temporarily paralyzed you! + + var duration = defender.Player ? PlayerFreezeDuration : NPCFreezeDuration; + + // Treat it as paralyze not as freeze, effect must be removed when damaged. + defender.Paralyze(duration); + + BeginImmunity(defender, duration + FreezeDelayDuration); + } + + public static bool IsImmune(Mobile m) => m_Table.ContainsKey(m); + + public static void BeginImmunity(Mobile m, TimeSpan duration) + { + if (m_Table.TryGetValue(m, out var timer)) + timer?.Stop(); + + m_Table[m] = timer = new InternalTimer(m, duration); + timer.Start(); + } + + public static void EndImmunity(Mobile m) + { + if (m_Table.TryGetValue(m, out var timer)) + { + timer?.Stop(); + m_Table.Remove(m); + } + } + + private class InternalTimer : Timer + { + private readonly Mobile m_Mobile; + + public InternalTimer(Mobile m, TimeSpan duration) : base(duration) + { + m_Mobile = m; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + EndImmunity(m_Mobile); + } + } } - - public override void OnHit(Mobile attacker, Mobile defender, int damage) - { - if (!Validate(attacker) || !CheckMana(attacker, true)) - return; - - ClearCurrentAbility(attacker); - - if (IsImmune(defender)) // Intentionally going after Mana consumption - { - attacker.SendLocalizedMessage(1070804); // Your target resists paralysis. - defender.SendLocalizedMessage(1070813); // You resist paralysis. - return; - } - - defender.FixedEffect(0x376A, 9, 32); - defender.PlaySound(0x204); - - attacker.SendLocalizedMessage(1060163); // You deliver a paralyzing blow! - defender.SendLocalizedMessage(1060164); // The attack has temporarily paralyzed you! - - TimeSpan duration = defender.Player ? PlayerFreezeDuration : NPCFreezeDuration; - - // Treat it as paralyze not as freeze, effect must be removed when damaged. - defender.Paralyze(duration); - - BeginImmunity(defender, duration + FreezeDelayDuration); - } - - public static bool IsImmune(Mobile m) => m_Table.ContainsKey(m); - - public static void BeginImmunity(Mobile m, TimeSpan duration) - { - if (m_Table.TryGetValue(m, out InternalTimer timer)) - timer?.Stop(); - - m_Table[m] = timer = new InternalTimer(m, duration); - timer.Start(); - } - - public static void EndImmunity(Mobile m) - { - if (m_Table.TryGetValue(m, out InternalTimer timer)) - { - timer?.Stop(); - m_Table.Remove(m); - } - } - - private class InternalTimer : Timer - { - private readonly Mobile m_Mobile; - - public InternalTimer(Mobile m, TimeSpan duration) : base(duration) - { - m_Mobile = m; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - EndImmunity(m_Mobile); - } - } - } } diff --git a/Projects/UOContent/Items/Weapons/Abilities/RidingSwipe.cs b/Projects/UOContent/Items/Weapons/Abilities/RidingSwipe.cs index 54461dc7b..ea7a9c4f5 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/RidingSwipe.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/RidingSwipe.cs @@ -3,75 +3,85 @@ using Server.Mobiles; namespace Server.Items { - /// - /// If you are on foot, dismounts your opponent and damage the ethereal's rider or the - /// living mount(which must be healed before ridden again). If you are mounted, damages - /// and stuns the mounted opponent. - /// - public class RidingSwipe : WeaponAbility - { - public override int BaseMana => 30; - - public override bool RequiresSE => true; - - public override bool CheckSkills(Mobile from) + /// + /// If you are on foot, dismounts your opponent and damage the ethereal's rider or the + /// living mount(which must be healed before ridden again). If you are mounted, damages + /// and stuns the mounted opponent. + /// + public class RidingSwipe : WeaponAbility { - if (GetSkill(from, SkillName.Bushido) < 50.0) - { - from.SendLocalizedMessage(1070768, - "50"); // You need ~1_SKILL_REQUIREMENT~ Bushido skill to perform that attack! - return false; - } + public override int BaseMana => 30; - return base.CheckSkills(from); + public override bool RequiresSE => true; + + public override bool CheckSkills(Mobile from) + { + if (GetSkill(from, SkillName.Bushido) < 50.0) + { + from.SendLocalizedMessage( + 1070768, + "50" + ); // You need ~1_SKILL_REQUIREMENT~ Bushido skill to perform that attack! + return false; + } + + return base.CheckSkills(from); + } + + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + if (!defender.Mounted) + { + attacker.SendLocalizedMessage(1060848); // This attack only works on mounted targets + ClearCurrentAbility(attacker); + return; + } + + if (!Validate(attacker) || !CheckMana(attacker, true)) + return; + + ClearCurrentAbility(attacker); + + if (!attacker.Mounted) + { + var mount = defender.Mount as Mobile; + BaseMount.Dismount(defender); + + if (mount != null) // Ethy mounts don't take damage + { + var amount = 10 + (int)(10.0 * (attacker.Skills.Bushido.Value - 50.0) / 70.0 + 5); + + AOS.Damage( + mount, + null, + amount, + 100, + 0, + 0, + 0, + 0 + ); // The mount just takes damage, there's no flagging as if it was attacking the mount directly + + // TODO: Mount prevention until mount healed + } + } + else + { + var amount = 10 + (int)(10.0 * (attacker.Skills.Bushido.Value - 50.0) / 70.0 + 5); + + AOS.Damage(defender, attacker, amount, 100, 0, 0, 0, 0); + + if (Items.ParalyzingBlow.IsImmune(defender)) // Does it still do damage? + { + attacker.SendLocalizedMessage(1070804); // Your target resists paralysis. + defender.SendLocalizedMessage(1070813); // You resist paralysis. + } + else + { + defender.Paralyze(TimeSpan.FromSeconds(3.0)); + Items.ParalyzingBlow.BeginImmunity(defender, Items.ParalyzingBlow.FreezeDelayDuration); + } + } + } } - - public override void OnHit(Mobile attacker, Mobile defender, int damage) - { - if (!defender.Mounted) - { - attacker.SendLocalizedMessage(1060848); // This attack only works on mounted targets - ClearCurrentAbility(attacker); - return; - } - - if (!Validate(attacker) || !CheckMana(attacker, true)) - return; - - ClearCurrentAbility(attacker); - - if (!attacker.Mounted) - { - Mobile mount = defender.Mount as Mobile; - BaseMount.Dismount(defender); - - if (mount != null) // Ethy mounts don't take damage - { - int amount = 10 + (int)(10.0 * (attacker.Skills.Bushido.Value - 50.0) / 70.0 + 5); - - AOS.Damage(mount, null, amount, 100, 0, 0, 0, - 0); // The mount just takes damage, there's no flagging as if it was attacking the mount directly - - // TODO: Mount prevention until mount healed - } - } - else - { - int amount = 10 + (int)(10.0 * (attacker.Skills.Bushido.Value - 50.0) / 70.0 + 5); - - AOS.Damage(defender, attacker, amount, 100, 0, 0, 0, 0); - - if (Items.ParalyzingBlow.IsImmune(defender)) // Does it still do damage? - { - attacker.SendLocalizedMessage(1070804); // Your target resists paralysis. - defender.SendLocalizedMessage(1070813); // You resist paralysis. - } - else - { - defender.Paralyze(TimeSpan.FromSeconds(3.0)); - Items.ParalyzingBlow.BeginImmunity(defender, Items.ParalyzingBlow.FreezeDelayDuration); - } - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Abilities/ShadowStrike.cs b/Projects/UOContent/Items/Weapons/Abilities/ShadowStrike.cs index fbb59c3de..41b1d0713 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/ShadowStrike.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/ShadowStrike.cs @@ -1,51 +1,56 @@ namespace Server.Items { - /// - /// This powerful ability requires secondary skills to activate. - /// Successful use of Shadowstrike deals extra damage to the target � and renders the attacker invisible! - /// Only those who are adept at the art of stealth will be able to use this ability. - /// - public class ShadowStrike : WeaponAbility - { - public override int BaseMana => 20; - public override double DamageScalar => 1.25; - - public override bool RequiresTactics(Mobile from) => false; - - public override bool CheckSkills(Mobile from) + /// + /// This powerful ability requires secondary skills to activate. + /// Successful use of Shadowstrike deals extra damage to the target � and renders the attacker invisible! + /// Only those who are adept at the art of stealth will be able to use this ability. + /// + public class ShadowStrike : WeaponAbility { - if (!base.CheckSkills(from)) - return false; + public override int BaseMana => 20; + public override double DamageScalar => 1.25; - Skill skill = from.Skills.Stealth; + public override bool RequiresTactics(Mobile from) => false; - if (skill?.Value >= 80.0) - return true; + public override bool CheckSkills(Mobile from) + { + if (!base.CheckSkills(from)) + return false; - from.SendLocalizedMessage(1060183); // You lack the required stealth to perform that attack + var skill = from.Skills.Stealth; - return false; + if (skill?.Value >= 80.0) + return true; + + from.SendLocalizedMessage(1060183); // You lack the required stealth to perform that attack + + return false; + } + + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + if (!Validate(attacker) || !CheckMana(attacker, true)) + return; + + ClearCurrentAbility(attacker); + + attacker.SendLocalizedMessage(1060078); // You strike and hide in the shadows! + defender.SendLocalizedMessage(1060079); // You are dazed by the attack and your attacker vanishes! + + Effects.SendLocationParticles( + EffectItem.Create(attacker.Location, attacker.Map, EffectItem.DefaultDuration), + 0x376A, + 8, + 12, + 9943 + ); + attacker.PlaySound(0x482); + + defender.FixedEffect(0x37BE, 20, 25); + + attacker.Combatant = null; + attacker.Warmode = false; + attacker.Hidden = true; + } } - - public override void OnHit(Mobile attacker, Mobile defender, int damage) - { - if (!Validate(attacker) || !CheckMana(attacker, true)) - return; - - ClearCurrentAbility(attacker); - - attacker.SendLocalizedMessage(1060078); // You strike and hide in the shadows! - defender.SendLocalizedMessage(1060079); // You are dazed by the attack and your attacker vanishes! - - Effects.SendLocationParticles(EffectItem.Create(attacker.Location, attacker.Map, EffectItem.DefaultDuration), - 0x376A, 8, 12, 9943); - attacker.PlaySound(0x482); - - defender.FixedEffect(0x37BE, 20, 25); - - attacker.Combatant = null; - attacker.Warmode = false; - attacker.Hidden = true; - } - } } diff --git a/Projects/UOContent/Items/Weapons/Abilities/TalonStrike.cs b/Projects/UOContent/Items/Weapons/Abilities/TalonStrike.cs index f6b524c9e..9f748d1cd 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/TalonStrike.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/TalonStrike.cs @@ -3,96 +3,103 @@ using System.Collections.Generic; namespace Server.Items { - /// - /// Attack with increased damage with additional damage over time. - /// - public class TalonStrike : WeaponAbility - { - private static readonly HashSet m_Table = new HashSet(); - - public override int BaseMana => 30; - public override double DamageScalar => 1.2; - - public override bool CheckSkills(Mobile from) + /// + /// Attack with increased damage with additional damage over time. + /// + public class TalonStrike : WeaponAbility { - if (GetSkill(from, SkillName.Ninjitsu) < 50.0) - { - from.SendLocalizedMessage(1063352, - "50"); // You need ~1_SKILL_REQUIREMENT~ Ninjitsu skill to perform that attack! - return false; - } + private static readonly HashSet m_Table = new HashSet(); - return base.CheckSkills(from); - } + public override int BaseMana => 30; + public override double DamageScalar => 1.2; - public override void OnHit(Mobile attacker, Mobile defender, int damage) - { - if (m_Table.Contains(defender) || !Validate(attacker) || !CheckMana(attacker, true)) - return; - - ClearCurrentAbility(attacker); - - attacker.SendLocalizedMessage(1063358); // You deliver a talon strike! - defender.SendLocalizedMessage(1063359); // Your attacker delivers a talon strike! - - defender.FixedParticles(0x373A, 1, 17, 0x26BC, 0x662, 0, EffectLayer.Waist); - - InternalTimer timer = new InternalTimer(defender, - (int)(10.0 * (attacker.Skills.Ninjitsu.Value - 50.0) / 70.0 + 5)); // 5 - 15 damage - - timer.Start(); - - m_Table.Add(defender); - } - - private class InternalTimer : Timer - { - private readonly double DamagePerTick; - private double m_DamageRemaining; - private double m_DamageToDo; - private readonly Mobile m_Defender; - - public InternalTimer(Mobile defender, int totalDamage) - : base(TimeSpan.Zero, TimeSpan.FromSeconds(0.25), - 12) // 3 seconds at .25 seconds apart = 12. Confirm delay inbetween of .25 each. - { - m_Defender = defender; - m_DamageRemaining = totalDamage; - Priority = TimerPriority.TwentyFiveMS; - - DamagePerTick = (double)totalDamage / 12 + .01; - } - - protected override void OnTick() - { - if (!m_Defender.Alive || m_DamageRemaining <= 0) + public override bool CheckSkills(Mobile from) { - Stop(); - m_Table.Remove(m_Defender); - return; + if (GetSkill(from, SkillName.Ninjitsu) < 50.0) + { + from.SendLocalizedMessage( + 1063352, + "50" + ); // You need ~1_SKILL_REQUIREMENT~ Ninjitsu skill to perform that attack! + return false; + } + + return base.CheckSkills(from); } - m_DamageRemaining -= DamagePerTick; - m_DamageToDo += DamagePerTick; - - if (m_DamageRemaining <= 0 && m_DamageToDo < 1) - m_DamageToDo = 1.0; // Confirm this 'round up' at the end - - int damage = (int)m_DamageToDo; - - if (damage > 0) + public override void OnHit(Mobile attacker, Mobile defender, int damage) { - // m_Defender.Damage( damage, m_Attacker, false ); - m_Defender.Hits -= damage; // Don't show damage, don't disrupt - m_DamageToDo -= damage; + if (m_Table.Contains(defender) || !Validate(attacker) || !CheckMana(attacker, true)) + return; + + ClearCurrentAbility(attacker); + + attacker.SendLocalizedMessage(1063358); // You deliver a talon strike! + defender.SendLocalizedMessage(1063359); // Your attacker delivers a talon strike! + + defender.FixedParticles(0x373A, 1, 17, 0x26BC, 0x662, 0, EffectLayer.Waist); + + var timer = new InternalTimer( + defender, + (int)(10.0 * (attacker.Skills.Ninjitsu.Value - 50.0) / 70.0 + 5) + ); // 5 - 15 damage + + timer.Start(); + + m_Table.Add(defender); } - if (!m_Defender.Alive || m_DamageRemaining <= 0) + private class InternalTimer : Timer { - Stop(); - m_Table.Remove(m_Defender); + private readonly double DamagePerTick; + private readonly Mobile m_Defender; + private double m_DamageRemaining; + private double m_DamageToDo; + + public InternalTimer(Mobile defender, int totalDamage) + : base( + TimeSpan.Zero, + TimeSpan.FromSeconds(0.25), + 12 + ) // 3 seconds at .25 seconds apart = 12. Confirm delay inbetween of .25 each. + { + m_Defender = defender; + m_DamageRemaining = totalDamage; + Priority = TimerPriority.TwentyFiveMS; + + DamagePerTick = (double)totalDamage / 12 + .01; + } + + protected override void OnTick() + { + if (!m_Defender.Alive || m_DamageRemaining <= 0) + { + Stop(); + m_Table.Remove(m_Defender); + return; + } + + m_DamageRemaining -= DamagePerTick; + m_DamageToDo += DamagePerTick; + + if (m_DamageRemaining <= 0 && m_DamageToDo < 1) + m_DamageToDo = 1.0; // Confirm this 'round up' at the end + + var damage = (int)m_DamageToDo; + + if (damage > 0) + { + // m_Defender.Damage( damage, m_Attacker, false ); + m_Defender.Hits -= damage; // Don't show damage, don't disrupt + m_DamageToDo -= damage; + } + + if (!m_Defender.Alive || m_DamageRemaining <= 0) + { + Stop(); + m_Table.Remove(m_Defender); + } + } } - } } - } } diff --git a/Projects/UOContent/Items/Weapons/Abilities/WeaponAbility.cs b/Projects/UOContent/Items/Weapons/Abilities/WeaponAbility.cs index 29a7ac88d..d05a0766b 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/WeaponAbility.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/WeaponAbility.cs @@ -10,436 +10,446 @@ using Server.Spells.Ninjitsu; namespace Server.Items { - public abstract class WeaponAbility - { - public static WeaponAbility[] Abilities { get; } = { - null, - new ArmorIgnore(), - new BleedAttack(), - new ConcussionBlow(), - new CrushingBlow(), - new Disarm(), - new Dismount(), - new DoubleStrike(), - new InfectiousStrike(), - new MortalStrike(), - new MovingShot(), - new ParalyzingBlow(), - new ShadowStrike(), - new WhirlwindAttack(), - - new RidingSwipe(), - new FrenziedWhirlwind(), - new Block(), - new DefenseMastery(), - new NerveStrike(), - new TalonStrike(), - new Feint(), - new DualWield(), - new DoubleShot(), - new ArmorPierce(), - null, - null, - null, - null, - null, - null, - new Disrobe() - }; - - public static readonly WeaponAbility ArmorIgnore = Abilities[1]; - public static readonly WeaponAbility BleedAttack = Abilities[2]; - public static readonly WeaponAbility ConcussionBlow = Abilities[3]; - public static readonly WeaponAbility CrushingBlow = Abilities[4]; - public static readonly WeaponAbility Disarm = Abilities[5]; - public static readonly WeaponAbility Dismount = Abilities[6]; - public static readonly WeaponAbility DoubleStrike = Abilities[7]; - public static readonly WeaponAbility InfectiousStrike = Abilities[8]; - public static readonly WeaponAbility MortalStrike = Abilities[9]; - public static readonly WeaponAbility MovingShot = Abilities[10]; - public static readonly WeaponAbility ParalyzingBlow = Abilities[11]; - public static readonly WeaponAbility ShadowStrike = Abilities[12]; - public static readonly WeaponAbility WhirlwindAttack = Abilities[13]; - - public static readonly WeaponAbility RidingSwipe = Abilities[14]; - public static readonly WeaponAbility FrenziedWhirlwind = Abilities[15]; - public static readonly WeaponAbility Block = Abilities[16]; - public static readonly WeaponAbility DefenseMastery = Abilities[17]; - public static readonly WeaponAbility NerveStrike = Abilities[18]; - public static readonly WeaponAbility TalonStrike = Abilities[19]; - public static readonly WeaponAbility Feint = Abilities[20]; - public static readonly WeaponAbility DualWield = Abilities[21]; - public static readonly WeaponAbility DoubleShot = Abilities[22]; - public static readonly WeaponAbility ArmorPierce = Abilities[23]; - - public static readonly WeaponAbility Bladeweave = Abilities[24]; - public static readonly WeaponAbility ForceArrow = Abilities[25]; - public static readonly WeaponAbility LightningArrow = Abilities[26]; - public static readonly WeaponAbility PsychicAttack = Abilities[27]; - public static readonly WeaponAbility SerpentArrow = Abilities[28]; - public static readonly WeaponAbility ForceOfNature = Abilities[29]; - - public static readonly WeaponAbility Disrobe = Abilities[30]; - - private static readonly Dictionary m_PlayersTable = new Dictionary(); - - public virtual int BaseMana => 0; - - public virtual int AccuracyBonus => 0; - public virtual double DamageScalar => 1.0; - - public virtual bool RequiresSE => false; - - public static Dictionary Table { get; } = new Dictionary(); - - public virtual bool ValidatesDuringHit => true; - - public virtual void OnHit(Mobile attacker, Mobile defender, int damage) + public abstract class WeaponAbility { - } + public static readonly WeaponAbility ArmorIgnore = Abilities[1]; + public static readonly WeaponAbility BleedAttack = Abilities[2]; + public static readonly WeaponAbility ConcussionBlow = Abilities[3]; + public static readonly WeaponAbility CrushingBlow = Abilities[4]; + public static readonly WeaponAbility Disarm = Abilities[5]; + public static readonly WeaponAbility Dismount = Abilities[6]; + public static readonly WeaponAbility DoubleStrike = Abilities[7]; + public static readonly WeaponAbility InfectiousStrike = Abilities[8]; + public static readonly WeaponAbility MortalStrike = Abilities[9]; + public static readonly WeaponAbility MovingShot = Abilities[10]; + public static readonly WeaponAbility ParalyzingBlow = Abilities[11]; + public static readonly WeaponAbility ShadowStrike = Abilities[12]; + public static readonly WeaponAbility WhirlwindAttack = Abilities[13]; - public virtual void OnMiss(Mobile attacker, Mobile defender) - { - } + public static readonly WeaponAbility RidingSwipe = Abilities[14]; + public static readonly WeaponAbility FrenziedWhirlwind = Abilities[15]; + public static readonly WeaponAbility Block = Abilities[16]; + public static readonly WeaponAbility DefenseMastery = Abilities[17]; + public static readonly WeaponAbility NerveStrike = Abilities[18]; + public static readonly WeaponAbility TalonStrike = Abilities[19]; + public static readonly WeaponAbility Feint = Abilities[20]; + public static readonly WeaponAbility DualWield = Abilities[21]; + public static readonly WeaponAbility DoubleShot = Abilities[22]; + public static readonly WeaponAbility ArmorPierce = Abilities[23]; - public virtual bool OnBeforeSwing(Mobile attacker, Mobile defender) => true; + public static readonly WeaponAbility Bladeweave = Abilities[24]; + public static readonly WeaponAbility ForceArrow = Abilities[25]; + public static readonly WeaponAbility LightningArrow = Abilities[26]; + public static readonly WeaponAbility PsychicAttack = Abilities[27]; + public static readonly WeaponAbility SerpentArrow = Abilities[28]; + public static readonly WeaponAbility ForceOfNature = Abilities[29]; - public virtual bool OnBeforeDamage(Mobile attacker, Mobile defender) => true; + public static readonly WeaponAbility Disrobe = Abilities[30]; - public virtual bool RequiresTactics(Mobile from) => true; + private static readonly Dictionary m_PlayersTable = + new Dictionary(); - public virtual double GetRequiredSkill(Mobile from) - { - if (from.Weapon is BaseWeapon weapon) - { - if (weapon.PrimaryAbility == this) - return 70.0; - if (weapon.SecondaryAbility == this) - return 90.0; - } - - return 200.0; - } - - public virtual int CalculateMana(Mobile from) - { - int mana = BaseMana; - - double skillTotal = GetSkill(from, SkillName.Swords) + GetSkill(from, SkillName.Macing) - + GetSkill(from, SkillName.Fencing) + - GetSkill(from, SkillName.Archery) + - GetSkill(from, SkillName.Parry) - + GetSkill(from, SkillName.Lumberjacking) + - GetSkill(from, SkillName.Stealth) - + GetSkill(from, SkillName.Poisoning) + - GetSkill(from, SkillName.Bushido) + - GetSkill(from, SkillName.Ninjitsu); - - if (skillTotal >= 300.0) - mana -= 10; - else if (skillTotal >= 200.0) - mana -= 5; - - double scalar = 1.0; - if (!MindRotSpell.GetMindRotScalar(from, ref scalar)) - scalar = 1.0; - - // Lower Mana Cost = 40% - int lmc = Math.Min(AosAttributes.GetValue(from, AosAttribute.LowerManaCost), 40); - - scalar -= (double)lmc / 100; - mana = (int)(mana * scalar); - - // Using a special move within 3 seconds of the previous special move costs double mana - if (GetContext(from) != null) - mana *= 2; - - return mana; - } - - public virtual bool CheckWeaponSkill(Mobile from) - { - if (!(from.Weapon is BaseWeapon weapon)) - return false; - - Skill skill = from.Skills[weapon.Skill]; - double reqSkill = GetRequiredSkill(from); - bool reqTactics = Core.ML && RequiresTactics(from); - - if (Core.ML && reqTactics && from.Skills.Tactics.Base < reqSkill) - { - from.SendLocalizedMessage(1079308, - reqSkill.ToString()); // You need ~1_SKILL_REQUIREMENT~ weapon and tactics skill to perform that attack - return false; - } - - if (skill?.Base >= reqSkill) - return true; - - /* */ - if (weapon.WeaponAttributes.UseBestSkill > 0 && (from.Skills.Swords.Base >= reqSkill || - from.Skills.Macing.Base >= reqSkill || - from.Skills.Fencing.Base >= reqSkill)) - return true; - /* */ - - if (reqTactics) - from.SendLocalizedMessage(1079308, - reqSkill.ToString()); // You need ~1_SKILL_REQUIREMENT~ weapon and tactics skill to perform that attack - else - from.SendLocalizedMessage(1060182, - reqSkill.ToString()); // You need ~1_SKILL_REQUIREMENT~ weapon skill to perform that attack - - return false; - } - - public virtual bool CheckSkills(Mobile from) => CheckWeaponSkill(from); - - public virtual double GetSkill(Mobile from, SkillName skillName) => from.Skills[skillName]?.Value ?? 0.0; - - public virtual bool CheckMana(Mobile from, bool consume) - { - int mana = CalculateMana(from); - - if (from.Mana < mana) - { - if (from is BaseCreature creature && creature.HasManaOveride) return true; - - from.SendLocalizedMessage(1060181, - mana.ToString()); // You need ~1_MANA_REQUIREMENT~ mana to perform that attack - return false; - } - - if (consume) - { - if (GetContext(from) == null) + public static WeaponAbility[] Abilities { get; } = { - Timer timer = new WeaponAbilityTimer(from); - timer.Start(); + null, + new ArmorIgnore(), + new BleedAttack(), + new ConcussionBlow(), + new CrushingBlow(), + new Disarm(), + new Dismount(), + new DoubleStrike(), + new InfectiousStrike(), + new MortalStrike(), + new MovingShot(), + new ParalyzingBlow(), + new ShadowStrike(), + new WhirlwindAttack(), - AddContext(from, new WeaponAbilityContext(timer)); + new RidingSwipe(), + new FrenziedWhirlwind(), + new Block(), + new DefenseMastery(), + new NerveStrike(), + new TalonStrike(), + new Feint(), + new DualWield(), + new DoubleShot(), + new ArmorPierce(), + null, + null, + null, + null, + null, + null, + new Disrobe() + }; + + public virtual int BaseMana => 0; + + public virtual int AccuracyBonus => 0; + public virtual double DamageScalar => 1.0; + + public virtual bool RequiresSE => false; + + public static Dictionary Table { get; } = new Dictionary(); + + public virtual bool ValidatesDuringHit => true; + + public virtual void OnHit(Mobile attacker, Mobile defender, int damage) + { } - from.Mana -= mana; - } + public virtual void OnMiss(Mobile attacker, Mobile defender) + { + } - return true; + public virtual bool OnBeforeSwing(Mobile attacker, Mobile defender) => true; + + public virtual bool OnBeforeDamage(Mobile attacker, Mobile defender) => true; + + public virtual bool RequiresTactics(Mobile from) => true; + + public virtual double GetRequiredSkill(Mobile from) + { + if (from.Weapon is BaseWeapon weapon) + { + if (weapon.PrimaryAbility == this) + return 70.0; + if (weapon.SecondaryAbility == this) + return 90.0; + } + + return 200.0; + } + + public virtual int CalculateMana(Mobile from) + { + var mana = BaseMana; + + var skillTotal = GetSkill(from, SkillName.Swords) + GetSkill(from, SkillName.Macing) + + GetSkill(from, SkillName.Fencing) + + GetSkill(from, SkillName.Archery) + + GetSkill(from, SkillName.Parry) + + GetSkill(from, SkillName.Lumberjacking) + + GetSkill(from, SkillName.Stealth) + + GetSkill(from, SkillName.Poisoning) + + GetSkill(from, SkillName.Bushido) + + GetSkill(from, SkillName.Ninjitsu); + + if (skillTotal >= 300.0) + mana -= 10; + else if (skillTotal >= 200.0) + mana -= 5; + + var scalar = 1.0; + if (!MindRotSpell.GetMindRotScalar(from, ref scalar)) + scalar = 1.0; + + // Lower Mana Cost = 40% + var lmc = Math.Min(AosAttributes.GetValue(from, AosAttribute.LowerManaCost), 40); + + scalar -= (double)lmc / 100; + mana = (int)(mana * scalar); + + // Using a special move within 3 seconds of the previous special move costs double mana + if (GetContext(from) != null) + mana *= 2; + + return mana; + } + + public virtual bool CheckWeaponSkill(Mobile from) + { + if (!(from.Weapon is BaseWeapon weapon)) + return false; + + var skill = from.Skills[weapon.Skill]; + var reqSkill = GetRequiredSkill(from); + var reqTactics = Core.ML && RequiresTactics(from); + + if (Core.ML && reqTactics && from.Skills.Tactics.Base < reqSkill) + { + from.SendLocalizedMessage( + 1079308, + reqSkill.ToString() + ); // You need ~1_SKILL_REQUIREMENT~ weapon and tactics skill to perform that attack + return false; + } + + if (skill?.Base >= reqSkill) + return true; + + /* */ + if (weapon.WeaponAttributes.UseBestSkill > 0 && (from.Skills.Swords.Base >= reqSkill || + from.Skills.Macing.Base >= reqSkill || + from.Skills.Fencing.Base >= reqSkill)) + return true; + /* */ + + if (reqTactics) + from.SendLocalizedMessage( + 1079308, + reqSkill.ToString() + ); // You need ~1_SKILL_REQUIREMENT~ weapon and tactics skill to perform that attack + else + from.SendLocalizedMessage( + 1060182, + reqSkill.ToString() + ); // You need ~1_SKILL_REQUIREMENT~ weapon skill to perform that attack + + return false; + } + + public virtual bool CheckSkills(Mobile from) => CheckWeaponSkill(from); + + public virtual double GetSkill(Mobile from, SkillName skillName) => from.Skills[skillName]?.Value ?? 0.0; + + public virtual bool CheckMana(Mobile from, bool consume) + { + var mana = CalculateMana(from); + + if (from.Mana < mana) + { + if (from is BaseCreature creature && creature.HasManaOveride) return true; + + from.SendLocalizedMessage( + 1060181, + mana.ToString() + ); // You need ~1_MANA_REQUIREMENT~ mana to perform that attack + return false; + } + + if (consume) + { + if (GetContext(from) == null) + { + Timer timer = new WeaponAbilityTimer(from); + timer.Start(); + + AddContext(from, new WeaponAbilityContext(timer)); + } + + from.Mana -= mana; + } + + return true; + } + + public virtual bool Validate(Mobile from) + { + if (!from.Player) + return true; + + var state = from.NetState; + + if (state == null) + return false; + + if (RequiresSE && !state.SupportsExpansion(Expansion.SE)) + { + from.SendLocalizedMessage(1063456); // You must upgrade to Samurai Empire in order to use that ability. + return false; + } + + if (HonorableExecution.IsUnderPenalty(from) || AnimalForm.UnderTransformation(from)) + { + from.SendLocalizedMessage(1063024); // You cannot perform this special move right now. + return false; + } + + if (Core.ML && from.Spell != null) + { + from.SendLocalizedMessage(1063024); // You cannot perform this special move right now. + return false; + } + + string option = null; + + if (this is ArmorIgnore) + option = "Armor Ignore"; + else if (this is BleedAttack) + option = "Bleed Attack"; + else if (this is ConcussionBlow) + option = "Concussion Blow"; + else if (this is CrushingBlow) + option = "Crushing Blow"; + else if (this is Disarm) + option = "Disarm"; + else if (this is Dismount) + option = "Dismount"; + else if (this is DoubleStrike) + option = "Double Strike"; + else if (this is InfectiousStrike) + option = "Infectious Strike"; + else if (this is MortalStrike) + option = "Mortal Strike"; + else if (this is MovingShot) + option = "Moving Shot"; + else if (this is ParalyzingBlow) + option = "Paralyzing Blow"; + else if (this is ShadowStrike) + option = "Shadow Strike"; + else if (this is WhirlwindAttack) + option = "Whirlwind Attack"; + else if (this is RidingSwipe) + option = "Riding Swipe"; + else if (this is FrenziedWhirlwind) + option = "Frenzied Whirlwind"; + else if (this is Block) + option = "Block"; + else if (this is DefenseMastery) + option = "Defense Mastery"; + else if (this is NerveStrike) + option = "Nerve Strike"; + else if (this is TalonStrike) + option = "Talon Strike"; + else if (this is Feint) + option = "Feint"; + else if (this is DualWield) + option = "Dual Wield"; + else if (this is DoubleShot) + option = "Double Shot"; + else if (this is ArmorPierce) + option = "Armor Pierce"; + + if (option != null && !DuelContext.AllowSpecialAbility(from, option, true)) + return false; + + return CheckSkills(from) && CheckMana(from, false); + } + + public static bool IsWeaponAbility(Mobile m, WeaponAbility a) => + a == null || !m.Player || m.Weapon is BaseWeapon weapon && + (weapon.PrimaryAbility == a || weapon.SecondaryAbility == a); + + public static WeaponAbility GetCurrentAbility(Mobile m) + { + if (!Core.AOS) + { + ClearCurrentAbility(m); + return null; + } + + Table.TryGetValue(m, out var a); + + if (!IsWeaponAbility(m, a)) + { + ClearCurrentAbility(m); + return null; + } + + if (a?.ValidatesDuringHit == true && !a.Validate(m)) + { + ClearCurrentAbility(m); + return null; + } + + return a; + } + + public static bool SetCurrentAbility(Mobile m, WeaponAbility a) + { + if (!Core.AOS) + { + ClearCurrentAbility(m); + return false; + } + + if (!IsWeaponAbility(m, a)) + { + ClearCurrentAbility(m); + return false; + } + + if (a?.Validate(m) == false) + { + ClearCurrentAbility(m); + return false; + } + + if (a == null) + { + Table.Remove(m); + } + else + { + SpecialMove.ClearCurrentMove(m); + Table[m] = a; + } + + return true; + } + + public static void ClearCurrentAbility(Mobile m) + { + Table.Remove(m); + + if (Core.AOS && m.NetState != null) + m.Send(ClearWeaponAbility.Instance); + } + + public static void Initialize() + { + EventSink.SetAbility += EventSink_SetAbility; + } + + private static void EventSink_SetAbility(Mobile m, int index) + { + if (index == 0) + ClearCurrentAbility(m); + else if (index >= 1 && index < Abilities.Length) + SetCurrentAbility(m, Abilities[index]); + } + + private static void AddContext(Mobile m, WeaponAbilityContext context) + { + m_PlayersTable[m] = context; + } + + private static void RemoveContext(Mobile m) + { + var context = GetContext(m); + + if (context != null) + RemoveContext(m, context); + } + + private static void RemoveContext(Mobile m, WeaponAbilityContext context) + { + m_PlayersTable.Remove(m); + + context.Timer.Stop(); + } + + private static WeaponAbilityContext GetContext(Mobile m) + { + m_PlayersTable.TryGetValue(m, out var context); + return context; + } + + private class WeaponAbilityTimer : Timer + { + private readonly Mobile m_Mobile; + + public WeaponAbilityTimer(Mobile from) : base(TimeSpan.FromSeconds(3.0)) + { + m_Mobile = from; + + Priority = TimerPriority.TwentyFiveMS; + } + + protected override void OnTick() + { + RemoveContext(m_Mobile); + } + } + + private class WeaponAbilityContext + { + public WeaponAbilityContext(Timer timer) => Timer = timer; + + public Timer Timer { get; } + } } - - public virtual bool Validate(Mobile from) - { - if (!from.Player) - return true; - - NetState state = from.NetState; - - if (state == null) - return false; - - if (RequiresSE && !state.SupportsExpansion(Expansion.SE)) - { - from.SendLocalizedMessage(1063456); // You must upgrade to Samurai Empire in order to use that ability. - return false; - } - - if (HonorableExecution.IsUnderPenalty(from) || AnimalForm.UnderTransformation(from)) - { - from.SendLocalizedMessage(1063024); // You cannot perform this special move right now. - return false; - } - - if (Core.ML && from.Spell != null) - { - from.SendLocalizedMessage(1063024); // You cannot perform this special move right now. - return false; - } - - string option = null; - - if (this is ArmorIgnore) - option = "Armor Ignore"; - else if (this is BleedAttack) - option = "Bleed Attack"; - else if (this is ConcussionBlow) - option = "Concussion Blow"; - else if (this is CrushingBlow) - option = "Crushing Blow"; - else if (this is Disarm) - option = "Disarm"; - else if (this is Dismount) - option = "Dismount"; - else if (this is DoubleStrike) - option = "Double Strike"; - else if (this is InfectiousStrike) - option = "Infectious Strike"; - else if (this is MortalStrike) - option = "Mortal Strike"; - else if (this is MovingShot) - option = "Moving Shot"; - else if (this is ParalyzingBlow) - option = "Paralyzing Blow"; - else if (this is ShadowStrike) - option = "Shadow Strike"; - else if (this is WhirlwindAttack) - option = "Whirlwind Attack"; - else if (this is RidingSwipe) - option = "Riding Swipe"; - else if (this is FrenziedWhirlwind) - option = "Frenzied Whirlwind"; - else if (this is Block) - option = "Block"; - else if (this is DefenseMastery) - option = "Defense Mastery"; - else if (this is NerveStrike) - option = "Nerve Strike"; - else if (this is TalonStrike) - option = "Talon Strike"; - else if (this is Feint) - option = "Feint"; - else if (this is DualWield) - option = "Dual Wield"; - else if (this is DoubleShot) - option = "Double Shot"; - else if (this is ArmorPierce) - option = "Armor Pierce"; - - if (option != null && !DuelContext.AllowSpecialAbility(from, option, true)) - return false; - - return CheckSkills(from) && CheckMana(from, false); - } - - public static bool IsWeaponAbility(Mobile m, WeaponAbility a) => - a == null || !m.Player || m.Weapon is BaseWeapon weapon && - (weapon.PrimaryAbility == a || weapon.SecondaryAbility == a); - - public static WeaponAbility GetCurrentAbility(Mobile m) - { - if (!Core.AOS) - { - ClearCurrentAbility(m); - return null; - } - - Table.TryGetValue(m, out WeaponAbility a); - - if (!IsWeaponAbility(m, a)) - { - ClearCurrentAbility(m); - return null; - } - - if (a?.ValidatesDuringHit == true && !a.Validate(m)) - { - ClearCurrentAbility(m); - return null; - } - - return a; - } - - public static bool SetCurrentAbility(Mobile m, WeaponAbility a) - { - if (!Core.AOS) - { - ClearCurrentAbility(m); - return false; - } - - if (!IsWeaponAbility(m, a)) - { - ClearCurrentAbility(m); - return false; - } - - if (a?.Validate(m) == false) - { - ClearCurrentAbility(m); - return false; - } - - if (a == null) - { - Table.Remove(m); - } - else - { - SpecialMove.ClearCurrentMove(m); - Table[m] = a; - } - - return true; - } - - public static void ClearCurrentAbility(Mobile m) - { - Table.Remove(m); - - if (Core.AOS && m.NetState != null) - m.Send(ClearWeaponAbility.Instance); - } - - public static void Initialize() - { - EventSink.SetAbility += EventSink_SetAbility; - } - - private static void EventSink_SetAbility(Mobile m, int index) - { - if (index == 0) - ClearCurrentAbility(m); - else if (index >= 1 && index < Abilities.Length) - SetCurrentAbility(m, Abilities[index]); - } - - private static void AddContext(Mobile m, WeaponAbilityContext context) - { - m_PlayersTable[m] = context; - } - - private static void RemoveContext(Mobile m) - { - WeaponAbilityContext context = GetContext(m); - - if (context != null) - RemoveContext(m, context); - } - - private static void RemoveContext(Mobile m, WeaponAbilityContext context) - { - m_PlayersTable.Remove(m); - - context.Timer.Stop(); - } - - private static WeaponAbilityContext GetContext(Mobile m) - { - m_PlayersTable.TryGetValue(m, out WeaponAbilityContext context); - return context; - } - - private class WeaponAbilityTimer : Timer - { - private readonly Mobile m_Mobile; - - public WeaponAbilityTimer(Mobile from) : base(TimeSpan.FromSeconds(3.0)) - { - m_Mobile = from; - - Priority = TimerPriority.TwentyFiveMS; - } - - protected override void OnTick() - { - RemoveContext(m_Mobile); - } - } - - private class WeaponAbilityContext - { - public WeaponAbilityContext(Timer timer) => Timer = timer; - - public Timer Timer { get; } - } - } } diff --git a/Projects/UOContent/Items/Weapons/Abilities/WhirlwindAttack.cs b/Projects/UOContent/Items/Weapons/Abilities/WhirlwindAttack.cs index 5e8ea0126..1a6aff235 100644 --- a/Projects/UOContent/Items/Weapons/Abilities/WhirlwindAttack.cs +++ b/Projects/UOContent/Items/Weapons/Abilities/WhirlwindAttack.cs @@ -1,64 +1,68 @@ using System; -using System.Collections.Generic; using System.Linq; using Server.Spells; namespace Server.Items { - /// - /// A godsend to a warrior surrounded, the Whirlwind Attack allows the fighter to strike at all nearby targets in one mighty - /// spinning swing. - /// - public class WhirlwindAttack : WeaponAbility - { - public override int BaseMana => 15; - - public override void OnHit(Mobile attacker, Mobile defender, int damage) + /// + /// A godsend to a warrior surrounded, the Whirlwind Attack allows the fighter to strike at all nearby targets in one mighty + /// spinning swing. + /// + public class WhirlwindAttack : WeaponAbility { - if (!Validate(attacker)) - return; + public override int BaseMana => 15; - ClearCurrentAbility(attacker); + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + if (!Validate(attacker)) + return; - Map map = attacker.Map; + ClearCurrentAbility(attacker); - if (map == null) - return; + var map = attacker.Map; - if (!(attacker.Weapon is BaseWeapon weapon)) - return; + if (map == null) + return; - if (!CheckMana(attacker, true)) - return; + if (!(attacker.Weapon is BaseWeapon weapon)) + return; - attacker.FixedEffect(0x3728, 10, 15); - attacker.PlaySound(0x2A1); + if (!CheckMana(attacker, true)) + return; - List targets = attacker.GetMobilesInRange(1).Where(m => - m?.Deleted == false && m != defender && m != attacker && SpellHelper.ValidIndirectTarget(attacker, m) && - m.Map == attacker.Map && m.Alive && attacker.CanSee(m) && attacker.CanBeHarmful(m) && - attacker.InRange(m, weapon.MaxRange) && attacker.InLOS(m)).ToList(); + attacker.FixedEffect(0x3728, 10, 15); + attacker.PlaySound(0x2A1); - if (targets.Count <= 0) - return; + var targets = attacker.GetMobilesInRange(1) + .Where( + m => + m?.Deleted == false && m != defender && m != attacker && + SpellHelper.ValidIndirectTarget(attacker, m) && + m.Map == attacker.Map && m.Alive && attacker.CanSee(m) && attacker.CanBeHarmful(m) && + attacker.InRange(m, weapon.MaxRange) && attacker.InLOS(m) + ) + .ToList(); - double bushido = attacker.Skills.Bushido.Value; - double damageBonus = 1.0 + Math.Pow(targets.Count * bushido / 60, 2) / 100; + if (targets.Count <= 0) + return; - if (damageBonus > 2.0) - damageBonus = 2.0; + var bushido = attacker.Skills.Bushido.Value; + var damageBonus = 1.0 + Math.Pow(targets.Count * bushido / 60, 2) / 100; - attacker.RevealingAction(); + if (damageBonus > 2.0) + damageBonus = 2.0; - for (int i = 0; i < targets.Count; ++i) - { - Mobile m = targets[i]; + attacker.RevealingAction(); - attacker.SendLocalizedMessage(1060161); // The whirling attack strikes a target! - m.SendLocalizedMessage(1060162); // You are struck by the whirling attack and take damage! + for (var i = 0; i < targets.Count; ++i) + { + var m = targets[i]; - weapon.OnHit(attacker, m, damageBonus); - } + attacker.SendLocalizedMessage(1060161); // The whirling attack strikes a target! + m.SendLocalizedMessage(1060162); // You are struck by the whirling attack and take damage! + + weapon.OnHit(attacker, m, damageBonus); + } + } } - } } diff --git a/Projects/UOContent/Items/Weapons/Artifacts/AxeOfTheHeavens.cs b/Projects/UOContent/Items/Weapons/Artifacts/AxeOfTheHeavens.cs index 173ac373a..e4d44d802 100644 --- a/Projects/UOContent/Items/Weapons/Artifacts/AxeOfTheHeavens.cs +++ b/Projects/UOContent/Items/Weapons/Artifacts/AxeOfTheHeavens.cs @@ -1,39 +1,39 @@ namespace Server.Items { - public class AxeOfTheHeavens : DoubleAxe - { - [Constructible] - public AxeOfTheHeavens() + public class AxeOfTheHeavens : DoubleAxe { - Hue = 0x4D5; - WeaponAttributes.HitLightning = 50; - Attributes.AttackChance = 15; - Attributes.DefendChance = 15; - Attributes.WeaponDamage = 50; + [Constructible] + public AxeOfTheHeavens() + { + Hue = 0x4D5; + WeaponAttributes.HitLightning = 50; + Attributes.AttackChance = 15; + Attributes.DefendChance = 15; + Attributes.WeaponDamage = 50; + } + + public AxeOfTheHeavens(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061106; // Axe of the Heavens + public override int ArtifactRarity => 11; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } } - - public AxeOfTheHeavens(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061106; // Axe of the Heavens - public override int ArtifactRarity => 11; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Artifacts/BladeOfInsanity.cs b/Projects/UOContent/Items/Weapons/Artifacts/BladeOfInsanity.cs index 611fba15f..f31fc26fd 100644 --- a/Projects/UOContent/Items/Weapons/Artifacts/BladeOfInsanity.cs +++ b/Projects/UOContent/Items/Weapons/Artifacts/BladeOfInsanity.cs @@ -1,42 +1,42 @@ namespace Server.Items { - public class BladeOfInsanity : Katana - { - [Constructible] - public BladeOfInsanity() + public class BladeOfInsanity : Katana { - Hue = 0x76D; - WeaponAttributes.HitLeechStam = 100; - Attributes.RegenStam = 2; - Attributes.WeaponSpeed = 30; - Attributes.WeaponDamage = 50; + [Constructible] + public BladeOfInsanity() + { + Hue = 0x76D; + WeaponAttributes.HitLeechStam = 100; + Attributes.RegenStam = 2; + Attributes.WeaponSpeed = 30; + Attributes.WeaponDamage = 50; + } + + public BladeOfInsanity(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061088; // Blade of Insanity + public override int ArtifactRarity => 11; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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 == 0x44F) + Hue = 0x76D; + } } - - public BladeOfInsanity(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061088; // Blade of Insanity - public override int ArtifactRarity => 11; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Hue == 0x44F) - Hue = 0x76D; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Artifacts/BladeOfTheRighteous.cs b/Projects/UOContent/Items/Weapons/Artifacts/BladeOfTheRighteous.cs index 46eafda58..d8b91b904 100644 --- a/Projects/UOContent/Items/Weapons/Artifacts/BladeOfTheRighteous.cs +++ b/Projects/UOContent/Items/Weapons/Artifacts/BladeOfTheRighteous.cs @@ -1,44 +1,44 @@ namespace Server.Items { - public class BladeOfTheRighteous : Longsword - { - [Constructible] - public BladeOfTheRighteous() + public class BladeOfTheRighteous : Longsword { - Hue = 0x47E; - // Slayer = SlayerName.DaemonDismissal; - Slayer = SlayerName.Exorcism; - WeaponAttributes.HitLeechHits = 50; - WeaponAttributes.UseBestSkill = 1; - Attributes.BonusHits = 10; - Attributes.WeaponDamage = 50; + [Constructible] + public BladeOfTheRighteous() + { + Hue = 0x47E; + // Slayer = SlayerName.DaemonDismissal; + Slayer = SlayerName.Exorcism; + WeaponAttributes.HitLeechHits = 50; + WeaponAttributes.UseBestSkill = 1; + Attributes.BonusHits = 10; + Attributes.WeaponDamage = 50; + } + + public BladeOfTheRighteous(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061107; // Blade of the Righteous + public override int ArtifactRarity => 10; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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 (Slayer == SlayerName.None) + Slayer = SlayerName.Exorcism; + } } - - public BladeOfTheRighteous(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061107; // Blade of the Righteous - public override int ArtifactRarity => 10; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Slayer == SlayerName.None) - Slayer = SlayerName.Exorcism; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Artifacts/BoneCrusher.cs b/Projects/UOContent/Items/Weapons/Artifacts/BoneCrusher.cs index 997f78083..601fac496 100644 --- a/Projects/UOContent/Items/Weapons/Artifacts/BoneCrusher.cs +++ b/Projects/UOContent/Items/Weapons/Artifacts/BoneCrusher.cs @@ -1,45 +1,45 @@ namespace Server.Items { - public class BoneCrusher : WarMace - { - [Constructible] - public BoneCrusher() + public class BoneCrusher : WarMace { - ItemID = 0x1406; - Hue = 0x60C; - WeaponAttributes.HitLowerDefend = 50; - Attributes.BonusStr = 10; - Attributes.WeaponDamage = 75; + [Constructible] + public BoneCrusher() + { + ItemID = 0x1406; + Hue = 0x60C; + WeaponAttributes.HitLowerDefend = 50; + Attributes.BonusStr = 10; + Attributes.WeaponDamage = 75; + } + + public BoneCrusher(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061596; // Bone Crusher + public override int ArtifactRarity => 11; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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 == 0x604) + Hue = 0x60C; + + if (ItemID == 0x1407) + ItemID = 0x1406; + } } - - public BoneCrusher(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061596; // Bone Crusher - public override int ArtifactRarity => 11; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Hue == 0x604) - Hue = 0x60C; - - if (ItemID == 0x1407) - ItemID = 0x1406; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Artifacts/BreathOfTheDead.cs b/Projects/UOContent/Items/Weapons/Artifacts/BreathOfTheDead.cs index 10e69c6a2..3b6df5f6d 100644 --- a/Projects/UOContent/Items/Weapons/Artifacts/BreathOfTheDead.cs +++ b/Projects/UOContent/Items/Weapons/Artifacts/BreathOfTheDead.cs @@ -1,39 +1,39 @@ namespace Server.Items { - public class BreathOfTheDead : BoneHarvester - { - [Constructible] - public BreathOfTheDead() + public class BreathOfTheDead : BoneHarvester { - Hue = 0x455; - WeaponAttributes.HitLeechHits = 100; - WeaponAttributes.HitHarm = 25; - Attributes.SpellDamage = 5; - Attributes.WeaponDamage = 50; + [Constructible] + public BreathOfTheDead() + { + Hue = 0x455; + WeaponAttributes.HitLeechHits = 100; + WeaponAttributes.HitHarm = 25; + Attributes.SpellDamage = 5; + Attributes.WeaponDamage = 50; + } + + public BreathOfTheDead(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061109; // Breath of the Dead + public override int ArtifactRarity => 11; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } } - - public BreathOfTheDead(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061109; // Breath of the Dead - public override int ArtifactRarity => 11; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Artifacts/Frostbringer.cs b/Projects/UOContent/Items/Weapons/Artifacts/Frostbringer.cs index 33cdb8edd..375768f56 100644 --- a/Projects/UOContent/Items/Weapons/Artifacts/Frostbringer.cs +++ b/Projects/UOContent/Items/Weapons/Artifacts/Frostbringer.cs @@ -1,45 +1,47 @@ namespace Server.Items { - public class Frostbringer : Bow - { - [Constructible] - public Frostbringer() + public class Frostbringer : Bow { - Hue = 0x4F2; - WeaponAttributes.HitDispel = 50; - Attributes.RegenStam = 10; - Attributes.WeaponDamage = 50; + [Constructible] + public Frostbringer() + { + Hue = 0x4F2; + WeaponAttributes.HitDispel = 50; + Attributes.RegenStam = 10; + Attributes.WeaponDamage = 50; + } + + public Frostbringer(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061111; // Frostbringer + public override int ArtifactRarity => 11; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + phys = fire = pois = nrgy = chaos = direct = 0; + cold = 100; + } + + 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(); + } } - - public Frostbringer(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061111; // Frostbringer - public override int ArtifactRarity => 11; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - phys = fire = pois = nrgy = chaos = direct = 0; - cold = 100; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Artifacts/LegacyOfTheDreadLord.cs b/Projects/UOContent/Items/Weapons/Artifacts/LegacyOfTheDreadLord.cs index 6d461bc84..02ba7ee3d 100644 --- a/Projects/UOContent/Items/Weapons/Artifacts/LegacyOfTheDreadLord.cs +++ b/Projects/UOContent/Items/Weapons/Artifacts/LegacyOfTheDreadLord.cs @@ -1,45 +1,45 @@ namespace Server.Items { - public class LegacyOfTheDreadLord : Bardiche - { - [Constructible] - public LegacyOfTheDreadLord() + public class LegacyOfTheDreadLord : Bardiche { - Hue = 0x676; - Attributes.SpellChanneling = 1; - Attributes.CastRecovery = 3; - Attributes.WeaponSpeed = 30; - Attributes.WeaponDamage = 50; + [Constructible] + public LegacyOfTheDreadLord() + { + Hue = 0x676; + Attributes.SpellChanneling = 1; + Attributes.CastRecovery = 3; + Attributes.WeaponSpeed = 30; + Attributes.WeaponDamage = 50; + } + + public LegacyOfTheDreadLord(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1060860; // Legacy of the Dread Lord + public override int ArtifactRarity => 10; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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 (Attributes.CastSpeed == 3) + Attributes.CastRecovery = 3; + + if (Hue == 0x4B9) + Hue = 0x676; + } } - - public LegacyOfTheDreadLord(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1060860; // Legacy of the Dread Lord - public override int ArtifactRarity => 10; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Attributes.CastSpeed == 3) - Attributes.CastRecovery = 3; - - if (Hue == 0x4B9) - Hue = 0x676; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Artifacts/SerpentsFang.cs b/Projects/UOContent/Items/Weapons/Artifacts/SerpentsFang.cs index 7d21d85a6..8a8cad13d 100644 --- a/Projects/UOContent/Items/Weapons/Artifacts/SerpentsFang.cs +++ b/Projects/UOContent/Items/Weapons/Artifacts/SerpentsFang.cs @@ -1,51 +1,53 @@ namespace Server.Items { - public class SerpentsFang : Kryss - { - [Constructible] - public SerpentsFang() + public class SerpentsFang : Kryss { - ItemID = 0x1400; - Hue = 0x488; - WeaponAttributes.HitPoisonArea = 100; - WeaponAttributes.ResistPoisonBonus = 20; - Attributes.AttackChance = 15; - Attributes.WeaponDamage = 50; + [Constructible] + public SerpentsFang() + { + ItemID = 0x1400; + Hue = 0x488; + WeaponAttributes.HitPoisonArea = 100; + WeaponAttributes.ResistPoisonBonus = 20; + Attributes.AttackChance = 15; + Attributes.WeaponDamage = 50; + } + + public SerpentsFang(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061601; // Serpent's Fang + public override int ArtifactRarity => 11; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + fire = cold = nrgy = chaos = direct = 0; + phys = 25; + pois = 75; + } + + 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 (ItemID == 0x1401) + ItemID = 0x1400; + } } - - public SerpentsFang(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061601; // Serpent's Fang - public override int ArtifactRarity => 11; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - fire = cold = nrgy = chaos = direct = 0; - phys = 25; - pois = 75; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (ItemID == 0x1401) - ItemID = 0x1400; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Artifacts/StaffOfTheMagi.cs b/Projects/UOContent/Items/Weapons/Artifacts/StaffOfTheMagi.cs index a4b54731c..896964f10 100644 --- a/Projects/UOContent/Items/Weapons/Artifacts/StaffOfTheMagi.cs +++ b/Projects/UOContent/Items/Weapons/Artifacts/StaffOfTheMagi.cs @@ -1,52 +1,54 @@ namespace Server.Items { - public class StaffOfTheMagi : BlackStaff - { - [Constructible] - public StaffOfTheMagi() + public class StaffOfTheMagi : BlackStaff { - Hue = 0x481; - WeaponAttributes.MageWeapon = 30; - Attributes.SpellChanneling = 1; - Attributes.CastSpeed = 1; - Attributes.WeaponDamage = 50; + [Constructible] + public StaffOfTheMagi() + { + Hue = 0x481; + WeaponAttributes.MageWeapon = 30; + Attributes.SpellChanneling = 1; + Attributes.CastSpeed = 1; + Attributes.WeaponDamage = 50; + } + + public StaffOfTheMagi(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061600; // Staff of the Magi + public override int ArtifactRarity => 11; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + phys = fire = cold = pois = chaos = direct = 0; + nrgy = 100; + } + + 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 (WeaponAttributes.MageWeapon == 0) + WeaponAttributes.MageWeapon = 30; + + if (ItemID == 0xDF1) + ItemID = 0xDF0; + } } - - public StaffOfTheMagi(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061600; // Staff of the Magi - public override int ArtifactRarity => 11; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - phys = fire = cold = pois = chaos = direct = 0; - nrgy = 100; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (WeaponAttributes.MageWeapon == 0) - WeaponAttributes.MageWeapon = 30; - - if (ItemID == 0xDF1) - ItemID = 0xDF0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Artifacts/TheBeserkersMaul.cs b/Projects/UOContent/Items/Weapons/Artifacts/TheBeserkersMaul.cs index da26f8c1e..77b6ddeb6 100644 --- a/Projects/UOContent/Items/Weapons/Artifacts/TheBeserkersMaul.cs +++ b/Projects/UOContent/Items/Weapons/Artifacts/TheBeserkersMaul.cs @@ -1,37 +1,37 @@ namespace Server.Items { - public class TheBeserkersMaul : Maul - { - [Constructible] - public TheBeserkersMaul() + public class TheBeserkersMaul : Maul { - Hue = 0x21; - Attributes.WeaponSpeed = 75; - Attributes.WeaponDamage = 50; + [Constructible] + public TheBeserkersMaul() + { + Hue = 0x21; + Attributes.WeaponSpeed = 75; + Attributes.WeaponDamage = 50; + } + + public TheBeserkersMaul(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061108; // The Berserker's Maul + public override int ArtifactRarity => 11; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } } - - public TheBeserkersMaul(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061108; // The Berserker's Maul - public override int ArtifactRarity => 11; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Artifacts/TheDragonSlayer.cs b/Projects/UOContent/Items/Weapons/Artifacts/TheDragonSlayer.cs index 587e5f4ba..417c216f7 100644 --- a/Projects/UOContent/Items/Weapons/Artifacts/TheDragonSlayer.cs +++ b/Projects/UOContent/Items/Weapons/Artifacts/TheDragonSlayer.cs @@ -1,50 +1,52 @@ namespace Server.Items { - public class TheDragonSlayer : Lance - { - [Constructible] - public TheDragonSlayer() + public class TheDragonSlayer : Lance { - Hue = 0x530; - Slayer = SlayerName.DragonSlaying; - Attributes.Luck = 110; - Attributes.WeaponDamage = 50; - WeaponAttributes.ResistFireBonus = 20; - WeaponAttributes.UseBestSkill = 1; + [Constructible] + public TheDragonSlayer() + { + Hue = 0x530; + Slayer = SlayerName.DragonSlaying; + Attributes.Luck = 110; + Attributes.WeaponDamage = 50; + WeaponAttributes.ResistFireBonus = 20; + WeaponAttributes.UseBestSkill = 1; + } + + public TheDragonSlayer(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061248; // The Dragon Slayer + public override int ArtifactRarity => 11; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + phys = fire = cold = pois = chaos = direct = 0; + nrgy = 100; + } + + 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 (Slayer == SlayerName.None) + Slayer = SlayerName.DragonSlaying; + } } - - public TheDragonSlayer(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061248; // The Dragon Slayer - public override int ArtifactRarity => 11; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - phys = fire = cold = pois = chaos = direct = 0; - nrgy = 100; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Slayer == SlayerName.None) - Slayer = SlayerName.DragonSlaying; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Artifacts/TheDryadBow.cs b/Projects/UOContent/Items/Weapons/Artifacts/TheDryadBow.cs index 1de330007..d0ab56ee8 100644 --- a/Projects/UOContent/Items/Weapons/Artifacts/TheDryadBow.cs +++ b/Projects/UOContent/Items/Weapons/Artifacts/TheDryadBow.cs @@ -1,54 +1,54 @@ namespace Server.Items { - public class TheDryadBow : Bow - { - private static readonly SkillName[] m_PossibleBonusSkills = + public class TheDryadBow : Bow { - SkillName.Archery, - SkillName.Healing, - SkillName.MagicResist, - SkillName.Peacemaking, - SkillName.Chivalry, - SkillName.Ninjitsu - }; + private static readonly SkillName[] m_PossibleBonusSkills = + { + SkillName.Archery, + SkillName.Healing, + SkillName.MagicResist, + SkillName.Peacemaking, + SkillName.Chivalry, + SkillName.Ninjitsu + }; - [Constructible] - public TheDryadBow() - { - ItemID = 0x13B1; - Hue = 0x48F; - SkillBonuses.SetValues(0, m_PossibleBonusSkills.RandomElement(), Utility.Random(4) == 0 ? 10.0 : 5.0); - WeaponAttributes.SelfRepair = 5; - Attributes.WeaponSpeed = 50; - Attributes.WeaponDamage = 35; - WeaponAttributes.ResistPoisonBonus = 15; + [Constructible] + public TheDryadBow() + { + ItemID = 0x13B1; + Hue = 0x48F; + SkillBonuses.SetValues(0, m_PossibleBonusSkills.RandomElement(), Utility.Random(4) == 0 ? 10.0 : 5.0); + WeaponAttributes.SelfRepair = 5; + Attributes.WeaponSpeed = 50; + Attributes.WeaponDamage = 35; + WeaponAttributes.ResistPoisonBonus = 15; + } + + public TheDryadBow(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061090; // The Dryad Bow + public override int ArtifactRarity => 11; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version < 1) + SkillBonuses.SetValues(0, m_PossibleBonusSkills.RandomElement(), Utility.Random(4) == 0 ? 10.0 : 5.0); + } } - - public TheDryadBow(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061090; // The Dryad Bow - public override int ArtifactRarity => 11; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1) - SkillBonuses.SetValues(0, m_PossibleBonusSkills.RandomElement(), Utility.Random(4) == 0 ? 10.0 : 5.0); - } - } } diff --git a/Projects/UOContent/Items/Weapons/Artifacts/TheTaskmaster.cs b/Projects/UOContent/Items/Weapons/Artifacts/TheTaskmaster.cs index d44bbd884..a7ddc3fbe 100644 --- a/Projects/UOContent/Items/Weapons/Artifacts/TheTaskmaster.cs +++ b/Projects/UOContent/Items/Weapons/Artifacts/TheTaskmaster.cs @@ -1,46 +1,48 @@ namespace Server.Items { - public class TheTaskmaster : WarFork - { - [Constructible] - public TheTaskmaster() + public class TheTaskmaster : WarFork { - Hue = 0x4F8; - WeaponAttributes.HitPoisonArea = 100; - Attributes.BonusDex = 5; - Attributes.AttackChance = 15; - Attributes.WeaponDamage = 50; + [Constructible] + public TheTaskmaster() + { + Hue = 0x4F8; + WeaponAttributes.HitPoisonArea = 100; + Attributes.BonusDex = 5; + Attributes.AttackChance = 15; + Attributes.WeaponDamage = 50; + } + + public TheTaskmaster(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061110; // The Taskmaster + public override int ArtifactRarity => 10; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + phys = fire = cold = nrgy = chaos = direct = 0; + pois = 100; + } + + 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(); + } } - - public TheTaskmaster(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061110; // The Taskmaster - public override int ArtifactRarity => 10; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - phys = fire = cold = nrgy = chaos = direct = 0; - pois = 100; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Artifacts/TitansHammer.cs b/Projects/UOContent/Items/Weapons/Artifacts/TitansHammer.cs index d7308a676..6c010ea22 100644 --- a/Projects/UOContent/Items/Weapons/Artifacts/TitansHammer.cs +++ b/Projects/UOContent/Items/Weapons/Artifacts/TitansHammer.cs @@ -1,39 +1,39 @@ namespace Server.Items { - public class TitansHammer : WarHammer - { - [Constructible] - public TitansHammer() + public class TitansHammer : WarHammer { - Hue = 0x482; - WeaponAttributes.HitEnergyArea = 100; - Attributes.BonusStr = 15; - Attributes.AttackChance = 15; - Attributes.WeaponDamage = 50; + [Constructible] + public TitansHammer() + { + Hue = 0x482; + WeaponAttributes.HitEnergyArea = 100; + Attributes.BonusStr = 15; + Attributes.AttackChance = 15; + Attributes.WeaponDamage = 50; + } + + public TitansHammer(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1060024; // Titan's Hammer + public override int ArtifactRarity => 10; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + 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(); + } } - - public TitansHammer(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1060024; // Titan's Hammer - public override int ArtifactRarity => 10; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Artifacts/ZyronicClaw.cs b/Projects/UOContent/Items/Weapons/Artifacts/ZyronicClaw.cs index ab44d3913..90855b710 100644 --- a/Projects/UOContent/Items/Weapons/Artifacts/ZyronicClaw.cs +++ b/Projects/UOContent/Items/Weapons/Artifacts/ZyronicClaw.cs @@ -1,49 +1,51 @@ namespace Server.Items { - public class ZyronicClaw : ExecutionersAxe - { - [Constructible] - public ZyronicClaw() + public class ZyronicClaw : ExecutionersAxe { - Hue = 0x485; - Slayer = SlayerName.ElementalBan; - WeaponAttributes.HitLeechMana = 50; - Attributes.AttackChance = 30; - Attributes.WeaponDamage = 50; + [Constructible] + public ZyronicClaw() + { + Hue = 0x485; + Slayer = SlayerName.ElementalBan; + WeaponAttributes.HitLeechMana = 50; + Attributes.AttackChance = 30; + Attributes.WeaponDamage = 50; + } + + public ZyronicClaw(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061593; // Zyronic Claw + public override int ArtifactRarity => 10; + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + chaos = direct = 0; + phys = fire = cold = pois = nrgy = 20; + } + + 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 (Slayer == SlayerName.None) + Slayer = SlayerName.ElementalBan; + } } - - public ZyronicClaw(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061593; // Zyronic Claw - public override int ArtifactRarity => 10; - - public override int InitMinHits => 255; - public override int InitMaxHits => 255; - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - chaos = direct = 0; - phys = fire = cold = pois = nrgy = 20; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Slayer == SlayerName.None) - Slayer = SlayerName.ElementalBan; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Axes/Axe.cs b/Projects/UOContent/Items/Weapons/Axes/Axe.cs index 23bb66b57..6eb032e05 100644 --- a/Projects/UOContent/Items/Weapons/Axes/Axe.cs +++ b/Projects/UOContent/Items/Weapons/Axes/Axe.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0xF49, 0xF4a)] - public class Axe : BaseAxe - { - [Constructible] - public Axe() : base(0xF49) => Weight = 4.0; - - public Axe(Serial serial) : base(serial) + [Flippable(0xF49, 0xF4a)] + public class Axe : BaseAxe { + [Constructible] + public Axe() : base(0xF49) => Weight = 4.0; + + public Axe(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow; + public override WeaponAbility SecondaryAbility => WeaponAbility.Dismount; + + public override int AosStrengthReq => 35; + public override int AosMinDamage => 14; + public override int AosMaxDamage => 16; + public override int AosSpeed => 37; + public override float MlSpeed => 3.00f; + + public override int OldStrengthReq => 35; + public override int OldMinDamage => 6; + public override int OldMaxDamage => 33; + public override int OldSpeed => 37; + + public override int InitMinHits => 31; + public override int InitMaxHits => 110; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow; - public override WeaponAbility SecondaryAbility => WeaponAbility.Dismount; - - public override int AosStrengthReq => 35; - public override int AosMinDamage => 14; - public override int AosMaxDamage => 16; - public override int AosSpeed => 37; - public override float MlSpeed => 3.00f; - - public override int OldStrengthReq => 35; - public override int OldMinDamage => 6; - public override int OldMaxDamage => 33; - public override int OldSpeed => 37; - - public override int InitMinHits => 31; - public override int InitMaxHits => 110; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Axes/BaseAxe.cs b/Projects/UOContent/Items/Weapons/Axes/BaseAxe.cs index ebaea2f8c..cd9c69755 100644 --- a/Projects/UOContent/Items/Weapons/Axes/BaseAxe.cs +++ b/Projects/UOContent/Items/Weapons/Axes/BaseAxe.cs @@ -7,175 +7,181 @@ using Server.Network; namespace Server.Items { - public interface IAxe - { - bool Axe(Mobile from, BaseAxe axe); - } - - public abstract class BaseAxe : BaseMeleeWeapon - { - private bool m_ShowUsesRemaining; - - private int m_UsesRemaining; - - public BaseAxe(int itemID) : base(itemID) => m_UsesRemaining = 150; - - public BaseAxe(Serial serial) : base(serial) + public interface IAxe { + bool Axe(Mobile from, BaseAxe axe); } - public override int DefHitSound => 0x232; - public override int DefMissSound => 0x23A; - - public override SkillName DefSkill => SkillName.Swords; - public override WeaponType DefType => WeaponType.Axe; - public override WeaponAnimation DefAnimation => WeaponAnimation.Slash2H; - - public virtual HarvestSystem HarvestSystem => Lumberjacking.System; - - [CommandProperty(AccessLevel.GameMaster)] - public int UsesRemaining + public abstract class BaseAxe : BaseMeleeWeapon { - get => m_UsesRemaining; - set - { - m_UsesRemaining = value; - InvalidateProperties(); - } - } + private bool m_ShowUsesRemaining; - [CommandProperty(AccessLevel.GameMaster)] - public bool ShowUsesRemaining - { - get => m_ShowUsesRemaining; - set - { - m_ShowUsesRemaining = value; - InvalidateProperties(); - } - } + private int m_UsesRemaining; - public virtual int GetUsesScalar() - { - if (Quality == WeaponQuality.Exceptional) - return 200; + public BaseAxe(int itemID) : base(itemID) => m_UsesRemaining = 150; - return 100; - } - - public override void UnscaleDurability() - { - base.UnscaleDurability(); - - int scale = GetUsesScalar(); - - m_UsesRemaining = (m_UsesRemaining * 100 + (scale - 1)) / scale; - InvalidateProperties(); - } - - public override void ScaleDurability() - { - base.ScaleDurability(); - - int scale = GetUsesScalar(); - - m_UsesRemaining = (m_UsesRemaining * scale + 99) / 100; - InvalidateProperties(); - } - - public override void OnDoubleClick(Mobile from) - { - if (HarvestSystem == null || Deleted) - return; - - Point3D loc = GetWorldLocation(); - - if (!from.InLOS(loc) || !from.InRange(loc, 2)) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 1019045); // I can't reach that - return; - } - - if (!IsAccessibleTo(from)) - { - PublicOverheadMessage(MessageType.Regular, 0x3E9, 1061637); // You are not allowed to access this. - return; - } - - if (!(HarvestSystem is Mining)) - from.SendLocalizedMessage(1010018); // What do you want to use this item on? - - HarvestSystem.BeginHarvesting(from, this); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (HarvestSystem != null) - BaseHarvestTool.AddContextMenuEntries(from, this, list, HarvestSystem); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(2); // version - - writer.Write(m_ShowUsesRemaining); - - writer.Write(m_UsesRemaining); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 2: - { - m_ShowUsesRemaining = reader.ReadBool(); - goto case 1; - } - case 1: - { - m_UsesRemaining = reader.ReadInt(); - goto case 0; - } - case 0: - { - if (m_UsesRemaining < 1) - m_UsesRemaining = 150; - - break; - } - } - } - - public override void OnHit(Mobile attacker, Mobile defender, double damageBonus = 1) - { - base.OnHit(attacker, defender, damageBonus); - - if (!Core.AOS && (attacker.Player || attacker.Body.IsHuman) && Layer == Layer.TwoHanded && - attacker.Skills.Anatomy.Value >= 80 && - attacker.Skills.Anatomy.Value / 400.0 >= Utility.RandomDouble() && - DuelContext.AllowSpecialAbility(attacker, "Concussion Blow", false)) - { - StatMod mod = defender.GetStatMod("Concussion"); - - if (mod == null) + public BaseAxe(Serial serial) : base(serial) { - defender.SendMessage("You receive a concussion blow!"); - defender.AddStatMod(new StatMod(StatType.Int, "Concussion", -(defender.RawInt / 2), - TimeSpan.FromSeconds(30.0))); - - attacker.SendMessage("You deliver a concussion blow!"); - attacker.PlaySound(0x308); } - } + + public override int DefHitSound => 0x232; + public override int DefMissSound => 0x23A; + + public override SkillName DefSkill => SkillName.Swords; + public override WeaponType DefType => WeaponType.Axe; + public override WeaponAnimation DefAnimation => WeaponAnimation.Slash2H; + + public virtual HarvestSystem HarvestSystem => Lumberjacking.System; + + [CommandProperty(AccessLevel.GameMaster)] + public int UsesRemaining + { + get => m_UsesRemaining; + set + { + m_UsesRemaining = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool ShowUsesRemaining + { + get => m_ShowUsesRemaining; + set + { + m_ShowUsesRemaining = value; + InvalidateProperties(); + } + } + + public virtual int GetUsesScalar() + { + if (Quality == WeaponQuality.Exceptional) + return 200; + + return 100; + } + + public override void UnscaleDurability() + { + base.UnscaleDurability(); + + var scale = GetUsesScalar(); + + m_UsesRemaining = (m_UsesRemaining * 100 + (scale - 1)) / scale; + InvalidateProperties(); + } + + public override void ScaleDurability() + { + base.ScaleDurability(); + + var scale = GetUsesScalar(); + + m_UsesRemaining = (m_UsesRemaining * scale + 99) / 100; + InvalidateProperties(); + } + + public override void OnDoubleClick(Mobile from) + { + if (HarvestSystem == null || Deleted) + return; + + var loc = GetWorldLocation(); + + if (!from.InLOS(loc) || !from.InRange(loc, 2)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 1019045); // I can't reach that + return; + } + + if (!IsAccessibleTo(from)) + { + PublicOverheadMessage(MessageType.Regular, 0x3E9, 1061637); // You are not allowed to access this. + return; + } + + if (!(HarvestSystem is Mining)) + from.SendLocalizedMessage(1010018); // What do you want to use this item on? + + HarvestSystem.BeginHarvesting(from, this); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (HarvestSystem != null) + BaseHarvestTool.AddContextMenuEntries(from, this, list, HarvestSystem); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(2); // version + + writer.Write(m_ShowUsesRemaining); + + writer.Write(m_UsesRemaining); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 2: + { + m_ShowUsesRemaining = reader.ReadBool(); + goto case 1; + } + case 1: + { + m_UsesRemaining = reader.ReadInt(); + goto case 0; + } + case 0: + { + if (m_UsesRemaining < 1) + m_UsesRemaining = 150; + + break; + } + } + } + + public override void OnHit(Mobile attacker, Mobile defender, double damageBonus = 1) + { + base.OnHit(attacker, defender, damageBonus); + + if (!Core.AOS && (attacker.Player || attacker.Body.IsHuman) && Layer == Layer.TwoHanded && + attacker.Skills.Anatomy.Value >= 80 && + attacker.Skills.Anatomy.Value / 400.0 >= Utility.RandomDouble() && + DuelContext.AllowSpecialAbility(attacker, "Concussion Blow", false)) + { + var mod = defender.GetStatMod("Concussion"); + + if (mod == null) + { + defender.SendMessage("You receive a concussion blow!"); + defender.AddStatMod( + new StatMod( + StatType.Int, + "Concussion", + -(defender.RawInt / 2), + TimeSpan.FromSeconds(30.0) + ) + ); + + attacker.SendMessage("You deliver a concussion blow!"); + attacker.PlaySound(0x308); + } + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Axes/BattleAxe.cs b/Projects/UOContent/Items/Weapons/Axes/BattleAxe.cs index c30d0ab3f..4d9c994e8 100644 --- a/Projects/UOContent/Items/Weapons/Axes/BattleAxe.cs +++ b/Projects/UOContent/Items/Weapons/Axes/BattleAxe.cs @@ -1,48 +1,48 @@ namespace Server.Items { - [Flippable(0xF47, 0xF48)] - public class BattleAxe : BaseAxe - { - [Constructible] - public BattleAxe() : base(0xF47) + [Flippable(0xF47, 0xF48)] + public class BattleAxe : BaseAxe { - Weight = 4.0; - Layer = Layer.TwoHanded; + [Constructible] + public BattleAxe() : base(0xF47) + { + Weight = 4.0; + Layer = Layer.TwoHanded; + } + + public BattleAxe(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.BleedAttack; + public override WeaponAbility SecondaryAbility => WeaponAbility.ConcussionBlow; + + public override int AosStrengthReq => 35; + public override int AosMinDamage => 15; + public override int AosMaxDamage => 17; + public override int AosSpeed => 31; + public override float MlSpeed => 3.50f; + + public override int OldStrengthReq => 40; + public override int OldMinDamage => 6; + public override int OldMaxDamage => 38; + public override int OldSpeed => 30; + + public override int InitMinHits => 31; + public override int InitMaxHits => 70; + + 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 BattleAxe(Serial serial) : base(serial) - { - } - - public override WeaponAbility PrimaryAbility => WeaponAbility.BleedAttack; - public override WeaponAbility SecondaryAbility => WeaponAbility.ConcussionBlow; - - public override int AosStrengthReq => 35; - public override int AosMinDamage => 15; - public override int AosMaxDamage => 17; - public override int AosSpeed => 31; - public override float MlSpeed => 3.50f; - - public override int OldStrengthReq => 40; - public override int OldMinDamage => 6; - public override int OldMaxDamage => 38; - public override int OldSpeed => 30; - - public override int InitMinHits => 31; - public override int InitMaxHits => 70; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Axes/DoubleAxe.cs b/Projects/UOContent/Items/Weapons/Axes/DoubleAxe.cs index 541ce57d6..85127804c 100644 --- a/Projects/UOContent/Items/Weapons/Axes/DoubleAxe.cs +++ b/Projects/UOContent/Items/Weapons/Axes/DoubleAxe.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0xf4b, 0xf4c)] - public class DoubleAxe : BaseAxe - { - [Constructible] - public DoubleAxe() : base(0xF4B) => Weight = 8.0; - - public DoubleAxe(Serial serial) : base(serial) + [Flippable(0xf4b, 0xf4c)] + public class DoubleAxe : BaseAxe { + [Constructible] + public DoubleAxe() : base(0xF4B) => Weight = 8.0; + + public DoubleAxe(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike; + public override WeaponAbility SecondaryAbility => WeaponAbility.WhirlwindAttack; + + public override int AosStrengthReq => 45; + public override int AosMinDamage => 15; + public override int AosMaxDamage => 17; + public override int AosSpeed => 33; + public override float MlSpeed => 3.25f; + + public override int OldStrengthReq => 45; + public override int OldMinDamage => 5; + public override int OldMaxDamage => 35; + public override int OldSpeed => 37; + + public override int InitMinHits => 31; + public override int InitMaxHits => 110; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike; - public override WeaponAbility SecondaryAbility => WeaponAbility.WhirlwindAttack; - - public override int AosStrengthReq => 45; - public override int AosMinDamage => 15; - public override int AosMaxDamage => 17; - public override int AosSpeed => 33; - public override float MlSpeed => 3.25f; - - public override int OldStrengthReq => 45; - public override int OldMinDamage => 5; - public override int OldMaxDamage => 35; - public override int OldSpeed => 37; - - public override int InitMinHits => 31; - public override int InitMaxHits => 110; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Axes/ExecutionersAxe.cs b/Projects/UOContent/Items/Weapons/Axes/ExecutionersAxe.cs index 7e935cb5c..6ea68a138 100644 --- a/Projects/UOContent/Items/Weapons/Axes/ExecutionersAxe.cs +++ b/Projects/UOContent/Items/Weapons/Axes/ExecutionersAxe.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0xf45, 0xf46)] - public class ExecutionersAxe : BaseAxe - { - [Constructible] - public ExecutionersAxe() : base(0xF45) => Weight = 8.0; - - public ExecutionersAxe(Serial serial) : base(serial) + [Flippable(0xf45, 0xf46)] + public class ExecutionersAxe : BaseAxe { + [Constructible] + public ExecutionersAxe() : base(0xF45) => Weight = 8.0; + + public ExecutionersAxe(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.BleedAttack; + public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike; + + public override int AosStrengthReq => 40; + public override int AosMinDamage => 15; + public override int AosMaxDamage => 17; + public override int AosSpeed => 33; + public override float MlSpeed => 3.25f; + + public override int OldStrengthReq => 35; + public override int OldMinDamage => 6; + public override int OldMaxDamage => 33; + public override int OldSpeed => 37; + + public override int InitMinHits => 31; + public override int InitMaxHits => 70; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.BleedAttack; - public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike; - - public override int AosStrengthReq => 40; - public override int AosMinDamage => 15; - public override int AosMaxDamage => 17; - public override int AosSpeed => 33; - public override float MlSpeed => 3.25f; - - public override int OldStrengthReq => 35; - public override int OldMinDamage => 6; - public override int OldMaxDamage => 33; - public override int OldSpeed => 37; - - public override int InitMinHits => 31; - public override int InitMaxHits => 70; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Axes/GuardianAxe.cs b/Projects/UOContent/Items/Weapons/Axes/GuardianAxe.cs index ea8e9832e..9ff8c2463 100644 --- a/Projects/UOContent/Items/Weapons/Axes/GuardianAxe.cs +++ b/Projects/UOContent/Items/Weapons/Axes/GuardianAxe.cs @@ -1,32 +1,32 @@ namespace Server.Items { - public class GuardianAxe : OrnateAxe - { - [Constructible] - public GuardianAxe() + public class GuardianAxe : OrnateAxe { - Attributes.BonusHits = 4; - Attributes.RegenHits = 1; + [Constructible] + public GuardianAxe() + { + Attributes.BonusHits = 4; + Attributes.RegenHits = 1; + } + + public GuardianAxe(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073545; // guardian axe + + 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(); + } } - - public GuardianAxe(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073545; // guardian axe - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Axes/Hatchet.cs b/Projects/UOContent/Items/Weapons/Axes/Hatchet.cs index 8521236e6..b8176b202 100644 --- a/Projects/UOContent/Items/Weapons/Axes/Hatchet.cs +++ b/Projects/UOContent/Items/Weapons/Axes/Hatchet.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0xF43, 0xF44)] - public class Hatchet : BaseAxe - { - [Constructible] - public Hatchet() : base(0xF43) => Weight = 4.0; - - public Hatchet(Serial serial) : base(serial) + [Flippable(0xF43, 0xF44)] + public class Hatchet : BaseAxe { + [Constructible] + public Hatchet() : base(0xF43) => Weight = 4.0; + + public Hatchet(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore; + public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm; + + public override int AosStrengthReq => 20; + public override int AosMinDamage => 13; + public override int AosMaxDamage => 15; + public override int AosSpeed => 41; + public override float MlSpeed => 2.75f; + + public override int OldStrengthReq => 15; + public override int OldMinDamage => 2; + public override int OldMaxDamage => 17; + public override int OldSpeed => 40; + + public override int InitMinHits => 31; + public override int InitMaxHits => 80; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore; - public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm; - - public override int AosStrengthReq => 20; - public override int AosMinDamage => 13; - public override int AosMaxDamage => 15; - public override int AosSpeed => 41; - public override float MlSpeed => 2.75f; - - public override int OldStrengthReq => 15; - public override int OldMinDamage => 2; - public override int OldMaxDamage => 17; - public override int OldSpeed => 40; - - public override int InitMinHits => 31; - public override int InitMaxHits => 80; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Axes/HeavyOrnateAxe.cs b/Projects/UOContent/Items/Weapons/Axes/HeavyOrnateAxe.cs index d7a807eb6..62747e84d 100644 --- a/Projects/UOContent/Items/Weapons/Axes/HeavyOrnateAxe.cs +++ b/Projects/UOContent/Items/Weapons/Axes/HeavyOrnateAxe.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class HeavyOrnateAxe : OrnateAxe - { - [Constructible] - public HeavyOrnateAxe() => Attributes.WeaponDamage = 8; - - public HeavyOrnateAxe(Serial serial) : base(serial) + public class HeavyOrnateAxe : OrnateAxe { + [Constructible] + public HeavyOrnateAxe() => Attributes.WeaponDamage = 8; + + public HeavyOrnateAxe(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073548; // heavy ornate axe + + 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(); + } } - - public override int LabelNumber => 1073548; // heavy ornate axe - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Axes/LargeBattleAxe.cs b/Projects/UOContent/Items/Weapons/Axes/LargeBattleAxe.cs index 484a35ef3..3a67f9007 100644 --- a/Projects/UOContent/Items/Weapons/Axes/LargeBattleAxe.cs +++ b/Projects/UOContent/Items/Weapons/Axes/LargeBattleAxe.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0x13FB, 0x13FA)] - public class LargeBattleAxe : BaseAxe - { - [Constructible] - public LargeBattleAxe() : base(0x13FB) => Weight = 6.0; - - public LargeBattleAxe(Serial serial) : base(serial) + [Flippable(0x13FB, 0x13FA)] + public class LargeBattleAxe : BaseAxe { + [Constructible] + public LargeBattleAxe() : base(0x13FB) => Weight = 6.0; + + public LargeBattleAxe(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.WhirlwindAttack; + public override WeaponAbility SecondaryAbility => WeaponAbility.BleedAttack; + + public override int AosStrengthReq => 80; + public override int AosMinDamage => 16; + public override int AosMaxDamage => 17; + public override int AosSpeed => 29; + public override float MlSpeed => 3.75f; + + public override int OldStrengthReq => 40; + public override int OldMinDamage => 6; + public override int OldMaxDamage => 38; + public override int OldSpeed => 30; + + public override int InitMinHits => 31; + public override int InitMaxHits => 70; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.WhirlwindAttack; - public override WeaponAbility SecondaryAbility => WeaponAbility.BleedAttack; - - public override int AosStrengthReq => 80; - public override int AosMinDamage => 16; - public override int AosMaxDamage => 17; - public override int AosSpeed => 29; - public override float MlSpeed => 3.75f; - - public override int OldStrengthReq => 40; - public override int OldMinDamage => 6; - public override int OldMaxDamage => 38; - public override int OldSpeed => 30; - - public override int InitMinHits => 31; - public override int InitMaxHits => 70; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Axes/Pickaxe.cs b/Projects/UOContent/Items/Weapons/Axes/Pickaxe.cs index 762c53ed5..c795a88db 100644 --- a/Projects/UOContent/Items/Weapons/Axes/Pickaxe.cs +++ b/Projects/UOContent/Items/Weapons/Axes/Pickaxe.cs @@ -2,55 +2,55 @@ using Server.Engines.Harvest; namespace Server.Items { - [Flippable(0xE86, 0xE85)] - public class Pickaxe : BaseAxe, IUsesRemaining - { - [Constructible] - public Pickaxe() : base(0xE86) + [Flippable(0xE86, 0xE85)] + public class Pickaxe : BaseAxe, IUsesRemaining { - Weight = 11.0; - UsesRemaining = 50; - ShowUsesRemaining = true; + [Constructible] + public Pickaxe() : base(0xE86) + { + Weight = 11.0; + UsesRemaining = 50; + ShowUsesRemaining = true; + } + + public Pickaxe(Serial serial) : base(serial) + { + } + + public override HarvestSystem HarvestSystem => Mining.System; + + public override WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike; + public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm; + + public override int AosStrengthReq => 50; + public override int AosMinDamage => 13; + public override int AosMaxDamage => 15; + public override int AosSpeed => 35; + public override float MlSpeed => 3.00f; + + public override int OldStrengthReq => 25; + public override int OldMinDamage => 1; + public override int OldMaxDamage => 15; + public override int OldSpeed => 35; + + public override int InitMinHits => 31; + public override int InitMaxHits => 60; + + public override WeaponAnimation DefAnimation => WeaponAnimation.Slash1H; + + 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(); + ShowUsesRemaining = true; + } } - - public Pickaxe(Serial serial) : base(serial) - { - } - - public override HarvestSystem HarvestSystem => Mining.System; - - public override WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike; - public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm; - - public override int AosStrengthReq => 50; - public override int AosMinDamage => 13; - public override int AosMaxDamage => 15; - public override int AosSpeed => 35; - public override float MlSpeed => 3.00f; - - public override int OldStrengthReq => 25; - public override int OldMinDamage => 1; - public override int OldMaxDamage => 15; - public override int OldSpeed => 35; - - public override int InitMinHits => 31; - public override int InitMaxHits => 60; - - public override WeaponAnimation DefAnimation => WeaponAnimation.Slash1H; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - ShowUsesRemaining = true; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Axes/SingingAxe.cs b/Projects/UOContent/Items/Weapons/Axes/SingingAxe.cs index cdb74c076..77ec74b72 100644 --- a/Projects/UOContent/Items/Weapons/Axes/SingingAxe.cs +++ b/Projects/UOContent/Items/Weapons/Axes/SingingAxe.cs @@ -1,31 +1,31 @@ namespace Server.Items { - public class SingingAxe : OrnateAxe - { - [Constructible] - public SingingAxe() + public class SingingAxe : OrnateAxe { - SkillBonuses.SetValues(0, SkillName.Musicianship, 5); + [Constructible] + public SingingAxe() + { + SkillBonuses.SetValues(0, SkillName.Musicianship, 5); + } + + public SingingAxe(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073546; // singing axe + + 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(); + } } - - public SingingAxe(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073546; // singing axe - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Axes/ThunderingAxe.cs b/Projects/UOContent/Items/Weapons/Axes/ThunderingAxe.cs index 9f9299150..d98b42830 100644 --- a/Projects/UOContent/Items/Weapons/Axes/ThunderingAxe.cs +++ b/Projects/UOContent/Items/Weapons/Axes/ThunderingAxe.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class ThunderingAxe : OrnateAxe - { - [Constructible] - public ThunderingAxe() => WeaponAttributes.HitLightning = 10; - - public ThunderingAxe(Serial serial) : base(serial) + public class ThunderingAxe : OrnateAxe { + [Constructible] + public ThunderingAxe() => WeaponAttributes.HitLightning = 10; + + public ThunderingAxe(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073547; // thundering axe + + 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(); + } } - - public override int LabelNumber => 1073547; // thundering axe - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Axes/TwoHandedAxe.cs b/Projects/UOContent/Items/Weapons/Axes/TwoHandedAxe.cs index 6739b8606..8ccfa570f 100644 --- a/Projects/UOContent/Items/Weapons/Axes/TwoHandedAxe.cs +++ b/Projects/UOContent/Items/Weapons/Axes/TwoHandedAxe.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0x1443, 0x1442)] - public class TwoHandedAxe : BaseAxe - { - [Constructible] - public TwoHandedAxe() : base(0x1443) => Weight = 8.0; - - public TwoHandedAxe(Serial serial) : base(serial) + [Flippable(0x1443, 0x1442)] + public class TwoHandedAxe : BaseAxe { + [Constructible] + public TwoHandedAxe() : base(0x1443) => Weight = 8.0; + + public TwoHandedAxe(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike; + public override WeaponAbility SecondaryAbility => WeaponAbility.ShadowStrike; + + public override int AosStrengthReq => 40; + public override int AosMinDamage => 16; + public override int AosMaxDamage => 17; + public override int AosSpeed => 31; + public override float MlSpeed => 3.50f; + + public override int OldStrengthReq => 35; + public override int OldMinDamage => 5; + public override int OldMaxDamage => 39; + public override int OldSpeed => 30; + + public override int InitMinHits => 31; + public override int InitMaxHits => 90; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike; - public override WeaponAbility SecondaryAbility => WeaponAbility.ShadowStrike; - - public override int AosStrengthReq => 40; - public override int AosMinDamage => 16; - public override int AosMaxDamage => 17; - public override int AosSpeed => 31; - public override float MlSpeed => 3.50f; - - public override int OldStrengthReq => 35; - public override int OldMinDamage => 5; - public override int OldMaxDamage => 39; - public override int OldSpeed => 30; - - public override int InitMinHits => 31; - public override int InitMaxHits => 90; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Axes/WarAxe.cs b/Projects/UOContent/Items/Weapons/Axes/WarAxe.cs index 5fc4e4728..1e8ace8f3 100644 --- a/Projects/UOContent/Items/Weapons/Axes/WarAxe.cs +++ b/Projects/UOContent/Items/Weapons/Axes/WarAxe.cs @@ -2,54 +2,54 @@ using Server.Engines.Harvest; namespace Server.Items { - [Flippable(0x13B0, 0x13AF)] - public class WarAxe : BaseAxe - { - [Constructible] - public WarAxe() : base(0x13B0) => Weight = 8.0; - - public WarAxe(Serial serial) : base(serial) + [Flippable(0x13B0, 0x13AF)] + public class WarAxe : BaseAxe { + [Constructible] + public WarAxe() : base(0x13B0) => Weight = 8.0; + + public WarAxe(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore; + public override WeaponAbility SecondaryAbility => WeaponAbility.BleedAttack; + + public override int AosStrengthReq => 35; + public override int AosMinDamage => 14; + public override int AosMaxDamage => 15; + public override int AosSpeed => 33; + public override float MlSpeed => 3.25f; + + public override int OldStrengthReq => 35; + public override int OldMinDamage => 9; + public override int OldMaxDamage => 27; + public override int OldSpeed => 40; + + public override int DefHitSound => 0x233; + public override int DefMissSound => 0x239; + + public override int InitMinHits => 31; + public override int InitMaxHits => 80; + + public override SkillName DefSkill => SkillName.Macing; + public override WeaponType DefType => WeaponType.Bashing; + public override WeaponAnimation DefAnimation => WeaponAnimation.Bash1H; + + public override HarvestSystem HarvestSystem => null; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore; - public override WeaponAbility SecondaryAbility => WeaponAbility.BleedAttack; - - public override int AosStrengthReq => 35; - public override int AosMinDamage => 14; - public override int AosMaxDamage => 15; - public override int AosSpeed => 33; - public override float MlSpeed => 3.25f; - - public override int OldStrengthReq => 35; - public override int OldMinDamage => 9; - public override int OldMaxDamage => 27; - public override int OldSpeed => 40; - - public override int DefHitSound => 0x233; - public override int DefMissSound => 0x239; - - public override int InitMinHits => 31; - public override int InitMaxHits => 80; - - public override SkillName DefSkill => SkillName.Macing; - public override WeaponType DefType => WeaponType.Bashing; - public override WeaponAnimation DefAnimation => WeaponAnimation.Bash1H; - - public override HarvestSystem HarvestSystem => null; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/BaseMeleeWeapon.cs b/Projects/UOContent/Items/Weapons/BaseMeleeWeapon.cs index 033719eb1..ca12df725 100644 --- a/Projects/UOContent/Items/Weapons/BaseMeleeWeapon.cs +++ b/Projects/UOContent/Items/Weapons/BaseMeleeWeapon.cs @@ -2,65 +2,65 @@ using Server.Spells.Spellweaving; namespace Server.Items { - public abstract class BaseMeleeWeapon : BaseWeapon - { - public BaseMeleeWeapon(int itemID) : base(itemID) + public abstract class BaseMeleeWeapon : BaseWeapon { - } - - public BaseMeleeWeapon(Serial serial) : base(serial) - { - } - - public override int AbsorbDamage(Mobile attacker, Mobile defender, int damage) - { - damage = base.AbsorbDamage(attacker, defender, damage); - - AttuneWeaponSpell.TryAbsorb(defender, ref damage); - - if (Core.AOS) - return damage; - - int absorb = defender.MeleeDamageAbsorb; - - if (absorb > 0) - { - if (absorb > damage) + public BaseMeleeWeapon(int itemID) : base(itemID) { - int react = damage / 5; - - if (react <= 0) - react = 1; - - defender.MeleeDamageAbsorb -= damage; - damage = 0; - - attacker.Damage(react, defender); - - attacker.PlaySound(0x1F1); - attacker.FixedEffect(0x374A, 10, 16); } - else + + public BaseMeleeWeapon(Serial serial) : base(serial) { - defender.MeleeDamageAbsorb = 0; - defender.SendLocalizedMessage(1005556); // Your reactive armor spell has been nullified. - DefensiveSpell.Nullify(defender); } - } - return damage; - } + public override int AbsorbDamage(Mobile attacker, Mobile defender, int damage) + { + damage = base.AbsorbDamage(attacker, defender, damage); - // ReSharper disable once RedundantOverriddenMember - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - } + AttuneWeaponSpell.TryAbsorb(defender, ref damage); - // ReSharper disable once RedundantOverriddenMember - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + if (Core.AOS) + return damage; + + var absorb = defender.MeleeDamageAbsorb; + + if (absorb > 0) + { + if (absorb > damage) + { + var react = damage / 5; + + if (react <= 0) + react = 1; + + defender.MeleeDamageAbsorb -= damage; + damage = 0; + + attacker.Damage(react, defender); + + attacker.PlaySound(0x1F1); + attacker.FixedEffect(0x374A, 10, 16); + } + else + { + defender.MeleeDamageAbsorb = 0; + defender.SendLocalizedMessage(1005556); // Your reactive armor spell has been nullified. + DefensiveSpell.Nullify(defender); + } + } + + return damage; + } + + // ReSharper disable once RedundantOverriddenMember + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + } + + // ReSharper disable once RedundantOverriddenMember + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + } } - } } diff --git a/Projects/UOContent/Items/Weapons/BaseWeapon.cs b/Projects/UOContent/Items/Weapons/BaseWeapon.cs index 06372adc3..eb335fa90 100644 --- a/Projects/UOContent/Items/Weapons/BaseWeapon.cs +++ b/Projects/UOContent/Items/Weapons/BaseWeapon.cs @@ -17,3445 +17,3519 @@ using Server.Spells.Spellweaving; namespace Server.Items { - public interface ISlayer - { - SlayerName Slayer { get; set; } - SlayerName Slayer2 { get; set; } - } - - public abstract class BaseWeapon : Item, IWeapon, IFactionItem, ICraftable, ISlayer, IDurability - { - private string m_EngravedText; - - public BaseWeapon(int itemID) : base(itemID) + public interface ISlayer { - Layer = (Layer)ItemData.Quality; - - m_Quality = WeaponQuality.Regular; - m_StrReq = -1; - m_DexReq = -1; - m_IntReq = -1; - m_MinDamage = -1; - m_MaxDamage = -1; - m_HitSound = -1; - m_MissSound = -1; - m_Speed = -1; - m_MaxRange = -1; - m_Skill = (SkillName)(-1); - m_Type = (WeaponType)(-1); - m_Animation = (WeaponAnimation)(-1); - - m_Hits = m_MaxHits = Utility.RandomMinMax(InitMinHits, InitMaxHits); - - m_Resource = CraftResource.Iron; - - Attributes = new AosAttributes(this); - WeaponAttributes = new AosWeaponAttributes(this); - SkillBonuses = new AosSkillBonuses(this); - AosElementDamages = new AosElementAttributes(this); + SlayerName Slayer { get; set; } + SlayerName Slayer2 { get; set; } } - public BaseWeapon(Serial serial) : base(serial) + public abstract class BaseWeapon : Item, IWeapon, IFactionItem, ICraftable, ISlayer, IDurability { - } - - [CommandProperty(AccessLevel.GameMaster)] - public string EngravedText - { - get => m_EngravedText; - set - { - m_EngravedText = value; - InvalidateProperties(); - } - } - - public virtual Race RequiredRace => - null; // On OSI, there are no weapons with race requirements, this is for custom stuff - - public virtual bool UseSkillMod => !Core.AOS; - - public static bool InDoubleStrike { get; set; } - - public virtual int VirtualDamageBonus => 0; - - [Hue] - [CommandProperty(AccessLevel.GameMaster)] - public override int Hue - { - get => base.Hue; - set - { - base.Hue = value; - InvalidateProperties(); - } - } - - public virtual int ArtifactRarity => 0; - - public static BaseWeapon Fists { get; set; } - - public int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, - CraftItem craftItem, int resHue) - { - Quality = (WeaponQuality)quality; - - if (makersMark) - Crafter = from; - - PlayerConstructed = true; - - Type resourceType = typeRes ?? craftItem.Resources[0].ItemType; - - if (Core.AOS) - { - Resource = CraftResources.GetFromType(resourceType); - - CraftContext context = craftSystem.GetContext(from); - - if (context?.DoNotColor == true) - Hue = 0; - - if (tool is BaseRunicTool runicTool) - runicTool.ApplyAttributesTo(this); - - if (Quality == WeaponQuality.Exceptional) - { - if (Attributes.WeaponDamage > 35) - Attributes.WeaponDamage -= 20; - else - Attributes.WeaponDamage = 15; - - if (Core.ML) - { - Attributes.WeaponDamage += (int)(from.Skills.ArmsLore.Value / 20); - - if (Attributes.WeaponDamage > 50) - Attributes.WeaponDamage = 50; - - from.CheckSkill(SkillName.ArmsLore, 0, 100); - } - } - } - else if (tool is BaseRunicTool runicTool) - { - CraftResource thisResource = CraftResources.GetFromType(resourceType); - - if (thisResource == runicTool.Resource) - { - Resource = thisResource; - - CraftContext context = craftSystem.GetContext(from); - - if (context?.DoNotColor == true) - Hue = 0; - - switch (thisResource) - { - case CraftResource.DullCopper: - { - Identified = true; - DurabilityLevel = WeaponDurabilityLevel.Durable; - AccuracyLevel = WeaponAccuracyLevel.Accurate; - break; - } - case CraftResource.ShadowIron: - { - Identified = true; - DurabilityLevel = WeaponDurabilityLevel.Durable; - DamageLevel = WeaponDamageLevel.Ruin; - break; - } - case CraftResource.Copper: - { - Identified = true; - DurabilityLevel = WeaponDurabilityLevel.Fortified; - DamageLevel = WeaponDamageLevel.Ruin; - AccuracyLevel = WeaponAccuracyLevel.Surpassingly; - break; - } - case CraftResource.Bronze: - { - Identified = true; - DurabilityLevel = WeaponDurabilityLevel.Fortified; - DamageLevel = WeaponDamageLevel.Might; - AccuracyLevel = WeaponAccuracyLevel.Surpassingly; - break; - } - case CraftResource.Gold: - { - Identified = true; - DurabilityLevel = WeaponDurabilityLevel.Indestructible; - DamageLevel = WeaponDamageLevel.Force; - AccuracyLevel = WeaponAccuracyLevel.Eminently; - break; - } - case CraftResource.Agapite: - { - Identified = true; - DurabilityLevel = WeaponDurabilityLevel.Indestructible; - DamageLevel = WeaponDamageLevel.Power; - AccuracyLevel = WeaponAccuracyLevel.Eminently; - break; - } - case CraftResource.Verite: - { - Identified = true; - DurabilityLevel = WeaponDurabilityLevel.Indestructible; - DamageLevel = WeaponDamageLevel.Power; - AccuracyLevel = WeaponAccuracyLevel.Exceedingly; - break; - } - case CraftResource.Valorite: - { - Identified = true; - DurabilityLevel = WeaponDurabilityLevel.Indestructible; - DamageLevel = WeaponDamageLevel.Vanq; - AccuracyLevel = WeaponAccuracyLevel.Supremely; - break; - } - } - } - } - - return quality; - } - - public virtual void UnscaleDurability() - { - int scale = 100 + GetDurabilityBonus(); - - m_Hits = (m_Hits * 100 + (scale - 1)) / scale; - m_MaxHits = (m_MaxHits * 100 + (scale - 1)) / scale; - InvalidateProperties(); - } - - public virtual void ScaleDurability() - { - int scale = 100 + GetDurabilityBonus(); - - m_Hits = (m_Hits * scale + 99) / 100; - m_MaxHits = (m_MaxHits * scale + 99) / 100; - InvalidateProperties(); - } - - public virtual void OnBeforeSwing(Mobile attacker, Mobile defender) - { - if (WeaponAbility.GetCurrentAbility(attacker)?.OnBeforeSwing(attacker, defender) == false) - WeaponAbility.ClearCurrentAbility(attacker); - - if (SpecialMove.GetCurrentMove(attacker)?.OnBeforeSwing(attacker, defender) == false) - SpecialMove.ClearCurrentMove(attacker); - } - - public virtual TimeSpan OnSwing(Mobile attacker, Mobile defender) => OnSwing(attacker, defender, 1.0); - - public virtual void GetStatusDamage(Mobile from, out int min, out int max) - { - GetBaseDamageRange(from, out int baseMin, out int baseMax); - - if (Core.AOS) - { - min = Math.Max((int)ScaleDamageAOS(from, baseMin, false), 1); - max = Math.Max((int)ScaleDamageAOS(from, baseMax, false), 1); - } - else - { - min = Math.Max((int)ScaleDamageOld(from, baseMin, false), 1); - max = Math.Max((int)ScaleDamageOld(from, baseMax, false), 1); - } - } - - public override void OnAfterDuped(Item newItem) - { - if (!(newItem is BaseWeapon weap)) - return; - - weap.Attributes = new AosAttributes(newItem, Attributes); - weap.AosElementDamages = new AosElementAttributes(newItem, AosElementDamages); - weap.SkillBonuses = new AosSkillBonuses(newItem, SkillBonuses); - weap.WeaponAttributes = new AosWeaponAttributes(newItem, WeaponAttributes); - } - - public int GetDurabilityBonus() - { - int bonus = 0; - - if (m_Quality == WeaponQuality.Exceptional) - bonus += 20; - - switch (m_DurabilityLevel) - { - case WeaponDurabilityLevel.Durable: - bonus += 20; - break; - case WeaponDurabilityLevel.Substantial: - bonus += 50; - break; - case WeaponDurabilityLevel.Massive: - bonus += 70; - break; - case WeaponDurabilityLevel.Fortified: - bonus += 100; - break; - case WeaponDurabilityLevel.Indestructible: - bonus += 120; - break; - } - - if (Core.AOS) - { - bonus += WeaponAttributes.DurabilityBonus; - - CraftResourceInfo resInfo = CraftResources.GetInfo(m_Resource); - CraftAttributeInfo attrInfo = null; - - if (resInfo != null) - attrInfo = resInfo.AttributeInfo; - - if (attrInfo != null) - bonus += attrInfo.WeaponDurability; - } - - return bonus; - } - - public int GetLowerStatReq() - { - if (!Core.AOS) - return 0; - - int v = WeaponAttributes.LowerStatReq; - - CraftAttributeInfo attrInfo = CraftResources.GetInfo(m_Resource)?.AttributeInfo; - - if (attrInfo != null) - v += attrInfo.WeaponLowerRequirements; - - if (v > 100) - v = 100; - - return v; - } - - public static void BlockEquip(Mobile m, TimeSpan duration) - { - if (m.BeginAction()) - new ResetEquipTimer(m, duration).Start(); - } - - public override bool CheckConflictingLayer(Mobile m, Item item, Layer layer) - { - if (base.CheckConflictingLayer(m, item, layer)) - return true; - - if (Layer == Layer.TwoHanded && layer == Layer.OneHanded) - { - m.SendLocalizedMessage(500214); // You already have something in both hands. - return true; - } - - if (Layer == Layer.OneHanded && layer == Layer.TwoHanded && !(item is BaseShield) && - !(item is BaseEquipableLight)) - { - m.SendLocalizedMessage(500215); // You can only wield one weapon at a time. - return true; - } - - return false; - } - - public override bool AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted) => - Ethic.CheckTrade(from, to, newOwner, this) && - base.AllowSecureTrade(from, to, newOwner, accepted); - - public override bool CanEquip(Mobile from) - { - if (!Ethic.CheckEquip(from, this)) - return false; - - if (RequiredRace != null && from.Race != RequiredRace) - { - if (RequiredRace == Race.Elf) - from.SendLocalizedMessage(1072203); // Only Elves may use this. - else - from.SendMessage("Only {0} may use this.", RequiredRace.PluralName); - - return false; - } - - if (from.Dex < DexRequirement) - { - from.SendMessage("You are not nimble enough to equip that."); - return false; - } - - if (from.Str < AOS.Scale(StrRequirement, 100 - GetLowerStatReq())) - { - from.SendLocalizedMessage(500213); // You are not strong enough to equip that. - return false; - } - - if (from.Int < IntRequirement) - { - from.SendMessage("You are not smart enough to equip that."); - return false; - } - - return from.CanBeginAction() && base.CanEquip(from); - } - - public override bool OnEquip(Mobile from) - { - int strBonus = Attributes.BonusStr; - int dexBonus = Attributes.BonusDex; - int intBonus = Attributes.BonusInt; - - if (strBonus != 0 || dexBonus != 0 || intBonus != 0) - { - Mobile m = from; - - string modName = Serial.ToString(); - - if (strBonus != 0) - m.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero)); - - if (dexBonus != 0) - m.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero)); - - if (intBonus != 0) - m.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero)); - } - - from.NextCombatTime = Core.TickCount + (int)GetDelay(from).TotalMilliseconds; - - if (UseSkillMod && m_AccuracyLevel != WeaponAccuracyLevel.Regular) - { - m_SkillMod?.Remove(); - - m_SkillMod = new DefaultSkillMod(AccuracySkill, true, (int)m_AccuracyLevel * 5); - from.AddSkillMod(m_SkillMod); - } - - if (Core.AOS && WeaponAttributes.MageWeapon != 0 && WeaponAttributes.MageWeapon != 30) - { - m_MageMod?.Remove(); - - m_MageMod = new DefaultSkillMod(SkillName.Magery, true, -30 + WeaponAttributes.MageWeapon); - from.AddSkillMod(m_MageMod); - } - - return true; - } - - public override void OnAdded(IEntity parent) - { - base.OnAdded(parent); - - if (parent is Mobile from) - { - if (Core.AOS) - SkillBonuses.AddTo(from); - - from.CheckStatTimers(); - from.Delta(MobileDelta.WeaponDamage); - } - } - - public override void OnRemoved(IEntity parent) - { - if (parent is Mobile m) - { - BaseWeapon weapon = m.Weapon as BaseWeapon; - - string modName = Serial.ToString(); - - m.RemoveStatMod($"{modName}Str"); - m.RemoveStatMod($"{modName}Dex"); - m.RemoveStatMod($"{modName}Int"); - - if (weapon != null) - m.NextCombatTime = Core.TickCount + (int)weapon.GetDelay(m).TotalMilliseconds; - - if (UseSkillMod && m_SkillMod != null) - { - m_SkillMod.Remove(); - m_SkillMod = null; - } - - if (m_MageMod != null) - { - m_MageMod.Remove(); - m_MageMod = null; - } - - if (Core.AOS) - SkillBonuses.Remove(); - - ImmolatingWeaponSpell.StopImmolating(this); - - m.CheckStatTimers(); - - m.Delta(MobileDelta.WeaponDamage); - } - } - - public virtual SkillName GetUsedSkill(Mobile m, bool checkSkillAttrs) - { - SkillName sk; - - if (checkSkillAttrs && WeaponAttributes.UseBestSkill != 0) - { - double swrd = m.Skills.Swords.Value; - double fenc = m.Skills.Fencing.Value; - double mcng = m.Skills.Macing.Value; - double val; - - sk = SkillName.Swords; - val = swrd; - - if (fenc > val) - { - sk = SkillName.Fencing; - val = fenc; - } - - if (mcng > val) sk = SkillName.Macing; - } - else if (WeaponAttributes.MageWeapon != 0) - { - if (m.Skills.Magery.Value > m.Skills[Skill].Value) - sk = SkillName.Magery; - else - sk = Skill; - } - else - { - sk = Skill; - - if (sk != SkillName.Wrestling && !m.Player && !m.Body.IsHuman && - m.Skills.Wrestling.Value > m.Skills[sk].Value) - sk = SkillName.Wrestling; - } - - return sk; - } - - public virtual double GetAttackSkillValue(Mobile attacker, Mobile defender) => attacker.Skills[GetUsedSkill(attacker, true)].Value; - - public virtual double GetDefendSkillValue(Mobile attacker, Mobile defender) => defender.Skills[GetUsedSkill(defender, true)].Value; - - private static bool CheckAnimal(Mobile m, Type type) => AnimalForm.UnderTransformation(m, type); - - public virtual bool CheckHit(Mobile attacker, Mobile defender) - { - BaseWeapon atkWeapon = attacker.Weapon as BaseWeapon; - BaseWeapon defWeapon = defender.Weapon as BaseWeapon; - - Skill atkSkill = attacker.Skills[atkWeapon?.Skill ?? SkillName.Wrestling]; - // Skill defSkill = defender.Skills[defWeapon.Skill]; - - double atkValue = atkWeapon?.GetAttackSkillValue(attacker, defender) ?? 0.0; - double defValue = defWeapon?.GetDefendSkillValue(attacker, defender) ?? 0.0; - - double ourValue, theirValue; - - int bonus = GetHitChanceBonus(); - - if (Core.AOS) - { - if (atkValue <= -20.0) - atkValue = -19.9; - - if (defValue <= -20.0) - defValue = -19.9; - - bonus += AosAttributes.GetValue(attacker, AosAttribute.AttackChance); - - if (DivineFurySpell.UnderEffect(attacker)) - bonus += 10; // attacker gets 10% bonus when they're under divine fury - - if (CheckAnimal(attacker, typeof(GreyWolf)) || CheckAnimal(attacker, typeof(BakeKitsune))) - bonus += 20; // attacker gets 20% bonus when under Wolf or Bake Kitsune form - - if (HitLower.IsUnderAttackEffect(attacker)) - bonus -= 25; // Under Hit Lower Attack effect -> 25% malus - - WeaponAbility ability = WeaponAbility.GetCurrentAbility(attacker); - - if (ability != null) - bonus += ability.AccuracyBonus; - - SpecialMove move = SpecialMove.GetCurrentMove(attacker); - - if (move != null) - bonus += move.GetAccuracyBonus(attacker); - - // Max Hit Chance Increase = 45% - if (bonus > 45) - bonus = 45; - - ourValue = (atkValue + 20.0) * (100 + bonus); - - bonus = AosAttributes.GetValue(defender, AosAttribute.DefendChance); - - if (DivineFurySpell.UnderEffect(defender)) - bonus -= 20; // defender loses 20% bonus when they're under divine fury - - if (HitLower.IsUnderDefenseEffect(defender)) - bonus -= 25; // Under Hit Lower Defense effect -> 25% malus - - int blockBonus = 0; - - if (Block.GetBonus(defender, ref blockBonus)) - bonus += blockBonus; - - int surpriseMalus = 0; - - if (SurpriseAttack.GetMalus(defender, ref surpriseMalus)) - bonus -= surpriseMalus; - - int discordanceEffect = 0; - - // Defender loses -0/-28% if under the effect of Discordance. - if (Discordance.GetEffect(attacker, ref discordanceEffect)) - bonus -= discordanceEffect; - - // Defense Chance Increase = 45% - if (bonus > 45) - bonus = 45; - - theirValue = (defValue + 20.0) * (100 + bonus); - - bonus = 0; - } - else - { - if (atkValue <= -50.0) - atkValue = -49.9; - - if (defValue <= -50.0) - defValue = -49.9; - - ourValue = atkValue + 50.0; - theirValue = defValue + 50.0; - } - - double chance = ourValue / (theirValue * 2.0); - - chance *= 1.0 + (double)bonus / 100; - - if (Core.AOS && chance < 0.02) - chance = 0.02; - - return attacker.CheckSkill(atkSkill.SkillName, chance); - } - - public virtual TimeSpan GetDelay(Mobile m) - { - double speed = Speed; - - if (speed == 0) - return TimeSpan.FromHours(1.0); - - double delayInSeconds; - - if (Core.SE) - { - /* - * This is likely true for Core.AOS as well... both guides report the same - * formula, and both are wrong. - * The old formula left in for AOS for legacy & because we aren't quite 100% - * Sure that AOS has THIS formula + private WeaponAccuracyLevel m_AccuracyLevel; + private WeaponAnimation m_Animation; + private Mobile m_Crafter; + + /* Weapon internals work differently now (Mar 13 2003) + * + * The attributes defined below default to -1. + * If the value is -1, the corresponding virtual 'Aos/Old' property is used. + * If not, the attribute value itself is used. Here's the list: + * - MinDamage + * - MaxDamage + * - Speed + * - HitSound + * - MissSound + * - StrRequirement, DexRequirement, IntRequirement + * - WeaponType + * - WeaponAnimation + * - MaxRange */ - int bonus = AosAttributes.GetValue(m, AosAttribute.WeaponSpeed); - if (DivineFurySpell.UnderEffect(m)) - bonus += 10; + // Instance values. These values are unique to each weapon. + private WeaponDamageLevel m_DamageLevel; + private WeaponDurabilityLevel m_DurabilityLevel; + private string m_EngravedText; - // Bonus granted by successful use of Honorable Execution. - bonus += HonorableExecution.GetSwingBonus(m); + private FactionItem m_FactionState; + private int m_Hits; + private int m_HitSound, m_MissSound; + private bool m_Identified; + private int m_MaxHits; + private int m_MaxRange; + private int m_MinDamage, m_MaxDamage; + private Poison m_Poison; + private int m_PoisonCharges; + private WeaponQuality m_Quality; + private CraftResource m_Resource; + private SkillName m_Skill; + private SkillMod m_SkillMod, m_MageMod; + private SlayerName m_Slayer; + private SlayerName m_Slayer2; + private float m_Speed; - if (DualWield.Registry.ContainsKey(m)) - bonus += DualWield.Registry[m].BonusSwingSpeed; + // Overridable values. These values are provided to override the defaults which get defined in the individual weapon scripts. + private int m_StrReq, m_DexReq, m_IntReq; + private WeaponType m_Type; - if (Feint.Registry.ContainsKey(m)) - bonus -= Feint.Registry[m].SwingSpeedReduction; - - TransformContext context = TransformationSpellHelper.GetContext(m); - - if (context?.Spell is ReaperFormSpell spell) - bonus += spell.SwingSpeedBonus; - - int discordanceEffect = 0; - - // Discordance gives a malus of -0/-28% to swing speed. - if (Discordance.GetEffect(m, ref discordanceEffect)) - bonus -= discordanceEffect; - - if (EssenceOfWindSpell.IsDebuffed(m)) - bonus -= EssenceOfWindSpell.GetSSIMalus(m); - - if (bonus > 60) - bonus = 60; - - double ticks; - - if (Core.ML) + public BaseWeapon(int itemID) : base(itemID) { - int stamTicks = m.Stam / 30; + Layer = (Layer)ItemData.Quality; - ticks = speed * 4; - ticks = Math.Floor((ticks - stamTicks) * (100.0 / (100 + bonus))); - } - else - { - speed = Math.Floor(speed * (bonus + 100.0) / 100.0); + m_Quality = WeaponQuality.Regular; + m_StrReq = -1; + m_DexReq = -1; + m_IntReq = -1; + m_MinDamage = -1; + m_MaxDamage = -1; + m_HitSound = -1; + m_MissSound = -1; + m_Speed = -1; + m_MaxRange = -1; + m_Skill = (SkillName)(-1); + m_Type = (WeaponType)(-1); + m_Animation = (WeaponAnimation)(-1); - if (speed <= 0) - speed = 1; + m_Hits = m_MaxHits = Utility.RandomMinMax(InitMinHits, InitMaxHits); - ticks = Math.Floor(80000.0 / ((m.Stam + 100) * speed) - 2); + m_Resource = CraftResource.Iron; + + Attributes = new AosAttributes(this); + WeaponAttributes = new AosWeaponAttributes(this); + SkillBonuses = new AosSkillBonuses(this); + AosElementDamages = new AosElementAttributes(this); } - // Swing speed currently capped at one swing every 1.25 seconds (5 ticks). - if (ticks < 5) - ticks = 5; - - delayInSeconds = ticks * 0.25; - } - else if (Core.AOS) - { - int v = (m.Stam + 100) * (int)speed; - - int bonus = AosAttributes.GetValue(m, AosAttribute.WeaponSpeed); - - if (DivineFurySpell.UnderEffect(m)) - bonus += 10; - - int discordanceEffect = 0; - - // Discordance gives a malus of -0/-28% to swing speed. - if (Discordance.GetEffect(m, ref discordanceEffect)) - bonus -= discordanceEffect; - - v += AOS.Scale(v, bonus); - - if (v <= 0) - v = 1; - - delayInSeconds = Math.Floor(40000.0 / v) * 0.5; - - // Maximum swing rate capped at one swing per second - // OSI dev said that it has and is supposed to be 1.25 - if (delayInSeconds < 1.25) - delayInSeconds = 1.25; - } - else - { - int v = (m.Stam + 100) * (int)speed; - - if (v <= 0) - v = 1; - - delayInSeconds = 15000.0 / v; - } - - return TimeSpan.FromSeconds(delayInSeconds); - } - - public virtual TimeSpan OnSwing(Mobile attacker, Mobile defender, double damageBonus) - { - bool canSwing = true; - - if (Core.AOS) - { - canSwing = !attacker.Paralyzed && !attacker.Frozen; - - if (canSwing) canSwing = !(attacker.Spell is Spell sp) || !sp.IsCasting || !sp.BlocksMovement; - - if (canSwing) canSwing = !(attacker is PlayerMobile p) || p.PeacedUntil <= DateTime.UtcNow; - } - - if ((attacker as PlayerMobile)?.DuelContext?.CheckItemEquip(attacker, this) == false) - canSwing = false; - - if (canSwing && attacker.HarmfulCheck(defender)) - { - attacker.DisruptiveAction(); - - if (attacker.NetState != null) - attacker.Send(new Swing(attacker.Serial, defender.Serial)); - - if (attacker is BaseCreature bc) + public BaseWeapon(Serial serial) : base(serial) { - WeaponAbility ab = bc.GetWeaponAbility(); - - if (ab != null) - { - if (bc.WeaponAbilityChance > Utility.RandomDouble()) - WeaponAbility.SetCurrentAbility(bc, ab); - else - WeaponAbility.ClearCurrentAbility(bc); - } } - if (CheckHit(attacker, defender)) - OnHit(attacker, defender, damageBonus); - else - OnMiss(attacker, defender); - } - - return GetDelay(attacker); - } - - public static bool CheckParry(Mobile defender) - { - if (defender == null) - return false; - - BaseShield shield = defender.FindItemOnLayer(Layer.TwoHanded) as BaseShield; - - double parry = defender.Skills.Parry.Value; - double bushidoNonRacial = defender.Skills.Bushido.NonRacialValue; - double bushido = defender.Skills.Bushido.Value; - double chance; - - if (shield != null) - { - // As per OSI, no genitive effect from the Racial stuffs, ie, 120 parry and '0' bushido with humans - chance = Math.Max((parry - bushidoNonRacial) / 400.0, 0); - - // Parry/Bushido over 100 grants a 5% bonus. - if (parry >= 100.0 || bushido >= 100.0) - chance += 0.05; - - // Evasion grants a variable bonus post ML. 50% prior. - if (Evasion.IsEvading(defender)) - chance *= Evasion.GetParryScalar(defender); - - // Low dexterity lowers the chance. - if (defender.Dex < 80) - chance = chance * (20 + defender.Dex) / 100; - - return defender.CheckSkill(SkillName.Parry, chance); - } - - if (defender.Weapon is Fists || defender.Weapon is BaseRanged) - return false; - - BaseWeapon weapon = defender.Weapon as BaseWeapon; - - double divisor = weapon?.Layer == Layer.OneHanded ? 48000.0 : 41140.0; - - chance = parry * bushido / divisor; - - double aosChance = parry / 800.0; - - // Parry or Bushido over 100 grant a 5% bonus. - if (parry >= 100.0) - { - chance += 0.05; - aosChance += 0.05; - } - else if (bushido >= 100.0) - { - chance += 0.05; - } - - // Evasion grants a variable bonus post ML. 50% prior. - if (Evasion.IsEvading(defender)) - chance *= Evasion.GetParryScalar(defender); - - // Low dexterity lowers the chance. - if (defender.Dex < 80) - chance = chance * (20 + defender.Dex) / 100; - - if (chance > aosChance) - return defender.CheckSkill(SkillName.Parry, chance); - - return - aosChance > Utility - .RandomDouble(); // Only skillcheck if wielding a shield & there's no effect from Bushido - } - - public virtual int AbsorbDamageAOS(Mobile attacker, Mobile defender, int damage) - { - bool blocked = false; - - if (defender.Player || defender.Body.IsHuman) - { - blocked = CheckParry(defender); - - if (blocked) + [CommandProperty(AccessLevel.GameMaster)] + public string EngravedText { - defender.FixedEffect(0x37B9, 10, 16); - damage = 0; - - // Successful block removes the Honorable Execution penalty. - HonorableExecution.RemovePenalty(defender); - - if (CounterAttack.IsCountering(defender)) - { - if (defender.Weapon is BaseWeapon weapon) + get => m_EngravedText; + set { - defender.FixedParticles(0x3779, 1, 15, 0x158B, 0x0, 0x3, EffectLayer.Waist); - weapon.OnSwing(defender, attacker); + m_EngravedText = value; + InvalidateProperties(); + } + } + + public virtual Race RequiredRace => + null; // On OSI, there are no weapons with race requirements, this is for custom stuff + + public virtual bool UseSkillMod => !Core.AOS; + + public static bool InDoubleStrike { get; set; } + + public virtual int VirtualDamageBonus => 0; + + [Hue] + [CommandProperty(AccessLevel.GameMaster)] + public override int Hue + { + get => base.Hue; + set + { + base.Hue = value; + InvalidateProperties(); + } + } + + public virtual int ArtifactRarity => 0; + + public static BaseWeapon Fists { get; set; } + + public virtual WeaponAbility PrimaryAbility => null; + public virtual WeaponAbility SecondaryAbility => null; + + public virtual int DefMaxRange => 1; + public virtual int DefHitSound => 0; + public virtual int DefMissSound => 0; + public virtual SkillName DefSkill => SkillName.Swords; + public virtual WeaponType DefType => WeaponType.Slashing; + public virtual WeaponAnimation DefAnimation => WeaponAnimation.Slash1H; + + public virtual int AosStrengthReq => 0; + public virtual int AosDexterityReq => 0; + public virtual int AosIntelligenceReq => 0; + public virtual int AosMinDamage => 0; + public virtual int AosMaxDamage => 0; + public virtual int AosSpeed => 0; + public virtual float MlSpeed => 0.0f; + public virtual int AosMaxRange => DefMaxRange; + public virtual int AosHitSound => DefHitSound; + public virtual int AosMissSound => DefMissSound; + public virtual SkillName AosSkill => DefSkill; + public virtual WeaponType AosType => DefType; + public virtual WeaponAnimation AosAnimation => DefAnimation; + + public virtual int OldStrengthReq => 0; + public virtual int OldDexterityReq => 0; + public virtual int OldIntelligenceReq => 0; + public virtual int OldMinDamage => 0; + public virtual int OldMaxDamage => 0; + public virtual int OldSpeed => 0; + public virtual int OldMaxRange => DefMaxRange; + public virtual int OldHitSound => DefHitSound; + public virtual int OldMissSound => DefMissSound; + public virtual SkillName OldSkill => DefSkill; + public virtual WeaponType OldType => DefType; + public virtual WeaponAnimation OldAnimation => DefAnimation; + + public override int PhysicalResistance => WeaponAttributes.ResistPhysicalBonus; + public override int FireResistance => WeaponAttributes.ResistFireBonus; + public override int ColdResistance => WeaponAttributes.ResistColdBonus; + public override int PoisonResistance => WeaponAttributes.ResistPoisonBonus; + public override int EnergyResistance => WeaponAttributes.ResistEnergyBonus; + + public virtual SkillName AccuracySkill => SkillName.Tactics; + + [CommandProperty(AccessLevel.GameMaster)] + public AosAttributes Attributes { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public AosWeaponAttributes WeaponAttributes { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public AosSkillBonuses SkillBonuses { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public AosElementAttributes AosElementDamages { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Cursed { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Consecrated { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Identified + { + get => m_Identified; + set + { + m_Identified = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int PoisonCharges + { + get => m_PoisonCharges; + set + { + m_PoisonCharges = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Poison Poison + { + get => m_Poison; + set + { + m_Poison = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public WeaponQuality Quality + { + get => m_Quality; + set + { + UnscaleDurability(); + m_Quality = value; + ScaleDurability(); + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Crafter + { + get => m_Crafter; + set + { + m_Crafter = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public CraftResource Resource + { + get => m_Resource; + set + { + UnscaleDurability(); + m_Resource = value; + Hue = CraftResources.GetHue(m_Resource); + InvalidateProperties(); + ScaleDurability(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public WeaponDamageLevel DamageLevel + { + get => m_DamageLevel; + set + { + m_DamageLevel = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public WeaponDurabilityLevel DurabilityLevel + { + get => m_DurabilityLevel; + set + { + UnscaleDurability(); + m_DurabilityLevel = value; + InvalidateProperties(); + ScaleDurability(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool PlayerConstructed { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public WeaponAnimation Animation + { + get => m_Animation == (WeaponAnimation)(-1) ? Core.AOS ? AosAnimation : OldAnimation : m_Animation; + set => m_Animation = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public WeaponType Type + { + get => m_Type == (WeaponType)(-1) ? Core.AOS ? AosType : OldType : m_Type; + set => m_Type = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public SkillName Skill + { + get => m_Skill == (SkillName)(-1) ? Core.AOS ? AosSkill : OldSkill : m_Skill; + set + { + m_Skill = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int HitSound + { + get => m_HitSound == -1 ? Core.AOS ? AosHitSound : OldHitSound : m_HitSound; + set => m_HitSound = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int MissSound + { + get => m_MissSound == -1 ? Core.AOS ? AosMissSound : OldMissSound : m_MissSound; + set => m_MissSound = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int MinDamage + { + get => m_MinDamage == -1 ? Core.AOS ? AosMinDamage : OldMinDamage : m_MinDamage; + set + { + m_MinDamage = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxDamage + { + get => m_MaxDamage == -1 ? Core.AOS ? AosMaxDamage : OldMaxDamage : m_MaxDamage; + set + { + m_MaxDamage = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public float Speed + { + get + { + if (m_Speed != -1) + return m_Speed; + + if (Core.ML) + return MlSpeed; + if (Core.AOS) + return AosSpeed; + + return OldSpeed; + } + set + { + m_Speed = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int StrRequirement + { + get => m_StrReq == -1 ? Core.AOS ? AosStrengthReq : OldStrengthReq : m_StrReq; + set + { + m_StrReq = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int DexRequirement + { + get => m_DexReq == -1 ? Core.AOS ? AosDexterityReq : OldDexterityReq : m_DexReq; + set => m_DexReq = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int IntRequirement + { + get => m_IntReq == -1 ? Core.AOS ? AosIntelligenceReq : OldIntelligenceReq : m_IntReq; + set => m_IntReq = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public WeaponAccuracyLevel AccuracyLevel + { + get => m_AccuracyLevel; + set + { + if (m_AccuracyLevel != value) + { + m_AccuracyLevel = value; + + if (UseSkillMod) + { + if (m_AccuracyLevel == WeaponAccuracyLevel.Regular) + { + m_SkillMod?.Remove(); + + m_SkillMod = null; + } + else if (m_SkillMod == null && Parent is Mobile mobile) + { + m_SkillMod = new DefaultSkillMod(AccuracySkill, true, (int)m_AccuracyLevel * 5); + mobile.AddSkillMod(m_SkillMod); + } + else if (m_SkillMod != null) + { + m_SkillMod.Value = (int)m_AccuracyLevel * 5; + } + } + + InvalidateProperties(); + } + } + } + + public int OnCraft( + int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, + CraftItem craftItem, int resHue + ) + { + Quality = (WeaponQuality)quality; + + if (makersMark) + Crafter = from; + + PlayerConstructed = true; + + var resourceType = typeRes ?? craftItem.Resources[0].ItemType; + + if (Core.AOS) + { + Resource = CraftResources.GetFromType(resourceType); + + var context = craftSystem.GetContext(from); + + if (context?.DoNotColor == true) + Hue = 0; + + if (tool is BaseRunicTool runicTool) + runicTool.ApplyAttributesTo(this); + + if (Quality == WeaponQuality.Exceptional) + { + if (Attributes.WeaponDamage > 35) + Attributes.WeaponDamage -= 20; + else + Attributes.WeaponDamage = 15; + + if (Core.ML) + { + Attributes.WeaponDamage += (int)(from.Skills.ArmsLore.Value / 20); + + if (Attributes.WeaponDamage > 50) + Attributes.WeaponDamage = 50; + + from.CheckSkill(SkillName.ArmsLore, 0, 100); + } + } + } + else if (tool is BaseRunicTool runicTool) + { + var thisResource = CraftResources.GetFromType(resourceType); + + if (thisResource == runicTool.Resource) + { + Resource = thisResource; + + var context = craftSystem.GetContext(from); + + if (context?.DoNotColor == true) + Hue = 0; + + switch (thisResource) + { + case CraftResource.DullCopper: + { + Identified = true; + DurabilityLevel = WeaponDurabilityLevel.Durable; + AccuracyLevel = WeaponAccuracyLevel.Accurate; + break; + } + case CraftResource.ShadowIron: + { + Identified = true; + DurabilityLevel = WeaponDurabilityLevel.Durable; + DamageLevel = WeaponDamageLevel.Ruin; + break; + } + case CraftResource.Copper: + { + Identified = true; + DurabilityLevel = WeaponDurabilityLevel.Fortified; + DamageLevel = WeaponDamageLevel.Ruin; + AccuracyLevel = WeaponAccuracyLevel.Surpassingly; + break; + } + case CraftResource.Bronze: + { + Identified = true; + DurabilityLevel = WeaponDurabilityLevel.Fortified; + DamageLevel = WeaponDamageLevel.Might; + AccuracyLevel = WeaponAccuracyLevel.Surpassingly; + break; + } + case CraftResource.Gold: + { + Identified = true; + DurabilityLevel = WeaponDurabilityLevel.Indestructible; + DamageLevel = WeaponDamageLevel.Force; + AccuracyLevel = WeaponAccuracyLevel.Eminently; + break; + } + case CraftResource.Agapite: + { + Identified = true; + DurabilityLevel = WeaponDurabilityLevel.Indestructible; + DamageLevel = WeaponDamageLevel.Power; + AccuracyLevel = WeaponAccuracyLevel.Eminently; + break; + } + case CraftResource.Verite: + { + Identified = true; + DurabilityLevel = WeaponDurabilityLevel.Indestructible; + DamageLevel = WeaponDamageLevel.Power; + AccuracyLevel = WeaponAccuracyLevel.Exceedingly; + break; + } + case CraftResource.Valorite: + { + Identified = true; + DurabilityLevel = WeaponDurabilityLevel.Indestructible; + DamageLevel = WeaponDamageLevel.Vanq; + AccuracyLevel = WeaponAccuracyLevel.Supremely; + break; + } + } + } } - CounterAttack.StopCountering(defender); - } - - if (Confidence.IsConfident(defender)) - { - defender.SendLocalizedMessage( - 1063117); // Your confidence reassures you as you successfully block your opponent's blow. - - double bushido = defender.Skills.Bushido.Value; - - defender.Hits += Utility.RandomMinMax(1, (int)(bushido / 12)); - defender.Stam += Utility.RandomMinMax(1, (int)(bushido / 5)); - } - - BaseShield shield = defender.FindItemOnLayer(Layer.TwoHanded) as BaseShield; - - shield?.OnHit(this, damage); + return quality; } - } - if (!blocked) - { - double positionChance = Utility.RandomDouble(); + public virtual void UnscaleDurability() + { + var scale = 100 + GetDurabilityBonus(); - Item armorItem; + m_Hits = (m_Hits * 100 + (scale - 1)) / scale; + m_MaxHits = (m_MaxHits * 100 + (scale - 1)) / scale; + InvalidateProperties(); + } - if (positionChance < 0.07) - armorItem = defender.NeckArmor; - else if (positionChance < 0.14) - armorItem = defender.HandArmor; - else if (positionChance < 0.28) - armorItem = defender.ArmsArmor; - else if (positionChance < 0.43) - armorItem = defender.HeadArmor; - else if (positionChance < 0.65) - armorItem = defender.LegsArmor; - else - armorItem = defender.ChestArmor; + public virtual void ScaleDurability() + { + var scale = 100 + GetDurabilityBonus(); - if (armorItem is IWearableDurability armor) - armor.OnHit(this, damage); // call OnHit to lose durability - } + m_Hits = (m_Hits * scale + 99) / 100; + m_MaxHits = (m_MaxHits * scale + 99) / 100; + InvalidateProperties(); + } - return damage; - } + public virtual int InitMinHits => 0; + public virtual int InitMaxHits => 0; - public virtual int AbsorbDamage(Mobile attacker, Mobile defender, int damage) - { - if (Core.AOS) - return AbsorbDamageAOS(attacker, defender, damage); + public virtual bool CanFortify => true; - if (defender.FindItemOnLayer(Layer.TwoHanded) is BaseShield shield) - damage = shield.OnHit(this, damage); + [CommandProperty(AccessLevel.GameMaster)] + public int HitPoints + { + get => m_Hits; + set + { + if (m_Hits == value) + return; - double chance = Utility.RandomDouble(); + if (value > m_MaxHits) + value = m_MaxHits; - Item armorItem; + m_Hits = value; - if (chance < 0.07) - armorItem = defender.NeckArmor; - else if (chance < 0.14) - armorItem = defender.HandArmor; - else if (chance < 0.28) - armorItem = defender.ArmsArmor; - else if (chance < 0.43) - armorItem = defender.HeadArmor; - else if (chance < 0.65) - armorItem = defender.LegsArmor; - else - armorItem = defender.ChestArmor; + InvalidateProperties(); + } + } - if (armorItem is IWearableDurability armor) - damage = armor.OnHit(this, damage); + [CommandProperty(AccessLevel.GameMaster)] + public int MaxHitPoints + { + get => m_MaxHits; + set + { + m_MaxHits = value; + InvalidateProperties(); + } + } - int virtualArmor = defender.VirtualArmor + defender.VirtualArmorMod; + public FactionItem FactionItemState + { + get => m_FactionState; + set + { + m_FactionState = value; - if (virtualArmor > 0) - { - double scalar; + if (m_FactionState == null) + Hue = CraftResources.GetHue(Resource); - if (chance < 0.14) - scalar = 0.07; - else if (chance < 0.28) - scalar = 0.14; - else if (chance < 0.43) - scalar = 0.15; - else if (chance < 0.65) - scalar = 0.22; - else - scalar = 0.35; + LootType = m_FactionState == null ? LootType.Regular : LootType.Blessed; + } + } - int from = (int)(virtualArmor * scalar) / 2; - int to = (int)(virtualArmor * scalar); + [CommandProperty(AccessLevel.GameMaster)] + public SlayerName Slayer + { + get => m_Slayer; + set + { + m_Slayer = value; + InvalidateProperties(); + } + } - damage -= Utility.Random(from, to - from + 1); - } + [CommandProperty(AccessLevel.GameMaster)] + public SlayerName Slayer2 + { + get => m_Slayer2; + set + { + m_Slayer2 = value; + InvalidateProperties(); + } + } - return damage; - } + public virtual void OnBeforeSwing(Mobile attacker, Mobile defender) + { + if (WeaponAbility.GetCurrentAbility(attacker)?.OnBeforeSwing(attacker, defender) == false) + WeaponAbility.ClearCurrentAbility(attacker); - public virtual int GetPackInstinctBonus(Mobile attacker, Mobile defender) - { - if (attacker.Player || defender.Player) - return 0; + if (SpecialMove.GetCurrentMove(attacker)?.OnBeforeSwing(attacker, defender) == false) + SpecialMove.ClearCurrentMove(attacker); + } - if (!(attacker is BaseCreature bc) || bc.PackInstinct == PackInstinct.None || (!bc.Controlled && !bc.Summoned)) - return 0; + public virtual TimeSpan OnSwing(Mobile attacker, Mobile defender) => OnSwing(attacker, defender, 1.0); - Mobile master = bc.ControlMaster ?? bc.SummonMaster; + public virtual void GetStatusDamage(Mobile from, out int min, out int max) + { + GetBaseDamageRange(from, out var baseMin, out var baseMax); - if (master == null) - return 0; + if (Core.AOS) + { + min = Math.Max((int)ScaleDamageAOS(from, baseMin, false), 1); + max = Math.Max((int)ScaleDamageAOS(from, baseMax, false), 1); + } + else + { + min = Math.Max((int)ScaleDamageOld(from, baseMin, false), 1); + max = Math.Max((int)ScaleDamageOld(from, baseMax, false), 1); + } + } - IPooledEnumerable eable = defender.GetMobilesInRange(1); - int inPack = 1 + eable.Where(m => m != attacker && (m.PackInstinct & bc.PackInstinct) != 0 && (m.Controlled || m.Summoned)) - .Count(m => master == (m.ControlMaster ?? m.SummonMaster) && m.Combatant == defender); + public virtual TimeSpan OnSwing(Mobile attacker, Mobile defender, double damageBonus) + { + var canSwing = true; - eable.Free(); + if (Core.AOS) + { + canSwing = !attacker.Paralyzed && !attacker.Frozen; - return inPack >= 5 ? 100 : inPack >= 4 ? 75 : inPack >= 3 ? 50 : inPack >= 2 ? 25 : 0; - } + if (canSwing) canSwing = !(attacker.Spell is Spell sp) || !sp.IsCasting || !sp.BlocksMovement; - public virtual void OnHit(Mobile attacker, Mobile defender, double damageBonus = 1.0) - { - if (MirrorImage.HasClone(defender) && defender.Skills.Ninjitsu.Value / 150.0 > Utility.RandomDouble()) - { - IPooledEnumerable eable = defender.GetMobilesInRange(4); - foreach (Clone m in eable) - if (m?.Summoned == true && m.SummonMaster == defender) - { - attacker.SendLocalizedMessage( - 1063141); // Your attack has been diverted to a nearby mirror image of your target! - defender.SendLocalizedMessage( - 1063140); // You manage to divert the attack onto one of your nearby mirror images. + if (canSwing) canSwing = !(attacker is PlayerMobile p) || p.PeacedUntil <= DateTime.UtcNow; + } + + if ((attacker as PlayerMobile)?.DuelContext?.CheckItemEquip(attacker, this) == false) + canSwing = false; + + if (canSwing && attacker.HarmfulCheck(defender)) + { + attacker.DisruptiveAction(); + + if (attacker.NetState != null) + attacker.Send(new Swing(attacker.Serial, defender.Serial)); + + if (attacker is BaseCreature bc) + { + var ab = bc.GetWeaponAbility(); + + if (ab != null) + { + if (bc.WeaponAbilityChance > Utility.RandomDouble()) + WeaponAbility.SetCurrentAbility(bc, ab); + else + WeaponAbility.ClearCurrentAbility(bc); + } + } + + if (CheckHit(attacker, defender)) + OnHit(attacker, defender, damageBonus); + else + OnMiss(attacker, defender); + } + + return GetDelay(attacker); + } + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxRange + { + get => m_MaxRange == -1 ? Core.AOS ? AosMaxRange : OldMaxRange : m_MaxRange; + set + { + m_MaxRange = value; + InvalidateProperties(); + } + } + + public override void OnAfterDuped(Item newItem) + { + if (!(newItem is BaseWeapon weap)) + return; + + weap.Attributes = new AosAttributes(newItem, Attributes); + weap.AosElementDamages = new AosElementAttributes(newItem, AosElementDamages); + weap.SkillBonuses = new AosSkillBonuses(newItem, SkillBonuses); + weap.WeaponAttributes = new AosWeaponAttributes(newItem, WeaponAttributes); + } + + public int GetDurabilityBonus() + { + var bonus = 0; + + if (m_Quality == WeaponQuality.Exceptional) + bonus += 20; + + switch (m_DurabilityLevel) + { + case WeaponDurabilityLevel.Durable: + bonus += 20; + break; + case WeaponDurabilityLevel.Substantial: + bonus += 50; + break; + case WeaponDurabilityLevel.Massive: + bonus += 70; + break; + case WeaponDurabilityLevel.Fortified: + bonus += 100; + break; + case WeaponDurabilityLevel.Indestructible: + bonus += 120; + break; + } + + if (Core.AOS) + { + bonus += WeaponAttributes.DurabilityBonus; + + var resInfo = CraftResources.GetInfo(m_Resource); + CraftAttributeInfo attrInfo = null; + + if (resInfo != null) + attrInfo = resInfo.AttributeInfo; + + if (attrInfo != null) + bonus += attrInfo.WeaponDurability; + } + + return bonus; + } + + public int GetLowerStatReq() + { + if (!Core.AOS) + return 0; + + var v = WeaponAttributes.LowerStatReq; + + var attrInfo = CraftResources.GetInfo(m_Resource)?.AttributeInfo; + + if (attrInfo != null) + v += attrInfo.WeaponLowerRequirements; + + if (v > 100) + v = 100; + + return v; + } + + public static void BlockEquip(Mobile m, TimeSpan duration) + { + if (m.BeginAction()) + new ResetEquipTimer(m, duration).Start(); + } + + public override bool CheckConflictingLayer(Mobile m, Item item, Layer layer) + { + if (base.CheckConflictingLayer(m, item, layer)) + return true; + + if (Layer == Layer.TwoHanded && layer == Layer.OneHanded) + { + m.SendLocalizedMessage(500214); // You already have something in both hands. + return true; + } + + if (Layer == Layer.OneHanded && layer == Layer.TwoHanded && !(item is BaseShield) && + !(item is BaseEquipableLight)) + { + m.SendLocalizedMessage(500215); // You can only wield one weapon at a time. + return true; + } + + return false; + } + + public override bool AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted) => + Ethic.CheckTrade(from, to, newOwner, this) && + base.AllowSecureTrade(from, to, newOwner, accepted); + + public override bool CanEquip(Mobile from) + { + if (!Ethic.CheckEquip(from, this)) + return false; + + if (RequiredRace != null && from.Race != RequiredRace) + { + if (RequiredRace == Race.Elf) + from.SendLocalizedMessage(1072203); // Only Elves may use this. + else + from.SendMessage("Only {0} may use this.", RequiredRace.PluralName); + + return false; + } + + if (from.Dex < DexRequirement) + { + from.SendMessage("You are not nimble enough to equip that."); + return false; + } + + if (from.Str < AOS.Scale(StrRequirement, 100 - GetLowerStatReq())) + { + from.SendLocalizedMessage(500213); // You are not strong enough to equip that. + return false; + } + + if (from.Int < IntRequirement) + { + from.SendMessage("You are not smart enough to equip that."); + return false; + } + + return from.CanBeginAction() && base.CanEquip(from); + } + + public override bool OnEquip(Mobile from) + { + var strBonus = Attributes.BonusStr; + var dexBonus = Attributes.BonusDex; + var intBonus = Attributes.BonusInt; + + if (strBonus != 0 || dexBonus != 0 || intBonus != 0) + { + var m = from; + + var modName = Serial.ToString(); + + if (strBonus != 0) + m.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero)); + + if (dexBonus != 0) + m.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero)); + + if (intBonus != 0) + m.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero)); + } + + from.NextCombatTime = Core.TickCount + (int)GetDelay(from).TotalMilliseconds; + + if (UseSkillMod && m_AccuracyLevel != WeaponAccuracyLevel.Regular) + { + m_SkillMod?.Remove(); + + m_SkillMod = new DefaultSkillMod(AccuracySkill, true, (int)m_AccuracyLevel * 5); + from.AddSkillMod(m_SkillMod); + } + + if (Core.AOS && WeaponAttributes.MageWeapon != 0 && WeaponAttributes.MageWeapon != 30) + { + m_MageMod?.Remove(); + + m_MageMod = new DefaultSkillMod(SkillName.Magery, true, -30 + WeaponAttributes.MageWeapon); + from.AddSkillMod(m_MageMod); + } + + return true; + } + + public override void OnAdded(IEntity parent) + { + base.OnAdded(parent); + + if (parent is Mobile from) + { + if (Core.AOS) + SkillBonuses.AddTo(from); + + from.CheckStatTimers(); + from.Delta(MobileDelta.WeaponDamage); + } + } + + public override void OnRemoved(IEntity parent) + { + if (parent is Mobile m) + { + var weapon = m.Weapon as BaseWeapon; + + var modName = Serial.ToString(); + + m.RemoveStatMod($"{modName}Str"); + m.RemoveStatMod($"{modName}Dex"); + m.RemoveStatMod($"{modName}Int"); + + if (weapon != null) + m.NextCombatTime = Core.TickCount + (int)weapon.GetDelay(m).TotalMilliseconds; + + if (UseSkillMod && m_SkillMod != null) + { + m_SkillMod.Remove(); + m_SkillMod = null; + } + + if (m_MageMod != null) + { + m_MageMod.Remove(); + m_MageMod = null; + } + + if (Core.AOS) + SkillBonuses.Remove(); + + ImmolatingWeaponSpell.StopImmolating(this); + + m.CheckStatTimers(); + + m.Delta(MobileDelta.WeaponDamage); + } + } + + public virtual SkillName GetUsedSkill(Mobile m, bool checkSkillAttrs) + { + SkillName sk; + + if (checkSkillAttrs && WeaponAttributes.UseBestSkill != 0) + { + var swrd = m.Skills.Swords.Value; + var fenc = m.Skills.Fencing.Value; + var mcng = m.Skills.Macing.Value; + double val; + + sk = SkillName.Swords; + val = swrd; + + if (fenc > val) + { + sk = SkillName.Fencing; + val = fenc; + } + + if (mcng > val) sk = SkillName.Macing; + } + else if (WeaponAttributes.MageWeapon != 0) + { + if (m.Skills.Magery.Value > m.Skills[Skill].Value) + sk = SkillName.Magery; + else + sk = Skill; + } + else + { + sk = Skill; + + if (sk != SkillName.Wrestling && !m.Player && !m.Body.IsHuman && + m.Skills.Wrestling.Value > m.Skills[sk].Value) + sk = SkillName.Wrestling; + } + + return sk; + } + + public virtual double GetAttackSkillValue(Mobile attacker, Mobile defender) => + attacker.Skills[GetUsedSkill(attacker, true)].Value; + + public virtual double GetDefendSkillValue(Mobile attacker, Mobile defender) => + defender.Skills[GetUsedSkill(defender, true)].Value; + + private static bool CheckAnimal(Mobile m, Type type) => AnimalForm.UnderTransformation(m, type); + + public virtual bool CheckHit(Mobile attacker, Mobile defender) + { + var atkWeapon = attacker.Weapon as BaseWeapon; + var defWeapon = defender.Weapon as BaseWeapon; + + var atkSkill = attacker.Skills[atkWeapon?.Skill ?? SkillName.Wrestling]; + // Skill defSkill = defender.Skills[defWeapon.Skill]; + + var atkValue = atkWeapon?.GetAttackSkillValue(attacker, defender) ?? 0.0; + var defValue = defWeapon?.GetDefendSkillValue(attacker, defender) ?? 0.0; + + double ourValue, theirValue; + + var bonus = GetHitChanceBonus(); + + if (Core.AOS) + { + if (atkValue <= -20.0) + atkValue = -19.9; + + if (defValue <= -20.0) + defValue = -19.9; + + bonus += AosAttributes.GetValue(attacker, AosAttribute.AttackChance); + + if (DivineFurySpell.UnderEffect(attacker)) + bonus += 10; // attacker gets 10% bonus when they're under divine fury + + if (CheckAnimal(attacker, typeof(GreyWolf)) || CheckAnimal(attacker, typeof(BakeKitsune))) + bonus += 20; // attacker gets 20% bonus when under Wolf or Bake Kitsune form + + if (HitLower.IsUnderAttackEffect(attacker)) + bonus -= 25; // Under Hit Lower Attack effect -> 25% malus + + var ability = WeaponAbility.GetCurrentAbility(attacker); + + if (ability != null) + bonus += ability.AccuracyBonus; + + var move = SpecialMove.GetCurrentMove(attacker); + + if (move != null) + bonus += move.GetAccuracyBonus(attacker); + + // Max Hit Chance Increase = 45% + if (bonus > 45) + bonus = 45; + + ourValue = (atkValue + 20.0) * (100 + bonus); + + bonus = AosAttributes.GetValue(defender, AosAttribute.DefendChance); + + if (DivineFurySpell.UnderEffect(defender)) + bonus -= 20; // defender loses 20% bonus when they're under divine fury + + if (HitLower.IsUnderDefenseEffect(defender)) + bonus -= 25; // Under Hit Lower Defense effect -> 25% malus + + var blockBonus = 0; + + if (Block.GetBonus(defender, ref blockBonus)) + bonus += blockBonus; + + var surpriseMalus = 0; + + if (SurpriseAttack.GetMalus(defender, ref surpriseMalus)) + bonus -= surpriseMalus; + + var discordanceEffect = 0; + + // Defender loses -0/-28% if under the effect of Discordance. + if (Discordance.GetEffect(attacker, ref discordanceEffect)) + bonus -= discordanceEffect; + + // Defense Chance Increase = 45% + if (bonus > 45) + bonus = 45; + + theirValue = (defValue + 20.0) * (100 + bonus); + + bonus = 0; + } + else + { + if (atkValue <= -50.0) + atkValue = -49.9; + + if (defValue <= -50.0) + defValue = -49.9; + + ourValue = atkValue + 50.0; + theirValue = defValue + 50.0; + } + + var chance = ourValue / (theirValue * 2.0); + + chance *= 1.0 + (double)bonus / 100; + + if (Core.AOS && chance < 0.02) + chance = 0.02; + + return attacker.CheckSkill(atkSkill.SkillName, chance); + } + + public virtual TimeSpan GetDelay(Mobile m) + { + double speed = Speed; + + if (speed == 0) + return TimeSpan.FromHours(1.0); + + double delayInSeconds; + + if (Core.SE) + { + /* + * This is likely true for Core.AOS as well... both guides report the same + * formula, and both are wrong. + * The old formula left in for AOS for legacy & because we aren't quite 100% + * Sure that AOS has THIS formula + */ + var bonus = AosAttributes.GetValue(m, AosAttribute.WeaponSpeed); + + if (DivineFurySpell.UnderEffect(m)) + bonus += 10; + + // Bonus granted by successful use of Honorable Execution. + bonus += HonorableExecution.GetSwingBonus(m); + + if (DualWield.Registry.ContainsKey(m)) + bonus += DualWield.Registry[m].BonusSwingSpeed; + + if (Feint.Registry.ContainsKey(m)) + bonus -= Feint.Registry[m].SwingSpeedReduction; + + var context = TransformationSpellHelper.GetContext(m); + + if (context?.Spell is ReaperFormSpell spell) + bonus += spell.SwingSpeedBonus; + + var discordanceEffect = 0; + + // Discordance gives a malus of -0/-28% to swing speed. + if (Discordance.GetEffect(m, ref discordanceEffect)) + bonus -= discordanceEffect; + + if (EssenceOfWindSpell.IsDebuffed(m)) + bonus -= EssenceOfWindSpell.GetSSIMalus(m); + + if (bonus > 60) + bonus = 60; + + double ticks; + + if (Core.ML) + { + var stamTicks = m.Stam / 30; + + ticks = speed * 4; + ticks = Math.Floor((ticks - stamTicks) * (100.0 / (100 + bonus))); + } + else + { + speed = Math.Floor(speed * (bonus + 100.0) / 100.0); + + if (speed <= 0) + speed = 1; + + ticks = Math.Floor(80000.0 / ((m.Stam + 100) * speed) - 2); + } + + // Swing speed currently capped at one swing every 1.25 seconds (5 ticks). + if (ticks < 5) + ticks = 5; + + delayInSeconds = ticks * 0.25; + } + else if (Core.AOS) + { + var v = (m.Stam + 100) * (int)speed; + + var bonus = AosAttributes.GetValue(m, AosAttribute.WeaponSpeed); + + if (DivineFurySpell.UnderEffect(m)) + bonus += 10; + + var discordanceEffect = 0; + + // Discordance gives a malus of -0/-28% to swing speed. + if (Discordance.GetEffect(m, ref discordanceEffect)) + bonus -= discordanceEffect; + + v += AOS.Scale(v, bonus); + + if (v <= 0) + v = 1; + + delayInSeconds = Math.Floor(40000.0 / v) * 0.5; + + // Maximum swing rate capped at one swing per second + // OSI dev said that it has and is supposed to be 1.25 + if (delayInSeconds < 1.25) + delayInSeconds = 1.25; + } + else + { + var v = (m.Stam + 100) * (int)speed; + + if (v <= 0) + v = 1; + + delayInSeconds = 15000.0 / v; + } + + return TimeSpan.FromSeconds(delayInSeconds); + } + + public static bool CheckParry(Mobile defender) + { + if (defender == null) + return false; + + var shield = defender.FindItemOnLayer(Layer.TwoHanded) as BaseShield; + + var parry = defender.Skills.Parry.Value; + var bushidoNonRacial = defender.Skills.Bushido.NonRacialValue; + var bushido = defender.Skills.Bushido.Value; + double chance; + + if (shield != null) + { + // As per OSI, no genitive effect from the Racial stuffs, ie, 120 parry and '0' bushido with humans + chance = Math.Max((parry - bushidoNonRacial) / 400.0, 0); + + // Parry/Bushido over 100 grants a 5% bonus. + if (parry >= 100.0 || bushido >= 100.0) + chance += 0.05; + + // Evasion grants a variable bonus post ML. 50% prior. + if (Evasion.IsEvading(defender)) + chance *= Evasion.GetParryScalar(defender); + + // Low dexterity lowers the chance. + if (defender.Dex < 80) + chance = chance * (20 + defender.Dex) / 100; + + return defender.CheckSkill(SkillName.Parry, chance); + } + + if (defender.Weapon is Fists || defender.Weapon is BaseRanged) + return false; + + var weapon = defender.Weapon as BaseWeapon; + + var divisor = weapon?.Layer == Layer.OneHanded ? 48000.0 : 41140.0; + + chance = parry * bushido / divisor; + + var aosChance = parry / 800.0; + + // Parry or Bushido over 100 grant a 5% bonus. + if (parry >= 100.0) + { + chance += 0.05; + aosChance += 0.05; + } + else if (bushido >= 100.0) + { + chance += 0.05; + } + + // Evasion grants a variable bonus post ML. 50% prior. + if (Evasion.IsEvading(defender)) + chance *= Evasion.GetParryScalar(defender); + + // Low dexterity lowers the chance. + if (defender.Dex < 80) + chance = chance * (20 + defender.Dex) / 100; + + if (chance > aosChance) + return defender.CheckSkill(SkillName.Parry, chance); + + return + aosChance > Utility + .RandomDouble(); // Only skillcheck if wielding a shield & there's no effect from Bushido + } + + public virtual int AbsorbDamageAOS(Mobile attacker, Mobile defender, int damage) + { + var blocked = false; + + if (defender.Player || defender.Body.IsHuman) + { + blocked = CheckParry(defender); + + if (blocked) + { + defender.FixedEffect(0x37B9, 10, 16); + damage = 0; + + // Successful block removes the Honorable Execution penalty. + HonorableExecution.RemovePenalty(defender); + + if (CounterAttack.IsCountering(defender)) + { + if (defender.Weapon is BaseWeapon weapon) + { + defender.FixedParticles(0x3779, 1, 15, 0x158B, 0x0, 0x3, EffectLayer.Waist); + weapon.OnSwing(defender, attacker); + } + + CounterAttack.StopCountering(defender); + } + + if (Confidence.IsConfident(defender)) + { + defender.SendLocalizedMessage( + 1063117 + ); // Your confidence reassures you as you successfully block your opponent's blow. + + var bushido = defender.Skills.Bushido.Value; + + defender.Hits += Utility.RandomMinMax(1, (int)(bushido / 12)); + defender.Stam += Utility.RandomMinMax(1, (int)(bushido / 5)); + } + + var shield = defender.FindItemOnLayer(Layer.TwoHanded) as BaseShield; + + shield?.OnHit(this, damage); + } + } + + if (!blocked) + { + var positionChance = Utility.RandomDouble(); + + Item armorItem; + + if (positionChance < 0.07) + armorItem = defender.NeckArmor; + else if (positionChance < 0.14) + armorItem = defender.HandArmor; + else if (positionChance < 0.28) + armorItem = defender.ArmsArmor; + else if (positionChance < 0.43) + armorItem = defender.HeadArmor; + else if (positionChance < 0.65) + armorItem = defender.LegsArmor; + else + armorItem = defender.ChestArmor; + + if (armorItem is IWearableDurability armor) + armor.OnHit(this, damage); // call OnHit to lose durability + } + + return damage; + } + + public virtual int AbsorbDamage(Mobile attacker, Mobile defender, int damage) + { + if (Core.AOS) + return AbsorbDamageAOS(attacker, defender, damage); + + if (defender.FindItemOnLayer(Layer.TwoHanded) is BaseShield shield) + damage = shield.OnHit(this, damage); + + var chance = Utility.RandomDouble(); + + Item armorItem; + + if (chance < 0.07) + armorItem = defender.NeckArmor; + else if (chance < 0.14) + armorItem = defender.HandArmor; + else if (chance < 0.28) + armorItem = defender.ArmsArmor; + else if (chance < 0.43) + armorItem = defender.HeadArmor; + else if (chance < 0.65) + armorItem = defender.LegsArmor; + else + armorItem = defender.ChestArmor; + + if (armorItem is IWearableDurability armor) + damage = armor.OnHit(this, damage); + + var virtualArmor = defender.VirtualArmor + defender.VirtualArmorMod; + + if (virtualArmor > 0) + { + double scalar; + + if (chance < 0.14) + scalar = 0.07; + else if (chance < 0.28) + scalar = 0.14; + else if (chance < 0.43) + scalar = 0.15; + else if (chance < 0.65) + scalar = 0.22; + else + scalar = 0.35; + + var from = (int)(virtualArmor * scalar) / 2; + var to = (int)(virtualArmor * scalar); + + damage -= Utility.Random(from, to - from + 1); + } + + return damage; + } + + public virtual int GetPackInstinctBonus(Mobile attacker, Mobile defender) + { + if (attacker.Player || defender.Player) + return 0; + + if (!(attacker is BaseCreature bc) || bc.PackInstinct == PackInstinct.None || !bc.Controlled && !bc.Summoned) + return 0; + + var master = bc.ControlMaster ?? bc.SummonMaster; + + if (master == null) + return 0; + + var eable = defender.GetMobilesInRange(1); + var inPack = 1 + eable + .Where(m => m != attacker && (m.PackInstinct & bc.PackInstinct) != 0 && (m.Controlled || m.Summoned)) + .Count(m => master == (m.ControlMaster ?? m.SummonMaster) && m.Combatant == defender); + + eable.Free(); + + return inPack >= 5 ? 100 : + inPack >= 4 ? 75 : + inPack >= 3 ? 50 : + inPack >= 2 ? 25 : 0; + } + + public virtual void OnHit(Mobile attacker, Mobile defender, double damageBonus = 1.0) + { + if (MirrorImage.HasClone(defender) && defender.Skills.Ninjitsu.Value / 150.0 > Utility.RandomDouble()) + { + var eable = defender.GetMobilesInRange(4); + foreach (var m in eable) + if (m?.Summoned == true && m.SummonMaster == defender) + { + attacker.SendLocalizedMessage( + 1063141 + ); // Your attack has been diverted to a nearby mirror image of your target! + defender.SendLocalizedMessage( + 1063140 + ); // You manage to divert the attack onto one of your nearby mirror images. + + /* + * TODO: What happens if the Clone parries a blow? + * And what about if the attacker is using Honorable Execution + * and kills it? + */ + + defender = m; + break; + } + + eable.Free(); + } + + PlaySwingAnimation(attacker); + PlayHurtAnimation(defender); + + attacker.PlaySound(GetHitAttackSound(attacker, defender)); + defender.PlaySound(GetHitDefendSound(attacker, defender)); + + var damage = ComputeDamage(attacker, defender); /* - * TODO: What happens if the Clone parries a blow? - * And what about if the attacker is using Honorable Execution - * and kills it? + * The following damage bonuses multiply damage by a factor. + * Capped at x3 (300%). + */ + var percentageBonus = 0; + + var a = WeaponAbility.GetCurrentAbility(attacker); + var move = SpecialMove.GetCurrentMove(attacker); + + if (a != null) percentageBonus += (int)(a.DamageScalar * 100) - 100; + + if (move != null) percentageBonus += (int)(move.GetDamageScalar(attacker, defender) * 100) - 100; + + percentageBonus += (int)(damageBonus * 100) - 100; + + var cs = CheckSlayers(attacker, defender); + + if (cs != CheckSlayerResult.None) + { + if (cs == CheckSlayerResult.Slayer) + defender.FixedEffect(0x37B9, 10, 5); + + percentageBonus += 100; + } + + if (!attacker.Player) + { + if (defender is PlayerMobile pm) + if (pm.EnemyOfOneType != null && pm.EnemyOfOneType != attacker.GetType()) + percentageBonus += 100; + } + else if (!defender.Player) + { + if (attacker is PlayerMobile pm) + { + if (pm.WaitingForEnemy) + { + pm.EnemyOfOneType = defender.GetType(); + pm.WaitingForEnemy = false; + } + + if (pm.EnemyOfOneType == defender.GetType()) + { + defender.FixedEffect(0x37B9, 10, 5, 1160, 0); + + percentageBonus += 50; + } + } + } + + var packInstinctBonus = GetPackInstinctBonus(attacker, defender); + + if (packInstinctBonus != 0) percentageBonus += packInstinctBonus; + + if (InDoubleStrike) percentageBonus -= 10; + + var context = TransformationSpellHelper.GetContext(defender); + + if ((m_Slayer == SlayerName.Silver || m_Slayer2 == SlayerName.Silver) && context?.Spell is NecromancerSpell && + context.Type != typeof(HorrificBeastSpell)) percentageBonus += 25; + + if (attacker is PlayerMobile pmAttacker && !(Core.ML && defender is PlayerMobile)) + { + if (pmAttacker.HonorActive && pmAttacker.InRange(defender, 1)) percentageBonus += 25; + + if (pmAttacker.SentHonorContext != null && pmAttacker.SentHonorContext.Target == defender) + percentageBonus += pmAttacker.SentHonorContext.PerfectionDamageBonus; + } + + if (attacker.Talisman is BaseTalisman talisman && talisman.Killer != null) + percentageBonus += talisman.Killer.DamageBonus(defender); + + percentageBonus = Math.Min(percentageBonus, 300); + + damage = AOS.Scale(damage, 100 + percentageBonus); + + var bcAtt = attacker as BaseCreature; + var bcDef = defender as BaseCreature; + + bcAtt?.AlterMeleeDamageTo(defender, ref damage); + bcDef?.AlterMeleeDamageFrom(attacker, ref damage); + + damage = AbsorbDamage(attacker, defender, damage); + + if (!Core.AOS && damage < 1) + damage = 1; + else if (Core.AOS && damage == 0) // parried + if (a?.Validate(attacker) == true) /*&& a.CheckMana( attacker, true )*/ + // Parried special moves have no mana cost + { + a = null; + WeaponAbility.ClearCurrentAbility(attacker); + + attacker.SendLocalizedMessage(1061140); // Your attack was parried! + } + + AddBlood(attacker, defender, damage); + + GetDamageTypes( + attacker, + out var phys, + out var fire, + out var cold, + out var pois, + out var nrgy, + out var chaos, + out var direct + ); + + if (Core.ML && this is BaseRanged) + if (attacker.FindItemOnLayer(Layer.Cloak) is BaseQuiver quiver) + quiver.AlterBowDamage(ref phys, ref fire, ref cold, ref pois, ref nrgy, ref chaos, ref direct); + + if (Consecrated) + { + phys = defender.PhysicalResistance; + fire = defender.FireResistance; + cold = defender.ColdResistance; + pois = defender.PoisonResistance; + nrgy = defender.EnergyResistance; + + int low = phys, type = 0; + + if (fire < low) + { + low = fire; + type = 1; + } + + if (cold < low) + { + low = cold; + type = 2; + } + + if (pois < low) + { + low = pois; + type = 3; + } + + if (nrgy < low) type = 4; + + phys = fire = cold = pois = nrgy = chaos = direct = 0; + + if (type == 0) phys = 100; + else if (type == 1) fire = 100; + else if (type == 2) cold = 100; + else if (type == 3) pois = 100; + else if (type == 4) nrgy = 100; + } + + // TODO: Scale damage, alongside the leech effects below, to weapon speed. + if (ImmolatingWeaponSpell.IsImmolating(this) && damage > 0) + ImmolatingWeaponSpell.DoEffect(this, defender); + + var damageGiven = damage; + + if (a?.OnBeforeDamage(attacker, defender) == false) + { + WeaponAbility.ClearCurrentAbility(attacker); + a = null; + } + + if (move?.OnBeforeDamage(attacker, defender) == false) + { + SpecialMove.ClearCurrentMove(attacker); + move = null; + } + + var ignoreArmor = a is ArmorIgnore || move?.IgnoreArmor(attacker) == true; + + damageGiven = AOS.Damage( + defender, + attacker, + damage, + ignoreArmor, + phys, + fire, + cold, + pois, + nrgy, + chaos, + direct, + false, + this is BaseRanged + ); + + var propertyBonus = move?.GetPropertyBonus(attacker) ?? 1.0; + + if (Core.AOS) + { + var lifeLeech = 0; + var stamLeech = 0; + var manaLeech = 0; + int wraithLeech; + + if ((int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLeechHits) * propertyBonus) > + Utility.Random(100)) + lifeLeech += 30; // HitLeechHits% chance to leech 30% of damage as hit points + + if ((int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLeechStam) * propertyBonus) > + Utility.Random(100)) + stamLeech += 100; // HitLeechStam% chance to leech 100% of damage as stamina + + if ((int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLeechMana) * propertyBonus) > + Utility.Random(100)) + manaLeech += 40; // HitLeechMana% chance to leech 40% of damage as mana + + if (Cursed) + lifeLeech += 50; // Additional 50% life leech for cursed weapons (necro spell) + + context = TransformationSpellHelper.GetContext(attacker); + + if (context?.Type == typeof(VampiricEmbraceSpell)) + lifeLeech += 20; // Vampiric embrace gives an additional 20% life leech + + if (context?.Type == typeof(WraithFormSpell)) + { + wraithLeech = + 5 + (int)(15 * attacker.Skills.SpiritSpeak.Value / + 100); // Wraith form gives an additional 5-20% mana leech + + // Mana leeched by the Wraith Form spell is actually stolen, not just leeched. + defender.Mana -= AOS.Scale(damageGiven, wraithLeech); + + manaLeech += wraithLeech; + } + + if (lifeLeech != 0) + attacker.Hits += AOS.Scale(damageGiven, lifeLeech); + + if (stamLeech != 0) + attacker.Stam += AOS.Scale(damageGiven, stamLeech); + + if (manaLeech != 0) + attacker.Mana += AOS.Scale(damageGiven, manaLeech); + + if (lifeLeech != 0 || stamLeech != 0 || manaLeech != 0) + attacker.PlaySound(0x44D); + } + + if (m_MaxHits > 0 && (MaxRange <= 1 && (defender is Slime || defender is AcidElemental) || + Utility.RandomDouble() < .04)) // Stratics says 50% chance, seems more like 4%.. + { + if (MaxRange <= 1 && (defender is Slime || defender is AcidElemental)) + attacker.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500263); // *Acid blood scars your weapon!* + + if (Core.AOS && WeaponAttributes.SelfRepair > Utility.Random(10)) + { + HitPoints += 2; + } + else + { + if (m_Hits > 0) + { + --HitPoints; + } + else if (m_MaxHits > 1) + { + --MaxHitPoints; + + if (Parent is Mobile mobile) + mobile.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1061121 + ); // Your equipment is severely damaged. + } + else + { + Delete(); + } + } + } + + if (attacker is VampireBatFamiliar bc) + { + var caster = bc.ControlMaster ?? bc.SummonMaster; + + if (caster != null && caster.Map == bc.Map && caster.InRange(bc, 2)) + caster.Hits += damage; + else + bc.Hits += damage; + } + + if (Core.AOS) + { + var physChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitPhysicalArea) * + propertyBonus); + var fireChance = + (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitFireArea) * propertyBonus); + var coldChance = + (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitColdArea) * propertyBonus); + var poisChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitPoisonArea) * + propertyBonus); + var nrgyChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitEnergyArea) * + propertyBonus); + + if (physChance != 0 && physChance > Utility.Random(100)) + DoAreaAttack(attacker, defender, 0x10E, 50, 100, 0, 0, 0, 0); + + if (fireChance != 0 && fireChance > Utility.Random(100)) + DoAreaAttack(attacker, defender, 0x11D, 1160, 0, 100, 0, 0, 0); + + if (coldChance != 0 && coldChance > Utility.Random(100)) + DoAreaAttack(attacker, defender, 0x0FC, 2100, 0, 0, 100, 0, 0); + + if (poisChance != 0 && poisChance > Utility.Random(100)) + DoAreaAttack(attacker, defender, 0x205, 1166, 0, 0, 0, 100, 0); + + if (nrgyChance != 0 && nrgyChance > Utility.Random(100)) + DoAreaAttack(attacker, defender, 0x1F1, 120, 0, 0, 0, 0, 100); + + var maChance = + (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitMagicArrow) * propertyBonus); + var harmChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitHarm) * propertyBonus); + var fireballChance = + (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitFireball) * propertyBonus); + var lightningChance = + (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLightning) * propertyBonus); + var dispelChance = + (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitDispel) * propertyBonus); + + if (maChance != 0 && maChance > Utility.Random(100)) + DoMagicArrow(attacker, defender); + + if (harmChance != 0 && harmChance > Utility.Random(100)) + DoHarm(attacker, defender); + + if (fireballChance != 0 && fireballChance > Utility.Random(100)) + DoFireball(attacker, defender); + + if (lightningChance != 0 && lightningChance > Utility.Random(100)) + DoLightning(attacker, defender); + + if (dispelChance != 0 && dispelChance > Utility.Random(100)) + DoDispel(attacker, defender); + + var laChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLowerAttack) * + propertyBonus); + var ldChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLowerDefend) * + propertyBonus); + + if (laChance != 0 && laChance > Utility.Random(100)) + DoLowerAttack(attacker, defender); + + if (ldChance != 0 && ldChance > Utility.Random(100)) + DoLowerDefense(attacker, defender); + } + + bcAtt?.OnGaveMeleeAttack(defender); + bcDef?.OnGotMeleeAttack(attacker); + + a?.OnHit(attacker, defender, damage); + move?.OnHit(attacker, defender, damage); + + if (defender is IHonorTarget it) + it.ReceivedHonorContext?.OnTargetHit(attacker); + + if (!(this is BaseRanged)) + { + if (AnimalForm.UnderTransformation(attacker, typeof(GiantSerpent))) + defender.ApplyPoison(attacker, Poison.Lesser); + + if (AnimalForm.UnderTransformation(defender, typeof(BullFrog))) + attacker.ApplyPoison(defender, Poison.Regular); + } + } + + public virtual double GetAosDamage(Mobile attacker, int bonus, uint dice, uint sides) + { + var damage = Utility.Dice(dice, sides, bonus) * 100; + + // Inscription bonus + var inscribeSkill = attacker.Skills.Inscribe.Fixed; + + var damageBonus = inscribeSkill / 200; + + if (inscribeSkill >= 1000) + damageBonus += 5; + + if (attacker.Player) + { + // Int bonus + damageBonus += attacker.Int / 10; + + // SDI bonus + damageBonus += AosAttributes.GetValue(attacker, AosAttribute.SpellDamage); + + var context = TransformationSpellHelper.GetContext(attacker); + + if (context?.Spell is ReaperFormSpell spell) + damageBonus += spell.SpellDamageBonus; + } + + damage = AOS.Scale(damage, 100 + damageBonus); + + return damage / 100.0; + } + + public virtual CheckSlayerResult CheckSlayers(Mobile attacker, Mobile defender) + { + var atkWeapon = attacker.Weapon as BaseWeapon; + var atkSlayer = SlayerGroup.GetEntryByName(atkWeapon?.Slayer ?? SlayerName.None); + var atkSlayer2 = SlayerGroup.GetEntryByName(atkWeapon?.Slayer2 ?? SlayerName.None); + + if (atkWeapon is ButchersWarCleaver && TalismanSlayer.Slays(TalismanSlayerName.Bovine, defender)) + return CheckSlayerResult.Slayer; + + if (atkSlayer?.Slays(defender) == true || atkSlayer2?.Slays(defender) == true) + return CheckSlayerResult.Slayer; + + if (attacker.Talisman is BaseTalisman talisman && TalismanSlayer.Slays(talisman.Slayer, defender)) + return CheckSlayerResult.Slayer; + + if (!Core.SE) + { + var defISlayer = Spellbook.FindEquippedSpellbook(defender) ?? defender.Weapon as ISlayer; + + if (defISlayer != null) + { + var defSlayer = SlayerGroup.GetEntryByName(defISlayer.Slayer); + var defSlayer2 = SlayerGroup.GetEntryByName(defISlayer.Slayer2); + + if (defSlayer?.Group.OppositionSuperSlays(attacker) == true || + defSlayer2?.Group.OppositionSuperSlays(attacker) == true) + return CheckSlayerResult.Opposition; + } + } + + return CheckSlayerResult.None; + } + + public virtual void AddBlood(Mobile attacker, Mobile defender, int damage) + { + if (damage <= 0) + return; + + new Blood().MoveToWorld(defender.Location, defender.Map); + + var extraBlood = Core.SE ? Utility.RandomMinMax(3, 4) : Utility.RandomMinMax(0, 1); + + for (var i = 0; i < extraBlood; i++) + new Blood().MoveToWorld( + new Point3D( + defender.X + Utility.RandomMinMax(-1, 1), + defender.Y + Utility.RandomMinMax(-1, 1), + defender.Z + ), + defender.Map + ); + } + + public virtual void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + if (wielder is BaseCreature bc) + { + phys = bc.PhysicalDamage; + fire = bc.FireDamage; + cold = bc.ColdDamage; + pois = bc.PoisonDamage; + nrgy = bc.EnergyDamage; + chaos = bc.ChaosDamage; + direct = bc.DirectDamage; + } + else + { + fire = AosElementDamages.Fire; + cold = AosElementDamages.Cold; + pois = AosElementDamages.Poison; + nrgy = AosElementDamages.Energy; + chaos = AosElementDamages.Chaos; + direct = AosElementDamages.Direct; + + phys = 100 - fire - cold - pois - nrgy - chaos - direct; + + var attrInfo = CraftResources.GetInfo(m_Resource)?.AttributeInfo; + + if (attrInfo != null) + { + var left = phys; + + left = ApplyCraftAttributeElementDamage(attrInfo.WeaponColdDamage, ref cold, left); + left = ApplyCraftAttributeElementDamage(attrInfo.WeaponEnergyDamage, ref nrgy, left); + left = ApplyCraftAttributeElementDamage(attrInfo.WeaponFireDamage, ref fire, left); + left = ApplyCraftAttributeElementDamage(attrInfo.WeaponPoisonDamage, ref pois, left); + left = ApplyCraftAttributeElementDamage(attrInfo.WeaponChaosDamage, ref chaos, left); + left = ApplyCraftAttributeElementDamage(attrInfo.WeaponDirectDamage, ref direct, left); + + phys = left; + } + } + } + + private int ApplyCraftAttributeElementDamage(int attrDamage, ref int element, int totalRemaining) + { + if (totalRemaining <= 0) + return 0; + + if (attrDamage <= 0) + return totalRemaining; + + var appliedDamage = attrDamage; + + if (appliedDamage + element > 100) + appliedDamage = 100 - element; + + if (appliedDamage > totalRemaining) + appliedDamage = totalRemaining; + + element += appliedDamage; + + return totalRemaining - appliedDamage; + } + + public virtual void OnMiss(Mobile attacker, Mobile defender) + { + PlaySwingAnimation(attacker); + attacker.PlaySound(GetMissAttackSound(attacker, defender)); + defender.PlaySound(GetMissDefendSound(attacker, defender)); + + var ability = WeaponAbility.GetCurrentAbility(attacker); + + ability?.OnMiss(attacker, defender); + + var move = SpecialMove.GetCurrentMove(attacker); + + move?.OnMiss(attacker, defender); + + if (defender is IHonorTarget target) target.ReceivedHonorContext?.OnTargetMissed(attacker); + } + + public virtual void GetBaseDamageRange(Mobile attacker, out int min, out int max) + { + if (attacker is BaseCreature c) + { + if (c.DamageMin >= 0) + { + min = c.DamageMin; + max = c.DamageMax; + return; + } + + if (this is Fists && !c.Body.IsHuman) + { + min = c.Str / 28; + max = c.Str / 28; + return; + } + } + + min = MinDamage; + max = MaxDamage; + } + + public virtual double GetBaseDamage(Mobile attacker) + { + GetBaseDamageRange(attacker, out var min, out var max); + + var damage = Utility.RandomMinMax(min, max); + + if (Core.AOS) return damage; + + /* Apply damage level offset + * : Regular : 0 + * : Ruin : 1 + * : Might : 3 + * : Force : 5 + * : Power : 7 + * : Vanq : 9 + */ + if (m_DamageLevel != WeaponDamageLevel.Regular) + damage += 2 * (int)m_DamageLevel - 1; + + return damage; + } + + public virtual double GetBonus(double value, double scalar, double threshold, double offset) + { + var bonus = value * scalar; + + if (value >= threshold) + bonus += offset; + + return bonus / 100; + } + + public virtual int GetHitChanceBonus() + { + if (!Core.AOS) + return 0; + + var bonus = 0; + + switch (m_AccuracyLevel) + { + case WeaponAccuracyLevel.Accurate: + bonus += 02; + break; + case WeaponAccuracyLevel.Surpassingly: + bonus += 04; + break; + case WeaponAccuracyLevel.Eminently: + bonus += 06; + break; + case WeaponAccuracyLevel.Exceedingly: + bonus += 08; + break; + case WeaponAccuracyLevel.Supremely: + bonus += 10; + break; + } + + return bonus; + } + + public virtual int GetDamageBonus() + { + var bonus = VirtualDamageBonus; + + switch (m_Quality) + { + case WeaponQuality.Low: + bonus -= 20; + break; + case WeaponQuality.Exceptional: + bonus += 20; + break; + } + + switch (m_DamageLevel) + { + case WeaponDamageLevel.Ruin: + bonus += 15; + break; + case WeaponDamageLevel.Might: + bonus += 20; + break; + case WeaponDamageLevel.Force: + bonus += 25; + break; + case WeaponDamageLevel.Power: + bonus += 30; + break; + case WeaponDamageLevel.Vanq: + bonus += 35; + break; + } + + return bonus; + } + + public virtual double ScaleDamageAOS(Mobile attacker, double damage, bool checkSkills) + { + if (checkSkills) + { + attacker.CheckSkill( + SkillName.Tactics, + 0.0, + attacker.Skills.Tactics.Cap + ); // Passively check tactics for gain + attacker.CheckSkill( + SkillName.Anatomy, + 0.0, + attacker.Skills.Anatomy.Cap + ); // Passively check Anatomy for gain + + if (Type == WeaponType.Axe) + attacker.CheckSkill(SkillName.Lumberjacking, 0.0, 100.0); // Passively check Lumberjacking for gain + } + + /* + * These are the bonuses given by the physical characteristics of the mobile. + * No caps apply. + */ + var strengthBonus = GetBonus(attacker.Str, 0.300, 100.0, 5.00); + var anatomyBonus = GetBonus(attacker.Skills.Anatomy.Value, 0.500, 100.0, 5.00); + var tacticsBonus = GetBonus(attacker.Skills.Tactics.Value, 0.625, 100.0, 6.25); + var lumberBonus = GetBonus(attacker.Skills.Lumberjacking.Value, 0.200, 100.0, 10.00); + + if (Type != WeaponType.Axe) + lumberBonus = 0.0; + + /* + * The following are damage modifiers whose effect shows on the status bar. + * Capped at 100% total. + */ + var damageBonus = AosAttributes.GetValue(attacker, AosAttribute.WeaponDamage); + + // Horrific Beast transformation gives a +25% bonus to damage. + if (TransformationSpellHelper.UnderTransformation(attacker, typeof(HorrificBeastSpell))) + damageBonus += 25; + + // Divine Fury gives a +10% bonus to damage. + if (DivineFurySpell.UnderEffect(attacker)) + damageBonus += 10; + + var defenseMasteryMalus = 0; + + // Defense Mastery gives a -50%/-80% malus to damage. + if (DefenseMastery.GetMalus(attacker, ref defenseMasteryMalus)) + damageBonus -= defenseMasteryMalus; + + var discordanceEffect = 0; + + // Discordance gives a -2%/-48% malus to damage. + if (Discordance.GetEffect(attacker, ref discordanceEffect)) + damageBonus -= discordanceEffect * 2; + + if (damageBonus > 100) + damageBonus = 100; + + var totalBonus = strengthBonus + anatomyBonus + tacticsBonus + lumberBonus + + (GetDamageBonus() + damageBonus) / 100.0; + + return damage + (int)(damage * totalBonus); + } + + public virtual int ComputeDamageAOS(Mobile attacker, Mobile defender) => + (int)ScaleDamageAOS(attacker, GetBaseDamage(attacker), true); + + public virtual double ScaleDamageOld(Mobile attacker, double damage, bool checkSkills) + { + if (checkSkills) + { + attacker.CheckSkill( + SkillName.Tactics, + 0.0, + attacker.Skills.Tactics.Cap + ); // Passively check tactics for gain + attacker.CheckSkill( + SkillName.Anatomy, + 0.0, + attacker.Skills.Anatomy.Cap + ); // Passively check Anatomy for gain + + if (Type == WeaponType.Axe) + attacker.CheckSkill(SkillName.Lumberjacking, 0.0, 100.0); // Passively check Lumberjacking for gain + } + + /* Compute tactics modifier + * : 0.0 = 50% loss + * : 50.0 = unchanged + * : 100.0 = 50% bonus + */ + damage += damage * ((attacker.Skills.Tactics.Value - 50.0) / 100.0); + + /* Compute strength modifier + * : 1% bonus for every 5 strength + */ + var modifiers = attacker.Str / 5.0 / 100.0; + + /* Compute anatomy modifier + * : 1% bonus for every 5 points of anatomy + * : +10% bonus at Grandmaster or higher + */ + var anatomyValue = attacker.Skills.Anatomy.Value; + modifiers += anatomyValue / 5.0 / 100.0; + + if (anatomyValue >= 100.0) + modifiers += 0.1; + + /* Compute lumberjacking bonus + * : 1% bonus for every 5 points of lumberjacking + * : +10% bonus at Grandmaster or higher + */ + if (Type == WeaponType.Axe) + { + var lumberValue = attacker.Skills.Lumberjacking.Value; + + modifiers += lumberValue / 5.0 / 100.0; + + if (lumberValue >= 100.0) + modifiers += 0.1; + } + + // New quality bonus: + if (m_Quality != WeaponQuality.Regular) + modifiers += ((int)m_Quality - 1) * 0.2; + + // Virtual damage bonus: + if (VirtualDamageBonus != 0) + modifiers += VirtualDamageBonus / 100.0; + + // Apply bonuses + damage += damage * modifiers; + + return ScaleDamageByDurability((int)damage); + } + + public virtual int ScaleDamageByDurability(int damage) + { + var scale = 100; + + if (m_MaxHits > 0 && m_Hits < m_MaxHits) + scale = 50 + 50 * m_Hits / m_MaxHits; + + return AOS.Scale(damage, scale); + } + + public virtual int ComputeDamage(Mobile attacker, Mobile defender) + { + if (Core.AOS) + return ComputeDamageAOS(attacker, defender); + + var damage = (int)ScaleDamageOld(attacker, GetBaseDamage(attacker), true); + + // pre-AOS, halve damage if the defender is a player or the attacker is not a player + if (defender is PlayerMobile || !(attacker is PlayerMobile)) + damage = (int)(damage / 2.0); + + return damage; + } + + public virtual void PlayHurtAnimation(Mobile from) + { + int action; + int frames; + + switch (from.Body.Type) + { + case BodyType.Sea: + case BodyType.Animal: + { + action = 7; + frames = 5; + break; + } + case BodyType.Monster: + { + action = 10; + frames = 4; + break; + } + case BodyType.Human: + { + action = 20; + frames = 5; + break; + } + default: return; + } + + if (from.Mounted) + return; + + from.Animate(action, frames, 1, true, false, 0); + } + + public virtual void PlaySwingAnimation(Mobile from) + { + int action; + + switch (from.Body.Type) + { + case BodyType.Sea: + case BodyType.Animal: + { + action = Utility.Random(5, 2); + break; + } + case BodyType.Monster: + { + switch (Animation) + { + default: + action = Utility.Random(4, 3); + break; + case WeaponAnimation.ShootBow: return; // 7 + case WeaponAnimation.ShootXBow: return; // 8 + } + + break; + } + case BodyType.Human: + { + if (!from.Mounted) + action = (int)Animation; + else + action = Animation switch + { + WeaponAnimation.Wrestle => 26, + WeaponAnimation.Bash1H => 26, + WeaponAnimation.Pierce1H => 26, + WeaponAnimation.Slash1H => 26, + WeaponAnimation.Bash2H => 29, + WeaponAnimation.Pierce2H => 29, + WeaponAnimation.Slash2H => 29, + WeaponAnimation.ShootBow => 27, + WeaponAnimation.ShootXBow => 28, + _ => 26 + }; + + break; + } + default: return; + } + + from.Animate(action, 7, 1, true, false, 0); + } + + private string GetNameString() => Name ?? $"#{LabelNumber}"; + + public int GetElementalDamageHue() + { + GetDamageTypes(null, out _, out var fire, out var cold, out var pois, out var nrgy, out _, out _); + // Order is Cold, Energy, Fire, Poison, Physical left + + var currentMax = 50; + var hue = 0; + + if (pois >= currentMax) + { + hue = 1267 + (pois - 50) / 10; + currentMax = pois; + } + + if (fire >= currentMax) + { + hue = 1255 + (fire - 50) / 10; + currentMax = fire; + } + + if (nrgy >= currentMax) + { + hue = 1273 + (nrgy - 50) / 10; + currentMax = nrgy; + } + + if (cold >= currentMax) hue = 1261 + (cold - 50) / 10; + + return hue; + } + + public override void AddNameProperty(ObjectPropertyList list) + { + var oreType = m_Resource switch + { + CraftResource.DullCopper => 1053108, + CraftResource.ShadowIron => 1053107, + CraftResource.Copper => 1053106, + CraftResource.Bronze => 1053105, + CraftResource.Gold => 1053104, + CraftResource.Agapite => 1053103, + CraftResource.Verite => 1053102, + CraftResource.Valorite => 1053101, + CraftResource.SpinedLeather => 1061118, + CraftResource.HornedLeather => 1061117, + CraftResource.BarbedLeather => 1061116, + CraftResource.RedScales => 1060814, + CraftResource.YellowScales => 1060818, + CraftResource.BlackScales => 1060820, + CraftResource.GreenScales => 1060819, + CraftResource.WhiteScales => 1060821, + CraftResource.BlueScales => 1060815, + _ => 0 + }; + + if (oreType != 0) + list.Add(1053099, "#{0}\t{1}", oreType, GetNameString()); // ~1_oretype~ ~2_armortype~ + else if (Name == null) + list.Add(LabelNumber); + else + list.Add(Name); + + /* + * Want to move this to the engraving tool, let the non-harmful + * formatting show, and remove CLILOCs embedded: more like OSI + * did with the books that had markup, etc. + * + * This will have a negative effect on a few event things imgame + * as is. + * + * If we cant find a more OSI-ish way to clean it up, we can + * easily put this back, and use it in the deserialize + * method and engraving tool, to make it perm cleaned up. */ - defender = m; - break; - } + if (!string.IsNullOrEmpty(m_EngravedText)) + list.Add(1062613, m_EngravedText); - eable.Free(); - } - - PlaySwingAnimation(attacker); - PlayHurtAnimation(defender); - - attacker.PlaySound(GetHitAttackSound(attacker, defender)); - defender.PlaySound(GetHitDefendSound(attacker, defender)); - - int damage = ComputeDamage(attacker, defender); - - /* - * The following damage bonuses multiply damage by a factor. - * Capped at x3 (300%). - */ - int percentageBonus = 0; - - WeaponAbility a = WeaponAbility.GetCurrentAbility(attacker); - SpecialMove move = SpecialMove.GetCurrentMove(attacker); - - if (a != null) percentageBonus += (int)(a.DamageScalar * 100) - 100; - - if (move != null) percentageBonus += (int)(move.GetDamageScalar(attacker, defender) * 100) - 100; - - percentageBonus += (int)(damageBonus * 100) - 100; - - CheckSlayerResult cs = CheckSlayers(attacker, defender); - - if (cs != CheckSlayerResult.None) - { - if (cs == CheckSlayerResult.Slayer) - defender.FixedEffect(0x37B9, 10, 5); - - percentageBonus += 100; - } - - if (!attacker.Player) - { - if (defender is PlayerMobile pm) - if (pm.EnemyOfOneType != null && pm.EnemyOfOneType != attacker.GetType()) - percentageBonus += 100; - } - else if (!defender.Player) - { - if (attacker is PlayerMobile pm) - { - if (pm.WaitingForEnemy) - { - pm.EnemyOfOneType = defender.GetType(); - pm.WaitingForEnemy = false; - } - - if (pm.EnemyOfOneType == defender.GetType()) - { - defender.FixedEffect(0x37B9, 10, 5, 1160, 0); - - percentageBonus += 50; - } - } - } - - int packInstinctBonus = GetPackInstinctBonus(attacker, defender); - - if (packInstinctBonus != 0) percentageBonus += packInstinctBonus; - - if (InDoubleStrike) percentageBonus -= 10; - - TransformContext context = TransformationSpellHelper.GetContext(defender); - - if ((m_Slayer == SlayerName.Silver || m_Slayer2 == SlayerName.Silver) && context?.Spell is NecromancerSpell && - context.Type != typeof(HorrificBeastSpell)) percentageBonus += 25; - - if (attacker is PlayerMobile pmAttacker && !(Core.ML && defender is PlayerMobile)) - { - if (pmAttacker.HonorActive && pmAttacker.InRange(defender, 1)) percentageBonus += 25; - - if (pmAttacker.SentHonorContext != null && pmAttacker.SentHonorContext.Target == defender) - percentageBonus += pmAttacker.SentHonorContext.PerfectionDamageBonus; - } - - if (attacker.Talisman is BaseTalisman talisman && talisman.Killer != null) - percentageBonus += talisman.Killer.DamageBonus(defender); - - percentageBonus = Math.Min(percentageBonus, 300); - - damage = AOS.Scale(damage, 100 + percentageBonus); - - BaseCreature bcAtt = attacker as BaseCreature; - BaseCreature bcDef = defender as BaseCreature; - - bcAtt?.AlterMeleeDamageTo(defender, ref damage); - bcDef?.AlterMeleeDamageFrom(attacker, ref damage); - - damage = AbsorbDamage(attacker, defender, damage); - - if (!Core.AOS && damage < 1) - damage = 1; - else if (Core.AOS && damage == 0) // parried - if (a?.Validate(attacker) == true) /*&& a.CheckMana( attacker, true )*/ - // Parried special moves have no mana cost - { - a = null; - WeaponAbility.ClearCurrentAbility(attacker); - - attacker.SendLocalizedMessage(1061140); // Your attack was parried! + /* list.Add( 1062613, Utility.FixHtml( m_EngravedText ) ); */ } - AddBlood(attacker, defender, damage); - - GetDamageTypes(attacker, out int phys, out int fire, out int cold, out int pois, out int nrgy, out int chaos, out int direct); - - if (Core.ML && this is BaseRanged) - if (attacker.FindItemOnLayer(Layer.Cloak) is BaseQuiver quiver) - quiver.AlterBowDamage(ref phys, ref fire, ref cold, ref pois, ref nrgy, ref chaos, ref direct); - - if (Consecrated) - { - phys = defender.PhysicalResistance; - fire = defender.FireResistance; - cold = defender.ColdResistance; - pois = defender.PoisonResistance; - nrgy = defender.EnergyResistance; - - int low = phys, type = 0; - - if (fire < low) + public override bool AllowEquippedCast(Mobile from) { - low = fire; - type = 1; + if (base.AllowEquippedCast(from)) + return true; + + return Attributes.SpellChanneling != 0; } - if (cold < low) + public virtual int GetLuckBonus() { - low = cold; - type = 2; + var resInfo = CraftResources.GetInfo(m_Resource); + + var attrInfo = resInfo?.AttributeInfo; + + if (attrInfo == null) + return 0; + + return attrInfo.WeaponLuck; } - if (pois < low) + public override void GetProperties(ObjectPropertyList list) { - low = pois; - type = 3; - } + base.GetProperties(list); - if (nrgy < low) type = 4; + if (m_Crafter != null) + list.Add(1050043, m_Crafter.Name); // crafted by ~1_NAME~ - phys = fire = cold = pois = nrgy = chaos = direct = 0; + if (m_FactionState != null) + list.Add(1041350); // faction item - if (type == 0) phys = 100; - else if (type == 1) fire = 100; - else if (type == 2) cold = 100; - else if (type == 3) pois = 100; - else if (type == 4) nrgy = 100; - } + SkillBonuses?.GetProperties(list); - // TODO: Scale damage, alongside the leech effects below, to weapon speed. - if (ImmolatingWeaponSpell.IsImmolating(this) && damage > 0) - ImmolatingWeaponSpell.DoEffect(this, defender); + if (m_Quality == WeaponQuality.Exceptional) + list.Add(1060636); // exceptional - int damageGiven = damage; + if (RequiredRace == Race.Elf) + list.Add(1075086); // Elves Only - if (a?.OnBeforeDamage(attacker, defender) == false) - { - WeaponAbility.ClearCurrentAbility(attacker); - a = null; - } + if (ArtifactRarity > 0) + list.Add(1061078, ArtifactRarity.ToString()); // artifact rarity ~1_val~ - if (move?.OnBeforeDamage(attacker, defender) == false) - { - SpecialMove.ClearCurrentMove(attacker); - move = null; - } + if (this is IUsesRemaining usesRemaining && usesRemaining.ShowUsesRemaining) + list.Add(1060584, usesRemaining.UsesRemaining.ToString()); // uses remaining: ~1_val~ - bool ignoreArmor = a is ArmorIgnore || move?.IgnoreArmor(attacker) == true; + if (m_Poison != null && m_PoisonCharges > 0) + list.Add(1062412 + m_Poison.Level, m_PoisonCharges.ToString()); - damageGiven = AOS.Damage(defender, attacker, damage, ignoreArmor, phys, fire, cold, pois, nrgy, chaos, direct, - false, this is BaseRanged); - - double propertyBonus = move?.GetPropertyBonus(attacker) ?? 1.0; - - if (Core.AOS) - { - int lifeLeech = 0; - int stamLeech = 0; - int manaLeech = 0; - int wraithLeech; - - if ((int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLeechHits) * propertyBonus) > - Utility.Random(100)) - lifeLeech += 30; // HitLeechHits% chance to leech 30% of damage as hit points - - if ((int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLeechStam) * propertyBonus) > - Utility.Random(100)) - stamLeech += 100; // HitLeechStam% chance to leech 100% of damage as stamina - - if ((int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLeechMana) * propertyBonus) > - Utility.Random(100)) - manaLeech += 40; // HitLeechMana% chance to leech 40% of damage as mana - - if (Cursed) - lifeLeech += 50; // Additional 50% life leech for cursed weapons (necro spell) - - context = TransformationSpellHelper.GetContext(attacker); - - if (context?.Type == typeof(VampiricEmbraceSpell)) - lifeLeech += 20; // Vampiric embrace gives an additional 20% life leech - - if (context?.Type == typeof(WraithFormSpell)) - { - wraithLeech = - 5 + (int)(15 * attacker.Skills.SpiritSpeak.Value / - 100); // Wraith form gives an additional 5-20% mana leech - - // Mana leeched by the Wraith Form spell is actually stolen, not just leeched. - defender.Mana -= AOS.Scale(damageGiven, wraithLeech); - - manaLeech += wraithLeech; - } - - if (lifeLeech != 0) - attacker.Hits += AOS.Scale(damageGiven, lifeLeech); - - if (stamLeech != 0) - attacker.Stam += AOS.Scale(damageGiven, stamLeech); - - if (manaLeech != 0) - attacker.Mana += AOS.Scale(damageGiven, manaLeech); - - if (lifeLeech != 0 || stamLeech != 0 || manaLeech != 0) - attacker.PlaySound(0x44D); - } - - if (m_MaxHits > 0 && ((MaxRange <= 1 && (defender is Slime || defender is AcidElemental)) || - Utility.RandomDouble() < .04)) // Stratics says 50% chance, seems more like 4%.. - { - if (MaxRange <= 1 && (defender is Slime || defender is AcidElemental)) - attacker.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500263); // *Acid blood scars your weapon!* - - if (Core.AOS && WeaponAttributes.SelfRepair > Utility.Random(10)) - { - HitPoints += 2; - } - else - { - if (m_Hits > 0) - { - --HitPoints; - } - else if (m_MaxHits > 1) - { - --MaxHitPoints; - - if (Parent is Mobile mobile) - mobile.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1061121); // Your equipment is severely damaged. - } - else - { - Delete(); - } - } - } - - if (attacker is VampireBatFamiliar bc) - { - Mobile caster = bc.ControlMaster ?? bc.SummonMaster; - - if (caster != null && caster.Map == bc.Map && caster.InRange(bc, 2)) - caster.Hits += damage; - else - bc.Hits += damage; - } - - if (Core.AOS) - { - int physChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitPhysicalArea) * - propertyBonus); - int fireChance = - (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitFireArea) * propertyBonus); - int coldChance = - (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitColdArea) * propertyBonus); - int poisChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitPoisonArea) * - propertyBonus); - int nrgyChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitEnergyArea) * - propertyBonus); - - if (physChance != 0 && physChance > Utility.Random(100)) - DoAreaAttack(attacker, defender, 0x10E, 50, 100, 0, 0, 0, 0); - - if (fireChance != 0 && fireChance > Utility.Random(100)) - DoAreaAttack(attacker, defender, 0x11D, 1160, 0, 100, 0, 0, 0); - - if (coldChance != 0 && coldChance > Utility.Random(100)) - DoAreaAttack(attacker, defender, 0x0FC, 2100, 0, 0, 100, 0, 0); - - if (poisChance != 0 && poisChance > Utility.Random(100)) - DoAreaAttack(attacker, defender, 0x205, 1166, 0, 0, 0, 100, 0); - - if (nrgyChance != 0 && nrgyChance > Utility.Random(100)) - DoAreaAttack(attacker, defender, 0x1F1, 120, 0, 0, 0, 0, 100); - - int maChance = - (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitMagicArrow) * propertyBonus); - int harmChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitHarm) * propertyBonus); - int fireballChance = - (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitFireball) * propertyBonus); - int lightningChance = - (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLightning) * propertyBonus); - int dispelChance = - (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitDispel) * propertyBonus); - - if (maChance != 0 && maChance > Utility.Random(100)) - DoMagicArrow(attacker, defender); - - if (harmChance != 0 && harmChance > Utility.Random(100)) - DoHarm(attacker, defender); - - if (fireballChance != 0 && fireballChance > Utility.Random(100)) - DoFireball(attacker, defender); - - if (lightningChance != 0 && lightningChance > Utility.Random(100)) - DoLightning(attacker, defender); - - if (dispelChance != 0 && dispelChance > Utility.Random(100)) - DoDispel(attacker, defender); - - int laChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLowerAttack) * - propertyBonus); - int ldChance = (int)(AosWeaponAttributes.GetValue(attacker, AosWeaponAttribute.HitLowerDefend) * - propertyBonus); - - if (laChance != 0 && laChance > Utility.Random(100)) - DoLowerAttack(attacker, defender); - - if (ldChance != 0 && ldChance > Utility.Random(100)) - DoLowerDefense(attacker, defender); - } - - bcAtt?.OnGaveMeleeAttack(defender); - bcDef?.OnGotMeleeAttack(attacker); - - a?.OnHit(attacker, defender, damage); - move?.OnHit(attacker, defender, damage); - - if (defender is IHonorTarget it) - it.ReceivedHonorContext?.OnTargetHit(attacker); - - if (!(this is BaseRanged)) - { - if (AnimalForm.UnderTransformation(attacker, typeof(GiantSerpent))) - defender.ApplyPoison(attacker, Poison.Lesser); - - if (AnimalForm.UnderTransformation(defender, typeof(BullFrog))) - attacker.ApplyPoison(defender, Poison.Regular); - } - } - - public virtual double GetAosDamage(Mobile attacker, int bonus, uint dice, uint sides) - { - int damage = Utility.Dice(dice, sides, bonus) * 100; - - // Inscription bonus - int inscribeSkill = attacker.Skills.Inscribe.Fixed; - - var damageBonus = inscribeSkill / 200; - - if (inscribeSkill >= 1000) - damageBonus += 5; - - if (attacker.Player) - { - // Int bonus - damageBonus += attacker.Int / 10; - - // SDI bonus - damageBonus += AosAttributes.GetValue(attacker, AosAttribute.SpellDamage); - - TransformContext context = TransformationSpellHelper.GetContext(attacker); - - if (context?.Spell is ReaperFormSpell spell) - damageBonus += spell.SpellDamageBonus; - } - - damage = AOS.Scale(damage, 100 + damageBonus); - - return damage / 100.0; - } - - public virtual CheckSlayerResult CheckSlayers(Mobile attacker, Mobile defender) - { - BaseWeapon atkWeapon = attacker.Weapon as BaseWeapon; - SlayerEntry atkSlayer = SlayerGroup.GetEntryByName(atkWeapon?.Slayer ?? SlayerName.None); - SlayerEntry atkSlayer2 = SlayerGroup.GetEntryByName(atkWeapon?.Slayer2 ?? SlayerName.None); - - if (atkWeapon is ButchersWarCleaver && TalismanSlayer.Slays(TalismanSlayerName.Bovine, defender)) - return CheckSlayerResult.Slayer; - - if (atkSlayer?.Slays(defender) == true || atkSlayer2?.Slays(defender) == true) - return CheckSlayerResult.Slayer; - - if (attacker.Talisman is BaseTalisman talisman && TalismanSlayer.Slays(talisman.Slayer, defender)) - return CheckSlayerResult.Slayer; - - if (!Core.SE) - { - ISlayer defISlayer = Spellbook.FindEquippedSpellbook(defender) ?? defender.Weapon as ISlayer; - - if (defISlayer != null) - { - SlayerEntry defSlayer = SlayerGroup.GetEntryByName(defISlayer.Slayer); - SlayerEntry defSlayer2 = SlayerGroup.GetEntryByName(defISlayer.Slayer2); - - if (defSlayer?.Group.OppositionSuperSlays(attacker) == true || - defSlayer2?.Group.OppositionSuperSlays(attacker) == true) - return CheckSlayerResult.Opposition; - } - } - - return CheckSlayerResult.None; - } - - public virtual void AddBlood(Mobile attacker, Mobile defender, int damage) - { - if (damage <= 0) - return; - - new Blood().MoveToWorld(defender.Location, defender.Map); - - int extraBlood = Core.SE ? Utility.RandomMinMax(3, 4) : Utility.RandomMinMax(0, 1); - - for (int i = 0; i < extraBlood; i++) - new Blood().MoveToWorld(new Point3D( - defender.X + Utility.RandomMinMax(-1, 1), - defender.Y + Utility.RandomMinMax(-1, 1), - defender.Z), defender.Map); - } - - public virtual void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - if (wielder is BaseCreature bc) - { - phys = bc.PhysicalDamage; - fire = bc.FireDamage; - cold = bc.ColdDamage; - pois = bc.PoisonDamage; - nrgy = bc.EnergyDamage; - chaos = bc.ChaosDamage; - direct = bc.DirectDamage; - } - else - { - fire = AosElementDamages.Fire; - cold = AosElementDamages.Cold; - pois = AosElementDamages.Poison; - nrgy = AosElementDamages.Energy; - chaos = AosElementDamages.Chaos; - direct = AosElementDamages.Direct; - - phys = 100 - fire - cold - pois - nrgy - chaos - direct; - - CraftAttributeInfo attrInfo = CraftResources.GetInfo(m_Resource)?.AttributeInfo; - - if (attrInfo != null) - { - int left = phys; - - left = ApplyCraftAttributeElementDamage(attrInfo.WeaponColdDamage, ref cold, left); - left = ApplyCraftAttributeElementDamage(attrInfo.WeaponEnergyDamage, ref nrgy, left); - left = ApplyCraftAttributeElementDamage(attrInfo.WeaponFireDamage, ref fire, left); - left = ApplyCraftAttributeElementDamage(attrInfo.WeaponPoisonDamage, ref pois, left); - left = ApplyCraftAttributeElementDamage(attrInfo.WeaponChaosDamage, ref chaos, left); - left = ApplyCraftAttributeElementDamage(attrInfo.WeaponDirectDamage, ref direct, left); - - phys = left; - } - } - } - - private int ApplyCraftAttributeElementDamage(int attrDamage, ref int element, int totalRemaining) - { - if (totalRemaining <= 0) - return 0; - - if (attrDamage <= 0) - return totalRemaining; - - int appliedDamage = attrDamage; - - if (appliedDamage + element > 100) - appliedDamage = 100 - element; - - if (appliedDamage > totalRemaining) - appliedDamage = totalRemaining; - - element += appliedDamage; - - return totalRemaining - appliedDamage; - } - - public virtual void OnMiss(Mobile attacker, Mobile defender) - { - PlaySwingAnimation(attacker); - attacker.PlaySound(GetMissAttackSound(attacker, defender)); - defender.PlaySound(GetMissDefendSound(attacker, defender)); - - WeaponAbility ability = WeaponAbility.GetCurrentAbility(attacker); - - ability?.OnMiss(attacker, defender); - - SpecialMove move = SpecialMove.GetCurrentMove(attacker); - - move?.OnMiss(attacker, defender); - - if (defender is IHonorTarget target) target.ReceivedHonorContext?.OnTargetMissed(attacker); - } - - public virtual void GetBaseDamageRange(Mobile attacker, out int min, out int max) - { - if (attacker is BaseCreature c) - { - if (c.DamageMin >= 0) - { - min = c.DamageMin; - max = c.DamageMax; - return; - } - - if (this is Fists && !c.Body.IsHuman) - { - min = c.Str / 28; - max = c.Str / 28; - return; - } - } - - min = MinDamage; - max = MaxDamage; - } - - public virtual double GetBaseDamage(Mobile attacker) - { - GetBaseDamageRange(attacker, out int min, out int max); - - int damage = Utility.RandomMinMax(min, max); - - if (Core.AOS) return damage; - - /* Apply damage level offset - * : Regular : 0 - * : Ruin : 1 - * : Might : 3 - * : Force : 5 - * : Power : 7 - * : Vanq : 9 - */ - if (m_DamageLevel != WeaponDamageLevel.Regular) - damage += 2 * (int)m_DamageLevel - 1; - - return damage; - } - - public virtual double GetBonus(double value, double scalar, double threshold, double offset) - { - double bonus = value * scalar; - - if (value >= threshold) - bonus += offset; - - return bonus / 100; - } - - public virtual int GetHitChanceBonus() - { - if (!Core.AOS) - return 0; - - int bonus = 0; - - switch (m_AccuracyLevel) - { - case WeaponAccuracyLevel.Accurate: - bonus += 02; - break; - case WeaponAccuracyLevel.Surpassingly: - bonus += 04; - break; - case WeaponAccuracyLevel.Eminently: - bonus += 06; - break; - case WeaponAccuracyLevel.Exceedingly: - bonus += 08; - break; - case WeaponAccuracyLevel.Supremely: - bonus += 10; - break; - } - - return bonus; - } - - public virtual int GetDamageBonus() - { - int bonus = VirtualDamageBonus; - - switch (m_Quality) - { - case WeaponQuality.Low: - bonus -= 20; - break; - case WeaponQuality.Exceptional: - bonus += 20; - break; - } - - switch (m_DamageLevel) - { - case WeaponDamageLevel.Ruin: - bonus += 15; - break; - case WeaponDamageLevel.Might: - bonus += 20; - break; - case WeaponDamageLevel.Force: - bonus += 25; - break; - case WeaponDamageLevel.Power: - bonus += 30; - break; - case WeaponDamageLevel.Vanq: - bonus += 35; - break; - } - - return bonus; - } - - public virtual double ScaleDamageAOS(Mobile attacker, double damage, bool checkSkills) - { - if (checkSkills) - { - attacker.CheckSkill(SkillName.Tactics, 0.0, - attacker.Skills.Tactics.Cap); // Passively check tactics for gain - attacker.CheckSkill(SkillName.Anatomy, 0.0, - attacker.Skills.Anatomy.Cap); // Passively check Anatomy for gain - - if (Type == WeaponType.Axe) - attacker.CheckSkill(SkillName.Lumberjacking, 0.0, 100.0); // Passively check Lumberjacking for gain - } - - /* - * These are the bonuses given by the physical characteristics of the mobile. - * No caps apply. - */ - double strengthBonus = GetBonus(attacker.Str, 0.300, 100.0, 5.00); - double anatomyBonus = GetBonus(attacker.Skills.Anatomy.Value, 0.500, 100.0, 5.00); - double tacticsBonus = GetBonus(attacker.Skills.Tactics.Value, 0.625, 100.0, 6.25); - double lumberBonus = GetBonus(attacker.Skills.Lumberjacking.Value, 0.200, 100.0, 10.00); - - if (Type != WeaponType.Axe) - lumberBonus = 0.0; - - /* - * The following are damage modifiers whose effect shows on the status bar. - * Capped at 100% total. - */ - int damageBonus = AosAttributes.GetValue(attacker, AosAttribute.WeaponDamage); - - // Horrific Beast transformation gives a +25% bonus to damage. - if (TransformationSpellHelper.UnderTransformation(attacker, typeof(HorrificBeastSpell))) - damageBonus += 25; - - // Divine Fury gives a +10% bonus to damage. - if (DivineFurySpell.UnderEffect(attacker)) - damageBonus += 10; - - int defenseMasteryMalus = 0; - - // Defense Mastery gives a -50%/-80% malus to damage. - if (DefenseMastery.GetMalus(attacker, ref defenseMasteryMalus)) - damageBonus -= defenseMasteryMalus; - - int discordanceEffect = 0; - - // Discordance gives a -2%/-48% malus to damage. - if (Discordance.GetEffect(attacker, ref discordanceEffect)) - damageBonus -= discordanceEffect * 2; - - if (damageBonus > 100) - damageBonus = 100; - - double totalBonus = strengthBonus + anatomyBonus + tacticsBonus + lumberBonus + - (GetDamageBonus() + damageBonus) / 100.0; - - return damage + (int)(damage * totalBonus); - } - - public virtual int ComputeDamageAOS(Mobile attacker, Mobile defender) => (int)ScaleDamageAOS(attacker, GetBaseDamage(attacker), true); - - public virtual double ScaleDamageOld(Mobile attacker, double damage, bool checkSkills) - { - if (checkSkills) - { - attacker.CheckSkill(SkillName.Tactics, 0.0, - attacker.Skills.Tactics.Cap); // Passively check tactics for gain - attacker.CheckSkill(SkillName.Anatomy, 0.0, - attacker.Skills.Anatomy.Cap); // Passively check Anatomy for gain - - if (Type == WeaponType.Axe) - attacker.CheckSkill(SkillName.Lumberjacking, 0.0, 100.0); // Passively check Lumberjacking for gain - } - - /* Compute tactics modifier - * : 0.0 = 50% loss - * : 50.0 = unchanged - * : 100.0 = 50% bonus - */ - damage += damage * ((attacker.Skills.Tactics.Value - 50.0) / 100.0); - - /* Compute strength modifier - * : 1% bonus for every 5 strength - */ - double modifiers = attacker.Str / 5.0 / 100.0; - - /* Compute anatomy modifier - * : 1% bonus for every 5 points of anatomy - * : +10% bonus at Grandmaster or higher - */ - double anatomyValue = attacker.Skills.Anatomy.Value; - modifiers += anatomyValue / 5.0 / 100.0; - - if (anatomyValue >= 100.0) - modifiers += 0.1; - - /* Compute lumberjacking bonus - * : 1% bonus for every 5 points of lumberjacking - * : +10% bonus at Grandmaster or higher - */ - if (Type == WeaponType.Axe) - { - double lumberValue = attacker.Skills.Lumberjacking.Value; - - modifiers += lumberValue / 5.0 / 100.0; - - if (lumberValue >= 100.0) - modifiers += 0.1; - } - - // New quality bonus: - if (m_Quality != WeaponQuality.Regular) - modifiers += ((int)m_Quality - 1) * 0.2; - - // Virtual damage bonus: - if (VirtualDamageBonus != 0) - modifiers += VirtualDamageBonus / 100.0; - - // Apply bonuses - damage += damage * modifiers; - - return ScaleDamageByDurability((int)damage); - } - - public virtual int ScaleDamageByDurability(int damage) - { - int scale = 100; - - if (m_MaxHits > 0 && m_Hits < m_MaxHits) - scale = 50 + 50 * m_Hits / m_MaxHits; - - return AOS.Scale(damage, scale); - } - - public virtual int ComputeDamage(Mobile attacker, Mobile defender) - { - if (Core.AOS) - return ComputeDamageAOS(attacker, defender); - - int damage = (int)ScaleDamageOld(attacker, GetBaseDamage(attacker), true); - - // pre-AOS, halve damage if the defender is a player or the attacker is not a player - if (defender is PlayerMobile || !(attacker is PlayerMobile)) - damage = (int)(damage / 2.0); - - return damage; - } - - public virtual void PlayHurtAnimation(Mobile from) - { - int action; - int frames; - - switch (from.Body.Type) - { - case BodyType.Sea: - case BodyType.Animal: - { - action = 7; - frames = 5; - break; - } - case BodyType.Monster: - { - action = 10; - frames = 4; - break; - } - case BodyType.Human: - { - action = 20; - frames = 5; - break; - } - default: return; - } - - if (from.Mounted) - return; - - from.Animate(action, frames, 1, true, false, 0); - } - - public virtual void PlaySwingAnimation(Mobile from) - { - int action; - - switch (from.Body.Type) - { - case BodyType.Sea: - case BodyType.Animal: - { - action = Utility.Random(5, 2); - break; - } - case BodyType.Monster: - { - switch (Animation) + if (m_Slayer != SlayerName.None) { - default: - action = Utility.Random(4, 3); - break; - case WeaponAnimation.ShootBow: return; // 7 - case WeaponAnimation.ShootXBow: return; // 8 + var entry = SlayerGroup.GetEntryByName(m_Slayer); + if (entry != null) + list.Add(entry.Title); } - break; - } - case BodyType.Human: - { - if (!from.Mounted) - action = (int)Animation; + if (m_Slayer2 != SlayerName.None) + { + var entry = SlayerGroup.GetEntryByName(m_Slayer2); + if (entry != null) + list.Add(entry.Title); + } + + AddResistanceProperties(list); + + int prop; + + var ranged = this as BaseRanged; + + if (Core.ML && ranged?.Balanced == true) + list.Add(1072792); // Balanced + + if (WeaponAttributes.UseBestSkill != 0) + list.Add(1060400); // use best weapon skill + + if ((prop = GetDamageBonus() + Attributes.WeaponDamage) != 0) + list.Add(1060401, prop.ToString()); // damage increase ~1_val~% + + if ((prop = Attributes.DefendChance) != 0) + list.Add(1060408, prop.ToString()); // defense chance increase ~1_val~% + + if ((prop = Attributes.EnhancePotions) != 0) + list.Add(1060411, prop.ToString()); // enhance potions ~1_val~% + + if ((prop = Attributes.CastRecovery) != 0) + list.Add(1060412, prop.ToString()); // faster cast recovery ~1_val~ + + if ((prop = Attributes.CastSpeed) != 0) + list.Add(1060413, prop.ToString()); // faster casting ~1_val~ + + if ((prop = GetHitChanceBonus() + Attributes.AttackChance) != 0) + list.Add(1060415, prop.ToString()); // hit chance increase ~1_val~% + + if ((prop = WeaponAttributes.HitColdArea) != 0) + list.Add(1060416, prop.ToString()); // hit cold area ~1_val~% + + if ((prop = WeaponAttributes.HitDispel) != 0) + list.Add(1060417, prop.ToString()); // hit dispel ~1_val~% + + if ((prop = WeaponAttributes.HitEnergyArea) != 0) + list.Add(1060418, prop.ToString()); // hit energy area ~1_val~% + + if ((prop = WeaponAttributes.HitFireArea) != 0) + list.Add(1060419, prop.ToString()); // hit fire area ~1_val~% + + if ((prop = WeaponAttributes.HitFireball) != 0) + list.Add(1060420, prop.ToString()); // hit fireball ~1_val~% + + if ((prop = WeaponAttributes.HitHarm) != 0) + list.Add(1060421, prop.ToString()); // hit harm ~1_val~% + + if ((prop = WeaponAttributes.HitLeechHits) != 0) + list.Add(1060422, prop.ToString()); // hit life leech ~1_val~% + + if ((prop = WeaponAttributes.HitLightning) != 0) + list.Add(1060423, prop.ToString()); // hit lightning ~1_val~% + + if ((prop = WeaponAttributes.HitLowerAttack) != 0) + list.Add(1060424, prop.ToString()); // hit lower attack ~1_val~% + + if ((prop = WeaponAttributes.HitLowerDefend) != 0) + list.Add(1060425, prop.ToString()); // hit lower defense ~1_val~% + + if ((prop = WeaponAttributes.HitMagicArrow) != 0) + list.Add(1060426, prop.ToString()); // hit magic arrow ~1_val~% + + if ((prop = WeaponAttributes.HitLeechMana) != 0) + list.Add(1060427, prop.ToString()); // hit mana leech ~1_val~% + + if ((prop = WeaponAttributes.HitPhysicalArea) != 0) + list.Add(1060428, prop.ToString()); // hit physical area ~1_val~% + + if ((prop = WeaponAttributes.HitPoisonArea) != 0) + list.Add(1060429, prop.ToString()); // hit poison area ~1_val~% + + if ((prop = WeaponAttributes.HitLeechStam) != 0) + list.Add(1060430, prop.ToString()); // hit stamina leech ~1_val~% + + if (ImmolatingWeaponSpell.IsImmolating(this)) + list.Add(1111917); // Immolated + + if (Core.ML && (ranged?.Velocity ?? 0) != 0) + list.Add(1072793, prop.ToString()); // Velocity ~1_val~% + + if ((prop = Attributes.BonusDex) != 0) + list.Add(1060409, prop.ToString()); // dexterity bonus ~1_val~ + + if ((prop = Attributes.BonusHits) != 0) + list.Add(1060431, prop.ToString()); // hit point increase ~1_val~ + + if ((prop = Attributes.BonusInt) != 0) + list.Add(1060432, prop.ToString()); // intelligence bonus ~1_val~ + + if ((prop = Attributes.LowerManaCost) != 0) + list.Add(1060433, prop.ToString()); // lower mana cost ~1_val~% + + if ((prop = Attributes.LowerRegCost) != 0) + list.Add(1060434, prop.ToString()); // lower reagent cost ~1_val~% + + if ((prop = GetLowerStatReq()) != 0) + list.Add(1060435, prop.ToString()); // lower requirements ~1_val~% + + if ((prop = GetLuckBonus() + Attributes.Luck) != 0) + list.Add(1060436, prop.ToString()); // luck ~1_val~ + + if ((prop = WeaponAttributes.MageWeapon) != 0) + list.Add(1060438, (30 - prop).ToString()); // mage weapon -~1_val~ skill + + if ((prop = Attributes.BonusMana) != 0) + list.Add(1060439, prop.ToString()); // mana increase ~1_val~ + + if ((prop = Attributes.RegenMana) != 0) + list.Add(1060440, prop.ToString()); // mana regeneration ~1_val~ + + if (Attributes.NightSight != 0) + list.Add(1060441); // night sight + + if ((prop = Attributes.ReflectPhysical) != 0) + list.Add(1060442, prop.ToString()); // reflect physical damage ~1_val~% + + if ((prop = Attributes.RegenStam) != 0) + list.Add(1060443, prop.ToString()); // stamina regeneration ~1_val~ + + if ((prop = Attributes.RegenHits) != 0) + list.Add(1060444, prop.ToString()); // hit point regeneration ~1_val~ + + if ((prop = WeaponAttributes.SelfRepair) != 0) + list.Add(1060450, prop.ToString()); // self repair ~1_val~ + + if (Attributes.SpellChanneling != 0) + list.Add(1060482); // spell channeling + + if ((prop = Attributes.SpellDamage) != 0) + list.Add(1060483, prop.ToString()); // spell damage increase ~1_val~% + + if ((prop = Attributes.BonusStam) != 0) + list.Add(1060484, prop.ToString()); // stamina increase ~1_val~ + + if ((prop = Attributes.BonusStr) != 0) + list.Add(1060485, prop.ToString()); // strength bonus ~1_val~ + + if ((prop = Attributes.WeaponSpeed) != 0) + list.Add(1060486, prop.ToString()); // swing speed increase ~1_val~% + + if (Core.ML && (prop = Attributes.IncreasedKarmaLoss) != 0) + list.Add(1075210, prop.ToString()); // Increased Karma Loss ~1val~% + + GetDamageTypes( + null, + out var phys, + out var fire, + out var cold, + out var pois, + out var nrgy, + out var chaos, + out var direct + ); + + if (phys != 0) + list.Add(1060403, phys.ToString()); // physical damage ~1_val~% + + if (fire != 0) + list.Add(1060405, fire.ToString()); // fire damage ~1_val~% + + if (cold != 0) + list.Add(1060404, cold.ToString()); // cold damage ~1_val~% + + if (pois != 0) + list.Add(1060406, pois.ToString()); // poison damage ~1_val~% + + if (nrgy != 0) + list.Add(1060407, nrgy.ToString()); // energy damage ~1_val + + if (Core.ML && chaos != 0) + list.Add(1072846, chaos.ToString()); // chaos damage ~1_val~% + + if (Core.ML && direct != 0) + list.Add(1079978, direct.ToString()); // Direct Damage: ~1_PERCENT~% + + list.Add(1061168, "{0}\t{1}", MinDamage.ToString(), MaxDamage.ToString()); // weapon damage ~1_val~ - ~2_val~ + + if (Core.ML) + list.Add(1061167, $"{Speed}s"); // weapon speed ~1_val~ else - action = Animation switch - { - WeaponAnimation.Wrestle => 26, - WeaponAnimation.Bash1H => 26, - WeaponAnimation.Pierce1H => 26, - WeaponAnimation.Slash1H => 26, - WeaponAnimation.Bash2H => 29, - WeaponAnimation.Pierce2H => 29, - WeaponAnimation.Slash2H => 29, - WeaponAnimation.ShootBow => 27, - WeaponAnimation.ShootXBow => 28, - _ => 26 - }; - - break; - } - default: return; - } - - from.Animate(action, 7, 1, true, false, 0); - } - - private string GetNameString() => Name ?? $"#{LabelNumber}"; - - public int GetElementalDamageHue() - { - GetDamageTypes(null, out _, out int fire, out int cold, out int pois, out int nrgy, out _, out _); - // Order is Cold, Energy, Fire, Poison, Physical left - - int currentMax = 50; - int hue = 0; - - if (pois >= currentMax) - { - hue = 1267 + (pois - 50) / 10; - currentMax = pois; - } - - if (fire >= currentMax) - { - hue = 1255 + (fire - 50) / 10; - currentMax = fire; - } - - if (nrgy >= currentMax) - { - hue = 1273 + (nrgy - 50) / 10; - currentMax = nrgy; - } - - if (cold >= currentMax) hue = 1261 + (cold - 50) / 10; - - return hue; - } - - public override void AddNameProperty(ObjectPropertyList list) - { - var oreType = m_Resource switch - { - CraftResource.DullCopper => 1053108, - CraftResource.ShadowIron => 1053107, - CraftResource.Copper => 1053106, - CraftResource.Bronze => 1053105, - CraftResource.Gold => 1053104, - CraftResource.Agapite => 1053103, - CraftResource.Verite => 1053102, - CraftResource.Valorite => 1053101, - CraftResource.SpinedLeather => 1061118, - CraftResource.HornedLeather => 1061117, - CraftResource.BarbedLeather => 1061116, - CraftResource.RedScales => 1060814, - CraftResource.YellowScales => 1060818, - CraftResource.BlackScales => 1060820, - CraftResource.GreenScales => 1060819, - CraftResource.WhiteScales => 1060821, - CraftResource.BlueScales => 1060815, - _ => 0 - }; - - if (oreType != 0) - list.Add(1053099, "#{0}\t{1}", oreType, GetNameString()); // ~1_oretype~ ~2_armortype~ - else if (Name == null) - list.Add(LabelNumber); - else - list.Add(Name); - - /* - * Want to move this to the engraving tool, let the non-harmful - * formatting show, and remove CLILOCs embedded: more like OSI - * did with the books that had markup, etc. - * - * This will have a negative effect on a few event things imgame - * as is. - * - * If we cant find a more OSI-ish way to clean it up, we can - * easily put this back, and use it in the deserialize - * method and engraving tool, to make it perm cleaned up. - */ - - if (!string.IsNullOrEmpty(m_EngravedText)) - list.Add(1062613, m_EngravedText); - - /* list.Add( 1062613, Utility.FixHtml( m_EngravedText ) ); */ - } - - public override bool AllowEquippedCast(Mobile from) - { - if (base.AllowEquippedCast(from)) - return true; - - return Attributes.SpellChanneling != 0; - } - - public virtual int GetLuckBonus() - { - CraftResourceInfo resInfo = CraftResources.GetInfo(m_Resource); - - CraftAttributeInfo attrInfo = resInfo?.AttributeInfo; - - if (attrInfo == null) - return 0; - - return attrInfo.WeaponLuck; - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_Crafter != null) - list.Add(1050043, m_Crafter.Name); // crafted by ~1_NAME~ - - if (m_FactionState != null) - list.Add(1041350); // faction item - - SkillBonuses?.GetProperties(list); - - if (m_Quality == WeaponQuality.Exceptional) - list.Add(1060636); // exceptional - - if (RequiredRace == Race.Elf) - list.Add(1075086); // Elves Only - - if (ArtifactRarity > 0) - list.Add(1061078, ArtifactRarity.ToString()); // artifact rarity ~1_val~ - - if (this is IUsesRemaining usesRemaining && usesRemaining.ShowUsesRemaining) - list.Add(1060584, usesRemaining.UsesRemaining.ToString()); // uses remaining: ~1_val~ - - if (m_Poison != null && m_PoisonCharges > 0) - list.Add(1062412 + m_Poison.Level, m_PoisonCharges.ToString()); - - if (m_Slayer != SlayerName.None) - { - SlayerEntry entry = SlayerGroup.GetEntryByName(m_Slayer); - if (entry != null) - list.Add(entry.Title); - } - - if (m_Slayer2 != SlayerName.None) - { - SlayerEntry entry = SlayerGroup.GetEntryByName(m_Slayer2); - if (entry != null) - list.Add(entry.Title); - } - - AddResistanceProperties(list); - - int prop; - - BaseRanged ranged = this as BaseRanged; - - if (Core.ML && ranged?.Balanced == true) - list.Add(1072792); // Balanced - - if (WeaponAttributes.UseBestSkill != 0) - list.Add(1060400); // use best weapon skill - - if ((prop = GetDamageBonus() + Attributes.WeaponDamage) != 0) - list.Add(1060401, prop.ToString()); // damage increase ~1_val~% - - if ((prop = Attributes.DefendChance) != 0) - list.Add(1060408, prop.ToString()); // defense chance increase ~1_val~% - - if ((prop = Attributes.EnhancePotions) != 0) - list.Add(1060411, prop.ToString()); // enhance potions ~1_val~% - - if ((prop = Attributes.CastRecovery) != 0) - list.Add(1060412, prop.ToString()); // faster cast recovery ~1_val~ - - if ((prop = Attributes.CastSpeed) != 0) - list.Add(1060413, prop.ToString()); // faster casting ~1_val~ - - if ((prop = GetHitChanceBonus() + Attributes.AttackChance) != 0) - list.Add(1060415, prop.ToString()); // hit chance increase ~1_val~% - - if ((prop = WeaponAttributes.HitColdArea) != 0) - list.Add(1060416, prop.ToString()); // hit cold area ~1_val~% - - if ((prop = WeaponAttributes.HitDispel) != 0) - list.Add(1060417, prop.ToString()); // hit dispel ~1_val~% - - if ((prop = WeaponAttributes.HitEnergyArea) != 0) - list.Add(1060418, prop.ToString()); // hit energy area ~1_val~% - - if ((prop = WeaponAttributes.HitFireArea) != 0) - list.Add(1060419, prop.ToString()); // hit fire area ~1_val~% - - if ((prop = WeaponAttributes.HitFireball) != 0) - list.Add(1060420, prop.ToString()); // hit fireball ~1_val~% - - if ((prop = WeaponAttributes.HitHarm) != 0) - list.Add(1060421, prop.ToString()); // hit harm ~1_val~% - - if ((prop = WeaponAttributes.HitLeechHits) != 0) - list.Add(1060422, prop.ToString()); // hit life leech ~1_val~% - - if ((prop = WeaponAttributes.HitLightning) != 0) - list.Add(1060423, prop.ToString()); // hit lightning ~1_val~% - - if ((prop = WeaponAttributes.HitLowerAttack) != 0) - list.Add(1060424, prop.ToString()); // hit lower attack ~1_val~% - - if ((prop = WeaponAttributes.HitLowerDefend) != 0) - list.Add(1060425, prop.ToString()); // hit lower defense ~1_val~% - - if ((prop = WeaponAttributes.HitMagicArrow) != 0) - list.Add(1060426, prop.ToString()); // hit magic arrow ~1_val~% - - if ((prop = WeaponAttributes.HitLeechMana) != 0) - list.Add(1060427, prop.ToString()); // hit mana leech ~1_val~% - - if ((prop = WeaponAttributes.HitPhysicalArea) != 0) - list.Add(1060428, prop.ToString()); // hit physical area ~1_val~% - - if ((prop = WeaponAttributes.HitPoisonArea) != 0) - list.Add(1060429, prop.ToString()); // hit poison area ~1_val~% - - if ((prop = WeaponAttributes.HitLeechStam) != 0) - list.Add(1060430, prop.ToString()); // hit stamina leech ~1_val~% - - if (ImmolatingWeaponSpell.IsImmolating(this)) - list.Add(1111917); // Immolated - - if (Core.ML && (ranged?.Velocity ?? 0) != 0) - list.Add(1072793, prop.ToString()); // Velocity ~1_val~% - - if ((prop = Attributes.BonusDex) != 0) - list.Add(1060409, prop.ToString()); // dexterity bonus ~1_val~ - - if ((prop = Attributes.BonusHits) != 0) - list.Add(1060431, prop.ToString()); // hit point increase ~1_val~ - - if ((prop = Attributes.BonusInt) != 0) - list.Add(1060432, prop.ToString()); // intelligence bonus ~1_val~ - - if ((prop = Attributes.LowerManaCost) != 0) - list.Add(1060433, prop.ToString()); // lower mana cost ~1_val~% - - if ((prop = Attributes.LowerRegCost) != 0) - list.Add(1060434, prop.ToString()); // lower reagent cost ~1_val~% - - if ((prop = GetLowerStatReq()) != 0) - list.Add(1060435, prop.ToString()); // lower requirements ~1_val~% - - if ((prop = GetLuckBonus() + Attributes.Luck) != 0) - list.Add(1060436, prop.ToString()); // luck ~1_val~ - - if ((prop = WeaponAttributes.MageWeapon) != 0) - list.Add(1060438, (30 - prop).ToString()); // mage weapon -~1_val~ skill - - if ((prop = Attributes.BonusMana) != 0) - list.Add(1060439, prop.ToString()); // mana increase ~1_val~ - - if ((prop = Attributes.RegenMana) != 0) - list.Add(1060440, prop.ToString()); // mana regeneration ~1_val~ - - if (Attributes.NightSight != 0) - list.Add(1060441); // night sight - - if ((prop = Attributes.ReflectPhysical) != 0) - list.Add(1060442, prop.ToString()); // reflect physical damage ~1_val~% - - if ((prop = Attributes.RegenStam) != 0) - list.Add(1060443, prop.ToString()); // stamina regeneration ~1_val~ - - if ((prop = Attributes.RegenHits) != 0) - list.Add(1060444, prop.ToString()); // hit point regeneration ~1_val~ - - if ((prop = WeaponAttributes.SelfRepair) != 0) - list.Add(1060450, prop.ToString()); // self repair ~1_val~ - - if (Attributes.SpellChanneling != 0) - list.Add(1060482); // spell channeling - - if ((prop = Attributes.SpellDamage) != 0) - list.Add(1060483, prop.ToString()); // spell damage increase ~1_val~% - - if ((prop = Attributes.BonusStam) != 0) - list.Add(1060484, prop.ToString()); // stamina increase ~1_val~ - - if ((prop = Attributes.BonusStr) != 0) - list.Add(1060485, prop.ToString()); // strength bonus ~1_val~ - - if ((prop = Attributes.WeaponSpeed) != 0) - list.Add(1060486, prop.ToString()); // swing speed increase ~1_val~% - - if (Core.ML && (prop = Attributes.IncreasedKarmaLoss) != 0) - list.Add(1075210, prop.ToString()); // Increased Karma Loss ~1val~% - - GetDamageTypes(null, out int phys, out int fire, out int cold, out int pois, out int nrgy, out int chaos, - out int direct); - - if (phys != 0) - list.Add(1060403, phys.ToString()); // physical damage ~1_val~% - - if (fire != 0) - list.Add(1060405, fire.ToString()); // fire damage ~1_val~% - - if (cold != 0) - list.Add(1060404, cold.ToString()); // cold damage ~1_val~% - - if (pois != 0) - list.Add(1060406, pois.ToString()); // poison damage ~1_val~% - - if (nrgy != 0) - list.Add(1060407, nrgy.ToString()); // energy damage ~1_val - - if (Core.ML && chaos != 0) - list.Add(1072846, chaos.ToString()); // chaos damage ~1_val~% - - if (Core.ML && direct != 0) - list.Add(1079978, direct.ToString()); // Direct Damage: ~1_PERCENT~% - - list.Add(1061168, "{0}\t{1}", MinDamage.ToString(), MaxDamage.ToString()); // weapon damage ~1_val~ - ~2_val~ - - if (Core.ML) - list.Add(1061167, $"{Speed}s"); // weapon speed ~1_val~ - else - list.Add(1061167, Speed.ToString()); - - if (MaxRange > 1) - list.Add(1061169, MaxRange.ToString()); // range ~1_val~ - - int strReq = AOS.Scale(StrRequirement, 100 - GetLowerStatReq()); - - if (strReq > 0) - list.Add(1061170, strReq.ToString()); // strength requirement ~1_val~ - - if (Layer == Layer.TwoHanded) - list.Add(1061171); // two-handed weapon - else - list.Add(1061824); // one-handed weapon - - if (Core.SE || WeaponAttributes.UseBestSkill == 0) - switch (Skill) - { - case SkillName.Swords: - list.Add(1061172); - break; // skill required: swordsmanship - case SkillName.Macing: - list.Add(1061173); - break; // skill required: mace fighting - case SkillName.Fencing: - list.Add(1061174); - break; // skill required: fencing - case SkillName.Archery: - list.Add(1061175); - break; // skill required: archery + list.Add(1061167, Speed.ToString()); + + if (MaxRange > 1) + list.Add(1061169, MaxRange.ToString()); // range ~1_val~ + + var strReq = AOS.Scale(StrRequirement, 100 - GetLowerStatReq()); + + if (strReq > 0) + list.Add(1061170, strReq.ToString()); // strength requirement ~1_val~ + + if (Layer == Layer.TwoHanded) + list.Add(1061171); // two-handed weapon + else + list.Add(1061824); // one-handed weapon + + if (Core.SE || WeaponAttributes.UseBestSkill == 0) + switch (Skill) + { + case SkillName.Swords: + list.Add(1061172); + break; // skill required: swordsmanship + case SkillName.Macing: + list.Add(1061173); + break; // skill required: mace fighting + case SkillName.Fencing: + list.Add(1061174); + break; // skill required: fencing + case SkillName.Archery: + list.Add(1061175); + break; // skill required: archery + } + + if (m_Hits >= 0 && m_MaxHits > 0) + list.Add(1060639, "{0}\t{1}", m_Hits, m_MaxHits); // durability ~1_val~ / ~2_val~ } - if (m_Hits >= 0 && m_MaxHits > 0) - list.Add(1060639, "{0}\t{1}", m_Hits, m_MaxHits); // durability ~1_val~ / ~2_val~ - } - - public override void OnSingleClick(Mobile from) - { - List attrs = new List(); - - if (DisplayLootType) - { - if (LootType == LootType.Blessed) - attrs.Add(new EquipInfoAttribute(1038021)); // blessed - else if (LootType == LootType.Cursed) - attrs.Add(new EquipInfoAttribute(1049643)); // cursed - } - - if (m_FactionState != null) - attrs.Add(new EquipInfoAttribute(1041350)); // faction item - - if (m_Quality == WeaponQuality.Exceptional) - attrs.Add(new EquipInfoAttribute(1018305 - (int)m_Quality)); - - if (m_Identified || from.AccessLevel >= AccessLevel.GameMaster) - { - if (m_Slayer != SlayerName.None) + public override void OnSingleClick(Mobile from) { - SlayerEntry entry = SlayerGroup.GetEntryByName(m_Slayer); - if (entry != null) - attrs.Add(new EquipInfoAttribute(entry.Title)); - } + var attrs = new List(); - if (m_Slayer2 != SlayerName.None) - { - SlayerEntry entry = SlayerGroup.GetEntryByName(m_Slayer2); - if (entry != null) - attrs.Add(new EquipInfoAttribute(entry.Title)); - } - - if (m_DurabilityLevel != WeaponDurabilityLevel.Regular) - attrs.Add(new EquipInfoAttribute(1038000 + (int)m_DurabilityLevel)); - - if (m_DamageLevel != WeaponDamageLevel.Regular) - attrs.Add(new EquipInfoAttribute(1038015 + (int)m_DamageLevel)); - - if (m_AccuracyLevel != WeaponAccuracyLevel.Regular) - attrs.Add(new EquipInfoAttribute(1038010 + (int)m_AccuracyLevel)); - } - else if (m_Slayer != SlayerName.None || m_Slayer2 != SlayerName.None || - m_DurabilityLevel != WeaponDurabilityLevel.Regular || m_DamageLevel != WeaponDamageLevel.Regular || - m_AccuracyLevel != WeaponAccuracyLevel.Regular) - { - attrs.Add(new EquipInfoAttribute(1038000)); // Unidentified - } - - if (m_Poison != null && m_PoisonCharges > 0) - attrs.Add(new EquipInfoAttribute(1017383, m_PoisonCharges)); - - int number; - - if (Name == null) - { - number = LabelNumber; - } - else - { - LabelTo(from, Name); - number = 1041000; - } - - if (attrs.Count == 0 && Crafter == null && Name != null) - return; - - EquipmentInfo eqInfo = new EquipmentInfo(number, m_Crafter, false, attrs.ToArray()); - - from.Send(new DisplayEquipmentInfo(this, eqInfo)); - } - - private class ResetEquipTimer : Timer - { - private readonly Mobile m_Mobile; - - public ResetEquipTimer(Mobile m, TimeSpan duration) : base(duration) => m_Mobile = m; - - protected override void OnTick() - { - m_Mobile.EndAction(); - } - } - - private FactionItem m_FactionState; - - public FactionItem FactionItemState - { - get => m_FactionState; - set - { - m_FactionState = value; - - if (m_FactionState == null) - Hue = CraftResources.GetHue(Resource); - - LootType = m_FactionState == null ? LootType.Regular : LootType.Blessed; - } - } - - /* Weapon internals work differently now (Mar 13 2003) - * - * The attributes defined below default to -1. - * If the value is -1, the corresponding virtual 'Aos/Old' property is used. - * If not, the attribute value itself is used. Here's the list: - * - MinDamage - * - MaxDamage - * - Speed - * - HitSound - * - MissSound - * - StrRequirement, DexRequirement, IntRequirement - * - WeaponType - * - WeaponAnimation - * - MaxRange - */ - - // Instance values. These values are unique to each weapon. - private WeaponDamageLevel m_DamageLevel; - private WeaponAccuracyLevel m_AccuracyLevel; - private WeaponDurabilityLevel m_DurabilityLevel; - private WeaponQuality m_Quality; - private Mobile m_Crafter; - private Poison m_Poison; - private int m_PoisonCharges; - private bool m_Identified; - private int m_Hits; - private int m_MaxHits; - private SlayerName m_Slayer; - private SlayerName m_Slayer2; - private SkillMod m_SkillMod, m_MageMod; - private CraftResource m_Resource; - - // Overridable values. These values are provided to override the defaults which get defined in the individual weapon scripts. - private int m_StrReq, m_DexReq, m_IntReq; - private int m_MinDamage, m_MaxDamage; - private int m_HitSound, m_MissSound; - private float m_Speed; - private int m_MaxRange; - private SkillName m_Skill; - private WeaponType m_Type; - private WeaponAnimation m_Animation; - - public virtual WeaponAbility PrimaryAbility => null; - public virtual WeaponAbility SecondaryAbility => null; - - public virtual int DefMaxRange => 1; - public virtual int DefHitSound => 0; - public virtual int DefMissSound => 0; - public virtual SkillName DefSkill => SkillName.Swords; - public virtual WeaponType DefType => WeaponType.Slashing; - public virtual WeaponAnimation DefAnimation => WeaponAnimation.Slash1H; - - public virtual int AosStrengthReq => 0; - public virtual int AosDexterityReq => 0; - public virtual int AosIntelligenceReq => 0; - public virtual int AosMinDamage => 0; - public virtual int AosMaxDamage => 0; - public virtual int AosSpeed => 0; - public virtual float MlSpeed => 0.0f; - public virtual int AosMaxRange => DefMaxRange; - public virtual int AosHitSound => DefHitSound; - public virtual int AosMissSound => DefMissSound; - public virtual SkillName AosSkill => DefSkill; - public virtual WeaponType AosType => DefType; - public virtual WeaponAnimation AosAnimation => DefAnimation; - - public virtual int OldStrengthReq => 0; - public virtual int OldDexterityReq => 0; - public virtual int OldIntelligenceReq => 0; - public virtual int OldMinDamage => 0; - public virtual int OldMaxDamage => 0; - public virtual int OldSpeed => 0; - public virtual int OldMaxRange => DefMaxRange; - public virtual int OldHitSound => DefHitSound; - public virtual int OldMissSound => DefMissSound; - public virtual SkillName OldSkill => DefSkill; - public virtual WeaponType OldType => DefType; - public virtual WeaponAnimation OldAnimation => DefAnimation; - - public virtual int InitMinHits => 0; - public virtual int InitMaxHits => 0; - - public virtual bool CanFortify => true; - - public override int PhysicalResistance => WeaponAttributes.ResistPhysicalBonus; - public override int FireResistance => WeaponAttributes.ResistFireBonus; - public override int ColdResistance => WeaponAttributes.ResistColdBonus; - public override int PoisonResistance => WeaponAttributes.ResistPoisonBonus; - public override int EnergyResistance => WeaponAttributes.ResistEnergyBonus; - - public virtual SkillName AccuracySkill => SkillName.Tactics; - - [CommandProperty(AccessLevel.GameMaster)] - public AosAttributes Attributes { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public AosWeaponAttributes WeaponAttributes { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public AosSkillBonuses SkillBonuses { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public AosElementAttributes AosElementDamages { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Cursed { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Consecrated { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Identified - { - get => m_Identified; - set - { - m_Identified = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int HitPoints - { - get => m_Hits; - set - { - if (m_Hits == value) - return; - - if (value > m_MaxHits) - value = m_MaxHits; - - m_Hits = value; - - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxHitPoints - { - get => m_MaxHits; - set - { - m_MaxHits = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int PoisonCharges - { - get => m_PoisonCharges; - set - { - m_PoisonCharges = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Poison Poison - { - get => m_Poison; - set - { - m_Poison = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public WeaponQuality Quality - { - get => m_Quality; - set - { - UnscaleDurability(); - m_Quality = value; - ScaleDurability(); - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Crafter - { - get => m_Crafter; - set - { - m_Crafter = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public SlayerName Slayer - { - get => m_Slayer; - set - { - m_Slayer = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public SlayerName Slayer2 - { - get => m_Slayer2; - set - { - m_Slayer2 = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public CraftResource Resource - { - get => m_Resource; - set - { - UnscaleDurability(); - m_Resource = value; - Hue = CraftResources.GetHue(m_Resource); - InvalidateProperties(); - ScaleDurability(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public WeaponDamageLevel DamageLevel - { - get => m_DamageLevel; - set - { - m_DamageLevel = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public WeaponDurabilityLevel DurabilityLevel - { - get => m_DurabilityLevel; - set - { - UnscaleDurability(); - m_DurabilityLevel = value; - InvalidateProperties(); - ScaleDurability(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool PlayerConstructed { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxRange - { - get => m_MaxRange == -1 ? Core.AOS ? AosMaxRange : OldMaxRange : m_MaxRange; - set - { - m_MaxRange = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public WeaponAnimation Animation - { - get => m_Animation == (WeaponAnimation)(-1) ? Core.AOS ? AosAnimation : OldAnimation : m_Animation; - set => m_Animation = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public WeaponType Type - { - get => m_Type == (WeaponType)(-1) ? Core.AOS ? AosType : OldType : m_Type; - set => m_Type = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public SkillName Skill - { - get => m_Skill == (SkillName)(-1) ? Core.AOS ? AosSkill : OldSkill : m_Skill; - set - { - m_Skill = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int HitSound - { - get => m_HitSound == -1 ? Core.AOS ? AosHitSound : OldHitSound : m_HitSound; - set => m_HitSound = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int MissSound - { - get => m_MissSound == -1 ? Core.AOS ? AosMissSound : OldMissSound : m_MissSound; - set => m_MissSound = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int MinDamage - { - get => m_MinDamage == -1 ? Core.AOS ? AosMinDamage : OldMinDamage : m_MinDamage; - set - { - m_MinDamage = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxDamage - { - get => m_MaxDamage == -1 ? Core.AOS ? AosMaxDamage : OldMaxDamage : m_MaxDamage; - set - { - m_MaxDamage = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public float Speed - { - get - { - if (m_Speed != -1) - return m_Speed; - - if (Core.ML) - return MlSpeed; - if (Core.AOS) - return AosSpeed; - - return OldSpeed; - } - set - { - m_Speed = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int StrRequirement - { - get => m_StrReq == -1 ? Core.AOS ? AosStrengthReq : OldStrengthReq : m_StrReq; - set - { - m_StrReq = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int DexRequirement - { - get => m_DexReq == -1 ? Core.AOS ? AosDexterityReq : OldDexterityReq : m_DexReq; - set => m_DexReq = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int IntRequirement - { - get => m_IntReq == -1 ? Core.AOS ? AosIntelligenceReq : OldIntelligenceReq : m_IntReq; - set => m_IntReq = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public WeaponAccuracyLevel AccuracyLevel - { - get => m_AccuracyLevel; - set - { - if (m_AccuracyLevel != value) - { - m_AccuracyLevel = value; - - if (UseSkillMod) - { - if (m_AccuracyLevel == WeaponAccuracyLevel.Regular) + if (DisplayLootType) { - m_SkillMod?.Remove(); + if (LootType == LootType.Blessed) + attrs.Add(new EquipInfoAttribute(1038021)); // blessed + else if (LootType == LootType.Cursed) + attrs.Add(new EquipInfoAttribute(1049643)); // cursed + } - m_SkillMod = null; - } - else if (m_SkillMod == null && Parent is Mobile mobile) - { - m_SkillMod = new DefaultSkillMod(AccuracySkill, true, (int)m_AccuracyLevel * 5); - mobile.AddSkillMod(m_SkillMod); - } - else if (m_SkillMod != null) - { - m_SkillMod.Value = (int)m_AccuracyLevel * 5; - } - } + if (m_FactionState != null) + attrs.Add(new EquipInfoAttribute(1041350)); // faction item - InvalidateProperties(); + if (m_Quality == WeaponQuality.Exceptional) + attrs.Add(new EquipInfoAttribute(1018305 - (int)m_Quality)); + + if (m_Identified || from.AccessLevel >= AccessLevel.GameMaster) + { + if (m_Slayer != SlayerName.None) + { + var entry = SlayerGroup.GetEntryByName(m_Slayer); + if (entry != null) + attrs.Add(new EquipInfoAttribute(entry.Title)); + } + + if (m_Slayer2 != SlayerName.None) + { + var entry = SlayerGroup.GetEntryByName(m_Slayer2); + if (entry != null) + attrs.Add(new EquipInfoAttribute(entry.Title)); + } + + if (m_DurabilityLevel != WeaponDurabilityLevel.Regular) + attrs.Add(new EquipInfoAttribute(1038000 + (int)m_DurabilityLevel)); + + if (m_DamageLevel != WeaponDamageLevel.Regular) + attrs.Add(new EquipInfoAttribute(1038015 + (int)m_DamageLevel)); + + if (m_AccuracyLevel != WeaponAccuracyLevel.Regular) + attrs.Add(new EquipInfoAttribute(1038010 + (int)m_AccuracyLevel)); + } + else if (m_Slayer != SlayerName.None || m_Slayer2 != SlayerName.None || + m_DurabilityLevel != WeaponDurabilityLevel.Regular || m_DamageLevel != WeaponDamageLevel.Regular || + m_AccuracyLevel != WeaponAccuracyLevel.Regular) + { + attrs.Add(new EquipInfoAttribute(1038000)); // Unidentified + } + + if (m_Poison != null && m_PoisonCharges > 0) + attrs.Add(new EquipInfoAttribute(1017383, m_PoisonCharges)); + + int number; + + if (Name == null) + { + number = LabelNumber; + } + else + { + LabelTo(from, Name); + number = 1041000; + } + + if (attrs.Count == 0 && Crafter == null && Name != null) + return; + + var eqInfo = new EquipmentInfo(number, m_Crafter, false, attrs.ToArray()); + + from.Send(new DisplayEquipmentInfo(this, eqInfo)); } - } - } - public virtual int GetHitAttackSound(Mobile attacker, Mobile defender) - { - int sound = attacker.GetAttackSound(); + public virtual int GetHitAttackSound(Mobile attacker, Mobile defender) + { + var sound = attacker.GetAttackSound(); - if (sound == -1) - sound = HitSound; + if (sound == -1) + sound = HitSound; - return sound; - } + return sound; + } - public virtual int GetHitDefendSound(Mobile attacker, Mobile defender) => defender.GetHurtSound(); + public virtual int GetHitDefendSound(Mobile attacker, Mobile defender) => defender.GetHurtSound(); - public virtual int GetMissAttackSound(Mobile attacker, Mobile defender) => attacker.GetAttackSound() == -1 ? MissSound : -1; + public virtual int GetMissAttackSound(Mobile attacker, Mobile defender) => + attacker.GetAttackSound() == -1 ? MissSound : -1; - public virtual int GetMissDefendSound(Mobile attacker, Mobile defender) => -1; + public virtual int GetMissDefendSound(Mobile attacker, Mobile defender) => -1; - public virtual void DoMagicArrow(Mobile attacker, Mobile defender) - { - if (!attacker.CanBeHarmful(defender, false)) - return; + public virtual void DoMagicArrow(Mobile attacker, Mobile defender) + { + if (!attacker.CanBeHarmful(defender, false)) + return; - attacker.DoHarmful(defender); + attacker.DoHarmful(defender); - double damage = GetAosDamage(attacker, 10, 1, 4); + var damage = GetAosDamage(attacker, 10, 1, 4); - attacker.MovingParticles(defender, 0x36E4, 5, 0, false, true, 3006, 4006, 0); - attacker.PlaySound(0x1E5); + attacker.MovingParticles(defender, 0x36E4, 5, 0, false, true, 3006, 4006, 0); + attacker.PlaySound(0x1E5); - SpellHelper.Damage(TimeSpan.FromSeconds(1.0), defender, attacker, damage, 0, 100, 0, 0, 0); - } + SpellHelper.Damage(TimeSpan.FromSeconds(1.0), defender, attacker, damage, 0, 100, 0, 0, 0); + } - public virtual void DoHarm(Mobile attacker, Mobile defender) - { - if (!attacker.CanBeHarmful(defender, false)) - return; + public virtual void DoHarm(Mobile attacker, Mobile defender) + { + if (!attacker.CanBeHarmful(defender, false)) + return; - attacker.DoHarmful(defender); + attacker.DoHarmful(defender); - double damage = GetAosDamage(attacker, 17, 1, 5); + var damage = GetAosDamage(attacker, 17, 1, 5); - if (!defender.InRange(attacker, 2)) - damage *= 0.25; // 1/4 damage at > 2 tile range - else if (!defender.InRange(attacker, 1)) - damage *= 0.50; // 1/2 damage at 2 tile range + if (!defender.InRange(attacker, 2)) + damage *= 0.25; // 1/4 damage at > 2 tile range + else if (!defender.InRange(attacker, 1)) + damage *= 0.50; // 1/2 damage at 2 tile range - defender.FixedParticles(0x374A, 10, 30, 5013, 1153, 2, EffectLayer.Waist); - defender.PlaySound(0x0FC); + defender.FixedParticles(0x374A, 10, 30, 5013, 1153, 2, EffectLayer.Waist); + defender.PlaySound(0x0FC); - SpellHelper.Damage(TimeSpan.Zero, defender, attacker, damage, 0, 0, 100, 0, 0); - } + SpellHelper.Damage(TimeSpan.Zero, defender, attacker, damage, 0, 0, 100, 0, 0); + } - public virtual void DoFireball(Mobile attacker, Mobile defender) - { - if (!attacker.CanBeHarmful(defender, false)) - return; + public virtual void DoFireball(Mobile attacker, Mobile defender) + { + if (!attacker.CanBeHarmful(defender, false)) + return; - attacker.DoHarmful(defender); + attacker.DoHarmful(defender); - double damage = GetAosDamage(attacker, 19, 1, 5); + var damage = GetAosDamage(attacker, 19, 1, 5); - attacker.MovingParticles(defender, 0x36D4, 7, 0, false, true, 9502, 4019, 0x160); - attacker.PlaySound(0x15E); + attacker.MovingParticles(defender, 0x36D4, 7, 0, false, true, 9502, 4019, 0x160); + attacker.PlaySound(0x15E); - SpellHelper.Damage(TimeSpan.FromSeconds(1.0), defender, attacker, damage, 0, 100, 0, 0, 0); - } + SpellHelper.Damage(TimeSpan.FromSeconds(1.0), defender, attacker, damage, 0, 100, 0, 0, 0); + } - public virtual void DoLightning(Mobile attacker, Mobile defender) - { - if (!attacker.CanBeHarmful(defender, false)) - return; + public virtual void DoLightning(Mobile attacker, Mobile defender) + { + if (!attacker.CanBeHarmful(defender, false)) + return; - attacker.DoHarmful(defender); + attacker.DoHarmful(defender); - double damage = GetAosDamage(attacker, 23, 1, 4); + var damage = GetAosDamage(attacker, 23, 1, 4); - defender.BoltEffect(0); + defender.BoltEffect(0); - SpellHelper.Damage(TimeSpan.Zero, defender, attacker, damage, 0, 0, 0, 0, 100); - } + SpellHelper.Damage(TimeSpan.Zero, defender, attacker, damage, 0, 0, 0, 0, 100); + } - public virtual void DoDispel(Mobile attacker, Mobile defender) - { - bool dispellable = false; + public virtual void DoDispel(Mobile attacker, Mobile defender) + { + var dispellable = false; - if (defender is BaseCreature creature) - dispellable = creature.Summoned && !creature.IsAnimatedDead; + if (defender is BaseCreature creature) + dispellable = creature.Summoned && !creature.IsAnimatedDead; - if (!dispellable) - return; + if (!dispellable) + return; - if (!attacker.CanBeHarmful(defender, false)) - return; + if (!attacker.CanBeHarmful(defender, false)) + return; - attacker.DoHarmful(defender); + attacker.DoHarmful(defender); - MagerySpell sp = new DispelSpell(attacker); + MagerySpell sp = new DispelSpell(attacker); - if (sp.CheckResisted(defender)) - { - defender.FixedEffect(0x3779, 10, 20); - } - else - { - Effects.SendLocationParticles(EffectItem.Create(defender.Location, defender.Map, EffectItem.DefaultDuration), - 0x3728, 8, 20, 5042); - Effects.PlaySound(defender, defender.Map, 0x201); - - defender.Delete(); - } - } - - public virtual void DoLowerAttack(Mobile from, Mobile defender) - { - if (HitLower.ApplyAttack(defender)) - { - defender.PlaySound(0x28E); - Effects.SendTargetEffect(defender, 0x37BE, 1, 4, 0xA, 3); - } - } - - public virtual void DoLowerDefense(Mobile from, Mobile defender) - { - if (HitLower.ApplyDefense(defender)) - { - defender.PlaySound(0x28E); - Effects.SendTargetEffect(defender, 0x37BE, 1, 4, 0x23, 3); - } - } - - public virtual void DoAreaAttack(Mobile from, Mobile defender, int sound, int hue, int phys, int fire, int cold, - int pois, int nrgy) - { - Map map = from.Map; - - if (map == null) - return; - - int range = Core.ML ? 5 : 10; - - IPooledEnumerable eable = from.GetMobilesInRange(range); - List list = eable.Where(m => - from != m && defender != m && SpellHelper.ValidIndirectTarget(from, m) - && from.CanBeHarmful(m, false) && (!Core.ML || from.InLOS(m))).ToList(); - eable.Free(); - - if (list.Count == 0) - return; - - Effects.PlaySound(from.Location, map, sound); - - for (int i = 0; i < list.Count; ++i) - { - Mobile m = list[i]; - - double scalar = Core.ML ? 1.0 : (11 - from.GetDistanceToSqrt(m)) / 10; - double damage = GetBaseDamage(from); - - if (scalar <= 0) continue; - - if (scalar < 1.0) damage *= (11 - from.GetDistanceToSqrt(m)) / 10; - - from.DoHarmful(m, true); - m.FixedEffect(0x3779, 1, 15, hue, 0); - AOS.Damage(m, from, (int)damage, phys, fire, cold, pois, nrgy); - } - } - - private static void SetSaveFlag(ref SaveFlag flags, SaveFlag toSet, bool setIf) - { - if (setIf) - flags |= toSet; - } - - private static bool GetSaveFlag(SaveFlag flags, SaveFlag toGet) => (flags & toGet) != 0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(9); // version - - SaveFlag flags = SaveFlag.None; - - SetSaveFlag(ref flags, SaveFlag.DamageLevel, m_DamageLevel != WeaponDamageLevel.Regular); - SetSaveFlag(ref flags, SaveFlag.AccuracyLevel, m_AccuracyLevel != WeaponAccuracyLevel.Regular); - SetSaveFlag(ref flags, SaveFlag.DurabilityLevel, m_DurabilityLevel != WeaponDurabilityLevel.Regular); - SetSaveFlag(ref flags, SaveFlag.Quality, m_Quality != WeaponQuality.Regular); - SetSaveFlag(ref flags, SaveFlag.Hits, m_Hits != 0); - SetSaveFlag(ref flags, SaveFlag.MaxHits, m_MaxHits != 0); - SetSaveFlag(ref flags, SaveFlag.Slayer, m_Slayer != SlayerName.None); - SetSaveFlag(ref flags, SaveFlag.Poison, m_Poison != null); - SetSaveFlag(ref flags, SaveFlag.PoisonCharges, m_PoisonCharges != 0); - SetSaveFlag(ref flags, SaveFlag.Crafter, m_Crafter != null); - SetSaveFlag(ref flags, SaveFlag.Identified, m_Identified); - SetSaveFlag(ref flags, SaveFlag.StrReq, m_StrReq != -1); - SetSaveFlag(ref flags, SaveFlag.DexReq, m_DexReq != -1); - SetSaveFlag(ref flags, SaveFlag.IntReq, m_IntReq != -1); - SetSaveFlag(ref flags, SaveFlag.MinDamage, m_MinDamage != -1); - SetSaveFlag(ref flags, SaveFlag.MaxDamage, m_MaxDamage != -1); - SetSaveFlag(ref flags, SaveFlag.HitSound, m_HitSound != -1); - SetSaveFlag(ref flags, SaveFlag.MissSound, m_MissSound != -1); - SetSaveFlag(ref flags, SaveFlag.Speed, m_Speed != -1); - SetSaveFlag(ref flags, SaveFlag.MaxRange, m_MaxRange != -1); - SetSaveFlag(ref flags, SaveFlag.Skill, m_Skill != (SkillName)(-1)); - SetSaveFlag(ref flags, SaveFlag.Type, m_Type != (WeaponType)(-1)); - SetSaveFlag(ref flags, SaveFlag.Animation, m_Animation != (WeaponAnimation)(-1)); - SetSaveFlag(ref flags, SaveFlag.Resource, m_Resource != CraftResource.Iron); - SetSaveFlag(ref flags, SaveFlag.xAttributes, !Attributes.IsEmpty); - SetSaveFlag(ref flags, SaveFlag.xWeaponAttributes, !WeaponAttributes.IsEmpty); - SetSaveFlag(ref flags, SaveFlag.PlayerConstructed, PlayerConstructed); - SetSaveFlag(ref flags, SaveFlag.SkillBonuses, !SkillBonuses.IsEmpty); - SetSaveFlag(ref flags, SaveFlag.Slayer2, m_Slayer2 != SlayerName.None); - SetSaveFlag(ref flags, SaveFlag.ElementalDamages, !AosElementDamages.IsEmpty); - SetSaveFlag(ref flags, SaveFlag.EngravedText, !string.IsNullOrEmpty(m_EngravedText)); - - writer.Write((int)flags); - - if (GetSaveFlag(flags, SaveFlag.DamageLevel)) - writer.Write((int)m_DamageLevel); - - if (GetSaveFlag(flags, SaveFlag.AccuracyLevel)) - writer.Write((int)m_AccuracyLevel); - - if (GetSaveFlag(flags, SaveFlag.DurabilityLevel)) - writer.Write((int)m_DurabilityLevel); - - if (GetSaveFlag(flags, SaveFlag.Quality)) - writer.Write((int)m_Quality); - - if (GetSaveFlag(flags, SaveFlag.Hits)) - writer.Write(m_Hits); - - if (GetSaveFlag(flags, SaveFlag.MaxHits)) - writer.Write(m_MaxHits); - - if (GetSaveFlag(flags, SaveFlag.Slayer)) - writer.Write((int)m_Slayer); - - if (GetSaveFlag(flags, SaveFlag.Poison)) - Poison.Serialize(m_Poison, writer); - - if (GetSaveFlag(flags, SaveFlag.PoisonCharges)) - writer.Write(m_PoisonCharges); - - if (GetSaveFlag(flags, SaveFlag.Crafter)) - writer.Write(m_Crafter); - - if (GetSaveFlag(flags, SaveFlag.StrReq)) - writer.Write(m_StrReq); - - if (GetSaveFlag(flags, SaveFlag.DexReq)) - writer.Write(m_DexReq); - - if (GetSaveFlag(flags, SaveFlag.IntReq)) - writer.Write(m_IntReq); - - if (GetSaveFlag(flags, SaveFlag.MinDamage)) - writer.Write(m_MinDamage); - - if (GetSaveFlag(flags, SaveFlag.MaxDamage)) - writer.Write(m_MaxDamage); - - if (GetSaveFlag(flags, SaveFlag.HitSound)) - writer.Write(m_HitSound); - - if (GetSaveFlag(flags, SaveFlag.MissSound)) - writer.Write(m_MissSound); - - if (GetSaveFlag(flags, SaveFlag.Speed)) - writer.Write(m_Speed); - - if (GetSaveFlag(flags, SaveFlag.MaxRange)) - writer.Write(m_MaxRange); - - if (GetSaveFlag(flags, SaveFlag.Skill)) - writer.Write((int)m_Skill); - - if (GetSaveFlag(flags, SaveFlag.Type)) - writer.Write((int)m_Type); - - if (GetSaveFlag(flags, SaveFlag.Animation)) - writer.Write((int)m_Animation); - - if (GetSaveFlag(flags, SaveFlag.Resource)) - writer.Write((int)m_Resource); - - if (GetSaveFlag(flags, SaveFlag.xAttributes)) - Attributes.Serialize(writer); - - if (GetSaveFlag(flags, SaveFlag.xWeaponAttributes)) - WeaponAttributes.Serialize(writer); - - if (GetSaveFlag(flags, SaveFlag.SkillBonuses)) - SkillBonuses.Serialize(writer); - - if (GetSaveFlag(flags, SaveFlag.Slayer2)) - writer.Write((int)m_Slayer2); - - if (GetSaveFlag(flags, SaveFlag.ElementalDamages)) - AosElementDamages.Serialize(writer); - - if (GetSaveFlag(flags, SaveFlag.EngravedText)) - writer.Write(m_EngravedText); - } - - [Flags] - private enum SaveFlag - { - None = 0x00000000, - DamageLevel = 0x00000001, - AccuracyLevel = 0x00000002, - DurabilityLevel = 0x00000004, - Quality = 0x00000008, - Hits = 0x00000010, - MaxHits = 0x00000020, - Slayer = 0x00000040, - Poison = 0x00000080, - PoisonCharges = 0x00000100, - Crafter = 0x00000200, - Identified = 0x00000400, - StrReq = 0x00000800, - DexReq = 0x00001000, - IntReq = 0x00002000, - MinDamage = 0x00004000, - MaxDamage = 0x00008000, - HitSound = 0x00010000, - MissSound = 0x00020000, - Speed = 0x00040000, - MaxRange = 0x00080000, - Skill = 0x00100000, - Type = 0x00200000, - Animation = 0x00400000, - Resource = 0x00800000, - xAttributes = 0x01000000, - xWeaponAttributes = 0x02000000, - PlayerConstructed = 0x04000000, - SkillBonuses = 0x08000000, - Slayer2 = 0x10000000, - ElementalDamages = 0x20000000, - EngravedText = 0x40000000 - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Mobile parentMobile = Parent as Mobile; - - switch (version) - { - case 9: - case 8: - case 7: - case 6: - case 5: - { - SaveFlag flags = (SaveFlag)reader.ReadInt(); + if (sp.CheckResisted(defender)) + { + defender.FixedEffect(0x3779, 10, 20); + } + else + { + Effects.SendLocationParticles( + EffectItem.Create(defender.Location, defender.Map, EffectItem.DefaultDuration), + 0x3728, + 8, + 20, + 5042 + ); + Effects.PlaySound(defender, defender.Map, 0x201); + + defender.Delete(); + } + } + + public virtual void DoLowerAttack(Mobile from, Mobile defender) + { + if (HitLower.ApplyAttack(defender)) + { + defender.PlaySound(0x28E); + Effects.SendTargetEffect(defender, 0x37BE, 1, 4, 0xA, 3); + } + } + + public virtual void DoLowerDefense(Mobile from, Mobile defender) + { + if (HitLower.ApplyDefense(defender)) + { + defender.PlaySound(0x28E); + Effects.SendTargetEffect(defender, 0x37BE, 1, 4, 0x23, 3); + } + } + + public virtual void DoAreaAttack( + Mobile from, Mobile defender, int sound, int hue, int phys, int fire, int cold, + int pois, int nrgy + ) + { + var map = from.Map; + + if (map == null) + return; + + var range = Core.ML ? 5 : 10; + + var eable = from.GetMobilesInRange(range); + var list = eable.Where( + m => + from != m && defender != m && SpellHelper.ValidIndirectTarget(from, m) + && from.CanBeHarmful(m, false) && (!Core.ML || from.InLOS(m)) + ) + .ToList(); + eable.Free(); + + if (list.Count == 0) + return; + + Effects.PlaySound(from.Location, map, sound); + + for (var i = 0; i < list.Count; ++i) + { + var m = list[i]; + + var scalar = Core.ML ? 1.0 : (11 - from.GetDistanceToSqrt(m)) / 10; + var damage = GetBaseDamage(from); + + if (scalar <= 0) continue; + + if (scalar < 1.0) damage *= (11 - from.GetDistanceToSqrt(m)) / 10; + + from.DoHarmful(m, true); + m.FixedEffect(0x3779, 1, 15, hue, 0); + AOS.Damage(m, from, (int)damage, phys, fire, cold, pois, nrgy); + } + } + + private static void SetSaveFlag(ref SaveFlag flags, SaveFlag toSet, bool setIf) + { + if (setIf) + flags |= toSet; + } + + private static bool GetSaveFlag(SaveFlag flags, SaveFlag toGet) => (flags & toGet) != 0; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(9); // version + + var flags = SaveFlag.None; + + SetSaveFlag(ref flags, SaveFlag.DamageLevel, m_DamageLevel != WeaponDamageLevel.Regular); + SetSaveFlag(ref flags, SaveFlag.AccuracyLevel, m_AccuracyLevel != WeaponAccuracyLevel.Regular); + SetSaveFlag(ref flags, SaveFlag.DurabilityLevel, m_DurabilityLevel != WeaponDurabilityLevel.Regular); + SetSaveFlag(ref flags, SaveFlag.Quality, m_Quality != WeaponQuality.Regular); + SetSaveFlag(ref flags, SaveFlag.Hits, m_Hits != 0); + SetSaveFlag(ref flags, SaveFlag.MaxHits, m_MaxHits != 0); + SetSaveFlag(ref flags, SaveFlag.Slayer, m_Slayer != SlayerName.None); + SetSaveFlag(ref flags, SaveFlag.Poison, m_Poison != null); + SetSaveFlag(ref flags, SaveFlag.PoisonCharges, m_PoisonCharges != 0); + SetSaveFlag(ref flags, SaveFlag.Crafter, m_Crafter != null); + SetSaveFlag(ref flags, SaveFlag.Identified, m_Identified); + SetSaveFlag(ref flags, SaveFlag.StrReq, m_StrReq != -1); + SetSaveFlag(ref flags, SaveFlag.DexReq, m_DexReq != -1); + SetSaveFlag(ref flags, SaveFlag.IntReq, m_IntReq != -1); + SetSaveFlag(ref flags, SaveFlag.MinDamage, m_MinDamage != -1); + SetSaveFlag(ref flags, SaveFlag.MaxDamage, m_MaxDamage != -1); + SetSaveFlag(ref flags, SaveFlag.HitSound, m_HitSound != -1); + SetSaveFlag(ref flags, SaveFlag.MissSound, m_MissSound != -1); + SetSaveFlag(ref flags, SaveFlag.Speed, m_Speed != -1); + SetSaveFlag(ref flags, SaveFlag.MaxRange, m_MaxRange != -1); + SetSaveFlag(ref flags, SaveFlag.Skill, m_Skill != (SkillName)(-1)); + SetSaveFlag(ref flags, SaveFlag.Type, m_Type != (WeaponType)(-1)); + SetSaveFlag(ref flags, SaveFlag.Animation, m_Animation != (WeaponAnimation)(-1)); + SetSaveFlag(ref flags, SaveFlag.Resource, m_Resource != CraftResource.Iron); + SetSaveFlag(ref flags, SaveFlag.xAttributes, !Attributes.IsEmpty); + SetSaveFlag(ref flags, SaveFlag.xWeaponAttributes, !WeaponAttributes.IsEmpty); + SetSaveFlag(ref flags, SaveFlag.PlayerConstructed, PlayerConstructed); + SetSaveFlag(ref flags, SaveFlag.SkillBonuses, !SkillBonuses.IsEmpty); + SetSaveFlag(ref flags, SaveFlag.Slayer2, m_Slayer2 != SlayerName.None); + SetSaveFlag(ref flags, SaveFlag.ElementalDamages, !AosElementDamages.IsEmpty); + SetSaveFlag(ref flags, SaveFlag.EngravedText, !string.IsNullOrEmpty(m_EngravedText)); + + writer.Write((int)flags); if (GetSaveFlag(flags, SaveFlag.DamageLevel)) - { - m_DamageLevel = (WeaponDamageLevel)reader.ReadInt(); - - if (m_DamageLevel > WeaponDamageLevel.Vanq) - m_DamageLevel = WeaponDamageLevel.Ruin; - } + writer.Write((int)m_DamageLevel); if (GetSaveFlag(flags, SaveFlag.AccuracyLevel)) - { - m_AccuracyLevel = (WeaponAccuracyLevel)reader.ReadInt(); - - if (m_AccuracyLevel > WeaponAccuracyLevel.Supremely) - m_AccuracyLevel = WeaponAccuracyLevel.Accurate; - } + writer.Write((int)m_AccuracyLevel); if (GetSaveFlag(flags, SaveFlag.DurabilityLevel)) - { - m_DurabilityLevel = (WeaponDurabilityLevel)reader.ReadInt(); - - if (m_DurabilityLevel > WeaponDurabilityLevel.Indestructible) - m_DurabilityLevel = WeaponDurabilityLevel.Durable; - } + writer.Write((int)m_DurabilityLevel); if (GetSaveFlag(flags, SaveFlag.Quality)) - m_Quality = (WeaponQuality)reader.ReadInt(); - else - m_Quality = WeaponQuality.Regular; + writer.Write((int)m_Quality); if (GetSaveFlag(flags, SaveFlag.Hits)) - m_Hits = reader.ReadInt(); + writer.Write(m_Hits); if (GetSaveFlag(flags, SaveFlag.MaxHits)) - m_MaxHits = reader.ReadInt(); + writer.Write(m_MaxHits); if (GetSaveFlag(flags, SaveFlag.Slayer)) - m_Slayer = (SlayerName)reader.ReadInt(); + writer.Write((int)m_Slayer); if (GetSaveFlag(flags, SaveFlag.Poison)) - m_Poison = Poison.Deserialize(reader); + Poison.Serialize(m_Poison, writer); if (GetSaveFlag(flags, SaveFlag.PoisonCharges)) - m_PoisonCharges = reader.ReadInt(); + writer.Write(m_PoisonCharges); if (GetSaveFlag(flags, SaveFlag.Crafter)) - m_Crafter = reader.ReadMobile(); - - if (GetSaveFlag(flags, SaveFlag.Identified)) - m_Identified = version >= 6 || reader.ReadBool(); + writer.Write(m_Crafter); if (GetSaveFlag(flags, SaveFlag.StrReq)) - m_StrReq = reader.ReadInt(); - else - m_StrReq = -1; + writer.Write(m_StrReq); if (GetSaveFlag(flags, SaveFlag.DexReq)) - m_DexReq = reader.ReadInt(); - else - m_DexReq = -1; + writer.Write(m_DexReq); if (GetSaveFlag(flags, SaveFlag.IntReq)) - m_IntReq = reader.ReadInt(); - else - m_IntReq = -1; + writer.Write(m_IntReq); if (GetSaveFlag(flags, SaveFlag.MinDamage)) - m_MinDamage = reader.ReadInt(); - else - m_MinDamage = -1; + writer.Write(m_MinDamage); if (GetSaveFlag(flags, SaveFlag.MaxDamage)) - m_MaxDamage = reader.ReadInt(); - else - m_MaxDamage = -1; + writer.Write(m_MaxDamage); if (GetSaveFlag(flags, SaveFlag.HitSound)) - m_HitSound = reader.ReadInt(); - else - m_HitSound = -1; + writer.Write(m_HitSound); if (GetSaveFlag(flags, SaveFlag.MissSound)) - m_MissSound = reader.ReadInt(); - else - m_MissSound = -1; + writer.Write(m_MissSound); if (GetSaveFlag(flags, SaveFlag.Speed)) - { - if (version < 9) - m_Speed = reader.ReadInt(); - else - m_Speed = reader.ReadFloat(); - } - else - { - m_Speed = -1; - } + writer.Write(m_Speed); if (GetSaveFlag(flags, SaveFlag.MaxRange)) - m_MaxRange = reader.ReadInt(); - else - m_MaxRange = -1; + writer.Write(m_MaxRange); if (GetSaveFlag(flags, SaveFlag.Skill)) - m_Skill = (SkillName)reader.ReadInt(); - else - m_Skill = (SkillName)(-1); + writer.Write((int)m_Skill); if (GetSaveFlag(flags, SaveFlag.Type)) - m_Type = (WeaponType)reader.ReadInt(); - else - m_Type = (WeaponType)(-1); + writer.Write((int)m_Type); if (GetSaveFlag(flags, SaveFlag.Animation)) - m_Animation = (WeaponAnimation)reader.ReadInt(); - else - m_Animation = (WeaponAnimation)(-1); + writer.Write((int)m_Animation); if (GetSaveFlag(flags, SaveFlag.Resource)) - m_Resource = (CraftResource)reader.ReadInt(); - else - m_Resource = CraftResource.Iron; + writer.Write((int)m_Resource); if (GetSaveFlag(flags, SaveFlag.xAttributes)) - Attributes = new AosAttributes(this, reader); - else - Attributes = new AosAttributes(this); + Attributes.Serialize(writer); if (GetSaveFlag(flags, SaveFlag.xWeaponAttributes)) - WeaponAttributes = new AosWeaponAttributes(this, reader); - else - WeaponAttributes = new AosWeaponAttributes(this); - - if (UseSkillMod && m_AccuracyLevel != WeaponAccuracyLevel.Regular && parentMobile != null) - { - m_SkillMod = new DefaultSkillMod(AccuracySkill, true, (int)m_AccuracyLevel * 5); - parentMobile.AddSkillMod(m_SkillMod); - } - - if (version < 7 && WeaponAttributes.MageWeapon != 0) - WeaponAttributes.MageWeapon = 30 - WeaponAttributes.MageWeapon; - - if (Core.AOS && WeaponAttributes.MageWeapon != 0 && WeaponAttributes.MageWeapon != 30 && - parentMobile != null) - { - m_MageMod = new DefaultSkillMod(SkillName.Magery, true, -30 + WeaponAttributes.MageWeapon); - parentMobile.AddSkillMod(m_MageMod); - } - - if (GetSaveFlag(flags, SaveFlag.PlayerConstructed)) - PlayerConstructed = true; + WeaponAttributes.Serialize(writer); if (GetSaveFlag(flags, SaveFlag.SkillBonuses)) - SkillBonuses = new AosSkillBonuses(this, reader); - else - SkillBonuses = new AosSkillBonuses(this); + SkillBonuses.Serialize(writer); if (GetSaveFlag(flags, SaveFlag.Slayer2)) - m_Slayer2 = (SlayerName)reader.ReadInt(); + writer.Write((int)m_Slayer2); if (GetSaveFlag(flags, SaveFlag.ElementalDamages)) - AosElementDamages = new AosElementAttributes(this, reader); - else - AosElementDamages = new AosElementAttributes(this); + AosElementDamages.Serialize(writer); if (GetSaveFlag(flags, SaveFlag.EngravedText)) - m_EngravedText = reader.ReadString(); + writer.Write(m_EngravedText); + } - break; - } - case 4: - { - m_Slayer = (SlayerName)reader.ReadInt(); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - goto case 3; - } - case 3: - { - m_StrReq = reader.ReadInt(); - m_DexReq = reader.ReadInt(); - m_IntReq = reader.ReadInt(); + var version = reader.ReadInt(); - goto case 2; - } - case 2: - { - m_Identified = reader.ReadBool(); + var parentMobile = Parent as Mobile; - goto case 1; - } - case 1: - { - m_MaxRange = reader.ReadInt(); - - goto case 0; - } - case 0: - { - if (version == 0) - m_MaxRange = 1; // default - - if (version < 5) + switch (version) { - m_Resource = CraftResource.Iron; - Attributes = new AosAttributes(this); - WeaponAttributes = new AosWeaponAttributes(this); - AosElementDamages = new AosElementAttributes(this); - SkillBonuses = new AosSkillBonuses(this); + case 9: + case 8: + case 7: + case 6: + case 5: + { + var flags = (SaveFlag)reader.ReadInt(); + + if (GetSaveFlag(flags, SaveFlag.DamageLevel)) + { + m_DamageLevel = (WeaponDamageLevel)reader.ReadInt(); + + if (m_DamageLevel > WeaponDamageLevel.Vanq) + m_DamageLevel = WeaponDamageLevel.Ruin; + } + + if (GetSaveFlag(flags, SaveFlag.AccuracyLevel)) + { + m_AccuracyLevel = (WeaponAccuracyLevel)reader.ReadInt(); + + if (m_AccuracyLevel > WeaponAccuracyLevel.Supremely) + m_AccuracyLevel = WeaponAccuracyLevel.Accurate; + } + + if (GetSaveFlag(flags, SaveFlag.DurabilityLevel)) + { + m_DurabilityLevel = (WeaponDurabilityLevel)reader.ReadInt(); + + if (m_DurabilityLevel > WeaponDurabilityLevel.Indestructible) + m_DurabilityLevel = WeaponDurabilityLevel.Durable; + } + + if (GetSaveFlag(flags, SaveFlag.Quality)) + m_Quality = (WeaponQuality)reader.ReadInt(); + else + m_Quality = WeaponQuality.Regular; + + if (GetSaveFlag(flags, SaveFlag.Hits)) + m_Hits = reader.ReadInt(); + + if (GetSaveFlag(flags, SaveFlag.MaxHits)) + m_MaxHits = reader.ReadInt(); + + if (GetSaveFlag(flags, SaveFlag.Slayer)) + m_Slayer = (SlayerName)reader.ReadInt(); + + if (GetSaveFlag(flags, SaveFlag.Poison)) + m_Poison = Poison.Deserialize(reader); + + if (GetSaveFlag(flags, SaveFlag.PoisonCharges)) + m_PoisonCharges = reader.ReadInt(); + + if (GetSaveFlag(flags, SaveFlag.Crafter)) + m_Crafter = reader.ReadMobile(); + + if (GetSaveFlag(flags, SaveFlag.Identified)) + m_Identified = version >= 6 || reader.ReadBool(); + + if (GetSaveFlag(flags, SaveFlag.StrReq)) + m_StrReq = reader.ReadInt(); + else + m_StrReq = -1; + + if (GetSaveFlag(flags, SaveFlag.DexReq)) + m_DexReq = reader.ReadInt(); + else + m_DexReq = -1; + + if (GetSaveFlag(flags, SaveFlag.IntReq)) + m_IntReq = reader.ReadInt(); + else + m_IntReq = -1; + + if (GetSaveFlag(flags, SaveFlag.MinDamage)) + m_MinDamage = reader.ReadInt(); + else + m_MinDamage = -1; + + if (GetSaveFlag(flags, SaveFlag.MaxDamage)) + m_MaxDamage = reader.ReadInt(); + else + m_MaxDamage = -1; + + if (GetSaveFlag(flags, SaveFlag.HitSound)) + m_HitSound = reader.ReadInt(); + else + m_HitSound = -1; + + if (GetSaveFlag(flags, SaveFlag.MissSound)) + m_MissSound = reader.ReadInt(); + else + m_MissSound = -1; + + if (GetSaveFlag(flags, SaveFlag.Speed)) + { + if (version < 9) + m_Speed = reader.ReadInt(); + else + m_Speed = reader.ReadFloat(); + } + else + { + m_Speed = -1; + } + + if (GetSaveFlag(flags, SaveFlag.MaxRange)) + m_MaxRange = reader.ReadInt(); + else + m_MaxRange = -1; + + if (GetSaveFlag(flags, SaveFlag.Skill)) + m_Skill = (SkillName)reader.ReadInt(); + else + m_Skill = (SkillName)(-1); + + if (GetSaveFlag(flags, SaveFlag.Type)) + m_Type = (WeaponType)reader.ReadInt(); + else + m_Type = (WeaponType)(-1); + + if (GetSaveFlag(flags, SaveFlag.Animation)) + m_Animation = (WeaponAnimation)reader.ReadInt(); + else + m_Animation = (WeaponAnimation)(-1); + + if (GetSaveFlag(flags, SaveFlag.Resource)) + m_Resource = (CraftResource)reader.ReadInt(); + else + m_Resource = CraftResource.Iron; + + if (GetSaveFlag(flags, SaveFlag.xAttributes)) + Attributes = new AosAttributes(this, reader); + else + Attributes = new AosAttributes(this); + + if (GetSaveFlag(flags, SaveFlag.xWeaponAttributes)) + WeaponAttributes = new AosWeaponAttributes(this, reader); + else + WeaponAttributes = new AosWeaponAttributes(this); + + if (UseSkillMod && m_AccuracyLevel != WeaponAccuracyLevel.Regular && parentMobile != null) + { + m_SkillMod = new DefaultSkillMod(AccuracySkill, true, (int)m_AccuracyLevel * 5); + parentMobile.AddSkillMod(m_SkillMod); + } + + if (version < 7 && WeaponAttributes.MageWeapon != 0) + WeaponAttributes.MageWeapon = 30 - WeaponAttributes.MageWeapon; + + if (Core.AOS && WeaponAttributes.MageWeapon != 0 && WeaponAttributes.MageWeapon != 30 && + parentMobile != null) + { + m_MageMod = new DefaultSkillMod(SkillName.Magery, true, -30 + WeaponAttributes.MageWeapon); + parentMobile.AddSkillMod(m_MageMod); + } + + if (GetSaveFlag(flags, SaveFlag.PlayerConstructed)) + PlayerConstructed = true; + + if (GetSaveFlag(flags, SaveFlag.SkillBonuses)) + SkillBonuses = new AosSkillBonuses(this, reader); + else + SkillBonuses = new AosSkillBonuses(this); + + if (GetSaveFlag(flags, SaveFlag.Slayer2)) + m_Slayer2 = (SlayerName)reader.ReadInt(); + + if (GetSaveFlag(flags, SaveFlag.ElementalDamages)) + AosElementDamages = new AosElementAttributes(this, reader); + else + AosElementDamages = new AosElementAttributes(this); + + if (GetSaveFlag(flags, SaveFlag.EngravedText)) + m_EngravedText = reader.ReadString(); + + break; + } + case 4: + { + m_Slayer = (SlayerName)reader.ReadInt(); + + goto case 3; + } + case 3: + { + m_StrReq = reader.ReadInt(); + m_DexReq = reader.ReadInt(); + m_IntReq = reader.ReadInt(); + + goto case 2; + } + case 2: + { + m_Identified = reader.ReadBool(); + + goto case 1; + } + case 1: + { + m_MaxRange = reader.ReadInt(); + + goto case 0; + } + case 0: + { + if (version == 0) + m_MaxRange = 1; // default + + if (version < 5) + { + m_Resource = CraftResource.Iron; + Attributes = new AosAttributes(this); + WeaponAttributes = new AosWeaponAttributes(this); + AosElementDamages = new AosElementAttributes(this); + SkillBonuses = new AosSkillBonuses(this); + } + + m_MinDamage = reader.ReadInt(); + m_MaxDamage = reader.ReadInt(); + + m_Speed = reader.ReadInt(); + + m_HitSound = reader.ReadInt(); + m_MissSound = reader.ReadInt(); + + m_Skill = (SkillName)reader.ReadInt(); + m_Type = (WeaponType)reader.ReadInt(); + m_Animation = (WeaponAnimation)reader.ReadInt(); + m_DamageLevel = (WeaponDamageLevel)reader.ReadInt(); + m_AccuracyLevel = (WeaponAccuracyLevel)reader.ReadInt(); + m_DurabilityLevel = (WeaponDurabilityLevel)reader.ReadInt(); + m_Quality = (WeaponQuality)reader.ReadInt(); + + m_Crafter = reader.ReadMobile(); + + m_Poison = Poison.Deserialize(reader); + m_PoisonCharges = reader.ReadInt(); + + if (m_StrReq == OldStrengthReq) + m_StrReq = -1; + + if (m_DexReq == OldDexterityReq) + m_DexReq = -1; + + if (m_IntReq == OldIntelligenceReq) + m_IntReq = -1; + + if (m_MinDamage == OldMinDamage) + m_MinDamage = -1; + + if (m_MaxDamage == OldMaxDamage) + m_MaxDamage = -1; + + if (m_HitSound == OldHitSound) + m_HitSound = -1; + + if (m_MissSound == OldMissSound) + m_MissSound = -1; + + if (m_Speed == OldSpeed) + m_Speed = -1; + + if (m_MaxRange == OldMaxRange) + m_MaxRange = -1; + + if (m_Skill == OldSkill) + m_Skill = (SkillName)(-1); + + if (m_Type == OldType) + m_Type = (WeaponType)(-1); + + if (m_Animation == OldAnimation) + m_Animation = (WeaponAnimation)(-1); + + if (UseSkillMod && m_AccuracyLevel != WeaponAccuracyLevel.Regular && parentMobile != null) + { + m_SkillMod = new DefaultSkillMod(AccuracySkill, true, (int)m_AccuracyLevel * 5); + parentMobile.AddSkillMod(m_SkillMod); + } + + break; + } } - m_MinDamage = reader.ReadInt(); - m_MaxDamage = reader.ReadInt(); + if (Core.AOS && parentMobile != null) + SkillBonuses.AddTo(parentMobile); - m_Speed = reader.ReadInt(); + var strBonus = Attributes.BonusStr; + var dexBonus = Attributes.BonusDex; + var intBonus = Attributes.BonusInt; - m_HitSound = reader.ReadInt(); - m_MissSound = reader.ReadInt(); - - m_Skill = (SkillName)reader.ReadInt(); - m_Type = (WeaponType)reader.ReadInt(); - m_Animation = (WeaponAnimation)reader.ReadInt(); - m_DamageLevel = (WeaponDamageLevel)reader.ReadInt(); - m_AccuracyLevel = (WeaponAccuracyLevel)reader.ReadInt(); - m_DurabilityLevel = (WeaponDurabilityLevel)reader.ReadInt(); - m_Quality = (WeaponQuality)reader.ReadInt(); - - m_Crafter = reader.ReadMobile(); - - m_Poison = Poison.Deserialize(reader); - m_PoisonCharges = reader.ReadInt(); - - if (m_StrReq == OldStrengthReq) - m_StrReq = -1; - - if (m_DexReq == OldDexterityReq) - m_DexReq = -1; - - if (m_IntReq == OldIntelligenceReq) - m_IntReq = -1; - - if (m_MinDamage == OldMinDamage) - m_MinDamage = -1; - - if (m_MaxDamage == OldMaxDamage) - m_MaxDamage = -1; - - if (m_HitSound == OldHitSound) - m_HitSound = -1; - - if (m_MissSound == OldMissSound) - m_MissSound = -1; - - if (m_Speed == OldSpeed) - m_Speed = -1; - - if (m_MaxRange == OldMaxRange) - m_MaxRange = -1; - - if (m_Skill == OldSkill) - m_Skill = (SkillName)(-1); - - if (m_Type == OldType) - m_Type = (WeaponType)(-1); - - if (m_Animation == OldAnimation) - m_Animation = (WeaponAnimation)(-1); - - if (UseSkillMod && m_AccuracyLevel != WeaponAccuracyLevel.Regular && parentMobile != null) + if (parentMobile != null && (strBonus != 0 || dexBonus != 0 || intBonus != 0)) { - m_SkillMod = new DefaultSkillMod(AccuracySkill, true, (int)m_AccuracyLevel * 5); - parentMobile.AddSkillMod(m_SkillMod); + var modName = Serial.ToString(); + + if (strBonus != 0) + parentMobile.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero)); + + if (dexBonus != 0) + parentMobile.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero)); + + if (intBonus != 0) + parentMobile.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero)); } - break; - } - } + parentMobile?.CheckStatTimers(); - if (Core.AOS && parentMobile != null) - SkillBonuses.AddTo(parentMobile); + if (m_Hits <= 0 && m_MaxHits <= 0) m_Hits = m_MaxHits = Utility.RandomMinMax(InitMinHits, InitMaxHits); - int strBonus = Attributes.BonusStr; - int dexBonus = Attributes.BonusDex; - int intBonus = Attributes.BonusInt; + if (version < 6) + PlayerConstructed = true; // we don't know, so, assume it's crafted + } - if (parentMobile != null && (strBonus != 0 || dexBonus != 0 || intBonus != 0)) - { - string modName = Serial.ToString(); + private class ResetEquipTimer : Timer + { + private readonly Mobile m_Mobile; - if (strBonus != 0) - parentMobile.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero)); + public ResetEquipTimer(Mobile m, TimeSpan duration) : base(duration) => m_Mobile = m; - if (dexBonus != 0) - parentMobile.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero)); + protected override void OnTick() + { + m_Mobile.EndAction(); + } + } - if (intBonus != 0) - parentMobile.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero)); - } - - parentMobile?.CheckStatTimers(); - - if (m_Hits <= 0 && m_MaxHits <= 0) m_Hits = m_MaxHits = Utility.RandomMinMax(InitMinHits, InitMaxHits); - - if (version < 6) - PlayerConstructed = true; // we don't know, so, assume it's crafted + [Flags] + private enum SaveFlag + { + None = 0x00000000, + DamageLevel = 0x00000001, + AccuracyLevel = 0x00000002, + DurabilityLevel = 0x00000004, + Quality = 0x00000008, + Hits = 0x00000010, + MaxHits = 0x00000020, + Slayer = 0x00000040, + Poison = 0x00000080, + PoisonCharges = 0x00000100, + Crafter = 0x00000200, + Identified = 0x00000400, + StrReq = 0x00000800, + DexReq = 0x00001000, + IntReq = 0x00002000, + MinDamage = 0x00004000, + MaxDamage = 0x00008000, + HitSound = 0x00010000, + MissSound = 0x00020000, + Speed = 0x00040000, + MaxRange = 0x00080000, + Skill = 0x00100000, + Type = 0x00200000, + Animation = 0x00400000, + Resource = 0x00800000, + xAttributes = 0x01000000, + xWeaponAttributes = 0x02000000, + PlayerConstructed = 0x04000000, + SkillBonuses = 0x08000000, + Slayer2 = 0x10000000, + ElementalDamages = 0x20000000, + EngravedText = 0x40000000 + } } - } - public enum CheckSlayerResult - { - None, - Slayer, - Opposition - } + public enum CheckSlayerResult + { + None, + Slayer, + Opposition + } } diff --git a/Projects/UOContent/Items/Weapons/Fists.cs b/Projects/UOContent/Items/Weapons/Fists.cs index 0ffbf0abe..95130342c 100644 --- a/Projects/UOContent/Items/Weapons/Fists.cs +++ b/Projects/UOContent/Items/Weapons/Fists.cs @@ -3,299 +3,299 @@ using Server.Engines.ConPVP; namespace Server.Items { - public class Fists : BaseMeleeWeapon - { - public Fists() : base(0) + public class Fists : BaseMeleeWeapon { - Visible = false; - Movable = false; - Quality = WeaponQuality.Regular; - } - - public Fists(Serial serial) : base(serial) - { - } - - public override WeaponAbility PrimaryAbility => WeaponAbility.Disarm; - public override WeaponAbility SecondaryAbility => WeaponAbility.ParalyzingBlow; - - public override int AosStrengthReq => 0; - public override int AosMinDamage => 1; - public override int AosMaxDamage => 4; - public override int AosSpeed => 50; - public override float MlSpeed => 2.50f; - - public override int OldStrengthReq => 0; - public override int OldMinDamage => 1; - public override int OldMaxDamage => 8; - public override int OldSpeed => 30; - - public override int DefHitSound => -1; - public override int DefMissSound => -1; - - public override SkillName DefSkill => SkillName.Wrestling; - public override WeaponType DefType => WeaponType.Fists; - public override WeaponAnimation DefAnimation => WeaponAnimation.Wrestle; - - public static void Initialize() - { - Mobile.DefaultWeapon = new Fists(); - - EventSink.DisarmRequest += EventSink_DisarmRequest; - EventSink.StunRequest += EventSink_StunRequest; - } - - public override double GetDefendSkillValue(Mobile attacker, Mobile defender) - { - double wresValue = defender.Skills.Wrestling.Value; - double anatValue = defender.Skills.Anatomy.Value; - double evalValue = defender.Skills.EvalInt.Value; - double incrValue = (anatValue + evalValue + 20.0) * 0.5; - - if (incrValue > 120.0) - incrValue = 120.0; - - if (wresValue > incrValue) - return wresValue; - return incrValue; - } - - private void CheckPreAOSMoves(Mobile attacker, Mobile defender) - { - if (attacker.StunReady) - { - if (attacker.CanBeginAction()) + public Fists() : base(0) { - if (attacker.Skills.Anatomy.Value >= 80.0 && - attacker.Skills.Wrestling.Value >= 80.0) - { - if (attacker.Stam >= 15) + Visible = false; + Movable = false; + Quality = WeaponQuality.Regular; + } + + public Fists(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.Disarm; + public override WeaponAbility SecondaryAbility => WeaponAbility.ParalyzingBlow; + + public override int AosStrengthReq => 0; + public override int AosMinDamage => 1; + public override int AosMaxDamage => 4; + public override int AosSpeed => 50; + public override float MlSpeed => 2.50f; + + public override int OldStrengthReq => 0; + public override int OldMinDamage => 1; + public override int OldMaxDamage => 8; + public override int OldSpeed => 30; + + public override int DefHitSound => -1; + public override int DefMissSound => -1; + + public override SkillName DefSkill => SkillName.Wrestling; + public override WeaponType DefType => WeaponType.Fists; + public override WeaponAnimation DefAnimation => WeaponAnimation.Wrestle; + + public static void Initialize() + { + Mobile.DefaultWeapon = new Fists(); + + EventSink.DisarmRequest += EventSink_DisarmRequest; + EventSink.StunRequest += EventSink_StunRequest; + } + + public override double GetDefendSkillValue(Mobile attacker, Mobile defender) + { + var wresValue = defender.Skills.Wrestling.Value; + var anatValue = defender.Skills.Anatomy.Value; + var evalValue = defender.Skills.EvalInt.Value; + var incrValue = (anatValue + evalValue + 20.0) * 0.5; + + if (incrValue > 120.0) + incrValue = 120.0; + + if (wresValue > incrValue) + return wresValue; + return incrValue; + } + + private void CheckPreAOSMoves(Mobile attacker, Mobile defender) + { + if (attacker.StunReady) { - attacker.Stam -= 15; + if (attacker.CanBeginAction()) + { + if (attacker.Skills.Anatomy.Value >= 80.0 && + attacker.Skills.Wrestling.Value >= 80.0) + { + if (attacker.Stam >= 15) + { + attacker.Stam -= 15; - if (CheckMove(attacker, SkillName.Anatomy)) - { - StartMoveDelay(attacker); + if (CheckMove(attacker, SkillName.Anatomy)) + { + StartMoveDelay(attacker); - attacker.StunReady = false; + attacker.StunReady = false; - attacker.SendLocalizedMessage(1004013); // You successfully stun your opponent! - defender.SendLocalizedMessage(1004014); // You have been stunned! + attacker.SendLocalizedMessage(1004013); // You successfully stun your opponent! + defender.SendLocalizedMessage(1004014); // You have been stunned! - defender.Freeze(TimeSpan.FromSeconds(4.0)); - } - else - { - attacker.SendLocalizedMessage(1004010); // You failed in your attempt to stun. - defender.SendLocalizedMessage(1004011); // Your opponent tried to stun you and failed. - } + defender.Freeze(TimeSpan.FromSeconds(4.0)); + } + else + { + attacker.SendLocalizedMessage(1004010); // You failed in your attempt to stun. + defender.SendLocalizedMessage(1004011); // Your opponent tried to stun you and failed. + } + } + else + { + attacker.SendLocalizedMessage(1004009); // You are too fatigued to attempt anything. + } + } + else + { + attacker.SendLocalizedMessage(1004008); // You are not skilled enough to stun your opponent. + attacker.StunReady = false; + } + } + } + else if (attacker.DisarmReady) + { + if (attacker.CanBeginAction()) + { + if (defender.Player || defender.Body.IsHuman) + { + if (attacker.Skills.ArmsLore.Value >= 80.0 && + attacker.Skills.Wrestling.Value >= 80.0) + { + if (attacker.Stam >= 15) + { + var toDisarm = defender.FindItemOnLayer(Layer.OneHanded); + + if (toDisarm?.Movable == false) + toDisarm = defender.FindItemOnLayer(Layer.TwoHanded); + + var pack = defender.Backpack; + + if (pack == null || toDisarm?.Movable == false) + { + attacker.SendLocalizedMessage(1004001); // You cannot disarm your opponent. + } + else if (CheckMove(attacker, SkillName.ArmsLore)) + { + StartMoveDelay(attacker); + + attacker.Stam -= 15; + attacker.DisarmReady = false; + + attacker.SendLocalizedMessage(1004006); // You successfully disarm your opponent! + defender.SendLocalizedMessage(1004007); // You have been disarmed! + + pack.DropItem(toDisarm); + } + else + { + attacker.Stam -= 15; + + attacker.SendLocalizedMessage(1004004); // You failed in your attempt to disarm. + defender.SendLocalizedMessage(1004005); // Your opponent tried to disarm you but failed. + } + } + else + { + attacker.SendLocalizedMessage(1004003); // You are too fatigued to attempt anything. + } + } + else + { + attacker.SendLocalizedMessage(1004002); // You are not skilled enough to disarm your opponent. + attacker.DisarmReady = false; + } + } + else + { + attacker.SendLocalizedMessage(1004001); // You cannot disarm your opponent. + } + } + } + } + + public override TimeSpan OnSwing(Mobile attacker, Mobile defender) + { + if (!Core.AOS) + CheckPreAOSMoves(attacker, defender); + + return base.OnSwing(attacker, defender); + } + + /*public override void OnMiss( Mobile attacker, Mobile defender ) + { + base.PlaySwingAnimation( attacker ); + }*/ + + 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(); + + Delete(); + } + + /* Wrestling moves */ + + private static bool CheckMove(Mobile m, SkillName other) + { + var wresValue = m.Skills.Wrestling.Value; + var scndValue = m.Skills[other].Value; + + /* 40% chance at 80, 80 + * 50% chance at 100, 100 + * 60% chance at 120, 120 + */ + + var chance = (wresValue + scndValue) / 400.0; + + return chance >= Utility.RandomDouble(); + } + + private static bool HasFreeHands(Mobile m) + { + var item = m.FindItemOnLayer(Layer.OneHanded); + + return (item == null || item is Spellbook) && m.FindItemOnLayer(Layer.TwoHanded) == null; + } + + private static void EventSink_DisarmRequest(Mobile m) + { + if (Core.AOS) + return; + + if (!DuelContext.AllowSpecialAbility(m, "Disarm", true)) + return; + + var armsValue = m.Skills.ArmsLore.Value; + var wresValue = m.Skills.Wrestling.Value; + + if (!HasFreeHands(m)) + { + m.SendLocalizedMessage(1004029); // You must have your hands free to attempt to disarm your opponent. + m.DisarmReady = false; + } + else if (armsValue >= 80.0 && wresValue >= 80.0) + { + m.DisruptiveAction(); + m.DisarmReady = !m.DisarmReady; + m.SendLocalizedMessage(m.DisarmReady ? 1019013 : 1019014); } else { - attacker.SendLocalizedMessage(1004009); // You are too fatigued to attempt anything. + m.SendLocalizedMessage(1004002); // You are not skilled enough to disarm your opponent. + m.DisarmReady = false; } - } - else - { - attacker.SendLocalizedMessage(1004008); // You are not skilled enough to stun your opponent. - attacker.StunReady = false; - } } - } - else if (attacker.DisarmReady) - { - if (attacker.CanBeginAction()) + + private static void EventSink_StunRequest(Mobile m) { - if (defender.Player || defender.Body.IsHuman) - { - if (attacker.Skills.ArmsLore.Value >= 80.0 && - attacker.Skills.Wrestling.Value >= 80.0) + if (Core.AOS) + return; + + if (!DuelContext.AllowSpecialAbility(m, "Stun", true)) + return; + + var anatValue = m.Skills.Anatomy.Value; + var wresValue = m.Skills.Wrestling.Value; + + if (!HasFreeHands(m)) { - if (attacker.Stam >= 15) - { - Item toDisarm = defender.FindItemOnLayer(Layer.OneHanded); - - if (toDisarm?.Movable == false) - toDisarm = defender.FindItemOnLayer(Layer.TwoHanded); - - Container pack = defender.Backpack; - - if (pack == null || toDisarm?.Movable == false) - { - attacker.SendLocalizedMessage(1004001); // You cannot disarm your opponent. - } - else if (CheckMove(attacker, SkillName.ArmsLore)) - { - StartMoveDelay(attacker); - - attacker.Stam -= 15; - attacker.DisarmReady = false; - - attacker.SendLocalizedMessage(1004006); // You successfully disarm your opponent! - defender.SendLocalizedMessage(1004007); // You have been disarmed! - - pack.DropItem(toDisarm); - } - else - { - attacker.Stam -= 15; - - attacker.SendLocalizedMessage(1004004); // You failed in your attempt to disarm. - defender.SendLocalizedMessage(1004005); // Your opponent tried to disarm you but failed. - } - } - else - { - attacker.SendLocalizedMessage(1004003); // You are too fatigued to attempt anything. - } + m.SendLocalizedMessage(1004031); // You must have your hands free to attempt to stun your opponent. + m.StunReady = false; + } + else if (anatValue >= 80.0 && wresValue >= 80.0) + { + m.DisruptiveAction(); + m.StunReady = !m.StunReady; + m.SendLocalizedMessage(m.StunReady ? 1019011 : 1019012); } else { - attacker.SendLocalizedMessage(1004002); // You are not skilled enough to disarm your opponent. - attacker.DisarmReady = false; + m.SendLocalizedMessage(1004008); // You are not skilled enough to stun your opponent. + m.StunReady = false; + } + } + + private static void StartMoveDelay(Mobile m) + { + new MoveDelayTimer(m).Start(); + } + + private class MoveDelayTimer : Timer + { + private readonly Mobile m_Mobile; + + public MoveDelayTimer(Mobile m) : base(TimeSpan.FromSeconds(10.0)) + { + m_Mobile = m; + + Priority = TimerPriority.TwoFiftyMS; + + m_Mobile.BeginAction(); + } + + protected override void OnTick() + { + m_Mobile.EndAction(); } - } - else - { - attacker.SendLocalizedMessage(1004001); // You cannot disarm your opponent. - } } - } } - - public override TimeSpan OnSwing(Mobile attacker, Mobile defender) - { - if (!Core.AOS) - CheckPreAOSMoves(attacker, defender); - - return base.OnSwing(attacker, defender); - } - - /*public override void OnMiss( Mobile attacker, Mobile defender ) - { - base.PlaySwingAnimation( attacker ); - }*/ - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Delete(); - } - - /* Wrestling moves */ - - private static bool CheckMove(Mobile m, SkillName other) - { - double wresValue = m.Skills.Wrestling.Value; - double scndValue = m.Skills[other].Value; - - /* 40% chance at 80, 80 - * 50% chance at 100, 100 - * 60% chance at 120, 120 - */ - - double chance = (wresValue + scndValue) / 400.0; - - return chance >= Utility.RandomDouble(); - } - - private static bool HasFreeHands(Mobile m) - { - Item item = m.FindItemOnLayer(Layer.OneHanded); - - return (item == null || item is Spellbook) && m.FindItemOnLayer(Layer.TwoHanded) == null; - } - - private static void EventSink_DisarmRequest(Mobile m) - { - if (Core.AOS) - return; - - if (!DuelContext.AllowSpecialAbility(m, "Disarm", true)) - return; - - double armsValue = m.Skills.ArmsLore.Value; - double wresValue = m.Skills.Wrestling.Value; - - if (!HasFreeHands(m)) - { - m.SendLocalizedMessage(1004029); // You must have your hands free to attempt to disarm your opponent. - m.DisarmReady = false; - } - else if (armsValue >= 80.0 && wresValue >= 80.0) - { - m.DisruptiveAction(); - m.DisarmReady = !m.DisarmReady; - m.SendLocalizedMessage(m.DisarmReady ? 1019013 : 1019014); - } - else - { - m.SendLocalizedMessage(1004002); // You are not skilled enough to disarm your opponent. - m.DisarmReady = false; - } - } - - private static void EventSink_StunRequest(Mobile m) - { - if (Core.AOS) - return; - - if (!DuelContext.AllowSpecialAbility(m, "Stun", true)) - return; - - double anatValue = m.Skills.Anatomy.Value; - double wresValue = m.Skills.Wrestling.Value; - - if (!HasFreeHands(m)) - { - m.SendLocalizedMessage(1004031); // You must have your hands free to attempt to stun your opponent. - m.StunReady = false; - } - else if (anatValue >= 80.0 && wresValue >= 80.0) - { - m.DisruptiveAction(); - m.StunReady = !m.StunReady; - m.SendLocalizedMessage(m.StunReady ? 1019011 : 1019012); - } - else - { - m.SendLocalizedMessage(1004008); // You are not skilled enough to stun your opponent. - m.StunReady = false; - } - } - - private static void StartMoveDelay(Mobile m) - { - new MoveDelayTimer(m).Start(); - } - - private class MoveDelayTimer : Timer - { - private readonly Mobile m_Mobile; - - public MoveDelayTimer(Mobile m) : base(TimeSpan.FromSeconds(10.0)) - { - m_Mobile = m; - - Priority = TimerPriority.TwoFiftyMS; - - m_Mobile.BeginAction(); - } - - protected override void OnTick() - { - m_Mobile.EndAction(); - } - } - } } diff --git a/Projects/UOContent/Items/Weapons/HitLower.cs b/Projects/UOContent/Items/Weapons/HitLower.cs index b736fc364..c694b7b80 100644 --- a/Projects/UOContent/Items/Weapons/HitLower.cs +++ b/Projects/UOContent/Items/Weapons/HitLower.cs @@ -3,84 +3,84 @@ using System.Collections.Generic; namespace Server.Items { - public class HitLower - { - public static readonly TimeSpan AttackEffectDuration = TimeSpan.FromSeconds(10.0); - public static readonly TimeSpan DefenseEffectDuration = TimeSpan.FromSeconds(8.0); - - private static readonly HashSet m_AttackTable = new HashSet(); - private static readonly HashSet m_DefenseTable = new HashSet(); - - public static bool IsUnderAttackEffect(Mobile m) => m_AttackTable.Contains(m); - - public static bool ApplyAttack(Mobile m) + public class HitLower { - if (IsUnderAttackEffect(m)) - return false; + public static readonly TimeSpan AttackEffectDuration = TimeSpan.FromSeconds(10.0); + public static readonly TimeSpan DefenseEffectDuration = TimeSpan.FromSeconds(8.0); - m_AttackTable.Add(m); - AttackTimer timer = new AttackTimer(m); - timer.Start(); - m.SendLocalizedMessage(1062319); // Your attack chance has been reduced! - return true; + private static readonly HashSet m_AttackTable = new HashSet(); + private static readonly HashSet m_DefenseTable = new HashSet(); + + public static bool IsUnderAttackEffect(Mobile m) => m_AttackTable.Contains(m); + + public static bool ApplyAttack(Mobile m) + { + if (IsUnderAttackEffect(m)) + return false; + + m_AttackTable.Add(m); + var timer = new AttackTimer(m); + timer.Start(); + m.SendLocalizedMessage(1062319); // Your attack chance has been reduced! + return true; + } + + private static void RemoveAttack(Mobile m) + { + m_AttackTable.Remove(m); + m.SendLocalizedMessage(1062320); // Your attack chance has returned to normal. + } + + public static bool IsUnderDefenseEffect(Mobile m) => m_DefenseTable.Contains(m); + + public static bool ApplyDefense(Mobile m) + { + if (IsUnderDefenseEffect(m)) + return false; + + m_DefenseTable.Add(m); + var timer = new DefenseTimer(m); + timer.Start(); + m.SendLocalizedMessage(1062318); // Your defense chance has been reduced! + return true; + } + + private static void RemoveDefense(Mobile m) + { + m_DefenseTable.Remove(m); + m.SendLocalizedMessage(1062321); // Your defense chance has returned to normal. + } + + private class AttackTimer : Timer + { + private readonly Mobile m_Player; + + public AttackTimer(Mobile player) : base(AttackEffectDuration) + { + m_Player = player; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + RemoveAttack(m_Player); + } + } + + private class DefenseTimer : Timer + { + private readonly Mobile m_Player; + + public DefenseTimer(Mobile player) : base(DefenseEffectDuration) + { + m_Player = player; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + RemoveDefense(m_Player); + } + } } - - private static void RemoveAttack(Mobile m) - { - m_AttackTable.Remove(m); - m.SendLocalizedMessage(1062320); // Your attack chance has returned to normal. - } - - public static bool IsUnderDefenseEffect(Mobile m) => m_DefenseTable.Contains(m); - - public static bool ApplyDefense(Mobile m) - { - if (IsUnderDefenseEffect(m)) - return false; - - m_DefenseTable.Add(m); - DefenseTimer timer = new DefenseTimer(m); - timer.Start(); - m.SendLocalizedMessage(1062318); // Your defense chance has been reduced! - return true; - } - - private static void RemoveDefense(Mobile m) - { - m_DefenseTable.Remove(m); - m.SendLocalizedMessage(1062321); // Your defense chance has returned to normal. - } - - private class AttackTimer : Timer - { - private readonly Mobile m_Player; - - public AttackTimer(Mobile player) : base(AttackEffectDuration) - { - m_Player = player; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - RemoveAttack(m_Player); - } - } - - private class DefenseTimer : Timer - { - private readonly Mobile m_Player; - - public DefenseTimer(Mobile player) : base(DefenseEffectDuration) - { - m_Player = player; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - RemoveDefense(m_Player); - } - } - } } diff --git a/Projects/UOContent/Items/Weapons/Knives/BaseKnife.cs b/Projects/UOContent/Items/Weapons/Knives/BaseKnife.cs index 992641dcd..841c541f7 100644 --- a/Projects/UOContent/Items/Weapons/Knives/BaseKnife.cs +++ b/Projects/UOContent/Items/Weapons/Knives/BaseKnife.cs @@ -2,55 +2,55 @@ using Server.Targets; namespace Server.Items { - public abstract class BaseKnife : BaseMeleeWeapon - { - public BaseKnife(int itemID) : base(itemID) + public abstract class BaseKnife : BaseMeleeWeapon { + public BaseKnife(int itemID) : base(itemID) + { + } + + public BaseKnife(Serial serial) : base(serial) + { + } + + public override int DefHitSound => 0x23B; + public override int DefMissSound => 0x238; + + public override SkillName DefSkill => SkillName.Swords; + public override WeaponType DefType => WeaponType.Slashing; + public override WeaponAnimation DefAnimation => WeaponAnimation.Slash1H; + + 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(1010018); // What do you want to use this item on? + + from.Target = new BladedItemTarget(this); + } + + public override void OnHit(Mobile attacker, Mobile defender, double damageBonus = 1) + { + base.OnHit(attacker, defender, damageBonus); + + if (!Core.AOS && Poison != null && PoisonCharges > 0) + { + --PoisonCharges; + + if (Utility.RandomDouble() >= 0.5) // 50% chance to poison + defender.ApplyPoison(attacker, Poison); + } + } } - - public BaseKnife(Serial serial) : base(serial) - { - } - - public override int DefHitSound => 0x23B; - public override int DefMissSound => 0x238; - - public override SkillName DefSkill => SkillName.Swords; - public override WeaponType DefType => WeaponType.Slashing; - public override WeaponAnimation DefAnimation => WeaponAnimation.Slash1H; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - from.SendLocalizedMessage(1010018); // What do you want to use this item on? - - from.Target = new BladedItemTarget(this); - } - - public override void OnHit(Mobile attacker, Mobile defender, double damageBonus = 1) - { - base.OnHit(attacker, defender, damageBonus); - - if (!Core.AOS && Poison != null && PoisonCharges > 0) - { - --PoisonCharges; - - if (Utility.RandomDouble() >= 0.5) // 50% chance to poison - defender.ApplyPoison(attacker, Poison); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Knives/ButcherKnife.cs b/Projects/UOContent/Items/Weapons/Knives/ButcherKnife.cs index 3c4479830..dce2b6606 100644 --- a/Projects/UOContent/Items/Weapons/Knives/ButcherKnife.cs +++ b/Projects/UOContent/Items/Weapons/Knives/ButcherKnife.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0x13F6, 0x13F7)] - public class ButcherKnife : BaseKnife - { - [Constructible] - public ButcherKnife() : base(0x13F6) => Weight = 1.0; - - public ButcherKnife(Serial serial) : base(serial) + [Flippable(0x13F6, 0x13F7)] + public class ButcherKnife : BaseKnife { + [Constructible] + public ButcherKnife() : base(0x13F6) => Weight = 1.0; + + public ButcherKnife(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.InfectiousStrike; + public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm; + + public override int AosStrengthReq => 5; + public override int AosMinDamage => 9; + public override int AosMaxDamage => 11; + public override int AosSpeed => 49; + public override float MlSpeed => 2.25f; + + public override int OldStrengthReq => 5; + public override int OldMinDamage => 2; + public override int OldMaxDamage => 14; + public override int OldSpeed => 40; + + public override int InitMinHits => 31; + public override int InitMaxHits => 40; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.InfectiousStrike; - public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm; - - public override int AosStrengthReq => 5; - public override int AosMinDamage => 9; - public override int AosMaxDamage => 11; - public override int AosSpeed => 49; - public override float MlSpeed => 2.25f; - - public override int OldStrengthReq => 5; - public override int OldMinDamage => 2; - public override int OldMaxDamage => 14; - public override int OldSpeed => 40; - - public override int InitMinHits => 31; - public override int InitMaxHits => 40; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Knives/Cleaver.cs b/Projects/UOContent/Items/Weapons/Knives/Cleaver.cs index 4ff28f762..11422cd46 100644 --- a/Projects/UOContent/Items/Weapons/Knives/Cleaver.cs +++ b/Projects/UOContent/Items/Weapons/Knives/Cleaver.cs @@ -1,47 +1,47 @@ namespace Server.Items { - [Flippable(0xEC3, 0xEC2)] - public class Cleaver : BaseKnife - { - [Constructible] - public Cleaver() : base(0xEC3) => Weight = 2.0; - - public Cleaver(Serial serial) : base(serial) + [Flippable(0xEC3, 0xEC2)] + public class Cleaver : BaseKnife { + [Constructible] + public Cleaver() : base(0xEC3) => Weight = 2.0; + + public Cleaver(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.BleedAttack; + public override WeaponAbility SecondaryAbility => WeaponAbility.InfectiousStrike; + + public override int AosStrengthReq => 10; + public override int AosMinDamage => 11; + public override int AosMaxDamage => 13; + public override int AosSpeed => 46; + public override float MlSpeed => 2.50f; + + public override int OldStrengthReq => 10; + public override int OldMinDamage => 2; + public override int OldMaxDamage => 13; + public override int OldSpeed => 40; + + public override int InitMinHits => 31; + public override int InitMaxHits => 50; + + 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 (Weight == 1.0) + Weight = 2.0; + } } - - public override WeaponAbility PrimaryAbility => WeaponAbility.BleedAttack; - public override WeaponAbility SecondaryAbility => WeaponAbility.InfectiousStrike; - - public override int AosStrengthReq => 10; - public override int AosMinDamage => 11; - public override int AosMaxDamage => 13; - public override int AosSpeed => 46; - public override float MlSpeed => 2.50f; - - public override int OldStrengthReq => 10; - public override int OldMinDamage => 2; - public override int OldMaxDamage => 13; - public override int OldSpeed => 40; - - public override int InitMinHits => 31; - public override int InitMaxHits => 50; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 2.0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Knives/Dagger.cs b/Projects/UOContent/Items/Weapons/Knives/Dagger.cs index 6a28d0529..516f1a100 100644 --- a/Projects/UOContent/Items/Weapons/Knives/Dagger.cs +++ b/Projects/UOContent/Items/Weapons/Knives/Dagger.cs @@ -1,48 +1,48 @@ namespace Server.Items { - [Flippable(0xF52, 0xF51)] - public class Dagger : BaseKnife - { - [Constructible] - public Dagger() : base(0xF52) => Weight = 1.0; - - public Dagger(Serial serial) : base(serial) + [Flippable(0xF52, 0xF51)] + public class Dagger : BaseKnife { + [Constructible] + public Dagger() : base(0xF52) => Weight = 1.0; + + public Dagger(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.InfectiousStrike; + public override WeaponAbility SecondaryAbility => WeaponAbility.ShadowStrike; + + public override int AosStrengthReq => 10; + public override int AosMinDamage => 10; + public override int AosMaxDamage => 11; + public override int AosSpeed => 56; + public override float MlSpeed => 2.00f; + + public override int OldStrengthReq => 1; + public override int OldMinDamage => 3; + public override int OldMaxDamage => 15; + public override int OldSpeed => 55; + + public override int InitMinHits => 31; + public override int InitMaxHits => 40; + + public override SkillName DefSkill => SkillName.Fencing; + public override WeaponType DefType => WeaponType.Piercing; + public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.InfectiousStrike; - public override WeaponAbility SecondaryAbility => WeaponAbility.ShadowStrike; - - public override int AosStrengthReq => 10; - public override int AosMinDamage => 10; - public override int AosMaxDamage => 11; - public override int AosSpeed => 56; - public override float MlSpeed => 2.00f; - - public override int OldStrengthReq => 1; - public override int OldMinDamage => 3; - public override int OldMaxDamage => 15; - public override int OldSpeed => 55; - - public override int InitMinHits => 31; - public override int InitMaxHits => 40; - - public override SkillName DefSkill => SkillName.Fencing; - public override WeaponType DefType => WeaponType.Piercing; - public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Knives/SkinningKnife.cs b/Projects/UOContent/Items/Weapons/Knives/SkinningKnife.cs index 480ed1a62..905490df5 100644 --- a/Projects/UOContent/Items/Weapons/Knives/SkinningKnife.cs +++ b/Projects/UOContent/Items/Weapons/Knives/SkinningKnife.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0xEC4, 0xEC5)] - public class SkinningKnife : BaseKnife - { - [Constructible] - public SkinningKnife() : base(0xEC4) => Weight = 1.0; - - public SkinningKnife(Serial serial) : base(serial) + [Flippable(0xEC4, 0xEC5)] + public class SkinningKnife : BaseKnife { + [Constructible] + public SkinningKnife() : base(0xEC4) => Weight = 1.0; + + public SkinningKnife(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.ShadowStrike; + public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm; + + public override int AosStrengthReq => 5; + public override int AosMinDamage => 9; + public override int AosMaxDamage => 11; + public override int AosSpeed => 49; + public override float MlSpeed => 2.25f; + + public override int OldStrengthReq => 5; + public override int OldMinDamage => 1; + public override int OldMaxDamage => 10; + public override int OldSpeed => 40; + + public override int InitMinHits => 31; + public override int InitMaxHits => 40; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.ShadowStrike; - public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm; - - public override int AosStrengthReq => 5; - public override int AosMinDamage => 9; - public override int AosMaxDamage => 11; - public override int AosSpeed => 49; - public override float MlSpeed => 2.25f; - - public override int OldStrengthReq => 5; - public override int OldMinDamage => 1; - public override int OldMaxDamage => 10; - public override int OldSpeed => 40; - - public override int InitMinHits => 31; - public override int InitMaxHits => 40; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Knives/ThrowingDagger.cs b/Projects/UOContent/Items/Weapons/Knives/ThrowingDagger.cs index cb69d6a1e..e667c6a89 100644 --- a/Projects/UOContent/Items/Weapons/Knives/ThrowingDagger.cs +++ b/Projects/UOContent/Items/Weapons/Knives/ThrowingDagger.cs @@ -3,128 +3,128 @@ using Server.Targeting; namespace Server.Items { - [Flippable(0xF52, 0xF51)] - public class ThrowingDagger : Item - { - [Constructible] - public ThrowingDagger() : base(0xF52) + [Flippable(0xF52, 0xF51)] + public class ThrowingDagger : Item { - Weight = 1.0; - Layer = Layer.OneHanded; - } + [Constructible] + public ThrowingDagger() : base(0xF52) + { + Weight = 1.0; + Layer = Layer.OneHanded; + } - public ThrowingDagger(Serial serial) : base(serial) - { - } + public ThrowingDagger(Serial serial) : base(serial) + { + } - public override string DefaultName => "a throwing dagger"; + public override string DefaultName => "a throwing dagger"; - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); - } + var version = reader.ReadInt(); + } - public override void OnDoubleClick(Mobile from) - { - if (from.Items.Contains(this)) - { - InternalTarget t = new InternalTarget(this); - from.Target = t; - } - else - { - from.SendMessage("You must be holding that weapon to use it."); - } - } - - private class InternalTarget : Target - { - private readonly ThrowingDagger m_Dagger; - - public InternalTarget(ThrowingDagger dagger) : base(10, false, TargetFlags.Harmful) => m_Dagger = dagger; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Dagger.Deleted) return; - - if (!from.Items.Contains(m_Dagger)) - from.SendMessage("You must be holding that weapon to use it."); - else if (targeted is Mobile m) - if (m != from && from.HarmfulCheck(m)) - { - Direction to = from.GetDirectionTo(m); - - from.Direction = to; - - from.Animate(from.Mounted ? 26 : 9, 7, 1, true, false, 0); - - if (Utility.RandomDouble() >= Math.Sqrt(m.Dex / 100.0) * 0.8) + public override void OnDoubleClick(Mobile from) + { + if (from.Items.Contains(this)) { - from.MovingEffect(m, 0x1BFE, 7, 1, false, false, 0x481, 0); - - AOS.Damage(m, from, Utility.Random(5, from.Str / 10), 100, 0, 0, 0, 0); - - m_Dagger.MoveToWorld(m.Location, m.Map); + var t = new InternalTarget(this); + from.Target = t; } else { - int x = 0, y = 0; - - switch (to & Direction.Mask) - { - case Direction.North: - --y; - break; - case Direction.South: - ++y; - break; - case Direction.West: - --x; - break; - case Direction.East: - ++x; - break; - case Direction.Up: - --x; - --y; - break; - case Direction.Down: - ++x; - ++y; - break; - case Direction.Left: - --x; - ++y; - break; - case Direction.Right: - ++x; - --y; - break; - } - - x += Utility.Random(-1, 3); - y += Utility.Random(-1, 3); - - x += m.X; - y += m.Y; - - m_Dagger.MoveToWorld(new Point3D(x, y, m.Z), m.Map); - - from.MovingEffect(m_Dagger, 0x1BFE, 7, 1, false, false, 0x481, 0); - - from.SendMessage("You miss."); + from.SendMessage("You must be holding that weapon to use it."); } - } - } + } + + private class InternalTarget : Target + { + private readonly ThrowingDagger m_Dagger; + + public InternalTarget(ThrowingDagger dagger) : base(10, false, TargetFlags.Harmful) => m_Dagger = dagger; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Dagger.Deleted) return; + + if (!from.Items.Contains(m_Dagger)) + from.SendMessage("You must be holding that weapon to use it."); + else if (targeted is Mobile m) + if (m != from && from.HarmfulCheck(m)) + { + var to = from.GetDirectionTo(m); + + from.Direction = to; + + from.Animate(from.Mounted ? 26 : 9, 7, 1, true, false, 0); + + if (Utility.RandomDouble() >= Math.Sqrt(m.Dex / 100.0) * 0.8) + { + from.MovingEffect(m, 0x1BFE, 7, 1, false, false, 0x481, 0); + + AOS.Damage(m, from, Utility.Random(5, from.Str / 10), 100, 0, 0, 0, 0); + + m_Dagger.MoveToWorld(m.Location, m.Map); + } + else + { + int x = 0, y = 0; + + switch (to & Direction.Mask) + { + case Direction.North: + --y; + break; + case Direction.South: + ++y; + break; + case Direction.West: + --x; + break; + case Direction.East: + ++x; + break; + case Direction.Up: + --x; + --y; + break; + case Direction.Down: + ++x; + ++y; + break; + case Direction.Left: + --x; + ++y; + break; + case Direction.Right: + ++x; + --y; + break; + } + + x += Utility.Random(-1, 3); + y += Utility.Random(-1, 3); + + x += m.X; + y += m.Y; + + m_Dagger.MoveToWorld(new Point3D(x, y, m.Z), m.Map); + + from.MovingEffect(m_Dagger, 0x1BFE, 7, 1, false, false, 0x481, 0); + + from.SendMessage("You miss."); + } + } + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/BlightGrippedLongbow.cs b/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/BlightGrippedLongbow.cs index 79cb67e38..ce2d8dc06 100644 --- a/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/BlightGrippedLongbow.cs +++ b/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/BlightGrippedLongbow.cs @@ -1,37 +1,37 @@ namespace Server.Items { - public class BlightGrippedLongbow : ElvenCompositeLongbow - { - [Constructible] - public BlightGrippedLongbow() + public class BlightGrippedLongbow : ElvenCompositeLongbow { - Hue = 0x8A4; + [Constructible] + public BlightGrippedLongbow() + { + Hue = 0x8A4; - WeaponAttributes.HitPoisonArea = 20; - Attributes.RegenStam = 3; - Attributes.NightSight = 1; - Attributes.WeaponSpeed = 20; - Attributes.WeaponDamage = 35; + WeaponAttributes.HitPoisonArea = 20; + Attributes.RegenStam = 3; + Attributes.NightSight = 1; + Attributes.WeaponSpeed = 20; + Attributes.WeaponDamage = 35; + } + + public BlightGrippedLongbow(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072907; // Blight Gripped Longbow + + 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(); + } } - - public BlightGrippedLongbow(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072907; // Blight Gripped Longbow - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/ColdForgedBlade.cs b/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/ColdForgedBlade.cs index 7bfec8939..88e446080 100644 --- a/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/ColdForgedBlade.cs +++ b/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/ColdForgedBlade.cs @@ -1,44 +1,46 @@ namespace Server.Items { - public class ColdForgedBlade : ElvenSpellblade - { - [Constructible] - public ColdForgedBlade() + public class ColdForgedBlade : ElvenSpellblade { - WeaponAttributes.HitHarm = 40; - Attributes.SpellChanneling = 1; - Attributes.NightSight = 1; - Attributes.WeaponSpeed = 25; - Attributes.WeaponDamage = 50; + [Constructible] + public ColdForgedBlade() + { + WeaponAttributes.HitHarm = 40; + Attributes.SpellChanneling = 1; + Attributes.NightSight = 1; + Attributes.WeaponSpeed = 25; + Attributes.WeaponDamage = 50; - Hue = GetElementalDamageHue(); + Hue = GetElementalDamageHue(); + } + + public ColdForgedBlade(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072916; // Cold Forged Blade + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + phys = fire = pois = nrgy = chaos = direct = 0; + cold = 100; + } + + 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(); + } } - - public ColdForgedBlade(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072916; // Cold Forged Blade - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - phys = fire = pois = nrgy = chaos = direct = 0; - cold = 100; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/LuminousRuneBlade.cs b/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/LuminousRuneBlade.cs index 0e737d89a..f84378657 100644 --- a/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/LuminousRuneBlade.cs +++ b/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/LuminousRuneBlade.cs @@ -1,44 +1,46 @@ namespace Server.Items { - public class LuminousRuneBlade : RuneBlade - { - [Constructible] - public LuminousRuneBlade() + public class LuminousRuneBlade : RuneBlade { - WeaponAttributes.HitLightning = 40; - WeaponAttributes.SelfRepair = 5; - Attributes.NightSight = 1; - Attributes.WeaponSpeed = 25; - Attributes.WeaponDamage = 55; + [Constructible] + public LuminousRuneBlade() + { + WeaponAttributes.HitLightning = 40; + WeaponAttributes.SelfRepair = 5; + Attributes.NightSight = 1; + Attributes.WeaponSpeed = 25; + Attributes.WeaponDamage = 55; - Hue = GetElementalDamageHue(); + Hue = GetElementalDamageHue(); + } + + public LuminousRuneBlade(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072922; // Luminous Rune Blade + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + phys = fire = cold = pois = chaos = direct = 0; + nrgy = 100; + } + + 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(); + } } - - public LuminousRuneBlade(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072922; // Luminous Rune Blade - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - phys = fire = cold = pois = chaos = direct = 0; - nrgy = 100; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/OverseerSunderedBlade.cs b/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/OverseerSunderedBlade.cs index 0780ec1d8..45b144e8c 100644 --- a/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/OverseerSunderedBlade.cs +++ b/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/OverseerSunderedBlade.cs @@ -1,46 +1,48 @@ namespace Server.Items { - public class OverseerSunderedBlade : RadiantScimitar - { - [Constructible] - public OverseerSunderedBlade() + public class OverseerSunderedBlade : RadiantScimitar { - ItemID = 0x2D27; - Hue = 0x485; + [Constructible] + public OverseerSunderedBlade() + { + ItemID = 0x2D27; + Hue = 0x485; - Attributes.RegenStam = 2; - Attributes.AttackChance = 10; - Attributes.WeaponSpeed = 35; - Attributes.WeaponDamage = 45; + Attributes.RegenStam = 2; + Attributes.AttackChance = 10; + Attributes.WeaponSpeed = 35; + Attributes.WeaponDamage = 45; - Hue = GetElementalDamageHue(); + Hue = GetElementalDamageHue(); + } + + public OverseerSunderedBlade(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072920; // Overseer Sundered Blade + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + phys = cold = pois = nrgy = chaos = direct = 0; + fire = 100; + } + + 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(); + } } - - public OverseerSunderedBlade(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072920; // Overseer Sundered Blade - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - phys = cold = pois = nrgy = chaos = direct = 0; - fire = 100; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/PhantomStaff.cs b/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/PhantomStaff.cs index d52685b33..908811df2 100644 --- a/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/PhantomStaff.cs +++ b/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/PhantomStaff.cs @@ -1,42 +1,44 @@ namespace Server.Items { - public class PhantomStaff : WildStaff - { - [Constructible] - public PhantomStaff() + public class PhantomStaff : WildStaff { - Hue = 0x1; - Attributes.RegenHits = 2; - Attributes.NightSight = 1; - Attributes.WeaponSpeed = 20; - Attributes.WeaponDamage = 60; + [Constructible] + public PhantomStaff() + { + Hue = 0x1; + Attributes.RegenHits = 2; + Attributes.NightSight = 1; + Attributes.WeaponSpeed = 20; + Attributes.WeaponDamage = 60; + } + + public PhantomStaff(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072919; // Phantom Staff + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + phys = fire = nrgy = chaos = direct = 0; + cold = pois = 50; + } + + 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(); + } } - - public PhantomStaff(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072919; // Phantom Staff - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - phys = fire = nrgy = chaos = direct = 0; - cold = pois = 50; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/RuneCarvingKnife.cs b/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/RuneCarvingKnife.cs index 67e970b6e..50c18aa23 100644 --- a/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/RuneCarvingKnife.cs +++ b/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/RuneCarvingKnife.cs @@ -1,37 +1,37 @@ namespace Server.Items { - public class RuneCarvingKnife : AssassinSpike - { - [Constructible] - public RuneCarvingKnife() + public class RuneCarvingKnife : AssassinSpike { - Hue = 0x48D; + [Constructible] + public RuneCarvingKnife() + { + Hue = 0x48D; - WeaponAttributes.HitLeechMana = 40; - Attributes.RegenStam = 2; - Attributes.LowerManaCost = 10; - Attributes.WeaponSpeed = 35; - Attributes.WeaponDamage = 30; + WeaponAttributes.HitLeechMana = 40; + Attributes.RegenStam = 2; + Attributes.LowerManaCost = 10; + Attributes.WeaponSpeed = 35; + Attributes.WeaponDamage = 30; + } + + public RuneCarvingKnife(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072915; // Rune Carving Knife + + 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(); + } } - - public RuneCarvingKnife(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072915; // Rune Carving Knife - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/ShardTrasher.cs b/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/ShardTrasher.cs index 728d494a6..ca5d86aa3 100644 --- a/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/ShardTrasher.cs +++ b/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/ShardTrasher.cs @@ -1,37 +1,37 @@ namespace Server.Items { - public class ShardThrasher : DiamondMace - { - [Constructible] - public ShardThrasher() + public class ShardThrasher : DiamondMace { - Hue = 0x4F2; + [Constructible] + public ShardThrasher() + { + Hue = 0x4F2; - WeaponAttributes.HitPhysicalArea = 30; - Attributes.BonusStam = 8; - Attributes.AttackChance = 10; - Attributes.WeaponSpeed = 35; - Attributes.WeaponDamage = 40; + WeaponAttributes.HitPhysicalArea = 30; + Attributes.BonusStam = 8; + Attributes.AttackChance = 10; + Attributes.WeaponSpeed = 35; + Attributes.WeaponDamage = 40; + } + + public ShardThrasher(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072918; // Shard Thrasher + + 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(); + } } - - public ShardThrasher(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072918; // Shard Thrasher - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/SilvanisFeywoodBow.cs b/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/SilvanisFeywoodBow.cs index ec64fccf5..26bafa967 100644 --- a/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/SilvanisFeywoodBow.cs +++ b/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/SilvanisFeywoodBow.cs @@ -1,43 +1,45 @@ namespace Server.Items { - public class SilvanisFeywoodBow : ElvenCompositeLongbow - { - [Constructible] - public SilvanisFeywoodBow() + public class SilvanisFeywoodBow : ElvenCompositeLongbow { - Hue = 0x1A; + [Constructible] + public SilvanisFeywoodBow() + { + Hue = 0x1A; - Attributes.SpellChanneling = 1; - Attributes.AttackChance = 12; - Attributes.WeaponSpeed = 30; - Attributes.WeaponDamage = 35; + Attributes.SpellChanneling = 1; + Attributes.AttackChance = 12; + Attributes.WeaponSpeed = 30; + Attributes.WeaponDamage = 35; + } + + public SilvanisFeywoodBow(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072955; // Silvani's Feywood Bow + + public override void GetDamageTypes( + Mobile wielder, out int phys, out int fire, out int cold, out int pois, + out int nrgy, out int chaos, out int direct + ) + { + phys = fire = cold = pois = chaos = direct = 0; + nrgy = 100; + } + + 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(); + } } - - public SilvanisFeywoodBow(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072955; // Silvani's Feywood Bow - - public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois, - out int nrgy, out int chaos, out int direct) - { - phys = fire = cold = pois = chaos = direct = 0; - nrgy = 100; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/TheNightReaper.cs b/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/TheNightReaper.cs index ad3654fc9..c397a4b4d 100644 --- a/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/TheNightReaper.cs +++ b/Projects/UOContent/Items/Weapons/ML Weapons/Artifacts/TheNightReaper.cs @@ -1,37 +1,37 @@ namespace Server.Items { - public class TheNightReaper : RepeatingCrossbow - { - [Constructible] - public TheNightReaper() + public class TheNightReaper : RepeatingCrossbow { - ItemID = 0x26CD; - Hue = 0x41C; + [Constructible] + public TheNightReaper() + { + ItemID = 0x26CD; + Hue = 0x41C; - Slayer = SlayerName.Exorcism; - Attributes.NightSight = 1; - Attributes.WeaponSpeed = 25; - Attributes.WeaponDamage = 55; + Slayer = SlayerName.Exorcism; + Attributes.NightSight = 1; + Attributes.WeaponSpeed = 25; + Attributes.WeaponDamage = 55; + } + + public TheNightReaper(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1072912; // The Night Reaper + + 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 TheNightReaper(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1072912; // The Night Reaper - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/ML Weapons/AssassinSpike.cs b/Projects/UOContent/Items/Weapons/ML Weapons/AssassinSpike.cs index 271e49544..507a50443 100644 --- a/Projects/UOContent/Items/Weapons/ML Weapons/AssassinSpike.cs +++ b/Projects/UOContent/Items/Weapons/ML Weapons/AssassinSpike.cs @@ -1,47 +1,47 @@ namespace Server.Items { - [Flippable(0x2D21, 0x2D2D)] - public class AssassinSpike : BaseKnife - { - [Constructible] - public AssassinSpike() : base(0x2D21) => Weight = 4.0; - - public AssassinSpike(Serial serial) : base(serial) + [Flippable(0x2D21, 0x2D2D)] + public class AssassinSpike : BaseKnife { + [Constructible] + public AssassinSpike() : base(0x2D21) => Weight = 4.0; + + public AssassinSpike(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.InfectiousStrike; + public override WeaponAbility SecondaryAbility => WeaponAbility.ShadowStrike; + + public override int AosStrengthReq => 15; + public override int AosMinDamage => 10; + public override int AosMaxDamage => 12; + public override int AosSpeed => 50; + public override float MlSpeed => 2.00f; + + public override int OldStrengthReq => 15; + public override int OldMinDamage => 10; + public override int OldMaxDamage => 12; + public override int OldSpeed => 50; + + public override int DefMissSound => 0x239; + public override SkillName DefSkill => SkillName.Fencing; + + public override int InitMinHits => 30; // TODO + public override int InitMaxHits => 60; // TODO + + 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(); + } } - - public override WeaponAbility PrimaryAbility => WeaponAbility.InfectiousStrike; - public override WeaponAbility SecondaryAbility => WeaponAbility.ShadowStrike; - - public override int AosStrengthReq => 15; - public override int AosMinDamage => 10; - public override int AosMaxDamage => 12; - public override int AosSpeed => 50; - public override float MlSpeed => 2.00f; - - public override int OldStrengthReq => 15; - public override int OldMinDamage => 10; - public override int OldMaxDamage => 12; - public override int OldSpeed => 50; - - public override int DefMissSound => 0x239; - public override SkillName DefSkill => SkillName.Fencing; - - public override int InitMinHits => 30; // TODO - public override int InitMaxHits => 60; // TODO - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/ML Weapons/ButchersWarCleaver.cs b/Projects/UOContent/Items/Weapons/ML Weapons/ButchersWarCleaver.cs index bacbfe04d..f360a4da4 100644 --- a/Projects/UOContent/Items/Weapons/ML Weapons/ButchersWarCleaver.cs +++ b/Projects/UOContent/Items/Weapons/ML Weapons/ButchersWarCleaver.cs @@ -1,37 +1,37 @@ namespace Server.Items { - public class ButchersWarCleaver : WarCleaver - { - [Constructible] - public ButchersWarCleaver() + public class ButchersWarCleaver : WarCleaver { + [Constructible] + public ButchersWarCleaver() + { + } + + public ButchersWarCleaver(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073526; // butcher's war cleaver + + public override void AppendChildNameProperties(ObjectPropertyList list) + { + base.AppendChildNameProperties(list); + + list.Add(1072512); // Bovine Slayer + } + + 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(); + } } - - public ButchersWarCleaver(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073526; // butcher's war cleaver - - public override void AppendChildNameProperties(ObjectPropertyList list) - { - base.AppendChildNameProperties(list); - - list.Add(1072512); // Bovine Slayer - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/ML Weapons/DiamondMace.cs b/Projects/UOContent/Items/Weapons/ML Weapons/DiamondMace.cs index 4df2440aa..bd10bfdff 100644 --- a/Projects/UOContent/Items/Weapons/ML Weapons/DiamondMace.cs +++ b/Projects/UOContent/Items/Weapons/ML Weapons/DiamondMace.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0x2D24, 0x2D30)] - public class DiamondMace : BaseBashing - { - [Constructible] - public DiamondMace() : base(0x2D24) => Weight = 10.0; - - public DiamondMace(Serial serial) : base(serial) + [Flippable(0x2D24, 0x2D30)] + public class DiamondMace : BaseBashing { + [Constructible] + public DiamondMace() : base(0x2D24) => Weight = 10.0; + + public DiamondMace(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.ConcussionBlow; + public override WeaponAbility SecondaryAbility => WeaponAbility.CrushingBlow; + + public override int AosStrengthReq => 35; + public override int AosMinDamage => 14; + public override int AosMaxDamage => 17; + public override int AosSpeed => 37; + public override float MlSpeed => 3.00f; + + public override int OldStrengthReq => 35; + public override int OldMinDamage => 14; + public override int OldMaxDamage => 17; + public override int OldSpeed => 37; + + public override int InitMinHits => 30; // TODO + public override int InitMaxHits => 60; // TODO + + 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(); + } } - - public override WeaponAbility PrimaryAbility => WeaponAbility.ConcussionBlow; - public override WeaponAbility SecondaryAbility => WeaponAbility.CrushingBlow; - - public override int AosStrengthReq => 35; - public override int AosMinDamage => 14; - public override int AosMaxDamage => 17; - public override int AosSpeed => 37; - public override float MlSpeed => 3.00f; - - public override int OldStrengthReq => 35; - public override int OldMinDamage => 14; - public override int OldMaxDamage => 17; - public override int OldSpeed => 37; - - public override int InitMinHits => 30; // TODO - public override int InitMaxHits => 60; // TODO - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/ML Weapons/ElvenCompositeLongbow.cs b/Projects/UOContent/Items/Weapons/ML Weapons/ElvenCompositeLongbow.cs index c5c438159..2a1dfc87d 100644 --- a/Projects/UOContent/Items/Weapons/ML Weapons/ElvenCompositeLongbow.cs +++ b/Projects/UOContent/Items/Weapons/ML Weapons/ElvenCompositeLongbow.cs @@ -2,53 +2,53 @@ using System; namespace Server.Items { - [Flippable(0x2D1E, 0x2D2A)] - public class ElvenCompositeLongbow : BaseRanged - { - [Constructible] - public ElvenCompositeLongbow() : base(0x2D1E) => Weight = 8.0; - - public ElvenCompositeLongbow(Serial serial) : base(serial) + [Flippable(0x2D1E, 0x2D2A)] + public class ElvenCompositeLongbow : BaseRanged { + [Constructible] + public ElvenCompositeLongbow() : base(0x2D1E) => Weight = 8.0; + + public ElvenCompositeLongbow(Serial serial) : base(serial) + { + } + + public override int EffectID => 0xF42; + public override Type AmmoType => typeof(Arrow); + public override Item Ammo => new Arrow(); + + public override WeaponAbility PrimaryAbility => WeaponAbility.ForceArrow; + public override WeaponAbility SecondaryAbility => WeaponAbility.SerpentArrow; + + public override int AosStrengthReq => 45; + public override int AosMinDamage => 12; + public override int AosMaxDamage => 16; + public override int AosSpeed => 27; + public override float MlSpeed => 4.00f; + + public override int OldStrengthReq => 45; + public override int OldMinDamage => 12; + public override int OldMaxDamage => 16; + public override int OldSpeed => 27; + + public override int DefMaxRange => 10; + + public override int InitMinHits => 41; + public override int InitMaxHits => 90; + + public override WeaponAnimation DefAnimation => WeaponAnimation.ShootBow; + + 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(); + } } - - public override int EffectID => 0xF42; - public override Type AmmoType => typeof(Arrow); - public override Item Ammo => new Arrow(); - - public override WeaponAbility PrimaryAbility => WeaponAbility.ForceArrow; - public override WeaponAbility SecondaryAbility => WeaponAbility.SerpentArrow; - - public override int AosStrengthReq => 45; - public override int AosMinDamage => 12; - public override int AosMaxDamage => 16; - public override int AosSpeed => 27; - public override float MlSpeed => 4.00f; - - public override int OldStrengthReq => 45; - public override int OldMinDamage => 12; - public override int OldMaxDamage => 16; - public override int OldSpeed => 27; - - public override int DefMaxRange => 10; - - public override int InitMinHits => 41; - public override int InitMaxHits => 90; - - public override WeaponAnimation DefAnimation => WeaponAnimation.ShootBow; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/ML Weapons/ElvenMachete.cs b/Projects/UOContent/Items/Weapons/ML Weapons/ElvenMachete.cs index 416235c43..57dba594f 100644 --- a/Projects/UOContent/Items/Weapons/ML Weapons/ElvenMachete.cs +++ b/Projects/UOContent/Items/Weapons/ML Weapons/ElvenMachete.cs @@ -1,47 +1,47 @@ namespace Server.Items { - [Flippable(0x2D35, 0x2D29)] - public class ElvenMachete : BaseSword - { - [Constructible] - public ElvenMachete() : base(0x2D35) => Weight = 6.0; - - public ElvenMachete(Serial serial) : base(serial) + [Flippable(0x2D35, 0x2D29)] + public class ElvenMachete : BaseSword { + [Constructible] + public ElvenMachete() : base(0x2D35) => Weight = 6.0; + + public ElvenMachete(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.DefenseMastery; + public override WeaponAbility SecondaryAbility => WeaponAbility.Bladeweave; + + public override int AosStrengthReq => 20; + public override int AosMinDamage => 13; + public override int AosMaxDamage => 15; + public override int AosSpeed => 41; + public override float MlSpeed => 2.75f; + + public override int OldStrengthReq => 20; + public override int OldMinDamage => 13; + public override int OldMaxDamage => 15; + public override int OldSpeed => 41; + + public override int DefHitSound => 0x23B; + public override int DefMissSound => 0x239; + + public override int InitMinHits => 30; + public override int InitMaxHits => 60; + + 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(); + } } - - public override WeaponAbility PrimaryAbility => WeaponAbility.DefenseMastery; - public override WeaponAbility SecondaryAbility => WeaponAbility.Bladeweave; - - public override int AosStrengthReq => 20; - public override int AosMinDamage => 13; - public override int AosMaxDamage => 15; - public override int AosSpeed => 41; - public override float MlSpeed => 2.75f; - - public override int OldStrengthReq => 20; - public override int OldMinDamage => 13; - public override int OldMaxDamage => 15; - public override int OldSpeed => 41; - - public override int DefHitSound => 0x23B; - public override int DefMissSound => 0x239; - - public override int InitMinHits => 30; - public override int InitMaxHits => 60; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/ML Weapons/ElvenSpellblade.cs b/Projects/UOContent/Items/Weapons/ML Weapons/ElvenSpellblade.cs index 3a83c87d4..6eb758385 100644 --- a/Projects/UOContent/Items/Weapons/ML Weapons/ElvenSpellblade.cs +++ b/Projects/UOContent/Items/Weapons/ML Weapons/ElvenSpellblade.cs @@ -1,50 +1,50 @@ namespace Server.Items { - [Flippable(0x2D20, 0x2D2C)] - public class ElvenSpellblade : BaseKnife - { - [Constructible] - public ElvenSpellblade() : base(0x2D20) + [Flippable(0x2D20, 0x2D2C)] + public class ElvenSpellblade : BaseKnife { - Weight = 5.0; - Layer = Layer.TwoHanded; + [Constructible] + public ElvenSpellblade() : base(0x2D20) + { + Weight = 5.0; + Layer = Layer.TwoHanded; + } + + public ElvenSpellblade(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.PsychicAttack; + public override WeaponAbility SecondaryAbility => WeaponAbility.BleedAttack; + + public override int AosStrengthReq => 35; + public override int AosMinDamage => 12; + public override int AosMaxDamage => 14; + public override int AosSpeed => 44; + public override float MlSpeed => 2.50f; + + public override int OldStrengthReq => 35; + public override int OldMinDamage => 12; + public override int OldMaxDamage => 14; + public override int OldSpeed => 44; + + public override int DefMissSound => 0x239; + + public override int InitMinHits => 30; // TODO + public override int InitMaxHits => 60; // TODO + + 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(); + } } - - public ElvenSpellblade(Serial serial) : base(serial) - { - } - - public override WeaponAbility PrimaryAbility => WeaponAbility.PsychicAttack; - public override WeaponAbility SecondaryAbility => WeaponAbility.BleedAttack; - - public override int AosStrengthReq => 35; - public override int AosMinDamage => 12; - public override int AosMaxDamage => 14; - public override int AosSpeed => 44; - public override float MlSpeed => 2.50f; - - public override int OldStrengthReq => 35; - public override int OldMinDamage => 12; - public override int OldMaxDamage => 14; - public override int OldSpeed => 44; - - public override int DefMissSound => 0x239; - - public override int InitMinHits => 30; // TODO - public override int InitMaxHits => 60; // TODO - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/ML Weapons/Leafblade.cs b/Projects/UOContent/Items/Weapons/ML Weapons/Leafblade.cs index beae85808..08c49dee4 100644 --- a/Projects/UOContent/Items/Weapons/ML Weapons/Leafblade.cs +++ b/Projects/UOContent/Items/Weapons/ML Weapons/Leafblade.cs @@ -1,47 +1,47 @@ namespace Server.Items { - [Flippable(0x2D22, 0x2D2E)] - public class Leafblade : BaseKnife - { - [Constructible] - public Leafblade() : base(0x2D22) => Weight = 8.0; - - public Leafblade(Serial serial) : base(serial) + [Flippable(0x2D22, 0x2D2E)] + public class Leafblade : BaseKnife { + [Constructible] + public Leafblade() : base(0x2D22) => Weight = 8.0; + + public Leafblade(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.Feint; + public override WeaponAbility SecondaryAbility => WeaponAbility.ArmorIgnore; + + public override int AosStrengthReq => 20; + public override int AosMinDamage => 13; + public override int AosMaxDamage => 15; + public override int AosSpeed => 42; + public override float MlSpeed => 2.75f; + + public override int OldStrengthReq => 20; + public override int OldMinDamage => 13; + public override int OldMaxDamage => 15; + public override int OldSpeed => 42; + + public override int DefMissSound => 0x239; + public override SkillName DefSkill => SkillName.Fencing; + + public override int InitMinHits => 30; // TODO + public override int InitMaxHits => 60; // TODO + + 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(); + } } - - public override WeaponAbility PrimaryAbility => WeaponAbility.Feint; - public override WeaponAbility SecondaryAbility => WeaponAbility.ArmorIgnore; - - public override int AosStrengthReq => 20; - public override int AosMinDamage => 13; - public override int AosMaxDamage => 15; - public override int AosSpeed => 42; - public override float MlSpeed => 2.75f; - - public override int OldStrengthReq => 20; - public override int OldMinDamage => 13; - public override int OldMaxDamage => 15; - public override int OldSpeed => 42; - - public override int DefMissSound => 0x239; - public override SkillName DefSkill => SkillName.Fencing; - - public override int InitMinHits => 30; // TODO - public override int InitMaxHits => 60; // TODO - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/ML Weapons/MagicalShortbow.cs b/Projects/UOContent/Items/Weapons/ML Weapons/MagicalShortbow.cs index f23de52d1..5a4b5e6b8 100644 --- a/Projects/UOContent/Items/Weapons/ML Weapons/MagicalShortbow.cs +++ b/Projects/UOContent/Items/Weapons/ML Weapons/MagicalShortbow.cs @@ -2,51 +2,51 @@ using System; namespace Server.Items { - [Flippable(0x2D2B, 0x2D1F)] - public class MagicalShortbow : BaseRanged - { - [Constructible] - public MagicalShortbow() : base(0x2D2B) => Weight = 6.0; - - public MagicalShortbow(Serial serial) : base(serial) + [Flippable(0x2D2B, 0x2D1F)] + public class MagicalShortbow : BaseRanged { + [Constructible] + public MagicalShortbow() : base(0x2D2B) => Weight = 6.0; + + public MagicalShortbow(Serial serial) : base(serial) + { + } + + public override int EffectID => 0xF42; + public override Type AmmoType => typeof(Arrow); + public override Item Ammo => new Arrow(); + + public override WeaponAbility PrimaryAbility => WeaponAbility.LightningArrow; + public override WeaponAbility SecondaryAbility => WeaponAbility.PsychicAttack; + + public override int AosStrengthReq => 45; + public override int AosMinDamage => 9; + public override int AosMaxDamage => 13; + public override int AosSpeed => 38; + public override float MlSpeed => 3.00f; + + public override int OldStrengthReq => 45; + public override int OldMinDamage => 9; + public override int OldMaxDamage => 13; + public override int OldSpeed => 38; + + public override int DefMaxRange => 10; + + public override int InitMinHits => 41; + public override int InitMaxHits => 90; + + 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(); + } } - - public override int EffectID => 0xF42; - public override Type AmmoType => typeof(Arrow); - public override Item Ammo => new Arrow(); - - public override WeaponAbility PrimaryAbility => WeaponAbility.LightningArrow; - public override WeaponAbility SecondaryAbility => WeaponAbility.PsychicAttack; - - public override int AosStrengthReq => 45; - public override int AosMinDamage => 9; - public override int AosMaxDamage => 13; - public override int AosSpeed => 38; - public override float MlSpeed => 3.00f; - - public override int OldStrengthReq => 45; - public override int OldMinDamage => 9; - public override int OldMaxDamage => 13; - public override int OldSpeed => 38; - - public override int DefMaxRange => 10; - - public override int InitMinHits => 41; - public override int InitMaxHits => 90; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/ML Weapons/OrnateAxe.cs b/Projects/UOContent/Items/Weapons/ML Weapons/OrnateAxe.cs index e43aaf31e..8f8ef261e 100644 --- a/Projects/UOContent/Items/Weapons/ML Weapons/OrnateAxe.cs +++ b/Projects/UOContent/Items/Weapons/ML Weapons/OrnateAxe.cs @@ -1,50 +1,50 @@ namespace Server.Items { - [Flippable(0x2D28, 0x2D34)] - public class OrnateAxe : BaseAxe - { - [Constructible] - public OrnateAxe() : base(0x2D28) + [Flippable(0x2D28, 0x2D34)] + public class OrnateAxe : BaseAxe { - Weight = 12.0; - Layer = Layer.TwoHanded; + [Constructible] + public OrnateAxe() : base(0x2D28) + { + Weight = 12.0; + Layer = Layer.TwoHanded; + } + + public OrnateAxe(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.Disarm; + public override WeaponAbility SecondaryAbility => WeaponAbility.CrushingBlow; + + public override int AosStrengthReq => 45; + public override int AosMinDamage => 18; + public override int AosMaxDamage => 20; + public override int AosSpeed => 26; + public override float MlSpeed => 3.50f; + + public override int OldStrengthReq => 45; + public override int OldMinDamage => 18; + public override int OldMaxDamage => 20; + public override int OldSpeed => 26; + + public override int DefMissSound => 0x239; + + public override int InitMinHits => 30; + public override int InitMaxHits => 60; + + 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(); + } } - - public OrnateAxe(Serial serial) : base(serial) - { - } - - public override WeaponAbility PrimaryAbility => WeaponAbility.Disarm; - public override WeaponAbility SecondaryAbility => WeaponAbility.CrushingBlow; - - public override int AosStrengthReq => 45; - public override int AosMinDamage => 18; - public override int AosMaxDamage => 20; - public override int AosSpeed => 26; - public override float MlSpeed => 3.50f; - - public override int OldStrengthReq => 45; - public override int OldMinDamage => 18; - public override int OldMaxDamage => 20; - public override int OldSpeed => 26; - - public override int DefMissSound => 0x239; - - public override int InitMinHits => 30; - public override int InitMaxHits => 60; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/ML Weapons/RadiantScimitar.cs b/Projects/UOContent/Items/Weapons/ML Weapons/RadiantScimitar.cs index 274ddf77f..615bfdbc5 100644 --- a/Projects/UOContent/Items/Weapons/ML Weapons/RadiantScimitar.cs +++ b/Projects/UOContent/Items/Weapons/ML Weapons/RadiantScimitar.cs @@ -1,47 +1,47 @@ namespace Server.Items { - [Flippable(0x2D33, 0x2D27)] - public class RadiantScimitar : BaseSword - { - [Constructible] - public RadiantScimitar() : base(0x2D33) => Weight = 9.0; - - public RadiantScimitar(Serial serial) : base(serial) + [Flippable(0x2D33, 0x2D27)] + public class RadiantScimitar : BaseSword { + [Constructible] + public RadiantScimitar() : base(0x2D33) => Weight = 9.0; + + public RadiantScimitar(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.WhirlwindAttack; + public override WeaponAbility SecondaryAbility => WeaponAbility.Bladeweave; + + public override int AosStrengthReq => 20; + public override int AosMinDamage => 12; + public override int AosMaxDamage => 14; + public override int AosSpeed => 43; + public override float MlSpeed => 2.50f; + + public override int OldStrengthReq => 20; + public override int OldMinDamage => 12; + public override int OldMaxDamage => 14; + public override int OldSpeed => 43; + + public override int DefHitSound => 0x23B; + public override int DefMissSound => 0x239; + + public override int InitMinHits => 30; + public override int InitMaxHits => 60; + + 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(); + } } - - public override WeaponAbility PrimaryAbility => WeaponAbility.WhirlwindAttack; - public override WeaponAbility SecondaryAbility => WeaponAbility.Bladeweave; - - public override int AosStrengthReq => 20; - public override int AosMinDamage => 12; - public override int AosMaxDamage => 14; - public override int AosSpeed => 43; - public override float MlSpeed => 2.50f; - - public override int OldStrengthReq => 20; - public override int OldMinDamage => 12; - public override int OldMaxDamage => 14; - public override int OldSpeed => 43; - - public override int DefHitSound => 0x23B; - public override int DefMissSound => 0x239; - - public override int InitMinHits => 30; - public override int InitMaxHits => 60; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/ML Weapons/RuneBlade.cs b/Projects/UOContent/Items/Weapons/ML Weapons/RuneBlade.cs index 17c69fea7..f2760736d 100644 --- a/Projects/UOContent/Items/Weapons/ML Weapons/RuneBlade.cs +++ b/Projects/UOContent/Items/Weapons/ML Weapons/RuneBlade.cs @@ -1,51 +1,51 @@ namespace Server.Items { - [Flippable(0x2D32, 0x2D26)] - public class RuneBlade : BaseSword - { - [Constructible] - public RuneBlade() : base(0x2D32) + [Flippable(0x2D32, 0x2D26)] + public class RuneBlade : BaseSword { - Weight = 7.0; - Layer = Layer.TwoHanded; + [Constructible] + public RuneBlade() : base(0x2D32) + { + Weight = 7.0; + Layer = Layer.TwoHanded; + } + + public RuneBlade(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.Disarm; + public override WeaponAbility SecondaryAbility => WeaponAbility.Bladeweave; + + public override int AosStrengthReq => 30; + public override int AosMinDamage => 15; + public override int AosMaxDamage => 17; + public override int AosSpeed => 35; + public override float MlSpeed => 3.00f; + + public override int OldStrengthReq => 30; + public override int OldMinDamage => 15; + public override int OldMaxDamage => 17; + public override int OldSpeed => 35; + + public override int DefHitSound => 0x23B; + public override int DefMissSound => 0x239; + + public override int InitMinHits => 30; + public override int InitMaxHits => 60; + + 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(); + } } - - public RuneBlade(Serial serial) : base(serial) - { - } - - public override WeaponAbility PrimaryAbility => WeaponAbility.Disarm; - public override WeaponAbility SecondaryAbility => WeaponAbility.Bladeweave; - - public override int AosStrengthReq => 30; - public override int AosMinDamage => 15; - public override int AosMaxDamage => 17; - public override int AosSpeed => 35; - public override float MlSpeed => 3.00f; - - public override int OldStrengthReq => 30; - public override int OldMinDamage => 15; - public override int OldMaxDamage => 17; - public override int OldSpeed => 35; - - public override int DefHitSound => 0x23B; - public override int DefMissSound => 0x239; - - public override int InitMinHits => 30; - public override int InitMaxHits => 60; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/ML Weapons/WarCleaver.cs b/Projects/UOContent/Items/Weapons/ML Weapons/WarCleaver.cs index f8b04c9b3..1e016ce4c 100644 --- a/Projects/UOContent/Items/Weapons/ML Weapons/WarCleaver.cs +++ b/Projects/UOContent/Items/Weapons/ML Weapons/WarCleaver.cs @@ -1,51 +1,51 @@ namespace Server.Items { - [Flippable(0x2D2F, 0x2D23)] - public class WarCleaver : BaseKnife - { - [Constructible] - public WarCleaver() : base(0x2D2F) => Weight = 10.0; - - public WarCleaver(Serial serial) : base(serial) + [Flippable(0x2D2F, 0x2D23)] + public class WarCleaver : BaseKnife { + [Constructible] + public WarCleaver() : base(0x2D2F) => Weight = 10.0; + + public WarCleaver(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.Disarm; + public override WeaponAbility SecondaryAbility => WeaponAbility.Bladeweave; + + public override int AosStrengthReq => 15; + public override int AosMinDamage => 9; + public override int AosMaxDamage => 11; + public override int AosSpeed => 48; + public override float MlSpeed => 2.25f; + + public override int OldStrengthReq => 15; + public override int OldMinDamage => 9; + public override int OldMaxDamage => 11; + public override int OldSpeed => 48; + + public override int DefHitSound => 0x23B; + public override int DefMissSound => 0x239; + + public override int InitMinHits => 30; // TODO + public override int InitMaxHits => 60; // TODO + + public override SkillName DefSkill => SkillName.Fencing; + public override WeaponType DefType => WeaponType.Piercing; + public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H; + + 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(); + } } - - public override WeaponAbility PrimaryAbility => WeaponAbility.Disarm; - public override WeaponAbility SecondaryAbility => WeaponAbility.Bladeweave; - - public override int AosStrengthReq => 15; - public override int AosMinDamage => 9; - public override int AosMaxDamage => 11; - public override int AosSpeed => 48; - public override float MlSpeed => 2.25f; - - public override int OldStrengthReq => 15; - public override int OldMinDamage => 9; - public override int OldMaxDamage => 11; - public override int OldSpeed => 48; - - public override int DefHitSound => 0x23B; - public override int DefMissSound => 0x239; - - public override int InitMinHits => 30; // TODO - public override int InitMaxHits => 60; // TODO - - public override SkillName DefSkill => SkillName.Fencing; - public override WeaponType DefType => WeaponType.Piercing; - public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/ML Weapons/WildStaff.cs b/Projects/UOContent/Items/Weapons/ML Weapons/WildStaff.cs index 54e868a29..960ac0afb 100644 --- a/Projects/UOContent/Items/Weapons/ML Weapons/WildStaff.cs +++ b/Projects/UOContent/Items/Weapons/ML Weapons/WildStaff.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0x2D25, 0x2D31)] - public class WildStaff : BaseStaff - { - [Constructible] - public WildStaff() : base(0x2D25) => Weight = 8.0; - - public WildStaff(Serial serial) : base(serial) + [Flippable(0x2D25, 0x2D31)] + public class WildStaff : BaseStaff { + [Constructible] + public WildStaff() : base(0x2D25) => Weight = 8.0; + + public WildStaff(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.Block; + public override WeaponAbility SecondaryAbility => WeaponAbility.ForceOfNature; + + public override int AosStrengthReq => 15; + public override int AosMinDamage => 10; + public override int AosMaxDamage => 12; + public override int AosSpeed => 48; + public override float MlSpeed => 2.25f; + + public override int OldStrengthReq => 15; + public override int OldMinDamage => 10; + public override int OldMaxDamage => 12; + public override int OldSpeed => 48; + + public override int InitMinHits => 30; + public override int InitMaxHits => 60; + + 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(); + } } - - public override WeaponAbility PrimaryAbility => WeaponAbility.Block; - public override WeaponAbility SecondaryAbility => WeaponAbility.ForceOfNature; - - public override int AosStrengthReq => 15; - public override int AosMinDamage => 10; - public override int AosMaxDamage => 12; - public override int AosSpeed => 48; - public override float MlSpeed => 2.25f; - - public override int OldStrengthReq => 15; - public override int OldMinDamage => 10; - public override int OldMaxDamage => 12; - public override int OldSpeed => 48; - - public override int InitMinHits => 30; - public override int InitMaxHits => 60; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Maces/BaseBashing.cs b/Projects/UOContent/Items/Weapons/Maces/BaseBashing.cs index 4239ff744..734b145ab 100644 --- a/Projects/UOContent/Items/Weapons/Maces/BaseBashing.cs +++ b/Projects/UOContent/Items/Weapons/Maces/BaseBashing.cs @@ -2,60 +2,60 @@ using Server.Engines.ConPVP; namespace Server.Items { - public abstract class BaseBashing : BaseMeleeWeapon - { - public BaseBashing(int itemID) : base(itemID) + public abstract class BaseBashing : BaseMeleeWeapon { + public BaseBashing(int itemID) : base(itemID) + { + } + + public BaseBashing(Serial serial) : base(serial) + { + } + + public override int DefHitSound => 0x233; + public override int DefMissSound => 0x239; + + public override SkillName DefSkill => SkillName.Macing; + public override WeaponType DefType => WeaponType.Bashing; + public override WeaponAnimation DefAnimation => WeaponAnimation.Bash1H; + + 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 OnHit(Mobile attacker, Mobile defender, double damageBonus = 1) + { + base.OnHit(attacker, defender, damageBonus); + + defender.Stam -= Utility.Random(3, 3); // 3-5 points of stamina loss + } + + public override double GetBaseDamage(Mobile attacker) + { + var damage = base.GetBaseDamage(attacker); + + if (!Core.AOS && (attacker.Player || attacker.Body.IsHuman) && Layer == Layer.TwoHanded && + attacker.Skills.Anatomy.Value >= 80 && + attacker.Skills.Anatomy.Value / 400.0 >= Utility.RandomDouble() && + DuelContext.AllowSpecialAbility(attacker, "Crushing Blow", false)) + { + damage *= 1.5; + + attacker.SendMessage("You deliver a crushing blow!"); // Is this not localized? + attacker.PlaySound(0x11C); + } + + return damage; + } } - - public BaseBashing(Serial serial) : base(serial) - { - } - - public override int DefHitSound => 0x233; - public override int DefMissSound => 0x239; - - public override SkillName DefSkill => SkillName.Macing; - public override WeaponType DefType => WeaponType.Bashing; - public override WeaponAnimation DefAnimation => WeaponAnimation.Bash1H; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnHit(Mobile attacker, Mobile defender, double damageBonus = 1) - { - base.OnHit(attacker, defender, damageBonus); - - defender.Stam -= Utility.Random(3, 3); // 3-5 points of stamina loss - } - - public override double GetBaseDamage(Mobile attacker) - { - double damage = base.GetBaseDamage(attacker); - - if (!Core.AOS && (attacker.Player || attacker.Body.IsHuman) && Layer == Layer.TwoHanded && - attacker.Skills.Anatomy.Value >= 80 && - attacker.Skills.Anatomy.Value / 400.0 >= Utility.RandomDouble() && - DuelContext.AllowSpecialAbility(attacker, "Crushing Blow", false)) - { - damage *= 1.5; - - attacker.SendMessage("You deliver a crushing blow!"); // Is this not localized? - attacker.PlaySound(0x11C); - } - - return damage; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Maces/Club.cs b/Projects/UOContent/Items/Weapons/Maces/Club.cs index f19714ec7..6331c3a21 100644 --- a/Projects/UOContent/Items/Weapons/Maces/Club.cs +++ b/Projects/UOContent/Items/Weapons/Maces/Club.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0x13b4, 0x13b3)] - public class Club : BaseBashing - { - [Constructible] - public Club() : base(0x13B4) => Weight = 9.0; - - public Club(Serial serial) : base(serial) + [Flippable(0x13b4, 0x13b3)] + public class Club : BaseBashing { + [Constructible] + public Club() : base(0x13B4) => Weight = 9.0; + + public Club(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.ShadowStrike; + public override WeaponAbility SecondaryAbility => WeaponAbility.Dismount; + + public override int AosStrengthReq => 40; + public override int AosMinDamage => 11; + public override int AosMaxDamage => 13; + public override int AosSpeed => 44; + public override float MlSpeed => 2.50f; + + public override int OldStrengthReq => 10; + public override int OldMinDamage => 8; + public override int OldMaxDamage => 24; + public override int OldSpeed => 40; + + public override int InitMinHits => 31; + public override int InitMaxHits => 40; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.ShadowStrike; - public override WeaponAbility SecondaryAbility => WeaponAbility.Dismount; - - public override int AosStrengthReq => 40; - public override int AosMinDamage => 11; - public override int AosMaxDamage => 13; - public override int AosSpeed => 44; - public override float MlSpeed => 2.50f; - - public override int OldStrengthReq => 10; - public override int OldMinDamage => 8; - public override int OldMaxDamage => 24; - public override int OldSpeed => 40; - - public override int InitMinHits => 31; - public override int InitMaxHits => 40; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Maces/EmeraldMace.cs b/Projects/UOContent/Items/Weapons/Maces/EmeraldMace.cs index bfcc0eb19..7d2114ec1 100644 --- a/Projects/UOContent/Items/Weapons/Maces/EmeraldMace.cs +++ b/Projects/UOContent/Items/Weapons/Maces/EmeraldMace.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class EmeraldMace : DiamondMace - { - [Constructible] - public EmeraldMace() => WeaponAttributes.ResistPoisonBonus = 5; - - public EmeraldMace(Serial serial) : base(serial) + public class EmeraldMace : DiamondMace { + [Constructible] + public EmeraldMace() => WeaponAttributes.ResistPoisonBonus = 5; + + public EmeraldMace(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073530; // emerald mace + + 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(); + } } - - public override int LabelNumber => 1073530; // emerald mace - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Maces/FireworksWand.cs b/Projects/UOContent/Items/Weapons/Maces/FireworksWand.cs index cf9b783a3..fee6501b7 100644 --- a/Projects/UOContent/Items/Weapons/Maces/FireworksWand.cs +++ b/Projects/UOContent/Items/Weapons/Maces/FireworksWand.cs @@ -2,129 +2,139 @@ using System; namespace Server.Items { - public class FireworksWand : MagicWand - { - private int m_Charges; - - [Constructible] - public FireworksWand(int charges = 100) + public class FireworksWand : MagicWand { - m_Charges = charges; - LootType = LootType.Blessed; - } + private int m_Charges; - public FireworksWand(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041424; // a fireworks wand - - [CommandProperty(AccessLevel.GameMaster)] - public int Charges - { - get => m_Charges; - set - { - m_Charges = value; - InvalidateProperties(); - } - } - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - list.Add(1060741, m_Charges.ToString()); // charges: ~1_val~ - } - - public override void OnDoubleClick(Mobile from) - { - BeginLaunch(from, true); - } - - public void BeginLaunch(Mobile from, bool useCharges) - { - Map map = from.Map; - - if (map == null || map == Map.Internal) - return; - - if (useCharges) - { - if (Charges > 0) + [Constructible] + public FireworksWand(int charges = 100) { - --Charges; + m_Charges = charges; + LootType = LootType.Blessed; } - else + + public FireworksWand(Serial serial) : base(serial) { - from.SendLocalizedMessage(502412); // There are no charges left on that item. - return; } - } - from.SendLocalizedMessage(502615); // You launch a firework! + public override int LabelNumber => 1041424; // a fireworks wand - Point3D ourLoc = GetWorldLocation(); + [CommandProperty(AccessLevel.GameMaster)] + public int Charges + { + get => m_Charges; + set + { + m_Charges = value; + InvalidateProperties(); + } + } - Point3D startLoc = new Point3D(ourLoc.X, ourLoc.Y, ourLoc.Z + 10); - Point3D endLoc = new Point3D(startLoc.X + Utility.RandomMinMax(-2, 2), startLoc.Y + Utility.RandomMinMax(-2, 2), - startLoc.Z + 32); + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); - Effects.SendMovingEffect(new Entity(Serial.Zero, startLoc, map), new Entity(Serial.Zero, endLoc, map), - 0x36E4, 5, 0, false, false); + list.Add(1060741, m_Charges.ToString()); // charges: ~1_val~ + } - Timer.DelayCall(TimeSpan.FromSeconds(1.0), FinishLaunch, endLoc, map); + public override void OnDoubleClick(Mobile from) + { + BeginLaunch(from, true); + } + + public void BeginLaunch(Mobile from, bool useCharges) + { + var map = from.Map; + + if (map == null || map == Map.Internal) + return; + + if (useCharges) + { + if (Charges > 0) + { + --Charges; + } + else + { + from.SendLocalizedMessage(502412); // There are no charges left on that item. + return; + } + } + + from.SendLocalizedMessage(502615); // You launch a firework! + + var ourLoc = GetWorldLocation(); + + var startLoc = new Point3D(ourLoc.X, ourLoc.Y, ourLoc.Z + 10); + var endLoc = new Point3D( + startLoc.X + Utility.RandomMinMax(-2, 2), + startLoc.Y + Utility.RandomMinMax(-2, 2), + startLoc.Z + 32 + ); + + Effects.SendMovingEffect( + new Entity(Serial.Zero, startLoc, map), + new Entity(Serial.Zero, endLoc, map), + 0x36E4, + 5, + 0, + false, + false + ); + + Timer.DelayCall(TimeSpan.FromSeconds(1.0), FinishLaunch, endLoc, map); + } + + private static void FinishLaunch(Point3D endLoc, Map map) + { + var hue = Utility.Random(40); + + if (hue < 8) + hue = 0x66D; + else if (hue < 10) + hue = 0x482; + else if (hue < 12) + hue = 0x47E; + else if (hue < 16) + hue = 0x480; + else if (hue < 20) + hue = 0x47F; + else + hue = 0; + + if (Utility.RandomBool()) + hue = Utility.RandomList(0x47E, 0x47F, 0x480, 0x482, 0x66D); + + var renderMode = Utility.RandomList(0, 2, 3, 4, 5, 7); + + Effects.PlaySound(endLoc, map, Utility.Random(0x11B, 4)); + Effects.SendLocationEffect(endLoc, map, 0x373A + 0x10 * Utility.Random(4), 16, 10, hue, renderMode); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Charges); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Charges = reader.ReadInt(); + break; + } + } + } } - - private static void FinishLaunch(Point3D endLoc, Map map) - { - int hue = Utility.Random(40); - - if (hue < 8) - hue = 0x66D; - else if (hue < 10) - hue = 0x482; - else if (hue < 12) - hue = 0x47E; - else if (hue < 16) - hue = 0x480; - else if (hue < 20) - hue = 0x47F; - else - hue = 0; - - if (Utility.RandomBool()) - hue = Utility.RandomList(0x47E, 0x47F, 0x480, 0x482, 0x66D); - - int renderMode = Utility.RandomList(0, 2, 3, 4, 5, 7); - - Effects.PlaySound(endLoc, map, Utility.Random(0x11B, 4)); - Effects.SendLocationEffect(endLoc, map, 0x373A + 0x10 * Utility.Random(4), 16, 10, hue, renderMode); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Charges); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Charges = reader.ReadInt(); - break; - } - } - } - } } diff --git a/Projects/UOContent/Items/Weapons/Maces/HammerPick.cs b/Projects/UOContent/Items/Weapons/Maces/HammerPick.cs index a33c39e03..deea4ce23 100644 --- a/Projects/UOContent/Items/Weapons/Maces/HammerPick.cs +++ b/Projects/UOContent/Items/Weapons/Maces/HammerPick.cs @@ -1,48 +1,48 @@ namespace Server.Items { - [Flippable(0x143D, 0x143C)] - public class HammerPick : BaseBashing - { - [Constructible] - public HammerPick() : base(0x143D) + [Flippable(0x143D, 0x143C)] + public class HammerPick : BaseBashing { - Weight = 9.0; - Layer = Layer.OneHanded; + [Constructible] + public HammerPick() : base(0x143D) + { + Weight = 9.0; + Layer = Layer.OneHanded; + } + + public HammerPick(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore; + public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike; + + public override int AosStrengthReq => 45; + public override int AosMinDamage => 15; + public override int AosMaxDamage => 17; + public override int AosSpeed => 28; + public override float MlSpeed => 3.75f; + + public override int OldStrengthReq => 35; + public override int OldMinDamage => 6; + public override int OldMaxDamage => 33; + public override int OldSpeed => 30; + + public override int InitMinHits => 31; + public override int InitMaxHits => 70; + + 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 HammerPick(Serial serial) : base(serial) - { - } - - public override WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore; - public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike; - - public override int AosStrengthReq => 45; - public override int AosMinDamage => 15; - public override int AosMaxDamage => 17; - public override int AosSpeed => 28; - public override float MlSpeed => 3.75f; - - public override int OldStrengthReq => 35; - public override int OldMinDamage => 6; - public override int OldMaxDamage => 33; - public override int OldSpeed => 30; - - public override int InitMinHits => 31; - public override int InitMaxHits => 70; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Maces/Mace.cs b/Projects/UOContent/Items/Weapons/Maces/Mace.cs index b84d5e2c5..d0513d1b8 100644 --- a/Projects/UOContent/Items/Weapons/Maces/Mace.cs +++ b/Projects/UOContent/Items/Weapons/Maces/Mace.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0xF5C, 0xF5D)] - public class Mace : BaseBashing - { - [Constructible] - public Mace() : base(0xF5C) => Weight = 14.0; - - public Mace(Serial serial) : base(serial) + [Flippable(0xF5C, 0xF5D)] + public class Mace : BaseBashing { + [Constructible] + public Mace() : base(0xF5C) => Weight = 14.0; + + public Mace(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.ConcussionBlow; + public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm; + + public override int AosStrengthReq => 45; + public override int AosMinDamage => 12; + public override int AosMaxDamage => 14; + public override int AosSpeed => 40; + public override float MlSpeed => 2.75f; + + public override int OldStrengthReq => 20; + public override int OldMinDamage => 8; + public override int OldMaxDamage => 32; + public override int OldSpeed => 30; + + public override int InitMinHits => 31; + public override int InitMaxHits => 70; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.ConcussionBlow; - public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm; - - public override int AosStrengthReq => 45; - public override int AosMinDamage => 12; - public override int AosMaxDamage => 14; - public override int AosSpeed => 40; - public override float MlSpeed => 2.75f; - - public override int OldStrengthReq => 20; - public override int OldMinDamage => 8; - public override int OldMaxDamage => 32; - public override int OldSpeed => 30; - - public override int InitMinHits => 31; - public override int InitMaxHits => 70; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Maces/MagicWand.cs b/Projects/UOContent/Items/Weapons/Maces/MagicWand.cs index 31a6664ff..22c2aeb20 100644 --- a/Projects/UOContent/Items/Weapons/Maces/MagicWand.cs +++ b/Projects/UOContent/Items/Weapons/Maces/MagicWand.cs @@ -1,43 +1,43 @@ namespace Server.Items { - public class MagicWand : BaseBashing - { - [Constructible] - public MagicWand() : base(0xDF2) => Weight = 1.0; - - public MagicWand(Serial serial) : base(serial) + public class MagicWand : BaseBashing { + [Constructible] + public MagicWand() : base(0xDF2) => Weight = 1.0; + + public MagicWand(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.Dismount; + public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm; + + public override int AosStrengthReq => 5; + public override int AosMinDamage => 9; + public override int AosMaxDamage => 11; + public override int AosSpeed => 40; + public override float MlSpeed => 2.75f; + + public override int OldStrengthReq => 0; + public override int OldMinDamage => 2; + public override int OldMaxDamage => 6; + public override int OldSpeed => 35; + + public override int InitMinHits => 31; + public override int InitMaxHits => 110; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.Dismount; - public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm; - - public override int AosStrengthReq => 5; - public override int AosMinDamage => 9; - public override int AosMaxDamage => 11; - public override int AosSpeed => 40; - public override float MlSpeed => 2.75f; - - public override int OldStrengthReq => 0; - public override int OldMinDamage => 2; - public override int OldMaxDamage => 6; - public override int OldSpeed => 35; - - public override int InitMinHits => 31; - public override int InitMaxHits => 110; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Maces/Maul.cs b/Projects/UOContent/Items/Weapons/Maces/Maul.cs index 555d17e45..b8ec91a60 100644 --- a/Projects/UOContent/Items/Weapons/Maces/Maul.cs +++ b/Projects/UOContent/Items/Weapons/Maces/Maul.cs @@ -1,47 +1,47 @@ namespace Server.Items { - [Flippable(0x143B, 0x143A)] - public class Maul : BaseBashing - { - [Constructible] - public Maul() : base(0x143B) => Weight = 10.0; - - public Maul(Serial serial) : base(serial) + [Flippable(0x143B, 0x143A)] + public class Maul : BaseBashing { + [Constructible] + public Maul() : base(0x143B) => Weight = 10.0; + + public Maul(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow; + public override WeaponAbility SecondaryAbility => WeaponAbility.ConcussionBlow; + + public override int AosStrengthReq => 45; + public override int AosMinDamage => 14; + public override int AosMaxDamage => 16; + public override int AosSpeed => 32; + public override float MlSpeed => 3.50f; + + public override int OldStrengthReq => 20; + public override int OldMinDamage => 10; + public override int OldMaxDamage => 30; + public override int OldSpeed => 30; + + public override int InitMinHits => 31; + public override int InitMaxHits => 70; + + 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 (Weight == 14.0) + Weight = 10.0; + } } - - public override WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow; - public override WeaponAbility SecondaryAbility => WeaponAbility.ConcussionBlow; - - public override int AosStrengthReq => 45; - public override int AosMinDamage => 14; - public override int AosMaxDamage => 16; - public override int AosSpeed => 32; - public override float MlSpeed => 3.50f; - - public override int OldStrengthReq => 20; - public override int OldMinDamage => 10; - public override int OldMaxDamage => 30; - public override int OldSpeed => 30; - - public override int InitMinHits => 31; - public override int InitMaxHits => 70; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 14.0) - Weight = 10.0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Maces/RubyMace.cs b/Projects/UOContent/Items/Weapons/Maces/RubyMace.cs index cf9516ca4..d19e236fd 100644 --- a/Projects/UOContent/Items/Weapons/Maces/RubyMace.cs +++ b/Projects/UOContent/Items/Weapons/Maces/RubyMace.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class RubyMace : DiamondMace - { - [Constructible] - public RubyMace() => Attributes.WeaponDamage = 5; - - public RubyMace(Serial serial) : base(serial) + public class RubyMace : DiamondMace { + [Constructible] + public RubyMace() => Attributes.WeaponDamage = 5; + + public RubyMace(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073529; // ruby mace + + 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(); + } } - - public override int LabelNumber => 1073529; // ruby mace - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Maces/SapphireMace.cs b/Projects/UOContent/Items/Weapons/Maces/SapphireMace.cs index 1afbf0cba..64e4b9226 100644 --- a/Projects/UOContent/Items/Weapons/Maces/SapphireMace.cs +++ b/Projects/UOContent/Items/Weapons/Maces/SapphireMace.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class SapphireMace : DiamondMace - { - [Constructible] - public SapphireMace() => WeaponAttributes.ResistEnergyBonus = 5; - - public SapphireMace(Serial serial) : base(serial) + public class SapphireMace : DiamondMace { + [Constructible] + public SapphireMace() => WeaponAttributes.ResistEnergyBonus = 5; + + public SapphireMace(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073531; // sapphire mace + + 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(); + } } - - public override int LabelNumber => 1073531; // sapphire mace - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Maces/Scepter.cs b/Projects/UOContent/Items/Weapons/Maces/Scepter.cs index 436d0dc59..4e994fb7c 100644 --- a/Projects/UOContent/Items/Weapons/Maces/Scepter.cs +++ b/Projects/UOContent/Items/Weapons/Maces/Scepter.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0x26BC, 0x26C6)] - public class Scepter : BaseBashing - { - [Constructible] - public Scepter() : base(0x26BC) => Weight = 8.0; - - public Scepter(Serial serial) : base(serial) + [Flippable(0x26BC, 0x26C6)] + public class Scepter : BaseBashing { + [Constructible] + public Scepter() : base(0x26BC) => Weight = 8.0; + + public Scepter(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow; + public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike; + + public override int AosStrengthReq => 40; + public override int AosMinDamage => 14; + public override int AosMaxDamage => 17; + public override int AosSpeed => 30; + public override float MlSpeed => 3.50f; + + public override int OldStrengthReq => 40; + public override int OldMinDamage => 14; + public override int OldMaxDamage => 17; + public override int OldSpeed => 30; + + public override int InitMinHits => 31; + public override int InitMaxHits => 110; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow; - public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike; - - public override int AosStrengthReq => 40; - public override int AosMinDamage => 14; - public override int AosMaxDamage => 17; - public override int AosSpeed => 30; - public override float MlSpeed => 3.50f; - - public override int OldStrengthReq => 40; - public override int OldMinDamage => 14; - public override int OldMaxDamage => 17; - public override int OldSpeed => 30; - - public override int InitMinHits => 31; - public override int InitMaxHits => 110; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Maces/SilverEtchedMace.cs b/Projects/UOContent/Items/Weapons/Maces/SilverEtchedMace.cs index 989ba0d81..95bc77245 100644 --- a/Projects/UOContent/Items/Weapons/Maces/SilverEtchedMace.cs +++ b/Projects/UOContent/Items/Weapons/Maces/SilverEtchedMace.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class SilverEtchedMace : DiamondMace - { - [Constructible] - public SilverEtchedMace() => Slayer = SlayerName.Exorcism; - - public SilverEtchedMace(Serial serial) : base(serial) + public class SilverEtchedMace : DiamondMace { + [Constructible] + public SilverEtchedMace() => Slayer = SlayerName.Exorcism; + + public SilverEtchedMace(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073532; // silver-etched mace + + 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(); + } } - - public override int LabelNumber => 1073532; // silver-etched mace - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Maces/WarHammer.cs b/Projects/UOContent/Items/Weapons/Maces/WarHammer.cs index 41b0ee747..b2f017d29 100644 --- a/Projects/UOContent/Items/Weapons/Maces/WarHammer.cs +++ b/Projects/UOContent/Items/Weapons/Maces/WarHammer.cs @@ -1,50 +1,50 @@ namespace Server.Items { - [Flippable(0x1439, 0x1438)] - public class WarHammer : BaseBashing - { - [Constructible] - public WarHammer() : base(0x1439) + [Flippable(0x1439, 0x1438)] + public class WarHammer : BaseBashing { - Weight = 10.0; - Layer = Layer.TwoHanded; + [Constructible] + public WarHammer() : base(0x1439) + { + Weight = 10.0; + Layer = Layer.TwoHanded; + } + + public WarHammer(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.WhirlwindAttack; + public override WeaponAbility SecondaryAbility => WeaponAbility.CrushingBlow; + + public override int AosStrengthReq => 95; + public override int AosMinDamage => 17; + public override int AosMaxDamage => 18; + public override int AosSpeed => 28; + public override float MlSpeed => 3.75f; + + public override int OldStrengthReq => 40; + public override int OldMinDamage => 8; + public override int OldMaxDamage => 36; + public override int OldSpeed => 31; + + public override int InitMinHits => 31; + public override int InitMaxHits => 110; + + public override WeaponAnimation DefAnimation => WeaponAnimation.Bash2H; + + 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 WarHammer(Serial serial) : base(serial) - { - } - - public override WeaponAbility PrimaryAbility => WeaponAbility.WhirlwindAttack; - public override WeaponAbility SecondaryAbility => WeaponAbility.CrushingBlow; - - public override int AosStrengthReq => 95; - public override int AosMinDamage => 17; - public override int AosMaxDamage => 18; - public override int AosSpeed => 28; - public override float MlSpeed => 3.75f; - - public override int OldStrengthReq => 40; - public override int OldMinDamage => 8; - public override int OldMaxDamage => 36; - public override int OldSpeed => 31; - - public override int InitMinHits => 31; - public override int InitMaxHits => 110; - - public override WeaponAnimation DefAnimation => WeaponAnimation.Bash2H; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Maces/WarMace.cs b/Projects/UOContent/Items/Weapons/Maces/WarMace.cs index ec8943e6f..184ce6172 100644 --- a/Projects/UOContent/Items/Weapons/Maces/WarMace.cs +++ b/Projects/UOContent/Items/Weapons/Maces/WarMace.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0x1407, 0x1406)] - public class WarMace : BaseBashing - { - [Constructible] - public WarMace() : base(0x1407) => Weight = 17.0; - - public WarMace(Serial serial) : base(serial) + [Flippable(0x1407, 0x1406)] + public class WarMace : BaseBashing { + [Constructible] + public WarMace() : base(0x1407) => Weight = 17.0; + + public WarMace(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow; + public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike; + + public override int AosStrengthReq => 80; + public override int AosMinDamage => 16; + public override int AosMaxDamage => 17; + public override int AosSpeed => 26; + public override float MlSpeed => 4.00f; + + public override int OldStrengthReq => 30; + public override int OldMinDamage => 10; + public override int OldMaxDamage => 30; + public override int OldSpeed => 32; + + public override int InitMinHits => 31; + public override int InitMaxHits => 110; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow; - public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike; - - public override int AosStrengthReq => 80; - public override int AosMinDamage => 16; - public override int AosMaxDamage => 17; - public override int AosSpeed => 26; - public override float MlSpeed => 4.00f; - - public override int OldStrengthReq => 30; - public override int OldMinDamage => 10; - public override int OldMaxDamage => 30; - public override int OldSpeed => 32; - - public override int InitMinHits => 31; - public override int InitMaxHits => 110; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/PoleArms/Bardiche.cs b/Projects/UOContent/Items/Weapons/PoleArms/Bardiche.cs index 1d031a241..bf0afa14b 100644 --- a/Projects/UOContent/Items/Weapons/PoleArms/Bardiche.cs +++ b/Projects/UOContent/Items/Weapons/PoleArms/Bardiche.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0xF4D, 0xF4E)] - public class Bardiche : BasePoleArm - { - [Constructible] - public Bardiche() : base(0xF4D) => Weight = 7.0; - - public Bardiche(Serial serial) : base(serial) + [Flippable(0xF4D, 0xF4E)] + public class Bardiche : BasePoleArm { + [Constructible] + public Bardiche() : base(0xF4D) => Weight = 7.0; + + public Bardiche(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.ParalyzingBlow; + public override WeaponAbility SecondaryAbility => WeaponAbility.Dismount; + + public override int AosStrengthReq => 45; + public override int AosMinDamage => 17; + public override int AosMaxDamage => 18; + public override int AosSpeed => 28; + public override float MlSpeed => 3.75f; + + public override int OldStrengthReq => 40; + public override int OldMinDamage => 5; + public override int OldMaxDamage => 43; + public override int OldSpeed => 26; + + public override int InitMinHits => 31; + public override int InitMaxHits => 100; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.ParalyzingBlow; - public override WeaponAbility SecondaryAbility => WeaponAbility.Dismount; - - public override int AosStrengthReq => 45; - public override int AosMinDamage => 17; - public override int AosMaxDamage => 18; - public override int AosSpeed => 28; - public override float MlSpeed => 3.75f; - - public override int OldStrengthReq => 40; - public override int OldMinDamage => 5; - public override int OldMaxDamage => 43; - public override int OldSpeed => 26; - - public override int InitMinHits => 31; - public override int InitMaxHits => 100; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/PoleArms/BasePoleArm.cs b/Projects/UOContent/Items/Weapons/PoleArms/BasePoleArm.cs index a4d2d8ad7..9d8748196 100644 --- a/Projects/UOContent/Items/Weapons/PoleArms/BasePoleArm.cs +++ b/Projects/UOContent/Items/Weapons/PoleArms/BasePoleArm.cs @@ -6,128 +6,134 @@ using Server.Engines.Harvest; namespace Server.Items { - public abstract class BasePoleArm : BaseMeleeWeapon, IUsesRemaining - { - private bool m_ShowUsesRemaining; - - private int m_UsesRemaining; - - public BasePoleArm(int itemID) : base(itemID) => m_UsesRemaining = 150; - - public BasePoleArm(Serial serial) : base(serial) + public abstract class BasePoleArm : BaseMeleeWeapon, IUsesRemaining { - } + private bool m_ShowUsesRemaining; - public override int DefHitSound => 0x237; - public override int DefMissSound => 0x238; + private int m_UsesRemaining; - public override SkillName DefSkill => SkillName.Swords; - public override WeaponType DefType => WeaponType.Polearm; - public override WeaponAnimation DefAnimation => WeaponAnimation.Slash2H; + public BasePoleArm(int itemID) : base(itemID) => m_UsesRemaining = 150; - public virtual HarvestSystem HarvestSystem => Lumberjacking.System; - - [CommandProperty(AccessLevel.GameMaster)] - public int UsesRemaining - { - get => m_UsesRemaining; - set - { - m_UsesRemaining = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool ShowUsesRemaining - { - get => m_ShowUsesRemaining; - set - { - m_ShowUsesRemaining = value; - InvalidateProperties(); - } - } - - public override void OnDoubleClick(Mobile from) - { - if (HarvestSystem == null) - return; - - if (IsChildOf(from.Backpack) || Parent == from) - HarvestSystem.BeginHarvesting(from, this); - else - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (HarvestSystem != null) - BaseHarvestTool.AddContextMenuEntries(from, this, list, HarvestSystem); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(2); // version - - writer.Write(m_ShowUsesRemaining); - - writer.Write(m_UsesRemaining); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 2: - { - m_ShowUsesRemaining = reader.ReadBool(); - goto case 1; - } - case 1: - { - m_UsesRemaining = reader.ReadInt(); - goto case 0; - } - case 0: - { - if (m_UsesRemaining < 1) - m_UsesRemaining = 150; - - break; - } - } - } - - public override void OnHit(Mobile attacker, Mobile defender, double damageBonus = 1) - { - base.OnHit(attacker, defender, damageBonus); - - if (!Core.AOS && (attacker.Player || attacker.Body.IsHuman) && Layer == Layer.TwoHanded && - attacker.Skills.Anatomy.Value >= 80 && - attacker.Skills.Anatomy.Value / 400.0 >= Utility.RandomDouble() && - DuelContext.AllowSpecialAbility(attacker, "Concussion Blow", false)) - { - StatMod mod = defender.GetStatMod("Concussion"); - - if (mod == null) + public BasePoleArm(Serial serial) : base(serial) { - defender.SendMessage("You receive a concussion blow!"); - defender.AddStatMod(new StatMod(StatType.Int, "Concussion", -(defender.RawInt / 2), - TimeSpan.FromSeconds(30.0))); - - attacker.SendMessage("You deliver a concussion blow!"); - attacker.PlaySound(0x11C); } - } + + public override int DefHitSound => 0x237; + public override int DefMissSound => 0x238; + + public override SkillName DefSkill => SkillName.Swords; + public override WeaponType DefType => WeaponType.Polearm; + public override WeaponAnimation DefAnimation => WeaponAnimation.Slash2H; + + public virtual HarvestSystem HarvestSystem => Lumberjacking.System; + + [CommandProperty(AccessLevel.GameMaster)] + public int UsesRemaining + { + get => m_UsesRemaining; + set + { + m_UsesRemaining = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool ShowUsesRemaining + { + get => m_ShowUsesRemaining; + set + { + m_ShowUsesRemaining = value; + InvalidateProperties(); + } + } + + public override void OnDoubleClick(Mobile from) + { + if (HarvestSystem == null) + return; + + if (IsChildOf(from.Backpack) || Parent == from) + HarvestSystem.BeginHarvesting(from, this); + else + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (HarvestSystem != null) + BaseHarvestTool.AddContextMenuEntries(from, this, list, HarvestSystem); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(2); // version + + writer.Write(m_ShowUsesRemaining); + + writer.Write(m_UsesRemaining); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 2: + { + m_ShowUsesRemaining = reader.ReadBool(); + goto case 1; + } + case 1: + { + m_UsesRemaining = reader.ReadInt(); + goto case 0; + } + case 0: + { + if (m_UsesRemaining < 1) + m_UsesRemaining = 150; + + break; + } + } + } + + public override void OnHit(Mobile attacker, Mobile defender, double damageBonus = 1) + { + base.OnHit(attacker, defender, damageBonus); + + if (!Core.AOS && (attacker.Player || attacker.Body.IsHuman) && Layer == Layer.TwoHanded && + attacker.Skills.Anatomy.Value >= 80 && + attacker.Skills.Anatomy.Value / 400.0 >= Utility.RandomDouble() && + DuelContext.AllowSpecialAbility(attacker, "Concussion Blow", false)) + { + var mod = defender.GetStatMod("Concussion"); + + if (mod == null) + { + defender.SendMessage("You receive a concussion blow!"); + defender.AddStatMod( + new StatMod( + StatType.Int, + "Concussion", + -(defender.RawInt / 2), + TimeSpan.FromSeconds(30.0) + ) + ); + + attacker.SendMessage("You deliver a concussion blow!"); + attacker.PlaySound(0x11C); + } + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/PoleArms/Halberd.cs b/Projects/UOContent/Items/Weapons/PoleArms/Halberd.cs index f6ce5b8cf..26c0022e1 100644 --- a/Projects/UOContent/Items/Weapons/PoleArms/Halberd.cs +++ b/Projects/UOContent/Items/Weapons/PoleArms/Halberd.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0x143E, 0x143F)] - public class Halberd : BasePoleArm - { - [Constructible] - public Halberd() : base(0x143E) => Weight = 16.0; - - public Halberd(Serial serial) : base(serial) + [Flippable(0x143E, 0x143F)] + public class Halberd : BasePoleArm { + [Constructible] + public Halberd() : base(0x143E) => Weight = 16.0; + + public Halberd(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.WhirlwindAttack; + public override WeaponAbility SecondaryAbility => WeaponAbility.ConcussionBlow; + + public override int AosStrengthReq => 95; + public override int AosMinDamage => 18; + public override int AosMaxDamage => 19; + public override int AosSpeed => 25; + public override float MlSpeed => 4.25f; + + public override int OldStrengthReq => 45; + public override int OldMinDamage => 5; + public override int OldMaxDamage => 49; + public override int OldSpeed => 25; + + public override int InitMinHits => 31; + public override int InitMaxHits => 80; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.WhirlwindAttack; - public override WeaponAbility SecondaryAbility => WeaponAbility.ConcussionBlow; - - public override int AosStrengthReq => 95; - public override int AosMinDamage => 18; - public override int AosMaxDamage => 19; - public override int AosSpeed => 25; - public override float MlSpeed => 4.25f; - - public override int OldStrengthReq => 45; - public override int OldMinDamage => 5; - public override int OldMaxDamage => 49; - public override int OldSpeed => 25; - - public override int InitMinHits => 31; - public override int InitMaxHits => 80; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/PoleArms/Scythe.cs b/Projects/UOContent/Items/Weapons/PoleArms/Scythe.cs index 61331e4dc..de3a63078 100644 --- a/Projects/UOContent/Items/Weapons/PoleArms/Scythe.cs +++ b/Projects/UOContent/Items/Weapons/PoleArms/Scythe.cs @@ -2,50 +2,50 @@ using Server.Engines.Harvest; namespace Server.Items { - [Flippable(0x26BA, 0x26C4)] - public class Scythe : BasePoleArm - { - [Constructible] - public Scythe() : base(0x26BA) => Weight = 5.0; - - public Scythe(Serial serial) : base(serial) + [Flippable(0x26BA, 0x26C4)] + public class Scythe : BasePoleArm { + [Constructible] + public Scythe() : base(0x26BA) => Weight = 5.0; + + public Scythe(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.BleedAttack; + public override WeaponAbility SecondaryAbility => WeaponAbility.ParalyzingBlow; + + public override int AosStrengthReq => 45; + public override int AosMinDamage => 15; + public override int AosMaxDamage => 18; + public override int AosSpeed => 32; + public override float MlSpeed => 3.50f; + + public override int OldStrengthReq => 45; + public override int OldMinDamage => 15; + public override int OldMaxDamage => 18; + public override int OldSpeed => 32; + + public override int InitMinHits => 31; + public override int InitMaxHits => 100; + + public override HarvestSystem HarvestSystem => null; + + 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 (Weight == 15.0) + Weight = 5.0; + } } - - public override WeaponAbility PrimaryAbility => WeaponAbility.BleedAttack; - public override WeaponAbility SecondaryAbility => WeaponAbility.ParalyzingBlow; - - public override int AosStrengthReq => 45; - public override int AosMinDamage => 15; - public override int AosMaxDamage => 18; - public override int AosSpeed => 32; - public override float MlSpeed => 3.50f; - - public override int OldStrengthReq => 45; - public override int OldMinDamage => 15; - public override int OldMaxDamage => 18; - public override int OldSpeed => 32; - - public override int InitMinHits => 31; - public override int InitMaxHits => 100; - - public override HarvestSystem HarvestSystem => null; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 15.0) - Weight = 5.0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Ranged/AssassinsShortbow.cs b/Projects/UOContent/Items/Weapons/Ranged/AssassinsShortbow.cs index 83e6d6b03..9003e920d 100644 --- a/Projects/UOContent/Items/Weapons/Ranged/AssassinsShortbow.cs +++ b/Projects/UOContent/Items/Weapons/Ranged/AssassinsShortbow.cs @@ -1,32 +1,32 @@ namespace Server.Items { - public class AssassinsShortbow : MagicalShortbow - { - [Constructible] - public AssassinsShortbow() + public class AssassinsShortbow : MagicalShortbow { - Attributes.AttackChance = 3; - Attributes.WeaponDamage = 4; + [Constructible] + public AssassinsShortbow() + { + Attributes.AttackChance = 3; + Attributes.WeaponDamage = 4; + } + + public AssassinsShortbow(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073512; // assassin's shortbow + + 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(); + } } - - public AssassinsShortbow(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073512; // assassin's shortbow - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Ranged/BarbedLongbow.cs b/Projects/UOContent/Items/Weapons/Ranged/BarbedLongbow.cs index e035a38b7..08fa60b86 100644 --- a/Projects/UOContent/Items/Weapons/Ranged/BarbedLongbow.cs +++ b/Projects/UOContent/Items/Weapons/Ranged/BarbedLongbow.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class BarbedLongbow : ElvenCompositeLongbow - { - [Constructible] - public BarbedLongbow() => Attributes.ReflectPhysical = 12; - - public BarbedLongbow(Serial serial) : base(serial) + public class BarbedLongbow : ElvenCompositeLongbow { + [Constructible] + public BarbedLongbow() => Attributes.ReflectPhysical = 12; + + public BarbedLongbow(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073505; // barbed longbow + + 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(); + } } - - public override int LabelNumber => 1073505; // barbed longbow - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Ranged/BaseRanged.cs b/Projects/UOContent/Items/Weapons/Ranged/BaseRanged.cs index ae9f9a1e7..e9339e29e 100644 --- a/Projects/UOContent/Items/Weapons/Ranged/BaseRanged.cs +++ b/Projects/UOContent/Items/Weapons/Ranged/BaseRanged.cs @@ -5,231 +5,237 @@ using Server.Spells; namespace Server.Items { - public abstract class BaseRanged : BaseMeleeWeapon - { - private bool m_Balanced; - - private Timer m_RecoveryTimer; // so we don't start too many timers - private int m_Velocity; - - public BaseRanged(int itemID) : base(itemID) + public abstract class BaseRanged : BaseMeleeWeapon { - } + private bool m_Balanced; - public BaseRanged(Serial serial) : base(serial) - { - } + private Timer m_RecoveryTimer; // so we don't start too many timers + private int m_Velocity; - public abstract int EffectID { get; } - public abstract Type AmmoType { get; } - public abstract Item Ammo { get; } - - public override int DefHitSound => 0x234; - public override int DefMissSound => 0x238; - - public override SkillName DefSkill => SkillName.Archery; - public override WeaponType DefType => WeaponType.Ranged; - public override WeaponAnimation DefAnimation => WeaponAnimation.ShootXBow; - - public override SkillName AccuracySkill => SkillName.Archery; - - [CommandProperty(AccessLevel.GameMaster)] - public bool Balanced - { - get => m_Balanced; - set - { - m_Balanced = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Velocity - { - get => m_Velocity; - set - { - m_Velocity = value; - InvalidateProperties(); - } - } - - public override TimeSpan OnSwing(Mobile attacker, Mobile defender) - { - // WeaponAbility a = WeaponAbility.GetCurrentAbility( attacker ); - - // Make sure we've been standing still for .25/.5/1 second depending on Era - if (Core.TickCount - attacker.LastMoveTime >= (Core.SE ? 250 : Core.AOS ? 500 : 1000) || - (Core.AOS && WeaponAbility.GetCurrentAbility(attacker) is MovingShot)) - { - bool canSwing = true; - - if (Core.AOS) + public BaseRanged(int itemID) : base(itemID) { - canSwing = !attacker.Paralyzed && !attacker.Frozen; - - if (canSwing) - canSwing = !(attacker.Spell is Spell sp) || !sp.IsCasting || !sp.BlocksMovement; } - if ((attacker as PlayerMobile)?.DuelContext?.CheckItemEquip(attacker, this) == false) - canSwing = false; - - if (canSwing && attacker.HarmfulCheck(defender)) + public BaseRanged(Serial serial) : base(serial) { - attacker.DisruptiveAction(); - attacker.Send(new Swing(attacker.Serial, defender.Serial)); - - if (OnFired(attacker, defender)) - { - if (CheckHit(attacker, defender)) - OnHit(attacker, defender); - else - OnMiss(attacker, defender); - } } - attacker.RevealingAction(); + public abstract int EffectID { get; } + public abstract Type AmmoType { get; } + public abstract Item Ammo { get; } - return GetDelay(attacker); - } + public override int DefHitSound => 0x234; + public override int DefMissSound => 0x238; - attacker.RevealingAction(); + public override SkillName DefSkill => SkillName.Archery; + public override WeaponType DefType => WeaponType.Ranged; + public override WeaponAnimation DefAnimation => WeaponAnimation.ShootXBow; - return TimeSpan.FromSeconds(0.25); - } + public override SkillName AccuracySkill => SkillName.Archery; - public override void OnHit(Mobile attacker, Mobile defender, double damageBonus = 1) - { - if (attacker.Player && !defender.Player && (defender.Body.IsAnimal || defender.Body.IsMonster) && - Utility.RandomDouble() <= 0.4) - defender.AddToBackpack(Ammo); - - if (Core.ML && m_Velocity > 0) - { - int bonus = (int)attacker.GetDistanceToSqrt(defender); - - if (bonus > 0 && m_Velocity > Utility.Random(100)) + [CommandProperty(AccessLevel.GameMaster)] + public bool Balanced { - AOS.Damage(defender, attacker, bonus * 3, 100, 0, 0, 0, 0); - - if (attacker.Player) - attacker.SendLocalizedMessage(1072794); // Your arrow hits its mark with velocity! - - if (defender.Player) - defender.SendLocalizedMessage(1072795); // You have been hit by an arrow with velocity! - } - } - - base.OnHit(attacker, defender, damageBonus); - } - - public override void OnMiss(Mobile attacker, Mobile defender) - { - if (attacker.Player && Utility.RandomDouble() <= 0.4) - { - if (Core.SE) - { - if (attacker is PlayerMobile pm) - { - Type ammo = AmmoType; - - if (pm.RecoverableAmmo.ContainsKey(ammo)) - pm.RecoverableAmmo[ammo]++; - else - pm.RecoverableAmmo.Add(ammo, 1); - - if (!pm.Warmode) + get => m_Balanced; + set { - m_RecoveryTimer ??= Timer.DelayCall(TimeSpan.FromSeconds(10), pm.RecoverAmmo); - - if (!m_RecoveryTimer.Running) - m_RecoveryTimer.Start(); + m_Balanced = value; + InvalidateProperties(); } - } } - else + + [CommandProperty(AccessLevel.GameMaster)] + public int Velocity { - Ammo.MoveToWorld( - new Point3D(defender.X + Utility.RandomMinMax(-1, 1), defender.Y + Utility.RandomMinMax(-1, 1), - defender.Z), defender.Map); + get => m_Velocity; + set + { + m_Velocity = value; + InvalidateProperties(); + } } - } - base.OnMiss(attacker, defender); - } - - public virtual bool OnFired(Mobile attacker, Mobile defender) - { - if (attacker.Player) - { - BaseQuiver quiver = attacker.FindItemOnLayer(Layer.Cloak) as BaseQuiver; - Container pack = attacker.Backpack; - - if (quiver == null || Utility.Random(100) >= quiver.LowerAmmoCost) + public override TimeSpan OnSwing(Mobile attacker, Mobile defender) { - // consume ammo - if (quiver?.ConsumeTotal(AmmoType) == true) - quiver.InvalidateWeight(); - else if (pack?.ConsumeTotal(AmmoType) != true) - return false; + // WeaponAbility a = WeaponAbility.GetCurrentAbility( attacker ); + + // Make sure we've been standing still for .25/.5/1 second depending on Era + if (Core.TickCount - attacker.LastMoveTime >= (Core.SE ? 250 : + Core.AOS ? 500 : 1000) || + Core.AOS && WeaponAbility.GetCurrentAbility(attacker) is MovingShot) + { + var canSwing = true; + + if (Core.AOS) + { + canSwing = !attacker.Paralyzed && !attacker.Frozen; + + if (canSwing) + canSwing = !(attacker.Spell is Spell sp) || !sp.IsCasting || !sp.BlocksMovement; + } + + if ((attacker as PlayerMobile)?.DuelContext?.CheckItemEquip(attacker, this) == false) + canSwing = false; + + if (canSwing && attacker.HarmfulCheck(defender)) + { + attacker.DisruptiveAction(); + attacker.Send(new Swing(attacker.Serial, defender.Serial)); + + if (OnFired(attacker, defender)) + { + if (CheckHit(attacker, defender)) + OnHit(attacker, defender); + else + OnMiss(attacker, defender); + } + } + + attacker.RevealingAction(); + + return GetDelay(attacker); + } + + attacker.RevealingAction(); + + return TimeSpan.FromSeconds(0.25); } - else if (quiver.FindItemByType(AmmoType) == null && pack?.FindItemByType(AmmoType) == null) + + public override void OnHit(Mobile attacker, Mobile defender, double damageBonus = 1) { - // lower ammo cost should not work when we have no ammo at all - return false; + if (attacker.Player && !defender.Player && (defender.Body.IsAnimal || defender.Body.IsMonster) && + Utility.RandomDouble() <= 0.4) + defender.AddToBackpack(Ammo); + + if (Core.ML && m_Velocity > 0) + { + var bonus = (int)attacker.GetDistanceToSqrt(defender); + + if (bonus > 0 && m_Velocity > Utility.Random(100)) + { + AOS.Damage(defender, attacker, bonus * 3, 100, 0, 0, 0, 0); + + if (attacker.Player) + attacker.SendLocalizedMessage(1072794); // Your arrow hits its mark with velocity! + + if (defender.Player) + defender.SendLocalizedMessage(1072795); // You have been hit by an arrow with velocity! + } + } + + base.OnHit(attacker, defender, damageBonus); } - } - attacker.MovingEffect(defender, EffectID, 18, 1, false, false); + public override void OnMiss(Mobile attacker, Mobile defender) + { + if (attacker.Player && Utility.RandomDouble() <= 0.4) + { + if (Core.SE) + { + if (attacker is PlayerMobile pm) + { + var ammo = AmmoType; - return true; + if (pm.RecoverableAmmo.ContainsKey(ammo)) + pm.RecoverableAmmo[ammo]++; + else + pm.RecoverableAmmo.Add(ammo, 1); + + if (!pm.Warmode) + { + m_RecoveryTimer ??= Timer.DelayCall(TimeSpan.FromSeconds(10), pm.RecoverAmmo); + + if (!m_RecoveryTimer.Running) + m_RecoveryTimer.Start(); + } + } + } + else + { + Ammo.MoveToWorld( + new Point3D( + defender.X + Utility.RandomMinMax(-1, 1), + defender.Y + Utility.RandomMinMax(-1, 1), + defender.Z + ), + defender.Map + ); + } + } + + base.OnMiss(attacker, defender); + } + + public virtual bool OnFired(Mobile attacker, Mobile defender) + { + if (attacker.Player) + { + var quiver = attacker.FindItemOnLayer(Layer.Cloak) as BaseQuiver; + var pack = attacker.Backpack; + + if (quiver == null || Utility.Random(100) >= quiver.LowerAmmoCost) + { + // consume ammo + if (quiver?.ConsumeTotal(AmmoType) == true) + quiver.InvalidateWeight(); + else if (pack?.ConsumeTotal(AmmoType) != true) + return false; + } + else if (quiver.FindItemByType(AmmoType) == null && pack?.FindItemByType(AmmoType) == null) + { + // lower ammo cost should not work when we have no ammo at all + return false; + } + } + + attacker.MovingEffect(defender, EffectID, 18, 1, false, false); + + return true; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(3); // version + + writer.Write(m_Balanced); + writer.Write(m_Velocity); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 3: + { + m_Balanced = reader.ReadBool(); + m_Velocity = reader.ReadInt(); + + goto case 2; + } + case 2: + case 1: + { + break; + } + case 0: + { + /*m_EffectID =*/ + reader.ReadInt(); + break; + } + } + + if (version < 2) + { + WeaponAttributes.MageWeapon = 0; + WeaponAttributes.UseBestSkill = 0; + } + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(3); // version - - writer.Write(m_Balanced); - writer.Write(m_Velocity); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 3: - { - m_Balanced = reader.ReadBool(); - m_Velocity = reader.ReadInt(); - - goto case 2; - } - case 2: - case 1: - { - break; - } - case 0: - { - /*m_EffectID =*/ - reader.ReadInt(); - break; - } - } - - if (version < 2) - { - WeaponAttributes.MageWeapon = 0; - WeaponAttributes.UseBestSkill = 0; - } - } - } } diff --git a/Projects/UOContent/Items/Weapons/Ranged/Bow.cs b/Projects/UOContent/Items/Weapons/Ranged/Bow.cs index 8993a26cf..fcc7dfeee 100644 --- a/Projects/UOContent/Items/Weapons/Ranged/Bow.cs +++ b/Projects/UOContent/Items/Weapons/Ranged/Bow.cs @@ -2,60 +2,60 @@ using System; namespace Server.Items { - [Flippable(0x13B2, 0x13B1)] - public class Bow : BaseRanged - { - [Constructible] - public Bow() : base(0x13B2) + [Flippable(0x13B2, 0x13B1)] + public class Bow : BaseRanged { - Weight = 6.0; - Layer = Layer.TwoHanded; + [Constructible] + public Bow() : base(0x13B2) + { + Weight = 6.0; + Layer = Layer.TwoHanded; + } + + public Bow(Serial serial) : base(serial) + { + } + + public override int EffectID => 0xF42; + public override Type AmmoType => typeof(Arrow); + public override Item Ammo => new Arrow(); + + public override WeaponAbility PrimaryAbility => WeaponAbility.ParalyzingBlow; + public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike; + + public override int AosStrengthReq => 30; + public override int AosMinDamage => Core.ML ? 15 : 16; + public override int AosMaxDamage => Core.ML ? 19 : 18; + public override int AosSpeed => 25; + public override float MlSpeed => 4.25f; + + public override int OldStrengthReq => 20; + public override int OldMinDamage => 9; + public override int OldMaxDamage => 41; + public override int OldSpeed => 20; + + public override int DefMaxRange => 10; + + public override int InitMinHits => 31; + public override int InitMaxHits => 60; + + public override WeaponAnimation DefAnimation => WeaponAnimation.ShootBow; + + 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 (Weight == 7.0) + Weight = 6.0; + } } - - public Bow(Serial serial) : base(serial) - { - } - - public override int EffectID => 0xF42; - public override Type AmmoType => typeof(Arrow); - public override Item Ammo => new Arrow(); - - public override WeaponAbility PrimaryAbility => WeaponAbility.ParalyzingBlow; - public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike; - - public override int AosStrengthReq => 30; - public override int AosMinDamage => Core.ML ? 15 : 16; - public override int AosMaxDamage => Core.ML ? 19 : 18; - public override int AosSpeed => 25; - public override float MlSpeed => 4.25f; - - public override int OldStrengthReq => 20; - public override int OldMinDamage => 9; - public override int OldMaxDamage => 41; - public override int OldSpeed => 20; - - public override int DefMaxRange => 10; - - public override int InitMinHits => 31; - public override int InitMaxHits => 60; - - public override WeaponAnimation DefAnimation => WeaponAnimation.ShootBow; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 7.0) - Weight = 6.0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Ranged/CompositeBow.cs b/Projects/UOContent/Items/Weapons/Ranged/CompositeBow.cs index 4ab0e85ea..1f4eed122 100644 --- a/Projects/UOContent/Items/Weapons/Ranged/CompositeBow.cs +++ b/Projects/UOContent/Items/Weapons/Ranged/CompositeBow.cs @@ -2,53 +2,53 @@ using System; namespace Server.Items { - [Flippable(0x26C2, 0x26CC)] - public class CompositeBow : BaseRanged - { - [Constructible] - public CompositeBow() : base(0x26C2) => Weight = 5.0; - - public CompositeBow(Serial serial) : base(serial) + [Flippable(0x26C2, 0x26CC)] + public class CompositeBow : BaseRanged { + [Constructible] + public CompositeBow() : base(0x26C2) => Weight = 5.0; + + public CompositeBow(Serial serial) : base(serial) + { + } + + public override int EffectID => 0xF42; + public override Type AmmoType => typeof(Arrow); + public override Item Ammo => new Arrow(); + + public override WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore; + public override WeaponAbility SecondaryAbility => WeaponAbility.MovingShot; + + public override int AosStrengthReq => 45; + public override int AosMinDamage => Core.ML ? 13 : 15; + public override int AosMaxDamage => 17; + public override int AosSpeed => 25; + public override float MlSpeed => 4.00f; + + public override int OldStrengthReq => 45; + public override int OldMinDamage => 15; + public override int OldMaxDamage => 17; + public override int OldSpeed => 25; + + public override int DefMaxRange => 10; + + public override int InitMinHits => 31; + public override int InitMaxHits => 70; + + public override WeaponAnimation DefAnimation => WeaponAnimation.ShootBow; + + 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 int EffectID => 0xF42; - public override Type AmmoType => typeof(Arrow); - public override Item Ammo => new Arrow(); - - public override WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore; - public override WeaponAbility SecondaryAbility => WeaponAbility.MovingShot; - - public override int AosStrengthReq => 45; - public override int AosMinDamage => Core.ML ? 13 : 15; - public override int AosMaxDamage => 17; - public override int AosSpeed => 25; - public override float MlSpeed => 4.00f; - - public override int OldStrengthReq => 45; - public override int OldMinDamage => 15; - public override int OldMaxDamage => 17; - public override int OldSpeed => 25; - - public override int DefMaxRange => 10; - - public override int InitMinHits => 31; - public override int InitMaxHits => 70; - - public override WeaponAnimation DefAnimation => WeaponAnimation.ShootBow; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Ranged/Crossbow.cs b/Projects/UOContent/Items/Weapons/Ranged/Crossbow.cs index 6dc8c9432..27abf71e4 100644 --- a/Projects/UOContent/Items/Weapons/Ranged/Crossbow.cs +++ b/Projects/UOContent/Items/Weapons/Ranged/Crossbow.cs @@ -2,55 +2,55 @@ using System; namespace Server.Items { - [Flippable(0xF50, 0xF4F)] - public class Crossbow : BaseRanged - { - [Constructible] - public Crossbow() : base(0xF50) + [Flippable(0xF50, 0xF4F)] + public class Crossbow : BaseRanged { - Weight = 7.0; - Layer = Layer.TwoHanded; + [Constructible] + public Crossbow() : base(0xF50) + { + Weight = 7.0; + Layer = Layer.TwoHanded; + } + + public Crossbow(Serial serial) : base(serial) + { + } + + public override int EffectID => 0x1BFE; + public override Type AmmoType => typeof(Bolt); + public override Item Ammo => new Bolt(); + + public override WeaponAbility PrimaryAbility => WeaponAbility.ConcussionBlow; + public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike; + + public override int AosStrengthReq => 35; + public override int AosMinDamage => 18; + public override int AosMaxDamage => Core.ML ? 22 : 20; + public override int AosSpeed => 24; + public override float MlSpeed => 4.50f; + + public override int OldStrengthReq => 30; + public override int OldMinDamage => 8; + public override int OldMaxDamage => 43; + public override int OldSpeed => 18; + + public override int DefMaxRange => 8; + + public override int InitMinHits => 31; + public override int InitMaxHits => 80; + + 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 Crossbow(Serial serial) : base(serial) - { - } - - public override int EffectID => 0x1BFE; - public override Type AmmoType => typeof(Bolt); - public override Item Ammo => new Bolt(); - - public override WeaponAbility PrimaryAbility => WeaponAbility.ConcussionBlow; - public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike; - - public override int AosStrengthReq => 35; - public override int AosMinDamage => 18; - public override int AosMaxDamage => Core.ML ? 22 : 20; - public override int AosSpeed => 24; - public override float MlSpeed => 4.50f; - - public override int OldStrengthReq => 30; - public override int OldMinDamage => 8; - public override int OldMaxDamage => 43; - public override int OldSpeed => 18; - - public override int DefMaxRange => 8; - - public override int InitMinHits => 31; - public override int InitMaxHits => 80; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Ranged/FrozenLongbow.cs b/Projects/UOContent/Items/Weapons/Ranged/FrozenLongbow.cs index 6e4bb86d2..653d888ea 100644 --- a/Projects/UOContent/Items/Weapons/Ranged/FrozenLongbow.cs +++ b/Projects/UOContent/Items/Weapons/Ranged/FrozenLongbow.cs @@ -1,32 +1,32 @@ namespace Server.Items { - public class FrozenLongbow : ElvenCompositeLongbow - { - [Constructible] - public FrozenLongbow() + public class FrozenLongbow : ElvenCompositeLongbow { - Attributes.WeaponSpeed = -5; - Attributes.DefendChance = 10; + [Constructible] + public FrozenLongbow() + { + Attributes.WeaponSpeed = -5; + Attributes.DefendChance = 10; + } + + public FrozenLongbow(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073507; // frozen longbow + + 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(); + } } - - public FrozenLongbow(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073507; // frozen longbow - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Ranged/HeavyCrossbow.cs b/Projects/UOContent/Items/Weapons/Ranged/HeavyCrossbow.cs index 4bd90dd57..68627c463 100644 --- a/Projects/UOContent/Items/Weapons/Ranged/HeavyCrossbow.cs +++ b/Projects/UOContent/Items/Weapons/Ranged/HeavyCrossbow.cs @@ -2,55 +2,55 @@ using System; namespace Server.Items { - [Flippable(0x13FD, 0x13FC)] - public class HeavyCrossbow : BaseRanged - { - [Constructible] - public HeavyCrossbow() : base(0x13FD) + [Flippable(0x13FD, 0x13FC)] + public class HeavyCrossbow : BaseRanged { - Weight = 9.0; - Layer = Layer.TwoHanded; + [Constructible] + public HeavyCrossbow() : base(0x13FD) + { + Weight = 9.0; + Layer = Layer.TwoHanded; + } + + public HeavyCrossbow(Serial serial) : base(serial) + { + } + + public override int EffectID => 0x1BFE; + public override Type AmmoType => typeof(Bolt); + public override Item Ammo => new Bolt(); + + public override WeaponAbility PrimaryAbility => WeaponAbility.MovingShot; + public override WeaponAbility SecondaryAbility => WeaponAbility.Dismount; + + public override int AosStrengthReq => 80; + public override int AosMinDamage => Core.ML ? 20 : 19; + public override int AosMaxDamage => Core.ML ? 24 : 20; + public override int AosSpeed => 22; + public override float MlSpeed => 5.00f; + + public override int OldStrengthReq => 40; + public override int OldMinDamage => 11; + public override int OldMaxDamage => 56; + public override int OldSpeed => 10; + + public override int DefMaxRange => 8; + + public override int InitMinHits => 31; + public override int InitMaxHits => 100; + + 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 HeavyCrossbow(Serial serial) : base(serial) - { - } - - public override int EffectID => 0x1BFE; - public override Type AmmoType => typeof(Bolt); - public override Item Ammo => new Bolt(); - - public override WeaponAbility PrimaryAbility => WeaponAbility.MovingShot; - public override WeaponAbility SecondaryAbility => WeaponAbility.Dismount; - - public override int AosStrengthReq => 80; - public override int AosMinDamage => Core.ML ? 20 : 19; - public override int AosMaxDamage => Core.ML ? 24 : 20; - public override int AosSpeed => 22; - public override float MlSpeed => 5.00f; - - public override int OldStrengthReq => 40; - public override int OldMinDamage => 11; - public override int OldMaxDamage => 56; - public override int OldSpeed => 10; - - public override int DefMaxRange => 8; - - public override int InitMinHits => 31; - public override int InitMaxHits => 100; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Ranged/JukaBow.cs b/Projects/UOContent/Items/Weapons/Ranged/JukaBow.cs index a5dc23278..0ac8a4c0b 100644 --- a/Projects/UOContent/Items/Weapons/Ranged/JukaBow.cs +++ b/Projects/UOContent/Items/Weapons/Ranged/JukaBow.cs @@ -2,90 +2,91 @@ using Server.Targeting; namespace Server.Items { - [Flippable(0x13B2, 0x13B1)] - public class JukaBow : Bow - { - [Constructible] - public JukaBow() + [Flippable(0x13B2, 0x13B1)] + public class JukaBow : Bow { + [Constructible] + public JukaBow() + { + } + + public JukaBow(Serial serial) : base(serial) + { + } + + public override int AosStrengthReq => 80; + public override int AosDexterityReq => 80; + + public override int OldStrengthReq => 80; + public override int OldDexterityReq => 80; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsModified => Hue == 0x453; + + public override void OnDoubleClick(Mobile from) + { + if (IsModified) + { + from.SendMessage("That has already been modified."); + } + else if (!IsChildOf(from.Backpack)) + { + from.SendMessage("This must be in your backpack to modify it."); + } + else if (from.Skills.Fletching.Base < 100.0) + { + from.SendMessage("Only a grandmaster bowcrafter can modify this weapon."); + } + else + { + from.BeginTarget(2, false, TargetFlags.None, OnTargetGears); + from.SendMessage("Select the gears you wish to use."); + } + } + + public void OnTargetGears(Mobile from, object targ) + { + if (!(targ is Gears g) || !g.IsChildOf(from.Backpack)) + { + from.SendMessage( + "Those are not gears." + ); // Apparently gears that aren't in your backpack aren't really gears at all. :-( + } + else if (IsModified) + { + from.SendMessage("That has already been modified."); + } + else if (!IsChildOf(from.Backpack)) + { + from.SendMessage("This must be in your backpack to modify it."); + } + else if (from.Skills.Fletching.Base < 100.0) + { + from.SendMessage("Only a grandmaster bowcrafter can modify this weapon."); + } + else + { + g.Consume(); + + Hue = 0x453; + Slayer = (SlayerName)Utility.Random(2, 25); + + from.SendMessage("You modify it."); + } + } + + 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 JukaBow(Serial serial) : base(serial) - { - } - - public override int AosStrengthReq => 80; - public override int AosDexterityReq => 80; - - public override int OldStrengthReq => 80; - public override int OldDexterityReq => 80; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsModified => Hue == 0x453; - - public override void OnDoubleClick(Mobile from) - { - if (IsModified) - { - from.SendMessage("That has already been modified."); - } - else if (!IsChildOf(from.Backpack)) - { - from.SendMessage("This must be in your backpack to modify it."); - } - else if (from.Skills.Fletching.Base < 100.0) - { - from.SendMessage("Only a grandmaster bowcrafter can modify this weapon."); - } - else - { - from.BeginTarget(2, false, TargetFlags.None, OnTargetGears); - from.SendMessage("Select the gears you wish to use."); - } - } - - public void OnTargetGears(Mobile from, object targ) - { - if (!(targ is Gears g) || !g.IsChildOf(from.Backpack)) - { - from.SendMessage( - "Those are not gears."); // Apparently gears that aren't in your backpack aren't really gears at all. :-( - } - else if (IsModified) - { - from.SendMessage("That has already been modified."); - } - else if (!IsChildOf(from.Backpack)) - { - from.SendMessage("This must be in your backpack to modify it."); - } - else if (from.Skills.Fletching.Base < 100.0) - { - from.SendMessage("Only a grandmaster bowcrafter can modify this weapon."); - } - else - { - g.Consume(); - - Hue = 0x453; - Slayer = (SlayerName)Utility.Random(2, 25); - - from.SendMessage("You modify it."); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Ranged/LightweightShortbow.cs b/Projects/UOContent/Items/Weapons/Ranged/LightweightShortbow.cs index 79be2ccb6..fd1c9aa85 100644 --- a/Projects/UOContent/Items/Weapons/Ranged/LightweightShortbow.cs +++ b/Projects/UOContent/Items/Weapons/Ranged/LightweightShortbow.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class LightweightShortbow : MagicalShortbow - { - [Constructible] - public LightweightShortbow() => Balanced = true; - - public LightweightShortbow(Serial serial) : base(serial) + public class LightweightShortbow : MagicalShortbow { + [Constructible] + public LightweightShortbow() => Balanced = true; + + public LightweightShortbow(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073510; // lightweight shortbow + + 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(); + } } - - public override int LabelNumber => 1073510; // lightweight shortbow - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Ranged/LongbowOfMight.cs b/Projects/UOContent/Items/Weapons/Ranged/LongbowOfMight.cs index 67a3db3c6..d7aca76e5 100644 --- a/Projects/UOContent/Items/Weapons/Ranged/LongbowOfMight.cs +++ b/Projects/UOContent/Items/Weapons/Ranged/LongbowOfMight.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class LongbowOfMight : ElvenCompositeLongbow - { - [Constructible] - public LongbowOfMight() => Attributes.WeaponDamage = 5; - - public LongbowOfMight(Serial serial) : base(serial) + public class LongbowOfMight : ElvenCompositeLongbow { + [Constructible] + public LongbowOfMight() => Attributes.WeaponDamage = 5; + + public LongbowOfMight(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073508; // longbow of might + + 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(); + } } - - public override int LabelNumber => 1073508; // longbow of might - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Ranged/MysticalShortbow.cs b/Projects/UOContent/Items/Weapons/Ranged/MysticalShortbow.cs index 8124e083f..428589ff0 100644 --- a/Projects/UOContent/Items/Weapons/Ranged/MysticalShortbow.cs +++ b/Projects/UOContent/Items/Weapons/Ranged/MysticalShortbow.cs @@ -1,32 +1,32 @@ namespace Server.Items { - public class MysticalShortbow : MagicalShortbow - { - [Constructible] - public MysticalShortbow() + public class MysticalShortbow : MagicalShortbow { - Attributes.SpellChanneling = 1; - Attributes.CastSpeed = -1; + [Constructible] + public MysticalShortbow() + { + Attributes.SpellChanneling = 1; + Attributes.CastSpeed = -1; + } + + public MysticalShortbow(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073511; // mystical shortbow + + 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(); + } } - - public MysticalShortbow(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073511; // mystical shortbow - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Ranged/RangersShortbow.cs b/Projects/UOContent/Items/Weapons/Ranged/RangersShortbow.cs index 1f28c27ea..19ad619e6 100644 --- a/Projects/UOContent/Items/Weapons/Ranged/RangersShortbow.cs +++ b/Projects/UOContent/Items/Weapons/Ranged/RangersShortbow.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class RangersShortbow : MagicalShortbow - { - [Constructible] - public RangersShortbow() => Attributes.WeaponSpeed = 5; - - public RangersShortbow(Serial serial) : base(serial) + public class RangersShortbow : MagicalShortbow { + [Constructible] + public RangersShortbow() => Attributes.WeaponSpeed = 5; + + public RangersShortbow(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073509; // ranger's shortbow + + 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(); + } } - - public override int LabelNumber => 1073509; // ranger's shortbow - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Ranged/RepeatingCrossbow.cs b/Projects/UOContent/Items/Weapons/Ranged/RepeatingCrossbow.cs index dc9625ec4..3b4bdeae6 100644 --- a/Projects/UOContent/Items/Weapons/Ranged/RepeatingCrossbow.cs +++ b/Projects/UOContent/Items/Weapons/Ranged/RepeatingCrossbow.cs @@ -2,51 +2,51 @@ using System; namespace Server.Items { - [Flippable(0x26C3, 0x26CD)] - public class RepeatingCrossbow : BaseRanged - { - [Constructible] - public RepeatingCrossbow() : base(0x26C3) => Weight = 6.0; - - public RepeatingCrossbow(Serial serial) : base(serial) + [Flippable(0x26C3, 0x26CD)] + public class RepeatingCrossbow : BaseRanged { + [Constructible] + public RepeatingCrossbow() : base(0x26C3) => Weight = 6.0; + + public RepeatingCrossbow(Serial serial) : base(serial) + { + } + + public override int EffectID => 0x1BFE; + public override Type AmmoType => typeof(Bolt); + public override Item Ammo => new Bolt(); + + public override WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike; + public override WeaponAbility SecondaryAbility => WeaponAbility.MovingShot; + + public override int AosStrengthReq => 30; + public override int AosMinDamage => Core.ML ? 8 : 10; + public override int AosMaxDamage => 12; + public override int AosSpeed => 41; + public override float MlSpeed => 2.75f; + + public override int OldStrengthReq => 30; + public override int OldMinDamage => 10; + public override int OldMaxDamage => 12; + public override int OldSpeed => 41; + + public override int DefMaxRange => 7; + + public override int InitMinHits => 31; + public override int InitMaxHits => 80; + + 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 int EffectID => 0x1BFE; - public override Type AmmoType => typeof(Bolt); - public override Item Ammo => new Bolt(); - - public override WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike; - public override WeaponAbility SecondaryAbility => WeaponAbility.MovingShot; - - public override int AosStrengthReq => 30; - public override int AosMinDamage => Core.ML ? 8 : 10; - public override int AosMaxDamage => 12; - public override int AosSpeed => 41; - public override float MlSpeed => 2.75f; - - public override int OldStrengthReq => 30; - public override int OldMinDamage => 10; - public override int OldMaxDamage => 12; - public override int OldSpeed => 41; - - public override int DefMaxRange => 7; - - public override int InitMinHits => 31; - public override int InitMaxHits => 80; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Ranged/SlayerLongbow.cs b/Projects/UOContent/Items/Weapons/Ranged/SlayerLongbow.cs index 9bbc4b329..620cefd5d 100644 --- a/Projects/UOContent/Items/Weapons/Ranged/SlayerLongbow.cs +++ b/Projects/UOContent/Items/Weapons/Ranged/SlayerLongbow.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class SlayerLongbow : ElvenCompositeLongbow - { - [Constructible] - public SlayerLongbow() => Slayer2 = (SlayerName)Utility.RandomMinMax(1, 27); - - public SlayerLongbow(Serial serial) : base(serial) + public class SlayerLongbow : ElvenCompositeLongbow { + [Constructible] + public SlayerLongbow() => Slayer2 = (SlayerName)Utility.RandomMinMax(1, 27); + + public SlayerLongbow(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073506; // slayer longbow + + 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(); + } } - - public override int LabelNumber => 1073506; // slayer longbow - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/SE Weapons/Bokuto.cs b/Projects/UOContent/Items/Weapons/SE Weapons/Bokuto.cs index d802c7d39..8e60922ba 100644 --- a/Projects/UOContent/Items/Weapons/SE Weapons/Bokuto.cs +++ b/Projects/UOContent/Items/Weapons/SE Weapons/Bokuto.cs @@ -1,47 +1,47 @@ namespace Server.Items { - [Flippable(0x27A8, 0x27F3)] - public class Bokuto : BaseSword - { - [Constructible] - public Bokuto() : base(0x27A8) => Weight = 7.0; - - public Bokuto(Serial serial) : base(serial) + [Flippable(0x27A8, 0x27F3)] + public class Bokuto : BaseSword { + [Constructible] + public Bokuto() : base(0x27A8) => Weight = 7.0; + + public Bokuto(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.Feint; + public override WeaponAbility SecondaryAbility => WeaponAbility.NerveStrike; + + public override int AosStrengthReq => 20; + public override int AosMinDamage => 9; + public override int AosMaxDamage => 11; + public override int AosSpeed => 53; + public override float MlSpeed => 2.00f; + + public override int OldStrengthReq => 20; + public override int OldMinDamage => 9; + public override int OldMaxDamage => 11; + public override int OldSpeed => 53; + + public override int DefHitSound => 0x536; + public override int DefMissSound => 0x23A; + + public override int InitMinHits => 25; + public override int InitMaxHits => 50; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.Feint; - public override WeaponAbility SecondaryAbility => WeaponAbility.NerveStrike; - - public override int AosStrengthReq => 20; - public override int AosMinDamage => 9; - public override int AosMaxDamage => 11; - public override int AosSpeed => 53; - public override float MlSpeed => 2.00f; - - public override int OldStrengthReq => 20; - public override int OldMinDamage => 9; - public override int OldMaxDamage => 11; - public override int OldSpeed => 53; - - public override int DefHitSound => 0x536; - public override int DefMissSound => 0x23A; - - public override int InitMinHits => 25; - public override int InitMaxHits => 50; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/SE Weapons/Daisho.cs b/Projects/UOContent/Items/Weapons/SE Weapons/Daisho.cs index adaca010e..75e920716 100644 --- a/Projects/UOContent/Items/Weapons/SE Weapons/Daisho.cs +++ b/Projects/UOContent/Items/Weapons/SE Weapons/Daisho.cs @@ -1,51 +1,51 @@ namespace Server.Items { - [Flippable(0x27A9, 0x27F4)] - public class Daisho : BaseSword - { - [Constructible] - public Daisho() : base(0x27A9) + [Flippable(0x27A9, 0x27F4)] + public class Daisho : BaseSword { - Weight = 8.0; - Layer = Layer.TwoHanded; + [Constructible] + public Daisho() : base(0x27A9) + { + Weight = 8.0; + Layer = Layer.TwoHanded; + } + + public Daisho(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.Feint; + public override WeaponAbility SecondaryAbility => WeaponAbility.DoubleStrike; + + public override int AosStrengthReq => 40; + public override int AosMinDamage => 13; + public override int AosMaxDamage => 15; + public override int AosSpeed => 40; + public override float MlSpeed => 2.75f; + + public override int OldStrengthReq => 40; + public override int OldMinDamage => 13; + public override int OldMaxDamage => 15; + public override int OldSpeed => 40; + + public override int DefHitSound => 0x23B; + public override int DefMissSound => 0x23A; + + public override int InitMinHits => 45; + public override int InitMaxHits => 65; + + 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 Daisho(Serial serial) : base(serial) - { - } - - public override WeaponAbility PrimaryAbility => WeaponAbility.Feint; - public override WeaponAbility SecondaryAbility => WeaponAbility.DoubleStrike; - - public override int AosStrengthReq => 40; - public override int AosMinDamage => 13; - public override int AosMaxDamage => 15; - public override int AosSpeed => 40; - public override float MlSpeed => 2.75f; - - public override int OldStrengthReq => 40; - public override int OldMinDamage => 13; - public override int OldMaxDamage => 15; - public override int OldSpeed => 40; - - public override int DefHitSound => 0x23B; - public override int DefMissSound => 0x23A; - - public override int InitMinHits => 45; - public override int InitMaxHits => 65; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/SE Weapons/Kama.cs b/Projects/UOContent/Items/Weapons/SE Weapons/Kama.cs index 509184564..97af898fa 100644 --- a/Projects/UOContent/Items/Weapons/SE Weapons/Kama.cs +++ b/Projects/UOContent/Items/Weapons/SE Weapons/Kama.cs @@ -1,55 +1,55 @@ namespace Server.Items { - [Flippable(0x27AD, 0x27F8)] - public class Kama : BaseKnife - { - [Constructible] - public Kama() : base(0x27AD) + [Flippable(0x27AD, 0x27F8)] + public class Kama : BaseKnife { - Weight = 7.0; - Layer = Layer.TwoHanded; + [Constructible] + public Kama() : base(0x27AD) + { + Weight = 7.0; + Layer = Layer.TwoHanded; + } + + public Kama(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.WhirlwindAttack; + public override WeaponAbility SecondaryAbility => WeaponAbility.DefenseMastery; + + public override int AosStrengthReq => 15; + public override int AosMinDamage => 9; + public override int AosMaxDamage => 11; + public override int AosSpeed => 55; + public override float MlSpeed => 2.00f; + + public override int OldStrengthReq => 15; + public override int OldMinDamage => 9; + public override int OldMaxDamage => 11; + public override int OldSpeed => 55; + + public override int DefHitSound => 0x232; + public override int DefMissSound => 0x238; + + public override int InitMinHits => 35; + public override int InitMaxHits => 60; + + public override SkillName DefSkill => SkillName.Fencing; + public override WeaponType DefType => WeaponType.Piercing; + public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H; + + 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 Kama(Serial serial) : base(serial) - { - } - - public override WeaponAbility PrimaryAbility => WeaponAbility.WhirlwindAttack; - public override WeaponAbility SecondaryAbility => WeaponAbility.DefenseMastery; - - public override int AosStrengthReq => 15; - public override int AosMinDamage => 9; - public override int AosMaxDamage => 11; - public override int AosSpeed => 55; - public override float MlSpeed => 2.00f; - - public override int OldStrengthReq => 15; - public override int OldMinDamage => 9; - public override int OldMaxDamage => 11; - public override int OldSpeed => 55; - - public override int DefHitSound => 0x232; - public override int DefMissSound => 0x238; - - public override int InitMinHits => 35; - public override int InitMaxHits => 60; - - public override SkillName DefSkill => SkillName.Fencing; - public override WeaponType DefType => WeaponType.Piercing; - public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/SE Weapons/Lajatang.cs b/Projects/UOContent/Items/Weapons/SE Weapons/Lajatang.cs index b15fa5aad..515f961a9 100644 --- a/Projects/UOContent/Items/Weapons/SE Weapons/Lajatang.cs +++ b/Projects/UOContent/Items/Weapons/SE Weapons/Lajatang.cs @@ -1,55 +1,55 @@ namespace Server.Items { - [Flippable(0x27A7, 0x27F2)] - public class Lajatang : BaseKnife - { - [Constructible] - public Lajatang() : base(0x27A7) + [Flippable(0x27A7, 0x27F2)] + public class Lajatang : BaseKnife { - Weight = 12.0; - Layer = Layer.TwoHanded; + [Constructible] + public Lajatang() : base(0x27A7) + { + Weight = 12.0; + Layer = Layer.TwoHanded; + } + + public Lajatang(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.DefenseMastery; + public override WeaponAbility SecondaryAbility => WeaponAbility.FrenziedWhirlwind; + + public override int AosStrengthReq => 65; + public override int AosMinDamage => 16; + public override int AosMaxDamage => 18; + public override int AosSpeed => 32; + public override float MlSpeed => 3.50f; + + public override int OldStrengthReq => 65; + public override int OldMinDamage => 16; + public override int OldMaxDamage => 18; + public override int OldSpeed => 55; + + public override int DefHitSound => 0x232; + public override int DefMissSound => 0x238; + + public override int InitMinHits => 90; + public override int InitMaxHits => 95; + + public override SkillName DefSkill => SkillName.Fencing; + public override WeaponType DefType => WeaponType.Piercing; + public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H; + + 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 Lajatang(Serial serial) : base(serial) - { - } - - public override WeaponAbility PrimaryAbility => WeaponAbility.DefenseMastery; - public override WeaponAbility SecondaryAbility => WeaponAbility.FrenziedWhirlwind; - - public override int AosStrengthReq => 65; - public override int AosMinDamage => 16; - public override int AosMaxDamage => 18; - public override int AosSpeed => 32; - public override float MlSpeed => 3.50f; - - public override int OldStrengthReq => 65; - public override int OldMinDamage => 16; - public override int OldMaxDamage => 18; - public override int OldSpeed => 55; - - public override int DefHitSound => 0x232; - public override int DefMissSound => 0x238; - - public override int InitMinHits => 90; - public override int InitMaxHits => 95; - - public override SkillName DefSkill => SkillName.Fencing; - public override WeaponType DefType => WeaponType.Piercing; - public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/SE Weapons/NoDachi.cs b/Projects/UOContent/Items/Weapons/SE Weapons/NoDachi.cs index af5e25fad..865b14da1 100644 --- a/Projects/UOContent/Items/Weapons/SE Weapons/NoDachi.cs +++ b/Projects/UOContent/Items/Weapons/SE Weapons/NoDachi.cs @@ -1,51 +1,51 @@ namespace Server.Items { - [Flippable(0x27A2, 0x27ED)] - public class NoDachi : BaseSword - { - [Constructible] - public NoDachi() : base(0x27A2) + [Flippable(0x27A2, 0x27ED)] + public class NoDachi : BaseSword { - Weight = 10.0; - Layer = Layer.TwoHanded; + [Constructible] + public NoDachi() : base(0x27A2) + { + Weight = 10.0; + Layer = Layer.TwoHanded; + } + + public NoDachi(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow; + public override WeaponAbility SecondaryAbility => WeaponAbility.RidingSwipe; + + public override int AosStrengthReq => 40; + public override int AosMinDamage => 16; + public override int AosMaxDamage => 18; + public override int AosSpeed => 35; + public override float MlSpeed => 3.50f; + + public override int OldStrengthReq => 40; + public override int OldMinDamage => 16; + public override int OldMaxDamage => 18; + public override int OldSpeed => 35; + + public override int DefHitSound => 0x23B; + public override int DefMissSound => 0x23A; + + public override int InitMinHits => 31; + public override int InitMaxHits => 90; + + 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 NoDachi(Serial serial) : base(serial) - { - } - - public override WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow; - public override WeaponAbility SecondaryAbility => WeaponAbility.RidingSwipe; - - public override int AosStrengthReq => 40; - public override int AosMinDamage => 16; - public override int AosMaxDamage => 18; - public override int AosSpeed => 35; - public override float MlSpeed => 3.50f; - - public override int OldStrengthReq => 40; - public override int OldMinDamage => 16; - public override int OldMaxDamage => 18; - public override int OldSpeed => 35; - - public override int DefHitSound => 0x23B; - public override int DefMissSound => 0x23A; - - public override int InitMinHits => 31; - public override int InitMaxHits => 90; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/SE Weapons/Nunchaku.cs b/Projects/UOContent/Items/Weapons/SE Weapons/Nunchaku.cs index 3e8632ca6..a43c7f4c5 100644 --- a/Projects/UOContent/Items/Weapons/SE Weapons/Nunchaku.cs +++ b/Projects/UOContent/Items/Weapons/SE Weapons/Nunchaku.cs @@ -1,47 +1,47 @@ namespace Server.Items { - [Flippable(0x27AE, 0x27F9)] - public class Nunchaku : BaseBashing - { - [Constructible] - public Nunchaku() : base(0x27AE) => Weight = 5.0; - - public Nunchaku(Serial serial) : base(serial) + [Flippable(0x27AE, 0x27F9)] + public class Nunchaku : BaseBashing { + [Constructible] + public Nunchaku() : base(0x27AE) => Weight = 5.0; + + public Nunchaku(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.Block; + public override WeaponAbility SecondaryAbility => WeaponAbility.Feint; + + public override int AosStrengthReq => 15; + public override int AosMinDamage => 11; + public override int AosMaxDamage => 13; + public override int AosSpeed => 47; + public override float MlSpeed => 2.50f; + + public override int OldStrengthReq => 15; + public override int OldMinDamage => 11; + public override int OldMaxDamage => 13; + public override int OldSpeed => 47; + + public override int DefHitSound => 0x535; + public override int DefMissSound => 0x239; + + public override int InitMinHits => 40; + public override int InitMaxHits => 55; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.Block; - public override WeaponAbility SecondaryAbility => WeaponAbility.Feint; - - public override int AosStrengthReq => 15; - public override int AosMinDamage => 11; - public override int AosMaxDamage => 13; - public override int AosSpeed => 47; - public override float MlSpeed => 2.50f; - - public override int OldStrengthReq => 15; - public override int OldMinDamage => 11; - public override int OldMaxDamage => 13; - public override int OldSpeed => 47; - - public override int DefHitSound => 0x535; - public override int DefMissSound => 0x239; - - public override int InitMinHits => 40; - public override int InitMaxHits => 55; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/SE Weapons/Sai.cs b/Projects/UOContent/Items/Weapons/SE Weapons/Sai.cs index 4b8b8fdeb..eecc23a32 100644 --- a/Projects/UOContent/Items/Weapons/SE Weapons/Sai.cs +++ b/Projects/UOContent/Items/Weapons/SE Weapons/Sai.cs @@ -1,55 +1,55 @@ namespace Server.Items { - [Flippable(0x27AF, 0x27FA)] - public class Sai : BaseKnife - { - [Constructible] - public Sai() : base(0x27AF) + [Flippable(0x27AF, 0x27FA)] + public class Sai : BaseKnife { - Weight = 7.0; - Layer = Layer.TwoHanded; + [Constructible] + public Sai() : base(0x27AF) + { + Weight = 7.0; + Layer = Layer.TwoHanded; + } + + public Sai(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.Block; + public override WeaponAbility SecondaryAbility => WeaponAbility.ArmorPierce; + + public override int AosStrengthReq => 15; + public override int AosMinDamage => 9; + public override int AosMaxDamage => 11; + public override int AosSpeed => 55; + public override float MlSpeed => 2.00f; + + public override int OldStrengthReq => 15; + public override int OldMinDamage => 9; + public override int OldMaxDamage => 11; + public override int OldSpeed => 55; + + public override int DefHitSound => 0x23C; + public override int DefMissSound => 0x232; + + public override int InitMinHits => 55; + public override int InitMaxHits => 60; + + public override SkillName DefSkill => SkillName.Fencing; + public override WeaponType DefType => WeaponType.Piercing; + public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H; + + 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 Sai(Serial serial) : base(serial) - { - } - - public override WeaponAbility PrimaryAbility => WeaponAbility.Block; - public override WeaponAbility SecondaryAbility => WeaponAbility.ArmorPierce; - - public override int AosStrengthReq => 15; - public override int AosMinDamage => 9; - public override int AosMaxDamage => 11; - public override int AosSpeed => 55; - public override float MlSpeed => 2.00f; - - public override int OldStrengthReq => 15; - public override int OldMinDamage => 9; - public override int OldMaxDamage => 11; - public override int OldSpeed => 55; - - public override int DefHitSound => 0x23C; - public override int DefMissSound => 0x232; - - public override int InitMinHits => 55; - public override int InitMaxHits => 60; - - public override SkillName DefSkill => SkillName.Fencing; - public override WeaponType DefType => WeaponType.Piercing; - public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/SE Weapons/Tekagi.cs b/Projects/UOContent/Items/Weapons/SE Weapons/Tekagi.cs index a45a758cd..f4b05b372 100644 --- a/Projects/UOContent/Items/Weapons/SE Weapons/Tekagi.cs +++ b/Projects/UOContent/Items/Weapons/SE Weapons/Tekagi.cs @@ -1,55 +1,55 @@ namespace Server.Items { - [Flippable(0x27Ab, 0x27F6)] - public class Tekagi : BaseKnife - { - [Constructible] - public Tekagi() : base(0x27AB) + [Flippable(0x27Ab, 0x27F6)] + public class Tekagi : BaseKnife { - Weight = 5.0; - Layer = Layer.TwoHanded; + [Constructible] + public Tekagi() : base(0x27AB) + { + Weight = 5.0; + Layer = Layer.TwoHanded; + } + + public Tekagi(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.DualWield; + public override WeaponAbility SecondaryAbility => WeaponAbility.TalonStrike; + + public override int AosStrengthReq => 10; + public override int AosMinDamage => 10; + public override int AosMaxDamage => 12; + public override int AosSpeed => 53; + public override float MlSpeed => 2.00f; + + public override int OldStrengthReq => 10; + public override int OldMinDamage => 10; + public override int OldMaxDamage => 12; + public override int OldSpeed => 53; + + public override int DefHitSound => 0x238; + public override int DefMissSound => 0x232; + + public override int InitMinHits => 35; + public override int InitMaxHits => 60; + + public override SkillName DefSkill => SkillName.Fencing; + public override WeaponType DefType => WeaponType.Piercing; + public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H; + + 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 Tekagi(Serial serial) : base(serial) - { - } - - public override WeaponAbility PrimaryAbility => WeaponAbility.DualWield; - public override WeaponAbility SecondaryAbility => WeaponAbility.TalonStrike; - - public override int AosStrengthReq => 10; - public override int AosMinDamage => 10; - public override int AosMaxDamage => 12; - public override int AosSpeed => 53; - public override float MlSpeed => 2.00f; - - public override int OldStrengthReq => 10; - public override int OldMinDamage => 10; - public override int OldMaxDamage => 12; - public override int OldSpeed => 53; - - public override int DefHitSound => 0x238; - public override int DefMissSound => 0x232; - - public override int InitMinHits => 35; - public override int InitMaxHits => 60; - - public override SkillName DefSkill => SkillName.Fencing; - public override WeaponType DefType => WeaponType.Piercing; - public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/SE Weapons/Tessen.cs b/Projects/UOContent/Items/Weapons/SE Weapons/Tessen.cs index 80f50621f..e57118a81 100644 --- a/Projects/UOContent/Items/Weapons/SE Weapons/Tessen.cs +++ b/Projects/UOContent/Items/Weapons/SE Weapons/Tessen.cs @@ -1,53 +1,53 @@ namespace Server.Items { - [Flippable(0x27A3, 0x27EE)] - public class Tessen : BaseBashing - { - [Constructible] - public Tessen() : base(0x27A3) + [Flippable(0x27A3, 0x27EE)] + public class Tessen : BaseBashing { - Weight = 6.0; - Layer = Layer.TwoHanded; + [Constructible] + public Tessen() : base(0x27A3) + { + Weight = 6.0; + Layer = Layer.TwoHanded; + } + + public Tessen(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.Feint; + public override WeaponAbility SecondaryAbility => WeaponAbility.Block; + + public override int AosStrengthReq => 10; + public override int AosMinDamage => 10; + public override int AosMaxDamage => 12; + public override int AosSpeed => 50; + public override float MlSpeed => 2.00f; + + public override int OldStrengthReq => 10; + public override int OldMinDamage => 10; + public override int OldMaxDamage => 12; + public override int OldSpeed => 50; + + public override int DefHitSound => 0x232; + public override int DefMissSound => 0x238; + + public override int InitMinHits => 55; + public override int InitMaxHits => 60; + + public override WeaponAnimation DefAnimation => WeaponAnimation.Bash2H; + + 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 Tessen(Serial serial) : base(serial) - { - } - - public override WeaponAbility PrimaryAbility => WeaponAbility.Feint; - public override WeaponAbility SecondaryAbility => WeaponAbility.Block; - - public override int AosStrengthReq => 10; - public override int AosMinDamage => 10; - public override int AosMaxDamage => 12; - public override int AosSpeed => 50; - public override float MlSpeed => 2.00f; - - public override int OldStrengthReq => 10; - public override int OldMinDamage => 10; - public override int OldMaxDamage => 12; - public override int OldSpeed => 50; - - public override int DefHitSound => 0x232; - public override int DefMissSound => 0x238; - - public override int InitMinHits => 55; - public override int InitMaxHits => 60; - - public override WeaponAnimation DefAnimation => WeaponAnimation.Bash2H; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/SE Weapons/Tetsubo.cs b/Projects/UOContent/Items/Weapons/SE Weapons/Tetsubo.cs index db058e778..c9e182b15 100644 --- a/Projects/UOContent/Items/Weapons/SE Weapons/Tetsubo.cs +++ b/Projects/UOContent/Items/Weapons/SE Weapons/Tetsubo.cs @@ -1,53 +1,53 @@ namespace Server.Items { - [Flippable(0x27A6, 0x27F1)] - public class Tetsubo : BaseBashing - { - [Constructible] - public Tetsubo() : base(0x27A6) + [Flippable(0x27A6, 0x27F1)] + public class Tetsubo : BaseBashing { - Weight = 8.0; - Layer = Layer.TwoHanded; + [Constructible] + public Tetsubo() : base(0x27A6) + { + Weight = 8.0; + Layer = Layer.TwoHanded; + } + + public Tetsubo(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.FrenziedWhirlwind; + public override WeaponAbility SecondaryAbility => WeaponAbility.CrushingBlow; + + public override int AosStrengthReq => 35; + public override int AosMinDamage => 12; + public override int AosMaxDamage => 14; + public override int AosSpeed => 45; + public override float MlSpeed => 2.50f; + + public override int OldStrengthReq => 35; + public override int OldMinDamage => 12; + public override int OldMaxDamage => 14; + public override int OldSpeed => 45; + + public override int DefHitSound => 0x233; + public override int DefMissSound => 0x238; + + public override int InitMinHits => 60; + public override int InitMaxHits => 65; + + public override WeaponAnimation DefAnimation => WeaponAnimation.Bash2H; + + 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 Tetsubo(Serial serial) : base(serial) - { - } - - public override WeaponAbility PrimaryAbility => WeaponAbility.FrenziedWhirlwind; - public override WeaponAbility SecondaryAbility => WeaponAbility.CrushingBlow; - - public override int AosStrengthReq => 35; - public override int AosMinDamage => 12; - public override int AosMaxDamage => 14; - public override int AosSpeed => 45; - public override float MlSpeed => 2.50f; - - public override int OldStrengthReq => 35; - public override int OldMinDamage => 12; - public override int OldMaxDamage => 14; - public override int OldSpeed => 45; - - public override int DefHitSound => 0x233; - public override int DefMissSound => 0x238; - - public override int InitMinHits => 60; - public override int InitMaxHits => 65; - - public override WeaponAnimation DefAnimation => WeaponAnimation.Bash2H; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/SE Weapons/Wakizashi.cs b/Projects/UOContent/Items/Weapons/SE Weapons/Wakizashi.cs index 58b2c2449..8c56960d8 100644 --- a/Projects/UOContent/Items/Weapons/SE Weapons/Wakizashi.cs +++ b/Projects/UOContent/Items/Weapons/SE Weapons/Wakizashi.cs @@ -1,51 +1,51 @@ namespace Server.Items { - [Flippable(0x27A4, 0x27EF)] - public class Wakizashi : BaseSword - { - [Constructible] - public Wakizashi() : base(0x27A4) + [Flippable(0x27A4, 0x27EF)] + public class Wakizashi : BaseSword { - Weight = 5.0; - Layer = Layer.OneHanded; + [Constructible] + public Wakizashi() : base(0x27A4) + { + Weight = 5.0; + Layer = Layer.OneHanded; + } + + public Wakizashi(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.FrenziedWhirlwind; + public override WeaponAbility SecondaryAbility => WeaponAbility.DoubleStrike; + + public override int AosStrengthReq => 20; + public override int AosMinDamage => 11; + public override int AosMaxDamage => 13; + public override int AosSpeed => 44; + public override float MlSpeed => 2.50f; + + public override int OldStrengthReq => 20; + public override int OldMinDamage => 11; + public override int OldMaxDamage => 13; + public override int OldSpeed => 44; + + public override int DefHitSound => 0x23B; + public override int DefMissSound => 0x23A; + + public override int InitMinHits => 45; + public override int InitMaxHits => 50; + + 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 Wakizashi(Serial serial) : base(serial) - { - } - - public override WeaponAbility PrimaryAbility => WeaponAbility.FrenziedWhirlwind; - public override WeaponAbility SecondaryAbility => WeaponAbility.DoubleStrike; - - public override int AosStrengthReq => 20; - public override int AosMinDamage => 11; - public override int AosMaxDamage => 13; - public override int AosSpeed => 44; - public override float MlSpeed => 2.50f; - - public override int OldStrengthReq => 20; - public override int OldMinDamage => 11; - public override int OldMaxDamage => 13; - public override int OldSpeed => 44; - - public override int DefHitSound => 0x23B; - public override int DefMissSound => 0x23A; - - public override int InitMinHits => 45; - public override int InitMaxHits => 50; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/SE Weapons/Yumi.cs b/Projects/UOContent/Items/Weapons/SE Weapons/Yumi.cs index c5fd4ae22..1a8d06931 100644 --- a/Projects/UOContent/Items/Weapons/SE Weapons/Yumi.cs +++ b/Projects/UOContent/Items/Weapons/SE Weapons/Yumi.cs @@ -2,60 +2,60 @@ using System; namespace Server.Items { - [Flippable(0x27A5, 0x27F0)] - public class Yumi : BaseRanged - { - [Constructible] - public Yumi() : base(0x27A5) + [Flippable(0x27A5, 0x27F0)] + public class Yumi : BaseRanged { - Weight = 9.0; - Layer = Layer.TwoHanded; + [Constructible] + public Yumi() : base(0x27A5) + { + Weight = 9.0; + Layer = Layer.TwoHanded; + } + + public Yumi(Serial serial) : base(serial) + { + } + + public override int EffectID => 0xF42; + public override Type AmmoType => typeof(Arrow); + public override Item Ammo => new Arrow(); + + public override WeaponAbility PrimaryAbility => WeaponAbility.ArmorPierce; + public override WeaponAbility SecondaryAbility => WeaponAbility.DoubleShot; + + public override int AosStrengthReq => 35; + public override int AosMinDamage => Core.ML ? 16 : 18; + public override int AosMaxDamage => 20; + public override int AosSpeed => 25; + public override float MlSpeed => 4.5f; + + public override int OldStrengthReq => 35; + public override int OldMinDamage => 18; + public override int OldMaxDamage => 20; + public override int OldSpeed => 25; + + public override int DefMaxRange => 10; + + public override int InitMinHits => 55; + public override int InitMaxHits => 60; + + public override WeaponAnimation DefAnimation => WeaponAnimation.ShootBow; + + 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 (Weight == 7.0) + Weight = 6.0; + } } - - public Yumi(Serial serial) : base(serial) - { - } - - public override int EffectID => 0xF42; - public override Type AmmoType => typeof(Arrow); - public override Item Ammo => new Arrow(); - - public override WeaponAbility PrimaryAbility => WeaponAbility.ArmorPierce; - public override WeaponAbility SecondaryAbility => WeaponAbility.DoubleShot; - - public override int AosStrengthReq => 35; - public override int AosMinDamage => Core.ML ? 16 : 18; - public override int AosMaxDamage => 20; - public override int AosSpeed => 25; - public override float MlSpeed => 4.5f; - - public override int OldStrengthReq => 35; - public override int OldMinDamage => 18; - public override int OldMaxDamage => 20; - public override int OldSpeed => 25; - - public override int DefMaxRange => 10; - - public override int InitMinHits => 55; - public override int InitMaxHits => 60; - - public override WeaponAnimation DefAnimation => WeaponAnimation.ShootBow; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 7.0) - Weight = 6.0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/SlayerEntry.cs b/Projects/UOContent/Items/Weapons/SlayerEntry.cs index c77670eee..efe675cf6 100644 --- a/Projects/UOContent/Items/Weapons/SlayerEntry.cs +++ b/Projects/UOContent/Items/Weapons/SlayerEntry.cs @@ -2,101 +2,101 @@ using System; namespace Server.Items { - public class SlayerEntry - { - private static readonly int[] m_AosTitles = + public class SlayerEntry { - 1060479, // undead slayer - 1060470, // orc slayer - 1060480, // troll slayer - 1060468, // ogre slayer - 1060472, // repond slayer - 1060462, // dragon slayer - 1060478, // terathan slayer - 1060475, // snake slayer - 1060467, // lizardman slayer - 1060473, // reptile slayer - 1060460, // demon slayer - 1060466, // gargoyle slayer - 1017396, // Balron Damnation - 1060461, // demon slayer - 1060469, // ophidian slayer - 1060477, // spider slayer - 1060474, // scorpion slayer - 1060458, // arachnid slayer - 1060465, // fire elemental slayer - 1060481, // water elemental slayer - 1060457, // air elemental slayer - 1060471, // poison elemental slayer - 1060463, // earth elemental slayer - 1060459, // blood elemental slayer - 1060476, // snow elemental slayer - 1060464, // elemental slayer - 1070855 // fey slayer - }; + private static readonly int[] m_AosTitles = + { + 1060479, // undead slayer + 1060470, // orc slayer + 1060480, // troll slayer + 1060468, // ogre slayer + 1060472, // repond slayer + 1060462, // dragon slayer + 1060478, // terathan slayer + 1060475, // snake slayer + 1060467, // lizardman slayer + 1060473, // reptile slayer + 1060460, // demon slayer + 1060466, // gargoyle slayer + 1017396, // Balron Damnation + 1060461, // demon slayer + 1060469, // ophidian slayer + 1060477, // spider slayer + 1060474, // scorpion slayer + 1060458, // arachnid slayer + 1060465, // fire elemental slayer + 1060481, // water elemental slayer + 1060457, // air elemental slayer + 1060471, // poison elemental slayer + 1060463, // earth elemental slayer + 1060459, // blood elemental slayer + 1060476, // snow elemental slayer + 1060464, // elemental slayer + 1070855 // fey slayer + }; - private static readonly int[] m_OldTitles = - { - 1017384, // Silver - 1017385, // Orc Slaying - 1017386, // Troll Slaughter - 1017387, // Ogre Thrashing - 1017388, // Repond - 1017389, // Dragon Slaying - 1017390, // Terathan - 1017391, // Snake's Bane - 1017392, // Lizardman Slaughter - 1017393, // Reptilian Death - 1017394, // Daemon Dismissal - 1017395, // Gargoyle's Foe - 1017396, // Balron Damnation - 1017397, // Exorcism - 1017398, // Ophidian - 1017399, // Spider's Death - 1017400, // Scorpion's Bane - 1017401, // Arachnid Doom - 1017402, // Flame Dousing - 1017403, // Water Dissipation - 1017404, // Vacuum - 1017405, // Elemental Health - 1017406, // Earth Shatter - 1017407, // Blood Drinking - 1017408, // Summer Wind - 1017409, // Elemental Ban - 1070855 // fey slayer - }; + private static readonly int[] m_OldTitles = + { + 1017384, // Silver + 1017385, // Orc Slaying + 1017386, // Troll Slaughter + 1017387, // Ogre Thrashing + 1017388, // Repond + 1017389, // Dragon Slaying + 1017390, // Terathan + 1017391, // Snake's Bane + 1017392, // Lizardman Slaughter + 1017393, // Reptilian Death + 1017394, // Daemon Dismissal + 1017395, // Gargoyle's Foe + 1017396, // Balron Damnation + 1017397, // Exorcism + 1017398, // Ophidian + 1017399, // Spider's Death + 1017400, // Scorpion's Bane + 1017401, // Arachnid Doom + 1017402, // Flame Dousing + 1017403, // Water Dissipation + 1017404, // Vacuum + 1017405, // Elemental Health + 1017406, // Earth Shatter + 1017407, // Blood Drinking + 1017408, // Summer Wind + 1017409, // Elemental Ban + 1070855 // fey slayer + }; - public SlayerEntry(SlayerName name, params Type[] types) - { - Name = name; - Types = types; + public SlayerEntry(SlayerName name, params Type[] types) + { + Name = name; + Types = types; + } + + public SlayerGroup Group { get; set; } + + public SlayerName Name { get; } + + public Type[] Types { get; } + + public int Title + { + get + { + var titles = Core.AOS ? m_AosTitles : m_OldTitles; + + return titles[(int)Name - 1]; + } + } + + public bool Slays(Mobile m) + { + var t = m.GetType(); + + for (var i = 0; i < Types.Length; ++i) + if (Types[i].IsAssignableFrom(t)) + return true; + + return false; + } } - - public SlayerGroup Group { get; set; } - - public SlayerName Name { get; } - - public Type[] Types { get; } - - public int Title - { - get - { - int[] titles = Core.AOS ? m_AosTitles : m_OldTitles; - - return titles[(int)Name - 1]; - } - } - - public bool Slays(Mobile m) - { - Type t = m.GetType(); - - for (int i = 0; i < Types.Length; ++i) - if (Types[i].IsAssignableFrom(t)) - return true; - - return false; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/SlayerGroup.cs b/Projects/UOContent/Items/Weapons/SlayerGroup.cs index 4927cdea7..19038fec1 100644 --- a/Projects/UOContent/Items/Weapons/SlayerGroup.cs +++ b/Projects/UOContent/Items/Weapons/SlayerGroup.cs @@ -3,240 +3,490 @@ using Server.Mobiles; namespace Server.Items { - public class SlayerGroup - { - static SlayerGroup() + public class SlayerGroup { - SlayerGroup humanoid = new SlayerGroup(); - SlayerGroup undead = new SlayerGroup(); - SlayerGroup elemental = new SlayerGroup(); - SlayerGroup abyss = new SlayerGroup(); - SlayerGroup arachnid = new SlayerGroup(); - SlayerGroup reptilian = new SlayerGroup(); - SlayerGroup fey = new SlayerGroup(); - - humanoid.Opposition = new[] { undead }; - humanoid.FoundOn = new[] { typeof(BoneKnight), typeof(Lich), typeof(LichLord) }; - humanoid.Super = new SlayerEntry(SlayerName.Repond, typeof(ArcticOgreLord), typeof(Cyclops), typeof(Ettin), - typeof(EvilMage), typeof(EvilMageLord), typeof(FrostTroll), typeof(MeerCaptain), typeof(MeerEternal), - typeof(MeerMage), typeof(MeerWarrior), typeof(Ogre), typeof(OgreLord), typeof(Orc), typeof(OrcBomber), - typeof(OrcBrute), typeof(OrcCaptain), /*typeof( OrcChopper ), typeof( OrcScout ),*/ typeof(OrcishLord), - typeof(OrcishMage), typeof(Ratman), typeof(RatmanArcher), typeof(RatmanMage), typeof(SavageRider), - typeof(SavageShaman), typeof(Savage), typeof(Titan), typeof(Troglodyte), typeof(Troll)); - humanoid.Entries = new[] - { - new SlayerEntry(SlayerName.OgreTrashing, typeof(Ogre), typeof(OgreLord), typeof(ArcticOgreLord)), - new SlayerEntry(SlayerName.OrcSlaying, typeof(Orc), typeof(OrcBomber), typeof(OrcBrute), - typeof(OrcCaptain), /* typeof( OrcChopper ), typeof( OrcScout ),*/ typeof(OrcishLord), - typeof(OrcishMage)), - new SlayerEntry(SlayerName.TrollSlaughter, typeof(Troll), typeof(FrostTroll)) - }; - - undead.Opposition = new[] { humanoid }; - undead.Super = new SlayerEntry(SlayerName.Silver, typeof(AncientLich), typeof(Bogle), typeof(BoneKnight), - typeof(BoneMagi), /* typeof( DarkGuardian ), */typeof(DarknightCreeper), typeof(FleshGolem), typeof(Ghoul), - typeof(GoreFiend), typeof(HellSteed), typeof(LadyOfTheSnow), typeof(Lich), typeof(LichLord), typeof(Mummy), - typeof(PestilentBandage), typeof(Revenant), typeof(RevenantLion), typeof(RottingCorpse), typeof(Shade), - typeof(ShadowKnight), typeof(SkeletalKnight), typeof(SkeletalMage), typeof(SkeletalMount), typeof(Skeleton), - typeof(Spectre), typeof(Wraith), typeof(Zombie)); - undead.Entries = Array.Empty(); - - fey.Opposition = new[] { abyss }; - fey.Super = new SlayerEntry(SlayerName.Fey, typeof(Centaur), typeof(CuSidhe), typeof(EtherealWarrior), - typeof(Kirin), typeof(LordOaks), typeof(Pixie), typeof(Silvani), typeof(Treefellow), typeof(Unicorn), - typeof(Wisp), typeof(MLDryad), typeof(Satyr)); - fey.Entries = Array.Empty(); - - elemental.Opposition = new[] { abyss }; - elemental.FoundOn = new[] { typeof(Balron), typeof(Daemon) }; - elemental.Super = new SlayerEntry(SlayerName.ElementalBan, typeof(AcidElemental), typeof(AgapiteElemental), - typeof(AirElemental), typeof(SummonedAirElemental), typeof(BloodElemental), typeof(BronzeElemental), - typeof(CopperElemental), typeof(CrystalElemental), typeof(DullCopperElemental), typeof(EarthElemental), - typeof(SummonedEarthElemental), typeof(Efreet), typeof(FireElemental), typeof(SummonedFireElemental), - typeof(GoldenElemental), typeof(IceElemental), typeof(KazeKemono), typeof(PoisonElemental), typeof(RaiJu), - typeof(SandVortex), typeof(ShadowIronElemental), typeof(SnowElemental), typeof(ValoriteElemental), - typeof(VeriteElemental), typeof(WaterElemental), typeof(SummonedWaterElemental)); - elemental.Entries = new[] - { - new SlayerEntry(SlayerName.BloodDrinking, typeof(BloodElemental)), - new SlayerEntry(SlayerName.EarthShatter, typeof(AgapiteElemental), typeof(BronzeElemental), - typeof(CopperElemental), typeof(DullCopperElemental), typeof(EarthElemental), - typeof(SummonedEarthElemental), typeof(GoldenElemental), typeof(ShadowIronElemental), - typeof(ValoriteElemental), typeof(VeriteElemental)), - new SlayerEntry(SlayerName.ElementalHealth, typeof(PoisonElemental)), - new SlayerEntry(SlayerName.FlameDousing, typeof(FireElemental), typeof(SummonedFireElemental)), - new SlayerEntry(SlayerName.SummerWind, typeof(SnowElemental), typeof(IceElemental)), - new SlayerEntry(SlayerName.Vacuum, typeof(AirElemental), typeof(SummonedAirElemental)), - new SlayerEntry(SlayerName.WaterDissipation, typeof(WaterElemental), typeof(SummonedWaterElemental)) - }; - - abyss.Opposition = new[] { elemental, fey }; - abyss.FoundOn = new[] { typeof(BloodElemental) }; - - if (Core.AOS) - { - abyss.Super = new SlayerEntry(SlayerName.Exorcism, typeof(AbysmalHorror), typeof(ArcaneDaemon), - typeof(Balron), typeof(BoneDemon), typeof(ChaosDaemon), typeof(Daemon), typeof(SummonedDaemon), - typeof(DemonKnight), typeof(Devourer), typeof(EnslavedGargoyle), typeof(FanDancer), typeof(FireGargoyle), - typeof(Gargoyle), typeof(GargoyleDestroyer), typeof(GargoyleEnforcer), typeof(Gibberling), - typeof(HordeMinion), typeof(IceFiend), typeof(Imp), typeof(Impaler), typeof(Moloch), typeof(Oni), - typeof(Ravager), typeof(Semidar), typeof(StoneGargoyle), typeof(Succubus), typeof(TsukiWolf)); - - abyss.Entries = new[] + static SlayerGroup() { - // Daemon Dismissal & Balron Damnation have been removed and moved up to super slayer on OSI. - new SlayerEntry(SlayerName.GargoylesFoe, typeof(EnslavedGargoyle), typeof(FireGargoyle), - typeof(Gargoyle), typeof(GargoyleDestroyer), typeof(GargoyleEnforcer), typeof(StoneGargoyle)) - }; - } - else - { - abyss.Super = new SlayerEntry(SlayerName.Exorcism, typeof(AbysmalHorror), typeof(Balron), typeof(BoneDemon), - typeof(ChaosDaemon), typeof(Daemon), typeof(SummonedDaemon), typeof(DemonKnight), typeof(Devourer), - typeof(Gargoyle), typeof(FireGargoyle), typeof(Gibberling), typeof(HordeMinion), typeof(IceFiend), - typeof(Imp), typeof(Impaler), typeof(Ravager), typeof(StoneGargoyle), typeof(ArcaneDaemon), - typeof(EnslavedGargoyle), typeof(GargoyleDestroyer), typeof(GargoyleEnforcer), typeof(Moloch)); + var humanoid = new SlayerGroup(); + var undead = new SlayerGroup(); + var elemental = new SlayerGroup(); + var abyss = new SlayerGroup(); + var arachnid = new SlayerGroup(); + var reptilian = new SlayerGroup(); + var fey = new SlayerGroup(); - abyss.Entries = new[] - { - new SlayerEntry(SlayerName.DaemonDismissal, typeof(AbysmalHorror), typeof(Balron), typeof(BoneDemon), - typeof(ChaosDaemon), typeof(Daemon), typeof(SummonedDaemon), typeof(DemonKnight), typeof(Devourer), - typeof(Gibberling), typeof(HordeMinion), typeof(IceFiend), typeof(Imp), typeof(Impaler), - typeof(Ravager), typeof(ArcaneDaemon), typeof(Moloch)), - new SlayerEntry(SlayerName.GargoylesFoe, typeof(FireGargoyle), typeof(Gargoyle), typeof(StoneGargoyle), - typeof(EnslavedGargoyle), typeof(GargoyleDestroyer), typeof(GargoyleEnforcer)), - new SlayerEntry(SlayerName.BalronDamnation, typeof(Balron)) - }; - } + humanoid.Opposition = new[] { undead }; + humanoid.FoundOn = new[] { typeof(BoneKnight), typeof(Lich), typeof(LichLord) }; + humanoid.Super = new SlayerEntry( + SlayerName.Repond, + typeof(ArcticOgreLord), + typeof(Cyclops), + typeof(Ettin), + typeof(EvilMage), + typeof(EvilMageLord), + typeof(FrostTroll), + typeof(MeerCaptain), + typeof(MeerEternal), + typeof(MeerMage), + typeof(MeerWarrior), + typeof(Ogre), + typeof(OgreLord), + typeof(Orc), + typeof(OrcBomber), + typeof(OrcBrute), + typeof(OrcCaptain), /*typeof( OrcChopper ), typeof( OrcScout ),*/ + typeof(OrcishLord), + typeof(OrcishMage), + typeof(Ratman), + typeof(RatmanArcher), + typeof(RatmanMage), + typeof(SavageRider), + typeof(SavageShaman), + typeof(Savage), + typeof(Titan), + typeof(Troglodyte), + typeof(Troll) + ); + humanoid.Entries = new[] + { + new SlayerEntry(SlayerName.OgreTrashing, typeof(Ogre), typeof(OgreLord), typeof(ArcticOgreLord)), + new SlayerEntry( + SlayerName.OrcSlaying, + typeof(Orc), + typeof(OrcBomber), + typeof(OrcBrute), + typeof(OrcCaptain), /* typeof( OrcChopper ), typeof( OrcScout ),*/ + typeof(OrcishLord), + typeof(OrcishMage) + ), + new SlayerEntry(SlayerName.TrollSlaughter, typeof(Troll), typeof(FrostTroll)) + }; - arachnid.Opposition = new[] { reptilian }; - arachnid.FoundOn = new[] - { - typeof(AncientWyrm), typeof(GreaterDragon), typeof(Dragon), typeof(OphidianMatriarch), typeof(ShadowWyrm) - }; - arachnid.Super = new SlayerEntry(SlayerName.ArachnidDoom, typeof(DreadSpider), typeof(FrostSpider), - typeof(GiantBlackWidow), typeof(GiantSpider), typeof(Mephitis), typeof(Scorpion), typeof(TerathanAvenger), - typeof(TerathanDrone), typeof(TerathanMatriarch), typeof(TerathanWarrior)); - arachnid.Entries = new[] - { - new SlayerEntry(SlayerName.ScorpionsBane, typeof(Scorpion)), - new SlayerEntry(SlayerName.SpidersDeath, typeof(DreadSpider), typeof(FrostSpider), typeof(GiantBlackWidow), - typeof(GiantSpider), typeof(Mephitis)), - new SlayerEntry(SlayerName.Terathan, typeof(TerathanAvenger), typeof(TerathanDrone), - typeof(TerathanMatriarch), typeof(TerathanWarrior)) - }; + undead.Opposition = new[] { humanoid }; + undead.Super = new SlayerEntry( + SlayerName.Silver, + typeof(AncientLich), + typeof(Bogle), + typeof(BoneKnight), + typeof(BoneMagi), /* typeof( DarkGuardian ), */ + typeof(DarknightCreeper), + typeof(FleshGolem), + typeof(Ghoul), + typeof(GoreFiend), + typeof(HellSteed), + typeof(LadyOfTheSnow), + typeof(Lich), + typeof(LichLord), + typeof(Mummy), + typeof(PestilentBandage), + typeof(Revenant), + typeof(RevenantLion), + typeof(RottingCorpse), + typeof(Shade), + typeof(ShadowKnight), + typeof(SkeletalKnight), + typeof(SkeletalMage), + typeof(SkeletalMount), + typeof(Skeleton), + typeof(Spectre), + typeof(Wraith), + typeof(Zombie) + ); + undead.Entries = Array.Empty(); - reptilian.Opposition = new[] { arachnid }; - reptilian.FoundOn = new[] { typeof(TerathanAvenger), typeof(TerathanMatriarch) }; - reptilian.Super = new SlayerEntry(SlayerName.ReptilianDeath, typeof(AncientWyrm), typeof(DeepSeaSerpent), - typeof(GreaterDragon), typeof(Dragon), typeof(Drake), typeof(GiantIceWorm), typeof(IceSerpent), - typeof(GiantSerpent), typeof(Hiryu), typeof(IceSnake), typeof(JukaLord), typeof(JukaMage), - typeof(JukaWarrior), typeof(LavaSerpent), typeof(LavaSnake), typeof(LesserHiryu), typeof(Lizardman), - typeof(OphidianArchmage), typeof(OphidianKnight), typeof(OphidianMage), typeof(OphidianMatriarch), - typeof(OphidianWarrior), typeof(Reptalon), typeof(SeaSerpent), typeof(Serado), typeof(SerpentineDragon), - typeof(ShadowWyrm), typeof(SilverSerpent), typeof(SkeletalDragon), typeof(Snake), typeof(SwampDragon), - typeof(WhiteWyrm), typeof(Wyvern), typeof(Yamandon)); - reptilian.Entries = new[] - { - new SlayerEntry(SlayerName.DragonSlaying, typeof(AncientWyrm), typeof(GreaterDragon), typeof(Dragon), - typeof(Drake), typeof(Hiryu), typeof(LesserHiryu), typeof(Reptalon), typeof(SerpentineDragon), - typeof(ShadowWyrm), typeof(SkeletalDragon), typeof(SwampDragon), typeof(WhiteWyrm), typeof(Wyvern)), - new SlayerEntry(SlayerName.LizardmanSlaughter, typeof(Lizardman)), - new SlayerEntry(SlayerName.Ophidian, typeof(OphidianArchmage), typeof(OphidianKnight), typeof(OphidianMage), - typeof(OphidianMatriarch), typeof(OphidianWarrior)), - new SlayerEntry(SlayerName.SnakesBane, typeof(DeepSeaSerpent), typeof(GiantIceWorm), typeof(GiantSerpent), - typeof(IceSerpent), typeof(IceSnake), typeof(LavaSerpent), typeof(LavaSnake), typeof(SeaSerpent), - typeof(Serado), typeof(SilverSerpent), typeof(Snake), typeof(Yamandon)) - }; + fey.Opposition = new[] { abyss }; + fey.Super = new SlayerEntry( + SlayerName.Fey, + typeof(Centaur), + typeof(CuSidhe), + typeof(EtherealWarrior), + typeof(Kirin), + typeof(LordOaks), + typeof(Pixie), + typeof(Silvani), + typeof(Treefellow), + typeof(Unicorn), + typeof(Wisp), + typeof(MLDryad), + typeof(Satyr) + ); + fey.Entries = Array.Empty(); - Groups = new[] - { - humanoid, - undead, - elemental, - abyss, - arachnid, - reptilian, - fey - }; + elemental.Opposition = new[] { abyss }; + elemental.FoundOn = new[] { typeof(Balron), typeof(Daemon) }; + elemental.Super = new SlayerEntry( + SlayerName.ElementalBan, + typeof(AcidElemental), + typeof(AgapiteElemental), + typeof(AirElemental), + typeof(SummonedAirElemental), + typeof(BloodElemental), + typeof(BronzeElemental), + typeof(CopperElemental), + typeof(CrystalElemental), + typeof(DullCopperElemental), + typeof(EarthElemental), + typeof(SummonedEarthElemental), + typeof(Efreet), + typeof(FireElemental), + typeof(SummonedFireElemental), + typeof(GoldenElemental), + typeof(IceElemental), + typeof(KazeKemono), + typeof(PoisonElemental), + typeof(RaiJu), + typeof(SandVortex), + typeof(ShadowIronElemental), + typeof(SnowElemental), + typeof(ValoriteElemental), + typeof(VeriteElemental), + typeof(WaterElemental), + typeof(SummonedWaterElemental) + ); + elemental.Entries = new[] + { + new SlayerEntry(SlayerName.BloodDrinking, typeof(BloodElemental)), + new SlayerEntry( + SlayerName.EarthShatter, + typeof(AgapiteElemental), + typeof(BronzeElemental), + typeof(CopperElemental), + typeof(DullCopperElemental), + typeof(EarthElemental), + typeof(SummonedEarthElemental), + typeof(GoldenElemental), + typeof(ShadowIronElemental), + typeof(ValoriteElemental), + typeof(VeriteElemental) + ), + new SlayerEntry(SlayerName.ElementalHealth, typeof(PoisonElemental)), + new SlayerEntry(SlayerName.FlameDousing, typeof(FireElemental), typeof(SummonedFireElemental)), + new SlayerEntry(SlayerName.SummerWind, typeof(SnowElemental), typeof(IceElemental)), + new SlayerEntry(SlayerName.Vacuum, typeof(AirElemental), typeof(SummonedAirElemental)), + new SlayerEntry(SlayerName.WaterDissipation, typeof(WaterElemental), typeof(SummonedWaterElemental)) + }; - TotalEntries = CompileEntries(Groups); - } + abyss.Opposition = new[] { elemental, fey }; + abyss.FoundOn = new[] { typeof(BloodElemental) }; - public static SlayerEntry[] TotalEntries { get; } + if (Core.AOS) + { + abyss.Super = new SlayerEntry( + SlayerName.Exorcism, + typeof(AbysmalHorror), + typeof(ArcaneDaemon), + typeof(Balron), + typeof(BoneDemon), + typeof(ChaosDaemon), + typeof(Daemon), + typeof(SummonedDaemon), + typeof(DemonKnight), + typeof(Devourer), + typeof(EnslavedGargoyle), + typeof(FanDancer), + typeof(FireGargoyle), + typeof(Gargoyle), + typeof(GargoyleDestroyer), + typeof(GargoyleEnforcer), + typeof(Gibberling), + typeof(HordeMinion), + typeof(IceFiend), + typeof(Imp), + typeof(Impaler), + typeof(Moloch), + typeof(Oni), + typeof(Ravager), + typeof(Semidar), + typeof(StoneGargoyle), + typeof(Succubus), + typeof(TsukiWolf) + ); - public static SlayerGroup[] Groups { get; } + abyss.Entries = new[] + { + // Daemon Dismissal & Balron Damnation have been removed and moved up to super slayer on OSI. + new SlayerEntry( + SlayerName.GargoylesFoe, + typeof(EnslavedGargoyle), + typeof(FireGargoyle), + typeof(Gargoyle), + typeof(GargoyleDestroyer), + typeof(GargoyleEnforcer), + typeof(StoneGargoyle) + ) + }; + } + else + { + abyss.Super = new SlayerEntry( + SlayerName.Exorcism, + typeof(AbysmalHorror), + typeof(Balron), + typeof(BoneDemon), + typeof(ChaosDaemon), + typeof(Daemon), + typeof(SummonedDaemon), + typeof(DemonKnight), + typeof(Devourer), + typeof(Gargoyle), + typeof(FireGargoyle), + typeof(Gibberling), + typeof(HordeMinion), + typeof(IceFiend), + typeof(Imp), + typeof(Impaler), + typeof(Ravager), + typeof(StoneGargoyle), + typeof(ArcaneDaemon), + typeof(EnslavedGargoyle), + typeof(GargoyleDestroyer), + typeof(GargoyleEnforcer), + typeof(Moloch) + ); - public SlayerGroup[] Opposition { get; set; } + abyss.Entries = new[] + { + new SlayerEntry( + SlayerName.DaemonDismissal, + typeof(AbysmalHorror), + typeof(Balron), + typeof(BoneDemon), + typeof(ChaosDaemon), + typeof(Daemon), + typeof(SummonedDaemon), + typeof(DemonKnight), + typeof(Devourer), + typeof(Gibberling), + typeof(HordeMinion), + typeof(IceFiend), + typeof(Imp), + typeof(Impaler), + typeof(Ravager), + typeof(ArcaneDaemon), + typeof(Moloch) + ), + new SlayerEntry( + SlayerName.GargoylesFoe, + typeof(FireGargoyle), + typeof(Gargoyle), + typeof(StoneGargoyle), + typeof(EnslavedGargoyle), + typeof(GargoyleDestroyer), + typeof(GargoyleEnforcer) + ), + new SlayerEntry(SlayerName.BalronDamnation, typeof(Balron)) + }; + } - public SlayerEntry Super { get; set; } + arachnid.Opposition = new[] { reptilian }; + arachnid.FoundOn = new[] + { + typeof(AncientWyrm), typeof(GreaterDragon), typeof(Dragon), typeof(OphidianMatriarch), typeof(ShadowWyrm) + }; + arachnid.Super = new SlayerEntry( + SlayerName.ArachnidDoom, + typeof(DreadSpider), + typeof(FrostSpider), + typeof(GiantBlackWidow), + typeof(GiantSpider), + typeof(Mephitis), + typeof(Scorpion), + typeof(TerathanAvenger), + typeof(TerathanDrone), + typeof(TerathanMatriarch), + typeof(TerathanWarrior) + ); + arachnid.Entries = new[] + { + new SlayerEntry(SlayerName.ScorpionsBane, typeof(Scorpion)), + new SlayerEntry( + SlayerName.SpidersDeath, + typeof(DreadSpider), + typeof(FrostSpider), + typeof(GiantBlackWidow), + typeof(GiantSpider), + typeof(Mephitis) + ), + new SlayerEntry( + SlayerName.Terathan, + typeof(TerathanAvenger), + typeof(TerathanDrone), + typeof(TerathanMatriarch), + typeof(TerathanWarrior) + ) + }; - public SlayerEntry[] Entries { get; set; } + reptilian.Opposition = new[] { arachnid }; + reptilian.FoundOn = new[] { typeof(TerathanAvenger), typeof(TerathanMatriarch) }; + reptilian.Super = new SlayerEntry( + SlayerName.ReptilianDeath, + typeof(AncientWyrm), + typeof(DeepSeaSerpent), + typeof(GreaterDragon), + typeof(Dragon), + typeof(Drake), + typeof(GiantIceWorm), + typeof(IceSerpent), + typeof(GiantSerpent), + typeof(Hiryu), + typeof(IceSnake), + typeof(JukaLord), + typeof(JukaMage), + typeof(JukaWarrior), + typeof(LavaSerpent), + typeof(LavaSnake), + typeof(LesserHiryu), + typeof(Lizardman), + typeof(OphidianArchmage), + typeof(OphidianKnight), + typeof(OphidianMage), + typeof(OphidianMatriarch), + typeof(OphidianWarrior), + typeof(Reptalon), + typeof(SeaSerpent), + typeof(Serado), + typeof(SerpentineDragon), + typeof(ShadowWyrm), + typeof(SilverSerpent), + typeof(SkeletalDragon), + typeof(Snake), + typeof(SwampDragon), + typeof(WhiteWyrm), + typeof(Wyvern), + typeof(Yamandon) + ); + reptilian.Entries = new[] + { + new SlayerEntry( + SlayerName.DragonSlaying, + typeof(AncientWyrm), + typeof(GreaterDragon), + typeof(Dragon), + typeof(Drake), + typeof(Hiryu), + typeof(LesserHiryu), + typeof(Reptalon), + typeof(SerpentineDragon), + typeof(ShadowWyrm), + typeof(SkeletalDragon), + typeof(SwampDragon), + typeof(WhiteWyrm), + typeof(Wyvern) + ), + new SlayerEntry(SlayerName.LizardmanSlaughter, typeof(Lizardman)), + new SlayerEntry( + SlayerName.Ophidian, + typeof(OphidianArchmage), + typeof(OphidianKnight), + typeof(OphidianMage), + typeof(OphidianMatriarch), + typeof(OphidianWarrior) + ), + new SlayerEntry( + SlayerName.SnakesBane, + typeof(DeepSeaSerpent), + typeof(GiantIceWorm), + typeof(GiantSerpent), + typeof(IceSerpent), + typeof(IceSnake), + typeof(LavaSerpent), + typeof(LavaSnake), + typeof(SeaSerpent), + typeof(Serado), + typeof(SilverSerpent), + typeof(Snake), + typeof(Yamandon) + ) + }; - public Type[] FoundOn { get; set; } + Groups = new[] + { + humanoid, + undead, + elemental, + abyss, + arachnid, + reptilian, + fey + }; - public static SlayerEntry GetEntryByName(SlayerName name) - { - int v = (int)name; - - if (v >= 0 && v < TotalEntries.Length) - return TotalEntries[v]; - - return null; - } - - public static SlayerName GetLootSlayerType(Type type) - { - for (int i = 0; i < Groups.Length; ++i) - { - SlayerGroup group = Groups[i]; - Type[] foundOn = group.FoundOn; - - bool inGroup = false; - - for (int j = 0; foundOn != null && !inGroup && j < foundOn.Length; ++j) - inGroup = foundOn[j] == type; - - if (inGroup) - { - int index = Utility.Random(1 + group.Entries.Length); - - return index == 0 ? group.Super.Name : group.Entries[index - 1].Name; + TotalEntries = CompileEntries(Groups); } - } - return SlayerName.Silver; - } + public static SlayerEntry[] TotalEntries { get; } - private static SlayerEntry[] CompileEntries(SlayerGroup[] groups) - { - SlayerEntry[] entries = new SlayerEntry[28]; + public static SlayerGroup[] Groups { get; } - for (int i = 0; i < groups.Length; ++i) - { - SlayerGroup g = groups[i]; + public SlayerGroup[] Opposition { get; set; } - g.Super.Group = g; + public SlayerEntry Super { get; set; } - entries[(int)g.Super.Name] = g.Super; + public SlayerEntry[] Entries { get; set; } - for (int j = 0; j < g.Entries.Length; ++j) + public Type[] FoundOn { get; set; } + + public static SlayerEntry GetEntryByName(SlayerName name) { - g.Entries[j].Group = g; - entries[(int)g.Entries[j].Name] = g.Entries[j]; + var v = (int)name; + + if (v >= 0 && v < TotalEntries.Length) + return TotalEntries[v]; + + return null; } - } - return entries; + public static SlayerName GetLootSlayerType(Type type) + { + for (var i = 0; i < Groups.Length; ++i) + { + var group = Groups[i]; + var foundOn = group.FoundOn; + + var inGroup = false; + + for (var j = 0; foundOn != null && !inGroup && j < foundOn.Length; ++j) + inGroup = foundOn[j] == type; + + if (inGroup) + { + var index = Utility.Random(1 + group.Entries.Length); + + return index == 0 ? group.Super.Name : group.Entries[index - 1].Name; + } + } + + return SlayerName.Silver; + } + + private static SlayerEntry[] CompileEntries(SlayerGroup[] groups) + { + var entries = new SlayerEntry[28]; + + for (var i = 0; i < groups.Length; ++i) + { + var g = groups[i]; + + g.Super.Group = g; + + entries[(int)g.Super.Name] = g.Super; + + for (var j = 0; j < g.Entries.Length; ++j) + { + g.Entries[j].Group = g; + entries[(int)g.Entries[j].Name] = g.Entries[j]; + } + } + + return entries; + } + + public bool OppositionSuperSlays(Mobile m) + { + for (var i = 0; i < Opposition.Length; i++) + if (Opposition[i].Super.Slays(m)) + return true; + + return false; + } } - - public bool OppositionSuperSlays(Mobile m) - { - for (int i = 0; i < Opposition.Length; i++) - if (Opposition[i].Super.Slays(m)) - return true; - - return false; - } - } } diff --git a/Projects/UOContent/Items/Weapons/SlayerName.cs b/Projects/UOContent/Items/Weapons/SlayerName.cs index 0148aa3a3..f6051a833 100644 --- a/Projects/UOContent/Items/Weapons/SlayerName.cs +++ b/Projects/UOContent/Items/Weapons/SlayerName.cs @@ -1,34 +1,34 @@ namespace Server.Items { - public enum SlayerName - { - None, - Silver, - OrcSlaying, - TrollSlaughter, - OgreTrashing, - Repond, - DragonSlaying, - Terathan, - SnakesBane, - LizardmanSlaughter, - ReptilianDeath, - DaemonDismissal, - GargoylesFoe, - BalronDamnation, - Exorcism, - Ophidian, - SpidersDeath, - ScorpionsBane, - ArachnidDoom, - FlameDousing, - WaterDissipation, - Vacuum, - ElementalHealth, - EarthShatter, - BloodDrinking, - SummerWind, - ElementalBan, // Bane? - Fey - } -} \ No newline at end of file + public enum SlayerName + { + None, + Silver, + OrcSlaying, + TrollSlaughter, + OgreTrashing, + Repond, + DragonSlaying, + Terathan, + SnakesBane, + LizardmanSlaughter, + ReptilianDeath, + DaemonDismissal, + GargoylesFoe, + BalronDamnation, + Exorcism, + Ophidian, + SpidersDeath, + ScorpionsBane, + ArachnidDoom, + FlameDousing, + WaterDissipation, + Vacuum, + ElementalHealth, + EarthShatter, + BloodDrinking, + SummerWind, + ElementalBan, // Bane? + Fey + } +} diff --git a/Projects/UOContent/Items/Weapons/SpearsAndForks/BaseSpear.cs b/Projects/UOContent/Items/Weapons/SpearsAndForks/BaseSpear.cs index b94d2c564..ffc521683 100644 --- a/Projects/UOContent/Items/Weapons/SpearsAndForks/BaseSpear.cs +++ b/Projects/UOContent/Items/Weapons/SpearsAndForks/BaseSpear.cs @@ -3,59 +3,59 @@ using Server.Engines.ConPVP; namespace Server.Items { - public abstract class BaseSpear : BaseMeleeWeapon - { - public BaseSpear(int itemID) : base(itemID) + public abstract class BaseSpear : BaseMeleeWeapon { + public BaseSpear(int itemID) : base(itemID) + { + } + + public BaseSpear(Serial serial) : base(serial) + { + } + + public override int DefHitSound => 0x23C; + public override int DefMissSound => 0x238; + + public override SkillName DefSkill => SkillName.Fencing; + public override WeaponType DefType => WeaponType.Piercing; + public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce2H; + + 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 OnHit(Mobile attacker, Mobile defender, double damageBonus = 1) + { + base.OnHit(attacker, defender, damageBonus); + + if (!Core.AOS && Layer == Layer.TwoHanded && + attacker.Skills.Anatomy.Value / 400.0 >= Utility.RandomDouble() && + DuelContext.AllowSpecialAbility(attacker, "Paralyzing Blow", false)) + { + defender.SendMessage("You receive a paralyzing blow!"); // Is this not localized? + defender.Freeze(TimeSpan.FromSeconds(2.0)); + + attacker.SendMessage("You deliver a paralyzing blow!"); // Is this not localized? + attacker.PlaySound(0x11C); + } + + if (!Core.AOS && Poison != null && PoisonCharges > 0) + { + --PoisonCharges; + + if (Utility.RandomDouble() >= 0.5) // 50% chance to poison + defender.ApplyPoison(attacker, Poison); + } + } } - - public BaseSpear(Serial serial) : base(serial) - { - } - - public override int DefHitSound => 0x23C; - public override int DefMissSound => 0x238; - - public override SkillName DefSkill => SkillName.Fencing; - public override WeaponType DefType => WeaponType.Piercing; - public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce2H; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnHit(Mobile attacker, Mobile defender, double damageBonus = 1) - { - base.OnHit(attacker, defender, damageBonus); - - if (!Core.AOS && Layer == Layer.TwoHanded && - attacker.Skills.Anatomy.Value / 400.0 >= Utility.RandomDouble() && - DuelContext.AllowSpecialAbility(attacker, "Paralyzing Blow", false)) - { - defender.SendMessage("You receive a paralyzing blow!"); // Is this not localized? - defender.Freeze(TimeSpan.FromSeconds(2.0)); - - attacker.SendMessage("You deliver a paralyzing blow!"); // Is this not localized? - attacker.PlaySound(0x11C); - } - - if (!Core.AOS && Poison != null && PoisonCharges > 0) - { - --PoisonCharges; - - if (Utility.RandomDouble() >= 0.5) // 50% chance to poison - defender.ApplyPoison(attacker, Poison); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/SpearsAndForks/BladedStaff.cs b/Projects/UOContent/Items/Weapons/SpearsAndForks/BladedStaff.cs index c932c318d..e79e1134c 100644 --- a/Projects/UOContent/Items/Weapons/SpearsAndForks/BladedStaff.cs +++ b/Projects/UOContent/Items/Weapons/SpearsAndForks/BladedStaff.cs @@ -1,46 +1,46 @@ namespace Server.Items { - [Flippable(0x26BD, 0x26C7)] - public class BladedStaff : BaseSpear - { - [Constructible] - public BladedStaff() : base(0x26BD) => Weight = 4.0; - - public BladedStaff(Serial serial) : base(serial) + [Flippable(0x26BD, 0x26C7)] + public class BladedStaff : BaseSpear { + [Constructible] + public BladedStaff() : base(0x26BD) => Weight = 4.0; + + public BladedStaff(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore; + public override WeaponAbility SecondaryAbility => WeaponAbility.Dismount; + + public override int AosStrengthReq => 40; + public override int AosMinDamage => 14; + public override int AosMaxDamage => 16; + public override int AosSpeed => 37; + public override float MlSpeed => 3.00f; + + public override int OldStrengthReq => 40; + public override int OldMinDamage => 14; + public override int OldMaxDamage => 16; + public override int OldSpeed => 37; + + public override int InitMinHits => 21; + public override int InitMaxHits => 110; + + public override SkillName DefSkill => SkillName.Swords; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore; - public override WeaponAbility SecondaryAbility => WeaponAbility.Dismount; - - public override int AosStrengthReq => 40; - public override int AosMinDamage => 14; - public override int AosMaxDamage => 16; - public override int AosSpeed => 37; - public override float MlSpeed => 3.00f; - - public override int OldStrengthReq => 40; - public override int OldMinDamage => 14; - public override int OldMaxDamage => 16; - public override int OldSpeed => 37; - - public override int InitMinHits => 21; - public override int InitMaxHits => 110; - - public override SkillName DefSkill => SkillName.Swords; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/SpearsAndForks/DoubleBladedStaff.cs b/Projects/UOContent/Items/Weapons/SpearsAndForks/DoubleBladedStaff.cs index 5f8623dd6..88f3054f3 100644 --- a/Projects/UOContent/Items/Weapons/SpearsAndForks/DoubleBladedStaff.cs +++ b/Projects/UOContent/Items/Weapons/SpearsAndForks/DoubleBladedStaff.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0x26BF, 0x26C9)] - public class DoubleBladedStaff : BaseSpear - { - [Constructible] - public DoubleBladedStaff() : base(0x26BF) => Weight = 2.0; - - public DoubleBladedStaff(Serial serial) : base(serial) + [Flippable(0x26BF, 0x26C9)] + public class DoubleBladedStaff : BaseSpear { + [Constructible] + public DoubleBladedStaff() : base(0x26BF) => Weight = 2.0; + + public DoubleBladedStaff(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike; + public override WeaponAbility SecondaryAbility => WeaponAbility.InfectiousStrike; + + public override int AosStrengthReq => 50; + public override int AosMinDamage => 12; + public override int AosMaxDamage => 13; + public override int AosSpeed => 49; + public override float MlSpeed => 2.25f; + + public override int OldStrengthReq => 50; + public override int OldMinDamage => 12; + public override int OldMaxDamage => 13; + public override int OldSpeed => 49; + + public override int InitMinHits => 31; + public override int InitMaxHits => 80; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike; - public override WeaponAbility SecondaryAbility => WeaponAbility.InfectiousStrike; - - public override int AosStrengthReq => 50; - public override int AosMinDamage => 12; - public override int AosMaxDamage => 13; - public override int AosSpeed => 49; - public override float MlSpeed => 2.25f; - - public override int OldStrengthReq => 50; - public override int OldMinDamage => 12; - public override int OldMaxDamage => 13; - public override int OldSpeed => 49; - - public override int InitMinHits => 31; - public override int InitMaxHits => 80; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/SpearsAndForks/Pike.cs b/Projects/UOContent/Items/Weapons/SpearsAndForks/Pike.cs index 4c96bf823..353ad41a4 100644 --- a/Projects/UOContent/Items/Weapons/SpearsAndForks/Pike.cs +++ b/Projects/UOContent/Items/Weapons/SpearsAndForks/Pike.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0x26BE, 0x26C8)] - public class Pike : BaseSpear - { - [Constructible] - public Pike() : base(0x26BE) => Weight = 8.0; - - public Pike(Serial serial) : base(serial) + [Flippable(0x26BE, 0x26C8)] + public class Pike : BaseSpear { + [Constructible] + public Pike() : base(0x26BE) => Weight = 8.0; + + public Pike(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.ParalyzingBlow; + public override WeaponAbility SecondaryAbility => WeaponAbility.InfectiousStrike; + + public override int AosStrengthReq => 50; + public override int AosMinDamage => 14; + public override int AosMaxDamage => 16; + public override int AosSpeed => 37; + public override float MlSpeed => 3.00f; + + public override int OldStrengthReq => 50; + public override int OldMinDamage => 14; + public override int OldMaxDamage => 16; + public override int OldSpeed => 37; + + public override int InitMinHits => 31; + public override int InitMaxHits => 110; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.ParalyzingBlow; - public override WeaponAbility SecondaryAbility => WeaponAbility.InfectiousStrike; - - public override int AosStrengthReq => 50; - public override int AosMinDamage => 14; - public override int AosMaxDamage => 16; - public override int AosSpeed => 37; - public override float MlSpeed => 3.00f; - - public override int OldStrengthReq => 50; - public override int OldMinDamage => 14; - public override int OldMaxDamage => 16; - public override int OldSpeed => 37; - - public override int InitMinHits => 31; - public override int InitMaxHits => 110; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/SpearsAndForks/Pitchfork.cs b/Projects/UOContent/Items/Weapons/SpearsAndForks/Pitchfork.cs index b3f4d9ec3..4e6086de3 100644 --- a/Projects/UOContent/Items/Weapons/SpearsAndForks/Pitchfork.cs +++ b/Projects/UOContent/Items/Weapons/SpearsAndForks/Pitchfork.cs @@ -1,47 +1,47 @@ namespace Server.Items { - [Flippable(0xE87, 0xE88)] - public class Pitchfork : BaseSpear - { - [Constructible] - public Pitchfork() : base(0xE87) => Weight = 11.0; - - public Pitchfork(Serial serial) : base(serial) + [Flippable(0xE87, 0xE88)] + public class Pitchfork : BaseSpear { + [Constructible] + public Pitchfork() : base(0xE87) => Weight = 11.0; + + public Pitchfork(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.BleedAttack; + public override WeaponAbility SecondaryAbility => WeaponAbility.Dismount; + + public override int AosStrengthReq => 55; + public override int AosMinDamage => 13; + public override int AosMaxDamage => 14; + public override int AosSpeed => 43; + public override float MlSpeed => 2.50f; + + public override int OldStrengthReq => 15; + public override int OldMinDamage => 4; + public override int OldMaxDamage => 16; + public override int OldSpeed => 45; + + public override int InitMinHits => 31; + public override int InitMaxHits => 60; + + 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 (Weight == 10.0) + Weight = 11.0; + } } - - public override WeaponAbility PrimaryAbility => WeaponAbility.BleedAttack; - public override WeaponAbility SecondaryAbility => WeaponAbility.Dismount; - - public override int AosStrengthReq => 55; - public override int AosMinDamage => 13; - public override int AosMaxDamage => 14; - public override int AosSpeed => 43; - public override float MlSpeed => 2.50f; - - public override int OldStrengthReq => 15; - public override int OldMinDamage => 4; - public override int OldMaxDamage => 16; - public override int OldSpeed => 45; - - public override int InitMinHits => 31; - public override int InitMaxHits => 60; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 10.0) - Weight = 11.0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/SpearsAndForks/ShortSpear.cs b/Projects/UOContent/Items/Weapons/SpearsAndForks/ShortSpear.cs index f64757e33..811f2dab0 100644 --- a/Projects/UOContent/Items/Weapons/SpearsAndForks/ShortSpear.cs +++ b/Projects/UOContent/Items/Weapons/SpearsAndForks/ShortSpear.cs @@ -1,46 +1,46 @@ namespace Server.Items { - [Flippable(0x1403, 0x1402)] - public class ShortSpear : BaseSpear - { - [Constructible] - public ShortSpear() : base(0x1403) => Weight = 4.0; - - public ShortSpear(Serial serial) : base(serial) + [Flippable(0x1403, 0x1402)] + public class ShortSpear : BaseSpear { + [Constructible] + public ShortSpear() : base(0x1403) => Weight = 4.0; + + public ShortSpear(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.ShadowStrike; + public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike; + + public override int AosStrengthReq => 40; + public override int AosMinDamage => 10; + public override int AosMaxDamage => 13; + public override int AosSpeed => 55; + public override float MlSpeed => 2.00f; + + public override int OldStrengthReq => 15; + public override int OldMinDamage => 4; + public override int OldMaxDamage => 32; + public override int OldSpeed => 50; + + public override int InitMinHits => 31; + public override int InitMaxHits => 70; + + public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.ShadowStrike; - public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike; - - public override int AosStrengthReq => 40; - public override int AosMinDamage => 10; - public override int AosMaxDamage => 13; - public override int AosSpeed => 55; - public override float MlSpeed => 2.00f; - - public override int OldStrengthReq => 15; - public override int OldMinDamage => 4; - public override int OldMaxDamage => 32; - public override int OldSpeed => 50; - - public override int InitMinHits => 31; - public override int InitMaxHits => 70; - - public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/SpearsAndForks/Spear.cs b/Projects/UOContent/Items/Weapons/SpearsAndForks/Spear.cs index 015bab192..37acd05e1 100644 --- a/Projects/UOContent/Items/Weapons/SpearsAndForks/Spear.cs +++ b/Projects/UOContent/Items/Weapons/SpearsAndForks/Spear.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0xF62, 0xF63)] - public class Spear : BaseSpear - { - [Constructible] - public Spear() : base(0xF62) => Weight = 7.0; - - public Spear(Serial serial) : base(serial) + [Flippable(0xF62, 0xF63)] + public class Spear : BaseSpear { + [Constructible] + public Spear() : base(0xF62) => Weight = 7.0; + + public Spear(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore; + public override WeaponAbility SecondaryAbility => WeaponAbility.ParalyzingBlow; + + public override int AosStrengthReq => 50; + public override int AosMinDamage => 13; + public override int AosMaxDamage => 15; + public override int AosSpeed => 42; + public override float MlSpeed => 2.75f; + + public override int OldStrengthReq => 30; + public override int OldMinDamage => 2; + public override int OldMaxDamage => 36; + public override int OldSpeed => 46; + + public override int InitMinHits => 31; + public override int InitMaxHits => 80; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore; - public override WeaponAbility SecondaryAbility => WeaponAbility.ParalyzingBlow; - - public override int AosStrengthReq => 50; - public override int AosMinDamage => 13; - public override int AosMaxDamage => 15; - public override int AosSpeed => 42; - public override float MlSpeed => 2.75f; - - public override int OldStrengthReq => 30; - public override int OldMinDamage => 2; - public override int OldMaxDamage => 36; - public override int OldSpeed => 46; - - public override int InitMinHits => 31; - public override int InitMaxHits => 80; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/SpearsAndForks/TribalSpear.cs b/Projects/UOContent/Items/Weapons/SpearsAndForks/TribalSpear.cs index 079661b70..254a06cb0 100644 --- a/Projects/UOContent/Items/Weapons/SpearsAndForks/TribalSpear.cs +++ b/Projects/UOContent/Items/Weapons/SpearsAndForks/TribalSpear.cs @@ -1,52 +1,52 @@ namespace Server.Items { - [Flippable(0xF62, 0xF63)] - public class TribalSpear : BaseSpear - { - [Constructible] - public TribalSpear() : base(0xF62) + [Flippable(0xF62, 0xF63)] + public class TribalSpear : BaseSpear { - Weight = 7.0; - Hue = 837; + [Constructible] + public TribalSpear() : base(0xF62) + { + Weight = 7.0; + Hue = 837; + } + + public TribalSpear(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore; + public override WeaponAbility SecondaryAbility => WeaponAbility.ParalyzingBlow; + + public override int AosStrengthReq => 50; + public override int AosMinDamage => 13; + public override int AosMaxDamage => 15; + public override int AosSpeed => 42; + public override float MlSpeed => 2.75f; + + public override int OldStrengthReq => 30; + public override int OldMinDamage => 2; + public override int OldMaxDamage => 36; + public override int OldSpeed => 46; + + public override int InitMinHits => 31; + public override int InitMaxHits => 80; + + public override int VirtualDamageBonus => 25; + + public override string DefaultName => "a tribal spear"; + + 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 TribalSpear(Serial serial) : base(serial) - { - } - - public override WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore; - public override WeaponAbility SecondaryAbility => WeaponAbility.ParalyzingBlow; - - public override int AosStrengthReq => 50; - public override int AosMinDamage => 13; - public override int AosMaxDamage => 15; - public override int AosSpeed => 42; - public override float MlSpeed => 2.75f; - - public override int OldStrengthReq => 30; - public override int OldMinDamage => 2; - public override int OldMaxDamage => 36; - public override int OldSpeed => 46; - - public override int InitMinHits => 31; - public override int InitMaxHits => 80; - - public override int VirtualDamageBonus => 25; - - public override string DefaultName => "a tribal spear"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/SpearsAndForks/WarFork.cs b/Projects/UOContent/Items/Weapons/SpearsAndForks/WarFork.cs index f5e5ce8ec..a4ecca3d6 100644 --- a/Projects/UOContent/Items/Weapons/SpearsAndForks/WarFork.cs +++ b/Projects/UOContent/Items/Weapons/SpearsAndForks/WarFork.cs @@ -1,49 +1,49 @@ namespace Server.Items { - [Flippable(0x1405, 0x1404)] - public class WarFork : BaseSpear - { - [Constructible] - public WarFork() : base(0x1405) => Weight = 9.0; - - public WarFork(Serial serial) : base(serial) + [Flippable(0x1405, 0x1404)] + public class WarFork : BaseSpear { + [Constructible] + public WarFork() : base(0x1405) => Weight = 9.0; + + public WarFork(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.BleedAttack; + public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm; + + public override int AosStrengthReq => 45; + public override int AosMinDamage => 12; + public override int AosMaxDamage => 13; + public override int AosSpeed => 43; + public override float MlSpeed => 2.50f; + + public override int OldStrengthReq => 35; + public override int OldMinDamage => 4; + public override int OldMaxDamage => 32; + public override int OldSpeed => 45; + + public override int DefHitSound => 0x236; + public override int DefMissSound => 0x238; + + public override int InitMinHits => 31; + public override int InitMaxHits => 110; + + public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.BleedAttack; - public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm; - - public override int AosStrengthReq => 45; - public override int AosMinDamage => 12; - public override int AosMaxDamage => 13; - public override int AosSpeed => 43; - public override float MlSpeed => 2.50f; - - public override int OldStrengthReq => 35; - public override int OldMinDamage => 4; - public override int OldMaxDamage => 32; - public override int OldSpeed => 45; - - public override int DefHitSound => 0x236; - public override int DefMissSound => 0x238; - - public override int InitMinHits => 31; - public override int InitMaxHits => 110; - - public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Staves/BaseStaff.cs b/Projects/UOContent/Items/Weapons/Staves/BaseStaff.cs index c94428d26..42a972c4a 100644 --- a/Projects/UOContent/Items/Weapons/Staves/BaseStaff.cs +++ b/Projects/UOContent/Items/Weapons/Staves/BaseStaff.cs @@ -1,41 +1,41 @@ namespace Server.Items { - public abstract class BaseStaff : BaseMeleeWeapon - { - public BaseStaff(int itemID) : base(itemID) + public abstract class BaseStaff : BaseMeleeWeapon { + public BaseStaff(int itemID) : base(itemID) + { + } + + public BaseStaff(Serial serial) : base(serial) + { + } + + public override int DefHitSound => 0x233; + public override int DefMissSound => 0x239; + + public override SkillName DefSkill => SkillName.Macing; + public override WeaponType DefType => WeaponType.Staff; + public override WeaponAnimation DefAnimation => WeaponAnimation.Bash2H; + + 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 OnHit(Mobile attacker, Mobile defender, double damageBonus = 1) + { + base.OnHit(attacker, defender, damageBonus); + + defender.Stam -= Utility.Random(3, 3); // 3-5 points of stamina loss + } } - - public BaseStaff(Serial serial) : base(serial) - { - } - - public override int DefHitSound => 0x233; - public override int DefMissSound => 0x239; - - public override SkillName DefSkill => SkillName.Macing; - public override WeaponType DefType => WeaponType.Staff; - public override WeaponAnimation DefAnimation => WeaponAnimation.Bash2H; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnHit(Mobile attacker, Mobile defender, double damageBonus = 1) - { - base.OnHit(attacker, defender, damageBonus); - - defender.Stam -= Utility.Random(3, 3); // 3-5 points of stamina loss - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Staves/BlackStaff.cs b/Projects/UOContent/Items/Weapons/Staves/BlackStaff.cs index 7d1fdc17a..fd49c5510 100644 --- a/Projects/UOContent/Items/Weapons/Staves/BlackStaff.cs +++ b/Projects/UOContent/Items/Weapons/Staves/BlackStaff.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0xDF1, 0xDF0)] - public class BlackStaff : BaseStaff - { - [Constructible] - public BlackStaff() : base(0xDF0) => Weight = 6.0; - - public BlackStaff(Serial serial) : base(serial) + [Flippable(0xDF1, 0xDF0)] + public class BlackStaff : BaseStaff { + [Constructible] + public BlackStaff() : base(0xDF0) => Weight = 6.0; + + public BlackStaff(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.WhirlwindAttack; + public override WeaponAbility SecondaryAbility => WeaponAbility.ParalyzingBlow; + + public override int AosStrengthReq => 35; + public override int AosMinDamage => 13; + public override int AosMaxDamage => 16; + public override int AosSpeed => 39; + public override float MlSpeed => 2.75f; + + public override int OldStrengthReq => 35; + public override int OldMinDamage => 8; + public override int OldMaxDamage => 33; + public override int OldSpeed => 35; + + public override int InitMinHits => 31; + public override int InitMaxHits => 70; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.WhirlwindAttack; - public override WeaponAbility SecondaryAbility => WeaponAbility.ParalyzingBlow; - - public override int AosStrengthReq => 35; - public override int AosMinDamage => 13; - public override int AosMaxDamage => 16; - public override int AosSpeed => 39; - public override float MlSpeed => 2.75f; - - public override int OldStrengthReq => 35; - public override int OldMinDamage => 8; - public override int OldMaxDamage => 33; - public override int OldSpeed => 35; - - public override int InitMinHits => 31; - public override int InitMaxHits => 70; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Staves/GlacialStaff.cs b/Projects/UOContent/Items/Weapons/Staves/GlacialStaff.cs index 8983eea50..affeb7845 100644 --- a/Projects/UOContent/Items/Weapons/Staves/GlacialStaff.cs +++ b/Projects/UOContent/Items/Weapons/Staves/GlacialStaff.cs @@ -1,36 +1,36 @@ namespace Server.Items { - public class GlacialStaff : BlackStaff - { - [Constructible] - public GlacialStaff() + public class GlacialStaff : BlackStaff { - Hue = 0x480; - WeaponAttributes.HitHarm = 5 * Utility.RandomMinMax(1, 5); - WeaponAttributes.MageWeapon = Utility.RandomMinMax(5, 10); + [Constructible] + public GlacialStaff() + { + Hue = 0x480; + WeaponAttributes.HitHarm = 5 * Utility.RandomMinMax(1, 5); + WeaponAttributes.MageWeapon = Utility.RandomMinMax(5, 10); - AosElementDamages[AosElementAttribute.Cold] = 20 + 5 * Utility.RandomMinMax(0, 6); + AosElementDamages[AosElementAttribute.Cold] = 20 + 5 * Utility.RandomMinMax(0, 6); + } + + public GlacialStaff(Serial serial) : base(serial) + { + } + + // TODO: Pre-AoS stuff + public override int LabelNumber => 1017413; // Glacial Staff + + 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 GlacialStaff(Serial serial) : base(serial) - { - } - - // TODO: Pre-AoS stuff - public override int LabelNumber => 1017413; // Glacial Staff - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Staves/GnarledStaff.cs b/Projects/UOContent/Items/Weapons/Staves/GnarledStaff.cs index 727d91a4c..786c793b2 100644 --- a/Projects/UOContent/Items/Weapons/Staves/GnarledStaff.cs +++ b/Projects/UOContent/Items/Weapons/Staves/GnarledStaff.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0x13F8, 0x13F9)] - public class GnarledStaff : BaseStaff - { - [Constructible] - public GnarledStaff() : base(0x13F8) => Weight = 3.0; - - public GnarledStaff(Serial serial) : base(serial) + [Flippable(0x13F8, 0x13F9)] + public class GnarledStaff : BaseStaff { + [Constructible] + public GnarledStaff() : base(0x13F8) => Weight = 3.0; + + public GnarledStaff(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.ConcussionBlow; + public override WeaponAbility SecondaryAbility => WeaponAbility.ParalyzingBlow; + + public override int AosStrengthReq => 20; + public override int AosMinDamage => 15; + public override int AosMaxDamage => 17; + public override int AosSpeed => 33; + public override float MlSpeed => 3.25f; + + public override int OldStrengthReq => 20; + public override int OldMinDamage => 10; + public override int OldMaxDamage => 30; + public override int OldSpeed => 33; + + public override int InitMinHits => 31; + public override int InitMaxHits => 50; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.ConcussionBlow; - public override WeaponAbility SecondaryAbility => WeaponAbility.ParalyzingBlow; - - public override int AosStrengthReq => 20; - public override int AosMinDamage => 15; - public override int AosMaxDamage => 17; - public override int AosSpeed => 33; - public override float MlSpeed => 3.25f; - - public override int OldStrengthReq => 20; - public override int OldMinDamage => 10; - public override int OldMaxDamage => 30; - public override int OldSpeed => 33; - - public override int InitMinHits => 31; - public override int InitMaxHits => 50; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Staves/QuarterStaff.cs b/Projects/UOContent/Items/Weapons/Staves/QuarterStaff.cs index 2880e4f94..a4a31b875 100644 --- a/Projects/UOContent/Items/Weapons/Staves/QuarterStaff.cs +++ b/Projects/UOContent/Items/Weapons/Staves/QuarterStaff.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0xE89, 0xE8a)] - public class QuarterStaff : BaseStaff - { - [Constructible] - public QuarterStaff() : base(0xE89) => Weight = 4.0; - - public QuarterStaff(Serial serial) : base(serial) + [Flippable(0xE89, 0xE8a)] + public class QuarterStaff : BaseStaff { + [Constructible] + public QuarterStaff() : base(0xE89) => Weight = 4.0; + + public QuarterStaff(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike; + public override WeaponAbility SecondaryAbility => WeaponAbility.ConcussionBlow; + + public override int AosStrengthReq => 30; + public override int AosMinDamage => 11; + public override int AosMaxDamage => 14; + public override int AosSpeed => 48; + public override float MlSpeed => 2.25f; + + public override int OldStrengthReq => 30; + public override int OldMinDamage => 8; + public override int OldMaxDamage => 28; + public override int OldSpeed => 48; + + public override int InitMinHits => 31; + public override int InitMaxHits => 60; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike; - public override WeaponAbility SecondaryAbility => WeaponAbility.ConcussionBlow; - - public override int AosStrengthReq => 30; - public override int AosMinDamage => 11; - public override int AosMaxDamage => 14; - public override int AosSpeed => 48; - public override float MlSpeed => 2.25f; - - public override int OldStrengthReq => 30; - public override int OldMinDamage => 8; - public override int OldMaxDamage => 28; - public override int OldSpeed => 48; - - public override int InitMinHits => 31; - public override int InitMaxHits => 60; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Staves/ShepherdsCrook.cs b/Projects/UOContent/Items/Weapons/Staves/ShepherdsCrook.cs index 22bda2a91..e171088ef 100644 --- a/Projects/UOContent/Items/Weapons/Staves/ShepherdsCrook.cs +++ b/Projects/UOContent/Items/Weapons/Staves/ShepherdsCrook.cs @@ -6,158 +6,166 @@ using Server.Targeting; namespace Server.Items { - [Flippable(0xE81, 0xE82)] - public class ShepherdsCrook : BaseStaff - { - [Constructible] - public ShepherdsCrook() : base(0xE81) => Weight = 4.0; - - public ShepherdsCrook(Serial serial) : base(serial) + [Flippable(0xE81, 0xE82)] + public class ShepherdsCrook : BaseStaff { - } + [Constructible] + public ShepherdsCrook() : base(0xE81) => Weight = 4.0; - public override WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow; - public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm; - - public override int AosStrengthReq => 20; - public override int AosMinDamage => 13; - public override int AosMaxDamage => 15; - public override int AosSpeed => 40; - public override float MlSpeed => 2.75f; - - public override int OldStrengthReq => 10; - public override int OldMinDamage => 3; - public override int OldMaxDamage => 12; - public override int OldSpeed => 30; - - public override int InitMinHits => 31; - public override int InitMaxHits => 50; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 2.0) - Weight = 4.0; - } - - public override void OnDoubleClick(Mobile from) - { - from.SendLocalizedMessage(502464); // Target the animal you wish to herd. - from.Target = new HerdingTarget(); - } - - private class HerdingTarget : Target - { - private static readonly Type[] m_ChampTamables = - { - typeof(StrongMongbat), typeof(Imp), typeof(Scorpion), typeof(GiantSpider), - typeof(Snake), typeof(LavaLizard), typeof(Drake), typeof(Dragon), - typeof(Kirin), typeof(Unicorn), typeof(GiantRat), typeof(Slime), - typeof(DireWolf), typeof(HellHound), typeof(DeathwatchBeetle), - typeof(LesserHiryu), typeof(Hiryu) - }; - - public HerdingTarget() : base(10, false, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object targ) - { - if (targ is BaseCreature bc) + public ShepherdsCrook(Serial serial) : base(serial) { - if (IsHerdable(bc)) - { - if (bc.Controlled) - { - bc.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 502467, - from.NetState); // That animal looks tame already. - } - else - { - from.SendLocalizedMessage(502475); // Click where you wish the animal to go. - from.Target = new InternalTarget(bc); - } - } - else - { - from.SendLocalizedMessage(502468); // That is not a herdable animal. - } - } - else - { - from.SendLocalizedMessage(502472); // You don't seem to be able to persuade that to move. - } - } - - private bool IsHerdable(BaseCreature bc) - { - if (bc.IsParagon) - return false; - - if (bc.Tamable) - return true; - - Map map = bc.Map; - - if (Region.Find(bc.Home, map) is ChampionSpawnRegion region) - { - ChampionSpawn spawn = region.ChampionSpawn; - - if (spawn?.IsChampionSpawn(bc) == true) - { - Type t = bc.GetType(); - - foreach (Type type in m_ChampTamables) - if (type == t) - return true; - } } - return false; - } + public override WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow; + public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm; - private class InternalTarget : Target - { - private readonly BaseCreature m_Creature; + public override int AosStrengthReq => 20; + public override int AosMinDamage => 13; + public override int AosMaxDamage => 15; + public override int AosSpeed => 40; + public override float MlSpeed => 2.75f; - public InternalTarget(BaseCreature c) : base(10, true, TargetFlags.None) => m_Creature = c; + public override int OldStrengthReq => 10; + public override int OldMinDamage => 3; + public override int OldMaxDamage => 12; + public override int OldSpeed => 30; - protected override void OnTarget(Mobile from, object targ) + public override int InitMinHits => 31; + public override int InitMaxHits => 50; + + public override void Serialize(IGenericWriter writer) { - if (targ is IPoint2D p) - { - double min = m_Creature.MinTameSkill - 30; - double max = m_Creature.MinTameSkill + 30 + Utility.Random(10); + base.Serialize(writer); - if (max <= from.Skills.Herding.Value) - m_Creature.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 502471, - from.NetState); // That wasn't even challenging. - - if (from.CheckTargetSkill(SkillName.Herding, m_Creature, min, max)) - { - if (p != from) - p = new Point2D(p.X, p.Y); - - m_Creature.TargetLocation = p; - from.SendLocalizedMessage(502479); // The animal walks where it was instructed to. - } - else - { - from.SendLocalizedMessage(502472); // You don't seem to be able to persuade that to move. - } - } + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (Weight == 2.0) + Weight = 4.0; + } + + public override void OnDoubleClick(Mobile from) + { + from.SendLocalizedMessage(502464); // Target the animal you wish to herd. + from.Target = new HerdingTarget(); + } + + private class HerdingTarget : Target + { + private static readonly Type[] m_ChampTamables = + { + typeof(StrongMongbat), typeof(Imp), typeof(Scorpion), typeof(GiantSpider), + typeof(Snake), typeof(LavaLizard), typeof(Drake), typeof(Dragon), + typeof(Kirin), typeof(Unicorn), typeof(GiantRat), typeof(Slime), + typeof(DireWolf), typeof(HellHound), typeof(DeathwatchBeetle), + typeof(LesserHiryu), typeof(Hiryu) + }; + + public HerdingTarget() : base(10, false, TargetFlags.None) + { + } + + protected override void OnTarget(Mobile from, object targ) + { + if (targ is BaseCreature bc) + { + if (IsHerdable(bc)) + { + if (bc.Controlled) + { + bc.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 502467, + from.NetState + ); // That animal looks tame already. + } + else + { + from.SendLocalizedMessage(502475); // Click where you wish the animal to go. + from.Target = new InternalTarget(bc); + } + } + else + { + from.SendLocalizedMessage(502468); // That is not a herdable animal. + } + } + else + { + from.SendLocalizedMessage(502472); // You don't seem to be able to persuade that to move. + } + } + + private bool IsHerdable(BaseCreature bc) + { + if (bc.IsParagon) + return false; + + if (bc.Tamable) + return true; + + var map = bc.Map; + + if (Region.Find(bc.Home, map) is ChampionSpawnRegion region) + { + var spawn = region.ChampionSpawn; + + if (spawn?.IsChampionSpawn(bc) == true) + { + var t = bc.GetType(); + + foreach (var type in m_ChampTamables) + if (type == t) + return true; + } + } + + return false; + } + + private class InternalTarget : Target + { + private readonly BaseCreature m_Creature; + + public InternalTarget(BaseCreature c) : base(10, true, TargetFlags.None) => m_Creature = c; + + protected override void OnTarget(Mobile from, object targ) + { + if (targ is IPoint2D p) + { + var min = m_Creature.MinTameSkill - 30; + var max = m_Creature.MinTameSkill + 30 + Utility.Random(10); + + if (max <= from.Skills.Herding.Value) + m_Creature.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 502471, + from.NetState + ); // That wasn't even challenging. + + if (from.CheckTargetSkill(SkillName.Herding, m_Creature, min, max)) + { + if (p != from) + p = new Point2D(p.X, p.Y); + + m_Creature.TargetLocation = p; + from.SendLocalizedMessage(502479); // The animal walks where it was instructed to. + } + else + { + from.SendLocalizedMessage(502472); // You don't seem to be able to persuade that to move. + } + } + } + } } - } } - } } diff --git a/Projects/UOContent/Items/Weapons/Swords/AdventurersMachete.cs b/Projects/UOContent/Items/Weapons/Swords/AdventurersMachete.cs index 9624827c0..eda110d6c 100644 --- a/Projects/UOContent/Items/Weapons/Swords/AdventurersMachete.cs +++ b/Projects/UOContent/Items/Weapons/Swords/AdventurersMachete.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class AdventurersMachete : ElvenMachete - { - [Constructible] - public AdventurersMachete() => Attributes.Luck = 20; - - public AdventurersMachete(Serial serial) : base(serial) + public class AdventurersMachete : ElvenMachete { + [Constructible] + public AdventurersMachete() => Attributes.Luck = 20; + + public AdventurersMachete(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073533; // adventurer's machete + + 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(); + } } - - public override int LabelNumber => 1073533; // adventurer's machete - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/BaseSword.cs b/Projects/UOContent/Items/Weapons/Swords/BaseSword.cs index 824e85656..7f3354fac 100644 --- a/Projects/UOContent/Items/Weapons/Swords/BaseSword.cs +++ b/Projects/UOContent/Items/Weapons/Swords/BaseSword.cs @@ -2,52 +2,52 @@ using Server.Targets; namespace Server.Items { - public abstract class BaseSword : BaseMeleeWeapon - { - public BaseSword(int itemID) : base(itemID) + public abstract class BaseSword : BaseMeleeWeapon { + public BaseSword(int itemID) : base(itemID) + { + } + + public BaseSword(Serial serial) : base(serial) + { + } + + public override SkillName DefSkill => SkillName.Swords; + public override WeaponType DefType => WeaponType.Slashing; + public override WeaponAnimation DefAnimation => WeaponAnimation.Slash1H; + + 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(1010018); // What do you want to use this item on? + + from.Target = new BladedItemTarget(this); + } + + public override void OnHit(Mobile attacker, Mobile defender, double damageBonus = 1) + { + base.OnHit(attacker, defender, damageBonus); + + if (!Core.AOS && Poison != null && PoisonCharges > 0) + { + --PoisonCharges; + + if (Utility.RandomDouble() >= 0.5) // 50% chance to poison + defender.ApplyPoison(attacker, Poison); + } + } } - - public BaseSword(Serial serial) : base(serial) - { - } - - public override SkillName DefSkill => SkillName.Swords; - public override WeaponType DefType => WeaponType.Slashing; - public override WeaponAnimation DefAnimation => WeaponAnimation.Slash1H; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnDoubleClick(Mobile from) - { - from.SendLocalizedMessage(1010018); // What do you want to use this item on? - - from.Target = new BladedItemTarget(this); - } - - public override void OnHit(Mobile attacker, Mobile defender, double damageBonus = 1) - { - base.OnHit(attacker, defender, damageBonus); - - if (!Core.AOS && Poison != null && PoisonCharges > 0) - { - --PoisonCharges; - - if (Utility.RandomDouble() >= 0.5) // 50% chance to poison - defender.ApplyPoison(attacker, Poison); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/BoneHarvester.cs b/Projects/UOContent/Items/Weapons/Swords/BoneHarvester.cs index b86c284cf..acb7e1466 100644 --- a/Projects/UOContent/Items/Weapons/Swords/BoneHarvester.cs +++ b/Projects/UOContent/Items/Weapons/Swords/BoneHarvester.cs @@ -1,47 +1,47 @@ namespace Server.Items { - [Flippable(0x26BB, 0x26C5)] - public class BoneHarvester : BaseSword - { - [Constructible] - public BoneHarvester() : base(0x26BB) => Weight = 3.0; - - public BoneHarvester(Serial serial) : base(serial) + [Flippable(0x26BB, 0x26C5)] + public class BoneHarvester : BaseSword { + [Constructible] + public BoneHarvester() : base(0x26BB) => Weight = 3.0; + + public BoneHarvester(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.ParalyzingBlow; + public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike; + + public override int AosStrengthReq => 25; + public override int AosMinDamage => 13; + public override int AosMaxDamage => 15; + public override int AosSpeed => 36; + public override float MlSpeed => 3.00f; + + public override int OldStrengthReq => 25; + public override int OldMinDamage => 13; + public override int OldMaxDamage => 15; + public override int OldSpeed => 36; + + public override int DefHitSound => 0x23B; + public override int DefMissSound => 0x23A; + + public override int InitMinHits => 31; + public override int InitMaxHits => 70; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.ParalyzingBlow; - public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike; - - public override int AosStrengthReq => 25; - public override int AosMinDamage => 13; - public override int AosMaxDamage => 15; - public override int AosSpeed => 36; - public override float MlSpeed => 3.00f; - - public override int OldStrengthReq => 25; - public override int OldMinDamage => 13; - public override int OldMaxDamage => 15; - public override int OldSpeed => 36; - - public override int DefHitSound => 0x23B; - public override int DefMissSound => 0x23A; - - public override int InitMinHits => 31; - public override int InitMaxHits => 70; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/BoneMachete.cs b/Projects/UOContent/Items/Weapons/Swords/BoneMachete.cs index 54657eba7..19f36fe02 100644 --- a/Projects/UOContent/Items/Weapons/Swords/BoneMachete.cs +++ b/Projects/UOContent/Items/Weapons/Swords/BoneMachete.cs @@ -2,55 +2,57 @@ using Server.Engines.MLQuests.Items; namespace Server.Items { - public class BoneMachete : ElvenMachete, ITicket - { - [Constructible] - public BoneMachete() => ItemID = 0x20E; - - public BoneMachete(Serial serial) - : base(serial) + public class BoneMachete : ElvenMachete, ITicket { + [Constructible] + public BoneMachete() => ItemID = 0x20E; + + public BoneMachete(Serial serial) + : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => null; + public override WeaponAbility SecondaryAbility => null; + + public override int PhysicalResistance => 1; + public override int FireResistance => 1; + public override int ColdResistance => 1; + public override int PoisonResistance => 1; + public override int EnergyResistance => 1; + + public override int InitMinHits => 5; + public override int InitMaxHits => 5; + + public void OnTicketUsed(Mobile from) + { + if (Utility.RandomDouble() < 0.25) + { + from.SendLocalizedMessage( + 1075007 + ); // Your bone handled machete snaps in half as you force your way through the poisonous undergrowth. + Delete(); + } + else + { + from.SendLocalizedMessage( + 1075008 + ); // Your bone handled machete has grown dull but you still manage to force your way past the venomous branches. + } + } + + 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(); + } } - - public override WeaponAbility PrimaryAbility => null; - public override WeaponAbility SecondaryAbility => null; - - public override int PhysicalResistance => 1; - public override int FireResistance => 1; - public override int ColdResistance => 1; - public override int PoisonResistance => 1; - public override int EnergyResistance => 1; - - public override int InitMinHits => 5; - public override int InitMaxHits => 5; - - public void OnTicketUsed(Mobile from) - { - if (Utility.RandomDouble() < 0.25) - { - from.SendLocalizedMessage( - 1075007); // Your bone handled machete snaps in half as you force your way through the poisonous undergrowth. - Delete(); - } - else - { - from.SendLocalizedMessage( - 1075008); // Your bone handled machete has grown dull but you still manage to force your way past the venomous branches. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/Broadsword.cs b/Projects/UOContent/Items/Weapons/Swords/Broadsword.cs index c8a107526..30822772a 100644 --- a/Projects/UOContent/Items/Weapons/Swords/Broadsword.cs +++ b/Projects/UOContent/Items/Weapons/Swords/Broadsword.cs @@ -1,47 +1,47 @@ namespace Server.Items { - [Flippable(0xF5E, 0xF5F)] - public class Broadsword : BaseSword - { - [Constructible] - public Broadsword() : base(0xF5E) => Weight = 6.0; - - public Broadsword(Serial serial) : base(serial) + [Flippable(0xF5E, 0xF5F)] + public class Broadsword : BaseSword { + [Constructible] + public Broadsword() : base(0xF5E) => Weight = 6.0; + + public Broadsword(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow; + public override WeaponAbility SecondaryAbility => WeaponAbility.ArmorIgnore; + + public override int AosStrengthReq => 30; + public override int AosMinDamage => 14; + public override int AosMaxDamage => 15; + public override int AosSpeed => 33; + public override float MlSpeed => 3.25f; + + public override int OldStrengthReq => 25; + public override int OldMinDamage => 5; + public override int OldMaxDamage => 29; + public override int OldSpeed => 45; + + public override int DefHitSound => 0x237; + public override int DefMissSound => 0x23A; + + public override int InitMinHits => 31; + public override int InitMaxHits => 100; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow; - public override WeaponAbility SecondaryAbility => WeaponAbility.ArmorIgnore; - - public override int AosStrengthReq => 30; - public override int AosMinDamage => 14; - public override int AosMaxDamage => 15; - public override int AosSpeed => 33; - public override float MlSpeed => 3.25f; - - public override int OldStrengthReq => 25; - public override int OldMinDamage => 5; - public override int OldMaxDamage => 29; - public override int OldSpeed => 45; - - public override int DefHitSound => 0x237; - public override int DefMissSound => 0x23A; - - public override int InitMinHits => 31; - public override int InitMaxHits => 100; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/ChargedAssassinSpike.cs b/Projects/UOContent/Items/Weapons/Swords/ChargedAssassinSpike.cs index fb744d43e..db3c21b1c 100644 --- a/Projects/UOContent/Items/Weapons/Swords/ChargedAssassinSpike.cs +++ b/Projects/UOContent/Items/Weapons/Swords/ChargedAssassinSpike.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class ChargedAssassinSpike : AssassinSpike - { - [Constructible] - public ChargedAssassinSpike() => WeaponAttributes.HitLightning = 10; - - public ChargedAssassinSpike(Serial serial) : base(serial) + public class ChargedAssassinSpike : AssassinSpike { + [Constructible] + public ChargedAssassinSpike() => WeaponAttributes.HitLightning = 10; + + public ChargedAssassinSpike(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073518; // charged assassin spike + + 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(); + } } - - public override int LabelNumber => 1073518; // charged assassin spike - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/CorruptedRuneBlade.cs b/Projects/UOContent/Items/Weapons/Swords/CorruptedRuneBlade.cs index 44867d010..31d2512e2 100644 --- a/Projects/UOContent/Items/Weapons/Swords/CorruptedRuneBlade.cs +++ b/Projects/UOContent/Items/Weapons/Swords/CorruptedRuneBlade.cs @@ -1,32 +1,32 @@ namespace Server.Items { - public class CorruptedRuneBlade : RuneBlade - { - [Constructible] - public CorruptedRuneBlade() + public class CorruptedRuneBlade : RuneBlade { - WeaponAttributes.ResistPhysicalBonus = -5; - WeaponAttributes.ResistPoisonBonus = 12; + [Constructible] + public CorruptedRuneBlade() + { + WeaponAttributes.ResistPhysicalBonus = -5; + WeaponAttributes.ResistPoisonBonus = 12; + } + + public CorruptedRuneBlade(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073540; // Corrupted Rune Blade + + 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(); + } } - - public CorruptedRuneBlade(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073540; // Corrupted Rune Blade - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/CrescentBlade.cs b/Projects/UOContent/Items/Weapons/Swords/CrescentBlade.cs index c36a0b4f6..479288f42 100644 --- a/Projects/UOContent/Items/Weapons/Swords/CrescentBlade.cs +++ b/Projects/UOContent/Items/Weapons/Swords/CrescentBlade.cs @@ -1,47 +1,47 @@ namespace Server.Items { - [Flippable(0x26C1, 0x26CB)] - public class CrescentBlade : BaseSword - { - [Constructible] - public CrescentBlade() : base(0x26C1) => Weight = 1.0; - - public CrescentBlade(Serial serial) : base(serial) + [Flippable(0x26C1, 0x26CB)] + public class CrescentBlade : BaseSword { + [Constructible] + public CrescentBlade() : base(0x26C1) => Weight = 1.0; + + public CrescentBlade(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike; + public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike; + + public override int AosStrengthReq => 55; + public override int AosMinDamage => 11; + public override int AosMaxDamage => 14; + public override int AosSpeed => 47; + public override float MlSpeed => 2.50f; + + public override int OldStrengthReq => 55; + public override int OldMinDamage => 11; + public override int OldMaxDamage => 14; + public override int OldSpeed => 47; + + public override int DefHitSound => 0x23B; + public override int DefMissSound => 0x23A; + + public override int InitMinHits => 51; + public override int InitMaxHits => 80; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike; - public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike; - - public override int AosStrengthReq => 55; - public override int AosMinDamage => 11; - public override int AosMaxDamage => 14; - public override int AosSpeed => 47; - public override float MlSpeed => 2.50f; - - public override int OldStrengthReq => 55; - public override int OldMinDamage => 11; - public override int OldMaxDamage => 14; - public override int OldSpeed => 47; - - public override int DefHitSound => 0x23B; - public override int DefMissSound => 0x23A; - - public override int InitMinHits => 51; - public override int InitMaxHits => 80; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/Cutlass.cs b/Projects/UOContent/Items/Weapons/Swords/Cutlass.cs index 23ca55c81..920bfc787 100644 --- a/Projects/UOContent/Items/Weapons/Swords/Cutlass.cs +++ b/Projects/UOContent/Items/Weapons/Swords/Cutlass.cs @@ -1,47 +1,47 @@ namespace Server.Items { - [Flippable(0x1441, 0x1440)] - public class Cutlass : BaseSword - { - [Constructible] - public Cutlass() : base(0x1441) => Weight = 8.0; - - public Cutlass(Serial serial) : base(serial) + [Flippable(0x1441, 0x1440)] + public class Cutlass : BaseSword { + [Constructible] + public Cutlass() : base(0x1441) => Weight = 8.0; + + public Cutlass(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.BleedAttack; + public override WeaponAbility SecondaryAbility => WeaponAbility.ShadowStrike; + + public override int AosStrengthReq => 25; + public override int AosMinDamage => 11; + public override int AosMaxDamage => 13; + public override int AosSpeed => 44; + public override float MlSpeed => 2.50f; + + public override int OldStrengthReq => 10; + public override int OldMinDamage => 6; + public override int OldMaxDamage => 28; + public override int OldSpeed => 45; + + public override int DefHitSound => 0x23B; + public override int DefMissSound => 0x23A; + + public override int InitMinHits => 31; + public override int InitMaxHits => 70; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.BleedAttack; - public override WeaponAbility SecondaryAbility => WeaponAbility.ShadowStrike; - - public override int AosStrengthReq => 25; - public override int AosMinDamage => 11; - public override int AosMaxDamage => 13; - public override int AosSpeed => 44; - public override float MlSpeed => 2.50f; - - public override int OldStrengthReq => 10; - public override int OldMinDamage => 6; - public override int OldMaxDamage => 28; - public override int OldSpeed => 45; - - public override int DefHitSound => 0x23B; - public override int DefMissSound => 0x23A; - - public override int InitMinHits => 31; - public override int InitMaxHits => 70; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/DarkglowScimitar.cs b/Projects/UOContent/Items/Weapons/Swords/DarkglowScimitar.cs index 49899fcc5..ca2123cc7 100644 --- a/Projects/UOContent/Items/Weapons/Swords/DarkglowScimitar.cs +++ b/Projects/UOContent/Items/Weapons/Swords/DarkglowScimitar.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class DarkglowScimitar : RadiantScimitar - { - [Constructible] - public DarkglowScimitar() => WeaponAttributes.HitDispel = 10; - - public DarkglowScimitar(Serial serial) : base(serial) + public class DarkglowScimitar : RadiantScimitar { + [Constructible] + public DarkglowScimitar() => WeaponAttributes.HitDispel = 10; + + public DarkglowScimitar(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073542; // darkglow scimitar + + 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(); + } } - - public override int LabelNumber => 1073542; // darkglow scimitar - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/DiseasedMachete.cs b/Projects/UOContent/Items/Weapons/Swords/DiseasedMachete.cs index d0a93854b..fbafbfe5b 100644 --- a/Projects/UOContent/Items/Weapons/Swords/DiseasedMachete.cs +++ b/Projects/UOContent/Items/Weapons/Swords/DiseasedMachete.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class DiseasedMachete : ElvenMachete - { - [Constructible] - public DiseasedMachete() => WeaponAttributes.HitPoisonArea = 25; - - public DiseasedMachete(Serial serial) : base(serial) + public class DiseasedMachete : ElvenMachete { + [Constructible] + public DiseasedMachete() => WeaponAttributes.HitPoisonArea = 25; + + public DiseasedMachete(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073536; // Diseased Machete + + 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(); + } } - - public override int LabelNumber => 1073536; // Diseased Machete - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/FierySpellblade.cs b/Projects/UOContent/Items/Weapons/Swords/FierySpellblade.cs index 7d968e5fe..347bc5c16 100644 --- a/Projects/UOContent/Items/Weapons/Swords/FierySpellblade.cs +++ b/Projects/UOContent/Items/Weapons/Swords/FierySpellblade.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class FierySpellblade : ElvenSpellblade - { - [Constructible] - public FierySpellblade() => WeaponAttributes.ResistFireBonus = 5; - - public FierySpellblade(Serial serial) : base(serial) + public class FierySpellblade : ElvenSpellblade { + [Constructible] + public FierySpellblade() => WeaponAttributes.ResistFireBonus = 5; + + public FierySpellblade(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073515; // fiery spellblade + + 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(); + } } - - public override int LabelNumber => 1073515; // fiery spellblade - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/IcyScimitar.cs b/Projects/UOContent/Items/Weapons/Swords/IcyScimitar.cs index a7d314015..ab778c8ee 100644 --- a/Projects/UOContent/Items/Weapons/Swords/IcyScimitar.cs +++ b/Projects/UOContent/Items/Weapons/Swords/IcyScimitar.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class IcyScimitar : RadiantScimitar - { - [Constructible] - public IcyScimitar() => WeaponAttributes.HitHarm = 15; - - public IcyScimitar(Serial serial) : base(serial) + public class IcyScimitar : RadiantScimitar { + [Constructible] + public IcyScimitar() => WeaponAttributes.HitHarm = 15; + + public IcyScimitar(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073543; // icy scimitar + + 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(); + } } - - public override int LabelNumber => 1073543; // icy scimitar - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/IcySpellblade.cs b/Projects/UOContent/Items/Weapons/Swords/IcySpellblade.cs index 6bc6985ff..4e7d3c0d4 100644 --- a/Projects/UOContent/Items/Weapons/Swords/IcySpellblade.cs +++ b/Projects/UOContent/Items/Weapons/Swords/IcySpellblade.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class IcySpellblade : ElvenSpellblade - { - [Constructible] - public IcySpellblade() => WeaponAttributes.ResistColdBonus = 5; - - public IcySpellblade(Serial serial) : base(serial) + public class IcySpellblade : ElvenSpellblade { + [Constructible] + public IcySpellblade() => WeaponAttributes.ResistColdBonus = 5; + + public IcySpellblade(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073514; // icy spellblade + + 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(); + } } - - public override int LabelNumber => 1073514; // icy spellblade - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/Katana.cs b/Projects/UOContent/Items/Weapons/Swords/Katana.cs index ed22d7984..c7192afd7 100644 --- a/Projects/UOContent/Items/Weapons/Swords/Katana.cs +++ b/Projects/UOContent/Items/Weapons/Swords/Katana.cs @@ -1,47 +1,47 @@ namespace Server.Items { - [Flippable(0x13FF, 0x13FE)] - public class Katana : BaseSword - { - [Constructible] - public Katana() : base(0x13FF) => Weight = 6.0; - - public Katana(Serial serial) : base(serial) + [Flippable(0x13FF, 0x13FE)] + public class Katana : BaseSword { + [Constructible] + public Katana() : base(0x13FF) => Weight = 6.0; + + public Katana(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike; + public override WeaponAbility SecondaryAbility => WeaponAbility.ArmorIgnore; + + public override int AosStrengthReq => 25; + public override int AosMinDamage => 11; + public override int AosMaxDamage => 13; + public override int AosSpeed => 46; + public override float MlSpeed => 2.50f; + + public override int OldStrengthReq => 10; + public override int OldMinDamage => 5; + public override int OldMaxDamage => 26; + public override int OldSpeed => 58; + + public override int DefHitSound => 0x23B; + public override int DefMissSound => 0x23A; + + public override int InitMinHits => 31; + public override int InitMaxHits => 90; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike; - public override WeaponAbility SecondaryAbility => WeaponAbility.ArmorIgnore; - - public override int AosStrengthReq => 25; - public override int AosMinDamage => 11; - public override int AosMaxDamage => 13; - public override int AosSpeed => 46; - public override float MlSpeed => 2.50f; - - public override int OldStrengthReq => 10; - public override int OldMinDamage => 5; - public override int OldMaxDamage => 26; - public override int OldSpeed => 58; - - public override int DefHitSound => 0x23B; - public override int DefMissSound => 0x23A; - - public override int InitMinHits => 31; - public override int InitMaxHits => 90; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/KnightsWarCleaver.cs b/Projects/UOContent/Items/Weapons/Swords/KnightsWarCleaver.cs index 921725b35..1b1493a60 100644 --- a/Projects/UOContent/Items/Weapons/Swords/KnightsWarCleaver.cs +++ b/Projects/UOContent/Items/Weapons/Swords/KnightsWarCleaver.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class KnightsWarCleaver : WarCleaver - { - [Constructible] - public KnightsWarCleaver() => Attributes.RegenHits = 3; - - public KnightsWarCleaver(Serial serial) : base(serial) + public class KnightsWarCleaver : WarCleaver { + [Constructible] + public KnightsWarCleaver() => Attributes.RegenHits = 3; + + public KnightsWarCleaver(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073525; // knight's war cleaver + + 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(); + } } - - public override int LabelNumber => 1073525; // knight's war cleaver - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/Kryss.cs b/Projects/UOContent/Items/Weapons/Swords/Kryss.cs index 125949436..9a43a5ca3 100644 --- a/Projects/UOContent/Items/Weapons/Swords/Kryss.cs +++ b/Projects/UOContent/Items/Weapons/Swords/Kryss.cs @@ -1,54 +1,54 @@ namespace Server.Items { - [Flippable(0x1401, 0x1400)] - public class Kryss : BaseSword - { - [Constructible] - public Kryss() : base(0x1401) => Weight = 2.0; - - public Kryss(Serial serial) : base(serial) + [Flippable(0x1401, 0x1400)] + public class Kryss : BaseSword { + [Constructible] + public Kryss() : base(0x1401) => Weight = 2.0; + + public Kryss(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore; + public override WeaponAbility SecondaryAbility => WeaponAbility.InfectiousStrike; + + public override int AosStrengthReq => 10; + public override int AosMinDamage => 10; + public override int AosMaxDamage => 12; + public override int AosSpeed => 53; + public override float MlSpeed => 2.00f; + + public override int OldStrengthReq => 10; + public override int OldMinDamage => 3; + public override int OldMaxDamage => 28; + public override int OldSpeed => 53; + + public override int DefHitSound => 0x23C; + public override int DefMissSound => 0x238; + + public override int InitMinHits => 31; + public override int InitMaxHits => 90; + + public override SkillName DefSkill => SkillName.Fencing; + public override WeaponType DefType => WeaponType.Piercing; + public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H; + + 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 (Weight == 1.0) + Weight = 2.0; + } } - - public override WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore; - public override WeaponAbility SecondaryAbility => WeaponAbility.InfectiousStrike; - - public override int AosStrengthReq => 10; - public override int AosMinDamage => 10; - public override int AosMaxDamage => 12; - public override int AosSpeed => 53; - public override float MlSpeed => 2.00f; - - public override int OldStrengthReq => 10; - public override int OldMinDamage => 3; - public override int OldMaxDamage => 28; - public override int OldSpeed => 53; - - public override int DefHitSound => 0x23C; - public override int DefMissSound => 0x238; - - public override int InitMinHits => 31; - public override int InitMaxHits => 90; - - public override SkillName DefSkill => SkillName.Fencing; - public override WeaponType DefType => WeaponType.Piercing; - public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 1.0) - Weight = 2.0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/Lance.cs b/Projects/UOContent/Items/Weapons/Swords/Lance.cs index 43616bd0d..7fd5d2582 100644 --- a/Projects/UOContent/Items/Weapons/Swords/Lance.cs +++ b/Projects/UOContent/Items/Weapons/Swords/Lance.cs @@ -1,51 +1,51 @@ namespace Server.Items { - [Flippable(0x26C0, 0x26CA)] - public class Lance : BaseSword - { - [Constructible] - public Lance() : base(0x26C0) => Weight = 12.0; - - public Lance(Serial serial) : base(serial) + [Flippable(0x26C0, 0x26CA)] + public class Lance : BaseSword { + [Constructible] + public Lance() : base(0x26C0) => Weight = 12.0; + + public Lance(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.Dismount; + public override WeaponAbility SecondaryAbility => WeaponAbility.ConcussionBlow; + + public override int AosStrengthReq => 95; + public override int AosMinDamage => 17; + public override int AosMaxDamage => 18; + public override int AosSpeed => 24; + public override float MlSpeed => 4.50f; + + public override int OldStrengthReq => 95; + public override int OldMinDamage => 17; + public override int OldMaxDamage => 18; + public override int OldSpeed => 24; + + public override int DefHitSound => 0x23C; + public override int DefMissSound => 0x238; + + public override int InitMinHits => 31; + public override int InitMaxHits => 110; + + public override SkillName DefSkill => SkillName.Fencing; + public override WeaponType DefType => WeaponType.Piercing; + public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.Dismount; - public override WeaponAbility SecondaryAbility => WeaponAbility.ConcussionBlow; - - public override int AosStrengthReq => 95; - public override int AosMinDamage => 17; - public override int AosMaxDamage => 18; - public override int AosSpeed => 24; - public override float MlSpeed => 4.50f; - - public override int OldStrengthReq => 95; - public override int OldMinDamage => 17; - public override int OldMaxDamage => 18; - public override int OldSpeed => 24; - - public override int DefHitSound => 0x23C; - public override int DefMissSound => 0x238; - - public override int InitMinHits => 31; - public override int InitMaxHits => 110; - - public override SkillName DefSkill => SkillName.Fencing; - public override WeaponType DefType => WeaponType.Piercing; - public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/LeafbladeOfEase.cs b/Projects/UOContent/Items/Weapons/Swords/LeafbladeOfEase.cs index 7ac4faf95..47e19a85e 100644 --- a/Projects/UOContent/Items/Weapons/Swords/LeafbladeOfEase.cs +++ b/Projects/UOContent/Items/Weapons/Swords/LeafbladeOfEase.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class LeafbladeOfEase : Leafblade - { - [Constructible] - public LeafbladeOfEase() => WeaponAttributes.UseBestSkill = 1; - - public LeafbladeOfEase(Serial serial) : base(serial) + public class LeafbladeOfEase : Leafblade { + [Constructible] + public LeafbladeOfEase() => WeaponAttributes.UseBestSkill = 1; + + public LeafbladeOfEase(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073524; // leafblade of ease + + 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(); + } } - - public override int LabelNumber => 1073524; // leafblade of ease - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/Longsword.cs b/Projects/UOContent/Items/Weapons/Swords/Longsword.cs index 9a6998947..42a5b988b 100644 --- a/Projects/UOContent/Items/Weapons/Swords/Longsword.cs +++ b/Projects/UOContent/Items/Weapons/Swords/Longsword.cs @@ -1,47 +1,47 @@ namespace Server.Items { - [Flippable(0xF61, 0xF60)] - public class Longsword : BaseSword - { - [Constructible] - public Longsword() : base(0xF61) => Weight = 7.0; - - public Longsword(Serial serial) : base(serial) + [Flippable(0xF61, 0xF60)] + public class Longsword : BaseSword { + [Constructible] + public Longsword() : base(0xF61) => Weight = 7.0; + + public Longsword(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore; + public override WeaponAbility SecondaryAbility => WeaponAbility.ConcussionBlow; + + public override int AosStrengthReq => 35; + public override int AosMinDamage => 15; + public override int AosMaxDamage => 16; + public override int AosSpeed => 30; + public override float MlSpeed => 3.50f; + + public override int OldStrengthReq => 25; + public override int OldMinDamage => 5; + public override int OldMaxDamage => 33; + public override int OldSpeed => 35; + + public override int DefHitSound => 0x237; + public override int DefMissSound => 0x23A; + + public override int InitMinHits => 31; + public override int InitMaxHits => 110; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore; - public override WeaponAbility SecondaryAbility => WeaponAbility.ConcussionBlow; - - public override int AosStrengthReq => 35; - public override int AosMinDamage => 15; - public override int AosMaxDamage => 16; - public override int AosSpeed => 30; - public override float MlSpeed => 3.50f; - - public override int OldStrengthReq => 25; - public override int OldMinDamage => 5; - public override int OldMaxDamage => 33; - public override int OldSpeed => 35; - - public override int DefHitSound => 0x237; - public override int DefMissSound => 0x23A; - - public override int InitMinHits => 31; - public override int InitMaxHits => 110; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/Luckblade.cs b/Projects/UOContent/Items/Weapons/Swords/Luckblade.cs index 29b91dffa..09b6f8282 100644 --- a/Projects/UOContent/Items/Weapons/Swords/Luckblade.cs +++ b/Projects/UOContent/Items/Weapons/Swords/Luckblade.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class Luckblade : Leafblade - { - [Constructible] - public Luckblade() => Attributes.Luck = 20; - - public Luckblade(Serial serial) : base(serial) + public class Luckblade : Leafblade { + [Constructible] + public Luckblade() => Attributes.Luck = 20; + + public Luckblade(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073522; // luckblade + + 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(); + } } - - public override int LabelNumber => 1073522; // luckblade - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/MacheteOfDefense.cs b/Projects/UOContent/Items/Weapons/Swords/MacheteOfDefense.cs index bd93c91e3..f6ce8931e 100644 --- a/Projects/UOContent/Items/Weapons/Swords/MacheteOfDefense.cs +++ b/Projects/UOContent/Items/Weapons/Swords/MacheteOfDefense.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class MacheteOfDefense : ElvenMachete - { - [Constructible] - public MacheteOfDefense() => Attributes.DefendChance = 5; - - public MacheteOfDefense(Serial serial) : base(serial) + public class MacheteOfDefense : ElvenMachete { + [Constructible] + public MacheteOfDefense() => Attributes.DefendChance = 5; + + public MacheteOfDefense(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073535; // machete of defense + + 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(); + } } - - public override int LabelNumber => 1073535; // machete of defense - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/MagekillerAssassinSpike.cs b/Projects/UOContent/Items/Weapons/Swords/MagekillerAssassinSpike.cs index ba0358bc7..9f522ed37 100644 --- a/Projects/UOContent/Items/Weapons/Swords/MagekillerAssassinSpike.cs +++ b/Projects/UOContent/Items/Weapons/Swords/MagekillerAssassinSpike.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class MagekillerAssassinSpike : AssassinSpike - { - [Constructible] - public MagekillerAssassinSpike() => WeaponAttributes.HitLeechMana = 16; - - public MagekillerAssassinSpike(Serial serial) : base(serial) + public class MagekillerAssassinSpike : AssassinSpike { + [Constructible] + public MagekillerAssassinSpike() => WeaponAttributes.HitLeechMana = 16; + + public MagekillerAssassinSpike(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073519; // magekiller assassin spike + + 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(); + } } - - public override int LabelNumber => 1073519; // magekiller assassin spike - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/MagekillerLeafblade.cs b/Projects/UOContent/Items/Weapons/Swords/MagekillerLeafblade.cs index 0ddde2e41..939a38f09 100644 --- a/Projects/UOContent/Items/Weapons/Swords/MagekillerLeafblade.cs +++ b/Projects/UOContent/Items/Weapons/Swords/MagekillerLeafblade.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class MagekillerLeafblade : Leafblade - { - [Constructible] - public MagekillerLeafblade() => WeaponAttributes.HitLeechMana = 16; - - public MagekillerLeafblade(Serial serial) : base(serial) + public class MagekillerLeafblade : Leafblade { + [Constructible] + public MagekillerLeafblade() => WeaponAttributes.HitLeechMana = 16; + + public MagekillerLeafblade(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073523; // maagekiller leafblade + + 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(); + } } - - public override int LabelNumber => 1073523; // maagekiller leafblade - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/MagesRuneBlade.cs b/Projects/UOContent/Items/Weapons/Swords/MagesRuneBlade.cs index a8dfe5277..8878c4879 100644 --- a/Projects/UOContent/Items/Weapons/Swords/MagesRuneBlade.cs +++ b/Projects/UOContent/Items/Weapons/Swords/MagesRuneBlade.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class MagesRuneBlade : RuneBlade - { - [Constructible] - public MagesRuneBlade() => Attributes.CastSpeed = 1; - - public MagesRuneBlade(Serial serial) : base(serial) + public class MagesRuneBlade : RuneBlade { + [Constructible] + public MagesRuneBlade() => Attributes.CastSpeed = 1; + + public MagesRuneBlade(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073538; // mage's rune blade + + 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(); + } } - - public override int LabelNumber => 1073538; // mage's rune blade - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/OrcishMachete.cs b/Projects/UOContent/Items/Weapons/Swords/OrcishMachete.cs index e834749ac..7a5f2b24f 100644 --- a/Projects/UOContent/Items/Weapons/Swords/OrcishMachete.cs +++ b/Projects/UOContent/Items/Weapons/Swords/OrcishMachete.cs @@ -1,32 +1,32 @@ namespace Server.Items { - public class OrcishMachete : ElvenMachete - { - [Constructible] - public OrcishMachete() + public class OrcishMachete : ElvenMachete { - Attributes.BonusInt = -5; - Attributes.WeaponDamage = 10; + [Constructible] + public OrcishMachete() + { + Attributes.BonusInt = -5; + Attributes.WeaponDamage = 10; + } + + public OrcishMachete(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073534; // Orcish Machete + + 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(); + } } - - public OrcishMachete(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073534; // Orcish Machete - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/RuneBladeOfKnowledge.cs b/Projects/UOContent/Items/Weapons/Swords/RuneBladeOfKnowledge.cs index 53417227c..591978394 100644 --- a/Projects/UOContent/Items/Weapons/Swords/RuneBladeOfKnowledge.cs +++ b/Projects/UOContent/Items/Weapons/Swords/RuneBladeOfKnowledge.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class RuneBladeOfKnowledge : RuneBlade - { - [Constructible] - public RuneBladeOfKnowledge() => Attributes.SpellDamage = 5; - - public RuneBladeOfKnowledge(Serial serial) : base(serial) + public class RuneBladeOfKnowledge : RuneBlade { + [Constructible] + public RuneBladeOfKnowledge() => Attributes.SpellDamage = 5; + + public RuneBladeOfKnowledge(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073539; // rune blade of knowledge + + 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(); + } } - - public override int LabelNumber => 1073539; // rune blade of knowledge - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/Runesabre.cs b/Projects/UOContent/Items/Weapons/Swords/Runesabre.cs index 77601e4b1..fb1437f4e 100644 --- a/Projects/UOContent/Items/Weapons/Swords/Runesabre.cs +++ b/Projects/UOContent/Items/Weapons/Swords/Runesabre.cs @@ -1,32 +1,32 @@ namespace Server.Items { - public class Runesabre : RuneBlade - { - [Constructible] - public Runesabre() + public class Runesabre : RuneBlade { - SkillBonuses.SetValues(0, SkillName.MagicResist, 5.0); - WeaponAttributes.MageWeapon = -29; + [Constructible] + public Runesabre() + { + SkillBonuses.SetValues(0, SkillName.MagicResist, 5.0); + WeaponAttributes.MageWeapon = -29; + } + + public Runesabre(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073537; // runesabre + + 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(); + } } - - public Runesabre(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073537; // runesabre - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/Scimitar.cs b/Projects/UOContent/Items/Weapons/Swords/Scimitar.cs index 59001b784..a0be1b489 100644 --- a/Projects/UOContent/Items/Weapons/Swords/Scimitar.cs +++ b/Projects/UOContent/Items/Weapons/Swords/Scimitar.cs @@ -1,47 +1,47 @@ namespace Server.Items { - [Flippable(0x13B6, 0x13B5)] - public class Scimitar : BaseSword - { - [Constructible] - public Scimitar() : base(0x13B6) => Weight = 5.0; - - public Scimitar(Serial serial) : base(serial) + [Flippable(0x13B6, 0x13B5)] + public class Scimitar : BaseSword { + [Constructible] + public Scimitar() : base(0x13B6) => Weight = 5.0; + + public Scimitar(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike; + public override WeaponAbility SecondaryAbility => WeaponAbility.ParalyzingBlow; + + public override int AosStrengthReq => 25; + public override int AosMinDamage => 13; + public override int AosMaxDamage => 15; + public override int AosSpeed => 37; + public override float MlSpeed => 3.00f; + + public override int OldStrengthReq => 10; + public override int OldMinDamage => 4; + public override int OldMaxDamage => 30; + public override int OldSpeed => 43; + + public override int DefHitSound => 0x23B; + public override int DefMissSound => 0x23A; + + public override int InitMinHits => 31; + public override int InitMaxHits => 90; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike; - public override WeaponAbility SecondaryAbility => WeaponAbility.ParalyzingBlow; - - public override int AosStrengthReq => 25; - public override int AosMinDamage => 13; - public override int AosMaxDamage => 15; - public override int AosSpeed => 37; - public override float MlSpeed => 3.00f; - - public override int OldStrengthReq => 10; - public override int OldMinDamage => 4; - public override int OldMaxDamage => 30; - public override int OldSpeed => 43; - - public override int DefHitSound => 0x23B; - public override int DefMissSound => 0x23A; - - public override int InitMinHits => 31; - public override int InitMaxHits => 90; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/SerratedWarCleaver.cs b/Projects/UOContent/Items/Weapons/Swords/SerratedWarCleaver.cs index 22144eca7..e72c28458 100644 --- a/Projects/UOContent/Items/Weapons/Swords/SerratedWarCleaver.cs +++ b/Projects/UOContent/Items/Weapons/Swords/SerratedWarCleaver.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class SerratedWarCleaver : WarCleaver - { - [Constructible] - public SerratedWarCleaver() => Attributes.WeaponDamage = 7; - - public SerratedWarCleaver(Serial serial) : base(serial) + public class SerratedWarCleaver : WarCleaver { + [Constructible] + public SerratedWarCleaver() => Attributes.WeaponDamage = 7; + + public SerratedWarCleaver(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073527; // serrated war cleaver + + 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(); + } } - - public override int LabelNumber => 1073527; // serrated war cleaver - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/SpellbladeOfDefense.cs b/Projects/UOContent/Items/Weapons/Swords/SpellbladeOfDefense.cs index 1da917f98..3ef82fb48 100644 --- a/Projects/UOContent/Items/Weapons/Swords/SpellbladeOfDefense.cs +++ b/Projects/UOContent/Items/Weapons/Swords/SpellbladeOfDefense.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class SpellbladeOfDefense : ElvenSpellblade - { - [Constructible] - public SpellbladeOfDefense() => Attributes.DefendChance = 5; - - public SpellbladeOfDefense(Serial serial) : base(serial) + public class SpellbladeOfDefense : ElvenSpellblade { + [Constructible] + public SpellbladeOfDefense() => Attributes.DefendChance = 5; + + public SpellbladeOfDefense(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073516; // spellblade of defense + + 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(); + } } - - public override int LabelNumber => 1073516; // spellblade of defense - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/ThinLongsword.cs b/Projects/UOContent/Items/Weapons/Swords/ThinLongsword.cs index d43554427..a17a11845 100644 --- a/Projects/UOContent/Items/Weapons/Swords/ThinLongsword.cs +++ b/Projects/UOContent/Items/Weapons/Swords/ThinLongsword.cs @@ -1,44 +1,44 @@ namespace Server.Items { - [Flippable(0x13B8, 0x13B7)] - public class ThinLongsword : BaseSword - { - [Constructible] - public ThinLongsword() : base(0x13B8) => Weight = 1.0; - - public ThinLongsword(Serial serial) : base(serial) + [Flippable(0x13B8, 0x13B7)] + public class ThinLongsword : BaseSword { + [Constructible] + public ThinLongsword() : base(0x13B8) => Weight = 1.0; + + public ThinLongsword(Serial serial) : base(serial) + { + } + + public override int AosStrengthReq => 35; + public override int AosMinDamage => 15; + public override int AosMaxDamage => 16; + public override int AosSpeed => 30; + public override float MlSpeed => 3.50f; + + public override int OldStrengthReq => 25; + public override int OldMinDamage => 5; + public override int OldMaxDamage => 33; + public override int OldSpeed => 35; + + public override int DefHitSound => 0x237; + public override int DefMissSound => 0x23A; + + public override int InitMinHits => 31; + public override int InitMaxHits => 110; + + 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 int AosStrengthReq => 35; - public override int AosMinDamage => 15; - public override int AosMaxDamage => 16; - public override int AosSpeed => 30; - public override float MlSpeed => 3.50f; - - public override int OldStrengthReq => 25; - public override int OldMinDamage => 5; - public override int OldMaxDamage => 33; - public override int OldSpeed => 35; - - public override int DefHitSound => 0x237; - public override int DefMissSound => 0x23A; - - public override int InitMinHits => 31; - public override int InitMaxHits => 110; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/TrueAssassinSpike.cs b/Projects/UOContent/Items/Weapons/Swords/TrueAssassinSpike.cs index 91d1123e2..9cf877eba 100644 --- a/Projects/UOContent/Items/Weapons/Swords/TrueAssassinSpike.cs +++ b/Projects/UOContent/Items/Weapons/Swords/TrueAssassinSpike.cs @@ -1,32 +1,32 @@ namespace Server.Items { - public class TrueAssassinSpike : AssassinSpike - { - [Constructible] - public TrueAssassinSpike() + public class TrueAssassinSpike : AssassinSpike { - Attributes.AttackChance = 4; - Attributes.WeaponDamage = 4; + [Constructible] + public TrueAssassinSpike() + { + Attributes.AttackChance = 4; + Attributes.WeaponDamage = 4; + } + + public TrueAssassinSpike(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073517; // true assassin spike + + 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(); + } } - - public TrueAssassinSpike(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073517; // true assassin spike - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/TrueLeafblade.cs b/Projects/UOContent/Items/Weapons/Swords/TrueLeafblade.cs index f7d78cc8c..8c50b73a9 100644 --- a/Projects/UOContent/Items/Weapons/Swords/TrueLeafblade.cs +++ b/Projects/UOContent/Items/Weapons/Swords/TrueLeafblade.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class TrueLeafblade : Leafblade - { - [Constructible] - public TrueLeafblade() => WeaponAttributes.ResistPoisonBonus = 5; - - public TrueLeafblade(Serial serial) : base(serial) + public class TrueLeafblade : Leafblade { + [Constructible] + public TrueLeafblade() => WeaponAttributes.ResistPoisonBonus = 5; + + public TrueLeafblade(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073521; // true leafblade + + 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(); + } } - - public override int LabelNumber => 1073521; // true leafblade - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/TrueRadiantScimitar.cs b/Projects/UOContent/Items/Weapons/Swords/TrueRadiantScimitar.cs index 004fd1364..bd3578382 100644 --- a/Projects/UOContent/Items/Weapons/Swords/TrueRadiantScimitar.cs +++ b/Projects/UOContent/Items/Weapons/Swords/TrueRadiantScimitar.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class TrueRadiantScimitar : RadiantScimitar - { - [Constructible] - public TrueRadiantScimitar() => Attributes.NightSight = 1; - - public TrueRadiantScimitar(Serial serial) : base(serial) + public class TrueRadiantScimitar : RadiantScimitar { + [Constructible] + public TrueRadiantScimitar() => Attributes.NightSight = 1; + + public TrueRadiantScimitar(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073541; // true radiant scimitar + + 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(); + } } - - public override int LabelNumber => 1073541; // true radiant scimitar - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/TrueSpellblade.cs b/Projects/UOContent/Items/Weapons/Swords/TrueSpellblade.cs index 4774abdca..a5460b999 100644 --- a/Projects/UOContent/Items/Weapons/Swords/TrueSpellblade.cs +++ b/Projects/UOContent/Items/Weapons/Swords/TrueSpellblade.cs @@ -1,32 +1,32 @@ namespace Server.Items { - public class TrueSpellblade : ElvenSpellblade - { - [Constructible] - public TrueSpellblade() + public class TrueSpellblade : ElvenSpellblade { - Attributes.SpellChanneling = 1; - Attributes.CastSpeed = -1; + [Constructible] + public TrueSpellblade() + { + Attributes.SpellChanneling = 1; + Attributes.CastSpeed = -1; + } + + public TrueSpellblade(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073513; // true spellblade + + 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(); + } } - - public TrueSpellblade(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073513; // true spellblade - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/TrueWarCleaver.cs b/Projects/UOContent/Items/Weapons/Swords/TrueWarCleaver.cs index e9416595c..9766a3f96 100644 --- a/Projects/UOContent/Items/Weapons/Swords/TrueWarCleaver.cs +++ b/Projects/UOContent/Items/Weapons/Swords/TrueWarCleaver.cs @@ -1,32 +1,32 @@ namespace Server.Items { - public class TrueWarCleaver : WarCleaver - { - [Constructible] - public TrueWarCleaver() + public class TrueWarCleaver : WarCleaver { - Attributes.WeaponDamage = 4; - Attributes.RegenHits = 2; + [Constructible] + public TrueWarCleaver() + { + Attributes.WeaponDamage = 4; + Attributes.RegenHits = 2; + } + + public TrueWarCleaver(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073528; // true war cleaver + + 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(); + } } - - public TrueWarCleaver(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073528; // true war cleaver - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/TwinklingScimitar.cs b/Projects/UOContent/Items/Weapons/Swords/TwinklingScimitar.cs index 2d70db01c..934f3892a 100644 --- a/Projects/UOContent/Items/Weapons/Swords/TwinklingScimitar.cs +++ b/Projects/UOContent/Items/Weapons/Swords/TwinklingScimitar.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class TwinklingScimitar : RadiantScimitar - { - [Constructible] - public TwinklingScimitar() => Attributes.DefendChance = 6; - - public TwinklingScimitar(Serial serial) : base(serial) + public class TwinklingScimitar : RadiantScimitar { + [Constructible] + public TwinklingScimitar() => Attributes.DefendChance = 6; + + public TwinklingScimitar(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073544; // twinkling scimitar + + 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(); + } } - - public override int LabelNumber => 1073544; // twinkling scimitar - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/VikingSword.cs b/Projects/UOContent/Items/Weapons/Swords/VikingSword.cs index e67c2b554..58215823e 100644 --- a/Projects/UOContent/Items/Weapons/Swords/VikingSword.cs +++ b/Projects/UOContent/Items/Weapons/Swords/VikingSword.cs @@ -1,47 +1,47 @@ namespace Server.Items { - [Flippable(0x13B9, 0x13Ba)] - public class VikingSword : BaseSword - { - [Constructible] - public VikingSword() : base(0x13B9) => Weight = 6.0; - - public VikingSword(Serial serial) : base(serial) + [Flippable(0x13B9, 0x13Ba)] + public class VikingSword : BaseSword { + [Constructible] + public VikingSword() : base(0x13B9) => Weight = 6.0; + + public VikingSword(Serial serial) : base(serial) + { + } + + public override WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow; + public override WeaponAbility SecondaryAbility => WeaponAbility.ParalyzingBlow; + + public override int AosStrengthReq => 40; + public override int AosMinDamage => 15; + public override int AosMaxDamage => 17; + public override int AosSpeed => 28; + public override float MlSpeed => 3.75f; + + public override int OldStrengthReq => 40; + public override int OldMinDamage => 6; + public override int OldMaxDamage => 34; + public override int OldSpeed => 30; + + public override int DefHitSound => 0x237; + public override int DefMissSound => 0x23A; + + public override int InitMinHits => 31; + public override int InitMaxHits => 100; + + 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 WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow; - public override WeaponAbility SecondaryAbility => WeaponAbility.ParalyzingBlow; - - public override int AosStrengthReq => 40; - public override int AosMinDamage => 15; - public override int AosMaxDamage => 17; - public override int AosSpeed => 28; - public override float MlSpeed => 3.75f; - - public override int OldStrengthReq => 40; - public override int OldMinDamage => 6; - public override int OldMaxDamage => 34; - public override int OldSpeed => 30; - - public override int DefHitSound => 0x237; - public override int DefMissSound => 0x23A; - - public override int InitMinHits => 31; - public override int InitMaxHits => 100; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Swords/WoundingAssassinSpike.cs b/Projects/UOContent/Items/Weapons/Swords/WoundingAssassinSpike.cs index 991ed7846..3a8388074 100644 --- a/Projects/UOContent/Items/Weapons/Swords/WoundingAssassinSpike.cs +++ b/Projects/UOContent/Items/Weapons/Swords/WoundingAssassinSpike.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class WoundingAssassinSpike : AssassinSpike - { - [Constructible] - public WoundingAssassinSpike() => WeaponAttributes.HitHarm = 15; - - public WoundingAssassinSpike(Serial serial) : base(serial) + public class WoundingAssassinSpike : AssassinSpike { + [Constructible] + public WoundingAssassinSpike() => WeaponAttributes.HitHarm = 15; + + public WoundingAssassinSpike(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073520; // wounding assassin spike + + 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(); + } } - - public override int LabelNumber => 1073520; // wounding assassin spike - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/WeaponEnums.cs b/Projects/UOContent/Items/Weapons/WeaponEnums.cs index 89ac3a9e7..b09563f05 100644 --- a/Projects/UOContent/Items/Weapons/WeaponEnums.cs +++ b/Projects/UOContent/Items/Weapons/WeaponEnums.cs @@ -1,64 +1,64 @@ namespace Server.Items { - public enum WeaponQuality - { - Low, - Regular, - Exceptional - } + public enum WeaponQuality + { + Low, + Regular, + Exceptional + } - public enum WeaponType - { - Axe, // Axes, Hatches, etc. These can give concussion blows - Slashing, // Katana, Broadsword, Longsword, etc. Slashing weapons are poisonable - Staff, // Staves - Bashing, // War Hammers, Maces, Mauls, etc. Two-handed bashing delivers crushing blows - Piercing, // Spears, Warforks, Daggers, etc. Two-handed piercing delivers paralyzing blows - Polearm, // Halberd, Bardiche - Ranged, // Bow, Crossbows - Fists // Fists - } + public enum WeaponType + { + Axe, // Axes, Hatches, etc. These can give concussion blows + Slashing, // Katana, Broadsword, Longsword, etc. Slashing weapons are poisonable + Staff, // Staves + Bashing, // War Hammers, Maces, Mauls, etc. Two-handed bashing delivers crushing blows + Piercing, // Spears, Warforks, Daggers, etc. Two-handed piercing delivers paralyzing blows + Polearm, // Halberd, Bardiche + Ranged, // Bow, Crossbows + Fists // Fists + } - public enum WeaponDamageLevel - { - Regular, - Ruin, - Might, - Force, - Power, - Vanq - } + public enum WeaponDamageLevel + { + Regular, + Ruin, + Might, + Force, + Power, + Vanq + } - public enum WeaponAccuracyLevel - { - Regular, - Accurate, - Surpassingly, - Eminently, - Exceedingly, - Supremely - } + public enum WeaponAccuracyLevel + { + Regular, + Accurate, + Surpassingly, + Eminently, + Exceedingly, + Supremely + } - public enum WeaponDurabilityLevel - { - Regular, - Durable, - Substantial, - Massive, - Fortified, - Indestructible - } + public enum WeaponDurabilityLevel + { + Regular, + Durable, + Substantial, + Massive, + Fortified, + Indestructible + } - public enum WeaponAnimation - { - Slash1H = 9, - Pierce1H = 10, - Bash1H = 11, - Bash2H = 12, - Slash2H = 13, - Pierce2H = 14, - ShootBow = 18, - ShootXBow = 19, - Wrestle = 31 - } -} \ No newline at end of file + public enum WeaponAnimation + { + Slash1H = 9, + Pierce1H = 10, + Bash1H = 11, + Bash2H = 12, + Slash2H = 13, + Pierce2H = 14, + ShootBow = 18, + ShootXBow = 19, + Wrestle = 31 + } +} diff --git a/Projects/UOContent/Items/Weapons/Wooden/AncientWildStaff.cs b/Projects/UOContent/Items/Weapons/Wooden/AncientWildStaff.cs index 098f60159..12cf818b8 100644 --- a/Projects/UOContent/Items/Weapons/Wooden/AncientWildStaff.cs +++ b/Projects/UOContent/Items/Weapons/Wooden/AncientWildStaff.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class AncientWildStaff : WildStaff - { - [Constructible] - public AncientWildStaff() => WeaponAttributes.ResistPoisonBonus = 5; - - public AncientWildStaff(Serial serial) : base(serial) + public class AncientWildStaff : WildStaff { + [Constructible] + public AncientWildStaff() => WeaponAttributes.ResistPoisonBonus = 5; + + public AncientWildStaff(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073550; // ancient wild staff + + 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(); + } } - - public override int LabelNumber => 1073550; // ancient wild staff - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Wooden/ArcanistsWildStaff.cs b/Projects/UOContent/Items/Weapons/Wooden/ArcanistsWildStaff.cs index f0997ee7e..a9e7497a4 100644 --- a/Projects/UOContent/Items/Weapons/Wooden/ArcanistsWildStaff.cs +++ b/Projects/UOContent/Items/Weapons/Wooden/ArcanistsWildStaff.cs @@ -1,32 +1,32 @@ namespace Server.Items { - public class ArcanistsWildStaff : WildStaff - { - [Constructible] - public ArcanistsWildStaff() + public class ArcanistsWildStaff : WildStaff { - Attributes.BonusMana = 3; - Attributes.WeaponDamage = 3; + [Constructible] + public ArcanistsWildStaff() + { + Attributes.BonusMana = 3; + Attributes.WeaponDamage = 3; + } + + public ArcanistsWildStaff(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073549; // arcanist's wild staff + + 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(); + } } - - public ArcanistsWildStaff(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1073549; // arcanist's wild staff - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Wooden/HardenedWildStaff.cs b/Projects/UOContent/Items/Weapons/Wooden/HardenedWildStaff.cs index 9416762b6..4fa7b6a0a 100644 --- a/Projects/UOContent/Items/Weapons/Wooden/HardenedWildStaff.cs +++ b/Projects/UOContent/Items/Weapons/Wooden/HardenedWildStaff.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class HardenedWildStaff : WildStaff - { - [Constructible] - public HardenedWildStaff() => Attributes.WeaponDamage = 5; - - public HardenedWildStaff(Serial serial) : base(serial) + public class HardenedWildStaff : WildStaff { + [Constructible] + public HardenedWildStaff() => Attributes.WeaponDamage = 5; + + public HardenedWildStaff(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073552; // hardened wild staff + + 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(); + } } - - public override int LabelNumber => 1073552; // hardened wild staff - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Items/Weapons/Wooden/ThornedWildStaff.cs b/Projects/UOContent/Items/Weapons/Wooden/ThornedWildStaff.cs index aa1d08e48..d34066fc6 100644 --- a/Projects/UOContent/Items/Weapons/Wooden/ThornedWildStaff.cs +++ b/Projects/UOContent/Items/Weapons/Wooden/ThornedWildStaff.cs @@ -1,28 +1,28 @@ namespace Server.Items { - public class ThornedWildStaff : WildStaff - { - [Constructible] - public ThornedWildStaff() => Attributes.ReflectPhysical = 12; - - public ThornedWildStaff(Serial serial) : base(serial) + public class ThornedWildStaff : WildStaff { + [Constructible] + public ThornedWildStaff() => Attributes.ReflectPhysical = 12; + + public ThornedWildStaff(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1073551; // thorned wild staff + + 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(); + } } - - public override int LabelNumber => 1073551; // thorned wild staff - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Json/Converters/TextDefinitionConverter.cs b/Projects/UOContent/Json/Converters/TextDefinitionConverter.cs index 68ed81a95..265c9ca41 100644 --- a/Projects/UOContent/Json/Converters/TextDefinitionConverter.cs +++ b/Projects/UOContent/Json/Converters/TextDefinitionConverter.cs @@ -25,22 +25,22 @@ using System.Text.Json.Serialization; namespace Server.Json { - public class TextDefinitionConverter : JsonConverter - { - public override TextDefinition Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => - reader.TokenType switch - { - JsonTokenType.String => new TextDefinition(reader.GetString()), - JsonTokenType.Number => new TextDefinition(reader.GetInt32()), - _ => throw new JsonException("TextDefinition value must be an integer or string") - }; - - public override void Write(Utf8JsonWriter writer, TextDefinition value, JsonSerializerOptions options) + public class TextDefinitionConverter : JsonConverter { - if (value.Number > 0) - writer.WriteNumberValue(value.Number); - else - writer.WriteStringValue(value.String); + public override TextDefinition Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => + reader.TokenType switch + { + JsonTokenType.String => new TextDefinition(reader.GetString()), + JsonTokenType.Number => new TextDefinition(reader.GetInt32()), + _ => throw new JsonException("TextDefinition value must be an integer or string") + }; + + public override void Write(Utf8JsonWriter writer, TextDefinition value, JsonSerializerOptions options) + { + if (value.Number > 0) + writer.WriteNumberValue(value.Number); + else + writer.WriteStringValue(value.String); + } } - } } diff --git a/Projects/UOContent/Json/Converters/TextDefinitionConverterFactory.cs b/Projects/UOContent/Json/Converters/TextDefinitionConverterFactory.cs index aaaa161f4..3b69b990c 100644 --- a/Projects/UOContent/Json/Converters/TextDefinitionConverterFactory.cs +++ b/Projects/UOContent/Json/Converters/TextDefinitionConverterFactory.cs @@ -25,11 +25,11 @@ using System.Text.Json.Serialization; namespace Server.Json { - public class TextDefinitionConverterFactory : JsonConverterFactory - { - public override bool CanConvert(Type typeToConvert) => typeToConvert == typeof(TextDefinition); + public class TextDefinitionConverterFactory : JsonConverterFactory + { + public override bool CanConvert(Type typeToConvert) => typeToConvert == typeof(TextDefinition); - public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) => - new TextDefinitionConverter(); - } + public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) => + new TextDefinitionConverter(); + } } diff --git a/Projects/UOContent/Misc/AOS.cs b/Projects/UOContent/Misc/AOS.cs index cd548c33e..6078e0cda 100644 --- a/Projects/UOContent/Misc/AOS.cs +++ b/Projects/UOContent/Misc/AOS.cs @@ -9,1448 +9,1461 @@ using Server.Spells.Seventh; namespace Server { - public class AOS - { - public static void DisableStatInfluences() + public class AOS { - for (int i = 0; i < SkillInfo.Table.Length; ++i) - { - SkillInfo info = SkillInfo.Table[i]; - - info.StrScale = 0.0; - info.DexScale = 0.0; - info.IntScale = 0.0; - info.StatTotal = 0.0; - } - } - - public static int Damage(Mobile m, int damage, bool ignoreArmor, int phys, int fire, int cold, int pois, int nrgy) => Damage(m, null, damage, ignoreArmor, phys, fire, cold, pois, nrgy); - - public static int Damage(Mobile m, int damage, int phys, int fire, int cold, int pois, int nrgy) => Damage(m, null, damage, phys, fire, cold, pois, nrgy); - - public static int Damage(Mobile m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy) => Damage(m, from, damage, false, phys, fire, cold, pois, nrgy); - - public static int Damage(Mobile m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, - int chaos) => - Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, chaos); - - public static int Damage(Mobile m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, - bool keepAlive) => - Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, 0, 0, keepAlive); - - public static int Damage(Mobile m, Mobile from, int damage, bool ignoreArmor, int phys, int fire, int cold, int pois, - int nrgy, int chaos = 0, int direct = 0, bool keepAlive = false, bool archer = false, bool deathStrike = false) - { - if (m?.Deleted != false || !m.Alive || damage <= 0) - return 0; - - if (phys == 0 && fire == 100 && cold == 0 && pois == 0 && nrgy == 0) - MeerMage.StopEffect(m, true); - - if (!Core.AOS) - { - m.Damage(damage, from); - return damage; - } - - Fix(ref phys); - Fix(ref fire); - Fix(ref cold); - Fix(ref pois); - Fix(ref nrgy); - Fix(ref chaos); - Fix(ref direct); - - if (Core.ML && chaos > 0) - switch (Utility.Random(5)) + public static void DisableStatInfluences() { - case 0: - phys += chaos; - break; - case 1: - fire += chaos; - break; - case 2: - cold += chaos; - break; - case 3: - pois += chaos; - break; - case 4: - nrgy += chaos; - break; + for (var i = 0; i < SkillInfo.Table.Length; ++i) + { + var info = SkillInfo.Table[i]; + + info.StrScale = 0.0; + info.DexScale = 0.0; + info.IntScale = 0.0; + info.StatTotal = 0.0; + } } - BaseQuiver quiver = null; + public static int Damage(Mobile m, int damage, bool ignoreArmor, int phys, int fire, int cold, int pois, int nrgy) => + Damage(m, null, damage, ignoreArmor, phys, fire, cold, pois, nrgy); - if (archer && from != null) - quiver = from.FindItemOnLayer(Layer.Cloak) as BaseQuiver; + public static int Damage(Mobile m, int damage, int phys, int fire, int cold, int pois, int nrgy) => + Damage(m, null, damage, phys, fire, cold, pois, nrgy); - int totalDamage; + public static int Damage(Mobile m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy) => + Damage(m, from, damage, false, phys, fire, cold, pois, nrgy); - if (!ignoreArmor) - { - // Armor Ignore on OSI ignores all defenses, not just physical. - int resPhys = m.PhysicalResistance; - int resFire = m.FireResistance; - int resCold = m.ColdResistance; - int resPois = m.PoisonResistance; - int resNrgy = m.EnergyResistance; + public static int Damage( + Mobile m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, + int chaos + ) => + Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, chaos); - totalDamage = damage * phys * (100 - resPhys); - totalDamage += damage * fire * (100 - resFire); - totalDamage += damage * cold * (100 - resCold); - totalDamage += damage * pois * (100 - resPois); - totalDamage += damage * nrgy * (100 - resNrgy); + public static int Damage( + Mobile m, Mobile from, int damage, int phys, int fire, int cold, int pois, int nrgy, + bool keepAlive + ) => + Damage(m, from, damage, false, phys, fire, cold, pois, nrgy, 0, 0, keepAlive); - totalDamage /= 10000; - - if (Core.ML) + public static int Damage( + Mobile m, Mobile from, int damage, bool ignoreArmor, int phys, int fire, int cold, int pois, + int nrgy, int chaos = 0, int direct = 0, bool keepAlive = false, bool archer = false, bool deathStrike = false + ) { - totalDamage += damage * direct / 100; + if (m?.Deleted != false || !m.Alive || damage <= 0) + return 0; - if (quiver != null) - totalDamage += totalDamage * quiver.DamageIncrease / 100; + if (phys == 0 && fire == 100 && cold == 0 && pois == 0 && nrgy == 0) + MeerMage.StopEffect(m, true); + + if (!Core.AOS) + { + m.Damage(damage, from); + return damage; + } + + Fix(ref phys); + Fix(ref fire); + Fix(ref cold); + Fix(ref pois); + Fix(ref nrgy); + Fix(ref chaos); + Fix(ref direct); + + if (Core.ML && chaos > 0) + switch (Utility.Random(5)) + { + case 0: + phys += chaos; + break; + case 1: + fire += chaos; + break; + case 2: + cold += chaos; + break; + case 3: + pois += chaos; + break; + case 4: + nrgy += chaos; + break; + } + + BaseQuiver quiver = null; + + if (archer && from != null) + quiver = from.FindItemOnLayer(Layer.Cloak) as BaseQuiver; + + int totalDamage; + + if (!ignoreArmor) + { + // Armor Ignore on OSI ignores all defenses, not just physical. + var resPhys = m.PhysicalResistance; + var resFire = m.FireResistance; + var resCold = m.ColdResistance; + var resPois = m.PoisonResistance; + var resNrgy = m.EnergyResistance; + + totalDamage = damage * phys * (100 - resPhys); + totalDamage += damage * fire * (100 - resFire); + totalDamage += damage * cold * (100 - resCold); + totalDamage += damage * pois * (100 - resPois); + totalDamage += damage * nrgy * (100 - resNrgy); + + totalDamage /= 10000; + + if (Core.ML) + { + totalDamage += damage * direct / 100; + + if (quiver != null) + totalDamage += totalDamage * quiver.DamageIncrease / 100; + } + + if (totalDamage < 1) + totalDamage = 1; + } + else if (Core.ML && m is PlayerMobile && from is PlayerMobile) + { + if (quiver != null) + damage += damage * quiver.DamageIncrease / 100; + + if (!deathStrike) + totalDamage = Math.Min(damage, 35); // Direct Damage cap of 35 + else + totalDamage = Math.Min(damage, 70); // Direct Damage cap of 70 + } + else + { + totalDamage = damage; + + if (Core.ML && quiver != null) + totalDamage += totalDamage * quiver.DamageIncrease / 100; + } + + if (from?.Player != true && m.Player && m.Mount is SwampDragon pet) + if (pet.HasBarding) + { + var percent = pet.BardingExceptional ? 20 : 10; + var absorbed = Scale(totalDamage, percent); + + totalDamage -= absorbed; + pet.BardingHP -= absorbed; + + if (pet.BardingHP < 0) + { + pet.HasBarding = false; + pet.BardingHP = 0; + + m.SendLocalizedMessage(1053031); // Your dragon's barding has been destroyed! + } + } + + if (keepAlive && totalDamage > m.Hits) + totalDamage = m.Hits; + + if (from?.Deleted == false && from.Alive) + { + var reflectPhys = AosAttributes.GetValue(m, AosAttribute.ReflectPhysical); + + if (reflectPhys != 0) + { + if ((from as ExodusMinion)?.FieldActive == true || + (from as ExodusOverseer)?.FieldActive == true) + { + from.FixedParticles(0x376A, 20, 10, 0x2530, EffectLayer.Waist); + from.PlaySound(0x2F4); + m.SendAsciiMessage("Your weapon cannot penetrate the creature's magical barrier"); + } + else + { + from.Damage( + Scale(damage * phys * (100 - (ignoreArmor ? 0 : m.PhysicalResistance)) / 10000, reflectPhys), + m + ); + } + } + } + + m.Damage(totalDamage, from); + return totalDamage; } - if (totalDamage < 1) - totalDamage = 1; - } - else if (Core.ML && m is PlayerMobile && from is PlayerMobile) - { - if (quiver != null) - damage += damage * quiver.DamageIncrease / 100; - - if (!deathStrike) - totalDamage = Math.Min(damage, 35); // Direct Damage cap of 35 - else - totalDamage = Math.Min(damage, 70); // Direct Damage cap of 70 - } - else - { - totalDamage = damage; - - if (Core.ML && quiver != null) - totalDamage += totalDamage * quiver.DamageIncrease / 100; - } - - if (from?.Player != true && m.Player && m.Mount is SwampDragon pet) - if (pet.HasBarding) + public static void Fix(ref int val) { - int percent = pet.BardingExceptional ? 20 : 10; - int absorbed = Scale(totalDamage, percent); - - totalDamage -= absorbed; - pet.BardingHP -= absorbed; - - if (pet.BardingHP < 0) - { - pet.HasBarding = false; - pet.BardingHP = 0; - - m.SendLocalizedMessage(1053031); // Your dragon's barding has been destroyed! - } + if (val < 0) + val = 0; } - if (keepAlive && totalDamage > m.Hits) - totalDamage = m.Hits; + public static int Scale(int input, int percent) => input * percent / 100; - if (from?.Deleted == false && from.Alive) - { - int reflectPhys = AosAttributes.GetValue(m, AosAttribute.ReflectPhysical); - - if (reflectPhys != 0) + public static int GetStatus(Mobile from, int index) { - if ((from as ExodusMinion)?.FieldActive == true || - (from as ExodusOverseer)?.FieldActive == true) - { - from.FixedParticles(0x376A, 20, 10, 0x2530, EffectLayer.Waist); - from.PlaySound(0x2F4); - m.SendAsciiMessage("Your weapon cannot penetrate the creature's magical barrier"); - } - else - { - from.Damage( - Scale(damage * phys * (100 - (ignoreArmor ? 0 : m.PhysicalResistance)) / 10000, reflectPhys), m); - } + return index switch + { + // TODO: Account for buffs/debuffs + 0 => from.GetMaxResistance(ResistanceType.Physical), + 1 => from.GetMaxResistance(ResistanceType.Fire), + 2 => from.GetMaxResistance(ResistanceType.Cold), + 3 => from.GetMaxResistance(ResistanceType.Poison), + 4 => from.GetMaxResistance(ResistanceType.Energy), + 5 => AosAttributes.GetValue(from, AosAttribute.DefendChance), + 6 => 45, + 7 => AosAttributes.GetValue(from, AosAttribute.AttackChance), + 8 => AosAttributes.GetValue(from, AosAttribute.WeaponSpeed), + 9 => AosAttributes.GetValue(from, AosAttribute.WeaponDamage), + 10 => AosAttributes.GetValue(from, AosAttribute.LowerRegCost), + 11 => AosAttributes.GetValue(from, AosAttribute.SpellDamage), + 12 => AosAttributes.GetValue(from, AosAttribute.CastRecovery), + 13 => AosAttributes.GetValue(from, AosAttribute.CastSpeed), + 14 => AosAttributes.GetValue(from, AosAttribute.LowerManaCost), + _ => 0 + }; } - } - - m.Damage(totalDamage, from); - return totalDamage; } - public static void Fix(ref int val) + [Flags] + public enum AosAttribute { - if (val < 0) - val = 0; + RegenHits = 0x00000001, + RegenStam = 0x00000002, + RegenMana = 0x00000004, + DefendChance = 0x00000008, + AttackChance = 0x00000010, + BonusStr = 0x00000020, + BonusDex = 0x00000040, + BonusInt = 0x00000080, + BonusHits = 0x00000100, + BonusStam = 0x00000200, + BonusMana = 0x00000400, + WeaponDamage = 0x00000800, + WeaponSpeed = 0x00001000, + SpellDamage = 0x00002000, + CastRecovery = 0x00004000, + CastSpeed = 0x00008000, + LowerManaCost = 0x00010000, + LowerRegCost = 0x00020000, + ReflectPhysical = 0x00040000, + EnhancePotions = 0x00080000, + Luck = 0x00100000, + SpellChanneling = 0x00200000, + NightSight = 0x00400000, + IncreasedKarmaLoss = 0x00800000 } - public static int Scale(int input, int percent) => input * percent / 100; - - public static int GetStatus(Mobile from, int index) + public sealed class AosAttributes : BaseAttributes { - return index switch - { - // TODO: Account for buffs/debuffs - 0 => from.GetMaxResistance(ResistanceType.Physical), - 1 => from.GetMaxResistance(ResistanceType.Fire), - 2 => from.GetMaxResistance(ResistanceType.Cold), - 3 => from.GetMaxResistance(ResistanceType.Poison), - 4 => from.GetMaxResistance(ResistanceType.Energy), - 5 => AosAttributes.GetValue(from, AosAttribute.DefendChance), - 6 => 45, - 7 => AosAttributes.GetValue(from, AosAttribute.AttackChance), - 8 => AosAttributes.GetValue(from, AosAttribute.WeaponSpeed), - 9 => AosAttributes.GetValue(from, AosAttribute.WeaponDamage), - 10 => AosAttributes.GetValue(from, AosAttribute.LowerRegCost), - 11 => AosAttributes.GetValue(from, AosAttribute.SpellDamage), - 12 => AosAttributes.GetValue(from, AosAttribute.CastRecovery), - 13 => AosAttributes.GetValue(from, AosAttribute.CastSpeed), - 14 => AosAttributes.GetValue(from, AosAttribute.LowerManaCost), - _ => 0 - }; - } - } - - [Flags] - public enum AosAttribute - { - RegenHits = 0x00000001, - RegenStam = 0x00000002, - RegenMana = 0x00000004, - DefendChance = 0x00000008, - AttackChance = 0x00000010, - BonusStr = 0x00000020, - BonusDex = 0x00000040, - BonusInt = 0x00000080, - BonusHits = 0x00000100, - BonusStam = 0x00000200, - BonusMana = 0x00000400, - WeaponDamage = 0x00000800, - WeaponSpeed = 0x00001000, - SpellDamage = 0x00002000, - CastRecovery = 0x00004000, - CastSpeed = 0x00008000, - LowerManaCost = 0x00010000, - LowerRegCost = 0x00020000, - ReflectPhysical = 0x00040000, - EnhancePotions = 0x00080000, - Luck = 0x00100000, - SpellChanneling = 0x00200000, - NightSight = 0x00400000, - IncreasedKarmaLoss = 0x00800000 - } - - public sealed class AosAttributes : BaseAttributes - { - public AosAttributes(Item owner) - : base(owner) - { - } - - public AosAttributes(Item owner, AosAttributes other) - : base(owner, other) - { - } - - public AosAttributes(Item owner, IGenericReader reader) - : base(owner, reader) - { - } - - public int this[AosAttribute attribute] - { - get => GetValue((int)attribute); - set => SetValue((int)attribute, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public int RegenHits - { - get => this[AosAttribute.RegenHits]; - set => this[AosAttribute.RegenHits] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int RegenStam - { - get => this[AosAttribute.RegenStam]; - set => this[AosAttribute.RegenStam] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int RegenMana - { - get => this[AosAttribute.RegenMana]; - set => this[AosAttribute.RegenMana] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int DefendChance - { - get => this[AosAttribute.DefendChance]; - set => this[AosAttribute.DefendChance] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int AttackChance - { - get => this[AosAttribute.AttackChance]; - set => this[AosAttribute.AttackChance] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int BonusStr - { - get => this[AosAttribute.BonusStr]; - set => this[AosAttribute.BonusStr] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int BonusDex - { - get => this[AosAttribute.BonusDex]; - set => this[AosAttribute.BonusDex] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int BonusInt - { - get => this[AosAttribute.BonusInt]; - set => this[AosAttribute.BonusInt] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int BonusHits - { - get => this[AosAttribute.BonusHits]; - set => this[AosAttribute.BonusHits] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int BonusStam - { - get => this[AosAttribute.BonusStam]; - set => this[AosAttribute.BonusStam] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int BonusMana - { - get => this[AosAttribute.BonusMana]; - set => this[AosAttribute.BonusMana] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int WeaponDamage - { - get => this[AosAttribute.WeaponDamage]; - set => this[AosAttribute.WeaponDamage] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int WeaponSpeed - { - get => this[AosAttribute.WeaponSpeed]; - set => this[AosAttribute.WeaponSpeed] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int SpellDamage - { - get => this[AosAttribute.SpellDamage]; - set => this[AosAttribute.SpellDamage] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int CastRecovery - { - get => this[AosAttribute.CastRecovery]; - set => this[AosAttribute.CastRecovery] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int CastSpeed - { - get => this[AosAttribute.CastSpeed]; - set => this[AosAttribute.CastSpeed] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int LowerManaCost - { - get => this[AosAttribute.LowerManaCost]; - set => this[AosAttribute.LowerManaCost] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int LowerRegCost - { - get => this[AosAttribute.LowerRegCost]; - set => this[AosAttribute.LowerRegCost] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int ReflectPhysical - { - get => this[AosAttribute.ReflectPhysical]; - set => this[AosAttribute.ReflectPhysical] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int EnhancePotions - { - get => this[AosAttribute.EnhancePotions]; - set => this[AosAttribute.EnhancePotions] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Luck - { - get => this[AosAttribute.Luck]; - set => this[AosAttribute.Luck] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int SpellChanneling - { - get => this[AosAttribute.SpellChanneling]; - set => this[AosAttribute.SpellChanneling] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int NightSight - { - get => this[AosAttribute.NightSight]; - set => this[AosAttribute.NightSight] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int IncreasedKarmaLoss - { - get => this[AosAttribute.IncreasedKarmaLoss]; - set => this[AosAttribute.IncreasedKarmaLoss] = value; - } - - public static int GetValue(Mobile m, AosAttribute attribute) - { - if (!Core.AOS) - return 0; - - List items = m.Items; - int value = 0; - - for (int i = 0; i < items.Count; ++i) - { - Item obj = items[i]; - - if (obj is BaseWeapon weapon) + public AosAttributes(Item owner) + : base(owner) { - AosAttributes attrs = weapon.Attributes; - - if (attrs != null) - value += attrs[attribute]; - - if (attribute == AosAttribute.Luck) - value += weapon.GetLuckBonus(); } - else if (obj is BaseArmor armor) + + public AosAttributes(Item owner, AosAttributes other) + : base(owner, other) { - AosAttributes attrs = armor.Attributes; - - if (attrs != null) - value += attrs[attribute]; - - if (attribute == AosAttribute.Luck) - value += armor.GetLuckBonus(); } - else if (obj is BaseJewel jewel) - { - AosAttributes attrs = jewel.Attributes; - if (attrs != null) - value += attrs[attribute]; + public AosAttributes(Item owner, IGenericReader reader) + : base(owner, reader) + { } - else if (obj is BaseClothing clothing) - { - AosAttributes attrs = clothing.Attributes; - if (attrs != null) - value += attrs[attribute]; + public int this[AosAttribute attribute] + { + get => GetValue((int)attribute); + set => SetValue((int)attribute, value); } - else if (obj is Spellbook spellbook) - { - AosAttributes attrs = spellbook.Attributes; - if (attrs != null) - value += attrs[attribute]; + [CommandProperty(AccessLevel.GameMaster)] + public int RegenHits + { + get => this[AosAttribute.RegenHits]; + set => this[AosAttribute.RegenHits] = value; } - else if (obj is BaseQuiver quiver) - { - AosAttributes attrs = quiver.Attributes; - if (attrs != null) - value += attrs[attribute]; + [CommandProperty(AccessLevel.GameMaster)] + public int RegenStam + { + get => this[AosAttribute.RegenStam]; + set => this[AosAttribute.RegenStam] = value; } - else if (obj is BaseTalisman talisman) - { - AosAttributes attrs = talisman.Attributes; - if (attrs != null) - value += attrs[attribute]; + [CommandProperty(AccessLevel.GameMaster)] + public int RegenMana + { + get => this[AosAttribute.RegenMana]; + set => this[AosAttribute.RegenMana] = value; } - } - return value; - } - - public override string ToString() => "..."; - - public void AddStatBonuses(Mobile to) - { - int strBonus = BonusStr; - int dexBonus = BonusDex; - int intBonus = BonusInt; - - if (strBonus != 0 || dexBonus != 0 || intBonus != 0) - { - string modName = Owner.Serial.ToString(); - - if (strBonus != 0) - to.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero)); - - if (dexBonus != 0) - to.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero)); - - if (intBonus != 0) - to.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero)); - } - - to.CheckStatTimers(); - } - - public void RemoveStatBonuses(Mobile from) - { - string modName = Owner.Serial.ToString(); - - from.RemoveStatMod($"{modName}Str"); - from.RemoveStatMod($"{modName}Dex"); - from.RemoveStatMod($"{modName}Int"); - - from.CheckStatTimers(); - } - } - - [Flags] - public enum AosWeaponAttribute - { - LowerStatReq = 0x00000001, - SelfRepair = 0x00000002, - HitLeechHits = 0x00000004, - HitLeechStam = 0x00000008, - HitLeechMana = 0x00000010, - HitLowerAttack = 0x00000020, - HitLowerDefend = 0x00000040, - HitMagicArrow = 0x00000080, - HitHarm = 0x00000100, - HitFireball = 0x00000200, - HitLightning = 0x00000400, - HitDispel = 0x00000800, - HitColdArea = 0x00001000, - HitFireArea = 0x00002000, - HitPoisonArea = 0x00004000, - HitEnergyArea = 0x00008000, - HitPhysicalArea = 0x00010000, - ResistPhysicalBonus = 0x00020000, - ResistFireBonus = 0x00040000, - ResistColdBonus = 0x00080000, - ResistPoisonBonus = 0x00100000, - ResistEnergyBonus = 0x00200000, - UseBestSkill = 0x00400000, - MageWeapon = 0x00800000, - DurabilityBonus = 0x01000000 - } - - public sealed class AosWeaponAttributes : BaseAttributes - { - public AosWeaponAttributes(Item owner) - : base(owner) - { - } - - public AosWeaponAttributes(Item owner, AosWeaponAttributes other) - : base(owner, other) - { - } - - public AosWeaponAttributes(Item owner, IGenericReader reader) - : base(owner, reader) - { - } - - public int this[AosWeaponAttribute attribute] - { - get => GetValue((int)attribute); - set => SetValue((int)attribute, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public int LowerStatReq - { - get => this[AosWeaponAttribute.LowerStatReq]; - set => this[AosWeaponAttribute.LowerStatReq] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int SelfRepair - { - get => this[AosWeaponAttribute.SelfRepair]; - set => this[AosWeaponAttribute.SelfRepair] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int HitLeechHits - { - get => this[AosWeaponAttribute.HitLeechHits]; - set => this[AosWeaponAttribute.HitLeechHits] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int HitLeechStam - { - get => this[AosWeaponAttribute.HitLeechStam]; - set => this[AosWeaponAttribute.HitLeechStam] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int HitLeechMana - { - get => this[AosWeaponAttribute.HitLeechMana]; - set => this[AosWeaponAttribute.HitLeechMana] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int HitLowerAttack - { - get => this[AosWeaponAttribute.HitLowerAttack]; - set => this[AosWeaponAttribute.HitLowerAttack] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int HitLowerDefend - { - get => this[AosWeaponAttribute.HitLowerDefend]; - set => this[AosWeaponAttribute.HitLowerDefend] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int HitMagicArrow - { - get => this[AosWeaponAttribute.HitMagicArrow]; - set => this[AosWeaponAttribute.HitMagicArrow] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int HitHarm - { - get => this[AosWeaponAttribute.HitHarm]; - set => this[AosWeaponAttribute.HitHarm] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int HitFireball - { - get => this[AosWeaponAttribute.HitFireball]; - set => this[AosWeaponAttribute.HitFireball] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int HitLightning - { - get => this[AosWeaponAttribute.HitLightning]; - set => this[AosWeaponAttribute.HitLightning] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int HitDispel - { - get => this[AosWeaponAttribute.HitDispel]; - set => this[AosWeaponAttribute.HitDispel] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int HitColdArea - { - get => this[AosWeaponAttribute.HitColdArea]; - set => this[AosWeaponAttribute.HitColdArea] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int HitFireArea - { - get => this[AosWeaponAttribute.HitFireArea]; - set => this[AosWeaponAttribute.HitFireArea] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int HitPoisonArea - { - get => this[AosWeaponAttribute.HitPoisonArea]; - set => this[AosWeaponAttribute.HitPoisonArea] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int HitEnergyArea - { - get => this[AosWeaponAttribute.HitEnergyArea]; - set => this[AosWeaponAttribute.HitEnergyArea] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int HitPhysicalArea - { - get => this[AosWeaponAttribute.HitPhysicalArea]; - set => this[AosWeaponAttribute.HitPhysicalArea] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int ResistPhysicalBonus - { - get => this[AosWeaponAttribute.ResistPhysicalBonus]; - set => this[AosWeaponAttribute.ResistPhysicalBonus] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int ResistFireBonus - { - get => this[AosWeaponAttribute.ResistFireBonus]; - set => this[AosWeaponAttribute.ResistFireBonus] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int ResistColdBonus - { - get => this[AosWeaponAttribute.ResistColdBonus]; - set => this[AosWeaponAttribute.ResistColdBonus] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int ResistPoisonBonus - { - get => this[AosWeaponAttribute.ResistPoisonBonus]; - set => this[AosWeaponAttribute.ResistPoisonBonus] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int ResistEnergyBonus - { - get => this[AosWeaponAttribute.ResistEnergyBonus]; - set => this[AosWeaponAttribute.ResistEnergyBonus] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int UseBestSkill - { - get => this[AosWeaponAttribute.UseBestSkill]; - set => this[AosWeaponAttribute.UseBestSkill] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int MageWeapon - { - get => this[AosWeaponAttribute.MageWeapon]; - set => this[AosWeaponAttribute.MageWeapon] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int DurabilityBonus - { - get => this[AosWeaponAttribute.DurabilityBonus]; - set => this[AosWeaponAttribute.DurabilityBonus] = value; - } - - public static int GetValue(Mobile m, AosWeaponAttribute attribute) - { - if (!Core.AOS) - return 0; - - List items = m.Items; - int value = 0; - - for (int i = 0; i < items.Count; ++i) - { - Item obj = items[i]; - - if (obj is BaseWeapon weapon) + [CommandProperty(AccessLevel.GameMaster)] + public int DefendChance { - AosWeaponAttributes attrs = weapon.WeaponAttributes; - - if (attrs != null) - value += attrs[attribute]; + get => this[AosAttribute.DefendChance]; + set => this[AosAttribute.DefendChance] = value; } - else if (obj is ElvenGlasses glasses) - { - AosWeaponAttributes attrs = glasses.WeaponAttributes; - if (attrs != null) - value += attrs[attribute]; + [CommandProperty(AccessLevel.GameMaster)] + public int AttackChance + { + get => this[AosAttribute.AttackChance]; + set => this[AosAttribute.AttackChance] = value; } - } - return value; - } - - public override string ToString() => "..."; - } - - [Flags] - public enum AosArmorAttribute - { - LowerStatReq = 0x00000001, - SelfRepair = 0x00000002, - MageArmor = 0x00000004, - DurabilityBonus = 0x00000008 - } - - public sealed class AosArmorAttributes : BaseAttributes - { - public AosArmorAttributes(Item owner) - : base(owner) - { - } - - public AosArmorAttributes(Item owner, IGenericReader reader) - : base(owner, reader) - { - } - - public AosArmorAttributes(Item owner, AosArmorAttributes other) - : base(owner, other) - { - } - - public int this[AosArmorAttribute attribute] - { - get => GetValue((int)attribute); - set => SetValue((int)attribute, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public int LowerStatReq - { - get => this[AosArmorAttribute.LowerStatReq]; - set => this[AosArmorAttribute.LowerStatReq] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int SelfRepair - { - get => this[AosArmorAttribute.SelfRepair]; - set => this[AosArmorAttribute.SelfRepair] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int MageArmor - { - get => this[AosArmorAttribute.MageArmor]; - set => this[AosArmorAttribute.MageArmor] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int DurabilityBonus - { - get => this[AosArmorAttribute.DurabilityBonus]; - set => this[AosArmorAttribute.DurabilityBonus] = value; - } - - public static int GetValue(Mobile m, AosArmorAttribute attribute) - { - if (!Core.AOS) - return 0; - - List items = m.Items; - int value = 0; - - for (int i = 0; i < items.Count; ++i) - { - Item obj = items[i]; - - if (obj is BaseArmor armor) + [CommandProperty(AccessLevel.GameMaster)] + public int BonusStr { - AosArmorAttributes attrs = armor.ArmorAttributes; - - if (attrs != null) - value += attrs[attribute]; + get => this[AosAttribute.BonusStr]; + set => this[AosAttribute.BonusStr] = value; } - else if (obj is BaseClothing clothing) - { - AosArmorAttributes attrs = clothing.ClothingAttributes; - if (attrs != null) - value += attrs[attribute]; + [CommandProperty(AccessLevel.GameMaster)] + public int BonusDex + { + get => this[AosAttribute.BonusDex]; + set => this[AosAttribute.BonusDex] = value; } - } - return value; - } - - public override string ToString() => "..."; - } - - public sealed class AosSkillBonuses : BaseAttributes - { - private List m_Mods; - - public AosSkillBonuses(Item owner) - : base(owner) - { - } - - public AosSkillBonuses(Item owner, IGenericReader reader) - : base(owner, reader) - { - } - - public AosSkillBonuses(Item owner, AosSkillBonuses other) - : base(owner, other) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public double Skill_1_Value - { - get => GetBonus(0); - set => SetBonus(0, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public SkillName Skill_1_Name - { - get => GetSkill(0); - set => SetSkill(0, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public double Skill_2_Value - { - get => GetBonus(1); - set => SetBonus(1, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public SkillName Skill_2_Name - { - get => GetSkill(1); - set => SetSkill(1, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public double Skill_3_Value - { - get => GetBonus(2); - set => SetBonus(2, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public SkillName Skill_3_Name - { - get => GetSkill(2); - set => SetSkill(2, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public double Skill_4_Value - { - get => GetBonus(3); - set => SetBonus(3, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public SkillName Skill_4_Name - { - get => GetSkill(3); - set => SetSkill(3, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public double Skill_5_Value - { - get => GetBonus(4); - set => SetBonus(4, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public SkillName Skill_5_Name - { - get => GetSkill(4); - set => SetSkill(4, value); - } - - public void GetProperties(ObjectPropertyList list) - { - for (int i = 0; i < 5; ++i) - if (GetValues(i, out SkillName skill, out double bonus)) - list.Add(1060451 + i, "#{0}\t{1}", GetLabel(skill), bonus); - } - - public static int GetLabel(SkillName skill) - { - return skill switch - { - SkillName.EvalInt => 1002070, // Evaluate Intelligence - SkillName.Forensics => 1002078, // Forensic Evaluation - SkillName.Lockpicking => 1002097, // Lockpicking - _ => 1044060 + (int)skill - }; - } - - public void AddTo(Mobile m) - { - Remove(); - - for (int i = 0; i < 5; ++i) - { - if (!GetValues(i, out SkillName skill, out double bonus)) - continue; - - m_Mods ??= new List(); - - SkillMod sk = new DefaultSkillMod(skill, true, bonus); - sk.ObeyCap = true; - m.AddSkillMod(sk); - m_Mods.Add(sk); - } - } - - public void Remove() - { - if (m_Mods == null) - return; - - for (int i = 0; i < m_Mods.Count; ++i) - { - Mobile m = m_Mods[i].Owner; - m_Mods[i].Remove(); - - if (Core.ML) - CheckCancelMorph(m); - } - - m_Mods = null; - } - - public bool GetValues(int index, out SkillName skill, out double bonus) - { - int v = GetValue(1 << index); - int vSkill = 0; - int vBonus = 0; - - for (int i = 0; i < 16; ++i) - { - vSkill <<= 1; - vSkill |= v & 1; - v >>= 1; - - vBonus <<= 1; - vBonus |= v & 1; - v >>= 1; - } - - skill = (SkillName)vSkill; - bonus = (double)vBonus / 10; - - return bonus != 0; - } - - public void SetValues(int index, SkillName skill, double bonus) - { - int v = 0; - int vSkill = (int)skill; - int vBonus = (int)(bonus * 10); - - for (int i = 0; i < 16; ++i) - { - v <<= 1; - v |= vBonus & 1; - vBonus >>= 1; - - v <<= 1; - v |= vSkill & 1; - vSkill >>= 1; - } - - SetValue(1 << index, v); - } - - public SkillName GetSkill(int index) - { - GetValues(index, out SkillName skill, out double _); - - return skill; - } - - public void SetSkill(int index, SkillName skill) - { - SetValues(index, skill, GetBonus(index)); - } - - public double GetBonus(int index) - { - GetValues(index, out SkillName _, out double bonus); - - return bonus; - } - - public void SetBonus(int index, double bonus) - { - SetValues(index, GetSkill(index), bonus); - } - - public override string ToString() => "..."; - - public void CheckCancelMorph(Mobile m) - { - if (m == null) - return; - - AnimalFormContext acontext = AnimalForm.GetContext(m); - TransformContext context = TransformationSpellHelper.GetContext(m); - - if (context?.Spell is Spell spell) - { - spell.GetCastSkills(out double minSkill, out _); - if (m.Skills[spell.CastSkill].Value < minSkill) - TransformationSpellHelper.RemoveContext(m, context, true); - } - - if (acontext != null) - { - int i; - for (i = 0; i < AnimalForm.Entries.Length; ++i) - if (AnimalForm.Entries[i].Type == acontext.Type) - break; - if (m.Skills.Ninjitsu.Value < AnimalForm.Entries[i].ReqSkill) - AnimalForm.RemoveContext(m, true); - } - - if (!m.CanBeginAction() && m.Skills.Magery.Value < 66.1) - { - m.BodyMod = 0; - m.HueMod = -1; - m.NameMod = null; - m.EndAction(); - BaseArmor.ValidateMobile(m); - BaseClothing.ValidateMobile(m); - } - - if (!m.CanBeginAction() && m.Skills.Magery.Value < 38.1) - { - if (m is PlayerMobile mobile) - mobile.SetHairMods(-1, -1); - m.BodyMod = 0; - m.HueMod = -1; - m.NameMod = null; - m.EndAction(); - BaseArmor.ValidateMobile(m); - BaseClothing.ValidateMobile(m); - BuffInfo.RemoveBuff(m, BuffIcon.Incognito); - } - } - } - - [Flags] - public enum AosElementAttribute - { - Physical = 0x00000001, - Fire = 0x00000002, - Cold = 0x00000004, - Poison = 0x00000008, - Energy = 0x00000010, - Chaos = 0x00000020, - Direct = 0x00000040 - } - - public sealed class AosElementAttributes : BaseAttributes - { - public AosElementAttributes(Item owner) - : base(owner) - { - } - - public AosElementAttributes(Item owner, AosElementAttributes other) - : base(owner, other) - { - } - - public AosElementAttributes(Item owner, IGenericReader reader) - : base(owner, reader) - { - } - - public int this[AosElementAttribute attribute] - { - get => GetValue((int)attribute); - set => SetValue((int)attribute, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Physical - { - get => this[AosElementAttribute.Physical]; - set => this[AosElementAttribute.Physical] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Fire - { - get => this[AosElementAttribute.Fire]; - set => this[AosElementAttribute.Fire] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Cold - { - get => this[AosElementAttribute.Cold]; - set => this[AosElementAttribute.Cold] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Poison - { - get => this[AosElementAttribute.Poison]; - set => this[AosElementAttribute.Poison] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Energy - { - get => this[AosElementAttribute.Energy]; - set => this[AosElementAttribute.Energy] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Chaos - { - get => this[AosElementAttribute.Chaos]; - set => this[AosElementAttribute.Chaos] = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Direct - { - get => this[AosElementAttribute.Direct]; - set => this[AosElementAttribute.Direct] = value; - } - - public override string ToString() => "..."; - } - - [PropertyObject] - public abstract class BaseAttributes - { - private static readonly int[] m_Empty = Array.Empty(); - private uint m_Names; - private int[] m_Values; - - public BaseAttributes(Item owner) - { - Owner = owner; - m_Values = m_Empty; - } - - public BaseAttributes(Item owner, BaseAttributes other) - { - Owner = owner; - m_Values = new int[other.m_Values.Length]; - other.m_Values.CopyTo(m_Values, 0); - m_Names = other.m_Names; - } - - public BaseAttributes(Item owner, IGenericReader reader) - { - Owner = owner; - - int version = reader.ReadByte(); - - switch (version) - { - case 1: - { - m_Names = reader.ReadUInt(); - m_Values = new int[reader.ReadEncodedInt()]; - - for (int i = 0; i < m_Values.Length; ++i) - m_Values[i] = reader.ReadEncodedInt(); - - break; - } - case 0: - { - m_Names = reader.ReadUInt(); - m_Values = new int[reader.ReadInt()]; - - for (int i = 0; i < m_Values.Length; ++i) - m_Values[i] = reader.ReadInt(); - - break; - } - } - } - - public bool IsEmpty => m_Names == 0; - public Item Owner { get; } - - public void Serialize(IGenericWriter writer) - { - writer.Write((byte)1); // version; - - writer.Write(m_Names); - writer.WriteEncodedInt(m_Values.Length); - - for (int i = 0; i < m_Values.Length; ++i) - writer.WriteEncodedInt(m_Values[i]); - } - - public int GetValue(int bitmask) - { - if (!Core.AOS) - return 0; - - uint mask = (uint)bitmask; - - if ((m_Names & mask) == 0) - return 0; - - int index = GetIndex(mask); - - if (index >= 0 && index < m_Values.Length) - return m_Values[index]; - - return 0; - } - - public void SetValue(int bitmask, int value) - { - if (bitmask == (int)AosWeaponAttribute.DurabilityBonus && this is AosWeaponAttributes) - { - if (Owner is BaseWeapon weapon) - weapon.UnscaleDurability(); - } - else if (bitmask == (int)AosArmorAttribute.DurabilityBonus && this is AosArmorAttributes) - { - if (Owner is BaseArmor armor) - armor.UnscaleDurability(); - else if (Owner is BaseClothing clothing) - clothing.UnscaleDurability(); - } - - uint mask = (uint)bitmask; - - if (value != 0) - { - if ((m_Names & mask) != 0) + [CommandProperty(AccessLevel.GameMaster)] + public int BonusInt { - int index = GetIndex(mask); - - if (index >= 0 && index < m_Values.Length) - m_Values[index] = value; + get => this[AosAttribute.BonusInt]; + set => this[AosAttribute.BonusInt] = value; } - else + + [CommandProperty(AccessLevel.GameMaster)] + public int BonusHits { - int index = GetIndex(mask); - - if (index >= 0 && index <= m_Values.Length) - { - int[] old = m_Values; - m_Values = new int[old.Length + 1]; - - for (int i = 0; i < index; ++i) - m_Values[i] = old[i]; - - m_Values[index] = value; - - for (int i = index; i < old.Length; ++i) - m_Values[i + 1] = old[i]; - - m_Names |= mask; - } + get => this[AosAttribute.BonusHits]; + set => this[AosAttribute.BonusHits] = value; } - } - else if ((m_Names & mask) != 0) - { - int index = GetIndex(mask); - if (index >= 0 && index < m_Values.Length) + [CommandProperty(AccessLevel.GameMaster)] + public int BonusStam { - m_Names &= ~mask; + get => this[AosAttribute.BonusStam]; + set => this[AosAttribute.BonusStam] = value; + } - if (m_Values.Length == 1) - { + [CommandProperty(AccessLevel.GameMaster)] + public int BonusMana + { + get => this[AosAttribute.BonusMana]; + set => this[AosAttribute.BonusMana] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int WeaponDamage + { + get => this[AosAttribute.WeaponDamage]; + set => this[AosAttribute.WeaponDamage] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int WeaponSpeed + { + get => this[AosAttribute.WeaponSpeed]; + set => this[AosAttribute.WeaponSpeed] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int SpellDamage + { + get => this[AosAttribute.SpellDamage]; + set => this[AosAttribute.SpellDamage] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int CastRecovery + { + get => this[AosAttribute.CastRecovery]; + set => this[AosAttribute.CastRecovery] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int CastSpeed + { + get => this[AosAttribute.CastSpeed]; + set => this[AosAttribute.CastSpeed] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int LowerManaCost + { + get => this[AosAttribute.LowerManaCost]; + set => this[AosAttribute.LowerManaCost] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int LowerRegCost + { + get => this[AosAttribute.LowerRegCost]; + set => this[AosAttribute.LowerRegCost] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int ReflectPhysical + { + get => this[AosAttribute.ReflectPhysical]; + set => this[AosAttribute.ReflectPhysical] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int EnhancePotions + { + get => this[AosAttribute.EnhancePotions]; + set => this[AosAttribute.EnhancePotions] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Luck + { + get => this[AosAttribute.Luck]; + set => this[AosAttribute.Luck] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int SpellChanneling + { + get => this[AosAttribute.SpellChanneling]; + set => this[AosAttribute.SpellChanneling] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int NightSight + { + get => this[AosAttribute.NightSight]; + set => this[AosAttribute.NightSight] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int IncreasedKarmaLoss + { + get => this[AosAttribute.IncreasedKarmaLoss]; + set => this[AosAttribute.IncreasedKarmaLoss] = value; + } + + public static int GetValue(Mobile m, AosAttribute attribute) + { + if (!Core.AOS) + return 0; + + var items = m.Items; + var value = 0; + + for (var i = 0; i < items.Count; ++i) + { + var obj = items[i]; + + if (obj is BaseWeapon weapon) + { + var attrs = weapon.Attributes; + + if (attrs != null) + value += attrs[attribute]; + + if (attribute == AosAttribute.Luck) + value += weapon.GetLuckBonus(); + } + else if (obj is BaseArmor armor) + { + var attrs = armor.Attributes; + + if (attrs != null) + value += attrs[attribute]; + + if (attribute == AosAttribute.Luck) + value += armor.GetLuckBonus(); + } + else if (obj is BaseJewel jewel) + { + var attrs = jewel.Attributes; + + if (attrs != null) + value += attrs[attribute]; + } + else if (obj is BaseClothing clothing) + { + var attrs = clothing.Attributes; + + if (attrs != null) + value += attrs[attribute]; + } + else if (obj is Spellbook spellbook) + { + var attrs = spellbook.Attributes; + + if (attrs != null) + value += attrs[attribute]; + } + else if (obj is BaseQuiver quiver) + { + var attrs = quiver.Attributes; + + if (attrs != null) + value += attrs[attribute]; + } + else if (obj is BaseTalisman talisman) + { + var attrs = talisman.Attributes; + + if (attrs != null) + value += attrs[attribute]; + } + } + + return value; + } + + public override string ToString() => "..."; + + public void AddStatBonuses(Mobile to) + { + var strBonus = BonusStr; + var dexBonus = BonusDex; + var intBonus = BonusInt; + + if (strBonus != 0 || dexBonus != 0 || intBonus != 0) + { + var modName = Owner.Serial.ToString(); + + if (strBonus != 0) + to.AddStatMod(new StatMod(StatType.Str, $"{modName}Str", strBonus, TimeSpan.Zero)); + + if (dexBonus != 0) + to.AddStatMod(new StatMod(StatType.Dex, $"{modName}Dex", dexBonus, TimeSpan.Zero)); + + if (intBonus != 0) + to.AddStatMod(new StatMod(StatType.Int, $"{modName}Int", intBonus, TimeSpan.Zero)); + } + + to.CheckStatTimers(); + } + + public void RemoveStatBonuses(Mobile from) + { + var modName = Owner.Serial.ToString(); + + from.RemoveStatMod($"{modName}Str"); + from.RemoveStatMod($"{modName}Dex"); + from.RemoveStatMod($"{modName}Int"); + + from.CheckStatTimers(); + } + } + + [Flags] + public enum AosWeaponAttribute + { + LowerStatReq = 0x00000001, + SelfRepair = 0x00000002, + HitLeechHits = 0x00000004, + HitLeechStam = 0x00000008, + HitLeechMana = 0x00000010, + HitLowerAttack = 0x00000020, + HitLowerDefend = 0x00000040, + HitMagicArrow = 0x00000080, + HitHarm = 0x00000100, + HitFireball = 0x00000200, + HitLightning = 0x00000400, + HitDispel = 0x00000800, + HitColdArea = 0x00001000, + HitFireArea = 0x00002000, + HitPoisonArea = 0x00004000, + HitEnergyArea = 0x00008000, + HitPhysicalArea = 0x00010000, + ResistPhysicalBonus = 0x00020000, + ResistFireBonus = 0x00040000, + ResistColdBonus = 0x00080000, + ResistPoisonBonus = 0x00100000, + ResistEnergyBonus = 0x00200000, + UseBestSkill = 0x00400000, + MageWeapon = 0x00800000, + DurabilityBonus = 0x01000000 + } + + public sealed class AosWeaponAttributes : BaseAttributes + { + public AosWeaponAttributes(Item owner) + : base(owner) + { + } + + public AosWeaponAttributes(Item owner, AosWeaponAttributes other) + : base(owner, other) + { + } + + public AosWeaponAttributes(Item owner, IGenericReader reader) + : base(owner, reader) + { + } + + public int this[AosWeaponAttribute attribute] + { + get => GetValue((int)attribute); + set => SetValue((int)attribute, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public int LowerStatReq + { + get => this[AosWeaponAttribute.LowerStatReq]; + set => this[AosWeaponAttribute.LowerStatReq] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int SelfRepair + { + get => this[AosWeaponAttribute.SelfRepair]; + set => this[AosWeaponAttribute.SelfRepair] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int HitLeechHits + { + get => this[AosWeaponAttribute.HitLeechHits]; + set => this[AosWeaponAttribute.HitLeechHits] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int HitLeechStam + { + get => this[AosWeaponAttribute.HitLeechStam]; + set => this[AosWeaponAttribute.HitLeechStam] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int HitLeechMana + { + get => this[AosWeaponAttribute.HitLeechMana]; + set => this[AosWeaponAttribute.HitLeechMana] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int HitLowerAttack + { + get => this[AosWeaponAttribute.HitLowerAttack]; + set => this[AosWeaponAttribute.HitLowerAttack] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int HitLowerDefend + { + get => this[AosWeaponAttribute.HitLowerDefend]; + set => this[AosWeaponAttribute.HitLowerDefend] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int HitMagicArrow + { + get => this[AosWeaponAttribute.HitMagicArrow]; + set => this[AosWeaponAttribute.HitMagicArrow] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int HitHarm + { + get => this[AosWeaponAttribute.HitHarm]; + set => this[AosWeaponAttribute.HitHarm] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int HitFireball + { + get => this[AosWeaponAttribute.HitFireball]; + set => this[AosWeaponAttribute.HitFireball] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int HitLightning + { + get => this[AosWeaponAttribute.HitLightning]; + set => this[AosWeaponAttribute.HitLightning] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int HitDispel + { + get => this[AosWeaponAttribute.HitDispel]; + set => this[AosWeaponAttribute.HitDispel] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int HitColdArea + { + get => this[AosWeaponAttribute.HitColdArea]; + set => this[AosWeaponAttribute.HitColdArea] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int HitFireArea + { + get => this[AosWeaponAttribute.HitFireArea]; + set => this[AosWeaponAttribute.HitFireArea] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int HitPoisonArea + { + get => this[AosWeaponAttribute.HitPoisonArea]; + set => this[AosWeaponAttribute.HitPoisonArea] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int HitEnergyArea + { + get => this[AosWeaponAttribute.HitEnergyArea]; + set => this[AosWeaponAttribute.HitEnergyArea] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int HitPhysicalArea + { + get => this[AosWeaponAttribute.HitPhysicalArea]; + set => this[AosWeaponAttribute.HitPhysicalArea] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int ResistPhysicalBonus + { + get => this[AosWeaponAttribute.ResistPhysicalBonus]; + set => this[AosWeaponAttribute.ResistPhysicalBonus] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int ResistFireBonus + { + get => this[AosWeaponAttribute.ResistFireBonus]; + set => this[AosWeaponAttribute.ResistFireBonus] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int ResistColdBonus + { + get => this[AosWeaponAttribute.ResistColdBonus]; + set => this[AosWeaponAttribute.ResistColdBonus] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int ResistPoisonBonus + { + get => this[AosWeaponAttribute.ResistPoisonBonus]; + set => this[AosWeaponAttribute.ResistPoisonBonus] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int ResistEnergyBonus + { + get => this[AosWeaponAttribute.ResistEnergyBonus]; + set => this[AosWeaponAttribute.ResistEnergyBonus] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int UseBestSkill + { + get => this[AosWeaponAttribute.UseBestSkill]; + set => this[AosWeaponAttribute.UseBestSkill] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int MageWeapon + { + get => this[AosWeaponAttribute.MageWeapon]; + set => this[AosWeaponAttribute.MageWeapon] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int DurabilityBonus + { + get => this[AosWeaponAttribute.DurabilityBonus]; + set => this[AosWeaponAttribute.DurabilityBonus] = value; + } + + public static int GetValue(Mobile m, AosWeaponAttribute attribute) + { + if (!Core.AOS) + return 0; + + var items = m.Items; + var value = 0; + + for (var i = 0; i < items.Count; ++i) + { + var obj = items[i]; + + if (obj is BaseWeapon weapon) + { + var attrs = weapon.WeaponAttributes; + + if (attrs != null) + value += attrs[attribute]; + } + else if (obj is ElvenGlasses glasses) + { + var attrs = glasses.WeaponAttributes; + + if (attrs != null) + value += attrs[attribute]; + } + } + + return value; + } + + public override string ToString() => "..."; + } + + [Flags] + public enum AosArmorAttribute + { + LowerStatReq = 0x00000001, + SelfRepair = 0x00000002, + MageArmor = 0x00000004, + DurabilityBonus = 0x00000008 + } + + public sealed class AosArmorAttributes : BaseAttributes + { + public AosArmorAttributes(Item owner) + : base(owner) + { + } + + public AosArmorAttributes(Item owner, IGenericReader reader) + : base(owner, reader) + { + } + + public AosArmorAttributes(Item owner, AosArmorAttributes other) + : base(owner, other) + { + } + + public int this[AosArmorAttribute attribute] + { + get => GetValue((int)attribute); + set => SetValue((int)attribute, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public int LowerStatReq + { + get => this[AosArmorAttribute.LowerStatReq]; + set => this[AosArmorAttribute.LowerStatReq] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int SelfRepair + { + get => this[AosArmorAttribute.SelfRepair]; + set => this[AosArmorAttribute.SelfRepair] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int MageArmor + { + get => this[AosArmorAttribute.MageArmor]; + set => this[AosArmorAttribute.MageArmor] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int DurabilityBonus + { + get => this[AosArmorAttribute.DurabilityBonus]; + set => this[AosArmorAttribute.DurabilityBonus] = value; + } + + public static int GetValue(Mobile m, AosArmorAttribute attribute) + { + if (!Core.AOS) + return 0; + + var items = m.Items; + var value = 0; + + for (var i = 0; i < items.Count; ++i) + { + var obj = items[i]; + + if (obj is BaseArmor armor) + { + var attrs = armor.ArmorAttributes; + + if (attrs != null) + value += attrs[attribute]; + } + else if (obj is BaseClothing clothing) + { + var attrs = clothing.ClothingAttributes; + + if (attrs != null) + value += attrs[attribute]; + } + } + + return value; + } + + public override string ToString() => "..."; + } + + public sealed class AosSkillBonuses : BaseAttributes + { + private List m_Mods; + + public AosSkillBonuses(Item owner) + : base(owner) + { + } + + public AosSkillBonuses(Item owner, IGenericReader reader) + : base(owner, reader) + { + } + + public AosSkillBonuses(Item owner, AosSkillBonuses other) + : base(owner, other) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public double Skill_1_Value + { + get => GetBonus(0); + set => SetBonus(0, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public SkillName Skill_1_Name + { + get => GetSkill(0); + set => SetSkill(0, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public double Skill_2_Value + { + get => GetBonus(1); + set => SetBonus(1, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public SkillName Skill_2_Name + { + get => GetSkill(1); + set => SetSkill(1, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public double Skill_3_Value + { + get => GetBonus(2); + set => SetBonus(2, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public SkillName Skill_3_Name + { + get => GetSkill(2); + set => SetSkill(2, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public double Skill_4_Value + { + get => GetBonus(3); + set => SetBonus(3, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public SkillName Skill_4_Name + { + get => GetSkill(3); + set => SetSkill(3, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public double Skill_5_Value + { + get => GetBonus(4); + set => SetBonus(4, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public SkillName Skill_5_Name + { + get => GetSkill(4); + set => SetSkill(4, value); + } + + public void GetProperties(ObjectPropertyList list) + { + for (var i = 0; i < 5; ++i) + if (GetValues(i, out var skill, out var bonus)) + list.Add(1060451 + i, "#{0}\t{1}", GetLabel(skill), bonus); + } + + public static int GetLabel(SkillName skill) + { + return skill switch + { + SkillName.EvalInt => 1002070, // Evaluate Intelligence + SkillName.Forensics => 1002078, // Forensic Evaluation + SkillName.Lockpicking => 1002097, // Lockpicking + _ => 1044060 + (int)skill + }; + } + + public void AddTo(Mobile m) + { + Remove(); + + for (var i = 0; i < 5; ++i) + { + if (!GetValues(i, out var skill, out var bonus)) + continue; + + m_Mods ??= new List(); + + SkillMod sk = new DefaultSkillMod(skill, true, bonus); + sk.ObeyCap = true; + m.AddSkillMod(sk); + m_Mods.Add(sk); + } + } + + public void Remove() + { + if (m_Mods == null) + return; + + for (var i = 0; i < m_Mods.Count; ++i) + { + var m = m_Mods[i].Owner; + m_Mods[i].Remove(); + + if (Core.ML) + CheckCancelMorph(m); + } + + m_Mods = null; + } + + public bool GetValues(int index, out SkillName skill, out double bonus) + { + var v = GetValue(1 << index); + var vSkill = 0; + var vBonus = 0; + + for (var i = 0; i < 16; ++i) + { + vSkill <<= 1; + vSkill |= v & 1; + v >>= 1; + + vBonus <<= 1; + vBonus |= v & 1; + v >>= 1; + } + + skill = (SkillName)vSkill; + bonus = (double)vBonus / 10; + + return bonus != 0; + } + + public void SetValues(int index, SkillName skill, double bonus) + { + var v = 0; + var vSkill = (int)skill; + var vBonus = (int)(bonus * 10); + + for (var i = 0; i < 16; ++i) + { + v <<= 1; + v |= vBonus & 1; + vBonus >>= 1; + + v <<= 1; + v |= vSkill & 1; + vSkill >>= 1; + } + + SetValue(1 << index, v); + } + + public SkillName GetSkill(int index) + { + GetValues(index, out var skill, out var _); + + return skill; + } + + public void SetSkill(int index, SkillName skill) + { + SetValues(index, skill, GetBonus(index)); + } + + public double GetBonus(int index) + { + GetValues(index, out var _, out var bonus); + + return bonus; + } + + public void SetBonus(int index, double bonus) + { + SetValues(index, GetSkill(index), bonus); + } + + public override string ToString() => "..."; + + public void CheckCancelMorph(Mobile m) + { + if (m == null) + return; + + var acontext = AnimalForm.GetContext(m); + var context = TransformationSpellHelper.GetContext(m); + + if (context?.Spell is Spell spell) + { + spell.GetCastSkills(out var minSkill, out _); + if (m.Skills[spell.CastSkill].Value < minSkill) + TransformationSpellHelper.RemoveContext(m, context, true); + } + + if (acontext != null) + { + int i; + for (i = 0; i < AnimalForm.Entries.Length; ++i) + if (AnimalForm.Entries[i].Type == acontext.Type) + break; + if (m.Skills.Ninjitsu.Value < AnimalForm.Entries[i].ReqSkill) + AnimalForm.RemoveContext(m, true); + } + + if (!m.CanBeginAction() && m.Skills.Magery.Value < 66.1) + { + m.BodyMod = 0; + m.HueMod = -1; + m.NameMod = null; + m.EndAction(); + BaseArmor.ValidateMobile(m); + BaseClothing.ValidateMobile(m); + } + + if (!m.CanBeginAction() && m.Skills.Magery.Value < 38.1) + { + if (m is PlayerMobile mobile) + mobile.SetHairMods(-1, -1); + m.BodyMod = 0; + m.HueMod = -1; + m.NameMod = null; + m.EndAction(); + BaseArmor.ValidateMobile(m); + BaseClothing.ValidateMobile(m); + BuffInfo.RemoveBuff(m, BuffIcon.Incognito); + } + } + } + + [Flags] + public enum AosElementAttribute + { + Physical = 0x00000001, + Fire = 0x00000002, + Cold = 0x00000004, + Poison = 0x00000008, + Energy = 0x00000010, + Chaos = 0x00000020, + Direct = 0x00000040 + } + + public sealed class AosElementAttributes : BaseAttributes + { + public AosElementAttributes(Item owner) + : base(owner) + { + } + + public AosElementAttributes(Item owner, AosElementAttributes other) + : base(owner, other) + { + } + + public AosElementAttributes(Item owner, IGenericReader reader) + : base(owner, reader) + { + } + + public int this[AosElementAttribute attribute] + { + get => GetValue((int)attribute); + set => SetValue((int)attribute, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Physical + { + get => this[AosElementAttribute.Physical]; + set => this[AosElementAttribute.Physical] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Fire + { + get => this[AosElementAttribute.Fire]; + set => this[AosElementAttribute.Fire] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Cold + { + get => this[AosElementAttribute.Cold]; + set => this[AosElementAttribute.Cold] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Poison + { + get => this[AosElementAttribute.Poison]; + set => this[AosElementAttribute.Poison] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Energy + { + get => this[AosElementAttribute.Energy]; + set => this[AosElementAttribute.Energy] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Chaos + { + get => this[AosElementAttribute.Chaos]; + set => this[AosElementAttribute.Chaos] = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Direct + { + get => this[AosElementAttribute.Direct]; + set => this[AosElementAttribute.Direct] = value; + } + + public override string ToString() => "..."; + } + + [PropertyObject] + public abstract class BaseAttributes + { + private static readonly int[] m_Empty = Array.Empty(); + private uint m_Names; + private int[] m_Values; + + public BaseAttributes(Item owner) + { + Owner = owner; m_Values = m_Empty; - } - else - { - int[] old = m_Values; - m_Values = new int[old.Length - 1]; - - for (int i = 0; i < index; ++i) - m_Values[i] = old[i]; - - for (int i = index + 1; i < old.Length; ++i) - m_Values[i - 1] = old[i]; - } } - } - if (bitmask == (int)AosWeaponAttribute.DurabilityBonus && this is AosWeaponAttributes) - { - if (Owner is BaseWeapon weapon) - weapon.ScaleDurability(); - } - else if (bitmask == (int)AosArmorAttribute.DurabilityBonus && this is AosArmorAttributes) - { - if (Owner is BaseArmor armor) - armor.ScaleDurability(); - else if (Owner is BaseClothing clothing) - clothing.ScaleDurability(); - } - - if (Owner.Parent is Mobile m) - { - m.CheckStatTimers(); - m.UpdateResistances(); - m.Delta(MobileDelta.Stat | MobileDelta.WeaponDamage | MobileDelta.Hits | MobileDelta.Stam | - MobileDelta.Mana); - - if (this is AosSkillBonuses) + public BaseAttributes(Item owner, BaseAttributes other) { - ((AosSkillBonuses)this).Remove(); - ((AosSkillBonuses)this).AddTo(m); + Owner = owner; + m_Values = new int[other.m_Values.Length]; + other.m_Values.CopyTo(m_Values, 0); + m_Names = other.m_Names; } - } - Owner.InvalidateProperties(); + public BaseAttributes(Item owner, IGenericReader reader) + { + Owner = owner; + + int version = reader.ReadByte(); + + switch (version) + { + case 1: + { + m_Names = reader.ReadUInt(); + m_Values = new int[reader.ReadEncodedInt()]; + + for (var i = 0; i < m_Values.Length; ++i) + m_Values[i] = reader.ReadEncodedInt(); + + break; + } + case 0: + { + m_Names = reader.ReadUInt(); + m_Values = new int[reader.ReadInt()]; + + for (var i = 0; i < m_Values.Length; ++i) + m_Values[i] = reader.ReadInt(); + + break; + } + } + } + + public bool IsEmpty => m_Names == 0; + public Item Owner { get; } + + public void Serialize(IGenericWriter writer) + { + writer.Write((byte)1); // version; + + writer.Write(m_Names); + writer.WriteEncodedInt(m_Values.Length); + + for (var i = 0; i < m_Values.Length; ++i) + writer.WriteEncodedInt(m_Values[i]); + } + + public int GetValue(int bitmask) + { + if (!Core.AOS) + return 0; + + var mask = (uint)bitmask; + + if ((m_Names & mask) == 0) + return 0; + + var index = GetIndex(mask); + + if (index >= 0 && index < m_Values.Length) + return m_Values[index]; + + return 0; + } + + public void SetValue(int bitmask, int value) + { + if (bitmask == (int)AosWeaponAttribute.DurabilityBonus && this is AosWeaponAttributes) + { + if (Owner is BaseWeapon weapon) + weapon.UnscaleDurability(); + } + else if (bitmask == (int)AosArmorAttribute.DurabilityBonus && this is AosArmorAttributes) + { + if (Owner is BaseArmor armor) + armor.UnscaleDurability(); + else if (Owner is BaseClothing clothing) + clothing.UnscaleDurability(); + } + + var mask = (uint)bitmask; + + if (value != 0) + { + if ((m_Names & mask) != 0) + { + var index = GetIndex(mask); + + if (index >= 0 && index < m_Values.Length) + m_Values[index] = value; + } + else + { + var index = GetIndex(mask); + + if (index >= 0 && index <= m_Values.Length) + { + var old = m_Values; + m_Values = new int[old.Length + 1]; + + for (var i = 0; i < index; ++i) + m_Values[i] = old[i]; + + m_Values[index] = value; + + for (var i = index; i < old.Length; ++i) + m_Values[i + 1] = old[i]; + + m_Names |= mask; + } + } + } + else if ((m_Names & mask) != 0) + { + var index = GetIndex(mask); + + if (index >= 0 && index < m_Values.Length) + { + m_Names &= ~mask; + + if (m_Values.Length == 1) + { + m_Values = m_Empty; + } + else + { + var old = m_Values; + m_Values = new int[old.Length - 1]; + + for (var i = 0; i < index; ++i) + m_Values[i] = old[i]; + + for (var i = index + 1; i < old.Length; ++i) + m_Values[i - 1] = old[i]; + } + } + } + + if (bitmask == (int)AosWeaponAttribute.DurabilityBonus && this is AosWeaponAttributes) + { + if (Owner is BaseWeapon weapon) + weapon.ScaleDurability(); + } + else if (bitmask == (int)AosArmorAttribute.DurabilityBonus && this is AosArmorAttributes) + { + if (Owner is BaseArmor armor) + armor.ScaleDurability(); + else if (Owner is BaseClothing clothing) + clothing.ScaleDurability(); + } + + if (Owner.Parent is Mobile m) + { + m.CheckStatTimers(); + m.UpdateResistances(); + m.Delta( + MobileDelta.Stat | MobileDelta.WeaponDamage | MobileDelta.Hits | MobileDelta.Stam | + MobileDelta.Mana + ); + + if (this is AosSkillBonuses) + { + ((AosSkillBonuses)this).Remove(); + ((AosSkillBonuses)this).AddTo(m); + } + } + + Owner.InvalidateProperties(); + } + + private int GetIndex(uint mask) + { + var index = 0; + var ourNames = m_Names; + uint currentBit = 1; + + while (currentBit != mask) + { + if ((ourNames & currentBit) != 0) + ++index; + + if (currentBit == 0x80000000) + return -1; + + currentBit <<= 1; + } + + return index; + } } - - private int GetIndex(uint mask) - { - int index = 0; - uint ourNames = m_Names; - uint currentBit = 1; - - while (currentBit != mask) - { - if ((ourNames & currentBit) != 0) - ++index; - - if (currentBit == 0x80000000) - return -1; - - currentBit <<= 1; - } - - return index; - } - } } diff --git a/Projects/UOContent/Misc/AccountPrompt.cs b/Projects/UOContent/Misc/AccountPrompt.cs index c08906aea..1e97064a5 100644 --- a/Projects/UOContent/Misc/AccountPrompt.cs +++ b/Projects/UOContent/Misc/AccountPrompt.cs @@ -3,37 +3,37 @@ using Server.Accounting; namespace Server.Misc { - public class AccountPrompt - { - public static void Initialize() + public class AccountPrompt { - if (Accounts.Count == 0) - { - Console.WriteLine("This server has no accounts."); - Console.Write("Do you want to create the owner account now? (y/n)"); - - if (Console.ReadKey(true).Key == ConsoleKey.Y) + public static void Initialize() { - Console.WriteLine(); + if (Accounts.Count == 0) + { + Console.WriteLine("This server has no accounts."); + Console.Write("Do you want to create the owner account now? (y/n)"); - Console.Write("Username: "); - string username = Console.ReadLine(); + if (Console.ReadKey(true).Key == ConsoleKey.Y) + { + Console.WriteLine(); - Console.Write("Password: "); - string password = Console.ReadLine(); + Console.Write("Username: "); + var username = Console.ReadLine(); - Account a = new Account(username, password); - a.AccessLevel = AccessLevel.Owner; + Console.Write("Password: "); + var password = Console.ReadLine(); - Console.WriteLine("Account created."); + var a = new Account(username, password); + a.AccessLevel = AccessLevel.Owner; + + Console.WriteLine("Account created."); + } + else + { + Console.WriteLine(); + + Console.WriteLine("Account not created."); + } + } } - else - { - Console.WriteLine(); - - Console.WriteLine("Account not created."); - } - } } - } } diff --git a/Projects/UOContent/Misc/Animations.cs b/Projects/UOContent/Misc/Animations.cs index a4bf4bcff..b5d7d12d2 100644 --- a/Projects/UOContent/Misc/Animations.cs +++ b/Projects/UOContent/Misc/Animations.cs @@ -1,23 +1,23 @@ namespace Server.Misc { - public static class Animations - { - public static void Initialize() + public static class Animations { - EventSink.AnimateRequest += EventSink_AnimateRequest; - } + public static void Initialize() + { + EventSink.AnimateRequest += EventSink_AnimateRequest; + } - private static void EventSink_AnimateRequest(Mobile from, string actionName) - { - int action = actionName switch - { - "bow" => 32, - "salute" => 33, - _ => 0, - }; + private static void EventSink_AnimateRequest(Mobile from, string actionName) + { + var action = actionName switch + { + "bow" => 32, + "salute" => 33, + _ => 0 + }; - if (action > 0 && from.Alive && !from.Mounted && from.Body.IsHuman) - from.Animate(action, 5, 1, true, false, 0); + if (action > 0 && from.Alive && !from.Mounted && from.Body.IsHuman) + from.Animate(action, 5, 1, true, false, 0); + } } - } } diff --git a/Projects/UOContent/Misc/AttackMessage.cs b/Projects/UOContent/Misc/AttackMessage.cs index 41852025e..0f56c8a9c 100644 --- a/Projects/UOContent/Misc/AttackMessage.cs +++ b/Projects/UOContent/Misc/AttackMessage.cs @@ -1,62 +1,69 @@ using System; -using System.Collections.Generic; using Server.Network; namespace Server.Misc { - public class AttackMessage - { - private const string AggressorFormat = "You are attacking {0}!"; - private const string AggressedFormat = "{0} is attacking you!"; - private const int Hue = 0x22; - - private static readonly TimeSpan Delay = TimeSpan.FromMinutes(1.0); - - public static void Initialize() + public class AttackMessage { - EventSink.AggressiveAction += EventSink_AggressiveAction; + private const string AggressorFormat = "You are attacking {0}!"; + private const string AggressedFormat = "{0} is attacking you!"; + private const int Hue = 0x22; + + private static readonly TimeSpan Delay = TimeSpan.FromMinutes(1.0); + + public static void Initialize() + { + EventSink.AggressiveAction += EventSink_AggressiveAction; + } + + public static void EventSink_AggressiveAction(AggressiveActionEventArgs e) + { + var aggressor = e.Aggressor; + var aggressed = e.Aggressed; + + if (!aggressor.Player || !aggressed.Player) + return; + + if (!CheckAggressions(aggressor, aggressed)) + { + aggressor.LocalOverheadMessage( + MessageType.Regular, + Hue, + true, + string.Format(AggressorFormat, aggressed.Name) + ); + aggressed.LocalOverheadMessage( + MessageType.Regular, + Hue, + true, + string.Format(AggressedFormat, aggressor.Name) + ); + } + } + + public static bool CheckAggressions(Mobile m1, Mobile m2) + { + var list = m1.Aggressors; + + for (var i = 0; i < list.Count; ++i) + { + var info = list[i]; + + if (info.Attacker == m2 && DateTime.UtcNow < info.LastCombatTime + Delay) + return true; + } + + list = m2.Aggressors; + + for (var i = 0; i < list.Count; ++i) + { + var info = list[i]; + + if (info.Attacker == m1 && DateTime.UtcNow < info.LastCombatTime + Delay) + return true; + } + + return false; + } } - - public static void EventSink_AggressiveAction(AggressiveActionEventArgs e) - { - Mobile aggressor = e.Aggressor; - Mobile aggressed = e.Aggressed; - - if (!aggressor.Player || !aggressed.Player) - return; - - if (!CheckAggressions(aggressor, aggressed)) - { - aggressor.LocalOverheadMessage(MessageType.Regular, Hue, true, - string.Format(AggressorFormat, aggressed.Name)); - aggressed.LocalOverheadMessage(MessageType.Regular, Hue, true, - string.Format(AggressedFormat, aggressor.Name)); - } - } - - public static bool CheckAggressions(Mobile m1, Mobile m2) - { - List list = m1.Aggressors; - - for (int i = 0; i < list.Count; ++i) - { - AggressorInfo info = list[i]; - - if (info.Attacker == m2 && DateTime.UtcNow < info.LastCombatTime + Delay) - return true; - } - - list = m2.Aggressors; - - for (int i = 0; i < list.Count; ++i) - { - AggressorInfo info = list[i]; - - if (info.Attacker == m1 && DateTime.UtcNow < info.LastCombatTime + Delay) - return true; - } - - return false; - } - } } diff --git a/Projects/UOContent/Misc/AutoRestart.cs b/Projects/UOContent/Misc/AutoRestart.cs index 246cdc93a..ab091af6f 100644 --- a/Projects/UOContent/Misc/AutoRestart.cs +++ b/Projects/UOContent/Misc/AutoRestart.cs @@ -2,82 +2,82 @@ using System; namespace Server.Misc { - public class AutoRestart : Timer - { - public static bool Enabled; // is the script enabled? - - private static readonly TimeSpan RestartTime = TimeSpan.FromHours(2.0); // time of day at which to restart - - private static readonly TimeSpan - RestartDelay = - TimeSpan.Zero; // how long the server should remain active before restart (period of 'server wars') - - private static readonly TimeSpan - WarningDelay = TimeSpan.FromMinutes(1.0); // at what interval should the shutdown message be displayed? - - private static DateTime m_RestartTime; - - public AutoRestart() : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)) + public class AutoRestart : Timer { - Priority = TimerPriority.FiveSeconds; + public static bool Enabled; // is the script enabled? - m_RestartTime = DateTime.UtcNow.Date + RestartTime; + private static readonly TimeSpan RestartTime = TimeSpan.FromHours(2.0); // time of day at which to restart - if (m_RestartTime < DateTime.UtcNow) - m_RestartTime += TimeSpan.FromDays(1.0); + private static readonly TimeSpan + RestartDelay = + TimeSpan.Zero; // how long the server should remain active before restart (period of 'server wars') + + private static readonly TimeSpan + WarningDelay = TimeSpan.FromMinutes(1.0); // at what interval should the shutdown message be displayed? + + private static DateTime m_RestartTime; + + public AutoRestart() : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)) + { + Priority = TimerPriority.FiveSeconds; + + m_RestartTime = DateTime.UtcNow.Date + RestartTime; + + if (m_RestartTime < DateTime.UtcNow) + m_RestartTime += TimeSpan.FromDays(1.0); + } + + public static bool Restarting { get; private set; } + + public static void Initialize() + { + CommandSystem.Register("Restart", AccessLevel.Administrator, Restart_OnCommand); + new AutoRestart().Start(); + } + + public static void Restart_OnCommand(CommandEventArgs e) + { + if (Restarting) + { + e.Mobile.SendMessage("The server is already restarting."); + } + else + { + e.Mobile.SendMessage("You have initiated server shutdown."); + Enabled = true; + m_RestartTime = DateTime.UtcNow; + } + } + + private void Warning_Callback() + { + World.Broadcast(0x22, true, "The server is going down shortly."); + } + + private void Restart_Callback() + { + Core.Kill(true); + } + + protected override void OnTick() + { + if (Restarting || !Enabled) + return; + + if (DateTime.UtcNow < m_RestartTime) + return; + + if (WarningDelay > TimeSpan.Zero) + { + Warning_Callback(); + DelayCall(WarningDelay, WarningDelay, Warning_Callback); + } + + AutoSave.Save(); + + Restarting = true; + + DelayCall(RestartDelay, Restart_Callback); + } } - - public static bool Restarting { get; private set; } - - public static void Initialize() - { - CommandSystem.Register("Restart", AccessLevel.Administrator, Restart_OnCommand); - new AutoRestart().Start(); - } - - public static void Restart_OnCommand(CommandEventArgs e) - { - if (Restarting) - { - e.Mobile.SendMessage("The server is already restarting."); - } - else - { - e.Mobile.SendMessage("You have initiated server shutdown."); - Enabled = true; - m_RestartTime = DateTime.UtcNow; - } - } - - private void Warning_Callback() - { - World.Broadcast(0x22, true, "The server is going down shortly."); - } - - private void Restart_Callback() - { - Core.Kill(true); - } - - protected override void OnTick() - { - if (Restarting || !Enabled) - return; - - if (DateTime.UtcNow < m_RestartTime) - return; - - if (WarningDelay > TimeSpan.Zero) - { - Warning_Callback(); - DelayCall(WarningDelay, WarningDelay, Warning_Callback); - } - - AutoSave.Save(); - - Restarting = true; - - DelayCall(RestartDelay, Restart_Callback); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Misc/AutoSave.cs b/Projects/UOContent/Misc/AutoSave.cs index 485c0fb32..79efa5bbb 100644 --- a/Projects/UOContent/Misc/AutoSave.cs +++ b/Projects/UOContent/Misc/AutoSave.cs @@ -3,182 +3,190 @@ using System.IO; namespace Server.Misc { - public class AutoSave : Timer - { - private static readonly TimeSpan m_Delay = TimeSpan.FromMinutes(5.0); - private static readonly TimeSpan m_Warning = TimeSpan.Zero; - - private static readonly string[] m_Backups = + public class AutoSave : Timer { - "Third Backup", - "Second Backup", - "Most Recent" - }; + private static readonly TimeSpan m_Delay = TimeSpan.FromMinutes(5.0); + private static readonly TimeSpan m_Warning = TimeSpan.Zero; - public AutoSave() : base(m_Delay - m_Warning, m_Delay) => Priority = TimerPriority.OneMinute; - - public static bool SavesEnabled { get; set; } = true; - // private static TimeSpan m_Warning = TimeSpan.FromSeconds( 15.0 ); - - public static void Initialize() - { - new AutoSave().Start(); - CommandSystem.Register("SetSaves", AccessLevel.Administrator, SetSaves_OnCommand); - } - - [Usage("SetSaves ")] - [Description("Enables or disables automatic shard saving.")] - public static void SetSaves_OnCommand(CommandEventArgs e) - { - if (e.Length == 1) - { - SavesEnabled = e.GetBoolean(0); - e.Mobile.SendMessage("Saves have been {0}.", SavesEnabled ? "enabled" : "disabled"); - } - else - { - e.Mobile.SendMessage("Format: SetSaves "); - } - } - - protected override void OnTick() - { - if (!SavesEnabled || AutoRestart.Restarting) - return; - - if (m_Warning == TimeSpan.Zero) - { - Save(true); - } - else - { - int s = (int)m_Warning.TotalSeconds; - int m = s / 60; - s %= 60; - - if (m > 0 && s > 0) - World.Broadcast(0x35, true, "The world will save in {0} minute{1} and {2} second{3}.", m, - m != 1 ? "s" : "", s, s != 1 ? "s" : ""); - else if (m > 0) - World.Broadcast(0x35, true, "The world will save in {0} minute{1}.", m, m != 1 ? "s" : ""); - else - World.Broadcast(0x35, true, "The world will save in {0} second{1}.", s, s != 1 ? "s" : ""); - - DelayCall(m_Warning, Save); - } - } - - public static void Save() - { - Save(false); - } - - public static void Save(bool permitBackgroundWrite) - { - if (AutoRestart.Restarting) - return; - - World.WaitForWriteCompletion(); - - try - { - Backup(); - } - catch (Exception e) - { - Console.WriteLine("WARNING: Automatic backup FAILED: {0}", e); - } - - World.Save(true, permitBackgroundWrite); - } - - private static void Backup() - { - if (m_Backups.Length == 0) - return; - - string root = Path.Combine(Core.BaseDirectory, "Backups/Automatic"); - - if (!Directory.Exists(root)) - Directory.CreateDirectory(root); - - string[] existing = Directory.GetDirectories(root); - - for (int i = 0; i < m_Backups.Length; ++i) - { - DirectoryInfo dir = Match(existing, m_Backups[i]); - - if (dir == null) - continue; - - if (i > 0) + private static readonly string[] m_Backups = { - string timeStamp = FindTimeStamp(dir.Name); + "Third Backup", + "Second Backup", + "Most Recent" + }; + + public AutoSave() : base(m_Delay - m_Warning, m_Delay) => Priority = TimerPriority.OneMinute; + + public static bool SavesEnabled { get; set; } = true; + // private static TimeSpan m_Warning = TimeSpan.FromSeconds( 15.0 ); + + public static void Initialize() + { + new AutoSave().Start(); + CommandSystem.Register("SetSaves", AccessLevel.Administrator, SetSaves_OnCommand); + } + + [Usage("SetSaves ")] + [Description("Enables or disables automatic shard saving.")] + public static void SetSaves_OnCommand(CommandEventArgs e) + { + if (e.Length == 1) + { + SavesEnabled = e.GetBoolean(0); + e.Mobile.SendMessage("Saves have been {0}.", SavesEnabled ? "enabled" : "disabled"); + } + else + { + e.Mobile.SendMessage("Format: SetSaves "); + } + } + + protected override void OnTick() + { + if (!SavesEnabled || AutoRestart.Restarting) + return; + + if (m_Warning == TimeSpan.Zero) + { + Save(true); + } + else + { + var s = (int)m_Warning.TotalSeconds; + var m = s / 60; + s %= 60; + + if (m > 0 && s > 0) + World.Broadcast( + 0x35, + true, + "The world will save in {0} minute{1} and {2} second{3}.", + m, + m != 1 ? "s" : "", + s, + s != 1 ? "s" : "" + ); + else if (m > 0) + World.Broadcast(0x35, true, "The world will save in {0} minute{1}.", m, m != 1 ? "s" : ""); + else + World.Broadcast(0x35, true, "The world will save in {0} second{1}.", s, s != 1 ? "s" : ""); + + DelayCall(m_Warning, Save); + } + } + + public static void Save() + { + Save(false); + } + + public static void Save(bool permitBackgroundWrite) + { + if (AutoRestart.Restarting) + return; + + World.WaitForWriteCompletion(); - if (timeStamp != null) try { - dir.MoveTo(FormatDirectory(root, m_Backups[i - 1], timeStamp)); + Backup(); } - catch + catch (Exception e) { - // ignored + Console.WriteLine("WARNING: Automatic backup FAILED: {0}", e); } + + World.Save(true, permitBackgroundWrite); } - else + + private static void Backup() { - try - { - dir.Delete(true); - } - catch - { - // ignored - } + if (m_Backups.Length == 0) + return; + + var root = Path.Combine(Core.BaseDirectory, "Backups/Automatic"); + + if (!Directory.Exists(root)) + Directory.CreateDirectory(root); + + var existing = Directory.GetDirectories(root); + + for (var i = 0; i < m_Backups.Length; ++i) + { + var dir = Match(existing, m_Backups[i]); + + if (dir == null) + continue; + + if (i > 0) + { + var timeStamp = FindTimeStamp(dir.Name); + + if (timeStamp != null) + try + { + dir.MoveTo(FormatDirectory(root, m_Backups[i - 1], timeStamp)); + } + catch + { + // ignored + } + } + else + { + try + { + dir.Delete(true); + } + catch + { + // ignored + } + } + } + + var saves = Path.Combine(Core.BaseDirectory, "Saves"); + + if (Directory.Exists(saves)) + Directory.Move(saves, FormatDirectory(root, m_Backups[^1], GetTimeStamp())); } - } - string saves = Path.Combine(Core.BaseDirectory, "Saves"); + private static DirectoryInfo Match(string[] paths, string match) + { + for (var i = 0; i < paths.Length; ++i) + { + var info = new DirectoryInfo(paths[i]); - if (Directory.Exists(saves)) - Directory.Move(saves, FormatDirectory(root, m_Backups[^1], GetTimeStamp())); + if (info.Name.StartsWith(match)) + return info; + } + + return null; + } + + private static string FormatDirectory(string root, string name, string timeStamp) => + Path.Combine(root, $"{name} ({timeStamp})"); + + private static string FindTimeStamp(string input) + { + var start = input.IndexOf('('); + + if (start >= 0) + { + var end = input.IndexOf(')', ++start); + + if (end >= start) + return input.Substring(start, end - start); + } + + return null; + } + + private static string GetTimeStamp() + { + var now = DateTime.UtcNow; + + return $"{now.Day}-{now.Month}-{now.Year} {now.Hour}-{now.Minute:D2}-{now.Second:D2}"; + } } - - private static DirectoryInfo Match(string[] paths, string match) - { - for (int i = 0; i < paths.Length; ++i) - { - DirectoryInfo info = new DirectoryInfo(paths[i]); - - if (info.Name.StartsWith(match)) - return info; - } - - return null; - } - - private static string FormatDirectory(string root, string name, string timeStamp) => Path.Combine(root, $"{name} ({timeStamp})"); - - private static string FindTimeStamp(string input) - { - int start = input.IndexOf('('); - - if (start >= 0) - { - int end = input.IndexOf(')', ++start); - - if (end >= start) - return input.Substring(start, end - start); - } - - return null; - } - - private static string GetTimeStamp() - { - DateTime now = DateTime.UtcNow; - - return $"{now.Day}-{now.Month}-{now.Year} {now.Hour}-{now.Minute:D2}-{now.Second:D2}"; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Misc/Broadcasts.cs b/Projects/UOContent/Misc/Broadcasts.cs index 5f84d81a8..d2b487e29 100644 --- a/Projects/UOContent/Misc/Broadcasts.cs +++ b/Projects/UOContent/Misc/Broadcasts.cs @@ -1,35 +1,35 @@ namespace Server.Misc { - public static class Broadcasts - { - public static void Initialize() + public static class Broadcasts { - EventSink.ServerCrashed += EventSink_Crashed; - EventSink.Shutdown += EventSink_Shutdown; - } + public static void Initialize() + { + EventSink.ServerCrashed += EventSink_Crashed; + EventSink.Shutdown += EventSink_Shutdown; + } - public static void EventSink_Crashed(ServerCrashedEventArgs e) - { - try - { - World.Broadcast(0x35, true, "The server has crashed."); - } - catch - { - // ignored - } - } - - public static void EventSink_Shutdown() - { - /* try + public static void EventSink_Crashed(ServerCrashedEventArgs e) + { + try { - World.Broadcast(0x35, true, "The server has shut down."); + World.Broadcast(0x35, true, "The server has crashed."); } catch { - // ignored - }*/ + // ignored + } + } + + public static void EventSink_Shutdown() + { + /* try + { + World.Broadcast(0x35, true, "The server has shut down."); + } + catch + { + // ignored + }*/ + } } - } } diff --git a/Projects/UOContent/Misc/BuffIcons.cs b/Projects/UOContent/Misc/BuffIcons.cs index 11a7e7ef1..36a1b7442 100644 --- a/Projects/UOContent/Misc/BuffIcons.cs +++ b/Projects/UOContent/Misc/BuffIcons.cs @@ -4,268 +4,282 @@ using Server.Network; namespace Server { - public class BuffInfo - { - public static bool Enabled { get; private set; } - - public static void Initialize() + public class BuffInfo { - Enabled = ServerConfiguration.GetOrUpdateSetting("buffIcons.enable", Core.ML); + public BuffInfo(BuffIcon iconID, int titleCliloc) + : this(iconID, titleCliloc, titleCliloc + 1) + { + } - if (Enabled) - EventSink.ClientVersionReceived += ResendBuffsOnClientVersionReceived; + public BuffInfo(BuffIcon iconID, int titleCliloc, int secondaryCliloc) + { + ID = iconID; + TitleCliloc = titleCliloc; + SecondaryCliloc = secondaryCliloc; + } + + public BuffInfo(BuffIcon iconID, int titleCliloc, TimeSpan length, Mobile m) + : this(iconID, titleCliloc, titleCliloc + 1, length, m) + { + } + + // Only the timed one needs to Mobile to know when to automagically remove it. + public BuffInfo(BuffIcon iconID, int titleCliloc, int secondaryCliloc, TimeSpan length, Mobile m) + : this(iconID, titleCliloc, secondaryCliloc) + { + TimeLength = length; + TimeStart = DateTime.UtcNow; + + Timer = Timer.DelayCall(length, RemoveBuff, m, this); + } + + public BuffInfo(BuffIcon iconID, int titleCliloc, TextDefinition args) + : this(iconID, titleCliloc, titleCliloc + 1, args) + { + } + + public BuffInfo(BuffIcon iconID, int titleCliloc, int secondaryCliloc, TextDefinition args) + : this(iconID, titleCliloc, secondaryCliloc) => + Args = args; + + public BuffInfo(BuffIcon iconID, int titleCliloc, bool retainThroughDeath) + : this(iconID, titleCliloc, titleCliloc + 1, retainThroughDeath) + { + } + + public BuffInfo(BuffIcon iconID, int titleCliloc, int secondaryCliloc, bool retainThroughDeath) + : this(iconID, titleCliloc, secondaryCliloc) => + RetainThroughDeath = retainThroughDeath; + + public BuffInfo(BuffIcon iconID, int titleCliloc, TextDefinition args, bool retainThroughDeath) + : this(iconID, titleCliloc, titleCliloc + 1, args, retainThroughDeath) + { + } + + public BuffInfo(BuffIcon iconID, int titleCliloc, int secondaryCliloc, TextDefinition args, bool retainThroughDeath) + : this(iconID, titleCliloc, secondaryCliloc, args) => + RetainThroughDeath = retainThroughDeath; + + public BuffInfo(BuffIcon iconID, int titleCliloc, TimeSpan length, Mobile m, TextDefinition args) + : this(iconID, titleCliloc, titleCliloc + 1, length, m, args) + { + } + + public BuffInfo( + BuffIcon iconID, int titleCliloc, int secondaryCliloc, TimeSpan length, Mobile m, + TextDefinition args + ) + : this(iconID, titleCliloc, secondaryCliloc, length, m) => + Args = args; + + public BuffInfo( + BuffIcon iconID, int titleCliloc, TimeSpan length, Mobile m, TextDefinition args, + bool retainThroughDeath + ) + : this(iconID, titleCliloc, titleCliloc + 1, length, m, args, retainThroughDeath) + { + } + + public BuffInfo( + BuffIcon iconID, int titleCliloc, int secondaryCliloc, TimeSpan length, Mobile m, + TextDefinition args, bool retainThroughDeath + ) + : this(iconID, titleCliloc, secondaryCliloc, length, m) + { + Args = args; + RetainThroughDeath = retainThroughDeath; + } + + public static bool Enabled { get; private set; } + + public BuffIcon ID { get; } + + public int TitleCliloc { get; } + + public int SecondaryCliloc { get; } + + public TimeSpan TimeLength { get; } + + public DateTime TimeStart { get; } + + public Timer Timer { get; } + + public bool RetainThroughDeath { get; } + + public TextDefinition Args { get; } + + public static void Initialize() + { + Enabled = ServerConfiguration.GetOrUpdateSetting("buffIcons.enable", Core.ML); + + if (Enabled) + EventSink.ClientVersionReceived += ResendBuffsOnClientVersionReceived; + } + + public static void ResendBuffsOnClientVersionReceived(NetState ns, ClientVersion cv) + { + if (ns.Mobile is PlayerMobile pm) + Timer.DelayCall(pm.ResendBuffs); + } + + public static void AddBuff(Mobile m, BuffInfo b) + { + if (m is PlayerMobile pm) + pm.AddBuff(b); + } + + public static void RemoveBuff(Mobile m, BuffInfo b) + { + if (m is PlayerMobile pm) + pm.RemoveBuff(b); + } + + public static void RemoveBuff(Mobile m, BuffIcon b) + { + if (m is PlayerMobile pm) + pm.RemoveBuff(b); + } } - public static void ResendBuffsOnClientVersionReceived(NetState ns, ClientVersion cv) + public enum BuffIcon : short { - if (ns.Mobile is PlayerMobile pm) - Timer.DelayCall(pm.ResendBuffs); + DismountPrevention = 0x3E9, + NoRearm = 0x3EA, + + // Currently, no 0x3EB or 0x3EC + NightSight = 0x3ED, // * + DeathStrike, + EvilOmen, + UnknownStandingSwirl, // Which is healing throttle & Stamina throttle? + UnknownKneelingSword, + DivineFury, // * + EnemyOfOne, // * + HidingAndOrStealth, // * + ActiveMeditation, // * + BloodOathCaster, // * + BloodOathCurse, // * + CorpseSkin, // * + Mindrot, // * + PainSpike, // * + Strangle, + GiftOfRenewal, // * + AttuneWeapon, // * + Thunderstorm, // * + EssenceOfWind, // * + EtherealVoyage, // * + GiftOfLife, // * + ArcaneEmpowerment, // * + MortalStrike, + ReactiveArmor, // * + Protection, // * + ArchProtection, + MagicReflection, // * + Incognito, // * + Disguised, + AnimalForm, + Polymorph, + Invisibility, // * + Paralyze, // * + Poison, + Bleed, + Clumsy, // * + FeebleMind, // * + Weaken, // * + Curse, // * + MassCurse, + Agility, // * + Cunning, // * + Strength, // * + Bless, // * + Sleep, + StoneForm, + SpellPlague, + SpellTrigger, + NetherBolt, + Fly } - public BuffIcon ID { get; } - - public int TitleCliloc { get; } - - public int SecondaryCliloc { get; } - - public TimeSpan TimeLength { get; } - - public DateTime TimeStart { get; } - - public Timer Timer { get; } - - public bool RetainThroughDeath { get; } - - public TextDefinition Args { get; } - - public BuffInfo(BuffIcon iconID, int titleCliloc) - : this(iconID, titleCliloc, titleCliloc + 1) + public sealed class AddBuffPacket : Packet { + public AddBuffPacket(Mobile m, BuffInfo info) + : this( + m, + info.ID, + info.TitleCliloc, + info.SecondaryCliloc, + info.Args, + info.TimeStart != DateTime.MinValue ? info.TimeStart + info.TimeLength - DateTime.UtcNow : TimeSpan.Zero + ) + { + } + + public AddBuffPacket( + Mobile mob, BuffIcon iconID, int titleCliloc, int secondaryCliloc, TextDefinition args, + TimeSpan length + ) + : base(0xDF) + { + var hasArgs = args != null; + + EnsureCapacity(hasArgs ? 48 + args.ToString().Length * 2 : 44); + Stream.Write(mob.Serial); + + Stream.Write((short)iconID); // ID + Stream.Write((short)0x1); // Type 0 for removal. 1 for add 2 for Data + + Stream.Fill(4); + + Stream.Write((short)iconID); // ID + Stream.Write((short)0x01); // Type 0 for removal. 1 for add 2 for Data + + Stream.Fill(4); + + if (length < TimeSpan.Zero) + length = TimeSpan.Zero; + + Stream.Write((short)length.TotalSeconds); // Time in seconds + + Stream.Fill(3); + Stream.Write(titleCliloc); + Stream.Write(secondaryCliloc); + + if (!hasArgs) + { + // m_Stream.Fill( 2 ); + Stream.Fill(10); + } + else + { + Stream.Fill(4); + Stream.Write((short)0x1); // Unknown -> Possibly something saying 'hey, I have more data!'? + Stream.Fill(2); + + // m_Stream.WriteLittleUniNull( "\t#1018280" ); + Stream.WriteLittleUniNull($"\t{args}"); + + Stream.Write((short)0x1); // Even more Unknown -> Possibly something saying 'hey, I have more data!'? + Stream.Fill(2); + } + } } - public BuffInfo(BuffIcon iconID, int titleCliloc, int secondaryCliloc) + public sealed class RemoveBuffPacket : Packet { - ID = iconID; - TitleCliloc = titleCliloc; - SecondaryCliloc = secondaryCliloc; + public RemoveBuffPacket(Mobile mob, BuffInfo info) + : this(mob, info.ID) + { + } + + public RemoveBuffPacket(Mobile mob, BuffIcon iconID) + : base(0xDF) + { + EnsureCapacity(13); + Stream.Write(mob.Serial); + + Stream.Write((short)iconID); // ID + Stream.Write((short)0x0); // Type 0 for removal. 1 for add 2 for Data + + Stream.Fill(4); + } } - - public BuffInfo(BuffIcon iconID, int titleCliloc, TimeSpan length, Mobile m) - : this(iconID, titleCliloc, titleCliloc + 1, length, m) - { - } - - // Only the timed one needs to Mobile to know when to automagically remove it. - public BuffInfo(BuffIcon iconID, int titleCliloc, int secondaryCliloc, TimeSpan length, Mobile m) - : this(iconID, titleCliloc, secondaryCliloc) - { - TimeLength = length; - TimeStart = DateTime.UtcNow; - - Timer = Timer.DelayCall(length, RemoveBuff, m, this); - } - - public BuffInfo(BuffIcon iconID, int titleCliloc, TextDefinition args) - : this(iconID, titleCliloc, titleCliloc + 1, args) - { - } - - public BuffInfo(BuffIcon iconID, int titleCliloc, int secondaryCliloc, TextDefinition args) - : this(iconID, titleCliloc, secondaryCliloc) => - Args = args; - - public BuffInfo(BuffIcon iconID, int titleCliloc, bool retainThroughDeath) - : this(iconID, titleCliloc, titleCliloc + 1, retainThroughDeath) - { - } - - public BuffInfo(BuffIcon iconID, int titleCliloc, int secondaryCliloc, bool retainThroughDeath) - : this(iconID, titleCliloc, secondaryCliloc) => - RetainThroughDeath = retainThroughDeath; - - public BuffInfo(BuffIcon iconID, int titleCliloc, TextDefinition args, bool retainThroughDeath) - : this(iconID, titleCliloc, titleCliloc + 1, args, retainThroughDeath) - { - } - - public BuffInfo(BuffIcon iconID, int titleCliloc, int secondaryCliloc, TextDefinition args, bool retainThroughDeath) - : this(iconID, titleCliloc, secondaryCliloc, args) => - RetainThroughDeath = retainThroughDeath; - - public BuffInfo(BuffIcon iconID, int titleCliloc, TimeSpan length, Mobile m, TextDefinition args) - : this(iconID, titleCliloc, titleCliloc + 1, length, m, args) - { - } - - public BuffInfo(BuffIcon iconID, int titleCliloc, int secondaryCliloc, TimeSpan length, Mobile m, - TextDefinition args) - : this(iconID, titleCliloc, secondaryCliloc, length, m) => - Args = args; - - public BuffInfo(BuffIcon iconID, int titleCliloc, TimeSpan length, Mobile m, TextDefinition args, - bool retainThroughDeath) - : this(iconID, titleCliloc, titleCliloc + 1, length, m, args, retainThroughDeath) - { - } - - public BuffInfo(BuffIcon iconID, int titleCliloc, int secondaryCliloc, TimeSpan length, Mobile m, - TextDefinition args, bool retainThroughDeath) - : this(iconID, titleCliloc, secondaryCliloc, length, m) - { - Args = args; - RetainThroughDeath = retainThroughDeath; - } - - public static void AddBuff(Mobile m, BuffInfo b) - { - if (m is PlayerMobile pm) - pm.AddBuff(b); - } - - public static void RemoveBuff(Mobile m, BuffInfo b) - { - if (m is PlayerMobile pm) - pm.RemoveBuff(b); - } - - public static void RemoveBuff(Mobile m, BuffIcon b) - { - if (m is PlayerMobile pm) - pm.RemoveBuff(b); - } - } - - public enum BuffIcon : short - { - DismountPrevention = 0x3E9, - NoRearm = 0x3EA, - - // Currently, no 0x3EB or 0x3EC - NightSight = 0x3ED, // * - DeathStrike, - EvilOmen, - UnknownStandingSwirl, // Which is healing throttle & Stamina throttle? - UnknownKneelingSword, - DivineFury, // * - EnemyOfOne, // * - HidingAndOrStealth, // * - ActiveMeditation, // * - BloodOathCaster, // * - BloodOathCurse, // * - CorpseSkin, // * - Mindrot, // * - PainSpike, // * - Strangle, - GiftOfRenewal, // * - AttuneWeapon, // * - Thunderstorm, // * - EssenceOfWind, // * - EtherealVoyage, // * - GiftOfLife, // * - ArcaneEmpowerment, // * - MortalStrike, - ReactiveArmor, // * - Protection, // * - ArchProtection, - MagicReflection, // * - Incognito, // * - Disguised, - AnimalForm, - Polymorph, - Invisibility, // * - Paralyze, // * - Poison, - Bleed, - Clumsy, // * - FeebleMind, // * - Weaken, // * - Curse, // * - MassCurse, - Agility, // * - Cunning, // * - Strength, // * - Bless, // * - Sleep, - StoneForm, - SpellPlague, - SpellTrigger, - NetherBolt, - Fly - } - - public sealed class AddBuffPacket : Packet - { - public AddBuffPacket(Mobile m, BuffInfo info) - : this(m, info.ID, info.TitleCliloc, info.SecondaryCliloc, info.Args, - info.TimeStart != DateTime.MinValue ? info.TimeStart + info.TimeLength - DateTime.UtcNow : TimeSpan.Zero) - { - } - - public AddBuffPacket(Mobile mob, BuffIcon iconID, int titleCliloc, int secondaryCliloc, TextDefinition args, - TimeSpan length) - : base(0xDF) - { - bool hasArgs = args != null; - - EnsureCapacity(hasArgs ? 48 + args.ToString().Length * 2 : 44); - Stream.Write(mob.Serial); - - Stream.Write((short)iconID); // ID - Stream.Write((short)0x1); // Type 0 for removal. 1 for add 2 for Data - - Stream.Fill(4); - - Stream.Write((short)iconID); // ID - Stream.Write((short)0x01); // Type 0 for removal. 1 for add 2 for Data - - Stream.Fill(4); - - if (length < TimeSpan.Zero) - length = TimeSpan.Zero; - - Stream.Write((short)length.TotalSeconds); // Time in seconds - - Stream.Fill(3); - Stream.Write(titleCliloc); - Stream.Write(secondaryCliloc); - - if (!hasArgs) - { - // m_Stream.Fill( 2 ); - Stream.Fill(10); - } - else - { - Stream.Fill(4); - Stream.Write((short)0x1); // Unknown -> Possibly something saying 'hey, I have more data!'? - Stream.Fill(2); - - // m_Stream.WriteLittleUniNull( "\t#1018280" ); - Stream.WriteLittleUniNull($"\t{args}"); - - Stream.Write((short)0x1); // Even more Unknown -> Possibly something saying 'hey, I have more data!'? - Stream.Fill(2); - } - } - } - - public sealed class RemoveBuffPacket : Packet - { - public RemoveBuffPacket(Mobile mob, BuffInfo info) - : this(mob, info.ID) - { - } - - public RemoveBuffPacket(Mobile mob, BuffIcon iconID) - : base(0xDF) - { - EnsureCapacity(13); - Stream.Write(mob.Serial); - - Stream.Write((short)iconID); // ID - Stream.Write((short)0x0); // Type 0 for removal. 1 for add 2 for Data - - Stream.Fill(4); - } - } } diff --git a/Projects/UOContent/Misc/CharacterCreation.cs b/Projects/UOContent/Misc/CharacterCreation.cs index 93f779550..f93eaef43 100644 --- a/Projects/UOContent/Misc/CharacterCreation.cs +++ b/Projects/UOContent/Misc/CharacterCreation.cs @@ -7,1730 +7,1731 @@ using Server.Network; namespace Server.Misc { - public static class CharacterCreation - { - private static readonly CityInfo m_NewHavenInfo = - new CityInfo("New Haven", "The Bountiful Harvest Inn", 3503, 2574, 14, Map.Trammel); - - private static Mobile m_Mobile; - - public static void Initialize() + public static class CharacterCreation { - // Register our event handler - EventSink.CharacterCreated += EventSink_CharacterCreated; - } + private static readonly CityInfo m_NewHavenInfo = + new CityInfo("New Haven", "The Bountiful Harvest Inn", 3503, 2574, 14, Map.Trammel); - private static void AddBackpack(Mobile m) - { - Container pack = m.Backpack; + private static Mobile m_Mobile; - if (pack == null) - { - pack = new Backpack(); - pack.Movable = false; - - m.AddItem(pack); - } - - PackItem(new RedBook("a book", m.Name, 20, true)); - PackItem(new Gold(1000)); // Starting gold can be customized here - PackItem(new Dagger()); - PackItem(new Candle()); - } - - private static Item MakeNewbie(Item item) - { - if (!Core.AOS) - item.LootType = LootType.Newbied; - - return item; - } - - private static void PlaceItemIn(Container parent, int x, int y, Item item) - { - parent.AddItem(item); - item.Location = new Point3D(x, y, 0); - } - - private static Item MakePotionKeg(PotionEffect type, int hue) - { - PotionKeg keg = new PotionKeg(); - - keg.Held = 100; - keg.Type = type; - keg.Hue = hue; - - return MakeNewbie(keg); - } - - private static void FillBankAOS(Mobile m) - { - BankBox bank = m.BankBox; - - // The new AOS bankboxes don't have powerscrolls, they are automatically 'applied': - - for (int i = 0; i < PowerScroll.Skills.Count; ++i) - m.Skills[PowerScroll.Skills[i]].Cap = 120.0; - - m.StatCap = 250; - - Container cont; - - // Begin box of money - cont = new WoodenBox(); - cont.ItemID = 0xE7D; - cont.Hue = 0x489; - - PlaceItemIn(cont, 16, 51, new BankCheck(500000)); - PlaceItemIn(cont, 28, 51, new BankCheck(250000)); - PlaceItemIn(cont, 40, 51, new BankCheck(100000)); - PlaceItemIn(cont, 52, 51, new BankCheck(100000)); - PlaceItemIn(cont, 64, 51, new BankCheck(50000)); - - PlaceItemIn(cont, 16, 115, new Silver(9000)); - PlaceItemIn(cont, 34, 115, new Gold(60000)); - - PlaceItemIn(bank, 18, 169, cont); - // End box of money - - // Begin bag of potion kegs - cont = new Backpack(); - cont.Name = "Various Potion Kegs"; - - PlaceItemIn(cont, 45, 149, MakePotionKeg(PotionEffect.CureGreater, 0x2D)); - PlaceItemIn(cont, 69, 149, MakePotionKeg(PotionEffect.HealGreater, 0x499)); - PlaceItemIn(cont, 93, 149, MakePotionKeg(PotionEffect.PoisonDeadly, 0x46)); - PlaceItemIn(cont, 117, 149, MakePotionKeg(PotionEffect.RefreshTotal, 0x21)); - PlaceItemIn(cont, 141, 149, MakePotionKeg(PotionEffect.ExplosionGreater, 0x74)); - - PlaceItemIn(cont, 93, 82, new Bottle(1000)); - - PlaceItemIn(bank, 53, 169, cont); - // End bag of potion kegs - - // Begin bag of tools - cont = new Bag(); - cont.Name = "Tool Bag"; - - PlaceItemIn(cont, 30, 35, new TinkerTools(1000)); - PlaceItemIn(cont, 60, 35, new HousePlacementTool()); - PlaceItemIn(cont, 90, 35, new DovetailSaw(1000)); - PlaceItemIn(cont, 30, 68, new Scissors()); - PlaceItemIn(cont, 45, 68, new MortarPestle(1000)); - PlaceItemIn(cont, 75, 68, new ScribesPen(1000)); - PlaceItemIn(cont, 90, 68, new SmithHammer(1000)); - PlaceItemIn(cont, 30, 118, new TwoHandedAxe()); - PlaceItemIn(cont, 60, 118, new FletcherTools(1000)); - PlaceItemIn(cont, 90, 118, new SewingKit(1000)); - - PlaceItemIn(cont, 36, 51, new RunicHammer(CraftResource.DullCopper, 1000)); - PlaceItemIn(cont, 42, 51, new RunicHammer(CraftResource.ShadowIron, 1000)); - PlaceItemIn(cont, 48, 51, new RunicHammer(CraftResource.Copper, 1000)); - PlaceItemIn(cont, 54, 51, new RunicHammer(CraftResource.Bronze, 1000)); - PlaceItemIn(cont, 61, 51, new RunicHammer(CraftResource.Gold, 1000)); - PlaceItemIn(cont, 67, 51, new RunicHammer(CraftResource.Agapite, 1000)); - PlaceItemIn(cont, 73, 51, new RunicHammer(CraftResource.Verite, 1000)); - PlaceItemIn(cont, 79, 51, new RunicHammer(CraftResource.Valorite, 1000)); - - PlaceItemIn(cont, 36, 55, new RunicSewingKit(CraftResource.SpinedLeather, 1000)); - PlaceItemIn(cont, 42, 55, new RunicSewingKit(CraftResource.HornedLeather, 1000)); - PlaceItemIn(cont, 48, 55, new RunicSewingKit(CraftResource.BarbedLeather, 1000)); - - PlaceItemIn(bank, 118, 169, cont); - // End bag of tools - - // Begin bag of archery ammo - cont = new Bag(); - cont.Name = "Bag Of Archery Ammo"; - - PlaceItemIn(cont, 48, 76, new Arrow(5000)); - PlaceItemIn(cont, 72, 76, new Bolt(5000)); - - PlaceItemIn(bank, 118, 124, cont); - // End bag of archery ammo - - // Begin bag of treasure maps - cont = new Bag(); - cont.Name = "Bag Of Treasure Maps"; - - PlaceItemIn(cont, 30, 35, new TreasureMap(1, Map.Trammel)); - PlaceItemIn(cont, 45, 35, new TreasureMap(2, Map.Trammel)); - PlaceItemIn(cont, 60, 35, new TreasureMap(3, Map.Trammel)); - PlaceItemIn(cont, 75, 35, new TreasureMap(4, Map.Trammel)); - PlaceItemIn(cont, 90, 35, new TreasureMap(5, Map.Trammel)); - PlaceItemIn(cont, 90, 35, new TreasureMap(6, Map.Trammel)); - - PlaceItemIn(cont, 30, 50, new TreasureMap(1, Map.Trammel)); - PlaceItemIn(cont, 45, 50, new TreasureMap(2, Map.Trammel)); - PlaceItemIn(cont, 60, 50, new TreasureMap(3, Map.Trammel)); - PlaceItemIn(cont, 75, 50, new TreasureMap(4, Map.Trammel)); - PlaceItemIn(cont, 90, 50, new TreasureMap(5, Map.Trammel)); - PlaceItemIn(cont, 90, 50, new TreasureMap(6, Map.Trammel)); - - PlaceItemIn(cont, 55, 100, new Lockpick(30)); - PlaceItemIn(cont, 60, 100, new Pickaxe()); - - PlaceItemIn(bank, 98, 124, cont); - // End bag of treasure maps - - // Begin bag of raw materials - cont = new Bag(); - cont.Hue = 0x835; - cont.Name = "Raw Materials Bag"; - - PlaceItemIn(cont, 92, 60, new BarbedLeather(5000)); - PlaceItemIn(cont, 92, 68, new HornedLeather(5000)); - PlaceItemIn(cont, 92, 76, new SpinedLeather(5000)); - PlaceItemIn(cont, 92, 84, new Leather(5000)); - - PlaceItemIn(cont, 30, 118, new Cloth(5000)); - PlaceItemIn(cont, 30, 84, new Board(5000)); - PlaceItemIn(cont, 57, 80, new BlankScroll(500)); - - PlaceItemIn(cont, 30, 35, new DullCopperIngot(5000)); - PlaceItemIn(cont, 37, 35, new ShadowIronIngot(5000)); - PlaceItemIn(cont, 44, 35, new CopperIngot(5000)); - PlaceItemIn(cont, 51, 35, new BronzeIngot(5000)); - PlaceItemIn(cont, 58, 35, new GoldIngot(5000)); - PlaceItemIn(cont, 65, 35, new AgapiteIngot(5000)); - PlaceItemIn(cont, 72, 35, new VeriteIngot(5000)); - PlaceItemIn(cont, 79, 35, new ValoriteIngot(5000)); - PlaceItemIn(cont, 86, 35, new IronIngot(5000)); - - PlaceItemIn(cont, 30, 59, new RedScales(5000)); - PlaceItemIn(cont, 36, 59, new YellowScales(5000)); - PlaceItemIn(cont, 42, 59, new BlackScales(5000)); - PlaceItemIn(cont, 48, 59, new GreenScales(5000)); - PlaceItemIn(cont, 54, 59, new WhiteScales(5000)); - PlaceItemIn(cont, 60, 59, new BlueScales(5000)); - - PlaceItemIn(bank, 98, 169, cont); - // End bag of raw materials - - // Begin bag of spell casting stuff - cont = new Backpack(); - cont.Hue = 0x480; - cont.Name = "Spell Casting Stuff"; - - PlaceItemIn(cont, 45, 105, new Spellbook(ulong.MaxValue)); - PlaceItemIn(cont, 65, 105, new NecromancerSpellbook(0xFFFFUL)); - PlaceItemIn(cont, 85, 105, new BookOfChivalry()); - PlaceItemIn(cont, 105, 105, new BookOfBushido()); // Default ctor = full - PlaceItemIn(cont, 125, 105, new BookOfNinjitsu()); // Default ctor = full - - Runebook runebook = new Runebook(10); - runebook.CurCharges = runebook.MaxCharges; - PlaceItemIn(cont, 145, 105, runebook); - - Item toHue = new BagOfReagents(150); - toHue.Hue = 0x2D; - PlaceItemIn(cont, 45, 150, toHue); - - toHue = new BagOfNecroReagents(150); - toHue.Hue = 0x488; - PlaceItemIn(cont, 65, 150, toHue); - - PlaceItemIn(cont, 140, 150, new BagOfAllReagents(500)); - - for (int i = 0; i < 9; ++i) - PlaceItemIn(cont, 45 + i * 10, 75, new RecallRune()); - - PlaceItemIn(cont, 141, 74, new FireHorn()); - - PlaceItemIn(bank, 78, 169, cont); - // End bag of spell casting stuff - - // Begin bag of ethereals - cont = new Backpack(); - cont.Hue = 0x490; - cont.Name = "Bag Of Ethy's!"; - - PlaceItemIn(cont, 45, 66, new EtherealHorse()); - PlaceItemIn(cont, 69, 82, new EtherealOstard()); - PlaceItemIn(cont, 93, 99, new EtherealLlama()); - PlaceItemIn(cont, 117, 115, new EtherealKirin()); - PlaceItemIn(cont, 45, 132, new EtherealUnicorn()); - PlaceItemIn(cont, 69, 66, new EtherealRidgeback()); - PlaceItemIn(cont, 93, 82, new EtherealSwampDragon()); - PlaceItemIn(cont, 117, 99, new EtherealBeetle()); - - PlaceItemIn(bank, 38, 124, cont); - // End bag of ethereals - - // Begin first bag of artifacts - cont = new Backpack(); - cont.Hue = 0x48F; - cont.Name = "Bag of Artifacts"; - - PlaceItemIn(cont, 45, 66, new TitansHammer()); - PlaceItemIn(cont, 69, 82, new InquisitorsResolution()); - PlaceItemIn(cont, 93, 99, new BladeOfTheRighteous()); - PlaceItemIn(cont, 117, 115, new ZyronicClaw()); - - PlaceItemIn(bank, 58, 124, cont); - // End first bag of artifacts - - // Begin second bag of artifacts - cont = new Backpack(); - cont.Hue = 0x48F; - cont.Name = "Bag of Artifacts"; - - PlaceItemIn(cont, 45, 66, new GauntletsOfNobility()); - PlaceItemIn(cont, 69, 82, new MidnightBracers()); - PlaceItemIn(cont, 93, 99, new VoiceOfTheFallenKing()); - PlaceItemIn(cont, 117, 115, new OrnateCrownOfTheHarrower()); - PlaceItemIn(cont, 45, 132, new HelmOfInsight()); - PlaceItemIn(cont, 69, 66, new HolyKnightsBreastplate()); - PlaceItemIn(cont, 93, 82, new ArmorOfFortune()); - PlaceItemIn(cont, 117, 99, new TunicOfFire()); - PlaceItemIn(cont, 45, 115, new LeggingsOfBane()); - PlaceItemIn(cont, 69, 132, new ArcaneShield()); - PlaceItemIn(cont, 93, 66, new Aegis()); - PlaceItemIn(cont, 117, 82, new RingOfTheVile()); - PlaceItemIn(cont, 45, 99, new BraceletOfHealth()); - PlaceItemIn(cont, 69, 115, new RingOfTheElements()); - PlaceItemIn(cont, 93, 132, new OrnamentOfTheMagician()); - PlaceItemIn(cont, 117, 66, new DivineCountenance()); - PlaceItemIn(cont, 45, 82, new JackalsCollar()); - PlaceItemIn(cont, 69, 99, new HuntersHeaddress()); - PlaceItemIn(cont, 93, 115, new HatOfTheMagi()); - PlaceItemIn(cont, 117, 132, new ShadowDancerLeggings()); - PlaceItemIn(cont, 45, 66, new SpiritOfTheTotem()); - PlaceItemIn(cont, 69, 82, new BladeOfInsanity()); - PlaceItemIn(cont, 93, 99, new AxeOfTheHeavens()); - PlaceItemIn(cont, 117, 115, new TheBeserkersMaul()); - PlaceItemIn(cont, 45, 132, new Frostbringer()); - PlaceItemIn(cont, 69, 66, new BreathOfTheDead()); - PlaceItemIn(cont, 93, 82, new TheDragonSlayer()); - PlaceItemIn(cont, 117, 99, new BoneCrusher()); - PlaceItemIn(cont, 45, 115, new StaffOfTheMagi()); - PlaceItemIn(cont, 69, 132, new SerpentsFang()); - PlaceItemIn(cont, 93, 66, new LegacyOfTheDreadLord()); - PlaceItemIn(cont, 117, 82, new TheTaskmaster()); - PlaceItemIn(cont, 45, 99, new TheDryadBow()); - - PlaceItemIn(bank, 78, 124, cont); - // End second bag of artifacts - - // Begin bag of minor artifacts - cont = new Backpack(); - cont.Hue = 0x48F; - cont.Name = "Bag of Minor Artifacts"; - - PlaceItemIn(cont, 45, 66, new LunaLance()); - PlaceItemIn(cont, 69, 82, new VioletCourage()); - PlaceItemIn(cont, 93, 99, new CavortingClub()); - PlaceItemIn(cont, 117, 115, new CaptainQuacklebushsCutlass()); - PlaceItemIn(cont, 45, 132, new NightsKiss()); - PlaceItemIn(cont, 69, 66, new ShipModelOfTheHMSCape()); - PlaceItemIn(cont, 93, 82, new AdmiralsHeartyRum()); - PlaceItemIn(cont, 117, 99, new CandelabraOfSouls()); - PlaceItemIn(cont, 45, 115, new IolosLute()); - PlaceItemIn(cont, 69, 132, new GwennosHarp()); - PlaceItemIn(cont, 93, 66, new ArcticDeathDealer()); - PlaceItemIn(cont, 117, 82, new EnchantedTitanLegBone()); - PlaceItemIn(cont, 45, 99, new NoxRangersHeavyCrossbow()); - PlaceItemIn(cont, 69, 115, new BlazeOfDeath()); - PlaceItemIn(cont, 93, 132, new DreadPirateHat()); - PlaceItemIn(cont, 117, 66, new BurglarsBandana()); - PlaceItemIn(cont, 45, 82, new GoldBricks()); - PlaceItemIn(cont, 69, 99, new AlchemistsBauble()); - PlaceItemIn(cont, 93, 115, new PhillipsWoodenSteed()); - PlaceItemIn(cont, 117, 132, new PolarBearMask()); - PlaceItemIn(cont, 45, 66, new BowOfTheJukaKing()); - PlaceItemIn(cont, 69, 82, new GlovesOfThePugilist()); - PlaceItemIn(cont, 93, 99, new OrcishVisage()); - PlaceItemIn(cont, 117, 115, new StaffOfPower()); - PlaceItemIn(cont, 45, 132, new ShieldOfInvulnerability()); - PlaceItemIn(cont, 69, 66, new HeartOfTheLion()); - PlaceItemIn(cont, 93, 82, new ColdBlood()); - PlaceItemIn(cont, 117, 99, new GhostShipAnchor()); - PlaceItemIn(cont, 45, 115, new SeahorseStatuette()); - PlaceItemIn(cont, 69, 132, new WrathOfTheDryad()); - PlaceItemIn(cont, 93, 66, new PixieSwatter()); - - for (int i = 0; i < 10; i++) - PlaceItemIn(cont, 117, 128, new MessageInABottle(Utility.RandomBool() ? Map.Trammel : Map.Felucca, 4)); - - PlaceItemIn(bank, 18, 124, cont); - - if (Core.SE) - { - cont = new Bag(); - cont.Hue = 0x501; - cont.Name = "Tokuno Minor Artifacts"; - - PlaceItemIn(cont, 42, 70, new Exiler()); - PlaceItemIn(cont, 38, 53, new HanzosBow()); - PlaceItemIn(cont, 45, 40, new TheDestroyer()); - PlaceItemIn(cont, 92, 80, new DragonNunchaku()); - PlaceItemIn(cont, 42, 56, new PeasantsBokuto()); - PlaceItemIn(cont, 44, 71, new TomeOfEnlightenment()); - PlaceItemIn(cont, 35, 35, new ChestOfHeirlooms()); - PlaceItemIn(cont, 29, 0, new HonorableSwords()); - PlaceItemIn(cont, 49, 85, new AncientUrn()); - PlaceItemIn(cont, 51, 58, new FluteOfRenewal()); - PlaceItemIn(cont, 70, 51, new PigmentsOfTokuno()); - PlaceItemIn(cont, 40, 79, new AncientSamuraiDo()); - PlaceItemIn(cont, 51, 61, new LegsOfStability()); - PlaceItemIn(cont, 88, 78, new GlovesOfTheSun()); - PlaceItemIn(cont, 55, 62, new AncientFarmersKasa()); - PlaceItemIn(cont, 55, 83, new ArmsOfTacticalExcellence()); - PlaceItemIn(cont, 50, 85, new DaimyosHelm()); - PlaceItemIn(cont, 52, 78, new BlackLotusHood()); - PlaceItemIn(cont, 52, 79, new DemonForks()); - PlaceItemIn(cont, 33, 49, new PilferedDancerFans()); - - PlaceItemIn(bank, 58, 124, cont); - } - - if (Core.SE) // This bag came only after SE. - { - cont = new Bag(); - cont.Name = "Bag of Bows"; - - PlaceItemIn(cont, 31, 84, new Bow()); - PlaceItemIn(cont, 78, 74, new CompositeBow()); - PlaceItemIn(cont, 53, 71, new Crossbow()); - PlaceItemIn(cont, 56, 39, new HeavyCrossbow()); - PlaceItemIn(cont, 82, 72, new RepeatingCrossbow()); - PlaceItemIn(cont, 49, 45, new Yumi()); - - for (int i = 0; i < cont.Items.Count; i++) - if (cont.Items[i] is BaseRanged bow) - { - bow.Attributes.WeaponSpeed = 35; - bow.Attributes.WeaponDamage = 35; - } - - PlaceItemIn(bank, 108, 135, cont); - } - } - - private static void FillBankbox(Mobile m) - { - if (Core.AOS) - { - FillBankAOS(m); - return; - } - - BankBox bank = m.BankBox; - - bank.DropItem(new BankCheck(1000000)); - - // Full spellbook - Spellbook book = new Spellbook(); - - book.Content = ulong.MaxValue; - - bank.DropItem(book); - - Bag bag = new Bag(); - - for (int i = 0; i < 5; ++i) - bag.DropItem(new Moonstone(MoonstoneType.Felucca)); - - // Felucca moonstones - bank.DropItem(bag); - - bag = new Bag(); - - for (int i = 0; i < 5; ++i) - bag.DropItem(new Moonstone(MoonstoneType.Trammel)); - - // Trammel moonstones - bank.DropItem(bag); - - // Treasure maps - bank.DropItem(new TreasureMap(1, Map.Trammel)); - bank.DropItem(new TreasureMap(2, Map.Trammel)); - bank.DropItem(new TreasureMap(3, Map.Trammel)); - bank.DropItem(new TreasureMap(4, Map.Trammel)); - bank.DropItem(new TreasureMap(5, Map.Trammel)); - - // Bag containing 50 of each reagent - bank.DropItem(new BagOfReagents()); - - // Craft tools - bank.DropItem(MakeNewbie(new Scissors())); - bank.DropItem(MakeNewbie(new SewingKit(1000))); - bank.DropItem(MakeNewbie(new SmithHammer(1000))); - bank.DropItem(MakeNewbie(new FletcherTools(1000))); - bank.DropItem(MakeNewbie(new DovetailSaw(1000))); - bank.DropItem(MakeNewbie(new MortarPestle(1000))); - bank.DropItem(MakeNewbie(new ScribesPen(1000))); - bank.DropItem(MakeNewbie(new TinkerTools(1000))); - - // A few dye tubs - bank.DropItem(new Dyes()); - bank.DropItem(new DyeTub()); - bank.DropItem(new DyeTub()); - bank.DropItem(new BlackDyeTub()); - - DyeTub darkRedTub = new DyeTub(); - - darkRedTub.DyedHue = 0x485; - darkRedTub.Redyable = false; - - bank.DropItem(darkRedTub); - - // Some food - bank.DropItem(MakeNewbie(new Apple(1000))); - - // Resources - bank.DropItem(MakeNewbie(new Feather(1000))); - bank.DropItem(MakeNewbie(new BoltOfCloth(1000))); - bank.DropItem(MakeNewbie(new BlankScroll(1000))); - bank.DropItem(MakeNewbie(new Hides(1000))); - bank.DropItem(MakeNewbie(new Bandage(1000))); - bank.DropItem(MakeNewbie(new Bottle(1000))); - bank.DropItem(MakeNewbie(new Log(1000))); - - bank.DropItem(MakeNewbie(new IronIngot(5000))); - bank.DropItem(MakeNewbie(new DullCopperIngot(5000))); - bank.DropItem(MakeNewbie(new ShadowIronIngot(5000))); - bank.DropItem(MakeNewbie(new CopperIngot(5000))); - bank.DropItem(MakeNewbie(new BronzeIngot(5000))); - bank.DropItem(MakeNewbie(new GoldIngot(5000))); - bank.DropItem(MakeNewbie(new AgapiteIngot(5000))); - bank.DropItem(MakeNewbie(new VeriteIngot(5000))); - bank.DropItem(MakeNewbie(new ValoriteIngot(5000))); - - // Reagents - bank.DropItem(MakeNewbie(new BlackPearl(1000))); - bank.DropItem(MakeNewbie(new Bloodmoss(1000))); - bank.DropItem(MakeNewbie(new Garlic(1000))); - bank.DropItem(MakeNewbie(new Ginseng(1000))); - bank.DropItem(MakeNewbie(new MandrakeRoot(1000))); - bank.DropItem(MakeNewbie(new Nightshade(1000))); - bank.DropItem(MakeNewbie(new SulfurousAsh(1000))); - bank.DropItem(MakeNewbie(new SpidersSilk(1000))); - - // Some extra starting gold - bank.DropItem(MakeNewbie(new Gold(9000))); - - // 5 blank recall runes - for (int i = 0; i < 5; ++i) - bank.DropItem(MakeNewbie(new RecallRune())); - - AddPowerScrolls(bank); - } - - private static void AddPowerScrolls(BankBox bank) - { - Bag bag = new Bag(); - - for (int i = 0; i < PowerScroll.Skills.Count; ++i) - bag.DropItem(new PowerScroll(PowerScroll.Skills[i], 120.0)); - - bag.DropItem(new StatCapScroll(250)); - - bank.DropItem(bag); - } - - private static void AddShirt(Mobile m, int shirtHue) - { - int hue = Utility.ClipDyedHue(shirtHue & 0x3FFF); - - if (m.Race == Race.Elf) - EquipItem(new ElvenShirt(hue), true); - else - switch (Utility.Random(3)) + public static void Initialize() { - case 0: - EquipItem(new Shirt(hue), true); - break; - case 1: - EquipItem(new FancyShirt(hue), true); - break; - case 2: - EquipItem(new Doublet(hue), true); - break; + // Register our event handler + EventSink.CharacterCreated += EventSink_CharacterCreated; } - } - - private static void AddPants(Mobile m, int pantsHue) - { - int hue = Utility.ClipDyedHue(pantsHue & 0x3FFF); - - if (m.Race == Race.Elf) - { - EquipItem(new ElvenPants(hue), true); - } - else - { - if (m.Female) - switch (Utility.Random(2)) - { - case 0: - EquipItem(new Skirt(hue), true); - break; - case 1: - EquipItem(new Kilt(hue), true); - break; - } - else - switch (Utility.Random(2)) - { - case 0: - EquipItem(new LongPants(hue), true); - break; - case 1: - EquipItem(new ShortPants(hue), true); - break; - } - } - } - - private static void AddShoes(Mobile m) - { - if (m.Race == Race.Elf) - EquipItem(new ElvenBoots(), true); - else - EquipItem(new Shoes(Utility.RandomYellowHue()), true); - } - - private static Mobile CreateMobile(Account a) - { - if (a.Count >= a.Limit) - return null; - - for (int i = 0; i < a.Length; ++i) - if (a[i] == null) - return a[i] = new PlayerMobile(); - - return null; - } - - private static void EventSink_CharacterCreated(CharacterCreatedEventArgs args) - { - if (!VerifyProfession(args.Profession)) - args.Profession = 0; - - NetState state = args.State; - - if (state == null) - return; - - Mobile newChar = CreateMobile(args.Account as Account); - - if (newChar == null) - { - Console.WriteLine("Login: {0}: Character creation failed, account full", state); - return; - } - - args.Mobile = newChar; - m_Mobile = newChar; - - newChar.Player = true; - newChar.AccessLevel = args.Account.AccessLevel; - newChar.Female = args.Female; - // newChar.Body = newChar.Female ? 0x191 : 0x190; - - if (Core.Expansion >= args.Race.RequiredExpansion) - newChar.Race = args.Race; // Sets body - else - newChar.Race = Race.DefaultRace; - - // newChar.Hue = Utility.ClipSkinHue( args.Hue & 0x3FFF ) | 0x8000; - newChar.Hue = newChar.Race.ClipSkinHue(args.Hue & 0x3FFF) | 0x8000; - - newChar.Hunger = 20; - - bool young = false; - - if (newChar is PlayerMobile pm) - { - pm.Profession = args.Profession; - - if (pm.AccessLevel == AccessLevel.Player && ((Account)pm.Account).Young) - young = pm.Young = true; - } - - SetName(newChar, args.Name); - - AddBackpack(newChar); - - SetStats(newChar, state, args.Str, args.Dex, args.Int); - SetSkills(newChar, args.Skills, args.Profession); - - Race race = newChar.Race; - - if (race.ValidateHair(newChar, args.HairID)) - { - newChar.HairItemID = args.HairID; - newChar.HairHue = race.ClipHairHue(args.HairHue & 0x3FFF); - } - - if (race.ValidateFacialHair(newChar, args.BeardID)) - { - newChar.FacialHairItemID = args.BeardID; - newChar.FacialHairHue = race.ClipHairHue(args.BeardHue & 0x3FFF); - } - - if (args.Profession <= 3) - { - AddShirt(newChar, args.ShirtHue); - AddPants(newChar, args.PantsHue); - AddShoes(newChar); - } - - if (TestCenter.Enabled) - FillBankbox(newChar); - - if (young) - { - NewPlayerTicket ticket = new NewPlayerTicket(); - ticket.Owner = newChar; - newChar.BankBox.DropItem(ticket); - } - - CityInfo city = GetStartLocation(args, young); - - newChar.MoveToWorld(city.Location, city.Map); - - Console.WriteLine("Login: {0}: New character being created (account={1})", state, args.Account.Username); - Console.WriteLine(" - Character: {0} (serial={1})", newChar.Name, newChar.Serial); - Console.WriteLine(" - Started: {0} {1} in {2}", city.City, city.Location, city.Map); - - new WelcomeTimer(newChar).Start(); - } - - public static bool VerifyProfession(int profession) - { - if (profession < 0) - return false; - if (profession < 4) - return true; - if (Core.AOS && profession < 6) - return true; - if (Core.SE && profession < 8) - return true; - - return false; - } - - private static CityInfo GetStartLocation(CharacterCreatedEventArgs args, bool isYoung) - { - if (Core.ML) return m_NewHavenInfo; // We don't get the client Version until AFTER Character creation - - bool useHaven = isYoung; - - ClientFlags flags = args.State?.Flags ?? ClientFlags.None; - Mobile m = args.Mobile; - - switch (args.Profession) - { - case 4: // Necro - { - if ((flags & ClientFlags.Malas) != 0) - return new CityInfo("Umbra", "Mardoth's Tower", 2114, 1301, -50, Map.Malas); - - useHaven = true; - - // ReSharper disable once CA1806 - new BadStartMessage(m, 1062205); - /* - * Unfortunately you are playing on a *NON-Age-Of-Shadows* game - * installation and cannot be transported to Malas. - * You will not be able to take your new player quest in Malas - * without an AOS client. You are now being taken to the city of - * Haven on the Trammel facet. - * */ - - break; - } - case 5: // Paladin - { - return m_NewHavenInfo; - } - case 6: // Samurai - { - if ((flags & ClientFlags.Tokuno) != 0) - return new CityInfo("Samurai DE", "Haoti's Grounds", 368, 780, -1, Map.Malas); - - useHaven = true; - - // ReSharper disable once CA1806 - new BadStartMessage(m, 1063487); - /* - * Unfortunately you are playing on a *NON-Samurai-Empire* game - * installation and cannot be transported to Tokuno. - * You will not be able to take your new player quest in Tokuno - * without an SE client. You are now being taken to the city of - * Haven on the Trammel facet. - * */ - - break; - } - case 7: // Ninja - { - if ((flags & ClientFlags.Tokuno) != 0) - return new CityInfo("Ninja DE", "Enimo's Residence", 414, 823, -1, Map.Malas); - - useHaven = true; - - new BadStartMessage(m, 1063487); - /* - * Unfortunately you are playing on a *NON-Samurai-Empire* game - * installation and cannot be transported to Tokuno. - * You will not be able to take your new player quest in Tokuno - * without an SE client. You are now being taken to the city of - * Haven on the Trammel facet. - * */ - - break; - } - } - - if (useHaven) - return m_NewHavenInfo; - - return args.City; - } - - private static void FixStats(ref int str, ref int dex, ref int intel, int max) - { - int vMax = max - 30; - - int vStr = str - 10; - int vDex = dex - 10; - int vInt = intel - 10; - - if (vStr < 0) - vStr = 0; - - if (vDex < 0) - vDex = 0; - - if (vInt < 0) - vInt = 0; - - int total = vStr + vDex + vInt; - - if (total == 0 || total == vMax) - return; - - double scalar = vMax / (double)total; - - vStr = (int)(vStr * scalar); - vDex = (int)(vDex * scalar); - vInt = (int)(vInt * scalar); - - FixStat(ref vStr, vStr + vDex + vInt - vMax, vMax); - FixStat(ref vDex, vStr + vDex + vInt - vMax, vMax); - FixStat(ref vInt, vStr + vDex + vInt - vMax, vMax); - - str = vStr + 10; - dex = vDex + 10; - intel = vInt + 10; - } - - private static void FixStat(ref int stat, int diff, int max) - { - stat = Math.Clamp(stat + diff, 0, max); - } - - private static void SetStats(Mobile m, NetState state, int str, int dex, int intel) - { - int max = state.NewCharacterCreation ? 90 : 80; - - FixStats(ref str, ref dex, ref intel, max); - - if (str < 10 || str > 60 || dex < 10 || dex > 60 || intel < 10 || intel > 60 || str + dex + intel != max) - { - str = 10; - dex = 10; - intel = 10; - } - m.InitStats(str, dex, intel); - } + private static void AddBackpack(Mobile m) + { + var pack = m.Backpack; - private static void SetName(Mobile m, string name) - { - name = name.Trim(); + if (pack == null) + { + pack = new Backpack(); + pack.Movable = false; + + m.AddItem(pack); + } + + PackItem(new RedBook("a book", m.Name, 20, true)); + PackItem(new Gold(1000)); // Starting gold can be customized here + PackItem(new Dagger()); + PackItem(new Candle()); + } + + private static Item MakeNewbie(Item item) + { + if (!Core.AOS) + item.LootType = LootType.Newbied; + + return item; + } - if (!NameVerification.Validate(name, 2, 16, true, false, true, 1, NameVerification.SpaceDashPeriodQuote)) - name = "Generic Player"; + private static void PlaceItemIn(Container parent, int x, int y, Item item) + { + parent.AddItem(item); + item.Location = new Point3D(x, y, 0); + } + + private static Item MakePotionKeg(PotionEffect type, int hue) + { + var keg = new PotionKeg(); + + keg.Held = 100; + keg.Type = type; + keg.Hue = hue; + + return MakeNewbie(keg); + } + + private static void FillBankAOS(Mobile m) + { + var bank = m.BankBox; + + // The new AOS bankboxes don't have powerscrolls, they are automatically 'applied': + + for (var i = 0; i < PowerScroll.Skills.Count; ++i) + m.Skills[PowerScroll.Skills[i]].Cap = 120.0; + + m.StatCap = 250; + + Container cont; + + // Begin box of money + cont = new WoodenBox(); + cont.ItemID = 0xE7D; + cont.Hue = 0x489; + + PlaceItemIn(cont, 16, 51, new BankCheck(500000)); + PlaceItemIn(cont, 28, 51, new BankCheck(250000)); + PlaceItemIn(cont, 40, 51, new BankCheck(100000)); + PlaceItemIn(cont, 52, 51, new BankCheck(100000)); + PlaceItemIn(cont, 64, 51, new BankCheck(50000)); + + PlaceItemIn(cont, 16, 115, new Silver(9000)); + PlaceItemIn(cont, 34, 115, new Gold(60000)); + + PlaceItemIn(bank, 18, 169, cont); + // End box of money + + // Begin bag of potion kegs + cont = new Backpack(); + cont.Name = "Various Potion Kegs"; + + PlaceItemIn(cont, 45, 149, MakePotionKeg(PotionEffect.CureGreater, 0x2D)); + PlaceItemIn(cont, 69, 149, MakePotionKeg(PotionEffect.HealGreater, 0x499)); + PlaceItemIn(cont, 93, 149, MakePotionKeg(PotionEffect.PoisonDeadly, 0x46)); + PlaceItemIn(cont, 117, 149, MakePotionKeg(PotionEffect.RefreshTotal, 0x21)); + PlaceItemIn(cont, 141, 149, MakePotionKeg(PotionEffect.ExplosionGreater, 0x74)); + + PlaceItemIn(cont, 93, 82, new Bottle(1000)); + + PlaceItemIn(bank, 53, 169, cont); + // End bag of potion kegs + + // Begin bag of tools + cont = new Bag(); + cont.Name = "Tool Bag"; + + PlaceItemIn(cont, 30, 35, new TinkerTools(1000)); + PlaceItemIn(cont, 60, 35, new HousePlacementTool()); + PlaceItemIn(cont, 90, 35, new DovetailSaw(1000)); + PlaceItemIn(cont, 30, 68, new Scissors()); + PlaceItemIn(cont, 45, 68, new MortarPestle(1000)); + PlaceItemIn(cont, 75, 68, new ScribesPen(1000)); + PlaceItemIn(cont, 90, 68, new SmithHammer(1000)); + PlaceItemIn(cont, 30, 118, new TwoHandedAxe()); + PlaceItemIn(cont, 60, 118, new FletcherTools(1000)); + PlaceItemIn(cont, 90, 118, new SewingKit(1000)); + + PlaceItemIn(cont, 36, 51, new RunicHammer(CraftResource.DullCopper, 1000)); + PlaceItemIn(cont, 42, 51, new RunicHammer(CraftResource.ShadowIron, 1000)); + PlaceItemIn(cont, 48, 51, new RunicHammer(CraftResource.Copper, 1000)); + PlaceItemIn(cont, 54, 51, new RunicHammer(CraftResource.Bronze, 1000)); + PlaceItemIn(cont, 61, 51, new RunicHammer(CraftResource.Gold, 1000)); + PlaceItemIn(cont, 67, 51, new RunicHammer(CraftResource.Agapite, 1000)); + PlaceItemIn(cont, 73, 51, new RunicHammer(CraftResource.Verite, 1000)); + PlaceItemIn(cont, 79, 51, new RunicHammer(CraftResource.Valorite, 1000)); + + PlaceItemIn(cont, 36, 55, new RunicSewingKit(CraftResource.SpinedLeather, 1000)); + PlaceItemIn(cont, 42, 55, new RunicSewingKit(CraftResource.HornedLeather, 1000)); + PlaceItemIn(cont, 48, 55, new RunicSewingKit(CraftResource.BarbedLeather, 1000)); + + PlaceItemIn(bank, 118, 169, cont); + // End bag of tools + + // Begin bag of archery ammo + cont = new Bag(); + cont.Name = "Bag Of Archery Ammo"; + + PlaceItemIn(cont, 48, 76, new Arrow(5000)); + PlaceItemIn(cont, 72, 76, new Bolt(5000)); + + PlaceItemIn(bank, 118, 124, cont); + // End bag of archery ammo + + // Begin bag of treasure maps + cont = new Bag(); + cont.Name = "Bag Of Treasure Maps"; + + PlaceItemIn(cont, 30, 35, new TreasureMap(1, Map.Trammel)); + PlaceItemIn(cont, 45, 35, new TreasureMap(2, Map.Trammel)); + PlaceItemIn(cont, 60, 35, new TreasureMap(3, Map.Trammel)); + PlaceItemIn(cont, 75, 35, new TreasureMap(4, Map.Trammel)); + PlaceItemIn(cont, 90, 35, new TreasureMap(5, Map.Trammel)); + PlaceItemIn(cont, 90, 35, new TreasureMap(6, Map.Trammel)); + + PlaceItemIn(cont, 30, 50, new TreasureMap(1, Map.Trammel)); + PlaceItemIn(cont, 45, 50, new TreasureMap(2, Map.Trammel)); + PlaceItemIn(cont, 60, 50, new TreasureMap(3, Map.Trammel)); + PlaceItemIn(cont, 75, 50, new TreasureMap(4, Map.Trammel)); + PlaceItemIn(cont, 90, 50, new TreasureMap(5, Map.Trammel)); + PlaceItemIn(cont, 90, 50, new TreasureMap(6, Map.Trammel)); + + PlaceItemIn(cont, 55, 100, new Lockpick(30)); + PlaceItemIn(cont, 60, 100, new Pickaxe()); + + PlaceItemIn(bank, 98, 124, cont); + // End bag of treasure maps + + // Begin bag of raw materials + cont = new Bag(); + cont.Hue = 0x835; + cont.Name = "Raw Materials Bag"; + + PlaceItemIn(cont, 92, 60, new BarbedLeather(5000)); + PlaceItemIn(cont, 92, 68, new HornedLeather(5000)); + PlaceItemIn(cont, 92, 76, new SpinedLeather(5000)); + PlaceItemIn(cont, 92, 84, new Leather(5000)); + + PlaceItemIn(cont, 30, 118, new Cloth(5000)); + PlaceItemIn(cont, 30, 84, new Board(5000)); + PlaceItemIn(cont, 57, 80, new BlankScroll(500)); + + PlaceItemIn(cont, 30, 35, new DullCopperIngot(5000)); + PlaceItemIn(cont, 37, 35, new ShadowIronIngot(5000)); + PlaceItemIn(cont, 44, 35, new CopperIngot(5000)); + PlaceItemIn(cont, 51, 35, new BronzeIngot(5000)); + PlaceItemIn(cont, 58, 35, new GoldIngot(5000)); + PlaceItemIn(cont, 65, 35, new AgapiteIngot(5000)); + PlaceItemIn(cont, 72, 35, new VeriteIngot(5000)); + PlaceItemIn(cont, 79, 35, new ValoriteIngot(5000)); + PlaceItemIn(cont, 86, 35, new IronIngot(5000)); + + PlaceItemIn(cont, 30, 59, new RedScales(5000)); + PlaceItemIn(cont, 36, 59, new YellowScales(5000)); + PlaceItemIn(cont, 42, 59, new BlackScales(5000)); + PlaceItemIn(cont, 48, 59, new GreenScales(5000)); + PlaceItemIn(cont, 54, 59, new WhiteScales(5000)); + PlaceItemIn(cont, 60, 59, new BlueScales(5000)); + + PlaceItemIn(bank, 98, 169, cont); + // End bag of raw materials + + // Begin bag of spell casting stuff + cont = new Backpack(); + cont.Hue = 0x480; + cont.Name = "Spell Casting Stuff"; + + PlaceItemIn(cont, 45, 105, new Spellbook(ulong.MaxValue)); + PlaceItemIn(cont, 65, 105, new NecromancerSpellbook(0xFFFFUL)); + PlaceItemIn(cont, 85, 105, new BookOfChivalry()); + PlaceItemIn(cont, 105, 105, new BookOfBushido()); // Default ctor = full + PlaceItemIn(cont, 125, 105, new BookOfNinjitsu()); // Default ctor = full + + var runebook = new Runebook(10); + runebook.CurCharges = runebook.MaxCharges; + PlaceItemIn(cont, 145, 105, runebook); + + Item toHue = new BagOfReagents(150); + toHue.Hue = 0x2D; + PlaceItemIn(cont, 45, 150, toHue); + + toHue = new BagOfNecroReagents(150); + toHue.Hue = 0x488; + PlaceItemIn(cont, 65, 150, toHue); + + PlaceItemIn(cont, 140, 150, new BagOfAllReagents(500)); + + for (var i = 0; i < 9; ++i) + PlaceItemIn(cont, 45 + i * 10, 75, new RecallRune()); + + PlaceItemIn(cont, 141, 74, new FireHorn()); + + PlaceItemIn(bank, 78, 169, cont); + // End bag of spell casting stuff + + // Begin bag of ethereals + cont = new Backpack(); + cont.Hue = 0x490; + cont.Name = "Bag Of Ethy's!"; + + PlaceItemIn(cont, 45, 66, new EtherealHorse()); + PlaceItemIn(cont, 69, 82, new EtherealOstard()); + PlaceItemIn(cont, 93, 99, new EtherealLlama()); + PlaceItemIn(cont, 117, 115, new EtherealKirin()); + PlaceItemIn(cont, 45, 132, new EtherealUnicorn()); + PlaceItemIn(cont, 69, 66, new EtherealRidgeback()); + PlaceItemIn(cont, 93, 82, new EtherealSwampDragon()); + PlaceItemIn(cont, 117, 99, new EtherealBeetle()); + + PlaceItemIn(bank, 38, 124, cont); + // End bag of ethereals + + // Begin first bag of artifacts + cont = new Backpack(); + cont.Hue = 0x48F; + cont.Name = "Bag of Artifacts"; + + PlaceItemIn(cont, 45, 66, new TitansHammer()); + PlaceItemIn(cont, 69, 82, new InquisitorsResolution()); + PlaceItemIn(cont, 93, 99, new BladeOfTheRighteous()); + PlaceItemIn(cont, 117, 115, new ZyronicClaw()); + + PlaceItemIn(bank, 58, 124, cont); + // End first bag of artifacts + + // Begin second bag of artifacts + cont = new Backpack(); + cont.Hue = 0x48F; + cont.Name = "Bag of Artifacts"; + + PlaceItemIn(cont, 45, 66, new GauntletsOfNobility()); + PlaceItemIn(cont, 69, 82, new MidnightBracers()); + PlaceItemIn(cont, 93, 99, new VoiceOfTheFallenKing()); + PlaceItemIn(cont, 117, 115, new OrnateCrownOfTheHarrower()); + PlaceItemIn(cont, 45, 132, new HelmOfInsight()); + PlaceItemIn(cont, 69, 66, new HolyKnightsBreastplate()); + PlaceItemIn(cont, 93, 82, new ArmorOfFortune()); + PlaceItemIn(cont, 117, 99, new TunicOfFire()); + PlaceItemIn(cont, 45, 115, new LeggingsOfBane()); + PlaceItemIn(cont, 69, 132, new ArcaneShield()); + PlaceItemIn(cont, 93, 66, new Aegis()); + PlaceItemIn(cont, 117, 82, new RingOfTheVile()); + PlaceItemIn(cont, 45, 99, new BraceletOfHealth()); + PlaceItemIn(cont, 69, 115, new RingOfTheElements()); + PlaceItemIn(cont, 93, 132, new OrnamentOfTheMagician()); + PlaceItemIn(cont, 117, 66, new DivineCountenance()); + PlaceItemIn(cont, 45, 82, new JackalsCollar()); + PlaceItemIn(cont, 69, 99, new HuntersHeaddress()); + PlaceItemIn(cont, 93, 115, new HatOfTheMagi()); + PlaceItemIn(cont, 117, 132, new ShadowDancerLeggings()); + PlaceItemIn(cont, 45, 66, new SpiritOfTheTotem()); + PlaceItemIn(cont, 69, 82, new BladeOfInsanity()); + PlaceItemIn(cont, 93, 99, new AxeOfTheHeavens()); + PlaceItemIn(cont, 117, 115, new TheBeserkersMaul()); + PlaceItemIn(cont, 45, 132, new Frostbringer()); + PlaceItemIn(cont, 69, 66, new BreathOfTheDead()); + PlaceItemIn(cont, 93, 82, new TheDragonSlayer()); + PlaceItemIn(cont, 117, 99, new BoneCrusher()); + PlaceItemIn(cont, 45, 115, new StaffOfTheMagi()); + PlaceItemIn(cont, 69, 132, new SerpentsFang()); + PlaceItemIn(cont, 93, 66, new LegacyOfTheDreadLord()); + PlaceItemIn(cont, 117, 82, new TheTaskmaster()); + PlaceItemIn(cont, 45, 99, new TheDryadBow()); + + PlaceItemIn(bank, 78, 124, cont); + // End second bag of artifacts + + // Begin bag of minor artifacts + cont = new Backpack(); + cont.Hue = 0x48F; + cont.Name = "Bag of Minor Artifacts"; + + PlaceItemIn(cont, 45, 66, new LunaLance()); + PlaceItemIn(cont, 69, 82, new VioletCourage()); + PlaceItemIn(cont, 93, 99, new CavortingClub()); + PlaceItemIn(cont, 117, 115, new CaptainQuacklebushsCutlass()); + PlaceItemIn(cont, 45, 132, new NightsKiss()); + PlaceItemIn(cont, 69, 66, new ShipModelOfTheHMSCape()); + PlaceItemIn(cont, 93, 82, new AdmiralsHeartyRum()); + PlaceItemIn(cont, 117, 99, new CandelabraOfSouls()); + PlaceItemIn(cont, 45, 115, new IolosLute()); + PlaceItemIn(cont, 69, 132, new GwennosHarp()); + PlaceItemIn(cont, 93, 66, new ArcticDeathDealer()); + PlaceItemIn(cont, 117, 82, new EnchantedTitanLegBone()); + PlaceItemIn(cont, 45, 99, new NoxRangersHeavyCrossbow()); + PlaceItemIn(cont, 69, 115, new BlazeOfDeath()); + PlaceItemIn(cont, 93, 132, new DreadPirateHat()); + PlaceItemIn(cont, 117, 66, new BurglarsBandana()); + PlaceItemIn(cont, 45, 82, new GoldBricks()); + PlaceItemIn(cont, 69, 99, new AlchemistsBauble()); + PlaceItemIn(cont, 93, 115, new PhillipsWoodenSteed()); + PlaceItemIn(cont, 117, 132, new PolarBearMask()); + PlaceItemIn(cont, 45, 66, new BowOfTheJukaKing()); + PlaceItemIn(cont, 69, 82, new GlovesOfThePugilist()); + PlaceItemIn(cont, 93, 99, new OrcishVisage()); + PlaceItemIn(cont, 117, 115, new StaffOfPower()); + PlaceItemIn(cont, 45, 132, new ShieldOfInvulnerability()); + PlaceItemIn(cont, 69, 66, new HeartOfTheLion()); + PlaceItemIn(cont, 93, 82, new ColdBlood()); + PlaceItemIn(cont, 117, 99, new GhostShipAnchor()); + PlaceItemIn(cont, 45, 115, new SeahorseStatuette()); + PlaceItemIn(cont, 69, 132, new WrathOfTheDryad()); + PlaceItemIn(cont, 93, 66, new PixieSwatter()); + + for (var i = 0; i < 10; i++) + PlaceItemIn(cont, 117, 128, new MessageInABottle(Utility.RandomBool() ? Map.Trammel : Map.Felucca, 4)); + + PlaceItemIn(bank, 18, 124, cont); + + if (Core.SE) + { + cont = new Bag(); + cont.Hue = 0x501; + cont.Name = "Tokuno Minor Artifacts"; + + PlaceItemIn(cont, 42, 70, new Exiler()); + PlaceItemIn(cont, 38, 53, new HanzosBow()); + PlaceItemIn(cont, 45, 40, new TheDestroyer()); + PlaceItemIn(cont, 92, 80, new DragonNunchaku()); + PlaceItemIn(cont, 42, 56, new PeasantsBokuto()); + PlaceItemIn(cont, 44, 71, new TomeOfEnlightenment()); + PlaceItemIn(cont, 35, 35, new ChestOfHeirlooms()); + PlaceItemIn(cont, 29, 0, new HonorableSwords()); + PlaceItemIn(cont, 49, 85, new AncientUrn()); + PlaceItemIn(cont, 51, 58, new FluteOfRenewal()); + PlaceItemIn(cont, 70, 51, new PigmentsOfTokuno()); + PlaceItemIn(cont, 40, 79, new AncientSamuraiDo()); + PlaceItemIn(cont, 51, 61, new LegsOfStability()); + PlaceItemIn(cont, 88, 78, new GlovesOfTheSun()); + PlaceItemIn(cont, 55, 62, new AncientFarmersKasa()); + PlaceItemIn(cont, 55, 83, new ArmsOfTacticalExcellence()); + PlaceItemIn(cont, 50, 85, new DaimyosHelm()); + PlaceItemIn(cont, 52, 78, new BlackLotusHood()); + PlaceItemIn(cont, 52, 79, new DemonForks()); + PlaceItemIn(cont, 33, 49, new PilferedDancerFans()); + + PlaceItemIn(bank, 58, 124, cont); + } + + if (Core.SE) // This bag came only after SE. + { + cont = new Bag(); + cont.Name = "Bag of Bows"; + + PlaceItemIn(cont, 31, 84, new Bow()); + PlaceItemIn(cont, 78, 74, new CompositeBow()); + PlaceItemIn(cont, 53, 71, new Crossbow()); + PlaceItemIn(cont, 56, 39, new HeavyCrossbow()); + PlaceItemIn(cont, 82, 72, new RepeatingCrossbow()); + PlaceItemIn(cont, 49, 45, new Yumi()); + + for (var i = 0; i < cont.Items.Count; i++) + if (cont.Items[i] is BaseRanged bow) + { + bow.Attributes.WeaponSpeed = 35; + bow.Attributes.WeaponDamage = 35; + } + + PlaceItemIn(bank, 108, 135, cont); + } + } + + private static void FillBankbox(Mobile m) + { + if (Core.AOS) + { + FillBankAOS(m); + return; + } + + var bank = m.BankBox; + + bank.DropItem(new BankCheck(1000000)); + + // Full spellbook + var book = new Spellbook(); + + book.Content = ulong.MaxValue; + + bank.DropItem(book); + + var bag = new Bag(); + + for (var i = 0; i < 5; ++i) + bag.DropItem(new Moonstone(MoonstoneType.Felucca)); + + // Felucca moonstones + bank.DropItem(bag); + + bag = new Bag(); + + for (var i = 0; i < 5; ++i) + bag.DropItem(new Moonstone(MoonstoneType.Trammel)); + + // Trammel moonstones + bank.DropItem(bag); + + // Treasure maps + bank.DropItem(new TreasureMap(1, Map.Trammel)); + bank.DropItem(new TreasureMap(2, Map.Trammel)); + bank.DropItem(new TreasureMap(3, Map.Trammel)); + bank.DropItem(new TreasureMap(4, Map.Trammel)); + bank.DropItem(new TreasureMap(5, Map.Trammel)); + + // Bag containing 50 of each reagent + bank.DropItem(new BagOfReagents()); + + // Craft tools + bank.DropItem(MakeNewbie(new Scissors())); + bank.DropItem(MakeNewbie(new SewingKit(1000))); + bank.DropItem(MakeNewbie(new SmithHammer(1000))); + bank.DropItem(MakeNewbie(new FletcherTools(1000))); + bank.DropItem(MakeNewbie(new DovetailSaw(1000))); + bank.DropItem(MakeNewbie(new MortarPestle(1000))); + bank.DropItem(MakeNewbie(new ScribesPen(1000))); + bank.DropItem(MakeNewbie(new TinkerTools(1000))); + + // A few dye tubs + bank.DropItem(new Dyes()); + bank.DropItem(new DyeTub()); + bank.DropItem(new DyeTub()); + bank.DropItem(new BlackDyeTub()); + + var darkRedTub = new DyeTub(); + + darkRedTub.DyedHue = 0x485; + darkRedTub.Redyable = false; + + bank.DropItem(darkRedTub); + + // Some food + bank.DropItem(MakeNewbie(new Apple(1000))); + + // Resources + bank.DropItem(MakeNewbie(new Feather(1000))); + bank.DropItem(MakeNewbie(new BoltOfCloth(1000))); + bank.DropItem(MakeNewbie(new BlankScroll(1000))); + bank.DropItem(MakeNewbie(new Hides(1000))); + bank.DropItem(MakeNewbie(new Bandage(1000))); + bank.DropItem(MakeNewbie(new Bottle(1000))); + bank.DropItem(MakeNewbie(new Log(1000))); + + bank.DropItem(MakeNewbie(new IronIngot(5000))); + bank.DropItem(MakeNewbie(new DullCopperIngot(5000))); + bank.DropItem(MakeNewbie(new ShadowIronIngot(5000))); + bank.DropItem(MakeNewbie(new CopperIngot(5000))); + bank.DropItem(MakeNewbie(new BronzeIngot(5000))); + bank.DropItem(MakeNewbie(new GoldIngot(5000))); + bank.DropItem(MakeNewbie(new AgapiteIngot(5000))); + bank.DropItem(MakeNewbie(new VeriteIngot(5000))); + bank.DropItem(MakeNewbie(new ValoriteIngot(5000))); + + // Reagents + bank.DropItem(MakeNewbie(new BlackPearl(1000))); + bank.DropItem(MakeNewbie(new Bloodmoss(1000))); + bank.DropItem(MakeNewbie(new Garlic(1000))); + bank.DropItem(MakeNewbie(new Ginseng(1000))); + bank.DropItem(MakeNewbie(new MandrakeRoot(1000))); + bank.DropItem(MakeNewbie(new Nightshade(1000))); + bank.DropItem(MakeNewbie(new SulfurousAsh(1000))); + bank.DropItem(MakeNewbie(new SpidersSilk(1000))); + + // Some extra starting gold + bank.DropItem(MakeNewbie(new Gold(9000))); + + // 5 blank recall runes + for (var i = 0; i < 5; ++i) + bank.DropItem(MakeNewbie(new RecallRune())); + + AddPowerScrolls(bank); + } + + private static void AddPowerScrolls(BankBox bank) + { + var bag = new Bag(); + + for (var i = 0; i < PowerScroll.Skills.Count; ++i) + bag.DropItem(new PowerScroll(PowerScroll.Skills[i], 120.0)); + + bag.DropItem(new StatCapScroll(250)); + + bank.DropItem(bag); + } + + private static void AddShirt(Mobile m, int shirtHue) + { + var hue = Utility.ClipDyedHue(shirtHue & 0x3FFF); + + if (m.Race == Race.Elf) + EquipItem(new ElvenShirt(hue), true); + else + switch (Utility.Random(3)) + { + case 0: + EquipItem(new Shirt(hue), true); + break; + case 1: + EquipItem(new FancyShirt(hue), true); + break; + case 2: + EquipItem(new Doublet(hue), true); + break; + } + } + + private static void AddPants(Mobile m, int pantsHue) + { + var hue = Utility.ClipDyedHue(pantsHue & 0x3FFF); + + if (m.Race == Race.Elf) + { + EquipItem(new ElvenPants(hue), true); + } + else + { + if (m.Female) + switch (Utility.Random(2)) + { + case 0: + EquipItem(new Skirt(hue), true); + break; + case 1: + EquipItem(new Kilt(hue), true); + break; + } + else + switch (Utility.Random(2)) + { + case 0: + EquipItem(new LongPants(hue), true); + break; + case 1: + EquipItem(new ShortPants(hue), true); + break; + } + } + } + + private static void AddShoes(Mobile m) + { + if (m.Race == Race.Elf) + EquipItem(new ElvenBoots(), true); + else + EquipItem(new Shoes(Utility.RandomYellowHue()), true); + } + + private static Mobile CreateMobile(Account a) + { + if (a.Count >= a.Limit) + return null; + + for (var i = 0; i < a.Length; ++i) + if (a[i] == null) + return a[i] = new PlayerMobile(); + + return null; + } + + private static void EventSink_CharacterCreated(CharacterCreatedEventArgs args) + { + if (!VerifyProfession(args.Profession)) + args.Profession = 0; + + var state = args.State; + + if (state == null) + return; + + var newChar = CreateMobile(args.Account as Account); + + if (newChar == null) + { + Console.WriteLine("Login: {0}: Character creation failed, account full", state); + return; + } + + args.Mobile = newChar; + m_Mobile = newChar; + + newChar.Player = true; + newChar.AccessLevel = args.Account.AccessLevel; + newChar.Female = args.Female; + // newChar.Body = newChar.Female ? 0x191 : 0x190; + + if (Core.Expansion >= args.Race.RequiredExpansion) + newChar.Race = args.Race; // Sets body + else + newChar.Race = Race.DefaultRace; + + // newChar.Hue = Utility.ClipSkinHue( args.Hue & 0x3FFF ) | 0x8000; + newChar.Hue = newChar.Race.ClipSkinHue(args.Hue & 0x3FFF) | 0x8000; + + newChar.Hunger = 20; + + var young = false; + + if (newChar is PlayerMobile pm) + { + pm.Profession = args.Profession; + + if (pm.AccessLevel == AccessLevel.Player && ((Account)pm.Account).Young) + young = pm.Young = true; + } + + SetName(newChar, args.Name); + + AddBackpack(newChar); + + SetStats(newChar, state, args.Str, args.Dex, args.Int); + SetSkills(newChar, args.Skills, args.Profession); + + var race = newChar.Race; + + if (race.ValidateHair(newChar, args.HairID)) + { + newChar.HairItemID = args.HairID; + newChar.HairHue = race.ClipHairHue(args.HairHue & 0x3FFF); + } + + if (race.ValidateFacialHair(newChar, args.BeardID)) + { + newChar.FacialHairItemID = args.BeardID; + newChar.FacialHairHue = race.ClipHairHue(args.BeardHue & 0x3FFF); + } + + if (args.Profession <= 3) + { + AddShirt(newChar, args.ShirtHue); + AddPants(newChar, args.PantsHue); + AddShoes(newChar); + } + + if (TestCenter.Enabled) + FillBankbox(newChar); - m.Name = name; - } + if (young) + { + var ticket = new NewPlayerTicket(); + ticket.Owner = newChar; + newChar.BankBox.DropItem(ticket); + } - private static bool ValidSkills(SkillNameValue[] skills) - { - int total = 0; + var city = GetStartLocation(args, young); - for (int i = 0; i < skills.Length; ++i) - { - if (skills[i].Value < 0 || skills[i].Value > 50) - return false; + newChar.MoveToWorld(city.Location, city.Map); - total += skills[i].Value; + Console.WriteLine("Login: {0}: New character being created (account={1})", state, args.Account.Username); + Console.WriteLine(" - Character: {0} (serial={1})", newChar.Name, newChar.Serial); + Console.WriteLine(" - Started: {0} {1} in {2}", city.City, city.Location, city.Map); + + new WelcomeTimer(newChar).Start(); + } + + public static bool VerifyProfession(int profession) + { + if (profession < 0) + return false; + if (profession < 4) + return true; + if (Core.AOS && profession < 6) + return true; + if (Core.SE && profession < 8) + return true; - for (int j = i + 1; j < skills.Length; ++j) - if (skills[j].Value > 0 && skills[j].Name == skills[i].Name) return false; - } - - return total == 100 || total == 120; - } - - private static void SetSkills(Mobile m, SkillNameValue[] skills, int prof) - { - switch (prof) - { - case 1: // Warrior - { - skills = new[] - { - new SkillNameValue(SkillName.Anatomy, 30), - new SkillNameValue(SkillName.Healing, 45), - new SkillNameValue(SkillName.Swords, 35), - new SkillNameValue(SkillName.Tactics, 50) - }; - - break; - } - case 2: // Magician - { - skills = new[] - { - new SkillNameValue(SkillName.EvalInt, 30), - new SkillNameValue(SkillName.Wrestling, 30), - new SkillNameValue(SkillName.Magery, 50), - new SkillNameValue(SkillName.Meditation, 50) - }; - - break; - } - case 3: // Blacksmith - { - skills = new[] - { - new SkillNameValue(SkillName.Mining, 30), - new SkillNameValue(SkillName.ArmsLore, 30), - new SkillNameValue(SkillName.Blacksmith, 50), - new SkillNameValue(SkillName.Tinkering, 50) - }; - - break; - } - case 4: // Necromancer - { - skills = new[] - { - new SkillNameValue(SkillName.Necromancy, 50), - new SkillNameValue(SkillName.Focus, 30), - new SkillNameValue(SkillName.SpiritSpeak, 30), - new SkillNameValue(SkillName.Swords, 30), - new SkillNameValue(SkillName.Tactics, 20) - }; - - break; - } - case 5: // Paladin - { - skills = new[] - { - new SkillNameValue(SkillName.Chivalry, 51), - new SkillNameValue(SkillName.Swords, 49), - new SkillNameValue(SkillName.Focus, 30), - new SkillNameValue(SkillName.Tactics, 30) - }; - - break; - } - case 6: // Samurai - { - skills = new[] - { - new SkillNameValue(SkillName.Bushido, 50), - new SkillNameValue(SkillName.Swords, 50), - new SkillNameValue(SkillName.Anatomy, 30), - new SkillNameValue(SkillName.Healing, 30) - }; - break; - } - case 7: // Ninja - { - skills = new[] - { - new SkillNameValue(SkillName.Ninjitsu, 50), - new SkillNameValue(SkillName.Hiding, 50), - new SkillNameValue(SkillName.Fencing, 30), - new SkillNameValue(SkillName.Stealth, 30) - }; - break; - } - default: - { - if (!ValidSkills(skills)) - return; - - break; - } - } - - bool addSkillItems = true; - bool elf = m.Race == Race.Elf; - - switch (prof) - { - case 1: // Warrior - { - if (elf) - EquipItem(new LeafChest()); - else - EquipItem(new LeatherChest()); - break; - } - case 4: // Necromancer - { - Container regs = new BagOfNecroReagents(); - - if (!Core.AOS) - foreach (Item item in regs.Items) - item.LootType = LootType.Newbied; - - PackItem(regs); - - regs.LootType = LootType.Regular; - - EquipItem(new BoneHelm()); - - if (elf) - { - EquipItem(new ElvenMachete()); - EquipItem(NecroHue(new LeafChest())); - EquipItem(NecroHue(new LeafArms())); - EquipItem(NecroHue(new LeafGloves())); - EquipItem(NecroHue(new LeafGorget())); - EquipItem(NecroHue(new LeafGorget())); - EquipItem(NecroHue(new ElvenPants())); // TODO: Verify the pants - EquipItem(new ElvenBoots()); - } - else - { - EquipItem(new BoneHarvester()); - EquipItem(NecroHue(new LeatherChest())); - EquipItem(NecroHue(new LeatherArms())); - EquipItem(NecroHue(new LeatherGloves())); - EquipItem(NecroHue(new LeatherGorget())); - EquipItem(NecroHue(new LeatherLegs())); - EquipItem(NecroHue(new Skirt())); - EquipItem(new Sandals(0x8FD)); - } - - Spellbook - book = new NecromancerSpellbook( - (ulong)0x8981); // animate dead, evil omen, pain spike, summon familiar, wraith form - - PackItem(book); - - book.LootType = LootType.Blessed; - - addSkillItems = false; - - break; - } - case 5: // Paladin - { - if (elf) - { - EquipItem(new ElvenMachete()); - EquipItem(new WingedHelm()); - EquipItem(new LeafGorget()); - EquipItem(new LeafArms()); - EquipItem(new LeafChest()); - EquipItem(new LeafLegs()); - EquipItem(new ElvenBoots()); // Verify hue - } - else - { - EquipItem(new Broadsword()); - EquipItem(new Helmet()); - EquipItem(new PlateGorget()); - EquipItem(new RingmailArms()); - EquipItem(new RingmailChest()); - EquipItem(new RingmailLegs()); - EquipItem(new ThighBoots(0x748)); - EquipItem(new Cloak(0xCF)); - EquipItem(new BodySash(0xCF)); - } - - Spellbook book = new BookOfChivalry(); - - PackItem(book); - - book.LootType = LootType.Blessed; - - addSkillItems = false; - - break; - } - - case 6: // Samurai - { - addSkillItems = false; - EquipItem(new HakamaShita(0x2C3)); - EquipItem(new Hakama(0x2C3)); - EquipItem(new SamuraiTabi(0x2C3)); - EquipItem(new TattsukeHakama(0x22D)); - EquipItem(new Bokuto()); - - if (elf) - EquipItem(new RavenHelm()); - else - EquipItem(new LeatherJingasa()); - - PackItem(new Scissors()); - PackItem(new Bandage(50)); - - Spellbook book = new BookOfBushido(); - PackItem(book); - - break; - } - case 7: // Ninja - { - addSkillItems = false; - EquipItem(new Kasa()); - - int[] hues = { 0x1A8, 0xEC, 0x99, 0x90, 0xB5, 0x336, 0x89 }; - // TODO: Verify that's ALL the hues for that above. - - EquipItem(new TattsukeHakama(hues.RandomElement())); - - EquipItem(new HakamaShita(0x2C3)); - EquipItem(new NinjaTabi(0x2C3)); - - if (elf) - EquipItem(new AssassinSpike()); - else - EquipItem(new Tekagi()); - - PackItem(new SmokeBomb()); - - Spellbook book = new BookOfNinjitsu(); - PackItem(book); - - break; - } - } - - for (int i = 0; i < skills.Length; ++i) - { - SkillNameValue snv = skills[i]; - - if (snv.Value > 0 && (snv.Name != SkillName.Stealth || prof == 7) && snv.Name != SkillName.RemoveTrap && - snv.Name != SkillName.Spellweaving) - { - Skill skill = m.Skills[snv.Name]; - - if (skill != null) - { - skill.BaseFixedPoint = snv.Value * 10; - - if (addSkillItems) - AddSkillItems(snv.Name, m); - } } - } - } - private static void EquipItem(Item item, bool mustEquip = false) - { - if (!Core.AOS) - item.LootType = LootType.Newbied; + private static CityInfo GetStartLocation(CharacterCreatedEventArgs args, bool isYoung) + { + if (Core.ML) return m_NewHavenInfo; // We don't get the client Version until AFTER Character creation - if (m_Mobile?.EquipItem(item) == true) - return; + var useHaven = isYoung; - Container pack = m_Mobile?.Backpack; + var flags = args.State?.Flags ?? ClientFlags.None; + var m = args.Mobile; - if (!mustEquip && pack != null) - pack.DropItem(item); - else - item.Delete(); - } - - private static void PackItem(Item item) - { - if (!Core.AOS) - item.LootType = LootType.Newbied; - - Container pack = m_Mobile.Backpack; - - if (pack != null) - pack.DropItem(item); - else - item.Delete(); - } - - private static void PackInstrument() - { - switch (Utility.Random(6)) - { - case 0: - PackItem(new Drums()); - break; - case 1: - PackItem(new Harp()); - break; - case 2: - PackItem(new LapHarp()); - break; - case 3: - PackItem(new Lute()); - break; - case 4: - PackItem(new Tambourine()); - break; - case 5: - PackItem(new TambourineTassel()); - break; - } - } - - private static void PackScroll(int circle) - { - switch (Utility.Random(8) * (circle + 1)) - { - case 0: - PackItem(new ClumsyScroll()); - break; - case 1: - PackItem(new CreateFoodScroll()); - break; - case 2: - PackItem(new FeeblemindScroll()); - break; - case 3: - PackItem(new HealScroll()); - break; - case 4: - PackItem(new MagicArrowScroll()); - break; - case 5: - PackItem(new NightSightScroll()); - break; - case 6: - PackItem(new ReactiveArmorScroll()); - break; - case 7: - PackItem(new WeakenScroll()); - break; - case 8: - PackItem(new AgilityScroll()); - break; - case 9: - PackItem(new CunningScroll()); - break; - case 10: - PackItem(new CureScroll()); - break; - case 11: - PackItem(new HarmScroll()); - break; - case 12: - PackItem(new MagicTrapScroll()); - break; - case 13: - PackItem(new MagicUnTrapScroll()); - break; - case 14: - PackItem(new ProtectionScroll()); - break; - case 15: - PackItem(new StrengthScroll()); - break; - case 16: - PackItem(new BlessScroll()); - break; - case 17: - PackItem(new FireballScroll()); - break; - case 18: - PackItem(new MagicLockScroll()); - break; - case 19: - PackItem(new PoisonScroll()); - break; - case 20: - PackItem(new TelekinesisScroll()); - break; - case 21: - PackItem(new TeleportScroll()); - break; - case 22: - PackItem(new UnlockScroll()); - break; - case 23: - PackItem(new WallOfStoneScroll()); - break; - } - } - - private static Item NecroHue(Item item) - { - item.Hue = 0x2C3; - - return item; - } - - private static void AddSkillItems(SkillName skill, Mobile m) - { - bool elf = m.Race == Race.Elf; - - switch (skill) - { - case SkillName.Alchemy: - { - PackItem(new Bottle(4)); - PackItem(new MortarPestle()); - - int hue = Utility.RandomPinkHue(); - - if (elf) + switch (args.Profession) { - if (m.Female) - EquipItem(new FemaleElvenRobe(hue)); - else - EquipItem(new MaleElvenRobe(hue)); - } - else - { - EquipItem(new Robe(Utility.RandomPinkHue())); + case 4: // Necro + { + if ((flags & ClientFlags.Malas) != 0) + return new CityInfo("Umbra", "Mardoth's Tower", 2114, 1301, -50, Map.Malas); + + useHaven = true; + + // ReSharper disable once CA1806 + new BadStartMessage(m, 1062205); + /* + * Unfortunately you are playing on a *NON-Age-Of-Shadows* game + * installation and cannot be transported to Malas. + * You will not be able to take your new player quest in Malas + * without an AOS client. You are now being taken to the city of + * Haven on the Trammel facet. + * */ + + break; + } + case 5: // Paladin + { + return m_NewHavenInfo; + } + case 6: // Samurai + { + if ((flags & ClientFlags.Tokuno) != 0) + return new CityInfo("Samurai DE", "Haoti's Grounds", 368, 780, -1, Map.Malas); + + useHaven = true; + + // ReSharper disable once CA1806 + new BadStartMessage(m, 1063487); + /* + * Unfortunately you are playing on a *NON-Samurai-Empire* game + * installation and cannot be transported to Tokuno. + * You will not be able to take your new player quest in Tokuno + * without an SE client. You are now being taken to the city of + * Haven on the Trammel facet. + * */ + + break; + } + case 7: // Ninja + { + if ((flags & ClientFlags.Tokuno) != 0) + return new CityInfo("Ninja DE", "Enimo's Residence", 414, 823, -1, Map.Malas); + + useHaven = true; + + new BadStartMessage(m, 1063487); + /* + * Unfortunately you are playing on a *NON-Samurai-Empire* game + * installation and cannot be transported to Tokuno. + * You will not be able to take your new player quest in Tokuno + * without an SE client. You are now being taken to the city of + * Haven on the Trammel facet. + * */ + + break; + } } - break; - } - case SkillName.Anatomy: - { - PackItem(new Bandage(3)); + if (useHaven) + return m_NewHavenInfo; - int hue = Utility.RandomYellowHue(); + return args.City; + } - if (elf) + private static void FixStats(ref int str, ref int dex, ref int intel, int max) + { + var vMax = max - 30; + + var vStr = str - 10; + var vDex = dex - 10; + var vInt = intel - 10; + + if (vStr < 0) + vStr = 0; + + if (vDex < 0) + vDex = 0; + + if (vInt < 0) + vInt = 0; + + var total = vStr + vDex + vInt; + + if (total == 0 || total == vMax) + return; + + var scalar = vMax / (double)total; + + vStr = (int)(vStr * scalar); + vDex = (int)(vDex * scalar); + vInt = (int)(vInt * scalar); + + FixStat(ref vStr, vStr + vDex + vInt - vMax, vMax); + FixStat(ref vDex, vStr + vDex + vInt - vMax, vMax); + FixStat(ref vInt, vStr + vDex + vInt - vMax, vMax); + + str = vStr + 10; + dex = vDex + 10; + intel = vInt + 10; + } + + private static void FixStat(ref int stat, int diff, int max) + { + stat = Math.Clamp(stat + diff, 0, max); + } + + private static void SetStats(Mobile m, NetState state, int str, int dex, int intel) + { + var max = state.NewCharacterCreation ? 90 : 80; + + FixStats(ref str, ref dex, ref intel, max); + + if (str < 10 || str > 60 || dex < 10 || dex > 60 || intel < 10 || intel > 60 || str + dex + intel != max) { - if (m.Female) - EquipItem(new FemaleElvenRobe(hue)); - else - EquipItem(new MaleElvenRobe(hue)); - } - else - { - EquipItem(new Robe(hue)); + str = 10; + dex = 10; + intel = 10; } - break; - } - case SkillName.AnimalLore: - { - int hue = Utility.RandomBlueHue(); + m.InitStats(str, dex, intel); + } - if (elf) - { - EquipItem(new WildStaff()); + private static void SetName(Mobile m, string name) + { + name = name.Trim(); - if (m.Female) - EquipItem(new FemaleElvenRobe(hue)); - else - EquipItem(new MaleElvenRobe(hue)); - } - else + if (!NameVerification.Validate(name, 2, 16, true, false, true, 1, NameVerification.SpaceDashPeriodQuote)) + name = "Generic Player"; + + m.Name = name; + } + + private static bool ValidSkills(SkillNameValue[] skills) + { + var total = 0; + + for (var i = 0; i < skills.Length; ++i) { - EquipItem(new ShepherdsCrook()); - EquipItem(new Robe(hue)); + if (skills[i].Value < 0 || skills[i].Value > 50) + return false; + + total += skills[i].Value; + + for (var j = i + 1; j < skills.Length; ++j) + if (skills[j].Value > 0 && skills[j].Name == skills[i].Name) + return false; } - break; - } - case SkillName.Archery: - { - PackItem(new Arrow(25)); + return total == 100 || total == 120; + } - if (elf) - EquipItem(new ElvenCompositeLongbow()); - else - EquipItem(new Bow()); - - break; - } - case SkillName.ArmsLore: - { - if (elf) - switch (Utility.Random(3)) - { - case 0: - EquipItem(new Leafblade()); - break; - case 1: - EquipItem(new RuneBlade()); - break; - case 2: - EquipItem(new DiamondMace()); - break; - } - else - switch (Utility.Random(3)) - { - case 0: - EquipItem(new Kryss()); - break; - case 1: - EquipItem(new Katana()); - break; - case 2: - EquipItem(new Club()); - break; - } - - break; - } - case SkillName.Begging: - { - if (elf) - EquipItem(new WildStaff()); - else - EquipItem(new GnarledStaff()); - break; - } - case SkillName.Blacksmith: - { - PackItem(new Tongs()); - PackItem(new Pickaxe()); - PackItem(new Pickaxe()); - PackItem(new IronIngot(50)); - EquipItem(new HalfApron(Utility.RandomYellowHue())); - break; - } - case SkillName.Bushido: - { - EquipItem(new Hakama()); - EquipItem(new Kasa()); - EquipItem(new BookOfBushido()); - break; - } - case SkillName.Fletching: - { - PackItem(new Board(14)); - PackItem(new Feather(5)); - PackItem(new Shaft(5)); - break; - } - case SkillName.Camping: - { - PackItem(new Bedroll()); - PackItem(new Kindling(5)); - break; - } - case SkillName.Carpentry: - { - PackItem(new Board(10)); - PackItem(new Saw()); - EquipItem(new HalfApron(Utility.RandomYellowHue())); - break; - } - case SkillName.Cartography: - { - PackItem(new BlankMap()); - PackItem(new BlankMap()); - PackItem(new BlankMap()); - PackItem(new BlankMap()); - PackItem(new Sextant()); - break; - } - case SkillName.Cooking: - { - PackItem(new Kindling(2)); - PackItem(new RawLambLeg()); - PackItem(new RawChickenLeg()); - PackItem(new RawFishSteak()); - PackItem(new SackFlour()); - PackItem(new Pitcher(BeverageType.Water)); - break; - } - case SkillName.Chivalry: - { - if (Core.ML) - PackItem(new BookOfChivalry()); - - break; - } - case SkillName.DetectHidden: - { - EquipItem(new Cloak(0x455)); - break; - } - case SkillName.Discordance: - { - PackInstrument(); - break; - } - case SkillName.Fencing: - { - if (elf) - EquipItem(new Leafblade()); - else - EquipItem(new Kryss()); - - break; - } - case SkillName.Fishing: - { - EquipItem(new FishingPole()); - - int hue = Utility.RandomYellowHue(); - - if (elf) + private static void SetSkills(Mobile m, SkillNameValue[] skills, int prof) + { + switch (prof) { - Item i = new Circlet(); - i.Hue = hue; - EquipItem(i); - } - else - { - EquipItem(new FloppyHat(hue)); + case 1: // Warrior + { + skills = new[] + { + new SkillNameValue(SkillName.Anatomy, 30), + new SkillNameValue(SkillName.Healing, 45), + new SkillNameValue(SkillName.Swords, 35), + new SkillNameValue(SkillName.Tactics, 50) + }; + + break; + } + case 2: // Magician + { + skills = new[] + { + new SkillNameValue(SkillName.EvalInt, 30), + new SkillNameValue(SkillName.Wrestling, 30), + new SkillNameValue(SkillName.Magery, 50), + new SkillNameValue(SkillName.Meditation, 50) + }; + + break; + } + case 3: // Blacksmith + { + skills = new[] + { + new SkillNameValue(SkillName.Mining, 30), + new SkillNameValue(SkillName.ArmsLore, 30), + new SkillNameValue(SkillName.Blacksmith, 50), + new SkillNameValue(SkillName.Tinkering, 50) + }; + + break; + } + case 4: // Necromancer + { + skills = new[] + { + new SkillNameValue(SkillName.Necromancy, 50), + new SkillNameValue(SkillName.Focus, 30), + new SkillNameValue(SkillName.SpiritSpeak, 30), + new SkillNameValue(SkillName.Swords, 30), + new SkillNameValue(SkillName.Tactics, 20) + }; + + break; + } + case 5: // Paladin + { + skills = new[] + { + new SkillNameValue(SkillName.Chivalry, 51), + new SkillNameValue(SkillName.Swords, 49), + new SkillNameValue(SkillName.Focus, 30), + new SkillNameValue(SkillName.Tactics, 30) + }; + + break; + } + case 6: // Samurai + { + skills = new[] + { + new SkillNameValue(SkillName.Bushido, 50), + new SkillNameValue(SkillName.Swords, 50), + new SkillNameValue(SkillName.Anatomy, 30), + new SkillNameValue(SkillName.Healing, 30) + }; + break; + } + case 7: // Ninja + { + skills = new[] + { + new SkillNameValue(SkillName.Ninjitsu, 50), + new SkillNameValue(SkillName.Hiding, 50), + new SkillNameValue(SkillName.Fencing, 30), + new SkillNameValue(SkillName.Stealth, 30) + }; + break; + } + default: + { + if (!ValidSkills(skills)) + return; + + break; + } } - break; - } - case SkillName.Healing: - { - PackItem(new Bandage(50)); - PackItem(new Scissors()); - break; - } - case SkillName.Herding: - { - if (elf) - EquipItem(new WildStaff()); - else - EquipItem(new ShepherdsCrook()); + var addSkillItems = true; + var elf = m.Race == Race.Elf; - break; - } - case SkillName.Hiding: - { - EquipItem(new Cloak(0x455)); - break; - } - case SkillName.Inscribe: - { - PackItem(new BlankScroll(2)); - PackItem(new BlueBook()); - break; - } - case SkillName.ItemID: - { - if (elf) - EquipItem(new WildStaff()); - else - EquipItem(new GnarledStaff()); - break; - } - case SkillName.Lockpicking: - { - PackItem(new Lockpick(20)); - break; - } - case SkillName.Lumberjacking: - { - EquipItem(new Hatchet()); - break; - } - case SkillName.Macing: - { - if (elf) - EquipItem(new DiamondMace()); - else - EquipItem(new Club()); + switch (prof) + { + case 1: // Warrior + { + if (elf) + EquipItem(new LeafChest()); + else + EquipItem(new LeatherChest()); + break; + } + case 4: // Necromancer + { + Container regs = new BagOfNecroReagents(); - break; - } - case SkillName.Magery: - { - BagOfReagents regs = new BagOfReagents(30); + if (!Core.AOS) + foreach (var item in regs.Items) + item.LootType = LootType.Newbied; + PackItem(regs); + + regs.LootType = LootType.Regular; + + EquipItem(new BoneHelm()); + + if (elf) + { + EquipItem(new ElvenMachete()); + EquipItem(NecroHue(new LeafChest())); + EquipItem(NecroHue(new LeafArms())); + EquipItem(NecroHue(new LeafGloves())); + EquipItem(NecroHue(new LeafGorget())); + EquipItem(NecroHue(new LeafGorget())); + EquipItem(NecroHue(new ElvenPants())); // TODO: Verify the pants + EquipItem(new ElvenBoots()); + } + else + { + EquipItem(new BoneHarvester()); + EquipItem(NecroHue(new LeatherChest())); + EquipItem(NecroHue(new LeatherArms())); + EquipItem(NecroHue(new LeatherGloves())); + EquipItem(NecroHue(new LeatherGorget())); + EquipItem(NecroHue(new LeatherLegs())); + EquipItem(NecroHue(new Skirt())); + EquipItem(new Sandals(0x8FD)); + } + + Spellbook + book = new NecromancerSpellbook( + (ulong)0x8981 + ); // animate dead, evil omen, pain spike, summon familiar, wraith form + + PackItem(book); + + book.LootType = LootType.Blessed; + + addSkillItems = false; + + break; + } + case 5: // Paladin + { + if (elf) + { + EquipItem(new ElvenMachete()); + EquipItem(new WingedHelm()); + EquipItem(new LeafGorget()); + EquipItem(new LeafArms()); + EquipItem(new LeafChest()); + EquipItem(new LeafLegs()); + EquipItem(new ElvenBoots()); // Verify hue + } + else + { + EquipItem(new Broadsword()); + EquipItem(new Helmet()); + EquipItem(new PlateGorget()); + EquipItem(new RingmailArms()); + EquipItem(new RingmailChest()); + EquipItem(new RingmailLegs()); + EquipItem(new ThighBoots(0x748)); + EquipItem(new Cloak(0xCF)); + EquipItem(new BodySash(0xCF)); + } + + Spellbook book = new BookOfChivalry(); + + PackItem(book); + + book.LootType = LootType.Blessed; + + addSkillItems = false; + + break; + } + + case 6: // Samurai + { + addSkillItems = false; + EquipItem(new HakamaShita(0x2C3)); + EquipItem(new Hakama(0x2C3)); + EquipItem(new SamuraiTabi(0x2C3)); + EquipItem(new TattsukeHakama(0x22D)); + EquipItem(new Bokuto()); + + if (elf) + EquipItem(new RavenHelm()); + else + EquipItem(new LeatherJingasa()); + + PackItem(new Scissors()); + PackItem(new Bandage(50)); + + Spellbook book = new BookOfBushido(); + PackItem(book); + + break; + } + case 7: // Ninja + { + addSkillItems = false; + EquipItem(new Kasa()); + + int[] hues = { 0x1A8, 0xEC, 0x99, 0x90, 0xB5, 0x336, 0x89 }; + // TODO: Verify that's ALL the hues for that above. + + EquipItem(new TattsukeHakama(hues.RandomElement())); + + EquipItem(new HakamaShita(0x2C3)); + EquipItem(new NinjaTabi(0x2C3)); + + if (elf) + EquipItem(new AssassinSpike()); + else + EquipItem(new Tekagi()); + + PackItem(new SmokeBomb()); + + Spellbook book = new BookOfNinjitsu(); + PackItem(book); + + break; + } + } + + for (var i = 0; i < skills.Length; ++i) + { + var snv = skills[i]; + + if (snv.Value > 0 && (snv.Name != SkillName.Stealth || prof == 7) && snv.Name != SkillName.RemoveTrap && + snv.Name != SkillName.Spellweaving) + { + var skill = m.Skills[snv.Name]; + + if (skill != null) + { + skill.BaseFixedPoint = snv.Value * 10; + + if (addSkillItems) + AddSkillItems(snv.Name, m); + } + } + } + } + + private static void EquipItem(Item item, bool mustEquip = false) + { if (!Core.AOS) - foreach (Item item in regs.Items) item.LootType = LootType.Newbied; - PackItem(regs); + if (m_Mobile?.EquipItem(item) == true) + return; - regs.LootType = LootType.Regular; + var pack = m_Mobile?.Backpack; - PackScroll(0); - PackScroll(1); - PackScroll(2); + if (!mustEquip && pack != null) + pack.DropItem(item); + else + item.Delete(); + } - Spellbook book = new Spellbook((ulong)0x382A8C38); + private static void PackItem(Item item) + { + if (!Core.AOS) + item.LootType = LootType.Newbied; - EquipItem(book); + var pack = m_Mobile.Backpack; - book.LootType = LootType.Blessed; + if (pack != null) + pack.DropItem(item); + else + item.Delete(); + } - if (elf) + private static void PackInstrument() + { + switch (Utility.Random(6)) { - EquipItem(new Circlet()); - - if (m.Female) - EquipItem(new FemaleElvenRobe(Utility.RandomBlueHue())); - else - EquipItem(new MaleElvenRobe(Utility.RandomBlueHue())); + case 0: + PackItem(new Drums()); + break; + case 1: + PackItem(new Harp()); + break; + case 2: + PackItem(new LapHarp()); + break; + case 3: + PackItem(new Lute()); + break; + case 4: + PackItem(new Tambourine()); + break; + case 5: + PackItem(new TambourineTassel()); + break; } - else + } + + private static void PackScroll(int circle) + { + switch (Utility.Random(8) * (circle + 1)) { - EquipItem(new WizardsHat()); - EquipItem(new Robe(Utility.RandomBlueHue())); + case 0: + PackItem(new ClumsyScroll()); + break; + case 1: + PackItem(new CreateFoodScroll()); + break; + case 2: + PackItem(new FeeblemindScroll()); + break; + case 3: + PackItem(new HealScroll()); + break; + case 4: + PackItem(new MagicArrowScroll()); + break; + case 5: + PackItem(new NightSightScroll()); + break; + case 6: + PackItem(new ReactiveArmorScroll()); + break; + case 7: + PackItem(new WeakenScroll()); + break; + case 8: + PackItem(new AgilityScroll()); + break; + case 9: + PackItem(new CunningScroll()); + break; + case 10: + PackItem(new CureScroll()); + break; + case 11: + PackItem(new HarmScroll()); + break; + case 12: + PackItem(new MagicTrapScroll()); + break; + case 13: + PackItem(new MagicUnTrapScroll()); + break; + case 14: + PackItem(new ProtectionScroll()); + break; + case 15: + PackItem(new StrengthScroll()); + break; + case 16: + PackItem(new BlessScroll()); + break; + case 17: + PackItem(new FireballScroll()); + break; + case 18: + PackItem(new MagicLockScroll()); + break; + case 19: + PackItem(new PoisonScroll()); + break; + case 20: + PackItem(new TelekinesisScroll()); + break; + case 21: + PackItem(new TeleportScroll()); + break; + case 22: + PackItem(new UnlockScroll()); + break; + case 23: + PackItem(new WallOfStoneScroll()); + break; } + } - break; - } - case SkillName.Mining: - { - PackItem(new Pickaxe()); - break; - } - case SkillName.Musicianship: - { - PackInstrument(); - break; - } - case SkillName.Necromancy: - { - if (Core.ML) + private static Item NecroHue(Item item) + { + item.Hue = 0x2C3; + + return item; + } + + private static void AddSkillItems(SkillName skill, Mobile m) + { + var elf = m.Race == Race.Elf; + + switch (skill) { - Container regs = new BagOfNecroReagents(); + case SkillName.Alchemy: + { + PackItem(new Bottle(4)); + PackItem(new MortarPestle()); - PackItem(regs); + var hue = Utility.RandomPinkHue(); - regs.LootType = LootType.Regular; + if (elf) + { + if (m.Female) + EquipItem(new FemaleElvenRobe(hue)); + else + EquipItem(new MaleElvenRobe(hue)); + } + else + { + EquipItem(new Robe(Utility.RandomPinkHue())); + } + + break; + } + case SkillName.Anatomy: + { + PackItem(new Bandage(3)); + + var hue = Utility.RandomYellowHue(); + + if (elf) + { + if (m.Female) + EquipItem(new FemaleElvenRobe(hue)); + else + EquipItem(new MaleElvenRobe(hue)); + } + else + { + EquipItem(new Robe(hue)); + } + + break; + } + case SkillName.AnimalLore: + { + var hue = Utility.RandomBlueHue(); + + if (elf) + { + EquipItem(new WildStaff()); + + if (m.Female) + EquipItem(new FemaleElvenRobe(hue)); + else + EquipItem(new MaleElvenRobe(hue)); + } + else + { + EquipItem(new ShepherdsCrook()); + EquipItem(new Robe(hue)); + } + + break; + } + case SkillName.Archery: + { + PackItem(new Arrow(25)); + + if (elf) + EquipItem(new ElvenCompositeLongbow()); + else + EquipItem(new Bow()); + + break; + } + case SkillName.ArmsLore: + { + if (elf) + switch (Utility.Random(3)) + { + case 0: + EquipItem(new Leafblade()); + break; + case 1: + EquipItem(new RuneBlade()); + break; + case 2: + EquipItem(new DiamondMace()); + break; + } + else + switch (Utility.Random(3)) + { + case 0: + EquipItem(new Kryss()); + break; + case 1: + EquipItem(new Katana()); + break; + case 2: + EquipItem(new Club()); + break; + } + + break; + } + case SkillName.Begging: + { + if (elf) + EquipItem(new WildStaff()); + else + EquipItem(new GnarledStaff()); + break; + } + case SkillName.Blacksmith: + { + PackItem(new Tongs()); + PackItem(new Pickaxe()); + PackItem(new Pickaxe()); + PackItem(new IronIngot(50)); + EquipItem(new HalfApron(Utility.RandomYellowHue())); + break; + } + case SkillName.Bushido: + { + EquipItem(new Hakama()); + EquipItem(new Kasa()); + EquipItem(new BookOfBushido()); + break; + } + case SkillName.Fletching: + { + PackItem(new Board(14)); + PackItem(new Feather(5)); + PackItem(new Shaft(5)); + break; + } + case SkillName.Camping: + { + PackItem(new Bedroll()); + PackItem(new Kindling(5)); + break; + } + case SkillName.Carpentry: + { + PackItem(new Board(10)); + PackItem(new Saw()); + EquipItem(new HalfApron(Utility.RandomYellowHue())); + break; + } + case SkillName.Cartography: + { + PackItem(new BlankMap()); + PackItem(new BlankMap()); + PackItem(new BlankMap()); + PackItem(new BlankMap()); + PackItem(new Sextant()); + break; + } + case SkillName.Cooking: + { + PackItem(new Kindling(2)); + PackItem(new RawLambLeg()); + PackItem(new RawChickenLeg()); + PackItem(new RawFishSteak()); + PackItem(new SackFlour()); + PackItem(new Pitcher(BeverageType.Water)); + break; + } + case SkillName.Chivalry: + { + if (Core.ML) + PackItem(new BookOfChivalry()); + + break; + } + case SkillName.DetectHidden: + { + EquipItem(new Cloak(0x455)); + break; + } + case SkillName.Discordance: + { + PackInstrument(); + break; + } + case SkillName.Fencing: + { + if (elf) + EquipItem(new Leafblade()); + else + EquipItem(new Kryss()); + + break; + } + case SkillName.Fishing: + { + EquipItem(new FishingPole()); + + var hue = Utility.RandomYellowHue(); + + if (elf) + { + Item i = new Circlet(); + i.Hue = hue; + EquipItem(i); + } + else + { + EquipItem(new FloppyHat(hue)); + } + + break; + } + case SkillName.Healing: + { + PackItem(new Bandage(50)); + PackItem(new Scissors()); + break; + } + case SkillName.Herding: + { + if (elf) + EquipItem(new WildStaff()); + else + EquipItem(new ShepherdsCrook()); + + break; + } + case SkillName.Hiding: + { + EquipItem(new Cloak(0x455)); + break; + } + case SkillName.Inscribe: + { + PackItem(new BlankScroll(2)); + PackItem(new BlueBook()); + break; + } + case SkillName.ItemID: + { + if (elf) + EquipItem(new WildStaff()); + else + EquipItem(new GnarledStaff()); + break; + } + case SkillName.Lockpicking: + { + PackItem(new Lockpick(20)); + break; + } + case SkillName.Lumberjacking: + { + EquipItem(new Hatchet()); + break; + } + case SkillName.Macing: + { + if (elf) + EquipItem(new DiamondMace()); + else + EquipItem(new Club()); + + break; + } + case SkillName.Magery: + { + var regs = new BagOfReagents(30); + + if (!Core.AOS) + foreach (var item in regs.Items) + item.LootType = LootType.Newbied; + + PackItem(regs); + + regs.LootType = LootType.Regular; + + PackScroll(0); + PackScroll(1); + PackScroll(2); + + var book = new Spellbook((ulong)0x382A8C38); + + EquipItem(book); + + book.LootType = LootType.Blessed; + + if (elf) + { + EquipItem(new Circlet()); + + if (m.Female) + EquipItem(new FemaleElvenRobe(Utility.RandomBlueHue())); + else + EquipItem(new MaleElvenRobe(Utility.RandomBlueHue())); + } + else + { + EquipItem(new WizardsHat()); + EquipItem(new Robe(Utility.RandomBlueHue())); + } + + break; + } + case SkillName.Mining: + { + PackItem(new Pickaxe()); + break; + } + case SkillName.Musicianship: + { + PackInstrument(); + break; + } + case SkillName.Necromancy: + { + if (Core.ML) + { + Container regs = new BagOfNecroReagents(); + + PackItem(regs); + + regs.LootType = LootType.Regular; + } + + break; + } + case SkillName.Ninjitsu: + { + EquipItem(new Hakama(0x2C3)); // Only ninjas get the hued one. + EquipItem(new Kasa()); + EquipItem(new BookOfNinjitsu()); + break; + } + case SkillName.Parry: + { + EquipItem(new WoodenShield()); + break; + } + case SkillName.Peacemaking: + { + PackInstrument(); + break; + } + case SkillName.Poisoning: + { + PackItem(new LesserPoisonPotion()); + PackItem(new LesserPoisonPotion()); + break; + } + case SkillName.Provocation: + { + PackInstrument(); + break; + } + case SkillName.Snooping: + { + PackItem(new Lockpick(20)); + break; + } + case SkillName.SpiritSpeak: + { + EquipItem(new Cloak(0x455)); + break; + } + case SkillName.Stealing: + { + PackItem(new Lockpick(20)); + break; + } + case SkillName.Swords: + { + if (elf) + EquipItem(new RuneBlade()); + else + EquipItem(new Katana()); + + break; + } + case SkillName.Tactics: + { + if (elf) + EquipItem(new RuneBlade()); + else + EquipItem(new Katana()); + + break; + } + case SkillName.Tailoring: + { + PackItem(new BoltOfCloth()); + PackItem(new SewingKit()); + break; + } + case SkillName.Tracking: + { + var shoes = m_Mobile?.FindItemOnLayer(Layer.Shoes); + + shoes?.Delete(); + + var hue = Utility.RandomYellowHue(); + + if (elf) + EquipItem(new ElvenBoots(hue)); + else + EquipItem(new Boots(hue)); + + EquipItem(new SkinningKnife()); + break; + } + case SkillName.Veterinary: + { + PackItem(new Bandage(5)); + PackItem(new Scissors()); + break; + } + case SkillName.Wrestling: + { + if (elf) + EquipItem(new LeafGloves()); + else + EquipItem(new LeatherGloves()); + + break; + } } - - break; - } - case SkillName.Ninjitsu: - { - EquipItem(new Hakama(0x2C3)); // Only ninjas get the hued one. - EquipItem(new Kasa()); - EquipItem(new BookOfNinjitsu()); - break; - } - case SkillName.Parry: - { - EquipItem(new WoodenShield()); - break; - } - case SkillName.Peacemaking: - { - PackInstrument(); - break; - } - case SkillName.Poisoning: - { - PackItem(new LesserPoisonPotion()); - PackItem(new LesserPoisonPotion()); - break; - } - case SkillName.Provocation: - { - PackInstrument(); - break; - } - case SkillName.Snooping: - { - PackItem(new Lockpick(20)); - break; - } - case SkillName.SpiritSpeak: - { - EquipItem(new Cloak(0x455)); - break; - } - case SkillName.Stealing: - { - PackItem(new Lockpick(20)); - break; - } - case SkillName.Swords: - { - if (elf) - EquipItem(new RuneBlade()); - else - EquipItem(new Katana()); - - break; - } - case SkillName.Tactics: - { - if (elf) - EquipItem(new RuneBlade()); - else - EquipItem(new Katana()); - - break; - } - case SkillName.Tailoring: - { - PackItem(new BoltOfCloth()); - PackItem(new SewingKit()); - break; - } - case SkillName.Tracking: - { - Item shoes = m_Mobile?.FindItemOnLayer(Layer.Shoes); - - shoes?.Delete(); - - int hue = Utility.RandomYellowHue(); - - if (elf) - EquipItem(new ElvenBoots(hue)); - else - EquipItem(new Boots(hue)); - - EquipItem(new SkinningKnife()); - break; - } - case SkillName.Veterinary: - { - PackItem(new Bandage(5)); - PackItem(new Scissors()); - break; - } - case SkillName.Wrestling: - { - if (elf) - EquipItem(new LeafGloves()); - else - EquipItem(new LeatherGloves()); - - break; - } - } + } } - } - class BadStartMessage : Timer - { - private readonly int m_Message; - private readonly Mobile m_Mobile; - - public BadStartMessage(Mobile m, int message) : base(TimeSpan.FromSeconds(3.5)) + internal class BadStartMessage : Timer { - m_Mobile = m; - m_Message = message; - Start(); - } + private readonly int m_Message; + private readonly Mobile m_Mobile; - protected override void OnTick() - { - m_Mobile.SendLocalizedMessage(m_Message); + public BadStartMessage(Mobile m, int message) : base(TimeSpan.FromSeconds(3.5)) + { + m_Mobile = m; + m_Message = message; + Start(); + } + + protected override void OnTick() + { + m_Mobile.SendLocalizedMessage(m_Message); + } } - } } diff --git a/Projects/UOContent/Misc/Cleanup.cs b/Projects/UOContent/Misc/Cleanup.cs index c862837f8..40d23317d 100644 --- a/Projects/UOContent/Misc/Cleanup.cs +++ b/Projects/UOContent/Misc/Cleanup.cs @@ -1,158 +1,161 @@ using System; using System.Collections.Generic; using Server.Items; -using Server.Mobiles; using Server.Multis; namespace Server.Misc { - public class Cleanup - { - public static void Initialize() + public class Cleanup { - Timer.DelayCall(TimeSpan.FromSeconds(2.5), Run); - } - - public static void Run() - { - List items = new List(); - List validItems = new List(); - List hairCleanup = new List(); - - int boxes = 0; - - foreach (Item item in World.Items.Values) - { - if (item.Map == null) + public static void Initialize() { - items.Add(item); - continue; + Timer.DelayCall(TimeSpan.FromSeconds(2.5), Run); } - if (item is CommodityDeed deed) + public static void Run() { - if (deed.Commodity != null) - validItems.Add(deed.Commodity); + var items = new List(); + var validItems = new List(); + var hairCleanup = new List(); - continue; - } + var boxes = 0; - if (item is BaseHouse house) - { - foreach (RelocatedEntity relEntity in house.RelocatedEntities) - if (relEntity.Entity is Item item1) - validItems.Add(item1); - - foreach (VendorInventory inventory in house.VendorInventories) - foreach (Item subItem in inventory.Items) - validItems.Add(subItem); - } - else if (item is BankBox box) - { - Mobile owner = box.Owner; - - if (owner == null) - { - items.Add(box); - ++boxes; - } - else if (box.Items.Count == 0) - { - items.Add(box); - ++boxes; - } - - continue; - } - else if (item.Layer == Layer.Hair || item.Layer == Layer.FacialHair) - { - if (item.RootParent is Mobile rootMobile) - { - if (item.Parent != rootMobile && rootMobile.AccessLevel == AccessLevel.Player) + foreach (var item in World.Items.Values) { - items.Add(item); - continue; + if (item.Map == null) + { + items.Add(item); + continue; + } + + if (item is CommodityDeed deed) + { + if (deed.Commodity != null) + validItems.Add(deed.Commodity); + + continue; + } + + if (item is BaseHouse house) + { + foreach (var relEntity in house.RelocatedEntities) + if (relEntity.Entity is Item item1) + validItems.Add(item1); + + foreach (var inventory in house.VendorInventories) + foreach (var subItem in inventory.Items) + validItems.Add(subItem); + } + else if (item is BankBox box) + { + var owner = box.Owner; + + if (owner == null) + { + items.Add(box); + ++boxes; + } + else if (box.Items.Count == 0) + { + items.Add(box); + ++boxes; + } + + continue; + } + else if (item.Layer == Layer.Hair || item.Layer == Layer.FacialHair) + { + if (item.RootParent is Mobile rootMobile) + { + if (item.Parent != rootMobile && rootMobile.AccessLevel == AccessLevel.Player) + { + items.Add(item); + continue; + } + + if (item.Parent == rootMobile) + { + hairCleanup.Add(rootMobile); + continue; + } + } + } + + if (item.Parent != null || item.Map != Map.Internal || item.HeldBy != null) + continue; + + if (item.Location != Point3D.Zero) + continue; + + if (!IsBuggable(item)) + continue; + + items.Add(item); } - if (item.Parent == rootMobile) + for (var i = 0; i < validItems.Count; ++i) + items.Remove(validItems[i]); + + if (items.Count > 0) { - hairCleanup.Add(rootMobile); - continue; + if (boxes > 0) + Console.WriteLine( + "Cleanup: Detected {0} inaccessible items, including {1} bank boxes, removing..", + items.Count, + boxes + ); + else + Console.WriteLine("Cleanup: Detected {0} inaccessible items, removing..", items.Count); + + for (var i = 0; i < items.Count; ++i) + items[i].Delete(); + } + + if (hairCleanup.Count > 0) + { + Console.WriteLine( + "Cleanup: Detected {0} hair and facial hair items being worn, converting to their virtual counterparts..", + hairCleanup.Count + ); + + for (var i = 0; i < hairCleanup.Count; i++) + hairCleanup[i].ConvertHair(); } - } } - if (item.Parent != null || item.Map != Map.Internal || item.HeldBy != null) - continue; + public static bool IsBuggable(Item item) + { + if (item is Fists) + return false; - if (item.Location != Point3D.Zero) - continue; + if (item is ICommodity || item is BaseBoat + || item is Fish || item is BigFish || item is Food || item is CookableFood + || item is SpecialFishingNet || item is BaseMagicFish + || item is Shoes || item is Sandals + || item is Boots || item is ThighBoots + || item is TreasureMap || item is MessageInABottle + || item is BaseArmor || item is BaseWeapon + || item is BaseClothing + || item is BaseJewel && Core.AOS || item is SkullPole + || item is EvilIdolSkull + || item is MonsterStatuette + || item is Pier + || item is ArtifactLargeVase + || item is ArtifactVase + || item is MinotaurStatueDeed + || item is SwampTile + || item is WallBlood + || item is TatteredAncientMummyWrapping + || item is LavaTile + || item is DemonSkull + || item is Web + || item is WaterTile + || item is WindSpirit + || item is DirtPatch + || item is Futon) + return true; - if (!IsBuggable(item)) - continue; - - items.Add(item); - } - - for (int i = 0; i < validItems.Count; ++i) - items.Remove(validItems[i]); - - if (items.Count > 0) - { - if (boxes > 0) - Console.WriteLine("Cleanup: Detected {0} inaccessible items, including {1} bank boxes, removing..", - items.Count, boxes); - else - Console.WriteLine("Cleanup: Detected {0} inaccessible items, removing..", items.Count); - - for (int i = 0; i < items.Count; ++i) - items[i].Delete(); - } - - if (hairCleanup.Count > 0) - { - Console.WriteLine( - "Cleanup: Detected {0} hair and facial hair items being worn, converting to their virtual counterparts..", - hairCleanup.Count); - - for (int i = 0; i < hairCleanup.Count; i++) - hairCleanup[i].ConvertHair(); - } + return false; + } } - - public static bool IsBuggable(Item item) - { - if (item is Fists) - return false; - - if (item is ICommodity || item is BaseBoat - || item is Fish || item is BigFish || item is Food || item is CookableFood - || item is SpecialFishingNet || item is BaseMagicFish - || item is Shoes || item is Sandals - || item is Boots || item is ThighBoots - || item is TreasureMap || item is MessageInABottle - || item is BaseArmor || item is BaseWeapon - || item is BaseClothing - || (item is BaseJewel && Core.AOS) || item is SkullPole - || item is EvilIdolSkull - || item is MonsterStatuette - || item is Pier - || item is ArtifactLargeVase - || item is ArtifactVase - || item is MinotaurStatueDeed - || item is SwampTile - || item is WallBlood - || item is TatteredAncientMummyWrapping - || item is LavaTile - || item is DemonSkull - || item is Web - || item is WaterTile - || item is WindSpirit - || item is DirtPatch - || item is Futon) - return true; - - return false; - } - } } diff --git a/Projects/UOContent/Misc/ClientVerification.cs b/Projects/UOContent/Misc/ClientVerification.cs index b3fd363a4..3e65afac0 100644 --- a/Projects/UOContent/Misc/ClientVerification.cs +++ b/Projects/UOContent/Misc/ClientVerification.cs @@ -7,174 +7,200 @@ using Server.Network; namespace Server.Misc { - public class ClientVerification - { - private static bool m_DetectClientRequirement; - private static OldClientResponse m_OldClientResponse; - - private static TimeSpan m_AgeLeniency; - private static TimeSpan m_GameTimeLeniency; - - public static ClientVersion Required { get; set; } - - public static bool AllowRegular { get; set; } = true; - - public static bool AllowUOTD { get; set; } = true; - - public static bool AllowGod { get; set; } = true; - - public static TimeSpan KickDelay { get; set; } - - public static void Initialize() + public class ClientVerification { - m_DetectClientRequirement = ServerConfiguration.GetOrUpdateSetting("clientVerification.enable", true); - m_OldClientResponse = - ServerConfiguration.GetOrUpdateSetting("clientVerification.oldClientResponse", OldClientResponse.Kick); - m_AgeLeniency = ServerConfiguration.GetOrUpdateSetting("clientVerification.ageLeniency", TimeSpan.FromDays(10)); - m_GameTimeLeniency = ServerConfiguration.GetOrUpdateSetting("clientVerification.gameTimeLeniency", TimeSpan.FromHours(25)); - KickDelay = ServerConfiguration.GetOrUpdateSetting("clientVerification.kickDelay", TimeSpan.FromSeconds(20.0)); + private static bool m_DetectClientRequirement; + private static OldClientResponse m_OldClientResponse; - EventSink.ClientVersionReceived += EventSink_ClientVersionReceived; + private static TimeSpan m_AgeLeniency; + private static TimeSpan m_GameTimeLeniency; - if (m_DetectClientRequirement) - { - string path = Core.FindDataFile("client.exe", false); + public static ClientVersion Required { get; set; } - if (File.Exists(path)) + public static bool AllowRegular { get; set; } = true; + + public static bool AllowUOTD { get; set; } = true; + + public static bool AllowGod { get; set; } = true; + + public static TimeSpan KickDelay { get; set; } + + public static void Initialize() { - FileVersionInfo info = FileVersionInfo.GetVersionInfo(path); + m_DetectClientRequirement = ServerConfiguration.GetOrUpdateSetting("clientVerification.enable", true); + m_OldClientResponse = + ServerConfiguration.GetOrUpdateSetting("clientVerification.oldClientResponse", OldClientResponse.Kick); + m_AgeLeniency = ServerConfiguration.GetOrUpdateSetting("clientVerification.ageLeniency", TimeSpan.FromDays(10)); + m_GameTimeLeniency = ServerConfiguration.GetOrUpdateSetting( + "clientVerification.gameTimeLeniency", + TimeSpan.FromHours(25) + ); + KickDelay = ServerConfiguration.GetOrUpdateSetting("clientVerification.kickDelay", TimeSpan.FromSeconds(20.0)); - if (info.FileMajorPart != 0 || info.FileMinorPart != 0 || info.FileBuildPart != 0 || - info.FilePrivatePart != 0) - Required = new ClientVersion(info.FileMajorPart, info.FileMinorPart, info.FileBuildPart, - info.FilePrivatePart); - } - } + EventSink.ClientVersionReceived += EventSink_ClientVersionReceived; - if (Required != null) - { - Utility.PushColor(ConsoleColor.White); - Console.WriteLine("Restricting client version to {0}. Action to be taken: {1}", Required, - m_OldClientResponse); - Utility.PopColor(); - } - } - - private static void EventSink_ClientVersionReceived(NetState state, ClientVersion version) - { - string kickMessage = null; - - if (state.Mobile?.AccessLevel != AccessLevel.Player) - return; - - if (Required != null && version < Required && (m_OldClientResponse == OldClientResponse.Kick || - m_OldClientResponse == OldClientResponse.LenientKick && - DateTime.UtcNow - state.Mobile.CreationTime > m_AgeLeniency && - state.Mobile is PlayerMobile mobile && - mobile.GameTime > m_GameTimeLeniency)) - { - kickMessage = $"This server requires your client version be at least {Required}."; - } - else if (!AllowGod || !AllowRegular || !AllowUOTD) - { - if (!AllowGod && version.Type == ClientType.God) - kickMessage = "This server does not allow god clients to connect."; - else if (!AllowRegular && version.Type == ClientType.Regular) - kickMessage = "This server does not allow regular clients to connect."; - else if (!AllowUOTD && state.IsUOTDClient) - kickMessage = "This server does not allow UO:TD clients to connect."; - - if (!AllowGod && !AllowRegular && !AllowUOTD) - { - kickMessage = "This server does not allow any clients to connect."; - } - else if (AllowGod && !AllowRegular && !AllowUOTD && version.Type != ClientType.God) - { - kickMessage = "This server requires you to use the god client."; - } - else if (kickMessage != null) - { - if (AllowRegular && AllowUOTD) - kickMessage += " You can use regular or UO:TD clients."; - else if (AllowRegular) - kickMessage += " You can use regular clients."; - else if (AllowUOTD) - kickMessage += " You can use UO:TD clients."; - } - } - - if (kickMessage != null) - { - state.Mobile.SendMessage(0x22, kickMessage); - state.Mobile.SendMessage(0x22, "You will be disconnected in {0} seconds.", KickDelay.TotalSeconds); - - Timer.DelayCall(KickDelay, OnKick, state); - } - else if (Required != null && version < Required) - { - switch (m_OldClientResponse) - { - case OldClientResponse.Warn: + if (m_DetectClientRequirement) { - state.Mobile.SendMessage(0x22, "Your client is out of date. Please update your client.", Required); - state.Mobile.SendMessage(0x22, "This server recommends that your client version be at least {0}.", - Required); - break; + var path = Core.FindDataFile("client.exe", false); + + if (File.Exists(path)) + { + var info = FileVersionInfo.GetVersionInfo(path); + + if (info.FileMajorPart != 0 || info.FileMinorPart != 0 || info.FileBuildPart != 0 || + info.FilePrivatePart != 0) + Required = new ClientVersion( + info.FileMajorPart, + info.FileMinorPart, + info.FileBuildPart, + info.FilePrivatePart + ); + } } - case OldClientResponse.LenientKick: - case OldClientResponse.Annoy: + + if (Required != null) { - SendAnnoyGump(state.Mobile); - break; + Utility.PushColor(ConsoleColor.White); + Console.WriteLine( + "Restricting client version to {0}. Action to be taken: {1}", + Required, + m_OldClientResponse + ); + Utility.PopColor(); } } - } + + private static void EventSink_ClientVersionReceived(NetState state, ClientVersion version) + { + string kickMessage = null; + + if (state.Mobile?.AccessLevel != AccessLevel.Player) + return; + + if (Required != null && version < Required && (m_OldClientResponse == OldClientResponse.Kick || + m_OldClientResponse == OldClientResponse.LenientKick && + DateTime.UtcNow - state.Mobile.CreationTime > m_AgeLeniency && + state.Mobile is PlayerMobile mobile && + mobile.GameTime > m_GameTimeLeniency)) + { + kickMessage = $"This server requires your client version be at least {Required}."; + } + else if (!AllowGod || !AllowRegular || !AllowUOTD) + { + if (!AllowGod && version.Type == ClientType.God) + kickMessage = "This server does not allow god clients to connect."; + else if (!AllowRegular && version.Type == ClientType.Regular) + kickMessage = "This server does not allow regular clients to connect."; + else if (!AllowUOTD && state.IsUOTDClient) + kickMessage = "This server does not allow UO:TD clients to connect."; + + if (!AllowGod && !AllowRegular && !AllowUOTD) + { + kickMessage = "This server does not allow any clients to connect."; + } + else if (AllowGod && !AllowRegular && !AllowUOTD && version.Type != ClientType.God) + { + kickMessage = "This server requires you to use the god client."; + } + else if (kickMessage != null) + { + if (AllowRegular && AllowUOTD) + kickMessage += " You can use regular or UO:TD clients."; + else if (AllowRegular) + kickMessage += " You can use regular clients."; + else if (AllowUOTD) + kickMessage += " You can use UO:TD clients."; + } + } + + if (kickMessage != null) + { + state.Mobile.SendMessage(0x22, kickMessage); + state.Mobile.SendMessage(0x22, "You will be disconnected in {0} seconds.", KickDelay.TotalSeconds); + + Timer.DelayCall(KickDelay, OnKick, state); + } + else if (Required != null && version < Required) + { + switch (m_OldClientResponse) + { + case OldClientResponse.Warn: + { + state.Mobile.SendMessage( + 0x22, + "Your client is out of date. Please update your client.", + Required + ); + state.Mobile.SendMessage( + 0x22, + "This server recommends that your client version be at least {0}.", + Required + ); + break; + } + case OldClientResponse.LenientKick: + case OldClientResponse.Annoy: + { + SendAnnoyGump(state.Mobile); + break; + } + } + } + } + + private static void OnKick(NetState ns) + { + if (ns.Connection != null) + { + Console.WriteLine("Client: {0}: Disconnecting, bad version", ns); + ns.Dispose(); + } + } + + private static void KickMessage(Mobile from, bool okay) + { + from.SendMessage("You will be reminded of this again."); + + if (m_OldClientResponse == OldClientResponse.LenientKick) + from.SendMessage( + "Old clients will be kicked after {0} days of character age and {1} hours of play time", + m_AgeLeniency, + m_GameTimeLeniency + ); + + Timer.DelayCall(TimeSpan.FromMinutes(Utility.Random(5, 15)), SendAnnoyGump, from); + } + + private static void SendAnnoyGump(Mobile m) + { + if (m.NetState != null && m.NetState.Version < Required) + { + Gump g = new WarningGump( + 1060637, + 30720, + $"Your client is out of date. Please update your client.
This server recommends that your client version be at least {Required}.

You are currently using version {m.NetState.Version}.

To patch, run UOPatch.exe inside your Ultima Online folder.", + 0xFFC000, + 480, + 360, + okay => KickMessage(m, okay), + false + ); + + g.Draggable = false; + g.Closable = false; + g.Resizable = false; + + m.SendGump(g); + } + } + + private enum OldClientResponse + { + Ignore, + Warn, + Annoy, + LenientKick, + Kick + } } - - private static void OnKick(NetState ns) - { - if (ns.Connection != null) - { - Console.WriteLine("Client: {0}: Disconnecting, bad version", ns); - ns.Dispose(); - } - } - - private static void KickMessage(Mobile from, bool okay) - { - from.SendMessage("You will be reminded of this again."); - - if (m_OldClientResponse == OldClientResponse.LenientKick) - from.SendMessage( - "Old clients will be kicked after {0} days of character age and {1} hours of play time", - m_AgeLeniency, m_GameTimeLeniency); - - Timer.DelayCall(TimeSpan.FromMinutes(Utility.Random(5, 15)), SendAnnoyGump, from); - } - - private static void SendAnnoyGump(Mobile m) - { - if (m.NetState != null && m.NetState.Version < Required) - { - Gump g = new WarningGump(1060637, 30720, - $"Your client is out of date. Please update your client.
This server recommends that your client version be at least {Required}.

You are currently using version {m.NetState.Version}.

To patch, run UOPatch.exe inside your Ultima Online folder.", - 0xFFC000, 480, 360, okay => KickMessage(m, okay), false); - - g.Draggable = false; - g.Closable = false; - g.Resizable = false; - - m.SendGump(g); - } - } - - private enum OldClientResponse - { - Ignore, - Warn, - Annoy, - LenientKick, - Kick - } - } } diff --git a/Projects/UOContent/Misc/CrashGuard.cs b/Projects/UOContent/Misc/CrashGuard.cs index 7cd43a006..0ac3b060d 100644 --- a/Projects/UOContent/Misc/CrashGuard.cs +++ b/Projects/UOContent/Misc/CrashGuard.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Diagnostics; using System.IO; using Server.Accounting; @@ -7,240 +6,240 @@ using Server.Network; namespace Server.Misc { - public static class CrashGuard - { - private static readonly bool Enabled = true; - private static readonly bool SaveBackup = true; - private static readonly bool RestartServer = true; - private static readonly bool GenerateReport = true; - - public static void Initialize() + public static class CrashGuard { - if (Enabled) // If enabled, register our crash event handler - EventSink.ServerCrashed += CrashGuard_OnCrash; - } + private static readonly bool Enabled = true; + private static readonly bool SaveBackup = true; + private static readonly bool RestartServer = true; + private static readonly bool GenerateReport = true; - public static void CrashGuard_OnCrash(ServerCrashedEventArgs e) - { - if (GenerateReport) - GenerateCrashReport(e); - - World.WaitForWriteCompletion(); - - if (SaveBackup) - Backup(); - - /*if (Core.Service) - e.Close = true; - else */ - if (RestartServer) - Restart(e); - } - - private static void SendEmail(string filePath) - { - Console.Write("Crash: Sending email..."); - - Email.SendCrashEmail(filePath); - } - - private static string GetRoot() - { - try - { - return Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]); - } - catch - { - return ""; - } - } - - private static string Combine(string path1, string path2) => path1.Length == 0 ? path2 : Path.Combine(path1, path2); - - private static void Restart(ServerCrashedEventArgs e) - { - string root = GetRoot(); - - Console.Write("Crash: Restarting..."); - - try - { - Process.Start(Core.ExePath, Core.Arguments); - Console.WriteLine("done"); - - e.Close = true; - } - catch - { - Console.WriteLine("failed"); - } - } - - private static void CreateDirectory(string path) - { - if (!Directory.Exists(path)) - Directory.CreateDirectory(path); - } - - private static void CreateDirectory(string path1, string path2) - { - CreateDirectory(Combine(path1, path2)); - } - - private static void CopyFile(string rootOrigin, string rootBackup, string path) - { - string originPath = Combine(rootOrigin, path); - string backupPath = Combine(rootBackup, path); - - try - { - if (File.Exists(originPath)) - File.Copy(originPath, backupPath); - } - catch - { - // ignored - } - } - - private static void Backup() - { - Console.Write("Crash: Backing up..."); - - try - { - string timeStamp = GetTimeStamp(); - - string root = GetRoot(); - string rootBackup = Combine(root, $"Backups/Crashed/{timeStamp}/"); - string rootOrigin = Combine(root, "Saves/"); - - // Create new directories - CreateDirectory(rootBackup); - CreateDirectory(rootBackup, "Accounts/"); - CreateDirectory(rootBackup, "Items/"); - CreateDirectory(rootBackup, "Mobiles/"); - CreateDirectory(rootBackup, "Guilds/"); - CreateDirectory(rootBackup, "Regions/"); - - // Copy files - CopyFile(rootOrigin, rootBackup, "Accounts/Accounts.xml"); - - CopyFile(rootOrigin, rootBackup, "Items/Items.bin"); - CopyFile(rootOrigin, rootBackup, "Items/Items.idx"); - CopyFile(rootOrigin, rootBackup, "Items/Items.tdb"); - - CopyFile(rootOrigin, rootBackup, "Mobiles/Mobiles.bin"); - CopyFile(rootOrigin, rootBackup, "Mobiles/Mobiles.idx"); - CopyFile(rootOrigin, rootBackup, "Mobiles/Mobiles.tdb"); - - CopyFile(rootOrigin, rootBackup, "Guilds/Guilds.bin"); - CopyFile(rootOrigin, rootBackup, "Guilds/Guilds.idx"); - - CopyFile(rootOrigin, rootBackup, "Regions/Regions.bin"); - CopyFile(rootOrigin, rootBackup, "Regions/Regions.idx"); - - Console.WriteLine("done"); - } - catch - { - Console.WriteLine("failed"); - } - } - - private static void GenerateCrashReport(ServerCrashedEventArgs e) - { - Console.Write("Crash: Generating report..."); - - try - { - string timeStamp = GetTimeStamp(); - string fileName = $"Crash {timeStamp}.log"; - - string root = GetRoot(); - string filePath = Combine(root, fileName); - - using (StreamWriter op = new StreamWriter(filePath)) + public static void Initialize() { - Version ver = Core.Assembly.GetName().Version ?? new Version("0.0.0.0"); - - op.WriteLine("Server Crash Report"); - op.WriteLine("==================="); - op.WriteLine(); - op.WriteLine($"ModernUO Version {ver.Major}.{ver.Minor}, Build {ver.Build}.{ver.Revision}"); - op.WriteLine("Operating System: {0}", Environment.OSVersion); - op.WriteLine(".NET Framework: {0}", Environment.Version); - op.WriteLine("Time: {0}", DateTime.UtcNow); - - try - { - op.WriteLine("Mobiles: {0}", World.Mobiles.Count); - } - catch - { - // ignored - } - - try - { - op.WriteLine("Items: {0}", World.Items.Count); - } - catch - { - // ignored - } - - op.WriteLine("Exception:"); - op.WriteLine(e.Exception); - op.WriteLine(); - - op.WriteLine("Clients:"); - - try - { - List states = TcpServer.Instances; - - op.WriteLine("- Count: {0}", states.Count); - - for (int i = 0; i < states.Count; ++i) - { - NetState state = states[i]; - - op.Write("+ {0}:", state); - - if (state.Account is Account a) - op.Write(" (account = {0})", a.Username); - - Mobile m = state.Mobile; - - if (m != null) - op.Write(" (mobile = 0x{0:X} '{1}')", m.Serial.Value, m.Name); - - op.WriteLine(); - } - } - catch - { - op.WriteLine("- Failed"); - } + if (Enabled) // If enabled, register our crash event handler + EventSink.ServerCrashed += CrashGuard_OnCrash; } - Console.WriteLine("done"); + public static void CrashGuard_OnCrash(ServerCrashedEventArgs e) + { + if (GenerateReport) + GenerateCrashReport(e); - SendEmail(filePath); - } - catch - { - Console.WriteLine("failed"); - } + World.WaitForWriteCompletion(); + + if (SaveBackup) + Backup(); + + /*if (Core.Service) + e.Close = true; + else */ + if (RestartServer) + Restart(e); + } + + private static void SendEmail(string filePath) + { + Console.Write("Crash: Sending email..."); + + Email.SendCrashEmail(filePath); + } + + private static string GetRoot() + { + try + { + return Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]); + } + catch + { + return ""; + } + } + + private static string Combine(string path1, string path2) => path1.Length == 0 ? path2 : Path.Combine(path1, path2); + + private static void Restart(ServerCrashedEventArgs e) + { + var root = GetRoot(); + + Console.Write("Crash: Restarting..."); + + try + { + Process.Start(Core.ExePath, Core.Arguments); + Console.WriteLine("done"); + + e.Close = true; + } + catch + { + Console.WriteLine("failed"); + } + } + + private static void CreateDirectory(string path) + { + if (!Directory.Exists(path)) + Directory.CreateDirectory(path); + } + + private static void CreateDirectory(string path1, string path2) + { + CreateDirectory(Combine(path1, path2)); + } + + private static void CopyFile(string rootOrigin, string rootBackup, string path) + { + var originPath = Combine(rootOrigin, path); + var backupPath = Combine(rootBackup, path); + + try + { + if (File.Exists(originPath)) + File.Copy(originPath, backupPath); + } + catch + { + // ignored + } + } + + private static void Backup() + { + Console.Write("Crash: Backing up..."); + + try + { + var timeStamp = GetTimeStamp(); + + var root = GetRoot(); + var rootBackup = Combine(root, $"Backups/Crashed/{timeStamp}/"); + var rootOrigin = Combine(root, "Saves/"); + + // Create new directories + CreateDirectory(rootBackup); + CreateDirectory(rootBackup, "Accounts/"); + CreateDirectory(rootBackup, "Items/"); + CreateDirectory(rootBackup, "Mobiles/"); + CreateDirectory(rootBackup, "Guilds/"); + CreateDirectory(rootBackup, "Regions/"); + + // Copy files + CopyFile(rootOrigin, rootBackup, "Accounts/Accounts.xml"); + + CopyFile(rootOrigin, rootBackup, "Items/Items.bin"); + CopyFile(rootOrigin, rootBackup, "Items/Items.idx"); + CopyFile(rootOrigin, rootBackup, "Items/Items.tdb"); + + CopyFile(rootOrigin, rootBackup, "Mobiles/Mobiles.bin"); + CopyFile(rootOrigin, rootBackup, "Mobiles/Mobiles.idx"); + CopyFile(rootOrigin, rootBackup, "Mobiles/Mobiles.tdb"); + + CopyFile(rootOrigin, rootBackup, "Guilds/Guilds.bin"); + CopyFile(rootOrigin, rootBackup, "Guilds/Guilds.idx"); + + CopyFile(rootOrigin, rootBackup, "Regions/Regions.bin"); + CopyFile(rootOrigin, rootBackup, "Regions/Regions.idx"); + + Console.WriteLine("done"); + } + catch + { + Console.WriteLine("failed"); + } + } + + private static void GenerateCrashReport(ServerCrashedEventArgs e) + { + Console.Write("Crash: Generating report..."); + + try + { + var timeStamp = GetTimeStamp(); + var fileName = $"Crash {timeStamp}.log"; + + var root = GetRoot(); + var filePath = Combine(root, fileName); + + using (var op = new StreamWriter(filePath)) + { + var ver = Core.Assembly.GetName().Version ?? new Version("0.0.0.0"); + + op.WriteLine("Server Crash Report"); + op.WriteLine("==================="); + op.WriteLine(); + op.WriteLine($"ModernUO Version {ver.Major}.{ver.Minor}, Build {ver.Build}.{ver.Revision}"); + op.WriteLine("Operating System: {0}", Environment.OSVersion); + op.WriteLine(".NET Framework: {0}", Environment.Version); + op.WriteLine("Time: {0}", DateTime.UtcNow); + + try + { + op.WriteLine("Mobiles: {0}", World.Mobiles.Count); + } + catch + { + // ignored + } + + try + { + op.WriteLine("Items: {0}", World.Items.Count); + } + catch + { + // ignored + } + + op.WriteLine("Exception:"); + op.WriteLine(e.Exception); + op.WriteLine(); + + op.WriteLine("Clients:"); + + try + { + var states = TcpServer.Instances; + + op.WriteLine("- Count: {0}", states.Count); + + for (var i = 0; i < states.Count; ++i) + { + var state = states[i]; + + op.Write("+ {0}:", state); + + if (state.Account is Account a) + op.Write(" (account = {0})", a.Username); + + var m = state.Mobile; + + if (m != null) + op.Write(" (mobile = 0x{0:X} '{1}')", m.Serial.Value, m.Name); + + op.WriteLine(); + } + } + catch + { + op.WriteLine("- Failed"); + } + } + + Console.WriteLine("done"); + + SendEmail(filePath); + } + catch + { + Console.WriteLine("failed"); + } + } + + private static string GetTimeStamp() + { + var now = DateTime.UtcNow; + + return $"{now.Day}-{now.Month}-{now.Year}-{now.Hour}-{now.Minute}-{now.Second}"; + } } - - private static string GetTimeStamp() - { - DateTime now = DateTime.UtcNow; - - return $"{now.Day}-{now.Month}-{now.Year}-{now.Hour}-{now.Minute}-{now.Second}"; - } - } } diff --git a/Projects/UOContent/Misc/DispellableAttribute.cs b/Projects/UOContent/Misc/DispellableAttribute.cs index d818f7e27..861aebb07 100644 --- a/Projects/UOContent/Misc/DispellableAttribute.cs +++ b/Projects/UOContent/Misc/DispellableAttribute.cs @@ -2,8 +2,8 @@ using System; namespace Server.Misc { - [AttributeUsage(AttributeTargets.Class)] - public class DispellableAttribute : Attribute - { - } -} \ No newline at end of file + [AttributeUsage(AttributeTargets.Class)] + public class DispellableAttribute : Attribute + { + } +} diff --git a/Projects/UOContent/Misc/DispellableFieldAttribute.cs b/Projects/UOContent/Misc/DispellableFieldAttribute.cs index 069292f4a..b3825b748 100644 --- a/Projects/UOContent/Misc/DispellableFieldAttribute.cs +++ b/Projects/UOContent/Misc/DispellableFieldAttribute.cs @@ -2,8 +2,8 @@ using System; namespace Server.Misc { - [AttributeUsage(AttributeTargets.Class)] - public class DispellableFieldAttribute : Attribute - { - } -} \ No newline at end of file + [AttributeUsage(AttributeTargets.Class)] + public class DispellableFieldAttribute : Attribute + { + } +} diff --git a/Projects/UOContent/Misc/DoorGenerator.cs b/Projects/UOContent/Misc/DoorGenerator.cs index f9b36e8a7..2882ed7d3 100644 --- a/Projects/UOContent/Misc/DoorGenerator.cs +++ b/Projects/UOContent/Misc/DoorGenerator.cs @@ -3,542 +3,549 @@ using Server.Network; namespace Server { - public class DoorGenerator - { - private static readonly Rectangle2D[] m_BritRegions = + public class DoorGenerator { - new Rectangle2D(new Point2D(250, 750), new Point2D(775, 1330)), - new Rectangle2D(new Point2D(525, 2095), new Point2D(925, 2430)), - new Rectangle2D(new Point2D(1025, 2155), new Point2D(1265, 2310)), - new Rectangle2D(new Point2D(1635, 2430), new Point2D(1705, 2508)), - new Rectangle2D(new Point2D(1775, 2605), new Point2D(2165, 2975)), - new Rectangle2D(new Point2D(1055, 3520), new Point2D(1570, 4075)), - new Rectangle2D(new Point2D(2860, 3310), new Point2D(3120, 3630)), - new Rectangle2D(new Point2D(2470, 1855), new Point2D(3950, 3045)), - new Rectangle2D(new Point2D(3425, 990), new Point2D(3900, 1455)), - new Rectangle2D(new Point2D(4175, 735), new Point2D(4840, 1600)), - new Rectangle2D(new Point2D(2375, 330), new Point2D(3100, 1045)), - new Rectangle2D(new Point2D(2100, 1090), new Point2D(2310, 1450)), - new Rectangle2D(new Point2D(1495, 1400), new Point2D(1550, 1475)), - new Rectangle2D(new Point2D(1085, 1520), new Point2D(1415, 1910)), - new Rectangle2D(new Point2D(1410, 1500), new Point2D(1745, 1795)), - new Rectangle2D(new Point2D(5120, 2300), new Point2D(6143, 4095)) - }; - - private static readonly Rectangle2D[] m_IlshRegions = - { - new Rectangle2D(new Point2D(0, 0), new Point2D(288 * 8, 200 * 8)) - }; - - private static readonly Rectangle2D[] m_MalasRegions = - { - new Rectangle2D(new Point2D(0, 0), new Point2D(320 * 8, 256 * 8)) - }; - - private static readonly int[] m_SouthFrames = - { - 0x0006, - 0x0008, - 0x000B, - 0x001A, - 0x001B, - 0x001F, - 0x0038, - 0x0057, - 0x0059, - 0x005B, - 0x005D, - 0x0080, - 0x0081, - 0x0082, - 0x0084, - 0x0090, - 0x0091, - 0x0094, - 0x0096, - 0x0099, - 0x00A6, - 0x00A7, - 0x00AA, - 0x00AE, - 0x00B0, - 0x00B3, - 0x00C7, - 0x00C9, - 0x00F8, - 0x00FA, - 0x00FD, - 0x00FE, - 0x0100, - 0x0103, - 0x0104, - 0x0106, - 0x0109, - 0x0127, - 0x0129, - 0x012B, - 0x012D, - 0x012F, - 0x0131, - 0x0132, - 0x0134, - 0x0135, - 0x0137, - 0x0139, - 0x013B, - 0x014C, - 0x014E, - 0x014F, - 0x0151, - 0x0153, - 0x0155, - 0x0157, - 0x0158, - 0x015A, - 0x015D, - 0x015E, - 0x015F, - 0x0162, - 0x01CF, - 0x01D1, - 0x01D4, - 0x01FF, - 0x0204, - 0x0206, - 0x0208, - 0x020A - }; - - private static readonly int[] m_NorthFrames = - { - 0x0006, - 0x0008, - 0x000D, - 0x001A, - 0x001B, - 0x0020, - 0x003A, - 0x0057, - 0x0059, - 0x005B, - 0x005D, - 0x0080, - 0x0081, - 0x0082, - 0x0084, - 0x0090, - 0x0091, - 0x0094, - 0x0096, - 0x0099, - 0x00A6, - 0x00A7, - 0x00AC, - 0x00AE, - 0x00B0, - 0x00C7, - 0x00C9, - 0x00F8, - 0x00FA, - 0x00FD, - 0x00FE, - 0x0100, - 0x0103, - 0x0104, - 0x0106, - 0x0109, - 0x0127, - 0x0129, - 0x012B, - 0x012D, - 0x012F, - 0x0131, - 0x0132, - 0x0134, - 0x0135, - 0x0137, - 0x0139, - 0x013B, - 0x014C, - 0x014E, - 0x014F, - 0x0151, - 0x0153, - 0x0155, - 0x0157, - 0x0158, - 0x015A, - 0x015D, - 0x015E, - 0x015F, - 0x0162, - 0x01CF, - 0x01D1, - 0x01D4, - 0x01FF, - 0x0201, - 0x0204, - 0x0208, - 0x020A - }; - - private static readonly int[] m_EastFrames = - { - 0x0007, - 0x000A, - 0x001A, - 0x001C, - 0x001E, - 0x0037, - 0x0058, - 0x0059, - 0x005C, - 0x005E, - 0x0080, - 0x0081, - 0x0082, - 0x0084, - 0x0090, - 0x0092, - 0x0095, - 0x0097, - 0x0098, - 0x00A6, - 0x00A8, - 0x00AB, - 0x00AE, - 0x00AF, - 0x00B2, - 0x00C7, - 0x00C8, - 0x00EA, - 0x00F8, - 0x00F9, - 0x00FC, - 0x00FE, - 0x00FF, - 0x0102, - 0x0104, - 0x0105, - 0x0108, - 0x0127, - 0x0128, - 0x012B, - 0x012C, - 0x012E, - 0x0130, - 0x0132, - 0x0133, - 0x0135, - 0x0136, - 0x0138, - 0x013A, - 0x014C, - 0x014D, - 0x014F, - 0x0150, - 0x0152, - 0x0154, - 0x0156, - 0x0158, - 0x0159, - 0x015C, - 0x015E, - 0x0160, - 0x0163, - 0x01CF, - 0x01D0, - 0x01D3, - 0x01FF, - 0x0203, - 0x0205, - 0x0207, - 0x0209 - }; - - private static readonly int[] m_WestFrames = - { - 0x0007, - 0x000C, - 0x001A, - 0x001C, - 0x0021, - 0x0039, - 0x0058, - 0x0059, - 0x005C, - 0x005E, - 0x0080, - 0x0081, - 0x0082, - 0x0084, - 0x0090, - 0x0092, - 0x0095, - 0x0097, - 0x0098, - 0x00A6, - 0x00A8, - 0x00AD, - 0x00AE, - 0x00AF, - 0x00B5, - 0x00C7, - 0x00C8, - 0x00EA, - 0x00F8, - 0x00F9, - 0x00FC, - 0x00FE, - 0x00FF, - 0x0102, - 0x0104, - 0x0105, - 0x0108, - 0x0127, - 0x0128, - 0x012C, - 0x012E, - 0x0130, - 0x0132, - 0x0133, - 0x0135, - 0x0136, - 0x0138, - 0x013A, - 0x014C, - 0x014D, - 0x014F, - 0x0150, - 0x0152, - 0x0154, - 0x0156, - 0x0158, - 0x0159, - 0x015C, - 0x015E, - 0x0160, - 0x0163, - 0x01CF, - 0x01D0, - 0x01D3, - 0x01FF, - 0x0200, - 0x0203, - 0x0207, - 0x0209 - }; - - private static Map m_Map; - private static int m_Count; - - public static void Initialize() - { - CommandSystem.Register("DoorGen", AccessLevel.Administrator, DoorGen_OnCommand); - } - - [Usage("DoorGen")] - [Description("Generates doors by analyzing the map. Slow.")] - public static void DoorGen_OnCommand(CommandEventArgs e) - { - Generate(); - } - - public static void Generate() - { - World.Broadcast(0x35, true, "Generating doors, please wait."); - - NetState.Pause(); - - m_Map = Map.Trammel; - m_Count = 0; - - for (int i = 0; i < m_BritRegions.Length; ++i) - Generate(m_BritRegions[i]); - - int trammelCount = m_Count; - - m_Map = Map.Felucca; - m_Count = 0; - - for (int i = 0; i < m_BritRegions.Length; ++i) - Generate(m_BritRegions[i]); - - int feluccaCount = m_Count; - - m_Map = Map.Ilshenar; - m_Count = 0; - - for (int i = 0; i < m_IlshRegions.Length; ++i) - Generate(m_IlshRegions[i]); - - int ilshenarCount = m_Count; - - m_Map = Map.Malas; - m_Count = 0; - - for (int i = 0; i < m_MalasRegions.Length; ++i) - Generate(m_MalasRegions[i]); - - int malasCount = m_Count; - - NetState.Resume(); - - World.Broadcast(0x35, true, "Door generation complete. Trammel: {0}; Felucca: {1}; Ilshenar: {2}; Malas: {3};", - trammelCount, feluccaCount, ilshenarCount, malasCount); - } - - public static bool IsFrame(int id, int[] list) - { - if (id > list[^1]) - return false; - - for (int i = 0; i < list.Length; ++i) - { - int delta = id - list[i]; - - if (delta < 0) - return false; - if (delta == 0) - return true; - } - - return false; - } - - public static bool IsNorthFrame(int id) => IsFrame(id, m_NorthFrames); - - public static bool IsSouthFrame(int id) => IsFrame(id, m_SouthFrames); - - public static bool IsWestFrame(int id) => IsFrame(id, m_WestFrames); - - public static bool IsEastFrame(int id) => IsFrame(id, m_EastFrames); - - public static bool IsEastFrame(int x, int y, int z) - { - StaticTile[] tiles = m_Map.Tiles.GetStaticTiles(x, y); - - for (int i = 0; i < tiles.Length; ++i) - { - StaticTile tile = tiles[i]; - - if (tile.Z == z && IsEastFrame(tile.ID)) - return true; - } - - return false; - } - - public static bool IsSouthFrame(int x, int y, int z) - { - StaticTile[] tiles = m_Map.Tiles.GetStaticTiles(x, y); - - for (int i = 0; i < tiles.Length; ++i) - { - StaticTile tile = tiles[i]; - - if (tile.Z == z && IsSouthFrame(tile.ID)) - return true; - } - - return false; - } - - public static BaseDoor AddDoor(int x, int y, int z, DoorFacing facing) - { - int doorZ = z; - int doorTop = doorZ + 20; - - if (!m_Map.CanFit(x, y, z, 16, false, false)) - return null; - - if (y == 1743 && x >= 1343 && x <= 1344) - return null; - - if (y == 1679 && x >= 1392 && x <= 1393) - return null; - - if (x == 1320 && y >= 1618 && y <= 1640) - return null; - - if (x == 1383 && y >= 1642 && y <= 1643) - return null; - - BaseDoor door = new DarkWoodDoor(facing); - door.MoveToWorld(new Point3D(x, y, z), m_Map); - - ++m_Count; - - return door; - } - - public static void Generate(Rectangle2D region) - { - for (int rx = 0; rx < region.Width; ++rx) - for (int ry = 0; ry < region.Height; ++ry) + private static readonly Rectangle2D[] m_BritRegions = { - int vx = rx + region.X; - int vy = ry + region.Y; + new Rectangle2D(new Point2D(250, 750), new Point2D(775, 1330)), + new Rectangle2D(new Point2D(525, 2095), new Point2D(925, 2430)), + new Rectangle2D(new Point2D(1025, 2155), new Point2D(1265, 2310)), + new Rectangle2D(new Point2D(1635, 2430), new Point2D(1705, 2508)), + new Rectangle2D(new Point2D(1775, 2605), new Point2D(2165, 2975)), + new Rectangle2D(new Point2D(1055, 3520), new Point2D(1570, 4075)), + new Rectangle2D(new Point2D(2860, 3310), new Point2D(3120, 3630)), + new Rectangle2D(new Point2D(2470, 1855), new Point2D(3950, 3045)), + new Rectangle2D(new Point2D(3425, 990), new Point2D(3900, 1455)), + new Rectangle2D(new Point2D(4175, 735), new Point2D(4840, 1600)), + new Rectangle2D(new Point2D(2375, 330), new Point2D(3100, 1045)), + new Rectangle2D(new Point2D(2100, 1090), new Point2D(2310, 1450)), + new Rectangle2D(new Point2D(1495, 1400), new Point2D(1550, 1475)), + new Rectangle2D(new Point2D(1085, 1520), new Point2D(1415, 1910)), + new Rectangle2D(new Point2D(1410, 1500), new Point2D(1745, 1795)), + new Rectangle2D(new Point2D(5120, 2300), new Point2D(6143, 4095)) + }; - StaticTile[] tiles = m_Map.Tiles.GetStaticTiles(vx, vy); + private static readonly Rectangle2D[] m_IlshRegions = + { + new Rectangle2D(new Point2D(0, 0), new Point2D(288 * 8, 200 * 8)) + }; - for (int i = 0; i < tiles.Length; ++i) - { - StaticTile tile = tiles[i]; + private static readonly Rectangle2D[] m_MalasRegions = + { + new Rectangle2D(new Point2D(0, 0), new Point2D(320 * 8, 256 * 8)) + }; - int id = tile.ID; - int z = tile.Z; + private static readonly int[] m_SouthFrames = + { + 0x0006, + 0x0008, + 0x000B, + 0x001A, + 0x001B, + 0x001F, + 0x0038, + 0x0057, + 0x0059, + 0x005B, + 0x005D, + 0x0080, + 0x0081, + 0x0082, + 0x0084, + 0x0090, + 0x0091, + 0x0094, + 0x0096, + 0x0099, + 0x00A6, + 0x00A7, + 0x00AA, + 0x00AE, + 0x00B0, + 0x00B3, + 0x00C7, + 0x00C9, + 0x00F8, + 0x00FA, + 0x00FD, + 0x00FE, + 0x0100, + 0x0103, + 0x0104, + 0x0106, + 0x0109, + 0x0127, + 0x0129, + 0x012B, + 0x012D, + 0x012F, + 0x0131, + 0x0132, + 0x0134, + 0x0135, + 0x0137, + 0x0139, + 0x013B, + 0x014C, + 0x014E, + 0x014F, + 0x0151, + 0x0153, + 0x0155, + 0x0157, + 0x0158, + 0x015A, + 0x015D, + 0x015E, + 0x015F, + 0x0162, + 0x01CF, + 0x01D1, + 0x01D4, + 0x01FF, + 0x0204, + 0x0206, + 0x0208, + 0x020A + }; - if (IsWestFrame(id)) + private static readonly int[] m_NorthFrames = + { + 0x0006, + 0x0008, + 0x000D, + 0x001A, + 0x001B, + 0x0020, + 0x003A, + 0x0057, + 0x0059, + 0x005B, + 0x005D, + 0x0080, + 0x0081, + 0x0082, + 0x0084, + 0x0090, + 0x0091, + 0x0094, + 0x0096, + 0x0099, + 0x00A6, + 0x00A7, + 0x00AC, + 0x00AE, + 0x00B0, + 0x00C7, + 0x00C9, + 0x00F8, + 0x00FA, + 0x00FD, + 0x00FE, + 0x0100, + 0x0103, + 0x0104, + 0x0106, + 0x0109, + 0x0127, + 0x0129, + 0x012B, + 0x012D, + 0x012F, + 0x0131, + 0x0132, + 0x0134, + 0x0135, + 0x0137, + 0x0139, + 0x013B, + 0x014C, + 0x014E, + 0x014F, + 0x0151, + 0x0153, + 0x0155, + 0x0157, + 0x0158, + 0x015A, + 0x015D, + 0x015E, + 0x015F, + 0x0162, + 0x01CF, + 0x01D1, + 0x01D4, + 0x01FF, + 0x0201, + 0x0204, + 0x0208, + 0x020A + }; + + private static readonly int[] m_EastFrames = + { + 0x0007, + 0x000A, + 0x001A, + 0x001C, + 0x001E, + 0x0037, + 0x0058, + 0x0059, + 0x005C, + 0x005E, + 0x0080, + 0x0081, + 0x0082, + 0x0084, + 0x0090, + 0x0092, + 0x0095, + 0x0097, + 0x0098, + 0x00A6, + 0x00A8, + 0x00AB, + 0x00AE, + 0x00AF, + 0x00B2, + 0x00C7, + 0x00C8, + 0x00EA, + 0x00F8, + 0x00F9, + 0x00FC, + 0x00FE, + 0x00FF, + 0x0102, + 0x0104, + 0x0105, + 0x0108, + 0x0127, + 0x0128, + 0x012B, + 0x012C, + 0x012E, + 0x0130, + 0x0132, + 0x0133, + 0x0135, + 0x0136, + 0x0138, + 0x013A, + 0x014C, + 0x014D, + 0x014F, + 0x0150, + 0x0152, + 0x0154, + 0x0156, + 0x0158, + 0x0159, + 0x015C, + 0x015E, + 0x0160, + 0x0163, + 0x01CF, + 0x01D0, + 0x01D3, + 0x01FF, + 0x0203, + 0x0205, + 0x0207, + 0x0209 + }; + + private static readonly int[] m_WestFrames = + { + 0x0007, + 0x000C, + 0x001A, + 0x001C, + 0x0021, + 0x0039, + 0x0058, + 0x0059, + 0x005C, + 0x005E, + 0x0080, + 0x0081, + 0x0082, + 0x0084, + 0x0090, + 0x0092, + 0x0095, + 0x0097, + 0x0098, + 0x00A6, + 0x00A8, + 0x00AD, + 0x00AE, + 0x00AF, + 0x00B5, + 0x00C7, + 0x00C8, + 0x00EA, + 0x00F8, + 0x00F9, + 0x00FC, + 0x00FE, + 0x00FF, + 0x0102, + 0x0104, + 0x0105, + 0x0108, + 0x0127, + 0x0128, + 0x012C, + 0x012E, + 0x0130, + 0x0132, + 0x0133, + 0x0135, + 0x0136, + 0x0138, + 0x013A, + 0x014C, + 0x014D, + 0x014F, + 0x0150, + 0x0152, + 0x0154, + 0x0156, + 0x0158, + 0x0159, + 0x015C, + 0x015E, + 0x0160, + 0x0163, + 0x01CF, + 0x01D0, + 0x01D3, + 0x01FF, + 0x0200, + 0x0203, + 0x0207, + 0x0209 + }; + + private static Map m_Map; + private static int m_Count; + + public static void Initialize() + { + CommandSystem.Register("DoorGen", AccessLevel.Administrator, DoorGen_OnCommand); + } + + [Usage("DoorGen")] + [Description("Generates doors by analyzing the map. Slow.")] + public static void DoorGen_OnCommand(CommandEventArgs e) + { + Generate(); + } + + public static void Generate() + { + World.Broadcast(0x35, true, "Generating doors, please wait."); + + NetState.Pause(); + + m_Map = Map.Trammel; + m_Count = 0; + + for (var i = 0; i < m_BritRegions.Length; ++i) + Generate(m_BritRegions[i]); + + var trammelCount = m_Count; + + m_Map = Map.Felucca; + m_Count = 0; + + for (var i = 0; i < m_BritRegions.Length; ++i) + Generate(m_BritRegions[i]); + + var feluccaCount = m_Count; + + m_Map = Map.Ilshenar; + m_Count = 0; + + for (var i = 0; i < m_IlshRegions.Length; ++i) + Generate(m_IlshRegions[i]); + + var ilshenarCount = m_Count; + + m_Map = Map.Malas; + m_Count = 0; + + for (var i = 0; i < m_MalasRegions.Length; ++i) + Generate(m_MalasRegions[i]); + + var malasCount = m_Count; + + NetState.Resume(); + + World.Broadcast( + 0x35, + true, + "Door generation complete. Trammel: {0}; Felucca: {1}; Ilshenar: {2}; Malas: {3};", + trammelCount, + feluccaCount, + ilshenarCount, + malasCount + ); + } + + public static bool IsFrame(int id, int[] list) + { + if (id > list[^1]) + return false; + + for (var i = 0; i < list.Length; ++i) { - if (IsEastFrame(vx + 2, vy, z)) - { - AddDoor(vx + 1, vy, z, DoorFacing.WestCW); - } - else if (IsEastFrame(vx + 3, vy, z)) - { - BaseDoor first = AddDoor(vx + 1, vy, z, DoorFacing.WestCW); - BaseDoor second = AddDoor(vx + 2, vy, z, DoorFacing.EastCCW); + var delta = id - list[i]; - if (first != null && second != null) - { - first.Link = second; - second.Link = first; - } - else - { - first?.Delete(); - - second?.Delete(); - } - } + if (delta < 0) + return false; + if (delta == 0) + return true; } - else if (IsNorthFrame(id)) + + return false; + } + + public static bool IsNorthFrame(int id) => IsFrame(id, m_NorthFrames); + + public static bool IsSouthFrame(int id) => IsFrame(id, m_SouthFrames); + + public static bool IsWestFrame(int id) => IsFrame(id, m_WestFrames); + + public static bool IsEastFrame(int id) => IsFrame(id, m_EastFrames); + + public static bool IsEastFrame(int x, int y, int z) + { + var tiles = m_Map.Tiles.GetStaticTiles(x, y); + + for (var i = 0; i < tiles.Length; ++i) { - if (IsSouthFrame(vx, vy + 2, z)) - { - AddDoor(vx, vy + 1, z, DoorFacing.SouthCW); - } - else if (IsSouthFrame(vx, vy + 3, z)) - { - BaseDoor first = AddDoor(vx, vy + 1, z, DoorFacing.NorthCCW); - BaseDoor second = AddDoor(vx, vy + 2, z, DoorFacing.SouthCW); + var tile = tiles[i]; - if (first != null && second != null) - { - first.Link = second; - second.Link = first; - } - else - { - first?.Delete(); - - second?.Delete(); - } - } + if (tile.Z == z && IsEastFrame(tile.ID)) + return true; } - } + + return false; + } + + public static bool IsSouthFrame(int x, int y, int z) + { + var tiles = m_Map.Tiles.GetStaticTiles(x, y); + + for (var i = 0; i < tiles.Length; ++i) + { + var tile = tiles[i]; + + if (tile.Z == z && IsSouthFrame(tile.ID)) + return true; + } + + return false; + } + + public static BaseDoor AddDoor(int x, int y, int z, DoorFacing facing) + { + var doorZ = z; + var doorTop = doorZ + 20; + + if (!m_Map.CanFit(x, y, z, 16, false, false)) + return null; + + if (y == 1743 && x >= 1343 && x <= 1344) + return null; + + if (y == 1679 && x >= 1392 && x <= 1393) + return null; + + if (x == 1320 && y >= 1618 && y <= 1640) + return null; + + if (x == 1383 && y >= 1642 && y <= 1643) + return null; + + BaseDoor door = new DarkWoodDoor(facing); + door.MoveToWorld(new Point3D(x, y, z), m_Map); + + ++m_Count; + + return door; + } + + public static void Generate(Rectangle2D region) + { + for (var rx = 0; rx < region.Width; ++rx) + for (var ry = 0; ry < region.Height; ++ry) + { + var vx = rx + region.X; + var vy = ry + region.Y; + + var tiles = m_Map.Tiles.GetStaticTiles(vx, vy); + + for (var i = 0; i < tiles.Length; ++i) + { + var tile = tiles[i]; + + var id = tile.ID; + var z = tile.Z; + + if (IsWestFrame(id)) + { + if (IsEastFrame(vx + 2, vy, z)) + { + AddDoor(vx + 1, vy, z, DoorFacing.WestCW); + } + else if (IsEastFrame(vx + 3, vy, z)) + { + var first = AddDoor(vx + 1, vy, z, DoorFacing.WestCW); + var second = AddDoor(vx + 2, vy, z, DoorFacing.EastCCW); + + if (first != null && second != null) + { + first.Link = second; + second.Link = first; + } + else + { + first?.Delete(); + + second?.Delete(); + } + } + } + else if (IsNorthFrame(id)) + { + if (IsSouthFrame(vx, vy + 2, z)) + { + AddDoor(vx, vy + 1, z, DoorFacing.SouthCW); + } + else if (IsSouthFrame(vx, vy + 3, z)) + { + var first = AddDoor(vx, vy + 1, z, DoorFacing.NorthCCW); + var second = AddDoor(vx, vy + 2, z, DoorFacing.SouthCW); + + if (first != null && second != null) + { + first.Link = second; + second.Link = first; + } + else + { + first?.Delete(); + + second?.Delete(); + } + } + } + } + } } } - } } diff --git a/Projects/UOContent/Misc/Email.cs b/Projects/UOContent/Misc/Email.cs index 10f14c31b..b33562e5b 100644 --- a/Projects/UOContent/Misc/Email.cs +++ b/Projects/UOContent/Misc/Email.cs @@ -9,28 +9,29 @@ using Server.Engines.Help; namespace Server.Misc { - public static class Email - { - /// - /// Sends Queue-Page request using Email - /// - /// - /// - public static void SendQueueEmail(PageEntry entry, string pageType) + public static class Email { - if (!EmailConfiguration.EmailEnabled) return; + /// + /// Sends Queue-Page request using Email + /// + /// + /// + public static void SendQueueEmail(PageEntry entry, string pageType) + { + if (!EmailConfiguration.EmailEnabled) return; - Mobile sender = entry.Sender; - DateTime time = DateTime.UtcNow; + var sender = entry.Sender; + var time = DateTime.UtcNow; - var message = new MimeMessage(); - message.From.Add(EmailConfiguration.FromAddress); - message.To.Add(EmailConfiguration.SpeechLogPageAddress); - message.Subject = "ModernUO Speech Log Page Forwarding"; + var message = new MimeMessage(); + message.From.Add(EmailConfiguration.FromAddress); + message.To.Add(EmailConfiguration.SpeechLogPageAddress); + message.Subject = "ModernUO Speech Log Page Forwarding"; - using (StringWriter writer = new StringWriter()) - { - writer.WriteLine(@$" + using (var writer = new StringWriter()) + { + writer.WriteLine( + @$" ModernUO Speech Log Page - {pageType} From: '{sender.RawName}', Account: '{(sender.Account is Account accSend ? accSend.Username : " ??? ")}' @@ -43,85 +44,92 @@ namespace Server.Misc Speech Log ========== - "); + " + ); - foreach (SpeechLogEntry logEntry in entry.SpeechLog) - { - Mobile from = logEntry.From; - string fromName = from.RawName; - string fromAccount = from.Account is Account accFrom ? accFrom.Username : "???"; - DateTime created = logEntry.Created; - string speech = logEntry.Speech; - writer.WriteLine(@$"{created.Hour}:{created.Minute:00}:{created.Second:00} - {fromName} ({fromAccount}): '{speech}'"); + foreach (var logEntry in entry.SpeechLog) + { + var from = logEntry.From; + var fromName = from.RawName; + var fromAccount = from.Account is Account accFrom ? accFrom.Username : "???"; + var created = logEntry.Created; + var speech = logEntry.Speech; + writer.WriteLine( + @$"{created.Hour}:{created.Minute:00}:{created.Second:00} - {fromName} ({fromAccount}): '{speech}'" + ); + } + + message.Body = new BodyBuilder + { + TextBody = writer.ToString(), + HtmlBody = null + }.ToMessageBody(); + } + + SendAsync(message); } - message.Body = new BodyBuilder + /// + /// Sends crash email + /// + /// + public static void SendCrashEmail(string filePath) { - TextBody = writer.ToString(), - HtmlBody = null - }.ToMessageBody(); - } - SendAsync(message); - } + if (EmailConfiguration.EmailEnabled) return; - /// - /// Sends crash email - /// - /// - public static void SendCrashEmail(string filePath) - { - if (EmailConfiguration.EmailEnabled) return; - - var message = new MimeMessage(); - message.From.Add(EmailConfiguration.FromAddress); - message.To.Add(EmailConfiguration.CrashAddress); - message.Subject = "Automated ModernUO Crash Report"; - var builder = new BodyBuilder - { - TextBody = "Automated ModernUO Crash Report. See attachment for details.", - HtmlBody = null - }; - builder.Attachments.Add(filePath); - message.Body = builder.ToMessageBody(); - } - - /// - /// Sends emails async - /// - /// - private static async void SendAsync(MimeMessage message) - { - if (!EmailConfiguration.EmailEnabled) return; - - DateTime now = DateTime.UtcNow; - string messageID = $"<{now:yyyyMMdd}.{now:HHmmssff}@{EmailConfiguration.EmailServer}>"; - message.Headers.Add("Message-ID", messageID); - message.From.Add(EmailConfiguration.FromAddress); - - int delay = EmailConfiguration.EmailSendRetryDelay; - - for (int i = 0; i < EmailConfiguration.EmailSendRetryCount; i++) - try - { - using SmtpClient client = new SmtpClient(); - await client.ConnectAsync(EmailConfiguration.EmailServer, EmailConfiguration.EmailPort, true); - await client.AuthenticateAsync(EmailConfiguration.EmailServerUsername, EmailConfiguration.EmailServerPassword); - await client.SendAsync(message); - await client.DisconnectAsync(true); - return; + var message = new MimeMessage(); + message.From.Add(EmailConfiguration.FromAddress); + message.To.Add(EmailConfiguration.CrashAddress); + message.Subject = "Automated ModernUO Crash Report"; + var builder = new BodyBuilder + { + TextBody = "Automated ModernUO Crash Report. See attachment for details.", + HtmlBody = null + }; + builder.Attachments.Add(filePath); + message.Body = builder.ToMessageBody(); } - catch (Exception ex) + + /// + /// Sends emails async + /// + /// + private static async void SendAsync(MimeMessage message) { - if (i == 0) - { - Console.WriteLine(ex.Message); - Console.WriteLine(ex.StackTrace); - } + if (!EmailConfiguration.EmailEnabled) return; - delay *= delay; + var now = DateTime.UtcNow; + var messageID = $"<{now:yyyyMMdd}.{now:HHmmssff}@{EmailConfiguration.EmailServer}>"; + message.Headers.Add("Message-ID", messageID); + message.From.Add(EmailConfiguration.FromAddress); - await Task.Delay(delay * 1000); + var delay = EmailConfiguration.EmailSendRetryDelay; + + for (var i = 0; i < EmailConfiguration.EmailSendRetryCount; i++) + try + { + using var client = new SmtpClient(); + await client.ConnectAsync(EmailConfiguration.EmailServer, EmailConfiguration.EmailPort, true); + await client.AuthenticateAsync( + EmailConfiguration.EmailServerUsername, + EmailConfiguration.EmailServerPassword + ); + await client.SendAsync(message); + await client.DisconnectAsync(true); + return; + } + catch (Exception ex) + { + if (i == 0) + { + Console.WriteLine(ex.Message); + Console.WriteLine(ex.StackTrace); + } + + delay *= delay; + + await Task.Delay(delay * 1000); + } } } - } } diff --git a/Projects/UOContent/Misc/Emitter.cs b/Projects/UOContent/Misc/Emitter.cs index d7444a48d..65506af5c 100644 --- a/Projects/UOContent/Misc/Emitter.cs +++ b/Projects/UOContent/Misc/Emitter.cs @@ -5,658 +5,663 @@ using System.Reflection.Emit; namespace Server { - public class AssemblyEmitter - { - private string m_AssemblyName; - - private AppDomain m_AppDomain; - private readonly AssemblyBuilder m_AssemblyBuilder; - private readonly ModuleBuilder m_ModuleBuilder; - - public AssemblyEmitter(string assemblyName) + public class AssemblyEmitter { - m_AssemblyName = assemblyName; + private readonly AssemblyBuilder m_AssemblyBuilder; + private readonly ModuleBuilder m_ModuleBuilder; - m_AppDomain = AppDomain.CurrentDomain; + private AppDomain m_AppDomain; + private string m_AssemblyName; - m_AssemblyBuilder = AssemblyBuilder.DefineDynamicAssembly( - new AssemblyName(assemblyName), - AssemblyBuilderAccess.Run); - - m_ModuleBuilder = m_AssemblyBuilder.DefineDynamicModule(assemblyName); - } - - public TypeBuilder DefineType(string typeName, TypeAttributes attrs, Type parentType) => m_ModuleBuilder.DefineType(typeName, attrs, parentType); - } - - public class MethodEmitter - { - private Type[] m_ArgumentTypes; - - public TypeBuilder Type { get; } - - public ILGenerator Generator { get; private set; } - - private class CallInfo - { - public readonly Type type; - public readonly MethodInfo method; - - public int index; - public readonly ParameterInfo[] parms; - - public CallInfo(Type type, MethodInfo method) - { - this.type = type; - this.method = method; - - parms = method.GetParameters(); - } - } - - private readonly Stack m_Stack; - private readonly Stack m_Calls; - - private readonly Dictionary> m_Temps; - - public MethodBuilder Method { get; private set; } - - public MethodEmitter(TypeBuilder typeBuilder) - { - Type = typeBuilder; - - m_Temps = new Dictionary>(); - - m_Stack = new Stack(); - m_Calls = new Stack(); - } - - public void Define(string name, MethodAttributes attr, Type returnType, Type[] parms) - { - Method = Type.DefineMethod(name, attr, returnType, parms); - Generator = Method.GetILGenerator(); - - m_ArgumentTypes = parms; - } - - public LocalBuilder CreateLocal(Type localType) => Generator.DeclareLocal(localType); - - public LocalBuilder AcquireTemp(Type localType) - { - if (!m_Temps.TryGetValue(localType, out Queue list)) - m_Temps[localType] = list = new Queue(); - - return list.Count > 0 ? list.Dequeue() : CreateLocal(localType); - } - - public void ReleaseTemp(LocalBuilder local) - { - if (local.LocalType == null) - return; - - if (!m_Temps.TryGetValue(local.LocalType, out Queue list)) - m_Temps[local.LocalType] = list = new Queue(); - - list.Enqueue(local); - } - - public void Branch(Label label) - { - Generator.Emit(OpCodes.Br, label); - } - - public void BranchIfFalse(Label label) - { - Pop(typeof(object)); - - Generator.Emit(OpCodes.Brfalse, label); - } - - public void BranchIfTrue(Label label) - { - Pop(typeof(object)); - - Generator.Emit(OpCodes.Brtrue, label); - } - - public Label CreateLabel() => Generator.DefineLabel(); - - public void MarkLabel(Label label) - { - Generator.MarkLabel(label); - } - - public void Pop() - { - m_Stack.Pop(); - } - - public void Pop(Type expected) - { - if (expected == null) - throw new InvalidOperationException("Expected type cannot be null."); - - Type onStack = m_Stack.Pop(); - - if (expected == typeof(bool)) - expected = typeof(int); - - if (onStack == typeof(bool)) - onStack = typeof(int); - - if (!expected.IsAssignableFrom(onStack)) - throw new InvalidOperationException("Unexpected stack state."); - } - - public void Push(Type type) - { - m_Stack.Push(type); - } - - public void Return() - { - if (m_Stack.Count != (Method.ReturnType == typeof(void) ? 0 : 1)) - throw new InvalidOperationException("Stack return mismatch."); - - Generator.Emit(OpCodes.Ret); - } - - public void LoadNull() - { - LoadNull(typeof(object)); - } - - public void LoadNull(Type type) - { - Push(type); - - Generator.Emit(OpCodes.Ldnull); - } - - public void Load(string value) - { - Push(typeof(string)); - - if (value != null) - Generator.Emit(OpCodes.Ldstr, value); - else - Generator.Emit(OpCodes.Ldnull); - } - - public void Load(Enum value) - { - int toLoad = ((IConvertible)value).ToInt32(null); - Load(toLoad); - - Pop(); - Push(value.GetType()); - } - - public void Load(long value) - { - Push(typeof(long)); - - Generator.Emit(OpCodes.Ldc_I8, value); - } - - public void Load(float value) - { - Push(typeof(float)); - - Generator.Emit(OpCodes.Ldc_R4, value); - } - - public void Load(double value) - { - Push(typeof(double)); - - Generator.Emit(OpCodes.Ldc_R8, value); - } - - public void Load(char value) - { - Load((int)value); - - Pop(); - Push(typeof(char)); - } - - public void Load(bool value) - { - Push(typeof(bool)); - - if (value) - Generator.Emit(OpCodes.Ldc_I4_1); - else - Generator.Emit(OpCodes.Ldc_I4_0); - } - - public void Load(int value) - { - Push(typeof(int)); - - switch (value) - { - case -1: - Generator.Emit(OpCodes.Ldc_I4_M1); - break; - - case 0: - Generator.Emit(OpCodes.Ldc_I4_0); - break; - - case 1: - Generator.Emit(OpCodes.Ldc_I4_1); - break; - - case 2: - Generator.Emit(OpCodes.Ldc_I4_2); - break; - - case 3: - Generator.Emit(OpCodes.Ldc_I4_3); - break; - - case 4: - Generator.Emit(OpCodes.Ldc_I4_4); - break; - - case 5: - Generator.Emit(OpCodes.Ldc_I4_5); - break; - - case 6: - Generator.Emit(OpCodes.Ldc_I4_6); - break; - - case 7: - Generator.Emit(OpCodes.Ldc_I4_7); - break; - - case 8: - Generator.Emit(OpCodes.Ldc_I4_8); - break; - - default: - if (value >= sbyte.MinValue && value <= sbyte.MaxValue) - Generator.Emit(OpCodes.Ldc_I4_S, (sbyte)value); - else - Generator.Emit(OpCodes.Ldc_I4, value); - - break; - } - } - - public void LoadField(FieldInfo field) - { - Pop(field.DeclaringType); - - Push(field.FieldType); - - Generator.Emit(OpCodes.Ldfld, field); - } - - public void LoadLocal(LocalBuilder local) - { - Push(local.LocalType); - - int index = local.LocalIndex; - - switch (index) - { - case 0: - Generator.Emit(OpCodes.Ldloc_0); - break; - - case 1: - Generator.Emit(OpCodes.Ldloc_1); - break; - - case 2: - Generator.Emit(OpCodes.Ldloc_2); - break; - - case 3: - Generator.Emit(OpCodes.Ldloc_3); - break; - - default: - if (index >= byte.MinValue && index <= byte.MinValue) - Generator.Emit(OpCodes.Ldloc_S, (byte)index); - else - Generator.Emit(OpCodes.Ldloc, (short)index); - - break; - } - } - - public void StoreLocal(LocalBuilder local) - { - Pop(local.LocalType); - - Generator.Emit(OpCodes.Stloc, local); - } - - public void LoadArgument(int index) - { - if (index > 0) - Push(m_ArgumentTypes[index - 1]); - else - Push(Type); - - switch (index) - { - case 0: - Generator.Emit(OpCodes.Ldarg_0); - break; - - case 1: - Generator.Emit(OpCodes.Ldarg_1); - break; - - case 2: - Generator.Emit(OpCodes.Ldarg_2); - break; - - case 3: - Generator.Emit(OpCodes.Ldarg_3); - break; - - default: - if (index >= byte.MinValue && index <= byte.MaxValue) - Generator.Emit(OpCodes.Ldarg_S, (byte)index); - else - Generator.Emit(OpCodes.Ldarg, (short)index); - - break; - } - } - - public void CastAs(Type type) - { - Pop(typeof(object)); - Push(type); - - Generator.Emit(OpCodes.Isinst, type); - } - - public void Neg() - { - Pop(typeof(int)); - - Push(typeof(int)); - - Generator.Emit(OpCodes.Neg); - } - - public void Compare(OpCode opCode) - { - Pop(); - Pop(); - - Push(typeof(int)); - - Generator.Emit(opCode); - } - - public void LogicalNot() - { - Pop(typeof(int)); - - Push(typeof(int)); - - Generator.Emit(OpCodes.Ldc_I4_0); - Generator.Emit(OpCodes.Ceq); - } - - public void Xor() - { - Pop(typeof(int)); - Pop(typeof(int)); - - Push(typeof(int)); - - Generator.Emit(OpCodes.Xor); - } - - public Type Active => m_Stack.Peek(); - - public void Chain(Property prop) - { - for (int i = 0; i < prop.Chain.Length; ++i) - Call(prop.Chain[i].GetGetMethod()); - } - - public void Call(MethodInfo method) - { - BeginCall(method); - - CallInfo call = m_Calls.Peek(); - - if (call.parms.Length > 0) - throw new InvalidOperationException("Method requires parameters."); - - FinishCall(); - } - - public delegate void Callback(); - - public bool CompareTo(int sign, Callback argGenerator) - { - Type active = Active; - - MethodInfo compareTo = active.GetMethod("CompareTo", new[] { active }); - - if (compareTo == null) - { - /* This gets a little tricky... - * - * There's a scenario where we might be trying to use CompareTo on an interface - * which, while it doesn't explicitly implement CompareTo itself, is said to - * extend IComparable indirectly. The implementation is implicitly passed off - * to implementers... - * - * interface ISomeInterface : IComparable - * { - * void SomeMethod(); - * } - * - * class SomeClass : ISomeInterface - * { - * void SomeMethod() { ... } - * int CompareTo( object other ) { ... } - * } - * - * In this case, calling ISomeInterface.GetMethod( "CompareTo" ) will return null. - * - * Bleh. - */ - - Type[] ifaces = active.FindInterfaces((type, obj) => type.IsGenericType - && type.GetGenericTypeDefinition() == typeof(IComparable<>) - && type.GetGenericArguments()[0].IsAssignableFrom(active), null); - - if (ifaces.Length > 0) + public AssemblyEmitter(string assemblyName) { - compareTo = ifaces[0].GetMethod("CompareTo", new[] { active }); + m_AssemblyName = assemblyName; + + m_AppDomain = AppDomain.CurrentDomain; + + m_AssemblyBuilder = AssemblyBuilder.DefineDynamicAssembly( + new AssemblyName(assemblyName), + AssemblyBuilderAccess.Run + ); + + m_ModuleBuilder = m_AssemblyBuilder.DefineDynamicModule(assemblyName); } - else - { - ifaces = active.FindInterfaces((type, obj) => type == typeof(IComparable), null); - if (ifaces.Length > 0) - compareTo = ifaces[0].GetMethod("CompareTo", new[] { active }); + public TypeBuilder DefineType(string typeName, TypeAttributes attrs, Type parentType) => + m_ModuleBuilder.DefineType(typeName, attrs, parentType); + } + + public class MethodEmitter + { + public delegate void Callback(); + + private readonly Stack m_Calls; + + private readonly Stack m_Stack; + + private readonly Dictionary> m_Temps; + private Type[] m_ArgumentTypes; + + public MethodEmitter(TypeBuilder typeBuilder) + { + Type = typeBuilder; + + m_Temps = new Dictionary>(); + + m_Stack = new Stack(); + m_Calls = new Stack(); } - } - if (compareTo == null) - return false; + public TypeBuilder Type { get; } - if (!active.IsValueType) - { - /* This object is a reference type, so we have to make it behave - * - * null.CompareTo( null ) = 0 - * real.CompareTo( null ) = -1 - * null.CompareTo( real ) = +1 - * - */ + public ILGenerator Generator { get; private set; } - LocalBuilder aValue = AcquireTemp(active); - LocalBuilder bValue = AcquireTemp(active); + public MethodBuilder Method { get; private set; } - StoreLocal(aValue); + public Type Active => m_Stack.Peek(); - argGenerator(); - - StoreLocal(bValue); - - /* if (aValue == null) - * { - * if (bValue == null) - * v = 0; - * else - * v = +1; - * } - * else if (bValue == null) - * { - * v = -1; - * } - * else - * { - * v = aValue.CompareTo( bValue ); - * } - */ - - Label store = CreateLabel(); - - Label aNotNull = CreateLabel(); - - LoadLocal(aValue); - BranchIfTrue(aNotNull); - // if (aValue == null) + public void Define(string name, MethodAttributes attr, Type returnType, Type[] parms) { - Label bNotNull = CreateLabel(); + Method = Type.DefineMethod(name, attr, returnType, parms); + Generator = Method.GetILGenerator(); - LoadLocal(bValue); - BranchIfTrue(bNotNull); - // if (bValue == null) - { - Load(0); - Pop(typeof(int)); - Branch(store); - } - MarkLabel(bNotNull); - // else - { - Load(sign); - Pop(typeof(int)); - Branch(store); - } + m_ArgumentTypes = parms; } - MarkLabel(aNotNull); - // else + + public LocalBuilder CreateLocal(Type localType) => Generator.DeclareLocal(localType); + + public LocalBuilder AcquireTemp(Type localType) { - Label bNotNull = CreateLabel(); + if (!m_Temps.TryGetValue(localType, out var list)) + m_Temps[localType] = list = new Queue(); - LoadLocal(bValue); - BranchIfTrue(bNotNull); - // bValue == null - { - Load(-sign); + return list.Count > 0 ? list.Dequeue() : CreateLocal(localType); + } + + public void ReleaseTemp(LocalBuilder local) + { + if (local.LocalType == null) + return; + + if (!m_Temps.TryGetValue(local.LocalType, out var list)) + m_Temps[local.LocalType] = list = new Queue(); + + list.Enqueue(local); + } + + public void Branch(Label label) + { + Generator.Emit(OpCodes.Br, label); + } + + public void BranchIfFalse(Label label) + { + Pop(typeof(object)); + + Generator.Emit(OpCodes.Brfalse, label); + } + + public void BranchIfTrue(Label label) + { + Pop(typeof(object)); + + Generator.Emit(OpCodes.Brtrue, label); + } + + public Label CreateLabel() => Generator.DefineLabel(); + + public void MarkLabel(Label label) + { + Generator.MarkLabel(label); + } + + public void Pop() + { + m_Stack.Pop(); + } + + public void Pop(Type expected) + { + if (expected == null) + throw new InvalidOperationException("Expected type cannot be null."); + + var onStack = m_Stack.Pop(); + + if (expected == typeof(bool)) + expected = typeof(int); + + if (onStack == typeof(bool)) + onStack = typeof(int); + + if (!expected.IsAssignableFrom(onStack)) + throw new InvalidOperationException("Unexpected stack state."); + } + + public void Push(Type type) + { + m_Stack.Push(type); + } + + public void Return() + { + if (m_Stack.Count != (Method.ReturnType == typeof(void) ? 0 : 1)) + throw new InvalidOperationException("Stack return mismatch."); + + Generator.Emit(OpCodes.Ret); + } + + public void LoadNull() + { + LoadNull(typeof(object)); + } + + public void LoadNull(Type type) + { + Push(type); + + Generator.Emit(OpCodes.Ldnull); + } + + public void Load(string value) + { + Push(typeof(string)); + + if (value != null) + Generator.Emit(OpCodes.Ldstr, value); + else + Generator.Emit(OpCodes.Ldnull); + } + + public void Load(Enum value) + { + var toLoad = ((IConvertible)value).ToInt32(null); + Load(toLoad); + + Pop(); + Push(value.GetType()); + } + + public void Load(long value) + { + Push(typeof(long)); + + Generator.Emit(OpCodes.Ldc_I8, value); + } + + public void Load(float value) + { + Push(typeof(float)); + + Generator.Emit(OpCodes.Ldc_R4, value); + } + + public void Load(double value) + { + Push(typeof(double)); + + Generator.Emit(OpCodes.Ldc_R8, value); + } + + public void Load(char value) + { + Load((int)value); + + Pop(); + Push(typeof(char)); + } + + public void Load(bool value) + { + Push(typeof(bool)); + + if (value) + Generator.Emit(OpCodes.Ldc_I4_1); + else + Generator.Emit(OpCodes.Ldc_I4_0); + } + + public void Load(int value) + { + Push(typeof(int)); + + switch (value) + { + case -1: + Generator.Emit(OpCodes.Ldc_I4_M1); + break; + + case 0: + Generator.Emit(OpCodes.Ldc_I4_0); + break; + + case 1: + Generator.Emit(OpCodes.Ldc_I4_1); + break; + + case 2: + Generator.Emit(OpCodes.Ldc_I4_2); + break; + + case 3: + Generator.Emit(OpCodes.Ldc_I4_3); + break; + + case 4: + Generator.Emit(OpCodes.Ldc_I4_4); + break; + + case 5: + Generator.Emit(OpCodes.Ldc_I4_5); + break; + + case 6: + Generator.Emit(OpCodes.Ldc_I4_6); + break; + + case 7: + Generator.Emit(OpCodes.Ldc_I4_7); + break; + + case 8: + Generator.Emit(OpCodes.Ldc_I4_8); + break; + + default: + if (value >= sbyte.MinValue && value <= sbyte.MaxValue) + Generator.Emit(OpCodes.Ldc_I4_S, (sbyte)value); + else + Generator.Emit(OpCodes.Ldc_I4, value); + + break; + } + } + + public void LoadField(FieldInfo field) + { + Pop(field.DeclaringType); + + Push(field.FieldType); + + Generator.Emit(OpCodes.Ldfld, field); + } + + public void LoadLocal(LocalBuilder local) + { + Push(local.LocalType); + + var index = local.LocalIndex; + + switch (index) + { + case 0: + Generator.Emit(OpCodes.Ldloc_0); + break; + + case 1: + Generator.Emit(OpCodes.Ldloc_1); + break; + + case 2: + Generator.Emit(OpCodes.Ldloc_2); + break; + + case 3: + Generator.Emit(OpCodes.Ldloc_3); + break; + + default: + if (index >= byte.MinValue && index <= byte.MinValue) + Generator.Emit(OpCodes.Ldloc_S, (byte)index); + else + Generator.Emit(OpCodes.Ldloc, (short)index); + + break; + } + } + + public void StoreLocal(LocalBuilder local) + { + Pop(local.LocalType); + + Generator.Emit(OpCodes.Stloc, local); + } + + public void LoadArgument(int index) + { + if (index > 0) + Push(m_ArgumentTypes[index - 1]); + else + Push(Type); + + switch (index) + { + case 0: + Generator.Emit(OpCodes.Ldarg_0); + break; + + case 1: + Generator.Emit(OpCodes.Ldarg_1); + break; + + case 2: + Generator.Emit(OpCodes.Ldarg_2); + break; + + case 3: + Generator.Emit(OpCodes.Ldarg_3); + break; + + default: + if (index >= byte.MinValue && index <= byte.MaxValue) + Generator.Emit(OpCodes.Ldarg_S, (byte)index); + else + Generator.Emit(OpCodes.Ldarg, (short)index); + + break; + } + } + + public void CastAs(Type type) + { + Pop(typeof(object)); + Push(type); + + Generator.Emit(OpCodes.Isinst, type); + } + + public void Neg() + { Pop(typeof(int)); - Branch(store); - } - MarkLabel(bNotNull); - // else - { - LoadLocal(aValue); - BeginCall(compareTo); - LoadLocal(bValue); - ArgumentPushed(); + Push(typeof(int)); + + Generator.Emit(OpCodes.Neg); + } + + public void Compare(OpCode opCode) + { + Pop(); + Pop(); + + Push(typeof(int)); + + Generator.Emit(opCode); + } + + public void LogicalNot() + { + Pop(typeof(int)); + + Push(typeof(int)); + + Generator.Emit(OpCodes.Ldc_I4_0); + Generator.Emit(OpCodes.Ceq); + } + + public void Xor() + { + Pop(typeof(int)); + Pop(typeof(int)); + + Push(typeof(int)); + + Generator.Emit(OpCodes.Xor); + } + + public void Chain(Property prop) + { + for (var i = 0; i < prop.Chain.Length; ++i) + Call(prop.Chain[i].GetGetMethod()); + } + + public void Call(MethodInfo method) + { + BeginCall(method); + + var call = m_Calls.Peek(); + + if (call.parms.Length > 0) + throw new InvalidOperationException("Method requires parameters."); FinishCall(); - - if (sign == -1) - Neg(); - } } - MarkLabel(store); + public bool CompareTo(int sign, Callback argGenerator) + { + var active = Active; - ReleaseTemp(aValue); - ReleaseTemp(bValue); - } - else - { - BeginCall(compareTo); + var compareTo = active.GetMethod("CompareTo", new[] { active }); - argGenerator(); + if (compareTo == null) + { + /* This gets a little tricky... + * + * There's a scenario where we might be trying to use CompareTo on an interface + * which, while it doesn't explicitly implement CompareTo itself, is said to + * extend IComparable indirectly. The implementation is implicitly passed off + * to implementers... + * + * interface ISomeInterface : IComparable + * { + * void SomeMethod(); + * } + * + * class SomeClass : ISomeInterface + * { + * void SomeMethod() { ... } + * int CompareTo( object other ) { ... } + * } + * + * In this case, calling ISomeInterface.GetMethod( "CompareTo" ) will return null. + * + * Bleh. + */ - ArgumentPushed(); + var ifaces = active.FindInterfaces( + (type, obj) => type.IsGenericType + && type.GetGenericTypeDefinition() == typeof(IComparable<>) + && type.GetGenericArguments()[0].IsAssignableFrom(active), + null + ); - FinishCall(); + if (ifaces.Length > 0) + { + compareTo = ifaces[0].GetMethod("CompareTo", new[] { active }); + } + else + { + ifaces = active.FindInterfaces((type, obj) => type == typeof(IComparable), null); - if (sign == -1) - Neg(); - } + if (ifaces.Length > 0) + compareTo = ifaces[0].GetMethod("CompareTo", new[] { active }); + } + } - return true; + if (compareTo == null) + return false; + + if (!active.IsValueType) + { + /* This object is a reference type, so we have to make it behave + * + * null.CompareTo( null ) = 0 + * real.CompareTo( null ) = -1 + * null.CompareTo( real ) = +1 + * + */ + + var aValue = AcquireTemp(active); + var bValue = AcquireTemp(active); + + StoreLocal(aValue); + + argGenerator(); + + StoreLocal(bValue); + + /* if (aValue == null) + * { + * if (bValue == null) + * v = 0; + * else + * v = +1; + * } + * else if (bValue == null) + * { + * v = -1; + * } + * else + * { + * v = aValue.CompareTo( bValue ); + * } + */ + + var store = CreateLabel(); + + var aNotNull = CreateLabel(); + + LoadLocal(aValue); + BranchIfTrue(aNotNull); + // if (aValue == null) + { + var bNotNull = CreateLabel(); + + LoadLocal(bValue); + BranchIfTrue(bNotNull); + // if (bValue == null) + { + Load(0); + Pop(typeof(int)); + Branch(store); + } + MarkLabel(bNotNull); + // else + { + Load(sign); + Pop(typeof(int)); + Branch(store); + } + } + MarkLabel(aNotNull); + // else + { + var bNotNull = CreateLabel(); + + LoadLocal(bValue); + BranchIfTrue(bNotNull); + // bValue == null + { + Load(-sign); + Pop(typeof(int)); + Branch(store); + } + MarkLabel(bNotNull); + // else + { + LoadLocal(aValue); + BeginCall(compareTo); + + LoadLocal(bValue); + ArgumentPushed(); + + FinishCall(); + + if (sign == -1) + Neg(); + } + } + + MarkLabel(store); + + ReleaseTemp(aValue); + ReleaseTemp(bValue); + } + else + { + BeginCall(compareTo); + + argGenerator(); + + ArgumentPushed(); + + FinishCall(); + + if (sign == -1) + Neg(); + } + + return true; + } + + public void BeginCall(MethodInfo method) + { + var type = (method.CallingConvention & CallingConventions.HasThis) != 0 ? m_Stack.Peek() : method.DeclaringType; + + m_Calls.Push(new CallInfo(type, method)); + + if (type!.IsValueType) + { + var temp = AcquireTemp(type); + + Generator.Emit(OpCodes.Stloc, temp); + Generator.Emit(OpCodes.Ldloca, temp); + + ReleaseTemp(temp); + } + } + + public void FinishCall() + { + var call = m_Calls.Pop(); + + if ((call.type.IsValueType || call.type.IsByRef) && call.method.DeclaringType != call.type) + Generator.Emit(OpCodes.Constrained, call.type); + + if (call.method.DeclaringType?.IsValueType == true || call.method.IsStatic) + Generator.Emit(OpCodes.Call, call.method); + else + Generator.Emit(OpCodes.Callvirt, call.method); + + for (var i = call.parms.Length - 1; i >= 0; --i) + Pop(call.parms[i].ParameterType); + + if ((call.method.CallingConvention & CallingConventions.HasThis) != 0) + Pop(call.method.DeclaringType); + + if (call.method.ReturnType != typeof(void)) + Push(call.method.ReturnType); + } + + public void ArgumentPushed() + { + var call = m_Calls.Peek(); + + var parm = call.parms[call.index++]; + + var argumentType = m_Stack.Peek(); + + if (!parm.ParameterType.IsAssignableFrom(argumentType)) + throw new InvalidOperationException("Parameter type mismatch."); + + if (argumentType.IsValueType && !parm.ParameterType.IsValueType) + Generator.Emit(OpCodes.Box, argumentType); + } + + private class CallInfo + { + public readonly MethodInfo method; + public readonly ParameterInfo[] parms; + public readonly Type type; + + public int index; + + public CallInfo(Type type, MethodInfo method) + { + this.type = type; + this.method = method; + + parms = method.GetParameters(); + } + } } - - public void BeginCall(MethodInfo method) - { - var type = (method.CallingConvention & CallingConventions.HasThis) != 0 ? m_Stack.Peek() : method.DeclaringType; - - m_Calls.Push(new CallInfo(type, method)); - - if (type!.IsValueType) - { - LocalBuilder temp = AcquireTemp(type); - - Generator.Emit(OpCodes.Stloc, temp); - Generator.Emit(OpCodes.Ldloca, temp); - - ReleaseTemp(temp); - } - } - - public void FinishCall() - { - CallInfo call = m_Calls.Pop(); - - if ((call.type.IsValueType || call.type.IsByRef) && call.method.DeclaringType != call.type) - Generator.Emit(OpCodes.Constrained, call.type); - - if (call.method.DeclaringType?.IsValueType == true || call.method.IsStatic) - Generator.Emit(OpCodes.Call, call.method); - else - Generator.Emit(OpCodes.Callvirt, call.method); - - for (int i = call.parms.Length - 1; i >= 0; --i) - Pop(call.parms[i].ParameterType); - - if ((call.method.CallingConvention & CallingConventions.HasThis) != 0) - Pop(call.method.DeclaringType); - - if (call.method.ReturnType != typeof(void)) - Push(call.method.ReturnType); - } - - public void ArgumentPushed() - { - CallInfo call = m_Calls.Peek(); - - ParameterInfo parm = call.parms[call.index++]; - - Type argumentType = m_Stack.Peek(); - - if (!parm.ParameterType.IsAssignableFrom(argumentType)) - throw new InvalidOperationException("Parameter type mismatch."); - - if (argumentType.IsValueType && !parm.ParameterType.IsValueType) - Generator.Emit(OpCodes.Box, argumentType); - } - } } diff --git a/Projects/UOContent/Misc/Fastwalk.cs b/Projects/UOContent/Misc/Fastwalk.cs index 02343e73b..6d2236d1b 100644 --- a/Projects/UOContent/Misc/Fastwalk.cs +++ b/Projects/UOContent/Misc/Fastwalk.cs @@ -2,32 +2,32 @@ using System; namespace Server.Misc { - // This fastwalk detection is no longer required - // As of B36 PlayerMobile implements movement packet throttling which more reliably controls movement speeds - public static class Fastwalk - { - private static readonly int MaxSteps = 4; // Maximum number of queued steps until fastwalk is detected - private static readonly bool Enabled = false; // Is fastwalk detection enabled? - private static readonly bool UOTDOverride = false; // Should UO:TD clients not be checked for fastwalk? - - private static readonly AccessLevel - AccessOverride = AccessLevel.GameMaster; // Anyone with this or higher access level is not checked for fastwalk - - public static void Initialize() + // This fastwalk detection is no longer required + // As of B36 PlayerMobile implements movement packet throttling which more reliably controls movement speeds + public static class Fastwalk { - Mobile.FwdMaxSteps = MaxSteps; - Mobile.FwdEnabled = Enabled; - Mobile.FwdUOTDOverride = UOTDOverride; - Mobile.FwdAccessOverride = AccessOverride; + private static readonly int MaxSteps = 4; // Maximum number of queued steps until fastwalk is detected + private static readonly bool Enabled = false; // Is fastwalk detection enabled? + private static readonly bool UOTDOverride = false; // Should UO:TD clients not be checked for fastwalk? - if (Enabled) - EventSink.FastWalk += OnFastWalk; - } + private static readonly AccessLevel + AccessOverride = AccessLevel.GameMaster; // Anyone with this or higher access level is not checked for fastwalk - public static void OnFastWalk(FastWalkEventArgs e) - { - e.Blocked = true; // disallow this fastwalk - Console.WriteLine("Client: {0}: Fast movement detected (name={1})", e.NetState, e.NetState.Mobile.Name); + public static void Initialize() + { + Mobile.FwdMaxSteps = MaxSteps; + Mobile.FwdEnabled = Enabled; + Mobile.FwdUOTDOverride = UOTDOverride; + Mobile.FwdAccessOverride = AccessOverride; + + if (Enabled) + EventSink.FastWalk += OnFastWalk; + } + + public static void OnFastWalk(FastWalkEventArgs e) + { + e.Blocked = true; // disallow this fastwalk + Console.WriteLine("Client: {0}: Fast movement detected (name={1})", e.NetState, e.NetState.Mobile.Name); + } } - } } diff --git a/Projects/UOContent/Misc/FoodDecay.cs b/Projects/UOContent/Misc/FoodDecay.cs index 82533cf0d..76ece4c53 100644 --- a/Projects/UOContent/Misc/FoodDecay.cs +++ b/Projects/UOContent/Misc/FoodDecay.cs @@ -3,39 +3,40 @@ using Server.Network; namespace Server.Misc { - public class FoodDecayTimer : Timer - { - public FoodDecayTimer() : base(TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)) => Priority = TimerPriority.OneMinute; - - public static void Initialize() + public class FoodDecayTimer : Timer { - new FoodDecayTimer().Start(); - } + public FoodDecayTimer() : base(TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)) => + Priority = TimerPriority.OneMinute; - protected override void OnTick() - { - FoodDecay(); - } + public static void Initialize() + { + new FoodDecayTimer().Start(); + } - public static void FoodDecay() - { - foreach (NetState state in TcpServer.Instances) - { - HungerDecay(state.Mobile); - ThirstDecay(state.Mobile); - } - } + protected override void OnTick() + { + FoodDecay(); + } - public static void HungerDecay(Mobile m) - { - if (m?.Hunger >= 1) - m.Hunger -= 1; - } + public static void FoodDecay() + { + foreach (var state in TcpServer.Instances) + { + HungerDecay(state.Mobile); + ThirstDecay(state.Mobile); + } + } - public static void ThirstDecay(Mobile m) - { - if (m?.Thirst >= 1) - m.Thirst -= 1; + public static void HungerDecay(Mobile m) + { + if (m?.Hunger >= 1) + m.Hunger -= 1; + } + + public static void ThirstDecay(Mobile m) + { + if (m?.Thirst >= 1) + m.Thirst -= 1; + } } - } } diff --git a/Projects/UOContent/Misc/Geometry.cs b/Projects/UOContent/Misc/Geometry.cs index f7ccf1747..9a9fb48e5 100644 --- a/Projects/UOContent/Misc/Geometry.cs +++ b/Projects/UOContent/Misc/Geometry.cs @@ -2,216 +2,220 @@ using System; namespace Server.Misc { - public delegate void DoEffect_Callback(Point3D p, Map map); + public delegate void DoEffect_Callback(Point3D p, Map map); - public static class Geometry - { - public static void Swap(ref T a, ref T b) + public static class Geometry { - T temp = a; - a = b; - b = temp; - } - - public static double RadiansToDegrees(double angle) => angle * (180.0 / Math.PI); - - public static double DegreesToRadians(double angle) => angle * (Math.PI / 180.0); - - public static Point2D ArcPoint(Point3D loc, int radius, int angle) - { - int sideA, sideB; - - angle = Math.Clamp(angle, 0, 90); - - sideA = (int)Math.Round(radius * Math.Sin(DegreesToRadians(angle))); - sideB = (int)Math.Round(radius * Math.Cos(DegreesToRadians(angle))); - - return new Point2D(loc.X - sideB, loc.Y - sideA); - } - - public static void Circle2D(Point3D loc, Map map, int radius, DoEffect_Callback effect) - { - Circle2D(loc, map, radius, effect, 0, 360); - } - - public static void Circle2D(Point3D loc, Map map, int radius, DoEffect_Callback effect, int angleStart, int angleEnd) - { - if (angleStart < 0 || angleStart > 360) - angleStart = 0; - - if (angleEnd > 360 || angleEnd < 0) - angleEnd = 360; - - if (angleStart == angleEnd) - return; - - bool opposite = angleStart > angleEnd; - - int startQuadrant = angleStart / 90; - int endQuadrant = angleEnd / 90; - - Point2D start = ArcPoint(loc, radius, angleStart % 90); - Point2D end = ArcPoint(loc, radius, angleEnd % 90); - - if (opposite) - { - Swap(ref start, ref end); - Swap(ref startQuadrant, ref endQuadrant); - } - - CirclePoint startPoint = new CirclePoint(start, angleStart, startQuadrant); - CirclePoint endPoint = new CirclePoint(end, angleEnd, endQuadrant); - - int error = -radius; - int x = radius; - int y = 0; - - while (x > y) - { - plot4points(loc, map, x, y, startPoint, endPoint, effect, opposite); - plot4points(loc, map, y, x, startPoint, endPoint, effect, opposite); - - error += y * 2 + 1; - ++y; - - if (error >= 0) + public static void Swap(ref T a, ref T b) { - --x; - error -= x * 2; + var temp = a; + a = b; + b = temp; } - } - plot4points(loc, map, x, y, startPoint, endPoint, effect, opposite); - } + public static double RadiansToDegrees(double angle) => angle * (180.0 / Math.PI); - public static void plot4points(Point3D loc, Map map, int x, int y, CirclePoint start, CirclePoint end, - DoEffect_Callback effect, bool opposite) - { - Point2D pointA = new Point2D(loc.X - x, loc.Y - y); - Point2D pointB = new Point2D(loc.X - y, loc.Y - x); + public static double DegreesToRadians(double angle) => angle * (Math.PI / 180.0); - int quadrant = 2; - - if (x == 0 && start.Quadrant == 3) - quadrant = 3; - - if (WithinCircleBounds(quadrant == 3 ? pointB : pointA, quadrant, loc, start, end, opposite)) - effect(new Point3D(loc.X + x, loc.Y + y, loc.Z), map); - - quadrant = 3; - - if (y == 0 && start.Quadrant == 0) - quadrant = 0; - - if (x != 0 && WithinCircleBounds(quadrant == 0 ? pointA : pointB, quadrant, loc, start, end, opposite)) - effect(new Point3D(loc.X - x, loc.Y + y, loc.Z), map); - if (y != 0 && WithinCircleBounds(pointB, 1, loc, start, end, opposite)) - effect(new Point3D(loc.X + x, loc.Y - y, loc.Z), map); - if (x != 0 && y != 0 && WithinCircleBounds(pointA, 0, loc, start, end, opposite)) - effect(new Point3D(loc.X - x, loc.Y - y, loc.Z), map); - } - - public static bool WithinCircleBounds(Point2D pointLoc, int pointQuadrant, Point3D center, CirclePoint start, - CirclePoint end, bool opposite) - { - if (start.Angle == 0 && end.Angle == 360) - return true; - - int startX = start.Point.X; - int startY = start.Point.Y; - int endX = end.Point.X; - int endY = end.Point.Y; - - int x = pointLoc.X; - int y = pointLoc.Y; - - if (pointQuadrant < start.Quadrant || pointQuadrant > end.Quadrant) - return opposite; - - if (pointQuadrant > start.Quadrant && pointQuadrant < end.Quadrant) - return !opposite; - - bool withinBounds = true; - - if (start.Quadrant == end.Quadrant) - { - if (startX == endX && (x > startX || y > startY || y < endY)) - withinBounds = false; - else if (startY == endY && (y < startY || x < startX || x > endX)) - withinBounds = false; - else if (x < startX || x > endX || y > startY || y < endY) - withinBounds = false; - } - else if (pointQuadrant == start.Quadrant && (x < startX || y > startY)) - { - withinBounds = false; - } - else if (pointQuadrant == end.Quadrant && (x > endX || y < endY)) - { - withinBounds = false; - } - - return opposite ? !withinBounds : withinBounds; - } - - public static void Line2D(Point3D start, Point3D end, Map map, DoEffect_Callback effect) - { - bool steep = Math.Abs(end.Y - start.Y) > Math.Abs(end.X - start.X); - - int x0 = start.X; - int x1 = end.X; - int y0 = start.Y; - int y1 = end.Y; - - if (steep) - { - Swap(ref x0, ref y0); - Swap(ref x1, ref y1); - } - - if (x0 > x1) - { - Swap(ref x0, ref x1); - Swap(ref y0, ref y1); - } - - int deltax = x1 - x0; - int deltay = Math.Abs(y1 - y0); - int error = deltax / 2; - int ystep = y0 < y1 ? 1 : -1; - int y = y0; - - for (int x = x0; x <= x1; x++) - { - if (steep) - effect(new Point3D(y, x, start.Z), map); - else - effect(new Point3D(x, y, start.Z), map); - - error -= deltay; - - if (error < 0) + public static Point2D ArcPoint(Point3D loc, int radius, int angle) { - y += ystep; - error += deltax; + int sideA, sideB; + + angle = Math.Clamp(angle, 0, 90); + + sideA = (int)Math.Round(radius * Math.Sin(DegreesToRadians(angle))); + sideB = (int)Math.Round(radius * Math.Cos(DegreesToRadians(angle))); + + return new Point2D(loc.X - sideB, loc.Y - sideA); + } + + public static void Circle2D(Point3D loc, Map map, int radius, DoEffect_Callback effect) + { + Circle2D(loc, map, radius, effect, 0, 360); + } + + public static void Circle2D(Point3D loc, Map map, int radius, DoEffect_Callback effect, int angleStart, int angleEnd) + { + if (angleStart < 0 || angleStart > 360) + angleStart = 0; + + if (angleEnd > 360 || angleEnd < 0) + angleEnd = 360; + + if (angleStart == angleEnd) + return; + + var opposite = angleStart > angleEnd; + + var startQuadrant = angleStart / 90; + var endQuadrant = angleEnd / 90; + + var start = ArcPoint(loc, radius, angleStart % 90); + var end = ArcPoint(loc, radius, angleEnd % 90); + + if (opposite) + { + Swap(ref start, ref end); + Swap(ref startQuadrant, ref endQuadrant); + } + + var startPoint = new CirclePoint(start, angleStart, startQuadrant); + var endPoint = new CirclePoint(end, angleEnd, endQuadrant); + + var error = -radius; + var x = radius; + var y = 0; + + while (x > y) + { + plot4points(loc, map, x, y, startPoint, endPoint, effect, opposite); + plot4points(loc, map, y, x, startPoint, endPoint, effect, opposite); + + error += y * 2 + 1; + ++y; + + if (error >= 0) + { + --x; + error -= x * 2; + } + } + + plot4points(loc, map, x, y, startPoint, endPoint, effect, opposite); + } + + public static void plot4points( + Point3D loc, Map map, int x, int y, CirclePoint start, CirclePoint end, + DoEffect_Callback effect, bool opposite + ) + { + var pointA = new Point2D(loc.X - x, loc.Y - y); + var pointB = new Point2D(loc.X - y, loc.Y - x); + + var quadrant = 2; + + if (x == 0 && start.Quadrant == 3) + quadrant = 3; + + if (WithinCircleBounds(quadrant == 3 ? pointB : pointA, quadrant, loc, start, end, opposite)) + effect(new Point3D(loc.X + x, loc.Y + y, loc.Z), map); + + quadrant = 3; + + if (y == 0 && start.Quadrant == 0) + quadrant = 0; + + if (x != 0 && WithinCircleBounds(quadrant == 0 ? pointA : pointB, quadrant, loc, start, end, opposite)) + effect(new Point3D(loc.X - x, loc.Y + y, loc.Z), map); + if (y != 0 && WithinCircleBounds(pointB, 1, loc, start, end, opposite)) + effect(new Point3D(loc.X + x, loc.Y - y, loc.Z), map); + if (x != 0 && y != 0 && WithinCircleBounds(pointA, 0, loc, start, end, opposite)) + effect(new Point3D(loc.X - x, loc.Y - y, loc.Z), map); + } + + public static bool WithinCircleBounds( + Point2D pointLoc, int pointQuadrant, Point3D center, CirclePoint start, + CirclePoint end, bool opposite + ) + { + if (start.Angle == 0 && end.Angle == 360) + return true; + + var startX = start.Point.X; + var startY = start.Point.Y; + var endX = end.Point.X; + var endY = end.Point.Y; + + var x = pointLoc.X; + var y = pointLoc.Y; + + if (pointQuadrant < start.Quadrant || pointQuadrant > end.Quadrant) + return opposite; + + if (pointQuadrant > start.Quadrant && pointQuadrant < end.Quadrant) + return !opposite; + + var withinBounds = true; + + if (start.Quadrant == end.Quadrant) + { + if (startX == endX && (x > startX || y > startY || y < endY)) + withinBounds = false; + else if (startY == endY && (y < startY || x < startX || x > endX)) + withinBounds = false; + else if (x < startX || x > endX || y > startY || y < endY) + withinBounds = false; + } + else if (pointQuadrant == start.Quadrant && (x < startX || y > startY)) + { + withinBounds = false; + } + else if (pointQuadrant == end.Quadrant && (x > endX || y < endY)) + { + withinBounds = false; + } + + return opposite ? !withinBounds : withinBounds; + } + + public static void Line2D(Point3D start, Point3D end, Map map, DoEffect_Callback effect) + { + var steep = Math.Abs(end.Y - start.Y) > Math.Abs(end.X - start.X); + + var x0 = start.X; + var x1 = end.X; + var y0 = start.Y; + var y1 = end.Y; + + if (steep) + { + Swap(ref x0, ref y0); + Swap(ref x1, ref y1); + } + + if (x0 > x1) + { + Swap(ref x0, ref x1); + Swap(ref y0, ref y1); + } + + var deltax = x1 - x0; + var deltay = Math.Abs(y1 - y0); + var error = deltax / 2; + var ystep = y0 < y1 ? 1 : -1; + var y = y0; + + for (var x = x0; x <= x1; x++) + { + if (steep) + effect(new Point3D(y, x, start.Z), map); + else + effect(new Point3D(x, y, start.Z), map); + + error -= deltay; + + if (error < 0) + { + y += ystep; + error += deltax; + } + } + } + + public class CirclePoint + { + public CirclePoint(Point2D point, int angle, int quadrant) + { + Point = point; + Angle = angle; + Quadrant = quadrant; + } + + public Point2D Point { get; } + + public int Angle { get; } + + public int Quadrant { get; } } - } } - - public class CirclePoint - { - public CirclePoint(Point2D point, int angle, int quadrant) - { - Point = point; - Angle = angle; - Quadrant = quadrant; - } - - public Point2D Point { get; } - - public int Angle { get; } - - public int Quadrant { get; } - } - } } diff --git a/Projects/UOContent/Misc/Gifts/Winter2004/DecorativeTopiary.cs b/Projects/UOContent/Misc/Gifts/Winter2004/DecorativeTopiary.cs index 96080dd25..3e7f3c02b 100644 --- a/Projects/UOContent/Misc/Gifts/Winter2004/DecorativeTopiary.cs +++ b/Projects/UOContent/Misc/Gifts/Winter2004/DecorativeTopiary.cs @@ -1,44 +1,44 @@ namespace Server.Items { - public class DecorativeTopiary : Item - { - [Constructible] - public DecorativeTopiary() : base(0x2378) + public class DecorativeTopiary : Item { - Weight = 1.0; - LootType = LootType.Blessed; + [Constructible] + public DecorativeTopiary() : base(0x2378) + { + Weight = 1.0; + LootType = LootType.Blessed; + } + + public DecorativeTopiary(Serial serial) : base(serial) + { + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + LabelTo(from, 1070880); // Winter 2004 + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1070880); // Winter 2004 + } + + 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 DecorativeTopiary(Serial serial) : base(serial) - { - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - LabelTo(from, 1070880); // Winter 2004 - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1070880); // Winter 2004 - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Misc/Gifts/Winter2004/FestiveCactus.cs b/Projects/UOContent/Misc/Gifts/Winter2004/FestiveCactus.cs index 0f7c41687..e347b2ada 100644 --- a/Projects/UOContent/Misc/Gifts/Winter2004/FestiveCactus.cs +++ b/Projects/UOContent/Misc/Gifts/Winter2004/FestiveCactus.cs @@ -1,44 +1,44 @@ namespace Server.Items { - public class FestiveCactus : Item - { - [Constructible] - public FestiveCactus() : base(0x2376) + public class FestiveCactus : Item { - Weight = 1.0; - LootType = LootType.Blessed; + [Constructible] + public FestiveCactus() : base(0x2376) + { + Weight = 1.0; + LootType = LootType.Blessed; + } + + public FestiveCactus(Serial serial) : base(serial) + { + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + LabelTo(from, 1070880); // Winter 2004 + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1070880); // Winter 2004 + } + + 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 FestiveCactus(Serial serial) : base(serial) - { - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - LabelTo(from, 1070880); // Winter 2004 - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1070880); // Winter 2004 - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Misc/Gifts/Winter2004/LightOfTheWinterSolstice.cs b/Projects/UOContent/Misc/Gifts/Winter2004/LightOfTheWinterSolstice.cs index 11457e71b..e5e636c8b 100644 --- a/Projects/UOContent/Misc/Gifts/Winter2004/LightOfTheWinterSolstice.cs +++ b/Projects/UOContent/Misc/Gifts/Winter2004/LightOfTheWinterSolstice.cs @@ -1,93 +1,93 @@ namespace Server.Items { - [Flippable(0x236E, 0x2371)] - public class LightOfTheWinterSolstice : Item - { - private static readonly string[] m_StaffNames = + [Flippable(0x236E, 0x2371)] + public class LightOfTheWinterSolstice : Item { - "Aenima", - "Alkiser", - "ASayre", - "David", - "Krrios", - "Mark", - "Merlin", - "Merlix", // LordMerlix - "Phantom", - "Phenos", - "psz", - "Ryan", - "Quantos", - "Outkast", // TheOutkastDev - "V", // Admin_V - "Zippy" - }; + private static readonly string[] m_StaffNames = + { + "Aenima", + "Alkiser", + "ASayre", + "David", + "Krrios", + "Mark", + "Merlin", + "Merlix", // LordMerlix + "Phantom", + "Phenos", + "psz", + "Ryan", + "Quantos", + "Outkast", // TheOutkastDev + "V", // Admin_V + "Zippy" + }; - [Constructible] - public LightOfTheWinterSolstice(string dipper = null) : base(0x236E) - { - Dipper = dipper ?? m_StaffNames.RandomElement(); + [Constructible] + public LightOfTheWinterSolstice(string dipper = null) : base(0x236E) + { + Dipper = dipper ?? m_StaffNames.RandomElement(); - Weight = 1.0; - LootType = LootType.Blessed; - Light = LightType.Circle300; - Hue = Utility.RandomDyedHue(); + Weight = 1.0; + LootType = LootType.Blessed; + Light = LightType.Circle300; + Hue = Utility.RandomDyedHue(); + } + + public LightOfTheWinterSolstice(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public string Dipper { get; set; } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + LabelTo(from, 1070881, Dipper); // Hand Dipped by ~1_name~ + LabelTo(from, 1070880); // Winter 2004 + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1070881, Dipper); // Hand Dipped by ~1_name~ + list.Add(1070880); // Winter 2004 + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(Dipper); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + Dipper = reader.ReadString(); + break; + } + case 0: + { + Dipper = m_StaffNames.RandomElement(); + break; + } + } + + if (Dipper != null) + Dipper = string.Intern(Dipper); + } } - - public LightOfTheWinterSolstice(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public string Dipper { get; set; } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - LabelTo(from, 1070881, Dipper); // Hand Dipped by ~1_name~ - LabelTo(from, 1070880); // Winter 2004 - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1070881, Dipper); // Hand Dipped by ~1_name~ - list.Add(1070880); // Winter 2004 - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(Dipper); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - Dipper = reader.ReadString(); - break; - } - case 0: - { - Dipper = m_StaffNames.RandomElement(); - break; - } - } - - if (Dipper != null) - Dipper = string.Intern(Dipper); - } - } } diff --git a/Projects/UOContent/Misc/Gifts/Winter2004/Mistletoe.cs b/Projects/UOContent/Misc/Gifts/Winter2004/Mistletoe.cs index a541af3dd..e86f7c792 100644 --- a/Projects/UOContent/Misc/Gifts/Winter2004/Mistletoe.cs +++ b/Projects/UOContent/Misc/Gifts/Winter2004/Mistletoe.cs @@ -5,317 +5,317 @@ using Server.Targeting; namespace Server.Items { - public class MistletoeAddon : Item, IDyable, IAddon - { - [Constructible] - public MistletoeAddon() : this(Utility.RandomDyedHue()) + public class MistletoeAddon : Item, IDyable, IAddon { - } - - [Constructible] - public MistletoeAddon(int hue) : base(0x2375) - { - Hue = hue; - Movable = false; - } - - public MistletoeAddon(Serial serial) : base(serial) - { - } - - public bool CouldFit(IPoint3D p, Map map) - { - if (!map.CanFit(p.X, p.Y, p.Z, ItemData.Height)) - return false; - - if (ItemID == 0x2375) - return BaseAddon.IsWall(p.X, p.Y - 1, p.Z, map); // North wall - return BaseAddon.IsWall(p.X - 1, p.Y, p.Z, map); // West wall - } - - public Item Deed => new MistletoeDeed(Hue); - - public virtual bool Dye(Mobile from, DyeTub sender) - { - if (Deleted) - return false; - - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (house?.IsCoOwner(from) == true) - { - if (from.InRange(GetWorldLocation(), 1)) + [Constructible] + public MistletoeAddon() : this(Utility.RandomDyedHue()) { - Hue = sender.DyedHue; - return true; } - from.SendLocalizedMessage(500295); // You are too far away to do that. - return false; - } - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Timer.DelayCall(FixMovingCrate); - } - - private void FixMovingCrate() - { - if (Deleted) - return; - - if (Movable || IsLockedDown) - { - Item deed = Deed; - - if (Parent is Item item) + [Constructible] + public MistletoeAddon(int hue) : base(0x2375) { - item.AddItem(deed); - deed.Location = Location; - } - else - { - deed.MoveToWorld(Location, Map); + Hue = hue; + Movable = false; } - Delete(); - } - } - - public override void OnDoubleClick(Mobile from) - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (house?.IsCoOwner(from) == true) - { - if (from.InRange(GetWorldLocation(), 3)) + public MistletoeAddon(Serial serial) : base(serial) { - from.CloseGump(); - from.SendGump(new MistletoeAddonGump(from, this)); } - else + + public bool CouldFit(IPoint3D p, Map map) { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + if (!map.CanFit(p.X, p.Y, p.Z, ItemData.Height)) + return false; + + if (ItemID == 0x2375) + return BaseAddon.IsWall(p.X, p.Y - 1, p.Z, map); // North wall + return BaseAddon.IsWall(p.X - 1, p.Y, p.Z, map); // West wall } - } - } - private class MistletoeAddonGump : Gump - { - private readonly MistletoeAddon m_Addon; - private readonly Mobile m_From; + public Item Deed => new MistletoeDeed(Hue); - public MistletoeAddonGump(Mobile from, MistletoeAddon addon) : base(150, 50) - { - m_From = from; - m_Addon = addon; - - AddPage(0); - - AddBackground(0, 0, 220, 170, 0x13BE); - AddBackground(10, 10, 200, 150, 0xBB8); - AddHtmlLocalized(20, 30, 180, 60, 1062839); // Do you wish to re-deed this decoration? - AddHtmlLocalized(55, 100, 160, 25, 1011011); // CONTINUE - AddButton(20, 100, 0xFA5, 0xFA7, 1); - AddHtmlLocalized(55, 125, 160, 25, 1011012); // CANCEL - AddButton(20, 125, 0xFA5, 0xFA7, 0); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Addon.Deleted || info.ButtonID != 1) - return; - - if (m_From.InRange(m_Addon.GetWorldLocation(), 3)) + public virtual bool Dye(Mobile from, DyeTub sender) { - m_From.AddToBackpack(m_Addon.Deed); - m_Addon.Delete(); + if (Deleted) + return false; + + var house = BaseHouse.FindHouseAt(this); + + if (house?.IsCoOwner(from) == true) + { + if (from.InRange(GetWorldLocation(), 1)) + { + Hue = sender.DyedHue; + return true; + } + + from.SendLocalizedMessage(500295); // You are too far away to do that. + return false; + } + + return false; } - else + + public override void Serialize(IGenericWriter writer) { - m_From.SendLocalizedMessage(500295); // You are too far away to do that. + base.Serialize(writer); + + writer.Write(0); // version } - } - } - } - [Flippable(0x14F0, 0x14EF)] - public class MistletoeDeed : Item - { - [Constructible] - public MistletoeDeed(int hue = 0) : base(0x14F0) - { - Hue = hue; - Weight = 1.0; - LootType = LootType.Blessed; - } - - public MistletoeDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070882; // Mistletoe Deed - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - LabelTo(from, 1070880); // Winter 2004 - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1070880); // Winter 2004 - } - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - { - BaseHouse house = BaseHouse.FindHouseAt(from); - - if (house?.IsCoOwner(from) == true) + public override void Deserialize(IGenericReader reader) { - from.SendLocalizedMessage(1062838); // Where would you like to place this decoration? - from.BeginTarget(-1, true, TargetFlags.None, Placement_OnTarget); + base.Deserialize(reader); + + var version = reader.ReadInt(); + + Timer.DelayCall(FixMovingCrate); } - else + + private void FixMovingCrate() { - from.SendLocalizedMessage(502092); // You must be in your house to do this. + if (Deleted) + return; + + if (Movable || IsLockedDown) + { + var deed = Deed; + + if (Parent is Item item) + { + item.AddItem(deed); + deed.Location = Location; + } + else + { + deed.MoveToWorld(Location, Map); + } + + Delete(); + } } - } - else - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - } - public void Placement_OnTarget(Mobile from, object targeted) - { - if (!(targeted is IPoint3D p)) - return; - - Point3D loc = new Point3D(p); - - BaseHouse house = BaseHouse.FindHouseAt(loc, from.Map, 16); - - if (house?.IsCoOwner(from) == true) - { - bool northWall = BaseAddon.IsWall(loc.X, loc.Y - 1, loc.Z, from.Map); - bool westWall = BaseAddon.IsWall(loc.X - 1, loc.Y, loc.Z, from.Map); - - if (northWall && westWall) - from.SendGump(new MistletoeDeedGump(from, loc, this)); - else - PlaceAddon(from, loc, northWall, westWall); - } - else - { - from.SendLocalizedMessage(1042036); // That location is not in your house. - } - } - - private void PlaceAddon(Mobile from, Point3D loc, bool northWall, bool westWall) - { - if (Deleted) - return; - - BaseHouse house = BaseHouse.FindHouseAt(loc, from.Map, 16); - - if (house?.IsCoOwner(from) != true) - { - from.SendLocalizedMessage(1042036); // That location is not in your house. - return; - } - - int itemID = 0; - - if (northWall) - itemID = 0x2374; - else if (westWall) - itemID = 0x2375; - else - from.SendLocalizedMessage(1070883); // The mistletoe must be placed next to a wall. - - if (itemID > 0) - { - Item addon = new MistletoeAddon(Hue); - - addon.ItemID = itemID; - addon.MoveToWorld(loc, from.Map); - - house.Addons.Add(addon); - Delete(); - } - } - - private class MistletoeDeedGump : Gump - { - private readonly MistletoeDeed m_Deed; - private readonly Mobile m_From; - private readonly Point3D m_Loc; - - public MistletoeDeedGump(Mobile from, Point3D loc, MistletoeDeed deed) : base(150, 50) - { - m_From = from; - m_Loc = loc; - m_Deed = deed; - - AddBackground(0, 0, 300, 150, 0xA28); - - AddPage(0); - - AddItem(90, 30, 0x2375); - AddItem(180, 30, 0x2374); - AddButton(50, 35, 0x868, 0x869, 1); - AddButton(145, 35, 0x868, 0x869, 2); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Deed.Deleted) - return; - - switch (info.ButtonID) + public override void OnDoubleClick(Mobile from) { - case 1: - m_Deed.PlaceAddon(m_From, m_Loc, false, true); - break; - case 2: - m_Deed.PlaceAddon(m_From, m_Loc, true, false); - break; + var house = BaseHouse.FindHouseAt(this); + + if (house?.IsCoOwner(from) == true) + { + if (from.InRange(GetWorldLocation(), 3)) + { + from.CloseGump(); + from.SendGump(new MistletoeAddonGump(from, this)); + } + else + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + } + } + } + + private class MistletoeAddonGump : Gump + { + private readonly MistletoeAddon m_Addon; + private readonly Mobile m_From; + + public MistletoeAddonGump(Mobile from, MistletoeAddon addon) : base(150, 50) + { + m_From = from; + m_Addon = addon; + + AddPage(0); + + AddBackground(0, 0, 220, 170, 0x13BE); + AddBackground(10, 10, 200, 150, 0xBB8); + AddHtmlLocalized(20, 30, 180, 60, 1062839); // Do you wish to re-deed this decoration? + AddHtmlLocalized(55, 100, 160, 25, 1011011); // CONTINUE + AddButton(20, 100, 0xFA5, 0xFA7, 1); + AddHtmlLocalized(55, 125, 160, 25, 1011012); // CANCEL + AddButton(20, 125, 0xFA5, 0xFA7, 0); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Addon.Deleted || info.ButtonID != 1) + return; + + if (m_From.InRange(m_Addon.GetWorldLocation(), 3)) + { + m_From.AddToBackpack(m_Addon.Deed); + m_Addon.Delete(); + } + else + { + m_From.SendLocalizedMessage(500295); // You are too far away to do that. + } + } + } + } + + [Flippable(0x14F0, 0x14EF)] + public class MistletoeDeed : Item + { + [Constructible] + public MistletoeDeed(int hue = 0) : base(0x14F0) + { + Hue = hue; + Weight = 1.0; + LootType = LootType.Blessed; + } + + public MistletoeDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1070882; // Mistletoe Deed + + 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 OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + LabelTo(from, 1070880); // Winter 2004 + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1070880); // Winter 2004 + } + + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + { + var house = BaseHouse.FindHouseAt(from); + + if (house?.IsCoOwner(from) == true) + { + from.SendLocalizedMessage(1062838); // Where would you like to place this decoration? + from.BeginTarget(-1, true, TargetFlags.None, Placement_OnTarget); + } + else + { + from.SendLocalizedMessage(502092); // You must be in your house to do this. + } + } + else + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + } + + public void Placement_OnTarget(Mobile from, object targeted) + { + if (!(targeted is IPoint3D p)) + return; + + var loc = new Point3D(p); + + var house = BaseHouse.FindHouseAt(loc, from.Map, 16); + + if (house?.IsCoOwner(from) == true) + { + var northWall = BaseAddon.IsWall(loc.X, loc.Y - 1, loc.Z, from.Map); + var westWall = BaseAddon.IsWall(loc.X - 1, loc.Y, loc.Z, from.Map); + + if (northWall && westWall) + from.SendGump(new MistletoeDeedGump(from, loc, this)); + else + PlaceAddon(from, loc, northWall, westWall); + } + else + { + from.SendLocalizedMessage(1042036); // That location is not in your house. + } + } + + private void PlaceAddon(Mobile from, Point3D loc, bool northWall, bool westWall) + { + if (Deleted) + return; + + var house = BaseHouse.FindHouseAt(loc, from.Map, 16); + + if (house?.IsCoOwner(from) != true) + { + from.SendLocalizedMessage(1042036); // That location is not in your house. + return; + } + + var itemID = 0; + + if (northWall) + itemID = 0x2374; + else if (westWall) + itemID = 0x2375; + else + from.SendLocalizedMessage(1070883); // The mistletoe must be placed next to a wall. + + if (itemID > 0) + { + Item addon = new MistletoeAddon(Hue); + + addon.ItemID = itemID; + addon.MoveToWorld(loc, from.Map); + + house.Addons.Add(addon); + Delete(); + } + } + + private class MistletoeDeedGump : Gump + { + private readonly MistletoeDeed m_Deed; + private readonly Mobile m_From; + private readonly Point3D m_Loc; + + public MistletoeDeedGump(Mobile from, Point3D loc, MistletoeDeed deed) : base(150, 50) + { + m_From = from; + m_Loc = loc; + m_Deed = deed; + + AddBackground(0, 0, 300, 150, 0xA28); + + AddPage(0); + + AddItem(90, 30, 0x2375); + AddItem(180, 30, 0x2374); + AddButton(50, 35, 0x868, 0x869, 1); + AddButton(145, 35, 0x868, 0x869, 2); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Deed.Deleted) + return; + + switch (info.ButtonID) + { + case 1: + m_Deed.PlaceAddon(m_From, m_Loc, false, true); + break; + case 2: + m_Deed.PlaceAddon(m_From, m_Loc, true, false); + break; + } + } } - } } - } } diff --git a/Projects/UOContent/Misc/Gifts/Winter2004/PileOfGlacialSnow.cs b/Projects/UOContent/Misc/Gifts/Winter2004/PileOfGlacialSnow.cs index 04fa176ec..69e09d85a 100644 --- a/Projects/UOContent/Misc/Gifts/Winter2004/PileOfGlacialSnow.cs +++ b/Projects/UOContent/Misc/Gifts/Winter2004/PileOfGlacialSnow.cs @@ -4,146 +4,148 @@ using Server.Targeting; namespace Server.Items { - public class PileOfGlacialSnow : Item - { - [Constructible] - public PileOfGlacialSnow() : base(0x913) + public class PileOfGlacialSnow : Item { - Hue = 0x480; - Weight = 1.0; - LootType = LootType.Blessed; - } - - public PileOfGlacialSnow(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1070874; // a Pile of Glacial Snow - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version == 0) - { - Weight = 1.0; - LootType = LootType.Blessed; - } - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - LabelTo(from, 1070880); // Winter 2004 - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1070880); // Winter 2004 - } - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042010); // You must have the object in your backpack to use it. - } - else if (from.Mounted) - { - from.SendLocalizedMessage(1010097); // You cannot use this while mounted. - } - else if (from.CanBeginAction()) - { - from.SendLocalizedMessage(1005575); // You carefully pack the snow into a ball... - from.Target = new SnowTarget(from, this); - } - else - { - from.SendLocalizedMessage(1005574); // The snow is not ready to be packed yet. Keep trying. - } - } - - private class InternalTimer : Timer - { - private readonly Mobile m_From; - - public InternalTimer(Mobile from) : base(TimeSpan.FromSeconds(5.0)) => m_From = from; - - protected override void OnTick() - { - m_From.EndAction(); - } - } - - private class SnowTarget : Target - { - private Item m_Snow; - private Mobile m_Thrower; - - public SnowTarget(Mobile thrower, Item snow) : base(10, false, TargetFlags.None) - { - m_Thrower = thrower; - m_Snow = snow; - } - - protected override void OnTarget(Mobile from, object target) - { - if (target == from) + [Constructible] + public PileOfGlacialSnow() : base(0x913) { - from.SendLocalizedMessage(1005576); // You can't throw this at yourself. + Hue = 0x480; + Weight = 1.0; + LootType = LootType.Blessed; } - else if (target is Mobile targ) + + public PileOfGlacialSnow(Serial serial) : base(serial) { - Container pack = targ.Backpack; + } - if (from.Region.IsPartOf() || targ.Region.IsPartOf()) - { - from.SendMessage("You may not throw snow here."); - } - else if (pack?.FindItemByType(new[] { typeof(SnowPile), typeof(PileOfGlacialSnow) }) != null) - { - if (from.BeginAction()) + public override int LabelNumber => 1070874; // a Pile of Glacial Snow + + 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) { - new InternalTimer(from).Start(); + Weight = 1.0; + LootType = LootType.Blessed; + } + } - from.PlaySound(0x145); + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); - from.Animate(9, 1, 1, true, false, 0); + LabelTo(from, 1070880); // Winter 2004 + } - targ.SendLocalizedMessage(1010572); // You have just been hit by a snowball! - from.SendLocalizedMessage(1010573); // You throw the snowball and hit the target! + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); - Effects.SendMovingEffect(from, targ, 0x36E4, 7, 0, false, true, 0x47F); + list.Add(1070880); // Winter 2004 + } + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042010); // You must have the object in your backpack to use it. + } + else if (from.Mounted) + { + from.SendLocalizedMessage(1010097); // You cannot use this while mounted. + } + else if (from.CanBeginAction()) + { + from.SendLocalizedMessage(1005575); // You carefully pack the snow into a ball... + from.Target = new SnowTarget(from, this); } else { - from.SendLocalizedMessage(1005574); // The snow is not ready to be packed yet. Keep trying. + from.SendLocalizedMessage(1005574); // The snow is not ready to be packed yet. Keep trying. } - } - else - { - from.SendLocalizedMessage( - 1005577); // You can only throw a snowball at something that can throw one back. - } } - else + + private class InternalTimer : Timer { - from.SendLocalizedMessage( - 1005577); // You can only throw a snowball at something that can throw one back. + private readonly Mobile m_From; + + public InternalTimer(Mobile from) : base(TimeSpan.FromSeconds(5.0)) => m_From = from; + + protected override void OnTick() + { + m_From.EndAction(); + } + } + + private class SnowTarget : Target + { + private Item m_Snow; + private Mobile m_Thrower; + + public SnowTarget(Mobile thrower, Item snow) : base(10, false, TargetFlags.None) + { + m_Thrower = thrower; + m_Snow = snow; + } + + protected override void OnTarget(Mobile from, object target) + { + if (target == from) + { + from.SendLocalizedMessage(1005576); // You can't throw this at yourself. + } + else if (target is Mobile targ) + { + var pack = targ.Backpack; + + if (from.Region.IsPartOf() || targ.Region.IsPartOf()) + { + from.SendMessage("You may not throw snow here."); + } + else if (pack?.FindItemByType(new[] { typeof(SnowPile), typeof(PileOfGlacialSnow) }) != null) + { + if (from.BeginAction()) + { + new InternalTimer(from).Start(); + + from.PlaySound(0x145); + + from.Animate(9, 1, 1, true, false, 0); + + targ.SendLocalizedMessage(1010572); // You have just been hit by a snowball! + from.SendLocalizedMessage(1010573); // You throw the snowball and hit the target! + + Effects.SendMovingEffect(from, targ, 0x36E4, 7, 0, false, true, 0x47F); + } + else + { + from.SendLocalizedMessage(1005574); // The snow is not ready to be packed yet. Keep trying. + } + } + else + { + from.SendLocalizedMessage( + 1005577 + ); // You can only throw a snowball at something that can throw one back. + } + } + else + { + from.SendLocalizedMessage( + 1005577 + ); // You can only throw a snowball at something that can throw one back. + } + } } - } } - } } diff --git a/Projects/UOContent/Misc/Gifts/Winter2004/SnowPile.cs b/Projects/UOContent/Misc/Gifts/Winter2004/SnowPile.cs index bee426f96..c0dd3b9d1 100644 --- a/Projects/UOContent/Misc/Gifts/Winter2004/SnowPile.cs +++ b/Projects/UOContent/Misc/Gifts/Winter2004/SnowPile.cs @@ -4,132 +4,134 @@ using Server.Targeting; namespace Server.Items { - public class SnowPile : Item - { - [Constructible] - public SnowPile() : base(0x913) + public class SnowPile : Item { - Hue = 0x481; - Weight = 1.0; - LootType = LootType.Blessed; - } - - public SnowPile(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1005578; // a pile of snow - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version == 0) - { - Weight = 1.0; - LootType = LootType.Blessed; - } - } - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042010); // You must have the object in your backpack to use it. - } - else if (from.Mounted) - { - from.SendLocalizedMessage(1010097); // You cannot use this while mounted. - } - else if (from.CanBeginAction()) - { - from.SendLocalizedMessage(1005575); // You carefully pack the snow into a ball... - from.Target = new SnowTarget(from, this); - } - else - { - from.SendLocalizedMessage(1005574); // The snow is not ready to be packed yet. Keep trying. - } - } - - private class InternalTimer : Timer - { - private readonly Mobile m_From; - - public InternalTimer(Mobile from) : base(TimeSpan.FromSeconds(5.0)) => m_From = from; - - protected override void OnTick() - { - m_From.EndAction(); - } - } - - private class SnowTarget : Target - { - private Item m_Snow; - private Mobile m_Thrower; - - public SnowTarget(Mobile thrower, Item snow) : base(10, false, TargetFlags.None) - { - m_Thrower = thrower; - m_Snow = snow; - } - - protected override void OnTarget(Mobile from, object target) - { - if (target == from) + [Constructible] + public SnowPile() : base(0x913) { - from.SendLocalizedMessage(1005576); // You can't throw this at yourself. + Hue = 0x481; + Weight = 1.0; + LootType = LootType.Blessed; } - else if (target is Mobile targ) + + public SnowPile(Serial serial) : base(serial) { - Container pack = targ.Backpack; + } - if (from.Region.IsPartOf() || targ.Region.IsPartOf()) - { - from.SendMessage("You may not throw snow here."); - } - else if (pack?.FindItemByType(new[] { typeof(SnowPile), typeof(PileOfGlacialSnow) }) != null) - { - if (from.BeginAction()) + public override int LabelNumber => 1005578; // a pile of snow + + 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) { - new InternalTimer(from).Start(); + Weight = 1.0; + LootType = LootType.Blessed; + } + } - from.PlaySound(0x145); - - from.Animate(9, 1, 1, true, false, 0); - - targ.SendLocalizedMessage(1010572); // You have just been hit by a snowball! - from.SendLocalizedMessage(1010573); // You throw the snowball and hit the target! - - Effects.SendMovingEffect(from, targ, 0x36E4, 7, 0, false, true, 0x480); + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042010); // You must have the object in your backpack to use it. + } + else if (from.Mounted) + { + from.SendLocalizedMessage(1010097); // You cannot use this while mounted. + } + else if (from.CanBeginAction()) + { + from.SendLocalizedMessage(1005575); // You carefully pack the snow into a ball... + from.Target = new SnowTarget(from, this); } else { - from.SendLocalizedMessage(1005574); // The snow is not ready to be packed yet. Keep trying. + from.SendLocalizedMessage(1005574); // The snow is not ready to be packed yet. Keep trying. } - } - else - { - from.SendLocalizedMessage( - 1005577); // You can only throw a snowball at something that can throw one back. - } } - else + + private class InternalTimer : Timer { - from.SendLocalizedMessage( - 1005577); // You can only throw a snowball at something that can throw one back. + private readonly Mobile m_From; + + public InternalTimer(Mobile from) : base(TimeSpan.FromSeconds(5.0)) => m_From = from; + + protected override void OnTick() + { + m_From.EndAction(); + } + } + + private class SnowTarget : Target + { + private Item m_Snow; + private Mobile m_Thrower; + + public SnowTarget(Mobile thrower, Item snow) : base(10, false, TargetFlags.None) + { + m_Thrower = thrower; + m_Snow = snow; + } + + protected override void OnTarget(Mobile from, object target) + { + if (target == from) + { + from.SendLocalizedMessage(1005576); // You can't throw this at yourself. + } + else if (target is Mobile targ) + { + var pack = targ.Backpack; + + if (from.Region.IsPartOf() || targ.Region.IsPartOf()) + { + from.SendMessage("You may not throw snow here."); + } + else if (pack?.FindItemByType(new[] { typeof(SnowPile), typeof(PileOfGlacialSnow) }) != null) + { + if (from.BeginAction()) + { + new InternalTimer(from).Start(); + + from.PlaySound(0x145); + + from.Animate(9, 1, 1, true, false, 0); + + targ.SendLocalizedMessage(1010572); // You have just been hit by a snowball! + from.SendLocalizedMessage(1010573); // You throw the snowball and hit the target! + + Effects.SendMovingEffect(from, targ, 0x36E4, 7, 0, false, true, 0x480); + } + else + { + from.SendLocalizedMessage(1005574); // The snow is not ready to be packed yet. Keep trying. + } + } + else + { + from.SendLocalizedMessage( + 1005577 + ); // You can only throw a snowball at something that can throw one back. + } + } + else + { + from.SendLocalizedMessage( + 1005577 + ); // You can only throw a snowball at something that can throw one back. + } + } } - } } - } } diff --git a/Projects/UOContent/Misc/Gifts/Winter2004/SnowyTree.cs b/Projects/UOContent/Misc/Gifts/Winter2004/SnowyTree.cs index 2385f0ea5..c9c038acc 100644 --- a/Projects/UOContent/Misc/Gifts/Winter2004/SnowyTree.cs +++ b/Projects/UOContent/Misc/Gifts/Winter2004/SnowyTree.cs @@ -1,44 +1,44 @@ namespace Server.Items { - public class SnowyTree : Item - { - [Constructible] - public SnowyTree() : base(0x2377) + public class SnowyTree : Item { - Weight = 1.0; - LootType = LootType.Blessed; + [Constructible] + public SnowyTree() : base(0x2377) + { + Weight = 1.0; + LootType = LootType.Blessed; + } + + public SnowyTree(Serial serial) : base(serial) + { + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + LabelTo(from, 1070880); // Winter 2004 + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1070880); // Winter 2004 + } + + 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 SnowyTree(Serial serial) : base(serial) - { - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - LabelTo(from, 1070880); // Winter 2004 - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1070880); // Winter 2004 - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Misc/Gifts/Winter2004/Winter2004.cs b/Projects/UOContent/Misc/Gifts/Winter2004/Winter2004.cs index ee1b13185..747b4e328 100644 --- a/Projects/UOContent/Misc/Gifts/Winter2004/Winter2004.cs +++ b/Projects/UOContent/Misc/Gifts/Winter2004/Winter2004.cs @@ -3,42 +3,42 @@ using Server.Items; namespace Server.Misc { - public class WinterGiftGiver2004 : GiftGiver - { - public override DateTime Start => new DateTime(2004, 12, 24); - public override DateTime Finish => new DateTime(2005, 1, 1); - - public static void Initialize() + public class WinterGiftGiver2004 : GiftGiver { - GiftGiving.Register(new WinterGiftGiver2004()); + public override DateTime Start => new DateTime(2004, 12, 24); + public override DateTime Finish => new DateTime(2005, 1, 1); + + public static void Initialize() + { + GiftGiving.Register(new WinterGiftGiver2004()); + } + + public override void GiveGift(Mobile mob) + { + var box = new GiftBox(); + + box.DropItem(new MistletoeDeed()); + box.DropItem(new PileOfGlacialSnow()); + box.DropItem(new LightOfTheWinterSolstice()); + + var random = Utility.Random(100); + + if (random < 60) + box.DropItem(new DecorativeTopiary()); + else if (random < 84) + box.DropItem(new FestiveCactus()); + else + box.DropItem(new SnowyTree()); + + switch (GiveGift(mob, box)) + { + case GiftResult.Backpack: + mob.SendMessage(0x482, "Happy Holidays from the team! Gift items have been placed in your backpack."); + break; + case GiftResult.BankBox: + mob.SendMessage(0x482, "Happy Holidays from the team! Gift items have been placed in your bank box."); + break; + } + } } - - public override void GiveGift(Mobile mob) - { - GiftBox box = new GiftBox(); - - box.DropItem(new MistletoeDeed()); - box.DropItem(new PileOfGlacialSnow()); - box.DropItem(new LightOfTheWinterSolstice()); - - int random = Utility.Random(100); - - if (random < 60) - box.DropItem(new DecorativeTopiary()); - else if (random < 84) - box.DropItem(new FestiveCactus()); - else - box.DropItem(new SnowyTree()); - - switch (GiveGift(mob, box)) - { - case GiftResult.Backpack: - mob.SendMessage(0x482, "Happy Holidays from the team! Gift items have been placed in your backpack."); - break; - case GiftResult.BankBox: - mob.SendMessage(0x482, "Happy Holidays from the team! Gift items have been placed in your bank box."); - break; - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Misc/Guild.cs b/Projects/UOContent/Misc/Guild.cs index 930a2022e..ad8ffff75 100644 --- a/Projects/UOContent/Misc/Guild.cs +++ b/Projects/UOContent/Misc/Guild.cs @@ -9,1407 +9,1455 @@ using Server.Targeting; namespace Server.Guilds { - [Flags] - public enum RankFlags - { - None = 0x00000000, - CanInvitePlayer = 0x00000001, - AccessGuildItems = 0x00000002, - RemoveLowestRank = 0x00000004, - RemovePlayers = 0x00000008, - CanPromoteDemote = 0x00000010, - ControlWarStatus = 0x00000020, - AllianceControl = 0x00000040, - CanSetGuildTitle = 0x00000080, - CanVote = 0x00000100, - - All = Member | CanInvitePlayer | RemovePlayers | CanPromoteDemote | ControlWarStatus | AllianceControl | - CanSetGuildTitle, - Member = RemoveLowestRank | AccessGuildItems | CanVote - } - - public class RankDefinition - { - public static RankDefinition[] Ranks = + [Flags] + public enum RankFlags { - new RankDefinition(1062963, 0, RankFlags.None), // Ronin - new RankDefinition(1062962, 1, RankFlags.Member), // Member - new RankDefinition(1062961, 2, - RankFlags.Member | RankFlags.RemovePlayers | RankFlags.CanInvitePlayer | RankFlags.CanSetGuildTitle | - RankFlags.CanPromoteDemote), // Emmissary - new RankDefinition(1062960, 3, RankFlags.Member | RankFlags.ControlWarStatus), // Warlord - new RankDefinition(1062959, 4, RankFlags.All) // Leader - }; + None = 0x00000000, + CanInvitePlayer = 0x00000001, + AccessGuildItems = 0x00000002, + RemoveLowestRank = 0x00000004, + RemovePlayers = 0x00000008, + CanPromoteDemote = 0x00000010, + ControlWarStatus = 0x00000020, + AllianceControl = 0x00000040, + CanSetGuildTitle = 0x00000080, + CanVote = 0x00000100, - public RankDefinition(TextDefinition name, int rank, RankFlags flags) - { - Name = name; - Rank = rank; - Flags = flags; + All = Member | CanInvitePlayer | RemovePlayers | CanPromoteDemote | ControlWarStatus | AllianceControl | + CanSetGuildTitle, + Member = RemoveLowestRank | AccessGuildItems | CanVote } - public static RankDefinition Leader => Ranks[4]; - public static RankDefinition Member => Ranks[1]; - public static RankDefinition Lowest => Ranks[0]; - - public TextDefinition Name { get; } - - public int Rank { get; } - - public RankFlags Flags { get; private set; } - - public bool GetFlag(RankFlags flag) => (Flags & flag) != 0; - - public void SetFlag(RankFlags flag, bool value) + public class RankDefinition { - if (value) - Flags |= flag; - else - Flags &= ~flag; - } - } - - public class AllianceInfo - { - private Guild m_Leader; - private readonly List m_Members; - private readonly List m_PendingMembers; - - public AllianceInfo(Guild leader, string name, Guild partner) - { - m_Leader = leader; - Name = name; - - m_Members = new List(); - m_PendingMembers = new List(); - - leader.Alliance = this; - partner.Alliance = this; - - if (!Alliances.ContainsKey(Name.ToLower())) - Alliances.Add(Name.ToLower(), this); - } - - public AllianceInfo(IGenericReader reader) - { - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Name = reader.ReadString(); - m_Leader = reader.ReadGuild() as Guild; - - m_Members = reader.ReadStrongGuildList(); - m_PendingMembers = reader.ReadStrongGuildList(); - - break; - } - } - } - - public static Dictionary Alliances { get; } = new Dictionary(); - - public string Name { get; } - - public Guild Leader - { - get - { - CheckLeader(); - return m_Leader; - } - set - { - if (m_Leader != value && value != null) - AllianceMessage(1070765, value.Name); // Your Alliance is now led by ~1_GUILDNAME~ - - m_Leader = value; - - if (m_Leader == null) - CalculateAllianceLeader(); - } - } - - public void CalculateAllianceLeader() - { - m_Leader = m_Members.Count >= 2 ? m_Members.RandomElement() : null; - } - - public void CheckLeader() - { - if (m_Leader?.Disbanded != false) - { - CalculateAllianceLeader(); - - if (m_Leader == null) - Disband(); - } - } - - public bool IsPendingMember(Guild g) - { - if (g.Alliance != this) - return false; - - return m_PendingMembers.Contains(g); - } - - public bool IsMember(Guild g) - { - if (g.Alliance != this) - return false; - - return m_Members.Contains(g); - } - - public void Serialize(IGenericWriter writer) - { - writer.Write(0); // Version - - writer.Write(Name); - writer.Write(m_Leader); - - writer.WriteGuildList(m_Members, true); - writer.WriteGuildList(m_PendingMembers, true); - - if (!Alliances.ContainsKey(Name.ToLower())) - Alliances.Add(Name.ToLower(), this); - } - - public void AddPendingGuild(Guild g) - { - if (g.Alliance != this || m_PendingMembers.Contains(g) || m_Members.Contains(g)) - return; - - m_PendingMembers.Add(g); - } - - public void TurnToMember(Guild g) - { - if (g.Alliance != this || !m_PendingMembers.Contains(g) || m_Members.Contains(g)) - return; - - g.GuildMessage(1070760, Name); // Your Guild has joined the ~1_ALLIANCENAME~ Alliance. - AllianceMessage(1070761, g.Name); // A new Guild has joined your Alliance: ~1_GUILDNAME~ - - m_PendingMembers.Remove(g); - m_Members.Add(g); - g.Alliance.InvalidateMemberProperties(); - } - - public void RemoveGuild(Guild g) - { - if (m_PendingMembers.Contains(g)) m_PendingMembers.Remove(g); - - if (m_Members.Contains(g)) // Sanity, just incase someone with a custom script adds a character to BOTH arrays - { - m_Members.Remove(g); - g.InvalidateMemberProperties(); - - g.GuildMessage(1070763, Name); // Your Guild has been removed from the ~1_ALLIANCENAME~ Alliance. - AllianceMessage(1070764, g.Name); // A Guild has left your Alliance: ~1_GUILDNAME~ - } - - // g.Alliance = null; //NO G.Alliance call here. Set the Guild's Alliance to null, if you JUST use RemoveGuild, it removes it from the alliance, but doesn't remove the link from the guild to the alliance. setting g.Alliance will call this method. - // to check on OSI: have 3 guilds, make 2 of them a member, one pending. remove one of the memebers. alliance still exist? - // ANSWER: NO - - if (g == m_Leader) CalculateAllianceLeader(); - - if (m_Members.Count < 2) - Disband(); - } - - public void Disband() - { - AllianceMessage(1070762); // Your Alliance has dissolved. - - for (int i = 0; i < m_PendingMembers.Count; i++) - m_PendingMembers[i].Alliance = null; - - for (int i = 0; i < m_Members.Count; i++) - m_Members[i].Alliance = null; - - if (Alliances.TryGetValue(Name.ToLower(), out AllianceInfo aInfo) && aInfo == this) - Alliances.Remove(Name.ToLower()); - } - - public void InvalidateMemberProperties(bool onlyOPL = false) - { - for (int i = 0; i < m_Members.Count; i++) - { - Guild g = m_Members[i]; - - g.InvalidateMemberProperties(onlyOPL); - } - } - - public void InvalidateMemberNotoriety() - { - for (int i = 0; i < m_Members.Count; i++) - m_Members[i].InvalidateMemberNotoriety(); - } - - public class AllianceRosterGump : GuildDiplomacyGump - { - private readonly AllianceInfo m_Alliance; - - public AllianceRosterGump(PlayerMobile pm, Guild g, AllianceInfo alliance) : base(pm, g, true, "", 0, - alliance.m_Members, alliance.Name) => - m_Alliance = alliance; - - public AllianceRosterGump(PlayerMobile pm, Guild g, AllianceInfo alliance, IComparer currentComparer, - bool ascending, string filter, int startNumber) : base(pm, g, currentComparer, ascending, filter, - startNumber, alliance.m_Members, alliance.Name) => - m_Alliance = alliance; - - protected override bool AllowAdvancedSearch => false; - - public override Gump GetResentGump(PlayerMobile pm, Guild g, IComparer comparer, bool ascending, - string filter, int startNumber) => - new AllianceRosterGump(pm, g, m_Alliance, comparer, ascending, filter, startNumber); - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID != 8) // So that they can't get to the AdvancedSearch button - base.OnResponse(sender, info); - } - } - - public void AllianceMessage(int num, bool append, string format, params object[] args) - { - AllianceMessage(num, append, string.Format(format, args)); - } - - public void AllianceMessage(int number) - { - for (int i = 0; i < m_Members.Count; ++i) - m_Members[i].GuildMessage(number); - } - - public void AllianceMessage(int number, string args, int hue = 0x3B2) - { - for (int i = 0; i < m_Members.Count; ++i) - m_Members[i].GuildMessage(number, args, hue); - } - - public void AllianceMessage(int number, bool append, string affix, string args = "", int hue = 0x3B2) - { - for (int i = 0; i < m_Members.Count; ++i) - m_Members[i].GuildMessage(number, append, affix, args, hue); - } - - public void AllianceTextMessage(string text) - { - AllianceTextMessage(0x3B2, text); - } - - public void AllianceTextMessage(string format, params object[] args) - { - AllianceTextMessage(0x3B2, string.Format(format, args)); - } - - public void AllianceTextMessage(int hue, string text) - { - for (int i = 0; i < m_Members.Count; ++i) - m_Members[i].GuildTextMessage(hue, text); - } - - public void AllianceTextMessage(int hue, string format, params object[] args) - { - AllianceTextMessage(hue, string.Format(format, args)); - } - - public void AllianceChat(Mobile from, int hue, string text) - { - Packet p = null; - for (int i = 0; i < m_Members.Count; i++) - { - Guild g = m_Members[i]; - - for (int j = 0; j < g.Members.Count; j++) + public static RankDefinition[] Ranks = { - Mobile m = g.Members[j]; + new RankDefinition(1062963, 0, RankFlags.None), // Ronin + new RankDefinition(1062962, 1, RankFlags.Member), // Member + new RankDefinition( + 1062961, + 2, + RankFlags.Member | RankFlags.RemovePlayers | RankFlags.CanInvitePlayer | RankFlags.CanSetGuildTitle | + RankFlags.CanPromoteDemote + ), // Emmissary + new RankDefinition(1062960, 3, RankFlags.Member | RankFlags.ControlWarStatus), // Warlord + new RankDefinition(1062959, 4, RankFlags.All) // Leader + }; - NetState state = m.NetState; - - if (state != null) - { - p ??= Packet.Acquire(new UnicodeMessage(from.Serial, from.Body, MessageType.Alliance, hue, 3, from.Language, from.Name, text)); - - state.Send(p); - } - } - } - - Packet.Release(p); - } - - public void AllianceChat(Mobile from, string text) - { - PlayerMobile pm = from as PlayerMobile; - - AllianceChat(from, pm?.AllianceMessageHue ?? 0x3B2, text); - } - } - - public enum WarStatus - { - InProgress = -1, - Win, - Lose, - Draw, - Pending - } - - public class WarDeclaration - { - public WarDeclaration(Guild g, Guild opponent, int maxKills, TimeSpan warLength, bool warRequester) - { - Guild = g; - MaxKills = maxKills; - Opponent = opponent; - WarLength = warLength; - WarRequester = warRequester; - } - - public WarDeclaration(IGenericReader reader) - { - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Kills = reader.ReadInt(); - MaxKills = reader.ReadInt(); - - WarLength = reader.ReadTimeSpan(); - WarBeginning = reader.ReadDateTime(); - - Guild = reader.ReadGuild() as Guild; - Opponent = reader.ReadGuild() as Guild; - - WarRequester = reader.ReadBool(); - - break; - } - } - } - - public int Kills { get; set; } - - public int MaxKills { get; set; } - - public TimeSpan WarLength { get; set; } - - public Guild Opponent { get; } - - public Guild Guild { get; } - - public DateTime WarBeginning { get; set; } - - public bool WarRequester { get; set; } - - public WarStatus Status - { - get - { - if (Opponent?.Disbanded != false) - return WarStatus.Win; - - if (Guild?.Disbanded != false) - return WarStatus.Lose; - - WarDeclaration w = Opponent.FindActiveWar(Guild); - - if (Opponent.FindPendingWar(Guild) != null && Guild.FindPendingWar(Opponent) != null) - return WarStatus.Pending; - - if (w == null) - return WarStatus.Win; - - if (WarLength != TimeSpan.Zero && WarBeginning + WarLength < DateTime.UtcNow) + public RankDefinition(TextDefinition name, int rank, RankFlags flags) { - if (Kills > w.Kills) - return WarStatus.Win; - - return Kills < w.Kills ? WarStatus.Lose : WarStatus.Draw; + Name = name; + Rank = rank; + Flags = flags; } - if (MaxKills > 0) + public static RankDefinition Leader => Ranks[4]; + public static RankDefinition Member => Ranks[1]; + public static RankDefinition Lowest => Ranks[0]; + + public TextDefinition Name { get; } + + public int Rank { get; } + + public RankFlags Flags { get; private set; } + + public bool GetFlag(RankFlags flag) => (Flags & flag) != 0; + + public void SetFlag(RankFlags flag, bool value) { - if (Kills >= MaxKills) - return WarStatus.Win; - if (w.Kills >= w.MaxKills) - return WarStatus.Lose; - } - - return WarStatus.InProgress; - } - } - - public void Serialize(IGenericWriter writer) - { - writer.Write(0); // version - - writer.Write(Kills); - writer.Write(MaxKills); - - writer.Write(WarLength); - writer.Write(WarBeginning); - - writer.Write(Guild); - writer.Write(Opponent); - - writer.Write(WarRequester); - } - } - - public class WarTimer : Timer - { - public WarTimer() : base(TimeSpan.FromMinutes(1.0), TimeSpan.FromMinutes(1.0)) => Priority = TimerPriority.FiveSeconds; - - public static void Initialize() - { - if (Guild.NewGuildSystem) - new WarTimer().Start(); - } - - protected override void OnTick() - { - foreach (BaseGuild g in BaseGuild.List.Values) - (g as Guild)?.CheckExpiredWars(); - } - } - - public class Guild : BaseGuild - { - public static readonly int RegistrationFee = 25000; - public static readonly int AbbrevLimit = 4; - public static readonly int NameLimit = 40; - public static readonly int MajorityPercentage = 66; - public static readonly TimeSpan InactiveTime = TimeSpan.FromDays(30); - - public Guild(Mobile leader, string name, string abbreviation) - { - m_Leader = leader; - - Members = new List(); - Allies = new List(); - Enemies = new List(); - WarDeclarations = new List(); - WarInvitations = new List(); - AllyDeclarations = new List(); - AllyInvitations = new List(); - Candidates = new List(); - Accepted = new List(); - - LastFealty = DateTime.UtcNow; - - m_Name = name; - m_Abbreviation = abbreviation; - - TypeLastChange = DateTime.MinValue; - - AddMember(m_Leader); - - if (m_Leader is PlayerMobile mobile) - mobile.GuildRank = RankDefinition.Leader; - - AcceptedWars = new List(); - PendingWars = new List(); - } - - public Guild(uint id) : base(id) // serialization ctor - { - } - - public static bool NewGuildSystem => Core.SE; - public static bool OrderChaos => !Core.SE; - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Leader - { - get - { - if (Disbanded || m_Leader.Guild != this) - CalculateGuildmaster(); - - return m_Leader; - } - set - { - if (value != null) - AddMember(value); // Also removes from old guild. - - if (m_Leader is PlayerMobile leader && leader.Guild == this) - leader.GuildRank = RankDefinition.Member; - - m_Leader = value; - - if (m_Leader is PlayerMobile mobile) - mobile.GuildRank = RankDefinition.Leader; - } - } - - public override bool Disbanded => m_Leader?.Deleted != false; - - public static void Configure() - { - EventSink.CreateGuild += EventSink_CreateGuild; - EventSink.GuildGumpRequest += EventSink_GuildGumpRequest; - - CommandSystem.Register("GuildProps", AccessLevel.Counselor, GuildProps_OnCommand); - } - - public void InvalidateMemberProperties(bool onlyOPL = false) - { - for (int i = 0; i < Members?.Count; i++) - { - Mobile m = Members[i]; - m.InvalidateProperties(); - - if (!onlyOPL) - m.Delta(MobileDelta.Noto); - } - } - - public void InvalidateMemberNotoriety() - { - for (int i = 0; i < Members?.Count; i++) - Members[i].Delta(MobileDelta.Noto); - } - - public void InvalidateWarNotoriety() - { - Guild g = GetAllianceLeader(this); - - if (g.Alliance != null) - g.Alliance.InvalidateMemberNotoriety(); - else - g.InvalidateMemberNotoriety(); - - if (g.AcceptedWars == null) - return; - - foreach (WarDeclaration warDec in g.AcceptedWars) - { - Guild opponent = warDec.Opponent; - - if (opponent.Alliance != null) - opponent.Alliance.InvalidateMemberNotoriety(); - else - opponent.InvalidateMemberNotoriety(); - } - } - - public override void OnDelete(Mobile mob) - { - RemoveMember(mob); - } - - public void Disband() - { - m_Leader = null; - - List.Remove(Serial); - - foreach (Mobile m in Members) - { - m.SendLocalizedMessage(502131); // Your guild has disbanded. - - if (m is PlayerMobile mobile) - mobile.GuildRank = RankDefinition.Lowest; - - m.Guild = null; - } - - Members.Clear(); - - for (int i = Allies.Count - 1; i >= 0; --i) - if (i < Allies.Count) - RemoveAlly(Allies[i]); - - for (int i = Enemies.Count - 1; i >= 0; --i) - if (i < Enemies.Count) - RemoveEnemy(Enemies[i]); - - if (!NewGuildSystem) - Guildstone?.Delete(); - - Guildstone = null; - - CheckExpiredWars(); - - Alliance = null; - } - - [Usage("GuildProps")] - [Description( - "Opens a menu where you can view and edit guild properties of a targeted player or guild stone. If the new Guild system is active, also brings up the guild gump.")] - private static void GuildProps_OnCommand(CommandEventArgs e) - { - string arg = e.ArgString.Trim(); - Mobile from = e.Mobile; - - if (arg.Length == 0) - { - e.Mobile.Target = new GuildPropsTarget(); - } - else - { - Guild g = uint.TryParse(arg, out uint id) - ? Find(id) as Guild - : FindByAbbrev(arg) as Guild ?? FindByName(arg) as Guild; - - if (g != null) - { - from.SendGump(new PropertiesGump(from, g)); - - if (NewGuildSystem && from.AccessLevel >= AccessLevel.GameMaster && from is PlayerMobile mobile) - mobile.SendGump(new GuildInfoGump(mobile, g)); - } - } - } - - private class GuildPropsTarget : Target - { - public GuildPropsTarget() : base(-1, true, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object o) - { - if (!BaseCommand.IsAccessible(from, o)) - { - from.SendLocalizedMessage(500447); // That is not accessible. - return; - } - - Guild g = null; - - if (o is Guildstone stone) - { - if (stone.Guild.Disbanded) - { - from.SendMessage("The guild associated with that Guildstone no longer exists"); - return; - } - - g = stone.Guild; - } - else if (o is Mobile mobile) - { - g = mobile.Guild as Guild; - } - - if (g == null) - { - from.SendMessage("That is not in a guild!"); - return; - } - - from.SendGump(new PropertiesGump(from, g)); - - if (NewGuildSystem && from.AccessLevel >= AccessLevel.GameMaster && from is PlayerMobile pm) - pm.SendGump(new GuildInfoGump(pm, g)); - } - } - - public static void EventSink_GuildGumpRequest(Mobile m) - { - if (!NewGuildSystem || !(m is PlayerMobile pm)) - return; - - if (pm.Guild == null) - pm.SendGump(new CreateGuildGump(pm)); - else - pm.SendGump(new GuildInfoGump(pm, pm.Guild as Guild)); - } - - public static void EventSink_CreateGuild(CreateGuildEventArgs args) - { - args.Guild = new Guild(args.Id); - } - - public AllianceInfo Alliance - { - get - { - if (m_AllianceInfo != null) - return m_AllianceInfo; - - return m_AllianceLeader?.m_AllianceInfo; - } - set - { - AllianceInfo current = Alliance; - - if (value == current) - return; - - current?.RemoveGuild(this); - - if (value != null) - { - if (value.Leader == this) - m_AllianceInfo = value; - else - m_AllianceLeader = value.Leader; - - value.AddPendingGuild(this); - } - else - { - m_AllianceInfo = null; - m_AllianceLeader = null; - } - } - } - - [CommandProperty(AccessLevel.Counselor)] - public string AllianceName => Alliance?.Name; - - [CommandProperty(AccessLevel.Counselor)] - public Guild AllianceLeader => Alliance?.Leader; - - [CommandProperty(AccessLevel.Counselor)] - public bool IsAllianceMember => Alliance?.IsMember(this) == true; - - [CommandProperty(AccessLevel.Counselor)] - public bool IsAlliancePendingMember => Alliance?.IsPendingMember(this) == true; - - public static Guild GetAllianceLeader(Guild g) - { - AllianceInfo alliance = g.Alliance; - - if (alliance?.Leader != null && alliance.IsMember(g)) - return alliance.Leader; - - return g; - } - - public List PendingWars { get; private set; } - - public List AcceptedWars { get; private set; } - - public WarDeclaration FindPendingWar(Guild g) - { - for (int i = 0; i < PendingWars.Count; i++) - { - WarDeclaration w = PendingWars[i]; - - if (w.Opponent == g) - return w; - } - - return null; - } - - public WarDeclaration FindActiveWar(Guild g) - { - for (int i = 0; i < AcceptedWars.Count; i++) - { - WarDeclaration w = AcceptedWars[i]; - - if (w.Opponent == g) - return w; - } - - return null; - } - - public void CheckExpiredWars() - { - for (int i = 0; i < AcceptedWars.Count; i++) - { - WarDeclaration w = AcceptedWars[i]; - Guild g = w.Opponent; - - WarStatus status = w.Status; - - if (status != WarStatus.InProgress) - { - AllianceInfo myAlliance = Alliance; - bool inAlliance = myAlliance?.IsMember(this) == true; - - AllianceInfo otherAlliance = g?.Alliance; - bool otherInAlliance = otherAlliance?.IsMember(this) == true; - - if (inAlliance) - { - myAlliance.AllianceMessage(1070739 + (int)status, - g == null ? "a deleted opponent" : otherInAlliance ? otherAlliance.Name : g.Name); - myAlliance.InvalidateMemberProperties(); - } - else - { - GuildMessage(1070739 + (int)status, - g == null ? "a deleted opponent" : otherInAlliance ? otherAlliance.Name : g.Name); - InvalidateMemberProperties(); - } - - AcceptedWars.Remove(w); - - if (g == null) - continue; - - if (status != WarStatus.Draw) - status = (WarStatus)((int)status + 1 % 2); - - if (otherInAlliance) - { - otherAlliance.AllianceMessage(1070739 + (int)status, inAlliance ? Alliance.Name : Name); - otherAlliance.InvalidateMemberProperties(); - } - else - { - g.GuildMessage(1070739 + (int)status, inAlliance ? Alliance.Name : Name); - g.InvalidateMemberProperties(); - } - - g.AcceptedWars.Remove(g.FindActiveWar(this)); - } - } - - for (int i = 0; i < PendingWars.Count; i++) - { - WarDeclaration w = PendingWars[i]; - Guild g = w.Opponent; - - if (w.Status != WarStatus.Pending) - { - // All sanity in here - PendingWars.Remove(w); - - g?.PendingWars.Remove(g.FindPendingWar(this)); - } - } - } - - public static void HandleDeath(Mobile victim, Mobile killer = null) - { - if (!NewGuildSystem) - return; - - killer ??= victim.FindMostRecentDamager(false); - - if (killer?.Guild == null || victim.Guild == null) - return; - - Guild victimGuild = GetAllianceLeader(victim.Guild as Guild); - Guild killerGuild = GetAllianceLeader(killer.Guild as Guild); - - WarDeclaration war = killerGuild.FindActiveWar(victimGuild); - - if (war == null) - return; - - war.Kills++; - - if (war.Opponent == victimGuild) - killerGuild.CheckExpiredWars(); - else - victimGuild.CheckExpiredWars(); - } - - private Mobile m_Leader; - - private string m_Name; - private string m_Abbreviation; - - private GuildType m_Type; - - private AllianceInfo m_AllianceInfo; - private Guild m_AllianceLeader; - - public bool IsMember(Mobile m) => Members.Contains(m); - - public bool IsAlly(Guild g) => NewGuildSystem ? Alliance?.IsMember(this) == true && Alliance.IsMember(g) : Allies.Contains(g); - - public bool IsEnemy(Guild g) => (Type != GuildType.Regular && g.Type != GuildType.Regular && Type != g.Type) || IsWar(g); - - public bool IsWar(Guild g) - { - if (g == null) - return false; - - if (!NewGuildSystem) - return Enemies.Contains(g); - - Guild guild = GetAllianceLeader(this); - Guild otherGuild = GetAllianceLeader(g); - - return guild.FindActiveWar(otherGuild) != null; - } - - public override void Serialize(IGenericWriter writer) - { - if (LastFealty + TimeSpan.FromDays(1.0) < DateTime.UtcNow) - CalculateGuildmaster(); - - CheckExpiredWars(); - - Alliance?.CheckLeader(); - - writer.Write(5); // version - - writer.Write(PendingWars.Count); - - for (int i = 0; i < PendingWars.Count; i++) PendingWars[i].Serialize(writer); - - writer.Write(AcceptedWars.Count); - - for (int i = 0; i < AcceptedWars.Count; i++) AcceptedWars[i].Serialize(writer); - - bool isAllianceLeader = m_AllianceLeader == null && m_AllianceInfo != null; - writer.Write(isAllianceLeader); - - if (isAllianceLeader) - m_AllianceInfo.Serialize(writer); - else - writer.Write(m_AllianceLeader); - - // - - writer.WriteGuildList(AllyDeclarations, true); - writer.WriteGuildList(AllyInvitations, true); - - writer.Write(TypeLastChange); - - writer.Write((int)m_Type); - - writer.Write(LastFealty); - - writer.Write(m_Leader); - writer.Write(m_Name); - writer.Write(m_Abbreviation); - - writer.WriteGuildList(Allies, true); - writer.WriteGuildList(Enemies, true); - writer.WriteGuildList(WarDeclarations, true); - writer.WriteGuildList(WarInvitations, true); - - writer.Write(Members, true); - writer.Write(Candidates, true); - writer.Write(Accepted, true); - - writer.Write(Guildstone); - writer.Write(Teleporter); - - writer.Write(Charter); - writer.Write(Website); - } - - public override void Deserialize(IGenericReader reader) - { - int version = reader.ReadInt(); - - switch (version) - { - case 5: - { - int count = reader.ReadInt(); - - PendingWars = new List(); - for (int i = 0; i < count; i++) PendingWars.Add(new WarDeclaration(reader)); - - count = reader.ReadInt(); - AcceptedWars = new List(); - for (int i = 0; i < count; i++) AcceptedWars.Add(new WarDeclaration(reader)); - - bool isAllianceLeader = reader.ReadBool(); - - if (isAllianceLeader) - m_AllianceInfo = new AllianceInfo(reader); + if (value) + Flags |= flag; else - m_AllianceLeader = reader.ReadGuild() as Guild; + Flags &= ~flag; + } + } - goto case 4; - } - case 4: - { - AllyDeclarations = reader.ReadStrongGuildList(); - AllyInvitations = reader.ReadStrongGuildList(); + public class AllianceInfo + { + private readonly List m_Members; + private readonly List m_PendingMembers; + private Guild m_Leader; - goto case 3; - } - case 3: - { - TypeLastChange = reader.ReadDateTime(); + public AllianceInfo(Guild leader, string name, Guild partner) + { + m_Leader = leader; + Name = name; - goto case 2; - } - case 2: - { - m_Type = (GuildType)reader.ReadInt(); + m_Members = new List(); + m_PendingMembers = new List(); - goto case 1; - } - case 1: - { - LastFealty = reader.ReadDateTime(); + leader.Alliance = this; + partner.Alliance = this; - goto case 0; - } - case 0: - { - m_Leader = reader.ReadMobile(); + if (!Alliances.ContainsKey(Name.ToLower())) + Alliances.Add(Name.ToLower(), this); + } + + public AllianceInfo(IGenericReader reader) + { + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Name = reader.ReadString(); + m_Leader = reader.ReadGuild() as Guild; + + m_Members = reader.ReadStrongGuildList(); + m_PendingMembers = reader.ReadStrongGuildList(); + + break; + } + } + } + + public static Dictionary Alliances { get; } = new Dictionary(); + + public string Name { get; } + + public Guild Leader + { + get + { + CheckLeader(); + return m_Leader; + } + set + { + if (m_Leader != value && value != null) + AllianceMessage(1070765, value.Name); // Your Alliance is now led by ~1_GUILDNAME~ + + m_Leader = value; + + if (m_Leader == null) + CalculateAllianceLeader(); + } + } + + public void CalculateAllianceLeader() + { + m_Leader = m_Members.Count >= 2 ? m_Members.RandomElement() : null; + } + + public void CheckLeader() + { + if (m_Leader?.Disbanded != false) + { + CalculateAllianceLeader(); + + if (m_Leader == null) + Disband(); + } + } + + public bool IsPendingMember(Guild g) + { + if (g.Alliance != this) + return false; + + return m_PendingMembers.Contains(g); + } + + public bool IsMember(Guild g) + { + if (g.Alliance != this) + return false; + + return m_Members.Contains(g); + } + + public void Serialize(IGenericWriter writer) + { + writer.Write(0); // Version + + writer.Write(Name); + writer.Write(m_Leader); + + writer.WriteGuildList(m_Members, true); + writer.WriteGuildList(m_PendingMembers, true); + + if (!Alliances.ContainsKey(Name.ToLower())) + Alliances.Add(Name.ToLower(), this); + } + + public void AddPendingGuild(Guild g) + { + if (g.Alliance != this || m_PendingMembers.Contains(g) || m_Members.Contains(g)) + return; + + m_PendingMembers.Add(g); + } + + public void TurnToMember(Guild g) + { + if (g.Alliance != this || !m_PendingMembers.Contains(g) || m_Members.Contains(g)) + return; + + g.GuildMessage(1070760, Name); // Your Guild has joined the ~1_ALLIANCENAME~ Alliance. + AllianceMessage(1070761, g.Name); // A new Guild has joined your Alliance: ~1_GUILDNAME~ + + m_PendingMembers.Remove(g); + m_Members.Add(g); + g.Alliance.InvalidateMemberProperties(); + } + + public void RemoveGuild(Guild g) + { + if (m_PendingMembers.Contains(g)) m_PendingMembers.Remove(g); + + if (m_Members.Contains(g)) // Sanity, just incase someone with a custom script adds a character to BOTH arrays + { + m_Members.Remove(g); + g.InvalidateMemberProperties(); + + g.GuildMessage(1070763, Name); // Your Guild has been removed from the ~1_ALLIANCENAME~ Alliance. + AllianceMessage(1070764, g.Name); // A Guild has left your Alliance: ~1_GUILDNAME~ + } + + // g.Alliance = null; //NO G.Alliance call here. Set the Guild's Alliance to null, if you JUST use RemoveGuild, it removes it from the alliance, but doesn't remove the link from the guild to the alliance. setting g.Alliance will call this method. + // to check on OSI: have 3 guilds, make 2 of them a member, one pending. remove one of the memebers. alliance still exist? + // ANSWER: NO + + if (g == m_Leader) CalculateAllianceLeader(); + + if (m_Members.Count < 2) + Disband(); + } + + public void Disband() + { + AllianceMessage(1070762); // Your Alliance has dissolved. + + for (var i = 0; i < m_PendingMembers.Count; i++) + m_PendingMembers[i].Alliance = null; + + for (var i = 0; i < m_Members.Count; i++) + m_Members[i].Alliance = null; + + if (Alliances.TryGetValue(Name.ToLower(), out var aInfo) && aInfo == this) + Alliances.Remove(Name.ToLower()); + } + + public void InvalidateMemberProperties(bool onlyOPL = false) + { + for (var i = 0; i < m_Members.Count; i++) + { + var g = m_Members[i]; + + g.InvalidateMemberProperties(onlyOPL); + } + } + + public void InvalidateMemberNotoriety() + { + for (var i = 0; i < m_Members.Count; i++) + m_Members[i].InvalidateMemberNotoriety(); + } + + public void AllianceMessage(int num, bool append, string format, params object[] args) + { + AllianceMessage(num, append, string.Format(format, args)); + } + + public void AllianceMessage(int number) + { + for (var i = 0; i < m_Members.Count; ++i) + m_Members[i].GuildMessage(number); + } + + public void AllianceMessage(int number, string args, int hue = 0x3B2) + { + for (var i = 0; i < m_Members.Count; ++i) + m_Members[i].GuildMessage(number, args, hue); + } + + public void AllianceMessage(int number, bool append, string affix, string args = "", int hue = 0x3B2) + { + for (var i = 0; i < m_Members.Count; ++i) + m_Members[i].GuildMessage(number, append, affix, args, hue); + } + + public void AllianceTextMessage(string text) + { + AllianceTextMessage(0x3B2, text); + } + + public void AllianceTextMessage(string format, params object[] args) + { + AllianceTextMessage(0x3B2, string.Format(format, args)); + } + + public void AllianceTextMessage(int hue, string text) + { + for (var i = 0; i < m_Members.Count; ++i) + m_Members[i].GuildTextMessage(hue, text); + } + + public void AllianceTextMessage(int hue, string format, params object[] args) + { + AllianceTextMessage(hue, string.Format(format, args)); + } + + public void AllianceChat(Mobile from, int hue, string text) + { + Packet p = null; + for (var i = 0; i < m_Members.Count; i++) + { + var g = m_Members[i]; + + for (var j = 0; j < g.Members.Count; j++) + { + var m = g.Members[j]; + + var state = m.NetState; + + if (state != null) + { + p ??= Packet.Acquire( + new UnicodeMessage( + from.Serial, + from.Body, + MessageType.Alliance, + hue, + 3, + from.Language, + from.Name, + text + ) + ); + + state.Send(p); + } + } + } + + Packet.Release(p); + } + + public void AllianceChat(Mobile from, string text) + { + var pm = from as PlayerMobile; + + AllianceChat(from, pm?.AllianceMessageHue ?? 0x3B2, text); + } + + public class AllianceRosterGump : GuildDiplomacyGump + { + private readonly AllianceInfo m_Alliance; + + public AllianceRosterGump(PlayerMobile pm, Guild g, AllianceInfo alliance) : base( + pm, + g, + true, + "", + 0, + alliance.m_Members, + alliance.Name + ) => + m_Alliance = alliance; + + public AllianceRosterGump( + PlayerMobile pm, Guild g, AllianceInfo alliance, IComparer currentComparer, + bool ascending, string filter, int startNumber + ) : base( + pm, + g, + currentComparer, + ascending, + filter, + startNumber, + alliance.m_Members, + alliance.Name + ) => + m_Alliance = alliance; + + protected override bool AllowAdvancedSearch => false; + + public override Gump GetResentGump( + PlayerMobile pm, Guild g, IComparer comparer, bool ascending, + string filter, int startNumber + ) => + new AllianceRosterGump(pm, g, m_Alliance, comparer, ascending, filter, startNumber); + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID != 8) // So that they can't get to the AdvancedSearch button + base.OnResponse(sender, info); + } + } + } + + public enum WarStatus + { + InProgress = -1, + Win, + Lose, + Draw, + Pending + } + + public class WarDeclaration + { + public WarDeclaration(Guild g, Guild opponent, int maxKills, TimeSpan warLength, bool warRequester) + { + Guild = g; + MaxKills = maxKills; + Opponent = opponent; + WarLength = warLength; + WarRequester = warRequester; + } + + public WarDeclaration(IGenericReader reader) + { + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Kills = reader.ReadInt(); + MaxKills = reader.ReadInt(); + + WarLength = reader.ReadTimeSpan(); + WarBeginning = reader.ReadDateTime(); + + Guild = reader.ReadGuild() as Guild; + Opponent = reader.ReadGuild() as Guild; + + WarRequester = reader.ReadBool(); + + break; + } + } + } + + public int Kills { get; set; } + + public int MaxKills { get; set; } + + public TimeSpan WarLength { get; set; } + + public Guild Opponent { get; } + + public Guild Guild { get; } + + public DateTime WarBeginning { get; set; } + + public bool WarRequester { get; set; } + + public WarStatus Status + { + get + { + if (Opponent?.Disbanded != false) + return WarStatus.Win; + + if (Guild?.Disbanded != false) + return WarStatus.Lose; + + var w = Opponent.FindActiveWar(Guild); + + if (Opponent.FindPendingWar(Guild) != null && Guild.FindPendingWar(Opponent) != null) + return WarStatus.Pending; + + if (w == null) + return WarStatus.Win; + + if (WarLength != TimeSpan.Zero && WarBeginning + WarLength < DateTime.UtcNow) + { + if (Kills > w.Kills) + return WarStatus.Win; + + return Kills < w.Kills ? WarStatus.Lose : WarStatus.Draw; + } + + if (MaxKills > 0) + { + if (Kills >= MaxKills) + return WarStatus.Win; + if (w.Kills >= w.MaxKills) + return WarStatus.Lose; + } + + return WarStatus.InProgress; + } + } + + public void Serialize(IGenericWriter writer) + { + writer.Write(0); // version + + writer.Write(Kills); + writer.Write(MaxKills); + + writer.Write(WarLength); + writer.Write(WarBeginning); + + writer.Write(Guild); + writer.Write(Opponent); + + writer.Write(WarRequester); + } + } + + public class WarTimer : Timer + { + public WarTimer() : base(TimeSpan.FromMinutes(1.0), TimeSpan.FromMinutes(1.0)) => + Priority = TimerPriority.FiveSeconds; + + public static void Initialize() + { + if (Guild.NewGuildSystem) + new WarTimer().Start(); + } + + protected override void OnTick() + { + foreach (var g in BaseGuild.List.Values) + (g as Guild)?.CheckExpiredWars(); + } + } + + public class Guild : BaseGuild + { + public static readonly int RegistrationFee = 25000; + public static readonly int AbbrevLimit = 4; + public static readonly int NameLimit = 40; + public static readonly int MajorityPercentage = 66; + public static readonly TimeSpan InactiveTime = TimeSpan.FromDays(30); + private string m_Abbreviation; + + private AllianceInfo m_AllianceInfo; + private Guild m_AllianceLeader; + + private Mobile m_Leader; + + private string m_Name; + + private GuildType m_Type; + + public Guild(Mobile leader, string name, string abbreviation) + { + m_Leader = leader; + + Members = new List(); + Allies = new List(); + Enemies = new List(); + WarDeclarations = new List(); + WarInvitations = new List(); + AllyDeclarations = new List(); + AllyInvitations = new List(); + Candidates = new List(); + Accepted = new List(); + + LastFealty = DateTime.UtcNow; + + m_Name = name; + m_Abbreviation = abbreviation; + + TypeLastChange = DateTime.MinValue; + + AddMember(m_Leader); if (m_Leader is PlayerMobile mobile) - mobile.GuildRank = RankDefinition.Leader; + mobile.GuildRank = RankDefinition.Leader; - m_Name = reader.ReadString(); - m_Abbreviation = reader.ReadString(); - - Allies = reader.ReadStrongGuildList(); - Enemies = reader.ReadStrongGuildList(); - WarDeclarations = reader.ReadStrongGuildList(); - WarInvitations = reader.ReadStrongGuildList(); - - Members = reader.ReadStrongMobileList(); - Candidates = reader.ReadStrongMobileList(); - Accepted = reader.ReadStrongMobileList(); - - Guildstone = reader.ReadItem(); - Teleporter = reader.ReadItem(); - - Charter = reader.ReadString(); - Website = reader.ReadString(); - - break; - } - } - - AllyDeclarations ??= new List(); - AllyInvitations ??= new List(); - AcceptedWars ??= new List(); - PendingWars ??= new List(); - - Timer.DelayCall(VerifyGuild_Callback); - } - - private void VerifyGuild_Callback() - { - if ((!NewGuildSystem && Guildstone == null) || Members.Count == 0) - Disband(); - - CheckExpiredWars(); - - AllianceInfo alliance = Alliance; - - alliance?.CheckLeader(); - - alliance = Alliance; // CheckLeader could possibly change the value of this.Alliance - - if (alliance?.IsMember(this) == false && !alliance.IsPendingMember(this)) // This block is there to fix a bug in the code in an older version. - Alliance = null; // Will call Alliance.RemoveGuild which will set it null & perform all the pertient checks as far as alliacne disbanding - } - - public void AddMember(Mobile m) - { - if (!Members.Contains(m)) - { - if (m.Guild != null && m.Guild != this) - ((Guild)m.Guild).RemoveMember(m); - - Members.Add(m); - m.Guild = this; - - m.GuildFealty = !NewGuildSystem ? m_Leader : null; - - if (m is PlayerMobile mobile) - mobile.GuildRank = RankDefinition.Lowest; - - ((Guild)m.Guild).InvalidateWarNotoriety(); - } - } - - public void RemoveMember(Mobile m, int message = 1018028) // You have been dismissed from your guild. - { - if (Members.Contains(m)) - { - Members.Remove(m); - - Guild guild = m.Guild as Guild; - - m.Guild = null; - - if (m is PlayerMobile mobile) - mobile.GuildRank = RankDefinition.Lowest; - - if (message > 0) - m.SendLocalizedMessage(message); - - if (m == m_Leader) - { - CalculateGuildmaster(); - - if (m_Leader == null) - Disband(); + AcceptedWars = new List(); + PendingWars = new List(); } - if (Members.Count == 0) - Disband(); - - guild?.InvalidateWarNotoriety(); - - m.Delta(MobileDelta.Noto); - } - } - - public void AddAlly(Guild g) - { - if (!Allies.Contains(g)) - { - Allies.Add(g); - - g.AddAlly(this); - } - } - - public void RemoveAlly(Guild g) - { - if (Allies.Contains(g)) - { - Allies.Remove(g); - - g.RemoveAlly(this); - } - } - - public void AddEnemy(Guild g) - { - if (!Enemies.Contains(g)) - { - Enemies.Add(g); - - g.AddEnemy(this); - } - } - - public void RemoveEnemy(Guild g) - { - if (Enemies.Contains(g)) - { - Enemies.Remove(g); - - g.RemoveEnemy(this); - } - } - - public void GuildMessage(int num, bool append, string format, params object[] args) - { - GuildMessage(num, append, string.Format(format, args)); - } - - public void GuildMessage(int number) - { - for (int i = 0; i < Members.Count; ++i) - Members[i].SendLocalizedMessage(number); - } - - public void GuildMessage(int number, string args, int hue = 0x3B2) - { - for (int i = 0; i < Members.Count; ++i) - Members[i].SendLocalizedMessage(number, args, hue); - } - - public void GuildMessage(int number, bool append, string affix, string args = "", int hue = 0x3B2) - { - for (int i = 0; i < Members.Count; ++i) - Members[i].SendLocalizedMessage(number, append, affix, args, hue); - } - - public void GuildTextMessage(string text) - { - GuildTextMessage(0x3B2, text); - } - - public void GuildTextMessage(string format, params object[] args) - { - GuildTextMessage(0x3B2, string.Format(format, args)); - } - - public void GuildTextMessage(int hue, string text) - { - for (int i = 0; i < Members.Count; ++i) - Members[i].SendMessage(hue, text); - } - - public void GuildTextMessage(int hue, string format, params object[] args) - { - GuildTextMessage(hue, string.Format(format, args)); - } - - public void GuildChat(Mobile from, int hue, string text) - { - Packet p = null; - for (int i = 0; i < Members.Count; i++) - { - Mobile m = Members[i]; - - NetState state = m.NetState; - - if (state != null) + public Guild(uint id) : base(id) // serialization ctor { - p ??= Packet.Acquire(new UnicodeMessage(from.Serial, from.Body, MessageType.Guild, hue, 3, from.Language, from.Name, text)); - - state.Send(p); - } - } - - Packet.Release(p); - } - - public void GuildChat(Mobile from, string text) - { - GuildChat(from, (from as PlayerMobile)?.GuildMessageHue ?? 0x3B2, text); - } - - public bool CanVote(Mobile m) => - (!NewGuildSystem || (m is PlayerMobile pm && pm.GuildRank.GetFlag(RankFlags.CanVote))) && - m?.Deleted == false && m.Guild == this; - - public bool CanBeVotedFor(Mobile m) => (!NewGuildSystem || (m is PlayerMobile pm && pm.LastOnline + InactiveTime >= DateTime.UtcNow)) && m?.Deleted == false && m.Guild == this; - - public void CalculateGuildmaster() - { - Dictionary votes = new Dictionary(); - - int votingMembers = 0; - - for (int i = 0; Members != null && i < Members.Count; ++i) - { - Mobile memb = Members[i]; - - if (!CanVote(memb)) - continue; - - Mobile m = memb.GuildFealty; - - if (!CanBeVotedFor(m)) - { - if (!Disbanded && m_Leader.Guild == this) - m = m_Leader; - else - m = memb; } - if (m == null) - continue; + public static bool NewGuildSystem => Core.SE; + public static bool OrderChaos => !Core.SE; - votes[m] = 1 + (votes.TryGetValue(m, out int v) ? v : 0); - votingMembers++; - } - - Mobile winner = null; - int highVotes = 0; - - foreach (KeyValuePair kvp in votes) - { - Mobile m = kvp.Key; - int val = kvp.Value; - - if (winner == null || val > highVotes) + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Leader { - winner = m; - highVotes = val; + get + { + if (Disbanded || m_Leader.Guild != this) + CalculateGuildmaster(); + + return m_Leader; + } + set + { + if (value != null) + AddMember(value); // Also removes from old guild. + + if (m_Leader is PlayerMobile leader && leader.Guild == this) + leader.GuildRank = RankDefinition.Member; + + m_Leader = value; + + if (m_Leader is PlayerMobile mobile) + mobile.GuildRank = RankDefinition.Leader; + } } - } - if (NewGuildSystem && highVotes * 100 / Math.Max(votingMembers, 1) < MajorityPercentage && !Disbanded && - winner != m_Leader && m_Leader.Guild == this) - winner = m_Leader; + public override bool Disbanded => m_Leader?.Deleted != false; - if (m_Leader != winner && winner != null) - GuildMessage(1018015, true, winner.Name); // Guild Message: Guildmaster changed to: - - Leader = winner; - LastFealty = DateTime.UtcNow; - } - - [CommandProperty(AccessLevel.GameMaster)] - public Item Guildstone { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Item Teleporter { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public override string Name - { - get => m_Name; - set - { - m_Name = value; - - InvalidateMemberProperties(true); - - Guildstone?.InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public string Website { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public override string Abbreviation - { - get => m_Abbreviation; - set - { - m_Abbreviation = value; - - InvalidateMemberProperties(true); - - Guildstone?.InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public string Charter { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public override GuildType Type - { - get => OrderChaos ? m_Type : GuildType.Regular; - set - { - if (m_Type != value) + public AllianceInfo Alliance { - m_Type = value; - TypeLastChange = DateTime.UtcNow; + get + { + if (m_AllianceInfo != null) + return m_AllianceInfo; - InvalidateMemberProperties(); + return m_AllianceLeader?.m_AllianceInfo; + } + set + { + var current = Alliance; + + if (value == current) + return; + + current?.RemoveGuild(this); + + if (value != null) + { + if (value.Leader == this) + m_AllianceInfo = value; + else + m_AllianceLeader = value.Leader; + + value.AddPendingGuild(this); + } + else + { + m_AllianceInfo = null; + m_AllianceLeader = null; + } + } + } + + [CommandProperty(AccessLevel.Counselor)] + public string AllianceName => Alliance?.Name; + + [CommandProperty(AccessLevel.Counselor)] + public Guild AllianceLeader => Alliance?.Leader; + + [CommandProperty(AccessLevel.Counselor)] + public bool IsAllianceMember => Alliance?.IsMember(this) == true; + + [CommandProperty(AccessLevel.Counselor)] + public bool IsAlliancePendingMember => Alliance?.IsPendingMember(this) == true; + + public List PendingWars { get; private set; } + + public List AcceptedWars { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Item Guildstone { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Item Teleporter { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public override string Name + { + get => m_Name; + set + { + m_Name = value; + + InvalidateMemberProperties(true); + + Guildstone?.InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public string Website { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public override string Abbreviation + { + get => m_Abbreviation; + set + { + m_Abbreviation = value; + + InvalidateMemberProperties(true); + + Guildstone?.InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public string Charter { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public override GuildType Type + { + get => OrderChaos ? m_Type : GuildType.Regular; + set + { + if (m_Type != value) + { + m_Type = value; + TypeLastChange = DateTime.UtcNow; + + InvalidateMemberProperties(); + } + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime LastFealty { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime TypeLastChange { get; private set; } + + public List Allies { get; private set; } + + public List Enemies { get; private set; } + + public List AllyDeclarations { get; private set; } + + public List AllyInvitations { get; private set; } + + public List WarDeclarations { get; private set; } + + public List WarInvitations { get; private set; } + + public List Candidates { get; private set; } + + public List Accepted { get; private set; } + + public List Members { get; private set; } + + public static void Configure() + { + EventSink.CreateGuild += EventSink_CreateGuild; + EventSink.GuildGumpRequest += EventSink_GuildGumpRequest; + + CommandSystem.Register("GuildProps", AccessLevel.Counselor, GuildProps_OnCommand); + } + + public void InvalidateMemberProperties(bool onlyOPL = false) + { + for (var i = 0; i < Members?.Count; i++) + { + var m = Members[i]; + m.InvalidateProperties(); + + if (!onlyOPL) + m.Delta(MobileDelta.Noto); + } + } + + public void InvalidateMemberNotoriety() + { + for (var i = 0; i < Members?.Count; i++) + Members[i].Delta(MobileDelta.Noto); + } + + public void InvalidateWarNotoriety() + { + var g = GetAllianceLeader(this); + + if (g.Alliance != null) + g.Alliance.InvalidateMemberNotoriety(); + else + g.InvalidateMemberNotoriety(); + + if (g.AcceptedWars == null) + return; + + foreach (var warDec in g.AcceptedWars) + { + var opponent = warDec.Opponent; + + if (opponent.Alliance != null) + opponent.Alliance.InvalidateMemberNotoriety(); + else + opponent.InvalidateMemberNotoriety(); + } + } + + public override void OnDelete(Mobile mob) + { + RemoveMember(mob); + } + + public void Disband() + { + m_Leader = null; + + List.Remove(Serial); + + foreach (var m in Members) + { + m.SendLocalizedMessage(502131); // Your guild has disbanded. + + if (m is PlayerMobile mobile) + mobile.GuildRank = RankDefinition.Lowest; + + m.Guild = null; + } + + Members.Clear(); + + for (var i = Allies.Count - 1; i >= 0; --i) + if (i < Allies.Count) + RemoveAlly(Allies[i]); + + for (var i = Enemies.Count - 1; i >= 0; --i) + if (i < Enemies.Count) + RemoveEnemy(Enemies[i]); + + if (!NewGuildSystem) + Guildstone?.Delete(); + + Guildstone = null; + + CheckExpiredWars(); + + Alliance = null; + } + + [Usage("GuildProps")] + [Description( + "Opens a menu where you can view and edit guild properties of a targeted player or guild stone. If the new Guild system is active, also brings up the guild gump." + )] + private static void GuildProps_OnCommand(CommandEventArgs e) + { + var arg = e.ArgString.Trim(); + var from = e.Mobile; + + if (arg.Length == 0) + { + e.Mobile.Target = new GuildPropsTarget(); + } + else + { + var g = uint.TryParse(arg, out var id) + ? Find(id) as Guild + : FindByAbbrev(arg) as Guild ?? FindByName(arg) as Guild; + + if (g != null) + { + from.SendGump(new PropertiesGump(from, g)); + + if (NewGuildSystem && from.AccessLevel >= AccessLevel.GameMaster && from is PlayerMobile mobile) + mobile.SendGump(new GuildInfoGump(mobile, g)); + } + } + } + + public static void EventSink_GuildGumpRequest(Mobile m) + { + if (!NewGuildSystem || !(m is PlayerMobile pm)) + return; + + if (pm.Guild == null) + pm.SendGump(new CreateGuildGump(pm)); + else + pm.SendGump(new GuildInfoGump(pm, pm.Guild as Guild)); + } + + public static void EventSink_CreateGuild(CreateGuildEventArgs args) + { + args.Guild = new Guild(args.Id); + } + + public static Guild GetAllianceLeader(Guild g) + { + var alliance = g.Alliance; + + if (alliance?.Leader != null && alliance.IsMember(g)) + return alliance.Leader; + + return g; + } + + public WarDeclaration FindPendingWar(Guild g) + { + for (var i = 0; i < PendingWars.Count; i++) + { + var w = PendingWars[i]; + + if (w.Opponent == g) + return w; + } + + return null; + } + + public WarDeclaration FindActiveWar(Guild g) + { + for (var i = 0; i < AcceptedWars.Count; i++) + { + var w = AcceptedWars[i]; + + if (w.Opponent == g) + return w; + } + + return null; + } + + public void CheckExpiredWars() + { + for (var i = 0; i < AcceptedWars.Count; i++) + { + var w = AcceptedWars[i]; + var g = w.Opponent; + + var status = w.Status; + + if (status != WarStatus.InProgress) + { + var myAlliance = Alliance; + var inAlliance = myAlliance?.IsMember(this) == true; + + var otherAlliance = g?.Alliance; + var otherInAlliance = otherAlliance?.IsMember(this) == true; + + if (inAlliance) + { + myAlliance.AllianceMessage( + 1070739 + (int)status, + g == null ? "a deleted opponent" : + otherInAlliance ? otherAlliance.Name : g.Name + ); + myAlliance.InvalidateMemberProperties(); + } + else + { + GuildMessage( + 1070739 + (int)status, + g == null ? "a deleted opponent" : + otherInAlliance ? otherAlliance.Name : g.Name + ); + InvalidateMemberProperties(); + } + + AcceptedWars.Remove(w); + + if (g == null) + continue; + + if (status != WarStatus.Draw) + status = (WarStatus)((int)status + 1 % 2); + + if (otherInAlliance) + { + otherAlliance.AllianceMessage(1070739 + (int)status, inAlliance ? Alliance.Name : Name); + otherAlliance.InvalidateMemberProperties(); + } + else + { + g.GuildMessage(1070739 + (int)status, inAlliance ? Alliance.Name : Name); + g.InvalidateMemberProperties(); + } + + g.AcceptedWars.Remove(g.FindActiveWar(this)); + } + } + + for (var i = 0; i < PendingWars.Count; i++) + { + var w = PendingWars[i]; + var g = w.Opponent; + + if (w.Status != WarStatus.Pending) + { + // All sanity in here + PendingWars.Remove(w); + + g?.PendingWars.Remove(g.FindPendingWar(this)); + } + } + } + + public static void HandleDeath(Mobile victim, Mobile killer = null) + { + if (!NewGuildSystem) + return; + + killer ??= victim.FindMostRecentDamager(false); + + if (killer?.Guild == null || victim.Guild == null) + return; + + var victimGuild = GetAllianceLeader(victim.Guild as Guild); + var killerGuild = GetAllianceLeader(killer.Guild as Guild); + + var war = killerGuild.FindActiveWar(victimGuild); + + if (war == null) + return; + + war.Kills++; + + if (war.Opponent == victimGuild) + killerGuild.CheckExpiredWars(); + else + victimGuild.CheckExpiredWars(); + } + + public bool IsMember(Mobile m) => Members.Contains(m); + + public bool IsAlly(Guild g) => + NewGuildSystem ? Alliance?.IsMember(this) == true && Alliance.IsMember(g) : Allies.Contains(g); + + public bool IsEnemy(Guild g) => + Type != GuildType.Regular && g.Type != GuildType.Regular && Type != g.Type || IsWar(g); + + public bool IsWar(Guild g) + { + if (g == null) + return false; + + if (!NewGuildSystem) + return Enemies.Contains(g); + + var guild = GetAllianceLeader(this); + var otherGuild = GetAllianceLeader(g); + + return guild.FindActiveWar(otherGuild) != null; + } + + public override void Serialize(IGenericWriter writer) + { + if (LastFealty + TimeSpan.FromDays(1.0) < DateTime.UtcNow) + CalculateGuildmaster(); + + CheckExpiredWars(); + + Alliance?.CheckLeader(); + + writer.Write(5); // version + + writer.Write(PendingWars.Count); + + for (var i = 0; i < PendingWars.Count; i++) PendingWars[i].Serialize(writer); + + writer.Write(AcceptedWars.Count); + + for (var i = 0; i < AcceptedWars.Count; i++) AcceptedWars[i].Serialize(writer); + + var isAllianceLeader = m_AllianceLeader == null && m_AllianceInfo != null; + writer.Write(isAllianceLeader); + + if (isAllianceLeader) + m_AllianceInfo.Serialize(writer); + else + writer.Write(m_AllianceLeader); + + // + + writer.WriteGuildList(AllyDeclarations, true); + writer.WriteGuildList(AllyInvitations, true); + + writer.Write(TypeLastChange); + + writer.Write((int)m_Type); + + writer.Write(LastFealty); + + writer.Write(m_Leader); + writer.Write(m_Name); + writer.Write(m_Abbreviation); + + writer.WriteGuildList(Allies, true); + writer.WriteGuildList(Enemies, true); + writer.WriteGuildList(WarDeclarations, true); + writer.WriteGuildList(WarInvitations, true); + + writer.Write(Members, true); + writer.Write(Candidates, true); + writer.Write(Accepted, true); + + writer.Write(Guildstone); + writer.Write(Teleporter); + + writer.Write(Charter); + writer.Write(Website); + } + + public override void Deserialize(IGenericReader reader) + { + var version = reader.ReadInt(); + + switch (version) + { + case 5: + { + var count = reader.ReadInt(); + + PendingWars = new List(); + for (var i = 0; i < count; i++) PendingWars.Add(new WarDeclaration(reader)); + + count = reader.ReadInt(); + AcceptedWars = new List(); + for (var i = 0; i < count; i++) AcceptedWars.Add(new WarDeclaration(reader)); + + var isAllianceLeader = reader.ReadBool(); + + if (isAllianceLeader) + m_AllianceInfo = new AllianceInfo(reader); + else + m_AllianceLeader = reader.ReadGuild() as Guild; + + goto case 4; + } + case 4: + { + AllyDeclarations = reader.ReadStrongGuildList(); + AllyInvitations = reader.ReadStrongGuildList(); + + goto case 3; + } + case 3: + { + TypeLastChange = reader.ReadDateTime(); + + goto case 2; + } + case 2: + { + m_Type = (GuildType)reader.ReadInt(); + + goto case 1; + } + case 1: + { + LastFealty = reader.ReadDateTime(); + + goto case 0; + } + case 0: + { + m_Leader = reader.ReadMobile(); + + if (m_Leader is PlayerMobile mobile) + mobile.GuildRank = RankDefinition.Leader; + + m_Name = reader.ReadString(); + m_Abbreviation = reader.ReadString(); + + Allies = reader.ReadStrongGuildList(); + Enemies = reader.ReadStrongGuildList(); + WarDeclarations = reader.ReadStrongGuildList(); + WarInvitations = reader.ReadStrongGuildList(); + + Members = reader.ReadStrongMobileList(); + Candidates = reader.ReadStrongMobileList(); + Accepted = reader.ReadStrongMobileList(); + + Guildstone = reader.ReadItem(); + Teleporter = reader.ReadItem(); + + Charter = reader.ReadString(); + Website = reader.ReadString(); + + break; + } + } + + AllyDeclarations ??= new List(); + AllyInvitations ??= new List(); + AcceptedWars ??= new List(); + PendingWars ??= new List(); + + Timer.DelayCall(VerifyGuild_Callback); + } + + private void VerifyGuild_Callback() + { + if (!NewGuildSystem && Guildstone == null || Members.Count == 0) + Disband(); + + CheckExpiredWars(); + + var alliance = Alliance; + + alliance?.CheckLeader(); + + alliance = Alliance; // CheckLeader could possibly change the value of this.Alliance + + if (alliance?.IsMember(this) == false && !alliance.IsPendingMember(this) + ) // This block is there to fix a bug in the code in an older version. + Alliance = null; // Will call Alliance.RemoveGuild which will set it null & perform all the pertient checks as far as alliacne disbanding + } + + public void AddMember(Mobile m) + { + if (!Members.Contains(m)) + { + if (m.Guild != null && m.Guild != this) + ((Guild)m.Guild).RemoveMember(m); + + Members.Add(m); + m.Guild = this; + + m.GuildFealty = !NewGuildSystem ? m_Leader : null; + + if (m is PlayerMobile mobile) + mobile.GuildRank = RankDefinition.Lowest; + + ((Guild)m.Guild).InvalidateWarNotoriety(); + } + } + + public void RemoveMember(Mobile m, int message = 1018028) // You have been dismissed from your guild. + { + if (Members.Contains(m)) + { + Members.Remove(m); + + var guild = m.Guild as Guild; + + m.Guild = null; + + if (m is PlayerMobile mobile) + mobile.GuildRank = RankDefinition.Lowest; + + if (message > 0) + m.SendLocalizedMessage(message); + + if (m == m_Leader) + { + CalculateGuildmaster(); + + if (m_Leader == null) + Disband(); + } + + if (Members.Count == 0) + Disband(); + + guild?.InvalidateWarNotoriety(); + + m.Delta(MobileDelta.Noto); + } + } + + public void AddAlly(Guild g) + { + if (!Allies.Contains(g)) + { + Allies.Add(g); + + g.AddAlly(this); + } + } + + public void RemoveAlly(Guild g) + { + if (Allies.Contains(g)) + { + Allies.Remove(g); + + g.RemoveAlly(this); + } + } + + public void AddEnemy(Guild g) + { + if (!Enemies.Contains(g)) + { + Enemies.Add(g); + + g.AddEnemy(this); + } + } + + public void RemoveEnemy(Guild g) + { + if (Enemies.Contains(g)) + { + Enemies.Remove(g); + + g.RemoveEnemy(this); + } + } + + public void GuildMessage(int num, bool append, string format, params object[] args) + { + GuildMessage(num, append, string.Format(format, args)); + } + + public void GuildMessage(int number) + { + for (var i = 0; i < Members.Count; ++i) + Members[i].SendLocalizedMessage(number); + } + + public void GuildMessage(int number, string args, int hue = 0x3B2) + { + for (var i = 0; i < Members.Count; ++i) + Members[i].SendLocalizedMessage(number, args, hue); + } + + public void GuildMessage(int number, bool append, string affix, string args = "", int hue = 0x3B2) + { + for (var i = 0; i < Members.Count; ++i) + Members[i].SendLocalizedMessage(number, append, affix, args, hue); + } + + public void GuildTextMessage(string text) + { + GuildTextMessage(0x3B2, text); + } + + public void GuildTextMessage(string format, params object[] args) + { + GuildTextMessage(0x3B2, string.Format(format, args)); + } + + public void GuildTextMessage(int hue, string text) + { + for (var i = 0; i < Members.Count; ++i) + Members[i].SendMessage(hue, text); + } + + public void GuildTextMessage(int hue, string format, params object[] args) + { + GuildTextMessage(hue, string.Format(format, args)); + } + + public void GuildChat(Mobile from, int hue, string text) + { + Packet p = null; + for (var i = 0; i < Members.Count; i++) + { + var m = Members[i]; + + var state = m.NetState; + + if (state != null) + { + p ??= Packet.Acquire( + new UnicodeMessage(from.Serial, from.Body, MessageType.Guild, hue, 3, from.Language, from.Name, text) + ); + + state.Send(p); + } + } + + Packet.Release(p); + } + + public void GuildChat(Mobile from, string text) + { + GuildChat(from, (from as PlayerMobile)?.GuildMessageHue ?? 0x3B2, text); + } + + public bool CanVote(Mobile m) => + (!NewGuildSystem || m is PlayerMobile pm && pm.GuildRank.GetFlag(RankFlags.CanVote)) && + m?.Deleted == false && m.Guild == this; + + public bool CanBeVotedFor(Mobile m) => + (!NewGuildSystem || m is PlayerMobile pm && pm.LastOnline + InactiveTime >= DateTime.UtcNow) && + m?.Deleted == false && m.Guild == this; + + public void CalculateGuildmaster() + { + var votes = new Dictionary(); + + var votingMembers = 0; + + for (var i = 0; Members != null && i < Members.Count; ++i) + { + var memb = Members[i]; + + if (!CanVote(memb)) + continue; + + var m = memb.GuildFealty; + + if (!CanBeVotedFor(m)) + { + if (!Disbanded && m_Leader.Guild == this) + m = m_Leader; + else + m = memb; + } + + if (m == null) + continue; + + votes[m] = 1 + (votes.TryGetValue(m, out var v) ? v : 0); + votingMembers++; + } + + Mobile winner = null; + var highVotes = 0; + + foreach (var kvp in votes) + { + var m = kvp.Key; + var val = kvp.Value; + + if (winner == null || val > highVotes) + { + winner = m; + highVotes = val; + } + } + + if (NewGuildSystem && highVotes * 100 / Math.Max(votingMembers, 1) < MajorityPercentage && !Disbanded && + winner != m_Leader && m_Leader.Guild == this) + winner = m_Leader; + + if (m_Leader != winner && winner != null) + GuildMessage(1018015, true, winner.Name); // Guild Message: Guildmaster changed to: + + Leader = winner; + LastFealty = DateTime.UtcNow; + } + + private class GuildPropsTarget : Target + { + public GuildPropsTarget() : base(-1, true, TargetFlags.None) + { + } + + protected override void OnTarget(Mobile from, object o) + { + if (!BaseCommand.IsAccessible(from, o)) + { + from.SendLocalizedMessage(500447); // That is not accessible. + return; + } + + Guild g = null; + + if (o is Guildstone stone) + { + if (stone.Guild.Disbanded) + { + from.SendMessage("The guild associated with that Guildstone no longer exists"); + return; + } + + g = stone.Guild; + } + else if (o is Mobile mobile) + { + g = mobile.Guild as Guild; + } + + if (g == null) + { + from.SendMessage("That is not in a guild!"); + return; + } + + from.SendGump(new PropertiesGump(from, g)); + + if (NewGuildSystem && from.AccessLevel >= AccessLevel.GameMaster && from is PlayerMobile pm) + pm.SendGump(new GuildInfoGump(pm, g)); + } } - } } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime LastFealty { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime TypeLastChange { get; private set; } - - public List Allies { get; private set; } - - public List Enemies { get; private set; } - - public List AllyDeclarations { get; private set; } - - public List AllyInvitations { get; private set; } - - public List WarDeclarations { get; private set; } - - public List WarInvitations { get; private set; } - - public List Candidates { get; private set; } - - public List Accepted { get; private set; } - - public List Members { get; private set; } - } } diff --git a/Projects/UOContent/Misc/HardwareInfo.cs b/Projects/UOContent/Misc/HardwareInfo.cs index afd69ce65..6438caa9f 100644 --- a/Projects/UOContent/Misc/HardwareInfo.cs +++ b/Projects/UOContent/Misc/HardwareInfo.cs @@ -7,166 +7,171 @@ using Server.Targeting; namespace Server { - public class HardwareInfo - { - [CommandProperty(AccessLevel.GameMaster)] - public int CpuModel { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int CpuClockSpeed { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int CpuQuantity { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int OSMajor { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int OSMinor { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int OSRevision { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int InstanceID { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int ScreenWidth { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int ScreenHeight { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int ScreenDepth { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int PhysicalMemory { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int CpuManufacturer { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int CpuFamily { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int VCVendorID { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int VCDeviceID { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int VCMemory { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int DXMajor { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int DXMinor { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public string VCDescription { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public string Language { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Distribution { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int ClientsRunning { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int ClientsInstalled { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int PartialInstalled { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public string Unknown { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime TimeReceived { get; private set; } - - public static void Initialize() + public class HardwareInfo { - PacketHandlers.Register(0xD9, 0x10C, false, OnReceive); + [CommandProperty(AccessLevel.GameMaster)] + public int CpuModel { get; private set; } - CommandSystem.Register("HWInfo", AccessLevel.GameMaster, HWInfo_OnCommand); - } + [CommandProperty(AccessLevel.GameMaster)] + public int CpuClockSpeed { get; private set; } - [Usage("HWInfo")] - [Description("Displays information about a targeted player's hardware.")] - public static void HWInfo_OnCommand(CommandEventArgs e) - { - e.Mobile.BeginTarget(-1, false, TargetFlags.None, HWInfo_OnTarget); - e.Mobile.SendMessage("Target a player to view their hardware information."); - } + [CommandProperty(AccessLevel.GameMaster)] + public int CpuQuantity { get; private set; } - public static void HWInfo_OnTarget(Mobile from, object obj) - { - if (obj is Mobile m && m.Player) - { - if (m.Account is Account acct) + [CommandProperty(AccessLevel.GameMaster)] + public int OSMajor { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int OSMinor { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int OSRevision { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int InstanceID { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int ScreenWidth { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int ScreenHeight { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int ScreenDepth { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int PhysicalMemory { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int CpuManufacturer { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int CpuFamily { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int VCVendorID { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int VCDeviceID { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int VCMemory { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int DXMajor { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int DXMinor { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public string VCDescription { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public string Language { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Distribution { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int ClientsRunning { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int ClientsInstalled { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int PartialInstalled { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public string Unknown { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime TimeReceived { get; private set; } + + public static void Initialize() { - HardwareInfo hwInfo = acct.HardwareInfo; + PacketHandlers.Register(0xD9, 0x10C, false, OnReceive); - if (hwInfo != null) - CommandLogging.WriteLine(from, "{0} {1} viewing hardware info of {2}", from.AccessLevel, - CommandLogging.Format(from), CommandLogging.Format(m)); - - if (hwInfo != null) - from.SendGump(new PropertiesGump(from, hwInfo)); - else - from.SendMessage("No hardware information for that account was found."); + CommandSystem.Register("HWInfo", AccessLevel.GameMaster, HWInfo_OnCommand); } - else + + [Usage("HWInfo")] + [Description("Displays information about a targeted player's hardware.")] + public static void HWInfo_OnCommand(CommandEventArgs e) { - from.SendMessage("No account has been attached to that player."); + e.Mobile.BeginTarget(-1, false, TargetFlags.None, HWInfo_OnTarget); + e.Mobile.SendMessage("Target a player to view their hardware information."); + } + + public static void HWInfo_OnTarget(Mobile from, object obj) + { + if (obj is Mobile m && m.Player) + { + if (m.Account is Account acct) + { + var hwInfo = acct.HardwareInfo; + + if (hwInfo != null) + CommandLogging.WriteLine( + from, + "{0} {1} viewing hardware info of {2}", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(m) + ); + + if (hwInfo != null) + from.SendGump(new PropertiesGump(from, hwInfo)); + else + from.SendMessage("No hardware information for that account was found."); + } + else + { + from.SendMessage("No account has been attached to that player."); + } + } + else + { + from.BeginTarget(-1, false, TargetFlags.None, HWInfo_OnTarget); + from.SendMessage("That is not a player. Try again."); + } + } + + public static void OnReceive(NetState state, PacketReader pvSrc) + { + pvSrc.ReadByte(); // 1: <4.0.1a, 2>=4.0.1a + + var info = new HardwareInfo(); + + info.InstanceID = pvSrc.ReadInt32(); + info.OSMajor = pvSrc.ReadInt32(); + info.OSMinor = pvSrc.ReadInt32(); + info.OSRevision = pvSrc.ReadInt32(); + info.CpuManufacturer = pvSrc.ReadByte(); + info.CpuFamily = pvSrc.ReadInt32(); + info.CpuModel = pvSrc.ReadInt32(); + info.CpuClockSpeed = pvSrc.ReadInt32(); + info.CpuQuantity = pvSrc.ReadByte(); + info.PhysicalMemory = pvSrc.ReadInt32(); + info.ScreenWidth = pvSrc.ReadInt32(); + info.ScreenHeight = pvSrc.ReadInt32(); + info.ScreenDepth = pvSrc.ReadInt32(); + info.DXMajor = pvSrc.ReadInt16(); + info.DXMinor = pvSrc.ReadInt16(); + info.VCDescription = pvSrc.ReadUnicodeStringLESafe(64); + info.VCVendorID = pvSrc.ReadInt32(); + info.VCDeviceID = pvSrc.ReadInt32(); + info.VCMemory = pvSrc.ReadInt32(); + info.Distribution = pvSrc.ReadByte(); + info.ClientsRunning = pvSrc.ReadByte(); + info.ClientsInstalled = pvSrc.ReadByte(); + info.PartialInstalled = pvSrc.ReadByte(); + info.Language = pvSrc.ReadUnicodeStringLESafe(4); + info.Unknown = pvSrc.ReadStringSafe(64); + + info.TimeReceived = DateTime.UtcNow; + + if (state.Account is Account acct) + acct.HardwareInfo = info; } - } - else - { - from.BeginTarget(-1, false, TargetFlags.None, HWInfo_OnTarget); - from.SendMessage("That is not a player. Try again."); - } } - - public static void OnReceive(NetState state, PacketReader pvSrc) - { - pvSrc.ReadByte(); // 1: <4.0.1a, 2>=4.0.1a - - HardwareInfo info = new HardwareInfo(); - - info.InstanceID = pvSrc.ReadInt32(); - info.OSMajor = pvSrc.ReadInt32(); - info.OSMinor = pvSrc.ReadInt32(); - info.OSRevision = pvSrc.ReadInt32(); - info.CpuManufacturer = pvSrc.ReadByte(); - info.CpuFamily = pvSrc.ReadInt32(); - info.CpuModel = pvSrc.ReadInt32(); - info.CpuClockSpeed = pvSrc.ReadInt32(); - info.CpuQuantity = pvSrc.ReadByte(); - info.PhysicalMemory = pvSrc.ReadInt32(); - info.ScreenWidth = pvSrc.ReadInt32(); - info.ScreenHeight = pvSrc.ReadInt32(); - info.ScreenDepth = pvSrc.ReadInt32(); - info.DXMajor = pvSrc.ReadInt16(); - info.DXMinor = pvSrc.ReadInt16(); - info.VCDescription = pvSrc.ReadUnicodeStringLESafe(64); - info.VCVendorID = pvSrc.ReadInt32(); - info.VCDeviceID = pvSrc.ReadInt32(); - info.VCMemory = pvSrc.ReadInt32(); - info.Distribution = pvSrc.ReadByte(); - info.ClientsRunning = pvSrc.ReadByte(); - info.ClientsInstalled = pvSrc.ReadByte(); - info.PartialInstalled = pvSrc.ReadByte(); - info.Language = pvSrc.ReadUnicodeStringLESafe(4); - info.Unknown = pvSrc.ReadStringSafe(64); - - info.TimeReceived = DateTime.UtcNow; - - if (state.Account is Account acct) - acct.HardwareInfo = info; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Misc/HexStringConverter.cs b/Projects/UOContent/Misc/HexStringConverter.cs index dbca21836..fc388ec06 100644 --- a/Projects/UOContent/Misc/HexStringConverter.cs +++ b/Projects/UOContent/Misc/HexStringConverter.cs @@ -2,53 +2,54 @@ using System; namespace Server.Misc { - public class HexStringConverter - { - public static readonly uint[] m_Lookup32Chars = CreateLookup32Chars(); - - private static uint[] CreateLookup32Chars() + public class HexStringConverter { - var result = new uint[256]; - for (int i = 0; i < 256; i++) - { - string s = i.ToString("X2"); - if (BitConverter.IsLittleEndian) - result[i] = s[0] + ((uint)s[1] << 16); - else - result[i] = s[1] + ((uint)s[0] << 16); - } + public static readonly uint[] m_Lookup32Chars = CreateLookup32Chars(); - return result; - } - - public static unsafe string GetString(ReadOnlySpan bytes) - { - var result = new string((char)0, bytes.Length * 2); - fixed (char* resultP = result) - { - uint* resultP2 = (uint*)resultP; - for (int i = 0; i < bytes.Length; i++) - resultP2[i] = m_Lookup32Chars[bytes[i]]; - } - return result; - } - - public static unsafe void GetBytes(string str, Span bytes) - { - fixed (char* strP = str) - { - int i = 0; - int j = 0; - while (i < str.Length) + private static uint[] CreateLookup32Chars() { - int chr1 = strP[i++]; - int chr2 = strP[i++]; - if (BitConverter.IsLittleEndian) - bytes[j++] = (byte)((chr1 - (chr1 >= 65 ? 55 : 48)) << 4 | (chr2 - (chr2 >= 65 ? 55 : 48))); - else - bytes[j++] = (byte)((chr1 - (chr1 >= 65 ? 55 : 48)) | ((chr2 - (chr2 >= 65 ? 55 : 48)) << 4)); + var result = new uint[256]; + for (var i = 0; i < 256; i++) + { + var s = i.ToString("X2"); + if (BitConverter.IsLittleEndian) + result[i] = s[0] + ((uint)s[1] << 16); + else + result[i] = s[1] + ((uint)s[0] << 16); + } + + return result; + } + + public static unsafe string GetString(ReadOnlySpan bytes) + { + var result = new string((char)0, bytes.Length * 2); + fixed (char* resultP = result) + { + var resultP2 = (uint*)resultP; + for (var i = 0; i < bytes.Length; i++) + resultP2[i] = m_Lookup32Chars[bytes[i]]; + } + + return result; + } + + public static unsafe void GetBytes(string str, Span bytes) + { + fixed (char* strP = str) + { + var i = 0; + var j = 0; + while (i < str.Length) + { + int chr1 = strP[i++]; + int chr2 = strP[i++]; + if (BitConverter.IsLittleEndian) + bytes[j++] = (byte)(((chr1 - (chr1 >= 65 ? 55 : 48)) << 4) | (chr2 - (chr2 >= 65 ? 55 : 48))); + else + bytes[j++] = (byte)((chr1 - (chr1 >= 65 ? 55 : 48)) | ((chr2 - (chr2 >= 65 ? 55 : 48)) << 4)); + } + } } - } } - } } diff --git a/Projects/UOContent/Misc/InhumanSpeech.cs b/Projects/UOContent/Misc/InhumanSpeech.cs index cfbf67c02..58a3ccd16 100644 --- a/Projects/UOContent/Misc/InhumanSpeech.cs +++ b/Projects/UOContent/Misc/InhumanSpeech.cs @@ -4,545 +4,561 @@ using System.Text; namespace Server.Misc { - [Flags] - public enum IHSFlags - { - None = 0x00, - OnDamaged = 0x01, - OnDeath = 0x02, - OnMovement = 0x04, - OnSpeech = 0x08, - All = OnDamaged | OnDeath | OnMovement - } // NOTE: To enable monster conversations, add " | OnSpeech" to the "All" line - - public class InhumanSpeech - { - private static InhumanSpeech m_RatmanSpeech; - - public static InhumanSpeech Ratman + [Flags] + public enum IHSFlags { - get - { - if (m_RatmanSpeech == null) + None = 0x00, + OnDamaged = 0x01, + OnDeath = 0x02, + OnMovement = 0x04, + OnSpeech = 0x08, + All = OnDamaged | OnDeath | OnMovement + } // NOTE: To enable monster conversations, add " | OnSpeech" to the "All" line + + public class InhumanSpeech + { + private static InhumanSpeech m_RatmanSpeech; + + private static InhumanSpeech m_OrcSpeech; + + private static InhumanSpeech m_LizardmanSpeech; + + private static InhumanSpeech m_WispSpeech; + + private Dictionary m_KeywordHash; + + private string[] m_Keywords; + + public static InhumanSpeech Ratman { - m_RatmanSpeech = new InhumanSpeech(); + get + { + if (m_RatmanSpeech == null) + { + m_RatmanSpeech = new InhumanSpeech(); - m_RatmanSpeech.Hue = 149; - m_RatmanSpeech.Sound = 438; + m_RatmanSpeech.Hue = 149; + m_RatmanSpeech.Sound = 438; - m_RatmanSpeech.Flags = IHSFlags.All; + m_RatmanSpeech.Flags = IHSFlags.All; - m_RatmanSpeech.Keywords = new[] - { - "meat", "gold", "kill", "killing", "slay", - "sword", "axe", "spell", "magic", "spells", - "swords", "axes", "mace", "maces", "monster", - "monsters", "food", "run", "escape", "away", - "help", "dead", "die", "dying", "lose", - "losing", "life", "lives", "death", "ghost", - "ghosts", "british", "blackthorn", "guild", - "guilds", "dragon", "dragons", "game", "games", - "ultima", "silly", "stupid", "dumb", "idiot", - "idiots", "cheesy", "cheezy", "crazy", "dork", - "jerk", "fool", "foolish", "ugly", "insult", "scum" - }; + m_RatmanSpeech.Keywords = new[] + { + "meat", "gold", "kill", "killing", "slay", + "sword", "axe", "spell", "magic", "spells", + "swords", "axes", "mace", "maces", "monster", + "monsters", "food", "run", "escape", "away", + "help", "dead", "die", "dying", "lose", + "losing", "life", "lives", "death", "ghost", + "ghosts", "british", "blackthorn", "guild", + "guilds", "dragon", "dragons", "game", "games", + "ultima", "silly", "stupid", "dumb", "idiot", + "idiots", "cheesy", "cheezy", "crazy", "dork", + "jerk", "fool", "foolish", "ugly", "insult", "scum" + }; - m_RatmanSpeech.Responses = new[] - { - "meat", "kill", "pound", "crush", "yum yum", - "crunch", "destroy", "murder", "eat", "munch", - "massacre", "food", "monster", "evil", "run", - "die", "lose", "dumb", "idiot", "fool", "crazy", - "dinner", "lunch", "breakfast", "fight", "battle", - "doomed", "rip apart", "tear apart", "smash", - "edible?", "shred", "disembowel", "ugly", "smelly", - "stupid", "hideous", "smell", "tasty", "invader", - "attack", "raid", "plunder", "pillage", "treasure", - "loser", "lose", "scum" - }; + m_RatmanSpeech.Responses = new[] + { + "meat", "kill", "pound", "crush", "yum yum", + "crunch", "destroy", "murder", "eat", "munch", + "massacre", "food", "monster", "evil", "run", + "die", "lose", "dumb", "idiot", "fool", "crazy", + "dinner", "lunch", "breakfast", "fight", "battle", + "doomed", "rip apart", "tear apart", "smash", + "edible?", "shred", "disembowel", "ugly", "smelly", + "stupid", "hideous", "smell", "tasty", "invader", + "attack", "raid", "plunder", "pillage", "treasure", + "loser", "lose", "scum" + }; - m_RatmanSpeech.Syllables = new[] - { - "skrit", + m_RatmanSpeech.Syllables = new[] + { + "skrit", - "ch", "ch", - "it", "ti", "it", "ti", + "ch", "ch", + "it", "ti", "it", "ti", - "ak", "ek", "ik", "ok", "uk", "yk", - "ka", "ke", "ki", "ko", "ku", "ky", - "at", "et", "it", "ot", "ut", "yt", + "ak", "ek", "ik", "ok", "uk", "yk", + "ka", "ke", "ki", "ko", "ku", "ky", + "at", "et", "it", "ot", "ut", "yt", - "cha", "che", "chi", "cho", "chu", "chy", - "ach", "ech", "ich", "och", "uch", "ych", - "att", "ett", "itt", "ott", "utt", "ytt", - "tat", "tet", "tit", "tot", "tut", "tyt", - "tta", "tte", "tti", "tto", "ttu", "tty", - "tak", "tek", "tik", "tok", "tuk", "tyk", - "ack", "eck", "ick", "ock", "uck", "yck", - "cka", "cke", "cki", "cko", "cku", "cky", - "rak", "rek", "rik", "rok", "ruk", "ryk", + "cha", "che", "chi", "cho", "chu", "chy", + "ach", "ech", "ich", "och", "uch", "ych", + "att", "ett", "itt", "ott", "utt", "ytt", + "tat", "tet", "tit", "tot", "tut", "tyt", + "tta", "tte", "tti", "tto", "ttu", "tty", + "tak", "tek", "tik", "tok", "tuk", "tyk", + "ack", "eck", "ick", "ock", "uck", "yck", + "cka", "cke", "cki", "cko", "cku", "cky", + "rak", "rek", "rik", "rok", "ruk", "ryk", - "tcha", "tche", "tchi", "tcho", "tchu", "tchy", - "rach", "rech", "rich", "roch", "ruch", "rych", - "rrap", "rrep", "rrip", "rrop", "rrup", "rryp", - "ccka", "ccke", "ccki", "ccko", "ccku", "ccky" - }; + "tcha", "tche", "tchi", "tcho", "tchu", "tchy", + "rach", "rech", "rich", "roch", "ruch", "rych", + "rrap", "rrep", "rrip", "rrop", "rrup", "rryp", + "ccka", "ccke", "ccki", "ccko", "ccku", "ccky" + }; + } + + return m_RatmanSpeech; + } } - return m_RatmanSpeech; - } - } - - private static InhumanSpeech m_OrcSpeech; - - public static InhumanSpeech Orc - { - get - { - if (m_OrcSpeech == null) + public static InhumanSpeech Orc { - m_OrcSpeech = new InhumanSpeech(); + get + { + if (m_OrcSpeech == null) + { + m_OrcSpeech = new InhumanSpeech(); - m_OrcSpeech.Hue = 34; - m_OrcSpeech.Sound = 432; + m_OrcSpeech.Hue = 34; + m_OrcSpeech.Sound = 432; - m_OrcSpeech.Flags = IHSFlags.All; + m_OrcSpeech.Flags = IHSFlags.All; - m_OrcSpeech.Keywords = new[] - { - "meat", "gold", "kill", "killing", "slay", - "sword", "axe", "spell", "magic", "spells", - "swords", "axes", "mace", "maces", "monster", - "monsters", "food", "run", "escape", "away", - "help", "dead", "die", "dying", "lose", - "losing", "life", "lives", "death", "ghost", - "ghosts", "british", "blackthorn", "guild", - "guilds", "dragon", "dragons", "game", "games", - "ultima", "silly", "stupid", "dumb", "idiot", - "idiots", "cheesy", "cheezy", "crazy", "dork", - "jerk", "fool", "foolish", "ugly", "insult", "scum" - }; + m_OrcSpeech.Keywords = new[] + { + "meat", "gold", "kill", "killing", "slay", + "sword", "axe", "spell", "magic", "spells", + "swords", "axes", "mace", "maces", "monster", + "monsters", "food", "run", "escape", "away", + "help", "dead", "die", "dying", "lose", + "losing", "life", "lives", "death", "ghost", + "ghosts", "british", "blackthorn", "guild", + "guilds", "dragon", "dragons", "game", "games", + "ultima", "silly", "stupid", "dumb", "idiot", + "idiots", "cheesy", "cheezy", "crazy", "dork", + "jerk", "fool", "foolish", "ugly", "insult", "scum" + }; - m_OrcSpeech.Responses = new[] - { - "meat", "kill", "pound", "crush", "yum yum", - "crunch", "destroy", "murder", "eat", "munch", - "massacre", "food", "monster", "evil", "run", - "die", "lose", "dumb", "idiot", "fool", "crazy", - "dinner", "lunch", "breakfast", "fight", "battle", - "doomed", "rip apart", "tear apart", "smash", - "edible?", "shred", "disembowel", "ugly", "smelly", - "stupid", "hideous", "smell", "tasty", "invader", - "attack", "raid", "plunder", "pillage", "treasure", - "loser", "lose", "scum" - }; + m_OrcSpeech.Responses = new[] + { + "meat", "kill", "pound", "crush", "yum yum", + "crunch", "destroy", "murder", "eat", "munch", + "massacre", "food", "monster", "evil", "run", + "die", "lose", "dumb", "idiot", "fool", "crazy", + "dinner", "lunch", "breakfast", "fight", "battle", + "doomed", "rip apart", "tear apart", "smash", + "edible?", "shred", "disembowel", "ugly", "smelly", + "stupid", "hideous", "smell", "tasty", "invader", + "attack", "raid", "plunder", "pillage", "treasure", + "loser", "lose", "scum" + }; - m_OrcSpeech.Syllables = new[] - { - "bu", "du", "fu", "ju", "gu", - "ulg", "gug", "gub", "gur", "oog", - "gub", "log", "ru", "stu", "glu", - "ug", "ud", "og", "log", "ro", "flu", - "bo", "duf", "fun", "nog", "dun", "bog", - "dug", "gh", "ghu", "gho", "nug", "ig", - "igh", "ihg", "luh", "duh", "bug", "dug", - "dru", "urd", "gurt", "grut", "grunt", - "snarf", "urgle", "igg", "glu", "glug", - "foo", "bar", "baz", "ghat", "ab", "ad", - "gugh", "guk", "ag", "alm", "thu", "log", - "bilge", "augh", "gha", "gig", "goth", - "zug", "pig", "auh", "gan", "azh", "bag", - "hig", "oth", "dagh", "gulg", "ugh", "ba", - "bid", "gug", "bug", "rug", "hat", "brui", - "gagh", "buad", "buil", "buim", "bum", - "hug", "hug", "buo", "ma", "buor", "ghed", - "buu", "ca", "guk", "clog", "thurg", "car", - "cro", "thu", "da", "cuk", "gil", "cur", "dak", - "dar", "deak", "der", "dil", "dit", "at", "ag", - "dor", "gar", "dre", "tk", "dri", "gka", "rim", - "eag", "egg", "ha", "rod", "eg", "lat", "eichel", - "ek", "ep", "ka", "it", "ut", "ewk", "ba", "dagh", - "faugh", "foz", "fog", "fid", "fruk", "gag", "fub", - "fud", "fur", "bog", "fup", "hagh", "gaa", "kt", - "rekk", "lub", "lug", "tug", "gna", "urg", "l", - "gno", "gnu", "gol", "gom", "kug", "ukk", "jak", - "jek", "rukk", "jja", "akt", "nuk", "hok", "hrol", - "olm", "natz", "i", "i", "o", "u", "ikk", "ign", - "juk", "kh", "kgh", "ka", "hig", "ke", "ki", "klap", - "klu", "knod", "kod", "knu", "thnu", "krug", "nug", - "nar", "nag", "neg", "neh", "oag", "ob", "ogh", "oh", - "om", "dud", "oo", "pa", "hrak", "qo", "quad", "quil", - "ghig", "rur", "sag", "sah", "sg" - }; + m_OrcSpeech.Syllables = new[] + { + "bu", "du", "fu", "ju", "gu", + "ulg", "gug", "gub", "gur", "oog", + "gub", "log", "ru", "stu", "glu", + "ug", "ud", "og", "log", "ro", "flu", + "bo", "duf", "fun", "nog", "dun", "bog", + "dug", "gh", "ghu", "gho", "nug", "ig", + "igh", "ihg", "luh", "duh", "bug", "dug", + "dru", "urd", "gurt", "grut", "grunt", + "snarf", "urgle", "igg", "glu", "glug", + "foo", "bar", "baz", "ghat", "ab", "ad", + "gugh", "guk", "ag", "alm", "thu", "log", + "bilge", "augh", "gha", "gig", "goth", + "zug", "pig", "auh", "gan", "azh", "bag", + "hig", "oth", "dagh", "gulg", "ugh", "ba", + "bid", "gug", "bug", "rug", "hat", "brui", + "gagh", "buad", "buil", "buim", "bum", + "hug", "hug", "buo", "ma", "buor", "ghed", + "buu", "ca", "guk", "clog", "thurg", "car", + "cro", "thu", "da", "cuk", "gil", "cur", "dak", + "dar", "deak", "der", "dil", "dit", "at", "ag", + "dor", "gar", "dre", "tk", "dri", "gka", "rim", + "eag", "egg", "ha", "rod", "eg", "lat", "eichel", + "ek", "ep", "ka", "it", "ut", "ewk", "ba", "dagh", + "faugh", "foz", "fog", "fid", "fruk", "gag", "fub", + "fud", "fur", "bog", "fup", "hagh", "gaa", "kt", + "rekk", "lub", "lug", "tug", "gna", "urg", "l", + "gno", "gnu", "gol", "gom", "kug", "ukk", "jak", + "jek", "rukk", "jja", "akt", "nuk", "hok", "hrol", + "olm", "natz", "i", "i", "o", "u", "ikk", "ign", + "juk", "kh", "kgh", "ka", "hig", "ke", "ki", "klap", + "klu", "knod", "kod", "knu", "thnu", "krug", "nug", + "nar", "nag", "neg", "neh", "oag", "ob", "ogh", "oh", + "om", "dud", "oo", "pa", "hrak", "qo", "quad", "quil", + "ghig", "rur", "sag", "sah", "sg" + }; + } + + return m_OrcSpeech; + } } - return m_OrcSpeech; - } - } - - private static InhumanSpeech m_LizardmanSpeech; - - public static InhumanSpeech Lizardman - { - get - { - if (m_LizardmanSpeech == null) + public static InhumanSpeech Lizardman { - m_LizardmanSpeech = new InhumanSpeech(); + get + { + if (m_LizardmanSpeech == null) + { + m_LizardmanSpeech = new InhumanSpeech(); - m_LizardmanSpeech.Hue = 58; - m_LizardmanSpeech.Sound = 418; + m_LizardmanSpeech.Hue = 58; + m_LizardmanSpeech.Sound = 418; - m_LizardmanSpeech.Flags = IHSFlags.All; + m_LizardmanSpeech.Flags = IHSFlags.All; - m_LizardmanSpeech.Keywords = new[] - { - "meat", "gold", "kill", "killing", "slay", - "sword", "axe", "spell", "magic", "spells", - "swords", "axes", "mace", "maces", "monster", - "monsters", "food", "run", "escape", "away", - "help", "dead", "die", "dying", "lose", - "losing", "life", "lives", "death", "ghost", - "ghosts", "british", "blackthorn", "guild", - "guilds", "dragon", "dragons", "game", "games", - "ultima", "silly", "stupid", "dumb", "idiot", - "idiots", "cheesy", "cheezy", "crazy", "dork", - "jerk", "fool", "foolish", "ugly", "insult", "scum" - }; + m_LizardmanSpeech.Keywords = new[] + { + "meat", "gold", "kill", "killing", "slay", + "sword", "axe", "spell", "magic", "spells", + "swords", "axes", "mace", "maces", "monster", + "monsters", "food", "run", "escape", "away", + "help", "dead", "die", "dying", "lose", + "losing", "life", "lives", "death", "ghost", + "ghosts", "british", "blackthorn", "guild", + "guilds", "dragon", "dragons", "game", "games", + "ultima", "silly", "stupid", "dumb", "idiot", + "idiots", "cheesy", "cheezy", "crazy", "dork", + "jerk", "fool", "foolish", "ugly", "insult", "scum" + }; - m_LizardmanSpeech.Responses = new[] - { - "meat", "kill", "pound", "crush", "yum yum", - "crunch", "destroy", "murder", "eat", "munch", - "massacre", "food", "monster", "evil", "run", - "die", "lose", "dumb", "idiot", "fool", "crazy", - "dinner", "lunch", "breakfast", "fight", "battle", - "doomed", "rip apart", "tear apart", "smash", - "edible?", "shred", "disembowel", "ugly", "smelly", - "stupid", "hideous", "smell", "tasty", "invader", - "attack", "raid", "plunder", "pillage", "treasure", - "loser", "lose", "scum" - }; + m_LizardmanSpeech.Responses = new[] + { + "meat", "kill", "pound", "crush", "yum yum", + "crunch", "destroy", "murder", "eat", "munch", + "massacre", "food", "monster", "evil", "run", + "die", "lose", "dumb", "idiot", "fool", "crazy", + "dinner", "lunch", "breakfast", "fight", "battle", + "doomed", "rip apart", "tear apart", "smash", + "edible?", "shred", "disembowel", "ugly", "smelly", + "stupid", "hideous", "smell", "tasty", "invader", + "attack", "raid", "plunder", "pillage", "treasure", + "loser", "lose", "scum" + }; - m_LizardmanSpeech.Syllables = new[] - { - "ss", "sth", "iss", "is", "ith", "kth", - "sith", "this", "its", "sit", "tis", "tsi", - "ssi", "sil", "lis", "sis", "lil", "thil", - "lith", "sthi", "lish", "shi", "shash", "sal", - "miss", "ra", "tha", "thes", "ses", "sas", "las", - "les", "sath", "sia", "ais", "isa", "asi", "asth", - "stha", "sthi", "isth", "asa", "ath", "tha", "als", - "sla", "thth", "ci", "ce", "cy", "yss", "ys", "yth", - "syth", "thys", "yts", "syt", "tys", "tsy", "ssy", - "syl", "lys", "sys", "lyl", "thyl", "lyth", "sthy", - "lysh", "shy", "myss", "ysa", "sthy", "ysth" - }; + m_LizardmanSpeech.Syllables = new[] + { + "ss", "sth", "iss", "is", "ith", "kth", + "sith", "this", "its", "sit", "tis", "tsi", + "ssi", "sil", "lis", "sis", "lil", "thil", + "lith", "sthi", "lish", "shi", "shash", "sal", + "miss", "ra", "tha", "thes", "ses", "sas", "las", + "les", "sath", "sia", "ais", "isa", "asi", "asth", + "stha", "sthi", "isth", "asa", "ath", "tha", "als", + "sla", "thth", "ci", "ce", "cy", "yss", "ys", "yth", + "syth", "thys", "yts", "syt", "tys", "tsy", "ssy", + "syl", "lys", "sys", "lyl", "thyl", "lyth", "sthy", + "lysh", "shy", "myss", "ysa", "sthy", "ysth" + }; + } + + return m_LizardmanSpeech; + } } - return m_LizardmanSpeech; - } - } - - private static InhumanSpeech m_WispSpeech; - - public static InhumanSpeech Wisp - { - get - { - if (m_WispSpeech == null) + public static InhumanSpeech Wisp { - m_WispSpeech = new InhumanSpeech(); + get + { + if (m_WispSpeech == null) + { + m_WispSpeech = new InhumanSpeech(); - m_WispSpeech.Hue = 89; - m_WispSpeech.Sound = 466; + m_WispSpeech.Hue = 89; + m_WispSpeech.Sound = 466; - m_WispSpeech.Flags = IHSFlags.OnMovement; + m_WispSpeech.Flags = IHSFlags.OnMovement; - m_WispSpeech.Syllables = new[] - { - "b", "c", "d", "f", "g", "h", "i", - "j", "k", "l", "m", "n", "p", "r", - "s", "t", "v", "w", "x", "z", "c", - "c", "x", "x", "x", "x", "x", "y", - "y", "y", "y", "t", "t", "k", "k", - "l", "l", "m", "m", "m", "m", "z" - }; + m_WispSpeech.Syllables = new[] + { + "b", "c", "d", "f", "g", "h", "i", + "j", "k", "l", "m", "n", "p", "r", + "s", "t", "v", "w", "x", "z", "c", + "c", "x", "x", "x", "x", "x", "y", + "y", "y", "y", "t", "t", "k", "k", + "l", "l", "m", "m", "m", "m", "z" + }; + } + + return m_WispSpeech; + } } - return m_WispSpeech; - } - } + public string[] Syllables { get; set; } - private string[] m_Keywords; - - private Dictionary m_KeywordHash; - - public string[] Syllables { get; set; } - - public string[] Keywords - { - get => m_Keywords; - set - { - m_Keywords = value; - m_KeywordHash = new Dictionary(m_Keywords.Length, StringComparer.OrdinalIgnoreCase); - for (int i = 0; i < m_Keywords.Length; ++i) - m_KeywordHash[m_Keywords[i]] = m_Keywords[i]; - } - } - - public string[] Responses { get; set; } - - public int Hue { get; set; } - - public int Sound { get; set; } - - public IHSFlags Flags { get; set; } - - public string GetRandomSyllable() => Syllables.RandomElement(); - - public string ConstructWord(int syllableCount) - { - string[] syllables = new string[syllableCount]; - - for (int i = 0; i < syllableCount; ++i) - syllables[i] = GetRandomSyllable(); - - return string.Concat(syllables); - } - - public string ConstructSentance(int wordCount) - { - StringBuilder sentance = new StringBuilder(); - - bool needUpperCase = true; - - for (int i = 0; i < wordCount; ++i) - { - if (i > 0) // not first word) + public string[] Keywords { - int random = Utility.RandomMinMax(1, 15); + get => m_Keywords; + set + { + m_Keywords = value; + m_KeywordHash = new Dictionary(m_Keywords.Length, StringComparer.OrdinalIgnoreCase); + for (var i = 0; i < m_Keywords.Length; ++i) + m_KeywordHash[m_Keywords[i]] = m_Keywords[i]; + } + } - if (random < 11) - { - sentance.Append(' '); - } - else - { - needUpperCase = true; + public string[] Responses { get; set; } - if (random > 13) - sentance.Append("! "); + public int Hue { get; set; } + + public int Sound { get; set; } + + public IHSFlags Flags { get; set; } + + public string GetRandomSyllable() => Syllables.RandomElement(); + + public string ConstructWord(int syllableCount) + { + var syllables = new string[syllableCount]; + + for (var i = 0; i < syllableCount; ++i) + syllables[i] = GetRandomSyllable(); + + return string.Concat(syllables); + } + + public string ConstructSentance(int wordCount) + { + var sentance = new StringBuilder(); + + var needUpperCase = true; + + for (var i = 0; i < wordCount; ++i) + { + if (i > 0) // not first word) + { + var random = Utility.RandomMinMax(1, 15); + + if (random < 11) + { + sentance.Append(' '); + } + else + { + needUpperCase = true; + + if (random > 13) + sentance.Append("! "); + else + sentance.Append(". "); + } + } + + int syllableCount; + + if (Utility.Random(100) < 30) + syllableCount = Utility.Random(1, 5); + else + syllableCount = Utility.Random(1, 3); + + var word = ConstructWord(syllableCount); + + sentance.Append(word); + + if (needUpperCase) + sentance.Replace(word[0], char.ToUpper(word[0]), sentance.Length - word.Length, 1); + + needUpperCase = false; + } + + if (Utility.RandomMinMax(1, 5) == 1) + sentance.Append('!'); else - sentance.Append(". "); - } + sentance.Append('.'); + + return sentance.ToString(); } - int syllableCount; - - if (Utility.Random(100) < 30) - syllableCount = Utility.Random(1, 5); - else - syllableCount = Utility.Random(1, 3); - - string word = ConstructWord(syllableCount); - - sentance.Append(word); - - if (needUpperCase) - sentance.Replace(word[0], char.ToUpper(word[0]), sentance.Length - word.Length, 1); - - needUpperCase = false; - } - - if (Utility.RandomMinMax(1, 5) == 1) - sentance.Append('!'); - else - sentance.Append('.'); - - return sentance.ToString(); - } - - public void SayRandomTranslate(Mobile mob, params string[] sentancesInEnglish) - { - SaySentance(mob, Utility.RandomMinMax(2, 3)); - mob.Say(sentancesInEnglish.RandomElement()); - } - - private string GetRandomResponseWord(List keywordsFound) - { - int random = Utility.Random(keywordsFound.Count + Responses.Length); - - return random < keywordsFound.Count ? keywordsFound[random] : Responses[random - keywordsFound.Count]; - } - - public bool OnSpeech(Mobile mob, Mobile speaker, string text) - { - if ((Flags & IHSFlags.OnSpeech) == 0 || m_Keywords == null || Responses == null || m_KeywordHash == null) - return false; // not enabled - - if (!speaker.Alive) - return false; - - if (!speaker.InRange(mob, 3)) - return false; - - if ((speaker.Direction & Direction.Mask) != speaker.GetDirectionTo(mob)) - return false; - - if ((mob.Direction & Direction.Mask) != mob.GetDirectionTo(speaker)) - return false; - - string[] split = text.Split(' '); - List keywordsFound = new List(); - - for (int i = 0; i < split.Length; ++i) - if (m_KeywordHash.TryGetValue(split[i], out string keyword)) - keywordsFound.Add(keyword); - - if (keywordsFound.Count > 0) - { - string responseWord; - - if (Utility.RandomBool()) - responseWord = GetRandomResponseWord(keywordsFound); - else - responseWord = keywordsFound.RandomElement(); - - string secondResponseWord = GetRandomResponseWord(keywordsFound); - - StringBuilder response = new StringBuilder(); - - switch (Utility.Random(6)) + public void SayRandomTranslate(Mobile mob, params string[] sentancesInEnglish) { - default: - case 0: - { - response.Append("Me ").Append(responseWord).Append('?'); - break; - } - case 1: - { - response.Append(responseWord).Append(" thee!"); - response.Replace(responseWord[0], char.ToUpper(responseWord[0]), 0, 1); - break; - } - case 2: - { - response.Append(responseWord).Append('?'); - response.Replace(responseWord[0], char.ToUpper(responseWord[0]), 0, 1); - break; - } - case 3: - { - response.Append(responseWord).Append("! ").Append(secondResponseWord).Append('.'); - response.Replace(responseWord[0], char.ToUpper(responseWord[0]), 0, 1); - response.Replace(secondResponseWord[0], char.ToUpper(secondResponseWord[0]), responseWord.Length + 2, 1); - break; - } - case 4: - { - response.Append(responseWord).Append('.'); - response.Replace(responseWord[0], char.ToUpper(responseWord[0]), 0, 1); - break; - } - case 5: - { - response.Append(responseWord).Append("? ").Append(secondResponseWord).Append('.'); - response.Replace(responseWord[0], char.ToUpper(responseWord[0]), 0, 1); - response.Replace(secondResponseWord[0], char.ToUpper(secondResponseWord[0]), responseWord.Length + 2, 1); - break; - } + SaySentance(mob, Utility.RandomMinMax(2, 3)); + mob.Say(sentancesInEnglish.RandomElement()); } - int maxWords = split.Length / 2 + 1; + private string GetRandomResponseWord(List keywordsFound) + { + var random = Utility.Random(keywordsFound.Count + Responses.Length); - if (maxWords < 2) - maxWords = 2; - else if (maxWords > 6) - maxWords = 6; + return random < keywordsFound.Count ? keywordsFound[random] : Responses[random - keywordsFound.Count]; + } - SaySentance(mob, Utility.RandomMinMax(2, maxWords)); - mob.Say(response.ToString()); + public bool OnSpeech(Mobile mob, Mobile speaker, string text) + { + if ((Flags & IHSFlags.OnSpeech) == 0 || m_Keywords == null || Responses == null || m_KeywordHash == null) + return false; // not enabled - return true; - } + if (!speaker.Alive) + return false; - return false; + if (!speaker.InRange(mob, 3)) + return false; + + if ((speaker.Direction & Direction.Mask) != speaker.GetDirectionTo(mob)) + return false; + + if ((mob.Direction & Direction.Mask) != mob.GetDirectionTo(speaker)) + return false; + + var split = text.Split(' '); + var keywordsFound = new List(); + + for (var i = 0; i < split.Length; ++i) + if (m_KeywordHash.TryGetValue(split[i], out var keyword)) + keywordsFound.Add(keyword); + + if (keywordsFound.Count > 0) + { + string responseWord; + + if (Utility.RandomBool()) + responseWord = GetRandomResponseWord(keywordsFound); + else + responseWord = keywordsFound.RandomElement(); + + var secondResponseWord = GetRandomResponseWord(keywordsFound); + + var response = new StringBuilder(); + + switch (Utility.Random(6)) + { + default: + case 0: + { + response.Append("Me ").Append(responseWord).Append('?'); + break; + } + case 1: + { + response.Append(responseWord).Append(" thee!"); + response.Replace(responseWord[0], char.ToUpper(responseWord[0]), 0, 1); + break; + } + case 2: + { + response.Append(responseWord).Append('?'); + response.Replace(responseWord[0], char.ToUpper(responseWord[0]), 0, 1); + break; + } + case 3: + { + response.Append(responseWord).Append("! ").Append(secondResponseWord).Append('.'); + response.Replace(responseWord[0], char.ToUpper(responseWord[0]), 0, 1); + response.Replace( + secondResponseWord[0], + char.ToUpper(secondResponseWord[0]), + responseWord.Length + 2, + 1 + ); + break; + } + case 4: + { + response.Append(responseWord).Append('.'); + response.Replace(responseWord[0], char.ToUpper(responseWord[0]), 0, 1); + break; + } + case 5: + { + response.Append(responseWord).Append("? ").Append(secondResponseWord).Append('.'); + response.Replace(responseWord[0], char.ToUpper(responseWord[0]), 0, 1); + response.Replace( + secondResponseWord[0], + char.ToUpper(secondResponseWord[0]), + responseWord.Length + 2, + 1 + ); + break; + } + } + + var maxWords = split.Length / 2 + 1; + + if (maxWords < 2) + maxWords = 2; + else if (maxWords > 6) + maxWords = 6; + + SaySentance(mob, Utility.RandomMinMax(2, maxWords)); + mob.Say(response.ToString()); + + return true; + } + + return false; + } + + public void OnDeath(Mobile mob) + { + if ((Flags & IHSFlags.OnDeath) == 0) + return; // not enabled + + if (Utility.Random(100) < 90) + return; // 90% chance to do nothing; 10% chance to talk + + SayRandomTranslate( + mob, + "Revenge!", + "NOOooo!", + "I... I...", + "Me no die!", + "Me die!", + "Must... not die...", + "Oooh, me hurt...", + "Me dying?" + ); + } + + public void OnMovement(Mobile mob, Mobile mover, Point3D oldLocation) + { + if ((Flags & IHSFlags.OnMovement) == 0) + return; // not enabled + + if (!mover.Player || mover.Hidden && mover.AccessLevel > AccessLevel.Player) + return; + + if (!mob.InRange(mover, 5) || mob.InRange(oldLocation, 5)) + return; // only talk when they enter 5 tile range + + if (Utility.Random(100) < 90) + return; // 90% chance to do nothing; 10% chance to talk + + SaySentance(mob, 6); + } + + public void OnDamage(Mobile mob, int amount) + { + if ((Flags & IHSFlags.OnDamaged) == 0) + return; // not enabled + + if (Utility.Random(100) < 90) + return; // 90% chance to do nothing; 10% chance to talk + + if (amount < 5) + SayRandomTranslate( + mob, + "Ouch!", + "Me not hurt bad!", + "Thou fight bad.", + "Thy blows soft!", + "You bad with weapon!" + ); + else + SayRandomTranslate( + mob, + "Ouch! Me hurt!", + "No, kill me not!", + "Me hurt!", + "Away with thee!", + "Oof! That hurt!", + "Aaah! That hurt...", + "Good blow!" + ); + } + + public void OnConstruct(Mobile mob) + { + mob.SpeechHue = Hue; + } + + public void SaySentance(Mobile mob, int wordCount) + { + mob.Say(ConstructSentance(wordCount)); + mob.PlaySound(Sound); + } } - - public void OnDeath(Mobile mob) - { - if ((Flags & IHSFlags.OnDeath) == 0) - return; // not enabled - - if (Utility.Random(100) < 90) - return; // 90% chance to do nothing; 10% chance to talk - - SayRandomTranslate(mob, - "Revenge!", - "NOOooo!", - "I... I...", - "Me no die!", - "Me die!", - "Must... not die...", - "Oooh, me hurt...", - "Me dying?"); - } - - public void OnMovement(Mobile mob, Mobile mover, Point3D oldLocation) - { - if ((Flags & IHSFlags.OnMovement) == 0) - return; // not enabled - - if (!mover.Player || (mover.Hidden && mover.AccessLevel > AccessLevel.Player)) - return; - - if (!mob.InRange(mover, 5) || mob.InRange(oldLocation, 5)) - return; // only talk when they enter 5 tile range - - if (Utility.Random(100) < 90) - return; // 90% chance to do nothing; 10% chance to talk - - SaySentance(mob, 6); - } - - public void OnDamage(Mobile mob, int amount) - { - if ((Flags & IHSFlags.OnDamaged) == 0) - return; // not enabled - - if (Utility.Random(100) < 90) - return; // 90% chance to do nothing; 10% chance to talk - - if (amount < 5) - SayRandomTranslate(mob, - "Ouch!", - "Me not hurt bad!", - "Thou fight bad.", - "Thy blows soft!", - "You bad with weapon!"); - else - SayRandomTranslate(mob, - "Ouch! Me hurt!", - "No, kill me not!", - "Me hurt!", - "Away with thee!", - "Oof! That hurt!", - "Aaah! That hurt...", - "Good blow!"); - } - - public void OnConstruct(Mobile mob) - { - mob.SpeechHue = Hue; - } - - public void SaySentance(Mobile mob, int wordCount) - { - mob.Say(ConstructSentance(wordCount)); - mob.PlaySound(Sound); - } - } } diff --git a/Projects/UOContent/Misc/Keywords.cs b/Projects/UOContent/Misc/Keywords.cs index 9aedce837..2ed875112 100644 --- a/Projects/UOContent/Misc/Keywords.cs +++ b/Projects/UOContent/Misc/Keywords.cs @@ -4,51 +4,55 @@ using Server.Mobiles; namespace Server.Misc { - public static class Keywords - { - public static void Initialize() + public static class Keywords { - // Register our speech handler - EventSink.Speech += EventSink_Speech; - } - - public static void EventSink_Speech(SpeechEventArgs args) - { - Mobile from = args.Mobile; - int[] keywords = args.Keywords; - - for (int i = 0; i < keywords.Length; ++i) - switch (keywords[i]) + public static void Initialize() { - case 0x002A: // *i resign from my guild* - { - ((Guild)from.Guild)?.RemoveMember(from); + // Register our speech handler + EventSink.Speech += EventSink_Speech; + } - break; - } - case 0x0032: // *i must consider my sins* - { - if (!Core.SE) - { - from.SendMessage("Short Term Murders : {0}", from.ShortTermMurders); - from.SendMessage("Long Term Murders : {0}", from.Kills); - } - else - { - from.SendMessage(0x3B2, "Short Term Murders: {0} Long Term Murders: {1}", from.ShortTermMurders, - from.Kills); - } + public static void EventSink_Speech(SpeechEventArgs args) + { + var from = args.Mobile; + var keywords = args.Keywords; - break; - } - case 0x0035: // i renounce my young player status* - { - if (from is PlayerMobile mobile && mobile.Young && !mobile.HasGump()) - mobile.SendGump(new RenounceYoungGump()); + for (var i = 0; i < keywords.Length; ++i) + switch (keywords[i]) + { + case 0x002A: // *i resign from my guild* + { + ((Guild)from.Guild)?.RemoveMember(from); - break; - } + break; + } + case 0x0032: // *i must consider my sins* + { + if (!Core.SE) + { + from.SendMessage("Short Term Murders : {0}", from.ShortTermMurders); + from.SendMessage("Long Term Murders : {0}", from.Kills); + } + else + { + from.SendMessage( + 0x3B2, + "Short Term Murders: {0} Long Term Murders: {1}", + from.ShortTermMurders, + from.Kills + ); + } + + break; + } + case 0x0035: // i renounce my young player status* + { + if (from is PlayerMobile mobile && mobile.Young && !mobile.HasGump()) + mobile.SendGump(new RenounceYoungGump()); + + break; + } + } } } - } } diff --git a/Projects/UOContent/Misc/LanguageStatistics.cs b/Projects/UOContent/Misc/LanguageStatistics.cs index 40131a242..4a9889f59 100644 --- a/Projects/UOContent/Misc/LanguageStatistics.cs +++ b/Projects/UOContent/Misc/LanguageStatistics.cs @@ -21,7 +21,7 @@ namespace Server.Misc **/ public class LanguageStatistics { - private static readonly InternationalCode[] InternationalCodes = + private static readonly InternationalCode[] InternationalCodes = { new InternationalCode("ARA", "Arabic", "Saudi Arabia", "العربية", "السعودية"), new InternationalCode("ARI", "Arabic", "Iraq", "العربية", "العراق"), @@ -160,48 +160,48 @@ namespace Server.Misc new InternationalCode("KOK", "Konkani", "India", "कोंकणी", "भारत") }; - private static readonly bool DefaultLocalNames = false; - private static readonly bool ShowAlternatives = true; - private static readonly bool CountAccounts = true; // will consider only first character's valid language + private static readonly bool DefaultLocalNames = false; + private static readonly bool ShowAlternatives = true; + private static readonly bool CountAccounts = true; // will consider only first character's valid language - private static string GetFormattedInfo(string code) + private static string GetFormattedInfo(string code) { if (code == null || code.Length != 3) return $"Unknown code {code}"; - for (int i = 0; i < InternationalCodes.Length; i++) + for (var i = 0; i < InternationalCodes.Length; i++) if (code == InternationalCodes[i].Code) return $"{InternationalCodes[i].GetName()}"; return $"Unknown code {code}"; } - public static void Initialize() + public static void Initialize() { CommandSystem.Register("LanguageStatistics", AccessLevel.Administrator, LanguageStatistics_OnCommand); } - [Usage("LanguageStatistics")] + [Usage("LanguageStatistics")] [Description("Generate a file containing the list of languages for each PlayerMobile.")] public static void LanguageStatistics_OnCommand(CommandEventArgs e) { - Dictionary ht = new Dictionary(); + var ht = new Dictionary(); - using StreamWriter writer = new StreamWriter("languages.txt"); + using var writer = new StreamWriter("languages.txt"); if (CountAccounts) foreach (Account acc in Accounts.GetAccounts()) - for (int i = 0; i < acc.Length; i++) + for (var i = 0; i < acc.Length; i++) { - Mobile mob = acc[i]; + var mob = acc[i]; - string lang = mob?.Language; + var lang = mob?.Language; if (lang == null) continue; lang = lang.ToUpper(); - if (ht.TryGetValue(lang, out InternationalCodeCounter codes)) + if (ht.TryGetValue(lang, out var codes)) codes.Increase(); else ht[lang] = new InternationalCodeCounter(lang); @@ -209,17 +209,17 @@ namespace Server.Misc break; } else - foreach (Mobile mob in World.Mobiles.Values) + foreach (var mob in World.Mobiles.Values) if (mob.Player) { - string lang = mob.Language; + var lang = mob.Language; if (lang == null) continue; lang = lang.ToUpper(); - if (ht.TryGetValue(lang, out InternationalCodeCounter codes)) + if (ht.TryGetValue(lang, out var codes)) codes.Increase(); else ht[lang] = new InternationalCodeCounter(lang); @@ -232,10 +232,10 @@ namespace Server.Misc writer.WriteLine(); // sort the list - List list = new List(ht.Values); + var list = new List(ht.Values); list.Sort(InternationalCodeComparer.Instance); - foreach (InternationalCodeCounter c in list) + foreach (var c in list) writer.WriteLine($"{GetFormattedInfo(c.Code)}‎ : {c.Count}"); e.Mobile.SendMessage("Languages list generated."); @@ -294,17 +294,17 @@ namespace Server.Misc private class InternationalCodeCounter { - public InternationalCodeCounter(string code) + public InternationalCodeCounter(string code) { Code = code; Count = 1; } - public string Code { get; } + public string Code { get; } - public int Count { get; private set; } + public int Count { get; private set; } - public void Increase() + public void Increase() { Count++; } @@ -312,9 +312,9 @@ namespace Server.Misc private class InternationalCodeComparer : IComparer { - public static readonly InternationalCodeComparer Instance = new InternationalCodeComparer(); + public static readonly InternationalCodeComparer Instance = new InternationalCodeComparer(); - public int Compare(InternationalCodeCounter x, InternationalCodeCounter y) + public int Compare(InternationalCodeCounter x, InternationalCodeCounter y) { string a = null, b = null; int ca = 0, cb = 0; diff --git a/Projects/UOContent/Misc/LightCycle.cs b/Projects/UOContent/Misc/LightCycle.cs index 30f084dc6..bd5443902 100644 --- a/Projects/UOContent/Misc/LightCycle.cs +++ b/Projects/UOContent/Misc/LightCycle.cs @@ -4,128 +4,129 @@ using Server.Network; namespace Server { - public class LightCycle - { - public const int DayLevel = 0; - public const int NightLevel = 12; - public const int DungeonLevel = 26; - public const int JailLevel = 9; - - private static int m_LevelOverride = int.MinValue; - - public static int LevelOverride + public class LightCycle { - get => m_LevelOverride; - set - { - m_LevelOverride = value; + public const int DayLevel = 0; + public const int NightLevel = 12; + public const int DungeonLevel = 26; + public const int JailLevel = 9; - for (int i = 0; i < TcpServer.Instances.Count; ++i) + private static int m_LevelOverride = int.MinValue; + + public static int LevelOverride { - NetState ns = TcpServer.Instances[i]; - Mobile m = ns.Mobile; + get => m_LevelOverride; + set + { + m_LevelOverride = value; - m?.CheckLightLevels(false); + for (var i = 0; i < TcpServer.Instances.Count; ++i) + { + var ns = TcpServer.Instances[i]; + var m = ns.Mobile; + + m?.CheckLightLevels(false); + } + } } - } - } - public static void Initialize() - { - new LightCycleTimer().Start(); - EventSink.Login += OnLogin; - - CommandSystem.Register("GlobalLight", AccessLevel.GameMaster, Light_OnCommand); - } - - [Usage("GlobalLight ")] - [Description("Sets the current global light level.")] - private static void Light_OnCommand(CommandEventArgs e) - { - if (e.Length >= 1) - { - LevelOverride = e.GetInt32(0); - e.Mobile.SendMessage("Global light level override has been changed to {0}.", m_LevelOverride); - } - else - { - LevelOverride = int.MinValue; - e.Mobile.SendMessage("Global light level override has been cleared."); - } - } - - public static void OnLogin(Mobile m) - { - m.CheckLightLevels(true); - } - - public static int ComputeLevelFor(Mobile from) - { - if (m_LevelOverride > int.MinValue) - return m_LevelOverride; - - Clock.GetTime(from.Map, from.X, from.Y, out int hours, out int minutes); - - /* OSI times: - * - * Midnight -> 3:59 AM : Night - * 4:00 AM -> 11:59 PM : Day - * - * RunUO times: - * - * 10:00 PM -> 11:59 PM : Scale to night - * Midnight -> 3:59 AM : Night - * 4:00 AM -> 5:59 AM : Scale to day - * 6:00 AM -> 9:59 PM : Day - */ - - if (hours < 4) - return NightLevel; - - if (hours < 6) - return NightLevel + ((hours - 4) * 60 + minutes) * (DayLevel - NightLevel) / 120; - - if (hours < 22) - return DayLevel; - - if (hours < 24) - return DayLevel + ((hours - 22) * 60 + minutes) * (NightLevel - DayLevel) / 120; - - return NightLevel; // should never be - } - - private class LightCycleTimer : Timer - { - public LightCycleTimer() : base(TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(5.0)) => Priority = TimerPriority.FiveSeconds; - - protected override void OnTick() - { - for (int i = 0; i < TcpServer.Instances.Count; ++i) + public static void Initialize() { - NetState ns = TcpServer.Instances[i]; - Mobile m = ns.Mobile; + new LightCycleTimer().Start(); + EventSink.Login += OnLogin; - m?.CheckLightLevels(false); + CommandSystem.Register("GlobalLight", AccessLevel.GameMaster, Light_OnCommand); + } + + [Usage("GlobalLight ")] + [Description("Sets the current global light level.")] + private static void Light_OnCommand(CommandEventArgs e) + { + if (e.Length >= 1) + { + LevelOverride = e.GetInt32(0); + e.Mobile.SendMessage("Global light level override has been changed to {0}.", m_LevelOverride); + } + else + { + LevelOverride = int.MinValue; + e.Mobile.SendMessage("Global light level override has been cleared."); + } + } + + public static void OnLogin(Mobile m) + { + m.CheckLightLevels(true); + } + + public static int ComputeLevelFor(Mobile from) + { + if (m_LevelOverride > int.MinValue) + return m_LevelOverride; + + Clock.GetTime(from.Map, from.X, from.Y, out var hours, out int minutes); + + /* OSI times: + * + * Midnight -> 3:59 AM : Night + * 4:00 AM -> 11:59 PM : Day + * + * RunUO times: + * + * 10:00 PM -> 11:59 PM : Scale to night + * Midnight -> 3:59 AM : Night + * 4:00 AM -> 5:59 AM : Scale to day + * 6:00 AM -> 9:59 PM : Day + */ + + if (hours < 4) + return NightLevel; + + if (hours < 6) + return NightLevel + ((hours - 4) * 60 + minutes) * (DayLevel - NightLevel) / 120; + + if (hours < 22) + return DayLevel; + + if (hours < 24) + return DayLevel + ((hours - 22) * 60 + minutes) * (NightLevel - DayLevel) / 120; + + return NightLevel; // should never be + } + + private class LightCycleTimer : Timer + { + public LightCycleTimer() : base(TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(5.0)) => + Priority = TimerPriority.FiveSeconds; + + protected override void OnTick() + { + for (var i = 0; i < TcpServer.Instances.Count; ++i) + { + var ns = TcpServer.Instances[i]; + var m = ns.Mobile; + + m?.CheckLightLevels(false); + } + } + } + + public class NightSightTimer : Timer + { + private readonly Mobile m_Owner; + + public NightSightTimer(Mobile owner) : base(TimeSpan.FromMinutes(Utility.Random(15, 25))) + { + m_Owner = owner; + Priority = TimerPriority.OneMinute; + } + + protected override void OnTick() + { + m_Owner.EndAction(); + m_Owner.LightLevel = 0; + BuffInfo.RemoveBuff(m_Owner, BuffIcon.NightSight); + } } - } } - - public class NightSightTimer : Timer - { - private readonly Mobile m_Owner; - - public NightSightTimer(Mobile owner) : base(TimeSpan.FromMinutes(Utility.Random(15, 25))) - { - m_Owner = owner; - Priority = TimerPriority.OneMinute; - } - - protected override void OnTick() - { - m_Owner.EndAction(); - m_Owner.LightLevel = 0; - BuffInfo.RemoveBuff(m_Owner, BuffIcon.NightSight); - } - } - } } diff --git a/Projects/UOContent/Misc/LoginStats.cs b/Projects/UOContent/Misc/LoginStats.cs index 537b1b532..f8f5d0784 100644 --- a/Projects/UOContent/Misc/LoginStats.cs +++ b/Projects/UOContent/Misc/LoginStats.cs @@ -2,27 +2,31 @@ using Server.Network; namespace Server.Misc { - public class LoginStats - { - public static void Initialize() + public class LoginStats { - // Register our event handler - EventSink.Login += EventSink_Login; - } + public static void Initialize() + { + // Register our event handler + EventSink.Login += EventSink_Login; + } - private static void EventSink_Login(Mobile m) - { - int userCount = TcpServer.Instances.Count; - int itemCount = World.Items.Count; - int mobileCount = World.Mobiles.Count; + private static void EventSink_Login(Mobile m) + { + var userCount = TcpServer.Instances.Count; + var itemCount = World.Items.Count; + var mobileCount = World.Mobiles.Count; - m.SendMessage( - "Welcome, {0}! There {1} currently {2} user{3} online, with {4} item{5} and {6} mobile{7} in the world.", - m.Name, - userCount == 1 ? "is" : "are", - userCount, userCount == 1 ? "" : "s", - itemCount, itemCount == 1 ? "" : "s", - mobileCount, mobileCount == 1 ? "" : "s"); + m.SendMessage( + "Welcome, {0}! There {1} currently {2} user{3} online, with {4} item{5} and {6} mobile{7} in the world.", + m.Name, + userCount == 1 ? "is" : "are", + userCount, + userCount == 1 ? "" : "s", + itemCount, + itemCount == 1 ? "" : "s", + mobileCount, + mobileCount == 1 ? "" : "s" + ); + } } - } } diff --git a/Projects/UOContent/Misc/Loot.cs b/Projects/UOContent/Misc/Loot.cs index b1dbd98ca..e32f7f325 100644 --- a/Projects/UOContent/Misc/Loot.cs +++ b/Projects/UOContent/Misc/Loot.cs @@ -4,660 +4,742 @@ using Server.Utilities; namespace Server { - public class Loot - { - public static Type[] MLWeaponTypes { get; } = + public class Loot { - typeof(AssassinSpike), typeof(DiamondMace), typeof(ElvenMachete), - typeof(ElvenSpellblade), typeof(Leafblade), typeof(OrnateAxe), - typeof(RadiantScimitar), typeof(RuneBlade), typeof(WarCleaver), - typeof(WildStaff) - }; - - public static Type[] MLRangedWeaponTypes { get; } = - { - typeof(ElvenCompositeLongbow), typeof(MagicalShortbow) - }; - - public static Type[] MLArmorTypes { get; } = - { - typeof(Circlet), typeof(GemmedCirclet), typeof(LeafTonlet), - typeof(RavenHelm), typeof(RoyalCirclet), typeof(VultureHelm), - typeof(WingedHelm), typeof(LeafArms), typeof(LeafChest), - typeof(LeafGloves), typeof(LeafGorget), typeof(LeafLegs), - typeof(WoodlandArms), typeof(WoodlandChest), typeof(WoodlandGloves), - typeof(WoodlandGorget), typeof(WoodlandLegs), typeof(HideChest), - typeof(HideGloves), typeof(HideGorget), typeof(HidePants), - typeof(HidePauldrons) - }; - - public static Type[] MLClothingTypes { get; } = - { - typeof(MaleElvenRobe), typeof(FemaleElvenRobe), typeof(ElvenPants), - typeof(ElvenShirt), typeof(ElvenDarkShirt), typeof(ElvenBoots), - typeof(VultureHelm), typeof(WoodlandBelt) - }; - - public static Type[] SEWeaponTypes { get; } = - { - typeof(Bokuto), typeof(Daisho), typeof(Kama), - typeof(Lajatang), typeof(NoDachi), typeof(Nunchaku), - typeof(Sai), typeof(Tekagi), typeof(Tessen), - typeof(Tetsubo), typeof(Wakizashi) - }; - - public static Type[] AosWeaponTypes { get; } = - { - typeof(Scythe), typeof(BoneHarvester), typeof(Scepter), - typeof(BladedStaff), typeof(Pike), typeof(DoubleBladedStaff), - typeof(Lance), typeof(CrescentBlade) - }; - - public static Type[] WeaponTypes { get; } = - { - typeof(Axe), typeof(BattleAxe), typeof(DoubleAxe), - typeof(ExecutionersAxe), typeof(Hatchet), typeof(LargeBattleAxe), - typeof(TwoHandedAxe), typeof(WarAxe), typeof(Club), - typeof(Mace), typeof(Maul), typeof(WarHammer), - typeof(WarMace), typeof(Bardiche), typeof(Halberd), - typeof(Spear), typeof(ShortSpear), typeof(Pitchfork), - typeof(WarFork), typeof(BlackStaff), typeof(GnarledStaff), - typeof(QuarterStaff), typeof(Broadsword), typeof(Cutlass), - typeof(Katana), typeof(Kryss), typeof(Longsword), - typeof(Scimitar), typeof(VikingSword), typeof(Pickaxe), - typeof(HammerPick), typeof(ButcherKnife), typeof(Cleaver), - typeof(Dagger), typeof(SkinningKnife), typeof(ShepherdsCrook) - }; - - public static Type[] SERangedWeaponTypes { get; } = - { - typeof(Yumi) - }; - - public static Type[] AosRangedWeaponTypes { get; } = - { - typeof(CompositeBow), typeof(RepeatingCrossbow) - }; - - public static Type[] RangedWeaponTypes { get; } = - { - typeof(Bow), typeof(Crossbow), typeof(HeavyCrossbow) - }; - - public static Type[] SEArmorTypes { get; } = - { - typeof(ChainHatsuburi), typeof(LeatherDo), typeof(LeatherHaidate), - typeof(LeatherHiroSode), typeof(LeatherJingasa), typeof(LeatherMempo), - typeof(LeatherNinjaHood), typeof(LeatherNinjaJacket), typeof(LeatherNinjaMitts), - typeof(LeatherNinjaPants), typeof(LeatherSuneate), typeof(DecorativePlateKabuto), - typeof(HeavyPlateJingasa), typeof(LightPlateJingasa), typeof(PlateBattleKabuto), - typeof(PlateDo), typeof(PlateHaidate), typeof(PlateHatsuburi), - typeof(PlateHiroSode), typeof(PlateMempo), typeof(PlateSuneate), - typeof(SmallPlateJingasa), typeof(StandardPlateKabuto), typeof(StuddedDo), - typeof(StuddedHaidate), typeof(StuddedHiroSode), typeof(StuddedMempo), - typeof(StuddedSuneate) - }; - - public static Type[] ArmorTypes { get; } = - { - typeof(BoneArms), typeof(BoneChest), typeof(BoneGloves), - typeof(BoneLegs), typeof(BoneHelm), typeof(ChainChest), - typeof(ChainLegs), typeof(ChainCoif), typeof(Bascinet), - typeof(CloseHelm), typeof(Helmet), typeof(NorseHelm), - typeof(OrcHelm), typeof(FemaleLeatherChest), typeof(LeatherArms), - typeof(LeatherBustierArms), typeof(LeatherChest), typeof(LeatherGloves), - typeof(LeatherGorget), typeof(LeatherLegs), typeof(LeatherShorts), - typeof(LeatherSkirt), typeof(LeatherCap), typeof(FemalePlateChest), - typeof(PlateArms), typeof(PlateChest), typeof(PlateGloves), - typeof(PlateGorget), typeof(PlateHelm), typeof(PlateLegs), - typeof(RingmailArms), typeof(RingmailChest), typeof(RingmailGloves), - typeof(RingmailLegs), typeof(FemaleStuddedChest), typeof(StuddedArms), - typeof(StuddedBustierArms), typeof(StuddedChest), typeof(StuddedGloves), - typeof(StuddedGorget), typeof(StuddedLegs) - }; - - public static Type[] AosShieldTypes { get; } = - { - typeof(ChaosShield), typeof(OrderShield) - }; - - public static Type[] ShieldTypes { get; } = - { - typeof(BronzeShield), typeof(Buckler), typeof(HeaterShield), - typeof(MetalShield), typeof(MetalKiteShield), typeof(WoodenKiteShield), - typeof(WoodenShield) - }; - - public static Type[] GemTypes { get; } = - { - typeof(Amber), typeof(Amethyst), typeof(Citrine), - typeof(Diamond), typeof(Emerald), typeof(Ruby), - typeof(Sapphire), typeof(StarSapphire), typeof(Tourmaline) - }; - - public static Type[] JewelryTypes { get; } = - { - typeof(GoldRing), typeof(GoldBracelet), - typeof(SilverRing), typeof(SilverBracelet) - }; - - public static Type[] RegTypes { get; } = - { - typeof(BlackPearl), typeof(Bloodmoss), typeof(Garlic), - typeof(Ginseng), typeof(MandrakeRoot), typeof(Nightshade), - typeof(SulfurousAsh), typeof(SpidersSilk) - }; - - public static Type[] NecroRegTypes { get; } = - { - typeof(BatWing), typeof(GraveDust), typeof(DaemonBlood), - typeof(NoxCrystal), typeof(PigIron) - }; - - public static Type[] PotionTypes { get; } = - { - typeof(AgilityPotion), typeof(StrengthPotion), typeof(RefreshPotion), - typeof(LesserCurePotion), typeof(LesserHealPotion), typeof(LesserPoisonPotion) - }; - - public static Type[] SEInstrumentTypes { get; } = - { - typeof(BambooFlute) - }; - - public static Type[] InstrumentTypes { get; } = - { - typeof(Drums), typeof(Harp), typeof(LapHarp), - typeof(Lute), typeof(Tambourine), typeof(TambourineTassel) - }; - - public static Type[] StatueTypes { get; } = - { - typeof(StatueSouth), typeof(StatueSouth2), typeof(StatueNorth), - typeof(StatueWest), typeof(StatueEast), typeof(StatueEast2), - typeof(StatueSouthEast), typeof(BustSouth), typeof(BustEast) - }; - - public static Type[] RegularScrollTypes { get; } = - { - typeof(ReactiveArmorScroll), typeof(ClumsyScroll), typeof(CreateFoodScroll), typeof(FeeblemindScroll), - typeof(HealScroll), typeof(MagicArrowScroll), typeof(NightSightScroll), typeof(WeakenScroll), - typeof(AgilityScroll), typeof(CunningScroll), typeof(CureScroll), typeof(HarmScroll), - typeof(MagicTrapScroll), typeof(MagicUnTrapScroll), typeof(ProtectionScroll), typeof(StrengthScroll), - typeof(BlessScroll), typeof(FireballScroll), typeof(MagicLockScroll), typeof(PoisonScroll), - typeof(TelekinesisScroll), typeof(TeleportScroll), typeof(UnlockScroll), typeof(WallOfStoneScroll), - typeof(ArchCureScroll), typeof(ArchProtectionScroll), typeof(CurseScroll), typeof(FireFieldScroll), - typeof(GreaterHealScroll), typeof(LightningScroll), typeof(ManaDrainScroll), typeof(RecallScroll), - typeof(BladeSpiritsScroll), typeof(DispelFieldScroll), typeof(IncognitoScroll), typeof(MagicReflectScroll), - typeof(MindBlastScroll), typeof(ParalyzeScroll), typeof(PoisonFieldScroll), typeof(SummonCreatureScroll), - typeof(DispelScroll), typeof(EnergyBoltScroll), typeof(ExplosionScroll), typeof(InvisibilityScroll), - typeof(MarkScroll), typeof(MassCurseScroll), typeof(ParalyzeFieldScroll), typeof(RevealScroll), - typeof(ChainLightningScroll), typeof(EnergyFieldScroll), typeof(FlamestrikeScroll), typeof(GateTravelScroll), - typeof(ManaVampireScroll), typeof(MassDispelScroll), typeof(MeteorSwarmScroll), typeof(PolymorphScroll), - typeof(EarthquakeScroll), typeof(EnergyVortexScroll), typeof(ResurrectionScroll), - typeof(SummonAirElementalScroll), - typeof(SummonDaemonScroll), typeof(SummonEarthElementalScroll), typeof(SummonFireElementalScroll), - typeof(SummonWaterElementalScroll) - }; - - public static Type[] NecromancyScrollTypes { get; } = - { - typeof(AnimateDeadScroll), typeof(BloodOathScroll), typeof(CorpseSkinScroll), typeof(CurseWeaponScroll), - typeof(EvilOmenScroll), typeof(HorrificBeastScroll), typeof(LichFormScroll), typeof(MindRotScroll), - typeof(PainSpikeScroll), typeof(PoisonStrikeScroll), typeof(StrangleScroll), typeof(SummonFamiliarScroll), - typeof(VampiricEmbraceScroll), typeof(VengefulSpiritScroll), typeof(WitherScroll), typeof(WraithFormScroll) - }; - - public static Type[] SENecromancyScrollTypes { get; } = - { - typeof(AnimateDeadScroll), typeof(BloodOathScroll), typeof(CorpseSkinScroll), typeof(CurseWeaponScroll), - typeof(EvilOmenScroll), typeof(HorrificBeastScroll), typeof(LichFormScroll), typeof(MindRotScroll), - typeof(PainSpikeScroll), typeof(PoisonStrikeScroll), typeof(StrangleScroll), typeof(SummonFamiliarScroll), - typeof(VampiricEmbraceScroll), typeof(VengefulSpiritScroll), typeof(WitherScroll), typeof(WraithFormScroll), - typeof(ExorcismScroll) - }; - - public static Type[] PaladinScrollTypes { get; } = Array.Empty(); - - public static Type[] ArcanistScrollTypes { get; } = - { - typeof(ArcaneCircleScroll), typeof(GiftOfRenewalScroll), typeof(ImmolatingWeaponScroll), - typeof(AttuneWeaponScroll), - typeof(ThunderstormScroll), - typeof(NatureFuryScroll), /*typeof( SummonFeyScroll ), typeof( SummonFiendScroll ),*/ - typeof(ReaperFormScroll), typeof(WildfireScroll), typeof(EssenceOfWindScroll), typeof(DryadAllureScroll), - typeof(EtherealVoyageScroll), typeof(WordOfDeathScroll), typeof(GiftOfLifeScroll), - typeof(ArcaneEmpowermentScroll) - }; - - public static Type[] GrimmochJournalTypes { get; } = - { - typeof(GrimmochJournal1), typeof(GrimmochJournal2), typeof(GrimmochJournal3), - typeof(GrimmochJournal6), typeof(GrimmochJournal7), typeof(GrimmochJournal11), - typeof(GrimmochJournal14), typeof(GrimmochJournal17), typeof(GrimmochJournal23) - }; - - public static Type[] LysanderNotebookTypes { get; } = - { - typeof(LysanderNotebook1), typeof(LysanderNotebook2), typeof(LysanderNotebook3), - typeof(LysanderNotebook7), typeof(LysanderNotebook8), typeof(LysanderNotebook11) - }; - - public static Type[] TavarasJournalTypes { get; } = - { - typeof(TavarasJournal1), typeof(TavarasJournal2), typeof(TavarasJournal3), - typeof(TavarasJournal6), typeof(TavarasJournal7), typeof(TavarasJournal8), - typeof(TavarasJournal9), typeof(TavarasJournal11), typeof(TavarasJournal14), - typeof(TavarasJournal16), typeof(TavarasJournal16b), typeof(TavarasJournal17), - typeof(TavarasJournal19) - }; - - public static Type[] NewWandTypes { get; } = - { - typeof(FireballWand), typeof(LightningWand), typeof(MagicArrowWand), - typeof(GreaterHealWand), typeof(HarmWand), typeof(HealWand) - }; - - public static Type[] WandTypes { get; } = - { - typeof(ClumsyWand), typeof(FeebleWand), - typeof(ManaDrainWand), typeof(WeaknessWand) - }; - - public static Type[] OldWandTypes { get; } = - { - typeof(IDWand) - }; - - public static Type[] SEClothingTypes { get; } = - { - typeof(ClothNinjaJacket), typeof(FemaleKimono), typeof(Hakama), - typeof(HakamaShita), typeof(JinBaori), typeof(Kamishimo), - typeof(MaleKimono), typeof(NinjaTabi), typeof(Obi), - typeof(SamuraiTabi), typeof(TattsukeHakama), typeof(Waraji) - }; - - public static Type[] AosClothingTypes { get; } = - { - typeof(FurSarong), typeof(FurCape), typeof(FlowerGarland), - typeof(GildedDress), typeof(FurBoots), typeof(FormalShirt) - }; - - public static Type[] ClothingTypes { get; } = - { - typeof(Cloak), - typeof(Bonnet), typeof(Cap), typeof(FeatheredHat), - typeof(FloppyHat), typeof(JesterHat), typeof(Surcoat), - typeof(SkullCap), typeof(StrawHat), typeof(TallStrawHat), - typeof(TricorneHat), typeof(WideBrimHat), typeof(WizardsHat), - typeof(BodySash), typeof(Doublet), typeof(Boots), - typeof(FullApron), typeof(JesterSuit), typeof(Sandals), - typeof(Tunic), typeof(Shoes), typeof(Shirt), - typeof(Kilt), typeof(Skirt), typeof(FancyShirt), - typeof(FancyDress), typeof(ThighBoots), typeof(LongPants), - typeof(PlainDress), typeof(Robe), typeof(ShortPants), - typeof(HalfApron) - }; - - public static Type[] SEHatTypes { get; } = - { - typeof(ClothNinjaHood), typeof(Kasa) - }; - - public static Type[] AosHatTypes { get; } = - { - typeof(FlowerGarland), typeof(BearMask), - typeof(DeerMask) // Are Bear& Deer mask inside the Pre-AoS loottables too? - }; - - public static Type[] HatTypes { get; } = - { - typeof(SkullCap), typeof(Bandana), typeof(FloppyHat), - typeof(Cap), typeof(WideBrimHat), typeof(StrawHat), - typeof(TallStrawHat), typeof(WizardsHat), typeof(Bonnet), - typeof(FeatheredHat), typeof(TricorneHat), typeof(JesterHat) - }; - - public static Type[] LibraryBookTypes { get; } = - { - typeof(GrammarOfOrcish), typeof(CallToAnarchy), typeof(ArmsAndWeaponsPrimer), - typeof(SongOfSamlethe), typeof(TaleOfThreeTribes), typeof(GuideToGuilds), - typeof(BirdsOfBritannia), typeof(BritannianFlora), typeof(ChildrenTalesVol2), - typeof(TalesOfVesperVol1), typeof(DeceitDungeonOfHorror), typeof(DimensionalTravel), - typeof(EthicalHedonism), typeof(MyStory), typeof(DiversityOfOurLand), - typeof(QuestOfVirtues), typeof(RegardingLlamas), typeof(TalkingToWisps), - typeof(TamingDragons), typeof(BoldStranger), typeof(BurningOfTrinsic), - typeof(TheFight), typeof(LifeOfATravellingMinstrel), typeof(MajorTradeAssociation), - typeof(RankingsOfTrades), typeof(WildGirlOfTheForest), typeof(TreatiseOnAlchemy), - typeof(VirtueBook) - }; - - public static BaseWand RandomWand() - { - if (Core.ML) - return Construct(NewWandTypes) as BaseWand; - if (Core.AOS) - return Construct(WandTypes, NewWandTypes) as BaseWand; - return Construct(OldWandTypes, WandTypes, NewWandTypes) as BaseWand; - } - - public static BaseClothing RandomClothing() => RandomClothing(false, false); - - public static BaseClothing RandomClothing(bool inTokuno, bool isMondain) - { - if (Core.ML && isMondain) - return Construct(MLClothingTypes, AosClothingTypes, ClothingTypes) as BaseClothing; - - if (Core.SE && inTokuno) - return Construct(SEClothingTypes, AosClothingTypes, ClothingTypes) as BaseClothing; - - if (Core.AOS) - return Construct(AosClothingTypes, ClothingTypes) as BaseClothing; - - return Construct(ClothingTypes) as BaseClothing; - } - - public static BaseWeapon RandomRangedWeapon() => RandomRangedWeapon(false, false); - - public static BaseWeapon RandomRangedWeapon(bool inTokuno, bool isMondain) - { - if (Core.ML && isMondain) - return Construct(MLRangedWeaponTypes, AosRangedWeaponTypes, RangedWeaponTypes) as BaseWeapon; - - if (Core.SE && inTokuno) - return Construct(SERangedWeaponTypes, AosRangedWeaponTypes, RangedWeaponTypes) as BaseWeapon; - - if (Core.AOS) - return Construct(AosRangedWeaponTypes, RangedWeaponTypes) as BaseWeapon; - - return Construct(RangedWeaponTypes) as BaseWeapon; - } - - public static BaseWeapon RandomWeapon() => RandomWeapon(false, false); - - public static BaseWeapon RandomWeapon(bool inTokuno, bool isMondain) - { - if (Core.ML && isMondain) - return Construct(MLWeaponTypes, AosWeaponTypes, WeaponTypes) as BaseWeapon; - - if (Core.SE && inTokuno) - return Construct(SEWeaponTypes, AosWeaponTypes, WeaponTypes) as BaseWeapon; - - if (Core.AOS) - return Construct(AosWeaponTypes, WeaponTypes) as BaseWeapon; - - return Construct(WeaponTypes) as BaseWeapon; - } - - public static Item RandomWeaponOrJewelry() => RandomWeaponOrJewelry(false, false); - - public static Item RandomWeaponOrJewelry(bool inTokuno, bool isMondain) - { - if (Core.ML && isMondain) - return Construct(MLWeaponTypes, AosWeaponTypes, WeaponTypes, JewelryTypes); - - if (Core.SE && inTokuno) - return Construct(SEWeaponTypes, AosWeaponTypes, WeaponTypes, JewelryTypes); - - if (Core.AOS) - return Construct(AosWeaponTypes, WeaponTypes, JewelryTypes); - - return Construct(WeaponTypes, JewelryTypes); - } - - public static BaseJewel RandomJewelry() => Construct(JewelryTypes) as BaseJewel; - - public static BaseArmor RandomArmor() => RandomArmor(false, false); - - public static BaseArmor RandomArmor(bool inTokuno, bool isMondain) - { - if (Core.ML && isMondain) - return Construct(MLArmorTypes, ArmorTypes) as BaseArmor; - - if (Core.SE && inTokuno) - return Construct(SEArmorTypes, ArmorTypes) as BaseArmor; - - return Construct(ArmorTypes) as BaseArmor; - } - - public static BaseHat RandomHat() => RandomHat(false); - - public static BaseHat RandomHat(bool inTokuno) - { - if (Core.SE && inTokuno) - return Construct(SEHatTypes, AosHatTypes, HatTypes) as BaseHat; - - if (Core.AOS) - return Construct(AosHatTypes, HatTypes) as BaseHat; - - return Construct(HatTypes) as BaseHat; - } - - public static Item RandomArmorOrHat() => RandomArmorOrHat(false, false); - - public static Item RandomArmorOrHat(bool inTokuno, bool isMondain) - { - if (Core.ML && isMondain) - return Construct(MLArmorTypes, ArmorTypes, AosHatTypes, HatTypes); - - if (Core.SE && inTokuno) - return Construct(SEArmorTypes, ArmorTypes, SEHatTypes, AosHatTypes, HatTypes); - - if (Core.AOS) - return Construct(ArmorTypes, AosHatTypes, HatTypes); - - return Construct(ArmorTypes, HatTypes); - } - - public static BaseShield RandomShield() - { - if (Core.AOS) - return Construct(AosShieldTypes, ShieldTypes) as BaseShield; - - return Construct(ShieldTypes) as BaseShield; - } - - public static BaseArmor RandomArmorOrShield() => RandomArmorOrShield(false, false); - - public static BaseArmor RandomArmorOrShield(bool inTokuno, bool isMondain) - { - if (Core.ML && isMondain) - return Construct(MLArmorTypes, ArmorTypes, AosShieldTypes, ShieldTypes) as BaseArmor; - - if (Core.SE && inTokuno) - return Construct(SEArmorTypes, ArmorTypes, AosShieldTypes, ShieldTypes) as BaseArmor; - - if (Core.AOS) - return Construct(ArmorTypes, AosShieldTypes, ShieldTypes) as BaseArmor; - - return Construct(ArmorTypes, ShieldTypes) as BaseArmor; - } - - public static Item RandomArmorOrShieldOrJewelry() => RandomArmorOrShieldOrJewelry(false, false); - - public static Item RandomArmorOrShieldOrJewelry(bool inTokuno, bool isMondain) - { - if (Core.ML && isMondain) - return Construct(MLArmorTypes, ArmorTypes, AosHatTypes, HatTypes, AosShieldTypes, ShieldTypes, JewelryTypes); - - if (Core.SE && inTokuno) - return Construct(SEArmorTypes, ArmorTypes, SEHatTypes, AosHatTypes, HatTypes, AosShieldTypes, ShieldTypes, - JewelryTypes); - - if (Core.AOS) - return Construct(ArmorTypes, AosHatTypes, HatTypes, AosShieldTypes, ShieldTypes, JewelryTypes); - - return Construct(ArmorTypes, HatTypes, ShieldTypes, JewelryTypes); - } - - public static Item RandomArmorOrShieldOrWeapon() => RandomArmorOrShieldOrWeapon(false, false); - - public static Item RandomArmorOrShieldOrWeapon(bool inTokuno, bool isMondain) - { - if (Core.ML && isMondain) - return Construct(MLWeaponTypes, AosWeaponTypes, WeaponTypes, MLRangedWeaponTypes, AosRangedWeaponTypes, - RangedWeaponTypes, MLArmorTypes, ArmorTypes, AosHatTypes, HatTypes, AosShieldTypes, ShieldTypes); - - if (Core.SE && inTokuno) - return Construct(SEWeaponTypes, AosWeaponTypes, WeaponTypes, SERangedWeaponTypes, AosRangedWeaponTypes, - RangedWeaponTypes, SEArmorTypes, ArmorTypes, SEHatTypes, AosHatTypes, HatTypes, AosShieldTypes, - ShieldTypes); - - if (Core.AOS) - return Construct(AosWeaponTypes, WeaponTypes, AosRangedWeaponTypes, RangedWeaponTypes, ArmorTypes, - AosHatTypes, HatTypes, AosShieldTypes, ShieldTypes); - - return Construct(WeaponTypes, RangedWeaponTypes, ArmorTypes, HatTypes, ShieldTypes); - } - - public static Item RandomArmorOrShieldOrWeaponOrJewelry() => RandomArmorOrShieldOrWeaponOrJewelry(false, false); - - public static Item RandomArmorOrShieldOrWeaponOrJewelry(bool inTokuno, bool isMondain) - { - if (Core.ML && isMondain) - return Construct(MLWeaponTypes, AosWeaponTypes, WeaponTypes, MLRangedWeaponTypes, AosRangedWeaponTypes, - RangedWeaponTypes, MLArmorTypes, ArmorTypes, AosHatTypes, HatTypes, AosShieldTypes, ShieldTypes, - JewelryTypes); - - if (Core.SE && inTokuno) - return Construct(SEWeaponTypes, AosWeaponTypes, WeaponTypes, SERangedWeaponTypes, AosRangedWeaponTypes, - RangedWeaponTypes, SEArmorTypes, ArmorTypes, SEHatTypes, AosHatTypes, HatTypes, AosShieldTypes, - ShieldTypes, JewelryTypes); - - if (Core.AOS) - return Construct(AosWeaponTypes, WeaponTypes, AosRangedWeaponTypes, RangedWeaponTypes, ArmorTypes, - AosHatTypes, HatTypes, AosShieldTypes, ShieldTypes, JewelryTypes); - - return Construct(WeaponTypes, RangedWeaponTypes, ArmorTypes, HatTypes, ShieldTypes, JewelryTypes); - } - - public static Item ChestOfHeirloomsContains() => Construct(SEArmorTypes, SEHatTypes, SEWeaponTypes, SERangedWeaponTypes, JewelryTypes); - - public static Item RandomGem() => Construct(GemTypes); - - public static Item RandomReagent() => Construct(RegTypes); - - public static Item RandomNecromancyReagent() => Construct(NecroRegTypes); - - public static Item RandomPossibleReagent() => Core.AOS ? Construct(RegTypes, NecroRegTypes) : Construct(RegTypes); - - public static Item RandomPotion() => Construct(PotionTypes); - - public static BaseInstrument RandomInstrument() - { - if (Core.SE) - return Construct(InstrumentTypes, SEInstrumentTypes) as BaseInstrument; - - return Construct(InstrumentTypes) as BaseInstrument; - } - - public static Item RandomStatue() => Construct(StatueTypes); - - public static SpellScroll RandomScroll(int minIndex, int maxIndex, SpellbookType type) - { - var types = type switch - { - SpellbookType.Regular => RegularScrollTypes, - SpellbookType.Necromancer => Core.SE ? SENecromancyScrollTypes : NecromancyScrollTypes, - SpellbookType.Paladin => PaladinScrollTypes, - SpellbookType.Arcanist => ArcanistScrollTypes, - _ => RegularScrollTypes - }; - - return Construct(types, Utility.RandomMinMax(minIndex, maxIndex)) as SpellScroll; - } - - public static BaseBook RandomGrimmochJournal() => Construct(GrimmochJournalTypes) as BaseBook; - - public static BaseBook RandomLysanderNotebook() => Construct(LysanderNotebookTypes) as BaseBook; - - public static BaseBook RandomTavarasJournal() => Construct(TavarasJournalTypes) as BaseBook; - - public static BaseBook RandomLibraryBook() => Construct(LibraryBookTypes) as BaseBook; - - public static BaseTalisman RandomTalisman() - { - BaseTalisman talisman = new BaseTalisman(BaseTalisman.GetRandomItemID()); - - talisman.Summoner = BaseTalisman.GetRandomSummoner(); - - if (talisman.Summoner.IsEmpty) - { - talisman.Removal = BaseTalisman.GetRandomRemoval(); - - if (talisman.Removal != TalismanRemoval.None) + public static Type[] MLWeaponTypes { get; } = { - talisman.MaxCharges = BaseTalisman.GetRandomCharges(); - talisman.MaxChargeTime = 1200; - } - } - else - { - talisman.MaxCharges = Utility.RandomMinMax(10, 50); + typeof(AssassinSpike), typeof(DiamondMace), typeof(ElvenMachete), + typeof(ElvenSpellblade), typeof(Leafblade), typeof(OrnateAxe), + typeof(RadiantScimitar), typeof(RuneBlade), typeof(WarCleaver), + typeof(WildStaff) + }; - if (talisman.Summoner.IsItem) - talisman.MaxChargeTime = 60; - else - talisman.MaxChargeTime = 1800; - } - - talisman.Blessed = BaseTalisman.GetRandomBlessed(); - talisman.Slayer = BaseTalisman.GetRandomSlayer(); - talisman.Protection = BaseTalisman.GetRandomProtection(); - talisman.Killer = BaseTalisman.GetRandomKiller(); - talisman.Skill = BaseTalisman.GetRandomSkill(); - talisman.ExceptionalBonus = BaseTalisman.GetRandomExceptional(); - talisman.SuccessBonus = BaseTalisman.GetRandomSuccessful(); - talisman.Charges = talisman.MaxCharges; - - return talisman; - } - - public static Item Construct(Type type) - { - if (type == null) return null; - - try - { - return ActivatorUtil.CreateInstance(type) as Item; - } - catch - { - return null; - } - } - - public static Item Construct(Type[] types) => Construct(types.RandomElement()); - - public static Item Construct(Type[] types, int index) - { - if (index >= 0 && index < types.Length) - return Construct(types[index]); - - return null; - } - - public static Item Construct(params Type[][] types) - { - int totalLength = 0; - - for (int i = 0; i < types.Length; ++i) - totalLength += types[i].Length; - - if (totalLength > 0) - { - int index = Utility.Random(totalLength); - - for (int i = 0; i < types.Length; ++i) + public static Type[] MLRangedWeaponTypes { get; } = { - if (index >= 0 && index < types[i].Length) - return Construct(types[i][index]); + typeof(ElvenCompositeLongbow), typeof(MagicalShortbow) + }; - index -= types[i].Length; + public static Type[] MLArmorTypes { get; } = + { + typeof(Circlet), typeof(GemmedCirclet), typeof(LeafTonlet), + typeof(RavenHelm), typeof(RoyalCirclet), typeof(VultureHelm), + typeof(WingedHelm), typeof(LeafArms), typeof(LeafChest), + typeof(LeafGloves), typeof(LeafGorget), typeof(LeafLegs), + typeof(WoodlandArms), typeof(WoodlandChest), typeof(WoodlandGloves), + typeof(WoodlandGorget), typeof(WoodlandLegs), typeof(HideChest), + typeof(HideGloves), typeof(HideGorget), typeof(HidePants), + typeof(HidePauldrons) + }; + + public static Type[] MLClothingTypes { get; } = + { + typeof(MaleElvenRobe), typeof(FemaleElvenRobe), typeof(ElvenPants), + typeof(ElvenShirt), typeof(ElvenDarkShirt), typeof(ElvenBoots), + typeof(VultureHelm), typeof(WoodlandBelt) + }; + + public static Type[] SEWeaponTypes { get; } = + { + typeof(Bokuto), typeof(Daisho), typeof(Kama), + typeof(Lajatang), typeof(NoDachi), typeof(Nunchaku), + typeof(Sai), typeof(Tekagi), typeof(Tessen), + typeof(Tetsubo), typeof(Wakizashi) + }; + + public static Type[] AosWeaponTypes { get; } = + { + typeof(Scythe), typeof(BoneHarvester), typeof(Scepter), + typeof(BladedStaff), typeof(Pike), typeof(DoubleBladedStaff), + typeof(Lance), typeof(CrescentBlade) + }; + + public static Type[] WeaponTypes { get; } = + { + typeof(Axe), typeof(BattleAxe), typeof(DoubleAxe), + typeof(ExecutionersAxe), typeof(Hatchet), typeof(LargeBattleAxe), + typeof(TwoHandedAxe), typeof(WarAxe), typeof(Club), + typeof(Mace), typeof(Maul), typeof(WarHammer), + typeof(WarMace), typeof(Bardiche), typeof(Halberd), + typeof(Spear), typeof(ShortSpear), typeof(Pitchfork), + typeof(WarFork), typeof(BlackStaff), typeof(GnarledStaff), + typeof(QuarterStaff), typeof(Broadsword), typeof(Cutlass), + typeof(Katana), typeof(Kryss), typeof(Longsword), + typeof(Scimitar), typeof(VikingSword), typeof(Pickaxe), + typeof(HammerPick), typeof(ButcherKnife), typeof(Cleaver), + typeof(Dagger), typeof(SkinningKnife), typeof(ShepherdsCrook) + }; + + public static Type[] SERangedWeaponTypes { get; } = + { + typeof(Yumi) + }; + + public static Type[] AosRangedWeaponTypes { get; } = + { + typeof(CompositeBow), typeof(RepeatingCrossbow) + }; + + public static Type[] RangedWeaponTypes { get; } = + { + typeof(Bow), typeof(Crossbow), typeof(HeavyCrossbow) + }; + + public static Type[] SEArmorTypes { get; } = + { + typeof(ChainHatsuburi), typeof(LeatherDo), typeof(LeatherHaidate), + typeof(LeatherHiroSode), typeof(LeatherJingasa), typeof(LeatherMempo), + typeof(LeatherNinjaHood), typeof(LeatherNinjaJacket), typeof(LeatherNinjaMitts), + typeof(LeatherNinjaPants), typeof(LeatherSuneate), typeof(DecorativePlateKabuto), + typeof(HeavyPlateJingasa), typeof(LightPlateJingasa), typeof(PlateBattleKabuto), + typeof(PlateDo), typeof(PlateHaidate), typeof(PlateHatsuburi), + typeof(PlateHiroSode), typeof(PlateMempo), typeof(PlateSuneate), + typeof(SmallPlateJingasa), typeof(StandardPlateKabuto), typeof(StuddedDo), + typeof(StuddedHaidate), typeof(StuddedHiroSode), typeof(StuddedMempo), + typeof(StuddedSuneate) + }; + + public static Type[] ArmorTypes { get; } = + { + typeof(BoneArms), typeof(BoneChest), typeof(BoneGloves), + typeof(BoneLegs), typeof(BoneHelm), typeof(ChainChest), + typeof(ChainLegs), typeof(ChainCoif), typeof(Bascinet), + typeof(CloseHelm), typeof(Helmet), typeof(NorseHelm), + typeof(OrcHelm), typeof(FemaleLeatherChest), typeof(LeatherArms), + typeof(LeatherBustierArms), typeof(LeatherChest), typeof(LeatherGloves), + typeof(LeatherGorget), typeof(LeatherLegs), typeof(LeatherShorts), + typeof(LeatherSkirt), typeof(LeatherCap), typeof(FemalePlateChest), + typeof(PlateArms), typeof(PlateChest), typeof(PlateGloves), + typeof(PlateGorget), typeof(PlateHelm), typeof(PlateLegs), + typeof(RingmailArms), typeof(RingmailChest), typeof(RingmailGloves), + typeof(RingmailLegs), typeof(FemaleStuddedChest), typeof(StuddedArms), + typeof(StuddedBustierArms), typeof(StuddedChest), typeof(StuddedGloves), + typeof(StuddedGorget), typeof(StuddedLegs) + }; + + public static Type[] AosShieldTypes { get; } = + { + typeof(ChaosShield), typeof(OrderShield) + }; + + public static Type[] ShieldTypes { get; } = + { + typeof(BronzeShield), typeof(Buckler), typeof(HeaterShield), + typeof(MetalShield), typeof(MetalKiteShield), typeof(WoodenKiteShield), + typeof(WoodenShield) + }; + + public static Type[] GemTypes { get; } = + { + typeof(Amber), typeof(Amethyst), typeof(Citrine), + typeof(Diamond), typeof(Emerald), typeof(Ruby), + typeof(Sapphire), typeof(StarSapphire), typeof(Tourmaline) + }; + + public static Type[] JewelryTypes { get; } = + { + typeof(GoldRing), typeof(GoldBracelet), + typeof(SilverRing), typeof(SilverBracelet) + }; + + public static Type[] RegTypes { get; } = + { + typeof(BlackPearl), typeof(Bloodmoss), typeof(Garlic), + typeof(Ginseng), typeof(MandrakeRoot), typeof(Nightshade), + typeof(SulfurousAsh), typeof(SpidersSilk) + }; + + public static Type[] NecroRegTypes { get; } = + { + typeof(BatWing), typeof(GraveDust), typeof(DaemonBlood), + typeof(NoxCrystal), typeof(PigIron) + }; + + public static Type[] PotionTypes { get; } = + { + typeof(AgilityPotion), typeof(StrengthPotion), typeof(RefreshPotion), + typeof(LesserCurePotion), typeof(LesserHealPotion), typeof(LesserPoisonPotion) + }; + + public static Type[] SEInstrumentTypes { get; } = + { + typeof(BambooFlute) + }; + + public static Type[] InstrumentTypes { get; } = + { + typeof(Drums), typeof(Harp), typeof(LapHarp), + typeof(Lute), typeof(Tambourine), typeof(TambourineTassel) + }; + + public static Type[] StatueTypes { get; } = + { + typeof(StatueSouth), typeof(StatueSouth2), typeof(StatueNorth), + typeof(StatueWest), typeof(StatueEast), typeof(StatueEast2), + typeof(StatueSouthEast), typeof(BustSouth), typeof(BustEast) + }; + + public static Type[] RegularScrollTypes { get; } = + { + typeof(ReactiveArmorScroll), typeof(ClumsyScroll), typeof(CreateFoodScroll), typeof(FeeblemindScroll), + typeof(HealScroll), typeof(MagicArrowScroll), typeof(NightSightScroll), typeof(WeakenScroll), + typeof(AgilityScroll), typeof(CunningScroll), typeof(CureScroll), typeof(HarmScroll), + typeof(MagicTrapScroll), typeof(MagicUnTrapScroll), typeof(ProtectionScroll), typeof(StrengthScroll), + typeof(BlessScroll), typeof(FireballScroll), typeof(MagicLockScroll), typeof(PoisonScroll), + typeof(TelekinesisScroll), typeof(TeleportScroll), typeof(UnlockScroll), typeof(WallOfStoneScroll), + typeof(ArchCureScroll), typeof(ArchProtectionScroll), typeof(CurseScroll), typeof(FireFieldScroll), + typeof(GreaterHealScroll), typeof(LightningScroll), typeof(ManaDrainScroll), typeof(RecallScroll), + typeof(BladeSpiritsScroll), typeof(DispelFieldScroll), typeof(IncognitoScroll), typeof(MagicReflectScroll), + typeof(MindBlastScroll), typeof(ParalyzeScroll), typeof(PoisonFieldScroll), typeof(SummonCreatureScroll), + typeof(DispelScroll), typeof(EnergyBoltScroll), typeof(ExplosionScroll), typeof(InvisibilityScroll), + typeof(MarkScroll), typeof(MassCurseScroll), typeof(ParalyzeFieldScroll), typeof(RevealScroll), + typeof(ChainLightningScroll), typeof(EnergyFieldScroll), typeof(FlamestrikeScroll), typeof(GateTravelScroll), + typeof(ManaVampireScroll), typeof(MassDispelScroll), typeof(MeteorSwarmScroll), typeof(PolymorphScroll), + typeof(EarthquakeScroll), typeof(EnergyVortexScroll), typeof(ResurrectionScroll), + typeof(SummonAirElementalScroll), + typeof(SummonDaemonScroll), typeof(SummonEarthElementalScroll), typeof(SummonFireElementalScroll), + typeof(SummonWaterElementalScroll) + }; + + public static Type[] NecromancyScrollTypes { get; } = + { + typeof(AnimateDeadScroll), typeof(BloodOathScroll), typeof(CorpseSkinScroll), typeof(CurseWeaponScroll), + typeof(EvilOmenScroll), typeof(HorrificBeastScroll), typeof(LichFormScroll), typeof(MindRotScroll), + typeof(PainSpikeScroll), typeof(PoisonStrikeScroll), typeof(StrangleScroll), typeof(SummonFamiliarScroll), + typeof(VampiricEmbraceScroll), typeof(VengefulSpiritScroll), typeof(WitherScroll), typeof(WraithFormScroll) + }; + + public static Type[] SENecromancyScrollTypes { get; } = + { + typeof(AnimateDeadScroll), typeof(BloodOathScroll), typeof(CorpseSkinScroll), typeof(CurseWeaponScroll), + typeof(EvilOmenScroll), typeof(HorrificBeastScroll), typeof(LichFormScroll), typeof(MindRotScroll), + typeof(PainSpikeScroll), typeof(PoisonStrikeScroll), typeof(StrangleScroll), typeof(SummonFamiliarScroll), + typeof(VampiricEmbraceScroll), typeof(VengefulSpiritScroll), typeof(WitherScroll), typeof(WraithFormScroll), + typeof(ExorcismScroll) + }; + + public static Type[] PaladinScrollTypes { get; } = Array.Empty(); + + public static Type[] ArcanistScrollTypes { get; } = + { + typeof(ArcaneCircleScroll), typeof(GiftOfRenewalScroll), typeof(ImmolatingWeaponScroll), + typeof(AttuneWeaponScroll), + typeof(ThunderstormScroll), + typeof(NatureFuryScroll), /*typeof( SummonFeyScroll ), typeof( SummonFiendScroll ),*/ + typeof(ReaperFormScroll), typeof(WildfireScroll), typeof(EssenceOfWindScroll), typeof(DryadAllureScroll), + typeof(EtherealVoyageScroll), typeof(WordOfDeathScroll), typeof(GiftOfLifeScroll), + typeof(ArcaneEmpowermentScroll) + }; + + public static Type[] GrimmochJournalTypes { get; } = + { + typeof(GrimmochJournal1), typeof(GrimmochJournal2), typeof(GrimmochJournal3), + typeof(GrimmochJournal6), typeof(GrimmochJournal7), typeof(GrimmochJournal11), + typeof(GrimmochJournal14), typeof(GrimmochJournal17), typeof(GrimmochJournal23) + }; + + public static Type[] LysanderNotebookTypes { get; } = + { + typeof(LysanderNotebook1), typeof(LysanderNotebook2), typeof(LysanderNotebook3), + typeof(LysanderNotebook7), typeof(LysanderNotebook8), typeof(LysanderNotebook11) + }; + + public static Type[] TavarasJournalTypes { get; } = + { + typeof(TavarasJournal1), typeof(TavarasJournal2), typeof(TavarasJournal3), + typeof(TavarasJournal6), typeof(TavarasJournal7), typeof(TavarasJournal8), + typeof(TavarasJournal9), typeof(TavarasJournal11), typeof(TavarasJournal14), + typeof(TavarasJournal16), typeof(TavarasJournal16b), typeof(TavarasJournal17), + typeof(TavarasJournal19) + }; + + public static Type[] NewWandTypes { get; } = + { + typeof(FireballWand), typeof(LightningWand), typeof(MagicArrowWand), + typeof(GreaterHealWand), typeof(HarmWand), typeof(HealWand) + }; + + public static Type[] WandTypes { get; } = + { + typeof(ClumsyWand), typeof(FeebleWand), + typeof(ManaDrainWand), typeof(WeaknessWand) + }; + + public static Type[] OldWandTypes { get; } = + { + typeof(IDWand) + }; + + public static Type[] SEClothingTypes { get; } = + { + typeof(ClothNinjaJacket), typeof(FemaleKimono), typeof(Hakama), + typeof(HakamaShita), typeof(JinBaori), typeof(Kamishimo), + typeof(MaleKimono), typeof(NinjaTabi), typeof(Obi), + typeof(SamuraiTabi), typeof(TattsukeHakama), typeof(Waraji) + }; + + public static Type[] AosClothingTypes { get; } = + { + typeof(FurSarong), typeof(FurCape), typeof(FlowerGarland), + typeof(GildedDress), typeof(FurBoots), typeof(FormalShirt) + }; + + public static Type[] ClothingTypes { get; } = + { + typeof(Cloak), + typeof(Bonnet), typeof(Cap), typeof(FeatheredHat), + typeof(FloppyHat), typeof(JesterHat), typeof(Surcoat), + typeof(SkullCap), typeof(StrawHat), typeof(TallStrawHat), + typeof(TricorneHat), typeof(WideBrimHat), typeof(WizardsHat), + typeof(BodySash), typeof(Doublet), typeof(Boots), + typeof(FullApron), typeof(JesterSuit), typeof(Sandals), + typeof(Tunic), typeof(Shoes), typeof(Shirt), + typeof(Kilt), typeof(Skirt), typeof(FancyShirt), + typeof(FancyDress), typeof(ThighBoots), typeof(LongPants), + typeof(PlainDress), typeof(Robe), typeof(ShortPants), + typeof(HalfApron) + }; + + public static Type[] SEHatTypes { get; } = + { + typeof(ClothNinjaHood), typeof(Kasa) + }; + + public static Type[] AosHatTypes { get; } = + { + typeof(FlowerGarland), typeof(BearMask), + typeof(DeerMask) // Are Bear& Deer mask inside the Pre-AoS loottables too? + }; + + public static Type[] HatTypes { get; } = + { + typeof(SkullCap), typeof(Bandana), typeof(FloppyHat), + typeof(Cap), typeof(WideBrimHat), typeof(StrawHat), + typeof(TallStrawHat), typeof(WizardsHat), typeof(Bonnet), + typeof(FeatheredHat), typeof(TricorneHat), typeof(JesterHat) + }; + + public static Type[] LibraryBookTypes { get; } = + { + typeof(GrammarOfOrcish), typeof(CallToAnarchy), typeof(ArmsAndWeaponsPrimer), + typeof(SongOfSamlethe), typeof(TaleOfThreeTribes), typeof(GuideToGuilds), + typeof(BirdsOfBritannia), typeof(BritannianFlora), typeof(ChildrenTalesVol2), + typeof(TalesOfVesperVol1), typeof(DeceitDungeonOfHorror), typeof(DimensionalTravel), + typeof(EthicalHedonism), typeof(MyStory), typeof(DiversityOfOurLand), + typeof(QuestOfVirtues), typeof(RegardingLlamas), typeof(TalkingToWisps), + typeof(TamingDragons), typeof(BoldStranger), typeof(BurningOfTrinsic), + typeof(TheFight), typeof(LifeOfATravellingMinstrel), typeof(MajorTradeAssociation), + typeof(RankingsOfTrades), typeof(WildGirlOfTheForest), typeof(TreatiseOnAlchemy), + typeof(VirtueBook) + }; + + public static BaseWand RandomWand() + { + if (Core.ML) + return Construct(NewWandTypes) as BaseWand; + if (Core.AOS) + return Construct(WandTypes, NewWandTypes) as BaseWand; + return Construct(OldWandTypes, WandTypes, NewWandTypes) as BaseWand; } - } - return null; + public static BaseClothing RandomClothing() => RandomClothing(false, false); + + public static BaseClothing RandomClothing(bool inTokuno, bool isMondain) + { + if (Core.ML && isMondain) + return Construct(MLClothingTypes, AosClothingTypes, ClothingTypes) as BaseClothing; + + if (Core.SE && inTokuno) + return Construct(SEClothingTypes, AosClothingTypes, ClothingTypes) as BaseClothing; + + if (Core.AOS) + return Construct(AosClothingTypes, ClothingTypes) as BaseClothing; + + return Construct(ClothingTypes) as BaseClothing; + } + + public static BaseWeapon RandomRangedWeapon() => RandomRangedWeapon(false, false); + + public static BaseWeapon RandomRangedWeapon(bool inTokuno, bool isMondain) + { + if (Core.ML && isMondain) + return Construct(MLRangedWeaponTypes, AosRangedWeaponTypes, RangedWeaponTypes) as BaseWeapon; + + if (Core.SE && inTokuno) + return Construct(SERangedWeaponTypes, AosRangedWeaponTypes, RangedWeaponTypes) as BaseWeapon; + + if (Core.AOS) + return Construct(AosRangedWeaponTypes, RangedWeaponTypes) as BaseWeapon; + + return Construct(RangedWeaponTypes) as BaseWeapon; + } + + public static BaseWeapon RandomWeapon() => RandomWeapon(false, false); + + public static BaseWeapon RandomWeapon(bool inTokuno, bool isMondain) + { + if (Core.ML && isMondain) + return Construct(MLWeaponTypes, AosWeaponTypes, WeaponTypes) as BaseWeapon; + + if (Core.SE && inTokuno) + return Construct(SEWeaponTypes, AosWeaponTypes, WeaponTypes) as BaseWeapon; + + if (Core.AOS) + return Construct(AosWeaponTypes, WeaponTypes) as BaseWeapon; + + return Construct(WeaponTypes) as BaseWeapon; + } + + public static Item RandomWeaponOrJewelry() => RandomWeaponOrJewelry(false, false); + + public static Item RandomWeaponOrJewelry(bool inTokuno, bool isMondain) + { + if (Core.ML && isMondain) + return Construct(MLWeaponTypes, AosWeaponTypes, WeaponTypes, JewelryTypes); + + if (Core.SE && inTokuno) + return Construct(SEWeaponTypes, AosWeaponTypes, WeaponTypes, JewelryTypes); + + if (Core.AOS) + return Construct(AosWeaponTypes, WeaponTypes, JewelryTypes); + + return Construct(WeaponTypes, JewelryTypes); + } + + public static BaseJewel RandomJewelry() => Construct(JewelryTypes) as BaseJewel; + + public static BaseArmor RandomArmor() => RandomArmor(false, false); + + public static BaseArmor RandomArmor(bool inTokuno, bool isMondain) + { + if (Core.ML && isMondain) + return Construct(MLArmorTypes, ArmorTypes) as BaseArmor; + + if (Core.SE && inTokuno) + return Construct(SEArmorTypes, ArmorTypes) as BaseArmor; + + return Construct(ArmorTypes) as BaseArmor; + } + + public static BaseHat RandomHat() => RandomHat(false); + + public static BaseHat RandomHat(bool inTokuno) + { + if (Core.SE && inTokuno) + return Construct(SEHatTypes, AosHatTypes, HatTypes) as BaseHat; + + if (Core.AOS) + return Construct(AosHatTypes, HatTypes) as BaseHat; + + return Construct(HatTypes) as BaseHat; + } + + public static Item RandomArmorOrHat() => RandomArmorOrHat(false, false); + + public static Item RandomArmorOrHat(bool inTokuno, bool isMondain) + { + if (Core.ML && isMondain) + return Construct(MLArmorTypes, ArmorTypes, AosHatTypes, HatTypes); + + if (Core.SE && inTokuno) + return Construct(SEArmorTypes, ArmorTypes, SEHatTypes, AosHatTypes, HatTypes); + + if (Core.AOS) + return Construct(ArmorTypes, AosHatTypes, HatTypes); + + return Construct(ArmorTypes, HatTypes); + } + + public static BaseShield RandomShield() + { + if (Core.AOS) + return Construct(AosShieldTypes, ShieldTypes) as BaseShield; + + return Construct(ShieldTypes) as BaseShield; + } + + public static BaseArmor RandomArmorOrShield() => RandomArmorOrShield(false, false); + + public static BaseArmor RandomArmorOrShield(bool inTokuno, bool isMondain) + { + if (Core.ML && isMondain) + return Construct(MLArmorTypes, ArmorTypes, AosShieldTypes, ShieldTypes) as BaseArmor; + + if (Core.SE && inTokuno) + return Construct(SEArmorTypes, ArmorTypes, AosShieldTypes, ShieldTypes) as BaseArmor; + + if (Core.AOS) + return Construct(ArmorTypes, AosShieldTypes, ShieldTypes) as BaseArmor; + + return Construct(ArmorTypes, ShieldTypes) as BaseArmor; + } + + public static Item RandomArmorOrShieldOrJewelry() => RandomArmorOrShieldOrJewelry(false, false); + + public static Item RandomArmorOrShieldOrJewelry(bool inTokuno, bool isMondain) + { + if (Core.ML && isMondain) + return Construct(MLArmorTypes, ArmorTypes, AosHatTypes, HatTypes, AosShieldTypes, ShieldTypes, JewelryTypes); + + if (Core.SE && inTokuno) + return Construct( + SEArmorTypes, + ArmorTypes, + SEHatTypes, + AosHatTypes, + HatTypes, + AosShieldTypes, + ShieldTypes, + JewelryTypes + ); + + if (Core.AOS) + return Construct(ArmorTypes, AosHatTypes, HatTypes, AosShieldTypes, ShieldTypes, JewelryTypes); + + return Construct(ArmorTypes, HatTypes, ShieldTypes, JewelryTypes); + } + + public static Item RandomArmorOrShieldOrWeapon() => RandomArmorOrShieldOrWeapon(false, false); + + public static Item RandomArmorOrShieldOrWeapon(bool inTokuno, bool isMondain) + { + if (Core.ML && isMondain) + return Construct( + MLWeaponTypes, + AosWeaponTypes, + WeaponTypes, + MLRangedWeaponTypes, + AosRangedWeaponTypes, + RangedWeaponTypes, + MLArmorTypes, + ArmorTypes, + AosHatTypes, + HatTypes, + AosShieldTypes, + ShieldTypes + ); + + if (Core.SE && inTokuno) + return Construct( + SEWeaponTypes, + AosWeaponTypes, + WeaponTypes, + SERangedWeaponTypes, + AosRangedWeaponTypes, + RangedWeaponTypes, + SEArmorTypes, + ArmorTypes, + SEHatTypes, + AosHatTypes, + HatTypes, + AosShieldTypes, + ShieldTypes + ); + + if (Core.AOS) + return Construct( + AosWeaponTypes, + WeaponTypes, + AosRangedWeaponTypes, + RangedWeaponTypes, + ArmorTypes, + AosHatTypes, + HatTypes, + AosShieldTypes, + ShieldTypes + ); + + return Construct(WeaponTypes, RangedWeaponTypes, ArmorTypes, HatTypes, ShieldTypes); + } + + public static Item RandomArmorOrShieldOrWeaponOrJewelry() => RandomArmorOrShieldOrWeaponOrJewelry(false, false); + + public static Item RandomArmorOrShieldOrWeaponOrJewelry(bool inTokuno, bool isMondain) + { + if (Core.ML && isMondain) + return Construct( + MLWeaponTypes, + AosWeaponTypes, + WeaponTypes, + MLRangedWeaponTypes, + AosRangedWeaponTypes, + RangedWeaponTypes, + MLArmorTypes, + ArmorTypes, + AosHatTypes, + HatTypes, + AosShieldTypes, + ShieldTypes, + JewelryTypes + ); + + if (Core.SE && inTokuno) + return Construct( + SEWeaponTypes, + AosWeaponTypes, + WeaponTypes, + SERangedWeaponTypes, + AosRangedWeaponTypes, + RangedWeaponTypes, + SEArmorTypes, + ArmorTypes, + SEHatTypes, + AosHatTypes, + HatTypes, + AosShieldTypes, + ShieldTypes, + JewelryTypes + ); + + if (Core.AOS) + return Construct( + AosWeaponTypes, + WeaponTypes, + AosRangedWeaponTypes, + RangedWeaponTypes, + ArmorTypes, + AosHatTypes, + HatTypes, + AosShieldTypes, + ShieldTypes, + JewelryTypes + ); + + return Construct(WeaponTypes, RangedWeaponTypes, ArmorTypes, HatTypes, ShieldTypes, JewelryTypes); + } + + public static Item ChestOfHeirloomsContains() => Construct( + SEArmorTypes, + SEHatTypes, + SEWeaponTypes, + SERangedWeaponTypes, + JewelryTypes + ); + + public static Item RandomGem() => Construct(GemTypes); + + public static Item RandomReagent() => Construct(RegTypes); + + public static Item RandomNecromancyReagent() => Construct(NecroRegTypes); + + public static Item RandomPossibleReagent() => Core.AOS ? Construct(RegTypes, NecroRegTypes) : Construct(RegTypes); + + public static Item RandomPotion() => Construct(PotionTypes); + + public static BaseInstrument RandomInstrument() + { + if (Core.SE) + return Construct(InstrumentTypes, SEInstrumentTypes) as BaseInstrument; + + return Construct(InstrumentTypes) as BaseInstrument; + } + + public static Item RandomStatue() => Construct(StatueTypes); + + public static SpellScroll RandomScroll(int minIndex, int maxIndex, SpellbookType type) + { + var types = type switch + { + SpellbookType.Regular => RegularScrollTypes, + SpellbookType.Necromancer => Core.SE ? SENecromancyScrollTypes : NecromancyScrollTypes, + SpellbookType.Paladin => PaladinScrollTypes, + SpellbookType.Arcanist => ArcanistScrollTypes, + _ => RegularScrollTypes + }; + + return Construct(types, Utility.RandomMinMax(minIndex, maxIndex)) as SpellScroll; + } + + public static BaseBook RandomGrimmochJournal() => Construct(GrimmochJournalTypes) as BaseBook; + + public static BaseBook RandomLysanderNotebook() => Construct(LysanderNotebookTypes) as BaseBook; + + public static BaseBook RandomTavarasJournal() => Construct(TavarasJournalTypes) as BaseBook; + + public static BaseBook RandomLibraryBook() => Construct(LibraryBookTypes) as BaseBook; + + public static BaseTalisman RandomTalisman() + { + var talisman = new BaseTalisman(BaseTalisman.GetRandomItemID()); + + talisman.Summoner = BaseTalisman.GetRandomSummoner(); + + if (talisman.Summoner.IsEmpty) + { + talisman.Removal = BaseTalisman.GetRandomRemoval(); + + if (talisman.Removal != TalismanRemoval.None) + { + talisman.MaxCharges = BaseTalisman.GetRandomCharges(); + talisman.MaxChargeTime = 1200; + } + } + else + { + talisman.MaxCharges = Utility.RandomMinMax(10, 50); + + if (talisman.Summoner.IsItem) + talisman.MaxChargeTime = 60; + else + talisman.MaxChargeTime = 1800; + } + + talisman.Blessed = BaseTalisman.GetRandomBlessed(); + talisman.Slayer = BaseTalisman.GetRandomSlayer(); + talisman.Protection = BaseTalisman.GetRandomProtection(); + talisman.Killer = BaseTalisman.GetRandomKiller(); + talisman.Skill = BaseTalisman.GetRandomSkill(); + talisman.ExceptionalBonus = BaseTalisman.GetRandomExceptional(); + talisman.SuccessBonus = BaseTalisman.GetRandomSuccessful(); + talisman.Charges = talisman.MaxCharges; + + return talisman; + } + + public static Item Construct(Type type) + { + if (type == null) return null; + + try + { + return ActivatorUtil.CreateInstance(type) as Item; + } + catch + { + return null; + } + } + + public static Item Construct(Type[] types) => Construct(types.RandomElement()); + + public static Item Construct(Type[] types, int index) + { + if (index >= 0 && index < types.Length) + return Construct(types[index]); + + return null; + } + + public static Item Construct(params Type[][] types) + { + var totalLength = 0; + + for (var i = 0; i < types.Length; ++i) + totalLength += types[i].Length; + + if (totalLength > 0) + { + var index = Utility.Random(totalLength); + + for (var i = 0; i < types.Length; ++i) + { + if (index >= 0 && index < types[i].Length) + return Construct(types[i][index]); + + index -= types[i].Length; + } + } + + return null; + } } - } } diff --git a/Projects/UOContent/Misc/LootPack.cs b/Projects/UOContent/Misc/LootPack.cs index 74475f989..be72eae9b 100644 --- a/Projects/UOContent/Misc/LootPack.cs +++ b/Projects/UOContent/Misc/LootPack.cs @@ -1,927 +1,1027 @@ using System; -using System.Collections.Generic; using Server.Items; using Server.Mobiles; using Server.Utilities; namespace Server { - public class LootPack - { - public static readonly LootPackItem[] Gold = + public class LootPack { - new LootPackItem(typeof(Gold), 1) - }; - - public static readonly LootPackItem[] Instruments = - { - new LootPackItem(typeof(BaseInstrument), 1) - }; - - public static readonly LootPackItem[] LowScrollItems = - { - new LootPackItem(typeof(ClumsyScroll), 1) - }; - - public static readonly LootPackItem[] MedScrollItems = - { - new LootPackItem(typeof(ArchCureScroll), 1) - }; - - public static readonly LootPackItem[] HighScrollItems = - { - new LootPackItem(typeof(SummonAirElementalScroll), 1) - }; - - public static readonly LootPackItem[] GemItems = - { - new LootPackItem(typeof(Amber), 1) - }; - - public static readonly LootPackItem[] PotionItems = - { - new LootPackItem(typeof(AgilityPotion), 1), - new LootPackItem(typeof(StrengthPotion), 1), - new LootPackItem(typeof(RefreshPotion), 1), - new LootPackItem(typeof(LesserCurePotion), 1), - new LootPackItem(typeof(LesserHealPotion), 1), - new LootPackItem(typeof(LesserPoisonPotion), 1) - }; - - public static readonly LootPackItem[] OldMagicItems = - { - new LootPackItem(typeof(BaseJewel), 1), - new LootPackItem(typeof(BaseArmor), 4), - new LootPackItem(typeof(BaseWeapon), 3), - new LootPackItem(typeof(BaseRanged), 1), - new LootPackItem(typeof(BaseShield), 1) - }; - - public static readonly LootPack LowScrolls = new LootPack(new[] - { - new LootPackEntry(false, LowScrollItems, 100.00, 1) - }); - - public static readonly LootPack MedScrolls = new LootPack(new[] - { - new LootPackEntry(false, MedScrollItems, 100.00, 1) - }); - - public static readonly LootPack HighScrolls = new LootPack(new[] - { - new LootPackEntry(false, HighScrollItems, 100.00, 1) - }); - - public static readonly LootPack Gems = new LootPack(new[] - { - new LootPackEntry(false, GemItems, 100.00, 1) - }); - - public static readonly LootPack Potions = new LootPack(new[] - { - new LootPackEntry(false, PotionItems, 100.00, 1) - }); - - private readonly LootPackEntry[] m_Entries; - - public LootPack(LootPackEntry[] entries) => m_Entries = entries; - - public static int GetLuckChance(Mobile killer, Mobile victim) - { - if (!Core.AOS) - return 0; - - int luck = killer.Luck; - - if (killer is PlayerMobile pmKiller && pmKiller.SentHonorContext != null && - pmKiller.SentHonorContext.Target == victim) - luck += pmKiller.SentHonorContext.PerfectionLuckBonus; - - if (luck < 0) - return 0; - - if (!Core.SE && luck > 1200) - luck = 1200; - - return (int)(Math.Pow(luck, 1 / 1.8) * 100); - } - - public static int GetLuckChanceForKiller(Mobile dead) - { - List list = BaseCreature.GetLootingRights(dead.DamageEntries, dead.HitsMax); - - DamageStore highest = null; - - for (int i = 0; i < list.Count; ++i) - { - DamageStore ds = list[i]; - - if (ds.m_HasRight && (highest == null || ds.m_Damage > highest.m_Damage)) - highest = ds; - } - - if (highest == null) - return 0; - - return GetLuckChance(highest.m_Mobile, dead); - } - - public static bool CheckLuck(int chance) => chance > Utility.Random(10000); - - public void Generate(Mobile from, Container cont, bool spawning, int luckChance) - { - if (cont == null) - return; - - bool checkLuck = Core.AOS; - - for (int i = 0; i < m_Entries.Length; ++i) - { - LootPackEntry entry = m_Entries[i]; - - bool shouldAdd = entry.Chance > Utility.Random(10000); - - if (!shouldAdd && checkLuck) + public static readonly LootPackItem[] Gold = { - checkLuck = false; + new LootPackItem(typeof(Gold), 1) + }; - if (CheckLuck(luckChance)) - shouldAdd = entry.Chance > Utility.Random(10000); - } - - if (!shouldAdd) - continue; - - Item item = entry.Construct(from, luckChance, spawning); - - if (item != null) - if (!item.Stackable || !cont.TryDropItem(from, item, false)) - cont.DropItem(item); - } - } - - public static readonly LootPackItem[] AosMagicItemsRichType1 = - { - new LootPackItem(typeof(BaseWeapon), 211), - new LootPackItem(typeof(BaseRanged), 53), - new LootPackItem(typeof(BaseArmor), 303), - new LootPackItem(typeof(BaseShield), 39), - new LootPackItem(typeof(BaseJewel), 158) - }; - - public static readonly LootPack MlRich = new LootPack(new[] - { - new LootPackEntry(true, Gold, 100.00, "4d50+450"), - new LootPackEntry(false, AosMagicItemsRichType1, 100.00, 1, 3, 0, 75), - new LootPackEntry(false, AosMagicItemsRichType1, 80.00, 1, 3, 0, 75), - new LootPackEntry(false, AosMagicItemsRichType1, 60.00, 1, 5, 0, 100), - new LootPackEntry(false, Instruments, 1.00, 1) - }); - - public static readonly LootPackItem[] AosMagicItemsPoor = - { - new LootPackItem(typeof(BaseWeapon), 3), - new LootPackItem(typeof(BaseRanged), 1), - new LootPackItem(typeof(BaseArmor), 4), - new LootPackItem(typeof(BaseShield), 1), - new LootPackItem(typeof(BaseJewel), 2) - }; - - public static readonly LootPackItem[] AosMagicItemsMeagerType1 = - { - new LootPackItem(typeof(BaseWeapon), 56), - new LootPackItem(typeof(BaseRanged), 14), - new LootPackItem(typeof(BaseArmor), 81), - new LootPackItem(typeof(BaseShield), 11), - new LootPackItem(typeof(BaseJewel), 42) - }; - - public static readonly LootPackItem[] AosMagicItemsMeagerType2 = - { - new LootPackItem(typeof(BaseWeapon), 28), - new LootPackItem(typeof(BaseRanged), 7), - new LootPackItem(typeof(BaseArmor), 40), - new LootPackItem(typeof(BaseShield), 5), - new LootPackItem(typeof(BaseJewel), 21) - }; - - public static readonly LootPackItem[] AosMagicItemsAverageType1 = - { - new LootPackItem(typeof(BaseWeapon), 90), - new LootPackItem(typeof(BaseRanged), 23), - new LootPackItem(typeof(BaseArmor), 130), - new LootPackItem(typeof(BaseShield), 17), - new LootPackItem(typeof(BaseJewel), 68) - }; - - public static readonly LootPackItem[] AosMagicItemsAverageType2 = - { - new LootPackItem(typeof(BaseWeapon), 54), - new LootPackItem(typeof(BaseRanged), 13), - new LootPackItem(typeof(BaseArmor), 77), - new LootPackItem(typeof(BaseShield), 10), - new LootPackItem(typeof(BaseJewel), 40) - }; - - public static readonly LootPackItem[] AosMagicItemsRichType2 = - { - new LootPackItem(typeof(BaseWeapon), 170), - new LootPackItem(typeof(BaseRanged), 43), - new LootPackItem(typeof(BaseArmor), 245), - new LootPackItem(typeof(BaseShield), 32), - new LootPackItem(typeof(BaseJewel), 128) - }; - - public static readonly LootPackItem[] AosMagicItemsFilthyRichType1 = - { - new LootPackItem(typeof(BaseWeapon), 219), - new LootPackItem(typeof(BaseRanged), 55), - new LootPackItem(typeof(BaseArmor), 315), - new LootPackItem(typeof(BaseShield), 41), - new LootPackItem(typeof(BaseJewel), 164) - }; - - public static readonly LootPackItem[] AosMagicItemsFilthyRichType2 = - { - new LootPackItem(typeof(BaseWeapon), 239), - new LootPackItem(typeof(BaseRanged), 60), - new LootPackItem(typeof(BaseArmor), 343), - new LootPackItem(typeof(BaseShield), 90), - new LootPackItem(typeof(BaseJewel), 45) - }; - - public static readonly LootPackItem[] AosMagicItemsUltraRich = - { - new LootPackItem(typeof(BaseWeapon), 276), - new LootPackItem(typeof(BaseRanged), 69), - new LootPackItem(typeof(BaseArmor), 397), - new LootPackItem(typeof(BaseShield), 52), - new LootPackItem(typeof(BaseJewel), 207) - }; - - public static readonly LootPack SePoor = new LootPack(new[] - { - new LootPackEntry(true, Gold, 100.00, "2d10+20"), - new LootPackEntry(false, AosMagicItemsPoor, 1.00, 1, 5, 0, 100), - new LootPackEntry(false, Instruments, 0.02, 1) - }); - - public static readonly LootPack SeMeager = new LootPack(new[] - { - new LootPackEntry(true, Gold, 100.00, "4d10+40"), - new LootPackEntry(false, AosMagicItemsMeagerType1, 20.40, 1, 2, 0, 50), - new LootPackEntry(false, AosMagicItemsMeagerType2, 10.20, 1, 5, 0, 100), - new LootPackEntry(false, Instruments, 0.10, 1) - }); - - public static readonly LootPack SeAverage = new LootPack(new[] - { - new LootPackEntry(true, Gold, 100.00, "8d10+100"), - new LootPackEntry(false, AosMagicItemsAverageType1, 32.80, 1, 3, 0, 50), - new LootPackEntry(false, AosMagicItemsAverageType1, 32.80, 1, 4, 0, 75), - new LootPackEntry(false, AosMagicItemsAverageType2, 19.50, 1, 5, 0, 100), - new LootPackEntry(false, Instruments, 0.40, 1) - }); - - public static readonly LootPack SeRich = new LootPack(new[] - { - new LootPackEntry(true, Gold, 100.00, "15d10+225"), - new LootPackEntry(false, AosMagicItemsRichType1, 76.30, 1, 4, 0, 75), - new LootPackEntry(false, AosMagicItemsRichType1, 76.30, 1, 4, 0, 75), - new LootPackEntry(false, AosMagicItemsRichType2, 61.70, 1, 5, 0, 100), - new LootPackEntry(false, Instruments, 1.00, 1) - }); - - public static readonly LootPack SeFilthyRich = new LootPack(new[] - { - new LootPackEntry(true, Gold, 100.00, "3d100+400"), - new LootPackEntry(false, AosMagicItemsFilthyRichType1, 79.50, 1, 5, 0, 100), - new LootPackEntry(false, AosMagicItemsFilthyRichType1, 79.50, 1, 5, 0, 100), - new LootPackEntry(false, AosMagicItemsFilthyRichType2, 77.60, 1, 5, 25, 100), - new LootPackEntry(false, Instruments, 2.00, 1) - }); - - public static readonly LootPack SeUltraRich = new LootPack(new[] - { - new LootPackEntry(true, Gold, 100.00, "6d100+600"), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 33, 100), - new LootPackEntry(false, Instruments, 2.00, 1) - }); - - public static readonly LootPack SeSuperBoss = new LootPack(new[] - { - new LootPackEntry(true, Gold, 100.00, "10d100+800"), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 33, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 33, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 33, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 33, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 50, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 50, 100), - new LootPackEntry(false, Instruments, 2.00, 1) - }); - - public static readonly LootPack AosPoor = new LootPack(new[] - { - new LootPackEntry(true, Gold, 100.00, "1d10+10"), - new LootPackEntry(false, AosMagicItemsPoor, 0.02, 1, 5, 0, 90), - new LootPackEntry(false, Instruments, 0.02, 1) - }); - - public static readonly LootPack AosMeager = new LootPack(new[] - { - new LootPackEntry(true, Gold, 100.00, "3d10+20"), - new LootPackEntry(false, AosMagicItemsMeagerType1, 1.00, 1, 2, 0, 10), - new LootPackEntry(false, AosMagicItemsMeagerType2, 0.20, 1, 5, 0, 90), - new LootPackEntry(false, Instruments, 0.10, 1) - }); - - public static readonly LootPack AosAverage = new LootPack(new[] - { - new LootPackEntry(true, Gold, 100.00, "5d10+50"), - new LootPackEntry(false, AosMagicItemsAverageType1, 5.00, 1, 4, 0, 20), - new LootPackEntry(false, AosMagicItemsAverageType1, 2.00, 1, 3, 0, 50), - new LootPackEntry(false, AosMagicItemsAverageType2, 0.50, 1, 5, 0, 90), - new LootPackEntry(false, Instruments, 0.40, 1) - }); - - public static readonly LootPack AosRich = new LootPack(new[] - { - new LootPackEntry(true, Gold, 100.00, "10d10+150"), - new LootPackEntry(false, AosMagicItemsRichType1, 20.00, 1, 4, 0, 40), - new LootPackEntry(false, AosMagicItemsRichType1, 10.00, 1, 5, 0, 60), - new LootPackEntry(false, AosMagicItemsRichType2, 1.00, 1, 5, 0, 90), - new LootPackEntry(false, Instruments, 1.00, 1) - }); - - public static readonly LootPack AosFilthyRich = new LootPack(new[] - { - new LootPackEntry(true, Gold, 100.00, "2d100+200"), - new LootPackEntry(false, AosMagicItemsFilthyRichType1, 33.00, 1, 4, 0, 50), - new LootPackEntry(false, AosMagicItemsFilthyRichType1, 33.00, 1, 4, 0, 60), - new LootPackEntry(false, AosMagicItemsFilthyRichType2, 20.00, 1, 5, 0, 75), - new LootPackEntry(false, AosMagicItemsFilthyRichType2, 5.00, 1, 5, 0, 100), - new LootPackEntry(false, Instruments, 2.00, 1) - }); - - public static readonly LootPack AosUltraRich = new LootPack(new[] - { - new LootPackEntry(true, Gold, 100.00, "5d100+500"), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 35, 100), - new LootPackEntry(false, Instruments, 2.00, 1) - }); - - public static readonly LootPack AosSuperBoss = new LootPack(new[] - { - new LootPackEntry(true, Gold, 100.00, "5d100+500"), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 33, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 33, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 33, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 33, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 50, 100), - new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 50, 100), - new LootPackEntry(false, Instruments, 2.00, 1) - }); - - public static readonly LootPack OldPoor = new LootPack(new[] - { - new LootPackEntry(true, Gold, 100.00, "1d25"), - new LootPackEntry(false, Instruments, 0.02, 1) - }); - - public static readonly LootPack OldMeager = new LootPack(new[] - { - new LootPackEntry(true, Gold, 100.00, "5d10+25"), - new LootPackEntry(false, Instruments, 0.10, 1), - new LootPackEntry(false, OldMagicItems, 1.00, 1, 1, 0, 60), - new LootPackEntry(false, OldMagicItems, 0.20, 1, 1, 10, 70) - }); - - public static readonly LootPack OldAverage = new LootPack(new[] - { - new LootPackEntry(true, Gold, 100.00, "10d10+50"), - new LootPackEntry(false, Instruments, 0.40, 1), - new LootPackEntry(false, OldMagicItems, 5.00, 1, 1, 20, 80), - new LootPackEntry(false, OldMagicItems, 2.00, 1, 1, 30, 90), - new LootPackEntry(false, OldMagicItems, 0.50, 1, 1, 40, 100) - }); - - public static readonly LootPack OldRich = new LootPack(new[] - { - new LootPackEntry(true, Gold, 100.00, "10d10+250"), - new LootPackEntry(false, Instruments, 1.00, 1), - new LootPackEntry(false, OldMagicItems, 20.00, 1, 1, 60, 100), - new LootPackEntry(false, OldMagicItems, 10.00, 1, 1, 65, 100), - new LootPackEntry(false, OldMagicItems, 1.00, 1, 1, 70, 100) - }); - - public static readonly LootPack OldFilthyRich = new LootPack(new[] - { - new LootPackEntry(true, Gold, 100.00, "2d125+400"), - new LootPackEntry(false, Instruments, 2.00, 1), - new LootPackEntry(false, OldMagicItems, 33.00, 1, 1, 50, 100), - new LootPackEntry(false, OldMagicItems, 33.00, 1, 1, 60, 100), - new LootPackEntry(false, OldMagicItems, 20.00, 1, 1, 70, 100), - new LootPackEntry(false, OldMagicItems, 5.00, 1, 1, 80, 100) - }); - - public static readonly LootPack OldUltraRich = new LootPack(new[] - { - new LootPackEntry(true, Gold, 100.00, "5d100+500"), - new LootPackEntry(false, Instruments, 2.00, 1), - new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 40, 100), - new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 40, 100), - new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 50, 100), - new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 50, 100), - new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 60, 100), - new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 60, 100) - }); - - public static readonly LootPack OldSuperBoss = new LootPack(new[] - { - new LootPackEntry(true, Gold, 100.00, "5d100+500"), - new LootPackEntry(false, Instruments, 2.00, 1), - new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 40, 100), - new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 40, 100), - new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 40, 100), - new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 50, 100), - new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 50, 100), - new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 50, 100), - new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 60, 100), - new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 60, 100), - new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 60, 100), - new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 70, 100) - }); - - public static LootPack Poor => Core.SE ? SePoor : Core.AOS ? AosPoor : OldPoor; - public static LootPack Meager => Core.SE ? SeMeager : Core.AOS ? AosMeager : OldMeager; - public static LootPack Average => Core.SE ? SeAverage : Core.AOS ? AosAverage : OldAverage; - public static LootPack Rich => Core.SE ? SeRich : Core.AOS ? AosRich : OldRich; - public static LootPack FilthyRich => Core.SE ? SeFilthyRich : Core.AOS ? AosFilthyRich : OldFilthyRich; - public static LootPack UltraRich => Core.SE ? SeUltraRich : Core.AOS ? AosUltraRich : OldUltraRich; - public static LootPack SuperBoss => Core.SE ? SeSuperBoss : Core.AOS ? AosSuperBoss : OldSuperBoss; - - /* - // TODO: Uncomment once added Legacy - public static readonly LootPackItem[] ParrotItem = new LootPackItem[] - { - new LootPackItem( typeof( ParrotItem ), 1 ) - }; - - public static readonly LootPack Parrot = new LootPack( new LootPackEntry[] - { - new LootPackEntry( false, ParrotItem, 10.00, 1 ) - } ); - */ - } - - public class LootPackEntry - { - private readonly bool m_AtSpawnTime; - - public LootPackEntry(bool atSpawnTime, LootPackItem[] items, double chance, string quantity) : this(atSpawnTime, - items, chance, new LootPackDice(quantity)) - { - } - - public LootPackEntry(bool atSpawnTime, LootPackItem[] items, double chance, int quantity) : this(atSpawnTime, items, - chance, new LootPackDice(0, 0, quantity)) - { - } - - public LootPackEntry(bool atSpawnTime, LootPackItem[] items, double chance, string quantity, int maxProps, - int minIntensity, int maxIntensity) : this(atSpawnTime, items, chance, new LootPackDice(quantity), maxProps, - minIntensity, maxIntensity) - { - } - - public LootPackEntry(bool atSpawnTime, LootPackItem[] items, double chance, int quantity, int maxProps, - int minIntensity, int maxIntensity) : this(atSpawnTime, items, chance, new LootPackDice(0, 0, quantity), - maxProps, minIntensity, maxIntensity) - { - } - - public LootPackEntry(bool atSpawnTime, LootPackItem[] items, double chance, LootPackDice quantity, int maxProps = 0, - int minIntensity = 0, int maxIntensity = 0) - { - m_AtSpawnTime = atSpawnTime; - Items = items; - Chance = (int)(100 * chance); - Quantity = quantity; - MaxProps = maxProps; - MinIntensity = minIntensity; - MaxIntensity = maxIntensity; - } - - public int Chance { get; set; } - - public LootPackDice Quantity { get; set; } - - public int MaxProps { get; set; } - - public int MinIntensity { get; set; } - - public int MaxIntensity { get; set; } - - public LootPackItem[] Items { get; set; } - - private static bool IsInTokuno(Mobile m) - { - if (m.Region.IsPartOf("Fan Dancer's Dojo")) - return true; - - if (m.Region.IsPartOf("Yomotsu Mines")) - return true; - - return m.Map == Map.Tokuno; - } - - private static bool IsMondain(Mobile m) => MondainsLegacy.IsMLRegion(m.Region); - - public Item Construct(Mobile from, int luckChance, bool spawning) - { - if (m_AtSpawnTime != spawning) - return null; - - int totalChance = 0; - - for (int i = 0; i < Items.Length; ++i) - totalChance += Items[i].Chance; - - int rnd = Utility.Random(totalChance); - - for (int i = 0; i < Items.Length; ++i) - { - LootPackItem item = Items[i]; - - if (rnd < item.Chance) - return Mutate(from, luckChance, item.Construct(IsInTokuno(from), IsMondain(from))); - - rnd -= item.Chance; - } - - return null; - } - - private int GetRandomOldBonus() - { - int rnd = Utility.RandomMinMax(MinIntensity, MaxIntensity); - - if (rnd < 50) - return 1; - rnd -= 50; - - if (rnd < 25) - return 2; - rnd -= 25; - - if (rnd < 14) - return 3; - rnd -= 14; - - if (rnd < 8) - return 4; - - return 5; - } - - public Item Mutate(Mobile from, int luckChance, Item item) - { - if (item != null) - { - if (item is BaseWeapon && Utility.Random(100) < 1) + public static readonly LootPackItem[] Instruments = { - item.Delete(); - item = new FireHorn(); - return item; - } + new LootPackItem(typeof(BaseInstrument), 1) + }; - if (item is BaseWeapon || item is BaseArmor || item is BaseJewel || item is BaseHat) + public static readonly LootPackItem[] LowScrollItems = { - if (Core.AOS) - { - int bonusProps = GetBonusProperties(); - int min = MinIntensity; - int max = MaxIntensity; + new LootPackItem(typeof(ClumsyScroll), 1) + }; - if (bonusProps < MaxProps && LootPack.CheckLuck(luckChance)) - ++bonusProps; + public static readonly LootPackItem[] MedScrollItems = + { + new LootPackItem(typeof(ArchCureScroll), 1) + }; - int props = 1 + bonusProps; + public static readonly LootPackItem[] HighScrollItems = + { + new LootPackItem(typeof(SummonAirElementalScroll), 1) + }; - // Make sure we're not spawning items with 6 properties. - if (props > MaxProps) - props = MaxProps; + public static readonly LootPackItem[] GemItems = + { + new LootPackItem(typeof(Amber), 1) + }; - if (item is BaseWeapon weapon) - BaseRunicTool.ApplyAttributesTo(weapon, false, luckChance, props, MinIntensity, MaxIntensity); - else if (item is BaseArmor armor) - BaseRunicTool.ApplyAttributesTo(armor, false, luckChance, props, MinIntensity, MaxIntensity); - else if (item is BaseJewel jewel) - BaseRunicTool.ApplyAttributesTo(jewel, false, luckChance, props, MinIntensity, MaxIntensity); - else - BaseRunicTool.ApplyAttributesTo((BaseHat)item, false, luckChance, props, MinIntensity, - MaxIntensity); - } - else // not aos - { - if (item is BaseWeapon weapon) + public static readonly LootPackItem[] PotionItems = + { + new LootPackItem(typeof(AgilityPotion), 1), + new LootPackItem(typeof(StrengthPotion), 1), + new LootPackItem(typeof(RefreshPotion), 1), + new LootPackItem(typeof(LesserCurePotion), 1), + new LootPackItem(typeof(LesserHealPotion), 1), + new LootPackItem(typeof(LesserPoisonPotion), 1) + }; + + public static readonly LootPackItem[] OldMagicItems = + { + new LootPackItem(typeof(BaseJewel), 1), + new LootPackItem(typeof(BaseArmor), 4), + new LootPackItem(typeof(BaseWeapon), 3), + new LootPackItem(typeof(BaseRanged), 1), + new LootPackItem(typeof(BaseShield), 1) + }; + + public static readonly LootPack LowScrolls = new LootPack( + new[] { - if (Utility.Random(100) < 80) - weapon.AccuracyLevel = (WeaponAccuracyLevel)GetRandomOldBonus(); - - if (Utility.Random(100) < 60) - weapon.DamageLevel = (WeaponDamageLevel)GetRandomOldBonus(); - - if (Utility.Random(100) < 40) - weapon.DurabilityLevel = (WeaponDurabilityLevel)GetRandomOldBonus(); - - if (Utility.Random(100) < 5) - weapon.Slayer = SlayerName.Silver; - - if (from != null && weapon.AccuracyLevel == 0 && weapon.DamageLevel == 0 && - weapon.DurabilityLevel == 0 && weapon.Slayer == SlayerName.None && Utility.Random(100) < 5) - weapon.Slayer = SlayerGroup.GetLootSlayerType(from.GetType()); + new LootPackEntry(false, LowScrollItems, 100.00, 1) } - else if (item is BaseArmor armor) + ); + + public static readonly LootPack MedScrolls = new LootPack( + new[] { - if (Utility.Random(100) < 80) - armor.ProtectionLevel = (ArmorProtectionLevel)GetRandomOldBonus(); - - if (Utility.Random(100) < 40) - armor.Durability = (ArmorDurabilityLevel)GetRandomOldBonus(); + new LootPackEntry(false, MedScrollItems, 100.00, 1) } - } - } - else if (item is BaseInstrument instr) + ); + + public static readonly LootPack HighScrolls = new LootPack( + new[] + { + new LootPackEntry(false, HighScrollItems, 100.00, 1) + } + ); + + public static readonly LootPack Gems = new LootPack( + new[] + { + new LootPackEntry(false, GemItems, 100.00, 1) + } + ); + + public static readonly LootPack Potions = new LootPack( + new[] + { + new LootPackEntry(false, PotionItems, 100.00, 1) + } + ); + + private readonly LootPackEntry[] m_Entries; + + public LootPack(LootPackEntry[] entries) => m_Entries = entries; + + public static int GetLuckChance(Mobile killer, Mobile victim) { - SlayerName slayer = SlayerName.None; + if (!Core.AOS) + return 0; - if (Core.AOS) - slayer = BaseRunicTool.GetRandomSlayer(); - else - slayer = SlayerGroup.GetLootSlayerType(from.GetType()); + var luck = killer.Luck; - if (slayer == SlayerName.None) + if (killer is PlayerMobile pmKiller && pmKiller.SentHonorContext != null && + pmKiller.SentHonorContext.Target == victim) + luck += pmKiller.SentHonorContext.PerfectionLuckBonus; + + if (luck < 0) + return 0; + + if (!Core.SE && luck > 1200) + luck = 1200; + + return (int)(Math.Pow(luck, 1 / 1.8) * 100); + } + + public static int GetLuckChanceForKiller(Mobile dead) + { + var list = BaseCreature.GetLootingRights(dead.DamageEntries, dead.HitsMax); + + DamageStore highest = null; + + for (var i = 0; i < list.Count; ++i) + { + var ds = list[i]; + + if (ds.m_HasRight && (highest == null || ds.m_Damage > highest.m_Damage)) + highest = ds; + } + + if (highest == null) + return 0; + + return GetLuckChance(highest.m_Mobile, dead); + } + + public static bool CheckLuck(int chance) => chance > Utility.Random(10000); + + public void Generate(Mobile from, Container cont, bool spawning, int luckChance) + { + if (cont == null) + return; + + var checkLuck = Core.AOS; + + for (var i = 0; i < m_Entries.Length; ++i) + { + var entry = m_Entries[i]; + + var shouldAdd = entry.Chance > Utility.Random(10000); + + if (!shouldAdd && checkLuck) + { + checkLuck = false; + + if (CheckLuck(luckChance)) + shouldAdd = entry.Chance > Utility.Random(10000); + } + + if (!shouldAdd) + continue; + + var item = entry.Construct(from, luckChance, spawning); + + if (item != null) + if (!item.Stackable || !cont.TryDropItem(from, item, false)) + cont.DropItem(item); + } + } + + public static readonly LootPackItem[] AosMagicItemsRichType1 = + { + new LootPackItem(typeof(BaseWeapon), 211), + new LootPackItem(typeof(BaseRanged), 53), + new LootPackItem(typeof(BaseArmor), 303), + new LootPackItem(typeof(BaseShield), 39), + new LootPackItem(typeof(BaseJewel), 158) + }; + + public static readonly LootPack MlRich = new LootPack( + new[] + { + new LootPackEntry(true, Gold, 100.00, "4d50+450"), + new LootPackEntry(false, AosMagicItemsRichType1, 100.00, 1, 3, 0, 75), + new LootPackEntry(false, AosMagicItemsRichType1, 80.00, 1, 3, 0, 75), + new LootPackEntry(false, AosMagicItemsRichType1, 60.00, 1, 5, 0, 100), + new LootPackEntry(false, Instruments, 1.00, 1) + } + ); + + public static readonly LootPackItem[] AosMagicItemsPoor = + { + new LootPackItem(typeof(BaseWeapon), 3), + new LootPackItem(typeof(BaseRanged), 1), + new LootPackItem(typeof(BaseArmor), 4), + new LootPackItem(typeof(BaseShield), 1), + new LootPackItem(typeof(BaseJewel), 2) + }; + + public static readonly LootPackItem[] AosMagicItemsMeagerType1 = + { + new LootPackItem(typeof(BaseWeapon), 56), + new LootPackItem(typeof(BaseRanged), 14), + new LootPackItem(typeof(BaseArmor), 81), + new LootPackItem(typeof(BaseShield), 11), + new LootPackItem(typeof(BaseJewel), 42) + }; + + public static readonly LootPackItem[] AosMagicItemsMeagerType2 = + { + new LootPackItem(typeof(BaseWeapon), 28), + new LootPackItem(typeof(BaseRanged), 7), + new LootPackItem(typeof(BaseArmor), 40), + new LootPackItem(typeof(BaseShield), 5), + new LootPackItem(typeof(BaseJewel), 21) + }; + + public static readonly LootPackItem[] AosMagicItemsAverageType1 = + { + new LootPackItem(typeof(BaseWeapon), 90), + new LootPackItem(typeof(BaseRanged), 23), + new LootPackItem(typeof(BaseArmor), 130), + new LootPackItem(typeof(BaseShield), 17), + new LootPackItem(typeof(BaseJewel), 68) + }; + + public static readonly LootPackItem[] AosMagicItemsAverageType2 = + { + new LootPackItem(typeof(BaseWeapon), 54), + new LootPackItem(typeof(BaseRanged), 13), + new LootPackItem(typeof(BaseArmor), 77), + new LootPackItem(typeof(BaseShield), 10), + new LootPackItem(typeof(BaseJewel), 40) + }; + + public static readonly LootPackItem[] AosMagicItemsRichType2 = + { + new LootPackItem(typeof(BaseWeapon), 170), + new LootPackItem(typeof(BaseRanged), 43), + new LootPackItem(typeof(BaseArmor), 245), + new LootPackItem(typeof(BaseShield), 32), + new LootPackItem(typeof(BaseJewel), 128) + }; + + public static readonly LootPackItem[] AosMagicItemsFilthyRichType1 = + { + new LootPackItem(typeof(BaseWeapon), 219), + new LootPackItem(typeof(BaseRanged), 55), + new LootPackItem(typeof(BaseArmor), 315), + new LootPackItem(typeof(BaseShield), 41), + new LootPackItem(typeof(BaseJewel), 164) + }; + + public static readonly LootPackItem[] AosMagicItemsFilthyRichType2 = + { + new LootPackItem(typeof(BaseWeapon), 239), + new LootPackItem(typeof(BaseRanged), 60), + new LootPackItem(typeof(BaseArmor), 343), + new LootPackItem(typeof(BaseShield), 90), + new LootPackItem(typeof(BaseJewel), 45) + }; + + public static readonly LootPackItem[] AosMagicItemsUltraRich = + { + new LootPackItem(typeof(BaseWeapon), 276), + new LootPackItem(typeof(BaseRanged), 69), + new LootPackItem(typeof(BaseArmor), 397), + new LootPackItem(typeof(BaseShield), 52), + new LootPackItem(typeof(BaseJewel), 207) + }; + + public static readonly LootPack SePoor = new LootPack( + new[] + { + new LootPackEntry(true, Gold, 100.00, "2d10+20"), + new LootPackEntry(false, AosMagicItemsPoor, 1.00, 1, 5, 0, 100), + new LootPackEntry(false, Instruments, 0.02, 1) + } + ); + + public static readonly LootPack SeMeager = new LootPack( + new[] + { + new LootPackEntry(true, Gold, 100.00, "4d10+40"), + new LootPackEntry(false, AosMagicItemsMeagerType1, 20.40, 1, 2, 0, 50), + new LootPackEntry(false, AosMagicItemsMeagerType2, 10.20, 1, 5, 0, 100), + new LootPackEntry(false, Instruments, 0.10, 1) + } + ); + + public static readonly LootPack SeAverage = new LootPack( + new[] + { + new LootPackEntry(true, Gold, 100.00, "8d10+100"), + new LootPackEntry(false, AosMagicItemsAverageType1, 32.80, 1, 3, 0, 50), + new LootPackEntry(false, AosMagicItemsAverageType1, 32.80, 1, 4, 0, 75), + new LootPackEntry(false, AosMagicItemsAverageType2, 19.50, 1, 5, 0, 100), + new LootPackEntry(false, Instruments, 0.40, 1) + } + ); + + public static readonly LootPack SeRich = new LootPack( + new[] + { + new LootPackEntry(true, Gold, 100.00, "15d10+225"), + new LootPackEntry(false, AosMagicItemsRichType1, 76.30, 1, 4, 0, 75), + new LootPackEntry(false, AosMagicItemsRichType1, 76.30, 1, 4, 0, 75), + new LootPackEntry(false, AosMagicItemsRichType2, 61.70, 1, 5, 0, 100), + new LootPackEntry(false, Instruments, 1.00, 1) + } + ); + + public static readonly LootPack SeFilthyRich = new LootPack( + new[] + { + new LootPackEntry(true, Gold, 100.00, "3d100+400"), + new LootPackEntry(false, AosMagicItemsFilthyRichType1, 79.50, 1, 5, 0, 100), + new LootPackEntry(false, AosMagicItemsFilthyRichType1, 79.50, 1, 5, 0, 100), + new LootPackEntry(false, AosMagicItemsFilthyRichType2, 77.60, 1, 5, 25, 100), + new LootPackEntry(false, Instruments, 2.00, 1) + } + ); + + public static readonly LootPack SeUltraRich = new LootPack( + new[] + { + new LootPackEntry(true, Gold, 100.00, "6d100+600"), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 33, 100), + new LootPackEntry(false, Instruments, 2.00, 1) + } + ); + + public static readonly LootPack SeSuperBoss = new LootPack( + new[] + { + new LootPackEntry(true, Gold, 100.00, "10d100+800"), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 33, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 33, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 33, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 33, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 50, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 50, 100), + new LootPackEntry(false, Instruments, 2.00, 1) + } + ); + + public static readonly LootPack AosPoor = new LootPack( + new[] + { + new LootPackEntry(true, Gold, 100.00, "1d10+10"), + new LootPackEntry(false, AosMagicItemsPoor, 0.02, 1, 5, 0, 90), + new LootPackEntry(false, Instruments, 0.02, 1) + } + ); + + public static readonly LootPack AosMeager = new LootPack( + new[] + { + new LootPackEntry(true, Gold, 100.00, "3d10+20"), + new LootPackEntry(false, AosMagicItemsMeagerType1, 1.00, 1, 2, 0, 10), + new LootPackEntry(false, AosMagicItemsMeagerType2, 0.20, 1, 5, 0, 90), + new LootPackEntry(false, Instruments, 0.10, 1) + } + ); + + public static readonly LootPack AosAverage = new LootPack( + new[] + { + new LootPackEntry(true, Gold, 100.00, "5d10+50"), + new LootPackEntry(false, AosMagicItemsAverageType1, 5.00, 1, 4, 0, 20), + new LootPackEntry(false, AosMagicItemsAverageType1, 2.00, 1, 3, 0, 50), + new LootPackEntry(false, AosMagicItemsAverageType2, 0.50, 1, 5, 0, 90), + new LootPackEntry(false, Instruments, 0.40, 1) + } + ); + + public static readonly LootPack AosRich = new LootPack( + new[] + { + new LootPackEntry(true, Gold, 100.00, "10d10+150"), + new LootPackEntry(false, AosMagicItemsRichType1, 20.00, 1, 4, 0, 40), + new LootPackEntry(false, AosMagicItemsRichType1, 10.00, 1, 5, 0, 60), + new LootPackEntry(false, AosMagicItemsRichType2, 1.00, 1, 5, 0, 90), + new LootPackEntry(false, Instruments, 1.00, 1) + } + ); + + public static readonly LootPack AosFilthyRich = new LootPack( + new[] + { + new LootPackEntry(true, Gold, 100.00, "2d100+200"), + new LootPackEntry(false, AosMagicItemsFilthyRichType1, 33.00, 1, 4, 0, 50), + new LootPackEntry(false, AosMagicItemsFilthyRichType1, 33.00, 1, 4, 0, 60), + new LootPackEntry(false, AosMagicItemsFilthyRichType2, 20.00, 1, 5, 0, 75), + new LootPackEntry(false, AosMagicItemsFilthyRichType2, 5.00, 1, 5, 0, 100), + new LootPackEntry(false, Instruments, 2.00, 1) + } + ); + + public static readonly LootPack AosUltraRich = new LootPack( + new[] + { + new LootPackEntry(true, Gold, 100.00, "5d100+500"), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 35, 100), + new LootPackEntry(false, Instruments, 2.00, 1) + } + ); + + public static readonly LootPack AosSuperBoss = new LootPack( + new[] + { + new LootPackEntry(true, Gold, 100.00, "5d100+500"), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 25, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 33, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 33, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 33, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 33, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 50, 100), + new LootPackEntry(false, AosMagicItemsUltraRich, 100.00, 1, 5, 50, 100), + new LootPackEntry(false, Instruments, 2.00, 1) + } + ); + + public static readonly LootPack OldPoor = new LootPack( + new[] + { + new LootPackEntry(true, Gold, 100.00, "1d25"), + new LootPackEntry(false, Instruments, 0.02, 1) + } + ); + + public static readonly LootPack OldMeager = new LootPack( + new[] + { + new LootPackEntry(true, Gold, 100.00, "5d10+25"), + new LootPackEntry(false, Instruments, 0.10, 1), + new LootPackEntry(false, OldMagicItems, 1.00, 1, 1, 0, 60), + new LootPackEntry(false, OldMagicItems, 0.20, 1, 1, 10, 70) + } + ); + + public static readonly LootPack OldAverage = new LootPack( + new[] + { + new LootPackEntry(true, Gold, 100.00, "10d10+50"), + new LootPackEntry(false, Instruments, 0.40, 1), + new LootPackEntry(false, OldMagicItems, 5.00, 1, 1, 20, 80), + new LootPackEntry(false, OldMagicItems, 2.00, 1, 1, 30, 90), + new LootPackEntry(false, OldMagicItems, 0.50, 1, 1, 40, 100) + } + ); + + public static readonly LootPack OldRich = new LootPack( + new[] + { + new LootPackEntry(true, Gold, 100.00, "10d10+250"), + new LootPackEntry(false, Instruments, 1.00, 1), + new LootPackEntry(false, OldMagicItems, 20.00, 1, 1, 60, 100), + new LootPackEntry(false, OldMagicItems, 10.00, 1, 1, 65, 100), + new LootPackEntry(false, OldMagicItems, 1.00, 1, 1, 70, 100) + } + ); + + public static readonly LootPack OldFilthyRich = new LootPack( + new[] + { + new LootPackEntry(true, Gold, 100.00, "2d125+400"), + new LootPackEntry(false, Instruments, 2.00, 1), + new LootPackEntry(false, OldMagicItems, 33.00, 1, 1, 50, 100), + new LootPackEntry(false, OldMagicItems, 33.00, 1, 1, 60, 100), + new LootPackEntry(false, OldMagicItems, 20.00, 1, 1, 70, 100), + new LootPackEntry(false, OldMagicItems, 5.00, 1, 1, 80, 100) + } + ); + + public static readonly LootPack OldUltraRich = new LootPack( + new[] + { + new LootPackEntry(true, Gold, 100.00, "5d100+500"), + new LootPackEntry(false, Instruments, 2.00, 1), + new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 40, 100), + new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 40, 100), + new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 50, 100), + new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 50, 100), + new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 60, 100), + new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 60, 100) + } + ); + + public static readonly LootPack OldSuperBoss = new LootPack( + new[] + { + new LootPackEntry(true, Gold, 100.00, "5d100+500"), + new LootPackEntry(false, Instruments, 2.00, 1), + new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 40, 100), + new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 40, 100), + new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 40, 100), + new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 50, 100), + new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 50, 100), + new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 50, 100), + new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 60, 100), + new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 60, 100), + new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 60, 100), + new LootPackEntry(false, OldMagicItems, 100.00, 1, 1, 70, 100) + } + ); + + public static LootPack Poor => Core.SE ? SePoor : + Core.AOS ? AosPoor : OldPoor; + + public static LootPack Meager => Core.SE ? SeMeager : + Core.AOS ? AosMeager : OldMeager; + + public static LootPack Average => Core.SE ? SeAverage : + Core.AOS ? AosAverage : OldAverage; + + public static LootPack Rich => Core.SE ? SeRich : + Core.AOS ? AosRich : OldRich; + + public static LootPack FilthyRich => Core.SE ? SeFilthyRich : + Core.AOS ? AosFilthyRich : OldFilthyRich; + + public static LootPack UltraRich => Core.SE ? SeUltraRich : + Core.AOS ? AosUltraRich : OldUltraRich; + + public static LootPack SuperBoss => Core.SE ? SeSuperBoss : + Core.AOS ? AosSuperBoss : OldSuperBoss; + + /* + // TODO: Uncomment once added Legacy + public static readonly LootPackItem[] ParrotItem = new LootPackItem[] { - instr.Delete(); + new LootPackItem( typeof( ParrotItem ), 1 ) + }; + + public static readonly LootPack Parrot = new LootPack( new LootPackEntry[] + { + new LootPackEntry( false, ParrotItem, 10.00, 1 ) + } ); + */ + } + + public class LootPackEntry + { + private readonly bool m_AtSpawnTime; + + public LootPackEntry(bool atSpawnTime, LootPackItem[] items, double chance, string quantity) : this( + atSpawnTime, + items, + chance, + new LootPackDice(quantity) + ) + { + } + + public LootPackEntry(bool atSpawnTime, LootPackItem[] items, double chance, int quantity) : this( + atSpawnTime, + items, + chance, + new LootPackDice(0, 0, quantity) + ) + { + } + + public LootPackEntry( + bool atSpawnTime, LootPackItem[] items, double chance, string quantity, int maxProps, + int minIntensity, int maxIntensity + ) : this( + atSpawnTime, + items, + chance, + new LootPackDice(quantity), + maxProps, + minIntensity, + maxIntensity + ) + { + } + + public LootPackEntry( + bool atSpawnTime, LootPackItem[] items, double chance, int quantity, int maxProps, + int minIntensity, int maxIntensity + ) : this( + atSpawnTime, + items, + chance, + new LootPackDice(0, 0, quantity), + maxProps, + minIntensity, + maxIntensity + ) + { + } + + public LootPackEntry( + bool atSpawnTime, LootPackItem[] items, double chance, LootPackDice quantity, int maxProps = 0, + int minIntensity = 0, int maxIntensity = 0 + ) + { + m_AtSpawnTime = atSpawnTime; + Items = items; + Chance = (int)(100 * chance); + Quantity = quantity; + MaxProps = maxProps; + MinIntensity = minIntensity; + MaxIntensity = maxIntensity; + } + + public int Chance { get; set; } + + public LootPackDice Quantity { get; set; } + + public int MaxProps { get; set; } + + public int MinIntensity { get; set; } + + public int MaxIntensity { get; set; } + + public LootPackItem[] Items { get; set; } + + private static bool IsInTokuno(Mobile m) + { + if (m.Region.IsPartOf("Fan Dancer's Dojo")) + return true; + + if (m.Region.IsPartOf("Yomotsu Mines")) + return true; + + return m.Map == Map.Tokuno; + } + + private static bool IsMondain(Mobile m) => MondainsLegacy.IsMLRegion(m.Region); + + public Item Construct(Mobile from, int luckChance, bool spawning) + { + if (m_AtSpawnTime != spawning) + return null; + + var totalChance = 0; + + for (var i = 0; i < Items.Length; ++i) + totalChance += Items[i].Chance; + + var rnd = Utility.Random(totalChance); + + for (var i = 0; i < Items.Length; ++i) + { + var item = Items[i]; + + if (rnd < item.Chance) + return Mutate(from, luckChance, item.Construct(IsInTokuno(from), IsMondain(from))); + + rnd -= item.Chance; + } + return null; - } - - instr.Quality = InstrumentQuality.Regular; - instr.Slayer = slayer; } - if (item.Stackable) - item.Amount = Quantity.Roll(); - } - - return item; - } - - public int GetBonusProperties() - { - int p0 = 0, p1 = 0, p2 = 0, p3 = 0, p4 = 0, p5 = 0; - - switch (MaxProps) - { - case 1: - p0 = 3; - p1 = 1; - break; - case 2: - p0 = 6; - p1 = 3; - p2 = 1; - break; - case 3: - p0 = 10; - p1 = 6; - p2 = 3; - p3 = 1; - break; - case 4: - p0 = 16; - p1 = 12; - p2 = 6; - p3 = 5; - p4 = 1; - break; - case 5: - p0 = 30; - p1 = 25; - p2 = 20; - p3 = 15; - p4 = 9; - p5 = 1; - break; - } - - int pc = p0 + p1 + p2 + p3 + p4 + p5; - - int rnd = Utility.Random(pc); - - if (rnd < p5) - return 5; - - rnd -= p5; - - if (rnd < p4) - return 4; - - rnd -= p4; - - if (rnd < p3) - return 3; - - rnd -= p3; - - if (rnd < p2) - return 2; - - return rnd - p2 < p1 ? 1 : 0; - } - } - - public class LootPackItem - { - private static readonly Type[] m_BlankTypes = { typeof(BlankScroll) }; - - private static readonly Type[][] m_NecroTypes = - { - new[] // low - { - typeof(AnimateDeadScroll), typeof(BloodOathScroll), typeof(CorpseSkinScroll), typeof(CurseWeaponScroll), - typeof(EvilOmenScroll), typeof(HorrificBeastScroll), typeof(MindRotScroll), typeof(PainSpikeScroll), - typeof(SummonFamiliarScroll), typeof(WraithFormScroll) - }, - new[] // med - { - typeof(LichFormScroll), typeof(PoisonStrikeScroll), typeof(StrangleScroll), typeof(WitherScroll) - }, - - Core.SE - ? new[] // high + private int GetRandomOldBonus() { - typeof(VengefulSpiritScroll), typeof(VampiricEmbraceScroll), typeof(ExorcismScroll) + var rnd = Utility.RandomMinMax(MinIntensity, MaxIntensity); + + if (rnd < 50) + return 1; + rnd -= 50; + + if (rnd < 25) + return 2; + rnd -= 25; + + if (rnd < 14) + return 3; + rnd -= 14; + + if (rnd < 8) + return 4; + + return 5; } - : new[] // high + + public Item Mutate(Mobile from, int luckChance, Item item) { - typeof(VengefulSpiritScroll), typeof(VampiricEmbraceScroll) + if (item != null) + { + if (item is BaseWeapon && Utility.Random(100) < 1) + { + item.Delete(); + item = new FireHorn(); + return item; + } + + if (item is BaseWeapon || item is BaseArmor || item is BaseJewel || item is BaseHat) + { + if (Core.AOS) + { + var bonusProps = GetBonusProperties(); + var min = MinIntensity; + var max = MaxIntensity; + + if (bonusProps < MaxProps && LootPack.CheckLuck(luckChance)) + ++bonusProps; + + var props = 1 + bonusProps; + + // Make sure we're not spawning items with 6 properties. + if (props > MaxProps) + props = MaxProps; + + if (item is BaseWeapon weapon) + BaseRunicTool.ApplyAttributesTo(weapon, false, luckChance, props, MinIntensity, MaxIntensity); + else if (item is BaseArmor armor) + BaseRunicTool.ApplyAttributesTo(armor, false, luckChance, props, MinIntensity, MaxIntensity); + else if (item is BaseJewel jewel) + BaseRunicTool.ApplyAttributesTo(jewel, false, luckChance, props, MinIntensity, MaxIntensity); + else + BaseRunicTool.ApplyAttributesTo( + (BaseHat)item, + false, + luckChance, + props, + MinIntensity, + MaxIntensity + ); + } + else // not aos + { + if (item is BaseWeapon weapon) + { + if (Utility.Random(100) < 80) + weapon.AccuracyLevel = (WeaponAccuracyLevel)GetRandomOldBonus(); + + if (Utility.Random(100) < 60) + weapon.DamageLevel = (WeaponDamageLevel)GetRandomOldBonus(); + + if (Utility.Random(100) < 40) + weapon.DurabilityLevel = (WeaponDurabilityLevel)GetRandomOldBonus(); + + if (Utility.Random(100) < 5) + weapon.Slayer = SlayerName.Silver; + + if (from != null && weapon.AccuracyLevel == 0 && weapon.DamageLevel == 0 && + weapon.DurabilityLevel == 0 && weapon.Slayer == SlayerName.None && Utility.Random(100) < 5) + weapon.Slayer = SlayerGroup.GetLootSlayerType(from.GetType()); + } + else if (item is BaseArmor armor) + { + if (Utility.Random(100) < 80) + armor.ProtectionLevel = (ArmorProtectionLevel)GetRandomOldBonus(); + + if (Utility.Random(100) < 40) + armor.Durability = (ArmorDurabilityLevel)GetRandomOldBonus(); + } + } + } + else if (item is BaseInstrument instr) + { + var slayer = SlayerName.None; + + if (Core.AOS) + slayer = BaseRunicTool.GetRandomSlayer(); + else + slayer = SlayerGroup.GetLootSlayerType(from.GetType()); + + if (slayer == SlayerName.None) + { + instr.Delete(); + return null; + } + + instr.Quality = InstrumentQuality.Regular; + instr.Slayer = slayer; + } + + if (item.Stackable) + item.Amount = Quantity.Roll(); + } + + return item; } - }; - public LootPackItem(Type type, int chance) - { - Type = type; - Chance = chance; + public int GetBonusProperties() + { + int p0 = 0, p1 = 0, p2 = 0, p3 = 0, p4 = 0, p5 = 0; + + switch (MaxProps) + { + case 1: + p0 = 3; + p1 = 1; + break; + case 2: + p0 = 6; + p1 = 3; + p2 = 1; + break; + case 3: + p0 = 10; + p1 = 6; + p2 = 3; + p3 = 1; + break; + case 4: + p0 = 16; + p1 = 12; + p2 = 6; + p3 = 5; + p4 = 1; + break; + case 5: + p0 = 30; + p1 = 25; + p2 = 20; + p3 = 15; + p4 = 9; + p5 = 1; + break; + } + + var pc = p0 + p1 + p2 + p3 + p4 + p5; + + var rnd = Utility.Random(pc); + + if (rnd < p5) + return 5; + + rnd -= p5; + + if (rnd < p4) + return 4; + + rnd -= p4; + + if (rnd < p3) + return 3; + + rnd -= p3; + + if (rnd < p2) + return 2; + + return rnd - p2 < p1 ? 1 : 0; + } } - public Type Type { get; set; } - - public int Chance { get; set; } - - public static Item RandomScroll(int index, int minCircle, int maxCircle) + public class LootPackItem { - --minCircle; - --maxCircle; + private static readonly Type[] m_BlankTypes = { typeof(BlankScroll) }; - int scrollCount = (maxCircle - minCircle + 1) * 8; + private static readonly Type[][] m_NecroTypes = + { + new[] // low + { + typeof(AnimateDeadScroll), typeof(BloodOathScroll), typeof(CorpseSkinScroll), typeof(CurseWeaponScroll), + typeof(EvilOmenScroll), typeof(HorrificBeastScroll), typeof(MindRotScroll), typeof(PainSpikeScroll), + typeof(SummonFamiliarScroll), typeof(WraithFormScroll) + }, + new[] // med + { + typeof(LichFormScroll), typeof(PoisonStrikeScroll), typeof(StrangleScroll), typeof(WitherScroll) + }, - if (index == 0) - scrollCount += m_BlankTypes.Length; + Core.SE + ? new[] // high + { + typeof(VengefulSpiritScroll), typeof(VampiricEmbraceScroll), typeof(ExorcismScroll) + } + : new[] // high + { + typeof(VengefulSpiritScroll), typeof(VampiricEmbraceScroll) + } + }; - if (Core.AOS) - scrollCount += m_NecroTypes[index].Length; + public LootPackItem(Type type, int chance) + { + Type = type; + Chance = chance; + } - int rnd = Utility.Random(scrollCount); + public Type Type { get; set; } - if (index == 0 && rnd < m_BlankTypes.Length) - return Loot.Construct(m_BlankTypes); - if (index == 0) - rnd -= m_BlankTypes.Length; + public int Chance { get; set; } - if (Core.AOS && rnd < m_NecroTypes.Length) - return Loot.Construct(m_NecroTypes[index]); + public static Item RandomScroll(int index, int minCircle, int maxCircle) + { + --minCircle; + --maxCircle; - return Loot.RandomScroll(minCircle * 8, maxCircle * 8 + 7, SpellbookType.Regular); + var scrollCount = (maxCircle - minCircle + 1) * 8; + + if (index == 0) + scrollCount += m_BlankTypes.Length; + + if (Core.AOS) + scrollCount += m_NecroTypes[index].Length; + + var rnd = Utility.Random(scrollCount); + + if (index == 0 && rnd < m_BlankTypes.Length) + return Loot.Construct(m_BlankTypes); + if (index == 0) + rnd -= m_BlankTypes.Length; + + if (Core.AOS && rnd < m_NecroTypes.Length) + return Loot.Construct(m_NecroTypes[index]); + + return Loot.RandomScroll(minCircle * 8, maxCircle * 8 + 7, SpellbookType.Regular); + } + + public Item Construct(bool inTokuno, bool isMondain) + { + try + { + Item item; + + if (Type == typeof(BaseRanged)) + item = Loot.RandomRangedWeapon(inTokuno, isMondain); + else if (Type == typeof(BaseWeapon)) + item = Loot.RandomWeapon(inTokuno, isMondain); + else if (Type == typeof(BaseArmor)) + item = Loot.RandomArmorOrHat(inTokuno, isMondain); + else if (Type == typeof(BaseShield)) + item = Loot.RandomShield(); + else if (Type == typeof(BaseJewel)) + item = Core.AOS ? Loot.RandomJewelry() : Loot.RandomArmorOrShieldOrWeapon(); + else if (Type == typeof(BaseInstrument)) + item = Loot.RandomInstrument(); + else if (Type == typeof(Amber)) // gem + item = Loot.RandomGem(); + else if (Type == typeof(ClumsyScroll)) // low scroll + item = RandomScroll(0, 1, 3); + else if (Type == typeof(ArchCureScroll)) // med scroll + item = RandomScroll(1, 4, 7); + else if (Type == typeof(SummonAirElementalScroll)) // high scroll + item = RandomScroll(2, 8, 8); + else + item = ActivatorUtil.CreateInstance(Type) as Item; + + return item; + } + catch + { + // ignored + } + + return null; + } } - public Item Construct(bool inTokuno, bool isMondain) + public class LootPackDice { - try - { - Item item; + public LootPackDice(string str) + { + var start = 0; + var index = str.IndexOf('d', start); - if (Type == typeof(BaseRanged)) - item = Loot.RandomRangedWeapon(inTokuno, isMondain); - else if (Type == typeof(BaseWeapon)) - item = Loot.RandomWeapon(inTokuno, isMondain); - else if (Type == typeof(BaseArmor)) - item = Loot.RandomArmorOrHat(inTokuno, isMondain); - else if (Type == typeof(BaseShield)) - item = Loot.RandomShield(); - else if (Type == typeof(BaseJewel)) - item = Core.AOS ? Loot.RandomJewelry() : Loot.RandomArmorOrShieldOrWeapon(); - else if (Type == typeof(BaseInstrument)) - item = Loot.RandomInstrument(); - else if (Type == typeof(Amber)) // gem - item = Loot.RandomGem(); - else if (Type == typeof(ClumsyScroll)) // low scroll - item = RandomScroll(0, 1, 3); - else if (Type == typeof(ArchCureScroll)) // med scroll - item = RandomScroll(1, 4, 7); - else if (Type == typeof(SummonAirElementalScroll)) // high scroll - item = RandomScroll(2, 8, 8); - else - item = ActivatorUtil.CreateInstance(Type) as Item; + if (index < start) + return; - return item; - } - catch - { - // ignored - } + Count = Utility.ToInt32(str.Substring(start, index - start)); - return null; + start = index + 1; + index = str.IndexOf('+', start); + + var negative = index < start; + + if (negative) + index = str.IndexOf('-', start); + + if (index < start) + index = str.Length; + + Sides = Utility.ToInt32(str.Substring(start, index - start)); + + if (index == str.Length) + return; + + start = index + 1; + index = str.Length; + + Bonus = Utility.ToInt32(str.Substring(start, index - start)); + + if (negative) + Bonus *= -1; + } + + public LootPackDice(int count, int sides, int bonus) + { + Count = count; + Sides = sides; + Bonus = bonus; + } + + public int Count { get; set; } + + public int Sides { get; set; } + + public int Bonus { get; set; } + + public int Roll() + { + var v = Bonus; + + for (var i = 0; i < Count; ++i) + v += Utility.Random(1, Sides); + + return v; + } } - } - - public class LootPackDice - { - public LootPackDice(string str) - { - int start = 0; - int index = str.IndexOf('d', start); - - if (index < start) - return; - - Count = Utility.ToInt32(str.Substring(start, index - start)); - - start = index + 1; - index = str.IndexOf('+', start); - - bool negative = index < start; - - if (negative) - index = str.IndexOf('-', start); - - if (index < start) - index = str.Length; - - Sides = Utility.ToInt32(str.Substring(start, index - start)); - - if (index == str.Length) - return; - - start = index + 1; - index = str.Length; - - Bonus = Utility.ToInt32(str.Substring(start, index - start)); - - if (negative) - Bonus *= -1; - } - - public LootPackDice(int count, int sides, int bonus) - { - Count = count; - Sides = sides; - Bonus = bonus; - } - - public int Count { get; set; } - - public int Sides { get; set; } - - public int Bonus { get; set; } - - public int Roll() - { - int v = Bonus; - - for (int i = 0; i < Count; ++i) - v += Utility.Random(1, Sides); - - return v; - } - } } diff --git a/Projects/UOContent/Misc/MapDefinitions.cs b/Projects/UOContent/Misc/MapDefinitions.cs index 924a5cb12..3af6886fb 100644 --- a/Projects/UOContent/Misc/MapDefinitions.cs +++ b/Projects/UOContent/Misc/MapDefinitions.cs @@ -1,53 +1,59 @@ namespace Server.Misc { - public static class MapDefinitions - { - public static void Configure() + public static class MapDefinitions { - /* Here we configure all maps. Some notes: - * - * 1) The first 32 maps are reserved for core use. - * 2) Map 0x7F is reserved for core use. - * 3) Map 0xFF is reserved for core use. - * 4) Changing or removing any predefined maps may cause server instability. - */ + public static void Configure() + { + /* Here we configure all maps. Some notes: + * + * 1) The first 32 maps are reserved for core use. + * 2) Map 0x7F is reserved for core use. + * 3) Map 0xFF is reserved for core use. + * 4) Changing or removing any predefined maps may cause server instability. + */ - RegisterMap(0, 0, 0, 7168, 4096, 4, "Felucca", MapRules.FeluccaRules); - RegisterMap(1, 1, 1, 7168, 4096, 0, "Trammel", MapRules.TrammelRules); - RegisterMap(2, 2, 2, 2304, 1600, 1, "Ilshenar", MapRules.TrammelRules); - RegisterMap(3, 3, 3, 2560, 2048, 1, "Malas", MapRules.TrammelRules); - RegisterMap(4, 4, 4, 1448, 1448, 1, "Tokuno", MapRules.TrammelRules); - RegisterMap(5, 5, 5, 1280, 4096, 1, "TerMur", MapRules.TrammelRules); + RegisterMap(0, 0, 0, 7168, 4096, 4, "Felucca", MapRules.FeluccaRules); + RegisterMap(1, 1, 1, 7168, 4096, 0, "Trammel", MapRules.TrammelRules); + RegisterMap(2, 2, 2, 2304, 1600, 1, "Ilshenar", MapRules.TrammelRules); + RegisterMap(3, 3, 3, 2560, 2048, 1, "Malas", MapRules.TrammelRules); + RegisterMap(4, 4, 4, 1448, 1448, 1, "Tokuno", MapRules.TrammelRules); + RegisterMap(5, 5, 5, 1280, 4096, 1, "TerMur", MapRules.TrammelRules); - RegisterMap(0x7F, 0x7F, 0x7F, Map.SectorSize, Map.SectorSize, 1, "Internal", MapRules.Internal); + RegisterMap(0x7F, 0x7F, 0x7F, Map.SectorSize, Map.SectorSize, 1, "Internal", MapRules.Internal); - /* Example of registering a custom map: - * RegisterMap( 32, 0, 0, 6144, 4096, 3, "Iceland", MapRules.FeluccaRules ); - * - * Defined: - * RegisterMap( , , , , , , , ); - * - : An unreserved unique index for this map - * - : An identification number used in client communications. For any visible maps, this value must be from 0-5 - * - : A file identification number. For any visible maps, this value must be from 0-5 - * - , : Size of the map (in tiles) - * - : Season of the map. 0 = Spring, 1 = Summer, 2 = Fall, 3 = Winter, 4 = Desolation - * - : Reference name for the map, used in props gump, get/set commands, region loading, etc - * - : Rules and restrictions associated with the map. See documentation for details - */ + /* Example of registering a custom map: + * RegisterMap( 32, 0, 0, 6144, 4096, 3, "Iceland", MapRules.FeluccaRules ); + * + * Defined: + * RegisterMap( , , , , , , , ); + * - : An unreserved unique index for this map + * - : An identification number used in client communications. For any visible maps, this value must be from 0-5 + * - : A file identification number. For any visible maps, this value must be from 0-5 + * - , : Size of the map (in tiles) + * - : Season of the map. 0 = Spring, 1 = Summer, 2 = Fall, 3 = Winter, 4 = Desolation + * - : Reference name for the map, used in props gump, get/set commands, region loading, etc + * - : Rules and restrictions associated with the map. See documentation for details + */ - // Using this requires the old mapDif files to be present. Only needed to support Clients < 6.0.0.0 - TileMatrixPatch.Enabled = ServerConfiguration.GetOrUpdateSetting("maps.enableTileMatrixPatches", !Core.SE); + // Using this requires the old mapDif files to be present. Only needed to support Clients < 6.0.0.0 + TileMatrixPatch.Enabled = ServerConfiguration.GetOrUpdateSetting("maps.enableTileMatrixPatches", !Core.SE); - MultiComponentList.PostHSFormat = ServerConfiguration.GetOrUpdateSetting("maps.enablePostHSMultiComponentFormat", true); // OSI Client Patch 7.0.9.0 + MultiComponentList.PostHSFormat = + ServerConfiguration.GetOrUpdateSetting( + "maps.enablePostHSMultiComponentFormat", + true + ); // OSI Client Patch 7.0.9.0 + } + + public static void RegisterMap( + int mapIndex, int mapID, int fileIndex, int width, int height, int season, + string name, MapRules rules + ) + { + var newMap = new Map(mapID, mapIndex, fileIndex, width, height, season, name, rules); + + Map.Maps[mapIndex] = newMap; + Map.AllMaps.Add(newMap); + } } - - public static void RegisterMap(int mapIndex, int mapID, int fileIndex, int width, int height, int season, - string name, MapRules rules) - { - Map newMap = new Map(mapID, mapIndex, fileIndex, width, height, season, name, rules); - - Map.Maps[mapIndex] = newMap; - Map.AllMaps.Add(newMap); - } - } } diff --git a/Projects/UOContent/Misc/MapUO.cs b/Projects/UOContent/Misc/MapUO.cs index 5430ef42a..d471135dc 100644 --- a/Projects/UOContent/Misc/MapUO.cs +++ b/Projects/UOContent/Misc/MapUO.cs @@ -5,126 +5,128 @@ using Server.Network; namespace Server.Misc { - public static class MapUO - { - public static void Initialize() + public static class MapUO { - if (Settings.PartyTrack) - ProtocolExtensions.Register(0x00, true, OnPartyTrack); - - if (Settings.GuildTrack) - ProtocolExtensions.Register(0x01, true, OnGuildTrack); - } - - private static void OnPartyTrack(NetState state, PacketReader pvSrc) - { - Mobile from = state.Mobile; - Party party = Party.Get(from); - - if (party != null) - { - Packets.PartyTrack packet = new Packets.PartyTrack(from, party); - - if (packet.Stream.Length > 8) - state.Send(packet); - } - } - - private static void OnGuildTrack(NetState state, PacketReader pvSrc) - { - Mobile from = state.Mobile; - - if (from.Guild is Guild guild) - { - bool locations = pvSrc.ReadByte() != 0; - - Packets.GuildTrack packet = new Packets.GuildTrack(from, guild, locations); - - if (packet.Stream.Length > (locations ? 9 : 5)) - state.Send(packet); - } - else - { - state.Send(new Packets.GuildTrack()); - } - } - - private static class Settings - { - public const bool PartyTrack = true; - public const bool GuildTrack = true; - public const bool GuildHitsPercent = true; - } - - private static class Packets - { - public sealed class PartyTrack : ProtocolExtension - { - public PartyTrack(Mobile from, Party party) : base(0x01, (party.Members.Count - 1) * 9 + 4) + public static void Initialize() { - for (int i = 0; i < party.Members.Count; ++i) - { - PartyMemberInfo pmi = party.Members[i]; + if (Settings.PartyTrack) + ProtocolExtensions.Register(0x00, true, OnPartyTrack); - if (pmi == null || pmi.Mobile == from) - continue; - - Mobile mob = pmi.Mobile; - - if (Utility.InUpdateRange(from, mob) && from.CanSee(mob)) - continue; - - Stream.Write(mob.Serial); - Stream.Write((short)mob.X); - Stream.Write((short)mob.Y); - Stream.Write((byte)(mob.Map?.MapID ?? 0)); - } - - Stream.Write(0); - } - } - - public sealed class GuildTrack : ProtocolExtension - { - public GuildTrack() : base(0x02, 5) - { - Stream.Write((byte)0); - Stream.Write(0); + if (Settings.GuildTrack) + ProtocolExtensions.Register(0x01, true, OnGuildTrack); } - public GuildTrack(Mobile from, Guild guild, bool locations) : base(0x02, - (guild.Members.Count - 1) * (locations ? 10 : 4) + 5) + private static void OnPartyTrack(NetState state, PacketReader pvSrc) { - Stream.Write((byte)(locations ? 1 : 0)); + var from = state.Mobile; + var party = Party.Get(from); - for (int i = 0; i < guild.Members.Count; ++i) - { - Mobile mob = guild.Members[i]; - - if (mob == null || mob == from || mob.NetState == null) - continue; - - if (locations && Utility.InUpdateRange(from, mob) && from.CanSee(mob)) - continue; - - Stream.Write(mob.Serial); - - if (locations) + if (party != null) { - Stream.Write((short)mob.X); - Stream.Write((short)mob.Y); - Stream.Write((byte)(mob.Map?.MapID ?? 0)); + var packet = new Packets.PartyTrack(from, party); - if (Settings.GuildHitsPercent && mob.Alive) - Stream.Write((byte)(mob.Hits / Math.Max(mob.HitsMax, 1.0) * 100)); - else - Stream.Write((byte)0); + if (packet.Stream.Length > 8) + state.Send(packet); + } + } + + private static void OnGuildTrack(NetState state, PacketReader pvSrc) + { + var from = state.Mobile; + + if (from.Guild is Guild guild) + { + var locations = pvSrc.ReadByte() != 0; + + var packet = new Packets.GuildTrack(from, guild, locations); + + if (packet.Stream.Length > (locations ? 9 : 5)) + state.Send(packet); + } + else + { + state.Send(new Packets.GuildTrack()); + } + } + + private static class Settings + { + public const bool PartyTrack = true; + public const bool GuildTrack = true; + public const bool GuildHitsPercent = true; + } + + private static class Packets + { + public sealed class PartyTrack : ProtocolExtension + { + public PartyTrack(Mobile from, Party party) : base(0x01, (party.Members.Count - 1) * 9 + 4) + { + for (var i = 0; i < party.Members.Count; ++i) + { + var pmi = party.Members[i]; + + if (pmi == null || pmi.Mobile == from) + continue; + + var mob = pmi.Mobile; + + if (Utility.InUpdateRange(from, mob) && from.CanSee(mob)) + continue; + + Stream.Write(mob.Serial); + Stream.Write((short)mob.X); + Stream.Write((short)mob.Y); + Stream.Write((byte)(mob.Map?.MapID ?? 0)); + } + + Stream.Write(0); + } + } + + public sealed class GuildTrack : ProtocolExtension + { + public GuildTrack() : base(0x02, 5) + { + Stream.Write((byte)0); + Stream.Write(0); + } + + public GuildTrack(Mobile from, Guild guild, bool locations) : base( + 0x02, + (guild.Members.Count - 1) * (locations ? 10 : 4) + 5 + ) + { + Stream.Write((byte)(locations ? 1 : 0)); + + for (var i = 0; i < guild.Members.Count; ++i) + { + var mob = guild.Members[i]; + + if (mob == null || mob == from || mob.NetState == null) + continue; + + if (locations && Utility.InUpdateRange(from, mob) && from.CanSee(mob)) + continue; + + Stream.Write(mob.Serial); + + if (locations) + { + Stream.Write((short)mob.X); + Stream.Write((short)mob.Y); + Stream.Write((byte)(mob.Map?.MapID ?? 0)); + + if (Settings.GuildHitsPercent && mob.Alive) + Stream.Write((byte)(mob.Hits / Math.Max(mob.HitsMax, 1.0) * 100)); + else + Stream.Write((byte)0); + } + } + + Stream.Write(0); + } } - } - - Stream.Write(0); } - } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Misc/MondainsLegacy.cs b/Projects/UOContent/Misc/MondainsLegacy.cs index fb9c7b070..a05b6a1b5 100644 --- a/Projects/UOContent/Misc/MondainsLegacy.cs +++ b/Projects/UOContent/Misc/MondainsLegacy.cs @@ -5,73 +5,75 @@ using Server.Utilities; namespace Server { - public static class MondainsLegacy - { - public static Type[] Artifacts { get; } = + public static class MondainsLegacy { - typeof(AegisOfGrace), typeof(BladeDance), typeof(BloodwoodSpirit), typeof(Bonesmasher), - typeof(Boomstick), typeof(BrightsightLenses), typeof(FeyLeggings), typeof(FleshRipper), - typeof(HelmOfSwiftness), typeof(PadsOfTheCuSidhe), typeof(QuiverOfRage), typeof(QuiverOfElements), - typeof(RaedsGlory), typeof(RighteousAnger), typeof(RobeOfTheEclipse), typeof(RobeOfTheEquinox), - typeof(SoulSeeker), typeof(TalonBite), typeof(TotemOfVoid), typeof(WildfireBow), - typeof(Windsong) - }; + public static Type[] Artifacts { get; } = + { + typeof(AegisOfGrace), typeof(BladeDance), typeof(BloodwoodSpirit), typeof(Bonesmasher), + typeof(Boomstick), typeof(BrightsightLenses), typeof(FeyLeggings), typeof(FleshRipper), + typeof(HelmOfSwiftness), typeof(PadsOfTheCuSidhe), typeof(QuiverOfRage), typeof(QuiverOfElements), + typeof(RaedsGlory), typeof(RighteousAnger), typeof(RobeOfTheEclipse), typeof(RobeOfTheEquinox), + typeof(SoulSeeker), typeof(TalonBite), typeof(TotemOfVoid), typeof(WildfireBow), + typeof(Windsong) + }; - public static bool CheckArtifactChance(Mobile m, BaseCreature bc) - { - if (!Core.ML) - return false; + public static bool CheckArtifactChance(Mobile m, BaseCreature bc) + { + if (!Core.ML) + return false; - return Paragon.CheckArtifactChance(m, bc); + return Paragon.CheckArtifactChance(m, bc); + } + + public static void GiveArtifactTo(Mobile m) + { + if (!(ActivatorUtil.CreateInstance(Artifacts.RandomElement()) is Item item)) + return; + + if (m.AddToBackpack(item)) + { + m.SendLocalizedMessage(1072223); // An item has been placed in your backpack. + m.SendLocalizedMessage( + 1062317 + ); // For your valor in combating the fallen beast, a special artifact has been bestowed on you. + } + else if (m.BankBox.TryDropItem(m, item, false)) + { + m.SendLocalizedMessage(1072224); // An item has been placed in your bank box. + m.SendLocalizedMessage( + 1062317 + ); // For your valor in combating the fallen beast, a special artifact has been bestowed on you. + } + else + { + // Item was placed at feet by m.AddToBackpack + m.SendLocalizedMessage(1072523); // You find an artifact, but your backpack and bank are too full to hold it. + } + } + + public static bool CheckML(Mobile from, bool message = true) + { + if (from?.NetState == null) + return false; + + if (from.NetState.SupportsExpansion(Expansion.ML)) + return true; + + if (message) + from.SendLocalizedMessage(1072791); // You must upgrade to Mondain's Legacy in order to use that item. + + return false; + } + + public static bool IsMLRegion(Region region) => + region.IsPartOf("Twisted Weald") + || region.IsPartOf("Sanctuary") + || region.IsPartOf("The Prism of Light") + || region.IsPartOf("The Citadel") + || region.IsPartOf("Bedlam") + || region.IsPartOf("Blighted Grove") + || region.IsPartOf("The Painted Caves") + || region.IsPartOf("The Palace of Paroxysmus") + || region.IsPartOf("Labyrinth"); } - - public static void GiveArtifactTo(Mobile m) - { - if (!(ActivatorUtil.CreateInstance(Artifacts.RandomElement()) is Item item)) - return; - - if (m.AddToBackpack(item)) - { - m.SendLocalizedMessage(1072223); // An item has been placed in your backpack. - m.SendLocalizedMessage( - 1062317); // For your valor in combating the fallen beast, a special artifact has been bestowed on you. - } - else if (m.BankBox.TryDropItem(m, item, false)) - { - m.SendLocalizedMessage(1072224); // An item has been placed in your bank box. - m.SendLocalizedMessage( - 1062317); // For your valor in combating the fallen beast, a special artifact has been bestowed on you. - } - else - { - // Item was placed at feet by m.AddToBackpack - m.SendLocalizedMessage(1072523); // You find an artifact, but your backpack and bank are too full to hold it. - } - } - - public static bool CheckML(Mobile from, bool message = true) - { - if (from?.NetState == null) - return false; - - if (from.NetState.SupportsExpansion(Expansion.ML)) - return true; - - if (message) - from.SendLocalizedMessage(1072791); // You must upgrade to Mondain's Legacy in order to use that item. - - return false; - } - - public static bool IsMLRegion(Region region) => - region.IsPartOf("Twisted Weald") - || region.IsPartOf("Sanctuary") - || region.IsPartOf("The Prism of Light") - || region.IsPartOf("The Citadel") - || region.IsPartOf("Bedlam") - || region.IsPartOf("Blighted Grove") - || region.IsPartOf("The Painted Caves") - || region.IsPartOf("The Palace of Paroxysmus") - || region.IsPartOf("Labyrinth"); - } } diff --git a/Projects/UOContent/Misc/NameList.cs b/Projects/UOContent/Misc/NameList.cs index 931b8fbe9..c5ac07925 100644 --- a/Projects/UOContent/Misc/NameList.cs +++ b/Projects/UOContent/Misc/NameList.cs @@ -6,52 +6,51 @@ using Server.Json; namespace Server { - public class NameList - { - [JsonPropertyName("type")] - public string Type { get; set; } - - [JsonPropertyName("names")] - public string[] List { get; set; } - - public bool ContainsName(string name) + public class NameList { - for (int i = 0; i < List.Length; i++) - if (name == List[i]) - return true; + private static readonly Dictionary m_Table = + new Dictionary(StringComparer.OrdinalIgnoreCase); - return false; + [JsonPropertyName("type")] public string Type { get; set; } + + [JsonPropertyName("names")] public string[] List { get; set; } + + public bool ContainsName(string name) + { + for (var i = 0; i < List.Length; i++) + if (name == List[i]) + return true; + + return false; + } + + public string GetRandomName() => List.RandomElement() ?? ""; + + public static NameList GetNameList(string type) + { + m_Table.TryGetValue(type, out var n); + return n; + } + + public static string RandomName(string type) => GetNameList(type)?.GetRandomName() ?? ""; + + public static void Configure() + { + // TODO: Turn this into a command so it can be updated in-game + var filePath = Path.Combine(Core.BaseDirectory, "Data/names.json"); + + var nameLists = JsonConfig.Deserialize>(filePath); + foreach (var nameList in nameLists) + { + nameList.FixNames(); + m_Table.Add(nameList.Type, nameList); + } + } + + private void FixNames() + { + for (var i = 0; i < List.Length; i++) + List[i] = Utility.Intern(List[i].Trim()); + } } - - public string GetRandomName() => List.RandomElement() ?? ""; - - public static NameList GetNameList(string type) - { - m_Table.TryGetValue(type, out NameList n); - return n; - } - - public static string RandomName(string type) => GetNameList(type)?.GetRandomName() ?? ""; - - private static readonly Dictionary m_Table = new Dictionary(StringComparer.OrdinalIgnoreCase); - - public static void Configure() - { - // TODO: Turn this into a command so it can be updated in-game - string filePath = Path.Combine(Core.BaseDirectory, "Data/names.json"); - - List nameLists = JsonConfig.Deserialize>(filePath); - foreach (var nameList in nameLists) - { - nameList.FixNames(); - m_Table.Add(nameList.Type, nameList); - } - } - - private void FixNames() - { - for (int i = 0; i < List.Length; i++) - List[i] = Utility.Intern(List[i].Trim()); - } - } } diff --git a/Projects/UOContent/Misc/NameVerification.cs b/Projects/UOContent/Misc/NameVerification.cs index 41594c252..ca6d278cc 100644 --- a/Projects/UOContent/Misc/NameVerification.cs +++ b/Projects/UOContent/Misc/NameVerification.cs @@ -1,198 +1,214 @@ +using System; + namespace Server.Misc { - public class NameVerification - { - public static readonly char[] SpaceDashPeriodQuote = + public class NameVerification { - ' ', '-', '.', '\'' - }; - - public static readonly char[] Empty = System.Array.Empty(); - - public static string[] StartDisallowed { get; } = - { - "seer", - "counselor", - "gm", - "admin", - "lady", - "lord" - }; - - public static string[] Disallowed { get; } = - { - "jigaboo", - "chigaboo", - "wop", - "kyke", - "kike", - "tit", - "spic", - "prick", - "piss", - "lezbo", - "lesbo", - "felatio", - "dyke", - "dildo", - "chinc", - "chink", - "cunnilingus", - "cum", - "cocksucker", - "cock", - "clitoris", - "clit", - "ass", - "hitler", - "penis", - "nigga", - "nigger", - "klit", - "kunt", - "jiz", - "jism", - "jerkoff", - "jackoff", - "goddamn", - "fag", - "blowjob", - "bitch", - "asshole", - "dick", - "pussy", - "snatch", - "cunt", - "twat", - "shit", - "fuck", - "tailor", - "smith", - "scholar", - "rogue", - "novice", - "neophyte", - "merchant", - "medium", - "master", - "mage", - "lb", - "journeyman", - "grandmaster", - "fisherman", - "expert", - "chef", - "carpenter", - "british", - "blackthorne", - "blackthorn", - "beggar", - "archer", - "apprentice", - "adept", - "gamemaster", - "frozen", - "squelched", - "invulnerable", - "osi", - "origin" - }; - - public static void Initialize() - { - CommandSystem.Register("ValidateName", AccessLevel.Administrator, ValidateName_OnCommand); - } - - [Usage("ValidateName")] - [Description("Checks the result of NameValidation on the specified name.")] - public static void ValidateName_OnCommand(CommandEventArgs e) - { - if (Validate(e.ArgString, 2, 16, true, false, true, 1, SpaceDashPeriodQuote)) - e.Mobile.SendMessage(0x59, "That name is considered valid."); - else - e.Mobile.SendMessage(0x22, "That name is considered invalid."); - } - - public static bool Validate(string name, int minLength, int maxLength, bool allowLetters, bool allowDigits, - bool noExceptionsAtStart, int maxExceptions, char[] exceptions) => - Validate(name, minLength, maxLength, allowLetters, allowDigits, noExceptionsAtStart, maxExceptions, - exceptions, Disallowed, StartDisallowed); - - public static bool Validate(string name, int minLength, int maxLength, bool allowLetters, bool allowDigits, - bool noExceptionsAtStart, int maxExceptions, char[] exceptions, string[] disallowed, string[] startDisallowed) - { - if (name == null || name.Length < minLength || name.Length > maxLength) - return false; - - int exceptCount = 0; - - name = name.ToLower(); - - if (!allowLetters || !allowDigits || - (exceptions.Length > 0 && (noExceptionsAtStart || maxExceptions < int.MaxValue))) - for (int i = 0; i < name.Length; ++i) + public static readonly char[] SpaceDashPeriodQuote = { - char c = name[i]; + ' ', '-', '.', '\'' + }; - if (c >= 'a' && c <= 'z') - { - if (!allowLetters) - return false; + public static readonly char[] Empty = Array.Empty(); - exceptCount = 0; - } - else if (c >= '0' && c <= '9') - { - if (!allowDigits) - return false; + public static string[] StartDisallowed { get; } = + { + "seer", + "counselor", + "gm", + "admin", + "lady", + "lord" + }; - exceptCount = 0; - } - else - { - bool except = false; + public static string[] Disallowed { get; } = + { + "jigaboo", + "chigaboo", + "wop", + "kyke", + "kike", + "tit", + "spic", + "prick", + "piss", + "lezbo", + "lesbo", + "felatio", + "dyke", + "dildo", + "chinc", + "chink", + "cunnilingus", + "cum", + "cocksucker", + "cock", + "clitoris", + "clit", + "ass", + "hitler", + "penis", + "nigga", + "nigger", + "klit", + "kunt", + "jiz", + "jism", + "jerkoff", + "jackoff", + "goddamn", + "fag", + "blowjob", + "bitch", + "asshole", + "dick", + "pussy", + "snatch", + "cunt", + "twat", + "shit", + "fuck", + "tailor", + "smith", + "scholar", + "rogue", + "novice", + "neophyte", + "merchant", + "medium", + "master", + "mage", + "lb", + "journeyman", + "grandmaster", + "fisherman", + "expert", + "chef", + "carpenter", + "british", + "blackthorne", + "blackthorn", + "beggar", + "archer", + "apprentice", + "adept", + "gamemaster", + "frozen", + "squelched", + "invulnerable", + "osi", + "origin" + }; - for (int j = 0; !except && j < exceptions.Length; ++j) - if (c == exceptions[j]) - except = true; - - if (!except || (i == 0 && noExceptionsAtStart)) - return false; - - if (exceptCount++ == maxExceptions) - return false; - } + public static void Initialize() + { + CommandSystem.Register("ValidateName", AccessLevel.Administrator, ValidateName_OnCommand); } - for (int i = 0; i < disallowed.Length; ++i) - { - int indexOf = name.IndexOf(disallowed[i]); + [Usage("ValidateName")] + [Description("Checks the result of NameValidation on the specified name.")] + public static void ValidateName_OnCommand(CommandEventArgs e) + { + if (Validate(e.ArgString, 2, 16, true, false, true, 1, SpaceDashPeriodQuote)) + e.Mobile.SendMessage(0x59, "That name is considered valid."); + else + e.Mobile.SendMessage(0x22, "That name is considered invalid."); + } - if (indexOf == -1) - continue; + public static bool Validate( + string name, int minLength, int maxLength, bool allowLetters, bool allowDigits, + bool noExceptionsAtStart, int maxExceptions, char[] exceptions + ) => + Validate( + name, + minLength, + maxLength, + allowLetters, + allowDigits, + noExceptionsAtStart, + maxExceptions, + exceptions, + Disallowed, + StartDisallowed + ); - bool badPrefix = indexOf == 0; + public static bool Validate( + string name, int minLength, int maxLength, bool allowLetters, bool allowDigits, + bool noExceptionsAtStart, int maxExceptions, char[] exceptions, string[] disallowed, string[] startDisallowed + ) + { + if (name == null || name.Length < minLength || name.Length > maxLength) + return false; - for (int j = 0; !badPrefix && j < exceptions.Length; ++j) - badPrefix = name[indexOf - 1] == exceptions[j]; + var exceptCount = 0; - if (!badPrefix) - continue; + name = name.ToLower(); - bool badSuffix = indexOf + disallowed[i].Length >= name.Length; + if (!allowLetters || !allowDigits || + exceptions.Length > 0 && (noExceptionsAtStart || maxExceptions < int.MaxValue)) + for (var i = 0; i < name.Length; ++i) + { + var c = name[i]; - for (int j = 0; !badSuffix && j < exceptions.Length; ++j) - badSuffix = name[indexOf + disallowed[i].Length] == exceptions[j]; + if (c >= 'a' && c <= 'z') + { + if (!allowLetters) + return false; - if (badSuffix) - return false; - } + exceptCount = 0; + } + else if (c >= '0' && c <= '9') + { + if (!allowDigits) + return false; - for (int i = 0; i < startDisallowed.Length; ++i) - if (name.StartsWith(startDisallowed[i])) - return false; + exceptCount = 0; + } + else + { + var except = false; - return true; + for (var j = 0; !except && j < exceptions.Length; ++j) + if (c == exceptions[j]) + except = true; + + if (!except || i == 0 && noExceptionsAtStart) + return false; + + if (exceptCount++ == maxExceptions) + return false; + } + } + + for (var i = 0; i < disallowed.Length; ++i) + { + var indexOf = name.IndexOf(disallowed[i]); + + if (indexOf == -1) + continue; + + var badPrefix = indexOf == 0; + + for (var j = 0; !badPrefix && j < exceptions.Length; ++j) + badPrefix = name[indexOf - 1] == exceptions[j]; + + if (!badPrefix) + continue; + + var badSuffix = indexOf + disallowed[i].Length >= name.Length; + + for (var j = 0; !badSuffix && j < exceptions.Length; ++j) + badSuffix = name[indexOf + disallowed[i].Length] == exceptions[j]; + + if (badSuffix) + return false; + } + + for (var i = 0; i < startDisallowed.Length; ++i) + if (name.StartsWith(startDisallowed[i])) + return false; + + return true; + } } - } } diff --git a/Projects/UOContent/Misc/Notoriety.cs b/Projects/UOContent/Misc/Notoriety.cs index eb7d5c3f5..e4ee30d27 100644 --- a/Projects/UOContent/Misc/Notoriety.cs +++ b/Projects/UOContent/Misc/Notoriety.cs @@ -12,433 +12,434 @@ using Server.Spells.Seventh; namespace Server.Misc { - public class NotorietyHandlers - { - public static void Initialize() + public class NotorietyHandlers { - Notoriety.Hues[Notoriety.Innocent] = 0x59; - Notoriety.Hues[Notoriety.Ally] = 0x3F; - Notoriety.Hues[Notoriety.CanBeAttacked] = 0x3B2; - Notoriety.Hues[Notoriety.Criminal] = 0x3B2; - Notoriety.Hues[Notoriety.Enemy] = 0x90; - Notoriety.Hues[Notoriety.Murderer] = 0x22; - Notoriety.Hues[Notoriety.Invulnerable] = 0x35; - - Notoriety.Handler = MobileNotoriety; - - Mobile.AllowBeneficialHandler = Mobile_AllowBeneficial; - Mobile.AllowHarmfulHandler = Mobile_AllowHarmful; - } - - private static GuildStatus GetGuildStatus(Mobile m) - { - if (m.Guild == null) - return GuildStatus.None; - if (((Guild)m.Guild).Enemies.Count == 0 && m.Guild.Type == GuildType.Regular) - return GuildStatus.Peaceful; - - return GuildStatus.Waring; - } - - private static bool CheckBeneficialStatus(GuildStatus from, GuildStatus target) - { - if (from == GuildStatus.Waring || target == GuildStatus.Waring) - return false; - - return true; - } - - /*private static bool CheckHarmfulStatus( GuildStatus from, GuildStatus target ) - { - if (from == GuildStatus.Waring && target == GuildStatus.Waring) - return true; - - return false; - }*/ - - public static bool Mobile_AllowBeneficial(Mobile from, Mobile target) - { - if (from == null || target == null || from.AccessLevel > AccessLevel.Player || - target.AccessLevel > AccessLevel.Player) - return true; - - PlayerMobile pmFrom = from as PlayerMobile; - PlayerMobile pmTarg = target as PlayerMobile; - - if (pmFrom == null && from is BaseCreature bcFrom && bcFrom.Summoned) - pmFrom = bcFrom.SummonMaster as PlayerMobile; - - if (pmTarg == null && target is BaseCreature bcTarg && bcTarg.Summoned) - pmTarg = bcTarg.SummonMaster as PlayerMobile; - - if (pmFrom != null && pmTarg != null) - { - if (pmFrom.DuelContext != pmTarg.DuelContext && - (pmFrom.DuelContext?.Started == true || pmTarg.DuelContext?.Started == true)) - return false; - - if (pmFrom.DuelContext != null && pmFrom.DuelContext == pmTarg.DuelContext && - ((pmFrom.DuelContext.StartedReadyCountdown && !pmFrom.DuelContext.Started) || pmFrom.DuelContext.Tied || - pmFrom.DuelPlayer.Eliminated || pmTarg.DuelPlayer.Eliminated)) - return false; - - if (pmFrom.DuelPlayer?.Eliminated == false && pmFrom.DuelContext?.IsSuddenDeath == true) - return false; - - if (pmFrom.DuelContext != null && pmFrom.DuelContext == pmTarg.DuelContext && - pmFrom.DuelContext.m_Tournament?.IsNotoRestricted == true && - pmFrom.DuelPlayer != null && pmTarg.DuelPlayer != null && - pmFrom.DuelPlayer.Participant != pmTarg.DuelPlayer.Participant) - return false; - - if (pmFrom.DuelContext?.Started == true && pmFrom.DuelContext == pmTarg.DuelContext) - return true; - } - - if (pmFrom?.DuelContext?.Started == true || pmTarg?.DuelContext?.Started == true) - return false; - - if (from.Region.IsPartOf() || target.Region.IsPartOf()) - return false; - - Map map = from.Map; - - Faction targetFaction = Faction.Find(target, true); - - if ((!Core.ML || map == Faction.Facet) && targetFaction != null) - if (Faction.Find(from, true) != targetFaction) - return false; - - if ((map?.Rules & MapRules.BeneficialRestrictions) == 0) - return true; // In felucca, anything goes - - if (!from.Player) - return true; // NPCs have no restrictions - - if (target is BaseCreature creature && !creature.Controlled) - return false; // Players cannot heal uncontrolled mobiles - - if (pmFrom?.Young == true || pmTarg?.Young == true) - return false; // Young players cannot perform beneficial actions towards older players - - if (from.Guild is Guild fromGuild && target.Guild is Guild targetGuild && - (targetGuild == fromGuild || fromGuild.IsAlly(targetGuild))) - return true; // Guild members can be beneficial - - return CheckBeneficialStatus(GetGuildStatus(from), GetGuildStatus(target)); - } - - public static bool Mobile_AllowHarmful(Mobile from, Mobile target) - { - if (from == null || target == null || from.AccessLevel > AccessLevel.Player || - target.AccessLevel > AccessLevel.Player) - return true; - - PlayerMobile pmFrom = from as PlayerMobile; - PlayerMobile pmTarg = target as PlayerMobile; - BaseCreature bcTarg = target as BaseCreature; - - if (pmFrom == null && from is BaseCreature bcFrom && bcFrom.Summoned) - pmFrom = bcFrom.SummonMaster as PlayerMobile; - - if (pmTarg == null && bcTarg?.Summoned == true) - pmTarg = bcTarg.SummonMaster as PlayerMobile; - - if (pmFrom != null && pmTarg != null) - { - if (pmFrom.DuelContext != pmTarg.DuelContext && - (pmFrom.DuelContext?.Started == true || pmTarg.DuelContext?.Started == true)) - return false; - - if (pmFrom.DuelContext != null && pmFrom.DuelContext == pmTarg.DuelContext && - ((pmFrom.DuelContext.StartedReadyCountdown && !pmFrom.DuelContext.Started) || pmFrom.DuelContext.Tied || - pmFrom.DuelPlayer.Eliminated || pmTarg.DuelPlayer.Eliminated)) - return false; - - if (pmFrom.DuelContext != null && pmFrom.DuelContext == pmTarg.DuelContext && - pmFrom.DuelContext.m_Tournament?.IsNotoRestricted == true && - pmFrom.DuelPlayer != null && pmTarg.DuelPlayer != null && - pmFrom.DuelPlayer.Participant == pmTarg.DuelPlayer.Participant) - return false; - - if (pmFrom.DuelContext?.Started == true && pmFrom.DuelContext == pmTarg.DuelContext) - return true; - } - - if (pmFrom?.DuelContext?.Started == true || pmTarg?.DuelContext?.Started == true) - return false; - - if (from.Region.IsPartOf() || target.Region.IsPartOf()) - return false; - - Map map = from.Map; - - if ((map?.Rules & MapRules.HarmfulRestrictions) == 0) - return true; // In felucca, anything goes - - if (!from.Player && !(from is BaseCreature bc && bc.GetMaster() != null && - bc.GetMaster().AccessLevel == AccessLevel.Player)) - { - if (!CheckAggressor(from.Aggressors, target) && !CheckAggressed(from.Aggressed, target) && - pmTarg?.CheckYoungProtection(from) == true) - return false; - - return true; // Uncontrolled NPCs are only restricted by the young system - } - - Guild fromGuild = GetGuildFor(from.Guild as Guild, from); - Guild targetGuild = GetGuildFor(target.Guild as Guild, target); - - if (fromGuild != null && targetGuild != null && - (fromGuild == targetGuild || fromGuild.IsAlly(targetGuild) || fromGuild.IsEnemy(targetGuild))) - return true; // Guild allies or enemies can be harmful - - if (bcTarg?.Controlled == true || (bcTarg?.Summoned == true && bcTarg?.SummonMaster != from)) - return false; // Cannot harm other controlled mobiles - - if (target.Player) - return false; // Cannot harm other players - - return bcTarg?.InitialInnocent == true || Notoriety.Compute(from, target) != Notoriety.Innocent; - } - - public static Guild GetGuildFor(Guild def, Mobile m) - { - Guild g = def; - - if (m is BaseCreature c && c.Controlled && c.ControlMaster != null) - { - c.DisplayGuildTitle = false; - - if (c.Map != Map.Internal && (Core.AOS || Guild.NewGuildSystem || c.ControlOrder == OrderType.Attack || - c.ControlOrder == OrderType.Guard)) - g = (Guild)(c.Guild = c.ControlMaster.Guild); - else if (c.Map == Map.Internal || c.ControlMaster.Guild == null) - g = (Guild)(c.Guild = null); - } - - return g; - } - - public static int CorpseNotoriety(Mobile source, Corpse target) - { - if (target.AccessLevel > AccessLevel.Player) - return Notoriety.CanBeAttacked; - - Body body = target.Amount; - - Guild sourceGuild = GetGuildFor(source.Guild as Guild, source); - Guild targetGuild = GetGuildFor(target.Guild, target.Owner); - - Faction srcFaction = Faction.Find(source, true, true); - Faction trgFaction = Faction.Find(target.Owner, true, true); - List list = target.Aggressors; - - if (sourceGuild != null && targetGuild != null) - { - if (sourceGuild == targetGuild || sourceGuild.IsAlly(targetGuild)) - return Notoriety.Ally; - if (sourceGuild.IsEnemy(targetGuild)) - return Notoriety.Enemy; - } - - if (target.Owner is BaseCreature creature) - { - if (srcFaction != null && trgFaction != null && srcFaction != trgFaction && source.Map == Faction.Facet) - return Notoriety.Enemy; - - if (CheckHouseFlag(source, creature, target.Location, target.Map)) - return Notoriety.CanBeAttacked; - - int actual = Notoriety.CanBeAttacked; - - if (target.Kills >= 5 || (body.IsMonster && IsSummoned(creature)) || creature.AlwaysMurderer || - creature.IsAnimatedDead) - actual = Notoriety.Murderer; - - if (DateTime.UtcNow >= target.TimeOfDeath + Corpse.MonsterLootRightSacrifice) - return actual; - - Party sourceParty = Party.Get(source); - - for (int i = 0; i < list.Count; ++i) - if (list[i] == source || (sourceParty != null && Party.Get(list[i]) == sourceParty)) - return actual; - - return Notoriety.Innocent; - } - - if (target.Kills >= 5 || body.IsMonster) - return Notoriety.Murderer; - - if (target.Criminal && target.Map != null && (target.Map.Rules & MapRules.HarmfulRestrictions) == 0) - return Notoriety.Criminal; - - if (srcFaction != null && trgFaction != null && srcFaction != trgFaction && source.Map == Faction.Facet) - for (int i = 0; i < list.Count; ++i) - if (list[i] == source || list[i] is BaseFactionGuard) - return Notoriety.Enemy; - - if (CheckHouseFlag(source, target.Owner, target.Location, target.Map)) - return Notoriety.CanBeAttacked; - - if (!(target.Owner is PlayerMobile)) - return Notoriety.CanBeAttacked; - - for (int i = 0; i < list.Count; ++i) - if (list[i] == source) - return Notoriety.CanBeAttacked; - - return Notoriety.Innocent; - } - - /* Must be thread-safe */ - public static int MobileNotoriety(Mobile source, Mobile target) - { - BaseCreature bcTarg = target as BaseCreature; - - if (Core.AOS && (target.Blessed || bcTarg?.IsInvulnerable == true || target is PlayerVendor || - target is TownCrier)) - return Notoriety.Invulnerable; - - PlayerMobile pmFrom = source as PlayerMobile; - PlayerMobile pmTarg = target as PlayerMobile; - - if (pmFrom != null && pmTarg != null) - if (pmFrom.DuelContext?.StartedBeginCountdown == true && !pmFrom.DuelContext.Finished && pmFrom.DuelContext == pmTarg.DuelContext) - return pmFrom.DuelContext.IsAlly(pmFrom, pmTarg) ? Notoriety.Ally : Notoriety.Enemy; - - if (target.AccessLevel > AccessLevel.Player) - return Notoriety.CanBeAttacked; - - if (source.Player && !target.Player && pmFrom != null && bcTarg != null) - { - Mobile master = bcTarg.GetMaster(); - - if (master?.AccessLevel > AccessLevel.Player) - return Notoriety.CanBeAttacked; - - master = bcTarg.ControlMaster; - - if (Core.ML && master != null) + public static void Initialize() { - if ((source == master && CheckAggressor(bcTarg.Aggressors, source)) || - CheckAggressor(source.Aggressors, bcTarg)) - return Notoriety.CanBeAttacked; + Notoriety.Hues[Notoriety.Innocent] = 0x59; + Notoriety.Hues[Notoriety.Ally] = 0x3F; + Notoriety.Hues[Notoriety.CanBeAttacked] = 0x3B2; + Notoriety.Hues[Notoriety.Criminal] = 0x3B2; + Notoriety.Hues[Notoriety.Enemy] = 0x90; + Notoriety.Hues[Notoriety.Murderer] = 0x22; + Notoriety.Hues[Notoriety.Invulnerable] = 0x35; - return MobileNotoriety(source, master); + Notoriety.Handler = MobileNotoriety; + + Mobile.AllowBeneficialHandler = Mobile_AllowBeneficial; + Mobile.AllowHarmfulHandler = Mobile_AllowHarmful; } - if (!bcTarg.Summoned && !bcTarg.Controlled && pmFrom.EnemyOfOneType == bcTarg.GetType()) - return Notoriety.Enemy; - } + private static GuildStatus GetGuildStatus(Mobile m) + { + if (m.Guild == null) + return GuildStatus.None; + if (((Guild)m.Guild).Enemies.Count == 0 && m.Guild.Type == GuildType.Regular) + return GuildStatus.Peaceful; - if (target.Kills >= 5 || - (target.Body.IsMonster && IsSummoned(bcTarg) && !(target is BaseFamiliar) && !(target is ArcaneFey) && - !(target is Golem)) || bcTarg?.AlwaysMurderer == true || bcTarg?.IsAnimatedDead == true) - return Notoriety.Murderer; + return GuildStatus.Waring; + } - if (target.Criminal) - return Notoriety.Criminal; + private static bool CheckBeneficialStatus(GuildStatus from, GuildStatus target) + { + if (from == GuildStatus.Waring || target == GuildStatus.Waring) + return false; - Guild sourceGuild = GetGuildFor(source.Guild as Guild, source); - Guild targetGuild = GetGuildFor(target.Guild as Guild, target); + return true; + } - if (sourceGuild != null && targetGuild != null) - { - if (sourceGuild == targetGuild || sourceGuild.IsAlly(targetGuild)) - return Notoriety.Ally; - if (sourceGuild.IsEnemy(targetGuild)) - return Notoriety.Enemy; - } + /*private static bool CheckHarmfulStatus( GuildStatus from, GuildStatus target ) + { + if (from == GuildStatus.Waring && target == GuildStatus.Waring) + return true; + + return false; + }*/ - Faction srcFaction = Faction.Find(source, true, true); - Faction trgFaction = Faction.Find(target, true, true); + public static bool Mobile_AllowBeneficial(Mobile from, Mobile target) + { + if (from == null || target == null || from.AccessLevel > AccessLevel.Player || + target.AccessLevel > AccessLevel.Player) + return true; - if (srcFaction != null && trgFaction != null && srcFaction != trgFaction && source.Map == Faction.Facet) - return Notoriety.Enemy; + var pmFrom = from as PlayerMobile; + var pmTarg = target as PlayerMobile; - if (Stealing.ClassicMode && pmTarg?.PermaFlags.Contains(source) == true) - return Notoriety.CanBeAttacked; + if (pmFrom == null && from is BaseCreature bcFrom && bcFrom.Summoned) + pmFrom = bcFrom.SummonMaster as PlayerMobile; - if (bcTarg?.AlwaysAttackable == true) - return Notoriety.CanBeAttacked; + if (pmTarg == null && target is BaseCreature bcTarg && bcTarg.Summoned) + pmTarg = bcTarg.SummonMaster as PlayerMobile; - if (CheckHouseFlag(source, target, target.Location, target.Map)) - return Notoriety.CanBeAttacked; + if (pmFrom != null && pmTarg != null) + { + if (pmFrom.DuelContext != pmTarg.DuelContext && + (pmFrom.DuelContext?.Started == true || pmTarg.DuelContext?.Started == true)) + return false; - if (bcTarg?.InitialInnocent != true) - if ((!target.Body.IsHuman && !target.Body.IsGhost && !IsPet(bcTarg) && pmTarg == null) || - (!Core.ML && !target.CanBeginAction())) - return Notoriety.CanBeAttacked; + if (pmFrom.DuelContext != null && pmFrom.DuelContext == pmTarg.DuelContext && + (pmFrom.DuelContext.StartedReadyCountdown && !pmFrom.DuelContext.Started || pmFrom.DuelContext.Tied || + pmFrom.DuelPlayer.Eliminated || pmTarg.DuelPlayer.Eliminated)) + return false; - if (CheckAggressor(source.Aggressors, target)) - return Notoriety.CanBeAttacked; + if (pmFrom.DuelPlayer?.Eliminated == false && pmFrom.DuelContext?.IsSuddenDeath == true) + return false; - if (CheckAggressed(source.Aggressed, target)) - return Notoriety.CanBeAttacked; + if (pmFrom.DuelContext != null && pmFrom.DuelContext == pmTarg.DuelContext && + pmFrom.DuelContext.m_Tournament?.IsNotoRestricted == true && + pmFrom.DuelPlayer != null && pmTarg.DuelPlayer != null && + pmFrom.DuelPlayer.Participant != pmTarg.DuelPlayer.Participant) + return false; - if (bcTarg?.Controlled == true && bcTarg.ControlOrder == OrderType.Guard && - bcTarg.ControlTarget == source) - return Notoriety.CanBeAttacked; + if (pmFrom.DuelContext?.Started == true && pmFrom.DuelContext == pmTarg.DuelContext) + return true; + } - if (source is BaseCreature bc) - { - Mobile master = bc.GetMaster(); + if (pmFrom?.DuelContext?.Started == true || pmTarg?.DuelContext?.Started == true) + return false; - if (master != null && (CheckAggressor(master.Aggressors, target) || - MobileNotoriety(master, target) == Notoriety.CanBeAttacked || bcTarg != null)) - return Notoriety.CanBeAttacked; - } + if (from.Region.IsPartOf() || target.Region.IsPartOf()) + return false; - return Notoriety.Innocent; + var map = from.Map; + + var targetFaction = Faction.Find(target, true); + + if ((!Core.ML || map == Faction.Facet) && targetFaction != null) + if (Faction.Find(from, true) != targetFaction) + return false; + + if ((map?.Rules & MapRules.BeneficialRestrictions) == 0) + return true; // In felucca, anything goes + + if (!from.Player) + return true; // NPCs have no restrictions + + if (target is BaseCreature creature && !creature.Controlled) + return false; // Players cannot heal uncontrolled mobiles + + if (pmFrom?.Young == true || pmTarg?.Young == true) + return false; // Young players cannot perform beneficial actions towards older players + + if (from.Guild is Guild fromGuild && target.Guild is Guild targetGuild && + (targetGuild == fromGuild || fromGuild.IsAlly(targetGuild))) + return true; // Guild members can be beneficial + + return CheckBeneficialStatus(GetGuildStatus(from), GetGuildStatus(target)); + } + + public static bool Mobile_AllowHarmful(Mobile from, Mobile target) + { + if (from == null || target == null || from.AccessLevel > AccessLevel.Player || + target.AccessLevel > AccessLevel.Player) + return true; + + var pmFrom = from as PlayerMobile; + var pmTarg = target as PlayerMobile; + var bcTarg = target as BaseCreature; + + if (pmFrom == null && from is BaseCreature bcFrom && bcFrom.Summoned) + pmFrom = bcFrom.SummonMaster as PlayerMobile; + + if (pmTarg == null && bcTarg?.Summoned == true) + pmTarg = bcTarg.SummonMaster as PlayerMobile; + + if (pmFrom != null && pmTarg != null) + { + if (pmFrom.DuelContext != pmTarg.DuelContext && + (pmFrom.DuelContext?.Started == true || pmTarg.DuelContext?.Started == true)) + return false; + + if (pmFrom.DuelContext != null && pmFrom.DuelContext == pmTarg.DuelContext && + (pmFrom.DuelContext.StartedReadyCountdown && !pmFrom.DuelContext.Started || pmFrom.DuelContext.Tied || + pmFrom.DuelPlayer.Eliminated || pmTarg.DuelPlayer.Eliminated)) + return false; + + if (pmFrom.DuelContext != null && pmFrom.DuelContext == pmTarg.DuelContext && + pmFrom.DuelContext.m_Tournament?.IsNotoRestricted == true && + pmFrom.DuelPlayer != null && pmTarg.DuelPlayer != null && + pmFrom.DuelPlayer.Participant == pmTarg.DuelPlayer.Participant) + return false; + + if (pmFrom.DuelContext?.Started == true && pmFrom.DuelContext == pmTarg.DuelContext) + return true; + } + + if (pmFrom?.DuelContext?.Started == true || pmTarg?.DuelContext?.Started == true) + return false; + + if (from.Region.IsPartOf() || target.Region.IsPartOf()) + return false; + + var map = from.Map; + + if ((map?.Rules & MapRules.HarmfulRestrictions) == 0) + return true; // In felucca, anything goes + + if (!from.Player && !(from is BaseCreature bc && bc.GetMaster() != null && + bc.GetMaster().AccessLevel == AccessLevel.Player)) + { + if (!CheckAggressor(from.Aggressors, target) && !CheckAggressed(from.Aggressed, target) && + pmTarg?.CheckYoungProtection(from) == true) + return false; + + return true; // Uncontrolled NPCs are only restricted by the young system + } + + var fromGuild = GetGuildFor(from.Guild as Guild, from); + var targetGuild = GetGuildFor(target.Guild as Guild, target); + + if (fromGuild != null && targetGuild != null && + (fromGuild == targetGuild || fromGuild.IsAlly(targetGuild) || fromGuild.IsEnemy(targetGuild))) + return true; // Guild allies or enemies can be harmful + + if (bcTarg?.Controlled == true || bcTarg?.Summoned == true && bcTarg?.SummonMaster != @from) + return false; // Cannot harm other controlled mobiles + + if (target.Player) + return false; // Cannot harm other players + + return bcTarg?.InitialInnocent == true || Notoriety.Compute(from, target) != Notoriety.Innocent; + } + + public static Guild GetGuildFor(Guild def, Mobile m) + { + var g = def; + + if (m is BaseCreature c && c.Controlled && c.ControlMaster != null) + { + c.DisplayGuildTitle = false; + + if (c.Map != Map.Internal && (Core.AOS || Guild.NewGuildSystem || c.ControlOrder == OrderType.Attack || + c.ControlOrder == OrderType.Guard)) + g = (Guild)(c.Guild = c.ControlMaster.Guild); + else if (c.Map == Map.Internal || c.ControlMaster.Guild == null) + g = (Guild)(c.Guild = null); + } + + return g; + } + + public static int CorpseNotoriety(Mobile source, Corpse target) + { + if (target.AccessLevel > AccessLevel.Player) + return Notoriety.CanBeAttacked; + + Body body = target.Amount; + + var sourceGuild = GetGuildFor(source.Guild as Guild, source); + var targetGuild = GetGuildFor(target.Guild, target.Owner); + + var srcFaction = Faction.Find(source, true, true); + var trgFaction = Faction.Find(target.Owner, true, true); + var list = target.Aggressors; + + if (sourceGuild != null && targetGuild != null) + { + if (sourceGuild == targetGuild || sourceGuild.IsAlly(targetGuild)) + return Notoriety.Ally; + if (sourceGuild.IsEnemy(targetGuild)) + return Notoriety.Enemy; + } + + if (target.Owner is BaseCreature creature) + { + if (srcFaction != null && trgFaction != null && srcFaction != trgFaction && source.Map == Faction.Facet) + return Notoriety.Enemy; + + if (CheckHouseFlag(source, creature, target.Location, target.Map)) + return Notoriety.CanBeAttacked; + + var actual = Notoriety.CanBeAttacked; + + if (target.Kills >= 5 || body.IsMonster && IsSummoned(creature) || creature.AlwaysMurderer || + creature.IsAnimatedDead) + actual = Notoriety.Murderer; + + if (DateTime.UtcNow >= target.TimeOfDeath + Corpse.MonsterLootRightSacrifice) + return actual; + + var sourceParty = Party.Get(source); + + for (var i = 0; i < list.Count; ++i) + if (list[i] == source || sourceParty != null && Party.Get(list[i]) == sourceParty) + return actual; + + return Notoriety.Innocent; + } + + if (target.Kills >= 5 || body.IsMonster) + return Notoriety.Murderer; + + if (target.Criminal && target.Map != null && (target.Map.Rules & MapRules.HarmfulRestrictions) == 0) + return Notoriety.Criminal; + + if (srcFaction != null && trgFaction != null && srcFaction != trgFaction && source.Map == Faction.Facet) + for (var i = 0; i < list.Count; ++i) + if (list[i] == source || list[i] is BaseFactionGuard) + return Notoriety.Enemy; + + if (CheckHouseFlag(source, target.Owner, target.Location, target.Map)) + return Notoriety.CanBeAttacked; + + if (!(target.Owner is PlayerMobile)) + return Notoriety.CanBeAttacked; + + for (var i = 0; i < list.Count; ++i) + if (list[i] == source) + return Notoriety.CanBeAttacked; + + return Notoriety.Innocent; + } + + /* Must be thread-safe */ + public static int MobileNotoriety(Mobile source, Mobile target) + { + var bcTarg = target as BaseCreature; + + if (Core.AOS && (target.Blessed || bcTarg?.IsInvulnerable == true || target is PlayerVendor || + target is TownCrier)) + return Notoriety.Invulnerable; + + var pmFrom = source as PlayerMobile; + var pmTarg = target as PlayerMobile; + + if (pmFrom != null && pmTarg != null) + if (pmFrom.DuelContext?.StartedBeginCountdown == true && !pmFrom.DuelContext.Finished && + pmFrom.DuelContext == pmTarg.DuelContext) + return pmFrom.DuelContext.IsAlly(pmFrom, pmTarg) ? Notoriety.Ally : Notoriety.Enemy; + + if (target.AccessLevel > AccessLevel.Player) + return Notoriety.CanBeAttacked; + + if (source.Player && !target.Player && pmFrom != null && bcTarg != null) + { + var master = bcTarg.GetMaster(); + + if (master?.AccessLevel > AccessLevel.Player) + return Notoriety.CanBeAttacked; + + master = bcTarg.ControlMaster; + + if (Core.ML && master != null) + { + if (source == master && CheckAggressor(bcTarg.Aggressors, source) || + CheckAggressor(source.Aggressors, bcTarg)) + return Notoriety.CanBeAttacked; + + return MobileNotoriety(source, master); + } + + if (!bcTarg.Summoned && !bcTarg.Controlled && pmFrom.EnemyOfOneType == bcTarg.GetType()) + return Notoriety.Enemy; + } + + if (target.Kills >= 5 || + target.Body.IsMonster && IsSummoned(bcTarg) && !(target is BaseFamiliar) && !(target is ArcaneFey) && + !(target is Golem) || bcTarg?.AlwaysMurderer == true || bcTarg?.IsAnimatedDead == true) + return Notoriety.Murderer; + + if (target.Criminal) + return Notoriety.Criminal; + + var sourceGuild = GetGuildFor(source.Guild as Guild, source); + var targetGuild = GetGuildFor(target.Guild as Guild, target); + + if (sourceGuild != null && targetGuild != null) + { + if (sourceGuild == targetGuild || sourceGuild.IsAlly(targetGuild)) + return Notoriety.Ally; + if (sourceGuild.IsEnemy(targetGuild)) + return Notoriety.Enemy; + } + + var srcFaction = Faction.Find(source, true, true); + var trgFaction = Faction.Find(target, true, true); + + if (srcFaction != null && trgFaction != null && srcFaction != trgFaction && source.Map == Faction.Facet) + return Notoriety.Enemy; + + if (Stealing.ClassicMode && pmTarg?.PermaFlags.Contains(source) == true) + return Notoriety.CanBeAttacked; + + if (bcTarg?.AlwaysAttackable == true) + return Notoriety.CanBeAttacked; + + if (CheckHouseFlag(source, target, target.Location, target.Map)) + return Notoriety.CanBeAttacked; + + if (bcTarg?.InitialInnocent != true) + if (!target.Body.IsHuman && !target.Body.IsGhost && !IsPet(bcTarg) && pmTarg == null || + !Core.ML && !target.CanBeginAction()) + return Notoriety.CanBeAttacked; + + if (CheckAggressor(source.Aggressors, target)) + return Notoriety.CanBeAttacked; + + if (CheckAggressed(source.Aggressed, target)) + return Notoriety.CanBeAttacked; + + if (bcTarg?.Controlled == true && bcTarg.ControlOrder == OrderType.Guard && + bcTarg.ControlTarget == source) + return Notoriety.CanBeAttacked; + + if (source is BaseCreature bc) + { + var master = bc.GetMaster(); + + if (master != null && (CheckAggressor(master.Aggressors, target) || + MobileNotoriety(master, target) == Notoriety.CanBeAttacked || bcTarg != null)) + return Notoriety.CanBeAttacked; + } + + return Notoriety.Innocent; + } + + public static bool CheckHouseFlag(Mobile from, Mobile m, Point3D p, Map map) + { + var house = BaseHouse.FindHouseAt(p, map, 16); + + if (house?.Public != false || !house.IsFriend(from)) + return false; + + if (m != null && house.IsFriend(m)) + return false; + + return !(m is BaseCreature c) || c.Deleted || !c.Controlled || c.ControlMaster == null || + !house.IsFriend(c.ControlMaster); + } + + public static bool IsPet(BaseCreature c) => c?.Controlled == true; + + public static bool IsSummoned(BaseCreature c) => c?.Summoned == true; + + public static bool CheckAggressor(List list, Mobile target) + { + for (var i = 0; i < list.Count; ++i) + if (list[i].Attacker == target) + return true; + + return false; + } + + public static bool CheckAggressed(List list, Mobile target) + { + for (var i = 0; i < list.Count; ++i) + { + var info = list[i]; + + if (!info.CriminalAggression && info.Defender == target) + return true; + } + + return false; + } + + private enum GuildStatus + { + None, + Peaceful, + Waring + } } - - public static bool CheckHouseFlag(Mobile from, Mobile m, Point3D p, Map map) - { - BaseHouse house = BaseHouse.FindHouseAt(p, map, 16); - - if (house?.Public != false || !house.IsFriend(from)) - return false; - - if (m != null && house.IsFriend(m)) - return false; - - return !(m is BaseCreature c) || c.Deleted || !c.Controlled || c.ControlMaster == null || - !house.IsFriend(c.ControlMaster); - } - - public static bool IsPet(BaseCreature c) => c?.Controlled == true; - - public static bool IsSummoned(BaseCreature c) => c?.Summoned == true; - - public static bool CheckAggressor(List list, Mobile target) - { - for (int i = 0; i < list.Count; ++i) - if (list[i].Attacker == target) - return true; - - return false; - } - - public static bool CheckAggressed(List list, Mobile target) - { - for (int i = 0; i < list.Count; ++i) - { - AggressorInfo info = list[i]; - - if (!info.CriminalAggression && info.Defender == target) - return true; - } - - return false; - } - - private enum GuildStatus - { - None, - Peaceful, - Waring - } - } } diff --git a/Projects/UOContent/Misc/Paperdoll.cs b/Projects/UOContent/Misc/Paperdoll.cs index 0770a5ced..81b634332 100644 --- a/Projects/UOContent/Misc/Paperdoll.cs +++ b/Projects/UOContent/Misc/Paperdoll.cs @@ -1,30 +1,35 @@ -using System.Collections.Generic; using Server.Network; namespace Server.Misc { - public static class Paperdoll - { - public static void Initialize() + public static class Paperdoll { - EventSink.PaperdollRequest += EventSink_PaperdollRequest; + public static void Initialize() + { + EventSink.PaperdollRequest += EventSink_PaperdollRequest; + } + + public static void EventSink_PaperdollRequest(Mobile beholder, Mobile beheld) + { + beholder.Send( + new DisplayPaperdoll( + beheld.Serial, + Titles.ComputeTitle(beholder, beheld), + beheld.Warmode, + beheld.AllowEquipFrom(beholder) + ) + ); + + if (ObjectPropertyList.Enabled) + { + var items = beheld.Items; + + for (var i = 0; i < items.Count; ++i) + beholder.Send(items[i].OPLPacket); + + // NOTE: OSI sends MobileUpdate when opening your own paperdoll. + // It has a very bad rubber-banding affect. What positive affects does it have? + } + } } - - public static void EventSink_PaperdollRequest(Mobile beholder, Mobile beheld) - { - beholder.Send(new DisplayPaperdoll(beheld.Serial, Titles.ComputeTitle(beholder, beheld), - beheld.Warmode, beheld.AllowEquipFrom(beholder))); - - if (ObjectPropertyList.Enabled) - { - List items = beheld.Items; - - for (int i = 0; i < items.Count; ++i) - beholder.Send(items[i].OPLPacket); - - // NOTE: OSI sends MobileUpdate when opening your own paperdoll. - // It has a very bad rubber-banding affect. What positive affects does it have? - } - } - } } diff --git a/Projects/UOContent/Misc/Poison.cs b/Projects/UOContent/Misc/Poison.cs index d72c84583..1fa2605b4 100644 --- a/Projects/UOContent/Misc/Poison.cs +++ b/Projects/UOContent/Misc/Poison.cs @@ -8,144 +8,155 @@ using Server.Spells.Ninjitsu; namespace Server { - public class PoisonImpl : Poison - { - private readonly int m_Count; - private readonly int m_MessageInterval; - - // Timers - private readonly TimeSpan m_Delay; - private readonly TimeSpan m_Interval; - - // Info - - // Damage - private readonly int m_Minimum; - private readonly int m_Maximum; - private readonly double m_Scalar; - - public PoisonImpl(string name, int level, int min, int max, double percent, double delay, double interval, int count, - int messageInterval) + public class PoisonImpl : Poison { - Name = name; - Level = level; - m_Minimum = min; - m_Maximum = max; - m_Scalar = percent * 0.01; - m_Delay = TimeSpan.FromSeconds(delay); - m_Interval = TimeSpan.FromSeconds(interval); - m_Count = count; - m_MessageInterval = messageInterval; - } + private readonly int m_Count; - public override string Name { get; } + // Timers + private readonly TimeSpan m_Delay; + private readonly TimeSpan m_Interval; + private readonly int m_Maximum; + private readonly int m_MessageInterval; - public override int Level { get; } + // Info - [CallPriority(10)] - public static void Configure() - { - if (Core.AOS) - { - Register(new PoisonImpl("Lesser", 0, 4, 16, 7.5, 3.0, 2.25, 10, 4)); - Register(new PoisonImpl("Regular", 1, 8, 18, 10.0, 3.0, 3.25, 10, 3)); - Register(new PoisonImpl("Greater", 2, 12, 20, 15.0, 3.0, 4.25, 10, 2)); - Register(new PoisonImpl("Deadly", 3, 16, 30, 30.0, 3.0, 5.25, 15, 2)); - Register(new PoisonImpl("Lethal", 4, 20, 50, 35.0, 3.0, 5.25, 20, 2)); - } - else - { - Register(new PoisonImpl("Lesser", 0, 4, 26, 2.500, 3.5, 3.0, 10, 2)); - Register(new PoisonImpl("Regular", 1, 5, 26, 3.125, 3.5, 3.0, 10, 2)); - Register(new PoisonImpl("Greater", 2, 6, 26, 6.250, 3.5, 3.0, 10, 2)); - Register(new PoisonImpl("Deadly", 3, 7, 26, 12.500, 3.5, 4.0, 10, 2)); - Register(new PoisonImpl("Lethal", 4, 9, 26, 25.000, 3.5, 5.0, 10, 2)); - } - } + // Damage + private readonly int m_Minimum; + private readonly double m_Scalar; - public static Poison IncreaseLevel(Poison oldPoison) - { - Poison newPoison = oldPoison == null ? null : GetPoison(oldPoison.Level + 1); - - return newPoison ?? oldPoison; - } - - public override Timer ConstructTimer(Mobile m) => new PoisonTimer(m, this); - - public class PoisonTimer : Timer - { - private int m_Index; - private int m_LastDamage; - private readonly Mobile m_Mobile; - private readonly PoisonImpl m_Poison; - - public PoisonTimer(Mobile m, PoisonImpl p) : base(p.m_Delay, p.m_Interval) - { - From = m; - m_Mobile = m; - m_Poison = p; - } - - public Mobile From { get; set; } - - protected override void OnTick() - { - if ((Core.AOS && m_Poison.Level < 4 && - TransformationSpellHelper.UnderTransformation(m_Mobile, typeof(VampiricEmbraceSpell))) || - (m_Poison.Level < 3 && OrangePetals.UnderEffect(m_Mobile)) || - AnimalForm.UnderTransformation(m_Mobile, typeof(Unicorn))) - if (m_Mobile.CurePoison(m_Mobile)) - { - m_Mobile.LocalOverheadMessage(MessageType.Emote, 0x3F, true, - "* You feel yourself resisting the effects of the poison *"); - - m_Mobile.NonlocalOverheadMessage(MessageType.Emote, 0x3F, true, - $"* {m_Mobile.Name} seems resistant to the poison *"); - - Stop(); - return; - } - - if (m_Index++ == m_Poison.m_Count) + public PoisonImpl( + string name, int level, int min, int max, double percent, double delay, double interval, int count, + int messageInterval + ) { - m_Mobile.SendLocalizedMessage(502136); // The poison seems to have worn off. - m_Mobile.Poison = null; - - Stop(); - return; + Name = name; + Level = level; + m_Minimum = min; + m_Maximum = max; + m_Scalar = percent * 0.01; + m_Delay = TimeSpan.FromSeconds(delay); + m_Interval = TimeSpan.FromSeconds(interval); + m_Count = count; + m_MessageInterval = messageInterval; } - int damage; + public override string Name { get; } - if (!Core.AOS && m_LastDamage != 0 && Utility.RandomBool()) + public override int Level { get; } + + [CallPriority(10)] + public static void Configure() { - damage = m_LastDamage; - } - else - { - damage = 1 + (int)(m_Mobile.Hits * m_Poison.m_Scalar); - - if (damage < m_Poison.m_Minimum) - damage = m_Poison.m_Minimum; - else if (damage > m_Poison.m_Maximum) - damage = m_Poison.m_Maximum; - - m_LastDamage = damage; + if (Core.AOS) + { + Register(new PoisonImpl("Lesser", 0, 4, 16, 7.5, 3.0, 2.25, 10, 4)); + Register(new PoisonImpl("Regular", 1, 8, 18, 10.0, 3.0, 3.25, 10, 3)); + Register(new PoisonImpl("Greater", 2, 12, 20, 15.0, 3.0, 4.25, 10, 2)); + Register(new PoisonImpl("Deadly", 3, 16, 30, 30.0, 3.0, 5.25, 15, 2)); + Register(new PoisonImpl("Lethal", 4, 20, 50, 35.0, 3.0, 5.25, 20, 2)); + } + else + { + Register(new PoisonImpl("Lesser", 0, 4, 26, 2.500, 3.5, 3.0, 10, 2)); + Register(new PoisonImpl("Regular", 1, 5, 26, 3.125, 3.5, 3.0, 10, 2)); + Register(new PoisonImpl("Greater", 2, 6, 26, 6.250, 3.5, 3.0, 10, 2)); + Register(new PoisonImpl("Deadly", 3, 7, 26, 12.500, 3.5, 4.0, 10, 2)); + Register(new PoisonImpl("Lethal", 4, 9, 26, 25.000, 3.5, 5.0, 10, 2)); + } } - From?.DoHarmful(m_Mobile, true); + public static Poison IncreaseLevel(Poison oldPoison) + { + var newPoison = oldPoison == null ? null : GetPoison(oldPoison.Level + 1); - if (m_Mobile is IHonorTarget honorTarget) - honorTarget.ReceivedHonorContext?.OnTargetPoisoned(); + return newPoison ?? oldPoison; + } - AOS.Damage(m_Mobile, From, damage, 0, 0, 0, 100, 0); + public override Timer ConstructTimer(Mobile m) => new PoisonTimer(m, this); - if (Utility.RandomDouble() >= 0.60) // OSI: randomly revealed between first and third damage tick, guessing 60% chance - m_Mobile.RevealingAction(); + public class PoisonTimer : Timer + { + private readonly Mobile m_Mobile; + private readonly PoisonImpl m_Poison; + private int m_Index; + private int m_LastDamage; - if (m_Index % m_Poison.m_MessageInterval == 0) - m_Mobile.OnPoisoned(From, m_Poison, m_Poison); - } + public PoisonTimer(Mobile m, PoisonImpl p) : base(p.m_Delay, p.m_Interval) + { + From = m; + m_Mobile = m; + m_Poison = p; + } + + public Mobile From { get; set; } + + protected override void OnTick() + { + if (Core.AOS && m_Poison.Level < 4 && + TransformationSpellHelper.UnderTransformation(m_Mobile, typeof(VampiricEmbraceSpell)) || + m_Poison.Level < 3 && OrangePetals.UnderEffect(m_Mobile) || + AnimalForm.UnderTransformation(m_Mobile, typeof(Unicorn))) + if (m_Mobile.CurePoison(m_Mobile)) + { + m_Mobile.LocalOverheadMessage( + MessageType.Emote, + 0x3F, + true, + "* You feel yourself resisting the effects of the poison *" + ); + + m_Mobile.NonlocalOverheadMessage( + MessageType.Emote, + 0x3F, + true, + $"* {m_Mobile.Name} seems resistant to the poison *" + ); + + Stop(); + return; + } + + if (m_Index++ == m_Poison.m_Count) + { + m_Mobile.SendLocalizedMessage(502136); // The poison seems to have worn off. + m_Mobile.Poison = null; + + Stop(); + return; + } + + int damage; + + if (!Core.AOS && m_LastDamage != 0 && Utility.RandomBool()) + { + damage = m_LastDamage; + } + else + { + damage = 1 + (int)(m_Mobile.Hits * m_Poison.m_Scalar); + + if (damage < m_Poison.m_Minimum) + damage = m_Poison.m_Minimum; + else if (damage > m_Poison.m_Maximum) + damage = m_Poison.m_Maximum; + + m_LastDamage = damage; + } + + From?.DoHarmful(m_Mobile, true); + + if (m_Mobile is IHonorTarget honorTarget) + honorTarget.ReceivedHonorContext?.OnTargetPoisoned(); + + AOS.Damage(m_Mobile, From, damage, 0, 0, 0, 100, 0); + + if (Utility.RandomDouble() >= 0.60 + ) // OSI: randomly revealed between first and third damage tick, guessing 60% chance + m_Mobile.RevealingAction(); + + if (m_Index % m_Poison.m_MessageInterval == 0) + m_Mobile.OnPoisoned(From, m_Poison, m_Poison); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Misc/ProfanityProtection.cs b/Projects/UOContent/Misc/ProfanityProtection.cs index 13fbb4cb4..676d116eb 100644 --- a/Projects/UOContent/Misc/ProfanityProtection.cs +++ b/Projects/UOContent/Misc/ProfanityProtection.cs @@ -1,122 +1,132 @@ namespace Server.Misc { - public enum ProfanityAction - { - None, // no action taken - Disallow, // speech is not displayed - Criminal, // makes the player criminal, not killable by guards - CriminalAction, // makes the player criminal, can be killed by guards - Disconnect, // player is kicked - Other // some other implementation - } - - public static class ProfanityProtection - { - // TODO: Move this to configuration - private static readonly bool Enabled = false; - - private static readonly ProfanityAction - Action = ProfanityAction.Disallow; // change here what to do when profanity is detected - - public static char[] Exceptions { get; } = + public enum ProfanityAction { - ' ', '-', '.', '\'', '"', ',', '_', '+', '=', '~', '`', '!', '^', '*', '\\', '/', ';', ':', '<', '>', '[', ']', - '{', '}', '?', '|', '(', ')', '%', '$', '&', '#', '@' - }; - - public static string[] StartDisallowed { get; } = { }; - - public static string[] Disallowed { get; } = - { - "jigaboo", - "chigaboo", - "wop", - "kyke", - "kike", - "tit", - "spic", - "prick", - "piss", - "lezbo", - "lesbo", - "felatio", - "dyke", - "dildo", - "chinc", - "chink", - "cunnilingus", - "cum", - "cocksucker", - "cock", - "clitoris", - "clit", - "ass", - "hitler", - "penis", - "nigga", - "nigger", - "klit", - "kunt", - "jiz", - "jism", - "jerkoff", - "jackoff", - "goddamn", - "fag", - "blowjob", - "bitch", - "asshole", - "dick", - "pussy", - "snatch", - "cunt", - "twat", - "shit", - "fuck" - }; - - public static void Initialize() - { - if (Enabled) - EventSink.Speech += EventSink_Speech; + None, // no action taken + Disallow, // speech is not displayed + Criminal, // makes the player criminal, not killable by guards + CriminalAction, // makes the player criminal, can be killed by guards + Disconnect, // player is kicked + Other // some other implementation } - private static bool OnProfanityDetected(Mobile from, string speech) + public static class ProfanityProtection { - switch (Action) - { - case ProfanityAction.None: return true; - case ProfanityAction.Disallow: return false; - case ProfanityAction.Criminal: - from.Criminal = true; - return true; - case ProfanityAction.CriminalAction: - from.CriminalAction(false); - return true; - case ProfanityAction.Disconnect: - { - from.NetState?.Dispose(); + // TODO: Move this to configuration + private static readonly bool Enabled = false; - return false; - } - default: - case ProfanityAction.Other: // TODO: Provide custom implementation if this is chosen - { - return true; - } - } + private static readonly ProfanityAction + Action = ProfanityAction.Disallow; // change here what to do when profanity is detected + + public static char[] Exceptions { get; } = + { + ' ', '-', '.', '\'', '"', ',', '_', '+', '=', '~', '`', '!', '^', '*', '\\', '/', ';', ':', '<', '>', '[', ']', + '{', '}', '?', '|', '(', ')', '%', '$', '&', '#', '@' + }; + + public static string[] StartDisallowed { get; } = { }; + + public static string[] Disallowed { get; } = + { + "jigaboo", + "chigaboo", + "wop", + "kyke", + "kike", + "tit", + "spic", + "prick", + "piss", + "lezbo", + "lesbo", + "felatio", + "dyke", + "dildo", + "chinc", + "chink", + "cunnilingus", + "cum", + "cocksucker", + "cock", + "clitoris", + "clit", + "ass", + "hitler", + "penis", + "nigga", + "nigger", + "klit", + "kunt", + "jiz", + "jism", + "jerkoff", + "jackoff", + "goddamn", + "fag", + "blowjob", + "bitch", + "asshole", + "dick", + "pussy", + "snatch", + "cunt", + "twat", + "shit", + "fuck" + }; + + public static void Initialize() + { + if (Enabled) + EventSink.Speech += EventSink_Speech; + } + + private static bool OnProfanityDetected(Mobile from, string speech) + { + switch (Action) + { + case ProfanityAction.None: return true; + case ProfanityAction.Disallow: return false; + case ProfanityAction.Criminal: + from.Criminal = true; + return true; + case ProfanityAction.CriminalAction: + from.CriminalAction(false); + return true; + case ProfanityAction.Disconnect: + { + from.NetState?.Dispose(); + + return false; + } + default: + case ProfanityAction.Other: // TODO: Provide custom implementation if this is chosen + { + return true; + } + } + } + + private static void EventSink_Speech(SpeechEventArgs e) + { + var from = e.Mobile; + + if (from.AccessLevel > AccessLevel.Player) + return; + + if (!NameVerification.Validate( + e.Speech, + 0, + int.MaxValue, + true, + true, + false, + int.MaxValue, + Exceptions, + Disallowed, + StartDisallowed + )) + e.Blocked = !OnProfanityDetected(from, e.Speech); + } } - - private static void EventSink_Speech(SpeechEventArgs e) - { - Mobile from = e.Mobile; - - if (from.AccessLevel > AccessLevel.Player) - return; - - if (!NameVerification.Validate(e.Speech, 0, int.MaxValue, true, true, false, int.MaxValue, Exceptions, - Disallowed, StartDisallowed)) - e.Blocked = !OnProfanityDetected(from, e.Speech); - } - } } diff --git a/Projects/UOContent/Misc/Profile.cs b/Projects/UOContent/Misc/Profile.cs index c05a0b5e9..8df6b5e1f 100644 --- a/Projects/UOContent/Misc/Profile.cs +++ b/Projects/UOContent/Misc/Profile.cs @@ -4,83 +4,83 @@ using Server.Network; namespace Server.Misc { - public static class Profile - { - public static void Initialize() + public static class Profile { - EventSink.ProfileRequest += EventSink_ProfileRequest; - EventSink.ChangeProfileRequest += EventSink_ChangeProfileRequest; + public static void Initialize() + { + EventSink.ProfileRequest += EventSink_ProfileRequest; + EventSink.ChangeProfileRequest += EventSink_ChangeProfileRequest; + } + + public static void EventSink_ChangeProfileRequest(Mobile beholder, Mobile beheld, string text) + { + if (beholder.ProfileLocked) + beholder.SendMessage("Your profile is locked. You may not change it."); + else + beholder.Profile = text; + } + + public static void EventSink_ProfileRequest(Mobile beholder, Mobile beheld) + { + if (!beheld.Player) + return; + + if (beholder.Map != beheld.Map || !beholder.InRange(beheld, 12) || !beholder.CanSee(beheld)) + return; + + var header = Titles.ComputeTitle(beholder, beheld); + + var footer = ""; + + if (beheld.ProfileLocked) + { + if (beholder == beheld) + footer = "Your profile has been locked."; + else if (beholder.AccessLevel >= AccessLevel.Counselor) + footer = "This profile has been locked."; + } + + if (footer.Length == 0 && beholder == beheld) + footer = GetAccountDuration(beheld); + + var body = beheld.Profile ?? ""; + var serial = beholder != beheld || !beheld.ProfileLocked ? beheld.Serial : Serial.Zero; + + beholder.Send(new DisplayProfile(serial, header, body, footer)); + } + + private static string GetAccountDuration(Mobile m) + { + if (!(m.Account is Account a)) + return ""; + + var ts = DateTime.UtcNow - a.Created; + + if (Format(ts.TotalDays, "This account is {0} day{1} old.", out var v)) + return v; + + if (Format(ts.TotalHours, "This account is {0} hour{1} old.", out v)) + return v; + + if (Format(ts.TotalMinutes, "This account is {0} minute{1} old.", out v)) + return v; + + if (Format(ts.TotalSeconds, "This account is {0} second{1} old.", out v)) + return v; + + return ""; + } + + public static bool Format(double value, string format, out string op) + { + if (value >= 1.0) + { + op = string.Format(format, (int)value, (int)value != 1 ? "s" : ""); + return true; + } + + op = null; + return false; + } } - - public static void EventSink_ChangeProfileRequest(Mobile beholder, Mobile beheld, string text) - { - if (beholder.ProfileLocked) - beholder.SendMessage("Your profile is locked. You may not change it."); - else - beholder.Profile = text; - } - - public static void EventSink_ProfileRequest(Mobile beholder, Mobile beheld) - { - if (!beheld.Player) - return; - - if (beholder.Map != beheld.Map || !beholder.InRange(beheld, 12) || !beholder.CanSee(beheld)) - return; - - string header = Titles.ComputeTitle(beholder, beheld); - - string footer = ""; - - if (beheld.ProfileLocked) - { - if (beholder == beheld) - footer = "Your profile has been locked."; - else if (beholder.AccessLevel >= AccessLevel.Counselor) - footer = "This profile has been locked."; - } - - if (footer.Length == 0 && beholder == beheld) - footer = GetAccountDuration(beheld); - - string body = beheld.Profile ?? ""; - Serial serial = beholder != beheld || !beheld.ProfileLocked ? beheld.Serial : Serial.Zero; - - beholder.Send(new DisplayProfile(serial, header, body, footer)); - } - - private static string GetAccountDuration(Mobile m) - { - if (!(m.Account is Account a)) - return ""; - - TimeSpan ts = DateTime.UtcNow - a.Created; - - if (Format(ts.TotalDays, "This account is {0} day{1} old.", out string v)) - return v; - - if (Format(ts.TotalHours, "This account is {0} hour{1} old.", out v)) - return v; - - if (Format(ts.TotalMinutes, "This account is {0} minute{1} old.", out v)) - return v; - - if (Format(ts.TotalSeconds, "This account is {0} second{1} old.", out v)) - return v; - - return ""; - } - - public static bool Format(double value, string format, out string op) - { - if (value >= 1.0) - { - op = string.Format(format, (int)value, (int)value != 1 ? "s" : ""); - return true; - } - - op = null; - return false; - } - } } diff --git a/Projects/UOContent/Misc/ProtocolExtensions.cs b/Projects/UOContent/Misc/ProtocolExtensions.cs index 10f0ac82a..124ba0b81 100644 --- a/Projects/UOContent/Misc/ProtocolExtensions.cs +++ b/Projects/UOContent/Misc/ProtocolExtensions.cs @@ -3,62 +3,64 @@ using Server.Network; namespace Server.Misc { - public class ProtocolExtensions - { - private static readonly PacketHandler[] m_Handlers = new PacketHandler[0x100]; - - public static void Initialize() + public class ProtocolExtensions { - PacketHandlers.Register(0xF0, 0, false, DecodeBundledPacket); - } + private static readonly PacketHandler[] m_Handlers = new PacketHandler[0x100]; - public static void Register(int packetID, bool ingame, OnPacketReceive onReceive) - { - m_Handlers[packetID] = new PacketHandler(packetID, 0, ingame, onReceive); - } - - public static PacketHandler GetHandler(int packetID) - { - if (packetID >= 0 && packetID < m_Handlers.Length) - return m_Handlers[packetID]; - - return null; - } - - public static void DecodeBundledPacket(NetState state, PacketReader pvSrc) - { - int packetID = pvSrc.ReadByte(); - - PacketHandler ph = GetHandler(packetID); - - if (ph != null) - { - if (ph.Ingame && state.Mobile == null) + public static void Initialize() { - Console.WriteLine( - "Client: {0}: Sent ingame packet (0xF0x{1:X2}) before having been attached to a mobile", state, - packetID); - state.Dispose(); + PacketHandlers.Register(0xF0, 0, false, DecodeBundledPacket); } - else if (ph.Ingame && state.Mobile.Deleted) - { - state.Dispose(); - } - else - { - ph.OnReceive(state, pvSrc); - } - } - } - } - public abstract class ProtocolExtension : Packet - { - public ProtocolExtension(int packetID, int capacity) : base(0xF0) + public static void Register(int packetID, bool ingame, OnPacketReceive onReceive) + { + m_Handlers[packetID] = new PacketHandler(packetID, 0, ingame, onReceive); + } + + public static PacketHandler GetHandler(int packetID) + { + if (packetID >= 0 && packetID < m_Handlers.Length) + return m_Handlers[packetID]; + + return null; + } + + public static void DecodeBundledPacket(NetState state, PacketReader pvSrc) + { + int packetID = pvSrc.ReadByte(); + + var ph = GetHandler(packetID); + + if (ph != null) + { + if (ph.Ingame && state.Mobile == null) + { + Console.WriteLine( + "Client: {0}: Sent ingame packet (0xF0x{1:X2}) before having been attached to a mobile", + state, + packetID + ); + state.Dispose(); + } + else if (ph.Ingame && state.Mobile.Deleted) + { + state.Dispose(); + } + else + { + ph.OnReceive(state, pvSrc); + } + } + } + } + + public abstract class ProtocolExtension : Packet { - EnsureCapacity(4 + capacity); + public ProtocolExtension(int packetID, int capacity) : base(0xF0) + { + EnsureCapacity(4 + capacity); - Stream.Write((byte)packetID); + Stream.Write((byte)packetID); + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Misc/RaceDefinitions.cs b/Projects/UOContent/Misc/RaceDefinitions.cs index f2c7dafe5..8628d9de1 100644 --- a/Projects/UOContent/Misc/RaceDefinitions.cs +++ b/Projects/UOContent/Misc/RaceDefinitions.cs @@ -1,275 +1,277 @@ namespace Server.Misc { - public class RaceDefinitions - { - public static void Configure() + public class RaceDefinitions { - /* Here we configure all races. Some notes: - * - * 1) The first 32 races are reserved for core use. - * 2) Race 0x7F is reserved for core use. - * 3) Race 0xFF is reserved for core use. - * 4) Changing or removing any predefined races may cause server instability. - */ - - RegisterRace(new Human(0, 0)); - RegisterRace(new Elf(1, 1)); - RegisterRace(new Gargoyle(2, 2)); - } - - public static void RegisterRace(Race race) - { - Race.Races[race.RaceIndex] = race; - Race.AllRaces.Add(race); - } - - private class Human : Race - { - public Human(int raceID, int raceIndex) - : base(raceID, raceIndex, "Human", "Humans", 400, 401, 402, 403, Expansion.None) - { - } - - public override bool ValidateHair(bool female, int itemID) - { - if (itemID == 0) - return true; - - if ((female && itemID == 0x2048) || (!female && itemID == 0x2046)) - return false; // Buns & Receding Hair - - if (itemID >= 0x203B && itemID <= 0x203D) - return true; - - if (itemID >= 0x2044 && itemID <= 0x204A) - return true; - - return false; - } - - public override int RandomHair(bool female) // Random hair doesn't include baldness - { - return Utility.Random(9) switch + public static void Configure() { - 0 => 0x203B, // Short - 1 => 0x203C, // Long - 2 => 0x203D, // Pony Tail - 3 => 0x2044, // Mohawk - 4 => 0x2045, // Pageboy - 5 => 0x2047, // Afro - 6 => 0x2049, // Pig tails - 7 => 0x204A, // Krisna - _ => female ? 0x2046 : 0x2048 - }; - } + /* Here we configure all races. Some notes: + * + * 1) The first 32 races are reserved for core use. + * 2) Race 0x7F is reserved for core use. + * 3) Race 0xFF is reserved for core use. + * 4) Changing or removing any predefined races may cause server instability. + */ - public override bool ValidateFacialHair(bool female, int itemID) - { - if (itemID == 0) - return true; + RegisterRace(new Human(0, 0)); + RegisterRace(new Elf(1, 1)); + RegisterRace(new Gargoyle(2, 2)); + } - if (female) - return false; - - if (itemID >= 0x203E && itemID <= 0x2041) - return true; - - if (itemID >= 0x204B && itemID <= 0x204D) - return true; - - return false; - } - - public override int RandomFacialHair(bool female) - { - if (female) - return 0; - - int rand = Utility.Random(7); - - return (rand < 4 ? 0x203E : 0x2047) + rand; - } - - public override int ClipSkinHue(int hue) - { - if (hue < 1002) - return 1002; - if (hue > 1058) - return 1058; - return hue; - } - - public override int RandomSkinHue() => Utility.Random(1002, 57) | 0x8000; - - public override int ClipHairHue(int hue) - { - if (hue < 1102) - return 1102; - if (hue > 1149) - return 1149; - return hue; - } - - public override int RandomHairHue() => Utility.Random(1102, 48); - } - - private class Elf : Race - { - private static readonly int[] m_SkinHues = - { - 0x0BF, 0x24D, 0x24E, 0x24F, 0x353, 0x361, 0x367, 0x374, - 0x375, 0x376, 0x381, 0x382, 0x383, 0x384, 0x385, 0x389, - 0x3DE, 0x3E5, 0x3E6, 0x3E8, 0x3E9, 0x430, 0x4A7, 0x4DE, - 0x51D, 0x53F, 0x579, 0x76B, 0x76C, 0x76D, 0x835, 0x903 - }; - - private static readonly int[] m_HairHues = - { - 0x034, 0x035, 0x036, 0x037, 0x038, 0x039, 0x058, 0x08E, - 0x08F, 0x090, 0x091, 0x092, 0x101, 0x159, 0x15A, 0x15B, - 0x15C, 0x15D, 0x15E, 0x128, 0x12F, 0x1BD, 0x1E4, 0x1F3, - 0x207, 0x211, 0x239, 0x251, 0x26C, 0x2C3, 0x2C9, 0x31D, - 0x31E, 0x31F, 0x320, 0x321, 0x322, 0x323, 0x324, 0x325, - 0x326, 0x369, 0x386, 0x387, 0x388, 0x389, 0x38A, 0x59D, - 0x6B8, 0x725, 0x853 - }; - - public Elf(int raceID, int raceIndex) - : base(raceID, raceIndex, "Elf", "Elves", 605, 606, 607, 608, Expansion.ML) - { - } - - public override bool ValidateHair(bool female, int itemID) - { - if (itemID == 0) - return true; - - if ((female && (itemID == 0x2FCD || itemID == 0x2FBF)) || (!female && (itemID == 0x2FCC || itemID == 0x2FD0))) - return false; - - if (itemID >= 0x2FBF && itemID <= 0x2FC2) - return true; - - if (itemID >= 0x2FCC && itemID <= 0x2FD1) - return true; - - return false; - } - - public override int RandomHair(bool female) // Random hair doesn't include baldness - { - return Utility.Random(8) switch + public static void RegisterRace(Race race) { - 0 => 0x2FC0, // Long Feather - 1 => 0x2FC1, // Short - 2 => 0x2FC2, // Mullet - 3 => 0x2FCE, // Knob - 4 => 0x2FCF, // Braided - 5 => 0x2FD1, // Spiked - 6 => female ? 0x2FCC : 0x2FBF, // Flower or Mid-long - _ => female ? 0x2FD0 : 0x2FCD - }; - } + Race.Races[race.RaceIndex] = race; + Race.AllRaces.Add(race); + } - public override bool ValidateFacialHair(bool female, int itemID) => itemID == 0; - - public override int RandomFacialHair(bool female) => 0; - - public override int ClipSkinHue(int hue) - { - for (int i = 0; i < m_SkinHues.Length; i++) - if (m_SkinHues[i] == hue) - return hue; - - return m_SkinHues[0]; - } - - public override int RandomSkinHue() => m_SkinHues.RandomElement() | 0x8000; - - public override int ClipHairHue(int hue) - { - for (int i = 0; i < m_HairHues.Length; i++) - if (m_HairHues[i] == hue) - return hue; - - return m_HairHues[0]; - } - - public override int RandomHairHue() => m_HairHues.RandomElement(); - } - - private class Gargoyle : Race - { - // Todo Finish body hues - private static readonly int[] m_BodyHues = - { - 0x86DB, 0x86DC, 0x86DD, 0x86DE, - 0x86DF, 0x86E0, 0x86E1, 0x86E2, - 0x86E3, 0x86E4, 0x86E5, 0x86E6 - // 0x, 0x, 0x, 0x, // 86E7/86E8/86E9/86EA? - // 0x, 0x, 0x, 0x, // 86EB/86EC/86ED/86EE? - // 0x86F3, 0x86DB, 0x86DC, 0x86DD - }; - - private static readonly int[] m_HornHues = - { - 0x709, 0x70B, 0x70D, 0x70F, 0x711, 0x763, - 0x765, 0x768, 0x76B, 0x6F3, 0x6F1, 0x6EF, - 0x6E4, 0x6E2, 0x6E0, 0x709, 0x70B, 0x70D - }; - - public Gargoyle(int raceID, int raceIndex) - : base(raceID, raceIndex, "Gargoyle", "Gargoyles", 666, 667, 402, 403, Expansion.SA) - { - } - - public override bool ValidateHair(bool female, int itemID) - { - if (female == false) return itemID >= 0x4258 && itemID <= 0x425F; - - return itemID == 0x4261 || itemID == 0x4262 || (itemID >= 0x4273 && itemID <= 0x4275) || itemID == 0x42B0 || - itemID == 0x42B1 || itemID == 0x42AA || itemID == 0x42AB; - } - - public override int RandomHair(bool female) - { - if (Utility.Random(9) == 0) - return 0; - if (!female) - return 0x4258 + Utility.Random(8); - return Utility.Random(9) switch + private class Human : Race { - 0 => 0x4261, - 1 => 0x4262, - 2 => 0x4273, - 3 => 0x4274, - 4 => 0x4275, - 5 => 0x42B0, - 6 => 0x42B1, - 7 => 0x42AA, - 8 => 0x42AB, - _ => 0 - }; - } + public Human(int raceID, int raceIndex) + : base(raceID, raceIndex, "Human", "Humans", 400, 401, 402, 403, Expansion.None) + { + } - public override bool ValidateFacialHair(bool female, int itemID) => !female && itemID >= 0x42AD && itemID <= 0x42B0; + public override bool ValidateHair(bool female, int itemID) + { + if (itemID == 0) + return true; - public override int RandomFacialHair(bool female) => female ? 0 : Utility.RandomList(0, 0x42AD, 0x42AE, 0x42AF, 0x42B0); + if (female && itemID == 0x2048 || !female && itemID == 0x2046) + return false; // Buns & Receding Hair - public override int ClipSkinHue(int hue) => hue; + if (itemID >= 0x203B && itemID <= 0x203D) + return true; - public override int RandomSkinHue() => m_BodyHues.RandomElement() | 0x8000; + if (itemID >= 0x2044 && itemID <= 0x204A) + return true; - public override int ClipHairHue(int hue) - { - for (int i = 0; i < m_HornHues.Length; i++) - if (m_HornHues[i] == hue) - return hue; + return false; + } - return m_HornHues[0]; - } + public override int RandomHair(bool female) // Random hair doesn't include baldness + { + return Utility.Random(9) switch + { + 0 => 0x203B, // Short + 1 => 0x203C, // Long + 2 => 0x203D, // Pony Tail + 3 => 0x2044, // Mohawk + 4 => 0x2045, // Pageboy + 5 => 0x2047, // Afro + 6 => 0x2049, // Pig tails + 7 => 0x204A, // Krisna + _ => female ? 0x2046 : 0x2048 + }; + } - public override int RandomHairHue() => m_HornHues.RandomElement(); + public override bool ValidateFacialHair(bool female, int itemID) + { + if (itemID == 0) + return true; + + if (female) + return false; + + if (itemID >= 0x203E && itemID <= 0x2041) + return true; + + if (itemID >= 0x204B && itemID <= 0x204D) + return true; + + return false; + } + + public override int RandomFacialHair(bool female) + { + if (female) + return 0; + + var rand = Utility.Random(7); + + return (rand < 4 ? 0x203E : 0x2047) + rand; + } + + public override int ClipSkinHue(int hue) + { + if (hue < 1002) + return 1002; + if (hue > 1058) + return 1058; + return hue; + } + + public override int RandomSkinHue() => Utility.Random(1002, 57) | 0x8000; + + public override int ClipHairHue(int hue) + { + if (hue < 1102) + return 1102; + if (hue > 1149) + return 1149; + return hue; + } + + public override int RandomHairHue() => Utility.Random(1102, 48); + } + + private class Elf : Race + { + private static readonly int[] m_SkinHues = + { + 0x0BF, 0x24D, 0x24E, 0x24F, 0x353, 0x361, 0x367, 0x374, + 0x375, 0x376, 0x381, 0x382, 0x383, 0x384, 0x385, 0x389, + 0x3DE, 0x3E5, 0x3E6, 0x3E8, 0x3E9, 0x430, 0x4A7, 0x4DE, + 0x51D, 0x53F, 0x579, 0x76B, 0x76C, 0x76D, 0x835, 0x903 + }; + + private static readonly int[] m_HairHues = + { + 0x034, 0x035, 0x036, 0x037, 0x038, 0x039, 0x058, 0x08E, + 0x08F, 0x090, 0x091, 0x092, 0x101, 0x159, 0x15A, 0x15B, + 0x15C, 0x15D, 0x15E, 0x128, 0x12F, 0x1BD, 0x1E4, 0x1F3, + 0x207, 0x211, 0x239, 0x251, 0x26C, 0x2C3, 0x2C9, 0x31D, + 0x31E, 0x31F, 0x320, 0x321, 0x322, 0x323, 0x324, 0x325, + 0x326, 0x369, 0x386, 0x387, 0x388, 0x389, 0x38A, 0x59D, + 0x6B8, 0x725, 0x853 + }; + + public Elf(int raceID, int raceIndex) + : base(raceID, raceIndex, "Elf", "Elves", 605, 606, 607, 608, Expansion.ML) + { + } + + public override bool ValidateHair(bool female, int itemID) + { + if (itemID == 0) + return true; + + if (female && (itemID == 0x2FCD || itemID == 0x2FBF) || !female && (itemID == 0x2FCC || itemID == 0x2FD0)) + return false; + + if (itemID >= 0x2FBF && itemID <= 0x2FC2) + return true; + + if (itemID >= 0x2FCC && itemID <= 0x2FD1) + return true; + + return false; + } + + public override int RandomHair(bool female) // Random hair doesn't include baldness + { + return Utility.Random(8) switch + { + 0 => 0x2FC0, // Long Feather + 1 => 0x2FC1, // Short + 2 => 0x2FC2, // Mullet + 3 => 0x2FCE, // Knob + 4 => 0x2FCF, // Braided + 5 => 0x2FD1, // Spiked + 6 => female ? 0x2FCC : 0x2FBF, // Flower or Mid-long + _ => female ? 0x2FD0 : 0x2FCD + }; + } + + public override bool ValidateFacialHair(bool female, int itemID) => itemID == 0; + + public override int RandomFacialHair(bool female) => 0; + + public override int ClipSkinHue(int hue) + { + for (var i = 0; i < m_SkinHues.Length; i++) + if (m_SkinHues[i] == hue) + return hue; + + return m_SkinHues[0]; + } + + public override int RandomSkinHue() => m_SkinHues.RandomElement() | 0x8000; + + public override int ClipHairHue(int hue) + { + for (var i = 0; i < m_HairHues.Length; i++) + if (m_HairHues[i] == hue) + return hue; + + return m_HairHues[0]; + } + + public override int RandomHairHue() => m_HairHues.RandomElement(); + } + + private class Gargoyle : Race + { + // Todo Finish body hues + private static readonly int[] m_BodyHues = + { + 0x86DB, 0x86DC, 0x86DD, 0x86DE, + 0x86DF, 0x86E0, 0x86E1, 0x86E2, + 0x86E3, 0x86E4, 0x86E5, 0x86E6 + // 0x, 0x, 0x, 0x, // 86E7/86E8/86E9/86EA? + // 0x, 0x, 0x, 0x, // 86EB/86EC/86ED/86EE? + // 0x86F3, 0x86DB, 0x86DC, 0x86DD + }; + + private static readonly int[] m_HornHues = + { + 0x709, 0x70B, 0x70D, 0x70F, 0x711, 0x763, + 0x765, 0x768, 0x76B, 0x6F3, 0x6F1, 0x6EF, + 0x6E4, 0x6E2, 0x6E0, 0x709, 0x70B, 0x70D + }; + + public Gargoyle(int raceID, int raceIndex) + : base(raceID, raceIndex, "Gargoyle", "Gargoyles", 666, 667, 402, 403, Expansion.SA) + { + } + + public override bool ValidateHair(bool female, int itemID) + { + if (female == false) return itemID >= 0x4258 && itemID <= 0x425F; + + return itemID == 0x4261 || itemID == 0x4262 || itemID >= 0x4273 && itemID <= 0x4275 || itemID == 0x42B0 || + itemID == 0x42B1 || itemID == 0x42AA || itemID == 0x42AB; + } + + public override int RandomHair(bool female) + { + if (Utility.Random(9) == 0) + return 0; + if (!female) + return 0x4258 + Utility.Random(8); + return Utility.Random(9) switch + { + 0 => 0x4261, + 1 => 0x4262, + 2 => 0x4273, + 3 => 0x4274, + 4 => 0x4275, + 5 => 0x42B0, + 6 => 0x42B1, + 7 => 0x42AA, + 8 => 0x42AB, + _ => 0 + }; + } + + public override bool ValidateFacialHair(bool female, int itemID) => + !female && itemID >= 0x42AD && itemID <= 0x42B0; + + public override int RandomFacialHair(bool female) => + female ? 0 : Utility.RandomList(0, 0x42AD, 0x42AE, 0x42AF, 0x42B0); + + public override int ClipSkinHue(int hue) => hue; + + public override int RandomSkinHue() => m_BodyHues.RandomElement() | 0x8000; + + public override int ClipHairHue(int hue) + { + for (var i = 0; i < m_HornHues.Length; i++) + if (m_HornHues[i] == hue) + return hue; + + return m_HornHues[0]; + } + + public override int RandomHairHue() => m_HornHues.RandomElement(); + } } - } } diff --git a/Projects/UOContent/Misc/RegenRates.cs b/Projects/UOContent/Misc/RegenRates.cs index e58aea592..c1664774e 100644 --- a/Projects/UOContent/Misc/RegenRates.cs +++ b/Projects/UOContent/Misc/RegenRates.cs @@ -7,205 +7,205 @@ using Server.Spells.Ninjitsu; namespace Server.Misc { - public class RegenRates - { - [CallPriority(10)] - public static void Configure() + public class RegenRates { - Mobile.DefaultHitsRate = TimeSpan.FromSeconds(11.0); - Mobile.DefaultStamRate = TimeSpan.FromSeconds(7.0); - Mobile.DefaultManaRate = TimeSpan.FromSeconds(7.0); + [CallPriority(10)] + public static void Configure() + { + Mobile.DefaultHitsRate = TimeSpan.FromSeconds(11.0); + Mobile.DefaultStamRate = TimeSpan.FromSeconds(7.0); + Mobile.DefaultManaRate = TimeSpan.FromSeconds(7.0); - Mobile.ManaRegenRateHandler = Mobile_ManaRegenRate; + Mobile.ManaRegenRateHandler = Mobile_ManaRegenRate; - if (Core.AOS) - { - Mobile.StamRegenRateHandler = Mobile_StamRegenRate; - Mobile.HitsRegenRateHandler = Mobile_HitsRegenRate; - } + if (Core.AOS) + { + Mobile.StamRegenRateHandler = Mobile_StamRegenRate; + Mobile.HitsRegenRateHandler = Mobile_HitsRegenRate; + } + } + + private static void CheckBonusSkill(Mobile m, int cur, int max, SkillName skill) + { + if (!m.Alive) + return; + + var n = (double)cur / max; + var v = Math.Sqrt(m.Skills[skill].Value * 0.005); + + n *= 1.0 - v; + n += v; + + m.CheckSkill(skill, n); + } + + private static bool CheckTransform(Mobile m, Type type) => TransformationSpellHelper.UnderTransformation(m, type); + + private static bool CheckAnimal(Mobile m, Type type) => AnimalForm.UnderTransformation(m, type); + + private static TimeSpan Mobile_HitsRegenRate(Mobile from) + { + var points = AosAttributes.GetValue(from, AosAttribute.RegenHits); + + var bc = from as BaseCreature; + + if (bc?.IsAnimatedDead == false) + points += 4; + + if (bc?.IsParagon == true || from is Leviathan) + points += 40; + + if (Core.ML && from.Race == Race.Human) // Is this affected by the cap? + points += 2; + + if (points < 0) + points = 0; + + if (Core.ML && from is PlayerMobile) // does racial bonus go before/after? + points = Math.Min(points, 18); + + if (CheckTransform(from, typeof(HorrificBeastSpell))) + points += 20; + + if (CheckAnimal(from, typeof(Dog)) || CheckAnimal(from, typeof(Cat))) + points += from.Skills.Ninjitsu.Fixed / 30; + + return TimeSpan.FromSeconds(1.0 / (0.1 * (1 + points))); + } + + private static TimeSpan Mobile_StamRegenRate(Mobile from) + { + if (from.Skills == null) + return Mobile.DefaultStamRate; + + CheckBonusSkill(from, from.Stam, from.StamMax, SkillName.Focus); + + var points = (int)(from.Skills.Focus.Value * 0.1); + + if (@from is BaseCreature creature && creature.IsParagon || from is Leviathan) + points += 40; + + var cappedPoints = AosAttributes.GetValue(from, AosAttribute.RegenStam); + + if (CheckTransform(from, typeof(VampiricEmbraceSpell))) + cappedPoints += 15; + + if (CheckAnimal(from, typeof(Kirin))) + cappedPoints += 20; + + if (Core.ML && from is PlayerMobile) + cappedPoints = Math.Min(cappedPoints, 24); + + points += cappedPoints; + + if (points < -1) + points = -1; + + return TimeSpan.FromSeconds(1.0 / (0.1 * (2 + points))); + } + + private static TimeSpan Mobile_ManaRegenRate(Mobile from) + { + if (from.Skills == null) + return Mobile.DefaultManaRate; + + if (!from.Meditating) + CheckBonusSkill(from, from.Mana, from.ManaMax, SkillName.Meditation); + + double rate; + var armorPenalty = GetArmorOffset(from); + + if (Core.AOS) + { + var medPoints = from.Int + from.Skills.Meditation.Value * 3; + + medPoints *= from.Skills.Meditation.Value < 100.0 ? 0.025 : 0.0275; + + CheckBonusSkill(from, from.Mana, from.ManaMax, SkillName.Focus); + + var focusPoints = from.Skills.Focus.Value * 0.05; + + if (armorPenalty > 0) + medPoints = 0; // In AOS, wearing any meditation-blocking armor completely removes meditation bonus + + var totalPoints = focusPoints + medPoints + (from.Meditating ? medPoints > 13.0 ? 13.0 : medPoints : 0.0); + + if (@from is BaseCreature creature && creature.IsParagon || from is Leviathan) + totalPoints += 40; + + var cappedPoints = AosAttributes.GetValue(from, AosAttribute.RegenMana); + + if (CheckTransform(from, typeof(VampiricEmbraceSpell))) + cappedPoints += 3; + else if (CheckTransform(from, typeof(LichFormSpell))) + cappedPoints += 13; + + if (Core.ML && from is PlayerMobile) + cappedPoints = Math.Min(cappedPoints, 18); + + totalPoints += cappedPoints; + + if (totalPoints < -1) + totalPoints = -1; + + if (Core.ML) + totalPoints = Math.Floor(totalPoints); + + rate = 1.0 / (0.1 * (2 + totalPoints)); + } + else + { + var medPoints = (from.Int + from.Skills.Meditation.Value) * 0.5; + + if (medPoints <= 0) + rate = 7.0; + else if (medPoints <= 100) + rate = 7.0 - 239 * medPoints / 2400 + 19 * medPoints * medPoints / 48000; + else if (medPoints < 120) + rate = 1.0; + else + rate = 0.75; + + rate += armorPenalty; + + if (from.Meditating) + rate *= 0.5; + + rate = Math.Clamp(rate, 0.5, 7.0); + } + + return TimeSpan.FromSeconds(rate); + } + + public static double GetArmorOffset(Mobile from) + { + var rating = 0.0; + + if (!Core.AOS) + rating += GetArmorMeditationValue(from.ShieldArmor as BaseArmor); + + rating += GetArmorMeditationValue(from.NeckArmor as BaseArmor); + rating += GetArmorMeditationValue(from.HandArmor as BaseArmor); + rating += GetArmorMeditationValue(from.HeadArmor as BaseArmor); + rating += GetArmorMeditationValue(from.ArmsArmor as BaseArmor); + rating += GetArmorMeditationValue(from.LegsArmor as BaseArmor); + rating += GetArmorMeditationValue(from.ChestArmor as BaseArmor); + + return rating / 4; + } + + private static double GetArmorMeditationValue(BaseArmor ar) + { + if (ar == null || ar.ArmorAttributes.MageArmor != 0 || ar.Attributes.SpellChanneling != 0) + return 0.0; + + return ar.MeditationAllowance switch + { + ArmorMeditationAllowance.None => ar.BaseArmorRatingScaled, + ArmorMeditationAllowance.Half => ar.BaseArmorRatingScaled / 2.0, + ArmorMeditationAllowance.All => 0.0, + _ => ar.BaseArmorRatingScaled + }; + } } - - private static void CheckBonusSkill(Mobile m, int cur, int max, SkillName skill) - { - if (!m.Alive) - return; - - double n = (double)cur / max; - double v = Math.Sqrt(m.Skills[skill].Value * 0.005); - - n *= 1.0 - v; - n += v; - - m.CheckSkill(skill, n); - } - - private static bool CheckTransform(Mobile m, Type type) => TransformationSpellHelper.UnderTransformation(m, type); - - private static bool CheckAnimal(Mobile m, Type type) => AnimalForm.UnderTransformation(m, type); - - private static TimeSpan Mobile_HitsRegenRate(Mobile from) - { - int points = AosAttributes.GetValue(from, AosAttribute.RegenHits); - - BaseCreature bc = from as BaseCreature; - - if (bc?.IsAnimatedDead == false) - points += 4; - - if (bc?.IsParagon == true || from is Leviathan) - points += 40; - - if (Core.ML && from.Race == Race.Human) // Is this affected by the cap? - points += 2; - - if (points < 0) - points = 0; - - if (Core.ML && from is PlayerMobile) // does racial bonus go before/after? - points = Math.Min(points, 18); - - if (CheckTransform(from, typeof(HorrificBeastSpell))) - points += 20; - - if (CheckAnimal(from, typeof(Dog)) || CheckAnimal(from, typeof(Cat))) - points += from.Skills.Ninjitsu.Fixed / 30; - - return TimeSpan.FromSeconds(1.0 / (0.1 * (1 + points))); - } - - private static TimeSpan Mobile_StamRegenRate(Mobile from) - { - if (from.Skills == null) - return Mobile.DefaultStamRate; - - CheckBonusSkill(from, from.Stam, from.StamMax, SkillName.Focus); - - int points = (int)(from.Skills.Focus.Value * 0.1); - - if ((from is BaseCreature creature && creature.IsParagon) || from is Leviathan) - points += 40; - - int cappedPoints = AosAttributes.GetValue(from, AosAttribute.RegenStam); - - if (CheckTransform(from, typeof(VampiricEmbraceSpell))) - cappedPoints += 15; - - if (CheckAnimal(from, typeof(Kirin))) - cappedPoints += 20; - - if (Core.ML && from is PlayerMobile) - cappedPoints = Math.Min(cappedPoints, 24); - - points += cappedPoints; - - if (points < -1) - points = -1; - - return TimeSpan.FromSeconds(1.0 / (0.1 * (2 + points))); - } - - private static TimeSpan Mobile_ManaRegenRate(Mobile from) - { - if (from.Skills == null) - return Mobile.DefaultManaRate; - - if (!from.Meditating) - CheckBonusSkill(from, from.Mana, from.ManaMax, SkillName.Meditation); - - double rate; - double armorPenalty = GetArmorOffset(from); - - if (Core.AOS) - { - double medPoints = from.Int + from.Skills.Meditation.Value * 3; - - medPoints *= from.Skills.Meditation.Value < 100.0 ? 0.025 : 0.0275; - - CheckBonusSkill(from, from.Mana, from.ManaMax, SkillName.Focus); - - double focusPoints = from.Skills.Focus.Value * 0.05; - - if (armorPenalty > 0) - medPoints = 0; // In AOS, wearing any meditation-blocking armor completely removes meditation bonus - - double totalPoints = focusPoints + medPoints + (from.Meditating ? medPoints > 13.0 ? 13.0 : medPoints : 0.0); - - if ((from is BaseCreature creature && creature.IsParagon) || from is Leviathan) - totalPoints += 40; - - int cappedPoints = AosAttributes.GetValue(from, AosAttribute.RegenMana); - - if (CheckTransform(from, typeof(VampiricEmbraceSpell))) - cappedPoints += 3; - else if (CheckTransform(from, typeof(LichFormSpell))) - cappedPoints += 13; - - if (Core.ML && from is PlayerMobile) - cappedPoints = Math.Min(cappedPoints, 18); - - totalPoints += cappedPoints; - - if (totalPoints < -1) - totalPoints = -1; - - if (Core.ML) - totalPoints = Math.Floor(totalPoints); - - rate = 1.0 / (0.1 * (2 + totalPoints)); - } - else - { - double medPoints = (from.Int + from.Skills.Meditation.Value) * 0.5; - - if (medPoints <= 0) - rate = 7.0; - else if (medPoints <= 100) - rate = 7.0 - 239 * medPoints / 2400 + 19 * medPoints * medPoints / 48000; - else if (medPoints < 120) - rate = 1.0; - else - rate = 0.75; - - rate += armorPenalty; - - if (from.Meditating) - rate *= 0.5; - - rate = Math.Clamp(rate, 0.5, 7.0); - } - - return TimeSpan.FromSeconds(rate); - } - - public static double GetArmorOffset(Mobile from) - { - double rating = 0.0; - - if (!Core.AOS) - rating += GetArmorMeditationValue(from.ShieldArmor as BaseArmor); - - rating += GetArmorMeditationValue(from.NeckArmor as BaseArmor); - rating += GetArmorMeditationValue(from.HandArmor as BaseArmor); - rating += GetArmorMeditationValue(from.HeadArmor as BaseArmor); - rating += GetArmorMeditationValue(from.ArmsArmor as BaseArmor); - rating += GetArmorMeditationValue(from.LegsArmor as BaseArmor); - rating += GetArmorMeditationValue(from.ChestArmor as BaseArmor); - - return rating / 4; - } - - private static double GetArmorMeditationValue(BaseArmor ar) - { - if (ar == null || ar.ArmorAttributes.MageArmor != 0 || ar.Attributes.SpellChanneling != 0) - return 0.0; - - return ar.MeditationAllowance switch - { - ArmorMeditationAllowance.None => ar.BaseArmorRatingScaled, - ArmorMeditationAllowance.Half => ar.BaseArmorRatingScaled / 2.0, - ArmorMeditationAllowance.All => 0.0, - _ => ar.BaseArmorRatingScaled - }; - } - } } diff --git a/Projects/UOContent/Misc/RenameRequests.cs b/Projects/UOContent/Misc/RenameRequests.cs index 3d4291fe7..8f613354c 100644 --- a/Projects/UOContent/Misc/RenameRequests.cs +++ b/Projects/UOContent/Misc/RenameRequests.cs @@ -1,43 +1,55 @@ namespace Server.Misc { - public static class RenameRequests - { - public static void Initialize() + public static class RenameRequests { - EventSink.RenameRequest += EventSink_RenameRequest; - } - - private static void EventSink_RenameRequest(Mobile from, Mobile targ, string name) - { - if (from.CanSee(targ) && from.InRange(targ, 12) && targ.CanBeRenamedBy(from)) - { - name = name.Trim(); - - if (NameVerification.Validate(name, 1, 16, true, false, true, 0, NameVerification.Empty, - NameVerification.StartDisallowed, Core.ML ? NameVerification.Disallowed : new string[] { })) + public static void Initialize() { - if (Core.ML) - { - string[] disallowed = ProfanityProtection.Disallowed; - - for (int i = 0; i < disallowed.Length; i++) - if (name.IndexOf(disallowed[i]) != -1) - { - from.SendLocalizedMessage(1072622); // That name isn't very polite. - return; - } - - from.SendLocalizedMessage(1072623, - $"{targ.Name}\t{name}"); // Pet ~1_OLDPETNAME~ renamed to ~2_NEWPETNAME~. - } - - targ.Name = name; + EventSink.RenameRequest += EventSink_RenameRequest; } - else + + private static void EventSink_RenameRequest(Mobile from, Mobile targ, string name) { - from.SendMessage("That name is unacceptable."); + if (from.CanSee(targ) && from.InRange(targ, 12) && targ.CanBeRenamedBy(from)) + { + name = name.Trim(); + + if (NameVerification.Validate( + name, + 1, + 16, + true, + false, + true, + 0, + NameVerification.Empty, + NameVerification.StartDisallowed, + Core.ML ? NameVerification.Disallowed : new string[] { } + )) + { + if (Core.ML) + { + var disallowed = ProfanityProtection.Disallowed; + + for (var i = 0; i < disallowed.Length; i++) + if (name.IndexOf(disallowed[i]) != -1) + { + from.SendLocalizedMessage(1072622); // That name isn't very polite. + return; + } + + from.SendLocalizedMessage( + 1072623, + $"{targ.Name}\t{name}" + ); // Pet ~1_OLDPETNAME~ renamed to ~2_NEWPETNAME~. + } + + targ.Name = name; + } + else + { + from.SendMessage("That name is unacceptable."); + } + } } - } } - } } diff --git a/Projects/UOContent/Misc/ResourceInfo.cs b/Projects/UOContent/Misc/ResourceInfo.cs index eb945dd3f..a6930ecbb 100644 --- a/Projects/UOContent/Misc/ResourceInfo.cs +++ b/Projects/UOContent/Misc/ResourceInfo.cs @@ -3,675 +3,939 @@ using System.Collections.Generic; namespace Server.Items { - public enum CraftResource - { - None = 0, - Iron = 1, - DullCopper, - ShadowIron, - Copper, - Bronze, - Gold, - Agapite, - Verite, - Valorite, - - RegularLeather = 101, - SpinedLeather, - HornedLeather, - BarbedLeather, - - RedScales = 201, - YellowScales, - BlackScales, - GreenScales, - WhiteScales, - BlueScales, - - RegularWood = 301, - OakWood, - AshWood, - YewWood, - Heartwood, - Bloodwood, - Frostwood - } - - public enum CraftResourceType - { - None, - Metal, - Leather, - Scales, - Wood - } - - public class CraftAttributeInfo - { - public int WeaponFireDamage { get; set; } - - public int WeaponColdDamage { get; set; } - - public int WeaponPoisonDamage { get; set; } - - public int WeaponEnergyDamage { get; set; } - - public int WeaponChaosDamage { get; set; } - - public int WeaponDirectDamage { get; set; } - - public int WeaponDurability { get; set; } - - public int WeaponLuck { get; set; } - - public int WeaponGoldIncrease { get; set; } - - public int WeaponLowerRequirements { get; set; } - - public int ArmorPhysicalResist { get; set; } - - public int ArmorFireResist { get; set; } - - public int ArmorColdResist { get; set; } - - public int ArmorPoisonResist { get; set; } - - public int ArmorEnergyResist { get; set; } - - public int ArmorDurability { get; set; } - - public int ArmorLuck { get; set; } - - public int ArmorGoldIncrease { get; set; } - - public int ArmorLowerRequirements { get; set; } - - public int RunicMinAttributes { get; set; } - - public int RunicMaxAttributes { get; set; } - - public int RunicMinIntensity { get; set; } - - public int RunicMaxIntensity { get; set; } - - public static readonly CraftAttributeInfo Blank; - public static readonly CraftAttributeInfo DullCopper, ShadowIron, Copper, Bronze, Golden, Agapite, Verite, Valorite; - public static readonly CraftAttributeInfo Spined, Horned, Barbed; - public static readonly CraftAttributeInfo RedScales, YellowScales, BlackScales, GreenScales, WhiteScales, BlueScales; - public static readonly CraftAttributeInfo OakWood, AshWood, YewWood, Heartwood, Bloodwood, Frostwood; - - static CraftAttributeInfo() + public enum CraftResource { - Blank = new CraftAttributeInfo(); + None = 0, + Iron = 1, + DullCopper, + ShadowIron, + Copper, + Bronze, + Gold, + Agapite, + Verite, + Valorite, - CraftAttributeInfo dullCopper = DullCopper = new CraftAttributeInfo(); + RegularLeather = 101, + SpinedLeather, + HornedLeather, + BarbedLeather, - dullCopper.ArmorPhysicalResist = 6; - dullCopper.ArmorDurability = 50; - dullCopper.ArmorLowerRequirements = 20; - dullCopper.WeaponDurability = 100; - dullCopper.WeaponLowerRequirements = 50; - dullCopper.RunicMinAttributes = 1; - dullCopper.RunicMaxAttributes = 2; - if (Core.ML) - { - dullCopper.RunicMinIntensity = 40; - dullCopper.RunicMaxIntensity = 100; - } - else - { - dullCopper.RunicMinIntensity = 10; - dullCopper.RunicMaxIntensity = 35; - } + RedScales = 201, + YellowScales, + BlackScales, + GreenScales, + WhiteScales, + BlueScales, - CraftAttributeInfo shadowIron = ShadowIron = new CraftAttributeInfo(); - - shadowIron.ArmorPhysicalResist = 2; - shadowIron.ArmorFireResist = 1; - shadowIron.ArmorEnergyResist = 5; - shadowIron.ArmorDurability = 100; - shadowIron.WeaponColdDamage = 20; - shadowIron.WeaponDurability = 50; - shadowIron.RunicMinAttributes = 2; - shadowIron.RunicMaxAttributes = 2; - if (Core.ML) - { - shadowIron.RunicMinIntensity = 45; - shadowIron.RunicMaxIntensity = 100; - } - else - { - shadowIron.RunicMinIntensity = 20; - shadowIron.RunicMaxIntensity = 45; - } - - CraftAttributeInfo copper = Copper = new CraftAttributeInfo(); - - copper.ArmorPhysicalResist = 1; - copper.ArmorFireResist = 1; - copper.ArmorPoisonResist = 5; - copper.ArmorEnergyResist = 2; - copper.WeaponPoisonDamage = 10; - copper.WeaponEnergyDamage = 20; - copper.RunicMinAttributes = 2; - copper.RunicMaxAttributes = 3; - if (Core.ML) - { - copper.RunicMinIntensity = 50; - copper.RunicMaxIntensity = 100; - } - else - { - copper.RunicMinIntensity = 25; - copper.RunicMaxIntensity = 50; - } - - CraftAttributeInfo bronze = Bronze = new CraftAttributeInfo(); - - bronze.ArmorPhysicalResist = 3; - bronze.ArmorColdResist = 5; - bronze.ArmorPoisonResist = 1; - bronze.ArmorEnergyResist = 1; - bronze.WeaponFireDamage = 40; - bronze.RunicMinAttributes = 3; - bronze.RunicMaxAttributes = 3; - if (Core.ML) - { - bronze.RunicMinIntensity = 55; - bronze.RunicMaxIntensity = 100; - } - else - { - bronze.RunicMinIntensity = 30; - bronze.RunicMaxIntensity = 65; - } - - CraftAttributeInfo golden = Golden = new CraftAttributeInfo(); - - golden.ArmorPhysicalResist = 1; - golden.ArmorFireResist = 1; - golden.ArmorColdResist = 2; - golden.ArmorEnergyResist = 2; - golden.ArmorLuck = 40; - golden.ArmorLowerRequirements = 30; - golden.WeaponLuck = 40; - golden.WeaponLowerRequirements = 50; - golden.RunicMinAttributes = 3; - golden.RunicMaxAttributes = 4; - if (Core.ML) - { - golden.RunicMinIntensity = 60; - golden.RunicMaxIntensity = 100; - } - else - { - golden.RunicMinIntensity = 35; - golden.RunicMaxIntensity = 75; - } - - CraftAttributeInfo agapite = Agapite = new CraftAttributeInfo(); - - agapite.ArmorPhysicalResist = 2; - agapite.ArmorFireResist = 3; - agapite.ArmorColdResist = 2; - agapite.ArmorPoisonResist = 2; - agapite.ArmorEnergyResist = 2; - agapite.WeaponColdDamage = 30; - agapite.WeaponEnergyDamage = 20; - agapite.RunicMinAttributes = 4; - agapite.RunicMaxAttributes = 4; - if (Core.ML) - { - agapite.RunicMinIntensity = 65; - agapite.RunicMaxIntensity = 100; - } - else - { - agapite.RunicMinIntensity = 40; - agapite.RunicMaxIntensity = 80; - } - - CraftAttributeInfo verite = Verite = new CraftAttributeInfo(); - - verite.ArmorPhysicalResist = 3; - verite.ArmorFireResist = 3; - verite.ArmorColdResist = 2; - verite.ArmorPoisonResist = 3; - verite.ArmorEnergyResist = 1; - verite.WeaponPoisonDamage = 40; - verite.WeaponEnergyDamage = 20; - verite.RunicMinAttributes = 4; - verite.RunicMaxAttributes = 5; - if (Core.ML) - { - verite.RunicMinIntensity = 70; - verite.RunicMaxIntensity = 100; - } - else - { - verite.RunicMinIntensity = 45; - verite.RunicMaxIntensity = 90; - } - - CraftAttributeInfo valorite = Valorite = new CraftAttributeInfo(); - - valorite.ArmorPhysicalResist = 4; - valorite.ArmorColdResist = 3; - valorite.ArmorPoisonResist = 3; - valorite.ArmorEnergyResist = 3; - valorite.ArmorDurability = 50; - valorite.WeaponFireDamage = 10; - valorite.WeaponColdDamage = 20; - valorite.WeaponPoisonDamage = 10; - valorite.WeaponEnergyDamage = 20; - valorite.RunicMinAttributes = 5; - valorite.RunicMaxAttributes = 5; - if (Core.ML) - { - valorite.RunicMinIntensity = 85; - valorite.RunicMaxIntensity = 100; - } - else - { - valorite.RunicMinIntensity = 50; - valorite.RunicMaxIntensity = 100; - } - - CraftAttributeInfo spined = Spined = new CraftAttributeInfo(); - - spined.ArmorPhysicalResist = 5; - spined.ArmorLuck = 40; - spined.RunicMinAttributes = 1; - spined.RunicMaxAttributes = 3; - if (Core.ML) - { - spined.RunicMinIntensity = 40; - spined.RunicMaxIntensity = 100; - } - else - { - spined.RunicMinIntensity = 20; - spined.RunicMaxIntensity = 40; - } - - CraftAttributeInfo horned = Horned = new CraftAttributeInfo(); - - horned.ArmorPhysicalResist = 2; - horned.ArmorFireResist = 3; - horned.ArmorColdResist = 2; - horned.ArmorPoisonResist = 2; - horned.ArmorEnergyResist = 2; - horned.RunicMinAttributes = 3; - horned.RunicMaxAttributes = 4; - if (Core.ML) - { - horned.RunicMinIntensity = 45; - horned.RunicMaxIntensity = 100; - } - else - { - horned.RunicMinIntensity = 30; - horned.RunicMaxIntensity = 70; - } - - CraftAttributeInfo barbed = Barbed = new CraftAttributeInfo(); - - barbed.ArmorPhysicalResist = 2; - barbed.ArmorFireResist = 1; - barbed.ArmorColdResist = 2; - barbed.ArmorPoisonResist = 3; - barbed.ArmorEnergyResist = 4; - barbed.RunicMinAttributes = 4; - barbed.RunicMaxAttributes = 5; - if (Core.ML) - { - barbed.RunicMinIntensity = 50; - barbed.RunicMaxIntensity = 100; - } - else - { - barbed.RunicMinIntensity = 40; - barbed.RunicMaxIntensity = 100; - } - - CraftAttributeInfo red = RedScales = new CraftAttributeInfo(); - - red.ArmorFireResist = 10; - red.ArmorColdResist = -3; - - CraftAttributeInfo yellow = YellowScales = new CraftAttributeInfo(); - - yellow.ArmorPhysicalResist = -3; - yellow.ArmorLuck = 20; - - CraftAttributeInfo black = BlackScales = new CraftAttributeInfo(); - - black.ArmorPhysicalResist = 10; - black.ArmorEnergyResist = -3; - - CraftAttributeInfo green = GreenScales = new CraftAttributeInfo(); - - green.ArmorFireResist = -3; - green.ArmorPoisonResist = 10; - - CraftAttributeInfo white = WhiteScales = new CraftAttributeInfo(); - - white.ArmorPhysicalResist = -3; - white.ArmorColdResist = 10; - - CraftAttributeInfo blue = BlueScales = new CraftAttributeInfo(); - - blue.ArmorPoisonResist = -3; - blue.ArmorEnergyResist = 10; - - // public static readonly CraftAttributeInfo OakWood, AshWood, YewWood, Heartwood, Bloodwood, Frostwood; - - CraftAttributeInfo oak = OakWood = new CraftAttributeInfo(); - - CraftAttributeInfo ash = AshWood = new CraftAttributeInfo(); - - CraftAttributeInfo yew = YewWood = new CraftAttributeInfo(); - - CraftAttributeInfo heart = Heartwood = new CraftAttributeInfo(); - - CraftAttributeInfo blood = Bloodwood = new CraftAttributeInfo(); - - CraftAttributeInfo frost = Frostwood = new CraftAttributeInfo(); - } - } - - public class CraftResourceInfo - { - public int Hue { get; } - - public int Number { get; } - - public string Name { get; } - - public CraftAttributeInfo AttributeInfo { get; } - - public CraftResource Resource { get; } - - public Type[] ResourceTypes { get; } - - public CraftResourceInfo(int hue, int number, string name, CraftAttributeInfo attributeInfo, CraftResource resource, params Type[] resourceTypes) - { - Hue = hue; - Number = number; - Name = name; - AttributeInfo = attributeInfo; - Resource = resource; - ResourceTypes = resourceTypes; - - for (int i = 0; i < resourceTypes.Length; ++i) - CraftResources.RegisterType(resourceTypes[i], resource); - } - } - - public static class CraftResources - { - private static readonly CraftResourceInfo[] m_MetalInfo = { - new CraftResourceInfo(0x000, 1053109, "Iron", CraftAttributeInfo.Blank, CraftResource.Iron, typeof(IronIngot), typeof(IronOre), typeof(Granite)), - new CraftResourceInfo(0x973, 1053108, "Dull Copper", CraftAttributeInfo.DullCopper, CraftResource.DullCopper, typeof(DullCopperIngot), typeof(DullCopperOre), typeof(DullCopperGranite)), - new CraftResourceInfo(0x966, 1053107, "Shadow Iron", CraftAttributeInfo.ShadowIron, CraftResource.ShadowIron, typeof(ShadowIronIngot), typeof(ShadowIronOre), typeof(ShadowIronGranite)), - new CraftResourceInfo(0x96D, 1053106, "Copper", CraftAttributeInfo.Copper, CraftResource.Copper, typeof(CopperIngot), typeof(CopperOre), typeof(CopperGranite)), - new CraftResourceInfo(0x972, 1053105, "Bronze", CraftAttributeInfo.Bronze, CraftResource.Bronze, typeof(BronzeIngot), typeof(BronzeOre), typeof(BronzeGranite)), - new CraftResourceInfo(0x8A5, 1053104, "Gold", CraftAttributeInfo.Golden, CraftResource.Gold, typeof(GoldIngot), typeof(GoldOre), typeof(GoldGranite)), - new CraftResourceInfo(0x979, 1053103, "Agapite", CraftAttributeInfo.Agapite, CraftResource.Agapite, typeof(AgapiteIngot), typeof(AgapiteOre), typeof(AgapiteGranite)), - new CraftResourceInfo(0x89F, 1053102, "Verite", CraftAttributeInfo.Verite, CraftResource.Verite, typeof(VeriteIngot), typeof(VeriteOre), typeof(VeriteGranite)), - new CraftResourceInfo(0x8AB, 1053101, "Valorite", CraftAttributeInfo.Valorite, CraftResource.Valorite, typeof(ValoriteIngot), typeof(ValoriteOre), typeof(ValoriteGranite)) - }; - - private static readonly CraftResourceInfo[] m_ScaleInfo = { - new CraftResourceInfo(0x66D, 1053129, "Red Scales", CraftAttributeInfo.RedScales, CraftResource.RedScales, typeof(RedScales)), - new CraftResourceInfo(0x8A8, 1053130, "Yellow Scales", CraftAttributeInfo.YellowScales, CraftResource.YellowScales, typeof(YellowScales)), - new CraftResourceInfo(0x455, 1053131, "Black Scales", CraftAttributeInfo.BlackScales, CraftResource.BlackScales, typeof(BlackScales)), - new CraftResourceInfo(0x851, 1053132, "Green Scales", CraftAttributeInfo.GreenScales, CraftResource.GreenScales, typeof(GreenScales)), - new CraftResourceInfo(0x8FD, 1053133, "White Scales", CraftAttributeInfo.WhiteScales, CraftResource.WhiteScales, typeof(WhiteScales)), - new CraftResourceInfo(0x8B0, 1053134, "Blue Scales", CraftAttributeInfo.BlueScales, CraftResource.BlueScales, typeof(BlueScales)) - }; - - private static readonly CraftResourceInfo[] m_LeatherInfo = { - new CraftResourceInfo(0x000, 1049353, "Normal", CraftAttributeInfo.Blank, CraftResource.RegularLeather, typeof(Leather), typeof(Hides)), - new CraftResourceInfo(0x283, 1049354, "Spined", CraftAttributeInfo.Spined, CraftResource.SpinedLeather, typeof(SpinedLeather), typeof(SpinedHides)), - new CraftResourceInfo(0x227, 1049355, "Horned", CraftAttributeInfo.Horned, CraftResource.HornedLeather, typeof(HornedLeather), typeof(HornedHides)), - new CraftResourceInfo(0x1C1, 1049356, "Barbed", CraftAttributeInfo.Barbed, CraftResource.BarbedLeather, typeof(BarbedLeather), typeof(BarbedHides)) - }; - - private static readonly CraftResourceInfo[] m_AOSLeatherInfo = { - new CraftResourceInfo(0x000, 1049353, "Normal", CraftAttributeInfo.Blank, CraftResource.RegularLeather, typeof(Leather), typeof(Hides)), - new CraftResourceInfo(0x8AC, 1049354, "Spined", CraftAttributeInfo.Spined, CraftResource.SpinedLeather, typeof(SpinedLeather), typeof(SpinedHides)), - new CraftResourceInfo(0x845, 1049355, "Horned", CraftAttributeInfo.Horned, CraftResource.HornedLeather, typeof(HornedLeather), typeof(HornedHides)), - new CraftResourceInfo(0x851, 1049356, "Barbed", CraftAttributeInfo.Barbed, CraftResource.BarbedLeather, typeof(BarbedLeather), typeof(BarbedHides)) - }; - - private static readonly CraftResourceInfo[] m_WoodInfo = { - new CraftResourceInfo(0x000, 1011542, "Normal", CraftAttributeInfo.Blank, CraftResource.RegularWood, typeof(Log), typeof(Board)), - new CraftResourceInfo(0x7DA, 1072533, "Oak", CraftAttributeInfo.OakWood, CraftResource.OakWood, typeof(OakLog), typeof(OakBoard)), - new CraftResourceInfo(0x4A7, 1072534, "Ash", CraftAttributeInfo.AshWood, CraftResource.AshWood, typeof(AshLog), typeof(AshBoard)), - new CraftResourceInfo(0x4A8, 1072535, "Yew", CraftAttributeInfo.YewWood, CraftResource.YewWood, typeof(YewLog), typeof(YewBoard)), - new CraftResourceInfo(0x4A9, 1072536, "Heartwood", CraftAttributeInfo.Heartwood, CraftResource.Heartwood, typeof(HeartwoodLog), typeof(HeartwoodBoard)), - new CraftResourceInfo(0x4AA, 1072538, "Bloodwood", CraftAttributeInfo.Bloodwood, CraftResource.Bloodwood, typeof(BloodwoodLog), typeof(BloodwoodBoard)), - new CraftResourceInfo(0x47F, 1072539, "Frostwood", CraftAttributeInfo.Frostwood, CraftResource.Frostwood, typeof(FrostwoodLog), typeof(FrostwoodBoard)) - }; - - /// - /// Returns true if '' is None, Iron, RegularLeather or RegularWood. False if otherwise. - /// - public static bool IsStandard(CraftResource resource) => resource == CraftResource.None || resource == CraftResource.Iron || resource == CraftResource.RegularLeather || resource == CraftResource.RegularWood; - - private static Dictionary m_TypeTable; - - /// - /// Registers that '' uses '' so that it can later be queried by - /// - public static void RegisterType(Type resourceType, CraftResource resource) - { - if (m_TypeTable == null) - m_TypeTable = new Dictionary(); - - m_TypeTable[resourceType] = resource; + RegularWood = 301, + OakWood, + AshWood, + YewWood, + Heartwood, + Bloodwood, + Frostwood } - /// - /// Returns the value for which '' uses -or- CraftResource.None if an unregistered type was specified. - /// - public static CraftResource GetFromType(Type resourceType) + public enum CraftResourceType { - if (m_TypeTable == null) - return CraftResource.None; - - return m_TypeTable.TryGetValue(resourceType, out CraftResource res) ? res : CraftResource.None; + None, + Metal, + Leather, + Scales, + Wood } - /// - /// Returns a instance describing '' -or- null if an invalid resource was specified. - /// - public static CraftResourceInfo GetInfo(CraftResource resource) + public class CraftAttributeInfo { - var list = GetType(resource) switch - { - CraftResourceType.Metal => m_MetalInfo, - CraftResourceType.Leather => Core.AOS ? m_AOSLeatherInfo : m_LeatherInfo, - CraftResourceType.Scales => m_ScaleInfo, - CraftResourceType.Wood => m_WoodInfo, - _ => null - }; + public static readonly CraftAttributeInfo Blank; + public static readonly CraftAttributeInfo DullCopper, ShadowIron, Copper, Bronze, Golden, Agapite, Verite, Valorite; + public static readonly CraftAttributeInfo Spined, Horned, Barbed; + public static readonly CraftAttributeInfo RedScales, YellowScales, BlackScales, GreenScales, WhiteScales, BlueScales; + public static readonly CraftAttributeInfo OakWood, AshWood, YewWood, Heartwood, Bloodwood, Frostwood; - if (list != null) - { - int index = GetIndex(resource); + static CraftAttributeInfo() + { + Blank = new CraftAttributeInfo(); - if (index >= 0 && index < list.Length) - return list[index]; - } + var dullCopper = DullCopper = new CraftAttributeInfo(); - return null; + dullCopper.ArmorPhysicalResist = 6; + dullCopper.ArmorDurability = 50; + dullCopper.ArmorLowerRequirements = 20; + dullCopper.WeaponDurability = 100; + dullCopper.WeaponLowerRequirements = 50; + dullCopper.RunicMinAttributes = 1; + dullCopper.RunicMaxAttributes = 2; + if (Core.ML) + { + dullCopper.RunicMinIntensity = 40; + dullCopper.RunicMaxIntensity = 100; + } + else + { + dullCopper.RunicMinIntensity = 10; + dullCopper.RunicMaxIntensity = 35; + } + + var shadowIron = ShadowIron = new CraftAttributeInfo(); + + shadowIron.ArmorPhysicalResist = 2; + shadowIron.ArmorFireResist = 1; + shadowIron.ArmorEnergyResist = 5; + shadowIron.ArmorDurability = 100; + shadowIron.WeaponColdDamage = 20; + shadowIron.WeaponDurability = 50; + shadowIron.RunicMinAttributes = 2; + shadowIron.RunicMaxAttributes = 2; + if (Core.ML) + { + shadowIron.RunicMinIntensity = 45; + shadowIron.RunicMaxIntensity = 100; + } + else + { + shadowIron.RunicMinIntensity = 20; + shadowIron.RunicMaxIntensity = 45; + } + + var copper = Copper = new CraftAttributeInfo(); + + copper.ArmorPhysicalResist = 1; + copper.ArmorFireResist = 1; + copper.ArmorPoisonResist = 5; + copper.ArmorEnergyResist = 2; + copper.WeaponPoisonDamage = 10; + copper.WeaponEnergyDamage = 20; + copper.RunicMinAttributes = 2; + copper.RunicMaxAttributes = 3; + if (Core.ML) + { + copper.RunicMinIntensity = 50; + copper.RunicMaxIntensity = 100; + } + else + { + copper.RunicMinIntensity = 25; + copper.RunicMaxIntensity = 50; + } + + var bronze = Bronze = new CraftAttributeInfo(); + + bronze.ArmorPhysicalResist = 3; + bronze.ArmorColdResist = 5; + bronze.ArmorPoisonResist = 1; + bronze.ArmorEnergyResist = 1; + bronze.WeaponFireDamage = 40; + bronze.RunicMinAttributes = 3; + bronze.RunicMaxAttributes = 3; + if (Core.ML) + { + bronze.RunicMinIntensity = 55; + bronze.RunicMaxIntensity = 100; + } + else + { + bronze.RunicMinIntensity = 30; + bronze.RunicMaxIntensity = 65; + } + + var golden = Golden = new CraftAttributeInfo(); + + golden.ArmorPhysicalResist = 1; + golden.ArmorFireResist = 1; + golden.ArmorColdResist = 2; + golden.ArmorEnergyResist = 2; + golden.ArmorLuck = 40; + golden.ArmorLowerRequirements = 30; + golden.WeaponLuck = 40; + golden.WeaponLowerRequirements = 50; + golden.RunicMinAttributes = 3; + golden.RunicMaxAttributes = 4; + if (Core.ML) + { + golden.RunicMinIntensity = 60; + golden.RunicMaxIntensity = 100; + } + else + { + golden.RunicMinIntensity = 35; + golden.RunicMaxIntensity = 75; + } + + var agapite = Agapite = new CraftAttributeInfo(); + + agapite.ArmorPhysicalResist = 2; + agapite.ArmorFireResist = 3; + agapite.ArmorColdResist = 2; + agapite.ArmorPoisonResist = 2; + agapite.ArmorEnergyResist = 2; + agapite.WeaponColdDamage = 30; + agapite.WeaponEnergyDamage = 20; + agapite.RunicMinAttributes = 4; + agapite.RunicMaxAttributes = 4; + if (Core.ML) + { + agapite.RunicMinIntensity = 65; + agapite.RunicMaxIntensity = 100; + } + else + { + agapite.RunicMinIntensity = 40; + agapite.RunicMaxIntensity = 80; + } + + var verite = Verite = new CraftAttributeInfo(); + + verite.ArmorPhysicalResist = 3; + verite.ArmorFireResist = 3; + verite.ArmorColdResist = 2; + verite.ArmorPoisonResist = 3; + verite.ArmorEnergyResist = 1; + verite.WeaponPoisonDamage = 40; + verite.WeaponEnergyDamage = 20; + verite.RunicMinAttributes = 4; + verite.RunicMaxAttributes = 5; + if (Core.ML) + { + verite.RunicMinIntensity = 70; + verite.RunicMaxIntensity = 100; + } + else + { + verite.RunicMinIntensity = 45; + verite.RunicMaxIntensity = 90; + } + + var valorite = Valorite = new CraftAttributeInfo(); + + valorite.ArmorPhysicalResist = 4; + valorite.ArmorColdResist = 3; + valorite.ArmorPoisonResist = 3; + valorite.ArmorEnergyResist = 3; + valorite.ArmorDurability = 50; + valorite.WeaponFireDamage = 10; + valorite.WeaponColdDamage = 20; + valorite.WeaponPoisonDamage = 10; + valorite.WeaponEnergyDamage = 20; + valorite.RunicMinAttributes = 5; + valorite.RunicMaxAttributes = 5; + if (Core.ML) + { + valorite.RunicMinIntensity = 85; + valorite.RunicMaxIntensity = 100; + } + else + { + valorite.RunicMinIntensity = 50; + valorite.RunicMaxIntensity = 100; + } + + var spined = Spined = new CraftAttributeInfo(); + + spined.ArmorPhysicalResist = 5; + spined.ArmorLuck = 40; + spined.RunicMinAttributes = 1; + spined.RunicMaxAttributes = 3; + if (Core.ML) + { + spined.RunicMinIntensity = 40; + spined.RunicMaxIntensity = 100; + } + else + { + spined.RunicMinIntensity = 20; + spined.RunicMaxIntensity = 40; + } + + var horned = Horned = new CraftAttributeInfo(); + + horned.ArmorPhysicalResist = 2; + horned.ArmorFireResist = 3; + horned.ArmorColdResist = 2; + horned.ArmorPoisonResist = 2; + horned.ArmorEnergyResist = 2; + horned.RunicMinAttributes = 3; + horned.RunicMaxAttributes = 4; + if (Core.ML) + { + horned.RunicMinIntensity = 45; + horned.RunicMaxIntensity = 100; + } + else + { + horned.RunicMinIntensity = 30; + horned.RunicMaxIntensity = 70; + } + + var barbed = Barbed = new CraftAttributeInfo(); + + barbed.ArmorPhysicalResist = 2; + barbed.ArmorFireResist = 1; + barbed.ArmorColdResist = 2; + barbed.ArmorPoisonResist = 3; + barbed.ArmorEnergyResist = 4; + barbed.RunicMinAttributes = 4; + barbed.RunicMaxAttributes = 5; + if (Core.ML) + { + barbed.RunicMinIntensity = 50; + barbed.RunicMaxIntensity = 100; + } + else + { + barbed.RunicMinIntensity = 40; + barbed.RunicMaxIntensity = 100; + } + + var red = RedScales = new CraftAttributeInfo(); + + red.ArmorFireResist = 10; + red.ArmorColdResist = -3; + + var yellow = YellowScales = new CraftAttributeInfo(); + + yellow.ArmorPhysicalResist = -3; + yellow.ArmorLuck = 20; + + var black = BlackScales = new CraftAttributeInfo(); + + black.ArmorPhysicalResist = 10; + black.ArmorEnergyResist = -3; + + var green = GreenScales = new CraftAttributeInfo(); + + green.ArmorFireResist = -3; + green.ArmorPoisonResist = 10; + + var white = WhiteScales = new CraftAttributeInfo(); + + white.ArmorPhysicalResist = -3; + white.ArmorColdResist = 10; + + var blue = BlueScales = new CraftAttributeInfo(); + + blue.ArmorPoisonResist = -3; + blue.ArmorEnergyResist = 10; + + // public static readonly CraftAttributeInfo OakWood, AshWood, YewWood, Heartwood, Bloodwood, Frostwood; + + var oak = OakWood = new CraftAttributeInfo(); + + var ash = AshWood = new CraftAttributeInfo(); + + var yew = YewWood = new CraftAttributeInfo(); + + var heart = Heartwood = new CraftAttributeInfo(); + + var blood = Bloodwood = new CraftAttributeInfo(); + + var frost = Frostwood = new CraftAttributeInfo(); + } + + public int WeaponFireDamage { get; set; } + + public int WeaponColdDamage { get; set; } + + public int WeaponPoisonDamage { get; set; } + + public int WeaponEnergyDamage { get; set; } + + public int WeaponChaosDamage { get; set; } + + public int WeaponDirectDamage { get; set; } + + public int WeaponDurability { get; set; } + + public int WeaponLuck { get; set; } + + public int WeaponGoldIncrease { get; set; } + + public int WeaponLowerRequirements { get; set; } + + public int ArmorPhysicalResist { get; set; } + + public int ArmorFireResist { get; set; } + + public int ArmorColdResist { get; set; } + + public int ArmorPoisonResist { get; set; } + + public int ArmorEnergyResist { get; set; } + + public int ArmorDurability { get; set; } + + public int ArmorLuck { get; set; } + + public int ArmorGoldIncrease { get; set; } + + public int ArmorLowerRequirements { get; set; } + + public int RunicMinAttributes { get; set; } + + public int RunicMaxAttributes { get; set; } + + public int RunicMinIntensity { get; set; } + + public int RunicMaxIntensity { get; set; } } - /// - /// Returns a value indiciating the type of ''. - /// - public static CraftResourceType GetType(CraftResource resource) + public class CraftResourceInfo { - if (resource >= CraftResource.Iron && resource <= CraftResource.Valorite) - return CraftResourceType.Metal; + public CraftResourceInfo( + int hue, int number, string name, CraftAttributeInfo attributeInfo, CraftResource resource, + params Type[] resourceTypes + ) + { + Hue = hue; + Number = number; + Name = name; + AttributeInfo = attributeInfo; + Resource = resource; + ResourceTypes = resourceTypes; - if (resource >= CraftResource.RegularLeather && resource <= CraftResource.BarbedLeather) - return CraftResourceType.Leather; + for (var i = 0; i < resourceTypes.Length; ++i) + CraftResources.RegisterType(resourceTypes[i], resource); + } - if (resource >= CraftResource.RedScales && resource <= CraftResource.BlueScales) - return CraftResourceType.Scales; + public int Hue { get; } - if (resource >= CraftResource.RegularWood && resource <= CraftResource.Frostwood) - return CraftResourceType.Wood; + public int Number { get; } - return CraftResourceType.None; + public string Name { get; } + + public CraftAttributeInfo AttributeInfo { get; } + + public CraftResource Resource { get; } + + public Type[] ResourceTypes { get; } } - /// - /// Returns the first in the series of resources for which '' belongs. - /// - public static CraftResource GetStart(CraftResource resource) + public static class CraftResources { - return GetType(resource) switch - { - CraftResourceType.Metal => CraftResource.Iron, - CraftResourceType.Leather => CraftResource.RegularLeather, - CraftResourceType.Scales => CraftResource.RedScales, - CraftResourceType.Wood => CraftResource.RegularWood, - _ => CraftResource.None - }; + private static readonly CraftResourceInfo[] m_MetalInfo = + { + new CraftResourceInfo( + 0x000, + 1053109, + "Iron", + CraftAttributeInfo.Blank, + CraftResource.Iron, + typeof(IronIngot), + typeof(IronOre), + typeof(Granite) + ), + new CraftResourceInfo( + 0x973, + 1053108, + "Dull Copper", + CraftAttributeInfo.DullCopper, + CraftResource.DullCopper, + typeof(DullCopperIngot), + typeof(DullCopperOre), + typeof(DullCopperGranite) + ), + new CraftResourceInfo( + 0x966, + 1053107, + "Shadow Iron", + CraftAttributeInfo.ShadowIron, + CraftResource.ShadowIron, + typeof(ShadowIronIngot), + typeof(ShadowIronOre), + typeof(ShadowIronGranite) + ), + new CraftResourceInfo( + 0x96D, + 1053106, + "Copper", + CraftAttributeInfo.Copper, + CraftResource.Copper, + typeof(CopperIngot), + typeof(CopperOre), + typeof(CopperGranite) + ), + new CraftResourceInfo( + 0x972, + 1053105, + "Bronze", + CraftAttributeInfo.Bronze, + CraftResource.Bronze, + typeof(BronzeIngot), + typeof(BronzeOre), + typeof(BronzeGranite) + ), + new CraftResourceInfo( + 0x8A5, + 1053104, + "Gold", + CraftAttributeInfo.Golden, + CraftResource.Gold, + typeof(GoldIngot), + typeof(GoldOre), + typeof(GoldGranite) + ), + new CraftResourceInfo( + 0x979, + 1053103, + "Agapite", + CraftAttributeInfo.Agapite, + CraftResource.Agapite, + typeof(AgapiteIngot), + typeof(AgapiteOre), + typeof(AgapiteGranite) + ), + new CraftResourceInfo( + 0x89F, + 1053102, + "Verite", + CraftAttributeInfo.Verite, + CraftResource.Verite, + typeof(VeriteIngot), + typeof(VeriteOre), + typeof(VeriteGranite) + ), + new CraftResourceInfo( + 0x8AB, + 1053101, + "Valorite", + CraftAttributeInfo.Valorite, + CraftResource.Valorite, + typeof(ValoriteIngot), + typeof(ValoriteOre), + typeof(ValoriteGranite) + ) + }; + + private static readonly CraftResourceInfo[] m_ScaleInfo = + { + new CraftResourceInfo( + 0x66D, + 1053129, + "Red Scales", + CraftAttributeInfo.RedScales, + CraftResource.RedScales, + typeof(RedScales) + ), + new CraftResourceInfo( + 0x8A8, + 1053130, + "Yellow Scales", + CraftAttributeInfo.YellowScales, + CraftResource.YellowScales, + typeof(YellowScales) + ), + new CraftResourceInfo( + 0x455, + 1053131, + "Black Scales", + CraftAttributeInfo.BlackScales, + CraftResource.BlackScales, + typeof(BlackScales) + ), + new CraftResourceInfo( + 0x851, + 1053132, + "Green Scales", + CraftAttributeInfo.GreenScales, + CraftResource.GreenScales, + typeof(GreenScales) + ), + new CraftResourceInfo( + 0x8FD, + 1053133, + "White Scales", + CraftAttributeInfo.WhiteScales, + CraftResource.WhiteScales, + typeof(WhiteScales) + ), + new CraftResourceInfo( + 0x8B0, + 1053134, + "Blue Scales", + CraftAttributeInfo.BlueScales, + CraftResource.BlueScales, + typeof(BlueScales) + ) + }; + + private static readonly CraftResourceInfo[] m_LeatherInfo = + { + new CraftResourceInfo( + 0x000, + 1049353, + "Normal", + CraftAttributeInfo.Blank, + CraftResource.RegularLeather, + typeof(Leather), + typeof(Hides) + ), + new CraftResourceInfo( + 0x283, + 1049354, + "Spined", + CraftAttributeInfo.Spined, + CraftResource.SpinedLeather, + typeof(SpinedLeather), + typeof(SpinedHides) + ), + new CraftResourceInfo( + 0x227, + 1049355, + "Horned", + CraftAttributeInfo.Horned, + CraftResource.HornedLeather, + typeof(HornedLeather), + typeof(HornedHides) + ), + new CraftResourceInfo( + 0x1C1, + 1049356, + "Barbed", + CraftAttributeInfo.Barbed, + CraftResource.BarbedLeather, + typeof(BarbedLeather), + typeof(BarbedHides) + ) + }; + + private static readonly CraftResourceInfo[] m_AOSLeatherInfo = + { + new CraftResourceInfo( + 0x000, + 1049353, + "Normal", + CraftAttributeInfo.Blank, + CraftResource.RegularLeather, + typeof(Leather), + typeof(Hides) + ), + new CraftResourceInfo( + 0x8AC, + 1049354, + "Spined", + CraftAttributeInfo.Spined, + CraftResource.SpinedLeather, + typeof(SpinedLeather), + typeof(SpinedHides) + ), + new CraftResourceInfo( + 0x845, + 1049355, + "Horned", + CraftAttributeInfo.Horned, + CraftResource.HornedLeather, + typeof(HornedLeather), + typeof(HornedHides) + ), + new CraftResourceInfo( + 0x851, + 1049356, + "Barbed", + CraftAttributeInfo.Barbed, + CraftResource.BarbedLeather, + typeof(BarbedLeather), + typeof(BarbedHides) + ) + }; + + private static readonly CraftResourceInfo[] m_WoodInfo = + { + new CraftResourceInfo( + 0x000, + 1011542, + "Normal", + CraftAttributeInfo.Blank, + CraftResource.RegularWood, + typeof(Log), + typeof(Board) + ), + new CraftResourceInfo( + 0x7DA, + 1072533, + "Oak", + CraftAttributeInfo.OakWood, + CraftResource.OakWood, + typeof(OakLog), + typeof(OakBoard) + ), + new CraftResourceInfo( + 0x4A7, + 1072534, + "Ash", + CraftAttributeInfo.AshWood, + CraftResource.AshWood, + typeof(AshLog), + typeof(AshBoard) + ), + new CraftResourceInfo( + 0x4A8, + 1072535, + "Yew", + CraftAttributeInfo.YewWood, + CraftResource.YewWood, + typeof(YewLog), + typeof(YewBoard) + ), + new CraftResourceInfo( + 0x4A9, + 1072536, + "Heartwood", + CraftAttributeInfo.Heartwood, + CraftResource.Heartwood, + typeof(HeartwoodLog), + typeof(HeartwoodBoard) + ), + new CraftResourceInfo( + 0x4AA, + 1072538, + "Bloodwood", + CraftAttributeInfo.Bloodwood, + CraftResource.Bloodwood, + typeof(BloodwoodLog), + typeof(BloodwoodBoard) + ), + new CraftResourceInfo( + 0x47F, + 1072539, + "Frostwood", + CraftAttributeInfo.Frostwood, + CraftResource.Frostwood, + typeof(FrostwoodLog), + typeof(FrostwoodBoard) + ) + }; + + private static Dictionary m_TypeTable; + + /// + /// Returns true if '' is None, Iron, RegularLeather or RegularWood. False if otherwise. + /// + public static bool IsStandard(CraftResource resource) => resource == CraftResource.None || + resource == CraftResource.Iron || + resource == CraftResource.RegularLeather || + resource == CraftResource.RegularWood; + + /// + /// Registers that '' uses '' so that it can later be queried by + /// + /// + public static void RegisterType(Type resourceType, CraftResource resource) + { + if (m_TypeTable == null) + m_TypeTable = new Dictionary(); + + m_TypeTable[resourceType] = resource; + } + + /// + /// Returns the value for which '' uses -or- CraftResource.None + /// if an unregistered type was specified. + /// + public static CraftResource GetFromType(Type resourceType) + { + if (m_TypeTable == null) + return CraftResource.None; + + return m_TypeTable.TryGetValue(resourceType, out var res) ? res : CraftResource.None; + } + + /// + /// Returns a instance describing '' -or- null if an invalid + /// resource was specified. + /// + public static CraftResourceInfo GetInfo(CraftResource resource) + { + var list = GetType(resource) switch + { + CraftResourceType.Metal => m_MetalInfo, + CraftResourceType.Leather => Core.AOS ? m_AOSLeatherInfo : m_LeatherInfo, + CraftResourceType.Scales => m_ScaleInfo, + CraftResourceType.Wood => m_WoodInfo, + _ => null + }; + + if (list != null) + { + var index = GetIndex(resource); + + if (index >= 0 && index < list.Length) + return list[index]; + } + + return null; + } + + /// + /// Returns a value indiciating the type of ''. + /// + public static CraftResourceType GetType(CraftResource resource) + { + if (resource >= CraftResource.Iron && resource <= CraftResource.Valorite) + return CraftResourceType.Metal; + + if (resource >= CraftResource.RegularLeather && resource <= CraftResource.BarbedLeather) + return CraftResourceType.Leather; + + if (resource >= CraftResource.RedScales && resource <= CraftResource.BlueScales) + return CraftResourceType.Scales; + + if (resource >= CraftResource.RegularWood && resource <= CraftResource.Frostwood) + return CraftResourceType.Wood; + + return CraftResourceType.None; + } + + /// + /// Returns the first in the series of resources for which '' + /// belongs. + /// + public static CraftResource GetStart(CraftResource resource) + { + return GetType(resource) switch + { + CraftResourceType.Metal => CraftResource.Iron, + CraftResourceType.Leather => CraftResource.RegularLeather, + CraftResourceType.Scales => CraftResource.RedScales, + CraftResourceType.Wood => CraftResource.RegularWood, + _ => CraftResource.None + }; + } + + /// + /// Returns the index of '' in the seriest of resources for which it belongs. + /// + public static int GetIndex(CraftResource resource) + { + var start = GetStart(resource); + + if (start == CraftResource.None) + return 0; + + return resource - start; + } + + /// + /// Returns the property of '' -or- 0 if an invalid + /// resource was specified. + /// + public static int GetLocalizationNumber(CraftResource resource) + { + var info = GetInfo(resource); + + return info?.Number ?? 0; + } + + /// + /// Returns the property of '' -or- 0 if an invalid + /// resource was specified. + /// + public static int GetHue(CraftResource resource) + { + var info = GetInfo(resource); + + return info?.Hue ?? 0; + } + + /// + /// Returns the property of '' -or- an empty string if the + /// resource specified was invalid. + /// + public static string GetName(CraftResource resource) + { + var info = GetInfo(resource); + + return info == null ? string.Empty : info.Name; + } + + /// + /// Returns the value which represents '' -or- CraftResource.None if + /// unable to convert. + /// + public static CraftResource GetFromOreInfo(OreInfo info) + { + if (info.Name.IndexOf("Spined") >= 0) + return CraftResource.SpinedLeather; + if (info.Name.IndexOf("Horned") >= 0) + return CraftResource.HornedLeather; + if (info.Name.IndexOf("Barbed") >= 0) + return CraftResource.BarbedLeather; + if (info.Name.IndexOf("Leather") >= 0) + return CraftResource.RegularLeather; + + if (info.Level == 0) + return CraftResource.Iron; + if (info.Level == 1) + return CraftResource.DullCopper; + if (info.Level == 2) + return CraftResource.ShadowIron; + if (info.Level == 3) + return CraftResource.Copper; + if (info.Level == 4) + return CraftResource.Bronze; + if (info.Level == 5) + return CraftResource.Gold; + if (info.Level == 6) + return CraftResource.Agapite; + if (info.Level == 7) + return CraftResource.Verite; + if (info.Level == 8) + return CraftResource.Valorite; + + return CraftResource.None; + } + + /// + /// Returns the value which represents '', using ' + /// ' to help resolve leather OreInfo instances. + /// + public static CraftResource GetFromOreInfo(OreInfo info, ArmorMaterialType material) + { + if (material == ArmorMaterialType.Studded || material == ArmorMaterialType.Leather || + material == ArmorMaterialType.Spined || + material == ArmorMaterialType.Horned || material == ArmorMaterialType.Barbed) + { + if (info.Level == 0) + return CraftResource.RegularLeather; + if (info.Level == 1) + return CraftResource.SpinedLeather; + if (info.Level == 2) + return CraftResource.HornedLeather; + if (info.Level == 3) + return CraftResource.BarbedLeather; + + return CraftResource.None; + } + + return GetFromOreInfo(info); + } } - /// - /// Returns the index of '' in the seriest of resources for which it belongs. - /// - public static int GetIndex(CraftResource resource) + // NOTE: This class is only for compatability with very old RunUO versions. + // No changes to it should be required for custom resources. + public class OreInfo { - CraftResource start = GetStart(resource); + public static readonly OreInfo Iron = new OreInfo(0, 0x000, "Iron"); + public static readonly OreInfo DullCopper = new OreInfo(1, 0x973, "Dull Copper"); + public static readonly OreInfo ShadowIron = new OreInfo(2, 0x966, "Shadow Iron"); + public static readonly OreInfo Copper = new OreInfo(3, 0x96D, "Copper"); + public static readonly OreInfo Bronze = new OreInfo(4, 0x972, "Bronze"); + public static readonly OreInfo Gold = new OreInfo(5, 0x8A5, "Gold"); + public static readonly OreInfo Agapite = new OreInfo(6, 0x979, "Agapite"); + public static readonly OreInfo Verite = new OreInfo(7, 0x89F, "Verite"); + public static readonly OreInfo Valorite = new OreInfo(8, 0x8AB, "Valorite"); - if (start == CraftResource.None) - return 0; + public OreInfo(int level, int hue, string name) + { + Level = level; + Hue = hue; + Name = name; + } - return resource - start; + public int Level { get; } + + public int Hue { get; } + + public string Name { get; } } - - /// - /// Returns the property of '' -or- 0 if an invalid resource was specified. - /// - public static int GetLocalizationNumber(CraftResource resource) - { - CraftResourceInfo info = GetInfo(resource); - - return info?.Number ?? 0; - } - - /// - /// Returns the property of '' -or- 0 if an invalid resource was specified. - /// - public static int GetHue(CraftResource resource) - { - CraftResourceInfo info = GetInfo(resource); - - return info?.Hue ?? 0; - } - - /// - /// Returns the property of '' -or- an empty string if the resource specified was invalid. - /// - public static string GetName(CraftResource resource) - { - CraftResourceInfo info = GetInfo(resource); - - return info == null ? string.Empty : info.Name; - } - - /// - /// Returns the value which represents '' -or- CraftResource.None if unable to convert. - /// - public static CraftResource GetFromOreInfo(OreInfo info) - { - if (info.Name.IndexOf("Spined") >= 0) - return CraftResource.SpinedLeather; - if (info.Name.IndexOf("Horned") >= 0) - return CraftResource.HornedLeather; - if (info.Name.IndexOf("Barbed") >= 0) - return CraftResource.BarbedLeather; - if (info.Name.IndexOf("Leather") >= 0) - return CraftResource.RegularLeather; - - if (info.Level == 0) - return CraftResource.Iron; - if (info.Level == 1) - return CraftResource.DullCopper; - if (info.Level == 2) - return CraftResource.ShadowIron; - if (info.Level == 3) - return CraftResource.Copper; - if (info.Level == 4) - return CraftResource.Bronze; - if (info.Level == 5) - return CraftResource.Gold; - if (info.Level == 6) - return CraftResource.Agapite; - if (info.Level == 7) - return CraftResource.Verite; - if (info.Level == 8) - return CraftResource.Valorite; - - return CraftResource.None; - } - - /// - /// Returns the value which represents '', using '' to help resolve leather OreInfo instances. - /// - public static CraftResource GetFromOreInfo(OreInfo info, ArmorMaterialType material) - { - if (material == ArmorMaterialType.Studded || material == ArmorMaterialType.Leather || material == ArmorMaterialType.Spined || - material == ArmorMaterialType.Horned || material == ArmorMaterialType.Barbed) - { - if (info.Level == 0) - return CraftResource.RegularLeather; - if (info.Level == 1) - return CraftResource.SpinedLeather; - if (info.Level == 2) - return CraftResource.HornedLeather; - if (info.Level == 3) - return CraftResource.BarbedLeather; - - return CraftResource.None; - } - - return GetFromOreInfo(info); - } - } - - // NOTE: This class is only for compatability with very old RunUO versions. - // No changes to it should be required for custom resources. - public class OreInfo - { - public static readonly OreInfo Iron = new OreInfo(0, 0x000, "Iron"); - public static readonly OreInfo DullCopper = new OreInfo(1, 0x973, "Dull Copper"); - public static readonly OreInfo ShadowIron = new OreInfo(2, 0x966, "Shadow Iron"); - public static readonly OreInfo Copper = new OreInfo(3, 0x96D, "Copper"); - public static readonly OreInfo Bronze = new OreInfo(4, 0x972, "Bronze"); - public static readonly OreInfo Gold = new OreInfo(5, 0x8A5, "Gold"); - public static readonly OreInfo Agapite = new OreInfo(6, 0x979, "Agapite"); - public static readonly OreInfo Verite = new OreInfo(7, 0x89F, "Verite"); - public static readonly OreInfo Valorite = new OreInfo(8, 0x8AB, "Valorite"); - - public OreInfo(int level, int hue, string name) - { - Level = level; - Hue = hue; - Name = name; - } - - public int Level { get; } - - public int Hue { get; } - - public string Name { get; } - } } diff --git a/Projects/UOContent/Misc/ServerList.cs b/Projects/UOContent/Misc/ServerList.cs index 55c13bec9..0c7e81408 100644 --- a/Projects/UOContent/Misc/ServerList.cs +++ b/Projects/UOContent/Misc/ServerList.cs @@ -4,169 +4,173 @@ using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; -using Server.Network; namespace Server.Misc { - public static class ServerList - { - /* - * The default setting for Address, a value of 'null', will use your local IP address. If all of your local IP addresses - * are private network addresses and AutoDetect is 'true' then RunUO will attempt to discover your public IP address - * for you automatically. - * - * If you do not plan on allowing clients outside of your LAN to connect, you can set AutoDetect to 'false' and leave - * Address set to 'null'. - * - * If your public IP address cannot be determined, you must change the value of Address to your public IP address - * manually to allow clients outside of your LAN to connect to your server. Address can be either an IP address or - * a hostname that will be resolved when RunUO starts. - * - * If you want players outside your LAN to be able to connect to your server and you are behind a router, you must also - * forward TCP port 2593 to your private IP address. The procedure for doing this varies by manufacturer but generally - * involves configuration of the router through your web browser. - * - * ServerList will direct connecting clients depending on both the address they are connecting from and the address and - * port they are connecting to. If it is determined that both ends of a connection are private IP addresses, ServerList - * will direct the client to the local private IP address. If a client is connecting to a local public IP address, they - * will be directed to whichever address and port they initially connected to. This allows multihomed servers to function - * properly and fully supports listening on multiple ports. If a client with a public IP address is connecting to a - * locally private address, the server will direct the client to either the AutoDetected IP address or the manually entered - * IP address or hostname, whichever is applicable. Loopback clients will be directed to loopback. - * - * If you would like to listen on additional ports (i.e. 22, 23, 80, for clients behind highly restrictive egress - * firewalls) or specific IP addresses you can do so by modifying the file SocketOptions.cs found in this directory. - */ - - public static string Address { get; private set; } - public static string ServerName { get; private set; } - - public static bool AutoDetect { get; private set; } - - private static IPAddress m_PublicAddress; - - public static void Initialize() + public static class ServerList { - Address = ServerConfiguration.GetOrUpdateSetting("serverListing.address", "(-null-)"); - AutoDetect = ServerConfiguration.GetOrUpdateSetting("serverListing.autoDetect", true); - ServerName = ServerConfiguration.GetOrUpdateSetting("serverListing.serverName", "ModernUO"); + private static IPAddress m_PublicAddress; + /* + * The default setting for Address, a value of 'null', will use your local IP address. If all of your local IP addresses + * are private network addresses and AutoDetect is 'true' then RunUO will attempt to discover your public IP address + * for you automatically. + * + * If you do not plan on allowing clients outside of your LAN to connect, you can set AutoDetect to 'false' and leave + * Address set to 'null'. + * + * If your public IP address cannot be determined, you must change the value of Address to your public IP address + * manually to allow clients outside of your LAN to connect to your server. Address can be either an IP address or + * a hostname that will be resolved when RunUO starts. + * + * If you want players outside your LAN to be able to connect to your server and you are behind a router, you must also + * forward TCP port 2593 to your private IP address. The procedure for doing this varies by manufacturer but generally + * involves configuration of the router through your web browser. + * + * ServerList will direct connecting clients depending on both the address they are connecting from and the address and + * port they are connecting to. If it is determined that both ends of a connection are private IP addresses, ServerList + * will direct the client to the local private IP address. If a client is connecting to a local public IP address, they + * will be directed to whichever address and port they initially connected to. This allows multihomed servers to function + * properly and fully supports listening on multiple ports. If a client with a public IP address is connecting to a + * locally private address, the server will direct the client to either the AutoDetected IP address or the manually entered + * IP address or hostname, whichever is applicable. Loopback clients will be directed to loopback. + * + * If you would like to listen on additional ports (i.e. 22, 23, 80, for clients behind highly restrictive egress + * firewalls) or specific IP addresses you can do so by modifying the file SocketOptions.cs found in this directory. + */ - if (Address == null) - { - if (AutoDetect) - AutoDetection(); - } - else - { - Resolve(Address, out m_PublicAddress); - } + public static string Address { get; private set; } + public static string ServerName { get; private set; } - EventSink.ServerList += EventSink_ServerList; - } + public static bool AutoDetect { get; private set; } - private static void EventSink_ServerList(ServerListEventArgs e) - { - try - { - NetState ns = e.State; - - IPEndPoint ipep = (IPEndPoint)ns.Connection.LocalEndPoint; - - IPAddress localAddress = ipep.Address; - int localPort = ipep.Port; - - if (IsPrivateNetwork(localAddress)) + public static void Initialize() { - ipep = (IPEndPoint)ns.Connection.RemoteEndPoint; - if (!IsPrivateNetwork(ipep.Address) && m_PublicAddress != null) - localAddress = m_PublicAddress; + Address = ServerConfiguration.GetOrUpdateSetting("serverListing.address", "(-null-)"); + AutoDetect = ServerConfiguration.GetOrUpdateSetting("serverListing.autoDetect", true); + ServerName = ServerConfiguration.GetOrUpdateSetting("serverListing.serverName", "ModernUO"); + + if (Address == null) + { + if (AutoDetect) + AutoDetection(); + } + else + { + Resolve(Address, out m_PublicAddress); + } + + EventSink.ServerList += EventSink_ServerList; } - e.AddServer(ServerName, new IPEndPoint(localAddress, localPort)); - } - catch (Exception er) - { - Console.WriteLine(er); - e.Rejected = true; - } + private static void EventSink_ServerList(ServerListEventArgs e) + { + try + { + var ns = e.State; + + var ipep = (IPEndPoint)ns.Connection.LocalEndPoint; + + var localAddress = ipep.Address; + var localPort = ipep.Port; + + if (IsPrivateNetwork(localAddress)) + { + ipep = (IPEndPoint)ns.Connection.RemoteEndPoint; + if (!IsPrivateNetwork(ipep.Address) && m_PublicAddress != null) + localAddress = m_PublicAddress; + } + + e.AddServer(ServerName, new IPEndPoint(localAddress, localPort)); + } + catch (Exception er) + { + Console.WriteLine(er); + e.Rejected = true; + } + } + + private static void AutoDetection() + { + if (!HasPublicIPAddress()) + { + Console.Write("ServerList: Auto-detecting public IP address..."); + m_PublicAddress = FindPublicAddress(); + + if (m_PublicAddress != null) + Console.WriteLine("done ({0})", m_PublicAddress); + else + Console.WriteLine("failed"); + } + } + + private static void Resolve(string addr, out IPAddress outValue) + { + if (IPAddress.TryParse(addr, out outValue)) + return; + + try + { + var iphe = Dns.GetHostEntry(addr); + + if (iphe.AddressList.Length > 0) + outValue = iphe.AddressList[^1]; + } + catch + { + // ignored + } + } + + private static bool HasPublicIPAddress() => + NetworkInterface.GetAllNetworkInterfaces() + .Select(adapter => adapter.GetIPProperties()) + .Any( + properties => properties.UnicastAddresses.Select(unicast => unicast.Address) + .Any( + ip => !IPAddress.IsLoopback(ip) && ip.AddressFamily != AddressFamily.InterNetworkV6 && + !IsPrivateNetwork(ip) + ) + ); + + // 10.0.0.0/8 + // 172.16.0.0/12 + // 192.168.0.0/16 + // 169.254.0.0/16 + // 100.64.0.0/10 RFC 6598 + private static bool IsPrivateNetwork(IPAddress ip) => + ip.AddressFamily != AddressFamily.InterNetworkV6 && + (Utility.IPMatch("192.168.*", ip) || + Utility.IPMatch("10.*", ip) || + Utility.IPMatch("172.16-31.*", ip) || + Utility.IPMatch("169.254.*", ip) || + Utility.IPMatch("100.64-127.*", ip)); + + private static IPAddress FindPublicAddress() + { + try + { + var req = WebRequest.Create("https://api.ipify.org"); + + req.Timeout = 15000; + + var res = req.GetResponse(); + + var s = res.GetResponseStream(); + + var sr = new StreamReader(s); + + var ip = IPAddress.Parse(sr.ReadLine() ?? ""); + + sr.Close(); + s.Close(); + res.Close(); + + return ip; + } + catch + { + return null; + } + } } - - private static void AutoDetection() - { - if (!HasPublicIPAddress()) - { - Console.Write("ServerList: Auto-detecting public IP address..."); - m_PublicAddress = FindPublicAddress(); - - if (m_PublicAddress != null) - Console.WriteLine("done ({0})", m_PublicAddress); - else - Console.WriteLine("failed"); - } - } - - private static void Resolve(string addr, out IPAddress outValue) - { - if (IPAddress.TryParse(addr, out outValue)) - return; - - try - { - IPHostEntry iphe = Dns.GetHostEntry(addr); - - if (iphe.AddressList.Length > 0) - outValue = iphe.AddressList[^1]; - } - catch - { - // ignored - } - } - - private static bool HasPublicIPAddress() => - NetworkInterface.GetAllNetworkInterfaces().Select(adapter => adapter.GetIPProperties()) - .Any(properties => properties.UnicastAddresses.Select(unicast => unicast.Address) - .Any(ip => !IPAddress.IsLoopback(ip) && ip.AddressFamily != AddressFamily.InterNetworkV6 && !IsPrivateNetwork(ip))); - - // 10.0.0.0/8 - // 172.16.0.0/12 - // 192.168.0.0/16 - // 169.254.0.0/16 - // 100.64.0.0/10 RFC 6598 - private static bool IsPrivateNetwork(IPAddress ip) => - ip.AddressFamily != AddressFamily.InterNetworkV6 && - (Utility.IPMatch("192.168.*", ip) || - Utility.IPMatch("10.*", ip) || - Utility.IPMatch("172.16-31.*", ip) || - Utility.IPMatch("169.254.*", ip) || - Utility.IPMatch("100.64-127.*", ip)); - - private static IPAddress FindPublicAddress() - { - try - { - WebRequest req = WebRequest.Create("https://api.ipify.org"); - - req.Timeout = 15000; - - WebResponse res = req.GetResponse(); - - Stream s = res.GetResponseStream(); - - StreamReader sr = new StreamReader(s); - - IPAddress ip = IPAddress.Parse(sr.ReadLine() ?? ""); - - sr.Close(); - s.Close(); - res.Close(); - - return ip; - } - catch - { - return null; - } - } - } } diff --git a/Projects/UOContent/Misc/ShardPoller.cs b/Projects/UOContent/Misc/ShardPoller.cs index cf6e0dda4..b2db1804b 100644 --- a/Projects/UOContent/Misc/ShardPoller.cs +++ b/Projects/UOContent/Misc/ShardPoller.cs @@ -8,599 +8,604 @@ using Server.Prompts; namespace Server.Misc { - public class ShardPoller : Item - { - private static readonly List m_ActivePollers = new List(); - - private bool m_Active; - private string m_Title; - - [Constructible(AccessLevel.Administrator)] - public ShardPoller() : base(0x1047) + public class ShardPoller : Item { - Duration = TimeSpan.FromHours(24.0); - Options = Array.Empty(); - Addresses = Array.Empty(); + private static readonly List m_ActivePollers = new List(); - Movable = false; - } + private bool m_Active; + private string m_Title; - public ShardPoller(Serial serial) : base(serial) - { - } - - public ShardPollOption[] Options { get; set; } - - public IPAddress[] Addresses { get; set; } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public string Title - { - get => m_Title; - set => m_Title = ShardPollPrompt.UrlToHref(value); - } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public TimeSpan Duration { get; set; } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public DateTime StartTime { get; set; } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public TimeSpan TimeRemaining - { - get - { - if (StartTime == DateTime.MinValue || !m_Active) - return TimeSpan.Zero; - - try + [Constructible(AccessLevel.Administrator)] + public ShardPoller() : base(0x1047) { - TimeSpan ts = StartTime + Duration - DateTime.UtcNow; + Duration = TimeSpan.FromHours(24.0); + Options = Array.Empty(); + Addresses = Array.Empty(); - if (ts < TimeSpan.Zero) - return TimeSpan.Zero; - - return ts; - } - catch - { - return TimeSpan.Zero; - } - } - } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public bool Active - { - get => m_Active; - set - { - if (m_Active == value) - return; - - m_Active = value; - - if (m_Active) - { - StartTime = DateTime.UtcNow; - m_ActivePollers.Add(this); - } - else - { - m_ActivePollers.Remove(this); - } - } - } - - public override string DefaultName => "shard poller"; - - public bool HasAlreadyVoted(NetState ns) - { - for (int i = 0; i < Options.Length; ++i) - if (Options[i].HasAlreadyVoted(ns)) - return true; - - return false; - } - - public void AddVote(NetState ns, ShardPollOption option) - { - option.AddVote(ns); - } - - public void RemoveOption(ShardPollOption option) - { - int index = Array.IndexOf(Options, option); - - if (index < 0) - return; - - ShardPollOption[] old = Options; - Options = new ShardPollOption[old.Length - 1]; - - for (int i = 0; i < index; ++i) - Options[i] = old[i]; - - for (int i = index; i < Options.Length; ++i) - Options[i] = old[i + 1]; - } - - public void AddOption(ShardPollOption option) - { - ShardPollOption[] old = Options; - Options = new ShardPollOption[old.Length + 1]; - - for (int i = 0; i < old.Length; ++i) - Options[i] = old[i]; - - Options[old.Length] = option; - } - - public static void Initialize() - { - EventSink.Login += EventSink_Login; - } - - private static void EventSink_Login(Mobile m) - { - if (m_ActivePollers.Count == 0) - return; - - Timer.DelayCall(TimeSpan.FromSeconds(1.0), EventSink_Login_Callback, m); - } - - private static void EventSink_Login_Callback(Mobile from) - { - NetState ns = from.NetState; - - if (ns == null) - return; - - ShardPollGump spg = null; - - for (int i = 0; i < m_ActivePollers.Count; ++i) - { - ShardPoller poller = m_ActivePollers[i]; - - if (poller.Deleted || !poller.Active) - continue; - - if (poller.TimeRemaining > TimeSpan.Zero) - { - if (poller.HasAlreadyVoted(ns)) - continue; - - if (spg == null) - { - spg = new ShardPollGump(from, poller, false, null); - from.SendGump(spg); - } - else - { - spg.QueuePoll(poller); - } - } - else - { - poller.Active = false; - } - } - } - - public override void OnDoubleClick(Mobile from) - { - if (from.AccessLevel >= AccessLevel.Administrator) - from.SendGump(new ShardPollGump(from, this, true, null)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Title); - writer.Write(Duration); - writer.Write(StartTime); - writer.Write(m_Active); - - writer.Write(Options.Length); - - for (int i = 0; i < Options.Length; ++i) - Options[i].Serialize(writer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Title = reader.ReadString(); - Duration = reader.ReadTimeSpan(); - StartTime = reader.ReadDateTime(); - m_Active = reader.ReadBool(); - - Options = new ShardPollOption[reader.ReadInt()]; - - for (int i = 0; i < Options.Length; ++i) - Options[i] = new ShardPollOption(reader); - - if (m_Active) - m_ActivePollers.Add(this); - - break; - } - } - } - - public override void OnDelete() - { - base.OnDelete(); - - Active = false; - } - } - - public class ShardPollOption - { - private string m_Title; - - public ShardPollOption(string title) - { - m_Title = title; - LineBreaks = GetBreaks(m_Title); - Voters = Array.Empty(); - } - - public ShardPollOption(IGenericReader reader) - { - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Title = reader.ReadString(); - LineBreaks = GetBreaks(m_Title); - - Voters = new IPAddress[reader.ReadInt()]; - - for (int i = 0; i < Voters.Length; ++i) - Voters[i] = Utility.Intern(reader.ReadIPAddress()); - - break; - } - } - } - - public string Title - { - get => m_Title; - set - { - m_Title = value; - LineBreaks = GetBreaks(m_Title); - } - } - - public int LineBreaks { get; private set; } - - public int Votes => Voters.Length; - public IPAddress[] Voters { get; set; } - - public bool HasAlreadyVoted(NetState ns) - { - if (ns == null) - return false; - - IPAddress ipAddress = ns.Address; - - for (int i = 0; i < Voters.Length; ++i) - if (Utility.IPMatchClassC(Voters[i], ipAddress)) - return true; - - return false; - } - - public void AddVote(NetState ns) - { - if (ns == null) - return; - - IPAddress[] old = Voters; - Voters = new IPAddress[old.Length + 1]; - - for (int i = 0; i < old.Length; ++i) - Voters[i] = old[i]; - - Voters[old.Length] = ns.Address; - } - - public int ComputeHeight() - { - int height = LineBreaks * 18; - - if (height > 30) - return height; - - return 30; - } - - public int GetBreaks(string title) - { - if (title == null) - return 1; - - int count = 0; - int index = -1; - - do - { - ++count; - index = title.IndexOf("
", index + 1); - } while (index >= 0); - - return count; - } - - public void Serialize(IGenericWriter writer) - { - writer.Write(0); // version - - writer.Write(m_Title); - - writer.Write(Voters.Length); - - for (int i = 0; i < Voters.Length; ++i) - writer.Write(Voters[i]); - } - } - - public class ShardPollGump : Gump - { - private const int LabelColor32 = 0xFFFFFF; - private readonly Mobile m_From; - private readonly ShardPoller m_Poller; - private Queue m_Polls; - - public ShardPollGump(Mobile from, ShardPoller poller, bool editing, Queue polls) : base(50, 50) - { - m_From = from; - m_Poller = poller; - Editing = editing; - m_Polls = polls; - - Closable = false; - - AddPage(0); - - int totalVotes = 0; - int totalOptionHeight = 0; - - for (int i = 0; i < poller.Options.Length; ++i) - { - totalVotes += poller.Options[i].Votes; - totalOptionHeight += poller.Options[i].ComputeHeight() + 5; - } - - bool isViewingResults = editing && poller.Active; - bool isCompleted = totalVotes > 0 && !poller.Active; - - if (editing && !isViewingResults) - totalOptionHeight += 35; - - int height = 115 + totalOptionHeight; - - AddBackground(1, 1, 398, height - 2, 3600); - AddAlphaRegion(16, 15, 369, height - 31); - - AddItem(308, 30, 0x1E5E); - - string title; - - if (editing) - title = isCompleted ? "Poll Completed" : "Poll Editor"; - else - title = "Shard Poll"; - - AddHtml(22, 22, 294, 20, Color(Center(title), LabelColor32)); - - if (editing) - { - AddHtml(22, 22, 294, 20, Color($"{totalVotes} total", LabelColor32)); - AddButton(287, 23, 0x2622, 0x2623, 2); - } - - AddHtml(22, 50, 294, 40, Color(poller.Title, 0x99CC66)); - - AddImageTiled(32, 88, 264, 1, 9107); - AddImageTiled(42, 90, 264, 1, 9157); - - int y = 100; - - for (int i = 0; i < poller.Options.Length; ++i) - { - ShardPollOption option = poller.Options[i]; - string text = option.Title; - - if (editing && totalVotes > 0) - { - double perc = option.Votes / (double)totalVotes; - - text = $"[{option.Votes}: {(int)(perc * 100)}%] {text}"; + Movable = false; } - int optHeight = option.ComputeHeight(); + public ShardPoller(Serial serial) : base(serial) + { + } - y += optHeight / 2; + public ShardPollOption[] Options { get; set; } - if (isViewingResults) - AddImage(24, y - 15, 0x25FE); - else - AddRadio(24, y - 15, 0x25F9, 0x25FC, false, 1 + i); + public IPAddress[] Addresses { get; set; } - AddHtml(60, y - 9 * option.LineBreaks, 250, 18 * option.LineBreaks, Color(text, LabelColor32)); + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public string Title + { + get => m_Title; + set => m_Title = ShardPollPrompt.UrlToHref(value); + } - y += optHeight / 2; - y += 5; - } + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public TimeSpan Duration { get; set; } - if (editing && !isViewingResults) - { - AddRadio(24, y + 15 - 15, 0x25F9, 0x25FC, false, 1 + poller.Options.Length); - AddHtml(60, y + 15 - 9, 250, 18, Color("Create new option.", 0x99CC66)); - } + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public DateTime StartTime { get; set; } - AddButton(314, height - 73, 247, 248, 1); - AddButton(314, height - 47, 242, 241, 0); - } - - public bool Editing { get; } - - public void QueuePoll(ShardPoller poller) - { - m_Polls ??= new Queue(4); - - m_Polls.Enqueue(poller); - } - - public string Center(string text) => $"
{text}
"; - - public string Color(string text, int color) => $"{text}"; - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (m_Polls?.Count > 0) - { - ShardPoller shardPoller = m_Polls.Dequeue(); - - if (shardPoller != null) - Timer.DelayCall(TimeSpan.FromSeconds(1.0), - data => + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public TimeSpan TimeRemaining + { + get { - var (mobile, poller, polls) = data; - m_From.SendGump(new ShardPollGump(mobile, poller, false, polls)); - }, (m_From, shardPoller, m_Polls)); - } + if (StartTime == DateTime.MinValue || !m_Active) + return TimeSpan.Zero; - if (info.ButtonID == 1) - { - int[] switches = info.Switches; + try + { + var ts = StartTime + Duration - DateTime.UtcNow; - if (switches.Length == 0) - return; + if (ts < TimeSpan.Zero) + return TimeSpan.Zero; - int switched = switches[0] - 1; - ShardPollOption opt = null; - - if (switched >= 0 && switched < m_Poller.Options.Length) - opt = m_Poller.Options[switched]; - - if (opt == null && !Editing) - return; - - if (Editing) - { - if (!m_Poller.Active) - { - m_From.SendMessage("Enter a title for the option. Escape to cancel.{0}", - opt == null ? "" : " Use \"DEL\" to delete."); - m_From.Prompt = new ShardPollPrompt(m_Poller, opt); - } - else - { - m_From.SendMessage("You may not edit an active poll. Deactivate it first."); - m_From.SendGump(new ShardPollGump(m_From, m_Poller, Editing, m_Polls)); - } + return ts; + } + catch + { + return TimeSpan.Zero; + } + } } - else + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public bool Active { - if (!m_Poller.Active) - m_From.SendMessage("The poll has been deactivated."); - else if (m_Poller.HasAlreadyVoted(sender)) - m_From.SendMessage("You have already voted on this poll."); - else - m_Poller.AddVote(sender, opt); + get => m_Active; + set + { + if (m_Active == value) + return; + + m_Active = value; + + if (m_Active) + { + StartTime = DateTime.UtcNow; + m_ActivePollers.Add(this); + } + else + { + m_ActivePollers.Remove(this); + } + } + } + + public override string DefaultName => "shard poller"; + + public bool HasAlreadyVoted(NetState ns) + { + for (var i = 0; i < Options.Length; ++i) + if (Options[i].HasAlreadyVoted(ns)) + return true; + + return false; + } + + public void AddVote(NetState ns, ShardPollOption option) + { + option.AddVote(ns); + } + + public void RemoveOption(ShardPollOption option) + { + var index = Array.IndexOf(Options, option); + + if (index < 0) + return; + + var old = Options; + Options = new ShardPollOption[old.Length - 1]; + + for (var i = 0; i < index; ++i) + Options[i] = old[i]; + + for (var i = index; i < Options.Length; ++i) + Options[i] = old[i + 1]; + } + + public void AddOption(ShardPollOption option) + { + var old = Options; + Options = new ShardPollOption[old.Length + 1]; + + for (var i = 0; i < old.Length; ++i) + Options[i] = old[i]; + + Options[old.Length] = option; + } + + public static void Initialize() + { + EventSink.Login += EventSink_Login; + } + + private static void EventSink_Login(Mobile m) + { + if (m_ActivePollers.Count == 0) + return; + + Timer.DelayCall(TimeSpan.FromSeconds(1.0), EventSink_Login_Callback, m); + } + + private static void EventSink_Login_Callback(Mobile from) + { + var ns = from.NetState; + + if (ns == null) + return; + + ShardPollGump spg = null; + + for (var i = 0; i < m_ActivePollers.Count; ++i) + { + var poller = m_ActivePollers[i]; + + if (poller.Deleted || !poller.Active) + continue; + + if (poller.TimeRemaining > TimeSpan.Zero) + { + if (poller.HasAlreadyVoted(ns)) + continue; + + if (spg == null) + { + spg = new ShardPollGump(from, poller, false, null); + from.SendGump(spg); + } + else + { + spg.QueuePoll(poller); + } + } + else + { + poller.Active = false; + } + } + } + + public override void OnDoubleClick(Mobile from) + { + if (from.AccessLevel >= AccessLevel.Administrator) + from.SendGump(new ShardPollGump(from, this, true, null)); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Title); + writer.Write(Duration); + writer.Write(StartTime); + writer.Write(m_Active); + + writer.Write(Options.Length); + + for (var i = 0; i < Options.Length; ++i) + Options[i].Serialize(writer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Title = reader.ReadString(); + Duration = reader.ReadTimeSpan(); + StartTime = reader.ReadDateTime(); + m_Active = reader.ReadBool(); + + Options = new ShardPollOption[reader.ReadInt()]; + + for (var i = 0; i < Options.Length; ++i) + Options[i] = new ShardPollOption(reader); + + if (m_Active) + m_ActivePollers.Add(this); + + break; + } + } + } + + public override void OnDelete() + { + base.OnDelete(); + + Active = false; } - } - else if (info.ButtonID == 2 && Editing) - { - m_From.SendGump(new ShardPollGump(m_From, m_Poller, Editing, m_Polls)); - m_From.SendGump(new PropertiesGump(m_From, m_Poller)); - } } - } - public class ShardPollPrompt : Prompt - { - private static readonly Regex m_UrlRegex = - new Regex(@"\[url(?:=(.*?))?\](.*?)\[/url\]", RegexOptions.IgnoreCase | RegexOptions.Compiled); - - private readonly ShardPollOption m_Option; - private readonly ShardPoller m_Poller; - - public ShardPollPrompt(ShardPoller poller, ShardPollOption opt) + public class ShardPollOption { - m_Poller = poller; - m_Option = opt; + private string m_Title; + + public ShardPollOption(string title) + { + m_Title = title; + LineBreaks = GetBreaks(m_Title); + Voters = Array.Empty(); + } + + public ShardPollOption(IGenericReader reader) + { + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Title = reader.ReadString(); + LineBreaks = GetBreaks(m_Title); + + Voters = new IPAddress[reader.ReadInt()]; + + for (var i = 0; i < Voters.Length; ++i) + Voters[i] = Utility.Intern(reader.ReadIPAddress()); + + break; + } + } + } + + public string Title + { + get => m_Title; + set + { + m_Title = value; + LineBreaks = GetBreaks(m_Title); + } + } + + public int LineBreaks { get; private set; } + + public int Votes => Voters.Length; + public IPAddress[] Voters { get; set; } + + public bool HasAlreadyVoted(NetState ns) + { + if (ns == null) + return false; + + var ipAddress = ns.Address; + + for (var i = 0; i < Voters.Length; ++i) + if (Utility.IPMatchClassC(Voters[i], ipAddress)) + return true; + + return false; + } + + public void AddVote(NetState ns) + { + if (ns == null) + return; + + var old = Voters; + Voters = new IPAddress[old.Length + 1]; + + for (var i = 0; i < old.Length; ++i) + Voters[i] = old[i]; + + Voters[old.Length] = ns.Address; + } + + public int ComputeHeight() + { + var height = LineBreaks * 18; + + if (height > 30) + return height; + + return 30; + } + + public int GetBreaks(string title) + { + if (title == null) + return 1; + + var count = 0; + var index = -1; + + do + { + ++count; + index = title.IndexOf("
", index + 1); + } while (index >= 0); + + return count; + } + + public void Serialize(IGenericWriter writer) + { + writer.Write(0); // version + + writer.Write(m_Title); + + writer.Write(Voters.Length); + + for (var i = 0; i < Voters.Length; ++i) + writer.Write(Voters[i]); + } } - public override void OnCancel(Mobile from) + public class ShardPollGump : Gump { - from.SendGump(new ShardPollGump(from, m_Poller, true, null)); + private const int LabelColor32 = 0xFFFFFF; + private readonly Mobile m_From; + private readonly ShardPoller m_Poller; + private Queue m_Polls; + + public ShardPollGump(Mobile from, ShardPoller poller, bool editing, Queue polls) : base(50, 50) + { + m_From = from; + m_Poller = poller; + Editing = editing; + m_Polls = polls; + + Closable = false; + + AddPage(0); + + var totalVotes = 0; + var totalOptionHeight = 0; + + for (var i = 0; i < poller.Options.Length; ++i) + { + totalVotes += poller.Options[i].Votes; + totalOptionHeight += poller.Options[i].ComputeHeight() + 5; + } + + var isViewingResults = editing && poller.Active; + var isCompleted = totalVotes > 0 && !poller.Active; + + if (editing && !isViewingResults) + totalOptionHeight += 35; + + var height = 115 + totalOptionHeight; + + AddBackground(1, 1, 398, height - 2, 3600); + AddAlphaRegion(16, 15, 369, height - 31); + + AddItem(308, 30, 0x1E5E); + + string title; + + if (editing) + title = isCompleted ? "Poll Completed" : "Poll Editor"; + else + title = "Shard Poll"; + + AddHtml(22, 22, 294, 20, Color(Center(title), LabelColor32)); + + if (editing) + { + AddHtml(22, 22, 294, 20, Color($"{totalVotes} total", LabelColor32)); + AddButton(287, 23, 0x2622, 0x2623, 2); + } + + AddHtml(22, 50, 294, 40, Color(poller.Title, 0x99CC66)); + + AddImageTiled(32, 88, 264, 1, 9107); + AddImageTiled(42, 90, 264, 1, 9157); + + var y = 100; + + for (var i = 0; i < poller.Options.Length; ++i) + { + var option = poller.Options[i]; + var text = option.Title; + + if (editing && totalVotes > 0) + { + var perc = option.Votes / (double)totalVotes; + + text = $"[{option.Votes}: {(int)(perc * 100)}%] {text}"; + } + + var optHeight = option.ComputeHeight(); + + y += optHeight / 2; + + if (isViewingResults) + AddImage(24, y - 15, 0x25FE); + else + AddRadio(24, y - 15, 0x25F9, 0x25FC, false, 1 + i); + + AddHtml(60, y - 9 * option.LineBreaks, 250, 18 * option.LineBreaks, Color(text, LabelColor32)); + + y += optHeight / 2; + y += 5; + } + + if (editing && !isViewingResults) + { + AddRadio(24, y + 15 - 15, 0x25F9, 0x25FC, false, 1 + poller.Options.Length); + AddHtml(60, y + 15 - 9, 250, 18, Color("Create new option.", 0x99CC66)); + } + + AddButton(314, height - 73, 247, 248, 1); + AddButton(314, height - 47, 242, 241, 0); + } + + public bool Editing { get; } + + public void QueuePoll(ShardPoller poller) + { + m_Polls ??= new Queue(4); + + m_Polls.Enqueue(poller); + } + + public string Center(string text) => $"
{text}
"; + + public string Color(string text, int color) => $"{text}"; + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_Polls?.Count > 0) + { + var shardPoller = m_Polls.Dequeue(); + + if (shardPoller != null) + Timer.DelayCall( + TimeSpan.FromSeconds(1.0), + data => + { + var (mobile, poller, polls) = data; + m_From.SendGump(new ShardPollGump(mobile, poller, false, polls)); + }, + (m_From, shardPoller, m_Polls) + ); + } + + if (info.ButtonID == 1) + { + var switches = info.Switches; + + if (switches.Length == 0) + return; + + var switched = switches[0] - 1; + ShardPollOption opt = null; + + if (switched >= 0 && switched < m_Poller.Options.Length) + opt = m_Poller.Options[switched]; + + if (opt == null && !Editing) + return; + + if (Editing) + { + if (!m_Poller.Active) + { + m_From.SendMessage( + "Enter a title for the option. Escape to cancel.{0}", + opt == null ? "" : " Use \"DEL\" to delete." + ); + m_From.Prompt = new ShardPollPrompt(m_Poller, opt); + } + else + { + m_From.SendMessage("You may not edit an active poll. Deactivate it first."); + m_From.SendGump(new ShardPollGump(m_From, m_Poller, Editing, m_Polls)); + } + } + else + { + if (!m_Poller.Active) + m_From.SendMessage("The poll has been deactivated."); + else if (m_Poller.HasAlreadyVoted(sender)) + m_From.SendMessage("You have already voted on this poll."); + else + m_Poller.AddVote(sender, opt); + } + } + else if (info.ButtonID == 2 && Editing) + { + m_From.SendGump(new ShardPollGump(m_From, m_Poller, Editing, m_Polls)); + m_From.SendGump(new PropertiesGump(m_From, m_Poller)); + } + } } - private static string UrlRegex_Match(Match m) + public class ShardPollPrompt : Prompt { - if (m.Groups[1].Success) - { - if (m.Groups[2].Success) - return $"{m.Groups[2].Value}"; - } - else if (m.Groups[2].Success) - { - return $"{m.Groups[2].Value}"; - } + private static readonly Regex m_UrlRegex = + new Regex(@"\[url(?:=(.*?))?\](.*?)\[/url\]", RegexOptions.IgnoreCase | RegexOptions.Compiled); - return m.Value; + private readonly ShardPollOption m_Option; + private readonly ShardPoller m_Poller; + + public ShardPollPrompt(ShardPoller poller, ShardPollOption opt) + { + m_Poller = poller; + m_Option = opt; + } + + public override void OnCancel(Mobile from) + { + from.SendGump(new ShardPollGump(from, m_Poller, true, null)); + } + + private static string UrlRegex_Match(Match m) + { + if (m.Groups[1].Success) + { + if (m.Groups[2].Success) + return $"{m.Groups[2].Value}"; + } + else if (m.Groups[2].Success) + { + return $"{m.Groups[2].Value}"; + } + + return m.Value; + } + + public static string UrlToHref(string text) + { + if (text == null) + return null; + + return m_UrlRegex.Replace(text, UrlRegex_Match); + } + + public override void OnResponse(Mobile from, string text) + { + if (m_Poller.Active) + { + from.SendMessage("You may not edit an active poll. Deactivate it first."); + } + else if (text == "DEL") + { + if (m_Option != null) + m_Poller.RemoveOption(m_Option); + } + else + { + text = UrlToHref(text); + + if (m_Option == null) + m_Poller.AddOption(new ShardPollOption(text)); + else + m_Option.Title = text; + } + + from.SendGump(new ShardPollGump(from, m_Poller, true, null)); + } } - - public static string UrlToHref(string text) - { - if (text == null) - return null; - - return m_UrlRegex.Replace(text, UrlRegex_Match); - } - - public override void OnResponse(Mobile from, string text) - { - if (m_Poller.Active) - { - from.SendMessage("You may not edit an active poll. Deactivate it first."); - } - else if (text == "DEL") - { - if (m_Option != null) - m_Poller.RemoveOption(m_Option); - } - else - { - text = UrlToHref(text); - - if (m_Option == null) - m_Poller.AddOption(new ShardPollOption(text)); - else - m_Option.Title = text; - } - - from.SendGump(new ShardPollGump(from, m_Poller, true, null)); - } - } } diff --git a/Projects/UOContent/Misc/ShrinkTable.cs b/Projects/UOContent/Misc/ShrinkTable.cs index dc15659fb..13be4826e 100644 --- a/Projects/UOContent/Misc/ShrinkTable.cs +++ b/Projects/UOContent/Misc/ShrinkTable.cs @@ -1,75 +1,76 @@ +using System; using System.IO; namespace Server { - public class ShrinkTable - { - public const int DefaultItemID = 0x1870; // Yellow virtue stone - - private static int[] m_Table; - - public static int Lookup(Mobile m) => Lookup(m.Body.BodyID, DefaultItemID); - - public static int Lookup(int body) => Lookup(body, DefaultItemID); - - public static int Lookup(Mobile m, int defaultValue) => Lookup(m.Body.BodyID, defaultValue); - - public static int Lookup(int body, int defaultValue) + public class ShrinkTable { - if (m_Table == null) - Load(); + public const int DefaultItemID = 0x1870; // Yellow virtue stone - int val = 0; + private static int[] m_Table; - if (body >= 0 && body < m_Table!.Length) - val = m_Table[body]; + public static int Lookup(Mobile m) => Lookup(m.Body.BodyID, DefaultItemID); - if (val == 0) - val = defaultValue; + public static int Lookup(int body) => Lookup(body, DefaultItemID); - return val; - } + public static int Lookup(Mobile m, int defaultValue) => Lookup(m.Body.BodyID, defaultValue); - private static void Load() - { - string path = Path.Combine(Core.BaseDirectory, "Data/shrink.cfg"); - - if (!File.Exists(path)) - { - m_Table = System.Array.Empty(); - return; - } - - m_Table = new int[1000]; - - using StreamReader ip = new StreamReader(path); - string line; - - while ((line = ip.ReadLine()) != null) - { - line = line.Trim(); - - if (line.Length == 0 || line.StartsWith("#")) - continue; - - try + public static int Lookup(int body, int defaultValue) { - string[] split = line.Split('\t'); + if (m_Table == null) + Load(); - if (split.Length >= 2) - { - int body = Utility.ToInt32(split[0]); - int item = Utility.ToInt32(split[1]); + var val = 0; - if (body >= 0 && body < m_Table.Length) - m_Table[body] = item; - } + if (body >= 0 && body < m_Table!.Length) + val = m_Table[body]; + + if (val == 0) + val = defaultValue; + + return val; } - catch + + private static void Load() { - // ignored + var path = Path.Combine(Core.BaseDirectory, "Data/shrink.cfg"); + + if (!File.Exists(path)) + { + m_Table = Array.Empty(); + return; + } + + m_Table = new int[1000]; + + using var ip = new StreamReader(path); + string line; + + while ((line = ip.ReadLine()) != null) + { + line = line.Trim(); + + if (line.Length == 0 || line.StartsWith("#")) + continue; + + try + { + var split = line.Split('\t'); + + if (split.Length >= 2) + { + var body = Utility.ToInt32(split[0]); + var item = Utility.ToInt32(split[1]); + + if (body >= 0 && body < m_Table.Length) + m_Table[body] = item; + } + } + catch + { + // ignored + } + } } - } } - } } diff --git a/Projects/UOContent/Misc/SkillCheck.cs b/Projects/UOContent/Misc/SkillCheck.cs index 22670fb1e..e458e7900 100644 --- a/Projects/UOContent/Misc/SkillCheck.cs +++ b/Projects/UOContent/Misc/SkillCheck.cs @@ -5,391 +5,394 @@ using Server.Regions; namespace Server.Misc { - public class SkillCheck - { - public enum Stat + public class SkillCheck { - Str, - Dex, - Int - } + public enum Stat + { + Str, + Dex, + Int + } - public const int Allowance = 3; // How many times may we use the same location/target for gain + public const int Allowance = 3; // How many times may we use the same location/target for gain - private const int - LocationSize = 5; // The size of eeach location, make this smaller so players dont have to move as far + private const int + LocationSize = 5; // The size of eeach location, make this smaller so players dont have to move as far - private static readonly bool AntiMacroCode = !Core.ML; // Change this to false to disable anti-macro code + private static readonly bool AntiMacroCode = !Core.ML; // Change this to false to disable anti-macro code - public static TimeSpan AntiMacroExpire = TimeSpan.FromMinutes(5.0); // How long do we remember targets/locations? + public static TimeSpan AntiMacroExpire = TimeSpan.FromMinutes(5.0); // How long do we remember targets/locations? - private static readonly bool[] UseAntiMacro = - { - // true if this skill uses the anti-macro code, false if it does not - false, // Alchemy = 0, - true, // Anatomy = 1, - true, // AnimalLore = 2, - true, // ItemID = 3, - true, // ArmsLore = 4, - false, // Parry = 5, - true, // Begging = 6, - false, // Blacksmith = 7, - false, // Fletching = 8, - true, // Peacemaking = 9, - true, // Camping = 10, - false, // Carpentry = 11, - false, // Cartography = 12, - false, // Cooking = 13, - true, // DetectHidden = 14, - true, // Discordance = 15, - true, // EvalInt = 16, - true, // Healing = 17, - true, // Fishing = 18, - true, // Forensics = 19, - true, // Herding = 20, - true, // Hiding = 21, - true, // Provocation = 22, - false, // Inscribe = 23, - true, // Lockpicking = 24, - true, // Magery = 25, - true, // MagicResist = 26, - false, // Tactics = 27, - true, // Snooping = 28, - true, // Musicianship = 29, - true, // Poisoning = 30, - false, // Archery = 31, - true, // SpiritSpeak = 32, - true, // Stealing = 33, - false, // Tailoring = 34, - true, // AnimalTaming = 35, - true, // TasteID = 36, - false, // Tinkering = 37, - true, // Tracking = 38, - true, // Veterinary = 39, - false, // Swords = 40, - false, // Macing = 41, - false, // Fencing = 42, - false, // Wrestling = 43, - true, // Lumberjacking = 44, - true, // Mining = 45, - true, // Meditation = 46, - true, // Stealth = 47, - true, // RemoveTrap = 48, - true, // Necromancy = 49, - false, // Focus = 50, - true, // Chivalry = 51 - true, // Bushido = 52 - true, // Ninjitsu = 53 - true // Spellweaving - }; + private static readonly bool[] UseAntiMacro = + { + // true if this skill uses the anti-macro code, false if it does not + false, // Alchemy = 0, + true, // Anatomy = 1, + true, // AnimalLore = 2, + true, // ItemID = 3, + true, // ArmsLore = 4, + false, // Parry = 5, + true, // Begging = 6, + false, // Blacksmith = 7, + false, // Fletching = 8, + true, // Peacemaking = 9, + true, // Camping = 10, + false, // Carpentry = 11, + false, // Cartography = 12, + false, // Cooking = 13, + true, // DetectHidden = 14, + true, // Discordance = 15, + true, // EvalInt = 16, + true, // Healing = 17, + true, // Fishing = 18, + true, // Forensics = 19, + true, // Herding = 20, + true, // Hiding = 21, + true, // Provocation = 22, + false, // Inscribe = 23, + true, // Lockpicking = 24, + true, // Magery = 25, + true, // MagicResist = 26, + false, // Tactics = 27, + true, // Snooping = 28, + true, // Musicianship = 29, + true, // Poisoning = 30, + false, // Archery = 31, + true, // SpiritSpeak = 32, + true, // Stealing = 33, + false, // Tailoring = 34, + true, // AnimalTaming = 35, + true, // TasteID = 36, + false, // Tinkering = 37, + true, // Tracking = 38, + true, // Veterinary = 39, + false, // Swords = 40, + false, // Macing = 41, + false, // Fencing = 42, + false, // Wrestling = 43, + true, // Lumberjacking = 44, + true, // Mining = 45, + true, // Meditation = 46, + true, // Stealth = 47, + true, // RemoveTrap = 48, + true, // Necromancy = 49, + false, // Focus = 50, + true, // Chivalry = 51 + true, // Bushido = 52 + true, // Ninjitsu = 53 + true // Spellweaving + }; - private static readonly TimeSpan m_StatGainDelay = TimeSpan.FromMinutes(Core.ML ? 0.05 : 15); - private static readonly TimeSpan m_PetStatGainDelay = TimeSpan.FromMinutes(5.0); + private static readonly TimeSpan m_StatGainDelay = TimeSpan.FromMinutes(Core.ML ? 0.05 : 15); + private static readonly TimeSpan m_PetStatGainDelay = TimeSpan.FromMinutes(5.0); - public static void Initialize() - { - Mobile.SkillCheckLocationHandler = Mobile_SkillCheckLocation; - Mobile.SkillCheckDirectLocationHandler = Mobile_SkillCheckDirectLocation; + public static void Initialize() + { + Mobile.SkillCheckLocationHandler = Mobile_SkillCheckLocation; + Mobile.SkillCheckDirectLocationHandler = Mobile_SkillCheckDirectLocation; - Mobile.SkillCheckTargetHandler = Mobile_SkillCheckTarget; - Mobile.SkillCheckDirectTargetHandler = Mobile_SkillCheckDirectTarget; - } + Mobile.SkillCheckTargetHandler = Mobile_SkillCheckTarget; + Mobile.SkillCheckDirectTargetHandler = Mobile_SkillCheckDirectTarget; + } - public static bool Mobile_SkillCheckLocation(Mobile from, SkillName skillName, double minSkill, double maxSkill) - { - Skill skill = from.Skills[skillName]; + public static bool Mobile_SkillCheckLocation(Mobile from, SkillName skillName, double minSkill, double maxSkill) + { + var skill = from.Skills[skillName]; - if (skill == null) - return false; + if (skill == null) + return false; - double value = skill.Value; + var value = skill.Value; - if (value < minSkill) - return false; // Too difficult - if (value >= maxSkill) - return true; // No challenge + if (value < minSkill) + return false; // Too difficult + if (value >= maxSkill) + return true; // No challenge - double chance = (value - minSkill) / (maxSkill - minSkill); + var chance = (value - minSkill) / (maxSkill - minSkill); - Point2D loc = new Point2D(from.Location.X / LocationSize, from.Location.Y / LocationSize); - return CheckSkill(from, skill, loc, chance); - } + var loc = new Point2D(from.Location.X / LocationSize, from.Location.Y / LocationSize); + return CheckSkill(from, skill, loc, chance); + } - public static bool Mobile_SkillCheckDirectLocation(Mobile from, SkillName skillName, double chance) - { - Skill skill = from.Skills[skillName]; + public static bool Mobile_SkillCheckDirectLocation(Mobile from, SkillName skillName, double chance) + { + var skill = from.Skills[skillName]; - if (skill == null) - return false; + if (skill == null) + return false; - if (chance < 0.0) - return false; // Too difficult - if (chance >= 1.0) - return true; // No challenge + if (chance < 0.0) + return false; // Too difficult + if (chance >= 1.0) + return true; // No challenge - Point2D loc = new Point2D(from.Location.X / LocationSize, from.Location.Y / LocationSize); - return CheckSkill(from, skill, loc, chance); - } + var loc = new Point2D(from.Location.X / LocationSize, from.Location.Y / LocationSize); + return CheckSkill(from, skill, loc, chance); + } - public static bool CheckSkill(Mobile from, Skill skill, object amObj, double chance) - { - if (from.Skills.Cap == 0) - return false; + public static bool CheckSkill(Mobile from, Skill skill, object amObj, double chance) + { + if (from.Skills.Cap == 0) + return false; - bool success = chance >= Utility.RandomDouble(); - double gc = (double)(from.Skills.Cap - from.Skills.Total) / from.Skills.Cap; - gc += (skill.Cap - skill.Base) / skill.Cap; - gc /= 2; + var success = chance >= Utility.RandomDouble(); + var gc = (double)(from.Skills.Cap - from.Skills.Total) / from.Skills.Cap; + gc += (skill.Cap - skill.Base) / skill.Cap; + gc /= 2; - gc += (1.0 - chance) * (success ? 0.5 : Core.AOS ? 0.0 : 0.2); - gc /= 2; + gc += (1.0 - chance) * (success ? 0.5 : + Core.AOS ? 0.0 : 0.2); + gc /= 2; - gc *= skill.Info.GainFactor; + gc *= skill.Info.GainFactor; - if (gc < 0.01) - gc = 0.01; + if (gc < 0.01) + gc = 0.01; - if (from is BaseCreature creature && creature.Controlled) - gc *= 2; - - if (from.Alive && ((gc >= Utility.RandomDouble() && AllowGain(from, skill, amObj)) || skill.Base < 10.0)) - Gain(from, skill); - - return success; - } - - public static bool Mobile_SkillCheckTarget(Mobile from, SkillName skillName, object target, double minSkill, - double maxSkill) - { - Skill skill = from.Skills[skillName]; - - if (skill == null) - return false; - - double value = skill.Value; - - if (value < minSkill) - return false; // Too difficult - if (value >= maxSkill) - return true; // No challenge - - double chance = (value - minSkill) / (maxSkill - minSkill); - - return CheckSkill(from, skill, target, chance); - } - - public static bool Mobile_SkillCheckDirectTarget(Mobile from, SkillName skillName, object target, double chance) - { - Skill skill = from.Skills[skillName]; - - if (skill == null) - return false; - - if (chance < 0.0) - return false; // Too difficult - if (chance >= 1.0) - return true; // No challenge - - return CheckSkill(from, skill, target, chance); - } - - private static bool AllowGain(Mobile from, Skill skill, object obj) - { - if (Core.AOS && Faction.InSkillLoss(from)) // Changed some time between the introduction of AoS and SE. - return false; - - if (AntiMacroCode && from is PlayerMobile mobile && UseAntiMacro[skill.Info.SkillID]) - return mobile.AntiMacroCheck(skill, obj); - - return true; - } - - public static void Gain(Mobile from, Skill skill) - { - if (from.Region.IsPartOf()) - return; - - if (from is BaseCreature creature && creature.IsDeadPet) - return; - - if (skill.SkillName == SkillName.Focus && from is BaseCreature) - return; - - if (skill.Base < skill.Cap && skill.Lock == SkillLock.Up) - { - int toGain = 1; - - if (skill.Base <= 10.0) - toGain = Utility.Random(4) + 1; - - Skills skills = from.Skills; - - if (from.Player && skills.Total / skills.Cap >= Utility.RandomDouble()) - for (int i = 0; i < skills.Length; ++i) - { - Skill toLower = skills[i]; - - if (toLower != skill && toLower.Lock == SkillLock.Down && toLower.BaseFixedPoint >= toGain) - { - toLower.BaseFixedPoint -= toGain; - break; - } - } - - if (from is PlayerMobile pm && skill.SkillName == pm.AcceleratedSkill && - pm.AcceleratedStart > DateTime.UtcNow) - toGain *= Utility.RandomMinMax(2, 5); - - if (!from.Player || skills.Total + toGain <= skills.Cap) skill.BaseFixedPoint += toGain; - } - - if (skill.Lock == SkillLock.Up) - { - SkillInfo info = skill.Info; - - if (from.StrLock == StatLockType.Up && info.StrGain / 33.3 > Utility.RandomDouble()) - GainStat(from, Stat.Str); - else if (from.DexLock == StatLockType.Up && info.DexGain / 33.3 > Utility.RandomDouble()) - GainStat(from, Stat.Dex); - else if (from.IntLock == StatLockType.Up && info.IntGain / 33.3 > Utility.RandomDouble()) - GainStat(from, Stat.Int); - } - } - - public static bool CanLower(Mobile from, Stat stat) - { - return stat switch - { - Stat.Str => from.StrLock == StatLockType.Down && from.RawStr > 10, - Stat.Dex => from.DexLock == StatLockType.Down && from.RawDex > 10, - Stat.Int => from.IntLock == StatLockType.Down && from.RawInt > 10, - _ => false - }; - } - - public static bool CanRaise(Mobile from, Stat stat) - { - if (!(from is BaseCreature creature && creature.Controlled)) - if (from.RawStatTotal >= from.StatCap) - return false; - - return stat switch - { - Stat.Str => from.StrLock == StatLockType.Up && from.RawStr < 125, - Stat.Dex => from.DexLock == StatLockType.Up && from.RawDex < 125, - Stat.Int => from.IntLock == StatLockType.Up && from.RawInt < 125, - _ => false - }; - } - - public static void IncreaseStat(Mobile from, Stat stat, bool atrophy) - { - atrophy = atrophy || from.RawStatTotal >= from.StatCap; - - switch (stat) - { - case Stat.Str: - { - if (atrophy) - { - if (CanLower(from, Stat.Dex) && (from.RawDex < from.RawInt || !CanLower(from, Stat.Int))) - --from.RawDex; - else if (CanLower(from, Stat.Int)) - --from.RawInt; - } - - if (CanRaise(from, Stat.Str)) - ++from.RawStr; - - break; - } - case Stat.Dex: - { - if (atrophy) - { - if (CanLower(from, Stat.Str) && (from.RawStr < from.RawInt || !CanLower(from, Stat.Int))) - --from.RawStr; - else if (CanLower(from, Stat.Int)) - --from.RawInt; - } - - if (CanRaise(from, Stat.Dex)) - ++from.RawDex; - - break; - } - case Stat.Int: - { - if (atrophy) - { - if (CanLower(from, Stat.Str) && (from.RawStr < from.RawDex || !CanLower(from, Stat.Dex))) - --from.RawStr; - else if (CanLower(from, Stat.Dex)) - --from.RawDex; - } - - if (CanRaise(from, Stat.Int)) - ++from.RawInt; - - break; - } - } - } - - public static void GainStat(Mobile from, Stat stat) - { - switch (stat) - { - case Stat.Str: - { if (from is BaseCreature creature && creature.Controlled) - { - if (creature.LastStrGain + m_PetStatGainDelay >= DateTime.UtcNow) + gc *= 2; + + if (from.Alive && (gc >= Utility.RandomDouble() && AllowGain(@from, skill, amObj) || skill.Base < 10.0)) + Gain(from, skill); + + return success; + } + + public static bool Mobile_SkillCheckTarget( + Mobile from, SkillName skillName, object target, double minSkill, + double maxSkill + ) + { + var skill = from.Skills[skillName]; + + if (skill == null) + return false; + + var value = skill.Value; + + if (value < minSkill) + return false; // Too difficult + if (value >= maxSkill) + return true; // No challenge + + var chance = (value - minSkill) / (maxSkill - minSkill); + + return CheckSkill(from, skill, target, chance); + } + + public static bool Mobile_SkillCheckDirectTarget(Mobile from, SkillName skillName, object target, double chance) + { + var skill = from.Skills[skillName]; + + if (skill == null) + return false; + + if (chance < 0.0) + return false; // Too difficult + if (chance >= 1.0) + return true; // No challenge + + return CheckSkill(from, skill, target, chance); + } + + private static bool AllowGain(Mobile from, Skill skill, object obj) + { + if (Core.AOS && Faction.InSkillLoss(from)) // Changed some time between the introduction of AoS and SE. + return false; + + if (AntiMacroCode && from is PlayerMobile mobile && UseAntiMacro[skill.Info.SkillID]) + return mobile.AntiMacroCheck(skill, obj); + + return true; + } + + public static void Gain(Mobile from, Skill skill) + { + if (from.Region.IsPartOf()) return; - } - else if (from.LastStrGain + m_StatGainDelay >= DateTime.UtcNow) - { - return; - } - from.LastStrGain = DateTime.UtcNow; - break; - } - case Stat.Dex: - { - if (from is BaseCreature creature && creature.Controlled) - { - if (creature.LastDexGain + m_PetStatGainDelay >= DateTime.UtcNow) + if (from is BaseCreature creature && creature.IsDeadPet) return; - } - else if (from.LastDexGain + m_StatGainDelay >= DateTime.UtcNow) - { - return; - } - from.LastDexGain = DateTime.UtcNow; - break; - } - case Stat.Int: - { - if (from is BaseCreature creature && creature.Controlled) - { - if (creature.LastIntGain + m_PetStatGainDelay >= DateTime.UtcNow) + if (skill.SkillName == SkillName.Focus && from is BaseCreature) return; - } - else if (from.LastIntGain + m_StatGainDelay >= DateTime.UtcNow) + + if (skill.Base < skill.Cap && skill.Lock == SkillLock.Up) { - return; + var toGain = 1; + + if (skill.Base <= 10.0) + toGain = Utility.Random(4) + 1; + + var skills = from.Skills; + + if (from.Player && skills.Total / skills.Cap >= Utility.RandomDouble()) + for (var i = 0; i < skills.Length; ++i) + { + var toLower = skills[i]; + + if (toLower != skill && toLower.Lock == SkillLock.Down && toLower.BaseFixedPoint >= toGain) + { + toLower.BaseFixedPoint -= toGain; + break; + } + } + + if (from is PlayerMobile pm && skill.SkillName == pm.AcceleratedSkill && + pm.AcceleratedStart > DateTime.UtcNow) + toGain *= Utility.RandomMinMax(2, 5); + + if (!from.Player || skills.Total + toGain <= skills.Cap) skill.BaseFixedPoint += toGain; } - from.LastIntGain = DateTime.UtcNow; - break; - } - } + if (skill.Lock == SkillLock.Up) + { + var info = skill.Info; - bool atrophy = from.RawStatTotal / (double)from.StatCap >= Utility.RandomDouble(); + if (from.StrLock == StatLockType.Up && info.StrGain / 33.3 > Utility.RandomDouble()) + GainStat(from, Stat.Str); + else if (from.DexLock == StatLockType.Up && info.DexGain / 33.3 > Utility.RandomDouble()) + GainStat(from, Stat.Dex); + else if (from.IntLock == StatLockType.Up && info.IntGain / 33.3 > Utility.RandomDouble()) + GainStat(from, Stat.Int); + } + } - IncreaseStat(from, stat, atrophy); + public static bool CanLower(Mobile from, Stat stat) + { + return stat switch + { + Stat.Str => from.StrLock == StatLockType.Down && from.RawStr > 10, + Stat.Dex => from.DexLock == StatLockType.Down && from.RawDex > 10, + Stat.Int => from.IntLock == StatLockType.Down && from.RawInt > 10, + _ => false + }; + } + + public static bool CanRaise(Mobile from, Stat stat) + { + if (!(from is BaseCreature creature && creature.Controlled)) + if (from.RawStatTotal >= from.StatCap) + return false; + + return stat switch + { + Stat.Str => from.StrLock == StatLockType.Up && from.RawStr < 125, + Stat.Dex => from.DexLock == StatLockType.Up && from.RawDex < 125, + Stat.Int => from.IntLock == StatLockType.Up && from.RawInt < 125, + _ => false + }; + } + + public static void IncreaseStat(Mobile from, Stat stat, bool atrophy) + { + atrophy = atrophy || from.RawStatTotal >= from.StatCap; + + switch (stat) + { + case Stat.Str: + { + if (atrophy) + { + if (CanLower(from, Stat.Dex) && (from.RawDex < from.RawInt || !CanLower(from, Stat.Int))) + --from.RawDex; + else if (CanLower(from, Stat.Int)) + --from.RawInt; + } + + if (CanRaise(from, Stat.Str)) + ++from.RawStr; + + break; + } + case Stat.Dex: + { + if (atrophy) + { + if (CanLower(from, Stat.Str) && (from.RawStr < from.RawInt || !CanLower(from, Stat.Int))) + --from.RawStr; + else if (CanLower(from, Stat.Int)) + --from.RawInt; + } + + if (CanRaise(from, Stat.Dex)) + ++from.RawDex; + + break; + } + case Stat.Int: + { + if (atrophy) + { + if (CanLower(from, Stat.Str) && (from.RawStr < from.RawDex || !CanLower(from, Stat.Dex))) + --from.RawStr; + else if (CanLower(from, Stat.Dex)) + --from.RawDex; + } + + if (CanRaise(from, Stat.Int)) + ++from.RawInt; + + break; + } + } + } + + public static void GainStat(Mobile from, Stat stat) + { + switch (stat) + { + case Stat.Str: + { + if (from is BaseCreature creature && creature.Controlled) + { + if (creature.LastStrGain + m_PetStatGainDelay >= DateTime.UtcNow) + return; + } + else if (from.LastStrGain + m_StatGainDelay >= DateTime.UtcNow) + { + return; + } + + from.LastStrGain = DateTime.UtcNow; + break; + } + case Stat.Dex: + { + if (from is BaseCreature creature && creature.Controlled) + { + if (creature.LastDexGain + m_PetStatGainDelay >= DateTime.UtcNow) + return; + } + else if (from.LastDexGain + m_StatGainDelay >= DateTime.UtcNow) + { + return; + } + + from.LastDexGain = DateTime.UtcNow; + break; + } + case Stat.Int: + { + if (from is BaseCreature creature && creature.Controlled) + { + if (creature.LastIntGain + m_PetStatGainDelay >= DateTime.UtcNow) + return; + } + else if (from.LastIntGain + m_StatGainDelay >= DateTime.UtcNow) + { + return; + } + + from.LastIntGain = DateTime.UtcNow; + break; + } + } + + var atrophy = from.RawStatTotal / (double)from.StatCap >= Utility.RandomDouble(); + + IncreaseStat(from, stat, atrophy); + } } - } } diff --git a/Projects/UOContent/Misc/TextDefinition.cs b/Projects/UOContent/Misc/TextDefinition.cs index 6e5ee94c0..17518e364 100644 --- a/Projects/UOContent/Misc/TextDefinition.cs +++ b/Projects/UOContent/Misc/TextDefinition.cs @@ -4,164 +4,176 @@ using Server.Network; namespace Server { - [Parsable] - public class TextDefinition - { - public TextDefinition(string text) : this(0, text) + [Parsable] + public class TextDefinition { + public TextDefinition(string text) : this(0, text) + { + } + + public TextDefinition(int number = 0, string text = null) + { + Number = number; + String = text; + } + + public int Number { get; } + + public string String { get; } + + public bool IsEmpty => Number <= 0 && String == null; + + public override string ToString() => Number > 0 ? $"#{Number}" : String ?? ""; + + public string Format(bool propsGump) => + Number > 0 ? $"{Number} (0x{Number:X})" : + String != null ? $"\"{String}\"" : + propsGump ? "-empty-" : "empty"; + + public string GetValue() => Number > 0 ? Number.ToString() : String ?? ""; + + public static void Serialize(IGenericWriter writer, TextDefinition def) + { + if (def == null) + { + writer.WriteEncodedInt(3); + } + else if (def.Number > 0) + { + writer.WriteEncodedInt(1); + writer.WriteEncodedInt(def.Number); + } + else if (def.String != null) + { + writer.WriteEncodedInt(2); + writer.Write(def.String); + } + else + { + writer.WriteEncodedInt(0); + } + } + + public static TextDefinition Deserialize(IGenericReader reader) + { + var type = reader.ReadEncodedInt(); + + return type switch + { + 0 => new TextDefinition(), + 1 => new TextDefinition(reader.ReadEncodedInt()), + 2 => new TextDefinition(reader.ReadString()), + _ => null + }; + } + + public static void AddTo(ObjectPropertyList list, TextDefinition def) + { + if (def == null) + return; + + if (def.Number > 0) + list.Add(def.Number); + else if (def.String != null) + list.Add(def.String); + } + + public static implicit operator TextDefinition(int v) => new TextDefinition(v); + + public static implicit operator TextDefinition(string s) => new TextDefinition(s); + + public static implicit operator int(TextDefinition m) => m?.Number ?? 0; + + public static implicit operator string(TextDefinition m) => m?.String; + + public static void AddHtmlText( + Gump g, int x, int y, int width, int height, TextDefinition def, bool back, + bool scroll, int numberColor, int stringColor + ) + { + if (def == null) + return; + + if (def.Number > 0) + { + if (numberColor >= 0) // 5 bits per RGB component (15 bit RGB) + g.AddHtmlLocalized(x, y, width, height, def.Number, numberColor, back, scroll); + else + g.AddHtmlLocalized(x, y, width, height, def.Number, back, scroll); + } + else if (def.String != null) + { + if (stringColor >= 0) // 8 bits per RGB component (24 bit RGB) + g.AddHtml( + x, + y, + width, + height, + $"{def.String}", + back, + scroll + ); + else + g.AddHtml(x, y, width, height, def.String, back, scroll); + } + } + + public static void AddHtmlText( + Gump g, int x, int y, int width, int height, TextDefinition def, bool back, + bool scroll + ) + { + AddHtmlText(g, x, y, width, height, def, back, scroll, -1, -1); + } + + public static void SendMessageTo(Mobile m, TextDefinition def) + { + if (def == null) + return; + + if (def.Number > 0) + m.SendLocalizedMessage(def.Number); + else if (def.String != null) + m.SendMessage(def.String); + } + + public static void SendMessageTo(Mobile m, TextDefinition def, int hue) + { + if (def == null) + return; + + if (def.Number > 0) + m.SendLocalizedMessage(def.Number, "", hue); + else if (def.String != null) + m.SendMessage(hue, def.String); + } + + public static void PublicOverheadMessage(Mobile m, MessageType messageType, int hue, TextDefinition def) + { + if (def == null) + return; + + if (def.Number > 0) + m.PublicOverheadMessage(messageType, hue, def.Number); + else if (def.String != null) + m.PublicOverheadMessage(messageType, hue, false, def.String); + } + + public static TextDefinition Parse(string value) + { + if (value == null) + return null; + + int i; + bool isInteger; + + isInteger = value.StartsWith("0x") + ? int.TryParse(value.Substring(2), NumberStyles.HexNumber, null, out i) + : int.TryParse(value, out i); + + return isInteger ? new TextDefinition(i) : new TextDefinition(value); + } + + public static bool IsNullOrEmpty(TextDefinition def) => def?.IsEmpty != false; } - - public TextDefinition(int number = 0, string text = null) - { - Number = number; - String = text; - } - - public int Number { get; } - - public string String { get; } - - public bool IsEmpty => Number <= 0 && String == null; - - public override string ToString() => Number > 0 ? $"#{Number}" : String ?? ""; - - public string Format(bool propsGump) => - Number > 0 ? $"{Number} (0x{Number:X})" : - String != null ? $"\"{String}\"" : propsGump ? "-empty-" : "empty"; - - public string GetValue() => Number > 0 ? Number.ToString() : String ?? ""; - - public static void Serialize(IGenericWriter writer, TextDefinition def) - { - if (def == null) - { - writer.WriteEncodedInt(3); - } - else if (def.Number > 0) - { - writer.WriteEncodedInt(1); - writer.WriteEncodedInt(def.Number); - } - else if (def.String != null) - { - writer.WriteEncodedInt(2); - writer.Write(def.String); - } - else - { - writer.WriteEncodedInt(0); - } - } - - public static TextDefinition Deserialize(IGenericReader reader) - { - int type = reader.ReadEncodedInt(); - - return type switch - { - 0 => new TextDefinition(), - 1 => new TextDefinition(reader.ReadEncodedInt()), - 2 => new TextDefinition(reader.ReadString()), - _ => null - }; - } - - public static void AddTo(ObjectPropertyList list, TextDefinition def) - { - if (def == null) - return; - - if (def.Number > 0) - list.Add(def.Number); - else if (def.String != null) - list.Add(def.String); - } - - public static implicit operator TextDefinition(int v) => new TextDefinition(v); - - public static implicit operator TextDefinition(string s) => new TextDefinition(s); - - public static implicit operator int(TextDefinition m) => m?.Number ?? 0; - - public static implicit operator string(TextDefinition m) => m?.String; - - public static void AddHtmlText(Gump g, int x, int y, int width, int height, TextDefinition def, bool back, - bool scroll, int numberColor, int stringColor) - { - if (def == null) - return; - - if (def.Number > 0) - { - if (numberColor >= 0) // 5 bits per RGB component (15 bit RGB) - g.AddHtmlLocalized(x, y, width, height, def.Number, numberColor, back, scroll); - else - g.AddHtmlLocalized(x, y, width, height, def.Number, back, scroll); - } - else if (def.String != null) - { - if (stringColor >= 0) // 8 bits per RGB component (24 bit RGB) - g.AddHtml(x, y, width, height, $"{def.String}", back, - scroll); - else - g.AddHtml(x, y, width, height, def.String, back, scroll); - } - } - - public static void AddHtmlText(Gump g, int x, int y, int width, int height, TextDefinition def, bool back, - bool scroll) - { - AddHtmlText(g, x, y, width, height, def, back, scroll, -1, -1); - } - - public static void SendMessageTo(Mobile m, TextDefinition def) - { - if (def == null) - return; - - if (def.Number > 0) - m.SendLocalizedMessage(def.Number); - else if (def.String != null) - m.SendMessage(def.String); - } - - public static void SendMessageTo(Mobile m, TextDefinition def, int hue) - { - if (def == null) - return; - - if (def.Number > 0) - m.SendLocalizedMessage(def.Number, "", hue); - else if (def.String != null) - m.SendMessage(hue, def.String); - } - - public static void PublicOverheadMessage(Mobile m, MessageType messageType, int hue, TextDefinition def) - { - if (def == null) - return; - - if (def.Number > 0) - m.PublicOverheadMessage(messageType, hue, def.Number); - else if (def.String != null) - m.PublicOverheadMessage(messageType, hue, false, def.String); - } - - public static TextDefinition Parse(string value) - { - if (value == null) - return null; - - int i; - bool isInteger; - - isInteger = value.StartsWith("0x") ? - int.TryParse(value.Substring(2), NumberStyles.HexNumber, null, out i) : - int.TryParse(value, out i); - - return isInteger ? new TextDefinition(i) : new TextDefinition(value); - } - - public static bool IsNullOrEmpty(TextDefinition def) => def?.IsEmpty != false; - } } diff --git a/Projects/UOContent/Misc/Titles.cs b/Projects/UOContent/Misc/Titles.cs index 7333ebcfb..cb7357b0b 100644 --- a/Projects/UOContent/Misc/Titles.cs +++ b/Projects/UOContent/Misc/Titles.cs @@ -5,387 +5,408 @@ using Server.Mobiles; namespace Server.Misc { - public class Titles - { - public const int MinFame = 0; - public const int MaxFame = 15000; - - public const int MinKarma = -15000; - public const int MaxKarma = 15000; - - public static string[] HarrowerTitles = + public class Titles { - "Spite", "Opponent", "Hunter", "Venom", "Executioner", "Annihilator", "Champion", "Assailant", "Purifier", - "Nullifier" - }; + public const int MinFame = 0; + public const int MaxFame = 15000; - private static readonly string[,] m_Levels = - { - { "Neophyte", "Neophyte", "Neophyte" }, - { "Novice", "Novice", "Novice" }, - { "Apprentice", "Apprentice", "Apprentice" }, - { "Journeyman", "Journeyman", "Journeyman" }, - { "Expert", "Expert", "Expert" }, - { "Adept", "Adept", "Adept" }, - { "Master", "Master", "Master" }, - { "Grandmaster", "Grandmaster", "Grandmaster" }, - { "Elder", "Tatsujin", "Shinobi" }, - { "Legendary", "Kengo", "Ka-ge" } - }; + public const int MinKarma = -15000; + public const int MaxKarma = 15000; - private static readonly FameEntry[] m_FameEntries = - { - new FameEntry(1249, new[] - { - new KarmaEntry(-10000, "The Outcast {0}"), - new KarmaEntry(-5000, "The Despicable {0}"), - new KarmaEntry(-2500, "The Scoundrel {0}"), - new KarmaEntry(-1250, "The Unsavory {0}"), - new KarmaEntry(-625, "The Rude {0}"), - new KarmaEntry(624, "{0}"), - new KarmaEntry(1249, "The Fair {0}"), - new KarmaEntry(2499, "The Kind {0}"), - new KarmaEntry(4999, "The Good {0}"), - new KarmaEntry(9999, "The Honest {0}"), - new KarmaEntry(10000, "The Trustworthy {0}") - }), - new FameEntry(2499, new[] - { - new KarmaEntry(-10000, "The Wretched {0}"), - new KarmaEntry(-5000, "The Dastardly {0}"), - new KarmaEntry(-2500, "The Malicious {0}"), - new KarmaEntry(-1250, "The Dishonorable {0}"), - new KarmaEntry(-625, "The Disreputable {0}"), - new KarmaEntry(624, "The Notable {0}"), - new KarmaEntry(1249, "The Upstanding {0}"), - new KarmaEntry(2499, "The Respectable {0}"), - new KarmaEntry(4999, "The Honorable {0}"), - new KarmaEntry(9999, "The Commendable {0}"), - new KarmaEntry(10000, "The Estimable {0}") - }), - new FameEntry(4999, new[] - { - new KarmaEntry(-10000, "The Nefarious {0}"), - new KarmaEntry(-5000, "The Wicked {0}"), - new KarmaEntry(-2500, "The Vile {0}"), - new KarmaEntry(-1250, "The Ignoble {0}"), - new KarmaEntry(-625, "The Notorious {0}"), - new KarmaEntry(624, "The Prominent {0}"), - new KarmaEntry(1249, "The Reputable {0}"), - new KarmaEntry(2499, "The Proper {0}"), - new KarmaEntry(4999, "The Admirable {0}"), - new KarmaEntry(9999, "The Famed {0}"), - new KarmaEntry(10000, "The Great {0}") - }), - new FameEntry(9999, new[] - { - new KarmaEntry(-10000, "The Dread {0}"), - new KarmaEntry(-5000, "The Evil {0}"), - new KarmaEntry(-2500, "The Villainous {0}"), - new KarmaEntry(-1250, "The Sinister {0}"), - new KarmaEntry(-625, "The Infamous {0}"), - new KarmaEntry(624, "The Renowned {0}"), - new KarmaEntry(1249, "The Distinguished {0}"), - new KarmaEntry(2499, "The Eminent {0}"), - new KarmaEntry(4999, "The Noble {0}"), - new KarmaEntry(9999, "The Illustrious {0}"), - new KarmaEntry(10000, "The Glorious {0}") - }), - new FameEntry(10000, new[] - { - new KarmaEntry(-10000, "The Dread {1} {0}"), - new KarmaEntry(-5000, "The Evil {1} {0}"), - new KarmaEntry(-2500, "The Dark {1} {0}"), - new KarmaEntry(-1250, "The Sinister {1} {0}"), - new KarmaEntry(-625, "The Dishonored {1} {0}"), - new KarmaEntry(624, "{1} {0}"), - new KarmaEntry(1249, "The Distinguished {1} {0}"), - new KarmaEntry(2499, "The Eminent {1} {0}"), - new KarmaEntry(4999, "The Noble {1} {0}"), - new KarmaEntry(9999, "The Illustrious {1} {0}"), - new KarmaEntry(10000, "The Glorious {1} {0}") - }) - }; - - public static void AwardFame(Mobile m, int offset, bool message) - { - if (offset > 0) - { - if (m.Fame >= MaxFame) - return; - - offset = Math.Max(offset - m.Fame / 100, 0); - } - else if (offset < 0) - { - if (m.Fame <= MinFame) - return; - - offset = Math.Min(offset - m.Fame / 100, 0); - } - - if (m.Fame + offset > MaxFame) - offset = MaxFame - m.Fame; - else if (m.Fame + offset < MinFame) - offset = MinFame - m.Fame; - - m.Fame += offset; - - if (message) - { - if (offset > 40) - m.SendLocalizedMessage(1019054); // You have gained a lot of fame. - else if (offset > 20) - m.SendLocalizedMessage(1019053); // You have gained a good amount of fame. - else if (offset > 10) - m.SendLocalizedMessage(1019052); // You have gained some fame. - else if (offset > 0) - m.SendLocalizedMessage(1019051); // You have gained a little fame. - else if (offset < -40) - m.SendLocalizedMessage(1019058); // You have lost a lot of fame. - else if (offset < -20) - m.SendLocalizedMessage(1019057); // You have lost a good amount of fame. - else if (offset < -10) - m.SendLocalizedMessage(1019056); // You have lost some fame. - else if (offset < 0) - m.SendLocalizedMessage(1019055); // You have lost a little fame. - } - } - - public static void AwardKarma(Mobile m, int offset, bool message) - { - PlayerMobile pm = m as PlayerMobile; - - if (offset > 0) - { - if (pm?.KarmaLocked == true) - return; - - if (m.Karma >= MaxKarma) - return; - - offset = Math.Max(offset - m.Karma / 100, 0); - } - else if (offset < 0) - { - if (m.Karma <= MinKarma) - return; - - offset = Math.Min(offset - m.Karma / 100, 0); - } - - if (m.Karma + offset > MaxKarma) - offset = MaxKarma - m.Karma; - else if (m.Karma + offset < MinKarma) - offset = MinKarma - m.Karma; - - bool wasPositiveKarma = m.Karma >= 0; - - m.Karma += offset; - - if (message) - { - if (offset > 40) - m.SendLocalizedMessage(1019062); // You have gained a lot of karma. - else if (offset > 20) - m.SendLocalizedMessage(1019061); // You have gained a good amount of karma. - else if (offset > 10) - m.SendLocalizedMessage(1019060); // You have gained some karma. - else if (offset > 0) - m.SendLocalizedMessage(1019059); // You have gained a little karma. - else if (offset < -40) - m.SendLocalizedMessage(1019066); // You have lost a lot of karma. - else if (offset < -20) - m.SendLocalizedMessage(1019065); // You have lost a good amount of karma. - else if (offset < -10) - m.SendLocalizedMessage(1019064); // You have lost some karma. - else if (offset < 0) - m.SendLocalizedMessage(1019063); // You have lost a little karma. - } - - if (!Core.AOS && wasPositiveKarma && m.Karma < 0 && pm?.KarmaLocked == false) - { - pm.KarmaLocked = true; - m.SendLocalizedMessage(1042511, "", - 0x22); // Karma is locked. A mantra spoken at a shrine will unlock it again. - } - } - - public static string ComputeTitle(Mobile beholder, Mobile beheld) - { - StringBuilder title = new StringBuilder(); - - int fame = beheld.Fame; - int karma = beheld.Karma; - - bool showSkillTitle = beheld.ShowFameTitle && (beholder == beheld || fame >= 5000); - - /*if (beheld.Kills >= 5) - { - title.AppendFormat( beheld.Fame >= 10000 ? "The Murderer {1} {0}" : "The Murderer {0}", beheld.Name, beheld.Female ? "Lady" : "Lord" ); - } - else*/ - if (beheld.ShowFameTitle || beholder == beheld) - for (int i = 0; i < m_FameEntries.Length; ++i) + public static string[] HarrowerTitles = { - FameEntry fe = m_FameEntries[i]; + "Spite", "Opponent", "Hunter", "Venom", "Executioner", "Annihilator", "Champion", "Assailant", "Purifier", + "Nullifier" + }; - if (fame <= fe.m_Fame || i == m_FameEntries.Length - 1) - { - KarmaEntry[] karmaEntries = fe.m_Karma; + private static readonly string[,] m_Levels = + { + { "Neophyte", "Neophyte", "Neophyte" }, + { "Novice", "Novice", "Novice" }, + { "Apprentice", "Apprentice", "Apprentice" }, + { "Journeyman", "Journeyman", "Journeyman" }, + { "Expert", "Expert", "Expert" }, + { "Adept", "Adept", "Adept" }, + { "Master", "Master", "Master" }, + { "Grandmaster", "Grandmaster", "Grandmaster" }, + { "Elder", "Tatsujin", "Shinobi" }, + { "Legendary", "Kengo", "Ka-ge" } + }; - for (int j = 0; j < karmaEntries.Length; ++j) + private static readonly FameEntry[] m_FameEntries = + { + new FameEntry( + 1249, + new[] + { + new KarmaEntry(-10000, "The Outcast {0}"), + new KarmaEntry(-5000, "The Despicable {0}"), + new KarmaEntry(-2500, "The Scoundrel {0}"), + new KarmaEntry(-1250, "The Unsavory {0}"), + new KarmaEntry(-625, "The Rude {0}"), + new KarmaEntry(624, "{0}"), + new KarmaEntry(1249, "The Fair {0}"), + new KarmaEntry(2499, "The Kind {0}"), + new KarmaEntry(4999, "The Good {0}"), + new KarmaEntry(9999, "The Honest {0}"), + new KarmaEntry(10000, "The Trustworthy {0}") + } + ), + new FameEntry( + 2499, + new[] + { + new KarmaEntry(-10000, "The Wretched {0}"), + new KarmaEntry(-5000, "The Dastardly {0}"), + new KarmaEntry(-2500, "The Malicious {0}"), + new KarmaEntry(-1250, "The Dishonorable {0}"), + new KarmaEntry(-625, "The Disreputable {0}"), + new KarmaEntry(624, "The Notable {0}"), + new KarmaEntry(1249, "The Upstanding {0}"), + new KarmaEntry(2499, "The Respectable {0}"), + new KarmaEntry(4999, "The Honorable {0}"), + new KarmaEntry(9999, "The Commendable {0}"), + new KarmaEntry(10000, "The Estimable {0}") + } + ), + new FameEntry( + 4999, + new[] + { + new KarmaEntry(-10000, "The Nefarious {0}"), + new KarmaEntry(-5000, "The Wicked {0}"), + new KarmaEntry(-2500, "The Vile {0}"), + new KarmaEntry(-1250, "The Ignoble {0}"), + new KarmaEntry(-625, "The Notorious {0}"), + new KarmaEntry(624, "The Prominent {0}"), + new KarmaEntry(1249, "The Reputable {0}"), + new KarmaEntry(2499, "The Proper {0}"), + new KarmaEntry(4999, "The Admirable {0}"), + new KarmaEntry(9999, "The Famed {0}"), + new KarmaEntry(10000, "The Great {0}") + } + ), + new FameEntry( + 9999, + new[] + { + new KarmaEntry(-10000, "The Dread {0}"), + new KarmaEntry(-5000, "The Evil {0}"), + new KarmaEntry(-2500, "The Villainous {0}"), + new KarmaEntry(-1250, "The Sinister {0}"), + new KarmaEntry(-625, "The Infamous {0}"), + new KarmaEntry(624, "The Renowned {0}"), + new KarmaEntry(1249, "The Distinguished {0}"), + new KarmaEntry(2499, "The Eminent {0}"), + new KarmaEntry(4999, "The Noble {0}"), + new KarmaEntry(9999, "The Illustrious {0}"), + new KarmaEntry(10000, "The Glorious {0}") + } + ), + new FameEntry( + 10000, + new[] + { + new KarmaEntry(-10000, "The Dread {1} {0}"), + new KarmaEntry(-5000, "The Evil {1} {0}"), + new KarmaEntry(-2500, "The Dark {1} {0}"), + new KarmaEntry(-1250, "The Sinister {1} {0}"), + new KarmaEntry(-625, "The Dishonored {1} {0}"), + new KarmaEntry(624, "{1} {0}"), + new KarmaEntry(1249, "The Distinguished {1} {0}"), + new KarmaEntry(2499, "The Eminent {1} {0}"), + new KarmaEntry(4999, "The Noble {1} {0}"), + new KarmaEntry(9999, "The Illustrious {1} {0}"), + new KarmaEntry(10000, "The Glorious {1} {0}") + } + ) + }; + + public static void AwardFame(Mobile m, int offset, bool message) + { + if (offset > 0) { - KarmaEntry ke = karmaEntries[j]; + if (m.Fame >= MaxFame) + return; - if (karma <= ke.m_Karma || j == karmaEntries.Length - 1) - { - title.AppendFormat(ke.m_Title, beheld.Name, beheld.Female ? "Lady" : "Lord"); - break; - } + offset = Math.Max(offset - m.Fame / 100, 0); + } + else if (offset < 0) + { + if (m.Fame <= MinFame) + return; + + offset = Math.Min(offset - m.Fame / 100, 0); } - break; - } - } - else - title.Append(beheld.Name); + if (m.Fame + offset > MaxFame) + offset = MaxFame - m.Fame; + else if (m.Fame + offset < MinFame) + offset = MinFame - m.Fame; - if (beheld is PlayerMobile mobile && mobile.DisplayChampionTitle) - { - PlayerMobile.ChampionTitleInfo info = mobile.ChampionTitles; + m.Fame += offset; - if (info.Harrower > 0) - { - title.AppendFormat(": {0} of Evil", HarrowerTitles[Math.Min(HarrowerTitles.Length, info.Harrower) - 1]); - } - else - { - int highestValue = 0, highestType = 0; - for (int i = 0; i < ChampionSpawnInfo.Table.Length; i++) - { - int v = info.GetValue(i); - - if (v > highestValue) + if (message) { - highestValue = v; - highestType = i; + if (offset > 40) + m.SendLocalizedMessage(1019054); // You have gained a lot of fame. + else if (offset > 20) + m.SendLocalizedMessage(1019053); // You have gained a good amount of fame. + else if (offset > 10) + m.SendLocalizedMessage(1019052); // You have gained some fame. + else if (offset > 0) + m.SendLocalizedMessage(1019051); // You have gained a little fame. + else if (offset < -40) + m.SendLocalizedMessage(1019058); // You have lost a lot of fame. + else if (offset < -20) + m.SendLocalizedMessage(1019057); // You have lost a good amount of fame. + else if (offset < -10) + m.SendLocalizedMessage(1019056); // You have lost some fame. + else if (offset < 0) + m.SendLocalizedMessage(1019055); // You have lost a little fame. } - } - - int offset = 0; - if (highestValue > 800) - offset = 3; - else if (highestValue > 300) - offset = highestValue / 300; - - if (offset > 0) - { - ChampionSpawnInfo champInfo = ChampionSpawnInfo.GetInfo((ChampionSpawnType)highestType); - title.AppendFormat(": {0} of the {1}", - champInfo.LevelNames[Math.Min(offset, champInfo.LevelNames.Length) - 1], champInfo.Name); - } } - } - string customTitle = beheld.Title; + public static void AwardKarma(Mobile m, int offset, bool message) + { + var pm = m as PlayerMobile; - if (customTitle != null && (customTitle = customTitle.Trim()).Length > 0) - { - title.AppendFormat(" {0}", customTitle); - } - else if (showSkillTitle && beheld.Player) - { - string skillTitle = GetSkillTitle(beheld); + if (offset > 0) + { + if (pm?.KarmaLocked == true) + return; - if (skillTitle != null) title.Append(", ").Append(skillTitle); - } + if (m.Karma >= MaxKarma) + return; - return title.ToString(); + offset = Math.Max(offset - m.Karma / 100, 0); + } + else if (offset < 0) + { + if (m.Karma <= MinKarma) + return; + + offset = Math.Min(offset - m.Karma / 100, 0); + } + + if (m.Karma + offset > MaxKarma) + offset = MaxKarma - m.Karma; + else if (m.Karma + offset < MinKarma) + offset = MinKarma - m.Karma; + + var wasPositiveKarma = m.Karma >= 0; + + m.Karma += offset; + + if (message) + { + if (offset > 40) + m.SendLocalizedMessage(1019062); // You have gained a lot of karma. + else if (offset > 20) + m.SendLocalizedMessage(1019061); // You have gained a good amount of karma. + else if (offset > 10) + m.SendLocalizedMessage(1019060); // You have gained some karma. + else if (offset > 0) + m.SendLocalizedMessage(1019059); // You have gained a little karma. + else if (offset < -40) + m.SendLocalizedMessage(1019066); // You have lost a lot of karma. + else if (offset < -20) + m.SendLocalizedMessage(1019065); // You have lost a good amount of karma. + else if (offset < -10) + m.SendLocalizedMessage(1019064); // You have lost some karma. + else if (offset < 0) + m.SendLocalizedMessage(1019063); // You have lost a little karma. + } + + if (!Core.AOS && wasPositiveKarma && m.Karma < 0 && pm?.KarmaLocked == false) + { + pm.KarmaLocked = true; + m.SendLocalizedMessage( + 1042511, + "", + 0x22 + ); // Karma is locked. A mantra spoken at a shrine will unlock it again. + } + } + + public static string ComputeTitle(Mobile beholder, Mobile beheld) + { + var title = new StringBuilder(); + + var fame = beheld.Fame; + var karma = beheld.Karma; + + var showSkillTitle = beheld.ShowFameTitle && (beholder == beheld || fame >= 5000); + + /*if (beheld.Kills >= 5) + { + title.AppendFormat( beheld.Fame >= 10000 ? "The Murderer {1} {0}" : "The Murderer {0}", beheld.Name, beheld.Female ? "Lady" : "Lord" ); + } + else*/ + if (beheld.ShowFameTitle || beholder == beheld) + for (var i = 0; i < m_FameEntries.Length; ++i) + { + var fe = m_FameEntries[i]; + + if (fame <= fe.m_Fame || i == m_FameEntries.Length - 1) + { + var karmaEntries = fe.m_Karma; + + for (var j = 0; j < karmaEntries.Length; ++j) + { + var ke = karmaEntries[j]; + + if (karma <= ke.m_Karma || j == karmaEntries.Length - 1) + { + title.AppendFormat(ke.m_Title, beheld.Name, beheld.Female ? "Lady" : "Lord"); + break; + } + } + + break; + } + } + else + title.Append(beheld.Name); + + if (beheld is PlayerMobile mobile && mobile.DisplayChampionTitle) + { + var info = mobile.ChampionTitles; + + if (info.Harrower > 0) + { + title.AppendFormat(": {0} of Evil", HarrowerTitles[Math.Min(HarrowerTitles.Length, info.Harrower) - 1]); + } + else + { + int highestValue = 0, highestType = 0; + for (var i = 0; i < ChampionSpawnInfo.Table.Length; i++) + { + var v = info.GetValue(i); + + if (v > highestValue) + { + highestValue = v; + highestType = i; + } + } + + var offset = 0; + if (highestValue > 800) + offset = 3; + else if (highestValue > 300) + offset = highestValue / 300; + + if (offset > 0) + { + var champInfo = ChampionSpawnInfo.GetInfo((ChampionSpawnType)highestType); + title.AppendFormat( + ": {0} of the {1}", + champInfo.LevelNames[Math.Min(offset, champInfo.LevelNames.Length) - 1], + champInfo.Name + ); + } + } + } + + var customTitle = beheld.Title; + + if (customTitle != null && (customTitle = customTitle.Trim()).Length > 0) + { + title.AppendFormat(" {0}", customTitle); + } + else if (showSkillTitle && beheld.Player) + { + var skillTitle = GetSkillTitle(beheld); + + if (skillTitle != null) title.Append(", ").Append(skillTitle); + } + + return title.ToString(); + } + + public static string GetSkillTitle(Mobile mob) + { + var highest = GetHighestSkill(mob); // beheld.Skills.Highest; + + if (highest?.BaseFixedPoint >= 300) + { + var skillLevel = GetSkillLevel(highest); + var skillTitle = highest.Info.Title; + + if (mob.Female && skillTitle.EndsWith("man")) + skillTitle = $"{skillTitle.Substring(0, skillTitle.Length - 3)}woman"; + + return $"{skillLevel} {skillTitle}"; + } + + return null; + } + + private static Skill GetHighestSkill(Mobile m) + { + var skills = m.Skills; + + if (!Core.AOS) + return skills.Highest; + + Skill highest = null; + + for (var i = 0; i < m.Skills.Length; ++i) + { + var check = m.Skills[i]; + + if (highest == null || check.BaseFixedPoint > highest.BaseFixedPoint) + highest = check; + else if (highest.Lock != SkillLock.Up && check.Lock == SkillLock.Up && + check.BaseFixedPoint == highest.BaseFixedPoint) + highest = check; + } + + return highest; + } + + private static string GetSkillLevel(Skill skill) => m_Levels[GetTableIndex(skill), GetTableType(skill)]; + + private static int GetTableType(Skill skill) + { + return skill.SkillName switch + { + SkillName.Bushido => 1, + SkillName.Ninjitsu => 2, + _ => 0 + }; + } + + private static int GetTableIndex(Skill skill) + { + var fp = Math.Min(skill.BaseFixedPoint, 1200); + + return (fp - 300) / 100; + } } - public static string GetSkillTitle(Mobile mob) + public class FameEntry { - Skill highest = GetHighestSkill(mob); // beheld.Skills.Highest; + public int m_Fame; + public KarmaEntry[] m_Karma; - if (highest?.BaseFixedPoint >= 300) - { - string skillLevel = GetSkillLevel(highest); - string skillTitle = highest.Info.Title; - - if (mob.Female && skillTitle.EndsWith("man")) - skillTitle = $"{skillTitle.Substring(0, skillTitle.Length - 3)}woman"; - - return $"{skillLevel} {skillTitle}"; - } - - return null; + public FameEntry(int fame, KarmaEntry[] karma) + { + m_Fame = fame; + m_Karma = karma; + } } - private static Skill GetHighestSkill(Mobile m) + public class KarmaEntry { - Skills skills = m.Skills; + public int m_Karma; + public string m_Title; - if (!Core.AOS) - return skills.Highest; - - Skill highest = null; - - for (int i = 0; i < m.Skills.Length; ++i) - { - Skill check = m.Skills[i]; - - if (highest == null || check.BaseFixedPoint > highest.BaseFixedPoint) - highest = check; - else if (highest.Lock != SkillLock.Up && check.Lock == SkillLock.Up && - check.BaseFixedPoint == highest.BaseFixedPoint) - highest = check; - } - - return highest; + public KarmaEntry(int karma, string title) + { + m_Karma = karma; + m_Title = title; + } } - - private static string GetSkillLevel(Skill skill) => m_Levels[GetTableIndex(skill), GetTableType(skill)]; - - private static int GetTableType(Skill skill) - { - return skill.SkillName switch - { - SkillName.Bushido => 1, - SkillName.Ninjitsu => 2, - _ => 0 - }; - } - - private static int GetTableIndex(Skill skill) - { - int fp = Math.Min(skill.BaseFixedPoint, 1200); - - return (fp - 300) / 100; - } - } - - public class FameEntry - { - public int m_Fame; - public KarmaEntry[] m_Karma; - - public FameEntry(int fame, KarmaEntry[] karma) - { - m_Fame = fame; - m_Karma = karma; - } - } - - public class KarmaEntry - { - public int m_Karma; - public string m_Title; - - public KarmaEntry(int karma, string title) - { - m_Karma = karma; - m_Title = title; - } - } } diff --git a/Projects/UOContent/Misc/ToggleItem.cs b/Projects/UOContent/Misc/ToggleItem.cs index 4cef1077e..b52d8dd7a 100644 --- a/Projects/UOContent/Misc/ToggleItem.cs +++ b/Projects/UOContent/Misc/ToggleItem.cs @@ -2,105 +2,105 @@ using Server.Commands.Generic; namespace Server.Items { - public class ToggleItem : Item - { - [Constructible] - public ToggleItem(int inactiveItemID, int activeItemID, bool playersCanToggle = false) - : base(inactiveItemID) + public class ToggleItem : Item { - Movable = false; - - InactiveItemID = inactiveItemID; - ActiveItemID = activeItemID; - PlayersCanToggle = playersCanToggle; - } - - public ToggleItem(Serial serial) - : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int InactiveItemID { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int ActiveItemID { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool PlayersCanToggle { get; set; } - - public static void Initialize() - { - TargetCommands.Register(new ToggleCommand()); - } - - public override void OnDoubleClick(Mobile from) - { - if (from.AccessLevel >= AccessLevel.GameMaster) - { - Toggle(); - } - else if (PlayersCanToggle) - { - if (from.InRange(GetWorldLocation(), 1)) - Toggle(); - else - from.SendLocalizedMessage(500446); // That is too far away. - } - } - - public void Toggle() - { - ItemID = ItemID == ActiveItemID ? InactiveItemID : ActiveItemID; - Visible = ItemID != 0x1; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(InactiveItemID); - writer.Write(ActiveItemID); - writer.Write(PlayersCanToggle); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - InactiveItemID = reader.ReadInt(); - ActiveItemID = reader.ReadInt(); - PlayersCanToggle = reader.ReadBool(); - } - - public class ToggleCommand : BaseCommand - { - public ToggleCommand() - { - AccessLevel = AccessLevel.GameMaster; - Supports = CommandSupport.AllItems; - Commands = new[] { "Toggle" }; - ObjectTypes = ObjectTypes.Items; - Usage = "Toggle"; - Description = "Toggles a targeted ToggleItem."; - } - - public override void Execute(CommandEventArgs e, object obj) - { - if (obj is ToggleItem item) + [Constructible] + public ToggleItem(int inactiveItemID, int activeItemID, bool playersCanToggle = false) + : base(inactiveItemID) { - item.Toggle(); - AddResponse("The item has been toggled."); + Movable = false; + + InactiveItemID = inactiveItemID; + ActiveItemID = activeItemID; + PlayersCanToggle = playersCanToggle; } - else + + public ToggleItem(Serial serial) + : base(serial) { - LogFailure("That is not a ToggleItem."); } - } + + [CommandProperty(AccessLevel.GameMaster)] + public int InactiveItemID { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int ActiveItemID { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool PlayersCanToggle { get; set; } + + public static void Initialize() + { + TargetCommands.Register(new ToggleCommand()); + } + + public override void OnDoubleClick(Mobile from) + { + if (from.AccessLevel >= AccessLevel.GameMaster) + { + Toggle(); + } + else if (PlayersCanToggle) + { + if (from.InRange(GetWorldLocation(), 1)) + Toggle(); + else + from.SendLocalizedMessage(500446); // That is too far away. + } + } + + public void Toggle() + { + ItemID = ItemID == ActiveItemID ? InactiveItemID : ActiveItemID; + Visible = ItemID != 0x1; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(InactiveItemID); + writer.Write(ActiveItemID); + writer.Write(PlayersCanToggle); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + InactiveItemID = reader.ReadInt(); + ActiveItemID = reader.ReadInt(); + PlayersCanToggle = reader.ReadBool(); + } + + public class ToggleCommand : BaseCommand + { + public ToggleCommand() + { + AccessLevel = AccessLevel.GameMaster; + Supports = CommandSupport.AllItems; + Commands = new[] { "Toggle" }; + ObjectTypes = ObjectTypes.Items; + Usage = "Toggle"; + Description = "Toggles a targeted ToggleItem."; + } + + public override void Execute(CommandEventArgs e, object obj) + { + if (obj is ToggleItem item) + { + item.Toggle(); + AddResponse("The item has been toggled."); + } + else + { + LogFailure("That is not a ToggleItem."); + } + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Misc/TreasureMapProtection.cs b/Projects/UOContent/Misc/TreasureMapProtection.cs index 9b4bc4d1d..b1f8d09bf 100644 --- a/Projects/UOContent/Misc/TreasureMapProtection.cs +++ b/Projects/UOContent/Misc/TreasureMapProtection.cs @@ -4,69 +4,73 @@ using Server.Regions; namespace Server { - public class TreasureRegion : BaseRegion - { - private const int Range = 5; // No house may be placed within 5 tiles of the treasure - - public TreasureRegion(int x, int y, Map map) : base(null, map, DefaultPriority, - new Rectangle2D(x - Range, y - Range, 1 + Range * 2, 1 + Range * 2)) + public class TreasureRegion : BaseRegion { - GoLocation = new Point3D(x, y, map.GetAverageZ(x, y)); + private const int Range = 5; // No house may be placed within 5 tiles of the treasure - Register(); - } - - public static void Initialize() - { - string filePath = Path.Combine(Core.BaseDirectory, "Data/treasure.cfg"); - int i = 0, x = 0, y = 0; - - if (File.Exists(filePath)) - { - using StreamReader ip = new StreamReader(filePath); - string line; - - while ((line = ip.ReadLine()) != null) + public TreasureRegion(int x, int y, Map map) : base( + null, + map, + DefaultPriority, + new Rectangle2D(x - Range, y - Range, 1 + Range * 2, 1 + Range * 2) + ) { - i++; + GoLocation = new Point3D(x, y, map.GetAverageZ(x, y)); - try - { - string[] split = line.Split(' '); - - x = Convert.ToInt32(split[0]); - y = Convert.ToInt32(split[1]); - - try - { - new TreasureRegion(x, y, Map.Felucca); - new TreasureRegion(x, y, Map.Trammel); - } - catch (Exception e) - { - Console.WriteLine("{0} {1} {2} {3}", i, x, y, e); - } - } - catch - { - Console.WriteLine("Warning: Error in Line '{0}' of Data/treasure.cfg", line); - } + Register(); } - } - } - public override bool AllowHousing(Mobile from, Point3D p) => false; + public static void Initialize() + { + var filePath = Path.Combine(Core.BaseDirectory, "Data/treasure.cfg"); + int i = 0, x = 0, y = 0; - public override void OnEnter(Mobile m) - { - if (m.AccessLevel > AccessLevel.Player) - m.SendMessage("You have entered a protected treasure map area."); - } + if (File.Exists(filePath)) + { + using var ip = new StreamReader(filePath); + string line; - public override void OnExit(Mobile m) - { - if (m.AccessLevel > AccessLevel.Player) - m.SendMessage("You have left a protected treasure map area."); + while ((line = ip.ReadLine()) != null) + { + i++; + + try + { + var split = line.Split(' '); + + x = Convert.ToInt32(split[0]); + y = Convert.ToInt32(split[1]); + + try + { + new TreasureRegion(x, y, Map.Felucca); + new TreasureRegion(x, y, Map.Trammel); + } + catch (Exception e) + { + Console.WriteLine("{0} {1} {2} {3}", i, x, y, e); + } + } + catch + { + Console.WriteLine("Warning: Error in Line '{0}' of Data/treasure.cfg", line); + } + } + } + } + + public override bool AllowHousing(Mobile from, Point3D p) => false; + + public override void OnEnter(Mobile m) + { + if (m.AccessLevel > AccessLevel.Player) + m.SendMessage("You have entered a protected treasure map area."); + } + + public override void OnExit(Mobile m) + { + if (m.AccessLevel > AccessLevel.Player) + m.SendMessage("You have left a protected treasure map area."); + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Misc/ValidationQueue.cs b/Projects/UOContent/Misc/ValidationQueue.cs index 2d51bcfd3..9f8ba1756 100644 --- a/Projects/UOContent/Misc/ValidationQueue.cs +++ b/Projects/UOContent/Misc/ValidationQueue.cs @@ -1,50 +1,49 @@ -using System; using System.Collections.Generic; using System.Reflection; namespace Server { - public delegate void ValidationEventHandler(); + public delegate void ValidationEventHandler(); - public static class ValidationQueue - { - public static event ValidationEventHandler StartValidation; - - public static void Initialize() + public static class ValidationQueue { - StartValidation?.Invoke(); + public static event ValidationEventHandler StartValidation; - StartValidation = null; - } - } + public static void Initialize() + { + StartValidation?.Invoke(); - public static class ValidationQueue - { - private static List m_Queue; - - static ValidationQueue() - { - m_Queue = new List(); - ValidationQueue.StartValidation += ValidateAll; + StartValidation = null; + } } - public static void Add(T obj) + public static class ValidationQueue { - m_Queue.Add(obj); + private static List m_Queue; + + static ValidationQueue() + { + m_Queue = new List(); + ValidationQueue.StartValidation += ValidateAll; + } + + public static void Add(T obj) + { + m_Queue.Add(obj); + } + + private static void ValidateAll() + { + var type = typeof(T); + + var m = type.GetMethod("Validate", BindingFlags.Instance | BindingFlags.Public); + + if (m != null) + for (var i = 0; i < m_Queue.Count; ++i) + m.Invoke(m_Queue[i], null); + + m_Queue.Clear(); + m_Queue = null; + } } - - private static void ValidateAll() - { - Type type = typeof(T); - - MethodInfo m = type.GetMethod("Validate", BindingFlags.Instance | BindingFlags.Public); - - if (m != null) - for (int i = 0; i < m_Queue.Count; ++i) - m.Invoke(m_Queue[i], null); - - m_Queue.Clear(); - m_Queue = null; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Misc/VendorGenerator.cs b/Projects/UOContent/Misc/VendorGenerator.cs index 5764007ce..8e4b532cc 100644 --- a/Projects/UOContent/Misc/VendorGenerator.cs +++ b/Projects/UOContent/Misc/VendorGenerator.cs @@ -5,436 +5,438 @@ using Server.Engines.Spawners; namespace Server { - public class VendorGenerator - { - private static readonly Rectangle2D[] m_BritRegions = + public class VendorGenerator { - new Rectangle2D(new Point2D(250, 750), new Point2D(775, 1330)), - new Rectangle2D(new Point2D(525, 2095), new Point2D(925, 2430)), - new Rectangle2D(new Point2D(1025, 2155), new Point2D(1265, 2310)), - new Rectangle2D(new Point2D(1635, 2430), new Point2D(1705, 2508)), - new Rectangle2D(new Point2D(1775, 2605), new Point2D(2165, 2975)), - new Rectangle2D(new Point2D(1055, 3520), new Point2D(1570, 4075)), - new Rectangle2D(new Point2D(2860, 3310), new Point2D(3120, 3630)), - new Rectangle2D(new Point2D(2470, 1855), new Point2D(3950, 3045)), - new Rectangle2D(new Point2D(3425, 990), new Point2D(3900, 1455)), - new Rectangle2D(new Point2D(4175, 735), new Point2D(4840, 1600)), - new Rectangle2D(new Point2D(2375, 330), new Point2D(3100, 1045)), - new Rectangle2D(new Point2D(2100, 1090), new Point2D(2310, 1450)), - new Rectangle2D(new Point2D(1495, 1400), new Point2D(1550, 1475)), - new Rectangle2D(new Point2D(1085, 1520), new Point2D(1415, 1910)), - new Rectangle2D(new Point2D(1410, 1500), new Point2D(1745, 1795)), - new Rectangle2D(new Point2D(5120, 2300), new Point2D(6143, 4095)) - }; - - private static readonly Rectangle2D[] m_IlshRegions = - { - new Rectangle2D(new Point2D(0, 0), new Point2D(288 * 8, 200 * 8)) - }; - - private static Dictionary m_ShopTable; - private static List m_ShopList; - - public static void Initialize() - { - CommandSystem.Register("VendorGen", AccessLevel.Administrator, VendorGen_OnCommand); - } - - [Usage("VendorGen")] - [Description("Generates vendors based on display cases and floor plans. Analyzes the map files, slow.")] - private static void VendorGen_OnCommand(CommandEventArgs e) - { - Process(Map.Trammel, m_BritRegions); - Process(Map.Felucca, m_BritRegions); - Process(Map.Ilshenar, m_IlshRegions); - } - - private static bool GetFloorZ(Map map, int x, int y, out int z) - { - LandTile lt = map.Tiles.GetLandTile(x, y); - - if (IsFloor(lt.ID) && map.CanFit(x, y, lt.Z, 16, false, false)) - { - z = lt.Z; - return true; - } - - StaticTile[] tiles = map.Tiles.GetStaticTiles(x, y); - - for (int i = 0; i < tiles.Length; ++i) - { - StaticTile t = tiles[i]; - ItemData id = TileData.ItemTable[t.ID & TileData.MaxItemValue]; - - if (IsStaticFloor(t.ID) && map.CanFit(x, y, t.Z + (id.Surface ? id.CalcHeight : 0), 16, false, false)) + private static readonly Rectangle2D[] m_BritRegions = { - z = t.Z + (id.Surface ? id.CalcHeight : 0); - return true; - } - } + new Rectangle2D(new Point2D(250, 750), new Point2D(775, 1330)), + new Rectangle2D(new Point2D(525, 2095), new Point2D(925, 2430)), + new Rectangle2D(new Point2D(1025, 2155), new Point2D(1265, 2310)), + new Rectangle2D(new Point2D(1635, 2430), new Point2D(1705, 2508)), + new Rectangle2D(new Point2D(1775, 2605), new Point2D(2165, 2975)), + new Rectangle2D(new Point2D(1055, 3520), new Point2D(1570, 4075)), + new Rectangle2D(new Point2D(2860, 3310), new Point2D(3120, 3630)), + new Rectangle2D(new Point2D(2470, 1855), new Point2D(3950, 3045)), + new Rectangle2D(new Point2D(3425, 990), new Point2D(3900, 1455)), + new Rectangle2D(new Point2D(4175, 735), new Point2D(4840, 1600)), + new Rectangle2D(new Point2D(2375, 330), new Point2D(3100, 1045)), + new Rectangle2D(new Point2D(2100, 1090), new Point2D(2310, 1450)), + new Rectangle2D(new Point2D(1495, 1400), new Point2D(1550, 1475)), + new Rectangle2D(new Point2D(1085, 1520), new Point2D(1415, 1910)), + new Rectangle2D(new Point2D(1410, 1500), new Point2D(1745, 1795)), + new Rectangle2D(new Point2D(5120, 2300), new Point2D(6143, 4095)) + }; - z = 0; - return false; - } - - private static bool IsFloor(Map map, int x, int y, bool canFit) - { - LandTile lt = map.Tiles.GetLandTile(x, y); - - if (IsFloor(lt.ID) && (canFit || CanFit(map, x, y, lt.Z))) - return true; - - StaticTile[] tiles = map.Tiles.GetStaticTiles(x, y); - - for (int i = 0; i < tiles.Length; ++i) - { - StaticTile t = tiles[i]; - ItemData id = TileData.ItemTable[t.ID & TileData.MaxItemValue]; - - if (IsStaticFloor(t.ID) && (canFit || CanFit(map, x, y, t.Z + (id.Surface ? id.CalcHeight : 0)))) - return true; - } - - return false; - } - - private static bool IsFloor(int itemID) - { - itemID &= TileData.MaxLandValue; - - return itemID >= 0x406 && itemID <= 0x51A; - } - - private static bool IsStaticFloor(int itemID) => - (itemID >= 0x495 && itemID <= 0x514) - || (itemID >= 0x519 && itemID <= 0x53A); - - private static bool IsDisplayCase(int itemID) => - (itemID >= 0xB00 && itemID <= 0xB02) - || (itemID >= 0xB06 && itemID <= 0xB0A) - || (itemID >= 0xB0D && itemID <= 0xB17); - - private static void Process(Map map, Rectangle2D[] regions) - { - m_ShopTable = new Dictionary(); - m_ShopList = new List(); - - World.Broadcast(0x35, true, "Generating vendor spawns for {0}, please wait.", map); - - for (int i = 0; i < regions.Length; ++i) - for (int x = 0; x < map.Width; ++x) - for (int y = 0; y < map.Height; ++y) - CheckPoint(map, regions[i].X + x, regions[i].Y + y); - - for (int i = 0; i < m_ShopList.Count; ++i) - { - ShopInfo si = m_ShopList[i]; - - int xTotal = 0; - int yTotal = 0; - - bool hasSpawner = false; - - for (int j = 0; j < si.m_Floor.Count; ++j) + private static readonly Rectangle2D[] m_IlshRegions = { - Point2D fp = si.m_Floor[j]; + new Rectangle2D(new Point2D(0, 0), new Point2D(288 * 8, 200 * 8)) + }; - xTotal += fp.X; - yTotal += fp.Y; + private static Dictionary m_ShopTable; + private static List m_ShopList; - IPooledEnumerable eable = map.GetItemsInRange(new Point3D(fp.X, fp.Y, 0), 0); - hasSpawner = eable.Any(); - eable.Free(); - - if (hasSpawner) - break; + public static void Initialize() + { + CommandSystem.Register("VendorGen", AccessLevel.Administrator, VendorGen_OnCommand); } - if (hasSpawner) - continue; - - int xAvg = xTotal / si.m_Floor.Count; - int yAvg = yTotal / si.m_Floor.Count; - - List names = new List(); - ShopFlags flags = si.m_Flags; - - if ((flags & ShopFlags.Armor) != 0) - names.Add("armorer"); - - if ((flags & ShopFlags.MetalWeapon) != 0) - names.Add("weaponsmith"); - - if ((flags & ShopFlags.ArcheryWeapon) != 0) - names.Add("bowyer"); - - if ((flags & ShopFlags.Scroll) != 0) - names.Add("mage"); - - if ((flags & ShopFlags.Spellbook) != 0) - names.Add("mage"); - - if ((flags & ShopFlags.Bread) != 0) - names.Add("baker"); - - if ((flags & ShopFlags.Jewel) != 0) - names.Add("jeweler"); - - if ((flags & ShopFlags.Potion) != 0) + [Usage("VendorGen")] + [Description("Generates vendors based on display cases and floor plans. Analyzes the map files, slow.")] + private static void VendorGen_OnCommand(CommandEventArgs e) { - names.Add("herbalist"); - names.Add("alchemist"); - names.Add("mage"); + Process(Map.Trammel, m_BritRegions); + Process(Map.Felucca, m_BritRegions); + Process(Map.Ilshenar, m_IlshRegions); } - if ((flags & ShopFlags.Reagent) != 0) + private static bool GetFloorZ(Map map, int x, int y, out int z) { - names.Add("mage"); - names.Add("herbalist"); - } + var lt = map.Tiles.GetLandTile(x, y); - if ((flags & ShopFlags.Clothes) != 0) - { - names.Add("tailor"); - names.Add("weaver"); - } - - for (int j = 0; j < names.Count; ++j) - { - Point2D cp = Point2D.Zero; - int dist = 100000; - - for (int k = 0; k < si.m_Floor.Count; ++k) - { - Point2D fp = si.m_Floor[k]; - - int rx = fp.X - xAvg; - int ry = fp.Y - yAvg; - int fd = (int)Math.Sqrt(rx * rx + ry * ry); - - if (fd > 0 && fd < 5) - fd -= Utility.Random(10); - - if (fd < dist && GetFloorZ(map, fp.X, fp.Y, out _)) + if (IsFloor(lt.ID) && map.CanFit(x, y, lt.Z, 16, false, false)) { - dist = fd; - cp = fp; + z = lt.Z; + return true; } - } - if (cp == Point2D.Zero) - continue; + var tiles = map.Tiles.GetStaticTiles(x, y); - if (!GetFloorZ(map, cp.X, cp.Y, out int z)) - continue; + for (var i = 0; i < tiles.Length; ++i) + { + var t = tiles[i]; + var id = TileData.ItemTable[t.ID & TileData.MaxItemValue]; - new Spawner(1, 1, 1, 0, 4, names[j]).MoveToWorld(new Point3D(cp.X, cp.Y, z), map); - } - } + if (IsStaticFloor(t.ID) && map.CanFit(x, y, t.Z + (id.Surface ? id.CalcHeight : 0), 16, false, false)) + { + z = t.Z + (id.Surface ? id.CalcHeight : 0); + return true; + } + } - World.Broadcast(0x35, true, "Generation complete. {0} spawners generated.", m_ShopList.Count); - } - - private static void CheckPoint(Map map, int x, int y) - { - if (IsFloor(map, x, y, true)) - CheckFloor(map, x, y); - } - - private static void CheckFloor(Map map, int x, int y) - { - StaticTile[] tiles = map.Tiles.GetStaticTiles(x, y); - - for (int i = 0; i < tiles.Length; ++i) - if (IsDisplayCase(tiles[i].ID)) - { - ProcessDisplayCase(map, tiles, x, y); - break; - } - } - - private static bool IsClothes(int itemID) => - (itemID >= 0x1515 && itemID <= 0x1518) || (itemID >= 0x152E && itemID <= 0x1531) || (itemID >= 0x1537 - && itemID <= 0x154C) || (itemID >= 0x1EFD && itemID <= 0x1F04) || (itemID >= 0x170B && itemID <= 0x171C); - - private static bool IsArmor(int itemID) => - (itemID >= 0x13BB && itemID <= 0x13E2) || (itemID >= 0x13E5 && itemID <= 0x13F2) || - (itemID >= 0x1408 && itemID <= 0x141A) || (itemID >= 0x144E && itemID <= 0x1457); - - private static bool IsMetalWeapon(int itemID) => - (itemID >= 0xF43 && itemID <= 0xF4E) || (itemID >= 0xF51 && itemID <= 0xF52) || - (itemID >= 0xF5C && itemID <= 0xF63) || (itemID >= 0x13AF && itemID <= 0x13B0) || - (itemID >= 0x13B5 && itemID <= 0x13BA) || (itemID >= 0x13FA && itemID <= 0x13FB) || - (itemID >= 0x13FE && itemID <= 0x1407) || (itemID >= 0x1438 && itemID <= 0x1443); - - private static bool IsArcheryWeapon(int itemID) => - (itemID >= 0xF4F && itemID <= 0xF50) || (itemID >= 0x13B1 && itemID <= 0x13B2) || - (itemID >= 0x13FC && itemID <= 0x13FD); - - private static ShopFlags ProcessDisplayedItem(int itemID) - { - itemID &= TileData.MaxItemValue; - - ShopFlags res = ShopFlags.None; - - ItemData id = TileData.ItemTable[itemID]; - TileFlag flags = id.Flags; - - if ((flags & TileFlag.Wearable) != 0) - { - if (IsClothes(itemID)) - res |= ShopFlags.Clothes; - else if (IsArmor(itemID)) - res |= ShopFlags.Armor; - else if (IsMetalWeapon(itemID)) - res |= ShopFlags.MetalWeapon; - else if (IsArcheryWeapon(itemID)) - res |= ShopFlags.ArcheryWeapon; - } - - if (itemID == 0x98C || itemID == 0x103B || itemID == 0x103C) - res |= ShopFlags.Bread; - - if (itemID >= 0xF0F && itemID <= 0xF30) - res |= ShopFlags.Jewel; - - if (itemID >= 0xEFB && itemID <= 0xF0D) - res |= ShopFlags.Potion; - - if (itemID >= 0xF78 && itemID <= 0xF91) - res |= ShopFlags.Reagent; - - if ((itemID >= 0xE35 && itemID <= 0xE3A) || (itemID >= 0xEF4 && itemID <= 0xEF9) || - (itemID >= 0x1F2D && itemID <= 0x1F72)) - res |= ShopFlags.Scroll; - - if (itemID == 0xE38 || itemID == 0xEFA) - res |= ShopFlags.Spellbook; - - return res; - } - - private static void ProcessDisplayCase(Map map, StaticTile[] tiles, int x, int y) - { - ShopFlags flags = tiles.Aggregate(ShopFlags.None, (current, t) => current | ProcessDisplayedItem(t.ID)); - - if (flags != ShopFlags.None) - { - Point2D p = new Point2D(x, y); - - if (m_ShopTable.TryGetValue(p, out ShopInfo si)) - si.m_Flags |= flags; - else - { - List floor = new List(); - - RecurseFindFloor(map, x, y, floor); - - if (floor.Count == 0) - return; - - si = new ShopInfo { m_Flags = flags, m_Floor = floor }; - m_ShopList.Add(si); - - for (int i = 0; i < floor.Count; ++i) - m_ShopTable[floor[i]] = si; - } - } - } - - private static bool CanFit(Map map, int x, int y, int z) - { - bool hasSurface = false; - - LandTile lt = map.Tiles.GetLandTile(x, y); - int lowZ = 0, avgZ = 0, topZ = 0; - - map.GetAverageZ(x, y, ref lowZ, ref avgZ, ref topZ); - TileFlag landFlags = TileData.LandTable[lt.ID & TileData.MaxLandValue].Flags; - - if ((landFlags & TileFlag.Impassable) != 0 && topZ > z && z + 16 > lowZ) - return false; - if ((landFlags & TileFlag.Impassable) == 0 && z == avgZ && !lt.Ignored) - hasSurface = true; - - StaticTile[] staticTiles = map.Tiles.GetStaticTiles(x, y); - - bool surface, impassable; - - for (int i = 0; i < staticTiles.Length; ++i) - { - if (IsDisplayCase(staticTiles[i].ID)) - continue; - - ItemData id = TileData.ItemTable[staticTiles[i].ID & TileData.MaxItemValue]; - - surface = id.Surface; - impassable = id.Impassable; - - if ((surface || impassable) && staticTiles[i].Z + id.CalcHeight > z && z + 16 > staticTiles[i].Z) - return false; - if (surface && !impassable && z == staticTiles[i].Z + id.CalcHeight) - hasSurface = true; - } - - Sector sector = map.GetSector(x, y); - List items = sector.Items; - - for (int i = 0; i < items.Count; ++i) - { - Item item = items[i]; - - if (item.AtWorldPoint(x, y)) - { - ItemData id = item.ItemData; - surface = id.Surface; - impassable = id.Impassable; - - if ((surface || impassable) && item.Z + id.CalcHeight > z && z + 16 > item.Z) + z = 0; return false; - if (surface && !impassable && z == item.Z + id.CalcHeight) - hasSurface = true; } - } - return hasSurface; + private static bool IsFloor(Map map, int x, int y, bool canFit) + { + var lt = map.Tiles.GetLandTile(x, y); + + if (IsFloor(lt.ID) && (canFit || CanFit(map, x, y, lt.Z))) + return true; + + var tiles = map.Tiles.GetStaticTiles(x, y); + + for (var i = 0; i < tiles.Length; ++i) + { + var t = tiles[i]; + var id = TileData.ItemTable[t.ID & TileData.MaxItemValue]; + + if (IsStaticFloor(t.ID) && (canFit || CanFit(map, x, y, t.Z + (id.Surface ? id.CalcHeight : 0)))) + return true; + } + + return false; + } + + private static bool IsFloor(int itemID) + { + itemID &= TileData.MaxLandValue; + + return itemID >= 0x406 && itemID <= 0x51A; + } + + private static bool IsStaticFloor(int itemID) => + itemID >= 0x495 && itemID <= 0x514 + || itemID >= 0x519 && itemID <= 0x53A; + + private static bool IsDisplayCase(int itemID) => + itemID >= 0xB00 && itemID <= 0xB02 + || itemID >= 0xB06 && itemID <= 0xB0A + || itemID >= 0xB0D && itemID <= 0xB17; + + private static void Process(Map map, Rectangle2D[] regions) + { + m_ShopTable = new Dictionary(); + m_ShopList = new List(); + + World.Broadcast(0x35, true, "Generating vendor spawns for {0}, please wait.", map); + + for (var i = 0; i < regions.Length; ++i) + for (var x = 0; x < map.Width; ++x) + for (var y = 0; y < map.Height; ++y) + CheckPoint(map, regions[i].X + x, regions[i].Y + y); + + for (var i = 0; i < m_ShopList.Count; ++i) + { + var si = m_ShopList[i]; + + var xTotal = 0; + var yTotal = 0; + + var hasSpawner = false; + + for (var j = 0; j < si.m_Floor.Count; ++j) + { + var fp = si.m_Floor[j]; + + xTotal += fp.X; + yTotal += fp.Y; + + var eable = map.GetItemsInRange(new Point3D(fp.X, fp.Y, 0), 0); + hasSpawner = eable.Any(); + eable.Free(); + + if (hasSpawner) + break; + } + + if (hasSpawner) + continue; + + var xAvg = xTotal / si.m_Floor.Count; + var yAvg = yTotal / si.m_Floor.Count; + + var names = new List(); + var flags = si.m_Flags; + + if ((flags & ShopFlags.Armor) != 0) + names.Add("armorer"); + + if ((flags & ShopFlags.MetalWeapon) != 0) + names.Add("weaponsmith"); + + if ((flags & ShopFlags.ArcheryWeapon) != 0) + names.Add("bowyer"); + + if ((flags & ShopFlags.Scroll) != 0) + names.Add("mage"); + + if ((flags & ShopFlags.Spellbook) != 0) + names.Add("mage"); + + if ((flags & ShopFlags.Bread) != 0) + names.Add("baker"); + + if ((flags & ShopFlags.Jewel) != 0) + names.Add("jeweler"); + + if ((flags & ShopFlags.Potion) != 0) + { + names.Add("herbalist"); + names.Add("alchemist"); + names.Add("mage"); + } + + if ((flags & ShopFlags.Reagent) != 0) + { + names.Add("mage"); + names.Add("herbalist"); + } + + if ((flags & ShopFlags.Clothes) != 0) + { + names.Add("tailor"); + names.Add("weaver"); + } + + for (var j = 0; j < names.Count; ++j) + { + var cp = Point2D.Zero; + var dist = 100000; + + for (var k = 0; k < si.m_Floor.Count; ++k) + { + var fp = si.m_Floor[k]; + + var rx = fp.X - xAvg; + var ry = fp.Y - yAvg; + var fd = (int)Math.Sqrt(rx * rx + ry * ry); + + if (fd > 0 && fd < 5) + fd -= Utility.Random(10); + + if (fd < dist && GetFloorZ(map, fp.X, fp.Y, out _)) + { + dist = fd; + cp = fp; + } + } + + if (cp == Point2D.Zero) + continue; + + if (!GetFloorZ(map, cp.X, cp.Y, out var z)) + continue; + + new Spawner(1, 1, 1, 0, 4, names[j]).MoveToWorld(new Point3D(cp.X, cp.Y, z), map); + } + } + + World.Broadcast(0x35, true, "Generation complete. {0} spawners generated.", m_ShopList.Count); + } + + private static void CheckPoint(Map map, int x, int y) + { + if (IsFloor(map, x, y, true)) + CheckFloor(map, x, y); + } + + private static void CheckFloor(Map map, int x, int y) + { + var tiles = map.Tiles.GetStaticTiles(x, y); + + for (var i = 0; i < tiles.Length; ++i) + if (IsDisplayCase(tiles[i].ID)) + { + ProcessDisplayCase(map, tiles, x, y); + break; + } + } + + private static bool IsClothes(int itemID) => + itemID >= 0x1515 && itemID <= 0x1518 || itemID >= 0x152E && itemID <= 0x1531 || itemID >= 0x1537 + && itemID <= 0x154C || itemID >= 0x1EFD && itemID <= 0x1F04 || itemID >= 0x170B && itemID <= 0x171C; + + private static bool IsArmor(int itemID) => + itemID >= 0x13BB && itemID <= 0x13E2 || itemID >= 0x13E5 && itemID <= 0x13F2 || + itemID >= 0x1408 && itemID <= 0x141A || itemID >= 0x144E && itemID <= 0x1457; + + private static bool IsMetalWeapon(int itemID) => + itemID >= 0xF43 && itemID <= 0xF4E || itemID >= 0xF51 && itemID <= 0xF52 || + itemID >= 0xF5C && itemID <= 0xF63 || itemID >= 0x13AF && itemID <= 0x13B0 || + itemID >= 0x13B5 && itemID <= 0x13BA || itemID >= 0x13FA && itemID <= 0x13FB || + itemID >= 0x13FE && itemID <= 0x1407 || itemID >= 0x1438 && itemID <= 0x1443; + + private static bool IsArcheryWeapon(int itemID) => + itemID >= 0xF4F && itemID <= 0xF50 || itemID >= 0x13B1 && itemID <= 0x13B2 || + itemID >= 0x13FC && itemID <= 0x13FD; + + private static ShopFlags ProcessDisplayedItem(int itemID) + { + itemID &= TileData.MaxItemValue; + + var res = ShopFlags.None; + + var id = TileData.ItemTable[itemID]; + var flags = id.Flags; + + if ((flags & TileFlag.Wearable) != 0) + { + if (IsClothes(itemID)) + res |= ShopFlags.Clothes; + else if (IsArmor(itemID)) + res |= ShopFlags.Armor; + else if (IsMetalWeapon(itemID)) + res |= ShopFlags.MetalWeapon; + else if (IsArcheryWeapon(itemID)) + res |= ShopFlags.ArcheryWeapon; + } + + if (itemID == 0x98C || itemID == 0x103B || itemID == 0x103C) + res |= ShopFlags.Bread; + + if (itemID >= 0xF0F && itemID <= 0xF30) + res |= ShopFlags.Jewel; + + if (itemID >= 0xEFB && itemID <= 0xF0D) + res |= ShopFlags.Potion; + + if (itemID >= 0xF78 && itemID <= 0xF91) + res |= ShopFlags.Reagent; + + if (itemID >= 0xE35 && itemID <= 0xE3A || itemID >= 0xEF4 && itemID <= 0xEF9 || + itemID >= 0x1F2D && itemID <= 0x1F72) + res |= ShopFlags.Scroll; + + if (itemID == 0xE38 || itemID == 0xEFA) + res |= ShopFlags.Spellbook; + + return res; + } + + private static void ProcessDisplayCase(Map map, StaticTile[] tiles, int x, int y) + { + var flags = tiles.Aggregate(ShopFlags.None, (current, t) => current | ProcessDisplayedItem(t.ID)); + + if (flags != ShopFlags.None) + { + var p = new Point2D(x, y); + + if (m_ShopTable.TryGetValue(p, out var si)) + { + si.m_Flags |= flags; + } + else + { + var floor = new List(); + + RecurseFindFloor(map, x, y, floor); + + if (floor.Count == 0) + return; + + si = new ShopInfo { m_Flags = flags, m_Floor = floor }; + m_ShopList.Add(si); + + for (var i = 0; i < floor.Count; ++i) + m_ShopTable[floor[i]] = si; + } + } + } + + private static bool CanFit(Map map, int x, int y, int z) + { + var hasSurface = false; + + var lt = map.Tiles.GetLandTile(x, y); + int lowZ = 0, avgZ = 0, topZ = 0; + + map.GetAverageZ(x, y, ref lowZ, ref avgZ, ref topZ); + var landFlags = TileData.LandTable[lt.ID & TileData.MaxLandValue].Flags; + + if ((landFlags & TileFlag.Impassable) != 0 && topZ > z && z + 16 > lowZ) + return false; + if ((landFlags & TileFlag.Impassable) == 0 && z == avgZ && !lt.Ignored) + hasSurface = true; + + var staticTiles = map.Tiles.GetStaticTiles(x, y); + + bool surface, impassable; + + for (var i = 0; i < staticTiles.Length; ++i) + { + if (IsDisplayCase(staticTiles[i].ID)) + continue; + + var id = TileData.ItemTable[staticTiles[i].ID & TileData.MaxItemValue]; + + surface = id.Surface; + impassable = id.Impassable; + + if ((surface || impassable) && staticTiles[i].Z + id.CalcHeight > z && z + 16 > staticTiles[i].Z) + return false; + if (surface && !impassable && z == staticTiles[i].Z + id.CalcHeight) + hasSurface = true; + } + + var sector = map.GetSector(x, y); + var items = sector.Items; + + for (var i = 0; i < items.Count; ++i) + { + var item = items[i]; + + if (item.AtWorldPoint(x, y)) + { + var id = item.ItemData; + surface = id.Surface; + impassable = id.Impassable; + + if ((surface || impassable) && item.Z + id.CalcHeight > z && z + 16 > item.Z) + return false; + if (surface && !impassable && z == item.Z + id.CalcHeight) + hasSurface = true; + } + } + + return hasSurface; + } + + private static void RecurseFindFloor(Map map, int x, int y, List floor) + { + var p = new Point2D(x, y); + + if (floor.Contains(p)) + return; + + floor.Add(p); + + for (var xo = -1; xo <= 1; ++xo) + for (var yo = -1; yo <= 1; ++yo) + if ((xo != 0 || yo != 0) && IsFloor(map, x + xo, y + yo, false)) + RecurseFindFloor(map, x + xo, y + yo, floor); + } + + [Flags] + private enum ShopFlags + { + None = 0x000, + Armor = 0x001, + MetalWeapon = 0x002, + Jewel = 0x004, + Reagent = 0x008, + Potion = 0x010, + Bread = 0x020, + Clothes = 0x040, + ArcheryWeapon = 0x080, + Scroll = 0x100, + Spellbook = 0x200 + } + + private class ShopInfo + { + public ShopFlags m_Flags; + public List m_Floor; + } } - - private static void RecurseFindFloor(Map map, int x, int y, List floor) - { - Point2D p = new Point2D(x, y); - - if (floor.Contains(p)) - return; - - floor.Add(p); - - for (int xo = -1; xo <= 1; ++xo) - for (int yo = -1; yo <= 1; ++yo) - if ((xo != 0 || yo != 0) && IsFloor(map, x + xo, y + yo, false)) - RecurseFindFloor(map, x + xo, y + yo, floor); - } - - [Flags] - private enum ShopFlags - { - None = 0x000, - Armor = 0x001, - MetalWeapon = 0x002, - Jewel = 0x004, - Reagent = 0x008, - Potion = 0x010, - Bread = 0x020, - Clothes = 0x040, - ArcheryWeapon = 0x080, - Scroll = 0x100, - Spellbook = 0x200 - } - - private class ShopInfo - { - public ShopFlags m_Flags; - public List m_Floor; - } - } } diff --git a/Projects/UOContent/Misc/Weather.cs b/Projects/UOContent/Misc/Weather.cs index b8a7765fe..1245144a3 100644 --- a/Projects/UOContent/Misc/Weather.cs +++ b/Projects/UOContent/Misc/Weather.cs @@ -5,346 +5,391 @@ using Server.Network; namespace Server.Misc { - public class Weather - { - private static Map[] m_Facets; - private static readonly Dictionary> m_WeatherByFacet = new Dictionary>(); - - public static void Initialize() + public class Weather { - m_Facets = new[] { Map.Felucca, Map.Trammel }; + private static Map[] m_Facets; + private static readonly Dictionary> m_WeatherByFacet = new Dictionary>(); + private bool m_Active; + private bool m_ExtremeTemperature; - /* Static weather: - * - * Format: - * AddWeather( temperature, chanceOfPercipitation, chanceOfExtremeTemperature, ); - */ + private int m_Stage; - // ice island - AddWeather(-15, 100, 5, new Rectangle2D(3850, 160, 390, 320), new Rectangle2D(3900, 480, 380, 180), new Rectangle2D(4160, 660, 150, 110)); - - // covetous entrance, around vesper and minoc - AddWeather(+15, 50, 5, new Rectangle2D(2425, 725, 250, 250)); - - // despise entrance, north of britain - AddWeather(+15, 50, 5, new Rectangle2D(1245, 1045, 250, 250)); - - /* Dynamic weather: - * - * Format: - * AddDynamicWeather( temperature, chanceOfPercipitation, chanceOfExtremeTemperature, moveSpeed, width, height, bounds ); - */ - - for (int i = 0; i < 15; ++i) - AddDynamicWeather(+15, 100, 5, 8, 400, 400, new Rectangle2D(0, 0, 5120, 4096)); - } - - public static List GetWeatherList(Map facet) - { - if (facet == null) - return null; - - if (!m_WeatherByFacet.TryGetValue(facet, out List list)) - m_WeatherByFacet[facet] = list = new List(); - - return list; - } - - public static void AddDynamicWeather(int temperature, int chanceOfPercipitation, int chanceOfExtremeTemperature, int moveSpeed, int width, int height, Rectangle2D bounds) - { - for (int i = 0; i < m_Facets.Length; ++i) - { - Rectangle2D area = new Rectangle2D(); - bool isValid = false; - - for (int j = 0; j < 10; ++j) + public Weather( + Map facet, Rectangle2D[] area, int temperature, int chanceOfPercipitation, int chanceOfExtremeTemperature, + TimeSpan interval + ) { - area = new Rectangle2D(bounds.X + Utility.Random(bounds.Width - width), bounds.Y + Utility.Random(bounds.Height - height), width, height); + Facet = facet; + Area = area; + Temperature = temperature; + ChanceOfPercipitation = chanceOfPercipitation; + ChanceOfExtremeTemperature = chanceOfExtremeTemperature; - if (!CheckWeatherConflict(m_Facets[i], null, area)) - isValid = true; + var list = GetWeatherList(facet); - if (isValid) - break; + list?.Add(this); + + Timer.DelayCall( + TimeSpan.FromSeconds((0.2 + Utility.RandomDouble() * 0.8) * interval.TotalSeconds), + interval, + OnTick + ); } - if (!isValid) - continue; + public Map Facet { get; } - new Weather(m_Facets[i], new[] { area }, temperature, chanceOfPercipitation, chanceOfExtremeTemperature, - TimeSpan.FromSeconds(30.0)) - { Bounds = bounds, MoveSpeed = moveSpeed }; - } - } + public Rectangle2D[] Area { get; set; } - public static void AddWeather(int temperature, int chanceOfPercipitation, int chanceOfExtremeTemperature, params Rectangle2D[] area) - { - for (int i = 0; i < m_Facets.Length; ++i) - new Weather(m_Facets[i], area, temperature, chanceOfPercipitation, chanceOfExtremeTemperature, TimeSpan.FromSeconds(30.0)); - } + public int Temperature { get; set; } - public static bool CheckWeatherConflict(Map facet, Weather exclude, Rectangle2D area) - { - List list = GetWeatherList(facet); + public int ChanceOfPercipitation { get; set; } - if (list == null) - return false; + public int ChanceOfExtremeTemperature { get; set; } - for (int i = 0; i < list.Count; ++i) - { - Weather w = list[i]; + // For dynamic weather: - if (w != exclude && w.IntersectsWith(area)) - return true; - } + public Rectangle2D Bounds { get; set; } - return false; - } + public int MoveSpeed { get; set; } - public Map Facet { get; } + public int MoveAngleX { get; set; } - public Rectangle2D[] Area { get; set; } + public int MoveAngleY { get; set; } - public int Temperature { get; set; } - - public int ChanceOfPercipitation { get; set; } - - public int ChanceOfExtremeTemperature { get; set; } - - // For dynamic weather: - - public Rectangle2D Bounds { get; set; } - - public int MoveSpeed { get; set; } - - public int MoveAngleX { get; set; } - - public int MoveAngleY { get; set; } - - public static bool CheckIntersection(Rectangle2D r1, Rectangle2D r2) => r1.X < r2.X + r2.Width && r2.X < r1.X + r1.Width && r1.Y < r2.Y + r2.Height && r2.Y < r1.Y + r1.Height; - - public static bool CheckContains(Rectangle2D big, Rectangle2D small) => - small.X >= big.X && small.Y >= big.Y && small.X + small.Width <= big.X + big.Width - && small.Y + small.Height <= big.Y + big.Height; - - public virtual bool IntersectsWith(Rectangle2D area) - { - for (int i = 0; i < Area.Length; ++i) - if (CheckIntersection(area, Area[i])) - return true; - - return false; - } - - public Weather(Map facet, Rectangle2D[] area, int temperature, int chanceOfPercipitation, int chanceOfExtremeTemperature, TimeSpan interval) - { - Facet = facet; - Area = area; - Temperature = temperature; - ChanceOfPercipitation = chanceOfPercipitation; - ChanceOfExtremeTemperature = chanceOfExtremeTemperature; - - List list = GetWeatherList(facet); - - list?.Add(this); - - Timer.DelayCall(TimeSpan.FromSeconds((0.2 + Utility.RandomDouble() * 0.8) * interval.TotalSeconds), interval, OnTick); - } - - public virtual void Reposition() - { - if (Area.Length == 0) - return; - - int width = Area[0].Width; - int height = Area[0].Height; - - Rectangle2D area = new Rectangle2D(); - bool isValid = false; - - for (int j = 0; j < 10; ++j) - { - area = new Rectangle2D(Bounds.X + Utility.Random(Bounds.Width - width), Bounds.Y + Utility.Random(Bounds.Height - height), width, height); - - if (!CheckWeatherConflict(Facet, this, area)) - isValid = true; - - if (isValid) - break; - } - - if (!isValid) - return; - - Area[0] = area; - } - - public virtual void RecalculateMovementAngle() - { - double angle = Utility.RandomDouble() * Math.PI * 2.0; - - double cos = Math.Cos(angle); - double sin = Math.Sin(angle); - - MoveAngleX = (int)(100 * cos); - MoveAngleY = (int)(100 * sin); - } - - public virtual void MoveForward() - { - if (Area.Length == 0) - return; - - for (int i = 0; i < 5; ++i) // try 5 times to find a valid spot - { - int xOffset = MoveSpeed * MoveAngleX / 100; - int yOffset = MoveSpeed * MoveAngleY / 100; - - Rectangle2D oldArea = Area[0]; - Rectangle2D newArea = new Rectangle2D(oldArea.X + xOffset, oldArea.Y + yOffset, oldArea.Width, oldArea.Height); - - if (!CheckWeatherConflict(Facet, this, newArea) && CheckContains(Bounds, newArea)) + public static void Initialize() { - Area[0] = newArea; - break; + m_Facets = new[] { Map.Felucca, Map.Trammel }; + + /* Static weather: + * + * Format: + * AddWeather( temperature, chanceOfPercipitation, chanceOfExtremeTemperature, ); + */ + + // ice island + AddWeather( + -15, + 100, + 5, + new Rectangle2D(3850, 160, 390, 320), + new Rectangle2D(3900, 480, 380, 180), + new Rectangle2D(4160, 660, 150, 110) + ); + + // covetous entrance, around vesper and minoc + AddWeather(+15, 50, 5, new Rectangle2D(2425, 725, 250, 250)); + + // despise entrance, north of britain + AddWeather(+15, 50, 5, new Rectangle2D(1245, 1045, 250, 250)); + + /* Dynamic weather: + * + * Format: + * AddDynamicWeather( temperature, chanceOfPercipitation, chanceOfExtremeTemperature, moveSpeed, width, height, bounds ); + */ + + for (var i = 0; i < 15; ++i) + AddDynamicWeather(+15, 100, 5, 8, 400, 400, new Rectangle2D(0, 0, 5120, 4096)); } - RecalculateMovementAngle(); - } - } - - private int m_Stage; - private bool m_Active; - private bool m_ExtremeTemperature; - - public virtual void OnTick() - { - if (m_Stage == 0) - { - m_Active = ChanceOfPercipitation > Utility.Random(100); - m_ExtremeTemperature = ChanceOfExtremeTemperature > Utility.Random(100); - - if (MoveSpeed > 0) + public static List GetWeatherList(Map facet) { - Reposition(); - RecalculateMovementAngle(); - } - } + if (facet == null) + return null; - if (m_Active) - { - if (m_Stage > 0 && MoveSpeed > 0) - MoveForward(); + if (!m_WeatherByFacet.TryGetValue(facet, out var list)) + m_WeatherByFacet[facet] = list = new List(); - int type, density; - int temperature = Temperature; - - if (m_ExtremeTemperature) - temperature *= -1; - - if (m_Stage < 15) - { - density = m_Stage * 5; - } - else - { - density = 150 - m_Stage * 5; - - if (density < 10) - density = 10; - else if (density > 70) - density = 70; + return list; } - if (density == 0) - type = 0xFE; - else if (temperature > 0) - type = 0; - else - type = 2; - - List states = TcpServer.Instances; - - Packet weatherPacket = null; - - for (int i = 0; i < states.Count; ++i) + public static void AddDynamicWeather( + int temperature, int chanceOfPercipitation, int chanceOfExtremeTemperature, int moveSpeed, int width, int height, + Rectangle2D bounds + ) { - NetState ns = states[i]; - Mobile mob = ns.Mobile; + for (var i = 0; i < m_Facets.Length; ++i) + { + var area = new Rectangle2D(); + var isValid = false; - if (mob == null || mob.Map != Facet) - continue; + for (var j = 0; j < 10; ++j) + { + area = new Rectangle2D( + bounds.X + Utility.Random(bounds.Width - width), + bounds.Y + Utility.Random(bounds.Height - height), + width, + height + ); - bool contains = Area.Length == 0; + if (!CheckWeatherConflict(m_Facets[i], null, area)) + isValid = true; - for (int j = 0; !contains && j < Area.Length; ++j) - contains = Area[j].Contains(mob.Location); + if (isValid) + break; + } - if (!contains) - continue; + if (!isValid) + continue; - if (weatherPacket == null) - weatherPacket = Packet.Acquire(new Server.Network.Weather(type, density, temperature)); - - ns.Send(weatherPacket); + new Weather( + m_Facets[i], + new[] { area }, + temperature, + chanceOfPercipitation, + chanceOfExtremeTemperature, + TimeSpan.FromSeconds(30.0) + ) + { Bounds = bounds, MoveSpeed = moveSpeed }; + } } - Packet.Release(weatherPacket); - } + public static void AddWeather( + int temperature, int chanceOfPercipitation, int chanceOfExtremeTemperature, params Rectangle2D[] area + ) + { + for (var i = 0; i < m_Facets.Length; ++i) + new Weather( + m_Facets[i], + area, + temperature, + chanceOfPercipitation, + chanceOfExtremeTemperature, + TimeSpan.FromSeconds(30.0) + ); + } - m_Stage++; - m_Stage %= 30; + public static bool CheckWeatherConflict(Map facet, Weather exclude, Rectangle2D area) + { + var list = GetWeatherList(facet); + + if (list == null) + return false; + + for (var i = 0; i < list.Count; ++i) + { + var w = list[i]; + + if (w != exclude && w.IntersectsWith(area)) + return true; + } + + return false; + } + + public static bool CheckIntersection(Rectangle2D r1, Rectangle2D r2) => r1.X < r2.X + r2.Width && + r2.X < r1.X + r1.Width && + r1.Y < r2.Y + r2.Height && + r2.Y < r1.Y + r1.Height; + + public static bool CheckContains(Rectangle2D big, Rectangle2D small) => + small.X >= big.X && small.Y >= big.Y && small.X + small.Width <= big.X + big.Width + && small.Y + small.Height <= big.Y + big.Height; + + public virtual bool IntersectsWith(Rectangle2D area) + { + for (var i = 0; i < Area.Length; ++i) + if (CheckIntersection(area, Area[i])) + return true; + + return false; + } + + public virtual void Reposition() + { + if (Area.Length == 0) + return; + + var width = Area[0].Width; + var height = Area[0].Height; + + var area = new Rectangle2D(); + var isValid = false; + + for (var j = 0; j < 10; ++j) + { + area = new Rectangle2D( + Bounds.X + Utility.Random(Bounds.Width - width), + Bounds.Y + Utility.Random(Bounds.Height - height), + width, + height + ); + + if (!CheckWeatherConflict(Facet, this, area)) + isValid = true; + + if (isValid) + break; + } + + if (!isValid) + return; + + Area[0] = area; + } + + public virtual void RecalculateMovementAngle() + { + var angle = Utility.RandomDouble() * Math.PI * 2.0; + + var cos = Math.Cos(angle); + var sin = Math.Sin(angle); + + MoveAngleX = (int)(100 * cos); + MoveAngleY = (int)(100 * sin); + } + + public virtual void MoveForward() + { + if (Area.Length == 0) + return; + + for (var i = 0; i < 5; ++i) // try 5 times to find a valid spot + { + var xOffset = MoveSpeed * MoveAngleX / 100; + var yOffset = MoveSpeed * MoveAngleY / 100; + + var oldArea = Area[0]; + var newArea = new Rectangle2D(oldArea.X + xOffset, oldArea.Y + yOffset, oldArea.Width, oldArea.Height); + + if (!CheckWeatherConflict(Facet, this, newArea) && CheckContains(Bounds, newArea)) + { + Area[0] = newArea; + break; + } + + RecalculateMovementAngle(); + } + } + + public virtual void OnTick() + { + if (m_Stage == 0) + { + m_Active = ChanceOfPercipitation > Utility.Random(100); + m_ExtremeTemperature = ChanceOfExtremeTemperature > Utility.Random(100); + + if (MoveSpeed > 0) + { + Reposition(); + RecalculateMovementAngle(); + } + } + + if (m_Active) + { + if (m_Stage > 0 && MoveSpeed > 0) + MoveForward(); + + int type, density; + var temperature = Temperature; + + if (m_ExtremeTemperature) + temperature *= -1; + + if (m_Stage < 15) + { + density = m_Stage * 5; + } + else + { + density = 150 - m_Stage * 5; + + if (density < 10) + density = 10; + else if (density > 70) + density = 70; + } + + if (density == 0) + type = 0xFE; + else if (temperature > 0) + type = 0; + else + type = 2; + + var states = TcpServer.Instances; + + Packet weatherPacket = null; + + for (var i = 0; i < states.Count; ++i) + { + var ns = states[i]; + var mob = ns.Mobile; + + if (mob == null || mob.Map != Facet) + continue; + + var contains = Area.Length == 0; + + for (var j = 0; !contains && j < Area.Length; ++j) + contains = Area[j].Contains(mob.Location); + + if (!contains) + continue; + + if (weatherPacket == null) + weatherPacket = Packet.Acquire(new Network.Weather(type, density, temperature)); + + ns.Send(weatherPacket); + } + + Packet.Release(weatherPacket); + } + + m_Stage++; + m_Stage %= 30; + } } - } - public class WeatherMap : MapItem - { - public override string DefaultName => "weather map"; - - [Constructible] - public WeatherMap() + public class WeatherMap : MapItem { - SetDisplay(0, 0, 5119, 4095, 400, 400); + [Constructible] + public WeatherMap() + { + SetDisplay(0, 0, 5119, 4095, 400, 400); + } + + public WeatherMap(Serial serial) : base(serial) + { + } + + public override string DefaultName => "weather map"; + + public override void OnDoubleClick(Mobile from) + { + var facet = from.Map; + + if (facet == null) + return; + + var list = Weather.GetWeatherList(facet); + + ClearPins(); + + for (var i = 0; i < list.Count; ++i) + { + var w = list[i]; + + for (var j = 0; j < w.Area.Length; ++j) + AddWorldPin(w.Area[j].X + w.Area[j].Width / 2, w.Area[j].Y + w.Area[j].Height / 2); + } + + base.OnDoubleClick(from); + } + + 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(); + } } - - public override void OnDoubleClick(Mobile from) - { - Map facet = from.Map; - - if (facet == null) - return; - - List list = Weather.GetWeatherList(facet); - - ClearPins(); - - for (int i = 0; i < list.Count; ++i) - { - Weather w = list[i]; - - for (int j = 0; j < w.Area.Length; ++j) - AddWorldPin(w.Area[j].X + w.Area[j].Width / 2, w.Area[j].Y + w.Area[j].Height / 2); - } - - base.OnDoubleClick(from); - } - - public WeatherMap(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Misc/WebStatus.cs b/Projects/UOContent/Misc/WebStatus.cs index ccee6bb79..b7ea82ab1 100644 --- a/Projects/UOContent/Misc/WebStatus.cs +++ b/Projects/UOContent/Misc/WebStatus.cs @@ -8,173 +8,174 @@ using Server.Network; namespace Server.Misc { - public class StatusPage : Timer - { - public static readonly bool Enabled = false; - - private static HttpListener _Listener; - - private static string _StatusPage = string.Empty; - private static byte[] _StatusBuffer = Array.Empty(); - - private static readonly object _StatusLock = new object(); - - public StatusPage() - : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(60.0)) => - Priority = TimerPriority.FiveSeconds; - - public static void Initialize() + public class StatusPage : Timer { - if (!Enabled) return; + public static readonly bool Enabled = false; - new StatusPage().Start(); + private static HttpListener _Listener; - Listen(); - } + private static string _StatusPage = string.Empty; + private static byte[] _StatusBuffer = Array.Empty(); - private static void Listen() - { - if (!HttpListener.IsSupported) return; + private static readonly object _StatusLock = new object(); - if (_Listener == null) - { - _Listener = new HttpListener(); - _Listener.Prefixes.Add("http://*:80/status/"); - _Listener.Start(); - } - else if (!_Listener.IsListening) - { - _Listener.Start(); - } + public StatusPage() + : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(60.0)) => + Priority = TimerPriority.FiveSeconds; - if (_Listener.IsListening) _Listener.BeginGetContext(ListenerCallback, null); - } - - private static void ListenerCallback(IAsyncResult result) - { - try - { - HttpListenerContext context = _Listener.EndGetContext(result); - - byte[] buffer; - - lock (_StatusLock) + public static void Initialize() { - buffer = _StatusBuffer; + if (!Enabled) return; + + new StatusPage().Start(); + + Listen(); } - context.Response.ContentLength64 = buffer.Length; - context.Response.OutputStream.Write(buffer, 0, buffer.Length); - context.Response.OutputStream.Close(); - } - catch - { - // ignored - } - - Listen(); - } - - private static string Encode(string input) - { - StringBuilder sb = new StringBuilder(input); - - sb.Replace("&", "&"); - sb.Replace("<", "<"); - sb.Replace(">", ">"); - sb.Replace("\"", """); - sb.Replace("'", "'"); - - return sb.ToString(); - } - - protected override void OnTick() - { - if (!Directory.Exists("web")) Directory.CreateDirectory("web"); - - using (StreamWriter op = new StreamWriter("web/status.html")) - { - op.WriteLine(""); - op.WriteLine(""); - op.WriteLine(" "); - op.WriteLine($" {ServerList.ServerName} Server Status"); - op.WriteLine(" "); - op.WriteLine(" "); - op.WriteLine(" "); - op.WriteLine("

RunUO Server Status

"); - op.WriteLine("

Online clients

"); - op.WriteLine(" "); - op.WriteLine( - " "); - - int index = 0; - - foreach (Mobile m in TcpServer.Instances.Where(state => state.Mobile != null).Select(state => state.Mobile)) + private static void Listen() { - ++index; + if (!HttpListener.IsSupported) return; - Guild g = m.Guild as Guild; - - op.Write($" "); + if (_Listener.IsListening) _Listener.BeginGetContext(ListenerCallback, null); } - op.WriteLine(" "); - op.WriteLine("
NameLocationKillsKarma/Fame
"); - - if (g != null) - { - op.Write(Encode(m.Name)); - op.Write(" ["); - - string title = m.GuildTitle; - - title = title?.Trim() ?? string.Empty; - - if (title.Length > 0) + if (_Listener == null) { - op.Write(Encode(title)); - op.Write(", "); + _Listener = new HttpListener(); + _Listener.Prefixes.Add("http://*:80/status/"); + _Listener.Start(); + } + else if (!_Listener.IsListening) + { + _Listener.Start(); } - op.Write(Encode(g.Abbreviation)); - - op.Write(']'); - } - else - { - op.Write(Encode(m.Name)); - } - - op.Write(""); - op.Write(m.X); - op.Write(", "); - op.Write(m.Y); - op.Write(", "); - op.Write(m.Z); - op.Write(" ("); - op.Write(m.Map); - op.Write(")"); - op.Write(m.Kills); - op.Write(""); - op.Write(m.Karma); - op.Write(" / "); - op.Write(m.Fame); - op.WriteLine("
"); - op.WriteLine(" "); - op.WriteLine(""); - } + private static void ListenerCallback(IAsyncResult result) + { + try + { + var context = _Listener.EndGetContext(result); - lock (_StatusLock) - { - _StatusPage = File.ReadAllText("web/status.html"); - _StatusBuffer = Encoding.UTF8.GetBytes(_StatusPage); - } + byte[] buffer; + + lock (_StatusLock) + { + buffer = _StatusBuffer; + } + + context.Response.ContentLength64 = buffer.Length; + context.Response.OutputStream.Write(buffer, 0, buffer.Length); + context.Response.OutputStream.Close(); + } + catch + { + // ignored + } + + Listen(); + } + + private static string Encode(string input) + { + var sb = new StringBuilder(input); + + sb.Replace("&", "&"); + sb.Replace("<", "<"); + sb.Replace(">", ">"); + sb.Replace("\"", """); + sb.Replace("'", "'"); + + return sb.ToString(); + } + + protected override void OnTick() + { + if (!Directory.Exists("web")) Directory.CreateDirectory("web"); + + using (var op = new StreamWriter("web/status.html")) + { + op.WriteLine(""); + op.WriteLine(""); + op.WriteLine(" "); + op.WriteLine($" {ServerList.ServerName} Server Status"); + op.WriteLine(" "); + op.WriteLine(" "); + op.WriteLine(" "); + op.WriteLine("

RunUO Server Status

"); + op.WriteLine("

Online clients

"); + op.WriteLine(" "); + op.WriteLine( + " " + ); + + var index = 0; + + foreach (var m in TcpServer.Instances.Where(state => state.Mobile != null).Select(state => state.Mobile)) + { + ++index; + + var g = m.Guild as Guild; + + op.Write($" "); + } + + op.WriteLine(" "); + op.WriteLine("
NameLocationKillsKarma/Fame
"); + + if (g != null) + { + op.Write(Encode(m.Name)); + op.Write(" ["); + + var title = m.GuildTitle; + + title = title?.Trim() ?? string.Empty; + + if (title.Length > 0) + { + op.Write(Encode(title)); + op.Write(", "); + } + + op.Write(Encode(g.Abbreviation)); + + op.Write(']'); + } + else + { + op.Write(Encode(m.Name)); + } + + op.Write(""); + op.Write(m.X); + op.Write(", "); + op.Write(m.Y); + op.Write(", "); + op.Write(m.Z); + op.Write(" ("); + op.Write(m.Map); + op.Write(")"); + op.Write(m.Kills); + op.Write(""); + op.Write(m.Karma); + op.Write(" / "); + op.Write(m.Fame); + op.WriteLine("
"); + op.WriteLine(" "); + op.WriteLine(""); + } + + lock (_StatusLock) + { + _StatusPage = File.ReadAllText("web/status.html"); + _StatusBuffer = Encoding.UTF8.GetBytes(_StatusPage); + } + } } - } } diff --git a/Projects/UOContent/Misc/WeightOverloading.cs b/Projects/UOContent/Misc/WeightOverloading.cs index 9ef791cf9..806494215 100644 --- a/Projects/UOContent/Misc/WeightOverloading.cs +++ b/Projects/UOContent/Misc/WeightOverloading.cs @@ -4,117 +4,118 @@ using Server.Spells.Ninjitsu; namespace Server.Misc { - public enum DFAlgorithm - { - Standard, - PainSpike - } - - public static class WeightOverloading - { - public const int OverloadAllowance = 4; // We can be four stones overweight without getting fatigued - - public static DFAlgorithm DFA { get; set; } - - public static void Initialize() + public enum DFAlgorithm { - EventSink.Movement += EventSink_Movement; + Standard, + PainSpike } - public static void FatigueOnDamage(Mobile m, int damage) + public static class WeightOverloading { - double fatigue = 0.0; + public const int OverloadAllowance = 4; // We can be four stones overweight without getting fatigued - switch (DFA) - { - case DFAlgorithm.Standard: - { - fatigue = damage * (100.0 / m.Hits) * ((double)m.Stam / 100) - 5.0; - break; - } - case DFAlgorithm.PainSpike: - { - fatigue = damage * (100.0 / m.Hits + (50.0 + m.Stam) / 100 - 1.0) - 5.0; - break; - } - } + public static DFAlgorithm DFA { get; set; } - if (fatigue > 0) - m.Stam -= (int)fatigue; - } - - public static int GetMaxWeight(Mobile m) => m.MaxWeight; - - public static void EventSink_Movement(MovementEventArgs e) - { - Mobile from = e.Mobile; - - if (!from.Alive || from.AccessLevel > AccessLevel.Player) - return; - - if (!from.Player) - { - // Else it won't work on monsters. - DeathStrike.AddStep(from); - return; - } - - int maxWeight = GetMaxWeight(from) + OverloadAllowance; - int overWeight = Mobile.BodyWeight + from.TotalWeight - maxWeight; - - if (overWeight > 0) - { - from.Stam -= GetStamLoss(from, overWeight, (e.Direction & Direction.Running) != 0); - - if (from.Stam == 0) + public static void Initialize() { - from.SendLocalizedMessage( - 500109); // You are too fatigued to move, because you are carrying too much weight! - e.Blocked = true; - return; + EventSink.Movement += EventSink_Movement; } - } - if (from.Stam * 100 / Math.Max(from.StamMax, 1) < 10) - --from.Stam; + public static void FatigueOnDamage(Mobile m, int damage) + { + var fatigue = 0.0; - if (from.Stam == 0) - { - from.SendLocalizedMessage(500110); // You are too fatigued to move. - e.Blocked = true; - return; - } + switch (DFA) + { + case DFAlgorithm.Standard: + { + fatigue = damage * (100.0 / m.Hits) * ((double)m.Stam / 100) - 5.0; + break; + } + case DFAlgorithm.PainSpike: + { + fatigue = damage * (100.0 / m.Hits + (50.0 + m.Stam) / 100 - 1.0) - 5.0; + break; + } + } - if (from is PlayerMobile pm) - { - int amt = pm.Mounted ? 48 : 16; + if (fatigue > 0) + m.Stam -= (int)fatigue; + } - if (++pm.StepsTaken % amt == 0) - --pm.Stam; - } + public static int GetMaxWeight(Mobile m) => m.MaxWeight; - DeathStrike.AddStep(from); + public static void EventSink_Movement(MovementEventArgs e) + { + var from = e.Mobile; + + if (!from.Alive || from.AccessLevel > AccessLevel.Player) + return; + + if (!from.Player) + { + // Else it won't work on monsters. + DeathStrike.AddStep(from); + return; + } + + var maxWeight = GetMaxWeight(from) + OverloadAllowance; + var overWeight = Mobile.BodyWeight + from.TotalWeight - maxWeight; + + if (overWeight > 0) + { + from.Stam -= GetStamLoss(from, overWeight, (e.Direction & Direction.Running) != 0); + + if (from.Stam == 0) + { + from.SendLocalizedMessage( + 500109 + ); // You are too fatigued to move, because you are carrying too much weight! + e.Blocked = true; + return; + } + } + + if (from.Stam * 100 / Math.Max(from.StamMax, 1) < 10) + --from.Stam; + + if (from.Stam == 0) + { + from.SendLocalizedMessage(500110); // You are too fatigued to move. + e.Blocked = true; + return; + } + + if (from is PlayerMobile pm) + { + var amt = pm.Mounted ? 48 : 16; + + if (++pm.StepsTaken % amt == 0) + --pm.Stam; + } + + DeathStrike.AddStep(from); + } + + public static int GetStamLoss(Mobile from, int overWeight, bool running) + { + var loss = 5 + overWeight / 25; + + if (from.Mounted) + loss /= 3; + + if (running) + loss *= 2; + + return loss; + } + + public static bool IsOverloaded(Mobile m) + { + if (!m.Player || !m.Alive || m.AccessLevel > AccessLevel.Player) + return false; + + return Mobile.BodyWeight + m.TotalWeight > GetMaxWeight(m) + OverloadAllowance; + } } - - public static int GetStamLoss(Mobile from, int overWeight, bool running) - { - int loss = 5 + overWeight / 25; - - if (from.Mounted) - loss /= 3; - - if (running) - loss *= 2; - - return loss; - } - - public static bool IsOverloaded(Mobile m) - { - if (!m.Player || !m.Alive || m.AccessLevel > AccessLevel.Player) - return false; - - return Mobile.BodyWeight + m.TotalWeight > GetMaxWeight(m) + OverloadAllowance; - } - } } diff --git a/Projects/UOContent/Misc/WelcomeTimer.cs b/Projects/UOContent/Misc/WelcomeTimer.cs index 023aafa71..5d9adb233 100644 --- a/Projects/UOContent/Misc/WelcomeTimer.cs +++ b/Projects/UOContent/Misc/WelcomeTimer.cs @@ -2,53 +2,54 @@ using System; namespace Server.Misc { - /// - /// This timer spouts some welcome messages to a user at a set interval. It is used on character creation and login. - /// - public class WelcomeTimer : Timer - { - private static readonly string[] m_Messages = TestCenter.Enabled - ? new[] - { - "Welcome to this test shard. You are able to customize your character's stats and skills at anytime to anything you wish. To see the commands to do this just say 'help'.", - "You will find a bank check worth 1,000,000 gold in your bank!", - "A spellbook and a bag of reagents has been placed into your bank box.", - "Various tools have been placed into your bank.", - "Various raw materials like ingots, logs, feathers, hides, bottles, etc, have been placed into your bank.", - "5 unmarked recall runes, 5 Felucca moonstones and 5 Trammel moonstones have been placed into your bank box.", - "One of each level of treasure map has been placed in your bank box.", - "You will find 9000 silver pieces deposited into your bank box. Spend it as you see fit and enjoy yourself!", - "You will find 9000 gold pieces deposited into your bank box. Spend it as you see fit and enjoy yourself!", - "A bag of PowerScrolls has been placed in your bank box." - } - : new[] - { - // Yes, this message is a pathetic message, It's suggested that you change it. - "Welcome to this shard.", - "Please enjoy your stay." - }; - - private readonly Mobile m_Mobile; - private int m_State; - private readonly int m_Count; - - public WelcomeTimer(Mobile m) : this(m, m_Messages.Length) + /// + /// This timer spouts some welcome messages to a user at a set interval. It is used on character creation and login. + /// + public class WelcomeTimer : Timer { - } + private static readonly string[] m_Messages = TestCenter.Enabled + ? new[] + { + "Welcome to this test shard. You are able to customize your character's stats and skills at anytime to anything you wish. To see the commands to do this just say 'help'.", + "You will find a bank check worth 1,000,000 gold in your bank!", + "A spellbook and a bag of reagents has been placed into your bank box.", + "Various tools have been placed into your bank.", + "Various raw materials like ingots, logs, feathers, hides, bottles, etc, have been placed into your bank.", + "5 unmarked recall runes, 5 Felucca moonstones and 5 Trammel moonstones have been placed into your bank box.", + "One of each level of treasure map has been placed in your bank box.", + "You will find 9000 silver pieces deposited into your bank box. Spend it as you see fit and enjoy yourself!", + "You will find 9000 gold pieces deposited into your bank box. Spend it as you see fit and enjoy yourself!", + "A bag of PowerScrolls has been placed in your bank box." + } + : new[] + { + // Yes, this message is a pathetic message, It's suggested that you change it. + "Welcome to this shard.", + "Please enjoy your stay." + }; - public WelcomeTimer(Mobile m, int count) : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(10.0)) - { - m_Mobile = m; - m_Count = count; - } + private readonly int m_Count; - protected override void OnTick() - { - if (m_State < m_Count) - m_Mobile.SendMessage(0x35, m_Messages[m_State++]); + private readonly Mobile m_Mobile; + private int m_State; - if (m_State == m_Count) - Stop(); + public WelcomeTimer(Mobile m) : this(m, m_Messages.Length) + { + } + + public WelcomeTimer(Mobile m, int count) : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(10.0)) + { + m_Mobile = m; + m_Count = count; + } + + protected override void OnTick() + { + if (m_State < m_Count) + m_Mobile.SendMessage(0x35, m_Messages[m_State++]); + + if (m_State == m_Count) + Stop(); + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Misc/uoamVendors.cs b/Projects/UOContent/Misc/uoamVendors.cs index 8346d5bce..eb2cd5bb8 100644 --- a/Projects/UOContent/Misc/uoamVendors.cs +++ b/Projects/UOContent/Misc/uoamVendors.cs @@ -7,345 +7,345 @@ using Server.Engines.Spawners; namespace Server { - public class UOAMVendorGenerator - { - // configuration - private const int - NPCCount = 2; // 2 npcs per type (so a mage spawner will spawn 2 npcs, a alchemist and herbalist spawner will spawn 4 npcs total) - - private const int HomeRange = 5; // How far should they wander? - private const bool TotalRespawn = true; // Should we spawn them up right away? - private const int Team = 0; // "team" the npcs are on - private static int m_Count; - private static readonly TimeSpan MinTime = TimeSpan.FromMinutes(2.5); // min spawn time - private static readonly TimeSpan MaxTime = TimeSpan.FromMinutes(10.0); // max spawn time - - public static void Initialize() + public class UOAMVendorGenerator { - CommandSystem.Register("UOAMVendors", AccessLevel.Administrator, Generate_OnCommand); - } + // configuration + private const int + NPCCount = 2; // 2 npcs per type (so a mage spawner will spawn 2 npcs, a alchemist and herbalist spawner will spawn 4 npcs total) - [Usage("UOAMVendors")] - [Description("Generates vendor spawners from Data/Common.MAP (taken from UOAutoMap)")] - private static void Generate_OnCommand(CommandEventArgs e) - { - Parse(e.Mobile); - } + private const int HomeRange = 5; // How far should they wander? + private const bool TotalRespawn = true; // Should we spawn them up right away? + private const int Team = 0; // "team" the npcs are on + private static int m_Count; + private static readonly TimeSpan MinTime = TimeSpan.FromMinutes(2.5); // min spawn time + private static readonly TimeSpan MaxTime = TimeSpan.FromMinutes(10.0); // max spawn time - public static void Parse(Mobile from) - { - string vendor_path = Path.Combine(Core.BaseDirectory, "Data/Common.map"); - m_Count = 0; - - if (!File.Exists(vendor_path)) - { - from.SendMessage("{0} not found!", vendor_path); - return; - } - - from.SendMessage("Generating Vendors..."); - - using (StreamReader ip = new StreamReader(vendor_path)) - { - string line; - - while ((line = ip.ReadLine()) != null) + public static void Initialize() { - int indexOf = line.IndexOf(':'); - - if (indexOf == -1) - continue; - - string type = line.Substring(0, ++indexOf).Trim(); - string sub = line.Substring(indexOf).Trim(); - - string[] split = sub.Split(' '); - - if (split.Length < 3) - continue; - - split = new[] { type, split[0], split[1], split[2] }; - - switch (split[0].ToLower()) - { - case "-healer:": - PlaceNPC(split[1], split[2], split[3], "Healer", "HealerGuildmaster"); - break; - case "-baker:": - PlaceNPC(split[1], split[2], split[3], "Baker"); - break; - case "-vet:": - PlaceNPC(split[1], split[2], split[3], "Veterinarian"); - break; - case "-gypsymaiden:": - PlaceNPC(split[1], split[2], split[3], "GypsyMaiden"); - break; - case "-gypsybank:": - PlaceNPC(split[1], split[2], split[3], "GypsyBanker"); - break; - case "-bank:": - PlaceNPC(split[1], split[2], split[3], "Banker", "Minter"); - break; - case "-inn:": - PlaceNPC(split[1], split[2], split[3], "Innkeeper"); - break; - case "-provisioner:": - PlaceNPC(split[1], split[2], split[3], "Provisioner", "Cobbler"); - break; - case "-tailor:": - PlaceNPC(split[1], split[2], split[3], "Tailor", "Weaver", "TailorGuildmaster"); - break; - case "-tavern:": - PlaceNPC(split[1], split[2], split[3], "Tavernkeeper", "Waiter", "Cook", "Barkeeper"); - break; - case "-reagents:": - PlaceNPC(split[1], split[2], split[3], "Herbalist", "Alchemist", "CustomHairstylist"); - break; - case "-fortuneteller:": - PlaceNPC(split[1], split[2], split[3], "FortuneTeller"); - break; - case "-holymage:": - PlaceNPC(split[1], split[2], split[3], "HolyMage"); - break; - case "-chivalrykeeper:": - PlaceNPC(split[1], split[2], split[3], "KeeperOfChivalry"); - break; - case "-mage:": - PlaceNPC(split[1], split[2], split[3], "Mage", "Alchemist", "MageGuildmaster"); - break; - case "-arms:": - PlaceNPC(split[1], split[2], split[3], "Armorer", "Weaponsmith"); - break; - case "-tinker:": - PlaceNPC(split[1], split[2], split[3], "Tinker", "TinkerGuildmaster"); - break; - case "-gypsystable:": - PlaceNPC(split[1], split[2], split[3], "GypsyAnimalTrainer"); - break; - case "-stable:": - PlaceNPC(split[1], split[2], split[3], "AnimalTrainer"); - break; - case "-blacksmith:": - PlaceNPC(split[1], split[2], split[3], "Blacksmith", "BlacksmithGuildmaster"); - break; - case "-bowyer:": - case "-fletcher:": - PlaceNPC(split[1], split[2], split[3], "Bowyer"); - break; - case "-carpenter:": - PlaceNPC(split[1], split[2], split[3], "Carpenter", "Architect", "RealEstateBroker"); - break; - case "-butcher:": - PlaceNPC(split[1], split[2], split[3], "Butcher"); - break; - case "-jeweler:": - PlaceNPC(split[1], split[2], split[3], "Jeweler"); - break; - case "-tanner:": - PlaceNPC(split[1], split[2], split[3], "Tanner", "Furtrader"); - break; - case "-bard:": - PlaceNPC(split[1], split[2], split[3], "Bard", "BardGuildmaster"); - break; - case "-market:": - PlaceNPC(split[1], split[2], split[3], "Butcher", "Farmer"); - break; - case "-library:": - PlaceNPC(split[1], split[2], split[3], "Scribe"); - break; - case "-shipwright:": - PlaceNPC(split[1], split[2], split[3], "Shipwright", "Mapmaker"); - break; - case "-docks:": - PlaceNPC(split[1], split[2], split[3], "Fisherman"); - break; - - case "-beekeeper:": - PlaceNPC(split[1], split[2], split[3], "Beekeeper"); - break; - - // Guilds & Misc - case "-tinkers guild:": - PlaceNPC(split[1], split[2], split[3], "TinkerGuildmaster"); - break; - case "-blacksmiths guild:": - PlaceNPC(split[1], split[2], split[3], "BlacksmithGuildmaster"); - break; - case "-sorcerors guild:": - PlaceNPC(split[1], split[2], split[3], "MageGuildmaster"); - break; - case "-customs:": break; - case "-painter:": break; - case "-theater:": break; - case "-warriors guild:": - PlaceNPC(split[1], split[2], split[3], "WarriorGuildmaster"); - break; - case "-archers guild:": - PlaceNPC(split[1], split[2], split[3], "RangerGuildmaster"); - break; - case "-thieves guild:": - PlaceNPC(split[1], split[2], split[3], "ThiefGuildmaster"); - break; - case "-miners guild:": - PlaceNPC(split[1], split[2], split[3], "MinerGuildmaster"); - break; - case "-fishermans guild:": - PlaceNPC(split[1], split[2], split[3], "FisherGuildmaster"); - break; - case "-merchants guild:": - PlaceNPC(split[1], split[2], split[3], "MerchantGuildmaster"); - break; - case "-illusionists guild:": break; - case "-armourers guild:": break; - case "-sorcerers guild:": break; - case "-mages guild:": - PlaceNPC(split[1], split[2], split[3], "MageGuildmaster"); - break; - case "-weapons guild:": break; - case "-bardic guild:": - PlaceNPC(split[1], split[2], split[3], "BardGuildmaster"); - break; - case "-rogues guild:": - break; - - // Skip - case "+landmark:": - case "-point of interest:": - case "+shrine:": - case "+moongate:": - case "+dungeon:": - case "+scenic:": - case "-gate:": - case "+Body of Water:": - case "+ruins:": - case "+teleporter:": - case "+Terrain:": - case "-exit:": - case "-bridge:": - case "-other:": - case "+champion:": - case "-stairs:": - case "-guild:": - case "+graveyard:": - case "+Island:": - case "+town:": - break; - /*default: - Console.WriteLine(split[0]); - break;*/ - } + CommandSystem.Register("UOAMVendors", AccessLevel.Administrator, Generate_OnCommand); } - } - from.SendMessage("Done, added {0} spawners", m_Count); + [Usage("UOAMVendors")] + [Description("Generates vendor spawners from Data/Common.MAP (taken from UOAutoMap)")] + private static void Generate_OnCommand(CommandEventArgs e) + { + Parse(e.Mobile); + } + + public static void Parse(Mobile from) + { + var vendor_path = Path.Combine(Core.BaseDirectory, "Data/Common.map"); + m_Count = 0; + + if (!File.Exists(vendor_path)) + { + from.SendMessage("{0} not found!", vendor_path); + return; + } + + from.SendMessage("Generating Vendors..."); + + using (var ip = new StreamReader(vendor_path)) + { + string line; + + while ((line = ip.ReadLine()) != null) + { + var indexOf = line.IndexOf(':'); + + if (indexOf == -1) + continue; + + var type = line.Substring(0, ++indexOf).Trim(); + var sub = line.Substring(indexOf).Trim(); + + var split = sub.Split(' '); + + if (split.Length < 3) + continue; + + split = new[] { type, split[0], split[1], split[2] }; + + switch (split[0].ToLower()) + { + case "-healer:": + PlaceNPC(split[1], split[2], split[3], "Healer", "HealerGuildmaster"); + break; + case "-baker:": + PlaceNPC(split[1], split[2], split[3], "Baker"); + break; + case "-vet:": + PlaceNPC(split[1], split[2], split[3], "Veterinarian"); + break; + case "-gypsymaiden:": + PlaceNPC(split[1], split[2], split[3], "GypsyMaiden"); + break; + case "-gypsybank:": + PlaceNPC(split[1], split[2], split[3], "GypsyBanker"); + break; + case "-bank:": + PlaceNPC(split[1], split[2], split[3], "Banker", "Minter"); + break; + case "-inn:": + PlaceNPC(split[1], split[2], split[3], "Innkeeper"); + break; + case "-provisioner:": + PlaceNPC(split[1], split[2], split[3], "Provisioner", "Cobbler"); + break; + case "-tailor:": + PlaceNPC(split[1], split[2], split[3], "Tailor", "Weaver", "TailorGuildmaster"); + break; + case "-tavern:": + PlaceNPC(split[1], split[2], split[3], "Tavernkeeper", "Waiter", "Cook", "Barkeeper"); + break; + case "-reagents:": + PlaceNPC(split[1], split[2], split[3], "Herbalist", "Alchemist", "CustomHairstylist"); + break; + case "-fortuneteller:": + PlaceNPC(split[1], split[2], split[3], "FortuneTeller"); + break; + case "-holymage:": + PlaceNPC(split[1], split[2], split[3], "HolyMage"); + break; + case "-chivalrykeeper:": + PlaceNPC(split[1], split[2], split[3], "KeeperOfChivalry"); + break; + case "-mage:": + PlaceNPC(split[1], split[2], split[3], "Mage", "Alchemist", "MageGuildmaster"); + break; + case "-arms:": + PlaceNPC(split[1], split[2], split[3], "Armorer", "Weaponsmith"); + break; + case "-tinker:": + PlaceNPC(split[1], split[2], split[3], "Tinker", "TinkerGuildmaster"); + break; + case "-gypsystable:": + PlaceNPC(split[1], split[2], split[3], "GypsyAnimalTrainer"); + break; + case "-stable:": + PlaceNPC(split[1], split[2], split[3], "AnimalTrainer"); + break; + case "-blacksmith:": + PlaceNPC(split[1], split[2], split[3], "Blacksmith", "BlacksmithGuildmaster"); + break; + case "-bowyer:": + case "-fletcher:": + PlaceNPC(split[1], split[2], split[3], "Bowyer"); + break; + case "-carpenter:": + PlaceNPC(split[1], split[2], split[3], "Carpenter", "Architect", "RealEstateBroker"); + break; + case "-butcher:": + PlaceNPC(split[1], split[2], split[3], "Butcher"); + break; + case "-jeweler:": + PlaceNPC(split[1], split[2], split[3], "Jeweler"); + break; + case "-tanner:": + PlaceNPC(split[1], split[2], split[3], "Tanner", "Furtrader"); + break; + case "-bard:": + PlaceNPC(split[1], split[2], split[3], "Bard", "BardGuildmaster"); + break; + case "-market:": + PlaceNPC(split[1], split[2], split[3], "Butcher", "Farmer"); + break; + case "-library:": + PlaceNPC(split[1], split[2], split[3], "Scribe"); + break; + case "-shipwright:": + PlaceNPC(split[1], split[2], split[3], "Shipwright", "Mapmaker"); + break; + case "-docks:": + PlaceNPC(split[1], split[2], split[3], "Fisherman"); + break; + + case "-beekeeper:": + PlaceNPC(split[1], split[2], split[3], "Beekeeper"); + break; + + // Guilds & Misc + case "-tinkers guild:": + PlaceNPC(split[1], split[2], split[3], "TinkerGuildmaster"); + break; + case "-blacksmiths guild:": + PlaceNPC(split[1], split[2], split[3], "BlacksmithGuildmaster"); + break; + case "-sorcerors guild:": + PlaceNPC(split[1], split[2], split[3], "MageGuildmaster"); + break; + case "-customs:": break; + case "-painter:": break; + case "-theater:": break; + case "-warriors guild:": + PlaceNPC(split[1], split[2], split[3], "WarriorGuildmaster"); + break; + case "-archers guild:": + PlaceNPC(split[1], split[2], split[3], "RangerGuildmaster"); + break; + case "-thieves guild:": + PlaceNPC(split[1], split[2], split[3], "ThiefGuildmaster"); + break; + case "-miners guild:": + PlaceNPC(split[1], split[2], split[3], "MinerGuildmaster"); + break; + case "-fishermans guild:": + PlaceNPC(split[1], split[2], split[3], "FisherGuildmaster"); + break; + case "-merchants guild:": + PlaceNPC(split[1], split[2], split[3], "MerchantGuildmaster"); + break; + case "-illusionists guild:": break; + case "-armourers guild:": break; + case "-sorcerers guild:": break; + case "-mages guild:": + PlaceNPC(split[1], split[2], split[3], "MageGuildmaster"); + break; + case "-weapons guild:": break; + case "-bardic guild:": + PlaceNPC(split[1], split[2], split[3], "BardGuildmaster"); + break; + case "-rogues guild:": + break; + + // Skip + case "+landmark:": + case "-point of interest:": + case "+shrine:": + case "+moongate:": + case "+dungeon:": + case "+scenic:": + case "-gate:": + case "+Body of Water:": + case "+ruins:": + case "+teleporter:": + case "+Terrain:": + case "-exit:": + case "-bridge:": + case "-other:": + case "+champion:": + case "-stairs:": + case "-guild:": + case "+graveyard:": + case "+Island:": + case "+town:": + break; + /*default: + Console.WriteLine(split[0]); + break;*/ + } + } + } + + from.SendMessage("Done, added {0} spawners", m_Count); + } + + public static void PlaceNPC(string sx, string sy, string sm, params string[] types) + { + if (types.Length == 0) + return; + + var x = Utility.ToInt32(sx); + var y = Utility.ToInt32(sy); + var map = Utility.ToInt32(sm); + + switch (map) + { + case 0: // Trammel and Felucca + MakeSpawner(types, x, y, Map.Felucca); + MakeSpawner(types, x, y, Map.Trammel); + break; + case 1: // Felucca + MakeSpawner(types, x, y, Map.Felucca); + break; + case 2: + MakeSpawner(types, x, y, Map.Trammel); + break; + case 3: + MakeSpawner(types, x, y, Map.Ilshenar); + break; + case 4: + MakeSpawner(types, x, y, Map.Malas); + break; + default: + Console.WriteLine("UOAM Vendor Parser: Warning, unknown map {0}", map); + break; + } + } + + public static int GetSpawnerZ(int x, int y, Map map) + { + var z = map.GetAverageZ(x, y); + + if (map.CanFit(x, y, z, 16, false, false)) + return z; + + for (var i = 1; i <= 5; ++i) + { + if (map.CanFit(x, y, z + i, 16, false, false)) + return z + i; + + if (map.CanFit(x, y, z - i, 16, false, false)) + return z - i; + } + + return z; + } + + public static void ClearSpawners(int x, int y, int z, Map map) + { + var eable = map.GetItemsInRange(new Point3D(x, y, z), 0); + var m_ToDelete = new Queue(); + + foreach (var item in eable) + if (item.Z == z) + m_ToDelete.Enqueue(item); + + eable.Free(); + + while (m_ToDelete.Count > 0) + m_ToDelete.Dequeue().Delete(); + } + + private static void MakeSpawner(string[] types, int x, int y, Map map) + { + if (types.Length == 0) + return; + + var z = GetSpawnerZ(x, y, map); + + ClearSpawners(x, y, z, map); + + var sp = new Spawner + { + MinDelay = MinTime, + MaxDelay = MaxTime, + Team = Team, + HomeRange = HomeRange + }; + + var count = 0; + + for (var i = 0; i < types.Length; ++i) + { + var isGuildMaster = types[i].EndsWith("Guildmaster"); + count += isGuildMaster ? 1 : NPCCount; + if (isGuildMaster) + count++; + + sp.AddEntry(types[i], 100, isGuildMaster ? 1 : NPCCount); + } + + sp.Count = count; + sp.MoveToWorld(new Point3D(x, y, z), map); + + if (TotalRespawn) + { + sp.Respawn(); + sp.BringToHome(); + } + + m_Count += types.Length; + } } - - public static void PlaceNPC(string sx, string sy, string sm, params string[] types) - { - if (types.Length == 0) - return; - - int x = Utility.ToInt32(sx); - int y = Utility.ToInt32(sy); - int map = Utility.ToInt32(sm); - - switch (map) - { - case 0: // Trammel and Felucca - MakeSpawner(types, x, y, Map.Felucca); - MakeSpawner(types, x, y, Map.Trammel); - break; - case 1: // Felucca - MakeSpawner(types, x, y, Map.Felucca); - break; - case 2: - MakeSpawner(types, x, y, Map.Trammel); - break; - case 3: - MakeSpawner(types, x, y, Map.Ilshenar); - break; - case 4: - MakeSpawner(types, x, y, Map.Malas); - break; - default: - Console.WriteLine("UOAM Vendor Parser: Warning, unknown map {0}", map); - break; - } - } - - public static int GetSpawnerZ(int x, int y, Map map) - { - int z = map.GetAverageZ(x, y); - - if (map.CanFit(x, y, z, 16, false, false)) - return z; - - for (int i = 1; i <= 5; ++i) - { - if (map.CanFit(x, y, z + i, 16, false, false)) - return z + i; - - if (map.CanFit(x, y, z - i, 16, false, false)) - return z - i; - } - - return z; - } - - public static void ClearSpawners(int x, int y, int z, Map map) - { - IPooledEnumerable eable = map.GetItemsInRange(new Point3D(x, y, z), 0); - Queue m_ToDelete = new Queue(); - - foreach (Spawner item in eable) - if (item.Z == z) - m_ToDelete.Enqueue(item); - - eable.Free(); - - while (m_ToDelete.Count > 0) - m_ToDelete.Dequeue().Delete(); - } - - private static void MakeSpawner(string[] types, int x, int y, Map map) - { - if (types.Length == 0) - return; - - int z = GetSpawnerZ(x, y, map); - - ClearSpawners(x, y, z, map); - - Spawner sp = new Spawner - { - MinDelay = MinTime, - MaxDelay = MaxTime, - Team = Team, - HomeRange = HomeRange - }; - - int count = 0; - - for (int i = 0; i < types.Length; ++i) - { - bool isGuildMaster = types[i].EndsWith("Guildmaster"); - count += isGuildMaster ? 1 : NPCCount; - if (isGuildMaster) - count++; - - sp.AddEntry(types[i], 100, isGuildMaster ? 1 : NPCCount); - } - - sp.Count = count; - sp.MoveToWorld(new Point3D(x, y, z), map); - - if (TotalRespawn) - { - sp.Respawn(); - sp.BringToHome(); - } - - m_Count += types.Length; - } - } } diff --git a/Projects/UOContent/Mobiles/AI/AIControlMobileTarget.cs b/Projects/UOContent/Mobiles/AI/AIControlMobileTarget.cs index 2f76ad6a9..68ca820ee 100644 --- a/Projects/UOContent/Mobiles/AI/AIControlMobileTarget.cs +++ b/Projects/UOContent/Mobiles/AI/AIControlMobileTarget.cs @@ -4,32 +4,35 @@ using Server.Targeting; namespace Server.Targets { - public class AIControlMobileTarget : Target - { - private readonly List m_List; - - public AIControlMobileTarget(BaseAI ai, OrderType order) : base(-1, false, - order == OrderType.Attack ? TargetFlags.Harmful : TargetFlags.None) + public class AIControlMobileTarget : Target { - m_List = new List(); - Order = order; + private readonly List m_List; - AddAI(ai); + public AIControlMobileTarget(BaseAI ai, OrderType order) : base( + -1, + false, + order == OrderType.Attack ? TargetFlags.Harmful : TargetFlags.None + ) + { + m_List = new List(); + Order = order; + + AddAI(ai); + } + + public OrderType Order { get; } + + public void AddAI(BaseAI ai) + { + if (!m_List.Contains(ai)) + m_List.Add(ai); + } + + protected override void OnTarget(Mobile from, object o) + { + if (o is Mobile m) + for (var i = 0; i < m_List.Count; ++i) + m_List[i].EndPickTarget(from, m, Order); + } } - - public OrderType Order { get; } - - public void AddAI(BaseAI ai) - { - if (!m_List.Contains(ai)) - m_List.Add(ai); - } - - protected override void OnTarget(Mobile from, object o) - { - if (o is Mobile m) - for (int i = 0; i < m_List.Count; ++i) - m_List[i].EndPickTarget(from, m, Order); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/AI/AnimalAI.cs b/Projects/UOContent/Mobiles/AI/AnimalAI.cs index b99024ed1..36357ef10 100644 --- a/Projects/UOContent/Mobiles/AI/AnimalAI.cs +++ b/Projects/UOContent/Mobiles/AI/AnimalAI.cs @@ -9,121 +9,121 @@ namespace Server.Mobiles { - public class AnimalAI : BaseAI - { - public AnimalAI(BaseCreature m) : base(m) + public class AnimalAI : BaseAI { - } - - public override bool DoActionWander() - { - // New, only flee @ 10% - - double hitPercent = (double)m_Mobile.Hits / m_Mobile.HitsMax; - - if (!m_Mobile.Summoned && !m_Mobile.Controlled && hitPercent < 0.1 && m_Mobile.CanFlee) // Less than 10% health - { - m_Mobile.DebugSay("I am low on health!"); - Action = ActionType.Flee; - } - else if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) - { - if (m_Mobile.Debug) - m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name); - - m_Mobile.Combatant = m_Mobile.FocusMob; - Action = ActionType.Combat; - } - else - { - base.DoActionWander(); - } - - return true; - } - - public override bool DoActionCombat() - { - Mobile combatant = m_Mobile.Combatant; - - if (combatant?.Deleted != false || combatant.Map != m_Mobile.Map) - { - m_Mobile.DebugSay("My combatant is gone.."); - - Action = ActionType.Wander; - - return true; - } - - if (WalkMobileRange(combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight)) - { - m_Mobile.Direction = m_Mobile.GetDirectionTo(combatant); - } - else - { - if (m_Mobile.GetDistanceToSqrt(combatant) > m_Mobile.RangePerception + 1) + public AnimalAI(BaseCreature m) : base(m) { - if (m_Mobile.Debug) - m_Mobile.DebugSay("I cannot find {0}", combatant.Name); - - Action = ActionType.Wander; - - return true; } - if (m_Mobile.Debug) - m_Mobile.DebugSay("I should be closer to {0}", combatant.Name); - } - - if (!m_Mobile.Controlled && !m_Mobile.Summoned && m_Mobile.CanFlee) - { - double hitPercent = (double)m_Mobile.Hits / m_Mobile.HitsMax; - - if (hitPercent < 0.1) + public override bool DoActionWander() { - m_Mobile.DebugSay("I am low on health!"); - Action = ActionType.Flee; + // New, only flee @ 10% + + var hitPercent = (double)m_Mobile.Hits / m_Mobile.HitsMax; + + if (!m_Mobile.Summoned && !m_Mobile.Controlled && hitPercent < 0.1 && m_Mobile.CanFlee) // Less than 10% health + { + m_Mobile.DebugSay("I am low on health!"); + Action = ActionType.Flee; + } + else if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) + { + if (m_Mobile.Debug) + m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name); + + m_Mobile.Combatant = m_Mobile.FocusMob; + Action = ActionType.Combat; + } + else + { + base.DoActionWander(); + } + + return true; } - } - return true; - } - - public override bool DoActionBackoff() - { - double hitPercent = (double)m_Mobile.Hits / m_Mobile.HitsMax; - - if (!m_Mobile.Summoned && !m_Mobile.Controlled && hitPercent < 0.1 && m_Mobile.CanFlee) // Less than 10% health - { - Action = ActionType.Flee; - } - else - { - if (AcquireFocusMob(m_Mobile.RangePerception * 2, FightMode.Closest, true, false, true)) + public override bool DoActionCombat() { - if (WalkMobileRange(m_Mobile.FocusMob, 1, false, m_Mobile.RangePerception, m_Mobile.RangePerception * 2)) - { - m_Mobile.DebugSay("Well, here I am safe"); - Action = ActionType.Wander; - } + var combatant = m_Mobile.Combatant; + + if (combatant?.Deleted != false || combatant.Map != m_Mobile.Map) + { + m_Mobile.DebugSay("My combatant is gone.."); + + Action = ActionType.Wander; + + return true; + } + + if (WalkMobileRange(combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight)) + { + m_Mobile.Direction = m_Mobile.GetDirectionTo(combatant); + } + else + { + if (m_Mobile.GetDistanceToSqrt(combatant) > m_Mobile.RangePerception + 1) + { + if (m_Mobile.Debug) + m_Mobile.DebugSay("I cannot find {0}", combatant.Name); + + Action = ActionType.Wander; + + return true; + } + + if (m_Mobile.Debug) + m_Mobile.DebugSay("I should be closer to {0}", combatant.Name); + } + + if (!m_Mobile.Controlled && !m_Mobile.Summoned && m_Mobile.CanFlee) + { + var hitPercent = (double)m_Mobile.Hits / m_Mobile.HitsMax; + + if (hitPercent < 0.1) + { + m_Mobile.DebugSay("I am low on health!"); + Action = ActionType.Flee; + } + } + + return true; } - else + + public override bool DoActionBackoff() { - m_Mobile.DebugSay("I have lost my focus, lets relax"); - Action = ActionType.Wander; + var hitPercent = (double)m_Mobile.Hits / m_Mobile.HitsMax; + + if (!m_Mobile.Summoned && !m_Mobile.Controlled && hitPercent < 0.1 && m_Mobile.CanFlee) // Less than 10% health + { + Action = ActionType.Flee; + } + else + { + if (AcquireFocusMob(m_Mobile.RangePerception * 2, FightMode.Closest, true, false, true)) + { + if (WalkMobileRange(m_Mobile.FocusMob, 1, false, m_Mobile.RangePerception, m_Mobile.RangePerception * 2)) + { + m_Mobile.DebugSay("Well, here I am safe"); + Action = ActionType.Wander; + } + } + else + { + m_Mobile.DebugSay("I have lost my focus, lets relax"); + Action = ActionType.Wander; + } + } + + return true; } - } - return true; + public override bool DoActionFlee() + { + AcquireFocusMob(m_Mobile.RangePerception * 2, m_Mobile.FightMode, true, false, true); + + m_Mobile.FocusMob ??= m_Mobile.Combatant; + + return base.DoActionFlee(); + } } - - public override bool DoActionFlee() - { - AcquireFocusMob(m_Mobile.RangePerception * 2, m_Mobile.FightMode, true, false, true); - - m_Mobile.FocusMob ??= m_Mobile.Combatant; - - return base.DoActionFlee(); - } - } } diff --git a/Projects/UOContent/Mobiles/AI/ArcherAI.cs b/Projects/UOContent/Mobiles/AI/ArcherAI.cs index 027e7152e..68c62c311 100644 --- a/Projects/UOContent/Mobiles/AI/ArcherAI.cs +++ b/Projects/UOContent/Mobiles/AI/ArcherAI.cs @@ -2,118 +2,118 @@ using Server.Items; namespace Server.Mobiles { - public class ArcherAI : BaseAI - { - public ArcherAI(BaseCreature m) : base(m) + public class ArcherAI : BaseAI { - } - - public override bool DoActionWander() - { - m_Mobile.DebugSay("I have no combatant"); - - if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) - { - if (m_Mobile.Debug) - m_Mobile.DebugSay("I have detected {0} and I will attack", m_Mobile.FocusMob.Name); - - m_Mobile.Combatant = m_Mobile.FocusMob; - Action = ActionType.Combat; - } - else - { - return base.DoActionWander(); - } - - return true; - } - - public override bool DoActionCombat() - { - if (m_Mobile.Combatant?.Deleted != false || !m_Mobile.Combatant.Alive || - m_Mobile.Combatant.IsDeadBondedPet) - { - m_Mobile.DebugSay("My combatant is deleted"); - Action = ActionType.Guard; - return true; - } - - if (Core.TickCount - m_Mobile.LastMoveTime > 1000) - { - if (WalkMobileRange(m_Mobile.Combatant, 1, true, m_Mobile.RangeFight, m_Mobile.Weapon.MaxRange)) + public ArcherAI(BaseCreature m) : base(m) { - // Be sure to face the combatant - m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant.Location); } - else - { - if (m_Mobile.Combatant != null) - { - if (m_Mobile.Debug) - m_Mobile.DebugSay("I am still not in range of {0}", m_Mobile.Combatant.Name); - if ((int)m_Mobile.GetDistanceToSqrt(m_Mobile.Combatant) > m_Mobile.RangePerception + 1) + public override bool DoActionWander() + { + m_Mobile.DebugSay("I have no combatant"); + + if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) { - if (m_Mobile.Debug) - m_Mobile.DebugSay("I have lost {0}", m_Mobile.Combatant.Name); + if (m_Mobile.Debug) + m_Mobile.DebugSay("I have detected {0} and I will attack", m_Mobile.FocusMob.Name); - m_Mobile.Combatant = null; - Action = ActionType.Guard; - return true; + m_Mobile.Combatant = m_Mobile.FocusMob; + Action = ActionType.Combat; } - } + else + { + return base.DoActionWander(); + } + + return true; } - } - // When we have no ammo, we flee - Container pack = m_Mobile.Backpack; - - if (pack?.FindItemByType() == null) - { - Action = ActionType.Flee; - return true; - } - - // At 20% we should check if we must leave - if (m_Mobile.Hits < m_Mobile.HitsMax * 20 / 100 && m_Mobile.CanFlee) - { - bool bFlee = false; - // if my current hits are more than my opponent, i don't care - if (m_Mobile.Combatant != null && m_Mobile.Hits < m_Mobile.Combatant.Hits) + public override bool DoActionCombat() { - int iDiff = m_Mobile.Combatant.Hits - m_Mobile.Hits; + if (m_Mobile.Combatant?.Deleted != false || !m_Mobile.Combatant.Alive || + m_Mobile.Combatant.IsDeadBondedPet) + { + m_Mobile.DebugSay("My combatant is deleted"); + Action = ActionType.Guard; + return true; + } - if (Utility.Random(0, 100) > 10 + iDiff) // 10% to flee + the diff of hits - bFlee = true; + if (Core.TickCount - m_Mobile.LastMoveTime > 1000) + { + if (WalkMobileRange(m_Mobile.Combatant, 1, true, m_Mobile.RangeFight, m_Mobile.Weapon.MaxRange)) + { + // Be sure to face the combatant + m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant.Location); + } + else + { + if (m_Mobile.Combatant != null) + { + if (m_Mobile.Debug) + m_Mobile.DebugSay("I am still not in range of {0}", m_Mobile.Combatant.Name); + + if ((int)m_Mobile.GetDistanceToSqrt(m_Mobile.Combatant) > m_Mobile.RangePerception + 1) + { + if (m_Mobile.Debug) + m_Mobile.DebugSay("I have lost {0}", m_Mobile.Combatant.Name); + + m_Mobile.Combatant = null; + Action = ActionType.Guard; + return true; + } + } + } + } + + // When we have no ammo, we flee + var pack = m_Mobile.Backpack; + + if (pack?.FindItemByType() == null) + { + Action = ActionType.Flee; + return true; + } + + // At 20% we should check if we must leave + if (m_Mobile.Hits < m_Mobile.HitsMax * 20 / 100 && m_Mobile.CanFlee) + { + var bFlee = false; + // if my current hits are more than my opponent, i don't care + if (m_Mobile.Combatant != null && m_Mobile.Hits < m_Mobile.Combatant.Hits) + { + var iDiff = m_Mobile.Combatant.Hits - m_Mobile.Hits; + + if (Utility.Random(0, 100) > 10 + iDiff) // 10% to flee + the diff of hits + bFlee = true; + } + else if (m_Mobile.Combatant != null && m_Mobile.Hits >= m_Mobile.Combatant.Hits) + { + if (Utility.Random(0, 100) > 10) // 10% to flee + bFlee = true; + } + + if (bFlee) Action = ActionType.Flee; + } + + return true; } - else if (m_Mobile.Combatant != null && m_Mobile.Hits >= m_Mobile.Combatant.Hits) + + public override bool DoActionGuard() { - if (Utility.Random(0, 100) > 10) // 10% to flee - bFlee = true; + if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) + { + if (m_Mobile.Debug) + m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name); + + m_Mobile.Combatant = m_Mobile.FocusMob; + Action = ActionType.Combat; + } + else + { + base.DoActionGuard(); + } + + return true; } - - if (bFlee) Action = ActionType.Flee; - } - - return true; } - - public override bool DoActionGuard() - { - if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) - { - if (m_Mobile.Debug) - m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name); - - m_Mobile.Combatant = m_Mobile.FocusMob; - Action = ActionType.Combat; - } - else - { - base.DoActionGuard(); - } - - return true; - } - } } diff --git a/Projects/UOContent/Mobiles/AI/BaseAI.cs b/Projects/UOContent/Mobiles/AI/BaseAI.cs index a3f8a60c0..91291da1b 100644 --- a/Projects/UOContent/Mobiles/AI/BaseAI.cs +++ b/Projects/UOContent/Mobiles/AI/BaseAI.cs @@ -16,2730 +16,2761 @@ using MoveImpl = Server.Movement.MovementImpl; namespace Server.Mobiles { - public enum AIType - { - AI_Use_Default, - AI_Melee, - AI_Animal, - AI_Archer, - AI_Healer, - AI_Vendor, - AI_Mage, - AI_Berserk, - AI_Predator, - AI_Thief - } - - public enum ActionType - { - Wander, - Combat, - Guard, - Flee, - Backoff, - Interact - } - - public abstract class BaseAI - { - private static readonly SkillName[] m_KeywordTable = + public enum AIType { - SkillName.Parry, - SkillName.Healing, - SkillName.Hiding, - SkillName.Stealing, - SkillName.Alchemy, - SkillName.AnimalLore, - SkillName.ItemID, - SkillName.ArmsLore, - SkillName.Begging, - SkillName.Blacksmith, - SkillName.Fletching, - SkillName.Peacemaking, - SkillName.Camping, - SkillName.Carpentry, - SkillName.Cartography, - SkillName.Cooking, - SkillName.DetectHidden, - SkillName.Discordance, // ?? - SkillName.EvalInt, - SkillName.Fishing, - SkillName.Provocation, - SkillName.Lockpicking, - SkillName.Magery, - SkillName.MagicResist, - SkillName.Tactics, - SkillName.Snooping, - SkillName.RemoveTrap, - SkillName.Musicianship, - SkillName.Poisoning, - SkillName.Archery, - SkillName.SpiritSpeak, - SkillName.Tailoring, - SkillName.AnimalTaming, - SkillName.TasteID, - SkillName.Tinkering, - SkillName.Veterinary, - SkillName.Forensics, - SkillName.Herding, - SkillName.Tracking, - SkillName.Stealth, - SkillName.Inscribe, - SkillName.Swords, - SkillName.Macing, - SkillName.Fencing, - SkillName.Wrestling, - SkillName.Lumberjacking, - SkillName.Mining, - SkillName.Meditation - }; - - private static readonly Queue m_Obstacles = new Queue(); - protected ActionType m_Action; - - public BaseCreature m_Mobile; - - private long m_NextDetectHidden; - private long m_NextStopGuard; - - protected PathFollower m_Path; - public Timer m_Timer; - - public BaseAI(BaseCreature m) - { - m_Mobile = m; - - m_Timer = new AITimer(this); - - bool activate; - - if (!m.PlayerRangeSensitive) - activate = true; - else if (World.Loading) - activate = false; - else if (m.Map == null || m.Map == Map.Internal || !m.Map.GetSector(m).Active) - activate = false; - else - activate = true; - - if (activate) - m_Timer.Start(); - - Action = ActionType.Wander; + AI_Use_Default, + AI_Melee, + AI_Animal, + AI_Archer, + AI_Healer, + AI_Vendor, + AI_Mage, + AI_Berserk, + AI_Predator, + AI_Thief } - public ActionType Action + public enum ActionType { - get => m_Action; - set - { - m_Action = value; - OnActionChanged(); - } + Wander, + Combat, + Guard, + Flee, + Backoff, + Interact } - public long NextMove { get; set; } - - public virtual bool CanDetectHidden => m_Mobile.Skills.DetectHidden.Value > 0; - - public virtual bool WasNamed(string speech) + public abstract class BaseAI { - string name = m_Mobile.Name; - - return name != null && Insensitive.StartsWith(speech, name); - } - - public virtual void GetContextMenuEntries(Mobile from, List list) - { - if (from.Alive && m_Mobile.Controlled && from.InRange(m_Mobile, 14)) - { - if (from == m_Mobile.ControlMaster) + private static readonly SkillName[] m_KeywordTable = { - list.Add(new InternalEntry(from, 6107, 14, m_Mobile, this, OrderType.Guard)); // Command: Guard - list.Add(new InternalEntry(from, 6108, 14, m_Mobile, this, OrderType.Follow)); // Command: Follow + SkillName.Parry, + SkillName.Healing, + SkillName.Hiding, + SkillName.Stealing, + SkillName.Alchemy, + SkillName.AnimalLore, + SkillName.ItemID, + SkillName.ArmsLore, + SkillName.Begging, + SkillName.Blacksmith, + SkillName.Fletching, + SkillName.Peacemaking, + SkillName.Camping, + SkillName.Carpentry, + SkillName.Cartography, + SkillName.Cooking, + SkillName.DetectHidden, + SkillName.Discordance, // ?? + SkillName.EvalInt, + SkillName.Fishing, + SkillName.Provocation, + SkillName.Lockpicking, + SkillName.Magery, + SkillName.MagicResist, + SkillName.Tactics, + SkillName.Snooping, + SkillName.RemoveTrap, + SkillName.Musicianship, + SkillName.Poisoning, + SkillName.Archery, + SkillName.SpiritSpeak, + SkillName.Tailoring, + SkillName.AnimalTaming, + SkillName.TasteID, + SkillName.Tinkering, + SkillName.Veterinary, + SkillName.Forensics, + SkillName.Herding, + SkillName.Tracking, + SkillName.Stealth, + SkillName.Inscribe, + SkillName.Swords, + SkillName.Macing, + SkillName.Fencing, + SkillName.Wrestling, + SkillName.Lumberjacking, + SkillName.Mining, + SkillName.Meditation + }; - if (m_Mobile.CanDrop) - list.Add(new InternalEntry(from, 6109, 14, m_Mobile, this, OrderType.Drop)); // Command: Drop + private static readonly Queue m_Obstacles = new Queue(); + protected ActionType m_Action; - list.Add(new InternalEntry(from, 6111, 14, m_Mobile, this, OrderType.Attack)); // Command: Kill + public BaseCreature m_Mobile; - list.Add(new InternalEntry(from, 6112, 14, m_Mobile, this, OrderType.Stop)); // Command: Stop - list.Add(new InternalEntry(from, 6114, 14, m_Mobile, this, OrderType.Stay)); // Command: Stay + private long m_NextDetectHidden; + private long m_NextStopGuard; - if (!m_Mobile.Summoned && !(m_Mobile is GrizzledMare)) - { - list.Add(new InternalEntry(from, 6110, 14, m_Mobile, this, OrderType.Friend)); // Add Friend - list.Add(new InternalEntry(from, 6099, 14, m_Mobile, this, OrderType.Unfriend)); // Remove Friend - list.Add(new InternalEntry(from, 6113, 14, m_Mobile, this, OrderType.Transfer)); // Transfer - } + protected PathFollower m_Path; + public Timer m_Timer; - list.Add(new InternalEntry(from, 6118, 14, m_Mobile, this, OrderType.Release)); // Release - } - else if (m_Mobile.IsPetFriend(from)) + public BaseAI(BaseCreature m) { - list.Add(new InternalEntry(from, 6108, 14, m_Mobile, this, OrderType.Follow)); // Command: Follow - list.Add(new InternalEntry(from, 6112, 14, m_Mobile, this, OrderType.Stop)); // Command: Stop - list.Add(new InternalEntry(from, 6114, 14, m_Mobile, this, OrderType.Stay)); // Command: Stay - } - } - } + m_Mobile = m; - public virtual void BeginPickTarget(Mobile from, OrderType order) - { - if (m_Mobile.Deleted || !m_Mobile.Controlled || !from.InRange(m_Mobile, 14) || from.Map != m_Mobile.Map) - return; + m_Timer = new AITimer(this); - bool isOwner = from == m_Mobile.ControlMaster; - bool isFriend = !isOwner && m_Mobile.IsPetFriend(from); + bool activate; - if (!isOwner && !isFriend) - return; - if (isFriend && order != OrderType.Follow && order != OrderType.Stay && order != OrderType.Stop) - return; + if (!m.PlayerRangeSensitive) + activate = true; + else if (World.Loading) + activate = false; + else if (m.Map == null || m.Map == Map.Internal || !m.Map.GetSector(m).Active) + activate = false; + else + activate = true; - if (from.Target == null) - { - if (order == OrderType.Transfer) - from.SendLocalizedMessage(502038); // Click on the person to transfer ownership to. - else if (order == OrderType.Friend) - from.SendLocalizedMessage(502020); // Click on the player whom you wish to make a co-owner. - else if (order == OrderType.Unfriend) - from.SendLocalizedMessage(1070948); // Click on the player whom you wish to remove as a co-owner. + if (activate) + m_Timer.Start(); - from.Target = new AIControlMobileTarget(this, order); - } - else if (from.Target is AIControlMobileTarget t) - { - if (t.Order == order) - t.AddAI(this); - } - } - - public virtual void OnAggressiveAction(Mobile aggressor) - { - Mobile currentCombat = m_Mobile.Combatant; - - if (currentCombat != null && !aggressor.Hidden && currentCombat != aggressor && - m_Mobile.GetDistanceToSqrt(currentCombat) > m_Mobile.GetDistanceToSqrt(aggressor)) - m_Mobile.Combatant = aggressor; - } - - public virtual void EndPickTarget(Mobile from, Mobile target, OrderType order) - { - if (m_Mobile.Deleted || !m_Mobile.Controlled || !from.InRange(m_Mobile, 14) || from.Map != m_Mobile.Map || - !from.CheckAlive()) - return; - - bool isOwner = from == m_Mobile.ControlMaster; - bool isFriend = !isOwner && m_Mobile.IsPetFriend(from); - - if (!isOwner && !isFriend) - return; - if (isFriend && order != OrderType.Follow && order != OrderType.Stay && order != OrderType.Stop) - return; - - if (order == OrderType.Attack) - { - if (target is BaseCreature creature && creature.IsScaryToPets && m_Mobile.IsScaredOfScaryThings) - { - m_Mobile.SayTo(from, "Your pet refuses to attack this creature!"); - return; + Action = ActionType.Wander; } - if (SolenHelper.CheckRedFriendship(from) && - (target is RedSolenInfiltratorQueen - || target is RedSolenInfiltratorWarrior - || target is RedSolenQueen - || target is RedSolenWarrior - || target is RedSolenWorker) - || SolenHelper.CheckBlackFriendship(from) && - (target is BlackSolenInfiltratorQueen - || target is BlackSolenInfiltratorWarrior - || target is BlackSolenQueen - || target is BlackSolenWarrior - || target is BlackSolenWorker)) + public ActionType Action { - from.SendAsciiMessage("You can not force your pet to attack a creature you are protected from."); - return; - } - - if (target is BaseFactionGuard) - { - m_Mobile.SayTo(from, "Your pet refuses to attack the guard."); - return; - } - } - - if (m_Mobile.CheckControlChance(from)) - { - m_Mobile.ControlTarget = target; - m_Mobile.ControlOrder = order; - } - } - - public virtual bool HandlesOnSpeech(Mobile from) - { - if (from.AccessLevel >= AccessLevel.GameMaster) - return true; - - if (from.Alive && m_Mobile.Controlled && m_Mobile.Commandable && - (from == m_Mobile.ControlMaster || m_Mobile.IsPetFriend(from))) - return true; - - return from.Alive && from.InRange(m_Mobile.Location, 3) && m_Mobile.IsHumanInTown(); - } - - public virtual void OnSpeech(SpeechEventArgs e) - { - if (e.Mobile.Alive && e.Mobile.InRange(m_Mobile.Location, 3) && m_Mobile.IsHumanInTown()) - { - if (e.HasKeyword(0x9D) && WasNamed(e.Speech)) // *move* - { - if (m_Mobile.Combatant != null) - { - // I am too busy fighting to deal with thee! - m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, 501482); - } - else - { - // Excuse me? - m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, 501516); - WalkRandomInHome(2, 2, 1); - } - } - else if (e.HasKeyword(0x9E) && WasNamed(e.Speech)) // *time* - { - if (m_Mobile.Combatant != null) - { - // I am too busy fighting to deal with thee! - m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, 501482); - } - else - { - Clock.GetTime(m_Mobile, out int generalNumber, out _); - - m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, generalNumber); - } - } - else if (e.HasKeyword(0x6C) && WasNamed(e.Speech)) // *train - { - if (m_Mobile.Combatant != null) - { - // I am too busy fighting to deal with thee! - m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, 501482); - } - else - { - bool foundSomething = false; - - Skills ourSkills = m_Mobile.Skills; - Skills theirSkills = e.Mobile.Skills; - - for (int i = 0; i < ourSkills.Length && i < theirSkills.Length; ++i) + get => m_Action; + set { - Skill skill = ourSkills[i]; - Skill theirSkill = theirSkills[i]; + m_Action = value; + OnActionChanged(); + } + } - if (skill != null && skill.Base >= 60.0 && - m_Mobile.CheckTeach(skill.SkillName, e.Mobile)) - { - double toTeach = skill.Base / 3.0; + public long NextMove { get; set; } - if (toTeach > 42.0) - toTeach = 42.0; + public virtual bool CanDetectHidden => m_Mobile.Skills.DetectHidden.Value > 0; - if (toTeach > theirSkill.Base) + public virtual bool WasNamed(string speech) + { + var name = m_Mobile.Name; + + return name != null && Insensitive.StartsWith(speech, name); + } + + public virtual void GetContextMenuEntries(Mobile from, List list) + { + if (from.Alive && m_Mobile.Controlled && from.InRange(m_Mobile, 14)) + { + if (from == m_Mobile.ControlMaster) { - int number = 1043059 + i; + list.Add(new InternalEntry(from, 6107, 14, m_Mobile, this, OrderType.Guard)); // Command: Guard + list.Add(new InternalEntry(from, 6108, 14, m_Mobile, this, OrderType.Follow)); // Command: Follow - if (number > 1043107) - continue; + if (m_Mobile.CanDrop) + list.Add(new InternalEntry(from, 6109, 14, m_Mobile, this, OrderType.Drop)); // Command: Drop - if (!foundSomething) - m_Mobile.Say(1043058); // I can train the following: + list.Add(new InternalEntry(from, 6111, 14, m_Mobile, this, OrderType.Attack)); // Command: Kill - m_Mobile.Say(number); + list.Add(new InternalEntry(from, 6112, 14, m_Mobile, this, OrderType.Stop)); // Command: Stop + list.Add(new InternalEntry(from, 6114, 14, m_Mobile, this, OrderType.Stay)); // Command: Stay - foundSomething = true; + if (!m_Mobile.Summoned && !(m_Mobile is GrizzledMare)) + { + list.Add(new InternalEntry(from, 6110, 14, m_Mobile, this, OrderType.Friend)); // Add Friend + list.Add(new InternalEntry(from, 6099, 14, m_Mobile, this, OrderType.Unfriend)); // Remove Friend + list.Add(new InternalEntry(from, 6113, 14, m_Mobile, this, OrderType.Transfer)); // Transfer + } + + list.Add(new InternalEntry(from, 6118, 14, m_Mobile, this, OrderType.Release)); // Release + } + else if (m_Mobile.IsPetFriend(from)) + { + list.Add(new InternalEntry(from, 6108, 14, m_Mobile, this, OrderType.Follow)); // Command: Follow + list.Add(new InternalEntry(from, 6112, 14, m_Mobile, this, OrderType.Stop)); // Command: Stop + list.Add(new InternalEntry(from, 6114, 14, m_Mobile, this, OrderType.Stay)); // Command: Stay } - } } - - if (!foundSomething) - m_Mobile.Say(501505); // Alas, I cannot teach thee anything. - } } - else + + public virtual void BeginPickTarget(Mobile from, OrderType order) { - SkillName toTrain = (SkillName)(-1); + if (m_Mobile.Deleted || !m_Mobile.Controlled || !from.InRange(m_Mobile, 14) || from.Map != m_Mobile.Map) + return; - for (int i = 0; toTrain == (SkillName)(-1) && i < e.Keywords.Length; ++i) - { - int keyword = e.Keywords[i]; + var isOwner = from == m_Mobile.ControlMaster; + var isFriend = !isOwner && m_Mobile.IsPetFriend(from); - if (keyword == 0x154) + if (!isOwner && !isFriend) + return; + if (isFriend && order != OrderType.Follow && order != OrderType.Stay && order != OrderType.Stop) + return; + + if (from.Target == null) { - toTrain = SkillName.Anatomy; + if (order == OrderType.Transfer) + from.SendLocalizedMessage(502038); // Click on the person to transfer ownership to. + else if (order == OrderType.Friend) + from.SendLocalizedMessage(502020); // Click on the player whom you wish to make a co-owner. + else if (order == OrderType.Unfriend) + from.SendLocalizedMessage(1070948); // Click on the player whom you wish to remove as a co-owner. + + from.Target = new AIControlMobileTarget(this, order); } - else if (keyword >= 0x6D && keyword <= 0x9C) + else if (from.Target is AIControlMobileTarget t) { - int index = keyword - 0x6D; - - if (index >= 0 && index < m_KeywordTable.Length) - toTrain = m_KeywordTable[index]; + if (t.Order == order) + t.AddAI(this); } - } + } - if (toTrain != (SkillName)(-1) && WasNamed(e.Speech)) - { - if (m_Mobile.Combatant != null) + public virtual void OnAggressiveAction(Mobile aggressor) + { + var currentCombat = m_Mobile.Combatant; + + if (currentCombat != null && !aggressor.Hidden && currentCombat != aggressor && + m_Mobile.GetDistanceToSqrt(currentCombat) > m_Mobile.GetDistanceToSqrt(aggressor)) + m_Mobile.Combatant = aggressor; + } + + public virtual void EndPickTarget(Mobile from, Mobile target, OrderType order) + { + if (m_Mobile.Deleted || !m_Mobile.Controlled || !from.InRange(m_Mobile, 14) || from.Map != m_Mobile.Map || + !from.CheckAlive()) + return; + + var isOwner = from == m_Mobile.ControlMaster; + var isFriend = !isOwner && m_Mobile.IsPetFriend(from); + + if (!isOwner && !isFriend) + return; + if (isFriend && order != OrderType.Follow && order != OrderType.Stay && order != OrderType.Stop) + return; + + if (order == OrderType.Attack) { - // I am too busy fighting to deal with thee! - m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, 501482); + if (target is BaseCreature creature && creature.IsScaryToPets && m_Mobile.IsScaredOfScaryThings) + { + m_Mobile.SayTo(from, "Your pet refuses to attack this creature!"); + return; + } + + if (SolenHelper.CheckRedFriendship(from) && + (target is RedSolenInfiltratorQueen + || target is RedSolenInfiltratorWarrior + || target is RedSolenQueen + || target is RedSolenWarrior + || target is RedSolenWorker) + || SolenHelper.CheckBlackFriendship(from) && + (target is BlackSolenInfiltratorQueen + || target is BlackSolenInfiltratorWarrior + || target is BlackSolenQueen + || target is BlackSolenWarrior + || target is BlackSolenWorker)) + { + from.SendAsciiMessage("You can not force your pet to attack a creature you are protected from."); + return; + } + + if (target is BaseFactionGuard) + { + m_Mobile.SayTo(from, "Your pet refuses to attack the guard."); + return; + } + } + + if (m_Mobile.CheckControlChance(from)) + { + m_Mobile.ControlTarget = target; + m_Mobile.ControlOrder = order; + } + } + + public virtual bool HandlesOnSpeech(Mobile from) + { + if (from.AccessLevel >= AccessLevel.GameMaster) + return true; + + if (from.Alive && m_Mobile.Controlled && m_Mobile.Commandable && + (from == m_Mobile.ControlMaster || m_Mobile.IsPetFriend(from))) + return true; + + return from.Alive && from.InRange(m_Mobile.Location, 3) && m_Mobile.IsHumanInTown(); + } + + public virtual void OnSpeech(SpeechEventArgs e) + { + if (e.Mobile.Alive && e.Mobile.InRange(m_Mobile.Location, 3) && m_Mobile.IsHumanInTown()) + { + if (e.HasKeyword(0x9D) && WasNamed(e.Speech)) // *move* + { + if (m_Mobile.Combatant != null) + { + // I am too busy fighting to deal with thee! + m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, 501482); + } + else + { + // Excuse me? + m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, 501516); + WalkRandomInHome(2, 2, 1); + } + } + else if (e.HasKeyword(0x9E) && WasNamed(e.Speech)) // *time* + { + if (m_Mobile.Combatant != null) + { + // I am too busy fighting to deal with thee! + m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, 501482); + } + else + { + Clock.GetTime(m_Mobile, out var generalNumber, out _); + + m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, generalNumber); + } + } + else if (e.HasKeyword(0x6C) && WasNamed(e.Speech)) // *train + { + if (m_Mobile.Combatant != null) + { + // I am too busy fighting to deal with thee! + m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, 501482); + } + else + { + var foundSomething = false; + + var ourSkills = m_Mobile.Skills; + var theirSkills = e.Mobile.Skills; + + for (var i = 0; i < ourSkills.Length && i < theirSkills.Length; ++i) + { + var skill = ourSkills[i]; + var theirSkill = theirSkills[i]; + + if (skill != null && skill.Base >= 60.0 && + m_Mobile.CheckTeach(skill.SkillName, e.Mobile)) + { + var toTeach = skill.Base / 3.0; + + if (toTeach > 42.0) + toTeach = 42.0; + + if (toTeach > theirSkill.Base) + { + var number = 1043059 + i; + + if (number > 1043107) + continue; + + if (!foundSomething) + m_Mobile.Say(1043058); // I can train the following: + + m_Mobile.Say(number); + + foundSomething = true; + } + } + } + + if (!foundSomething) + m_Mobile.Say(501505); // Alas, I cannot teach thee anything. + } + } + else + { + var toTrain = (SkillName)(-1); + + for (var i = 0; toTrain == (SkillName)(-1) && i < e.Keywords.Length; ++i) + { + var keyword = e.Keywords[i]; + + if (keyword == 0x154) + { + toTrain = SkillName.Anatomy; + } + else if (keyword >= 0x6D && keyword <= 0x9C) + { + var index = keyword - 0x6D; + + if (index >= 0 && index < m_KeywordTable.Length) + toTrain = m_KeywordTable[index]; + } + } + + if (toTrain != (SkillName)(-1) && WasNamed(e.Speech)) + { + if (m_Mobile.Combatant != null) + { + // I am too busy fighting to deal with thee! + m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, 501482); + } + else + { + var skills = m_Mobile.Skills; + var skill = skills[toTrain]; + + if (skill == null || skill.Base < 60.0 || !m_Mobile.CheckTeach(toTrain, e.Mobile)) + m_Mobile.Say(501507); // 'Tis not something I can teach thee of. + else + m_Mobile.Teach(toTrain, e.Mobile, 0, false); + } + } + } + } + + if (m_Mobile.Controlled && m_Mobile.Commandable) + { + m_Mobile.DebugSay("Listening..."); + + var isOwner = e.Mobile == m_Mobile.ControlMaster; + var isFriend = !isOwner && m_Mobile.IsPetFriend(e.Mobile); + + if (e.Mobile.Alive && (isOwner || isFriend)) + { + m_Mobile.DebugSay("It's from my master"); + + var keywords = e.Keywords; + var speech = e.Speech; + + // First, check the all* + for (var i = 0; i < keywords.Length; ++i) + { + var keyword = keywords[i]; + + switch (keyword) + { + case 0x164: // all come + { + if (!isOwner) + break; + + if (m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Come; + } + + return; + } + case 0x165: // all follow + { + BeginPickTarget(e.Mobile, OrderType.Follow); + return; + } + case 0x166: // all guard + case 0x16B: // all guard me + { + if (!isOwner) + break; + + if (m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Guard; + } + + return; + } + case 0x167: // all stop + { + if (m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Stop; + } + + return; + } + case 0x168: // all kill + case 0x169: // all attack + { + if (!isOwner) + break; + + BeginPickTarget(e.Mobile, OrderType.Attack); + return; + } + case 0x16C: // all follow me + { + if (m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = e.Mobile; + m_Mobile.ControlOrder = OrderType.Follow; + } + + return; + } + case 0x170: // all stay + { + if (m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Stay; + } + + return; + } + } + } + + // No all*, so check *command + for (var i = 0; i < keywords.Length; ++i) + { + var keyword = keywords[i]; + + switch (keyword) + { + case 0x155: // *come + { + if (!isOwner) + break; + + if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Come; + } + + return; + } + case 0x156: // *drop + { + if (!isOwner) + break; + + if (!m_Mobile.IsDeadPet && !m_Mobile.Summoned && WasNamed(speech) && + m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Drop; + } + + return; + } + case 0x15A: // *follow + { + if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + BeginPickTarget(e.Mobile, OrderType.Follow); + + return; + } + case 0x15B: // *friend + { + if (!isOwner) + break; + + if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + { + if (m_Mobile.Summoned || m_Mobile is GrizzledMare) + e.Mobile.SendLocalizedMessage( + 1005481 + ); // Summoned creatures are loyal only to their summoners. + else if (e.Mobile.HasTrade) + e.Mobile.SendLocalizedMessage( + 1070947 + ); // You cannot friend a pet with a trade pending + else + BeginPickTarget(e.Mobile, OrderType.Friend); + } + + return; + } + case 0x15C: // *guard + { + if (!isOwner) + break; + + if (!m_Mobile.IsDeadPet && WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Guard; + } + + return; + } + case 0x15D: // *kill + case 0x15E: // *attack + { + if (!isOwner) + break; + + if (!m_Mobile.IsDeadPet && WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + BeginPickTarget(e.Mobile, OrderType.Attack); + + return; + } + case 0x15F: // *patrol + { + if (!isOwner) + break; + + if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Patrol; + } + + return; + } + case 0x161: // *stop + { + if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Stop; + } + + return; + } + case 0x163: // *follow me + { + if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = e.Mobile; + m_Mobile.ControlOrder = OrderType.Follow; + } + + return; + } + case 0x16D: // *release + { + if (!isOwner) + break; + + if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + { + if (!m_Mobile.Summoned) + { + e.Mobile.SendGump(new ConfirmReleaseGump(e.Mobile, m_Mobile)); + } + else + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Release; + } + } + + return; + } + case 0x16E: // *transfer + { + if (!isOwner) + break; + + if (!m_Mobile.IsDeadPet && WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + { + if (m_Mobile.Summoned || m_Mobile is GrizzledMare) + e.Mobile.SendLocalizedMessage( + 1005487 + ); // You cannot transfer ownership of a summoned creature. + else if (e.Mobile.HasTrade) + e.Mobile.SendLocalizedMessage( + 1010507 + ); // You cannot transfer a pet with a trade pending + else + BeginPickTarget(e.Mobile, OrderType.Transfer); + } + + return; + } + case 0x16F: // *stay + { + if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Stay; + } + + return; + } + } + } + } } else { - Skills skills = m_Mobile.Skills; - Skill skill = skills[toTrain]; - - if (skill == null || skill.Base < 60.0 || !m_Mobile.CheckTeach(toTrain, e.Mobile)) - m_Mobile.Say(501507); // 'Tis not something I can teach thee of. - else - m_Mobile.Teach(toTrain, e.Mobile, 0, false); - } - } - } - } - - if (m_Mobile.Controlled && m_Mobile.Commandable) - { - m_Mobile.DebugSay("Listening..."); - - bool isOwner = e.Mobile == m_Mobile.ControlMaster; - bool isFriend = !isOwner && m_Mobile.IsPetFriend(e.Mobile); - - if (e.Mobile.Alive && (isOwner || isFriend)) - { - m_Mobile.DebugSay("It's from my master"); - - int[] keywords = e.Keywords; - string speech = e.Speech; - - // First, check the all* - for (int i = 0; i < keywords.Length; ++i) - { - int keyword = keywords[i]; - - switch (keyword) - { - case 0x164: // all come + if (e.Mobile.AccessLevel >= AccessLevel.GameMaster) { - if (!isOwner) - break; + m_Mobile.DebugSay("It's from a GM"); - if (m_Mobile.CheckControlChance(e.Mobile)) - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Come; - } - - return; - } - case 0x165: // all follow - { - BeginPickTarget(e.Mobile, OrderType.Follow); - return; - } - case 0x166: // all guard - case 0x16B: // all guard me - { - if (!isOwner) - break; - - if (m_Mobile.CheckControlChance(e.Mobile)) - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Guard; - } - - return; - } - case 0x167: // all stop - { - if (m_Mobile.CheckControlChance(e.Mobile)) - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Stop; - } - - return; - } - case 0x168: // all kill - case 0x169: // all attack - { - if (!isOwner) - break; - - BeginPickTarget(e.Mobile, OrderType.Attack); - return; - } - case 0x16C: // all follow me - { - if (m_Mobile.CheckControlChance(e.Mobile)) - { - m_Mobile.ControlTarget = e.Mobile; - m_Mobile.ControlOrder = OrderType.Follow; - } - - return; - } - case 0x170: // all stay - { - if (m_Mobile.CheckControlChance(e.Mobile)) - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Stay; - } - - return; - } - } - } - - // No all*, so check *command - for (int i = 0; i < keywords.Length; ++i) - { - int keyword = keywords[i]; - - switch (keyword) - { - case 0x155: // *come - { - if (!isOwner) - break; - - if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Come; - } - - return; - } - case 0x156: // *drop - { - if (!isOwner) - break; - - if (!m_Mobile.IsDeadPet && !m_Mobile.Summoned && WasNamed(speech) && - m_Mobile.CheckControlChance(e.Mobile)) - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Drop; - } - - return; - } - case 0x15A: // *follow - { - if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) - BeginPickTarget(e.Mobile, OrderType.Follow); - - return; - } - case 0x15B: // *friend - { - if (!isOwner) - break; - - if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) - { - if (m_Mobile.Summoned || m_Mobile is GrizzledMare) - e.Mobile.SendLocalizedMessage( - 1005481); // Summoned creatures are loyal only to their summoners. - else if (e.Mobile.HasTrade) - e.Mobile.SendLocalizedMessage( - 1070947); // You cannot friend a pet with a trade pending - else - BeginPickTarget(e.Mobile, OrderType.Friend); - } - - return; - } - case 0x15C: // *guard - { - if (!isOwner) - break; - - if (!m_Mobile.IsDeadPet && WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Guard; - } - - return; - } - case 0x15D: // *kill - case 0x15E: // *attack - { - if (!isOwner) - break; - - if (!m_Mobile.IsDeadPet && WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) - BeginPickTarget(e.Mobile, OrderType.Attack); - - return; - } - case 0x15F: // *patrol - { - if (!isOwner) - break; - - if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Patrol; - } - - return; - } - case 0x161: // *stop - { - if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Stop; - } - - return; - } - case 0x163: // *follow me - { - if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) - { - m_Mobile.ControlTarget = e.Mobile; - m_Mobile.ControlOrder = OrderType.Follow; - } - - return; - } - case 0x16D: // *release - { - if (!isOwner) - break; - - if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) - { - if (!m_Mobile.Summoned) + if (m_Mobile.FindMyName(e.Speech, true)) { - e.Mobile.SendGump(new ConfirmReleaseGump(e.Mobile, m_Mobile)); + var str = e.Speech.Split(' '); + int i; + + for (i = 0; i < str.Length; i++) + { + var word = str[i]; + + if (Insensitive.Equals(word, "obey")) + { + m_Mobile.SetControlMaster(e.Mobile); + + if (m_Mobile.Summoned) + m_Mobile.SummonMaster = e.Mobile; + + return; + } + } } - else - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Release; - } - } - - return; - } - case 0x16E: // *transfer - { - if (!isOwner) - break; - - if (!m_Mobile.IsDeadPet && WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) - { - if (m_Mobile.Summoned || m_Mobile is GrizzledMare) - e.Mobile.SendLocalizedMessage( - 1005487); // You cannot transfer ownership of a summoned creature. - else if (e.Mobile.HasTrade) - e.Mobile.SendLocalizedMessage( - 1010507); // You cannot transfer a pet with a trade pending - else - BeginPickTarget(e.Mobile, OrderType.Transfer); - } - - return; - } - case 0x16F: // *stay - { - if (WasNamed(speech) && m_Mobile.CheckControlChance(e.Mobile)) - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Stay; - } - - return; } } - } } - } - else - { - if (e.Mobile.AccessLevel >= AccessLevel.GameMaster) + + public virtual bool Think() { - m_Mobile.DebugSay("It's from a GM"); + if (m_Mobile.Deleted) + return false; - if (m_Mobile.FindMyName(e.Speech, true)) - { - string[] str = e.Speech.Split(' '); - int i; + if (CheckFlee()) + return true; - for (i = 0; i < str.Length; i++) + switch (Action) { - string word = str[i]; + case ActionType.Wander: + m_Mobile.OnActionWander(); + return DoActionWander(); - if (Insensitive.Equals(word, "obey")) - { - m_Mobile.SetControlMaster(e.Mobile); + case ActionType.Combat: + m_Mobile.OnActionCombat(); + return DoActionCombat(); - if (m_Mobile.Summoned) - m_Mobile.SummonMaster = e.Mobile; + case ActionType.Guard: + m_Mobile.OnActionGuard(); + return DoActionGuard(); + case ActionType.Flee: + m_Mobile.OnActionFlee(); + return DoActionFlee(); + + case ActionType.Interact: + m_Mobile.OnActionInteract(); + return DoActionInteract(); + + case ActionType.Backoff: + m_Mobile.OnActionBackoff(); + return DoActionBackoff(); + + default: + return false; + } + } + + public virtual void OnActionChanged() + { + switch (Action) + { + case ActionType.Wander: + m_Mobile.Warmode = false; + m_Mobile.Combatant = null; + m_Mobile.FocusMob = null; + m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; + break; + + case ActionType.Combat: + m_Mobile.Warmode = true; + m_Mobile.FocusMob = null; + m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; + break; + + case ActionType.Guard: + m_Mobile.Warmode = true; + m_Mobile.FocusMob = null; + m_Mobile.Combatant = null; + m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; + m_NextStopGuard = Core.TickCount + (int)TimeSpan.FromSeconds(10).TotalMilliseconds; + m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; + break; + + case ActionType.Flee: + m_Mobile.Warmode = true; + m_Mobile.FocusMob = null; + m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; + break; + + case ActionType.Interact: + m_Mobile.Warmode = false; + m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; + break; + + case ActionType.Backoff: + m_Mobile.Warmode = false; + m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; + break; + } + } + + public virtual bool OnAtWayPoint() => true; + + public virtual bool DoActionWander() + { + if (CheckHerding()) + { + m_Mobile.DebugSay("Praise the shepherd!"); + } + else if (m_Mobile.CurrentWayPoint != null) + { + var point = m_Mobile.CurrentWayPoint; + if ((point.X != m_Mobile.Location.X || point.Y != m_Mobile.Location.Y) && point.Map == m_Mobile.Map && + point.Parent == null && !point.Deleted) + { + m_Mobile.DebugSay("I will move towards my waypoint."); + DoMove(m_Mobile.GetDirectionTo(m_Mobile.CurrentWayPoint)); + } + else if (OnAtWayPoint()) + { + m_Mobile.DebugSay("I will go to the next waypoint"); + m_Mobile.CurrentWayPoint = point.NextPoint; + if (point.NextPoint?.Deleted == true) + m_Mobile.CurrentWayPoint = point.NextPoint = point.NextPoint.NextPoint; + } + } + else if (m_Mobile.IsAnimatedDead) + { + // animated dead follow their master + var master = m_Mobile.SummonMaster; + + if (master != null && master.Map == m_Mobile.Map && master.InRange(m_Mobile, m_Mobile.RangePerception)) + MoveTo(master, false, 1); + else + WalkRandomInHome(2, 2, 1); + } + else if (CheckMove()) + { + if (!m_Mobile.CheckIdle()) + WalkRandomInHome(2, 2, 1); + } + + if (m_Mobile.Combatant?.Deleted == false && m_Mobile.Combatant.Alive && + !m_Mobile.Combatant.IsDeadBondedPet) m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant); + + return true; + } + + public virtual bool DoActionCombat() + { + if (Core.AOS && CheckHerding()) + { + m_Mobile.DebugSay("Praise the shepherd!"); + } + else + { + var c = m_Mobile.Combatant; + + if (c?.Deleted != false || c.Map != m_Mobile.Map || !c.Alive || c.IsDeadBondedPet) + Action = ActionType.Wander; + else + m_Mobile.Direction = m_Mobile.GetDirectionTo(c); + } + + return true; + } + + public virtual bool DoActionGuard() + { + if (Core.AOS && CheckHerding()) + { + m_Mobile.DebugSay("Praise the shepherd!"); + } + else if (Core.TickCount - m_NextStopGuard < 0) + { + m_Mobile.DebugSay("I am on guard"); + // m_Mobile.Turn( Utility.Random(0, 2) - 1 ); + } + else + { + m_Mobile.DebugSay("I stopped being on guard"); + Action = ActionType.Wander; + } + + return true; + } + + public virtual bool DoActionFlee() + { + var from = m_Mobile.FocusMob; + + if (from?.Deleted != false || from.Map != m_Mobile.Map) + { + m_Mobile.DebugSay("I have lost him"); + Action = ActionType.Guard; + return true; + } + + if (WalkMobileRange(from, 1, true, m_Mobile.RangePerception * 2, m_Mobile.RangePerception * 3)) + { + m_Mobile.DebugSay("I have fled"); + Action = ActionType.Guard; + return true; + } + + m_Mobile.DebugSay("I am fleeing!"); + + return true; + } + + public virtual bool DoActionInteract() => true; + + public virtual bool DoActionBackoff() => true; + + public virtual bool Obey() + { + if (m_Mobile.Deleted) + return false; + + return m_Mobile.ControlOrder switch + { + OrderType.None => DoOrderNone(), + OrderType.Come => DoOrderCome(), + OrderType.Drop => DoOrderDrop(), + OrderType.Friend => DoOrderFriend(), + OrderType.Unfriend => DoOrderUnfriend(), + OrderType.Guard => DoOrderGuard(), + OrderType.Attack => DoOrderAttack(), + OrderType.Patrol => DoOrderPatrol(), + OrderType.Release => DoOrderRelease(), + OrderType.Stay => DoOrderStay(), + OrderType.Stop => DoOrderStop(), + OrderType.Follow => DoOrderFollow(), + OrderType.Transfer => DoOrderTransfer(), + _ => false + }; + } + + public virtual void OnCurrentOrderChanged() + { + if (m_Mobile.Deleted || m_Mobile.ControlMaster?.Deleted != false) return; - } - } - } - } - } - } - public virtual bool Think() - { - if (m_Mobile.Deleted) - return false; - - if (CheckFlee()) - return true; - - switch (Action) - { - case ActionType.Wander: - m_Mobile.OnActionWander(); - return DoActionWander(); - - case ActionType.Combat: - m_Mobile.OnActionCombat(); - return DoActionCombat(); - - case ActionType.Guard: - m_Mobile.OnActionGuard(); - return DoActionGuard(); - - case ActionType.Flee: - m_Mobile.OnActionFlee(); - return DoActionFlee(); - - case ActionType.Interact: - m_Mobile.OnActionInteract(); - return DoActionInteract(); - - case ActionType.Backoff: - m_Mobile.OnActionBackoff(); - return DoActionBackoff(); - - default: - return false; - } - } - - public virtual void OnActionChanged() - { - switch (Action) - { - case ActionType.Wander: - m_Mobile.Warmode = false; - m_Mobile.Combatant = null; - m_Mobile.FocusMob = null; - m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; - break; - - case ActionType.Combat: - m_Mobile.Warmode = true; - m_Mobile.FocusMob = null; - m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; - break; - - case ActionType.Guard: - m_Mobile.Warmode = true; - m_Mobile.FocusMob = null; - m_Mobile.Combatant = null; - m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; - m_NextStopGuard = Core.TickCount + (int)TimeSpan.FromSeconds(10).TotalMilliseconds; - m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; - break; - - case ActionType.Flee: - m_Mobile.Warmode = true; - m_Mobile.FocusMob = null; - m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; - break; - - case ActionType.Interact: - m_Mobile.Warmode = false; - m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; - break; - - case ActionType.Backoff: - m_Mobile.Warmode = false; - m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; - break; - } - } - - public virtual bool OnAtWayPoint() => true; - - public virtual bool DoActionWander() - { - if (CheckHerding()) - { - m_Mobile.DebugSay("Praise the shepherd!"); - } - else if (m_Mobile.CurrentWayPoint != null) - { - WayPoint point = m_Mobile.CurrentWayPoint; - if ((point.X != m_Mobile.Location.X || point.Y != m_Mobile.Location.Y) && point.Map == m_Mobile.Map && - point.Parent == null && !point.Deleted) - { - m_Mobile.DebugSay("I will move towards my waypoint."); - DoMove(m_Mobile.GetDirectionTo(m_Mobile.CurrentWayPoint)); - } - else if (OnAtWayPoint()) - { - m_Mobile.DebugSay("I will go to the next waypoint"); - m_Mobile.CurrentWayPoint = point.NextPoint; - if (point.NextPoint?.Deleted == true) - m_Mobile.CurrentWayPoint = point.NextPoint = point.NextPoint.NextPoint; - } - } - else if (m_Mobile.IsAnimatedDead) - { - // animated dead follow their master - Mobile master = m_Mobile.SummonMaster; - - if (master != null && master.Map == m_Mobile.Map && master.InRange(m_Mobile, m_Mobile.RangePerception)) - MoveTo(master, false, 1); - else - WalkRandomInHome(2, 2, 1); - } - else if (CheckMove()) - { - if (!m_Mobile.CheckIdle()) - WalkRandomInHome(2, 2, 1); - } - - if (m_Mobile.Combatant?.Deleted == false && m_Mobile.Combatant.Alive && - !m_Mobile.Combatant.IsDeadBondedPet) m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant); - - return true; - } - - public virtual bool DoActionCombat() - { - if (Core.AOS && CheckHerding()) - { - m_Mobile.DebugSay("Praise the shepherd!"); - } - else - { - Mobile c = m_Mobile.Combatant; - - if (c?.Deleted != false || c.Map != m_Mobile.Map || !c.Alive || c.IsDeadBondedPet) - Action = ActionType.Wander; - else - m_Mobile.Direction = m_Mobile.GetDirectionTo(c); - } - - return true; - } - - public virtual bool DoActionGuard() - { - if (Core.AOS && CheckHerding()) - { - m_Mobile.DebugSay("Praise the shepherd!"); - } - else if (Core.TickCount - m_NextStopGuard < 0) - { - m_Mobile.DebugSay("I am on guard"); - // m_Mobile.Turn( Utility.Random(0, 2) - 1 ); - } - else - { - m_Mobile.DebugSay("I stopped being on guard"); - Action = ActionType.Wander; - } - - return true; - } - - public virtual bool DoActionFlee() - { - Mobile from = m_Mobile.FocusMob; - - if (from?.Deleted != false || from.Map != m_Mobile.Map) - { - m_Mobile.DebugSay("I have lost him"); - Action = ActionType.Guard; - return true; - } - - if (WalkMobileRange(from, 1, true, m_Mobile.RangePerception * 2, m_Mobile.RangePerception * 3)) - { - m_Mobile.DebugSay("I have fled"); - Action = ActionType.Guard; - return true; - } - - m_Mobile.DebugSay("I am fleeing!"); - - return true; - } - - public virtual bool DoActionInteract() => true; - - public virtual bool DoActionBackoff() => true; - - public virtual bool Obey() - { - if (m_Mobile.Deleted) - return false; - - return m_Mobile.ControlOrder switch - { - OrderType.None => DoOrderNone(), - OrderType.Come => DoOrderCome(), - OrderType.Drop => DoOrderDrop(), - OrderType.Friend => DoOrderFriend(), - OrderType.Unfriend => DoOrderUnfriend(), - OrderType.Guard => DoOrderGuard(), - OrderType.Attack => DoOrderAttack(), - OrderType.Patrol => DoOrderPatrol(), - OrderType.Release => DoOrderRelease(), - OrderType.Stay => DoOrderStay(), - OrderType.Stop => DoOrderStop(), - OrderType.Follow => DoOrderFollow(), - OrderType.Transfer => DoOrderTransfer(), - _ => false - }; - } - - public virtual void OnCurrentOrderChanged() - { - if (m_Mobile.Deleted || m_Mobile.ControlMaster?.Deleted != false) - return; - - switch (m_Mobile.ControlOrder) - { - case OrderType.None: - m_Mobile.ControlMaster.RevealingAction(); - m_Mobile.Home = m_Mobile.Location; - m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; - m_Mobile.PlaySound(m_Mobile.GetIdleSound()); - m_Mobile.Warmode = false; - m_Mobile.Combatant = null; - break; - - case OrderType.Come: - m_Mobile.ControlMaster.RevealingAction(); - m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; - m_Mobile.PlaySound(m_Mobile.GetIdleSound()); - m_Mobile.Warmode = false; - m_Mobile.Combatant = null; - break; - - case OrderType.Drop: - m_Mobile.ControlMaster.RevealingAction(); - m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; - m_Mobile.PlaySound(m_Mobile.GetIdleSound()); - m_Mobile.Warmode = true; - m_Mobile.Combatant = null; - break; - - case OrderType.Friend: - case OrderType.Unfriend: - m_Mobile.ControlMaster.RevealingAction(); - break; - - case OrderType.Guard: - m_Mobile.ControlMaster.RevealingAction(); - m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; - m_Mobile.PlaySound(m_Mobile.GetIdleSound()); - m_Mobile.Warmode = true; - m_Mobile.Combatant = null; - string petname = $"{m_Mobile.Name}"; - m_Mobile.ControlMaster.SendLocalizedMessage(1049671, petname); // ~1_PETNAME~ is now guarding you. - break; - - case OrderType.Attack: - m_Mobile.ControlMaster.RevealingAction(); - m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; - m_Mobile.PlaySound(m_Mobile.GetIdleSound()); - - m_Mobile.Warmode = true; - m_Mobile.Combatant = null; - break; - - case OrderType.Patrol: - m_Mobile.ControlMaster.RevealingAction(); - m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; - m_Mobile.PlaySound(m_Mobile.GetIdleSound()); - m_Mobile.Warmode = false; - m_Mobile.Combatant = null; - break; - - case OrderType.Release: - m_Mobile.ControlMaster.RevealingAction(); - m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; - m_Mobile.PlaySound(m_Mobile.GetIdleSound()); - m_Mobile.Warmode = false; - m_Mobile.Combatant = null; - break; - - case OrderType.Stay: - m_Mobile.ControlMaster.RevealingAction(); - m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; - m_Mobile.PlaySound(m_Mobile.GetIdleSound()); - m_Mobile.Warmode = false; - m_Mobile.Combatant = null; - break; - - case OrderType.Stop: - m_Mobile.ControlMaster.RevealingAction(); - m_Mobile.Home = m_Mobile.Location; - m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; - m_Mobile.PlaySound(m_Mobile.GetIdleSound()); - m_Mobile.Warmode = false; - m_Mobile.Combatant = null; - break; - - case OrderType.Follow: - m_Mobile.ControlMaster.RevealingAction(); - m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; - m_Mobile.PlaySound(m_Mobile.GetIdleSound()); - - m_Mobile.Warmode = false; - m_Mobile.Combatant = null; - break; - - case OrderType.Transfer: - m_Mobile.ControlMaster.RevealingAction(); - m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; - m_Mobile.PlaySound(m_Mobile.GetIdleSound()); - - m_Mobile.Warmode = false; - m_Mobile.Combatant = null; - break; - } - } - - public virtual bool DoOrderNone() - { - m_Mobile.DebugSay("I have no order"); - - WalkRandomInHome(3, 2, 1); - - if (m_Mobile.Combatant?.Deleted == false && m_Mobile.Combatant.Alive && - !m_Mobile.Combatant.IsDeadBondedPet) - { - m_Mobile.Warmode = true; - m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant); - } - else - { - m_Mobile.Warmode = false; - } - - return true; - } - - public virtual bool DoOrderCome() - { - if (m_Mobile.ControlMaster?.Deleted != false) - return true; - - int iCurrDist = (int)m_Mobile.GetDistanceToSqrt(m_Mobile.ControlMaster); - - if (iCurrDist > m_Mobile.RangePerception) - { - m_Mobile.DebugSay("I have lost my master. I stay here"); - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.None; - } - else - { - m_Mobile.DebugSay("My master told me come"); - - // Not exactly OSI style, but better than nothing. - bool bRun = iCurrDist > 5; - - if (WalkMobileRange(m_Mobile.ControlMaster, 1, bRun, 0, 1)) - { - if (m_Mobile.Combatant?.Deleted == false && m_Mobile.Combatant.Alive && - !m_Mobile.Combatant.IsDeadBondedPet) - { - m_Mobile.Warmode = true; - m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant); - } - else - { - m_Mobile.Warmode = false; - } - } - } - - return true; - } - - public virtual bool DoOrderDrop() - { - if (m_Mobile.IsDeadPet || !m_Mobile.CanDrop) - return true; - - m_Mobile.DebugSay("I drop my stuff for my master"); - - Container pack = m_Mobile.Backpack; - - if (pack != null) - { - List list = pack.Items; - - for (int i = list.Count - 1; i >= 0; --i) - if (i < list.Count) - list[i].MoveToWorld(m_Mobile.Location, m_Mobile.Map); - } - - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.None; - - return true; - } - - public virtual bool CheckHerding() - { - IPoint2D target = m_Mobile.TargetLocation; - - if (target == null) - return false; // Creature is not being herded - - double distance = m_Mobile.GetDistanceToSqrt(target); - - if (!(distance < 1 || distance > 15)) - { - DoMove(m_Mobile.GetDirectionTo(target)); - return true; - } - - if (distance < 1 && target.X == 1076 && target.Y == 450 && m_Mobile is HordeMinionFamiliar) - if (m_Mobile.ControlMaster is PlayerMobile pm) - { - QuestSystem qs = pm.Quest; - - if (qs is DarkTidesQuest) - { - QuestObjective obj = qs.FindObjective(); - - if (obj?.Completed == false) + switch (m_Mobile.ControlOrder) { - m_Mobile.AddToBackpack(new ScrollOfAbraxus()); - obj.Complete(); + case OrderType.None: + m_Mobile.ControlMaster.RevealingAction(); + m_Mobile.Home = m_Mobile.Location; + m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; + m_Mobile.PlaySound(m_Mobile.GetIdleSound()); + m_Mobile.Warmode = false; + m_Mobile.Combatant = null; + break; + + case OrderType.Come: + m_Mobile.ControlMaster.RevealingAction(); + m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; + m_Mobile.PlaySound(m_Mobile.GetIdleSound()); + m_Mobile.Warmode = false; + m_Mobile.Combatant = null; + break; + + case OrderType.Drop: + m_Mobile.ControlMaster.RevealingAction(); + m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; + m_Mobile.PlaySound(m_Mobile.GetIdleSound()); + m_Mobile.Warmode = true; + m_Mobile.Combatant = null; + break; + + case OrderType.Friend: + case OrderType.Unfriend: + m_Mobile.ControlMaster.RevealingAction(); + break; + + case OrderType.Guard: + m_Mobile.ControlMaster.RevealingAction(); + m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; + m_Mobile.PlaySound(m_Mobile.GetIdleSound()); + m_Mobile.Warmode = true; + m_Mobile.Combatant = null; + var petname = $"{m_Mobile.Name}"; + m_Mobile.ControlMaster.SendLocalizedMessage(1049671, petname); // ~1_PETNAME~ is now guarding you. + break; + + case OrderType.Attack: + m_Mobile.ControlMaster.RevealingAction(); + m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; + m_Mobile.PlaySound(m_Mobile.GetIdleSound()); + + m_Mobile.Warmode = true; + m_Mobile.Combatant = null; + break; + + case OrderType.Patrol: + m_Mobile.ControlMaster.RevealingAction(); + m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; + m_Mobile.PlaySound(m_Mobile.GetIdleSound()); + m_Mobile.Warmode = false; + m_Mobile.Combatant = null; + break; + + case OrderType.Release: + m_Mobile.ControlMaster.RevealingAction(); + m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; + m_Mobile.PlaySound(m_Mobile.GetIdleSound()); + m_Mobile.Warmode = false; + m_Mobile.Combatant = null; + break; + + case OrderType.Stay: + m_Mobile.ControlMaster.RevealingAction(); + m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; + m_Mobile.PlaySound(m_Mobile.GetIdleSound()); + m_Mobile.Warmode = false; + m_Mobile.Combatant = null; + break; + + case OrderType.Stop: + m_Mobile.ControlMaster.RevealingAction(); + m_Mobile.Home = m_Mobile.Location; + m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; + m_Mobile.PlaySound(m_Mobile.GetIdleSound()); + m_Mobile.Warmode = false; + m_Mobile.Combatant = null; + break; + + case OrderType.Follow: + m_Mobile.ControlMaster.RevealingAction(); + m_Mobile.CurrentSpeed = m_Mobile.ActiveSpeed; + m_Mobile.PlaySound(m_Mobile.GetIdleSound()); + + m_Mobile.Warmode = false; + m_Mobile.Combatant = null; + break; + + case OrderType.Transfer: + m_Mobile.ControlMaster.RevealingAction(); + m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed; + m_Mobile.PlaySound(m_Mobile.GetIdleSound()); + + m_Mobile.Warmode = false; + m_Mobile.Combatant = null; + break; } - } } - m_Mobile.TargetLocation = null; - return false; // At the target or too far away - } - - public virtual bool DoOrderFollow() - { - if (CheckHerding()) - { - m_Mobile.DebugSay("Praise the shepherd!"); - } - else if (m_Mobile.ControlTarget?.Deleted == false && m_Mobile.ControlTarget != m_Mobile) - { - int iCurrDist = (int)m_Mobile.GetDistanceToSqrt(m_Mobile.ControlTarget); - - if (iCurrDist > m_Mobile.RangePerception) + public virtual bool DoOrderNone() { - m_Mobile.DebugSay("I have lost the one to follow. I stay here"); + m_Mobile.DebugSay("I have no order"); - if (m_Mobile.Combatant?.Deleted == false && m_Mobile.Combatant.Alive && - !m_Mobile.Combatant.IsDeadBondedPet) - { - m_Mobile.Warmode = true; - m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant); - } - else - { - m_Mobile.Warmode = false; - } - } - else - { - m_Mobile.DebugSay("My master told me to follow: {0}", m_Mobile.ControlTarget.Name); + WalkRandomInHome(3, 2, 1); - // Not exactly OSI style, but better than nothing. - bool bRun = iCurrDist > 5; - - if (WalkMobileRange(m_Mobile.ControlTarget, 1, bRun, 0, 1)) - { if (m_Mobile.Combatant?.Deleted == false && m_Mobile.Combatant.Alive && !m_Mobile.Combatant.IsDeadBondedPet) { - m_Mobile.Warmode = true; - m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant); + m_Mobile.Warmode = true; + m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant); } else { - m_Mobile.Warmode = false; - if (Core.AOS) - m_Mobile.CurrentSpeed = 0.1; + m_Mobile.Warmode = false; } - } + + return true; } - } - else - { - m_Mobile.DebugSay("I have nobody to follow"); - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.None; - } - return true; - } - - public virtual bool DoOrderFriend() - { - Mobile from = m_Mobile.ControlMaster; - Mobile to = m_Mobile.ControlTarget; - - if (from?.Deleted != false || to?.Deleted != false || from == to || !to.Player) - { - m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, 502039); // *looks confused* - } - else - { - bool youngFrom = from is PlayerMobile mobile && mobile.Young; - bool youngTo = to is PlayerMobile playerMobile && playerMobile.Young; - - if (youngFrom && !youngTo) + public virtual bool DoOrderCome() { - from.SendLocalizedMessage(502040); // As a young player, you may not friend pets to older players. - } - else if (!youngFrom && youngTo) - { - from.SendLocalizedMessage(502041); // As an older player, you may not friend pets to young players. - } - else if (from.CanBeBeneficial(to, true)) - { - NetState fromState = from.NetState, toState = to.NetState; + if (m_Mobile.ControlMaster?.Deleted != false) + return true; - if (fromState != null && toState != null) - { - if (from.HasTrade) + var iCurrDist = (int)m_Mobile.GetDistanceToSqrt(m_Mobile.ControlMaster); + + if (iCurrDist > m_Mobile.RangePerception) { - from.SendLocalizedMessage(1070947); // You cannot friend a pet with a trade pending - } - else if (to.HasTrade) - { - to.SendLocalizedMessage(1070947); // You cannot friend a pet with a trade pending - } - else if (m_Mobile.IsPetFriend(to)) - { - from.SendLocalizedMessage(1049691); // That person is already a friend. - } - else if (!m_Mobile.AllowNewPetFriend) - { - from.SendLocalizedMessage( - 1005482); // Your pet does not seem to be interested in making new friends right now. + m_Mobile.DebugSay("I have lost my master. I stay here"); + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.None; } else { - // ~1_NAME~ will now accept movement commands from ~2_NAME~. - from.SendLocalizedMessage(1049676, $"{m_Mobile.Name}\t{to.Name}"); + m_Mobile.DebugSay("My master told me come"); - /* ~1_NAME~ has granted you the ability to give orders to their pet ~2_PET_NAME~. - * This creature will now consider you as a friend. - */ - to.SendLocalizedMessage(1043246, $"{from.Name}\t{m_Mobile.Name}"); + // Not exactly OSI style, but better than nothing. + var bRun = iCurrDist > 5; - m_Mobile.AddPetFriend(to); - - m_Mobile.ControlTarget = to; - m_Mobile.ControlOrder = OrderType.Follow; - - return true; - } - } - } - } - - m_Mobile.ControlTarget = from; - m_Mobile.ControlOrder = OrderType.Follow; - - return true; - } - - public virtual bool DoOrderUnfriend() - { - Mobile from = m_Mobile.ControlMaster; - Mobile to = m_Mobile.ControlTarget; - - if (from?.Deleted != false || to?.Deleted != false || from == to || !to.Player) - { - m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, 502039); // *looks confused* - } - else if (!m_Mobile.IsPetFriend(to)) - { - from.SendLocalizedMessage(1070953); // That person is not a friend. - } - else - { - // ~1_NAME~ will no longer accept movement commands from ~2_NAME~. - from.SendLocalizedMessage(1070951, $"{m_Mobile.Name}\t{to.Name}"); - - /* ~1_NAME~ has no longer granted you the ability to give orders to their pet ~2_PET_NAME~. - * This creature will no longer consider you as a friend. - */ - to.SendLocalizedMessage(1070952, $"{from.Name}\t{m_Mobile.Name}"); - - m_Mobile.RemovePetFriend(to); - } - - m_Mobile.ControlTarget = from; - m_Mobile.ControlOrder = OrderType.Follow; - - return true; - } - - public virtual bool DoOrderGuard() - { - if (m_Mobile.IsDeadPet) - return true; - - Mobile controlMaster = m_Mobile.ControlMaster; - - if (controlMaster?.Deleted != false) - return true; - - Mobile combatant = m_Mobile.Combatant; - - List aggressors = controlMaster.Aggressors; - - if (aggressors.Count > 0) - { - for (int i = 0; i < aggressors.Count; ++i) - { - AggressorInfo info = aggressors[i]; - Mobile attacker = info.Attacker; - - if (attacker?.Deleted == false && - attacker.GetDistanceToSqrt(m_Mobile) <= m_Mobile.RangePerception) - if (combatant == null || attacker.GetDistanceToSqrt(controlMaster) < - combatant.GetDistanceToSqrt(controlMaster)) - combatant = attacker; - } - - if (combatant != null) - m_Mobile.DebugSay("Crap, my master has been attacked! I will attack one of those bastards!"); - } - - if (combatant?.Deleted == false && combatant != m_Mobile && combatant != m_Mobile.ControlMaster && - combatant.Alive && !combatant.IsDeadBondedPet && m_Mobile.CanSee(combatant) && - m_Mobile.CanBeHarmful(combatant, false) && combatant.Map == m_Mobile.Map) - { - m_Mobile.DebugSay("Guarding from target..."); - - m_Mobile.Combatant = combatant; - m_Mobile.FocusMob = combatant; - Action = ActionType.Combat; - - /* - * We need to call Think() here or spell casting monsters will not use - * spells when guarding because their target is never processed. - */ - Think(); - } - else - { - m_Mobile.DebugSay("Nothing to guard from"); - - m_Mobile.Warmode = false; - if (Core.AOS) - m_Mobile.CurrentSpeed = 0.1; - - WalkMobileRange(controlMaster, 1, false, 0, 1); - } - - return true; - } - - public virtual bool DoOrderAttack() - { - if (m_Mobile.IsDeadPet) - return true; - - if (m_Mobile.ControlTarget?.Deleted != false || m_Mobile.ControlTarget.Map != m_Mobile.Map || - !m_Mobile.ControlTarget.Alive || m_Mobile.ControlTarget.IsDeadBondedPet) - { - m_Mobile.DebugSay( - "I think he might be dead. He's not anywhere around here at least. That's cool. I'm glad he's dead."); - - if (Core.AOS) - { - m_Mobile.ControlTarget = m_Mobile.ControlMaster; - m_Mobile.ControlOrder = OrderType.Follow; - } - else - { - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.None; - } - - if (m_Mobile.FightMode == FightMode.Closest || m_Mobile.FightMode == FightMode.Aggressor) - { - Mobile newCombatant = null; - double newScore = 0.0; - - foreach (Mobile aggr in m_Mobile.GetMobilesInRange(m_Mobile.RangePerception)) - { - if (!m_Mobile.CanSee(aggr) || aggr.Combatant != m_Mobile) - continue; - - if (aggr.IsDeadBondedPet || !aggr.Alive) - continue; - - double aggrScore = m_Mobile.GetFightModeRanking(aggr, FightMode.Closest, false); - - if ((newCombatant == null || aggrScore > newScore) && m_Mobile.InLOS(aggr)) - { - newCombatant = aggr; - newScore = aggrScore; - } - } - - if (newCombatant != null) - { - m_Mobile.ControlTarget = newCombatant; - m_Mobile.ControlOrder = OrderType.Attack; - m_Mobile.Combatant = newCombatant; - m_Mobile.DebugSay("But -that- is not dead. Here we go again..."); - Think(); - } - } - } - else - { - m_Mobile.DebugSay("Attacking target..."); - Think(); - } - - return true; - } - - public virtual bool DoOrderPatrol() - { - m_Mobile.DebugSay("This order is not yet coded"); - return true; - } - - public virtual bool DoOrderRelease() - { - m_Mobile.DebugSay("I have been released"); - - m_Mobile.PlaySound(m_Mobile.GetAngerSound()); - - m_Mobile.SetControlMaster(null); - m_Mobile.SummonMaster = null; - - m_Mobile.BondingBegin = DateTime.MinValue; - m_Mobile.OwnerAbandonTime = DateTime.MinValue; - m_Mobile.IsBonded = false; - - var spawner = m_Mobile.Spawner; - - if (spawner != null && spawner.HomeLocation != Point3D.Zero) - { - m_Mobile.Home = spawner.HomeLocation; - m_Mobile.RangeHome = spawner.HomeRange; - } - - if (m_Mobile.DeleteOnRelease || m_Mobile.IsDeadPet) - m_Mobile.Delete(); - - m_Mobile.BeginDeleteTimer(); - m_Mobile.DropBackpack(); - - return true; - } - - public virtual bool DoOrderStay() - { - if (CheckHerding()) - m_Mobile.DebugSay("Praise the shepherd!"); - else - m_Mobile.DebugSay("My master told me to stay"); - - // m_Mobile.Direction = m_Mobile.GetDirectionTo( m_Mobile.ControlMaster ); - - return true; - } - - public virtual bool DoOrderStop() - { - if (m_Mobile.ControlMaster?.Deleted != false) - return true; - - m_Mobile.DebugSay("My master told me to stop."); - - m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.ControlMaster); - m_Mobile.Home = m_Mobile.Location; - - m_Mobile.ControlTarget = null; - - if (Core.ML) - WalkRandomInHome(3, 2, 1); - else - m_Mobile.ControlOrder = OrderType.None; - - return true; - } - - public virtual bool DoOrderTransfer() - { - if (m_Mobile.IsDeadPet) - return true; - - Mobile from = m_Mobile.ControlMaster; - Mobile to = m_Mobile.ControlTarget; - - if (from?.Deleted == false && to?.Deleted == false && from != to && to.Player) - { - m_Mobile.DebugSay("Begin transfer with {0}", to.Name); - - bool youngFrom = from is PlayerMobile mobile && mobile.Young; - bool youngTo = to is PlayerMobile playerMobile && playerMobile.Young; - - if (youngFrom && !youngTo) - { - from.SendLocalizedMessage(502051); // As a young player, you may not transfer pets to older players. - } - else if (!youngFrom && youngTo) - { - from.SendLocalizedMessage(502052); // As an older player, you may not transfer pets to young players. - } - else if (!m_Mobile.CanBeControlledBy(to)) - { - string args = $"{to.Name}\t{from.Name}\t "; - - from.SendLocalizedMessage(1043248, - args); // The pet refuses to be transferred because it will not obey ~1_NAME~.~3_BLANK~ - to.SendLocalizedMessage(1043249, - args); // The pet will not accept you as a master because it does not trust you.~3_BLANK~ - } - else if (!m_Mobile.CanBeControlledBy(from)) - { - string args = $"{to.Name}\t{from.Name}\t "; - - from.SendLocalizedMessage(1043250, - args); // The pet refuses to be transferred because it will not obey you sufficiently.~3_BLANK~ - to.SendLocalizedMessage(1043251, - args); // The pet will not accept you as a master because it does not trust ~2_NAME~.~3_BLANK~ - } - else if (TransferItem.IsInCombat(m_Mobile)) - { - from.SendMessage("You may not transfer a pet that has recently been in combat."); - to.SendMessage("The pet may not be transferred to you because it has recently been in combat."); - } - else - { - NetState fromState = from.NetState, toState = to.NetState; - - if (fromState != null && toState != null) - { - if (from.HasTrade) - { - from.SendLocalizedMessage(1010507); // You cannot transfer a pet with a trade pending - } - else if (to.HasTrade) - { - to.SendLocalizedMessage(1010507); // You cannot transfer a pet with a trade pending - } - else - { - Container c = fromState.AddTrade(toState); - c.DropItem(new TransferItem(m_Mobile)); - } - } - } - } - - m_Mobile.ControlTarget = null; - m_Mobile.ControlOrder = OrderType.Stay; - - return true; - } - - public virtual bool DoBardPacified() - { - if (DateTime.UtcNow < m_Mobile.BardEndTime) - { - m_Mobile.DebugSay("I am pacified, I wait"); - m_Mobile.Combatant = null; - m_Mobile.Warmode = false; - } - else - { - m_Mobile.DebugSay("I'm not pacified any longer"); - m_Mobile.BardPacified = false; - } - - return true; - } - - public virtual bool DoBardProvoked() - { - if (DateTime.UtcNow >= m_Mobile.BardEndTime && - (m_Mobile.BardMaster?.Deleted != false || - m_Mobile.BardMaster.Map != m_Mobile.Map || m_Mobile.GetDistanceToSqrt(m_Mobile.BardMaster) > - m_Mobile.RangePerception)) - { - m_Mobile.DebugSay("I have lost my provoker"); - m_Mobile.BardProvoked = false; - m_Mobile.BardMaster = null; - m_Mobile.BardTarget = null; - - m_Mobile.Combatant = null; - m_Mobile.Warmode = false; - } - else - { - if (m_Mobile.BardTarget?.Deleted != false || m_Mobile.BardTarget.Map != m_Mobile.Map || - m_Mobile.GetDistanceToSqrt(m_Mobile.BardTarget) > m_Mobile.RangePerception) - { - m_Mobile.DebugSay("I have lost my provoke target"); - m_Mobile.BardProvoked = false; - m_Mobile.BardMaster = null; - m_Mobile.BardTarget = null; - - m_Mobile.Combatant = null; - m_Mobile.Warmode = false; - } - else - { - m_Mobile.Combatant = m_Mobile.BardTarget; - m_Action = ActionType.Combat; - - m_Mobile.OnThink(); - Think(); - } - } - - return true; - } - - public virtual void WalkRandom(int iChanceToNotMove, int iChanceToDir, int iSteps) - { - if (m_Mobile.Deleted || m_Mobile.DisallowAllMoves) - return; - - for (int i = 0; i < iSteps; i++) - if (Utility.Random(8 * iChanceToNotMove) <= 8) - { - int iRndMove = Utility.Random(0, 8 + 9 * iChanceToDir); - - switch (iRndMove) - { - case 0: - DoMove(Direction.Up); - break; - case 1: - DoMove(Direction.North); - break; - case 2: - DoMove(Direction.Left); - break; - case 3: - DoMove(Direction.West); - break; - case 5: - DoMove(Direction.Down); - break; - case 6: - DoMove(Direction.South); - break; - case 7: - DoMove(Direction.Right); - break; - case 8: - DoMove(Direction.East); - break; - default: - DoMove(m_Mobile.Direction); - break; - } - } - } - - public double TransformMoveDelay(double delay) - { - bool isPassive = delay == m_Mobile.PassiveSpeed; - bool isControlled = m_Mobile.Controlled || m_Mobile.Summoned; - - if (delay == 0.2) - delay = 0.3; - else if (delay == 0.25) - delay = 0.45; - else if (delay == 0.3) - delay = 0.6; - else if (delay == 0.4) - delay = 0.9; - else if (delay == 0.5) - delay = 1.05; - else if (delay == 0.6) - delay = 1.2; - else if (delay == 0.8) - delay = 1.5; - - if (isPassive) - delay += 0.2; - - if (!isControlled) - { - delay += 0.1; - } - else if (m_Mobile.Controlled) - { - if (m_Mobile.ControlOrder == OrderType.Follow && m_Mobile.ControlTarget == m_Mobile.ControlMaster) - delay *= 0.5; - - delay -= 0.075; - } - - if (m_Mobile.ReduceSpeedWithDamage || m_Mobile.IsSubdued) - { - double offset = (double)m_Mobile.Hits / m_Mobile.HitsMax; - - if (offset < 0.0) - offset = 0.0; - else if (offset > 1.0) - offset = 1.0; - - offset = 1.0 - offset; - - delay += offset * 0.8; - } - - if (delay < 0.0) - delay = 0.0; - - if (double.IsNaN(delay)) - { - using (StreamWriter op = new StreamWriter("nan_transform.txt", true)) - { - op.WriteLine( - $"NaN in TransformMoveDelay: {DateTime.UtcNow}, {GetType()}, {m_Mobile?.GetType()}, {m_Mobile.HitsMax}"); - } - - return 1.0; - } - - return delay; - } - - public virtual bool CheckMove() => Core.TickCount - NextMove >= 0; - - public virtual bool DoMove(Direction d) => DoMove(d, false); - - public virtual bool DoMove(Direction d, bool badStateOk) - { - MoveResult res = DoMoveImpl(d); - - return res == MoveResult.Success || res == MoveResult.SuccessAutoTurn || - (badStateOk && res == MoveResult.BadState); - } - - public virtual MoveResult DoMoveImpl(Direction d) - { - if (m_Mobile.Deleted || m_Mobile.Frozen || m_Mobile.Paralyzed || - m_Mobile.Spell?.IsCasting == true || m_Mobile.DisallowAllMoves) - return MoveResult.BadState; - if (!CheckMove()) - return MoveResult.BadState; - - // This makes them always move one step, never any direction changes - m_Mobile.Direction = d; - - int delay = (int)(TransformMoveDelay(m_Mobile.CurrentSpeed) * 1000); - - NextMove += delay; - - if (Core.TickCount - NextMove > 0) - NextMove = Core.TickCount; - - m_Mobile.Pushing = false; - - MoveImpl.IgnoreMovableImpassables = m_Mobile.CanMoveOverObstacles && !m_Mobile.CanDestroyObstacles; - - if ((m_Mobile.Direction & Direction.Mask) != (d & Direction.Mask)) - { - bool v = m_Mobile.Move(d); - - MoveImpl.IgnoreMovableImpassables = false; - return v ? MoveResult.Success : MoveResult.Blocked; - } - - if (!m_Mobile.Move(d)) - { - bool wasPushing = m_Mobile.Pushing; - - bool blocked = true; - - bool canOpenDoors = m_Mobile.CanOpenDoors; - bool canDestroyObstacles = m_Mobile.CanDestroyObstacles; - - if (canOpenDoors || canDestroyObstacles) - { - m_Mobile.DebugSay("My movement was blocked, I will try to clear some obstacles."); - - Map map = m_Mobile.Map; - - if (map != null) - { - int x = m_Mobile.X, y = m_Mobile.Y; - Movement.Movement.Offset(d, ref x, ref y); - - int destroyables = 0; - - IPooledEnumerable eable = map.GetItemsInRange(new Point3D(x, y, m_Mobile.Location.Z), 1); - - foreach (Item item in eable) - if (canOpenDoors && item is BaseDoor door && door.Z + door.ItemData.Height > m_Mobile.Z && - m_Mobile.Z + 16 > door.Z) - { - if (door.X != x || door.Y != y) - continue; - - if (!door.Locked || !door.UseLocks()) - m_Obstacles.Enqueue(door); - - if (!canDestroyObstacles) - break; - } - else if (canDestroyObstacles && item.Movable && item.ItemData.Impassable && - item.Z + item.ItemData.Height > m_Mobile.Z && m_Mobile.Z + 16 > item.Z) - { - if (!m_Mobile.InRange(item.GetWorldLocation(), 1)) - continue; - - m_Obstacles.Enqueue(item); - ++destroyables; - } - - eable.Free(); - - if (destroyables > 0) - Effects.PlaySound(new Point3D(x, y, m_Mobile.Z), m_Mobile.Map, 0x3B3); - - if (m_Obstacles.Count > 0) - blocked = false; // retry movement - - while (m_Obstacles.Count > 0) - { - Item item = m_Obstacles.Dequeue(); - - if (item is BaseDoor door) - { - m_Mobile.DebugSay( - "Little do they expect, I've learned how to open doors. Didn't they read the script??"); - m_Mobile.DebugSay("*twist*"); - - door.Use(m_Mobile); - } - else - { - m_Mobile.DebugSay("Ugabooga. I'm so big and tough I can destroy it: {0}", - item.GetType().Name); - - if (item is Container cont) + if (WalkMobileRange(m_Mobile.ControlMaster, 1, bRun, 0, 1)) { - for (int i = 0; i < cont.Items.Count; ++i) - { - Item check = cont.Items[i]; + if (m_Mobile.Combatant?.Deleted == false && m_Mobile.Combatant.Alive && + !m_Mobile.Combatant.IsDeadBondedPet) + { + m_Mobile.Warmode = true; + m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant); + } + else + { + m_Mobile.Warmode = false; + } + } + } - if (check.Movable && check.ItemData.Impassable && - cont.Z + check.ItemData.Height > m_Mobile.Z) - m_Obstacles.Enqueue(check); - } + return true; + } - cont.Destroy(); + public virtual bool DoOrderDrop() + { + if (m_Mobile.IsDeadPet || !m_Mobile.CanDrop) + return true; + + m_Mobile.DebugSay("I drop my stuff for my master"); + + var pack = m_Mobile.Backpack; + + if (pack != null) + { + var list = pack.Items; + + for (var i = list.Count - 1; i >= 0; --i) + if (i < list.Count) + list[i].MoveToWorld(m_Mobile.Location, m_Mobile.Map); + } + + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.None; + + return true; + } + + public virtual bool CheckHerding() + { + var target = m_Mobile.TargetLocation; + + if (target == null) + return false; // Creature is not being herded + + var distance = m_Mobile.GetDistanceToSqrt(target); + + if (!(distance < 1 || distance > 15)) + { + DoMove(m_Mobile.GetDirectionTo(target)); + return true; + } + + if (distance < 1 && target.X == 1076 && target.Y == 450 && m_Mobile is HordeMinionFamiliar) + if (m_Mobile.ControlMaster is PlayerMobile pm) + { + var qs = pm.Quest; + + if (qs is DarkTidesQuest) + { + QuestObjective obj = qs.FindObjective(); + + if (obj?.Completed == false) + { + m_Mobile.AddToBackpack(new ScrollOfAbraxus()); + obj.Complete(); + } + } + } + + m_Mobile.TargetLocation = null; + return false; // At the target or too far away + } + + public virtual bool DoOrderFollow() + { + if (CheckHerding()) + { + m_Mobile.DebugSay("Praise the shepherd!"); + } + else if (m_Mobile.ControlTarget?.Deleted == false && m_Mobile.ControlTarget != m_Mobile) + { + var iCurrDist = (int)m_Mobile.GetDistanceToSqrt(m_Mobile.ControlTarget); + + if (iCurrDist > m_Mobile.RangePerception) + { + m_Mobile.DebugSay("I have lost the one to follow. I stay here"); + + if (m_Mobile.Combatant?.Deleted == false && m_Mobile.Combatant.Alive && + !m_Mobile.Combatant.IsDeadBondedPet) + { + m_Mobile.Warmode = true; + m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant); + } + else + { + m_Mobile.Warmode = false; + } } else { - item.Delete(); + m_Mobile.DebugSay("My master told me to follow: {0}", m_Mobile.ControlTarget.Name); + + // Not exactly OSI style, but better than nothing. + var bRun = iCurrDist > 5; + + if (WalkMobileRange(m_Mobile.ControlTarget, 1, bRun, 0, 1)) + { + if (m_Mobile.Combatant?.Deleted == false && m_Mobile.Combatant.Alive && + !m_Mobile.Combatant.IsDeadBondedPet) + { + m_Mobile.Warmode = true; + m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant); + } + else + { + m_Mobile.Warmode = false; + if (Core.AOS) + m_Mobile.CurrentSpeed = 0.1; + } + } } - } - } - - if (!blocked) - blocked = !m_Mobile.Move(d); - } - } - - if (blocked) - { - int offset = Utility.RandomDouble() >= 0.6 ? 1 : -1; - - for (int i = 0; i < 2; ++i) - { - m_Mobile.TurnInternal(offset); - - if (m_Mobile.Move(m_Mobile.Direction)) - { - MoveImpl.IgnoreMovableImpassables = false; - return MoveResult.SuccessAutoTurn; - } - } - - MoveImpl.IgnoreMovableImpassables = false; - return wasPushing ? MoveResult.BadState : MoveResult.Blocked; - } - - MoveImpl.IgnoreMovableImpassables = false; - return MoveResult.Success; - } - - MoveImpl.IgnoreMovableImpassables = false; - return MoveResult.Success; - } - - public virtual void WalkRandomInHome(int iChanceToNotMove, int iChanceToDir, int iSteps) - { - if (m_Mobile.Deleted || m_Mobile.DisallowAllMoves) - return; - - if (m_Mobile.Home == Point3D.Zero) - { - if (m_Mobile.Spawner is RegionSpawner rs) - { - Region region = rs.SpawnRegion; - - if (m_Mobile.Region.AcceptsSpawnsFrom(region)) - { - m_Mobile.WalkRegion = region; - WalkRandom(iChanceToNotMove, iChanceToDir, iSteps); - m_Mobile.WalkRegion = null; - } - else - { - if (region.GoLocation != Point3D.Zero && Utility.Random(10) > 5) - DoMove(m_Mobile.GetDirectionTo(region.GoLocation)); - else - WalkRandom(iChanceToNotMove, iChanceToDir, 1); - } - } - else - { - WalkRandom(iChanceToNotMove, iChanceToDir, iSteps); - } - } - else - { - for (int i = 0; i < iSteps; i++) - if (m_Mobile.RangeHome != 0) - { - int iCurrDist = (int)m_Mobile.GetDistanceToSqrt(m_Mobile.Home); - - if (iCurrDist < m_Mobile.RangeHome * 2 / 3) - { - WalkRandom(iChanceToNotMove, iChanceToDir, 1); - } - else if (iCurrDist > m_Mobile.RangeHome) - { - DoMove(m_Mobile.GetDirectionTo(m_Mobile.Home)); } else { - if (Utility.Random(10) > 5) - DoMove(m_Mobile.GetDirectionTo(m_Mobile.Home)); - else - WalkRandom(iChanceToNotMove, iChanceToDir, 1); + m_Mobile.DebugSay("I have nobody to follow"); + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.None; } - } - else - { - if (m_Mobile.Location != m_Mobile.Home) DoMove(m_Mobile.GetDirectionTo(m_Mobile.Home)); - } - } - } - public virtual bool CheckFlee() - { - if (m_Mobile.CheckFlee()) - { - Mobile combatant = m_Mobile.Combatant; - - if (combatant == null) - { - WalkRandom(1, 2, 1); - } - else - { - Direction d = combatant.GetDirectionTo(m_Mobile); - - d = (Direction)((int)d + Utility.RandomMinMax(-1, +1)); - - m_Mobile.Direction = d; - m_Mobile.Move(d); + return true; } - return true; - } - - return false; - } - - public virtual void OnTeleported() - { - if (m_Path != null) - { - m_Mobile.DebugSay("Teleported; repathing"); - m_Path.ForceRepath(); - } - } - - public virtual bool MoveTo(Mobile m, bool run, int range) - { - if (m_Mobile.Deleted || m_Mobile.DisallowAllMoves || m?.Deleted != false) - return false; - - if (m_Mobile.InRange(m, range)) - { - m_Path = null; - return true; - } - - if (m_Path?.Goal == m) - { - if (m_Path.Follow(run, 1)) + public virtual bool DoOrderFriend() { - m_Path = null; - return true; - } - } - else if (!DoMove(m_Mobile.GetDirectionTo(m), true)) - { - m_Path = new PathFollower(m_Mobile, m); - m_Path.Mover = DoMoveImpl; + var from = m_Mobile.ControlMaster; + var to = m_Mobile.ControlTarget; - if (m_Path.Follow(run, 1)) - { - m_Path = null; - return true; - } - } - else - { - m_Path = null; - return true; - } - - return false; - } - - /* - * Walk at range distance from mobile - * - * iSteps : Number of steps - * bRun : Do we run - * iWantDistMin : The minimum distance we want to be - * iWantDistMax : The maximum distance we want to be - * - */ - public virtual bool WalkMobileRange(Mobile m, int iSteps, bool bRun, int iWantDistMin, int iWantDistMax) - { - if (m_Mobile.Deleted || m_Mobile.DisallowAllMoves) - return false; - - if (m == null) - return false; - - for (int i = 0; i < iSteps; i++) - { - // Get the current distance - int iCurrDist = (int)m_Mobile.GetDistanceToSqrt(m); - - if (iCurrDist < iWantDistMin || iCurrDist > iWantDistMax) - { - bool needCloser = iCurrDist > iWantDistMax; - bool needFurther = !needCloser; - - if (needCloser && m_Path != null && m_Path.Goal == m) - { - if (m_Path.Follow(bRun, 1)) - m_Path = null; - } - else - { - Direction dirTo; - - if (iCurrDist > iWantDistMax) - dirTo = m_Mobile.GetDirectionTo(m); - else - dirTo = m.GetDirectionTo(m_Mobile); - - // Add the run flag - if (bRun) - dirTo = dirTo | Direction.Running; - - if (!DoMove(dirTo, true) && needCloser) + if (from?.Deleted != false || to?.Deleted != false || from == to || !to.Player) { - m_Path = new PathFollower(m_Mobile, m) {Mover = DoMoveImpl}; - - if (m_Path.Follow(bRun, 1)) - m_Path = null; + m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, 502039); // *looks confused* } else { - m_Path = null; + var youngFrom = from is PlayerMobile mobile && mobile.Young; + var youngTo = to is PlayerMobile playerMobile && playerMobile.Young; + + if (youngFrom && !youngTo) + { + from.SendLocalizedMessage(502040); // As a young player, you may not friend pets to older players. + } + else if (!youngFrom && youngTo) + { + from.SendLocalizedMessage(502041); // As an older player, you may not friend pets to young players. + } + else if (from.CanBeBeneficial(to, true)) + { + NetState fromState = from.NetState, toState = to.NetState; + + if (fromState != null && toState != null) + { + if (from.HasTrade) + { + from.SendLocalizedMessage(1070947); // You cannot friend a pet with a trade pending + } + else if (to.HasTrade) + { + to.SendLocalizedMessage(1070947); // You cannot friend a pet with a trade pending + } + else if (m_Mobile.IsPetFriend(to)) + { + from.SendLocalizedMessage(1049691); // That person is already a friend. + } + else if (!m_Mobile.AllowNewPetFriend) + { + from.SendLocalizedMessage( + 1005482 + ); // Your pet does not seem to be interested in making new friends right now. + } + else + { + // ~1_NAME~ will now accept movement commands from ~2_NAME~. + from.SendLocalizedMessage(1049676, $"{m_Mobile.Name}\t{to.Name}"); + + /* ~1_NAME~ has granted you the ability to give orders to their pet ~2_PET_NAME~. + * This creature will now consider you as a friend. + */ + to.SendLocalizedMessage(1043246, $"{from.Name}\t{m_Mobile.Name}"); + + m_Mobile.AddPetFriend(to); + + m_Mobile.ControlTarget = to; + m_Mobile.ControlOrder = OrderType.Follow; + + return true; + } + } + } } - } - } - else - { - return true; - } - } - // Get the current distance - int iNewDist = (int)m_Mobile.GetDistanceToSqrt(m); + m_Mobile.ControlTarget = from; + m_Mobile.ControlOrder = OrderType.Follow; - if (iNewDist >= iWantDistMin && iNewDist <= iWantDistMax) - return true; - - return false; - } - - /* - * Here we check to acquire a target from our surrounding - * - * iRange : The range - * acqType : A type of acquire we want (closest, strongest, etc) - * bPlayerOnly : Don't bother with other creatures or NPCs, want a player - * bFacFriend : Check people in my faction - * bFacFoe : Check people in other factions - * - */ - public virtual bool AcquireFocusMob(int iRange, FightMode acqType, bool bPlayerOnly, bool bFacFriend, bool bFacFoe) - { - if (m_Mobile.Deleted) - return false; - - if (m_Mobile.BardProvoked) - { - if (m_Mobile.BardTarget?.Deleted != false) - { - m_Mobile.FocusMob = null; - return false; + return true; } - m_Mobile.FocusMob = m_Mobile.BardTarget; - return m_Mobile.FocusMob != null; - } - - if (m_Mobile.Controlled) - { - if (m_Mobile.ControlTarget?.Deleted != false || m_Mobile.ControlTarget.Hidden || - !m_Mobile.ControlTarget.Alive || m_Mobile.ControlTarget.IsDeadBondedPet || - !m_Mobile.InRange(m_Mobile.ControlTarget, m_Mobile.RangePerception * 2)) + public virtual bool DoOrderUnfriend() { - if (m_Mobile.ControlTarget != null && m_Mobile.ControlTarget != m_Mobile.ControlMaster) + var from = m_Mobile.ControlMaster; + var to = m_Mobile.ControlTarget; + + if (from?.Deleted != false || to?.Deleted != false || from == to || !to.Player) + { + m_Mobile.PublicOverheadMessage(MessageType.Regular, 0x3B2, 502039); // *looks confused* + } + else if (!m_Mobile.IsPetFriend(to)) + { + from.SendLocalizedMessage(1070953); // That person is not a friend. + } + else + { + // ~1_NAME~ will no longer accept movement commands from ~2_NAME~. + from.SendLocalizedMessage(1070951, $"{m_Mobile.Name}\t{to.Name}"); + + /* ~1_NAME~ has no longer granted you the ability to give orders to their pet ~2_PET_NAME~. + * This creature will no longer consider you as a friend. + */ + to.SendLocalizedMessage(1070952, $"{from.Name}\t{m_Mobile.Name}"); + + m_Mobile.RemovePetFriend(to); + } + + m_Mobile.ControlTarget = from; + m_Mobile.ControlOrder = OrderType.Follow; + + return true; + } + + public virtual bool DoOrderGuard() + { + if (m_Mobile.IsDeadPet) + return true; + + var controlMaster = m_Mobile.ControlMaster; + + if (controlMaster?.Deleted != false) + return true; + + var combatant = m_Mobile.Combatant; + + var aggressors = controlMaster.Aggressors; + + if (aggressors.Count > 0) + { + for (var i = 0; i < aggressors.Count; ++i) + { + var info = aggressors[i]; + var attacker = info.Attacker; + + if (attacker?.Deleted == false && + attacker.GetDistanceToSqrt(m_Mobile) <= m_Mobile.RangePerception) + if (combatant == null || attacker.GetDistanceToSqrt(controlMaster) < + combatant.GetDistanceToSqrt(controlMaster)) + combatant = attacker; + } + + if (combatant != null) + m_Mobile.DebugSay("Crap, my master has been attacked! I will attack one of those bastards!"); + } + + if (combatant?.Deleted == false && combatant != m_Mobile && combatant != m_Mobile.ControlMaster && + combatant.Alive && !combatant.IsDeadBondedPet && m_Mobile.CanSee(combatant) && + m_Mobile.CanBeHarmful(combatant, false) && combatant.Map == m_Mobile.Map) + { + m_Mobile.DebugSay("Guarding from target..."); + + m_Mobile.Combatant = combatant; + m_Mobile.FocusMob = combatant; + Action = ActionType.Combat; + + /* + * We need to call Think() here or spell casting monsters will not use + * spells when guarding because their target is never processed. + */ + Think(); + } + else + { + m_Mobile.DebugSay("Nothing to guard from"); + + m_Mobile.Warmode = false; + if (Core.AOS) + m_Mobile.CurrentSpeed = 0.1; + + WalkMobileRange(controlMaster, 1, false, 0, 1); + } + + return true; + } + + public virtual bool DoOrderAttack() + { + if (m_Mobile.IsDeadPet) + return true; + + if (m_Mobile.ControlTarget?.Deleted != false || m_Mobile.ControlTarget.Map != m_Mobile.Map || + !m_Mobile.ControlTarget.Alive || m_Mobile.ControlTarget.IsDeadBondedPet) + { + m_Mobile.DebugSay( + "I think he might be dead. He's not anywhere around here at least. That's cool. I'm glad he's dead." + ); + + if (Core.AOS) + { + m_Mobile.ControlTarget = m_Mobile.ControlMaster; + m_Mobile.ControlOrder = OrderType.Follow; + } + else + { + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.None; + } + + if (m_Mobile.FightMode == FightMode.Closest || m_Mobile.FightMode == FightMode.Aggressor) + { + Mobile newCombatant = null; + var newScore = 0.0; + + foreach (var aggr in m_Mobile.GetMobilesInRange(m_Mobile.RangePerception)) + { + if (!m_Mobile.CanSee(aggr) || aggr.Combatant != m_Mobile) + continue; + + if (aggr.IsDeadBondedPet || !aggr.Alive) + continue; + + var aggrScore = m_Mobile.GetFightModeRanking(aggr, FightMode.Closest, false); + + if ((newCombatant == null || aggrScore > newScore) && m_Mobile.InLOS(aggr)) + { + newCombatant = aggr; + newScore = aggrScore; + } + } + + if (newCombatant != null) + { + m_Mobile.ControlTarget = newCombatant; + m_Mobile.ControlOrder = OrderType.Attack; + m_Mobile.Combatant = newCombatant; + m_Mobile.DebugSay("But -that- is not dead. Here we go again..."); + Think(); + } + } + } + else + { + m_Mobile.DebugSay("Attacking target..."); + Think(); + } + + return true; + } + + public virtual bool DoOrderPatrol() + { + m_Mobile.DebugSay("This order is not yet coded"); + return true; + } + + public virtual bool DoOrderRelease() + { + m_Mobile.DebugSay("I have been released"); + + m_Mobile.PlaySound(m_Mobile.GetAngerSound()); + + m_Mobile.SetControlMaster(null); + m_Mobile.SummonMaster = null; + + m_Mobile.BondingBegin = DateTime.MinValue; + m_Mobile.OwnerAbandonTime = DateTime.MinValue; + m_Mobile.IsBonded = false; + + var spawner = m_Mobile.Spawner; + + if (spawner != null && spawner.HomeLocation != Point3D.Zero) + { + m_Mobile.Home = spawner.HomeLocation; + m_Mobile.RangeHome = spawner.HomeRange; + } + + if (m_Mobile.DeleteOnRelease || m_Mobile.IsDeadPet) + m_Mobile.Delete(); + + m_Mobile.BeginDeleteTimer(); + m_Mobile.DropBackpack(); + + return true; + } + + public virtual bool DoOrderStay() + { + if (CheckHerding()) + m_Mobile.DebugSay("Praise the shepherd!"); + else + m_Mobile.DebugSay("My master told me to stay"); + + // m_Mobile.Direction = m_Mobile.GetDirectionTo( m_Mobile.ControlMaster ); + + return true; + } + + public virtual bool DoOrderStop() + { + if (m_Mobile.ControlMaster?.Deleted != false) + return true; + + m_Mobile.DebugSay("My master told me to stop."); + + m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.ControlMaster); + m_Mobile.Home = m_Mobile.Location; + m_Mobile.ControlTarget = null; - m_Mobile.FocusMob = null; - return false; + if (Core.ML) + WalkRandomInHome(3, 2, 1); + else + m_Mobile.ControlOrder = OrderType.None; + + return true; } - m_Mobile.FocusMob = m_Mobile.ControlTarget; - return m_Mobile.FocusMob != null; - } - - if (m_Mobile.ConstantFocus != null) - { - m_Mobile.DebugSay("Acquired my constant focus"); - m_Mobile.FocusMob = m_Mobile.ConstantFocus; - return true; - } - - if (acqType == FightMode.None) - { - m_Mobile.FocusMob = null; - return false; - } - - if (acqType == FightMode.Aggressor && m_Mobile.Aggressors.Count == 0 && m_Mobile.Aggressed.Count == 0 && - m_Mobile.FactionAllegiance == null && m_Mobile.EthicAllegiance == null) - { - m_Mobile.FocusMob = null; - return false; - } - - if (Core.TickCount - m_Mobile.NextReacquireTime < 0) - { - m_Mobile.FocusMob = null; - return false; - } - - m_Mobile.NextReacquireTime = Core.TickCount + (int)m_Mobile.ReacquireDelay.TotalMilliseconds; - - m_Mobile.DebugSay("Acquiring..."); - - Map map = m_Mobile.Map; - - if (map != null) - { - Mobile newFocusMob = null; - double val = double.MinValue; - - IPooledEnumerable eable = map.GetMobilesInRange(m_Mobile.Location, iRange); - - foreach (Mobile m in eable) + public virtual bool DoOrderTransfer() { - if (m.Deleted || m.Blessed) - continue; + if (m_Mobile.IsDeadPet) + return true; - // Let's not target ourselves... - if (m == m_Mobile || m is BaseFamiliar) - continue; + var from = m_Mobile.ControlMaster; + var to = m_Mobile.ControlTarget; - // Dead targets are invalid. - if (!m.Alive || m.IsDeadBondedPet) - continue; - - // Staff members cannot be targeted. - if (m.AccessLevel > AccessLevel.Player) - continue; - - // Does it have to be a player? - if (bPlayerOnly && !m.Player) - continue; - - // Can't acquire a target we can't see. - if (!m_Mobile.CanSee(m)) - continue; - - BaseCreature bc = m as BaseCreature; - PlayerMobile pm = m as PlayerMobile; - - if (Core.AOS && bc?.Summoned == true && bc?.Controlled != true) - continue; - - if (m_Mobile.Summoned && m_Mobile.SummonMaster != null) - { - // If this is a summon, it can't target its controller. - if (m == m_Mobile.SummonMaster) - continue; - - // It also must abide by harmful spell rules. - if (!SpellHelper.ValidIndirectTarget(m_Mobile.SummonMaster, m)) - continue; - - // Animated creatures cannot attack players directly. - if (pm != null && m_Mobile.IsAnimatedDead) - continue; - } - - // If we only want faction friends, make sure it's one. - if (bFacFriend && !m_Mobile.IsFriend(m)) - continue; - - // Ignore anyone under EtherealVoyage - if (TransformationSpellHelper.UnderTransformation(m, typeof(EtherealVoyageSpell))) - continue; - - // Ignore players with activated honor - if (pm?.HonorActive == true && m_Mobile.Combatant != m) - continue; - - if (acqType == FightMode.Aggressor || acqType == FightMode.Evil) - { - bool bValid = IsHostile(m); - - if (!bValid) - bValid = m_Mobile.GetFactionAllegiance(m) == BaseCreature.Allegiance.Enemy || - m_Mobile.GetEthicAllegiance(m) == BaseCreature.Allegiance.Enemy; - - if (acqType == FightMode.Evil && !bValid) + if (from?.Deleted == false && to?.Deleted == false && from != to && to.Player) { - if (bc?.Controlled == true && bc?.ControlMaster != null) - bValid = bc.ControlMaster.Karma < 0; - else - bValid = m.Karma < 0; - } + m_Mobile.DebugSay("Begin transfer with {0}", to.Name); - if (!bValid) - continue; - } - else - { - // Same goes for faction enemies. - if (bFacFoe && !m_Mobile.IsEnemy(m)) - continue; + var youngFrom = from is PlayerMobile mobile && mobile.Young; + var youngTo = to is PlayerMobile playerMobile && playerMobile.Young; - // If it's an enemy factioned mobile, make sure we can be harmful to it. - if (bFacFoe && !bFacFriend && !m_Mobile.CanBeHarmful(m, false)) - continue; - } + if (youngFrom && !youngTo) + { + from.SendLocalizedMessage(502051); // As a young player, you may not transfer pets to older players. + } + else if (!youngFrom && youngTo) + { + from.SendLocalizedMessage(502052); // As an older player, you may not transfer pets to young players. + } + else if (!m_Mobile.CanBeControlledBy(to)) + { + var args = $"{to.Name}\t{from.Name}\t "; - double theirVal = m_Mobile.GetFightModeRanking(m, acqType, bPlayerOnly); + from.SendLocalizedMessage( + 1043248, + args + ); // The pet refuses to be transferred because it will not obey ~1_NAME~.~3_BLANK~ + to.SendLocalizedMessage( + 1043249, + args + ); // The pet will not accept you as a master because it does not trust you.~3_BLANK~ + } + else if (!m_Mobile.CanBeControlledBy(from)) + { + var args = $"{to.Name}\t{from.Name}\t "; - if (theirVal > val && m_Mobile.InLOS(m)) - { - newFocusMob = m; - val = theirVal; - } - } - - eable.Free(); - - m_Mobile.FocusMob = newFocusMob; - } - - return m_Mobile.FocusMob != null; - } - - private bool IsHostile(Mobile from) - { - int count = Math.Max(m_Mobile.Aggressors.Count, m_Mobile.Aggressed.Count); - - if (m_Mobile.Combatant == from || from.Combatant == m_Mobile) return true; - - if (count > 0) - for (int a = 0; a < count; ++a) - { - if (a < m_Mobile.Aggressed.Count && m_Mobile.Aggressed[a].Attacker == from) return true; - - if (a < m_Mobile.Aggressors.Count && m_Mobile.Aggressors[a].Defender == from) return true; - } - - return false; - } - - public virtual void DetectHidden() - { - if (m_Mobile.Deleted || m_Mobile.Map == null) - return; - - m_Mobile.DebugSay("Checking for hidden players"); - - double srcSkill = m_Mobile.Skills.DetectHidden.Value; - - if (srcSkill <= 0) - return; - - IPooledEnumerable eable = m_Mobile.GetMobilesInRange(m_Mobile.RangePerception); - - foreach (Mobile trg in eable) - if (trg != m_Mobile && trg.Player && trg.Alive && trg.Hidden && trg.AccessLevel == AccessLevel.Player && - m_Mobile.InLOS(trg)) - { - m_Mobile.DebugSay("Trying to detect {0}", trg.Name); - - double trgHiding = trg.Skills.Hiding.Value / 2.9; - double trgStealth = trg.Skills.Stealth.Value / 1.8; - - double chance = srcSkill / 1.2 - Math.Min(trgHiding, trgStealth); - - if (chance < srcSkill / 10) - chance = srcSkill / 10; - - chance /= 100; - - if (chance > Utility.RandomDouble()) - { - trg.RevealingAction(); - trg.SendLocalizedMessage(500814); // You have been revealed! - } - } - - eable.Free(); - } - - public virtual void Deactivate() - { - if (m_Mobile.PlayerRangeSensitive) - { - m_Timer.Stop(); - - var spawner = m_Mobile.Spawner; - - if (spawner?.ReturnOnDeactivate == true && !m_Mobile.Controlled && ( - spawner.HomeLocation == Point3D.Zero && !m_Mobile.Region.AcceptsSpawnsFrom(spawner.Region) || - !m_Mobile.InRange(spawner.HomeLocation, spawner.HomeRange) - )) - Timer.DelayCall(ReturnToHome); - } - } - - private void ReturnToHome() - { - if (m_Mobile.Spawner != null) - { - Point3D loc = m_Mobile.Spawner.GetSpawnPosition(m_Mobile, m_Mobile.Spawner.Map); - - if (loc != Point3D.Zero) m_Mobile.MoveToWorld(loc, m_Mobile.Spawner.Map); - } - } - - public virtual void Activate() - { - if (!m_Timer.Running) - { - m_Timer.Delay = TimeSpan.Zero; - m_Timer.Start(); - } - } - - /* - * The mobile changed it speed, we must adjust the timer - */ - public virtual void OnCurrentSpeedChanged() - { - m_Timer.Stop(); - m_Timer.Delay = TimeSpan.FromSeconds(Utility.RandomDouble()); - m_Timer.Interval = TimeSpan.FromSeconds(Math.Max(0.0, m_Mobile.CurrentSpeed)); - m_Timer.Start(); - } - - private class InternalEntry : ContextMenuEntry - { - private readonly BaseAI m_AI; - private readonly Mobile m_From; - private readonly BaseCreature m_Mobile; - private readonly OrderType m_Order; - - public InternalEntry(Mobile from, int number, int range, BaseCreature mobile, BaseAI ai, OrderType order) - : base(number, range) - { - m_From = from; - m_Mobile = mobile; - m_AI = ai; - m_Order = order; - - if (mobile.IsDeadPet && (order == OrderType.Guard || order == OrderType.Attack || - order == OrderType.Transfer || order == OrderType.Drop)) - Enabled = false; - } - - public override void OnClick() - { - if (!m_Mobile.Deleted && m_Mobile.Controlled && m_From.CheckAlive()) - { - if (m_Mobile.IsDeadPet && (m_Order == OrderType.Guard || m_Order == OrderType.Attack || - m_Order == OrderType.Transfer || m_Order == OrderType.Drop)) - return; - - bool isOwner = m_From == m_Mobile.ControlMaster; - bool isFriend = !isOwner && m_Mobile.IsPetFriend(m_From); - - if (!isOwner && !isFriend) - return; - if (isFriend && m_Order != OrderType.Follow && m_Order != OrderType.Stay && m_Order != OrderType.Stop) - return; - - switch (m_Order) - { - case OrderType.Follow: - case OrderType.Attack: - case OrderType.Transfer: - case OrderType.Friend: - case OrderType.Unfriend: - { - if (m_Order == OrderType.Transfer && m_From.HasTrade) - m_From.SendLocalizedMessage(1010507); // You cannot transfer a pet with a trade pending - else if (m_Order == OrderType.Friend && m_From.HasTrade) - m_From.SendLocalizedMessage(1070947); // You cannot friend a pet with a trade pending + from.SendLocalizedMessage( + 1043250, + args + ); // The pet refuses to be transferred because it will not obey you sufficiently.~3_BLANK~ + to.SendLocalizedMessage( + 1043251, + args + ); // The pet will not accept you as a master because it does not trust ~2_NAME~.~3_BLANK~ + } + else if (TransferItem.IsInCombat(m_Mobile)) + { + from.SendMessage("You may not transfer a pet that has recently been in combat."); + to.SendMessage("The pet may not be transferred to you because it has recently been in combat."); + } else - m_AI.BeginPickTarget(m_From, m_Order); + { + NetState fromState = from.NetState, toState = to.NetState; - break; - } - case OrderType.Release: - { - if (m_Mobile.Summoned) - goto default; - m_From.SendGump(new ConfirmReleaseGump(m_From, m_Mobile)); - - break; - } - default: - { - if (m_Mobile.CheckControlChance(m_From)) - m_Mobile.ControlOrder = m_Order; - - break; - } - } - } - } - } - - private class TransferItem : Item - { - private readonly BaseCreature m_Creature; - - public TransferItem(BaseCreature creature) - : base(ShrinkTable.Lookup(creature)) - { - m_Creature = creature; - - Movable = false; - - if (!Core.AOS) - Name = creature.Name; - else if (ItemID == ShrinkTable.DefaultItemID || - creature.GetType().IsDefined(typeof(FriendlyNameAttribute), false) || creature is Reptalon) - Name = FriendlyNameAttribute.GetFriendlyNameFor(creature.GetType()).ToString(); - - // (As Per OSI)No name. Normally, set by the ItemID of the Shrink Item unless we either explicitly set it with an Attribute, or, no lookup found - - Hue = creature.Hue & 0x0FFF; - } - - public TransferItem(Serial serial) - : base(serial) - { - } - - public static bool IsInCombat(BaseCreature creature) => creature != null && (creature.Aggressors.Count > 0 || creature.Aggressed.Count > 0); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Delete(); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1041603); // This item represents a pet currently in consideration for trade - list.Add(1041601, m_Creature.Name); // Pet Name: ~1_val~ - - if (m_Creature.ControlMaster != null) - list.Add(1041602, m_Creature.ControlMaster.Name); // Owner: ~1_val~ - } - - public override bool AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted) - { - if (!base.AllowSecureTrade(from, to, newOwner, accepted)) - return false; - - if (Deleted || m_Creature?.Deleted != false || m_Creature.ControlMaster != from || - !from.CheckAlive() || !to.CheckAlive()) - return false; - - if (from.Map != m_Creature.Map || !from.InRange(m_Creature, 14)) - return false; - - bool youngFrom = from is PlayerMobile mobile && mobile.Young; - bool youngTo = to is PlayerMobile playerMobile && playerMobile.Young; - - if (accepted && youngFrom && !youngTo) - { - from.SendLocalizedMessage(502051); // As a young player, you may not transfer pets to older players. - } - else if (accepted && !youngFrom && youngTo) - { - from.SendLocalizedMessage(502052); // As an older player, you may not transfer pets to young players. - } - else if (accepted && !m_Creature.CanBeControlledBy(to)) - { - string args = $"{to.Name}\t{from.Name}\t "; - - from.SendLocalizedMessage(1043248, - args); // The pet refuses to be transferred because it will not obey ~1_NAME~.~3_BLANK~ - to.SendLocalizedMessage(1043249, - args); // The pet will not accept you as a master because it does not trust you.~3_BLANK~ - - return false; - } - else if (accepted && !m_Creature.CanBeControlledBy(from)) - { - string args = $"{to.Name}\t{from.Name}\t "; - - from.SendLocalizedMessage(1043250, - args); // The pet refuses to be transferred because it will not obey you sufficiently.~3_BLANK~ - to.SendLocalizedMessage(1043251, - args); // The pet will not accept you as a master because it does not trust ~2_NAME~.~3_BLANK~ - } - else if (accepted && to.Followers + m_Creature.ControlSlots > to.FollowersMax) - { - to.SendLocalizedMessage(1049607); // You have too many followers to control that creature. - - return false; - } - else if (accepted && IsInCombat(m_Creature)) - { - from.SendMessage("You may not transfer a pet that has recently been in combat."); - to.SendMessage("The pet may not be transferred to you because it has recently been in combat."); - - return false; - } - - return true; - } - - public override void OnSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted) - { - if (Deleted) - return; - - Delete(); - - if (m_Creature?.Deleted != false || m_Creature.ControlMaster != from || !from.CheckAlive() || - !to.CheckAlive()) - return; - - if (from.Map != m_Creature.Map || !from.InRange(m_Creature, 14)) - return; - - if (accepted) - if (m_Creature.SetControlMaster(to)) - { - if (m_Creature.Summoned) - m_Creature.SummonMaster = to; - - m_Creature.ControlTarget = to; - m_Creature.ControlOrder = OrderType.Follow; - - m_Creature.BondingBegin = DateTime.MinValue; - m_Creature.OwnerAbandonTime = DateTime.MinValue; - m_Creature.IsBonded = false; - - m_Creature.PlaySound(m_Creature.GetIdleSound()); - - string args = $"{from.Name}\t{m_Creature.Name}\t{to.Name}"; - - from.SendLocalizedMessage(1043253, args); // You have transferred your pet to ~3_GETTER~. - to.SendLocalizedMessage(1043252, - args); // ~1_NAME~ has transferred the allegiance of ~2_PET_NAME~ to you. - } - } - } - - /* - * The Timer object - */ - private class AITimer : Timer - { - private readonly BaseAI m_Owner; - - public AITimer(BaseAI owner) - : base(TimeSpan.FromSeconds(Utility.RandomDouble()), - TimeSpan.FromSeconds(Math.Max(0.0, owner.m_Mobile.CurrentSpeed))) - { - m_Owner = owner; - - m_Owner.m_NextDetectHidden = Core.TickCount; - - Priority = TimerPriority.FiftyMS; - } - - protected override void OnTick() - { - if (m_Owner.m_Mobile.Deleted) - { - Stop(); - return; - } - - if (m_Owner.m_Mobile.Map == null || m_Owner.m_Mobile.Map == Map.Internal) - { - m_Owner.Deactivate(); - return; - } - - if (m_Owner.m_Mobile.PlayerRangeSensitive) // have to check this in the timer.... - { - Sector sect = m_Owner.m_Mobile.Map.GetSector(m_Owner.m_Mobile); - if (!sect.Active) - { - m_Owner.Deactivate(); - return; - } - } - - m_Owner.m_Mobile.OnThink(); - - if (m_Owner.m_Mobile.Deleted) - { - Stop(); - return; - } - - if (m_Owner.m_Mobile.Map == null || m_Owner.m_Mobile.Map == Map.Internal) - { - m_Owner.Deactivate(); - return; - } - - if (m_Owner.m_Mobile.BardPacified) - { - m_Owner.DoBardPacified(); - } - else if (m_Owner.m_Mobile.BardProvoked) - { - m_Owner.DoBardProvoked(); - } - else - { - if (!m_Owner.m_Mobile.Controlled) - { - if (!m_Owner.Think()) - { - Stop(); - return; + if (fromState != null && toState != null) + { + if (from.HasTrade) + { + from.SendLocalizedMessage(1010507); // You cannot transfer a pet with a trade pending + } + else if (to.HasTrade) + { + to.SendLocalizedMessage(1010507); // You cannot transfer a pet with a trade pending + } + else + { + Container c = fromState.AddTrade(toState); + c.DropItem(new TransferItem(m_Mobile)); + } + } + } } - } - else - { - if (!m_Owner.Obey()) - { - Stop(); - return; - } - } + + m_Mobile.ControlTarget = null; + m_Mobile.ControlOrder = OrderType.Stay; + + return true; } - if (m_Owner.CanDetectHidden && Core.TickCount - m_Owner.m_NextDetectHidden >= 0) + public virtual bool DoBardPacified() { - m_Owner.DetectHidden(); + if (DateTime.UtcNow < m_Mobile.BardEndTime) + { + m_Mobile.DebugSay("I am pacified, I wait"); + m_Mobile.Combatant = null; + m_Mobile.Warmode = false; + } + else + { + m_Mobile.DebugSay("I'm not pacified any longer"); + m_Mobile.BardPacified = false; + } - // Not exactly OSI style, approximation. - int delay = Math.Min(15000 / m_Owner.m_Mobile.Int, 60); - - int min = delay * (9 / 10); // 13s at 1000 int, 33s at 400 int, 54s at <250 int - int max = delay * (10 / 9); // 16s at 1000 int, 41s at 400 int, 66s at <250 int - - m_Owner.m_NextDetectHidden = Core.TickCount + - (int)TimeSpan.FromSeconds(Utility.RandomMinMax(min, max)).TotalMilliseconds; + return true; + } + + public virtual bool DoBardProvoked() + { + if (DateTime.UtcNow >= m_Mobile.BardEndTime && + (m_Mobile.BardMaster?.Deleted != false || + m_Mobile.BardMaster.Map != m_Mobile.Map || m_Mobile.GetDistanceToSqrt(m_Mobile.BardMaster) > + m_Mobile.RangePerception)) + { + m_Mobile.DebugSay("I have lost my provoker"); + m_Mobile.BardProvoked = false; + m_Mobile.BardMaster = null; + m_Mobile.BardTarget = null; + + m_Mobile.Combatant = null; + m_Mobile.Warmode = false; + } + else + { + if (m_Mobile.BardTarget?.Deleted != false || m_Mobile.BardTarget.Map != m_Mobile.Map || + m_Mobile.GetDistanceToSqrt(m_Mobile.BardTarget) > m_Mobile.RangePerception) + { + m_Mobile.DebugSay("I have lost my provoke target"); + m_Mobile.BardProvoked = false; + m_Mobile.BardMaster = null; + m_Mobile.BardTarget = null; + + m_Mobile.Combatant = null; + m_Mobile.Warmode = false; + } + else + { + m_Mobile.Combatant = m_Mobile.BardTarget; + m_Action = ActionType.Combat; + + m_Mobile.OnThink(); + Think(); + } + } + + return true; + } + + public virtual void WalkRandom(int iChanceToNotMove, int iChanceToDir, int iSteps) + { + if (m_Mobile.Deleted || m_Mobile.DisallowAllMoves) + return; + + for (var i = 0; i < iSteps; i++) + if (Utility.Random(8 * iChanceToNotMove) <= 8) + { + var iRndMove = Utility.Random(0, 8 + 9 * iChanceToDir); + + switch (iRndMove) + { + case 0: + DoMove(Direction.Up); + break; + case 1: + DoMove(Direction.North); + break; + case 2: + DoMove(Direction.Left); + break; + case 3: + DoMove(Direction.West); + break; + case 5: + DoMove(Direction.Down); + break; + case 6: + DoMove(Direction.South); + break; + case 7: + DoMove(Direction.Right); + break; + case 8: + DoMove(Direction.East); + break; + default: + DoMove(m_Mobile.Direction); + break; + } + } + } + + public double TransformMoveDelay(double delay) + { + var isPassive = delay == m_Mobile.PassiveSpeed; + var isControlled = m_Mobile.Controlled || m_Mobile.Summoned; + + if (delay == 0.2) + delay = 0.3; + else if (delay == 0.25) + delay = 0.45; + else if (delay == 0.3) + delay = 0.6; + else if (delay == 0.4) + delay = 0.9; + else if (delay == 0.5) + delay = 1.05; + else if (delay == 0.6) + delay = 1.2; + else if (delay == 0.8) + delay = 1.5; + + if (isPassive) + delay += 0.2; + + if (!isControlled) + { + delay += 0.1; + } + else if (m_Mobile.Controlled) + { + if (m_Mobile.ControlOrder == OrderType.Follow && m_Mobile.ControlTarget == m_Mobile.ControlMaster) + delay *= 0.5; + + delay -= 0.075; + } + + if (m_Mobile.ReduceSpeedWithDamage || m_Mobile.IsSubdued) + { + var offset = (double)m_Mobile.Hits / m_Mobile.HitsMax; + + if (offset < 0.0) + offset = 0.0; + else if (offset > 1.0) + offset = 1.0; + + offset = 1.0 - offset; + + delay += offset * 0.8; + } + + if (delay < 0.0) + delay = 0.0; + + if (double.IsNaN(delay)) + { + using (var op = new StreamWriter("nan_transform.txt", true)) + { + op.WriteLine( + $"NaN in TransformMoveDelay: {DateTime.UtcNow}, {GetType()}, {m_Mobile?.GetType()}, {m_Mobile.HitsMax}" + ); + } + + return 1.0; + } + + return delay; + } + + public virtual bool CheckMove() => Core.TickCount - NextMove >= 0; + + public virtual bool DoMove(Direction d) => DoMove(d, false); + + public virtual bool DoMove(Direction d, bool badStateOk) + { + var res = DoMoveImpl(d); + + return res == MoveResult.Success || res == MoveResult.SuccessAutoTurn || + badStateOk && res == MoveResult.BadState; + } + + public virtual MoveResult DoMoveImpl(Direction d) + { + if (m_Mobile.Deleted || m_Mobile.Frozen || m_Mobile.Paralyzed || + m_Mobile.Spell?.IsCasting == true || m_Mobile.DisallowAllMoves) + return MoveResult.BadState; + if (!CheckMove()) + return MoveResult.BadState; + + // This makes them always move one step, never any direction changes + m_Mobile.Direction = d; + + var delay = (int)(TransformMoveDelay(m_Mobile.CurrentSpeed) * 1000); + + NextMove += delay; + + if (Core.TickCount - NextMove > 0) + NextMove = Core.TickCount; + + m_Mobile.Pushing = false; + + MoveImpl.IgnoreMovableImpassables = m_Mobile.CanMoveOverObstacles && !m_Mobile.CanDestroyObstacles; + + if ((m_Mobile.Direction & Direction.Mask) != (d & Direction.Mask)) + { + var v = m_Mobile.Move(d); + + MoveImpl.IgnoreMovableImpassables = false; + return v ? MoveResult.Success : MoveResult.Blocked; + } + + if (!m_Mobile.Move(d)) + { + var wasPushing = m_Mobile.Pushing; + + var blocked = true; + + var canOpenDoors = m_Mobile.CanOpenDoors; + var canDestroyObstacles = m_Mobile.CanDestroyObstacles; + + if (canOpenDoors || canDestroyObstacles) + { + m_Mobile.DebugSay("My movement was blocked, I will try to clear some obstacles."); + + var map = m_Mobile.Map; + + if (map != null) + { + int x = m_Mobile.X, y = m_Mobile.Y; + Movement.Movement.Offset(d, ref x, ref y); + + var destroyables = 0; + + var eable = map.GetItemsInRange(new Point3D(x, y, m_Mobile.Location.Z), 1); + + foreach (var item in eable) + if (canOpenDoors && item is BaseDoor door && door.Z + door.ItemData.Height > m_Mobile.Z && + m_Mobile.Z + 16 > door.Z) + { + if (door.X != x || door.Y != y) + continue; + + if (!door.Locked || !door.UseLocks()) + m_Obstacles.Enqueue(door); + + if (!canDestroyObstacles) + break; + } + else if (canDestroyObstacles && item.Movable && item.ItemData.Impassable && + item.Z + item.ItemData.Height > m_Mobile.Z && m_Mobile.Z + 16 > item.Z) + { + if (!m_Mobile.InRange(item.GetWorldLocation(), 1)) + continue; + + m_Obstacles.Enqueue(item); + ++destroyables; + } + + eable.Free(); + + if (destroyables > 0) + Effects.PlaySound(new Point3D(x, y, m_Mobile.Z), m_Mobile.Map, 0x3B3); + + if (m_Obstacles.Count > 0) + blocked = false; // retry movement + + while (m_Obstacles.Count > 0) + { + var item = m_Obstacles.Dequeue(); + + if (item is BaseDoor door) + { + m_Mobile.DebugSay( + "Little do they expect, I've learned how to open doors. Didn't they read the script??" + ); + m_Mobile.DebugSay("*twist*"); + + door.Use(m_Mobile); + } + else + { + m_Mobile.DebugSay( + "Ugabooga. I'm so big and tough I can destroy it: {0}", + item.GetType().Name + ); + + if (item is Container cont) + { + for (var i = 0; i < cont.Items.Count; ++i) + { + var check = cont.Items[i]; + + if (check.Movable && check.ItemData.Impassable && + cont.Z + check.ItemData.Height > m_Mobile.Z) + m_Obstacles.Enqueue(check); + } + + cont.Destroy(); + } + else + { + item.Delete(); + } + } + } + + if (!blocked) + blocked = !m_Mobile.Move(d); + } + } + + if (blocked) + { + var offset = Utility.RandomDouble() >= 0.6 ? 1 : -1; + + for (var i = 0; i < 2; ++i) + { + m_Mobile.TurnInternal(offset); + + if (m_Mobile.Move(m_Mobile.Direction)) + { + MoveImpl.IgnoreMovableImpassables = false; + return MoveResult.SuccessAutoTurn; + } + } + + MoveImpl.IgnoreMovableImpassables = false; + return wasPushing ? MoveResult.BadState : MoveResult.Blocked; + } + + MoveImpl.IgnoreMovableImpassables = false; + return MoveResult.Success; + } + + MoveImpl.IgnoreMovableImpassables = false; + return MoveResult.Success; + } + + public virtual void WalkRandomInHome(int iChanceToNotMove, int iChanceToDir, int iSteps) + { + if (m_Mobile.Deleted || m_Mobile.DisallowAllMoves) + return; + + if (m_Mobile.Home == Point3D.Zero) + { + if (m_Mobile.Spawner is RegionSpawner rs) + { + Region region = rs.SpawnRegion; + + if (m_Mobile.Region.AcceptsSpawnsFrom(region)) + { + m_Mobile.WalkRegion = region; + WalkRandom(iChanceToNotMove, iChanceToDir, iSteps); + m_Mobile.WalkRegion = null; + } + else + { + if (region.GoLocation != Point3D.Zero && Utility.Random(10) > 5) + DoMove(m_Mobile.GetDirectionTo(region.GoLocation)); + else + WalkRandom(iChanceToNotMove, iChanceToDir, 1); + } + } + else + { + WalkRandom(iChanceToNotMove, iChanceToDir, iSteps); + } + } + else + { + for (var i = 0; i < iSteps; i++) + if (m_Mobile.RangeHome != 0) + { + var iCurrDist = (int)m_Mobile.GetDistanceToSqrt(m_Mobile.Home); + + if (iCurrDist < m_Mobile.RangeHome * 2 / 3) + { + WalkRandom(iChanceToNotMove, iChanceToDir, 1); + } + else if (iCurrDist > m_Mobile.RangeHome) + { + DoMove(m_Mobile.GetDirectionTo(m_Mobile.Home)); + } + else + { + if (Utility.Random(10) > 5) + DoMove(m_Mobile.GetDirectionTo(m_Mobile.Home)); + else + WalkRandom(iChanceToNotMove, iChanceToDir, 1); + } + } + else + { + if (m_Mobile.Location != m_Mobile.Home) DoMove(m_Mobile.GetDirectionTo(m_Mobile.Home)); + } + } + } + + public virtual bool CheckFlee() + { + if (m_Mobile.CheckFlee()) + { + var combatant = m_Mobile.Combatant; + + if (combatant == null) + { + WalkRandom(1, 2, 1); + } + else + { + var d = combatant.GetDirectionTo(m_Mobile); + + d = (Direction)((int)d + Utility.RandomMinMax(-1, +1)); + + m_Mobile.Direction = d; + m_Mobile.Move(d); + } + + return true; + } + + return false; + } + + public virtual void OnTeleported() + { + if (m_Path != null) + { + m_Mobile.DebugSay("Teleported; repathing"); + m_Path.ForceRepath(); + } + } + + public virtual bool MoveTo(Mobile m, bool run, int range) + { + if (m_Mobile.Deleted || m_Mobile.DisallowAllMoves || m?.Deleted != false) + return false; + + if (m_Mobile.InRange(m, range)) + { + m_Path = null; + return true; + } + + if (m_Path?.Goal == m) + { + if (m_Path.Follow(run, 1)) + { + m_Path = null; + return true; + } + } + else if (!DoMove(m_Mobile.GetDirectionTo(m), true)) + { + m_Path = new PathFollower(m_Mobile, m); + m_Path.Mover = DoMoveImpl; + + if (m_Path.Follow(run, 1)) + { + m_Path = null; + return true; + } + } + else + { + m_Path = null; + return true; + } + + return false; + } + + /* + * Walk at range distance from mobile + * + * iSteps : Number of steps + * bRun : Do we run + * iWantDistMin : The minimum distance we want to be + * iWantDistMax : The maximum distance we want to be + * + */ + public virtual bool WalkMobileRange(Mobile m, int iSteps, bool bRun, int iWantDistMin, int iWantDistMax) + { + if (m_Mobile.Deleted || m_Mobile.DisallowAllMoves) + return false; + + if (m == null) + return false; + + for (var i = 0; i < iSteps; i++) + { + // Get the current distance + var iCurrDist = (int)m_Mobile.GetDistanceToSqrt(m); + + if (iCurrDist < iWantDistMin || iCurrDist > iWantDistMax) + { + var needCloser = iCurrDist > iWantDistMax; + var needFurther = !needCloser; + + if (needCloser && m_Path != null && m_Path.Goal == m) + { + if (m_Path.Follow(bRun, 1)) + m_Path = null; + } + else + { + Direction dirTo; + + if (iCurrDist > iWantDistMax) + dirTo = m_Mobile.GetDirectionTo(m); + else + dirTo = m.GetDirectionTo(m_Mobile); + + // Add the run flag + if (bRun) + dirTo = dirTo | Direction.Running; + + if (!DoMove(dirTo, true) && needCloser) + { + m_Path = new PathFollower(m_Mobile, m) { Mover = DoMoveImpl }; + + if (m_Path.Follow(bRun, 1)) + m_Path = null; + } + else + { + m_Path = null; + } + } + } + else + { + return true; + } + } + + // Get the current distance + var iNewDist = (int)m_Mobile.GetDistanceToSqrt(m); + + if (iNewDist >= iWantDistMin && iNewDist <= iWantDistMax) + return true; + + return false; + } + + /* + * Here we check to acquire a target from our surrounding + * + * iRange : The range + * acqType : A type of acquire we want (closest, strongest, etc) + * bPlayerOnly : Don't bother with other creatures or NPCs, want a player + * bFacFriend : Check people in my faction + * bFacFoe : Check people in other factions + * + */ + public virtual bool AcquireFocusMob(int iRange, FightMode acqType, bool bPlayerOnly, bool bFacFriend, bool bFacFoe) + { + if (m_Mobile.Deleted) + return false; + + if (m_Mobile.BardProvoked) + { + if (m_Mobile.BardTarget?.Deleted != false) + { + m_Mobile.FocusMob = null; + return false; + } + + m_Mobile.FocusMob = m_Mobile.BardTarget; + return m_Mobile.FocusMob != null; + } + + if (m_Mobile.Controlled) + { + if (m_Mobile.ControlTarget?.Deleted != false || m_Mobile.ControlTarget.Hidden || + !m_Mobile.ControlTarget.Alive || m_Mobile.ControlTarget.IsDeadBondedPet || + !m_Mobile.InRange(m_Mobile.ControlTarget, m_Mobile.RangePerception * 2)) + { + if (m_Mobile.ControlTarget != null && m_Mobile.ControlTarget != m_Mobile.ControlMaster) + m_Mobile.ControlTarget = null; + + m_Mobile.FocusMob = null; + return false; + } + + m_Mobile.FocusMob = m_Mobile.ControlTarget; + return m_Mobile.FocusMob != null; + } + + if (m_Mobile.ConstantFocus != null) + { + m_Mobile.DebugSay("Acquired my constant focus"); + m_Mobile.FocusMob = m_Mobile.ConstantFocus; + return true; + } + + if (acqType == FightMode.None) + { + m_Mobile.FocusMob = null; + return false; + } + + if (acqType == FightMode.Aggressor && m_Mobile.Aggressors.Count == 0 && m_Mobile.Aggressed.Count == 0 && + m_Mobile.FactionAllegiance == null && m_Mobile.EthicAllegiance == null) + { + m_Mobile.FocusMob = null; + return false; + } + + if (Core.TickCount - m_Mobile.NextReacquireTime < 0) + { + m_Mobile.FocusMob = null; + return false; + } + + m_Mobile.NextReacquireTime = Core.TickCount + (int)m_Mobile.ReacquireDelay.TotalMilliseconds; + + m_Mobile.DebugSay("Acquiring..."); + + var map = m_Mobile.Map; + + if (map != null) + { + Mobile newFocusMob = null; + var val = double.MinValue; + + var eable = map.GetMobilesInRange(m_Mobile.Location, iRange); + + foreach (var m in eable) + { + if (m.Deleted || m.Blessed) + continue; + + // Let's not target ourselves... + if (m == m_Mobile || m is BaseFamiliar) + continue; + + // Dead targets are invalid. + if (!m.Alive || m.IsDeadBondedPet) + continue; + + // Staff members cannot be targeted. + if (m.AccessLevel > AccessLevel.Player) + continue; + + // Does it have to be a player? + if (bPlayerOnly && !m.Player) + continue; + + // Can't acquire a target we can't see. + if (!m_Mobile.CanSee(m)) + continue; + + var bc = m as BaseCreature; + var pm = m as PlayerMobile; + + if (Core.AOS && bc?.Summoned == true && bc?.Controlled != true) + continue; + + if (m_Mobile.Summoned && m_Mobile.SummonMaster != null) + { + // If this is a summon, it can't target its controller. + if (m == m_Mobile.SummonMaster) + continue; + + // It also must abide by harmful spell rules. + if (!SpellHelper.ValidIndirectTarget(m_Mobile.SummonMaster, m)) + continue; + + // Animated creatures cannot attack players directly. + if (pm != null && m_Mobile.IsAnimatedDead) + continue; + } + + // If we only want faction friends, make sure it's one. + if (bFacFriend && !m_Mobile.IsFriend(m)) + continue; + + // Ignore anyone under EtherealVoyage + if (TransformationSpellHelper.UnderTransformation(m, typeof(EtherealVoyageSpell))) + continue; + + // Ignore players with activated honor + if (pm?.HonorActive == true && m_Mobile.Combatant != m) + continue; + + if (acqType == FightMode.Aggressor || acqType == FightMode.Evil) + { + var bValid = IsHostile(m); + + if (!bValid) + bValid = m_Mobile.GetFactionAllegiance(m) == BaseCreature.Allegiance.Enemy || + m_Mobile.GetEthicAllegiance(m) == BaseCreature.Allegiance.Enemy; + + if (acqType == FightMode.Evil && !bValid) + { + if (bc?.Controlled == true && bc?.ControlMaster != null) + bValid = bc.ControlMaster.Karma < 0; + else + bValid = m.Karma < 0; + } + + if (!bValid) + continue; + } + else + { + // Same goes for faction enemies. + if (bFacFoe && !m_Mobile.IsEnemy(m)) + continue; + + // If it's an enemy factioned mobile, make sure we can be harmful to it. + if (bFacFoe && !bFacFriend && !m_Mobile.CanBeHarmful(m, false)) + continue; + } + + var theirVal = m_Mobile.GetFightModeRanking(m, acqType, bPlayerOnly); + + if (theirVal > val && m_Mobile.InLOS(m)) + { + newFocusMob = m; + val = theirVal; + } + } + + eable.Free(); + + m_Mobile.FocusMob = newFocusMob; + } + + return m_Mobile.FocusMob != null; + } + + private bool IsHostile(Mobile from) + { + var count = Math.Max(m_Mobile.Aggressors.Count, m_Mobile.Aggressed.Count); + + if (m_Mobile.Combatant == from || from.Combatant == m_Mobile) return true; + + if (count > 0) + for (var a = 0; a < count; ++a) + { + if (a < m_Mobile.Aggressed.Count && m_Mobile.Aggressed[a].Attacker == from) return true; + + if (a < m_Mobile.Aggressors.Count && m_Mobile.Aggressors[a].Defender == from) return true; + } + + return false; + } + + public virtual void DetectHidden() + { + if (m_Mobile.Deleted || m_Mobile.Map == null) + return; + + m_Mobile.DebugSay("Checking for hidden players"); + + var srcSkill = m_Mobile.Skills.DetectHidden.Value; + + if (srcSkill <= 0) + return; + + var eable = m_Mobile.GetMobilesInRange(m_Mobile.RangePerception); + + foreach (var trg in eable) + if (trg != m_Mobile && trg.Player && trg.Alive && trg.Hidden && trg.AccessLevel == AccessLevel.Player && + m_Mobile.InLOS(trg)) + { + m_Mobile.DebugSay("Trying to detect {0}", trg.Name); + + var trgHiding = trg.Skills.Hiding.Value / 2.9; + var trgStealth = trg.Skills.Stealth.Value / 1.8; + + var chance = srcSkill / 1.2 - Math.Min(trgHiding, trgStealth); + + if (chance < srcSkill / 10) + chance = srcSkill / 10; + + chance /= 100; + + if (chance > Utility.RandomDouble()) + { + trg.RevealingAction(); + trg.SendLocalizedMessage(500814); // You have been revealed! + } + } + + eable.Free(); + } + + public virtual void Deactivate() + { + if (m_Mobile.PlayerRangeSensitive) + { + m_Timer.Stop(); + + var spawner = m_Mobile.Spawner; + + if (spawner?.ReturnOnDeactivate == true && !m_Mobile.Controlled && ( + spawner.HomeLocation == Point3D.Zero && !m_Mobile.Region.AcceptsSpawnsFrom(spawner.Region) || + !m_Mobile.InRange(spawner.HomeLocation, spawner.HomeRange) + )) + Timer.DelayCall(ReturnToHome); + } + } + + private void ReturnToHome() + { + if (m_Mobile.Spawner != null) + { + var loc = m_Mobile.Spawner.GetSpawnPosition(m_Mobile, m_Mobile.Spawner.Map); + + if (loc != Point3D.Zero) m_Mobile.MoveToWorld(loc, m_Mobile.Spawner.Map); + } + } + + public virtual void Activate() + { + if (!m_Timer.Running) + { + m_Timer.Delay = TimeSpan.Zero; + m_Timer.Start(); + } + } + + /* + * The mobile changed it speed, we must adjust the timer + */ + public virtual void OnCurrentSpeedChanged() + { + m_Timer.Stop(); + m_Timer.Delay = TimeSpan.FromSeconds(Utility.RandomDouble()); + m_Timer.Interval = TimeSpan.FromSeconds(Math.Max(0.0, m_Mobile.CurrentSpeed)); + m_Timer.Start(); + } + + private class InternalEntry : ContextMenuEntry + { + private readonly BaseAI m_AI; + private readonly Mobile m_From; + private readonly BaseCreature m_Mobile; + private readonly OrderType m_Order; + + public InternalEntry(Mobile from, int number, int range, BaseCreature mobile, BaseAI ai, OrderType order) + : base(number, range) + { + m_From = from; + m_Mobile = mobile; + m_AI = ai; + m_Order = order; + + if (mobile.IsDeadPet && (order == OrderType.Guard || order == OrderType.Attack || + order == OrderType.Transfer || order == OrderType.Drop)) + Enabled = false; + } + + public override void OnClick() + { + if (!m_Mobile.Deleted && m_Mobile.Controlled && m_From.CheckAlive()) + { + if (m_Mobile.IsDeadPet && (m_Order == OrderType.Guard || m_Order == OrderType.Attack || + m_Order == OrderType.Transfer || m_Order == OrderType.Drop)) + return; + + var isOwner = m_From == m_Mobile.ControlMaster; + var isFriend = !isOwner && m_Mobile.IsPetFriend(m_From); + + if (!isOwner && !isFriend) + return; + if (isFriend && m_Order != OrderType.Follow && m_Order != OrderType.Stay && m_Order != OrderType.Stop) + return; + + switch (m_Order) + { + case OrderType.Follow: + case OrderType.Attack: + case OrderType.Transfer: + case OrderType.Friend: + case OrderType.Unfriend: + { + if (m_Order == OrderType.Transfer && m_From.HasTrade) + m_From.SendLocalizedMessage(1010507); // You cannot transfer a pet with a trade pending + else if (m_Order == OrderType.Friend && m_From.HasTrade) + m_From.SendLocalizedMessage(1070947); // You cannot friend a pet with a trade pending + else + m_AI.BeginPickTarget(m_From, m_Order); + + break; + } + case OrderType.Release: + { + if (m_Mobile.Summoned) + goto default; + m_From.SendGump(new ConfirmReleaseGump(m_From, m_Mobile)); + + break; + } + default: + { + if (m_Mobile.CheckControlChance(m_From)) + m_Mobile.ControlOrder = m_Order; + + break; + } + } + } + } + } + + private class TransferItem : Item + { + private readonly BaseCreature m_Creature; + + public TransferItem(BaseCreature creature) + : base(ShrinkTable.Lookup(creature)) + { + m_Creature = creature; + + Movable = false; + + if (!Core.AOS) + Name = creature.Name; + else if (ItemID == ShrinkTable.DefaultItemID || + creature.GetType().IsDefined(typeof(FriendlyNameAttribute), false) || creature is Reptalon) + Name = FriendlyNameAttribute.GetFriendlyNameFor(creature.GetType()).ToString(); + + // (As Per OSI)No name. Normally, set by the ItemID of the Shrink Item unless we either explicitly set it with an Attribute, or, no lookup found + + Hue = creature.Hue & 0x0FFF; + } + + public TransferItem(Serial serial) + : base(serial) + { + } + + public static bool IsInCombat(BaseCreature creature) => + creature != null && (creature.Aggressors.Count > 0 || creature.Aggressed.Count > 0); + + 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(); + + Delete(); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1041603); // This item represents a pet currently in consideration for trade + list.Add(1041601, m_Creature.Name); // Pet Name: ~1_val~ + + if (m_Creature.ControlMaster != null) + list.Add(1041602, m_Creature.ControlMaster.Name); // Owner: ~1_val~ + } + + public override bool AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted) + { + if (!base.AllowSecureTrade(from, to, newOwner, accepted)) + return false; + + if (Deleted || m_Creature?.Deleted != false || m_Creature.ControlMaster != from || + !from.CheckAlive() || !to.CheckAlive()) + return false; + + if (from.Map != m_Creature.Map || !from.InRange(m_Creature, 14)) + return false; + + var youngFrom = from is PlayerMobile mobile && mobile.Young; + var youngTo = to is PlayerMobile playerMobile && playerMobile.Young; + + if (accepted && youngFrom && !youngTo) + { + from.SendLocalizedMessage(502051); // As a young player, you may not transfer pets to older players. + } + else if (accepted && !youngFrom && youngTo) + { + from.SendLocalizedMessage(502052); // As an older player, you may not transfer pets to young players. + } + else if (accepted && !m_Creature.CanBeControlledBy(to)) + { + var args = $"{to.Name}\t{from.Name}\t "; + + from.SendLocalizedMessage( + 1043248, + args + ); // The pet refuses to be transferred because it will not obey ~1_NAME~.~3_BLANK~ + to.SendLocalizedMessage( + 1043249, + args + ); // The pet will not accept you as a master because it does not trust you.~3_BLANK~ + + return false; + } + else if (accepted && !m_Creature.CanBeControlledBy(from)) + { + var args = $"{to.Name}\t{from.Name}\t "; + + from.SendLocalizedMessage( + 1043250, + args + ); // The pet refuses to be transferred because it will not obey you sufficiently.~3_BLANK~ + to.SendLocalizedMessage( + 1043251, + args + ); // The pet will not accept you as a master because it does not trust ~2_NAME~.~3_BLANK~ + } + else if (accepted && to.Followers + m_Creature.ControlSlots > to.FollowersMax) + { + to.SendLocalizedMessage(1049607); // You have too many followers to control that creature. + + return false; + } + else if (accepted && IsInCombat(m_Creature)) + { + from.SendMessage("You may not transfer a pet that has recently been in combat."); + to.SendMessage("The pet may not be transferred to you because it has recently been in combat."); + + return false; + } + + return true; + } + + public override void OnSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted) + { + if (Deleted) + return; + + Delete(); + + if (m_Creature?.Deleted != false || m_Creature.ControlMaster != from || !from.CheckAlive() || + !to.CheckAlive()) + return; + + if (from.Map != m_Creature.Map || !from.InRange(m_Creature, 14)) + return; + + if (accepted) + if (m_Creature.SetControlMaster(to)) + { + if (m_Creature.Summoned) + m_Creature.SummonMaster = to; + + m_Creature.ControlTarget = to; + m_Creature.ControlOrder = OrderType.Follow; + + m_Creature.BondingBegin = DateTime.MinValue; + m_Creature.OwnerAbandonTime = DateTime.MinValue; + m_Creature.IsBonded = false; + + m_Creature.PlaySound(m_Creature.GetIdleSound()); + + var args = $"{from.Name}\t{m_Creature.Name}\t{to.Name}"; + + from.SendLocalizedMessage(1043253, args); // You have transferred your pet to ~3_GETTER~. + to.SendLocalizedMessage( + 1043252, + args + ); // ~1_NAME~ has transferred the allegiance of ~2_PET_NAME~ to you. + } + } + } + + /* + * The Timer object + */ + private class AITimer : Timer + { + private readonly BaseAI m_Owner; + + public AITimer(BaseAI owner) + : base( + TimeSpan.FromSeconds(Utility.RandomDouble()), + TimeSpan.FromSeconds(Math.Max(0.0, owner.m_Mobile.CurrentSpeed)) + ) + { + m_Owner = owner; + + m_Owner.m_NextDetectHidden = Core.TickCount; + + Priority = TimerPriority.FiftyMS; + } + + protected override void OnTick() + { + if (m_Owner.m_Mobile.Deleted) + { + Stop(); + return; + } + + if (m_Owner.m_Mobile.Map == null || m_Owner.m_Mobile.Map == Map.Internal) + { + m_Owner.Deactivate(); + return; + } + + if (m_Owner.m_Mobile.PlayerRangeSensitive) // have to check this in the timer.... + { + var sect = m_Owner.m_Mobile.Map.GetSector(m_Owner.m_Mobile); + if (!sect.Active) + { + m_Owner.Deactivate(); + return; + } + } + + m_Owner.m_Mobile.OnThink(); + + if (m_Owner.m_Mobile.Deleted) + { + Stop(); + return; + } + + if (m_Owner.m_Mobile.Map == null || m_Owner.m_Mobile.Map == Map.Internal) + { + m_Owner.Deactivate(); + return; + } + + if (m_Owner.m_Mobile.BardPacified) + { + m_Owner.DoBardPacified(); + } + else if (m_Owner.m_Mobile.BardProvoked) + { + m_Owner.DoBardProvoked(); + } + else + { + if (!m_Owner.m_Mobile.Controlled) + { + if (!m_Owner.Think()) + { + Stop(); + return; + } + } + else + { + if (!m_Owner.Obey()) + { + Stop(); + return; + } + } + } + + if (m_Owner.CanDetectHidden && Core.TickCount - m_Owner.m_NextDetectHidden >= 0) + { + m_Owner.DetectHidden(); + + // Not exactly OSI style, approximation. + var delay = Math.Min(15000 / m_Owner.m_Mobile.Int, 60); + + var min = delay * (9 / 10); // 13s at 1000 int, 33s at 400 int, 54s at <250 int + var max = delay * (10 / 9); // 16s at 1000 int, 41s at 400 int, 66s at <250 int + + m_Owner.m_NextDetectHidden = Core.TickCount + + (int)TimeSpan.FromSeconds(Utility.RandomMinMax(min, max)).TotalMilliseconds; + } + } } - } } - } } diff --git a/Projects/UOContent/Mobiles/AI/BerserkAI.cs b/Projects/UOContent/Mobiles/AI/BerserkAI.cs index 385c1cfc5..f89a6ad90 100644 --- a/Projects/UOContent/Mobiles/AI/BerserkAI.cs +++ b/Projects/UOContent/Mobiles/AI/BerserkAI.cs @@ -1,82 +1,82 @@ namespace Server.Mobiles { - public class BerserkAI : BaseAI - { - public BerserkAI(BaseCreature m) : base(m) + public class BerserkAI : BaseAI { - } - - public override bool DoActionWander() - { - m_Mobile.DebugSay("I have No Combatant"); - - if (AcquireFocusMob(m_Mobile.RangePerception, FightMode.Closest, false, true, true)) - { - if (m_Mobile.Debug) - m_Mobile.DebugSay($"I have detected {m_Mobile.FocusMob.Name} and I will attack"); - - m_Mobile.Combatant = m_Mobile.FocusMob; - Action = ActionType.Combat; - } - else - { - base.DoActionWander(); - } - - return true; - } - - public override bool DoActionCombat() - { - if (m_Mobile.Combatant?.Deleted != false) - { - m_Mobile.DebugSay("My combatant is deleted"); - Action = ActionType.Guard; - return true; - } - - if (WalkMobileRange(m_Mobile.Combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight)) - { - // Be sure to face the combatant - m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant.Location); - } - else - { - if (m_Mobile.Combatant != null) + public BerserkAI(BaseCreature m) : base(m) { - if (m_Mobile.Debug) - m_Mobile.DebugSay($"I am still not in range of {m_Mobile.Combatant.Name}"); - - if ((int)m_Mobile.GetDistanceToSqrt(m_Mobile.Combatant) > m_Mobile.RangePerception + 1) - { - if (m_Mobile.Debug) - m_Mobile.DebugSay($"I have lost {m_Mobile.Combatant.Name}"); - - Action = ActionType.Guard; - return true; - } } - } - return true; + public override bool DoActionWander() + { + m_Mobile.DebugSay("I have No Combatant"); + + if (AcquireFocusMob(m_Mobile.RangePerception, FightMode.Closest, false, true, true)) + { + if (m_Mobile.Debug) + m_Mobile.DebugSay($"I have detected {m_Mobile.FocusMob.Name} and I will attack"); + + m_Mobile.Combatant = m_Mobile.FocusMob; + Action = ActionType.Combat; + } + else + { + base.DoActionWander(); + } + + return true; + } + + public override bool DoActionCombat() + { + if (m_Mobile.Combatant?.Deleted != false) + { + m_Mobile.DebugSay("My combatant is deleted"); + Action = ActionType.Guard; + return true; + } + + if (WalkMobileRange(m_Mobile.Combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight)) + { + // Be sure to face the combatant + m_Mobile.Direction = m_Mobile.GetDirectionTo(m_Mobile.Combatant.Location); + } + else + { + if (m_Mobile.Combatant != null) + { + if (m_Mobile.Debug) + m_Mobile.DebugSay($"I am still not in range of {m_Mobile.Combatant.Name}"); + + if ((int)m_Mobile.GetDistanceToSqrt(m_Mobile.Combatant) > m_Mobile.RangePerception + 1) + { + if (m_Mobile.Debug) + m_Mobile.DebugSay($"I have lost {m_Mobile.Combatant.Name}"); + + Action = ActionType.Guard; + return true; + } + } + } + + return true; + } + + public override bool DoActionGuard() + { + if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, true, true)) + { + if (m_Mobile.Debug) + m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name); + + m_Mobile.Combatant = m_Mobile.FocusMob; + Action = ActionType.Combat; + } + else + { + base.DoActionGuard(); + } + + return true; + } } - - public override bool DoActionGuard() - { - if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, true, true)) - { - if (m_Mobile.Debug) - m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name); - - m_Mobile.Combatant = m_Mobile.FocusMob; - Action = ActionType.Combat; - } - else - { - base.DoActionGuard(); - } - - return true; - } - } } diff --git a/Projects/UOContent/Mobiles/AI/HealerAI.cs b/Projects/UOContent/Mobiles/AI/HealerAI.cs index dccc0d961..13ee31e36 100644 --- a/Projects/UOContent/Mobiles/AI/HealerAI.cs +++ b/Projects/UOContent/Mobiles/AI/HealerAI.cs @@ -6,143 +6,143 @@ using Server.Targeting; namespace Server.Mobiles { - public class HealerAI : BaseAI - { - private static readonly NeedDelegate m_Cure = NeedCure; - private static readonly NeedDelegate m_GHeal = NeedGHeal; - private static readonly NeedDelegate m_LHeal = NeedLHeal; - private static readonly NeedDelegate[] m_ACure = { m_Cure }; - private static readonly NeedDelegate[] m_AGHeal = { m_GHeal }; - private static readonly NeedDelegate[] m_ALHeal = { m_LHeal }; - private static readonly NeedDelegate[] m_All = { m_Cure, m_GHeal, m_LHeal }; - - public HealerAI(BaseCreature m) : base(m) + public class HealerAI : BaseAI { - } + private static readonly NeedDelegate m_Cure = NeedCure; + private static readonly NeedDelegate m_GHeal = NeedGHeal; + private static readonly NeedDelegate m_LHeal = NeedLHeal; + private static readonly NeedDelegate[] m_ACure = { m_Cure }; + private static readonly NeedDelegate[] m_AGHeal = { m_GHeal }; + private static readonly NeedDelegate[] m_ALHeal = { m_LHeal }; + private static readonly NeedDelegate[] m_All = { m_Cure, m_GHeal, m_LHeal }; - public override bool Think() - { - if (m_Mobile.Deleted) - return false; - - Target targ = m_Mobile.Target; - - if (targ != null) - { - ISpellTarget spellTarg = targ as ISpellTarget; - - if (spellTarg?.Spell is CureSpell) - ProcessTarget(targ, m_ACure); - else if (spellTarg?.Spell is GreaterHealSpell) - ProcessTarget(targ, m_AGHeal); - else if (spellTarg?.Spell is HealSpell) - ProcessTarget(targ, m_ALHeal); - else - targ.Cancel(m_Mobile, TargetCancelType.Canceled); - } - else - { - Mobile toHelp = Find(m_All); - - if (toHelp != null) + public HealerAI(BaseCreature m) : base(m) { - if (NeedCure(toHelp)) - { - if (m_Mobile.Debug) - m_Mobile.DebugSay("{0} needs a cure", toHelp.Name); - - if (!new CureSpell(m_Mobile).Cast()) - new CureSpell(m_Mobile).Cast(); - } - else if (NeedGHeal(toHelp)) - { - if (m_Mobile.Debug) - m_Mobile.DebugSay("{0} needs a greater heal", toHelp.Name); - - if (!new GreaterHealSpell(m_Mobile).Cast()) - new HealSpell(m_Mobile).Cast(); - } - else if (NeedLHeal(toHelp)) - { - if (m_Mobile.Debug) - m_Mobile.DebugSay("{0} needs a lesser heal", toHelp.Name); - - new HealSpell(m_Mobile).Cast(); - } } - else + + public override bool Think() { - if (AcquireFocusMob(m_Mobile.RangePerception, FightMode.Weakest, false, true, false)) - WalkMobileRange(m_Mobile.FocusMob, 1, false, 4, 7); - else - WalkRandomInHome(3, 2, 1); - } - } + if (m_Mobile.Deleted) + return false; - return true; - } + var targ = m_Mobile.Target; - private void ProcessTarget(Target targ, NeedDelegate[] func) - { - Mobile toHelp = Find(func); - - if (toHelp != null) - { - if (targ.Range != -1 && !m_Mobile.InRange(toHelp, targ.Range)) - DoMove(m_Mobile.GetDirectionTo(toHelp) | Direction.Running); - else - targ.Invoke(m_Mobile, toHelp); - } - else - { - targ.Cancel(m_Mobile, TargetCancelType.Canceled); - } - } - - private Mobile Find(params NeedDelegate[] funcs) - { - if (m_Mobile.Deleted) - return null; - - Map map = m_Mobile.Map; - - if (map != null) - { - double prio = 0.0; - Mobile found = null; - - foreach (Mobile m in m_Mobile.GetMobilesInRange(m_Mobile.RangePerception)) - { - if (!m_Mobile.CanSee(m) || !(m is BaseCreature) || ((BaseCreature)m).Team != m_Mobile.Team) - continue; - - for (int i = 0; i < funcs.Length; ++i) - if (funcs[i](m)) + if (targ != null) { - double val = -m_Mobile.GetDistanceToSqrt(m); + var spellTarg = targ as ISpellTarget; - if (found == null || val > prio) - { - prio = val; - found = m; - } + if (spellTarg?.Spell is CureSpell) + ProcessTarget(targ, m_ACure); + else if (spellTarg?.Spell is GreaterHealSpell) + ProcessTarget(targ, m_AGHeal); + else if (spellTarg?.Spell is HealSpell) + ProcessTarget(targ, m_ALHeal); + else + targ.Cancel(m_Mobile, TargetCancelType.Canceled); + } + else + { + var toHelp = Find(m_All); - break; + if (toHelp != null) + { + if (NeedCure(toHelp)) + { + if (m_Mobile.Debug) + m_Mobile.DebugSay("{0} needs a cure", toHelp.Name); + + if (!new CureSpell(m_Mobile).Cast()) + new CureSpell(m_Mobile).Cast(); + } + else if (NeedGHeal(toHelp)) + { + if (m_Mobile.Debug) + m_Mobile.DebugSay("{0} needs a greater heal", toHelp.Name); + + if (!new GreaterHealSpell(m_Mobile).Cast()) + new HealSpell(m_Mobile).Cast(); + } + else if (NeedLHeal(toHelp)) + { + if (m_Mobile.Debug) + m_Mobile.DebugSay("{0} needs a lesser heal", toHelp.Name); + + new HealSpell(m_Mobile).Cast(); + } + } + else + { + if (AcquireFocusMob(m_Mobile.RangePerception, FightMode.Weakest, false, true, false)) + WalkMobileRange(m_Mobile.FocusMob, 1, false, 4, 7); + else + WalkRandomInHome(3, 2, 1); + } + } + + return true; + } + + private void ProcessTarget(Target targ, NeedDelegate[] func) + { + var toHelp = Find(func); + + if (toHelp != null) + { + if (targ.Range != -1 && !m_Mobile.InRange(toHelp, targ.Range)) + DoMove(m_Mobile.GetDirectionTo(toHelp) | Direction.Running); + else + targ.Invoke(m_Mobile, toHelp); + } + else + { + targ.Cancel(m_Mobile, TargetCancelType.Canceled); } } - return found; - } + private Mobile Find(params NeedDelegate[] funcs) + { + if (m_Mobile.Deleted) + return null; - return null; + var map = m_Mobile.Map; + + if (map != null) + { + var prio = 0.0; + Mobile found = null; + + foreach (var m in m_Mobile.GetMobilesInRange(m_Mobile.RangePerception)) + { + if (!m_Mobile.CanSee(m) || !(m is BaseCreature) || ((BaseCreature)m).Team != m_Mobile.Team) + continue; + + for (var i = 0; i < funcs.Length; ++i) + if (funcs[i](m)) + { + var val = -m_Mobile.GetDistanceToSqrt(m); + + if (found == null || val > prio) + { + prio = val; + found = m; + } + + break; + } + } + + return found; + } + + return null; + } + + private static bool NeedCure(Mobile m) => m.Poisoned; + + private static bool NeedGHeal(Mobile m) => m.Hits < m.HitsMax - 40; + + private static bool NeedLHeal(Mobile m) => m.Hits < m.HitsMax - 10; + + private delegate bool NeedDelegate(Mobile m); } - - private static bool NeedCure(Mobile m) => m.Poisoned; - - private static bool NeedGHeal(Mobile m) => m.Hits < m.HitsMax - 40; - - private static bool NeedLHeal(Mobile m) => m.Hits < m.HitsMax - 10; - - private delegate bool NeedDelegate(Mobile m); - } } diff --git a/Projects/UOContent/Mobiles/AI/MageAI.cs b/Projects/UOContent/Mobiles/AI/MageAI.cs index 7fc1aa196..39136b683 100644 --- a/Projects/UOContent/Mobiles/AI/MageAI.cs +++ b/Projects/UOContent/Mobiles/AI/MageAI.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using Server.Spells; using Server.Spells.Fifth; using Server.Spells.First; @@ -13,1064 +12,1075 @@ using Server.Targeting; namespace Server.Mobiles { - public class MageAI : BaseAI - { - private const double HealChance = 0.10; // 10% chance to heal at gm magery - private const double TeleportChance = 0.05; // 5% chance to teleport at gm magery - private const double DispelChance = 0.75; // 75% chance to dispel at gm magery - - private static readonly int[] m_Offsets = + public class MageAI : BaseAI { - -1, -1, - -1, 0, - -1, 1, - 0, -1, - 0, 1, - 1, -1, - 1, 0, - 1, 1, + private const double HealChance = 0.10; // 10% chance to heal at gm magery + private const double TeleportChance = 0.05; // 5% chance to teleport at gm magery + private const double DispelChance = 0.75; // 75% chance to dispel at gm magery - -2, -2, - -2, -1, - -2, 0, - -2, 1, - -2, 2, - -1, -2, - -1, 2, - 0, -2, - 0, 2, - 1, -2, - 1, 2, - 2, -2, - 2, -1, - 2, 0, - 2, 1, - 2, 2 - }; - - protected int m_Combo = -1; - - private Mobile m_LastTarget; - private Point3D m_LastTargetLoc; - private long m_NextCastTime; - private long m_NextHealTime; - - private LandTarget m_RevealTarget; - - public MageAI(BaseCreature m) - : base(m) - { - } - - public virtual bool SmartAI => m_Mobile is BaseVendor || m_Mobile is BaseEscortable || m_Mobile is Changeling; - - public virtual bool IsNecromancer => Core.AOS && m_Mobile.Skills.Necromancy.Value > 50; - - public override bool Think() - { - if (m_Mobile.Deleted) - return false; - - if (ProcessTarget()) - return true; - return base.Think(); - } - - public virtual double ScaleBySkill(double v, SkillName skill) => v * m_Mobile.Skills[skill].Value / 100; - - public override bool DoActionWander() - { - if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) - { - m_Mobile.DebugSay("I am going to attack {0}", m_Mobile.FocusMob.Name); - - m_Mobile.Combatant = m_Mobile.FocusMob; - Action = ActionType.Combat; - m_NextCastTime = Core.TickCount; - } - else if (SmartAI && m_Mobile.Mana < m_Mobile.ManaMax && !m_Mobile.Meditating) - { - m_Mobile.DebugSay("I am going to meditate"); - - m_Mobile.UseSkill(SkillName.Meditation); - } - else - { - m_Mobile.DebugSay("I am wandering"); - - m_Mobile.Warmode = false; - - base.DoActionWander(); - - if (Utility.RandomDouble() < 0.05) + private static readonly int[] m_Offsets = { - Spell spell = CheckCastHealingSpell(); + -1, -1, + -1, 0, + -1, 1, + 0, -1, + 0, 1, + 1, -1, + 1, 0, + 1, 1, - spell?.Cast(); - } - } + -2, -2, + -2, -1, + -2, 0, + -2, 1, + -2, 2, + -1, -2, + -1, 2, + 0, -2, + 0, 2, + 1, -2, + 1, 2, + 2, -2, + 2, -1, + 2, 0, + 2, 1, + 2, 2 + }; - return true; - } + protected int m_Combo = -1; - private Spell CheckCastHealingSpell() - { - // If I'm poisoned, always attempt to cure. - if (m_Mobile.Poisoned) - return new CureSpell(m_Mobile); + private Mobile m_LastTarget; + private Point3D m_LastTargetLoc; + private long m_NextCastTime; + private long m_NextHealTime; - // Summoned creatures never heal themselves. - if (m_Mobile.Summoned) - return null; + private LandTarget m_RevealTarget; - if (m_Mobile.Controlled) - if (Core.TickCount - m_NextHealTime < 0) - return null; - - if (!SmartAI) - { - if (ScaleBySkill(HealChance, SkillName.Magery) < Utility.RandomDouble()) - return null; - } - else - { - if (Utility.Random(0, 4 + (m_Mobile.Hits == 0 ? m_Mobile.HitsMax : m_Mobile.HitsMax / m_Mobile.Hits)) < 3) - return null; - } - - Spell spell = null; - - if (m_Mobile.Hits < m_Mobile.HitsMax - 50) - { - if (UseNecromancy()) - m_Mobile.UseSkill(SkillName.SpiritSpeak); - else - spell = new GreaterHealSpell(m_Mobile); - } - else if (m_Mobile.Hits < m_Mobile.HitsMax - 10) - { - spell = new HealSpell(m_Mobile); - } - - double delay; - - if (m_Mobile.Int >= 500) - delay = Utility.RandomMinMax(7, 10); - else - delay = Math.Sqrt(600 - m_Mobile.Int); - - m_NextHealTime = Core.TickCount + (int)TimeSpan.FromSeconds(delay).TotalMilliseconds; - - return spell; - } - - public void RunTo(Mobile m) - { - if (!SmartAI) - { - if (!MoveTo(m, true, m_Mobile.RangeFight)) - OnFailedMove(); - - return; - } - - if (m.Paralyzed || m.Frozen) - { - if (m_Mobile.InRange(m, 1)) - RunFrom(m); - else if (!m_Mobile.InRange(m, m_Mobile.RangeFight > 2 ? m_Mobile.RangeFight : 2) && !MoveTo(m, true, 1)) - OnFailedMove(); - } - else - { - if (!m_Mobile.InRange(m, m_Mobile.RangeFight)) + public MageAI(BaseCreature m) + : base(m) { - if (!MoveTo(m, true, 1)) - OnFailedMove(); - } - else if (m_Mobile.InRange(m, m_Mobile.RangeFight - 1)) - { - RunFrom(m); - } - } - } - - public void RunFrom(Mobile m) - { - Run(m_Mobile.GetDirectionTo(m) - 4 & Direction.Mask); - } - - public void OnFailedMove() - { - if (!m_Mobile.DisallowAllMoves && (SmartAI - ? Utility.Random(4) == 0 - : ScaleBySkill(TeleportChance, SkillName.Magery) > Utility.RandomDouble())) - { - m_Mobile.Target?.Cancel(m_Mobile, TargetCancelType.Canceled); - - new TeleportSpell(m_Mobile).Cast(); - - m_Mobile.DebugSay("I am stuck, I'm going to try teleporting away"); - } - else if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) - { - m_Mobile.DebugSay("My move is blocked, so I am going to attack {0}", m_Mobile.FocusMob.Name); - - m_Mobile.Combatant = m_Mobile.FocusMob; - Action = ActionType.Combat; - } - else - { - m_Mobile.DebugSay("I am stuck"); - } - } - - public void Run(Direction d) - { - if (m_Mobile.Spell?.IsCasting == true || m_Mobile.Paralyzed || m_Mobile.Frozen || - m_Mobile.DisallowAllMoves) - return; - - m_Mobile.Direction = d | Direction.Running; - - if (!DoMove(m_Mobile.Direction, true)) - OnFailedMove(); - } - - public virtual bool UseNecromancy() - { - if (IsNecromancer) - return Utility.Random(m_Mobile.Skills.Magery.BaseFixedPoint + - m_Mobile.Skills.Necromancy.BaseFixedPoint) >= - m_Mobile.Skills.Magery.BaseFixedPoint; - - return false; - } - - public virtual Spell GetRandomDamageSpell() => UseNecromancy() ? GetRandomDamageSpellNecro() : GetRandomDamageSpellMage(); - - public virtual Spell GetRandomDamageSpellNecro() - { - int bound = m_Mobile.Skills.Necromancy.Value >= 100 ? 5 : 3; - - switch (Utility.Random(bound)) - { - case 0: - m_Mobile.DebugSay("Pain Spike"); - return new PainSpikeSpell(m_Mobile); - case 1: - m_Mobile.DebugSay("Poison Strike"); - return new PoisonStrikeSpell(m_Mobile); - case 2: - m_Mobile.DebugSay("Strangle"); - return new StrangleSpell(m_Mobile); - case 3: - m_Mobile.DebugSay("Wither"); - return new WitherSpell(m_Mobile); - default: - m_Mobile.DebugSay("Vengeful Spirit"); - return new VengefulSpiritSpell(m_Mobile); - } - } - - public virtual Spell GetRandomDamageSpellMage() - { - int maxCircle = Math.Clamp((int)((m_Mobile.Skills.Magery.Value + 20.0) / (100.0 / 7.0)), 1, 8); - - return Utility.Random(maxCircle * 2) switch - { - 0 => new MagicArrowSpell(m_Mobile), - 1 => new MagicArrowSpell(m_Mobile), - 2 => new HarmSpell(m_Mobile), - 3 => new HarmSpell(m_Mobile), - 4 => new FireballSpell(m_Mobile), - 5 => new FireballSpell(m_Mobile), - 6 => new LightningSpell(m_Mobile), - 7 => new LightningSpell(m_Mobile), - 8 => new MindBlastSpell(m_Mobile), - 9 => new MindBlastSpell(m_Mobile), - 10 => new EnergyBoltSpell(m_Mobile), - 11 => new ExplosionSpell(m_Mobile), - _ => new FlameStrikeSpell(m_Mobile) - }; - } - - public virtual Spell GetRandomCurseSpell() => UseNecromancy() ? GetRandomCurseSpellNecro() : GetRandomCurseSpellMage(); - - public virtual Spell GetRandomCurseSpellNecro() - { - switch (Utility.Random(4)) - { - case 0: - m_Mobile.DebugSay("Blood Oath"); - return new BloodOathSpell(m_Mobile); - case 1: - m_Mobile.DebugSay("Corpse Skin"); - return new CorpseSkinSpell(m_Mobile); - case 2: - m_Mobile.DebugSay("Evil Omen"); - return new EvilOmenSpell(m_Mobile); - default: - m_Mobile.DebugSay("Mind Rot"); - return new MindRotSpell(m_Mobile); - } - } - - public virtual Spell GetRandomCurseSpellMage() - { - if (m_Mobile.Skills.Magery.Value >= 40.0 && Utility.Random(4) == 0) - return new CurseSpell(m_Mobile); - - return Utility.Random(3) switch - { - 0 => new WeakenSpell(m_Mobile), - 1 => new ClumsySpell(m_Mobile), - _ => new FeeblemindSpell(m_Mobile) - }; - } - - public virtual Spell GetRandomManaDrainSpell() - { - if (m_Mobile.Skills.Magery.Value >= 80.0 && Utility.RandomBool()) - return new ManaVampireSpell(m_Mobile); - - return new ManaDrainSpell(m_Mobile); - } - - public virtual Spell DoDispel(Mobile toDispel) - { - if (!SmartAI) - { - if (ScaleBySkill(DispelChance, SkillName.Magery) > Utility.RandomDouble()) - return new DispelSpell(m_Mobile); - - return ChooseSpell(toDispel); - } - - Spell spell = CheckCastHealingSpell(); - - if (spell == null) - { - if (!m_Mobile.DisallowAllMoves && Utility.Random((int)m_Mobile.GetDistanceToSqrt(toDispel)) == 0) - spell = new TeleportSpell(m_Mobile); - else if (Utility.Random(3) == 0 && !m_Mobile.InRange(toDispel, 3) && !toDispel.Paralyzed && !toDispel.Frozen) - spell = new ParalyzeSpell(m_Mobile); - else - spell = new DispelSpell(m_Mobile); - } - - return spell; - } - - public virtual Spell ChooseSpell(Mobile c) - { - Spell spell; - - if (!SmartAI) - { - spell = CheckCastHealingSpell(); - - if (spell != null) - return spell; - - if (IsNecromancer) - { - double psDamage = - (m_Mobile.Skills.SpiritSpeak.Value - c.Skills.MagicResist.Value) / 10 + - (c.Player ? 18 : 30); - - if (psDamage > c.Hits) - return new PainSpikeSpell(m_Mobile); } - switch (Utility.Random(16)) + public virtual bool SmartAI => m_Mobile is BaseVendor || m_Mobile is BaseEscortable || m_Mobile is Changeling; + + public virtual bool IsNecromancer => Core.AOS && m_Mobile.Skills.Necromancy.Value > 50; + + public override bool Think() { - case 0: - case 1: // Poison them - { - if (c.Poisoned) - goto default; + if (m_Mobile.Deleted) + return false; - m_Mobile.DebugSay("Attempting to poison"); - - spell = new PoisonSpell(m_Mobile); - break; - } - case 2: // Bless ourselves - { - m_Mobile.DebugSay("Blessing myself"); - - spell = new BlessSpell(m_Mobile); - break; - } - case 3: - case 4: // Curse them - { - m_Mobile.DebugSay("Attempting to curse"); - - spell = GetRandomCurseSpell(); - break; - } - case 5: // Paralyze them - { - if (c.Paralyzed || m_Mobile.Skills.Magery.Value <= 50.0) - goto default; - - m_Mobile.DebugSay("Attempting to paralyze"); - - spell = new ParalyzeSpell(m_Mobile); - break; - } - case 6: // Drain mana - { - m_Mobile.DebugSay("Attempting to drain mana"); - - spell = GetRandomManaDrainSpell(); - break; - } - case 7: // Invis ourselves - { - if (Utility.RandomBool()) - goto default; - - m_Mobile.DebugSay("Attempting to invis myself"); - - spell = new InvisibilitySpell(m_Mobile); - break; - } - default: // Damage them - { - m_Mobile.DebugSay("Just doing damage"); - - spell = GetRandomDamageSpell(); - break; - } + if (ProcessTarget()) + return true; + return base.Think(); } - return spell; - } + public virtual double ScaleBySkill(double v, SkillName skill) => v * m_Mobile.Skills[skill].Value / 100; - spell = CheckCastHealingSpell(); - - if (spell != null) - return spell; - - switch (Utility.Random(3)) - { - case 0: // Poison them - { - if (c.Poisoned) - goto case 1; - - spell = new PoisonSpell(m_Mobile); - break; - } - case 1: // Deal some damage - { - spell = GetRandomDamageSpell(); - - break; - } - default: // Set up a combo - { - if (m_Mobile.Mana > 15 && m_Mobile.Mana < 40) + public override bool DoActionWander() + { + if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) + { + m_Mobile.DebugSay("I am going to attack {0}", m_Mobile.FocusMob.Name); + + m_Mobile.Combatant = m_Mobile.FocusMob; + Action = ActionType.Combat; + m_NextCastTime = Core.TickCount; + } + else if (SmartAI && m_Mobile.Mana < m_Mobile.ManaMax && !m_Mobile.Meditating) { - if (c.Paralyzed && !c.Poisoned && !m_Mobile.Meditating) - { m_Mobile.DebugSay("I am going to meditate"); m_Mobile.UseSkill(SkillName.Meditation); - } - else if (!c.Poisoned) - { - spell = new ParalyzeSpell(m_Mobile); - } } - else if (m_Mobile.Mana > 60) + else { - if (Utility.RandomBool() && !c.Paralyzed && !c.Frozen && !c.Poisoned) - { - m_Combo = 0; - spell = new ParalyzeSpell(m_Mobile); - } - else - { - m_Combo = 1; - spell = new ExplosionSpell(m_Mobile); - } + m_Mobile.DebugSay("I am wandering"); + + m_Mobile.Warmode = false; + + base.DoActionWander(); + + if (Utility.RandomDouble() < 0.05) + { + var spell = CheckCastHealingSpell(); + + spell?.Cast(); + } } - break; - } - } - - return spell; - } - - public virtual Spell DoCombo(Mobile c) - { - Spell spell = null; - - if (m_Combo == 0) - { - spell = new ExplosionSpell(m_Mobile); - ++m_Combo; // Move to next spell - } - else if (m_Combo == 1) - { - spell = new WeakenSpell(m_Mobile); - ++m_Combo; // Move to next spell - } - else if (m_Combo == 2) - { - if (!c.Poisoned) - spell = new PoisonSpell(m_Mobile); - else if (IsNecromancer) - spell = new StrangleSpell(m_Mobile); - - ++m_Combo; // Move to next spell - } - - if (m_Combo == 3 && spell == null) - { - switch (Utility.Random(IsNecromancer ? 4 : 3)) - { - case 0: - { - if (c.Int < c.Dex) - spell = new FeeblemindSpell(m_Mobile); - else - spell = new ClumsySpell(m_Mobile); - - ++m_Combo; // Move to next spell - - break; - } - case 1: - { - spell = new EnergyBoltSpell(m_Mobile); - m_Combo = -1; // Reset combo state - break; - } - case 2: - { - spell = new FlameStrikeSpell(m_Mobile); - m_Combo = -1; // Reset combo state - break; - } - default: - { - spell = new PainSpikeSpell(m_Mobile); - m_Combo = -1; // Reset combo state - break; - } - } - } - else if (m_Combo == 4 && spell == null) - { - spell = new MindBlastSpell(m_Mobile); - m_Combo = -1; - } - - return spell; - } - - private TimeSpan GetDelay(Spell spell) - { - if (SmartAI || spell is DispelSpell) return TimeSpan.FromSeconds(m_Mobile.ActiveSpeed); - - double del = ScaleBySkill(3.0, SkillName.Magery); - double min = 6.0 - del * 0.75; - double max = 6.0 - del * 1.25; - - return TimeSpan.FromSeconds(min + (max - min) * Utility.RandomDouble()); - } - - public override bool DoActionCombat() - { - Mobile c = m_Mobile.Combatant; - m_Mobile.Warmode = true; - - if (c?.Deleted != false || !c.Alive || c.IsDeadBondedPet || !m_Mobile.CanSee(c) || - !m_Mobile.CanBeHarmful(c, false) || c.Map != m_Mobile.Map) - { - // Our combatant is deleted, dead, hidden, or we cannot hurt them - // Try to find another combatant - - if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) - { - m_Mobile.DebugSay("Something happened to my combatant, so I am going to fight {0}", - m_Mobile.FocusMob.Name); - - m_Mobile.Combatant = c = m_Mobile.FocusMob; - m_Mobile.FocusMob = null; - } - else - { - m_Mobile.DebugSay("Something happened to my combatant, and nothing is around. I am on guard."); - Action = ActionType.Guard; - return true; - } - } - - if (!m_Mobile.InLOS(c)) - { - m_Mobile.DebugSay("I can't see my target"); - - if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) - { - m_Mobile.DebugSay("I will switch to {0}", m_Mobile.FocusMob.Name); - m_Mobile.Combatant = c = m_Mobile.FocusMob; - m_Mobile.FocusMob = null; - } - } - - if (!Core.AOS && SmartAI && !m_Mobile.StunReady && m_Mobile.Skills.Wrestling.Value >= 80.0 && - m_Mobile.Skills.Anatomy.Value >= 80.0) - EventSink.InvokeStunRequest(m_Mobile); - - if (!m_Mobile.InRange(c, m_Mobile.RangePerception)) - { - // They are somewhat far away, can we find something else? - - if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) - { - m_Mobile.Combatant = m_Mobile.FocusMob; - m_Mobile.FocusMob = null; - } - else if (!m_Mobile.InRange(c, m_Mobile.RangePerception * 3)) - { - m_Mobile.Combatant = null; - } - - c = m_Mobile.Combatant; - - if (c == null) - { - m_Mobile.DebugSay("My combatant has fled, so I am on guard"); - Action = ActionType.Guard; - - return true; - } - } - - if (!m_Mobile.Controlled && !m_Mobile.Summoned && m_Mobile.CanFlee) - if (m_Mobile.Hits < m_Mobile.HitsMax * 20 / 100) - { - // We are low on health, should we flee? - - bool flee; - - if (m_Mobile.Hits < c.Hits) - { - // We are more hurt than them - - int diff = c.Hits - m_Mobile.Hits; - - flee = Utility.Random(0, 100) > 10 + diff; // (10 + diff)% chance to flee - } - else - { - flee = Utility.Random(0, 100) > 10; // 10% chance to flee - } - - if (flee) - { - m_Mobile.DebugSay("I am going to flee from {0}", c.Name); - - Action = ActionType.Flee; return true; - } } - if (m_Mobile.Spell == null && Core.TickCount - m_NextCastTime >= 0 && m_Mobile.InRange(c, Core.ML ? 10 : 12)) - { - // We are ready to cast a spell - - Spell spell; - Mobile toDispel = FindDispelTarget(true); - - if (m_Mobile.Poisoned) // Top cast priority is cure + private Spell CheckCastHealingSpell() { - m_Mobile.DebugSay("I am going to cure myself"); + // If I'm poisoned, always attempt to cure. + if (m_Mobile.Poisoned) + return new CureSpell(m_Mobile); - spell = new CureSpell(m_Mobile); - } - else if (toDispel != null) // Something dispellable is attacking us - { - m_Mobile.DebugSay("I am going to dispel {0}", toDispel); + // Summoned creatures never heal themselves. + if (m_Mobile.Summoned) + return null; - spell = DoDispel(toDispel); - } - else if (SmartAI && m_Combo != -1) // We are doing a spell combo - { - spell = DoCombo(c); - } - else if (SmartAI && (c.Spell is HealSpell || c.Spell is GreaterHealSpell) && !c.Poisoned) // They have a heal spell out - { - spell = new PoisonSpell(m_Mobile); - } - else - { - spell = ChooseSpell(c); - } + if (m_Mobile.Controlled) + if (Core.TickCount - m_NextHealTime < 0) + return null; - // Now we have a spell picked - // Move first before casting - - if (SmartAI && toDispel != null) - { - if (m_Mobile.InRange(toDispel, 10)) - RunFrom(toDispel); - else if (!m_Mobile.InRange(toDispel, Core.ML ? 10 : 12)) - RunTo(toDispel); - } - else - { - RunTo(c); - } - - spell?.Cast(); - - m_NextCastTime = Core.TickCount + (int)GetDelay(spell).TotalMilliseconds; - } - else if (m_Mobile.Spell?.IsCasting != true) - { - RunTo(c); - } - - m_LastTarget = c; - m_LastTargetLoc = c.Location; - - return true; - } - - public override bool DoActionGuard() - { - if (m_LastTarget?.Hidden == true) - { - Map map = m_Mobile.Map; - - if (map == null || !m_Mobile.InRange(m_LastTargetLoc, Core.ML ? 10 : 12)) - { - m_LastTarget = null; - } - else if (m_Mobile.Spell == null && Core.TickCount - m_NextCastTime >= 0) - { - m_Mobile.DebugSay("I am going to reveal my last target"); - - m_RevealTarget = new LandTarget(m_LastTargetLoc, map); - Spell spell = new RevealSpell(m_Mobile); - - if (spell.Cast()) - m_LastTarget = null; // only do it once - - m_NextCastTime = Core.TickCount + (int)GetDelay(spell).TotalMilliseconds; - } - } - - if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) - { - m_Mobile.DebugSay("I am going to attack {0}", m_Mobile.FocusMob.Name); - - m_Mobile.Combatant = m_Mobile.FocusMob; - Action = ActionType.Combat; - } - else - { - if (!m_Mobile.Controlled) - { - ProcessTarget(); - - Spell spell = CheckCastHealingSpell(); - - spell?.Cast(); - } - - base.DoActionGuard(); - } - - return true; - } - - public override bool DoActionFlee() - { - // Mobile c = m_Mobile.Combatant; - - if ((m_Mobile.Mana > 20 || m_Mobile.Mana == m_Mobile.ManaMax) && m_Mobile.Hits > m_Mobile.HitsMax / 2) - { - m_Mobile.DebugSay("I am stronger now, my guard is up"); - Action = ActionType.Guard; - } - else if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) - { - m_Mobile.DebugSay("I am scared of {0}", m_Mobile.FocusMob.Name); - - RunFrom(m_Mobile.FocusMob); - m_Mobile.FocusMob = null; - - if (m_Mobile.Poisoned && Utility.Random(0, 5) == 0) - new CureSpell(m_Mobile).Cast(); - } - else - { - m_Mobile.DebugSay("Area seems clear, but my guard is up"); - - Action = ActionType.Guard; - m_Mobile.Warmode = true; - } - - return true; - } - - public Mobile FindDispelTarget(bool activeOnly) - { - if (m_Mobile.Deleted || m_Mobile.Int < 95 || CanDispel(m_Mobile) || m_Mobile.AutoDispel) - return null; - - if (activeOnly) - { - List aggressed = m_Mobile.Aggressed; - List aggressors = m_Mobile.Aggressors; - - Mobile active = null; - double activePrio = 0.0; - - Mobile comb = m_Mobile.Combatant; - - if (comb?.Deleted == false && comb.Alive && !comb.IsDeadBondedPet && - m_Mobile.InRange(comb, Core.ML ? 10 : 12) && CanDispel(comb)) - { - active = comb; - activePrio = m_Mobile.GetDistanceToSqrt(comb); - - if (activePrio <= 2) - return active; - } - - for (int i = 0; i < aggressed.Count; ++i) - { - AggressorInfo info = aggressed[i]; - Mobile m = info.Defender; - - if (m != comb && m.Combatant == m_Mobile && m_Mobile.InRange(m, Core.ML ? 10 : 12) && CanDispel(m)) - { - double prio = m_Mobile.GetDistanceToSqrt(m); - - if (active == null || prio < activePrio) + if (!SmartAI) { - active = m; - activePrio = prio; + if (ScaleBySkill(HealChance, SkillName.Magery) < Utility.RandomDouble()) + return null; + } + else + { + if (Utility.Random(0, 4 + (m_Mobile.Hits == 0 ? m_Mobile.HitsMax : m_Mobile.HitsMax / m_Mobile.Hits)) < 3) + return null; + } + + Spell spell = null; + + if (m_Mobile.Hits < m_Mobile.HitsMax - 50) + { + if (UseNecromancy()) + m_Mobile.UseSkill(SkillName.SpiritSpeak); + else + spell = new GreaterHealSpell(m_Mobile); + } + else if (m_Mobile.Hits < m_Mobile.HitsMax - 10) + { + spell = new HealSpell(m_Mobile); + } + + double delay; + + if (m_Mobile.Int >= 500) + delay = Utility.RandomMinMax(7, 10); + else + delay = Math.Sqrt(600 - m_Mobile.Int); + + m_NextHealTime = Core.TickCount + (int)TimeSpan.FromSeconds(delay).TotalMilliseconds; + + return spell; + } + + public void RunTo(Mobile m) + { + if (!SmartAI) + { + if (!MoveTo(m, true, m_Mobile.RangeFight)) + OnFailedMove(); + + return; + } + + if (m.Paralyzed || m.Frozen) + { + if (m_Mobile.InRange(m, 1)) + RunFrom(m); + else if (!m_Mobile.InRange(m, m_Mobile.RangeFight > 2 ? m_Mobile.RangeFight : 2) && !MoveTo(m, true, 1)) + OnFailedMove(); + } + else + { + if (!m_Mobile.InRange(m, m_Mobile.RangeFight)) + { + if (!MoveTo(m, true, 1)) + OnFailedMove(); + } + else if (m_Mobile.InRange(m, m_Mobile.RangeFight - 1)) + { + RunFrom(m); + } + } + } + + public void RunFrom(Mobile m) + { + Run((m_Mobile.GetDirectionTo(m) - 4) & Direction.Mask); + } + + public void OnFailedMove() + { + if (!m_Mobile.DisallowAllMoves && (SmartAI + ? Utility.Random(4) == 0 + : ScaleBySkill(TeleportChance, SkillName.Magery) > Utility.RandomDouble())) + { + m_Mobile.Target?.Cancel(m_Mobile, TargetCancelType.Canceled); + + new TeleportSpell(m_Mobile).Cast(); + + m_Mobile.DebugSay("I am stuck, I'm going to try teleporting away"); + } + else if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) + { + m_Mobile.DebugSay("My move is blocked, so I am going to attack {0}", m_Mobile.FocusMob.Name); + + m_Mobile.Combatant = m_Mobile.FocusMob; + Action = ActionType.Combat; + } + else + { + m_Mobile.DebugSay("I am stuck"); + } + } + + public void Run(Direction d) + { + if (m_Mobile.Spell?.IsCasting == true || m_Mobile.Paralyzed || m_Mobile.Frozen || + m_Mobile.DisallowAllMoves) + return; + + m_Mobile.Direction = d | Direction.Running; + + if (!DoMove(m_Mobile.Direction, true)) + OnFailedMove(); + } + + public virtual bool UseNecromancy() + { + if (IsNecromancer) + return Utility.Random( + m_Mobile.Skills.Magery.BaseFixedPoint + + m_Mobile.Skills.Necromancy.BaseFixedPoint + ) >= + m_Mobile.Skills.Magery.BaseFixedPoint; + + return false; + } + + public virtual Spell GetRandomDamageSpell() => + UseNecromancy() ? GetRandomDamageSpellNecro() : GetRandomDamageSpellMage(); + + public virtual Spell GetRandomDamageSpellNecro() + { + var bound = m_Mobile.Skills.Necromancy.Value >= 100 ? 5 : 3; + + switch (Utility.Random(bound)) + { + case 0: + m_Mobile.DebugSay("Pain Spike"); + return new PainSpikeSpell(m_Mobile); + case 1: + m_Mobile.DebugSay("Poison Strike"); + return new PoisonStrikeSpell(m_Mobile); + case 2: + m_Mobile.DebugSay("Strangle"); + return new StrangleSpell(m_Mobile); + case 3: + m_Mobile.DebugSay("Wither"); + return new WitherSpell(m_Mobile); + default: + m_Mobile.DebugSay("Vengeful Spirit"); + return new VengefulSpiritSpell(m_Mobile); + } + } + + public virtual Spell GetRandomDamageSpellMage() + { + var maxCircle = Math.Clamp((int)((m_Mobile.Skills.Magery.Value + 20.0) / (100.0 / 7.0)), 1, 8); + + return Utility.Random(maxCircle * 2) switch + { + 0 => new MagicArrowSpell(m_Mobile), + 1 => new MagicArrowSpell(m_Mobile), + 2 => new HarmSpell(m_Mobile), + 3 => new HarmSpell(m_Mobile), + 4 => new FireballSpell(m_Mobile), + 5 => new FireballSpell(m_Mobile), + 6 => new LightningSpell(m_Mobile), + 7 => new LightningSpell(m_Mobile), + 8 => new MindBlastSpell(m_Mobile), + 9 => new MindBlastSpell(m_Mobile), + 10 => new EnergyBoltSpell(m_Mobile), + 11 => new ExplosionSpell(m_Mobile), + _ => new FlameStrikeSpell(m_Mobile) + }; + } + + public virtual Spell GetRandomCurseSpell() => + UseNecromancy() ? GetRandomCurseSpellNecro() : GetRandomCurseSpellMage(); + + public virtual Spell GetRandomCurseSpellNecro() + { + switch (Utility.Random(4)) + { + case 0: + m_Mobile.DebugSay("Blood Oath"); + return new BloodOathSpell(m_Mobile); + case 1: + m_Mobile.DebugSay("Corpse Skin"); + return new CorpseSkinSpell(m_Mobile); + case 2: + m_Mobile.DebugSay("Evil Omen"); + return new EvilOmenSpell(m_Mobile); + default: + m_Mobile.DebugSay("Mind Rot"); + return new MindRotSpell(m_Mobile); + } + } + + public virtual Spell GetRandomCurseSpellMage() + { + if (m_Mobile.Skills.Magery.Value >= 40.0 && Utility.Random(4) == 0) + return new CurseSpell(m_Mobile); + + return Utility.Random(3) switch + { + 0 => new WeakenSpell(m_Mobile), + 1 => new ClumsySpell(m_Mobile), + _ => new FeeblemindSpell(m_Mobile) + }; + } + + public virtual Spell GetRandomManaDrainSpell() + { + if (m_Mobile.Skills.Magery.Value >= 80.0 && Utility.RandomBool()) + return new ManaVampireSpell(m_Mobile); + + return new ManaDrainSpell(m_Mobile); + } + + public virtual Spell DoDispel(Mobile toDispel) + { + if (!SmartAI) + { + if (ScaleBySkill(DispelChance, SkillName.Magery) > Utility.RandomDouble()) + return new DispelSpell(m_Mobile); + + return ChooseSpell(toDispel); + } + + var spell = CheckCastHealingSpell(); + + if (spell == null) + { + if (!m_Mobile.DisallowAllMoves && Utility.Random((int)m_Mobile.GetDistanceToSqrt(toDispel)) == 0) + spell = new TeleportSpell(m_Mobile); + else if (Utility.Random(3) == 0 && !m_Mobile.InRange(toDispel, 3) && !toDispel.Paralyzed && !toDispel.Frozen) + spell = new ParalyzeSpell(m_Mobile); + else + spell = new DispelSpell(m_Mobile); + } + + return spell; + } + + public virtual Spell ChooseSpell(Mobile c) + { + Spell spell; + + if (!SmartAI) + { + spell = CheckCastHealingSpell(); + + if (spell != null) + return spell; + + if (IsNecromancer) + { + var psDamage = + (m_Mobile.Skills.SpiritSpeak.Value - c.Skills.MagicResist.Value) / 10 + + (c.Player ? 18 : 30); + + if (psDamage > c.Hits) + return new PainSpikeSpell(m_Mobile); + } + + switch (Utility.Random(16)) + { + case 0: + case 1: // Poison them + { + if (c.Poisoned) + goto default; + + m_Mobile.DebugSay("Attempting to poison"); + + spell = new PoisonSpell(m_Mobile); + break; + } + case 2: // Bless ourselves + { + m_Mobile.DebugSay("Blessing myself"); + + spell = new BlessSpell(m_Mobile); + break; + } + case 3: + case 4: // Curse them + { + m_Mobile.DebugSay("Attempting to curse"); + + spell = GetRandomCurseSpell(); + break; + } + case 5: // Paralyze them + { + if (c.Paralyzed || m_Mobile.Skills.Magery.Value <= 50.0) + goto default; + + m_Mobile.DebugSay("Attempting to paralyze"); + + spell = new ParalyzeSpell(m_Mobile); + break; + } + case 6: // Drain mana + { + m_Mobile.DebugSay("Attempting to drain mana"); + + spell = GetRandomManaDrainSpell(); + break; + } + case 7: // Invis ourselves + { + if (Utility.RandomBool()) + goto default; + + m_Mobile.DebugSay("Attempting to invis myself"); + + spell = new InvisibilitySpell(m_Mobile); + break; + } + default: // Damage them + { + m_Mobile.DebugSay("Just doing damage"); + + spell = GetRandomDamageSpell(); + break; + } + } + + return spell; + } + + spell = CheckCastHealingSpell(); + + if (spell != null) + return spell; + + switch (Utility.Random(3)) + { + case 0: // Poison them + { + if (c.Poisoned) + goto case 1; + + spell = new PoisonSpell(m_Mobile); + break; + } + case 1: // Deal some damage + { + spell = GetRandomDamageSpell(); + + break; + } + default: // Set up a combo + { + if (m_Mobile.Mana > 15 && m_Mobile.Mana < 40) + { + if (c.Paralyzed && !c.Poisoned && !m_Mobile.Meditating) + { + m_Mobile.DebugSay("I am going to meditate"); + + m_Mobile.UseSkill(SkillName.Meditation); + } + else if (!c.Poisoned) + { + spell = new ParalyzeSpell(m_Mobile); + } + } + else if (m_Mobile.Mana > 60) + { + if (Utility.RandomBool() && !c.Paralyzed && !c.Frozen && !c.Poisoned) + { + m_Combo = 0; + spell = new ParalyzeSpell(m_Mobile); + } + else + { + m_Combo = 1; + spell = new ExplosionSpell(m_Mobile); + } + } + + break; + } + } + + return spell; + } + + public virtual Spell DoCombo(Mobile c) + { + Spell spell = null; + + if (m_Combo == 0) + { + spell = new ExplosionSpell(m_Mobile); + ++m_Combo; // Move to next spell + } + else if (m_Combo == 1) + { + spell = new WeakenSpell(m_Mobile); + ++m_Combo; // Move to next spell + } + else if (m_Combo == 2) + { + if (!c.Poisoned) + spell = new PoisonSpell(m_Mobile); + else if (IsNecromancer) + spell = new StrangleSpell(m_Mobile); + + ++m_Combo; // Move to next spell + } + + if (m_Combo == 3 && spell == null) + { + switch (Utility.Random(IsNecromancer ? 4 : 3)) + { + case 0: + { + if (c.Int < c.Dex) + spell = new FeeblemindSpell(m_Mobile); + else + spell = new ClumsySpell(m_Mobile); + + ++m_Combo; // Move to next spell + + break; + } + case 1: + { + spell = new EnergyBoltSpell(m_Mobile); + m_Combo = -1; // Reset combo state + break; + } + case 2: + { + spell = new FlameStrikeSpell(m_Mobile); + m_Combo = -1; // Reset combo state + break; + } + default: + { + spell = new PainSpikeSpell(m_Mobile); + m_Combo = -1; // Reset combo state + break; + } + } + } + else if (m_Combo == 4 && spell == null) + { + spell = new MindBlastSpell(m_Mobile); + m_Combo = -1; + } + + return spell; + } + + private TimeSpan GetDelay(Spell spell) + { + if (SmartAI || spell is DispelSpell) return TimeSpan.FromSeconds(m_Mobile.ActiveSpeed); + + var del = ScaleBySkill(3.0, SkillName.Magery); + var min = 6.0 - del * 0.75; + var max = 6.0 - del * 1.25; + + return TimeSpan.FromSeconds(min + (max - min) * Utility.RandomDouble()); + } + + public override bool DoActionCombat() + { + var c = m_Mobile.Combatant; + m_Mobile.Warmode = true; + + if (c?.Deleted != false || !c.Alive || c.IsDeadBondedPet || !m_Mobile.CanSee(c) || + !m_Mobile.CanBeHarmful(c, false) || c.Map != m_Mobile.Map) + { + // Our combatant is deleted, dead, hidden, or we cannot hurt them + // Try to find another combatant + + if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) + { + m_Mobile.DebugSay( + "Something happened to my combatant, so I am going to fight {0}", + m_Mobile.FocusMob.Name + ); + + m_Mobile.Combatant = c = m_Mobile.FocusMob; + m_Mobile.FocusMob = null; + } + else + { + m_Mobile.DebugSay("Something happened to my combatant, and nothing is around. I am on guard."); + Action = ActionType.Guard; + return true; + } + } + + if (!m_Mobile.InLOS(c)) + { + m_Mobile.DebugSay("I can't see my target"); + + if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) + { + m_Mobile.DebugSay("I will switch to {0}", m_Mobile.FocusMob.Name); + m_Mobile.Combatant = c = m_Mobile.FocusMob; + m_Mobile.FocusMob = null; + } + } + + if (!Core.AOS && SmartAI && !m_Mobile.StunReady && m_Mobile.Skills.Wrestling.Value >= 80.0 && + m_Mobile.Skills.Anatomy.Value >= 80.0) + EventSink.InvokeStunRequest(m_Mobile); + + if (!m_Mobile.InRange(c, m_Mobile.RangePerception)) + { + // They are somewhat far away, can we find something else? + + if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) + { + m_Mobile.Combatant = m_Mobile.FocusMob; + m_Mobile.FocusMob = null; + } + else if (!m_Mobile.InRange(c, m_Mobile.RangePerception * 3)) + { + m_Mobile.Combatant = null; + } + + c = m_Mobile.Combatant; + + if (c == null) + { + m_Mobile.DebugSay("My combatant has fled, so I am on guard"); + Action = ActionType.Guard; + + return true; + } + } + + if (!m_Mobile.Controlled && !m_Mobile.Summoned && m_Mobile.CanFlee) + if (m_Mobile.Hits < m_Mobile.HitsMax * 20 / 100) + { + // We are low on health, should we flee? + + bool flee; + + if (m_Mobile.Hits < c.Hits) + { + // We are more hurt than them + + var diff = c.Hits - m_Mobile.Hits; + + flee = Utility.Random(0, 100) > 10 + diff; // (10 + diff)% chance to flee + } + else + { + flee = Utility.Random(0, 100) > 10; // 10% chance to flee + } + + if (flee) + { + m_Mobile.DebugSay("I am going to flee from {0}", c.Name); + + Action = ActionType.Flee; + return true; + } + } + + if (m_Mobile.Spell == null && Core.TickCount - m_NextCastTime >= 0 && m_Mobile.InRange(c, Core.ML ? 10 : 12)) + { + // We are ready to cast a spell + + Spell spell; + var toDispel = FindDispelTarget(true); + + if (m_Mobile.Poisoned) // Top cast priority is cure + { + m_Mobile.DebugSay("I am going to cure myself"); + + spell = new CureSpell(m_Mobile); + } + else if (toDispel != null) // Something dispellable is attacking us + { + m_Mobile.DebugSay("I am going to dispel {0}", toDispel); + + spell = DoDispel(toDispel); + } + else if (SmartAI && m_Combo != -1) // We are doing a spell combo + { + spell = DoCombo(c); + } + else if (SmartAI && (c.Spell is HealSpell || c.Spell is GreaterHealSpell) && !c.Poisoned + ) // They have a heal spell out + { + spell = new PoisonSpell(m_Mobile); + } + else + { + spell = ChooseSpell(c); + } + + // Now we have a spell picked + // Move first before casting + + if (SmartAI && toDispel != null) + { + if (m_Mobile.InRange(toDispel, 10)) + RunFrom(toDispel); + else if (!m_Mobile.InRange(toDispel, Core.ML ? 10 : 12)) + RunTo(toDispel); + } + else + { + RunTo(c); + } + + spell?.Cast(); + + m_NextCastTime = Core.TickCount + (int)GetDelay(spell).TotalMilliseconds; + } + else if (m_Mobile.Spell?.IsCasting != true) + { + RunTo(c); + } + + m_LastTarget = c; + m_LastTargetLoc = c.Location; + + return true; + } + + public override bool DoActionGuard() + { + if (m_LastTarget?.Hidden == true) + { + var map = m_Mobile.Map; + + if (map == null || !m_Mobile.InRange(m_LastTargetLoc, Core.ML ? 10 : 12)) + { + m_LastTarget = null; + } + else if (m_Mobile.Spell == null && Core.TickCount - m_NextCastTime >= 0) + { + m_Mobile.DebugSay("I am going to reveal my last target"); + + m_RevealTarget = new LandTarget(m_LastTargetLoc, map); + Spell spell = new RevealSpell(m_Mobile); + + if (spell.Cast()) + m_LastTarget = null; // only do it once + + m_NextCastTime = Core.TickCount + (int)GetDelay(spell).TotalMilliseconds; + } + } + + if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) + { + m_Mobile.DebugSay("I am going to attack {0}", m_Mobile.FocusMob.Name); + + m_Mobile.Combatant = m_Mobile.FocusMob; + Action = ActionType.Combat; + } + else + { + if (!m_Mobile.Controlled) + { + ProcessTarget(); + + var spell = CheckCastHealingSpell(); + + spell?.Cast(); + } + + base.DoActionGuard(); + } + + return true; + } + + public override bool DoActionFlee() + { + // Mobile c = m_Mobile.Combatant; + + if ((m_Mobile.Mana > 20 || m_Mobile.Mana == m_Mobile.ManaMax) && m_Mobile.Hits > m_Mobile.HitsMax / 2) + { + m_Mobile.DebugSay("I am stronger now, my guard is up"); + Action = ActionType.Guard; + } + else if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) + { + m_Mobile.DebugSay("I am scared of {0}", m_Mobile.FocusMob.Name); + + RunFrom(m_Mobile.FocusMob); + m_Mobile.FocusMob = null; + + if (m_Mobile.Poisoned && Utility.Random(0, 5) == 0) + new CureSpell(m_Mobile).Cast(); + } + else + { + m_Mobile.DebugSay("Area seems clear, but my guard is up"); + + Action = ActionType.Guard; + m_Mobile.Warmode = true; + } + + return true; + } + + public Mobile FindDispelTarget(bool activeOnly) + { + if (m_Mobile.Deleted || m_Mobile.Int < 95 || CanDispel(m_Mobile) || m_Mobile.AutoDispel) + return null; + + if (activeOnly) + { + var aggressed = m_Mobile.Aggressed; + var aggressors = m_Mobile.Aggressors; + + Mobile active = null; + var activePrio = 0.0; + + var comb = m_Mobile.Combatant; + + if (comb?.Deleted == false && comb.Alive && !comb.IsDeadBondedPet && + m_Mobile.InRange(comb, Core.ML ? 10 : 12) && CanDispel(comb)) + { + active = comb; + activePrio = m_Mobile.GetDistanceToSqrt(comb); + + if (activePrio <= 2) + return active; + } + + for (var i = 0; i < aggressed.Count; ++i) + { + var info = aggressed[i]; + var m = info.Defender; + + if (m != comb && m.Combatant == m_Mobile && m_Mobile.InRange(m, Core.ML ? 10 : 12) && CanDispel(m)) + { + var prio = m_Mobile.GetDistanceToSqrt(m); + + if (active == null || prio < activePrio) + { + active = m; + activePrio = prio; + + if (activePrio <= 2) + return active; + } + } + } + + for (var i = 0; i < aggressors.Count; ++i) + { + var info = aggressors[i]; + var m = info.Attacker; + + if (m != comb && m.Combatant == m_Mobile && m_Mobile.InRange(m, Core.ML ? 10 : 12) && CanDispel(m)) + { + var prio = m_Mobile.GetDistanceToSqrt(m); + + if (active == null || prio < activePrio) + { + active = m; + activePrio = prio; + + if (activePrio <= 2) + return active; + } + } + } - if (activePrio <= 2) return active; } - } + + var map = m_Mobile.Map; + + if (map != null) + { + Mobile active = null, inactive = null; + double actPrio = 0.0, inactPrio = 0.0; + + var comb = m_Mobile.Combatant; + + if (comb?.Deleted == false && comb.Alive && !comb.IsDeadBondedPet && CanDispel(comb)) + { + active = inactive = comb; + actPrio = inactPrio = m_Mobile.GetDistanceToSqrt(comb); + } + + foreach (var m in m_Mobile.GetMobilesInRange(Core.ML ? 10 : 12)) + if (m != m_Mobile && CanDispel(m)) + { + var prio = m_Mobile.GetDistanceToSqrt(m); + + if (inactive == null || prio < inactPrio) + { + inactive = m; + inactPrio = prio; + } + + if ((m_Mobile.Combatant == m || m.Combatant == m_Mobile) && (active == null || prio < actPrio)) + { + active = m; + actPrio = prio; + } + } + + return active ?? inactive; + } + + return null; } - for (int i = 0; i < aggressors.Count; ++i) + public bool CanDispel(Mobile m) => + m is BaseCreature creature && creature.Summoned && m_Mobile.CanBeHarmful(creature, false) && + !creature.IsAnimatedDead; + + private bool ProcessTarget() { - AggressorInfo info = aggressors[i]; - Mobile m = info.Attacker; + var targ = m_Mobile.Target; - if (m != comb && m.Combatant == m_Mobile && m_Mobile.InRange(m, Core.ML ? 10 : 12) && CanDispel(m)) - { - double prio = m_Mobile.GetDistanceToSqrt(m); + if (targ == null) + return false; - if (active == null || prio < activePrio) + var spellTarg = targ as ISpellTarget; + + var isReveal = spellTarg?.Spell is RevealSpell; + var isDispel = spellTarg?.Spell is DispelSpell; + var isParalyze = spellTarg?.Spell is ParalyzeSpell; + var isTeleport = spellTarg?.Spell is TeleportSpell; + var isInvisible = spellTarg?.Spell is InvisibilitySpell; + var teleportAway = false; + + Mobile toTarget; + + if (isInvisible) { - active = m; - activePrio = prio; - - if (activePrio <= 2) - return active; + toTarget = m_Mobile; } - } + else if (isDispel) + { + toTarget = FindDispelTarget(false); + + if (!SmartAI && toTarget != null) + RunTo(toTarget); + else if (toTarget != null && m_Mobile.InRange(toTarget, 10)) + RunFrom(toTarget); + } + else if (SmartAI && (isParalyze || isTeleport)) + { + toTarget = FindDispelTarget(true); + + if (toTarget == null) + { + toTarget = m_Mobile.Combatant; + + if (toTarget != null) + RunTo(toTarget); + } + else if (m_Mobile.InRange(toTarget, 10)) + { + RunFrom(toTarget); + teleportAway = true; + } + else + { + teleportAway = true; + } + } + else + { + toTarget = m_Mobile.Combatant; + + if (toTarget != null) + RunTo(toTarget); + } + + if ((targ.Flags & TargetFlags.Harmful) != 0 && toTarget != null) + { + if ((targ.Range == -1 || m_Mobile.InRange(toTarget, targ.Range)) && m_Mobile.CanSee(toTarget) && + m_Mobile.InLOS(toTarget)) + targ.Invoke(m_Mobile, toTarget); + else if (isDispel) targ.Cancel(m_Mobile, TargetCancelType.Canceled); + } + else if ((targ.Flags & TargetFlags.Beneficial) != 0) + { + targ.Invoke(m_Mobile, m_Mobile); + } + else if (isReveal && m_RevealTarget != null) + { + targ.Invoke(m_Mobile, m_RevealTarget); + } + else + { + var map = m_Mobile.Map; + + if (map != null && isTeleport && toTarget != null) + { + var teleRange = targ.Range >= 0 ? targ.Range : + Core.ML ? 11 : 12; + + int px, py; + + if (teleportAway) + { + var rx = m_Mobile.X - toTarget.X; + var ry = m_Mobile.Y - toTarget.Y; + + var d = m_Mobile.GetDistanceToSqrt(toTarget); + + px = toTarget.X + (int)(rx * (10 / d)); + py = toTarget.Y + (int)(ry * (10 / d)); + } + else + { + px = toTarget.X; + py = toTarget.Y; + } + + for (var i = 0; i < m_Offsets.Length; i += 2) + { + int x = m_Offsets[i], y = m_Offsets[i + 1]; + + var p = new Point3D(px + x, py + y, 0); + + var lt = new LandTarget(p, map); + + if ((targ.Range == -1 || m_Mobile.InRange(p, targ.Range)) && m_Mobile.InLOS(lt) && + map.CanSpawnMobile(px + x, py + y, lt.Z) && !SpellHelper.CheckMulti(p, map)) + { + targ.Invoke(m_Mobile, lt); + return true; + } + } + + for (var i = 0; i < 10; ++i) + { + var randomPoint = new Point3D( + m_Mobile.X - teleRange + Utility.Random(teleRange * 2 + 1), + m_Mobile.Y - teleRange + Utility.Random(teleRange * 2 + 1), + 0 + ); + + var lt = new LandTarget(randomPoint, map); + + if (m_Mobile.InLOS(lt) && map.CanSpawnMobile(lt.X, lt.Y, lt.Z) && + !SpellHelper.CheckMulti(randomPoint, map)) + { + targ.Invoke(m_Mobile, new LandTarget(randomPoint, map)); + return true; + } + } + } + + targ.Cancel(m_Mobile, TargetCancelType.Canceled); + } + + return true; } - - return active; - } - - Map map = m_Mobile.Map; - - if (map != null) - { - Mobile active = null, inactive = null; - double actPrio = 0.0, inactPrio = 0.0; - - Mobile comb = m_Mobile.Combatant; - - if (comb?.Deleted == false && comb.Alive && !comb.IsDeadBondedPet && CanDispel(comb)) - { - active = inactive = comb; - actPrio = inactPrio = m_Mobile.GetDistanceToSqrt(comb); - } - - foreach (Mobile m in m_Mobile.GetMobilesInRange(Core.ML ? 10 : 12)) - if (m != m_Mobile && CanDispel(m)) - { - double prio = m_Mobile.GetDistanceToSqrt(m); - - if (inactive == null || prio < inactPrio) - { - inactive = m; - inactPrio = prio; - } - - if ((m_Mobile.Combatant == m || m.Combatant == m_Mobile) && (active == null || prio < actPrio)) - { - active = m; - actPrio = prio; - } - } - - return active ?? inactive; - } - - return null; } - - public bool CanDispel(Mobile m) => - m is BaseCreature creature && creature.Summoned && m_Mobile.CanBeHarmful(creature, false) && - !creature.IsAnimatedDead; - - private bool ProcessTarget() - { - Target targ = m_Mobile.Target; - - if (targ == null) - return false; - - ISpellTarget spellTarg = targ as ISpellTarget; - - bool isReveal = spellTarg?.Spell is RevealSpell; - bool isDispel = spellTarg?.Spell is DispelSpell; - bool isParalyze = spellTarg?.Spell is ParalyzeSpell; - bool isTeleport = spellTarg?.Spell is TeleportSpell; - bool isInvisible = spellTarg?.Spell is InvisibilitySpell; - bool teleportAway = false; - - Mobile toTarget; - - if (isInvisible) - { - toTarget = m_Mobile; - } - else if (isDispel) - { - toTarget = FindDispelTarget(false); - - if (!SmartAI && toTarget != null) - RunTo(toTarget); - else if (toTarget != null && m_Mobile.InRange(toTarget, 10)) - RunFrom(toTarget); - } - else if (SmartAI && (isParalyze || isTeleport)) - { - toTarget = FindDispelTarget(true); - - if (toTarget == null) - { - toTarget = m_Mobile.Combatant; - - if (toTarget != null) - RunTo(toTarget); - } - else if (m_Mobile.InRange(toTarget, 10)) - { - RunFrom(toTarget); - teleportAway = true; - } - else - { - teleportAway = true; - } - } - else - { - toTarget = m_Mobile.Combatant; - - if (toTarget != null) - RunTo(toTarget); - } - - if ((targ.Flags & TargetFlags.Harmful) != 0 && toTarget != null) - { - if ((targ.Range == -1 || m_Mobile.InRange(toTarget, targ.Range)) && m_Mobile.CanSee(toTarget) && - m_Mobile.InLOS(toTarget)) - targ.Invoke(m_Mobile, toTarget); - else if (isDispel) targ.Cancel(m_Mobile, TargetCancelType.Canceled); - } - else if ((targ.Flags & TargetFlags.Beneficial) != 0) - { - targ.Invoke(m_Mobile, m_Mobile); - } - else if (isReveal && m_RevealTarget != null) - { - targ.Invoke(m_Mobile, m_RevealTarget); - } - else - { - Map map = m_Mobile.Map; - - if (map != null && isTeleport && toTarget != null) - { - int teleRange = targ.Range >= 0 ? targ.Range : Core.ML ? 11 : 12; - - int px, py; - - if (teleportAway) - { - int rx = m_Mobile.X - toTarget.X; - int ry = m_Mobile.Y - toTarget.Y; - - double d = m_Mobile.GetDistanceToSqrt(toTarget); - - px = toTarget.X + (int)(rx * (10 / d)); - py = toTarget.Y + (int)(ry * (10 / d)); - } - else - { - px = toTarget.X; - py = toTarget.Y; - } - - for (int i = 0; i < m_Offsets.Length; i += 2) - { - int x = m_Offsets[i], y = m_Offsets[i + 1]; - - Point3D p = new Point3D(px + x, py + y, 0); - - LandTarget lt = new LandTarget(p, map); - - if ((targ.Range == -1 || m_Mobile.InRange(p, targ.Range)) && m_Mobile.InLOS(lt) && - map.CanSpawnMobile(px + x, py + y, lt.Z) && !SpellHelper.CheckMulti(p, map)) - { - targ.Invoke(m_Mobile, lt); - return true; - } - } - - for (int i = 0; i < 10; ++i) - { - Point3D randomPoint = new Point3D(m_Mobile.X - teleRange + Utility.Random(teleRange * 2 + 1), - m_Mobile.Y - teleRange + Utility.Random(teleRange * 2 + 1), 0); - - LandTarget lt = new LandTarget(randomPoint, map); - - if (m_Mobile.InLOS(lt) && map.CanSpawnMobile(lt.X, lt.Y, lt.Z) && - !SpellHelper.CheckMulti(randomPoint, map)) - { - targ.Invoke(m_Mobile, new LandTarget(randomPoint, map)); - return true; - } - } - } - - targ.Cancel(m_Mobile, TargetCancelType.Canceled); - } - - return true; - } - } } diff --git a/Projects/UOContent/Mobiles/AI/MeleeAI.cs b/Projects/UOContent/Mobiles/AI/MeleeAI.cs index 50031e314..ae05784df 100644 --- a/Projects/UOContent/Mobiles/AI/MeleeAI.cs +++ b/Projects/UOContent/Mobiles/AI/MeleeAI.cs @@ -1,172 +1,172 @@ namespace Server.Mobiles { - public class MeleeAI : BaseAI - { - public MeleeAI(BaseCreature m) : base(m) + public class MeleeAI : BaseAI { - } - - public override bool DoActionWander() - { - m_Mobile.DebugSay("I have no combatant"); - - if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) - { - if (m_Mobile.Debug) - m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name); - - m_Mobile.Combatant = m_Mobile.FocusMob; - Action = ActionType.Combat; - } - else - { - base.DoActionWander(); - } - - return true; - } - - public override bool DoActionCombat() - { - Mobile combatant = m_Mobile.Combatant; - - if (combatant?.Deleted != false || combatant.Map != m_Mobile.Map || !combatant.Alive || - combatant.IsDeadBondedPet) - { - m_Mobile.DebugSay("My combatant is gone, so my guard is up"); - - Action = ActionType.Guard; - - return true; - } - - if (!m_Mobile.InRange(combatant, m_Mobile.RangePerception)) - { - // They are somewhat far away, can we find something else? - - if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) + public MeleeAI(BaseCreature m) : base(m) { - m_Mobile.Combatant = m_Mobile.FocusMob; - m_Mobile.FocusMob = null; - } - else if (!m_Mobile.InRange(combatant, m_Mobile.RangePerception * 3)) - { - m_Mobile.Combatant = null; } - combatant = m_Mobile.Combatant; - - if (combatant == null) + public override bool DoActionWander() { - m_Mobile.DebugSay("My combatant has fled, so I am on guard"); - Action = ActionType.Guard; + m_Mobile.DebugSay("I have no combatant"); - return true; - } - } + if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) + { + if (m_Mobile.Debug) + m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name); - /*if (!m_Mobile.InLOS( combatant )) - { - if (AcquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true )) - { - m_Mobile.Combatant = combatant = m_Mobile.FocusMob; - m_Mobile.FocusMob = null; - } - }*/ + m_Mobile.Combatant = m_Mobile.FocusMob; + Action = ActionType.Combat; + } + else + { + base.DoActionWander(); + } - if (MoveTo(combatant, true, m_Mobile.RangeFight)) - { - m_Mobile.Direction = m_Mobile.GetDirectionTo(combatant); - } - else if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) - { - if (m_Mobile.Debug) - m_Mobile.DebugSay("My move is blocked, so I am going to attack {0}", m_Mobile.FocusMob.Name); - - m_Mobile.Combatant = m_Mobile.FocusMob; - Action = ActionType.Combat; - - return true; - } - else if (m_Mobile.GetDistanceToSqrt(combatant) > m_Mobile.RangePerception + 1) - { - if (m_Mobile.Debug) - m_Mobile.DebugSay("I cannot find {0}, so my guard is up", combatant.Name); - - Action = ActionType.Guard; - - return true; - } - else - { - if (m_Mobile.Debug) - m_Mobile.DebugSay("I should be closer to {0}", combatant.Name); - } - - if (!m_Mobile.Controlled && !m_Mobile.Summoned && m_Mobile.CanFlee) - if (m_Mobile.Hits < m_Mobile.HitsMax * 20 / 100) - { - // We are low on health, should we flee? - - bool flee = false; - - if (m_Mobile.Hits < combatant.Hits) - { - // We are more hurt than them - - int diff = combatant.Hits - m_Mobile.Hits; - - flee = Utility.Random(0, 100) < 10 + diff; // (10 + diff)% chance to flee - } - else - { - flee = Utility.Random(0, 100) < 10; // 10% chance to flee - } - - if (flee) - { - if (m_Mobile.Debug) - m_Mobile.DebugSay("I am going to flee from {0}", combatant.Name); - - Action = ActionType.Flee; - } + return true; } - return true; + public override bool DoActionCombat() + { + var combatant = m_Mobile.Combatant; + + if (combatant?.Deleted != false || combatant.Map != m_Mobile.Map || !combatant.Alive || + combatant.IsDeadBondedPet) + { + m_Mobile.DebugSay("My combatant is gone, so my guard is up"); + + Action = ActionType.Guard; + + return true; + } + + if (!m_Mobile.InRange(combatant, m_Mobile.RangePerception)) + { + // They are somewhat far away, can we find something else? + + if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) + { + m_Mobile.Combatant = m_Mobile.FocusMob; + m_Mobile.FocusMob = null; + } + else if (!m_Mobile.InRange(combatant, m_Mobile.RangePerception * 3)) + { + m_Mobile.Combatant = null; + } + + combatant = m_Mobile.Combatant; + + if (combatant == null) + { + m_Mobile.DebugSay("My combatant has fled, so I am on guard"); + Action = ActionType.Guard; + + return true; + } + } + + /*if (!m_Mobile.InLOS( combatant )) + { + if (AcquireFocusMob( m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true )) + { + m_Mobile.Combatant = combatant = m_Mobile.FocusMob; + m_Mobile.FocusMob = null; + } + }*/ + + if (MoveTo(combatant, true, m_Mobile.RangeFight)) + { + m_Mobile.Direction = m_Mobile.GetDirectionTo(combatant); + } + else if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) + { + if (m_Mobile.Debug) + m_Mobile.DebugSay("My move is blocked, so I am going to attack {0}", m_Mobile.FocusMob.Name); + + m_Mobile.Combatant = m_Mobile.FocusMob; + Action = ActionType.Combat; + + return true; + } + else if (m_Mobile.GetDistanceToSqrt(combatant) > m_Mobile.RangePerception + 1) + { + if (m_Mobile.Debug) + m_Mobile.DebugSay("I cannot find {0}, so my guard is up", combatant.Name); + + Action = ActionType.Guard; + + return true; + } + else + { + if (m_Mobile.Debug) + m_Mobile.DebugSay("I should be closer to {0}", combatant.Name); + } + + if (!m_Mobile.Controlled && !m_Mobile.Summoned && m_Mobile.CanFlee) + if (m_Mobile.Hits < m_Mobile.HitsMax * 20 / 100) + { + // We are low on health, should we flee? + + var flee = false; + + if (m_Mobile.Hits < combatant.Hits) + { + // We are more hurt than them + + var diff = combatant.Hits - m_Mobile.Hits; + + flee = Utility.Random(0, 100) < 10 + diff; // (10 + diff)% chance to flee + } + else + { + flee = Utility.Random(0, 100) < 10; // 10% chance to flee + } + + if (flee) + { + if (m_Mobile.Debug) + m_Mobile.DebugSay("I am going to flee from {0}", combatant.Name); + + Action = ActionType.Flee; + } + } + + return true; + } + + public override bool DoActionGuard() + { + if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) + { + if (m_Mobile.Debug) + m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name); + + m_Mobile.Combatant = m_Mobile.FocusMob; + Action = ActionType.Combat; + } + else + { + base.DoActionGuard(); + } + + return true; + } + + public override bool DoActionFlee() + { + if (m_Mobile.Hits > m_Mobile.HitsMax / 2) + { + m_Mobile.DebugSay("I am stronger now, so I will continue fighting"); + Action = ActionType.Combat; + } + else + { + m_Mobile.FocusMob = m_Mobile.Combatant; + base.DoActionFlee(); + } + + return true; + } } - - public override bool DoActionGuard() - { - if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) - { - if (m_Mobile.Debug) - m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name); - - m_Mobile.Combatant = m_Mobile.FocusMob; - Action = ActionType.Combat; - } - else - { - base.DoActionGuard(); - } - - return true; - } - - public override bool DoActionFlee() - { - if (m_Mobile.Hits > m_Mobile.HitsMax / 2) - { - m_Mobile.DebugSay("I am stronger now, so I will continue fighting"); - Action = ActionType.Combat; - } - else - { - m_Mobile.FocusMob = m_Mobile.Combatant; - base.DoActionFlee(); - } - - return true; - } - } } diff --git a/Projects/UOContent/Mobiles/AI/OppositionGroup.cs b/Projects/UOContent/Mobiles/AI/OppositionGroup.cs index e8488d2e9..607b27d92 100644 --- a/Projects/UOContent/Mobiles/AI/OppositionGroup.cs +++ b/Projects/UOContent/Mobiles/AI/OppositionGroup.cs @@ -3,121 +3,127 @@ using Server.Mobiles; namespace Server { - public class OppositionGroup - { - private readonly Type[][] m_Types; - - public OppositionGroup(Type[][] types) => m_Types = types; - - public static OppositionGroup TerathansAndOphidians { get; } = new OppositionGroup(new[] + public class OppositionGroup { - new[] - { - typeof(TerathanAvenger), - typeof(TerathanDrone), - typeof(TerathanMatriarch), - typeof(TerathanWarrior) - }, - new[] - { - typeof(OphidianArchmage), - typeof(OphidianKnight), - typeof(OphidianMage), - typeof(OphidianMatriarch), - typeof(OphidianWarrior) - } - }); + private readonly Type[][] m_Types; - public static OppositionGroup SavagesAndOrcs { get; } = new OppositionGroup(new[] - { - new[] - { - typeof(Orc), - typeof(OrcBomber), - typeof(OrcBrute), - typeof(OrcCaptain), - typeof(OrcishLord), - typeof(OrcishMage), - typeof(SpawnedOrcishLord) - }, - new[] - { - typeof(Savage), - typeof(SavageRider), - typeof(SavageRidgeback), - typeof(SavageShaman) - } - }); + public OppositionGroup(Type[][] types) => m_Types = types; - public static OppositionGroup FeyAndUndead { get; } = new OppositionGroup(new[] - { - new[] - { - typeof(Centaur), - typeof(EtherealWarrior), - typeof(Kirin), - typeof(LordOaks), - typeof(Pixie), - typeof(Silvani), - typeof(Unicorn), - typeof(Wisp), - typeof(Treefellow), - typeof(MLDryad), - typeof(Satyr) - }, - new[] - { - typeof(AncientLich), - typeof(Bogle), - typeof(LichLord), - typeof(Shade), - typeof(Spectre), - typeof(Wraith), - typeof(BoneKnight), - typeof(Ghoul), - typeof(Mummy), - typeof(SkeletalKnight), - typeof(Skeleton), - typeof(Zombie), - typeof(ShadowKnight), - typeof(DarknightCreeper), - typeof(RevenantLion), - typeof(LadyOfTheSnow), - typeof(RottingCorpse), - typeof(SkeletalDragon), - typeof(Lich) - } - }); + public static OppositionGroup TerathansAndOphidians { get; } = new OppositionGroup( + new[] + { + new[] + { + typeof(TerathanAvenger), + typeof(TerathanDrone), + typeof(TerathanMatriarch), + typeof(TerathanWarrior) + }, + new[] + { + typeof(OphidianArchmage), + typeof(OphidianKnight), + typeof(OphidianMage), + typeof(OphidianMatriarch), + typeof(OphidianWarrior) + } + } + ); - public bool IsEnemy(object from, object target) - { - int fromGroup = IndexOf(from); - int targGroup = IndexOf(target); + public static OppositionGroup SavagesAndOrcs { get; } = new OppositionGroup( + new[] + { + new[] + { + typeof(Orc), + typeof(OrcBomber), + typeof(OrcBrute), + typeof(OrcCaptain), + typeof(OrcishLord), + typeof(OrcishMage), + typeof(SpawnedOrcishLord) + }, + new[] + { + typeof(Savage), + typeof(SavageRider), + typeof(SavageRidgeback), + typeof(SavageShaman) + } + } + ); - return fromGroup != -1 && targGroup != -1 && fromGroup != targGroup; + public static OppositionGroup FeyAndUndead { get; } = new OppositionGroup( + new[] + { + new[] + { + typeof(Centaur), + typeof(EtherealWarrior), + typeof(Kirin), + typeof(LordOaks), + typeof(Pixie), + typeof(Silvani), + typeof(Unicorn), + typeof(Wisp), + typeof(Treefellow), + typeof(MLDryad), + typeof(Satyr) + }, + new[] + { + typeof(AncientLich), + typeof(Bogle), + typeof(LichLord), + typeof(Shade), + typeof(Spectre), + typeof(Wraith), + typeof(BoneKnight), + typeof(Ghoul), + typeof(Mummy), + typeof(SkeletalKnight), + typeof(Skeleton), + typeof(Zombie), + typeof(ShadowKnight), + typeof(DarknightCreeper), + typeof(RevenantLion), + typeof(LadyOfTheSnow), + typeof(RottingCorpse), + typeof(SkeletalDragon), + typeof(Lich) + } + } + ); + + public bool IsEnemy(object from, object target) + { + var fromGroup = IndexOf(from); + var targGroup = IndexOf(target); + + return fromGroup != -1 && targGroup != -1 && fromGroup != targGroup; + } + + public int IndexOf(object obj) + { + if (obj == null) + return -1; + + var type = obj.GetType(); + + for (var i = 0; i < m_Types.Length; ++i) + { + var group = m_Types[i]; + + var contains = false; + + for (var j = 0; !contains && j < group.Length; ++j) + contains = group[j].IsAssignableFrom(type); + + if (contains) + return i; + } + + return -1; + } } - - public int IndexOf(object obj) - { - if (obj == null) - return -1; - - Type type = obj.GetType(); - - for (int i = 0; i < m_Types.Length; ++i) - { - Type[] group = m_Types[i]; - - bool contains = false; - - for (int j = 0; !contains && j < group.Length; ++j) - contains = group[j].IsAssignableFrom(type); - - if (contains) - return i; - } - - return -1; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/AI/PredatorAI.cs b/Projects/UOContent/Mobiles/AI/PredatorAI.cs index 9ac47e3bd..3991d6354 100644 --- a/Projects/UOContent/Mobiles/AI/PredatorAI.cs +++ b/Projects/UOContent/Mobiles/AI/PredatorAI.cs @@ -1,86 +1,86 @@ namespace Server.Mobiles { - public class PredatorAI : BaseAI - { - public PredatorAI(BaseCreature m) : base(m) + public class PredatorAI : BaseAI { - } - - public override bool DoActionWander() - { - if (m_Mobile.Combatant != null) - { - m_Mobile.DebugSay("I am hurt or being attacked, I kill him"); - Action = ActionType.Combat; - } - else if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, true, false, true)) - { - m_Mobile.DebugSay("There is something near, I go away"); - Action = ActionType.Backoff; - } - else - { - base.DoActionWander(); - } - - return true; - } - - public override bool DoActionCombat() - { - Mobile combatant = m_Mobile.Combatant; - - if (combatant?.Deleted != false || combatant.Map != m_Mobile.Map) - { - m_Mobile.DebugSay("My combatant is gone, so my guard is up"); - Action = ActionType.Wander; - return true; - } - - if (WalkMobileRange(combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight)) - { - m_Mobile.Direction = m_Mobile.GetDirectionTo(combatant); - } - else - { - if (m_Mobile.GetDistanceToSqrt(combatant) > m_Mobile.RangePerception + 1) + public PredatorAI(BaseCreature m) : base(m) { - m_Mobile.DebugSay("I cannot find {0}", combatant.Name); - - Action = ActionType.Wander; - return true; } - m_Mobile.DebugSay("I should be closer to {0}", combatant.Name); - } - - return true; - } - - public override bool DoActionBackoff() - { - if (m_Mobile.IsHurt() || m_Mobile.Combatant != null) - { - Action = ActionType.Combat; - } - else - { - if (AcquireFocusMob(m_Mobile.RangePerception * 2, FightMode.Closest, true, false, true)) + public override bool DoActionWander() { - if (WalkMobileRange(m_Mobile.FocusMob, 1, false, m_Mobile.RangePerception, m_Mobile.RangePerception * 2)) - { - m_Mobile.DebugSay("Well, here I am safe"); - Action = ActionType.Wander; - } - } - else - { - m_Mobile.DebugSay("I have lost my focus, lets relax"); - Action = ActionType.Wander; - } - } + if (m_Mobile.Combatant != null) + { + m_Mobile.DebugSay("I am hurt or being attacked, I kill him"); + Action = ActionType.Combat; + } + else if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, true, false, true)) + { + m_Mobile.DebugSay("There is something near, I go away"); + Action = ActionType.Backoff; + } + else + { + base.DoActionWander(); + } - return true; + return true; + } + + public override bool DoActionCombat() + { + var combatant = m_Mobile.Combatant; + + if (combatant?.Deleted != false || combatant.Map != m_Mobile.Map) + { + m_Mobile.DebugSay("My combatant is gone, so my guard is up"); + Action = ActionType.Wander; + return true; + } + + if (WalkMobileRange(combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight)) + { + m_Mobile.Direction = m_Mobile.GetDirectionTo(combatant); + } + else + { + if (m_Mobile.GetDistanceToSqrt(combatant) > m_Mobile.RangePerception + 1) + { + m_Mobile.DebugSay("I cannot find {0}", combatant.Name); + + Action = ActionType.Wander; + return true; + } + + m_Mobile.DebugSay("I should be closer to {0}", combatant.Name); + } + + return true; + } + + public override bool DoActionBackoff() + { + if (m_Mobile.IsHurt() || m_Mobile.Combatant != null) + { + Action = ActionType.Combat; + } + else + { + if (AcquireFocusMob(m_Mobile.RangePerception * 2, FightMode.Closest, true, false, true)) + { + if (WalkMobileRange(m_Mobile.FocusMob, 1, false, m_Mobile.RangePerception, m_Mobile.RangePerception * 2)) + { + m_Mobile.DebugSay("Well, here I am safe"); + Action = ActionType.Wander; + } + } + else + { + m_Mobile.DebugSay("I have lost my focus, lets relax"); + Action = ActionType.Wander; + } + } + + return true; + } } - } } diff --git a/Projects/UOContent/Mobiles/AI/SpeedInfo.cs b/Projects/UOContent/Mobiles/AI/SpeedInfo.cs index 562d8c5d6..6d1b7fd9c 100644 --- a/Projects/UOContent/Mobiles/AI/SpeedInfo.cs +++ b/Projects/UOContent/Mobiles/AI/SpeedInfo.cs @@ -5,196 +5,212 @@ using Server.Mobiles; namespace Server { - public class SpeedInfo - { - // Should we use the new method of speeds? - private static readonly bool Enabled = true; - - private static Dictionary m_Table; - - private static readonly SpeedInfo[] m_Speeds = + public class SpeedInfo { - /* Slow */ - new SpeedInfo(0.3, 0.6, new[] - { - typeof(AntLion), typeof(ArcticOgreLord), typeof(BogThing), - typeof(Bogle), typeof(BoneKnight), typeof(EarthElemental), - typeof(Ettin), typeof(FrostOoze), typeof(FrostTroll), - typeof(GazerLarva), typeof(Ghoul), typeof(Golem), - typeof(HeadlessOne), typeof(Jwilson), typeof(Mummy), - typeof(Ogre), typeof(OgreLord), typeof(PlagueBeast), - typeof(Quagmire), typeof(Rat), typeof(RottingCorpse), - typeof(SewerRat), typeof(Skeleton), typeof(Slime), - typeof(Zombie), typeof(Walrus), typeof(RestlessSoul), - typeof(CrystalElemental), typeof(DarknightCreeper), typeof(MoundOfMaggots), - typeof(Juggernaut), typeof(Yamandon), typeof(Serado) - }), - /* Fast */ - new SpeedInfo(0.2, 0.4, new[] - { - typeof(LordOaks), typeof(Silvani), typeof(AirElemental), - typeof(AncientWyrm), typeof(Balron), typeof(BladeSpirits), - typeof(DreadSpider), typeof(Efreet), typeof(EtherealWarrior), - typeof(Lich), typeof(Nightmare), typeof(OphidianArchmage), - typeof(OphidianMage), typeof(OphidianWarrior), typeof(OphidianMatriarch), - typeof(OphidianKnight), typeof(PoisonElemental), typeof(Revenant), - typeof(SandVortex), typeof(SavageRider), typeof(SavageShaman), - typeof(SnowElemental), typeof(WhiteWyrm), typeof(Wisp), - typeof(DemonKnight), typeof(GiantBlackWidow), typeof(SummonedAirElemental), - typeof(LesserHiryu), typeof(Hiryu), typeof(LadyOfTheSnow), - typeof(RaiJu), typeof(Ronin), typeof(RuneBeetle), - typeof(Changeling), typeof(LadyJennifyr), typeof(LadyMarai), typeof(MasterJonath), - typeof(MasterMikael), typeof(MasterTheophilus), typeof(RedDeath), - typeof(SirPatrick), typeof(Miasma), typeof(Rend), - typeof(Grobu), typeof(Gnaw), typeof(Guile), - typeof(Irk), typeof(Spite), typeof(LadyLissith), - typeof(LadySabrix), typeof(Malefic), typeof(Silk), - typeof(Virulent) - // TODO: Where to put Lurg, Putrefier, Swoop and Pyre? They seem slower. - }), - /* Very Fast */ - new SpeedInfo(0.175, 0.350, new[] - { - typeof(Barracoon), typeof(Mephitis), typeof(Neira), - typeof(Rikktor), typeof(Semidar), typeof(EnergyVortex), - typeof(EliteNinja), typeof(Pixie), typeof(SilverSerpent), - typeof(VorpalBunny), typeof(FleshRenderer), typeof(KhaldunRevenant), - typeof(FactionDragoon), typeof(FactionKnight), typeof(FactionPaladin), - typeof(FactionHenchman), typeof(FactionMercenary), typeof(FactionNecromancer), - typeof(FactionSorceress), typeof(FactionWizard), typeof(FactionBerserker), - typeof(FactionPaladin), typeof(Leviathan), typeof(FireBeetle), - typeof(FanDancer), typeof(FactionDeathKnight) - }), - /* Medium */ - new SpeedInfo(0.25, 0.5, new[] - { - typeof(AcidElemental), typeof(AgapiteElemental), typeof(Alligator), - typeof(AncientLich), typeof(Betrayer), typeof(Bird), - typeof(BlackBear), typeof(BlackSolenInfiltratorQueen), typeof(BlackSolenInfiltratorWarrior), - typeof(BlackSolenQueen), typeof(BlackSolenWarrior), typeof(BlackSolenWorker), - typeof(BloodElemental), typeof(Boar), typeof(Bogling), - typeof(BoneMagi), typeof(Brigand), typeof(BronzeElemental), - typeof(BrownBear), typeof(Bull), typeof(BullFrog), - typeof(Cat), typeof(Centaur), typeof(ChaosDaemon), - typeof(Chicken), typeof(GolemController), typeof(CopperElemental), - typeof(CopperElemental), typeof(Cougar), typeof(Cow), - typeof(Cyclops), typeof(Daemon), typeof(DeepSeaSerpent), - typeof(DesertOstard), typeof(DireWolf), typeof(Dog), - typeof(Dolphin), typeof(Dragon), typeof(Drake), - typeof(DullCopperElemental), typeof(Eagle), typeof(ElderGazer), - typeof(EvilMage), typeof(EvilMageLord), typeof(Executioner), - typeof(Savage), typeof(FireElemental), typeof(FireGargoyle), - typeof(FireSteed), typeof(ForestOstard), typeof(FrenziedOstard), - typeof(FrostSpider), typeof(Gargoyle), typeof(Gazer), - typeof(IceSerpent), typeof(GiantRat), typeof(GiantSerpent), - typeof(GiantSpider), typeof(GiantToad), typeof(Goat), - typeof(GoldenElemental), typeof(Gorilla), typeof(GreatHart), - typeof(GreyWolf), typeof(GrizzlyBear), typeof(Guardian), - typeof(Harpy), typeof(Harrower), typeof(HellHound), - typeof(Hind), typeof(HordeMinion), typeof(Horse), - typeof(Horse), typeof(IceElemental), typeof(IceFiend), - typeof(IceSnake), typeof(Imp), typeof(JackRabbit), - typeof(Kirin), typeof(Kraken), typeof(PredatorHellCat), - typeof(LavaLizard), typeof(LavaSerpent), typeof(LavaSnake), - typeof(Lizardman), typeof(Llama), typeof(Mongbat), - typeof(StrongMongbat), typeof(MountainGoat), typeof(Orc), - typeof(OrcBomber), typeof(OrcBrute), typeof(OrcCaptain), - typeof(OrcishLord), typeof(OrcishMage), typeof(PackHorse), - typeof(PackLlama), typeof(Panther), typeof(Pig), - typeof(PlagueSpawn), typeof(PolarBear), typeof(Rabbit), - typeof(Ratman), typeof(RatmanArcher), typeof(RatmanMage), - typeof(RedSolenInfiltratorQueen), typeof(RedSolenInfiltratorWarrior), typeof(RedSolenQueen), - typeof(RedSolenWarrior), typeof(RedSolenWorker), typeof(RidableLlama), - typeof(Ridgeback), typeof(Scorpion), typeof(SeaSerpent), - typeof(SerpentineDragon), typeof(Shade), typeof(ShadowIronElemental), - typeof(ShadowWisp), typeof(ShadowWyrm), typeof(Sheep), - typeof(SilverSteed), typeof(SkeletalDragon), typeof(SkeletalMage), - typeof(SkeletalMount), typeof(HellCat), typeof(Snake), - typeof(SnowLeopard), typeof(SpectralArmour), typeof(Spectre), - typeof(StoneGargoyle), typeof(StoneHarpy), typeof(SwampDragon), - typeof(ScaledSwampDragon), typeof(SwampTentacle), typeof(TerathanAvenger), - typeof(TerathanDrone), typeof(TerathanMatriarch), typeof(TerathanWarrior), - typeof(TimberWolf), typeof(Titan), typeof(Troll), - typeof(Unicorn), typeof(ValoriteElemental), typeof(VeriteElemental), - typeof(CoMWarHorse), typeof(MinaxWarHorse), typeof(SLWarHorse), - typeof(TBWarHorse), typeof(WaterElemental), typeof(WhippingVine), - typeof(WhiteWolf), typeof(Wraith), typeof(Wyvern), - typeof(KhaldunZealot), typeof(KhaldunSummoner), typeof(SavageRidgeback), - typeof(LichLord), typeof(SkeletalKnight), typeof(SummonedDaemon), - typeof(SummonedEarthElemental), typeof(SummonedWaterElemental), typeof(SummonedFireElemental), - typeof(MeerWarrior), typeof(MeerEternal), typeof(MeerMage), - typeof(MeerCaptain), typeof(JukaLord), typeof(JukaMage), - typeof(JukaWarrior), typeof(AbysmalHorror), typeof(BoneDemon), - typeof(Devourer), typeof(FleshGolem), typeof(Gibberling), - typeof(GoreFiend), typeof(Impaler), typeof(PatchworkSkeleton), - typeof(Ravager), typeof(ShadowKnight), typeof(SkitteringHopper), - typeof(Treefellow), typeof(VampireBat), typeof(WailingBanshee), - typeof(WandererOfTheVoid), typeof(Cursed), typeof(GrimmochDrummel), - typeof(LysanderGathenwale), typeof(MorgBergen), typeof(ShadowFiend), - typeof(SpectralArmour), typeof(TavaraSewel), typeof(ArcaneDaemon), - typeof(Doppleganger), typeof(EnslavedGargoyle), typeof(ExodusMinion), - typeof(ExodusOverseer), typeof(GargoyleDestroyer), typeof(GargoyleEnforcer), - typeof(Moloch), typeof(BakeKitsune), typeof(DeathwatchBeetleHatchling), - typeof(Kappa), typeof(KazeKemono), typeof(DeathwatchBeetle), - typeof(TsukiWolf), typeof(YomotsuElder), typeof(YomotsuPriest), - typeof(YomotsuWarrior), typeof(RevenantLion), typeof(Oni), - typeof(Gaman), typeof(Crane), typeof(Beetle) - }) - }; + // Should we use the new method of speeds? + private static readonly bool Enabled = true; - public SpeedInfo(double activeSpeed, double passiveSpeed, Type[] types) - { - ActiveSpeed = activeSpeed; - PassiveSpeed = passiveSpeed; - Types = types; + private static Dictionary m_Table; + + private static readonly SpeedInfo[] m_Speeds = + { + /* Slow */ + new SpeedInfo( + 0.3, + 0.6, + new[] + { + typeof(AntLion), typeof(ArcticOgreLord), typeof(BogThing), + typeof(Bogle), typeof(BoneKnight), typeof(EarthElemental), + typeof(Ettin), typeof(FrostOoze), typeof(FrostTroll), + typeof(GazerLarva), typeof(Ghoul), typeof(Golem), + typeof(HeadlessOne), typeof(Jwilson), typeof(Mummy), + typeof(Ogre), typeof(OgreLord), typeof(PlagueBeast), + typeof(Quagmire), typeof(Rat), typeof(RottingCorpse), + typeof(SewerRat), typeof(Skeleton), typeof(Slime), + typeof(Zombie), typeof(Walrus), typeof(RestlessSoul), + typeof(CrystalElemental), typeof(DarknightCreeper), typeof(MoundOfMaggots), + typeof(Juggernaut), typeof(Yamandon), typeof(Serado) + } + ), + /* Fast */ + new SpeedInfo( + 0.2, + 0.4, + new[] + { + typeof(LordOaks), typeof(Silvani), typeof(AirElemental), + typeof(AncientWyrm), typeof(Balron), typeof(BladeSpirits), + typeof(DreadSpider), typeof(Efreet), typeof(EtherealWarrior), + typeof(Lich), typeof(Nightmare), typeof(OphidianArchmage), + typeof(OphidianMage), typeof(OphidianWarrior), typeof(OphidianMatriarch), + typeof(OphidianKnight), typeof(PoisonElemental), typeof(Revenant), + typeof(SandVortex), typeof(SavageRider), typeof(SavageShaman), + typeof(SnowElemental), typeof(WhiteWyrm), typeof(Wisp), + typeof(DemonKnight), typeof(GiantBlackWidow), typeof(SummonedAirElemental), + typeof(LesserHiryu), typeof(Hiryu), typeof(LadyOfTheSnow), + typeof(RaiJu), typeof(Ronin), typeof(RuneBeetle), + typeof(Changeling), typeof(LadyJennifyr), typeof(LadyMarai), typeof(MasterJonath), + typeof(MasterMikael), typeof(MasterTheophilus), typeof(RedDeath), + typeof(SirPatrick), typeof(Miasma), typeof(Rend), + typeof(Grobu), typeof(Gnaw), typeof(Guile), + typeof(Irk), typeof(Spite), typeof(LadyLissith), + typeof(LadySabrix), typeof(Malefic), typeof(Silk), + typeof(Virulent) + // TODO: Where to put Lurg, Putrefier, Swoop and Pyre? They seem slower. + } + ), + /* Very Fast */ + new SpeedInfo( + 0.175, + 0.350, + new[] + { + typeof(Barracoon), typeof(Mephitis), typeof(Neira), + typeof(Rikktor), typeof(Semidar), typeof(EnergyVortex), + typeof(EliteNinja), typeof(Pixie), typeof(SilverSerpent), + typeof(VorpalBunny), typeof(FleshRenderer), typeof(KhaldunRevenant), + typeof(FactionDragoon), typeof(FactionKnight), typeof(FactionPaladin), + typeof(FactionHenchman), typeof(FactionMercenary), typeof(FactionNecromancer), + typeof(FactionSorceress), typeof(FactionWizard), typeof(FactionBerserker), + typeof(FactionPaladin), typeof(Leviathan), typeof(FireBeetle), + typeof(FanDancer), typeof(FactionDeathKnight) + } + ), + /* Medium */ + new SpeedInfo( + 0.25, + 0.5, + new[] + { + typeof(AcidElemental), typeof(AgapiteElemental), typeof(Alligator), + typeof(AncientLich), typeof(Betrayer), typeof(Bird), + typeof(BlackBear), typeof(BlackSolenInfiltratorQueen), typeof(BlackSolenInfiltratorWarrior), + typeof(BlackSolenQueen), typeof(BlackSolenWarrior), typeof(BlackSolenWorker), + typeof(BloodElemental), typeof(Boar), typeof(Bogling), + typeof(BoneMagi), typeof(Brigand), typeof(BronzeElemental), + typeof(BrownBear), typeof(Bull), typeof(BullFrog), + typeof(Cat), typeof(Centaur), typeof(ChaosDaemon), + typeof(Chicken), typeof(GolemController), typeof(CopperElemental), + typeof(CopperElemental), typeof(Cougar), typeof(Cow), + typeof(Cyclops), typeof(Daemon), typeof(DeepSeaSerpent), + typeof(DesertOstard), typeof(DireWolf), typeof(Dog), + typeof(Dolphin), typeof(Dragon), typeof(Drake), + typeof(DullCopperElemental), typeof(Eagle), typeof(ElderGazer), + typeof(EvilMage), typeof(EvilMageLord), typeof(Executioner), + typeof(Savage), typeof(FireElemental), typeof(FireGargoyle), + typeof(FireSteed), typeof(ForestOstard), typeof(FrenziedOstard), + typeof(FrostSpider), typeof(Gargoyle), typeof(Gazer), + typeof(IceSerpent), typeof(GiantRat), typeof(GiantSerpent), + typeof(GiantSpider), typeof(GiantToad), typeof(Goat), + typeof(GoldenElemental), typeof(Gorilla), typeof(GreatHart), + typeof(GreyWolf), typeof(GrizzlyBear), typeof(Guardian), + typeof(Harpy), typeof(Harrower), typeof(HellHound), + typeof(Hind), typeof(HordeMinion), typeof(Horse), + typeof(Horse), typeof(IceElemental), typeof(IceFiend), + typeof(IceSnake), typeof(Imp), typeof(JackRabbit), + typeof(Kirin), typeof(Kraken), typeof(PredatorHellCat), + typeof(LavaLizard), typeof(LavaSerpent), typeof(LavaSnake), + typeof(Lizardman), typeof(Llama), typeof(Mongbat), + typeof(StrongMongbat), typeof(MountainGoat), typeof(Orc), + typeof(OrcBomber), typeof(OrcBrute), typeof(OrcCaptain), + typeof(OrcishLord), typeof(OrcishMage), typeof(PackHorse), + typeof(PackLlama), typeof(Panther), typeof(Pig), + typeof(PlagueSpawn), typeof(PolarBear), typeof(Rabbit), + typeof(Ratman), typeof(RatmanArcher), typeof(RatmanMage), + typeof(RedSolenInfiltratorQueen), typeof(RedSolenInfiltratorWarrior), typeof(RedSolenQueen), + typeof(RedSolenWarrior), typeof(RedSolenWorker), typeof(RidableLlama), + typeof(Ridgeback), typeof(Scorpion), typeof(SeaSerpent), + typeof(SerpentineDragon), typeof(Shade), typeof(ShadowIronElemental), + typeof(ShadowWisp), typeof(ShadowWyrm), typeof(Sheep), + typeof(SilverSteed), typeof(SkeletalDragon), typeof(SkeletalMage), + typeof(SkeletalMount), typeof(HellCat), typeof(Snake), + typeof(SnowLeopard), typeof(SpectralArmour), typeof(Spectre), + typeof(StoneGargoyle), typeof(StoneHarpy), typeof(SwampDragon), + typeof(ScaledSwampDragon), typeof(SwampTentacle), typeof(TerathanAvenger), + typeof(TerathanDrone), typeof(TerathanMatriarch), typeof(TerathanWarrior), + typeof(TimberWolf), typeof(Titan), typeof(Troll), + typeof(Unicorn), typeof(ValoriteElemental), typeof(VeriteElemental), + typeof(CoMWarHorse), typeof(MinaxWarHorse), typeof(SLWarHorse), + typeof(TBWarHorse), typeof(WaterElemental), typeof(WhippingVine), + typeof(WhiteWolf), typeof(Wraith), typeof(Wyvern), + typeof(KhaldunZealot), typeof(KhaldunSummoner), typeof(SavageRidgeback), + typeof(LichLord), typeof(SkeletalKnight), typeof(SummonedDaemon), + typeof(SummonedEarthElemental), typeof(SummonedWaterElemental), typeof(SummonedFireElemental), + typeof(MeerWarrior), typeof(MeerEternal), typeof(MeerMage), + typeof(MeerCaptain), typeof(JukaLord), typeof(JukaMage), + typeof(JukaWarrior), typeof(AbysmalHorror), typeof(BoneDemon), + typeof(Devourer), typeof(FleshGolem), typeof(Gibberling), + typeof(GoreFiend), typeof(Impaler), typeof(PatchworkSkeleton), + typeof(Ravager), typeof(ShadowKnight), typeof(SkitteringHopper), + typeof(Treefellow), typeof(VampireBat), typeof(WailingBanshee), + typeof(WandererOfTheVoid), typeof(Cursed), typeof(GrimmochDrummel), + typeof(LysanderGathenwale), typeof(MorgBergen), typeof(ShadowFiend), + typeof(SpectralArmour), typeof(TavaraSewel), typeof(ArcaneDaemon), + typeof(Doppleganger), typeof(EnslavedGargoyle), typeof(ExodusMinion), + typeof(ExodusOverseer), typeof(GargoyleDestroyer), typeof(GargoyleEnforcer), + typeof(Moloch), typeof(BakeKitsune), typeof(DeathwatchBeetleHatchling), + typeof(Kappa), typeof(KazeKemono), typeof(DeathwatchBeetle), + typeof(TsukiWolf), typeof(YomotsuElder), typeof(YomotsuPriest), + typeof(YomotsuWarrior), typeof(RevenantLion), typeof(Oni), + typeof(Gaman), typeof(Crane), typeof(Beetle) + } + ) + }; + + public SpeedInfo(double activeSpeed, double passiveSpeed, Type[] types) + { + ActiveSpeed = activeSpeed; + PassiveSpeed = passiveSpeed; + Types = types; + } + + public double ActiveSpeed { get; set; } + + public double PassiveSpeed { get; set; } + + public Type[] Types { get; set; } + + public static bool Contains(object obj) + { + if (!Enabled) + return false; + + if (m_Table == null) + LoadTable(); + + return m_Table.ContainsKey(obj.GetType()); + } + + public static bool GetSpeeds(object obj, ref double activeSpeed, ref double passiveSpeed) + { + if (!Enabled) + return false; + + if (m_Table == null) + LoadTable(); + + if (!m_Table.TryGetValue(obj.GetType(), out var sp)) + return false; + + activeSpeed = sp.ActiveSpeed; + passiveSpeed = sp.PassiveSpeed; + + return true; + } + + private static void LoadTable() + { + m_Table = new Dictionary(); + + for (var i = 0; i < m_Speeds.Length; ++i) + { + var info = m_Speeds[i]; + var types = info.Types; + + for (var j = 0; j < types.Length; ++j) + m_Table[types[j]] = info; + } + } } - - public double ActiveSpeed { get; set; } - - public double PassiveSpeed { get; set; } - - public Type[] Types { get; set; } - - public static bool Contains(object obj) - { - if (!Enabled) - return false; - - if (m_Table == null) - LoadTable(); - - return m_Table.ContainsKey(obj.GetType()); - } - - public static bool GetSpeeds(object obj, ref double activeSpeed, ref double passiveSpeed) - { - if (!Enabled) - return false; - - if (m_Table == null) - LoadTable(); - - if (!m_Table.TryGetValue(obj.GetType(), out SpeedInfo sp)) - return false; - - activeSpeed = sp.ActiveSpeed; - passiveSpeed = sp.PassiveSpeed; - - return true; - } - - private static void LoadTable() - { - m_Table = new Dictionary(); - - for (int i = 0; i < m_Speeds.Length; ++i) - { - SpeedInfo info = m_Speeds[i]; - Type[] types = info.Types; - - for (int j = 0; j < types.Length; ++j) - m_Table[types[j]] = info; - } - } - } } diff --git a/Projects/UOContent/Mobiles/AI/ThiefAI.cs b/Projects/UOContent/Mobiles/AI/ThiefAI.cs index 92842c8ab..1bf11d7f7 100644 --- a/Projects/UOContent/Mobiles/AI/ThiefAI.cs +++ b/Projects/UOContent/Mobiles/AI/ThiefAI.cs @@ -2,174 +2,174 @@ using Server.Items; namespace Server.Mobiles { - public class ThiefAI : BaseAI - { - private Item m_toDisarm; - - public ThiefAI(BaseCreature m) : base(m) + public class ThiefAI : BaseAI { - } + private Item m_toDisarm; - public override bool DoActionWander() - { - m_Mobile.DebugSay("I have no combatant"); - - if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) - { - m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name); - - m_Mobile.Combatant = m_Mobile.FocusMob; - Action = ActionType.Combat; - } - else - { - base.DoActionWander(); - } - - return true; - } - - public override bool DoActionCombat() - { - Mobile combatant = m_Mobile.Combatant; - - if (combatant?.Deleted != false || combatant.Map != m_Mobile.Map) - { - m_Mobile.DebugSay("My combatant is gone, so my guard is up"); - - Action = ActionType.Guard; - - return true; - } - - if (WalkMobileRange(combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight)) - { - m_Mobile.Direction = m_Mobile.GetDirectionTo(combatant); - - if (m_toDisarm?.IsChildOf(m_Mobile.Backpack) != false) - m_toDisarm = combatant.FindItemOnLayer(Layer.OneHanded) ?? combatant.FindItemOnLayer(Layer.TwoHanded); - - if (!Core.AOS && !m_Mobile.DisarmReady && m_Mobile.Skills.Wrestling.Value >= 80.0 && - m_Mobile.Skills.ArmsLore.Value >= 80.0 && m_toDisarm != null) - EventSink.InvokeDisarmRequest(m_Mobile); - - if (m_toDisarm?.IsChildOf(combatant.Backpack) == true && - Core.TickCount - m_Mobile.NextSkillTime >= 0 && m_toDisarm.LootType != LootType.Blessed && - m_toDisarm.LootType != LootType.Newbied) + public ThiefAI(BaseCreature m) : base(m) { - m_Mobile.DebugSay("Trying to steal from combatant."); - m_Mobile.UseSkill(SkillName.Stealing); - m_Mobile.Target?.Invoke(m_Mobile, m_toDisarm); } - else if (m_toDisarm == null && Core.TickCount - m_Mobile.NextSkillTime >= 0) + + public override bool DoActionWander() { - Container cpack = combatant.Backpack; + m_Mobile.DebugSay("I have no combatant"); - if (cpack != null) - { - Item steala = cpack.FindItemByType(); - if (steala != null) + if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) { - m_Mobile.DebugSay("Trying to steal from combatant."); - m_Mobile.UseSkill(SkillName.Stealing); - m_Mobile.Target?.Invoke(m_Mobile, steala); + m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name); + + m_Mobile.Combatant = m_Mobile.FocusMob; + Action = ActionType.Combat; + } + else + { + base.DoActionWander(); } - Item stealb = cpack.FindItemByType(); - if (stealb != null) - { - m_Mobile.DebugSay("Trying to steal from combatant."); - m_Mobile.UseSkill(SkillName.Stealing); - m_Mobile.Target?.Invoke(m_Mobile, stealb); - } - - Item stealc = cpack.FindItemByType(); - if (stealc != null) - { - m_Mobile.DebugSay("Trying to steal from combatant."); - m_Mobile.UseSkill(SkillName.Stealing); - m_Mobile.Target?.Invoke(m_Mobile, stealc); - } - - Item steald = cpack.FindItemByType(); - if (steald != null) - { - m_Mobile.DebugSay("Trying to steal from combatant."); - m_Mobile.UseSkill(SkillName.Stealing); - m_Mobile.Target?.Invoke(m_Mobile, steald); - } - else if (steala == null && stealb == null && stealc == null) - { - m_Mobile.DebugSay("I am going to flee from {0}", combatant.Name); - - Action = ActionType.Flee; - } - } + return true; } - } - else - { - m_Mobile.DebugSay("I should be closer to {0}", combatant.Name); - } - if (m_Mobile.Hits >= m_Mobile.HitsMax * 20 / 100 || !m_Mobile.CanFlee) - return true; - // We are low on health, should we flee? + public override bool DoActionCombat() + { + var combatant = m_Mobile.Combatant; - bool flee; + if (combatant?.Deleted != false || combatant.Map != m_Mobile.Map) + { + m_Mobile.DebugSay("My combatant is gone, so my guard is up"); - if (m_Mobile.Hits < combatant.Hits) - { - // We are more hurt than them - int diff = combatant.Hits - m_Mobile.Hits; + Action = ActionType.Guard; - flee = Utility.Random(0, 100) > 10 + diff; // (10 + diff)% chance to flee - } - else - { - flee = Utility.Random(0, 100) > 10; // 10% chance to flee - } + return true; + } - if (flee) - { - m_Mobile.DebugSay("I am going to flee from {0}", combatant.Name); - Action = ActionType.Flee; - } + if (WalkMobileRange(combatant, 1, true, m_Mobile.RangeFight, m_Mobile.RangeFight)) + { + m_Mobile.Direction = m_Mobile.GetDirectionTo(combatant); - return true; + if (m_toDisarm?.IsChildOf(m_Mobile.Backpack) != false) + m_toDisarm = combatant.FindItemOnLayer(Layer.OneHanded) ?? combatant.FindItemOnLayer(Layer.TwoHanded); + + if (!Core.AOS && !m_Mobile.DisarmReady && m_Mobile.Skills.Wrestling.Value >= 80.0 && + m_Mobile.Skills.ArmsLore.Value >= 80.0 && m_toDisarm != null) + EventSink.InvokeDisarmRequest(m_Mobile); + + if (m_toDisarm?.IsChildOf(combatant.Backpack) == true && + Core.TickCount - m_Mobile.NextSkillTime >= 0 && m_toDisarm.LootType != LootType.Blessed && + m_toDisarm.LootType != LootType.Newbied) + { + m_Mobile.DebugSay("Trying to steal from combatant."); + m_Mobile.UseSkill(SkillName.Stealing); + m_Mobile.Target?.Invoke(m_Mobile, m_toDisarm); + } + else if (m_toDisarm == null && Core.TickCount - m_Mobile.NextSkillTime >= 0) + { + var cpack = combatant.Backpack; + + if (cpack != null) + { + Item steala = cpack.FindItemByType(); + if (steala != null) + { + m_Mobile.DebugSay("Trying to steal from combatant."); + m_Mobile.UseSkill(SkillName.Stealing); + m_Mobile.Target?.Invoke(m_Mobile, steala); + } + + Item stealb = cpack.FindItemByType(); + if (stealb != null) + { + m_Mobile.DebugSay("Trying to steal from combatant."); + m_Mobile.UseSkill(SkillName.Stealing); + m_Mobile.Target?.Invoke(m_Mobile, stealb); + } + + Item stealc = cpack.FindItemByType(); + if (stealc != null) + { + m_Mobile.DebugSay("Trying to steal from combatant."); + m_Mobile.UseSkill(SkillName.Stealing); + m_Mobile.Target?.Invoke(m_Mobile, stealc); + } + + Item steald = cpack.FindItemByType(); + if (steald != null) + { + m_Mobile.DebugSay("Trying to steal from combatant."); + m_Mobile.UseSkill(SkillName.Stealing); + m_Mobile.Target?.Invoke(m_Mobile, steald); + } + else if (steala == null && stealb == null && stealc == null) + { + m_Mobile.DebugSay("I am going to flee from {0}", combatant.Name); + + Action = ActionType.Flee; + } + } + } + } + else + { + m_Mobile.DebugSay("I should be closer to {0}", combatant.Name); + } + + if (m_Mobile.Hits >= m_Mobile.HitsMax * 20 / 100 || !m_Mobile.CanFlee) + return true; + // We are low on health, should we flee? + + bool flee; + + if (m_Mobile.Hits < combatant.Hits) + { + // We are more hurt than them + var diff = combatant.Hits - m_Mobile.Hits; + + flee = Utility.Random(0, 100) > 10 + diff; // (10 + diff)% chance to flee + } + else + { + flee = Utility.Random(0, 100) > 10; // 10% chance to flee + } + + if (flee) + { + m_Mobile.DebugSay("I am going to flee from {0}", combatant.Name); + Action = ActionType.Flee; + } + + return true; + } + + public override bool DoActionGuard() + { + if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) + { + m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name); + + m_Mobile.Combatant = m_Mobile.FocusMob; + Action = ActionType.Combat; + } + else + { + base.DoActionGuard(); + } + + return true; + } + + public override bool DoActionFlee() + { + if (m_Mobile.Hits > m_Mobile.HitsMax / 2) + { + m_Mobile.DebugSay("I am stronger now, so I will continue fighting"); + Action = ActionType.Combat; + } + else + { + m_Mobile.FocusMob = m_Mobile.Combatant; + base.DoActionFlee(); + } + + return true; + } } - - public override bool DoActionGuard() - { - if (AcquireFocusMob(m_Mobile.RangePerception, m_Mobile.FightMode, false, false, true)) - { - m_Mobile.DebugSay("I have detected {0}, attacking", m_Mobile.FocusMob.Name); - - m_Mobile.Combatant = m_Mobile.FocusMob; - Action = ActionType.Combat; - } - else - { - base.DoActionGuard(); - } - - return true; - } - - public override bool DoActionFlee() - { - if (m_Mobile.Hits > m_Mobile.HitsMax / 2) - { - m_Mobile.DebugSay("I am stronger now, so I will continue fighting"); - Action = ActionType.Combat; - } - else - { - m_Mobile.FocusMob = m_Mobile.Combatant; - base.DoActionFlee(); - } - - return true; - } - } } diff --git a/Projects/UOContent/Mobiles/AI/VendorAI.cs b/Projects/UOContent/Mobiles/AI/VendorAI.cs index d114ddb7c..28b3c0dcc 100644 --- a/Projects/UOContent/Mobiles/AI/VendorAI.cs +++ b/Projects/UOContent/Mobiles/AI/VendorAI.cs @@ -1,145 +1,145 @@ namespace Server.Mobiles { - public class VendorAI : BaseAI - { - public VendorAI(BaseCreature m) : base(m) + public class VendorAI : BaseAI { + public VendorAI(BaseCreature m) : base(m) + { + } + + public override bool DoActionWander() + { + m_Mobile.DebugSay("I'm fine"); + + if (m_Mobile.Combatant != null) + { + if (m_Mobile.Debug) + m_Mobile.DebugSay("{0} is attacking me", m_Mobile.Combatant.Name); + + m_Mobile.Say(Utility.RandomList(1005305, 501603)); + + Action = ActionType.Flee; + } + else + { + if (m_Mobile.FocusMob != null) + { + if (m_Mobile.Debug) + m_Mobile.DebugSay("{0} has talked to me", m_Mobile.FocusMob.Name); + + Action = ActionType.Interact; + } + else + { + m_Mobile.Warmode = false; + + base.DoActionWander(); + } + } + + return true; + } + + public override bool DoActionInteract() + { + var customer = m_Mobile.FocusMob; + + if (m_Mobile.Combatant != null) + { + if (m_Mobile.Debug) + m_Mobile.DebugSay("{0} is attacking me", m_Mobile.Combatant.Name); + + m_Mobile.Say(Utility.RandomList(1005305, 501603)); + + Action = ActionType.Flee; + + return true; + } + + if (customer?.Deleted != false || customer.Map != m_Mobile.Map) + { + m_Mobile.DebugSay("My customer have disapeared"); + m_Mobile.FocusMob = null; + + Action = ActionType.Wander; + } + else + { + if (customer.InRange(m_Mobile, m_Mobile.RangeFight)) + { + if (m_Mobile.Debug) + m_Mobile.DebugSay("I am with {0}", customer.Name); + + m_Mobile.Direction = m_Mobile.GetDirectionTo(customer); + } + else + { + if (m_Mobile.Debug) + m_Mobile.DebugSay("{0} is gone", customer.Name); + + m_Mobile.FocusMob = null; + + Action = ActionType.Wander; + } + } + + return true; + } + + public override bool DoActionGuard() + { + m_Mobile.FocusMob = m_Mobile.Combatant; + return base.DoActionGuard(); + } + + public override bool HandlesOnSpeech(Mobile from) + { + if (from.InRange(m_Mobile, 4)) + return true; + + return base.HandlesOnSpeech(from); + } + + // Temporary + public override void OnSpeech(SpeechEventArgs e) + { + base.OnSpeech(e); + + var from = e.Mobile; + + if (m_Mobile is BaseVendor vendor && from.InRange(m_Mobile, Core.AOS ? 1 : 4) && !e.Handled) + { + if (e.HasKeyword(0x14D)) // *vendor sell* + { + e.Handled = true; + + vendor.VendorSell(from); + vendor.FocusMob = from; + } + else if (e.HasKeyword(0x3C)) // *vendor buy* + { + e.Handled = true; + + vendor.VendorBuy(from); + vendor.FocusMob = from; + } + else if (WasNamed(e.Speech)) + { + if (e.HasKeyword(0x177)) // *sell* + { + e.Handled = true; + + vendor.VendorSell(from); + } + else if (e.HasKeyword(0x171)) // *buy* + { + e.Handled = true; + + vendor.VendorBuy(from); + } + + vendor.FocusMob = from; + } + } + } } - - public override bool DoActionWander() - { - m_Mobile.DebugSay("I'm fine"); - - if (m_Mobile.Combatant != null) - { - if (m_Mobile.Debug) - m_Mobile.DebugSay("{0} is attacking me", m_Mobile.Combatant.Name); - - m_Mobile.Say(Utility.RandomList(1005305, 501603)); - - Action = ActionType.Flee; - } - else - { - if (m_Mobile.FocusMob != null) - { - if (m_Mobile.Debug) - m_Mobile.DebugSay("{0} has talked to me", m_Mobile.FocusMob.Name); - - Action = ActionType.Interact; - } - else - { - m_Mobile.Warmode = false; - - base.DoActionWander(); - } - } - - return true; - } - - public override bool DoActionInteract() - { - Mobile customer = m_Mobile.FocusMob; - - if (m_Mobile.Combatant != null) - { - if (m_Mobile.Debug) - m_Mobile.DebugSay("{0} is attacking me", m_Mobile.Combatant.Name); - - m_Mobile.Say(Utility.RandomList(1005305, 501603)); - - Action = ActionType.Flee; - - return true; - } - - if (customer?.Deleted != false || customer.Map != m_Mobile.Map) - { - m_Mobile.DebugSay("My customer have disapeared"); - m_Mobile.FocusMob = null; - - Action = ActionType.Wander; - } - else - { - if (customer.InRange(m_Mobile, m_Mobile.RangeFight)) - { - if (m_Mobile.Debug) - m_Mobile.DebugSay("I am with {0}", customer.Name); - - m_Mobile.Direction = m_Mobile.GetDirectionTo(customer); - } - else - { - if (m_Mobile.Debug) - m_Mobile.DebugSay("{0} is gone", customer.Name); - - m_Mobile.FocusMob = null; - - Action = ActionType.Wander; - } - } - - return true; - } - - public override bool DoActionGuard() - { - m_Mobile.FocusMob = m_Mobile.Combatant; - return base.DoActionGuard(); - } - - public override bool HandlesOnSpeech(Mobile from) - { - if (from.InRange(m_Mobile, 4)) - return true; - - return base.HandlesOnSpeech(from); - } - - // Temporary - public override void OnSpeech(SpeechEventArgs e) - { - base.OnSpeech(e); - - Mobile from = e.Mobile; - - if (m_Mobile is BaseVendor vendor && from.InRange(m_Mobile, Core.AOS ? 1 : 4) && !e.Handled) - { - if (e.HasKeyword(0x14D)) // *vendor sell* - { - e.Handled = true; - - vendor.VendorSell(from); - vendor.FocusMob = from; - } - else if (e.HasKeyword(0x3C)) // *vendor buy* - { - e.Handled = true; - - vendor.VendorBuy(from); - vendor.FocusMob = from; - } - else if (WasNamed(e.Speech)) - { - if (e.HasKeyword(0x177)) // *sell* - { - e.Handled = true; - - vendor.VendorSell(from); - } - else if (e.HasKeyword(0x171)) // *buy* - { - e.Handled = true; - - vendor.VendorBuy(from); - } - - vendor.FocusMob = from; - } - } - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Bears/BlackBear.cs b/Projects/UOContent/Mobiles/Animals/Bears/BlackBear.cs index df228116d..536a9a97e 100644 --- a/Projects/UOContent/Mobiles/Animals/Bears/BlackBear.cs +++ b/Projects/UOContent/Mobiles/Animals/Bears/BlackBear.cs @@ -1,67 +1,67 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Bear")] - public class BlackBear : BaseCreature - { - [Constructible] - public BlackBear() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Bear")] + public class BlackBear : BaseCreature { - Body = 211; - BaseSoundID = 0xA3; + [Constructible] + public BlackBear() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 211; + BaseSoundID = 0xA3; - SetStr(76, 100); - SetDex(56, 75); - SetInt(11, 14); + SetStr(76, 100); + SetDex(56, 75); + SetInt(11, 14); - SetHits(46, 60); - SetMana(0); + SetHits(46, 60); + SetMana(0); - SetDamage(4, 10); + SetDamage(4, 10); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 20, 25); - SetResistance(ResistanceType.Cold, 10, 15); - SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Physical, 20, 25); + SetResistance(ResistanceType.Cold, 10, 15); + SetResistance(ResistanceType.Poison, 5, 10); - SetSkill(SkillName.MagicResist, 20.1, 40.0); - SetSkill(SkillName.Tactics, 40.1, 60.0); - SetSkill(SkillName.Wrestling, 40.1, 60.0); + SetSkill(SkillName.MagicResist, 20.1, 40.0); + SetSkill(SkillName.Tactics, 40.1, 60.0); + SetSkill(SkillName.Wrestling, 40.1, 60.0); - Fame = 450; - Karma = 0; + Fame = 450; + Karma = 0; - VirtualArmor = 24; + VirtualArmor = 24; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 35.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 35.1; + } + + public BlackBear(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a bear corpse"; + public override string DefaultName => "a black bear"; + + public override int Meat => 1; + public override int Hides => 12; + public override FoodType FavoriteFood => FoodType.Fish | FoodType.Meat | FoodType.FruitsAndVegies; + public override PackInstinct PackInstinct => PackInstinct.Bear; + + 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(); + } } - - public BlackBear(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a bear corpse"; - public override string DefaultName => "a black bear"; - - public override int Meat => 1; - public override int Hides => 12; - public override FoodType FavoriteFood => FoodType.Fish | FoodType.Meat | FoodType.FruitsAndVegies; - public override PackInstinct PackInstinct => PackInstinct.Bear; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Bears/BrownBear.cs b/Projects/UOContent/Mobiles/Animals/Bears/BrownBear.cs index 44bbf74cc..1e3175411 100644 --- a/Projects/UOContent/Mobiles/Animals/Bears/BrownBear.cs +++ b/Projects/UOContent/Mobiles/Animals/Bears/BrownBear.cs @@ -1,66 +1,66 @@ namespace Server.Mobiles { - public class BrownBear : BaseCreature - { - [Constructible] - public BrownBear() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class BrownBear : BaseCreature { - Body = 167; - BaseSoundID = 0xA3; + [Constructible] + public BrownBear() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 167; + BaseSoundID = 0xA3; - SetStr(76, 100); - SetDex(26, 45); - SetInt(23, 47); + SetStr(76, 100); + SetDex(26, 45); + SetInt(23, 47); - SetHits(46, 60); - SetMana(0); + SetHits(46, 60); + SetMana(0); - SetDamage(6, 12); + SetDamage(6, 12); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 20, 30); - SetResistance(ResistanceType.Cold, 15, 20); - SetResistance(ResistanceType.Poison, 10, 15); + SetResistance(ResistanceType.Physical, 20, 30); + SetResistance(ResistanceType.Cold, 15, 20); + SetResistance(ResistanceType.Poison, 10, 15); - SetSkill(SkillName.MagicResist, 25.1, 35.0); - SetSkill(SkillName.Tactics, 40.1, 60.0); - SetSkill(SkillName.Wrestling, 40.1, 60.0); + SetSkill(SkillName.MagicResist, 25.1, 35.0); + SetSkill(SkillName.Tactics, 40.1, 60.0); + SetSkill(SkillName.Wrestling, 40.1, 60.0); - Fame = 450; - Karma = 0; + Fame = 450; + Karma = 0; - VirtualArmor = 24; + VirtualArmor = 24; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 41.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 41.1; + } + + public BrownBear(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a bear corpse"; + public override string DefaultName => "a brown bear"; + + public override int Meat => 1; + public override int Hides => 12; + public override FoodType FavoriteFood => FoodType.Fish | FoodType.FruitsAndVegies | FoodType.Meat; + public override PackInstinct PackInstinct => PackInstinct.Bear; + + 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(); + } } - - public BrownBear(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a bear corpse"; - public override string DefaultName => "a brown bear"; - - public override int Meat => 1; - public override int Hides => 12; - public override FoodType FavoriteFood => FoodType.Fish | FoodType.FruitsAndVegies | FoodType.Meat; - public override PackInstinct PackInstinct => PackInstinct.Bear; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Bears/GrizzlyBear.cs b/Projects/UOContent/Mobiles/Animals/Bears/GrizzlyBear.cs index c4604b22b..56a40674c 100644 --- a/Projects/UOContent/Mobiles/Animals/Bears/GrizzlyBear.cs +++ b/Projects/UOContent/Mobiles/Animals/Bears/GrizzlyBear.cs @@ -1,68 +1,68 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Grizzlybear")] - public class GrizzlyBear : BaseCreature - { - [Constructible] - public GrizzlyBear() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Grizzlybear")] + public class GrizzlyBear : BaseCreature { - Body = 212; - BaseSoundID = 0xA3; + [Constructible] + public GrizzlyBear() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 212; + BaseSoundID = 0xA3; - SetStr(126, 155); - SetDex(81, 105); - SetInt(16, 40); + SetStr(126, 155); + SetDex(81, 105); + SetInt(16, 40); - SetHits(76, 93); - SetMana(0); + SetHits(76, 93); + SetMana(0); - SetDamage(8, 13); + SetDamage(8, 13); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 25, 35); - SetResistance(ResistanceType.Cold, 15, 25); - SetResistance(ResistanceType.Poison, 5, 10); - SetResistance(ResistanceType.Energy, 5, 10); + SetResistance(ResistanceType.Physical, 25, 35); + SetResistance(ResistanceType.Cold, 15, 25); + SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Energy, 5, 10); - SetSkill(SkillName.MagicResist, 25.1, 40.0); - SetSkill(SkillName.Tactics, 70.1, 100.0); - SetSkill(SkillName.Wrestling, 45.1, 70.0); + SetSkill(SkillName.MagicResist, 25.1, 40.0); + SetSkill(SkillName.Tactics, 70.1, 100.0); + SetSkill(SkillName.Wrestling, 45.1, 70.0); - Fame = 1000; - Karma = 0; + Fame = 1000; + Karma = 0; - VirtualArmor = 24; + VirtualArmor = 24; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 59.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 59.1; + } + + public GrizzlyBear(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a grizzly bear corpse"; + public override string DefaultName => "a grizzly bear"; + + public override int Meat => 2; + public override int Hides => 16; + public override FoodType FavoriteFood => FoodType.Fish | FoodType.FruitsAndVegies | FoodType.Meat; + public override PackInstinct PackInstinct => PackInstinct.Bear; + + 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(); + } } - - public GrizzlyBear(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a grizzly bear corpse"; - public override string DefaultName => "a grizzly bear"; - - public override int Meat => 2; - public override int Hides => 16; - public override FoodType FavoriteFood => FoodType.Fish | FoodType.FruitsAndVegies | FoodType.Meat; - public override PackInstinct PackInstinct => PackInstinct.Bear; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Bears/PolarBear.cs b/Projects/UOContent/Mobiles/Animals/Bears/PolarBear.cs index b46a5cbcf..eccc1716d 100644 --- a/Projects/UOContent/Mobiles/Animals/Bears/PolarBear.cs +++ b/Projects/UOContent/Mobiles/Animals/Bears/PolarBear.cs @@ -1,68 +1,68 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Polarbear")] - public class PolarBear : BaseCreature - { - [Constructible] - public PolarBear() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Polarbear")] + public class PolarBear : BaseCreature { - Body = 213; - BaseSoundID = 0xA3; + [Constructible] + public PolarBear() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 213; + BaseSoundID = 0xA3; - SetStr(116, 140); - SetDex(81, 105); - SetInt(26, 50); + SetStr(116, 140); + SetDex(81, 105); + SetInt(26, 50); - SetHits(70, 84); - SetMana(0); + SetHits(70, 84); + SetMana(0); - SetDamage(7, 12); + SetDamage(7, 12); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 25, 35); - SetResistance(ResistanceType.Cold, 60, 80); - SetResistance(ResistanceType.Poison, 15, 25); - SetResistance(ResistanceType.Energy, 10, 15); + SetResistance(ResistanceType.Physical, 25, 35); + SetResistance(ResistanceType.Cold, 60, 80); + SetResistance(ResistanceType.Poison, 15, 25); + SetResistance(ResistanceType.Energy, 10, 15); - SetSkill(SkillName.MagicResist, 45.1, 60.0); - SetSkill(SkillName.Tactics, 60.1, 90.0); - SetSkill(SkillName.Wrestling, 45.1, 70.0); + SetSkill(SkillName.MagicResist, 45.1, 60.0); + SetSkill(SkillName.Tactics, 60.1, 90.0); + SetSkill(SkillName.Wrestling, 45.1, 70.0); - Fame = 1500; - Karma = 0; + Fame = 1500; + Karma = 0; - VirtualArmor = 18; + VirtualArmor = 18; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 35.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 35.1; + } + + public PolarBear(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a polar bear corpse"; + public override string DefaultName => "a polar bear"; + + public override int Meat => 2; + public override int Hides => 16; + public override FoodType FavoriteFood => FoodType.Fish | FoodType.FruitsAndVegies | FoodType.Meat; + public override PackInstinct PackInstinct => PackInstinct.Bear; + + 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(); + } } - - public PolarBear(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a polar bear corpse"; - public override string DefaultName => "a polar bear"; - - public override int Meat => 2; - public override int Hides => 16; - public override FoodType FavoriteFood => FoodType.Fish | FoodType.FruitsAndVegies | FoodType.Meat; - public override PackInstinct PackInstinct => PackInstinct.Bear; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Birds/Chicken.cs b/Projects/UOContent/Mobiles/Animals/Birds/Chicken.cs index 517faf037..756de8844 100644 --- a/Projects/UOContent/Mobiles/Animals/Birds/Chicken.cs +++ b/Projects/UOContent/Mobiles/Animals/Birds/Chicken.cs @@ -1,66 +1,66 @@ namespace Server.Mobiles { - public class Chicken : BaseCreature - { - [Constructible] - public Chicken() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Chicken : BaseCreature { - Body = 0xD0; - BaseSoundID = 0x6E; + [Constructible] + public Chicken() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 0xD0; + BaseSoundID = 0x6E; - SetStr(5); - SetDex(15); - SetInt(5); + SetStr(5); + SetDex(15); + SetInt(5); - SetHits(3); - SetMana(0); + SetHits(3); + SetMana(0); - SetDamage(1); + SetDamage(1); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 1, 5); + SetResistance(ResistanceType.Physical, 1, 5); - SetSkill(SkillName.MagicResist, 4.0); - SetSkill(SkillName.Tactics, 5.0); - SetSkill(SkillName.Wrestling, 5.0); + SetSkill(SkillName.MagicResist, 4.0); + SetSkill(SkillName.Tactics, 5.0); + SetSkill(SkillName.Wrestling, 5.0); - Fame = 150; - Karma = 0; + Fame = 150; + Karma = 0; - VirtualArmor = 2; + VirtualArmor = 2; - Tamable = true; - ControlSlots = 1; - MinTameSkill = -0.9; + Tamable = true; + ControlSlots = 1; + MinTameSkill = -0.9; + } + + public Chicken(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a chicken corpse"; + public override string DefaultName => "a chicken"; + + public override int Meat => 1; + public override MeatType MeatType => MeatType.Bird; + public override FoodType FavoriteFood => FoodType.GrainsAndHay; + public override bool CanFly => true; + + public override int Feathers => 25; + + 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(); + } } - - public Chicken(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a chicken corpse"; - public override string DefaultName => "a chicken"; - - public override int Meat => 1; - public override MeatType MeatType => MeatType.Bird; - public override FoodType FavoriteFood => FoodType.GrainsAndHay; - public override bool CanFly => true; - - public override int Feathers => 25; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Birds/Crane.cs b/Projects/UOContent/Mobiles/Animals/Birds/Crane.cs index 96f020852..1cb10d33d 100644 --- a/Projects/UOContent/Mobiles/Animals/Birds/Crane.cs +++ b/Projects/UOContent/Mobiles/Animals/Birds/Crane.cs @@ -1,68 +1,68 @@ namespace Server.Mobiles { - public class Crane : BaseCreature - { - [Constructible] - public Crane() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Crane : BaseCreature { - Body = 254; - BaseSoundID = 0x4D7; + [Constructible] + public Crane() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 254; + BaseSoundID = 0x4D7; - SetStr(26, 35); - SetDex(16, 25); - SetInt(11, 15); + SetStr(26, 35); + SetDex(16, 25); + SetInt(11, 15); - SetHits(26, 35); - SetMana(0); + SetHits(26, 35); + SetMana(0); - SetDamage(1, 1); + SetDamage(1, 1); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 5, 5); + SetResistance(ResistanceType.Physical, 5, 5); - SetSkill(SkillName.MagicResist, 4.1, 5.0); - SetSkill(SkillName.Tactics, 10.1, 11.0); - SetSkill(SkillName.Wrestling, 10.1, 11.0); + SetSkill(SkillName.MagicResist, 4.1, 5.0); + SetSkill(SkillName.Tactics, 10.1, 11.0); + SetSkill(SkillName.Wrestling, 10.1, 11.0); - Fame = 0; - Karma = 200; + Fame = 0; + Karma = 200; - VirtualArmor = 5; + VirtualArmor = 5; + } + + public Crane(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a bird corpse"; + public override string DefaultName => "a crane"; + + public override int Meat => 1; + public override int Feathers => 25; + + public override int GetAngerSound() => 0x4D9; + + public override int GetIdleSound() => 0x4D8; + + public override int GetAttackSound() => 0x4D7; + + public override int GetHurtSound() => 0x4DA; + + public override int GetDeathSound() => 0x4D6; + + 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(); + } } - - public Crane(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a bird corpse"; - public override string DefaultName => "a crane"; - - public override int Meat => 1; - public override int Feathers => 25; - - public override int GetAngerSound() => 0x4D9; - - public override int GetIdleSound() => 0x4D8; - - public override int GetAttackSound() => 0x4D7; - - public override int GetHurtSound() => 0x4DA; - - public override int GetDeathSound() => 0x4D6; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Birds/Eagle.cs b/Projects/UOContent/Mobiles/Animals/Birds/Eagle.cs index 3ac721336..593a2c694 100644 --- a/Projects/UOContent/Mobiles/Animals/Birds/Eagle.cs +++ b/Projects/UOContent/Mobiles/Animals/Birds/Eagle.cs @@ -1,69 +1,69 @@ namespace Server.Mobiles { - public class Eagle : BaseCreature - { - [Constructible] - public Eagle() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Eagle : BaseCreature { - Body = 5; - BaseSoundID = 0x2EE; + [Constructible] + public Eagle() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 5; + BaseSoundID = 0x2EE; - SetStr(31, 47); - SetDex(36, 60); - SetInt(8, 20); + SetStr(31, 47); + SetDex(36, 60); + SetInt(8, 20); - SetHits(20, 27); - SetMana(0); + SetHits(20, 27); + SetMana(0); - SetDamage(5, 10); + SetDamage(5, 10); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 20, 25); - SetResistance(ResistanceType.Fire, 10, 15); - SetResistance(ResistanceType.Cold, 20, 25); - SetResistance(ResistanceType.Poison, 5, 10); - SetResistance(ResistanceType.Energy, 5, 10); + SetResistance(ResistanceType.Physical, 20, 25); + SetResistance(ResistanceType.Fire, 10, 15); + SetResistance(ResistanceType.Cold, 20, 25); + SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Energy, 5, 10); - SetSkill(SkillName.MagicResist, 15.3, 30.0); - SetSkill(SkillName.Tactics, 18.1, 37.0); - SetSkill(SkillName.Wrestling, 20.1, 30.0); + SetSkill(SkillName.MagicResist, 15.3, 30.0); + SetSkill(SkillName.Tactics, 18.1, 37.0); + SetSkill(SkillName.Wrestling, 20.1, 30.0); - Fame = 300; - Karma = 0; + Fame = 300; + Karma = 0; - VirtualArmor = 22; + VirtualArmor = 22; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 17.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 17.1; + } + + public Eagle(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a bird corpse"; + public override string DefaultName => "an eagle"; + + public override int Meat => 1; + public override MeatType MeatType => MeatType.Bird; + public override int Feathers => 36; + public override FoodType FavoriteFood => FoodType.Meat | FoodType.Fish; + public override bool CanFly => true; + + 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(); + } } - - public Eagle(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a bird corpse"; - public override string DefaultName => "an eagle"; - - public override int Meat => 1; - public override MeatType MeatType => MeatType.Bird; - public override int Feathers => 36; - public override FoodType FavoriteFood => FoodType.Meat | FoodType.Fish; - public override bool CanFly => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Birds/Phoenix.cs b/Projects/UOContent/Mobiles/Animals/Birds/Phoenix.cs index cce0f59b6..49179359c 100644 --- a/Projects/UOContent/Mobiles/Animals/Birds/Phoenix.cs +++ b/Projects/UOContent/Mobiles/Animals/Birds/Phoenix.cs @@ -1,71 +1,71 @@ namespace Server.Mobiles { - public class Phoenix : BaseCreature - { - [Constructible] - public Phoenix() : base(AIType.AI_Mage, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Phoenix : BaseCreature { - Body = 5; - Hue = 0x674; - BaseSoundID = 0x8F; + [Constructible] + public Phoenix() : base(AIType.AI_Mage, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 5; + Hue = 0x674; + BaseSoundID = 0x8F; - SetStr(504, 700); - SetDex(202, 300); - SetInt(504, 700); + SetStr(504, 700); + SetDex(202, 300); + SetInt(504, 700); - SetHits(340, 383); + SetHits(340, 383); - SetDamage(25); + SetDamage(25); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Fire, 50); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Fire, 50); - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 60, 70); - SetResistance(ResistanceType.Poison, 25, 35); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 60, 70); + SetResistance(ResistanceType.Poison, 25, 35); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.EvalInt, 90.2, 100.0); - SetSkill(SkillName.Magery, 90.2, 100.0); - SetSkill(SkillName.Meditation, 75.1, 100.0); - SetSkill(SkillName.MagicResist, 86.0, 135.0); - SetSkill(SkillName.Tactics, 80.1, 90.0); - SetSkill(SkillName.Wrestling, 90.1, 100.0); + SetSkill(SkillName.EvalInt, 90.2, 100.0); + SetSkill(SkillName.Magery, 90.2, 100.0); + SetSkill(SkillName.Meditation, 75.1, 100.0); + SetSkill(SkillName.MagicResist, 86.0, 135.0); + SetSkill(SkillName.Tactics, 80.1, 90.0); + SetSkill(SkillName.Wrestling, 90.1, 100.0); - Fame = 15000; - Karma = 0; + Fame = 15000; + Karma = 0; - VirtualArmor = 60; + VirtualArmor = 60; + } + + public Phoenix(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a phoenix corpse"; + public override string DefaultName => "a phoenix"; + + public override int Meat => 1; + public override MeatType MeatType => MeatType.Bird; + public override int Feathers => 36; + public override bool CanFly => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.Rich); + } + + 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(); + } } - - public Phoenix(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a phoenix corpse"; - public override string DefaultName => "a phoenix"; - - public override int Meat => 1; - public override MeatType MeatType => MeatType.Bird; - public override int Feathers => 36; - public override bool CanFly => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.Rich); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Canines/DireWolf.cs b/Projects/UOContent/Mobiles/Animals/Canines/DireWolf.cs index 884df155c..2a6edf148 100644 --- a/Projects/UOContent/Mobiles/Animals/Canines/DireWolf.cs +++ b/Projects/UOContent/Mobiles/Animals/Canines/DireWolf.cs @@ -1,70 +1,70 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Direwolf")] - public class DireWolf : BaseCreature - { - [Constructible] - public DireWolf() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Direwolf")] + public class DireWolf : BaseCreature { - Body = 23; - BaseSoundID = 0xE5; + [Constructible] + public DireWolf() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 23; + BaseSoundID = 0xE5; - SetStr(96, 120); - SetDex(81, 105); - SetInt(36, 60); + SetStr(96, 120); + SetDex(81, 105); + SetInt(36, 60); - SetHits(58, 72); - SetMana(0); + SetHits(58, 72); + SetMana(0); - SetDamage(11, 17); + SetDamage(11, 17); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 20, 25); - SetResistance(ResistanceType.Fire, 10, 20); - SetResistance(ResistanceType.Cold, 5, 10); - SetResistance(ResistanceType.Poison, 5, 10); - SetResistance(ResistanceType.Energy, 10, 15); + SetResistance(ResistanceType.Physical, 20, 25); + SetResistance(ResistanceType.Fire, 10, 20); + SetResistance(ResistanceType.Cold, 5, 10); + SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Energy, 10, 15); - SetSkill(SkillName.MagicResist, 57.6, 75.0); - SetSkill(SkillName.Tactics, 50.1, 70.0); - SetSkill(SkillName.Wrestling, 60.1, 80.0); + SetSkill(SkillName.MagicResist, 57.6, 75.0); + SetSkill(SkillName.Tactics, 50.1, 70.0); + SetSkill(SkillName.Wrestling, 60.1, 80.0); - Fame = 2500; - Karma = -2500; + Fame = 2500; + Karma = -2500; - VirtualArmor = 22; + VirtualArmor = 22; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 83.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 83.1; + } + + public DireWolf(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a dire wolf corpse"; + public override string DefaultName => "a dire wolf"; + + public override int Meat => 1; + public override int Hides => 7; + public override HideType HideType => HideType.Spined; + public override FoodType FavoriteFood => FoodType.Meat; + public override PackInstinct PackInstinct => PackInstinct.Canine; + + 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(); + } } - - public DireWolf(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a dire wolf corpse"; - public override string DefaultName => "a dire wolf"; - - public override int Meat => 1; - public override int Hides => 7; - public override HideType HideType => HideType.Spined; - public override FoodType FavoriteFood => FoodType.Meat; - public override PackInstinct PackInstinct => PackInstinct.Canine; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Canines/GreyWolf.cs b/Projects/UOContent/Mobiles/Animals/Canines/GreyWolf.cs index 5e7a027f6..195bcfadc 100644 --- a/Projects/UOContent/Mobiles/Animals/Canines/GreyWolf.cs +++ b/Projects/UOContent/Mobiles/Animals/Canines/GreyWolf.cs @@ -1,69 +1,69 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Greywolf")] - public class GreyWolf : BaseCreature - { - [Constructible] - public GreyWolf() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Greywolf")] + public class GreyWolf : BaseCreature { - Body = Utility.RandomList(25, 27); - BaseSoundID = 0xE5; + [Constructible] + public GreyWolf() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = Utility.RandomList(25, 27); + BaseSoundID = 0xE5; - SetStr(56, 80); - SetDex(56, 75); - SetInt(31, 55); + SetStr(56, 80); + SetDex(56, 75); + SetInt(31, 55); - SetHits(34, 48); - SetMana(0); + SetHits(34, 48); + SetMana(0); - SetDamage(3, 7); + SetDamage(3, 7); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 15, 20); - SetResistance(ResistanceType.Fire, 10, 15); - SetResistance(ResistanceType.Cold, 20, 25); - SetResistance(ResistanceType.Poison, 10, 15); - SetResistance(ResistanceType.Energy, 10, 15); + SetResistance(ResistanceType.Physical, 15, 20); + SetResistance(ResistanceType.Fire, 10, 15); + SetResistance(ResistanceType.Cold, 20, 25); + SetResistance(ResistanceType.Poison, 10, 15); + SetResistance(ResistanceType.Energy, 10, 15); - SetSkill(SkillName.MagicResist, 20.1, 35.0); - SetSkill(SkillName.Tactics, 45.1, 60.0); - SetSkill(SkillName.Wrestling, 45.1, 60.0); + SetSkill(SkillName.MagicResist, 20.1, 35.0); + SetSkill(SkillName.Tactics, 45.1, 60.0); + SetSkill(SkillName.Wrestling, 45.1, 60.0); - Fame = 450; - Karma = 0; + Fame = 450; + Karma = 0; - VirtualArmor = 16; + VirtualArmor = 16; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 53.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 53.1; + } + + public GreyWolf(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a grey wolf corpse"; + public override string DefaultName => "a grey wolf"; + + public override int Meat => 1; + public override int Hides => 6; + public override FoodType FavoriteFood => FoodType.Meat; + public override PackInstinct PackInstinct => PackInstinct.Canine; + + 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(); + } } - - public GreyWolf(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a grey wolf corpse"; - public override string DefaultName => "a grey wolf"; - - public override int Meat => 1; - public override int Hides => 6; - public override FoodType FavoriteFood => FoodType.Meat; - public override PackInstinct PackInstinct => PackInstinct.Canine; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Canines/TimberWolf.cs b/Projects/UOContent/Mobiles/Animals/Canines/TimberWolf.cs index edd46f367..f808128cf 100644 --- a/Projects/UOContent/Mobiles/Animals/Canines/TimberWolf.cs +++ b/Projects/UOContent/Mobiles/Animals/Canines/TimberWolf.cs @@ -1,69 +1,69 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Timberwolf")] - public class TimberWolf : BaseCreature - { - [Constructible] - public TimberWolf() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Timberwolf")] + public class TimberWolf : BaseCreature { - Body = 225; - BaseSoundID = 0xE5; + [Constructible] + public TimberWolf() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 225; + BaseSoundID = 0xE5; - SetStr(56, 80); - SetDex(56, 75); - SetInt(11, 25); + SetStr(56, 80); + SetDex(56, 75); + SetInt(11, 25); - SetHits(34, 48); - SetMana(0); + SetHits(34, 48); + SetMana(0); - SetDamage(5, 9); + SetDamage(5, 9); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 15, 20); - SetResistance(ResistanceType.Fire, 5, 10); - SetResistance(ResistanceType.Cold, 10, 15); - SetResistance(ResistanceType.Poison, 5, 10); - SetResistance(ResistanceType.Energy, 5, 10); + SetResistance(ResistanceType.Physical, 15, 20); + SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Cold, 10, 15); + SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Energy, 5, 10); - SetSkill(SkillName.MagicResist, 27.6, 45.0); - SetSkill(SkillName.Tactics, 30.1, 50.0); - SetSkill(SkillName.Wrestling, 40.1, 60.0); + SetSkill(SkillName.MagicResist, 27.6, 45.0); + SetSkill(SkillName.Tactics, 30.1, 50.0); + SetSkill(SkillName.Wrestling, 40.1, 60.0); - Fame = 450; - Karma = 0; + Fame = 450; + Karma = 0; - VirtualArmor = 16; + VirtualArmor = 16; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 23.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 23.1; + } + + public TimberWolf(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a timber wolf corpse"; + public override string DefaultName => "a timber wolf"; + + public override int Meat => 1; + public override int Hides => 5; + public override FoodType FavoriteFood => FoodType.Meat; + public override PackInstinct PackInstinct => PackInstinct.Canine; + + 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(); + } } - - public TimberWolf(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a timber wolf corpse"; - public override string DefaultName => "a timber wolf"; - - public override int Meat => 1; - public override int Hides => 5; - public override FoodType FavoriteFood => FoodType.Meat; - public override PackInstinct PackInstinct => PackInstinct.Canine; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Canines/WhiteWolf.cs b/Projects/UOContent/Mobiles/Animals/Canines/WhiteWolf.cs index 5d3b0cd6d..bb57d611d 100644 --- a/Projects/UOContent/Mobiles/Animals/Canines/WhiteWolf.cs +++ b/Projects/UOContent/Mobiles/Animals/Canines/WhiteWolf.cs @@ -1,69 +1,69 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Whitewolf")] - public class WhiteWolf : BaseCreature - { - [Constructible] - public WhiteWolf() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Whitewolf")] + public class WhiteWolf : BaseCreature { - Body = Utility.RandomList(34, 37); - BaseSoundID = 0xE5; + [Constructible] + public WhiteWolf() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = Utility.RandomList(34, 37); + BaseSoundID = 0xE5; - SetStr(56, 80); - SetDex(56, 75); - SetInt(31, 55); + SetStr(56, 80); + SetDex(56, 75); + SetInt(31, 55); - SetHits(34, 48); - SetMana(0); + SetHits(34, 48); + SetMana(0); - SetDamage(3, 7); + SetDamage(3, 7); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 15, 20); - SetResistance(ResistanceType.Fire, 10, 15); - SetResistance(ResistanceType.Cold, 20, 25); - SetResistance(ResistanceType.Poison, 10, 15); - SetResistance(ResistanceType.Energy, 10, 15); + SetResistance(ResistanceType.Physical, 15, 20); + SetResistance(ResistanceType.Fire, 10, 15); + SetResistance(ResistanceType.Cold, 20, 25); + SetResistance(ResistanceType.Poison, 10, 15); + SetResistance(ResistanceType.Energy, 10, 15); - SetSkill(SkillName.MagicResist, 20.1, 35.0); - SetSkill(SkillName.Tactics, 45.1, 60.0); - SetSkill(SkillName.Wrestling, 45.1, 60.0); + SetSkill(SkillName.MagicResist, 20.1, 35.0); + SetSkill(SkillName.Tactics, 45.1, 60.0); + SetSkill(SkillName.Wrestling, 45.1, 60.0); - Fame = 450; - Karma = 0; + Fame = 450; + Karma = 0; - VirtualArmor = 16; + VirtualArmor = 16; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 65.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 65.1; + } + + public WhiteWolf(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a white wolf corpse"; + public override string DefaultName => "a white wolf"; + + public override int Meat => 1; + public override int Hides => 6; + public override FoodType FavoriteFood => FoodType.Meat; + public override PackInstinct PackInstinct => PackInstinct.Canine; + + 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(); + } } - - public WhiteWolf(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a white wolf corpse"; - public override string DefaultName => "a white wolf"; - - public override int Meat => 1; - public override int Hides => 6; - public override FoodType FavoriteFood => FoodType.Meat; - public override PackInstinct PackInstinct => PackInstinct.Canine; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Cows/Bull.cs b/Projects/UOContent/Mobiles/Animals/Cows/Bull.cs index b50818715..7328f0f8f 100644 --- a/Projects/UOContent/Mobiles/Animals/Cows/Bull.cs +++ b/Projects/UOContent/Mobiles/Animals/Cows/Bull.cs @@ -1,68 +1,68 @@ namespace Server.Mobiles { - public class Bull : BaseCreature - { - [Constructible] - public Bull() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Bull : BaseCreature { - Body = Utility.RandomList(0xE8, 0xE9); - BaseSoundID = 0x64; + [Constructible] + public Bull() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = Utility.RandomList(0xE8, 0xE9); + BaseSoundID = 0x64; - if (Utility.RandomDouble() <= 0.5) - Hue = 0x901; + if (Utility.RandomDouble() <= 0.5) + Hue = 0x901; - SetStr(77, 111); - SetDex(56, 75); - SetInt(47, 75); + SetStr(77, 111); + SetDex(56, 75); + SetInt(47, 75); - SetHits(50, 64); - SetMana(0); + SetHits(50, 64); + SetMana(0); - SetDamage(4, 9); + SetDamage(4, 9); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 25, 30); - SetResistance(ResistanceType.Cold, 10, 15); + SetResistance(ResistanceType.Physical, 25, 30); + SetResistance(ResistanceType.Cold, 10, 15); - SetSkill(SkillName.MagicResist, 17.6, 25.0); - SetSkill(SkillName.Tactics, 67.6, 85.0); - SetSkill(SkillName.Wrestling, 40.1, 57.5); + SetSkill(SkillName.MagicResist, 17.6, 25.0); + SetSkill(SkillName.Tactics, 67.6, 85.0); + SetSkill(SkillName.Wrestling, 40.1, 57.5); - Fame = 600; - Karma = 0; + Fame = 600; + Karma = 0; - VirtualArmor = 28; + VirtualArmor = 28; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 71.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 71.1; + } + + public Bull(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a bull corpse"; + public override string DefaultName => "a bull"; + + public override int Meat => 10; + public override int Hides => 15; + public override FoodType FavoriteFood => FoodType.GrainsAndHay; + public override PackInstinct PackInstinct => PackInstinct.Bull; + + 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(); + } } - - public Bull(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a bull corpse"; - public override string DefaultName => "a bull"; - - public override int Meat => 10; - public override int Hides => 15; - public override FoodType FavoriteFood => FoodType.GrainsAndHay; - public override PackInstinct PackInstinct => PackInstinct.Bull; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Cows/Cow.cs b/Projects/UOContent/Mobiles/Animals/Cows/Cow.cs index 599dd1400..d71580747 100644 --- a/Projects/UOContent/Mobiles/Animals/Cows/Cow.cs +++ b/Projects/UOContent/Mobiles/Animals/Cows/Cow.cs @@ -2,129 +2,129 @@ using System; namespace Server.Mobiles { - public class Cow : BaseCreature - { - [Constructible] - public Cow() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Cow : BaseCreature { - Body = Utility.RandomList(0xD8, 0xE7); - BaseSoundID = 0x78; + [Constructible] + public Cow() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = Utility.RandomList(0xD8, 0xE7); + BaseSoundID = 0x78; - SetStr(30); - SetDex(15); - SetInt(5); + SetStr(30); + SetDex(15); + SetInt(5); - SetHits(18); - SetMana(0); + SetHits(18); + SetMana(0); - SetDamage(1, 4); + SetDamage(1, 4); - SetDamage(1, 4); + SetDamage(1, 4); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 5, 15); + SetResistance(ResistanceType.Physical, 5, 15); - SetSkill(SkillName.MagicResist, 5.5); - SetSkill(SkillName.Tactics, 5.5); - SetSkill(SkillName.Wrestling, 5.5); + SetSkill(SkillName.MagicResist, 5.5); + SetSkill(SkillName.Tactics, 5.5); + SetSkill(SkillName.Wrestling, 5.5); - Fame = 300; - Karma = 0; + Fame = 300; + Karma = 0; - VirtualArmor = 10; + VirtualArmor = 10; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 11.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 11.1; - if (Core.AOS && Utility.Random(1000) == 0) // 0.1% chance to have mad cows - FightMode = FightMode.Closest; + if (Core.AOS && Utility.Random(1000) == 0) // 0.1% chance to have mad cows + FightMode = FightMode.Closest; + } + + public Cow(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a cow corpse"; + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime MilkedOn { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Milk { get; set; } + + public override string DefaultName => "a cow"; + + public override int Meat => 8; + public override int Hides => 12; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + + public override void OnDoubleClick(Mobile from) + { + base.OnDoubleClick(from); + + var random = Utility.Random(100); + + if (random < 5) + Tip(); + else if (random < 20) + PlaySound(120); + else if (random < 40) + PlaySound(121); + } + + public void Tip() + { + PlaySound(121); + Animate(8, 0, 3, true, false, 0); + } + + public bool TryMilk(Mobile from) + { + if (!from.InLOS(this) || !from.InRange(Location, 2)) + from.SendLocalizedMessage(1080400); // You can not milk the cow from this location. + if (Controlled && ControlMaster != from) + from.SendLocalizedMessage(1071182); // The cow nimbly escapes your attempts to milk it. + if (Milk == 0 && MilkedOn + TimeSpan.FromDays(1) > DateTime.UtcNow) + { + from.SendLocalizedMessage(1080198); // This cow can not be milked now. Please wait for some time. + } + else + { + if (Milk == 0) + Milk = 4; + + MilkedOn = DateTime.UtcNow; + Milk--; + + return true; + } + + return false; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + + writer.Write(MilkedOn); + writer.Write(Milk); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (version > 0) + { + MilkedOn = reader.ReadDateTime(); + Milk = reader.ReadInt(); + } + } } - - public Cow(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a cow corpse"; - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime MilkedOn { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Milk { get; set; } - - public override string DefaultName => "a cow"; - - public override int Meat => 8; - public override int Hides => 12; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - - public override void OnDoubleClick(Mobile from) - { - base.OnDoubleClick(from); - - int random = Utility.Random(100); - - if (random < 5) - Tip(); - else if (random < 20) - PlaySound(120); - else if (random < 40) - PlaySound(121); - } - - public void Tip() - { - PlaySound(121); - Animate(8, 0, 3, true, false, 0); - } - - public bool TryMilk(Mobile from) - { - if (!from.InLOS(this) || !from.InRange(Location, 2)) - from.SendLocalizedMessage(1080400); // You can not milk the cow from this location. - if (Controlled && ControlMaster != from) - from.SendLocalizedMessage(1071182); // The cow nimbly escapes your attempts to milk it. - if (Milk == 0 && MilkedOn + TimeSpan.FromDays(1) > DateTime.UtcNow) - { - from.SendLocalizedMessage(1080198); // This cow can not be milked now. Please wait for some time. - } - else - { - if (Milk == 0) - Milk = 4; - - MilkedOn = DateTime.UtcNow; - Milk--; - - return true; - } - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - - writer.Write(MilkedOn); - writer.Write(Milk); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version > 0) - { - MilkedOn = reader.ReadDateTime(); - Milk = reader.ReadInt(); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Felines/Cougar.cs b/Projects/UOContent/Mobiles/Animals/Felines/Cougar.cs index bba54284f..ede2b5ae5 100644 --- a/Projects/UOContent/Mobiles/Animals/Felines/Cougar.cs +++ b/Projects/UOContent/Mobiles/Animals/Felines/Cougar.cs @@ -1,67 +1,67 @@ namespace Server.Mobiles { - public class Cougar : BaseCreature - { - [Constructible] - public Cougar() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Cougar : BaseCreature { - Body = 63; - BaseSoundID = 0x73; + [Constructible] + public Cougar() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 63; + BaseSoundID = 0x73; - SetStr(56, 80); - SetDex(66, 85); - SetInt(26, 50); + SetStr(56, 80); + SetDex(66, 85); + SetInt(26, 50); - SetHits(34, 48); - SetMana(0); + SetHits(34, 48); + SetMana(0); - SetDamage(4, 10); + SetDamage(4, 10); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 20, 25); - SetResistance(ResistanceType.Fire, 5, 10); - SetResistance(ResistanceType.Cold, 10, 15); - SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Physical, 20, 25); + SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Cold, 10, 15); + SetResistance(ResistanceType.Poison, 5, 10); - SetSkill(SkillName.MagicResist, 15.1, 30.0); - SetSkill(SkillName.Tactics, 45.1, 60.0); - SetSkill(SkillName.Wrestling, 45.1, 60.0); + SetSkill(SkillName.MagicResist, 15.1, 30.0); + SetSkill(SkillName.Tactics, 45.1, 60.0); + SetSkill(SkillName.Wrestling, 45.1, 60.0); - Fame = 450; - Karma = 0; + Fame = 450; + Karma = 0; - VirtualArmor = 16; + VirtualArmor = 16; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 41.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 41.1; + } + + public Cougar(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a cougar corpse"; + public override string DefaultName => "a cougar"; + + public override int Meat => 1; + public override int Hides => 10; + public override FoodType FavoriteFood => FoodType.Fish | FoodType.Meat; + public override PackInstinct PackInstinct => PackInstinct.Feline; + + 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(); + } } - - public Cougar(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a cougar corpse"; - public override string DefaultName => "a cougar"; - - public override int Meat => 1; - public override int Hides => 10; - public override FoodType FavoriteFood => FoodType.Fish | FoodType.Meat; - public override PackInstinct PackInstinct => PackInstinct.Feline; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Felines/HellCat.cs b/Projects/UOContent/Mobiles/Animals/Felines/HellCat.cs index a5384f60e..b1742f463 100644 --- a/Projects/UOContent/Mobiles/Animals/Felines/HellCat.cs +++ b/Projects/UOContent/Mobiles/Animals/Felines/HellCat.cs @@ -1,74 +1,74 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Hellcat")] - public class HellCat : BaseCreature - { - [Constructible] - public HellCat() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Hellcat")] + public class HellCat : BaseCreature { - Body = 0xC9; - Hue = Utility.RandomList(0x647, 0x650, 0x659, 0x662, 0x66B, 0x674); - BaseSoundID = 0x69; + [Constructible] + public HellCat() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0xC9; + Hue = Utility.RandomList(0x647, 0x650, 0x659, 0x662, 0x66B, 0x674); + BaseSoundID = 0x69; - SetStr(51, 100); - SetDex(52, 150); - SetInt(13, 85); + SetStr(51, 100); + SetDex(52, 150); + SetInt(13, 85); - SetHits(48, 67); + SetHits(48, 67); - SetDamage(6, 12); + SetDamage(6, 12); - SetDamageType(ResistanceType.Physical, 40); - SetDamageType(ResistanceType.Fire, 60); + SetDamageType(ResistanceType.Physical, 40); + SetDamageType(ResistanceType.Fire, 60); - SetResistance(ResistanceType.Physical, 25, 35); - SetResistance(ResistanceType.Fire, 80, 90); - SetResistance(ResistanceType.Energy, 15, 20); + SetResistance(ResistanceType.Physical, 25, 35); + SetResistance(ResistanceType.Fire, 80, 90); + SetResistance(ResistanceType.Energy, 15, 20); - SetSkill(SkillName.MagicResist, 45.1, 60.0); - SetSkill(SkillName.Tactics, 40.1, 55.0); - SetSkill(SkillName.Wrestling, 30.1, 40.0); + SetSkill(SkillName.MagicResist, 45.1, 60.0); + SetSkill(SkillName.Tactics, 40.1, 55.0); + SetSkill(SkillName.Wrestling, 30.1, 40.0); - Fame = 1000; - Karma = -1000; + Fame = 1000; + Karma = -1000; - VirtualArmor = 30; + VirtualArmor = 30; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 71.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 71.1; + } + + public HellCat(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a hell cat corpse"; + public override string DefaultName => "a hell cat"; + + public override bool HasBreath => true; // fire breath enabled + public override int Hides => 10; + public override HideType HideType => HideType.Spined; + public override FoodType FavoriteFood => FoodType.Meat; + public override PackInstinct PackInstinct => PackInstinct.Feline; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + 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(); + } } - - public HellCat(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a hell cat corpse"; - public override string DefaultName => "a hell cat"; - - public override bool HasBreath => true; // fire breath enabled - public override int Hides => 10; - public override HideType HideType => HideType.Spined; - public override FoodType FavoriteFood => FoodType.Meat; - public override PackInstinct PackInstinct => PackInstinct.Feline; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Felines/Panther.cs b/Projects/UOContent/Mobiles/Animals/Felines/Panther.cs index 9f7e9b5d8..966d998a6 100644 --- a/Projects/UOContent/Mobiles/Animals/Felines/Panther.cs +++ b/Projects/UOContent/Mobiles/Animals/Felines/Panther.cs @@ -1,68 +1,68 @@ namespace Server.Mobiles { - public class Panther : BaseCreature - { - [Constructible] - public Panther() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Panther : BaseCreature { - Body = 0xD6; - Hue = 0x901; - BaseSoundID = 0x462; + [Constructible] + public Panther() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 0xD6; + Hue = 0x901; + BaseSoundID = 0x462; - SetStr(61, 85); - SetDex(86, 105); - SetInt(26, 50); + SetStr(61, 85); + SetDex(86, 105); + SetInt(26, 50); - SetHits(37, 51); - SetMana(0); + SetHits(37, 51); + SetMana(0); - SetDamage(4, 12); + SetDamage(4, 12); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 20, 25); - SetResistance(ResistanceType.Fire, 5, 10); - SetResistance(ResistanceType.Cold, 10, 15); - SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Physical, 20, 25); + SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Cold, 10, 15); + SetResistance(ResistanceType.Poison, 5, 10); - SetSkill(SkillName.MagicResist, 15.1, 30.0); - SetSkill(SkillName.Tactics, 50.1, 65.0); - SetSkill(SkillName.Wrestling, 50.1, 65.0); + SetSkill(SkillName.MagicResist, 15.1, 30.0); + SetSkill(SkillName.Tactics, 50.1, 65.0); + SetSkill(SkillName.Wrestling, 50.1, 65.0); - Fame = 450; - Karma = 0; + Fame = 450; + Karma = 0; - VirtualArmor = 16; + VirtualArmor = 16; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 53.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 53.1; + } + + public Panther(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a panther corpse"; + public override string DefaultName => "a panther"; + + public override int Meat => 1; + public override int Hides => 10; + public override FoodType FavoriteFood => FoodType.Meat | FoodType.Fish; + public override PackInstinct PackInstinct => PackInstinct.Feline; + + 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(); + } } - - public Panther(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a panther corpse"; - public override string DefaultName => "a panther"; - - public override int Meat => 1; - public override int Hides => 10; - public override FoodType FavoriteFood => FoodType.Meat | FoodType.Fish; - public override PackInstinct PackInstinct => PackInstinct.Feline; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Felines/PredatorHellCat.cs b/Projects/UOContent/Mobiles/Animals/Felines/PredatorHellCat.cs index 3439d3e8d..8dcf0286f 100644 --- a/Projects/UOContent/Mobiles/Animals/Felines/PredatorHellCat.cs +++ b/Projects/UOContent/Mobiles/Animals/Felines/PredatorHellCat.cs @@ -1,73 +1,73 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Preditorhellcat")] - public class PredatorHellCat : BaseCreature - { - [Constructible] - public PredatorHellCat() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Preditorhellcat")] + public class PredatorHellCat : BaseCreature { - Body = 127; - BaseSoundID = 0xBA; + [Constructible] + public PredatorHellCat() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 127; + BaseSoundID = 0xBA; - SetStr(161, 185); - SetDex(96, 115); - SetInt(76, 100); + SetStr(161, 185); + SetDex(96, 115); + SetInt(76, 100); - SetHits(97, 131); + SetHits(97, 131); - SetDamage(5, 17); + SetDamage(5, 17); - SetDamageType(ResistanceType.Physical, 75); - SetDamageType(ResistanceType.Fire, 25); + SetDamageType(ResistanceType.Physical, 75); + SetDamageType(ResistanceType.Fire, 25); - SetResistance(ResistanceType.Physical, 25, 35); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Energy, 5, 15); + SetResistance(ResistanceType.Physical, 25, 35); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Energy, 5, 15); - SetSkill(SkillName.MagicResist, 75.1, 90.0); - SetSkill(SkillName.Tactics, 50.1, 65.0); - SetSkill(SkillName.Wrestling, 50.1, 65.0); + SetSkill(SkillName.MagicResist, 75.1, 90.0); + SetSkill(SkillName.Tactics, 50.1, 65.0); + SetSkill(SkillName.Wrestling, 50.1, 65.0); - Fame = 2500; - Karma = -2500; + Fame = 2500; + Karma = -2500; - VirtualArmor = 30; + VirtualArmor = 30; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 89.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 89.1; + } + + public PredatorHellCat(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a hell cat corpse"; + public override string DefaultName => "a hell cat"; + + public override bool HasBreath => true; // fire breath enabled + public override int Hides => 10; + public override HideType HideType => HideType.Spined; + public override FoodType FavoriteFood => FoodType.Meat; + public override PackInstinct PackInstinct => PackInstinct.Feline; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + } + + 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(); + } } - - public PredatorHellCat(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a hell cat corpse"; - public override string DefaultName => "a hell cat"; - - public override bool HasBreath => true; // fire breath enabled - public override int Hides => 10; - public override HideType HideType => HideType.Spined; - public override FoodType FavoriteFood => FoodType.Meat; - public override PackInstinct PackInstinct => PackInstinct.Feline; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Felines/SnowLeopard.cs b/Projects/UOContent/Mobiles/Animals/Felines/SnowLeopard.cs index 531e0bfe2..28f86bb0e 100644 --- a/Projects/UOContent/Mobiles/Animals/Felines/SnowLeopard.cs +++ b/Projects/UOContent/Mobiles/Animals/Felines/SnowLeopard.cs @@ -1,69 +1,69 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Snowleopard")] - public class SnowLeopard : BaseCreature - { - [Constructible] - public SnowLeopard() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Snowleopard")] + public class SnowLeopard : BaseCreature { - Body = Utility.RandomList(64, 65); - BaseSoundID = 0x73; + [Constructible] + public SnowLeopard() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = Utility.RandomList(64, 65); + BaseSoundID = 0x73; - SetStr(56, 80); - SetDex(66, 85); - SetInt(26, 50); + SetStr(56, 80); + SetDex(66, 85); + SetInt(26, 50); - SetHits(34, 48); - SetMana(0); + SetHits(34, 48); + SetMana(0); - SetDamage(3, 9); + SetDamage(3, 9); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 20, 25); - SetResistance(ResistanceType.Fire, 5, 10); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 10, 20); - SetResistance(ResistanceType.Energy, 20, 30); + SetResistance(ResistanceType.Physical, 20, 25); + SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Energy, 20, 30); - SetSkill(SkillName.MagicResist, 25.1, 35.0); - SetSkill(SkillName.Tactics, 45.1, 60.0); - SetSkill(SkillName.Wrestling, 40.1, 50.0); + SetSkill(SkillName.MagicResist, 25.1, 35.0); + SetSkill(SkillName.Tactics, 45.1, 60.0); + SetSkill(SkillName.Wrestling, 40.1, 50.0); - Fame = 450; - Karma = 0; + Fame = 450; + Karma = 0; - VirtualArmor = 24; + VirtualArmor = 24; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 53.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 53.1; + } + + public SnowLeopard(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a leopard corpse"; + public override string DefaultName => "a snow leopard"; + + public override int Meat => 1; + public override int Hides => 8; + public override FoodType FavoriteFood => FoodType.Meat | FoodType.Fish; + public override PackInstinct PackInstinct => PackInstinct.Feline; + + 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(); + } } - - public SnowLeopard(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a leopard corpse"; - public override string DefaultName => "a snow leopard"; - - public override int Meat => 1; - public override int Hides => 8; - public override FoodType FavoriteFood => FoodType.Meat | FoodType.Fish; - public override PackInstinct PackInstinct => PackInstinct.Feline; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Misc/Boar.cs b/Projects/UOContent/Mobiles/Animals/Misc/Boar.cs index 375cb54ab..57dfbb36c 100644 --- a/Projects/UOContent/Mobiles/Animals/Misc/Boar.cs +++ b/Projects/UOContent/Mobiles/Animals/Misc/Boar.cs @@ -1,64 +1,64 @@ namespace Server.Mobiles { - public class Boar : BaseCreature - { - [Constructible] - public Boar() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Boar : BaseCreature { - Body = 0x122; - BaseSoundID = 0xC4; + [Constructible] + public Boar() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 0x122; + BaseSoundID = 0xC4; - SetStr(25); - SetDex(15); - SetInt(5); + SetStr(25); + SetDex(15); + SetInt(5); - SetHits(15); - SetMana(0); + SetHits(15); + SetMana(0); - SetDamage(3, 6); + SetDamage(3, 6); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 10, 15); - SetResistance(ResistanceType.Fire, 5, 10); - SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Physical, 10, 15); + SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Poison, 5, 10); - SetSkill(SkillName.MagicResist, 9.0); - SetSkill(SkillName.Tactics, 9.0); - SetSkill(SkillName.Wrestling, 9.0); + SetSkill(SkillName.MagicResist, 9.0); + SetSkill(SkillName.Tactics, 9.0); + SetSkill(SkillName.Wrestling, 9.0); - Fame = 300; - Karma = 0; + Fame = 300; + Karma = 0; - VirtualArmor = 10; + VirtualArmor = 10; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 29.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 29.1; + } + + public Boar(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a pig corpse"; + public override string DefaultName => "a boar"; + + public override int Meat => 2; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + + 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(); + } } - - public Boar(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a pig corpse"; - public override string DefaultName => "a boar"; - - public override int Meat => 2; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Misc/BullFrog.cs b/Projects/UOContent/Mobiles/Animals/Misc/BullFrog.cs index bc48bbd4d..7ef3d5fcd 100644 --- a/Projects/UOContent/Mobiles/Animals/Misc/BullFrog.cs +++ b/Projects/UOContent/Mobiles/Animals/Misc/BullFrog.cs @@ -1,70 +1,70 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Bullfrog")] - public class BullFrog : BaseCreature - { - [Constructible] - public BullFrog() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Bullfrog")] + public class BullFrog : BaseCreature { - Body = 81; - Hue = Utility.RandomList(0x5AC, 0x5A3, 0x59A, 0x591, 0x588, 0x57F); - BaseSoundID = 0x266; + [Constructible] + public BullFrog() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 81; + Hue = Utility.RandomList(0x5AC, 0x5A3, 0x59A, 0x591, 0x588, 0x57F); + BaseSoundID = 0x266; - SetStr(46, 70); - SetDex(6, 25); - SetInt(11, 20); + SetStr(46, 70); + SetDex(6, 25); + SetInt(11, 20); - SetHits(28, 42); - SetMana(0); + SetHits(28, 42); + SetMana(0); - SetDamage(1, 2); + SetDamage(1, 2); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 5, 10); + SetResistance(ResistanceType.Physical, 5, 10); - SetSkill(SkillName.MagicResist, 25.1, 40.0); - SetSkill(SkillName.Tactics, 40.1, 60.0); - SetSkill(SkillName.Wrestling, 40.1, 60.0); + SetSkill(SkillName.MagicResist, 25.1, 40.0); + SetSkill(SkillName.Tactics, 40.1, 60.0); + SetSkill(SkillName.Wrestling, 40.1, 60.0); - Fame = 350; - Karma = 0; + Fame = 350; + Karma = 0; - VirtualArmor = 6; + VirtualArmor = 6; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 23.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 23.1; + } + + public BullFrog(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a bull frog corpse"; + public override string DefaultName => "a bull frog"; + + public override int Meat => 1; + public override int Hides => 4; + public override FoodType FavoriteFood => FoodType.Fish | FoodType.Meat; + + public override void GenerateLoot() + { + AddLoot(LootPack.Poor); + } + + 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(); + } } - - public BullFrog(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a bull frog corpse"; - public override string DefaultName => "a bull frog"; - - public override int Meat => 1; - public override int Hides => 4; - public override FoodType FavoriteFood => FoodType.Fish | FoodType.Meat; - - public override void GenerateLoot() - { - AddLoot(LootPack.Poor); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Misc/Dolphin.cs b/Projects/UOContent/Mobiles/Animals/Misc/Dolphin.cs index 7ddaf9c6c..1e185432e 100644 --- a/Projects/UOContent/Mobiles/Animals/Misc/Dolphin.cs +++ b/Projects/UOContent/Mobiles/Animals/Misc/Dolphin.cs @@ -1,86 +1,86 @@ namespace Server.Mobiles { - public class Dolphin : BaseCreature - { - [Constructible] - public Dolphin() - : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Dolphin : BaseCreature { - Body = 0x97; - BaseSoundID = 0x8A; + [Constructible] + public Dolphin() + : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 0x97; + BaseSoundID = 0x8A; - SetStr(21, 49); - SetDex(66, 85); - SetInt(96, 110); + SetStr(21, 49); + SetDex(66, 85); + SetInt(96, 110); - SetHits(15, 27); + SetHits(15, 27); - SetDamage(3, 6); + SetDamage(3, 6); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 15, 20); - SetResistance(ResistanceType.Fire, 70, 80); - SetResistance(ResistanceType.Cold, 25, 30); - SetResistance(ResistanceType.Poison, 10, 15); - SetResistance(ResistanceType.Energy, 10, 15); + SetResistance(ResistanceType.Physical, 15, 20); + SetResistance(ResistanceType.Fire, 70, 80); + SetResistance(ResistanceType.Cold, 25, 30); + SetResistance(ResistanceType.Poison, 10, 15); + SetResistance(ResistanceType.Energy, 10, 15); - SetSkill(SkillName.MagicResist, 15.1, 20.0); - SetSkill(SkillName.Tactics, 19.2, 29.0); - SetSkill(SkillName.Wrestling, 19.2, 29.0); + SetSkill(SkillName.MagicResist, 15.1, 20.0); + SetSkill(SkillName.Tactics, 19.2, 29.0); + SetSkill(SkillName.Wrestling, 19.2, 29.0); - Fame = 500; - Karma = 2000; + Fame = 500; + Karma = 2000; - VirtualArmor = 16; - CanSwim = true; - CantWalk = true; + VirtualArmor = 16; + CanSwim = true; + CantWalk = true; + } + + public Dolphin(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a dolphin corpse"; + public override string DefaultName => "a dolphin"; + + public override int Meat => 1; + + public override void OnDoubleClick(Mobile from) + { + if (from.AccessLevel >= AccessLevel.GameMaster) + Jump(); + } + + public virtual void Jump() + { + if (Utility.RandomBool()) + Animate(3, 16, 1, true, false, 0); + else + Animate(4, 20, 1, true, false, 0); + } + + public override void OnThink() + { + if (Utility.RandomDouble() < .005) // slim chance to jump + Jump(); + + base.OnThink(); + } + + 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(); + } } - - public Dolphin(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a dolphin corpse"; - public override string DefaultName => "a dolphin"; - - public override int Meat => 1; - - public override void OnDoubleClick(Mobile from) - { - if (from.AccessLevel >= AccessLevel.GameMaster) - Jump(); - } - - public virtual void Jump() - { - if (Utility.RandomBool()) - Animate(3, 16, 1, true, false, 0); - else - Animate(4, 20, 1, true, false, 0); - } - - public override void OnThink() - { - if (Utility.RandomDouble() < .005) // slim chance to jump - Jump(); - - base.OnThink(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Misc/Gaman.cs b/Projects/UOContent/Mobiles/Animals/Misc/Gaman.cs index 7446374f7..380890a2c 100644 --- a/Projects/UOContent/Mobiles/Animals/Misc/Gaman.cs +++ b/Projects/UOContent/Mobiles/Animals/Misc/Gaman.cs @@ -2,79 +2,79 @@ using Server.Items; namespace Server.Mobiles { - public class Gaman : BaseCreature - { - [Constructible] - public Gaman() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Gaman : BaseCreature { - Body = 248; + [Constructible] + public Gaman() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 248; - SetStr(146, 175); - SetDex(111, 150); - SetInt(46, 60); + SetStr(146, 175); + SetDex(111, 150); + SetInt(46, 60); - SetHits(131, 160); - SetMana(0); + SetHits(131, 160); + SetMana(0); - SetDamage(6, 11); + SetDamage(6, 11); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 50, 70); - SetResistance(ResistanceType.Fire, 30, 50); - SetResistance(ResistanceType.Cold, 30, 50); - SetResistance(ResistanceType.Poison, 40, 60); - SetResistance(ResistanceType.Energy, 30, 50); + SetResistance(ResistanceType.Physical, 50, 70); + SetResistance(ResistanceType.Fire, 30, 50); + SetResistance(ResistanceType.Cold, 30, 50); + SetResistance(ResistanceType.Poison, 40, 60); + SetResistance(ResistanceType.Energy, 30, 50); - SetSkill(SkillName.MagicResist, 37.6, 42.5); - SetSkill(SkillName.Tactics, 70.6, 83.0); - SetSkill(SkillName.Wrestling, 50.1, 57.5); + SetSkill(SkillName.MagicResist, 37.6, 42.5); + SetSkill(SkillName.Tactics, 70.6, 83.0); + SetSkill(SkillName.Wrestling, 50.1, 57.5); - Fame = 2000; - Karma = -2000; + Fame = 2000; + Karma = -2000; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 68.7; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 68.7; + } + + public Gaman(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a gaman corpse"; + public override string DefaultName => "a gaman"; + + public override int Meat => 10; + public override int Hides => 15; + public override FoodType FavoriteFood => FoodType.GrainsAndHay; + + public override int GetAngerSound() => 0x4F8; + + public override int GetIdleSound() => 0x4F7; + + public override int GetAttackSound() => 0x4F6; + + public override int GetHurtSound() => 0x4F9; + + public override int GetDeathSound() => 0x4F5; + + public override void OnDeath(Container c) + { + base.OnDeath(c); + c.DropItem(new GamanHorns(Utility.RandomBool() ? 1 : 2)); + } + + 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(); + } } - - public Gaman(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a gaman corpse"; - public override string DefaultName => "a gaman"; - - public override int Meat => 10; - public override int Hides => 15; - public override FoodType FavoriteFood => FoodType.GrainsAndHay; - - public override int GetAngerSound() => 0x4F8; - - public override int GetIdleSound() => 0x4F7; - - public override int GetAttackSound() => 0x4F6; - - public override int GetHurtSound() => 0x4F9; - - public override int GetDeathSound() => 0x4F5; - - public override void OnDeath(Container c) - { - base.OnDeath(c); - c.DropItem(new GamanHorns(Utility.RandomBool() ? 1 : 2)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Misc/GiantToad.cs b/Projects/UOContent/Mobiles/Animals/Misc/GiantToad.cs index f86d035bf..6730d6b21 100644 --- a/Projects/UOContent/Mobiles/Animals/Misc/GiantToad.cs +++ b/Projects/UOContent/Mobiles/Animals/Misc/GiantToad.cs @@ -1,76 +1,76 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Gianttoad")] - public class GiantToad : BaseCreature - { - [Constructible] - public GiantToad() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Gianttoad")] + public class GiantToad : BaseCreature { - Body = 80; - BaseSoundID = 0x26B; + [Constructible] + public GiantToad() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 80; + BaseSoundID = 0x26B; - SetStr(76, 100); - SetDex(6, 25); - SetInt(11, 20); + SetStr(76, 100); + SetDex(6, 25); + SetInt(11, 20); - SetHits(46, 60); - SetMana(0); + SetHits(46, 60); + SetMana(0); - SetDamage(5, 17); + SetDamage(5, 17); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 20, 25); - SetResistance(ResistanceType.Fire, 5, 10); - SetResistance(ResistanceType.Energy, 5, 10); + SetResistance(ResistanceType.Physical, 20, 25); + SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Energy, 5, 10); - SetSkill(SkillName.MagicResist, 25.1, 40.0); - SetSkill(SkillName.Tactics, 40.1, 60.0); - SetSkill(SkillName.Wrestling, 40.1, 60.0); + SetSkill(SkillName.MagicResist, 25.1, 40.0); + SetSkill(SkillName.Tactics, 40.1, 60.0); + SetSkill(SkillName.Wrestling, 40.1, 60.0); - Fame = 750; - Karma = -750; + Fame = 750; + Karma = -750; - VirtualArmor = 24; + VirtualArmor = 24; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 77.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 77.1; + } + + public GiantToad(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a giant toad corpse"; + public override string DefaultName => "a giant toad"; + + public override int Hides => 12; + public override HideType HideType => HideType.Spined; + public override FoodType FavoriteFood => FoodType.Fish | FoodType.Meat; + + public override void GenerateLoot() + { + AddLoot(LootPack.Poor); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + if (version < 1) + { + AI = AIType.AI_Melee; + FightMode = FightMode.Closest; + } + } } - - public GiantToad(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a giant toad corpse"; - public override string DefaultName => "a giant toad"; - - public override int Hides => 12; - public override HideType HideType => HideType.Spined; - public override FoodType FavoriteFood => FoodType.Fish | FoodType.Meat; - - public override void GenerateLoot() - { - AddLoot(LootPack.Poor); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - if (version < 1) - { - AI = AIType.AI_Melee; - FightMode = FightMode.Closest; - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Misc/Goat.cs b/Projects/UOContent/Mobiles/Animals/Misc/Goat.cs index 2dab9d6ce..3e45ad600 100644 --- a/Projects/UOContent/Mobiles/Animals/Misc/Goat.cs +++ b/Projects/UOContent/Mobiles/Animals/Misc/Goat.cs @@ -1,63 +1,63 @@ namespace Server.Mobiles { - public class Goat : BaseCreature - { - [Constructible] - public Goat() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Goat : BaseCreature { - Body = 0xD1; - BaseSoundID = 0x99; + [Constructible] + public Goat() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 0xD1; + BaseSoundID = 0x99; - SetStr(19); - SetDex(15); - SetInt(5); + SetStr(19); + SetDex(15); + SetInt(5); - SetHits(12); - SetMana(0); + SetHits(12); + SetMana(0); - SetDamage(3, 4); + SetDamage(3, 4); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 5, 15); + SetResistance(ResistanceType.Physical, 5, 15); - SetSkill(SkillName.MagicResist, 5.0); - SetSkill(SkillName.Tactics, 5.0); - SetSkill(SkillName.Wrestling, 5.0); + SetSkill(SkillName.MagicResist, 5.0); + SetSkill(SkillName.Tactics, 5.0); + SetSkill(SkillName.Wrestling, 5.0); - Fame = 150; - Karma = 0; + Fame = 150; + Karma = 0; - VirtualArmor = 10; + VirtualArmor = 10; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 11.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 11.1; + } + + public Goat(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a goat corpse"; + public override string DefaultName => "a goat"; + + public override int Meat => 2; + public override int Hides => 8; + public override FoodType FavoriteFood => FoodType.GrainsAndHay | FoodType.FruitsAndVegies; + + 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(); + } } - - public Goat(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a goat corpse"; - public override string DefaultName => "a goat"; - - public override int Meat => 2; - public override int Hides => 8; - public override FoodType FavoriteFood => FoodType.GrainsAndHay | FoodType.FruitsAndVegies; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Misc/Gorilla.cs b/Projects/UOContent/Mobiles/Animals/Misc/Gorilla.cs index fa1e23e6c..9978d0118 100644 --- a/Projects/UOContent/Mobiles/Animals/Misc/Gorilla.cs +++ b/Projects/UOContent/Mobiles/Animals/Misc/Gorilla.cs @@ -1,65 +1,65 @@ namespace Server.Mobiles { - public class Gorilla : BaseCreature - { - [Constructible] - public Gorilla() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Gorilla : BaseCreature { - Body = 0x1D; - BaseSoundID = 0x9E; + [Constructible] + public Gorilla() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 0x1D; + BaseSoundID = 0x9E; - SetStr(53, 95); - SetDex(36, 55); - SetInt(36, 60); + SetStr(53, 95); + SetDex(36, 55); + SetInt(36, 60); - SetHits(38, 51); - SetMana(0); + SetHits(38, 51); + SetMana(0); - SetDamage(4, 10); + SetDamage(4, 10); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 20, 25); - SetResistance(ResistanceType.Fire, 5, 10); - SetResistance(ResistanceType.Cold, 10, 15); + SetResistance(ResistanceType.Physical, 20, 25); + SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Cold, 10, 15); - SetSkill(SkillName.MagicResist, 45.1, 60.0); - SetSkill(SkillName.Tactics, 43.3, 58.0); - SetSkill(SkillName.Wrestling, 43.3, 58.0); + SetSkill(SkillName.MagicResist, 45.1, 60.0); + SetSkill(SkillName.Tactics, 43.3, 58.0); + SetSkill(SkillName.Wrestling, 43.3, 58.0); - Fame = 450; - Karma = 0; + Fame = 450; + Karma = 0; - VirtualArmor = 20; + VirtualArmor = 20; - Tamable = true; - ControlSlots = 1; - MinTameSkill = -18.9; + Tamable = true; + ControlSlots = 1; + MinTameSkill = -18.9; + } + + public Gorilla(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a gorilla corpse"; + public override string DefaultName => "a gorilla"; + + public override int Meat => 1; + public override int Hides => 6; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + + 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(); + } } - - public Gorilla(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a gorilla corpse"; - public override string DefaultName => "a gorilla"; - - public override int Meat => 1; - public override int Hides => 6; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Misc/GreatHart.cs b/Projects/UOContent/Mobiles/Animals/Misc/GreatHart.cs index ee93e76af..470c773b3 100644 --- a/Projects/UOContent/Mobiles/Animals/Misc/GreatHart.cs +++ b/Projects/UOContent/Mobiles/Animals/Misc/GreatHart.cs @@ -1,70 +1,70 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Greathart")] - public class GreatHart : BaseCreature - { - [Constructible] - public GreatHart() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Greathart")] + public class GreatHart : BaseCreature { - Body = 0xEA; + [Constructible] + public GreatHart() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 0xEA; - SetStr(41, 71); - SetDex(47, 77); - SetInt(27, 57); + SetStr(41, 71); + SetDex(47, 77); + SetInt(27, 57); - SetHits(27, 41); - SetMana(0); + SetHits(27, 41); + SetMana(0); - SetDamage(5, 9); + SetDamage(5, 9); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 20, 25); - SetResistance(ResistanceType.Cold, 5, 10); + SetResistance(ResistanceType.Physical, 20, 25); + SetResistance(ResistanceType.Cold, 5, 10); - SetSkill(SkillName.MagicResist, 26.8, 44.5); - SetSkill(SkillName.Tactics, 29.8, 47.5); - SetSkill(SkillName.Wrestling, 29.8, 47.5); + SetSkill(SkillName.MagicResist, 26.8, 44.5); + SetSkill(SkillName.Tactics, 29.8, 47.5); + SetSkill(SkillName.Wrestling, 29.8, 47.5); - Fame = 300; - Karma = 0; + Fame = 300; + Karma = 0; - VirtualArmor = 24; + VirtualArmor = 24; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 59.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 59.1; + } + + public GreatHart(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a deer corpse"; + public override string DefaultName => "a great hart"; + + public override int Meat => 6; + public override int Hides => 15; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + + public override int GetAttackSound() => 0x82; + + public override int GetHurtSound() => 0x83; + + public override int GetDeathSound() => 0x84; + + 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(); + } } - - public GreatHart(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a deer corpse"; - public override string DefaultName => "a great hart"; - - public override int Meat => 6; - public override int Hides => 15; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - - public override int GetAttackSound() => 0x82; - - public override int GetHurtSound() => 0x83; - - public override int GetDeathSound() => 0x84; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Misc/Hind.cs b/Projects/UOContent/Mobiles/Animals/Misc/Hind.cs index 1639833a9..96ba6bc12 100644 --- a/Projects/UOContent/Mobiles/Animals/Misc/Hind.cs +++ b/Projects/UOContent/Mobiles/Animals/Misc/Hind.cs @@ -1,69 +1,69 @@ namespace Server.Mobiles { - public class Hind : BaseCreature - { - [Constructible] - public Hind() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Hind : BaseCreature { - Body = 0xED; + [Constructible] + public Hind() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 0xED; - SetStr(21, 51); - SetDex(47, 77); - SetInt(17, 47); + SetStr(21, 51); + SetDex(47, 77); + SetInt(17, 47); - SetHits(15, 29); - SetMana(0); + SetHits(15, 29); + SetMana(0); - SetDamage(4); + SetDamage(4); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 5, 15); - SetResistance(ResistanceType.Cold, 5); + SetResistance(ResistanceType.Physical, 5, 15); + SetResistance(ResistanceType.Cold, 5); - SetSkill(SkillName.MagicResist, 15.0); - SetSkill(SkillName.Tactics, 19.0); - SetSkill(SkillName.Wrestling, 26.0); + SetSkill(SkillName.MagicResist, 15.0); + SetSkill(SkillName.Tactics, 19.0); + SetSkill(SkillName.Wrestling, 26.0); - Fame = 300; - Karma = 0; + Fame = 300; + Karma = 0; - VirtualArmor = 8; + VirtualArmor = 8; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 23.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 23.1; + } + + public Hind(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a deer corpse"; + public override string DefaultName => "a hind"; + + public override int Meat => 5; + public override int Hides => 8; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + + public override int GetAttackSound() => 0x82; + + public override int GetHurtSound() => 0x83; + + public override int GetDeathSound() => 0x84; + + 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(); + } } - - public Hind(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a deer corpse"; - public override string DefaultName => "a hind"; - - public override int Meat => 5; - public override int Hides => 8; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - - public override int GetAttackSound() => 0x82; - - public override int GetHurtSound() => 0x83; - - public override int GetDeathSound() => 0x84; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Misc/Llama.cs b/Projects/UOContent/Mobiles/Animals/Misc/Llama.cs index 6799b733e..e8f4976d5 100644 --- a/Projects/UOContent/Mobiles/Animals/Misc/Llama.cs +++ b/Projects/UOContent/Mobiles/Animals/Misc/Llama.cs @@ -1,63 +1,63 @@ namespace Server.Mobiles { - public class Llama : BaseCreature - { - [Constructible] - public Llama() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Llama : BaseCreature { - Body = 0xDC; - BaseSoundID = 0x3F3; + [Constructible] + public Llama() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 0xDC; + BaseSoundID = 0x3F3; - SetStr(21, 49); - SetDex(36, 55); - SetInt(16, 30); + SetStr(21, 49); + SetDex(36, 55); + SetInt(16, 30); - SetHits(15, 27); - SetMana(0); + SetHits(15, 27); + SetMana(0); - SetDamage(3, 5); + SetDamage(3, 5); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 15, 20); + SetResistance(ResistanceType.Physical, 15, 20); - SetSkill(SkillName.MagicResist, 15.1, 20.0); - SetSkill(SkillName.Tactics, 19.2, 29.0); - SetSkill(SkillName.Wrestling, 19.2, 29.0); + SetSkill(SkillName.MagicResist, 15.1, 20.0); + SetSkill(SkillName.Tactics, 19.2, 29.0); + SetSkill(SkillName.Wrestling, 19.2, 29.0); - Fame = 300; - Karma = 0; + Fame = 300; + Karma = 0; - VirtualArmor = 16; + VirtualArmor = 16; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 35.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 35.1; + } + + public Llama(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a llama corpse"; + public override string DefaultName => "a llama"; + + public override int Meat => 1; + public override int Hides => 12; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + + 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(); + } } - - public Llama(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a llama corpse"; - public override string DefaultName => "a llama"; - - public override int Meat => 1; - public override int Hides => 12; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Misc/MountainGoat.cs b/Projects/UOContent/Mobiles/Animals/Misc/MountainGoat.cs index 2f1872ec3..a0d403404 100644 --- a/Projects/UOContent/Mobiles/Animals/Misc/MountainGoat.cs +++ b/Projects/UOContent/Mobiles/Animals/Misc/MountainGoat.cs @@ -1,67 +1,67 @@ namespace Server.Mobiles { - public class MountainGoat : BaseCreature - { - [Constructible] - public MountainGoat() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class MountainGoat : BaseCreature { - Body = 88; - BaseSoundID = 0x99; + [Constructible] + public MountainGoat() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 88; + BaseSoundID = 0x99; - SetStr(22, 64); - SetDex(56, 75); - SetInt(16, 30); + SetStr(22, 64); + SetDex(56, 75); + SetInt(16, 30); - SetHits(20, 33); - SetMana(0); + SetHits(20, 33); + SetMana(0); - SetDamage(3, 7); + SetDamage(3, 7); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 10, 20); - SetResistance(ResistanceType.Fire, 5, 10); - SetResistance(ResistanceType.Cold, 10, 20); - SetResistance(ResistanceType.Poison, 10, 15); - SetResistance(ResistanceType.Energy, 10, 15); + SetResistance(ResistanceType.Physical, 10, 20); + SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Poison, 10, 15); + SetResistance(ResistanceType.Energy, 10, 15); - SetSkill(SkillName.MagicResist, 25.1, 30.0); - SetSkill(SkillName.Tactics, 29.3, 44.0); - SetSkill(SkillName.Wrestling, 29.3, 44.0); + SetSkill(SkillName.MagicResist, 25.1, 30.0); + SetSkill(SkillName.Tactics, 29.3, 44.0); + SetSkill(SkillName.Wrestling, 29.3, 44.0); - Fame = 300; - Karma = 0; + Fame = 300; + Karma = 0; - VirtualArmor = 10; + VirtualArmor = 10; - Tamable = true; - ControlSlots = 1; - MinTameSkill = -0.9; + Tamable = true; + ControlSlots = 1; + MinTameSkill = -0.9; + } + + public MountainGoat(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a mountain goat corpse"; + public override string DefaultName => "a mountain goat"; + + public override int Meat => 2; + public override int Hides => 12; + public override FoodType FavoriteFood => FoodType.GrainsAndHay | FoodType.FruitsAndVegies; + + 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(); + } } - - public MountainGoat(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a mountain goat corpse"; - public override string DefaultName => "a mountain goat"; - - public override int Meat => 2; - public override int Hides => 12; - public override FoodType FavoriteFood => FoodType.GrainsAndHay | FoodType.FruitsAndVegies; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Misc/PackHorse.cs b/Projects/UOContent/Mobiles/Animals/Misc/PackHorse.cs index 361c34d42..1355dfdef 100644 --- a/Projects/UOContent/Mobiles/Animals/Misc/PackHorse.cs +++ b/Projects/UOContent/Mobiles/Animals/Misc/PackHorse.cs @@ -4,206 +4,206 @@ using Server.Items; namespace Server.Mobiles { - public class PackHorse : BaseCreature - { - [Constructible] - public PackHorse() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class PackHorse : BaseCreature { - Body = 291; - BaseSoundID = 0xA8; - - SetStr(44, 120); - SetDex(36, 55); - SetInt(6, 10); - - SetHits(61, 80); - SetStam(81, 100); - SetMana(0); - - SetDamage(5, 11); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 20, 25); - SetResistance(ResistanceType.Fire, 10, 15); - SetResistance(ResistanceType.Cold, 20, 25); - SetResistance(ResistanceType.Poison, 10, 15); - SetResistance(ResistanceType.Energy, 10, 15); - - SetSkill(SkillName.MagicResist, 25.1, 30.0); - SetSkill(SkillName.Tactics, 29.3, 44.0); - SetSkill(SkillName.Wrestling, 29.3, 44.0); - - Fame = 0; - Karma = 200; - - VirtualArmor = 16; - - Tamable = true; - ControlSlots = 1; - MinTameSkill = 11.1; - - Container pack = Backpack; - - pack?.Delete(); - - pack = new StrongBackpack(); - pack.Movable = false; - - AddItem(pack); - } - - public PackHorse(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a horse corpse"; - public override string DefaultName => "a pack horse"; - - public override int Meat => 3; - public override int Hides => 10; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override bool OnBeforeDeath() - { - if (!base.OnBeforeDeath()) - return false; - - PackAnimal.CombineBackpacks(this); - - return true; - } - - public override DeathMoveResult GetInventoryMoveResultFor(Item item) => DeathMoveResult.MoveToCorpse; - - public override bool IsSnoop(Mobile from) - { - if (PackAnimal.CheckAccess(this, from)) - return false; - - return base.IsSnoop(from); - } - - public override bool OnDragDrop(Mobile from, Item item) - { - if (CheckFeed(from, item)) - return true; - - if (PackAnimal.CheckAccess(this, from)) - { - AddToBackpack(item); - return true; - } - - return base.OnDragDrop(from, item); - } - - public override bool CheckNonlocalDrop(Mobile from, Item item, Item target) => PackAnimal.CheckAccess(this, from); - - public override bool CheckNonlocalLift(Mobile from, Item item) => PackAnimal.CheckAccess(this, from); - - public override void OnDoubleClick(Mobile from) - { - PackAnimal.TryPackOpen(this, from); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - PackAnimal.GetContextMenuEntries(this, from, list); - } - } - - public class PackAnimalBackpackEntry : ContextMenuEntry - { - private readonly BaseCreature m_Animal; - private readonly Mobile m_From; - - public PackAnimalBackpackEntry(BaseCreature animal, Mobile from) : base(6145, 3) - { - m_Animal = animal; - m_From = from; - - if (animal.IsDeadPet) - Enabled = false; - } - - public override void OnClick() - { - PackAnimal.TryPackOpen(m_Animal, m_From); - } - } - - public class PackAnimal - { - public static void GetContextMenuEntries(BaseCreature animal, Mobile from, List list) - { - if (CheckAccess(animal, from)) - list.Add(new PackAnimalBackpackEntry(animal, from)); - } - - public static bool CheckAccess(BaseCreature animal, Mobile from) - { - if (from == animal || from.AccessLevel >= AccessLevel.GameMaster) - return true; - - if (from.Alive && animal.Controlled && !animal.IsDeadPet && - (from == animal.ControlMaster || from == animal.SummonMaster || animal.IsPetFriend(from))) - return true; - - return false; - } - - public static void CombineBackpacks(BaseCreature animal) - { - if (Core.AOS) - return; - - if (animal.IsBonded || animal.IsDeadPet) - return; - - Container pack = animal.Backpack; - - if (pack != null) - { - Container newPack = new Backpack(); - - for (int i = pack.Items.Count - 1; i >= 0; --i) + [Constructible] + public PackHorse() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) { - if (i >= pack.Items.Count) - continue; + Body = 291; + BaseSoundID = 0xA8; - newPack.DropItem(pack.Items[i]); + SetStr(44, 120); + SetDex(36, 55); + SetInt(6, 10); + + SetHits(61, 80); + SetStam(81, 100); + SetMana(0); + + SetDamage(5, 11); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 20, 25); + SetResistance(ResistanceType.Fire, 10, 15); + SetResistance(ResistanceType.Cold, 20, 25); + SetResistance(ResistanceType.Poison, 10, 15); + SetResistance(ResistanceType.Energy, 10, 15); + + SetSkill(SkillName.MagicResist, 25.1, 30.0); + SetSkill(SkillName.Tactics, 29.3, 44.0); + SetSkill(SkillName.Wrestling, 29.3, 44.0); + + Fame = 0; + Karma = 200; + + VirtualArmor = 16; + + Tamable = true; + ControlSlots = 1; + MinTameSkill = 11.1; + + var pack = Backpack; + + pack?.Delete(); + + pack = new StrongBackpack(); + pack.Movable = false; + + AddItem(pack); } - pack.DropItem(newPack); - } + public PackHorse(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a horse corpse"; + public override string DefaultName => "a pack horse"; + + public override int Meat => 3; + public override int Hides => 10; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + + 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(); + } + + public override bool OnBeforeDeath() + { + if (!base.OnBeforeDeath()) + return false; + + PackAnimal.CombineBackpacks(this); + + return true; + } + + public override DeathMoveResult GetInventoryMoveResultFor(Item item) => DeathMoveResult.MoveToCorpse; + + public override bool IsSnoop(Mobile from) + { + if (PackAnimal.CheckAccess(this, from)) + return false; + + return base.IsSnoop(from); + } + + public override bool OnDragDrop(Mobile from, Item item) + { + if (CheckFeed(from, item)) + return true; + + if (PackAnimal.CheckAccess(this, from)) + { + AddToBackpack(item); + return true; + } + + return base.OnDragDrop(from, item); + } + + public override bool CheckNonlocalDrop(Mobile from, Item item, Item target) => PackAnimal.CheckAccess(this, from); + + public override bool CheckNonlocalLift(Mobile from, Item item) => PackAnimal.CheckAccess(this, from); + + public override void OnDoubleClick(Mobile from) + { + PackAnimal.TryPackOpen(this, from); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + PackAnimal.GetContextMenuEntries(this, from, list); + } } - public static void TryPackOpen(BaseCreature animal, Mobile from) + public class PackAnimalBackpackEntry : ContextMenuEntry { - if (animal.IsDeadPet) - return; + private readonly BaseCreature m_Animal; + private readonly Mobile m_From; - Container item = animal.Backpack; + public PackAnimalBackpackEntry(BaseCreature animal, Mobile from) : base(6145, 3) + { + m_Animal = animal; + m_From = from; - if (item != null) - from.Use(item); + if (animal.IsDeadPet) + Enabled = false; + } + + public override void OnClick() + { + PackAnimal.TryPackOpen(m_Animal, m_From); + } } - } -} \ No newline at end of file + + public class PackAnimal + { + public static void GetContextMenuEntries(BaseCreature animal, Mobile from, List list) + { + if (CheckAccess(animal, from)) + list.Add(new PackAnimalBackpackEntry(animal, from)); + } + + public static bool CheckAccess(BaseCreature animal, Mobile from) + { + if (from == animal || from.AccessLevel >= AccessLevel.GameMaster) + return true; + + if (from.Alive && animal.Controlled && !animal.IsDeadPet && + (from == animal.ControlMaster || from == animal.SummonMaster || animal.IsPetFriend(from))) + return true; + + return false; + } + + public static void CombineBackpacks(BaseCreature animal) + { + if (Core.AOS) + return; + + if (animal.IsBonded || animal.IsDeadPet) + return; + + var pack = animal.Backpack; + + if (pack != null) + { + Container newPack = new Backpack(); + + for (var i = pack.Items.Count - 1; i >= 0; --i) + { + if (i >= pack.Items.Count) + continue; + + newPack.DropItem(pack.Items[i]); + } + + pack.DropItem(newPack); + } + } + + public static void TryPackOpen(BaseCreature animal, Mobile from) + { + if (animal.IsDeadPet) + return; + + var item = animal.Backpack; + + if (item != null) + from.Use(item); + } + } +} diff --git a/Projects/UOContent/Mobiles/Animals/Misc/PackLlama.cs b/Projects/UOContent/Mobiles/Animals/Misc/PackLlama.cs index bcd7bdc36..9f9e4cda3 100644 --- a/Projects/UOContent/Mobiles/Animals/Misc/PackLlama.cs +++ b/Projects/UOContent/Mobiles/Animals/Misc/PackLlama.cs @@ -4,127 +4,127 @@ using Server.Items; namespace Server.Mobiles { - public class PackLlama : BaseCreature - { - [Constructible] - public PackLlama() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class PackLlama : BaseCreature { - Body = 292; - BaseSoundID = 0x3F3; + [Constructible] + public PackLlama() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 292; + BaseSoundID = 0x3F3; - SetStr(52, 80); - SetDex(36, 55); - SetInt(16, 30); + SetStr(52, 80); + SetDex(36, 55); + SetInt(16, 30); - SetHits(50); - SetStam(86, 105); - SetMana(0); + SetHits(50); + SetStam(86, 105); + SetMana(0); - SetDamage(2, 6); + SetDamage(2, 6); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 25, 35); - SetResistance(ResistanceType.Fire, 10, 15); - SetResistance(ResistanceType.Cold, 10, 15); - SetResistance(ResistanceType.Poison, 10, 15); - SetResistance(ResistanceType.Energy, 10, 15); + SetResistance(ResistanceType.Physical, 25, 35); + SetResistance(ResistanceType.Fire, 10, 15); + SetResistance(ResistanceType.Cold, 10, 15); + SetResistance(ResistanceType.Poison, 10, 15); + SetResistance(ResistanceType.Energy, 10, 15); - SetSkill(SkillName.MagicResist, 15.1, 20.0); - SetSkill(SkillName.Tactics, 19.2, 29.0); - SetSkill(SkillName.Wrestling, 19.2, 29.0); + SetSkill(SkillName.MagicResist, 15.1, 20.0); + SetSkill(SkillName.Tactics, 19.2, 29.0); + SetSkill(SkillName.Wrestling, 19.2, 29.0); - Fame = 0; - Karma = 200; + Fame = 0; + Karma = 200; - VirtualArmor = 16; + VirtualArmor = 16; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 11.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 11.1; - Container pack = Backpack; + var pack = Backpack; - pack?.Delete(); + pack?.Delete(); - pack = new StrongBackpack(); - pack.Movable = false; + pack = new StrongBackpack(); + pack.Movable = false; - AddItem(pack); + AddItem(pack); + } + + public PackLlama(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a llama corpse"; + public override string DefaultName => "a pack llama"; + + public override int Meat => 1; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + + 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(); + } + + public override bool OnBeforeDeath() + { + if (!base.OnBeforeDeath()) + return false; + + PackAnimal.CombineBackpacks(this); + + return true; + } + + public override DeathMoveResult GetInventoryMoveResultFor(Item item) => DeathMoveResult.MoveToCorpse; + + public override bool IsSnoop(Mobile from) + { + if (PackAnimal.CheckAccess(this, from)) + return false; + + return base.IsSnoop(from); + } + + public override bool OnDragDrop(Mobile from, Item item) + { + if (CheckFeed(from, item)) + return true; + + if (PackAnimal.CheckAccess(this, from)) + { + AddToBackpack(item); + return true; + } + + return base.OnDragDrop(from, item); + } + + public override bool CheckNonlocalDrop(Mobile from, Item item, Item target) => PackAnimal.CheckAccess(this, from); + + public override bool CheckNonlocalLift(Mobile from, Item item) => PackAnimal.CheckAccess(this, from); + + public override void OnDoubleClick(Mobile from) + { + PackAnimal.TryPackOpen(this, from); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + PackAnimal.GetContextMenuEntries(this, from, list); + } } - - public PackLlama(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a llama corpse"; - public override string DefaultName => "a pack llama"; - - public override int Meat => 1; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override bool OnBeforeDeath() - { - if (!base.OnBeforeDeath()) - return false; - - PackAnimal.CombineBackpacks(this); - - return true; - } - - public override DeathMoveResult GetInventoryMoveResultFor(Item item) => DeathMoveResult.MoveToCorpse; - - public override bool IsSnoop(Mobile from) - { - if (PackAnimal.CheckAccess(this, from)) - return false; - - return base.IsSnoop(from); - } - - public override bool OnDragDrop(Mobile from, Item item) - { - if (CheckFeed(from, item)) - return true; - - if (PackAnimal.CheckAccess(this, from)) - { - AddToBackpack(item); - return true; - } - - return base.OnDragDrop(from, item); - } - - public override bool CheckNonlocalDrop(Mobile from, Item item, Item target) => PackAnimal.CheckAccess(this, from); - - public override bool CheckNonlocalLift(Mobile from, Item item) => PackAnimal.CheckAccess(this, from); - - public override void OnDoubleClick(Mobile from) - { - PackAnimal.TryPackOpen(this, from); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - PackAnimal.GetContextMenuEntries(this, from, list); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Misc/Pig.cs b/Projects/UOContent/Mobiles/Animals/Misc/Pig.cs index 8a57e9286..cbc1e4ae8 100644 --- a/Projects/UOContent/Mobiles/Animals/Misc/Pig.cs +++ b/Projects/UOContent/Mobiles/Animals/Misc/Pig.cs @@ -1,62 +1,62 @@ namespace Server.Mobiles { - public class Pig : BaseCreature - { - [Constructible] - public Pig() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Pig : BaseCreature { - Body = 0xCB; - BaseSoundID = 0xC4; + [Constructible] + public Pig() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 0xCB; + BaseSoundID = 0xC4; - SetStr(20); - SetDex(20); - SetInt(5); + SetStr(20); + SetDex(20); + SetInt(5); - SetHits(12); - SetMana(0); + SetHits(12); + SetMana(0); - SetDamage(2, 4); + SetDamage(2, 4); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 10, 15); + SetResistance(ResistanceType.Physical, 10, 15); - SetSkill(SkillName.MagicResist, 5.0); - SetSkill(SkillName.Tactics, 5.0); - SetSkill(SkillName.Wrestling, 5.0); + SetSkill(SkillName.MagicResist, 5.0); + SetSkill(SkillName.Tactics, 5.0); + SetSkill(SkillName.Wrestling, 5.0); - Fame = 150; - Karma = 0; + Fame = 150; + Karma = 0; - VirtualArmor = 12; + VirtualArmor = 12; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 11.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 11.1; + } + + public Pig(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a pig corpse"; + public override string DefaultName => "a pig"; + + public override int Meat => 1; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + + 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(); + } } - - public Pig(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a pig corpse"; - public override string DefaultName => "a pig"; - - public override int Meat => 1; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Misc/Sheep.cs b/Projects/UOContent/Mobiles/Animals/Misc/Sheep.cs index a6e298392..af53f866b 100644 --- a/Projects/UOContent/Mobiles/Animals/Misc/Sheep.cs +++ b/Projects/UOContent/Mobiles/Animals/Misc/Sheep.cs @@ -4,112 +4,112 @@ using Server.Network; namespace Server.Mobiles { - public class Sheep : BaseCreature, ICarvable - { - private DateTime m_NextWoolTime; - - [Constructible] - public Sheep() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Sheep : BaseCreature, ICarvable { - Body = 0xCF; - BaseSoundID = 0xD6; + private DateTime m_NextWoolTime; - SetStr(19); - SetDex(25); - SetInt(5); + [Constructible] + public Sheep() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 0xCF; + BaseSoundID = 0xD6; - SetHits(12); - SetMana(0); + SetStr(19); + SetDex(25); + SetInt(5); - SetDamage(1, 2); + SetHits(12); + SetMana(0); - SetDamageType(ResistanceType.Physical, 100); + SetDamage(1, 2); - SetResistance(ResistanceType.Physical, 5, 10); + SetDamageType(ResistanceType.Physical, 100); - SetSkill(SkillName.MagicResist, 5.0); - SetSkill(SkillName.Tactics, 6.0); - SetSkill(SkillName.Wrestling, 5.0); + SetResistance(ResistanceType.Physical, 5, 10); - Fame = 300; - Karma = 0; + SetSkill(SkillName.MagicResist, 5.0); + SetSkill(SkillName.Tactics, 6.0); + SetSkill(SkillName.Wrestling, 5.0); - VirtualArmor = 6; + Fame = 300; + Karma = 0; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 11.1; + VirtualArmor = 6; + + Tamable = true; + ControlSlots = 1; + MinTameSkill = 11.1; + } + + public Sheep(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a sheep corpse"; + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime NextWoolTime + { + get => m_NextWoolTime; + set + { + m_NextWoolTime = value; + Body = DateTime.UtcNow >= m_NextWoolTime ? 0xCF : 0xDF; + } + } + + public override string DefaultName => "a sheep"; + + public override int Meat => 3; + public override MeatType MeatType => MeatType.LambLeg; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + + public override int Wool => Body == 0xCF ? 3 : 0; + + public void Carve(Mobile from, Item item) + { + if (DateTime.UtcNow < m_NextWoolTime) + { + // This sheep is not yet ready to be shorn. + PrivateOverheadMessage(MessageType.Regular, 0x3B2, 500449, from.NetState); + return; + } + + from.SendLocalizedMessage(500452); // You place the gathered wool into your backpack. + from.AddToBackpack(new Wool(Map == Map.Felucca ? 2 : 1)); + + NextWoolTime = DateTime.UtcNow + TimeSpan.FromHours(3.0); // TODO: Proper time delay + } + + public override void OnThink() + { + base.OnThink(); + Body = DateTime.UtcNow >= m_NextWoolTime ? 0xCF : 0xDF; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); + + writer.WriteDeltaTime(m_NextWoolTime); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + NextWoolTime = reader.ReadDeltaTime(); + break; + } + } + } } - - public Sheep(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a sheep corpse"; - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime NextWoolTime - { - get => m_NextWoolTime; - set - { - m_NextWoolTime = value; - Body = DateTime.UtcNow >= m_NextWoolTime ? 0xCF : 0xDF; - } - } - - public override string DefaultName => "a sheep"; - - public override int Meat => 3; - public override MeatType MeatType => MeatType.LambLeg; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - - public override int Wool => Body == 0xCF ? 3 : 0; - - public void Carve(Mobile from, Item item) - { - if (DateTime.UtcNow < m_NextWoolTime) - { - // This sheep is not yet ready to be shorn. - PrivateOverheadMessage(MessageType.Regular, 0x3B2, 500449, from.NetState); - return; - } - - from.SendLocalizedMessage(500452); // You place the gathered wool into your backpack. - from.AddToBackpack(new Wool(Map == Map.Felucca ? 2 : 1)); - - NextWoolTime = DateTime.UtcNow + TimeSpan.FromHours(3.0); // TODO: Proper time delay - } - - public override void OnThink() - { - base.OnThink(); - Body = DateTime.UtcNow >= m_NextWoolTime ? 0xCF : 0xDF; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); - - writer.WriteDeltaTime(m_NextWoolTime); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - NextWoolTime = reader.ReadDeltaTime(); - break; - } - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Misc/Walrus.cs b/Projects/UOContent/Mobiles/Animals/Misc/Walrus.cs index d2a68271b..480744c5c 100644 --- a/Projects/UOContent/Mobiles/Animals/Misc/Walrus.cs +++ b/Projects/UOContent/Mobiles/Animals/Misc/Walrus.cs @@ -1,67 +1,67 @@ namespace Server.Mobiles { - public class Walrus : BaseCreature - { - [Constructible] - public Walrus() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Walrus : BaseCreature { - Body = 0xDD; - BaseSoundID = 0xE0; + [Constructible] + public Walrus() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 0xDD; + BaseSoundID = 0xE0; - SetStr(21, 29); - SetDex(46, 55); - SetInt(16, 20); + SetStr(21, 29); + SetDex(46, 55); + SetInt(16, 20); - SetHits(14, 17); - SetMana(0); + SetHits(14, 17); + SetMana(0); - SetDamage(4, 10); + SetDamage(4, 10); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 20, 25); - SetResistance(ResistanceType.Fire, 5, 10); - SetResistance(ResistanceType.Cold, 20, 25); - SetResistance(ResistanceType.Poison, 5, 10); - SetResistance(ResistanceType.Energy, 5, 10); + SetResistance(ResistanceType.Physical, 20, 25); + SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Cold, 20, 25); + SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Energy, 5, 10); - SetSkill(SkillName.MagicResist, 15.1, 20.0); - SetSkill(SkillName.Tactics, 19.2, 29.0); - SetSkill(SkillName.Wrestling, 19.2, 29.0); + SetSkill(SkillName.MagicResist, 15.1, 20.0); + SetSkill(SkillName.Tactics, 19.2, 29.0); + SetSkill(SkillName.Wrestling, 19.2, 29.0); - Fame = 150; - Karma = 0; + Fame = 150; + Karma = 0; - VirtualArmor = 18; + VirtualArmor = 18; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 35.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 35.1; + } + + public Walrus(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a walrus corpse"; + public override string DefaultName => "a walrus"; + + public override int Meat => 1; + public override int Hides => 12; + public override FoodType FavoriteFood => FoodType.Fish; + + 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(); + } } - - public Walrus(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a walrus corpse"; - public override string DefaultName => "a walrus"; - - public override int Meat => 1; - public override int Hides => 12; - public override FoodType FavoriteFood => FoodType.Fish; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/BaseMount.cs b/Projects/UOContent/Mobiles/Animals/Mounts/BaseMount.cs index 21ddb1869..293d25d7c 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/BaseMount.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/BaseMount.cs @@ -6,343 +6,355 @@ using Server.Targeting; namespace Server.Mobiles { - public abstract class BaseMount : BaseCreature, IMount - { - private Mobile m_Rider; - - public BaseMount(string name, int bodyID, int itemID, AIType aiType, FightMode fightMode, int rangePerception, - int rangeFight, double activeSpeed, double passiveSpeed) : base(aiType, fightMode, rangePerception, rangeFight, - activeSpeed, passiveSpeed) + public abstract class BaseMount : BaseCreature, IMount { - Name = name; - Body = bodyID; + private Mobile m_Rider; - InternalItem = new MountItem(this, itemID); - } - - public BaseMount(Serial serial) - : base(serial) - { - } - - public virtual TimeSpan MountAbilityDelay => TimeSpan.Zero; - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime NextMountAbility { get; set; } - - protected Item InternalItem { get; private set; } - - public virtual bool AllowMaleRider => true; - public virtual bool AllowFemaleRider => true; - - [Hue] - [CommandProperty(AccessLevel.GameMaster)] - public override int Hue - { - get => base.Hue; - set - { - base.Hue = value; - - if (InternalItem != null) - InternalItem.Hue = value; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int ItemID - { - get => InternalItem?.ItemID ?? 0; - set - { - if (InternalItem != null) - InternalItem.ItemID = value; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Rider - { - get => m_Rider; - set - { - if (m_Rider != value) + public BaseMount( + string name, int bodyID, int itemID, AIType aiType, FightMode fightMode, int rangePerception, + int rangeFight, double activeSpeed, double passiveSpeed + ) : base( + aiType, + fightMode, + rangePerception, + rangeFight, + activeSpeed, + passiveSpeed + ) { - if (value == null) - { - Point3D loc = m_Rider.Location; - Map map = m_Rider.Map; + Name = name; + Body = bodyID; - if (map == null || map == Map.Internal) + InternalItem = new MountItem(this, itemID); + } + + public BaseMount(Serial serial) + : base(serial) + { + } + + public virtual TimeSpan MountAbilityDelay => TimeSpan.Zero; + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime NextMountAbility { get; set; } + + protected Item InternalItem { get; private set; } + + public virtual bool AllowMaleRider => true; + public virtual bool AllowFemaleRider => true; + + [Hue] + [CommandProperty(AccessLevel.GameMaster)] + public override int Hue + { + get => base.Hue; + set { - loc = m_Rider.LogoutLocation; - map = m_Rider.LogoutMap; + base.Hue = value; + + if (InternalItem != null) + InternalItem.Hue = value; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int ItemID + { + get => InternalItem?.ItemID ?? 0; + set + { + if (InternalItem != null) + InternalItem.ItemID = value; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Rider + { + get => m_Rider; + set + { + if (m_Rider != value) + { + if (value == null) + { + var loc = m_Rider.Location; + var map = m_Rider.Map; + + if (map == null || map == Map.Internal) + { + loc = m_Rider.LogoutLocation; + map = m_Rider.LogoutMap; + } + + Direction = m_Rider.Direction; + Location = loc; + Map = map; + + InternalItem?.Internalize(); + } + else + { + if (m_Rider != null) Dismount(m_Rider); + + Dismount(value); + + if (InternalItem != null) + value.AddItem(InternalItem); + + value.Direction = Direction; + + Internalize(); + + if (value.Target is Bola.BolaTarget) Target.Cancel(value); + } + + m_Rider = value; + } + } + } + + public virtual void OnRiderDamaged(int amount, Mobile from, bool willKill) + { + if (m_Rider == null) + return; + + var attacker = from ?? m_Rider.FindMostRecentDamager(true); + + if (!(attacker == this || attacker == m_Rider || willKill || DateTime.UtcNow < NextMountAbility) + && DoMountAbility(amount, from)) + NextMountAbility = DateTime.UtcNow + MountAbilityDelay; + } + + public override bool OnBeforeDeath() + { + Rider = null; + return base.OnBeforeDeath(); + } + + public override void OnAfterDelete() + { + InternalItem?.Delete(); + InternalItem = null; + + base.OnAfterDelete(); + } + + public override void OnDelete() + { + Rider = null; + + base.OnDelete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(NextMountAbility); + + writer.Write(m_Rider); + writer.Write(InternalItem); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + NextMountAbility = reader.ReadDateTime(); + goto case 0; + } + case 0: + { + m_Rider = reader.ReadMobile(); + InternalItem = reader.ReadItem(); + + if (InternalItem == null) + Delete(); + + break; + } + } + } + + public virtual void OnDisallowedRider(Mobile m) + { + m.SendMessage("You may not ride this creature."); + } + + public override void OnDoubleClick(Mobile from) + { + if (IsDeadPet) + return; + + if (from.IsBodyMod && !from.Body.IsHuman) + { + if (Core.AOS) // You cannot ride a mount in your current form. + PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1062061, from.NetState); + else + from.SendLocalizedMessage(1061628); // You can't do that while polymorphed. + + return; } - Direction = m_Rider.Direction; - Location = loc; - Map = map; + if (!CheckMountAllowed(from)) + return; - InternalItem?.Internalize(); - } - else - { - if (m_Rider != null) Dismount(m_Rider); + if (from.Mounted) + { + from.SendLocalizedMessage(1005583); // Please dismount first. + return; + } - Dismount(value); + if (from.Female ? !AllowFemaleRider : !AllowMaleRider) + { + OnDisallowedRider(from); + return; + } - if (InternalItem != null) - value.AddItem(InternalItem); + if (!DesignContext.Check(from)) + return; - value.Direction = Direction; + if (from.HasTrade) + { + from.SendLocalizedMessage(1042317, "", 0x41); // You may not ride at this time + return; + } - Internalize(); + if (from.InRange(this, 1)) + { + var canAccess = from.AccessLevel >= AccessLevel.GameMaster + || Controlled && ControlMaster == @from + || Summoned && SummonMaster == @from; - if (value.Target is Bola.BolaTarget) Target.Cancel(value); - } - - m_Rider = value; + if (canAccess) + { + if (Poisoned) + PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 1049692, + from.NetState + ); // This mount is too ill to ride. + else + Rider = from; + } + else if (!Controlled && !Summoned) + { + // That mount does not look broken! You would have to tame it to ride it. + PrivateOverheadMessage(MessageType.Regular, 0x3B2, 501263, from.NetState); + } + else + { + // This isn't your mount; it refuses to let you ride. + PrivateOverheadMessage(MessageType.Regular, 0x3B2, 501264, from.NetState); + } + } + else + { + from.SendLocalizedMessage(500206); // That is too far away to ride. + } } - } - } - public virtual void OnRiderDamaged(int amount, Mobile from, bool willKill) - { - if (m_Rider == null) - return; - - Mobile attacker = from ?? m_Rider.FindMostRecentDamager(true); - - if (!(attacker == this || attacker == m_Rider || willKill || DateTime.UtcNow < NextMountAbility) - && DoMountAbility(amount, from)) - NextMountAbility = DateTime.UtcNow + MountAbilityDelay; - } - - public override bool OnBeforeDeath() - { - Rider = null; - return base.OnBeforeDeath(); - } - - public override void OnAfterDelete() - { - InternalItem?.Delete(); - InternalItem = null; - - base.OnAfterDelete(); - } - - public override void OnDelete() - { - Rider = null; - - base.OnDelete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(NextMountAbility); - - writer.Write(m_Rider); - writer.Write(InternalItem); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - NextMountAbility = reader.ReadDateTime(); - goto case 0; - } - case 0: - { - m_Rider = reader.ReadMobile(); - InternalItem = reader.ReadItem(); - - if (InternalItem == null) - Delete(); - - break; - } - } - } - - public virtual void OnDisallowedRider(Mobile m) - { - m.SendMessage("You may not ride this creature."); - } - - public override void OnDoubleClick(Mobile from) - { - if (IsDeadPet) - return; - - if (from.IsBodyMod && !from.Body.IsHuman) - { - if (Core.AOS) // You cannot ride a mount in your current form. - PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1062061, from.NetState); - else - from.SendLocalizedMessage(1061628); // You can't do that while polymorphed. - - return; - } - - if (!CheckMountAllowed(from)) - return; - - if (from.Mounted) - { - from.SendLocalizedMessage(1005583); // Please dismount first. - return; - } - - if (from.Female ? !AllowFemaleRider : !AllowMaleRider) - { - OnDisallowedRider(from); - return; - } - - if (!DesignContext.Check(from)) - return; - - if (from.HasTrade) - { - from.SendLocalizedMessage(1042317, "", 0x41); // You may not ride at this time - return; - } - - if (from.InRange(this, 1)) - { - bool canAccess = from.AccessLevel >= AccessLevel.GameMaster - || (Controlled && ControlMaster == from) - || (Summoned && SummonMaster == from); - - if (canAccess) + public static void Dismount(Mobile m) { - if (Poisoned) - PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1049692, - from.NetState); // This mount is too ill to ride. - else - Rider = from; + var mount = m.Mount; + + if (mount != null) + mount.Rider = null; } - else if (!Controlled && !Summoned) + + // 1040024 You are still too dazed from being knocked off your mount to ride! + // 1062910 You cannot mount while recovering from a bola throw. + // 1070859 You cannot mount while recovering from a dismount special maneuver. + + public static bool CheckMountAllowed(Mobile mob) { - // That mount does not look broken! You would have to tame it to ride it. - PrivateOverheadMessage(MessageType.Regular, 0x3B2, 501263, from.NetState); + var result = true; + + if (mob is PlayerMobile mobile && mobile.MountBlockReason != BlockMountType.None) + { + mobile.SendLocalizedMessage((int)mobile.MountBlockReason); + result = false; + } + + return result; } - else + + public virtual bool DoMountAbility(int damage, Mobile attacker) => false; + } + + public class MountItem : Item, IMountItem + { + private BaseMount m_Mount; + + public MountItem(BaseMount mount, int itemID) : base(itemID) { - // This isn't your mount; it refuses to let you ride. - PrivateOverheadMessage(MessageType.Regular, 0x3B2, 501264, from.NetState); + Layer = Layer.Mount; + Movable = false; + + m_Mount = mount; + } + + public MountItem(Serial serial) : base(serial) + { + } + + public override double DefaultWeight => 0; + + public IMount Mount => m_Mount; + + public override void OnAfterDelete() + { + m_Mount?.Delete(); + m_Mount = null; + + base.OnAfterDelete(); + } + + public override DeathMoveResult OnParentDeath(Mobile parent) + { + if (m_Mount != null) + m_Mount.Rider = null; + + return DeathMoveResult.RemainEquipped; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Mount); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Mount = reader.ReadMobile() as BaseMount; + + if (m_Mount == null) + Delete(); + + break; + } + } } - } - else - { - from.SendLocalizedMessage(500206); // That is too far away to ride. - } } - - public static void Dismount(Mobile m) - { - IMount mount = m.Mount; - - if (mount != null) - mount.Rider = null; - } - - // 1040024 You are still too dazed from being knocked off your mount to ride! - // 1062910 You cannot mount while recovering from a bola throw. - // 1070859 You cannot mount while recovering from a dismount special maneuver. - - public static bool CheckMountAllowed(Mobile mob) - { - bool result = true; - - if (mob is PlayerMobile mobile && mobile.MountBlockReason != BlockMountType.None) - { - mobile.SendLocalizedMessage((int)mobile.MountBlockReason); - result = false; - } - - return result; - } - - public virtual bool DoMountAbility(int damage, Mobile attacker) => false; - } - - public class MountItem : Item, IMountItem - { - private BaseMount m_Mount; - - public MountItem(BaseMount mount, int itemID) : base(itemID) - { - Layer = Layer.Mount; - Movable = false; - - m_Mount = mount; - } - - public MountItem(Serial serial) : base(serial) - { - } - - public override double DefaultWeight => 0; - - public IMount Mount => m_Mount; - - public override void OnAfterDelete() - { - m_Mount?.Delete(); - m_Mount = null; - - base.OnAfterDelete(); - } - - public override DeathMoveResult OnParentDeath(Mobile parent) - { - if (m_Mount != null) - m_Mount.Rider = null; - - return DeathMoveResult.RemainEquipped; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Mount); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Mount = reader.ReadMobile() as BaseMount; - - if (m_Mount == null) - Delete(); - - break; - } - } - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/Beetle.cs b/Projects/UOContent/Mobiles/Animals/Mounts/Beetle.cs index 20a7774fb..8135fe92c 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/Beetle.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/Beetle.cs @@ -4,139 +4,149 @@ using Server.Items; namespace Server.Mobiles { - public class Beetle : BaseMount - { - [Constructible] - public Beetle(string name = "a giant beetle") : base(name, 0x317, 0x3EBC, AIType.AI_Melee, FightMode.Closest, 10, 1, 0.25, 0.5) + public class Beetle : BaseMount { - SetStr(300); - SetDex(100); - SetInt(500); + [Constructible] + public Beetle(string name = "a giant beetle") : base( + name, + 0x317, + 0x3EBC, + AIType.AI_Melee, + FightMode.Closest, + 10, + 1, + 0.25, + 0.5 + ) + { + SetStr(300); + SetDex(100); + SetInt(500); - SetHits(200); + SetHits(200); - SetDamage(7, 20); + SetDamage(7, 20); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 30, 40); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 20, 30); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 20, 30); + SetResistance(ResistanceType.Physical, 30, 40); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 20, 30); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 20, 30); - SetSkill(SkillName.MagicResist, 80.0); - SetSkill(SkillName.Tactics, 100.0); - SetSkill(SkillName.Wrestling, 100.0); + SetSkill(SkillName.MagicResist, 80.0); + SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.Wrestling, 100.0); - Fame = 4000; - Karma = -4000; + Fame = 4000; + Karma = -4000; - Tamable = true; - ControlSlots = 3; - MinTameSkill = 29.1; + Tamable = true; + ControlSlots = 3; + MinTameSkill = 29.1; - Container pack = Backpack; + var pack = Backpack; - pack?.Delete(); + pack?.Delete(); - pack = new StrongBackpack(); - pack.Movable = false; + pack = new StrongBackpack(); + pack.Movable = false; - AddItem(pack); + AddItem(pack); + } + + public Beetle(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a giant beetle corpse"; + public virtual double BoostedSpeed => 0.1; + + public override bool SubdueBeforeTame => true; // Must be beaten into submission + public override bool ReduceSpeedWithDamage => false; + + public override FoodType FavoriteFood => FoodType.Meat; + + public override int GetAngerSound() => 0x21D; + + public override int GetIdleSound() => 0x21D; + + public override int GetAttackSound() => 0x162; + + public override int GetHurtSound() => 0x163; + + public override int GetDeathSound() => 0x21D; + + public override void OnHarmfulSpell(Mobile from) + { + if (!Controlled && ControlMaster == null) + CurrentSpeed = BoostedSpeed; + } + + public override void OnCombatantChange() + { + if (Combatant == null && !Controlled && ControlMaster == null) + CurrentSpeed = PassiveSpeed; + } + + 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 OnBeforeDeath() + { + if (!base.OnBeforeDeath()) + return false; + + PackAnimal.CombineBackpacks(this); + + return true; + } + + public override DeathMoveResult GetInventoryMoveResultFor(Item item) => DeathMoveResult.MoveToCorpse; + + public override bool IsSnoop(Mobile from) + { + if (PackAnimal.CheckAccess(this, from)) + return false; + + return base.IsSnoop(from); + } + + public override bool OnDragDrop(Mobile from, Item item) + { + if (CheckFeed(from, item)) + return true; + + if (PackAnimal.CheckAccess(this, from)) + { + AddToBackpack(item); + return true; + } + + return base.OnDragDrop(from, item); + } + + public override bool CheckNonlocalDrop(Mobile from, Item item, Item target) => PackAnimal.CheckAccess(this, from); + + public override bool CheckNonlocalLift(Mobile from, Item item) => PackAnimal.CheckAccess(this, from); + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + PackAnimal.GetContextMenuEntries(this, from, list); + } } - - public Beetle(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a giant beetle corpse"; - public virtual double BoostedSpeed => 0.1; - - public override bool SubdueBeforeTame => true; // Must be beaten into submission - public override bool ReduceSpeedWithDamage => false; - - public override FoodType FavoriteFood => FoodType.Meat; - - public override int GetAngerSound() => 0x21D; - - public override int GetIdleSound() => 0x21D; - - public override int GetAttackSound() => 0x162; - - public override int GetHurtSound() => 0x163; - - public override int GetDeathSound() => 0x21D; - - public override void OnHarmfulSpell(Mobile from) - { - if (!Controlled && ControlMaster == null) - CurrentSpeed = BoostedSpeed; - } - - public override void OnCombatantChange() - { - if (Combatant == null && !Controlled && ControlMaster == null) - CurrentSpeed = PassiveSpeed; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override bool OnBeforeDeath() - { - if (!base.OnBeforeDeath()) - return false; - - PackAnimal.CombineBackpacks(this); - - return true; - } - - public override DeathMoveResult GetInventoryMoveResultFor(Item item) => DeathMoveResult.MoveToCorpse; - - public override bool IsSnoop(Mobile from) - { - if (PackAnimal.CheckAccess(this, from)) - return false; - - return base.IsSnoop(from); - } - - public override bool OnDragDrop(Mobile from, Item item) - { - if (CheckFeed(from, item)) - return true; - - if (PackAnimal.CheckAccess(this, from)) - { - AddToBackpack(item); - return true; - } - - return base.OnDragDrop(from, item); - } - - public override bool CheckNonlocalDrop(Mobile from, Item item, Item target) => PackAnimal.CheckAccess(this, from); - - public override bool CheckNonlocalLift(Mobile from, Item item) => PackAnimal.CheckAccess(this, from); - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - PackAnimal.GetContextMenuEntries(this, from, list); - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/DesertOstard.cs b/Projects/UOContent/Mobiles/Animals/Mounts/DesertOstard.cs index f784df64f..ec67254a9 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/DesertOstard.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/DesertOstard.cs @@ -1,60 +1,70 @@ namespace Server.Mobiles { - public class DesertOstard : BaseMount - { - [Constructible] - public DesertOstard(string name = "a desert ostard") : base(name, 0xD2, 0x3EA3, AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class DesertOstard : BaseMount { - BaseSoundID = 0x270; + [Constructible] + public DesertOstard(string name = "a desert ostard") : base( + name, + 0xD2, + 0x3EA3, + AIType.AI_Animal, + FightMode.Aggressor, + 10, + 1, + 0.2, + 0.4 + ) + { + BaseSoundID = 0x270; - SetStr(94, 170); - SetDex(56, 75); - SetInt(6, 10); + SetStr(94, 170); + SetDex(56, 75); + SetInt(6, 10); - SetHits(71, 88); - SetMana(0); + SetHits(71, 88); + SetMana(0); - SetDamage(5, 11); + SetDamage(5, 11); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 15, 20); - SetResistance(ResistanceType.Fire, 5, 15); + SetResistance(ResistanceType.Physical, 15, 20); + SetResistance(ResistanceType.Fire, 5, 15); - SetSkill(SkillName.MagicResist, 25.1, 30.0); - SetSkill(SkillName.Tactics, 25.3, 40.0); - SetSkill(SkillName.Wrestling, 29.3, 44.0); + SetSkill(SkillName.MagicResist, 25.1, 30.0); + SetSkill(SkillName.Tactics, 25.3, 40.0); + SetSkill(SkillName.Wrestling, 29.3, 44.0); - Fame = 450; - Karma = 0; + Fame = 450; + Karma = 0; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 29.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 29.1; + } + + public DesertOstard(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ostard corpse"; + + public override int Meat => 3; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + public override PackInstinct PackInstinct => PackInstinct.Ostard; + + 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 DesertOstard(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ostard corpse"; - - public override int Meat => 3; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - public override PackInstinct PackInstinct => PackInstinct.Ostard; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/Ethereals.cs b/Projects/UOContent/Mobiles/Animals/Mounts/Ethereals.cs index c20182d7c..866d568b9 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/Ethereals.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/Ethereals.cs @@ -1,824 +1,825 @@ using System; using Server.Engines.VeteranRewards; -using Server.Items; using Server.Multis; using Server.Spells; namespace Server.Mobiles { - public class EtherealMount : Item, IMount, IMountItem, IRewardItem - { - private bool m_IsDonationItem; - private int m_MountedID; - private int m_RegularID; - private Mobile m_Rider; - - [Constructible] - public EtherealMount(int itemID, int mountID) - : base(itemID) + public class EtherealMount : Item, IMount, IMountItem, IRewardItem { - m_MountedID = mountID; - m_RegularID = itemID; - m_Rider = null; + private bool m_IsDonationItem; + private int m_MountedID; + private int m_RegularID; + private Mobile m_Rider; - Layer = Layer.Invalid; - - LootType = LootType.Blessed; - } - - public EtherealMount(Serial serial) - : base(serial) - { - } - - public override double DefaultWeight => 1.0; - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public bool IsDonationItem - { - get => m_IsDonationItem; - set - { - m_IsDonationItem = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int MountedID - { - get => m_MountedID; - set - { - if (m_MountedID != value) + [Constructible] + public EtherealMount(int itemID, int mountID) + : base(itemID) { - m_MountedID = value; - - if (m_Rider != null) - ItemID = value; - } - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int RegularID - { - get => m_RegularID; - set - { - if (m_RegularID != value) - { - m_RegularID = value; - - if (m_Rider == null) - ItemID = value; - } - } - } - - public override bool DisplayLootType => false; - - public virtual int FollowerSlots => 1; - - public virtual int EtherealHue => 0x4001; - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Rider - { - get => m_Rider; - set - { - if (value != m_Rider) - { - if (value == null) - { - Internalize(); - UnmountMe(); - - RemoveFollowers(); + m_MountedID = mountID; + m_RegularID = itemID; m_Rider = null; - } - else - { + + Layer = Layer.Invalid; + + LootType = LootType.Blessed; + } + + public EtherealMount(Serial serial) + : base(serial) + { + } + + public override double DefaultWeight => 1.0; + + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public bool IsDonationItem + { + get => m_IsDonationItem; + set + { + m_IsDonationItem = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int MountedID + { + get => m_MountedID; + set + { + if (m_MountedID != value) + { + m_MountedID = value; + + if (m_Rider != null) + ItemID = value; + } + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int RegularID + { + get => m_RegularID; + set + { + if (m_RegularID != value) + { + m_RegularID = value; + + if (m_Rider == null) + ItemID = value; + } + } + } + + public override bool DisplayLootType => false; + + public virtual int FollowerSlots => 1; + + public virtual int EtherealHue => 0x4001; + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Rider + { + get => m_Rider; + set + { + if (value != m_Rider) + { + if (value == null) + { + Internalize(); + UnmountMe(); + + RemoveFollowers(); + m_Rider = null; + } + else + { + if (m_Rider != null) + Dismount(m_Rider); + + Dismount(value); + + RemoveFollowers(); + m_Rider = value; + AddFollowers(); + + MountMe(); + } + } + } + } + + public void OnRiderDamaged(int amount, Mobile from, bool willKill) + { + } + + public IMount Mount => this; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsRewardItem { get; set; } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_IsDonationItem) + { + list.Add("Donation Ethereal"); + list.Add("7.5 sec slower cast time if not a 9mo. Veteran"); + } + + if (Core.ML && IsRewardItem) + list.Add(RewardSystem.GetRewardYearLabel(this, new object[] { })); // X Year Veteran Reward + } + + public void RemoveFollowers() + { if (m_Rider != null) - Dismount(m_Rider); + m_Rider.Followers -= Math.Min(m_Rider.Followers, FollowerSlots); + } - Dismount(value); + public void AddFollowers() + { + if (m_Rider != null) + m_Rider.Followers += FollowerSlots; + } + + public virtual bool Validate(Mobile from) + { + if (Parent == null) + { + from.SayTo(from, 1010095); // This must be on your person to use. + return false; + } + + if (IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this) || !BaseMount.CheckMountAllowed(from)) + return false; + + if (from.Mounted) + { + from.SendLocalizedMessage(1005583); // Please dismount first. + return false; + } + + if (from.IsBodyMod && !from.Body.IsHuman) + { + from.SendLocalizedMessage(1061628); // You can't do that while polymorphed. + return false; + } + + if (from.HasTrade) + { + from.SendLocalizedMessage(1042317, "", 0x41); // You may not ride at this time + return false; + } + + if (from.Followers + FollowerSlots > from.FollowersMax) + { + from.SendLocalizedMessage(1049679); // You have too many followers to summon your mount. + return false; + } + + return DesignContext.Check(from); + } + + public override void OnDoubleClick(Mobile from) + { + if (Validate(from)) + new EtherealSpell(this, from).Cast(); + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + + LabelTo(from, m_IsDonationItem ? "Donation Ethereal" : "Veteran Reward"); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(3); // version + + writer.Write(m_IsDonationItem); + writer.Write(IsRewardItem); + + writer.Write(m_MountedID); + writer.Write(m_RegularID); + writer.Write(m_Rider); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + LootType = LootType.Blessed; + + var version = reader.ReadInt(); + + switch (version) + { + case 3: + { + m_IsDonationItem = reader.ReadBool(); + goto case 2; + } + case 2: + { + IsRewardItem = reader.ReadBool(); + goto case 0; + } + case 1: + reader.ReadInt(); + goto case 0; + case 0: + { + m_MountedID = reader.ReadInt(); + m_RegularID = reader.ReadInt(); + m_Rider = reader.ReadMobile(); + + if (m_MountedID == 0x3EA2) + m_MountedID = 0x3EAA; + + break; + } + } - RemoveFollowers(); - m_Rider = value; AddFollowers(); - MountMe(); - } + if (version < 3 && Weight == 0) + Weight = -1; } - } - } - public void OnRiderDamaged(int amount, Mobile from, bool willKill) - { - } - - public IMount Mount => this; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsRewardItem { get; set; } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_IsDonationItem) - { - list.Add("Donation Ethereal"); - list.Add("7.5 sec slower cast time if not a 9mo. Veteran"); - } - - if (Core.ML && IsRewardItem) - list.Add(RewardSystem.GetRewardYearLabel(this, new object[] { })); // X Year Veteran Reward - } - - public void RemoveFollowers() - { - if (m_Rider != null) - m_Rider.Followers -= Math.Min(m_Rider.Followers, FollowerSlots); - } - - public void AddFollowers() - { - if (m_Rider != null) - m_Rider.Followers += FollowerSlots; - } - - public virtual bool Validate(Mobile from) - { - if (Parent == null) - { - from.SayTo(from, 1010095); // This must be on your person to use. - return false; - } - - if (IsRewardItem && !RewardSystem.CheckIsUsableBy(from, this) || !BaseMount.CheckMountAllowed(from)) - return false; - - if (from.Mounted) - { - from.SendLocalizedMessage(1005583); // Please dismount first. - return false; - } - - if (from.IsBodyMod && !from.Body.IsHuman) - { - from.SendLocalizedMessage(1061628); // You can't do that while polymorphed. - return false; - } - - if (from.HasTrade) - { - from.SendLocalizedMessage(1042317, "", 0x41); // You may not ride at this time - return false; - } - - if (from.Followers + FollowerSlots > from.FollowersMax) - { - from.SendLocalizedMessage(1049679); // You have too many followers to summon your mount. - return false; - } - - return DesignContext.Check(from); - } - - public override void OnDoubleClick(Mobile from) - { - if (Validate(from)) - new EtherealSpell(this, from).Cast(); - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - - LabelTo(from, m_IsDonationItem ? "Donation Ethereal" : "Veteran Reward"); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(3); // version - - writer.Write(m_IsDonationItem); - writer.Write(IsRewardItem); - - writer.Write(m_MountedID); - writer.Write(m_RegularID); - writer.Write(m_Rider); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - LootType = LootType.Blessed; - - int version = reader.ReadInt(); - - switch (version) - { - case 3: - { - m_IsDonationItem = reader.ReadBool(); - goto case 2; - } - case 2: - { - IsRewardItem = reader.ReadBool(); - goto case 0; - } - case 1: - reader.ReadInt(); - goto case 0; - case 0: - { - m_MountedID = reader.ReadInt(); - m_RegularID = reader.ReadInt(); - m_Rider = reader.ReadMobile(); - - if (m_MountedID == 0x3EA2) - m_MountedID = 0x3EAA; - - break; - } - } - - AddFollowers(); - - if (version < 3 && Weight == 0) - Weight = -1; - } - - public override DeathMoveResult OnParentDeath(Mobile parent) - { - Rider = null; // get off, move to pack - - return DeathMoveResult.RemainEquipped; - } - - public static void Dismount(Mobile m) - { - IMount mount = m.Mount; - - if (mount != null) - mount.Rider = null; - } - - public void UnmountMe() - { - Container bp = m_Rider.Backpack; - - ItemID = m_RegularID; - Layer = Layer.Invalid; - Movable = true; - - if (Hue == EtherealHue) - Hue = 0; - - if (bp != null) - { - bp.DropItem(this); - } - else - { - Point3D loc = m_Rider.Location; - Map map = m_Rider.Map; - - if (map == null || map == Map.Internal) + public override DeathMoveResult OnParentDeath(Mobile parent) { - loc = m_Rider.LogoutLocation; - map = m_Rider.LogoutMap; + Rider = null; // get off, move to pack + + return DeathMoveResult.RemainEquipped; } - MoveToWorld(loc, map); - } + public static void Dismount(Mobile m) + { + var mount = m.Mount; + + if (mount != null) + mount.Rider = null; + } + + public void UnmountMe() + { + var bp = m_Rider.Backpack; + + ItemID = m_RegularID; + Layer = Layer.Invalid; + Movable = true; + + if (Hue == EtherealHue) + Hue = 0; + + if (bp != null) + { + bp.DropItem(this); + } + else + { + var loc = m_Rider.Location; + var map = m_Rider.Map; + + if (map == null || map == Map.Internal) + { + loc = m_Rider.LogoutLocation; + map = m_Rider.LogoutMap; + } + + MoveToWorld(loc, map); + } + } + + public void MountMe() + { + ItemID = m_MountedID; + Layer = Layer.Mount; + Movable = false; + + if (Hue == 0) + Hue = EtherealHue; + + ProcessDelta(); + m_Rider.ProcessDelta(); + m_Rider.EquipItem(this); + m_Rider.ProcessDelta(); + ProcessDelta(); + } + + public static void StopMounting(Mobile mob) + { + (mob.Spell as EtherealSpell)?.Stop(); + } + + private class EtherealSpell : Spell + { + private static readonly SpellInfo m_Info = new SpellInfo("Ethereal Mount", "", 230); + + private readonly EtherealMount m_Mount; + private readonly Mobile m_Rider; + + private bool m_Stop; + + public EtherealSpell(EtherealMount mount, Mobile rider) + : base(rider, null, m_Info) + { + m_Rider = rider; + m_Mount = mount; + } + + public override bool ClearHandsOnCast => false; + public override bool RevealOnCast => false; + + public override double CastDelayFastScalar => 0; + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds( + m_Mount.IsDonationItem && RewardSystem.GetRewardLevel(m_Rider) < 3 ? 7.5 + (Core.AOS ? 3.0 : 2.0) : + Core.AOS ? 3.0 : 2.0 + ); + + public override TimeSpan GetCastRecovery() => TimeSpan.Zero; + + public override int GetMana() => 0; + + public override bool ConsumeReagents() => true; + + public override bool CheckFizzle() => true; + + public void Stop() + { + m_Stop = true; + Disturb(DisturbType.Hurt, false); + } + + public override bool CheckDisturb(DisturbType type, bool checkFirst, bool resistable) + { + if (type == DisturbType.EquipRequest || type == DisturbType.UseRequest /* || type == DisturbType.Hurt*/) + return false; + + return true; + } + + public override void DoHurtFizzle() + { + if (!m_Stop) + base.DoHurtFizzle(); + } + + public override void DoFizzle() + { + if (!m_Stop) + base.DoFizzle(); + } + + public override void OnDisturb(DisturbType type, bool message) + { + if (message && !m_Stop) + Caster.SendLocalizedMessage( + 1049455 + ); // You have been disrupted while attempting to summon your ethereal mount! + + // m_Mount.UnmountMe(); + } + + public override void OnCast() + { + if (!m_Mount.Deleted && m_Mount.Rider == null && m_Mount.Validate(m_Rider)) + m_Mount.Rider = m_Rider; + + FinishSequence(); + } + } } - public void MountMe() + public class EtherealHorse : EtherealMount { - ItemID = m_MountedID; - Layer = Layer.Mount; - Movable = false; + [Constructible] + public EtherealHorse() + : base(0x20DD, 0x3EAA) + { + } - if (Hue == 0) - Hue = EtherealHue; + public EtherealHorse(Serial serial) + : base(serial) + { + } - ProcessDelta(); - m_Rider.ProcessDelta(); - m_Rider.EquipItem(this); - m_Rider.ProcessDelta(); - ProcessDelta(); + public override int LabelNumber => 1041298; // Ethereal Horse Statuette + + 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 (Name == "an ethereal horse") + Name = null; + + if (ItemID == 0x2124) + ItemID = 0x20DD; + } } - public static void StopMounting(Mobile mob) + public class EtherealLlama : EtherealMount { - (mob.Spell as EtherealSpell)?.Stop(); + [Constructible] + public EtherealLlama() + : base(0x20F6, 0x3EAB) + { + } + + public EtherealLlama(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1041300; // Ethereal Llama Statuette + + 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 (Name == "an ethereal llama") + Name = null; + } } - private class EtherealSpell : Spell + public class EtherealOstard : EtherealMount { - private static readonly SpellInfo m_Info = new SpellInfo("Ethereal Mount", "", 230); + [Constructible] + public EtherealOstard() + : base(0x2135, 0x3EAC) + { + } - private readonly EtherealMount m_Mount; - private readonly Mobile m_Rider; + public EtherealOstard(Serial serial) + : base(serial) + { + } - private bool m_Stop; + public override int LabelNumber => 1041299; // Ethereal Ostard Statuette - public EtherealSpell(EtherealMount mount, Mobile rider) - : base(rider, null, m_Info) - { - m_Rider = rider; - m_Mount = mount; - } + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - public override bool ClearHandsOnCast => false; - public override bool RevealOnCast => false; + writer.Write(0); // version + } - public override double CastDelayFastScalar => 0; + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds( - m_Mount.IsDonationItem && RewardSystem.GetRewardLevel(m_Rider) < 3 ? 7.5 + (Core.AOS ? 3.0 : 2.0) : - Core.AOS ? 3.0 : 2.0); + var version = reader.ReadInt(); - public override TimeSpan GetCastRecovery() => TimeSpan.Zero; - - public override int GetMana() => 0; - - public override bool ConsumeReagents() => true; - - public override bool CheckFizzle() => true; - - public void Stop() - { - m_Stop = true; - Disturb(DisturbType.Hurt, false); - } - - public override bool CheckDisturb(DisturbType type, bool checkFirst, bool resistable) - { - if (type == DisturbType.EquipRequest || type == DisturbType.UseRequest /* || type == DisturbType.Hurt*/) - return false; - - return true; - } - - public override void DoHurtFizzle() - { - if (!m_Stop) - base.DoHurtFizzle(); - } - - public override void DoFizzle() - { - if (!m_Stop) - base.DoFizzle(); - } - - public override void OnDisturb(DisturbType type, bool message) - { - if (message && !m_Stop) - Caster.SendLocalizedMessage( - 1049455); // You have been disrupted while attempting to summon your ethereal mount! - - // m_Mount.UnmountMe(); - } - - public override void OnCast() - { - if (!m_Mount.Deleted && m_Mount.Rider == null && m_Mount.Validate(m_Rider)) - m_Mount.Rider = m_Rider; - - FinishSequence(); - } + if (Name == "an ethereal ostard") + Name = null; + } } - } - public class EtherealHorse : EtherealMount - { - [Constructible] - public EtherealHorse() - : base(0x20DD, 0x3EAA) + public class EtherealRidgeback : EtherealMount { + [Constructible] + public EtherealRidgeback() + : base(0x2615, 0x3E9A) + { + } + + public EtherealRidgeback(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1049747; // Ethereal Ridgeback Statuette + + 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 (Name == "an ethereal ridgeback") + Name = null; + } } - public EtherealHorse(Serial serial) - : base(serial) + public class EtherealUnicorn : EtherealMount { + [Constructible] + public EtherealUnicorn() + : base(0x25CE, 0x3E9B) + { + } + + public EtherealUnicorn(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1049745; // Ethereal Unicorn Statuette + + 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 (Name == "an ethereal unicorn") + Name = null; + } } - public override int LabelNumber => 1041298; // Ethereal Horse Statuette - - public override void Serialize(IGenericWriter writer) + public class EtherealBeetle : EtherealMount { - base.Serialize(writer); + [Constructible] + public EtherealBeetle() + : base(0x260F, 0x3E97) + { + } - writer.Write(0); // version + public EtherealBeetle(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1049748; // Ethereal Beetle Statuette + + 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 (Name == "an ethereal beetle") + Name = null; + } } - public override void Deserialize(IGenericReader reader) + public class EtherealKirin : EtherealMount { - base.Deserialize(reader); + [Constructible] + public EtherealKirin() + : base(0x25A0, 0x3E9C) + { + } - int version = reader.ReadInt(); + public EtherealKirin(Serial serial) + : base(serial) + { + } - if (Name == "an ethereal horse") - Name = null; + public override int LabelNumber => 1049746; // Ethereal Ki-Rin Statuette - if (ItemID == 0x2124) - ItemID = 0x20DD; + 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 (Name == "an ethereal kirin") + Name = null; + } } - } - public class EtherealLlama : EtherealMount - { - [Constructible] - public EtherealLlama() - : base(0x20F6, 0x3EAB) + public class EtherealSwampDragon : EtherealMount { + [Constructible] + public EtherealSwampDragon() + : base(0x2619, 0x3E98) + { + } + + public EtherealSwampDragon(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1049749; // Ethereal Swamp Dragon Statuette + + 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 (Name == "an ethereal swamp dragon") + Name = null; + } } - public EtherealLlama(Serial serial) - : base(serial) + public class RideablePolarBear : EtherealMount { + [Constructible] + public RideablePolarBear() + : base(0x20E1, 0x3EC5) + { + } + + public RideablePolarBear(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1076159; // Rideable Polar Bear + public override int EtherealHue => 0; + + 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(); + } } - public override int LabelNumber => 1041300; // Ethereal Llama Statuette - - public override void Serialize(IGenericWriter writer) + public class EtherealCuSidhe : EtherealMount { - base.Serialize(writer); + [Constructible] + public EtherealCuSidhe() + : base(0x2D96, 0x3E91) + { + } - writer.Write(0); // version + public EtherealCuSidhe(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1080386; // Ethereal Cu Sidhe Statuette + + 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(); + } } - public override void Deserialize(IGenericReader reader) + public class EtherealHiryu : EtherealMount { - base.Deserialize(reader); + [Constructible] + public EtherealHiryu() + : base(0x276A, 0x3E94) + { + } - int version = reader.ReadInt(); + public EtherealHiryu(Serial serial) + : base(serial) + { + } - if (Name == "an ethereal llama") - Name = null; + public override int LabelNumber => 1113813; // Ethereal Hiryu Statuette + + 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(); + } } - } - public class EtherealOstard : EtherealMount - { - [Constructible] - public EtherealOstard() - : base(0x2135, 0x3EAC) + public class EtherealReptalon : EtherealMount { + [Constructible] + public EtherealReptalon() + : base(0x2d95, 0x3e90) + { + } + + public EtherealReptalon(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1113812; // Ethereal Reptalon Statuette + + 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(); + } } - public EtherealOstard(Serial serial) - : base(serial) + public class ChargerOfTheFallen : EtherealMount { + [Constructible] + public ChargerOfTheFallen() + : base(0x2D9C, 0x3E92) + { + } + + public ChargerOfTheFallen(Serial serial) + : base(serial) + { + } + + public override int LabelNumber => 1074816; // Charger of the Fallen Statuette + + public override int EtherealHue => 0; + + 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 (version <= 1 && Hue != 0) Hue = 0; + } } - - public override int LabelNumber => 1041299; // Ethereal Ostard Statuette - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Name == "an ethereal ostard") - Name = null; - } - } - - public class EtherealRidgeback : EtherealMount - { - [Constructible] - public EtherealRidgeback() - : base(0x2615, 0x3E9A) - { - } - - public EtherealRidgeback(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1049747; // Ethereal Ridgeback Statuette - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Name == "an ethereal ridgeback") - Name = null; - } - } - - public class EtherealUnicorn : EtherealMount - { - [Constructible] - public EtherealUnicorn() - : base(0x25CE, 0x3E9B) - { - } - - public EtherealUnicorn(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1049745; // Ethereal Unicorn Statuette - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Name == "an ethereal unicorn") - Name = null; - } - } - - public class EtherealBeetle : EtherealMount - { - [Constructible] - public EtherealBeetle() - : base(0x260F, 0x3E97) - { - } - - public EtherealBeetle(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1049748; // Ethereal Beetle Statuette - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Name == "an ethereal beetle") - Name = null; - } - } - - public class EtherealKirin : EtherealMount - { - [Constructible] - public EtherealKirin() - : base(0x25A0, 0x3E9C) - { - } - - public EtherealKirin(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1049746; // Ethereal Ki-Rin Statuette - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Name == "an ethereal kirin") - Name = null; - } - } - - public class EtherealSwampDragon : EtherealMount - { - [Constructible] - public EtherealSwampDragon() - : base(0x2619, 0x3E98) - { - } - - public EtherealSwampDragon(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1049749; // Ethereal Swamp Dragon Statuette - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Name == "an ethereal swamp dragon") - Name = null; - } - } - - public class RideablePolarBear : EtherealMount - { - [Constructible] - public RideablePolarBear() - : base(0x20E1, 0x3EC5) - { - } - - public RideablePolarBear(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1076159; // Rideable Polar Bear - public override int EtherealHue => 0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class EtherealCuSidhe : EtherealMount - { - [Constructible] - public EtherealCuSidhe() - : base(0x2D96, 0x3E91) - { - } - - public EtherealCuSidhe(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1080386; // Ethereal Cu Sidhe Statuette - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class EtherealHiryu : EtherealMount - { - [Constructible] - public EtherealHiryu() - : base(0x276A, 0x3E94) - { - } - - public EtherealHiryu(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1113813; // Ethereal Hiryu Statuette - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class EtherealReptalon : EtherealMount - { - [Constructible] - public EtherealReptalon() - : base(0x2d95, 0x3e90) - { - } - - public EtherealReptalon(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1113812; // Ethereal Reptalon Statuette - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } - - public class ChargerOfTheFallen : EtherealMount - { - [Constructible] - public ChargerOfTheFallen() - : base(0x2D9C, 0x3E92) - { - } - - public ChargerOfTheFallen(Serial serial) - : base(serial) - { - } - - public override int LabelNumber => 1074816; // Charger of the Fallen Statuette - - public override int EtherealHue => 0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version <= 1 && Hue != 0) Hue = 0; - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/FireSteed.cs b/Projects/UOContent/Mobiles/Animals/Mounts/FireSteed.cs index 501e4058d..3ca420c22 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/FireSteed.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/FireSteed.cs @@ -3,81 +3,91 @@ using Server.Items; namespace Server.Mobiles { - public class FireSteed : BaseMount - { - [Constructible] - public FireSteed(string name = "a fire steed") : base(name, 0xBE, 0x3E9E, AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class FireSteed : BaseMount { - BaseSoundID = 0xA8; - - SetStr(376, 400); - SetDex(91, 120); - SetInt(291, 300); - - SetHits(226, 240); - - SetDamage(11, 30); - - SetDamageType(ResistanceType.Physical, 20); - SetDamageType(ResistanceType.Fire, 80); - - SetResistance(ResistanceType.Physical, 30, 40); - SetResistance(ResistanceType.Fire, 70, 80); - SetResistance(ResistanceType.Cold, 20, 30); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 30, 40); - - SetSkill(SkillName.MagicResist, 100.0, 120.0); - SetSkill(SkillName.Tactics, 100.0); - SetSkill(SkillName.Wrestling, 100.0); - - Fame = 20000; - Karma = -20000; - - Tamable = true; - ControlSlots = 2; - MinTameSkill = 106.0; - } - - public FireSteed(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a fire steed corpse"; - - public override bool HasBreath => true; // fire breath enabled - public override FoodType FavoriteFood => FoodType.Meat; - public override PackInstinct PackInstinct => PackInstinct.Daemon | PackInstinct.Equine; - - public override void GenerateLoot() - { - PackItem(new SulfurousAsh(Utility.RandomMinMax(151, 300))); - PackItem(new Ruby(Utility.RandomMinMax(16, 30))); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (BaseSoundID <= 0) - BaseSoundID = 0xA8; - - if (version < 1) - for (int i = 0; i < Skills.Length; ++i) + [Constructible] + public FireSteed(string name = "a fire steed") : base( + name, + 0xBE, + 0x3E9E, + AIType.AI_Melee, + FightMode.Closest, + 10, + 1, + 0.2, + 0.4 + ) { - Skills[i].Cap = Math.Max(100.0, Skills[i].Cap * 0.9); + BaseSoundID = 0xA8; - if (Skills[i].Base > Skills[i].Cap) Skills[i].Base = Skills[i].Cap; + SetStr(376, 400); + SetDex(91, 120); + SetInt(291, 300); + + SetHits(226, 240); + + SetDamage(11, 30); + + SetDamageType(ResistanceType.Physical, 20); + SetDamageType(ResistanceType.Fire, 80); + + SetResistance(ResistanceType.Physical, 30, 40); + SetResistance(ResistanceType.Fire, 70, 80); + SetResistance(ResistanceType.Cold, 20, 30); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 30, 40); + + SetSkill(SkillName.MagicResist, 100.0, 120.0); + SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.Wrestling, 100.0); + + Fame = 20000; + Karma = -20000; + + Tamable = true; + ControlSlots = 2; + MinTameSkill = 106.0; + } + + public FireSteed(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a fire steed corpse"; + + public override bool HasBreath => true; // fire breath enabled + public override FoodType FavoriteFood => FoodType.Meat; + public override PackInstinct PackInstinct => PackInstinct.Daemon | PackInstinct.Equine; + + public override void GenerateLoot() + { + PackItem(new SulfurousAsh(Utility.RandomMinMax(151, 300))); + PackItem(new Ruby(Utility.RandomMinMax(16, 30))); + } + + 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 (BaseSoundID <= 0) + BaseSoundID = 0xA8; + + if (version < 1) + for (var i = 0; i < Skills.Length; ++i) + { + Skills[i].Cap = Math.Max(100.0, Skills[i].Cap * 0.9); + + if (Skills[i].Base > Skills[i].Cap) Skills[i].Base = Skills[i].Cap; + } } } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/ForestOstard.cs b/Projects/UOContent/Mobiles/Animals/Mounts/ForestOstard.cs index dadc9a30b..c8a7cce51 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/ForestOstard.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/ForestOstard.cs @@ -1,61 +1,71 @@ namespace Server.Mobiles { - public class ForestOstard : BaseMount - { - [Constructible] - public ForestOstard(string name = "a forest ostard") : base(name, 0xDB, 0x3EA5, AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class ForestOstard : BaseMount { - Hue = Utility.RandomSlimeHue() | 0x8000; + [Constructible] + public ForestOstard(string name = "a forest ostard") : base( + name, + 0xDB, + 0x3EA5, + AIType.AI_Animal, + FightMode.Aggressor, + 10, + 1, + 0.2, + 0.4 + ) + { + Hue = Utility.RandomSlimeHue() | 0x8000; - BaseSoundID = 0x270; + BaseSoundID = 0x270; - SetStr(94, 170); - SetDex(56, 75); - SetInt(6, 10); + SetStr(94, 170); + SetDex(56, 75); + SetInt(6, 10); - SetHits(71, 88); - SetMana(0); + SetHits(71, 88); + SetMana(0); - SetDamage(8, 14); + SetDamage(8, 14); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 15, 20); + SetResistance(ResistanceType.Physical, 15, 20); - SetSkill(SkillName.MagicResist, 27.1, 32.0); - SetSkill(SkillName.Tactics, 29.3, 44.0); - SetSkill(SkillName.Wrestling, 29.3, 44.0); + SetSkill(SkillName.MagicResist, 27.1, 32.0); + SetSkill(SkillName.Tactics, 29.3, 44.0); + SetSkill(SkillName.Wrestling, 29.3, 44.0); - Fame = 450; - Karma = 0; + Fame = 450; + Karma = 0; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 29.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 29.1; + } + + public ForestOstard(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ostard corpse"; + + public override int Meat => 3; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + public override PackInstinct PackInstinct => PackInstinct.Ostard; + + 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 ForestOstard(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ostard corpse"; - - public override int Meat => 3; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - public override PackInstinct PackInstinct => PackInstinct.Ostard; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/FrenziedOstard.cs b/Projects/UOContent/Mobiles/Animals/Mounts/FrenziedOstard.cs index c0ec8d654..33e7b144b 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/FrenziedOstard.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/FrenziedOstard.cs @@ -1,64 +1,74 @@ namespace Server.Mobiles { - public class FrenziedOstard : BaseMount - { - [Constructible] - public FrenziedOstard(string name = "a frenzied ostard") : base(name, 0xDA, 0x3EA4, AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class FrenziedOstard : BaseMount { - Hue = Race.Human.RandomHairHue() | 0x8000; + [Constructible] + public FrenziedOstard(string name = "a frenzied ostard") : base( + name, + 0xDA, + 0x3EA4, + AIType.AI_Melee, + FightMode.Closest, + 10, + 1, + 0.2, + 0.4 + ) + { + Hue = Race.Human.RandomHairHue() | 0x8000; - BaseSoundID = 0x275; + BaseSoundID = 0x275; - SetStr(94, 170); - SetDex(96, 115); - SetInt(6, 10); + SetStr(94, 170); + SetDex(96, 115); + SetInt(6, 10); - SetHits(71, 110); - SetMana(0); + SetHits(71, 110); + SetMana(0); - SetDamage(11, 17); + SetDamage(11, 17); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 25, 30); - SetResistance(ResistanceType.Fire, 10, 15); - SetResistance(ResistanceType.Poison, 20, 25); - SetResistance(ResistanceType.Energy, 20, 25); + SetResistance(ResistanceType.Physical, 25, 30); + SetResistance(ResistanceType.Fire, 10, 15); + SetResistance(ResistanceType.Poison, 20, 25); + SetResistance(ResistanceType.Energy, 20, 25); - SetSkill(SkillName.MagicResist, 75.1, 80.0); - SetSkill(SkillName.Tactics, 79.3, 94.0); - SetSkill(SkillName.Wrestling, 79.3, 94.0); + SetSkill(SkillName.MagicResist, 75.1, 80.0); + SetSkill(SkillName.Tactics, 79.3, 94.0); + SetSkill(SkillName.Wrestling, 79.3, 94.0); - Fame = 1500; - Karma = -1500; + Fame = 1500; + Karma = -1500; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 77.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 77.1; + } + + public FrenziedOstard(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ostard corpse"; + + public override int Meat => 3; + public override FoodType FavoriteFood => FoodType.Meat | FoodType.Fish | FoodType.Eggs | FoodType.FruitsAndVegies; + public override PackInstinct PackInstinct => PackInstinct.Ostard; + + 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 FrenziedOstard(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ostard corpse"; - - public override int Meat => 3; - public override FoodType FavoriteFood => FoodType.Meat | FoodType.Fish | FoodType.Eggs | FoodType.FruitsAndVegies; - public override PackInstinct PackInstinct => PackInstinct.Ostard; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/HellSteed.cs b/Projects/UOContent/Mobiles/Animals/Mounts/HellSteed.cs index 9f7d11074..1c2479baa 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/HellSteed.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/HellSteed.cs @@ -1,59 +1,69 @@ namespace Server.Mobiles { - public class HellSteed : BaseMount - { - [Constructible] - public HellSteed(string name = "a hellsteed") : base(name, 793, 0x3EBB, AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class HellSteed : BaseMount { - SetStats(this); + [Constructible] + public HellSteed(string name = "a hellsteed") : base( + name, + 793, + 0x3EBB, + AIType.AI_Animal, + FightMode.Aggressor, + 10, + 1, + 0.2, + 0.4 + ) + { + SetStats(this); + } + + public HellSteed(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a hellsteed corpse"; + public override bool HasBreath => true; + public override int BreathChaosDamage => 100; + public override Poison PoisonImmune => Poison.Lethal; + + public static void SetStats(BaseCreature steed) + { + steed.SetStr(201, 210); + steed.SetDex(101, 110); + steed.SetInt(101, 115); + + steed.SetHits(201, 220); + + steed.SetDamage(20, 24); + + steed.SetDamageType(ResistanceType.Physical, 25); + steed.SetDamageType(ResistanceType.Fire, 75); + + steed.SetResistance(ResistanceType.Physical, 60, 70); + steed.SetResistance(ResistanceType.Fire, 90); + steed.SetResistance(ResistanceType.Poison, 100); + + steed.SetSkill(SkillName.MagicResist, 90.1, 110.0); + steed.SetSkill(SkillName.Tactics, 50.0); + steed.SetSkill(SkillName.Wrestling, 90.1, 110.0); + + steed.Fame = 0; + steed.Karma = 0; + } + + 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 HellSteed(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a hellsteed corpse"; - public override bool HasBreath => true; - public override int BreathChaosDamage => 100; - public override Poison PoisonImmune => Poison.Lethal; - - public static void SetStats(BaseCreature steed) - { - steed.SetStr(201, 210); - steed.SetDex(101, 110); - steed.SetInt(101, 115); - - steed.SetHits(201, 220); - - steed.SetDamage(20, 24); - - steed.SetDamageType(ResistanceType.Physical, 25); - steed.SetDamageType(ResistanceType.Fire, 75); - - steed.SetResistance(ResistanceType.Physical, 60, 70); - steed.SetResistance(ResistanceType.Fire, 90); - steed.SetResistance(ResistanceType.Poison, 100); - - steed.SetSkill(SkillName.MagicResist, 90.1, 110.0); - steed.SetSkill(SkillName.Tactics, 50.0); - steed.SetSkill(SkillName.Wrestling, 90.1, 110.0); - - steed.Fame = 0; - steed.Karma = 0; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/Hiryu.cs b/Projects/UOContent/Mobiles/Animals/Mounts/Hiryu.cs index a78f873ad..f5f705a83 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/Hiryu.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/Hiryu.cs @@ -5,222 +5,223 @@ using Server.Items; namespace Server.Mobiles { - public class Hiryu : BaseMount - { - private static readonly Dictionary m_Table = new Dictionary(); - - [Constructible] - public Hiryu() - : base("a hiryu", 243, 0x3E94, AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Hiryu : BaseMount { - Hue = GetHue(); + private static readonly Dictionary m_Table = new Dictionary(); - SetStr(1201, 1410); - SetDex(171, 270); - SetInt(301, 325); - - SetHits(901, 1100); - SetMana(60); - - SetDamage(20, 30); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 55, 70); - SetResistance(ResistanceType.Fire, 70, 90); - SetResistance(ResistanceType.Cold, 15, 25); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 40, 50); - - SetSkill(SkillName.Anatomy, 75.1, 80.0); - SetSkill(SkillName.MagicResist, 85.1, 100.0); - SetSkill(SkillName.Tactics, 100.1, 110.0); - SetSkill(SkillName.Wrestling, 100.1, 120.0); - - Fame = 18000; - Karma = -18000; - - Tamable = true; - ControlSlots = 4; - MinTameSkill = 98.7; - - if (Utility.RandomDouble() < .33) - PackItem(Seed.RandomBonsaiSeed()); - - if (Core.ML && Utility.RandomDouble() < .33) - PackItem(Seed.RandomPeculiarSeed(3)); - } - - public Hiryu(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a hiryu corpse"; - public override double WeaponAbilityChance => 0.07; /* 1 in 15 chance of using per landed hit */ - - public override bool StatLossAfterTame => true; - - public override int TreasureMapLevel => 5; - public override int Meat => 16; - public override int Hides => 60; - public override FoodType FavoriteFood => FoodType.Meat; - public override bool CanAngerOnTame => true; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.Dismount; - - private static int GetHue() - { - int rand = Utility.Random(1075); - - if (rand <= 0) - return 0x855C; - if (rand <= 1) - return 0x8490; - if (rand <= 3) - return 0x8030; - if (rand <= 5) - return 0x8037; - if (rand <= 8) - return 0x8295; - if (rand <= 11) - return 0x8123; - if (rand <= 16) - return 0x8482; - if (rand <= 24) - return 0x8487; - if (rand <= 34) - return 0x8032; - if (rand <= 44) - return 0x8899; - if (rand <= 54) - return 0x8495; - if (rand <= 64) - return 0x848D; - if (rand <= 74) - return 0x847F; - - return 0; - } - - public override int GetAngerSound() => 0x4FE; - - public override int GetIdleSound() => 0x4FD; - - public override int GetAttackSound() => 0x4FC; - - public override int GetHurtSound() => 0x4FF; - - public override int GetDeathSound() => 0x4FB; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 3); - AddLoot(LootPack.Gems, 4); - } - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (Utility.RandomDouble() >= 0.1) - return; - - /* Grasping Claw - * Start cliloc: 1070836 - * Effect: Physical resistance -15% for 5 seconds - * End cliloc: 1070838 - * Effect: Type: "3" - From: "0x57D4F5B" (player) - To: "0x0" - ItemId: "0x37B9" - ItemIdName: "glow" - FromLocation: "(1149 808, 32)" - ToLocation: "(1149 808, 32)" - Speed: "10" - Duration: "5" - FixedDirection: "True" - Explode: "False" - */ - - if (m_Table.TryGetValue(defender, out ExpireTimer timer)) - { - timer.DoExpire(); - defender.SendLocalizedMessage(1070837); // The creature lands another blow in your weakened state. - } - else - { - defender.SendLocalizedMessage( - 1070836); // The blow from the creature's claws has made you more susceptible to physical attacks. - } - - int effect = -(defender.PhysicalResistance * 15 / 100); - - ResistanceMod mod = new ResistanceMod(ResistanceType.Physical, effect); - - defender.FixedEffect(0x37B9, 10, 5); - defender.AddResistanceMod(mod); - - timer = new ExpireTimer(defender, mod, TimeSpan.FromSeconds(5.0)); - timer.Start(); - m_Table[defender] = timer; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(2); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (version <= 1) - Timer.DelayCall(Fix, version); - - if (version < 2) - for (int i = 0; i < Skills.Length; ++i) + [Constructible] + public Hiryu() + : base("a hiryu", 243, 0x3E94, AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) { - Skills[i].Cap = Math.Max(100.0, Skills[i].Cap * 0.9); + Hue = GetHue(); - if (Skills[i].Base > Skills[i].Cap) Skills[i].Base = Skills[i].Cap; + SetStr(1201, 1410); + SetDex(171, 270); + SetInt(301, 325); + + SetHits(901, 1100); + SetMana(60); + + SetDamage(20, 30); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 55, 70); + SetResistance(ResistanceType.Fire, 70, 90); + SetResistance(ResistanceType.Cold, 15, 25); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 40, 50); + + SetSkill(SkillName.Anatomy, 75.1, 80.0); + SetSkill(SkillName.MagicResist, 85.1, 100.0); + SetSkill(SkillName.Tactics, 100.1, 110.0); + SetSkill(SkillName.Wrestling, 100.1, 120.0); + + Fame = 18000; + Karma = -18000; + + Tamable = true; + ControlSlots = 4; + MinTameSkill = 98.7; + + if (Utility.RandomDouble() < .33) + PackItem(Seed.RandomBonsaiSeed()); + + if (Core.ML && Utility.RandomDouble() < .33) + PackItem(Seed.RandomPeculiarSeed(3)); + } + + public Hiryu(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a hiryu corpse"; + public override double WeaponAbilityChance => 0.07; /* 1 in 15 chance of using per landed hit */ + + public override bool StatLossAfterTame => true; + + public override int TreasureMapLevel => 5; + public override int Meat => 16; + public override int Hides => 60; + public override FoodType FavoriteFood => FoodType.Meat; + public override bool CanAngerOnTame => true; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.Dismount; + + private static int GetHue() + { + var rand = Utility.Random(1075); + + if (rand <= 0) + return 0x855C; + if (rand <= 1) + return 0x8490; + if (rand <= 3) + return 0x8030; + if (rand <= 5) + return 0x8037; + if (rand <= 8) + return 0x8295; + if (rand <= 11) + return 0x8123; + if (rand <= 16) + return 0x8482; + if (rand <= 24) + return 0x8487; + if (rand <= 34) + return 0x8032; + if (rand <= 44) + return 0x8899; + if (rand <= 54) + return 0x8495; + if (rand <= 64) + return 0x848D; + if (rand <= 74) + return 0x847F; + + return 0; + } + + public override int GetAngerSound() => 0x4FE; + + public override int GetIdleSound() => 0x4FD; + + public override int GetAttackSound() => 0x4FC; + + public override int GetHurtSound() => 0x4FF; + + public override int GetDeathSound() => 0x4FB; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 3); + AddLoot(LootPack.Gems, 4); + } + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomDouble() >= 0.1) + return; + + /* Grasping Claw + * Start cliloc: 1070836 + * Effect: Physical resistance -15% for 5 seconds + * End cliloc: 1070838 + * Effect: Type: "3" - From: "0x57D4F5B" (player) - To: "0x0" - ItemId: "0x37B9" - ItemIdName: "glow" - FromLocation: "(1149 808, 32)" - ToLocation: "(1149 808, 32)" - Speed: "10" - Duration: "5" - FixedDirection: "True" - Explode: "False" + */ + + if (m_Table.TryGetValue(defender, out var timer)) + { + timer.DoExpire(); + defender.SendLocalizedMessage(1070837); // The creature lands another blow in your weakened state. + } + else + { + defender.SendLocalizedMessage( + 1070836 + ); // The blow from the creature's claws has made you more susceptible to physical attacks. + } + + var effect = -(defender.PhysicalResistance * 15 / 100); + + var mod = new ResistanceMod(ResistanceType.Physical, effect); + + defender.FixedEffect(0x37B9, 10, 5); + defender.AddResistanceMod(mod); + + timer = new ExpireTimer(defender, mod, TimeSpan.FromSeconds(5.0)); + timer.Start(); + m_Table[defender] = timer; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(2); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + if (version <= 1) + Timer.DelayCall(Fix, version); + + if (version < 2) + for (var i = 0; i < Skills.Length; ++i) + { + Skills[i].Cap = Math.Max(100.0, Skills[i].Cap * 0.9); + + if (Skills[i].Base > Skills[i].Cap) Skills[i].Base = Skills[i].Cap; + } + } + + private void Fix(int version) + { + switch (version) + { + case 1: + { + if (InternalItem != null) InternalItem.Hue = Hue; + goto case 0; + } + case 0: + { + Hue = GetHue(); + break; + } + } + } + + private class ExpireTimer : Timer + { + private readonly Mobile m_Mobile; + private readonly ResistanceMod m_Mod; + + public ExpireTimer(Mobile m, ResistanceMod mod, TimeSpan delay) + : base(delay) + { + m_Mobile = m; + m_Mod = mod; + Priority = TimerPriority.TwoFiftyMS; + } + + public void DoExpire() + { + m_Mobile.RemoveResistanceMod(m_Mod); + Stop(); + m_Table.Remove(m_Mobile); + } + + protected override void OnTick() + { + m_Mobile.SendLocalizedMessage(1070838); // Your resistance to physical attacks has returned. + DoExpire(); + } } } - - private void Fix(int version) - { - switch (version) - { - case 1: - { - if (InternalItem != null) InternalItem.Hue = Hue; - goto case 0; - } - case 0: - { - Hue = GetHue(); - break; - } - } - } - - private class ExpireTimer : Timer - { - private readonly Mobile m_Mobile; - private readonly ResistanceMod m_Mod; - - public ExpireTimer(Mobile m, ResistanceMod mod, TimeSpan delay) - : base(delay) - { - m_Mobile = m; - m_Mod = mod; - Priority = TimerPriority.TwoFiftyMS; - } - - public void DoExpire() - { - m_Mobile.RemoveResistanceMod(m_Mod); - Stop(); - m_Table.Remove(m_Mobile); - } - - protected override void OnTick() - { - m_Mobile.SendLocalizedMessage(1070838); // Your resistance to physical attacks has returned. - DoExpire(); - } - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/Horse.cs b/Projects/UOContent/Mobiles/Animals/Mounts/Horse.cs index 451df4d43..7a31777a4 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/Horse.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/Horse.cs @@ -1,73 +1,87 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.BrownHorse", "Server.Mobiles.DirtyHorse", "Server.Mobiles.GrayHorse", - "Server.Mobiles.TanHorse")] - public class Horse : BaseMount - { - private static readonly int[] m_IDs = + [TypeAlias( + "Server.Mobiles.BrownHorse", + "Server.Mobiles.DirtyHorse", + "Server.Mobiles.GrayHorse", + "Server.Mobiles.TanHorse" + )] + public class Horse : BaseMount { - 0xC8, 0x3E9F, - 0xE2, 0x3EA0, - 0xE4, 0x3EA1, - 0xCC, 0x3EA2 - }; + private static readonly int[] m_IDs = + { + 0xC8, 0x3E9F, + 0xE2, 0x3EA0, + 0xE4, 0x3EA1, + 0xCC, 0x3EA2 + }; - [Constructible] - public Horse(string name = "a horse") : base(name, 0xE2, 0x3EA0, AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) - { - int random = Utility.Random(4); + [Constructible] + public Horse(string name = "a horse") : base( + name, + 0xE2, + 0x3EA0, + AIType.AI_Animal, + FightMode.Aggressor, + 10, + 1, + 0.2, + 0.4 + ) + { + var random = Utility.Random(4); - Body = m_IDs[random * 2]; - ItemID = m_IDs[random * 2 + 1]; - BaseSoundID = 0xA8; + Body = m_IDs[random * 2]; + ItemID = m_IDs[random * 2 + 1]; + BaseSoundID = 0xA8; - SetStr(22, 98); - SetDex(56, 75); - SetInt(6, 10); + SetStr(22, 98); + SetDex(56, 75); + SetInt(6, 10); - SetHits(28, 45); - SetMana(0); + SetHits(28, 45); + SetMana(0); - SetDamage(3, 4); + SetDamage(3, 4); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 15, 20); + SetResistance(ResistanceType.Physical, 15, 20); - SetSkill(SkillName.MagicResist, 25.1, 30.0); - SetSkill(SkillName.Tactics, 29.3, 44.0); - SetSkill(SkillName.Wrestling, 29.3, 44.0); + SetSkill(SkillName.MagicResist, 25.1, 30.0); + SetSkill(SkillName.Tactics, 29.3, 44.0); + SetSkill(SkillName.Wrestling, 29.3, 44.0); - Fame = 300; - Karma = 300; + Fame = 300; + Karma = 300; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 29.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 29.1; + } + + public Horse(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a horse corpse"; + + public override int Meat => 3; + public override int Hides => 10; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + + 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 Horse(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a horse corpse"; - - public override int Meat => 3; - public override int Hides => 10; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/Kirin.cs b/Projects/UOContent/Mobiles/Animals/Mounts/Kirin.cs index 836234e13..6c6e1f898 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/Kirin.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/Kirin.cs @@ -4,123 +4,130 @@ using Server.Network; namespace Server.Mobiles { - public class Kirin : BaseMount - { - [Constructible] - public Kirin(string name = "a ki-rin") : base(name, 132, 0x3EAD, AIType.AI_Mage, FightMode.Evil, 10, 1, 0.2, 0.4) + public class Kirin : BaseMount { - BaseSoundID = 0x3C5; + [Constructible] + public Kirin(string name = "a ki-rin") : base(name, 132, 0x3EAD, AIType.AI_Mage, FightMode.Evil, 10, 1, 0.2, 0.4) + { + BaseSoundID = 0x3C5; - SetStr(296, 325); - SetDex(86, 105); - SetInt(186, 225); + SetStr(296, 325); + SetDex(86, 105); + SetInt(186, 225); - SetHits(191, 210); + SetHits(191, 210); - SetDamage(16, 22); + SetDamage(16, 22); - SetDamageType(ResistanceType.Physical, 70); - SetDamageType(ResistanceType.Fire, 10); - SetDamageType(ResistanceType.Cold, 10); - SetDamageType(ResistanceType.Energy, 10); + SetDamageType(ResistanceType.Physical, 70); + SetDamageType(ResistanceType.Fire, 10); + SetDamageType(ResistanceType.Cold, 10); + SetDamageType(ResistanceType.Energy, 10); - SetResistance(ResistanceType.Physical, 55, 65); - SetResistance(ResistanceType.Fire, 35, 45); - SetResistance(ResistanceType.Cold, 25, 35); - SetResistance(ResistanceType.Poison, 25, 35); - SetResistance(ResistanceType.Energy, 25, 35); + SetResistance(ResistanceType.Physical, 55, 65); + SetResistance(ResistanceType.Fire, 35, 45); + SetResistance(ResistanceType.Cold, 25, 35); + SetResistance(ResistanceType.Poison, 25, 35); + SetResistance(ResistanceType.Energy, 25, 35); - SetSkill(SkillName.EvalInt, 80.1, 90.0); - SetSkill(SkillName.Magery, 60.4, 100.0); - SetSkill(SkillName.Meditation, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 85.3, 100.0); - SetSkill(SkillName.Tactics, 20.1, 22.5); - SetSkill(SkillName.Wrestling, 80.5, 92.5); + SetSkill(SkillName.EvalInt, 80.1, 90.0); + SetSkill(SkillName.Magery, 60.4, 100.0); + SetSkill(SkillName.Meditation, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 85.3, 100.0); + SetSkill(SkillName.Tactics, 20.1, 22.5); + SetSkill(SkillName.Wrestling, 80.5, 92.5); - Fame = 9000; - Karma = 9000; + Fame = 9000; + Karma = 9000; - Tamable = true; - ControlSlots = 2; - MinTameSkill = 95.1; + Tamable = true; + ControlSlots = 2; + MinTameSkill = 95.1; + } + + public Kirin(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a ki-rin corpse"; + public override bool AllowFemaleRider => false; + public override bool AllowFemaleTamer => false; + + public override bool InitialInnocent => true; + + public override TimeSpan MountAbilityDelay => TimeSpan.FromHours(1.0); + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override int Meat => 3; + public override int Hides => 10; + public override HideType HideType => HideType.Horned; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + + public override void OnDisallowedRider(Mobile m) + { + m.SendLocalizedMessage(1042319); // The Ki-Rin refuses your attempts to mount it. + } + + public override bool DoMountAbility(int damage, Mobile attacker) + { + if (Rider == null || attacker == null) // sanity + return false; + + if (Rider.Hits - damage < 30 && Rider.Map == attacker.Map && Rider.InRange(attacker, 18) + ) // Range and map checked here instead of other base fuction because of abiliites that don't need to check this + { + attacker.BoltEffect(0); + // 35~100 damage, unresistable, by the Ki-rin. + attacker.Damage( + Utility.RandomMinMax(35, 100), + this, + false + ); // Don't inform mount about this damage, Still unsure wether or not it's flagged as the mount doing damage or the player. If changed to player, without the extra bool it'd be an infinite loop + + Rider.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1042534 + ); // Your mount calls down the forces of nature on your opponent. + Rider.FixedParticles(0, 0, 0, 0x13A7, EffectLayer.Waist); + Rider.PlaySound(0xA9); // Ki-rin's whinny. + return true; + } + + return false; + } + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.LowScrolls); + AddLoot(LootPack.Potions); + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + if (Utility.RandomDouble() < 0.35) + c.DropItem(new KirinBrains()); + } + + 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) + AI = AIType.AI_Mage; + } } - - public Kirin(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a ki-rin corpse"; - public override bool AllowFemaleRider => false; - public override bool AllowFemaleTamer => false; - - public override bool InitialInnocent => true; - - public override TimeSpan MountAbilityDelay => TimeSpan.FromHours(1.0); - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override int Meat => 3; - public override int Hides => 10; - public override HideType HideType => HideType.Horned; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - - public override void OnDisallowedRider(Mobile m) - { - m.SendLocalizedMessage(1042319); // The Ki-Rin refuses your attempts to mount it. - } - - public override bool DoMountAbility(int damage, Mobile attacker) - { - if (Rider == null || attacker == null) // sanity - return false; - - if (Rider.Hits - damage < 30 && Rider.Map == attacker.Map && Rider.InRange(attacker, 18)) // Range and map checked here instead of other base fuction because of abiliites that don't need to check this - { - attacker.BoltEffect(0); - // 35~100 damage, unresistable, by the Ki-rin. - attacker.Damage(Utility.RandomMinMax(35, 100), this, - false); // Don't inform mount about this damage, Still unsure wether or not it's flagged as the mount doing damage or the player. If changed to player, without the extra bool it'd be an infinite loop - - Rider.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1042534); // Your mount calls down the forces of nature on your opponent. - Rider.FixedParticles(0, 0, 0, 0x13A7, EffectLayer.Waist); - Rider.PlaySound(0xA9); // Ki-rin's whinny. - return true; - } - - return false; - } - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.LowScrolls); - AddLoot(LootPack.Potions); - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - if (Utility.RandomDouble() < 0.35) - c.DropItem(new KirinBrains()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version == 0) - AI = AIType.AI_Mage; - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/LesserHiryu.cs b/Projects/UOContent/Mobiles/Animals/Mounts/LesserHiryu.cs index d66a77c16..994af5bc6 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/LesserHiryu.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/LesserHiryu.cs @@ -5,239 +5,240 @@ using Server.Items; namespace Server.Mobiles { - public class LesserHiryu : BaseMount - { - private static readonly Dictionary m_Table = new Dictionary(); - - [Constructible] - public LesserHiryu() - : base("a lesser hiryu", 243, 0x3E94, AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class LesserHiryu : BaseMount { - Hue = GetHue(); + private static readonly Dictionary m_Table = new Dictionary(); - SetStr(301, 410); - SetDex(171, 270); - SetInt(301, 325); - - SetHits(401, 600); - SetMana(60); - - SetDamage(18, 23); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 45, 70); - SetResistance(ResistanceType.Fire, 60, 80); - SetResistance(ResistanceType.Cold, 5, 15); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 30, 40); - - SetSkill(SkillName.Anatomy, 75.1, 80.0); - SetSkill(SkillName.MagicResist, 85.1, 100.0); - SetSkill(SkillName.Tactics, 100.1, 110.0); - SetSkill(SkillName.Wrestling, 100.1, 120.0); - - Fame = 10000; - Karma = -10000; - - Tamable = true; - ControlSlots = 3; - MinTameSkill = 98.7; - - if (Utility.RandomDouble() < .33) - PackItem(Seed.RandomBonsaiSeed()); - } - - public LesserHiryu(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a hiryu corpse"; - public override double WeaponAbilityChance => 0.07; /* 1 in 15 chance of using; 1 in 5 chance of success */ - - public override bool StatLossAfterTame => true; - - public override int TreasureMapLevel => 3; - public override int Meat => 16; - public override int Hides => 60; - public override FoodType FavoriteFood => FoodType.Meat; - public override bool CanAngerOnTame => true; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.Dismount; - - private static int GetHue() - { - int rand = Utility.Random(527); - - /* - - 500 527 No Hue Color 94.88% 0 - 10 527 Green 1.90% 0x8295 - 10 527 Green 1.90% 0x8163 (Very Close to Above Green) //this one is an approximation - 5 527 Dark Green 0.95% 0x87D4 - 1 527 Valorite 0.19% 0x88AB - 1 527 Midnight Blue 0.19% 0x8258 - - * */ - - if (rand <= 0) - return 0x8258; - if (rand <= 1) - return 0x88AB; - if (rand <= 6) - return 0x87D4; - if (rand <= 16) - return 0x8163; - if (rand <= 26) - return 0x8295; - - return 0; - } - - public override bool OverrideBondingReqs() - { - if (ControlMaster.Skills.Bushido.Base >= 90.0) - return true; - return false; - } - - public override int GetAngerSound() => 0x4FE; - - public override int GetIdleSound() => 0x4FD; - - public override int GetAttackSound() => 0x4FC; - - public override int GetHurtSound() => 0x4FF; - - public override int GetDeathSound() => 0x4FB; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 2); - AddLoot(LootPack.Gems, 4); - } - - public override double GetControlChance(Mobile m, bool useBaseSkill = false) - { - double tamingChance = base.GetControlChance(m, useBaseSkill); - - if (tamingChance >= 0.95) return tamingChance; - - double skill = useBaseSkill ? m.Skills.Bushido.Base : m.Skills.Bushido.Value; - - if (skill < 90.0) return tamingChance; - - double bushidoChance = (skill - 30.0) / 100; - - if (m.Skills.Bushido.Base >= 120) - bushidoChance += 0.05; - - return bushidoChance > tamingChance ? bushidoChance : tamingChance; - } - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (Utility.RandomDouble() >= 0.1) - return; - - /* Grasping Claw - * Start cliloc: 1070836 - * Effect: Physical resistance -15% for 5 seconds - * End cliloc: 1070838 - * Effect: Type: "3" - From: "0x57D4F5B" (player) - To: "0x0" - ItemId: "0x37B9" - ItemIdName: "glow" - FromLocation: "(1149 808, 32)" - ToLocation: "(1149 808, 32)" - Speed: "10" - Duration: "5" - FixedDirection: "True" - Explode: "False" - */ - - if (m_Table.TryGetValue(defender, out ExpireTimer timer)) - { - timer.DoExpire(); - defender.SendLocalizedMessage(1070837); // The creature lands another blow in your weakened state. - } - else - { - defender.SendLocalizedMessage( - 1070836); // The blow from the creature's claws has made you more susceptible to physical attacks. - } - - int effect = -(defender.PhysicalResistance * 15 / 100); - - ResistanceMod mod = new ResistanceMod(ResistanceType.Physical, effect); - - defender.FixedEffect(0x37B9, 10, 5); - defender.AddResistanceMod(mod); - - timer = new ExpireTimer(defender, mod, TimeSpan.FromSeconds(5.0)); - timer.Start(); - m_Table[defender] = timer; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(2); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (version <= 1) - Timer.DelayCall(Fix, version); - - if (version < 2) - for (int i = 0; i < Skills.Length; ++i) + [Constructible] + public LesserHiryu() + : base("a lesser hiryu", 243, 0x3E94, AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) { - Skills[i].Cap = Math.Max(100.0, Skills[i].Cap * 0.9); + Hue = GetHue(); - if (Skills[i].Base > Skills[i].Cap) Skills[i].Base = Skills[i].Cap; + SetStr(301, 410); + SetDex(171, 270); + SetInt(301, 325); + + SetHits(401, 600); + SetMana(60); + + SetDamage(18, 23); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 45, 70); + SetResistance(ResistanceType.Fire, 60, 80); + SetResistance(ResistanceType.Cold, 5, 15); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 30, 40); + + SetSkill(SkillName.Anatomy, 75.1, 80.0); + SetSkill(SkillName.MagicResist, 85.1, 100.0); + SetSkill(SkillName.Tactics, 100.1, 110.0); + SetSkill(SkillName.Wrestling, 100.1, 120.0); + + Fame = 10000; + Karma = -10000; + + Tamable = true; + ControlSlots = 3; + MinTameSkill = 98.7; + + if (Utility.RandomDouble() < .33) + PackItem(Seed.RandomBonsaiSeed()); + } + + public LesserHiryu(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a hiryu corpse"; + public override double WeaponAbilityChance => 0.07; /* 1 in 15 chance of using; 1 in 5 chance of success */ + + public override bool StatLossAfterTame => true; + + public override int TreasureMapLevel => 3; + public override int Meat => 16; + public override int Hides => 60; + public override FoodType FavoriteFood => FoodType.Meat; + public override bool CanAngerOnTame => true; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.Dismount; + + private static int GetHue() + { + var rand = Utility.Random(527); + + /* + + 500 527 No Hue Color 94.88% 0 + 10 527 Green 1.90% 0x8295 + 10 527 Green 1.90% 0x8163 (Very Close to Above Green) //this one is an approximation + 5 527 Dark Green 0.95% 0x87D4 + 1 527 Valorite 0.19% 0x88AB + 1 527 Midnight Blue 0.19% 0x8258 + + * */ + + if (rand <= 0) + return 0x8258; + if (rand <= 1) + return 0x88AB; + if (rand <= 6) + return 0x87D4; + if (rand <= 16) + return 0x8163; + if (rand <= 26) + return 0x8295; + + return 0; + } + + public override bool OverrideBondingReqs() + { + if (ControlMaster.Skills.Bushido.Base >= 90.0) + return true; + return false; + } + + public override int GetAngerSound() => 0x4FE; + + public override int GetIdleSound() => 0x4FD; + + public override int GetAttackSound() => 0x4FC; + + public override int GetHurtSound() => 0x4FF; + + public override int GetDeathSound() => 0x4FB; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 2); + AddLoot(LootPack.Gems, 4); + } + + public override double GetControlChance(Mobile m, bool useBaseSkill = false) + { + var tamingChance = base.GetControlChance(m, useBaseSkill); + + if (tamingChance >= 0.95) return tamingChance; + + var skill = useBaseSkill ? m.Skills.Bushido.Base : m.Skills.Bushido.Value; + + if (skill < 90.0) return tamingChance; + + var bushidoChance = (skill - 30.0) / 100; + + if (m.Skills.Bushido.Base >= 120) + bushidoChance += 0.05; + + return bushidoChance > tamingChance ? bushidoChance : tamingChance; + } + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomDouble() >= 0.1) + return; + + /* Grasping Claw + * Start cliloc: 1070836 + * Effect: Physical resistance -15% for 5 seconds + * End cliloc: 1070838 + * Effect: Type: "3" - From: "0x57D4F5B" (player) - To: "0x0" - ItemId: "0x37B9" - ItemIdName: "glow" - FromLocation: "(1149 808, 32)" - ToLocation: "(1149 808, 32)" - Speed: "10" - Duration: "5" - FixedDirection: "True" - Explode: "False" + */ + + if (m_Table.TryGetValue(defender, out var timer)) + { + timer.DoExpire(); + defender.SendLocalizedMessage(1070837); // The creature lands another blow in your weakened state. + } + else + { + defender.SendLocalizedMessage( + 1070836 + ); // The blow from the creature's claws has made you more susceptible to physical attacks. + } + + var effect = -(defender.PhysicalResistance * 15 / 100); + + var mod = new ResistanceMod(ResistanceType.Physical, effect); + + defender.FixedEffect(0x37B9, 10, 5); + defender.AddResistanceMod(mod); + + timer = new ExpireTimer(defender, mod, TimeSpan.FromSeconds(5.0)); + timer.Start(); + m_Table[defender] = timer; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(2); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + if (version <= 1) + Timer.DelayCall(Fix, version); + + if (version < 2) + for (var i = 0; i < Skills.Length; ++i) + { + Skills[i].Cap = Math.Max(100.0, Skills[i].Cap * 0.9); + + if (Skills[i].Base > Skills[i].Cap) Skills[i].Base = Skills[i].Cap; + } + } + + private void Fix(int version) + { + switch (version) + { + case 1: + { + if (InternalItem != null) InternalItem.Hue = Hue; + goto case 0; + } + case 0: + { + Hue = GetHue(); + break; + } + } + } + + private class ExpireTimer : Timer + { + private readonly Mobile m_Mobile; + private readonly ResistanceMod m_Mod; + + public ExpireTimer(Mobile m, ResistanceMod mod, TimeSpan delay) + : base(delay) + { + m_Mobile = m; + m_Mod = mod; + Priority = TimerPriority.TwoFiftyMS; + } + + public void DoExpire() + { + m_Mobile.RemoveResistanceMod(m_Mod); + Stop(); + m_Table.Remove(m_Mobile); + } + + protected override void OnTick() + { + m_Mobile.SendLocalizedMessage(1070838); // Your resistance to physical attacks has returned. + DoExpire(); + } } } - - private void Fix(int version) - { - switch (version) - { - case 1: - { - if (InternalItem != null) InternalItem.Hue = Hue; - goto case 0; - } - case 0: - { - Hue = GetHue(); - break; - } - } - } - - private class ExpireTimer : Timer - { - private readonly Mobile m_Mobile; - private readonly ResistanceMod m_Mod; - - public ExpireTimer(Mobile m, ResistanceMod mod, TimeSpan delay) - : base(delay) - { - m_Mobile = m; - m_Mod = mod; - Priority = TimerPriority.TwoFiftyMS; - } - - public void DoExpire() - { - m_Mobile.RemoveResistanceMod(m_Mod); - Stop(); - m_Table.Remove(m_Mobile); - } - - protected override void OnTick() - { - m_Mobile.SendLocalizedMessage(1070838); // Your resistance to physical attacks has returned. - DoExpire(); - } - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/Nightmare.cs b/Projects/UOContent/Mobiles/Animals/Mounts/Nightmare.cs index 1e66754b5..a700a4446 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/Nightmare.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/Nightmare.cs @@ -2,117 +2,127 @@ using Server.Items; namespace Server.Mobiles { - public class Nightmare : BaseMount - { - [Constructible] - public Nightmare(string name = "a nightmare") : base(name, 0x74, 0x3EA7, AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Nightmare : BaseMount { - BaseSoundID = Core.AOS ? 0xA8 : 0x16A; + [Constructible] + public Nightmare(string name = "a nightmare") : base( + name, + 0x74, + 0x3EA7, + AIType.AI_Mage, + FightMode.Closest, + 10, + 1, + 0.2, + 0.4 + ) + { + BaseSoundID = Core.AOS ? 0xA8 : 0x16A; - SetStr(496, 525); - SetDex(86, 105); - SetInt(86, 125); + SetStr(496, 525); + SetDex(86, 105); + SetInt(86, 125); - SetHits(298, 315); + SetHits(298, 315); - SetDamage(16, 22); + SetDamage(16, 22); - SetDamageType(ResistanceType.Physical, 40); - SetDamageType(ResistanceType.Fire, 40); - SetDamageType(ResistanceType.Energy, 20); + SetDamageType(ResistanceType.Physical, 40); + SetDamageType(ResistanceType.Fire, 40); + SetDamageType(ResistanceType.Energy, 20); - SetResistance(ResistanceType.Physical, 55, 65); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 20, 30); + SetResistance(ResistanceType.Physical, 55, 65); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 20, 30); - SetSkill(SkillName.EvalInt, 10.4, 50.0); - SetSkill(SkillName.Magery, 10.4, 50.0); - SetSkill(SkillName.MagicResist, 85.3, 100.0); - SetSkill(SkillName.Tactics, 97.6, 100.0); - SetSkill(SkillName.Wrestling, 80.5, 92.5); + SetSkill(SkillName.EvalInt, 10.4, 50.0); + SetSkill(SkillName.Magery, 10.4, 50.0); + SetSkill(SkillName.MagicResist, 85.3, 100.0); + SetSkill(SkillName.Tactics, 97.6, 100.0); + SetSkill(SkillName.Wrestling, 80.5, 92.5); - Fame = 14000; - Karma = -14000; + Fame = 14000; + Karma = -14000; - VirtualArmor = 60; + VirtualArmor = 60; - Tamable = true; - ControlSlots = 2; - MinTameSkill = 95.1; + Tamable = true; + ControlSlots = 2; + MinTameSkill = 95.1; - switch (Utility.Random(3)) - { - case 0: - { - BodyValue = 116; - ItemID = 16039; - break; - } - case 1: - { - BodyValue = 178; - ItemID = 16041; - break; - } - case 2: - { - BodyValue = 179; - ItemID = 16055; - break; - } - } + switch (Utility.Random(3)) + { + case 0: + { + BodyValue = 116; + ItemID = 16039; + break; + } + case 1: + { + BodyValue = 178; + ItemID = 16041; + break; + } + case 2: + { + BodyValue = 179; + ItemID = 16055; + break; + } + } - PackItem(new SulfurousAsh(Utility.RandomMinMax(3, 5))); + PackItem(new SulfurousAsh(Utility.RandomMinMax(3, 5))); + } + + public Nightmare(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a nightmare corpse"; + + public override bool HasBreath => true; // fire breath enabled + public override int Meat => 5; + public override int Hides => 10; + public override HideType HideType => HideType.Barbed; + public override FoodType FavoriteFood => FoodType.Meat; + public override bool CanAngerOnTame => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.Average); + AddLoot(LootPack.LowScrolls); + AddLoot(LootPack.Potions); + } + + public override int GetAngerSound() + { + if (!Controlled) + return 0x16A; + + return base.GetAngerSound(); + } + + 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 (Core.AOS && BaseSoundID == 0x16A) + BaseSoundID = 0xA8; + else if (!Core.AOS && BaseSoundID == 0xA8) + BaseSoundID = 0x16A; + } } - - public Nightmare(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a nightmare corpse"; - - public override bool HasBreath => true; // fire breath enabled - public override int Meat => 5; - public override int Hides => 10; - public override HideType HideType => HideType.Barbed; - public override FoodType FavoriteFood => FoodType.Meat; - public override bool CanAngerOnTame => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.Average); - AddLoot(LootPack.LowScrolls); - AddLoot(LootPack.Potions); - } - - public override int GetAngerSound() - { - if (!Controlled) - return 0x16A; - - return base.GetAngerSound(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Core.AOS && BaseSoundID == 0x16A) - BaseSoundID = 0xA8; - else if (!Core.AOS && BaseSoundID == 0xA8) - BaseSoundID = 0x16A; - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/RidableLlama.cs b/Projects/UOContent/Mobiles/Animals/Mounts/RidableLlama.cs index ca298e515..d35d8ef1a 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/RidableLlama.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/RidableLlama.cs @@ -1,63 +1,73 @@ namespace Server.Mobiles { - public class RidableLlama : BaseMount - { - [Constructible] - public RidableLlama(string name = "a ridable llama") : base(name, 0xDC, 0x3EA6, AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class RidableLlama : BaseMount { - BaseSoundID = 0x3F3; + [Constructible] + public RidableLlama(string name = "a ridable llama") : base( + name, + 0xDC, + 0x3EA6, + AIType.AI_Animal, + FightMode.Aggressor, + 10, + 1, + 0.2, + 0.4 + ) + { + BaseSoundID = 0x3F3; - SetStr(21, 49); - SetDex(56, 75); - SetInt(16, 30); + SetStr(21, 49); + SetDex(56, 75); + SetInt(16, 30); - SetHits(15, 27); - SetMana(0); + SetHits(15, 27); + SetMana(0); - SetDamage(3, 5); + SetDamage(3, 5); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 10, 15); - SetResistance(ResistanceType.Fire, 5, 10); - SetResistance(ResistanceType.Cold, 5, 10); - SetResistance(ResistanceType.Poison, 5, 10); - SetResistance(ResistanceType.Energy, 5, 10); + SetResistance(ResistanceType.Physical, 10, 15); + SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Cold, 5, 10); + SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Energy, 5, 10); - SetSkill(SkillName.MagicResist, 15.1, 20.0); - SetSkill(SkillName.Tactics, 19.2, 29.0); - SetSkill(SkillName.Wrestling, 19.2, 29.0); + SetSkill(SkillName.MagicResist, 15.1, 20.0); + SetSkill(SkillName.Tactics, 19.2, 29.0); + SetSkill(SkillName.Wrestling, 19.2, 29.0); - Fame = 300; - Karma = 0; + Fame = 300; + Karma = 0; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 29.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 29.1; + } + + public RidableLlama(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a llama corpse"; + + public override int Meat => 1; + public override int Hides => 12; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + + 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 RidableLlama(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a llama corpse"; - - public override int Meat => 1; - public override int Hides => 12; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/Ridgeback.cs b/Projects/UOContent/Mobiles/Animals/Mounts/Ridgeback.cs index ff5995900..f92bcebf7 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/Ridgeback.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/Ridgeback.cs @@ -1,68 +1,78 @@ namespace Server.Mobiles { - public class Ridgeback : BaseMount - { - [Constructible] - public Ridgeback(string name = "a ridgeback") : base(name, 187, 0x3EBA, AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Ridgeback : BaseMount { - BaseSoundID = 0x3F3; + [Constructible] + public Ridgeback(string name = "a ridgeback") : base( + name, + 187, + 0x3EBA, + AIType.AI_Animal, + FightMode.Aggressor, + 10, + 1, + 0.2, + 0.4 + ) + { + BaseSoundID = 0x3F3; - SetStr(58, 100); - SetDex(56, 75); - SetInt(16, 30); + SetStr(58, 100); + SetDex(56, 75); + SetInt(16, 30); - SetHits(41, 54); - SetMana(0); + SetHits(41, 54); + SetMana(0); - SetDamage(3, 5); + SetDamage(3, 5); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 15, 25); - SetResistance(ResistanceType.Fire, 5, 10); - SetResistance(ResistanceType.Cold, 5, 10); - SetResistance(ResistanceType.Poison, 5, 10); - SetResistance(ResistanceType.Energy, 5, 10); + SetResistance(ResistanceType.Physical, 15, 25); + SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Cold, 5, 10); + SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Energy, 5, 10); - SetSkill(SkillName.MagicResist, 25.3, 40.0); - SetSkill(SkillName.Tactics, 29.3, 44.0); - SetSkill(SkillName.Wrestling, 35.1, 45.0); + SetSkill(SkillName.MagicResist, 25.3, 40.0); + SetSkill(SkillName.Tactics, 29.3, 44.0); + SetSkill(SkillName.Wrestling, 35.1, 45.0); - Fame = 300; - Karma = 0; + Fame = 300; + Karma = 0; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 83.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 83.1; + } + + public Ridgeback(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a ridgeback corpse"; + + public override int Meat => 1; + public override int Hides => 12; + public override HideType HideType => HideType.Spined; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + + public override bool OverrideBondingReqs() => true; + + public override double GetControlChance(Mobile m, bool useBaseSkill = false) => 1.0; + + 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 Ridgeback(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a ridgeback corpse"; - - public override int Meat => 1; - public override int Hides => 12; - public override HideType HideType => HideType.Spined; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - - public override bool OverrideBondingReqs() => true; - - public override double GetControlChance(Mobile m, bool useBaseSkill = false) => 1.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/SavageRidgeback.cs b/Projects/UOContent/Mobiles/Animals/Mounts/SavageRidgeback.cs index 3f67c0942..ad1292e19 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/SavageRidgeback.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/SavageRidgeback.cs @@ -1,68 +1,78 @@ namespace Server.Mobiles { - public class SavageRidgeback : BaseMount - { - [Constructible] - public SavageRidgeback(string name = "a savage ridgeback") : base(name, 188, 0x3EB8, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class SavageRidgeback : BaseMount { - BaseSoundID = 0x3F3; + [Constructible] + public SavageRidgeback(string name = "a savage ridgeback") : base( + name, + 188, + 0x3EB8, + AIType.AI_Melee, + FightMode.Aggressor, + 10, + 1, + 0.2, + 0.4 + ) + { + BaseSoundID = 0x3F3; - SetStr(58, 100); - SetDex(56, 75); - SetInt(16, 30); + SetStr(58, 100); + SetDex(56, 75); + SetInt(16, 30); - SetHits(41, 54); - SetMana(0); + SetHits(41, 54); + SetMana(0); - SetDamage(3, 5); + SetDamage(3, 5); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 15, 20); - SetResistance(ResistanceType.Fire, 10, 15); - SetResistance(ResistanceType.Cold, 15, 20); - SetResistance(ResistanceType.Poison, 10, 15); - SetResistance(ResistanceType.Energy, 10, 15); + SetResistance(ResistanceType.Physical, 15, 20); + SetResistance(ResistanceType.Fire, 10, 15); + SetResistance(ResistanceType.Cold, 15, 20); + SetResistance(ResistanceType.Poison, 10, 15); + SetResistance(ResistanceType.Energy, 10, 15); - SetSkill(SkillName.MagicResist, 25.3, 40.0); - SetSkill(SkillName.Tactics, 29.3, 44.0); - SetSkill(SkillName.Wrestling, 35.1, 45.0); + SetSkill(SkillName.MagicResist, 25.3, 40.0); + SetSkill(SkillName.Tactics, 29.3, 44.0); + SetSkill(SkillName.Wrestling, 35.1, 45.0); - Fame = 300; - Karma = 0; + Fame = 300; + Karma = 0; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 83.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 83.1; + } + + public SavageRidgeback(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a savage ridgeback corpse"; + + public override int Meat => 1; + public override int Hides => 12; + public override HideType HideType => HideType.Spined; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + + public override bool OverrideBondingReqs() => true; + + public override double GetControlChance(Mobile m, bool useBaseSkill = false) => 1.0; + + 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 SavageRidgeback(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a savage ridgeback corpse"; - - public override int Meat => 1; - public override int Hides => 12; - public override HideType HideType => HideType.Spined; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - - public override bool OverrideBondingReqs() => true; - - public override double GetControlChance(Mobile m, bool useBaseSkill = false) => 1.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/ScaledSwampDragon.cs b/Projects/UOContent/Mobiles/Animals/Mounts/ScaledSwampDragon.cs index f04cf712e..045dd8e25 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/ScaledSwampDragon.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/ScaledSwampDragon.cs @@ -1,65 +1,75 @@ namespace Server.Mobiles { - public class ScaledSwampDragon : BaseMount - { - [Constructible] - public ScaledSwampDragon(string name = "a swamp dragon") : base(name, 0x31F, 0x3EBE, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class ScaledSwampDragon : BaseMount { - SetStr(201, 300); - SetDex(66, 85); - SetInt(61, 100); + [Constructible] + public ScaledSwampDragon(string name = "a swamp dragon") : base( + name, + 0x31F, + 0x3EBE, + AIType.AI_Melee, + FightMode.Aggressor, + 10, + 1, + 0.2, + 0.4 + ) + { + SetStr(201, 300); + SetDex(66, 85); + SetInt(61, 100); - SetHits(121, 180); + SetHits(121, 180); - SetDamage(3, 4); + SetDamage(3, 4); - SetDamageType(ResistanceType.Physical, 75); - SetDamageType(ResistanceType.Poison, 25); + SetDamageType(ResistanceType.Physical, 75); + SetDamageType(ResistanceType.Poison, 25); - SetResistance(ResistanceType.Physical, 35, 40); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 20, 40); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 35, 40); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 20, 40); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.Anatomy, 45.1, 55.0); - SetSkill(SkillName.MagicResist, 45.1, 55.0); - SetSkill(SkillName.Tactics, 45.1, 55.0); - SetSkill(SkillName.Wrestling, 45.1, 55.0); + SetSkill(SkillName.Anatomy, 45.1, 55.0); + SetSkill(SkillName.MagicResist, 45.1, 55.0); + SetSkill(SkillName.Tactics, 45.1, 55.0); + SetSkill(SkillName.Wrestling, 45.1, 55.0); - Fame = 2000; - Karma = -2000; + Fame = 2000; + Karma = -2000; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 93.9; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 93.9; + } + + public ScaledSwampDragon(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a swamp dragon corpse"; + + public override bool AutoDispel => !Controlled; + public override FoodType FavoriteFood => FoodType.Meat; + + public override bool OverrideBondingReqs() => true; + + public override double GetControlChance(Mobile m, bool useBaseSkill = false) => 1.0; + + 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 ScaledSwampDragon(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a swamp dragon corpse"; - - public override bool AutoDispel => !Controlled; - public override FoodType FavoriteFood => FoodType.Meat; - - public override bool OverrideBondingReqs() => true; - - public override double GetControlChance(Mobile m, bool useBaseSkill = false) => 1.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/SeaHorse.cs b/Projects/UOContent/Mobiles/Animals/Mounts/SeaHorse.cs index 065012fe3..0729514cd 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/SeaHorse.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/SeaHorse.cs @@ -1,34 +1,44 @@ namespace Server.Mobiles { - public class SeaHorse : BaseMount - { - [Constructible] - public SeaHorse(string name = "a sea horse") : base(name, 0x90, 0x3EB3, AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class SeaHorse : BaseMount { - InitStats(Utility.Random(50, 30), Utility.Random(50, 30), 10); - Skills.MagicResist.Base = 25.0 + Utility.RandomDouble() * 5.0; - Skills.Wrestling.Base = 35.0 + Utility.RandomDouble() * 10.0; - Skills.Tactics.Base = 30.0 + Utility.RandomDouble() * 15.0; + [Constructible] + public SeaHorse(string name = "a sea horse") : base( + name, + 0x90, + 0x3EB3, + AIType.AI_Animal, + FightMode.Aggressor, + 10, + 1, + 0.2, + 0.4 + ) + { + InitStats(Utility.Random(50, 30), Utility.Random(50, 30), 10); + Skills.MagicResist.Base = 25.0 + Utility.RandomDouble() * 5.0; + Skills.Wrestling.Base = 35.0 + Utility.RandomDouble() * 10.0; + Skills.Tactics.Base = 30.0 + Utility.RandomDouble() * 15.0; + } + + public SeaHorse(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a sea horse corpse"; + + 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 SeaHorse(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a sea horse corpse"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/SilverSteed.cs b/Projects/UOContent/Mobiles/Animals/Mounts/SilverSteed.cs index 9ce533002..3ffe7159a 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/SilverSteed.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/SilverSteed.cs @@ -1,38 +1,48 @@ namespace Server.Mobiles { - public class SilverSteed : BaseMount - { - [Constructible] - public SilverSteed(string name = "a silver steed") : base(name, 0x75, 0x3EA8, AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class SilverSteed : BaseMount { - InitStats(Utility.Random(50, 30), Utility.Random(50, 30), 10); - Skills.MagicResist.Base = 25.0 + Utility.RandomDouble() * 5.0; - Skills.Wrestling.Base = 35.0 + Utility.RandomDouble() * 10.0; - Skills.Tactics.Base = 30.0 + Utility.RandomDouble() * 15.0; + [Constructible] + public SilverSteed(string name = "a silver steed") : base( + name, + 0x75, + 0x3EA8, + AIType.AI_Animal, + FightMode.Aggressor, + 10, + 1, + 0.2, + 0.4 + ) + { + InitStats(Utility.Random(50, 30), Utility.Random(50, 30), 10); + Skills.MagicResist.Base = 25.0 + Utility.RandomDouble() * 5.0; + Skills.Wrestling.Base = 35.0 + Utility.RandomDouble() * 10.0; + Skills.Tactics.Base = 30.0 + Utility.RandomDouble() * 15.0; - ControlSlots = 1; - Tamable = true; - MinTameSkill = 103.1; + ControlSlots = 1; + Tamable = true; + MinTameSkill = 103.1; + } + + public SilverSteed(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a silver steed corpse"; + + 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 SilverSteed(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a silver steed corpse"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/SkeletalMount.cs b/Projects/UOContent/Mobiles/Animals/Mounts/SkeletalMount.cs index 1d7f7401a..eb14bdb2f 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/SkeletalMount.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/SkeletalMount.cs @@ -1,67 +1,77 @@ namespace Server.Mobiles { - public class SkeletalMount : BaseMount - { - [Constructible] - public SkeletalMount(string name = null) : base(name, 793, 0x3EBB, AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class SkeletalMount : BaseMount { - SetStr(91, 100); - SetDex(46, 55); - SetInt(46, 60); + [Constructible] + public SkeletalMount(string name = null) : base( + name, + 793, + 0x3EBB, + AIType.AI_Animal, + FightMode.Aggressor, + 10, + 1, + 0.2, + 0.4 + ) + { + SetStr(91, 100); + SetDex(46, 55); + SetInt(46, 60); - SetHits(41, 50); + SetHits(41, 50); - SetDamage(5, 12); + SetDamage(5, 12); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Cold, 50); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Cold, 50); - SetResistance(ResistanceType.Physical, 50, 60); - SetResistance(ResistanceType.Cold, 90, 95); - SetResistance(ResistanceType.Poison, 100); - SetResistance(ResistanceType.Energy, 10, 15); + SetResistance(ResistanceType.Physical, 50, 60); + SetResistance(ResistanceType.Cold, 90, 95); + SetResistance(ResistanceType.Poison, 100); + SetResistance(ResistanceType.Energy, 10, 15); - SetSkill(SkillName.MagicResist, 95.1, 100.0); - SetSkill(SkillName.Tactics, 50.0); - SetSkill(SkillName.Wrestling, 70.1, 80.0); + SetSkill(SkillName.MagicResist, 95.1, 100.0); + SetSkill(SkillName.Tactics, 50.0); + SetSkill(SkillName.Wrestling, 70.1, 80.0); - Fame = 0; - Karma = 0; + Fame = 0; + Karma = 0; + } + + public SkeletalMount(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an undead horse corpse"; + public override string DefaultName => "a skeletal steed"; + + public override Poison PoisonImmune => Poison.Lethal; + public override bool BleedImmune => true; + + 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(); + + switch (version) + { + case 0: + { + Tamable = false; + MinTameSkill = 0.0; + ControlSlots = 0; + break; + } + } + } } - - public SkeletalMount(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an undead horse corpse"; - public override string DefaultName => "a skeletal steed"; - - public override Poison PoisonImmune => Poison.Lethal; - public override bool BleedImmune => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Tamable = false; - MinTameSkill = 0.0; - ControlSlots = 0; - break; - } - } - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/SwampDragon.cs b/Projects/UOContent/Mobiles/Animals/Mounts/SwampDragon.cs index 77b18641a..e917988a7 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/SwampDragon.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/SwampDragon.cs @@ -2,199 +2,209 @@ using Server.Items; namespace Server.Mobiles { - public class SwampDragon : BaseMount - { - private Mobile m_BardingCrafter; - private bool m_BardingExceptional; - private int m_BardingHP; - private CraftResource m_BardingResource; - private bool m_HasBarding; - - [Constructible] - public SwampDragon(string name = "a swamp dragon") : base(name, 0x31A, 0x3EBD, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class SwampDragon : BaseMount { - BaseSoundID = 0x16A; + private Mobile m_BardingCrafter; + private bool m_BardingExceptional; + private int m_BardingHP; + private CraftResource m_BardingResource; + private bool m_HasBarding; - SetStr(201, 300); - SetDex(66, 85); - SetInt(61, 100); - - SetHits(121, 180); - - SetDamage(3, 4); - - SetDamageType(ResistanceType.Physical, 75); - SetDamageType(ResistanceType.Poison, 25); - - SetResistance(ResistanceType.Physical, 35, 40); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 20, 40); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 30, 40); - - SetSkill(SkillName.Anatomy, 45.1, 55.0); - SetSkill(SkillName.MagicResist, 45.1, 55.0); - SetSkill(SkillName.Tactics, 45.1, 55.0); - SetSkill(SkillName.Wrestling, 45.1, 55.0); - - Fame = 2000; - Karma = -2000; - - Hue = 0x851; - - Tamable = true; - ControlSlots = 1; - MinTameSkill = 93.9; - } - - public SwampDragon(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a swamp dragon corpse"; - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile BardingCrafter - { - get => m_BardingCrafter; - set - { - m_BardingCrafter = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool BardingExceptional - { - get => m_BardingExceptional; - set - { - m_BardingExceptional = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int BardingHP - { - get => m_BardingHP; - set - { - m_BardingHP = value; - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool HasBarding - { - get => m_HasBarding; - set - { - m_HasBarding = value; - - if (m_HasBarding) + [Constructible] + public SwampDragon(string name = "a swamp dragon") : base( + name, + 0x31A, + 0x3EBD, + AIType.AI_Melee, + FightMode.Aggressor, + 10, + 1, + 0.2, + 0.4 + ) { - Hue = CraftResources.GetHue(m_BardingResource); - BodyValue = 0x31F; - ItemID = 0x3EBE; - } - else - { - Hue = 0x851; - BodyValue = 0x31A; - ItemID = 0x3EBD; + BaseSoundID = 0x16A; + + SetStr(201, 300); + SetDex(66, 85); + SetInt(61, 100); + + SetHits(121, 180); + + SetDamage(3, 4); + + SetDamageType(ResistanceType.Physical, 75); + SetDamageType(ResistanceType.Poison, 25); + + SetResistance(ResistanceType.Physical, 35, 40); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 20, 40); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 30, 40); + + SetSkill(SkillName.Anatomy, 45.1, 55.0); + SetSkill(SkillName.MagicResist, 45.1, 55.0); + SetSkill(SkillName.Tactics, 45.1, 55.0); + SetSkill(SkillName.Wrestling, 45.1, 55.0); + + Fame = 2000; + Karma = -2000; + + Hue = 0x851; + + Tamable = true; + ControlSlots = 1; + MinTameSkill = 93.9; } - InvalidateProperties(); - } + public SwampDragon(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a swamp dragon corpse"; + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile BardingCrafter + { + get => m_BardingCrafter; + set + { + m_BardingCrafter = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool BardingExceptional + { + get => m_BardingExceptional; + set + { + m_BardingExceptional = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int BardingHP + { + get => m_BardingHP; + set + { + m_BardingHP = value; + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool HasBarding + { + get => m_HasBarding; + set + { + m_HasBarding = value; + + if (m_HasBarding) + { + Hue = CraftResources.GetHue(m_BardingResource); + BodyValue = 0x31F; + ItemID = 0x3EBE; + } + else + { + Hue = 0x851; + BodyValue = 0x31A; + ItemID = 0x3EBD; + } + + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public CraftResource BardingResource + { + get => m_BardingResource; + set + { + m_BardingResource = value; + + if (m_HasBarding) + Hue = CraftResources.GetHue(value); + + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int BardingMaxHP => m_BardingExceptional ? 2500 : 1000; + + public override bool ReacquireOnMovement => true; + public override bool AutoDispel => !Controlled; + public override FoodType FavoriteFood => FoodType.Meat; + public override int Meat => 19; + public override int Hides => 20; + public override int Scales => 5; + public override ScaleType ScaleType => ScaleType.Green; + public override bool CanAngerOnTame => true; + + public override bool OverrideBondingReqs() => true; + + public override int GetIdleSound() => 0x2CE; + + public override int GetDeathSound() => 0x2CC; + + public override int GetHurtSound() => 0x2D1; + + public override int GetAttackSound() => 0x2C8; + + public override double GetControlChance(Mobile m, bool useBaseSkill = false) => 1.0; + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (m_HasBarding && m_BardingExceptional && m_BardingCrafter != null) + list.Add(1060853, m_BardingCrafter.Name); // armor exceptionally crafted by ~1_val~ + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(m_BardingExceptional); + writer.Write(m_BardingCrafter); + writer.Write(m_HasBarding); + writer.Write(m_BardingHP); + writer.Write((int)m_BardingResource); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_BardingExceptional = reader.ReadBool(); + m_BardingCrafter = reader.ReadMobile(); + m_HasBarding = reader.ReadBool(); + m_BardingHP = reader.ReadInt(); + m_BardingResource = (CraftResource)reader.ReadInt(); + break; + } + } + + if (Hue == 0 && !m_HasBarding) + Hue = 0x851; + + if (BaseSoundID == -1) + BaseSoundID = 0x16A; + } } - - [CommandProperty(AccessLevel.GameMaster)] - public CraftResource BardingResource - { - get => m_BardingResource; - set - { - m_BardingResource = value; - - if (m_HasBarding) - Hue = CraftResources.GetHue(value); - - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int BardingMaxHP => m_BardingExceptional ? 2500 : 1000; - - public override bool ReacquireOnMovement => true; - public override bool AutoDispel => !Controlled; - public override FoodType FavoriteFood => FoodType.Meat; - public override int Meat => 19; - public override int Hides => 20; - public override int Scales => 5; - public override ScaleType ScaleType => ScaleType.Green; - public override bool CanAngerOnTame => true; - - public override bool OverrideBondingReqs() => true; - - public override int GetIdleSound() => 0x2CE; - - public override int GetDeathSound() => 0x2CC; - - public override int GetHurtSound() => 0x2D1; - - public override int GetAttackSound() => 0x2C8; - - public override double GetControlChance(Mobile m, bool useBaseSkill = false) => 1.0; - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (m_HasBarding && m_BardingExceptional && m_BardingCrafter != null) - list.Add(1060853, m_BardingCrafter.Name); // armor exceptionally crafted by ~1_val~ - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(m_BardingExceptional); - writer.Write(m_BardingCrafter); - writer.Write(m_HasBarding); - writer.Write(m_BardingHP); - writer.Write((int)m_BardingResource); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_BardingExceptional = reader.ReadBool(); - m_BardingCrafter = reader.ReadMobile(); - m_HasBarding = reader.ReadBool(); - m_BardingHP = reader.ReadInt(); - m_BardingResource = (CraftResource)reader.ReadInt(); - break; - } - } - - if (Hue == 0 && !m_HasBarding) - Hue = 0x851; - - if (BaseSoundID == -1) - BaseSoundID = 0x16A; - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/Unicorn.cs b/Projects/UOContent/Mobiles/Animals/Mounts/Unicorn.cs index b9f8a1881..3c5dcd79f 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/Unicorn.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/Unicorn.cs @@ -4,129 +4,134 @@ using Server.Network; namespace Server.Mobiles { - public class Unicorn : BaseMount - { - [Constructible] - public Unicorn(string name = "a unicorn") : base(name, 0x7A, 0x3EB4, AIType.AI_Mage, FightMode.Evil, 10, 1, 0.2, 0.4) + public class Unicorn : BaseMount { - BaseSoundID = 0x4BC; - - SetStr(296, 325); - SetDex(96, 115); - SetInt(186, 225); - - SetHits(191, 210); - - SetDamage(16, 22); - - SetDamageType(ResistanceType.Physical, 75); - SetDamageType(ResistanceType.Energy, 25); - - SetResistance(ResistanceType.Physical, 55, 65); - SetResistance(ResistanceType.Fire, 25, 40); - SetResistance(ResistanceType.Cold, 25, 40); - SetResistance(ResistanceType.Poison, 55, 65); - SetResistance(ResistanceType.Energy, 25, 40); - - SetSkill(SkillName.EvalInt, 80.1, 90.0); - SetSkill(SkillName.Magery, 60.2, 80.0); - SetSkill(SkillName.Meditation, 50.1, 60.0); - SetSkill(SkillName.MagicResist, 75.3, 90.0); - SetSkill(SkillName.Tactics, 20.1, 22.5); - SetSkill(SkillName.Wrestling, 80.5, 92.5); - - Fame = 9000; - Karma = 9000; - - Tamable = true; - ControlSlots = 2; - MinTameSkill = 95.1; - } - - public Unicorn(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a unicorn corpse"; - public override bool AllowMaleRider => false; - public override bool AllowMaleTamer => false; - - public override bool InitialInnocent => true; - - public override TimeSpan MountAbilityDelay => TimeSpan.FromHours(1.0); - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override Poison PoisonImmune => Poison.Lethal; - public override int Meat => 3; - public override int Hides => 10; - public override HideType HideType => HideType.Horned; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - - public override void OnDisallowedRider(Mobile m) - { - m.SendLocalizedMessage(1042318); // The unicorn refuses to allow you to ride it. - } - - public override bool DoMountAbility(int damage, Mobile attacker) - { - if (Rider == null || attacker == null) // sanity - return false; - - if (Rider.Poisoned && Rider.Hits - damage < 40) - { - Poison p = Rider.Poison; - - if (p != null) + [Constructible] + public Unicorn(string name = "a unicorn") : base(name, 0x7A, 0x3EB4, AIType.AI_Mage, FightMode.Evil, 10, 1, 0.2, 0.4) { - int chanceToCure = 10000 + (int)(Skills.Magery.Value * 75) - - (p.Level + 1) * (Core.AOS ? p.Level < 4 ? 3300 : 3100 : 1750); - chanceToCure /= 100; + BaseSoundID = 0x4BC; - if (chanceToCure > Utility.Random(100)) - if (Rider.CurePoison(this)) // TODO: Confirm if mount is the one flagged for curing it or the rider is - { - Rider.LocalOverheadMessage(MessageType.Regular, 0x3B2, true, - "Your mount senses you are in danger and aids you with magic."); - Rider.FixedParticles(0x373A, 10, 15, 5012, EffectLayer.Waist); - Rider.PlaySound(0x1E0); // Cure spell effect. - Rider.PlaySound(0xA9); // Unicorn's whinny. + SetStr(296, 325); + SetDex(96, 115); + SetInt(186, 225); - return true; - } + SetHits(191, 210); + + SetDamage(16, 22); + + SetDamageType(ResistanceType.Physical, 75); + SetDamageType(ResistanceType.Energy, 25); + + SetResistance(ResistanceType.Physical, 55, 65); + SetResistance(ResistanceType.Fire, 25, 40); + SetResistance(ResistanceType.Cold, 25, 40); + SetResistance(ResistanceType.Poison, 55, 65); + SetResistance(ResistanceType.Energy, 25, 40); + + SetSkill(SkillName.EvalInt, 80.1, 90.0); + SetSkill(SkillName.Magery, 60.2, 80.0); + SetSkill(SkillName.Meditation, 50.1, 60.0); + SetSkill(SkillName.MagicResist, 75.3, 90.0); + SetSkill(SkillName.Tactics, 20.1, 22.5); + SetSkill(SkillName.Wrestling, 80.5, 92.5); + + Fame = 9000; + Karma = 9000; + + Tamable = true; + ControlSlots = 2; + MinTameSkill = 95.1; } - } - return false; + public Unicorn(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a unicorn corpse"; + public override bool AllowMaleRider => false; + public override bool AllowMaleTamer => false; + + public override bool InitialInnocent => true; + + public override TimeSpan MountAbilityDelay => TimeSpan.FromHours(1.0); + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override Poison PoisonImmune => Poison.Lethal; + public override int Meat => 3; + public override int Hides => 10; + public override HideType HideType => HideType.Horned; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + + public override void OnDisallowedRider(Mobile m) + { + m.SendLocalizedMessage(1042318); // The unicorn refuses to allow you to ride it. + } + + public override bool DoMountAbility(int damage, Mobile attacker) + { + if (Rider == null || attacker == null) // sanity + return false; + + if (Rider.Poisoned && Rider.Hits - damage < 40) + { + var p = Rider.Poison; + + if (p != null) + { + var chanceToCure = 10000 + (int)(Skills.Magery.Value * 75) - + (p.Level + 1) * (Core.AOS ? p.Level < 4 ? 3300 : 3100 : 1750); + chanceToCure /= 100; + + if (chanceToCure > Utility.Random(100)) + if (Rider.CurePoison(this) + ) // TODO: Confirm if mount is the one flagged for curing it or the rider is + { + Rider.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + true, + "Your mount senses you are in danger and aids you with magic." + ); + Rider.FixedParticles(0x373A, 10, 15, 5012, EffectLayer.Waist); + Rider.PlaySound(0x1E0); // Cure spell effect. + Rider.PlaySound(0xA9); // Unicorn's whinny. + + return true; + } + } + } + + return false; + } + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.LowScrolls); + AddLoot(LootPack.Potions); + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + if (Utility.RandomDouble() < 0.35) + c.DropItem(new UnicornRibs()); + } + + 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 GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.LowScrolls); - AddLoot(LootPack.Potions); - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - if (Utility.RandomDouble() < 0.35) - c.DropItem(new UnicornRibs()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/War Horses/BaseWarHorse.cs b/Projects/UOContent/Mobiles/Animals/Mounts/War Horses/BaseWarHorse.cs index 4d07138e7..a103a344d 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/War Horses/BaseWarHorse.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/War Horses/BaseWarHorse.cs @@ -1,64 +1,75 @@ namespace Server.Mobiles { - public abstract class BaseWarHorse : BaseMount - { - public BaseWarHorse(int bodyID, int itemID, AIType aiType, FightMode fightMode, int rangePerception, int rangeFight, - double activeSpeed, double passiveSpeed) : base("a war horse", bodyID, itemID, aiType, fightMode, - rangePerception, rangeFight, activeSpeed, passiveSpeed) + public abstract class BaseWarHorse : BaseMount { - BaseSoundID = 0xA8; + public BaseWarHorse( + int bodyID, int itemID, AIType aiType, FightMode fightMode, int rangePerception, int rangeFight, + double activeSpeed, double passiveSpeed + ) : base( + "a war horse", + bodyID, + itemID, + aiType, + fightMode, + rangePerception, + rangeFight, + activeSpeed, + passiveSpeed + ) + { + BaseSoundID = 0xA8; - InitStats(Utility.Random(300, 100), 125, 60); + InitStats(Utility.Random(300, 100), 125, 60); - SetStr(400); - SetDex(125); - SetInt(51, 55); + SetStr(400); + SetDex(125); + SetInt(51, 55); - SetHits(240); - SetMana(0); + SetHits(240); + SetMana(0); - SetDamage(5, 8); + SetDamage(5, 8); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 40, 50); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 40, 50); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.MagicResist, 25.1, 30.0); - SetSkill(SkillName.Tactics, 29.3, 44.0); - SetSkill(SkillName.Wrestling, 29.3, 44.0); + SetSkill(SkillName.MagicResist, 25.1, 30.0); + SetSkill(SkillName.Tactics, 29.3, 44.0); + SetSkill(SkillName.Wrestling, 29.3, 44.0); - Fame = 300; - Karma = 300; + Fame = 300; + Karma = 300; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 29.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 29.1; + } + + public BaseWarHorse(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a war horse corpse"; + + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + + 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 BaseWarHorse(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a war horse corpse"; - - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/War Horses/CoMWarHorse.cs b/Projects/UOContent/Mobiles/Animals/Mounts/War Horses/CoMWarHorse.cs index fc6ece6bb..0b18db03f 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/War Horses/CoMWarHorse.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/War Horses/CoMWarHorse.cs @@ -1,28 +1,28 @@ namespace Server.Mobiles { - public class CoMWarHorse : BaseWarHorse - { - [Constructible] - public CoMWarHorse() : base(0x77, 0x3EB1, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class CoMWarHorse : BaseWarHorse { + [Constructible] + public CoMWarHorse() : base(0x77, 0x3EB1, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + } + + public CoMWarHorse(Serial serial) : base(serial) + { + } + + 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 CoMWarHorse(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/War Horses/MinaxWarHorse.cs b/Projects/UOContent/Mobiles/Animals/Mounts/War Horses/MinaxWarHorse.cs index 2e2451306..e116dabdb 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/War Horses/MinaxWarHorse.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/War Horses/MinaxWarHorse.cs @@ -1,28 +1,28 @@ namespace Server.Mobiles { - public class MinaxWarHorse : BaseWarHorse - { - [Constructible] - public MinaxWarHorse() : base(0x78, 0x3EAF, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class MinaxWarHorse : BaseWarHorse { + [Constructible] + public MinaxWarHorse() : base(0x78, 0x3EAF, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + } + + public MinaxWarHorse(Serial serial) : base(serial) + { + } + + 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 MinaxWarHorse(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/War Horses/SLWarHorse.cs b/Projects/UOContent/Mobiles/Animals/Mounts/War Horses/SLWarHorse.cs index 2081d9d68..fb2e04c5d 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/War Horses/SLWarHorse.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/War Horses/SLWarHorse.cs @@ -1,28 +1,28 @@ namespace Server.Mobiles { - public class SLWarHorse : BaseWarHorse - { - [Constructible] - public SLWarHorse() : base(0x79, 0x3EB0, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class SLWarHorse : BaseWarHorse { + [Constructible] + public SLWarHorse() : base(0x79, 0x3EB0, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + } + + public SLWarHorse(Serial serial) : base(serial) + { + } + + 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 SLWarHorse(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Mounts/War Horses/TBWarHorse.cs b/Projects/UOContent/Mobiles/Animals/Mounts/War Horses/TBWarHorse.cs index a165d17cd..aeced8675 100644 --- a/Projects/UOContent/Mobiles/Animals/Mounts/War Horses/TBWarHorse.cs +++ b/Projects/UOContent/Mobiles/Animals/Mounts/War Horses/TBWarHorse.cs @@ -1,28 +1,28 @@ namespace Server.Mobiles { - public class TBWarHorse : BaseWarHorse - { - [Constructible] - public TBWarHorse() : base(0x76, 0x3EB2, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class TBWarHorse : BaseWarHorse { + [Constructible] + public TBWarHorse() : base(0x76, 0x3EB2, AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + } + + public TBWarHorse(Serial serial) : base(serial) + { + } + + 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 TBWarHorse(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Reptiles/Alligator.cs b/Projects/UOContent/Mobiles/Animals/Reptiles/Alligator.cs index d6bed03a2..ab1a45454 100644 --- a/Projects/UOContent/Mobiles/Animals/Reptiles/Alligator.cs +++ b/Projects/UOContent/Mobiles/Animals/Reptiles/Alligator.cs @@ -1,70 +1,70 @@ namespace Server.Mobiles { - public class Alligator : BaseCreature - { - [Constructible] - public Alligator() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Alligator : BaseCreature { - Body = 0xCA; - BaseSoundID = 660; + [Constructible] + public Alligator() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0xCA; + BaseSoundID = 660; - SetStr(76, 100); - SetDex(6, 25); - SetInt(11, 20); + SetStr(76, 100); + SetDex(6, 25); + SetInt(11, 20); - SetHits(46, 60); - SetStam(46, 65); - SetMana(0); + SetHits(46, 60); + SetStam(46, 65); + SetMana(0); - SetDamage(5, 15); + SetDamage(5, 15); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 25, 35); - SetResistance(ResistanceType.Fire, 5, 10); - SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Physical, 25, 35); + SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Poison, 5, 10); - SetSkill(SkillName.MagicResist, 25.1, 40.0); - SetSkill(SkillName.Tactics, 40.1, 60.0); - SetSkill(SkillName.Wrestling, 40.1, 60.0); + SetSkill(SkillName.MagicResist, 25.1, 40.0); + SetSkill(SkillName.Tactics, 40.1, 60.0); + SetSkill(SkillName.Wrestling, 40.1, 60.0); - Fame = 600; - Karma = -600; + Fame = 600; + Karma = -600; - VirtualArmor = 30; + VirtualArmor = 30; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 47.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 47.1; + } + + public Alligator(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an alligator corpse"; + public override string DefaultName => "an alligator"; + + public override int Meat => 1; + public override int Hides => 12; + public override HideType HideType => HideType.Spined; + public override FoodType FavoriteFood => FoodType.Meat | FoodType.Fish; + + 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 (BaseSoundID == 0x5A) + BaseSoundID = 660; + } } - - public Alligator(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an alligator corpse"; - public override string DefaultName => "an alligator"; - - public override int Meat => 1; - public override int Hides => 12; - public override HideType HideType => HideType.Spined; - public override FoodType FavoriteFood => FoodType.Meat | FoodType.Fish; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (BaseSoundID == 0x5A) - BaseSoundID = 660; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Reptiles/GiantSerpent.cs b/Projects/UOContent/Mobiles/Animals/Reptiles/GiantSerpent.cs index afd522f0d..530f140f1 100644 --- a/Projects/UOContent/Mobiles/Animals/Reptiles/GiantSerpent.cs +++ b/Projects/UOContent/Mobiles/Animals/Reptiles/GiantSerpent.cs @@ -2,84 +2,84 @@ using Server.Items; namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Serpant")] - public class GiantSerpent : BaseCreature - { - [Constructible] - public GiantSerpent() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Serpant")] + public class GiantSerpent : BaseCreature { - Body = 0x15; - Hue = Utility.RandomSnakeHue(); - BaseSoundID = 219; + [Constructible] + public GiantSerpent() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0x15; + Hue = Utility.RandomSnakeHue(); + BaseSoundID = 219; - SetStr(186, 215); - SetDex(56, 80); - SetInt(66, 85); + SetStr(186, 215); + SetDex(56, 80); + SetInt(66, 85); - SetHits(112, 129); - SetMana(0); + SetHits(112, 129); + SetMana(0); - SetDamage(7, 17); + SetDamage(7, 17); - SetDamageType(ResistanceType.Physical, 40); - SetDamageType(ResistanceType.Poison, 60); + SetDamageType(ResistanceType.Physical, 40); + SetDamageType(ResistanceType.Poison, 60); - SetResistance(ResistanceType.Physical, 30, 35); - SetResistance(ResistanceType.Fire, 5, 10); - SetResistance(ResistanceType.Cold, 10, 20); - SetResistance(ResistanceType.Poison, 70, 90); - SetResistance(ResistanceType.Energy, 10, 20); + SetResistance(ResistanceType.Physical, 30, 35); + SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Poison, 70, 90); + SetResistance(ResistanceType.Energy, 10, 20); - SetSkill(SkillName.Poisoning, 70.1, 100.0); - SetSkill(SkillName.MagicResist, 25.1, 40.0); - SetSkill(SkillName.Tactics, 65.1, 70.0); - SetSkill(SkillName.Wrestling, 60.1, 80.0); + SetSkill(SkillName.Poisoning, 70.1, 100.0); + SetSkill(SkillName.MagicResist, 25.1, 40.0); + SetSkill(SkillName.Tactics, 65.1, 70.0); + SetSkill(SkillName.Wrestling, 60.1, 80.0); - Fame = 2500; - Karma = -2500; + Fame = 2500; + Karma = -2500; - VirtualArmor = 32; + VirtualArmor = 32; - PackItem(new Bone()); - // TODO: Body parts + PackItem(new Bone()); + // TODO: Body parts + } + + public GiantSerpent(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a giant serpent corpse"; + public override string DefaultName => "a giant snake"; + + public override Poison PoisonImmune => Poison.Greater; + public override Poison HitPoison => Utility.RandomDouble() <= 0.8 ? Poison.Greater : Poison.Deadly; + + public override bool DeathAdderCharmable => true; + + public override int Meat => 4; + public override int Hides => 15; + public override HideType HideType => HideType.Spined; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + } + + 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 (BaseSoundID == -1) + BaseSoundID = 219; + } } - - public GiantSerpent(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a giant serpent corpse"; - public override string DefaultName => "a giant snake"; - - public override Poison PoisonImmune => Poison.Greater; - public override Poison HitPoison => Utility.RandomDouble() <= 0.8 ? Poison.Greater : Poison.Deadly; - - public override bool DeathAdderCharmable => true; - - public override int Meat => 4; - public override int Hides => 15; - public override HideType HideType => HideType.Spined; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (BaseSoundID == -1) - BaseSoundID = 219; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Reptiles/IceSerpent.cs b/Projects/UOContent/Mobiles/Animals/Reptiles/IceSerpent.cs index a2091373e..a7d731da7 100644 --- a/Projects/UOContent/Mobiles/Animals/Reptiles/IceSerpent.cs +++ b/Projects/UOContent/Mobiles/Animals/Reptiles/IceSerpent.cs @@ -2,94 +2,94 @@ using Server.Items; namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Iceserpant")] - public class IceSerpent : BaseCreature - { - [Constructible] - public IceSerpent() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Iceserpant")] + public class IceSerpent : BaseCreature { - Body = 89; - BaseSoundID = 219; - - SetStr(216, 245); - SetDex(26, 50); - SetInt(66, 85); - - SetHits(130, 147); - SetMana(0); - - SetDamage(7, 17); - - SetDamageType(ResistanceType.Physical, 10); - SetDamageType(ResistanceType.Cold, 90); - - SetResistance(ResistanceType.Physical, 30, 35); - SetResistance(ResistanceType.Cold, 80, 90); - SetResistance(ResistanceType.Poison, 15, 25); - SetResistance(ResistanceType.Energy, 10, 20); - - SetSkill(SkillName.Anatomy, 27.5, 50.0); - SetSkill(SkillName.MagicResist, 25.1, 40.0); - SetSkill(SkillName.Tactics, 75.1, 80.0); - SetSkill(SkillName.Wrestling, 60.1, 80.0); - - Fame = 3500; - Karma = -3500; - - VirtualArmor = 32; - - PackItem(Loot.RandomArmorOrShieldOrWeapon()); - - PackItem( - Utility.Random(10) switch + [Constructible] + public IceSerpent() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) { - 0 => new LeftArm(), - 1 => new RightArm(), - 2 => new Torso(), - 3 => new Bone(), - 4 => new RibCage(), - 5 => new RibCage(), - _ => new BonePile() // 6-9 + Body = 89; + BaseSoundID = 219; + + SetStr(216, 245); + SetDex(26, 50); + SetInt(66, 85); + + SetHits(130, 147); + SetMana(0); + + SetDamage(7, 17); + + SetDamageType(ResistanceType.Physical, 10); + SetDamageType(ResistanceType.Cold, 90); + + SetResistance(ResistanceType.Physical, 30, 35); + SetResistance(ResistanceType.Cold, 80, 90); + SetResistance(ResistanceType.Poison, 15, 25); + SetResistance(ResistanceType.Energy, 10, 20); + + SetSkill(SkillName.Anatomy, 27.5, 50.0); + SetSkill(SkillName.MagicResist, 25.1, 40.0); + SetSkill(SkillName.Tactics, 75.1, 80.0); + SetSkill(SkillName.Wrestling, 60.1, 80.0); + + Fame = 3500; + Karma = -3500; + + VirtualArmor = 32; + + PackItem(Loot.RandomArmorOrShieldOrWeapon()); + + PackItem( + Utility.Random(10) switch + { + 0 => new LeftArm(), + 1 => new RightArm(), + 2 => new Torso(), + 3 => new Bone(), + 4 => new RibCage(), + 5 => new RibCage(), + _ => new BonePile() // 6-9 + } + ); + + if (Utility.RandomDouble() < 0.025) + PackItem(new GlacialStaff()); } - ); - if (Utility.RandomDouble() < 0.025) - PackItem(new GlacialStaff()); + public IceSerpent(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ice serpent corpse"; + public override string DefaultName => "a giant ice serpent"; + + public override bool DeathAdderCharmable => true; + + public override int Meat => 4; + public override int Hides => 15; + public override HideType HideType => HideType.Spined; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + 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 (BaseSoundID == -1) + BaseSoundID = 219; + } } - - public IceSerpent(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ice serpent corpse"; - public override string DefaultName => "a giant ice serpent"; - - public override bool DeathAdderCharmable => true; - - public override int Meat => 4; - public override int Hides => 15; - public override HideType HideType => HideType.Spined; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (BaseSoundID == -1) - BaseSoundID = 219; - } - } } diff --git a/Projects/UOContent/Mobiles/Animals/Reptiles/IceSnake.cs b/Projects/UOContent/Mobiles/Animals/Reptiles/IceSnake.cs index 6590cec72..751be390b 100644 --- a/Projects/UOContent/Mobiles/Animals/Reptiles/IceSnake.cs +++ b/Projects/UOContent/Mobiles/Animals/Reptiles/IceSnake.cs @@ -1,70 +1,70 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Icesnake")] - public class IceSnake : BaseCreature - { - [Constructible] - public IceSnake() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Icesnake")] + public class IceSnake : BaseCreature { - Body = 52; - Hue = 0x480; - BaseSoundID = 0xDB; + [Constructible] + public IceSnake() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 52; + Hue = 0x480; + BaseSoundID = 0xDB; - SetStr(42, 54); - SetDex(36, 45); - SetInt(26, 30); + SetStr(42, 54); + SetDex(36, 45); + SetInt(26, 30); - SetMana(0); + SetMana(0); - SetDamage(4, 12); + SetDamage(4, 12); - SetDamageType(ResistanceType.Physical, 25); - SetDamageType(ResistanceType.Cold, 25); - SetDamageType(ResistanceType.Poison, 50); + SetDamageType(ResistanceType.Physical, 25); + SetDamageType(ResistanceType.Cold, 25); + SetDamageType(ResistanceType.Poison, 50); - SetResistance(ResistanceType.Physical, 20, 25); - SetResistance(ResistanceType.Cold, 80, 90); - SetResistance(ResistanceType.Poison, 60, 70); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 20, 25); + SetResistance(ResistanceType.Cold, 80, 90); + SetResistance(ResistanceType.Poison, 60, 70); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.MagicResist, 15.1, 20.0); - SetSkill(SkillName.Tactics, 39.3, 54.0); - SetSkill(SkillName.Wrestling, 39.3, 54.0); + SetSkill(SkillName.MagicResist, 15.1, 20.0); + SetSkill(SkillName.Tactics, 39.3, 54.0); + SetSkill(SkillName.Wrestling, 39.3, 54.0); - Fame = 900; - Karma = -900; + Fame = 900; + Karma = -900; - VirtualArmor = 30; + VirtualArmor = 30; + } + + public IceSnake(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ice snake corpse"; + public override string DefaultName => "an ice snake"; + + public override bool DeathAdderCharmable => true; + + public override int Meat => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + 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(); + } } - - public IceSnake(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ice snake corpse"; - public override string DefaultName => "an ice snake"; - - public override bool DeathAdderCharmable => true; - - public override int Meat => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Reptiles/LavaLizard.cs b/Projects/UOContent/Mobiles/Animals/Reptiles/LavaLizard.cs index 81d75d1f8..ac0dfb0b0 100644 --- a/Projects/UOContent/Mobiles/Animals/Reptiles/LavaLizard.cs +++ b/Projects/UOContent/Mobiles/Animals/Reptiles/LavaLizard.cs @@ -2,76 +2,76 @@ using Server.Items; namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Lavalizard")] - public class LavaLizard : BaseCreature - { - [Constructible] - public LavaLizard() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Lavalizard")] + public class LavaLizard : BaseCreature { - Body = 0xCE; - Hue = Utility.RandomList(0x647, 0x650, 0x659, 0x662, 0x66B, 0x674); - BaseSoundID = 0x5A; + [Constructible] + public LavaLizard() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0xCE; + Hue = Utility.RandomList(0x647, 0x650, 0x659, 0x662, 0x66B, 0x674); + BaseSoundID = 0x5A; - SetStr(126, 150); - SetDex(56, 75); - SetInt(11, 20); + SetStr(126, 150); + SetDex(56, 75); + SetInt(11, 20); - SetHits(76, 90); - SetMana(0); + SetHits(76, 90); + SetMana(0); - SetDamage(6, 24); + SetDamage(6, 24); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 30, 45); - SetResistance(ResistanceType.Poison, 25, 35); - SetResistance(ResistanceType.Energy, 25, 35); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 30, 45); + SetResistance(ResistanceType.Poison, 25, 35); + SetResistance(ResistanceType.Energy, 25, 35); - SetSkill(SkillName.MagicResist, 55.1, 70.0); - SetSkill(SkillName.Tactics, 60.1, 80.0); - SetSkill(SkillName.Wrestling, 60.1, 80.0); + SetSkill(SkillName.MagicResist, 55.1, 70.0); + SetSkill(SkillName.Tactics, 60.1, 80.0); + SetSkill(SkillName.Wrestling, 60.1, 80.0); - Fame = 3000; - Karma = -3000; + Fame = 3000; + Karma = -3000; - VirtualArmor = 40; + VirtualArmor = 40; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 80.7; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 80.7; - PackItem(new SulfurousAsh(Utility.Random(4, 10))); + PackItem(new SulfurousAsh(Utility.Random(4, 10))); + } + + public LavaLizard(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a lava lizard corpse"; + public override string DefaultName => "a lava lizard"; + + public override bool HasBreath => true; // fire breath enabled + public override int Hides => 12; + public override HideType HideType => HideType.Spined; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + 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(); + } } - - public LavaLizard(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a lava lizard corpse"; - public override string DefaultName => "a lava lizard"; - - public override bool HasBreath => true; // fire breath enabled - public override int Hides => 12; - public override HideType HideType => HideType.Spined; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Reptiles/LavaSerpent.cs b/Projects/UOContent/Mobiles/Animals/Reptiles/LavaSerpent.cs index 98351cd43..5a27976a4 100644 --- a/Projects/UOContent/Mobiles/Animals/Reptiles/LavaSerpent.cs +++ b/Projects/UOContent/Mobiles/Animals/Reptiles/LavaSerpent.cs @@ -2,80 +2,80 @@ using Server.Items; namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Lavaserpant")] - public class LavaSerpent : BaseCreature - { - [Constructible] - public LavaSerpent() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Lavaserpant")] + public class LavaSerpent : BaseCreature { - Body = 90; - BaseSoundID = 219; + [Constructible] + public LavaSerpent() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 90; + BaseSoundID = 219; - SetStr(386, 415); - SetDex(56, 80); - SetInt(66, 85); + SetStr(386, 415); + SetDex(56, 80); + SetInt(66, 85); - SetHits(232, 249); - SetMana(0); + SetHits(232, 249); + SetMana(0); - SetDamage(10, 22); + SetDamage(10, 22); - SetDamageType(ResistanceType.Physical, 20); - SetDamageType(ResistanceType.Fire, 80); + SetDamageType(ResistanceType.Physical, 20); + SetDamageType(ResistanceType.Fire, 80); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 70, 80); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 10, 20); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 70, 80); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 10, 20); - SetSkill(SkillName.MagicResist, 25.3, 70.0); - SetSkill(SkillName.Tactics, 65.1, 70.0); - SetSkill(SkillName.Wrestling, 60.1, 80.0); + SetSkill(SkillName.MagicResist, 25.3, 70.0); + SetSkill(SkillName.Tactics, 65.1, 70.0); + SetSkill(SkillName.Wrestling, 60.1, 80.0); - Fame = 4500; - Karma = -4500; + Fame = 4500; + Karma = -4500; - VirtualArmor = 40; + VirtualArmor = 40; - PackItem(new SulfurousAsh(3)); - PackItem(new Bone()); - // TODO: body parts, armour + PackItem(new SulfurousAsh(3)); + PackItem(new Bone()); + // TODO: body parts, armour + } + + public LavaSerpent(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a lava serpent corpse"; + public override string DefaultName => "a lava serpent"; + + public override bool DeathAdderCharmable => true; + + public override bool HasBreath => true; // fire breath enabled + public override int Meat => 4; + public override int Hides => 15; + public override HideType HideType => HideType.Spined; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + } + + 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 (BaseSoundID == -1) + BaseSoundID = 219; + } } - - public LavaSerpent(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a lava serpent corpse"; - public override string DefaultName => "a lava serpent"; - - public override bool DeathAdderCharmable => true; - - public override bool HasBreath => true; // fire breath enabled - public override int Meat => 4; - public override int Hides => 15; - public override HideType HideType => HideType.Spined; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (BaseSoundID == -1) - BaseSoundID = 219; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Reptiles/LavaSnake.cs b/Projects/UOContent/Mobiles/Animals/Reptiles/LavaSnake.cs index a564b640e..cd6434ba6 100644 --- a/Projects/UOContent/Mobiles/Animals/Reptiles/LavaSnake.cs +++ b/Projects/UOContent/Mobiles/Animals/Reptiles/LavaSnake.cs @@ -2,73 +2,73 @@ using Server.Items; namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Lavasnake")] - public class LavaSnake : BaseCreature - { - [Constructible] - public LavaSnake() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Lavasnake")] + public class LavaSnake : BaseCreature { - Body = 52; - Hue = Utility.RandomList(0x647, 0x650, 0x659, 0x662, 0x66B, 0x674); - BaseSoundID = 0xDB; + [Constructible] + public LavaSnake() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 52; + Hue = Utility.RandomList(0x647, 0x650, 0x659, 0x662, 0x66B, 0x674); + BaseSoundID = 0xDB; - SetStr(43, 55); - SetDex(16, 25); - SetInt(6, 10); + SetStr(43, 55); + SetDex(16, 25); + SetInt(6, 10); - SetHits(28, 32); - SetMana(0); + SetHits(28, 32); + SetMana(0); - SetDamage(1, 8); + SetDamage(1, 8); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 20, 25); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 10, 20); + SetResistance(ResistanceType.Physical, 20, 25); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 10, 20); - SetSkill(SkillName.MagicResist, 15.1, 20.0); - SetSkill(SkillName.Tactics, 19.3, 34.0); - SetSkill(SkillName.Wrestling, 19.3, 34.0); + SetSkill(SkillName.MagicResist, 15.1, 20.0); + SetSkill(SkillName.Tactics, 19.3, 34.0); + SetSkill(SkillName.Wrestling, 19.3, 34.0); - Fame = 600; - Karma = -600; + Fame = 600; + Karma = -600; - VirtualArmor = 24; + VirtualArmor = 24; - PackItem(new SulfurousAsh()); + PackItem(new SulfurousAsh()); + } + + public LavaSnake(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a lava snake corpse"; + public override string DefaultName => "a lava snake"; + + public override bool DeathAdderCharmable => true; + + public override bool HasBreath => true; // fire breath enabled + public override int Meat => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Poor); + } + + 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(); + } } - - public LavaSnake(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a lava snake corpse"; - public override string DefaultName => "a lava snake"; - - public override bool DeathAdderCharmable => true; - - public override bool HasBreath => true; // fire breath enabled - public override int Meat => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Poor); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Reptiles/SilverSerpent.cs b/Projects/UOContent/Mobiles/Animals/Reptiles/SilverSerpent.cs index df7b343b1..27ea25f4e 100644 --- a/Projects/UOContent/Mobiles/Animals/Reptiles/SilverSerpent.cs +++ b/Projects/UOContent/Mobiles/Animals/Reptiles/SilverSerpent.cs @@ -3,80 +3,80 @@ using Server.Factions; namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Silverserpant")] - public class SilverSerpent : BaseCreature - { - [Constructible] - public SilverSerpent() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Silverserpant")] + public class SilverSerpent : BaseCreature { - Body = 92; - BaseSoundID = 219; + [Constructible] + public SilverSerpent() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 92; + BaseSoundID = 219; - SetStr(161, 360); - SetDex(151, 300); - SetInt(21, 40); + SetStr(161, 360); + SetDex(151, 300); + SetInt(21, 40); - SetHits(97, 216); + SetHits(97, 216); - SetDamage(5, 21); + SetDamage(5, 21); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Poison, 50); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Poison, 50); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 5, 10); - SetResistance(ResistanceType.Cold, 5, 10); - SetResistance(ResistanceType.Poison, 100); - SetResistance(ResistanceType.Energy, 5, 10); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Cold, 5, 10); + SetResistance(ResistanceType.Poison, 100); + SetResistance(ResistanceType.Energy, 5, 10); - SetSkill(SkillName.Poisoning, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 95.1, 100.0); - SetSkill(SkillName.Tactics, 80.1, 95.0); - SetSkill(SkillName.Wrestling, 85.1, 100.0); + SetSkill(SkillName.Poisoning, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 95.1, 100.0); + SetSkill(SkillName.Tactics, 80.1, 95.0); + SetSkill(SkillName.Wrestling, 85.1, 100.0); - Fame = 7000; - Karma = -7000; + Fame = 7000; + Karma = -7000; - VirtualArmor = 40; + VirtualArmor = 40; + } + + public SilverSerpent(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a silver serpent corpse"; + public override Faction FactionAllegiance => TrueBritannians.Instance; + public override Ethic EthicAllegiance => Ethic.Hero; + + public override string DefaultName => "a silver serpent"; + + public override bool DeathAdderCharmable => true; + + public override int Meat => 1; + public override Poison PoisonImmune => Poison.Lethal; + public override Poison HitPoison => Poison.Lethal; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Gems, 2); + } + + 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 (BaseSoundID == -1) + BaseSoundID = 219; + } } - - public SilverSerpent(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a silver serpent corpse"; - public override Faction FactionAllegiance => TrueBritannians.Instance; - public override Ethic EthicAllegiance => Ethic.Hero; - - public override string DefaultName => "a silver serpent"; - - public override bool DeathAdderCharmable => true; - - public override int Meat => 1; - public override Poison PoisonImmune => Poison.Lethal; - public override Poison HitPoison => Poison.Lethal; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Gems, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (BaseSoundID == -1) - BaseSoundID = 219; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Reptiles/Snake.cs b/Projects/UOContent/Mobiles/Animals/Reptiles/Snake.cs index d1c6a311a..4e8467de5 100644 --- a/Projects/UOContent/Mobiles/Animals/Reptiles/Snake.cs +++ b/Projects/UOContent/Mobiles/Animals/Reptiles/Snake.cs @@ -1,70 +1,70 @@ namespace Server.Mobiles { - public class Snake : BaseCreature - { - [Constructible] - public Snake() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Snake : BaseCreature { - Body = 52; - Hue = Utility.RandomSnakeHue(); - BaseSoundID = 0xDB; + [Constructible] + public Snake() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 52; + Hue = Utility.RandomSnakeHue(); + BaseSoundID = 0xDB; - SetStr(22, 34); - SetDex(16, 25); - SetInt(6, 10); + SetStr(22, 34); + SetDex(16, 25); + SetInt(6, 10); - SetHits(15, 19); - SetMana(0); + SetHits(15, 19); + SetMana(0); - SetDamage(1, 4); + SetDamage(1, 4); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 15, 20); - SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Physical, 15, 20); + SetResistance(ResistanceType.Poison, 20, 30); - SetSkill(SkillName.Poisoning, 50.1, 70.0); - SetSkill(SkillName.MagicResist, 15.1, 20.0); - SetSkill(SkillName.Tactics, 19.3, 34.0); - SetSkill(SkillName.Wrestling, 19.3, 34.0); + SetSkill(SkillName.Poisoning, 50.1, 70.0); + SetSkill(SkillName.MagicResist, 15.1, 20.0); + SetSkill(SkillName.Tactics, 19.3, 34.0); + SetSkill(SkillName.Wrestling, 19.3, 34.0); - Fame = 300; - Karma = -300; + Fame = 300; + Karma = -300; - VirtualArmor = 16; + VirtualArmor = 16; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 59.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 59.1; + } + + public Snake(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a snake corpse"; + public override string DefaultName => "a snake"; + + public override Poison PoisonImmune => Poison.Lesser; + public override Poison HitPoison => Poison.Lesser; + + public override bool DeathAdderCharmable => true; + + public override int Meat => 1; + public override FoodType FavoriteFood => FoodType.Eggs; + + 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(); + } } - - public Snake(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a snake corpse"; - public override string DefaultName => "a snake"; - - public override Poison PoisonImmune => Poison.Lesser; - public override Poison HitPoison => Poison.Lesser; - - public override bool DeathAdderCharmable => true; - - public override int Meat => 1; - public override FoodType FavoriteFood => FoodType.Eggs; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Rodents/GiantRat.cs b/Projects/UOContent/Mobiles/Animals/Rodents/GiantRat.cs index e9ab16301..cda852b99 100644 --- a/Projects/UOContent/Mobiles/Animals/Rodents/GiantRat.cs +++ b/Projects/UOContent/Mobiles/Animals/Rodents/GiantRat.cs @@ -1,71 +1,71 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Giantrat")] - public class GiantRat : BaseCreature - { - [Constructible] - public GiantRat() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Giantrat")] + public class GiantRat : BaseCreature { - Body = 0xD7; - BaseSoundID = 0x188; + [Constructible] + public GiantRat() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0xD7; + BaseSoundID = 0x188; - SetStr(32, 74); - SetDex(46, 65); - SetInt(16, 30); + SetStr(32, 74); + SetDex(46, 65); + SetInt(16, 30); - SetHits(26, 39); - SetMana(0); + SetHits(26, 39); + SetMana(0); - SetDamage(4, 8); + SetDamage(4, 8); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 15, 20); - SetResistance(ResistanceType.Fire, 5, 10); - SetResistance(ResistanceType.Poison, 25, 35); + SetResistance(ResistanceType.Physical, 15, 20); + SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Poison, 25, 35); - SetSkill(SkillName.MagicResist, 25.1, 30.0); - SetSkill(SkillName.Tactics, 29.3, 44.0); - SetSkill(SkillName.Wrestling, 29.3, 44.0); + SetSkill(SkillName.MagicResist, 25.1, 30.0); + SetSkill(SkillName.Tactics, 29.3, 44.0); + SetSkill(SkillName.Wrestling, 29.3, 44.0); - Fame = 300; - Karma = -300; + Fame = 300; + Karma = -300; - VirtualArmor = 18; + VirtualArmor = 18; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 29.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 29.1; + } + + public GiantRat(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a giant rat corpse"; + public override string DefaultName => "a giant rat"; + + public override int Meat => 1; + public override int Hides => 6; + public override FoodType FavoriteFood => FoodType.Fish | FoodType.Meat | FoodType.FruitsAndVegies | FoodType.Eggs; + + public override void GenerateLoot() + { + AddLoot(LootPack.Poor); + } + + 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(); + } } - - public GiantRat(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a giant rat corpse"; - public override string DefaultName => "a giant rat"; - - public override int Meat => 1; - public override int Hides => 6; - public override FoodType FavoriteFood => FoodType.Fish | FoodType.Meat | FoodType.FruitsAndVegies | FoodType.Eggs; - - public override void GenerateLoot() - { - AddLoot(LootPack.Poor); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Rodents/JackRabbit.cs b/Projects/UOContent/Mobiles/Animals/Rodents/JackRabbit.cs index c148a1798..35504b199 100644 --- a/Projects/UOContent/Mobiles/Animals/Rodents/JackRabbit.cs +++ b/Projects/UOContent/Mobiles/Animals/Rodents/JackRabbit.cs @@ -1,70 +1,70 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Jackrabbit")] - public class JackRabbit : BaseCreature - { - [Constructible] - public JackRabbit() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Jackrabbit")] + public class JackRabbit : BaseCreature { - Body = 0xCD; - Hue = 0x1BB; + [Constructible] + public JackRabbit() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 0xCD; + Hue = 0x1BB; - SetStr(15); - SetDex(25); - SetInt(5); + SetStr(15); + SetDex(25); + SetInt(5); - SetHits(9); - SetMana(0); + SetHits(9); + SetMana(0); - SetDamage(1, 2); + SetDamage(1, 2); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 2, 5); + SetResistance(ResistanceType.Physical, 2, 5); - SetSkill(SkillName.MagicResist, 5.0); - SetSkill(SkillName.Tactics, 5.0); - SetSkill(SkillName.Wrestling, 5.0); + SetSkill(SkillName.MagicResist, 5.0); + SetSkill(SkillName.Tactics, 5.0); + SetSkill(SkillName.Wrestling, 5.0); - Fame = 150; - Karma = 0; + Fame = 150; + Karma = 0; - VirtualArmor = 4; + VirtualArmor = 4; - Tamable = true; - ControlSlots = 1; - MinTameSkill = -18.9; + Tamable = true; + ControlSlots = 1; + MinTameSkill = -18.9; + } + + public JackRabbit(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a jack rabbit corpse"; + public override string DefaultName => "a jack rabbit"; + + public override int Meat => 1; + public override int Hides => 1; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies; + + public override int GetAttackSound() => 0xC9; + + public override int GetHurtSound() => 0xCA; + + public override int GetDeathSound() => 0xCB; + + 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(); + } } - - public JackRabbit(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a jack rabbit corpse"; - public override string DefaultName => "a jack rabbit"; - - public override int Meat => 1; - public override int Hides => 1; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies; - - public override int GetAttackSound() => 0xC9; - - public override int GetHurtSound() => 0xCA; - - public override int GetDeathSound() => 0xCB; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Rodents/Rabbit.cs b/Projects/UOContent/Mobiles/Animals/Rodents/Rabbit.cs index e9572dff1..ec4cdc065 100644 --- a/Projects/UOContent/Mobiles/Animals/Rodents/Rabbit.cs +++ b/Projects/UOContent/Mobiles/Animals/Rodents/Rabbit.cs @@ -1,71 +1,71 @@ namespace Server.Mobiles { - public class Rabbit : BaseCreature - { - [Constructible] - public Rabbit() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Rabbit : BaseCreature { - Body = 205; + [Constructible] + public Rabbit() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 205; - if (Utility.RandomBool()) - Hue = Utility.RandomAnimalHue(); + if (Utility.RandomBool()) + Hue = Utility.RandomAnimalHue(); - SetStr(6, 10); - SetDex(26, 38); - SetInt(6, 14); + SetStr(6, 10); + SetDex(26, 38); + SetInt(6, 14); - SetHits(4, 6); - SetMana(0); + SetHits(4, 6); + SetMana(0); - SetDamage(1); + SetDamage(1); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 5, 10); + SetResistance(ResistanceType.Physical, 5, 10); - SetSkill(SkillName.MagicResist, 5.0); - SetSkill(SkillName.Tactics, 5.0); - SetSkill(SkillName.Wrestling, 5.0); + SetSkill(SkillName.MagicResist, 5.0); + SetSkill(SkillName.Tactics, 5.0); + SetSkill(SkillName.Wrestling, 5.0); - Fame = 150; - Karma = 0; + Fame = 150; + Karma = 0; - VirtualArmor = 6; + VirtualArmor = 6; - Tamable = true; - ControlSlots = 1; - MinTameSkill = -18.9; + Tamable = true; + ControlSlots = 1; + MinTameSkill = -18.9; + } + + public Rabbit(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a hare corpse"; + public override string DefaultName => "a rabbit"; + + public override int Meat => 1; + public override int Hides => 1; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies; + + public override int GetAttackSound() => 0xC9; + + public override int GetHurtSound() => 0xCA; + + public override int GetDeathSound() => 0xCB; + + 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(); + } } - - public Rabbit(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a hare corpse"; - public override string DefaultName => "a rabbit"; - - public override int Meat => 1; - public override int Hides => 1; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies; - - public override int GetAttackSound() => 0xC9; - - public override int GetHurtSound() => 0xCA; - - public override int GetDeathSound() => 0xCB; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Rodents/SewerRat.cs b/Projects/UOContent/Mobiles/Animals/Rodents/SewerRat.cs index a4aa20a8c..d2148adb8 100644 --- a/Projects/UOContent/Mobiles/Animals/Rodents/SewerRat.cs +++ b/Projects/UOContent/Mobiles/Animals/Rodents/SewerRat.cs @@ -1,70 +1,70 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Sewerrat")] - public class SewerRat : BaseCreature - { - [Constructible] - public SewerRat() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Sewerrat")] + public class SewerRat : BaseCreature { - Body = 238; - BaseSoundID = 0xCC; + [Constructible] + public SewerRat() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 238; + BaseSoundID = 0xCC; - SetStr(9); - SetDex(25); - SetInt(6, 10); + SetStr(9); + SetDex(25); + SetInt(6, 10); - SetHits(6); - SetMana(0); + SetHits(6); + SetMana(0); - SetDamage(1, 2); + SetDamage(1, 2); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 5, 10); - SetResistance(ResistanceType.Poison, 15, 25); - SetResistance(ResistanceType.Energy, 5, 10); + SetResistance(ResistanceType.Physical, 5, 10); + SetResistance(ResistanceType.Poison, 15, 25); + SetResistance(ResistanceType.Energy, 5, 10); - SetSkill(SkillName.MagicResist, 5.0); - SetSkill(SkillName.Tactics, 5.0); - SetSkill(SkillName.Wrestling, 5.0); + SetSkill(SkillName.MagicResist, 5.0); + SetSkill(SkillName.Tactics, 5.0); + SetSkill(SkillName.Wrestling, 5.0); - Fame = 300; - Karma = -300; + Fame = 300; + Karma = -300; - VirtualArmor = 6; + VirtualArmor = 6; - Tamable = true; - ControlSlots = 1; - MinTameSkill = -0.9; + Tamable = true; + ControlSlots = 1; + MinTameSkill = -0.9; + } + + public SewerRat(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a rat corpse"; + public override string DefaultName => "a sewer rat"; + + public override int Meat => 1; + public override FoodType FavoriteFood => FoodType.Meat | FoodType.Eggs | FoodType.FruitsAndVegies; + + public override void GenerateLoot() + { + AddLoot(LootPack.Poor); + } + + 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(); + } } - - public SewerRat(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a rat corpse"; - public override string DefaultName => "a sewer rat"; - - public override int Meat => 1; - public override FoodType FavoriteFood => FoodType.Meat | FoodType.Eggs | FoodType.FruitsAndVegies; - - public override void GenerateLoot() - { - AddLoot(LootPack.Poor); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Slimes/Jwilson.cs b/Projects/UOContent/Mobiles/Animals/Slimes/Jwilson.cs index d85e21ace..2b0e90b42 100644 --- a/Projects/UOContent/Mobiles/Animals/Slimes/Jwilson.cs +++ b/Projects/UOContent/Mobiles/Animals/Slimes/Jwilson.cs @@ -1,54 +1,54 @@ namespace Server.Mobiles { - public class Jwilson : BaseCreature - { - [Constructible] - public Jwilson() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Jwilson : BaseCreature { - Hue = Utility.RandomList(0x89C, 0x8A2, 0x8A8, 0x8AE); - Body = 0x33; - VirtualArmor = 8; + [Constructible] + public Jwilson() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Hue = Utility.RandomList(0x89C, 0x8A2, 0x8A8, 0x8AE); + Body = 0x33; + VirtualArmor = 8; - InitStats(Utility.Random(22, 13), Utility.Random(16, 6), Utility.Random(16, 5)); + InitStats(Utility.Random(22, 13), Utility.Random(16, 6), Utility.Random(16, 5)); - Skills.Wrestling.Base = Utility.Random(24, 17); - Skills.Tactics.Base = Utility.Random(18, 14); - Skills.MagicResist.Base = Utility.Random(15, 6); - Skills.Poisoning.Base = Utility.Random(31, 20); + Skills.Wrestling.Base = Utility.Random(24, 17); + Skills.Tactics.Base = Utility.Random(18, 14); + Skills.MagicResist.Base = Utility.Random(15, 6); + Skills.Poisoning.Base = Utility.Random(31, 20); - Fame = Utility.Random(0, 1249); - Karma = Utility.Random(0, -624); + Fame = Utility.Random(0, 1249); + Karma = Utility.Random(0, -624); + } + + public Jwilson(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a jwilson corpse"; + public override string DefaultName => "a jwilson"; + + public override int GetAngerSound() => 0x1C8; + + public override int GetIdleSound() => 0x1C9; + + public override int GetAttackSound() => 0x1CA; + + public override int GetHurtSound() => 0x1CB; + + public override int GetDeathSound() => 0x1CC; + + 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(); + } } - - public Jwilson(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a jwilson corpse"; - public override string DefaultName => "a jwilson"; - - public override int GetAngerSound() => 0x1C8; - - public override int GetIdleSound() => 0x1C9; - - public override int GetAttackSound() => 0x1CA; - - public override int GetHurtSound() => 0x1CB; - - public override int GetDeathSound() => 0x1CC; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Town Critters/(UO 3D Only) Parrot.cs b/Projects/UOContent/Mobiles/Animals/Town Critters/(UO 3D Only) Parrot.cs index a698e6674..71cc1be60 100644 --- a/Projects/UOContent/Mobiles/Animals/Town Critters/(UO 3D Only) Parrot.cs +++ b/Projects/UOContent/Mobiles/Animals/Town Critters/(UO 3D Only) Parrot.cs @@ -1,56 +1,56 @@ namespace Server.Mobiles { - public class Parrot : BaseCreature - { - [Constructible] - public Parrot() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Parrot : BaseCreature { - Body = 831; - VirtualArmor = Utility.Random(0, 6); + [Constructible] + public Parrot() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 831; + VirtualArmor = Utility.Random(0, 6); - InitStats(10, Utility.Random(25, 16), 10); + InitStats(10, Utility.Random(25, 16), 10); - Skills.Wrestling.Base = 6; - Skills.Tactics.Base = 6; - Skills.MagicResist.Base = 5; + Skills.Wrestling.Base = 6; + Skills.Tactics.Base = 6; + Skills.MagicResist.Base = 5; - Fame = Utility.Random(0, 1249); - Karma = Utility.Random(0, -624); + Fame = Utility.Random(0, 1249); + Karma = Utility.Random(0, -624); - Tamable = true; - ControlSlots = 1; - MinTameSkill = 0.0; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 0.0; + } + + public Parrot(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a parrot corpse"; + public override string DefaultName => "a parrot"; + + public override int GetAngerSound() => 0x1B; + + public override int GetIdleSound() => 0x1C; + + public override int GetAttackSound() => 0x1D; + + public override int GetHurtSound() => 0x1E; + + public override int GetDeathSound() => 0x1F; + + 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(); + } } - - public Parrot(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a parrot corpse"; - public override string DefaultName => "a parrot"; - - public override int GetAngerSound() => 0x1B; - - public override int GetIdleSound() => 0x1C; - - public override int GetAttackSound() => 0x1D; - - public override int GetHurtSound() => 0x1E; - - public override int GetDeathSound() => 0x1F; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Town Critters/Bird.cs b/Projects/UOContent/Mobiles/Animals/Town Critters/Bird.cs index 57cd301d6..12e673eac 100644 --- a/Projects/UOContent/Mobiles/Animals/Town Critters/Bird.cs +++ b/Projects/UOContent/Mobiles/Animals/Town Critters/Bird.cs @@ -1,138 +1,138 @@ namespace Server.Mobiles { - public class Bird : BaseCreature - { - [Constructible] - public Bird() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Bird : BaseCreature { - if (Utility.RandomBool()) - { - Hue = 0x901; - - Name = Utility.Random(3) switch + [Constructible] + public Bird() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) { - 0 => "a crow", - 2 => "a raven", - 1 => "a magpie", - _ => Name - }; - } - else - { - Hue = Utility.RandomBirdHue(); - Name = NameList.RandomName("bird"); - } + if (Utility.RandomBool()) + { + Hue = 0x901; - Body = 6; - BaseSoundID = 0x1B; + Name = Utility.Random(3) switch + { + 0 => "a crow", + 2 => "a raven", + 1 => "a magpie", + _ => Name + }; + } + else + { + Hue = Utility.RandomBirdHue(); + Name = NameList.RandomName("bird"); + } - VirtualArmor = Utility.RandomMinMax(0, 6); + Body = 6; + BaseSoundID = 0x1B; - SetStr(10); - SetDex(25, 35); - SetInt(10); + VirtualArmor = Utility.RandomMinMax(0, 6); - SetDamage(0); + SetStr(10); + SetDex(25, 35); + SetInt(10); - SetDamageType(ResistanceType.Physical, 100); + SetDamage(0); - SetSkill(SkillName.Wrestling, 4.2, 6.4); - SetSkill(SkillName.Tactics, 4.0, 6.0); - SetSkill(SkillName.MagicResist, 4.0, 5.0); + SetDamageType(ResistanceType.Physical, 100); - Fame = 150; - Karma = 0; + SetSkill(SkillName.Wrestling, 4.2, 6.4); + SetSkill(SkillName.Tactics, 4.0, 6.0); + SetSkill(SkillName.MagicResist, 4.0, 5.0); - Tamable = true; - ControlSlots = 1; - MinTameSkill = -6.9; + Fame = 150; + Karma = 0; + + Tamable = true; + ControlSlots = 1; + MinTameSkill = -6.9; + } + + public Bird(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a bird corpse"; + + public override MeatType MeatType => MeatType.Bird; + public override int Meat => 1; + public override int Feathers => 25; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + + 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 == 0) + Hue = Utility.RandomBirdHue(); + } } - public Bird(Serial serial) : base(serial) + public class TropicalBird : BaseCreature { + [Constructible] + public TropicalBird() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Hue = Utility.RandomBirdHue(); + + Body = 6; + BaseSoundID = 0xBF; + + VirtualArmor = Utility.RandomMinMax(0, 6); + + SetStr(10); + SetDex(25, 35); + SetInt(10); + + SetDamage(0); + + SetDamageType(ResistanceType.Physical, 100); + + SetSkill(SkillName.Wrestling, 4.2, 6.4); + SetSkill(SkillName.Tactics, 4.0, 6.0); + SetSkill(SkillName.MagicResist, 4.0, 5.0); + + Fame = 150; + Karma = 0; + + Tamable = true; + ControlSlots = 1; + MinTameSkill = -6.9; + } + + public TropicalBird(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a bird corpse"; + public override string DefaultName => "a tropical bird"; + + public override MeatType MeatType => MeatType.Bird; + public override int Meat => 1; + public override int Feathers => 25; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + + 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(); + } } - - public override string CorpseName => "a bird corpse"; - - public override MeatType MeatType => MeatType.Bird; - public override int Meat => 1; - public override int Feathers => 25; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Hue == 0) - Hue = Utility.RandomBirdHue(); - } - } - - public class TropicalBird : BaseCreature - { - [Constructible] - public TropicalBird() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) - { - Hue = Utility.RandomBirdHue(); - - Body = 6; - BaseSoundID = 0xBF; - - VirtualArmor = Utility.RandomMinMax(0, 6); - - SetStr(10); - SetDex(25, 35); - SetInt(10); - - SetDamage(0); - - SetDamageType(ResistanceType.Physical, 100); - - SetSkill(SkillName.Wrestling, 4.2, 6.4); - SetSkill(SkillName.Tactics, 4.0, 6.0); - SetSkill(SkillName.MagicResist, 4.0, 5.0); - - Fame = 150; - Karma = 0; - - Tamable = true; - ControlSlots = 1; - MinTameSkill = -6.9; - } - - public TropicalBird(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a bird corpse"; - public override string DefaultName => "a tropical bird"; - - public override MeatType MeatType => MeatType.Bird; - public override int Meat => 1; - public override int Feathers => 25; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Town Critters/Cat.cs b/Projects/UOContent/Mobiles/Animals/Town Critters/Cat.cs index dc8607339..e27517958 100644 --- a/Projects/UOContent/Mobiles/Animals/Town Critters/Cat.cs +++ b/Projects/UOContent/Mobiles/Animals/Town Critters/Cat.cs @@ -1,65 +1,65 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Housecat")] - public class Cat : BaseCreature - { - [Constructible] - public Cat() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Housecat")] + public class Cat : BaseCreature { - Body = 0xC9; - Hue = Utility.RandomAnimalHue(); - BaseSoundID = 0x69; + [Constructible] + public Cat() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 0xC9; + Hue = Utility.RandomAnimalHue(); + BaseSoundID = 0x69; - SetStr(9); - SetDex(35); - SetInt(5); + SetStr(9); + SetDex(35); + SetInt(5); - SetHits(6); - SetMana(0); + SetHits(6); + SetMana(0); - SetDamage(1); + SetDamage(1); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 5, 10); + SetResistance(ResistanceType.Physical, 5, 10); - SetSkill(SkillName.MagicResist, 5.0); - SetSkill(SkillName.Tactics, 4.0); - SetSkill(SkillName.Wrestling, 5.0); + SetSkill(SkillName.MagicResist, 5.0); + SetSkill(SkillName.Tactics, 4.0); + SetSkill(SkillName.Wrestling, 5.0); - Fame = 0; - Karma = 150; + Fame = 0; + Karma = 150; - VirtualArmor = 8; + VirtualArmor = 8; - Tamable = true; - ControlSlots = 1; - MinTameSkill = -0.9; + Tamable = true; + ControlSlots = 1; + MinTameSkill = -0.9; + } + + public Cat(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a cat corpse"; + public override string DefaultName => "a cat"; + + public override int Meat => 1; + public override FoodType FavoriteFood => FoodType.Meat | FoodType.Fish; + public override PackInstinct PackInstinct => PackInstinct.Feline; + + 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(); + } } - - public Cat(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a cat corpse"; - public override string DefaultName => "a cat"; - - public override int Meat => 1; - public override FoodType FavoriteFood => FoodType.Meat | FoodType.Fish; - public override PackInstinct PackInstinct => PackInstinct.Feline; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Town Critters/Dog.cs b/Projects/UOContent/Mobiles/Animals/Town Critters/Dog.cs index 6f0e21cb8..cd2c4ce10 100644 --- a/Projects/UOContent/Mobiles/Animals/Town Critters/Dog.cs +++ b/Projects/UOContent/Mobiles/Animals/Town Critters/Dog.cs @@ -1,64 +1,64 @@ namespace Server.Mobiles { - public class Dog : BaseCreature - { - [Constructible] - public Dog() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Dog : BaseCreature { - Body = 0xD9; - Hue = Utility.RandomAnimalHue(); - BaseSoundID = 0x85; + [Constructible] + public Dog() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 0xD9; + Hue = Utility.RandomAnimalHue(); + BaseSoundID = 0x85; - SetStr(27, 37); - SetDex(28, 43); - SetInt(29, 37); + SetStr(27, 37); + SetDex(28, 43); + SetInt(29, 37); - SetHits(17, 22); - SetMana(0); + SetHits(17, 22); + SetMana(0); - SetDamage(4, 7); + SetDamage(4, 7); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 10, 15); + SetResistance(ResistanceType.Physical, 10, 15); - SetSkill(SkillName.MagicResist, 22.1, 47.0); - SetSkill(SkillName.Tactics, 19.2, 31.0); - SetSkill(SkillName.Wrestling, 19.2, 31.0); + SetSkill(SkillName.MagicResist, 22.1, 47.0); + SetSkill(SkillName.Tactics, 19.2, 31.0); + SetSkill(SkillName.Wrestling, 19.2, 31.0); - Fame = 0; - Karma = 300; + Fame = 0; + Karma = 300; - VirtualArmor = 12; + VirtualArmor = 12; - Tamable = true; - ControlSlots = 1; - MinTameSkill = -15.3; + Tamable = true; + ControlSlots = 1; + MinTameSkill = -15.3; + } + + public Dog(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a dog corpse"; + public override string DefaultName => "a dog"; + + public override int Meat => 1; + public override FoodType FavoriteFood => FoodType.Meat; + public override PackInstinct PackInstinct => PackInstinct.Canine; + + 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(); + } } - - public Dog(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a dog corpse"; - public override string DefaultName => "a dog"; - - public override int Meat => 1; - public override FoodType FavoriteFood => FoodType.Meat; - public override PackInstinct PackInstinct => PackInstinct.Canine; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Animals/Town Critters/Rat.cs b/Projects/UOContent/Mobiles/Animals/Town Critters/Rat.cs index 20f22ad1b..fad7e803a 100644 --- a/Projects/UOContent/Mobiles/Animals/Town Critters/Rat.cs +++ b/Projects/UOContent/Mobiles/Animals/Town Critters/Rat.cs @@ -1,68 +1,68 @@ namespace Server.Mobiles { - public class Rat : BaseCreature - { - [Constructible] - public Rat() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Rat : BaseCreature { - Body = 238; - BaseSoundID = 0xCC; + [Constructible] + public Rat() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 238; + BaseSoundID = 0xCC; - SetStr(9); - SetDex(35); - SetInt(5); + SetStr(9); + SetDex(35); + SetInt(5); - SetHits(6); - SetMana(0); + SetHits(6); + SetMana(0); - SetDamage(1, 2); + SetDamage(1, 2); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 5, 10); - SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Physical, 5, 10); + SetResistance(ResistanceType.Poison, 5, 10); - SetSkill(SkillName.MagicResist, 4.0); - SetSkill(SkillName.Tactics, 4.0); - SetSkill(SkillName.Wrestling, 4.0); + SetSkill(SkillName.MagicResist, 4.0); + SetSkill(SkillName.Tactics, 4.0); + SetSkill(SkillName.Wrestling, 4.0); - Fame = 150; - Karma = -150; + Fame = 150; + Karma = -150; - VirtualArmor = 6; + VirtualArmor = 6; - Tamable = true; - ControlSlots = 1; - MinTameSkill = -0.9; + Tamable = true; + ControlSlots = 1; + MinTameSkill = -0.9; + } + + public Rat(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a rat corpse"; + public override string DefaultName => "a rat"; + + public override int Meat => 1; + public override FoodType FavoriteFood => FoodType.Meat | FoodType.Fish | FoodType.Eggs | FoodType.GrainsAndHay; + + public override void GenerateLoot() + { + AddLoot(LootPack.Poor); + } + + 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(); + } } - - public Rat(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a rat corpse"; - public override string DefaultName => "a rat"; - - public override int Meat => 1; - public override FoodType FavoriteFood => FoodType.Meat | FoodType.Fish | FoodType.Eggs | FoodType.GrainsAndHay; - - public override void GenerateLoot() - { - AddLoot(LootPack.Poor); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/BaseCreature.cs b/Projects/UOContent/Mobiles/BaseCreature.cs index b966b7aa1..65b2b6e5c 100644 --- a/Projects/UOContent/Mobiles/BaseCreature.cs +++ b/Projects/UOContent/Mobiles/BaseCreature.cs @@ -5,8 +5,6 @@ using System.Threading.Tasks; using Server.ContextMenus; using Server.Engines.ConPVP; using Server.Engines.MLQuests; -using Server.Engines.PartySystem; -using Server.Engines.Quests; using Server.Engines.Quests.Doom; using Server.Engines.Quests.Haven; using Server.Engines.Spawners; @@ -28,4983 +26,5043 @@ using Server.Utilities; namespace Server.Mobiles { - /// - /// Summary description for MobileAI. - /// - public enum FightMode - { - None, // Never focus on others - Aggressor, // Only attack aggressors - Strongest, // Attack the strongest - Weakest, // Attack the weakest - Closest, // Attack the closest - Evil // Only attack aggressor -or- negative karma - } - - public enum OrderType - { - None, // When no order, let's roam - Come, // "(All/Name) come" Summons all or one pet to your location. - Drop, // "(Name) drop" Drops its loot to the ground (if it carries any). - Follow, // "(Name) follow" Follows targeted being. - - // "(All/Name) follow me" Makes all or one pet follow you. - Friend, // "(Name) friend" Allows targeted player to confirm resurrection. - Unfriend, // Remove a friend - Guard, // "(Name) guard" Makes the specified pet guard you. Pets can only guard their owner. - - // "(All/Name) guard me" Makes all or one pet guard you. - Attack, // "(All/Name) kill", - - // "(All/Name) attack" All or the specified pet(s) currently under your control attack the target. - Patrol, // "(Name) patrol" Roves between two or more guarded targets. - Release, // "(Name) release" Releases pet back into the wild (removes "tame" status). - Stay, // "(All/Name) stay" All or the specified pet(s) will stop and stay in current spot. - Stop, // "(All/Name) stop Cancels any current orders to attack, guard or follow. - Transfer // "(Name) transfer" Transfers complete ownership to targeted player. - } - - [Flags] - public enum FoodType - { - None = 0x0000, - Meat = 0x0001, - FruitsAndVegies = 0x0002, - GrainsAndHay = 0x0004, - Fish = 0x0008, - Eggs = 0x0010, - Gold = 0x0020 - } - - [Flags] - public enum PackInstinct - { - None = 0x0000, - Canine = 0x0001, - Ostard = 0x0002, - Feline = 0x0004, - Arachnid = 0x0008, - Daemon = 0x0010, - Bear = 0x0020, - Equine = 0x0040, - Bull = 0x0080 - } - - public enum ScaleType - { - Red, - Yellow, - Black, - Green, - White, - Blue, - All - } - - public enum MeatType - { - Ribs, - Bird, - LambLeg - } - - public enum HideType - { - Regular, - Spined, - Horned, - Barbed - } - - public class DamageStore : IComparable - { - public int m_Damage; - public bool m_HasRight; - public Mobile m_Mobile; - - public DamageStore(Mobile m, int damage) + /// + /// Summary description for MobileAI. + /// + public enum FightMode { - m_Mobile = m; - m_Damage = damage; + None, // Never focus on others + Aggressor, // Only attack aggressors + Strongest, // Attack the strongest + Weakest, // Attack the weakest + Closest, // Attack the closest + Evil // Only attack aggressor -or- negative karma } - public int CompareTo(DamageStore ds) => ds?.m_Damage ?? 0 - m_Damage; - } - - [AttributeUsage(AttributeTargets.Class)] - public class FriendlyNameAttribute : Attribute - { - public FriendlyNameAttribute(TextDefinition friendlyName) => FriendlyName = friendlyName; - // future use: Talisman 'Protection/Bonus vs. Specific Creature - - public TextDefinition FriendlyName { get; } - - public static TextDefinition GetFriendlyNameFor(Type t) + public enum OrderType { - if (t.IsDefined(typeof(FriendlyNameAttribute), false)) - { - object[] objs = t.GetCustomAttributes(typeof(FriendlyNameAttribute), false); + None, // When no order, let's roam + Come, // "(All/Name) come" Summons all or one pet to your location. + Drop, // "(Name) drop" Drops its loot to the ground (if it carries any). + Follow, // "(Name) follow" Follows targeted being. - if (objs.Length > 0) - return (objs[0] as FriendlyNameAttribute)?.FriendlyName ?? ""; - } + // "(All/Name) follow me" Makes all or one pet follow you. + Friend, // "(Name) friend" Allows targeted player to confirm resurrection. + Unfriend, // Remove a friend + Guard, // "(Name) guard" Makes the specified pet guard you. Pets can only guard their owner. - return t.Name; - } - } + // "(All/Name) guard me" Makes all or one pet guard you. + Attack, // "(All/Name) kill", - public class BaseCreature : Mobile, IHonorTarget, IQuestGiver - { - public const int MaxLoyalty = 100; - - public const int MaxOwners = 5; - - public const int DefaultRangePerception = 16; - public const int OldRangePerception = 10; - - private const double ChanceToRummage = 0.5; // 50% - - private const double MinutesToNextRummageMin = 1.0; - private const double MinutesToNextRummageMax = 4.0; - - private const double MinutesToNextChanceMin = 0.25; - private const double MinutesToNextChanceMax = 0.75; - - private static readonly Type[] m_AnimateDeadTypes = - { - typeof(MoundOfMaggots), typeof(HellSteed), typeof(SkeletalMount), - typeof(WailingBanshee), typeof(Wraith), typeof(SkeletalDragon), - typeof(LichLord), typeof(FleshGolem), typeof(Lich), - typeof(SkeletalKnight), typeof(BoneKnight), typeof(Mummy), - typeof(SkeletalMage), typeof(BoneMagi), typeof(PatchworkSkeleton) - }; - - private static readonly double[] m_StandardActiveSpeeds = - { - 0.175, 0.1, 0.15, 0.2, 0.25, 0.3, 0.4, 0.5, 0.6, 0.8 - }; - - private static readonly double[] m_StandardPassiveSpeeds = - { - 0.350, 0.2, 0.4, 0.5, 0.6, 0.8, 1.0, 1.2, 1.6, 2.0 - }; - - private static Mobile m_NoDupeGuards; - - private static readonly bool EnableRummaging = true; - - private DateTime m_IdleReleaseTime; - - private long m_NextRummageTime; - - /* until we are sure about who should be getting deleted, move them instead */ - /* On OSI, they despawn */ - - private bool m_ReturnQueued; - - public BaseCreature(AIType ai, - FightMode mode, - int iRangePerception, - int iRangeFight, - double dActiveSpeed, - double dPassiveSpeed) - { - if (iRangePerception == OldRangePerception) - iRangePerception = DefaultRangePerception; - - m_Loyalty = MaxLoyalty; // Wonderfully Happy - - m_CurrentAI = ai; - m_DefaultAI = ai; - - RangePerception = iRangePerception; - RangeFight = iRangeFight; - - FightMode = mode; - - m_Team = 0; - - SpeedInfo.GetSpeeds(this, ref dActiveSpeed, ref dPassiveSpeed); - - ActiveSpeed = dActiveSpeed; - PassiveSpeed = dPassiveSpeed; - m_CurrentSpeed = dPassiveSpeed; - - Debug = false; - - m_SpellAttack = new List(); - m_SpellDefense = new List(); - - m_Controlled = false; - m_ControlMaster = null; - ControlTarget = null; - m_ControlOrder = OrderType.None; - - m_bTamable = false; - - Owners = new List(); - - NextReacquireTime = Core.TickCount + (int)ReacquireDelay.TotalMilliseconds; - - ChangeAIType(AI); - - InhumanSpeech speechType = SpeechType; - - speechType?.OnConstruct(this); - - if (IsInvulnerable && !Core.AOS) - NameHue = 0x35; - - GenerateLoot(true); + // "(All/Name) attack" All or the specified pet(s) currently under your control attack the target. + Patrol, // "(Name) patrol" Roves between two or more guarded targets. + Release, // "(Name) release" Releases pet back into the wild (removes "tame" status). + Stay, // "(All/Name) stay" All or the specified pet(s) will stop and stay in current spot. + Stop, // "(All/Name) stop Cancels any current orders to attack, guard or follow. + Transfer // "(Name) transfer" Transfers complete ownership to targeted player. } - public BaseCreature(Serial serial) : base(serial) + [Flags] + public enum FoodType { - m_SpellAttack = new List(); - m_SpellDefense = new List(); - - Debug = false; + None = 0x0000, + Meat = 0x0001, + FruitsAndVegies = 0x0002, + GrainsAndHay = 0x0004, + Fish = 0x0008, + Eggs = 0x0010, + Gold = 0x0020 } - public virtual string DefaultName => null; - public virtual string CorpseName => null; - - [CommandProperty(AccessLevel.GameMaster)] - public override string Name + [Flags] + public enum PackInstinct { - get - { - if (NameMod == null && base.Name == null) - return DefaultName; - - return base.Name; - } - set => base.Name = value == DefaultName ? null : value; + None = 0x0000, + Canine = 0x0001, + Ostard = 0x0002, + Feline = 0x0004, + Arachnid = 0x0008, + Daemon = 0x0010, + Bear = 0x0020, + Equine = 0x0040, + Bull = 0x0080 } - public virtual InhumanSpeech SpeechType => null; - - /* Do not serialize this till the code is finalized */ - - [CommandProperty(AccessLevel.GameMaster)] - public bool SeeksHome { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public string CorpseNameOverride { get; set; } - - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public bool IsStabled + public enum ScaleType { - get => m_IsStabled; - set - { - m_IsStabled = value; - if (m_IsStabled) - StopDeleteTimer(); - } + Red, + Yellow, + Black, + Green, + White, + Blue, + All } - [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] - public Mobile StabledBy { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsPrisoner { get; set; } - - protected DateTime SummonEnd { get; set; } - - public virtual Faction FactionAllegiance => null; - public virtual int FactionSilverWorth => 30; - - public virtual double WeaponAbilityChance => 0.4; - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsParagon + public enum MeatType { - get => m_Paragon; - set - { - if (m_Paragon == value) - return; - if (value) - Paragon.Convert(this); - else - Paragon.UnConvert(this); - - m_Paragon = value; - - InvalidateProperties(); - } + Ribs, + Bird, + LambLeg } - public virtual bool HasManaOveride => false; - - public virtual FoodType FavoriteFood => FoodType.Meat; - public virtual PackInstinct PackInstinct => PackInstinct.None; - - public List Owners { get; private set; } - - public virtual bool AllowMaleTamer => true; - public virtual bool AllowFemaleTamer => true; - public virtual bool SubdueBeforeTame => false; - public virtual bool StatLossAfterTame => SubdueBeforeTame; - public virtual bool ReduceSpeedWithDamage => true; - public virtual bool IsSubdued => SubdueBeforeTame && Hits < HitsMax / 10; - - public virtual bool Commandable => true; - - public virtual Poison HitPoison => null; - public virtual double HitPoisonChance => 0.5; - public virtual Poison PoisonImmune => null; - - public virtual bool BardImmune => false; - public virtual bool Unprovokable => BardImmune || IsDeadPet; - public virtual bool Uncalmable => BardImmune || IsDeadPet; - public virtual bool AreaPeaceImmune => BardImmune || IsDeadPet; - - public virtual bool BleedImmune => false; - public virtual double BonusPetDamageScalar => 1.0; - - public virtual bool DeathAdderCharmable => false; - - // TODO: Find the pub 31 tweaks to the DispelDifficulty and apply them of course. - public virtual double DispelDifficulty // at this skill level we dispel 50% chance - => 0.0; - - public virtual double DispelFocus // at difficulty - focus we have 0%, at difficulty + focus we have 100% - => 20.0; - - public virtual bool DisplayWeight => Backpack is StrongBackpack; - - public virtual bool CanFly => false; - - public virtual bool IsInvulnerable => false; - - public BaseAI AIObject { get; private set; } - - public virtual OppositionGroup OppositionGroup => null; - - public virtual bool IsAnimatedDead + public enum HideType { - get - { - if (!Summoned) - return false; - - Type type = GetType(); - - bool contains = false; - - for (int i = 0; !contains && i < m_AnimateDeadTypes.Length; ++i) - contains = type == m_AnimateDeadTypes[i]; - - return contains; - } + Regular, + Spined, + Horned, + Barbed } - public virtual bool IsNecroFamiliar => - Summoned && m_ControlMaster != null && - SummonFamiliarSpell.Table.TryGetValue(m_ControlMaster, out BaseCreature bc) && bc == this; - - public virtual bool DeleteCorpseOnDeath => !Core.AOS && m_bSummoned; - - [CommandProperty(AccessLevel.GameMaster)] - public int Loyalty + public class DamageStore : IComparable { - get => m_Loyalty; - set => m_Loyalty = Math.Clamp(value, 0, MaxLoyalty); - } + public int m_Damage; + public bool m_HasRight; + public Mobile m_Mobile; - [CommandProperty(AccessLevel.GameMaster)] - public WayPoint CurrentWayPoint { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public IPoint2D TargetLocation { get; set; } - - public virtual Mobile ConstantFocus => null; - - public virtual bool DisallowAllMoves => false; - - public virtual bool InitialInnocent => false; - - public virtual bool AlwaysMurderer => false; - - public virtual bool AlwaysAttackable => false; - - [CommandProperty(AccessLevel.GameMaster)] - public virtual int DamageMin - { - get => m_DamageMin; - set => m_DamageMin = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public virtual int DamageMax - { - get => m_DamageMax; - set => m_DamageMax = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public override int HitsMax => HitsMaxSeed <= 0 ? Str : Math.Clamp(HitsMaxSeed + GetStatOffset(StatType.Str), 1, 65000); - - [CommandProperty(AccessLevel.GameMaster)] - public int HitsMaxSeed { get; set; } = -1; - - [CommandProperty(AccessLevel.GameMaster)] - public override int StamMax => StamMaxSeed <= 0 ? Dex : Math.Clamp(StamMaxSeed + GetStatOffset(StatType.Dex), 1, 65000); - - [CommandProperty(AccessLevel.GameMaster)] - public int StamMaxSeed { get; set; } = -1; - - [CommandProperty(AccessLevel.GameMaster)] - public override int ManaMax => ManaMaxSeed <= 0 ? Int : Math.Clamp((ManaMaxSeed + GetStatOffset(StatType.Int)), 1, 65000); - - [CommandProperty(AccessLevel.GameMaster)] - public int ManaMaxSeed { get; set; } = -1; - - public virtual bool CanOpenDoors => !Body.IsAnimal && !Body.IsSea; - - public virtual bool CanMoveOverObstacles => Core.AOS || Body.IsMonster; - - public virtual bool CanDestroyObstacles => false; - - /* - Seems this actually was removed on OSI somewhere between the original bug report and now. - We will call it ML, until we can get better information. I suspect it was on the OSI TC when - originally it taken out of RunUO, and not implemented on OSIs production shards until more - recently. Either way, this is, or was, accurate OSI behavior, and just entirely - removing it was incorrect. OSI followers were distracted by being attacked well into - AoS, at very least. - - */ - - public virtual bool CanBeDistracted => !Core.ML; - - public override bool ShouldCheckStatTimers => false; - - public virtual bool CanAngerOnTame => false; - - protected virtual BaseAI ForcedAI => null; - - [CommandProperty(AccessLevel.GameMaster)] - public AIType AI - { - get => m_CurrentAI; - set - { - m_CurrentAI = value; - - if (m_CurrentAI == AIType.AI_Use_Default) - m_CurrentAI = m_DefaultAI; - - ChangeAIType(m_CurrentAI); - } - } - - [CommandProperty(AccessLevel.Administrator)] - public bool Debug { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Team - { - get => m_Team; - set - { - m_Team = value; - OnTeamChange(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile FocusMob { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public FightMode FightMode { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int RangePerception { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int RangeFight { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int RangeHome { get; set; } = 10; - - [CommandProperty(AccessLevel.GameMaster)] - public double ActiveSpeed { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public double PassiveSpeed { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public double CurrentSpeed - { - get => TargetLocation != null ? 0.3 : m_CurrentSpeed; - set - { - if (m_CurrentSpeed != value) + public DamageStore(Mobile m, int damage) { - m_CurrentSpeed = value; - AIObject?.OnCurrentSpeedChanged(); - } - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D Home - { - get => m_Home; - set => m_Home = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public Map HomeMap { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Controlled - { - get => m_Controlled; - set - { - if (m_Controlled == value) - return; - - m_Controlled = value; - Delta(MobileDelta.Noto); - - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile ControlMaster - { - get => m_ControlMaster; - set - { - if (m_ControlMaster == value || this == value) - return; - - RemoveFollowers(); - m_ControlMaster = value; - AddFollowers(); - if (m_ControlMaster != null) - StopDeleteTimer(); - - Delta(MobileDelta.Noto); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile SummonMaster - { - get => m_SummonMaster; - set - { - if (m_SummonMaster == value || this == value) - return; - - RemoveFollowers(); - m_SummonMaster = value; - AddFollowers(); - - Delta(MobileDelta.Noto); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile ControlTarget { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D ControlDest { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public OrderType ControlOrder - { - get => m_ControlOrder; - set - { - m_ControlOrder = value; - - AIObject?.OnCurrentOrderChanged(); - - InvalidateProperties(); - - m_ControlMaster?.InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool BardProvoked { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool BardPacified { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile BardMaster { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile BardTarget { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime BardEndTime { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public double MinTameSkill { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Tamable - { - get => m_bTamable && !m_Paragon; - set => m_bTamable = value; - } - - [CommandProperty(AccessLevel.Administrator)] - public bool Summoned - { - get => m_bSummoned; - set - { - if (m_bSummoned == value) - return; - - NextReacquireTime = Core.TickCount; - - m_bSummoned = value; - Delta(MobileDelta.Noto); - - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.Administrator)] - public int ControlSlots { get; set; } = 1; - - public virtual bool NoHouseRestrictions => false; - public virtual bool IsHouseSummonable => false; - - public virtual bool AutoDispel => false; - public virtual double AutoDispelChance => Core.SE ? .10 : 1.0; - - public virtual bool IsScaryToPets => false; - public virtual bool IsScaredOfScaryThings => true; - - public virtual bool CanRummageCorpses => false; - - public virtual bool DeleteOnRelease => m_bSummoned; - - public virtual bool CanDrop => IsBonded; - - public virtual int TreasureMapLevel => -1; - - public virtual bool IgnoreYoungProtection => false; - - public bool NoKillAwards { get; set; } - - public virtual bool GivesMLMinorArtifact => false; - - /* To save on cpu usage, RunUO creatures only reacquire creatures under the following circumstances: - * - 10 seconds have elapsed since the last time it tried - * - The creature was attacked - * - Some creatures, like dragons, will reacquire when they see someone move - * - * This functionality appears to be implemented on OSI as well - */ - - public long NextReacquireTime { get; set; } - - public virtual TimeSpan ReacquireDelay => TimeSpan.FromSeconds(10.0); - public virtual bool ReacquireOnMovement => false; - public virtual bool AcquireOnApproach => m_Paragon; - public virtual int AcquireOnApproachRange => 10; - - public static bool Summoning { get; set; } - - public virtual bool CanBreath => HasBreath && !Summoned; - public virtual bool IsDispellable => Summoned && !IsAnimatedDead; - - public virtual bool - PlayerRangeSensitive // If they are following a waypoint, they'll continue to follow it even if players aren't around - => CurrentWayPoint == null; - - public virtual bool ReturnsToHome => - SeeksHome && Home != Point3D.Zero && !m_ReturnQueued && !Controlled && !Summoned; - - // used for deleting untamed creatures [in houses] - - [CommandProperty(AccessLevel.GameMaster)] - public bool RemoveIfUntamed { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int RemoveStep { get; set; } - - public HonorContext ReceivedHonorContext { get; set; } - - public virtual WeaponAbility GetWeaponAbility() => null; - - public virtual bool IsEnemy(Mobile m) - { - if (OppositionGroup?.IsEnemy(this, m) == true) - return true; - - if (m is BaseGuard) - return false; - - if (GetFactionAllegiance(m) == Allegiance.Ally) - return false; - - Ethic ourEthic = EthicAllegiance; - Player pl = Ethics.Player.Find(m, true); - - if (pl?.IsShielded == true && (ourEthic == null || ourEthic == pl.Ethic)) - return false; - - if (m is PlayerMobile mobile && mobile.HonorActive) - return false; - - if (!(m is BaseCreature c) || m is MilitiaFighter) - return true; - - if (TransformationSpellHelper.UnderTransformation(m, typeof(EtherealVoyageSpell))) - return false; - - if ((FightMode == FightMode.Evil && m.Karma < 0) || (c.FightMode == FightMode.Evil && Karma < 0)) - return true; - - return m_Team != c.m_Team || (m_bSummoned || m_Controlled) != (c.m_bSummoned || c.m_Controlled); - } - - public override string ApplyNameSuffix(string suffix) - { - if (IsParagon && !GivesMLMinorArtifact) suffix = suffix.Length == 0 ? "(Paragon)" : $"{suffix} (Paragon)"; - - return base.ApplyNameSuffix(suffix); - } - - public virtual bool CheckControlChance(Mobile m) - { - if (GetControlChance(m) > Utility.RandomDouble()) - { - Loyalty += 1; - return true; - } - - PlaySound(GetAngerSound()); - - if (Body.IsAnimal) - Animate(10, 5, 1, true, false, 0); - else if (Body.IsMonster) - Animate(18, 5, 1, true, false, 0); - - Loyalty -= 3; - return false; - } - - public virtual bool CanBeControlledBy(Mobile m) => GetControlChance(m) > 0.0; - - public virtual double GetControlChance(Mobile m, bool useBaseSkill = false) - { - if (MinTameSkill <= 29.1 || m_bSummoned || m.AccessLevel >= AccessLevel.GameMaster) - return 1.0; - - double dMinTameSkill = MinTameSkill; - - if (dMinTameSkill > -24.9 && AnimalTaming.CheckMastery(m, this)) - dMinTameSkill = -24.9; - - int taming = - (int)((useBaseSkill ? m.Skills.AnimalTaming.Base : m.Skills.AnimalTaming.Value) * 10); - int lore = - (int)((useBaseSkill ? m.Skills.AnimalLore.Base : m.Skills.AnimalLore.Value) * 10); - int bonus, chance = 700; - - if (Core.ML) - { - int SkillBonus = taming - (int)(dMinTameSkill * 10); - int LoreBonus = lore - (int)(dMinTameSkill * 10); - - int SkillMod = 6; - int LoreMod = 6; - - if (SkillBonus < 0) - SkillMod = 28; - - if (LoreBonus < 0) - LoreMod = 14; - - SkillBonus *= SkillMod; - LoreBonus *= LoreMod; - - bonus = (SkillBonus + LoreBonus) / 2; - } - else - { - int difficulty = (int)(dMinTameSkill * 10); - int weighted = (taming * 4 + lore) / 5; - bonus = weighted - difficulty; - - if (bonus <= 0) - bonus *= 14; - else - bonus *= 6; - } - - chance += bonus; - - if (chance >= 0 && chance < 200) - chance = 200; - else if (chance > 990) - chance = 990; - - chance -= (MaxLoyalty - m_Loyalty) * 10; - - return (double)chance / 1000; - } - - public override void Damage(int amount, Mobile from) - { - int oldHits = Hits; - - if (Core.AOS && !Summoned && Controlled && Utility.RandomDouble() < 0.2) - amount = (int)(amount * BonusPetDamageScalar); - - if (EvilOmenSpell.TryEndEffect(this)) - amount = (int)(amount * 1.25); - - Mobile oath = BloodOathSpell.GetBloodOath(from); - - if (oath == this) - { - amount = (int)(amount * 1.1); - from.Damage(amount, from); - } - - base.Damage(amount, from); - - if (SubdueBeforeTame && !Controlled && oldHits > HitsMax / 10 && Hits <= HitsMax / 10) - PublicOverheadMessage(MessageType.Regular, 0x3B2, false, - "* The creature has been beaten into subjugation! *"); - } - - public override void SetLocation(Point3D newLocation, bool isTeleport) - { - base.SetLocation(newLocation, isTeleport); - - if (isTeleport) - AIObject?.OnTeleported(); - } - - public override void OnBeforeSpawn(Point3D location, Map m) - { - if (Paragon.CheckConvert(this, location, m)) - IsParagon = true; - - base.OnBeforeSpawn(location, m); - } - - public override ApplyPoisonResult ApplyPoison(Mobile from, Poison poison) - { - if (!Alive || IsDeadPet) - return ApplyPoisonResult.Immune; - - if (EvilOmenSpell.TryEndEffect(this)) - poison = PoisonImpl.IncreaseLevel(poison); - - ApplyPoisonResult result = base.ApplyPoison(from, poison); - - if (from != null && result == ApplyPoisonResult.Poisoned && PoisonTimer is PoisonImpl.PoisonTimer timer) - timer.From = from; - - return result; - } - - public override bool CheckPoisonImmunity(Mobile from, Poison poison) => - base.CheckPoisonImmunity(from, poison) || - (m_Paragon ? PoisonImpl.IncreaseLevel(PoisonImmune) : PoisonImmune)?.Level >= poison.Level; - - public void Unpacify() - { - BardEndTime = DateTime.UtcNow; - BardPacified = false; - } - - public virtual void CheckDistracted(Mobile from) - { - if (Utility.RandomDouble() < .10) - { - ControlTarget = from; - ControlOrder = OrderType.Attack; - Combatant = from; - Warmode = true; - } - } - - public override void OnDamage(int amount, Mobile from, bool willKill) - { - if (BardPacified && (HitsMax - Hits) * 0.001 > Utility.RandomDouble()) - Unpacify(); - - int disruptThreshold; - // NPCs can use bandages too! - if (!Core.AOS) - disruptThreshold = 0; - else if (from?.Player == true) - disruptThreshold = 18; - else - disruptThreshold = 25; - - if (amount > disruptThreshold) - { - BandageContext c = BandageContext.GetContext(this); - - c?.Slip(); - } - - if (Confidence.IsRegenerating(this)) - Confidence.StopRegenerating(this); - - WeightOverloading.FatigueOnDamage(this, amount); - - InhumanSpeech speechType = SpeechType; - - if (speechType != null && !willKill) - speechType.OnDamage(this, amount); - - ReceivedHonorContext?.OnTargetDamaged(from, amount); - - if (!willKill) - { - if (CanBeDistracted && ControlOrder == OrderType.Follow) CheckDistracted(from); - } - else if (from is PlayerMobile mobile) - { - Timer.DelayCall(TimeSpan.FromSeconds(10), mobile.RecoverAmmo); - } - - base.OnDamage(amount, from, willKill); - } - - public virtual void OnDamagedBySpell(Mobile from) - { - if (CanBeDistracted && ControlOrder == OrderType.Follow) CheckDistracted(from); - } - - public virtual void OnHarmfulSpell(Mobile from) - { - } - - public virtual void CheckReflect(Mobile caster, ref bool reflect) - { - } - - public virtual void OnCarve(Mobile from, Corpse corpse, Item with) - { - int feathers = Feathers; - int wool = Wool; - int meat = Meat; - int hides = Hides; - int scales = Scales; - - if ((feathers == 0 && wool == 0 && meat == 0 && hides == 0 && scales == 0) || Summoned || IsBonded || - corpse.Animated) - { - if (corpse.Animated) - corpse.SendLocalizedMessageTo(from, 500464); // Use this on corpses to carve away meat and hide - else - from.SendLocalizedMessage(500485); // You see nothing useful to carve from the corpse. - } - else - { - if (Core.ML && from.Race == Race.Human) - hides = (int)Math.Ceiling(hides * 1.1); // 10% bonus only applies to hides, ore & logs - - if (corpse.Map == Map.Felucca) - { - feathers *= 2; - wool *= 2; - hides *= 2; - - if (Core.ML) - { - meat *= 2; - scales *= 2; - } + m_Mobile = m; + m_Damage = damage; } - new Blood(0x122D).MoveToWorld(corpse.Location, corpse.Map); + public int CompareTo(DamageStore ds) => ds?.m_Damage ?? 0 - m_Damage; + } - if (feathers != 0) + [AttributeUsage(AttributeTargets.Class)] + public class FriendlyNameAttribute : Attribute + { + public FriendlyNameAttribute(TextDefinition friendlyName) => FriendlyName = friendlyName; + // future use: Talisman 'Protection/Bonus vs. Specific Creature + + public TextDefinition FriendlyName { get; } + + public static TextDefinition GetFriendlyNameFor(Type t) { - corpse.AddCarvedItem(new Feather(feathers), from); - from.SendLocalizedMessage(500479); // You pluck the bird. The feathers are now on the corpse. - } - - if (wool != 0) - { - corpse.AddCarvedItem(new TaintedWool(wool), from); - from.SendLocalizedMessage(500483); // You shear it, and the wool is now on the corpse. - } - - if (meat != 0) - { - if (MeatType == MeatType.Ribs) - corpse.AddCarvedItem(new RawRibs(meat), from); - else if (MeatType == MeatType.Bird) - corpse.AddCarvedItem(new RawBird(meat), from); - else if (MeatType == MeatType.LambLeg) - corpse.AddCarvedItem(new RawLambLeg(meat), from); - - from.SendLocalizedMessage(500467); // You carve some meat, which remains on the corpse. - } - - if (hides != 0) - { - Item holding = from.Weapon as Item; - - if (Core.AOS && holding is SkinningKnife) - { - var leather = HideType switch + if (t.IsDefined(typeof(FriendlyNameAttribute), false)) { - HideType.Regular => (Item)new Leather(hides), - HideType.Spined => new SpinedLeather(hides), - HideType.Horned => new HornedLeather(hides), - HideType.Barbed => new BarbedLeather(hides), - _ => null - }; + var objs = t.GetCustomAttributes(typeof(FriendlyNameAttribute), false); - if (leather != null) - { - if (!from.PlaceInBackpack(leather)) - { - corpse.DropItem(leather); - from.SendLocalizedMessage(500471); // You skin it, and the hides are now in the corpse. - } - else - { - from.SendLocalizedMessage( - 1073555); // You skin it and place the cut-up hides in your backpack. - } + if (objs.Length > 0) + return (objs[0] as FriendlyNameAttribute)?.FriendlyName ?? ""; } - } - else - { - if (HideType == HideType.Regular) - corpse.DropItem(new Hides(hides)); - else if (HideType == HideType.Spined) - corpse.DropItem(new SpinedHides(hides)); - else if (HideType == HideType.Horned) - corpse.DropItem(new HornedHides(hides)); - else if (HideType == HideType.Barbed) - corpse.DropItem(new BarbedHides(hides)); - from.SendLocalizedMessage(500471); // You skin it, and the hides are now in the corpse. - } + return t.Name; + } + } + + public class BaseCreature : Mobile, IHonorTarget, IQuestGiver + { + public enum Allegiance + { + None, + Ally, + Enemy } - if (scales != 0) + public enum TeachResult { - ScaleType sc = ScaleType; - - switch (sc) - { - case ScaleType.Red: - corpse.AddCarvedItem(new RedScales(scales), from); - break; - case ScaleType.Yellow: - corpse.AddCarvedItem(new YellowScales(scales), from); - break; - case ScaleType.Black: - corpse.AddCarvedItem(new BlackScales(scales), from); - break; - case ScaleType.Green: - corpse.AddCarvedItem(new GreenScales(scales), from); - break; - case ScaleType.White: - corpse.AddCarvedItem(new WhiteScales(scales), from); - break; - case ScaleType.Blue: - corpse.AddCarvedItem(new BlueScales(scales), from); - break; - case ScaleType.All: - { - corpse.AddCarvedItem(new RedScales(scales), from); - corpse.AddCarvedItem(new YellowScales(scales), from); - corpse.AddCarvedItem(new BlackScales(scales), from); - corpse.AddCarvedItem(new GreenScales(scales), from); - corpse.AddCarvedItem(new WhiteScales(scales), from); - corpse.AddCarvedItem(new BlueScales(scales), from); - break; - } - } - - from.SendMessage("You cut away some scales, but they remain on the corpse."); + Success, + Failure, + KnowsMoreThanMe, + KnowsWhatIKnow, + SkillNotRaisable, + NotEnoughFreePoints } - corpse.Carved = true; + public const int MaxLoyalty = 100; - if (corpse.IsCriminalAction(from)) - from.CriminalAction(true); - } - } + public const int MaxOwners = 5; - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public const int DefaultRangePerception = 16; + public const int OldRangePerception = 10; - writer.Write(19); // version + private const double ChanceToRummage = 0.5; // 50% - writer.Write((int)m_CurrentAI); - writer.Write((int)m_DefaultAI); + private const double MinutesToNextRummageMin = 1.0; + private const double MinutesToNextRummageMax = 4.0; - writer.Write(RangePerception); - writer.Write(RangeFight); + private const double MinutesToNextChanceMin = 0.25; + private const double MinutesToNextChanceMax = 0.75; - writer.Write(m_Team); + public const int ShoutRange = 8; - writer.Write(ActiveSpeed); - writer.Write(PassiveSpeed); - writer.Write(m_CurrentSpeed); - - writer.Write(m_Home.X); - writer.Write(m_Home.Y); - writer.Write(m_Home.Z); - - // Version 1 - writer.Write(RangeHome); - - int i = 0; - - writer.Write(m_SpellAttack.Count); - for (i = 0; i < m_SpellAttack.Count; i++) writer.Write(m_SpellAttack[i].ToString()); - - writer.Write(m_SpellDefense.Count); - for (i = 0; i < m_SpellDefense.Count; i++) writer.Write(m_SpellDefense[i].ToString()); - - // Version 2 - writer.Write((int)FightMode); - - writer.Write(m_Controlled); - writer.Write(m_ControlMaster); - writer.Write(ControlTarget); - writer.Write(ControlDest); - writer.Write((int)m_ControlOrder); - writer.Write(MinTameSkill); - // Removed in version 9 - // writer.Write( (double) m_dMaxTameSkill ); - writer.Write(m_bTamable); - writer.Write(m_bSummoned); - - if (m_bSummoned) - writer.WriteDeltaTime(SummonEnd); - - writer.Write(ControlSlots); - - // Version 3 - writer.Write(m_Loyalty); - - // Version 4 - writer.Write(CurrentWayPoint); - - // Verison 5 - writer.Write(m_SummonMaster); - - // Version 6 - writer.Write(HitsMaxSeed); - writer.Write(StamMaxSeed); - writer.Write(ManaMaxSeed); - writer.Write(m_DamageMin); - writer.Write(m_DamageMax); - - // Version 7 - writer.Write(m_PhysicalResistance); - writer.Write(PhysicalDamage); - - writer.Write(m_FireResistance); - writer.Write(FireDamage); - - writer.Write(m_ColdResistance); - writer.Write(ColdDamage); - - writer.Write(m_PoisonResistance); - writer.Write(PoisonDamage); - - writer.Write(m_EnergyResistance); - writer.Write(EnergyDamage); - - // Version 8 - writer.Write(Owners, true); - - // Version 10 - writer.Write(IsDeadPet); - writer.Write(m_IsBonded); - writer.Write(BondingBegin); - writer.Write(OwnerAbandonTime); - - // Version 11 - writer.Write(m_HasGeneratedLoot); - - // Version 12 - writer.Write(m_Paragon); - - // Version 13 - writer.Write(Friends?.Count > 0); - - if (Friends?.Count > 0) - writer.Write(Friends, true); - - // Version 14 - writer.Write(RemoveIfUntamed); - writer.Write(RemoveStep); - - // Version 17 - if (IsStabled || (Controlled && ControlMaster != null)) - writer.Write(TimeSpan.Zero); - else - writer.Write(DeleteTimeLeft); - - // Version 18 - writer.Write(CorpseNameOverride); - - // Version 19 - writer.Write(HomeMap); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_CurrentAI = (AIType)reader.ReadInt(); - m_DefaultAI = (AIType)reader.ReadInt(); - - RangePerception = reader.ReadInt(); - RangeFight = reader.ReadInt(); - - m_Team = reader.ReadInt(); - - ActiveSpeed = reader.ReadDouble(); - PassiveSpeed = reader.ReadDouble(); - m_CurrentSpeed = reader.ReadDouble(); - - if (RangePerception == OldRangePerception) - RangePerception = DefaultRangePerception; - - m_Home.X = reader.ReadInt(); - m_Home.Y = reader.ReadInt(); - m_Home.Z = reader.ReadInt(); - - if (version >= 1) - { - RangeHome = reader.ReadInt(); - - int iCount = reader.ReadInt(); - for (int i = 0; i < iCount; i++) + private static readonly Type[] m_AnimateDeadTypes = { - string str = reader.ReadString(); - Type type = Type.GetType(str); + typeof(MoundOfMaggots), typeof(HellSteed), typeof(SkeletalMount), + typeof(WailingBanshee), typeof(Wraith), typeof(SkeletalDragon), + typeof(LichLord), typeof(FleshGolem), typeof(Lich), + typeof(SkeletalKnight), typeof(BoneKnight), typeof(Mummy), + typeof(SkeletalMage), typeof(BoneMagi), typeof(PatchworkSkeleton) + }; - if (type != null) m_SpellAttack.Add(type); + private static readonly double[] m_StandardActiveSpeeds = + { + 0.175, 0.1, 0.15, 0.2, 0.25, 0.3, 0.4, 0.5, 0.6, 0.8 + }; + + private static readonly double[] m_StandardPassiveSpeeds = + { + 0.350, 0.2, 0.4, 0.5, 0.6, 0.8, 1.0, 1.2, 1.6, 2.0 + }; + + private static Mobile m_NoDupeGuards; + + private static readonly bool EnableRummaging = true; + public static readonly TimeSpan ShoutDelay = TimeSpan.FromMinutes(1); + + private static readonly Type[] m_Eggs = + { + typeof(FriedEggs), typeof(Eggs) + }; + + private static readonly Type[] m_Fish = + { + typeof(FishSteak), typeof(RawFishSteak) + }; + + private static readonly Type[] m_GrainsAndHay = + { + typeof(BreadLoaf), typeof(FrenchBread), typeof(SheafOfHay) + }; + + private static readonly Type[] m_Meat = + { + /* Cooked */ + typeof(Bacon), typeof(CookedBird), typeof(Sausage), + typeof(Ham), typeof(Ribs), typeof(LambLeg), + typeof(ChickenLeg), + + /* Uncooked */ + typeof(RawBird), typeof(RawRibs), typeof(RawLambLeg), + typeof(RawChickenLeg), + + /* Body Parts */ + typeof(Head), typeof(LeftArm), typeof(LeftLeg), + typeof(Torso), typeof(RightArm), typeof(RightLeg) + }; + + private static readonly Type[] m_FruitsAndVegies = + { + typeof(HoneydewMelon), typeof(YellowGourd), typeof(GreenGourd), + typeof(Banana), typeof(Bananas), typeof(Lemon), typeof(Lime), + typeof(Dates), typeof(Grapes), typeof(Peach), typeof(Pear), + typeof(Apple), typeof(Watermelon), typeof(Squash), + typeof(Cantaloupe), typeof(Carrot), typeof(Cabbage), + typeof(Onion), typeof(Lettuce), typeof(Pumpkin) + }; + + private static readonly Type[] m_Gold = + { + // white wyrms eat gold.. + typeof(Gold) + }; + + private readonly List m_SpellAttack; // List of attack spell/power + private readonly List m_SpellDefense; // List of defensive spell/power + + private bool m_bSummoned; + + private bool m_bTamable; + private int m_ColdResistance; + + private bool m_Controlled; // Is controlled + private Mobile m_ControlMaster; // My master + private OrderType m_ControlOrder; // My order + + private AIType m_CurrentAI; // The current AI + + private double m_CurrentSpeed; // The current speed, lets say it could be changed by something; + private int m_DamageMax = -1; + + private int m_DamageMin = -1; + private AIType m_DefaultAI; // The default AI + + private DeleteTimer m_DeleteTimer; + private int m_EnergyResistance; + + private int m_FailedReturnHome; /* return to home failure counter */ + private int m_FireResistance; + + private bool m_HasGeneratedLoot; // have we generated our loot yet? + private Timer m_HealTimer; + + private Point3D m_Home; // The home position of the creature, used by some AI + + private DateTime m_IdleReleaseTime; + + private bool m_IsBonded; + + private bool m_IsStabled; + protected int m_KillersLuck; + + private int m_Loyalty; + + private DateTime m_MLNextShout; + + private List m_MLQuests; + + private long m_NextAura; + + private long m_NextBreathTime; + private long m_NextHealOwnerTime = Core.TickCount; + + private long m_NextHealTime = Core.TickCount; + + private long m_NextRummageTime; + + private bool m_Paragon; + + private int m_PhysicalResistance; + private int m_PoisonResistance; + + /* until we are sure about who should be getting deleted, move them instead */ + /* On OSI, they despawn */ + + private bool m_ReturnQueued; + + protected bool m_Spawning; + + private Mobile m_SummonMaster; + + private SkillName m_Teaching = (SkillName)(-1); + + private int m_Team; // Monster Team + + public BaseCreature( + AIType ai, + FightMode mode, + int iRangePerception, + int iRangeFight, + double dActiveSpeed, + double dPassiveSpeed + ) + { + if (iRangePerception == OldRangePerception) + iRangePerception = DefaultRangePerception; + + m_Loyalty = MaxLoyalty; // Wonderfully Happy + + m_CurrentAI = ai; + m_DefaultAI = ai; + + RangePerception = iRangePerception; + RangeFight = iRangeFight; + + FightMode = mode; + + m_Team = 0; + + SpeedInfo.GetSpeeds(this, ref dActiveSpeed, ref dPassiveSpeed); + + ActiveSpeed = dActiveSpeed; + PassiveSpeed = dPassiveSpeed; + m_CurrentSpeed = dPassiveSpeed; + + Debug = false; + + m_SpellAttack = new List(); + m_SpellDefense = new List(); + + m_Controlled = false; + m_ControlMaster = null; + ControlTarget = null; + m_ControlOrder = OrderType.None; + + m_bTamable = false; + + Owners = new List(); + + NextReacquireTime = Core.TickCount + (int)ReacquireDelay.TotalMilliseconds; + + ChangeAIType(AI); + + var speechType = SpeechType; + + speechType?.OnConstruct(this); + + if (IsInvulnerable && !Core.AOS) + NameHue = 0x35; + + GenerateLoot(true); } - iCount = reader.ReadInt(); - for (int i = 0; i < iCount; i++) + public BaseCreature(Serial serial) : base(serial) { - string str = reader.ReadString(); - Type type = Type.GetType(str); + m_SpellAttack = new List(); + m_SpellDefense = new List(); - if (type != null) m_SpellDefense.Add(type); - } - } - else - { - RangeHome = 0; - } - - if (version >= 2) - { - FightMode = (FightMode)reader.ReadInt(); - - m_Controlled = reader.ReadBool(); - m_ControlMaster = reader.ReadMobile(); - ControlTarget = reader.ReadMobile(); - ControlDest = reader.ReadPoint3D(); - m_ControlOrder = (OrderType)reader.ReadInt(); - - MinTameSkill = reader.ReadDouble(); - - if (version < 9) - reader.ReadDouble(); - - m_bTamable = reader.ReadBool(); - m_bSummoned = reader.ReadBool(); - - if (m_bSummoned) - { - SummonEnd = reader.ReadDeltaTime(); - new UnsummonTimer(m_ControlMaster, this, SummonEnd - DateTime.UtcNow).Start(); + Debug = false; } - ControlSlots = reader.ReadInt(); - } - else - { - FightMode = FightMode.Closest; + public virtual string DefaultName => null; + public virtual string CorpseName => null; - m_Controlled = false; - m_ControlMaster = null; - ControlTarget = null; - m_ControlOrder = OrderType.None; - } - - if (version >= 3) - m_Loyalty = reader.ReadInt(); - else - m_Loyalty = MaxLoyalty; // Wonderfully Happy - - if (version >= 4) - CurrentWayPoint = reader.ReadItem() as WayPoint; - - if (version >= 5) - m_SummonMaster = reader.ReadMobile(); - - if (version >= 6) - { - HitsMaxSeed = reader.ReadInt(); - StamMaxSeed = reader.ReadInt(); - ManaMaxSeed = reader.ReadInt(); - m_DamageMin = reader.ReadInt(); - m_DamageMax = reader.ReadInt(); - } - - if (version >= 7) - { - m_PhysicalResistance = reader.ReadInt(); - PhysicalDamage = reader.ReadInt(); - - m_FireResistance = reader.ReadInt(); - FireDamage = reader.ReadInt(); - - m_ColdResistance = reader.ReadInt(); - ColdDamage = reader.ReadInt(); - - m_PoisonResistance = reader.ReadInt(); - PoisonDamage = reader.ReadInt(); - - m_EnergyResistance = reader.ReadInt(); - EnergyDamage = reader.ReadInt(); - } - - if (version >= 8) - Owners = reader.ReadStrongMobileList(); - else - Owners = new List(); - - if (version >= 10) - { - IsDeadPet = reader.ReadBool(); - m_IsBonded = reader.ReadBool(); - BondingBegin = reader.ReadDateTime(); - OwnerAbandonTime = reader.ReadDateTime(); - } - - if (version >= 11) - m_HasGeneratedLoot = reader.ReadBool(); - else - m_HasGeneratedLoot = true; - - if (version >= 12) - m_Paragon = reader.ReadBool(); - else - m_Paragon = false; - - if (version >= 13 && reader.ReadBool()) - Friends = reader.ReadStrongMobileList(); - else if (version < 13 && m_ControlOrder >= OrderType.Unfriend) - ++m_ControlOrder; - - if (version < 16 && Loyalty != MaxLoyalty) - Loyalty *= 10; - - double activeSpeed = ActiveSpeed; - double passiveSpeed = PassiveSpeed; - - SpeedInfo.GetSpeeds(this, ref activeSpeed, ref passiveSpeed); - - bool isStandardActive = false; - for (int i = 0; !isStandardActive && i < m_StandardActiveSpeeds.Length; ++i) - isStandardActive = ActiveSpeed == m_StandardActiveSpeeds[i]; - - bool isStandardPassive = false; - for (int i = 0; !isStandardPassive && i < m_StandardPassiveSpeeds.Length; ++i) - isStandardPassive = PassiveSpeed == m_StandardPassiveSpeeds[i]; - - if (isStandardActive && m_CurrentSpeed == ActiveSpeed) - m_CurrentSpeed = activeSpeed; - else if (isStandardPassive && m_CurrentSpeed == PassiveSpeed) - m_CurrentSpeed = passiveSpeed; - - if (isStandardActive && !m_Paragon) - ActiveSpeed = activeSpeed; - - if (isStandardPassive && !m_Paragon) - PassiveSpeed = passiveSpeed; - - if (version >= 14) - { - RemoveIfUntamed = reader.ReadBool(); - RemoveStep = reader.ReadInt(); - } - - TimeSpan deleteTime = TimeSpan.Zero; - - if (version >= 17) - deleteTime = reader.ReadTimeSpan(); - - if (deleteTime > TimeSpan.Zero || (LastOwner != null && !Controlled && !IsStabled)) - { - if (deleteTime == TimeSpan.Zero) - deleteTime = TimeSpan.FromDays(3.0); - - m_DeleteTimer = new DeleteTimer(this, deleteTime); - m_DeleteTimer.Start(); - } - - if (version >= 18) - CorpseNameOverride = reader.ReadString(); - - if (version >= 19) - HomeMap = reader.ReadMap(); - - if (version <= 14 && m_Paragon && Hue == 0x31) Hue = Paragon.Hue; // Paragon hue fixed, should now be 0x501. - - if (Core.AOS && NameHue == 0x35) - NameHue = -1; - - CheckStatTimers(); - - ChangeAIType(m_CurrentAI); - - AddFollowers(); - - if (IsAnimatedDead) - AnimateDeadSpell.Register(m_SummonMaster, this); - } - - public virtual bool IsHumanInTown() => Body.IsHuman && Region.IsPartOf(); - - public virtual bool CheckGold(Mobile from, Item dropped) => dropped is Gold gold && OnGoldGiven(from, gold); - - public virtual bool OnGoldGiven(Mobile from, Gold dropped) - { - if (CheckTeachingMatch(from)) - { - if (Teach(m_Teaching, from, dropped.Amount, true)) + [CommandProperty(AccessLevel.GameMaster)] + public override string Name { - dropped.Delete(); - return true; - } - } - else if (IsHumanInTown()) - { - Direction = GetDirectionTo(from); - - int oldSpeechHue = SpeechHue; - - SpeechHue = 0x23F; - SayTo(from, "Thou art giving me gold?"); - - SayTo(from, dropped.Amount >= 400 ? "'Tis a noble gift." : "Money is always welcome."); - - SpeechHue = 0x3B2; - SayTo(from, 501548); // I thank thee. - - SpeechHue = oldSpeechHue; - - dropped.Delete(); - return true; - } - - return false; - } - - public virtual bool OverrideBondingReqs() => false; - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (CheckFeed(from, dropped)) - return true; - if (CheckGold(from, dropped)) - return true; - - // Note: Yes, this happens for all questers (regardless of type, e.g. escorts), - // even if they can't offer you anything at the moment - if (MLQuestSystem.Enabled && CanGiveMLQuest && from is PlayerMobile mobile) - { - MLQuestSystem.Tell(this, mobile, - 1074893); // You need to mark your quest items so I don't take the wrong object. Then speak to me. - return false; - } - - return base.OnDragDrop(from, dropped); - } - - public void ChangeAIType(AIType newAI) - { - AIObject?.m_Timer.Stop(); - - if (ForcedAI != null) - { - AIObject = ForcedAI; - return; - } - - AIObject = newAI switch - { - AIType.AI_Melee => (BaseAI)new MeleeAI(this), - AIType.AI_Animal => new AnimalAI(this), - AIType.AI_Berserk => new BerserkAI(this), - AIType.AI_Archer => new ArcherAI(this), - AIType.AI_Healer => new HealerAI(this), - AIType.AI_Vendor => new VendorAI(this), - AIType.AI_Mage => new MageAI(this), - AIType.AI_Predator => - // m_AI = new PredatorAI(this); - new MeleeAI(this), - AIType.AI_Thief => new ThiefAI(this), - _ => null - }; - } - - public virtual void OnTeamChange() - { - } - - public override void RevealingAction() - { - InvisibilitySpell.RemoveTimer(this); - - base.RevealingAction(); - } - - public void RemoveFollowers() - { - if (m_ControlMaster != null) - { - m_ControlMaster.Followers -= ControlSlots; - if (m_ControlMaster is PlayerMobile mobile) - { - mobile.AllFollowers.Remove(this); - if (mobile.AutoStabled.Contains(this)) - mobile.AutoStabled.Remove(this); - } - } - else if (m_SummonMaster != null) - { - m_SummonMaster.Followers -= ControlSlots; - (m_SummonMaster as PlayerMobile)?.AllFollowers.Remove(this); - } - - if (m_ControlMaster?.Followers < 0) - m_ControlMaster.Followers = 0; - - if (m_SummonMaster?.Followers < 0) - m_SummonMaster.Followers = 0; - } - - public void AddFollowers() - { - if (m_ControlMaster != null) - { - m_ControlMaster.Followers += ControlSlots; - if (m_ControlMaster is PlayerMobile mobile) - mobile.AllFollowers.Add(this); - } - else if (m_SummonMaster != null) - { - m_SummonMaster.Followers += ControlSlots; - if (m_SummonMaster is PlayerMobile mobile) - mobile.AllFollowers.Add(this); - } - } - - public virtual void OnGotMeleeAttack(Mobile attacker) - { - if (AutoDispel && attacker is BaseCreature creature && creature.IsDispellable && - AutoDispelChance > Utility.RandomDouble()) - Dispel(creature); - } - - public virtual void Dispel(Mobile m) - { - Effects.SendLocationParticles(EffectItem.Create(m.Location, m.Map, EffectItem.DefaultDuration), 0x3728, 8, 20, - 5042); - Effects.PlaySound(m, m.Map, 0x201); - - m.Delete(); - } - - public virtual void OnGaveMeleeAttack(Mobile defender) - { - Poison p = m_Paragon ? PoisonImpl.IncreaseLevel(HitPoison) : HitPoison; - - if (p != null && HitPoisonChance >= Utility.RandomDouble()) - { - defender.ApplyPoison(this, p); - - if (Controlled) - CheckSkill(SkillName.Poisoning, 0, Skills.Poisoning.Cap); - } - - if (AutoDispel && defender is BaseCreature creature && creature.IsDispellable && - AutoDispelChance > Utility.RandomDouble()) - Dispel(creature); - } - - public override void OnAfterDelete() - { - if (AIObject != null) - { - AIObject.m_Timer?.Stop(); - AIObject = null; - } - - if (m_DeleteTimer != null) - { - m_DeleteTimer.Stop(); - m_DeleteTimer = null; - } - - FocusMob = null; - - if (IsAnimatedDead) - AnimateDeadSpell.Unregister(m_SummonMaster, this); - - if (MLQuestSystem.Enabled) - MLQuestSystem.HandleDeletion(this); - - base.OnAfterDelete(); - } - - public void DebugSay(string text) - { - if (Debug) - PublicOverheadMessage(MessageType.Regular, 41, false, text); - } - - public void DebugSay(string format, params object[] args) - { - if (Debug) - PublicOverheadMessage(MessageType.Regular, 41, false, string.Format(format, args)); - } - - /* - * This function can be overridden.. so a "Strongest" mobile, can have a different definition depending - * on who check for value - * -Could add a FightMode.Preferred - * - */ - - public virtual double GetFightModeRanking(Mobile m, FightMode acqType, bool bPlayerOnly) - { - if (bPlayerOnly && !m.Player) - return double.MinValue; - - return acqType switch - { - FightMode.Strongest => m.Skills.Tactics.Value + m.Str, // returns strongest mobile - FightMode.Weakest => -m.Hits, // returns weakest mobile - _ => -GetDistanceToSqrt(m) - }; - } - - // Turn, - for left, + for right - // Basic for now, needs work - public virtual void Turn(int iTurnSteps) - { - int v = (int)Direction; - - Direction = (Direction)((v & 0x7) + iTurnSteps & 0x7 | v & 0x80); - } - - public virtual void TurnInternal(int iTurnSteps) - { - int v = (int)Direction; - - SetDirection((Direction)((v & 0x7) + iTurnSteps & 0x7 | v & 0x80)); - } - - public bool IsHurt() => Hits != HitsMax; - - public double GetHomeDistance() => GetDistanceToSqrt(m_Home); - - public virtual int GetTeamSize(int iRange) - { - int iCount = 0; - - foreach (Mobile m in GetMobilesInRange(iRange)) - if (m != this && m is BaseCreature creature && !creature.Deleted && creature.Team == Team && - CanSee(creature)) - iCount++; - - return iCount; - } - - public override void AggressiveAction(Mobile aggressor, bool criminal) - { - base.AggressiveAction(aggressor, criminal); - - if (ControlMaster != null && NotorietyHandlers.CheckAggressor(ControlMaster.Aggressors, aggressor)) - aggressor.Aggressors.Add(AggressorInfo.Create(this, aggressor, true)); - - OrderType ct = m_ControlOrder; - - if (AIObject != null) - { - if (!Core.ML || (ct != OrderType.Follow && ct != OrderType.Stop && ct != OrderType.Stay)) - { - AIObject.OnAggressiveAction(aggressor); - } - else - { - DebugSay("I'm being attacked but my master told me not to fight."); - Warmode = false; - return; - } - } - - StopFlee(); - - ForceReacquire(); - - if (!IsEnemy(aggressor)) - { - Player pl = Ethics.Player.Find(aggressor, true); - - if (pl?.IsShielded == true) - pl.FinishShield(); - } - - if (aggressor.ChangingCombatant && (m_Controlled || m_bSummoned) && - (ct == OrderType.Come || (!Core.ML && ct == OrderType.Stay) || ct == OrderType.Stop || ct == OrderType.None || - ct == OrderType.Follow)) - { - ControlTarget = aggressor; - ControlOrder = OrderType.Attack; - } - else if (Combatant == null && !BardPacified) - { - Warmode = true; - Combatant = aggressor; - } - } - - public override bool OnMoveOver(Mobile m) - { - if (m is BaseCreature creature && !creature.Controlled) - return !Alive || !creature.Alive || IsDeadBondedPet || creature.IsDeadBondedPet || - (Hidden && AccessLevel > AccessLevel.Player); - - if (Region.IsPartOf() && m is PlayerMobile pm && - (pm.DuelContext?.Started != true || pm.DuelContext.Finished || - pm.DuelPlayer?.Eliminated != false)) - return true; - - return base.OnMoveOver(m); - } - - public virtual void AddCustomContextEntries(Mobile from, List list) - { - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (Commandable) - AIObject?.GetContextMenuEntries(from, list); - - if (m_bTamable && !m_Controlled && from.Alive) - list.Add(new TameEntry(from, this)); - - AddCustomContextEntries(from, list); - - if (CanTeach && from.Alive) - { - Skills ourSkills = Skills; - Skills theirSkills = from.Skills; - - for (int i = 0; i < ourSkills.Length && i < theirSkills.Length; ++i) - { - Skill skill = ourSkills[i]; - Skill theirSkill = theirSkills[i]; - - if (skill?.Base >= 60.0 && CheckTeach(skill.SkillName, from)) - { - int toTeach = skill.BaseFixedPoint / 3; - - if (toTeach > 420) - toTeach = 420; - - list.Add(new TeachEntry((SkillName)i, this, from, toTeach > theirSkill.BaseFixedPoint)); - } - } - } - } - - public override bool HandlesOnSpeech(Mobile from) => - ((SpeechType?.Flags & IHSFlags.OnSpeech) != 0 && from.InRange(this, 3)) || - (AIObject?.HandlesOnSpeech(from) == true && from.InRange(this, RangePerception)); - - public override void OnSpeech(SpeechEventArgs e) - { - InhumanSpeech speechType = SpeechType; - - if (speechType?.OnSpeech(this, e.Mobile, e.Speech) == true) - e.Handled = true; - else if (!e.Handled && AIObject != null && e.Mobile.InRange(this, RangePerception)) - AIObject.OnSpeech(e); - } - - public override bool IsHarmfulCriminal(Mobile target) => - (!Controlled || target != m_ControlMaster) && (!Summoned || target != m_SummonMaster) && - (!(target is BaseCreature creature) || !creature.InitialInnocent || creature.Controlled) && - (!(target is PlayerMobile mobile) || mobile.PermaFlags.Count <= 0) && base.IsHarmfulCriminal(target); - - public override void CriminalAction(bool message) - { - base.CriminalAction(message); - - if (Controlled || Summoned) - { - if (m_ControlMaster?.Player == true) - m_ControlMaster.CriminalAction(false); - else if (m_SummonMaster?.Player == true) - m_SummonMaster.CriminalAction(false); - } - } - - public override void DoHarmful(Mobile target, bool indirect) - { - base.DoHarmful(target, indirect); - - if (target == this || target == m_ControlMaster || target == m_SummonMaster || (!Controlled && !Summoned)) - return; - - List list = Aggressors; - - for (int i = 0; i < list.Count; ++i) - { - AggressorInfo ai = list[i]; - - if (ai.Attacker == target) - return; - } - - list = Aggressed; - - for (int i = 0; i < list.Count; ++i) - { - AggressorInfo ai = list[i]; - - if (ai.Defender == target) - { - if (m_ControlMaster?.Player == true && m_ControlMaster.CanBeHarmful(target, false)) - m_ControlMaster.DoHarmful(target, true); - else if (m_SummonMaster?.Player == true && m_SummonMaster.CanBeHarmful(target, false)) - m_SummonMaster.DoHarmful(target, true); - - return; - } - } - } - - public void ReleaseGuardDupeLock() - { - m_NoDupeGuards = null; - } - - public void ReleaseGuardLock() - { - EndAction(); - } - - public virtual bool CheckIdle() - { - if (Combatant != null) - return false; // in combat.. not idling - - if (m_IdleReleaseTime > DateTime.MinValue) - { - // idling... - - if (DateTime.UtcNow >= m_IdleReleaseTime) - { - m_IdleReleaseTime = DateTime.MinValue; - return false; // idle is over - } - - return true; // still idling - } - - if (Utility.Random(100) < 95) - return false; // not idling, but don't want to enter idle state - - m_IdleReleaseTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(15, 25)); - - if (Body.IsHuman) - switch (Utility.Random(2)) - { - case 0: - CheckedAnimate(5, 5, 1, true, true, 1); - break; - case 1: - CheckedAnimate(6, 5, 1, true, false, 1); - break; - } - else if (Body.IsAnimal) - switch (Utility.Random(3)) - { - case 0: - CheckedAnimate(3, 3, 1, true, false, 1); - break; - case 1: - CheckedAnimate(9, 5, 1, true, false, 1); - break; - case 2: - CheckedAnimate(10, 5, 1, true, false, 1); - break; - } - else if (Body.IsMonster) - switch (Utility.Random(2)) - { - case 0: - CheckedAnimate(17, 5, 1, true, false, 1); - break; - case 1: - CheckedAnimate(18, 5, 1, true, false, 1); - break; - } - - PlaySound(GetIdleSound()); - return true; // entered idle state - } - - /* - this way, due to the huge number of locations this will have to be changed - Perhaps we can change this in the future when fixing game play is not the - major issue. - */ - - public virtual void CheckedAnimate(int action, int frameCount, int repeatCount, bool forward, bool repeat, int delay) - { - if (!Mounted) - Animate(action, frameCount, repeatCount, forward, repeat, delay); - } - - private void CheckAIActive() - { - Map map = Map; - - if (PlayerRangeSensitive && AIObject != null && map?.GetSector(Location).Active == true) - AIObject.Activate(); - } - - public override void OnCombatantChange() - { - base.OnCombatantChange(); - - Warmode = Combatant?.Deleted == false && Combatant.Alive; - - if (CanFly && Warmode) - Flying = false; - } - - protected override void OnMapChange(Map oldMap) - { - CheckAIActive(); - - base.OnMapChange(oldMap); - } - - protected override void OnLocationChange(Point3D oldLocation) - { - CheckAIActive(); - - base.OnLocationChange(oldLocation); - } - - public virtual void ForceReacquire() - { - NextReacquireTime = Core.TickCount; - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (AcquireOnApproach && !Controlled && !Summoned && FightMode != FightMode.Aggressor) - { - if (InRange(m.Location, AcquireOnApproachRange) && !InRange(oldLocation, AcquireOnApproachRange) && - CanBeHarmful(m) && IsEnemy(m)) - { - Combatant = FocusMob = m; - AIObject?.MoveTo(m, true, 1); - DoHarmful(m); - } - } - else if (ReacquireOnMovement) - { - ForceReacquire(); - } - - InhumanSpeech speechType = SpeechType; - - speechType?.OnMovement(this, m, oldLocation); - - /* Begin notice sound */ - if ((!m.Hidden || m.AccessLevel == AccessLevel.Player) && m.Player && FightMode != FightMode.Aggressor && - FightMode != FightMode.None && Combatant == null && !Controlled && !Summoned && - InRange(m.Location, 18) && !InRange(oldLocation, 18)) - { - if (Body.IsMonster) - Animate(11, 5, 1, true, false, 1); - - PlaySound(GetAngerSound()); - } - /* End notice sound */ - - if (MLQuestSystem.Enabled && CanShout && m is PlayerMobile mobile) - CheckShout(mobile, oldLocation); - - if (m_NoDupeGuards == m) - return; - - if (!Body.IsHuman || Kills >= 5 || AlwaysMurderer || AlwaysAttackable || m.Kills < 5 || - !m.InRange(Location, 12) || !m.Alive) - return; - - GuardedRegion guardedRegion = Region.GetRegion(); - - if (guardedRegion?.IsDisabled() == false && guardedRegion.IsGuardCandidate(m) && BeginAction()) - { - Say(1013037 + Utility.Random(16)); - guardedRegion.CallGuards(Location); - - Timer.DelayCall(TimeSpan.FromSeconds(5.0), ReleaseGuardLock); - - m_NoDupeGuards = m; - Timer.DelayCall(ReleaseGuardDupeLock); - } - } - - public void AddSpellAttack(Type type) - { - m_SpellAttack.Add(type); - } - - public void AddSpellDefense(Type type) - { - m_SpellDefense.Add(type); - } - - public Spell GetAttackSpellRandom() - { - Type type = m_SpellAttack.RandomElement(); - return type == null ? null : ActivatorUtil.CreateInstance(type, this, null) as Spell; - } - - public Spell GetDefenseSpellRandom() - { - Type type = m_SpellDefense.RandomElement(); - return type == null ? null : ActivatorUtil.CreateInstance(type, this, null) as Spell; - } - - public Spell GetSpellSpecific(Type type) - { - int i; - - for (i = 0; i < m_SpellAttack.Count; i++) - if (m_SpellAttack[i] == type) - return ActivatorUtil.CreateInstance(type, this, null) as Spell; - - for (i = 0; i < m_SpellDefense.Count; i++) - if (m_SpellDefense[i] == type) - return ActivatorUtil.CreateInstance(type, this, null) as Spell; - - return null; - } - - public static void Cap(ref int val, int min, int max) - { - if (val < min) - val = min; - else if (val > max) - val = max; - } - - public override void OnDoubleClick(Mobile from) - { - if (from.AccessLevel >= AccessLevel.GameMaster && !Body.IsHuman) - { - Container pack = Backpack; - - pack?.DisplayTo(from); - } - - if (DeathAdderCharmable && from.CanBeHarmful(this, false)) - if (SummonFamiliarSpell.Table.TryGetValue(from, out BaseCreature bc) && (bc as DeathAdder)?.Deleted == false) - { - from.SendAsciiMessage("You charm the snake. Select a target to attack."); - from.Target = new DeathAdderCharmTarget(this); - } - - if (MLQuestSystem.Enabled && CanGiveMLQuest && from is PlayerMobile mobile) - MLQuestSystem.OnDoubleClick(this, mobile); - - base.OnDoubleClick(from); - } - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - if (MLQuestSystem.Enabled && CanGiveMLQuest) - list.Add(1072269); // Quest Giver - - if (Core.ML) - { - if (DisplayWeight) - list.Add(TotalWeight == 1 ? 1072788 : 1072789, TotalWeight.ToString()); // Weight: ~1_WEIGHT~ stones - - if (m_ControlOrder == OrderType.Guard) - list.Add(1080078); // guarding - } - - if (Summoned && !(IsAnimatedDead || IsNecroFamiliar || this is Clone)) - { - list.Add(1049646); // (summoned) - } - else if (Controlled && Commandable) - { - if (IsBonded) // Intentional difference (showing ONLY bonded when bonded instead of bonded & tame) - list.Add(1049608); // (bonded) - else - list.Add(502006); // (tame) - } - } - - public override void OnSingleClick(Mobile from) - { - if (Controlled && Commandable) - { - int number; - - if (Summoned) - number = 1049646; // (summoned) - else if (IsBonded) - number = 1049608; // (bonded) - else - number = 502006; // (tame) - - PrivateOverheadMessage(MessageType.Regular, 0x3B2, number, from.NetState); - } - - base.OnSingleClick(from); - } - - public override bool OnBeforeDeath() - { - int treasureLevel = TreasureMapLevel; - - if (treasureLevel == 1 && Map == Map.Trammel && TreasureMap.IsInHavenIsland(this)) - { - Mobile killer = LastKiller; - - if (killer is BaseCreature bc) - killer = bc.GetMaster(); - - if (killer is PlayerMobile mobile && mobile.Young) - treasureLevel = 0; - } - - if (!Summoned && !NoKillAwards && !IsBonded) - { - if (treasureLevel >= 0) - { - if (m_Paragon && Paragon.ChestChance > Utility.RandomDouble()) - PackItem(new ParagonChest(Name, treasureLevel)); - else if ((Map == Map.Felucca || Map == Map.Trammel) && Utility.RandomDouble() <= TreasureMap.LootChance) - PackItem(new TreasureMap(treasureLevel, Map)); - } - - if (m_Paragon && Paragon.ChocolateIngredientChance > Utility.RandomDouble()) - switch (Utility.Random(4)) - { - case 0: - PackItem(new CocoaButter()); - break; - case 1: - PackItem(new CocoaLiquor()); - break; - case 2: - PackItem(new SackOfSugar()); - break; - case 3: - PackItem(new Vanilla()); - break; - } - } - - if (!Summoned && !NoKillAwards && !m_HasGeneratedLoot) - { - m_HasGeneratedLoot = true; - GenerateLoot(false); - } - - if (!NoKillAwards && Region.IsPartOf("Doom")) - { - int bones = TheSummoningQuest.GetDaemonBonesFor(this); - - if (bones > 0) - PackItem(new DaemonBone(bones)); - } - - if (IsAnimatedDead) - Effects.SendLocationEffect(Location, Map, 0x3728, 13, 1, 0x461, 4); - - InhumanSpeech speechType = SpeechType; - speechType?.OnDeath(this); - ReceivedHonorContext?.OnTargetKilled(); - - return base.OnBeforeDeath(); - } - - public int ComputeBonusDamage(List list, Mobile m) - { - int bonus = 0; - - for (int i = list.Count - 1; i >= 0; --i) - { - DamageEntry de = list[i]; - - if (de.Damager == m || !(de.Damager is BaseCreature bc)) - continue; - - if (bc.GetMaster() == m) - bonus += de.DamageGiven; - } - - return bonus; - } - - public Mobile GetMaster() - { - if (Controlled && ControlMaster != null) - return ControlMaster; - if (Summoned && SummonMaster != null) - return SummonMaster; - - return null; - } - - public static List GetLootingRights(List damageEntries, int hitsMax) - { - List rights = new List(); - - for (int i = damageEntries.Count - 1; i >= 0; --i) - { - if (i >= damageEntries.Count) - continue; - - DamageEntry de = damageEntries[i]; - - if (de.HasExpired) - { - damageEntries.RemoveAt(i); - continue; - } - - int damage = de.DamageGiven; - - List respList = de.Responsible; - - for (int j = 0; j < respList?.Count; ++j) - { - DamageEntry subEntry = respList[j]; - Mobile master = subEntry.Damager; - - if (master?.Deleted != false || !master.Player) - continue; - - bool needNewSubEntry = true; - - for (int k = 0; needNewSubEntry && k < rights.Count; ++k) - { - DamageStore ds = rights[k]; - - if (ds.m_Mobile == master) + get { - ds.m_Damage += subEntry.DamageGiven; - needNewSubEntry = false; + if (NameMod == null && base.Name == null) + return DefaultName; + + return base.Name; } - } - - if (needNewSubEntry) - rights.Add(new DamageStore(master, subEntry.DamageGiven)); - - damage -= subEntry.DamageGiven; + set => base.Name = value == DefaultName ? null : value; } - Mobile m = de.Damager; + public virtual InhumanSpeech SpeechType => null; - if (m?.Deleted != false || !m.Player) - continue; + /* Do not serialize this till the code is finalized */ - if (damage <= 0) - continue; + [CommandProperty(AccessLevel.GameMaster)] + public bool SeeksHome { get; set; } - bool needNewEntry = true; + [CommandProperty(AccessLevel.GameMaster)] + public string CorpseNameOverride { get; set; } - for (int j = 0; needNewEntry && j < rights.Count; ++j) + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public bool IsStabled { - DamageStore ds = rights[j]; - - if (ds.m_Mobile == m) - { - ds.m_Damage += damage; - needNewEntry = false; - } - } - - if (needNewEntry) - rights.Add(new DamageStore(m, damage)); - } - - if (rights.Count > 0) - { - rights[0].m_Damage = - (int)(rights[0].m_Damage * - 1.25); // This would be the first valid person attacking it. Gets a 25% bonus. Per 1/19/07 Five on Friday - - if (rights.Count > 1) - rights.Sort(); // Sort by damage - - int topDamage = rights[0].m_Damage; - int minDamage; - - if (hitsMax >= 3000) - minDamage = topDamage / 16; - else if (hitsMax >= 1000) - minDamage = topDamage / 8; - else if (hitsMax >= 200) - minDamage = topDamage / 4; - else - minDamage = topDamage / 2; - - for (int i = 0; i < rights.Count; ++i) - { - DamageStore ds = rights[i]; - - ds.m_HasRight = ds.m_Damage >= minDamage; - } - } - - return rights; - } - - public virtual void OnKilledBy(Mobile mob) - { - if (GivesMLMinorArtifact) - { - if (MondainsLegacy.CheckArtifactChance(mob, this)) - MondainsLegacy.GiveArtifactTo(mob); - } - else if (m_Paragon) - { - if (Paragon.CheckArtifactChance(mob, this)) - Paragon.GiveArtifactTo(mob); - } - } - - public override void OnDeath(Container c) - { - MeerMage.StopEffect(this, false); - - if (IsBonded) - { - int sound = GetDeathSound(); - - if (sound >= 0) - Effects.PlaySound(this, Map, sound); - - Warmode = false; - - Poison = null; - Combatant = null; - - Hits = 0; - Stam = 0; - Mana = 0; - - IsDeadPet = true; - ControlTarget = ControlMaster; - ControlOrder = OrderType.Follow; - - ProcessDeltaQueue(); - SendIncomingPacket(); - SendIncomingPacket(); - - // TODO: This can be done in Parallel if there are lots of them. - List aggressors = Aggressors; - - for (int i = 0; i < aggressors.Count; ++i) - { - AggressorInfo info = aggressors[i]; - - if (info.Attacker.Combatant == this) - info.Attacker.Combatant = null; - } - - List aggressed = Aggressed; - - for (int i = 0; i < aggressed.Count; ++i) - { - AggressorInfo info = aggressed[i]; - - if (info.Defender.Combatant == this) - info.Defender.Combatant = null; - } - - Mobile owner = ControlMaster; - - if (owner?.Deleted != false || owner.Map != Map || !owner.InRange(this, 12) || !CanSee(owner) || - !InLOS(owner)) - { - if (OwnerAbandonTime == DateTime.MinValue) - OwnerAbandonTime = DateTime.UtcNow; - } - else - { - OwnerAbandonTime = DateTime.MinValue; - } - - GiftOfLifeSpell.HandleDeath(this); - - CheckStatTimers(); - } - else - { - if (!Summoned && !NoKillAwards) - { - int totalFame = Fame / 100; - int totalKarma = -Karma / 100; - - if (Map == Map.Felucca) - { - totalFame += totalFame / 10 * 3; - totalKarma += totalKarma / 10 * 3; - } - - List list = GetLootingRights(DamageEntries, HitsMax); - List titles = new List(); - List fame = new List(); - List karma = new List(); - - bool givenQuestKill = false; - bool givenFactionKill = false; - bool givenToTKill = false; - - for (int i = 0; i < list.Count; ++i) - { - DamageStore ds = list[i]; - - if (!ds.m_HasRight) - continue; - - Party party = Engines.PartySystem.Party.Get(ds.m_Mobile); - - if (party != null) + get => m_IsStabled; + set { - int divedFame = totalFame / party.Members.Count; - int divedKarma = totalKarma / party.Members.Count; + m_IsStabled = value; + if (m_IsStabled) + StopDeleteTimer(); + } + } - for (int j = 0; j < party.Members.Count; ++j) - { - PartyMemberInfo info = party.Members[j]; + [CommandProperty(AccessLevel.GameMaster, AccessLevel.Administrator)] + public Mobile StabledBy { get; set; } - if (info?.Mobile != null) + [CommandProperty(AccessLevel.GameMaster)] + public bool IsPrisoner { get; set; } + + protected DateTime SummonEnd { get; set; } + + public virtual Faction FactionAllegiance => null; + public virtual int FactionSilverWorth => 30; + + public virtual double WeaponAbilityChance => 0.4; + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsParagon + { + get => m_Paragon; + set + { + if (m_Paragon == value) + return; + if (value) + Paragon.Convert(this); + else + Paragon.UnConvert(this); + + m_Paragon = value; + + InvalidateProperties(); + } + } + + public virtual bool HasManaOveride => false; + + public virtual FoodType FavoriteFood => FoodType.Meat; + public virtual PackInstinct PackInstinct => PackInstinct.None; + + public List Owners { get; private set; } + + public virtual bool AllowMaleTamer => true; + public virtual bool AllowFemaleTamer => true; + public virtual bool SubdueBeforeTame => false; + public virtual bool StatLossAfterTame => SubdueBeforeTame; + public virtual bool ReduceSpeedWithDamage => true; + public virtual bool IsSubdued => SubdueBeforeTame && Hits < HitsMax / 10; + + public virtual bool Commandable => true; + + public virtual Poison HitPoison => null; + public virtual double HitPoisonChance => 0.5; + public virtual Poison PoisonImmune => null; + + public virtual bool BardImmune => false; + public virtual bool Unprovokable => BardImmune || IsDeadPet; + public virtual bool Uncalmable => BardImmune || IsDeadPet; + public virtual bool AreaPeaceImmune => BardImmune || IsDeadPet; + + public virtual bool BleedImmune => false; + public virtual double BonusPetDamageScalar => 1.0; + + public virtual bool DeathAdderCharmable => false; + + // TODO: Find the pub 31 tweaks to the DispelDifficulty and apply them of course. + public virtual double DispelDifficulty // at this skill level we dispel 50% chance + => 0.0; + + public virtual double DispelFocus // at difficulty - focus we have 0%, at difficulty + focus we have 100% + => 20.0; + + public virtual bool DisplayWeight => Backpack is StrongBackpack; + + public virtual bool CanFly => false; + + public virtual bool IsInvulnerable => false; + + public BaseAI AIObject { get; private set; } + + public virtual OppositionGroup OppositionGroup => null; + + public virtual bool IsAnimatedDead + { + get + { + if (!Summoned) + return false; + + var type = GetType(); + + var contains = false; + + for (var i = 0; !contains && i < m_AnimateDeadTypes.Length; ++i) + contains = type == m_AnimateDeadTypes[i]; + + return contains; + } + } + + public virtual bool IsNecroFamiliar => + Summoned && m_ControlMaster != null && + SummonFamiliarSpell.Table.TryGetValue(m_ControlMaster, out var bc) && bc == this; + + public virtual bool DeleteCorpseOnDeath => !Core.AOS && m_bSummoned; + + [CommandProperty(AccessLevel.GameMaster)] + public int Loyalty + { + get => m_Loyalty; + set => m_Loyalty = Math.Clamp(value, 0, MaxLoyalty); + } + + [CommandProperty(AccessLevel.GameMaster)] + public WayPoint CurrentWayPoint { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public IPoint2D TargetLocation { get; set; } + + public virtual Mobile ConstantFocus => null; + + public virtual bool DisallowAllMoves => false; + + public virtual bool InitialInnocent => false; + + public virtual bool AlwaysMurderer => false; + + public virtual bool AlwaysAttackable => false; + + [CommandProperty(AccessLevel.GameMaster)] + public virtual int DamageMin + { + get => m_DamageMin; + set => m_DamageMin = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public virtual int DamageMax + { + get => m_DamageMax; + set => m_DamageMax = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public override int HitsMax => + HitsMaxSeed <= 0 ? Str : Math.Clamp(HitsMaxSeed + GetStatOffset(StatType.Str), 1, 65000); + + [CommandProperty(AccessLevel.GameMaster)] + public int HitsMaxSeed { get; set; } = -1; + + [CommandProperty(AccessLevel.GameMaster)] + public override int StamMax => + StamMaxSeed <= 0 ? Dex : Math.Clamp(StamMaxSeed + GetStatOffset(StatType.Dex), 1, 65000); + + [CommandProperty(AccessLevel.GameMaster)] + public int StamMaxSeed { get; set; } = -1; + + [CommandProperty(AccessLevel.GameMaster)] + public override int ManaMax => + ManaMaxSeed <= 0 ? Int : Math.Clamp(ManaMaxSeed + GetStatOffset(StatType.Int), 1, 65000); + + [CommandProperty(AccessLevel.GameMaster)] + public int ManaMaxSeed { get; set; } = -1; + + public virtual bool CanOpenDoors => !Body.IsAnimal && !Body.IsSea; + + public virtual bool CanMoveOverObstacles => Core.AOS || Body.IsMonster; + + public virtual bool CanDestroyObstacles => false; + + /* + Seems this actually was removed on OSI somewhere between the original bug report and now. + We will call it ML, until we can get better information. I suspect it was on the OSI TC when + originally it taken out of RunUO, and not implemented on OSIs production shards until more + recently. Either way, this is, or was, accurate OSI behavior, and just entirely + removing it was incorrect. OSI followers were distracted by being attacked well into + AoS, at very least. + + */ + + public virtual bool CanBeDistracted => !Core.ML; + + public override bool ShouldCheckStatTimers => false; + + public virtual bool CanAngerOnTame => false; + + protected virtual BaseAI ForcedAI => null; + + [CommandProperty(AccessLevel.GameMaster)] + public AIType AI + { + get => m_CurrentAI; + set + { + m_CurrentAI = value; + + if (m_CurrentAI == AIType.AI_Use_Default) + m_CurrentAI = m_DefaultAI; + + ChangeAIType(m_CurrentAI); + } + } + + [CommandProperty(AccessLevel.Administrator)] + public bool Debug { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Team + { + get => m_Team; + set + { + m_Team = value; + OnTeamChange(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile FocusMob { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public FightMode FightMode { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int RangePerception { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int RangeFight { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int RangeHome { get; set; } = 10; + + [CommandProperty(AccessLevel.GameMaster)] + public double ActiveSpeed { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public double PassiveSpeed { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public double CurrentSpeed + { + get => TargetLocation != null ? 0.3 : m_CurrentSpeed; + set + { + if (m_CurrentSpeed != value) { - int index = titles.IndexOf(info.Mobile); - - if (index == -1) - { - titles.Add(info.Mobile); - fame.Add(divedFame); - karma.Add(divedKarma); - } - else - { - fame[index] += divedFame; - karma[index] += divedKarma; - } + m_CurrentSpeed = value; + AIObject?.OnCurrentSpeedChanged(); } - } } - else + } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D Home + { + get => m_Home; + set => m_Home = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public Map HomeMap { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Controlled + { + get => m_Controlled; + set { - titles.Add(ds.m_Mobile); - fame.Add(totalFame); - karma.Add(totalKarma); + if (m_Controlled == value) + return; + + m_Controlled = value; + Delta(MobileDelta.Noto); + + InvalidateProperties(); } + } - OnKilledBy(ds.m_Mobile); - - if (!givenFactionKill) + [CommandProperty(AccessLevel.GameMaster)] + public Mobile ControlMaster + { + get => m_ControlMaster; + set { - givenFactionKill = true; - Faction.HandleDeath(this, ds.m_Mobile); + if (m_ControlMaster == value || this == value) + return; + + RemoveFollowers(); + m_ControlMaster = value; + AddFollowers(); + if (m_ControlMaster != null) + StopDeleteTimer(); + + Delta(MobileDelta.Noto); } + } - Region region = ds.m_Mobile.Region; - - if (!givenToTKill && (Map == Map.Tokuno || region.IsPartOf("Yomotsu Mines") || - region.IsPartOf("Fan Dancer's Dojo"))) + [CommandProperty(AccessLevel.GameMaster)] + public Mobile SummonMaster + { + get => m_SummonMaster; + set { - givenToTKill = true; - TreasuresOfTokuno.HandleKill(this, ds.m_Mobile); - } + if (m_SummonMaster == value || this == value) + return; - if (ds.m_Mobile is PlayerMobile pm) + RemoveFollowers(); + m_SummonMaster = value; + AddFollowers(); + + Delta(MobileDelta.Noto); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile ControlTarget { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D ControlDest { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public OrderType ControlOrder + { + get => m_ControlOrder; + set { - if (MLQuestSystem.Enabled) MLQuestSystem.HandleKill(pm, this); + m_ControlOrder = value; - if (givenQuestKill) - continue; + AIObject?.OnCurrentOrderChanged(); - QuestSystem qs = pm.Quest; + InvalidateProperties(); - if (qs != null) - { - qs.OnKill(this, c); - givenQuestKill = true; - } + m_ControlMaster?.InvalidateProperties(); } - } - - for (int i = 0; i < titles.Count; ++i) - { - Titles.AwardFame(titles[i], fame[i], true); - Titles.AwardKarma(titles[i], karma[i], true); - } } - base.OnDeath(c); + [CommandProperty(AccessLevel.GameMaster)] + public bool BardProvoked { get; set; } - if (DeleteCorpseOnDeath) - c.Delete(); - } - } + [CommandProperty(AccessLevel.GameMaster)] + public bool BardPacified { get; set; } - public override void OnDelete() - { - Mobile m = m_ControlMaster; - SetControlMaster(null); + [CommandProperty(AccessLevel.GameMaster)] + public Mobile BardMaster { get; set; } - SummonMaster = null; - ReceivedHonorContext?.Cancel(); - base.OnDelete(); - m?.InvalidateProperties(); - } + [CommandProperty(AccessLevel.GameMaster)] + public Mobile BardTarget { get; set; } - public override bool CanBeHarmful(Mobile target, bool message, bool ignoreOurBlessedness) - { - if (target is BaseFactionGuard) - return false; + [CommandProperty(AccessLevel.GameMaster)] + public DateTime BardEndTime { get; set; } - if ((target is BaseCreature creature && creature.IsInvulnerable) || target is PlayerVendor || target is TownCrier) - { - if (message) + [CommandProperty(AccessLevel.GameMaster)] + public double MinTameSkill { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Tamable { - if (target.Title == null) - SendMessage("{0} cannot be harmed.", target.Name); - else - SendMessage("{0} {1} cannot be harmed.", target.Name, target.Title); + get => m_bTamable && !m_Paragon; + set => m_bTamable = value; } - return false; - } - - return base.CanBeHarmful(target, message, ignoreOurBlessedness); - } - - public override bool CanBeRenamedBy(Mobile from) => - (Controlled && from == ControlMaster && !from.Region.IsPartOf()) || - base.CanBeRenamedBy(from); - - public bool SetControlMaster(Mobile m) - { - if (m == null) - { - ControlMaster = null; - Controlled = false; - ControlTarget = null; - ControlOrder = OrderType.None; - Guild = null; - - Delta(MobileDelta.Noto); - } - else - { - ISpawner se = Spawner; - if (se?.UnlinkOnTaming == true) + [CommandProperty(AccessLevel.Administrator)] + public bool Summoned { - Spawner.Remove(this); - Spawner = null; - } - - if (m.Followers + ControlSlots > m.FollowersMax) - { - m.SendLocalizedMessage(1049607); // You have too many followers to control that creature. - return false; - } - - CurrentWayPoint = null; // so tamed animals don't try to go back - - Home = Point3D.Zero; - - ControlMaster = m; - Controlled = true; - ControlTarget = null; - ControlOrder = OrderType.Come; - Guild = null; - - if (m_DeleteTimer != null) - { - m_DeleteTimer.Stop(); - m_DeleteTimer = null; - } - - Delta(MobileDelta.Noto); - } - - InvalidateProperties(); - - return true; - } - - public override void OnRegionChange(Region Old, Region New) - { - base.OnRegionChange(Old, New); - - if (Controlled && Spawner?.UnlinkOnTaming == false && New?.AcceptsSpawnsFrom(Spawner.Region) != true) - { - Spawner.Remove(this); - Spawner = null; - } - } - - public static bool Summon(BaseCreature creature, Mobile caster, Point3D p, int sound, TimeSpan duration) => Summon(creature, true, caster, p, sound, duration); - - public static bool Summon(BaseCreature creature, bool controlled, Mobile caster, Point3D p, int sound, - TimeSpan duration) - { - if (caster.Followers + creature.ControlSlots > caster.FollowersMax) - { - caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. - creature.Delete(); - return false; - } - - Summoning = true; - - if (controlled) - creature.SetControlMaster(caster); - - creature.RangeHome = 10; - creature.Summoned = true; - - creature.SummonMaster = caster; - - Container pack = creature.Backpack; - - if (pack != null) - for (int i = pack.Items.Count - 1; i >= 0; --i) - { - if (i >= pack.Items.Count) - continue; - - pack.Items[i].Delete(); - } - - new UnsummonTimer(caster, creature, duration).Start(); - creature.SummonEnd = DateTime.UtcNow + duration; - - creature.MoveToWorld(p, caster.Map); - - Effects.PlaySound(p, creature.Map, sound); - - Summoning = false; - - return true; - } - - public virtual void OnThink() - { - long tc = Core.TickCount; - - if (EnableRummaging && CanRummageCorpses && !Summoned && !Controlled && tc - m_NextRummageTime >= 0) - { - double min, max; - - if (Utility.RandomDouble() < ChanceToRummage && Rummage()) - { - min = MinutesToNextRummageMin; - max = MinutesToNextRummageMax; - } - else - { - min = MinutesToNextChanceMin; - max = MinutesToNextChanceMax; - } - - double delay = min + Utility.RandomDouble() * (max - min); - m_NextRummageTime = tc + (int)TimeSpan.FromMinutes(delay).TotalMilliseconds; - } - - if (CanBreath && tc - m_NextBreathTime >= 0) // tested: controlled dragons do breath fire, what about summoned skeletal dragons? - { - Mobile target = Combatant; - - if (target?.Alive == true && !target.IsDeadBondedPet && CanBeHarmful(target) && target.Map == Map && - !IsDeadBondedPet && target.InRange(this, BreathRange) && InLOS(target) && !BardPacified) - { - if (Core.TickCount - m_NextBreathTime < 30000 && Utility.RandomBool()) BreathStart(target); - - m_NextBreathTime = tc + (int)TimeSpan.FromSeconds(BreathMinDelay + Utility.RandomDouble() * (BreathMaxDelay - BreathMinDelay)).TotalMilliseconds; - } - } - - if ((CanHeal || CanHealOwner) && Alive && !IsHealing && !BardPacified) - { - Mobile owner = ControlMaster; - - if (owner != null && CanHealOwner && tc - m_NextHealOwnerTime >= 0 && CanBeBeneficial(owner, true, true) && - owner.Map == Map && InRange(owner, HealStartRange) && InLOS(owner) && - owner.Hits < HealOwnerTrigger * owner.HitsMax) - { - HealStart(owner); - - m_NextHealOwnerTime = tc + (int)TimeSpan.FromSeconds(HealOwnerInterval).TotalMilliseconds; - } - else if (CanHeal && tc - m_NextHealTime >= 0 && CanBeBeneficial(this) && - (Hits < HealTrigger * HitsMax || Poisoned)) - { - HealStart(this); - - m_NextHealTime = tc + (int)TimeSpan.FromSeconds(HealInterval).TotalMilliseconds; - } - } - - if (ReturnsToHome && IsSpawnerBound() && !InRange(Home, RangeHome)) - { - if (Combatant == null && Warmode == false && Utility.RandomDouble() < .10) /* some throttling */ - { - m_FailedReturnHome = !Move(GetDirectionTo(Home.X, Home.Y)) ? m_FailedReturnHome + 1 : 0; - - if (m_FailedReturnHome > 5) - { - SetLocation(Home, true); - - m_FailedReturnHome = 0; - } - } - } - else - { - m_FailedReturnHome = 0; - } - - if (HasAura && tc - m_NextAura >= 0) - { - AuraDamage(); - m_NextAura = tc + (int)AuraInterval.TotalMilliseconds; - } - } - - public virtual bool Rummage() - { - IPooledEnumerable eable = GetItemsInRange(2); - Corpse toRummage = eable.FirstOrDefault(item => item.Items.Count > 0); - - eable.Free(); - - if (toRummage == null) - return false; - - if (Backpack == null) - return false; - - List items = toRummage.Items; - - for (int i = 0; i < items.Count; ++i) - { - Item item = items.RandomElement(); - - Lift(item, item.Amount, out bool rejected, out LRReason _); - - if (!rejected && Drop(this, new Point3D(-1, -1, 0))) - { - // *rummages through a corpse and takes an item* - PublicOverheadMessage(MessageType.Emote, 0x3B2, 1008086); - // TODO: Instancing of Rummaged stuff. - return true; - } - } - - return false; - } - - public void Pacify(Mobile master, DateTime endtime) - { - BardPacified = true; - BardEndTime = endtime; - } - - public override Mobile GetDamageMaster(Mobile damagee) - { - if (BardProvoked && damagee == BardTarget) - return BardMaster; - if (m_Controlled && m_ControlMaster != null) - return m_ControlMaster; - if (m_bSummoned && m_SummonMaster != null) - return m_SummonMaster; - - return base.GetDamageMaster(damagee); - } - - public void Provoke(Mobile master, Mobile target, bool bSuccess) - { - BardProvoked = true; - - if (!Core.ML) PublicOverheadMessage(MessageType.Emote, EmoteHue, false, "*looks furious*"); - - if (bSuccess) - { - PlaySound(GetIdleSound()); - - BardMaster = master; - BardTarget = target; - Combatant = target; - BardEndTime = DateTime.UtcNow + TimeSpan.FromSeconds(30.0); - - if (target is BaseCreature t) - { - if (t.Unprovokable || (t.IsParagon && BaseInstrument.GetBaseDifficulty(t) >= 160.0)) - return; - - t.BardProvoked = true; - - t.BardMaster = master; - t.BardTarget = this; - t.Combatant = this; - t.BardEndTime = DateTime.UtcNow + TimeSpan.FromSeconds(30.0); - } - } - else - { - PlaySound(GetAngerSound()); - - BardMaster = master; - BardTarget = target; - } - } - - public bool FindMyName(string str, bool bWithAll) - { - string name = Name; - - if (name == null || str.Length < name.Length) - return false; - - string[] wordsString = str.Split(' '); - string[] wordsName = name.Split(' '); - - for (int j = 0; j < wordsName.Length; j++) - { - string wordName = wordsName[j]; - - bool bFound = false; - for (int i = 0; i < wordsString.Length; i++) - { - string word = wordsString[i]; - - if (Insensitive.Equals(word, wordName)) - bFound = true; - - if (bWithAll && Insensitive.Equals(word, "all")) - return true; - } - - if (!bFound) - return false; - } - - return true; - } - - public static void TeleportPets(Mobile master, Point3D loc, Map map, bool onlyBonded = false) - { - List move = new List(); - - foreach (Mobile m in master.GetMobilesInRange(3)) - if (m is BaseCreature pet) - if ((pet.Controlled && pet.ControlMaster == master && !onlyBonded) || pet.IsBonded) - if (pet.ControlOrder == OrderType.Guard || pet.ControlOrder == OrderType.Follow || - pet.ControlOrder == OrderType.Come) - move.Add(pet); - - foreach (Mobile m in move) - m.MoveToWorld(loc, map); - } - - public virtual void ResurrectPet() - { - if (!IsDeadPet) - return; - - OnBeforeResurrect(); - - Poison = null; - - Warmode = false; - - Hits = 10; - Stam = StamMax; - Mana = 0; - - ProcessDeltaQueue(); - - IsDeadPet = false; - - Effects.SendPacket(Location, Map, new BondedStatus(Serial, false)); - - SendIncomingPacket(); - SendIncomingPacket(); - - OnAfterResurrect(); - - Mobile owner = ControlMaster; - - if (owner?.Deleted != false || owner.Map != Map || !owner.InRange(this, 12) || !CanSee(owner) || - !InLOS(owner)) - { - if (OwnerAbandonTime == DateTime.MinValue) - OwnerAbandonTime = DateTime.UtcNow; - } - else - { - OwnerAbandonTime = DateTime.MinValue; - } - - CheckStatTimers(); - } - - public override bool CanBeDamaged() - { - if (IsDeadPet || IsInvulnerable) - return false; - - return base.CanBeDamaged(); - } - - private bool IsSpawnerBound() => - Map != null && Map != Map.Internal && - FightMode != FightMode.None && RangeHome >= 0 && - !Controlled && !Summoned && Spawner is Spawner spawner && spawner.Map == Map; - - public override void OnSectorDeactivate() - { - if (!Deleted && ReturnsToHome && IsSpawnerBound() && !InRange(Home, RangeHome + 5)) - { - Timer.DelayCall(TimeSpan.FromSeconds(Utility.Random(45) + 15), GoHome_Callback); - - m_ReturnQueued = true; - } - else if (PlayerRangeSensitive) - { - AIObject?.Deactivate(); - } - - base.OnSectorDeactivate(); - } - - public void GoHome_Callback() - { - if (m_ReturnQueued && IsSpawnerBound()) - if (!Map.GetSector(X, Y).Active) - { - SetLocation(Home, true); - - if (!Map.GetSector(X, Y).Active) AIObject?.Deactivate(); - } - - m_ReturnQueued = false; - } - - public override void OnSectorActivate() - { - if (PlayerRangeSensitive) AIObject?.Activate(); - - base.OnSectorActivate(); - } - - private class TameEntry : ContextMenuEntry - { - private readonly BaseCreature m_Mobile; - - public TameEntry(Mobile from, BaseCreature creature) : base(6130, 6) - { - m_Mobile = creature; - - Enabled = Enabled && (from.Female ? creature.AllowFemaleTamer : creature.AllowMaleTamer); - } - - public override void OnClick() - { - if (!Owner.From.CheckAlive()) - return; - - Owner.From.TargetLocked = true; - AnimalTaming.DisableMessage = true; - - if (Owner.From.UseSkill(SkillName.AnimalTaming)) - Owner.From.Target.Invoke(Owner.From, m_Mobile); - - AnimalTaming.DisableMessage = false; - Owner.From.TargetLocked = false; - } - } - - private class DeathAdderCharmTarget : Target - { - private readonly BaseCreature m_Charmed; - - public DeathAdderCharmTarget(BaseCreature charmed) : base(-1, false, TargetFlags.Harmful) => m_Charmed = charmed; - - protected override void OnTarget(Mobile from, object targeted) - { - if (!m_Charmed.DeathAdderCharmable || m_Charmed.Combatant != null || !from.CanBeHarmful(m_Charmed, false)) - return; - - if (!(SummonFamiliarSpell.Table.TryGetValue(from, out BaseCreature bc) && (bc as DeathAdder)?.Deleted == false)) - return; - - if (!(targeted is Mobile targ && from.CanBeHarmful(targ, false))) - return; - - from.RevealingAction(); - from.DoHarmful(targ, true); - - m_Charmed.Combatant = targ; - - if (m_Charmed.AIObject != null) - m_Charmed.AIObject.Action = ActionType.Combat; - } - } - - private AIType m_CurrentAI; // The current AI - private AIType m_DefaultAI; // The default AI - - private int m_Team; // Monster Team - - private double m_CurrentSpeed; // The current speed, lets say it could be changed by something; - - private Point3D m_Home; // The home position of the creature, used by some AI - - private readonly List m_SpellAttack; // List of attack spell/power - private readonly List m_SpellDefense; // List of defensive spell/power - - private bool m_Controlled; // Is controlled - private Mobile m_ControlMaster; // My master - private OrderType m_ControlOrder; // My order - - private int m_Loyalty; - - private bool m_bTamable; - - private bool m_bSummoned; - - private Mobile m_SummonMaster; - - private int m_DamageMin = -1; - private int m_DamageMax = -1; - - private int m_PhysicalResistance; - private int m_FireResistance; - private int m_ColdResistance; - private int m_PoisonResistance; - private int m_EnergyResistance; - - private bool m_IsStabled; - - private bool m_HasGeneratedLoot; // have we generated our loot yet? - - private bool m_Paragon; - - private int m_FailedReturnHome; /* return to home failure counter */ - - private List m_MLQuests; - - public List MLQuests - { - get - { - if (m_MLQuests == null) - { - if (StaticMLQuester) - m_MLQuests = MLQuestSystem.FindQuestList(GetType()); - else - m_MLQuests = ConstructQuestList(); - - if (m_MLQuests == null) - return - MLQuestSystem - .EmptyList; // return EmptyList, but don't cache it (run construction again next time) - } - - return m_MLQuests; - } - } - - public virtual bool CanGiveMLQuest => MLQuests.Count != 0; - public virtual bool StaticMLQuester => true; - - protected virtual List ConstructQuestList() => null; - - public virtual bool CanShout => false; - - public const int ShoutRange = 8; - public static readonly TimeSpan ShoutDelay = TimeSpan.FromMinutes(1); - - private DateTime m_MLNextShout; - - private void CheckShout(PlayerMobile pm, Point3D oldLocation) - { - if (m_MLNextShout > DateTime.UtcNow || pm.Hidden || !pm.Alive) - return; - - int shoutRange = ShoutRange; - - if (!InRange(pm.Location, shoutRange) || InRange(oldLocation, shoutRange) || !CanSee(pm) || !InLOS(pm)) - return; - - MLQuestContext context = MLQuestSystem.GetContext(pm); - - if (context?.IsFull == true) - return; - - MLQuest quest = MLQuestSystem.RandomStarterQuest(this, pm, context); - - if (quest?.Activated != true || context?.IsDoingQuest(quest) == true) - return; - - Shout(pm); - m_MLNextShout = DateTime.UtcNow + ShoutDelay; - } - - public virtual void Shout(PlayerMobile pm) - { - } - - public static void Initialize() - { - BondingEnabled = ServerConfiguration.GetOrUpdateSetting("taming.enableBonding", true); - } - - public static bool BondingEnabled { get; private set; } - - public virtual bool IsBondable => BondingEnabled && !Summoned; - public virtual TimeSpan BondingDelay => TimeSpan.FromDays(7.0); - public virtual TimeSpan BondingAbandonDelay => TimeSpan.FromDays(1.0); - - public override bool CanRegenHits => !IsDeadPet && base.CanRegenHits; - public override bool CanRegenStam => !IsParagon && !IsDeadPet && base.CanRegenStam; - public override bool CanRegenMana => !IsDeadPet && base.CanRegenMana; - - public override bool IsDeadBondedPet => IsDeadPet; - - private bool m_IsBonded; - - [CommandProperty(AccessLevel.GameMaster)] - public Spawner MySpawner => Spawner as Spawner; - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile LastOwner - { - get - { - if (Owners == null || Owners.Count == 0) - return null; - - return Owners[^1]; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsBonded - { - get => m_IsBonded; - set - { - m_IsBonded = value; - InvalidateProperties(); - } - } - - public bool IsDeadPet { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime BondingBegin { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime OwnerAbandonTime { get; set; } - - private DeleteTimer m_DeleteTimer; - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan DeleteTimeLeft - { - get - { - if (m_DeleteTimer?.Running == true) - return m_DeleteTimer.Next - DateTime.UtcNow; - - return TimeSpan.Zero; - } - } - - private class DeleteTimer : Timer - { - private readonly Mobile m; - - public DeleteTimer(Mobile creature, TimeSpan delay) : base(delay) - { - m = creature; - Priority = TimerPriority.OneMinute; - } - - protected override void OnTick() - { - m.Delete(); - } - } - - public void BeginDeleteTimer() - { - if (!(this is BaseEscortable) && !Summoned && !Deleted && !IsStabled) - { - StopDeleteTimer(); - m_DeleteTimer = new DeleteTimer(this, TimeSpan.FromDays(3.0)); - m_DeleteTimer.Start(); - } - } - - public void StopDeleteTimer() - { - if (m_DeleteTimer != null) - { - m_DeleteTimer.Stop(); - m_DeleteTimer = null; - } - } - - public override int BasePhysicalResistance => m_PhysicalResistance; - public override int BaseFireResistance => m_FireResistance; - public override int BaseColdResistance => m_ColdResistance; - public override int BasePoisonResistance => m_PoisonResistance; - public override int BaseEnergyResistance => m_EnergyResistance; - - [CommandProperty(AccessLevel.GameMaster)] - public int PhysicalResistanceSeed - { - get => m_PhysicalResistance; - set - { - m_PhysicalResistance = value; - UpdateResistances(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int FireResistSeed - { - get => m_FireResistance; - set - { - m_FireResistance = value; - UpdateResistances(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int ColdResistSeed - { - get => m_ColdResistance; - set - { - m_ColdResistance = value; - UpdateResistances(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int PoisonResistSeed - { - get => m_PoisonResistance; - set - { - m_PoisonResistance = value; - UpdateResistances(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int EnergyResistSeed - { - get => m_EnergyResistance; - set - { - m_EnergyResistance = value; - UpdateResistances(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int PhysicalDamage { get; set; } = 100; - - [CommandProperty(AccessLevel.GameMaster)] - public int FireDamage { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int ColdDamage { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int PoisonDamage { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int EnergyDamage { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int ChaosDamage { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int DirectDamage { get; set; } - - private long m_NextBreathTime; - - // Must be overridden in subclass to enable - public virtual bool HasBreath => false; - - // Base damage given is: CurrentHitPoints * BreathDamageScalar - public virtual double BreathDamageScalar => Core.AOS ? 0.16 : 0.05; - - // Min/max seconds until next breath - public virtual double BreathMinDelay => 30.0; - public virtual double BreathMaxDelay => 45.0; - - // Creature stops moving for 1.0 seconds while breathing - public virtual double BreathStallTime => 1.0; - - // Effect is sent 1.3 seconds after BreathAngerSound and BreathAngerAnimation is played - public virtual double BreathEffectDelay => 1.3; - - // Damage is given 1.0 seconds after effect is sent - public virtual double BreathDamageDelay => 1.0; - - public virtual int BreathRange => RangePerception; - - // Damage types - public virtual int BreathChaosDamage => 0; - public virtual int BreathPhysicalDamage => 0; - public virtual int BreathFireDamage => 100; - public virtual int BreathColdDamage => 0; - public virtual int BreathPoisonDamage => 0; - public virtual int BreathEnergyDamage => 0; - - // Is immune to breath damages - public virtual bool BreathImmune => false; - - // Effect details and sound - public virtual int BreathEffectItemID => 0x36D4; - public virtual int BreathEffectSpeed => 5; - public virtual int BreathEffectDuration => 0; - public virtual bool BreathEffectExplodes => false; - public virtual bool BreathEffectFixedDir => false; - public virtual int BreathEffectHue => 0; - public virtual int BreathEffectRenderMode => 0; - - public virtual int BreathEffectSound => 0x227; - - // Anger sound/animations - public virtual int BreathAngerSound => GetAngerSound(); - public virtual int BreathAngerAnimation => 12; - - public virtual void BreathStart(Mobile target) - { - BreathStallMovement(); - BreathPlayAngerSound(); - BreathPlayAngerAnimation(); - - Direction = GetDirectionTo(target); - - Timer.DelayCall(TimeSpan.FromSeconds(BreathEffectDelay), BreathEffect_Callback, target); - } - - public virtual void BreathStallMovement() - { - if (AIObject != null) - AIObject.NextMove = Core.TickCount + (int)(BreathStallTime * 1000); - } - - public virtual void BreathPlayAngerSound() - { - PlaySound(BreathAngerSound); - } - - public virtual void BreathPlayAngerAnimation() - { - Animate(BreathAngerAnimation, 5, 1, true, false, 0); - } - - public virtual void BreathEffect_Callback(Mobile target) - { - if (!target.Alive || !CanBeHarmful(target)) - return; - - BreathPlayEffectSound(); - BreathPlayEffect(target); - - Timer.DelayCall(TimeSpan.FromSeconds(BreathDamageDelay), BreathDamage_Callback, target); - } - - public virtual void BreathPlayEffectSound() - { - PlaySound(BreathEffectSound); - } - - public virtual void BreathPlayEffect(Mobile target) - { - Effects.SendMovingEffect(this, target, BreathEffectItemID, - BreathEffectSpeed, BreathEffectDuration, BreathEffectFixedDir, - BreathEffectExplodes, BreathEffectHue, BreathEffectRenderMode); - } - - public virtual void BreathDamage_Callback(Mobile target) - { - if (target is BaseCreature creature && creature.BreathImmune) - return; - - if (CanBeHarmful(target)) - { - DoHarmful(target); - BreathDealDamage(target); - } - } - - public virtual void BreathDealDamage(Mobile target) - { - if (!Evasion.CheckSpellEvasion(target)) - { - int physDamage = BreathPhysicalDamage; - int fireDamage = BreathFireDamage; - int coldDamage = BreathColdDamage; - int poisDamage = BreathPoisonDamage; - int nrgyDamage = BreathEnergyDamage; - - if (BreathChaosDamage > 0) - switch (Utility.Random(5)) - { - case 0: - physDamage += BreathChaosDamage; - break; - case 1: - fireDamage += BreathChaosDamage; - break; - case 2: - coldDamage += BreathChaosDamage; - break; - case 3: - poisDamage += BreathChaosDamage; - break; - case 4: - nrgyDamage += BreathChaosDamage; - break; - } - - if (physDamage == 0 && fireDamage == 0 && coldDamage == 0 && poisDamage == 0 && nrgyDamage == 0) - target.Damage(BreathComputeDamage(), this); // Unresistable damage even in AOS - else - AOS.Damage(target, this, BreathComputeDamage(), physDamage, fireDamage, coldDamage, poisDamage, - nrgyDamage); - } - } - - public virtual int BreathComputeDamage() - { - int damage = (int)(Hits * BreathDamageScalar); - - if (IsParagon) - damage = (int)(damage / Paragon.HitsBuff); - - if (damage > 200) - damage = 200; - - return damage; - } - - public void SpillAcid(int amount) - { - SpillAcid(null, amount); - } - - public void SpillAcid(Mobile target, int amount) - { - if ((target != null && target.Map == null) || Map == null) - return; - - for (int i = 0; i < amount; ++i) - { - Point3D loc; - Map map = Map; - - if (target != null && amount == 1) - { - loc = target.Location; - map = target.Map; - } - else - loc = map.GetRandomNearbyLocation(Location); - - Item acid = NewHarmfulItem(); - acid.MoveToWorld(loc, map); - } - } - - /* - Solen Style, override me for other mobiles/items: - kappa+acidslime, grizzles+whatever, etc. - */ - - public virtual Item NewHarmfulItem() => new PoolOfAcid(TimeSpan.FromSeconds(10), 30, 30); - - public virtual bool CanFlee => !m_Paragon; - - public DateTime EndFleeTime { get; set; } - - public virtual void StopFlee() - { - EndFleeTime = DateTime.MinValue; - } - - public virtual bool CheckFlee() - { - if (EndFleeTime == DateTime.MinValue) - return false; - - if (DateTime.UtcNow >= EndFleeTime) - { - StopFlee(); - return false; - } - - return true; - } - - public virtual void BeginFlee(TimeSpan maxDuration) - { - EndFleeTime = DateTime.UtcNow + maxDuration; - } - - public List Friends { get; private set; } - - public virtual bool AllowNewPetFriend => Friends == null || Friends.Count < 5; - - public virtual bool IsPetFriend(Mobile m) => Friends.Contains(m); - - public virtual void AddPetFriend(Mobile m) - { - Friends ??= new List(); - - Friends.Add(m); - } - - public virtual void RemovePetFriend(Mobile m) - { - Friends?.Remove(m); - } - - public virtual bool IsFriend(Mobile m) => - OppositionGroup?.IsEnemy(this, m) != true && m is BaseCreature c && m_Team == c.m_Team - && (m_bSummoned || m_Controlled) == (c.m_bSummoned || c.m_Controlled); - - public virtual Ethic EthicAllegiance => null; - - public enum Allegiance - { - None, - Ally, - Enemy - } - - public virtual Allegiance GetFactionAllegiance(Mobile mob) - { - if (mob == null || mob.Map != Faction.Facet || FactionAllegiance == null) - return Allegiance.None; - - Faction fac = Faction.Find(mob, true); - - if (fac == null) - return Allegiance.None; - - return fac == FactionAllegiance ? Allegiance.Ally : Allegiance.Enemy; - } - - public virtual Allegiance GetEthicAllegiance(Mobile mob) - { - if (mob == null || mob.Map != Faction.Facet || EthicAllegiance == null) - return Allegiance.None; - - Ethic ethic = Ethic.Find(mob, true); - - if (ethic == null) - return Allegiance.None; - - return ethic == EthicAllegiance ? Allegiance.Ally : Allegiance.Enemy; - } - - public virtual void AlterDamageScalarFrom(Mobile caster, ref double scalar) - { - } - - public virtual void AlterDamageScalarTo(Mobile target, ref double scalar) - { - } - - public virtual void AlterSpellDamageFrom(Mobile from, ref int damage) - { - } - - public virtual void AlterSpellDamageTo(Mobile to, ref int damage) - { - } - - public virtual void AlterMeleeDamageFrom(Mobile from, ref int damage) - { - } - - public virtual void AlterMeleeDamageTo(Mobile to, ref int damage) - { - } - - private static readonly Type[] m_Eggs = - { - typeof(FriedEggs), typeof(Eggs) - }; - - private static readonly Type[] m_Fish = - { - typeof(FishSteak), typeof(RawFishSteak) - }; - - private static readonly Type[] m_GrainsAndHay = - { - typeof(BreadLoaf), typeof(FrenchBread), typeof(SheafOfHay) - }; - - private static readonly Type[] m_Meat = - { - /* Cooked */ - typeof(Bacon), typeof(CookedBird), typeof(Sausage), - typeof(Ham), typeof(Ribs), typeof(LambLeg), - typeof(ChickenLeg), - - /* Uncooked */ - typeof(RawBird), typeof(RawRibs), typeof(RawLambLeg), - typeof(RawChickenLeg), - - /* Body Parts */ - typeof(Head), typeof(LeftArm), typeof(LeftLeg), - typeof(Torso), typeof(RightArm), typeof(RightLeg) - }; - - private static readonly Type[] m_FruitsAndVegies = - { - typeof(HoneydewMelon), typeof(YellowGourd), typeof(GreenGourd), - typeof(Banana), typeof(Bananas), typeof(Lemon), typeof(Lime), - typeof(Dates), typeof(Grapes), typeof(Peach), typeof(Pear), - typeof(Apple), typeof(Watermelon), typeof(Squash), - typeof(Cantaloupe), typeof(Carrot), typeof(Cabbage), - typeof(Onion), typeof(Lettuce), typeof(Pumpkin) - }; - - private static readonly Type[] m_Gold = - { - // white wyrms eat gold.. - typeof(Gold) - }; - - public virtual bool CheckFoodPreference(Item f) - { - if (CheckFoodPreference(f, FoodType.Eggs, m_Eggs)) - return true; - - if (CheckFoodPreference(f, FoodType.Fish, m_Fish)) - return true; - - if (CheckFoodPreference(f, FoodType.GrainsAndHay, m_GrainsAndHay)) - return true; - - if (CheckFoodPreference(f, FoodType.Meat, m_Meat)) - return true; - - if (CheckFoodPreference(f, FoodType.FruitsAndVegies, m_FruitsAndVegies)) - return true; - - if (CheckFoodPreference(f, FoodType.Gold, m_Gold)) - return true; - - return false; - } - - public virtual bool CheckFoodPreference(Item fed, FoodType type, Type[] types) - { - if ((FavoriteFood & type) == 0) - return false; - - Type fedType = fed.GetType(); - bool contains = false; - - for (int i = 0; !contains && i < types.Length; ++i) - contains = fedType == types[i]; - - return contains; - } - - public virtual bool CheckFeed(Mobile from, Item dropped) - { - if (!IsDeadPet && Controlled && (ControlMaster == from || IsPetFriend(from))) - { - Item f = dropped; - - if (CheckFoodPreference(f)) - { - int amount = f.Amount; - - if (amount > 0) - { - int stamGain; - - if (f is Gold) - stamGain = amount - 50; - else - stamGain = amount * 15 - 50; - - if (stamGain > 0) - Stam += stamGain; - - if (Core.SE) + get => m_bSummoned; + set { - if (m_Loyalty < MaxLoyalty) m_Loyalty = MaxLoyalty; + if (m_bSummoned == value) + return; + + NextReacquireTime = Core.TickCount; + + m_bSummoned = value; + Delta(MobileDelta.Noto); + + InvalidateProperties(); } - else + } + + [CommandProperty(AccessLevel.Administrator)] + public int ControlSlots { get; set; } = 1; + + public virtual bool NoHouseRestrictions => false; + public virtual bool IsHouseSummonable => false; + + public virtual bool AutoDispel => false; + public virtual double AutoDispelChance => Core.SE ? .10 : 1.0; + + public virtual bool IsScaryToPets => false; + public virtual bool IsScaredOfScaryThings => true; + + public virtual bool CanRummageCorpses => false; + + public virtual bool DeleteOnRelease => m_bSummoned; + + public virtual bool CanDrop => IsBonded; + + public virtual int TreasureMapLevel => -1; + + public virtual bool IgnoreYoungProtection => false; + + public bool NoKillAwards { get; set; } + + public virtual bool GivesMLMinorArtifact => false; + + /* To save on cpu usage, RunUO creatures only reacquire creatures under the following circumstances: + * - 10 seconds have elapsed since the last time it tried + * - The creature was attacked + * - Some creatures, like dragons, will reacquire when they see someone move + * + * This functionality appears to be implemented on OSI as well + */ + + public long NextReacquireTime { get; set; } + + public virtual TimeSpan ReacquireDelay => TimeSpan.FromSeconds(10.0); + public virtual bool ReacquireOnMovement => false; + public virtual bool AcquireOnApproach => m_Paragon; + public virtual int AcquireOnApproachRange => 10; + + public static bool Summoning { get; set; } + + public virtual bool CanBreath => HasBreath && !Summoned; + public virtual bool IsDispellable => Summoned && !IsAnimatedDead; + + public virtual bool + PlayerRangeSensitive // If they are following a waypoint, they'll continue to follow it even if players aren't around + => CurrentWayPoint == null; + + public virtual bool ReturnsToHome => + SeeksHome && Home != Point3D.Zero && !m_ReturnQueued && !Controlled && !Summoned; + + // used for deleting untamed creatures [in houses] + + [CommandProperty(AccessLevel.GameMaster)] + public bool RemoveIfUntamed { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int RemoveStep { get; set; } + + public virtual bool CanGiveMLQuest => MLQuests.Count != 0; + public virtual bool StaticMLQuester => true; + + public virtual bool CanShout => false; + + public static bool BondingEnabled { get; private set; } + + public virtual bool IsBondable => BondingEnabled && !Summoned; + public virtual TimeSpan BondingDelay => TimeSpan.FromDays(7.0); + public virtual TimeSpan BondingAbandonDelay => TimeSpan.FromDays(1.0); + + public override bool CanRegenHits => !IsDeadPet && base.CanRegenHits; + public override bool CanRegenStam => !IsParagon && !IsDeadPet && base.CanRegenStam; + public override bool CanRegenMana => !IsDeadPet && base.CanRegenMana; + + public override bool IsDeadBondedPet => IsDeadPet; + + [CommandProperty(AccessLevel.GameMaster)] + public Spawner MySpawner => Spawner as Spawner; + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile LastOwner + { + get { - for (int i = 0; i < amount; ++i) - if (m_Loyalty < MaxLoyalty && Utility.RandomDouble() <= 0.5) - m_Loyalty += 10; + if (Owners == null || Owners.Count == 0) + return null; + + return Owners[^1]; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsBonded + { + get => m_IsBonded; + set + { + m_IsBonded = value; + InvalidateProperties(); + } + } + + public bool IsDeadPet { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime BondingBegin { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime OwnerAbandonTime { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan DeleteTimeLeft + { + get + { + if (m_DeleteTimer?.Running == true) + return m_DeleteTimer.Next - DateTime.UtcNow; + + return TimeSpan.Zero; + } + } + + public override int BasePhysicalResistance => m_PhysicalResistance; + public override int BaseFireResistance => m_FireResistance; + public override int BaseColdResistance => m_ColdResistance; + public override int BasePoisonResistance => m_PoisonResistance; + public override int BaseEnergyResistance => m_EnergyResistance; + + [CommandProperty(AccessLevel.GameMaster)] + public int PhysicalResistanceSeed + { + get => m_PhysicalResistance; + set + { + m_PhysicalResistance = value; + UpdateResistances(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int FireResistSeed + { + get => m_FireResistance; + set + { + m_FireResistance = value; + UpdateResistances(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int ColdResistSeed + { + get => m_ColdResistance; + set + { + m_ColdResistance = value; + UpdateResistances(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int PoisonResistSeed + { + get => m_PoisonResistance; + set + { + m_PoisonResistance = value; + UpdateResistances(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int EnergyResistSeed + { + get => m_EnergyResistance; + set + { + m_EnergyResistance = value; + UpdateResistances(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int PhysicalDamage { get; set; } = 100; + + [CommandProperty(AccessLevel.GameMaster)] + public int FireDamage { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int ColdDamage { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int PoisonDamage { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int EnergyDamage { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int ChaosDamage { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int DirectDamage { get; set; } + + // Must be overridden in subclass to enable + public virtual bool HasBreath => false; + + // Base damage given is: CurrentHitPoints * BreathDamageScalar + public virtual double BreathDamageScalar => Core.AOS ? 0.16 : 0.05; + + // Min/max seconds until next breath + public virtual double BreathMinDelay => 30.0; + public virtual double BreathMaxDelay => 45.0; + + // Creature stops moving for 1.0 seconds while breathing + public virtual double BreathStallTime => 1.0; + + // Effect is sent 1.3 seconds after BreathAngerSound and BreathAngerAnimation is played + public virtual double BreathEffectDelay => 1.3; + + // Damage is given 1.0 seconds after effect is sent + public virtual double BreathDamageDelay => 1.0; + + public virtual int BreathRange => RangePerception; + + // Damage types + public virtual int BreathChaosDamage => 0; + public virtual int BreathPhysicalDamage => 0; + public virtual int BreathFireDamage => 100; + public virtual int BreathColdDamage => 0; + public virtual int BreathPoisonDamage => 0; + public virtual int BreathEnergyDamage => 0; + + // Is immune to breath damages + public virtual bool BreathImmune => false; + + // Effect details and sound + public virtual int BreathEffectItemID => 0x36D4; + public virtual int BreathEffectSpeed => 5; + public virtual int BreathEffectDuration => 0; + public virtual bool BreathEffectExplodes => false; + public virtual bool BreathEffectFixedDir => false; + public virtual int BreathEffectHue => 0; + public virtual int BreathEffectRenderMode => 0; + + public virtual int BreathEffectSound => 0x227; + + // Anger sound/animations + public virtual int BreathAngerSound => GetAngerSound(); + public virtual int BreathAngerAnimation => 12; + + public virtual bool CanFlee => !m_Paragon; + + public DateTime EndFleeTime { get; set; } + + public List Friends { get; private set; } + + public virtual bool AllowNewPetFriend => Friends == null || Friends.Count < 5; + + public virtual Ethic EthicAllegiance => null; + + public virtual int Feathers => 0; + public virtual int Wool => 0; + + public virtual MeatType MeatType => MeatType.Ribs; + public virtual int Meat => 0; + + public virtual int Hides => 0; + public virtual HideType HideType => HideType.Regular; + + public virtual int Scales => 0; + public virtual ScaleType ScaleType => ScaleType.Red; + + public virtual bool CanTeach => false; + + public virtual bool CanHeal => false; + public virtual bool CanHealOwner => false; + public virtual double HealScalar => 1.0; + + public virtual int HealSound => 0x57; + public virtual int HealStartRange => 2; + public virtual int HealEndRange => RangePerception; + public virtual double HealTrigger => 0.78; + public virtual double HealDelay => 6.5; + public virtual double HealInterval => 0.0; + public virtual bool HealFully => true; + public virtual double HealOwnerTrigger => 0.78; + public virtual double HealOwnerDelay => 6.5; + public virtual double HealOwnerInterval => 30.0; + public virtual bool HealOwnerFully => false; + + public bool IsHealing => m_HealTimer != null; + + public virtual bool HasAura => false; + public virtual TimeSpan AuraInterval => TimeSpan.FromSeconds(5); + public virtual int AuraRange => 4; + + public virtual int AuraBaseDamage => 5; + public virtual int AuraPhysicalDamage => 0; + public virtual int AuraFireDamage => 100; + public virtual int AuraColdDamage => 0; + public virtual int AuraPoisonDamage => 0; + public virtual int AuraEnergyDamage => 0; + public virtual int AuraChaosDamage => 0; + + public HonorContext ReceivedHonorContext { get; set; } + + public List MLQuests + { + get + { + if (m_MLQuests == null) + { + if (StaticMLQuester) + m_MLQuests = MLQuestSystem.FindQuestList(GetType()); + else + m_MLQuests = ConstructQuestList(); + + if (m_MLQuests == null) + return + MLQuestSystem + .EmptyList; // return EmptyList, but don't cache it (run construction again next time) + } + + return m_MLQuests; + } + } + + public virtual WeaponAbility GetWeaponAbility() => null; + + public virtual bool IsEnemy(Mobile m) + { + if (OppositionGroup?.IsEnemy(this, m) == true) + return true; + + if (m is BaseGuard) + return false; + + if (GetFactionAllegiance(m) == Allegiance.Ally) + return false; + + var ourEthic = EthicAllegiance; + var pl = Ethics.Player.Find(m, true); + + if (pl?.IsShielded == true && (ourEthic == null || ourEthic == pl.Ethic)) + return false; + + if (m is PlayerMobile mobile && mobile.HonorActive) + return false; + + if (!(m is BaseCreature c) || m is MilitiaFighter) + return true; + + if (TransformationSpellHelper.UnderTransformation(m, typeof(EtherealVoyageSpell))) + return false; + + if (FightMode == FightMode.Evil && m.Karma < 0 || c.FightMode == FightMode.Evil && Karma < 0) + return true; + + return m_Team != c.m_Team || (m_bSummoned || m_Controlled) != (c.m_bSummoned || c.m_Controlled); + } + + public override string ApplyNameSuffix(string suffix) + { + if (IsParagon && !GivesMLMinorArtifact) suffix = suffix.Length == 0 ? "(Paragon)" : $"{suffix} (Paragon)"; + + return base.ApplyNameSuffix(suffix); + } + + public virtual bool CheckControlChance(Mobile m) + { + if (GetControlChance(m) > Utility.RandomDouble()) + { + Loyalty += 1; + return true; } - /* if (happier )*/ - // looks like in OSI pets say they are happier even if they are at maximum loyalty - SayTo(from, 502060); // Your pet looks happier. + PlaySound(GetAngerSound()); if (Body.IsAnimal) - Animate(3, 5, 1, true, false, 0); + Animate(10, 5, 1, true, false, 0); else if (Body.IsMonster) - Animate(17, 5, 1, true, false, 0); + Animate(18, 5, 1, true, false, 0); - if (IsBondable && !IsBonded) - { - Mobile master = m_ControlMaster; - - if (master != null && master == from) // So friends can't start the bonding process - { - if (MinTameSkill <= 29.1 || master.Skills.AnimalTaming.Base >= MinTameSkill || - OverrideBondingReqs() || - (Core.ML && master.Skills.AnimalTaming.Value >= MinTameSkill)) - { - if (BondingBegin == DateTime.MinValue) - { - BondingBegin = DateTime.UtcNow; - } - else if (BondingBegin + BondingDelay <= DateTime.UtcNow) - { - IsBonded = true; - BondingBegin = DateTime.MinValue; - from.SendLocalizedMessage(1049666); // Your pet has bonded with you! - } - } - else if (Core.ML) - { - from.SendLocalizedMessage( - 1075268); // Your pet cannot form a bond with you until your animal taming ability has risen. - } - } - } - - dropped.Delete(); - return true; - } + Loyalty -= 3; + return false; } - } - return false; - } + public virtual bool CanBeControlledBy(Mobile m) => GetControlChance(m) > 0.0; - public virtual void OnActionWander() - { - } - - public virtual void OnActionCombat() - { - } - - public virtual void OnActionGuard() - { - } - - public virtual void OnActionFlee() - { - } - - public virtual void OnActionInteract() - { - } - - public virtual void OnActionBackoff() - { - } - - public virtual int Feathers => 0; - public virtual int Wool => 0; - - public virtual MeatType MeatType => MeatType.Ribs; - public virtual int Meat => 0; - - public virtual int Hides => 0; - public virtual HideType HideType => HideType.Regular; - - public virtual int Scales => 0; - public virtual ScaleType ScaleType => ScaleType.Red; - - public virtual bool CanTeach => false; - - public virtual bool CheckTeach(SkillName skill, Mobile from) - { - if (!CanTeach) - return false; - - if (skill == SkillName.Stealth && from.Skills.Hiding.Base < Stealth.HidingRequirement) - return false; - - if (skill == SkillName.RemoveTrap && (from.Skills.Lockpicking.Base < 50.0 || - from.Skills.DetectHidden.Base < 50.0)) - return false; - - if (!Core.AOS && (skill == SkillName.Focus || skill == SkillName.Chivalry || skill == SkillName.Necromancy)) - return false; - - return true; - } - - public enum TeachResult - { - Success, - Failure, - KnowsMoreThanMe, - KnowsWhatIKnow, - SkillNotRaisable, - NotEnoughFreePoints - } - - public virtual TeachResult CheckTeachSkills(SkillName skill, Mobile m, int maxPointsToLearn, ref int pointsToLearn, - bool doTeach) - { - if (!CheckTeach(skill, m) || !m.CheckAlive()) - return TeachResult.Failure; - - Skill ourSkill = Skills[skill]; - Skill theirSkill = m.Skills[skill]; - - if (ourSkill == null || theirSkill == null) - return TeachResult.Failure; - - int baseToSet = ourSkill.BaseFixedPoint / 3; - - if (baseToSet > 420) - baseToSet = 420; - else if (baseToSet < 200) - return TeachResult.Failure; - - if (baseToSet > theirSkill.CapFixedPoint) - baseToSet = theirSkill.CapFixedPoint; - - pointsToLearn = baseToSet - theirSkill.BaseFixedPoint; - - if (maxPointsToLearn > 0 && pointsToLearn > maxPointsToLearn) - { - pointsToLearn = maxPointsToLearn; - baseToSet = theirSkill.BaseFixedPoint + pointsToLearn; - } - - if (pointsToLearn < 0) - return TeachResult.KnowsMoreThanMe; - - if (pointsToLearn == 0) - return TeachResult.KnowsWhatIKnow; - - if (theirSkill.Lock != SkillLock.Up) - return TeachResult.SkillNotRaisable; - - int freePoints = Math.Max(m.Skills.Cap - m.Skills.Total, 0); - int freeablePoints = 0; - - for (int i = 0; freePoints + freeablePoints < pointsToLearn && i < m.Skills.Length; ++i) - { - Skill sk = m.Skills[i]; - - if (sk == theirSkill || sk.Lock != SkillLock.Down) - continue; - - freeablePoints += sk.BaseFixedPoint; - } - - if (freePoints + freeablePoints == 0) - return TeachResult.NotEnoughFreePoints; - - if (freePoints + freeablePoints < pointsToLearn) - { - pointsToLearn = freePoints + freeablePoints; - baseToSet = theirSkill.BaseFixedPoint + pointsToLearn; - } - - if (doTeach) - { - int need = pointsToLearn - freePoints; - - for (int i = 0; need > 0 && i < m.Skills.Length; ++i) + public virtual double GetControlChance(Mobile m, bool useBaseSkill = false) { - Skill sk = m.Skills[i]; + if (MinTameSkill <= 29.1 || m_bSummoned || m.AccessLevel >= AccessLevel.GameMaster) + return 1.0; - if (sk == theirSkill || sk.Lock != SkillLock.Down) - continue; + var dMinTameSkill = MinTameSkill; - if (sk.BaseFixedPoint < need) - { - need -= sk.BaseFixedPoint; - sk.BaseFixedPoint = 0; - } - else - { - sk.BaseFixedPoint -= need; - need = 0; - } - } + if (dMinTameSkill > -24.9 && AnimalTaming.CheckMastery(m, this)) + dMinTameSkill = -24.9; - /* Sanity check */ - if (baseToSet > theirSkill.CapFixedPoint || - m.Skills.Total - theirSkill.BaseFixedPoint + baseToSet > m.Skills.Cap) - return TeachResult.NotEnoughFreePoints; + var taming = + (int)((useBaseSkill ? m.Skills.AnimalTaming.Base : m.Skills.AnimalTaming.Value) * 10); + var lore = + (int)((useBaseSkill ? m.Skills.AnimalLore.Base : m.Skills.AnimalLore.Value) * 10); + int bonus, chance = 700; - theirSkill.BaseFixedPoint = baseToSet; - } - - return TeachResult.Success; - } - - public virtual bool CheckTeachingMatch(Mobile m) - { - if (m_Teaching == (SkillName)(-1)) - return false; - - if (m is PlayerMobile mobile) - return mobile.Learning == m_Teaching; - - return true; - } - - private SkillName m_Teaching = (SkillName)(-1); - - public virtual bool Teach(SkillName skill, Mobile m, int maxPointsToLearn, bool doTeach) - { - int pointsToLearn = 0; - TeachResult res = CheckTeachSkills(skill, m, maxPointsToLearn, ref pointsToLearn, doTeach); - - switch (res) - { - case TeachResult.KnowsMoreThanMe: - { - Say(501508); // I cannot teach thee, for thou knowest more than I! - break; - } - case TeachResult.KnowsWhatIKnow: - { - Say(501509); // I cannot teach thee, for thou knowest all I can teach! - break; - } - case TeachResult.NotEnoughFreePoints: - case TeachResult.SkillNotRaisable: - { - // Make sure this skill is marked to raise. If you are near the skill cap (700 points) you may need to lose some points in another skill first. - m.SendLocalizedMessage(501510, "", 0x22); - break; - } - case TeachResult.Success: - { - if (doTeach) + if (Core.ML) { - Say(501539); // Let me show thee something of how this is done. - m.SendLocalizedMessage(501540); // Your skill level increases. + var SkillBonus = taming - (int)(dMinTameSkill * 10); + var LoreBonus = lore - (int)(dMinTameSkill * 10); - m_Teaching = (SkillName)(-1); + var SkillMod = 6; + var LoreMod = 6; - if (m is PlayerMobile mobile) - mobile.Learning = (SkillName)(-1); + if (SkillBonus < 0) + SkillMod = 28; + + if (LoreBonus < 0) + LoreMod = 14; + + SkillBonus *= SkillMod; + LoreBonus *= LoreMod; + + bonus = (SkillBonus + LoreBonus) / 2; } else { - // I will teach thee all I know, if paid the amount in full. The price is: - Say(1019077, AffixType.Append, $" {pointsToLearn}", ""); - Say(1043108); // For less I shall teach thee less. + var difficulty = (int)(dMinTameSkill * 10); + var weighted = (taming * 4 + lore) / 5; + bonus = weighted - difficulty; - m_Teaching = skill; + if (bonus <= 0) + bonus *= 14; + else + bonus *= 6; + } - if (m is PlayerMobile mobile) - mobile.Learning = skill; + chance += bonus; + + if (chance >= 0 && chance < 200) + chance = 200; + else if (chance > 990) + chance = 990; + + chance -= (MaxLoyalty - m_Loyalty) * 10; + + return (double)chance / 1000; + } + + public override void Damage(int amount, Mobile from) + { + var oldHits = Hits; + + if (Core.AOS && !Summoned && Controlled && Utility.RandomDouble() < 0.2) + amount = (int)(amount * BonusPetDamageScalar); + + if (EvilOmenSpell.TryEndEffect(this)) + amount = (int)(amount * 1.25); + + var oath = BloodOathSpell.GetBloodOath(from); + + if (oath == this) + { + amount = (int)(amount * 1.1); + from.Damage(amount, from); + } + + base.Damage(amount, from); + + if (SubdueBeforeTame && !Controlled && oldHits > HitsMax / 10 && Hits <= HitsMax / 10) + PublicOverheadMessage( + MessageType.Regular, + 0x3B2, + false, + "* The creature has been beaten into subjugation! *" + ); + } + + public override void SetLocation(Point3D newLocation, bool isTeleport) + { + base.SetLocation(newLocation, isTeleport); + + if (isTeleport) + AIObject?.OnTeleported(); + } + + public override void OnBeforeSpawn(Point3D location, Map m) + { + if (Paragon.CheckConvert(this, location, m)) + IsParagon = true; + + base.OnBeforeSpawn(location, m); + } + + public override ApplyPoisonResult ApplyPoison(Mobile from, Poison poison) + { + if (!Alive || IsDeadPet) + return ApplyPoisonResult.Immune; + + if (EvilOmenSpell.TryEndEffect(this)) + poison = PoisonImpl.IncreaseLevel(poison); + + var result = base.ApplyPoison(from, poison); + + if (from != null && result == ApplyPoisonResult.Poisoned && PoisonTimer is PoisonImpl.PoisonTimer timer) + timer.From = from; + + return result; + } + + public override bool CheckPoisonImmunity(Mobile from, Poison poison) => + base.CheckPoisonImmunity(from, poison) || + (m_Paragon ? PoisonImpl.IncreaseLevel(PoisonImmune) : PoisonImmune)?.Level >= poison.Level; + + public void Unpacify() + { + BardEndTime = DateTime.UtcNow; + BardPacified = false; + } + + public virtual void CheckDistracted(Mobile from) + { + if (Utility.RandomDouble() < .10) + { + ControlTarget = from; + ControlOrder = OrderType.Attack; + Combatant = from; + Warmode = true; + } + } + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + if (BardPacified && (HitsMax - Hits) * 0.001 > Utility.RandomDouble()) + Unpacify(); + + int disruptThreshold; + // NPCs can use bandages too! + if (!Core.AOS) + disruptThreshold = 0; + else if (from?.Player == true) + disruptThreshold = 18; + else + disruptThreshold = 25; + + if (amount > disruptThreshold) + { + var c = BandageContext.GetContext(this); + + c?.Slip(); + } + + if (Confidence.IsRegenerating(this)) + Confidence.StopRegenerating(this); + + WeightOverloading.FatigueOnDamage(this, amount); + + var speechType = SpeechType; + + if (speechType != null && !willKill) + speechType.OnDamage(this, amount); + + ReceivedHonorContext?.OnTargetDamaged(from, amount); + + if (!willKill) + { + if (CanBeDistracted && ControlOrder == OrderType.Follow) CheckDistracted(from); + } + else if (from is PlayerMobile mobile) + { + Timer.DelayCall(TimeSpan.FromSeconds(10), mobile.RecoverAmmo); + } + + base.OnDamage(amount, from, willKill); + } + + public virtual void OnDamagedBySpell(Mobile from) + { + if (CanBeDistracted && ControlOrder == OrderType.Follow) CheckDistracted(from); + } + + public virtual void OnHarmfulSpell(Mobile from) + { + } + + public virtual void CheckReflect(Mobile caster, ref bool reflect) + { + } + + public virtual void OnCarve(Mobile from, Corpse corpse, Item with) + { + var feathers = Feathers; + var wool = Wool; + var meat = Meat; + var hides = Hides; + var scales = Scales; + + if (feathers == 0 && wool == 0 && meat == 0 && hides == 0 && scales == 0 || Summoned || IsBonded || + corpse.Animated) + { + if (corpse.Animated) + corpse.SendLocalizedMessageTo(from, 500464); // Use this on corpses to carve away meat and hide + else + from.SendLocalizedMessage(500485); // You see nothing useful to carve from the corpse. + } + else + { + if (Core.ML && from.Race == Race.Human) + hides = (int)Math.Ceiling(hides * 1.1); // 10% bonus only applies to hides, ore & logs + + if (corpse.Map == Map.Felucca) + { + feathers *= 2; + wool *= 2; + hides *= 2; + + if (Core.ML) + { + meat *= 2; + scales *= 2; + } + } + + new Blood(0x122D).MoveToWorld(corpse.Location, corpse.Map); + + if (feathers != 0) + { + corpse.AddCarvedItem(new Feather(feathers), from); + from.SendLocalizedMessage(500479); // You pluck the bird. The feathers are now on the corpse. + } + + if (wool != 0) + { + corpse.AddCarvedItem(new TaintedWool(wool), from); + from.SendLocalizedMessage(500483); // You shear it, and the wool is now on the corpse. + } + + if (meat != 0) + { + if (MeatType == MeatType.Ribs) + corpse.AddCarvedItem(new RawRibs(meat), from); + else if (MeatType == MeatType.Bird) + corpse.AddCarvedItem(new RawBird(meat), from); + else if (MeatType == MeatType.LambLeg) + corpse.AddCarvedItem(new RawLambLeg(meat), from); + + from.SendLocalizedMessage(500467); // You carve some meat, which remains on the corpse. + } + + if (hides != 0) + { + var holding = from.Weapon as Item; + + if (Core.AOS && holding is SkinningKnife) + { + var leather = HideType switch + { + HideType.Regular => (Item)new Leather(hides), + HideType.Spined => new SpinedLeather(hides), + HideType.Horned => new HornedLeather(hides), + HideType.Barbed => new BarbedLeather(hides), + _ => null + }; + + if (leather != null) + { + if (!from.PlaceInBackpack(leather)) + { + corpse.DropItem(leather); + from.SendLocalizedMessage(500471); // You skin it, and the hides are now in the corpse. + } + else + { + from.SendLocalizedMessage( + 1073555 + ); // You skin it and place the cut-up hides in your backpack. + } + } + } + else + { + if (HideType == HideType.Regular) + corpse.DropItem(new Hides(hides)); + else if (HideType == HideType.Spined) + corpse.DropItem(new SpinedHides(hides)); + else if (HideType == HideType.Horned) + corpse.DropItem(new HornedHides(hides)); + else if (HideType == HideType.Barbed) + corpse.DropItem(new BarbedHides(hides)); + + from.SendLocalizedMessage(500471); // You skin it, and the hides are now in the corpse. + } + } + + if (scales != 0) + { + var sc = ScaleType; + + switch (sc) + { + case ScaleType.Red: + corpse.AddCarvedItem(new RedScales(scales), from); + break; + case ScaleType.Yellow: + corpse.AddCarvedItem(new YellowScales(scales), from); + break; + case ScaleType.Black: + corpse.AddCarvedItem(new BlackScales(scales), from); + break; + case ScaleType.Green: + corpse.AddCarvedItem(new GreenScales(scales), from); + break; + case ScaleType.White: + corpse.AddCarvedItem(new WhiteScales(scales), from); + break; + case ScaleType.Blue: + corpse.AddCarvedItem(new BlueScales(scales), from); + break; + case ScaleType.All: + { + corpse.AddCarvedItem(new RedScales(scales), from); + corpse.AddCarvedItem(new YellowScales(scales), from); + corpse.AddCarvedItem(new BlackScales(scales), from); + corpse.AddCarvedItem(new GreenScales(scales), from); + corpse.AddCarvedItem(new WhiteScales(scales), from); + corpse.AddCarvedItem(new BlueScales(scales), from); + break; + } + } + + from.SendMessage("You cut away some scales, but they remain on the corpse."); + } + + corpse.Carved = true; + + if (corpse.IsCriminalAction(from)) + from.CriminalAction(true); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(19); // version + + writer.Write((int)m_CurrentAI); + writer.Write((int)m_DefaultAI); + + writer.Write(RangePerception); + writer.Write(RangeFight); + + writer.Write(m_Team); + + writer.Write(ActiveSpeed); + writer.Write(PassiveSpeed); + writer.Write(m_CurrentSpeed); + + writer.Write(m_Home.X); + writer.Write(m_Home.Y); + writer.Write(m_Home.Z); + + // Version 1 + writer.Write(RangeHome); + + var i = 0; + + writer.Write(m_SpellAttack.Count); + for (i = 0; i < m_SpellAttack.Count; i++) writer.Write(m_SpellAttack[i].ToString()); + + writer.Write(m_SpellDefense.Count); + for (i = 0; i < m_SpellDefense.Count; i++) writer.Write(m_SpellDefense[i].ToString()); + + // Version 2 + writer.Write((int)FightMode); + + writer.Write(m_Controlled); + writer.Write(m_ControlMaster); + writer.Write(ControlTarget); + writer.Write(ControlDest); + writer.Write((int)m_ControlOrder); + writer.Write(MinTameSkill); + // Removed in version 9 + // writer.Write( (double) m_dMaxTameSkill ); + writer.Write(m_bTamable); + writer.Write(m_bSummoned); + + if (m_bSummoned) + writer.WriteDeltaTime(SummonEnd); + + writer.Write(ControlSlots); + + // Version 3 + writer.Write(m_Loyalty); + + // Version 4 + writer.Write(CurrentWayPoint); + + // Verison 5 + writer.Write(m_SummonMaster); + + // Version 6 + writer.Write(HitsMaxSeed); + writer.Write(StamMaxSeed); + writer.Write(ManaMaxSeed); + writer.Write(m_DamageMin); + writer.Write(m_DamageMax); + + // Version 7 + writer.Write(m_PhysicalResistance); + writer.Write(PhysicalDamage); + + writer.Write(m_FireResistance); + writer.Write(FireDamage); + + writer.Write(m_ColdResistance); + writer.Write(ColdDamage); + + writer.Write(m_PoisonResistance); + writer.Write(PoisonDamage); + + writer.Write(m_EnergyResistance); + writer.Write(EnergyDamage); + + // Version 8 + writer.Write(Owners, true); + + // Version 10 + writer.Write(IsDeadPet); + writer.Write(m_IsBonded); + writer.Write(BondingBegin); + writer.Write(OwnerAbandonTime); + + // Version 11 + writer.Write(m_HasGeneratedLoot); + + // Version 12 + writer.Write(m_Paragon); + + // Version 13 + writer.Write(Friends?.Count > 0); + + if (Friends?.Count > 0) + writer.Write(Friends, true); + + // Version 14 + writer.Write(RemoveIfUntamed); + writer.Write(RemoveStep); + + // Version 17 + if (IsStabled || Controlled && ControlMaster != null) + writer.Write(TimeSpan.Zero); + else + writer.Write(DeleteTimeLeft); + + // Version 18 + writer.Write(CorpseNameOverride); + + // Version 19 + writer.Write(HomeMap); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_CurrentAI = (AIType)reader.ReadInt(); + m_DefaultAI = (AIType)reader.ReadInt(); + + RangePerception = reader.ReadInt(); + RangeFight = reader.ReadInt(); + + m_Team = reader.ReadInt(); + + ActiveSpeed = reader.ReadDouble(); + PassiveSpeed = reader.ReadDouble(); + m_CurrentSpeed = reader.ReadDouble(); + + if (RangePerception == OldRangePerception) + RangePerception = DefaultRangePerception; + + m_Home.X = reader.ReadInt(); + m_Home.Y = reader.ReadInt(); + m_Home.Z = reader.ReadInt(); + + if (version >= 1) + { + RangeHome = reader.ReadInt(); + + var iCount = reader.ReadInt(); + for (var i = 0; i < iCount; i++) + { + var str = reader.ReadString(); + var type = Type.GetType(str); + + if (type != null) m_SpellAttack.Add(type); + } + + iCount = reader.ReadInt(); + for (var i = 0; i < iCount; i++) + { + var str = reader.ReadString(); + var type = Type.GetType(str); + + if (type != null) m_SpellDefense.Add(type); + } + } + else + { + RangeHome = 0; + } + + if (version >= 2) + { + FightMode = (FightMode)reader.ReadInt(); + + m_Controlled = reader.ReadBool(); + m_ControlMaster = reader.ReadMobile(); + ControlTarget = reader.ReadMobile(); + ControlDest = reader.ReadPoint3D(); + m_ControlOrder = (OrderType)reader.ReadInt(); + + MinTameSkill = reader.ReadDouble(); + + if (version < 9) + reader.ReadDouble(); + + m_bTamable = reader.ReadBool(); + m_bSummoned = reader.ReadBool(); + + if (m_bSummoned) + { + SummonEnd = reader.ReadDeltaTime(); + new UnsummonTimer(m_ControlMaster, this, SummonEnd - DateTime.UtcNow).Start(); + } + + ControlSlots = reader.ReadInt(); + } + else + { + FightMode = FightMode.Closest; + + m_Controlled = false; + m_ControlMaster = null; + ControlTarget = null; + m_ControlOrder = OrderType.None; + } + + if (version >= 3) + m_Loyalty = reader.ReadInt(); + else + m_Loyalty = MaxLoyalty; // Wonderfully Happy + + if (version >= 4) + CurrentWayPoint = reader.ReadItem() as WayPoint; + + if (version >= 5) + m_SummonMaster = reader.ReadMobile(); + + if (version >= 6) + { + HitsMaxSeed = reader.ReadInt(); + StamMaxSeed = reader.ReadInt(); + ManaMaxSeed = reader.ReadInt(); + m_DamageMin = reader.ReadInt(); + m_DamageMax = reader.ReadInt(); + } + + if (version >= 7) + { + m_PhysicalResistance = reader.ReadInt(); + PhysicalDamage = reader.ReadInt(); + + m_FireResistance = reader.ReadInt(); + FireDamage = reader.ReadInt(); + + m_ColdResistance = reader.ReadInt(); + ColdDamage = reader.ReadInt(); + + m_PoisonResistance = reader.ReadInt(); + PoisonDamage = reader.ReadInt(); + + m_EnergyResistance = reader.ReadInt(); + EnergyDamage = reader.ReadInt(); + } + + if (version >= 8) + Owners = reader.ReadStrongMobileList(); + else + Owners = new List(); + + if (version >= 10) + { + IsDeadPet = reader.ReadBool(); + m_IsBonded = reader.ReadBool(); + BondingBegin = reader.ReadDateTime(); + OwnerAbandonTime = reader.ReadDateTime(); + } + + if (version >= 11) + m_HasGeneratedLoot = reader.ReadBool(); + else + m_HasGeneratedLoot = true; + + if (version >= 12) + m_Paragon = reader.ReadBool(); + else + m_Paragon = false; + + if (version >= 13 && reader.ReadBool()) + Friends = reader.ReadStrongMobileList(); + else if (version < 13 && m_ControlOrder >= OrderType.Unfriend) + ++m_ControlOrder; + + if (version < 16 && Loyalty != MaxLoyalty) + Loyalty *= 10; + + var activeSpeed = ActiveSpeed; + var passiveSpeed = PassiveSpeed; + + SpeedInfo.GetSpeeds(this, ref activeSpeed, ref passiveSpeed); + + var isStandardActive = false; + for (var i = 0; !isStandardActive && i < m_StandardActiveSpeeds.Length; ++i) + isStandardActive = ActiveSpeed == m_StandardActiveSpeeds[i]; + + var isStandardPassive = false; + for (var i = 0; !isStandardPassive && i < m_StandardPassiveSpeeds.Length; ++i) + isStandardPassive = PassiveSpeed == m_StandardPassiveSpeeds[i]; + + if (isStandardActive && m_CurrentSpeed == ActiveSpeed) + m_CurrentSpeed = activeSpeed; + else if (isStandardPassive && m_CurrentSpeed == PassiveSpeed) + m_CurrentSpeed = passiveSpeed; + + if (isStandardActive && !m_Paragon) + ActiveSpeed = activeSpeed; + + if (isStandardPassive && !m_Paragon) + PassiveSpeed = passiveSpeed; + + if (version >= 14) + { + RemoveIfUntamed = reader.ReadBool(); + RemoveStep = reader.ReadInt(); + } + + var deleteTime = TimeSpan.Zero; + + if (version >= 17) + deleteTime = reader.ReadTimeSpan(); + + if (deleteTime > TimeSpan.Zero || LastOwner != null && !Controlled && !IsStabled) + { + if (deleteTime == TimeSpan.Zero) + deleteTime = TimeSpan.FromDays(3.0); + + m_DeleteTimer = new DeleteTimer(this, deleteTime); + m_DeleteTimer.Start(); + } + + if (version >= 18) + CorpseNameOverride = reader.ReadString(); + + if (version >= 19) + HomeMap = reader.ReadMap(); + + if (version <= 14 && m_Paragon && Hue == 0x31) Hue = Paragon.Hue; // Paragon hue fixed, should now be 0x501. + + if (Core.AOS && NameHue == 0x35) + NameHue = -1; + + CheckStatTimers(); + + ChangeAIType(m_CurrentAI); + + AddFollowers(); + + if (IsAnimatedDead) + AnimateDeadSpell.Register(m_SummonMaster, this); + } + + public virtual bool IsHumanInTown() => Body.IsHuman && Region.IsPartOf(); + + public virtual bool CheckGold(Mobile from, Item dropped) => dropped is Gold gold && OnGoldGiven(from, gold); + + public virtual bool OnGoldGiven(Mobile from, Gold dropped) + { + if (CheckTeachingMatch(from)) + { + if (Teach(m_Teaching, from, dropped.Amount, true)) + { + dropped.Delete(); + return true; + } + } + else if (IsHumanInTown()) + { + Direction = GetDirectionTo(from); + + var oldSpeechHue = SpeechHue; + + SpeechHue = 0x23F; + SayTo(from, "Thou art giving me gold?"); + + SayTo(from, dropped.Amount >= 400 ? "'Tis a noble gift." : "Money is always welcome."); + + SpeechHue = 0x3B2; + SayTo(from, 501548); // I thank thee. + + SpeechHue = oldSpeechHue; + + dropped.Delete(); + return true; + } + + return false; + } + + public virtual bool OverrideBondingReqs() => false; + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (CheckFeed(from, dropped)) + return true; + if (CheckGold(from, dropped)) + return true; + + // Note: Yes, this happens for all questers (regardless of type, e.g. escorts), + // even if they can't offer you anything at the moment + if (MLQuestSystem.Enabled && CanGiveMLQuest && from is PlayerMobile mobile) + { + MLQuestSystem.Tell( + this, + mobile, + 1074893 + ); // You need to mark your quest items so I don't take the wrong object. Then speak to me. + return false; + } + + return base.OnDragDrop(from, dropped); + } + + public void ChangeAIType(AIType newAI) + { + AIObject?.m_Timer.Stop(); + + if (ForcedAI != null) + { + AIObject = ForcedAI; + return; + } + + AIObject = newAI switch + { + AIType.AI_Melee => new MeleeAI(this), + AIType.AI_Animal => new AnimalAI(this), + AIType.AI_Berserk => new BerserkAI(this), + AIType.AI_Archer => new ArcherAI(this), + AIType.AI_Healer => new HealerAI(this), + AIType.AI_Vendor => new VendorAI(this), + AIType.AI_Mage => new MageAI(this), + AIType.AI_Predator => + // m_AI = new PredatorAI(this); + new MeleeAI(this), + AIType.AI_Thief => new ThiefAI(this), + _ => null + }; + } + + public virtual void OnTeamChange() + { + } + + public override void RevealingAction() + { + InvisibilitySpell.RemoveTimer(this); + + base.RevealingAction(); + } + + public void RemoveFollowers() + { + if (m_ControlMaster != null) + { + m_ControlMaster.Followers -= ControlSlots; + if (m_ControlMaster is PlayerMobile mobile) + { + mobile.AllFollowers.Remove(this); + if (mobile.AutoStabled.Contains(this)) + mobile.AutoStabled.Remove(this); + } + } + else if (m_SummonMaster != null) + { + m_SummonMaster.Followers -= ControlSlots; + (m_SummonMaster as PlayerMobile)?.AllFollowers.Remove(this); + } + + if (m_ControlMaster?.Followers < 0) + m_ControlMaster.Followers = 0; + + if (m_SummonMaster?.Followers < 0) + m_SummonMaster.Followers = 0; + } + + public void AddFollowers() + { + if (m_ControlMaster != null) + { + m_ControlMaster.Followers += ControlSlots; + if (m_ControlMaster is PlayerMobile mobile) + mobile.AllFollowers.Add(this); + } + else if (m_SummonMaster != null) + { + m_SummonMaster.Followers += ControlSlots; + if (m_SummonMaster is PlayerMobile mobile) + mobile.AllFollowers.Add(this); + } + } + + public virtual void OnGotMeleeAttack(Mobile attacker) + { + if (AutoDispel && attacker is BaseCreature creature && creature.IsDispellable && + AutoDispelChance > Utility.RandomDouble()) + Dispel(creature); + } + + public virtual void Dispel(Mobile m) + { + Effects.SendLocationParticles( + EffectItem.Create(m.Location, m.Map, EffectItem.DefaultDuration), + 0x3728, + 8, + 20, + 5042 + ); + Effects.PlaySound(m, m.Map, 0x201); + + m.Delete(); + } + + public virtual void OnGaveMeleeAttack(Mobile defender) + { + var p = m_Paragon ? PoisonImpl.IncreaseLevel(HitPoison) : HitPoison; + + if (p != null && HitPoisonChance >= Utility.RandomDouble()) + { + defender.ApplyPoison(this, p); + + if (Controlled) + CheckSkill(SkillName.Poisoning, 0, Skills.Poisoning.Cap); + } + + if (AutoDispel && defender is BaseCreature creature && creature.IsDispellable && + AutoDispelChance > Utility.RandomDouble()) + Dispel(creature); + } + + public override void OnAfterDelete() + { + if (AIObject != null) + { + AIObject.m_Timer?.Stop(); + AIObject = null; + } + + if (m_DeleteTimer != null) + { + m_DeleteTimer.Stop(); + m_DeleteTimer = null; + } + + FocusMob = null; + + if (IsAnimatedDead) + AnimateDeadSpell.Unregister(m_SummonMaster, this); + + if (MLQuestSystem.Enabled) + MLQuestSystem.HandleDeletion(this); + + base.OnAfterDelete(); + } + + public void DebugSay(string text) + { + if (Debug) + PublicOverheadMessage(MessageType.Regular, 41, false, text); + } + + public void DebugSay(string format, params object[] args) + { + if (Debug) + PublicOverheadMessage(MessageType.Regular, 41, false, string.Format(format, args)); + } + + /* + * This function can be overridden.. so a "Strongest" mobile, can have a different definition depending + * on who check for value + * -Could add a FightMode.Preferred + * + */ + + public virtual double GetFightModeRanking(Mobile m, FightMode acqType, bool bPlayerOnly) + { + if (bPlayerOnly && !m.Player) + return double.MinValue; + + return acqType switch + { + FightMode.Strongest => m.Skills.Tactics.Value + m.Str, // returns strongest mobile + FightMode.Weakest => -m.Hits, // returns weakest mobile + _ => -GetDistanceToSqrt(m) + }; + } + + // Turn, - for left, + for right + // Basic for now, needs work + public virtual void Turn(int iTurnSteps) + { + var v = (int)Direction; + + Direction = (Direction)((((v & 0x7) + iTurnSteps) & 0x7) | (v & 0x80)); + } + + public virtual void TurnInternal(int iTurnSteps) + { + var v = (int)Direction; + + SetDirection((Direction)((((v & 0x7) + iTurnSteps) & 0x7) | (v & 0x80))); + } + + public bool IsHurt() => Hits != HitsMax; + + public double GetHomeDistance() => GetDistanceToSqrt(m_Home); + + public virtual int GetTeamSize(int iRange) + { + var iCount = 0; + + foreach (var m in GetMobilesInRange(iRange)) + if (m != this && m is BaseCreature creature && !creature.Deleted && creature.Team == Team && + CanSee(creature)) + iCount++; + + return iCount; + } + + public override void AggressiveAction(Mobile aggressor, bool criminal) + { + base.AggressiveAction(aggressor, criminal); + + if (ControlMaster != null && NotorietyHandlers.CheckAggressor(ControlMaster.Aggressors, aggressor)) + aggressor.Aggressors.Add(AggressorInfo.Create(this, aggressor, true)); + + var ct = m_ControlOrder; + + if (AIObject != null) + { + if (!Core.ML || ct != OrderType.Follow && ct != OrderType.Stop && ct != OrderType.Stay) + { + AIObject.OnAggressiveAction(aggressor); + } + else + { + DebugSay("I'm being attacked but my master told me not to fight."); + Warmode = false; + return; + } + } + + StopFlee(); + + ForceReacquire(); + + if (!IsEnemy(aggressor)) + { + var pl = Ethics.Player.Find(aggressor, true); + + if (pl?.IsShielded == true) + pl.FinishShield(); + } + + if (aggressor.ChangingCombatant && (m_Controlled || m_bSummoned) && + (ct == OrderType.Come || !Core.ML && ct == OrderType.Stay || ct == OrderType.Stop || ct == OrderType.None || + ct == OrderType.Follow)) + { + ControlTarget = aggressor; + ControlOrder = OrderType.Attack; + } + else if (Combatant == null && !BardPacified) + { + Warmode = true; + Combatant = aggressor; + } + } + + public override bool OnMoveOver(Mobile m) + { + if (m is BaseCreature creature && !creature.Controlled) + return !Alive || !creature.Alive || IsDeadBondedPet || creature.IsDeadBondedPet || + Hidden && AccessLevel > AccessLevel.Player; + + if (Region.IsPartOf() && m is PlayerMobile pm && + (pm.DuelContext?.Started != true || pm.DuelContext.Finished || + pm.DuelPlayer?.Eliminated != false)) + return true; + + return base.OnMoveOver(m); + } + + public virtual void AddCustomContextEntries(Mobile from, List list) + { + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (Commandable) + AIObject?.GetContextMenuEntries(from, list); + + if (m_bTamable && !m_Controlled && from.Alive) + list.Add(new TameEntry(from, this)); + + AddCustomContextEntries(from, list); + + if (CanTeach && from.Alive) + { + var ourSkills = Skills; + var theirSkills = from.Skills; + + for (var i = 0; i < ourSkills.Length && i < theirSkills.Length; ++i) + { + var skill = ourSkills[i]; + var theirSkill = theirSkills[i]; + + if (skill?.Base >= 60.0 && CheckTeach(skill.SkillName, from)) + { + var toTeach = skill.BaseFixedPoint / 3; + + if (toTeach > 420) + toTeach = 420; + + list.Add(new TeachEntry((SkillName)i, this, from, toTeach > theirSkill.BaseFixedPoint)); + } + } + } + } + + public override bool HandlesOnSpeech(Mobile from) => + (SpeechType?.Flags & IHSFlags.OnSpeech) != 0 && from.InRange(this, 3) || + AIObject?.HandlesOnSpeech(from) == true && from.InRange(this, RangePerception); + + public override void OnSpeech(SpeechEventArgs e) + { + var speechType = SpeechType; + + if (speechType?.OnSpeech(this, e.Mobile, e.Speech) == true) + e.Handled = true; + else if (!e.Handled && AIObject != null && e.Mobile.InRange(this, RangePerception)) + AIObject.OnSpeech(e); + } + + public override bool IsHarmfulCriminal(Mobile target) => + (!Controlled || target != m_ControlMaster) && (!Summoned || target != m_SummonMaster) && + (!(target is BaseCreature creature) || !creature.InitialInnocent || creature.Controlled) && + (!(target is PlayerMobile mobile) || mobile.PermaFlags.Count <= 0) && base.IsHarmfulCriminal(target); + + public override void CriminalAction(bool message) + { + base.CriminalAction(message); + + if (Controlled || Summoned) + { + if (m_ControlMaster?.Player == true) + m_ControlMaster.CriminalAction(false); + else if (m_SummonMaster?.Player == true) + m_SummonMaster.CriminalAction(false); + } + } + + public override void DoHarmful(Mobile target, bool indirect) + { + base.DoHarmful(target, indirect); + + if (target == this || target == m_ControlMaster || target == m_SummonMaster || !Controlled && !Summoned) + return; + + var list = Aggressors; + + for (var i = 0; i < list.Count; ++i) + { + var ai = list[i]; + + if (ai.Attacker == target) + return; + } + + list = Aggressed; + + for (var i = 0; i < list.Count; ++i) + { + var ai = list[i]; + + if (ai.Defender == target) + { + if (m_ControlMaster?.Player == true && m_ControlMaster.CanBeHarmful(target, false)) + m_ControlMaster.DoHarmful(target, true); + else if (m_SummonMaster?.Player == true && m_SummonMaster.CanBeHarmful(target, false)) + m_SummonMaster.DoHarmful(target, true); + + return; + } + } + } + + public void ReleaseGuardDupeLock() + { + m_NoDupeGuards = null; + } + + public void ReleaseGuardLock() + { + EndAction(); + } + + public virtual bool CheckIdle() + { + if (Combatant != null) + return false; // in combat.. not idling + + if (m_IdleReleaseTime > DateTime.MinValue) + { + // idling... + + if (DateTime.UtcNow >= m_IdleReleaseTime) + { + m_IdleReleaseTime = DateTime.MinValue; + return false; // idle is over + } + + return true; // still idling + } + + if (Utility.Random(100) < 95) + return false; // not idling, but don't want to enter idle state + + m_IdleReleaseTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(15, 25)); + + if (Body.IsHuman) + switch (Utility.Random(2)) + { + case 0: + CheckedAnimate(5, 5, 1, true, true, 1); + break; + case 1: + CheckedAnimate(6, 5, 1, true, false, 1); + break; + } + else if (Body.IsAnimal) + switch (Utility.Random(3)) + { + case 0: + CheckedAnimate(3, 3, 1, true, false, 1); + break; + case 1: + CheckedAnimate(9, 5, 1, true, false, 1); + break; + case 2: + CheckedAnimate(10, 5, 1, true, false, 1); + break; + } + else if (Body.IsMonster) + switch (Utility.Random(2)) + { + case 0: + CheckedAnimate(17, 5, 1, true, false, 1); + break; + case 1: + CheckedAnimate(18, 5, 1, true, false, 1); + break; + } + + PlaySound(GetIdleSound()); + return true; // entered idle state + } + + /* + this way, due to the huge number of locations this will have to be changed + Perhaps we can change this in the future when fixing game play is not the + major issue. + */ + + public virtual void CheckedAnimate(int action, int frameCount, int repeatCount, bool forward, bool repeat, int delay) + { + if (!Mounted) + Animate(action, frameCount, repeatCount, forward, repeat, delay); + } + + private void CheckAIActive() + { + var map = Map; + + if (PlayerRangeSensitive && AIObject != null && map?.GetSector(Location).Active == true) + AIObject.Activate(); + } + + public override void OnCombatantChange() + { + base.OnCombatantChange(); + + Warmode = Combatant?.Deleted == false && Combatant.Alive; + + if (CanFly && Warmode) + Flying = false; + } + + protected override void OnMapChange(Map oldMap) + { + CheckAIActive(); + + base.OnMapChange(oldMap); + } + + protected override void OnLocationChange(Point3D oldLocation) + { + CheckAIActive(); + + base.OnLocationChange(oldLocation); + } + + public virtual void ForceReacquire() + { + NextReacquireTime = Core.TickCount; + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (AcquireOnApproach && !Controlled && !Summoned && FightMode != FightMode.Aggressor) + { + if (InRange(m.Location, AcquireOnApproachRange) && !InRange(oldLocation, AcquireOnApproachRange) && + CanBeHarmful(m) && IsEnemy(m)) + { + Combatant = FocusMob = m; + AIObject?.MoveTo(m, true, 1); + DoHarmful(m); + } + } + else if (ReacquireOnMovement) + { + ForceReacquire(); + } + + var speechType = SpeechType; + + speechType?.OnMovement(this, m, oldLocation); + + /* Begin notice sound */ + if ((!m.Hidden || m.AccessLevel == AccessLevel.Player) && m.Player && FightMode != FightMode.Aggressor && + FightMode != FightMode.None && Combatant == null && !Controlled && !Summoned && + InRange(m.Location, 18) && !InRange(oldLocation, 18)) + { + if (Body.IsMonster) + Animate(11, 5, 1, true, false, 1); + + PlaySound(GetAngerSound()); + } + /* End notice sound */ + + if (MLQuestSystem.Enabled && CanShout && m is PlayerMobile mobile) + CheckShout(mobile, oldLocation); + + if (m_NoDupeGuards == m) + return; + + if (!Body.IsHuman || Kills >= 5 || AlwaysMurderer || AlwaysAttackable || m.Kills < 5 || + !m.InRange(Location, 12) || !m.Alive) + return; + + var guardedRegion = Region.GetRegion(); + + if (guardedRegion?.IsDisabled() == false && guardedRegion.IsGuardCandidate(m) && BeginAction()) + { + Say(1013037 + Utility.Random(16)); + guardedRegion.CallGuards(Location); + + Timer.DelayCall(TimeSpan.FromSeconds(5.0), ReleaseGuardLock); + + m_NoDupeGuards = m; + Timer.DelayCall(ReleaseGuardDupeLock); + } + } + + public void AddSpellAttack(Type type) + { + m_SpellAttack.Add(type); + } + + public void AddSpellDefense(Type type) + { + m_SpellDefense.Add(type); + } + + public Spell GetAttackSpellRandom() + { + var type = m_SpellAttack.RandomElement(); + return type == null ? null : ActivatorUtil.CreateInstance(type, this, null) as Spell; + } + + public Spell GetDefenseSpellRandom() + { + var type = m_SpellDefense.RandomElement(); + return type == null ? null : ActivatorUtil.CreateInstance(type, this, null) as Spell; + } + + public Spell GetSpellSpecific(Type type) + { + int i; + + for (i = 0; i < m_SpellAttack.Count; i++) + if (m_SpellAttack[i] == type) + return ActivatorUtil.CreateInstance(type, this, null) as Spell; + + for (i = 0; i < m_SpellDefense.Count; i++) + if (m_SpellDefense[i] == type) + return ActivatorUtil.CreateInstance(type, this, null) as Spell; + + return null; + } + + public static void Cap(ref int val, int min, int max) + { + if (val < min) + val = min; + else if (val > max) + val = max; + } + + public override void OnDoubleClick(Mobile from) + { + if (from.AccessLevel >= AccessLevel.GameMaster && !Body.IsHuman) + { + var pack = Backpack; + + pack?.DisplayTo(from); + } + + if (DeathAdderCharmable && from.CanBeHarmful(this, false)) + if (SummonFamiliarSpell.Table.TryGetValue(from, out var bc) && (bc as DeathAdder)?.Deleted == false) + { + from.SendAsciiMessage("You charm the snake. Select a target to attack."); + from.Target = new DeathAdderCharmTarget(this); + } + + if (MLQuestSystem.Enabled && CanGiveMLQuest && from is PlayerMobile mobile) + MLQuestSystem.OnDoubleClick(this, mobile); + + base.OnDoubleClick(from); + } + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + if (MLQuestSystem.Enabled && CanGiveMLQuest) + list.Add(1072269); // Quest Giver + + if (Core.ML) + { + if (DisplayWeight) + list.Add(TotalWeight == 1 ? 1072788 : 1072789, TotalWeight.ToString()); // Weight: ~1_WEIGHT~ stones + + if (m_ControlOrder == OrderType.Guard) + list.Add(1080078); // guarding + } + + if (Summoned && !(IsAnimatedDead || IsNecroFamiliar || this is Clone)) + { + list.Add(1049646); // (summoned) + } + else if (Controlled && Commandable) + { + if (IsBonded) // Intentional difference (showing ONLY bonded when bonded instead of bonded & tame) + list.Add(1049608); // (bonded) + else + list.Add(502006); // (tame) + } + } + + public override void OnSingleClick(Mobile from) + { + if (Controlled && Commandable) + { + int number; + + if (Summoned) + number = 1049646; // (summoned) + else if (IsBonded) + number = 1049608; // (bonded) + else + number = 502006; // (tame) + + PrivateOverheadMessage(MessageType.Regular, 0x3B2, number, from.NetState); + } + + base.OnSingleClick(from); + } + + public override bool OnBeforeDeath() + { + var treasureLevel = TreasureMapLevel; + + if (treasureLevel == 1 && Map == Map.Trammel && TreasureMap.IsInHavenIsland(this)) + { + var killer = LastKiller; + + if (killer is BaseCreature bc) + killer = bc.GetMaster(); + + if (killer is PlayerMobile mobile && mobile.Young) + treasureLevel = 0; + } + + if (!Summoned && !NoKillAwards && !IsBonded) + { + if (treasureLevel >= 0) + { + if (m_Paragon && Paragon.ChestChance > Utility.RandomDouble()) + PackItem(new ParagonChest(Name, treasureLevel)); + else if ((Map == Map.Felucca || Map == Map.Trammel) && Utility.RandomDouble() <= TreasureMap.LootChance) + PackItem(new TreasureMap(treasureLevel, Map)); + } + + if (m_Paragon && Paragon.ChocolateIngredientChance > Utility.RandomDouble()) + switch (Utility.Random(4)) + { + case 0: + PackItem(new CocoaButter()); + break; + case 1: + PackItem(new CocoaLiquor()); + break; + case 2: + PackItem(new SackOfSugar()); + break; + case 3: + PackItem(new Vanilla()); + break; + } + } + + if (!Summoned && !NoKillAwards && !m_HasGeneratedLoot) + { + m_HasGeneratedLoot = true; + GenerateLoot(false); + } + + if (!NoKillAwards && Region.IsPartOf("Doom")) + { + var bones = TheSummoningQuest.GetDaemonBonesFor(this); + + if (bones > 0) + PackItem(new DaemonBone(bones)); + } + + if (IsAnimatedDead) + Effects.SendLocationEffect(Location, Map, 0x3728, 13, 1, 0x461, 4); + + var speechType = SpeechType; + speechType?.OnDeath(this); + ReceivedHonorContext?.OnTargetKilled(); + + return base.OnBeforeDeath(); + } + + public int ComputeBonusDamage(List list, Mobile m) + { + var bonus = 0; + + for (var i = list.Count - 1; i >= 0; --i) + { + var de = list[i]; + + if (de.Damager == m || !(de.Damager is BaseCreature bc)) + continue; + + if (bc.GetMaster() == m) + bonus += de.DamageGiven; + } + + return bonus; + } + + public Mobile GetMaster() + { + if (Controlled && ControlMaster != null) + return ControlMaster; + if (Summoned && SummonMaster != null) + return SummonMaster; + + return null; + } + + public static List GetLootingRights(List damageEntries, int hitsMax) + { + var rights = new List(); + + for (var i = damageEntries.Count - 1; i >= 0; --i) + { + if (i >= damageEntries.Count) + continue; + + var de = damageEntries[i]; + + if (de.HasExpired) + { + damageEntries.RemoveAt(i); + continue; + } + + var damage = de.DamageGiven; + + var respList = de.Responsible; + + for (var j = 0; j < respList?.Count; ++j) + { + var subEntry = respList[j]; + var master = subEntry.Damager; + + if (master?.Deleted != false || !master.Player) + continue; + + var needNewSubEntry = true; + + for (var k = 0; needNewSubEntry && k < rights.Count; ++k) + { + var ds = rights[k]; + + if (ds.m_Mobile == master) + { + ds.m_Damage += subEntry.DamageGiven; + needNewSubEntry = false; + } + } + + if (needNewSubEntry) + rights.Add(new DamageStore(master, subEntry.DamageGiven)); + + damage -= subEntry.DamageGiven; + } + + var m = de.Damager; + + if (m?.Deleted != false || !m.Player) + continue; + + if (damage <= 0) + continue; + + var needNewEntry = true; + + for (var j = 0; needNewEntry && j < rights.Count; ++j) + { + var ds = rights[j]; + + if (ds.m_Mobile == m) + { + ds.m_Damage += damage; + needNewEntry = false; + } + } + + if (needNewEntry) + rights.Add(new DamageStore(m, damage)); + } + + if (rights.Count > 0) + { + rights[0].m_Damage = + (int)(rights[0].m_Damage * + 1.25 + ); // This would be the first valid person attacking it. Gets a 25% bonus. Per 1/19/07 Five on Friday + + if (rights.Count > 1) + rights.Sort(); // Sort by damage + + var topDamage = rights[0].m_Damage; + int minDamage; + + if (hitsMax >= 3000) + minDamage = topDamage / 16; + else if (hitsMax >= 1000) + minDamage = topDamage / 8; + else if (hitsMax >= 200) + minDamage = topDamage / 4; + else + minDamage = topDamage / 2; + + for (var i = 0; i < rights.Count; ++i) + { + var ds = rights[i]; + + ds.m_HasRight = ds.m_Damage >= minDamage; + } + } + + return rights; + } + + public virtual void OnKilledBy(Mobile mob) + { + if (GivesMLMinorArtifact) + { + if (MondainsLegacy.CheckArtifactChance(mob, this)) + MondainsLegacy.GiveArtifactTo(mob); + } + else if (m_Paragon) + { + if (Paragon.CheckArtifactChance(mob, this)) + Paragon.GiveArtifactTo(mob); + } + } + + public override void OnDeath(Container c) + { + MeerMage.StopEffect(this, false); + + if (IsBonded) + { + var sound = GetDeathSound(); + + if (sound >= 0) + Effects.PlaySound(this, Map, sound); + + Warmode = false; + + Poison = null; + Combatant = null; + + Hits = 0; + Stam = 0; + Mana = 0; + + IsDeadPet = true; + ControlTarget = ControlMaster; + ControlOrder = OrderType.Follow; + + ProcessDeltaQueue(); + SendIncomingPacket(); + SendIncomingPacket(); + + // TODO: This can be done in Parallel if there are lots of them. + var aggressors = Aggressors; + + for (var i = 0; i < aggressors.Count; ++i) + { + var info = aggressors[i]; + + if (info.Attacker.Combatant == this) + info.Attacker.Combatant = null; + } + + var aggressed = Aggressed; + + for (var i = 0; i < aggressed.Count; ++i) + { + var info = aggressed[i]; + + if (info.Defender.Combatant == this) + info.Defender.Combatant = null; + } + + var owner = ControlMaster; + + if (owner?.Deleted != false || owner.Map != Map || !owner.InRange(this, 12) || !CanSee(owner) || + !InLOS(owner)) + { + if (OwnerAbandonTime == DateTime.MinValue) + OwnerAbandonTime = DateTime.UtcNow; + } + else + { + OwnerAbandonTime = DateTime.MinValue; + } + + GiftOfLifeSpell.HandleDeath(this); + + CheckStatTimers(); + } + else + { + if (!Summoned && !NoKillAwards) + { + var totalFame = Fame / 100; + var totalKarma = -Karma / 100; + + if (Map == Map.Felucca) + { + totalFame += totalFame / 10 * 3; + totalKarma += totalKarma / 10 * 3; + } + + var list = GetLootingRights(DamageEntries, HitsMax); + var titles = new List(); + var fame = new List(); + var karma = new List(); + + var givenQuestKill = false; + var givenFactionKill = false; + var givenToTKill = false; + + for (var i = 0; i < list.Count; ++i) + { + var ds = list[i]; + + if (!ds.m_HasRight) + continue; + + var party = Engines.PartySystem.Party.Get(ds.m_Mobile); + + if (party != null) + { + var divedFame = totalFame / party.Members.Count; + var divedKarma = totalKarma / party.Members.Count; + + for (var j = 0; j < party.Members.Count; ++j) + { + var info = party.Members[j]; + + if (info?.Mobile != null) + { + var index = titles.IndexOf(info.Mobile); + + if (index == -1) + { + titles.Add(info.Mobile); + fame.Add(divedFame); + karma.Add(divedKarma); + } + else + { + fame[index] += divedFame; + karma[index] += divedKarma; + } + } + } + } + else + { + titles.Add(ds.m_Mobile); + fame.Add(totalFame); + karma.Add(totalKarma); + } + + OnKilledBy(ds.m_Mobile); + + if (!givenFactionKill) + { + givenFactionKill = true; + Faction.HandleDeath(this, ds.m_Mobile); + } + + var region = ds.m_Mobile.Region; + + if (!givenToTKill && (Map == Map.Tokuno || region.IsPartOf("Yomotsu Mines") || + region.IsPartOf("Fan Dancer's Dojo"))) + { + givenToTKill = true; + TreasuresOfTokuno.HandleKill(this, ds.m_Mobile); + } + + if (ds.m_Mobile is PlayerMobile pm) + { + if (MLQuestSystem.Enabled) MLQuestSystem.HandleKill(pm, this); + + if (givenQuestKill) + continue; + + var qs = pm.Quest; + + if (qs != null) + { + qs.OnKill(this, c); + givenQuestKill = true; + } + } + } + + for (var i = 0; i < titles.Count; ++i) + { + Titles.AwardFame(titles[i], fame[i], true); + Titles.AwardKarma(titles[i], karma[i], true); + } + } + + base.OnDeath(c); + + if (DeleteCorpseOnDeath) + c.Delete(); + } + } + + public override void OnDelete() + { + var m = m_ControlMaster; + SetControlMaster(null); + + SummonMaster = null; + ReceivedHonorContext?.Cancel(); + base.OnDelete(); + m?.InvalidateProperties(); + } + + public override bool CanBeHarmful(Mobile target, bool message, bool ignoreOurBlessedness) + { + if (target is BaseFactionGuard) + return false; + + if (target is BaseCreature creature && creature.IsInvulnerable || target is PlayerVendor || target is TownCrier) + { + if (message) + { + if (target.Title == null) + SendMessage("{0} cannot be harmed.", target.Name); + else + SendMessage("{0} {1} cannot be harmed.", target.Name, target.Title); + } + + return false; + } + + return base.CanBeHarmful(target, message, ignoreOurBlessedness); + } + + public override bool CanBeRenamedBy(Mobile from) => + Controlled && from == ControlMaster && !from.Region.IsPartOf() || + base.CanBeRenamedBy(from); + + public bool SetControlMaster(Mobile m) + { + if (m == null) + { + ControlMaster = null; + Controlled = false; + ControlTarget = null; + ControlOrder = OrderType.None; + Guild = null; + + Delta(MobileDelta.Noto); + } + else + { + var se = Spawner; + if (se?.UnlinkOnTaming == true) + { + Spawner.Remove(this); + Spawner = null; + } + + if (m.Followers + ControlSlots > m.FollowersMax) + { + m.SendLocalizedMessage(1049607); // You have too many followers to control that creature. + return false; + } + + CurrentWayPoint = null; // so tamed animals don't try to go back + + Home = Point3D.Zero; + + ControlMaster = m; + Controlled = true; + ControlTarget = null; + ControlOrder = OrderType.Come; + Guild = null; + + if (m_DeleteTimer != null) + { + m_DeleteTimer.Stop(); + m_DeleteTimer = null; + } + + Delta(MobileDelta.Noto); + } + + InvalidateProperties(); + + return true; + } + + public override void OnRegionChange(Region Old, Region New) + { + base.OnRegionChange(Old, New); + + if (Controlled && Spawner?.UnlinkOnTaming == false && New?.AcceptsSpawnsFrom(Spawner.Region) != true) + { + Spawner.Remove(this); + Spawner = null; + } + } + + public static bool Summon(BaseCreature creature, Mobile caster, Point3D p, int sound, TimeSpan duration) => + Summon(creature, true, caster, p, sound, duration); + + public static bool Summon( + BaseCreature creature, bool controlled, Mobile caster, Point3D p, int sound, + TimeSpan duration + ) + { + if (caster.Followers + creature.ControlSlots > caster.FollowersMax) + { + caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. + creature.Delete(); + return false; + } + + Summoning = true; + + if (controlled) + creature.SetControlMaster(caster); + + creature.RangeHome = 10; + creature.Summoned = true; + + creature.SummonMaster = caster; + + var pack = creature.Backpack; + + if (pack != null) + for (var i = pack.Items.Count - 1; i >= 0; --i) + { + if (i >= pack.Items.Count) + continue; + + pack.Items[i].Delete(); + } + + new UnsummonTimer(caster, creature, duration).Start(); + creature.SummonEnd = DateTime.UtcNow + duration; + + creature.MoveToWorld(p, caster.Map); + + Effects.PlaySound(p, creature.Map, sound); + + Summoning = false; + + return true; + } + + public virtual void OnThink() + { + var tc = Core.TickCount; + + if (EnableRummaging && CanRummageCorpses && !Summoned && !Controlled && tc - m_NextRummageTime >= 0) + { + double min, max; + + if (Utility.RandomDouble() < ChanceToRummage && Rummage()) + { + min = MinutesToNextRummageMin; + max = MinutesToNextRummageMax; + } + else + { + min = MinutesToNextChanceMin; + max = MinutesToNextChanceMax; + } + + var delay = min + Utility.RandomDouble() * (max - min); + m_NextRummageTime = tc + (int)TimeSpan.FromMinutes(delay).TotalMilliseconds; + } + + if (CanBreath && tc - m_NextBreathTime >= 0 + ) // tested: controlled dragons do breath fire, what about summoned skeletal dragons? + { + var target = Combatant; + + if (target?.Alive == true && !target.IsDeadBondedPet && CanBeHarmful(target) && target.Map == Map && + !IsDeadBondedPet && target.InRange(this, BreathRange) && InLOS(target) && !BardPacified) + { + if (Core.TickCount - m_NextBreathTime < 30000 && Utility.RandomBool()) BreathStart(target); + + m_NextBreathTime = tc + (int)TimeSpan + .FromSeconds(BreathMinDelay + Utility.RandomDouble() * (BreathMaxDelay - BreathMinDelay)) + .TotalMilliseconds; + } + } + + if ((CanHeal || CanHealOwner) && Alive && !IsHealing && !BardPacified) + { + var owner = ControlMaster; + + if (owner != null && CanHealOwner && tc - m_NextHealOwnerTime >= 0 && CanBeBeneficial(owner, true, true) && + owner.Map == Map && InRange(owner, HealStartRange) && InLOS(owner) && + owner.Hits < HealOwnerTrigger * owner.HitsMax) + { + HealStart(owner); + + m_NextHealOwnerTime = tc + (int)TimeSpan.FromSeconds(HealOwnerInterval).TotalMilliseconds; + } + else if (CanHeal && tc - m_NextHealTime >= 0 && CanBeBeneficial(this) && + (Hits < HealTrigger * HitsMax || Poisoned)) + { + HealStart(this); + + m_NextHealTime = tc + (int)TimeSpan.FromSeconds(HealInterval).TotalMilliseconds; + } + } + + if (ReturnsToHome && IsSpawnerBound() && !InRange(Home, RangeHome)) + { + if (Combatant == null && Warmode == false && Utility.RandomDouble() < .10) /* some throttling */ + { + m_FailedReturnHome = !Move(GetDirectionTo(Home.X, Home.Y)) ? m_FailedReturnHome + 1 : 0; + + if (m_FailedReturnHome > 5) + { + SetLocation(Home, true); + + m_FailedReturnHome = 0; + } + } + } + else + { + m_FailedReturnHome = 0; + } + + if (HasAura && tc - m_NextAura >= 0) + { + AuraDamage(); + m_NextAura = tc + (int)AuraInterval.TotalMilliseconds; + } + } + + public virtual bool Rummage() + { + var eable = GetItemsInRange(2); + var toRummage = eable.FirstOrDefault(item => item.Items.Count > 0); + + eable.Free(); + + if (toRummage == null) + return false; + + if (Backpack == null) + return false; + + var items = toRummage.Items; + + for (var i = 0; i < items.Count; ++i) + { + var item = items.RandomElement(); + + Lift(item, item.Amount, out var rejected, out var _); + + if (!rejected && Drop(this, new Point3D(-1, -1, 0))) + { + // *rummages through a corpse and takes an item* + PublicOverheadMessage(MessageType.Emote, 0x3B2, 1008086); + // TODO: Instancing of Rummaged stuff. + return true; + } + } + + return false; + } + + public void Pacify(Mobile master, DateTime endtime) + { + BardPacified = true; + BardEndTime = endtime; + } + + public override Mobile GetDamageMaster(Mobile damagee) + { + if (BardProvoked && damagee == BardTarget) + return BardMaster; + if (m_Controlled && m_ControlMaster != null) + return m_ControlMaster; + if (m_bSummoned && m_SummonMaster != null) + return m_SummonMaster; + + return base.GetDamageMaster(damagee); + } + + public void Provoke(Mobile master, Mobile target, bool bSuccess) + { + BardProvoked = true; + + if (!Core.ML) PublicOverheadMessage(MessageType.Emote, EmoteHue, false, "*looks furious*"); + + if (bSuccess) + { + PlaySound(GetIdleSound()); + + BardMaster = master; + BardTarget = target; + Combatant = target; + BardEndTime = DateTime.UtcNow + TimeSpan.FromSeconds(30.0); + + if (target is BaseCreature t) + { + if (t.Unprovokable || t.IsParagon && BaseInstrument.GetBaseDifficulty(t) >= 160.0) + return; + + t.BardProvoked = true; + + t.BardMaster = master; + t.BardTarget = this; + t.Combatant = this; + t.BardEndTime = DateTime.UtcNow + TimeSpan.FromSeconds(30.0); + } + } + else + { + PlaySound(GetAngerSound()); + + BardMaster = master; + BardTarget = target; + } + } + + public bool FindMyName(string str, bool bWithAll) + { + var name = Name; + + if (name == null || str.Length < name.Length) + return false; + + var wordsString = str.Split(' '); + var wordsName = name.Split(' '); + + for (var j = 0; j < wordsName.Length; j++) + { + var wordName = wordsName[j]; + + var bFound = false; + for (var i = 0; i < wordsString.Length; i++) + { + var word = wordsString[i]; + + if (Insensitive.Equals(word, wordName)) + bFound = true; + + if (bWithAll && Insensitive.Equals(word, "all")) + return true; + } + + if (!bFound) + return false; } return true; - } - } - - return false; - } - - public void SetDamage(int val) - { - m_DamageMin = val; - m_DamageMax = val; - } - - public void SetDamage(int min, int max) - { - m_DamageMin = min; - m_DamageMax = max; - } - - public void SetHits(int val) - { - if (val < 1000 && !Core.AOS) - val = val * 100 / 60; - - HitsMaxSeed = val; - Hits = HitsMax; - } - - public void SetHits(int min, int max) - { - if (min < 1000 && !Core.AOS) - { - min = min * 100 / 60; - max = max * 100 / 60; - } - - HitsMaxSeed = Utility.RandomMinMax(min, max); - Hits = HitsMax; - } - - public void SetStam(int val) - { - StamMaxSeed = val; - Stam = StamMax; - } - - public void SetStam(int min, int max) - { - StamMaxSeed = Utility.RandomMinMax(min, max); - Stam = StamMax; - } - - public void SetMana(int val) - { - ManaMaxSeed = val; - Mana = ManaMax; - } - - public void SetMana(int min, int max) - { - ManaMaxSeed = Utility.RandomMinMax(min, max); - Mana = ManaMax; - } - - public void SetStr(int val) - { - RawStr = val; - Hits = HitsMax; - } - - public void SetStr(int min, int max) - { - RawStr = Utility.RandomMinMax(min, max); - Hits = HitsMax; - } - - public void SetDex(int val) - { - RawDex = val; - Stam = StamMax; - } - - public void SetDex(int min, int max) - { - RawDex = Utility.RandomMinMax(min, max); - Stam = StamMax; - } - - public void SetInt(int val) - { - RawInt = val; - Mana = ManaMax; - } - - public void SetInt(int min, int max) - { - RawInt = Utility.RandomMinMax(min, max); - Mana = ManaMax; - } - - public void SetDamageType(ResistanceType type, int min, int max) - { - SetDamageType(type, Utility.RandomMinMax(min, max)); - } - - public void SetDamageType(ResistanceType type, int val) - { - switch (type) - { - case ResistanceType.Physical: - PhysicalDamage = val; - break; - case ResistanceType.Fire: - FireDamage = val; - break; - case ResistanceType.Cold: - ColdDamage = val; - break; - case ResistanceType.Poison: - PoisonDamage = val; - break; - case ResistanceType.Energy: - EnergyDamage = val; - break; - } - } - - public void SetResistance(ResistanceType type, int min, int max) - { - SetResistance(type, Utility.RandomMinMax(min, max)); - } - - public void SetResistance(ResistanceType type, int val) - { - switch (type) - { - case ResistanceType.Physical: - m_PhysicalResistance = val; - break; - case ResistanceType.Fire: - m_FireResistance = val; - break; - case ResistanceType.Cold: - m_ColdResistance = val; - break; - case ResistanceType.Poison: - m_PoisonResistance = val; - break; - case ResistanceType.Energy: - m_EnergyResistance = val; - break; - } - - UpdateResistances(); - } - - public void SetSkill(SkillName name, double val) - { - Skills[name].BaseFixedPoint = (int)(val * 10); - - if (Skills[name].Base > Skills[name].Cap) - { - if (Core.SE) - SkillsCap += Skills[name].BaseFixedPoint - Skills[name].CapFixedPoint; - - Skills[name].Cap = Skills[name].Base; - } - } - - public void SetSkill(SkillName name, double min, double max) - { - int minFixed = (int)(min * 10); - int maxFixed = (int)(max * 10); - - Skills[name].BaseFixedPoint = Utility.RandomMinMax(minFixed, maxFixed); - - if (Skills[name].Base > Skills[name].Cap) - { - if (Core.SE) - SkillsCap += Skills[name].BaseFixedPoint - Skills[name].CapFixedPoint; - - Skills[name].Cap = Skills[name].Base; - } - } - - public void SetFameLevel(int level) - { - Fame = level switch - { - 1 => Utility.RandomMinMax(0, 1249), - 2 => Utility.RandomMinMax(1250, 2499), - 3 => Utility.RandomMinMax(2500, 4999), - 4 => Utility.RandomMinMax(5000, 9999), - 5 => Utility.RandomMinMax(10000, 10000), - _ => Fame - }; - } - - public void SetKarmaLevel(int level) - { - Karma = level switch - { - 0 => -Utility.RandomMinMax(0, 624), - 1 => -Utility.RandomMinMax(625, 1249), - 2 => -Utility.RandomMinMax(1250, 2499), - 3 => -Utility.RandomMinMax(2500, 4999), - 4 => -Utility.RandomMinMax(5000, 9999), - 5 => -Utility.RandomMinMax(10000, 10000), - _ => Karma - }; - } - - public void PackArcaneScroll(int min, int max) - { - PackArcaneScroll(Utility.RandomMinMax(min, max)); - } - - public void PackArcaneScroll(int amount) - { - for (int i = 0; i < amount; ++i) - PackArcaneScroll(); - } - - public void PackArcaneScroll() - { - if (!Core.ML) - return; - - PackItem(Loot.Construct(Loot.ArcanistScrollTypes)); - } - - public void PackPotion() - { - PackItem(Loot.RandomPotion()); - } - - public void PackArcanceScroll(double chance) - { - if (!Core.ML || chance <= Utility.RandomDouble()) - return; - - PackItem(Loot.Construct(Loot.ArcanistScrollTypes)); - } - - public void PackNecroScroll(int index) - { - if (!Core.AOS || Utility.RandomDouble() >= 0.05) - return; - - PackItem(Loot.Construct(Loot.NecromancyScrollTypes, index)); - } - - public void PackScroll(int minCircle, int maxCircle) - { - PackScroll(Utility.RandomMinMax(minCircle, maxCircle)); - } - - public void PackScroll(int circle) - { - int min = (circle - 1) * 8; - - PackItem(Loot.RandomScroll(min, min + 7, SpellbookType.Regular)); - } - - public void PackMagicItems(int minLevel, int maxLevel, double armorChance = 0.30, double weaponChance = 0.15) - { - if (!PackArmor(minLevel, maxLevel, armorChance)) - PackWeapon(minLevel, maxLevel, weaponChance); - } - - public virtual void DropBackpack() - { - if (Backpack?.Items.Count > 0) - { - Backpack b = new CreatureBackpack(Name); - - List list = new List(Backpack.Items); - foreach (Item item in list) b.DropItem(item); - - BaseHouse house = BaseHouse.FindHouseAt(this); - if (house != null) - b.MoveToWorld(house.BanLocation, house.Map); - else - b.MoveToWorld(Location, Map); - } - } - - protected bool m_Spawning; - protected int m_KillersLuck; - - public virtual void GenerateLoot(bool spawning) - { - m_Spawning = spawning; - - if (!spawning) - m_KillersLuck = LootPack.GetLuckChanceForKiller(this); - - GenerateLoot(); - - if (m_Paragon) - { - if (Fame < 1250) - AddLoot(LootPack.Meager); - else if (Fame < 2500) - AddLoot(LootPack.Average); - else if (Fame < 5000) - AddLoot(LootPack.Rich); - else if (Fame < 10000) - AddLoot(LootPack.FilthyRich); - else - AddLoot(LootPack.UltraRich); - } - - m_Spawning = false; - m_KillersLuck = 0; - } - - public virtual void GenerateLoot() - { - } - - public virtual void AddLoot(LootPack pack, int amount) - { - for (int i = 0; i < amount; ++i) - AddLoot(pack); - } - - public virtual void AddLoot(LootPack pack) - { - if (Summoned) - return; - - Container backpack = Backpack ?? new Backpack { Movable = false }; - AddItem(backpack); - - pack.Generate(this, backpack, m_Spawning, m_KillersLuck); - } - - public bool PackArmor(int minLevel, int maxLevel) => PackArmor(minLevel, maxLevel, 1.0); - - public bool PackArmor(int minLevel, int maxLevel, double chance) - { - if (chance <= Utility.RandomDouble()) - return false; - - Cap(ref minLevel, 0, 5); - Cap(ref maxLevel, 0, 5); - - if (Core.AOS) - { - Item item = Loot.RandomArmorOrShieldOrJewelry(); - - if (item == null) - return false; - - GetRandomAOSStats(minLevel, maxLevel, out int attributeCount, out int min, out int max); - - if (item is BaseArmor armor) - BaseRunicTool.ApplyAttributesTo(armor, attributeCount, min, max); - else if (item is BaseJewel jewel) - BaseRunicTool.ApplyAttributesTo(jewel, attributeCount, min, max); - - PackItem(item); - } - else - { - BaseArmor armor = Loot.RandomArmorOrShield(); - - if (armor == null) - return false; - - armor.ProtectionLevel = (ArmorProtectionLevel)RandomMinMaxScaled(minLevel, maxLevel); - armor.Durability = (ArmorDurabilityLevel)RandomMinMaxScaled(minLevel, maxLevel); - - PackItem(armor); - } - - return true; - } - - public static void GetRandomAOSStats(int minLevel, int maxLevel, out int attributeCount, out int min, out int max) - { - int v = RandomMinMaxScaled(minLevel, maxLevel); - - if (v >= 5) - { - attributeCount = Utility.RandomMinMax(2, 6); - min = 20; - max = 70; - } - else if (v == 4) - { - attributeCount = Utility.RandomMinMax(2, 4); - min = 20; - max = 50; - } - else if (v == 3) - { - attributeCount = Utility.RandomMinMax(2, 3); - min = 20; - max = 40; - } - else if (v == 2) - { - attributeCount = Utility.RandomMinMax(1, 2); - min = 10; - max = 30; - } - else - { - attributeCount = 1; - min = 10; - max = 20; - } - } - - public static int RandomMinMaxScaled(int min, int max) - { - if (min == max) - return min; - - if (min > max) - { - int hold = min; - min = max; - max = hold; - } - - /* Example: - * min: 1 - * max: 5 - * count: 5 - * - * total = (5*5) + (4*4) + (3*3) + (2*2) + (1*1) = 25 + 16 + 9 + 4 + 1 = 55 - * - * chance for min+0 : 25/55 : 45.45% - * chance for min+1 : 16/55 : 29.09% - * chance for min+2 : 9/55 : 16.36% - * chance for min+3 : 4/55 : 7.27% - * chance for min+4 : 1/55 : 1.81% - */ - - int count = max - min + 1; - int total = 0, toAdd = count; - - for (int i = 0; i < count; ++i, --toAdd) - total += toAdd * toAdd; - - int rand = Utility.Random(total); - toAdd = count; - - int val = min; - - for (int i = 0; i < count; ++i, --toAdd, ++val) - { - rand -= toAdd * toAdd; - - if (rand < 0) - break; - } - - return val; - } - - public bool PackSlayer(double chance = 0.05) - { - if (chance <= Utility.RandomDouble()) - return false; - - if (Utility.RandomBool()) - { - BaseInstrument instrument = Loot.RandomInstrument(); - - if (instrument != null) - { - instrument.Slayer = SlayerGroup.GetLootSlayerType(GetType()); - PackItem(instrument); - } - } - else if (!Core.AOS) - { - BaseWeapon weapon = Loot.RandomWeapon(); - - if (weapon != null) - { - weapon.Slayer = SlayerGroup.GetLootSlayerType(GetType()); - PackItem(weapon); - } - } - - return true; - } - - public bool PackWeapon(int minLevel, int maxLevel, double chance = 1.0) - { - if (chance <= Utility.RandomDouble()) - return false; - - Cap(ref minLevel, 0, 5); - Cap(ref maxLevel, 0, 5); - - if (Core.AOS) - { - Item item = Loot.RandomWeaponOrJewelry(); - - if (item == null) - return false; - - GetRandomAOSStats(minLevel, maxLevel, out int attributeCount, out int min, out int max); - - if (item is BaseWeapon weapon) - BaseRunicTool.ApplyAttributesTo(weapon, attributeCount, min, max); - else if (item is BaseJewel jewel) - BaseRunicTool.ApplyAttributesTo(jewel, attributeCount, min, max); - - PackItem(item); - } - else - { - BaseWeapon weapon = Loot.RandomWeapon(); - - if (weapon == null) - return false; - - if (Utility.RandomDouble() < 0.05) - weapon.Slayer = SlayerName.Silver; - - weapon.DamageLevel = (WeaponDamageLevel)RandomMinMaxScaled(minLevel, maxLevel); - weapon.AccuracyLevel = (WeaponAccuracyLevel)RandomMinMaxScaled(minLevel, maxLevel); - weapon.DurabilityLevel = (WeaponDurabilityLevel)RandomMinMaxScaled(minLevel, maxLevel); - - PackItem(weapon); - } - - return true; - } - - public void PackGold(int amount) - { - if (amount > 0) - PackItem(new Gold(amount)); - } - - public void PackGold(int min, int max) - { - PackGold(Utility.RandomMinMax(min, max)); - } - - public void PackStatue(int min, int max) - { - PackStatue(Utility.RandomMinMax(min, max)); - } - - public void PackStatue(int amount) - { - for (int i = 0; i < amount; ++i) - PackStatue(); - } - - public void PackStatue() - { - PackItem(Loot.RandomStatue()); - } - - public void PackGem(int min, int max) - { - PackGem(Utility.RandomMinMax(min, max)); - } - - public void PackGem(int amount = 1) - { - if (amount <= 0) - return; - - Item gem = Loot.RandomGem(); - - gem.Amount = amount; - - PackItem(gem); - } - - public void PackNecroReg(int min, int max) - { - PackNecroReg(Utility.RandomMinMax(min, max)); - } - - public void PackNecroReg(int amount) - { - for (int i = 0; i < amount; ++i) - PackNecroReg(); - } - - public void PackNecroReg() - { - if (!Core.AOS) - return; - - PackItem(Loot.RandomNecromancyReagent()); - } - - public void PackReg(int min, int max) - { - PackReg(Utility.RandomMinMax(min, max)); - } - - public void PackReg(int amount) - { - if (amount <= 0) - return; - - Item reg = Loot.RandomReagent(); - - reg.Amount = amount; - - PackItem(reg); - } - - public void PackItem(Item item) - { - if (item == null) return; - - if (Summoned) - { - item.Delete(); - return; - } - - Container pack = Backpack ?? new Backpack { Movable = false }; - AddItem(pack); - - if (!item.Stackable || !pack.TryDropItem(this, item, false)) // try stack - pack.DropItem(item); // failed, drop it anyway - } - - public virtual bool CanHeal => false; - public virtual bool CanHealOwner => false; - public virtual double HealScalar => 1.0; - - public virtual int HealSound => 0x57; - public virtual int HealStartRange => 2; - public virtual int HealEndRange => RangePerception; - public virtual double HealTrigger => 0.78; - public virtual double HealDelay => 6.5; - public virtual double HealInterval => 0.0; - public virtual bool HealFully => true; - public virtual double HealOwnerTrigger => 0.78; - public virtual double HealOwnerDelay => 6.5; - public virtual double HealOwnerInterval => 30.0; - public virtual bool HealOwnerFully => false; - - private long m_NextHealTime = Core.TickCount; - private long m_NextHealOwnerTime = Core.TickCount; - private Timer m_HealTimer; - - public bool IsHealing => m_HealTimer != null; - - public virtual void HealStart(Mobile patient) - { - bool onSelf = patient == this; - - // DoBeneficial( patient ); - - RevealingAction(); - - if (!onSelf) - { - patient.RevealingAction(); - patient.SendLocalizedMessage(1008078, false, Name); // : Attempting to heal you. - } - - double seconds = (onSelf ? HealDelay : HealOwnerDelay) + (patient.Alive ? 0.0 : 5.0); - - m_HealTimer = Timer.DelayCall(TimeSpan.FromSeconds(seconds), Heal, patient); - } - - public virtual void Heal(Mobile patient) - { - if (!Alive || Map == Map.Internal || !CanBeBeneficial(patient, true, true) || patient.Map != Map || - !InRange(patient, HealEndRange)) - { - StopHeal(); - return; - } - - bool onSelf = patient == this; - - if (!patient.Alive) - { - } - else if (patient.Poisoned) - { - int poisonLevel = patient.Poison.Level; - - double healing = Skills.Healing.Value; - double anatomy = Skills.Anatomy.Value; - double chance = (healing - 30.0) / 50.0 - poisonLevel * 0.1; - - if (healing >= 60.0 && anatomy >= 60.0 && chance > Utility.RandomDouble()) - if (patient.CurePoison(this)) - { - patient.SendLocalizedMessage(1010059); // You have been cured of all poisons. - - CheckSkill(SkillName.Healing, 0.0, 60.0 + poisonLevel * 10.0); // TODO: Verify formula - CheckSkill(SkillName.Anatomy, 0.0, 100.0); - } - } - else if (BleedAttack.IsBleeding(patient)) - { - patient.SendLocalizedMessage(1060167); // The bleeding wounds have healed, you are no longer bleeding! - BleedAttack.EndBleed(patient, false); - } - else - { - double healing = Skills.Healing.Value; - double anatomy = Skills.Anatomy.Value; - double chance = (healing + 10.0) / 100.0; - - if (chance > Utility.RandomDouble()) - { - double min = anatomy / 10.0 + healing / 6.0 + 4.0; - double max = anatomy / 8.0 + healing / 3.0 + 4.0; - - if (onSelf) - max += 10; - - double toHeal = min + Utility.RandomDouble() * (max - min); - - toHeal *= HealScalar; - - patient.Heal((int)toHeal); - - CheckSkill(SkillName.Healing, 0.0, 90.0); - CheckSkill(SkillName.Anatomy, 0.0, 100.0); - } - } - - HealEffect(patient); - - StopHeal(); - - if ((onSelf && HealFully && Hits >= HealTrigger * HitsMax && Hits < HitsMax) || - (!onSelf && HealOwnerFully && patient.Hits >= HealOwnerTrigger * patient.HitsMax && - patient.Hits < patient.HitsMax)) - HealStart(patient); - } - - public virtual void StopHeal() - { - m_HealTimer?.Stop(); - - m_HealTimer = null; - } - - public virtual void HealEffect(Mobile patient) - { - patient.PlaySound(HealSound); - } - - private long m_NextAura; - - public virtual bool HasAura => false; - public virtual TimeSpan AuraInterval => TimeSpan.FromSeconds(5); - public virtual int AuraRange => 4; - - public virtual int AuraBaseDamage => 5; - public virtual int AuraPhysicalDamage => 0; - public virtual int AuraFireDamage => 100; - public virtual int AuraColdDamage => 0; - public virtual int AuraPoisonDamage => 0; - public virtual int AuraEnergyDamage => 0; - public virtual int AuraChaosDamage => 0; - - public virtual void AuraDamage() - { - if (!Alive || IsDeadBondedPet) - return; - - IPooledEnumerable eable = GetMobilesInRange(AuraRange); - - IEnumerable list = eable.Where(m => - m != this && CanBeHarmful(m, false) && (Core.AOS || InLOS(m)) && - ((m is BaseCreature bc && (bc.Controlled || bc.Summoned || bc.Team != Team)) || m.Player)); - - foreach (Mobile m in list) - { - AOS.Damage(m, this, AuraBaseDamage, AuraPhysicalDamage, AuraFireDamage, AuraColdDamage, AuraPoisonDamage, - AuraEnergyDamage, AuraChaosDamage); - AuraEffect(m); - } - - eable.Free(); - } - - public virtual void AuraEffect(Mobile m) - { - } - } - - public class LoyaltyTimer : Timer - { - private static readonly TimeSpan InternalDelay = TimeSpan.FromMinutes(5.0); - - private DateTime m_NextHourlyCheck; - - public LoyaltyTimer() : base(InternalDelay, InternalDelay) - { - m_NextHourlyCheck = DateTime.UtcNow + TimeSpan.FromHours(1.0); - Priority = TimerPriority.FiveSeconds; - } - - public static void Initialize() - { - new LoyaltyTimer().Start(); - } - - protected override void OnTick() - { - if (DateTime.UtcNow >= m_NextHourlyCheck) - m_NextHourlyCheck = DateTime.UtcNow + TimeSpan.FromHours(1.0); - else - return; - - List toRelease = new List(); - - // added array for wild creatures in house regions to be removed - List toRemove = new List(); - - Parallel.ForEach(World.Mobiles.Values, m => - { - if (!(m is BaseCreature c)) - return; - - if (c is BaseMount mount && mount.Rider != null) - { - mount.OwnerAbandonTime = DateTime.MinValue; - return; } - if (c.IsDeadPet) + public static void TeleportPets(Mobile master, Point3D loc, Map map, bool onlyBonded = false) { - Mobile owner = c.ControlMaster; + var move = new List(); - if (!c.IsStabled && (owner?.Deleted != false || owner.Map != c.Map || - !owner.InRange(c, 12) || !c.CanSee(owner) || !c.InLOS(owner))) - { - if (c.OwnerAbandonTime == DateTime.MinValue) - c.OwnerAbandonTime = DateTime.UtcNow; - else if (c.OwnerAbandonTime + c.BondingAbandonDelay <= DateTime.UtcNow) - lock (toRemove) - { - toRemove.Add(c); - } - } - else - { - c.OwnerAbandonTime = DateTime.MinValue; - } + foreach (var m in master.GetMobilesInRange(3)) + if (m is BaseCreature pet) + if (pet.Controlled && pet.ControlMaster == master && !onlyBonded || pet.IsBonded) + if (pet.ControlOrder == OrderType.Guard || pet.ControlOrder == OrderType.Follow || + pet.ControlOrder == OrderType.Come) + move.Add(pet); + + foreach (var m in move) + m.MoveToWorld(loc, map); } - else if (c.Controlled && c.Commandable) + + public virtual void ResurrectPet() { - c.OwnerAbandonTime = DateTime.MinValue; + if (!IsDeadPet) + return; - if (c.Map != Map.Internal) - { - c.Loyalty -= BaseCreature.MaxLoyalty / 10; + OnBeforeResurrect(); - if (c.Loyalty < BaseCreature.MaxLoyalty / 10) + Poison = null; + + Warmode = false; + + Hits = 10; + Stam = StamMax; + Mana = 0; + + ProcessDeltaQueue(); + + IsDeadPet = false; + + Effects.SendPacket(Location, Map, new BondedStatus(Serial, false)); + + SendIncomingPacket(); + SendIncomingPacket(); + + OnAfterResurrect(); + + var owner = ControlMaster; + + if (owner?.Deleted != false || owner.Map != Map || !owner.InRange(this, 12) || !CanSee(owner) || + !InLOS(owner)) { - c.Say(1043270, c.Name); // * ~1_NAME~ looks around desperately * - c.PlaySound(c.GetIdleSound()); + if (OwnerAbandonTime == DateTime.MinValue) + OwnerAbandonTime = DateTime.UtcNow; + } + else + { + OwnerAbandonTime = DateTime.MinValue; } - if (c.Loyalty <= 0) - lock (toRelease) - { - toRelease.Add(c); - } - } + CheckStatTimers(); } - // added lines to check if a wild creature in a house region has to be removed or not - if (!c.Controlled && !c.IsStabled && ((c.Region.IsPartOf() && c.CanBeDamaged()) || - (c.RemoveIfUntamed && c.Spawner == null))) + public override bool CanBeDamaged() { - c.RemoveStep++; + if (IsDeadPet || IsInvulnerable) + return false; - if (c.RemoveStep >= 20) - lock (toRemove) + return base.CanBeDamaged(); + } + + private bool IsSpawnerBound() => + Map != null && Map != Map.Internal && + FightMode != FightMode.None && RangeHome >= 0 && + !Controlled && !Summoned && Spawner is Spawner spawner && spawner.Map == Map; + + public override void OnSectorDeactivate() + { + if (!Deleted && ReturnsToHome && IsSpawnerBound() && !InRange(Home, RangeHome + 5)) { - toRemove.Add(c); + Timer.DelayCall(TimeSpan.FromSeconds(Utility.Random(45) + 15), GoHome_Callback); + + m_ReturnQueued = true; + } + else if (PlayerRangeSensitive) + { + AIObject?.Deactivate(); + } + + base.OnSectorDeactivate(); + } + + public void GoHome_Callback() + { + if (m_ReturnQueued && IsSpawnerBound()) + if (!Map.GetSector(X, Y).Active) + { + SetLocation(Home, true); + + if (!Map.GetSector(X, Y).Active) AIObject?.Deactivate(); + } + + m_ReturnQueued = false; + } + + public override void OnSectorActivate() + { + if (PlayerRangeSensitive) AIObject?.Activate(); + + base.OnSectorActivate(); + } + + protected virtual List ConstructQuestList() => null; + + private void CheckShout(PlayerMobile pm, Point3D oldLocation) + { + if (m_MLNextShout > DateTime.UtcNow || pm.Hidden || !pm.Alive) + return; + + var shoutRange = ShoutRange; + + if (!InRange(pm.Location, shoutRange) || InRange(oldLocation, shoutRange) || !CanSee(pm) || !InLOS(pm)) + return; + + var context = MLQuestSystem.GetContext(pm); + + if (context?.IsFull == true) + return; + + var quest = MLQuestSystem.RandomStarterQuest(this, pm, context); + + if (quest?.Activated != true || context?.IsDoingQuest(quest) == true) + return; + + Shout(pm); + m_MLNextShout = DateTime.UtcNow + ShoutDelay; + } + + public virtual void Shout(PlayerMobile pm) + { + } + + public static void Initialize() + { + BondingEnabled = ServerConfiguration.GetOrUpdateSetting("taming.enableBonding", true); + } + + public void BeginDeleteTimer() + { + if (!(this is BaseEscortable) && !Summoned && !Deleted && !IsStabled) + { + StopDeleteTimer(); + m_DeleteTimer = new DeleteTimer(this, TimeSpan.FromDays(3.0)); + m_DeleteTimer.Start(); } } - else + + public void StopDeleteTimer() { - c.RemoveStep = 0; + if (m_DeleteTimer != null) + { + m_DeleteTimer.Stop(); + m_DeleteTimer = null; + } } - }); - // TODO: Parallelize this - foreach (BaseCreature c in toRelease) - { - c.Say(1043255, c.Name); // ~1_NAME~ appears to have decided that is better off without a master! - c.Loyalty = BaseCreature.MaxLoyalty; // Wonderfully Happy - c.IsBonded = false; - c.BondingBegin = DateTime.MinValue; - c.OwnerAbandonTime = DateTime.MinValue; - c.ControlTarget = null; - c.AIObject - .DoOrderRelease(); // this will prevent no release of creatures left alone with AI disabled (and consequent bug of Followers) - c.DropBackpack(); - } + public virtual void BreathStart(Mobile target) + { + BreathStallMovement(); + BreathPlayAngerSound(); + BreathPlayAngerAnimation(); - foreach (BaseCreature c in toRemove) - c.Delete(); + Direction = GetDirectionTo(target); + + Timer.DelayCall(TimeSpan.FromSeconds(BreathEffectDelay), BreathEffect_Callback, target); + } + + public virtual void BreathStallMovement() + { + if (AIObject != null) + AIObject.NextMove = Core.TickCount + (int)(BreathStallTime * 1000); + } + + public virtual void BreathPlayAngerSound() + { + PlaySound(BreathAngerSound); + } + + public virtual void BreathPlayAngerAnimation() + { + Animate(BreathAngerAnimation, 5, 1, true, false, 0); + } + + public virtual void BreathEffect_Callback(Mobile target) + { + if (!target.Alive || !CanBeHarmful(target)) + return; + + BreathPlayEffectSound(); + BreathPlayEffect(target); + + Timer.DelayCall(TimeSpan.FromSeconds(BreathDamageDelay), BreathDamage_Callback, target); + } + + public virtual void BreathPlayEffectSound() + { + PlaySound(BreathEffectSound); + } + + public virtual void BreathPlayEffect(Mobile target) + { + Effects.SendMovingEffect( + this, + target, + BreathEffectItemID, + BreathEffectSpeed, + BreathEffectDuration, + BreathEffectFixedDir, + BreathEffectExplodes, + BreathEffectHue, + BreathEffectRenderMode + ); + } + + public virtual void BreathDamage_Callback(Mobile target) + { + if (target is BaseCreature creature && creature.BreathImmune) + return; + + if (CanBeHarmful(target)) + { + DoHarmful(target); + BreathDealDamage(target); + } + } + + public virtual void BreathDealDamage(Mobile target) + { + if (!Evasion.CheckSpellEvasion(target)) + { + var physDamage = BreathPhysicalDamage; + var fireDamage = BreathFireDamage; + var coldDamage = BreathColdDamage; + var poisDamage = BreathPoisonDamage; + var nrgyDamage = BreathEnergyDamage; + + if (BreathChaosDamage > 0) + switch (Utility.Random(5)) + { + case 0: + physDamage += BreathChaosDamage; + break; + case 1: + fireDamage += BreathChaosDamage; + break; + case 2: + coldDamage += BreathChaosDamage; + break; + case 3: + poisDamage += BreathChaosDamage; + break; + case 4: + nrgyDamage += BreathChaosDamage; + break; + } + + if (physDamage == 0 && fireDamage == 0 && coldDamage == 0 && poisDamage == 0 && nrgyDamage == 0) + target.Damage(BreathComputeDamage(), this); // Unresistable damage even in AOS + else + AOS.Damage( + target, + this, + BreathComputeDamage(), + physDamage, + fireDamage, + coldDamage, + poisDamage, + nrgyDamage + ); + } + } + + public virtual int BreathComputeDamage() + { + var damage = (int)(Hits * BreathDamageScalar); + + if (IsParagon) + damage = (int)(damage / Paragon.HitsBuff); + + if (damage > 200) + damage = 200; + + return damage; + } + + public void SpillAcid(int amount) + { + SpillAcid(null, amount); + } + + public void SpillAcid(Mobile target, int amount) + { + if (target != null && target.Map == null || Map == null) + return; + + for (var i = 0; i < amount; ++i) + { + Point3D loc; + var map = Map; + + if (target != null && amount == 1) + { + loc = target.Location; + map = target.Map; + } + else + { + loc = map.GetRandomNearbyLocation(Location); + } + + var acid = NewHarmfulItem(); + acid.MoveToWorld(loc, map); + } + } + + /* + Solen Style, override me for other mobiles/items: + kappa+acidslime, grizzles+whatever, etc. + */ + + public virtual Item NewHarmfulItem() => new PoolOfAcid(TimeSpan.FromSeconds(10), 30, 30); + + public virtual void StopFlee() + { + EndFleeTime = DateTime.MinValue; + } + + public virtual bool CheckFlee() + { + if (EndFleeTime == DateTime.MinValue) + return false; + + if (DateTime.UtcNow >= EndFleeTime) + { + StopFlee(); + return false; + } + + return true; + } + + public virtual void BeginFlee(TimeSpan maxDuration) + { + EndFleeTime = DateTime.UtcNow + maxDuration; + } + + public virtual bool IsPetFriend(Mobile m) => Friends.Contains(m); + + public virtual void AddPetFriend(Mobile m) + { + Friends ??= new List(); + + Friends.Add(m); + } + + public virtual void RemovePetFriend(Mobile m) + { + Friends?.Remove(m); + } + + public virtual bool IsFriend(Mobile m) => + OppositionGroup?.IsEnemy(this, m) != true && m is BaseCreature c && m_Team == c.m_Team + && (m_bSummoned || m_Controlled) == (c.m_bSummoned || c.m_Controlled); + + public virtual Allegiance GetFactionAllegiance(Mobile mob) + { + if (mob == null || mob.Map != Faction.Facet || FactionAllegiance == null) + return Allegiance.None; + + var fac = Faction.Find(mob, true); + + if (fac == null) + return Allegiance.None; + + return fac == FactionAllegiance ? Allegiance.Ally : Allegiance.Enemy; + } + + public virtual Allegiance GetEthicAllegiance(Mobile mob) + { + if (mob == null || mob.Map != Faction.Facet || EthicAllegiance == null) + return Allegiance.None; + + var ethic = Ethic.Find(mob, true); + + if (ethic == null) + return Allegiance.None; + + return ethic == EthicAllegiance ? Allegiance.Ally : Allegiance.Enemy; + } + + public virtual void AlterDamageScalarFrom(Mobile caster, ref double scalar) + { + } + + public virtual void AlterDamageScalarTo(Mobile target, ref double scalar) + { + } + + public virtual void AlterSpellDamageFrom(Mobile from, ref int damage) + { + } + + public virtual void AlterSpellDamageTo(Mobile to, ref int damage) + { + } + + public virtual void AlterMeleeDamageFrom(Mobile from, ref int damage) + { + } + + public virtual void AlterMeleeDamageTo(Mobile to, ref int damage) + { + } + + public virtual bool CheckFoodPreference(Item f) + { + if (CheckFoodPreference(f, FoodType.Eggs, m_Eggs)) + return true; + + if (CheckFoodPreference(f, FoodType.Fish, m_Fish)) + return true; + + if (CheckFoodPreference(f, FoodType.GrainsAndHay, m_GrainsAndHay)) + return true; + + if (CheckFoodPreference(f, FoodType.Meat, m_Meat)) + return true; + + if (CheckFoodPreference(f, FoodType.FruitsAndVegies, m_FruitsAndVegies)) + return true; + + if (CheckFoodPreference(f, FoodType.Gold, m_Gold)) + return true; + + return false; + } + + public virtual bool CheckFoodPreference(Item fed, FoodType type, Type[] types) + { + if ((FavoriteFood & type) == 0) + return false; + + var fedType = fed.GetType(); + var contains = false; + + for (var i = 0; !contains && i < types.Length; ++i) + contains = fedType == types[i]; + + return contains; + } + + public virtual bool CheckFeed(Mobile from, Item dropped) + { + if (!IsDeadPet && Controlled && (ControlMaster == from || IsPetFriend(from))) + { + var f = dropped; + + if (CheckFoodPreference(f)) + { + var amount = f.Amount; + + if (amount > 0) + { + int stamGain; + + if (f is Gold) + stamGain = amount - 50; + else + stamGain = amount * 15 - 50; + + if (stamGain > 0) + Stam += stamGain; + + if (Core.SE) + { + if (m_Loyalty < MaxLoyalty) m_Loyalty = MaxLoyalty; + } + else + { + for (var i = 0; i < amount; ++i) + if (m_Loyalty < MaxLoyalty && Utility.RandomDouble() <= 0.5) + m_Loyalty += 10; + } + + /* if (happier )*/ + // looks like in OSI pets say they are happier even if they are at maximum loyalty + SayTo(from, 502060); // Your pet looks happier. + + if (Body.IsAnimal) + Animate(3, 5, 1, true, false, 0); + else if (Body.IsMonster) + Animate(17, 5, 1, true, false, 0); + + if (IsBondable && !IsBonded) + { + var master = m_ControlMaster; + + if (master != null && master == from) // So friends can't start the bonding process + { + if (MinTameSkill <= 29.1 || master.Skills.AnimalTaming.Base >= MinTameSkill || + OverrideBondingReqs() || + Core.ML && master.Skills.AnimalTaming.Value >= MinTameSkill) + { + if (BondingBegin == DateTime.MinValue) + { + BondingBegin = DateTime.UtcNow; + } + else if (BondingBegin + BondingDelay <= DateTime.UtcNow) + { + IsBonded = true; + BondingBegin = DateTime.MinValue; + from.SendLocalizedMessage(1049666); // Your pet has bonded with you! + } + } + else if (Core.ML) + { + from.SendLocalizedMessage( + 1075268 + ); // Your pet cannot form a bond with you until your animal taming ability has risen. + } + } + } + + dropped.Delete(); + return true; + } + } + } + + return false; + } + + public virtual void OnActionWander() + { + } + + public virtual void OnActionCombat() + { + } + + public virtual void OnActionGuard() + { + } + + public virtual void OnActionFlee() + { + } + + public virtual void OnActionInteract() + { + } + + public virtual void OnActionBackoff() + { + } + + public virtual bool CheckTeach(SkillName skill, Mobile from) + { + if (!CanTeach) + return false; + + if (skill == SkillName.Stealth && from.Skills.Hiding.Base < Stealth.HidingRequirement) + return false; + + if (skill == SkillName.RemoveTrap && (from.Skills.Lockpicking.Base < 50.0 || + from.Skills.DetectHidden.Base < 50.0)) + return false; + + if (!Core.AOS && (skill == SkillName.Focus || skill == SkillName.Chivalry || skill == SkillName.Necromancy)) + return false; + + return true; + } + + public virtual TeachResult CheckTeachSkills( + SkillName skill, Mobile m, int maxPointsToLearn, ref int pointsToLearn, + bool doTeach + ) + { + if (!CheckTeach(skill, m) || !m.CheckAlive()) + return TeachResult.Failure; + + var ourSkill = Skills[skill]; + var theirSkill = m.Skills[skill]; + + if (ourSkill == null || theirSkill == null) + return TeachResult.Failure; + + var baseToSet = ourSkill.BaseFixedPoint / 3; + + if (baseToSet > 420) + baseToSet = 420; + else if (baseToSet < 200) + return TeachResult.Failure; + + if (baseToSet > theirSkill.CapFixedPoint) + baseToSet = theirSkill.CapFixedPoint; + + pointsToLearn = baseToSet - theirSkill.BaseFixedPoint; + + if (maxPointsToLearn > 0 && pointsToLearn > maxPointsToLearn) + { + pointsToLearn = maxPointsToLearn; + baseToSet = theirSkill.BaseFixedPoint + pointsToLearn; + } + + if (pointsToLearn < 0) + return TeachResult.KnowsMoreThanMe; + + if (pointsToLearn == 0) + return TeachResult.KnowsWhatIKnow; + + if (theirSkill.Lock != SkillLock.Up) + return TeachResult.SkillNotRaisable; + + var freePoints = Math.Max(m.Skills.Cap - m.Skills.Total, 0); + var freeablePoints = 0; + + for (var i = 0; freePoints + freeablePoints < pointsToLearn && i < m.Skills.Length; ++i) + { + var sk = m.Skills[i]; + + if (sk == theirSkill || sk.Lock != SkillLock.Down) + continue; + + freeablePoints += sk.BaseFixedPoint; + } + + if (freePoints + freeablePoints == 0) + return TeachResult.NotEnoughFreePoints; + + if (freePoints + freeablePoints < pointsToLearn) + { + pointsToLearn = freePoints + freeablePoints; + baseToSet = theirSkill.BaseFixedPoint + pointsToLearn; + } + + if (doTeach) + { + var need = pointsToLearn - freePoints; + + for (var i = 0; need > 0 && i < m.Skills.Length; ++i) + { + var sk = m.Skills[i]; + + if (sk == theirSkill || sk.Lock != SkillLock.Down) + continue; + + if (sk.BaseFixedPoint < need) + { + need -= sk.BaseFixedPoint; + sk.BaseFixedPoint = 0; + } + else + { + sk.BaseFixedPoint -= need; + need = 0; + } + } + + /* Sanity check */ + if (baseToSet > theirSkill.CapFixedPoint || + m.Skills.Total - theirSkill.BaseFixedPoint + baseToSet > m.Skills.Cap) + return TeachResult.NotEnoughFreePoints; + + theirSkill.BaseFixedPoint = baseToSet; + } + + return TeachResult.Success; + } + + public virtual bool CheckTeachingMatch(Mobile m) + { + if (m_Teaching == (SkillName)(-1)) + return false; + + if (m is PlayerMobile mobile) + return mobile.Learning == m_Teaching; + + return true; + } + + public virtual bool Teach(SkillName skill, Mobile m, int maxPointsToLearn, bool doTeach) + { + var pointsToLearn = 0; + var res = CheckTeachSkills(skill, m, maxPointsToLearn, ref pointsToLearn, doTeach); + + switch (res) + { + case TeachResult.KnowsMoreThanMe: + { + Say(501508); // I cannot teach thee, for thou knowest more than I! + break; + } + case TeachResult.KnowsWhatIKnow: + { + Say(501509); // I cannot teach thee, for thou knowest all I can teach! + break; + } + case TeachResult.NotEnoughFreePoints: + case TeachResult.SkillNotRaisable: + { + // Make sure this skill is marked to raise. If you are near the skill cap (700 points) you may need to lose some points in another skill first. + m.SendLocalizedMessage(501510, "", 0x22); + break; + } + case TeachResult.Success: + { + if (doTeach) + { + Say(501539); // Let me show thee something of how this is done. + m.SendLocalizedMessage(501540); // Your skill level increases. + + m_Teaching = (SkillName)(-1); + + if (m is PlayerMobile mobile) + mobile.Learning = (SkillName)(-1); + } + else + { + // I will teach thee all I know, if paid the amount in full. The price is: + Say(1019077, AffixType.Append, $" {pointsToLearn}", ""); + Say(1043108); // For less I shall teach thee less. + + m_Teaching = skill; + + if (m is PlayerMobile mobile) + mobile.Learning = skill; + } + + return true; + } + } + + return false; + } + + public void SetDamage(int val) + { + m_DamageMin = val; + m_DamageMax = val; + } + + public void SetDamage(int min, int max) + { + m_DamageMin = min; + m_DamageMax = max; + } + + public void SetHits(int val) + { + if (val < 1000 && !Core.AOS) + val = val * 100 / 60; + + HitsMaxSeed = val; + Hits = HitsMax; + } + + public void SetHits(int min, int max) + { + if (min < 1000 && !Core.AOS) + { + min = min * 100 / 60; + max = max * 100 / 60; + } + + HitsMaxSeed = Utility.RandomMinMax(min, max); + Hits = HitsMax; + } + + public void SetStam(int val) + { + StamMaxSeed = val; + Stam = StamMax; + } + + public void SetStam(int min, int max) + { + StamMaxSeed = Utility.RandomMinMax(min, max); + Stam = StamMax; + } + + public void SetMana(int val) + { + ManaMaxSeed = val; + Mana = ManaMax; + } + + public void SetMana(int min, int max) + { + ManaMaxSeed = Utility.RandomMinMax(min, max); + Mana = ManaMax; + } + + public void SetStr(int val) + { + RawStr = val; + Hits = HitsMax; + } + + public void SetStr(int min, int max) + { + RawStr = Utility.RandomMinMax(min, max); + Hits = HitsMax; + } + + public void SetDex(int val) + { + RawDex = val; + Stam = StamMax; + } + + public void SetDex(int min, int max) + { + RawDex = Utility.RandomMinMax(min, max); + Stam = StamMax; + } + + public void SetInt(int val) + { + RawInt = val; + Mana = ManaMax; + } + + public void SetInt(int min, int max) + { + RawInt = Utility.RandomMinMax(min, max); + Mana = ManaMax; + } + + public void SetDamageType(ResistanceType type, int min, int max) + { + SetDamageType(type, Utility.RandomMinMax(min, max)); + } + + public void SetDamageType(ResistanceType type, int val) + { + switch (type) + { + case ResistanceType.Physical: + PhysicalDamage = val; + break; + case ResistanceType.Fire: + FireDamage = val; + break; + case ResistanceType.Cold: + ColdDamage = val; + break; + case ResistanceType.Poison: + PoisonDamage = val; + break; + case ResistanceType.Energy: + EnergyDamage = val; + break; + } + } + + public void SetResistance(ResistanceType type, int min, int max) + { + SetResistance(type, Utility.RandomMinMax(min, max)); + } + + public void SetResistance(ResistanceType type, int val) + { + switch (type) + { + case ResistanceType.Physical: + m_PhysicalResistance = val; + break; + case ResistanceType.Fire: + m_FireResistance = val; + break; + case ResistanceType.Cold: + m_ColdResistance = val; + break; + case ResistanceType.Poison: + m_PoisonResistance = val; + break; + case ResistanceType.Energy: + m_EnergyResistance = val; + break; + } + + UpdateResistances(); + } + + public void SetSkill(SkillName name, double val) + { + Skills[name].BaseFixedPoint = (int)(val * 10); + + if (Skills[name].Base > Skills[name].Cap) + { + if (Core.SE) + SkillsCap += Skills[name].BaseFixedPoint - Skills[name].CapFixedPoint; + + Skills[name].Cap = Skills[name].Base; + } + } + + public void SetSkill(SkillName name, double min, double max) + { + var minFixed = (int)(min * 10); + var maxFixed = (int)(max * 10); + + Skills[name].BaseFixedPoint = Utility.RandomMinMax(minFixed, maxFixed); + + if (Skills[name].Base > Skills[name].Cap) + { + if (Core.SE) + SkillsCap += Skills[name].BaseFixedPoint - Skills[name].CapFixedPoint; + + Skills[name].Cap = Skills[name].Base; + } + } + + public void SetFameLevel(int level) + { + Fame = level switch + { + 1 => Utility.RandomMinMax(0, 1249), + 2 => Utility.RandomMinMax(1250, 2499), + 3 => Utility.RandomMinMax(2500, 4999), + 4 => Utility.RandomMinMax(5000, 9999), + 5 => Utility.RandomMinMax(10000, 10000), + _ => Fame + }; + } + + public void SetKarmaLevel(int level) + { + Karma = level switch + { + 0 => -Utility.RandomMinMax(0, 624), + 1 => -Utility.RandomMinMax(625, 1249), + 2 => -Utility.RandomMinMax(1250, 2499), + 3 => -Utility.RandomMinMax(2500, 4999), + 4 => -Utility.RandomMinMax(5000, 9999), + 5 => -Utility.RandomMinMax(10000, 10000), + _ => Karma + }; + } + + public void PackArcaneScroll(int min, int max) + { + PackArcaneScroll(Utility.RandomMinMax(min, max)); + } + + public void PackArcaneScroll(int amount) + { + for (var i = 0; i < amount; ++i) + PackArcaneScroll(); + } + + public void PackArcaneScroll() + { + if (!Core.ML) + return; + + PackItem(Loot.Construct(Loot.ArcanistScrollTypes)); + } + + public void PackPotion() + { + PackItem(Loot.RandomPotion()); + } + + public void PackArcanceScroll(double chance) + { + if (!Core.ML || chance <= Utility.RandomDouble()) + return; + + PackItem(Loot.Construct(Loot.ArcanistScrollTypes)); + } + + public void PackNecroScroll(int index) + { + if (!Core.AOS || Utility.RandomDouble() >= 0.05) + return; + + PackItem(Loot.Construct(Loot.NecromancyScrollTypes, index)); + } + + public void PackScroll(int minCircle, int maxCircle) + { + PackScroll(Utility.RandomMinMax(minCircle, maxCircle)); + } + + public void PackScroll(int circle) + { + var min = (circle - 1) * 8; + + PackItem(Loot.RandomScroll(min, min + 7, SpellbookType.Regular)); + } + + public void PackMagicItems(int minLevel, int maxLevel, double armorChance = 0.30, double weaponChance = 0.15) + { + if (!PackArmor(minLevel, maxLevel, armorChance)) + PackWeapon(minLevel, maxLevel, weaponChance); + } + + public virtual void DropBackpack() + { + if (Backpack?.Items.Count > 0) + { + Backpack b = new CreatureBackpack(Name); + + var list = new List(Backpack.Items); + foreach (var item in list) b.DropItem(item); + + var house = BaseHouse.FindHouseAt(this); + if (house != null) + b.MoveToWorld(house.BanLocation, house.Map); + else + b.MoveToWorld(Location, Map); + } + } + + public virtual void GenerateLoot(bool spawning) + { + m_Spawning = spawning; + + if (!spawning) + m_KillersLuck = LootPack.GetLuckChanceForKiller(this); + + GenerateLoot(); + + if (m_Paragon) + { + if (Fame < 1250) + AddLoot(LootPack.Meager); + else if (Fame < 2500) + AddLoot(LootPack.Average); + else if (Fame < 5000) + AddLoot(LootPack.Rich); + else if (Fame < 10000) + AddLoot(LootPack.FilthyRich); + else + AddLoot(LootPack.UltraRich); + } + + m_Spawning = false; + m_KillersLuck = 0; + } + + public virtual void GenerateLoot() + { + } + + public virtual void AddLoot(LootPack pack, int amount) + { + for (var i = 0; i < amount; ++i) + AddLoot(pack); + } + + public virtual void AddLoot(LootPack pack) + { + if (Summoned) + return; + + var backpack = Backpack ?? new Backpack { Movable = false }; + AddItem(backpack); + + pack.Generate(this, backpack, m_Spawning, m_KillersLuck); + } + + public bool PackArmor(int minLevel, int maxLevel) => PackArmor(minLevel, maxLevel, 1.0); + + public bool PackArmor(int minLevel, int maxLevel, double chance) + { + if (chance <= Utility.RandomDouble()) + return false; + + Cap(ref minLevel, 0, 5); + Cap(ref maxLevel, 0, 5); + + if (Core.AOS) + { + var item = Loot.RandomArmorOrShieldOrJewelry(); + + if (item == null) + return false; + + GetRandomAOSStats(minLevel, maxLevel, out var attributeCount, out var min, out var max); + + if (item is BaseArmor armor) + BaseRunicTool.ApplyAttributesTo(armor, attributeCount, min, max); + else if (item is BaseJewel jewel) + BaseRunicTool.ApplyAttributesTo(jewel, attributeCount, min, max); + + PackItem(item); + } + else + { + var armor = Loot.RandomArmorOrShield(); + + if (armor == null) + return false; + + armor.ProtectionLevel = (ArmorProtectionLevel)RandomMinMaxScaled(minLevel, maxLevel); + armor.Durability = (ArmorDurabilityLevel)RandomMinMaxScaled(minLevel, maxLevel); + + PackItem(armor); + } + + return true; + } + + public static void GetRandomAOSStats(int minLevel, int maxLevel, out int attributeCount, out int min, out int max) + { + var v = RandomMinMaxScaled(minLevel, maxLevel); + + if (v >= 5) + { + attributeCount = Utility.RandomMinMax(2, 6); + min = 20; + max = 70; + } + else if (v == 4) + { + attributeCount = Utility.RandomMinMax(2, 4); + min = 20; + max = 50; + } + else if (v == 3) + { + attributeCount = Utility.RandomMinMax(2, 3); + min = 20; + max = 40; + } + else if (v == 2) + { + attributeCount = Utility.RandomMinMax(1, 2); + min = 10; + max = 30; + } + else + { + attributeCount = 1; + min = 10; + max = 20; + } + } + + public static int RandomMinMaxScaled(int min, int max) + { + if (min == max) + return min; + + if (min > max) + { + var hold = min; + min = max; + max = hold; + } + + /* Example: + * min: 1 + * max: 5 + * count: 5 + * + * total = (5*5) + (4*4) + (3*3) + (2*2) + (1*1) = 25 + 16 + 9 + 4 + 1 = 55 + * + * chance for min+0 : 25/55 : 45.45% + * chance for min+1 : 16/55 : 29.09% + * chance for min+2 : 9/55 : 16.36% + * chance for min+3 : 4/55 : 7.27% + * chance for min+4 : 1/55 : 1.81% + */ + + var count = max - min + 1; + int total = 0, toAdd = count; + + for (var i = 0; i < count; ++i, --toAdd) + total += toAdd * toAdd; + + var rand = Utility.Random(total); + toAdd = count; + + var val = min; + + for (var i = 0; i < count; ++i, --toAdd, ++val) + { + rand -= toAdd * toAdd; + + if (rand < 0) + break; + } + + return val; + } + + public bool PackSlayer(double chance = 0.05) + { + if (chance <= Utility.RandomDouble()) + return false; + + if (Utility.RandomBool()) + { + var instrument = Loot.RandomInstrument(); + + if (instrument != null) + { + instrument.Slayer = SlayerGroup.GetLootSlayerType(GetType()); + PackItem(instrument); + } + } + else if (!Core.AOS) + { + var weapon = Loot.RandomWeapon(); + + if (weapon != null) + { + weapon.Slayer = SlayerGroup.GetLootSlayerType(GetType()); + PackItem(weapon); + } + } + + return true; + } + + public bool PackWeapon(int minLevel, int maxLevel, double chance = 1.0) + { + if (chance <= Utility.RandomDouble()) + return false; + + Cap(ref minLevel, 0, 5); + Cap(ref maxLevel, 0, 5); + + if (Core.AOS) + { + var item = Loot.RandomWeaponOrJewelry(); + + if (item == null) + return false; + + GetRandomAOSStats(minLevel, maxLevel, out var attributeCount, out var min, out var max); + + if (item is BaseWeapon weapon) + BaseRunicTool.ApplyAttributesTo(weapon, attributeCount, min, max); + else if (item is BaseJewel jewel) + BaseRunicTool.ApplyAttributesTo(jewel, attributeCount, min, max); + + PackItem(item); + } + else + { + var weapon = Loot.RandomWeapon(); + + if (weapon == null) + return false; + + if (Utility.RandomDouble() < 0.05) + weapon.Slayer = SlayerName.Silver; + + weapon.DamageLevel = (WeaponDamageLevel)RandomMinMaxScaled(minLevel, maxLevel); + weapon.AccuracyLevel = (WeaponAccuracyLevel)RandomMinMaxScaled(minLevel, maxLevel); + weapon.DurabilityLevel = (WeaponDurabilityLevel)RandomMinMaxScaled(minLevel, maxLevel); + + PackItem(weapon); + } + + return true; + } + + public void PackGold(int amount) + { + if (amount > 0) + PackItem(new Gold(amount)); + } + + public void PackGold(int min, int max) + { + PackGold(Utility.RandomMinMax(min, max)); + } + + public void PackStatue(int min, int max) + { + PackStatue(Utility.RandomMinMax(min, max)); + } + + public void PackStatue(int amount) + { + for (var i = 0; i < amount; ++i) + PackStatue(); + } + + public void PackStatue() + { + PackItem(Loot.RandomStatue()); + } + + public void PackGem(int min, int max) + { + PackGem(Utility.RandomMinMax(min, max)); + } + + public void PackGem(int amount = 1) + { + if (amount <= 0) + return; + + var gem = Loot.RandomGem(); + + gem.Amount = amount; + + PackItem(gem); + } + + public void PackNecroReg(int min, int max) + { + PackNecroReg(Utility.RandomMinMax(min, max)); + } + + public void PackNecroReg(int amount) + { + for (var i = 0; i < amount; ++i) + PackNecroReg(); + } + + public void PackNecroReg() + { + if (!Core.AOS) + return; + + PackItem(Loot.RandomNecromancyReagent()); + } + + public void PackReg(int min, int max) + { + PackReg(Utility.RandomMinMax(min, max)); + } + + public void PackReg(int amount) + { + if (amount <= 0) + return; + + var reg = Loot.RandomReagent(); + + reg.Amount = amount; + + PackItem(reg); + } + + public void PackItem(Item item) + { + if (item == null) return; + + if (Summoned) + { + item.Delete(); + return; + } + + var pack = Backpack ?? new Backpack { Movable = false }; + AddItem(pack); + + if (!item.Stackable || !pack.TryDropItem(this, item, false)) // try stack + pack.DropItem(item); // failed, drop it anyway + } + + public virtual void HealStart(Mobile patient) + { + var onSelf = patient == this; + + // DoBeneficial( patient ); + + RevealingAction(); + + if (!onSelf) + { + patient.RevealingAction(); + patient.SendLocalizedMessage(1008078, false, Name); // : Attempting to heal you. + } + + var seconds = (onSelf ? HealDelay : HealOwnerDelay) + (patient.Alive ? 0.0 : 5.0); + + m_HealTimer = Timer.DelayCall(TimeSpan.FromSeconds(seconds), Heal, patient); + } + + public virtual void Heal(Mobile patient) + { + if (!Alive || Map == Map.Internal || !CanBeBeneficial(patient, true, true) || patient.Map != Map || + !InRange(patient, HealEndRange)) + { + StopHeal(); + return; + } + + var onSelf = patient == this; + + if (!patient.Alive) + { + } + else if (patient.Poisoned) + { + var poisonLevel = patient.Poison.Level; + + var healing = Skills.Healing.Value; + var anatomy = Skills.Anatomy.Value; + var chance = (healing - 30.0) / 50.0 - poisonLevel * 0.1; + + if (healing >= 60.0 && anatomy >= 60.0 && chance > Utility.RandomDouble()) + if (patient.CurePoison(this)) + { + patient.SendLocalizedMessage(1010059); // You have been cured of all poisons. + + CheckSkill(SkillName.Healing, 0.0, 60.0 + poisonLevel * 10.0); // TODO: Verify formula + CheckSkill(SkillName.Anatomy, 0.0, 100.0); + } + } + else if (BleedAttack.IsBleeding(patient)) + { + patient.SendLocalizedMessage(1060167); // The bleeding wounds have healed, you are no longer bleeding! + BleedAttack.EndBleed(patient, false); + } + else + { + var healing = Skills.Healing.Value; + var anatomy = Skills.Anatomy.Value; + var chance = (healing + 10.0) / 100.0; + + if (chance > Utility.RandomDouble()) + { + var min = anatomy / 10.0 + healing / 6.0 + 4.0; + var max = anatomy / 8.0 + healing / 3.0 + 4.0; + + if (onSelf) + max += 10; + + var toHeal = min + Utility.RandomDouble() * (max - min); + + toHeal *= HealScalar; + + patient.Heal((int)toHeal); + + CheckSkill(SkillName.Healing, 0.0, 90.0); + CheckSkill(SkillName.Anatomy, 0.0, 100.0); + } + } + + HealEffect(patient); + + StopHeal(); + + if (onSelf && HealFully && Hits >= HealTrigger * HitsMax && Hits < HitsMax || + !onSelf && HealOwnerFully && patient.Hits >= HealOwnerTrigger * patient.HitsMax && + patient.Hits < patient.HitsMax) + HealStart(patient); + } + + public virtual void StopHeal() + { + m_HealTimer?.Stop(); + + m_HealTimer = null; + } + + public virtual void HealEffect(Mobile patient) + { + patient.PlaySound(HealSound); + } + + public virtual void AuraDamage() + { + if (!Alive || IsDeadBondedPet) + return; + + var eable = GetMobilesInRange(AuraRange); + + var list = eable.Where( + m => + m != this && CanBeHarmful(m, false) && (Core.AOS || InLOS(m)) && + (m is BaseCreature bc && (bc.Controlled || bc.Summoned || bc.Team != Team) || m.Player) + ); + + foreach (var m in list) + { + AOS.Damage( + m, + this, + AuraBaseDamage, + AuraPhysicalDamage, + AuraFireDamage, + AuraColdDamage, + AuraPoisonDamage, + AuraEnergyDamage, + AuraChaosDamage + ); + AuraEffect(m); + } + + eable.Free(); + } + + public virtual void AuraEffect(Mobile m) + { + } + + private class TameEntry : ContextMenuEntry + { + private readonly BaseCreature m_Mobile; + + public TameEntry(Mobile from, BaseCreature creature) : base(6130, 6) + { + m_Mobile = creature; + + Enabled = Enabled && (from.Female ? creature.AllowFemaleTamer : creature.AllowMaleTamer); + } + + public override void OnClick() + { + if (!Owner.From.CheckAlive()) + return; + + Owner.From.TargetLocked = true; + AnimalTaming.DisableMessage = true; + + if (Owner.From.UseSkill(SkillName.AnimalTaming)) + Owner.From.Target.Invoke(Owner.From, m_Mobile); + + AnimalTaming.DisableMessage = false; + Owner.From.TargetLocked = false; + } + } + + private class DeathAdderCharmTarget : Target + { + private readonly BaseCreature m_Charmed; + + public DeathAdderCharmTarget(BaseCreature charmed) : base(-1, false, TargetFlags.Harmful) => m_Charmed = charmed; + + protected override void OnTarget(Mobile from, object targeted) + { + if (!m_Charmed.DeathAdderCharmable || m_Charmed.Combatant != null || !from.CanBeHarmful(m_Charmed, false)) + return; + + if (!(SummonFamiliarSpell.Table.TryGetValue(from, out var bc) && (bc as DeathAdder)?.Deleted == false)) + return; + + if (!(targeted is Mobile targ && from.CanBeHarmful(targ, false))) + return; + + from.RevealingAction(); + from.DoHarmful(targ, true); + + m_Charmed.Combatant = targ; + + if (m_Charmed.AIObject != null) + m_Charmed.AIObject.Action = ActionType.Combat; + } + } + + private class DeleteTimer : Timer + { + private readonly Mobile m; + + public DeleteTimer(Mobile creature, TimeSpan delay) : base(delay) + { + m = creature; + Priority = TimerPriority.OneMinute; + } + + protected override void OnTick() + { + m.Delete(); + } + } + } + + public class LoyaltyTimer : Timer + { + private static readonly TimeSpan InternalDelay = TimeSpan.FromMinutes(5.0); + + private DateTime m_NextHourlyCheck; + + public LoyaltyTimer() : base(InternalDelay, InternalDelay) + { + m_NextHourlyCheck = DateTime.UtcNow + TimeSpan.FromHours(1.0); + Priority = TimerPriority.FiveSeconds; + } + + public static void Initialize() + { + new LoyaltyTimer().Start(); + } + + protected override void OnTick() + { + if (DateTime.UtcNow >= m_NextHourlyCheck) + m_NextHourlyCheck = DateTime.UtcNow + TimeSpan.FromHours(1.0); + else + return; + + var toRelease = new List(); + + // added array for wild creatures in house regions to be removed + var toRemove = new List(); + + Parallel.ForEach( + World.Mobiles.Values, + m => + { + if (!(m is BaseCreature c)) + return; + + if (c is BaseMount mount && mount.Rider != null) + { + mount.OwnerAbandonTime = DateTime.MinValue; + return; + } + + if (c.IsDeadPet) + { + var owner = c.ControlMaster; + + if (!c.IsStabled && (owner?.Deleted != false || owner.Map != c.Map || + !owner.InRange(c, 12) || !c.CanSee(owner) || !c.InLOS(owner))) + { + if (c.OwnerAbandonTime == DateTime.MinValue) + c.OwnerAbandonTime = DateTime.UtcNow; + else if (c.OwnerAbandonTime + c.BondingAbandonDelay <= DateTime.UtcNow) + lock (toRemove) + { + toRemove.Add(c); + } + } + else + { + c.OwnerAbandonTime = DateTime.MinValue; + } + } + else if (c.Controlled && c.Commandable) + { + c.OwnerAbandonTime = DateTime.MinValue; + + if (c.Map != Map.Internal) + { + c.Loyalty -= BaseCreature.MaxLoyalty / 10; + + if (c.Loyalty < BaseCreature.MaxLoyalty / 10) + { + c.Say(1043270, c.Name); // * ~1_NAME~ looks around desperately * + c.PlaySound(c.GetIdleSound()); + } + + if (c.Loyalty <= 0) + lock (toRelease) + { + toRelease.Add(c); + } + } + } + + // added lines to check if a wild creature in a house region has to be removed or not + if (!c.Controlled && !c.IsStabled && (c.Region.IsPartOf() && c.CanBeDamaged() || + c.RemoveIfUntamed && c.Spawner == null)) + { + c.RemoveStep++; + + if (c.RemoveStep >= 20) + lock (toRemove) + { + toRemove.Add(c); + } + } + else + { + c.RemoveStep = 0; + } + } + ); + + // TODO: Parallelize this + foreach (var c in toRelease) + { + c.Say(1043255, c.Name); // ~1_NAME~ appears to have decided that is better off without a master! + c.Loyalty = BaseCreature.MaxLoyalty; // Wonderfully Happy + c.IsBonded = false; + c.BondingBegin = DateTime.MinValue; + c.OwnerAbandonTime = DateTime.MinValue; + c.ControlTarget = null; + c.AIObject + .DoOrderRelease(); // this will prevent no release of creatures left alone with AI disabled (and consequent bug of Followers) + c.DropBackpack(); + } + + foreach (var c in toRemove) + c.Delete(); + } } - } } diff --git a/Projects/UOContent/Mobiles/Familiars/BaseFamiliar.cs b/Projects/UOContent/Mobiles/Familiars/BaseFamiliar.cs index 1b4bb33cd..c61e88c6a 100644 --- a/Projects/UOContent/Mobiles/Familiars/BaseFamiliar.cs +++ b/Projects/UOContent/Mobiles/Familiars/BaseFamiliar.cs @@ -4,172 +4,180 @@ using Server.Items; namespace Server.Mobiles { - public abstract class BaseFamiliar : BaseCreature - { - private bool m_LastHidden; - - public BaseFamiliar() - : base(AIType.AI_Melee, FightMode.Closest, 10, 1, .1, .1) + public abstract class BaseFamiliar : BaseCreature { + private bool m_LastHidden; + + public BaseFamiliar() + : base(AIType.AI_Melee, FightMode.Closest, 10, 1, .1, .1) + { + } + + public BaseFamiliar(Serial serial) : base(serial) + { + } + + public override bool BardImmune => true; + public override Poison PoisonImmune => Poison.Lethal; + public override bool Commandable => false; + + public override bool PlayerRangeSensitive => false; + + public virtual void RangeCheck() + { + if (Deleted || ControlMaster?.Deleted != false) + return; + + var range = RangeHome - 2; + + if (InRange(ControlMaster.Location, RangeHome)) + return; + + var master = ControlMaster; + + var m_Loc = Point3D.Zero; + + if (Map != master.Map) + return; + + var x = X > master.X ? master.X + range : master.X - range; + var y = Y > master.Y ? master.Y + range : master.Y - range; + + for (var i = 0; i < 10; i++) + { + m_Loc.X = x + Utility.RandomMinMax(-1, 1); + m_Loc.Y = y + Utility.RandomMinMax(-1, 1); + + m_Loc.Z = Map.GetAverageZ(m_Loc.X, m_Loc.Y); + + if (Map.CanSpawnMobile(m_Loc)) break; + + m_Loc = master.Location; + } + + if (!Deleted) + SetLocation(m_Loc, true); + } + + public override void OnThink() + { + var master = ControlMaster; + + if (Deleted) return; + if (master?.Deleted != false) + { + DropPackContents(); + EndRelease(null); + return; + } + + RangeCheck(); + + if (m_LastHidden != master.Hidden) + Hidden = m_LastHidden = master.Hidden; + + if (AIObject?.WalkMobileRange(master, 5, true, 1, 1) == true) + { + Warmode = master.Warmode; + Combatant = master.Combatant; + + CurrentSpeed = 0.10; + } + else + { + Warmode = false; + FocusMob = Combatant = null; + + CurrentSpeed = .01; + } + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (from.Alive && Controlled && from == ControlMaster && from.InRange(this, 14)) + list.Add(new ReleaseEntry(from, this)); + } + + public virtual void BeginRelease(Mobile from) + { + if (!Deleted && Controlled && from == ControlMaster && from.CheckAlive()) + EndRelease(from); + } + + public virtual void EndRelease(Mobile from) + { + if (from?.CheckAlive() != false && !Deleted && Controlled && from == ControlMaster) + { + Effects.SendLocationParticles( + EffectItem.Create(Location, Map, EffectItem.DefaultDuration), + 0x3728, + 1, + 13, + 2100, + 3, + 5042, + 0 + ); + PlaySound(0x201); + Delete(); + } + } + + public virtual void DropPackContents() + { + var map = Map; + var pack = Backpack; + + if (map != null && map != Map.Internal && pack != null) + { + var list = new List(pack.Items); + + for (var i = 0; i < list.Count; ++i) + list[i].MoveToWorld(Location, map); + } + } + + 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(); + + ValidationQueue.Add(this); + } + + public void Validate() + { + DropPackContents(); + Delete(); + } + + private class ReleaseEntry : ContextMenuEntry + { + private readonly BaseFamiliar m_Familiar; + private readonly Mobile m_From; + + public ReleaseEntry(Mobile from, BaseFamiliar familiar) : base(6118, 14) + { + m_From = from; + m_Familiar = familiar; + } + + public override void OnClick() + { + if (!m_Familiar.Deleted && m_Familiar.Controlled && m_From == m_Familiar.ControlMaster && + m_From.CheckAlive()) + m_Familiar.BeginRelease(m_From); + } + } } - - public BaseFamiliar(Serial serial) : base(serial) - { - } - - public override bool BardImmune => true; - public override Poison PoisonImmune => Poison.Lethal; - public override bool Commandable => false; - - public override bool PlayerRangeSensitive => false; - - public virtual void RangeCheck() - { - if (Deleted || ControlMaster?.Deleted != false) - return; - - int range = RangeHome - 2; - - if (InRange(ControlMaster.Location, RangeHome)) - return; - - Mobile master = ControlMaster; - - Point3D m_Loc = Point3D.Zero; - - if (Map != master.Map) - return; - - int x = X > master.X ? master.X + range : master.X - range; - int y = Y > master.Y ? master.Y + range : master.Y - range; - - for (int i = 0; i < 10; i++) - { - m_Loc.X = x + Utility.RandomMinMax(-1, 1); - m_Loc.Y = y + Utility.RandomMinMax(-1, 1); - - m_Loc.Z = Map.GetAverageZ(m_Loc.X, m_Loc.Y); - - if (Map.CanSpawnMobile(m_Loc)) break; - - m_Loc = master.Location; - } - - if (!Deleted) - SetLocation(m_Loc, true); - } - - public override void OnThink() - { - Mobile master = ControlMaster; - - if (Deleted) return; - if (master?.Deleted != false) - { - DropPackContents(); - EndRelease(null); - return; - } - - RangeCheck(); - - if (m_LastHidden != master.Hidden) - Hidden = m_LastHidden = master.Hidden; - - if (AIObject?.WalkMobileRange(master, 5, true, 1, 1) == true) - { - Warmode = master.Warmode; - Combatant = master.Combatant; - - CurrentSpeed = 0.10; - } - else - { - Warmode = false; - FocusMob = Combatant = null; - - CurrentSpeed = .01; - } - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (from.Alive && Controlled && from == ControlMaster && from.InRange(this, 14)) - list.Add(new ReleaseEntry(from, this)); - } - - public virtual void BeginRelease(Mobile from) - { - if (!Deleted && Controlled && from == ControlMaster && from.CheckAlive()) - EndRelease(from); - } - - public virtual void EndRelease(Mobile from) - { - if (from?.CheckAlive() != false && !Deleted && Controlled && from == ControlMaster) - { - Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x3728, 1, 13, - 2100, 3, 5042, 0); - PlaySound(0x201); - Delete(); - } - } - - public virtual void DropPackContents() - { - Map map = Map; - Container pack = Backpack; - - if (map != null && map != Map.Internal && pack != null) - { - List list = new List(pack.Items); - - for (int i = 0; i < list.Count; ++i) - list[i].MoveToWorld(Location, map); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - ValidationQueue.Add(this); - } - - public void Validate() - { - DropPackContents(); - Delete(); - } - - private class ReleaseEntry : ContextMenuEntry - { - private readonly BaseFamiliar m_Familiar; - private readonly Mobile m_From; - - public ReleaseEntry(Mobile from, BaseFamiliar familiar) : base(6118, 14) - { - m_From = from; - m_Familiar = familiar; - } - - public override void OnClick() - { - if (!m_Familiar.Deleted && m_Familiar.Controlled && m_From == m_Familiar.ControlMaster && - m_From.CheckAlive()) - m_Familiar.BeginRelease(m_From); - } - } - } } diff --git a/Projects/UOContent/Mobiles/Familiars/DarkWolf.cs b/Projects/UOContent/Mobiles/Familiars/DarkWolf.cs index 0e64bf73a..a9b6783c7 100644 --- a/Projects/UOContent/Mobiles/Familiars/DarkWolf.cs +++ b/Projects/UOContent/Mobiles/Familiars/DarkWolf.cs @@ -2,74 +2,74 @@ using System; namespace Server.Mobiles { - public class DarkWolfFamiliar : BaseFamiliar - { - private DateTime m_NextRestore; - - public DarkWolfFamiliar() + public class DarkWolfFamiliar : BaseFamiliar { - Body = 99; - Hue = 0x901; - BaseSoundID = 0xE5; + private DateTime m_NextRestore; - SetStr(100); - SetDex(90); - SetInt(90); + public DarkWolfFamiliar() + { + Body = 99; + Hue = 0x901; + BaseSoundID = 0xE5; - SetHits(60); - SetStam(90); - SetMana(0); + SetStr(100); + SetDex(90); + SetInt(90); - SetDamage(5, 10); + SetHits(60); + SetStam(90); + SetMana(0); - SetDamageType(ResistanceType.Physical, 100); + SetDamage(5, 10); - SetResistance(ResistanceType.Physical, 40, 50); - SetResistance(ResistanceType.Fire, 25, 40); - SetResistance(ResistanceType.Cold, 25, 40); - SetResistance(ResistanceType.Poison, 25, 40); - SetResistance(ResistanceType.Energy, 25, 40); + SetDamageType(ResistanceType.Physical, 100); - SetSkill(SkillName.Wrestling, 85.1, 90.0); - SetSkill(SkillName.Tactics, 50.0); + SetResistance(ResistanceType.Physical, 40, 50); + SetResistance(ResistanceType.Fire, 25, 40); + SetResistance(ResistanceType.Cold, 25, 40); + SetResistance(ResistanceType.Poison, 25, 40); + SetResistance(ResistanceType.Energy, 25, 40); - ControlSlots = 1; + SetSkill(SkillName.Wrestling, 85.1, 90.0); + SetSkill(SkillName.Tactics, 50.0); + + ControlSlots = 1; + } + + public DarkWolfFamiliar(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a dark wolf corpse"; + public override string DefaultName => "a dark wolf"; + + public override void OnThink() + { + base.OnThink(); + + if (DateTime.UtcNow < m_NextRestore) + return; + + m_NextRestore = DateTime.UtcNow + TimeSpan.FromSeconds(2.0); + + var caster = ControlMaster ?? SummonMaster; + + if (caster != null) + ++caster.Stam; + } + + 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(); + } } - - public DarkWolfFamiliar(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a dark wolf corpse"; - public override string DefaultName => "a dark wolf"; - - public override void OnThink() - { - base.OnThink(); - - if (DateTime.UtcNow < m_NextRestore) - return; - - m_NextRestore = DateTime.UtcNow + TimeSpan.FromSeconds(2.0); - - Mobile caster = ControlMaster ?? SummonMaster; - - if (caster != null) - ++caster.Stam; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Familiars/DeathAdder.cs b/Projects/UOContent/Mobiles/Familiars/DeathAdder.cs index f5b292c03..c42811e4a 100644 --- a/Projects/UOContent/Mobiles/Familiars/DeathAdder.cs +++ b/Projects/UOContent/Mobiles/Familiars/DeathAdder.cs @@ -1,56 +1,56 @@ namespace Server.Mobiles { - public class DeathAdder : BaseFamiliar - { - public DeathAdder() + public class DeathAdder : BaseFamiliar { - Body = 0x15; - Hue = 0x455; - BaseSoundID = 219; + public DeathAdder() + { + Body = 0x15; + Hue = 0x455; + BaseSoundID = 219; - SetStr(70); - SetDex(150); - SetInt(100); + SetStr(70); + SetDex(150); + SetInt(100); - SetHits(50); - SetStam(150); - SetMana(0); + SetHits(50); + SetStam(150); + SetMana(0); - SetDamage(1, 4); - SetDamageType(ResistanceType.Physical, 100); + SetDamage(1, 4); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 10); - SetResistance(ResistanceType.Poison, 100); + SetResistance(ResistanceType.Physical, 10); + SetResistance(ResistanceType.Poison, 100); - SetSkill(SkillName.Wrestling, 90.0); - SetSkill(SkillName.Tactics, 50.0); - SetSkill(SkillName.MagicResist, 100.0); - SetSkill(SkillName.Poisoning, 150.0); + SetSkill(SkillName.Wrestling, 90.0); + SetSkill(SkillName.Tactics, 50.0); + SetSkill(SkillName.MagicResist, 100.0); + SetSkill(SkillName.Poisoning, 150.0); - ControlSlots = 1; + ControlSlots = 1; + } + + public DeathAdder(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a death adder corpse"; + public override string DefaultName => "a death adder"; + + public override Poison HitPoison => Utility.RandomDouble() <= 0.8 ? Poison.Greater : Poison.Deadly; + + 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(); + } } - - public DeathAdder(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a death adder corpse"; - public override string DefaultName => "a death adder"; - - public override Poison HitPoison => Utility.RandomDouble() <= 0.8 ? Poison.Greater : Poison.Deadly; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Familiars/HordeMinion.cs b/Projects/UOContent/Mobiles/Familiars/HordeMinion.cs index 6eaf02ab2..28b786ed5 100644 --- a/Projects/UOContent/Mobiles/Familiars/HordeMinion.cs +++ b/Projects/UOContent/Mobiles/Familiars/HordeMinion.cs @@ -4,174 +4,175 @@ using System.Linq; using Server.ContextMenus; using Server.Gumps; using Server.Items; -using Server.Network; namespace Server.Mobiles { - public class HordeMinionFamiliar : BaseFamiliar - { - private DateTime m_NextPickup; - - public HordeMinionFamiliar() + public class HordeMinionFamiliar : BaseFamiliar { - Body = 776; - BaseSoundID = 0x39D; + private DateTime m_NextPickup; - SetStr(100); - SetDex(110); - SetInt(100); + public HordeMinionFamiliar() + { + Body = 776; + BaseSoundID = 0x39D; - SetHits(70); - SetStam(110); - SetMana(0); + SetStr(100); + SetDex(110); + SetInt(100); - SetDamage(5, 10); + SetHits(70); + SetStam(110); + SetMana(0); - SetDamageType(ResistanceType.Physical, 100); + SetDamage(5, 10); - SetResistance(ResistanceType.Physical, 50, 60); - SetResistance(ResistanceType.Fire, 50, 55); - SetResistance(ResistanceType.Poison, 25, 30); - SetResistance(ResistanceType.Energy, 25, 30); + SetDamageType(ResistanceType.Physical, 100); - SetSkill(SkillName.Wrestling, 70.1, 75.0); - SetSkill(SkillName.Tactics, 50.0); + SetResistance(ResistanceType.Physical, 50, 60); + SetResistance(ResistanceType.Fire, 50, 55); + SetResistance(ResistanceType.Poison, 25, 30); + SetResistance(ResistanceType.Energy, 25, 30); - ControlSlots = 1; + SetSkill(SkillName.Wrestling, 70.1, 75.0); + SetSkill(SkillName.Tactics, 50.0); - Container pack = Backpack; + ControlSlots = 1; - pack?.Delete(); + var pack = Backpack; - pack = new Backpack(); - pack.Movable = false; - pack.Weight = 13.0; + pack?.Delete(); - AddItem(pack); + pack = new Backpack(); + pack.Movable = false; + pack.Weight = 13.0; + + AddItem(pack); + } + + public HordeMinionFamiliar(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a horde minion corpse"; + public override bool DisplayWeight => true; + + public override string DefaultName => "a horde minion"; + + public override void OnThink() + { + base.OnThink(); + + if (DateTime.UtcNow < m_NextPickup) + return; + + m_NextPickup = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(5, 10)); + + var pack = Backpack; + + if (pack == null) + return; + + var eable = GetItemsInRange(2).Where(item => item.Movable && item.Stackable); + + var pickedUp = 0; + + foreach (var item in eable) + { + if (!pack.CheckHold(this, item, false, true)) + return; + + NextActionTime = Core.TickCount; + + Lift(item, item.Amount, out var rejected, out var _); + + if (rejected) + continue; + + Drop(this, Point3D.Zero); + + if (++pickedUp == 3) + break; + } + } + + private void ConfirmRelease_Callback(Mobile from, bool okay) + { + if (okay) + EndRelease(from); + } + + public override void BeginRelease(Mobile from) + { + if (Backpack?.Items.Count > 0) + from.SendGump( + new WarningGump(1060635, 30720, 1061672, 32512, 420, 280, okay => ConfirmRelease_Callback(from, okay)) + ); + else + EndRelease(from); + } + + 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(); + } + + public override bool OnBeforeDeath() + { + if (!base.OnBeforeDeath()) + return false; + + PackAnimal.CombineBackpacks(this); + + return true; + } + + public override DeathMoveResult GetInventoryMoveResultFor(Item item) => DeathMoveResult.MoveToCorpse; + + public override bool IsSnoop(Mobile from) + { + if (PackAnimal.CheckAccess(this, from)) + return false; + + return base.IsSnoop(from); + } + + public override bool OnDragDrop(Mobile from, Item item) + { + if (CheckFeed(from, item)) + return true; + + if (PackAnimal.CheckAccess(this, from)) + { + AddToBackpack(item); + return true; + } + + return base.OnDragDrop(from, item); + } + + public override bool CheckNonlocalDrop(Mobile from, Item item, Item target) => PackAnimal.CheckAccess(this, from); + + public override bool CheckNonlocalLift(Mobile from, Item item) => PackAnimal.CheckAccess(this, from); + + public override void OnDoubleClick(Mobile from) + { + PackAnimal.TryPackOpen(this, from); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + PackAnimal.GetContextMenuEntries(this, from, list); + } } - - public HordeMinionFamiliar(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a horde minion corpse"; - public override bool DisplayWeight => true; - - public override string DefaultName => "a horde minion"; - - public override void OnThink() - { - base.OnThink(); - - if (DateTime.UtcNow < m_NextPickup) - return; - - m_NextPickup = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(5, 10)); - - Container pack = Backpack; - - if (pack == null) - return; - - IEnumerable eable = GetItemsInRange(2).Where(item => item.Movable && item.Stackable); - - int pickedUp = 0; - - foreach (Item item in eable) - { - if (!pack.CheckHold(this, item, false, true)) - return; - - NextActionTime = Core.TickCount; - - Lift(item, item.Amount, out bool rejected, out LRReason _); - - if (rejected) - continue; - - Drop(this, Point3D.Zero); - - if (++pickedUp == 3) - break; - } - } - - private void ConfirmRelease_Callback(Mobile from, bool okay) - { - if (okay) - EndRelease(from); - } - - public override void BeginRelease(Mobile from) - { - if (Backpack?.Items.Count > 0) - from.SendGump(new WarningGump(1060635, 30720, 1061672, 32512, 420, 280, okay => ConfirmRelease_Callback(from, okay))); - else - EndRelease(from); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override bool OnBeforeDeath() - { - if (!base.OnBeforeDeath()) - return false; - - PackAnimal.CombineBackpacks(this); - - return true; - } - - public override DeathMoveResult GetInventoryMoveResultFor(Item item) => DeathMoveResult.MoveToCorpse; - - public override bool IsSnoop(Mobile from) - { - if (PackAnimal.CheckAccess(this, from)) - return false; - - return base.IsSnoop(from); - } - - public override bool OnDragDrop(Mobile from, Item item) - { - if (CheckFeed(from, item)) - return true; - - if (PackAnimal.CheckAccess(this, from)) - { - AddToBackpack(item); - return true; - } - - return base.OnDragDrop(from, item); - } - - public override bool CheckNonlocalDrop(Mobile from, Item item, Item target) => PackAnimal.CheckAccess(this, from); - - public override bool CheckNonlocalLift(Mobile from, Item item) => PackAnimal.CheckAccess(this, from); - - public override void OnDoubleClick(Mobile from) - { - PackAnimal.TryPackOpen(this, from); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - PackAnimal.GetContextMenuEntries(this, from, list); - } - } } diff --git a/Projects/UOContent/Mobiles/Familiars/ShadowWisp.cs b/Projects/UOContent/Mobiles/Familiars/ShadowWisp.cs index 7270f74bb..d46c2ab36 100644 --- a/Projects/UOContent/Mobiles/Familiars/ShadowWisp.cs +++ b/Projects/UOContent/Mobiles/Familiars/ShadowWisp.cs @@ -1,106 +1,109 @@ using System; -using System.Collections.Generic; using System.Linq; namespace Server.Mobiles { - public class ShadowWispFamiliar : BaseFamiliar - { - private DateTime m_NextFlare; - - public ShadowWispFamiliar() + public class ShadowWispFamiliar : BaseFamiliar { - Body = 165; - Hue = 0x901; - BaseSoundID = 466; + private DateTime m_NextFlare; - SetStr(50); - SetDex(60); - SetInt(100); - - SetHits(50); - SetStam(60); - SetMana(0); - - SetDamage(5, 10); - - SetDamageType(ResistanceType.Energy, 100); - - SetResistance(ResistanceType.Physical, 10, 15); - SetResistance(ResistanceType.Fire, 10, 15); - SetResistance(ResistanceType.Cold, 10, 15); - SetResistance(ResistanceType.Poison, 10, 15); - SetResistance(ResistanceType.Energy, 99); - - SetSkill(SkillName.Wrestling, 40.0); - SetSkill(SkillName.Tactics, 40.0); - - ControlSlots = 1; - } - - public ShadowWispFamiliar(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a shadow wisp corpse"; - public override string DefaultName => "a shadow wisp"; - - public override void OnThink() - { - base.OnThink(); - - if (DateTime.UtcNow < m_NextFlare) - return; - - m_NextFlare = DateTime.UtcNow + TimeSpan.FromSeconds(5.0 + 25.0 * Utility.RandomDouble()); - - FixedEffect(0x37C4, 1, 12, 1109, 6); - PlaySound(0x1D3); - - Timer.DelayCall(TimeSpan.FromSeconds(0.5), Flare); - } - - private void Flare() - { - Mobile caster = ControlMaster ?? SummonMaster; - - if (caster == null) - return; - - List list = GetMobilesInRange(5).Where(m => - m.Player && m.Alive && !m.IsDeadBondedPet && m.Karma <= 0 && m.AccessLevel < AccessLevel.Counselor).ToList(); - - for (int i = 0; i < list.Count; ++i) - { - Mobile m = list[i]; - bool friendly = true; - - for (int j = 0; friendly && j < caster.Aggressors.Count; ++j) - friendly = caster.Aggressors[j].Attacker != m; - - for (int j = 0; friendly && j < caster.Aggressed.Count; ++j) - friendly = caster.Aggressed[j].Defender != m; - - if (friendly) + public ShadowWispFamiliar() { - m.FixedEffect(0x37C4, 1, 12, 1109, 3); // At player - m.Mana += 1 - m.Karma / 1000; + Body = 165; + Hue = 0x901; + BaseSoundID = 466; + + SetStr(50); + SetDex(60); + SetInt(100); + + SetHits(50); + SetStam(60); + SetMana(0); + + SetDamage(5, 10); + + SetDamageType(ResistanceType.Energy, 100); + + SetResistance(ResistanceType.Physical, 10, 15); + SetResistance(ResistanceType.Fire, 10, 15); + SetResistance(ResistanceType.Cold, 10, 15); + SetResistance(ResistanceType.Poison, 10, 15); + SetResistance(ResistanceType.Energy, 99); + + SetSkill(SkillName.Wrestling, 40.0); + SetSkill(SkillName.Tactics, 40.0); + + ControlSlots = 1; + } + + public ShadowWispFamiliar(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a shadow wisp corpse"; + public override string DefaultName => "a shadow wisp"; + + public override void OnThink() + { + base.OnThink(); + + if (DateTime.UtcNow < m_NextFlare) + return; + + m_NextFlare = DateTime.UtcNow + TimeSpan.FromSeconds(5.0 + 25.0 * Utility.RandomDouble()); + + FixedEffect(0x37C4, 1, 12, 1109, 6); + PlaySound(0x1D3); + + Timer.DelayCall(TimeSpan.FromSeconds(0.5), Flare); + } + + private void Flare() + { + var caster = ControlMaster ?? SummonMaster; + + if (caster == null) + return; + + var list = GetMobilesInRange(5) + .Where( + m => + m.Player && m.Alive && !m.IsDeadBondedPet && m.Karma <= 0 && m.AccessLevel < AccessLevel.Counselor + ) + .ToList(); + + for (var i = 0; i < list.Count; ++i) + { + var m = list[i]; + var friendly = true; + + for (var j = 0; friendly && j < caster.Aggressors.Count; ++j) + friendly = caster.Aggressors[j].Attacker != m; + + for (var j = 0; friendly && j < caster.Aggressed.Count; ++j) + friendly = caster.Aggressed[j].Defender != m; + + if (friendly) + { + m.FixedEffect(0x37C4, 1, 12, 1109, 3); // At player + m.Mana += 1 - m.Karma / 1000; + } + } + } + + 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(); } - } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Familiars/VampireBat.cs b/Projects/UOContent/Mobiles/Familiars/VampireBat.cs index 9b644f397..1a0e7a1d3 100644 --- a/Projects/UOContent/Mobiles/Familiars/VampireBat.cs +++ b/Projects/UOContent/Mobiles/Familiars/VampireBat.cs @@ -1,55 +1,55 @@ namespace Server.Mobiles { - public class VampireBatFamiliar : BaseFamiliar - { - public VampireBatFamiliar() + public class VampireBatFamiliar : BaseFamiliar { - Body = 317; - BaseSoundID = 0x270; + public VampireBatFamiliar() + { + Body = 317; + BaseSoundID = 0x270; - SetStr(120); - SetDex(120); - SetInt(100); + SetStr(120); + SetDex(120); + SetInt(100); - SetHits(90); - SetStam(120); - SetMana(0); + SetHits(90); + SetStam(120); + SetMana(0); - SetDamage(5, 10); + SetDamage(5, 10); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 10, 15); - SetResistance(ResistanceType.Fire, 10, 15); - SetResistance(ResistanceType.Cold, 10, 15); - SetResistance(ResistanceType.Poison, 10, 15); - SetResistance(ResistanceType.Energy, 10, 15); + SetResistance(ResistanceType.Physical, 10, 15); + SetResistance(ResistanceType.Fire, 10, 15); + SetResistance(ResistanceType.Cold, 10, 15); + SetResistance(ResistanceType.Poison, 10, 15); + SetResistance(ResistanceType.Energy, 10, 15); - SetSkill(SkillName.Wrestling, 95.1, 100.0); - SetSkill(SkillName.Tactics, 50.0); + SetSkill(SkillName.Wrestling, 95.1, 100.0); + SetSkill(SkillName.Tactics, 50.0); - ControlSlots = 1; + ControlSlots = 1; + } + + public VampireBatFamiliar(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a vampire bat corpse"; + public override string DefaultName => "a vampire bat"; + + 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(); + } } - - public VampireBatFamiliar(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a vampire bat corpse"; - public override string DefaultName => "a vampire bat"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Guards/ArcherGuard.cs b/Projects/UOContent/Mobiles/Guards/ArcherGuard.cs index 3aac190bf..36e690b11 100644 --- a/Projects/UOContent/Mobiles/Guards/ArcherGuard.cs +++ b/Projects/UOContent/Mobiles/Guards/ArcherGuard.cs @@ -3,376 +3,396 @@ using Server.Items; namespace Server.Mobiles { - public class ArcherGuard : BaseGuard - { - private Timer m_AttackTimer, m_IdleTimer; - - private Mobile m_Focus; - - [Constructible] - public ArcherGuard(Mobile target = null) : base(target) + public class ArcherGuard : BaseGuard { - InitStats(100, 125, 25); - Title = "the guard"; + private Timer m_AttackTimer, m_IdleTimer; - SpeechHue = Utility.RandomDyedHue(); + private Mobile m_Focus; - Hue = Race.Human.RandomSkinHue(); - - if (Female = Utility.RandomBool()) - { - Body = 0x191; - Name = NameList.RandomName("female"); - } - else - { - Body = 0x190; - Name = NameList.RandomName("male"); - } - - new Horse().Rider = this; - - AddItem(new StuddedChest()); - AddItem(new StuddedArms()); - AddItem(new StuddedGloves()); - AddItem(new StuddedGorget()); - AddItem(new StuddedLegs()); - AddItem(new Boots()); - AddItem(new SkullCap()); - - Bow bow = new Bow(); - - bow.Movable = false; - bow.Crafter = this; - bow.Quality = WeaponQuality.Exceptional; - - AddItem(bow); - - Container pack = new Backpack(); - - pack.Movable = false; - - Arrow arrows = new Arrow(250); - - arrows.LootType = LootType.Newbied; - - pack.DropItem(arrows); - pack.DropItem(new Gold(10, 25)); - - AddItem(pack); - - Skills.Anatomy.Base = 120.0; - Skills.Tactics.Base = 120.0; - Skills.Archery.Base = 120.0; - Skills.MagicResist.Base = 120.0; - Skills.DetectHidden.Base = 100.0; - - NextCombatTime = Core.TickCount + 500; - Focus = target; - } - - public ArcherGuard(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public override Mobile Focus - { - get => m_Focus; - set - { - if (Deleted) - return; - - Mobile oldFocus = m_Focus; - - if (oldFocus != value) + [Constructible] + public ArcherGuard(Mobile target = null) : base(target) { - m_Focus = value; + InitStats(100, 125, 25); + Title = "the guard"; - if (value != null) - AggressiveAction(value); + SpeechHue = Utility.RandomDyedHue(); - Combatant = value; + Hue = Race.Human.RandomSkinHue(); - if (oldFocus?.Alive == false) - Say("Thou hast suffered thy punishment, scoundrel."); - - if (value != null) - Say(500131); // Thou wilt regret thine actions, swine! - - if (m_AttackTimer != null) - { - m_AttackTimer.Stop(); - m_AttackTimer = null; - } - - if (m_IdleTimer != null) - { - m_IdleTimer.Stop(); - m_IdleTimer = null; - } - - if (m_Focus != null) - { - m_AttackTimer = new AttackTimer(this); - m_AttackTimer.Start(); - ((AttackTimer)m_AttackTimer).DoOnTick(); - } - else - { - m_IdleTimer = new IdleTimer(this); - m_IdleTimer.Start(); - } - } - else if (m_Focus == null && m_IdleTimer == null) - { - m_IdleTimer = new IdleTimer(this); - m_IdleTimer.Start(); - } - } - } - - public override bool OnBeforeDeath() - { - if (m_Focus?.Alive == true) - new AvengeTimer(m_Focus).Start(); // If a guard dies, three more guards will spawn - - return base.OnBeforeDeath(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Focus); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Focus = reader.ReadMobile(); - - if (m_Focus != null) + if (Female = Utility.RandomBool()) { - m_AttackTimer = new AttackTimer(this); - m_AttackTimer.Start(); + Body = 0x191; + Name = NameList.RandomName("female"); } else { - m_IdleTimer = new IdleTimer(this); - m_IdleTimer.Start(); + Body = 0x190; + Name = NameList.RandomName("male"); } - break; - } - } - } + new Horse().Rider = this; - public override void OnAfterDelete() - { - if (m_AttackTimer != null) - { - m_AttackTimer.Stop(); - m_AttackTimer = null; - } + AddItem(new StuddedChest()); + AddItem(new StuddedArms()); + AddItem(new StuddedGloves()); + AddItem(new StuddedGorget()); + AddItem(new StuddedLegs()); + AddItem(new Boots()); + AddItem(new SkullCap()); - if (m_IdleTimer != null) - { - m_IdleTimer.Stop(); - m_IdleTimer = null; - } + var bow = new Bow(); - base.OnAfterDelete(); - } + bow.Movable = false; + bow.Crafter = this; + bow.Quality = WeaponQuality.Exceptional; - private class AvengeTimer : Timer - { - private readonly Mobile m_Focus; + AddItem(bow); - public AvengeTimer(Mobile focus) : base(TimeSpan.FromSeconds(2.5), TimeSpan.FromSeconds(1.0), - 3) // After 2.5 seconds, one guard will spawn every 1.0 second, three times - => - m_Focus = focus; + Container pack = new Backpack(); - protected override void OnTick() - { - Spawn(m_Focus, m_Focus, 1, true); - } - } + pack.Movable = false; - private class AttackTimer : Timer - { - private readonly ArcherGuard m_Owner; - // private bool m_Shooting; + var arrows = new Arrow(250); - public AttackTimer(ArcherGuard owner) : base(TimeSpan.FromSeconds(0.25), TimeSpan.FromSeconds(0.1)) => m_Owner = owner; + arrows.LootType = LootType.Newbied; - public void DoOnTick() - { - OnTick(); - } + pack.DropItem(arrows); + pack.DropItem(new Gold(10, 25)); - protected override void OnTick() - { - if (m_Owner.Deleted) - { - Stop(); - return; + AddItem(pack); + + Skills.Anatomy.Base = 120.0; + Skills.Tactics.Base = 120.0; + Skills.Archery.Base = 120.0; + Skills.MagicResist.Base = 120.0; + Skills.DetectHidden.Base = 100.0; + + NextCombatTime = Core.TickCount + 500; + Focus = target; } - m_Owner.Criminal = false; - m_Owner.Kills = 0; - m_Owner.Stam = m_Owner.StamMax; - - Mobile target = m_Owner.Focus; - - if (target != null && (target.Deleted || !target.Alive || !m_Owner.CanBeHarmful(target))) + public ArcherGuard(Serial serial) : base(serial) { - m_Owner.Focus = null; - Stop(); - return; } - if (m_Owner.Weapon is Fists) + [CommandProperty(AccessLevel.GameMaster)] + public override Mobile Focus { - m_Owner.Kill(); - Stop(); - return; - } - - if (target != null && m_Owner.Combatant != target) - m_Owner.Combatant = target; - - if (target == null) - { - Stop(); - } - else - { - // - TeleportTo(target); - target.BoltEffect(0); - - if (target is BaseCreature creature) - creature.NoKillAwards = true; - - target.Damage(target.HitsMax, m_Owner); - target.Kill(); // just in case, maybe Damage is overridden on some shard - - if (target.Corpse != null && !target.Player) - target.Corpse.Delete(); - - m_Owner.Focus = null; - Stop(); - } // - - /*else if (!m_Owner.InRange( target, 20 )) - { - m_Shooting = false; - m_Owner.Focus = null; - } - else if (!m_Owner.InLOS( target )) - { - m_Shooting = false; - TeleportTo( target ); - } - else if (!m_Owner.CanSee( target )) - { - m_Shooting = false; - - if (!m_Owner.InRange( target, 2 )) - { - if (!m_Owner.Move( m_Owner.GetDirectionTo( target ) | Direction.Running ) && OutOfMaxDistance( target )) - TeleportTo( target ); - } - else - { - if (!m_Owner.UseSkill( SkillName.DetectHidden ) && Utility.Random( 50 ) == 0) - m_Owner.Say( "Reveal!" ); - } - } - else - { - if (m_Shooting && (TimeToSpare() || OutOfMaxDistance( target ))) - m_Shooting = false; - else if (!m_Shooting && InMinDistance( target )) - m_Shooting = true; - - if (!m_Shooting) - { - if (m_Owner.InRange( target, 1 )) + get => m_Focus; + set { - if (!m_Owner.Move( (Direction)(m_Owner.GetDirectionTo( target ) - 4) | Direction.Running ) && OutOfMaxDistance( target )) - TeleportTo( target ); // Too close, move away + if (Deleted) + return; + + var oldFocus = m_Focus; + + if (oldFocus != value) + { + m_Focus = value; + + if (value != null) + AggressiveAction(value); + + Combatant = value; + + if (oldFocus?.Alive == false) + Say("Thou hast suffered thy punishment, scoundrel."); + + if (value != null) + Say(500131); // Thou wilt regret thine actions, swine! + + if (m_AttackTimer != null) + { + m_AttackTimer.Stop(); + m_AttackTimer = null; + } + + if (m_IdleTimer != null) + { + m_IdleTimer.Stop(); + m_IdleTimer = null; + } + + if (m_Focus != null) + { + m_AttackTimer = new AttackTimer(this); + m_AttackTimer.Start(); + ((AttackTimer)m_AttackTimer).DoOnTick(); + } + else + { + m_IdleTimer = new IdleTimer(this); + m_IdleTimer.Start(); + } + } + else if (m_Focus == null && m_IdleTimer == null) + { + m_IdleTimer = new IdleTimer(this); + m_IdleTimer.Start(); + } } - else if (!m_Owner.InRange( target, 2 )) + } + + public override bool OnBeforeDeath() + { + if (m_Focus?.Alive == true) + new AvengeTimer(m_Focus).Start(); // If a guard dies, three more guards will spawn + + return base.OnBeforeDeath(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Focus); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) { - if (!m_Owner.Move( m_Owner.GetDirectionTo( target ) | Direction.Running ) && OutOfMaxDistance( target )) - TeleportTo( target ); + case 0: + { + m_Focus = reader.ReadMobile(); + + if (m_Focus != null) + { + m_AttackTimer = new AttackTimer(this); + m_AttackTimer.Start(); + } + else + { + m_IdleTimer = new IdleTimer(this); + m_IdleTimer.Start(); + } + + break; + } } - } - }*/ - } - - private bool TimeToSpare() => m_Owner.NextCombatTime - Core.TickCount > 1000; - - private bool OutOfMaxDistance(IPoint2D target) => !m_Owner.InRange(target, m_Owner.Weapon.MaxRange); - - private bool InMinDistance(IPoint2D target) => m_Owner.InRange(target, 4); - - private void TeleportTo(IEntity target) - { - Point3D from = m_Owner.Location; - Point3D to = target.Location; - - m_Owner.Location = to; - - Effects.SendLocationParticles(EffectItem.Create(from, m_Owner.Map, EffectItem.DefaultDuration), 0x3728, 10, - 10, 2023); - Effects.SendLocationParticles(EffectItem.Create(to, m_Owner.Map, EffectItem.DefaultDuration), 0x3728, 10, 10, - 5023); - - m_Owner.PlaySound(0x1FE); - } - } - - private class IdleTimer : Timer - { - private readonly ArcherGuard m_Owner; - private int m_Stage; - - public IdleTimer(ArcherGuard owner) : base(TimeSpan.FromSeconds(2.0), TimeSpan.FromSeconds(2.5)) => m_Owner = owner; - - protected override void OnTick() - { - if (m_Owner.Deleted) - { - Stop(); - return; } - if (m_Stage++ % 4 == 0 || !m_Owner.Move(m_Owner.Direction)) - m_Owner.Direction = (Direction)Utility.Random(8); - - if (m_Stage > 16) + public override void OnAfterDelete() { - Effects.SendLocationParticles( - EffectItem.Create(m_Owner.Location, m_Owner.Map, EffectItem.DefaultDuration), 0x3728, 10, 10, 2023); - m_Owner.PlaySound(0x1FE); + if (m_AttackTimer != null) + { + m_AttackTimer.Stop(); + m_AttackTimer = null; + } - m_Owner.Delete(); + if (m_IdleTimer != null) + { + m_IdleTimer.Stop(); + m_IdleTimer = null; + } + + base.OnAfterDelete(); + } + + private class AvengeTimer : Timer + { + private readonly Mobile m_Focus; + + public AvengeTimer(Mobile focus) : base( + TimeSpan.FromSeconds(2.5), + TimeSpan.FromSeconds(1.0), + 3 + ) // After 2.5 seconds, one guard will spawn every 1.0 second, three times + => + m_Focus = focus; + + protected override void OnTick() + { + Spawn(m_Focus, m_Focus, 1, true); + } + } + + private class AttackTimer : Timer + { + private readonly ArcherGuard m_Owner; + // private bool m_Shooting; + + public AttackTimer(ArcherGuard owner) : base(TimeSpan.FromSeconds(0.25), TimeSpan.FromSeconds(0.1)) => + m_Owner = owner; + + public void DoOnTick() + { + OnTick(); + } + + protected override void OnTick() + { + if (m_Owner.Deleted) + { + Stop(); + return; + } + + m_Owner.Criminal = false; + m_Owner.Kills = 0; + m_Owner.Stam = m_Owner.StamMax; + + var target = m_Owner.Focus; + + if (target != null && (target.Deleted || !target.Alive || !m_Owner.CanBeHarmful(target))) + { + m_Owner.Focus = null; + Stop(); + return; + } + + if (m_Owner.Weapon is Fists) + { + m_Owner.Kill(); + Stop(); + return; + } + + if (target != null && m_Owner.Combatant != target) + m_Owner.Combatant = target; + + if (target == null) + { + Stop(); + } + else + { + // + TeleportTo(target); + target.BoltEffect(0); + + if (target is BaseCreature creature) + creature.NoKillAwards = true; + + target.Damage(target.HitsMax, m_Owner); + target.Kill(); // just in case, maybe Damage is overridden on some shard + + if (target.Corpse != null && !target.Player) + target.Corpse.Delete(); + + m_Owner.Focus = null; + Stop(); + } // + + /*else if (!m_Owner.InRange( target, 20 )) + { + m_Shooting = false; + m_Owner.Focus = null; + } + else if (!m_Owner.InLOS( target )) + { + m_Shooting = false; + TeleportTo( target ); + } + else if (!m_Owner.CanSee( target )) + { + m_Shooting = false; + + if (!m_Owner.InRange( target, 2 )) + { + if (!m_Owner.Move( m_Owner.GetDirectionTo( target ) | Direction.Running ) && OutOfMaxDistance( target )) + TeleportTo( target ); + } + else + { + if (!m_Owner.UseSkill( SkillName.DetectHidden ) && Utility.Random( 50 ) == 0) + m_Owner.Say( "Reveal!" ); + } + } + else + { + if (m_Shooting && (TimeToSpare() || OutOfMaxDistance( target ))) + m_Shooting = false; + else if (!m_Shooting && InMinDistance( target )) + m_Shooting = true; + + if (!m_Shooting) + { + if (m_Owner.InRange( target, 1 )) + { + if (!m_Owner.Move( (Direction)(m_Owner.GetDirectionTo( target ) - 4) | Direction.Running ) && OutOfMaxDistance( target )) + TeleportTo( target ); // Too close, move away + } + else if (!m_Owner.InRange( target, 2 )) + { + if (!m_Owner.Move( m_Owner.GetDirectionTo( target ) | Direction.Running ) && OutOfMaxDistance( target )) + TeleportTo( target ); + } + } + }*/ + } + + private bool TimeToSpare() => m_Owner.NextCombatTime - Core.TickCount > 1000; + + private bool OutOfMaxDistance(IPoint2D target) => !m_Owner.InRange(target, m_Owner.Weapon.MaxRange); + + private bool InMinDistance(IPoint2D target) => m_Owner.InRange(target, 4); + + private void TeleportTo(IEntity target) + { + var from = m_Owner.Location; + var to = target.Location; + + m_Owner.Location = to; + + Effects.SendLocationParticles( + EffectItem.Create(from, m_Owner.Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 2023 + ); + Effects.SendLocationParticles( + EffectItem.Create(to, m_Owner.Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 5023 + ); + + m_Owner.PlaySound(0x1FE); + } + } + + private class IdleTimer : Timer + { + private readonly ArcherGuard m_Owner; + private int m_Stage; + + public IdleTimer(ArcherGuard owner) : base(TimeSpan.FromSeconds(2.0), TimeSpan.FromSeconds(2.5)) => + m_Owner = owner; + + protected override void OnTick() + { + if (m_Owner.Deleted) + { + Stop(); + return; + } + + if (m_Stage++ % 4 == 0 || !m_Owner.Move(m_Owner.Direction)) + m_Owner.Direction = (Direction)Utility.Random(8); + + if (m_Stage > 16) + { + Effects.SendLocationParticles( + EffectItem.Create(m_Owner.Location, m_Owner.Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 2023 + ); + m_Owner.PlaySound(0x1FE); + + m_Owner.Delete(); + } + } } - } } - } } diff --git a/Projects/UOContent/Mobiles/Guards/BaseGuard.cs b/Projects/UOContent/Mobiles/Guards/BaseGuard.cs index cdb21bc12..a7938d8ba 100644 --- a/Projects/UOContent/Mobiles/Guards/BaseGuard.cs +++ b/Projects/UOContent/Mobiles/Guards/BaseGuard.cs @@ -2,74 +2,84 @@ using Server.Items; namespace Server.Mobiles { - public abstract class BaseGuard : Mobile - { - public BaseGuard(Mobile target) + public abstract class BaseGuard : Mobile { - if (target != null) - { - Location = target.Location; - Map = target.Map; - - Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x3728, 10, 10, - 5023); - } - } - - public BaseGuard(Serial serial) : base(serial) - { - } - - public abstract Mobile Focus { get; set; } - - public static void Spawn(Mobile caller, Mobile target, int amount = 1, bool onlyAdditional = false) - { - if (target?.Deleted != false) - return; - - foreach (Mobile m in target.GetMobilesInRange(15)) - if (m is BaseGuard g) + public BaseGuard(Mobile target) { - if (g.Focus == null) // idling - { - g.Focus = target; + if (target != null) + { + Location = target.Location; + Map = target.Map; - --amount; - } - else if (g.Focus == target && !onlyAdditional) - { - --amount; - } + Effects.SendLocationParticles( + EffectItem.Create(Location, Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 5023 + ); + } } - while (amount-- > 0) - caller.Region.MakeGuard(target); + public BaseGuard(Serial serial) : base(serial) + { + } + + public abstract Mobile Focus { get; set; } + + public static void Spawn(Mobile caller, Mobile target, int amount = 1, bool onlyAdditional = false) + { + if (target?.Deleted != false) + return; + + foreach (var m in target.GetMobilesInRange(15)) + if (m is BaseGuard g) + { + if (g.Focus == null) // idling + { + g.Focus = target; + + --amount; + } + else if (g.Focus == target && !onlyAdditional) + { + --amount; + } + } + + while (amount-- > 0) + caller.Region.MakeGuard(target); + } + + public override bool OnBeforeDeath() + { + Effects.SendLocationParticles( + EffectItem.Create(Location, Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 2023 + ); + + PlaySound(0x1FE); + + Delete(); + + return 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 OnBeforeDeath() - { - Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x3728, 10, 10, - 2023); - - PlaySound(0x1FE); - - Delete(); - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Guards/WarriorGuard.cs b/Projects/UOContent/Mobiles/Guards/WarriorGuard.cs index af4164622..ab1ce37d7 100644 --- a/Projects/UOContent/Mobiles/Guards/WarriorGuard.cs +++ b/Projects/UOContent/Mobiles/Guards/WarriorGuard.cs @@ -3,354 +3,372 @@ using Server.Items; namespace Server.Mobiles { - public class WarriorGuard : BaseGuard - { - private Timer m_AttackTimer, m_IdleTimer; - - private Mobile m_Focus; - - [Constructible] - public WarriorGuard(Mobile target = null) : base(target) + public class WarriorGuard : BaseGuard { - InitStats(1000, 1000, 1000); - Title = "the guard"; + private Timer m_AttackTimer, m_IdleTimer; - SpeechHue = Utility.RandomDyedHue(); + private Mobile m_Focus; - Hue = Race.Human.RandomSkinHue(); - - if (Female = Utility.RandomBool()) - { - Body = 0x191; - Name = NameList.RandomName("female"); - - AddItem(Utility.RandomBool() ? (Item)new LeatherSkirt() : new LeatherShorts()); - - AddItem( - Utility.Random(5) switch - { - 0 => new FemaleLeatherChest(), - 1 => new FemaleStuddedChest(), - 2 => new LeatherBustierArms(), - 3 => new StuddedBustierArms(), - _ => new FemalePlateChest(), // 4 - } - ); - } - else - { - Body = 0x190; - Name = NameList.RandomName("male"); - - AddItem(new PlateChest()); - AddItem(new PlateArms()); - AddItem(new PlateLegs()); - - AddItem( - Utility.Random(3) switch - { - 0 => new Doublet(Utility.RandomNondyedHue()), - 1 => new Tunic(Utility.RandomNondyedHue()), - _ => new BodySash(Utility.RandomNondyedHue()) // 3 - } - ); - } - - Utility.AssignRandomHair(this); - - if (Utility.RandomBool()) - Utility.AssignRandomFacialHair(this, HairHue); - - Halberd weapon = new Halberd(); - - weapon.Movable = false; - weapon.Crafter = this; - weapon.Quality = WeaponQuality.Exceptional; - - AddItem(weapon); - - Container pack = new Backpack(); - - pack.Movable = false; - - pack.DropItem(new Gold(10, 25)); - - AddItem(pack); - - Skills.Anatomy.Base = 120.0; - Skills.Tactics.Base = 120.0; - Skills.Swords.Base = 120.0; - Skills.MagicResist.Base = 120.0; - Skills.DetectHidden.Base = 100.0; - - NextCombatTime = Core.TickCount + 500; - Focus = target; - } - - public WarriorGuard(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public override Mobile Focus - { - get => m_Focus; - set - { - if (Deleted) - return; - - Mobile oldFocus = m_Focus; - - if (oldFocus != value) + [Constructible] + public WarriorGuard(Mobile target = null) : base(target) { - m_Focus = value; + InitStats(1000, 1000, 1000); + Title = "the guard"; - if (value != null) - AggressiveAction(value); + SpeechHue = Utility.RandomDyedHue(); - Combatant = value; + Hue = Race.Human.RandomSkinHue(); - if (oldFocus?.Alive == false) - Say("Thou hast suffered thy punishment, scoundrel."); - - if (value != null) - Say(500131); // Thou wilt regret thine actions, swine! - - if (m_AttackTimer != null) - { - m_AttackTimer.Stop(); - m_AttackTimer = null; - } - - if (m_IdleTimer != null) - { - m_IdleTimer.Stop(); - m_IdleTimer = null; - } - - if (m_Focus != null) - { - m_AttackTimer = new AttackTimer(this); - m_AttackTimer.Start(); - ((AttackTimer)m_AttackTimer).DoOnTick(); - } - else - { - m_IdleTimer = new IdleTimer(this); - m_IdleTimer.Start(); - } - } - else if (m_Focus == null && m_IdleTimer == null) - { - m_IdleTimer = new IdleTimer(this); - m_IdleTimer.Start(); - } - } - } - - public override bool OnBeforeDeath() - { - if (m_Focus?.Alive == true) - new AvengeTimer(m_Focus).Start(); // If a guard dies, three more guards will spawn - - return base.OnBeforeDeath(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Focus); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Focus = reader.ReadMobile(); - - if (m_Focus != null) + if (Female = Utility.RandomBool()) { - m_AttackTimer = new AttackTimer(this); - m_AttackTimer.Start(); + Body = 0x191; + Name = NameList.RandomName("female"); + + AddItem(Utility.RandomBool() ? (Item)new LeatherSkirt() : new LeatherShorts()); + + AddItem( + Utility.Random(5) switch + { + 0 => new FemaleLeatherChest(), + 1 => new FemaleStuddedChest(), + 2 => new LeatherBustierArms(), + 3 => new StuddedBustierArms(), + _ => new FemalePlateChest() // 4 + } + ); } else { - m_IdleTimer = new IdleTimer(this); - m_IdleTimer.Start(); + Body = 0x190; + Name = NameList.RandomName("male"); + + AddItem(new PlateChest()); + AddItem(new PlateArms()); + AddItem(new PlateLegs()); + + AddItem( + Utility.Random(3) switch + { + 0 => new Doublet(Utility.RandomNondyedHue()), + 1 => new Tunic(Utility.RandomNondyedHue()), + _ => new BodySash(Utility.RandomNondyedHue()) // 3 + } + ); } - break; - } - } + Utility.AssignRandomHair(this); + + if (Utility.RandomBool()) + Utility.AssignRandomFacialHair(this, HairHue); + + var weapon = new Halberd(); + + weapon.Movable = false; + weapon.Crafter = this; + weapon.Quality = WeaponQuality.Exceptional; + + AddItem(weapon); + + Container pack = new Backpack(); + + pack.Movable = false; + + pack.DropItem(new Gold(10, 25)); + + AddItem(pack); + + Skills.Anatomy.Base = 120.0; + Skills.Tactics.Base = 120.0; + Skills.Swords.Base = 120.0; + Skills.MagicResist.Base = 120.0; + Skills.DetectHidden.Base = 100.0; + + NextCombatTime = Core.TickCount + 500; + Focus = target; + } + + public WarriorGuard(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public override Mobile Focus + { + get => m_Focus; + set + { + if (Deleted) + return; + + var oldFocus = m_Focus; + + if (oldFocus != value) + { + m_Focus = value; + + if (value != null) + AggressiveAction(value); + + Combatant = value; + + if (oldFocus?.Alive == false) + Say("Thou hast suffered thy punishment, scoundrel."); + + if (value != null) + Say(500131); // Thou wilt regret thine actions, swine! + + if (m_AttackTimer != null) + { + m_AttackTimer.Stop(); + m_AttackTimer = null; + } + + if (m_IdleTimer != null) + { + m_IdleTimer.Stop(); + m_IdleTimer = null; + } + + if (m_Focus != null) + { + m_AttackTimer = new AttackTimer(this); + m_AttackTimer.Start(); + ((AttackTimer)m_AttackTimer).DoOnTick(); + } + else + { + m_IdleTimer = new IdleTimer(this); + m_IdleTimer.Start(); + } + } + else if (m_Focus == null && m_IdleTimer == null) + { + m_IdleTimer = new IdleTimer(this); + m_IdleTimer.Start(); + } + } + } + + public override bool OnBeforeDeath() + { + if (m_Focus?.Alive == true) + new AvengeTimer(m_Focus).Start(); // If a guard dies, three more guards will spawn + + return base.OnBeforeDeath(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Focus); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Focus = reader.ReadMobile(); + + if (m_Focus != null) + { + m_AttackTimer = new AttackTimer(this); + m_AttackTimer.Start(); + } + else + { + m_IdleTimer = new IdleTimer(this); + m_IdleTimer.Start(); + } + + break; + } + } + } + + public override void OnAfterDelete() + { + if (m_AttackTimer != null) + { + m_AttackTimer.Stop(); + m_AttackTimer = null; + } + + if (m_IdleTimer != null) + { + m_IdleTimer.Stop(); + m_IdleTimer = null; + } + + base.OnAfterDelete(); + } + + private class AvengeTimer : Timer + { + private readonly Mobile m_Focus; + + public AvengeTimer(Mobile focus) : base(TimeSpan.FromSeconds(2.5), TimeSpan.FromSeconds(1.0), 3) => + m_Focus = focus; + + protected override void OnTick() + { + Spawn(m_Focus, m_Focus, 1, true); + } + } + + private class AttackTimer : Timer + { + private readonly WarriorGuard m_Owner; + + public AttackTimer(WarriorGuard owner) : base(TimeSpan.FromSeconds(0.25), TimeSpan.FromSeconds(0.1)) => + m_Owner = owner; + + public void DoOnTick() + { + OnTick(); + } + + protected override void OnTick() + { + if (m_Owner.Deleted) + { + Stop(); + return; + } + + m_Owner.Criminal = false; + m_Owner.Kills = 0; + m_Owner.Stam = m_Owner.StamMax; + + var target = m_Owner.Focus; + + if (target != null && (target.Deleted || !target.Alive || !m_Owner.CanBeHarmful(target))) + { + m_Owner.Focus = null; + Stop(); + return; + } + + if (m_Owner.Weapon is Fists) + { + m_Owner.Kill(); + Stop(); + return; + } + + if (target != null && m_Owner.Combatant != target) + m_Owner.Combatant = target; + + if (target == null) + { + Stop(); + } + else + { + // + TeleportTo(target); + target.BoltEffect(0); + + if (target is BaseCreature creature) + creature.NoKillAwards = true; + + target.Damage(target.HitsMax, m_Owner); + target.Kill(); // just in case, maybe Damage is overridden on some shard + + if (target.Corpse != null && !target.Player) + target.Corpse.Delete(); + + m_Owner.Focus = null; + Stop(); + } // + + /*else if (!m_Owner.InRange( target, 20 )) + { + m_Owner.Focus = null; + } + else if (!m_Owner.InRange( target, 10 ) || !m_Owner.InLOS( target )) + { + TeleportTo( target ); + } + else if (!m_Owner.InRange( target, 1 )) + { + if (!m_Owner.Move( m_Owner.GetDirectionTo( target ) | Direction.Running )) + TeleportTo( target ); + } + else if (!m_Owner.CanSee( target )) + { + if (!m_Owner.UseSkill( SkillName.DetectHidden ) && Utility.Random( 50 ) == 0) + m_Owner.Say( "Reveal!" ); + }*/ + } + + private void TeleportTo(Mobile target) + { + var from = m_Owner.Location; + var to = target.Location; + + m_Owner.Location = to; + + Effects.SendLocationParticles( + EffectItem.Create(from, m_Owner.Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 2023 + ); + Effects.SendLocationParticles( + EffectItem.Create(to, m_Owner.Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 5023 + ); + + m_Owner.PlaySound(0x1FE); + } + } + + private class IdleTimer : Timer + { + private readonly WarriorGuard m_Owner; + private int m_Stage; + + public IdleTimer(WarriorGuard owner) : base(TimeSpan.FromSeconds(2.0), TimeSpan.FromSeconds(2.5)) => + m_Owner = owner; + + protected override void OnTick() + { + if (m_Owner.Deleted) + { + Stop(); + return; + } + + if (m_Stage++ % 4 == 0 || !m_Owner.Move(m_Owner.Direction)) + m_Owner.Direction = (Direction)Utility.Random(8); + + if (m_Stage > 16) + { + Effects.SendLocationParticles( + EffectItem.Create(m_Owner.Location, m_Owner.Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 2023 + ); + m_Owner.PlaySound(0x1FE); + + m_Owner.Delete(); + } + } + } } - - public override void OnAfterDelete() - { - if (m_AttackTimer != null) - { - m_AttackTimer.Stop(); - m_AttackTimer = null; - } - - if (m_IdleTimer != null) - { - m_IdleTimer.Stop(); - m_IdleTimer = null; - } - - base.OnAfterDelete(); - } - - private class AvengeTimer : Timer - { - private readonly Mobile m_Focus; - - public AvengeTimer(Mobile focus) : base(TimeSpan.FromSeconds(2.5), TimeSpan.FromSeconds(1.0), 3) => m_Focus = focus; - - protected override void OnTick() - { - Spawn(m_Focus, m_Focus, 1, true); - } - } - - private class AttackTimer : Timer - { - private readonly WarriorGuard m_Owner; - - public AttackTimer(WarriorGuard owner) : base(TimeSpan.FromSeconds(0.25), TimeSpan.FromSeconds(0.1)) => m_Owner = owner; - - public void DoOnTick() - { - OnTick(); - } - - protected override void OnTick() - { - if (m_Owner.Deleted) - { - Stop(); - return; - } - - m_Owner.Criminal = false; - m_Owner.Kills = 0; - m_Owner.Stam = m_Owner.StamMax; - - Mobile target = m_Owner.Focus; - - if (target != null && (target.Deleted || !target.Alive || !m_Owner.CanBeHarmful(target))) - { - m_Owner.Focus = null; - Stop(); - return; - } - - if (m_Owner.Weapon is Fists) - { - m_Owner.Kill(); - Stop(); - return; - } - - if (target != null && m_Owner.Combatant != target) - m_Owner.Combatant = target; - - if (target == null) - { - Stop(); - } - else - { - // - TeleportTo(target); - target.BoltEffect(0); - - if (target is BaseCreature creature) - creature.NoKillAwards = true; - - target.Damage(target.HitsMax, m_Owner); - target.Kill(); // just in case, maybe Damage is overridden on some shard - - if (target.Corpse != null && !target.Player) - target.Corpse.Delete(); - - m_Owner.Focus = null; - Stop(); - } // - - /*else if (!m_Owner.InRange( target, 20 )) - { - m_Owner.Focus = null; - } - else if (!m_Owner.InRange( target, 10 ) || !m_Owner.InLOS( target )) - { - TeleportTo( target ); - } - else if (!m_Owner.InRange( target, 1 )) - { - if (!m_Owner.Move( m_Owner.GetDirectionTo( target ) | Direction.Running )) - TeleportTo( target ); - } - else if (!m_Owner.CanSee( target )) - { - if (!m_Owner.UseSkill( SkillName.DetectHidden ) && Utility.Random( 50 ) == 0) - m_Owner.Say( "Reveal!" ); - }*/ - } - - private void TeleportTo(Mobile target) - { - Point3D from = m_Owner.Location; - Point3D to = target.Location; - - m_Owner.Location = to; - - Effects.SendLocationParticles(EffectItem.Create(from, m_Owner.Map, EffectItem.DefaultDuration), 0x3728, 10, - 10, 2023); - Effects.SendLocationParticles(EffectItem.Create(to, m_Owner.Map, EffectItem.DefaultDuration), 0x3728, 10, 10, - 5023); - - m_Owner.PlaySound(0x1FE); - } - } - - private class IdleTimer : Timer - { - private readonly WarriorGuard m_Owner; - private int m_Stage; - - public IdleTimer(WarriorGuard owner) : base(TimeSpan.FromSeconds(2.0), TimeSpan.FromSeconds(2.5)) => m_Owner = owner; - - protected override void OnTick() - { - if (m_Owner.Deleted) - { - Stop(); - return; - } - - if (m_Stage++ % 4 == 0 || !m_Owner.Move(m_Owner.Direction)) - m_Owner.Direction = (Direction)Utility.Random(8); - - if (m_Stage > 16) - { - Effects.SendLocationParticles( - EffectItem.Create(m_Owner.Location, m_Owner.Map, EffectItem.DefaultDuration), 0x3728, 10, 10, 2023); - m_Owner.PlaySound(0x1FE); - - m_Owner.Delete(); - } - } - } - } } diff --git a/Projects/UOContent/Mobiles/Healers/BaseHealer.cs b/Projects/UOContent/Mobiles/Healers/BaseHealer.cs index 4ca75169d..ec2cb4102 100644 --- a/Projects/UOContent/Mobiles/Healers/BaseHealer.cs +++ b/Projects/UOContent/Mobiles/Healers/BaseHealer.cs @@ -5,148 +5,148 @@ using Server.Items; namespace Server.Mobiles { - public abstract class BaseHealer : BaseVendor - { - private static readonly TimeSpan ResurrectDelay = TimeSpan.FromSeconds(2.0); - - private DateTime m_NextResurrect; - - public BaseHealer() + public abstract class BaseHealer : BaseVendor { - if (!IsInvulnerable) - { - AI = AIType.AI_Mage; - ActiveSpeed = 0.2; - PassiveSpeed = 0.8; - RangePerception = DefaultRangePerception; - FightMode = FightMode.Aggressor; - } + private static readonly TimeSpan ResurrectDelay = TimeSpan.FromSeconds(2.0); - SpeechHue = 0; + private DateTime m_NextResurrect; - SetStr(304, 400); - SetDex(102, 150); - SetInt(204, 300); - - SetDamage(10, 23); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 40, 50); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 40, 50); - - SetSkill(SkillName.Anatomy, 75.0, 97.5); - SetSkill(SkillName.EvalInt, 82.0, 100.0); - SetSkill(SkillName.Healing, 75.0, 97.5); - SetSkill(SkillName.Magery, 82.0, 100.0); - SetSkill(SkillName.MagicResist, 82.0, 100.0); - SetSkill(SkillName.Tactics, 82.0, 100.0); - - Fame = 1000; - Karma = 10000; - - PackItem(new Bandage(Utility.RandomMinMax(5, 10))); - PackItem(new HealPotion()); - PackItem(new CurePotion()); - } - - public BaseHealer(Serial serial) : base(serial) - { - } - - protected override List SBInfos { get; } = new List(); - - public override bool IsActiveVendor => false; - public override bool IsInvulnerable => false; - - public override VendorShoeType ShoeType => VendorShoeType.Sandals; - - public virtual bool HealsYoungPlayers => true; - - public override void InitSBInfo() - { - } - - public virtual int GetRobeColor() => Utility.RandomYellowHue(); - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new Robe(GetRobeColor())); - } - - public virtual bool CheckResurrect(Mobile m) => true; - - public virtual void OfferResurrection(Mobile m) - { - Direction = GetDirectionTo(m); - - m.PlaySound(0x1F2); - m.FixedEffect(0x376A, 10, 16); - - m.CloseGump(); - m.SendGump(new ResurrectGump(m, ResurrectMessage.Healer)); - } - - public virtual void OfferHeal(PlayerMobile m) - { - Direction = GetDirectionTo(m); - - if (m.CheckYoungHealTime()) - { - Say(501229); // You look like you need some healing my child. - - m.PlaySound(0x1F2); - m.FixedEffect(0x376A, 9, 32); - - m.Hits = m.HitsMax; - } - else - { - Say(501228); // I can do no more for you at this time. - } - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (!m.Frozen && DateTime.UtcNow >= m_NextResurrect && InRange(m, 4) && !InRange(oldLocation, 4) && InLOS(m)) - { - if (!m.Alive) + public BaseHealer() { - m_NextResurrect = DateTime.UtcNow + ResurrectDelay; + if (!IsInvulnerable) + { + AI = AIType.AI_Mage; + ActiveSpeed = 0.2; + PassiveSpeed = 0.8; + RangePerception = DefaultRangePerception; + FightMode = FightMode.Aggressor; + } - if (m.Map?.CanFit(m.Location, 16, false, false) != true) - m.SendLocalizedMessage(502391); // Thou can not be resurrected there! - else if (CheckResurrect(m)) OfferResurrection(m); + SpeechHue = 0; + + SetStr(304, 400); + SetDex(102, 150); + SetInt(204, 300); + + SetDamage(10, 23); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 40, 50); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 40, 50); + + SetSkill(SkillName.Anatomy, 75.0, 97.5); + SetSkill(SkillName.EvalInt, 82.0, 100.0); + SetSkill(SkillName.Healing, 75.0, 97.5); + SetSkill(SkillName.Magery, 82.0, 100.0); + SetSkill(SkillName.MagicResist, 82.0, 100.0); + SetSkill(SkillName.Tactics, 82.0, 100.0); + + Fame = 1000; + Karma = 10000; + + PackItem(new Bandage(Utility.RandomMinMax(5, 10))); + PackItem(new HealPotion()); + PackItem(new CurePotion()); } - else if (HealsYoungPlayers && m.Hits < m.HitsMax && m is PlayerMobile mobile && mobile.Young) + + public BaseHealer(Serial serial) : base(serial) { - OfferHeal(mobile); } - } - } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - } + protected override List SBInfos { get; } = new List(); - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override bool IsActiveVendor => false; + public override bool IsInvulnerable => false; - if (!IsInvulnerable) - { - AI = AIType.AI_Mage; - ActiveSpeed = 0.2; - PassiveSpeed = 0.8; - RangePerception = DefaultRangePerception; - FightMode = FightMode.Aggressor; - } + public override VendorShoeType ShoeType => VendorShoeType.Sandals; + + public virtual bool HealsYoungPlayers => true; + + public override void InitSBInfo() + { + } + + public virtual int GetRobeColor() => Utility.RandomYellowHue(); + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new Robe(GetRobeColor())); + } + + public virtual bool CheckResurrect(Mobile m) => true; + + public virtual void OfferResurrection(Mobile m) + { + Direction = GetDirectionTo(m); + + m.PlaySound(0x1F2); + m.FixedEffect(0x376A, 10, 16); + + m.CloseGump(); + m.SendGump(new ResurrectGump(m, ResurrectMessage.Healer)); + } + + public virtual void OfferHeal(PlayerMobile m) + { + Direction = GetDirectionTo(m); + + if (m.CheckYoungHealTime()) + { + Say(501229); // You look like you need some healing my child. + + m.PlaySound(0x1F2); + m.FixedEffect(0x376A, 9, 32); + + m.Hits = m.HitsMax; + } + else + { + Say(501228); // I can do no more for you at this time. + } + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (!m.Frozen && DateTime.UtcNow >= m_NextResurrect && InRange(m, 4) && !InRange(oldLocation, 4) && InLOS(m)) + { + if (!m.Alive) + { + m_NextResurrect = DateTime.UtcNow + ResurrectDelay; + + if (m.Map?.CanFit(m.Location, 16, false, false) != true) + m.SendLocalizedMessage(502391); // Thou can not be resurrected there! + else if (CheckResurrect(m)) OfferResurrection(m); + } + else if (HealsYoungPlayers && m.Hits < m.HitsMax && m is PlayerMobile mobile && mobile.Young) + { + OfferHeal(mobile); + } + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + if (!IsInvulnerable) + { + AI = AIType.AI_Mage; + ActiveSpeed = 0.2; + PassiveSpeed = 0.8; + RangePerception = DefaultRangePerception; + FightMode = FightMode.Aggressor; + } + } } - } } diff --git a/Projects/UOContent/Mobiles/Healers/EvilHealer.cs b/Projects/UOContent/Mobiles/Healers/EvilHealer.cs index 3d1e9fcfc..6c672108d 100644 --- a/Projects/UOContent/Mobiles/Healers/EvilHealer.cs +++ b/Projects/UOContent/Mobiles/Healers/EvilHealer.cs @@ -1,67 +1,67 @@ namespace Server.Mobiles { - public class EvilHealer : BaseHealer - { - [Constructible] - public EvilHealer() + public class EvilHealer : BaseHealer { - Title = "the healer"; + [Constructible] + public EvilHealer() + { + Title = "the healer"; - Karma = -10000; + Karma = -10000; - SetSkill(SkillName.Forensics, 80.0, 100.0); - SetSkill(SkillName.SpiritSpeak, 80.0, 100.0); - SetSkill(SkillName.Swords, 80.0, 100.0); + SetSkill(SkillName.Forensics, 80.0, 100.0); + SetSkill(SkillName.SpiritSpeak, 80.0, 100.0); + SetSkill(SkillName.Swords, 80.0, 100.0); + } + + public EvilHealer(Serial serial) : base(serial) + { + } + + public override bool CanTeach => true; + + public override bool AlwaysMurderer => true; + public override bool IsActiveVendor => true; + + public override bool CheckTeach(SkillName skill, Mobile from) + { + if (!base.CheckTeach(skill, from)) + return false; + + return skill == SkillName.Forensics + || skill == SkillName.Healing + || skill == SkillName.SpiritSpeak + || skill == SkillName.Swords; + } + + public override void InitSBInfo() + { + SBInfos.Add(new SBHealer()); + } + + public override bool CheckResurrect(Mobile m) + { + if (Core.AOS && m.Criminal) + { + Say(501222); // Thou art a criminal. I shall not resurrect thee. + return false; + } + + return true; + } + + 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 EvilHealer(Serial serial) : base(serial) - { - } - - public override bool CanTeach => true; - - public override bool AlwaysMurderer => true; - public override bool IsActiveVendor => true; - - public override bool CheckTeach(SkillName skill, Mobile from) - { - if (!base.CheckTeach(skill, from)) - return false; - - return skill == SkillName.Forensics - || skill == SkillName.Healing - || skill == SkillName.SpiritSpeak - || skill == SkillName.Swords; - } - - public override void InitSBInfo() - { - SBInfos.Add(new SBHealer()); - } - - public override bool CheckResurrect(Mobile m) - { - if (Core.AOS && m.Criminal) - { - Say(501222); // Thou art a criminal. I shall not resurrect thee. - return false; - } - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Healers/EvilWanderingHealer.cs b/Projects/UOContent/Mobiles/Healers/EvilWanderingHealer.cs index d6c0e98f3..e74fbdd64 100644 --- a/Projects/UOContent/Mobiles/Healers/EvilWanderingHealer.cs +++ b/Projects/UOContent/Mobiles/Healers/EvilWanderingHealer.cs @@ -2,76 +2,76 @@ using Server.Items; namespace Server.Mobiles { - public class EvilWanderingHealer : BaseHealer - { - [Constructible] - public EvilWanderingHealer() + public class EvilWanderingHealer : BaseHealer { - Title = Core.AOS ? "the Priest Of Mondain" : "the evil wandering healer"; - Karma = -10000; + [Constructible] + public EvilWanderingHealer() + { + Title = Core.AOS ? "the Priest Of Mondain" : "the evil wandering healer"; + Karma = -10000; - AddItem(new GnarledStaff()); + AddItem(new GnarledStaff()); - SetSkill(SkillName.Camping, 80.0, 100.0); - SetSkill(SkillName.Forensics, 80.0, 100.0); - SetSkill(SkillName.SpiritSpeak, 80.0, 100.0); + SetSkill(SkillName.Camping, 80.0, 100.0); + SetSkill(SkillName.Forensics, 80.0, 100.0); + SetSkill(SkillName.SpiritSpeak, 80.0, 100.0); + } + + public EvilWanderingHealer(Serial serial) : base(serial) + { + } + + public override bool CanTeach => true; + + public override bool AlwaysMurderer => true; + public override bool ClickTitle => false; // Do not display title in OnSingleClick + + public override bool CheckTeach(SkillName skill, Mobile from) + { + if (!base.CheckTeach(skill, from)) + return false; + + return skill == SkillName.Anatomy + || skill == SkillName.Camping + || skill == SkillName.Forensics + || skill == SkillName.Healing + || skill == SkillName.SpiritSpeak; + } + + public override bool CheckResurrect(Mobile m) + { + if (Core.AOS && m.Criminal) + { + Say(501222); // Thou art a criminal. I shall not resurrect thee. + return false; + } + + return true; + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + if (Utility.RandomDouble() < 0.5) + c.DropItem(new FragmentOfAMap()); + } + + 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 < 1 && Title == "the wandering healer" && Core.AOS) + Title = "the priest of Mondain"; + } } - - public EvilWanderingHealer(Serial serial) : base(serial) - { - } - - public override bool CanTeach => true; - - public override bool AlwaysMurderer => true; - public override bool ClickTitle => false; // Do not display title in OnSingleClick - - public override bool CheckTeach(SkillName skill, Mobile from) - { - if (!base.CheckTeach(skill, from)) - return false; - - return skill == SkillName.Anatomy - || skill == SkillName.Camping - || skill == SkillName.Forensics - || skill == SkillName.Healing - || skill == SkillName.SpiritSpeak; - } - - public override bool CheckResurrect(Mobile m) - { - if (Core.AOS && m.Criminal) - { - Say(501222); // Thou art a criminal. I shall not resurrect thee. - return false; - } - - return true; - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - if (Utility.RandomDouble() < 0.5) - c.DropItem(new FragmentOfAMap()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1 && Title == "the wandering healer" && Core.AOS) - Title = "the priest of Mondain"; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Healers/FortuneTeller.cs b/Projects/UOContent/Mobiles/Healers/FortuneTeller.cs index c0a8b1a20..8c4c104d6 100644 --- a/Projects/UOContent/Mobiles/Healers/FortuneTeller.cs +++ b/Projects/UOContent/Mobiles/Healers/FortuneTeller.cs @@ -2,79 +2,79 @@ using Server.Items; namespace Server.Mobiles { - public class FortuneTeller : BaseHealer - { - [Constructible] - public FortuneTeller() + public class FortuneTeller : BaseHealer { - Title = "the fortune teller"; + [Constructible] + public FortuneTeller() + { + Title = "the fortune teller"; - SetSkill(SkillName.Anatomy, 85.0, 100.0); - SetSkill(SkillName.Healing, 90.0, 100.0); - SetSkill(SkillName.Forensics, 75.0, 98.0); - SetSkill(SkillName.SpiritSpeak, 65.0, 88.0); + SetSkill(SkillName.Anatomy, 85.0, 100.0); + SetSkill(SkillName.Healing, 90.0, 100.0); + SetSkill(SkillName.Forensics, 75.0, 98.0); + SetSkill(SkillName.SpiritSpeak, 65.0, 88.0); + } + + public FortuneTeller(Serial serial) : base(serial) + { + } + + public override bool CanTeach => true; + + public override bool IsActiveVendor => true; + public override bool IsInvulnerable => true; + + public override bool CheckTeach(SkillName skill, Mobile from) + { + if (!base.CheckTeach(skill, from)) + return false; + + return skill == SkillName.Anatomy + || skill == SkillName.Healing + || skill == SkillName.Forensics + || skill == SkillName.SpiritSpeak; + } + + public override void InitSBInfo() + { + SBInfos.Add(new SBMage()); + SBInfos.Add(new SBFortuneTeller()); + } + + public override int GetRobeColor() => Utility.RandomBrightHue(); + + public override void InitOutfit() + { + base.InitOutfit(); + + switch (Utility.Random(3)) + { + case 0: + AddItem(new SkullCap(Utility.RandomBrightHue())); + break; + case 1: + AddItem(new WizardsHat(Utility.RandomBrightHue())); + break; + case 2: + AddItem(new Bandana(Utility.RandomBrightHue())); + break; + } + + AddItem(new Spellbook()); + } + + 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 FortuneTeller(Serial serial) : base(serial) - { - } - - public override bool CanTeach => true; - - public override bool IsActiveVendor => true; - public override bool IsInvulnerable => true; - - public override bool CheckTeach(SkillName skill, Mobile from) - { - if (!base.CheckTeach(skill, from)) - return false; - - return skill == SkillName.Anatomy - || skill == SkillName.Healing - || skill == SkillName.Forensics - || skill == SkillName.SpiritSpeak; - } - - public override void InitSBInfo() - { - SBInfos.Add(new SBMage()); - SBInfos.Add(new SBFortuneTeller()); - } - - public override int GetRobeColor() => Utility.RandomBrightHue(); - - public override void InitOutfit() - { - base.InitOutfit(); - - switch (Utility.Random(3)) - { - case 0: - AddItem(new SkullCap(Utility.RandomBrightHue())); - break; - case 1: - AddItem(new WizardsHat(Utility.RandomBrightHue())); - break; - case 2: - AddItem(new Bandana(Utility.RandomBrightHue())); - break; - } - - AddItem(new Spellbook()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Healers/Healer.cs b/Projects/UOContent/Mobiles/Healers/Healer.cs index cbd2cb337..d1de8dfc0 100644 --- a/Projects/UOContent/Mobiles/Healers/Healer.cs +++ b/Projects/UOContent/Mobiles/Healers/Healer.cs @@ -1,80 +1,80 @@ namespace Server.Mobiles { - public class Healer : BaseHealer - { - [Constructible] - public Healer() + public class Healer : BaseHealer { - Title = "the healer"; + [Constructible] + public Healer() + { + Title = "the healer"; - if (!Core.AOS) - NameHue = 0x35; + if (!Core.AOS) + NameHue = 0x35; - SetSkill(SkillName.Forensics, 80.0, 100.0); - SetSkill(SkillName.SpiritSpeak, 80.0, 100.0); - SetSkill(SkillName.Swords, 80.0, 100.0); + SetSkill(SkillName.Forensics, 80.0, 100.0); + SetSkill(SkillName.SpiritSpeak, 80.0, 100.0); + SetSkill(SkillName.Swords, 80.0, 100.0); + } + + public Healer(Serial serial) : base(serial) + { + } + + public override bool CanTeach => true; + + public override bool IsActiveVendor => true; + public override bool IsInvulnerable => true; + + public override bool CheckTeach(SkillName skill, Mobile from) + { + if (!base.CheckTeach(skill, from)) + return false; + + return skill == SkillName.Forensics + || skill == SkillName.Healing + || skill == SkillName.SpiritSpeak + || skill == SkillName.Swords; + } + + public override void InitSBInfo() + { + SBInfos.Add(new SBHealer()); + } + + public override bool CheckResurrect(Mobile m) + { + if (m.Criminal) + { + Say(501222); // Thou art a criminal. I shall not resurrect thee. + return false; + } + + if (m.Kills >= 5) + { + Say(501223); // Thou'rt not a decent and good person. I shall not resurrect thee. + return false; + } + + if (m.Karma < 0) + Say(501224); // Thou hast strayed from the path of virtue, but thou still deservest a second chance. + + return true; + } + + 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 (Core.AOS && NameHue == 0x35) + NameHue = -1; + } } - - public Healer(Serial serial) : base(serial) - { - } - - public override bool CanTeach => true; - - public override bool IsActiveVendor => true; - public override bool IsInvulnerable => true; - - public override bool CheckTeach(SkillName skill, Mobile from) - { - if (!base.CheckTeach(skill, from)) - return false; - - return skill == SkillName.Forensics - || skill == SkillName.Healing - || skill == SkillName.SpiritSpeak - || skill == SkillName.Swords; - } - - public override void InitSBInfo() - { - SBInfos.Add(new SBHealer()); - } - - public override bool CheckResurrect(Mobile m) - { - if (m.Criminal) - { - Say(501222); // Thou art a criminal. I shall not resurrect thee. - return false; - } - - if (m.Kills >= 5) - { - Say(501223); // Thou'rt not a decent and good person. I shall not resurrect thee. - return false; - } - - if (m.Karma < 0) - Say(501224); // Thou hast strayed from the path of virtue, but thou still deservest a second chance. - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Core.AOS && NameHue == 0x35) - NameHue = -1; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Healers/PricedHealer.cs b/Projects/UOContent/Mobiles/Healers/PricedHealer.cs index 58d24d9e1..5c4f6ad62 100644 --- a/Projects/UOContent/Mobiles/Healers/PricedHealer.cs +++ b/Projects/UOContent/Mobiles/Healers/PricedHealer.cs @@ -2,68 +2,68 @@ using Server.Gumps; namespace Server.Mobiles { - public class PricedHealer : BaseHealer - { - [Constructible] - public PricedHealer(int price = 5000) + public class PricedHealer : BaseHealer { - Price = price; + [Constructible] + public PricedHealer(int price = 5000) + { + Price = price; - if (!Core.AOS) - NameHue = 0x35; + if (!Core.AOS) + NameHue = 0x35; + } + + public PricedHealer(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Price { get; set; } + + public override bool IsInvulnerable => true; + + public override bool HealsYoungPlayers => false; + + public override void InitSBInfo() + { + } + + public override void OfferResurrection(Mobile m) + { + Direction = GetDirectionTo(m); + + m.PlaySound(0x214); + m.FixedEffect(0x376A, 10, 16); + + m.CloseGump(); + m.SendGump(new ResurrectGump(m, this, Price)); + } + + public override bool CheckResurrect(Mobile m) => true; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(Price); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Price = reader.ReadInt(); + break; + } + } + } } - - public PricedHealer(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Price { get; set; } - - public override bool IsInvulnerable => true; - - public override bool HealsYoungPlayers => false; - - public override void InitSBInfo() - { - } - - public override void OfferResurrection(Mobile m) - { - Direction = GetDirectionTo(m); - - m.PlaySound(0x214); - m.FixedEffect(0x376A, 10, 16); - - m.CloseGump(); - m.SendGump(new ResurrectGump(m, this, Price)); - } - - public override bool CheckResurrect(Mobile m) => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(Price); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Price = reader.ReadInt(); - break; - } - } - } - } } diff --git a/Projects/UOContent/Mobiles/Healers/WanderingHealer.cs b/Projects/UOContent/Mobiles/Healers/WanderingHealer.cs index 8a0fdf317..a329ecc8a 100644 --- a/Projects/UOContent/Mobiles/Healers/WanderingHealer.cs +++ b/Projects/UOContent/Mobiles/Healers/WanderingHealer.cs @@ -2,72 +2,72 @@ using Server.Items; namespace Server.Mobiles { - public class WanderingHealer : BaseHealer - { - [Constructible] - public WanderingHealer() + public class WanderingHealer : BaseHealer { - Title = "the wandering healer"; + [Constructible] + public WanderingHealer() + { + Title = "the wandering healer"; - AddItem(new GnarledStaff()); + AddItem(new GnarledStaff()); - SetSkill(SkillName.Camping, 80.0, 100.0); - SetSkill(SkillName.Forensics, 80.0, 100.0); - SetSkill(SkillName.SpiritSpeak, 80.0, 100.0); + SetSkill(SkillName.Camping, 80.0, 100.0); + SetSkill(SkillName.Forensics, 80.0, 100.0); + SetSkill(SkillName.SpiritSpeak, 80.0, 100.0); + } + + public WanderingHealer(Serial serial) : base(serial) + { + } + + public override bool CanTeach => true; + + public override bool ClickTitle => false; // Do not display title in OnSingleClick + + public override bool CheckTeach(SkillName skill, Mobile from) + { + if (!base.CheckTeach(skill, from)) + return false; + + return skill == SkillName.Anatomy + || skill == SkillName.Camping + || skill == SkillName.Forensics + || skill == SkillName.Healing + || skill == SkillName.SpiritSpeak; + } + + public override bool CheckResurrect(Mobile m) + { + if (m.Criminal) + { + Say(501222); // Thou art a criminal. I shall not resurrect thee. + return false; + } + + if (m.Kills >= 5) + { + Say(501223); // Thou'rt not a decent and good person. I shall not resurrect thee. + return false; + } + + if (m.Karma < 0) + Say(501224); // Thou hast strayed from the path of virtue, but thou still deservest a second chance. + + return true; + } + + 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 WanderingHealer(Serial serial) : base(serial) - { - } - - public override bool CanTeach => true; - - public override bool ClickTitle => false; // Do not display title in OnSingleClick - - public override bool CheckTeach(SkillName skill, Mobile from) - { - if (!base.CheckTeach(skill, from)) - return false; - - return skill == SkillName.Anatomy - || skill == SkillName.Camping - || skill == SkillName.Forensics - || skill == SkillName.Healing - || skill == SkillName.SpiritSpeak; - } - - public override bool CheckResurrect(Mobile m) - { - if (m.Criminal) - { - Say(501222); // Thou art a criminal. I shall not resurrect thee. - return false; - } - - if (m.Kills >= 5) - { - Say(501223); // Thou'rt not a decent and good person. I shall not resurrect thee. - return false; - } - - if (m.Karma < 0) - Say(501224); // Thou hast strayed from the path of virtue, but thou still deservest a second chance. - - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/AOS/AbysmalHorror.cs b/Projects/UOContent/Mobiles/Monsters/AOS/AbysmalHorror.cs index 51878fc7d..b575bdc66 100644 --- a/Projects/UOContent/Mobiles/Monsters/AOS/AbysmalHorror.cs +++ b/Projects/UOContent/Mobiles/Monsters/AOS/AbysmalHorror.cs @@ -2,88 +2,89 @@ using Server.Items; namespace Server.Mobiles { - public class AbysmalHorror : BaseCreature - { - [Constructible] - public AbysmalHorror() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class AbysmalHorror : BaseCreature { - Body = 312; - BaseSoundID = 0x451; + [Constructible] + public AbysmalHorror() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 312; + BaseSoundID = 0x451; - SetStr(401, 420); - SetDex(81, 90); - SetInt(401, 420); + SetStr(401, 420); + SetDex(81, 90); + SetInt(401, 420); - SetHits(6000); + SetHits(6000); - SetDamage(13, 17); + SetDamage(13, 17); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Poison, 50); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Poison, 50); - SetResistance(ResistanceType.Physical, 30, 35); - SetResistance(ResistanceType.Fire, 100); - SetResistance(ResistanceType.Cold, 50, 55); - SetResistance(ResistanceType.Poison, 60, 65); - SetResistance(ResistanceType.Energy, 77, 80); + SetResistance(ResistanceType.Physical, 30, 35); + SetResistance(ResistanceType.Fire, 100); + SetResistance(ResistanceType.Cold, 50, 55); + SetResistance(ResistanceType.Poison, 60, 65); + SetResistance(ResistanceType.Energy, 77, 80); - SetSkill(SkillName.EvalInt, 200.0); - SetSkill(SkillName.Magery, 112.6, 117.5); - SetSkill(SkillName.Meditation, 200.0); - SetSkill(SkillName.MagicResist, 117.6, 120.0); - SetSkill(SkillName.Tactics, 100.0); - SetSkill(SkillName.Wrestling, 84.1, 88.0); + SetSkill(SkillName.EvalInt, 200.0); + SetSkill(SkillName.Magery, 112.6, 117.5); + SetSkill(SkillName.Meditation, 200.0); + SetSkill(SkillName.MagicResist, 117.6, 120.0); + SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.Wrestling, 84.1, 88.0); - Fame = 26000; - Karma = -26000; + Fame = 26000; + Karma = -26000; - VirtualArmor = 54; + VirtualArmor = 54; + } + + public AbysmalHorror(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an abysmal horror corpse"; + + public override bool IgnoreYoungProtection => Core.ML; + + public override string DefaultName => "an abysmal horror"; + + public override bool BardImmune => !Core.SE; + public override bool Unprovokable => Core.SE; + public override bool AreaPeaceImmune => Core.SE; + public override Poison PoisonImmune => Poison.Lethal; + public override int TreasureMapLevel => 1; + + public override WeaponAbility GetWeaponAbility() => + Utility.RandomBool() ? WeaponAbility.MortalStrike : WeaponAbility.WhirlwindAttack; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 2); + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + if (!Summoned && !NoKillAwards && DemonKnight.CheckArtifactChance(this)) + DemonKnight.DistributeArtifact(this); + } + + 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 (BaseSoundID == 357) + BaseSoundID = 0x451; + } } - - public AbysmalHorror(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an abysmal horror corpse"; - - public override bool IgnoreYoungProtection => Core.ML; - - public override string DefaultName => "an abysmal horror"; - - public override bool BardImmune => !Core.SE; - public override bool Unprovokable => Core.SE; - public override bool AreaPeaceImmune => Core.SE; - public override Poison PoisonImmune => Poison.Lethal; - public override int TreasureMapLevel => 1; - - public override WeaponAbility GetWeaponAbility() => Utility.RandomBool() ? WeaponAbility.MortalStrike : WeaponAbility.WhirlwindAttack; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 2); - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - if (!Summoned && !NoKillAwards && DemonKnight.CheckArtifactChance(this)) - DemonKnight.DistributeArtifact(this); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (BaseSoundID == 357) - BaseSoundID = 0x451; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/AOS/BoneDemon.cs b/Projects/UOContent/Mobiles/Monsters/AOS/BoneDemon.cs index e0920fdc8..adbc7f5a1 100644 --- a/Projects/UOContent/Mobiles/Monsters/AOS/BoneDemon.cs +++ b/Projects/UOContent/Mobiles/Monsters/AOS/BoneDemon.cs @@ -1,72 +1,72 @@ namespace Server.Mobiles { - public class BoneDemon : BaseCreature - { - [Constructible] - public BoneDemon() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class BoneDemon : BaseCreature { - Body = 308; - BaseSoundID = 0x48D; + [Constructible] + public BoneDemon() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 308; + BaseSoundID = 0x48D; - SetStr(1000); - SetDex(151, 175); - SetInt(171, 220); + SetStr(1000); + SetDex(151, 175); + SetInt(171, 220); - SetHits(3600); + SetHits(3600); - SetDamage(34, 36); + SetDamage(34, 36); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Cold, 50); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Cold, 50); - SetResistance(ResistanceType.Physical, 75); - SetResistance(ResistanceType.Fire, 60); - SetResistance(ResistanceType.Cold, 90); - SetResistance(ResistanceType.Poison, 100); - SetResistance(ResistanceType.Energy, 60); + SetResistance(ResistanceType.Physical, 75); + SetResistance(ResistanceType.Fire, 60); + SetResistance(ResistanceType.Cold, 90); + SetResistance(ResistanceType.Poison, 100); + SetResistance(ResistanceType.Energy, 60); - SetSkill(SkillName.DetectHidden, 80.0); - SetSkill(SkillName.EvalInt, 77.6, 87.5); - SetSkill(SkillName.Magery, 77.6, 87.5); - SetSkill(SkillName.Meditation, 100.0); - SetSkill(SkillName.MagicResist, 50.1, 75.0); - SetSkill(SkillName.Tactics, 100.0); - SetSkill(SkillName.Wrestling, 100.0); + SetSkill(SkillName.DetectHidden, 80.0); + SetSkill(SkillName.EvalInt, 77.6, 87.5); + SetSkill(SkillName.Magery, 77.6, 87.5); + SetSkill(SkillName.Meditation, 100.0); + SetSkill(SkillName.MagicResist, 50.1, 75.0); + SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.Wrestling, 100.0); - Fame = 20000; - Karma = -20000; + Fame = 20000; + Karma = -20000; - VirtualArmor = 44; + VirtualArmor = 44; + } + + public BoneDemon(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a bone demon corpse"; + public override string DefaultName => "a bone demon"; + + public override bool BardImmune => !Core.SE; + public override bool Unprovokable => Core.SE; + public override bool AreaPeaceImmune => Core.SE; + public override Poison PoisonImmune => Poison.Lethal; + public override int TreasureMapLevel => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 8); + } + + 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(); + } } - - public BoneDemon(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a bone demon corpse"; - public override string DefaultName => "a bone demon"; - - public override bool BardImmune => !Core.SE; - public override bool Unprovokable => Core.SE; - public override bool AreaPeaceImmune => Core.SE; - public override Poison PoisonImmune => Poison.Lethal; - public override int TreasureMapLevel => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 8); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/AOS/CrystalElemental.cs b/Projects/UOContent/Mobiles/Monsters/AOS/CrystalElemental.cs index 3a8130a20..3d1ba2821 100644 --- a/Projects/UOContent/Mobiles/Monsters/AOS/CrystalElemental.cs +++ b/Projects/UOContent/Mobiles/Monsters/AOS/CrystalElemental.cs @@ -2,74 +2,74 @@ using Server.Items; namespace Server.Mobiles { - public class CrystalElemental : BaseCreature - { - [Constructible] - public CrystalElemental() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class CrystalElemental : BaseCreature { - Body = 300; - BaseSoundID = 278; + [Constructible] + public CrystalElemental() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 300; + BaseSoundID = 278; - SetStr(136, 160); - SetDex(51, 65); - SetInt(86, 110); + SetStr(136, 160); + SetDex(51, 65); + SetInt(86, 110); - SetHits(150); + SetHits(150); - SetDamage(10, 15); + SetDamage(10, 15); - SetDamageType(ResistanceType.Physical, 80); - SetDamageType(ResistanceType.Energy, 20); + SetDamageType(ResistanceType.Physical, 80); + SetDamageType(ResistanceType.Energy, 20); - SetResistance(ResistanceType.Physical, 50, 60); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 100); - SetResistance(ResistanceType.Energy, 55, 70); + SetResistance(ResistanceType.Physical, 50, 60); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 100); + SetResistance(ResistanceType.Energy, 55, 70); - SetSkill(SkillName.EvalInt, 70.1, 75.0); - SetSkill(SkillName.Magery, 70.1, 75.0); - SetSkill(SkillName.Meditation, 65.1, 75.0); - SetSkill(SkillName.MagicResist, 80.1, 90.0); - SetSkill(SkillName.Tactics, 75.1, 85.0); - SetSkill(SkillName.Wrestling, 65.1, 75.0); + SetSkill(SkillName.EvalInt, 70.1, 75.0); + SetSkill(SkillName.Magery, 70.1, 75.0); + SetSkill(SkillName.Meditation, 65.1, 75.0); + SetSkill(SkillName.MagicResist, 80.1, 90.0); + SetSkill(SkillName.Tactics, 75.1, 85.0); + SetSkill(SkillName.Wrestling, 65.1, 75.0); - Fame = 6500; - Karma = -6500; + Fame = 6500; + Karma = -6500; - VirtualArmor = 54; + VirtualArmor = 54; + } + + public CrystalElemental(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a crystal elemental corpse"; + + public override string DefaultName => "a crystal elemental"; + + public override bool BleedImmune => true; + public override Poison PoisonImmune => Poison.Lethal; + public override int TreasureMapLevel => 1; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.BleedAttack; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.Average); + } + + 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(); + } } - - public CrystalElemental(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a crystal elemental corpse"; - - public override string DefaultName => "a crystal elemental"; - - public override bool BleedImmune => true; - public override Poison PoisonImmune => Poison.Lethal; - public override int TreasureMapLevel => 1; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.BleedAttack; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.Average); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/AOS/DarknightCreeper.cs b/Projects/UOContent/Mobiles/Monsters/AOS/DarknightCreeper.cs index 90f2f4a1d..39f063798 100644 --- a/Projects/UOContent/Mobiles/Monsters/AOS/DarknightCreeper.cs +++ b/Projects/UOContent/Mobiles/Monsters/AOS/DarknightCreeper.cs @@ -2,91 +2,91 @@ using Server.Items; namespace Server.Mobiles { - public class DarknightCreeper : BaseCreature - { - [Constructible] - public DarknightCreeper() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class DarknightCreeper : BaseCreature { - Name = NameList.RandomName("darknight creeper"); - Body = 313; - BaseSoundID = 0xE0; + [Constructible] + public DarknightCreeper() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Name = NameList.RandomName("darknight creeper"); + Body = 313; + BaseSoundID = 0xE0; - SetStr(301, 330); - SetDex(101, 110); - SetInt(301, 330); + SetStr(301, 330); + SetDex(101, 110); + SetInt(301, 330); - SetHits(4000); + SetHits(4000); - SetDamage(22, 26); + SetDamage(22, 26); - SetDamageType(ResistanceType.Physical, 85); - SetDamageType(ResistanceType.Poison, 15); + SetDamageType(ResistanceType.Physical, 85); + SetDamageType(ResistanceType.Poison, 15); - SetResistance(ResistanceType.Physical, 60); - SetResistance(ResistanceType.Fire, 60); - SetResistance(ResistanceType.Cold, 100); - SetResistance(ResistanceType.Poison, 90); - SetResistance(ResistanceType.Energy, 75); + SetResistance(ResistanceType.Physical, 60); + SetResistance(ResistanceType.Fire, 60); + SetResistance(ResistanceType.Cold, 100); + SetResistance(ResistanceType.Poison, 90); + SetResistance(ResistanceType.Energy, 75); - SetSkill(SkillName.DetectHidden, 80.0); - SetSkill(SkillName.EvalInt, 118.1, 120.0); - SetSkill(SkillName.Magery, 112.6, 120.0); - SetSkill(SkillName.Meditation, 150.0); - SetSkill(SkillName.Poisoning, 120.0); - SetSkill(SkillName.MagicResist, 90.1, 90.9); - SetSkill(SkillName.Tactics, 100.0); - SetSkill(SkillName.Wrestling, 90.1, 90.9); - SetSkill(SkillName.Necromancy, 120.1, 130.0); - SetSkill(SkillName.SpiritSpeak, 120.1, 130.0); + SetSkill(SkillName.DetectHidden, 80.0); + SetSkill(SkillName.EvalInt, 118.1, 120.0); + SetSkill(SkillName.Magery, 112.6, 120.0); + SetSkill(SkillName.Meditation, 150.0); + SetSkill(SkillName.Poisoning, 120.0); + SetSkill(SkillName.MagicResist, 90.1, 90.9); + SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.Wrestling, 90.1, 90.9); + SetSkill(SkillName.Necromancy, 120.1, 130.0); + SetSkill(SkillName.SpiritSpeak, 120.1, 130.0); - Fame = 22000; - Karma = -22000; + Fame = 22000; + Karma = -22000; - VirtualArmor = 34; + VirtualArmor = 34; + } + + public DarknightCreeper(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a darknight creeper corpse"; + public override bool IgnoreYoungProtection => Core.ML; + + public override bool BardImmune => !Core.SE; + public override bool Unprovokable => Core.SE; + public override bool AreaPeaceImmune => Core.SE; + public override bool BleedImmune => true; + public override Poison PoisonImmune => Poison.Lethal; + public override Poison HitPoison => Poison.Lethal; + + public override int TreasureMapLevel => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 2); + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + if (!Summoned && !NoKillAwards && DemonKnight.CheckArtifactChance(this)) + DemonKnight.DistributeArtifact(this); + } + + 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 (BaseSoundID == 471) + BaseSoundID = 0xE0; + } } - - public DarknightCreeper(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a darknight creeper corpse"; - public override bool IgnoreYoungProtection => Core.ML; - - public override bool BardImmune => !Core.SE; - public override bool Unprovokable => Core.SE; - public override bool AreaPeaceImmune => Core.SE; - public override bool BleedImmune => true; - public override Poison PoisonImmune => Poison.Lethal; - public override Poison HitPoison => Poison.Lethal; - - public override int TreasureMapLevel => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 2); - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - if (!Summoned && !NoKillAwards && DemonKnight.CheckArtifactChance(this)) - DemonKnight.DistributeArtifact(this); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (BaseSoundID == 471) - BaseSoundID = 0xE0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/AOS/DemonKnight.cs b/Projects/UOContent/Mobiles/Monsters/AOS/DemonKnight.cs index 493fa88ae..8843185f8 100644 --- a/Projects/UOContent/Mobiles/Monsters/AOS/DemonKnight.cs +++ b/Projects/UOContent/Mobiles/Monsters/AOS/DemonKnight.cs @@ -1,284 +1,284 @@ using System; -using System.Collections.Generic; using Server.Items; namespace Server.Mobiles { - public class DemonKnight : BaseCreature - { - private static bool m_InHere; - - [Constructible] - public DemonKnight() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class DemonKnight : BaseCreature { - Name = NameList.RandomName("demon knight"); - Title = "the Dark Father"; - Body = 318; - BaseSoundID = 0x165; + private static bool m_InHere; - SetStr(500); - SetDex(100); - SetInt(1000); - - SetHits(30000); - SetMana(5000); - - SetDamage(17, 21); - - SetDamageType(ResistanceType.Physical, 20); - SetDamageType(ResistanceType.Fire, 20); - SetDamageType(ResistanceType.Cold, 20); - SetDamageType(ResistanceType.Poison, 20); - SetDamageType(ResistanceType.Energy, 20); - - SetResistance(ResistanceType.Physical, 30); - SetResistance(ResistanceType.Fire, 30); - SetResistance(ResistanceType.Cold, 30); - SetResistance(ResistanceType.Poison, 30); - SetResistance(ResistanceType.Energy, 30); - - SetSkill(SkillName.Necromancy, 120, 120.0); - SetSkill(SkillName.SpiritSpeak, 120.0, 120.0); - - SetSkill(SkillName.DetectHidden, 80.0); - SetSkill(SkillName.EvalInt, 100.0); - SetSkill(SkillName.Magery, 100.0); - SetSkill(SkillName.Meditation, 120.0); - SetSkill(SkillName.MagicResist, 150.0); - SetSkill(SkillName.Tactics, 100.0); - SetSkill(SkillName.Wrestling, 120.0); - - Fame = 28000; - Karma = -28000; - - VirtualArmor = 64; - } - - public DemonKnight(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a demon knight corpse"; - public override bool IgnoreYoungProtection => Core.ML; - - public static Type[] ArtifactRarity10 { get; } = - { - typeof(LegacyOfTheDreadLord), - typeof(TheTaskmaster) - }; - - public static Type[] ArtifactRarity11 { get; } = - { - typeof(TheDragonSlayer), - typeof(ArmorOfFortune), - typeof(GauntletsOfNobility), - typeof(HelmOfInsight), - typeof(HolyKnightsBreastplate), - typeof(JackalsCollar), - typeof(LeggingsOfBane), - typeof(MidnightBracers), - typeof(OrnateCrownOfTheHarrower), - typeof(ShadowDancerLeggings), - typeof(TunicOfFire), - typeof(VoiceOfTheFallenKing), - typeof(BraceletOfHealth), - typeof(OrnamentOfTheMagician), - typeof(RingOfTheElements), - typeof(RingOfTheVile), - typeof(Aegis), - typeof(ArcaneShield), - typeof(AxeOfTheHeavens), - typeof(BladeOfInsanity), - typeof(BoneCrusher), - typeof(BreathOfTheDead), - typeof(Frostbringer), - typeof(SerpentsFang), - typeof(StaffOfTheMagi), - typeof(TheBeserkersMaul), - typeof(TheDryadBow), - typeof(DivineCountenance), - typeof(HatOfTheMagi), - typeof(HuntersHeaddress), - typeof(SpiritOfTheTotem) - }; - - public override bool BardImmune => !Core.SE; - public override bool Unprovokable => Core.SE; - public override bool AreaPeaceImmune => Core.SE; - public override Poison PoisonImmune => Poison.Lethal; - - public override int TreasureMapLevel => 1; - - public static Item CreateRandomArtifact() - { - if (!Core.AOS) - return null; - - int count = ArtifactRarity10.Length * 5 + ArtifactRarity11.Length * 4; - int random = Utility.Random(count); - Type type; - - if (random < ArtifactRarity10.Length * 5) - { - type = ArtifactRarity10[random / 5]; - } - else - { - random -= ArtifactRarity10.Length * 5; - type = ArtifactRarity11[random / 4]; - } - - return Loot.Construct(type); - } - - public static Mobile FindRandomPlayer(BaseCreature creature) - { - List rights = GetLootingRights(creature.DamageEntries, creature.HitsMax); - - for (int i = rights.Count - 1; i >= 0; --i) - { - DamageStore ds = rights[i]; - - if (!ds.m_HasRight) - rights.RemoveAt(i); - } - - return rights.RandomElement()?.m_Mobile; - } - - public static void DistributeArtifact(BaseCreature creature) - { - DistributeArtifact(creature, CreateRandomArtifact()); - } - - public static void DistributeArtifact(BaseCreature creature, Item artifact) - { - DistributeArtifact(FindRandomPlayer(creature), artifact); - } - - public static void DistributeArtifact(Mobile to) - { - DistributeArtifact(to, CreateRandomArtifact()); - } - - public static void DistributeArtifact(Mobile to, Item artifact) - { - if (to == null || artifact == null) - return; - - Container pack = to.Backpack; - - if (pack?.TryDropItem(to, artifact, false) != true) - to.BankBox.DropItem(artifact); - - to.SendLocalizedMessage( - 1062317); // For your valor in combating the fallen beast, a special artifact has been bestowed on you. - } - - public static int GetArtifactChance(Mobile boss) - { - if (!Core.AOS) - return 0; - - int luck = LootPack.GetLuckChanceForKiller(boss); - int chance; - - if (boss is DemonKnight) - chance = 1500 + luck / 5; - else - chance = 750 + luck / 10; - - return chance; - } - - public static bool CheckArtifactChance(Mobile boss) => GetArtifactChance(boss) > Utility.Random(100000); - - public override WeaponAbility GetWeaponAbility() - { - return Utility.Random(3) switch - { - 0 => WeaponAbility.DoubleStrike, - 1 => WeaponAbility.WhirlwindAttack, - 2 => WeaponAbility.CrushingBlow, - _ => WeaponAbility.DoubleStrike - }; - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - if (!Summoned && !NoKillAwards && CheckArtifactChance(this)) - DistributeArtifact(this); - } - - public override void GenerateLoot() - { - AddLoot(LootPack.SuperBoss, 2); - AddLoot(LootPack.HighScrolls, Utility.RandomMinMax(6, 60)); - } - - public override void OnDamage(int amount, Mobile from, bool willKill) - { - if (from != null && from != this && !m_InHere) - { - m_InHere = true; - AOS.Damage(from, this, Utility.RandomMinMax(8, 20), 100, 0, 0, 0, 0); - - MovingEffect(from, 0xECA, 10, 0, false, false, 0, 0); - PlaySound(0x491); - - if (Utility.RandomDouble() < 0.05) - Timer.DelayCall(TimeSpan.FromSeconds(1.0), CreateBones_Callback, from); - - m_InHere = false; - } - } - - public virtual void CreateBones_Callback(Mobile from) - { - Map map = from.Map; - - if (map == null) - return; - - int count = Utility.RandomMinMax(1, 3); - - for (int i = 0; i < count; ++i) - { - int x = from.X + Utility.RandomMinMax(-1, 1); - int y = from.Y + Utility.RandomMinMax(-1, 1); - int z = from.Z; - - if (!map.CanFit(x, y, z, 16)) + [Constructible] + public DemonKnight() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) { - z = map.GetAverageZ(x, y); + Name = NameList.RandomName("demon knight"); + Title = "the Dark Father"; + Body = 318; + BaseSoundID = 0x165; - if (z == from.Z || !map.CanFit(x, y, z, 16)) - continue; + SetStr(500); + SetDex(100); + SetInt(1000); + + SetHits(30000); + SetMana(5000); + + SetDamage(17, 21); + + SetDamageType(ResistanceType.Physical, 20); + SetDamageType(ResistanceType.Fire, 20); + SetDamageType(ResistanceType.Cold, 20); + SetDamageType(ResistanceType.Poison, 20); + SetDamageType(ResistanceType.Energy, 20); + + SetResistance(ResistanceType.Physical, 30); + SetResistance(ResistanceType.Fire, 30); + SetResistance(ResistanceType.Cold, 30); + SetResistance(ResistanceType.Poison, 30); + SetResistance(ResistanceType.Energy, 30); + + SetSkill(SkillName.Necromancy, 120, 120.0); + SetSkill(SkillName.SpiritSpeak, 120.0, 120.0); + + SetSkill(SkillName.DetectHidden, 80.0); + SetSkill(SkillName.EvalInt, 100.0); + SetSkill(SkillName.Magery, 100.0); + SetSkill(SkillName.Meditation, 120.0); + SetSkill(SkillName.MagicResist, 150.0); + SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.Wrestling, 120.0); + + Fame = 28000; + Karma = -28000; + + VirtualArmor = 64; } - UnholyBone bone = new UnholyBone + public DemonKnight(Serial serial) : base(serial) { - Hue = 0, - Name = "unholy bones", - ItemID = Utility.Random(0xECA, 9) + } + + public override string CorpseName => "a demon knight corpse"; + public override bool IgnoreYoungProtection => Core.ML; + + public static Type[] ArtifactRarity10 { get; } = + { + typeof(LegacyOfTheDreadLord), + typeof(TheTaskmaster) }; - bone.MoveToWorld(new Point3D(x, y, z), map); - } - } + public static Type[] ArtifactRarity11 { get; } = + { + typeof(TheDragonSlayer), + typeof(ArmorOfFortune), + typeof(GauntletsOfNobility), + typeof(HelmOfInsight), + typeof(HolyKnightsBreastplate), + typeof(JackalsCollar), + typeof(LeggingsOfBane), + typeof(MidnightBracers), + typeof(OrnateCrownOfTheHarrower), + typeof(ShadowDancerLeggings), + typeof(TunicOfFire), + typeof(VoiceOfTheFallenKing), + typeof(BraceletOfHealth), + typeof(OrnamentOfTheMagician), + typeof(RingOfTheElements), + typeof(RingOfTheVile), + typeof(Aegis), + typeof(ArcaneShield), + typeof(AxeOfTheHeavens), + typeof(BladeOfInsanity), + typeof(BoneCrusher), + typeof(BreathOfTheDead), + typeof(Frostbringer), + typeof(SerpentsFang), + typeof(StaffOfTheMagi), + typeof(TheBeserkersMaul), + typeof(TheDryadBow), + typeof(DivineCountenance), + typeof(HatOfTheMagi), + typeof(HuntersHeaddress), + typeof(SpiritOfTheTotem) + }; - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } + public override bool BardImmune => !Core.SE; + public override bool Unprovokable => Core.SE; + public override bool AreaPeaceImmune => Core.SE; + public override Poison PoisonImmune => Poison.Lethal; - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); + public override int TreasureMapLevel => 1; + + public static Item CreateRandomArtifact() + { + if (!Core.AOS) + return null; + + var count = ArtifactRarity10.Length * 5 + ArtifactRarity11.Length * 4; + var random = Utility.Random(count); + Type type; + + if (random < ArtifactRarity10.Length * 5) + { + type = ArtifactRarity10[random / 5]; + } + else + { + random -= ArtifactRarity10.Length * 5; + type = ArtifactRarity11[random / 4]; + } + + return Loot.Construct(type); + } + + public static Mobile FindRandomPlayer(BaseCreature creature) + { + var rights = GetLootingRights(creature.DamageEntries, creature.HitsMax); + + for (var i = rights.Count - 1; i >= 0; --i) + { + var ds = rights[i]; + + if (!ds.m_HasRight) + rights.RemoveAt(i); + } + + return rights.RandomElement()?.m_Mobile; + } + + public static void DistributeArtifact(BaseCreature creature) + { + DistributeArtifact(creature, CreateRandomArtifact()); + } + + public static void DistributeArtifact(BaseCreature creature, Item artifact) + { + DistributeArtifact(FindRandomPlayer(creature), artifact); + } + + public static void DistributeArtifact(Mobile to) + { + DistributeArtifact(to, CreateRandomArtifact()); + } + + public static void DistributeArtifact(Mobile to, Item artifact) + { + if (to == null || artifact == null) + return; + + var pack = to.Backpack; + + if (pack?.TryDropItem(to, artifact, false) != true) + to.BankBox.DropItem(artifact); + + to.SendLocalizedMessage( + 1062317 + ); // For your valor in combating the fallen beast, a special artifact has been bestowed on you. + } + + public static int GetArtifactChance(Mobile boss) + { + if (!Core.AOS) + return 0; + + var luck = LootPack.GetLuckChanceForKiller(boss); + int chance; + + if (boss is DemonKnight) + chance = 1500 + luck / 5; + else + chance = 750 + luck / 10; + + return chance; + } + + public static bool CheckArtifactChance(Mobile boss) => GetArtifactChance(boss) > Utility.Random(100000); + + public override WeaponAbility GetWeaponAbility() + { + return Utility.Random(3) switch + { + 0 => WeaponAbility.DoubleStrike, + 1 => WeaponAbility.WhirlwindAttack, + 2 => WeaponAbility.CrushingBlow, + _ => WeaponAbility.DoubleStrike + }; + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + if (!Summoned && !NoKillAwards && CheckArtifactChance(this)) + DistributeArtifact(this); + } + + public override void GenerateLoot() + { + AddLoot(LootPack.SuperBoss, 2); + AddLoot(LootPack.HighScrolls, Utility.RandomMinMax(6, 60)); + } + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + if (from != null && from != this && !m_InHere) + { + m_InHere = true; + AOS.Damage(from, this, Utility.RandomMinMax(8, 20), 100, 0, 0, 0, 0); + + MovingEffect(from, 0xECA, 10, 0, false, false, 0, 0); + PlaySound(0x491); + + if (Utility.RandomDouble() < 0.05) + Timer.DelayCall(TimeSpan.FromSeconds(1.0), CreateBones_Callback, from); + + m_InHere = false; + } + } + + public virtual void CreateBones_Callback(Mobile from) + { + var map = from.Map; + + if (map == null) + return; + + var count = Utility.RandomMinMax(1, 3); + + for (var i = 0; i < count; ++i) + { + var x = from.X + Utility.RandomMinMax(-1, 1); + var y = from.Y + Utility.RandomMinMax(-1, 1); + var z = from.Z; + + if (!map.CanFit(x, y, z, 16)) + { + z = map.GetAverageZ(x, y); + + if (z == from.Z || !map.CanFit(x, y, z, 16)) + continue; + } + + var bone = new UnholyBone + { + Hue = 0, + Name = "unholy bones", + ItemID = Utility.Random(0xECA, 9) + }; + + bone.MoveToWorld(new Point3D(x, y, z), map); + } + } + + 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(); + } } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/AOS/Devourer.cs b/Projects/UOContent/Mobiles/Monsters/AOS/Devourer.cs index 6774b713a..6e8417836 100644 --- a/Projects/UOContent/Mobiles/Monsters/AOS/Devourer.cs +++ b/Projects/UOContent/Mobiles/Monsters/AOS/Devourer.cs @@ -1,72 +1,72 @@ namespace Server.Mobiles { - public class Devourer : BaseCreature - { - [Constructible] - public Devourer() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Devourer : BaseCreature { - Body = 303; - BaseSoundID = 357; + [Constructible] + public Devourer() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 303; + BaseSoundID = 357; - SetStr(801, 950); - SetDex(126, 175); - SetInt(201, 250); + SetStr(801, 950); + SetDex(126, 175); + SetInt(201, 250); - SetHits(650); + SetHits(650); - SetDamage(22, 26); + SetDamage(22, 26); - SetDamageType(ResistanceType.Physical, 60); - SetDamageType(ResistanceType.Cold, 20); - SetDamageType(ResistanceType.Energy, 20); + SetDamageType(ResistanceType.Physical, 60); + SetDamageType(ResistanceType.Cold, 20); + SetDamageType(ResistanceType.Energy, 20); - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 25, 35); - SetResistance(ResistanceType.Cold, 15, 25); - SetResistance(ResistanceType.Poison, 60, 70); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 25, 35); + SetResistance(ResistanceType.Cold, 15, 25); + SetResistance(ResistanceType.Poison, 60, 70); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.EvalInt, 90.1, 100.0); - SetSkill(SkillName.Magery, 90.1, 100.0); - SetSkill(SkillName.Meditation, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 90.1, 105.0); - SetSkill(SkillName.Tactics, 75.1, 85.0); - SetSkill(SkillName.Wrestling, 80.1, 100.0); + SetSkill(SkillName.EvalInt, 90.1, 100.0); + SetSkill(SkillName.Magery, 90.1, 100.0); + SetSkill(SkillName.Meditation, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 90.1, 105.0); + SetSkill(SkillName.Tactics, 75.1, 85.0); + SetSkill(SkillName.Wrestling, 80.1, 100.0); - Fame = 9500; - Karma = -9500; + Fame = 9500; + Karma = -9500; - VirtualArmor = 44; + VirtualArmor = 44; - PackNecroReg(24, 45); + PackNecroReg(24, 45); + } + + public Devourer(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a devourer of souls corpse"; + public override string DefaultName => "a devourer of souls"; + + public override Poison PoisonImmune => Poison.Lethal; + + public override int Meat => 3; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 2); + } + + 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(); + } } - - public Devourer(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a devourer of souls corpse"; - public override string DefaultName => "a devourer of souls"; - - public override Poison PoisonImmune => Poison.Lethal; - - public override int Meat => 3; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/AOS/FleshGolem.cs b/Projects/UOContent/Mobiles/Monsters/AOS/FleshGolem.cs index 4bcd5e4e7..a4b26857b 100644 --- a/Projects/UOContent/Mobiles/Monsters/AOS/FleshGolem.cs +++ b/Projects/UOContent/Mobiles/Monsters/AOS/FleshGolem.cs @@ -2,68 +2,68 @@ using Server.Items; namespace Server.Mobiles { - public class FleshGolem : BaseCreature - { - [Constructible] - public FleshGolem() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class FleshGolem : BaseCreature { - Body = 304; - BaseSoundID = 684; + [Constructible] + public FleshGolem() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 304; + BaseSoundID = 684; - SetStr(176, 200); - SetDex(51, 75); - SetInt(46, 70); + SetStr(176, 200); + SetDex(51, 75); + SetInt(46, 70); - SetHits(106, 120); + SetHits(106, 120); - SetDamage(18, 22); + SetDamage(18, 22); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 50, 60); - SetResistance(ResistanceType.Fire, 25, 35); - SetResistance(ResistanceType.Cold, 15, 25); - SetResistance(ResistanceType.Poison, 60, 70); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 50, 60); + SetResistance(ResistanceType.Fire, 25, 35); + SetResistance(ResistanceType.Cold, 15, 25); + SetResistance(ResistanceType.Poison, 60, 70); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.MagicResist, 50.1, 75.0); - SetSkill(SkillName.Tactics, 55.1, 80.0); - SetSkill(SkillName.Wrestling, 60.1, 70.0); + SetSkill(SkillName.MagicResist, 50.1, 75.0); + SetSkill(SkillName.Tactics, 55.1, 80.0); + SetSkill(SkillName.Wrestling, 60.1, 70.0); - Fame = 1000; - Karma = -1800; + Fame = 1000; + Karma = -1800; - VirtualArmor = 34; + VirtualArmor = 34; + } + + public FleshGolem(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a flesh golem corpse"; + + public override string DefaultName => "a flesh golem"; + + public override bool BleedImmune => true; + public override int TreasureMapLevel => 1; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.BleedAttack; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + } + + 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(); + } } - - public FleshGolem(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a flesh golem corpse"; - - public override string DefaultName => "a flesh golem"; - - public override bool BleedImmune => true; - public override int TreasureMapLevel => 1; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.BleedAttack; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/AOS/FleshRenderer.cs b/Projects/UOContent/Mobiles/Monsters/AOS/FleshRenderer.cs index 6a8754eb8..f8fb17a72 100644 --- a/Projects/UOContent/Mobiles/Monsters/AOS/FleshRenderer.cs +++ b/Projects/UOContent/Mobiles/Monsters/AOS/FleshRenderer.cs @@ -2,98 +2,99 @@ using Server.Items; namespace Server.Mobiles { - public class FleshRenderer : BaseCreature - { - [Constructible] - public FleshRenderer() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class FleshRenderer : BaseCreature { - Body = 315; + [Constructible] + public FleshRenderer() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 315; - SetStr(401, 460); - SetDex(201, 210); - SetInt(221, 260); + SetStr(401, 460); + SetDex(201, 210); + SetInt(221, 260); - SetHits(4500); + SetHits(4500); - SetDamage(16, 20); + SetDamage(16, 20); - SetDamageType(ResistanceType.Physical, 80); - SetDamageType(ResistanceType.Poison, 20); + SetDamageType(ResistanceType.Physical, 80); + SetDamageType(ResistanceType.Poison, 20); - SetResistance(ResistanceType.Physical, 80, 90); - SetResistance(ResistanceType.Fire, 50, 60); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 100); - SetResistance(ResistanceType.Energy, 70, 80); + SetResistance(ResistanceType.Physical, 80, 90); + SetResistance(ResistanceType.Fire, 50, 60); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 100); + SetResistance(ResistanceType.Energy, 70, 80); - SetSkill(SkillName.DetectHidden, 80.0); - SetSkill(SkillName.MagicResist, 155.1, 160.0); - SetSkill(SkillName.Meditation, 100.0); - SetSkill(SkillName.Tactics, 100.0); - SetSkill(SkillName.Wrestling, 90.1, 100.0); + SetSkill(SkillName.DetectHidden, 80.0); + SetSkill(SkillName.MagicResist, 155.1, 160.0); + SetSkill(SkillName.Meditation, 100.0); + SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.Wrestling, 90.1, 100.0); - Fame = 23000; - Karma = -23000; + Fame = 23000; + Karma = -23000; - VirtualArmor = 24; + VirtualArmor = 24; + } + + public FleshRenderer(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a fleshrenderer corpse"; + + public override bool IgnoreYoungProtection => Core.ML; + + public override string DefaultName => "a fleshrenderer"; + + public override bool AutoDispel => true; + public override bool BardImmune => !Core.SE; + public override bool Unprovokable => Core.SE; + public override bool AreaPeaceImmune => Core.SE; + public override Poison PoisonImmune => Poison.Lethal; + + public override int TreasureMapLevel => 1; + + public override WeaponAbility GetWeaponAbility() => + Utility.RandomBool() ? WeaponAbility.Dismount : WeaponAbility.ParalyzingBlow; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 2); + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + if (!Summoned && !NoKillAwards && DemonKnight.CheckArtifactChance(this)) + DemonKnight.DistributeArtifact(this); + } + + public override int GetAttackSound() => 0x34C; + + public override int GetHurtSound() => 0x354; + + public override int GetAngerSound() => 0x34C; + + public override int GetIdleSound() => 0x34C; + + public override int GetDeathSound() => 0x354; + + 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 (BaseSoundID == 660) + BaseSoundID = -1; + } } - - public FleshRenderer(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a fleshrenderer corpse"; - - public override bool IgnoreYoungProtection => Core.ML; - - public override string DefaultName => "a fleshrenderer"; - - public override bool AutoDispel => true; - public override bool BardImmune => !Core.SE; - public override bool Unprovokable => Core.SE; - public override bool AreaPeaceImmune => Core.SE; - public override Poison PoisonImmune => Poison.Lethal; - - public override int TreasureMapLevel => 1; - - public override WeaponAbility GetWeaponAbility() => Utility.RandomBool() ? WeaponAbility.Dismount : WeaponAbility.ParalyzingBlow; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 2); - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - if (!Summoned && !NoKillAwards && DemonKnight.CheckArtifactChance(this)) - DemonKnight.DistributeArtifact(this); - } - - public override int GetAttackSound() => 0x34C; - - public override int GetHurtSound() => 0x354; - - public override int GetAngerSound() => 0x34C; - - public override int GetIdleSound() => 0x34C; - - public override int GetDeathSound() => 0x354; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (BaseSoundID == 660) - BaseSoundID = -1; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/AOS/Gibberling.cs b/Projects/UOContent/Mobiles/Monsters/AOS/Gibberling.cs index 17b97e246..d870f5f6a 100644 --- a/Projects/UOContent/Mobiles/Monsters/AOS/Gibberling.cs +++ b/Projects/UOContent/Mobiles/Monsters/AOS/Gibberling.cs @@ -2,69 +2,69 @@ using Server.Items; namespace Server.Mobiles { - public class Gibberling : BaseCreature - { - [Constructible] - public Gibberling() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Gibberling : BaseCreature { - Body = 307; - BaseSoundID = 422; + [Constructible] + public Gibberling() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 307; + BaseSoundID = 422; - SetStr(141, 165); - SetDex(101, 125); - SetInt(56, 80); + SetStr(141, 165); + SetDex(101, 125); + SetInt(56, 80); - SetHits(85, 99); + SetHits(85, 99); - SetDamage(12, 17); + SetDamage(12, 17); - SetDamageType(ResistanceType.Physical, 0); - SetDamageType(ResistanceType.Fire, 40); - SetDamageType(ResistanceType.Energy, 60); + SetDamageType(ResistanceType.Physical, 0); + SetDamageType(ResistanceType.Fire, 40); + SetDamageType(ResistanceType.Energy, 60); - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 25, 35); - SetResistance(ResistanceType.Cold, 25, 35); - SetResistance(ResistanceType.Poison, 10, 20); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 25, 35); + SetResistance(ResistanceType.Cold, 25, 35); + SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.MagicResist, 45.1, 70.0); - SetSkill(SkillName.Tactics, 67.6, 92.5); - SetSkill(SkillName.Wrestling, 60.1, 80.0); + SetSkill(SkillName.MagicResist, 45.1, 70.0); + SetSkill(SkillName.Tactics, 67.6, 92.5); + SetSkill(SkillName.Wrestling, 60.1, 80.0); - Fame = 1500; - Karma = -1500; + Fame = 1500; + Karma = -1500; - VirtualArmor = 27; + VirtualArmor = 27; + } + + public Gibberling(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a gibberling corpse"; + + public override string DefaultName => "a gibberling"; + + public override int TreasureMapLevel => 1; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.Dismount; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + 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(); + } } - - public Gibberling(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a gibberling corpse"; - - public override string DefaultName => "a gibberling"; - - public override int TreasureMapLevel => 1; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.Dismount; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/AOS/GoreFiend.cs b/Projects/UOContent/Mobiles/Monsters/AOS/GoreFiend.cs index 57f7ad43c..ed3b5ccad 100644 --- a/Projects/UOContent/Mobiles/Monsters/AOS/GoreFiend.cs +++ b/Projects/UOContent/Mobiles/Monsters/AOS/GoreFiend.cs @@ -1,66 +1,66 @@ namespace Server.Mobiles { - public class GoreFiend : BaseCreature - { - [Constructible] - public GoreFiend() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class GoreFiend : BaseCreature { - Body = 305; - BaseSoundID = 224; + [Constructible] + public GoreFiend() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 305; + BaseSoundID = 224; - SetStr(161, 185); - SetDex(41, 65); - SetInt(46, 70); + SetStr(161, 185); + SetDex(41, 65); + SetInt(46, 70); - SetHits(97, 111); + SetHits(97, 111); - SetDamage(15, 21); + SetDamage(15, 21); - SetDamageType(ResistanceType.Physical, 85); - SetDamageType(ResistanceType.Poison, 15); + SetDamageType(ResistanceType.Physical, 85); + SetDamageType(ResistanceType.Poison, 15); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 25, 35); - SetResistance(ResistanceType.Cold, 15, 25); - SetResistance(ResistanceType.Poison, 5, 15); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 25, 35); + SetResistance(ResistanceType.Cold, 15, 25); + SetResistance(ResistanceType.Poison, 5, 15); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.MagicResist, 40.1, 55.0); - SetSkill(SkillName.Tactics, 45.1, 70.0); - SetSkill(SkillName.Wrestling, 50.1, 70.0); + SetSkill(SkillName.MagicResist, 40.1, 55.0); + SetSkill(SkillName.Tactics, 45.1, 70.0); + SetSkill(SkillName.Wrestling, 50.1, 70.0); - Fame = 1500; - Karma = -1500; + Fame = 1500; + Karma = -1500; - VirtualArmor = 24; + VirtualArmor = 24; + } + + public GoreFiend(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a gore fiend corpse"; + public override string DefaultName => "a gore fiend"; + + public override bool BleedImmune => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + } + + public override int GetDeathSound() => 1218; + + 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(); + } } - - public GoreFiend(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a gore fiend corpse"; - public override string DefaultName => "a gore fiend"; - - public override bool BleedImmune => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - } - - public override int GetDeathSound() => 1218; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/AOS/Impaler.cs b/Projects/UOContent/Mobiles/Monsters/AOS/Impaler.cs index 0bdc6213d..7c09d3858 100644 --- a/Projects/UOContent/Mobiles/Monsters/AOS/Impaler.cs +++ b/Projects/UOContent/Mobiles/Monsters/AOS/Impaler.cs @@ -2,89 +2,90 @@ using Server.Items; namespace Server.Mobiles { - public class Impaler : BaseCreature - { - [Constructible] - public Impaler() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Impaler : BaseCreature { - Name = NameList.RandomName("impaler"); - Body = 306; - BaseSoundID = 0x2A7; + [Constructible] + public Impaler() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Name = NameList.RandomName("impaler"); + Body = 306; + BaseSoundID = 0x2A7; - SetStr(190); - SetDex(45); - SetInt(190); + SetStr(190); + SetDex(45); + SetInt(190); - SetHits(5000); + SetHits(5000); - SetDamage(31, 35); + SetDamage(31, 35); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 90); - SetResistance(ResistanceType.Fire, 60); - SetResistance(ResistanceType.Cold, 75); - SetResistance(ResistanceType.Poison, 60); - SetResistance(ResistanceType.Energy, 100); + SetResistance(ResistanceType.Physical, 90); + SetResistance(ResistanceType.Fire, 60); + SetResistance(ResistanceType.Cold, 75); + SetResistance(ResistanceType.Poison, 60); + SetResistance(ResistanceType.Energy, 100); - SetSkill(SkillName.DetectHidden, 80.0); - SetSkill(SkillName.Meditation, 120.0); - SetSkill(SkillName.Poisoning, 160.0); - SetSkill(SkillName.MagicResist, 100.0); - SetSkill(SkillName.Tactics, 100.0); - SetSkill(SkillName.Wrestling, 80.0); + SetSkill(SkillName.DetectHidden, 80.0); + SetSkill(SkillName.Meditation, 120.0); + SetSkill(SkillName.Poisoning, 160.0); + SetSkill(SkillName.MagicResist, 100.0); + SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.Wrestling, 80.0); - Fame = 24000; - Karma = -24000; + Fame = 24000; + Karma = -24000; - VirtualArmor = 49; + VirtualArmor = 49; + } + + public Impaler(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an impaler corpse"; + + public override bool IgnoreYoungProtection => Core.ML; + + public override bool AutoDispel => true; + public override bool BardImmune => !Core.SE; + public override bool Unprovokable => Core.SE; + public override bool AreaPeaceImmune => Core.SE; + public override Poison PoisonImmune => Poison.Lethal; + public override Poison HitPoison => Utility.RandomDouble() <= 0.8 ? Poison.Greater : Poison.Deadly; + + public override int TreasureMapLevel => 1; + + public override WeaponAbility GetWeaponAbility() => + Utility.RandomBool() ? WeaponAbility.MortalStrike : WeaponAbility.BleedAttack; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 2); + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + if (!Summoned && !NoKillAwards && DemonKnight.CheckArtifactChance(this)) + DemonKnight.DistributeArtifact(this); + } + + 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 (BaseSoundID == 1200) + BaseSoundID = 0x2A7; + } } - - public Impaler(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an impaler corpse"; - - public override bool IgnoreYoungProtection => Core.ML; - - public override bool AutoDispel => true; - public override bool BardImmune => !Core.SE; - public override bool Unprovokable => Core.SE; - public override bool AreaPeaceImmune => Core.SE; - public override Poison PoisonImmune => Poison.Lethal; - public override Poison HitPoison => Utility.RandomDouble() <= 0.8 ? Poison.Greater : Poison.Deadly; - - public override int TreasureMapLevel => 1; - - public override WeaponAbility GetWeaponAbility() => Utility.RandomBool() ? WeaponAbility.MortalStrike : WeaponAbility.BleedAttack; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 2); - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - if (!Summoned && !NoKillAwards && DemonKnight.CheckArtifactChance(this)) - DemonKnight.DistributeArtifact(this); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (BaseSoundID == 1200) - BaseSoundID = 0x2A7; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/AOS/MoundOfMaggots.cs b/Projects/UOContent/Mobiles/Monsters/AOS/MoundOfMaggots.cs index 216f4bda0..84176bbd2 100644 --- a/Projects/UOContent/Mobiles/Monsters/AOS/MoundOfMaggots.cs +++ b/Projects/UOContent/Mobiles/Monsters/AOS/MoundOfMaggots.cs @@ -1,63 +1,63 @@ namespace Server.Mobiles { - public class MoundOfMaggots : BaseCreature - { - [Constructible] - public MoundOfMaggots() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class MoundOfMaggots : BaseCreature { - Body = 319; - BaseSoundID = 898; + [Constructible] + public MoundOfMaggots() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 319; + BaseSoundID = 898; - SetStr(61, 70); - SetDex(61, 70); - SetInt(10); + SetStr(61, 70); + SetDex(61, 70); + SetInt(10); - SetMana(0); + SetMana(0); - SetDamage(3, 9); + SetDamage(3, 9); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Poison, 50); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Poison, 50); - SetResistance(ResistanceType.Physical, 90); - SetResistance(ResistanceType.Poison, 100); + SetResistance(ResistanceType.Physical, 90); + SetResistance(ResistanceType.Poison, 100); - SetSkill(SkillName.Tactics, 50.0); - SetSkill(SkillName.Wrestling, 50.1, 60.0); + SetSkill(SkillName.Tactics, 50.0); + SetSkill(SkillName.Wrestling, 50.1, 60.0); - Fame = 1000; - Karma = -1000; + Fame = 1000; + Karma = -1000; - VirtualArmor = 24; + VirtualArmor = 24; + } + + public MoundOfMaggots(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a maggoty corpse"; + public override string DefaultName => "a mound of maggots"; + + public override Poison PoisonImmune => Poison.Lethal; + + public override int TreasureMapLevel => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + AddLoot(LootPack.Gems); + } + + 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(); + } } - - public MoundOfMaggots(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a maggoty corpse"; - public override string DefaultName => "a mound of maggots"; - - public override Poison PoisonImmune => Poison.Lethal; - - public override int TreasureMapLevel => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - AddLoot(LootPack.Gems); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/AOS/PatchworkSkeleton.cs b/Projects/UOContent/Mobiles/Monsters/AOS/PatchworkSkeleton.cs index 86fb6bb84..3de36c43b 100644 --- a/Projects/UOContent/Mobiles/Monsters/AOS/PatchworkSkeleton.cs +++ b/Projects/UOContent/Mobiles/Monsters/AOS/PatchworkSkeleton.cs @@ -2,71 +2,71 @@ using Server.Items; namespace Server.Mobiles { - public class PatchworkSkeleton : BaseCreature - { - [Constructible] - public PatchworkSkeleton() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class PatchworkSkeleton : BaseCreature { - Body = 309; - BaseSoundID = 0x48D; + [Constructible] + public PatchworkSkeleton() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 309; + BaseSoundID = 0x48D; - SetStr(96, 120); - SetDex(71, 95); - SetInt(16, 40); + SetStr(96, 120); + SetDex(71, 95); + SetInt(16, 40); - SetHits(58, 72); + SetHits(58, 72); - SetDamage(18, 22); + SetDamage(18, 22); - SetDamageType(ResistanceType.Physical, 85); - SetDamageType(ResistanceType.Cold, 15); + SetDamageType(ResistanceType.Physical, 85); + SetDamageType(ResistanceType.Cold, 15); - SetResistance(ResistanceType.Physical, 55, 65); - SetResistance(ResistanceType.Fire, 50, 60); - SetResistance(ResistanceType.Cold, 70, 80); - SetResistance(ResistanceType.Poison, 100); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 55, 65); + SetResistance(ResistanceType.Fire, 50, 60); + SetResistance(ResistanceType.Cold, 70, 80); + SetResistance(ResistanceType.Poison, 100); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.MagicResist, 70.1, 95.0); - SetSkill(SkillName.Tactics, 55.1, 80.0); - SetSkill(SkillName.Wrestling, 50.1, 70.0); + SetSkill(SkillName.MagicResist, 70.1, 95.0); + SetSkill(SkillName.Tactics, 55.1, 80.0); + SetSkill(SkillName.Wrestling, 50.1, 70.0); - Fame = 500; - Karma = -500; + Fame = 500; + Karma = -500; - VirtualArmor = 54; + VirtualArmor = 54; + } + + public PatchworkSkeleton(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a patchwork skeletal corpse"; + + public override string DefaultName => "a patchwork skeleton"; + + public override bool BleedImmune => true; + public override Poison PoisonImmune => Poison.Lethal; + + public override int TreasureMapLevel => 1; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.Dismount; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + 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(); + } } - - public PatchworkSkeleton(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a patchwork skeletal corpse"; - - public override string DefaultName => "a patchwork skeleton"; - - public override bool BleedImmune => true; - public override Poison PoisonImmune => Poison.Lethal; - - public override int TreasureMapLevel => 1; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.Dismount; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/AOS/Ravager.cs b/Projects/UOContent/Mobiles/Monsters/AOS/Ravager.cs index 81281031c..6e770b6f6 100644 --- a/Projects/UOContent/Mobiles/Monsters/AOS/Ravager.cs +++ b/Projects/UOContent/Mobiles/Monsters/AOS/Ravager.cs @@ -2,65 +2,66 @@ using Server.Items; namespace Server.Mobiles { - public class Ravager : BaseCreature - { - [Constructible] - public Ravager() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Ravager : BaseCreature { - Body = 314; - BaseSoundID = 357; + [Constructible] + public Ravager() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 314; + BaseSoundID = 357; - SetStr(251, 275); - SetDex(101, 125); - SetInt(66, 90); + SetStr(251, 275); + SetDex(101, 125); + SetInt(66, 90); - SetHits(161, 175); + SetHits(161, 175); - SetDamage(15, 20); + SetDamage(15, 20); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 50, 60); - SetResistance(ResistanceType.Fire, 50, 60); - SetResistance(ResistanceType.Cold, 60, 70); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 20, 30); + SetResistance(ResistanceType.Physical, 50, 60); + SetResistance(ResistanceType.Fire, 50, 60); + SetResistance(ResistanceType.Cold, 60, 70); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 20, 30); - SetSkill(SkillName.MagicResist, 50.1, 75.0); - SetSkill(SkillName.Tactics, 75.1, 100.0); - SetSkill(SkillName.Wrestling, 70.1, 90.0); + SetSkill(SkillName.MagicResist, 50.1, 75.0); + SetSkill(SkillName.Tactics, 75.1, 100.0); + SetSkill(SkillName.Wrestling, 70.1, 90.0); - Fame = 3500; - Karma = -3500; + Fame = 3500; + Karma = -3500; - VirtualArmor = 54; + VirtualArmor = 54; + } + + public Ravager(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a ravager corpse"; + + public override string DefaultName => "a ravager"; + + public override WeaponAbility GetWeaponAbility() => + Utility.RandomBool() ? WeaponAbility.Dismount : WeaponAbility.CrushingBlow; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + } + + 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(); + } } - - public Ravager(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a ravager corpse"; - - public override string DefaultName => "a ravager"; - - public override WeaponAbility GetWeaponAbility() => Utility.RandomBool() ? WeaponAbility.Dismount : WeaponAbility.CrushingBlow; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/AOS/Revenant.cs b/Projects/UOContent/Mobiles/Monsters/AOS/Revenant.cs index 1b0e02e1f..9aef148d8 100644 --- a/Projects/UOContent/Mobiles/Monsters/AOS/Revenant.cs +++ b/Projects/UOContent/Mobiles/Monsters/AOS/Revenant.cs @@ -1,172 +1,195 @@ using System; using Server.Items; -using Server.Targeting; namespace Server.Mobiles { - public class Revenant : BaseCreature - { - private readonly DateTime m_ExpireTime; - private readonly Mobile m_Target; - - public Revenant(Mobile caster, Mobile target, TimeSpan duration) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, - 0.18, 0.36) + public class Revenant : BaseCreature { - Body = 400; - Hue = 1; - // TODO: Sound values? + private readonly DateTime m_ExpireTime; + private readonly Mobile m_Target; - double scalar = caster.Skills.SpiritSpeak.Value * 0.01; + public Revenant(Mobile caster, Mobile target, TimeSpan duration) : base( + AIType.AI_Melee, + FightMode.Closest, + 10, + 1, + 0.18, + 0.36 + ) + { + Body = 400; + Hue = 1; + // TODO: Sound values? - m_Target = target; - m_ExpireTime = DateTime.UtcNow + duration; + var scalar = caster.Skills.SpiritSpeak.Value * 0.01; - SetStr(200); - SetDex(150); - SetInt(150); + m_Target = target; + m_ExpireTime = DateTime.UtcNow + duration; - SetDamage(16, 17); + SetStr(200); + SetDex(150); + SetInt(150); - // Bestiary says 50 phys 50 cold, animal lore says differently - SetDamageType(ResistanceType.Physical, 100); + SetDamage(16, 17); - SetSkill(SkillName.MagicResist, 100.0 * scalar); // magic resist is absolute value of spiritspeak - SetSkill(SkillName.Tactics, 100.0); // always 100 - SetSkill(SkillName.Swords, - 100.0 * scalar); // not displayed in animal lore but tests clearly show this is influenced - SetSkill(SkillName.DetectHidden, 75.0 * scalar); + // Bestiary says 50 phys 50 cold, animal lore says differently + SetDamageType(ResistanceType.Physical, 100); - scalar /= 1.2; + SetSkill(SkillName.MagicResist, 100.0 * scalar); // magic resist is absolute value of spiritspeak + SetSkill(SkillName.Tactics, 100.0); // always 100 + SetSkill( + SkillName.Swords, + 100.0 * scalar + ); // not displayed in animal lore but tests clearly show this is influenced + SetSkill(SkillName.DetectHidden, 75.0 * scalar); - SetResistance(ResistanceType.Physical, 40 + (int)(20 * scalar), 50 + (int)(20 * scalar)); - SetResistance(ResistanceType.Cold, 40 + (int)(20 * scalar), 50 + (int)(20 * scalar)); - SetResistance(ResistanceType.Fire, (int)(20 * scalar)); - SetResistance(ResistanceType.Poison, 100); - SetResistance(ResistanceType.Energy, 40 + (int)(20 * scalar), 50 + (int)(20 * scalar)); + scalar /= 1.2; - Fame = 0; - Karma = 0; + SetResistance(ResistanceType.Physical, 40 + (int)(20 * scalar), 50 + (int)(20 * scalar)); + SetResistance(ResistanceType.Cold, 40 + (int)(20 * scalar), 50 + (int)(20 * scalar)); + SetResistance(ResistanceType.Fire, (int)(20 * scalar)); + SetResistance(ResistanceType.Poison, 100); + SetResistance(ResistanceType.Energy, 40 + (int)(20 * scalar), 50 + (int)(20 * scalar)); - ControlSlots = 3; + Fame = 0; + Karma = 0; - VirtualArmor = 32; + ControlSlots = 3; - AddItem(new DeathShroud { Hue = 0x455, Movable = false }); - AddItem(new Halberd { Hue = 1, Movable = false }); - } + VirtualArmor = 32; - public Revenant(Serial serial) : base(serial) - { - } + AddItem(new DeathShroud { Hue = 0x455, Movable = false }); + AddItem(new Halberd { Hue = 1, Movable = false }); + } - public override Mobile ConstantFocus => m_Target; - public override bool NoHouseRestrictions => true; + public Revenant(Serial serial) : base(serial) + { + } - public override double DispelDifficulty => 80.0; - public override double DispelFocus => 20.0; + public override Mobile ConstantFocus => m_Target; + public override bool NoHouseRestrictions => true; - public override string DefaultName => "a revenant"; + public override double DispelDifficulty => 80.0; + public override double DispelFocus => 20.0; - public override bool AlwaysMurderer => true; + public override string DefaultName => "a revenant"; - public override bool BleedImmune => true; - public override bool BardImmune => true; - public override Poison PoisonImmune => Poison.Lethal; + public override bool AlwaysMurderer => true; - public override void DisplayPaperdollTo(Mobile to) - { - // Do nothing - } + public override bool BleedImmune => true; + public override bool BardImmune => true; + public override Poison PoisonImmune => Poison.Lethal; - public override void OnThink() - { - if (!m_Target.Alive || DateTime.UtcNow > m_ExpireTime) - { - Kill(); - return; - } + public override void DisplayPaperdollTo(Mobile to) + { + // Do nothing + } - if (Map != m_Target.Map || !InRange(m_Target, 15)) - { - Map fromMap = Map; - Point3D from = Location; - - Map toMap = m_Target.Map; - Point3D to = m_Target.Location; - - if (toMap != null) - for (int i = 0; i < 5; ++i) - { - Point3D loc = new Point3D(to.X - 4 + Utility.Random(9), to.Y - 4 + Utility.Random(9), to.Z); - - if (toMap.CanSpawnMobile(loc)) + public override void OnThink() + { + if (!m_Target.Alive || DateTime.UtcNow > m_ExpireTime) { - to = loc; - break; + Kill(); + return; } - loc.Z = toMap.GetAverageZ(loc.X, loc.Y); - - if (toMap.CanSpawnMobile(loc)) + if (Map != m_Target.Map || !InRange(m_Target, 15)) { - to = loc; - break; + var fromMap = Map; + var from = Location; + + var toMap = m_Target.Map; + var to = m_Target.Location; + + if (toMap != null) + for (var i = 0; i < 5; ++i) + { + var loc = new Point3D(to.X - 4 + Utility.Random(9), to.Y - 4 + Utility.Random(9), to.Z); + + if (toMap.CanSpawnMobile(loc)) + { + to = loc; + break; + } + + loc.Z = toMap.GetAverageZ(loc.X, loc.Y); + + if (toMap.CanSpawnMobile(loc)) + { + to = loc; + break; + } + } + + Map = toMap; + Location = to; + + ProcessDelta(); + + Effects.SendLocationParticles( + EffectItem.Create(from, fromMap, EffectItem.DefaultDuration), + 0x3728, + 1, + 13, + 37, + 7, + 5023, + 0 + ); + FixedParticles(0x3728, 1, 13, 5023, 37, 7, EffectLayer.Waist); + + PlaySound(0x37D); } - } - Map = toMap; - Location = to; + if (m_Target.Hidden && InRange(m_Target, 3) && Core.TickCount - NextSkillTime >= 0 && + UseSkill(SkillName.DetectHidden)) + { + var targ = Target; - ProcessDelta(); + targ?.Invoke(this, this); + } - Effects.SendLocationParticles(EffectItem.Create(from, fromMap, EffectItem.DefaultDuration), 0x3728, 1, 13, - 37, 7, 5023, 0); - FixedParticles(0x3728, 1, 13, 5023, 37, 7, EffectLayer.Waist); + Combatant = m_Target; + FocusMob = m_Target; - PlaySound(0x37D); - } + if (AIObject != null) + AIObject.Action = ActionType.Combat; - if (m_Target.Hidden && InRange(m_Target, 3) && Core.TickCount - NextSkillTime >= 0 && - UseSkill(SkillName.DetectHidden)) - { - Target targ = Target; + base.OnThink(); + } - targ?.Invoke(this, this); - } + public override bool OnBeforeDeath() + { + Effects.PlaySound(Location, Map, 0x10B); + Effects.SendLocationParticles( + EffectItem.Create(Location, Map, TimeSpan.FromSeconds(10.0)), + 0x37CC, + 1, + 50, + 2101, + 7, + 9909, + 0 + ); - Combatant = m_Target; - FocusMob = m_Target; + Delete(); + return false; + } - if (AIObject != null) - AIObject.Action = ActionType.Combat; + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - base.OnThink(); + writer.Write(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + Delete(); + } } - - public override bool OnBeforeDeath() - { - Effects.PlaySound(Location, Map, 0x10B); - Effects.SendLocationParticles(EffectItem.Create(Location, Map, TimeSpan.FromSeconds(10.0)), 0x37CC, 1, 50, 2101, - 7, 9909, 0); - - Delete(); - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Delete(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/AOS/ShadowKnight.cs b/Projects/UOContent/Mobiles/Monsters/AOS/ShadowKnight.cs index 38cc01839..73d66a551 100644 --- a/Projects/UOContent/Mobiles/Monsters/AOS/ShadowKnight.cs +++ b/Projects/UOContent/Mobiles/Monsters/AOS/ShadowKnight.cs @@ -3,176 +3,190 @@ using Server.Items; namespace Server.Mobiles { - public class ShadowKnight : BaseCreature - { - private bool m_HasTeleportedAway; - - private Timer m_SoundTimer; - - [Constructible] - public ShadowKnight() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class ShadowKnight : BaseCreature { - Name = NameList.RandomName("shadow knight"); - Title = "the Shadow Knight"; - Body = 311; + private bool m_HasTeleportedAway; - SetStr(250); - SetDex(100); - SetInt(100); + private Timer m_SoundTimer; - SetHits(2000); + [Constructible] + public ShadowKnight() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Name = NameList.RandomName("shadow knight"); + Title = "the Shadow Knight"; + Body = 311; - SetDamage(20, 30); + SetStr(250); + SetDex(100); + SetInt(100); - SetDamageType(ResistanceType.Physical, 60); - SetDamageType(ResistanceType.Cold, 40); + SetHits(2000); - SetResistance(ResistanceType.Physical, 90); - SetResistance(ResistanceType.Fire, 65); - SetResistance(ResistanceType.Cold, 75); - SetResistance(ResistanceType.Poison, 75); - SetResistance(ResistanceType.Energy, 55); + SetDamage(20, 30); - SetSkill(SkillName.Chivalry, 120.0); - SetSkill(SkillName.DetectHidden, 80.0); - SetSkill(SkillName.EvalInt, 100.0); - SetSkill(SkillName.Magery, 100.0); - SetSkill(SkillName.Meditation, 100.0); - SetSkill(SkillName.MagicResist, 120.0); - SetSkill(SkillName.Tactics, 100.0); - SetSkill(SkillName.Wrestling, 100.0); + SetDamageType(ResistanceType.Physical, 60); + SetDamageType(ResistanceType.Cold, 40); - Fame = 25000; - Karma = -25000; + SetResistance(ResistanceType.Physical, 90); + SetResistance(ResistanceType.Fire, 65); + SetResistance(ResistanceType.Cold, 75); + SetResistance(ResistanceType.Poison, 75); + SetResistance(ResistanceType.Energy, 55); - VirtualArmor = 54; + SetSkill(SkillName.Chivalry, 120.0); + SetSkill(SkillName.DetectHidden, 80.0); + SetSkill(SkillName.EvalInt, 100.0); + SetSkill(SkillName.Magery, 100.0); + SetSkill(SkillName.Meditation, 100.0); + SetSkill(SkillName.MagicResist, 120.0); + SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.Wrestling, 100.0); + + Fame = 25000; + Karma = -25000; + + VirtualArmor = 54; + } + + public ShadowKnight(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a shadow knight corpse"; + + public override bool IgnoreYoungProtection => Core.ML; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override bool BardImmune => !Core.SE; + public override bool Unprovokable => Core.SE; + public override bool AreaPeaceImmune => Core.SE; + public override Poison PoisonImmune => Poison.Lethal; + + public override int TreasureMapLevel => 1; + + public override WeaponAbility GetWeaponAbility() => + Utility.RandomBool() ? WeaponAbility.ConcussionBlow : WeaponAbility.CrushingBlow; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 2); + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + if (!Summoned && !NoKillAwards && DemonKnight.CheckArtifactChance(this)) + DemonKnight.DistributeArtifact(this); + } + + public override int GetIdleSound() => 0x2CE; + + public override int GetDeathSound() => 0x2C1; + + public override int GetHurtSound() => 0x2D1; + + public override int GetAttackSound() => 0x2C8; + + public override void OnCombatantChange() + { + base.OnCombatantChange(); + + if (Hidden && Combatant != null) + Combatant = null; + } + + public virtual void SendTrackingSound() + { + if (Hidden) + { + Effects.PlaySound(Location, Map, 0x2C8); + Combatant = null; + } + else + { + Frozen = false; + + m_SoundTimer?.Stop(); + + m_SoundTimer = null; + } + } + + public override void OnThink() + { + if (!m_HasTeleportedAway && Hits < HitsMax / 2) + { + var map = Map; + + if (map != null) + for (var i = 0; i < 10; ++i) + { + var x = X + Utility.RandomMinMax(5, 10) * (Utility.RandomBool() ? 1 : -1); + var y = Y + Utility.RandomMinMax(5, 10) * (Utility.RandomBool() ? 1 : -1); + var z = Z; + + if (!map.CanFit(x, y, z, 16, false, false)) + continue; + + var from = Location; + var to = new Point3D(x, y, z); + + if (!InLOS(to)) + continue; + + Location = to; + ProcessDelta(); + Hidden = true; + Combatant = null; + + Effects.SendLocationParticles( + EffectItem.Create(from, map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 2023 + ); + Effects.SendLocationParticles( + EffectItem.Create(to, map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 5023 + ); + + Effects.PlaySound(to, map, 0x1FE); + + m_HasTeleportedAway = true; + m_SoundTimer = Timer.DelayCall( + TimeSpan.FromSeconds(5.0), + TimeSpan.FromSeconds(2.5), + SendTrackingSound + ); + + Frozen = true; + + break; + } + } + + base.OnThink(); + } + + 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 (BaseSoundID == 357) + BaseSoundID = -1; + } } - - public ShadowKnight(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a shadow knight corpse"; - - public override bool IgnoreYoungProtection => Core.ML; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override bool BardImmune => !Core.SE; - public override bool Unprovokable => Core.SE; - public override bool AreaPeaceImmune => Core.SE; - public override Poison PoisonImmune => Poison.Lethal; - - public override int TreasureMapLevel => 1; - - public override WeaponAbility GetWeaponAbility() => Utility.RandomBool() ? WeaponAbility.ConcussionBlow : WeaponAbility.CrushingBlow; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 2); - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - if (!Summoned && !NoKillAwards && DemonKnight.CheckArtifactChance(this)) - DemonKnight.DistributeArtifact(this); - } - - public override int GetIdleSound() => 0x2CE; - - public override int GetDeathSound() => 0x2C1; - - public override int GetHurtSound() => 0x2D1; - - public override int GetAttackSound() => 0x2C8; - - public override void OnCombatantChange() - { - base.OnCombatantChange(); - - if (Hidden && Combatant != null) - Combatant = null; - } - - public virtual void SendTrackingSound() - { - if (Hidden) - { - Effects.PlaySound(Location, Map, 0x2C8); - Combatant = null; - } - else - { - Frozen = false; - - m_SoundTimer?.Stop(); - - m_SoundTimer = null; - } - } - - public override void OnThink() - { - if (!m_HasTeleportedAway && Hits < HitsMax / 2) - { - Map map = Map; - - if (map != null) - for (int i = 0; i < 10; ++i) - { - int x = X + Utility.RandomMinMax(5, 10) * (Utility.RandomBool() ? 1 : -1); - int y = Y + Utility.RandomMinMax(5, 10) * (Utility.RandomBool() ? 1 : -1); - int z = Z; - - if (!map.CanFit(x, y, z, 16, false, false)) - continue; - - Point3D from = Location; - Point3D to = new Point3D(x, y, z); - - if (!InLOS(to)) - continue; - - Location = to; - ProcessDelta(); - Hidden = true; - Combatant = null; - - Effects.SendLocationParticles(EffectItem.Create(from, map, EffectItem.DefaultDuration), 0x3728, 10, - 10, 2023); - Effects.SendLocationParticles(EffectItem.Create(to, map, EffectItem.DefaultDuration), 0x3728, 10, 10, - 5023); - - Effects.PlaySound(to, map, 0x1FE); - - m_HasTeleportedAway = true; - m_SoundTimer = Timer.DelayCall(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(2.5), - SendTrackingSound); - - Frozen = true; - - break; - } - } - - base.OnThink(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (BaseSoundID == 357) - BaseSoundID = -1; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/AOS/SkitteringHopper.cs b/Projects/UOContent/Mobiles/Monsters/AOS/SkitteringHopper.cs index beca3b74b..c88a3a9f2 100644 --- a/Projects/UOContent/Mobiles/Monsters/AOS/SkitteringHopper.cs +++ b/Projects/UOContent/Mobiles/Monsters/AOS/SkitteringHopper.cs @@ -1,65 +1,65 @@ namespace Server.Mobiles { - public class SkitteringHopper : BaseCreature - { - [Constructible] - public SkitteringHopper() : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class SkitteringHopper : BaseCreature { - Body = 302; - BaseSoundID = 959; + [Constructible] + public SkitteringHopper() : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 302; + BaseSoundID = 959; - SetStr(41, 65); - SetDex(91, 115); - SetInt(26, 50); + SetStr(41, 65); + SetDex(91, 115); + SetInt(26, 50); - SetHits(31, 45); + SetHits(31, 45); - SetDamage(3, 5); + SetDamage(3, 5); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 5, 10); - SetResistance(ResistanceType.Cold, 10, 20); - SetResistance(ResistanceType.Energy, 5, 10); + SetResistance(ResistanceType.Physical, 5, 10); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Energy, 5, 10); - SetSkill(SkillName.MagicResist, 30.1, 45.0); - SetSkill(SkillName.Tactics, 45.1, 70.0); - SetSkill(SkillName.Wrestling, 40.1, 60.0); + SetSkill(SkillName.MagicResist, 30.1, 45.0); + SetSkill(SkillName.Tactics, 45.1, 70.0); + SetSkill(SkillName.Wrestling, 40.1, 60.0); - Fame = 300; - Karma = 0; + Fame = 300; + Karma = 0; - Tamable = true; - ControlSlots = 1; - MinTameSkill = -12.9; + Tamable = true; + ControlSlots = 1; + MinTameSkill = -12.9; - VirtualArmor = 12; + VirtualArmor = 12; + } + + public SkitteringHopper(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a skittering hopper corpse"; + public override string DefaultName => "a skittering hopper"; + + public override int TreasureMapLevel => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + 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(); + } } - - public SkitteringHopper(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a skittering hopper corpse"; - public override string DefaultName => "a skittering hopper"; - - public override int TreasureMapLevel => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/AOS/Treefellow.cs b/Projects/UOContent/Mobiles/Monsters/AOS/Treefellow.cs index 45547a251..84af1c054 100644 --- a/Projects/UOContent/Mobiles/Monsters/AOS/Treefellow.cs +++ b/Projects/UOContent/Mobiles/Monsters/AOS/Treefellow.cs @@ -2,77 +2,77 @@ using Server.Items; namespace Server.Mobiles { - public class Treefellow : BaseCreature - { - [Constructible] - public Treefellow() : base(AIType.AI_Melee, FightMode.Evil, 10, 1, 0.2, 0.4) + public class Treefellow : BaseCreature { - Body = 301; + [Constructible] + public Treefellow() : base(AIType.AI_Melee, FightMode.Evil, 10, 1, 0.2, 0.4) + { + Body = 301; - SetStr(196, 220); - SetDex(31, 55); - SetInt(66, 90); + SetStr(196, 220); + SetDex(31, 55); + SetInt(66, 90); - SetHits(118, 132); + SetHits(118, 132); - SetDamage(12, 16); + SetDamage(12, 16); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 20, 25); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 30, 35); - SetResistance(ResistanceType.Energy, 20, 30); + SetResistance(ResistanceType.Physical, 20, 25); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 30, 35); + SetResistance(ResistanceType.Energy, 20, 30); - SetSkill(SkillName.MagicResist, 40.1, 55.0); - SetSkill(SkillName.Tactics, 65.1, 90.0); - SetSkill(SkillName.Wrestling, 65.1, 85.0); + SetSkill(SkillName.MagicResist, 40.1, 55.0); + SetSkill(SkillName.Tactics, 65.1, 90.0); + SetSkill(SkillName.Wrestling, 65.1, 85.0); - Fame = 500; - Karma = 1500; + Fame = 500; + Karma = 1500; - VirtualArmor = 24; - PackItem(new Log(Utility.RandomMinMax(23, 34))); + VirtualArmor = 24; + PackItem(new Log(Utility.RandomMinMax(23, 34))); + } + + public Treefellow(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a treefellow corpse"; + + public override string DefaultName => "a treefellow"; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override bool BleedImmune => true; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.Dismount; + + public override int GetIdleSound() => 443; + + public override int GetDeathSound() => 31; + + public override int GetAttackSound() => 672; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + } + + 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 (BaseSoundID == 442) + BaseSoundID = -1; + } } - - public Treefellow(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a treefellow corpse"; - - public override string DefaultName => "a treefellow"; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override bool BleedImmune => true; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.Dismount; - - public override int GetIdleSound() => 443; - - public override int GetDeathSound() => 31; - - public override int GetAttackSound() => 672; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (BaseSoundID == 442) - BaseSoundID = -1; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/AOS/VampireBat.cs b/Projects/UOContent/Mobiles/Monsters/AOS/VampireBat.cs index 6b029aebf..9629f4a7d 100644 --- a/Projects/UOContent/Mobiles/Monsters/AOS/VampireBat.cs +++ b/Projects/UOContent/Mobiles/Monsters/AOS/VampireBat.cs @@ -1,64 +1,64 @@ namespace Server.Mobiles { - public class VampireBat : BaseCreature - { - [Constructible] - public VampireBat() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class VampireBat : BaseCreature { - Body = 317; - BaseSoundID = 0x270; + [Constructible] + public VampireBat() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 317; + BaseSoundID = 0x270; - SetStr(91, 110); - SetDex(91, 115); - SetInt(26, 50); + SetStr(91, 110); + SetDex(91, 115); + SetInt(26, 50); - SetHits(55, 66); + SetHits(55, 66); - SetDamage(7, 9); + SetDamage(7, 9); - SetDamageType(ResistanceType.Physical, 80); - SetDamageType(ResistanceType.Poison, 20); + SetDamageType(ResistanceType.Physical, 80); + SetDamageType(ResistanceType.Poison, 20); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 15, 25); - SetResistance(ResistanceType.Cold, 15, 25); - SetResistance(ResistanceType.Poison, 60, 70); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 15, 25); + SetResistance(ResistanceType.Cold, 15, 25); + SetResistance(ResistanceType.Poison, 60, 70); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.MagicResist, 70.1, 95.0); - SetSkill(SkillName.Tactics, 55.1, 80.0); - SetSkill(SkillName.Wrestling, 30.1, 55.0); + SetSkill(SkillName.MagicResist, 70.1, 95.0); + SetSkill(SkillName.Tactics, 55.1, 80.0); + SetSkill(SkillName.Wrestling, 30.1, 55.0); - Fame = 1000; - Karma = -1000; + Fame = 1000; + Karma = -1000; - VirtualArmor = 14; + VirtualArmor = 14; + } + + public VampireBat(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a vampire bat corpse"; + public override string DefaultName => "a vampire bat"; + + public override void GenerateLoot() + { + AddLoot(LootPack.Poor); + } + + public override int GetIdleSound() => 0x29B; + + 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(); + } } - - public VampireBat(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a vampire bat corpse"; - public override string DefaultName => "a vampire bat"; - - public override void GenerateLoot() - { - AddLoot(LootPack.Poor); - } - - public override int GetIdleSound() => 0x29B; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/AOS/WailingBanshee.cs b/Projects/UOContent/Mobiles/Monsters/AOS/WailingBanshee.cs index 853b5462e..ae86f37f7 100644 --- a/Projects/UOContent/Mobiles/Monsters/AOS/WailingBanshee.cs +++ b/Projects/UOContent/Mobiles/Monsters/AOS/WailingBanshee.cs @@ -2,69 +2,69 @@ using Server.Items; namespace Server.Mobiles { - public class WailingBanshee : BaseCreature - { - [Constructible] - public WailingBanshee() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class WailingBanshee : BaseCreature { - Body = 310; - BaseSoundID = 0x482; + [Constructible] + public WailingBanshee() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 310; + BaseSoundID = 0x482; - SetStr(126, 150); - SetDex(76, 100); - SetInt(86, 110); + SetStr(126, 150); + SetDex(76, 100); + SetInt(86, 110); - SetHits(76, 90); + SetHits(76, 90); - SetDamage(10, 14); + SetDamage(10, 14); - SetDamageType(ResistanceType.Physical, 20); - SetDamageType(ResistanceType.Cold, 60); - SetDamageType(ResistanceType.Poison, 20); + SetDamageType(ResistanceType.Physical, 20); + SetDamageType(ResistanceType.Cold, 60); + SetDamageType(ResistanceType.Poison, 20); - SetResistance(ResistanceType.Physical, 50, 60); - SetResistance(ResistanceType.Fire, 25, 30); - SetResistance(ResistanceType.Cold, 70, 80); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 50, 60); + SetResistance(ResistanceType.Fire, 25, 30); + SetResistance(ResistanceType.Cold, 70, 80); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.MagicResist, 70.1, 95.0); - SetSkill(SkillName.Tactics, 45.1, 70.0); - SetSkill(SkillName.Wrestling, 50.1, 70.0); + SetSkill(SkillName.MagicResist, 70.1, 95.0); + SetSkill(SkillName.Tactics, 45.1, 70.0); + SetSkill(SkillName.Wrestling, 50.1, 70.0); - Fame = 1500; - Karma = -1500; + Fame = 1500; + Karma = -1500; - VirtualArmor = 19; + VirtualArmor = 19; + } + + public WailingBanshee(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a wailing banshee corpse"; + + public override string DefaultName => "a wailing banshee"; + + public override bool BleedImmune => true; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.MortalStrike; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + 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(); + } } - - public WailingBanshee(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a wailing banshee corpse"; - - public override string DefaultName => "a wailing banshee"; - - public override bool BleedImmune => true; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.MortalStrike; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/AOS/WandererOfTheVoid.cs b/Projects/UOContent/Mobiles/Monsters/AOS/WandererOfTheVoid.cs index 332e451b7..54283b701 100644 --- a/Projects/UOContent/Mobiles/Monsters/AOS/WandererOfTheVoid.cs +++ b/Projects/UOContent/Mobiles/Monsters/AOS/WandererOfTheVoid.cs @@ -2,76 +2,76 @@ using Server.Items; namespace Server.Mobiles { - public class WandererOfTheVoid : BaseCreature - { - [Constructible] - public WandererOfTheVoid() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class WandererOfTheVoid : BaseCreature { - Body = 316; - BaseSoundID = 377; + [Constructible] + public WandererOfTheVoid() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 316; + BaseSoundID = 377; - SetStr(111, 200); - SetDex(101, 125); - SetInt(301, 390); + SetStr(111, 200); + SetDex(101, 125); + SetInt(301, 390); - SetHits(351, 400); + SetHits(351, 400); - SetDamage(11, 13); + SetDamage(11, 13); - SetDamageType(ResistanceType.Physical, 0); - SetDamageType(ResistanceType.Cold, 15); - SetDamageType(ResistanceType.Energy, 85); + SetDamageType(ResistanceType.Physical, 0); + SetDamageType(ResistanceType.Cold, 15); + SetDamageType(ResistanceType.Energy, 85); - SetResistance(ResistanceType.Physical, 40, 50); - SetResistance(ResistanceType.Fire, 15, 25); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 50, 75); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 40, 50); + SetResistance(ResistanceType.Fire, 15, 25); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 50, 75); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.EvalInt, 60.1, 70.0); - SetSkill(SkillName.Magery, 60.1, 70.0); - SetSkill(SkillName.Meditation, 60.1, 70.0); - SetSkill(SkillName.MagicResist, 50.1, 75.0); - SetSkill(SkillName.Tactics, 60.1, 70.0); - SetSkill(SkillName.Wrestling, 60.1, 70.0); + SetSkill(SkillName.EvalInt, 60.1, 70.0); + SetSkill(SkillName.Magery, 60.1, 70.0); + SetSkill(SkillName.Meditation, 60.1, 70.0); + SetSkill(SkillName.MagicResist, 50.1, 75.0); + SetSkill(SkillName.Tactics, 60.1, 70.0); + SetSkill(SkillName.Wrestling, 60.1, 70.0); - Fame = 20000; - Karma = -20000; + Fame = 20000; + Karma = -20000; - VirtualArmor = 44; + VirtualArmor = 44; - int count = Utility.RandomMinMax(2, 3); + var count = Utility.RandomMinMax(2, 3); - for (int i = 0; i < count; ++i) - PackItem(new TreasureMap(3, Map.Trammel)); + for (var i = 0; i < count; ++i) + PackItem(new TreasureMap(3, Map.Trammel)); + } + + public WandererOfTheVoid(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a wanderer of the void corpse"; + public override string DefaultName => "a wanderer of the void"; + + public override bool BleedImmune => true; + public override Poison PoisonImmune => Poison.Lethal; + public override int TreasureMapLevel => Core.AOS ? 4 : 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + } + + 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(); + } } - - public WandererOfTheVoid(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a wanderer of the void corpse"; - public override string DefaultName => "a wanderer of the void"; - - public override bool BleedImmune => true; - public override Poison PoisonImmune => Poison.Lethal; - public override int TreasureMapLevel => Core.AOS ? 4 : 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Ants/AntLion.cs b/Projects/UOContent/Mobiles/Monsters/Ants/AntLion.cs index c453630bf..ea40f7d7c 100644 --- a/Projects/UOContent/Mobiles/Monsters/Ants/AntLion.cs +++ b/Projects/UOContent/Mobiles/Monsters/Ants/AntLion.cs @@ -3,93 +3,93 @@ using Server.Items; namespace Server.Mobiles { - public class AntLion : BaseCreature - { - [Constructible] - public AntLion() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class AntLion : BaseCreature { - Body = 787; - BaseSoundID = 1006; + [Constructible] + public AntLion() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 787; + BaseSoundID = 1006; - SetStr(296, 320); - SetDex(81, 105); - SetInt(36, 60); + SetStr(296, 320); + SetDex(81, 105); + SetInt(36, 60); - SetHits(151, 162); + SetHits(151, 162); - SetDamage(7, 21); + SetDamage(7, 21); - SetDamageType(ResistanceType.Physical, 70); - SetDamageType(ResistanceType.Poison, 30); + SetDamageType(ResistanceType.Physical, 70); + SetDamageType(ResistanceType.Poison, 30); - SetResistance(ResistanceType.Physical, 45, 60); - SetResistance(ResistanceType.Fire, 25, 35); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 30, 35); + SetResistance(ResistanceType.Physical, 45, 60); + SetResistance(ResistanceType.Fire, 25, 35); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 30, 35); - SetSkill(SkillName.MagicResist, 70.0); - SetSkill(SkillName.Tactics, 90.0); - SetSkill(SkillName.Wrestling, 90.0); + SetSkill(SkillName.MagicResist, 70.0); + SetSkill(SkillName.Tactics, 90.0); + SetSkill(SkillName.Wrestling, 90.0); - Fame = 4500; - Karma = -4500; + Fame = 4500; + Karma = -4500; - VirtualArmor = 45; + VirtualArmor = 45; - PackItem(new Bone(3)); - PackItem(new FertileDirt(Utility.RandomMinMax(1, 5))); + PackItem(new Bone(3)); + PackItem(new FertileDirt(Utility.RandomMinMax(1, 5))); - if (Core.ML && Utility.RandomDouble() < .33) - PackItem(Seed.RandomPeculiarSeed(2)); + if (Core.ML && Utility.RandomDouble() < .33) + PackItem(Seed.RandomPeculiarSeed(2)); - var orepile = Utility.Random(4) switch - { - 0 => (Item)new DullCopperOre(), - 1 => new ShadowIronOre(), - 2 => new CopperOre(), - _ => new BronzeOre() - }; + var orepile = Utility.Random(4) switch + { + 0 => (Item)new DullCopperOre(), + 1 => new ShadowIronOre(), + 2 => new CopperOre(), + _ => new BronzeOre() + }; - orepile.Amount = Utility.RandomMinMax(1, 10); - orepile.ItemID = 0x19B9; - PackItem(orepile); + orepile.Amount = Utility.RandomMinMax(1, 10); + orepile.ItemID = 0x19B9; + PackItem(orepile); - // TODO: skeleton + // TODO: skeleton + } + + public AntLion(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ant lion corpse"; + public override string DefaultName => "an ant lion"; + + public override int GetAngerSound() => 0x5A; + + public override int GetIdleSound() => 0x5A; + + public override int GetAttackSound() => 0x164; + + public override int GetHurtSound() => 0x187; + + public override int GetDeathSound() => 0x1BA; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average, 2); + } + + 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(); + } } - - public AntLion(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ant lion corpse"; - public override string DefaultName => "an ant lion"; - - public override int GetAngerSound() => 0x5A; - - public override int GetIdleSound() => 0x5A; - - public override int GetAttackSound() => 0x164; - - public override int GetHurtSound() => 0x187; - - public override int GetDeathSound() => 0x1BA; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Ants/BlackSolenInfiltratorQueen.cs b/Projects/UOContent/Mobiles/Monsters/Ants/BlackSolenInfiltratorQueen.cs index df8f06f5c..14e7a0b6a 100644 --- a/Projects/UOContent/Mobiles/Monsters/Ants/BlackSolenInfiltratorQueen.cs +++ b/Projects/UOContent/Mobiles/Monsters/Ants/BlackSolenInfiltratorQueen.cs @@ -2,92 +2,92 @@ using Server.Items; namespace Server.Mobiles { - public class BlackSolenInfiltratorQueen : BaseCreature - { - [Constructible] - public BlackSolenInfiltratorQueen() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class BlackSolenInfiltratorQueen : BaseCreature { - Body = 807; - BaseSoundID = 959; - Hue = 0x453; + [Constructible] + public BlackSolenInfiltratorQueen() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 807; + BaseSoundID = 959; + Hue = 0x453; - SetStr(326, 350); - SetDex(141, 165); - SetInt(96, 120); + SetStr(326, 350); + SetDex(141, 165); + SetInt(96, 120); - SetHits(151, 162); + SetHits(151, 162); - SetDamage(10, 15); + SetDamage(10, 15); - SetDamageType(ResistanceType.Physical, 70); - SetDamageType(ResistanceType.Poison, 30); + SetDamageType(ResistanceType.Physical, 70); + SetDamageType(ResistanceType.Poison, 30); - SetResistance(ResistanceType.Physical, 30, 40); - SetResistance(ResistanceType.Fire, 30, 35); - SetResistance(ResistanceType.Cold, 25, 35); - SetResistance(ResistanceType.Poison, 35, 40); - SetResistance(ResistanceType.Energy, 25, 30); + SetResistance(ResistanceType.Physical, 30, 40); + SetResistance(ResistanceType.Fire, 30, 35); + SetResistance(ResistanceType.Cold, 25, 35); + SetResistance(ResistanceType.Poison, 35, 40); + SetResistance(ResistanceType.Energy, 25, 30); - SetSkill(SkillName.MagicResist, 90.0); - SetSkill(SkillName.Tactics, 90.0); - SetSkill(SkillName.Wrestling, 90.0); + SetSkill(SkillName.MagicResist, 90.0); + SetSkill(SkillName.Tactics, 90.0); + SetSkill(SkillName.Wrestling, 90.0); - Fame = 6500; - Karma = -6500; + Fame = 6500; + Karma = -6500; - VirtualArmor = 50; + VirtualArmor = 50; - SolenHelper.PackPicnicBasket(this); + SolenHelper.PackPicnicBasket(this); - PackItem(new ZoogiFungus(Utility.RandomDouble() < 0.05 ? 16 : 4)); + PackItem(new ZoogiFungus(Utility.RandomDouble() < 0.05 ? 16 : 4)); + } + + public BlackSolenInfiltratorQueen(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a solen infiltrator corpse"; + public override string DefaultName => "a black solen infiltrator"; + + public override int GetAngerSound() => 0x259; + + public override int GetIdleSound() => 0x259; + + public override int GetAttackSound() => 0x195; + + public override int GetHurtSound() => 0x250; + + public override int GetDeathSound() => 0x25B; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + } + + public override bool IsEnemy(Mobile m) + { + if (SolenHelper.CheckBlackFriendship(m)) + return false; + return base.IsEnemy(m); + } + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + SolenHelper.OnBlackDamage(from); + + base.OnDamage(amount, from, willKill); + } + + 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(); + } } - - public BlackSolenInfiltratorQueen(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a solen infiltrator corpse"; - public override string DefaultName => "a black solen infiltrator"; - - public override int GetAngerSound() => 0x259; - - public override int GetIdleSound() => 0x259; - - public override int GetAttackSound() => 0x195; - - public override int GetHurtSound() => 0x250; - - public override int GetDeathSound() => 0x25B; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - } - - public override bool IsEnemy(Mobile m) - { - if (SolenHelper.CheckBlackFriendship(m)) - return false; - return base.IsEnemy(m); - } - - public override void OnDamage(int amount, Mobile from, bool willKill) - { - SolenHelper.OnBlackDamage(from); - - base.OnDamage(amount, from, willKill); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Ants/BlackSolenInfiltratorWarrior.cs b/Projects/UOContent/Mobiles/Monsters/Ants/BlackSolenInfiltratorWarrior.cs index 7e73f9352..7bbe72f2b 100644 --- a/Projects/UOContent/Mobiles/Monsters/Ants/BlackSolenInfiltratorWarrior.cs +++ b/Projects/UOContent/Mobiles/Monsters/Ants/BlackSolenInfiltratorWarrior.cs @@ -2,93 +2,93 @@ using Server.Items; namespace Server.Mobiles { - public class BlackSolenInfiltratorWarrior : BaseCreature - { - [Constructible] - public BlackSolenInfiltratorWarrior() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class BlackSolenInfiltratorWarrior : BaseCreature { - Body = 806; - BaseSoundID = 959; - Hue = 0x453; + [Constructible] + public BlackSolenInfiltratorWarrior() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 806; + BaseSoundID = 959; + Hue = 0x453; - SetStr(206, 230); - SetDex(121, 145); - SetInt(66, 90); + SetStr(206, 230); + SetDex(121, 145); + SetInt(66, 90); - SetHits(96, 107); + SetHits(96, 107); - SetDamage(5, 15); + SetDamage(5, 15); - SetDamageType(ResistanceType.Physical, 80); - SetDamageType(ResistanceType.Poison, 20); + SetDamageType(ResistanceType.Physical, 80); + SetDamageType(ResistanceType.Poison, 20); - SetResistance(ResistanceType.Physical, 20, 35); - SetResistance(ResistanceType.Fire, 20, 35); - SetResistance(ResistanceType.Cold, 10, 25); - SetResistance(ResistanceType.Poison, 20, 35); - SetResistance(ResistanceType.Energy, 10, 25); + SetResistance(ResistanceType.Physical, 20, 35); + SetResistance(ResistanceType.Fire, 20, 35); + SetResistance(ResistanceType.Cold, 10, 25); + SetResistance(ResistanceType.Poison, 20, 35); + SetResistance(ResistanceType.Energy, 10, 25); - SetSkill(SkillName.MagicResist, 80.0); - SetSkill(SkillName.Tactics, 80.0); - SetSkill(SkillName.Wrestling, 80.0); + SetSkill(SkillName.MagicResist, 80.0); + SetSkill(SkillName.Tactics, 80.0); + SetSkill(SkillName.Wrestling, 80.0); - Fame = 3000; - Karma = -3000; + Fame = 3000; + Karma = -3000; - VirtualArmor = 40; + VirtualArmor = 40; - SolenHelper.PackPicnicBasket(this); + SolenHelper.PackPicnicBasket(this); - PackItem(new ZoogiFungus(Utility.RandomDouble() < 0.05 ? 13 : 3)); + PackItem(new ZoogiFungus(Utility.RandomDouble() < 0.05 ? 13 : 3)); + } + + public BlackSolenInfiltratorWarrior(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a solen infiltrator corpse"; + public override string DefaultName => "a black solen infiltrator"; + + public override int GetAngerSound() => 0xB5; + + public override int GetIdleSound() => 0xB5; + + public override int GetAttackSound() => 0x289; + + public override int GetHurtSound() => 0xBC; + + public override int GetDeathSound() => 0xE4; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average, 2); + AddLoot(LootPack.Gems, Utility.RandomMinMax(1, 4)); + } + + public override bool IsEnemy(Mobile m) + { + if (SolenHelper.CheckBlackFriendship(m)) + return false; + return base.IsEnemy(m); + } + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + SolenHelper.OnBlackDamage(from); + + base.OnDamage(amount, from, willKill); + } + + 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(); + } } - - public BlackSolenInfiltratorWarrior(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a solen infiltrator corpse"; - public override string DefaultName => "a black solen infiltrator"; - - public override int GetAngerSound() => 0xB5; - - public override int GetIdleSound() => 0xB5; - - public override int GetAttackSound() => 0x289; - - public override int GetHurtSound() => 0xBC; - - public override int GetDeathSound() => 0xE4; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average, 2); - AddLoot(LootPack.Gems, Utility.RandomMinMax(1, 4)); - } - - public override bool IsEnemy(Mobile m) - { - if (SolenHelper.CheckBlackFriendship(m)) - return false; - return base.IsEnemy(m); - } - - public override void OnDamage(int amount, Mobile from, bool willKill) - { - SolenHelper.OnBlackDamage(from); - - base.OnDamage(amount, from, willKill); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Ants/BlackSolenQueen.cs b/Projects/UOContent/Mobiles/Monsters/Ants/BlackSolenQueen.cs index c0f4b3975..f9c17e48b 100644 --- a/Projects/UOContent/Mobiles/Monsters/Ants/BlackSolenQueen.cs +++ b/Projects/UOContent/Mobiles/Monsters/Ants/BlackSolenQueen.cs @@ -3,130 +3,130 @@ using Server.Network; namespace Server.Mobiles { - public class BlackSolenQueen : BaseCreature - { - [Constructible] - public BlackSolenQueen() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class BlackSolenQueen : BaseCreature { - Body = 807; - BaseSoundID = 959; - Hue = 0x453; - - SetStr(296, 320); - SetDex(121, 145); - SetInt(76, 100); - - SetHits(151, 162); - - SetDamage(10, 15); - - SetDamageType(ResistanceType.Physical, 70); - SetDamageType(ResistanceType.Poison, 30); - - SetResistance(ResistanceType.Physical, 30, 40); - SetResistance(ResistanceType.Fire, 30, 35); - SetResistance(ResistanceType.Cold, 25, 35); - SetResistance(ResistanceType.Poison, 35, 40); - SetResistance(ResistanceType.Energy, 25, 30); - - SetSkill(SkillName.MagicResist, 70.0); - SetSkill(SkillName.Tactics, 90.0); - SetSkill(SkillName.Wrestling, 90.0); - - Fame = 4500; - Karma = -4500; - - VirtualArmor = 45; - - SolenHelper.PackPicnicBasket(this); - - PackItem(new ZoogiFungus(Utility.RandomDouble() > 0.05 ? 5 : 25)); - - if (Utility.RandomDouble() < 0.05) - PackItem(new BallOfSummoning()); - } - - public BlackSolenQueen(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a solen queen corpse"; - public bool BurstSac { get; private set; } - - public override string DefaultName => "a black solen queen"; - - public override int GetAngerSound() => 0x259; - - public override int GetIdleSound() => 0x259; - - public override int GetAttackSound() => 0x195; - - public override int GetHurtSound() => 0x250; - - public override int GetDeathSound() => 0x25B; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - } - - public override bool IsEnemy(Mobile m) - { - if (SolenHelper.CheckBlackFriendship(m)) - return false; - return base.IsEnemy(m); - } - - public override void OnDamage(int amount, Mobile from, bool willKill) - { - SolenHelper.OnBlackDamage(from); - - if (!willKill) - { - if (!BurstSac) + [Constructible] + public BlackSolenQueen() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) { - if (Hits < 50) - { - PublicOverheadMessage(MessageType.Regular, 0x3B2, true, "* The solen's acid sac is burst open! *"); - BurstSac = true; - } + Body = 807; + BaseSoundID = 959; + Hue = 0x453; + + SetStr(296, 320); + SetDex(121, 145); + SetInt(76, 100); + + SetHits(151, 162); + + SetDamage(10, 15); + + SetDamageType(ResistanceType.Physical, 70); + SetDamageType(ResistanceType.Poison, 30); + + SetResistance(ResistanceType.Physical, 30, 40); + SetResistance(ResistanceType.Fire, 30, 35); + SetResistance(ResistanceType.Cold, 25, 35); + SetResistance(ResistanceType.Poison, 35, 40); + SetResistance(ResistanceType.Energy, 25, 30); + + SetSkill(SkillName.MagicResist, 70.0); + SetSkill(SkillName.Tactics, 90.0); + SetSkill(SkillName.Wrestling, 90.0); + + Fame = 4500; + Karma = -4500; + + VirtualArmor = 45; + + SolenHelper.PackPicnicBasket(this); + + PackItem(new ZoogiFungus(Utility.RandomDouble() > 0.05 ? 5 : 25)); + + if (Utility.RandomDouble() < 0.05) + PackItem(new BallOfSummoning()); } - else if (from != null && from != this && InRange(from, 1)) + + public BlackSolenQueen(Serial serial) : base(serial) { - SpillAcid(from, 1); } - } - base.OnDamage(amount, from, willKill); + public override string CorpseName => "a solen queen corpse"; + public bool BurstSac { get; private set; } + + public override string DefaultName => "a black solen queen"; + + public override int GetAngerSound() => 0x259; + + public override int GetIdleSound() => 0x259; + + public override int GetAttackSound() => 0x195; + + public override int GetHurtSound() => 0x250; + + public override int GetDeathSound() => 0x25B; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + } + + public override bool IsEnemy(Mobile m) + { + if (SolenHelper.CheckBlackFriendship(m)) + return false; + return base.IsEnemy(m); + } + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + SolenHelper.OnBlackDamage(from); + + if (!willKill) + { + if (!BurstSac) + { + if (Hits < 50) + { + PublicOverheadMessage(MessageType.Regular, 0x3B2, true, "* The solen's acid sac is burst open! *"); + BurstSac = true; + } + } + else if (from != null && from != this && InRange(from, 1)) + { + SpillAcid(from, 1); + } + } + + base.OnDamage(amount, from, willKill); + } + + public override bool OnBeforeDeath() + { + SpillAcid(4); + + return base.OnBeforeDeath(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(1); + writer.Write(BurstSac); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + BurstSac = reader.ReadBool(); + break; + } + } + } } - - public override bool OnBeforeDeath() - { - SpillAcid(4); - - return base.OnBeforeDeath(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); - writer.Write(BurstSac); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - BurstSac = reader.ReadBool(); - break; - } - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Ants/BlackSolenWarrior.cs b/Projects/UOContent/Mobiles/Monsters/Ants/BlackSolenWarrior.cs index 4770eff58..73c87680e 100644 --- a/Projects/UOContent/Mobiles/Monsters/Ants/BlackSolenWarrior.cs +++ b/Projects/UOContent/Mobiles/Monsters/Ants/BlackSolenWarrior.cs @@ -3,131 +3,131 @@ using Server.Network; namespace Server.Mobiles { - public class BlackSolenWarrior : BaseCreature - { - [Constructible] - public BlackSolenWarrior() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class BlackSolenWarrior : BaseCreature { - Body = 806; - BaseSoundID = 959; - Hue = 0x453; - - SetStr(196, 220); - SetDex(101, 125); - SetInt(36, 60); - - SetHits(96, 107); - - SetDamage(5, 15); - - SetDamageType(ResistanceType.Physical, 80); - SetDamageType(ResistanceType.Poison, 20); - - SetResistance(ResistanceType.Physical, 20, 35); - SetResistance(ResistanceType.Fire, 20, 35); - SetResistance(ResistanceType.Cold, 10, 25); - SetResistance(ResistanceType.Poison, 20, 35); - SetResistance(ResistanceType.Energy, 10, 25); - - SetSkill(SkillName.MagicResist, 60.0); - SetSkill(SkillName.Tactics, 80.0); - SetSkill(SkillName.Wrestling, 80.0); - - Fame = 3000; - Karma = -3000; - - VirtualArmor = 35; - - SolenHelper.PackPicnicBasket(this); - - PackItem(new ZoogiFungus(Utility.RandomDouble() < 0.05 ? 13 : 3)); - - if (Utility.RandomDouble() < 0.05) - PackItem(new BraceletOfBinding()); - } - - public BlackSolenWarrior(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a solen warrior corpse"; - public bool BurstSac { get; private set; } - - public override string DefaultName => "a black solen warrior"; - - public override int GetAngerSound() => 0xB5; - - public override int GetIdleSound() => 0xB5; - - public override int GetAttackSound() => 0x289; - - public override int GetHurtSound() => 0xBC; - - public override int GetDeathSound() => 0xE4; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.Gems, Utility.RandomMinMax(1, 4)); - } - - public override bool IsEnemy(Mobile m) - { - if (SolenHelper.CheckBlackFriendship(m)) - return false; - return base.IsEnemy(m); - } - - public override void OnDamage(int amount, Mobile from, bool willKill) - { - SolenHelper.OnBlackDamage(from); - - if (!willKill) - { - if (!BurstSac) + [Constructible] + public BlackSolenWarrior() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) { - if (Hits < 50) - { - PublicOverheadMessage(MessageType.Regular, 0x3B2, true, "* The solen's acid sac is burst open! *"); - BurstSac = true; - } + Body = 806; + BaseSoundID = 959; + Hue = 0x453; + + SetStr(196, 220); + SetDex(101, 125); + SetInt(36, 60); + + SetHits(96, 107); + + SetDamage(5, 15); + + SetDamageType(ResistanceType.Physical, 80); + SetDamageType(ResistanceType.Poison, 20); + + SetResistance(ResistanceType.Physical, 20, 35); + SetResistance(ResistanceType.Fire, 20, 35); + SetResistance(ResistanceType.Cold, 10, 25); + SetResistance(ResistanceType.Poison, 20, 35); + SetResistance(ResistanceType.Energy, 10, 25); + + SetSkill(SkillName.MagicResist, 60.0); + SetSkill(SkillName.Tactics, 80.0); + SetSkill(SkillName.Wrestling, 80.0); + + Fame = 3000; + Karma = -3000; + + VirtualArmor = 35; + + SolenHelper.PackPicnicBasket(this); + + PackItem(new ZoogiFungus(Utility.RandomDouble() < 0.05 ? 13 : 3)); + + if (Utility.RandomDouble() < 0.05) + PackItem(new BraceletOfBinding()); } - else if (from != null && from != this && InRange(from, 1)) + + public BlackSolenWarrior(Serial serial) : base(serial) { - SpillAcid(from, 1); } - } - base.OnDamage(amount, from, willKill); + public override string CorpseName => "a solen warrior corpse"; + public bool BurstSac { get; private set; } + + public override string DefaultName => "a black solen warrior"; + + public override int GetAngerSound() => 0xB5; + + public override int GetIdleSound() => 0xB5; + + public override int GetAttackSound() => 0x289; + + public override int GetHurtSound() => 0xBC; + + public override int GetDeathSound() => 0xE4; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.Gems, Utility.RandomMinMax(1, 4)); + } + + public override bool IsEnemy(Mobile m) + { + if (SolenHelper.CheckBlackFriendship(m)) + return false; + return base.IsEnemy(m); + } + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + SolenHelper.OnBlackDamage(from); + + if (!willKill) + { + if (!BurstSac) + { + if (Hits < 50) + { + PublicOverheadMessage(MessageType.Regular, 0x3B2, true, "* The solen's acid sac is burst open! *"); + BurstSac = true; + } + } + else if (from != null && from != this && InRange(from, 1)) + { + SpillAcid(from, 1); + } + } + + base.OnDamage(amount, from, willKill); + } + + public override bool OnBeforeDeath() + { + SpillAcid(4); + + return base.OnBeforeDeath(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(1); + writer.Write(BurstSac); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + BurstSac = reader.ReadBool(); + break; + } + } + } } - - public override bool OnBeforeDeath() - { - SpillAcid(4); - - return base.OnBeforeDeath(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); - writer.Write(BurstSac); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - BurstSac = reader.ReadBool(); - break; - } - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Ants/BlackSolenWorker.cs b/Projects/UOContent/Mobiles/Monsters/Ants/BlackSolenWorker.cs index 97a39f665..460669c72 100644 --- a/Projects/UOContent/Mobiles/Monsters/Ants/BlackSolenWorker.cs +++ b/Projects/UOContent/Mobiles/Monsters/Ants/BlackSolenWorker.cs @@ -2,93 +2,93 @@ using Server.Items; namespace Server.Mobiles { - public class BlackSolenWorker : BaseCreature - { - [Constructible] - public BlackSolenWorker() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class BlackSolenWorker : BaseCreature { - Body = 805; - BaseSoundID = 959; - Hue = 0x453; + [Constructible] + public BlackSolenWorker() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 805; + BaseSoundID = 959; + Hue = 0x453; - SetStr(96, 120); - SetDex(81, 105); - SetInt(36, 60); + SetStr(96, 120); + SetDex(81, 105); + SetInt(36, 60); - SetHits(58, 72); + SetHits(58, 72); - SetDamage(5, 7); + SetDamage(5, 7); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 25, 30); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 10, 20); - SetResistance(ResistanceType.Poison, 10, 20); - SetResistance(ResistanceType.Energy, 20, 30); + SetResistance(ResistanceType.Physical, 25, 30); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Energy, 20, 30); - SetSkill(SkillName.MagicResist, 60.0); - SetSkill(SkillName.Tactics, 65.0); - SetSkill(SkillName.Wrestling, 60.0); + SetSkill(SkillName.MagicResist, 60.0); + SetSkill(SkillName.Tactics, 65.0); + SetSkill(SkillName.Wrestling, 60.0); - Fame = 1500; - Karma = -1500; + Fame = 1500; + Karma = -1500; - VirtualArmor = 28; + VirtualArmor = 28; - PackGold(Utility.Random(100, 180)); + PackGold(Utility.Random(100, 180)); - SolenHelper.PackPicnicBasket(this); + SolenHelper.PackPicnicBasket(this); - PackItem(new ZoogiFungus()); + PackItem(new ZoogiFungus()); + } + + public BlackSolenWorker(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a solen worker corpse"; + public override string DefaultName => "a black solen worker"; + + public override int GetAngerSound() => 0x269; + + public override int GetIdleSound() => 0x269; + + public override int GetAttackSound() => 0x186; + + public override int GetHurtSound() => 0x1BE; + + public override int GetDeathSound() => 0x8E; + + public override void GenerateLoot() + { + AddLoot(LootPack.Gems, Utility.RandomMinMax(1, 2)); + } + + public override bool IsEnemy(Mobile m) + { + if (SolenHelper.CheckBlackFriendship(m)) + return false; + return base.IsEnemy(m); + } + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + SolenHelper.OnBlackDamage(from); + + base.OnDamage(amount, from, willKill); + } + + 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(); + } } - - public BlackSolenWorker(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a solen worker corpse"; - public override string DefaultName => "a black solen worker"; - - public override int GetAngerSound() => 0x269; - - public override int GetIdleSound() => 0x269; - - public override int GetAttackSound() => 0x186; - - public override int GetHurtSound() => 0x1BE; - - public override int GetDeathSound() => 0x8E; - - public override void GenerateLoot() - { - AddLoot(LootPack.Gems, Utility.RandomMinMax(1, 2)); - } - - public override bool IsEnemy(Mobile m) - { - if (SolenHelper.CheckBlackFriendship(m)) - return false; - return base.IsEnemy(m); - } - - public override void OnDamage(int amount, Mobile from, bool willKill) - { - SolenHelper.OnBlackDamage(from); - - base.OnDamage(amount, from, willKill); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Ants/RedSolenInfiltratorQueen.cs b/Projects/UOContent/Mobiles/Monsters/Ants/RedSolenInfiltratorQueen.cs index ee1f2e908..0a410828a 100644 --- a/Projects/UOContent/Mobiles/Monsters/Ants/RedSolenInfiltratorQueen.cs +++ b/Projects/UOContent/Mobiles/Monsters/Ants/RedSolenInfiltratorQueen.cs @@ -2,91 +2,91 @@ using Server.Items; namespace Server.Mobiles { - public class RedSolenInfiltratorQueen : BaseCreature - { - [Constructible] - public RedSolenInfiltratorQueen() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class RedSolenInfiltratorQueen : BaseCreature { - Body = 783; - BaseSoundID = 959; + [Constructible] + public RedSolenInfiltratorQueen() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 783; + BaseSoundID = 959; - SetStr(326, 350); - SetDex(141, 165); - SetInt(96, 120); + SetStr(326, 350); + SetDex(141, 165); + SetInt(96, 120); - SetHits(151, 162); + SetHits(151, 162); - SetDamage(10, 15); + SetDamage(10, 15); - SetDamageType(ResistanceType.Physical, 70); - SetDamageType(ResistanceType.Poison, 30); + SetDamageType(ResistanceType.Physical, 70); + SetDamageType(ResistanceType.Poison, 30); - SetResistance(ResistanceType.Physical, 30, 40); - SetResistance(ResistanceType.Fire, 30, 35); - SetResistance(ResistanceType.Cold, 25, 35); - SetResistance(ResistanceType.Poison, 35, 40); - SetResistance(ResistanceType.Energy, 25, 30); + SetResistance(ResistanceType.Physical, 30, 40); + SetResistance(ResistanceType.Fire, 30, 35); + SetResistance(ResistanceType.Cold, 25, 35); + SetResistance(ResistanceType.Poison, 35, 40); + SetResistance(ResistanceType.Energy, 25, 30); - SetSkill(SkillName.MagicResist, 90.0); - SetSkill(SkillName.Tactics, 90.0); - SetSkill(SkillName.Wrestling, 90.0); + SetSkill(SkillName.MagicResist, 90.0); + SetSkill(SkillName.Tactics, 90.0); + SetSkill(SkillName.Wrestling, 90.0); - Fame = 6500; - Karma = -6500; + Fame = 6500; + Karma = -6500; - VirtualArmor = 50; + VirtualArmor = 50; - SolenHelper.PackPicnicBasket(this); + SolenHelper.PackPicnicBasket(this); - PackItem(new ZoogiFungus(Utility.RandomDouble() > 0.05 ? 4 : 16)); + PackItem(new ZoogiFungus(Utility.RandomDouble() > 0.05 ? 4 : 16)); + } + + public RedSolenInfiltratorQueen(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a solen infiltrator corpse"; + public override string DefaultName => "a red solen infiltrator"; + + public override int GetAngerSound() => 0x259; + + public override int GetIdleSound() => 0x259; + + public override int GetAttackSound() => 0x195; + + public override int GetHurtSound() => 0x250; + + public override int GetDeathSound() => 0x25B; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + } + + public override bool IsEnemy(Mobile m) + { + if (SolenHelper.CheckRedFriendship(m)) + return false; + return base.IsEnemy(m); + } + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + SolenHelper.OnRedDamage(from); + + base.OnDamage(amount, from, willKill); + } + + 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(); + } } - - public RedSolenInfiltratorQueen(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a solen infiltrator corpse"; - public override string DefaultName => "a red solen infiltrator"; - - public override int GetAngerSound() => 0x259; - - public override int GetIdleSound() => 0x259; - - public override int GetAttackSound() => 0x195; - - public override int GetHurtSound() => 0x250; - - public override int GetDeathSound() => 0x25B; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - } - - public override bool IsEnemy(Mobile m) - { - if (SolenHelper.CheckRedFriendship(m)) - return false; - return base.IsEnemy(m); - } - - public override void OnDamage(int amount, Mobile from, bool willKill) - { - SolenHelper.OnRedDamage(from); - - base.OnDamage(amount, from, willKill); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Ants/RedSolenInfiltratorWarrior.cs b/Projects/UOContent/Mobiles/Monsters/Ants/RedSolenInfiltratorWarrior.cs index e76376a77..566f8a77f 100644 --- a/Projects/UOContent/Mobiles/Monsters/Ants/RedSolenInfiltratorWarrior.cs +++ b/Projects/UOContent/Mobiles/Monsters/Ants/RedSolenInfiltratorWarrior.cs @@ -2,92 +2,92 @@ using Server.Items; namespace Server.Mobiles { - public class RedSolenInfiltratorWarrior : BaseCreature - { - [Constructible] - public RedSolenInfiltratorWarrior() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class RedSolenInfiltratorWarrior : BaseCreature { - Body = 782; - BaseSoundID = 959; + [Constructible] + public RedSolenInfiltratorWarrior() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 782; + BaseSoundID = 959; - SetStr(206, 230); - SetDex(121, 145); - SetInt(66, 90); + SetStr(206, 230); + SetDex(121, 145); + SetInt(66, 90); - SetHits(96, 107); + SetHits(96, 107); - SetDamage(5, 15); + SetDamage(5, 15); - SetDamageType(ResistanceType.Physical, 80); - SetDamageType(ResistanceType.Poison, 20); + SetDamageType(ResistanceType.Physical, 80); + SetDamageType(ResistanceType.Poison, 20); - SetResistance(ResistanceType.Physical, 20, 35); - SetResistance(ResistanceType.Fire, 20, 35); - SetResistance(ResistanceType.Cold, 10, 25); - SetResistance(ResistanceType.Poison, 20, 35); - SetResistance(ResistanceType.Energy, 10, 25); + SetResistance(ResistanceType.Physical, 20, 35); + SetResistance(ResistanceType.Fire, 20, 35); + SetResistance(ResistanceType.Cold, 10, 25); + SetResistance(ResistanceType.Poison, 20, 35); + SetResistance(ResistanceType.Energy, 10, 25); - SetSkill(SkillName.MagicResist, 80.0); - SetSkill(SkillName.Tactics, 80.0); - SetSkill(SkillName.Wrestling, 80.0); + SetSkill(SkillName.MagicResist, 80.0); + SetSkill(SkillName.Tactics, 80.0); + SetSkill(SkillName.Wrestling, 80.0); - Fame = 3000; - Karma = -3000; + Fame = 3000; + Karma = -3000; - VirtualArmor = 40; + VirtualArmor = 40; - SolenHelper.PackPicnicBasket(this); + SolenHelper.PackPicnicBasket(this); - PackItem(new ZoogiFungus(Utility.RandomDouble() > 0.05 ? 3 : 13)); + PackItem(new ZoogiFungus(Utility.RandomDouble() > 0.05 ? 3 : 13)); + } + + public RedSolenInfiltratorWarrior(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a solen infiltrator corpse"; + public override string DefaultName => "a red solen infiltrator"; + + public override int GetAngerSound() => 0xB5; + + public override int GetIdleSound() => 0xB5; + + public override int GetAttackSound() => 0x289; + + public override int GetHurtSound() => 0xBC; + + public override int GetDeathSound() => 0xE4; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average, 2); + AddLoot(LootPack.Gems, Utility.RandomMinMax(1, 4)); + } + + public override bool IsEnemy(Mobile m) + { + if (SolenHelper.CheckRedFriendship(m)) + return false; + return base.IsEnemy(m); + } + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + SolenHelper.OnRedDamage(from); + + base.OnDamage(amount, from, willKill); + } + + 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(); + } } - - public RedSolenInfiltratorWarrior(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a solen infiltrator corpse"; - public override string DefaultName => "a red solen infiltrator"; - - public override int GetAngerSound() => 0xB5; - - public override int GetIdleSound() => 0xB5; - - public override int GetAttackSound() => 0x289; - - public override int GetHurtSound() => 0xBC; - - public override int GetDeathSound() => 0xE4; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average, 2); - AddLoot(LootPack.Gems, Utility.RandomMinMax(1, 4)); - } - - public override bool IsEnemy(Mobile m) - { - if (SolenHelper.CheckRedFriendship(m)) - return false; - return base.IsEnemy(m); - } - - public override void OnDamage(int amount, Mobile from, bool willKill) - { - SolenHelper.OnRedDamage(from); - - base.OnDamage(amount, from, willKill); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Ants/RedSolenQueen.cs b/Projects/UOContent/Mobiles/Monsters/Ants/RedSolenQueen.cs index 0b9f772f8..4de0f4a00 100644 --- a/Projects/UOContent/Mobiles/Monsters/Ants/RedSolenQueen.cs +++ b/Projects/UOContent/Mobiles/Monsters/Ants/RedSolenQueen.cs @@ -3,129 +3,129 @@ using Server.Network; namespace Server.Mobiles { - public class RedSolenQueen : BaseCreature - { - [Constructible] - public RedSolenQueen() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class RedSolenQueen : BaseCreature { - Body = 783; - BaseSoundID = 959; - - SetStr(296, 320); - SetDex(121, 145); - SetInt(76, 100); - - SetHits(151, 162); - - SetDamage(10, 15); - - SetDamageType(ResistanceType.Physical, 70); - SetDamageType(ResistanceType.Poison, 30); - - SetResistance(ResistanceType.Physical, 30, 40); - SetResistance(ResistanceType.Fire, 30, 35); - SetResistance(ResistanceType.Cold, 25, 35); - SetResistance(ResistanceType.Poison, 35, 40); - SetResistance(ResistanceType.Energy, 25, 30); - - SetSkill(SkillName.MagicResist, 70.0); - SetSkill(SkillName.Tactics, 90.0); - SetSkill(SkillName.Wrestling, 90.0); - - Fame = 4500; - Karma = -4500; - - VirtualArmor = 45; - - SolenHelper.PackPicnicBasket(this); - - PackItem(new ZoogiFungus(Utility.RandomDouble() > 0.05 ? 5 : 25)); - - if (Utility.RandomDouble() < 0.05) - PackItem(new BallOfSummoning()); - } - - public RedSolenQueen(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a solen queen corpse"; - public bool BurstSac { get; private set; } - - public override string DefaultName => "a red solen queen"; - - public override int GetAngerSound() => 0x259; - - public override int GetIdleSound() => 0x259; - - public override int GetAttackSound() => 0x195; - - public override int GetHurtSound() => 0x250; - - public override int GetDeathSound() => 0x25B; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - } - - public override bool IsEnemy(Mobile m) - { - if (SolenHelper.CheckRedFriendship(m)) - return false; - return base.IsEnemy(m); - } - - public override void OnDamage(int amount, Mobile from, bool willKill) - { - SolenHelper.OnRedDamage(from); - - if (!willKill) - { - if (!BurstSac) + [Constructible] + public RedSolenQueen() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) { - if (Hits < 50) - { - PublicOverheadMessage(MessageType.Regular, 0x3B2, true, "* The solen's acid sac is burst open! *"); - BurstSac = true; - } + Body = 783; + BaseSoundID = 959; + + SetStr(296, 320); + SetDex(121, 145); + SetInt(76, 100); + + SetHits(151, 162); + + SetDamage(10, 15); + + SetDamageType(ResistanceType.Physical, 70); + SetDamageType(ResistanceType.Poison, 30); + + SetResistance(ResistanceType.Physical, 30, 40); + SetResistance(ResistanceType.Fire, 30, 35); + SetResistance(ResistanceType.Cold, 25, 35); + SetResistance(ResistanceType.Poison, 35, 40); + SetResistance(ResistanceType.Energy, 25, 30); + + SetSkill(SkillName.MagicResist, 70.0); + SetSkill(SkillName.Tactics, 90.0); + SetSkill(SkillName.Wrestling, 90.0); + + Fame = 4500; + Karma = -4500; + + VirtualArmor = 45; + + SolenHelper.PackPicnicBasket(this); + + PackItem(new ZoogiFungus(Utility.RandomDouble() > 0.05 ? 5 : 25)); + + if (Utility.RandomDouble() < 0.05) + PackItem(new BallOfSummoning()); } - else if (from != null && from != this && InRange(from, 1)) + + public RedSolenQueen(Serial serial) : base(serial) { - SpillAcid(from, 1); } - } - base.OnDamage(amount, from, willKill); + public override string CorpseName => "a solen queen corpse"; + public bool BurstSac { get; private set; } + + public override string DefaultName => "a red solen queen"; + + public override int GetAngerSound() => 0x259; + + public override int GetIdleSound() => 0x259; + + public override int GetAttackSound() => 0x195; + + public override int GetHurtSound() => 0x250; + + public override int GetDeathSound() => 0x25B; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + } + + public override bool IsEnemy(Mobile m) + { + if (SolenHelper.CheckRedFriendship(m)) + return false; + return base.IsEnemy(m); + } + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + SolenHelper.OnRedDamage(from); + + if (!willKill) + { + if (!BurstSac) + { + if (Hits < 50) + { + PublicOverheadMessage(MessageType.Regular, 0x3B2, true, "* The solen's acid sac is burst open! *"); + BurstSac = true; + } + } + else if (from != null && from != this && InRange(from, 1)) + { + SpillAcid(from, 1); + } + } + + base.OnDamage(amount, from, willKill); + } + + public override bool OnBeforeDeath() + { + SpillAcid(4); + + return base.OnBeforeDeath(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(1); + writer.Write(BurstSac); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + BurstSac = reader.ReadBool(); + break; + } + } + } } - - public override bool OnBeforeDeath() - { - SpillAcid(4); - - return base.OnBeforeDeath(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); - writer.Write(BurstSac); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - BurstSac = reader.ReadBool(); - break; - } - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Ants/RedSolenWarrior.cs b/Projects/UOContent/Mobiles/Monsters/Ants/RedSolenWarrior.cs index 21415d005..c51004b31 100644 --- a/Projects/UOContent/Mobiles/Monsters/Ants/RedSolenWarrior.cs +++ b/Projects/UOContent/Mobiles/Monsters/Ants/RedSolenWarrior.cs @@ -3,129 +3,129 @@ using Server.Network; namespace Server.Mobiles { - public class RedSolenWarrior : BaseCreature - { - [Constructible] - public RedSolenWarrior() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class RedSolenWarrior : BaseCreature { - Body = 782; - BaseSoundID = 959; - - SetStr(196, 220); - SetDex(101, 125); - SetInt(36, 60); - - SetHits(96, 107); - - SetDamage(5, 15); - - SetDamageType(ResistanceType.Physical, 80); - SetDamageType(ResistanceType.Poison, 20); - - SetResistance(ResistanceType.Physical, 20, 35); - SetResistance(ResistanceType.Fire, 20, 35); - SetResistance(ResistanceType.Cold, 10, 25); - SetResistance(ResistanceType.Poison, 20, 35); - SetResistance(ResistanceType.Energy, 10, 25); - - SetSkill(SkillName.MagicResist, 60.0); - SetSkill(SkillName.Tactics, 80.0); - SetSkill(SkillName.Wrestling, 80.0); - - Fame = 3000; - Karma = -3000; - - VirtualArmor = 35; - - SolenHelper.PackPicnicBasket(this); - PackItem(new ZoogiFungus(Utility.RandomDouble() > 0.05 ? 3 : 13)); - - if (Utility.RandomDouble() < 0.05) - PackItem(new BraceletOfBinding()); - } - - public RedSolenWarrior(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a solen warrior corpse"; - public bool BurstSac { get; private set; } - - public override string DefaultName => "a red solen warrior"; - - public override int GetAngerSound() => 0xB5; - - public override int GetIdleSound() => 0xB5; - - public override int GetAttackSound() => 0x289; - - public override int GetHurtSound() => 0xBC; - - public override int GetDeathSound() => 0xE4; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.Gems, Utility.RandomMinMax(1, 4)); - } - - public override bool IsEnemy(Mobile m) - { - if (SolenHelper.CheckRedFriendship(m)) - return false; - return base.IsEnemy(m); - } - - public override void OnDamage(int amount, Mobile from, bool willKill) - { - SolenHelper.OnRedDamage(from); - - if (!willKill) - { - if (!BurstSac) + [Constructible] + public RedSolenWarrior() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) { - if (Hits < 50) - { - PublicOverheadMessage(MessageType.Regular, 0x3B2, true, "* The solen's acid sac is burst open! *"); - BurstSac = true; - } + Body = 782; + BaseSoundID = 959; + + SetStr(196, 220); + SetDex(101, 125); + SetInt(36, 60); + + SetHits(96, 107); + + SetDamage(5, 15); + + SetDamageType(ResistanceType.Physical, 80); + SetDamageType(ResistanceType.Poison, 20); + + SetResistance(ResistanceType.Physical, 20, 35); + SetResistance(ResistanceType.Fire, 20, 35); + SetResistance(ResistanceType.Cold, 10, 25); + SetResistance(ResistanceType.Poison, 20, 35); + SetResistance(ResistanceType.Energy, 10, 25); + + SetSkill(SkillName.MagicResist, 60.0); + SetSkill(SkillName.Tactics, 80.0); + SetSkill(SkillName.Wrestling, 80.0); + + Fame = 3000; + Karma = -3000; + + VirtualArmor = 35; + + SolenHelper.PackPicnicBasket(this); + PackItem(new ZoogiFungus(Utility.RandomDouble() > 0.05 ? 3 : 13)); + + if (Utility.RandomDouble() < 0.05) + PackItem(new BraceletOfBinding()); } - else if (from != null && from != this && InRange(from, 1)) + + public RedSolenWarrior(Serial serial) : base(serial) { - SpillAcid(from, 1); } - } - base.OnDamage(amount, from, willKill); + public override string CorpseName => "a solen warrior corpse"; + public bool BurstSac { get; private set; } + + public override string DefaultName => "a red solen warrior"; + + public override int GetAngerSound() => 0xB5; + + public override int GetIdleSound() => 0xB5; + + public override int GetAttackSound() => 0x289; + + public override int GetHurtSound() => 0xBC; + + public override int GetDeathSound() => 0xE4; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.Gems, Utility.RandomMinMax(1, 4)); + } + + public override bool IsEnemy(Mobile m) + { + if (SolenHelper.CheckRedFriendship(m)) + return false; + return base.IsEnemy(m); + } + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + SolenHelper.OnRedDamage(from); + + if (!willKill) + { + if (!BurstSac) + { + if (Hits < 50) + { + PublicOverheadMessage(MessageType.Regular, 0x3B2, true, "* The solen's acid sac is burst open! *"); + BurstSac = true; + } + } + else if (from != null && from != this && InRange(from, 1)) + { + SpillAcid(from, 1); + } + } + + base.OnDamage(amount, from, willKill); + } + + public override bool OnBeforeDeath() + { + SpillAcid(4); + + return base.OnBeforeDeath(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(1); + writer.Write(BurstSac); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + BurstSac = reader.ReadBool(); + break; + } + } + } } - - public override bool OnBeforeDeath() - { - SpillAcid(4); - - return base.OnBeforeDeath(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); - writer.Write(BurstSac); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - BurstSac = reader.ReadBool(); - break; - } - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Ants/RedSolenWorker.cs b/Projects/UOContent/Mobiles/Monsters/Ants/RedSolenWorker.cs index adc708690..e323ab22d 100644 --- a/Projects/UOContent/Mobiles/Monsters/Ants/RedSolenWorker.cs +++ b/Projects/UOContent/Mobiles/Monsters/Ants/RedSolenWorker.cs @@ -2,92 +2,92 @@ using Server.Items; namespace Server.Mobiles { - public class RedSolenWorker : BaseCreature - { - [Constructible] - public RedSolenWorker() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class RedSolenWorker : BaseCreature { - Body = 781; - BaseSoundID = 959; + [Constructible] + public RedSolenWorker() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 781; + BaseSoundID = 959; - SetStr(96, 120); - SetDex(81, 105); - SetInt(36, 60); + SetStr(96, 120); + SetDex(81, 105); + SetInt(36, 60); - SetHits(58, 72); + SetHits(58, 72); - SetDamage(5, 7); + SetDamage(5, 7); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 25, 30); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 10, 20); - SetResistance(ResistanceType.Poison, 10, 20); - SetResistance(ResistanceType.Energy, 20, 30); + SetResistance(ResistanceType.Physical, 25, 30); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Energy, 20, 30); - SetSkill(SkillName.MagicResist, 60.0); - SetSkill(SkillName.Tactics, 65.0); - SetSkill(SkillName.Wrestling, 60.0); + SetSkill(SkillName.MagicResist, 60.0); + SetSkill(SkillName.Tactics, 65.0); + SetSkill(SkillName.Wrestling, 60.0); - Fame = 1500; - Karma = -1500; + Fame = 1500; + Karma = -1500; - VirtualArmor = 28; + VirtualArmor = 28; - PackGold(Utility.Random(100, 180)); + PackGold(Utility.Random(100, 180)); - SolenHelper.PackPicnicBasket(this); + SolenHelper.PackPicnicBasket(this); - PackItem(new ZoogiFungus()); + PackItem(new ZoogiFungus()); + } + + public RedSolenWorker(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a solen worker corpse"; + public override string DefaultName => "a red solen worker"; + + public override int GetAngerSound() => 0x269; + + public override int GetIdleSound() => 0x269; + + public override int GetAttackSound() => 0x186; + + public override int GetHurtSound() => 0x1BE; + + public override int GetDeathSound() => 0x8E; + + public override void GenerateLoot() + { + AddLoot(LootPack.Gems, Utility.RandomMinMax(1, 2)); + } + + public override bool IsEnemy(Mobile m) + { + if (SolenHelper.CheckRedFriendship(m)) + return false; + return base.IsEnemy(m); + } + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + SolenHelper.OnRedDamage(from); + + base.OnDamage(amount, from, willKill); + } + + 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(); + } } - - public RedSolenWorker(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a solen worker corpse"; - public override string DefaultName => "a red solen worker"; - - public override int GetAngerSound() => 0x269; - - public override int GetIdleSound() => 0x269; - - public override int GetAttackSound() => 0x186; - - public override int GetHurtSound() => 0x1BE; - - public override int GetDeathSound() => 0x8E; - - public override void GenerateLoot() - { - AddLoot(LootPack.Gems, Utility.RandomMinMax(1, 2)); - } - - public override bool IsEnemy(Mobile m) - { - if (SolenHelper.CheckRedFriendship(m)) - return false; - return base.IsEnemy(m); - } - - public override void OnDamage(int amount, Mobile from, bool willKill) - { - SolenHelper.OnRedDamage(from); - - base.OnDamage(amount, from, willKill); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Ants/SolenHelper.cs b/Projects/UOContent/Mobiles/Monsters/Ants/SolenHelper.cs index 97e7b6d7d..21ed67f77 100644 --- a/Projects/UOContent/Mobiles/Monsters/Ants/SolenHelper.cs +++ b/Projects/UOContent/Mobiles/Monsters/Ants/SolenHelper.cs @@ -3,83 +3,89 @@ using Server.Network; namespace Server.Mobiles { - public class SolenHelper - { - public static void PackPicnicBasket(BaseCreature solen) + public class SolenHelper { - if (Utility.Random(100) < 1) - { - PicnicBasket basket = new PicnicBasket(); + public static void PackPicnicBasket(BaseCreature solen) + { + if (Utility.Random(100) < 1) + { + var basket = new PicnicBasket(); - basket.DropItem(new BeverageBottle(BeverageType.Wine)); - basket.DropItem(new CheeseWedge()); + basket.DropItem(new BeverageBottle(BeverageType.Wine)); + basket.DropItem(new CheeseWedge()); - solen.PackItem(basket); - } + solen.PackItem(basket); + } + } + + public static bool CheckRedFriendship(Mobile m) + { + if (m is BaseCreature bc) + { + if (bc.Controlled && bc.ControlMaster is PlayerMobile) + return CheckRedFriendship(bc.ControlMaster); + if (bc.Summoned && bc.SummonMaster is PlayerMobile) + return CheckRedFriendship(bc.SummonMaster); + } + + return m is PlayerMobile player && player.SolenFriendship == SolenFriendship.Red; + } + + public static bool CheckBlackFriendship(Mobile m) + { + if (m is BaseCreature bc) + { + if (bc.Controlled && bc.ControlMaster is PlayerMobile) + return CheckBlackFriendship(bc.ControlMaster); + if (bc.Summoned && bc.SummonMaster is PlayerMobile) + return CheckBlackFriendship(bc.SummonMaster); + } + + return m is PlayerMobile player && player.SolenFriendship == SolenFriendship.Black; + } + + public static void OnRedDamage(Mobile from) + { + if (from is BaseCreature bc) + { + if (bc.Controlled && bc.ControlMaster is PlayerMobile) + OnRedDamage(bc.ControlMaster); + else if (bc.Summoned && bc.SummonMaster is PlayerMobile) + OnRedDamage(bc.SummonMaster); + } + + if (from is PlayerMobile player && player.SolenFriendship == SolenFriendship.Red) + { + player.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1054103 + ); // The solen revoke their friendship. You will now be considered an intruder. + + player.SolenFriendship = SolenFriendship.None; + } + } + + public static void OnBlackDamage(Mobile from) + { + if (from is BaseCreature bc) + { + if (bc.Controlled && bc.ControlMaster is PlayerMobile) + OnBlackDamage(bc.ControlMaster); + else if (bc.Summoned && bc.SummonMaster is PlayerMobile) + OnBlackDamage(bc.SummonMaster); + } + + if (from is PlayerMobile player && player.SolenFriendship == SolenFriendship.Black) + { + player.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1054103 + ); // The solen revoke their friendship. You will now be considered an intruder. + + player.SolenFriendship = SolenFriendship.None; + } + } } - - public static bool CheckRedFriendship(Mobile m) - { - if (m is BaseCreature bc) - { - if (bc.Controlled && bc.ControlMaster is PlayerMobile) - return CheckRedFriendship(bc.ControlMaster); - if (bc.Summoned && bc.SummonMaster is PlayerMobile) - return CheckRedFriendship(bc.SummonMaster); - } - - return m is PlayerMobile player && player.SolenFriendship == SolenFriendship.Red; - } - - public static bool CheckBlackFriendship(Mobile m) - { - if (m is BaseCreature bc) - { - if (bc.Controlled && bc.ControlMaster is PlayerMobile) - return CheckBlackFriendship(bc.ControlMaster); - if (bc.Summoned && bc.SummonMaster is PlayerMobile) - return CheckBlackFriendship(bc.SummonMaster); - } - - return m is PlayerMobile player && player.SolenFriendship == SolenFriendship.Black; - } - - public static void OnRedDamage(Mobile from) - { - if (from is BaseCreature bc) - { - if (bc.Controlled && bc.ControlMaster is PlayerMobile) - OnRedDamage(bc.ControlMaster); - else if (bc.Summoned && bc.SummonMaster is PlayerMobile) - OnRedDamage(bc.SummonMaster); - } - - if (from is PlayerMobile player && player.SolenFriendship == SolenFriendship.Red) - { - player.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1054103); // The solen revoke their friendship. You will now be considered an intruder. - - player.SolenFriendship = SolenFriendship.None; - } - } - - public static void OnBlackDamage(Mobile from) - { - if (from is BaseCreature bc) - { - if (bc.Controlled && bc.ControlMaster is PlayerMobile) - OnBlackDamage(bc.ControlMaster); - else if (bc.Summoned && bc.SummonMaster is PlayerMobile) - OnBlackDamage(bc.SummonMaster); - } - - if (from is PlayerMobile player && player.SolenFriendship == SolenFriendship.Black) - { - player.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1054103); // The solen revoke their friendship. You will now be considered an intruder. - - player.SolenFriendship = SolenFriendship.None; - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Arachnid/Magic/DreadSpider.cs b/Projects/UOContent/Mobiles/Monsters/Arachnid/Magic/DreadSpider.cs index 102eb4e26..2b1345cd4 100644 --- a/Projects/UOContent/Mobiles/Monsters/Arachnid/Magic/DreadSpider.cs +++ b/Projects/UOContent/Mobiles/Monsters/Arachnid/Magic/DreadSpider.cs @@ -2,75 +2,75 @@ using Server.Items; namespace Server.Mobiles { - public class DreadSpider : BaseCreature - { - [Constructible] - public DreadSpider() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class DreadSpider : BaseCreature { - Body = 11; - BaseSoundID = 1170; + [Constructible] + public DreadSpider() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 11; + BaseSoundID = 1170; - SetStr(196, 220); - SetDex(126, 145); - SetInt(286, 310); + SetStr(196, 220); + SetDex(126, 145); + SetInt(286, 310); - SetHits(118, 132); + SetHits(118, 132); - SetDamage(5, 17); + SetDamage(5, 17); - SetDamageType(ResistanceType.Physical, 20); - SetDamageType(ResistanceType.Poison, 80); + SetDamageType(ResistanceType.Physical, 20); + SetDamageType(ResistanceType.Poison, 80); - SetResistance(ResistanceType.Physical, 40, 50); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 20, 30); - SetResistance(ResistanceType.Poison, 90, 100); - SetResistance(ResistanceType.Energy, 20, 30); + SetResistance(ResistanceType.Physical, 40, 50); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 20, 30); + SetResistance(ResistanceType.Poison, 90, 100); + SetResistance(ResistanceType.Energy, 20, 30); - SetSkill(SkillName.EvalInt, 65.1, 80.0); - SetSkill(SkillName.Magery, 65.1, 80.0); - SetSkill(SkillName.Meditation, 65.1, 80.0); - SetSkill(SkillName.MagicResist, 45.1, 60.0); - SetSkill(SkillName.Tactics, 55.1, 70.0); - SetSkill(SkillName.Wrestling, 60.1, 75.0); + SetSkill(SkillName.EvalInt, 65.1, 80.0); + SetSkill(SkillName.Magery, 65.1, 80.0); + SetSkill(SkillName.Meditation, 65.1, 80.0); + SetSkill(SkillName.MagicResist, 45.1, 60.0); + SetSkill(SkillName.Tactics, 55.1, 70.0); + SetSkill(SkillName.Wrestling, 60.1, 75.0); - Fame = 5000; - Karma = -5000; + Fame = 5000; + Karma = -5000; - VirtualArmor = 36; + VirtualArmor = 36; - PackItem(new SpidersSilk(8)); + PackItem(new SpidersSilk(8)); + } + + public DreadSpider(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a dread spider corpse"; + public override string DefaultName => "a dread spider"; + + public override Poison PoisonImmune => Poison.Lethal; + public override Poison HitPoison => Poison.Lethal; + public override int TreasureMapLevel => 3; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + } + + 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 (BaseSoundID == 263) + BaseSoundID = 1170; + } } - - public DreadSpider(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a dread spider corpse"; - public override string DefaultName => "a dread spider"; - - public override Poison PoisonImmune => Poison.Lethal; - public override Poison HitPoison => Poison.Lethal; - public override int TreasureMapLevel => 3; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (BaseSoundID == 263) - BaseSoundID = 1170; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Arachnid/Magic/TerathanAvenger.cs b/Projects/UOContent/Mobiles/Monsters/Arachnid/Magic/TerathanAvenger.cs index 6741f7a98..8fa4260d5 100644 --- a/Projects/UOContent/Mobiles/Monsters/Arachnid/Magic/TerathanAvenger.cs +++ b/Projects/UOContent/Mobiles/Monsters/Arachnid/Magic/TerathanAvenger.cs @@ -1,76 +1,76 @@ namespace Server.Mobiles { - public class TerathanAvenger : BaseCreature - { - [Constructible] - public TerathanAvenger() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class TerathanAvenger : BaseCreature { - Body = 152; - BaseSoundID = 0x24D; + [Constructible] + public TerathanAvenger() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 152; + BaseSoundID = 0x24D; - SetStr(467, 645); - SetDex(77, 95); - SetInt(126, 150); + SetStr(467, 645); + SetDex(77, 95); + SetInt(126, 150); - SetHits(296, 372); - SetMana(46, 70); + SetHits(296, 372); + SetMana(46, 70); - SetDamage(18, 22); + SetDamage(18, 22); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Poison, 50); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Poison, 50); - SetResistance(ResistanceType.Physical, 40, 50); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 35, 45); - SetResistance(ResistanceType.Poison, 90, 100); - SetResistance(ResistanceType.Energy, 35, 45); + SetResistance(ResistanceType.Physical, 40, 50); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 35, 45); + SetResistance(ResistanceType.Poison, 90, 100); + SetResistance(ResistanceType.Energy, 35, 45); - SetSkill(SkillName.EvalInt, 70.3, 100.0); - SetSkill(SkillName.Magery, 70.3, 100.0); - SetSkill(SkillName.Poisoning, 60.1, 80.0); - SetSkill(SkillName.MagicResist, 65.1, 80.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); - SetSkill(SkillName.Wrestling, 90.1, 100.0); + SetSkill(SkillName.EvalInt, 70.3, 100.0); + SetSkill(SkillName.Magery, 70.3, 100.0); + SetSkill(SkillName.Poisoning, 60.1, 80.0); + SetSkill(SkillName.MagicResist, 65.1, 80.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.Wrestling, 90.1, 100.0); - Fame = 15000; - Karma = -15000; + Fame = 15000; + Karma = -15000; - VirtualArmor = 50; + VirtualArmor = 50; + } + + public TerathanAvenger(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a terathan avenger corpse"; + public override string DefaultName => "a terathan avenger"; + + public override Poison PoisonImmune => Poison.Deadly; + public override Poison HitPoison => Poison.Deadly; + public override int TreasureMapLevel => 3; + public override int Meat => 2; + + public override OppositionGroup OppositionGroup => OppositionGroup.TerathansAndOphidians; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich, 2); + } + + 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 (BaseSoundID == 263) + BaseSoundID = 0x24D; + } } - - public TerathanAvenger(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a terathan avenger corpse"; - public override string DefaultName => "a terathan avenger"; - - public override Poison PoisonImmune => Poison.Deadly; - public override Poison HitPoison => Poison.Deadly; - public override int TreasureMapLevel => 3; - public override int Meat => 2; - - public override OppositionGroup OppositionGroup => OppositionGroup.TerathansAndOphidians; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (BaseSoundID == 263) - BaseSoundID = 0x24D; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Arachnid/Magic/TerathanMatriarch.cs b/Projects/UOContent/Mobiles/Monsters/Arachnid/Magic/TerathanMatriarch.cs index ba6720a5e..fbec2457a 100644 --- a/Projects/UOContent/Mobiles/Monsters/Arachnid/Magic/TerathanMatriarch.cs +++ b/Projects/UOContent/Mobiles/Monsters/Arachnid/Magic/TerathanMatriarch.cs @@ -2,72 +2,72 @@ using Server.Items; namespace Server.Mobiles { - public class TerathanMatriarch : BaseCreature - { - [Constructible] - public TerathanMatriarch() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class TerathanMatriarch : BaseCreature { - Body = 72; - BaseSoundID = 599; + [Constructible] + public TerathanMatriarch() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 72; + BaseSoundID = 599; - SetStr(316, 405); - SetDex(96, 115); - SetInt(366, 455); + SetStr(316, 405); + SetDex(96, 115); + SetInt(366, 455); - SetHits(190, 243); + SetHits(190, 243); - SetDamage(11, 14); + SetDamage(11, 14); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 35, 45); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 35, 45); + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 35, 45); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 35, 45); - SetSkill(SkillName.EvalInt, 90.1, 100.0); - SetSkill(SkillName.Magery, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 90.1, 100.0); - SetSkill(SkillName.Tactics, 50.1, 70.0); - SetSkill(SkillName.Wrestling, 60.1, 80.0); + SetSkill(SkillName.EvalInt, 90.1, 100.0); + SetSkill(SkillName.Magery, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 90.1, 100.0); + SetSkill(SkillName.Tactics, 50.1, 70.0); + SetSkill(SkillName.Wrestling, 60.1, 80.0); - Fame = 10000; - Karma = -10000; + Fame = 10000; + Karma = -10000; - PackItem(new SpidersSilk(5)); - PackNecroReg(Utility.RandomMinMax(4, 10)); + PackItem(new SpidersSilk(5)); + PackNecroReg(Utility.RandomMinMax(4, 10)); + } + + public TerathanMatriarch(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a terathan matriarch corpse"; + public override string DefaultName => "a terathan matriarch"; + + public override int TreasureMapLevel => 4; + + public override OppositionGroup OppositionGroup => OppositionGroup.TerathansAndOphidians; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.Average, 2); + AddLoot(LootPack.MedScrolls, 2); + AddLoot(LootPack.Potions); + } + + 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(); + } } - - public TerathanMatriarch(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a terathan matriarch corpse"; - public override string DefaultName => "a terathan matriarch"; - - public override int TreasureMapLevel => 4; - - public override OppositionGroup OppositionGroup => OppositionGroup.TerathansAndOphidians; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.Average, 2); - AddLoot(LootPack.MedScrolls, 2); - AddLoot(LootPack.Potions); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Arachnid/Melee/FrostSpider.cs b/Projects/UOContent/Mobiles/Monsters/Arachnid/Melee/FrostSpider.cs index 4d2131c55..8a1c2d732 100644 --- a/Projects/UOContent/Mobiles/Monsters/Arachnid/Melee/FrostSpider.cs +++ b/Projects/UOContent/Mobiles/Monsters/Arachnid/Melee/FrostSpider.cs @@ -2,77 +2,77 @@ using Server.Items; namespace Server.Mobiles { - public class FrostSpider : BaseCreature - { - [Constructible] - public FrostSpider() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class FrostSpider : BaseCreature { - Body = 20; - BaseSoundID = 0x388; + [Constructible] + public FrostSpider() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 20; + BaseSoundID = 0x388; - SetStr(76, 100); - SetDex(126, 145); - SetInt(36, 60); + SetStr(76, 100); + SetDex(126, 145); + SetInt(36, 60); - SetHits(46, 60); - SetMana(0); + SetHits(46, 60); + SetMana(0); - SetDamage(6, 16); + SetDamage(6, 16); - SetDamageType(ResistanceType.Physical, 20); - SetDamageType(ResistanceType.Cold, 80); + SetDamageType(ResistanceType.Physical, 20); + SetDamageType(ResistanceType.Cold, 80); - SetResistance(ResistanceType.Physical, 25, 30); - SetResistance(ResistanceType.Fire, 5, 10); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 10, 20); + SetResistance(ResistanceType.Physical, 25, 30); + SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 10, 20); - SetSkill(SkillName.MagicResist, 25.1, 40.0); - SetSkill(SkillName.Tactics, 35.1, 50.0); - SetSkill(SkillName.Wrestling, 50.1, 65.0); + SetSkill(SkillName.MagicResist, 25.1, 40.0); + SetSkill(SkillName.Tactics, 35.1, 50.0); + SetSkill(SkillName.Wrestling, 50.1, 65.0); - Fame = 775; - Karma = -775; + Fame = 775; + Karma = -775; - VirtualArmor = 28; + VirtualArmor = 28; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 74.7; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 74.7; - PackItem(new SpidersSilk(7)); + PackItem(new SpidersSilk(7)); + } + + public FrostSpider(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a frost spider corpse"; + public override string DefaultName => "a frost spider"; + + public override FoodType FavoriteFood => FoodType.Meat; + public override PackInstinct PackInstinct => PackInstinct.Arachnid; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + AddLoot(LootPack.Poor); + } + + 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 (BaseSoundID == 387) + BaseSoundID = 0x388; + } } - - public FrostSpider(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a frost spider corpse"; - public override string DefaultName => "a frost spider"; - - public override FoodType FavoriteFood => FoodType.Meat; - public override PackInstinct PackInstinct => PackInstinct.Arachnid; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - AddLoot(LootPack.Poor); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (BaseSoundID == 387) - BaseSoundID = 0x388; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Arachnid/Melee/GiantBlackWidow.cs b/Projects/UOContent/Mobiles/Monsters/Arachnid/Melee/GiantBlackWidow.cs index c965765ba..9649635ae 100644 --- a/Projects/UOContent/Mobiles/Monsters/Arachnid/Melee/GiantBlackWidow.cs +++ b/Projects/UOContent/Mobiles/Monsters/Arachnid/Melee/GiantBlackWidow.cs @@ -2,72 +2,72 @@ using Server.Items; namespace Server.Mobiles { - public class GiantBlackWidow : BaseCreature - { - [Constructible] - public GiantBlackWidow() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class GiantBlackWidow : BaseCreature { - Body = 0x9D; - BaseSoundID = 0x388; // TODO: validate + [Constructible] + public GiantBlackWidow() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0x9D; + BaseSoundID = 0x388; // TODO: validate - SetStr(76, 100); - SetDex(96, 115); - SetInt(36, 60); + SetStr(76, 100); + SetDex(96, 115); + SetInt(36, 60); - SetHits(46, 60); + SetHits(46, 60); - SetDamage(5, 17); + SetDamage(5, 17); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 20, 30); - SetResistance(ResistanceType.Fire, 10, 20); - SetResistance(ResistanceType.Cold, 10, 20); - SetResistance(ResistanceType.Poison, 50, 60); - SetResistance(ResistanceType.Energy, 10, 20); + SetResistance(ResistanceType.Physical, 20, 30); + SetResistance(ResistanceType.Fire, 10, 20); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Poison, 50, 60); + SetResistance(ResistanceType.Energy, 10, 20); - SetSkill(SkillName.Anatomy, 30.3, 75.0); - SetSkill(SkillName.Poisoning, 60.1, 80.0); - SetSkill(SkillName.MagicResist, 45.1, 60.0); - SetSkill(SkillName.Tactics, 65.1, 80.0); - SetSkill(SkillName.Wrestling, 70.1, 85.0); + SetSkill(SkillName.Anatomy, 30.3, 75.0); + SetSkill(SkillName.Poisoning, 60.1, 80.0); + SetSkill(SkillName.MagicResist, 45.1, 60.0); + SetSkill(SkillName.Tactics, 65.1, 80.0); + SetSkill(SkillName.Wrestling, 70.1, 85.0); - Fame = 3500; - Karma = -3500; + Fame = 3500; + Karma = -3500; - VirtualArmor = 24; + VirtualArmor = 24; - PackItem(new SpidersSilk(5)); - PackItem(new LesserPoisonPotion()); - PackItem(new LesserPoisonPotion()); + PackItem(new SpidersSilk(5)); + PackItem(new LesserPoisonPotion()); + PackItem(new LesserPoisonPotion()); + } + + public GiantBlackWidow(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a giant black widow spider corpse"; + public override string DefaultName => "a giant black wide"; + + public override FoodType FavoriteFood => FoodType.Meat; + public override Poison PoisonImmune => Poison.Deadly; + public override Poison HitPoison => Poison.Deadly; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + } + + 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(); + } } - - public GiantBlackWidow(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a giant black widow spider corpse"; - public override string DefaultName => "a giant black wide"; - - public override FoodType FavoriteFood => FoodType.Meat; - public override Poison PoisonImmune => Poison.Deadly; - public override Poison HitPoison => Poison.Deadly; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Arachnid/Melee/GiantSpider.cs b/Projects/UOContent/Mobiles/Monsters/Arachnid/Melee/GiantSpider.cs index 8f83dc3ad..dbe2c6852 100644 --- a/Projects/UOContent/Mobiles/Monsters/Arachnid/Melee/GiantSpider.cs +++ b/Projects/UOContent/Mobiles/Monsters/Arachnid/Melee/GiantSpider.cs @@ -2,72 +2,72 @@ using Server.Items; namespace Server.Mobiles { - public class GiantSpider : BaseCreature - { - [Constructible] - public GiantSpider() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class GiantSpider : BaseCreature { - Body = 28; - BaseSoundID = 0x388; + [Constructible] + public GiantSpider() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 28; + BaseSoundID = 0x388; - SetStr(76, 100); - SetDex(76, 95); - SetInt(36, 60); + SetStr(76, 100); + SetDex(76, 95); + SetInt(36, 60); - SetHits(46, 60); - SetMana(0); + SetHits(46, 60); + SetMana(0); - SetDamage(5, 13); + SetDamage(5, 13); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 15, 20); - SetResistance(ResistanceType.Poison, 25, 35); + SetResistance(ResistanceType.Physical, 15, 20); + SetResistance(ResistanceType.Poison, 25, 35); - SetSkill(SkillName.Poisoning, 60.1, 80.0); - SetSkill(SkillName.MagicResist, 25.1, 40.0); - SetSkill(SkillName.Tactics, 35.1, 50.0); - SetSkill(SkillName.Wrestling, 50.1, 65.0); + SetSkill(SkillName.Poisoning, 60.1, 80.0); + SetSkill(SkillName.MagicResist, 25.1, 40.0); + SetSkill(SkillName.Tactics, 35.1, 50.0); + SetSkill(SkillName.Wrestling, 50.1, 65.0); - Fame = 600; - Karma = -600; + Fame = 600; + Karma = -600; - VirtualArmor = 16; + VirtualArmor = 16; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 59.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 59.1; - PackItem(new SpidersSilk(5)); + PackItem(new SpidersSilk(5)); + } + + public GiantSpider(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a giant spider corpse"; + public override string DefaultName => "a giant spider"; + + public override FoodType FavoriteFood => FoodType.Meat; + public override PackInstinct PackInstinct => PackInstinct.Arachnid; + public override Poison PoisonImmune => Poison.Regular; + public override Poison HitPoison => Poison.Regular; + + public override void GenerateLoot() + { + AddLoot(LootPack.Poor); + } + + 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(); + } } - - public GiantSpider(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a giant spider corpse"; - public override string DefaultName => "a giant spider"; - - public override FoodType FavoriteFood => FoodType.Meat; - public override PackInstinct PackInstinct => PackInstinct.Arachnid; - public override Poison PoisonImmune => Poison.Regular; - public override Poison HitPoison => Poison.Regular; - - public override void GenerateLoot() - { - AddLoot(LootPack.Poor); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Arachnid/Melee/TerathanDrone.cs b/Projects/UOContent/Mobiles/Monsters/Arachnid/Melee/TerathanDrone.cs index 741ba7a95..4314d2139 100644 --- a/Projects/UOContent/Mobiles/Monsters/Arachnid/Melee/TerathanDrone.cs +++ b/Projects/UOContent/Mobiles/Monsters/Arachnid/Melee/TerathanDrone.cs @@ -2,74 +2,74 @@ using Server.Items; namespace Server.Mobiles { - public class TerathanDrone : BaseCreature - { - [Constructible] - public TerathanDrone() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class TerathanDrone : BaseCreature { - Body = 71; - BaseSoundID = 594; + [Constructible] + public TerathanDrone() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 71; + BaseSoundID = 594; - SetStr(36, 65); - SetDex(96, 145); - SetInt(21, 45); + SetStr(36, 65); + SetDex(96, 145); + SetInt(21, 45); - SetHits(22, 39); - SetMana(0); + SetHits(22, 39); + SetMana(0); - SetDamage(6, 12); + SetDamage(6, 12); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 20, 25); - SetResistance(ResistanceType.Fire, 10, 20); - SetResistance(ResistanceType.Cold, 15, 25); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 15, 25); + SetResistance(ResistanceType.Physical, 20, 25); + SetResistance(ResistanceType.Fire, 10, 20); + SetResistance(ResistanceType.Cold, 15, 25); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 15, 25); - SetSkill(SkillName.Poisoning, 40.1, 60.0); - SetSkill(SkillName.MagicResist, 30.1, 45.0); - SetSkill(SkillName.Tactics, 30.1, 50.0); - SetSkill(SkillName.Wrestling, 40.1, 50.0); + SetSkill(SkillName.Poisoning, 40.1, 60.0); + SetSkill(SkillName.MagicResist, 30.1, 45.0); + SetSkill(SkillName.Tactics, 30.1, 50.0); + SetSkill(SkillName.Wrestling, 40.1, 50.0); - Fame = 2000; - Karma = -2000; + Fame = 2000; + Karma = -2000; - VirtualArmor = 24; + VirtualArmor = 24; - PackItem(new SpidersSilk(2)); + PackItem(new SpidersSilk(2)); + } + + public TerathanDrone(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a terathan drone corpse"; + public override string DefaultName => "a terathan drone"; + + public override int Meat => 4; + + public override OppositionGroup OppositionGroup => OppositionGroup.TerathansAndOphidians; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + // TODO: weapon? + } + + 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 (BaseSoundID == 589) + BaseSoundID = 594; + } } - - public TerathanDrone(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a terathan drone corpse"; - public override string DefaultName => "a terathan drone"; - - public override int Meat => 4; - - public override OppositionGroup OppositionGroup => OppositionGroup.TerathansAndOphidians; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - // TODO: weapon? - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (BaseSoundID == 589) - BaseSoundID = 594; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Arachnid/Melee/TerathanWarrior.cs b/Projects/UOContent/Mobiles/Monsters/Arachnid/Melee/TerathanWarrior.cs index 2fb7265bb..dd5c487e8 100644 --- a/Projects/UOContent/Mobiles/Monsters/Arachnid/Melee/TerathanWarrior.cs +++ b/Projects/UOContent/Mobiles/Monsters/Arachnid/Melee/TerathanWarrior.cs @@ -2,72 +2,72 @@ using Server.Engines.Plants; namespace Server.Mobiles { - public class TerathanWarrior : BaseCreature - { - [Constructible] - public TerathanWarrior() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class TerathanWarrior : BaseCreature { - Body = 70; - BaseSoundID = 589; + [Constructible] + public TerathanWarrior() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 70; + BaseSoundID = 589; - SetStr(166, 215); - SetDex(96, 145); - SetInt(41, 65); + SetStr(166, 215); + SetDex(96, 145); + SetInt(41, 65); - SetHits(100, 129); - SetMana(0); + SetHits(100, 129); + SetMana(0); - SetDamage(7, 17); + SetDamage(7, 17); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 30, 35); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 25, 35); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 25, 35); + SetResistance(ResistanceType.Physical, 30, 35); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 25, 35); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 25, 35); - SetSkill(SkillName.Poisoning, 60.1, 80.0); - SetSkill(SkillName.MagicResist, 60.1, 75.0); - SetSkill(SkillName.Tactics, 80.1, 100.0); - SetSkill(SkillName.Wrestling, 80.1, 90.0); + SetSkill(SkillName.Poisoning, 60.1, 80.0); + SetSkill(SkillName.MagicResist, 60.1, 75.0); + SetSkill(SkillName.Tactics, 80.1, 100.0); + SetSkill(SkillName.Wrestling, 80.1, 90.0); - Fame = 4000; - Karma = -4000; + Fame = 4000; + Karma = -4000; - VirtualArmor = 30; + VirtualArmor = 30; - if (Core.ML && Utility.RandomDouble() < .33) - PackItem(Seed.RandomPeculiarSeed(3)); + if (Core.ML && Utility.RandomDouble() < .33) + PackItem(Seed.RandomPeculiarSeed(3)); + } + + public TerathanWarrior(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a terathan warrior corpse"; + public override string DefaultName => "a terathan warrior"; + + public override int TreasureMapLevel => 1; + public override int Meat => 4; + + public override OppositionGroup OppositionGroup => OppositionGroup.TerathansAndOphidians; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + } + + 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(); + } } - - public TerathanWarrior(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a terathan warrior corpse"; - public override string DefaultName => "a terathan warrior"; - - public override int TreasureMapLevel => 1; - public override int Meat => 4; - - public override OppositionGroup OppositionGroup => OppositionGroup.TerathansAndOphidians; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/AcidElemental.cs b/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/AcidElemental.cs index 70995ce1f..8111796a1 100644 --- a/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/AcidElemental.cs +++ b/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/AcidElemental.cs @@ -1,84 +1,84 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.ToxicElemental")] - public class AcidElemental : BaseCreature - { - [Constructible] - public AcidElemental() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.ToxicElemental")] + public class AcidElemental : BaseCreature { - Body = 0x9E; - BaseSoundID = 278; + [Constructible] + public AcidElemental() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0x9E; + BaseSoundID = 278; - SetStr(326, 355); - SetDex(66, 85); - SetInt(271, 295); + SetStr(326, 355); + SetDex(66, 85); + SetInt(271, 295); - SetHits(196, 213); + SetHits(196, 213); - SetDamage(9, 15); + SetDamage(9, 15); - SetDamageType(ResistanceType.Physical, 25); - SetDamageType(ResistanceType.Fire, 50); - SetDamageType(ResistanceType.Energy, 25); + SetDamageType(ResistanceType.Physical, 25); + SetDamageType(ResistanceType.Fire, 50); + SetDamageType(ResistanceType.Energy, 25); - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 20, 30); - SetResistance(ResistanceType.Poison, 10, 20); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 20, 30); + SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.Anatomy, 30.3, 60.0); - SetSkill(SkillName.EvalInt, 70.1, 85.0); - SetSkill(SkillName.Magery, 70.1, 85.0); - SetSkill(SkillName.MagicResist, 60.1, 75.0); - SetSkill(SkillName.Tactics, 80.1, 90.0); - SetSkill(SkillName.Wrestling, 70.1, 90.0); + SetSkill(SkillName.Anatomy, 30.3, 60.0); + SetSkill(SkillName.EvalInt, 70.1, 85.0); + SetSkill(SkillName.Magery, 70.1, 85.0); + SetSkill(SkillName.MagicResist, 60.1, 75.0); + SetSkill(SkillName.Tactics, 80.1, 90.0); + SetSkill(SkillName.Wrestling, 70.1, 90.0); - Fame = 10000; - Karma = -10000; + Fame = 10000; + Karma = -10000; - VirtualArmor = 40; + VirtualArmor = 40; + } + + public AcidElemental(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "an acid elemental corpse"; + public override string DefaultName => "an acid elemental"; + + public override bool BleedImmune => true; + public override Poison HitPoison => Poison.Lethal; + public override double HitPoisonChance => 0.6; + + public override int TreasureMapLevel => Core.AOS ? 2 : 3; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.Average); + } + + 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 (BaseSoundID == 263) + BaseSoundID = 278; + + if (Body == 13) + Body = 0x9E; + + if (Hue == 0x4001) + Hue = 0; + } } - - public AcidElemental(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "an acid elemental corpse"; - public override string DefaultName => "an acid elemental"; - - public override bool BleedImmune => true; - public override Poison HitPoison => Poison.Lethal; - public override double HitPoisonChance => 0.6; - - public override int TreasureMapLevel => Core.AOS ? 2 : 3; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.Average); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (BaseSoundID == 263) - BaseSoundID = 278; - - if (Body == 13) - Body = 0x9E; - - if (Hue == 0x4001) - Hue = 0; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/AirElemental.cs b/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/AirElemental.cs index cf07b7f3d..fc173824d 100644 --- a/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/AirElemental.cs +++ b/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/AirElemental.cs @@ -1,79 +1,79 @@ namespace Server.Mobiles { - public class AirElemental : BaseCreature - { - [Constructible] - public AirElemental() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class AirElemental : BaseCreature { - Body = 13; - Hue = 0x4001; - BaseSoundID = 655; + [Constructible] + public AirElemental() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 13; + Hue = 0x4001; + BaseSoundID = 655; - SetStr(126, 155); - SetDex(166, 185); - SetInt(101, 125); + SetStr(126, 155); + SetDex(166, 185); + SetInt(101, 125); - SetHits(76, 93); + SetHits(76, 93); - SetDamage(8, 10); + SetDamage(8, 10); - SetDamageType(ResistanceType.Physical, 20); - SetDamageType(ResistanceType.Cold, 40); - SetDamageType(ResistanceType.Energy, 40); + SetDamageType(ResistanceType.Physical, 20); + SetDamageType(ResistanceType.Cold, 40); + SetDamageType(ResistanceType.Energy, 40); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 15, 25); - SetResistance(ResistanceType.Cold, 10, 20); - SetResistance(ResistanceType.Poison, 10, 20); - SetResistance(ResistanceType.Energy, 25, 35); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 15, 25); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Energy, 25, 35); - SetSkill(SkillName.EvalInt, 60.1, 75.0); - SetSkill(SkillName.Magery, 60.1, 75.0); - SetSkill(SkillName.MagicResist, 60.1, 75.0); - SetSkill(SkillName.Tactics, 60.1, 80.0); - SetSkill(SkillName.Wrestling, 60.1, 80.0); + SetSkill(SkillName.EvalInt, 60.1, 75.0); + SetSkill(SkillName.Magery, 60.1, 75.0); + SetSkill(SkillName.MagicResist, 60.1, 75.0); + SetSkill(SkillName.Tactics, 60.1, 80.0); + SetSkill(SkillName.Wrestling, 60.1, 80.0); - Fame = 4500; - Karma = -4500; + Fame = 4500; + Karma = -4500; - VirtualArmor = 40; - ControlSlots = 2; + VirtualArmor = 40; + ControlSlots = 2; + } + + public AirElemental(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an air elemental corpse"; + public override double DispelDifficulty => 117.5; + public override double DispelFocus => 45.0; + + public override string DefaultName => "an air elemental"; + + public override bool BleedImmune => true; + public override int TreasureMapLevel => 2; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Meager); + AddLoot(LootPack.LowScrolls); + AddLoot(LootPack.MedScrolls); + } + + 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 (BaseSoundID == 263) + BaseSoundID = 655; + } } - - public AirElemental(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an air elemental corpse"; - public override double DispelDifficulty => 117.5; - public override double DispelFocus => 45.0; - - public override string DefaultName => "an air elemental"; - - public override bool BleedImmune => true; - public override int TreasureMapLevel => 2; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Meager); - AddLoot(LootPack.LowScrolls); - AddLoot(LootPack.MedScrolls); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (BaseSoundID == 263) - BaseSoundID = 655; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/BloodElemental.cs b/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/BloodElemental.cs index 085025d60..81898c98a 100644 --- a/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/BloodElemental.cs +++ b/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/BloodElemental.cs @@ -1,69 +1,69 @@ namespace Server.Mobiles { - public class BloodElemental : BaseCreature - { - [Constructible] - public BloodElemental() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class BloodElemental : BaseCreature { - Body = 159; - BaseSoundID = 278; + [Constructible] + public BloodElemental() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 159; + BaseSoundID = 278; - SetStr(526, 615); - SetDex(66, 85); - SetInt(226, 350); + SetStr(526, 615); + SetDex(66, 85); + SetInt(226, 350); - SetHits(316, 369); + SetHits(316, 369); - SetDamage(17, 27); + SetDamage(17, 27); - SetDamageType(ResistanceType.Physical, 0); - SetDamageType(ResistanceType.Poison, 50); - SetDamageType(ResistanceType.Energy, 50); + SetDamageType(ResistanceType.Physical, 0); + SetDamageType(ResistanceType.Poison, 50); + SetDamageType(ResistanceType.Energy, 50); - SetResistance(ResistanceType.Physical, 55, 65); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 50, 60); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 55, 65); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 50, 60); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.EvalInt, 85.1, 100.0); - SetSkill(SkillName.Magery, 85.1, 100.0); - SetSkill(SkillName.Meditation, 10.4, 50.0); - SetSkill(SkillName.MagicResist, 80.1, 95.0); - SetSkill(SkillName.Tactics, 80.1, 100.0); - SetSkill(SkillName.Wrestling, 80.1, 100.0); + SetSkill(SkillName.EvalInt, 85.1, 100.0); + SetSkill(SkillName.Magery, 85.1, 100.0); + SetSkill(SkillName.Meditation, 10.4, 50.0); + SetSkill(SkillName.MagicResist, 80.1, 95.0); + SetSkill(SkillName.Tactics, 80.1, 100.0); + SetSkill(SkillName.Wrestling, 80.1, 100.0); - Fame = 12500; - Karma = -12500; + Fame = 12500; + Karma = -12500; - VirtualArmor = 60; + VirtualArmor = 60; + } + + public BloodElemental(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a blood elemental corpse"; + public override string DefaultName => "a blood elemental"; + + public override int TreasureMapLevel => 5; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.Rich); + } + + 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(); + } } - - public BloodElemental(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a blood elemental corpse"; - public override string DefaultName => "a blood elemental"; - - public override int TreasureMapLevel => 5; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.Rich); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/Efreet.cs b/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/Efreet.cs index fa6db1b06..bbf975ea9 100644 --- a/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/Efreet.cs +++ b/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/Efreet.cs @@ -2,89 +2,89 @@ using Server.Items; namespace Server.Mobiles { - public class Efreet : BaseCreature - { - [Constructible] - public Efreet() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Efreet : BaseCreature { - Body = 131; - BaseSoundID = 768; - - SetStr(326, 355); - SetDex(266, 285); - SetInt(171, 195); - - SetHits(196, 213); - - SetDamage(11, 13); - - SetDamageType(ResistanceType.Physical, 0); - SetDamageType(ResistanceType.Fire, 50); - SetDamageType(ResistanceType.Energy, 50); - - SetResistance(ResistanceType.Physical, 50, 60); - SetResistance(ResistanceType.Fire, 60, 70); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 40, 50); - - SetSkill(SkillName.EvalInt, 60.1, 75.0); - SetSkill(SkillName.Magery, 60.1, 75.0); - SetSkill(SkillName.MagicResist, 60.1, 75.0); - SetSkill(SkillName.Tactics, 60.1, 80.0); - SetSkill(SkillName.Wrestling, 60.1, 80.0); - - Fame = 10000; - Karma = -10000; - - VirtualArmor = 56; - } - - public Efreet(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an efreet corpse"; - public override string DefaultName => "an efreet"; - - public override int TreasureMapLevel => Core.AOS ? 4 : 5; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.Average); - AddLoot(LootPack.Gems); - - if (Utility.RandomDouble() < 0.02) - switch (Utility.Random(5)) + [Constructible] + public Efreet() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) { - case 0: - PackItem(new DaemonArms()); - break; - case 1: - PackItem(new DaemonChest()); - break; - case 2: - PackItem(new DaemonGloves()); - break; - case 3: - PackItem(new DaemonLegs()); - break; - case 4: - PackItem(new DaemonHelm()); - break; + Body = 131; + BaseSoundID = 768; + + SetStr(326, 355); + SetDex(266, 285); + SetInt(171, 195); + + SetHits(196, 213); + + SetDamage(11, 13); + + SetDamageType(ResistanceType.Physical, 0); + SetDamageType(ResistanceType.Fire, 50); + SetDamageType(ResistanceType.Energy, 50); + + SetResistance(ResistanceType.Physical, 50, 60); + SetResistance(ResistanceType.Fire, 60, 70); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 40, 50); + + SetSkill(SkillName.EvalInt, 60.1, 75.0); + SetSkill(SkillName.Magery, 60.1, 75.0); + SetSkill(SkillName.MagicResist, 60.1, 75.0); + SetSkill(SkillName.Tactics, 60.1, 80.0); + SetSkill(SkillName.Wrestling, 60.1, 80.0); + + Fame = 10000; + Karma = -10000; + + VirtualArmor = 56; + } + + public Efreet(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an efreet corpse"; + public override string DefaultName => "an efreet"; + + public override int TreasureMapLevel => Core.AOS ? 4 : 5; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.Average); + AddLoot(LootPack.Gems); + + if (Utility.RandomDouble() < 0.02) + switch (Utility.Random(5)) + { + case 0: + PackItem(new DaemonArms()); + break; + case 1: + PackItem(new DaemonChest()); + break; + case 2: + PackItem(new DaemonGloves()); + break; + case 3: + PackItem(new DaemonLegs()); + break; + case 4: + PackItem(new DaemonHelm()); + break; + } + } + + 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(); } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/FireElemental.cs b/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/FireElemental.cs index 67e18aa46..d9baf6382 100644 --- a/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/FireElemental.cs +++ b/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/FireElemental.cs @@ -2,81 +2,81 @@ using Server.Items; namespace Server.Mobiles { - public class FireElemental : BaseCreature - { - [Constructible] - public FireElemental() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class FireElemental : BaseCreature { - Body = 15; - BaseSoundID = 838; + [Constructible] + public FireElemental() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 15; + BaseSoundID = 838; - SetStr(126, 155); - SetDex(166, 185); - SetInt(101, 125); + SetStr(126, 155); + SetDex(166, 185); + SetInt(101, 125); - SetHits(76, 93); + SetHits(76, 93); - SetDamage(7, 9); + SetDamage(7, 9); - SetDamageType(ResistanceType.Physical, 25); - SetDamageType(ResistanceType.Fire, 75); + SetDamageType(ResistanceType.Physical, 25); + SetDamageType(ResistanceType.Fire, 75); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 60, 80); - SetResistance(ResistanceType.Cold, 5, 10); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 60, 80); + SetResistance(ResistanceType.Cold, 5, 10); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.EvalInt, 60.1, 75.0); - SetSkill(SkillName.Magery, 60.1, 75.0); - SetSkill(SkillName.MagicResist, 75.2, 105.0); - SetSkill(SkillName.Tactics, 80.1, 100.0); - SetSkill(SkillName.Wrestling, 70.1, 100.0); + SetSkill(SkillName.EvalInt, 60.1, 75.0); + SetSkill(SkillName.Magery, 60.1, 75.0); + SetSkill(SkillName.MagicResist, 75.2, 105.0); + SetSkill(SkillName.Tactics, 80.1, 100.0); + SetSkill(SkillName.Wrestling, 70.1, 100.0); - Fame = 4500; - Karma = -4500; + Fame = 4500; + Karma = -4500; - VirtualArmor = 40; - ControlSlots = 4; + VirtualArmor = 40; + ControlSlots = 4; - PackItem(new SulfurousAsh(3)); + PackItem(new SulfurousAsh(3)); - AddItem(new LightSource()); + AddItem(new LightSource()); + } + + public FireElemental(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a fire elemental corpse"; + public override double DispelDifficulty => 117.5; + public override double DispelFocus => 45.0; + + public override string DefaultName => "a fire elemental"; + + public override bool BleedImmune => true; + public override int TreasureMapLevel => 2; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Meager); + AddLoot(LootPack.Gems); + } + + 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 (BaseSoundID == 274) + BaseSoundID = 838; + } } - - public FireElemental(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a fire elemental corpse"; - public override double DispelDifficulty => 117.5; - public override double DispelFocus => 45.0; - - public override string DefaultName => "a fire elemental"; - - public override bool BleedImmune => true; - public override int TreasureMapLevel => 2; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Meager); - AddLoot(LootPack.Gems); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (BaseSoundID == 274) - BaseSoundID = 838; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/IceElemental.cs b/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/IceElemental.cs index 31f811d8b..b55d93c93 100644 --- a/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/IceElemental.cs +++ b/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/IceElemental.cs @@ -2,70 +2,70 @@ using Server.Items; namespace Server.Mobiles { - public class IceElemental : BaseCreature - { - [Constructible] - public IceElemental() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class IceElemental : BaseCreature { - Body = 161; - BaseSoundID = 268; + [Constructible] + public IceElemental() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 161; + BaseSoundID = 268; - SetStr(156, 185); - SetDex(96, 115); - SetInt(171, 192); + SetStr(156, 185); + SetDex(96, 115); + SetInt(171, 192); - SetHits(94, 111); + SetHits(94, 111); - SetDamage(10, 21); + SetDamage(10, 21); - SetDamageType(ResistanceType.Physical, 25); - SetDamageType(ResistanceType.Cold, 75); + SetDamageType(ResistanceType.Physical, 25); + SetDamageType(ResistanceType.Cold, 75); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 5, 10); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 20, 30); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 20, 30); - SetSkill(SkillName.EvalInt, 10.5, 60.0); - SetSkill(SkillName.Magery, 10.5, 60.0); - SetSkill(SkillName.MagicResist, 30.1, 80.0); - SetSkill(SkillName.Tactics, 70.1, 100.0); - SetSkill(SkillName.Wrestling, 60.1, 100.0); + SetSkill(SkillName.EvalInt, 10.5, 60.0); + SetSkill(SkillName.Magery, 10.5, 60.0); + SetSkill(SkillName.MagicResist, 30.1, 80.0); + SetSkill(SkillName.Tactics, 70.1, 100.0); + SetSkill(SkillName.Wrestling, 60.1, 100.0); - Fame = 4000; - Karma = -4000; + Fame = 4000; + Karma = -4000; - VirtualArmor = 40; + VirtualArmor = 40; - PackItem(new BlackPearl()); - PackReg(3); + PackItem(new BlackPearl()); + PackReg(3); + } + + public IceElemental(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ice elemental corpse"; + public override string DefaultName => "an ice elemental"; + public override bool BleedImmune => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average, 2); + AddLoot(LootPack.Gems, 2); + } + + 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(); + } } - - public IceElemental(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ice elemental corpse"; - public override string DefaultName => "an ice elemental"; - public override bool BleedImmune => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average, 2); - AddLoot(LootPack.Gems, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/PoisonElemental.cs b/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/PoisonElemental.cs index 49acfd82b..d0061309e 100644 --- a/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/PoisonElemental.cs +++ b/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/PoisonElemental.cs @@ -2,80 +2,80 @@ using Server.Items; namespace Server.Mobiles { - public class PoisonElemental : BaseCreature - { - [Constructible] - public PoisonElemental() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class PoisonElemental : BaseCreature { - Body = 162; - BaseSoundID = 263; + [Constructible] + public PoisonElemental() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 162; + BaseSoundID = 263; - SetStr(426, 515); - SetDex(166, 185); - SetInt(361, 435); + SetStr(426, 515); + SetDex(166, 185); + SetInt(361, 435); - SetHits(256, 309); + SetHits(256, 309); - SetDamage(12, 18); + SetDamage(12, 18); - SetDamageType(ResistanceType.Physical, 10); - SetDamageType(ResistanceType.Poison, 90); + SetDamageType(ResistanceType.Physical, 10); + SetDamageType(ResistanceType.Poison, 90); - SetResistance(ResistanceType.Physical, 60, 70); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 20, 30); - SetResistance(ResistanceType.Poison, 100); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 60, 70); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 20, 30); + SetResistance(ResistanceType.Poison, 100); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.EvalInt, 80.1, 95.0); - SetSkill(SkillName.Magery, 80.1, 95.0); - SetSkill(SkillName.Meditation, 80.2, 120.0); - SetSkill(SkillName.Poisoning, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 85.2, 115.0); - SetSkill(SkillName.Tactics, 80.1, 100.0); - SetSkill(SkillName.Wrestling, 70.1, 90.0); + SetSkill(SkillName.EvalInt, 80.1, 95.0); + SetSkill(SkillName.Magery, 80.1, 95.0); + SetSkill(SkillName.Meditation, 80.2, 120.0); + SetSkill(SkillName.Poisoning, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 85.2, 115.0); + SetSkill(SkillName.Tactics, 80.1, 100.0); + SetSkill(SkillName.Wrestling, 70.1, 90.0); - Fame = 12500; - Karma = -12500; + Fame = 12500; + Karma = -12500; - VirtualArmor = 70; + VirtualArmor = 70; - PackItem(new Nightshade(4)); - PackItem(new LesserPoisonPotion()); + PackItem(new Nightshade(4)); + PackItem(new LesserPoisonPotion()); + } + + public PoisonElemental(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a poison elementals corpse"; + public override string DefaultName => "a poison elemental"; + + public override bool BleedImmune => true; + public override Poison PoisonImmune => Poison.Lethal; + + public override Poison HitPoison => Poison.Lethal; + public override double HitPoisonChance => 0.75; + + public override int TreasureMapLevel => 5; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.Rich); + AddLoot(LootPack.MedScrolls); + } + + 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(); + } } - - public PoisonElemental(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a poison elementals corpse"; - public override string DefaultName => "a poison elemental"; - - public override bool BleedImmune => true; - public override Poison PoisonImmune => Poison.Lethal; - - public override Poison HitPoison => Poison.Lethal; - public override double HitPoisonChance => 0.75; - - public override int TreasureMapLevel => 5; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.Rich); - AddLoot(LootPack.MedScrolls); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/WaterElemental.cs b/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/WaterElemental.cs index 6bf051a62..f9ccba620 100644 --- a/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/WaterElemental.cs +++ b/Projects/UOContent/Mobiles/Monsters/Elemental/Magic/WaterElemental.cs @@ -2,76 +2,76 @@ using Server.Items; namespace Server.Mobiles { - public class WaterElemental : BaseCreature - { - [Constructible] - public WaterElemental() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class WaterElemental : BaseCreature { - Body = 16; - BaseSoundID = 278; + [Constructible] + public WaterElemental() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 16; + BaseSoundID = 278; - SetStr(126, 155); - SetDex(66, 85); - SetInt(101, 125); + SetStr(126, 155); + SetDex(66, 85); + SetInt(101, 125); - SetHits(76, 93); + SetHits(76, 93); - SetDamage(7, 9); + SetDamage(7, 9); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 10, 25); - SetResistance(ResistanceType.Cold, 10, 25); - SetResistance(ResistanceType.Poison, 60, 70); - SetResistance(ResistanceType.Energy, 5, 10); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 10, 25); + SetResistance(ResistanceType.Cold, 10, 25); + SetResistance(ResistanceType.Poison, 60, 70); + SetResistance(ResistanceType.Energy, 5, 10); - SetSkill(SkillName.EvalInt, 60.1, 75.0); - SetSkill(SkillName.Magery, 60.1, 75.0); - SetSkill(SkillName.MagicResist, 100.1, 115.0); - SetSkill(SkillName.Tactics, 50.1, 70.0); - SetSkill(SkillName.Wrestling, 50.1, 70.0); + SetSkill(SkillName.EvalInt, 60.1, 75.0); + SetSkill(SkillName.Magery, 60.1, 75.0); + SetSkill(SkillName.MagicResist, 100.1, 115.0); + SetSkill(SkillName.Tactics, 50.1, 70.0); + SetSkill(SkillName.Wrestling, 50.1, 70.0); - Fame = 4500; - Karma = -4500; + Fame = 4500; + Karma = -4500; - VirtualArmor = 40; - ControlSlots = 3; - CanSwim = true; + VirtualArmor = 40; + ControlSlots = 3; + CanSwim = true; - PackItem(new BlackPearl(3)); + PackItem(new BlackPearl(3)); + } + + public WaterElemental(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a water elemental corpse"; + public override double DispelDifficulty => 117.5; + public override double DispelFocus => 45.0; + + public override string DefaultName => "a water elemental"; + + public override bool BleedImmune => true; + public override int TreasureMapLevel => 2; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Meager); + AddLoot(LootPack.Potions); + } + + 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(); + } } - - public WaterElemental(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a water elemental corpse"; - public override double DispelDifficulty => 117.5; - public override double DispelFocus => 45.0; - - public override string DefaultName => "a water elemental"; - - public override bool BleedImmune => true; - public override int TreasureMapLevel => 2; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Meager); - AddLoot(LootPack.Potions); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Elemental/Melee/EarthElemental.cs b/Projects/UOContent/Mobiles/Monsters/Elemental/Melee/EarthElemental.cs index 2e607ce54..7af2c20c0 100644 --- a/Projects/UOContent/Mobiles/Monsters/Elemental/Melee/EarthElemental.cs +++ b/Projects/UOContent/Mobiles/Monsters/Elemental/Melee/EarthElemental.cs @@ -2,78 +2,78 @@ using Server.Items; namespace Server.Mobiles { - public class EarthElemental : BaseCreature - { - [Constructible] - public EarthElemental() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class EarthElemental : BaseCreature { - Body = 14; - BaseSoundID = 268; + [Constructible] + public EarthElemental() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 14; + BaseSoundID = 268; - SetStr(126, 155); - SetDex(66, 85); - SetInt(71, 92); + SetStr(126, 155); + SetDex(66, 85); + SetInt(71, 92); - SetHits(76, 93); + SetHits(76, 93); - SetDamage(9, 16); + SetDamage(9, 16); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 30, 35); - SetResistance(ResistanceType.Fire, 10, 20); - SetResistance(ResistanceType.Cold, 10, 20); - SetResistance(ResistanceType.Poison, 15, 25); - SetResistance(ResistanceType.Energy, 15, 25); + SetResistance(ResistanceType.Physical, 30, 35); + SetResistance(ResistanceType.Fire, 10, 20); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Poison, 15, 25); + SetResistance(ResistanceType.Energy, 15, 25); - SetSkill(SkillName.MagicResist, 50.1, 95.0); - SetSkill(SkillName.Tactics, 60.1, 100.0); - SetSkill(SkillName.Wrestling, 60.1, 100.0); + SetSkill(SkillName.MagicResist, 50.1, 95.0); + SetSkill(SkillName.Tactics, 60.1, 100.0); + SetSkill(SkillName.Wrestling, 60.1, 100.0); - Fame = 3500; - Karma = -3500; + Fame = 3500; + Karma = -3500; - VirtualArmor = 34; - ControlSlots = 2; + VirtualArmor = 34; + ControlSlots = 2; - PackItem(new FertileDirt(Utility.RandomMinMax(1, 4))); - PackItem(new MandrakeRoot()); + PackItem(new FertileDirt(Utility.RandomMinMax(1, 4))); + PackItem(new MandrakeRoot()); - Item ore = new IronOre(5); - ore.ItemID = 0x19B7; - PackItem(ore); + Item ore = new IronOre(5); + ore.ItemID = 0x19B7; + PackItem(ore); + } + + public EarthElemental(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an earth elemental corpse"; + public override double DispelDifficulty => 117.5; + public override double DispelFocus => 45.0; + + public override string DefaultName => "an earth elemental"; + + public override bool BleedImmune => true; + public override int TreasureMapLevel => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Meager); + AddLoot(LootPack.Gems); + } + + 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(); + } } - - public EarthElemental(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an earth elemental corpse"; - public override double DispelDifficulty => 117.5; - public override double DispelFocus => 45.0; - - public override string DefaultName => "an earth elemental"; - - public override bool BleedImmune => true; - public override int TreasureMapLevel => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Meager); - AddLoot(LootPack.Gems); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Elemental/Melee/SnowElemental.cs b/Projects/UOContent/Mobiles/Monsters/Elemental/Melee/SnowElemental.cs index 7b1e510eb..0b4ef83c4 100644 --- a/Projects/UOContent/Mobiles/Monsters/Elemental/Melee/SnowElemental.cs +++ b/Projects/UOContent/Mobiles/Monsters/Elemental/Melee/SnowElemental.cs @@ -2,72 +2,72 @@ using Server.Items; namespace Server.Mobiles { - public class SnowElemental : BaseCreature - { - [Constructible] - public SnowElemental() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class SnowElemental : BaseCreature { - Body = 163; - BaseSoundID = 263; + [Constructible] + public SnowElemental() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 163; + BaseSoundID = 263; - SetStr(326, 355); - SetDex(166, 185); - SetInt(71, 95); + SetStr(326, 355); + SetDex(166, 185); + SetInt(71, 95); - SetHits(196, 213); + SetHits(196, 213); - SetDamage(11, 17); + SetDamage(11, 17); - SetDamageType(ResistanceType.Physical, 20); - SetDamageType(ResistanceType.Cold, 80); + SetDamageType(ResistanceType.Physical, 20); + SetDamageType(ResistanceType.Cold, 80); - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 10, 15); - SetResistance(ResistanceType.Cold, 60, 70); - SetResistance(ResistanceType.Poison, 25, 35); - SetResistance(ResistanceType.Energy, 25, 35); + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 10, 15); + SetResistance(ResistanceType.Cold, 60, 70); + SetResistance(ResistanceType.Poison, 25, 35); + SetResistance(ResistanceType.Energy, 25, 35); - SetSkill(SkillName.MagicResist, 50.1, 65.0); - SetSkill(SkillName.Tactics, 80.1, 100.0); - SetSkill(SkillName.Wrestling, 80.1, 100.0); + SetSkill(SkillName.MagicResist, 50.1, 65.0); + SetSkill(SkillName.Tactics, 80.1, 100.0); + SetSkill(SkillName.Wrestling, 80.1, 100.0); - Fame = 5000; - Karma = -5000; + Fame = 5000; + Karma = -5000; - VirtualArmor = 50; + VirtualArmor = 50; - PackItem(new BlackPearl(3)); - Item ore = new IronOre(3); - ore.ItemID = 0x19B8; - PackItem(ore); + PackItem(new BlackPearl(3)); + Item ore = new IronOre(3); + ore.ItemID = 0x19B8; + PackItem(ore); + } + + public SnowElemental(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a snow elemental corpse"; + public override string DefaultName => "a snow elemental"; + + public override bool BleedImmune => true; + + public override int TreasureMapLevel => Utility.RandomList(2, 3); + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + } + + 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(); + } } - - public SnowElemental(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a snow elemental corpse"; - public override string DefaultName => "a snow elemental"; - - public override bool BleedImmune => true; - - public override int TreasureMapLevel => Utility.RandomList(2, 3); - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/AncientLich.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/AncientLich.cs index bea8b64dd..9018c87e6 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/AncientLich.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/AncientLich.cs @@ -1,88 +1,88 @@ namespace Server.Mobiles { - public class AncientLich : BaseCreature - { - [Constructible] - public AncientLich() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class AncientLich : BaseCreature { - Name = NameList.RandomName("ancient lich"); - Body = 78; - BaseSoundID = 412; + [Constructible] + public AncientLich() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Name = NameList.RandomName("ancient lich"); + Body = 78; + BaseSoundID = 412; - SetStr(216, 305); - SetDex(96, 115); - SetInt(966, 1045); + SetStr(216, 305); + SetDex(96, 115); + SetInt(966, 1045); - SetHits(560, 595); + SetHits(560, 595); - SetDamage(15, 27); + SetDamage(15, 27); - SetDamageType(ResistanceType.Physical, 20); - SetDamageType(ResistanceType.Cold, 40); - SetDamageType(ResistanceType.Energy, 40); + SetDamageType(ResistanceType.Physical, 20); + SetDamageType(ResistanceType.Cold, 40); + SetDamageType(ResistanceType.Energy, 40); - SetResistance(ResistanceType.Physical, 55, 65); - SetResistance(ResistanceType.Fire, 25, 30); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 50, 60); - SetResistance(ResistanceType.Energy, 25, 30); + SetResistance(ResistanceType.Physical, 55, 65); + SetResistance(ResistanceType.Fire, 25, 30); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 50, 60); + SetResistance(ResistanceType.Energy, 25, 30); - SetSkill(SkillName.EvalInt, 120.1, 130.0); - SetSkill(SkillName.Magery, 120.1, 130.0); - SetSkill(SkillName.Meditation, 100.1, 101.0); - SetSkill(SkillName.Poisoning, 100.1, 101.0); - SetSkill(SkillName.MagicResist, 175.2, 200.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); - SetSkill(SkillName.Wrestling, 75.1, 100.0); - SetSkill(SkillName.Necromancy, 120.1, 130.0); - SetSkill(SkillName.SpiritSpeak, 120.1, 130.0); + SetSkill(SkillName.EvalInt, 120.1, 130.0); + SetSkill(SkillName.Magery, 120.1, 130.0); + SetSkill(SkillName.Meditation, 100.1, 101.0); + SetSkill(SkillName.Poisoning, 100.1, 101.0); + SetSkill(SkillName.MagicResist, 175.2, 200.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.Wrestling, 75.1, 100.0); + SetSkill(SkillName.Necromancy, 120.1, 130.0); + SetSkill(SkillName.SpiritSpeak, 120.1, 130.0); - Fame = 23000; - Karma = -23000; + Fame = 23000; + Karma = -23000; - VirtualArmor = 60; - PackNecroReg(30, 275); + VirtualArmor = 60; + PackNecroReg(30, 275); + } + + public AncientLich(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ancient lich's corpse"; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override bool Unprovokable => true; + public override bool BleedImmune => true; + public override Poison PoisonImmune => Poison.Lethal; + public override int TreasureMapLevel => 5; + + public override int GetIdleSound() => 0x19D; + + public override int GetAngerSound() => 0x175; + + public override int GetDeathSound() => 0x108; + + public override int GetAttackSound() => 0xE2; + + public override int GetHurtSound() => 0x28B; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 3); + AddLoot(LootPack.MedScrolls, 2); + } + + 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(); + } } - - public AncientLich(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ancient lich's corpse"; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override bool Unprovokable => true; - public override bool BleedImmune => true; - public override Poison PoisonImmune => Poison.Lethal; - public override int TreasureMapLevel => 5; - - public override int GetIdleSound() => 0x19D; - - public override int GetAngerSound() => 0x175; - - public override int GetDeathSound() => 0x108; - - public override int GetAttackSound() => 0xE2; - - public override int GetHurtSound() => 0x28B; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 3); - AddLoot(LootPack.MedScrolls, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/ArcaneDaemon.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/ArcaneDaemon.cs index b8ba53672..d283f8996 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/ArcaneDaemon.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/ArcaneDaemon.cs @@ -2,71 +2,71 @@ using Server.Items; namespace Server.Mobiles { - public class ArcaneDaemon : BaseCreature - { - [Constructible] - public ArcaneDaemon() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class ArcaneDaemon : BaseCreature { - Body = 0x310; - BaseSoundID = 0x47D; + [Constructible] + public ArcaneDaemon() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0x310; + BaseSoundID = 0x47D; - SetStr(131, 150); - SetDex(126, 145); - SetInt(301, 350); + SetStr(131, 150); + SetDex(126, 145); + SetInt(301, 350); - SetHits(101, 115); + SetHits(101, 115); - SetDamage(12, 16); + SetDamage(12, 16); - SetDamageType(ResistanceType.Physical, 80); - SetDamageType(ResistanceType.Fire, 20); + SetDamageType(ResistanceType.Physical, 80); + SetDamageType(ResistanceType.Fire, 20); - SetResistance(ResistanceType.Physical, 50, 60); - SetResistance(ResistanceType.Fire, 70, 80); - SetResistance(ResistanceType.Cold, 10, 20); - SetResistance(ResistanceType.Poison, 50, 60); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 50, 60); + SetResistance(ResistanceType.Fire, 70, 80); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Poison, 50, 60); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.MagicResist, 85.1, 95.0); - SetSkill(SkillName.Tactics, 70.1, 80.0); - SetSkill(SkillName.Wrestling, 60.1, 80.0); - SetSkill(SkillName.Magery, 80.1, 90.0); - SetSkill(SkillName.EvalInt, 70.1, 80.0); - SetSkill(SkillName.Meditation, 70.1, 80.0); + SetSkill(SkillName.MagicResist, 85.1, 95.0); + SetSkill(SkillName.Tactics, 70.1, 80.0); + SetSkill(SkillName.Wrestling, 60.1, 80.0); + SetSkill(SkillName.Magery, 80.1, 90.0); + SetSkill(SkillName.EvalInt, 70.1, 80.0); + SetSkill(SkillName.Meditation, 70.1, 80.0); - Fame = 7000; - Karma = -10000; + Fame = 7000; + Karma = -10000; - VirtualArmor = 55; + VirtualArmor = 55; + } + + public ArcaneDaemon(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an arcane daemon corpse"; + + public override string DefaultName => "an arcane daemon"; + + public override Poison PoisonImmune => Poison.Deadly; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.ConcussionBlow; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average, 2); + } + + 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(); + } } - - public ArcaneDaemon(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an arcane daemon corpse"; - - public override string DefaultName => "an arcane daemon"; - - public override Poison PoisonImmune => Poison.Deadly; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.ConcussionBlow; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Balron.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Balron.cs index 51fd1480e..c0132e5cb 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Balron.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Balron.cs @@ -2,77 +2,77 @@ using Server.Items; namespace Server.Mobiles { - public class Balron : BaseCreature - { - [Constructible] - public Balron() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Balron : BaseCreature { - Name = NameList.RandomName("balron"); - Body = 40; - BaseSoundID = 357; + [Constructible] + public Balron() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Name = NameList.RandomName("balron"); + Body = 40; + BaseSoundID = 357; - SetStr(986, 1185); - SetDex(177, 255); - SetInt(151, 250); + SetStr(986, 1185); + SetDex(177, 255); + SetInt(151, 250); - SetHits(592, 711); + SetHits(592, 711); - SetDamage(22, 29); + SetDamage(22, 29); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Fire, 25); - SetDamageType(ResistanceType.Energy, 25); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Fire, 25); + SetDamageType(ResistanceType.Energy, 25); - SetResistance(ResistanceType.Physical, 65, 80); - SetResistance(ResistanceType.Fire, 60, 80); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 100); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 65, 80); + SetResistance(ResistanceType.Fire, 60, 80); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 100); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.Anatomy, 25.1, 50.0); - SetSkill(SkillName.EvalInt, 90.1, 100.0); - SetSkill(SkillName.Magery, 95.5, 100.0); - SetSkill(SkillName.Meditation, 25.1, 50.0); - SetSkill(SkillName.MagicResist, 100.5, 150.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); - SetSkill(SkillName.Wrestling, 90.1, 100.0); + SetSkill(SkillName.Anatomy, 25.1, 50.0); + SetSkill(SkillName.EvalInt, 90.1, 100.0); + SetSkill(SkillName.Magery, 95.5, 100.0); + SetSkill(SkillName.Meditation, 25.1, 50.0); + SetSkill(SkillName.MagicResist, 100.5, 150.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.Wrestling, 90.1, 100.0); - Fame = 24000; - Karma = -24000; + Fame = 24000; + Karma = -24000; - VirtualArmor = 90; + VirtualArmor = 90; - PackItem(new Longsword()); + PackItem(new Longsword()); + } + + public Balron(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a balron corpse"; + + public override bool CanRummageCorpses => true; + public override Poison PoisonImmune => Poison.Deadly; + public override int TreasureMapLevel => 5; + public override int Meat => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 2); + AddLoot(LootPack.Rich); + AddLoot(LootPack.MedScrolls, 2); + } + + 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(); + } } - - public Balron(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a balron corpse"; - - public override bool CanRummageCorpses => true; - public override Poison PoisonImmune => Poison.Deadly; - public override int TreasureMapLevel => 5; - public override int Meat => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 2); - AddLoot(LootPack.Rich); - AddLoot(LootPack.MedScrolls, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Betrayer.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Betrayer.cs index 74fd8ea20..2d48d2cab 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Betrayer.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Betrayer.cs @@ -4,167 +4,171 @@ using Server.Network; namespace Server.Mobiles { - public class Betrayer : BaseCreature - { - private DateTime m_NextAbilityTime; - private bool m_Stunning; - - [Constructible] - public Betrayer() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Betrayer : BaseCreature { - Body = 767; + private DateTime m_NextAbilityTime; + private bool m_Stunning; - SetStr(401, 500); - SetDex(81, 100); - SetInt(151, 200); - - SetHits(241, 300); - - SetDamage(16, 22); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 60, 70); - SetResistance(ResistanceType.Fire, 60, 70); - SetResistance(ResistanceType.Cold, 60, 70); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 20, 30); - - SetSkill(SkillName.Anatomy, 90.1, 100.0); - SetSkill(SkillName.EvalInt, 90.1, 100.0); - SetSkill(SkillName.Magery, 50.1, 100.0); - SetSkill(SkillName.Meditation, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 120.1, 130.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); - SetSkill(SkillName.Wrestling, 90.1, 100.0); - - Fame = 15000; - Karma = -15000; - - VirtualArmor = 65; - SpeechHue = Utility.RandomDyedHue(); - - PackItem(new PowerCrystal()); - - if (Utility.RandomDouble() < 0.02) - PackItem(new BlackthornWelcomeBook()); - - m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(5, 30)); - } - - public Betrayer(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a betrayer corpse"; - - public override string DefaultName => "a betrayer"; - - public override bool AlwaysMurderer => true; - public override bool BardImmune => !Core.AOS; - public override Poison PoisonImmune => Poison.Lethal; - public override int Meat => 1; - public override int TreasureMapLevel => 5; - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - if (Utility.RandomDouble() < 0.05) - { - if (!IsParagon) + [Constructible] + public Betrayer() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) { - if (Utility.RandomDouble() < 0.75) - c.DropItem(DawnsMusicGear.RandomCommon); - else - c.DropItem(DawnsMusicGear.RandomUncommon); + Body = 767; + + SetStr(401, 500); + SetDex(81, 100); + SetInt(151, 200); + + SetHits(241, 300); + + SetDamage(16, 22); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 60, 70); + SetResistance(ResistanceType.Fire, 60, 70); + SetResistance(ResistanceType.Cold, 60, 70); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 20, 30); + + SetSkill(SkillName.Anatomy, 90.1, 100.0); + SetSkill(SkillName.EvalInt, 90.1, 100.0); + SetSkill(SkillName.Magery, 50.1, 100.0); + SetSkill(SkillName.Meditation, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 120.1, 130.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.Wrestling, 90.1, 100.0); + + Fame = 15000; + Karma = -15000; + + VirtualArmor = 65; + SpeechHue = Utility.RandomDyedHue(); + + PackItem(new PowerCrystal()); + + if (Utility.RandomDouble() < 0.02) + PackItem(new BlackthornWelcomeBook()); + + m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(5, 30)); } - else + + public Betrayer(Serial serial) + : base(serial) { - c.DropItem(DawnsMusicGear.RandomRare); } - } - } - public override int GetDeathSound() => 0x423; + public override string CorpseName => "a betrayer corpse"; - public override int GetAttackSound() => 0x23B; + public override string DefaultName => "a betrayer"; - public override int GetHurtSound() => 0x140; + public override bool AlwaysMurderer => true; + public override bool BardImmune => !Core.AOS; + public override Poison PoisonImmune => Poison.Lethal; + public override int Meat => 1; + public override int TreasureMapLevel => 5; - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.Rich); - AddLoot(LootPack.Gems, 1); - } - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (!m_Stunning && Utility.RandomDouble() < 0.3) - { - m_Stunning = true; - - defender.Animate(21, 6, 1, true, false, 0); - PlaySound(0xEE); - defender.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, - "You have been stunned by a colossal blow!"); - - if (Weapon is BaseWeapon weapon) - weapon.OnHit(this, defender); - - if (defender.Alive) + public override void OnDeath(Container c) { - defender.Frozen = true; - Timer.DelayCall(TimeSpan.FromSeconds(5.0), Recover_Callback, defender); + base.OnDeath(c); + + if (Utility.RandomDouble() < 0.05) + { + if (!IsParagon) + { + if (Utility.RandomDouble() < 0.75) + c.DropItem(DawnsMusicGear.RandomCommon); + else + c.DropItem(DawnsMusicGear.RandomUncommon); + } + else + { + c.DropItem(DawnsMusicGear.RandomRare); + } + } + } + + public override int GetDeathSound() => 0x423; + + public override int GetAttackSound() => 0x23B; + + public override int GetHurtSound() => 0x140; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.Rich); + AddLoot(LootPack.Gems, 1); + } + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (!m_Stunning && Utility.RandomDouble() < 0.3) + { + m_Stunning = true; + + defender.Animate(21, 6, 1, true, false, 0); + PlaySound(0xEE); + defender.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + false, + "You have been stunned by a colossal blow!" + ); + + if (Weapon is BaseWeapon weapon) + weapon.OnHit(this, defender); + + if (defender.Alive) + { + defender.Frozen = true; + Timer.DelayCall(TimeSpan.FromSeconds(5.0), Recover_Callback, defender); + } + } + } + + private void Recover_Callback(Mobile defender) + { + defender.Frozen = false; + defender.Combatant = null; + defender.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You recover your senses."); + m_Stunning = false; + } + + public override void OnActionCombat() + { + var combatant = Combatant; + + if (DateTime.UtcNow < m_NextAbilityTime || combatant?.Deleted != false || combatant.Map != Map || + !InRange(combatant, 3) || !CanBeHarmful(combatant) || !InLOS(combatant)) + return; + + m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(5, 30)); + + if (Utility.RandomBool()) + { + FixedParticles(0x376A, 9, 32, 0x2539, EffectLayer.LeftHand); + PlaySound(0x1DE); + + foreach (var m in GetMobilesInRange(2)) + if (m != this && IsEnemy(m)) + m.ApplyPoison(this, Poison.Deadly); + } + } + + 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(); } - } } - - private void Recover_Callback(Mobile defender) - { - defender.Frozen = false; - defender.Combatant = null; - defender.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You recover your senses."); - m_Stunning = false; - } - - public override void OnActionCombat() - { - Mobile combatant = Combatant; - - if (DateTime.UtcNow < m_NextAbilityTime || combatant?.Deleted != false || combatant.Map != Map || - !InRange(combatant, 3) || !CanBeHarmful(combatant) || !InLOS(combatant)) - return; - - m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(5, 30)); - - if (Utility.RandomBool()) - { - FixedParticles(0x376A, 9, 32, 0x2539, EffectLayer.LeftHand); - PlaySound(0x1DE); - - foreach (Mobile m in GetMobilesInRange(2)) - if (m != this && IsEnemy(m)) - m.ApplyPoison(this, Poison.Deadly); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Bogle.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Bogle.cs index 7ec10718f..07831fb92 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Bogle.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Bogle.cs @@ -2,63 +2,63 @@ using Server.Items; namespace Server.Mobiles { - public class Bogle : BaseCreature - { - [Constructible] - public Bogle() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Bogle : BaseCreature { - Body = 153; - BaseSoundID = 0x482; + [Constructible] + public Bogle() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 153; + BaseSoundID = 0x482; - SetStr(76, 100); - SetDex(76, 95); - SetInt(36, 60); + SetStr(76, 100); + SetDex(76, 95); + SetInt(36, 60); - SetHits(46, 60); + SetHits(46, 60); - SetDamage(7, 11); + SetDamage(7, 11); - SetSkill(SkillName.EvalInt, 55.1, 70.0); - SetSkill(SkillName.Magery, 55.1, 70.0); - SetSkill(SkillName.MagicResist, 55.1, 70.0); - SetSkill(SkillName.Tactics, 45.1, 60.0); - SetSkill(SkillName.Wrestling, 45.1, 55.0); + SetSkill(SkillName.EvalInt, 55.1, 70.0); + SetSkill(SkillName.Magery, 55.1, 70.0); + SetSkill(SkillName.MagicResist, 55.1, 70.0); + SetSkill(SkillName.Tactics, 45.1, 60.0); + SetSkill(SkillName.Wrestling, 45.1, 55.0); - Fame = 4000; - Karma = -4000; + Fame = 4000; + Karma = -4000; - VirtualArmor = 28; - PackItem(Loot.RandomWeapon()); - PackItem(new Bone()); + VirtualArmor = 28; + PackItem(Loot.RandomWeapon()); + PackItem(new Bone()); + } + + public Bogle(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a ghostly corpse"; + public override string DefaultName => "a bogle"; + + public override bool BleedImmune => true; + public override Poison PoisonImmune => Poison.Lethal; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + 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(); + } } - - public Bogle(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a ghostly corpse"; - public override string DefaultName => "a bogle"; - - public override bool BleedImmune => true; - public override Poison PoisonImmune => Poison.Lethal; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/BoneMagi.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/BoneMagi.cs index 9e7ae078f..2eabcc511 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/BoneMagi.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/BoneMagi.cs @@ -2,79 +2,79 @@ using Server.Items; namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.BoneMage")] - public class BoneMagi : BaseCreature - { - [Constructible] - public BoneMagi() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.BoneMage")] + public class BoneMagi : BaseCreature { - Body = 148; - BaseSoundID = 451; + [Constructible] + public BoneMagi() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 148; + BaseSoundID = 451; - SetStr(76, 100); - SetDex(56, 75); - SetInt(186, 210); + SetStr(76, 100); + SetDex(56, 75); + SetInt(186, 210); - SetHits(46, 60); + SetHits(46, 60); - SetDamage(3, 7); + SetDamage(3, 7); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 35, 40); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 35, 40); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.EvalInt, 60.1, 70.0); - SetSkill(SkillName.Magery, 60.1, 70.0); - SetSkill(SkillName.MagicResist, 55.1, 70.0); - SetSkill(SkillName.Tactics, 45.1, 60.0); - SetSkill(SkillName.Wrestling, 45.1, 55.0); - SetSkill(SkillName.Necromancy, 89, 99.1); - SetSkill(SkillName.SpiritSpeak, 90.0, 99.0); + SetSkill(SkillName.EvalInt, 60.1, 70.0); + SetSkill(SkillName.Magery, 60.1, 70.0); + SetSkill(SkillName.MagicResist, 55.1, 70.0); + SetSkill(SkillName.Tactics, 45.1, 60.0); + SetSkill(SkillName.Wrestling, 45.1, 55.0); + SetSkill(SkillName.Necromancy, 89, 99.1); + SetSkill(SkillName.SpiritSpeak, 90.0, 99.0); - Fame = 3000; - Karma = -3000; + Fame = 3000; + Karma = -3000; - VirtualArmor = 38; + VirtualArmor = 38; - PackReg(3); - PackNecroReg(3, 10); - PackItem(new Bone()); + PackReg(3); + PackNecroReg(3, 10); + PackItem(new Bone()); + } + + public BoneMagi(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a skeletal corpse"; + public override string DefaultName => "a bone mage"; + + public override bool BleedImmune => true; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override Poison PoisonImmune => Poison.Regular; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.LowScrolls); + AddLoot(LootPack.Potions); + } + + 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(); + } } - - public BoneMagi(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a skeletal corpse"; - public override string DefaultName => "a bone mage"; - - public override bool BleedImmune => true; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override Poison PoisonImmune => Poison.Regular; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.LowScrolls); - AddLoot(LootPack.Potions); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Daemon.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Daemon.cs index 664cc64a5..18de26c29 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Daemon.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Daemon.cs @@ -3,78 +3,78 @@ using Server.Factions; namespace Server.Mobiles { - public class Daemon : BaseCreature - { - [Constructible] - public Daemon() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Daemon : BaseCreature { - Name = NameList.RandomName("daemon"); - Body = 9; - BaseSoundID = 357; + [Constructible] + public Daemon() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Name = NameList.RandomName("daemon"); + Body = 9; + BaseSoundID = 357; - SetStr(476, 505); - SetDex(76, 95); - SetInt(301, 325); + SetStr(476, 505); + SetDex(76, 95); + SetInt(301, 325); - SetHits(286, 303); + SetHits(286, 303); - SetDamage(7, 14); + SetDamage(7, 14); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 45, 60); - SetResistance(ResistanceType.Fire, 50, 60); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 45, 60); + SetResistance(ResistanceType.Fire, 50, 60); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.EvalInt, 70.1, 80.0); - SetSkill(SkillName.Magery, 70.1, 80.0); - SetSkill(SkillName.MagicResist, 85.1, 95.0); - SetSkill(SkillName.Tactics, 70.1, 80.0); - SetSkill(SkillName.Wrestling, 60.1, 80.0); + SetSkill(SkillName.EvalInt, 70.1, 80.0); + SetSkill(SkillName.Magery, 70.1, 80.0); + SetSkill(SkillName.MagicResist, 85.1, 95.0); + SetSkill(SkillName.Tactics, 70.1, 80.0); + SetSkill(SkillName.Wrestling, 60.1, 80.0); - Fame = 15000; - Karma = -15000; + Fame = 15000; + Karma = -15000; - VirtualArmor = 58; - ControlSlots = Core.SE ? 4 : 5; + VirtualArmor = 58; + ControlSlots = Core.SE ? 4 : 5; + } + + public Daemon(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a daemon corpse"; + public override double DispelDifficulty => 125.0; + public override double DispelFocus => 45.0; + + public override Faction FactionAllegiance => Shadowlords.Instance; + public override Ethic EthicAllegiance => Ethic.Evil; + + public override bool CanRummageCorpses => true; + public override Poison PoisonImmune => Poison.Regular; + public override int TreasureMapLevel => 4; + public override int Meat => 1; + public override bool CanFly => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.Average, 2); + AddLoot(LootPack.MedScrolls, 2); + } + + 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(); + } } - - public Daemon(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a daemon corpse"; - public override double DispelDifficulty => 125.0; - public override double DispelFocus => 45.0; - - public override Faction FactionAllegiance => Shadowlords.Instance; - public override Ethic EthicAllegiance => Ethic.Evil; - - public override bool CanRummageCorpses => true; - public override Poison PoisonImmune => Poison.Regular; - public override int TreasureMapLevel => 4; - public override int Meat => 1; - public override bool CanFly => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.Average, 2); - AddLoot(LootPack.MedScrolls, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/ElderGazer.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/ElderGazer.cs index 1e2362689..827953361 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/ElderGazer.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/ElderGazer.cs @@ -1,67 +1,67 @@ namespace Server.Mobiles { - public class ElderGazer : BaseCreature - { - [Constructible] - public ElderGazer() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class ElderGazer : BaseCreature { - Body = 22; - BaseSoundID = 377; + [Constructible] + public ElderGazer() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 22; + BaseSoundID = 377; - SetStr(296, 325); - SetDex(86, 105); - SetInt(291, 385); + SetStr(296, 325); + SetDex(86, 105); + SetInt(291, 385); - SetHits(178, 195); + SetHits(178, 195); - SetDamage(8, 19); + SetDamage(8, 19); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Energy, 50); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Energy, 50); - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 60, 70); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 60, 70); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.Anatomy, 62.0, 100.0); - SetSkill(SkillName.EvalInt, 90.1, 100.0); - SetSkill(SkillName.Magery, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 115.1, 130.0); - SetSkill(SkillName.Tactics, 80.1, 100.0); - SetSkill(SkillName.Wrestling, 80.1, 100.0); + SetSkill(SkillName.Anatomy, 62.0, 100.0); + SetSkill(SkillName.EvalInt, 90.1, 100.0); + SetSkill(SkillName.Magery, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 115.1, 130.0); + SetSkill(SkillName.Tactics, 80.1, 100.0); + SetSkill(SkillName.Wrestling, 80.1, 100.0); - Fame = 12500; - Karma = -12500; + Fame = 12500; + Karma = -12500; - VirtualArmor = 50; + VirtualArmor = 50; + } + + public ElderGazer(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an elder gazer corpse"; + public override string DefaultName => "an elder gazer"; + + public override int TreasureMapLevel => Core.AOS ? 4 : 0; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + } + + 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(); + } } - - public ElderGazer(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an elder gazer corpse"; - public override string DefaultName => "an elder gazer"; - - public override int TreasureMapLevel => Core.AOS ? 4 : 0; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/EvilMage.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/EvilMage.cs index dec6903a2..28529129f 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/EvilMage.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/EvilMage.cs @@ -2,72 +2,72 @@ using Server.Items; namespace Server.Mobiles { - public class EvilMage : BaseCreature - { - [Constructible] - public EvilMage() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class EvilMage : BaseCreature { - Name = NameList.RandomName("evil mage"); - Title = "the evil mage"; - Body = 124; + [Constructible] + public EvilMage() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Name = NameList.RandomName("evil mage"); + Title = "the evil mage"; + Body = 124; - SetStr(81, 105); - SetDex(91, 115); - SetInt(96, 120); + SetStr(81, 105); + SetDex(91, 115); + SetInt(96, 120); - SetHits(49, 63); + SetHits(49, 63); - SetDamage(5, 10); + SetDamage(5, 10); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 15, 20); - SetResistance(ResistanceType.Fire, 5, 10); - SetResistance(ResistanceType.Poison, 5, 10); - SetResistance(ResistanceType.Energy, 5, 10); + SetResistance(ResistanceType.Physical, 15, 20); + SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Energy, 5, 10); - SetSkill(SkillName.EvalInt, 75.1, 100.0); - SetSkill(SkillName.Magery, 75.1, 100.0); - SetSkill(SkillName.MagicResist, 75.0, 97.5); - SetSkill(SkillName.Tactics, 65.0, 87.5); - SetSkill(SkillName.Wrestling, 20.2, 60.0); + SetSkill(SkillName.EvalInt, 75.1, 100.0); + SetSkill(SkillName.Magery, 75.1, 100.0); + SetSkill(SkillName.MagicResist, 75.0, 97.5); + SetSkill(SkillName.Tactics, 65.0, 87.5); + SetSkill(SkillName.Wrestling, 20.2, 60.0); - Fame = 2500; - Karma = -2500; + Fame = 2500; + Karma = -2500; - VirtualArmor = 16; - PackReg(6); - PackItem(new Robe(Utility.RandomNeutralHue())); // TODO: Proper hue - PackItem(new Sandals()); + VirtualArmor = 16; + PackReg(6); + PackItem(new Robe(Utility.RandomNeutralHue())); // TODO: Proper hue + PackItem(new Sandals()); + } + + public EvilMage(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an evil mage corpse"; + + public override bool CanRummageCorpses => true; + public override bool AlwaysMurderer => true; + public override int Meat => 1; + public override int TreasureMapLevel => Core.AOS ? 1 : 0; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.MedScrolls); + } + + 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(); + } } - - public EvilMage(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an evil mage corpse"; - - public override bool CanRummageCorpses => true; - public override bool AlwaysMurderer => true; - public override int Meat => 1; - public override int TreasureMapLevel => Core.AOS ? 1 : 0; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.MedScrolls); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/EvilMageLord.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/EvilMageLord.cs index 29da15b7e..56a5b9a50 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/EvilMageLord.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/EvilMageLord.cs @@ -2,79 +2,79 @@ using Server.Items; namespace Server.Mobiles { - public class EvilMageLord : BaseCreature - { - [Constructible] - public EvilMageLord() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class EvilMageLord : BaseCreature { - Name = NameList.RandomName("evil mage lord"); - Body = Utility.RandomList(125, 126); + [Constructible] + public EvilMageLord() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Name = NameList.RandomName("evil mage lord"); + Body = Utility.RandomList(125, 126); - PackItem(new Robe(Utility.RandomMetalHue())); - PackItem(new WizardsHat(Utility.RandomMetalHue())); + PackItem(new Robe(Utility.RandomMetalHue())); + PackItem(new WizardsHat(Utility.RandomMetalHue())); - SetStr(81, 105); - SetDex(191, 215); - SetInt(126, 150); + SetStr(81, 105); + SetDex(191, 215); + SetInt(126, 150); - SetHits(49, 63); + SetHits(49, 63); - SetDamage(5, 10); + SetDamage(5, 10); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 35, 40); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 35, 40); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.EvalInt, 80.2, 100.0); - SetSkill(SkillName.Magery, 95.1, 100.0); - SetSkill(SkillName.Meditation, 27.5, 50.0); - SetSkill(SkillName.MagicResist, 77.5, 100.0); - SetSkill(SkillName.Tactics, 65.0, 87.5); - SetSkill(SkillName.Wrestling, 20.3, 80.0); + SetSkill(SkillName.EvalInt, 80.2, 100.0); + SetSkill(SkillName.Magery, 95.1, 100.0); + SetSkill(SkillName.Meditation, 27.5, 50.0); + SetSkill(SkillName.MagicResist, 77.5, 100.0); + SetSkill(SkillName.Tactics, 65.0, 87.5); + SetSkill(SkillName.Wrestling, 20.3, 80.0); - Fame = 10500; - Karma = -10500; + Fame = 10500; + Karma = -10500; - VirtualArmor = 16; - PackReg(23); - if (Utility.RandomBool()) - PackItem(new Shoes()); - else - PackItem(new Sandals()); + VirtualArmor = 16; + PackReg(23); + if (Utility.RandomBool()) + PackItem(new Shoes()); + else + PackItem(new Sandals()); + } + + public EvilMageLord(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an evil mage lord corpse"; + + public override bool CanRummageCorpses => true; + public override bool AlwaysMurderer => true; + public override int Meat => 1; + public override int TreasureMapLevel => Core.AOS ? 2 : 0; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Meager); + AddLoot(LootPack.MedScrolls, 2); + } + + 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(); + } } - - public EvilMageLord(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an evil mage lord corpse"; - - public override bool CanRummageCorpses => true; - public override bool AlwaysMurderer => true; - public override int Meat => 1; - public override int TreasureMapLevel => Core.AOS ? 2 : 0; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Meager); - AddLoot(LootPack.MedScrolls, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/FireGargoyle.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/FireGargoyle.cs index 0f562c2e1..b86c9eca3 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/FireGargoyle.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/FireGargoyle.cs @@ -1,71 +1,71 @@ namespace Server.Mobiles { - public class FireGargoyle : BaseCreature - { - [Constructible] - public FireGargoyle() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class FireGargoyle : BaseCreature { - Name = NameList.RandomName("fire gargoyle"); - Body = 130; - BaseSoundID = 0x174; + [Constructible] + public FireGargoyle() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Name = NameList.RandomName("fire gargoyle"); + Body = 130; + BaseSoundID = 0x174; - SetStr(351, 400); - SetDex(126, 145); - SetInt(226, 250); + SetStr(351, 400); + SetDex(126, 145); + SetInt(226, 250); - SetHits(211, 240); + SetHits(211, 240); - SetDamage(7, 14); + SetDamage(7, 14); - SetDamageType(ResistanceType.Physical, 20); - SetDamageType(ResistanceType.Fire, 80); + SetDamageType(ResistanceType.Physical, 20); + SetDamageType(ResistanceType.Fire, 80); - SetResistance(ResistanceType.Physical, 30, 35); - SetResistance(ResistanceType.Fire, 50, 60); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 20, 30); + SetResistance(ResistanceType.Physical, 30, 35); + SetResistance(ResistanceType.Fire, 50, 60); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 20, 30); - SetSkill(SkillName.Anatomy, 75.1, 85.0); - SetSkill(SkillName.EvalInt, 90.1, 105.0); - SetSkill(SkillName.Magery, 90.1, 105.0); - SetSkill(SkillName.Meditation, 90.1, 105.0); - SetSkill(SkillName.MagicResist, 90.1, 105.0); - SetSkill(SkillName.Tactics, 80.1, 100.0); - SetSkill(SkillName.Wrestling, 40.1, 80.0); + SetSkill(SkillName.Anatomy, 75.1, 85.0); + SetSkill(SkillName.EvalInt, 90.1, 105.0); + SetSkill(SkillName.Magery, 90.1, 105.0); + SetSkill(SkillName.Meditation, 90.1, 105.0); + SetSkill(SkillName.MagicResist, 90.1, 105.0); + SetSkill(SkillName.Tactics, 80.1, 100.0); + SetSkill(SkillName.Wrestling, 40.1, 80.0); - Fame = 3500; - Karma = -3500; + Fame = 3500; + Karma = -3500; - VirtualArmor = 32; + VirtualArmor = 32; + } + + public FireGargoyle(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a charred corpse"; + + public override bool HasBreath => true; // fire breath enabled + public override int TreasureMapLevel => 1; + public override int Meat => 1; + public override bool CanFly => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.Gems); + } + + 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(); + } } - - public FireGargoyle(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a charred corpse"; - - public override bool HasBreath => true; // fire breath enabled - public override int TreasureMapLevel => 1; - public override int Meat => 1; - public override bool CanFly => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.Gems); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Gargoyle.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Gargoyle.cs index a5c8cc480..80abd8f1d 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Gargoyle.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Gargoyle.cs @@ -2,73 +2,73 @@ using Server.Items; namespace Server.Mobiles { - public class Gargoyle : BaseCreature - { - [Constructible] - public Gargoyle() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Gargoyle : BaseCreature { - Body = 4; - BaseSoundID = 372; + [Constructible] + public Gargoyle() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 4; + BaseSoundID = 372; - SetStr(146, 175); - SetDex(76, 95); - SetInt(81, 105); + SetStr(146, 175); + SetDex(76, 95); + SetInt(81, 105); - SetHits(88, 105); + SetHits(88, 105); - SetDamage(7, 14); + SetDamage(7, 14); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 30, 35); - SetResistance(ResistanceType.Fire, 25, 35); - SetResistance(ResistanceType.Cold, 5, 10); - SetResistance(ResistanceType.Poison, 15, 25); + SetResistance(ResistanceType.Physical, 30, 35); + SetResistance(ResistanceType.Fire, 25, 35); + SetResistance(ResistanceType.Cold, 5, 10); + SetResistance(ResistanceType.Poison, 15, 25); - SetSkill(SkillName.EvalInt, 70.1, 85.0); - SetSkill(SkillName.Magery, 70.1, 85.0); - SetSkill(SkillName.MagicResist, 70.1, 85.0); - SetSkill(SkillName.Tactics, 50.1, 70.0); - SetSkill(SkillName.Wrestling, 40.1, 80.0); + SetSkill(SkillName.EvalInt, 70.1, 85.0); + SetSkill(SkillName.Magery, 70.1, 85.0); + SetSkill(SkillName.MagicResist, 70.1, 85.0); + SetSkill(SkillName.Tactics, 50.1, 70.0); + SetSkill(SkillName.Wrestling, 40.1, 80.0); - Fame = 3500; - Karma = -3500; + Fame = 3500; + Karma = -3500; - VirtualArmor = 32; + VirtualArmor = 32; - if (Utility.RandomDouble() < 0.025) - PackItem(new GargoylesPickaxe()); + if (Utility.RandomDouble() < 0.025) + PackItem(new GargoylesPickaxe()); + } + + public Gargoyle(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a gargoyle corpse"; + public override string DefaultName => "a gargoyle"; + + public override bool CanFly => true; + + public override int TreasureMapLevel => 1; + public override int Meat => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.MedScrolls); + AddLoot(LootPack.Gems, Utility.RandomMinMax(1, 4)); + } + + 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(); + } } - - public Gargoyle(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a gargoyle corpse"; - public override string DefaultName => "a gargoyle"; - - public override bool CanFly => true; - - public override int TreasureMapLevel => 1; - public override int Meat => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.MedScrolls); - AddLoot(LootPack.Gems, Utility.RandomMinMax(1, 4)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/GargoyleDestroyer.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/GargoyleDestroyer.cs index d0601acca..807e5b675 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/GargoyleDestroyer.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/GargoyleDestroyer.cs @@ -2,99 +2,99 @@ using Server.Items; namespace Server.Mobiles { - public class GargoyleDestroyer : BaseCreature - { - [Constructible] - public GargoyleDestroyer() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class GargoyleDestroyer : BaseCreature { - Body = 0x2F3; - BaseSoundID = 0x174; + [Constructible] + public GargoyleDestroyer() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0x2F3; + BaseSoundID = 0x174; - SetStr(760, 850); - SetDex(102, 150); - SetInt(152, 200); + SetStr(760, 850); + SetDex(102, 150); + SetInt(152, 200); - SetHits(482, 485); + SetHits(482, 485); - SetDamage(7, 14); + SetDamage(7, 14); - SetResistance(ResistanceType.Physical, 40, 60); - SetResistance(ResistanceType.Fire, 60, 70); - SetResistance(ResistanceType.Cold, 15, 25); - SetResistance(ResistanceType.Poison, 15, 25); - SetResistance(ResistanceType.Energy, 15, 25); + SetResistance(ResistanceType.Physical, 40, 60); + SetResistance(ResistanceType.Fire, 60, 70); + SetResistance(ResistanceType.Cold, 15, 25); + SetResistance(ResistanceType.Poison, 15, 25); + SetResistance(ResistanceType.Energy, 15, 25); - SetSkill(SkillName.Wrestling, 90.1, 100.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 120.4, 160.0); - SetSkill(SkillName.Anatomy, 50.5, 100.0); - SetSkill(SkillName.Swords, 90.1, 100.0); - SetSkill(SkillName.Macing, 90.1, 100.0); - SetSkill(SkillName.Fencing, 90.1, 100.0); - SetSkill(SkillName.Magery, 90.1, 100.0); - SetSkill(SkillName.EvalInt, 90.1, 100.0); - SetSkill(SkillName.Meditation, 90.1, 100.0); + SetSkill(SkillName.Wrestling, 90.1, 100.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 120.4, 160.0); + SetSkill(SkillName.Anatomy, 50.5, 100.0); + SetSkill(SkillName.Swords, 90.1, 100.0); + SetSkill(SkillName.Macing, 90.1, 100.0); + SetSkill(SkillName.Fencing, 90.1, 100.0); + SetSkill(SkillName.Magery, 90.1, 100.0); + SetSkill(SkillName.EvalInt, 90.1, 100.0); + SetSkill(SkillName.Meditation, 90.1, 100.0); - Fame = 10000; - Karma = -10000; + Fame = 10000; + Karma = -10000; - VirtualArmor = 50; + VirtualArmor = 50; - if (Utility.RandomDouble() < 0.2) - PackItem(new GargoylesPickaxe()); + if (Utility.RandomDouble() < 0.2) + PackItem(new GargoylesPickaxe()); + } + + public GargoyleDestroyer(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a gargoyle corpse"; + public override string DefaultName => "a gargoyle destroyer"; + + public override bool BardImmune => !Core.AOS; + public override int Meat => 1; + public override bool CanFly => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.Rich); + AddLoot(LootPack.MedScrolls); + AddLoot(LootPack.Gems, 2); + } + + public override void OnDamagedBySpell(Mobile from) + { + if (from?.Alive == true && Utility.RandomDouble() < 0.4) + ThrowHatchet(from); + } + + public override void OnGotMeleeAttack(Mobile attacker) + { + base.OnGotMeleeAttack(attacker); + + if (attacker?.Alive == true && attacker.Weapon is BaseRanged && Utility.RandomDouble() < 0.4) + ThrowHatchet(attacker); + } + + public void ThrowHatchet(Mobile to) + { + var damage = 50; + MovingEffect(to, 0xF43, 10, 0, false, false); + DoHarmful(to); + AOS.Damage(to, this, damage, 100, 0, 0, 0, 0); + } + + 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(); + } } - - public GargoyleDestroyer(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a gargoyle corpse"; - public override string DefaultName => "a gargoyle destroyer"; - - public override bool BardImmune => !Core.AOS; - public override int Meat => 1; - public override bool CanFly => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.Rich); - AddLoot(LootPack.MedScrolls); - AddLoot(LootPack.Gems, 2); - } - - public override void OnDamagedBySpell(Mobile from) - { - if (from?.Alive == true && Utility.RandomDouble() < 0.4) - ThrowHatchet(from); - } - - public override void OnGotMeleeAttack(Mobile attacker) - { - base.OnGotMeleeAttack(attacker); - - if (attacker?.Alive == true && attacker.Weapon is BaseRanged && Utility.RandomDouble() < 0.4) - ThrowHatchet(attacker); - } - - public void ThrowHatchet(Mobile to) - { - int damage = 50; - MovingEffect(to, 0xF43, 10, 0, false, false); - DoHarmful(to); - AOS.Damage(to, this, damage, 100, 0, 0, 0, 0); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/GargoyleEnforcer.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/GargoyleEnforcer.cs index 23cb78f35..7db1f1ad8 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/GargoyleEnforcer.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/GargoyleEnforcer.cs @@ -2,76 +2,76 @@ using Server.Items; namespace Server.Mobiles { - public class GargoyleEnforcer : BaseCreature - { - [Constructible] - public GargoyleEnforcer() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class GargoyleEnforcer : BaseCreature { - Body = 0x2F2; - BaseSoundID = 0x174; + [Constructible] + public GargoyleEnforcer() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0x2F2; + BaseSoundID = 0x174; - SetStr(760, 850); - SetDex(102, 150); - SetInt(152, 200); + SetStr(760, 850); + SetDex(102, 150); + SetInt(152, 200); - SetHits(482, 485); + SetHits(482, 485); - SetDamage(7, 14); + SetDamage(7, 14); - SetResistance(ResistanceType.Physical, 40, 60); - SetResistance(ResistanceType.Fire, 50, 60); - SetResistance(ResistanceType.Cold, 20, 30); - SetResistance(ResistanceType.Poison, 25, 35); - SetResistance(ResistanceType.Energy, 15, 25); + SetResistance(ResistanceType.Physical, 40, 60); + SetResistance(ResistanceType.Fire, 50, 60); + SetResistance(ResistanceType.Cold, 20, 30); + SetResistance(ResistanceType.Poison, 25, 35); + SetResistance(ResistanceType.Energy, 15, 25); - SetSkill(SkillName.MagicResist, 120.1, 130.0); - SetSkill(SkillName.Tactics, 70.1, 80.0); - SetSkill(SkillName.Wrestling, 80.1, 90.0); - SetSkill(SkillName.Swords, 80.1, 90.0); - SetSkill(SkillName.Anatomy, 70.1, 80.0); - SetSkill(SkillName.Magery, 80.1, 90.0); - SetSkill(SkillName.EvalInt, 70.3, 100.0); - SetSkill(SkillName.Meditation, 70.3, 100.0); + SetSkill(SkillName.MagicResist, 120.1, 130.0); + SetSkill(SkillName.Tactics, 70.1, 80.0); + SetSkill(SkillName.Wrestling, 80.1, 90.0); + SetSkill(SkillName.Swords, 80.1, 90.0); + SetSkill(SkillName.Anatomy, 70.1, 80.0); + SetSkill(SkillName.Magery, 80.1, 90.0); + SetSkill(SkillName.EvalInt, 70.3, 100.0); + SetSkill(SkillName.Meditation, 70.3, 100.0); - Fame = 5000; - Karma = -5000; + Fame = 5000; + Karma = -5000; - VirtualArmor = 50; + VirtualArmor = 50; - if (Utility.RandomDouble() < 0.2) - PackItem(new GargoylesPickaxe()); + if (Utility.RandomDouble() < 0.2) + PackItem(new GargoylesPickaxe()); + } + + public GargoyleEnforcer(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a gargoyle corpse"; + + public override string DefaultName => "a gargoyle enforcer"; + + public override bool CanFly => true; + + public override int Meat => 1; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.WhirlwindAttack; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.MedScrolls); + } + + 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(); + } } - - public GargoyleEnforcer(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a gargoyle corpse"; - - public override string DefaultName => "a gargoyle enforcer"; - - public override bool CanFly => true; - - public override int Meat => 1; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.WhirlwindAttack; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.MedScrolls); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Gazer.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Gazer.cs index e2e69d2fa..47aa1d08a 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Gazer.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Gazer.cs @@ -2,70 +2,70 @@ using Server.Items; namespace Server.Mobiles { - public class Gazer : BaseCreature - { - [Constructible] - public Gazer() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Gazer : BaseCreature { - Body = 22; - BaseSoundID = 377; + [Constructible] + public Gazer() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 22; + BaseSoundID = 377; - SetStr(96, 125); - SetDex(86, 105); - SetInt(141, 165); + SetStr(96, 125); + SetDex(86, 105); + SetInt(141, 165); - SetHits(58, 75); + SetHits(58, 75); - SetDamage(5, 10); + SetDamage(5, 10); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 35, 40); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 20, 30); - SetResistance(ResistanceType.Poison, 10, 20); - SetResistance(ResistanceType.Energy, 20, 30); + SetResistance(ResistanceType.Physical, 35, 40); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 20, 30); + SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Energy, 20, 30); - SetSkill(SkillName.EvalInt, 50.1, 65.0); - SetSkill(SkillName.Magery, 50.1, 65.0); - SetSkill(SkillName.MagicResist, 60.1, 75.0); - SetSkill(SkillName.Tactics, 50.1, 70.0); - SetSkill(SkillName.Wrestling, 50.1, 70.0); + SetSkill(SkillName.EvalInt, 50.1, 65.0); + SetSkill(SkillName.Magery, 50.1, 65.0); + SetSkill(SkillName.MagicResist, 60.1, 75.0); + SetSkill(SkillName.Tactics, 50.1, 70.0); + SetSkill(SkillName.Wrestling, 50.1, 70.0); - Fame = 3500; - Karma = -3500; + Fame = 3500; + Karma = -3500; - VirtualArmor = 36; + VirtualArmor = 36; - PackItem(new Nightshade(4)); + PackItem(new Nightshade(4)); + } + + public Gazer(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a gazer corpse"; + public override string DefaultName => "a gazer"; + + public override int TreasureMapLevel => 1; + public override int Meat => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Potions); + } + + 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(); + } } - - public Gazer(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a gazer corpse"; - public override string DefaultName => "a gazer"; - - public override int TreasureMapLevel => 1; - public override int Meat => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Potions); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/GolemController.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/GolemController.cs index 811f8d1db..c9ca8d5cd 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/GolemController.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/GolemController.cs @@ -2,89 +2,89 @@ using Server.Items; namespace Server.Mobiles { - public class GolemController : BaseCreature - { - [Constructible] - public GolemController() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class GolemController : BaseCreature { - Name = NameList.RandomName("golem controller"); - Title = "the controller"; + [Constructible] + public GolemController() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Name = NameList.RandomName("golem controller"); + Title = "the controller"; - Body = 400; - Hue = 0x455; + Body = 400; + Hue = 0x455; - AddArcane(new Robe()); - AddArcane(new ThighBoots()); - AddArcane(new LeatherGloves()); - AddArcane(new Cloak()); + AddArcane(new Robe()); + AddArcane(new ThighBoots()); + AddArcane(new LeatherGloves()); + AddArcane(new Cloak()); - SetStr(126, 150); - SetDex(96, 120); - SetInt(151, 175); + SetStr(126, 150); + SetDex(96, 120); + SetInt(151, 175); - SetHits(76, 90); + SetHits(76, 90); - SetDamage(6, 12); + SetDamage(6, 12); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 30, 40); - SetResistance(ResistanceType.Fire, 25, 35); - SetResistance(ResistanceType.Cold, 35, 45); - SetResistance(ResistanceType.Poison, 5, 15); - SetResistance(ResistanceType.Energy, 15, 25); + SetResistance(ResistanceType.Physical, 30, 40); + SetResistance(ResistanceType.Fire, 25, 35); + SetResistance(ResistanceType.Cold, 35, 45); + SetResistance(ResistanceType.Poison, 5, 15); + SetResistance(ResistanceType.Energy, 15, 25); - SetSkill(SkillName.EvalInt, 95.1, 100.0); - SetSkill(SkillName.Magery, 95.1, 100.0); - SetSkill(SkillName.Meditation, 95.1, 100.0); - SetSkill(SkillName.MagicResist, 102.5, 125.0); - SetSkill(SkillName.Tactics, 65.0, 87.5); - SetSkill(SkillName.Wrestling, 65.0, 87.5); + SetSkill(SkillName.EvalInt, 95.1, 100.0); + SetSkill(SkillName.Magery, 95.1, 100.0); + SetSkill(SkillName.Meditation, 95.1, 100.0); + SetSkill(SkillName.MagicResist, 102.5, 125.0); + SetSkill(SkillName.Tactics, 65.0, 87.5); + SetSkill(SkillName.Wrestling, 65.0, 87.5); - Fame = 4000; - Karma = -4000; + Fame = 4000; + Karma = -4000; - VirtualArmor = 16; + VirtualArmor = 16; - if (Utility.RandomDouble() < 0.7) - PackItem(new ArcaneGem()); + if (Utility.RandomDouble() < 0.7) + PackItem(new ArcaneGem()); + } + + public GolemController(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a golem controller corpse"; + + public override bool ClickTitle => false; + public override bool ShowFameTitle => false; + public override bool AlwaysMurderer => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + } + + public void AddArcane(Item item) + { + if (item is IArcaneEquip eq) eq.CurArcaneCharges = eq.MaxArcaneCharges = 20; + + item.Hue = ArcaneGem.DefaultArcaneHue; + item.LootType = LootType.Newbied; + + AddItem(item); + } + + 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(); + } } - - public GolemController(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a golem controller corpse"; - - public override bool ClickTitle => false; - public override bool ShowFameTitle => false; - public override bool AlwaysMurderer => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - } - - public void AddArcane(Item item) - { - if (item is IArcaneEquip eq) eq.CurArcaneCharges = eq.MaxArcaneCharges = 20; - - item.Hue = ArcaneGem.DefaultArcaneHue; - item.LootType = LootType.Newbied; - - AddItem(item); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/IceFiend.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/IceFiend.cs index be9f9841a..8fa4cf347 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/IceFiend.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/IceFiend.cs @@ -1,67 +1,67 @@ namespace Server.Mobiles { - public class IceFiend : BaseCreature - { - [Constructible] - public IceFiend() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class IceFiend : BaseCreature { - Body = 43; - BaseSoundID = 357; + [Constructible] + public IceFiend() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 43; + BaseSoundID = 357; - SetStr(376, 405); - SetDex(176, 195); - SetInt(201, 225); + SetStr(376, 405); + SetDex(176, 195); + SetInt(201, 225); - SetHits(226, 243); + SetHits(226, 243); - SetDamage(8, 19); + SetDamage(8, 19); - SetSkill(SkillName.EvalInt, 80.1, 90.0); - SetSkill(SkillName.Magery, 80.1, 90.0); - SetSkill(SkillName.MagicResist, 75.1, 85.0); - SetSkill(SkillName.Tactics, 80.1, 90.0); - SetSkill(SkillName.Wrestling, 80.1, 100.0); + SetSkill(SkillName.EvalInt, 80.1, 90.0); + SetSkill(SkillName.Magery, 80.1, 90.0); + SetSkill(SkillName.MagicResist, 75.1, 85.0); + SetSkill(SkillName.Tactics, 80.1, 90.0); + SetSkill(SkillName.Wrestling, 80.1, 100.0); - SetResistance(ResistanceType.Physical, 55, 65); - SetResistance(ResistanceType.Fire, 10, 20); - SetResistance(ResistanceType.Cold, 60, 70); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 55, 65); + SetResistance(ResistanceType.Fire, 10, 20); + SetResistance(ResistanceType.Cold, 60, 70); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 30, 40); - Fame = 18000; - Karma = -18000; + Fame = 18000; + Karma = -18000; - VirtualArmor = 60; + VirtualArmor = 60; + } + + public IceFiend(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ice fiend corpse"; + public override string DefaultName => "an ice fiend"; + + public override int TreasureMapLevel => 4; + public override int Meat => 1; + public override bool CanFly => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.Average); + AddLoot(LootPack.MedScrolls, 2); + } + + 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(); + } } - - public IceFiend(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ice fiend corpse"; - public override string DefaultName => "an ice fiend"; - - public override int TreasureMapLevel => 4; - public override int Meat => 1; - public override bool CanFly => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.Average); - AddLoot(LootPack.MedScrolls, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Imp.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Imp.cs index 9588a8f25..43747d769 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Imp.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Imp.cs @@ -1,77 +1,77 @@ namespace Server.Mobiles { - public class Imp : BaseCreature - { - [Constructible] - public Imp() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Imp : BaseCreature { - Body = 74; - BaseSoundID = 422; + [Constructible] + public Imp() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 74; + BaseSoundID = 422; - SetStr(91, 115); - SetDex(61, 80); - SetInt(86, 105); + SetStr(91, 115); + SetDex(61, 80); + SetInt(86, 105); - SetHits(55, 70); + SetHits(55, 70); - SetDamage(10, 14); + SetDamage(10, 14); - SetDamageType(ResistanceType.Physical, 0); - SetDamageType(ResistanceType.Fire, 50); - SetDamageType(ResistanceType.Poison, 50); + SetDamageType(ResistanceType.Physical, 0); + SetDamageType(ResistanceType.Fire, 50); + SetDamageType(ResistanceType.Poison, 50); - SetResistance(ResistanceType.Physical, 25, 35); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 20, 30); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 25, 35); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 20, 30); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.EvalInt, 20.1, 30.0); - SetSkill(SkillName.Magery, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 30.1, 50.0); - SetSkill(SkillName.Tactics, 42.1, 50.0); - SetSkill(SkillName.Wrestling, 40.1, 44.0); + SetSkill(SkillName.EvalInt, 20.1, 30.0); + SetSkill(SkillName.Magery, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 30.1, 50.0); + SetSkill(SkillName.Tactics, 42.1, 50.0); + SetSkill(SkillName.Wrestling, 40.1, 44.0); - Fame = 2500; - Karma = -2500; + Fame = 2500; + Karma = -2500; - VirtualArmor = 30; + VirtualArmor = 30; - Tamable = true; - ControlSlots = 2; - MinTameSkill = 83.1; + Tamable = true; + ControlSlots = 2; + MinTameSkill = 83.1; + } + + public Imp(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an imp corpse"; + public override string DefaultName => "an imp"; + + public override int Meat => 1; + public override int Hides => 6; + public override HideType HideType => HideType.Spined; + public override FoodType FavoriteFood => FoodType.Meat; + public override PackInstinct PackInstinct => PackInstinct.Daemon; + public override bool CanFly => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + AddLoot(LootPack.MedScrolls, 2); + } + + 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(); + } } - - public Imp(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an imp corpse"; - public override string DefaultName => "an imp"; - - public override int Meat => 1; - public override int Hides => 6; - public override HideType HideType => HideType.Spined; - public override FoodType FavoriteFood => FoodType.Meat; - public override PackInstinct PackInstinct => PackInstinct.Daemon; - public override bool CanFly => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - AddLoot(LootPack.MedScrolls, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Lich.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Lich.cs index 62815d657..75926f12b 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Lich.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Lich.cs @@ -2,79 +2,79 @@ using Server.Items; namespace Server.Mobiles { - public class Lich : BaseCreature - { - [Constructible] - public Lich() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Lich : BaseCreature { - Body = 24; - BaseSoundID = 0x3E9; + [Constructible] + public Lich() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 24; + BaseSoundID = 0x3E9; - SetStr(171, 200); - SetDex(126, 145); - SetInt(276, 305); + SetStr(171, 200); + SetDex(126, 145); + SetInt(276, 305); - SetHits(103, 120); + SetHits(103, 120); - SetDamage(24, 26); + SetDamage(24, 26); - SetDamageType(ResistanceType.Physical, 10); - SetDamageType(ResistanceType.Cold, 40); - SetDamageType(ResistanceType.Energy, 50); + SetDamageType(ResistanceType.Physical, 10); + SetDamageType(ResistanceType.Cold, 40); + SetDamageType(ResistanceType.Energy, 50); - SetResistance(ResistanceType.Physical, 40, 60); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 55, 65); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 40, 60); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 55, 65); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.Necromancy, 89, 99.1); - SetSkill(SkillName.SpiritSpeak, 90.0, 99.0); + SetSkill(SkillName.Necromancy, 89, 99.1); + SetSkill(SkillName.SpiritSpeak, 90.0, 99.0); - SetSkill(SkillName.EvalInt, 100.0); - SetSkill(SkillName.Magery, 70.1, 80.0); - SetSkill(SkillName.Meditation, 85.1, 95.0); - SetSkill(SkillName.MagicResist, 80.1, 100.0); - SetSkill(SkillName.Tactics, 70.1, 90.0); + SetSkill(SkillName.EvalInt, 100.0); + SetSkill(SkillName.Magery, 70.1, 80.0); + SetSkill(SkillName.Meditation, 85.1, 95.0); + SetSkill(SkillName.MagicResist, 80.1, 100.0); + SetSkill(SkillName.Tactics, 70.1, 90.0); - Fame = 8000; - Karma = -8000; + Fame = 8000; + Karma = -8000; - VirtualArmor = 50; - PackItem(new GnarledStaff()); - PackNecroReg(17, 24); + VirtualArmor = 50; + PackItem(new GnarledStaff()); + PackNecroReg(17, 24); + } + + public Lich(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a lich's corpse"; + public override string DefaultName => "a lich"; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override bool CanRummageCorpses => true; + public override bool BleedImmune => true; + public override Poison PoisonImmune => Poison.Lethal; + public override int TreasureMapLevel => 3; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.MedScrolls, 2); + } + + 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(); + } } - - public Lich(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a lich's corpse"; - public override string DefaultName => "a lich"; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override bool CanRummageCorpses => true; - public override bool BleedImmune => true; - public override Poison PoisonImmune => Poison.Lethal; - public override int TreasureMapLevel => 3; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.MedScrolls, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/LichLord.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/LichLord.cs index c7c4ebb1d..1717af145 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/LichLord.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/LichLord.cs @@ -2,79 +2,79 @@ using Server.Items; namespace Server.Mobiles { - public class LichLord : BaseCreature - { - [Constructible] - public LichLord() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class LichLord : BaseCreature { - Body = 79; - BaseSoundID = 412; + [Constructible] + public LichLord() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 79; + BaseSoundID = 412; - SetStr(416, 505); - SetDex(146, 165); - SetInt(566, 655); + SetStr(416, 505); + SetDex(146, 165); + SetInt(566, 655); - SetHits(250, 303); + SetHits(250, 303); - SetDamage(11, 13); + SetDamage(11, 13); - SetDamageType(ResistanceType.Physical, 0); - SetDamageType(ResistanceType.Cold, 60); - SetDamageType(ResistanceType.Energy, 40); + SetDamageType(ResistanceType.Physical, 0); + SetDamageType(ResistanceType.Cold, 60); + SetDamageType(ResistanceType.Energy, 40); - SetResistance(ResistanceType.Physical, 40, 50); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 50, 60); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 40, 50); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 50, 60); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.Necromancy, 90, 110.0); - SetSkill(SkillName.SpiritSpeak, 90.0, 110.0); + SetSkill(SkillName.Necromancy, 90, 110.0); + SetSkill(SkillName.SpiritSpeak, 90.0, 110.0); - SetSkill(SkillName.EvalInt, 90.1, 100.0); - SetSkill(SkillName.Magery, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 150.5, 200.0); - SetSkill(SkillName.Tactics, 50.1, 70.0); - SetSkill(SkillName.Wrestling, 60.1, 80.0); + SetSkill(SkillName.EvalInt, 90.1, 100.0); + SetSkill(SkillName.Magery, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 150.5, 200.0); + SetSkill(SkillName.Tactics, 50.1, 70.0); + SetSkill(SkillName.Wrestling, 60.1, 80.0); - Fame = 18000; - Karma = -18000; + Fame = 18000; + Karma = -18000; - VirtualArmor = 50; - PackItem(new GnarledStaff()); - PackNecroReg(12, 40); + VirtualArmor = 50; + PackItem(new GnarledStaff()); + PackNecroReg(12, 40); + } + + public LichLord(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a lich's corpse"; + public override string DefaultName => "a lich lord"; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override bool CanRummageCorpses => true; + public override bool BleedImmune => true; + public override Poison PoisonImmune => Poison.Lethal; + public override int TreasureMapLevel => 4; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.MedScrolls, 2); + } + + 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(); + } } - - public LichLord(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a lich's corpse"; - public override string DefaultName => "a lich lord"; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override bool CanRummageCorpses => true; - public override bool BleedImmune => true; - public override Poison PoisonImmune => Poison.Lethal; - public override int TreasureMapLevel => 4; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.MedScrolls, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/OrcishMage.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/OrcishMage.cs index e64071465..3b7d34c91 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/OrcishMage.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/OrcishMage.cs @@ -3,101 +3,101 @@ using Server.Misc; namespace Server.Mobiles { - public class OrcishMage : BaseCreature - { - [Constructible] - public OrcishMage() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class OrcishMage : BaseCreature { - Body = 140; - BaseSoundID = 0x45A; + [Constructible] + public OrcishMage() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 140; + BaseSoundID = 0x45A; - SetStr(116, 150); - SetDex(91, 115); - SetInt(161, 185); + SetStr(116, 150); + SetDex(91, 115); + SetInt(161, 185); - SetHits(70, 90); + SetHits(70, 90); - SetDamage(4, 14); + SetDamage(4, 14); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 25, 35); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 20, 30); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 25, 35); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 20, 30); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.EvalInt, 60.1, 72.5); - SetSkill(SkillName.Magery, 60.1, 72.5); - SetSkill(SkillName.MagicResist, 60.1, 75.0); - SetSkill(SkillName.Tactics, 50.1, 65.0); - SetSkill(SkillName.Wrestling, 40.1, 50.0); + SetSkill(SkillName.EvalInt, 60.1, 72.5); + SetSkill(SkillName.Magery, 60.1, 72.5); + SetSkill(SkillName.MagicResist, 60.1, 75.0); + SetSkill(SkillName.Tactics, 50.1, 65.0); + SetSkill(SkillName.Wrestling, 40.1, 50.0); - Fame = 3000; - Karma = -3000; + Fame = 3000; + Karma = -3000; - VirtualArmor = 30; + VirtualArmor = 30; - PackReg(6); + PackReg(6); - if (Utility.RandomDouble() < 0.05) - PackItem(new OrcishKinMask()); + if (Utility.RandomDouble() < 0.05) + PackItem(new OrcishKinMask()); + } + + public OrcishMage(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a glowing orc corpse"; + public override InhumanSpeech SpeechType => InhumanSpeech.Orc; + + public override string DefaultName => "an orcish mage"; + + public override bool CanRummageCorpses => true; + public override int TreasureMapLevel => 1; + public override int Meat => 1; + + public override OppositionGroup OppositionGroup => OppositionGroup.SavagesAndOrcs; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.LowScrolls); + } + + public override bool IsEnemy(Mobile m) + { + if (m.Player && m.FindItemOnLayer(Layer.Helm) is OrcishKinMask) + return false; + + return base.IsEnemy(m); + } + + public override void AggressiveAction(Mobile aggressor, bool criminal) + { + base.AggressiveAction(aggressor, criminal); + + var item = aggressor.FindItemOnLayer(Layer.Helm); + + if (item is OrcishKinMask) + { + AOS.Damage(aggressor, 50, 0, 100, 0, 0, 0); + item.Delete(); + aggressor.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); + aggressor.PlaySound(0x307); + } + } + + 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(); + } } - - public OrcishMage(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a glowing orc corpse"; - public override InhumanSpeech SpeechType => InhumanSpeech.Orc; - - public override string DefaultName => "an orcish mage"; - - public override bool CanRummageCorpses => true; - public override int TreasureMapLevel => 1; - public override int Meat => 1; - - public override OppositionGroup OppositionGroup => OppositionGroup.SavagesAndOrcs; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.LowScrolls); - } - - public override bool IsEnemy(Mobile m) - { - if (m.Player && m.FindItemOnLayer(Layer.Helm) is OrcishKinMask) - return false; - - return base.IsEnemy(m); - } - - public override void AggressiveAction(Mobile aggressor, bool criminal) - { - base.AggressiveAction(aggressor, criminal); - - Item item = aggressor.FindItemOnLayer(Layer.Helm); - - if (item is OrcishKinMask) - { - AOS.Damage(aggressor, 50, 0, 100, 0, 0, 0); - item.Delete(); - aggressor.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); - aggressor.PlaySound(0x307); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/RatmanMage.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/RatmanMage.cs index 73e62e5a9..130c94b27 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/RatmanMage.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/RatmanMage.cs @@ -2,82 +2,82 @@ using Server.Misc; namespace Server.Mobiles { - public class RatmanMage : BaseCreature - { - [Constructible] - public RatmanMage() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class RatmanMage : BaseCreature { - Name = NameList.RandomName("ratman"); - Body = 0x8F; - BaseSoundID = 437; + [Constructible] + public RatmanMage() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Name = NameList.RandomName("ratman"); + Body = 0x8F; + BaseSoundID = 437; - SetStr(146, 180); - SetDex(101, 130); - SetInt(186, 210); + SetStr(146, 180); + SetDex(101, 130); + SetInt(186, 210); - SetHits(88, 108); + SetHits(88, 108); - SetDamage(7, 14); + SetDamage(7, 14); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 40, 45); - SetResistance(ResistanceType.Fire, 10, 20); - SetResistance(ResistanceType.Cold, 10, 20); - SetResistance(ResistanceType.Poison, 10, 20); - SetResistance(ResistanceType.Energy, 10, 20); + SetResistance(ResistanceType.Physical, 40, 45); + SetResistance(ResistanceType.Fire, 10, 20); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Energy, 10, 20); - SetSkill(SkillName.EvalInt, 70.1, 80.0); - SetSkill(SkillName.Magery, 70.1, 80.0); - SetSkill(SkillName.MagicResist, 65.1, 90.0); - SetSkill(SkillName.Tactics, 50.1, 75.0); - SetSkill(SkillName.Wrestling, 50.1, 75.0); + SetSkill(SkillName.EvalInt, 70.1, 80.0); + SetSkill(SkillName.Magery, 70.1, 80.0); + SetSkill(SkillName.MagicResist, 65.1, 90.0); + SetSkill(SkillName.Tactics, 50.1, 75.0); + SetSkill(SkillName.Wrestling, 50.1, 75.0); - Fame = 7500; - Karma = -7500; + Fame = 7500; + Karma = -7500; - VirtualArmor = 44; + VirtualArmor = 44; - PackReg(6); + PackReg(6); - if (Utility.RandomDouble() < 0.02) - PackStatue(); + if (Utility.RandomDouble() < 0.02) + PackStatue(); + } + + public RatmanMage(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a glowing ratman corpse"; + public override InhumanSpeech SpeechType => InhumanSpeech.Ratman; + + public override bool CanRummageCorpses => true; + public override int Meat => 1; + public override int Hides => 8; + public override HideType HideType => HideType.Spined; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.LowScrolls); + } + + 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 (Body == 42) + { + Body = 0x8F; + Hue = 0; + } + } } - - public RatmanMage(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a glowing ratman corpse"; - public override InhumanSpeech SpeechType => InhumanSpeech.Ratman; - - public override bool CanRummageCorpses => true; - public override int Meat => 1; - public override int Hides => 8; - public override HideType HideType => HideType.Spined; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.LowScrolls); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Body == 42) - { - Body = 0x8F; - Hue = 0; - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/SavageShaman.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/SavageShaman.cs index f57cbe7f7..89a90135e 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/SavageShaman.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/SavageShaman.cs @@ -5,275 +5,275 @@ using Server.Spells; namespace Server.Mobiles { - public class SavageShaman : BaseCreature - { - [Constructible] - public SavageShaman() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class SavageShaman : BaseCreature { - Name = NameList.RandomName("savage shaman"); - - if (Utility.RandomBool()) - Body = 184; - else - Body = 183; - - SetStr(126, 145); - SetDex(91, 110); - SetInt(161, 185); - - SetDamage(4, 10); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 30, 40); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 20, 30); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 40, 50); - - SetSkill(SkillName.EvalInt, 77.5, 100.0); - SetSkill(SkillName.Fencing, 62.5, 85.0); - SetSkill(SkillName.Macing, 62.5, 85.0); - SetSkill(SkillName.Magery, 72.5, 95.0); - SetSkill(SkillName.Meditation, 77.5, 100.0); - SetSkill(SkillName.MagicResist, 77.5, 100.0); - SetSkill(SkillName.Swords, 62.5, 85.0); - SetSkill(SkillName.Tactics, 62.5, 85.0); - SetSkill(SkillName.Wrestling, 62.5, 85.0); - - Fame = 1000; - Karma = -1000; - - PackReg(10, 15); - PackItem(new Bandage(Utility.RandomMinMax(1, 15))); - - if (Utility.RandomDouble() < 0.1) - PackItem(new TribalBerry()); - - AddItem(new BoneArms()); - AddItem(new BoneLegs()); - AddItem(new DeerMask()); - } - - public SavageShaman(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a savage corpse"; - - public override int Meat => 1; - public override bool AlwaysMurderer => true; - public override bool ShowFameTitle => false; - - public override OppositionGroup OppositionGroup => OppositionGroup.SavagesAndOrcs; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - } - - public override bool IsEnemy(Mobile m) - { - if (m.BodyMod == 183 || m.BodyMod == 184) - return false; - - return base.IsEnemy(m); - } - - public override void AggressiveAction(Mobile aggressor, bool criminal) - { - base.AggressiveAction(aggressor, criminal); - - if (aggressor.BodyMod == 183 || aggressor.BodyMod == 184) - { - AOS.Damage(aggressor, 50, 0, 100, 0, 0, 0); - aggressor.BodyMod = 0; - aggressor.HueMod = -1; - aggressor.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); - aggressor.PlaySound(0x307); - aggressor.SendLocalizedMessage(1040008); // Your skin is scorched as the tribal paint burns away! - - if (aggressor is PlayerMobile mobile) - mobile.SavagePaintExpiration = TimeSpan.Zero; - } - } - - public override void AlterMeleeDamageTo(Mobile to, ref int damage) - { - if (to is Dragon || to is WhiteWyrm || to is SwampDragon || to is Drake || to is Nightmare || to is Hiryu || - to is LesserHiryu || to is Daemon) - damage *= 3; - } - - public override void OnGotMeleeAttack(Mobile attacker) - { - base.OnGotMeleeAttack(attacker); - - if (Utility.RandomDouble() < 0.1) - BeginSavageDance(); - } - - public void BeginSavageDance() - { - if (Map == null) - return; - - List list = new List(); - - foreach (Mobile m in GetMobilesInRange(8)) - if (m != this && m is SavageShaman ss) - list.Add(ss); - - Animate(111, 5, 1, true, false, 0); // Do a little dance... - - if (AIObject != null) - AIObject.NextMove = Core.TickCount + 1000; - - if (list.Count >= 3) - { - for (int i = 0; i < list.Count; ++i) + [Constructible] + public SavageShaman() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) { - SavageShaman dancer = list[i]; + Name = NameList.RandomName("savage shaman"); - dancer.Animate(111, 5, 1, true, false, 0); // Get down tonight... + if (Utility.RandomBool()) + Body = 184; + else + Body = 183; - if (dancer.AIObject != null) - dancer.AIObject.NextMove = Core.TickCount + 1000; + SetStr(126, 145); + SetDex(91, 110); + SetInt(161, 185); + + SetDamage(4, 10); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 30, 40); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 20, 30); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 40, 50); + + SetSkill(SkillName.EvalInt, 77.5, 100.0); + SetSkill(SkillName.Fencing, 62.5, 85.0); + SetSkill(SkillName.Macing, 62.5, 85.0); + SetSkill(SkillName.Magery, 72.5, 95.0); + SetSkill(SkillName.Meditation, 77.5, 100.0); + SetSkill(SkillName.MagicResist, 77.5, 100.0); + SetSkill(SkillName.Swords, 62.5, 85.0); + SetSkill(SkillName.Tactics, 62.5, 85.0); + SetSkill(SkillName.Wrestling, 62.5, 85.0); + + Fame = 1000; + Karma = -1000; + + PackReg(10, 15); + PackItem(new Bandage(Utility.RandomMinMax(1, 15))); + + if (Utility.RandomDouble() < 0.1) + PackItem(new TribalBerry()); + + AddItem(new BoneArms()); + AddItem(new BoneLegs()); + AddItem(new DeerMask()); } - Timer.DelayCall(TimeSpan.FromSeconds(1.0), EndSavageDance); - } - } + public SavageShaman(Serial serial) : base(serial) + { + } - public void EndSavageDance() - { - if (Deleted) - return; + public override string CorpseName => "a savage corpse"; - IPooledEnumerable eable = GetMobilesInRange(8); + public override int Meat => 1; + public override bool AlwaysMurderer => true; + public override bool ShowFameTitle => false; - switch (Utility.Random(3)) - { - case 0: /* greater heal */ - { - foreach (Mobile m in eable) + public override OppositionGroup OppositionGroup => OppositionGroup.SavagesAndOrcs; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + } + + public override bool IsEnemy(Mobile m) + { + if (m.BodyMod == 183 || m.BodyMod == 184) + return false; + + return base.IsEnemy(m); + } + + public override void AggressiveAction(Mobile aggressor, bool criminal) + { + base.AggressiveAction(aggressor, criminal); + + if (aggressor.BodyMod == 183 || aggressor.BodyMod == 184) { - bool isFriendly = m is Savage || m is SavageRider || m is SavageShaman || m is SavageRidgeback; + AOS.Damage(aggressor, 50, 0, 100, 0, 0, 0); + aggressor.BodyMod = 0; + aggressor.HueMod = -1; + aggressor.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); + aggressor.PlaySound(0x307); + aggressor.SendLocalizedMessage(1040008); // Your skin is scorched as the tribal paint burns away! - if (!isFriendly) - continue; + if (aggressor is PlayerMobile mobile) + mobile.SavagePaintExpiration = TimeSpan.Zero; + } + } - if (m.Poisoned || MortalStrike.IsWounded(m) || !CanBeBeneficial(m)) - continue; + public override void AlterMeleeDamageTo(Mobile to, ref int damage) + { + if (to is Dragon || to is WhiteWyrm || to is SwampDragon || to is Drake || to is Nightmare || to is Hiryu || + to is LesserHiryu || to is Daemon) + damage *= 3; + } - DoBeneficial(m); + public override void OnGotMeleeAttack(Mobile attacker) + { + base.OnGotMeleeAttack(attacker); - // Algorithm: (40% of magery) + (1-10) + if (Utility.RandomDouble() < 0.1) + BeginSavageDance(); + } - int toHeal = (int)(Skills.Magery.Value * 0.4); - toHeal += Utility.Random(1, 10); + public void BeginSavageDance() + { + if (Map == null) + return; - m.Heal(toHeal, this); + var list = new List(); - m.FixedParticles(0x376A, 9, 32, 5030, EffectLayer.Waist); - m.PlaySound(0x202); + foreach (var m in GetMobilesInRange(8)) + if (m != this && m is SavageShaman ss) + list.Add(ss); + + Animate(111, 5, 1, true, false, 0); // Do a little dance... + + if (AIObject != null) + AIObject.NextMove = Core.TickCount + 1000; + + if (list.Count >= 3) + { + for (var i = 0; i < list.Count; ++i) + { + var dancer = list[i]; + + dancer.Animate(111, 5, 1, true, false, 0); // Get down tonight... + + if (dancer.AIObject != null) + dancer.AIObject.NextMove = Core.TickCount + 1000; + } + + Timer.DelayCall(TimeSpan.FromSeconds(1.0), EndSavageDance); + } + } + + public void EndSavageDance() + { + if (Deleted) + return; + + var eable = GetMobilesInRange(8); + + switch (Utility.Random(3)) + { + case 0: /* greater heal */ + { + foreach (var m in eable) + { + var isFriendly = m is Savage || m is SavageRider || m is SavageShaman || m is SavageRidgeback; + + if (!isFriendly) + continue; + + if (m.Poisoned || MortalStrike.IsWounded(m) || !CanBeBeneficial(m)) + continue; + + DoBeneficial(m); + + // Algorithm: (40% of magery) + (1-10) + + var toHeal = (int)(Skills.Magery.Value * 0.4); + toHeal += Utility.Random(1, 10); + + m.Heal(toHeal, this); + + m.FixedParticles(0x376A, 9, 32, 5030, EffectLayer.Waist); + m.PlaySound(0x202); + } + + break; + } + case 1: /* lightning */ + { + foreach (var m in eable) + { + var isFriendly = m is Savage || m is SavageRider || m is SavageShaman || m is SavageRidgeback; + + if (isFriendly) + continue; + + if (!CanBeHarmful(m)) + continue; + + DoHarmful(m); + + double damage; + + if (Core.AOS) + { + var baseDamage = 6 + (int)(Skills.EvalInt.Value / 5.0); + + damage = Utility.RandomMinMax(baseDamage, baseDamage + 3); + } + else + { + damage = Utility.Random(12, 9); + } + + m.BoltEffect(0); + + SpellHelper.Damage(TimeSpan.FromSeconds(0.25), m, this, damage, 0, 0, 0, 0, 100); + } + + break; + } + case 2: /* poison */ + { + foreach (var m in eable) + { + var isFriendly = m is Savage || m is SavageRider || m is SavageShaman || m is SavageRidgeback; + + if (isFriendly) + continue; + + if (!CanBeHarmful(m)) + continue; + + DoHarmful(m); + + m.Spell?.OnCasterHurt(); + + m.Paralyzed = false; + + var total = Skills.Magery.Value + Skills.Poisoning.Value; + + var dist = GetDistanceToSqrt(m); + + if (dist >= 3.0) + total -= (dist - 3.0) * 10.0; + + int level; + + if (total >= 200.0 && Utility.Random(1, 100) <= 10) + level = 3; + else if (total > 170.0) + level = 2; + else if (total > 130.0) + level = 1; + else + level = 0; + + m.ApplyPoison(this, Poison.GetPoison(level)); + + m.FixedParticles(0x374A, 10, 15, 5021, EffectLayer.Waist); + m.PlaySound(0x474); + } + + break; + } } - break; - } - case 1: /* lightning */ - { - foreach (Mobile m in eable) - { - bool isFriendly = m is Savage || m is SavageRider || m is SavageShaman || m is SavageRidgeback; + eable.Free(); + } - if (isFriendly) - continue; + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(0); + } - if (!CanBeHarmful(m)) - continue; - - DoHarmful(m); - - double damage; - - if (Core.AOS) - { - int baseDamage = 6 + (int)(Skills.EvalInt.Value / 5.0); - - damage = Utility.RandomMinMax(baseDamage, baseDamage + 3); - } - else - { - damage = Utility.Random(12, 9); - } - - m.BoltEffect(0); - - SpellHelper.Damage(TimeSpan.FromSeconds(0.25), m, this, damage, 0, 0, 0, 0, 100); - } - - break; - } - case 2: /* poison */ - { - foreach (Mobile m in eable) - { - bool isFriendly = m is Savage || m is SavageRider || m is SavageShaman || m is SavageRidgeback; - - if (isFriendly) - continue; - - if (!CanBeHarmful(m)) - continue; - - DoHarmful(m); - - m.Spell?.OnCasterHurt(); - - m.Paralyzed = false; - - double total = Skills.Magery.Value + Skills.Poisoning.Value; - - double dist = GetDistanceToSqrt(m); - - if (dist >= 3.0) - total -= (dist - 3.0) * 10.0; - - int level; - - if (total >= 200.0 && Utility.Random(1, 100) <= 10) - level = 3; - else if (total > 170.0) - level = 2; - else if (total > 130.0) - level = 1; - else - level = 0; - - m.ApplyPoison(this, Poison.GetPoison(level)); - - m.FixedParticles(0x374A, 10, 15, 5021, EffectLayer.Waist); - m.PlaySound(0x474); - } - - break; - } - } - - eable.Free(); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Shade.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Shade.cs index b69381e89..06fc00dd9 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Shade.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Shade.cs @@ -1,71 +1,71 @@ namespace Server.Mobiles { - public class Shade : BaseCreature - { - [Constructible] - public Shade() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Shade : BaseCreature { - Body = 26; - Hue = 0x4001; - BaseSoundID = 0x482; + [Constructible] + public Shade() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 26; + Hue = 0x4001; + BaseSoundID = 0x482; - SetStr(76, 100); - SetDex(76, 95); - SetInt(36, 60); + SetStr(76, 100); + SetDex(76, 95); + SetInt(36, 60); - SetHits(46, 60); + SetHits(46, 60); - SetDamage(7, 11); + SetDamage(7, 11); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Cold, 50); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Cold, 50); - SetResistance(ResistanceType.Physical, 25, 30); - SetResistance(ResistanceType.Cold, 15, 25); - SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Physical, 25, 30); + SetResistance(ResistanceType.Cold, 15, 25); + SetResistance(ResistanceType.Poison, 10, 20); - SetSkill(SkillName.EvalInt, 55.1, 70.0); - SetSkill(SkillName.Magery, 55.1, 70.0); - SetSkill(SkillName.MagicResist, 55.1, 70.0); - SetSkill(SkillName.Tactics, 45.1, 60.0); - SetSkill(SkillName.Wrestling, 45.1, 55.0); + SetSkill(SkillName.EvalInt, 55.1, 70.0); + SetSkill(SkillName.Magery, 55.1, 70.0); + SetSkill(SkillName.MagicResist, 55.1, 70.0); + SetSkill(SkillName.Tactics, 45.1, 60.0); + SetSkill(SkillName.Wrestling, 45.1, 55.0); - Fame = 4000; - Karma = -4000; + Fame = 4000; + Karma = -4000; - VirtualArmor = 28; + VirtualArmor = 28; - PackReg(10); + PackReg(10); + } + + public Shade(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a ghostly corpse"; + public override string DefaultName => "a shade"; + + public override bool BleedImmune => true; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override Poison PoisonImmune => Poison.Lethal; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + 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(); + } } - - public Shade(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a ghostly corpse"; - public override string DefaultName => "a shade"; - - public override bool BleedImmune => true; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override Poison PoisonImmune => Poison.Lethal; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/SkeletalMage.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/SkeletalMage.cs index d7fb6768d..ad767f10d 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/SkeletalMage.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/SkeletalMage.cs @@ -2,77 +2,77 @@ using Server.Items; namespace Server.Mobiles { - public class SkeletalMage : BaseCreature - { - [Constructible] - public SkeletalMage() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class SkeletalMage : BaseCreature { - Body = 148; - BaseSoundID = 451; + [Constructible] + public SkeletalMage() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 148; + BaseSoundID = 451; - SetStr(76, 100); - SetDex(56, 75); - SetInt(186, 210); + SetStr(76, 100); + SetDex(56, 75); + SetInt(186, 210); - SetHits(46, 60); + SetHits(46, 60); - SetDamage(3, 7); + SetDamage(3, 7); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 35, 40); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 35, 40); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.EvalInt, 60.1, 70.0); - SetSkill(SkillName.Magery, 60.1, 70.0); - SetSkill(SkillName.MagicResist, 55.1, 70.0); - SetSkill(SkillName.Tactics, 45.1, 60.0); - SetSkill(SkillName.Wrestling, 45.1, 55.0); - SetSkill(SkillName.Necromancy, 89, 99.1); - SetSkill(SkillName.SpiritSpeak, 90.0, 99.0); + SetSkill(SkillName.EvalInt, 60.1, 70.0); + SetSkill(SkillName.Magery, 60.1, 70.0); + SetSkill(SkillName.MagicResist, 55.1, 70.0); + SetSkill(SkillName.Tactics, 45.1, 60.0); + SetSkill(SkillName.Wrestling, 45.1, 55.0); + SetSkill(SkillName.Necromancy, 89, 99.1); + SetSkill(SkillName.SpiritSpeak, 90.0, 99.0); - Fame = 3000; - Karma = -3000; + Fame = 3000; + Karma = -3000; - VirtualArmor = 38; - PackReg(3); - PackNecroReg(3, 10); - PackItem(new Bone()); + VirtualArmor = 38; + PackReg(3); + PackNecroReg(3, 10); + PackItem(new Bone()); + } + + public SkeletalMage(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a skeletal corpse"; + public override string DefaultName => "a skeletal mage"; + + public override bool BleedImmune => true; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override Poison PoisonImmune => Poison.Regular; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.LowScrolls); + AddLoot(LootPack.Potions); + } + + 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(); + } } - - public SkeletalMage(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a skeletal corpse"; - public override string DefaultName => "a skeletal mage"; - - public override bool BleedImmune => true; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override Poison PoisonImmune => Poison.Regular; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.LowScrolls); - AddLoot(LootPack.Potions); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Spectre.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Spectre.cs index a4ce73d20..fdff55b9b 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Spectre.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Spectre.cs @@ -1,71 +1,71 @@ namespace Server.Mobiles { - public class Spectre : BaseCreature - { - [Constructible] - public Spectre() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Spectre : BaseCreature { - Body = 26; - Hue = 0x4001; - BaseSoundID = 0x482; + [Constructible] + public Spectre() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 26; + Hue = 0x4001; + BaseSoundID = 0x482; - SetStr(76, 100); - SetDex(76, 95); - SetInt(36, 60); + SetStr(76, 100); + SetDex(76, 95); + SetInt(36, 60); - SetHits(46, 60); + SetHits(46, 60); - SetDamage(7, 11); + SetDamage(7, 11); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Cold, 50); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Cold, 50); - SetResistance(ResistanceType.Physical, 25, 30); - SetResistance(ResistanceType.Cold, 15, 25); - SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Physical, 25, 30); + SetResistance(ResistanceType.Cold, 15, 25); + SetResistance(ResistanceType.Poison, 10, 20); - SetSkill(SkillName.EvalInt, 55.1, 70.0); - SetSkill(SkillName.Magery, 55.1, 70.0); - SetSkill(SkillName.MagicResist, 55.1, 70.0); - SetSkill(SkillName.Tactics, 45.1, 60.0); - SetSkill(SkillName.Wrestling, 45.1, 55.0); + SetSkill(SkillName.EvalInt, 55.1, 70.0); + SetSkill(SkillName.Magery, 55.1, 70.0); + SetSkill(SkillName.MagicResist, 55.1, 70.0); + SetSkill(SkillName.Tactics, 45.1, 60.0); + SetSkill(SkillName.Wrestling, 45.1, 55.0); - Fame = 4000; - Karma = -4000; + Fame = 4000; + Karma = -4000; - VirtualArmor = 28; + VirtualArmor = 28; - PackReg(10); + PackReg(10); + } + + public Spectre(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a ghostly corpse"; + public override string DefaultName => "a spectre"; + + public override bool BleedImmune => true; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override Poison PoisonImmune => Poison.Lethal; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + 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(); + } } - - public Spectre(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a ghostly corpse"; - public override string DefaultName => "a spectre"; - - public override bool BleedImmune => true; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override Poison PoisonImmune => Poison.Lethal; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Succubus.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Succubus.cs index 2a1fc0ee8..94e7dc538 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Succubus.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Succubus.cs @@ -1,112 +1,112 @@ namespace Server.Mobiles { - public class Succubus : BaseCreature - { - [Constructible] - public Succubus() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Succubus : BaseCreature { - Body = 149; - BaseSoundID = 0x4B0; + [Constructible] + public Succubus() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 149; + BaseSoundID = 0x4B0; - SetStr(488, 620); - SetDex(121, 170); - SetInt(498, 657); + SetStr(488, 620); + SetDex(121, 170); + SetInt(498, 657); - SetHits(312, 353); + SetHits(312, 353); - SetDamage(18, 28); + SetDamage(18, 28); - SetDamageType(ResistanceType.Physical, 75); - SetDamageType(ResistanceType.Energy, 25); + SetDamageType(ResistanceType.Physical, 75); + SetDamageType(ResistanceType.Energy, 25); - SetResistance(ResistanceType.Physical, 80, 90); - SetResistance(ResistanceType.Fire, 70, 80); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 50, 60); - SetResistance(ResistanceType.Energy, 50, 60); + SetResistance(ResistanceType.Physical, 80, 90); + SetResistance(ResistanceType.Fire, 70, 80); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 50, 60); + SetResistance(ResistanceType.Energy, 50, 60); - SetSkill(SkillName.EvalInt, 90.1, 100.0); - SetSkill(SkillName.Magery, 99.1, 100.0); - SetSkill(SkillName.Meditation, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 100.5, 150.0); - SetSkill(SkillName.Tactics, 80.1, 90.0); - SetSkill(SkillName.Wrestling, 80.1, 90.0); + SetSkill(SkillName.EvalInt, 90.1, 100.0); + SetSkill(SkillName.Magery, 99.1, 100.0); + SetSkill(SkillName.Meditation, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 100.5, 150.0); + SetSkill(SkillName.Tactics, 80.1, 90.0); + SetSkill(SkillName.Wrestling, 80.1, 90.0); - Fame = 24000; - Karma = -24000; + Fame = 24000; + Karma = -24000; - VirtualArmor = 80; + VirtualArmor = 80; + } + + public Succubus(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a succubus corpse"; + public override string DefaultName => "a succubus"; + + public override int Meat => 1; + public override int TreasureMapLevel => 5; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 2); + AddLoot(LootPack.MedScrolls, 2); + } + + public void DrainLife() + { + var eable = GetMobilesInRange(2); + + foreach (var m in eable) + { + if (m == this || !CanBeHarmful(m) || + !(m.Player || m is BaseCreature creature && + (creature.Controlled || creature.Summoned || creature.Team != Team))) + continue; + + DoHarmful(m); + + m.FixedParticles(0x374A, 10, 15, 5013, 0x496, 0, EffectLayer.Waist); + m.PlaySound(0x231); + + // m.SendMessage( "You feel the life drain out of you!" ); + + var toDrain = Utility.RandomMinMax(10, 40); + + Hits += toDrain; + m.Damage(toDrain, this); + } + + eable.Free(); + } + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomDouble() <= 0.1) + DrainLife(); + } + + public override void OnGotMeleeAttack(Mobile attacker) + { + base.OnGotMeleeAttack(attacker); + + if (Utility.RandomDouble() <= 0.1) + DrainLife(); + } + + 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(); + } } - - public Succubus(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a succubus corpse"; - public override string DefaultName => "a succubus"; - - public override int Meat => 1; - public override int TreasureMapLevel => 5; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 2); - AddLoot(LootPack.MedScrolls, 2); - } - - public void DrainLife() - { - IPooledEnumerable eable = GetMobilesInRange(2); - - foreach (Mobile m in eable) - { - if (m == this || !CanBeHarmful(m) || - !(m.Player || (m is BaseCreature creature && - (creature.Controlled || creature.Summoned || creature.Team != Team)))) - continue; - - DoHarmful(m); - - m.FixedParticles(0x374A, 10, 15, 5013, 0x496, 0, EffectLayer.Waist); - m.PlaySound(0x231); - - // m.SendMessage( "You feel the life drain out of you!" ); - - int toDrain = Utility.RandomMinMax(10, 40); - - Hits += toDrain; - m.Damage(toDrain, this); - } - - eable.Free(); - } - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (Utility.RandomDouble() <= 0.1) - DrainLife(); - } - - public override void OnGotMeleeAttack(Mobile attacker) - { - base.OnGotMeleeAttack(attacker); - - if (Utility.RandomDouble() <= 0.1) - DrainLife(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Titan.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Titan.cs index 5b567cbfb..136a8ca50 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Titan.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Titan.cs @@ -2,73 +2,73 @@ using Server.Engines.Plants; namespace Server.Mobiles { - public class Titan : BaseCreature - { - [Constructible] - public Titan() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Titan : BaseCreature { - Body = 76; - BaseSoundID = 609; + [Constructible] + public Titan() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 76; + BaseSoundID = 609; - SetStr(536, 585); - SetDex(126, 145); - SetInt(281, 305); + SetStr(536, 585); + SetDex(126, 145); + SetInt(281, 305); - SetHits(322, 351); + SetHits(322, 351); - SetDamage(13, 16); + SetDamage(13, 16); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 25, 35); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 25, 35); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.EvalInt, 85.1, 100.0); - SetSkill(SkillName.Magery, 85.1, 100.0); - SetSkill(SkillName.MagicResist, 80.2, 110.0); - SetSkill(SkillName.Tactics, 60.1, 80.0); - SetSkill(SkillName.Wrestling, 40.1, 50.0); + SetSkill(SkillName.EvalInt, 85.1, 100.0); + SetSkill(SkillName.Magery, 85.1, 100.0); + SetSkill(SkillName.MagicResist, 80.2, 110.0); + SetSkill(SkillName.Tactics, 60.1, 80.0); + SetSkill(SkillName.Wrestling, 40.1, 50.0); - Fame = 11500; - Karma = -11500; + Fame = 11500; + Karma = -11500; - VirtualArmor = 40; + VirtualArmor = 40; - if (Core.ML && Utility.RandomDouble() < .33) - PackItem(Seed.RandomPeculiarSeed(1)); + if (Core.ML && Utility.RandomDouble() < .33) + PackItem(Seed.RandomPeculiarSeed(1)); + } + + public Titan(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a titans corpse"; + public override string DefaultName => "a titan"; + + public override int Meat => 4; + public override Poison PoisonImmune => Poison.Regular; + public override int TreasureMapLevel => 5; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.Average); + AddLoot(LootPack.MedScrolls); + } + + 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(); + } } - - public Titan(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a titans corpse"; - public override string DefaultName => "a titan"; - - public override int Meat => 4; - public override Poison PoisonImmune => Poison.Regular; - public override int TreasureMapLevel => 5; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.Average); - AddLoot(LootPack.MedScrolls); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Wraith.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Wraith.cs index 979f9fc94..51d506ef4 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Wraith.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Magic/Wraith.cs @@ -1,71 +1,71 @@ namespace Server.Mobiles { - public class Wraith : BaseCreature - { - [Constructible] - public Wraith() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Wraith : BaseCreature { - Body = 26; - Hue = 0x4001; - BaseSoundID = 0x482; + [Constructible] + public Wraith() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 26; + Hue = 0x4001; + BaseSoundID = 0x482; - SetStr(76, 100); - SetDex(76, 95); - SetInt(36, 60); + SetStr(76, 100); + SetDex(76, 95); + SetInt(36, 60); - SetHits(46, 60); + SetHits(46, 60); - SetDamage(7, 11); + SetDamage(7, 11); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Cold, 50); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Cold, 50); - SetResistance(ResistanceType.Physical, 25, 30); - SetResistance(ResistanceType.Cold, 15, 25); - SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Physical, 25, 30); + SetResistance(ResistanceType.Cold, 15, 25); + SetResistance(ResistanceType.Poison, 10, 20); - SetSkill(SkillName.EvalInt, 55.1, 70.0); - SetSkill(SkillName.Magery, 55.1, 70.0); - SetSkill(SkillName.MagicResist, 55.1, 70.0); - SetSkill(SkillName.Tactics, 45.1, 60.0); - SetSkill(SkillName.Wrestling, 45.1, 55.0); + SetSkill(SkillName.EvalInt, 55.1, 70.0); + SetSkill(SkillName.Magery, 55.1, 70.0); + SetSkill(SkillName.MagicResist, 55.1, 70.0); + SetSkill(SkillName.Tactics, 45.1, 60.0); + SetSkill(SkillName.Wrestling, 45.1, 55.0); - Fame = 4000; - Karma = -4000; + Fame = 4000; + Karma = -4000; - VirtualArmor = 28; + VirtualArmor = 28; - PackReg(10); + PackReg(10); + } + + public Wraith(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a ghostly corpse"; + public override string DefaultName => "a wraith"; + + public override bool BleedImmune => true; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override Poison PoisonImmune => Poison.Lethal; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + 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(); + } } - - public Wraith(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a ghostly corpse"; - public override string DefaultName => "a wraith"; - - public override bool BleedImmune => true; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override Poison PoisonImmune => Poison.Lethal; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/ArcticOgreLord.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/ArcticOgreLord.cs index bcd9e6e0a..0c516ccb8 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/ArcticOgreLord.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/ArcticOgreLord.cs @@ -2,69 +2,69 @@ using Server.Items; namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.ArticOgreLord")] - public class ArcticOgreLord : BaseCreature - { - [Constructible] - public ArcticOgreLord() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.ArticOgreLord")] + public class ArcticOgreLord : BaseCreature { - Body = 135; - BaseSoundID = 427; + [Constructible] + public ArcticOgreLord() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 135; + BaseSoundID = 427; - SetStr(767, 945); - SetDex(66, 75); - SetInt(46, 70); + SetStr(767, 945); + SetDex(66, 75); + SetInt(46, 70); - SetHits(476, 552); + SetHits(476, 552); - SetDamage(20, 25); + SetDamage(20, 25); - SetDamageType(ResistanceType.Physical, 30); - SetDamageType(ResistanceType.Cold, 70); + SetDamageType(ResistanceType.Physical, 30); + SetDamageType(ResistanceType.Cold, 70); - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Cold, 60, 70); - SetResistance(ResistanceType.Poison, 100); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Cold, 60, 70); + SetResistance(ResistanceType.Poison, 100); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.MagicResist, 125.1, 140.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); - SetSkill(SkillName.Wrestling, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 125.1, 140.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.Wrestling, 90.1, 100.0); - Fame = 15000; - Karma = -15000; + Fame = 15000; + Karma = -15000; - VirtualArmor = 50; + VirtualArmor = 50; - PackItem(new Club()); + PackItem(new Club()); + } + + public ArcticOgreLord(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a frozen ogre lord's corpse"; + public override string DefaultName => "an arctic ogre lord"; + + public override Poison PoisonImmune => Poison.Regular; + public override int TreasureMapLevel => 3; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.Rich); + } + + 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(); + } } - - public ArcticOgreLord(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a frozen ogre lord's corpse"; - public override string DefaultName => "an arctic ogre lord"; - - public override Poison PoisonImmune => Poison.Regular; - public override int TreasureMapLevel => 3; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.Rich); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/BoneKnight.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/BoneKnight.cs index 0e2499861..e11ac3186 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/BoneKnight.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/BoneKnight.cs @@ -2,94 +2,94 @@ using Server.Items; namespace Server.Mobiles { - public class BoneKnight : BaseCreature - { - [Constructible] - public BoneKnight() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class BoneKnight : BaseCreature { - Body = 57; - BaseSoundID = 451; + [Constructible] + public BoneKnight() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 57; + BaseSoundID = 451; - SetStr(196, 250); - SetDex(76, 95); - SetInt(36, 60); + SetStr(196, 250); + SetDex(76, 95); + SetInt(36, 60); - SetHits(118, 150); + SetHits(118, 150); - SetDamage(8, 18); + SetDamage(8, 18); - SetDamageType(ResistanceType.Physical, 40); - SetDamageType(ResistanceType.Cold, 60); + SetDamageType(ResistanceType.Physical, 40); + SetDamageType(ResistanceType.Cold, 60); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.MagicResist, 65.1, 80.0); - SetSkill(SkillName.Tactics, 85.1, 100.0); - SetSkill(SkillName.Wrestling, 85.1, 95.0); + SetSkill(SkillName.MagicResist, 65.1, 80.0); + SetSkill(SkillName.Tactics, 85.1, 100.0); + SetSkill(SkillName.Wrestling, 85.1, 95.0); - Fame = 3000; - Karma = -3000; + Fame = 3000; + Karma = -3000; - VirtualArmor = 40; + VirtualArmor = 40; - switch (Utility.Random(6)) - { - case 0: - PackItem(new PlateArms()); - break; - case 1: - PackItem(new PlateChest()); - break; - case 2: - PackItem(new PlateGloves()); - break; - case 3: - PackItem(new PlateGorget()); - break; - case 4: - PackItem(new PlateLegs()); - break; - case 5: - PackItem(new PlateHelm()); - break; - } + switch (Utility.Random(6)) + { + case 0: + PackItem(new PlateArms()); + break; + case 1: + PackItem(new PlateChest()); + break; + case 2: + PackItem(new PlateGloves()); + break; + case 3: + PackItem(new PlateGorget()); + break; + case 4: + PackItem(new PlateLegs()); + break; + case 5: + PackItem(new PlateHelm()); + break; + } - PackSlayer(); - PackItem(new Scimitar()); - PackItem(new WoodenShield()); + PackSlayer(); + PackItem(new Scimitar()); + PackItem(new WoodenShield()); + } + + public BoneKnight(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a skeletal corpse"; + public override string DefaultName => "a bone knight"; + + public override bool BleedImmune => true; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Meager); + } + + 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(); + } } - - public BoneKnight(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a skeletal corpse"; - public override string DefaultName => "a bone knight"; - - public override bool BleedImmune => true; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Brigand.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Brigand.cs index d19913364..b48309dc9 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Brigand.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Brigand.cs @@ -2,97 +2,97 @@ using Server.Items; namespace Server.Mobiles { - public class Brigand : BaseCreature - { - [Constructible] - public Brigand() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Brigand : BaseCreature { - SpeechHue = Utility.RandomDyedHue(); - Title = "the brigand"; - Hue = Race.Human.RandomSkinHue(); - - if (Female = Utility.RandomBool()) - { - Body = 0x191; - Name = NameList.RandomName("female"); - AddItem(new Skirt(Utility.RandomNeutralHue())); - } - else - { - Body = 0x190; - Name = NameList.RandomName("male"); - AddItem(new ShortPants(Utility.RandomNeutralHue())); - } - - SetStr(86, 100); - SetDex(81, 95); - SetInt(61, 75); - - SetDamage(10, 23); - - SetSkill(SkillName.Fencing, 66.0, 97.5); - SetSkill(SkillName.Macing, 65.0, 87.5); - SetSkill(SkillName.MagicResist, 25.0, 47.5); - SetSkill(SkillName.Swords, 65.0, 87.5); - SetSkill(SkillName.Tactics, 65.0, 87.5); - SetSkill(SkillName.Wrestling, 15.0, 37.5); - - Fame = 1000; - Karma = -1000; - - AddItem(new Boots(Utility.RandomNeutralHue())); - AddItem(new FancyShirt()); - AddItem(new Bandana()); - - AddItem( - Utility.Random(7) switch + [Constructible] + public Brigand() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) { - 0 => new Longsword(), - 1 => new Cutlass(), - 2 => new Broadsword(), - 3 => new Axe(), - 4 => new Club(), - 5 => new Dagger(), - _ => new Spear() // 6 + SpeechHue = Utility.RandomDyedHue(); + Title = "the brigand"; + Hue = Race.Human.RandomSkinHue(); + + if (Female = Utility.RandomBool()) + { + Body = 0x191; + Name = NameList.RandomName("female"); + AddItem(new Skirt(Utility.RandomNeutralHue())); + } + else + { + Body = 0x190; + Name = NameList.RandomName("male"); + AddItem(new ShortPants(Utility.RandomNeutralHue())); + } + + SetStr(86, 100); + SetDex(81, 95); + SetInt(61, 75); + + SetDamage(10, 23); + + SetSkill(SkillName.Fencing, 66.0, 97.5); + SetSkill(SkillName.Macing, 65.0, 87.5); + SetSkill(SkillName.MagicResist, 25.0, 47.5); + SetSkill(SkillName.Swords, 65.0, 87.5); + SetSkill(SkillName.Tactics, 65.0, 87.5); + SetSkill(SkillName.Wrestling, 15.0, 37.5); + + Fame = 1000; + Karma = -1000; + + AddItem(new Boots(Utility.RandomNeutralHue())); + AddItem(new FancyShirt()); + AddItem(new Bandana()); + + AddItem( + Utility.Random(7) switch + { + 0 => new Longsword(), + 1 => new Cutlass(), + 2 => new Broadsword(), + 3 => new Axe(), + 4 => new Club(), + 5 => new Dagger(), + _ => new Spear() // 6 + } + ); + + Utility.AssignRandomHair(this); } - ); - Utility.AssignRandomHair(this); + public Brigand(Serial serial) : base(serial) + { + } + + public override bool ClickTitle => false; + + public override bool AlwaysMurderer => true; + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + if (Utility.RandomDouble() < 0.9) + c.DropItem(new SeveredHumanEars()); + } + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + } + + 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 Brigand(Serial serial) : base(serial) - { - } - - public override bool ClickTitle => false; - - public override bool AlwaysMurderer => true; - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - if (Utility.RandomDouble() < 0.9) - c.DropItem(new SeveredHumanEars()); - } - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/ChaosDaemon.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/ChaosDaemon.cs index e4da6a91e..643516358 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/ChaosDaemon.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/ChaosDaemon.cs @@ -2,67 +2,67 @@ using Server.Items; namespace Server.Mobiles { - public class ChaosDaemon : BaseCreature - { - [Constructible] - public ChaosDaemon() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class ChaosDaemon : BaseCreature { - Body = 792; - BaseSoundID = 0x3E9; + [Constructible] + public ChaosDaemon() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 792; + BaseSoundID = 0x3E9; - SetStr(106, 130); - SetDex(171, 200); - SetInt(56, 80); + SetStr(106, 130); + SetDex(171, 200); + SetInt(56, 80); - SetHits(91, 110); + SetHits(91, 110); - SetDamage(12, 17); + SetDamage(12, 17); - SetDamageType(ResistanceType.Physical, 85); - SetDamageType(ResistanceType.Fire, 15); + SetDamageType(ResistanceType.Physical, 85); + SetDamageType(ResistanceType.Fire, 15); - SetResistance(ResistanceType.Physical, 50, 60); - SetResistance(ResistanceType.Fire, 60, 70); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 20, 30); + SetResistance(ResistanceType.Physical, 50, 60); + SetResistance(ResistanceType.Fire, 60, 70); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 20, 30); - SetSkill(SkillName.MagicResist, 85.1, 95.0); - SetSkill(SkillName.Tactics, 70.1, 80.0); - SetSkill(SkillName.Wrestling, 95.1, 100.0); + SetSkill(SkillName.MagicResist, 85.1, 95.0); + SetSkill(SkillName.Tactics, 70.1, 80.0); + SetSkill(SkillName.Wrestling, 95.1, 100.0); - Fame = 3000; - Karma = -4000; + Fame = 3000; + Karma = -4000; - VirtualArmor = 15; + VirtualArmor = 15; + } + + public ChaosDaemon(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a chaos daemon corpse"; + + public override string DefaultName => "a chaos daemon"; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.CrushingBlow; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Meager); + } + + 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(); + } } - - public ChaosDaemon(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a chaos daemon corpse"; - - public override string DefaultName => "a chaos daemon"; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.CrushingBlow; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Cursed.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Cursed.cs index dc9beadae..352cd3ae2 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Cursed.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Cursed.cs @@ -2,80 +2,80 @@ using Server.Items; namespace Server.Mobiles { - public class Cursed : BaseCreature - { - [Constructible] - public Cursed() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Cursed : BaseCreature { - Title = "the Cursed"; + [Constructible] + public Cursed() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Title = "the Cursed"; - Hue = Utility.RandomMinMax(0x8596, 0x8599); - Body = 0x190; - Name = NameList.RandomName("male"); - BaseSoundID = 471; + Hue = Utility.RandomMinMax(0x8596, 0x8599); + Body = 0x190; + Name = NameList.RandomName("male"); + BaseSoundID = 471; - AddItem(new ShortPants(Utility.RandomNeutralHue())); - AddItem(new Shirt(Utility.RandomNeutralHue())); + AddItem(new ShortPants(Utility.RandomNeutralHue())); + AddItem(new Shirt(Utility.RandomNeutralHue())); - BaseWeapon weapon = Loot.RandomWeapon(); - weapon.Movable = false; - AddItem(weapon); + var weapon = Loot.RandomWeapon(); + weapon.Movable = false; + AddItem(weapon); - SetStr(91, 100); - SetDex(86, 95); - SetInt(61, 70); + SetStr(91, 100); + SetDex(86, 95); + SetInt(61, 70); - SetHits(91, 120); + SetHits(91, 120); - SetDamage(5, 13); + SetDamage(5, 13); - SetResistance(ResistanceType.Physical, 15, 25); - SetResistance(ResistanceType.Fire, 5, 10); - SetResistance(ResistanceType.Cold, 25, 35); - SetResistance(ResistanceType.Poison, 5, 10); - SetResistance(ResistanceType.Energy, 5, 10); + SetResistance(ResistanceType.Physical, 15, 25); + SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Cold, 25, 35); + SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Energy, 5, 10); - SetSkill(SkillName.Fencing, 46.0, 77.5); - SetSkill(SkillName.Macing, 35.0, 57.5); - SetSkill(SkillName.MagicResist, 53.5, 62.5); - SetSkill(SkillName.Swords, 55.0, 77.5); - SetSkill(SkillName.Tactics, 60.0, 82.5); - SetSkill(SkillName.Poisoning, 60.0, 82.5); + SetSkill(SkillName.Fencing, 46.0, 77.5); + SetSkill(SkillName.Macing, 35.0, 57.5); + SetSkill(SkillName.MagicResist, 53.5, 62.5); + SetSkill(SkillName.Swords, 55.0, 77.5); + SetSkill(SkillName.Tactics, 60.0, 82.5); + SetSkill(SkillName.Poisoning, 60.0, 82.5); - Fame = 1000; - Karma = -2000; + Fame = 1000; + Karma = -2000; + } + + public Cursed(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an inhuman corpse"; + public override bool ClickTitle => false; + public override bool ShowFameTitle => false; + + public override bool AlwaysMurderer => true; + + public override int GetAttackSound() => -1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + // AddLoot( LootPack.Miscellaneous ); + } + + 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 Cursed(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an inhuman corpse"; - public override bool ClickTitle => false; - public override bool ShowFameTitle => false; - - public override bool AlwaysMurderer => true; - - public override int GetAttackSound() => -1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - // AddLoot( LootPack.Miscellaneous ); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Cyclops.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Cyclops.cs index c34793266..edc0183ad 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Cyclops.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Cyclops.cs @@ -1,66 +1,66 @@ namespace Server.Mobiles { - public class Cyclops : BaseCreature - { - [Constructible] - public Cyclops() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Cyclops : BaseCreature { - Body = 75; - BaseSoundID = 604; + [Constructible] + public Cyclops() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 75; + BaseSoundID = 604; - SetStr(336, 385); - SetDex(96, 115); - SetInt(31, 55); + SetStr(336, 385); + SetDex(96, 115); + SetInt(31, 55); - SetHits(202, 231); - SetMana(0); + SetHits(202, 231); + SetMana(0); - SetDamage(7, 23); + SetDamage(7, 23); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 45, 50); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 25, 35); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 45, 50); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 25, 35); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.MagicResist, 60.3, 105.0); - SetSkill(SkillName.Tactics, 80.1, 100.0); - SetSkill(SkillName.Wrestling, 80.1, 90.0); + SetSkill(SkillName.MagicResist, 60.3, 105.0); + SetSkill(SkillName.Tactics, 80.1, 100.0); + SetSkill(SkillName.Wrestling, 80.1, 90.0); - Fame = 4500; - Karma = -4500; + Fame = 4500; + Karma = -4500; - VirtualArmor = 48; + VirtualArmor = 48; + } + + public Cyclops(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a cyclopean corpse"; + public override string DefaultName => "a cyclopean warrior"; + + public override int Meat => 4; + public override int TreasureMapLevel => 3; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.Average); + } + + 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(); + } } - - public Cyclops(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a cyclopean corpse"; - public override string DefaultName => "a cyclopean warrior"; - - public override int Meat => 4; - public override int TreasureMapLevel => 3; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.Average); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Doppleganger.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Doppleganger.cs index fe65ea396..255977082 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Doppleganger.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Doppleganger.cs @@ -1,62 +1,62 @@ namespace Server.Mobiles { - public class Doppleganger : BaseCreature - { - [Constructible] - public Doppleganger() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Doppleganger : BaseCreature { - Body = 0x309; - BaseSoundID = 0x451; + [Constructible] + public Doppleganger() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0x309; + BaseSoundID = 0x451; - SetStr(81, 110); - SetDex(56, 75); - SetInt(81, 105); + SetStr(81, 110); + SetDex(56, 75); + SetInt(81, 105); - SetHits(101, 120); + SetHits(101, 120); - SetDamage(8, 12); + SetDamage(8, 12); - SetResistance(ResistanceType.Physical, 50, 60); - SetResistance(ResistanceType.Fire, 10, 20); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 50, 60); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 50, 60); + SetResistance(ResistanceType.Fire, 10, 20); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 50, 60); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.MagicResist, 75.1, 85.0); - SetSkill(SkillName.Tactics, 70.1, 80.0); - SetSkill(SkillName.Wrestling, 80.1, 90.0); + SetSkill(SkillName.MagicResist, 75.1, 85.0); + SetSkill(SkillName.Tactics, 70.1, 80.0); + SetSkill(SkillName.Wrestling, 80.1, 90.0); - Fame = 1000; - Karma = -1000; + Fame = 1000; + Karma = -1000; - VirtualArmor = 55; + VirtualArmor = 55; + } + + public Doppleganger(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a doppleganger corpse"; + public override string DefaultName => "a doppleganger"; + + public override int Hides => 6; + public override int Meat => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + } + + 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(); + } } - - public Doppleganger(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a doppleganger corpse"; - public override string DefaultName => "a doppleganger"; - - public override int Hides => 6; - public override int Meat => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/ElfBrigand.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/ElfBrigand.cs index 18e6eb9e9..ca204c17f 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/ElfBrigand.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/ElfBrigand.cs @@ -2,116 +2,116 @@ using Server.Items; namespace Server.Mobiles { - // TODO: Needs some Spellweaving abilities - public class ElfBrigand : BaseCreature - { - [Constructible] - public ElfBrigand() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + // TODO: Needs some Spellweaving abilities + public class ElfBrigand : BaseCreature { - SpeechHue = Utility.RandomDyedHue(); - Title = "the brigand"; - Race = Race.Elf; - Hue = Race.RandomSkinHue(); - - if (Female = Utility.RandomBool()) - { - Body = 0x25E; - Name = NameList.RandomName("female elf brigand"); - - switch (Utility.Random(2)) + [Constructible] + public ElfBrigand() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) { - case 0: - AddItem(new Skirt(Utility.RandomNondyedHue())); - break; - case 1: - AddItem(new Kilt(Utility.RandomNondyedHue())); - break; + SpeechHue = Utility.RandomDyedHue(); + Title = "the brigand"; + Race = Race.Elf; + Hue = Race.RandomSkinHue(); + + if (Female = Utility.RandomBool()) + { + Body = 0x25E; + Name = NameList.RandomName("female elf brigand"); + + switch (Utility.Random(2)) + { + case 0: + AddItem(new Skirt(Utility.RandomNondyedHue())); + break; + case 1: + AddItem(new Kilt(Utility.RandomNondyedHue())); + break; + } + } + else + { + Body = 0x25D; + Name = NameList.RandomName("male elf brigand"); + AddItem(new ShortPants(Utility.RandomNondyedHue())); + } + + SetStr(86, 100); + SetDex(81, 95); + SetInt(61, 75); + + SetDamage(10, 23); + + SetSkill(SkillName.Fencing, 66.0, 97.5); + SetSkill(SkillName.Macing, 65.0, 87.5); + SetSkill(SkillName.MagicResist, 25.0, 47.5); + SetSkill(SkillName.Swords, 65.0, 87.5); + SetSkill(SkillName.Tactics, 65.0, 87.5); + SetSkill(SkillName.Wrestling, 15.0, 37.5); + + Fame = 1000; + Karma = -1000; + + AddItem( + Utility.Random(4) switch + { + 0 => new Boots(), + 1 => new ThighBoots(), + 2 => new Sandals(), + _ => new Shoes() // 3 + } + ); + + AddItem(new Shirt(Utility.RandomNondyedHue())); + + AddItem( + Utility.Random(7) switch + { + 0 => new Longsword(), + 1 => new Cutlass(), + 2 => new Broadsword(), + 3 => new Axe(), + 4 => new Club(), + 5 => new Dagger(), + _ => new Spear() // 6 + } + ); + + Utility.AssignRandomHair(this); } - } - else - { - Body = 0x25D; - Name = NameList.RandomName("male elf brigand"); - AddItem(new ShortPants(Utility.RandomNondyedHue())); - } - SetStr(86, 100); - SetDex(81, 95); - SetInt(61, 75); - - SetDamage(10, 23); - - SetSkill(SkillName.Fencing, 66.0, 97.5); - SetSkill(SkillName.Macing, 65.0, 87.5); - SetSkill(SkillName.MagicResist, 25.0, 47.5); - SetSkill(SkillName.Swords, 65.0, 87.5); - SetSkill(SkillName.Tactics, 65.0, 87.5); - SetSkill(SkillName.Wrestling, 15.0, 37.5); - - Fame = 1000; - Karma = -1000; - - AddItem( - Utility.Random(4) switch + public ElfBrigand(Serial serial) : base(serial) { - 0 => new Boots(), - 1 => new ThighBoots(), - 2 => new Sandals(), - _ => new Shoes() // 3 } - ); - AddItem(new Shirt(Utility.RandomNondyedHue())); + public override bool ClickTitle => false; - AddItem( - Utility.Random(7) switch + public override bool AlwaysMurderer => true; + + public override void OnDeath(Container c) { - 0 => new Longsword(), - 1 => new Cutlass(), - 2 => new Broadsword(), - 3 => new Axe(), - 4 => new Club(), - 5 => new Dagger(), - _ => new Spear() // 6 + base.OnDeath(c); + + if (Utility.RandomDouble() < 0.9) + c.DropItem(new SeveredElfEars()); } - ); - Utility.AssignRandomHair(this); + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + } + + 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 ElfBrigand(Serial serial) : base(serial) - { - } - - public override bool ClickTitle => false; - - public override bool AlwaysMurderer => true; - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - if (Utility.RandomDouble() < 0.9) - c.DropItem(new SeveredElfEars()); - } - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/EnslavedGargoyle.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/EnslavedGargoyle.cs index a6af042bf..74b565b89 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/EnslavedGargoyle.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/EnslavedGargoyle.cs @@ -2,67 +2,67 @@ using Server.Items; namespace Server.Mobiles { - public class EnslavedGargoyle : BaseCreature - { - [Constructible] - public EnslavedGargoyle() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class EnslavedGargoyle : BaseCreature { - Body = 0x2F1; - BaseSoundID = 0x174; + [Constructible] + public EnslavedGargoyle() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0x2F1; + BaseSoundID = 0x174; - SetStr(302, 360); - SetDex(76, 95); - SetInt(81, 105); + SetStr(302, 360); + SetDex(76, 95); + SetInt(81, 105); - SetHits(186, 212); + SetHits(186, 212); - SetDamage(7, 14); + SetDamage(7, 14); - SetResistance(ResistanceType.Physical, 30, 40); - SetResistance(ResistanceType.Fire, 50, 70); - SetResistance(ResistanceType.Cold, 15, 25); - SetResistance(ResistanceType.Poison, 25, 30); - SetResistance(ResistanceType.Energy, 25, 30); + SetResistance(ResistanceType.Physical, 30, 40); + SetResistance(ResistanceType.Fire, 50, 70); + SetResistance(ResistanceType.Cold, 15, 25); + SetResistance(ResistanceType.Poison, 25, 30); + SetResistance(ResistanceType.Energy, 25, 30); - SetSkill(SkillName.MagicResist, 70.1, 85.0); - SetSkill(SkillName.Tactics, 50.1, 70.0); - SetSkill(SkillName.Wrestling, 40.1, 80.0); + SetSkill(SkillName.MagicResist, 70.1, 85.0); + SetSkill(SkillName.Tactics, 50.1, 70.0); + SetSkill(SkillName.Wrestling, 40.1, 80.0); - Fame = 3500; - Karma = 0; + Fame = 3500; + Karma = 0; - VirtualArmor = 35; + VirtualArmor = 35; - if (Utility.RandomDouble() < 0.2) - PackItem(new GargoylesPickaxe()); + if (Utility.RandomDouble() < 0.2) + PackItem(new GargoylesPickaxe()); + } + + public EnslavedGargoyle(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an enslaved gargoyle corpse"; + public override string DefaultName => "an enslaved gargoyle"; + + public override int Meat => 1; + public override int TreasureMapLevel => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average, 2); + AddLoot(LootPack.Gems); + } + + 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(); + } } - - public EnslavedGargoyle(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an enslaved gargoyle corpse"; - public override string DefaultName => "an enslaved gargoyle"; - - public override int Meat => 1; - public override int TreasureMapLevel => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average, 2); - AddLoot(LootPack.Gems); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Ettin.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Ettin.cs index 9793fca52..e41162e7b 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Ettin.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Ettin.cs @@ -1,67 +1,67 @@ namespace Server.Mobiles { - public class Ettin : BaseCreature - { - [Constructible] - public Ettin() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Ettin : BaseCreature { - Body = 18; - BaseSoundID = 367; + [Constructible] + public Ettin() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 18; + BaseSoundID = 367; - SetStr(136, 165); - SetDex(56, 75); - SetInt(31, 55); + SetStr(136, 165); + SetDex(56, 75); + SetInt(31, 55); - SetHits(82, 99); + SetHits(82, 99); - SetDamage(7, 17); + SetDamage(7, 17); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 35, 40); - SetResistance(ResistanceType.Fire, 15, 25); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 15, 25); - SetResistance(ResistanceType.Energy, 15, 25); + SetResistance(ResistanceType.Physical, 35, 40); + SetResistance(ResistanceType.Fire, 15, 25); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 15, 25); + SetResistance(ResistanceType.Energy, 15, 25); - SetSkill(SkillName.MagicResist, 40.1, 55.0); - SetSkill(SkillName.Tactics, 50.1, 70.0); - SetSkill(SkillName.Wrestling, 50.1, 60.0); + SetSkill(SkillName.MagicResist, 40.1, 55.0); + SetSkill(SkillName.Tactics, 50.1, 70.0); + SetSkill(SkillName.Wrestling, 50.1, 60.0); - Fame = 3000; - Karma = -3000; + Fame = 3000; + Karma = -3000; - VirtualArmor = 38; + VirtualArmor = 38; + } + + public Ettin(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ettins corpse"; + public override string DefaultName => "an ettin"; + + public override bool CanRummageCorpses => true; + public override int TreasureMapLevel => 1; + public override int Meat => 4; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + AddLoot(LootPack.Average); + AddLoot(LootPack.Potions); + } + + 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(); + } } - - public Ettin(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ettins corpse"; - public override string DefaultName => "an ettin"; - - public override bool CanRummageCorpses => true; - public override int TreasureMapLevel => 1; - public override int Meat => 4; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - AddLoot(LootPack.Average); - AddLoot(LootPack.Potions); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Executioner.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Executioner.cs index c01f3c11e..e241fb044 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Executioner.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Executioner.cs @@ -2,87 +2,87 @@ using Server.Items; namespace Server.Mobiles { - public class Executioner : BaseCreature - { - [Constructible] - public Executioner() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Executioner : BaseCreature { - SpeechHue = Utility.RandomDyedHue(); - Title = "the executioner"; - Hue = Race.Human.RandomSkinHue(); + [Constructible] + public Executioner() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + SpeechHue = Utility.RandomDyedHue(); + Title = "the executioner"; + Hue = Race.Human.RandomSkinHue(); - if (Female = Utility.RandomBool()) - { - Body = 0x191; - Name = NameList.RandomName("female"); - AddItem(new Skirt(Utility.RandomRedHue())); - } - else - { - Body = 0x190; - Name = NameList.RandomName("male"); - AddItem(new ShortPants(Utility.RandomRedHue())); - } + if (Female = Utility.RandomBool()) + { + Body = 0x191; + Name = NameList.RandomName("female"); + AddItem(new Skirt(Utility.RandomRedHue())); + } + else + { + Body = 0x190; + Name = NameList.RandomName("male"); + AddItem(new ShortPants(Utility.RandomRedHue())); + } - SetStr(386, 400); - SetDex(151, 165); - SetInt(161, 175); + SetStr(386, 400); + SetDex(151, 165); + SetInt(161, 175); - SetDamage(8, 10); + SetDamage(8, 10); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 25, 30); - SetResistance(ResistanceType.Cold, 25, 30); - SetResistance(ResistanceType.Poison, 10, 20); - SetResistance(ResistanceType.Energy, 10, 20); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 25, 30); + SetResistance(ResistanceType.Cold, 25, 30); + SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Energy, 10, 20); - SetSkill(SkillName.Anatomy, 125.0); - SetSkill(SkillName.Fencing, 46.0, 77.5); - SetSkill(SkillName.Macing, 35.0, 57.5); - SetSkill(SkillName.Poisoning, 60.0, 82.5); - SetSkill(SkillName.MagicResist, 83.5, 92.5); - SetSkill(SkillName.Swords, 125.0); - SetSkill(SkillName.Tactics, 125.0); - SetSkill(SkillName.Lumberjacking, 125.0); + SetSkill(SkillName.Anatomy, 125.0); + SetSkill(SkillName.Fencing, 46.0, 77.5); + SetSkill(SkillName.Macing, 35.0, 57.5); + SetSkill(SkillName.Poisoning, 60.0, 82.5); + SetSkill(SkillName.MagicResist, 83.5, 92.5); + SetSkill(SkillName.Swords, 125.0); + SetSkill(SkillName.Tactics, 125.0); + SetSkill(SkillName.Lumberjacking, 125.0); - Fame = 5000; - Karma = -5000; + Fame = 5000; + Karma = -5000; - VirtualArmor = 40; + VirtualArmor = 40; - AddItem(new ThighBoots(Utility.RandomRedHue())); - AddItem(new Surcoat(Utility.RandomRedHue())); - AddItem(new ExecutionersAxe()); + AddItem(new ThighBoots(Utility.RandomRedHue())); + AddItem(new Surcoat(Utility.RandomRedHue())); + AddItem(new ExecutionersAxe()); - Utility.AssignRandomHair(this); + Utility.AssignRandomHair(this); + } + + public Executioner(Serial serial) : base(serial) + { + } + + public override bool AlwaysMurderer => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.Meager); + } + + 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 Executioner(Serial serial) : base(serial) - { - } - - public override bool AlwaysMurderer => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/FrostTroll.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/FrostTroll.cs index ca3a5d35b..e96b21cdf 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/FrostTroll.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/FrostTroll.cs @@ -2,68 +2,68 @@ using Server.Items; namespace Server.Mobiles { - public class FrostTroll : BaseCreature - { - [Constructible] - public FrostTroll() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class FrostTroll : BaseCreature { - Body = 55; - BaseSoundID = 461; + [Constructible] + public FrostTroll() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 55; + BaseSoundID = 461; - SetStr(227, 265); - SetDex(66, 85); - SetInt(46, 70); + SetStr(227, 265); + SetDex(66, 85); + SetInt(46, 70); - SetHits(140, 156); + SetHits(140, 156); - SetDamage(14, 20); + SetDamage(14, 20); - SetDamageType(ResistanceType.Physical, 75); - SetDamageType(ResistanceType.Cold, 25); + SetDamageType(ResistanceType.Physical, 75); + SetDamageType(ResistanceType.Cold, 25); - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 5, 10); - SetResistance(ResistanceType.Energy, 5, 10); + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Energy, 5, 10); - SetSkill(SkillName.MagicResist, 65.1, 80.0); - SetSkill(SkillName.Tactics, 80.1, 100.0); - SetSkill(SkillName.Wrestling, 80.1, 100.0); + SetSkill(SkillName.MagicResist, 65.1, 80.0); + SetSkill(SkillName.Tactics, 80.1, 100.0); + SetSkill(SkillName.Wrestling, 80.1, 100.0); - Fame = 4000; - Karma = -4000; + Fame = 4000; + Karma = -4000; - VirtualArmor = 50; + VirtualArmor = 50; - PackItem(new DoubleAxe()); // TODO: Weapon?? + PackItem(new DoubleAxe()); // TODO: Weapon?? + } + + public FrostTroll(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a frost troll corpse"; + public override string DefaultName => "a frost troll"; + + public override int Meat => 2; + public override int TreasureMapLevel => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Gems); + } + + 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(); + } } - - public FrostTroll(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a frost troll corpse"; - public override string DefaultName => "a frost troll"; - - public override int Meat => 2; - public override int TreasureMapLevel => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Gems); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/GazerLarva.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/GazerLarva.cs index bfd7ec52b..7bbac091b 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/GazerLarva.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/GazerLarva.cs @@ -2,62 +2,62 @@ using Server.Items; namespace Server.Mobiles { - public class GazerLarva : BaseCreature - { - [Constructible] - public GazerLarva() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class GazerLarva : BaseCreature { - Body = 778; - BaseSoundID = 377; + [Constructible] + public GazerLarva() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 778; + BaseSoundID = 377; - SetStr(76, 100); - SetDex(51, 75); - SetInt(56, 80); + SetStr(76, 100); + SetDex(51, 75); + SetInt(56, 80); - SetHits(36, 47); + SetHits(36, 47); - SetDamage(2, 9); + SetDamage(2, 9); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 15, 25); + SetResistance(ResistanceType.Physical, 15, 25); - SetSkill(SkillName.MagicResist, 70.0); - SetSkill(SkillName.Tactics, 70.0); - SetSkill(SkillName.Wrestling, 70.0); + SetSkill(SkillName.MagicResist, 70.0); + SetSkill(SkillName.Tactics, 70.0); + SetSkill(SkillName.Wrestling, 70.0); - Fame = 900; - Karma = -900; + Fame = 900; + Karma = -900; - VirtualArmor = 25; + VirtualArmor = 25; - PackItem(new Nightshade(Utility.RandomMinMax(2, 3))); + PackItem(new Nightshade(Utility.RandomMinMax(2, 3))); + } + + public GazerLarva(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a gazer larva corpse"; + public override string DefaultName => "a gazer larva"; + + public override int Meat => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Poor); + } + + 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(); + } } - - public GazerLarva(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a gazer larva corpse"; - public override string DefaultName => "a gazer larva"; - - public override int Meat => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Poor); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Ghoul.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Ghoul.cs index 0d46c9444..f3130d9b7 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Ghoul.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Ghoul.cs @@ -1,68 +1,68 @@ namespace Server.Mobiles { - public class Ghoul : BaseCreature - { - [Constructible] - public Ghoul() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Ghoul : BaseCreature { - Body = 153; - BaseSoundID = 0x482; + [Constructible] + public Ghoul() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 153; + BaseSoundID = 0x482; - SetStr(76, 100); - SetDex(76, 95); - SetInt(36, 60); + SetStr(76, 100); + SetDex(76, 95); + SetInt(36, 60); - SetHits(46, 60); - SetMana(0); + SetHits(46, 60); + SetMana(0); - SetDamage(7, 9); + SetDamage(7, 9); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 25, 30); - SetResistance(ResistanceType.Cold, 20, 30); - SetResistance(ResistanceType.Poison, 5, 10); - SetResistance(ResistanceType.Energy, 10, 20); + SetResistance(ResistanceType.Physical, 25, 30); + SetResistance(ResistanceType.Cold, 20, 30); + SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Energy, 10, 20); - SetSkill(SkillName.MagicResist, 45.1, 60.0); - SetSkill(SkillName.Tactics, 45.1, 60.0); - SetSkill(SkillName.Wrestling, 45.1, 55.0); + SetSkill(SkillName.MagicResist, 45.1, 60.0); + SetSkill(SkillName.Tactics, 45.1, 60.0); + SetSkill(SkillName.Wrestling, 45.1, 55.0); - Fame = 2500; - Karma = -2500; + Fame = 2500; + Karma = -2500; - VirtualArmor = 28; + VirtualArmor = 28; - PackItem(Loot.RandomWeapon()); + PackItem(Loot.RandomWeapon()); + } + + public Ghoul(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a ghostly corpse"; + public override string DefaultName => "a ghoul"; + + public override bool BleedImmune => true; + public override Poison PoisonImmune => Poison.Regular; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + 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(); + } } - - public Ghoul(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a ghostly corpse"; - public override string DefaultName => "a ghoul"; - - public override bool BleedImmune => true; - public override Poison PoisonImmune => Poison.Regular; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/GreaterMongbat.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/GreaterMongbat.cs index a75dc08d7..4fcf786af 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/GreaterMongbat.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/GreaterMongbat.cs @@ -1,67 +1,67 @@ namespace Server.Mobiles { - public class GreaterMongbat : BaseCreature - { - [Constructible] - public GreaterMongbat() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class GreaterMongbat : BaseCreature { - Body = 39; - BaseSoundID = 422; + [Constructible] + public GreaterMongbat() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 39; + BaseSoundID = 422; - SetStr(56, 80); - SetDex(61, 80); - SetInt(26, 50); + SetStr(56, 80); + SetDex(61, 80); + SetInt(26, 50); - SetHits(34, 48); - SetStam(61, 80); - SetMana(26, 50); + SetHits(34, 48); + SetStam(61, 80); + SetMana(26, 50); - SetDamage(5, 7); + SetDamage(5, 7); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 15, 25); + SetResistance(ResistanceType.Physical, 15, 25); - SetSkill(SkillName.MagicResist, 15.1, 30.0); - SetSkill(SkillName.Tactics, 35.1, 50.0); - SetSkill(SkillName.Wrestling, 20.1, 35.0); + SetSkill(SkillName.MagicResist, 15.1, 30.0); + SetSkill(SkillName.Tactics, 35.1, 50.0); + SetSkill(SkillName.Wrestling, 20.1, 35.0); - Fame = 450; - Karma = -450; + Fame = 450; + Karma = -450; - VirtualArmor = 10; + VirtualArmor = 10; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 71.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 71.1; + } + + public GreaterMongbat(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a mongbat corpse"; + public override string DefaultName => "a greater mongbat"; + + public override int Meat => 1; + public override int Hides => 6; + public override FoodType FavoriteFood => FoodType.Meat; + + public override void GenerateLoot() + { + AddLoot(LootPack.Poor); + } + + 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(); + } } - - public GreaterMongbat(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a mongbat corpse"; - public override string DefaultName => "a greater mongbat"; - - public override int Meat => 1; - public override int Hides => 6; - public override FoodType FavoriteFood => FoodType.Meat; - - public override void GenerateLoot() - { - AddLoot(LootPack.Poor); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Guardian.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Guardian.cs index acb6b30d2..cb868762e 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Guardian.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Guardian.cs @@ -2,84 +2,84 @@ using Server.Items; namespace Server.Mobiles { - public class Guardian : BaseCreature - { - [Constructible] - public Guardian() : base(AIType.AI_Archer, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Guardian : BaseCreature { - InitStats(100, 125, 25); - Title = "the guardian"; + [Constructible] + public Guardian() : base(AIType.AI_Archer, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + InitStats(100, 125, 25); + Title = "the guardian"; - SpeechHue = Utility.RandomDyedHue(); + SpeechHue = Utility.RandomDyedHue(); - Hue = Race.Human.RandomSkinHue(); + Hue = Race.Human.RandomSkinHue(); - if (Female = Utility.RandomBool()) - { - Body = 0x191; - Name = NameList.RandomName("female"); - } - else - { - Body = 0x190; - Name = NameList.RandomName("male"); - } + if (Female = Utility.RandomBool()) + { + Body = 0x191; + Name = NameList.RandomName("female"); + } + else + { + Body = 0x190; + Name = NameList.RandomName("male"); + } - new ForestOstard().Rider = this; + new ForestOstard().Rider = this; - PlateChest chest = new PlateChest(); - chest.Hue = 0x966; - AddItem(chest); - PlateArms arms = new PlateArms(); - arms.Hue = 0x966; - AddItem(arms); - PlateGloves gloves = new PlateGloves(); - gloves.Hue = 0x966; - AddItem(gloves); - PlateGorget gorget = new PlateGorget(); - gorget.Hue = 0x966; - AddItem(gorget); - PlateLegs legs = new PlateLegs(); - legs.Hue = 0x966; - AddItem(legs); - PlateHelm helm = new PlateHelm(); - helm.Hue = 0x966; - AddItem(helm); + var chest = new PlateChest(); + chest.Hue = 0x966; + AddItem(chest); + var arms = new PlateArms(); + arms.Hue = 0x966; + AddItem(arms); + var gloves = new PlateGloves(); + gloves.Hue = 0x966; + AddItem(gloves); + var gorget = new PlateGorget(); + gorget.Hue = 0x966; + AddItem(gorget); + var legs = new PlateLegs(); + legs.Hue = 0x966; + AddItem(legs); + var helm = new PlateHelm(); + helm.Hue = 0x966; + AddItem(helm); - Bow bow = new Bow(); + var bow = new Bow(); - bow.Movable = false; - bow.Crafter = this; - bow.Quality = WeaponQuality.Exceptional; + bow.Movable = false; + bow.Crafter = this; + bow.Quality = WeaponQuality.Exceptional; - AddItem(bow); + AddItem(bow); - PackItem(new Arrow(250)); - PackGold(250, 500); + PackItem(new Arrow(250)); + PackGold(250, 500); - Skills.Anatomy.Base = 120.0; - Skills.Tactics.Base = 120.0; - Skills.Archery.Base = 120.0; - Skills.MagicResist.Base = 120.0; - Skills.DetectHidden.Base = 100.0; + Skills.Anatomy.Base = 120.0; + Skills.Tactics.Base = 120.0; + Skills.Archery.Base = 120.0; + Skills.MagicResist.Base = 120.0; + Skills.DetectHidden.Base = 100.0; + } + + public Guardian(Serial serial) : base(serial) + { + } + + 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 Guardian(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/HeadlessOne.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/HeadlessOne.cs index 1e19c7448..0934f9f8c 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/HeadlessOne.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/HeadlessOne.cs @@ -1,62 +1,62 @@ namespace Server.Mobiles { - public class HeadlessOne : BaseCreature - { - [Constructible] - public HeadlessOne() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class HeadlessOne : BaseCreature { - Body = 31; - Hue = Race.Human.RandomSkinHue() & 0x7FFF; - BaseSoundID = 0x39D; + [Constructible] + public HeadlessOne() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 31; + Hue = Race.Human.RandomSkinHue() & 0x7FFF; + BaseSoundID = 0x39D; - SetStr(26, 50); - SetDex(36, 55); - SetInt(16, 30); + SetStr(26, 50); + SetDex(36, 55); + SetInt(16, 30); - SetHits(16, 30); + SetHits(16, 30); - SetDamage(5, 10); + SetDamage(5, 10); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 15, 20); + SetResistance(ResistanceType.Physical, 15, 20); - SetSkill(SkillName.MagicResist, 15.1, 20.0); - SetSkill(SkillName.Tactics, 25.1, 40.0); - SetSkill(SkillName.Wrestling, 25.1, 40.0); + SetSkill(SkillName.MagicResist, 15.1, 20.0); + SetSkill(SkillName.Tactics, 25.1, 40.0); + SetSkill(SkillName.Wrestling, 25.1, 40.0); - Fame = 450; - Karma = -450; + Fame = 450; + Karma = -450; - VirtualArmor = 18; + VirtualArmor = 18; + } + + public HeadlessOne(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a headless corpse"; + public override string DefaultName => "a headless one"; + + public override bool CanRummageCorpses => true; + public override int Meat => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Poor); + // TODO: body parts + } + + 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(); + } } - - public HeadlessOne(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a headless corpse"; - public override string DefaultName => "a headless one"; - - public override bool CanRummageCorpses => true; - public override int Meat => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Poor); - // TODO: body parts - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/HordeMinion.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/HordeMinion.cs index d76c6df31..b1fc8822f 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/HordeMinion.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/HordeMinion.cs @@ -2,69 +2,69 @@ using Server.Items; namespace Server.Mobiles { - public class HordeMinion : BaseCreature - { - [Constructible] - public HordeMinion() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class HordeMinion : BaseCreature { - Body = 776; - BaseSoundID = 357; + [Constructible] + public HordeMinion() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 776; + BaseSoundID = 357; - SetStr(16, 40); - SetDex(31, 60); - SetInt(11, 25); + SetStr(16, 40); + SetDex(31, 60); + SetInt(11, 25); - SetHits(10, 24); + SetHits(10, 24); - SetDamage(5, 10); + SetDamage(5, 10); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 15, 20); - SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Physical, 15, 20); + SetResistance(ResistanceType.Fire, 5, 10); - SetSkill(SkillName.MagicResist, 10.0); - SetSkill(SkillName.Tactics, 0.1, 15.0); - SetSkill(SkillName.Wrestling, 25.1, 40.0); + SetSkill(SkillName.MagicResist, 10.0); + SetSkill(SkillName.Tactics, 0.1, 15.0); + SetSkill(SkillName.Wrestling, 25.1, 40.0); - Fame = 500; - Karma = -500; + Fame = 500; + Karma = -500; - VirtualArmor = 18; + VirtualArmor = 18; - AddItem(new LightSource()); + AddItem(new LightSource()); - PackItem(new Bone(3)); - // TODO: Body parts + PackItem(new Bone(3)); + // TODO: Body parts + } + + public HordeMinion(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a horde minion corpse"; + public override string DefaultName => "a horde minion"; + + public override int GetIdleSound() => 338; + + public override int GetAngerSound() => 338; + + public override int GetDeathSound() => 338; + + public override int GetAttackSound() => 406; + + public override int GetHurtSound() => 194; + + 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(); + } } - - public HordeMinion(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a horde minion corpse"; - public override string DefaultName => "a horde minion"; - - public override int GetIdleSound() => 338; - - public override int GetAngerSound() => 338; - - public override int GetDeathSound() => 338; - - public override int GetAttackSound() => 406; - - public override int GetHurtSound() => 194; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Juggernaut.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Juggernaut.cs index 8d78a5b42..c71e3091f 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Juggernaut.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Juggernaut.cs @@ -4,141 +4,145 @@ using Server.Network; namespace Server.Mobiles { - public class Juggernaut : BaseCreature - { - private bool m_Stunning; - - [Constructible] - public Juggernaut() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.3, 0.6) + public class Juggernaut : BaseCreature { - Body = 768; + private bool m_Stunning; - SetStr(301, 400); - SetDex(51, 70); - SetInt(51, 100); - - SetHits(181, 240); - - SetDamage(12, 19); - - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Fire, 25); - SetDamageType(ResistanceType.Energy, 25); - - SetResistance(ResistanceType.Physical, 65, 75); - SetResistance(ResistanceType.Fire, 35, 45); - SetResistance(ResistanceType.Cold, 35, 45); - SetResistance(ResistanceType.Poison, 15, 25); - SetResistance(ResistanceType.Energy, 10, 20); - - SetSkill(SkillName.Anatomy, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 140.1, 150.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); - SetSkill(SkillName.Wrestling, 90.1, 100.0); - - Fame = 12000; - Karma = -12000; - - VirtualArmor = 70; - - if (Utility.RandomDouble() < 0.1) - PackItem(new PowerCrystal()); - - if (Utility.RandomDouble() < 0.4) - PackItem(new ClockworkAssembly()); - } - - public Juggernaut(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a juggernaut corpse"; - - public override string DefaultName => "a blackthorn juggernaut"; - - public override bool AlwaysMurderer => true; - public override bool BardImmune => !Core.AOS; - public override bool BleedImmune => true; - public override Poison PoisonImmune => Poison.Lethal; - public override int Meat => 1; - public override int TreasureMapLevel => 5; - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - if (Utility.RandomDouble() < 0.05) - { - if (!IsParagon) + [Constructible] + public Juggernaut() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.3, 0.6) { - if (Utility.RandomDouble() < 0.75) - c.DropItem(DawnsMusicGear.RandomCommon); - else - c.DropItem(DawnsMusicGear.RandomUncommon); + Body = 768; + + SetStr(301, 400); + SetDex(51, 70); + SetInt(51, 100); + + SetHits(181, 240); + + SetDamage(12, 19); + + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Fire, 25); + SetDamageType(ResistanceType.Energy, 25); + + SetResistance(ResistanceType.Physical, 65, 75); + SetResistance(ResistanceType.Fire, 35, 45); + SetResistance(ResistanceType.Cold, 35, 45); + SetResistance(ResistanceType.Poison, 15, 25); + SetResistance(ResistanceType.Energy, 10, 20); + + SetSkill(SkillName.Anatomy, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 140.1, 150.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.Wrestling, 90.1, 100.0); + + Fame = 12000; + Karma = -12000; + + VirtualArmor = 70; + + if (Utility.RandomDouble() < 0.1) + PackItem(new PowerCrystal()); + + if (Utility.RandomDouble() < 0.4) + PackItem(new ClockworkAssembly()); } - else + + public Juggernaut(Serial serial) : base(serial) { - c.DropItem(DawnsMusicGear.RandomRare); } - } - } - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.Gems, 1); - } + public override string CorpseName => "a juggernaut corpse"; - public override int GetDeathSound() => 0x423; + public override string DefaultName => "a blackthorn juggernaut"; - public override int GetAttackSound() => 0x23B; + public override bool AlwaysMurderer => true; + public override bool BardImmune => !Core.AOS; + public override bool BleedImmune => true; + public override Poison PoisonImmune => Poison.Lethal; + public override int Meat => 1; + public override int TreasureMapLevel => 5; - public override int GetHurtSound() => 0x140; - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (!m_Stunning && Utility.RandomDouble() < 0.3) - { - m_Stunning = true; - - defender.Animate(21, 6, 1, true, false, 0); - PlaySound(0xEE); - defender.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, - "You have been stunned by a colossal blow!"); - - if (Weapon is BaseWeapon weapon) - weapon.OnHit(this, defender); - - if (defender.Alive) + public override void OnDeath(Container c) { - defender.Frozen = true; - Timer.DelayCall(TimeSpan.FromSeconds(5.0), Recover_Callback, defender); + base.OnDeath(c); + + if (Utility.RandomDouble() < 0.05) + { + if (!IsParagon) + { + if (Utility.RandomDouble() < 0.75) + c.DropItem(DawnsMusicGear.RandomCommon); + else + c.DropItem(DawnsMusicGear.RandomUncommon); + } + else + { + c.DropItem(DawnsMusicGear.RandomRare); + } + } + } + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.Gems, 1); + } + + public override int GetDeathSound() => 0x423; + + public override int GetAttackSound() => 0x23B; + + public override int GetHurtSound() => 0x140; + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (!m_Stunning && Utility.RandomDouble() < 0.3) + { + m_Stunning = true; + + defender.Animate(21, 6, 1, true, false, 0); + PlaySound(0xEE); + defender.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + false, + "You have been stunned by a colossal blow!" + ); + + if (Weapon is BaseWeapon weapon) + weapon.OnHit(this, defender); + + if (defender.Alive) + { + defender.Frozen = true; + Timer.DelayCall(TimeSpan.FromSeconds(5.0), Recover_Callback, defender); + } + } + } + + private void Recover_Callback(Mobile defender) + { + defender.Frozen = false; + defender.Combatant = null; + defender.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You recover your senses."); + m_Stunning = 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(); } - } } - - private void Recover_Callback(Mobile defender) - { - defender.Frozen = false; - defender.Combatant = null; - defender.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You recover your senses."); - m_Stunning = false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/KhaldunRevenant.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/KhaldunRevenant.cs index ec56eef41..dd5217b98 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/KhaldunRevenant.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/KhaldunRevenant.cs @@ -5,154 +5,154 @@ using Server.Items; namespace Server.Mobiles { - public class KhaldunRevenant : BaseCreature - { - private static readonly HashSet m_Set = new HashSet(); - private readonly DateTime m_ExpireTime; - - private readonly Mobile m_Target; - - public KhaldunRevenant(Mobile target) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.18, 0.36) + public class KhaldunRevenant : BaseCreature { - Body = 0x3CA; - Hue = 0x41CE; + private static readonly HashSet m_Set = new HashSet(); + private readonly DateTime m_ExpireTime; - m_Target = target; - m_ExpireTime = DateTime.UtcNow + TimeSpan.FromMinutes(10.0); + private readonly Mobile m_Target; - SetStr(401, 500); - SetDex(296, 315); - SetInt(101, 200); + public KhaldunRevenant(Mobile target) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.18, 0.36) + { + Body = 0x3CA; + Hue = 0x41CE; - SetHits(241, 300); - SetStam(242, 280); + m_Target = target; + m_ExpireTime = DateTime.UtcNow + TimeSpan.FromMinutes(10.0); - SetDamage(20, 30); + SetStr(401, 500); + SetDex(296, 315); + SetInt(101, 200); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Cold, 50); + SetHits(241, 300); + SetStam(242, 280); - SetSkill(SkillName.MagicResist, 100.1, 150.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); - SetSkill(SkillName.Swords, 140.1, 150.0); - SetSkill(SkillName.Wrestling, 90.1, 100.0); + SetDamage(20, 30); - SetResistance(ResistanceType.Physical, 55, 65); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 60, 70); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 20, 30); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Cold, 50); - Fame = 0; - Karma = 0; + SetSkill(SkillName.MagicResist, 100.1, 150.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.Swords, 140.1, 150.0); + SetSkill(SkillName.Wrestling, 90.1, 100.0); - VirtualArmor = 60; + SetResistance(ResistanceType.Physical, 55, 65); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 60, 70); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 20, 30); - Halberd weapon = new Halberd { Hue = 0x41CE, Movable = false }; + Fame = 0; + Karma = 0; - AddItem(weapon); + VirtualArmor = 60; + + var weapon = new Halberd { Hue = 0x41CE, Movable = false }; + + AddItem(weapon); + } + + public KhaldunRevenant(Serial serial) : base(serial) + { + } + + public override bool DeleteCorpseOnDeath => true; + + public override Mobile ConstantFocus => m_Target; + public override bool AlwaysAttackable => true; + + public override string DefaultName => "a revenant"; + + public override bool BardImmune => true; + public override Poison PoisonImmune => Poison.Lethal; + + public new static void Initialize() + { + EventSink.PlayerDeath += EventSink_PlayerDeath; + } + + public static void EventSink_PlayerDeath(Mobile m) + { + var lastKiller = m.LastKiller; + + if (lastKiller is BaseCreature creature) + lastKiller = creature.GetMaster(); + + if (IsInsideKhaldun(m) && IsInsideKhaldun(lastKiller) && lastKiller.Player && !m_Set.Contains(lastKiller) && + m.Aggressors.Any(ai => ai.Attacker == lastKiller && ai.CanReportMurder)) + SummonRevenant(m, lastKiller); + } + + public static void SummonRevenant(Mobile victim, Mobile killer) + { + var revenant = new KhaldunRevenant(killer); + + revenant.MoveToWorld(victim.Location, victim.Map); + revenant.Combatant = killer; + revenant.FixedParticles(0, 0, 0, 0x13A7, EffectLayer.Waist); + Effects.PlaySound(revenant.Location, revenant.Map, 0x29); + + m_Set.Add(killer); + } + + public static bool IsInsideKhaldun(Mobile from) => from?.Region?.IsPartOf("Khaldun") == true; + + public override void DisplayPaperdollTo(Mobile to) + { + } + + public override int GetIdleSound() => 0x1BF; + + public override int GetAngerSound() => 0x107; + + public override int GetDeathSound() => 0xFD; + + public override void OnThink() + { + if (!m_Target.Alive || DateTime.UtcNow > m_ExpireTime) + { + Delete(); + return; + } + + // Combatant = m_Target; + // FocusMob = m_Target; + + if (AIObject != null) + AIObject.Action = ActionType.Combat; + + base.OnThink(); + } + + public override bool OnBeforeDeath() + { + Effects.SendLocationEffect(Location, Map, 0x376A, 10, 1); + return true; + } + + public override void OnDelete() + { + if (m_Target != null) + m_Set.Remove(m_Target); + + base.OnDelete(); + } + + 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(); + + Delete(); + } } - - public KhaldunRevenant(Serial serial) : base(serial) - { - } - - public override bool DeleteCorpseOnDeath => true; - - public override Mobile ConstantFocus => m_Target; - public override bool AlwaysAttackable => true; - - public override string DefaultName => "a revenant"; - - public override bool BardImmune => true; - public override Poison PoisonImmune => Poison.Lethal; - - public static new void Initialize() - { - EventSink.PlayerDeath += EventSink_PlayerDeath; - } - - public static void EventSink_PlayerDeath(Mobile m) - { - Mobile lastKiller = m.LastKiller; - - if (lastKiller is BaseCreature creature) - lastKiller = creature.GetMaster(); - - if (IsInsideKhaldun(m) && IsInsideKhaldun(lastKiller) && lastKiller.Player && !m_Set.Contains(lastKiller) && - m.Aggressors.Any(ai => ai.Attacker == lastKiller && ai.CanReportMurder)) - SummonRevenant(m, lastKiller); - } - - public static void SummonRevenant(Mobile victim, Mobile killer) - { - KhaldunRevenant revenant = new KhaldunRevenant(killer); - - revenant.MoveToWorld(victim.Location, victim.Map); - revenant.Combatant = killer; - revenant.FixedParticles(0, 0, 0, 0x13A7, EffectLayer.Waist); - Effects.PlaySound(revenant.Location, revenant.Map, 0x29); - - m_Set.Add(killer); - } - - public static bool IsInsideKhaldun(Mobile from) => from?.Region?.IsPartOf("Khaldun") == true; - - public override void DisplayPaperdollTo(Mobile to) - { - } - - public override int GetIdleSound() => 0x1BF; - - public override int GetAngerSound() => 0x107; - - public override int GetDeathSound() => 0xFD; - - public override void OnThink() - { - if (!m_Target.Alive || DateTime.UtcNow > m_ExpireTime) - { - Delete(); - return; - } - - // Combatant = m_Target; - // FocusMob = m_Target; - - if (AIObject != null) - AIObject.Action = ActionType.Combat; - - base.OnThink(); - } - - public override bool OnBeforeDeath() - { - Effects.SendLocationEffect(Location, Map, 0x376A, 10, 1); - return true; - } - - public override void OnDelete() - { - if (m_Target != null) - m_Set.Remove(m_Target); - - base.OnDelete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Delete(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/KhaldunSummoner.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/KhaldunSummoner.cs index 8295bd32d..a2fb42e8d 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/KhaldunSummoner.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/KhaldunSummoner.cs @@ -2,127 +2,127 @@ using Server.Items; namespace Server.Mobiles { - public class KhaldunSummoner : BaseCreature - { - [Constructible] - public KhaldunSummoner() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class KhaldunSummoner : BaseCreature { - Body = 0x190; - Title = "the Summoner"; + [Constructible] + public KhaldunSummoner() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0x190; + Title = "the Summoner"; - SetStr(351, 400); - SetDex(101, 150); - SetInt(502, 700); + SetStr(351, 400); + SetDex(101, 150); + SetInt(502, 700); - SetHits(421, 480); + SetHits(421, 480); - SetDamage(5, 15); + SetDamage(5, 15); - SetDamageType(ResistanceType.Physical, 75); - SetDamageType(ResistanceType.Cold, 25); + SetDamageType(ResistanceType.Physical, 75); + SetDamageType(ResistanceType.Cold, 25); - SetResistance(ResistanceType.Physical, 35, 40); - SetResistance(ResistanceType.Fire, 25, 30); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 25, 35); - SetResistance(ResistanceType.Energy, 25, 35); + SetResistance(ResistanceType.Physical, 35, 40); + SetResistance(ResistanceType.Fire, 25, 30); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 25, 35); + SetResistance(ResistanceType.Energy, 25, 35); - SetSkill(SkillName.Wrestling, 90.1, 100.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 90.1, 100.0); - SetSkill(SkillName.Magery, 90.1, 100.0); - SetSkill(SkillName.EvalInt, 100.0); - SetSkill(SkillName.Meditation, 120.1, 130.0); + SetSkill(SkillName.Wrestling, 90.1, 100.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 90.1, 100.0); + SetSkill(SkillName.Magery, 90.1, 100.0); + SetSkill(SkillName.EvalInt, 100.0); + SetSkill(SkillName.Meditation, 120.1, 130.0); - VirtualArmor = 36; - Fame = 10000; - Karma = -10000; + VirtualArmor = 36; + Fame = 10000; + Karma = -10000; - LeatherGloves gloves = new LeatherGloves(); - gloves.Hue = 0x66D; - AddItem(gloves); + var gloves = new LeatherGloves(); + gloves.Hue = 0x66D; + AddItem(gloves); - BoneHelm helm = new BoneHelm(); - helm.Hue = 0x835; - AddItem(helm); + var helm = new BoneHelm(); + helm.Hue = 0x835; + AddItem(helm); - Necklace necklace = new Necklace(); - necklace.Hue = 0x66D; - AddItem(necklace); + var necklace = new Necklace(); + necklace.Hue = 0x66D; + AddItem(necklace); - Cloak cloak = new Cloak(); - cloak.Hue = 0x66D; - AddItem(cloak); + var cloak = new Cloak(); + cloak.Hue = 0x66D; + AddItem(cloak); - Kilt kilt = new Kilt(); - kilt.Hue = 0x66D; - AddItem(kilt); + var kilt = new Kilt(); + kilt.Hue = 0x66D; + AddItem(kilt); - Sandals sandals = new Sandals(); - sandals.Hue = 0x66D; - AddItem(sandals); + var sandals = new Sandals(); + sandals.Hue = 0x66D; + AddItem(sandals); + } + + public KhaldunSummoner(Serial serial) : base(serial) + { + } + + public override bool ClickTitle => false; + public override bool ShowFameTitle => false; + + public override string DefaultName => "Zealot of Khaldun"; + + public override bool AlwaysMurderer => true; + public override bool Unprovokable => true; + + public override int GetIdleSound() => 0x184; + + public override int GetAngerSound() => 0x286; + + public override int GetDeathSound() => 0x288; + + public override int GetHurtSound() => 0x19F; + + public override bool OnBeforeDeath() + { + var rm = new BoneMagi(); + rm.Team = Team; + rm.Combatant = Combatant; + rm.NoKillAwards = true; + + if (rm.Backpack == null) + { + var pack = new Backpack(); + pack.Movable = false; + rm.AddItem(pack); + } + + for (var i = 0; i < 2; i++) + { + LootPack.FilthyRich.Generate(this, rm.Backpack, true, LootPack.GetLuckChanceForKiller(this)); + LootPack.FilthyRich.Generate(this, rm.Backpack, false, LootPack.GetLuckChanceForKiller(this)); + } + + Effects.PlaySound(this, Map, GetDeathSound()); + Effects.SendLocationEffect(Location, Map, 0x3709, 30, 10, 0x835, 0); + rm.MoveToWorld(Location, Map); + + Delete(); + return 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 KhaldunSummoner(Serial serial) : base(serial) - { - } - - public override bool ClickTitle => false; - public override bool ShowFameTitle => false; - - public override string DefaultName => "Zealot of Khaldun"; - - public override bool AlwaysMurderer => true; - public override bool Unprovokable => true; - - public override int GetIdleSound() => 0x184; - - public override int GetAngerSound() => 0x286; - - public override int GetDeathSound() => 0x288; - - public override int GetHurtSound() => 0x19F; - - public override bool OnBeforeDeath() - { - BoneMagi rm = new BoneMagi(); - rm.Team = Team; - rm.Combatant = Combatant; - rm.NoKillAwards = true; - - if (rm.Backpack == null) - { - Backpack pack = new Backpack(); - pack.Movable = false; - rm.AddItem(pack); - } - - for (int i = 0; i < 2; i++) - { - LootPack.FilthyRich.Generate(this, rm.Backpack, true, LootPack.GetLuckChanceForKiller(this)); - LootPack.FilthyRich.Generate(this, rm.Backpack, false, LootPack.GetLuckChanceForKiller(this)); - } - - Effects.PlaySound(this, Map, GetDeathSound()); - Effects.SendLocationEffect(Location, Map, 0x3709, 30, 10, 0x835, 0); - rm.MoveToWorld(Location, Map); - - Delete(); - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/KhaldunZealot.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/KhaldunZealot.cs index 28579cac1..ebbc1456e 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/KhaldunZealot.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/KhaldunZealot.cs @@ -2,136 +2,136 @@ using Server.Items; namespace Server.Mobiles { - public class KhaldunZealot : BaseCreature - { - [Constructible] - public KhaldunZealot() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class KhaldunZealot : BaseCreature { - Body = 0x190; - Title = "the Knight"; - Hue = 0; + [Constructible] + public KhaldunZealot() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0x190; + Title = "the Knight"; + Hue = 0; - SetStr(351, 400); - SetDex(151, 165); - SetInt(76, 100); + SetStr(351, 400); + SetDex(151, 165); + SetInt(76, 100); - SetHits(448, 470); + SetHits(448, 470); - SetDamage(15, 25); + SetDamage(15, 25); - SetDamageType(ResistanceType.Physical, 75); - SetDamageType(ResistanceType.Cold, 25); + SetDamageType(ResistanceType.Physical, 75); + SetDamageType(ResistanceType.Cold, 25); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 25, 30); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 25, 35); - SetResistance(ResistanceType.Energy, 25, 35); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 25, 30); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 25, 35); + SetResistance(ResistanceType.Energy, 25, 35); - SetSkill(SkillName.Wrestling, 70.1, 80.0); - SetSkill(SkillName.Swords, 120.1, 130.0); - SetSkill(SkillName.Anatomy, 120.1, 130.0); - SetSkill(SkillName.MagicResist, 90.1, 100.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.Wrestling, 70.1, 80.0); + SetSkill(SkillName.Swords, 120.1, 130.0); + SetSkill(SkillName.Anatomy, 120.1, 130.0); + SetSkill(SkillName.MagicResist, 90.1, 100.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); - Fame = 10000; - Karma = -10000; - VirtualArmor = 40; + Fame = 10000; + Karma = -10000; + VirtualArmor = 40; - VikingSword weapon = new VikingSword(); - weapon.Hue = 0x835; - weapon.Movable = false; - AddItem(weapon); + var weapon = new VikingSword(); + weapon.Hue = 0x835; + weapon.Movable = false; + AddItem(weapon); - MetalShield shield = new MetalShield(); - shield.Hue = 0x835; - shield.Movable = false; - AddItem(shield); + var shield = new MetalShield(); + shield.Hue = 0x835; + shield.Movable = false; + AddItem(shield); - BoneHelm helm = new BoneHelm(); - helm.Hue = 0x835; - AddItem(helm); + var helm = new BoneHelm(); + helm.Hue = 0x835; + AddItem(helm); - BoneArms arms = new BoneArms(); - arms.Hue = 0x835; - AddItem(arms); + var arms = new BoneArms(); + arms.Hue = 0x835; + AddItem(arms); - BoneGloves gloves = new BoneGloves(); - gloves.Hue = 0x835; - AddItem(gloves); + var gloves = new BoneGloves(); + gloves.Hue = 0x835; + AddItem(gloves); - BoneChest tunic = new BoneChest(); - tunic.Hue = 0x835; - AddItem(tunic); + var tunic = new BoneChest(); + tunic.Hue = 0x835; + AddItem(tunic); - BoneLegs legs = new BoneLegs(); - legs.Hue = 0x835; - AddItem(legs); + var legs = new BoneLegs(); + legs.Hue = 0x835; + AddItem(legs); - AddItem(new Boots()); + AddItem(new Boots()); + } + + public KhaldunZealot(Serial serial) : base(serial) + { + } + + public override bool ClickTitle => false; + public override bool ShowFameTitle => false; + + public override string DefaultName => "Zealot of Khaldun"; + + public override bool AlwaysMurderer => true; + public override bool Unprovokable => true; + public override Poison PoisonImmune => Poison.Deadly; + + public override int GetIdleSound() => 0x184; + + public override int GetAngerSound() => 0x286; + + public override int GetDeathSound() => 0x288; + + public override int GetHurtSound() => 0x19F; + + public override bool OnBeforeDeath() + { + var rm = new BoneKnight(); + rm.Team = Team; + rm.Combatant = Combatant; + rm.NoKillAwards = true; + + if (rm.Backpack == null) + { + var pack = new Backpack(); + pack.Movable = false; + rm.AddItem(pack); + } + + for (var i = 0; i < 2; i++) + { + LootPack.FilthyRich.Generate(this, rm.Backpack, true, LootPack.GetLuckChanceForKiller(this)); + LootPack.FilthyRich.Generate(this, rm.Backpack, false, LootPack.GetLuckChanceForKiller(this)); + } + + Effects.PlaySound(this, Map, GetDeathSound()); + Effects.SendLocationEffect(Location, Map, 0x3709, 30, 10, 0x835, 0); + rm.MoveToWorld(Location, Map); + + Delete(); + return 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 KhaldunZealot(Serial serial) : base(serial) - { - } - - public override bool ClickTitle => false; - public override bool ShowFameTitle => false; - - public override string DefaultName => "Zealot of Khaldun"; - - public override bool AlwaysMurderer => true; - public override bool Unprovokable => true; - public override Poison PoisonImmune => Poison.Deadly; - - public override int GetIdleSound() => 0x184; - - public override int GetAngerSound() => 0x286; - - public override int GetDeathSound() => 0x288; - - public override int GetHurtSound() => 0x19F; - - public override bool OnBeforeDeath() - { - BoneKnight rm = new BoneKnight(); - rm.Team = Team; - rm.Combatant = Combatant; - rm.NoKillAwards = true; - - if (rm.Backpack == null) - { - Backpack pack = new Backpack(); - pack.Movable = false; - rm.AddItem(pack); - } - - for (int i = 0; i < 2; i++) - { - LootPack.FilthyRich.Generate(this, rm.Backpack, true, LootPack.GetLuckChanceForKiller(this)); - LootPack.FilthyRich.Generate(this, rm.Backpack, false, LootPack.GetLuckChanceForKiller(this)); - } - - Effects.PlaySound(this, Map, GetDeathSound()); - Effects.SendLocationEffect(Location, Map, 0x3709, 30, 10, 0x835, 0); - rm.MoveToWorld(Location, Map); - - Delete(); - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Moloch.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Moloch.cs index ac313270e..75d8d80ba 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Moloch.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Moloch.cs @@ -2,65 +2,65 @@ using Server.Items; namespace Server.Mobiles { - public class Moloch : BaseCreature - { - [Constructible] - public Moloch() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Moloch : BaseCreature { - Body = 0x311; - BaseSoundID = 0x300; + [Constructible] + public Moloch() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0x311; + BaseSoundID = 0x300; - SetStr(331, 360); - SetDex(66, 85); - SetInt(41, 65); + SetStr(331, 360); + SetDex(66, 85); + SetInt(41, 65); - SetHits(171, 200); + SetHits(171, 200); - SetDamage(15, 23); + SetDamage(15, 23); - SetResistance(ResistanceType.Physical, 60, 70); - SetResistance(ResistanceType.Fire, 60, 70); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 20, 30); + SetResistance(ResistanceType.Physical, 60, 70); + SetResistance(ResistanceType.Fire, 60, 70); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 20, 30); - SetSkill(SkillName.MagicResist, 65.1, 75.0); - SetSkill(SkillName.Tactics, 75.1, 90.0); - SetSkill(SkillName.Wrestling, 70.1, 90.0); + SetSkill(SkillName.MagicResist, 65.1, 75.0); + SetSkill(SkillName.Tactics, 75.1, 90.0); + SetSkill(SkillName.Wrestling, 70.1, 90.0); - Fame = 7500; - Karma = -7500; + Fame = 7500; + Karma = -7500; - VirtualArmor = 32; + VirtualArmor = 32; + } + + public Moloch(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a moloch corpse"; + + public override string DefaultName => "a moloch"; + + public override Poison PoisonImmune => Poison.Regular; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.ConcussionBlow; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + } + + 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(); + } } - - public Moloch(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a moloch corpse"; - - public override string DefaultName => "a moloch"; - - public override Poison PoisonImmune => Poison.Regular; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.ConcussionBlow; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Mongbat.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Mongbat.cs index ce0ce9aef..b4628c2cc 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Mongbat.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Mongbat.cs @@ -1,67 +1,67 @@ namespace Server.Mobiles { - public class Mongbat : BaseCreature - { - [Constructible] - public Mongbat() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Mongbat : BaseCreature { - Body = 39; - BaseSoundID = 422; + [Constructible] + public Mongbat() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 39; + BaseSoundID = 422; - SetStr(6, 10); - SetDex(26, 38); - SetInt(6, 14); + SetStr(6, 10); + SetDex(26, 38); + SetInt(6, 14); - SetHits(4, 6); - SetMana(0); + SetHits(4, 6); + SetMana(0); - SetDamage(1, 2); + SetDamage(1, 2); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 5, 10); + SetResistance(ResistanceType.Physical, 5, 10); - SetSkill(SkillName.MagicResist, 5.1, 14.0); - SetSkill(SkillName.Tactics, 5.1, 10.0); - SetSkill(SkillName.Wrestling, 5.1, 10.0); + SetSkill(SkillName.MagicResist, 5.1, 14.0); + SetSkill(SkillName.Tactics, 5.1, 10.0); + SetSkill(SkillName.Wrestling, 5.1, 10.0); - Fame = 150; - Karma = -150; + Fame = 150; + Karma = -150; - VirtualArmor = 10; + VirtualArmor = 10; - Tamable = true; - ControlSlots = 1; - MinTameSkill = -18.9; + Tamable = true; + ControlSlots = 1; + MinTameSkill = -18.9; + } + + public Mongbat(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a mongbat corpse"; + public override string DefaultName => "a mongbat"; + + public override bool CanFly => true; + + public override int Meat => 1; + public override FoodType FavoriteFood => FoodType.Meat; + + public override void GenerateLoot() + { + AddLoot(LootPack.Poor); + } + + 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(); + } } - - public Mongbat(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a mongbat corpse"; - public override string DefaultName => "a mongbat"; - - public override bool CanFly => true; - - public override int Meat => 1; - public override FoodType FavoriteFood => FoodType.Meat; - - public override void GenerateLoot() - { - AddLoot(LootPack.Poor); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Mummy.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Mummy.cs index 225724af4..884f361ea 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Mummy.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Mummy.cs @@ -3,76 +3,76 @@ using Server.Items; namespace Server.Mobiles { - public class Mummy : BaseCreature - { - [Constructible] - public Mummy() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.4, 0.8) + public class Mummy : BaseCreature { - Body = 154; - BaseSoundID = 471; + [Constructible] + public Mummy() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.4, 0.8) + { + Body = 154; + BaseSoundID = 471; - SetStr(346, 370); - SetDex(71, 90); - SetInt(26, 40); + SetStr(346, 370); + SetDex(71, 90); + SetInt(26, 40); - SetHits(208, 222); + SetHits(208, 222); - SetDamage(13, 23); + SetDamage(13, 23); - SetDamageType(ResistanceType.Physical, 40); - SetDamageType(ResistanceType.Cold, 60); + SetDamageType(ResistanceType.Physical, 40); + SetDamageType(ResistanceType.Cold, 60); - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 10, 20); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 20, 30); + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 10, 20); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 20, 30); - SetSkill(SkillName.MagicResist, 15.1, 40.0); - SetSkill(SkillName.Tactics, 35.1, 50.0); - SetSkill(SkillName.Wrestling, 35.1, 50.0); + SetSkill(SkillName.MagicResist, 15.1, 40.0); + SetSkill(SkillName.Tactics, 35.1, 50.0); + SetSkill(SkillName.Wrestling, 35.1, 50.0); - Fame = 4000; - Karma = -4000; + Fame = 4000; + Karma = -4000; - VirtualArmor = 50; + VirtualArmor = 50; - if (Core.ML && Utility.RandomDouble() < .33) - PackItem(Seed.RandomPeculiarSeed(2)); + if (Core.ML && Utility.RandomDouble() < .33) + PackItem(Seed.RandomPeculiarSeed(2)); - PackItem(new Garlic(5)); - PackItem(new Bandage(10)); + PackItem(new Garlic(5)); + PackItem(new Bandage(10)); + } + + public Mummy(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a mummy corpse"; + public override string DefaultName => "a mummy"; + + public override bool BleedImmune => true; + public override Poison PoisonImmune => Poison.Lesser; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.Gems); + AddLoot(LootPack.Potions); + } + + 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(); + } } - - public Mummy(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a mummy corpse"; - public override string DefaultName => "a mummy"; - - public override bool BleedImmune => true; - public override Poison PoisonImmune => Poison.Lesser; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.Gems); - AddLoot(LootPack.Potions); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Ogre.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Ogre.cs index efe8a8f3f..cb68c9464 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Ogre.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Ogre.cs @@ -2,70 +2,70 @@ using Server.Items; namespace Server.Mobiles { - public class Ogre : BaseCreature - { - [Constructible] - public Ogre() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Ogre : BaseCreature { - Body = 1; - BaseSoundID = 427; + [Constructible] + public Ogre() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 1; + BaseSoundID = 427; - SetStr(166, 195); - SetDex(46, 65); - SetInt(46, 70); + SetStr(166, 195); + SetDex(46, 65); + SetInt(46, 70); - SetHits(100, 117); - SetMana(0); + SetHits(100, 117); + SetMana(0); - SetDamage(9, 11); + SetDamage(9, 11); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 30, 35); - SetResistance(ResistanceType.Fire, 15, 25); - SetResistance(ResistanceType.Cold, 15, 25); - SetResistance(ResistanceType.Poison, 15, 25); - SetResistance(ResistanceType.Energy, 25); + SetResistance(ResistanceType.Physical, 30, 35); + SetResistance(ResistanceType.Fire, 15, 25); + SetResistance(ResistanceType.Cold, 15, 25); + SetResistance(ResistanceType.Poison, 15, 25); + SetResistance(ResistanceType.Energy, 25); - SetSkill(SkillName.MagicResist, 55.1, 70.0); - SetSkill(SkillName.Tactics, 60.1, 70.0); - SetSkill(SkillName.Wrestling, 70.1, 80.0); + SetSkill(SkillName.MagicResist, 55.1, 70.0); + SetSkill(SkillName.Tactics, 60.1, 70.0); + SetSkill(SkillName.Wrestling, 70.1, 80.0); - Fame = 3000; - Karma = -3000; + Fame = 3000; + Karma = -3000; - VirtualArmor = 32; + VirtualArmor = 32; - PackItem(new Club()); + PackItem(new Club()); + } + + public Ogre(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ogre corpse"; + public override string DefaultName => "an ogre"; + + public override bool CanRummageCorpses => true; + public override int TreasureMapLevel => 1; + public override int Meat => 2; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Potions); + } + + 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(); + } } - - public Ogre(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ogre corpse"; - public override string DefaultName => "an ogre"; - - public override bool CanRummageCorpses => true; - public override int TreasureMapLevel => 1; - public override int Meat => 2; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Potions); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/OgreLord.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/OgreLord.cs index 97f95d1ef..a3305cd0c 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/OgreLord.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/OgreLord.cs @@ -4,72 +4,72 @@ using Server.Items; namespace Server.Mobiles { - public class OgreLord : BaseCreature - { - [Constructible] - public OgreLord() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class OgreLord : BaseCreature { - Body = 83; - BaseSoundID = 427; + [Constructible] + public OgreLord() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 83; + BaseSoundID = 427; - SetStr(767, 945); - SetDex(66, 75); - SetInt(46, 70); + SetStr(767, 945); + SetDex(66, 75); + SetInt(46, 70); - SetHits(476, 552); + SetHits(476, 552); - SetDamage(20, 25); + SetDamage(20, 25); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.MagicResist, 125.1, 140.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); - SetSkill(SkillName.Wrestling, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 125.1, 140.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.Wrestling, 90.1, 100.0); - Fame = 15000; - Karma = -15000; + Fame = 15000; + Karma = -15000; - VirtualArmor = 50; + VirtualArmor = 50; - PackItem(new Club()); + PackItem(new Club()); + } + + public OgreLord(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ogre lords corpse"; + public override Faction FactionAllegiance => Minax.Instance; + public override Ethic EthicAllegiance => Ethic.Evil; + + public override string DefaultName => "an ogre lord"; + + public override bool CanRummageCorpses => true; + public override Poison PoisonImmune => Poison.Regular; + public override int TreasureMapLevel => 3; + public override int Meat => 2; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich, 2); + } + + 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(); + } } - - public OgreLord(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ogre lords corpse"; - public override Faction FactionAllegiance => Minax.Instance; - public override Ethic EthicAllegiance => Ethic.Evil; - - public override string DefaultName => "an ogre lord"; - - public override bool CanRummageCorpses => true; - public override Poison PoisonImmune => Poison.Regular; - public override int TreasureMapLevel => 3; - public override int Meat => 2; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Orc.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Orc.cs index 56d539938..cec0a1cfb 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Orc.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Orc.cs @@ -3,119 +3,119 @@ using Server.Misc; namespace Server.Mobiles { - public class Orc : BaseCreature - { - [Constructible] - public Orc() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Orc : BaseCreature { - Name = NameList.RandomName("orc"); - Body = 17; - BaseSoundID = 0x45A; - - SetStr(96, 120); - SetDex(81, 105); - SetInt(36, 60); - - SetHits(58, 72); - - SetDamage(5, 7); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 25, 30); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 10, 20); - SetResistance(ResistanceType.Poison, 10, 20); - SetResistance(ResistanceType.Energy, 20, 30); - - SetSkill(SkillName.MagicResist, 50.1, 75.0); - SetSkill(SkillName.Tactics, 55.1, 80.0); - SetSkill(SkillName.Wrestling, 50.1, 70.0); - - Fame = 1500; - Karma = -1500; - - VirtualArmor = 28; - - PackItem( - Utility.Random(20) switch + [Constructible] + public Orc() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) { - 0 => new Scimitar(), - 1 => new Katana(), - 2 => new WarMace(), - 3 => new WarHammer(), - 4 => new Kryss(), - 5 => new Pitchfork(), - _ => null // 6-19 + Name = NameList.RandomName("orc"); + Body = 17; + BaseSoundID = 0x45A; + + SetStr(96, 120); + SetDex(81, 105); + SetInt(36, 60); + + SetHits(58, 72); + + SetDamage(5, 7); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 25, 30); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Energy, 20, 30); + + SetSkill(SkillName.MagicResist, 50.1, 75.0); + SetSkill(SkillName.Tactics, 55.1, 80.0); + SetSkill(SkillName.Wrestling, 50.1, 70.0); + + Fame = 1500; + Karma = -1500; + + VirtualArmor = 28; + + PackItem( + Utility.Random(20) switch + { + 0 => new Scimitar(), + 1 => new Katana(), + 2 => new WarMace(), + 3 => new WarHammer(), + 4 => new Kryss(), + 5 => new Pitchfork(), + _ => null // 6-19 + } + ); + + PackItem(new ThighBoots()); + + PackItem( + Utility.Random(3) switch + { + 0 => new Ribs(), + 1 => new Shaft(), + _ => new Candle() // 2 + } + ); + + if (Utility.RandomDouble() < 0.2) + PackItem(new BolaBall()); } - ); - PackItem(new ThighBoots()); - - PackItem( - Utility.Random(3) switch + public Orc(Serial serial) : base(serial) { - 0 => new Ribs(), - 1 => new Shaft(), - _ => new Candle() // 2 } - ); - if (Utility.RandomDouble() < 0.2) - PackItem(new BolaBall()); + public override string CorpseName => "an orcish corpse"; + public override InhumanSpeech SpeechType => InhumanSpeech.Orc; + + public override bool CanRummageCorpses => true; + public override int TreasureMapLevel => 1; + public override int Meat => 1; + + public override OppositionGroup OppositionGroup => OppositionGroup.SavagesAndOrcs; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + public override bool IsEnemy(Mobile m) + { + if (m.Player && m.FindItemOnLayer(Layer.Helm) is OrcishKinMask) + return false; + + return base.IsEnemy(m); + } + + public override void AggressiveAction(Mobile aggressor, bool criminal) + { + base.AggressiveAction(aggressor, criminal); + + var item = aggressor.FindItemOnLayer(Layer.Helm); + + if (item is OrcishKinMask) + { + AOS.Damage(aggressor, 50, 0, 100, 0, 0, 0); + item.Delete(); + aggressor.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); + aggressor.PlaySound(0x307); + } + } + + 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(); + } } - - public Orc(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an orcish corpse"; - public override InhumanSpeech SpeechType => InhumanSpeech.Orc; - - public override bool CanRummageCorpses => true; - public override int TreasureMapLevel => 1; - public override int Meat => 1; - - public override OppositionGroup OppositionGroup => OppositionGroup.SavagesAndOrcs; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } - - public override bool IsEnemy(Mobile m) - { - if (m.Player && m.FindItemOnLayer(Layer.Helm) is OrcishKinMask) - return false; - - return base.IsEnemy(m); - } - - public override void AggressiveAction(Mobile aggressor, bool criminal) - { - base.AggressiveAction(aggressor, criminal); - - Item item = aggressor.FindItemOnLayer(Layer.Helm); - - if (item is OrcishKinMask) - { - AOS.Damage(aggressor, 50, 0, 100, 0, 0, 0); - item.Delete(); - aggressor.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); - aggressor.PlaySound(0x307); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/OrcBomber.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/OrcBomber.cs index b7c405abe..4d4acbff4 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/OrcBomber.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/OrcBomber.cs @@ -4,155 +4,155 @@ using Server.Misc; namespace Server.Mobiles { - public class OrcBomber : BaseCreature - { - private DateTime m_NextBomb; - private int m_Thrown; - - [Constructible] - public OrcBomber() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class OrcBomber : BaseCreature { - Body = 182; - BaseSoundID = 0x45A; + private DateTime m_NextBomb; + private int m_Thrown; - SetStr(147, 215); - SetDex(91, 115); - SetInt(61, 85); + [Constructible] + public OrcBomber() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 182; + BaseSoundID = 0x45A; - SetHits(95, 123); + SetStr(147, 215); + SetDex(91, 115); + SetInt(61, 85); - SetDamage(1, 8); + SetHits(95, 123); - SetDamageType(ResistanceType.Physical, 75); - SetDamageType(ResistanceType.Fire, 25); + SetDamage(1, 8); - SetResistance(ResistanceType.Physical, 25, 35); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 15, 25); - SetResistance(ResistanceType.Poison, 15, 20); - SetResistance(ResistanceType.Energy, 25, 30); + SetDamageType(ResistanceType.Physical, 75); + SetDamageType(ResistanceType.Fire, 25); - SetSkill(SkillName.MagicResist, 70.1, 85.0); - SetSkill(SkillName.Swords, 60.1, 85.0); - SetSkill(SkillName.Tactics, 75.1, 90.0); - SetSkill(SkillName.Wrestling, 60.1, 85.0); + SetResistance(ResistanceType.Physical, 25, 35); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 15, 25); + SetResistance(ResistanceType.Poison, 15, 20); + SetResistance(ResistanceType.Energy, 25, 30); - Fame = 2500; - Karma = -2500; + SetSkill(SkillName.MagicResist, 70.1, 85.0); + SetSkill(SkillName.Swords, 60.1, 85.0); + SetSkill(SkillName.Tactics, 75.1, 90.0); + SetSkill(SkillName.Wrestling, 60.1, 85.0); - VirtualArmor = 30; + Fame = 2500; + Karma = -2500; - PackItem(new SulfurousAsh(Utility.RandomMinMax(6, 10))); - PackItem(new MandrakeRoot(Utility.RandomMinMax(6, 10))); - PackItem(new BlackPearl(Utility.RandomMinMax(6, 10))); - PackItem(new MortarPestle()); - PackItem(new LesserExplosionPotion()); + VirtualArmor = 30; - if (Utility.RandomDouble() < 0.2) - PackItem(new BolaBall()); + PackItem(new SulfurousAsh(Utility.RandomMinMax(6, 10))); + PackItem(new MandrakeRoot(Utility.RandomMinMax(6, 10))); + PackItem(new BlackPearl(Utility.RandomMinMax(6, 10))); + PackItem(new MortarPestle()); + PackItem(new LesserExplosionPotion()); + + if (Utility.RandomDouble() < 0.2) + PackItem(new BolaBall()); + } + + public OrcBomber(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an orcish corpse"; + public override InhumanSpeech SpeechType => InhumanSpeech.Orc; + + public override string DefaultName => "an orc bomber"; + + public override bool CanRummageCorpses => true; + + public override OppositionGroup OppositionGroup => OppositionGroup.SavagesAndOrcs; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Meager); + } + + public override bool IsEnemy(Mobile m) + { + if (m.Player && m.FindItemOnLayer(Layer.Helm) is OrcishKinMask) + return false; + + return base.IsEnemy(m); + } + + public override void AggressiveAction(Mobile aggressor, bool criminal) + { + base.AggressiveAction(aggressor, criminal); + + var item = aggressor.FindItemOnLayer(Layer.Helm); + + if (item is OrcishKinMask) + { + AOS.Damage(aggressor, 50, 0, 100, 0, 0, 0); + item.Delete(); + aggressor.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); + aggressor.PlaySound(0x307); + } + } + + public override void OnActionCombat() + { + var combatant = Combatant; + + if (combatant?.Deleted != false || combatant.Map != Map || !InRange(combatant, 12) || + !CanBeHarmful(combatant) || !InLOS(combatant)) + return; + + if (DateTime.UtcNow >= m_NextBomb) + { + ThrowBomb(combatant); + + m_Thrown++; + + if (Utility.RandomDouble() <= 0.75 && m_Thrown % 2 == 1) // 75% chance to quickly throw another bomb + m_NextBomb = DateTime.UtcNow + TimeSpan.FromSeconds(3.0); + else + m_NextBomb = DateTime.UtcNow + TimeSpan.FromSeconds(5.0 + 10.0 * Utility.RandomDouble()); // 5-15 seconds + } + } + + public void ThrowBomb(Mobile m) + { + DoHarmful(m); + + MovingParticles(m, 0x1C19, 1, 0, false, true, 0, 0, 9502, 6014, 0x11D, EffectLayer.Waist, 0); + + new InternalTimer(m, this).Start(); + } + + 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(); + } + + private class InternalTimer : Timer + { + private readonly Mobile m_From; + private readonly Mobile m_Mobile; + + public InternalTimer(Mobile m, Mobile from) : base(TimeSpan.FromSeconds(1.0)) + { + m_Mobile = m; + m_From = from; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + m_Mobile.PlaySound(0x11D); + AOS.Damage(m_Mobile, m_From, Utility.RandomMinMax(10, 20), 0, 100, 0, 0, 0); + } + } } - - public OrcBomber(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an orcish corpse"; - public override InhumanSpeech SpeechType => InhumanSpeech.Orc; - - public override string DefaultName => "an orc bomber"; - - public override bool CanRummageCorpses => true; - - public override OppositionGroup OppositionGroup => OppositionGroup.SavagesAndOrcs; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Meager); - } - - public override bool IsEnemy(Mobile m) - { - if (m.Player && m.FindItemOnLayer(Layer.Helm) is OrcishKinMask) - return false; - - return base.IsEnemy(m); - } - - public override void AggressiveAction(Mobile aggressor, bool criminal) - { - base.AggressiveAction(aggressor, criminal); - - Item item = aggressor.FindItemOnLayer(Layer.Helm); - - if (item is OrcishKinMask) - { - AOS.Damage(aggressor, 50, 0, 100, 0, 0, 0); - item.Delete(); - aggressor.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); - aggressor.PlaySound(0x307); - } - } - - public override void OnActionCombat() - { - Mobile combatant = Combatant; - - if (combatant?.Deleted != false || combatant.Map != Map || !InRange(combatant, 12) || - !CanBeHarmful(combatant) || !InLOS(combatant)) - return; - - if (DateTime.UtcNow >= m_NextBomb) - { - ThrowBomb(combatant); - - m_Thrown++; - - if (Utility.RandomDouble() <= 0.75 && m_Thrown % 2 == 1) // 75% chance to quickly throw another bomb - m_NextBomb = DateTime.UtcNow + TimeSpan.FromSeconds(3.0); - else - m_NextBomb = DateTime.UtcNow + TimeSpan.FromSeconds(5.0 + 10.0 * Utility.RandomDouble()); // 5-15 seconds - } - } - - public void ThrowBomb(Mobile m) - { - DoHarmful(m); - - MovingParticles(m, 0x1C19, 1, 0, false, true, 0, 0, 9502, 6014, 0x11D, EffectLayer.Waist, 0); - - new InternalTimer(m, this).Start(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - - private class InternalTimer : Timer - { - private readonly Mobile m_Mobile; - private readonly Mobile m_From; - - public InternalTimer(Mobile m, Mobile from) : base(TimeSpan.FromSeconds(1.0)) - { - m_Mobile = m; - m_From = from; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - m_Mobile.PlaySound(0x11D); - AOS.Damage(m_Mobile, m_From, Utility.RandomMinMax(10, 20), 0, 100, 0, 0, 0); - } - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/OrcBrute.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/OrcBrute.cs index 06c2ba835..55fa18d35 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/OrcBrute.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/OrcBrute.cs @@ -3,135 +3,135 @@ using Server.Items; namespace Server.Mobiles { - public class OrcBrute : BaseCreature - { - [Constructible] - public OrcBrute() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class OrcBrute : BaseCreature { - Body = 189; - BaseSoundID = 0x45A; + [Constructible] + public OrcBrute() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 189; + BaseSoundID = 0x45A; - SetStr(767, 945); - SetDex(66, 75); - SetInt(46, 70); + SetStr(767, 945); + SetDex(66, 75); + SetInt(46, 70); - SetHits(476, 552); + SetHits(476, 552); - SetDamage(20, 25); + SetDamage(20, 25); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 25, 35); - SetResistance(ResistanceType.Poison, 25, 35); - SetResistance(ResistanceType.Energy, 25, 35); + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 25, 35); + SetResistance(ResistanceType.Poison, 25, 35); + SetResistance(ResistanceType.Energy, 25, 35); - SetSkill(SkillName.Macing, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 125.1, 140.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); - SetSkill(SkillName.Wrestling, 90.1, 100.0); + SetSkill(SkillName.Macing, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 125.1, 140.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.Wrestling, 90.1, 100.0); - Fame = 15000; - Karma = -15000; + Fame = 15000; + Karma = -15000; - VirtualArmor = 50; + VirtualArmor = 50; - Item ore = new ShadowIronOre(25); - ore.ItemID = 0x19B9; - PackItem(ore); - PackItem(new IronIngot(10)); + Item ore = new ShadowIronOre(25); + ore.ItemID = 0x19B9; + PackItem(ore); + PackItem(new IronIngot(10)); - if (Utility.RandomDouble() < 0.05) - PackItem(new OrcishKinMask()); + if (Utility.RandomDouble() < 0.05) + PackItem(new OrcishKinMask()); - if (Utility.RandomDouble() < 0.2) - PackItem(new BolaBall()); + if (Utility.RandomDouble() < 0.2) + PackItem(new BolaBall()); + } + + public OrcBrute(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an orcish corpse"; + public override string DefaultName => "an orc brute"; + + public override bool BardImmune => !Core.AOS; + public override Poison PoisonImmune => Poison.Lethal; + public override int Meat => 2; + + public override OppositionGroup OppositionGroup => OppositionGroup.SavagesAndOrcs; + + public override bool CanRummageCorpses => true; + public override bool AutoDispel => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.Rich); + } + + public override bool IsEnemy(Mobile m) + { + if (m.Player && m.FindItemOnLayer(Layer.Helm) is OrcishKinMask) + return false; + + return base.IsEnemy(m); + } + + public override void AggressiveAction(Mobile aggressor, bool criminal) + { + base.AggressiveAction(aggressor, criminal); + + var item = aggressor.FindItemOnLayer(Layer.Helm); + + if (item is OrcishKinMask) + { + AOS.Damage(aggressor, 50, 0, 100, 0, 0, 0); + item.Delete(); + aggressor.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); + aggressor.PlaySound(0x307); + } + } + + public override void OnDamagedBySpell(Mobile caster) + { + if (caster == this) + return; + + SpawnOrcLord(caster); + } + + public void SpawnOrcLord(Mobile target) + { + var map = target.Map; + + if (map == null) + return; + + var eable = GetMobilesInRange(10); + + if (eable.Count() < 10) + { + BaseCreature orc = new SpawnedOrcishLord { Team = Team }; + + orc.MoveToWorld(map.GetRandomNearbyLocation(target.Location), map); + orc.Combatant = target; + } + + eable.Free(); + } + + 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(); + } } - - public OrcBrute(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an orcish corpse"; - public override string DefaultName => "an orc brute"; - - public override bool BardImmune => !Core.AOS; - public override Poison PoisonImmune => Poison.Lethal; - public override int Meat => 2; - - public override OppositionGroup OppositionGroup => OppositionGroup.SavagesAndOrcs; - - public override bool CanRummageCorpses => true; - public override bool AutoDispel => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.Rich); - } - - public override bool IsEnemy(Mobile m) - { - if (m.Player && m.FindItemOnLayer(Layer.Helm) is OrcishKinMask) - return false; - - return base.IsEnemy(m); - } - - public override void AggressiveAction(Mobile aggressor, bool criminal) - { - base.AggressiveAction(aggressor, criminal); - - Item item = aggressor.FindItemOnLayer(Layer.Helm); - - if (item is OrcishKinMask) - { - AOS.Damage(aggressor, 50, 0, 100, 0, 0, 0); - item.Delete(); - aggressor.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); - aggressor.PlaySound(0x307); - } - } - - public override void OnDamagedBySpell(Mobile caster) - { - if (caster == this) - return; - - SpawnOrcLord(caster); - } - - public void SpawnOrcLord(Mobile target) - { - Map map = target.Map; - - if (map == null) - return; - - IPooledEnumerable eable = GetMobilesInRange(10); - - if (eable.Count() < 10) - { - BaseCreature orc = new SpawnedOrcishLord { Team = Team }; - - orc.MoveToWorld(map.GetRandomNearbyLocation(target.Location), map); - orc.Combatant = target; - } - - eable.Free(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/OrcCaptain.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/OrcCaptain.cs index 248d4aae3..2c69243c8 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/OrcCaptain.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/OrcCaptain.cs @@ -3,117 +3,117 @@ using Server.Misc; namespace Server.Mobiles { - public class OrcCaptain : BaseCreature - { - [Constructible] - public OrcCaptain() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class OrcCaptain : BaseCreature { - Name = NameList.RandomName("orc"); - Body = 7; - BaseSoundID = 0x45A; - - SetStr(111, 145); - SetDex(101, 135); - SetInt(86, 110); - - SetHits(67, 87); - - SetDamage(5, 15); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 30, 35); - SetResistance(ResistanceType.Fire, 10, 20); - SetResistance(ResistanceType.Cold, 15, 25); - SetResistance(ResistanceType.Poison, 5, 10); - SetResistance(ResistanceType.Energy, 5, 10); - - SetSkill(SkillName.MagicResist, 70.1, 85.0); - SetSkill(SkillName.Swords, 70.1, 95.0); - SetSkill(SkillName.Tactics, 85.1, 100.0); - - Fame = 2500; - Karma = -2500; - - VirtualArmor = 34; - - // TODO: Skull? - PackItem( - Utility.Random(7) switch + [Constructible] + public OrcCaptain() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) { - 0 => new Arrow(), - 1 => new Lockpick(), - 2 => new Shaft(), - 3 => new Ribs(), - 4 => new Bandage(), - 5 => new BeverageBottle(BeverageType.Wine), - _ => new Jug(BeverageType.Cider) // 6 + Name = NameList.RandomName("orc"); + Body = 7; + BaseSoundID = 0x45A; + + SetStr(111, 145); + SetDex(101, 135); + SetInt(86, 110); + + SetHits(67, 87); + + SetDamage(5, 15); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 30, 35); + SetResistance(ResistanceType.Fire, 10, 20); + SetResistance(ResistanceType.Cold, 15, 25); + SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Energy, 5, 10); + + SetSkill(SkillName.MagicResist, 70.1, 85.0); + SetSkill(SkillName.Swords, 70.1, 95.0); + SetSkill(SkillName.Tactics, 85.1, 100.0); + + Fame = 2500; + Karma = -2500; + + VirtualArmor = 34; + + // TODO: Skull? + PackItem( + Utility.Random(7) switch + { + 0 => new Arrow(), + 1 => new Lockpick(), + 2 => new Shaft(), + 3 => new Ribs(), + 4 => new Bandage(), + 5 => new BeverageBottle(BeverageType.Wine), + _ => new Jug(BeverageType.Cider) // 6 + } + ); + + if (Core.AOS) + PackItem(Loot.RandomNecromancyReagent()); } - ); - if (Core.AOS) - PackItem(Loot.RandomNecromancyReagent()); + public OrcCaptain(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an orcish corpse"; + public override InhumanSpeech SpeechType => InhumanSpeech.Orc; + + public override bool CanRummageCorpses => true; + public override int Meat => 1; + + public override OppositionGroup OppositionGroup => OppositionGroup.SavagesAndOrcs; + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + // TODO: Check drop rate + if (Utility.RandomDouble() < 0.05) + c.DropItem(new StoutWhip()); + } + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager, 2); + } + + public override bool IsEnemy(Mobile m) + { + if (m.Player && m.FindItemOnLayer(Layer.Helm) is OrcishKinMask) + return false; + + return base.IsEnemy(m); + } + + public override void AggressiveAction(Mobile aggressor, bool criminal) + { + base.AggressiveAction(aggressor, criminal); + + var item = aggressor.FindItemOnLayer(Layer.Helm); + + if (item is OrcishKinMask) + { + AOS.Damage(aggressor, 50, 0, 100, 0, 0, 0); + item.Delete(); + aggressor.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); + aggressor.PlaySound(0x307); + } + } + + 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(); + } } - - public OrcCaptain(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an orcish corpse"; - public override InhumanSpeech SpeechType => InhumanSpeech.Orc; - - public override bool CanRummageCorpses => true; - public override int Meat => 1; - - public override OppositionGroup OppositionGroup => OppositionGroup.SavagesAndOrcs; - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - // TODO: Check drop rate - if (Utility.RandomDouble() < 0.05) - c.DropItem(new StoutWhip()); - } - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager, 2); - } - - public override bool IsEnemy(Mobile m) - { - if (m.Player && m.FindItemOnLayer(Layer.Helm) is OrcishKinMask) - return false; - - return base.IsEnemy(m); - } - - public override void AggressiveAction(Mobile aggressor, bool criminal) - { - base.AggressiveAction(aggressor, criminal); - - Item item = aggressor.FindItemOnLayer(Layer.Helm); - - if (item is OrcishKinMask) - { - AOS.Damage(aggressor, 50, 0, 100, 0, 0, 0); - item.Delete(); - aggressor.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); - aggressor.PlaySound(0x307); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/OrcishLord.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/OrcishLord.cs index fe561e358..ad235e6f1 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/OrcishLord.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/OrcishLord.cs @@ -3,113 +3,113 @@ using Server.Misc; namespace Server.Mobiles { - public class OrcishLord : BaseCreature - { - [Constructible] - public OrcishLord() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class OrcishLord : BaseCreature { - Body = 138; - BaseSoundID = 0x45A; - - SetStr(147, 215); - SetDex(91, 115); - SetInt(61, 85); - - SetHits(95, 123); - - SetDamage(4, 14); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 25, 35); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 20, 30); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 30, 40); - - SetSkill(SkillName.MagicResist, 70.1, 85.0); - SetSkill(SkillName.Swords, 60.1, 85.0); - SetSkill(SkillName.Tactics, 75.1, 90.0); - SetSkill(SkillName.Wrestling, 60.1, 85.0); - - Fame = 2500; - Karma = -2500; - - PackItem( - Utility.Random(5) switch + [Constructible] + public OrcishLord() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) { - 0 => new Lockpick(), - 1 => new MortarPestle(), - 2 => new Bottle(), - 3 => new RawRibs(), - _ => new Shovel() // 4 + Body = 138; + BaseSoundID = 0x45A; + + SetStr(147, 215); + SetDex(91, 115); + SetInt(61, 85); + + SetHits(95, 123); + + SetDamage(4, 14); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 25, 35); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 20, 30); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 30, 40); + + SetSkill(SkillName.MagicResist, 70.1, 85.0); + SetSkill(SkillName.Swords, 60.1, 85.0); + SetSkill(SkillName.Tactics, 75.1, 90.0); + SetSkill(SkillName.Wrestling, 60.1, 85.0); + + Fame = 2500; + Karma = -2500; + + PackItem( + Utility.Random(5) switch + { + 0 => new Lockpick(), + 1 => new MortarPestle(), + 2 => new Bottle(), + 3 => new RawRibs(), + _ => new Shovel() // 4 + } + ); + + PackItem(new RingmailChest()); + + if (Utility.RandomDouble() < 0.3) + PackItem(Loot.RandomPossibleReagent()); + + if (Utility.RandomDouble() < 0.2) + PackItem(new BolaBall()); } - ); - PackItem(new RingmailChest()); + public OrcishLord(Serial serial) : base(serial) + { + } - if (Utility.RandomDouble() < 0.3) - PackItem(Loot.RandomPossibleReagent()); + public override string CorpseName => "an orcish corpse"; + public override InhumanSpeech SpeechType => InhumanSpeech.Orc; - if (Utility.RandomDouble() < 0.2) - PackItem(new BolaBall()); + public override string DefaultName => "an orcish lord"; + + public override bool CanRummageCorpses => true; + public override int TreasureMapLevel => 1; + public override int Meat => 1; + + public override OppositionGroup OppositionGroup => OppositionGroup.SavagesAndOrcs; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + AddLoot(LootPack.Average); + // TODO: evil orc helm + } + + public override bool IsEnemy(Mobile m) + { + if (m.Player && m.FindItemOnLayer(Layer.Helm) is OrcishKinMask) + return false; + + return base.IsEnemy(m); + } + + public override void AggressiveAction(Mobile aggressor, bool criminal) + { + base.AggressiveAction(aggressor, criminal); + + var item = aggressor.FindItemOnLayer(Layer.Helm); + + if (item is OrcishKinMask) + { + AOS.Damage(aggressor, 50, 0, 100, 0, 0, 0); + item.Delete(); + aggressor.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); + aggressor.PlaySound(0x307); + } + } + + 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(); + } } - - public OrcishLord(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an orcish corpse"; - public override InhumanSpeech SpeechType => InhumanSpeech.Orc; - - public override string DefaultName => "an orcish lord"; - - public override bool CanRummageCorpses => true; - public override int TreasureMapLevel => 1; - public override int Meat => 1; - - public override OppositionGroup OppositionGroup => OppositionGroup.SavagesAndOrcs; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - AddLoot(LootPack.Average); - // TODO: evil orc helm - } - - public override bool IsEnemy(Mobile m) - { - if (m.Player && m.FindItemOnLayer(Layer.Helm) is OrcishKinMask) - return false; - - return base.IsEnemy(m); - } - - public override void AggressiveAction(Mobile aggressor, bool criminal) - { - base.AggressiveAction(aggressor, criminal); - - Item item = aggressor.FindItemOnLayer(Layer.Helm); - - if (item is OrcishKinMask) - { - AOS.Damage(aggressor, 50, 0, 100, 0, 0, 0); - item.Delete(); - aggressor.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); - aggressor.PlaySound(0x307); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Ratman.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Ratman.cs index 493a16073..9bac39e79 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Ratman.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Ratman.cs @@ -2,68 +2,68 @@ using Server.Misc; namespace Server.Mobiles { - public class Ratman : BaseCreature - { - [Constructible] - public Ratman() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Ratman : BaseCreature { - Name = NameList.RandomName("ratman"); - Body = 42; - BaseSoundID = 437; + [Constructible] + public Ratman() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Name = NameList.RandomName("ratman"); + Body = 42; + BaseSoundID = 437; - SetStr(96, 120); - SetDex(81, 100); - SetInt(36, 60); + SetStr(96, 120); + SetDex(81, 100); + SetInt(36, 60); - SetHits(58, 72); + SetHits(58, 72); - SetDamage(4, 5); + SetDamage(4, 5); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 25, 30); - SetResistance(ResistanceType.Fire, 10, 20); - SetResistance(ResistanceType.Cold, 10, 20); - SetResistance(ResistanceType.Poison, 10, 20); - SetResistance(ResistanceType.Energy, 10, 20); + SetResistance(ResistanceType.Physical, 25, 30); + SetResistance(ResistanceType.Fire, 10, 20); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Energy, 10, 20); - SetSkill(SkillName.MagicResist, 35.1, 60.0); - SetSkill(SkillName.Tactics, 50.1, 75.0); - SetSkill(SkillName.Wrestling, 50.1, 75.0); + SetSkill(SkillName.MagicResist, 35.1, 60.0); + SetSkill(SkillName.Tactics, 50.1, 75.0); + SetSkill(SkillName.Wrestling, 50.1, 75.0); - Fame = 1500; - Karma = -1500; + Fame = 1500; + Karma = -1500; - VirtualArmor = 28; + VirtualArmor = 28; + } + + public Ratman(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a ratman's corpse"; + public override InhumanSpeech SpeechType => InhumanSpeech.Ratman; + + public override bool CanRummageCorpses => true; + public override int Hides => 8; + public override HideType HideType => HideType.Spined; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + // TODO: weapon, misc + } + + 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(); + } } - - public Ratman(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a ratman's corpse"; - public override InhumanSpeech SpeechType => InhumanSpeech.Ratman; - - public override bool CanRummageCorpses => true; - public override int Hides => 8; - public override HideType HideType => HideType.Spined; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - // TODO: weapon, misc - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/RatmanArcher.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/RatmanArcher.cs index fecd789d5..b8ac7f09c 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/RatmanArcher.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/RatmanArcher.cs @@ -3,78 +3,78 @@ using Server.Misc; namespace Server.Mobiles { - public class RatmanArcher : BaseCreature - { - [Constructible] - public RatmanArcher() : base(AIType.AI_Archer, FightMode.Closest, 10, 1, 0.2, 0.4) + public class RatmanArcher : BaseCreature { - Name = NameList.RandomName("ratman"); - Body = 0x8E; - BaseSoundID = 437; + [Constructible] + public RatmanArcher() : base(AIType.AI_Archer, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Name = NameList.RandomName("ratman"); + Body = 0x8E; + BaseSoundID = 437; - SetStr(146, 180); - SetDex(101, 130); - SetInt(116, 140); + SetStr(146, 180); + SetDex(101, 130); + SetInt(116, 140); - SetHits(88, 108); + SetHits(88, 108); - SetDamage(4, 10); + SetDamage(4, 10); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 40, 55); - SetResistance(ResistanceType.Fire, 10, 20); - SetResistance(ResistanceType.Cold, 10, 20); - SetResistance(ResistanceType.Poison, 10, 20); - SetResistance(ResistanceType.Energy, 10, 20); + SetResistance(ResistanceType.Physical, 40, 55); + SetResistance(ResistanceType.Fire, 10, 20); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Energy, 10, 20); - SetSkill(SkillName.Anatomy, 60.2, 100.0); - SetSkill(SkillName.Archery, 80.1, 90.0); - SetSkill(SkillName.MagicResist, 65.1, 90.0); - SetSkill(SkillName.Tactics, 50.1, 75.0); - SetSkill(SkillName.Wrestling, 50.1, 75.0); + SetSkill(SkillName.Anatomy, 60.2, 100.0); + SetSkill(SkillName.Archery, 80.1, 90.0); + SetSkill(SkillName.MagicResist, 65.1, 90.0); + SetSkill(SkillName.Tactics, 50.1, 75.0); + SetSkill(SkillName.Wrestling, 50.1, 75.0); - Fame = 6500; - Karma = -6500; + Fame = 6500; + Karma = -6500; - VirtualArmor = 56; + VirtualArmor = 56; - AddItem(new Bow()); - PackItem(new Arrow(Utility.RandomMinMax(50, 70))); + AddItem(new Bow()); + PackItem(new Arrow(Utility.RandomMinMax(50, 70))); + } + + public RatmanArcher(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a ratman archer corpse"; + public override InhumanSpeech SpeechType => InhumanSpeech.Ratman; + + public override bool CanRummageCorpses => true; + public override int Hides => 8; + public override HideType HideType => HideType.Spined; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + } + + 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 (Body == 42) + { + Body = 0x8E; + Hue = 0; + } + } } - - public RatmanArcher(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a ratman archer corpse"; - public override InhumanSpeech SpeechType => InhumanSpeech.Ratman; - - public override bool CanRummageCorpses => true; - public override int Hides => 8; - public override HideType HideType => HideType.Spined; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (Body == 42) - { - Body = 0x8E; - Hue = 0; - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/RestlessSoul.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/RestlessSoul.cs index 04ad09abd..38296fd86 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/RestlessSoul.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/RestlessSoul.cs @@ -1,101 +1,101 @@ using System.Collections.Generic; using Server.ContextMenus; -using Server.Engines.Quests; using Server.Engines.Quests.Haven; namespace Server.Mobiles { - public class RestlessSoul : BaseCreature - { - [Constructible] - public RestlessSoul() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.4, 0.8) + public class RestlessSoul : BaseCreature { - Body = 0x3CA; - Hue = 0x453; + [Constructible] + public RestlessSoul() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.4, 0.8) + { + Body = 0x3CA; + Hue = 0x453; - SetStr(26, 40); - SetDex(26, 40); - SetInt(26, 40); + SetStr(26, 40); + SetDex(26, 40); + SetInt(26, 40); - SetHits(16, 24); + SetHits(16, 24); - SetDamage(1, 10); + SetDamage(1, 10); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 15, 25); - SetResistance(ResistanceType.Fire, 5, 15); - SetResistance(ResistanceType.Cold, 25, 40); - SetResistance(ResistanceType.Poison, 5, 10); - SetResistance(ResistanceType.Energy, 10, 20); + SetResistance(ResistanceType.Physical, 15, 25); + SetResistance(ResistanceType.Fire, 5, 15); + SetResistance(ResistanceType.Cold, 25, 40); + SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Energy, 10, 20); - SetSkill(SkillName.MagicResist, 20.1, 30.0); - SetSkill(SkillName.Swords, 20.1, 30.0); - SetSkill(SkillName.Tactics, 20.1, 30.0); - SetSkill(SkillName.Wrestling, 20.1, 30.0); + SetSkill(SkillName.MagicResist, 20.1, 30.0); + SetSkill(SkillName.Swords, 20.1, 30.0); + SetSkill(SkillName.Tactics, 20.1, 30.0); + SetSkill(SkillName.Wrestling, 20.1, 30.0); - Fame = 500; - Karma = -500; + Fame = 500; + Karma = -500; - VirtualArmor = 6; + VirtualArmor = 6; + } + + public RestlessSoul(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a ghostly corpse"; + public override string DefaultName => "a restless soul"; + + public override bool AlwaysAttackable => true; + public override bool BleedImmune => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.Poor); + } + + public override void DisplayPaperdollTo(Mobile to) + { + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + for (var i = 0; i < list.Count; ++i) + if (list[i] is PaperdollEntry) + list.RemoveAt(i--); + } + + public override int GetIdleSound() => 0x107; + + public override int GetAngerSound() => 0x1BF; + + public override int GetDeathSound() => 0xFD; + + public override bool IsEnemy(Mobile m) + { + if (m is PlayerMobile player && Map == Map.Trammel && X >= 5199 && X <= 5271 && Y >= 1812 && Y <= 1865 + ) // Schmendrick's cave + { + var qs = player.Quest; + + if (qs is UzeraanTurmoilQuest && qs.IsObjectiveInProgress(typeof(FindSchmendrickObjective))) return false; + } + + return base.IsEnemy(m); + } + + 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(); + } } - - public RestlessSoul(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a ghostly corpse"; - public override string DefaultName => "a restless soul"; - - public override bool AlwaysAttackable => true; - public override bool BleedImmune => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.Poor); - } - - public override void DisplayPaperdollTo(Mobile to) - { - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - for (int i = 0; i < list.Count; ++i) - if (list[i] is PaperdollEntry) - list.RemoveAt(i--); - } - - public override int GetIdleSound() => 0x107; - - public override int GetAngerSound() => 0x1BF; - - public override int GetDeathSound() => 0xFD; - - public override bool IsEnemy(Mobile m) - { - if (m is PlayerMobile player && Map == Map.Trammel && X >= 5199 && X <= 5271 && Y >= 1812 && Y <= 1865) // Schmendrick's cave - { - QuestSystem qs = player.Quest; - - if (qs is UzeraanTurmoilQuest && qs.IsObjectiveInProgress(typeof(FindSchmendrickObjective))) return false; - } - - return base.IsEnemy(m); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/RottingCorpse.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/RottingCorpse.cs index d3519daf5..48dc7bfe4 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/RottingCorpse.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/RottingCorpse.cs @@ -1,73 +1,73 @@ namespace Server.Mobiles { - public class RottingCorpse : BaseCreature - { - [Constructible] - public RottingCorpse() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class RottingCorpse : BaseCreature { - Body = 155; - BaseSoundID = 471; + [Constructible] + public RottingCorpse() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 155; + BaseSoundID = 471; - SetStr(301, 350); - SetDex(75); - SetInt(151, 200); + SetStr(301, 350); + SetDex(75); + SetInt(151, 200); - SetHits(1200); - SetStam(150); - SetMana(0); + SetHits(1200); + SetStam(150); + SetMana(0); - SetDamage(8, 10); + SetDamage(8, 10); - SetDamageType(ResistanceType.Physical, 0); - SetDamageType(ResistanceType.Cold, 50); - SetDamageType(ResistanceType.Poison, 50); + SetDamageType(ResistanceType.Physical, 0); + SetDamageType(ResistanceType.Cold, 50); + SetDamageType(ResistanceType.Poison, 50); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 50, 70); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 20, 30); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 50, 70); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 20, 30); - SetSkill(SkillName.Poisoning, 120.0); - SetSkill(SkillName.MagicResist, 250.0); - SetSkill(SkillName.Tactics, 100.0); - SetSkill(SkillName.Wrestling, 90.1, 100.0); + SetSkill(SkillName.Poisoning, 120.0); + SetSkill(SkillName.MagicResist, 250.0); + SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.Wrestling, 90.1, 100.0); - Fame = 6000; - Karma = -6000; + Fame = 6000; + Karma = -6000; - VirtualArmor = 40; + VirtualArmor = 40; + } + + public RottingCorpse(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a rotting corpse"; + public override string DefaultName => "a rotting corpse"; + + public override bool BleedImmune => true; + public override Poison PoisonImmune => Poison.Lethal; + public override Poison HitPoison => Poison.Lethal; + public override int TreasureMapLevel => 5; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 2); + } + + 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(); + } } - - public RottingCorpse(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a rotting corpse"; - public override string DefaultName => "a rotting corpse"; - - public override bool BleedImmune => true; - public override Poison PoisonImmune => Poison.Lethal; - public override Poison HitPoison => Poison.Lethal; - public override int TreasureMapLevel => 5; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Savage.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Savage.cs index c7c80d53a..79049d39a 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Savage.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Savage.cs @@ -3,113 +3,113 @@ using Server.Items; namespace Server.Mobiles { - public class Savage : BaseCreature - { - [Constructible] - public Savage() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Savage : BaseCreature { - Name = NameList.RandomName("savage"); + [Constructible] + public Savage() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Name = NameList.RandomName("savage"); - if (Female = Utility.RandomBool()) - Body = 184; - else - Body = 183; + if (Female = Utility.RandomBool()) + Body = 184; + else + Body = 183; - SetStr(96, 115); - SetDex(86, 105); - SetInt(51, 65); + SetStr(96, 115); + SetDex(86, 105); + SetInt(51, 65); - SetDamage(23, 27); + SetDamage(23, 27); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetSkill(SkillName.Fencing, 60.0, 82.5); - SetSkill(SkillName.Macing, 60.0, 82.5); - SetSkill(SkillName.Poisoning, 60.0, 82.5); - SetSkill(SkillName.MagicResist, 57.5, 80.0); - SetSkill(SkillName.Swords, 60.0, 82.5); - SetSkill(SkillName.Tactics, 60.0, 82.5); + SetSkill(SkillName.Fencing, 60.0, 82.5); + SetSkill(SkillName.Macing, 60.0, 82.5); + SetSkill(SkillName.Poisoning, 60.0, 82.5); + SetSkill(SkillName.MagicResist, 57.5, 80.0); + SetSkill(SkillName.Swords, 60.0, 82.5); + SetSkill(SkillName.Tactics, 60.0, 82.5); - Fame = 1000; - Karma = -1000; + Fame = 1000; + Karma = -1000; - PackItem(new Bandage(Utility.RandomMinMax(1, 15))); + PackItem(new Bandage(Utility.RandomMinMax(1, 15))); - if (Female && Utility.RandomDouble() < 0.1) - PackItem(new TribalBerry()); - else if (!Female && Utility.RandomDouble() < 0.1) - PackItem(new BolaBall()); + if (Female && Utility.RandomDouble() < 0.1) + PackItem(new TribalBerry()); + else if (!Female && Utility.RandomDouble() < 0.1) + PackItem(new BolaBall()); - AddItem(new Spear()); - AddItem(new BoneArms()); - AddItem(new BoneLegs()); + AddItem(new Spear()); + AddItem(new BoneArms()); + AddItem(new BoneLegs()); - if (Utility.RandomDouble() < 0.5) - AddItem(new SavageMask()); - else if (Utility.RandomDouble() < 0.1) - AddItem(new OrcishKinMask()); + if (Utility.RandomDouble() < 0.5) + AddItem(new SavageMask()); + else if (Utility.RandomDouble() < 0.1) + AddItem(new OrcishKinMask()); + } + + public Savage(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a savage corpse"; + + public override int Meat => 1; + public override bool AlwaysMurderer => true; + public override bool ShowFameTitle => false; + + public override OppositionGroup OppositionGroup => OppositionGroup.SavagesAndOrcs; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + public override bool IsEnemy(Mobile m) + { + if (m.BodyMod == 183 || m.BodyMod == 184) + return false; + + return base.IsEnemy(m); + } + + public override void AggressiveAction(Mobile aggressor, bool criminal) + { + base.AggressiveAction(aggressor, criminal); + + if (aggressor.BodyMod == 183 || aggressor.BodyMod == 184) + { + AOS.Damage(aggressor, 50, 0, 100, 0, 0, 0); + aggressor.BodyMod = 0; + aggressor.HueMod = -1; + aggressor.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); + aggressor.PlaySound(0x307); + aggressor.SendLocalizedMessage(1040008); // Your skin is scorched as the tribal paint burns away! + + if (aggressor is PlayerMobile mobile) + mobile.SavagePaintExpiration = TimeSpan.Zero; + } + } + + public override void AlterMeleeDamageTo(Mobile to, ref int damage) + { + if (to is Dragon || to is WhiteWyrm || to is SwampDragon || to is Drake || to is Nightmare || to is Hiryu || + to is LesserHiryu || to is Daemon) + damage *= 3; + } + + 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(); + } } - - public Savage(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a savage corpse"; - - public override int Meat => 1; - public override bool AlwaysMurderer => true; - public override bool ShowFameTitle => false; - - public override OppositionGroup OppositionGroup => OppositionGroup.SavagesAndOrcs; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } - - public override bool IsEnemy(Mobile m) - { - if (m.BodyMod == 183 || m.BodyMod == 184) - return false; - - return base.IsEnemy(m); - } - - public override void AggressiveAction(Mobile aggressor, bool criminal) - { - base.AggressiveAction(aggressor, criminal); - - if (aggressor.BodyMod == 183 || aggressor.BodyMod == 184) - { - AOS.Damage(aggressor, 50, 0, 100, 0, 0, 0); - aggressor.BodyMod = 0; - aggressor.HueMod = -1; - aggressor.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); - aggressor.PlaySound(0x307); - aggressor.SendLocalizedMessage(1040008); // Your skin is scorched as the tribal paint burns away! - - if (aggressor is PlayerMobile mobile) - mobile.SavagePaintExpiration = TimeSpan.Zero; - } - } - - public override void AlterMeleeDamageTo(Mobile to, ref int damage) - { - if (to is Dragon || to is WhiteWyrm || to is SwampDragon || to is Drake || to is Nightmare || to is Hiryu || - to is LesserHiryu || to is Daemon) - damage *= 3; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/SavageRider.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/SavageRider.cs index 996ad21f6..a8ebb8a0c 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/SavageRider.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/SavageRider.cs @@ -3,123 +3,123 @@ using Server.Items; namespace Server.Mobiles { - public class SavageRider : BaseCreature - { - [Constructible] - public SavageRider() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.15, 0.4) + public class SavageRider : BaseCreature { - Name = NameList.RandomName("savage rider"); + [Constructible] + public SavageRider() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.15, 0.4) + { + Name = NameList.RandomName("savage rider"); - if (Female = Utility.RandomBool()) - Body = 186; - else - Body = 185; + if (Female = Utility.RandomBool()) + Body = 186; + else + Body = 185; - SetStr(151, 170); - SetDex(92, 130); - SetInt(51, 65); + SetStr(151, 170); + SetDex(92, 130); + SetInt(51, 65); - SetDamage(29, 34); + SetDamage(29, 34); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetSkill(SkillName.Fencing, 72.5, 95.0); - SetSkill(SkillName.Healing, 60.3, 90.0); - SetSkill(SkillName.Macing, 72.5, 95.0); - SetSkill(SkillName.Poisoning, 60.0, 82.5); - SetSkill(SkillName.MagicResist, 72.5, 95.0); - SetSkill(SkillName.Swords, 72.5, 95.0); - SetSkill(SkillName.Tactics, 72.5, 95.0); + SetSkill(SkillName.Fencing, 72.5, 95.0); + SetSkill(SkillName.Healing, 60.3, 90.0); + SetSkill(SkillName.Macing, 72.5, 95.0); + SetSkill(SkillName.Poisoning, 60.0, 82.5); + SetSkill(SkillName.MagicResist, 72.5, 95.0); + SetSkill(SkillName.Swords, 72.5, 95.0); + SetSkill(SkillName.Tactics, 72.5, 95.0); - Fame = 1000; - Karma = -1000; + Fame = 1000; + Karma = -1000; - PackItem(new Bandage(Utility.RandomMinMax(1, 15))); + PackItem(new Bandage(Utility.RandomMinMax(1, 15))); - if (Utility.RandomDouble() < 0.1) - PackItem(new BolaBall()); + if (Utility.RandomDouble() < 0.1) + PackItem(new BolaBall()); - AddItem(new TribalSpear()); - AddItem(new BoneArms()); - AddItem(new BoneLegs()); - // TODO: BEAR MASK + AddItem(new TribalSpear()); + AddItem(new BoneArms()); + AddItem(new BoneLegs()); + // TODO: BEAR MASK - new SavageRidgeback().Rider = this; + new SavageRidgeback().Rider = this; + } + + public SavageRider(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a savage corpse"; + + public override int Meat => 1; + public override bool AlwaysMurderer => true; + public override bool ShowFameTitle => false; + + public override OppositionGroup OppositionGroup => OppositionGroup.SavagesAndOrcs; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + } + + public override bool OnBeforeDeath() + { + var mount = Mount; + + if (mount != null) + mount.Rider = null; + + if (mount is Mobile mobile) + mobile.Delete(); + + return base.OnBeforeDeath(); + } + + public override bool IsEnemy(Mobile m) + { + if (m.BodyMod == 183 || m.BodyMod == 184) + return false; + + return base.IsEnemy(m); + } + + public override void AggressiveAction(Mobile aggressor, bool criminal) + { + base.AggressiveAction(aggressor, criminal); + + if (aggressor.BodyMod == 183 || aggressor.BodyMod == 184) + { + AOS.Damage(aggressor, 50, 0, 100, 0, 0, 0); + aggressor.BodyMod = 0; + aggressor.HueMod = -1; + aggressor.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); + aggressor.PlaySound(0x307); + aggressor.SendLocalizedMessage(1040008); // Your skin is scorched as the tribal paint burns away! + + if (aggressor is PlayerMobile mobile) + mobile.SavagePaintExpiration = TimeSpan.Zero; + } + } + + public override void AlterMeleeDamageTo(Mobile to, ref int damage) + { + if (to is Dragon || to is WhiteWyrm || to is SwampDragon || to is Drake || to is Nightmare || to is Hiryu || + to is LesserHiryu || to is Daemon) + damage *= 3; + } + + 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(); + } } - - public SavageRider(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a savage corpse"; - - public override int Meat => 1; - public override bool AlwaysMurderer => true; - public override bool ShowFameTitle => false; - - public override OppositionGroup OppositionGroup => OppositionGroup.SavagesAndOrcs; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - } - - public override bool OnBeforeDeath() - { - IMount mount = Mount; - - if (mount != null) - mount.Rider = null; - - if (mount is Mobile mobile) - mobile.Delete(); - - return base.OnBeforeDeath(); - } - - public override bool IsEnemy(Mobile m) - { - if (m.BodyMod == 183 || m.BodyMod == 184) - return false; - - return base.IsEnemy(m); - } - - public override void AggressiveAction(Mobile aggressor, bool criminal) - { - base.AggressiveAction(aggressor, criminal); - - if (aggressor.BodyMod == 183 || aggressor.BodyMod == 184) - { - AOS.Damage(aggressor, 50, 0, 100, 0, 0, 0); - aggressor.BodyMod = 0; - aggressor.HueMod = -1; - aggressor.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); - aggressor.PlaySound(0x307); - aggressor.SendLocalizedMessage(1040008); // Your skin is scorched as the tribal paint burns away! - - if (aggressor is PlayerMobile mobile) - mobile.SavagePaintExpiration = TimeSpan.Zero; - } - } - - public override void AlterMeleeDamageTo(Mobile to, ref int damage) - { - if (to is Dragon || to is WhiteWyrm || to is SwampDragon || to is Drake || to is Nightmare || to is Hiryu || - to is LesserHiryu || to is Daemon) - damage *= 3; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/ShadowFiend.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/ShadowFiend.cs index fb0f2c29e..25be8c22f 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/ShadowFiend.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/ShadowFiend.cs @@ -3,124 +3,124 @@ using Server.Items; namespace Server.Mobiles { - public class ShadowFiend : BaseCreature - { - private UnhideTimer m_Timer; - - [Constructible] - public ShadowFiend() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class ShadowFiend : BaseCreature { - Body = 0xA8; + private UnhideTimer m_Timer; - // this to allow shadow fiend to loot from corpses - Backpack backpack = new Backpack(); - backpack.Movable = false; - AddItem(backpack); - - SetStr(46, 55); - SetDex(121, 130); - SetInt(46, 55); - - SetHits(28, 33); - SetStam(46, 55); - - SetDamage(10, 22); - - SetDamageType(ResistanceType.Physical, 20); - SetDamageType(ResistanceType.Cold, 80); - - SetResistance(ResistanceType.Physical, 20, 25); - SetResistance(ResistanceType.Fire, 20, 25); - SetResistance(ResistanceType.Cold, 40, 45); - SetResistance(ResistanceType.Poison, 60, 70); - SetResistance(ResistanceType.Energy, 5, 10); - - SetSkill(SkillName.MagicResist, 20.1, 30.0); - SetSkill(SkillName.Tactics, 20.1, 30.0); - SetSkill(SkillName.Wrestling, 20.1, 30.0); - - Fame = 1000; - Karma = -1000; - - m_Timer = new UnhideTimer(this); - m_Timer.Start(); - } - - public ShadowFiend(Serial serial) : base(serial) - { - } - - public override bool DeleteCorpseOnDeath => true; - - public override string DefaultName => "a shadow fiend"; - - public override bool CanRummageCorpses => true; - - public override int GetIdleSound() => 0x37A; - - public override int GetAngerSound() => 0x379; - - public override int GetDeathSound() => 0x381; - - public override int GetAttackSound() => 0x37F; - - public override int GetHurtSound() => 0x380; - - public override bool OnBeforeDeath() - { - Backpack?.Destroy(); - - Effects.SendLocationEffect(Location, Map, 0x376A, 10, 1); - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - m_Timer = new UnhideTimer(this); - m_Timer.Start(); - } - - public override void OnAfterDelete() - { - m_Timer?.Stop(); - - m_Timer = null; - - base.OnAfterDelete(); - } - - private class UnhideTimer : Timer - { - private readonly ShadowFiend m_Owner; - - public UnhideTimer(ShadowFiend owner) : base(TimeSpan.FromSeconds(30.0)) - { - m_Owner = owner; - Priority = TimerPriority.OneSecond; - } - - protected override void OnTick() - { - if (m_Owner.Deleted) + [Constructible] + public ShadowFiend() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) { - Stop(); - return; + Body = 0xA8; + + // this to allow shadow fiend to loot from corpses + var backpack = new Backpack(); + backpack.Movable = false; + AddItem(backpack); + + SetStr(46, 55); + SetDex(121, 130); + SetInt(46, 55); + + SetHits(28, 33); + SetStam(46, 55); + + SetDamage(10, 22); + + SetDamageType(ResistanceType.Physical, 20); + SetDamageType(ResistanceType.Cold, 80); + + SetResistance(ResistanceType.Physical, 20, 25); + SetResistance(ResistanceType.Fire, 20, 25); + SetResistance(ResistanceType.Cold, 40, 45); + SetResistance(ResistanceType.Poison, 60, 70); + SetResistance(ResistanceType.Energy, 5, 10); + + SetSkill(SkillName.MagicResist, 20.1, 30.0); + SetSkill(SkillName.Tactics, 20.1, 30.0); + SetSkill(SkillName.Wrestling, 20.1, 30.0); + + Fame = 1000; + Karma = -1000; + + m_Timer = new UnhideTimer(this); + m_Timer.Start(); } - foreach (Mobile m in m_Owner.GetMobilesInRange(3)) - if (m != m_Owner && m.Player && m.Hidden && m_Owner.CanBeHarmful(m) && - m.AccessLevel == AccessLevel.Player) - m.Hidden = false; - } + public ShadowFiend(Serial serial) : base(serial) + { + } + + public override bool DeleteCorpseOnDeath => true; + + public override string DefaultName => "a shadow fiend"; + + public override bool CanRummageCorpses => true; + + public override int GetIdleSound() => 0x37A; + + public override int GetAngerSound() => 0x379; + + public override int GetDeathSound() => 0x381; + + public override int GetAttackSound() => 0x37F; + + public override int GetHurtSound() => 0x380; + + public override bool OnBeforeDeath() + { + Backpack?.Destroy(); + + Effects.SendLocationEffect(Location, Map, 0x376A, 10, 1); + return true; + } + + 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(); + + m_Timer = new UnhideTimer(this); + m_Timer.Start(); + } + + public override void OnAfterDelete() + { + m_Timer?.Stop(); + + m_Timer = null; + + base.OnAfterDelete(); + } + + private class UnhideTimer : Timer + { + private readonly ShadowFiend m_Owner; + + public UnhideTimer(ShadowFiend owner) : base(TimeSpan.FromSeconds(30.0)) + { + m_Owner = owner; + Priority = TimerPriority.OneSecond; + } + + protected override void OnTick() + { + if (m_Owner.Deleted) + { + Stop(); + return; + } + + foreach (var m in m_Owner.GetMobilesInRange(3)) + if (m != m_Owner && m.Player && m.Hidden && m_Owner.CanBeHarmful(m) && + m.AccessLevel == AccessLevel.Player) + m.Hidden = false; + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/SkeletalKnight.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/SkeletalKnight.cs index 3baa0492d..0d3fe161e 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/SkeletalKnight.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/SkeletalKnight.cs @@ -2,93 +2,93 @@ using Server.Items; namespace Server.Mobiles { - public class SkeletalKnight : BaseCreature - { - [Constructible] - public SkeletalKnight() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class SkeletalKnight : BaseCreature { - Body = 147; - BaseSoundID = 451; + [Constructible] + public SkeletalKnight() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 147; + BaseSoundID = 451; - SetStr(196, 250); - SetDex(76, 95); - SetInt(36, 60); + SetStr(196, 250); + SetDex(76, 95); + SetInt(36, 60); - SetHits(118, 150); + SetHits(118, 150); - SetDamage(8, 18); + SetDamage(8, 18); - SetDamageType(ResistanceType.Physical, 40); - SetDamageType(ResistanceType.Cold, 60); + SetDamageType(ResistanceType.Physical, 40); + SetDamageType(ResistanceType.Cold, 60); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.MagicResist, 65.1, 80.0); - SetSkill(SkillName.Tactics, 85.1, 100.0); - SetSkill(SkillName.Wrestling, 85.1, 95.0); + SetSkill(SkillName.MagicResist, 65.1, 80.0); + SetSkill(SkillName.Tactics, 85.1, 100.0); + SetSkill(SkillName.Wrestling, 85.1, 95.0); - Fame = 3000; - Karma = -3000; + Fame = 3000; + Karma = -3000; - VirtualArmor = 40; + VirtualArmor = 40; - switch (Utility.Random(6)) - { - case 0: - PackItem(new PlateArms()); - break; - case 1: - PackItem(new PlateChest()); - break; - case 2: - PackItem(new PlateGloves()); - break; - case 3: - PackItem(new PlateGorget()); - break; - case 4: - PackItem(new PlateLegs()); - break; - case 5: - PackItem(new PlateHelm()); - break; - } + switch (Utility.Random(6)) + { + case 0: + PackItem(new PlateArms()); + break; + case 1: + PackItem(new PlateChest()); + break; + case 2: + PackItem(new PlateGloves()); + break; + case 3: + PackItem(new PlateGorget()); + break; + case 4: + PackItem(new PlateLegs()); + break; + case 5: + PackItem(new PlateHelm()); + break; + } - PackItem(new Scimitar()); - PackItem(new WoodenShield()); + PackItem(new Scimitar()); + PackItem(new WoodenShield()); + } + + public SkeletalKnight(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a skeletal corpse"; + public override string DefaultName => "a skeletal knight"; + + public override bool BleedImmune => true; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Meager); + } + + 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(); + } } - - public SkeletalKnight(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a skeletal corpse"; - public override string DefaultName => "a skeletal knight"; - - public override bool BleedImmune => true; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Skeleton.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Skeleton.cs index 7c011cd04..b1df50d4c 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Skeleton.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Skeleton.cs @@ -2,86 +2,86 @@ using Server.Items; namespace Server.Mobiles { - public class Skeleton : BaseCreature - { - [Constructible] - public Skeleton() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Skeleton : BaseCreature { - Body = Utility.RandomList(50, 56); - BaseSoundID = 0x48D; + [Constructible] + public Skeleton() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = Utility.RandomList(50, 56); + BaseSoundID = 0x48D; - SetStr(56, 80); - SetDex(56, 75); - SetInt(16, 40); + SetStr(56, 80); + SetDex(56, 75); + SetInt(16, 40); - SetHits(34, 48); + SetHits(34, 48); - SetDamage(3, 7); + SetDamage(3, 7); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 15, 20); - SetResistance(ResistanceType.Fire, 5, 10); - SetResistance(ResistanceType.Cold, 25, 40); - SetResistance(ResistanceType.Poison, 25, 35); - SetResistance(ResistanceType.Energy, 5, 15); + SetResistance(ResistanceType.Physical, 15, 20); + SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Cold, 25, 40); + SetResistance(ResistanceType.Poison, 25, 35); + SetResistance(ResistanceType.Energy, 5, 15); - SetSkill(SkillName.MagicResist, 45.1, 60.0); - SetSkill(SkillName.Tactics, 45.1, 60.0); - SetSkill(SkillName.Wrestling, 45.1, 55.0); + SetSkill(SkillName.MagicResist, 45.1, 60.0); + SetSkill(SkillName.Tactics, 45.1, 60.0); + SetSkill(SkillName.Wrestling, 45.1, 55.0); - Fame = 450; - Karma = -450; + Fame = 450; + Karma = -450; - VirtualArmor = 16; + VirtualArmor = 16; - switch (Utility.Random(5)) - { - case 0: - PackItem(new BoneArms()); - break; - case 1: - PackItem(new BoneChest()); - break; - case 2: - PackItem(new BoneGloves()); - break; - case 3: - PackItem(new BoneLegs()); - break; - case 4: - PackItem(new BoneHelm()); - break; - } + switch (Utility.Random(5)) + { + case 0: + PackItem(new BoneArms()); + break; + case 1: + PackItem(new BoneChest()); + break; + case 2: + PackItem(new BoneGloves()); + break; + case 3: + PackItem(new BoneLegs()); + break; + case 4: + PackItem(new BoneHelm()); + break; + } + } + + public Skeleton(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a skeletal corpse"; + public override string DefaultName => "a skeleton"; + + public override bool BleedImmune => true; + public override Poison PoisonImmune => Poison.Lesser; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override void GenerateLoot() + { + AddLoot(LootPack.Poor); + } + + 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(); + } } - - public Skeleton(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a skeletal corpse"; - public override string DefaultName => "a skeleton"; - - public override bool BleedImmune => true; - public override Poison PoisonImmune => Poison.Lesser; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override void GenerateLoot() - { - AddLoot(LootPack.Poor); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/SpawnedOrcishLord.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/SpawnedOrcishLord.cs index 429ff4e6f..333d8d13d 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/SpawnedOrcishLord.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/SpawnedOrcishLord.cs @@ -2,42 +2,42 @@ using Server.Items; namespace Server.Mobiles { - public class SpawnedOrcishLord : OrcishLord - { - [Constructible] - public SpawnedOrcishLord() + public class SpawnedOrcishLord : OrcishLord { - Container pack = Backpack; + [Constructible] + public SpawnedOrcishLord() + { + var pack = Backpack; - pack?.Delete(); + pack?.Delete(); - NoKillAwards = true; + NoKillAwards = true; + } + + public SpawnedOrcishLord(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an orcish corpse"; + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + c.Delete(); + } + + 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(); + NoKillAwards = true; + } } - - public SpawnedOrcishLord(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an orcish corpse"; - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - c.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - NoKillAwards = true; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/SpectralArmour.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/SpectralArmour.cs index 5b20aee41..3b151c88c 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/SpectralArmour.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/SpectralArmour.cs @@ -2,81 +2,81 @@ using Server.Items; namespace Server.Mobiles { - public class SpectralArmour : BaseCreature - { - [Constructible] - public SpectralArmour() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class SpectralArmour : BaseCreature { - Body = 637; - Hue = 0x8026; + [Constructible] + public SpectralArmour() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 637; + Hue = 0x8026; - AddItem(new Buckler{Movable = false, Hue = 0x835}); - AddItem(new ChainCoif{Hue = 0x835}); - AddItem(new PlateGloves{Hue = 0x835}); + AddItem(new Buckler { Movable = false, Hue = 0x835 }); + AddItem(new ChainCoif { Hue = 0x835 }); + AddItem(new PlateGloves { Hue = 0x835 }); - SetStr(101, 110); - SetDex(101, 110); - SetInt(101, 110); + SetStr(101, 110); + SetDex(101, 110); + SetInt(101, 110); - SetHits(178, 201); - SetStam(191, 200); + SetHits(178, 201); + SetStam(191, 200); - SetDamage(10, 22); + SetDamage(10, 22); - SetDamageType(ResistanceType.Physical, 75); - SetDamageType(ResistanceType.Cold, 25); + SetDamageType(ResistanceType.Physical, 75); + SetDamageType(ResistanceType.Cold, 25); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 20, 30); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 20, 30); - SetSkill(SkillName.Wrestling, 75.1, 100.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 90.1, 100); + SetSkill(SkillName.Wrestling, 75.1, 100.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 90.1, 100); - VirtualArmor = 40; - Fame = 7000; - Karma = -7000; + VirtualArmor = 40; + Fame = 7000; + Karma = -7000; + } + + public SpectralArmour(Serial serial) : base(serial) + { + } + + public override bool DeleteCorpseOnDeath => true; + + public override string DefaultName => "a spectral armour"; + + public override Poison PoisonImmune => Poison.Regular; + + public override int GetIdleSound() => 0x200; + + public override int GetAngerSound() => 0x56; + + public override bool OnBeforeDeath() + { + if (!base.OnBeforeDeath()) + return false; + + var gold = new Gold(Utility.RandomMinMax(240, 375)); + gold.MoveToWorld(Location, Map); + + Effects.SendLocationEffect(Location, Map, 0x376A, 10, 1); + return true; + } + + 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(); + } } - - public SpectralArmour(Serial serial) : base(serial) - { - } - - public override bool DeleteCorpseOnDeath => true; - - public override string DefaultName => "a spectral armour"; - - public override Poison PoisonImmune => Poison.Regular; - - public override int GetIdleSound() => 0x200; - - public override int GetAngerSound() => 0x56; - - public override bool OnBeforeDeath() - { - if (!base.OnBeforeDeath()) - return false; - - Gold gold = new Gold(Utility.RandomMinMax(240, 375)); - gold.MoveToWorld(Location, Map); - - Effects.SendLocationEffect(Location, Map, 0x376A, 10, 1); - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/StoneGargoyle.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/StoneGargoyle.cs index cb92fbfff..345070909 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/StoneGargoyle.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/StoneGargoyle.cs @@ -2,71 +2,71 @@ using Server.Items; namespace Server.Mobiles { - public class StoneGargoyle : BaseCreature - { - [Constructible] - public StoneGargoyle() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class StoneGargoyle : BaseCreature { - Body = 67; - BaseSoundID = 0x174; + [Constructible] + public StoneGargoyle() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 67; + BaseSoundID = 0x174; - SetStr(246, 275); - SetDex(76, 95); - SetInt(81, 105); + SetStr(246, 275); + SetDex(76, 95); + SetInt(81, 105); - SetHits(148, 165); + SetHits(148, 165); - SetDamage(11, 17); + SetDamage(11, 17); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 10, 20); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.MagicResist, 85.1, 100.0); - SetSkill(SkillName.Tactics, 80.1, 100.0); - SetSkill(SkillName.Wrestling, 60.1, 100.0); + SetSkill(SkillName.MagicResist, 85.1, 100.0); + SetSkill(SkillName.Tactics, 80.1, 100.0); + SetSkill(SkillName.Wrestling, 60.1, 100.0); - Fame = 4000; - Karma = -4000; + Fame = 4000; + Karma = -4000; - VirtualArmor = 50; + VirtualArmor = 50; - PackItem(new IronIngot(12)); + PackItem(new IronIngot(12)); - if (Utility.RandomDouble() < 0.05) - PackItem(new GargoylesPickaxe()); + if (Utility.RandomDouble() < 0.05) + PackItem(new GargoylesPickaxe()); + } + + public StoneGargoyle(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a gargoyle corpse"; + public override string DefaultName => "a stone gargoyle"; + + public override int TreasureMapLevel => 2; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average, 2); + AddLoot(LootPack.Gems, 1); + AddLoot(LootPack.Potions); + } + + 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(); + } } - - public StoneGargoyle(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a gargoyle corpse"; - public override string DefaultName => "a stone gargoyle"; - - public override int TreasureMapLevel => 2; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average, 2); - AddLoot(LootPack.Gems, 1); - AddLoot(LootPack.Potions); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/StrongMongbat.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/StrongMongbat.cs index e5a4d5e5c..1d942c9da 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/StrongMongbat.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/StrongMongbat.cs @@ -1,66 +1,66 @@ namespace Server.Mobiles { - public class StrongMongbat : BaseCreature - { - [Constructible] - public StrongMongbat() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class StrongMongbat : BaseCreature { - Body = 39; - BaseSoundID = 422; + [Constructible] + public StrongMongbat() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 39; + BaseSoundID = 422; - SetStr(6, 10); - SetDex(26, 38); - SetInt(6, 14); + SetStr(6, 10); + SetDex(26, 38); + SetInt(6, 14); - SetHits(4, 6); - SetMana(0); + SetHits(4, 6); + SetMana(0); - SetDamage(5, 7); + SetDamage(5, 7); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 15, 25); + SetResistance(ResistanceType.Physical, 15, 25); - SetSkill(SkillName.MagicResist, 15.1, 30.0); - SetSkill(SkillName.Tactics, 35.1, 50.0); - SetSkill(SkillName.Wrestling, 20.1, 35.0); + SetSkill(SkillName.MagicResist, 15.1, 30.0); + SetSkill(SkillName.Tactics, 35.1, 50.0); + SetSkill(SkillName.Wrestling, 20.1, 35.0); - Fame = 150; - Karma = -150; + Fame = 150; + Karma = -150; - VirtualArmor = 10; + VirtualArmor = 10; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 71.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 71.1; + } + + public StrongMongbat(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a mongbat corpse"; + public override string DefaultName => "a mongbat"; + + public override int Meat => 1; + public override int Hides => 6; + public override FoodType FavoriteFood => FoodType.Meat; + + public override void GenerateLoot() + { + AddLoot(LootPack.Poor); + } + + 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(); + } } - - public StrongMongbat(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a mongbat corpse"; - public override string DefaultName => "a mongbat"; - - public override int Meat => 1; - public override int Hides => 6; - public override FoodType FavoriteFood => FoodType.Meat; - - public override void GenerateLoot() - { - AddLoot(LootPack.Poor); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Troll.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Troll.cs index 10808278b..5b47fd587 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Troll.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Troll.cs @@ -1,65 +1,65 @@ namespace Server.Mobiles { - public class Troll : BaseCreature - { - [Constructible] - public Troll() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Troll : BaseCreature { - Body = Utility.RandomList(53, 54); - BaseSoundID = 461; + [Constructible] + public Troll() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = Utility.RandomList(53, 54); + BaseSoundID = 461; - SetStr(176, 205); - SetDex(46, 65); - SetInt(46, 70); + SetStr(176, 205); + SetDex(46, 65); + SetInt(46, 70); - SetHits(106, 123); + SetHits(106, 123); - SetDamage(8, 14); + SetDamage(8, 14); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 25, 35); - SetResistance(ResistanceType.Cold, 15, 25); - SetResistance(ResistanceType.Poison, 5, 15); - SetResistance(ResistanceType.Energy, 5, 15); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 25, 35); + SetResistance(ResistanceType.Cold, 15, 25); + SetResistance(ResistanceType.Poison, 5, 15); + SetResistance(ResistanceType.Energy, 5, 15); - SetSkill(SkillName.MagicResist, 45.1, 60.0); - SetSkill(SkillName.Tactics, 50.1, 70.0); - SetSkill(SkillName.Wrestling, 50.1, 70.0); + SetSkill(SkillName.MagicResist, 45.1, 60.0); + SetSkill(SkillName.Tactics, 50.1, 70.0); + SetSkill(SkillName.Wrestling, 50.1, 70.0); - Fame = 3500; - Karma = -3500; + Fame = 3500; + Karma = -3500; - VirtualArmor = 40; + VirtualArmor = 40; + } + + public Troll(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a troll corpse"; + public override string DefaultName => "a troll"; + + public override bool CanRummageCorpses => true; + public override int TreasureMapLevel => 1; + public override int Meat => 2; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + } + + 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(); + } } - - public Troll(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a troll corpse"; - public override string DefaultName => "a troll"; - - public override bool CanRummageCorpses => true; - public override int TreasureMapLevel => 1; - public override int Meat => 2; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Zombie.cs b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Zombie.cs index 829836353..dc886d409 100644 --- a/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Zombie.cs +++ b/Projects/UOContent/Mobiles/Monsters/Humanoid/Melee/Zombie.cs @@ -2,78 +2,78 @@ using Server.Items; namespace Server.Mobiles { - public class Zombie : BaseCreature - { - [Constructible] - public Zombie() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Zombie : BaseCreature { - Body = 3; - BaseSoundID = 471; - - SetStr(46, 70); - SetDex(31, 50); - SetInt(26, 40); - - SetHits(28, 42); - - SetDamage(3, 7); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 15, 20); - SetResistance(ResistanceType.Cold, 20, 30); - SetResistance(ResistanceType.Poison, 5, 10); - - SetSkill(SkillName.MagicResist, 15.1, 40.0); - SetSkill(SkillName.Tactics, 35.1, 50.0); - SetSkill(SkillName.Wrestling, 35.1, 50.0); - - Fame = 600; - Karma = -600; - - VirtualArmor = 18; - - PackItem( - Utility.Random(10) switch + [Constructible] + public Zombie() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) { - 0 => new LeftArm(), - 1 => new RightArm(), - 2 => new Torso(), - 3 => new Bone(), - 4 => new RibCage(), - 5 => new RibCage(), - _ => new BonePile() // 6-9 + Body = 3; + BaseSoundID = 471; + + SetStr(46, 70); + SetDex(31, 50); + SetInt(26, 40); + + SetHits(28, 42); + + SetDamage(3, 7); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 15, 20); + SetResistance(ResistanceType.Cold, 20, 30); + SetResistance(ResistanceType.Poison, 5, 10); + + SetSkill(SkillName.MagicResist, 15.1, 40.0); + SetSkill(SkillName.Tactics, 35.1, 50.0); + SetSkill(SkillName.Wrestling, 35.1, 50.0); + + Fame = 600; + Karma = -600; + + VirtualArmor = 18; + + PackItem( + Utility.Random(10) switch + { + 0 => new LeftArm(), + 1 => new RightArm(), + 2 => new Torso(), + 3 => new Bone(), + 4 => new RibCage(), + 5 => new RibCage(), + _ => new BonePile() // 6-9 + } + ); + } + + public Zombie(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a rotting corpse"; + public override string DefaultName => "a zombie"; + + public override bool BleedImmune => true; + public override Poison PoisonImmune => Poison.Regular; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + 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(); } - ); } - - public Zombie(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a rotting corpse"; - public override string DefaultName => "a zombie"; - - public override bool BleedImmune => true; - public override Poison PoisonImmune => Poison.Regular; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/LBR/Exodus/ExodusMinion.cs b/Projects/UOContent/Mobiles/Monsters/LBR/Exodus/ExodusMinion.cs index d624e405d..54767ccfd 100644 --- a/Projects/UOContent/Mobiles/Monsters/LBR/Exodus/ExodusMinion.cs +++ b/Projects/UOContent/Mobiles/Monsters/LBR/Exodus/ExodusMinion.cs @@ -2,179 +2,179 @@ using Server.Items; namespace Server.Mobiles { - public class ExodusMinion : BaseCreature - { - [Constructible] - public ExodusMinion() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class ExodusMinion : BaseCreature { - Body = 0x2F5; + [Constructible] + public ExodusMinion() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0x2F5; - SetStr(851, 950); - SetDex(71, 80); - SetInt(61, 90); + SetStr(851, 950); + SetDex(71, 80); + SetInt(61, 90); - SetHits(511, 570); + SetHits(511, 570); - SetDamage(16, 22); + SetDamage(16, 22); - SetResistance(ResistanceType.Physical, 60, 70); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 15, 25); - SetResistance(ResistanceType.Poison, 15, 25); - SetResistance(ResistanceType.Energy, 15, 25); + SetResistance(ResistanceType.Physical, 60, 70); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 15, 25); + SetResistance(ResistanceType.Poison, 15, 25); + SetResistance(ResistanceType.Energy, 15, 25); - SetSkill(SkillName.MagicResist, 90.1, 100.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); - SetSkill(SkillName.Wrestling, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 90.1, 100.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.Wrestling, 90.1, 100.0); - Fame = 18000; - Karma = -18000; - VirtualArmor = 65; + Fame = 18000; + Karma = -18000; + VirtualArmor = 65; - PackItem(new PowerCrystal()); - PackItem(new ArcaneGem()); - PackItem(new ClockworkAssembly()); + PackItem(new PowerCrystal()); + PackItem(new ArcaneGem()); + PackItem(new ClockworkAssembly()); - switch (Utility.Random(3)) - { - case 0: - PackItem(new PowerCrystal()); - break; - case 1: - PackItem(new ArcaneGem()); - break; - case 2: - PackItem(new ClockworkAssembly()); - break; - } + switch (Utility.Random(3)) + { + case 0: + PackItem(new PowerCrystal()); + break; + case 1: + PackItem(new ArcaneGem()); + break; + case 2: + PackItem(new ClockworkAssembly()); + break; + } - FieldActive = CanUseField; + FieldActive = CanUseField; + } + + public ExodusMinion(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a minion's corpse"; + public bool FieldActive { get; private set; } + + public bool CanUseField // TODO: an OSI bug prevents to verify this + => Hits >= HitsMax * 9 / 10; + + public override bool IsScaredOfScaryThings => false; + public override bool IsScaryToPets => true; + + public override string DefaultName => "an exodus minion"; + + public override bool AutoDispel => true; + public override bool BardImmune => !Core.AOS; + public override Poison PoisonImmune => Poison.Lethal; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Rich); + } + + public override int GetIdleSound() => 0x218; + + public override int GetAngerSound() => 0x26C; + + public override int GetDeathSound() => 0x211; + + public override int GetAttackSound() => 0x232; + + public override int GetHurtSound() => 0x140; + + public override void AlterMeleeDamageFrom(Mobile from, ref int damage) + { + if (FieldActive) + damage = 0; // no melee damage when the field is up + } + + public override void AlterSpellDamageFrom(Mobile from, ref int damage) + { + if (!FieldActive) + damage = 0; // no spell damage when the field is down + } + + public override void OnDamagedBySpell(Mobile from) + { + if (from?.Alive == true && Utility.RandomDouble() < 0.4) SendEBolt(from); + + if (!FieldActive) + { + // should there be an effect when spells nullifying is on? + FixedParticles(0, 10, 0, 0x2522, EffectLayer.Waist); + } + else if (FieldActive && !CanUseField) + { + FieldActive = false; + + // TODO: message and effect when field turns down; cannot be verified on OSI due to a bug + FixedParticles(0x3735, 1, 30, 0x251F, EffectLayer.Waist); + } + } + + public override void OnGotMeleeAttack(Mobile attacker) + { + base.OnGotMeleeAttack(attacker); + + if (FieldActive) + { + FixedParticles(0x376A, 20, 10, 0x2530, EffectLayer.Waist); + + PlaySound(0x2F4); + + attacker.SendAsciiMessage("Your weapon cannot penetrate the creature's magical barrier"); + } + + if (attacker?.Alive == true && attacker.Weapon is BaseRanged && Utility.RandomDouble() < 0.4) + SendEBolt(attacker); + } + + public override void OnThink() + { + base.OnThink(); + + // TODO: an OSI bug prevents to verify if the field can regenerate or not + if (!FieldActive && !IsHurt()) + FieldActive = true; + } + + public override bool Move(Direction d) + { + var move = base.Move(d); + + if (move && FieldActive && Combatant != null) + FixedParticles(0, 10, 0, 0x2530, EffectLayer.Waist); + + return move; + } + + public void SendEBolt(Mobile to) + { + MovingParticles(to, 0x379F, 7, 0, false, true, 0xBE3, 0xFCB, 0x211); + to.PlaySound(0x229); + DoHarmful(to); + AOS.Damage(to, this, 50, 0, 0, 0, 0, 100); + } + + 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(); + + FieldActive = CanUseField; + + if (Name == "Exodus Minion") + Name = null; + } } - - public ExodusMinion(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a minion's corpse"; - public bool FieldActive { get; private set; } - - public bool CanUseField // TODO: an OSI bug prevents to verify this - => Hits >= HitsMax * 9 / 10; - - public override bool IsScaredOfScaryThings => false; - public override bool IsScaryToPets => true; - - public override string DefaultName => "an exodus minion"; - - public override bool AutoDispel => true; - public override bool BardImmune => !Core.AOS; - public override Poison PoisonImmune => Poison.Lethal; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Rich); - } - - public override int GetIdleSound() => 0x218; - - public override int GetAngerSound() => 0x26C; - - public override int GetDeathSound() => 0x211; - - public override int GetAttackSound() => 0x232; - - public override int GetHurtSound() => 0x140; - - public override void AlterMeleeDamageFrom(Mobile from, ref int damage) - { - if (FieldActive) - damage = 0; // no melee damage when the field is up - } - - public override void AlterSpellDamageFrom(Mobile from, ref int damage) - { - if (!FieldActive) - damage = 0; // no spell damage when the field is down - } - - public override void OnDamagedBySpell(Mobile from) - { - if (from?.Alive == true && Utility.RandomDouble() < 0.4) SendEBolt(from); - - if (!FieldActive) - { - // should there be an effect when spells nullifying is on? - FixedParticles(0, 10, 0, 0x2522, EffectLayer.Waist); - } - else if (FieldActive && !CanUseField) - { - FieldActive = false; - - // TODO: message and effect when field turns down; cannot be verified on OSI due to a bug - FixedParticles(0x3735, 1, 30, 0x251F, EffectLayer.Waist); - } - } - - public override void OnGotMeleeAttack(Mobile attacker) - { - base.OnGotMeleeAttack(attacker); - - if (FieldActive) - { - FixedParticles(0x376A, 20, 10, 0x2530, EffectLayer.Waist); - - PlaySound(0x2F4); - - attacker.SendAsciiMessage("Your weapon cannot penetrate the creature's magical barrier"); - } - - if (attacker?.Alive == true && attacker.Weapon is BaseRanged && Utility.RandomDouble() < 0.4) - SendEBolt(attacker); - } - - public override void OnThink() - { - base.OnThink(); - - // TODO: an OSI bug prevents to verify if the field can regenerate or not - if (!FieldActive && !IsHurt()) - FieldActive = true; - } - - public override bool Move(Direction d) - { - bool move = base.Move(d); - - if (move && FieldActive && Combatant != null) - FixedParticles(0, 10, 0, 0x2530, EffectLayer.Waist); - - return move; - } - - public void SendEBolt(Mobile to) - { - MovingParticles(to, 0x379F, 7, 0, false, true, 0xBE3, 0xFCB, 0x211); - to.PlaySound(0x229); - DoHarmful(to); - AOS.Damage(to, this, 50, 0, 0, 0, 0, 100); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - FieldActive = CanUseField; - - if (Name == "Exodus Minion") - Name = null; - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/LBR/Exodus/ExodusOverseer.cs b/Projects/UOContent/Mobiles/Monsters/LBR/Exodus/ExodusOverseer.cs index bd43d23b0..42e5796e3 100644 --- a/Projects/UOContent/Mobiles/Monsters/LBR/Exodus/ExodusOverseer.cs +++ b/Projects/UOContent/Mobiles/Monsters/LBR/Exodus/ExodusOverseer.cs @@ -2,169 +2,169 @@ using Server.Items; namespace Server.Mobiles { - public class ExodusOverseer : BaseCreature - { - [Constructible] - public ExodusOverseer() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class ExodusOverseer : BaseCreature { - Body = 0x2F4; + [Constructible] + public ExodusOverseer() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0x2F4; - SetStr(561, 650); - SetDex(76, 95); - SetInt(61, 90); + SetStr(561, 650); + SetDex(76, 95); + SetInt(61, 90); - SetHits(331, 390); + SetHits(331, 390); - SetDamage(13, 19); + SetDamage(13, 19); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Energy, 50); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Energy, 50); - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 40, 60); - SetResistance(ResistanceType.Cold, 25, 35); - SetResistance(ResistanceType.Poison, 25, 35); - SetResistance(ResistanceType.Energy, 25, 35); + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 40, 60); + SetResistance(ResistanceType.Cold, 25, 35); + SetResistance(ResistanceType.Poison, 25, 35); + SetResistance(ResistanceType.Energy, 25, 35); - SetSkill(SkillName.MagicResist, 80.2, 98.0); - SetSkill(SkillName.Tactics, 80.2, 98.0); - SetSkill(SkillName.Wrestling, 80.2, 98.0); + SetSkill(SkillName.MagicResist, 80.2, 98.0); + SetSkill(SkillName.Tactics, 80.2, 98.0); + SetSkill(SkillName.Wrestling, 80.2, 98.0); - Fame = 10000; - Karma = -10000; - VirtualArmor = 50; + Fame = 10000; + Karma = -10000; + VirtualArmor = 50; - if (Utility.Random(2) == 0) - PackItem(new PowerCrystal()); - else - PackItem(new ArcaneGem()); + if (Utility.Random(2) == 0) + PackItem(new PowerCrystal()); + else + PackItem(new ArcaneGem()); - FieldActive = CanUseField; + FieldActive = CanUseField; + } + + public ExodusOverseer(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an overseer's corpse"; + public bool FieldActive { get; private set; } + + public bool CanUseField // TODO: an OSI bug prevents to verify this + => Hits >= HitsMax * 9 / 10; + + public override bool IsScaredOfScaryThings => false; + public override bool IsScaryToPets => true; + + public override string DefaultName => "an exodus overseer"; + + public override bool AutoDispel => true; + public override bool BardImmune => !Core.AOS; + public override Poison PoisonImmune => Poison.Lethal; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + } + + public override int GetIdleSound() => 0xFD; + + public override int GetAngerSound() => 0x26C; + + public override int GetDeathSound() => 0x211; + + public override int GetAttackSound() => 0x23B; + + public override int GetHurtSound() => 0x140; + + public override void AlterMeleeDamageFrom(Mobile from, ref int damage) + { + if (FieldActive) + damage = 0; // no melee damage when the field is up + } + + public override void AlterSpellDamageFrom(Mobile caster, ref int damage) + { + if (!FieldActive) + damage = 0; // no spell damage when the field is down + } + + public override void OnDamagedBySpell(Mobile from) + { + if (from?.Alive == true && Utility.RandomDouble() < 0.4) SendEBolt(from); + + if (!FieldActive) + { + // should there be an effect when spells nullifying is on? + FixedParticles(0, 10, 0, 0x2522, EffectLayer.Waist); + } + else if (FieldActive && !CanUseField) + { + FieldActive = false; + + // TODO: message and effect when field turns down; cannot be verified on OSI due to a bug + FixedParticles(0x3735, 1, 30, 0x251F, EffectLayer.Waist); + } + } + + public override void OnGotMeleeAttack(Mobile attacker) + { + base.OnGotMeleeAttack(attacker); + + if (FieldActive) + { + FixedParticles(0x376A, 20, 10, 0x2530, EffectLayer.Waist); + + PlaySound(0x2F4); + + attacker.SendAsciiMessage("Your weapon cannot penetrate the creature's magical barrier"); + } + + if (attacker?.Alive == true && attacker.Weapon is BaseRanged && Utility.RandomDouble() < 0.4) + SendEBolt(attacker); + } + + public override void OnThink() + { + base.OnThink(); + + // TODO: an OSI bug prevents to verify if the field can regenerate or not + if (!FieldActive && !IsHurt()) + FieldActive = true; + } + + public override bool Move(Direction d) + { + var move = base.Move(d); + + if (move && FieldActive && Combatant != null) + FixedParticles(0, 10, 0, 0x2530, EffectLayer.Waist); + + return move; + } + + public void SendEBolt(Mobile to) + { + MovingParticles(to, 0x379F, 7, 0, false, true, 0xBE3, 0xFCB, 0x211); + to.PlaySound(0x229); + DoHarmful(to); + AOS.Damage(to, this, 50, 0, 0, 0, 0, 100); + } + + 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(); + + FieldActive = CanUseField; + + if (Name == "Exodus Overseer") + Name = null; + } } - - public ExodusOverseer(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an overseer's corpse"; - public bool FieldActive { get; private set; } - - public bool CanUseField // TODO: an OSI bug prevents to verify this - => Hits >= HitsMax * 9 / 10; - - public override bool IsScaredOfScaryThings => false; - public override bool IsScaryToPets => true; - - public override string DefaultName => "an exodus overseer"; - - public override bool AutoDispel => true; - public override bool BardImmune => !Core.AOS; - public override Poison PoisonImmune => Poison.Lethal; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - } - - public override int GetIdleSound() => 0xFD; - - public override int GetAngerSound() => 0x26C; - - public override int GetDeathSound() => 0x211; - - public override int GetAttackSound() => 0x23B; - - public override int GetHurtSound() => 0x140; - - public override void AlterMeleeDamageFrom(Mobile from, ref int damage) - { - if (FieldActive) - damage = 0; // no melee damage when the field is up - } - - public override void AlterSpellDamageFrom(Mobile caster, ref int damage) - { - if (!FieldActive) - damage = 0; // no spell damage when the field is down - } - - public override void OnDamagedBySpell(Mobile from) - { - if (from?.Alive == true && Utility.RandomDouble() < 0.4) SendEBolt(from); - - if (!FieldActive) - { - // should there be an effect when spells nullifying is on? - FixedParticles(0, 10, 0, 0x2522, EffectLayer.Waist); - } - else if (FieldActive && !CanUseField) - { - FieldActive = false; - - // TODO: message and effect when field turns down; cannot be verified on OSI due to a bug - FixedParticles(0x3735, 1, 30, 0x251F, EffectLayer.Waist); - } - } - - public override void OnGotMeleeAttack(Mobile attacker) - { - base.OnGotMeleeAttack(attacker); - - if (FieldActive) - { - FixedParticles(0x376A, 20, 10, 0x2530, EffectLayer.Waist); - - PlaySound(0x2F4); - - attacker.SendAsciiMessage("Your weapon cannot penetrate the creature's magical barrier"); - } - - if (attacker?.Alive == true && attacker.Weapon is BaseRanged && Utility.RandomDouble() < 0.4) - SendEBolt(attacker); - } - - public override void OnThink() - { - base.OnThink(); - - // TODO: an OSI bug prevents to verify if the field can regenerate or not - if (!FieldActive && !IsHurt()) - FieldActive = true; - } - - public override bool Move(Direction d) - { - bool move = base.Move(d); - - if (move && FieldActive && Combatant != null) - FixedParticles(0, 10, 0, 0x2530, EffectLayer.Waist); - - return move; - } - - public void SendEBolt(Mobile to) - { - MovingParticles(to, 0x379F, 7, 0, false, true, 0xBE3, 0xFCB, 0x211); - to.PlaySound(0x229); - DoHarmful(to); - AOS.Damage(to, this, 50, 0, 0, 0, 0, 100); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - FieldActive = CanUseField; - - if (Name == "Exodus Overseer") - Name = null; - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/LBR/Jukas/ChaosDragoon.cs b/Projects/UOContent/Mobiles/Monsters/LBR/Jukas/ChaosDragoon.cs index 5034281cd..817a1d3a6 100644 --- a/Projects/UOContent/Mobiles/Monsters/LBR/Jukas/ChaosDragoon.cs +++ b/Projects/UOContent/Mobiles/Monsters/LBR/Jukas/ChaosDragoon.cs @@ -2,146 +2,146 @@ using Server.Items; namespace Server.Mobiles { - public class ChaosDragoon : BaseCreature - { - [Constructible] - public ChaosDragoon() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.15, 0.4) + public class ChaosDragoon : BaseCreature { - Body = 0x190; - Hue = Race.Human.RandomSkinHue(); - - SetStr(176, 225); - SetDex(81, 95); - SetInt(61, 85); - - SetHits(176, 225); - - SetDamage(24, 26); - - SetDamageType(ResistanceType.Physical, 25); - SetDamageType(ResistanceType.Fire, 25); - SetDamageType(ResistanceType.Cold, 25); - SetDamageType(ResistanceType.Energy, 25); - - // SetResistance( ResistanceType.Physical, 25, 38 ); - // SetResistance( ResistanceType.Fire, 25, 38 ); - // SetResistance( ResistanceType.Cold, 25, 38 ); - // SetResistance( ResistanceType.Poison, 25, 38 ); - // SetResistance( ResistanceType.Energy, 25, 38 ); - - SetSkill(SkillName.Fencing, 77.6, 92.5); - SetSkill(SkillName.Healing, 60.3, 90.0); - SetSkill(SkillName.Macing, 77.6, 92.5); - SetSkill(SkillName.Anatomy, 77.6, 87.5); - SetSkill(SkillName.MagicResist, 77.6, 97.5); - SetSkill(SkillName.Swords, 77.6, 92.5); - SetSkill(SkillName.Tactics, 77.6, 87.5); - - Fame = 5000; - Karma = -5000; - - var res = Utility.Random(6) switch - { - 0 => CraftResource.BlackScales, - 1 => CraftResource.RedScales, - 2 => CraftResource.BlueScales, - 3 => CraftResource.YellowScales, - 4 => CraftResource.GreenScales, - _ => CraftResource.WhiteScales // 5 - }; - - var melee = Utility.Random(3) switch - { - 0 => (BaseWeapon)new Kryss(), - 1 => new Broadsword(), - _ => new Katana() // 2 - }; - - melee.Movable = false; - AddItem(melee); - - AddItem(new DragonHelm {Resource = res, Movable = false}); - AddItem(new DragonChest {Resource = res, Movable = false}); - AddItem(new DragonArms {Resource = res, Movable = false}); - AddItem(new DragonGloves {Resource = res, Movable = false}); - AddItem(new DragonLegs {Resource = res, Movable = false}); - AddItem(new ChaosShield {Movable = false}); - - AddItem(new Shirt()); - AddItem(new Boots()); - - int amount = Utility.RandomMinMax(1, 3); - - AddItem( - res switch + [Constructible] + public ChaosDragoon() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.15, 0.4) { - CraftResource.BlackScales => new BlackScales(amount), - CraftResource.RedScales => new RedScales(amount), - CraftResource.BlueScales => new BlueScales(amount), - CraftResource.YellowScales => new YellowScales(amount), - CraftResource.GreenScales => new GreenScales(amount), - _ => new WhiteScales(amount) // CraftResource.WhiteScales + Body = 0x190; + Hue = Race.Human.RandomSkinHue(); + + SetStr(176, 225); + SetDex(81, 95); + SetInt(61, 85); + + SetHits(176, 225); + + SetDamage(24, 26); + + SetDamageType(ResistanceType.Physical, 25); + SetDamageType(ResistanceType.Fire, 25); + SetDamageType(ResistanceType.Cold, 25); + SetDamageType(ResistanceType.Energy, 25); + + // SetResistance( ResistanceType.Physical, 25, 38 ); + // SetResistance( ResistanceType.Fire, 25, 38 ); + // SetResistance( ResistanceType.Cold, 25, 38 ); + // SetResistance( ResistanceType.Poison, 25, 38 ); + // SetResistance( ResistanceType.Energy, 25, 38 ); + + SetSkill(SkillName.Fencing, 77.6, 92.5); + SetSkill(SkillName.Healing, 60.3, 90.0); + SetSkill(SkillName.Macing, 77.6, 92.5); + SetSkill(SkillName.Anatomy, 77.6, 87.5); + SetSkill(SkillName.MagicResist, 77.6, 97.5); + SetSkill(SkillName.Swords, 77.6, 92.5); + SetSkill(SkillName.Tactics, 77.6, 87.5); + + Fame = 5000; + Karma = -5000; + + var res = Utility.Random(6) switch + { + 0 => CraftResource.BlackScales, + 1 => CraftResource.RedScales, + 2 => CraftResource.BlueScales, + 3 => CraftResource.YellowScales, + 4 => CraftResource.GreenScales, + _ => CraftResource.WhiteScales // 5 + }; + + var melee = Utility.Random(3) switch + { + 0 => (BaseWeapon)new Kryss(), + 1 => new Broadsword(), + _ => new Katana() // 2 + }; + + melee.Movable = false; + AddItem(melee); + + AddItem(new DragonHelm { Resource = res, Movable = false }); + AddItem(new DragonChest { Resource = res, Movable = false }); + AddItem(new DragonArms { Resource = res, Movable = false }); + AddItem(new DragonGloves { Resource = res, Movable = false }); + AddItem(new DragonLegs { Resource = res, Movable = false }); + AddItem(new ChaosShield { Movable = false }); + + AddItem(new Shirt()); + AddItem(new Boots()); + + var amount = Utility.RandomMinMax(1, 3); + + AddItem( + res switch + { + CraftResource.BlackScales => new BlackScales(amount), + CraftResource.RedScales => new RedScales(amount), + CraftResource.BlueScales => new BlueScales(amount), + CraftResource.YellowScales => new YellowScales(amount), + CraftResource.GreenScales => new GreenScales(amount), + _ => new WhiteScales(amount) // CraftResource.WhiteScales + } + ); + + new SwampDragon().Rider = this; } - ); - new SwampDragon().Rider = this; + public ChaosDragoon(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a chaos dragoon corpse"; + public override string DefaultName => "a chaos dragoon"; + + public override bool HasBreath => true; + public override bool AutoDispel => true; + public override bool BardImmune => !Core.AOS; + public override bool CanRummageCorpses => true; + public override bool AlwaysMurderer => true; + public override bool ShowFameTitle => false; + + public override int GetIdleSound() => 0x2CE; + + public override int GetDeathSound() => 0x2CC; + + public override int GetHurtSound() => 0x2D1; + + public override int GetAttackSound() => 0x2C8; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + // AddLoot( LootPack.Gems ); + } + + public override bool OnBeforeDeath() + { + var mount = Mount; + + if (mount != null) + mount.Rider = null; + + return base.OnBeforeDeath(); + } + + public override void AlterMeleeDamageTo(Mobile to, ref int damage) + { + if (to is Dragon || to is WhiteWyrm || to is SwampDragon || to is Drake || to is Nightmare || to is Hiryu || + to is LesserHiryu || to is Daemon) + damage *= 3; + } + + 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(); + } } - - public ChaosDragoon(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a chaos dragoon corpse"; - public override string DefaultName => "a chaos dragoon"; - - public override bool HasBreath => true; - public override bool AutoDispel => true; - public override bool BardImmune => !Core.AOS; - public override bool CanRummageCorpses => true; - public override bool AlwaysMurderer => true; - public override bool ShowFameTitle => false; - - public override int GetIdleSound() => 0x2CE; - - public override int GetDeathSound() => 0x2CC; - - public override int GetHurtSound() => 0x2D1; - - public override int GetAttackSound() => 0x2C8; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - // AddLoot( LootPack.Gems ); - } - - public override bool OnBeforeDeath() - { - IMount mount = Mount; - - if (mount != null) - mount.Rider = null; - - return base.OnBeforeDeath(); - } - - public override void AlterMeleeDamageTo(Mobile to, ref int damage) - { - if (to is Dragon || to is WhiteWyrm || to is SwampDragon || to is Drake || to is Nightmare || to is Hiryu || - to is LesserHiryu || to is Daemon) - damage *= 3; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/LBR/Jukas/ChaosDragoonElite.cs b/Projects/UOContent/Mobiles/Monsters/LBR/Jukas/ChaosDragoonElite.cs index 738b537b7..cb29c77ee 100644 --- a/Projects/UOContent/Mobiles/Monsters/LBR/Jukas/ChaosDragoonElite.cs +++ b/Projects/UOContent/Mobiles/Monsters/LBR/Jukas/ChaosDragoonElite.cs @@ -2,168 +2,168 @@ using Server.Items; namespace Server.Mobiles { - public class ChaosDragoonElite : BaseCreature - { - [Constructible] - public ChaosDragoonElite() - : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.15, 0.4) + public class ChaosDragoonElite : BaseCreature { - Body = 0x190; - Hue = Race.Human.RandomSkinHue(); - - SetStr(276, 350); - SetDex(66, 90); - SetInt(126, 150); - - SetHits(276, 350); - - SetDamage(29, 34); - - SetDamageType(ResistanceType.Physical, 100); - - /*SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 15, 25); - SetResistance(ResistanceType.Cold, 50); - SetResistance(ResistanceType.Poison, 25, 35); - SetResistance(ResistanceType.Energy, 25, 35);*/ - - SetSkill(SkillName.Tactics, 80.1, 100.0); - SetSkill(SkillName.MagicResist, 100.1, 110.0); - SetSkill(SkillName.Anatomy, 80.1, 100.0); - SetSkill(SkillName.Magery, 85.1, 100.0); - SetSkill(SkillName.EvalInt, 85.1, 100.0); - SetSkill(SkillName.Swords, 72.5, 95.0); - SetSkill(SkillName.Fencing, 85.1, 100); - SetSkill(SkillName.Macing, 85.1, 100); - - Fame = 8000; - Karma = -8000; - - CraftResource res; - - res = Utility.Random(6) switch - { - 0 => CraftResource.BlackScales, - 1 => CraftResource.RedScales, - 2 => CraftResource.BlueScales, - 3 => CraftResource.YellowScales, - 4 => CraftResource.GreenScales, - _ => CraftResource.WhiteScales // 5 - }; - - var melee = Utility.Random(3) switch - { - 0 => (BaseWeapon)new Kryss(), - 1 => new Broadsword(), - _ => new Katana() // 2 - }; - - melee.Movable = false; - AddItem(melee); - - AddItem(new DragonChest {Resource = res, Movable = false}); - AddItem(new DragonLegs {Resource = res, Movable = false}); - AddItem(new DragonArms {Resource = res, Movable = false}); - AddItem(new DragonGloves {Resource = res, Movable = false}); - AddItem(new DragonHelm {Resource = res, Movable = false}); - AddItem(new ChaosShield {Movable = false}); - - AddItem(new Boots(0x455)); - AddItem(new Shirt(Utility.RandomMetalHue())); - - int amount = Utility.RandomMinMax(1, 3); - - AddItem( - res switch + [Constructible] + public ChaosDragoonElite() + : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.15, 0.4) { - CraftResource.BlackScales => new BlackScales(amount), - CraftResource.RedScales => new RedScales(amount), - CraftResource.BlueScales => new BlueScales(amount), - CraftResource.YellowScales => new YellowScales(amount), - CraftResource.GreenScales => new GreenScales(amount), - _ => new WhiteScales(amount) // CraftResource.WhiteScales + Body = 0x190; + Hue = Race.Human.RandomSkinHue(); + + SetStr(276, 350); + SetDex(66, 90); + SetInt(126, 150); + + SetHits(276, 350); + + SetDamage(29, 34); + + SetDamageType(ResistanceType.Physical, 100); + + /*SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 15, 25); + SetResistance(ResistanceType.Cold, 50); + SetResistance(ResistanceType.Poison, 25, 35); + SetResistance(ResistanceType.Energy, 25, 35);*/ + + SetSkill(SkillName.Tactics, 80.1, 100.0); + SetSkill(SkillName.MagicResist, 100.1, 110.0); + SetSkill(SkillName.Anatomy, 80.1, 100.0); + SetSkill(SkillName.Magery, 85.1, 100.0); + SetSkill(SkillName.EvalInt, 85.1, 100.0); + SetSkill(SkillName.Swords, 72.5, 95.0); + SetSkill(SkillName.Fencing, 85.1, 100); + SetSkill(SkillName.Macing, 85.1, 100); + + Fame = 8000; + Karma = -8000; + + CraftResource res; + + res = Utility.Random(6) switch + { + 0 => CraftResource.BlackScales, + 1 => CraftResource.RedScales, + 2 => CraftResource.BlueScales, + 3 => CraftResource.YellowScales, + 4 => CraftResource.GreenScales, + _ => CraftResource.WhiteScales // 5 + }; + + var melee = Utility.Random(3) switch + { + 0 => (BaseWeapon)new Kryss(), + 1 => new Broadsword(), + _ => new Katana() // 2 + }; + + melee.Movable = false; + AddItem(melee); + + AddItem(new DragonChest { Resource = res, Movable = false }); + AddItem(new DragonLegs { Resource = res, Movable = false }); + AddItem(new DragonArms { Resource = res, Movable = false }); + AddItem(new DragonGloves { Resource = res, Movable = false }); + AddItem(new DragonHelm { Resource = res, Movable = false }); + AddItem(new ChaosShield { Movable = false }); + + AddItem(new Boots(0x455)); + AddItem(new Shirt(Utility.RandomMetalHue())); + + var amount = Utility.RandomMinMax(1, 3); + + AddItem( + res switch + { + CraftResource.BlackScales => new BlackScales(amount), + CraftResource.RedScales => new RedScales(amount), + CraftResource.BlueScales => new BlueScales(amount), + CraftResource.YellowScales => new YellowScales(amount), + CraftResource.GreenScales => new GreenScales(amount), + _ => new WhiteScales(amount) // CraftResource.WhiteScales + } + ); + + res = Utility.Random(9) switch + { + 0 => CraftResource.DullCopper, + 1 => CraftResource.ShadowIron, + 2 => CraftResource.Copper, + 3 => CraftResource.Bronze, + 4 => CraftResource.Gold, + 5 => CraftResource.Agapite, + 6 => CraftResource.Verite, + 7 => CraftResource.Valorite, + _ => CraftResource.Iron // 8 + }; + + var mt = new SwampDragon { HasBarding = true, BardingResource = res }; + mt.BardingHP = mt.BardingMaxHP; + mt.Rider = this; } - ); - res = Utility.Random(9) switch - { - 0 => CraftResource.DullCopper, - 1 => CraftResource.ShadowIron, - 2 => CraftResource.Copper, - 3 => CraftResource.Bronze, - 4 => CraftResource.Gold, - 5 => CraftResource.Agapite, - 6 => CraftResource.Verite, - 7 => CraftResource.Valorite, - _ => CraftResource.Iron // 8 - }; + public ChaosDragoonElite(Serial serial) + : base(serial) + { + } - SwampDragon mt = new SwampDragon {HasBarding = true, BardingResource = res}; - mt.BardingHP = mt.BardingMaxHP; - mt.Rider = this; + public override string CorpseName => "a chaos dragoon elite corpse"; + public override string DefaultName => "a chaos dragoon elite"; + + public override bool HasBreath => true; + public override bool AutoDispel => true; + public override bool BardImmune => !Core.AOS; + public override bool CanRummageCorpses => true; + public override bool AlwaysMurderer => true; + public override bool ShowFameTitle => false; + + public override int GetIdleSound() => 0x2CE; + + public override int GetDeathSound() => 0x2CC; + + public override int GetHurtSound() => 0x2D1; + + public override int GetAttackSound() => 0x2C8; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.Gems); + } + + public override bool OnBeforeDeath() + { + var mount = Mount; + + if (mount != null) + { + if (mount is SwampDragon dragon) + dragon.HasBarding = false; + + mount.Rider = null; + } + + return base.OnBeforeDeath(); + } + + public override void AlterMeleeDamageTo(Mobile to, ref int damage) + { + if (to is Dragon || to is WhiteWyrm || to is SwampDragon || to is Drake || to is Nightmare || to is Hiryu || + to is LesserHiryu || to is Daemon) + damage *= 3; + } + + 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(); + } } - - public ChaosDragoonElite(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a chaos dragoon elite corpse"; - public override string DefaultName => "a chaos dragoon elite"; - - public override bool HasBreath => true; - public override bool AutoDispel => true; - public override bool BardImmune => !Core.AOS; - public override bool CanRummageCorpses => true; - public override bool AlwaysMurderer => true; - public override bool ShowFameTitle => false; - - public override int GetIdleSound() => 0x2CE; - - public override int GetDeathSound() => 0x2CC; - - public override int GetHurtSound() => 0x2D1; - - public override int GetAttackSound() => 0x2C8; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.Gems); - } - - public override bool OnBeforeDeath() - { - IMount mount = Mount; - - if (mount != null) - { - if (mount is SwampDragon dragon) - dragon.HasBarding = false; - - mount.Rider = null; - } - - return base.OnBeforeDeath(); - } - - public override void AlterMeleeDamageTo(Mobile to, ref int damage) - { - if (to is Dragon || to is WhiteWyrm || to is SwampDragon || to is Drake || to is Nightmare || to is Hiryu || - to is LesserHiryu || to is Daemon) - damage *= 3; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/LBR/Jukas/JukaLord.cs b/Projects/UOContent/Mobiles/Monsters/LBR/Jukas/JukaLord.cs index 1c48d0eb4..55fa320db 100644 --- a/Projects/UOContent/Mobiles/Monsters/LBR/Jukas/JukaLord.cs +++ b/Projects/UOContent/Mobiles/Monsters/LBR/Jukas/JukaLord.cs @@ -2,112 +2,112 @@ using Server.Items; namespace Server.Mobiles { - public class JukaLord : BaseCreature - { - [Constructible] - public JukaLord() : base(AIType.AI_Archer, FightMode.Closest, 10, 3, 0.2, 0.4) + public class JukaLord : BaseCreature { - Body = 766; - - SetStr(401, 500); - SetDex(81, 100); - SetInt(151, 200); - - SetHits(241, 300); - - SetDamage(10, 12); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 40, 50); - SetResistance(ResistanceType.Fire, 45, 50); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 20, 25); - SetResistance(ResistanceType.Energy, 40, 50); - - SetSkill(SkillName.Anatomy, 90.1, 100.0); - SetSkill(SkillName.Archery, 95.1, 100.0); - SetSkill(SkillName.Healing, 80.1, 100.0); - SetSkill(SkillName.MagicResist, 120.1, 130.0); - SetSkill(SkillName.Swords, 90.1, 100.0); - SetSkill(SkillName.Tactics, 95.1, 100.0); - SetSkill(SkillName.Wrestling, 90.1, 100.0); - - Fame = 15000; - Karma = -15000; - - VirtualArmor = 28; - - Container pack = new Backpack(); - - pack.DropItem(new Arrow(Utility.RandomMinMax(25, 35))); - pack.DropItem(new Arrow(Utility.RandomMinMax(25, 35))); - pack.DropItem(new Bandage(Utility.RandomMinMax(5, 15))); - pack.DropItem(new Bandage(Utility.RandomMinMax(5, 15))); - pack.DropItem(Loot.RandomGem()); - pack.DropItem(new ArcaneGem()); - - PackItem(pack); - - AddItem(new JukaBow()); - - // TODO: Bandage self - } - - public JukaLord(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a jukan corpse"; - public override string DefaultName => "a juka lord"; - - public override bool AlwaysMurderer => true; - public override bool BardImmune => !Core.AOS; - public override bool CanRummageCorpses => true; - public override int Meat => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.Average); - } - - public override void OnDamage(int amount, Mobile from, bool willKill) - { - if (!willKill && amount > 5 && from?.Player == true && Utility.Random(100) < 5) - { - string[] toSay = + [Constructible] + public JukaLord() : base(AIType.AI_Archer, FightMode.Closest, 10, 3, 0.2, 0.4) { - "{0}!! You will have to do better than that!", - "{0}!! Prepare to meet your doom!", - "{0}!! My armies will crush you!", - "{0}!! You will pay for that!" - }; + Body = 766; - Say(true, string.Format(toSay.RandomElement(), from.Name)); - } + SetStr(401, 500); + SetDex(81, 100); + SetInt(151, 200); - base.OnDamage(amount, from, willKill); + SetHits(241, 300); + + SetDamage(10, 12); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 40, 50); + SetResistance(ResistanceType.Fire, 45, 50); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 20, 25); + SetResistance(ResistanceType.Energy, 40, 50); + + SetSkill(SkillName.Anatomy, 90.1, 100.0); + SetSkill(SkillName.Archery, 95.1, 100.0); + SetSkill(SkillName.Healing, 80.1, 100.0); + SetSkill(SkillName.MagicResist, 120.1, 130.0); + SetSkill(SkillName.Swords, 90.1, 100.0); + SetSkill(SkillName.Tactics, 95.1, 100.0); + SetSkill(SkillName.Wrestling, 90.1, 100.0); + + Fame = 15000; + Karma = -15000; + + VirtualArmor = 28; + + Container pack = new Backpack(); + + pack.DropItem(new Arrow(Utility.RandomMinMax(25, 35))); + pack.DropItem(new Arrow(Utility.RandomMinMax(25, 35))); + pack.DropItem(new Bandage(Utility.RandomMinMax(5, 15))); + pack.DropItem(new Bandage(Utility.RandomMinMax(5, 15))); + pack.DropItem(Loot.RandomGem()); + pack.DropItem(new ArcaneGem()); + + PackItem(pack); + + AddItem(new JukaBow()); + + // TODO: Bandage self + } + + public JukaLord(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a jukan corpse"; + public override string DefaultName => "a juka lord"; + + public override bool AlwaysMurderer => true; + public override bool BardImmune => !Core.AOS; + public override bool CanRummageCorpses => true; + public override int Meat => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.Average); + } + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + if (!willKill && amount > 5 && from?.Player == true && Utility.Random(100) < 5) + { + string[] toSay = + { + "{0}!! You will have to do better than that!", + "{0}!! Prepare to meet your doom!", + "{0}!! My armies will crush you!", + "{0}!! You will pay for that!" + }; + + Say(true, string.Format(toSay.RandomElement(), from.Name)); + } + + base.OnDamage(amount, from, willKill); + } + + public override int GetIdleSound() => 0x262; + + public override int GetAngerSound() => 0x263; + + public override int GetHurtSound() => 0x1D0; + + public override int GetDeathSound() => 0x28D; + + 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(); + } } - - public override int GetIdleSound() => 0x262; - - public override int GetAngerSound() => 0x263; - - public override int GetHurtSound() => 0x1D0; - - public override int GetDeathSound() => 0x28D; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/LBR/Jukas/JukaMage.cs b/Projects/UOContent/Mobiles/Monsters/LBR/Jukas/JukaMage.cs index 8b256a252..2142798dc 100644 --- a/Projects/UOContent/Mobiles/Monsters/LBR/Jukas/JukaMage.cs +++ b/Projects/UOContent/Mobiles/Monsters/LBR/Jukas/JukaMage.cs @@ -5,189 +5,192 @@ using Server.Spells; namespace Server.Mobiles { - public class JukaMage : BaseCreature - { - private DateTime m_NextAbilityTime; - - [Constructible] - public JukaMage() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class JukaMage : BaseCreature { - Body = 765; + private DateTime m_NextAbilityTime; - SetStr(201, 300); - SetDex(71, 90); - SetInt(451, 500); - - SetHits(121, 180); - - SetDamage(4, 10); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 20, 30); - SetResistance(ResistanceType.Fire, 35, 45); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 10, 20); - SetResistance(ResistanceType.Energy, 35, 45); - - SetSkill(SkillName.Anatomy, 80.1, 90.0); - SetSkill(SkillName.EvalInt, 80.2, 100.0); - SetSkill(SkillName.Magery, 99.1, 100.0); - SetSkill(SkillName.Meditation, 80.2, 100.0); - SetSkill(SkillName.MagicResist, 140.1, 150.0); - SetSkill(SkillName.Tactics, 80.1, 90.0); - SetSkill(SkillName.Wrestling, 80.1, 90.0); - - Fame = 15000; - Karma = -15000; - - VirtualArmor = 16; - - Container bag = new Bag(); - - int count = Utility.RandomMinMax(10, 20); - - for (int i = 0; i < count; ++i) - { - Item item = Loot.RandomReagent(); - - if (item == null) - continue; - - if (!bag.TryDropItem(this, item, false)) - item.Delete(); - } - - PackItem(bag); - - PackItem(new ArcaneGem()); - - if (Core.ML && Utility.RandomDouble() < .33) - PackItem(Seed.RandomPeculiarSeed(4)); - - m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(2, 5)); - } - - public JukaMage(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a jukan corpse"; - public override string DefaultName => "a juka mage"; - - public override bool AlwaysMurderer => true; - public override bool CanRummageCorpses => true; - public override int Meat => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average, 2); - AddLoot(LootPack.MedScrolls, 2); - } - - public override int GetIdleSound() => 0x1AC; - - public override int GetAngerSound() => 0x1CD; - - public override int GetHurtSound() => 0x1D0; - - public override int GetDeathSound() => 0x28D; - - public override void OnThink() - { - if (DateTime.UtcNow >= m_NextAbilityTime) - { - JukaLord toBuff = null; - - foreach (Mobile m in GetMobilesInRange(8)) - if (m is JukaLord lord && IsFriend(lord) && lord.Combatant != null && CanBeBeneficial(lord) && - lord.CanBeginAction() && InLOS(lord)) - { - toBuff = lord; - break; - } - - if (toBuff != null) + [Constructible] + public JukaMage() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) { - if (CanBeBeneficial(toBuff) && toBuff.BeginAction()) - { - m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(30, 60)); + Body = 765; - toBuff.Say(true, "Give me the power to destroy my enemies!"); - Say(true, "Fight well my lord!"); + SetStr(201, 300); + SetDex(71, 90); + SetInt(451, 500); - DoBeneficial(toBuff); + SetHits(121, 180); - SpellHelper.Turn(this, toBuff); + SetDamage(4, 10); - int toScale = toBuff.HitsMaxSeed; + SetDamageType(ResistanceType.Physical, 100); - if (toScale > 0) + SetResistance(ResistanceType.Physical, 20, 30); + SetResistance(ResistanceType.Fire, 35, 45); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Energy, 35, 45); + + SetSkill(SkillName.Anatomy, 80.1, 90.0); + SetSkill(SkillName.EvalInt, 80.2, 100.0); + SetSkill(SkillName.Magery, 99.1, 100.0); + SetSkill(SkillName.Meditation, 80.2, 100.0); + SetSkill(SkillName.MagicResist, 140.1, 150.0); + SetSkill(SkillName.Tactics, 80.1, 90.0); + SetSkill(SkillName.Wrestling, 80.1, 90.0); + + Fame = 15000; + Karma = -15000; + + VirtualArmor = 16; + + Container bag = new Bag(); + + var count = Utility.RandomMinMax(10, 20); + + for (var i = 0; i < count; ++i) { - toBuff.HitsMaxSeed += AOS.Scale(toScale, 75); - toBuff.Hits += AOS.Scale(toScale, 75); + var item = Loot.RandomReagent(); + + if (item == null) + continue; + + if (!bag.TryDropItem(this, item, false)) + item.Delete(); } - toScale = toBuff.RawStr; + PackItem(bag); - if (toScale > 0) - toBuff.RawStr += AOS.Scale(toScale, 50); + PackItem(new ArcaneGem()); - toScale = toBuff.RawDex; + if (Core.ML && Utility.RandomDouble() < .33) + PackItem(Seed.RandomPeculiarSeed(4)); - if (toScale > 0) + m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(2, 5)); + } + + public JukaMage(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a jukan corpse"; + public override string DefaultName => "a juka mage"; + + public override bool AlwaysMurderer => true; + public override bool CanRummageCorpses => true; + public override int Meat => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average, 2); + AddLoot(LootPack.MedScrolls, 2); + } + + public override int GetIdleSound() => 0x1AC; + + public override int GetAngerSound() => 0x1CD; + + public override int GetHurtSound() => 0x1D0; + + public override int GetDeathSound() => 0x28D; + + public override void OnThink() + { + if (DateTime.UtcNow >= m_NextAbilityTime) { - toBuff.RawDex += AOS.Scale(toScale, 50); - toBuff.Stam += AOS.Scale(toScale, 50); + JukaLord toBuff = null; + + foreach (var m in GetMobilesInRange(8)) + if (m is JukaLord lord && IsFriend(lord) && lord.Combatant != null && CanBeBeneficial(lord) && + lord.CanBeginAction() && InLOS(lord)) + { + toBuff = lord; + break; + } + + if (toBuff != null) + { + if (CanBeBeneficial(toBuff) && toBuff.BeginAction()) + { + m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(30, 60)); + + toBuff.Say(true, "Give me the power to destroy my enemies!"); + Say(true, "Fight well my lord!"); + + DoBeneficial(toBuff); + + SpellHelper.Turn(this, toBuff); + + var toScale = toBuff.HitsMaxSeed; + + if (toScale > 0) + { + toBuff.HitsMaxSeed += AOS.Scale(toScale, 75); + toBuff.Hits += AOS.Scale(toScale, 75); + } + + toScale = toBuff.RawStr; + + if (toScale > 0) + toBuff.RawStr += AOS.Scale(toScale, 50); + + toScale = toBuff.RawDex; + + if (toScale > 0) + { + toBuff.RawDex += AOS.Scale(toScale, 50); + toBuff.Stam += AOS.Scale(toScale, 50); + } + + toBuff.Hits = toBuff.Hits; + toBuff.Stam = toBuff.Stam; + + toBuff.FixedParticles(0x375A, 10, 15, 5017, EffectLayer.Waist); + toBuff.PlaySound(0x1EE); + + Timer.DelayCall( + TimeSpan.FromSeconds(20.0), + Unbuff, + toBuff, + toBuff.HitsMaxSeed, + toBuff.RawStr, + toBuff.RawDex + ); + } + } + else + { + m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(2, 5)); + } } - toBuff.Hits = toBuff.Hits; - toBuff.Stam = toBuff.Stam; - - toBuff.FixedParticles(0x375A, 10, 15, 5017, EffectLayer.Waist); - toBuff.PlaySound(0x1EE); - - Timer.DelayCall( - TimeSpan.FromSeconds(20.0), - Unbuff, - toBuff, toBuff.HitsMaxSeed, toBuff.RawStr, toBuff.RawDex - ); - } + base.OnThink(); } - else + + private void Unbuff(JukaLord toDebuff, int hitsMaxSeed, int rawStr, int rawDex) { - m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(2, 5)); + toDebuff.EndAction(); + + if (toDebuff.Deleted) + return; + + toDebuff.HitsMaxSeed = hitsMaxSeed; + toDebuff.RawStr = rawStr; + toDebuff.RawDex = rawDex; + + toDebuff.Hits = toDebuff.Hits; + toDebuff.Stam = toDebuff.Stam; } - } - base.OnThink(); + 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(); + } } - - private void Unbuff(JukaLord toDebuff, int hitsMaxSeed, int rawStr, int rawDex) - { - toDebuff.EndAction(); - - if (toDebuff.Deleted) - return; - - toDebuff.HitsMaxSeed = hitsMaxSeed; - toDebuff.RawStr = rawStr; - toDebuff.RawDex = rawDex; - - toDebuff.Hits = toDebuff.Hits; - toDebuff.Stam = toDebuff.Stam; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/LBR/Jukas/JukaWarrior.cs b/Projects/UOContent/Mobiles/Monsters/LBR/Jukas/JukaWarrior.cs index db1293469..a62b0b35d 100644 --- a/Projects/UOContent/Mobiles/Monsters/LBR/Jukas/JukaWarrior.cs +++ b/Projects/UOContent/Mobiles/Monsters/LBR/Jukas/JukaWarrior.cs @@ -3,112 +3,112 @@ using Server.Items; namespace Server.Mobiles { - public class JukaWarrior : BaseCreature - { - [Constructible] - public JukaWarrior() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class JukaWarrior : BaseCreature { - Body = 764; + [Constructible] + public JukaWarrior() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 764; - SetStr(251, 350); - SetDex(61, 80); - SetInt(101, 150); + SetStr(251, 350); + SetDex(61, 80); + SetInt(101, 150); - SetHits(151, 210); + SetHits(151, 210); - SetDamage(7, 9); + SetDamage(7, 9); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 40, 50); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 25, 35); - SetResistance(ResistanceType.Poison, 10, 20); - SetResistance(ResistanceType.Energy, 10, 20); + SetResistance(ResistanceType.Physical, 40, 50); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 25, 35); + SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Energy, 10, 20); - SetSkill(SkillName.Anatomy, 80.1, 90.0); - SetSkill(SkillName.Fencing, 80.1, 90.0); - SetSkill(SkillName.Macing, 80.1, 90.0); - SetSkill(SkillName.MagicResist, 120.1, 130.0); - SetSkill(SkillName.Swords, 80.1, 90.0); - SetSkill(SkillName.Tactics, 80.1, 90.0); - SetSkill(SkillName.Wrestling, 80.1, 90.0); + SetSkill(SkillName.Anatomy, 80.1, 90.0); + SetSkill(SkillName.Fencing, 80.1, 90.0); + SetSkill(SkillName.Macing, 80.1, 90.0); + SetSkill(SkillName.MagicResist, 120.1, 130.0); + SetSkill(SkillName.Swords, 80.1, 90.0); + SetSkill(SkillName.Tactics, 80.1, 90.0); + SetSkill(SkillName.Wrestling, 80.1, 90.0); - Fame = 10000; - Karma = -10000; + Fame = 10000; + Karma = -10000; - VirtualArmor = 22; + VirtualArmor = 22; - if (Utility.RandomDouble() < 0.1) - PackItem(new ArcaneGem()); + if (Utility.RandomDouble() < 0.1) + PackItem(new ArcaneGem()); + } + + public JukaWarrior(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a jukan corpse"; + public override string DefaultName => "a juka warrior"; + + public override bool AlwaysMurderer => true; + public override bool CanRummageCorpses => true; + public override int Meat => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Meager); + AddLoot(LootPack.Gems, 1); + } + + public override int GetIdleSound() => 0x1AC; + + public override int GetAngerSound() => 0x1CD; + + public override int GetHurtSound() => 0x1D0; + + public override int GetDeathSound() => 0x28D; + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomDouble() > 0.2) + return; + + switch (Utility.Random(3)) + { + case 0: + { + defender.SendLocalizedMessage(1004014); // You have been stunned! + defender.Freeze(TimeSpan.FromSeconds(4.0)); + break; + } + case 1: + { + defender.SendAsciiMessage("You have been hit by a paralyzing blow!"); + defender.Freeze(TimeSpan.FromSeconds(3.0)); + break; + } + case 2: + { + AOS.Damage(defender, this, Utility.Random(10, 5), 100, 0, 0, 0, 0); + defender.SendAsciiMessage("You have been hit by a critical strike!"); + break; + } + } + } + + 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(); + } } - - public JukaWarrior(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a jukan corpse"; - public override string DefaultName => "a juka warrior"; - - public override bool AlwaysMurderer => true; - public override bool CanRummageCorpses => true; - public override int Meat => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Meager); - AddLoot(LootPack.Gems, 1); - } - - public override int GetIdleSound() => 0x1AC; - - public override int GetAngerSound() => 0x1CD; - - public override int GetHurtSound() => 0x1D0; - - public override int GetDeathSound() => 0x28D; - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (Utility.RandomDouble() > 0.2) - return; - - switch (Utility.Random(3)) - { - case 0: - { - defender.SendLocalizedMessage(1004014); // You have been stunned! - defender.Freeze(TimeSpan.FromSeconds(4.0)); - break; - } - case 1: - { - defender.SendAsciiMessage("You have been hit by a paralyzing blow!"); - defender.Freeze(TimeSpan.FromSeconds(3.0)); - break; - } - case 2: - { - AOS.Damage(defender, this, Utility.Random(10, 5), 100, 0, 0, 0, 0); - defender.SendAsciiMessage("You have been hit by a critical strike!"); - break; - } - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/LBR/Meers/EnragedCreatures.cs b/Projects/UOContent/Mobiles/Monsters/LBR/Meers/EnragedCreatures.cs index 4160edf2c..11eaae8a3 100644 --- a/Projects/UOContent/Mobiles/Monsters/LBR/Meers/EnragedCreatures.cs +++ b/Projects/UOContent/Mobiles/Monsters/LBR/Meers/EnragedCreatures.cs @@ -2,243 +2,243 @@ using Server.Network; namespace Server.Mobiles { - public class EnragedRabbit : BaseEnraged - { - public EnragedRabbit(Mobile summoner) : base(summoner) => Body = 0xcd; - - public EnragedRabbit(Serial serial) : base(serial) + public class EnragedRabbit : BaseEnraged { + public EnragedRabbit(Mobile summoner) : base(summoner) => Body = 0xcd; + + public EnragedRabbit(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a hare corpse"; + public override string DefaultName => "a rabbit"; + + public override int GetAttackSound() => 0xC9; + + public override int GetHurtSound() => 0xCA; + + public override int GetDeathSound() => 0xCB; + + 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(); + } } - public override string CorpseName => "a hare corpse"; - public override string DefaultName => "a rabbit"; - - public override int GetAttackSound() => 0xC9; - - public override int GetHurtSound() => 0xCA; - - public override int GetDeathSound() => 0xCB; - - public override void Serialize(IGenericWriter writer) + public class EnragedHart : BaseEnraged { - base.Serialize(writer); - writer.Write(0); + public EnragedHart(Mobile summoner) : base(summoner) => Body = 0xea; + + public EnragedHart(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a deer corpse"; + public override string DefaultName => "a great hart"; + + public override int GetAttackSound() => 0x82; + + public override int GetHurtSound() => 0x83; + + public override int GetDeathSound() => 0x84; + + 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(); + } } - public override void Deserialize(IGenericReader reader) + public class EnragedHind : BaseEnraged { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } + public EnragedHind(Mobile summoner) : base(summoner) => Body = 0xed; - public class EnragedHart : BaseEnraged - { - public EnragedHart(Mobile summoner) : base(summoner) => Body = 0xea; + public EnragedHind(Serial serial) : base(serial) + { + } - public EnragedHart(Serial serial) : base(serial) - { + public override string CorpseName => "a deer corpse"; + public override string DefaultName => "a hind"; + + public override int GetAttackSound() => 0x82; + + public override int GetHurtSound() => 0x83; + + public override int GetDeathSound() => 0x84; + + 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(); + } } - public override string CorpseName => "a deer corpse"; - public override string DefaultName => "a great hart"; - - public override int GetAttackSound() => 0x82; - - public override int GetHurtSound() => 0x83; - - public override int GetDeathSound() => 0x84; - - public override void Serialize(IGenericWriter writer) + public class EnragedBlackBear : BaseEnraged { - base.Serialize(writer); - writer.Write(0); + public EnragedBlackBear(Mobile summoner) : base(summoner) + { + Body = 0xd3; + BaseSoundID = 0xa3; + } + + public EnragedBlackBear(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a bear corpse"; + public override string DefaultName => "a black bear"; + + 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(); + } } - public override void Deserialize(IGenericReader reader) + public class EnragedEagle : BaseEnraged { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } + public EnragedEagle(Mobile summoner) : base(summoner) + { + Body = 0x5; + BaseSoundID = 0x2ee; + } - public class EnragedHind : BaseEnraged - { - public EnragedHind(Mobile summoner) : base(summoner) => Body = 0xed; + public EnragedEagle(Serial serial) : base(serial) + { + } - public EnragedHind(Serial serial) : base(serial) - { + public override string CorpseName => "an eagle corpse"; + public override string DefaultName => "an eagle"; + + 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(); + } } - public override string CorpseName => "a deer corpse"; - public override string DefaultName => "a hind"; - - public override int GetAttackSound() => 0x82; - - public override int GetHurtSound() => 0x83; - - public override int GetDeathSound() => 0x84; - - public override void Serialize(IGenericWriter writer) + public class BaseEnraged : BaseCreature { - base.Serialize(writer); - writer.Write(0); + public BaseEnraged(Mobile summoner) + : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + SetStr(50, 200); + SetDex(50, 200); + SetHits(50, 200); + SetStam(50, 200); + + /* + On OSI, all stats are random 50-200, but + str is never less than hits, and dex is never + less than stam. + */ + + if (Str < Hits) + Str = Hits; + if (Dex < Stam) + Dex = Stam; + + Karma = -1000; + Tamable = false; + + SummonMaster = summoner; + } + + public BaseEnraged(Serial serial) : base(serial) + { + } + + public override void OnThink() + { + if (SummonMaster?.Deleted != false) + { + Delete(); + } + /* + On OSI, without combatant, they behave as if they have been + given "come" command, ie they wander towards their summoner, + but never actually "follow". + */ + else if (!Combat(this)) + { + AIObject?.MoveTo(SummonMaster, false, 5); + } + /* + On OSI, if the summon attacks a mobile, the summoner meer also + attacks them, regardless of karma, etc. as long as the combatant + is a player or controlled/summoned, and the summoner is not already + engaged in combat. + */ + else if (!Combat(SummonMaster)) + { + if (Combatant.Player || Combatant is BaseCreature bc && (bc.Controlled || bc.SummonMaster != null)) + SummonMaster.Combatant = Combatant; + } + else + { + base.OnThink(); + } + } + + private bool Combat(Mobile mobile) + { + var combatant = mobile.Combatant; + return combatant?.Deleted == false && !combatant.IsDeadBondedPet && combatant.Alive; + } + + public override void OnSingleClick(Mobile from) + { + base.OnSingleClick(from); + PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1060768, from.NetState); // enraged + } + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + list.Add(1060768); // enraged + } + + 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(); + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class EnragedBlackBear : BaseEnraged - { - public EnragedBlackBear(Mobile summoner) : base(summoner) - { - Body = 0xd3; - BaseSoundID = 0xa3; - } - - public EnragedBlackBear(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a bear corpse"; - public override string DefaultName => "a black bear"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class EnragedEagle : BaseEnraged - { - public EnragedEagle(Mobile summoner) : base(summoner) - { - Body = 0x5; - BaseSoundID = 0x2ee; - } - - public EnragedEagle(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an eagle corpse"; - public override string DefaultName => "an eagle"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class BaseEnraged : BaseCreature - { - public BaseEnraged(Mobile summoner) - : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) - { - SetStr(50, 200); - SetDex(50, 200); - SetHits(50, 200); - SetStam(50, 200); - - /* - On OSI, all stats are random 50-200, but - str is never less than hits, and dex is never - less than stam. - */ - - if (Str < Hits) - Str = Hits; - if (Dex < Stam) - Dex = Stam; - - Karma = -1000; - Tamable = false; - - SummonMaster = summoner; - } - - public BaseEnraged(Serial serial) : base(serial) - { - } - - public override void OnThink() - { - if (SummonMaster?.Deleted != false) - { - Delete(); - } - /* - On OSI, without combatant, they behave as if they have been - given "come" command, ie they wander towards their summoner, - but never actually "follow". - */ - else if (!Combat(this)) - { - AIObject?.MoveTo(SummonMaster, false, 5); - } - /* - On OSI, if the summon attacks a mobile, the summoner meer also - attacks them, regardless of karma, etc. as long as the combatant - is a player or controlled/summoned, and the summoner is not already - engaged in combat. - */ - else if (!Combat(SummonMaster)) - { - if (Combatant.Player || (Combatant is BaseCreature bc && (bc.Controlled || bc.SummonMaster != null))) - SummonMaster.Combatant = Combatant; - } - else - { - base.OnThink(); - } - } - - private bool Combat(Mobile mobile) - { - Mobile combatant = mobile.Combatant; - return combatant?.Deleted == false && !combatant.IsDeadBondedPet && combatant.Alive; - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1060768, from.NetState); // enraged - } - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - list.Add(1060768); // enraged - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/LBR/Meers/MeerCaptain.cs b/Projects/UOContent/Mobiles/Monsters/LBR/Meers/MeerCaptain.cs index 08d5ff04a..4308a7eb8 100644 --- a/Projects/UOContent/Mobiles/Monsters/LBR/Meers/MeerCaptain.cs +++ b/Projects/UOContent/Mobiles/Monsters/LBR/Meers/MeerCaptain.cs @@ -4,154 +4,154 @@ using Server.Spells; namespace Server.Mobiles { - public class MeerCaptain : BaseCreature - { - private DateTime m_NextAbilityTime; - - [Constructible] - public MeerCaptain() : base(AIType.AI_Archer, FightMode.Evil, 10, 1, 0.2, 0.4) + public class MeerCaptain : BaseCreature { - Body = 773; + private DateTime m_NextAbilityTime; - SetStr(96, 110); - SetDex(186, 200); - SetInt(96, 110); - - SetHits(58, 66); - - SetDamage(5, 15); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 10, 20); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 35, 45); - SetResistance(ResistanceType.Energy, 35, 45); - - SetSkill(SkillName.Archery, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 91.0, 100.0); - SetSkill(SkillName.Swords, 90.1, 100.0); - SetSkill(SkillName.Tactics, 91.0, 100.0); - SetSkill(SkillName.Wrestling, 80.9, 89.9); - - Fame = 2000; - Karma = 5000; - - VirtualArmor = 28; - - Container pack = new Backpack(); - - pack.DropItem(new Bolt(Utility.RandomMinMax(10, 20))); - pack.DropItem(new Bolt(Utility.RandomMinMax(10, 20))); - - AddItem( - Utility.Random(6) switch + [Constructible] + public MeerCaptain() : base(AIType.AI_Archer, FightMode.Evil, 10, 1, 0.2, 0.4) { - 0 => new Longsword(), - 1 => new Cutlass(), - 2 => new Broadsword(), - 3 => new Katana(), - 4 => new Scimitar(), - _ => new VikingSword() // 5 - } - ); + Body = 773; - Container bag = new Bag(); + SetStr(96, 110); + SetDex(186, 200); + SetInt(96, 110); - int count = Utility.RandomMinMax(10, 20); + SetHits(58, 66); - for (int i = 0; i < count; ++i) - { - Item item = Loot.RandomReagent(); + SetDamage(5, 15); - if (item == null) - continue; + SetDamageType(ResistanceType.Physical, 100); - if (!bag.TryDropItem(this, item, false)) - item.Delete(); - } + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 10, 20); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 35, 45); + SetResistance(ResistanceType.Energy, 35, 45); - pack.DropItem(bag); + SetSkill(SkillName.Archery, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 91.0, 100.0); + SetSkill(SkillName.Swords, 90.1, 100.0); + SetSkill(SkillName.Tactics, 91.0, 100.0); + SetSkill(SkillName.Wrestling, 80.9, 89.9); - AddItem(new Crossbow()); - PackItem(pack); + Fame = 2000; + Karma = 5000; - m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(2, 5)); - } + VirtualArmor = 28; - public MeerCaptain(Serial serial) : base(serial) - { - } + Container pack = new Backpack(); - public override string CorpseName => "a meer corpse"; - public override string DefaultName => "a meer captain"; + pack.DropItem(new Bolt(Utility.RandomMinMax(10, 20))); + pack.DropItem(new Bolt(Utility.RandomMinMax(10, 20))); - public override bool BardImmune => !Core.AOS; - public override bool CanRummageCorpses => true; + AddItem( + Utility.Random(6) switch + { + 0 => new Longsword(), + 1 => new Cutlass(), + 2 => new Broadsword(), + 3 => new Katana(), + 4 => new Scimitar(), + _ => new VikingSword() // 5 + } + ); - public override bool InitialInnocent => true; + Container bag = new Bag(); - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } + var count = Utility.RandomMinMax(10, 20); - public override int GetHurtSound() => 0x14D; + for (var i = 0; i < count; ++i) + { + var item = Loot.RandomReagent(); - public override int GetDeathSound() => 0x314; + if (item == null) + continue; - public override int GetAttackSound() => 0x75; + if (!bag.TryDropItem(this, item, false)) + item.Delete(); + } - public override void OnThink() - { - if (Combatant != null && MagicDamageAbsorb < 1) - { - MagicDamageAbsorb = Utility.RandomMinMax(5, 7); - FixedParticles(0x375A, 10, 15, 5037, EffectLayer.Waist); - PlaySound(0x1E9); - } + pack.DropItem(bag); - if (DateTime.UtcNow >= m_NextAbilityTime) - { - m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(10, 15)); + AddItem(new Crossbow()); + PackItem(pack); - IPooledEnumerable eable = GetMobilesInRange(8); - - foreach (Mobile m in eable) - { - if (!(m is MeerWarrior) || !IsFriend(m) || !CanBeBeneficial(m) || m.Hits >= m.HitsMax || m.Poisoned || - MortalStrike.IsWounded(m)) - continue; - - DoBeneficial(m); - - int toHeal = Utility.RandomMinMax(20, 30); - - SpellHelper.Turn(this, m); - - m.Heal(toHeal, this); - - m.FixedParticles(0x376A, 9, 32, 5030, EffectLayer.Waist); - m.PlaySound(0x202); + m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(2, 5)); } - eable.Free(); - } + public MeerCaptain(Serial serial) : base(serial) + { + } - base.OnThink(); - } + public override string CorpseName => "a meer corpse"; + public override string DefaultName => "a meer captain"; - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } + public override bool BardImmune => !Core.AOS; + public override bool CanRummageCorpses => true; - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); + public override bool InitialInnocent => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + public override int GetHurtSound() => 0x14D; + + public override int GetDeathSound() => 0x314; + + public override int GetAttackSound() => 0x75; + + public override void OnThink() + { + if (Combatant != null && MagicDamageAbsorb < 1) + { + MagicDamageAbsorb = Utility.RandomMinMax(5, 7); + FixedParticles(0x375A, 10, 15, 5037, EffectLayer.Waist); + PlaySound(0x1E9); + } + + if (DateTime.UtcNow >= m_NextAbilityTime) + { + m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(10, 15)); + + var eable = GetMobilesInRange(8); + + foreach (var m in eable) + { + if (!(m is MeerWarrior) || !IsFriend(m) || !CanBeBeneficial(m) || m.Hits >= m.HitsMax || m.Poisoned || + MortalStrike.IsWounded(m)) + continue; + + DoBeneficial(m); + + var toHeal = Utility.RandomMinMax(20, 30); + + SpellHelper.Turn(this, m); + + m.Heal(toHeal, this); + + m.FixedParticles(0x376A, 9, 32, 5030, EffectLayer.Waist); + m.PlaySound(0x202); + } + + eable.Free(); + } + + base.OnThink(); + } + + 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(); + } } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/LBR/Meers/MeerEternal.cs b/Projects/UOContent/Mobiles/Monsters/LBR/Meers/MeerEternal.cs index dd0f0d540..0105fa7c7 100644 --- a/Projects/UOContent/Mobiles/Monsters/LBR/Meers/MeerEternal.cs +++ b/Projects/UOContent/Mobiles/Monsters/LBR/Meers/MeerEternal.cs @@ -1,202 +1,203 @@ using System; -using System.Collections.Generic; using System.Linq; namespace Server.Mobiles { - public class MeerEternal : BaseCreature - { - private DateTime m_NextAbilityTime; - - [Constructible] - public MeerEternal() : base(AIType.AI_Mage, FightMode.Evil, 10, 1, 0.2, 0.4) + public class MeerEternal : BaseCreature { - Body = 772; + private DateTime m_NextAbilityTime; - SetStr(416, 505); - SetDex(146, 165); - SetInt(566, 655); - - SetHits(250, 303); - - SetDamage(11, 13); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 15, 25); - SetResistance(ResistanceType.Cold, 45, 55); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 30, 40); - - SetSkill(SkillName.EvalInt, 90.1, 100.0); - SetSkill(SkillName.Magery, 90.1, 100.0); - SetSkill(SkillName.Meditation, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 150.5, 200.0); - SetSkill(SkillName.Tactics, 50.1, 70.0); - SetSkill(SkillName.Wrestling, 60.1, 80.0); - - Fame = 18000; - Karma = 18000; - - VirtualArmor = 34; - - m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(2, 5)); - } - - public MeerEternal(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a meer's corpse"; - public override string DefaultName => "a meer eternal"; - - public override bool AutoDispel => true; - public override bool BardImmune => !Core.AOS; - public override bool CanRummageCorpses => true; - public override Poison PoisonImmune => Poison.Lethal; - public override int TreasureMapLevel => Core.AOS ? 5 : 4; - - public override bool InitialInnocent => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 2); - AddLoot(LootPack.MedScrolls, 2); - AddLoot(LootPack.HighScrolls, 2); - } - - public override int GetHurtSound() => 0x167; - - public override int GetDeathSound() => 0xBC; - - public override int GetAttackSound() => 0x28B; - - private void DoAreaLeech() - { - m_NextAbilityTime += TimeSpan.FromSeconds(2.5); - - Say(true, "Beware, mortals! You have provoked my wrath!"); - FixedParticles(0x376A, 10, 10, 9537, 33, 0, EffectLayer.Waist); - - Timer.DelayCall(TimeSpan.FromSeconds(5.0), DoAreaLeech_Finish); - } - - private void DoAreaLeech_Finish() - { - IPooledEnumerable eable = GetMobilesInRange(6); - List list = eable.Where(m => CanBeHarmful(m) && IsEnemy(m)).ToList(); - eable.Free(); - - if (list.Count == 0) - { - Say(true, "Bah! You have escaped my grasp this time, mortal!"); - } - else - { - double scalar; - - if (list.Count == 1) - scalar = 0.75; - else if (list.Count == 2) - scalar = 0.50; - else - scalar = 0.25; - - for (int i = 0; i < list.Count; ++i) + [Constructible] + public MeerEternal() : base(AIType.AI_Mage, FightMode.Evil, 10, 1, 0.2, 0.4) { - Mobile m = list[i]; + Body = 772; - int damage = (int)(m.Hits * scalar) + Utility.RandomMinMax(-5, 5); + SetStr(416, 505); + SetDex(146, 165); + SetInt(566, 655); - m.MovingParticles(this, 0x36F4, 1, 0, false, false, 32, 0, 9535, 1, 0, (EffectLayer)255, 0x100); - m.MovingParticles(this, 0x0001, 1, 0, false, true, 32, 0, 9535, 9536, 0, (EffectLayer)255, 0); + SetHits(250, 303); - DoHarmful(m); - Hits += AOS.Damage(m, this, Math.Max(damage, 1), 100, 0, 0, 0, 0); + SetDamage(11, 13); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 15, 25); + SetResistance(ResistanceType.Cold, 45, 55); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 30, 40); + + SetSkill(SkillName.EvalInt, 90.1, 100.0); + SetSkill(SkillName.Magery, 90.1, 100.0); + SetSkill(SkillName.Meditation, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 150.5, 200.0); + SetSkill(SkillName.Tactics, 50.1, 70.0); + SetSkill(SkillName.Wrestling, 60.1, 80.0); + + Fame = 18000; + Karma = 18000; + + VirtualArmor = 34; + + m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(2, 5)); } - Say(true, "If I cannot cleanse thy soul, I will destroy it!"); - } - } - - private void DoFocusedLeech(Mobile combatant, string message) - { - Say(true, message); - - Timer.DelayCall(TimeSpan.FromSeconds(0.5), DoFocusedLeech_Stage1, combatant); - } - - private void DoFocusedLeech_Stage1(Mobile combatant) - { - if (CanBeHarmful(combatant)) - { - MovingParticles(combatant, 0x36FA, 1, 0, false, false, 1108, 0, 9533, 1, 0, (EffectLayer)255, 0x100); - MovingParticles(combatant, 0x0001, 1, 0, false, true, 1108, 0, 9533, 9534, 0, (EffectLayer)255, 0); - PlaySound(0x1FB); - - Timer.DelayCall(TimeSpan.FromSeconds(1.0), DoFocusedLeech_Stage2, combatant); - } - } - - private void DoFocusedLeech_Stage2(Mobile combatant) - { - if (CanBeHarmful(combatant)) - { - combatant.MovingParticles(this, 0x36F4, 1, 0, false, false, 32, 0, 9535, 1, 0, (EffectLayer)255, 0x100); - combatant.MovingParticles(this, 0x0001, 1, 0, false, true, 32, 0, 9535, 9536, 0, (EffectLayer)255, 0); - - PlaySound(0x209); - DoHarmful(combatant); - Hits += AOS.Damage(combatant, this, Utility.RandomMinMax(30, 40) - (Core.AOS ? 0 : 10), 100, 0, 0, 0, 0); - } - } - - public override void OnThink() - { - if (DateTime.UtcNow >= m_NextAbilityTime) - { - Mobile combatant = Combatant; - - if (combatant != null && combatant.Map == Map && combatant.InRange(this, 12)) + public MeerEternal(Serial serial) : base(serial) { - m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(10, 15)); - - int ability = Utility.Random(4); - - switch (ability) - { - case 0: - DoFocusedLeech(combatant, "Thine essence will fill my withering body with strength!"); - break; - case 1: - DoFocusedLeech(combatant, - "I rebuke thee, worm, and cleanse thy vile spirit of its tainted blood!"); - break; - case 2: - DoFocusedLeech(combatant, "I devour your life's essence to strengthen my resolve!"); - break; - case 3: - DoAreaLeech(); - break; - // TODO: Resurrect ability - } } - } - base.OnThink(); - } + public override string CorpseName => "a meer's corpse"; + public override string DefaultName => "a meer eternal"; - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } + public override bool AutoDispel => true; + public override bool BardImmune => !Core.AOS; + public override bool CanRummageCorpses => true; + public override Poison PoisonImmune => Poison.Lethal; + public override int TreasureMapLevel => Core.AOS ? 5 : 4; - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); + public override bool InitialInnocent => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 2); + AddLoot(LootPack.MedScrolls, 2); + AddLoot(LootPack.HighScrolls, 2); + } + + public override int GetHurtSound() => 0x167; + + public override int GetDeathSound() => 0xBC; + + public override int GetAttackSound() => 0x28B; + + private void DoAreaLeech() + { + m_NextAbilityTime += TimeSpan.FromSeconds(2.5); + + Say(true, "Beware, mortals! You have provoked my wrath!"); + FixedParticles(0x376A, 10, 10, 9537, 33, 0, EffectLayer.Waist); + + Timer.DelayCall(TimeSpan.FromSeconds(5.0), DoAreaLeech_Finish); + } + + private void DoAreaLeech_Finish() + { + var eable = GetMobilesInRange(6); + var list = eable.Where(m => CanBeHarmful(m) && IsEnemy(m)).ToList(); + eable.Free(); + + if (list.Count == 0) + { + Say(true, "Bah! You have escaped my grasp this time, mortal!"); + } + else + { + double scalar; + + if (list.Count == 1) + scalar = 0.75; + else if (list.Count == 2) + scalar = 0.50; + else + scalar = 0.25; + + for (var i = 0; i < list.Count; ++i) + { + var m = list[i]; + + var damage = (int)(m.Hits * scalar) + Utility.RandomMinMax(-5, 5); + + m.MovingParticles(this, 0x36F4, 1, 0, false, false, 32, 0, 9535, 1, 0, (EffectLayer)255, 0x100); + m.MovingParticles(this, 0x0001, 1, 0, false, true, 32, 0, 9535, 9536, 0, (EffectLayer)255, 0); + + DoHarmful(m); + Hits += AOS.Damage(m, this, Math.Max(damage, 1), 100, 0, 0, 0, 0); + } + + Say(true, "If I cannot cleanse thy soul, I will destroy it!"); + } + } + + private void DoFocusedLeech(Mobile combatant, string message) + { + Say(true, message); + + Timer.DelayCall(TimeSpan.FromSeconds(0.5), DoFocusedLeech_Stage1, combatant); + } + + private void DoFocusedLeech_Stage1(Mobile combatant) + { + if (CanBeHarmful(combatant)) + { + MovingParticles(combatant, 0x36FA, 1, 0, false, false, 1108, 0, 9533, 1, 0, (EffectLayer)255, 0x100); + MovingParticles(combatant, 0x0001, 1, 0, false, true, 1108, 0, 9533, 9534, 0, (EffectLayer)255, 0); + PlaySound(0x1FB); + + Timer.DelayCall(TimeSpan.FromSeconds(1.0), DoFocusedLeech_Stage2, combatant); + } + } + + private void DoFocusedLeech_Stage2(Mobile combatant) + { + if (CanBeHarmful(combatant)) + { + combatant.MovingParticles(this, 0x36F4, 1, 0, false, false, 32, 0, 9535, 1, 0, (EffectLayer)255, 0x100); + combatant.MovingParticles(this, 0x0001, 1, 0, false, true, 32, 0, 9535, 9536, 0, (EffectLayer)255, 0); + + PlaySound(0x209); + DoHarmful(combatant); + Hits += AOS.Damage(combatant, this, Utility.RandomMinMax(30, 40) - (Core.AOS ? 0 : 10), 100, 0, 0, 0, 0); + } + } + + public override void OnThink() + { + if (DateTime.UtcNow >= m_NextAbilityTime) + { + var combatant = Combatant; + + if (combatant != null && combatant.Map == Map && combatant.InRange(this, 12)) + { + m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(10, 15)); + + var ability = Utility.Random(4); + + switch (ability) + { + case 0: + DoFocusedLeech(combatant, "Thine essence will fill my withering body with strength!"); + break; + case 1: + DoFocusedLeech( + combatant, + "I rebuke thee, worm, and cleanse thy vile spirit of its tainted blood!" + ); + break; + case 2: + DoFocusedLeech(combatant, "I devour your life's essence to strengthen my resolve!"); + break; + case 3: + DoAreaLeech(); + break; + // TODO: Resurrect ability + } + } + } + + base.OnThink(); + } + + 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(); + } } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/LBR/Meers/MeerMage.cs b/Projects/UOContent/Mobiles/Monsters/LBR/Meers/MeerMage.cs index ae70a3ab9..bf0792677 100644 --- a/Projects/UOContent/Mobiles/Monsters/LBR/Meers/MeerMage.cs +++ b/Projects/UOContent/Mobiles/Monsters/LBR/Meers/MeerMage.cs @@ -5,193 +5,214 @@ using Server.Network; namespace Server.Mobiles { - public class MeerMage : BaseCreature - { - private static readonly Dictionary m_Table = new Dictionary(); - - private DateTime m_NextAbilityTime; - - [Constructible] - public MeerMage() : base(AIType.AI_Mage, FightMode.Evil, 10, 1, 0.2, 0.4) + public class MeerMage : BaseCreature { - Body = 770; + private static readonly Dictionary m_Table = new Dictionary(); - SetStr(171, 200); - SetDex(126, 145); - SetInt(276, 305); + private DateTime m_NextAbilityTime; - SetHits(103, 120); - - SetDamage(24, 26); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 15, 25); - SetResistance(ResistanceType.Cold, 50); - SetResistance(ResistanceType.Poison, 25, 35); - SetResistance(ResistanceType.Energy, 25, 35); - - SetSkill(SkillName.EvalInt, 100.0); - SetSkill(SkillName.Magery, 70.1, 80.0); - SetSkill(SkillName.Meditation, 85.1, 95.0); - SetSkill(SkillName.MagicResist, 80.1, 100.0); - SetSkill(SkillName.Tactics, 70.1, 90.0); - SetSkill(SkillName.Wrestling, 60.1, 80.0); - - Fame = 8000; - Karma = 8000; - - VirtualArmor = 16; - - m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(2, 5)); - } - - public MeerMage(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a meer's corpse"; - public override string DefaultName => "a meer mage"; - - public override bool AutoDispel => true; - public override Poison PoisonImmune => Poison.Lethal; - public override bool CanRummageCorpses => true; - public override int TreasureMapLevel => 3; - - public override bool InitialInnocent => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.MedScrolls, 2); - // TODO: Daemon bone ... - } - - public override int GetHurtSound() => 0x14D; - - public override int GetDeathSound() => 0x314; - - public override int GetAttackSound() => 0x75; - - public override void OnThink() - { - if (DateTime.UtcNow >= m_NextAbilityTime) - { - Mobile combatant = Combatant; - - if (combatant != null && combatant.Map == Map && combatant.InRange(this, 12) && IsEnemy(combatant) && - !UnderEffect(combatant)) + [Constructible] + public MeerMage() : base(AIType.AI_Mage, FightMode.Evil, 10, 1, 0.2, 0.4) { - m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(20, 30)); + Body = 770; - if (combatant is BaseCreature bc) - if (bc.Controlled && bc.ControlMaster?.Deleted == false && bc.ControlMaster.Alive) - if (bc.ControlMaster.Map == Map && bc.ControlMaster.InRange(this, 12) && - !UnderEffect(bc.ControlMaster)) - Combatant = combatant = bc.ControlMaster; + SetStr(171, 200); + SetDex(126, 145); + SetInt(276, 305); - if (Utility.RandomDouble() < .1) - { - int[][] coord = + SetHits(103, 120); + + SetDamage(24, 26); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 15, 25); + SetResistance(ResistanceType.Cold, 50); + SetResistance(ResistanceType.Poison, 25, 35); + SetResistance(ResistanceType.Energy, 25, 35); + + SetSkill(SkillName.EvalInt, 100.0); + SetSkill(SkillName.Magery, 70.1, 80.0); + SetSkill(SkillName.Meditation, 85.1, 95.0); + SetSkill(SkillName.MagicResist, 80.1, 100.0); + SetSkill(SkillName.Tactics, 70.1, 90.0); + SetSkill(SkillName.Wrestling, 60.1, 80.0); + + Fame = 8000; + Karma = 8000; + + VirtualArmor = 16; + + m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(2, 5)); + } + + public MeerMage(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a meer's corpse"; + public override string DefaultName => "a meer mage"; + + public override bool AutoDispel => true; + public override Poison PoisonImmune => Poison.Lethal; + public override bool CanRummageCorpses => true; + public override int TreasureMapLevel => 3; + + public override bool InitialInnocent => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.MedScrolls, 2); + // TODO: Daemon bone ... + } + + public override int GetHurtSound() => 0x14D; + + public override int GetDeathSound() => 0x314; + + public override int GetAttackSound() => 0x75; + + public override void OnThink() + { + if (DateTime.UtcNow >= m_NextAbilityTime) { - new[] { -4, -6 }, new[] { 4, -6 }, new[] { 0, -8 }, new[] { -5, 5 }, new[] { 5, 5 } - }; + var combatant = Combatant; - for (int i = 0; i < 5; i++) - { - int x = combatant.X + coord[i][0]; - int y = combatant.Y + coord[i][1]; + if (combatant != null && combatant.Map == Map && combatant.InRange(this, 12) && IsEnemy(combatant) && + !UnderEffect(combatant)) + { + m_NextAbilityTime = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(20, 30)); - Point3D loc = new Point3D(x, y, combatant.Map.GetAverageZ(x, y)); + if (combatant is BaseCreature bc) + if (bc.Controlled && bc.ControlMaster?.Deleted == false && bc.ControlMaster.Alive) + if (bc.ControlMaster.Map == Map && bc.ControlMaster.InRange(this, 12) && + !UnderEffect(bc.ControlMaster)) + Combatant = combatant = bc.ControlMaster; - if (!combatant.Map.CanSpawnMobile(loc)) - continue; + if (Utility.RandomDouble() < .1) + { + int[][] coord = + { + new[] { -4, -6 }, new[] { 4, -6 }, new[] { 0, -8 }, new[] { -5, 5 }, new[] { 5, 5 } + }; - var rabid = i switch - { - 0 => (BaseCreature)new EnragedRabbit(this), - 1 => new EnragedHind(this), - 2 => new EnragedHart(this), - 3 => new EnragedBlackBear(this), - _ => new EnragedEagle(this) - }; + for (var i = 0; i < 5; i++) + { + var x = combatant.X + coord[i][0]; + var y = combatant.Y + coord[i][1]; - rabid.FocusMob = combatant; - rabid.MoveToWorld(loc, combatant.Map); + var loc = new Point3D(x, y, combatant.Map.GetAverageZ(x, y)); + + if (!combatant.Map.CanSpawnMobile(loc)) + continue; + + var rabid = i switch + { + 0 => (BaseCreature)new EnragedRabbit(this), + 1 => new EnragedHind(this), + 2 => new EnragedHart(this), + 3 => new EnragedBlackBear(this), + _ => new EnragedEagle(this) + }; + + rabid.FocusMob = combatant; + rabid.MoveToWorld(loc, combatant.Map); + } + + Say( + 1071932 + ); // Creatures of the forest, I call to thee! Aid me in the fight against all that is evil! + } + else if (combatant.Player) + { + var count = 0; + + Say(true, "I call a plague of insects to sting your flesh!"); + m_Table[combatant] = Timer.DelayCall( + TimeSpan.FromSeconds(0.5), + TimeSpan.FromSeconds(7.0), + () => DoEffect(combatant, count++) + ); + } + } } - Say(1071932); // Creatures of the forest, I call to thee! Aid me in the fight against all that is evil! - } - else if (combatant.Player) - { - int count = 0; - - Say(true, "I call a plague of insects to sting your flesh!"); - m_Table[combatant] = Timer.DelayCall(TimeSpan.FromSeconds(0.5), TimeSpan.FromSeconds(7.0), - () => DoEffect(combatant, count++)); - } + base.OnThink(); } - } - base.OnThink(); - } + public static bool UnderEffect(Mobile m) => m_Table.ContainsKey(m); - public static bool UnderEffect(Mobile m) => m_Table.ContainsKey(m); - - public static void StopEffect(Mobile m, bool message) - { - if (m_Table.TryGetValue(m, out Timer timer)) - { - if (message) - m.PublicOverheadMessage(MessageType.Emote, m.SpeechHue, true, - "* The open flame begins to scatter the swarm of insects *"); - - timer.Stop(); - m_Table.Remove(m); - } - } - - public void DoEffect(Mobile m, int count) - { - if (!m.Alive) - StopEffect(m, false); - else - { - if (m.FindItemOnLayer(Layer.TwoHanded) is Torch torch && torch.Burning) - StopEffect(m, true); - else + public static void StopEffect(Mobile m, bool message) { - if (count % 4 == 0) - { - m.LocalOverheadMessage(MessageType.Emote, m.SpeechHue, true, - "* The swarm of insects bites and stings your flesh! *"); - m.NonlocalOverheadMessage(MessageType.Emote, m.SpeechHue, true, - $"* {m.Name} is stung by a swarm of insects *"); - } + if (m_Table.TryGetValue(m, out var timer)) + { + if (message) + m.PublicOverheadMessage( + MessageType.Emote, + m.SpeechHue, + true, + "* The open flame begins to scatter the swarm of insects *" + ); - m.FixedParticles(0x91C, 10, 180, 9539, EffectLayer.Waist); - m.PlaySound(0x00E); - m.PlaySound(0x1BC); - - AOS.Damage(m, this, Utility.RandomMinMax(30, 40) - (Core.AOS ? 0 : 10), 100, 0, 0, 0, 0); - - if (!m.Alive) - StopEffect(m, false); + timer.Stop(); + m_Table.Remove(m); + } } - } - } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } + public void DoEffect(Mobile m, int count) + { + if (!m.Alive) + { + StopEffect(m, false); + } + else + { + if (m.FindItemOnLayer(Layer.TwoHanded) is Torch torch && torch.Burning) + { + StopEffect(m, true); + } + else + { + if (count % 4 == 0) + { + m.LocalOverheadMessage( + MessageType.Emote, + m.SpeechHue, + true, + "* The swarm of insects bites and stings your flesh! *" + ); + m.NonlocalOverheadMessage( + MessageType.Emote, + m.SpeechHue, + true, + $"* {m.Name} is stung by a swarm of insects *" + ); + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); + m.FixedParticles(0x91C, 10, 180, 9539, EffectLayer.Waist); + m.PlaySound(0x00E); + m.PlaySound(0x1BC); + + AOS.Damage(m, this, Utility.RandomMinMax(30, 40) - (Core.AOS ? 0 : 10), 100, 0, 0, 0, 0); + + if (!m.Alive) + StopEffect(m, false); + } + } + } + + 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(); + } } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/LBR/Meers/MeerWarrior.cs b/Projects/UOContent/Mobiles/Monsters/LBR/Meers/MeerWarrior.cs index 8fca01583..5019d678f 100644 --- a/Projects/UOContent/Mobiles/Monsters/LBR/Meers/MeerWarrior.cs +++ b/Projects/UOContent/Mobiles/Monsters/LBR/Meers/MeerWarrior.cs @@ -3,82 +3,91 @@ using Server.Spells; namespace Server.Mobiles { - public class MeerWarrior : BaseCreature - { - [Constructible] - public MeerWarrior() : base(AIType.AI_Melee, FightMode.Evil, 10, 1, 0.2, 0.4) + public class MeerWarrior : BaseCreature { - Body = 771; + [Constructible] + public MeerWarrior() : base(AIType.AI_Melee, FightMode.Evil, 10, 1, 0.2, 0.4) + { + Body = 771; - SetStr(86, 100); - SetDex(186, 200); - SetInt(86, 100); + SetStr(86, 100); + SetDex(186, 200); + SetInt(86, 100); - SetHits(52, 60); + SetHits(52, 60); - SetDamage(12, 19); + SetDamage(12, 19); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 5, 15); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 25, 35); - SetResistance(ResistanceType.Energy, 25, 35); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 5, 15); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 25, 35); + SetResistance(ResistanceType.Energy, 25, 35); - SetSkill(SkillName.MagicResist, 91.0, 100.0); - SetSkill(SkillName.Tactics, 91.0, 100.0); - SetSkill(SkillName.Wrestling, 91.0, 100.0); + SetSkill(SkillName.MagicResist, 91.0, 100.0); + SetSkill(SkillName.Tactics, 91.0, 100.0); + SetSkill(SkillName.Wrestling, 91.0, 100.0); - VirtualArmor = 22; + VirtualArmor = 22; - Fame = 2000; - Karma = 5000; + Fame = 2000; + Karma = 5000; + } + + public MeerWarrior(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a meer corpse"; + public override string DefaultName => "a meer warrior"; + + public override bool BardImmune => !Core.AOS; + public override bool CanRummageCorpses => true; + + public override bool InitialInnocent => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + if (from != null && !willKill && amount > 3 && !InRange(from, 7)) + { + MovingEffect(from, 0xF51, 10, 0, false, false); + SpellHelper.Damage( + TimeSpan.FromSeconds(1.0), + from, + this, + Utility.RandomMinMax(30, 40) - (Core.AOS ? 0 : 10), + 100, + 0, + 0, + 0, + 0 + ); + } + + base.OnDamage(amount, from, willKill); + } + + public override int GetHurtSound() => 0x156; + + public override int GetDeathSound() => 0x15C; + + 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(); + } } - - public MeerWarrior(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a meer corpse"; - public override string DefaultName => "a meer warrior"; - - public override bool BardImmune => !Core.AOS; - public override bool CanRummageCorpses => true; - - public override bool InitialInnocent => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } - - public override void OnDamage(int amount, Mobile from, bool willKill) - { - if (from != null && !willKill && amount > 3 && !InRange(from, 7)) - { - MovingEffect(from, 0xF51, 10, 0, false, false); - SpellHelper.Damage(TimeSpan.FromSeconds(1.0), from, this, Utility.RandomMinMax(30, 40) - (Core.AOS ? 0 : 10), - 100, 0, 0, 0, 0); - } - - base.OnDamage(amount, from, willKill); - } - - public override int GetHurtSound() => 0x156; - - public override int GetDeathSound() => 0x15C; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Animal/CuSidhe.cs b/Projects/UOContent/Mobiles/Monsters/ML/Animal/CuSidhe.cs index 6272b92b0..e2d8c06fd 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Animal/CuSidhe.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Animal/CuSidhe.cs @@ -2,129 +2,129 @@ using Server.Items; namespace Server.Mobiles { - public class CuSidhe : BaseMount - { - [Constructible] - public CuSidhe(string name = null) : base(name, 277, 0x3E91, AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class CuSidhe : BaseMount { - double chance = Utility.RandomDouble() * 23301; - - if (chance <= 1) - Hue = 0x489; - else if (chance < 50) - Hue = Utility.RandomList(0x657, 0x515, 0x4B1, 0x481, 0x482, 0x455); - else if (chance < 500) - Hue = Utility.RandomList(0x97A, 0x978, 0x901, 0x8AC, 0x5A7, 0x527); - - SetStr(1200, 1225); - SetDex(150, 170); - SetInt(250, 285); - - SetHits(1010, 1275); - - SetDamage(21, 28); - - SetDamageType(ResistanceType.Physical, 0); - SetDamageType(ResistanceType.Cold, 50); - SetDamageType(ResistanceType.Energy, 50); - - SetResistance(ResistanceType.Physical, 50, 65); - SetResistance(ResistanceType.Fire, 25, 45); - SetResistance(ResistanceType.Cold, 70, 85); - SetResistance(ResistanceType.Poison, 30, 50); - SetResistance(ResistanceType.Energy, 70, 85); - - SetSkill(SkillName.Wrestling, 90.1, 96.8); - SetSkill(SkillName.Tactics, 90.3, 99.3); - SetSkill(SkillName.MagicResist, 75.3, 90.0); - SetSkill(SkillName.Anatomy, 65.5, 69.4); - SetSkill(SkillName.Healing, 72.2, 98.9); - - Fame = 5000; // Guessing here - Karma = 5000; // Guessing here - - Tamable = true; - ControlSlots = 4; - MinTameSkill = 101.1; - - if (Utility.RandomDouble() < 0.2) - PackItem(new TreasureMap(5, Map.Trammel)); - - // if (Utility.RandomDouble() < 0.1) - // PackItem( new ParrotItem() ); - - PackGold(500, 800); - - // TODO 0-2 spellweaving scroll - } - - public CuSidhe(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a cu sidhe corpse"; - public override string DefaultName => "a cu sidhe"; - - public override bool CanHeal => true; - public override bool CanHealOwner => true; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies; - public override bool CanAngerOnTame => true; - public override bool StatLossAfterTame => true; - public override int Hides => 10; - public override int Meat => 3; - - public override void GenerateLoot() - { - AddLoot(LootPack.AosFilthyRich, 5); - } - - public override void OnDoubleClick(Mobile from) - { - if (from.Race != Race.Elf && from == ControlMaster && from.AccessLevel == AccessLevel.Player) - { - Item pads = from.FindItemOnLayer(Layer.Shoes); - - if (pads is PadsOfTheCuSidhe) + [Constructible] + public CuSidhe(string name = null) : base(name, 277, 0x3E91, AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) { - from.SendLocalizedMessage(1071981); // Your boots allow you to mount the Cu Sidhe. + var chance = Utility.RandomDouble() * 23301; + + if (chance <= 1) + Hue = 0x489; + else if (chance < 50) + Hue = Utility.RandomList(0x657, 0x515, 0x4B1, 0x481, 0x482, 0x455); + else if (chance < 500) + Hue = Utility.RandomList(0x97A, 0x978, 0x901, 0x8AC, 0x5A7, 0x527); + + SetStr(1200, 1225); + SetDex(150, 170); + SetInt(250, 285); + + SetHits(1010, 1275); + + SetDamage(21, 28); + + SetDamageType(ResistanceType.Physical, 0); + SetDamageType(ResistanceType.Cold, 50); + SetDamageType(ResistanceType.Energy, 50); + + SetResistance(ResistanceType.Physical, 50, 65); + SetResistance(ResistanceType.Fire, 25, 45); + SetResistance(ResistanceType.Cold, 70, 85); + SetResistance(ResistanceType.Poison, 30, 50); + SetResistance(ResistanceType.Energy, 70, 85); + + SetSkill(SkillName.Wrestling, 90.1, 96.8); + SetSkill(SkillName.Tactics, 90.3, 99.3); + SetSkill(SkillName.MagicResist, 75.3, 90.0); + SetSkill(SkillName.Anatomy, 65.5, 69.4); + SetSkill(SkillName.Healing, 72.2, 98.9); + + Fame = 5000; // Guessing here + Karma = 5000; // Guessing here + + Tamable = true; + ControlSlots = 4; + MinTameSkill = 101.1; + + if (Utility.RandomDouble() < 0.2) + PackItem(new TreasureMap(5, Map.Trammel)); + + // if (Utility.RandomDouble() < 0.1) + // PackItem( new ParrotItem() ); + + PackGold(500, 800); + + // TODO 0-2 spellweaving scroll } - else + + public CuSidhe(Serial serial) : base(serial) { - from.SendLocalizedMessage(1072203); // Only Elves may use this. - return; } - } - base.OnDoubleClick(from); + public override string CorpseName => "a cu sidhe corpse"; + public override string DefaultName => "a cu sidhe"; + + public override bool CanHeal => true; + public override bool CanHealOwner => true; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies; + public override bool CanAngerOnTame => true; + public override bool StatLossAfterTame => true; + public override int Hides => 10; + public override int Meat => 3; + + public override void GenerateLoot() + { + AddLoot(LootPack.AosFilthyRich, 5); + } + + public override void OnDoubleClick(Mobile from) + { + if (from.Race != Race.Elf && from == ControlMaster && from.AccessLevel == AccessLevel.Player) + { + var pads = from.FindItemOnLayer(Layer.Shoes); + + if (pads is PadsOfTheCuSidhe) + { + from.SendLocalizedMessage(1071981); // Your boots allow you to mount the Cu Sidhe. + } + else + { + from.SendLocalizedMessage(1072203); // Only Elves may use this. + return; + } + } + + base.OnDoubleClick(from); + } + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.BleedAttack; + + public override int GetIdleSound() => 0x577; + + public override int GetAttackSound() => 0x576; + + public override int GetAngerSound() => 0x578; + + public override int GetHurtSound() => 0x576; + + public override int GetDeathSound() => 0x579; + + 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 < 1 && Name == "a Cu Sidhe") + Name = null; + } } - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.BleedAttack; - - public override int GetIdleSound() => 0x577; - - public override int GetAttackSound() => 0x576; - - public override int GetAngerSound() => 0x578; - - public override int GetHurtSound() => 0x576; - - public override int GetDeathSound() => 0x579; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version < 1 && Name == "a Cu Sidhe") - Name = null; - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Animal/Ferret.cs b/Projects/UOContent/Mobiles/Monsters/ML/Animal/Ferret.cs index 4648d8c1f..9e17963ec 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Animal/Ferret.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Animal/Ferret.cs @@ -3,107 +3,107 @@ using Server.Engines.Quests; namespace Server.Mobiles { - public class Ferret : BaseCreature - { - private static readonly string[] m_Vocabulary = + public class Ferret : BaseCreature { - "dook", - "dook dook", - "dook dook dook!" - }; + private static readonly string[] m_Vocabulary = + { + "dook", + "dook dook", + "dook dook dook!" + }; - private bool m_CanTalk; + private bool m_CanTalk; - [Constructible] - public Ferret() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) - { - Body = 0x117; + [Constructible] + public Ferret() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 0x117; - SetStr(41, 48); - SetDex(55); - SetInt(75); + SetStr(41, 48); + SetDex(55); + SetInt(75); - SetHits(45, 50); + SetHits(45, 50); - SetDamage(7, 9); + SetDamage(7, 9); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 45, 50); - SetResistance(ResistanceType.Fire, 10, 14); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 21, 25); - SetResistance(ResistanceType.Energy, 20, 25); + SetResistance(ResistanceType.Physical, 45, 50); + SetResistance(ResistanceType.Fire, 10, 14); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 21, 25); + SetResistance(ResistanceType.Energy, 20, 25); - SetSkill(SkillName.MagicResist, 4.0); - SetSkill(SkillName.Tactics, 4.0); - SetSkill(SkillName.Wrestling, 4.0); + SetSkill(SkillName.MagicResist, 4.0); + SetSkill(SkillName.Tactics, 4.0); + SetSkill(SkillName.Wrestling, 4.0); - Tamable = true; - ControlSlots = 1; - MinTameSkill = -21.3; + Tamable = true; + ControlSlots = 1; + MinTameSkill = -21.3; - m_CanTalk = true; + m_CanTalk = true; + } + + public Ferret(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a ferret corpse"; + public override string DefaultName => "a ferret"; + + public override int Meat => 1; + public override FoodType FavoriteFood => FoodType.Fish; + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (m is Ferret ferret && ferret.InRange(this, 3) && ferret.Alive) + Talk(ferret); + } + + public void Talk() + { + Talk(null); + } + + public void Talk(Ferret to) + { + if (m_CanTalk) + { + if (to != null) + QuestSystem.FocusTo(this, to); + + Say(m_Vocabulary.RandomElement()); + + if (to != null && Utility.RandomBool()) + Timer.DelayCall(TimeSpan.FromSeconds(Utility.RandomMinMax(5, 8)), to.Talk); + + m_CanTalk = false; + + Timer.DelayCall(TimeSpan.FromSeconds(Utility.RandomMinMax(20, 30)), ResetCanTalk); + } + } + + private void ResetCanTalk() + { + m_CanTalk = true; + } + + 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(); + + m_CanTalk = true; + } } - - public Ferret(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a ferret corpse"; - public override string DefaultName => "a ferret"; - - public override int Meat => 1; - public override FoodType FavoriteFood => FoodType.Fish; - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (m is Ferret ferret && ferret.InRange(this, 3) && ferret.Alive) - Talk(ferret); - } - - public void Talk() - { - Talk(null); - } - - public void Talk(Ferret to) - { - if (m_CanTalk) - { - if (to != null) - QuestSystem.FocusTo(this, to); - - Say(m_Vocabulary.RandomElement()); - - if (to != null && Utility.RandomBool()) - Timer.DelayCall(TimeSpan.FromSeconds(Utility.RandomMinMax(5, 8)), to.Talk); - - m_CanTalk = false; - - Timer.DelayCall(TimeSpan.FromSeconds(Utility.RandomMinMax(20, 30)), ResetCanTalk); - } - } - - private void ResetCanTalk() - { - m_CanTalk = true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - m_CanTalk = true; - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Animal/RagingGrizzlyBear.cs b/Projects/UOContent/Mobiles/Monsters/ML/Animal/RagingGrizzlyBear.cs index 7217a40da..be3ff5a76 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Animal/RagingGrizzlyBear.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Animal/RagingGrizzlyBear.cs @@ -1,66 +1,66 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Grizzlybear")] - public class RagingGrizzlyBear : BaseCreature - { - [Constructible] - public RagingGrizzlyBear() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Grizzlybear")] + public class RagingGrizzlyBear : BaseCreature { - Body = 212; - BaseSoundID = 0xA3; + [Constructible] + public RagingGrizzlyBear() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 212; + BaseSoundID = 0xA3; - SetStr(1251, 1550); - SetDex(801, 1050); - SetInt(151, 400); + SetStr(1251, 1550); + SetDex(801, 1050); + SetInt(151, 400); - SetHits(751, 930); - SetMana(0); + SetHits(751, 930); + SetMana(0); - SetDamage(18, 23); + SetDamage(18, 23); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 50, 70); - SetResistance(ResistanceType.Cold, 30, 50); - SetResistance(ResistanceType.Poison, 10, 20); - SetResistance(ResistanceType.Energy, 10, 20); + SetResistance(ResistanceType.Physical, 50, 70); + SetResistance(ResistanceType.Cold, 30, 50); + SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Energy, 10, 20); - SetSkill(SkillName.Wrestling, 73.4, 88.1); - SetSkill(SkillName.Tactics, 73.6, 110.5); - SetSkill(SkillName.MagicResist, 32.8, 54.6); - SetSkill(SkillName.Anatomy, 0, 0); + SetSkill(SkillName.Wrestling, 73.4, 88.1); + SetSkill(SkillName.Tactics, 73.6, 110.5); + SetSkill(SkillName.MagicResist, 32.8, 54.6); + SetSkill(SkillName.Anatomy, 0, 0); - Fame = 10000; // Guessing here - Karma = 10000; // Guessing here + Fame = 10000; // Guessing here + Karma = 10000; // Guessing here - VirtualArmor = 24; + VirtualArmor = 24; - Tamable = false; + Tamable = false; + } + + public RagingGrizzlyBear(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a grizzly bear corpse"; + public override string DefaultName => "a raging grizzly bear"; + + public override int Meat => 4; + public override int Hides => 32; + public override PackInstinct PackInstinct => PackInstinct.Bear; + + 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(); + } } - - public RagingGrizzlyBear(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a grizzly bear corpse"; - public override string DefaultName => "a raging grizzly bear"; - - public override int Meat => 4; - public override int Hides => 32; - public override PackInstinct PackInstinct => PackInstinct.Bear; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Animal/Squirrel.cs b/Projects/UOContent/Mobiles/Monsters/ML/Animal/Squirrel.cs index f0e32d940..a94614772 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Animal/Squirrel.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Animal/Squirrel.cs @@ -1,59 +1,59 @@ namespace Server.Mobiles { - public class Squirrel : BaseCreature - { - [Constructible] - public Squirrel() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Squirrel : BaseCreature { - Body = 0x116; + [Constructible] + public Squirrel() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 0x116; - SetStr(44, 50); - SetDex(35); - SetInt(5); + SetStr(44, 50); + SetDex(35); + SetInt(5); - SetHits(42, 50); + SetHits(42, 50); - SetDamage(1, 2); + SetDamage(1, 2); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 30, 34); - SetResistance(ResistanceType.Fire, 10, 14); - SetResistance(ResistanceType.Cold, 30, 35); - SetResistance(ResistanceType.Poison, 20, 25); - SetResistance(ResistanceType.Energy, 20, 25); + SetResistance(ResistanceType.Physical, 30, 34); + SetResistance(ResistanceType.Fire, 10, 14); + SetResistance(ResistanceType.Cold, 30, 35); + SetResistance(ResistanceType.Poison, 20, 25); + SetResistance(ResistanceType.Energy, 20, 25); - SetSkill(SkillName.MagicResist, 4.0); - SetSkill(SkillName.Tactics, 4.0); - SetSkill(SkillName.Wrestling, 4.0); + SetSkill(SkillName.MagicResist, 4.0); + SetSkill(SkillName.Tactics, 4.0); + SetSkill(SkillName.Wrestling, 4.0); - Tamable = true; - ControlSlots = 1; - MinTameSkill = -21.3; + Tamable = true; + ControlSlots = 1; + MinTameSkill = -21.3; + } + + public Squirrel(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a squirrel corpse"; + public override string DefaultName => "a squirrell"; + + public override int Meat => 1; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies; + + 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 Squirrel(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a squirrel corpse"; - public override string DefaultName => "a squirrell"; - - public override int Meat => 1; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/LadyJennifyr.cs b/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/LadyJennifyr.cs index f743cfd34..73d3dfb81 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/LadyJennifyr.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/LadyJennifyr.cs @@ -3,134 +3,135 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class LadyJennifyr : SkeletalKnight - { - private static readonly Dictionary m_Table = new Dictionary(); - - [Constructible] - public LadyJennifyr() + public class LadyJennifyr : SkeletalKnight { - IsParagon = true; + private static readonly Dictionary m_Table = new Dictionary(); - Hue = 0x76D; + [Constructible] + public LadyJennifyr() + { + IsParagon = true; - SetStr(208, 309); - SetDex(91, 118); - SetInt(44, 101); + Hue = 0x76D; - SetHits(1113, 1285); + SetStr(208, 309); + SetDex(91, 118); + SetInt(44, 101); - SetDamage(15, 25); + SetHits(1113, 1285); - SetDamageType(ResistanceType.Physical, 40); - SetDamageType(ResistanceType.Cold, 60); + SetDamage(15, 25); - SetResistance(ResistanceType.Physical, 56, 65); - SetResistance(ResistanceType.Fire, 41, 49); - SetResistance(ResistanceType.Cold, 71, 80); - SetResistance(ResistanceType.Poison, 41, 50); - SetResistance(ResistanceType.Energy, 50, 58); + SetDamageType(ResistanceType.Physical, 40); + SetDamageType(ResistanceType.Cold, 60); - SetSkill(SkillName.Wrestling, 127.9, 137.1); - SetSkill(SkillName.Tactics, 128.4, 141.9); - SetSkill(SkillName.MagicResist, 102.1, 119.5); - SetSkill(SkillName.Anatomy, 129.0, 137.5); + SetResistance(ResistanceType.Physical, 56, 65); + SetResistance(ResistanceType.Fire, 41, 49); + SetResistance(ResistanceType.Cold, 71, 80); + SetResistance(ResistanceType.Poison, 41, 50); + SetResistance(ResistanceType.Energy, 50, 58); - Fame = 18000; - Karma = -18000; + SetSkill(SkillName.Wrestling, 127.9, 137.1); + SetSkill(SkillName.Tactics, 128.4, 141.9); + SetSkill(SkillName.MagicResist, 102.1, 119.5); + SetSkill(SkillName.Anatomy, 129.0, 137.5); + + Fame = 18000; + Karma = -18000; + } + + public LadyJennifyr(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Lady Jennifyr corpse"; + public override string DefaultName => "Lady Jennifyr"; + + /* + // TODO: Uncomment once added + public override void OnDeath( Container c ) + { + base.OnDeath( c ); + + if (Utility.RandomDouble() < 0.15) + c.DropItem( new DisintegratingThesisNotes() ); + + if (Utility.RandomDouble() < 0.1) + c.DropItem( new ParrotItem() ); + } + */ + + public override bool GivesMLMinorArtifact => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 3); + } + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomDouble() >= 0.1) + return; + + if (m_Table.TryGetValue(defender, out var timer)) + timer.DoExpire(); + + defender.FixedParticles(0x3709, 10, 30, 5052, EffectLayer.LeftFoot); + defender.PlaySound(0x208); + defender.SendLocalizedMessage( + 1070833 + ); // The creature fans you with fire, reducing your resistance to fire attacks. + + var mod = new ResistanceMod(ResistanceType.Fire, -10); + defender.AddResistanceMod(mod); + + m_Table[defender] = timer = new ExpireTimer(defender, mod); + timer.Start(); + } + + 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(); + } + + private class ExpireTimer : Timer + { + private readonly Mobile m_Mobile; + private readonly ResistanceMod m_Mod; + + public ExpireTimer(Mobile m, ResistanceMod mod) + : base(TimeSpan.FromSeconds(10)) + { + m_Mobile = m; + m_Mod = mod; + Priority = TimerPriority.TwoFiftyMS; + } + + public void DoExpire() + { + m_Mobile.RemoveResistanceMod(m_Mod); + + Stop(); + m_Table.Remove(m_Mobile); + } + + protected override void OnTick() + { + m_Mobile.SendLocalizedMessage(1070834); // Your resistance to fire attacks has returned. + DoExpire(); + } + } } - - public LadyJennifyr(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Lady Jennifyr corpse"; - public override string DefaultName => "Lady Jennifyr"; - - /* - // TODO: Uncomment once added - public override void OnDeath( Container c ) - { - base.OnDeath( c ); - - if (Utility.RandomDouble() < 0.15) - c.DropItem( new DisintegratingThesisNotes() ); - - if (Utility.RandomDouble() < 0.1) - c.DropItem( new ParrotItem() ); - } - */ - - public override bool GivesMLMinorArtifact => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 3); - } - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (Utility.RandomDouble() >= 0.1) - return; - - if (m_Table.TryGetValue(defender, out ExpireTimer timer)) - timer.DoExpire(); - - defender.FixedParticles(0x3709, 10, 30, 5052, EffectLayer.LeftFoot); - defender.PlaySound(0x208); - defender.SendLocalizedMessage( - 1070833); // The creature fans you with fire, reducing your resistance to fire attacks. - - ResistanceMod mod = new ResistanceMod(ResistanceType.Fire, -10); - defender.AddResistanceMod(mod); - - m_Table[defender] = timer = new ExpireTimer(defender, mod); - timer.Start(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private class ExpireTimer : Timer - { - private readonly Mobile m_Mobile; - private readonly ResistanceMod m_Mod; - - public ExpireTimer(Mobile m, ResistanceMod mod) - : base(TimeSpan.FromSeconds(10)) - { - m_Mobile = m; - m_Mod = mod; - Priority = TimerPriority.TwoFiftyMS; - } - - public void DoExpire() - { - m_Mobile.RemoveResistanceMod(m_Mod); - - Stop(); - m_Table.Remove(m_Mobile); - } - - protected override void OnTick() - { - m_Mobile.SendLocalizedMessage(1070834); // Your resistance to fire attacks has returned. - DoExpire(); - } - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/LadyMarai.cs b/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/LadyMarai.cs index ce5423e77..14ee4f796 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/LadyMarai.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/LadyMarai.cs @@ -2,84 +2,84 @@ using Server.Items; namespace Server.Mobiles { - public class LadyMarai : SkeletalKnight - { - [Constructible] - public LadyMarai() + public class LadyMarai : SkeletalKnight { - IsParagon = true; + [Constructible] + public LadyMarai() + { + IsParagon = true; - Hue = 0x21; + Hue = 0x21; - SetStr(221, 304); - SetDex(98, 138); - SetInt(54, 99); + SetStr(221, 304); + SetDex(98, 138); + SetInt(54, 99); - SetHits(694, 846); + SetHits(694, 846); - SetDamage(15, 25); + SetDamage(15, 25); - SetDamageType(ResistanceType.Physical, 40); - SetDamageType(ResistanceType.Cold, 60); + SetDamageType(ResistanceType.Physical, 40); + SetDamageType(ResistanceType.Cold, 60); - SetResistance(ResistanceType.Physical, 55, 65); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 70, 80); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 50, 60); + SetResistance(ResistanceType.Physical, 55, 65); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 70, 80); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 50, 60); - SetSkill(SkillName.Wrestling, 126.6, 137.2); - SetSkill(SkillName.Tactics, 128.7, 134.5); - SetSkill(SkillName.MagicResist, 102.1, 119.1); - SetSkill(SkillName.Anatomy, 126.2, 136.5); + SetSkill(SkillName.Wrestling, 126.6, 137.2); + SetSkill(SkillName.Tactics, 128.7, 134.5); + SetSkill(SkillName.MagicResist, 102.1, 119.1); + SetSkill(SkillName.Anatomy, 126.2, 136.5); - Fame = 18000; - Karma = -18000; + Fame = 18000; + Karma = -18000; + } + + public LadyMarai(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Lady Marai corpse"; + public override string DefaultName => "Lady Marai"; + + /* + // TODO: Uncomment once added + public override void OnDeath( Container c ) + { + base.OnDeath( c ); + + if (Utility.RandomDouble() < 0.15) + c.DropItem( new DisintegratingThesisNotes() ); + + if (Utility.RandomDouble() < 0.1) + c.DropItem( new ParrotItem() ); + } + */ + + public override bool GivesMLMinorArtifact => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 3); + } + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.CrushingBlow; + + 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 LadyMarai(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Lady Marai corpse"; - public override string DefaultName => "Lady Marai"; - - /* - // TODO: Uncomment once added - public override void OnDeath( Container c ) - { - base.OnDeath( c ); - - if (Utility.RandomDouble() < 0.15) - c.DropItem( new DisintegratingThesisNotes() ); - - if (Utility.RandomDouble() < 0.1) - c.DropItem( new ParrotItem() ); - } - */ - - public override bool GivesMLMinorArtifact => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 3); - } - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.CrushingBlow; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/MasterJonath.cs b/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/MasterJonath.cs index 72d6722eb..60c4aac8c 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/MasterJonath.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/MasterJonath.cs @@ -1,95 +1,95 @@ namespace Server.Mobiles { - public class MasterJonath : BoneMagi - { - [Constructible] - public MasterJonath() + public class MasterJonath : BoneMagi { - IsParagon = true; + [Constructible] + public MasterJonath() + { + IsParagon = true; - Hue = 0x455; + Hue = 0x455; - SetStr(109, 131); - SetDex(98, 110); - SetInt(232, 259); + SetStr(109, 131); + SetDex(98, 110); + SetInt(232, 259); - SetHits(766, 920); + SetHits(766, 920); - SetDamage(10, 15); + SetDamage(10, 15); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 55, 60); - SetResistance(ResistanceType.Fire, 43, 49); - SetResistance(ResistanceType.Cold, 45, 80); - SetResistance(ResistanceType.Poison, 41, 45); - SetResistance(ResistanceType.Energy, 54, 55); + SetResistance(ResistanceType.Physical, 55, 60); + SetResistance(ResistanceType.Fire, 43, 49); + SetResistance(ResistanceType.Cold, 45, 80); + SetResistance(ResistanceType.Poison, 41, 45); + SetResistance(ResistanceType.Energy, 54, 55); - SetSkill(SkillName.Wrestling, 80.5, 88.6); - SetSkill(SkillName.Tactics, 88.5, 95.1); - SetSkill(SkillName.MagicResist, 102.7, 102.9); - SetSkill(SkillName.Magery, 100.0, 106.6); - SetSkill(SkillName.EvalInt, 99.6, 106.9); - SetSkill(SkillName.Necromancy, 100.0, 106.6); - SetSkill(SkillName.SpiritSpeak, 99.6, 106.9); + SetSkill(SkillName.Wrestling, 80.5, 88.6); + SetSkill(SkillName.Tactics, 88.5, 95.1); + SetSkill(SkillName.MagicResist, 102.7, 102.9); + SetSkill(SkillName.Magery, 100.0, 106.6); + SetSkill(SkillName.EvalInt, 99.6, 106.9); + SetSkill(SkillName.Necromancy, 100.0, 106.6); + SetSkill(SkillName.SpiritSpeak, 99.6, 106.9); - Fame = 18000; - Karma = -18000; + Fame = 18000; + Karma = -18000; - if (Utility.RandomBool()) - PackNecroScroll(Utility.RandomMinMax(5, 9)); - else - PackScroll(4, 7); + if (Utility.RandomBool()) + PackNecroScroll(Utility.RandomMinMax(5, 9)); + else + PackScroll(4, 7); - PackReg(7); - PackReg(7); - PackReg(8); + PackReg(7); + PackReg(7); + PackReg(8); + } + + public MasterJonath(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Master Jonath corpse"; + public override string DefaultName => "Master Jonath"; + + // TODO: Special move? + + /* + // TODO: uncomment once added + public override void OnDeath( Container c ) + { + base.OnDeath( c ); + + if (Utility.RandomDouble() < 0.05) + c.DropItem( new ParrotItem() ); + + if (Utility.RandomDouble() < 0.15) + c.DropItem( new DisintegratingThesisNotes() ); + } + */ + + public override bool GivesMLMinorArtifact => true; + public override int TreasureMapLevel => 5; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 3); + } + + 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 MasterJonath(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Master Jonath corpse"; - public override string DefaultName => "Master Jonath"; - - // TODO: Special move? - - /* - // TODO: uncomment once added - public override void OnDeath( Container c ) - { - base.OnDeath( c ); - - if (Utility.RandomDouble() < 0.05) - c.DropItem( new ParrotItem() ); - - if (Utility.RandomDouble() < 0.15) - c.DropItem( new DisintegratingThesisNotes() ); - } - */ - - public override bool GivesMLMinorArtifact => true; - public override int TreasureMapLevel => 5; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 3); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/MasterMikael.cs b/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/MasterMikael.cs index c5723e1b7..28527f0cd 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/MasterMikael.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/MasterMikael.cs @@ -1,93 +1,93 @@ namespace Server.Mobiles { - public class MasterMikael : BoneMagi - { - [Constructible] - public MasterMikael() + public class MasterMikael : BoneMagi { - IsParagon = true; + [Constructible] + public MasterMikael() + { + IsParagon = true; - Hue = 0x8FD; + Hue = 0x8FD; - SetStr(93, 122); - SetDex(91, 100); - SetInt(252, 271); + SetStr(93, 122); + SetDex(91, 100); + SetInt(252, 271); - SetHits(789, 1014); + SetHits(789, 1014); - SetDamage(11, 19); + SetDamage(11, 19); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 55, 59); - SetResistance(ResistanceType.Fire, 40, 46); - SetResistance(ResistanceType.Cold, 72, 80); - SetResistance(ResistanceType.Poison, 44, 49); - SetResistance(ResistanceType.Energy, 50, 57); + SetResistance(ResistanceType.Physical, 55, 59); + SetResistance(ResistanceType.Fire, 40, 46); + SetResistance(ResistanceType.Cold, 72, 80); + SetResistance(ResistanceType.Poison, 44, 49); + SetResistance(ResistanceType.Energy, 50, 57); - SetSkill(SkillName.Wrestling, 80.1, 87.2); - SetSkill(SkillName.Tactics, 79.0, 90.9); - SetSkill(SkillName.MagicResist, 90.3, 106.9); - SetSkill(SkillName.Magery, 103.8, 108.0); - SetSkill(SkillName.EvalInt, 96.1, 105.3); - SetSkill(SkillName.Necromancy, 103.8, 108.0); - SetSkill(SkillName.SpiritSpeak, 96.1, 105.3); + SetSkill(SkillName.Wrestling, 80.1, 87.2); + SetSkill(SkillName.Tactics, 79.0, 90.9); + SetSkill(SkillName.MagicResist, 90.3, 106.9); + SetSkill(SkillName.Magery, 103.8, 108.0); + SetSkill(SkillName.EvalInt, 96.1, 105.3); + SetSkill(SkillName.Necromancy, 103.8, 108.0); + SetSkill(SkillName.SpiritSpeak, 96.1, 105.3); - Fame = 18000; - Karma = -18000; + Fame = 18000; + Karma = -18000; - if (Utility.RandomBool()) - PackNecroScroll(Utility.RandomMinMax(5, 9)); - else - PackScroll(4, 7); + if (Utility.RandomBool()) + PackNecroScroll(Utility.RandomMinMax(5, 9)); + else + PackScroll(4, 7); - PackReg(3); - PackNecroReg(1, 10); + PackReg(3); + PackNecroReg(1, 10); + } + + public MasterMikael(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Master Mikael corpse"; + public override string DefaultName => "Master Mikael"; + + // TODO: Special move? + + /* + // TODO: uncomment once added + public override void OnDeath( Container c ) + { + base.OnDeath( c ); + + if (Utility.RandomDouble() < 0.15) + c.DropItem( new DisintegratingThesisNotes() ); + + if (Utility.RandomDouble() < 0.1) + c.DropItem( new ParrotItem() ); + } + */ + + public override bool GivesMLMinorArtifact => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 2); + } + + 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 MasterMikael(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Master Mikael corpse"; - public override string DefaultName => "Master Mikael"; - - // TODO: Special move? - - /* - // TODO: uncomment once added - public override void OnDeath( Container c ) - { - base.OnDeath( c ); - - if (Utility.RandomDouble() < 0.15) - c.DropItem( new DisintegratingThesisNotes() ); - - if (Utility.RandomDouble() < 0.1) - c.DropItem( new ParrotItem() ); - } - */ - - public override bool GivesMLMinorArtifact => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/MasterTheophilus.cs b/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/MasterTheophilus.cs index a930156b1..dc325b2af 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/MasterTheophilus.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/MasterTheophilus.cs @@ -2,88 +2,88 @@ using Server.Items; namespace Server.Mobiles { - public class MasterTheophilus : EvilMageLord - { - [Constructible] - public MasterTheophilus() + public class MasterTheophilus : EvilMageLord { - IsParagon = true; + [Constructible] + public MasterTheophilus() + { + IsParagon = true; - Title = "the necromancer"; - Hue = 0; + Title = "the necromancer"; + Hue = 0; - SetStr(137, 187); - SetDex(253, 301); - SetInt(393, 444); + SetStr(137, 187); + SetDex(253, 301); + SetInt(393, 444); - SetHits(663, 876); + SetHits(663, 876); - SetDamage(15, 20); + SetDamage(15, 20); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 55, 60); - SetResistance(ResistanceType.Fire, 50, 58); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 50, 60); - SetResistance(ResistanceType.Energy, 50, 60); + SetResistance(ResistanceType.Physical, 55, 60); + SetResistance(ResistanceType.Fire, 50, 58); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 50, 60); + SetResistance(ResistanceType.Energy, 50, 60); - SetSkill(SkillName.Wrestling, 69.9, 105.3); - SetSkill(SkillName.Tactics, 113.0, 117.9); - SetSkill(SkillName.MagicResist, 127.0, 132.8); - SetSkill(SkillName.Magery, 138.1, 143.7); - SetSkill(SkillName.EvalInt, 125.6, 133.8); - SetSkill(SkillName.Necromancy, 125.6, 133.8); - SetSkill(SkillName.SpiritSpeak, 125.6, 133.8); - SetSkill(SkillName.Meditation, 128.8, 132.9); + SetSkill(SkillName.Wrestling, 69.9, 105.3); + SetSkill(SkillName.Tactics, 113.0, 117.9); + SetSkill(SkillName.MagicResist, 127.0, 132.8); + SetSkill(SkillName.Magery, 138.1, 143.7); + SetSkill(SkillName.EvalInt, 125.6, 133.8); + SetSkill(SkillName.Necromancy, 125.6, 133.8); + SetSkill(SkillName.SpiritSpeak, 125.6, 133.8); + SetSkill(SkillName.Meditation, 128.8, 132.9); - Fame = 18000; - Karma = -18000; + Fame = 18000; + Karma = -18000; - AddItem(new Shoes(0x537)); - AddItem(new Robe(0x452)); + AddItem(new Shoes(0x537)); + AddItem(new Robe(0x452)); - for (int i = 0; i < 2; ++i) - if (Utility.RandomBool()) - PackNecroScroll(Utility.RandomMinMax(5, 9)); - else - PackScroll(4, 7); + for (var i = 0; i < 2; ++i) + if (Utility.RandomBool()) + PackNecroScroll(Utility.RandomMinMax(5, 9)); + else + PackScroll(4, 7); - PackReg(7); - PackReg(7); - PackReg(8); + PackReg(7); + PackReg(7); + PackReg(8); + } + + public MasterTheophilus(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Master Theophilus corpse"; + public override string DefaultName => "Master Theophilus"; + + public override bool GivesMLMinorArtifact => true; + public override int TreasureMapLevel => 5; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 3); + } + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.ParalyzingBlow; + + 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 MasterTheophilus(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Master Theophilus corpse"; - public override string DefaultName => "Master Theophilus"; - - public override bool GivesMLMinorArtifact => true; - public override int TreasureMapLevel => 5; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 3); - } - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.ParalyzingBlow; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/RedDeath.cs b/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/RedDeath.cs index 6fff80537..36e8d2132 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/RedDeath.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/RedDeath.cs @@ -2,91 +2,91 @@ using Server.Items; namespace Server.Mobiles { - public class RedDeath : SkeletalMount - { - [Constructible] - public RedDeath() - : base("Red Death") + public class RedDeath : SkeletalMount { - IsParagon = true; + [Constructible] + public RedDeath() + : base("Red Death") + { + IsParagon = true; - Hue = 0x21; - BaseSoundID = 0x1C3; + Hue = 0x21; + BaseSoundID = 0x1C3; - AI = AIType.AI_Melee; - FightMode = FightMode.Closest; + AI = AIType.AI_Melee; + FightMode = FightMode.Closest; - SetStr(319, 324); - SetDex(241, 244); - SetInt(242, 255); + SetStr(319, 324); + SetDex(241, 244); + SetInt(242, 255); - SetHits(1540, 1605); + SetHits(1540, 1605); - SetDamage(25, 29); + SetDamage(25, 29); - SetDamageType(ResistanceType.Physical, 25); - SetDamageType(ResistanceType.Fire, 75); - SetDamageType(ResistanceType.Cold, 0); + SetDamageType(ResistanceType.Physical, 25); + SetDamageType(ResistanceType.Fire, 75); + SetDamageType(ResistanceType.Cold, 0); - SetResistance(ResistanceType.Physical, 60, 70); - SetResistance(ResistanceType.Fire, 90); - SetResistance(ResistanceType.Cold, 0); - SetResistance(ResistanceType.Poison, 100); - SetResistance(ResistanceType.Energy, 0); + SetResistance(ResistanceType.Physical, 60, 70); + SetResistance(ResistanceType.Fire, 90); + SetResistance(ResistanceType.Cold, 0); + SetResistance(ResistanceType.Poison, 100); + SetResistance(ResistanceType.Energy, 0); - SetSkill(SkillName.Wrestling, 121.4, 143.7); - SetSkill(SkillName.Tactics, 120.9, 142.2); - SetSkill(SkillName.MagicResist, 120.1, 142.3); - SetSkill(SkillName.Anatomy, 120.2, 144.0); + SetSkill(SkillName.Wrestling, 121.4, 143.7); + SetSkill(SkillName.Tactics, 120.9, 142.2); + SetSkill(SkillName.MagicResist, 120.1, 142.3); + SetSkill(SkillName.Anatomy, 120.2, 144.0); - Fame = 28000; - Karma = -28000; + Fame = 28000; + Karma = -28000; - if (Utility.RandomBool()) - PackNecroScroll(Utility.RandomMinMax(5, 9)); - else - PackScroll(4, 7); + if (Utility.RandomBool()) + PackNecroScroll(Utility.RandomMinMax(5, 9)); + else + PackScroll(4, 7); + } + + public RedDeath(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Red Death corpse"; + + public override bool GivesMLMinorArtifact => true; + public override bool AlwaysMurderer => true; + public override bool HasBreath => true; + public override int BreathChaosDamage => 100; + public override int BreathFireDamage => 0; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 3); + } + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.WhirlwindAttack; + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + c.DropItem(new ResolvesBridle()); + } + + 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 RedDeath(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Red Death corpse"; - - public override bool GivesMLMinorArtifact => true; - public override bool AlwaysMurderer => true; - public override bool HasBreath => true; - public override int BreathChaosDamage => 100; - public override int BreathFireDamage => 0; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 3); - } - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.WhirlwindAttack; - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - c.DropItem(new ResolvesBridle()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/SirPatrick.cs b/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/SirPatrick.cs index c562f7204..a7ccfc9ee 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/SirPatrick.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Bedlam/SirPatrick.cs @@ -2,132 +2,132 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class SirPatrick : SkeletalKnight - { - [Constructible] - public SirPatrick() + public class SirPatrick : SkeletalKnight { - IsParagon = true; - - Hue = 0x47E; - - SetStr(208, 319); - SetDex(98, 132); - SetInt(45, 91); - - SetHits(616, 884); - - SetDamage(15, 25); - - SetDamageType(ResistanceType.Physical, 40); - SetDamageType(ResistanceType.Cold, 60); - - SetResistance(ResistanceType.Physical, 55, 62); - SetResistance(ResistanceType.Fire, 40, 48); - SetResistance(ResistanceType.Cold, 71, 80); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 50, 60); - - SetSkill(SkillName.Wrestling, 126.3, 136.5); - SetSkill(SkillName.Tactics, 128.5, 143.8); - SetSkill(SkillName.MagicResist, 102.8, 117.9); - SetSkill(SkillName.Anatomy, 127.5, 137.2); - - Fame = 18000; - Karma = -18000; - } - - public SirPatrick(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Sir Patrick corpse"; - public override string DefaultName => "Sir Patrick"; - - /* - // TODO: uncomment once added - public override void OnDeath( Container c ) - { - base.OnDeath( c ); - - if (Utility.RandomDouble() < 0.15) - c.DropItem( new DisintegratingThesisNotes() ); - - if (Utility.RandomDouble() < 0.05) - c.DropItem( new AssassinChest() ); - } - */ - - public override bool GivesMLMinorArtifact => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 2); - } - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (Utility.RandomDouble() < 0.1) - DrainLife(); - } - - public override void OnGotMeleeAttack(Mobile attacker) - { - base.OnGotMeleeAttack(attacker); - - if (Utility.RandomDouble() < 0.1) - DrainLife(); - } - - public virtual void DrainLife() - { - List list = new List(); - - foreach (Mobile m in GetMobilesInRange(2)) - { - if (m == this || !CanBeHarmful(m, false) || (Core.AOS && !InLOS(m))) - continue; - - if (m is BaseCreature bc) + [Constructible] + public SirPatrick() { - if (bc.Controlled || bc.Summoned || bc.Team != Team) - list.Add(bc); + IsParagon = true; + + Hue = 0x47E; + + SetStr(208, 319); + SetDex(98, 132); + SetInt(45, 91); + + SetHits(616, 884); + + SetDamage(15, 25); + + SetDamageType(ResistanceType.Physical, 40); + SetDamageType(ResistanceType.Cold, 60); + + SetResistance(ResistanceType.Physical, 55, 62); + SetResistance(ResistanceType.Fire, 40, 48); + SetResistance(ResistanceType.Cold, 71, 80); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 50, 60); + + SetSkill(SkillName.Wrestling, 126.3, 136.5); + SetSkill(SkillName.Tactics, 128.5, 143.8); + SetSkill(SkillName.MagicResist, 102.8, 117.9); + SetSkill(SkillName.Anatomy, 127.5, 137.2); + + Fame = 18000; + Karma = -18000; } - else if (m.Player) + + public SirPatrick(Serial serial) + : base(serial) { - list.Add(m); } - } - foreach (Mobile m in list) - { - DoHarmful(m); + public override string CorpseName => "a Sir Patrick corpse"; + public override string DefaultName => "Sir Patrick"; - m.FixedParticles(0x374A, 10, 15, 5013, 0x455, 0, EffectLayer.Waist); - m.PlaySound(0x1EA); + /* + // TODO: uncomment once added + public override void OnDeath( Container c ) + { + base.OnDeath( c ); + + if (Utility.RandomDouble() < 0.15) + c.DropItem( new DisintegratingThesisNotes() ); + + if (Utility.RandomDouble() < 0.05) + c.DropItem( new AssassinChest() ); + } + */ - int drain = Utility.RandomMinMax(14, 30); + public override bool GivesMLMinorArtifact => true; - Hits += drain; - m.Damage(drain, this); - } + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 2); + } + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomDouble() < 0.1) + DrainLife(); + } + + public override void OnGotMeleeAttack(Mobile attacker) + { + base.OnGotMeleeAttack(attacker); + + if (Utility.RandomDouble() < 0.1) + DrainLife(); + } + + public virtual void DrainLife() + { + var list = new List(); + + foreach (var m in GetMobilesInRange(2)) + { + if (m == this || !CanBeHarmful(m, false) || Core.AOS && !InLOS(m)) + continue; + + if (m is BaseCreature bc) + { + if (bc.Controlled || bc.Summoned || bc.Team != Team) + list.Add(bc); + } + else if (m.Player) + { + list.Add(m); + } + } + + foreach (var m in list) + { + DoHarmful(m); + + m.FixedParticles(0x374A, 10, 15, 5013, 0x455, 0, EffectLayer.Waist); + m.PlaySound(0x1EA); + + var drain = Utility.RandomMinMax(14, 30); + + Hits += drain; + m.Damage(drain, this); + } + } + + 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 Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Abscess.cs b/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Abscess.cs index 41ced7750..06a696b2e 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Abscess.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Abscess.cs @@ -2,77 +2,77 @@ using Server.Items; namespace Server.Mobiles { - public class Abscess : Hydra - { - [Constructible] - public Abscess() + public class Abscess : Hydra { - IsParagon = true; + [Constructible] + public Abscess() + { + IsParagon = true; - Hue = 0x8FD; + Hue = 0x8FD; - SetStr(845, 871); - SetDex(121, 134); - SetInt(124, 142); + SetStr(845, 871); + SetDex(121, 134); + SetInt(124, 142); - SetHits(7470, 7540); + SetHits(7470, 7540); - SetDamage(26, 31); + SetDamage(26, 31); - SetDamageType(ResistanceType.Physical, 60); - SetDamageType(ResistanceType.Fire, 10); - SetDamageType(ResistanceType.Cold, 10); - SetDamageType(ResistanceType.Poison, 10); - SetDamageType(ResistanceType.Energy, 10); + SetDamageType(ResistanceType.Physical, 60); + SetDamageType(ResistanceType.Fire, 10); + SetDamageType(ResistanceType.Cold, 10); + SetDamageType(ResistanceType.Poison, 10); + SetDamageType(ResistanceType.Energy, 10); - SetResistance(ResistanceType.Physical, 65, 75); - SetResistance(ResistanceType.Fire, 70, 80); - SetResistance(ResistanceType.Cold, 25, 35); - SetResistance(ResistanceType.Poison, 35, 45); - SetResistance(ResistanceType.Energy, 35, 45); + SetResistance(ResistanceType.Physical, 65, 75); + SetResistance(ResistanceType.Fire, 70, 80); + SetResistance(ResistanceType.Cold, 25, 35); + SetResistance(ResistanceType.Poison, 35, 45); + SetResistance(ResistanceType.Energy, 35, 45); - SetSkill(SkillName.Wrestling, 132.3, 143.8); - SetSkill(SkillName.Tactics, 121.0, 130.5); - SetSkill(SkillName.MagicResist, 102.9, 119.0); - SetSkill(SkillName.Anatomy, 91.8, 94.3); + SetSkill(SkillName.Wrestling, 132.3, 143.8); + SetSkill(SkillName.Tactics, 121.0, 130.5); + SetSkill(SkillName.MagicResist, 102.9, 119.0); + SetSkill(SkillName.Anatomy, 91.8, 94.3); - // TODO: Fame/Karma + // TODO: Fame/Karma + } + + public Abscess(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "an Abscess corpse"; + public override string DefaultName => "Abscess"; + + public override bool GivesMLMinorArtifact => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 4); + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + c.DropItem(new AbscessTail()); + } + + 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 Abscess(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "an Abscess corpse"; - public override string DefaultName => "Abscess"; - - public override bool GivesMLMinorArtifact => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 4); - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - c.DropItem(new AbscessTail()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Coil.cs b/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Coil.cs index 914ef3307..342449352 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Coil.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Coil.cs @@ -2,101 +2,101 @@ using Server.Items; namespace Server.Mobiles { - public class Coil : SilverSerpent - { - [Constructible] - public Coil() + public class Coil : SilverSerpent { - IsParagon = true; - - Hue = 0x3F; - - SetStr(205, 343); - SetDex(202, 283); - SetInt(88, 142); - - SetHits(628, 1291); - - SetDamage(19, 28); - - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Poison, 50); - - SetResistance(ResistanceType.Physical, 56, 62); - SetResistance(ResistanceType.Fire, 25, 30); - SetResistance(ResistanceType.Cold, 25, 30); - SetResistance(ResistanceType.Poison, 100); - SetResistance(ResistanceType.Energy, 25, 30); - - SetSkill(SkillName.Wrestling, 124.5, 141.3); - SetSkill(SkillName.Tactics, 130.2, 142.0); - SetSkill(SkillName.MagicResist, 102.3, 113.0); - SetSkill(SkillName.Anatomy, 120.8, 138.1); - SetSkill(SkillName.Poisoning, 110.1, 133.4); - - // TODO: Fame/Karma - - PackGem(2); - PackItem(new Bone()); - } - - public Coil(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Coil corpse"; - // TODO: Check faction allegiance - - public override string DefaultName => "Coil"; - - public override Poison HitPoison => Poison.Lethal; - public override Poison PoisonImmune => Poison.Lethal; - public override bool GivesMLMinorArtifact => true; - public override int Hides => 48; - public override int Meat => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 3); - } - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.MortalStrike; - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - c.DropItem(new CoilsFang()); - - /* - // TODO: uncomment once added - if (Utility.RandomDouble() < 0.025) - { - switch ( Utility.Random( 5 ) ) + [Constructible] + public Coil() { - case 0: c.DropItem( new AssassinChest() ); break; - case 1: c.DropItem( new DeathGloves() ); break; - case 2: c.DropItem( new LeafweaveLegs() ); break; - case 3: c.DropItem( new HunterLegs() ); break; - case 4: c.DropItem( new MyrmidonLegs() ); break; + IsParagon = true; + + Hue = 0x3F; + + SetStr(205, 343); + SetDex(202, 283); + SetInt(88, 142); + + SetHits(628, 1291); + + SetDamage(19, 28); + + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Poison, 50); + + SetResistance(ResistanceType.Physical, 56, 62); + SetResistance(ResistanceType.Fire, 25, 30); + SetResistance(ResistanceType.Cold, 25, 30); + SetResistance(ResistanceType.Poison, 100); + SetResistance(ResistanceType.Energy, 25, 30); + + SetSkill(SkillName.Wrestling, 124.5, 141.3); + SetSkill(SkillName.Tactics, 130.2, 142.0); + SetSkill(SkillName.MagicResist, 102.3, 113.0); + SetSkill(SkillName.Anatomy, 120.8, 138.1); + SetSkill(SkillName.Poisoning, 110.1, 133.4); + + // TODO: Fame/Karma + + PackGem(2); + PackItem(new Bone()); + } + + public Coil(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Coil corpse"; + // TODO: Check faction allegiance + + public override string DefaultName => "Coil"; + + public override Poison HitPoison => Poison.Lethal; + public override Poison PoisonImmune => Poison.Lethal; + public override bool GivesMLMinorArtifact => true; + public override int Hides => 48; + public override int Meat => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 3); + } + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.MortalStrike; + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + c.DropItem(new CoilsFang()); + + /* + // TODO: uncomment once added + if (Utility.RandomDouble() < 0.025) + { + switch ( Utility.Random( 5 ) ) + { + case 0: c.DropItem( new AssassinChest() ); break; + case 1: c.DropItem( new DeathGloves() ); break; + case 2: c.DropItem( new LeafweaveLegs() ); break; + case 3: c.DropItem( new HunterLegs() ); break; + case 4: c.DropItem( new MyrmidonLegs() ); break; + } + } + */ + } + + 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 Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/EnslavedSatyr.cs b/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/EnslavedSatyr.cs index a89d284d4..2acc3e418 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/EnslavedSatyr.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/EnslavedSatyr.cs @@ -1,43 +1,43 @@ namespace Server.Mobiles { - public class EnslavedSatyr : Satyr - { - [Constructible] - public EnslavedSatyr() + public class EnslavedSatyr : Satyr { + [Constructible] + public EnslavedSatyr() + { + } + + /* + // TODO: uncomment once added + public override void OnDeath( Container c ) + { + base.OnDeath( c ); + + if (Utility.RandomDouble() < 0.1) + c.DropItem( new ParrotItem() ); + } + */ + + public EnslavedSatyr(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "an enslaved satyr corpse"; + public override string DefaultName => "an enslaved satyr"; + + 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(); + } } - - /* - // TODO: uncomment once added - public override void OnDeath( Container c ) - { - base.OnDeath( c ); - - if (Utility.RandomDouble() < 0.1) - c.DropItem( new ParrotItem() ); - } - */ - - public EnslavedSatyr(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "an enslaved satyr corpse"; - public override string DefaultName => "an enslaved satyr"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Hydra.cs b/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Hydra.cs index 81bbdefb8..6a8b5c609 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Hydra.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Hydra.cs @@ -2,89 +2,89 @@ using Server.Items; namespace Server.Mobiles { - public class Hydra : BaseCreature - { - [Constructible] - public Hydra() - : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Hydra : BaseCreature { - Body = 0x109; - BaseSoundID = 0x16A; + [Constructible] + public Hydra() + : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0x109; + BaseSoundID = 0x16A; - SetStr(801, 828); - SetDex(102, 118); - SetInt(102, 120); + SetStr(801, 828); + SetDex(102, 118); + SetInt(102, 120); - SetHits(1480, 1500); + SetHits(1480, 1500); - SetDamage(21, 26); + SetDamage(21, 26); - SetDamageType(ResistanceType.Physical, 60); - SetDamageType(ResistanceType.Fire, 10); - SetDamageType(ResistanceType.Cold, 10); - SetDamageType(ResistanceType.Poison, 10); - SetDamageType(ResistanceType.Energy, 10); + SetDamageType(ResistanceType.Physical, 60); + SetDamageType(ResistanceType.Fire, 10); + SetDamageType(ResistanceType.Cold, 10); + SetDamageType(ResistanceType.Poison, 10); + SetDamageType(ResistanceType.Energy, 10); - SetResistance(ResistanceType.Physical, 65, 75); - SetResistance(ResistanceType.Fire, 70, 85); - SetResistance(ResistanceType.Cold, 25, 35); - SetResistance(ResistanceType.Poison, 35, 43); - SetResistance(ResistanceType.Energy, 36, 45); + SetResistance(ResistanceType.Physical, 65, 75); + SetResistance(ResistanceType.Fire, 70, 85); + SetResistance(ResistanceType.Cold, 25, 35); + SetResistance(ResistanceType.Poison, 35, 43); + SetResistance(ResistanceType.Energy, 36, 45); - SetSkill(SkillName.Wrestling, 103.5, 117.4); - SetSkill(SkillName.Tactics, 100.1, 109.8); - SetSkill(SkillName.MagicResist, 85.5, 98.5); - SetSkill(SkillName.Anatomy, 75.4, 79.8); + SetSkill(SkillName.Wrestling, 103.5, 117.4); + SetSkill(SkillName.Tactics, 100.1, 109.8); + SetSkill(SkillName.MagicResist, 85.5, 98.5); + SetSkill(SkillName.Anatomy, 75.4, 79.8); - // TODO: Fame/Karma + // TODO: Fame/Karma + } + + public Hydra(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a hydra corpse"; + public override string DefaultName => "a hydra"; + + public override bool HasBreath => true; + public override int Hides => 40; + public override int Meat => 19; + public override int TreasureMapLevel => 5; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 3); + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + c.DropItem(new HydraScale()); + + /* + // TODO: uncomment once added + if (Utility.RandomDouble() < 0.2) + c.DropItem( new ParrotItem() ); + + if (Utility.RandomDouble() < 0.05) + c.DropItem( new ThorvaldsMedallion() ); + */ + } + + 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 Hydra(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a hydra corpse"; - public override string DefaultName => "a hydra"; - - public override bool HasBreath => true; - public override int Hides => 40; - public override int Meat => 19; - public override int TreasureMapLevel => 5; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 3); - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - c.DropItem(new HydraScale()); - - /* - // TODO: uncomment once added - if (Utility.RandomDouble() < 0.2) - c.DropItem( new ParrotItem() ); - - if (Utility.RandomDouble() < 0.05) - c.DropItem( new ThorvaldsMedallion() ); - */ - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/InsaneDryad.cs b/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/InsaneDryad.cs index b3698cdd2..8be8eac1f 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/InsaneDryad.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/InsaneDryad.cs @@ -1,46 +1,46 @@ namespace Server.Mobiles { - public class InsaneDryad : MLDryad - { - [Constructible] - public InsaneDryad() + public class InsaneDryad : MLDryad { - // TODO: Perhaps these should have negative karma? + [Constructible] + public InsaneDryad() + { + // TODO: Perhaps these should have negative karma? + } + + /* + // TODO: uncomment once added + public override void OnDeath( Container c ) + { + base.OnDeath( c ); + + if (Utility.RandomDouble() < 0.1) + c.DropItem( new ParrotItem() ); + } + */ + + public InsaneDryad(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "an insane dryad corpse"; + public override bool InitialInnocent => false; + + public override string DefaultName => "an insane dryad"; + + 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(); + } } - - /* - // TODO: uncomment once added - public override void OnDeath( Container c ) - { - base.OnDeath( c ); - - if (Utility.RandomDouble() < 0.1) - c.DropItem( new ParrotItem() ); - } - */ - - public InsaneDryad(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "an insane dryad corpse"; - public override bool InitialInnocent => false; - - public override string DefaultName => "an insane dryad"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Saliva.cs b/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Saliva.cs index 1132e8f07..a82a715ae 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Saliva.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Saliva.cs @@ -2,75 +2,75 @@ using Server.Items; namespace Server.Mobiles { - public class Saliva : Harpy - { - [Constructible] - public Saliva() + public class Saliva : Harpy { - // TODO: Not a paragon? No ML arties? - // It moves like a paragon on OSI... + [Constructible] + public Saliva() + { + // TODO: Not a paragon? No ML arties? + // It moves like a paragon on OSI... - Hue = 0x11E; + Hue = 0x11E; - SetStr(110, 206); - SetDex(123, 222); - SetInt(80, 127); + SetStr(110, 206); + SetDex(123, 222); + SetInt(80, 127); - SetHits(409, 842); + SetHits(409, 842); - SetDamage(20, 22); + SetDamage(20, 22); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 46, 48); - SetResistance(ResistanceType.Fire, 32, 40); - SetResistance(ResistanceType.Cold, 34, 49); - SetResistance(ResistanceType.Poison, 40, 48); - SetResistance(ResistanceType.Energy, 35, 39); + SetResistance(ResistanceType.Physical, 46, 48); + SetResistance(ResistanceType.Fire, 32, 40); + SetResistance(ResistanceType.Cold, 34, 49); + SetResistance(ResistanceType.Poison, 40, 48); + SetResistance(ResistanceType.Energy, 35, 39); - SetSkill(SkillName.Wrestling, 106.4, 128.8); - SetSkill(SkillName.Tactics, 129.9, 141.0); - SetSkill(SkillName.MagicResist, 84.3, 105.0); + SetSkill(SkillName.Wrestling, 106.4, 128.8); + SetSkill(SkillName.Tactics, 129.9, 141.0); + SetSkill(SkillName.MagicResist, 84.3, 105.0); - // TODO: Fame/Karma? + // TODO: Fame/Karma? + } + + public Saliva(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Saliva corpse"; + public override string DefaultName => "Saliva"; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 2); + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + c.DropItem(new SalivasFeather()); + + // TODO: uncomment once added + // if (Utility.RandomDouble() < 0.1) + // c.DropItem( new ParrotItem() ); + } + + 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 Saliva(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Saliva corpse"; - public override string DefaultName => "Saliva"; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 2); - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - c.DropItem(new SalivasFeather()); - - // TODO: uncomment once added - // if (Utility.RandomDouble() < 0.1) - // c.DropItem( new ParrotItem() ); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Tangle.cs b/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Tangle.cs index 2fc2d8a6c..aa46d54a3 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Tangle.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Tangle.cs @@ -2,76 +2,76 @@ using Server.Items; namespace Server.Mobiles { - public class Tangle : BogThing - { - [Constructible] - public Tangle() + public class Tangle : BogThing { - // TODO: Not a paragon? No ML arties? - // It moves like a paragon on OSI... + [Constructible] + public Tangle() + { + // TODO: Not a paragon? No ML arties? + // It moves like a paragon on OSI... - Hue = 0x21; + Hue = 0x21; - SetStr(870, 940); - SetDex(58, 74); - SetInt(46, 58); + SetStr(870, 940); + SetDex(58, 74); + SetInt(46, 58); - SetHits(2468, 2733); - SetMana(8, 12); + SetHits(2468, 2733); + SetMana(8, 12); - SetDamage(15, 28); + SetDamage(15, 28); - SetDamageType(ResistanceType.Physical, 60); - SetDamageType(ResistanceType.Poison, 40); + SetDamageType(ResistanceType.Physical, 60); + SetDamageType(ResistanceType.Poison, 40); - SetResistance(ResistanceType.Physical, 50, 57); - SetResistance(ResistanceType.Fire, 40, 43); - SetResistance(ResistanceType.Cold, 30, 35); - SetResistance(ResistanceType.Poison, 61, 69); - SetResistance(ResistanceType.Energy, 41, 45); + SetResistance(ResistanceType.Physical, 50, 57); + SetResistance(ResistanceType.Fire, 40, 43); + SetResistance(ResistanceType.Cold, 30, 35); + SetResistance(ResistanceType.Poison, 61, 69); + SetResistance(ResistanceType.Energy, 41, 45); - SetSkill(SkillName.Wrestling, 77.8, 94.6); - SetSkill(SkillName.Tactics, 90.6, 100.4); - SetSkill(SkillName.MagicResist, 108.4, 114.0); + SetSkill(SkillName.Wrestling, 77.8, 94.6); + SetSkill(SkillName.Tactics, 90.6, 100.4); + SetSkill(SkillName.MagicResist, 108.4, 114.0); - // TODO: Fame/Karma? + // TODO: Fame/Karma? + } + + public Tangle(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Tangle corpse"; + public override string DefaultName => "Tangle"; + + public override Poison PoisonImmune => Poison.Lethal; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 3); + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + if (Utility.RandomDouble() < 0.3) + c.DropItem(new TaintedSeeds()); + } + + 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 Tangle(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Tangle corpse"; - public override string DefaultName => "Tangle"; - - public override Poison PoisonImmune => Poison.Lethal; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 3); - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - if (Utility.RandomDouble() < 0.3) - c.DropItem(new TaintedSeeds()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Thrasher.cs b/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Thrasher.cs index 09cdfc48d..379e9599c 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Thrasher.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Blighted Grove/Thrasher.cs @@ -2,76 +2,76 @@ using Server.Items; namespace Server.Mobiles { - public class Thrasher : Alligator - { - [Constructible] - public Thrasher() + public class Thrasher : Alligator { - IsParagon = true; + [Constructible] + public Thrasher() + { + IsParagon = true; - Hue = 0x497; + Hue = 0x497; - SetStr(93, 327); - SetDex(7, 201); - SetInt(15, 67); + SetStr(93, 327); + SetDex(7, 201); + SetInt(15, 67); - SetHits(260, 984); - SetStam(56, 75); - SetMana(25, 30); + SetHits(260, 984); + SetStam(56, 75); + SetMana(25, 30); - SetDamage(20, 30); + SetDamage(20, 30); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 50, 55); - SetResistance(ResistanceType.Fire, 25, 29); - SetResistance(ResistanceType.Poison, 25, 28); + SetResistance(ResistanceType.Physical, 50, 55); + SetResistance(ResistanceType.Fire, 25, 29); + SetResistance(ResistanceType.Poison, 25, 28); - SetSkill(SkillName.Wrestling, 101.2, 118.3); - SetSkill(SkillName.Tactics, 96.3, 117.3); - SetSkill(SkillName.MagicResist, 102.4, 118.6); + SetSkill(SkillName.Wrestling, 101.2, 118.3); + SetSkill(SkillName.Tactics, 96.3, 117.3); + SetSkill(SkillName.MagicResist, 102.4, 118.6); - // TODO: Fame/Karma + // TODO: Fame/Karma + } + + public Thrasher(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Thrasher corpse"; + public override string DefaultName => "Thrasher"; + + public override bool GivesMLMinorArtifact => true; + public override int Hides => 48; + public override int Meat => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 4); + } + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.ArmorIgnore; + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + c.DropItem(new ThrashersTail()); + } + + 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 Thrasher(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Thrasher corpse"; - public override string DefaultName => "Thrasher"; - - public override bool GivesMLMinorArtifact => true; - public override int Hides => 48; - public override int Meat => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 4); - } - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.ArmorIgnore; - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - c.DropItem(new ThrashersTail()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Magic/FetidEssence.cs b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Magic/FetidEssence.cs index 35da2df8f..fc7419898 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Magic/FetidEssence.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Magic/FetidEssence.cs @@ -1,92 +1,92 @@ namespace Server.Mobiles { - public class FetidEssence : BaseCreature - { - [Constructible] - public FetidEssence() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class FetidEssence : BaseCreature { - Body = 273; + [Constructible] + public FetidEssence() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 273; - SetStr(101, 150); - SetDex(210, 250); - SetInt(451, 550); + SetStr(101, 150); + SetDex(210, 250); + SetInt(451, 550); - SetHits(551, 650); + SetHits(551, 650); - SetDamage(21, 25); + SetDamage(21, 25); - SetDamageType(ResistanceType.Physical, 30); - SetDamageType(ResistanceType.Poison, 70); + SetDamageType(ResistanceType.Physical, 30); + SetDamageType(ResistanceType.Poison, 70); - SetResistance(ResistanceType.Physical, 40, 50); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 70, 90); - SetResistance(ResistanceType.Energy, 75, 80); + SetResistance(ResistanceType.Physical, 40, 50); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 70, 90); + SetResistance(ResistanceType.Energy, 75, 80); - SetSkill(SkillName.Meditation, 91.4, 99.4); - SetSkill(SkillName.EvalInt, 88.5, 92.3); - SetSkill(SkillName.Magery, 97.9, 101.7); - SetSkill(SkillName.Poisoning, 100); - SetSkill(SkillName.Anatomy, 0, 4.5); - SetSkill(SkillName.MagicResist, 103.5, 108.8); - SetSkill(SkillName.Tactics, 81.0, 84.6); - SetSkill(SkillName.Wrestling, 81.3, 83.9); + SetSkill(SkillName.Meditation, 91.4, 99.4); + SetSkill(SkillName.EvalInt, 88.5, 92.3); + SetSkill(SkillName.Magery, 97.9, 101.7); + SetSkill(SkillName.Poisoning, 100); + SetSkill(SkillName.Anatomy, 0, 4.5); + SetSkill(SkillName.MagicResist, 103.5, 108.8); + SetSkill(SkillName.Tactics, 81.0, 84.6); + SetSkill(SkillName.Wrestling, 81.3, 83.9); - Fame = 3700; // Guessed - Karma = -3700; // Guessed + Fame = 3700; // Guessed + Karma = -3700; // Guessed + } + + public FetidEssence(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a fetid essence corpse"; + public override string DefaultName => "a fetid essence"; + + public override Poison HitPoison => Poison.Deadly; + public override Poison PoisonImmune => Poison.Deadly; + + public override void GenerateLoot() // Need to verify + { + AddLoot(LootPack.FilthyRich); + } + + public override int GetAngerSound() => 0x56d; + + public override int GetIdleSound() => 0x56b; + + public override int GetAttackSound() => 0x56c; + + public override int GetHurtSound() => 0x56c; + + public override int GetDeathSound() => 0x56e; + + 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(); + } + + /*private class InternalTimer : Timer + { + private Mobile m_From; + private Mobile m_Mobile; + private int m_Count; + + public InternalTimer( Mobile from, Mobile m ) : base( TimeSpan.FromSeconds( 1.0 ), TimeSpan.FromSeconds( 1.0 ) ) + { + m_From = from; + m_Mobile = m; + Priority = TimerPriority.TwoFiftyMS; + } + + }*/ } - - public FetidEssence(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a fetid essence corpse"; - public override string DefaultName => "a fetid essence"; - - public override Poison HitPoison => Poison.Deadly; - public override Poison PoisonImmune => Poison.Deadly; - - public override void GenerateLoot() // Need to verify - { - AddLoot(LootPack.FilthyRich); - } - - public override int GetAngerSound() => 0x56d; - - public override int GetIdleSound() => 0x56b; - - public override int GetAttackSound() => 0x56c; - - public override int GetHurtSound() => 0x56c; - - public override int GetDeathSound() => 0x56e; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - - /*private class InternalTimer : Timer - { - private Mobile m_From; - private Mobile m_Mobile; - private int m_Count; - - public InternalTimer( Mobile from, Mobile m ) : base( TimeSpan.FromSeconds( 1.0 ), TimeSpan.FromSeconds( 1.0 ) ) - { - m_From = from; - m_Mobile = m; - Priority = TimerPriority.TwoFiftyMS; - } - - }*/ - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Magic/InterredGrizzle .cs b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Magic/InterredGrizzle .cs index 9865a4037..94da8ee6c 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Magic/InterredGrizzle .cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Magic/InterredGrizzle .cs @@ -2,146 +2,146 @@ using System.Linq; namespace Server.Mobiles { - public class InterredGrizzle : BaseCreature - { - [Constructible] - public InterredGrizzle() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class InterredGrizzle : BaseCreature { - Body = 259; - - SetStr(451, 500); - SetDex(201, 250); - SetInt(801, 850); - - SetHits(1500); - SetStam(150); - - SetDamage(16, 19); - - SetDamageType(ResistanceType.Physical, 30); - SetDamageType(ResistanceType.Fire, 70); - - SetResistance(ResistanceType.Physical, 35, 55); - SetResistance(ResistanceType.Fire, 20, 65); - SetResistance(ResistanceType.Cold, 55, 80); - SetResistance(ResistanceType.Poison, 20, 35); - SetResistance(ResistanceType.Energy, 60, 80); - - SetSkill(SkillName.Meditation, 77.7, 84.0); - SetSkill(SkillName.EvalInt, 72.2, 79.6); - SetSkill(SkillName.Magery, 83.7, 89.6); - SetSkill(SkillName.Poisoning, 0); - SetSkill(SkillName.Anatomy, 0); - SetSkill(SkillName.MagicResist, 80.2, 87.3); - SetSkill(SkillName.Tactics, 104.5, 105.1); - SetSkill(SkillName.Wrestling, 105.1, 109.4); - - Fame = 3700; // Guessed - Karma = -3700; // Guessed - } - /* - public override bool OnBeforeDeath() - { - SpillAcid( 1, 4, 10, 6, 10 ); - - return base.OnBeforeDeath(); - } - */ - - public InterredGrizzle(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an interred grizzle corpse"; - public override string DefaultName => "a interred grizzle"; - - public override void GenerateLoot() // -- Need to verify - { - AddLoot(LootPack.FilthyRich); - } - - // TODO: Acid Blood - /* - * Message: 1070820 - * Spits pool of acid (blood, hue 0x3F), hits lost 6-10 per second/step - * Damage is resistable (physical) - * Acid last 10 seconds - */ - - public override int GetAngerSound() => 0x581; - - public override int GetIdleSound() => 0x582; - - public override int GetAttackSound() => 0x580; - - public override int GetHurtSound() => 0x583; - - public override int GetDeathSound() => 0x584; - - public override void OnDamage(int amount, Mobile from, bool willKill) - { - if (Utility.RandomDouble() < 0.1) - DropOoze(); - - base.OnDamage(amount, from, willKill); - } - - private int RandomPoint(int mid) => mid + Utility.RandomMinMax(-2, 2); - - public virtual Point3D GetSpawnPosition(int range) => GetSpawnPosition(Location, Map, range); - - public virtual Point3D GetSpawnPosition(Point3D from, Map map, int range) - { - if (map == null) - return from; - - Point3D loc = new Point3D(RandomPoint(X), RandomPoint(Y), Z); - - loc.Z = Map.GetAverageZ(loc.X, loc.Y); - - return loc; - } - - public virtual void DropOoze() - { - int amount = Utility.RandomMinMax(1, 3); - bool corrosive = Utility.RandomBool(); - - for (int i = 0; i < amount; i++) - { - Item ooze = new StainedOoze(corrosive); - Point3D p = new Point3D(Location); - - for (int j = 0; j < 5; j++) + [Constructible] + public InterredGrizzle() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) { - p = GetSpawnPosition(2); + Body = 259; - if (!Map.GetItemsInRange(p, 0).OfType().Any()) - break; + SetStr(451, 500); + SetDex(201, 250); + SetInt(801, 850); + + SetHits(1500); + SetStam(150); + + SetDamage(16, 19); + + SetDamageType(ResistanceType.Physical, 30); + SetDamageType(ResistanceType.Fire, 70); + + SetResistance(ResistanceType.Physical, 35, 55); + SetResistance(ResistanceType.Fire, 20, 65); + SetResistance(ResistanceType.Cold, 55, 80); + SetResistance(ResistanceType.Poison, 20, 35); + SetResistance(ResistanceType.Energy, 60, 80); + + SetSkill(SkillName.Meditation, 77.7, 84.0); + SetSkill(SkillName.EvalInt, 72.2, 79.6); + SetSkill(SkillName.Magery, 83.7, 89.6); + SetSkill(SkillName.Poisoning, 0); + SetSkill(SkillName.Anatomy, 0); + SetSkill(SkillName.MagicResist, 80.2, 87.3); + SetSkill(SkillName.Tactics, 104.5, 105.1); + SetSkill(SkillName.Wrestling, 105.1, 109.4); + + Fame = 3700; // Guessed + Karma = -3700; // Guessed + } + /* + public override bool OnBeforeDeath() + { + SpillAcid( 1, 4, 10, 6, 10 ); + + return base.OnBeforeDeath(); + } + */ + + public InterredGrizzle(Serial serial) : base(serial) + { } - ooze.MoveToWorld(p, Map); - } + public override string CorpseName => "an interred grizzle corpse"; + public override string DefaultName => "a interred grizzle"; - if (Combatant != null) - { - if (corrosive) - Combatant.SendLocalizedMessage(1072071); // A corrosive gas seeps out of your enemy's skin! - else - Combatant.SendLocalizedMessage(1072072); // A poisonous gas seeps out of your enemy's skin! - } - } + public override void GenerateLoot() // -- Need to verify + { + AddLoot(LootPack.FilthyRich); + } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } + // TODO: Acid Blood + /* + * Message: 1070820 + * Spits pool of acid (blood, hue 0x3F), hits lost 6-10 per second/step + * Damage is resistable (physical) + * Acid last 10 seconds + */ - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); + public override int GetAngerSound() => 0x581; + + public override int GetIdleSound() => 0x582; + + public override int GetAttackSound() => 0x580; + + public override int GetHurtSound() => 0x583; + + public override int GetDeathSound() => 0x584; + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + if (Utility.RandomDouble() < 0.1) + DropOoze(); + + base.OnDamage(amount, from, willKill); + } + + private int RandomPoint(int mid) => mid + Utility.RandomMinMax(-2, 2); + + public virtual Point3D GetSpawnPosition(int range) => GetSpawnPosition(Location, Map, range); + + public virtual Point3D GetSpawnPosition(Point3D from, Map map, int range) + { + if (map == null) + return from; + + var loc = new Point3D(RandomPoint(X), RandomPoint(Y), Z); + + loc.Z = Map.GetAverageZ(loc.X, loc.Y); + + return loc; + } + + public virtual void DropOoze() + { + var amount = Utility.RandomMinMax(1, 3); + var corrosive = Utility.RandomBool(); + + for (var i = 0; i < amount; i++) + { + Item ooze = new StainedOoze(corrosive); + var p = new Point3D(Location); + + for (var j = 0; j < 5; j++) + { + p = GetSpawnPosition(2); + + if (!Map.GetItemsInRange(p, 0).OfType().Any()) + break; + } + + ooze.MoveToWorld(p, Map); + } + + if (Combatant != null) + { + if (corrosive) + Combatant.SendLocalizedMessage(1072071); // A corrosive gas seeps out of your enemy's skin! + else + Combatant.SendLocalizedMessage(1072072); // A poisonous gas seeps out of your enemy's skin! + } + } + + 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(); + } } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Magic/MLDryad.cs b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Magic/MLDryad.cs index 1ceca84b8..503bf7134 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Magic/MLDryad.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Magic/MLDryad.cs @@ -3,149 +3,150 @@ using Server.Engines.Plants; namespace Server.Mobiles { - public class MLDryad : BaseCreature - { - [Constructible] - public MLDryad() : base(AIType.AI_Mage, FightMode.Evil, 10, 1, 0.2, 0.4) + public class MLDryad : BaseCreature { - Body = 266; - BaseSoundID = 0x57B; + private DateTime m_NextPeace; - SetStr(132, 149); - SetDex(152, 168); - SetInt(251, 280); + private DateTime m_NextUndress; - SetHits(304, 321); - - SetDamage(11, 20); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 40, 50); - SetResistance(ResistanceType.Fire, 15, 25); - SetResistance(ResistanceType.Cold, 40, 45); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 25, 35); - - SetSkill(SkillName.Meditation, 80.0, 90.0); - SetSkill(SkillName.EvalInt, 70.0, 80.0); - SetSkill(SkillName.Magery, 70.0, 80.0); - SetSkill(SkillName.Anatomy, 0); - SetSkill(SkillName.MagicResist, 100.0, 120.0); - SetSkill(SkillName.Tactics, 70.0, 80.0); - SetSkill(SkillName.Wrestling, 70.0, 80.0); - - Fame = 5000; - Karma = 5000; - - VirtualArmor = 28; // Don't know what it should be - - if (Core.ML && Utility.RandomDouble() < .60) - PackItem(Seed.RandomPeculiarSeed(1)); - - PackArcanceScroll(0.05); - } - - public MLDryad(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a dryad's corpse"; - public override bool InitialInnocent => true; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override string DefaultName => "a dryad"; - - public override int Meat => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.MlRich); - } - - public override void OnThink() - { - base.OnThink(); - - AreaPeace(); - AreaUndress(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private DateTime m_NextPeace; - - public void AreaPeace() - { - if (Combatant == null || Deleted || !Alive || m_NextPeace > DateTime.UtcNow || Utility.RandomDouble() > 0.1) - return; - - TimeSpan duration = TimeSpan.FromSeconds(Utility.RandomMinMax(20, 80)); - - foreach (Mobile m in GetMobilesInRange(RangePerception)) - { - PlayerMobile p = m as PlayerMobile; - - if (IsValidTarget(p)) + [Constructible] + public MLDryad() : base(AIType.AI_Mage, FightMode.Evil, 10, 1, 0.2, 0.4) { - p.PeacedUntil = DateTime.UtcNow + duration; - p.SendLocalizedMessage(1072065); // You gaze upon the dryad's beauty, and forget to continue battling! - p.FixedParticles(0x376A, 1, 20, 0x7F5, EffectLayer.Waist); - p.Combatant = null; - } - } + Body = 266; + BaseSoundID = 0x57B; - m_NextPeace = DateTime.UtcNow + TimeSpan.FromSeconds(10); - PlaySound(0x1D3); - } + SetStr(132, 149); + SetDex(152, 168); + SetInt(251, 280); - public bool IsValidTarget(PlayerMobile m) => - m?.PeacedUntil < DateTime.UtcNow && !m.Hidden && m.AccessLevel == AccessLevel.Player && - CanBeHarmful(m); + SetHits(304, 321); - private DateTime m_NextUndress; + SetDamage(11, 20); - public void AreaUndress() - { - if (Combatant == null || Deleted || !Alive || m_NextUndress > DateTime.UtcNow || Utility.RandomDouble() > 0.005) - return; + SetDamageType(ResistanceType.Physical, 100); - foreach (Mobile m in GetMobilesInRange(RangePerception)) - if (m?.Player == true && !m.Female && !m.Hidden && m.AccessLevel == AccessLevel.Player && - CanBeHarmful(m)) - { - UndressItem(m, Layer.OuterTorso); - UndressItem(m, Layer.InnerTorso); - UndressItem(m, Layer.MiddleTorso); - UndressItem(m, Layer.Pants); - UndressItem(m, Layer.Shirt); + SetResistance(ResistanceType.Physical, 40, 50); + SetResistance(ResistanceType.Fire, 15, 25); + SetResistance(ResistanceType.Cold, 40, 45); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 25, 35); - m.SendLocalizedMessage( - 1072197); // The dryad's beauty makes your blood race. Your clothing is too confining. + SetSkill(SkillName.Meditation, 80.0, 90.0); + SetSkill(SkillName.EvalInt, 70.0, 80.0); + SetSkill(SkillName.Magery, 70.0, 80.0); + SetSkill(SkillName.Anatomy, 0); + SetSkill(SkillName.MagicResist, 100.0, 120.0); + SetSkill(SkillName.Tactics, 70.0, 80.0); + SetSkill(SkillName.Wrestling, 70.0, 80.0); + + Fame = 5000; + Karma = 5000; + + VirtualArmor = 28; // Don't know what it should be + + if (Core.ML && Utility.RandomDouble() < .60) + PackItem(Seed.RandomPeculiarSeed(1)); + + PackArcanceScroll(0.05); } - m_NextUndress = DateTime.UtcNow + TimeSpan.FromMinutes(1); - } + public MLDryad(Serial serial) : base(serial) + { + } - public void UndressItem(Mobile m, Layer layer) - { - Item item = m.FindItemOnLayer(layer); + public override string CorpseName => "a dryad's corpse"; + public override bool InitialInnocent => true; - if (item?.Movable == true) - m.PlaceInBackpack(item); + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override string DefaultName => "a dryad"; + + public override int Meat => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.MlRich); + } + + public override void OnThink() + { + base.OnThink(); + + AreaPeace(); + AreaUndress(); + } + + 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 void AreaPeace() + { + if (Combatant == null || Deleted || !Alive || m_NextPeace > DateTime.UtcNow || Utility.RandomDouble() > 0.1) + return; + + var duration = TimeSpan.FromSeconds(Utility.RandomMinMax(20, 80)); + + foreach (var m in GetMobilesInRange(RangePerception)) + { + var p = m as PlayerMobile; + + if (IsValidTarget(p)) + { + p.PeacedUntil = DateTime.UtcNow + duration; + p.SendLocalizedMessage(1072065); // You gaze upon the dryad's beauty, and forget to continue battling! + p.FixedParticles(0x376A, 1, 20, 0x7F5, EffectLayer.Waist); + p.Combatant = null; + } + } + + m_NextPeace = DateTime.UtcNow + TimeSpan.FromSeconds(10); + PlaySound(0x1D3); + } + + public bool IsValidTarget(PlayerMobile m) => + m?.PeacedUntil < DateTime.UtcNow && !m.Hidden && m.AccessLevel == AccessLevel.Player && + CanBeHarmful(m); + + public void AreaUndress() + { + if (Combatant == null || Deleted || !Alive || m_NextUndress > DateTime.UtcNow || Utility.RandomDouble() > 0.005) + return; + + foreach (var m in GetMobilesInRange(RangePerception)) + if (m?.Player == true && !m.Female && !m.Hidden && m.AccessLevel == AccessLevel.Player && + CanBeHarmful(m)) + { + UndressItem(m, Layer.OuterTorso); + UndressItem(m, Layer.InnerTorso); + UndressItem(m, Layer.MiddleTorso); + UndressItem(m, Layer.Pants); + UndressItem(m, Layer.Shirt); + + m.SendLocalizedMessage( + 1072197 + ); // The dryad's beauty makes your blood race. Your clothing is too confining. + } + + m_NextUndress = DateTime.UtcNow + TimeSpan.FromMinutes(1); + } + + public void UndressItem(Mobile m, Layer layer) + { + var item = m.FindItemOnLayer(layer); + + if (item?.Movable == true) + m.PlaceInBackpack(item); + } } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Magic/Satyr.cs b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Magic/Satyr.cs index 61fd2fa24..c3545a8a1 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Magic/Satyr.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Magic/Satyr.cs @@ -3,223 +3,224 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class Satyr : BaseCreature - { - [Constructible] - public Satyr() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Satyr : BaseCreature { - Body = 271; - BaseSoundID = 0x586; + private static readonly Dictionary m_Suppressed = new Dictionary(); - SetStr(177, 195); - SetDex(251, 269); - SetInt(153, 170); + private DateTime m_NextPeace; - SetHits(350, 400); + private DateTime m_NextProvoke; + private DateTime m_NextSuppress; - SetDamage(13, 24); + private DateTime m_NextUndress; - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 55, 60); - SetResistance(ResistanceType.Fire, 25, 35); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 30, 40); - - SetSkill(SkillName.MagicResist, 55.0, 65.0); - SetSkill(SkillName.Tactics, 80.0, 100.0); - SetSkill(SkillName.Wrestling, 80.0, 100.0); - - Fame = 5000; - Karma = 0; - - VirtualArmor = 28; // Don't know what it should be - - PackArcanceScroll(0.05); - } - - public Satyr(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a satyr's corpse"; - public override string DefaultName => "a satyr"; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override int Meat => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.MlRich); - } - - public override void OnThink() - { - base.OnThink(); - - Peace(Combatant); - Undress(Combatant); - Suppress(Combatant); - Provoke(Combatant); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private DateTime m_NextPeace; - - public void Peace(Mobile target) - { - if (target == null || Deleted || !Alive || m_NextPeace > DateTime.UtcNow || Utility.RandomDouble() > 0.1) - return; - - if (target is PlayerMobile p && p.PeacedUntil < DateTime.UtcNow && !p.Hidden && CanBeHarmful(p)) - { - p.PeacedUntil = DateTime.UtcNow + TimeSpan.FromMinutes(1); - p.SendLocalizedMessage(500616); // You hear lovely music, and forget to continue battling! - p.FixedParticles(0x376A, 1, 32, 0x15BD, EffectLayer.Waist); - p.Combatant = null; - - PlaySound(0x58D); - } - - m_NextPeace = DateTime.UtcNow + TimeSpan.FromSeconds(10); - } - - private static readonly Dictionary m_Suppressed = new Dictionary(); - private DateTime m_NextSuppress; - - public void Suppress(Mobile target) - { - if (target == null || m_Suppressed.ContainsKey(target) || Deleted || !Alive || - m_NextSuppress > DateTime.UtcNow || Utility.RandomDouble() > 0.1) - return; - - TimeSpan delay = TimeSpan.FromSeconds(Utility.RandomMinMax(20, 80)); - - if (!target.Hidden && CanBeHarmful(target)) - { - target.SendLocalizedMessage(1072061); // You hear jarring music, suppressing your strength. - - for (int i = 0; i < target.Skills.Length; i++) + [Constructible] + public Satyr() : base(AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4) { - Skill s = target.Skills[i]; + Body = 271; + BaseSoundID = 0x586; - target.AddSkillMod(new TimedSkillMod(s.SkillName, true, s.Base * -0.28, delay)); + SetStr(177, 195); + SetDex(251, 269); + SetInt(153, 170); + + SetHits(350, 400); + + SetDamage(13, 24); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 55, 60); + SetResistance(ResistanceType.Fire, 25, 35); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 30, 40); + + SetSkill(SkillName.MagicResist, 55.0, 65.0); + SetSkill(SkillName.Tactics, 80.0, 100.0); + SetSkill(SkillName.Wrestling, 80.0, 100.0); + + Fame = 5000; + Karma = 0; + + VirtualArmor = 28; // Don't know what it should be + + PackArcanceScroll(0.05); } - int count = (int)Math.Round(delay.TotalSeconds / 1.25); - Timer timer = new AnimateTimer(target, count); - m_Suppressed.Add(target, timer); - timer.Start(); - - PlaySound(0x58C); - } - - m_NextSuppress = DateTime.UtcNow + TimeSpan.FromSeconds(10); - } - - public static void SuppressRemove(Mobile target) - { - if (target == null) - return; - - if (m_Suppressed.TryGetValue(target, out Timer t)) - { - if (t.Running) - t.Stop(); - - m_Suppressed.Remove(target); - } - } - - private class AnimateTimer : Timer - { - private int m_Count; - private readonly Mobile m_Owner; - - public AnimateTimer(Mobile owner, int count) : base(TimeSpan.Zero, TimeSpan.FromSeconds(1.25)) - { - m_Owner = owner; - m_Count = count; - } - - protected override void OnTick() - { - if (m_Owner.Deleted || !m_Owner.Alive || m_Count-- < 0) - SuppressRemove(m_Owner); - else - m_Owner.FixedParticles(0x376A, 1, 32, 0x15BD, EffectLayer.Waist); - } - } - - private DateTime m_NextUndress; - - public void Undress(Mobile target) - { - if (target == null || Deleted || !Alive || m_NextUndress > DateTime.UtcNow || Utility.RandomDouble() > 0.005) - return; - - if (target.Player && target.Female && !target.Hidden && CanBeHarmful(target)) - { - UndressItem(target, Layer.OuterTorso); - UndressItem(target, Layer.InnerTorso); - UndressItem(target, Layer.MiddleTorso); - UndressItem(target, Layer.Pants); - UndressItem(target, Layer.Shirt); - - target.SendLocalizedMessage( - 1072196); // The satyr's music makes your blood race. Your clothing is too confining. - } - - m_NextUndress = DateTime.UtcNow + TimeSpan.FromMinutes(1); - } - - public void UndressItem(Mobile m, Layer layer) - { - Item item = m.FindItemOnLayer(layer); - - if (item?.Movable == true) - m.PlaceInBackpack(item); - } - - private DateTime m_NextProvoke; - - public void Provoke(Mobile target) - { - if (target == null || Deleted || !Alive || m_NextProvoke > DateTime.UtcNow || Utility.RandomDouble() > 0.05) - return; - - foreach (Mobile m in GetMobilesInRange(RangePerception)) - if (m is BaseCreature c) + public Satyr(Serial serial) : base(serial) { - if (c == this || c == target || c.Unprovokable || c.IsParagon || c.BardProvoked || - c.AccessLevel != AccessLevel.Player || !c.CanBeHarmful(target)) - continue; - - c.Provoke(this, target, true); - - if (target.Player) - target.SendLocalizedMessage(1072062); // You hear angry music, and start to fight. - - PlaySound(0x58A); - break; } - m_NextProvoke = DateTime.UtcNow + TimeSpan.FromSeconds(10); + public override string CorpseName => "a satyr's corpse"; + public override string DefaultName => "a satyr"; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override int Meat => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.MlRich); + } + + public override void OnThink() + { + base.OnThink(); + + Peace(Combatant); + Undress(Combatant); + Suppress(Combatant); + Provoke(Combatant); + } + + 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 void Peace(Mobile target) + { + if (target == null || Deleted || !Alive || m_NextPeace > DateTime.UtcNow || Utility.RandomDouble() > 0.1) + return; + + if (target is PlayerMobile p && p.PeacedUntil < DateTime.UtcNow && !p.Hidden && CanBeHarmful(p)) + { + p.PeacedUntil = DateTime.UtcNow + TimeSpan.FromMinutes(1); + p.SendLocalizedMessage(500616); // You hear lovely music, and forget to continue battling! + p.FixedParticles(0x376A, 1, 32, 0x15BD, EffectLayer.Waist); + p.Combatant = null; + + PlaySound(0x58D); + } + + m_NextPeace = DateTime.UtcNow + TimeSpan.FromSeconds(10); + } + + public void Suppress(Mobile target) + { + if (target == null || m_Suppressed.ContainsKey(target) || Deleted || !Alive || + m_NextSuppress > DateTime.UtcNow || Utility.RandomDouble() > 0.1) + return; + + var delay = TimeSpan.FromSeconds(Utility.RandomMinMax(20, 80)); + + if (!target.Hidden && CanBeHarmful(target)) + { + target.SendLocalizedMessage(1072061); // You hear jarring music, suppressing your strength. + + for (var i = 0; i < target.Skills.Length; i++) + { + var s = target.Skills[i]; + + target.AddSkillMod(new TimedSkillMod(s.SkillName, true, s.Base * -0.28, delay)); + } + + var count = (int)Math.Round(delay.TotalSeconds / 1.25); + Timer timer = new AnimateTimer(target, count); + m_Suppressed.Add(target, timer); + timer.Start(); + + PlaySound(0x58C); + } + + m_NextSuppress = DateTime.UtcNow + TimeSpan.FromSeconds(10); + } + + public static void SuppressRemove(Mobile target) + { + if (target == null) + return; + + if (m_Suppressed.TryGetValue(target, out var t)) + { + if (t.Running) + t.Stop(); + + m_Suppressed.Remove(target); + } + } + + public void Undress(Mobile target) + { + if (target == null || Deleted || !Alive || m_NextUndress > DateTime.UtcNow || Utility.RandomDouble() > 0.005) + return; + + if (target.Player && target.Female && !target.Hidden && CanBeHarmful(target)) + { + UndressItem(target, Layer.OuterTorso); + UndressItem(target, Layer.InnerTorso); + UndressItem(target, Layer.MiddleTorso); + UndressItem(target, Layer.Pants); + UndressItem(target, Layer.Shirt); + + target.SendLocalizedMessage( + 1072196 + ); // The satyr's music makes your blood race. Your clothing is too confining. + } + + m_NextUndress = DateTime.UtcNow + TimeSpan.FromMinutes(1); + } + + public void UndressItem(Mobile m, Layer layer) + { + var item = m.FindItemOnLayer(layer); + + if (item?.Movable == true) + m.PlaceInBackpack(item); + } + + public void Provoke(Mobile target) + { + if (target == null || Deleted || !Alive || m_NextProvoke > DateTime.UtcNow || Utility.RandomDouble() > 0.05) + return; + + foreach (var m in GetMobilesInRange(RangePerception)) + if (m is BaseCreature c) + { + if (c == this || c == target || c.Unprovokable || c.IsParagon || c.BardProvoked || + c.AccessLevel != AccessLevel.Player || !c.CanBeHarmful(target)) + continue; + + c.Provoke(this, target, true); + + if (target.Player) + target.SendLocalizedMessage(1072062); // You hear angry music, and start to fight. + + PlaySound(0x58A); + break; + } + + m_NextProvoke = DateTime.UtcNow + TimeSpan.FromSeconds(10); + } + + private class AnimateTimer : Timer + { + private readonly Mobile m_Owner; + private int m_Count; + + public AnimateTimer(Mobile owner, int count) : base(TimeSpan.Zero, TimeSpan.FromSeconds(1.25)) + { + m_Owner = owner; + m_Count = count; + } + + protected override void OnTick() + { + if (m_Owner.Deleted || !m_Owner.Alive || m_Count-- < 0) + SuppressRemove(m_Owner); + else + m_Owner.FixedParticles(0x376A, 1, 32, 0x15BD, EffectLayer.Waist); + } + } } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/CorruptedSoul.cs b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/CorruptedSoul.cs index 53fa70862..2cf934006 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/CorruptedSoul.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/CorruptedSoul.cs @@ -1,89 +1,89 @@ namespace Server.Mobiles { - public class CorruptedSoul : BaseCreature - { - [Constructible] - public CorruptedSoul() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, .1, 5) + public class CorruptedSoul : BaseCreature { - Body = 0x3CA; - Hue = 0x453; + [Constructible] + public CorruptedSoul() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, .1, 5) + { + Body = 0x3CA; + Hue = 0x453; - SetStr(102, 115); - SetDex(101, 115); - SetInt(203, 215); + SetStr(102, 115); + SetDex(101, 115); + SetInt(203, 215); - SetHits(61, 69); + SetHits(61, 69); - SetDamage(4, 40); + SetDamage(4, 40); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 61, 74); - SetResistance(ResistanceType.Fire, 22, 48); - SetResistance(ResistanceType.Cold, 73, 100); - SetResistance(ResistanceType.Poison, 0); - SetResistance(ResistanceType.Energy, 51, 60); + SetResistance(ResistanceType.Physical, 61, 74); + SetResistance(ResistanceType.Fire, 22, 48); + SetResistance(ResistanceType.Cold, 73, 100); + SetResistance(ResistanceType.Poison, 0); + SetResistance(ResistanceType.Energy, 51, 60); - SetSkill(SkillName.MagicResist, 80.2, 89.4); - SetSkill(SkillName.Tactics, 81.3, 89.9); - SetSkill(SkillName.Wrestling, 80.1, 88.7); + SetSkill(SkillName.MagicResist, 80.2, 89.4); + SetSkill(SkillName.Tactics, 81.3, 89.9); + SetSkill(SkillName.Wrestling, 80.1, 88.7); - Fame = 5000; - Karma = -5000; + Fame = 5000; + Karma = -5000; - // VirtualArmor = 6; Not sure + // VirtualArmor = 6; Not sure + } + + public CorruptedSoul(Serial serial) : base(serial) + { + } + + public override bool DeleteCorpseOnDeath => true; + + public override string DefaultName => "a corrupted soul"; + + public override bool AlwaysAttackable => true; + public override bool BleedImmune => true; // NEED TO VERIFY + + /*public override int GetDeathSound() + { + return 0x0; + }*/ + + public override bool AlwaysMurderer => true; + + // NEED TO VERIFY SOUNDS! Known: No Idle Sound. + + /*public override int GetAngerSound() + { + return 0x0; + }*/ + + public override int GetAttackSound() => 0x233; + + // TODO: Proper OnDeath Effect + + public override bool OnBeforeDeath() + { + if (!base.OnBeforeDeath()) + return false; + + // 1 in 20 chance that a Thread of Fate will appear in the killer's pack + + Effects.SendLocationEffect(Location, Map, 0x376A, 10, 1); + return true; + } + + 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(); + } } - - public CorruptedSoul(Serial serial) : base(serial) - { - } - - public override bool DeleteCorpseOnDeath => true; - - public override string DefaultName => "a corrupted soul"; - - public override bool AlwaysAttackable => true; - public override bool BleedImmune => true; // NEED TO VERIFY - - /*public override int GetDeathSound() - { - return 0x0; - }*/ - - public override bool AlwaysMurderer => true; - - // NEED TO VERIFY SOUNDS! Known: No Idle Sound. - - /*public override int GetAngerSound() - { - return 0x0; - }*/ - - public override int GetAttackSound() => 0x233; - - // TODO: Proper OnDeath Effect - - public override bool OnBeforeDeath() - { - if (!base.OnBeforeDeath()) - return false; - - // 1 in 20 chance that a Thread of Fate will appear in the killer's pack - - Effects.SendLocationEffect(Location, Map, 0x376A, 10, 1); - return true; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/FerelTreefellow.cs b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/FerelTreefellow.cs index 7265827ff..f375eeb4e 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/FerelTreefellow.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/FerelTreefellow.cs @@ -2,75 +2,75 @@ using Server.Items; namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.FerelTreefellow")] - public class FeralTreefellow : BaseCreature - { - [Constructible] - public FeralTreefellow() : base(AIType.AI_Melee, FightMode.Evil, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.FerelTreefellow")] + public class FeralTreefellow : BaseCreature { - Body = 301; + [Constructible] + public FeralTreefellow() : base(AIType.AI_Melee, FightMode.Evil, 10, 1, 0.2, 0.4) + { + Body = 301; - SetStr(1351, 1600); - SetDex(301, 550); - SetInt(651, 900); + SetStr(1351, 1600); + SetDex(301, 550); + SetInt(651, 900); - SetHits(1170, 1320); + SetHits(1170, 1320); - SetDamage(26, 35); + SetDamage(26, 35); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 60, 70); - SetResistance(ResistanceType.Cold, 70, 80); - SetResistance(ResistanceType.Poison, 60, 70); - SetResistance(ResistanceType.Energy, 40, 60); + SetResistance(ResistanceType.Physical, 60, 70); + SetResistance(ResistanceType.Cold, 70, 80); + SetResistance(ResistanceType.Poison, 60, 70); + SetResistance(ResistanceType.Energy, 40, 60); - SetSkill(SkillName.MagicResist, 40.1, 55.0); // Unknown - SetSkill(SkillName.Tactics, 65.1, 90.0); // Unknown - SetSkill(SkillName.Wrestling, 65.1, 85.0); // Unknown + SetSkill(SkillName.MagicResist, 40.1, 55.0); // Unknown + SetSkill(SkillName.Tactics, 65.1, 90.0); // Unknown + SetSkill(SkillName.Wrestling, 65.1, 85.0); // Unknown - Fame = 12500; // Unknown - Karma = 12500; // Unknown + Fame = 12500; // Unknown + Karma = 12500; // Unknown - VirtualArmor = 24; - PackItem(new Log(Utility.RandomMinMax(23, 34))); + VirtualArmor = 24; + PackItem(new Log(Utility.RandomMinMax(23, 34))); + } + + public FeralTreefellow(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a treefellow corpse"; + + public override string DefaultName => "a feral treefellow"; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override bool BleedImmune => true; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.Dismount; + + public override int GetIdleSound() => 443; + + public override int GetDeathSound() => 31; + + public override int GetAttackSound() => 672; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); // Unknown + } + + 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(); + } } - - public FeralTreefellow(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a treefellow corpse"; - - public override string DefaultName => "a feral treefellow"; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override bool BleedImmune => true; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.Dismount; - - public override int GetIdleSound() => 443; - - public override int GetDeathSound() => 31; - - public override int GetAttackSound() => 672; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); // Unknown - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/Minotaur.cs b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/Minotaur.cs index 490367ce1..7fb8be852 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/Minotaur.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/Minotaur.cs @@ -2,80 +2,80 @@ using Server.Items; namespace Server.Mobiles { - public class Minotaur : BaseCreature - { - [Constructible] - public Minotaur() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) // NEED TO CHECK + public class Minotaur : BaseCreature { - Body = 263; + [Constructible] + public Minotaur() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) // NEED TO CHECK + { + Body = 263; - SetStr(301, 340); - SetDex(91, 110); - SetInt(31, 50); + SetStr(301, 340); + SetDex(91, 110); + SetInt(31, 50); - SetHits(301, 340); + SetHits(301, 340); - SetDamage(11, 20); + SetDamage(11, 20); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 55, 65); - SetResistance(ResistanceType.Fire, 25, 35); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 55, 65); + SetResistance(ResistanceType.Fire, 25, 35); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.Meditation, 0); - SetSkill(SkillName.EvalInt, 0); - SetSkill(SkillName.Magery, 0); - SetSkill(SkillName.Poisoning, 0); - SetSkill(SkillName.Anatomy, 0); - SetSkill(SkillName.MagicResist, 56.1, 64.0); - SetSkill(SkillName.Tactics, 93.3, 97.8); - SetSkill(SkillName.Wrestling, 90.4, 92.1); + SetSkill(SkillName.Meditation, 0); + SetSkill(SkillName.EvalInt, 0); + SetSkill(SkillName.Magery, 0); + SetSkill(SkillName.Poisoning, 0); + SetSkill(SkillName.Anatomy, 0); + SetSkill(SkillName.MagicResist, 56.1, 64.0); + SetSkill(SkillName.Tactics, 93.3, 97.8); + SetSkill(SkillName.Wrestling, 90.4, 92.1); - Fame = 5000; - Karma = -5000; + Fame = 5000; + Karma = -5000; - VirtualArmor = 28; // Don't know what it should be + VirtualArmor = 28; // Don't know what it should be + } + + public Minotaur(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a minotaur corpse"; + + public override string DefaultName => "a minotaur"; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.ParalyzingBlow; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); // Need to verify + } + + // Using Tormented Minotaur sounds - Need to veryfy + public override int GetAngerSound() => 0x597; + + public override int GetIdleSound() => 0x596; + + public override int GetAttackSound() => 0x599; + + public override int GetHurtSound() => 0x59a; + + public override int GetDeathSound() => 0x59c; + + 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(); + } } - - public Minotaur(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a minotaur corpse"; - - public override string DefaultName => "a minotaur"; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.ParalyzingBlow; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); // Need to verify - } - - // Using Tormented Minotaur sounds - Need to veryfy - public override int GetAngerSound() => 0x597; - - public override int GetIdleSound() => 0x596; - - public override int GetAttackSound() => 0x599; - - public override int GetHurtSound() => 0x59a; - - public override int GetDeathSound() => 0x59c; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/MinotaurCaptain.cs b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/MinotaurCaptain.cs index 5974e0222..701dd75a7 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/MinotaurCaptain.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/MinotaurCaptain.cs @@ -2,80 +2,80 @@ using Server.Items; namespace Server.Mobiles { - public class MinotaurCaptain : BaseCreature - { - [Constructible] - public MinotaurCaptain() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) // NEED TO CHECK + public class MinotaurCaptain : BaseCreature { - Body = 280; + [Constructible] + public MinotaurCaptain() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) // NEED TO CHECK + { + Body = 280; - SetStr(401, 425); - SetDex(91, 110); - SetInt(31, 50); + SetStr(401, 425); + SetDex(91, 110); + SetInt(31, 50); - SetHits(401, 440); + SetHits(401, 440); - SetDamage(11, 20); + SetDamage(11, 20); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 65, 75); - SetResistance(ResistanceType.Fire, 35, 45); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 65, 75); + SetResistance(ResistanceType.Fire, 35, 45); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.Meditation, 0); - SetSkill(SkillName.EvalInt, 0); - SetSkill(SkillName.Magery, 0); - SetSkill(SkillName.Poisoning, 0); - SetSkill(SkillName.Anatomy, 0, 6.3); - SetSkill(SkillName.MagicResist, 66.1, 73.6); - SetSkill(SkillName.Tactics, 93.0, 109.9); - SetSkill(SkillName.Wrestling, 92.6, 107.2); + SetSkill(SkillName.Meditation, 0); + SetSkill(SkillName.EvalInt, 0); + SetSkill(SkillName.Magery, 0); + SetSkill(SkillName.Poisoning, 0); + SetSkill(SkillName.Anatomy, 0, 6.3); + SetSkill(SkillName.MagicResist, 66.1, 73.6); + SetSkill(SkillName.Tactics, 93.0, 109.9); + SetSkill(SkillName.Wrestling, 92.6, 107.2); - Fame = 7000; - Karma = -7000; + Fame = 7000; + Karma = -7000; - VirtualArmor = 28; // Don't know what it should be + VirtualArmor = 28; // Don't know what it should be + } + + public MinotaurCaptain(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a minotaur corpse"; + + public override string DefaultName => "a minotaur captain"; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.ParalyzingBlow; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); // Need to verify + } + + // Using Tormented Minotaur sounds - Need to veryfy + public override int GetAngerSound() => 0x597; + + public override int GetIdleSound() => 0x596; + + public override int GetAttackSound() => 0x599; + + public override int GetHurtSound() => 0x59a; + + public override int GetDeathSound() => 0x59c; + + 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(); + } } - - public MinotaurCaptain(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a minotaur corpse"; - - public override string DefaultName => "a minotaur captain"; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.ParalyzingBlow; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); // Need to verify - } - - // Using Tormented Minotaur sounds - Need to veryfy - public override int GetAngerSound() => 0x597; - - public override int GetIdleSound() => 0x596; - - public override int GetAttackSound() => 0x599; - - public override int GetHurtSound() => 0x59a; - - public override int GetDeathSound() => 0x59c; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/MinotaurScout.cs b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/MinotaurScout.cs index 1532cc0dd..ca8842240 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/MinotaurScout.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/MinotaurScout.cs @@ -2,80 +2,80 @@ using Server.Items; namespace Server.Mobiles { - public class MinotaurScout : BaseCreature - { - [Constructible] - public MinotaurScout() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) // NEED TO CHECK + public class MinotaurScout : BaseCreature { - Body = 281; + [Constructible] + public MinotaurScout() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) // NEED TO CHECK + { + Body = 281; - SetStr(353, 375); - SetDex(111, 130); - SetInt(34, 50); + SetStr(353, 375); + SetDex(111, 130); + SetInt(34, 50); - SetHits(354, 383); + SetHits(354, 383); - SetDamage(11, 20); + SetDamage(11, 20); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 55, 65); - SetResistance(ResistanceType.Fire, 25, 35); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 55, 65); + SetResistance(ResistanceType.Fire, 25, 35); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 30, 40); - // SetSkill( SkillName.Meditation, Unknown ); - // SetSkill( SkillName.EvalInt, Unknown ); - // SetSkill( SkillName.Magery, Unknown ); - // SetSkill( SkillName.Poisoning, Unknown ); - SetSkill(SkillName.Anatomy, 0); - SetSkill(SkillName.MagicResist, 60.6, 67.5); - SetSkill(SkillName.Tactics, 86.9, 103.6); - SetSkill(SkillName.Wrestling, 85.6, 104.5); + // SetSkill( SkillName.Meditation, Unknown ); + // SetSkill( SkillName.EvalInt, Unknown ); + // SetSkill( SkillName.Magery, Unknown ); + // SetSkill( SkillName.Poisoning, Unknown ); + SetSkill(SkillName.Anatomy, 0); + SetSkill(SkillName.MagicResist, 60.6, 67.5); + SetSkill(SkillName.Tactics, 86.9, 103.6); + SetSkill(SkillName.Wrestling, 85.6, 104.5); - Fame = 5000; - Karma = -5000; + Fame = 5000; + Karma = -5000; - VirtualArmor = 28; // Don't know what it should be + VirtualArmor = 28; // Don't know what it should be + } + + public MinotaurScout(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a minotaur corpse"; + + public override string DefaultName => "a minotaur scout"; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.ParalyzingBlow; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); // Need to verify + } + + // Using Tormented Minotaur sounds - Need to veryfy + public override int GetAngerSound() => 0x597; + + public override int GetIdleSound() => 0x596; + + public override int GetAttackSound() => 0x599; + + public override int GetHurtSound() => 0x59a; + + public override int GetDeathSound() => 0x59c; + + 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(); + } } - - public MinotaurScout(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a minotaur corpse"; - - public override string DefaultName => "a minotaur scout"; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.ParalyzingBlow; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); // Need to verify - } - - // Using Tormented Minotaur sounds - Need to veryfy - public override int GetAngerSound() => 0x597; - - public override int GetIdleSound() => 0x596; - - public override int GetAttackSound() => 0x599; - - public override int GetHurtSound() => 0x59a; - - public override int GetDeathSound() => 0x59c; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/PestilentBandage.cs b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/PestilentBandage.cs index 08c0093c5..b1d3aa862 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/PestilentBandage.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/PestilentBandage.cs @@ -2,79 +2,79 @@ using Server.Items; namespace Server.Mobiles { - public class PestilentBandage : BaseCreature - { - [Constructible] - public PestilentBandage() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) // NEED TO CHECK + public class PestilentBandage : BaseCreature { - Body = 154; - Hue = 0x515; - BaseSoundID = 471; + [Constructible] + public PestilentBandage() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) // NEED TO CHECK + { + Body = 154; + Hue = 0x515; + BaseSoundID = 471; - SetStr(691, 740); - SetDex(141, 180); - SetInt(51, 80); + SetStr(691, 740); + SetDex(141, 180); + SetInt(51, 80); - SetHits(415, 445); + SetHits(415, 445); - SetDamage(13, 23); + SetDamage(13, 23); - SetDamageType(ResistanceType.Physical, 40); - SetDamageType(ResistanceType.Cold, 20); - SetDamageType(ResistanceType.Poison, 40); + SetDamageType(ResistanceType.Physical, 40); + SetDamageType(ResistanceType.Cold, 20); + SetDamageType(ResistanceType.Poison, 40); - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 10, 20); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 20, 30); + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 10, 20); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 20, 30); - SetSkill(SkillName.Poisoning, 0.0, 10.0); - SetSkill(SkillName.Anatomy, 0); - SetSkill(SkillName.MagicResist, 75.0, 80.0); - SetSkill(SkillName.Tactics, 80.0, 85.0); - SetSkill(SkillName.Wrestling, 70.0, 75.0); + SetSkill(SkillName.Poisoning, 0.0, 10.0); + SetSkill(SkillName.Anatomy, 0); + SetSkill(SkillName.MagicResist, 75.0, 80.0); + SetSkill(SkillName.Tactics, 80.0, 85.0); + SetSkill(SkillName.Wrestling, 70.0, 75.0); - Fame = 20000; - Karma = -20000; + Fame = 20000; + Karma = -20000; - // VirtualArmor = 28; // Don't know what it should be + // VirtualArmor = 28; // Don't know what it should be - PackItem(new Bandage(5)); // How many? + PackItem(new Bandage(5)); // How many? + } + + public PestilentBandage(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a pestilent bandage corpse"; + // Neither Stratics nor UOGuide have much description + // beyond being a "Grey Mummy". BodyValue, Sound and + // Hue are all guessed until they can be verified. + // Loot and Fame/Karma are also guesses at this point. + // + // They also apparently have a Poison Attack, which I've stolen from Yamandons. + + public override string DefaultName => "a pestilent bandage"; + + public override Poison HitPoison => Poison.Lethal; + public override bool CanHeal => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); // Need to verify + } + + 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(); + } } - - public PestilentBandage(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a pestilent bandage corpse"; - // Neither Stratics nor UOGuide have much description - // beyond being a "Grey Mummy". BodyValue, Sound and - // Hue are all guessed until they can be verified. - // Loot and Fame/Karma are also guesses at this point. - // - // They also apparently have a Poison Attack, which I've stolen from Yamandons. - - public override string DefaultName => "a pestilent bandage"; - - public override Poison HitPoison => Poison.Lethal; - public override bool CanHeal => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); // Need to verify - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/Tormented Minotaur.cs b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/Tormented Minotaur.cs index 775b3d26a..25cbf5d27 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/Tormented Minotaur.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/Tormented Minotaur.cs @@ -2,77 +2,77 @@ using Server.Items; namespace Server.Mobiles { - public class TormentedMinotaur : BaseCreature - { - [Constructible] - public TormentedMinotaur() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class TormentedMinotaur : BaseCreature { - Body = 262; + [Constructible] + public TormentedMinotaur() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 262; - SetStr(822, 930); - SetDex(401, 415); - SetInt(128, 138); + SetStr(822, 930); + SetDex(401, 415); + SetInt(128, 138); - SetHits(4000, 4200); + SetHits(4000, 4200); - SetDamage(16, 30); + SetDamage(16, 30); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 62); - SetResistance(ResistanceType.Fire, 74); - SetResistance(ResistanceType.Cold, 54); - SetResistance(ResistanceType.Poison, 56); - SetResistance(ResistanceType.Energy, 54); + SetResistance(ResistanceType.Physical, 62); + SetResistance(ResistanceType.Fire, 74); + SetResistance(ResistanceType.Cold, 54); + SetResistance(ResistanceType.Poison, 56); + SetResistance(ResistanceType.Energy, 54); - SetSkill(SkillName.Wrestling, 110.1, 111.0); - SetSkill(SkillName.Tactics, 100.7, 102.8); - SetSkill(SkillName.MagicResist, 104.3, 116.3); + SetSkill(SkillName.Wrestling, 110.1, 111.0); + SetSkill(SkillName.Tactics, 100.7, 102.8); + SetSkill(SkillName.MagicResist, 104.3, 116.3); - Fame = 20000; - Karma = -20000; + Fame = 20000; + Karma = -20000; + } + + public TormentedMinotaur(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a tormented minotaur corpse"; + + public override string DefaultName => "Tormented Minotaur"; + + public override Poison PoisonImmune => Poison.Deadly; + public override int TreasureMapLevel => 3; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.Dismount; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 10); + } + + public override int GetDeathSound() => 0x596; + + public override int GetAttackSound() => 0x597; + + public override int GetIdleSound() => 0x598; + + public override int GetAngerSound() => 0x599; + + public override int GetHurtSound() => 0x59A; + + 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 TormentedMinotaur(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a tormented minotaur corpse"; - - public override string DefaultName => "Tormented Minotaur"; - - public override Poison PoisonImmune => Poison.Deadly; - public override int TreasureMapLevel => 3; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.Dismount; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 10); - } - - public override int GetDeathSound() => 0x596; - - public override int GetAttackSound() => 0x597; - - public override int GetIdleSound() => 0x598; - - public override int GetAngerSound() => 0x599; - - public override int GetHurtSound() => 0x59A; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/Troglodyte.cs b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/Troglodyte.cs index 8608021eb..51b659db9 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/Troglodyte.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Humanoid/Melee/Troglodyte.cs @@ -2,77 +2,77 @@ using Server.Items; namespace Server.Mobiles { - public class Troglodyte : BaseCreature - { - [Constructible] - public Troglodyte() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) // NEED TO CHECK + public class Troglodyte : BaseCreature { - Body = 267; - BaseSoundID = 0x59F; + [Constructible] + public Troglodyte() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) // NEED TO CHECK + { + Body = 267; + BaseSoundID = 0x59F; - SetStr(148, 217); - SetDex(91, 120); - SetInt(51, 70); + SetStr(148, 217); + SetDex(91, 120); + SetInt(51, 70); - SetHits(302, 340); + SetHits(302, 340); - SetDamage(11, 14); + SetDamage(11, 14); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 30, 35); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 35, 40); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 30, 35); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 35, 40); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.Anatomy, 70.5, 94.8); - SetSkill(SkillName.MagicResist, 51.8, 65.0); - SetSkill(SkillName.Tactics, 80.4, 94.7); - SetSkill(SkillName.Wrestling, 70.2, 93.5); - SetSkill(SkillName.Healing, 70.0, 95.0); + SetSkill(SkillName.Anatomy, 70.5, 94.8); + SetSkill(SkillName.MagicResist, 51.8, 65.0); + SetSkill(SkillName.Tactics, 80.4, 94.7); + SetSkill(SkillName.Wrestling, 70.2, 93.5); + SetSkill(SkillName.Healing, 70.0, 95.0); - Fame = 5000; - Karma = -5000; + Fame = 5000; + Karma = -5000; - VirtualArmor = 28; // Don't know what it should be + VirtualArmor = 28; // Don't know what it should be - PackItem(new Bandage(5)); // How many? - PackItem(new Ribs()); + PackItem(new Bandage(5)); // How many? + PackItem(new Ribs()); + } + + public Troglodyte(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a troglodyte corpse"; + public override string DefaultName => "a troglodyte"; + + public override bool CanHeal => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); // Need to verify + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + if (Utility.RandomDouble() < 0.1) + c.DropItem(new PrimitiveFetish()); + } + + 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(); + } } - - public Troglodyte(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a troglodyte corpse"; - public override string DefaultName => "a troglodyte"; - - public override bool CanHeal => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); // Need to verify - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - if (Utility.RandomDouble() < 0.1) - c.DropItem(new PrimitiveFetish()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Labyrinth/Miasma.cs b/Projects/UOContent/Mobiles/Monsters/ML/Labyrinth/Miasma.cs index 0091360fc..ab70964d3 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Labyrinth/Miasma.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Labyrinth/Miasma.cs @@ -2,109 +2,109 @@ using Server.Items; namespace Server.Mobiles { - public class Miasma : Scorpion - { - [Constructible] - public Miasma() + public class Miasma : Scorpion { - IsParagon = true; - - Hue = 0x8FD; - - SetStr(255, 847); - SetDex(145, 428); - SetInt(26, 380); - - SetHits(750, 2000); - SetMana(5, 60); - - SetDamage(20, 30); - - SetDamageType(ResistanceType.Physical, 60); - SetDamageType(ResistanceType.Poison, 40); - - SetResistance(ResistanceType.Physical, 50, 54); - SetResistance(ResistanceType.Fire, 40, 45); - SetResistance(ResistanceType.Cold, 50, 55); - SetResistance(ResistanceType.Poison, 70, 80); - SetResistance(ResistanceType.Energy, 40, 45); - - SetSkill(SkillName.Wrestling, 84.9, 103.3); - SetSkill(SkillName.Tactics, 98.4, 110.6); - SetSkill(SkillName.Anatomy, 0); - SetSkill(SkillName.MagicResist, 74.4, 77.7); - SetSkill(SkillName.Poisoning, 128.5, 143.6); - - Fame = 21000; - Karma = -21000; - } - - /* - // TODO: uncomment once added - public override void OnDeath( Container c ) - { - base.OnDeath( c ); - - if (Utility.RandomDouble() < 0.025) - { - switch ( Utility.Random( 16 ) ) + [Constructible] + public Miasma() { - case 0: c.DropItem( new MyrmidonGloves() ); break; - case 1: c.DropItem( new MyrmidonGorget() ); break; - case 2: c.DropItem( new MyrmidonLegs() ); break; - case 3: c.DropItem( new MyrmidonArms() ); break; - case 4: c.DropItem( new PaladinArms() ); break; - case 5: c.DropItem( new PaladinGorget() ); break; - case 6: c.DropItem( new LeafweaveLegs() ); break; - case 7: c.DropItem( new DeathChest() ); break; - case 8: c.DropItem( new DeathGloves() ); break; - case 9: c.DropItem( new DeathLegs() ); break; - case 10: c.DropItem( new GreymistGloves() ); break; - case 11: c.DropItem( new GreymistArms() ); break; - case 12: c.DropItem( new AssassinChest() ); break; - case 13: c.DropItem( new AssassinArms() ); break; - case 14: c.DropItem( new HunterGloves() ); break; - case 15: c.DropItem( new HunterLegs() ); break; + IsParagon = true; + + Hue = 0x8FD; + + SetStr(255, 847); + SetDex(145, 428); + SetInt(26, 380); + + SetHits(750, 2000); + SetMana(5, 60); + + SetDamage(20, 30); + + SetDamageType(ResistanceType.Physical, 60); + SetDamageType(ResistanceType.Poison, 40); + + SetResistance(ResistanceType.Physical, 50, 54); + SetResistance(ResistanceType.Fire, 40, 45); + SetResistance(ResistanceType.Cold, 50, 55); + SetResistance(ResistanceType.Poison, 70, 80); + SetResistance(ResistanceType.Energy, 40, 45); + + SetSkill(SkillName.Wrestling, 84.9, 103.3); + SetSkill(SkillName.Tactics, 98.4, 110.6); + SetSkill(SkillName.Anatomy, 0); + SetSkill(SkillName.MagicResist, 74.4, 77.7); + SetSkill(SkillName.Poisoning, 128.5, 143.6); + + Fame = 21000; + Karma = -21000; + } + + /* + // TODO: uncomment once added + public override void OnDeath( Container c ) + { + base.OnDeath( c ); + + if (Utility.RandomDouble() < 0.025) + { + switch ( Utility.Random( 16 ) ) + { + case 0: c.DropItem( new MyrmidonGloves() ); break; + case 1: c.DropItem( new MyrmidonGorget() ); break; + case 2: c.DropItem( new MyrmidonLegs() ); break; + case 3: c.DropItem( new MyrmidonArms() ); break; + case 4: c.DropItem( new PaladinArms() ); break; + case 5: c.DropItem( new PaladinGorget() ); break; + case 6: c.DropItem( new LeafweaveLegs() ); break; + case 7: c.DropItem( new DeathChest() ); break; + case 8: c.DropItem( new DeathGloves() ); break; + case 9: c.DropItem( new DeathLegs() ); break; + case 10: c.DropItem( new GreymistGloves() ); break; + case 11: c.DropItem( new GreymistArms() ); break; + case 12: c.DropItem( new AssassinChest() ); break; + case 13: c.DropItem( new AssassinArms() ); break; + case 14: c.DropItem( new HunterGloves() ); break; + case 15: c.DropItem( new HunterLegs() ); break; + } + } + } + */ + + public Miasma(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Miasma corpse"; + public override string DefaultName => "Miasma"; + + /* yes, this is OSI style */ + public override double WeaponAbilityChance => 0.75; + public override double HitPoisonChance => 0.35; + public override Poison HitPoison => Poison.Lethal; + public override bool HasManaOveride => true; + public override bool GivesMLMinorArtifact => true; + public override int TreasureMapLevel => 5; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 4); + } + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.MortalStrike; + + 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 Miasma(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Miasma corpse"; - public override string DefaultName => "Miasma"; - - /* yes, this is OSI style */ - public override double WeaponAbilityChance => 0.75; - public override double HitPoisonChance => 0.35; - public override Poison HitPoison => Poison.Lethal; - public override bool HasManaOveride => true; - public override bool GivesMLMinorArtifact => true; - public override int TreasureMapLevel => 5; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 4); - } - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.MortalStrike; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Labyrinth/Pyre.cs b/Projects/UOContent/Mobiles/Monsters/ML/Labyrinth/Pyre.cs index 3c1303b5b..7f7634a5b 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Labyrinth/Pyre.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Labyrinth/Pyre.cs @@ -2,81 +2,81 @@ using Server.Items; namespace Server.Mobiles { - public class Pyre : Phoenix - { - [Constructible] - public Pyre() + public class Pyre : Phoenix { - IsParagon = true; + [Constructible] + public Pyre() + { + IsParagon = true; - Hue = 0x489; + Hue = 0x489; - FightMode = FightMode.Closest; + FightMode = FightMode.Closest; - SetStr(605, 611); - SetDex(391, 519); - SetInt(669, 818); + SetStr(605, 611); + SetDex(391, 519); + SetInt(669, 818); - SetHits(1783, 1939); + SetHits(1783, 1939); - SetDamage(30); + SetDamage(30); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Fire, 50); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Fire, 50); - SetResistance(ResistanceType.Physical, 65); - SetResistance(ResistanceType.Fire, 72, 75); - SetResistance(ResistanceType.Poison, 36, 41); - SetResistance(ResistanceType.Energy, 50, 51); + SetResistance(ResistanceType.Physical, 65); + SetResistance(ResistanceType.Fire, 72, 75); + SetResistance(ResistanceType.Poison, 36, 41); + SetResistance(ResistanceType.Energy, 50, 51); - SetSkill(SkillName.Wrestling, 121.9, 130.6); - SetSkill(SkillName.Tactics, 114.4, 117.4); - SetSkill(SkillName.MagicResist, 147.7, 153.0); - SetSkill(SkillName.Poisoning, 122.8, 124.0); - SetSkill(SkillName.Magery, 121.8, 127.8); - SetSkill(SkillName.EvalInt, 103.6, 117.0); - SetSkill(SkillName.Meditation, 100.0, 110.0); + SetSkill(SkillName.Wrestling, 121.9, 130.6); + SetSkill(SkillName.Tactics, 114.4, 117.4); + SetSkill(SkillName.MagicResist, 147.7, 153.0); + SetSkill(SkillName.Poisoning, 122.8, 124.0); + SetSkill(SkillName.Magery, 121.8, 127.8); + SetSkill(SkillName.EvalInt, 103.6, 117.0); + SetSkill(SkillName.Meditation, 100.0, 110.0); - Fame = 21000; - Karma = -21000; + Fame = 21000; + Karma = -21000; + } + + public Pyre(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Pyre corpse"; + public override string DefaultName => "Pyre"; + + public override bool GivesMLMinorArtifact => true; + public override int TreasureMapLevel => 5; + public override bool HasAura => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 3); + } + + public override WeaponAbility GetWeaponAbility() + { + if (Utility.RandomBool()) + return WeaponAbility.ParalyzingBlow; + return WeaponAbility.BleedAttack; + } + + 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 Pyre(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Pyre corpse"; - public override string DefaultName => "Pyre"; - - public override bool GivesMLMinorArtifact => true; - public override int TreasureMapLevel => 5; - public override bool HasAura => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 3); - } - - public override WeaponAbility GetWeaponAbility() - { - if (Utility.RandomBool()) - return WeaponAbility.ParalyzingBlow; - return WeaponAbility.BleedAttack; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Labyrinth/Rend.cs b/Projects/UOContent/Mobiles/Monsters/ML/Labyrinth/Rend.cs index 2dc8228d7..045d6eef6 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Labyrinth/Rend.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Labyrinth/Rend.cs @@ -2,76 +2,76 @@ using Server.Items; namespace Server.Mobiles { - public class Rend : Reptalon - { - [Constructible] - public Rend() + public class Rend : Reptalon { - IsParagon = true; + [Constructible] + public Rend() + { + IsParagon = true; - Hue = 0x455; + Hue = 0x455; - SetStr(1261, 1284); - SetDex(363, 384); - SetInt(601, 642); + SetStr(1261, 1284); + SetDex(363, 384); + SetInt(601, 642); - SetHits(5176, 6100); + SetHits(5176, 6100); - SetDamage(26, 33); + SetDamage(26, 33); - SetDamageType(ResistanceType.Physical, 100); - SetDamageType(ResistanceType.Poison, 0); - SetDamageType(ResistanceType.Energy, 0); + SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Poison, 0); + SetDamageType(ResistanceType.Energy, 0); - SetResistance(ResistanceType.Physical, 75, 85); - SetResistance(ResistanceType.Fire, 81, 94); - SetResistance(ResistanceType.Cold, 46, 55); - SetResistance(ResistanceType.Poison, 35, 44); - SetResistance(ResistanceType.Energy, 45, 52); + SetResistance(ResistanceType.Physical, 75, 85); + SetResistance(ResistanceType.Fire, 81, 94); + SetResistance(ResistanceType.Cold, 46, 55); + SetResistance(ResistanceType.Poison, 35, 44); + SetResistance(ResistanceType.Energy, 45, 52); - SetSkill(SkillName.Wrestling, 136.3, 150.3); - SetSkill(SkillName.Tactics, 133.4, 141.4); - SetSkill(SkillName.MagicResist, 90.9, 110.0); - SetSkill(SkillName.Anatomy, 66.6, 72.0); + SetSkill(SkillName.Wrestling, 136.3, 150.3); + SetSkill(SkillName.Tactics, 133.4, 141.4); + SetSkill(SkillName.MagicResist, 90.9, 110.0); + SetSkill(SkillName.Anatomy, 66.6, 72.0); - Fame = 21000; - Karma = -21000; + Fame = 21000; + Karma = -21000; + } + + public Rend(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Rend corpse"; + public override string DefaultName => "Rend"; + + public override bool GivesMLMinorArtifact => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 3); + } + + public override WeaponAbility GetWeaponAbility() + { + if (Utility.RandomBool()) + return WeaponAbility.ParalyzingBlow; + return WeaponAbility.BleedAttack; + } + + 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 Rend(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Rend corpse"; - public override string DefaultName => "Rend"; - - public override bool GivesMLMinorArtifact => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 3); - } - - public override WeaponAbility GetWeaponAbility() - { - if (Utility.RandomBool()) - return WeaponAbility.ParalyzingBlow; - return WeaponAbility.BleedAttack; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Misc/Magic/GreaterDragon.cs b/Projects/UOContent/Mobiles/Monsters/ML/Misc/Magic/GreaterDragon.cs index f940c7ff6..d62c27d4f 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Misc/Magic/GreaterDragon.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Misc/Magic/GreaterDragon.cs @@ -3,100 +3,100 @@ using Server.SkillHandlers; namespace Server.Mobiles { - public class GreaterDragon : BaseCreature - { - [Constructible] - public GreaterDragon() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.3, 0.5) + public class GreaterDragon : BaseCreature { - Body = Utility.RandomList(12, 59); - BaseSoundID = 362; + [Constructible] + public GreaterDragon() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.3, 0.5) + { + Body = Utility.RandomList(12, 59); + BaseSoundID = 362; - SetStr(1025, 1425); - SetDex(81, 148); - SetInt(475, 675); + SetStr(1025, 1425); + SetDex(81, 148); + SetInt(475, 675); - SetHits(1000, 2000); - SetStam(120, 135); + SetHits(1000, 2000); + SetStam(120, 135); - SetDamage(24, 33); + SetDamage(24, 33); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 60, 85); - SetResistance(ResistanceType.Fire, 65, 90); - SetResistance(ResistanceType.Cold, 40, 55); - SetResistance(ResistanceType.Poison, 40, 60); - SetResistance(ResistanceType.Energy, 50, 75); + SetResistance(ResistanceType.Physical, 60, 85); + SetResistance(ResistanceType.Fire, 65, 90); + SetResistance(ResistanceType.Cold, 40, 55); + SetResistance(ResistanceType.Poison, 40, 60); + SetResistance(ResistanceType.Energy, 50, 75); - SetSkill(SkillName.Meditation, 0); - SetSkill(SkillName.EvalInt, 110.0, 140.0); - SetSkill(SkillName.Magery, 110.0, 140.0); - SetSkill(SkillName.Poisoning, 0); - SetSkill(SkillName.Anatomy, 0); - SetSkill(SkillName.MagicResist, 110.0, 140.0); - SetSkill(SkillName.Tactics, 110.0, 140.0); - SetSkill(SkillName.Wrestling, 115.0, 145.0); + SetSkill(SkillName.Meditation, 0); + SetSkill(SkillName.EvalInt, 110.0, 140.0); + SetSkill(SkillName.Magery, 110.0, 140.0); + SetSkill(SkillName.Poisoning, 0); + SetSkill(SkillName.Anatomy, 0); + SetSkill(SkillName.MagicResist, 110.0, 140.0); + SetSkill(SkillName.Tactics, 110.0, 140.0); + SetSkill(SkillName.Wrestling, 115.0, 145.0); - Fame = 22000; - Karma = -15000; + Fame = 22000; + Karma = -15000; - VirtualArmor = 60; + VirtualArmor = 60; - Tamable = true; - ControlSlots = 5; - MinTameSkill = 104.7; + Tamable = true; + ControlSlots = 5; + MinTameSkill = 104.7; + } + + public GreaterDragon(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a dragon corpse"; + public override bool StatLossAfterTame => true; + public override string DefaultName => "a greater dragon"; + + public override bool ReacquireOnMovement => !Controlled; + public override bool HasBreath => true; // fire breath enabled + public override bool AutoDispel => !Controlled; + public override int TreasureMapLevel => 5; + public override int Meat => 19; + public override int Hides => 30; + public override HideType HideType => HideType.Barbed; + public override int Scales => 7; + public override ScaleType ScaleType => Body == 12 ? ScaleType.Yellow : ScaleType.Red; + public override FoodType FavoriteFood => FoodType.Meat; + public override bool CanAngerOnTame => true; + public override bool CanFly => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 4); + AddLoot(LootPack.Gems, 8); + } + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.BleedAttack; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + SetDamage(24, 33); + + if (version == 0) + { + AnimalTaming.ScaleStats(this, 0.50); + AnimalTaming.ScaleSkills(this, 0.80, 0.90); // 90% * 80% = 72% of original skills trainable to 90% + Skills.Magery.Base = + Skills.Magery + .Cap; // Greater dragons have a 90% cap reduction and 90% skill reduction on magery + } + } } - - public GreaterDragon(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a dragon corpse"; - public override bool StatLossAfterTame => true; - public override string DefaultName => "a greater dragon"; - - public override bool ReacquireOnMovement => !Controlled; - public override bool HasBreath => true; // fire breath enabled - public override bool AutoDispel => !Controlled; - public override int TreasureMapLevel => 5; - public override int Meat => 19; - public override int Hides => 30; - public override HideType HideType => HideType.Barbed; - public override int Scales => 7; - public override ScaleType ScaleType => Body == 12 ? ScaleType.Yellow : ScaleType.Red; - public override FoodType FavoriteFood => FoodType.Meat; - public override bool CanAngerOnTame => true; - public override bool CanFly => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 4); - AddLoot(LootPack.Gems, 8); - } - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.BleedAttack; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - SetDamage(24, 33); - - if (version == 0) - { - AnimalTaming.ScaleStats(this, 0.50); - AnimalTaming.ScaleSkills(this, 0.80, 0.90); // 90% * 80% = 72% of original skills trainable to 90% - Skills.Magery.Base = - Skills.Magery - .Cap; // Greater dragons have a 90% cap reduction and 90% skill reduction on magery - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Misc/Melee/CorrosiveSlime.cs b/Projects/UOContent/Mobiles/Monsters/ML/Misc/Melee/CorrosiveSlime.cs index 9e43e4651..b54b44d78 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Misc/Melee/CorrosiveSlime.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Misc/Melee/CorrosiveSlime.cs @@ -1,73 +1,73 @@ namespace Server.Mobiles { - public class CorrosiveSlime : BaseCreature - { - [Constructible] - public CorrosiveSlime() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class CorrosiveSlime : BaseCreature { - Body = 51; - BaseSoundID = 456; + [Constructible] + public CorrosiveSlime() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 51; + BaseSoundID = 456; - Hue = Utility.RandomSlimeHue(); + Hue = Utility.RandomSlimeHue(); - SetStr(22, 34); - SetDex(16, 21); - SetInt(16, 20); + SetStr(22, 34); + SetDex(16, 21); + SetInt(16, 20); - SetHits(15, 19); + SetHits(15, 19); - SetDamage(1, 5); + SetDamage(1, 5); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 5, 10); - SetResistance(ResistanceType.Poison, 15, 20); + SetResistance(ResistanceType.Physical, 5, 10); + SetResistance(ResistanceType.Poison, 15, 20); - SetSkill(SkillName.Poisoning, 36.0, 49.1); - SetSkill(SkillName.Anatomy, 0); - SetSkill(SkillName.MagicResist, 15.9, 18.9); - SetSkill(SkillName.Tactics, 24.6, 26.1); - SetSkill(SkillName.Wrestling, 24.9, 26.1); + SetSkill(SkillName.Poisoning, 36.0, 49.1); + SetSkill(SkillName.Anatomy, 0); + SetSkill(SkillName.MagicResist, 15.9, 18.9); + SetSkill(SkillName.Tactics, 24.6, 26.1); + SetSkill(SkillName.Wrestling, 24.9, 26.1); - Fame = 300; - Karma = -300; + Fame = 300; + Karma = -300; - VirtualArmor = 8; + VirtualArmor = 8; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 23.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 23.1; + } + + // TODO: Damage weapon via acid + + public CorrosiveSlime(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a slimey corpse"; + public override string DefaultName => "a corrosive slime"; + + public override Poison PoisonImmune => Poison.Regular; + public override Poison HitPoison => Poison.Regular; + public override FoodType FavoriteFood => FoodType.Fish; + + public override void GenerateLoot() + { + AddLoot(LootPack.Poor); + AddLoot(LootPack.Gems); + } + + 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(); + } } - - // TODO: Damage weapon via acid - - public CorrosiveSlime(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a slimey corpse"; - public override string DefaultName => "a corrosive slime"; - - public override Poison PoisonImmune => Poison.Regular; - public override Poison HitPoison => Poison.Regular; - public override FoodType FavoriteFood => FoodType.Fish; - - public override void GenerateLoot() - { - AddLoot(LootPack.Poor); - AddLoot(LootPack.Gems); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Misc/Melee/Reptalon.cs b/Projects/UOContent/Mobiles/Monsters/ML/Misc/Melee/Reptalon.cs index 22a55aa22..20c23967d 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Misc/Melee/Reptalon.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Misc/Melee/Reptalon.cs @@ -2,75 +2,75 @@ using Server.Items; namespace Server.Mobiles { - public class Reptalon : BaseMount - { - [Constructible] - public Reptalon() : base("a reptalon", 0x114, 0x3E90, AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.35) + public class Reptalon : BaseMount { - BaseSoundID = 0x16A; + [Constructible] + public Reptalon() : base("a reptalon", 0x114, 0x3E90, AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.35) + { + BaseSoundID = 0x16A; - SetStr(1001, 1025); - SetDex(152, 164); - SetInt(251, 289); + SetStr(1001, 1025); + SetDex(152, 164); + SetInt(251, 289); - SetHits(833, 931); + SetHits(833, 931); - SetDamage(21, 28); + SetDamage(21, 28); - SetDamageType(ResistanceType.Physical, 0); - SetDamageType(ResistanceType.Poison, 25); - SetDamageType(ResistanceType.Energy, 75); + SetDamageType(ResistanceType.Physical, 0); + SetDamageType(ResistanceType.Poison, 25); + SetDamageType(ResistanceType.Energy, 75); - SetResistance(ResistanceType.Physical, 53, 64); - SetResistance(ResistanceType.Fire, 35, 45); - SetResistance(ResistanceType.Cold, 36, 45); - SetResistance(ResistanceType.Poison, 52, 63); - SetResistance(ResistanceType.Energy, 71, 83); + SetResistance(ResistanceType.Physical, 53, 64); + SetResistance(ResistanceType.Fire, 35, 45); + SetResistance(ResistanceType.Cold, 36, 45); + SetResistance(ResistanceType.Poison, 52, 63); + SetResistance(ResistanceType.Energy, 71, 83); - SetSkill(SkillName.Wrestling, 101.5, 118.2); - SetSkill(SkillName.Tactics, 101.7, 108.2); - SetSkill(SkillName.MagicResist, 76.4, 89.9); - SetSkill(SkillName.Anatomy, 56.4, 59.7); + SetSkill(SkillName.Wrestling, 101.5, 118.2); + SetSkill(SkillName.Tactics, 101.7, 108.2); + SetSkill(SkillName.MagicResist, 76.4, 89.9); + SetSkill(SkillName.Anatomy, 56.4, 59.7); - Tamable = true; - ControlSlots = 4; - MinTameSkill = 101.1; + Tamable = true; + ControlSlots = 4; + MinTameSkill = 101.1; + } + + public Reptalon(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a reptalon corpse"; + + public override int TreasureMapLevel => 5; + public override int Meat => 5; + public override int Hides => 10; + public override bool CanBreath => true; + public override bool CanAngerOnTame => true; + public override bool StatLossAfterTame => true; + public override FoodType FavoriteFood => FoodType.Meat; + public override bool CanFly => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.AosUltraRich, 3); + } + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.ParalyzingBlow; + + 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 Reptalon(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a reptalon corpse"; - - public override int TreasureMapLevel => 5; - public override int Meat => 5; - public override int Hides => 10; - public override bool CanBreath => true; - public override bool CanAngerOnTame => true; - public override bool StatLossAfterTame => true; - public override FoodType FavoriteFood => FoodType.Meat; - public override bool CanFly => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.AosUltraRich, 3); - } - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.ParalyzingBlow; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Painted Caves/Grobu.cs b/Projects/UOContent/Mobiles/Monsters/ML/Painted Caves/Grobu.cs index e4e4a16ea..fd89388cf 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Painted Caves/Grobu.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Painted Caves/Grobu.cs @@ -2,78 +2,78 @@ using Server.Items; namespace Server.Mobiles { - public class Grobu : BlackBear - { - [Constructible] - public Grobu() + public class Grobu : BlackBear { - IsParagon = true; + [Constructible] + public Grobu() + { + IsParagon = true; - Hue = 0x455; + Hue = 0x455; - AI = AIType.AI_Melee; - FightMode = FightMode.Closest; + AI = AIType.AI_Melee; + FightMode = FightMode.Closest; - SetStr(192, 210); - SetDex(132, 150); - SetInt(50, 52); + SetStr(192, 210); + SetDex(132, 150); + SetInt(50, 52); - SetHits(1235, 1299); - SetStam(132, 150); - SetMana(9); + SetHits(1235, 1299); + SetStam(132, 150); + SetMana(9); - SetDamage(15, 18); + SetDamage(15, 18); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 40, 45); - SetResistance(ResistanceType.Fire, 20, 40); - SetResistance(ResistanceType.Cold, 32, 35); - SetResistance(ResistanceType.Poison, 25, 30); - SetResistance(ResistanceType.Energy, 22, 34); + SetResistance(ResistanceType.Physical, 40, 45); + SetResistance(ResistanceType.Fire, 20, 40); + SetResistance(ResistanceType.Cold, 32, 35); + SetResistance(ResistanceType.Poison, 25, 30); + SetResistance(ResistanceType.Energy, 22, 34); - SetSkill(SkillName.Wrestling, 96.4, 119.0); - SetSkill(SkillName.Tactics, 96.2, 116.5); - SetSkill(SkillName.MagicResist, 66.2, 83.7); + SetSkill(SkillName.Wrestling, 96.4, 119.0); + SetSkill(SkillName.Tactics, 96.2, 116.5); + SetSkill(SkillName.MagicResist, 66.2, 83.7); - Fame = 1000; - Karma = 1000; + Fame = 1000; + Karma = 1000; + } + + public Grobu(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Grobu corpse"; + public override string DefaultName => "Grobu"; + + public override bool GivesMLMinorArtifact => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 2); + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + c.DropItem(new GrobusFur()); + } + + 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 Grobu(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Grobu corpse"; - public override string DefaultName => "Grobu"; - - public override bool GivesMLMinorArtifact => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 2); - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - c.DropItem(new GrobusFur()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Painted Caves/Lurg.cs b/Projects/UOContent/Mobiles/Monsters/ML/Painted Caves/Lurg.cs index 70051d7ed..f3e7f5f47 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Painted Caves/Lurg.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Painted Caves/Lurg.cs @@ -2,73 +2,73 @@ using Server.Items; namespace Server.Mobiles { - public class Lurg : Troglodyte - { - [Constructible] - public Lurg() + public class Lurg : Troglodyte { - IsParagon = true; + [Constructible] + public Lurg() + { + IsParagon = true; - Hue = 0x455; + Hue = 0x455; - SetStr(584, 625); - SetDex(163, 176); - SetInt(90, 106); + SetStr(584, 625); + SetDex(163, 176); + SetInt(90, 106); - SetHits(3034, 3189); - SetStam(163, 176); - SetMana(90, 106); + SetHits(3034, 3189); + SetStam(163, 176); + SetMana(90, 106); - SetDamage(16, 19); + SetDamage(16, 19); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 50, 53); - SetResistance(ResistanceType.Fire, 45, 47); - SetResistance(ResistanceType.Cold, 56, 60); - SetResistance(ResistanceType.Poison, 50, 60); - SetResistance(ResistanceType.Energy, 41, 56); + SetResistance(ResistanceType.Physical, 50, 53); + SetResistance(ResistanceType.Fire, 45, 47); + SetResistance(ResistanceType.Cold, 56, 60); + SetResistance(ResistanceType.Poison, 50, 60); + SetResistance(ResistanceType.Energy, 41, 56); - SetSkill(SkillName.Wrestling, 122.7, 130.5); - SetSkill(SkillName.Tactics, 109.3, 118.5); - SetSkill(SkillName.MagicResist, 72.9, 87.6); - SetSkill(SkillName.Anatomy, 110.5, 124.0); - SetSkill(SkillName.Healing, 84.1, 105.0); + SetSkill(SkillName.Wrestling, 122.7, 130.5); + SetSkill(SkillName.Tactics, 109.3, 118.5); + SetSkill(SkillName.MagicResist, 72.9, 87.6); + SetSkill(SkillName.Anatomy, 110.5, 124.0); + SetSkill(SkillName.Healing, 84.1, 105.0); - Fame = 10000; - Karma = -10000; + Fame = 10000; + Karma = -10000; + } + + public Lurg(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Lurg corpse"; + public override string DefaultName => "Lurg"; + + public override bool GivesMLMinorArtifact => true; + public override int TreasureMapLevel => 4; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 2); + } + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.CrushingBlow; + + 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 Lurg(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Lurg corpse"; - public override string DefaultName => "Lurg"; - - public override bool GivesMLMinorArtifact => true; - public override int TreasureMapLevel => 4; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 2); - } - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.CrushingBlow; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Palace of Paroxysmus/Putrefier.cs b/Projects/UOContent/Mobiles/Monsters/ML/Palace of Paroxysmus/Putrefier.cs index e5f84b788..3b015cf6c 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Palace of Paroxysmus/Putrefier.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Palace of Paroxysmus/Putrefier.cs @@ -1,91 +1,91 @@ namespace Server.Mobiles { - public class Putrefier : Balron - { - [Constructible] - public Putrefier() + public class Putrefier : Balron { - IsParagon = true; + [Constructible] + public Putrefier() + { + IsParagon = true; - Hue = 63; + Hue = 63; - SetStr(1057, 1400); - SetDex(232, 560); - SetInt(201, 440); + SetStr(1057, 1400); + SetDex(232, 560); + SetInt(201, 440); - SetHits(3010, 4092); + SetHits(3010, 4092); - SetDamage(27, 34); + SetDamage(27, 34); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Fire, 0); - SetDamageType(ResistanceType.Poison, 50); - SetDamageType(ResistanceType.Energy, 0); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Fire, 0); + SetDamageType(ResistanceType.Poison, 50); + SetDamageType(ResistanceType.Energy, 0); - SetResistance(ResistanceType.Physical, 65, 80); - SetResistance(ResistanceType.Fire, 65, 80); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 100); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 65, 80); + SetResistance(ResistanceType.Fire, 65, 80); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 100); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.Wrestling, 111.2, 128.0); - SetSkill(SkillName.Tactics, 115.2, 125.2); - SetSkill(SkillName.MagicResist, 143.4, 170.0); - SetSkill(SkillName.Anatomy, 44.6, 67.0); - SetSkill(SkillName.Magery, 117.6, 118.8); - SetSkill(SkillName.EvalInt, 113.0, 128.8); - SetSkill(SkillName.Meditation, 41.4, 85.0); - SetSkill(SkillName.Poisoning, 45.0, 50.0); + SetSkill(SkillName.Wrestling, 111.2, 128.0); + SetSkill(SkillName.Tactics, 115.2, 125.2); + SetSkill(SkillName.MagicResist, 143.4, 170.0); + SetSkill(SkillName.Anatomy, 44.6, 67.0); + SetSkill(SkillName.Magery, 117.6, 118.8); + SetSkill(SkillName.EvalInt, 113.0, 128.8); + SetSkill(SkillName.Meditation, 41.4, 85.0); + SetSkill(SkillName.Poisoning, 45.0, 50.0); - Fame = 24000; - Karma = -24000; + Fame = 24000; + Karma = -24000; - PackScroll(4, 7); - PackScroll(4, 7); + PackScroll(4, 7); + PackScroll(4, 7); + } + + public Putrefier(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Putrefier corpse"; + public override string DefaultName => "Putrefier"; + + /* + // TODO: uncomment once added + public override void OnDeath( Container c ) + { + base.OnDeath( c ); + + c.DropItem( new SpleenOfThePutrefier() ); + + if (Utility.RandomDouble() < 0.6) + c.DropItem( new ParrotItem() ); + } + */ + + public override bool GivesMLMinorArtifact => true; + public override Poison HitPoison => Poison.Deadly; // Becomes Lethal with Paragon bonus + public override int TreasureMapLevel => 5; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 3); + } + + 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 Putrefier(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Putrefier corpse"; - public override string DefaultName => "Putrefier"; - - /* - // TODO: uncomment once added - public override void OnDeath( Container c ) - { - base.OnDeath( c ); - - c.DropItem( new SpleenOfThePutrefier() ); - - if (Utility.RandomDouble() < 0.6) - c.DropItem( new ParrotItem() ); - } - */ - - public override bool GivesMLMinorArtifact => true; - public override Poison HitPoison => Poison.Deadly; // Becomes Lethal with Paragon bonus - public override int TreasureMapLevel => 5; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 3); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CorporealBrume.cs b/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CorporealBrume.cs index c126ef0ad..0c6c772c5 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CorporealBrume.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CorporealBrume.cs @@ -2,81 +2,81 @@ using System; namespace Server.Mobiles { - public class CorporealBrume : BaseCreature - { - [Constructible] - public CorporealBrume() - : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class CorporealBrume : BaseCreature { - Body = 0x104; // TODO: Verify - BaseSoundID = 0x56B; + [Constructible] + public CorporealBrume() + : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0x104; // TODO: Verify + BaseSoundID = 0x56B; - SetStr(400, 450); - SetDex(100, 150); - SetInt(50, 60); + SetStr(400, 450); + SetDex(100, 150); + SetInt(50, 60); - SetHits(1150, 1250); + SetHits(1150, 1250); - SetDamage(21, 25); + SetDamage(21, 25); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 50, 60); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 100); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 50, 60); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.Wrestling, 110.0, 115.0); - SetSkill(SkillName.Tactics, 110.0, 115.0); - SetSkill(SkillName.MagicResist, 80.0, 95.0); - SetSkill(SkillName.Anatomy, 100.0, 110.0); + SetSkill(SkillName.Wrestling, 110.0, 115.0); + SetSkill(SkillName.Tactics, 110.0, 115.0); + SetSkill(SkillName.MagicResist, 80.0, 95.0); + SetSkill(SkillName.Anatomy, 100.0, 110.0); - Fame = 12000; - Karma = -12000; + Fame = 12000; + Karma = -12000; + } + + public CorporealBrume(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a corporeal brume corpse"; + public override string DefaultName => "a corporeal brume"; + + // TODO: Verify area attack specifics + public override bool HasAura => Combatant != null; + public override TimeSpan AuraInterval => TimeSpan.FromSeconds(20); + public override int AuraRange => 10; + + public override int AuraBaseDamage => Utility.RandomMinMax(25, 35); + public override int AuraFireDamage => 0; + public override int AuraColdDamage => 100; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.Rich); + } + + public override void AuraEffect(Mobile m) + { + m.FixedParticles(0x374A, 10, 15, 5038, 1181, 2, EffectLayer.Head); + m.PlaySound(0x213); + } + + 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 CorporealBrume(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a corporeal brume corpse"; - public override string DefaultName => "a corporeal brume"; - - // TODO: Verify area attack specifics - public override bool HasAura => Combatant != null; - public override TimeSpan AuraInterval => TimeSpan.FromSeconds(20); - public override int AuraRange => 10; - - public override int AuraBaseDamage => Utility.RandomMinMax(25, 35); - public override int AuraFireDamage => 0; - public override int AuraColdDamage => 100; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.Rich); - } - - public override void AuraEffect(Mobile m) - { - m.FixedParticles(0x374A, 10, 15, 5038, 1181, 2, EffectLayer.Head); - m.PlaySound(0x213); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CrystalDaemon.cs b/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CrystalDaemon.cs index b3a240072..b2e6726a5 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CrystalDaemon.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CrystalDaemon.cs @@ -1,82 +1,82 @@ namespace Server.Mobiles { - public class CrystalDaemon : BaseCreature - { - [Constructible] - public CrystalDaemon() - : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class CrystalDaemon : BaseCreature { - Body = 0x310; - Hue = 0x3E8; - BaseSoundID = 0x47D; + [Constructible] + public CrystalDaemon() + : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0x310; + Hue = 0x3E8; + BaseSoundID = 0x47D; - SetStr(140, 200); - SetDex(120, 150); - SetInt(800, 850); + SetStr(140, 200); + SetDex(120, 150); + SetInt(800, 850); - SetHits(200, 220); + SetHits(200, 220); - SetDamage(16, 20); + SetDamage(16, 20); - SetDamageType(ResistanceType.Physical, 0); - SetDamageType(ResistanceType.Cold, 40); - SetDamageType(ResistanceType.Energy, 60); + SetDamageType(ResistanceType.Physical, 0); + SetDamageType(ResistanceType.Cold, 40); + SetDamageType(ResistanceType.Energy, 60); - SetResistance(ResistanceType.Physical, 20, 40); - SetResistance(ResistanceType.Fire, 0, 20); - SetResistance(ResistanceType.Cold, 60, 80); - SetResistance(ResistanceType.Poison, 20, 40); - SetResistance(ResistanceType.Energy, 65, 75); + SetResistance(ResistanceType.Physical, 20, 40); + SetResistance(ResistanceType.Fire, 0, 20); + SetResistance(ResistanceType.Cold, 60, 80); + SetResistance(ResistanceType.Poison, 20, 40); + SetResistance(ResistanceType.Energy, 65, 75); - SetSkill(SkillName.Wrestling, 60.0, 80.0); - SetSkill(SkillName.Tactics, 70.0, 80.0); - SetSkill(SkillName.MagicResist, 100.0, 110.0); - SetSkill(SkillName.Magery, 120.0, 130.0); - SetSkill(SkillName.EvalInt, 100.0, 110.0); - SetSkill(SkillName.Meditation, 100.0, 110.0); + SetSkill(SkillName.Wrestling, 60.0, 80.0); + SetSkill(SkillName.Tactics, 70.0, 80.0); + SetSkill(SkillName.MagicResist, 100.0, 110.0); + SetSkill(SkillName.Magery, 120.0, 130.0); + SetSkill(SkillName.EvalInt, 100.0, 110.0); + SetSkill(SkillName.Meditation, 100.0, 110.0); - Fame = 15000; - Karma = -15000; + Fame = 15000; + Karma = -15000; - PackArcaneScroll(0, 1); + PackArcaneScroll(0, 1); + } + + /* + // TODO: uncomment once added + public override void OnDeath( Container c ) + { + base.OnDeath( c ); + + if (Utility.RandomDouble() < 0.4) + c.DropItem( new ScatteredCrystals() ); + } + */ + + public CrystalDaemon(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a crystal daemon corpse"; + public override string DefaultName => "a crystal daemon"; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 3); + } + + 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(); + } } - - /* - // TODO: uncomment once added - public override void OnDeath( Container c ) - { - base.OnDeath( c ); - - if (Utility.RandomDouble() < 0.4) - c.DropItem( new ScatteredCrystals() ); - } - */ - - public CrystalDaemon(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a crystal daemon corpse"; - public override string DefaultName => "a crystal daemon"; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 3); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CrystalLatticeSeeker.cs b/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CrystalLatticeSeeker.cs index 848368cbd..de9a09e82 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CrystalLatticeSeeker.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CrystalLatticeSeeker.cs @@ -1,154 +1,154 @@ namespace Server.Mobiles { - public class CrystalLatticeSeeker : BaseCreature - { - [Constructible] - public CrystalLatticeSeeker() - : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class CrystalLatticeSeeker : BaseCreature { - Body = 0x7B; - Hue = 0x47E; + [Constructible] + public CrystalLatticeSeeker() + : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0x7B; + Hue = 0x47E; - SetStr(550, 850); - SetDex(190, 250); - SetInt(350, 450); + SetStr(550, 850); + SetDex(190, 250); + SetInt(350, 450); - SetHits(350, 550); + SetHits(350, 550); - SetDamage(13, 19); + SetDamage(13, 19); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 80, 90); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 80, 90); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.Anatomy, 50.0, 75.0); - SetSkill(SkillName.EvalInt, 90.0, 100.0); - SetSkill(SkillName.Magery, 100.0, 100.0); - SetSkill(SkillName.Meditation, 90.0, 100.0); - SetSkill(SkillName.MagicResist, 90.0, 100.0); - SetSkill(SkillName.Tactics, 90.0, 100.0); - SetSkill(SkillName.Wrestling, 90.0, 100.0); + SetSkill(SkillName.Anatomy, 50.0, 75.0); + SetSkill(SkillName.EvalInt, 90.0, 100.0); + SetSkill(SkillName.Magery, 100.0, 100.0); + SetSkill(SkillName.Meditation, 90.0, 100.0); + SetSkill(SkillName.MagicResist, 90.0, 100.0); + SetSkill(SkillName.Tactics, 90.0, 100.0); + SetSkill(SkillName.Wrestling, 90.0, 100.0); - Fame = 17000; - Karma = -17000; + Fame = 17000; + Karma = -17000; - PackArcaneScroll(0, 2); + PackArcaneScroll(0, 2); + } + + public CrystalLatticeSeeker(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Crystal Lattice Seeker corpse"; + public override string DefaultName => "Crystal Lattice Seeker"; + + /* + // TODO: uncomment once added + public override void OnDeath( Container c ) + { + base.OnDeath( c ); + + if (Utility.RandomDouble() < 0.75) + c.DropItem( new CrystallineFragments() ); + + if (Utility.RandomDouble() < 0.07) + c.DropItem( new PiecesOfCrystal() ); + } + */ + + public override int Feathers => 100; + public override int TreasureMapLevel => 5; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 4); + // TODO: uncomment once added + // AddLoot( LootPack.Parrot ); + AddLoot(LootPack.Gems); + } + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomDouble() < 0.1) + Drain(defender); + } + + public override void OnGotMeleeAttack(Mobile attacker) + { + base.OnGotMeleeAttack(attacker); + + if (Utility.RandomDouble() < 0.1) + Drain(attacker); + } + + public virtual void Drain(Mobile m) + { + int toDrain; + + switch (Utility.Random(3)) + { + case 0: + { + Say(1042156); // I can grant life, and I can sap it as easily. + PlaySound(0x1E6); + + toDrain = Utility.RandomMinMax(3, 6); + Hits += toDrain; + m.Hits -= toDrain; + break; + } + case 1: + { + Say(1042157); // You'll go nowhere, unless I deem it should be so. + PlaySound(0x1DF); + + toDrain = Utility.RandomMinMax(10, 25); + Stam += toDrain; + m.Stam -= toDrain; + break; + } + case 2: + { + Say(1042155); // Your power is mine to use as I will. + PlaySound(0x1F8); + + toDrain = Utility.RandomMinMax(15, 25); + Mana += toDrain; + m.Mana -= toDrain; + break; + } + } + } + + public override int GetAttackSound() => 0x2F6; + + public override int GetDeathSound() => 0x2F7; + + public override int GetAngerSound() => 0x2F8; + + public override int GetHurtSound() => 0x2F9; + + public override int GetIdleSound() => 0x2FA; + + 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 CrystalLatticeSeeker(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Crystal Lattice Seeker corpse"; - public override string DefaultName => "Crystal Lattice Seeker"; - - /* - // TODO: uncomment once added - public override void OnDeath( Container c ) - { - base.OnDeath( c ); - - if (Utility.RandomDouble() < 0.75) - c.DropItem( new CrystallineFragments() ); - - if (Utility.RandomDouble() < 0.07) - c.DropItem( new PiecesOfCrystal() ); - } - */ - - public override int Feathers => 100; - public override int TreasureMapLevel => 5; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 4); - // TODO: uncomment once added - // AddLoot( LootPack.Parrot ); - AddLoot(LootPack.Gems); - } - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (Utility.RandomDouble() < 0.1) - Drain(defender); - } - - public override void OnGotMeleeAttack(Mobile attacker) - { - base.OnGotMeleeAttack(attacker); - - if (Utility.RandomDouble() < 0.1) - Drain(attacker); - } - - public virtual void Drain(Mobile m) - { - int toDrain; - - switch (Utility.Random(3)) - { - case 0: - { - Say(1042156); // I can grant life, and I can sap it as easily. - PlaySound(0x1E6); - - toDrain = Utility.RandomMinMax(3, 6); - Hits += toDrain; - m.Hits -= toDrain; - break; - } - case 1: - { - Say(1042157); // You'll go nowhere, unless I deem it should be so. - PlaySound(0x1DF); - - toDrain = Utility.RandomMinMax(10, 25); - Stam += toDrain; - m.Stam -= toDrain; - break; - } - case 2: - { - Say(1042155); // Your power is mine to use as I will. - PlaySound(0x1F8); - - toDrain = Utility.RandomMinMax(15, 25); - Mana += toDrain; - m.Mana -= toDrain; - break; - } - } - } - - public override int GetAttackSound() => 0x2F6; - - public override int GetDeathSound() => 0x2F7; - - public override int GetAngerSound() => 0x2F8; - - public override int GetHurtSound() => 0x2F9; - - public override int GetIdleSound() => 0x2FA; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CrystalSeaSerpent.cs b/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CrystalSeaSerpent.cs index 935ecb055..2b7515846 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CrystalSeaSerpent.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CrystalSeaSerpent.cs @@ -1,68 +1,68 @@ namespace Server.Mobiles { - public class CrystalSeaSerpent : SeaSerpent - { - [Constructible] - public CrystalSeaSerpent() + public class CrystalSeaSerpent : SeaSerpent { - Hue = 0x47E; + [Constructible] + public CrystalSeaSerpent() + { + Hue = 0x47E; - SetStr(250, 450); - SetDex(100, 150); - SetInt(90, 190); + SetStr(250, 450); + SetDex(100, 150); + SetInt(90, 190); - SetHits(230, 330); + SetHits(230, 330); - SetDamage(10, 18); + SetDamage(10, 18); - SetDamageType(ResistanceType.Physical, 10); - SetDamageType(ResistanceType.Cold, 45); - SetDamageType(ResistanceType.Energy, 45); + SetDamageType(ResistanceType.Physical, 10); + SetDamageType(ResistanceType.Cold, 45); + SetDamageType(ResistanceType.Energy, 45); - SetResistance(ResistanceType.Physical, 50, 70); - SetResistance(ResistanceType.Fire, 0); - SetResistance(ResistanceType.Cold, 70, 90); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 60, 80); + SetResistance(ResistanceType.Physical, 50, 70); + SetResistance(ResistanceType.Fire, 0); + SetResistance(ResistanceType.Cold, 70, 90); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 60, 80); + } + + /* + // TODO: uncomment once added + public override void OnDeath( Container c ) + { + base.OnDeath( c ); + + if (Utility.RandomDouble() < 0.05) + c.DropItem( new CrushedCrystals() ); + + if (Utility.RandomDouble() < 0.1) + c.DropItem( new IcyHeart() ); + + if (Utility.RandomDouble() < 0.1) + c.DropItem( new LuckyDagger() ); + } + */ + + public CrystalSeaSerpent(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a crystal sea serpent corpse"; + public override string DefaultName => "a crystal sea serpent"; + + 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(); + } } - - /* - // TODO: uncomment once added - public override void OnDeath( Container c ) - { - base.OnDeath( c ); - - if (Utility.RandomDouble() < 0.05) - c.DropItem( new CrushedCrystals() ); - - if (Utility.RandomDouble() < 0.1) - c.DropItem( new IcyHeart() ); - - if (Utility.RandomDouble() < 0.1) - c.DropItem( new LuckyDagger() ); - } - */ - - public CrystalSeaSerpent(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a crystal sea serpent corpse"; - public override string DefaultName => "a crystal sea serpent"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CrystalVortex.cs b/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CrystalVortex.cs index 2cf8534af..e20773064 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CrystalVortex.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CrystalVortex.cs @@ -1,89 +1,89 @@ namespace Server.Mobiles { - public class CrystalVortex : BaseCreature - { - [Constructible] - public CrystalVortex() - : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class CrystalVortex : BaseCreature { - Body = 0xD; - Hue = 0x2B2; - BaseSoundID = 0x107; + [Constructible] + public CrystalVortex() + : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0xD; + Hue = 0x2B2; + BaseSoundID = 0x107; - SetStr(800, 900); - SetDex(500, 600); - SetInt(200); + SetStr(800, 900); + SetDex(500, 600); + SetInt(200); - SetHits(350, 400); - SetMana(0); + SetHits(350, 400); + SetMana(0); - SetDamage(15, 20); + SetDamage(15, 20); - SetDamageType(ResistanceType.Physical, 0); - SetDamageType(ResistanceType.Cold, 50); - SetDamageType(ResistanceType.Energy, 50); + SetDamageType(ResistanceType.Physical, 0); + SetDamageType(ResistanceType.Cold, 50); + SetDamageType(ResistanceType.Energy, 50); - SetResistance(ResistanceType.Physical, 60, 80); - SetResistance(ResistanceType.Fire, 0, 10); - SetResistance(ResistanceType.Cold, 70, 80); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 60, 90); + SetResistance(ResistanceType.Physical, 60, 80); + SetResistance(ResistanceType.Fire, 0, 10); + SetResistance(ResistanceType.Cold, 70, 80); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 60, 90); - SetSkill(SkillName.MagicResist, 120.0); - SetSkill(SkillName.Tactics, 120.0); - SetSkill(SkillName.Wrestling, 120.0); + SetSkill(SkillName.MagicResist, 120.0); + SetSkill(SkillName.Tactics, 120.0); + SetSkill(SkillName.Wrestling, 120.0); - Fame = 17000; - Karma = -17000; + Fame = 17000; + Karma = -17000; - PackArcaneScroll(0, 2); + PackArcaneScroll(0, 2); + } + + public CrystalVortex(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a crystal vortex corpse"; + public override string DefaultName => "a crystal vortex"; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 2); + // TODO: uncomment once added + // AddLoot( LootPack.Parrot ); + } + + /* + // TODO: uncomment once added + public override void OnDeath( Container c ) + { + base.OnDeath( c ); + + if (Utility.RandomDouble() < 0.75) + c.DropItem( new CrystallineFragments() ); + + if (Utility.RandomDouble() < 0.06) + c.DropItem( new JaggedCrystals() ); + } + */ + + public override int GetAngerSound() => 0x15; + + public override int GetAttackSound() => 0x28; + + 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 CrystalVortex(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a crystal vortex corpse"; - public override string DefaultName => "a crystal vortex"; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 2); - // TODO: uncomment once added - // AddLoot( LootPack.Parrot ); - } - - /* - // TODO: uncomment once added - public override void OnDeath( Container c ) - { - base.OnDeath( c ); - - if (Utility.RandomDouble() < 0.75) - c.DropItem( new CrystallineFragments() ); - - if (Utility.RandomDouble() < 0.06) - c.DropItem( new JaggedCrystals() ); - } - */ - - public override int GetAngerSound() => 0x15; - - public override int GetAttackSound() => 0x28; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CrystalWisp.cs b/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CrystalWisp.cs index 270fa8d06..653573987 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CrystalWisp.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/CrystalWisp.cs @@ -1,34 +1,34 @@ namespace Server.Mobiles { - public class CrystalWisp : Wisp - { - [Constructible] - public CrystalWisp() + public class CrystalWisp : Wisp { - Hue = 0x482; + [Constructible] + public CrystalWisp() + { + Hue = 0x482; - PackArcaneScroll(0, 1); + PackArcaneScroll(0, 1); + } + + public CrystalWisp(Serial serial) + : base(serial) + { + } + + public override string DefaultName => "a crystal wisp"; + + 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 CrystalWisp(Serial serial) - : base(serial) - { - } - - public override string DefaultName => "a crystal wisp"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/MantraEffervescence.cs b/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/MantraEffervescence.cs index 79de668d9..d1a0f67b2 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/MantraEffervescence.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/MantraEffervescence.cs @@ -1,68 +1,68 @@ namespace Server.Mobiles { - public class MantraEffervescence : BaseCreature - { - [Constructible] - public MantraEffervescence() - : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class MantraEffervescence : BaseCreature { - Body = 0x111; - BaseSoundID = 0x56E; + [Constructible] + public MantraEffervescence() + : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0x111; + BaseSoundID = 0x56E; - SetStr(130, 150); - SetDex(120, 130); - SetInt(150, 230); + SetStr(130, 150); + SetDex(120, 130); + SetInt(150, 230); - SetHits(150, 250); + SetHits(150, 250); - SetDamage(21, 25); + SetDamage(21, 25); - SetDamageType(ResistanceType.Physical, 30); - SetDamageType(ResistanceType.Energy, 70); + SetDamageType(ResistanceType.Physical, 30); + SetDamageType(ResistanceType.Energy, 70); - SetResistance(ResistanceType.Physical, 60, 65); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 50, 60); - SetResistance(ResistanceType.Energy, 100); + SetResistance(ResistanceType.Physical, 60, 65); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 50, 60); + SetResistance(ResistanceType.Energy, 100); - SetSkill(SkillName.Wrestling, 80.0, 85.0); - SetSkill(SkillName.Tactics, 80.0, 85.0); - SetSkill(SkillName.MagicResist, 105.0, 115.0); - SetSkill(SkillName.Magery, 90.0, 110.0); - SetSkill(SkillName.EvalInt, 80.0, 90.0); - SetSkill(SkillName.Meditation, 90.0, 100.0); + SetSkill(SkillName.Wrestling, 80.0, 85.0); + SetSkill(SkillName.Tactics, 80.0, 85.0); + SetSkill(SkillName.MagicResist, 105.0, 115.0); + SetSkill(SkillName.Magery, 90.0, 110.0); + SetSkill(SkillName.EvalInt, 80.0, 90.0); + SetSkill(SkillName.Meditation, 90.0, 100.0); - Fame = 6500; - Karma = -6500; + Fame = 6500; + Karma = -6500; + } + + public MantraEffervescence(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a mantra effervescence corpse"; + public override string DefaultName => "a mantra effervescence"; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.Rich); + } + + 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 MantraEffervescence(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a mantra effervescence corpse"; - public override string DefaultName => "a mantra effervescence"; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.Rich); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/Protector.cs b/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/Protector.cs index 5d6cbc165..5a9101cb3 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/Protector.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/Protector.cs @@ -2,106 +2,106 @@ using Server.Items; namespace Server.Mobiles { - public class Protector : BaseCreature - { - [Constructible] - public Protector() - : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Protector : BaseCreature { - Body = 401; - Female = true; - Hue = Race.Human.RandomSkinHue(); - HairItemID = Race.Human.RandomHair(this); - HairHue = Race.Human.RandomHairHue(); + [Constructible] + public Protector() + : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 401; + Female = true; + Hue = Race.Human.RandomSkinHue(); + HairItemID = Race.Human.RandomHair(this); + HairHue = Race.Human.RandomHairHue(); - Title = "the mystic llamaherder"; + Title = "the mystic llamaherder"; - SetStr(700, 800); - SetDex(100, 150); - SetInt(50, 75); + SetStr(700, 800); + SetDex(100, 150); + SetInt(50, 75); - SetHits(350, 450); + SetHits(350, 450); - SetDamage(6, 12); + SetDamage(6, 12); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 30, 40); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 35, 40); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 30, 40); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 35, 40); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.Wrestling, 70.0, 100.0); - SetSkill(SkillName.Tactics, 80.0, 100.0); - SetSkill(SkillName.MagicResist, 50.0, 70.0); - SetSkill(SkillName.Anatomy, 70.0, 100.0); + SetSkill(SkillName.Wrestling, 70.0, 100.0); + SetSkill(SkillName.Tactics, 80.0, 100.0); + SetSkill(SkillName.MagicResist, 50.0, 70.0); + SetSkill(SkillName.Anatomy, 70.0, 100.0); - Fame = 10000; - Karma = -10000; + Fame = 10000; + Karma = -10000; - Item boots = new ThighBoots(); - boots.Movable = false; - boots.Hue = Utility.Random(2); + Item boots = new ThighBoots(); + boots.Movable = false; + boots.Hue = Utility.Random(2); - Item shroud = new Item(0x204E); - shroud.Layer = Layer.OuterTorso; - shroud.Movable = false; - shroud.Hue = Utility.Random(2); + var shroud = new Item(0x204E); + shroud.Layer = Layer.OuterTorso; + shroud.Movable = false; + shroud.Hue = Utility.Random(2); - AddItem(boots); - AddItem(shroud); + AddItem(boots); + AddItem(shroud); + } + + public Protector(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a human corpse"; + public override string DefaultName => "a Protector"; + + public override bool AlwaysMurderer => true; + public override bool PropertyTitle => false; + public override bool ShowFameTitle => false; + + public override void GenerateLoot(bool spawning) + { + if (spawning) + return; // No loot/backpack on spawn + + base.GenerateLoot(true); + base.GenerateLoot(false); + } + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + } + + /* + // TODO: uncomment once added + public override void OnDeath( Container c ) + { + base.OnDeath( c ); + + if (Utility.RandomDouble() < 0.4) + c.DropItem( new ProtectorsEssence() ); + } + */ + + 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 Protector(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a human corpse"; - public override string DefaultName => "a Protector"; - - public override bool AlwaysMurderer => true; - public override bool PropertyTitle => false; - public override bool ShowFameTitle => false; - - public override void GenerateLoot(bool spawning) - { - if (spawning) - return; // No loot/backpack on spawn - - base.GenerateLoot(true); - base.GenerateLoot(false); - } - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - } - - /* - // TODO: uncomment once added - public override void OnDeath( Container c ) - { - base.OnDeath( c ); - - if (Utility.RandomDouble() < 0.4) - c.DropItem( new ProtectorsEssence() ); - } - */ - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/UnfrozenMummy.cs b/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/UnfrozenMummy.cs index 1c1750135..56ca7f095 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/UnfrozenMummy.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Prism of Light/UnfrozenMummy.cs @@ -1,87 +1,87 @@ namespace Server.Mobiles { - public class UnfrozenMummy : BaseCreature - { - [Constructible] - public UnfrozenMummy() - : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.4, 0.8) + public class UnfrozenMummy : BaseCreature { - Body = 0x9B; - Hue = 0x480; - BaseSoundID = 0x1D7; + [Constructible] + public UnfrozenMummy() + : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.4, 0.8) + { + Body = 0x9B; + Hue = 0x480; + BaseSoundID = 0x1D7; - SetStr(450, 500); - SetDex(200, 250); - SetInt(800, 850); + SetStr(450, 500); + SetDex(200, 250); + SetInt(800, 850); - SetHits(1500); + SetHits(1500); - SetDamage(16, 20); + SetDamage(16, 20); - SetDamageType(ResistanceType.Physical, 0); - SetDamageType(ResistanceType.Energy, 50); - SetDamageType(ResistanceType.Cold, 50); + SetDamageType(ResistanceType.Physical, 0); + SetDamageType(ResistanceType.Energy, 50); + SetDamageType(ResistanceType.Cold, 50); - SetResistance(ResistanceType.Physical, 35, 40); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 60, 80); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 70, 80); + SetResistance(ResistanceType.Physical, 35, 40); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 60, 80); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 70, 80); - SetSkill(SkillName.Wrestling, 90.0, 100.0); - SetSkill(SkillName.Tactics, 100.0); - SetSkill(SkillName.MagicResist, 250.0); - SetSkill(SkillName.Magery, 50.0, 60.0); - SetSkill(SkillName.EvalInt, 50.0, 60.0); - SetSkill(SkillName.Meditation, 80.0); + SetSkill(SkillName.Wrestling, 90.0, 100.0); + SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.MagicResist, 250.0); + SetSkill(SkillName.Magery, 50.0, 60.0); + SetSkill(SkillName.EvalInt, 50.0, 60.0); + SetSkill(SkillName.Meditation, 80.0); - Fame = 25000; - Karma = -25000; + Fame = 25000; + Karma = -25000; - PackArcaneScroll(0, 2); + PackArcaneScroll(0, 2); + } + + /* + // TODO: uncomment once added + public override void OnDeath( Container c ) + { + base.OnDeath( c ); + + if (Utility.RandomDouble() < 0.6) + c.DropItem( new BrokenCrystals() ); + + if (Utility.RandomDouble() < 0.1) + c.DropItem( new ParrotItem() ); + } + */ + + public UnfrozenMummy(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "an unfrozen mummy corpse"; + public override string DefaultName => "an unfrozen mummy"; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 2); + // TODO: uncomment once added + // AddLoot( LootPack.Parrot ); + } + + 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(); + } } - - /* - // TODO: uncomment once added - public override void OnDeath( Container c ) - { - base.OnDeath( c ); - - if (Utility.RandomDouble() < 0.6) - c.DropItem( new BrokenCrystals() ); - - if (Utility.RandomDouble() < 0.1) - c.DropItem( new ParrotItem() ); - } - */ - - public UnfrozenMummy(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "an unfrozen mummy corpse"; - public override string DefaultName => "an unfrozen mummy"; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 2); - // TODO: uncomment once added - // AddLoot( LootPack.Parrot ); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Sanctuary/Chiikkaha.cs b/Projects/UOContent/Mobiles/Monsters/ML/Sanctuary/Chiikkaha.cs index 9ad4d969b..97d187be0 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Sanctuary/Chiikkaha.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Sanctuary/Chiikkaha.cs @@ -1,56 +1,56 @@ namespace Server.Mobiles { - public class Chiikkaha : RatmanMage - { - [Constructible] - public Chiikkaha() + public class Chiikkaha : RatmanMage { - SetStr(450, 476); - SetDex(157, 179); - SetInt(251, 275); + [Constructible] + public Chiikkaha() + { + SetStr(450, 476); + SetDex(157, 179); + SetInt(251, 275); - SetHits(400, 425); + SetHits(400, 425); - SetDamage(10, 17); + SetDamage(10, 17); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 40, 45); - SetResistance(ResistanceType.Fire, 10, 20); - SetResistance(ResistanceType.Cold, 10, 20); - SetResistance(ResistanceType.Poison, 10, 20); - SetResistance(ResistanceType.Energy, 100); + SetResistance(ResistanceType.Physical, 40, 45); + SetResistance(ResistanceType.Fire, 10, 20); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Energy, 100); - SetSkill(SkillName.EvalInt, 70.1, 80.0); - SetSkill(SkillName.Magery, 70.1, 90.0); - SetSkill(SkillName.MagicResist, 65.1, 96.0); - SetSkill(SkillName.Tactics, 50.1, 75.0); - SetSkill(SkillName.Wrestling, 50.1, 75.0); + SetSkill(SkillName.EvalInt, 70.1, 80.0); + SetSkill(SkillName.Magery, 70.1, 90.0); + SetSkill(SkillName.MagicResist, 65.1, 96.0); + SetSkill(SkillName.Tactics, 50.1, 75.0); + SetSkill(SkillName.Wrestling, 50.1, 75.0); - Fame = 7500; - Karma = -7500; + Fame = 7500; + Karma = -7500; + } + + public Chiikkaha(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Chiikkaha the Toothed corpse"; + public override string DefaultName => "Chiikkaha the Toothed"; + + 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 Chiikkaha(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Chiikkaha the Toothed corpse"; - public override string DefaultName => "Chiikkaha the Toothed"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Sanctuary/MougGuur.cs b/Projects/UOContent/Mobiles/Monsters/ML/Sanctuary/MougGuur.cs index 8274d9cf4..781dd00db 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Sanctuary/MougGuur.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Sanctuary/MougGuur.cs @@ -1,54 +1,54 @@ namespace Server.Mobiles { - public class MougGuur : Ettin - { - [Constructible] - public MougGuur() + public class MougGuur : Ettin { - SetStr(556, 575); - SetDex(84, 94); - SetInt(59, 73); + [Constructible] + public MougGuur() + { + SetStr(556, 575); + SetDex(84, 94); + SetInt(59, 73); - SetHits(400, 415); + SetHits(400, 415); - SetDamage(12, 20); + SetDamage(12, 20); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 61, 65); - SetResistance(ResistanceType.Fire, 16, 19); - SetResistance(ResistanceType.Cold, 41, 46); - SetResistance(ResistanceType.Poison, 21, 24); - SetResistance(ResistanceType.Energy, 19, 25); + SetResistance(ResistanceType.Physical, 61, 65); + SetResistance(ResistanceType.Fire, 16, 19); + SetResistance(ResistanceType.Cold, 41, 46); + SetResistance(ResistanceType.Poison, 21, 24); + SetResistance(ResistanceType.Energy, 19, 25); - SetSkill(SkillName.MagicResist, 70.2, 75.0); - SetSkill(SkillName.Tactics, 80.8, 81.7); - SetSkill(SkillName.Wrestling, 93.9, 99.4); + SetSkill(SkillName.MagicResist, 70.2, 75.0); + SetSkill(SkillName.Tactics, 80.8, 81.7); + SetSkill(SkillName.Wrestling, 93.9, 99.4); - Fame = 3000; - Karma = -3000; + Fame = 3000; + Karma = -3000; + } + + public MougGuur(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Moug-Guur corpse"; + public override string DefaultName => "Moug-Guur"; + + 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 MougGuur(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Moug-Guur corpse"; - public override string DefaultName => "Moug-Guur"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Sanctuary/Szavetra.cs b/Projects/UOContent/Mobiles/Monsters/ML/Sanctuary/Szavetra.cs index eaf11c384..f55b2f37d 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Sanctuary/Szavetra.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Sanctuary/Szavetra.cs @@ -1,58 +1,58 @@ namespace Server.Mobiles { - public class Szavetra : Succubus - { - [Constructible] - public Szavetra() + public class Szavetra : Succubus { - SetStr(627, 655); - SetDex(164, 193); - SetInt(566, 595); + [Constructible] + public Szavetra() + { + SetStr(627, 655); + SetDex(164, 193); + SetInt(566, 595); - SetHits(312, 415); + SetHits(312, 415); - SetDamage(20, 30); + SetDamage(20, 30); - SetDamageType(ResistanceType.Physical, 75); - SetDamageType(ResistanceType.Energy, 25); + SetDamageType(ResistanceType.Physical, 75); + SetDamageType(ResistanceType.Energy, 25); - SetResistance(ResistanceType.Physical, 83, 90); - SetResistance(ResistanceType.Fire, 72, 80); - SetResistance(ResistanceType.Cold, 40, 49); - SetResistance(ResistanceType.Poison, 51, 60); - SetResistance(ResistanceType.Energy, 50, 60); + SetResistance(ResistanceType.Physical, 83, 90); + SetResistance(ResistanceType.Fire, 72, 80); + SetResistance(ResistanceType.Cold, 40, 49); + SetResistance(ResistanceType.Poison, 51, 60); + SetResistance(ResistanceType.Energy, 50, 60); - SetSkill(SkillName.EvalInt, 90.3, 99.8); - SetSkill(SkillName.Magery, 100.1, 100.6); // 10.1-10.6 on OSI, bug? - SetSkill(SkillName.Meditation, 90.1, 110.0); - SetSkill(SkillName.MagicResist, 112.2, 127.2); - SetSkill(SkillName.Tactics, 91.2, 92.8); - SetSkill(SkillName.Wrestling, 80.2, 86.4); + SetSkill(SkillName.EvalInt, 90.3, 99.8); + SetSkill(SkillName.Magery, 100.1, 100.6); // 10.1-10.6 on OSI, bug? + SetSkill(SkillName.Meditation, 90.1, 110.0); + SetSkill(SkillName.MagicResist, 112.2, 127.2); + SetSkill(SkillName.Tactics, 91.2, 92.8); + SetSkill(SkillName.Wrestling, 80.2, 86.4); - Fame = 24000; - Karma = -24000; + Fame = 24000; + Karma = -24000; + } + + public Szavetra(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Szavetra corpse"; + public override string DefaultName => "Szavetra"; + + 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 Szavetra(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Szavetra corpse"; - public override string DefaultName => "Szavetra"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Special/Ilhenir.cs b/Projects/UOContent/Mobiles/Monsters/ML/Special/Ilhenir.cs index ea10ea8ba..3c395a9be 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Special/Ilhenir.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Special/Ilhenir.cs @@ -7,378 +7,381 @@ using Server.Network; namespace Server.Mobiles { - public class Ilhenir : BaseChampion - { - private static readonly HashSet m_Table = new HashSet(); - - [Constructible] - public Ilhenir() - : base(AIType.AI_Mage) + public class Ilhenir : BaseChampion { - Title = "the Stained"; - Body = 0x103; + private static readonly HashSet m_Table = new HashSet(); - BaseSoundID = 589; - - SetStr(1105, 1350); - SetDex(82, 160); - SetInt(505, 750); - - SetHits(9000); - - SetDamage(21, 28); - - SetDamageType(ResistanceType.Physical, 60); - SetDamageType(ResistanceType.Fire, 20); - SetDamageType(ResistanceType.Poison, 20); - - SetResistance(ResistanceType.Physical, 55, 65); - SetResistance(ResistanceType.Fire, 50, 60); - SetResistance(ResistanceType.Cold, 55, 65); - SetResistance(ResistanceType.Poison, 70, 90); - SetResistance(ResistanceType.Energy, 65, 75); - - SetSkill(SkillName.EvalInt, 100); - SetSkill(SkillName.Magery, 100); - SetSkill(SkillName.Meditation, 0); - SetSkill(SkillName.Poisoning, 5.4); - SetSkill(SkillName.Anatomy, 117.5); - SetSkill(SkillName.MagicResist, 120.0); - SetSkill(SkillName.Tactics, 119.9); - SetSkill(SkillName.Wrestling, 119.9); - - Fame = 50000; - Karma = -50000; - - VirtualArmor = 44; - - if (Core.ML) - { - PackResources(8); - PackTalismans(5); - } - } - - public Ilhenir(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a corpse of Ilhenir"; - public override ChampionSkullType SkullType => ChampionSkullType.Pain; - - public override Type[] UniqueList => new Type[] { }; - - public override Type[] SharedList => new[] - { - typeof(ANecromancerShroud), - typeof(LieutenantOfTheBritannianRoyalGuard), - typeof(OblivionsNeedle), - typeof(TheRobeOfBritanniaAri) - }; - - public override Type[] DecorativeList => new[] { typeof(MonsterStatuette) }; - - public override MonsterStatuetteType[] StatueTypes => new[] - { - MonsterStatuetteType.PlagueBeast, - MonsterStatuetteType.RedDeath - }; - - public override string DefaultName => "Ilhenir"; - - public override bool Unprovokable => true; - public override bool Uncalmable => true; - - public override Poison PoisonImmune => Poison.Lethal; - - // public override bool GivesMLMinorArtifact => true; // TODO: Needs verification - public override int TreasureMapLevel => 5; - - public virtual void PackResources(int amount) - { - for (int i = 0; i < amount; i++) - PackItem( - Utility.Random(6) switch - { - 0 => new Blight(), - 1 => new Scourge(), - 2 => new Taint(), - 3 => new Putrefication(), - 4 => new Corruption(), - _ => new Muculent() // 5 - } - ); - } - - public virtual void PackItems(Item item, int amount) - { - for (int i = 0; i < amount; i++) - PackItem(item); - } - - public virtual void PackTalismans(int amount) - { - int count = Utility.Random(amount); - - for (int i = 0; i < count; i++) - PackItem(new RandomTalisman()); - } - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 8); - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - if (Core.ML) - { - c.DropItem(new GrizzledBones()); - - // TODO: Parrots - /*if (Utility.RandomDouble() < 0.6) - c.DropItem( new ParrotItem() ); */ - - if (Utility.RandomDouble() < 0.05) - c.DropItem(new GrizzledMareStatuette()); - - if (Utility.RandomDouble() < 0.025) - c.DropItem(new CrimsonCincture()); - - // TODO: Armor sets - /*if (Utility.RandomDouble() < 0.05) + [Constructible] + public Ilhenir() + : base(AIType.AI_Mage) { - switch ( Utility.Random(5) ) - { - case 0: c.DropItem( new GrizzleGauntlets() ); break; - case 1: c.DropItem( new GrizzleGreaves() ); break; - case 2: c.DropItem( new GrizzleHelm() ); break; - case 3: c.DropItem( new GrizzleTunic() ); break; - case 4: c.DropItem( new GrizzleVambraces() ); break; - } - }*/ - } - } + Title = "the Stained"; + Body = 0x103; - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); + BaseSoundID = 589; - if (Utility.RandomDouble() < 0.25) - CacophonicAttack(defender); - } + SetStr(1105, 1350); + SetDex(82, 160); + SetInt(505, 750); - public override void OnDamage(int amount, Mobile from, bool willKill) - { - if (Utility.RandomDouble() < 0.1) - DropOoze(); + SetHits(9000); - base.OnDamage(amount, from, willKill); - } + SetDamage(21, 28); - public override int GetAngerSound() => 0x581; + SetDamageType(ResistanceType.Physical, 60); + SetDamageType(ResistanceType.Fire, 20); + SetDamageType(ResistanceType.Poison, 20); - public override int GetIdleSound() => 0x582; + SetResistance(ResistanceType.Physical, 55, 65); + SetResistance(ResistanceType.Fire, 50, 60); + SetResistance(ResistanceType.Cold, 55, 65); + SetResistance(ResistanceType.Poison, 70, 90); + SetResistance(ResistanceType.Energy, 65, 75); - public override int GetAttackSound() => 0x580; + SetSkill(SkillName.EvalInt, 100); + SetSkill(SkillName.Magery, 100); + SetSkill(SkillName.Meditation, 0); + SetSkill(SkillName.Poisoning, 5.4); + SetSkill(SkillName.Anatomy, 117.5); + SetSkill(SkillName.MagicResist, 120.0); + SetSkill(SkillName.Tactics, 119.9); + SetSkill(SkillName.Wrestling, 119.9); - public override int GetHurtSound() => 0x583; + Fame = 50000; + Karma = -50000; - public override int GetDeathSound() => 0x584; + VirtualArmor = 44; - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public virtual void CacophonicAttack(Mobile to) - { - if (to.Alive && to.Player && !UnderCacophonicAttack(to)) - { - to.Send(SpeedControl.WalkSpeed); - to.SendLocalizedMessage(1072069); // A cacophonic sound lambastes you, suppressing your ability to move. - to.PlaySound(0x584); - - m_Table.Add(to); - Timer.DelayCall(TimeSpan.FromSeconds(30), CacophonicEnd, to); - } - } - - public virtual void CacophonicEnd(Mobile from) - { - m_Table.Remove(from); - from.Send(SpeedControl.Disable); - } - - public static bool UnderCacophonicAttack(Mobile from) => m_Table.Contains(from); - - public virtual void DropOoze() - { - int amount = Utility.RandomMinMax(1, 3); - bool corrosive = Utility.RandomBool(); - - for (int i = 0; i < amount; i++) - { - Item ooze = new StainedOoze(corrosive); - Point3D p = new Point3D(Location); - - for (int j = 0; j < 5; j++) - { - p = GetSpawnPosition(2); - - if (!Map.GetItemsInRange(p, 0).OfType().Any()) - break; + if (Core.ML) + { + PackResources(8); + PackTalismans(5); + } } - ooze.MoveToWorld(p, Map); - } - - if (Combatant != null) - { - if (corrosive) - Combatant.SendLocalizedMessage(1072071); // A corrosive gas seeps out of your enemy's skin! - else - Combatant.SendLocalizedMessage(1072072); // A poisonous gas seeps out of your enemy's skin! - } - } - - private int RandomPoint(int mid) => mid + Utility.RandomMinMax(-2, 2); - - public virtual Point3D GetSpawnPosition(int range) => GetSpawnPosition(Location, Map, range); - - public virtual Point3D GetSpawnPosition(Point3D from, Map map, int range) - { - if (map == null) - return from; - - Point3D loc = new Point3D(RandomPoint(X), RandomPoint(Y), Z); - - loc.Z = Map.GetAverageZ(loc.X, loc.Y); - - return loc; - } - } - - public class StainedOoze : Item - { - private int m_Ticks; - private Timer m_Timer; - - [Constructible] - public StainedOoze(bool corrosive = false) : base(0x122A) - { - Movable = false; - Hue = 0x95; - - Corrosive = corrosive; - m_Timer = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromSeconds(1), OnTick); - m_Ticks = 0; - } - - public StainedOoze(Serial serial) - : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Corrosive { get; set; } - - public override void OnAfterDelete() - { - if (m_Timer != null) - { - m_Timer.Stop(); - m_Timer = null; - } - } - - private void OnTick() - { - List toDamage = new List(); - - foreach (Mobile m in GetMobilesInRange(0)) - { - if (m is BaseCreature bc) + public Ilhenir(Serial serial) + : base(serial) { - if (!bc.Controlled && !bc.Summoned) - continue; - } - else if (!m.Player) - { - continue; } - if (m.Alive && !m.IsDeadBondedPet && m.CanBeDamaged()) - toDamage.Add(m); - } + public override string CorpseName => "a corpse of Ilhenir"; + public override ChampionSkullType SkullType => ChampionSkullType.Pain; - for (int i = 0; i < toDamage.Count; ++i) - Damage(toDamage[i]); + public override Type[] UniqueList => new Type[] { }; - ++m_Ticks; - - if (m_Ticks >= 35) - Delete(); - else if (m_Ticks == 30) - ItemID = 0x122B; - } - - public void Damage(Mobile m) - { - if (Corrosive) - { - List items = m.Items; - bool damaged = false; - - for (int i = 0; i < items.Count; ++i) - if (items[i] is IDurability wearable && wearable.HitPoints >= 10 && Utility.RandomDouble() < 0.25) - { - wearable.HitPoints -= wearable.HitPoints == 10 ? Utility.Random(1, 5) : 10; - damaged = true; - } - - if (damaged) + public override Type[] SharedList => new[] { - m.LocalOverheadMessage(MessageType.Regular, 0x21, - 1072070); // The infernal ooze scorches you, setting you and your equipment ablaze! - return; + typeof(ANecromancerShroud), + typeof(LieutenantOfTheBritannianRoyalGuard), + typeof(OblivionsNeedle), + typeof(TheRobeOfBritanniaAri) + }; + + public override Type[] DecorativeList => new[] { typeof(MonsterStatuette) }; + + public override MonsterStatuetteType[] StatueTypes => new[] + { + MonsterStatuetteType.PlagueBeast, + MonsterStatuetteType.RedDeath + }; + + public override string DefaultName => "Ilhenir"; + + public override bool Unprovokable => true; + public override bool Uncalmable => true; + + public override Poison PoisonImmune => Poison.Lethal; + + // public override bool GivesMLMinorArtifact => true; // TODO: Needs verification + public override int TreasureMapLevel => 5; + + public virtual void PackResources(int amount) + { + for (var i = 0; i < amount; i++) + PackItem( + Utility.Random(6) switch + { + 0 => new Blight(), + 1 => new Scourge(), + 2 => new Taint(), + 3 => new Putrefication(), + 4 => new Corruption(), + _ => new Muculent() // 5 + } + ); } - } - AOS.Damage(m, 40, 0, 0, 0, 100, 0); + public virtual void PackItems(Item item, int amount) + { + for (var i = 0; i < amount; i++) + PackItem(item); + } + + public virtual void PackTalismans(int amount) + { + var count = Utility.Random(amount); + + for (var i = 0; i < count; i++) + PackItem(new RandomTalisman()); + } + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 8); + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + if (Core.ML) + { + c.DropItem(new GrizzledBones()); + + // TODO: Parrots + /*if (Utility.RandomDouble() < 0.6) + c.DropItem( new ParrotItem() ); */ + + if (Utility.RandomDouble() < 0.05) + c.DropItem(new GrizzledMareStatuette()); + + if (Utility.RandomDouble() < 0.025) + c.DropItem(new CrimsonCincture()); + + // TODO: Armor sets + /*if (Utility.RandomDouble() < 0.05) + { + switch ( Utility.Random(5) ) + { + case 0: c.DropItem( new GrizzleGauntlets() ); break; + case 1: c.DropItem( new GrizzleGreaves() ); break; + case 2: c.DropItem( new GrizzleHelm() ); break; + case 3: c.DropItem( new GrizzleTunic() ); break; + case 4: c.DropItem( new GrizzleVambraces() ); break; + } + }*/ + } + } + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomDouble() < 0.25) + CacophonicAttack(defender); + } + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + if (Utility.RandomDouble() < 0.1) + DropOoze(); + + base.OnDamage(amount, from, willKill); + } + + public override int GetAngerSound() => 0x581; + + public override int GetIdleSound() => 0x582; + + public override int GetAttackSound() => 0x580; + + public override int GetHurtSound() => 0x583; + + public override int GetDeathSound() => 0x584; + + 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 virtual void CacophonicAttack(Mobile to) + { + if (to.Alive && to.Player && !UnderCacophonicAttack(to)) + { + to.Send(SpeedControl.WalkSpeed); + to.SendLocalizedMessage(1072069); // A cacophonic sound lambastes you, suppressing your ability to move. + to.PlaySound(0x584); + + m_Table.Add(to); + Timer.DelayCall(TimeSpan.FromSeconds(30), CacophonicEnd, to); + } + } + + public virtual void CacophonicEnd(Mobile from) + { + m_Table.Remove(from); + from.Send(SpeedControl.Disable); + } + + public static bool UnderCacophonicAttack(Mobile from) => m_Table.Contains(from); + + public virtual void DropOoze() + { + var amount = Utility.RandomMinMax(1, 3); + var corrosive = Utility.RandomBool(); + + for (var i = 0; i < amount; i++) + { + Item ooze = new StainedOoze(corrosive); + var p = new Point3D(Location); + + for (var j = 0; j < 5; j++) + { + p = GetSpawnPosition(2); + + if (!Map.GetItemsInRange(p, 0).OfType().Any()) + break; + } + + ooze.MoveToWorld(p, Map); + } + + if (Combatant != null) + { + if (corrosive) + Combatant.SendLocalizedMessage(1072071); // A corrosive gas seeps out of your enemy's skin! + else + Combatant.SendLocalizedMessage(1072072); // A poisonous gas seeps out of your enemy's skin! + } + } + + private int RandomPoint(int mid) => mid + Utility.RandomMinMax(-2, 2); + + public virtual Point3D GetSpawnPosition(int range) => GetSpawnPosition(Location, Map, range); + + public virtual Point3D GetSpawnPosition(Point3D from, Map map, int range) + { + if (map == null) + return from; + + var loc = new Point3D(RandomPoint(X), RandomPoint(Y), Z); + + loc.Z = Map.GetAverageZ(loc.X, loc.Y); + + return loc; + } } - public override void Serialize(IGenericWriter writer) + public class StainedOoze : Item { - base.Serialize(writer); + private int m_Ticks; + private Timer m_Timer; - writer.Write(0); // version + [Constructible] + public StainedOoze(bool corrosive = false) : base(0x122A) + { + Movable = false; + Hue = 0x95; - writer.Write(Corrosive); + Corrosive = corrosive; + m_Timer = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromSeconds(1), OnTick); + m_Ticks = 0; + } + + public StainedOoze(Serial serial) + : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Corrosive { get; set; } + + public override void OnAfterDelete() + { + if (m_Timer != null) + { + m_Timer.Stop(); + m_Timer = null; + } + } + + private void OnTick() + { + var toDamage = new List(); + + foreach (var m in GetMobilesInRange(0)) + { + if (m is BaseCreature bc) + { + if (!bc.Controlled && !bc.Summoned) + continue; + } + else if (!m.Player) + { + continue; + } + + if (m.Alive && !m.IsDeadBondedPet && m.CanBeDamaged()) + toDamage.Add(m); + } + + for (var i = 0; i < toDamage.Count; ++i) + Damage(toDamage[i]); + + ++m_Ticks; + + if (m_Ticks >= 35) + Delete(); + else if (m_Ticks == 30) + ItemID = 0x122B; + } + + public void Damage(Mobile m) + { + if (Corrosive) + { + var items = m.Items; + var damaged = false; + + for (var i = 0; i < items.Count; ++i) + if (items[i] is IDurability wearable && wearable.HitPoints >= 10 && Utility.RandomDouble() < 0.25) + { + wearable.HitPoints -= wearable.HitPoints == 10 ? Utility.Random(1, 5) : 10; + damaged = true; + } + + if (damaged) + { + m.LocalOverheadMessage( + MessageType.Regular, + 0x21, + 1072070 + ); // The infernal ooze scorches you, setting you and your equipment ablaze! + return; + } + } + + AOS.Damage(m, 40, 0, 0, 0, 100, 0); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(Corrosive); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + Corrosive = reader.ReadBool(); + + m_Timer = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromSeconds(1), OnTick); + m_Ticks = ItemID == 0x122A ? 0 : 30; + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Corrosive = reader.ReadBool(); - - m_Timer = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromSeconds(1), OnTick); - m_Ticks = ItemID == 0x122A ? 0 : 30; - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Special/Meraktus.cs b/Projects/UOContent/Mobiles/Monsters/ML/Special/Meraktus.cs index a9efb408b..c2a5abbfc 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Special/Meraktus.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Special/Meraktus.cs @@ -4,213 +4,213 @@ using Server.Items; namespace Server.Mobiles { - public class Meraktus : BaseChampion - { - [Constructible] - public Meraktus() - : base(AIType.AI_Melee) + public class Meraktus : BaseChampion { - Title = "the Tormented"; - Body = 263; - BaseSoundID = 680; - Hue = 0x835; - - SetStr(1419, 1438); - SetDex(309, 413); - SetInt(129, 131); - - SetHits(4100, 4200); - - SetDamage(16, 30); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 65, 90); - SetResistance(ResistanceType.Fire, 65, 70); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 40, 60); - SetResistance(ResistanceType.Energy, 50, 55); - - // SetSkill( SkillName.Meditation, Unknown ); - // SetSkill( SkillName.EvalInt, Unknown ); - // SetSkill( SkillName.Magery, Unknown ); - // SetSkill( SkillName.Poisoning, Unknown ); - SetSkill(SkillName.Anatomy, 0); - SetSkill(SkillName.MagicResist, 107.0, 111.3); - SetSkill(SkillName.Tactics, 107.0, 117.0); - SetSkill(SkillName.Wrestling, 100.0, 105.0); - - Fame = 70000; - Karma = -70000; - - VirtualArmor = 28; // Don't know what it should be - - if (Core.ML) - { - PackResources(8); - PackTalismans(5); - } - - Timer.DelayCall(TimeSpan.FromSeconds(1), SpawnTormented); - } - - public Meraktus(Serial serial) : base(serial) - { - } - - public override string CorpseName => "the remains of Meraktus"; - public override ChampionSkullType SkullType => ChampionSkullType.Pain; - - public override Type[] UniqueList => new[] { typeof(Subdue) }; - public override Type[] SharedList => new Type[] { }; - - public override Type[] DecorativeList => new[] - { - typeof(ArtifactLargeVase), - typeof(ArtifactVase), - typeof(MinotaurStatueDeed) - }; - - public override MonsterStatuetteType[] StatueTypes => new[] { MonsterStatuetteType.Minotaur }; - - public override string DefaultName => "Meraktus"; - - public override int Meat => 2; - public override int Hides => 10; - public override HideType HideType => HideType.Regular; - public override Poison PoisonImmune => Poison.Regular; - public override int TreasureMapLevel => 3; - public override bool BardImmune => true; - public override bool Unprovokable => true; - public override bool Uncalmable => true; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.Dismount; - - public virtual void PackResources(int amount) - { - for (int i = 0; i < amount; i++) - PackItem( - Utility.Random(6) switch - { - 0 => new Blight(), - 1 => new Scourge(), - 2 => new Taint(), - 3 => new Putrefication(), - 4 => new Corruption(), - _ => new Muculent() // 5 - } - ); - } - - public virtual void PackTalismans(int amount) - { - int count = Utility.Random(amount); - - for (int i = 0; i < count; i++) - PackItem(new RandomTalisman()); - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - if (!Core.ML) - return; - - c.DropItem(new MalletAndChisel()); - - c.DropItem( - Utility.Random(3) switch + [Constructible] + public Meraktus() + : base(AIType.AI_Melee) { - 0 => new MinotaurHedge(), - 1 => new LightYarn(), - _ => new BonePile() // 2 + Title = "the Tormented"; + Body = 263; + BaseSoundID = 680; + Hue = 0x835; + + SetStr(1419, 1438); + SetDex(309, 413); + SetInt(129, 131); + + SetHits(4100, 4200); + + SetDamage(16, 30); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 65, 90); + SetResistance(ResistanceType.Fire, 65, 70); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 40, 60); + SetResistance(ResistanceType.Energy, 50, 55); + + // SetSkill( SkillName.Meditation, Unknown ); + // SetSkill( SkillName.EvalInt, Unknown ); + // SetSkill( SkillName.Magery, Unknown ); + // SetSkill( SkillName.Poisoning, Unknown ); + SetSkill(SkillName.Anatomy, 0); + SetSkill(SkillName.MagicResist, 107.0, 111.3); + SetSkill(SkillName.Tactics, 107.0, 117.0); + SetSkill(SkillName.Wrestling, 100.0, 105.0); + + Fame = 70000; + Karma = -70000; + + VirtualArmor = 28; // Don't know what it should be + + if (Core.ML) + { + PackResources(8); + PackTalismans(5); + } + + Timer.DelayCall(TimeSpan.FromSeconds(1), SpawnTormented); } - ); - if (Utility.RandomBool()) - c.DropItem(new TormentedChains()); + public Meraktus(Serial serial) : base(serial) + { + } - if (Utility.RandomDouble() < 0.025) - c.DropItem(new CrimsonCincture()); + public override string CorpseName => "the remains of Meraktus"; + public override ChampionSkullType SkullType => ChampionSkullType.Pain; + + public override Type[] UniqueList => new[] { typeof(Subdue) }; + public override Type[] SharedList => new Type[] { }; + + public override Type[] DecorativeList => new[] + { + typeof(ArtifactLargeVase), + typeof(ArtifactVase), + typeof(MinotaurStatueDeed) + }; + + public override MonsterStatuetteType[] StatueTypes => new[] { MonsterStatuetteType.Minotaur }; + + public override string DefaultName => "Meraktus"; + + public override int Meat => 2; + public override int Hides => 10; + public override HideType HideType => HideType.Regular; + public override Poison PoisonImmune => Poison.Regular; + public override int TreasureMapLevel => 3; + public override bool BardImmune => true; + public override bool Unprovokable => true; + public override bool Uncalmable => true; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.Dismount; + + public virtual void PackResources(int amount) + { + for (var i = 0; i < amount; i++) + PackItem( + Utility.Random(6) switch + { + 0 => new Blight(), + 1 => new Scourge(), + 2 => new Taint(), + 3 => new Putrefication(), + 4 => new Corruption(), + _ => new Muculent() // 5 + } + ); + } + + public virtual void PackTalismans(int amount) + { + var count = Utility.Random(amount); + + for (var i = 0; i < count; i++) + PackItem(new RandomTalisman()); + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + if (!Core.ML) + return; + + c.DropItem(new MalletAndChisel()); + + c.DropItem( + Utility.Random(3) switch + { + 0 => new MinotaurHedge(), + 1 => new LightYarn(), + _ => new BonePile() // 2 + } + ); + + if (Utility.RandomBool()) + c.DropItem(new TormentedChains()); + + if (Utility.RandomDouble() < 0.025) + c.DropItem(new CrimsonCincture()); + } + + public override void GenerateLoot() + { + if (Core.ML) + AddLoot(LootPack.AosSuperBoss, 5); // Need to verify + } + + public override int GetAngerSound() => 0x597; + + public override int GetIdleSound() => 0x596; + + public override int GetAttackSound() => 0x599; + + public override int GetHurtSound() => 0x59a; + + public override int GetDeathSound() => 0x59c; + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomDouble() <= 0.2) + Earthquake(); + } + + public void Earthquake() + { + var eable = GetMobilesInRange(8); + + foreach (var m in eable) + { + if (m == this || !CanBeHarmful(m) || m.Deleted || !m.Player && + !(m is BaseCreature creature && (creature.Controlled || creature.Summoned || creature.Team != Team))) + continue; + + if (m is PlayerMobile pm && pm.Mounted) + pm.Mount.Rider = null; + + var damage = (int)(m.Hits * 0.6); + if (damage < 10) + damage = 10; + else if (damage > 75) + damage = 75; + DoHarmful(m); + AOS.Damage(m, this, damage, 100, 0, 0, 0, 0); + if (m.Alive && m.Body.IsHuman && !m.Mounted) + m.Animate(20, 7, 1, true, false, 0); // take hit + } + + eable.Free(); + } + + 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(); + } + + public void SpawnTormented() + { + BaseCreature spawna = new TormentedMinotaur(); + spawna.MoveToWorld(Location, Map); + + BaseCreature spawnb = new TormentedMinotaur(); + spawnb.MoveToWorld(Location, Map); + + BaseCreature spawnc = new TormentedMinotaur(); + spawnc.MoveToWorld(Location, Map); + + BaseCreature spawnd = new TormentedMinotaur(); + spawnd.MoveToWorld(Location, Map); + } } - - public override void GenerateLoot() - { - if (Core.ML) - AddLoot(LootPack.AosSuperBoss, 5); // Need to verify - } - - public override int GetAngerSound() => 0x597; - - public override int GetIdleSound() => 0x596; - - public override int GetAttackSound() => 0x599; - - public override int GetHurtSound() => 0x59a; - - public override int GetDeathSound() => 0x59c; - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (Utility.RandomDouble() <= 0.2) - Earthquake(); - } - - public void Earthquake() - { - IPooledEnumerable eable = GetMobilesInRange(8); - - foreach (Mobile m in eable) - { - if (m == this || !CanBeHarmful(m) || m.Deleted || !m.Player && - !(m is BaseCreature creature && (creature.Controlled || creature.Summoned || creature.Team != Team))) - continue; - - if (m is PlayerMobile pm && pm.Mounted) - pm.Mount.Rider = null; - - int damage = (int)(m.Hits * 0.6); - if (damage < 10) - damage = 10; - else if (damage > 75) - damage = 75; - DoHarmful(m); - AOS.Damage(m, this, damage, 100, 0, 0, 0, 0); - if (m.Alive && m.Body.IsHuman && !m.Mounted) - m.Animate(20, 7, 1, true, false, 0); // take hit - } - - eable.Free(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - - public void SpawnTormented() - { - BaseCreature spawna = new TormentedMinotaur(); - spawna.MoveToWorld(Location, Map); - - BaseCreature spawnb = new TormentedMinotaur(); - spawnb.MoveToWorld(Location, Map); - - BaseCreature spawnc = new TormentedMinotaur(); - spawnc.MoveToWorld(Location, Map); - - BaseCreature spawnd = new TormentedMinotaur(); - spawnd.MoveToWorld(Location, Map); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Special/Twaulo.cs b/Projects/UOContent/Mobiles/Monsters/ML/Special/Twaulo.cs index 4b020f367..55aef6f6a 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Special/Twaulo.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Special/Twaulo.cs @@ -4,135 +4,135 @@ using Server.Items; namespace Server.Mobiles { - public class Twaulo : BaseChampion - { - [Constructible] - public Twaulo() - : base(AIType.AI_Melee) + public class Twaulo : BaseChampion { - Title = "of the Glade"; - Body = 101; - BaseSoundID = 679; - Hue = 0x455; + [Constructible] + public Twaulo() + : base(AIType.AI_Melee) + { + Title = "of the Glade"; + Body = 101; + BaseSoundID = 679; + Hue = 0x455; - SetStr(1751, 1950); - SetDex(251, 450); - SetInt(801, 1000); + SetStr(1751, 1950); + SetDex(251, 450); + SetInt(801, 1000); - SetHits(7500); + SetHits(7500); - SetDamage(19, 24); + SetDamage(19, 24); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 65, 75); - SetResistance(ResistanceType.Fire, 45, 55); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 50, 60); - SetResistance(ResistanceType.Energy, 50, 60); + SetResistance(ResistanceType.Physical, 65, 75); + SetResistance(ResistanceType.Fire, 45, 55); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 50, 60); + SetResistance(ResistanceType.Energy, 50, 60); - SetSkill(SkillName.EvalInt, 0); // Per Stratics?!? - SetSkill(SkillName.Magery, 0); // Per Stratics?!? - SetSkill(SkillName.Meditation, 0); // Per Stratics?!? - SetSkill(SkillName.Anatomy, 95.1, 115.0); - SetSkill(SkillName.Archery, 95.1, 100.0); - SetSkill(SkillName.MagicResist, 50.3, 80.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); - SetSkill(SkillName.Wrestling, 95.1, 100.0); + SetSkill(SkillName.EvalInt, 0); // Per Stratics?!? + SetSkill(SkillName.Magery, 0); // Per Stratics?!? + SetSkill(SkillName.Meditation, 0); // Per Stratics?!? + SetSkill(SkillName.Anatomy, 95.1, 115.0); + SetSkill(SkillName.Archery, 95.1, 100.0); + SetSkill(SkillName.MagicResist, 50.3, 80.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.Wrestling, 95.1, 100.0); - Fame = 50000; - Karma = 50000; + Fame = 50000; + Karma = 50000; - VirtualArmor = 50; + VirtualArmor = 50; - AddItem(new Bow()); - PackItem(new Arrow(Utility.RandomMinMax(500, 700))); + AddItem(new Bow()); + PackItem(new Arrow(Utility.RandomMinMax(500, 700))); + } + + public Twaulo(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a corpse of Twaulo"; + public override ChampionSkullType SkullType => ChampionSkullType.Pain; + + public override Type[] UniqueList => new[] { typeof(Quell) }; + public override Type[] SharedList => new[] { typeof(TheMostKnowledgePerson), typeof(OblivionsNeedle) }; + public override Type[] DecorativeList => new[] { typeof(Pier), typeof(MonsterStatuette) }; + + public override MonsterStatuetteType[] StatueTypes => new[] { MonsterStatuetteType.DreadHorn }; + + public override string DefaultName => "Twaulo"; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override bool Unprovokable => true; + public override Poison PoisonImmune => Poison.Regular; + public override int TreasureMapLevel => 5; + public override int Meat => 1; + public override int Hides => 8; + public override HideType HideType => HideType.Spined; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 2); + AddLoot(LootPack.Average); + AddLoot(LootPack.Gems); + } + + public void SpawnPixies(Mobile target) + { + var map = Map; + + if (map == null) + return; + + var newPixies = Utility.RandomMinMax(3, 6); + + for (var i = 0; i < newPixies; ++i) + { + var pixie = new Pixie { Team = Team, FightMode = FightMode.Closest }; + + pixie.MoveToWorld(map.GetRandomNearbyLocation(Location), map); + pixie.Combatant = target; + } + } + + public override void AlterDamageScalarFrom(Mobile caster, ref double scalar) + { + if (Utility.RandomDouble() <= 0.1) + SpawnPixies(caster); + } + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + defender.Damage(Utility.Random(20, 10), this); + defender.Stam -= Utility.Random(20, 10); + defender.Mana -= Utility.Random(20, 10); + } + + public override void OnGotMeleeAttack(Mobile attacker) + { + base.OnGotMeleeAttack(attacker); + + if (Utility.RandomDouble() <= 0.1) + SpawnPixies(attacker); + } + + 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(); + } } - - public Twaulo(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a corpse of Twaulo"; - public override ChampionSkullType SkullType => ChampionSkullType.Pain; - - public override Type[] UniqueList => new[] { typeof(Quell) }; - public override Type[] SharedList => new[] { typeof(TheMostKnowledgePerson), typeof(OblivionsNeedle) }; - public override Type[] DecorativeList => new[] { typeof(Pier), typeof(MonsterStatuette) }; - - public override MonsterStatuetteType[] StatueTypes => new[] { MonsterStatuetteType.DreadHorn }; - - public override string DefaultName => "Twaulo"; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override bool Unprovokable => true; - public override Poison PoisonImmune => Poison.Regular; - public override int TreasureMapLevel => 5; - public override int Meat => 1; - public override int Hides => 8; - public override HideType HideType => HideType.Spined; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 2); - AddLoot(LootPack.Average); - AddLoot(LootPack.Gems); - } - - public void SpawnPixies(Mobile target) - { - Map map = Map; - - if (map == null) - return; - - int newPixies = Utility.RandomMinMax(3, 6); - - for (int i = 0; i < newPixies; ++i) - { - Pixie pixie = new Pixie { Team = Team, FightMode = FightMode.Closest }; - - pixie.MoveToWorld(map.GetRandomNearbyLocation(Location), map); - pixie.Combatant = target; - } - } - - public override void AlterDamageScalarFrom(Mobile caster, ref double scalar) - { - if (Utility.RandomDouble() <= 0.1) - SpawnPixies(caster); - } - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - defender.Damage(Utility.Random(20, 10), this); - defender.Stam -= Utility.Random(20, 10); - defender.Mana -= Utility.Random(20, 10); - } - - public override void OnGotMeleeAttack(Mobile attacker) - { - base.OnGotMeleeAttack(attacker); - - if (Utility.RandomDouble() <= 0.1) - SpawnPixies(attacker); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Changeling.cs b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Changeling.cs index 84c6055b5..21c91054f 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Changeling.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Changeling.cs @@ -4,297 +4,297 @@ using Server.Spells; namespace Server.Mobiles { - public class Changeling : BaseCreature - { - private static readonly int[] m_FireNorth = + public class Changeling : BaseCreature { - -1, -1, - 1, -1, - -1, 2, - 1, 2 - }; - - private static readonly int[] m_FireEast = - { - -1, 0, - 2, 0 - }; - - private DateTime m_LastMorph; - - private Mobile m_MorphedInto; - private DateTime m_NextFireRing; - - [Constructible] - public Changeling() - : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) - { - Body = 264; - Hue = DefaultHue; - - SetStr(36, 105); - SetDex(212, 262); - SetInt(317, 399); - - SetHits(201, 211); - SetStam(212, 262); - SetMana(317, 399); - - SetDamage(9, 15); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 81, 90); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 40, 49); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 43, 50); - - SetSkill(SkillName.Wrestling, 10.4, 12.5); - SetSkill(SkillName.Tactics, 101.1, 108.3); - SetSkill(SkillName.MagicResist, 121.6, 132.2); - SetSkill(SkillName.Magery, 91.6, 99.5); - SetSkill(SkillName.EvalInt, 91.5, 98.8); - SetSkill(SkillName.Meditation, 91.7, 98.5); - - Fame = 15000; - Karma = -15000; - - PackScroll(1, 7); - PackItem(new Arrow(35)); - PackItem(new Bolt(25)); - PackGem(2); - - PackArcaneScroll(0, 1); - } - - public Changeling(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a changeling corpse"; - public override string DefaultName => "a changeling"; - public virtual int DefaultHue => 0; - - public override bool ShowFameTitle => false; - public override bool InitialInnocent => m_MorphedInto != null; - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile MorphedInto - { - get => m_MorphedInto; - set - { - if (value == this) - value = null; - - if (m_MorphedInto != value) + private static readonly int[] m_FireNorth = { - Revert(); + -1, -1, + 1, -1, + -1, 2, + 1, 2 + }; - if (value != null) - { - Morph(value); - m_LastMorph = DateTime.UtcNow; - } - - m_MorphedInto = value; - Delta(MobileDelta.Noto); - } - } - } - - public override void GenerateLoot() - { - AddLoot(LootPack.AosRich, 3); - } - - public override int GetAngerSound() => 0x46E; - - public override int GetIdleSound() => 0x470; - - public override int GetAttackSound() => 0x46D; - - public override int GetHurtSound() => 0x471; - - public override int GetDeathSound() => 0x46F; - - public override void OnThink() - { - base.OnThink(); - - if (Combatant != null) - { - if (m_NextFireRing <= DateTime.UtcNow && Utility.RandomDouble() < 0.02) + private static readonly int[] m_FireEast = { - FireRing(); - m_NextFireRing = DateTime.UtcNow + TimeSpan.FromMinutes(2); + -1, 0, + 2, 0 + }; + + private DateTime m_LastMorph; + + private Mobile m_MorphedInto; + private DateTime m_NextFireRing; + + [Constructible] + public Changeling() + : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 264; + Hue = DefaultHue; + + SetStr(36, 105); + SetDex(212, 262); + SetInt(317, 399); + + SetHits(201, 211); + SetStam(212, 262); + SetMana(317, 399); + + SetDamage(9, 15); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 81, 90); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 40, 49); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 43, 50); + + SetSkill(SkillName.Wrestling, 10.4, 12.5); + SetSkill(SkillName.Tactics, 101.1, 108.3); + SetSkill(SkillName.MagicResist, 121.6, 132.2); + SetSkill(SkillName.Magery, 91.6, 99.5); + SetSkill(SkillName.EvalInt, 91.5, 98.8); + SetSkill(SkillName.Meditation, 91.7, 98.5); + + Fame = 15000; + Karma = -15000; + + PackScroll(1, 7); + PackItem(new Arrow(35)); + PackItem(new Bolt(25)); + PackGem(2); + + PackArcaneScroll(0, 1); } - if (Combatant.Player && m_MorphedInto != Combatant && Utility.RandomDouble() < 0.05) - MorphedInto = Combatant; - } - } - - public override bool CheckIdle() - { - bool idle = base.CheckIdle(); - - if (idle && m_MorphedInto != null && DateTime.UtcNow - m_LastMorph > TimeSpan.FromSeconds(30)) - MorphedInto = null; - - return idle; - } - - private void FireEffects(int itemID, int[] offsets) - { - for (int i = 0; i < offsets.Length; i += 2) - { - Point3D p = Location; - - p.X += offsets[i]; - p.Y += offsets[i + 1]; - - if (SpellHelper.AdjustField(ref p, Map, 12, false)) - Effects.SendLocationEffect(p, Map, itemID, 50); - } - } - - protected virtual void FireRing() - { - FireEffects(0x3E27, m_FireNorth); - FireEffects(0x3E31, m_FireEast); - } - - protected virtual void Morph(Mobile m) - { - Body = m.Body; - Hue = m.Hue; - Female = m.Female; - Name = m.Name; - NameHue = m.NameHue; - Title = m.Title; - Kills = m.Kills; - HairItemID = m.HairItemID; - HairHue = m.HairHue; - FacialHairItemID = m.FacialHairItemID; - FacialHairHue = m.FacialHairHue; - - // TODO: Skills? - - foreach (Item item in m.Items) - if (item.Layer != Layer.Backpack && item.Layer != Layer.Mount && item.Layer != Layer.Bank) - AddItem(new ClonedItem(item)); // TODO: Clone weapon/armor attributes - - PlaySound(0x511); - FixedParticles(0x376A, 1, 14, 5045, EffectLayer.Waist); - } - - protected virtual void Revert() - { - Body = 264; - Hue = IsParagon && DefaultHue == 0 ? Paragon.Hue : DefaultHue; - Female = false; - Name = null; - NameHue = -1; - Title = null; - Kills = 0; - HairItemID = 0; - HairHue = 0; - FacialHairItemID = 0; - FacialHairHue = 0; - - DeleteClonedItems(); - - PlaySound(0x511); - FixedParticles(0x376A, 1, 14, 5045, EffectLayer.Waist); - } - - public void DeleteClonedItems() - { - for (int i = Items.Count - 1; i >= 0; --i) - { - Item item = Items[i]; - - if (item is ClonedItem) - item.Delete(); - } - - if (Backpack != null) - for (int i = Backpack.Items.Count - 1; i >= 0; --i) + public Changeling(Serial serial) + : base(serial) { - Item item = Backpack.Items[i]; + } - if (item is ClonedItem) - item.Delete(); + public override string CorpseName => "a changeling corpse"; + public override string DefaultName => "a changeling"; + public virtual int DefaultHue => 0; + + public override bool ShowFameTitle => false; + public override bool InitialInnocent => m_MorphedInto != null; + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile MorphedInto + { + get => m_MorphedInto; + set + { + if (value == this) + value = null; + + if (m_MorphedInto != value) + { + Revert(); + + if (value != null) + { + Morph(value); + m_LastMorph = DateTime.UtcNow; + } + + m_MorphedInto = value; + Delta(MobileDelta.Noto); + } + } + } + + public override void GenerateLoot() + { + AddLoot(LootPack.AosRich, 3); + } + + public override int GetAngerSound() => 0x46E; + + public override int GetIdleSound() => 0x470; + + public override int GetAttackSound() => 0x46D; + + public override int GetHurtSound() => 0x471; + + public override int GetDeathSound() => 0x46F; + + public override void OnThink() + { + base.OnThink(); + + if (Combatant != null) + { + if (m_NextFireRing <= DateTime.UtcNow && Utility.RandomDouble() < 0.02) + { + FireRing(); + m_NextFireRing = DateTime.UtcNow + TimeSpan.FromMinutes(2); + } + + if (Combatant.Player && m_MorphedInto != Combatant && Utility.RandomDouble() < 0.05) + MorphedInto = Combatant; + } + } + + public override bool CheckIdle() + { + var idle = base.CheckIdle(); + + if (idle && m_MorphedInto != null && DateTime.UtcNow - m_LastMorph > TimeSpan.FromSeconds(30)) + MorphedInto = null; + + return idle; + } + + private void FireEffects(int itemID, int[] offsets) + { + for (var i = 0; i < offsets.Length; i += 2) + { + var p = Location; + + p.X += offsets[i]; + p.Y += offsets[i + 1]; + + if (SpellHelper.AdjustField(ref p, Map, 12, false)) + Effects.SendLocationEffect(p, Map, itemID, 50); + } + } + + protected virtual void FireRing() + { + FireEffects(0x3E27, m_FireNorth); + FireEffects(0x3E31, m_FireEast); + } + + protected virtual void Morph(Mobile m) + { + Body = m.Body; + Hue = m.Hue; + Female = m.Female; + Name = m.Name; + NameHue = m.NameHue; + Title = m.Title; + Kills = m.Kills; + HairItemID = m.HairItemID; + HairHue = m.HairHue; + FacialHairItemID = m.FacialHairItemID; + FacialHairHue = m.FacialHairHue; + + // TODO: Skills? + + foreach (var item in m.Items) + if (item.Layer != Layer.Backpack && item.Layer != Layer.Mount && item.Layer != Layer.Bank) + AddItem(new ClonedItem(item)); // TODO: Clone weapon/armor attributes + + PlaySound(0x511); + FixedParticles(0x376A, 1, 14, 5045, EffectLayer.Waist); + } + + protected virtual void Revert() + { + Body = 264; + Hue = IsParagon && DefaultHue == 0 ? Paragon.Hue : DefaultHue; + Female = false; + Name = null; + NameHue = -1; + Title = null; + Kills = 0; + HairItemID = 0; + HairHue = 0; + FacialHairItemID = 0; + FacialHairHue = 0; + + DeleteClonedItems(); + + PlaySound(0x511); + FixedParticles(0x376A, 1, 14, 5045, EffectLayer.Waist); + } + + public void DeleteClonedItems() + { + for (var i = Items.Count - 1; i >= 0; --i) + { + var item = Items[i]; + + if (item is ClonedItem) + item.Delete(); + } + + if (Backpack != null) + for (var i = Backpack.Items.Count - 1; i >= 0; --i) + { + var item = Backpack.Items[i]; + + if (item is ClonedItem) + item.Delete(); + } + } + + public override void OnAfterDelete() + { + DeleteClonedItems(); + + base.OnAfterDelete(); + } + + public override void ClearHands() + { + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + writer.Write(m_MorphedInto != null); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (reader.ReadBool()) + ValidationQueue.Add(this); + } + + public void Validate() + { + Revert(); + } + + private class ClonedItem : Item + { + public ClonedItem(Item item) + : base(item.ItemID) + { + Name = item.Name; + Weight = item.Weight; + Hue = item.Hue; + Layer = item.Layer; + Movable = false; + } + + public ClonedItem(Serial serial) + : base(serial) + { + } + + 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 OnAfterDelete() - { - DeleteClonedItems(); - - base.OnAfterDelete(); - } - - public override void ClearHands() - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - writer.Write(m_MorphedInto != null); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (reader.ReadBool()) - ValidationQueue.Add(this); - } - - public void Validate() - { - Revert(); - } - - private class ClonedItem : Item - { - public ClonedItem(Item item) - : base(item.ItemID) - { - Name = item.Name; - Weight = item.Weight; - Hue = item.Hue; - Layer = item.Layer; - Movable = false; - } - - public ClonedItem(Serial serial) - : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Gnaw.cs b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Gnaw.cs index 7623297f1..d38d248df 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Gnaw.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Gnaw.cs @@ -1,80 +1,80 @@ namespace Server.Mobiles { - public class Gnaw : DireWolf - { - [Constructible] - public Gnaw() + public class Gnaw : DireWolf { - IsParagon = true; + [Constructible] + public Gnaw() + { + IsParagon = true; - Hue = 0x130; + Hue = 0x130; - SetStr(151, 172); - SetDex(124, 145); - SetInt(60, 86); + SetStr(151, 172); + SetDex(124, 145); + SetInt(60, 86); - SetHits(817, 857); - SetStam(124, 145); - SetMana(52, 86); + SetHits(817, 857); + SetStam(124, 145); + SetMana(52, 86); - SetDamage(16, 22); + SetDamage(16, 22); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 64, 69); - SetResistance(ResistanceType.Fire, 53, 56); - SetResistance(ResistanceType.Cold, 22, 27); - SetResistance(ResistanceType.Poison, 27, 30); - SetResistance(ResistanceType.Energy, 21, 34); + SetResistance(ResistanceType.Physical, 64, 69); + SetResistance(ResistanceType.Fire, 53, 56); + SetResistance(ResistanceType.Cold, 22, 27); + SetResistance(ResistanceType.Poison, 27, 30); + SetResistance(ResistanceType.Energy, 21, 34); - SetSkill(SkillName.Wrestling, 106.4, 116.5); - SetSkill(SkillName.Tactics, 84.1, 103.2); - SetSkill(SkillName.MagicResist, 96.8, 110.7); + SetSkill(SkillName.Wrestling, 106.4, 116.5); + SetSkill(SkillName.Tactics, 84.1, 103.2); + SetSkill(SkillName.MagicResist, 96.8, 110.7); - Fame = 17500; - Karma = -17500; + Fame = 17500; + Karma = -17500; + } + + /* + // TODO: uncomment once added + public override void OnDeath( Container c ) + { + base.OnDeath( c ); + + if (Utility.RandomDouble() < 0.3) + c.DropItem( new GnawsFang() ); + } + */ + + public Gnaw(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Gnaw corpse"; + public override string DefaultName => "Gnaw"; + + public override bool GivesMLMinorArtifact => true; + public override int Hides => 28; + public override int Meat => 4; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 2); + } + + 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(); + } } - - /* - // TODO: uncomment once added - public override void OnDeath( Container c ) - { - base.OnDeath( c ); - - if (Utility.RandomDouble() < 0.3) - c.DropItem( new GnawsFang() ); - } - */ - - public Gnaw(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Gnaw corpse"; - public override string DefaultName => "Gnaw"; - - public override bool GivesMLMinorArtifact => true; - public override int Hides => 28; - public override int Meat => 4; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Guile.cs b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Guile.cs index e8b65eae0..47909f87b 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Guile.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Guile.cs @@ -1,84 +1,84 @@ namespace Server.Mobiles { - public class Guile : Changeling - { - [Constructible] - public Guile() + public class Guile : Changeling { - IsParagon = true; - - Hue = DefaultHue; - - SetStr(53, 214); - SetDex(243, 367); - SetInt(369, 586); - - SetHits(1013, 1058); - SetStam(243, 367); - SetMana(369, 586); - - SetDamage(14, 20); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 80, 90); - SetResistance(ResistanceType.Fire, 43, 46); - SetResistance(ResistanceType.Cold, 42, 44); - SetResistance(ResistanceType.Poison, 42, 50); - SetResistance(ResistanceType.Energy, 47, 50); - - SetSkill(SkillName.Wrestling, 12.8, 16.7); - SetSkill(SkillName.Tactics, 102.6, 131.0); - SetSkill(SkillName.MagicResist, 141.2, 161.6); - SetSkill(SkillName.Magery, 108.4, 120.0); - SetSkill(SkillName.EvalInt, 108.4, 120.0); - SetSkill(SkillName.Meditation, 109.2, 120.0); - - Fame = 21000; - Karma = -21000; - } - - public Guile(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Guile corpse"; - public override string DefaultName => "Guile"; - public override int DefaultHue => 0x3F; - - public override bool GivesMLMinorArtifact => true; - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (Utility.RandomBool()) - if (!Kappa.IsBeingDrained(defender) && Mana > 14) + [Constructible] + public Guile() { - defender.SendLocalizedMessage(1070848); // You feel your life force being stolen away. - Kappa.BeginLifeDrain(defender, this); - Mana -= 15; + IsParagon = true; + + Hue = DefaultHue; + + SetStr(53, 214); + SetDex(243, 367); + SetInt(369, 586); + + SetHits(1013, 1058); + SetStam(243, 367); + SetMana(369, 586); + + SetDamage(14, 20); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 80, 90); + SetResistance(ResistanceType.Fire, 43, 46); + SetResistance(ResistanceType.Cold, 42, 44); + SetResistance(ResistanceType.Poison, 42, 50); + SetResistance(ResistanceType.Energy, 47, 50); + + SetSkill(SkillName.Wrestling, 12.8, 16.7); + SetSkill(SkillName.Tactics, 102.6, 131.0); + SetSkill(SkillName.MagicResist, 141.2, 161.6); + SetSkill(SkillName.Magery, 108.4, 120.0); + SetSkill(SkillName.EvalInt, 108.4, 120.0); + SetSkill(SkillName.Meditation, 109.2, 120.0); + + Fame = 21000; + Karma = -21000; + } + + public Guile(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Guile corpse"; + public override string DefaultName => "Guile"; + public override int DefaultHue => 0x3F; + + public override bool GivesMLMinorArtifact => true; + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomBool()) + if (!Kappa.IsBeingDrained(defender) && Mana > 14) + { + defender.SendLocalizedMessage(1070848); // You feel your life force being stolen away. + Kappa.BeginLifeDrain(defender, this); + Mana -= 15; + } + } + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 2); + } + + 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 GenerateLoot() - { - AddLoot(LootPack.UltraRich, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Irk.cs b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Irk.cs index 426b876b8..7654a38a4 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Irk.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Irk.cs @@ -1,85 +1,85 @@ namespace Server.Mobiles { - public class Irk : Changeling - { - [Constructible] - public Irk() + public class Irk : Changeling { - IsParagon = true; + [Constructible] + public Irk() + { + IsParagon = true; - Hue = DefaultHue; + Hue = DefaultHue; - SetStr(23, 183); - SetDex(259, 360); - SetInt(374, 600); + SetStr(23, 183); + SetDex(259, 360); + SetInt(374, 600); - SetHits(1006, 1064); - SetStam(259, 360); - SetMana(374, 600); + SetHits(1006, 1064); + SetStam(259, 360); + SetMana(374, 600); - SetDamage(14, 20); + SetDamage(14, 20); - SetResistance(ResistanceType.Physical, 80, 90); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 41, 50); - SetResistance(ResistanceType.Energy, 40, 49); + SetResistance(ResistanceType.Physical, 80, 90); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 41, 50); + SetResistance(ResistanceType.Energy, 40, 49); - SetSkill(SkillName.Wrestling, 120.3, 123.0); - SetSkill(SkillName.Tactics, 120.1, 131.8); - SetSkill(SkillName.MagicResist, 132.3, 165.8); - SetSkill(SkillName.Magery, 108.9, 119.7); - SetSkill(SkillName.EvalInt, 108.4, 120.0); - SetSkill(SkillName.Meditation, 108.9, 119.1); + SetSkill(SkillName.Wrestling, 120.3, 123.0); + SetSkill(SkillName.Tactics, 120.1, 131.8); + SetSkill(SkillName.MagicResist, 132.3, 165.8); + SetSkill(SkillName.Magery, 108.9, 119.7); + SetSkill(SkillName.EvalInt, 108.4, 120.0); + SetSkill(SkillName.Meditation, 108.9, 119.1); - Fame = 21000; - Karma = -21000; + Fame = 21000; + Karma = -21000; + } + + /* + // TODO: uncomment once added + public override void OnDeath( Container c ) + { + base.OnDeath( c ); + + if (Utility.RandomDouble() < 0.25) + c.DropItem( new IrksBrain() ); + + if (Utility.RandomDouble() < 0.025) + c.DropItem( new PaladinGloves() ); + } + */ + + public Irk(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "an Irk corpse"; + public override string DefaultName => "Irk"; + public override int DefaultHue => 0x489; + + // TODO: Angry fire + + public override bool GivesMLMinorArtifact => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 2); + } + + 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(); + } } - - /* - // TODO: uncomment once added - public override void OnDeath( Container c ) - { - base.OnDeath( c ); - - if (Utility.RandomDouble() < 0.25) - c.DropItem( new IrksBrain() ); - - if (Utility.RandomDouble() < 0.025) - c.DropItem( new PaladinGloves() ); - } - */ - - public Irk(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "an Irk corpse"; - public override string DefaultName => "Irk"; - public override int DefaultHue => 0x489; - - // TODO: Angry fire - - public override bool GivesMLMinorArtifact => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/LadyLissith.cs b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/LadyLissith.cs index 1b4dfbb8a..62cdd6d31 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/LadyLissith.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/LadyLissith.cs @@ -2,88 +2,88 @@ using Server.Items; namespace Server.Mobiles { - public class LadyLissith : GiantBlackWidow - { - [Constructible] - public LadyLissith() + public class LadyLissith : GiantBlackWidow { - IsParagon = true; - Hue = 0x452; + [Constructible] + public LadyLissith() + { + IsParagon = true; + Hue = 0x452; - SetStr(81, 130); - SetDex(116, 152); - SetInt(44, 100); + SetStr(81, 130); + SetDex(116, 152); + SetInt(44, 100); - SetHits(245, 375); - SetStam(116, 152); - SetMana(44, 100); + SetHits(245, 375); + SetStam(116, 152); + SetMana(44, 100); - SetDamage(15, 22); + SetDamage(15, 22); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 40, 50); - SetResistance(ResistanceType.Fire, 31, 39); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 71, 80); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 40, 50); + SetResistance(ResistanceType.Fire, 31, 39); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 71, 80); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.Wrestling, 108.6, 123.0); - SetSkill(SkillName.Tactics, 102.7, 119.0); - SetSkill(SkillName.MagicResist, 78.8, 95.6); - SetSkill(SkillName.Anatomy, 68.6, 106.8); - SetSkill(SkillName.Poisoning, 96.6, 112.9); + SetSkill(SkillName.Wrestling, 108.6, 123.0); + SetSkill(SkillName.Tactics, 102.7, 119.0); + SetSkill(SkillName.MagicResist, 78.8, 95.6); + SetSkill(SkillName.Anatomy, 68.6, 106.8); + SetSkill(SkillName.Poisoning, 96.6, 112.9); - Fame = 18900; - Karma = -18900; + Fame = 18900; + Karma = -18900; + } + + public LadyLissith(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Lady Lissith corpse"; + public override string DefaultName => "Lady Lissith"; + + /* + // TODO: uncomment once added + public override void OnDeath( Container c ) + { + base.OnDeath( c ); + + if (Utility.RandomDouble() < 0.025) + c.DropItem( new GreymistChest() ); + + if (Utility.RandomDouble() < 0.45) + c.DropItem( new LissithsSilk() ); + + if (Utility.RandomDouble() < 0.1) + c.DropItem( new ParrotItem() ); + } + */ + + public override bool GivesMLMinorArtifact => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 2); + } + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.BleedAttack; + + 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 LadyLissith(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Lady Lissith corpse"; - public override string DefaultName => "Lady Lissith"; - - /* - // TODO: uncomment once added - public override void OnDeath( Container c ) - { - base.OnDeath( c ); - - if (Utility.RandomDouble() < 0.025) - c.DropItem( new GreymistChest() ); - - if (Utility.RandomDouble() < 0.45) - c.DropItem( new LissithsSilk() ); - - if (Utility.RandomDouble() < 0.1) - c.DropItem( new ParrotItem() ); - } - */ - - public override bool GivesMLMinorArtifact => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 2); - } - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.BleedAttack; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/LadySabrix.cs b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/LadySabrix.cs index fbd8d58a5..a766101f9 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/LadySabrix.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/LadySabrix.cs @@ -2,94 +2,94 @@ using Server.Items; namespace Server.Mobiles { - public class LadySabrix : GiantBlackWidow - { - [Constructible] - public LadySabrix() + public class LadySabrix : GiantBlackWidow { - IsParagon = true; - Hue = 0x497; - - SetStr(82, 130); - SetDex(117, 146); - SetInt(50, 98); - - SetHits(233, 361); - SetStam(117, 146); - SetMana(50, 98); - - SetDamage(15, 22); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 40, 50); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 30, 39); - SetResistance(ResistanceType.Poison, 70, 80); - SetResistance(ResistanceType.Energy, 35, 44); - - SetSkill(SkillName.Wrestling, 109.8, 122.8); - SetSkill(SkillName.Tactics, 102.8, 120.0); - SetSkill(SkillName.MagicResist, 79.4, 95.1); - SetSkill(SkillName.Anatomy, 68.8, 105.1); - SetSkill(SkillName.Poisoning, 97.8, 116.7); - - Fame = 18900; - Karma = -18900; - } - - public LadySabrix(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Lady Sabrix corpse"; - public override string DefaultName => "Lady Sabrix"; - - /* - // TODO: uncomment once added - public override void OnDeath( Container c ) - { - base.OnDeath( c ); - - if (Utility.RandomDouble() < 0.2) - c.DropItem( new SabrixsEye() ); - - if (Utility.RandomDouble() < 0.25) - { - switch ( Utility.Random( 2 ) ) + [Constructible] + public LadySabrix() { - case 0: AddToBackpack( new PaladinArms() ); break; - case 1: AddToBackpack( new HunterLegs() ); break; + IsParagon = true; + Hue = 0x497; + + SetStr(82, 130); + SetDex(117, 146); + SetInt(50, 98); + + SetHits(233, 361); + SetStam(117, 146); + SetMana(50, 98); + + SetDamage(15, 22); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 40, 50); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 30, 39); + SetResistance(ResistanceType.Poison, 70, 80); + SetResistance(ResistanceType.Energy, 35, 44); + + SetSkill(SkillName.Wrestling, 109.8, 122.8); + SetSkill(SkillName.Tactics, 102.8, 120.0); + SetSkill(SkillName.MagicResist, 79.4, 95.1); + SetSkill(SkillName.Anatomy, 68.8, 105.1); + SetSkill(SkillName.Poisoning, 97.8, 116.7); + + Fame = 18900; + Karma = -18900; } - } - if (Utility.RandomDouble() < 0.1) - c.DropItem( new ParrotItem() ); + public LadySabrix(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Lady Sabrix corpse"; + public override string DefaultName => "Lady Sabrix"; + + /* + // TODO: uncomment once added + public override void OnDeath( Container c ) + { + base.OnDeath( c ); + + if (Utility.RandomDouble() < 0.2) + c.DropItem( new SabrixsEye() ); + + if (Utility.RandomDouble() < 0.25) + { + switch ( Utility.Random( 2 ) ) + { + case 0: AddToBackpack( new PaladinArms() ); break; + case 1: AddToBackpack( new HunterLegs() ); break; + } + } + + if (Utility.RandomDouble() < 0.1) + c.DropItem( new ParrotItem() ); + } + */ + + public override bool GivesMLMinorArtifact => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 2); + } + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.ArmorIgnore; + + 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 GivesMLMinorArtifact => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 2); - } - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.ArmorIgnore; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Malefic.cs b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Malefic.cs index 97804c373..4e5d7a606 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Malefic.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Malefic.cs @@ -2,79 +2,79 @@ using Server.Items; namespace Server.Mobiles { - public class Malefic : DreadSpider - { - [Constructible] - public Malefic() + public class Malefic : DreadSpider { - IsParagon = true; - Hue = 0x455; + [Constructible] + public Malefic() + { + IsParagon = true; + Hue = 0x455; - SetStr(210, 284); - SetDex(153, 197); - SetInt(349, 390); + SetStr(210, 284); + SetDex(153, 197); + SetInt(349, 390); - SetHits(600, 747); - SetStam(153, 197); - SetMana(349, 390); + SetHits(600, 747); + SetStam(153, 197); + SetMana(349, 390); - SetDamage(15, 22); + SetDamage(15, 22); - SetDamageType(ResistanceType.Physical, 20); - SetDamageType(ResistanceType.Poison, 80); + SetDamageType(ResistanceType.Physical, 20); + SetDamageType(ResistanceType.Poison, 80); - SetResistance(ResistanceType.Physical, 60, 70); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 40, 49); - SetResistance(ResistanceType.Poison, 100); - SetResistance(ResistanceType.Energy, 41, 48); + SetResistance(ResistanceType.Physical, 60, 70); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 40, 49); + SetResistance(ResistanceType.Poison, 100); + SetResistance(ResistanceType.Energy, 41, 48); - SetSkill(SkillName.Wrestling, 96.9, 112.4); - SetSkill(SkillName.Tactics, 91.3, 105.4); - SetSkill(SkillName.MagicResist, 79.8, 95.1); - SetSkill(SkillName.Magery, 103.0, 118.6); - SetSkill(SkillName.EvalInt, 105.7, 119.6); - SetSkill(SkillName.Meditation, 0); + SetSkill(SkillName.Wrestling, 96.9, 112.4); + SetSkill(SkillName.Tactics, 91.3, 105.4); + SetSkill(SkillName.MagicResist, 79.8, 95.1); + SetSkill(SkillName.Magery, 103.0, 118.6); + SetSkill(SkillName.EvalInt, 105.7, 119.6); + SetSkill(SkillName.Meditation, 0); - Fame = 21000; - Karma = -21000; + Fame = 21000; + Karma = -21000; - /* - // TODO: uncomment once added - if (Utility.RandomDouble() < 0.1) - PackItem( new ParrotItem() ); - */ + /* + // TODO: uncomment once added + if (Utility.RandomDouble() < 0.1) + PackItem( new ParrotItem() ); + */ + } + + public Malefic(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Malefic corpse"; + public override string DefaultName => "Malefic"; + + public override bool GivesMLMinorArtifact => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 3); + } + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.Dismount; + + 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 Malefic(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Malefic corpse"; - public override string DefaultName => "Malefic"; - - public override bool GivesMLMinorArtifact => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 3); - } - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.Dismount; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Silk.cs b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Silk.cs index c0273b5b5..b86642212 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Silk.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Silk.cs @@ -2,71 +2,71 @@ using Server.Items; namespace Server.Mobiles { - public class Silk : GiantBlackWidow - { - [Constructible] - public Silk() + public class Silk : GiantBlackWidow { - IsParagon = true; - Hue = 0x47E; + [Constructible] + public Silk() + { + IsParagon = true; + Hue = 0x47E; - SetStr(80, 131); - SetDex(126, 156); - SetInt(63, 102); + SetStr(80, 131); + SetDex(126, 156); + SetInt(63, 102); - SetHits(279, 378); - SetStam(126, 156); - SetMana(63, 102); + SetHits(279, 378); + SetStam(126, 156); + SetMana(63, 102); - SetDamage(15, 22); + SetDamage(15, 22); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 40, 50); - SetResistance(ResistanceType.Fire, 30, 39); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 70, 76); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 40, 50); + SetResistance(ResistanceType.Fire, 30, 39); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 70, 76); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.Wrestling, 114.1, 123.7); - SetSkill(SkillName.Tactics, 102.6, 118.3); - SetSkill(SkillName.MagicResist, 78.6, 94.8); - SetSkill(SkillName.Anatomy, 81.3, 105.7); - SetSkill(SkillName.Poisoning, 106.0, 119.2); + SetSkill(SkillName.Wrestling, 114.1, 123.7); + SetSkill(SkillName.Tactics, 102.6, 118.3); + SetSkill(SkillName.MagicResist, 78.6, 94.8); + SetSkill(SkillName.Anatomy, 81.3, 105.7); + SetSkill(SkillName.Poisoning, 106.0, 119.2); - Fame = 18900; - Karma = -18900; + Fame = 18900; + Karma = -18900; + } + + public Silk(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Silk corpse"; + public override string DefaultName => "Silk"; + + public override bool GivesMLMinorArtifact => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 2); + } + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.ParalyzingBlow; + + 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 Silk(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Silk corpse"; - public override string DefaultName => "Silk"; - - public override bool GivesMLMinorArtifact => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 2); - } - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.ParalyzingBlow; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Spite.cs b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Spite.cs index bd3a59dcb..31920e211 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Spite.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Spite.cs @@ -1,71 +1,71 @@ namespace Server.Mobiles { - public class Spite : Changeling - { - [Constructible] - public Spite() + public class Spite : Changeling { - IsParagon = true; + [Constructible] + public Spite() + { + IsParagon = true; - Hue = DefaultHue; + Hue = DefaultHue; - SetStr(53, 214); - SetDex(243, 367); - SetInt(369, 586); + SetStr(53, 214); + SetDex(243, 367); + SetInt(369, 586); - SetHits(1013, 1052); - SetStam(243, 367); - SetMana(369, 586); + SetHits(1013, 1052); + SetStam(243, 367); + SetMana(369, 586); - SetDamage(14, 20); + SetDamage(14, 20); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 85, 90); - SetResistance(ResistanceType.Fire, 41, 46); - SetResistance(ResistanceType.Cold, 40, 44); - SetResistance(ResistanceType.Poison, 42, 46); - SetResistance(ResistanceType.Energy, 45, 47); + SetResistance(ResistanceType.Physical, 85, 90); + SetResistance(ResistanceType.Fire, 41, 46); + SetResistance(ResistanceType.Cold, 40, 44); + SetResistance(ResistanceType.Poison, 42, 46); + SetResistance(ResistanceType.Energy, 45, 47); - SetSkill(SkillName.Wrestling, 12.8, 16.7); - SetSkill(SkillName.Tactics, 102.6, 131.0); - SetSkill(SkillName.MagicResist, 141.2, 161.6); - SetSkill(SkillName.Magery, 108.4, 119.2); - SetSkill(SkillName.EvalInt, 108.4, 120.0); - SetSkill(SkillName.Meditation, 109.2, 120.0); + SetSkill(SkillName.Wrestling, 12.8, 16.7); + SetSkill(SkillName.Tactics, 102.6, 131.0); + SetSkill(SkillName.MagicResist, 141.2, 161.6); + SetSkill(SkillName.Magery, 108.4, 119.2); + SetSkill(SkillName.EvalInt, 108.4, 120.0); + SetSkill(SkillName.Meditation, 109.2, 120.0); - Fame = 21000; - Karma = -21000; + Fame = 21000; + Karma = -21000; + } + + public Spite(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Spite corpse"; + public override string DefaultName => "Spite"; + public override int DefaultHue => 0x21; + + public override bool GivesMLMinorArtifact => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 2); + } + + 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 Spite(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Spite corpse"; - public override string DefaultName => "Spite"; - public override int DefaultHue => 0x21; - - public override bool GivesMLMinorArtifact => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Swoop.cs b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Swoop.cs index 1003314c5..6c5c52e9b 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Swoop.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Swoop.cs @@ -3,168 +3,169 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class Swoop : Eagle - { - private static readonly Dictionary m_Table = new Dictionary(); - - [Constructible] - public Swoop() + public class Swoop : Eagle { - IsParagon = true; - Hue = 0xE0; + private static readonly Dictionary m_Table = new Dictionary(); - AI = AIType.AI_Melee; - - SetStr(100, 150); - SetDex(400, 500); - SetInt(80, 90); - - SetHits(1500, 2000); - - SetDamage(20, 30); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 75, 90); - SetResistance(ResistanceType.Fire, 60, 77); - SetResistance(ResistanceType.Cold, 70, 85); - SetResistance(ResistanceType.Poison, 55, 85); - SetResistance(ResistanceType.Energy, 50, 60); - - SetSkill(SkillName.Wrestling, 120.0, 140.0); - SetSkill(SkillName.Tactics, 120.0, 140.0); - SetSkill(SkillName.MagicResist, 95.0, 105.0); - - Fame = 18000; - Karma = 0; - - PackReg(4); - PackArcaneScroll(0, 1); - } - - /* - // TODO: uncomment once added - public override void OnDeath( Container c ) - { - base.OnDeath( c ); - - if (Utility.RandomDouble() < 0.025) - { - switch ( Utility.Random( 18 ) ) + [Constructible] + public Swoop() { - case 0: c.DropItem( new AssassinChest() ); break; - case 1: c.DropItem( new AssassinArms() ); break; - case 2: c.DropItem( new DeathChest() ); break; - case 3: c.DropItem( new MyrmidonArms() ); break; - case 4: c.DropItem( new MyrmidonLegs() ); break; - case 5: c.DropItem( new MyrmidonGorget() ); break; - case 6: c.DropItem( new LeafweaveGloves() ); break; - case 7: c.DropItem( new LeafweaveLegs() ); break; - case 8: c.DropItem( new LeafweavePauldrons() ); break; - case 9: c.DropItem( new PaladinGloves() ); break; - case 10: c.DropItem( new PaladinGorget() ); break; - case 11: c.DropItem( new PaladinArms() ); break; - case 12: c.DropItem( new HunterArms() ); break; - case 13: c.DropItem( new HunterGloves() ); break; - case 14: c.DropItem( new HunterLegs() ); break; - case 15: c.DropItem( new HunterChest() ); break; - case 16: c.DropItem( new GreymistArms() ); break; - case 17: c.DropItem( new GreymistGloves() ); break; + IsParagon = true; + Hue = 0xE0; + + AI = AIType.AI_Melee; + + SetStr(100, 150); + SetDex(400, 500); + SetInt(80, 90); + + SetHits(1500, 2000); + + SetDamage(20, 30); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 75, 90); + SetResistance(ResistanceType.Fire, 60, 77); + SetResistance(ResistanceType.Cold, 70, 85); + SetResistance(ResistanceType.Poison, 55, 85); + SetResistance(ResistanceType.Energy, 50, 60); + + SetSkill(SkillName.Wrestling, 120.0, 140.0); + SetSkill(SkillName.Tactics, 120.0, 140.0); + SetSkill(SkillName.MagicResist, 95.0, 105.0); + + Fame = 18000; + Karma = 0; + + PackReg(4); + PackArcaneScroll(0, 1); } - } - if (Utility.RandomDouble() < 0.1) - c.DropItem( new ParrotItem() ); + /* + // TODO: uncomment once added + public override void OnDeath( Container c ) + { + base.OnDeath( c ); + + if (Utility.RandomDouble() < 0.025) + { + switch ( Utility.Random( 18 ) ) + { + case 0: c.DropItem( new AssassinChest() ); break; + case 1: c.DropItem( new AssassinArms() ); break; + case 2: c.DropItem( new DeathChest() ); break; + case 3: c.DropItem( new MyrmidonArms() ); break; + case 4: c.DropItem( new MyrmidonLegs() ); break; + case 5: c.DropItem( new MyrmidonGorget() ); break; + case 6: c.DropItem( new LeafweaveGloves() ); break; + case 7: c.DropItem( new LeafweaveLegs() ); break; + case 8: c.DropItem( new LeafweavePauldrons() ); break; + case 9: c.DropItem( new PaladinGloves() ); break; + case 10: c.DropItem( new PaladinGorget() ); break; + case 11: c.DropItem( new PaladinArms() ); break; + case 12: c.DropItem( new HunterArms() ); break; + case 13: c.DropItem( new HunterGloves() ); break; + case 14: c.DropItem( new HunterLegs() ); break; + case 15: c.DropItem( new HunterChest() ); break; + case 16: c.DropItem( new GreymistArms() ); break; + case 17: c.DropItem( new GreymistGloves() ); break; + } + } + + if (Utility.RandomDouble() < 0.1) + c.DropItem( new ParrotItem() ); + } + */ + + public Swoop(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Swoop corpse"; + public override string DefaultName => "Swoop"; + + public override bool CanFly => true; + public override bool GivesMLMinorArtifact => true; + public override int Feathers => 72; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 2); + } + + // TODO: Put this attack shared with Hiryu and Lesser Hiryu in one place + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomDouble() >= 0.1) + return; + + if (m_Table.TryGetValue(defender, out var timer)) + { + timer.DoExpire(); + defender.SendLocalizedMessage(1070837); // The creature lands another blow in your weakened state. + } + else + { + defender.SendLocalizedMessage( + 1070836 + ); // The blow from the creature's claws has made you more susceptible to physical attacks. + } + + var effect = -(defender.PhysicalResistance * 15 / 100); + + var mod = new ResistanceMod(ResistanceType.Physical, effect); + + defender.FixedEffect(0x37B9, 10, 5); + defender.AddResistanceMod(mod); + + timer = new ExpireTimer(defender, mod, TimeSpan.FromSeconds(5.0)); + timer.Start(); + m_Table[defender] = timer; + } + + 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(); + } + + private class ExpireTimer : Timer + { + private readonly Mobile m_Mobile; + private readonly ResistanceMod m_Mod; + + public ExpireTimer(Mobile m, ResistanceMod mod, TimeSpan delay) + : base(delay) + { + m_Mobile = m; + m_Mod = mod; + Priority = TimerPriority.TwoFiftyMS; + } + + public void DoExpire() + { + m_Mobile.RemoveResistanceMod(m_Mod); + Stop(); + m_Table.Remove(m_Mobile); + } + + protected override void OnTick() + { + m_Mobile.SendLocalizedMessage(1070838); // Your resistance to physical attacks has returned. + DoExpire(); + } + } } - */ - - public Swoop(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Swoop corpse"; - public override string DefaultName => "Swoop"; - - public override bool CanFly => true; - public override bool GivesMLMinorArtifact => true; - public override int Feathers => 72; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 2); - } - - // TODO: Put this attack shared with Hiryu and Lesser Hiryu in one place - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (Utility.RandomDouble() >= 0.1) - return; - - if (m_Table.TryGetValue(defender, out ExpireTimer timer)) - { - timer.DoExpire(); - defender.SendLocalizedMessage(1070837); // The creature lands another blow in your weakened state. - } - else - { - defender.SendLocalizedMessage( - 1070836); // The blow from the creature's claws has made you more susceptible to physical attacks. - } - - int effect = -(defender.PhysicalResistance * 15 / 100); - - ResistanceMod mod = new ResistanceMod(ResistanceType.Physical, effect); - - defender.FixedEffect(0x37B9, 10, 5); - defender.AddResistanceMod(mod); - - timer = new ExpireTimer(defender, mod, TimeSpan.FromSeconds(5.0)); - timer.Start(); - m_Table[defender] = timer; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private class ExpireTimer : Timer - { - private readonly Mobile m_Mobile; - private readonly ResistanceMod m_Mod; - - public ExpireTimer(Mobile m, ResistanceMod mod, TimeSpan delay) - : base(delay) - { - m_Mobile = m; - m_Mod = mod; - Priority = TimerPriority.TwoFiftyMS; - } - - public void DoExpire() - { - m_Mobile.RemoveResistanceMod(m_Mod); - Stop(); - m_Table.Remove(m_Mobile); - } - - protected override void OnTick() - { - m_Mobile.SendLocalizedMessage(1070838); // Your resistance to physical attacks has returned. - DoExpire(); - } - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Virulent.cs b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Virulent.cs index ac833c644..d0289658d 100644 --- a/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Virulent.cs +++ b/Projects/UOContent/Mobiles/Monsters/ML/Twisted Weald/Virulent.cs @@ -2,93 +2,93 @@ using Server.Items; namespace Server.Mobiles { - public class Virulent : DreadSpider - { - [Constructible] - public Virulent() + public class Virulent : DreadSpider { - IsParagon = true; - Hue = 0x8FD; - - SetStr(207, 252); - SetDex(156, 194); - SetInt(346, 398); - - SetHits(616, 740); - SetStam(156, 194); - SetMana(346, 398); - - SetDamage(15, 22); - - SetDamageType(ResistanceType.Physical, 20); - SetDamageType(ResistanceType.Poison, 80); - - SetResistance(ResistanceType.Physical, 60, 68); - SetResistance(ResistanceType.Fire, 40, 49); - SetResistance(ResistanceType.Cold, 41, 50); - SetResistance(ResistanceType.Poison, 100); - SetResistance(ResistanceType.Energy, 40, 49); - - SetSkill(SkillName.Wrestling, 92.8, 111.7); - SetSkill(SkillName.Tactics, 91.6, 107.4); - SetSkill(SkillName.MagicResist, 78.1, 93.3); - SetSkill(SkillName.Poisoning, 120.0); - SetSkill(SkillName.Magery, 104.2, 119.8); - SetSkill(SkillName.EvalInt, 102.8, 117.8); - - Fame = 21000; - Karma = -21000; - } - - public Virulent(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a Virulent corpse"; - public override string DefaultName => "Virulent"; - - /* - // TODO: uncomment once added - public override void OnDeath( Container c ) - { - base.OnDeath( c ); - - if (Utility.RandomDouble() < 0.025) - { - switch ( Utility.Random( 2 ) ) + [Constructible] + public Virulent() { - case 0: c.DropItem( new HunterLegs() ); break; - case 1: c.DropItem( new MalekisHonor() ); break; + IsParagon = true; + Hue = 0x8FD; + + SetStr(207, 252); + SetDex(156, 194); + SetInt(346, 398); + + SetHits(616, 740); + SetStam(156, 194); + SetMana(346, 398); + + SetDamage(15, 22); + + SetDamageType(ResistanceType.Physical, 20); + SetDamageType(ResistanceType.Poison, 80); + + SetResistance(ResistanceType.Physical, 60, 68); + SetResistance(ResistanceType.Fire, 40, 49); + SetResistance(ResistanceType.Cold, 41, 50); + SetResistance(ResistanceType.Poison, 100); + SetResistance(ResistanceType.Energy, 40, 49); + + SetSkill(SkillName.Wrestling, 92.8, 111.7); + SetSkill(SkillName.Tactics, 91.6, 107.4); + SetSkill(SkillName.MagicResist, 78.1, 93.3); + SetSkill(SkillName.Poisoning, 120.0); + SetSkill(SkillName.Magery, 104.2, 119.8); + SetSkill(SkillName.EvalInt, 102.8, 117.8); + + Fame = 21000; + Karma = -21000; } - } - if (Utility.RandomDouble() < 0.1) - c.DropItem( new ParrotItem() ); + public Virulent(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a Virulent corpse"; + public override string DefaultName => "Virulent"; + + /* + // TODO: uncomment once added + public override void OnDeath( Container c ) + { + base.OnDeath( c ); + + if (Utility.RandomDouble() < 0.025) + { + switch ( Utility.Random( 2 ) ) + { + case 0: c.DropItem( new HunterLegs() ); break; + case 1: c.DropItem( new MalekisHonor() ); break; + } + } + + if (Utility.RandomDouble() < 0.1) + c.DropItem( new ParrotItem() ); + } + */ + + public override bool GivesMLMinorArtifact => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 3); + } + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.MortalStrike; + + 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 GivesMLMinorArtifact => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 3); - } - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.MortalStrike; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Mammal/Melee/HellHound.cs b/Projects/UOContent/Mobiles/Monsters/Mammal/Melee/HellHound.cs index abfe298f5..d98775042 100644 --- a/Projects/UOContent/Mobiles/Monsters/Mammal/Melee/HellHound.cs +++ b/Projects/UOContent/Mobiles/Monsters/Mammal/Melee/HellHound.cs @@ -2,70 +2,70 @@ using Server.Items; namespace Server.Mobiles { - public class HellHound : BaseCreature - { - [Constructible] - public HellHound() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class HellHound : BaseCreature { - Body = 98; - BaseSoundID = 229; + [Constructible] + public HellHound() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 98; + BaseSoundID = 229; - SetStr(102, 150); - SetDex(81, 105); - SetInt(36, 60); + SetStr(102, 150); + SetDex(81, 105); + SetInt(36, 60); - SetHits(66, 125); + SetHits(66, 125); - SetDamage(11, 17); + SetDamage(11, 17); - SetDamageType(ResistanceType.Physical, 20); - SetDamageType(ResistanceType.Fire, 80); + SetDamageType(ResistanceType.Physical, 20); + SetDamageType(ResistanceType.Fire, 80); - SetResistance(ResistanceType.Physical, 25, 35); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Poison, 10, 20); - SetResistance(ResistanceType.Energy, 10, 20); + SetResistance(ResistanceType.Physical, 25, 35); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Energy, 10, 20); - Fame = 3400; - Karma = -3400; + Fame = 3400; + Karma = -3400; - VirtualArmor = 30; + VirtualArmor = 30; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 85.5; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 85.5; - PackItem(new SulfurousAsh(5)); + PackItem(new SulfurousAsh(5)); + } + + public HellHound(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a hell hound corpse"; + public override string DefaultName => "a hell hound"; + + public override bool HasBreath => true; // fire breath enabled + public override int Meat => 1; + public override FoodType FavoriteFood => FoodType.Meat; + public override PackInstinct PackInstinct => PackInstinct.Canine; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Meager); + } + + 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(); + } } - - public HellHound(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a hell hound corpse"; - public override string DefaultName => "a hell hound"; - - public override bool HasBreath => true; // fire breath enabled - public override int Meat => 1; - public override FoodType FavoriteFood => FoodType.Meat; - public override PackInstinct PackInstinct => PackInstinct.Canine; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Mammal/Melee/VorpalBunny.cs b/Projects/UOContent/Mobiles/Monsters/Mammal/Melee/VorpalBunny.cs index 2a15dd595..6369c875c 100644 --- a/Projects/UOContent/Mobiles/Monsters/Mammal/Melee/VorpalBunny.cs +++ b/Projects/UOContent/Mobiles/Monsters/Mammal/Melee/VorpalBunny.cs @@ -3,135 +3,135 @@ using Server.Items; namespace Server.Mobiles { - public class VorpalBunny : BaseCreature - { - [Constructible] - public VorpalBunny() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class VorpalBunny : BaseCreature { - Body = 205; - Hue = 0x480; + [Constructible] + public VorpalBunny() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 205; + Hue = 0x480; - SetStr(15); - SetDex(2000); - SetInt(1000); + SetStr(15); + SetDex(2000); + SetInt(1000); - SetHits(2000); - SetStam(500); - SetMana(0); + SetHits(2000); + SetStam(500); + SetMana(0); - SetDamage(1); + SetDamage(1); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetSkill(SkillName.MagicResist, 200.0); - SetSkill(SkillName.Tactics, 5.0); - SetSkill(SkillName.Wrestling, 5.0); + SetSkill(SkillName.MagicResist, 200.0); + SetSkill(SkillName.Tactics, 5.0); + SetSkill(SkillName.Wrestling, 5.0); - Fame = 1000; - Karma = 0; + Fame = 1000; + Karma = 0; - VirtualArmor = 4; + VirtualArmor = 4; - int carrots = Utility.RandomMinMax(5, 10); - PackItem(new Carrot(carrots)); + var carrots = Utility.RandomMinMax(5, 10); + PackItem(new Carrot(carrots)); - if (Utility.Random(5) == 0) - PackItem(new BrightlyColoredEggs()); + if (Utility.Random(5) == 0) + PackItem(new BrightlyColoredEggs()); - PackStatue(); + PackStatue(); - DelayBeginTunnel(); + DelayBeginTunnel(); + } + + public VorpalBunny(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a vorpal bunny corpse"; + public override string DefaultName => "a vorpal bunny"; + + public override int Meat => 1; + public override int Hides => 1; + public override bool BardImmune => !Core.AOS; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.Rich, 2); + } + + public virtual void DelayBeginTunnel() + { + Timer.DelayCall(TimeSpan.FromMinutes(3.0), BeginTunnel); + } + + public virtual void BeginTunnel() + { + if (Deleted) + return; + + new BunnyHole().MoveToWorld(Location, Map); + + Frozen = true; + Say("* The bunny begins to dig a tunnel back to its underground lair *"); + PlaySound(0x247); + + Timer.DelayCall(TimeSpan.FromSeconds(5.0), Delete); + } + + public override int GetAttackSound() => 0xC9; + + public override int GetHurtSound() => 0xCA; + + public override int GetDeathSound() => 0xCB; + + 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(); + + DelayBeginTunnel(); + } + + public class BunnyHole : Item + { + public BunnyHole() : base(0x913) + { + Movable = false; + Hue = 1; + + Timer.DelayCall(TimeSpan.FromSeconds(40.0), Delete); + } + + public BunnyHole(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a mysterious rabbit hole"; + + 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(); + + Delete(); + } + } } - - public VorpalBunny(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a vorpal bunny corpse"; - public override string DefaultName => "a vorpal bunny"; - - public override int Meat => 1; - public override int Hides => 1; - public override bool BardImmune => !Core.AOS; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.Rich, 2); - } - - public virtual void DelayBeginTunnel() - { - Timer.DelayCall(TimeSpan.FromMinutes(3.0), BeginTunnel); - } - - public virtual void BeginTunnel() - { - if (Deleted) - return; - - new BunnyHole().MoveToWorld(Location, Map); - - Frozen = true; - Say("* The bunny begins to dig a tunnel back to its underground lair *"); - PlaySound(0x247); - - Timer.DelayCall(TimeSpan.FromSeconds(5.0), Delete); - } - - public override int GetAttackSound() => 0xC9; - - public override int GetHurtSound() => 0xCA; - - public override int GetDeathSound() => 0xCB; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - DelayBeginTunnel(); - } - - public class BunnyHole : Item - { - public BunnyHole() : base(0x913) - { - Movable = false; - Hue = 1; - - Timer.DelayCall(TimeSpan.FromSeconds(40.0), Delete); - } - - public BunnyHole(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a mysterious rabbit hole"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Delete(); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Misc/Magic/DarkWisp.cs b/Projects/UOContent/Mobiles/Monsters/Misc/Magic/DarkWisp.cs index 8689aa85e..0bbb5ee34 100644 --- a/Projects/UOContent/Mobiles/Monsters/Misc/Magic/DarkWisp.cs +++ b/Projects/UOContent/Mobiles/Monsters/Misc/Magic/DarkWisp.cs @@ -5,77 +5,77 @@ using Server.Misc; namespace Server.Mobiles { - public class DarkWisp : BaseCreature - { - [Constructible] - public DarkWisp() : base(AIType.AI_Mage, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class DarkWisp : BaseCreature { - Body = 165; - BaseSoundID = 466; + [Constructible] + public DarkWisp() : base(AIType.AI_Mage, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 165; + BaseSoundID = 466; - SetStr(196, 225); - SetDex(196, 225); - SetInt(196, 225); + SetStr(196, 225); + SetDex(196, 225); + SetInt(196, 225); - SetHits(118, 135); + SetHits(118, 135); - SetDamage(17, 18); + SetDamage(17, 18); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Energy, 50); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Energy, 50); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 20, 40); - SetResistance(ResistanceType.Cold, 10, 30); - SetResistance(ResistanceType.Poison, 5, 10); - SetResistance(ResistanceType.Energy, 50, 70); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 20, 40); + SetResistance(ResistanceType.Cold, 10, 30); + SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Energy, 50, 70); - SetSkill(SkillName.EvalInt, 80.0); - SetSkill(SkillName.Magery, 80.0); - SetSkill(SkillName.MagicResist, 80.0); - SetSkill(SkillName.Tactics, 80.0); - SetSkill(SkillName.Wrestling, 80.0); + SetSkill(SkillName.EvalInt, 80.0); + SetSkill(SkillName.Magery, 80.0); + SetSkill(SkillName.MagicResist, 80.0); + SetSkill(SkillName.Tactics, 80.0); + SetSkill(SkillName.Wrestling, 80.0); - Fame = 4000; - Karma = -4000; + Fame = 4000; + Karma = -4000; - VirtualArmor = 40; + VirtualArmor = 40; - AddItem(new LightSource()); + AddItem(new LightSource()); + } + + public DarkWisp(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a wisp corpse"; + public override InhumanSpeech SpeechType => InhumanSpeech.Wisp; + + public override Ethic EthicAllegiance => Ethic.Evil; + + public override TimeSpan ReacquireDelay => TimeSpan.FromSeconds(1.0); + + public override string DefaultName => "a wisp"; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.Average); + } + + 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(); + } } - - public DarkWisp(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a wisp corpse"; - public override InhumanSpeech SpeechType => InhumanSpeech.Wisp; - - public override Ethic EthicAllegiance => Ethic.Evil; - - public override TimeSpan ReacquireDelay => TimeSpan.FromSeconds(1.0); - - public override string DefaultName => "a wisp"; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.Average); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Misc/Magic/EtherealWarrior.cs b/Projects/UOContent/Mobiles/Monsters/Misc/Magic/EtherealWarrior.cs index 6fa75c887..5478daf09 100644 --- a/Projects/UOContent/Mobiles/Monsters/Misc/Magic/EtherealWarrior.cs +++ b/Projects/UOContent/Mobiles/Monsters/Misc/Magic/EtherealWarrior.cs @@ -3,124 +3,124 @@ using Server.Gumps; namespace Server.Mobiles { - public class EtherealWarrior : BaseCreature - { - private static readonly TimeSpan ResurrectDelay = TimeSpan.FromSeconds(2.0); - - private DateTime m_NextResurrect; - - [Constructible] - public EtherealWarrior() : base(AIType.AI_Mage, FightMode.Evil, 10, 1, 0.2, 0.4) + public class EtherealWarrior : BaseCreature { - Name = NameList.RandomName("ethereal warrior"); - Body = 123; + private static readonly TimeSpan ResurrectDelay = TimeSpan.FromSeconds(2.0); - SetStr(586, 785); - SetDex(177, 255); - SetInt(351, 450); + private DateTime m_NextResurrect; - SetHits(352, 471); - - SetDamage(13, 19); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 80, 90); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 40, 50); - - SetSkill(SkillName.Anatomy, 50.1, 75.0); - SetSkill(SkillName.EvalInt, 90.1, 100.0); - SetSkill(SkillName.Magery, 99.1, 100.0); - SetSkill(SkillName.Meditation, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 90.1, 100.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); - SetSkill(SkillName.Wrestling, 97.6, 100.0); - - Fame = 7000; - Karma = 7000; - - VirtualArmor = 120; - } - - public EtherealWarrior(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ethereal warrior corpse"; - public override bool InitialInnocent => true; - - public override int TreasureMapLevel => Core.AOS ? 5 : 0; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override int Feathers => 100; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich, 3); - AddLoot(LootPack.Gems); - } - - public override void OnMovement(Mobile from, Point3D oldLocation) - { - if (!from.Alive && from is PlayerMobile) - if (!from.Frozen && DateTime.UtcNow >= m_NextResurrect && InRange(from, 4) && !InRange(oldLocation, 4) && - InLOS(from)) + [Constructible] + public EtherealWarrior() : base(AIType.AI_Mage, FightMode.Evil, 10, 1, 0.2, 0.4) { - m_NextResurrect = DateTime.UtcNow + ResurrectDelay; - if (!from.Criminal && from.Kills < 5 && from.Karma > 0) - if (from.Map?.CanFit(from.Location, 16, false, false) == true) - { - Direction = GetDirectionTo(from); - from.PlaySound(0x1F2); - from.FixedEffect(0x376A, 10, 16); - from.CloseGump(); - from.SendGump(new ResurrectGump(from, ResurrectMessage.Healer)); - } + Name = NameList.RandomName("ethereal warrior"); + Body = 123; + + SetStr(586, 785); + SetDex(177, 255); + SetInt(351, 450); + + SetHits(352, 471); + + SetDamage(13, 19); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 80, 90); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 40, 50); + + SetSkill(SkillName.Anatomy, 50.1, 75.0); + SetSkill(SkillName.EvalInt, 90.1, 100.0); + SetSkill(SkillName.Magery, 99.1, 100.0); + SetSkill(SkillName.Meditation, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 90.1, 100.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.Wrestling, 97.6, 100.0); + + Fame = 7000; + Karma = 7000; + + VirtualArmor = 120; + } + + public EtherealWarrior(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ethereal warrior corpse"; + public override bool InitialInnocent => true; + + public override int TreasureMapLevel => Core.AOS ? 5 : 0; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override int Feathers => 100; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich, 3); + AddLoot(LootPack.Gems); + } + + public override void OnMovement(Mobile from, Point3D oldLocation) + { + if (!from.Alive && from is PlayerMobile) + if (!from.Frozen && DateTime.UtcNow >= m_NextResurrect && InRange(from, 4) && !InRange(oldLocation, 4) && + InLOS(from)) + { + m_NextResurrect = DateTime.UtcNow + ResurrectDelay; + if (!from.Criminal && from.Kills < 5 && from.Karma > 0) + if (from.Map?.CanFit(from.Location, 16, false, false) == true) + { + Direction = GetDirectionTo(from); + from.PlaySound(0x1F2); + from.FixedEffect(0x376A, 10, 16); + from.CloseGump(); + from.SendGump(new ResurrectGump(from, ResurrectMessage.Healer)); + } + } + } + + public override int GetAngerSound() => 0x2F8; + + public override int GetIdleSound() => 0x2F8; + + public override int GetAttackSound() => Utility.Random(0x2F5, 2); + + public override int GetHurtSound() => 0x2F9; + + public override int GetDeathSound() => 0x2F7; + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + defender.Damage(Utility.Random(10, 10), this); + defender.Stam -= Utility.Random(10, 10); + defender.Mana -= Utility.Random(10, 10); + } + + public override void OnGotMeleeAttack(Mobile attacker) + { + base.OnGotMeleeAttack(attacker); + + attacker.Damage(Utility.Random(10, 10), this); + attacker.Stam -= Utility.Random(10, 10); + attacker.Mana -= Utility.Random(10, 10); + } + + 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(); } } - - public override int GetAngerSound() => 0x2F8; - - public override int GetIdleSound() => 0x2F8; - - public override int GetAttackSound() => Utility.Random(0x2F5, 2); - - public override int GetHurtSound() => 0x2F9; - - public override int GetDeathSound() => 0x2F7; - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - defender.Damage(Utility.Random(10, 10), this); - defender.Stam -= Utility.Random(10, 10); - defender.Mana -= Utility.Random(10, 10); - } - - public override void OnGotMeleeAttack(Mobile attacker) - { - base.OnGotMeleeAttack(attacker); - - attacker.Damage(Utility.Random(10, 10), this); - attacker.Stam -= Utility.Random(10, 10); - attacker.Mana -= Utility.Random(10, 10); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Misc/Magic/Pixie.cs b/Projects/UOContent/Mobiles/Monsters/Misc/Magic/Pixie.cs index 8c3cc26dc..5a2e2a851 100644 --- a/Projects/UOContent/Mobiles/Monsters/Misc/Magic/Pixie.cs +++ b/Projects/UOContent/Mobiles/Monsters/Misc/Magic/Pixie.cs @@ -2,84 +2,84 @@ using Server.Items; namespace Server.Mobiles { - public class Pixie : BaseCreature - { - [Constructible] - public Pixie() : base(AIType.AI_Mage, FightMode.Evil, 10, 1, 0.2, 0.4) + public class Pixie : BaseCreature { - Name = NameList.RandomName("pixie"); - Body = 128; - BaseSoundID = 0x467; + [Constructible] + public Pixie() : base(AIType.AI_Mage, FightMode.Evil, 10, 1, 0.2, 0.4) + { + Name = NameList.RandomName("pixie"); + Body = 128; + BaseSoundID = 0x467; - SetStr(21, 30); - SetDex(301, 400); - SetInt(201, 250); + SetStr(21, 30); + SetDex(301, 400); + SetInt(201, 250); - SetHits(13, 18); + SetHits(13, 18); - SetDamage(9, 15); + SetDamage(9, 15); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 80, 90); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 80, 90); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.EvalInt, 90.1, 100.0); - SetSkill(SkillName.Magery, 90.1, 100.0); - SetSkill(SkillName.Meditation, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 100.5, 150.0); - SetSkill(SkillName.Tactics, 10.1, 20.0); - SetSkill(SkillName.Wrestling, 10.1, 12.5); + SetSkill(SkillName.EvalInt, 90.1, 100.0); + SetSkill(SkillName.Magery, 90.1, 100.0); + SetSkill(SkillName.Meditation, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 100.5, 150.0); + SetSkill(SkillName.Tactics, 10.1, 20.0); + SetSkill(SkillName.Wrestling, 10.1, 12.5); - Fame = 7000; - Karma = 7000; + Fame = 7000; + Karma = 7000; - VirtualArmor = 100; - if (Utility.RandomDouble() < 0.02) - PackStatue(); + VirtualArmor = 100; + if (Utility.RandomDouble() < 0.02) + PackStatue(); + } + + public Pixie(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a pixie corpse"; + public override bool InitialInnocent => true; + + public override HideType HideType => HideType.Spined; + public override int Hides => 5; + public override int Meat => 1; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override void GenerateLoot() + { + AddLoot(LootPack.LowScrolls); + AddLoot(LootPack.Gems, 2); + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + if (Utility.RandomDouble() < 0.35) + c.DropItem(new PixieLeg()); + } + + 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(); + } } - - public Pixie(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a pixie corpse"; - public override bool InitialInnocent => true; - - public override HideType HideType => HideType.Spined; - public override int Hides => 5; - public override int Meat => 1; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override void GenerateLoot() - { - AddLoot(LootPack.LowScrolls); - AddLoot(LootPack.Gems, 2); - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - if (Utility.RandomDouble() < 0.35) - c.DropItem(new PixieLeg()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Misc/Magic/ShadowWisp.cs b/Projects/UOContent/Mobiles/Monsters/Misc/Magic/ShadowWisp.cs index 8c0597816..451acc6d8 100644 --- a/Projects/UOContent/Mobiles/Monsters/Misc/Magic/ShadowWisp.cs +++ b/Projects/UOContent/Mobiles/Monsters/Misc/Magic/ShadowWisp.cs @@ -2,75 +2,75 @@ using Server.Items; namespace Server.Mobiles { - public class ShadowWisp : BaseCreature - { - [Constructible] - public ShadowWisp() : base(AIType.AI_Mage, FightMode.Aggressor, 10, 1, 0.3, 0.6) + public class ShadowWisp : BaseCreature { - Body = 165; - BaseSoundID = 466; - - SetStr(16, 40); - SetDex(16, 45); - SetInt(11, 25); - - SetHits(10, 24); - - SetDamage(5, 10); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 15, 20); - SetResistance(ResistanceType.Fire, 5, 10); - SetResistance(ResistanceType.Poison, 5, 10); - SetResistance(ResistanceType.Energy, 15, 20); - - SetSkill(SkillName.EvalInt, 40.0); - SetSkill(SkillName.Magery, 50.0); - SetSkill(SkillName.Meditation, 40.0); - SetSkill(SkillName.MagicResist, 10.0); - SetSkill(SkillName.Tactics, 0.1, 15.0); - SetSkill(SkillName.Wrestling, 25.1, 40.0); - - Fame = 500; - - VirtualArmor = 18; - - AddItem(new LightSource()); - - PackItem( - Utility.Random(10) switch + [Constructible] + public ShadowWisp() : base(AIType.AI_Mage, FightMode.Aggressor, 10, 1, 0.3, 0.6) { - 0 => new LeftArm(), - 1 => new RightArm(), - 2 => new Torso(), - 3 => new Bone(), - 4 => new RibCage(), - 5 => new RibCage(), - _ => new BonePile() // 6-9 + Body = 165; + BaseSoundID = 466; + + SetStr(16, 40); + SetDex(16, 45); + SetInt(11, 25); + + SetHits(10, 24); + + SetDamage(5, 10); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 15, 20); + SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Energy, 15, 20); + + SetSkill(SkillName.EvalInt, 40.0); + SetSkill(SkillName.Magery, 50.0); + SetSkill(SkillName.Meditation, 40.0); + SetSkill(SkillName.MagicResist, 10.0); + SetSkill(SkillName.Tactics, 0.1, 15.0); + SetSkill(SkillName.Wrestling, 25.1, 40.0); + + Fame = 500; + + VirtualArmor = 18; + + AddItem(new LightSource()); + + PackItem( + Utility.Random(10) switch + { + 0 => new LeftArm(), + 1 => new RightArm(), + 2 => new Torso(), + 3 => new Bone(), + 4 => new RibCage(), + 5 => new RibCage(), + _ => new BonePile() // 6-9 + } + ); + } + + public ShadowWisp(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a wisp corpse"; + public override string DefaultName => "a shadow wisp"; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + 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(); } - ); } - - public ShadowWisp(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a wisp corpse"; - public override string DefaultName => "a shadow wisp"; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Misc/Magic/Wisp.cs b/Projects/UOContent/Mobiles/Monsters/Misc/Magic/Wisp.cs index 9cf13f280..e66eb3186 100644 --- a/Projects/UOContent/Mobiles/Monsters/Misc/Magic/Wisp.cs +++ b/Projects/UOContent/Mobiles/Monsters/Misc/Magic/Wisp.cs @@ -7,80 +7,80 @@ using Server.Misc; namespace Server.Mobiles { - public class Wisp : BaseCreature - { - [Constructible] - public Wisp() : base(AIType.AI_Mage, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Wisp : BaseCreature { - Body = 58; - BaseSoundID = 466; + [Constructible] + public Wisp() : base(AIType.AI_Mage, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Body = 58; + BaseSoundID = 466; - SetStr(196, 225); - SetDex(196, 225); - SetInt(196, 225); + SetStr(196, 225); + SetDex(196, 225); + SetInt(196, 225); - SetHits(118, 135); + SetHits(118, 135); - SetDamage(17, 18); + SetDamage(17, 18); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Energy, 50); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Energy, 50); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 20, 40); - SetResistance(ResistanceType.Cold, 10, 30); - SetResistance(ResistanceType.Poison, 5, 10); - SetResistance(ResistanceType.Energy, 50, 70); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 20, 40); + SetResistance(ResistanceType.Cold, 10, 30); + SetResistance(ResistanceType.Poison, 5, 10); + SetResistance(ResistanceType.Energy, 50, 70); - SetSkill(SkillName.EvalInt, 80.0); - SetSkill(SkillName.Magery, 80.0); - SetSkill(SkillName.MagicResist, 80.0); - SetSkill(SkillName.Tactics, 80.0); - SetSkill(SkillName.Wrestling, 80.0); + SetSkill(SkillName.EvalInt, 80.0); + SetSkill(SkillName.Magery, 80.0); + SetSkill(SkillName.MagicResist, 80.0); + SetSkill(SkillName.Tactics, 80.0); + SetSkill(SkillName.Wrestling, 80.0); - Fame = 4000; - Karma = 0; + Fame = 4000; + Karma = 0; - VirtualArmor = 40; + VirtualArmor = 40; - if (Core.ML && Utility.RandomDouble() < .33) - PackItem(Seed.RandomPeculiarSeed(3)); + if (Core.ML && Utility.RandomDouble() < .33) + PackItem(Seed.RandomPeculiarSeed(3)); - AddItem(new LightSource()); + AddItem(new LightSource()); + } + + public Wisp(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a wisp corpse"; + public override InhumanSpeech SpeechType => InhumanSpeech.Wisp; + + public override Faction FactionAllegiance => CouncilOfMages.Instance; + public override Ethic EthicAllegiance => Ethic.Hero; + + public override TimeSpan ReacquireDelay => TimeSpan.FromSeconds(1.0); + + public override string DefaultName => "a wisp"; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.Average); + } + + 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(); + } } - - public Wisp(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a wisp corpse"; - public override InhumanSpeech SpeechType => InhumanSpeech.Wisp; - - public override Faction FactionAllegiance => CouncilOfMages.Instance; - public override Ethic EthicAllegiance => Ethic.Hero; - - public override TimeSpan ReacquireDelay => TimeSpan.FromSeconds(1.0); - - public override string DefaultName => "a wisp"; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.Average); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Misc/Melee/AnimatedWeapon.cs b/Projects/UOContent/Mobiles/Monsters/Misc/Melee/AnimatedWeapon.cs index f8446d871..091b1c3db 100644 --- a/Projects/UOContent/Mobiles/Monsters/Misc/Melee/AnimatedWeapon.cs +++ b/Projects/UOContent/Mobiles/Monsters/Misc/Melee/AnimatedWeapon.cs @@ -2,98 +2,99 @@ namespace Server.Mobiles { - public class AnimatedWeapon : BaseCreature - { - [Constructible] - public AnimatedWeapon(Mobile caster, int level) - : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.3, 0.6) + public class AnimatedWeapon : BaseCreature { - Body = 692; + [Constructible] + public AnimatedWeapon(Mobile caster, int level) + : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.3, 0.6) + { + Body = 692; - SetStr(10 + level); - SetDex(10 + level); - SetInt(10); + SetStr(10 + level); + SetDex(10 + level); + SetInt(10); - SetHits(20 + level * 3 / 2); - SetStam(10 + level); - SetMana(0); + SetHits(20 + level * 3 / 2); + SetStam(10 + level); + SetMana(0); - if (level >= 120) - SetDamage(14, 18); - else if (level >= 105) - SetDamage(13, 17); - else if (level >= 90) - SetDamage(12, 15); - else if (level >= 75) - SetDamage(11, 14); - else if (level >= 60) - SetDamage(10, 12); - else if (level >= 45) - SetDamage(9, 11); - else if (level >= 30) - SetDamage(8, 9); - else - SetDamage(7, 8); + if (level >= 120) + SetDamage(14, 18); + else if (level >= 105) + SetDamage(13, 17); + else if (level >= 90) + SetDamage(12, 15); + else if (level >= 75) + SetDamage(11, 14); + else if (level >= 60) + SetDamage(10, 12); + else if (level >= 45) + SetDamage(9, 11); + else if (level >= 30) + SetDamage(8, 9); + else + SetDamage(7, 8); - SetDamageType(ResistanceType.Physical, 60); - SetDamageType(ResistanceType.Poison, 20); - SetDamageType(ResistanceType.Energy, 20); + SetDamageType(ResistanceType.Physical, 60); + SetDamageType(ResistanceType.Poison, 20); + SetDamageType(ResistanceType.Energy, 20); - SetResistance(ResistanceType.Physical, 40, 50); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 100); - SetResistance(ResistanceType.Energy, 20, 30); + SetResistance(ResistanceType.Physical, 40, 50); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 100); + SetResistance(ResistanceType.Energy, 20, 30); - SetSkill(SkillName.MagicResist, level); - SetSkill(SkillName.Wrestling, level); - SetSkill(SkillName.Anatomy, caster.Skills.Anatomy.Value / 2); - SetSkill(SkillName.Tactics, caster.Skills.Tactics.Value / 2); + SetSkill(SkillName.MagicResist, level); + SetSkill(SkillName.Wrestling, level); + SetSkill(SkillName.Anatomy, caster.Skills.Anatomy.Value / 2); + SetSkill(SkillName.Tactics, caster.Skills.Tactics.Value / 2); - Fame = 0; - Karma = 0; + Fame = 0; + Karma = 0; - ControlSlots = 4; + ControlSlots = 4; + } + + public AnimatedWeapon(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "an animated weapon corpse"; + public override bool DeleteCorpseOnDeath => true; + public override bool IsHouseSummonable => true; + + public override double DispelDifficulty => 0.0; + public override double DispelFocus => 20.0; + + public override string DefaultName => "an animated weapon"; + + public override bool BleedImmune => true; + public override Poison PoisonImmune => Poison.Lethal; + + public override double GetFightModeRanking(Mobile m, FightMode acqType, bool bPlayerOnly) => + m.Str / Math.Max(GetDistanceToSqrt(m), 1.0); + + public override int GetAngerSound() => 0x23A; + + public override int GetAttackSound() => 0x3B8; + + public override int GetHurtSound() => 0x23A; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + /*int version = */ + reader.ReadInt(); + } } - - public AnimatedWeapon(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "an animated weapon corpse"; - public override bool DeleteCorpseOnDeath => true; - public override bool IsHouseSummonable => true; - - public override double DispelDifficulty => 0.0; - public override double DispelFocus => 20.0; - - public override string DefaultName => "an animated weapon"; - - public override bool BleedImmune => true; - public override Poison PoisonImmune => Poison.Lethal; - - public override double GetFightModeRanking(Mobile m, FightMode acqType, bool bPlayerOnly) => m.Str / Math.Max(GetDistanceToSqrt(m), 1.0); - - public override int GetAngerSound() => 0x23A; - - public override int GetAttackSound() => 0x3B8; - - public override int GetHurtSound() => 0x23A; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - /*int version = */ - reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Misc/Melee/BladeSpirits.cs b/Projects/UOContent/Mobiles/Monsters/Misc/Melee/BladeSpirits.cs index 1e934b075..d0c70f67f 100644 --- a/Projects/UOContent/Mobiles/Monsters/Misc/Melee/BladeSpirits.cs +++ b/Projects/UOContent/Mobiles/Monsters/Misc/Melee/BladeSpirits.cs @@ -1,105 +1,106 @@ using System; -using System.Collections.Generic; using System.Linq; namespace Server.Mobiles { - public class BladeSpirits : BaseCreature - { - [Constructible] - public BladeSpirits() - : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.3, 0.6) + public class BladeSpirits : BaseCreature { - Body = 574; - - SetStr(150); - SetDex(150); - SetInt(100); - - SetHits(Core.SE ? 160 : 80); - SetStam(250); - SetMana(0); - - SetDamage(10, 14); - - SetDamageType(ResistanceType.Physical, 60); - SetDamageType(ResistanceType.Poison, 20); - SetDamageType(ResistanceType.Energy, 20); - - SetResistance(ResistanceType.Physical, 30, 40); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 100); - SetResistance(ResistanceType.Energy, 20, 30); - - SetSkill(SkillName.MagicResist, 70.0); - SetSkill(SkillName.Tactics, 90.0); - SetSkill(SkillName.Wrestling, 90.0); - - Fame = 0; - Karma = 0; - - VirtualArmor = 40; - ControlSlots = Core.SE ? 2 : 1; - } - - public BladeSpirits(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a blade spirit corpse"; - public override bool DeleteCorpseOnDeath => Core.AOS; - public override bool IsHouseSummonable => true; - - public override double DispelDifficulty => 0.0; - public override double DispelFocus => 20.0; - - public override string DefaultName => "a blade spirit"; - - public override bool BleedImmune => true; - public override Poison PoisonImmune => Poison.Lethal; - - public override double GetFightModeRanking(Mobile m, FightMode acqType, bool bPlayerOnly) => (m.Str + m.Skills.Tactics.Value) / Math.Max(GetDistanceToSqrt(m), 1.0); - - public override int GetAngerSound() => 0x23A; - - public override int GetAttackSound() => 0x3B8; - - public override int GetHurtSound() => 0x23A; - - public override void OnThink() - { - if (Core.SE && Summoned) - { - IPooledEnumerable eable = GetMobilesInRange(5); - List spiritsOrVortexes = eable - .Where(m => (m is EnergyVortex || m is BladeSpirits) && ((BaseCreature)m).Summoned).ToList(); - - eable.Free(); - - while (spiritsOrVortexes.Count > 6) + [Constructible] + public BladeSpirits() + : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.3, 0.6) { - var random = spiritsOrVortexes.RandomElement(); - Dispel(random); - spiritsOrVortexes.Remove(random); + Body = 574; + + SetStr(150); + SetDex(150); + SetInt(100); + + SetHits(Core.SE ? 160 : 80); + SetStam(250); + SetMana(0); + + SetDamage(10, 14); + + SetDamageType(ResistanceType.Physical, 60); + SetDamageType(ResistanceType.Poison, 20); + SetDamageType(ResistanceType.Energy, 20); + + SetResistance(ResistanceType.Physical, 30, 40); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 100); + SetResistance(ResistanceType.Energy, 20, 30); + + SetSkill(SkillName.MagicResist, 70.0); + SetSkill(SkillName.Tactics, 90.0); + SetSkill(SkillName.Wrestling, 90.0); + + Fame = 0; + Karma = 0; + + VirtualArmor = 40; + ControlSlots = Core.SE ? 2 : 1; } - } - base.OnThink(); + public BladeSpirits(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a blade spirit corpse"; + public override bool DeleteCorpseOnDeath => Core.AOS; + public override bool IsHouseSummonable => true; + + public override double DispelDifficulty => 0.0; + public override double DispelFocus => 20.0; + + public override string DefaultName => "a blade spirit"; + + public override bool BleedImmune => true; + public override Poison PoisonImmune => Poison.Lethal; + + public override double GetFightModeRanking(Mobile m, FightMode acqType, bool bPlayerOnly) => + (m.Str + m.Skills.Tactics.Value) / Math.Max(GetDistanceToSqrt(m), 1.0); + + public override int GetAngerSound() => 0x23A; + + public override int GetAttackSound() => 0x3B8; + + public override int GetHurtSound() => 0x23A; + + public override void OnThink() + { + if (Core.SE && Summoned) + { + var eable = GetMobilesInRange(5); + var spiritsOrVortexes = eable + .Where(m => (m is EnergyVortex || m is BladeSpirits) && ((BaseCreature)m).Summoned) + .ToList(); + + eable.Free(); + + while (spiritsOrVortexes.Count > 6) + { + var random = spiritsOrVortexes.RandomElement(); + Dispel(random); + spiritsOrVortexes.Remove(random); + } + } + + base.OnThink(); + } + + 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 Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Misc/Melee/Centaur.cs b/Projects/UOContent/Mobiles/Monsters/Misc/Melee/Centaur.cs index 1f9383847..9024dcc7a 100644 --- a/Projects/UOContent/Mobiles/Monsters/Misc/Melee/Centaur.cs +++ b/Projects/UOContent/Mobiles/Monsters/Misc/Melee/Centaur.cs @@ -2,78 +2,84 @@ using Server.Items; namespace Server.Mobiles { - public class Centaur : BaseCreature - { - [Constructible] - public Centaur() : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Centaur : BaseCreature { - Name = NameList.RandomName("centaur"); - Body = 101; - BaseSoundID = 679; + [Constructible] + public Centaur() : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Name = NameList.RandomName("centaur"); + Body = 101; + BaseSoundID = 679; - SetStr(202, 300); - SetDex(104, 260); - SetInt(91, 100); + SetStr(202, 300); + SetDex(104, 260); + SetInt(91, 100); - SetHits(130, 172); + SetHits(130, 172); - SetDamage(13, 24); + SetDamage(13, 24); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 35, 45); - SetResistance(ResistanceType.Cold, 25, 35); - SetResistance(ResistanceType.Poison, 45, 55); - SetResistance(ResistanceType.Energy, 35, 45); + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 35, 45); + SetResistance(ResistanceType.Cold, 25, 35); + SetResistance(ResistanceType.Poison, 45, 55); + SetResistance(ResistanceType.Energy, 35, 45); - SetSkill(SkillName.Anatomy, 95.1, 115.0); - SetSkill(SkillName.Archery, 95.1, 100.0); - SetSkill(SkillName.MagicResist, 50.3, 80.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); - SetSkill(SkillName.Wrestling, 95.1, 100.0); + SetSkill(SkillName.Anatomy, 95.1, 115.0); + SetSkill(SkillName.Archery, 95.1, 100.0); + SetSkill(SkillName.MagicResist, 50.3, 80.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.Wrestling, 95.1, 100.0); - Fame = 6500; - Karma = 0; + Fame = 6500; + Karma = 0; - VirtualArmor = 50; - AddItem(new Bow()); - PackItem(new Arrow(Utility.RandomMinMax(80, - 90))); // OSI it is different: in a sub backpack, this is probably just a limitation of their engine + VirtualArmor = 50; + AddItem(new Bow()); + PackItem( + new Arrow( + Utility.RandomMinMax( + 80, + 90 + ) + ) + ); // OSI it is different: in a sub backpack, this is probably just a limitation of their engine + } + + public Centaur(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a centaur corpse"; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override int Meat => 1; + public override int Hides => 8; + public override HideType HideType => HideType.Spined; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.Average); + AddLoot(LootPack.Gems); + } + + 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 (BaseSoundID == 678) + BaseSoundID = 679; + } } - - public Centaur(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a centaur corpse"; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override int Meat => 1; - public override int Hides => 8; - public override HideType HideType => HideType.Spined; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.Average); - AddLoot(LootPack.Gems); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (BaseSoundID == 678) - BaseSoundID = 679; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Misc/Melee/EnergyVortex.cs b/Projects/UOContent/Mobiles/Monsters/Misc/Melee/EnergyVortex.cs index 2d9758670..b22b19534 100644 --- a/Projects/UOContent/Mobiles/Monsters/Misc/Melee/EnergyVortex.cs +++ b/Projects/UOContent/Mobiles/Monsters/Misc/Melee/EnergyVortex.cs @@ -1,115 +1,116 @@ using System; -using System.Collections.Generic; using System.Linq; namespace Server.Mobiles { - public class EnergyVortex : BaseCreature - { - [Constructible] - public EnergyVortex() - : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class EnergyVortex : BaseCreature { - if (Core.SE && Utility.RandomDouble() < 0.002) // Per OSI FoF, it's a 1/500 chance. - { - // Llama vortex! - Body = 0xDC; - Hue = 0x76; - } - else - { - Body = 164; - } - - SetStr(200); - SetDex(200); - SetInt(100); - - SetHits(Core.SE ? 140 : 70); - SetStam(250); - SetMana(0); - - SetDamage(14, 17); - - SetDamageType(ResistanceType.Physical, 0); - SetDamageType(ResistanceType.Energy, 100); - - SetResistance(ResistanceType.Physical, 60, 70); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 90, 100); - - SetSkill(SkillName.MagicResist, 99.9); - SetSkill(SkillName.Tactics, 100.0); - SetSkill(SkillName.Wrestling, 120.0); - - Fame = 0; - Karma = 0; - - VirtualArmor = 40; - ControlSlots = Core.SE ? 2 : 1; - } - - public EnergyVortex(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "an energy vortex corpse"; - public override bool DeleteCorpseOnDeath => Summoned; - public override bool AlwaysMurderer => true; // Or Llama vortices will appear gray. - - public override double DispelDifficulty => 80.0; - public override double DispelFocus => 20.0; - - public override string DefaultName => "an energy vortex"; - - public override bool BleedImmune => true; - public override Poison PoisonImmune => Poison.Lethal; - - public override double GetFightModeRanking(Mobile m, FightMode acqType, bool bPlayerOnly) => (m.Int + m.Skills.Magery.Value) / Math.Max(GetDistanceToSqrt(m), 1.0); - - public override int GetAngerSound() => 0x15; - - public override int GetAttackSound() => 0x28; - - public override void OnThink() - { - if (Core.SE && Summoned) - { - IPooledEnumerable eable = GetMobilesInRange(5); - List spiritsOrVortexes = eable - .Where(m => (m is EnergyVortex || m is BladeSpirits) && ((BaseCreature)m).Summoned).ToList(); - - eable.Free(); - - while (spiritsOrVortexes.Count > 6) + [Constructible] + public EnergyVortex() + : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) { - var random = spiritsOrVortexes.RandomElement(); - Dispel(random); - spiritsOrVortexes.Remove(random); + if (Core.SE && Utility.RandomDouble() < 0.002) // Per OSI FoF, it's a 1/500 chance. + { + // Llama vortex! + Body = 0xDC; + Hue = 0x76; + } + else + { + Body = 164; + } + + SetStr(200); + SetDex(200); + SetInt(100); + + SetHits(Core.SE ? 140 : 70); + SetStam(250); + SetMana(0); + + SetDamage(14, 17); + + SetDamageType(ResistanceType.Physical, 0); + SetDamageType(ResistanceType.Energy, 100); + + SetResistance(ResistanceType.Physical, 60, 70); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 90, 100); + + SetSkill(SkillName.MagicResist, 99.9); + SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.Wrestling, 120.0); + + Fame = 0; + Karma = 0; + + VirtualArmor = 40; + ControlSlots = Core.SE ? 2 : 1; } - } - base.OnThink(); + public EnergyVortex(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "an energy vortex corpse"; + public override bool DeleteCorpseOnDeath => Summoned; + public override bool AlwaysMurderer => true; // Or Llama vortices will appear gray. + + public override double DispelDifficulty => 80.0; + public override double DispelFocus => 20.0; + + public override string DefaultName => "an energy vortex"; + + public override bool BleedImmune => true; + public override Poison PoisonImmune => Poison.Lethal; + + public override double GetFightModeRanking(Mobile m, FightMode acqType, bool bPlayerOnly) => + (m.Int + m.Skills.Magery.Value) / Math.Max(GetDistanceToSqrt(m), 1.0); + + public override int GetAngerSound() => 0x15; + + public override int GetAttackSound() => 0x28; + + public override void OnThink() + { + if (Core.SE && Summoned) + { + var eable = GetMobilesInRange(5); + var spiritsOrVortexes = eable + .Where(m => (m is EnergyVortex || m is BladeSpirits) && ((BaseCreature)m).Summoned) + .ToList(); + + eable.Free(); + + while (spiritsOrVortexes.Count > 6) + { + var random = spiritsOrVortexes.RandomElement(); + Dispel(random); + spiritsOrVortexes.Remove(random); + } + } + + base.OnThink(); + } + + 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 (BaseSoundID == 263) + BaseSoundID = 0; + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (BaseSoundID == 263) - BaseSoundID = 0; - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Misc/Melee/FrostOoze.cs b/Projects/UOContent/Mobiles/Monsters/Misc/Melee/FrostOoze.cs index e606a86e6..b4e4e5577 100644 --- a/Projects/UOContent/Mobiles/Monsters/Misc/Melee/FrostOoze.cs +++ b/Projects/UOContent/Mobiles/Monsters/Misc/Melee/FrostOoze.cs @@ -1,60 +1,60 @@ namespace Server.Mobiles { - public class FrostOoze : BaseCreature - { - [Constructible] - public FrostOoze() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class FrostOoze : BaseCreature { - Body = 94; - BaseSoundID = 456; + [Constructible] + public FrostOoze() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 94; + BaseSoundID = 456; - SetStr(18, 30); - SetDex(16, 21); - SetInt(16, 20); + SetStr(18, 30); + SetDex(16, 21); + SetInt(16, 20); - SetHits(13, 17); + SetHits(13, 17); - SetDamage(3, 9); + SetDamage(3, 9); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 15, 20); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 10, 20); + SetResistance(ResistanceType.Physical, 15, 20); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 10, 20); - SetSkill(SkillName.MagicResist, 5.1, 10.0); - SetSkill(SkillName.Tactics, 19.3, 34.0); - SetSkill(SkillName.Wrestling, 25.3, 40.0); + SetSkill(SkillName.MagicResist, 5.1, 10.0); + SetSkill(SkillName.Tactics, 19.3, 34.0); + SetSkill(SkillName.Wrestling, 25.3, 40.0); - Fame = 450; - Karma = -450; + Fame = 450; + Karma = -450; - VirtualArmor = 38; + VirtualArmor = 38; + } + + public FrostOoze(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a frost ooze corpse"; + public override string DefaultName => "a frost ooze"; + + public override void GenerateLoot() + { + AddLoot(LootPack.Gems, Utility.RandomMinMax(1, 2)); + } + + 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(); + } } - - public FrostOoze(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a frost ooze corpse"; - public override string DefaultName => "a frost ooze"; - - public override void GenerateLoot() - { - AddLoot(LootPack.Gems, Utility.RandomMinMax(1, 2)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Misc/Melee/Golem.cs b/Projects/UOContent/Mobiles/Monsters/Misc/Melee/Golem.cs index ca8a8f222..5354f9826 100644 --- a/Projects/UOContent/Mobiles/Monsters/Misc/Melee/Golem.cs +++ b/Projects/UOContent/Mobiles/Monsters/Misc/Melee/Golem.cs @@ -4,213 +4,217 @@ using Server.Network; namespace Server.Mobiles { - public class Golem : BaseCreature - { - private bool m_Stunning; - - [Constructible] - public Golem(bool summoned = false, double scalar = 1.0) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.4, 0.8) + public class Golem : BaseCreature { - Body = 752; + private bool m_Stunning; - if (summoned) - Hue = 2101; - - SetStr((int)(251 * scalar), (int)(350 * scalar)); - SetDex((int)(76 * scalar), (int)(100 * scalar)); - SetInt((int)(101 * scalar), (int)(150 * scalar)); - - SetHits((int)(151 * scalar), (int)(210 * scalar)); - - SetDamage((int)(13 * scalar), (int)(24 * scalar)); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, (int)(35 * scalar), (int)(55 * scalar)); - - if (summoned) - SetResistance(ResistanceType.Fire, (int)(50 * scalar), (int)(60 * scalar)); - else - SetResistance(ResistanceType.Fire, (int)(100 * scalar)); - - SetResistance(ResistanceType.Cold, (int)(10 * scalar), (int)(30 * scalar)); - SetResistance(ResistanceType.Poison, (int)(10 * scalar), (int)(25 * scalar)); - SetResistance(ResistanceType.Energy, (int)(30 * scalar), (int)(40 * scalar)); - - SetSkill(SkillName.MagicResist, 150.1 * scalar, 190.0 * scalar); - SetSkill(SkillName.Tactics, 60.1 * scalar, 100.0 * scalar); - SetSkill(SkillName.Wrestling, 60.1 * scalar, 100.0 * scalar); - - if (summoned) - { - Fame = 10; - Karma = 10; - } - else - { - Fame = 3500; - Karma = -3500; - } - - if (!summoned) - { - PackItem(new IronIngot(Utility.RandomMinMax(13, 21))); - - if (Utility.RandomDouble() < 0.1) - PackItem(new PowerCrystal()); - - if (Utility.RandomDouble() < 0.15) - PackItem(new ClockworkAssembly()); - - if (Utility.RandomDouble() < 0.2) - PackItem(new ArcaneGem()); - - if (Utility.RandomDouble() < 0.25) - PackItem(new Gears()); - } - - ControlSlots = 3; - } - - public Golem(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a golem corpse"; - - public override bool IsScaredOfScaryThings => false; - public override bool IsScaryToPets => true; - - public override bool IsBondable => false; - - public override FoodType FavoriteFood => FoodType.None; - - public override bool CanBeDistracted => false; - - public override string DefaultName => "a golem"; - - public override bool DeleteOnRelease => true; - - public override bool AutoDispel => !Controlled; - public override bool BleedImmune => true; - - public override bool BardImmune => !Core.AOS || Controlled; - public override Poison PoisonImmune => Poison.Lethal; - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - if (Utility.RandomDouble() < 0.05) - { - if (!IsParagon) + [Constructible] + public Golem(bool summoned = false, double scalar = 1.0) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.4, 0.8) { - if (Utility.RandomDouble() < 0.75) - c.DropItem(DawnsMusicGear.RandomCommon); - else - c.DropItem(DawnsMusicGear.RandomUncommon); + Body = 752; + + if (summoned) + Hue = 2101; + + SetStr((int)(251 * scalar), (int)(350 * scalar)); + SetDex((int)(76 * scalar), (int)(100 * scalar)); + SetInt((int)(101 * scalar), (int)(150 * scalar)); + + SetHits((int)(151 * scalar), (int)(210 * scalar)); + + SetDamage((int)(13 * scalar), (int)(24 * scalar)); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, (int)(35 * scalar), (int)(55 * scalar)); + + if (summoned) + SetResistance(ResistanceType.Fire, (int)(50 * scalar), (int)(60 * scalar)); + else + SetResistance(ResistanceType.Fire, (int)(100 * scalar)); + + SetResistance(ResistanceType.Cold, (int)(10 * scalar), (int)(30 * scalar)); + SetResistance(ResistanceType.Poison, (int)(10 * scalar), (int)(25 * scalar)); + SetResistance(ResistanceType.Energy, (int)(30 * scalar), (int)(40 * scalar)); + + SetSkill(SkillName.MagicResist, 150.1 * scalar, 190.0 * scalar); + SetSkill(SkillName.Tactics, 60.1 * scalar, 100.0 * scalar); + SetSkill(SkillName.Wrestling, 60.1 * scalar, 100.0 * scalar); + + if (summoned) + { + Fame = 10; + Karma = 10; + } + else + { + Fame = 3500; + Karma = -3500; + } + + if (!summoned) + { + PackItem(new IronIngot(Utility.RandomMinMax(13, 21))); + + if (Utility.RandomDouble() < 0.1) + PackItem(new PowerCrystal()); + + if (Utility.RandomDouble() < 0.15) + PackItem(new ClockworkAssembly()); + + if (Utility.RandomDouble() < 0.2) + PackItem(new ArcaneGem()); + + if (Utility.RandomDouble() < 0.25) + PackItem(new Gears()); + } + + ControlSlots = 3; } - else + + public Golem(Serial serial) : base(serial) { - c.DropItem(DawnsMusicGear.RandomRare); } - } - } - public override int GetAngerSound() => 541; + public override string CorpseName => "a golem corpse"; - public override int GetIdleSound() - { - if (!Controlled) - return 542; + public override bool IsScaredOfScaryThings => false; + public override bool IsScaryToPets => true; - return base.GetIdleSound(); - } + public override bool IsBondable => false; - public override int GetDeathSound() - { - if (!Controlled) - return 545; + public override FoodType FavoriteFood => FoodType.None; - return base.GetDeathSound(); - } + public override bool CanBeDistracted => false; - public override int GetAttackSound() => 562; + public override string DefaultName => "a golem"; - public override int GetHurtSound() - { - if (Controlled) - return 320; + public override bool DeleteOnRelease => true; - return base.GetHurtSound(); - } + public override bool AutoDispel => !Controlled; + public override bool BleedImmune => true; - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); + public override bool BardImmune => !Core.AOS || Controlled; + public override Poison PoisonImmune => Poison.Lethal; - if (!m_Stunning && Utility.RandomDouble() < 0.3) - { - m_Stunning = true; - - defender.Animate(21, 6, 1, true, false, 0); - PlaySound(0xEE); - defender.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, - "You have been stunned by a colossal blow!"); - - if (Weapon is BaseWeapon weapon) - weapon.OnHit(this, defender); - - if (defender.Alive) + public override void OnDeath(Container c) { - defender.Frozen = true; - Timer.DelayCall(TimeSpan.FromSeconds(5.0), Recover_Callback, defender); + base.OnDeath(c); + + if (Utility.RandomDouble() < 0.05) + { + if (!IsParagon) + { + if (Utility.RandomDouble() < 0.75) + c.DropItem(DawnsMusicGear.RandomCommon); + else + c.DropItem(DawnsMusicGear.RandomUncommon); + } + else + { + c.DropItem(DawnsMusicGear.RandomRare); + } + } } - } - } - private void Recover_Callback(Mobile defender) - { - defender.Frozen = false; - defender.Combatant = null; - defender.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You recover your senses."); - m_Stunning = false; - } + public override int GetAngerSound() => 541; - public override void OnDamage(int amount, Mobile from, bool willKill) - { - if (Controlled || Summoned) - { - Mobile master = ControlMaster ?? SummonMaster; - - if (master?.Player == true && master.Map == Map && master.InRange(Location, 20)) + public override int GetIdleSound() { - if (master.Mana >= amount) - { - master.Mana -= amount; - } - else - { - amount -= master.Mana; - master.Mana = 0; - master.Damage(amount); - } + if (!Controlled) + return 542; + + return base.GetIdleSound(); } - } - base.OnDamage(amount, from, willKill); - } + public override int GetDeathSound() + { + if (!Controlled) + return 545; - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } + return base.GetDeathSound(); + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); + public override int GetAttackSound() => 562; + + public override int GetHurtSound() + { + if (Controlled) + return 320; + + return base.GetHurtSound(); + } + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (!m_Stunning && Utility.RandomDouble() < 0.3) + { + m_Stunning = true; + + defender.Animate(21, 6, 1, true, false, 0); + PlaySound(0xEE); + defender.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + false, + "You have been stunned by a colossal blow!" + ); + + if (Weapon is BaseWeapon weapon) + weapon.OnHit(this, defender); + + if (defender.Alive) + { + defender.Frozen = true; + Timer.DelayCall(TimeSpan.FromSeconds(5.0), Recover_Callback, defender); + } + } + } + + private void Recover_Callback(Mobile defender) + { + defender.Frozen = false; + defender.Combatant = null; + defender.LocalOverheadMessage(MessageType.Regular, 0x3B2, false, "You recover your senses."); + m_Stunning = false; + } + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + if (Controlled || Summoned) + { + var master = ControlMaster ?? SummonMaster; + + if (master?.Player == true && master.Map == Map && master.InRange(Location, 20)) + { + if (master.Mana >= amount) + { + master.Mana -= amount; + } + else + { + amount -= master.Mana; + master.Mana = 0; + master.Damage(amount); + } + } + } + + base.OnDamage(amount, from, willKill); + } + + 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(); + } } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Misc/Melee/PlagueBeast.cs b/Projects/UOContent/Mobiles/Monsters/Misc/Melee/PlagueBeast.cs index 70a46148e..d9f05c91c 100644 --- a/Projects/UOContent/Mobiles/Monsters/Misc/Melee/PlagueBeast.cs +++ b/Projects/UOContent/Mobiles/Monsters/Misc/Melee/PlagueBeast.cs @@ -5,228 +5,236 @@ using Server.Network; namespace Server.Mobiles { - public class PlagueBeast : BaseCreature, IDevourer - { - private int m_DevourGoal; - - [Constructible] - public PlagueBeast() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class PlagueBeast : BaseCreature, IDevourer { - Body = 775; + private int m_DevourGoal; - SetStr(302, 500); - SetDex(80); - SetInt(16, 20); + [Constructible] + public PlagueBeast() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 775; - SetHits(318, 404); + SetStr(302, 500); + SetDex(80); + SetInt(16, 20); - SetDamage(20, 24); + SetHits(318, 404); - SetDamageType(ResistanceType.Physical, 60); - SetDamageType(ResistanceType.Poison, 40); + SetDamage(20, 24); - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 25, 35); - SetResistance(ResistanceType.Poison, 65, 75); - SetResistance(ResistanceType.Energy, 25, 35); + SetDamageType(ResistanceType.Physical, 60); + SetDamageType(ResistanceType.Poison, 40); - SetSkill(SkillName.MagicResist, 35.0); - SetSkill(SkillName.Tactics, 100.0); - SetSkill(SkillName.Wrestling, 100.0); + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 25, 35); + SetResistance(ResistanceType.Poison, 65, 75); + SetResistance(ResistanceType.Energy, 25, 35); - Fame = 13000; - Karma = -13000; + SetSkill(SkillName.MagicResist, 35.0); + SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.Wrestling, 100.0); - VirtualArmor = 30; - PackArmor(1, 5); - if (Utility.RandomDouble() < 0.80) - PackItem(new PlagueBeastGland()); + Fame = 13000; + Karma = -13000; - if (Core.ML && Utility.RandomDouble() < 0.33) - PackItem(Seed.RandomPeculiarSeed(4)); + VirtualArmor = 30; + PackArmor(1, 5); + if (Utility.RandomDouble() < 0.80) + PackItem(new PlagueBeastGland()); - TotalDevoured = 0; - m_DevourGoal = Utility.RandomMinMax(15, 25); // How many corpses must be devoured before a metal chest is awarded + if (Core.ML && Utility.RandomDouble() < 0.33) + PackItem(Seed.RandomPeculiarSeed(4)); + + TotalDevoured = 0; + m_DevourGoal = Utility.RandomMinMax(15, 25); // How many corpses must be devoured before a metal chest is awarded + } + + public PlagueBeast(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a plague beast corpse"; + + [CommandProperty(AccessLevel.GameMaster)] + public int TotalDevoured { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int DevourGoal + { + get => IsParagon ? m_DevourGoal + 25 : m_DevourGoal; + set => m_DevourGoal = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool HasMetalChest { get; private set; } + + public override string DefaultName => "a plague beast"; + + public override bool AutoDispel => true; + public override Poison PoisonImmune => Poison.Lethal; + + public bool Devour(Corpse corpse) + { + if (corpse?.Owner == null) // sorry we can't devour because the corpse's owner is null + return false; + + if (corpse.Owner.Body.IsHuman) + corpse.TurnToBones(); // Not bones yet, and we are a human body therefore we turn to bones. + + IncreaseHits((int)Math.Ceiling(corpse.Owner.HitsMax * 0.75)); + TotalDevoured++; + + PublicOverheadMessage( + MessageType.Emote, + 0x3B2, + 1053033 + ); // * The plague beast absorbs the fleshy remains of the corpse * + + if (!HasMetalChest && TotalDevoured >= DevourGoal) + { + PackItem(new MetalChest()); + HasMetalChest = true; + } + + return true; + } + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.Gems, Utility.Random(1, 3)); + // TODO: dungeon chest, healthy gland + } + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + defender.ApplyPoison(this, IsParagon ? Poison.Lethal : Poison.Deadly); + defender.FixedParticles(0x374A, 10, 15, 5021, EffectLayer.Waist); + defender.PlaySound(0x1CB); + } + + public override void OnDamagedBySpell(Mobile caster) + { + if (Map != null && caster != this && Utility.RandomDouble() < 0.25) + { + BaseCreature spawn = new PlagueSpawn(this); + + spawn.Team = Team; + spawn.MoveToWorld(Location, Map); + spawn.Combatant = caster; + + Say(1053034); // * The plague beast creates another beast from its flesh! * + } + + base.OnDamagedBySpell(caster); + } + + public override void OnGotMeleeAttack(Mobile attacker) + { + if (Map != null && attacker != this && Utility.RandomDouble() < 0.25) + { + BaseCreature spawn = new PlagueSpawn(this); + + spawn.Team = Team; + spawn.MoveToWorld(Location, Map); + spawn.Combatant = attacker; + + Say(1053034); // * The plague beast creates another beast from its flesh! * + } + + base.OnGotMeleeAttack(attacker); + } + + public override int GetIdleSound() => 0x1BF; + + public override int GetAttackSound() => 0x1C0; + + public override int GetHurtSound() => 0x1C1; + + public override int GetDeathSound() => 0x1C2; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(1); + + writer.Write(HasMetalChest); + writer.Write(TotalDevoured); + writer.Write(m_DevourGoal); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + HasMetalChest = reader.ReadBool(); + TotalDevoured = reader.ReadInt(); + m_DevourGoal = reader.ReadInt(); + break; + } + } + } + + public override void OnThink() + { + base.OnThink(); + + // Check to see if we need to devour any corpses + var eable = GetItemsInRange(3); // Get all corpses in range + + foreach (var item in eable) + // Ensure that the corpse was killed by us + if (item.Killer == this && item.Owner != null && !item.DevourCorpse() && !item.Devoured) + PublicOverheadMessage( + MessageType.Emote, + 0x3B2, + 1053032 + ); // * The plague beast attempts to absorb the remains, but cannot! * + + eable.Free(); + } + + private void IncreaseHits(int hp) + { + var maxhits = 2000; + + if (IsParagon) + maxhits = (int)(maxhits * Paragon.HitsBuff); + + if (hp < 1000 && !Core.AOS) + hp = hp * 100 / 60; + + if (HitsMaxSeed >= maxhits) + { + HitsMaxSeed = maxhits; + + var newHits = + Hits + hp + Utility.RandomMinMax( + 10, + 20 + ); // increase the hp until it hits if it goes over it'll max at 2000 + + Hits = Math.Min(maxhits, newHits); + // Also provide heal for each devour on top of the hp increase + } + else + { + var min = hp / 2 + 10; + var max = hp + 20; + var hpToIncrease = Utility.RandomMinMax(min, max); + + HitsMaxSeed += hpToIncrease; + Hits += hpToIncrease; + // Also provide heal for each devour + } + } } - - public PlagueBeast(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a plague beast corpse"; - - [CommandProperty(AccessLevel.GameMaster)] - public int TotalDevoured { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int DevourGoal - { - get => IsParagon ? m_DevourGoal + 25 : m_DevourGoal; - set => m_DevourGoal = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool HasMetalChest { get; private set; } - - public override string DefaultName => "a plague beast"; - - public override bool AutoDispel => true; - public override Poison PoisonImmune => Poison.Lethal; - - public bool Devour(Corpse corpse) - { - if (corpse?.Owner == null) // sorry we can't devour because the corpse's owner is null - return false; - - if (corpse.Owner.Body.IsHuman) - corpse.TurnToBones(); // Not bones yet, and we are a human body therefore we turn to bones. - - IncreaseHits((int)Math.Ceiling(corpse.Owner.HitsMax * 0.75)); - TotalDevoured++; - - PublicOverheadMessage(MessageType.Emote, 0x3B2, - 1053033); // * The plague beast absorbs the fleshy remains of the corpse * - - if (!HasMetalChest && TotalDevoured >= DevourGoal) - { - PackItem(new MetalChest()); - HasMetalChest = true; - } - - return true; - } - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.Gems, Utility.Random(1, 3)); - // TODO: dungeon chest, healthy gland - } - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - defender.ApplyPoison(this, IsParagon ? Poison.Lethal : Poison.Deadly); - defender.FixedParticles(0x374A, 10, 15, 5021, EffectLayer.Waist); - defender.PlaySound(0x1CB); - } - - public override void OnDamagedBySpell(Mobile caster) - { - if (Map != null && caster != this && Utility.RandomDouble() < 0.25) - { - BaseCreature spawn = new PlagueSpawn(this); - - spawn.Team = Team; - spawn.MoveToWorld(Location, Map); - spawn.Combatant = caster; - - Say(1053034); // * The plague beast creates another beast from its flesh! * - } - - base.OnDamagedBySpell(caster); - } - - public override void OnGotMeleeAttack(Mobile attacker) - { - if (Map != null && attacker != this && Utility.RandomDouble() < 0.25) - { - BaseCreature spawn = new PlagueSpawn(this); - - spawn.Team = Team; - spawn.MoveToWorld(Location, Map); - spawn.Combatant = attacker; - - Say(1053034); // * The plague beast creates another beast from its flesh! * - } - - base.OnGotMeleeAttack(attacker); - } - - public override int GetIdleSound() => 0x1BF; - - public override int GetAttackSound() => 0x1C0; - - public override int GetHurtSound() => 0x1C1; - - public override int GetDeathSound() => 0x1C2; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); - - writer.Write(HasMetalChest); - writer.Write(TotalDevoured); - writer.Write(m_DevourGoal); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - HasMetalChest = reader.ReadBool(); - TotalDevoured = reader.ReadInt(); - m_DevourGoal = reader.ReadInt(); - break; - } - } - } - - public override void OnThink() - { - base.OnThink(); - - // Check to see if we need to devour any corpses - IPooledEnumerable eable = GetItemsInRange(3); // Get all corpses in range - - foreach (Corpse item in eable) - // Ensure that the corpse was killed by us - if (item.Killer == this && item.Owner != null && !item.DevourCorpse() && !item.Devoured) - PublicOverheadMessage(MessageType.Emote, 0x3B2, - 1053032); // * The plague beast attempts to absorb the remains, but cannot! * - - eable.Free(); - } - - private void IncreaseHits(int hp) - { - int maxhits = 2000; - - if (IsParagon) - maxhits = (int)(maxhits * Paragon.HitsBuff); - - if (hp < 1000 && !Core.AOS) - hp = hp * 100 / 60; - - if (HitsMaxSeed >= maxhits) - { - HitsMaxSeed = maxhits; - - int newHits = - Hits + hp + Utility.RandomMinMax(10, - 20); // increase the hp until it hits if it goes over it'll max at 2000 - - Hits = Math.Min(maxhits, newHits); - // Also provide heal for each devour on top of the hp increase - } - else - { - int min = hp / 2 + 10; - int max = hp + 20; - int hpToIncrease = Utility.RandomMinMax(min, max); - - HitsMaxSeed += hpToIncrease; - Hits += hpToIncrease; - // Also provide heal for each devour - } - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Misc/Melee/PlagueBeastLord.cs b/Projects/UOContent/Mobiles/Monsters/Misc/Melee/PlagueBeastLord.cs index 774bb21ec..134ad9f86 100644 --- a/Projects/UOContent/Mobiles/Monsters/Misc/Melee/PlagueBeastLord.cs +++ b/Projects/UOContent/Mobiles/Monsters/Misc/Melee/PlagueBeastLord.cs @@ -4,328 +4,356 @@ using Server.Network; namespace Server.Mobiles { - public class PlagueBeastLord : BaseCreature, ICarvable, IScissorable - { - private DecayTimer m_Timer; - - [Constructible] - public PlagueBeastLord() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class PlagueBeastLord : BaseCreature, ICarvable, IScissorable { - Body = 775; - BaseSoundID = 679; - SpeechHue = 0x3B2; + private DecayTimer m_Timer; - SetStr(500); - SetDex(100); - SetInt(30); - - SetHits(1800); - - SetDamage(20, 25); - - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Fire, 25); - SetDamageType(ResistanceType.Poison, 25); - - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 25, 35); - SetResistance(ResistanceType.Poison, 75, 85); - SetResistance(ResistanceType.Energy, 25, 35); - - SetSkill(SkillName.Tactics, 100); - SetSkill(SkillName.Wrestling, 100); - - Fame = 2000; - Karma = -2000; - - VirtualArmor = 50; - } - - public PlagueBeastLord(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a plague beast lord corpse"; - public override Poison PoisonImmune => Poison.Lethal; - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile OpenedBy { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsBleeding - { - get - { - Container pack = Backpack; - - if (pack != null) - for (int i = 0; i < pack.Items.Count; i++) - if (pack.Items[i] is PlagueBeastBlood blood && !blood.Patched) - return true; - - return false; - } - } - - public override string DefaultName => "a plague beast lord"; - - public virtual void Carve(Mobile from, Item item) - { - if (OpenedBy == null && IsAccessibleTo(from)) - { - OpenedBy = from; - - m_Timer ??= new DecayTimer(this); - - if (!m_Timer.Running) - m_Timer.Start(); - - m_Timer.StartDissolving(); - - PlagueBeastBackpack pack = new PlagueBeastBackpack(); - AddItem(pack); - pack.Initialize(); - - foreach (NetState state in GetClientsInRange(12)) + [Constructible] + public PlagueBeastLord() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) { - Mobile m = state.Mobile; + Body = 775; + BaseSoundID = 679; + SpeechHue = 0x3B2; - if (m?.Player == true && m != from) - PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1071919, from.Name, - m.NetState); // * ~1_VAL~ slices through the plague beast's amorphous tissue * + SetStr(500); + SetDex(100); + SetInt(30); + + SetHits(1800); + + SetDamage(20, 25); + + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Fire, 25); + SetDamageType(ResistanceType.Poison, 25); + + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 25, 35); + SetResistance(ResistanceType.Poison, 75, 85); + SetResistance(ResistanceType.Energy, 25, 35); + + SetSkill(SkillName.Tactics, 100); + SetSkill(SkillName.Wrestling, 100); + + Fame = 2000; + Karma = -2000; + + VirtualArmor = 50; } - from.LocalOverheadMessage(MessageType.Regular, 0x21, - 1071904); // * You slice through the plague beast's amorphous tissue * - Timer.DelayCall(pack.Open, from); - } - } - - public virtual bool Scissor(Mobile from, Scissors scissors) - { - if (IsAccessibleTo(from)) - scissors.PublicOverheadMessage(MessageType.Regular, 0x3B2, - 1071918); // You can't cut through the plague beast's amorphous skin with scissors! - - return false; - } - - public override void OnDoubleClick(Mobile from) - { - if (IsAccessibleTo(from)) - { - if (OpenedBy != null && Backpack != null) - Backpack.DisplayTo(from); - else - PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1071917, - from.NetState); // * You attempt to tear open the amorphous flesh, but it resists * - } - } - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (IsAccessibleTo(from) && (dropped is PlagueBeastInnard || dropped is PlagueBeastGland)) - return base.OnDragDrop(from, dropped); - - return false; - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - for (int i = c.Items.Count - 1; i >= 0; i--) - c.Items[i].Delete(); - } - - public override void OnDelete() - { - if (OpenedBy?.Holding is PlagueBeastInnard) - OpenedBy.Holding.Delete(); - - if (Backpack != null) - { - for (int i = Backpack.Items.Count - 1; i >= 0; i--) - Backpack.Items[i].Delete(); - - Backpack.Delete(); - } - - base.OnDelete(); - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - base.OnMovement(m, oldLocation); - - if (Backpack != null && IsAccessibleTo(m) && m.InRange(oldLocation, 3) && !m.InRange(this, 3)) - Backpack.SendRemovePacket(); - } - - public override bool CheckNonlocalLift(Mobile from, Item item) => true; - - public override bool CheckNonlocalDrop(Mobile from, Item item, Item target) => true; - - public override bool IsSnoop(Mobile from) => false; - - public override int GetIdleSound() => 0x1BF; - - public override int GetAttackSound() => 0x1C0; - - public override int GetHurtSound() => 0x1C1; - - public override int GetDeathSound() => 0x1C2; - - public virtual void OnParalyzed(Mobile from) - { - FightMode = FightMode.None; - Frozen = true; - Blessed = true; - Combatant = null; - Hue = 0x480; - from.Combatant = null; - from.Warmode = false; - - m_Timer = new DecayTimer(this); - m_Timer.Start(); - - Timer.DelayCall(BroadcastMessage); - } - - private void BroadcastMessage() - { - PublicOverheadMessage(MessageType.Regular, 0x3B2, - 1071920); // * The plague beast's amorphous flesh hardens and becomes immobilized * - } - - public virtual bool IsAccessibleTo(Mobile check) - { - if (check.AccessLevel >= AccessLevel.GameMaster) - return true; - - if (!InRange(check, 2)) - PrivateOverheadMessage(MessageType.Label, 0x3B2, 500446, check.NetState); // That is too far away. - else if (OpenedBy != null && OpenedBy != check) - PrivateOverheadMessage(MessageType.Label, 0x3B2, 500365, - check.NetState); // That is being used by someone else - else if (Frozen) - return true; - - return false; - } - - public void Unfreeze() - { - FightMode = FightMode.Closest; - Frozen = false; - Blessed = false; - - if (OpenedBy == null) - Hue = 0; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(OpenedBy); - - if (m_Timer != null) - { - writer.Write(true); - writer.Write(m_Timer.Count); - writer.Write(m_Timer.Deadline); - } - else - { - writer.Write(false); - } - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - OpenedBy = reader.ReadMobile(); - - if (reader.ReadBool()) - { - int count = reader.ReadInt(); - int deadline = reader.ReadInt(); - - m_Timer = new DecayTimer(this, count, deadline); - m_Timer.Start(); - } - - if (FightMode == FightMode.None) - Frozen = true; - } - - private class DecayTimer : Timer - { - private readonly PlagueBeastLord m_Lord; - - public DecayTimer(PlagueBeastLord lord, int count = 0, int deadline = 120) : base(TimeSpan.Zero, TimeSpan.FromSeconds(1)) - { - m_Lord = lord; - Count = count; - Deadline = deadline; - } - - public int Count { get; private set; } - - public int Deadline { get; private set; } - - protected override void OnTick() - { - if (m_Lord?.Deleted != false) + public PlagueBeastLord(Serial serial) : base(serial) { - Stop(); - return; } - if (Count + 15 == Deadline) - { - if (m_Lord.OpenedBy != null) - m_Lord.PublicOverheadMessage(MessageType.Regular, 0x3B2, - 1071921); // * The plague beast begins to bubble and dissolve! * + public override string CorpseName => "a plague beast lord corpse"; + public override Poison PoisonImmune => Poison.Lethal; - m_Lord.PlaySound(0x103); - } - else if (Count + 10 == Deadline) - { - m_Lord.PlaySound(0x21); - } - else if (Count + 5 == Deadline) - { - m_Lord.PlaySound(0x1C2); - } - else if (Count == Deadline) - { - m_Lord.Unfreeze(); + [CommandProperty(AccessLevel.GameMaster)] + public Mobile OpenedBy { get; set; } - if (m_Lord.OpenedBy != null) - m_Lord.Kill(); - - Stop(); - } - else if (Count % 15 == 0) + [CommandProperty(AccessLevel.GameMaster)] + public bool IsBleeding { - m_Lord.PlaySound(0x1BF); + get + { + var pack = Backpack; + + if (pack != null) + for (var i = 0; i < pack.Items.Count; i++) + if (pack.Items[i] is PlagueBeastBlood blood && !blood.Patched) + return true; + + return false; + } } - Count++; - } + public override string DefaultName => "a plague beast lord"; - public void StartDissolving() - { - Deadline = Math.Min(Count + 60, Deadline); - } + public virtual void Carve(Mobile from, Item item) + { + if (OpenedBy == null && IsAccessibleTo(from)) + { + OpenedBy = from; + + m_Timer ??= new DecayTimer(this); + + if (!m_Timer.Running) + m_Timer.Start(); + + m_Timer.StartDissolving(); + + var pack = new PlagueBeastBackpack(); + AddItem(pack); + pack.Initialize(); + + foreach (var state in GetClientsInRange(12)) + { + var m = state.Mobile; + + if (m?.Player == true && m != from) + PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 1071919, + from.Name, + m.NetState + ); // * ~1_VAL~ slices through the plague beast's amorphous tissue * + } + + from.LocalOverheadMessage( + MessageType.Regular, + 0x21, + 1071904 + ); // * You slice through the plague beast's amorphous tissue * + Timer.DelayCall(pack.Open, from); + } + } + + public virtual bool Scissor(Mobile from, Scissors scissors) + { + if (IsAccessibleTo(from)) + scissors.PublicOverheadMessage( + MessageType.Regular, + 0x3B2, + 1071918 + ); // You can't cut through the plague beast's amorphous skin with scissors! + + return false; + } + + public override void OnDoubleClick(Mobile from) + { + if (IsAccessibleTo(from)) + { + if (OpenedBy != null && Backpack != null) + Backpack.DisplayTo(from); + else + PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 1071917, + from.NetState + ); // * You attempt to tear open the amorphous flesh, but it resists * + } + } + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (IsAccessibleTo(from) && (dropped is PlagueBeastInnard || dropped is PlagueBeastGland)) + return base.OnDragDrop(from, dropped); + + return false; + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + for (var i = c.Items.Count - 1; i >= 0; i--) + c.Items[i].Delete(); + } + + public override void OnDelete() + { + if (OpenedBy?.Holding is PlagueBeastInnard) + OpenedBy.Holding.Delete(); + + if (Backpack != null) + { + for (var i = Backpack.Items.Count - 1; i >= 0; i--) + Backpack.Items[i].Delete(); + + Backpack.Delete(); + } + + base.OnDelete(); + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + base.OnMovement(m, oldLocation); + + if (Backpack != null && IsAccessibleTo(m) && m.InRange(oldLocation, 3) && !m.InRange(this, 3)) + Backpack.SendRemovePacket(); + } + + public override bool CheckNonlocalLift(Mobile from, Item item) => true; + + public override bool CheckNonlocalDrop(Mobile from, Item item, Item target) => true; + + public override bool IsSnoop(Mobile from) => false; + + public override int GetIdleSound() => 0x1BF; + + public override int GetAttackSound() => 0x1C0; + + public override int GetHurtSound() => 0x1C1; + + public override int GetDeathSound() => 0x1C2; + + public virtual void OnParalyzed(Mobile from) + { + FightMode = FightMode.None; + Frozen = true; + Blessed = true; + Combatant = null; + Hue = 0x480; + from.Combatant = null; + from.Warmode = false; + + m_Timer = new DecayTimer(this); + m_Timer.Start(); + + Timer.DelayCall(BroadcastMessage); + } + + private void BroadcastMessage() + { + PublicOverheadMessage( + MessageType.Regular, + 0x3B2, + 1071920 + ); // * The plague beast's amorphous flesh hardens and becomes immobilized * + } + + public virtual bool IsAccessibleTo(Mobile check) + { + if (check.AccessLevel >= AccessLevel.GameMaster) + return true; + + if (!InRange(check, 2)) + PrivateOverheadMessage(MessageType.Label, 0x3B2, 500446, check.NetState); // That is too far away. + else if (OpenedBy != null && OpenedBy != check) + PrivateOverheadMessage( + MessageType.Label, + 0x3B2, + 500365, + check.NetState + ); // That is being used by someone else + else if (Frozen) + return true; + + return false; + } + + public void Unfreeze() + { + FightMode = FightMode.Closest; + Frozen = false; + Blessed = false; + + if (OpenedBy == null) + Hue = 0; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(OpenedBy); + + if (m_Timer != null) + { + writer.Write(true); + writer.Write(m_Timer.Count); + writer.Write(m_Timer.Deadline); + } + else + { + writer.Write(false); + } + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + OpenedBy = reader.ReadMobile(); + + if (reader.ReadBool()) + { + var count = reader.ReadInt(); + var deadline = reader.ReadInt(); + + m_Timer = new DecayTimer(this, count, deadline); + m_Timer.Start(); + } + + if (FightMode == FightMode.None) + Frozen = true; + } + + private class DecayTimer : Timer + { + private readonly PlagueBeastLord m_Lord; + + public DecayTimer(PlagueBeastLord lord, int count = 0, int deadline = 120) : base( + TimeSpan.Zero, + TimeSpan.FromSeconds(1) + ) + { + m_Lord = lord; + Count = count; + Deadline = deadline; + } + + public int Count { get; private set; } + + public int Deadline { get; private set; } + + protected override void OnTick() + { + if (m_Lord?.Deleted != false) + { + Stop(); + return; + } + + if (Count + 15 == Deadline) + { + if (m_Lord.OpenedBy != null) + m_Lord.PublicOverheadMessage( + MessageType.Regular, + 0x3B2, + 1071921 + ); // * The plague beast begins to bubble and dissolve! * + + m_Lord.PlaySound(0x103); + } + else if (Count + 10 == Deadline) + { + m_Lord.PlaySound(0x21); + } + else if (Count + 5 == Deadline) + { + m_Lord.PlaySound(0x1C2); + } + else if (Count == Deadline) + { + m_Lord.Unfreeze(); + + if (m_Lord.OpenedBy != null) + m_Lord.Kill(); + + Stop(); + } + else if (Count % 15 == 0) + { + m_Lord.PlaySound(0x1BF); + } + + Count++; + } + + public void StartDissolving() + { + Deadline = Math.Min(Count + 60, Deadline); + } + } } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Misc/Melee/PlagueSpawn.cs b/Projects/UOContent/Mobiles/Monsters/Misc/Melee/PlagueSpawn.cs index 5bdd6661f..eee430bcc 100644 --- a/Projects/UOContent/Mobiles/Monsters/Misc/Melee/PlagueSpawn.cs +++ b/Projects/UOContent/Mobiles/Monsters/Misc/Melee/PlagueSpawn.cs @@ -4,127 +4,127 @@ using Server.ContextMenus; namespace Server.Mobiles { - public class PlagueSpawn : BaseCreature - { - [Constructible] - public PlagueSpawn(Mobile owner = null) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class PlagueSpawn : BaseCreature { - Owner = owner; - ExpireTime = DateTime.UtcNow + TimeSpan.FromMinutes(1.0); + [Constructible] + public PlagueSpawn(Mobile owner = null) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Owner = owner; + ExpireTime = DateTime.UtcNow + TimeSpan.FromMinutes(1.0); - Hue = Utility.Random(0x11, 15); + Hue = Utility.Random(0x11, 15); - switch (Utility.Random(12)) - { - case 0: // earth elemental - Body = 14; - BaseSoundID = 268; - break; - case 1: // headless one - Body = 31; - BaseSoundID = 0x39D; - break; - case 2: // person - Body = Utility.RandomList(400, 401); - break; - case 3: // gorilla - Body = 0x1D; - BaseSoundID = 0x9E; - break; - case 4: // serpent - Body = 0x15; - BaseSoundID = 0xDB; - break; - default: // slime - Body = 51; - BaseSoundID = 456; - break; - } + switch (Utility.Random(12)) + { + case 0: // earth elemental + Body = 14; + BaseSoundID = 268; + break; + case 1: // headless one + Body = 31; + BaseSoundID = 0x39D; + break; + case 2: // person + Body = Utility.RandomList(400, 401); + break; + case 3: // gorilla + Body = 0x1D; + BaseSoundID = 0x9E; + break; + case 4: // serpent + Body = 0x15; + BaseSoundID = 0xDB; + break; + default: // slime + Body = 51; + BaseSoundID = 456; + break; + } - SetStr(201, 300); - SetDex(80); - SetInt(16, 20); + SetStr(201, 300); + SetDex(80); + SetInt(16, 20); - SetHits(121, 180); + SetHits(121, 180); - SetDamage(11, 17); + SetDamage(11, 17); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 25, 35); - SetResistance(ResistanceType.Poison, 65, 75); - SetResistance(ResistanceType.Energy, 25, 35); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 25, 35); + SetResistance(ResistanceType.Poison, 65, 75); + SetResistance(ResistanceType.Energy, 25, 35); - SetSkill(SkillName.MagicResist, 25.0); - SetSkill(SkillName.Tactics, 25.0); - SetSkill(SkillName.Wrestling, 50.0); + SetSkill(SkillName.MagicResist, 25.0); + SetSkill(SkillName.Tactics, 25.0); + SetSkill(SkillName.Wrestling, 50.0); - Fame = 1000; - Karma = -1000; + Fame = 1000; + Karma = -1000; - VirtualArmor = 20; + VirtualArmor = 20; + } + + public PlagueSpawn(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a plague spawn corpse"; + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Owner { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime ExpireTime { get; set; } + + public override bool AlwaysMurderer => true; + + public override string DefaultName => "a plague spawn"; + + public override void DisplayPaperdollTo(Mobile to) + { + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + for (var i = 0; i < list.Count; ++i) + if (list[i] is PaperdollEntry) + list.RemoveAt(i--); + } + + public override void OnThink() + { + if (Owner != null && (DateTime.UtcNow >= ExpireTime || Owner.Deleted || Map != Owner.Map || !InRange(Owner, 16))) + { + PlaySound(GetIdleSound()); + Delete(); + } + else + { + base.OnThink(); + } + } + + public override void GenerateLoot() + { + AddLoot(LootPack.Poor); + AddLoot(LootPack.Gems); + } + + 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(); + } } - - public PlagueSpawn(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a plague spawn corpse"; - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Owner { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime ExpireTime { get; set; } - - public override bool AlwaysMurderer => true; - - public override string DefaultName => "a plague spawn"; - - public override void DisplayPaperdollTo(Mobile to) - { - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - for (int i = 0; i < list.Count; ++i) - if (list[i] is PaperdollEntry) - list.RemoveAt(i--); - } - - public override void OnThink() - { - if (Owner != null && (DateTime.UtcNow >= ExpireTime || Owner.Deleted || Map != Owner.Map || !InRange(Owner, 16))) - { - PlaySound(GetIdleSound()); - Delete(); - } - else - { - base.OnThink(); - } - } - - public override void GenerateLoot() - { - AddLoot(LootPack.Poor); - AddLoot(LootPack.Gems); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Misc/Melee/SandVortex.cs b/Projects/UOContent/Mobiles/Monsters/Misc/Melee/SandVortex.cs index 6750b942f..5e0f86ec0 100644 --- a/Projects/UOContent/Mobiles/Monsters/Misc/Melee/SandVortex.cs +++ b/Projects/UOContent/Mobiles/Monsters/Misc/Melee/SandVortex.cs @@ -3,111 +3,111 @@ using Server.Items; namespace Server.Mobiles { - public class SandVortex : BaseCreature - { - private DateTime m_NextAttack; - - [Constructible] - public SandVortex() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class SandVortex : BaseCreature { - Body = 790; - BaseSoundID = 263; + private DateTime m_NextAttack; - SetStr(96, 120); - SetDex(171, 195); - SetInt(76, 100); + [Constructible] + public SandVortex() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 790; + BaseSoundID = 263; - SetHits(51, 62); + SetStr(96, 120); + SetDex(171, 195); + SetInt(76, 100); - SetDamage(3, 16); + SetHits(51, 62); - SetDamageType(ResistanceType.Physical, 90); - SetDamageType(ResistanceType.Fire, 10); + SetDamage(3, 16); - SetResistance(ResistanceType.Physical, 80, 90); - SetResistance(ResistanceType.Fire, 60, 70); - SetResistance(ResistanceType.Cold, 60, 70); - SetResistance(ResistanceType.Poison, 60, 70); - SetResistance(ResistanceType.Energy, 60, 70); + SetDamageType(ResistanceType.Physical, 90); + SetDamageType(ResistanceType.Fire, 10); - SetSkill(SkillName.MagicResist, 150.0); - SetSkill(SkillName.Tactics, 70.0); - SetSkill(SkillName.Wrestling, 80.0); + SetResistance(ResistanceType.Physical, 80, 90); + SetResistance(ResistanceType.Fire, 60, 70); + SetResistance(ResistanceType.Cold, 60, 70); + SetResistance(ResistanceType.Poison, 60, 70); + SetResistance(ResistanceType.Energy, 60, 70); - Fame = 4500; - Karma = -4500; + SetSkill(SkillName.MagicResist, 150.0); + SetSkill(SkillName.Tactics, 70.0); + SetSkill(SkillName.Wrestling, 80.0); - VirtualArmor = 28; - PackItem(new Bone()); + Fame = 4500; + Karma = -4500; + + VirtualArmor = 28; + PackItem(new Bone()); + } + + public SandVortex(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a sand vortex corpse"; + public override string DefaultName => "a sand vortex"; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager, 2); + } + + public override void OnActionCombat() + { + var combatant = Combatant; + + if (combatant?.Deleted != false || combatant.Map != Map || !InRange(combatant, 12) || + !CanBeHarmful(combatant) || !InLOS(combatant)) + return; + + if (DateTime.UtcNow >= m_NextAttack) + { + SandAttack(combatant); + m_NextAttack = DateTime.UtcNow + TimeSpan.FromSeconds(10.0 + 10.0 * Utility.RandomDouble()); + } + } + + public void SandAttack(Mobile m) + { + DoHarmful(m); + + m.FixedParticles(0x36B0, 10, 25, 9540, 2413, 0, EffectLayer.Waist); + + new InternalTimer(m, this).Start(); + } + + 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(); + } + + private class InternalTimer : Timer + { + private readonly Mobile m_From; + private readonly Mobile m_Mobile; + + public InternalTimer(Mobile m, Mobile from) : base(TimeSpan.FromSeconds(1.0)) + { + m_Mobile = m; + m_From = from; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + m_Mobile.PlaySound(0x4CF); + AOS.Damage(m_Mobile, m_From, Utility.RandomMinMax(1, 40), 90, 10, 0, 0, 0); + } + } } - - public SandVortex(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a sand vortex corpse"; - public override string DefaultName => "a sand vortex"; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager, 2); - } - - public override void OnActionCombat() - { - Mobile combatant = Combatant; - - if (combatant?.Deleted != false || combatant.Map != Map || !InRange(combatant, 12) || - !CanBeHarmful(combatant) || !InLOS(combatant)) - return; - - if (DateTime.UtcNow >= m_NextAttack) - { - SandAttack(combatant); - m_NextAttack = DateTime.UtcNow + TimeSpan.FromSeconds(10.0 + 10.0 * Utility.RandomDouble()); - } - } - - public void SandAttack(Mobile m) - { - DoHarmful(m); - - m.FixedParticles(0x36B0, 10, 25, 9540, 2413, 0, EffectLayer.Waist); - - new InternalTimer(m, this).Start(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private class InternalTimer : Timer - { - private readonly Mobile m_Mobile; - private readonly Mobile m_From; - - public InternalTimer(Mobile m, Mobile from) : base(TimeSpan.FromSeconds(1.0)) - { - m_Mobile = m; - m_From = from; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - m_Mobile.PlaySound(0x4CF); - AOS.Damage(m_Mobile, m_From, Utility.RandomMinMax(1, 40), 90, 10, 0, 0, 0); - } - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Misc/Melee/Slime.cs b/Projects/UOContent/Mobiles/Monsters/Misc/Melee/Slime.cs index a681d19b6..1ba5420a2 100644 --- a/Projects/UOContent/Mobiles/Monsters/Misc/Melee/Slime.cs +++ b/Projects/UOContent/Mobiles/Monsters/Misc/Melee/Slime.cs @@ -1,72 +1,72 @@ namespace Server.Mobiles { - public class Slime : BaseCreature - { - [Constructible] - public Slime() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Slime : BaseCreature { - Body = 51; - BaseSoundID = 456; + [Constructible] + public Slime() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 51; + BaseSoundID = 456; - Hue = Utility.RandomSlimeHue(); + Hue = Utility.RandomSlimeHue(); - SetStr(22, 34); - SetDex(16, 21); - SetInt(16, 20); + SetStr(22, 34); + SetDex(16, 21); + SetInt(16, 20); - SetHits(15, 19); + SetHits(15, 19); - SetDamage(1, 5); + SetDamage(1, 5); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 5, 10); - SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Physical, 5, 10); + SetResistance(ResistanceType.Poison, 10, 20); - SetSkill(SkillName.Poisoning, 30.1, 50.0); - SetSkill(SkillName.MagicResist, 15.1, 20.0); - SetSkill(SkillName.Tactics, 19.3, 34.0); - SetSkill(SkillName.Wrestling, 19.3, 34.0); + SetSkill(SkillName.Poisoning, 30.1, 50.0); + SetSkill(SkillName.MagicResist, 15.1, 20.0); + SetSkill(SkillName.Tactics, 19.3, 34.0); + SetSkill(SkillName.Wrestling, 19.3, 34.0); - Fame = 300; - Karma = -300; + Fame = 300; + Karma = -300; - VirtualArmor = 8; + VirtualArmor = 8; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 23.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 23.1; + } + + public Slime(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a slimey corpse"; + public override string DefaultName => "a slime"; + + public override Poison PoisonImmune => Poison.Lesser; + public override Poison HitPoison => Poison.Lesser; + + public override FoodType FavoriteFood => FoodType.Meat | FoodType.Fish | FoodType.FruitsAndVegies | + FoodType.GrainsAndHay | FoodType.Eggs; + + public override void GenerateLoot() + { + AddLoot(LootPack.Poor); + AddLoot(LootPack.Gems); + } + + 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(); + } } - - public Slime(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a slimey corpse"; - public override string DefaultName => "a slime"; - - public override Poison PoisonImmune => Poison.Lesser; - public override Poison HitPoison => Poison.Lesser; - - public override FoodType FavoriteFood => FoodType.Meat | FoodType.Fish | FoodType.FruitsAndVegies | - FoodType.GrainsAndHay | FoodType.Eggs; - - public override void GenerateLoot() - { - AddLoot(LootPack.Poor); - AddLoot(LootPack.Gems); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Ore Elementals/AgapiteElemental.cs b/Projects/UOContent/Mobiles/Monsters/Ore Elementals/AgapiteElemental.cs index a0aa9295f..600e7f2b2 100644 --- a/Projects/UOContent/Mobiles/Monsters/Ore Elementals/AgapiteElemental.cs +++ b/Projects/UOContent/Mobiles/Monsters/Ore Elementals/AgapiteElemental.cs @@ -2,71 +2,71 @@ using Server.Items; namespace Server.Mobiles { - public class AgapiteElemental : BaseCreature - { - [Constructible] - public AgapiteElemental(int oreAmount = 2) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class AgapiteElemental : BaseCreature { - Body = 107; - BaseSoundID = 268; + [Constructible] + public AgapiteElemental(int oreAmount = 2) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 107; + BaseSoundID = 268; - SetStr(226, 255); - SetDex(126, 145); - SetInt(71, 92); + SetStr(226, 255); + SetDex(126, 145); + SetInt(71, 92); - SetHits(136, 153); + SetHits(136, 153); - SetDamage(28); + SetDamage(28); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 30, 40); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 10, 20); + SetResistance(ResistanceType.Physical, 30, 40); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 10, 20); - SetSkill(SkillName.MagicResist, 50.1, 95.0); - SetSkill(SkillName.Tactics, 60.1, 100.0); - SetSkill(SkillName.Wrestling, 60.1, 100.0); + SetSkill(SkillName.MagicResist, 50.1, 95.0); + SetSkill(SkillName.Tactics, 60.1, 100.0); + SetSkill(SkillName.Wrestling, 60.1, 100.0); - Fame = 3500; - Karma = -3500; + Fame = 3500; + Karma = -3500; - VirtualArmor = 32; + VirtualArmor = 32; - Item ore = new AgapiteOre(oreAmount); - ore.ItemID = 0x19B9; - PackItem(ore); + Item ore = new AgapiteOre(oreAmount); + ore.ItemID = 0x19B9; + PackItem(ore); + } + + public AgapiteElemental(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ore elemental corpse"; + public override string DefaultName => "an agapite elemental"; + + public override bool BleedImmune => true; + public override bool AutoDispel => true; + public override int TreasureMapLevel => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Gems, 2); + } + + 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(); + } } - - public AgapiteElemental(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ore elemental corpse"; - public override string DefaultName => "an agapite elemental"; - - public override bool BleedImmune => true; - public override bool AutoDispel => true; - public override int TreasureMapLevel => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Gems, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Ore Elementals/BronzeElemental.cs b/Projects/UOContent/Mobiles/Monsters/Ore Elementals/BronzeElemental.cs index 34c5c933a..a9da2c0f7 100644 --- a/Projects/UOContent/Mobiles/Monsters/Ore Elementals/BronzeElemental.cs +++ b/Projects/UOContent/Mobiles/Monsters/Ore Elementals/BronzeElemental.cs @@ -2,73 +2,73 @@ using Server.Items; namespace Server.Mobiles { - public class BronzeElemental : BaseCreature - { - [Constructible] - public BronzeElemental(int oreAmount = 2) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class BronzeElemental : BaseCreature { - // TODO: Gas attack - Body = 108; - BaseSoundID = 268; + [Constructible] + public BronzeElemental(int oreAmount = 2) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + // TODO: Gas attack + Body = 108; + BaseSoundID = 268; - SetStr(226, 255); - SetDex(126, 145); - SetInt(71, 92); + SetStr(226, 255); + SetDex(126, 145); + SetInt(71, 92); - SetHits(136, 153); + SetHits(136, 153); - SetDamage(9, 16); + SetDamage(9, 16); - SetDamageType(ResistanceType.Physical, 30); - SetDamageType(ResistanceType.Fire, 70); + SetDamageType(ResistanceType.Physical, 30); + SetDamageType(ResistanceType.Fire, 70); - SetResistance(ResistanceType.Physical, 30, 40); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 10, 20); - SetResistance(ResistanceType.Poison, 70, 80); - SetResistance(ResistanceType.Energy, 20, 30); + SetResistance(ResistanceType.Physical, 30, 40); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Poison, 70, 80); + SetResistance(ResistanceType.Energy, 20, 30); - SetSkill(SkillName.MagicResist, 50.1, 95.0); - SetSkill(SkillName.Tactics, 60.1, 100.0); - SetSkill(SkillName.Wrestling, 60.1, 100.0); + SetSkill(SkillName.MagicResist, 50.1, 95.0); + SetSkill(SkillName.Tactics, 60.1, 100.0); + SetSkill(SkillName.Wrestling, 60.1, 100.0); - Fame = 5000; - Karma = -5000; + Fame = 5000; + Karma = -5000; - VirtualArmor = 29; + VirtualArmor = 29; - Item ore = new BronzeOre(oreAmount); - ore.ItemID = 0x19B9; - PackItem(ore); + Item ore = new BronzeOre(oreAmount); + ore.ItemID = 0x19B9; + PackItem(ore); + } + + public BronzeElemental(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ore elemental corpse"; + public override string DefaultName => "a bronze elemental"; + + public override bool BleedImmune => true; + public override bool AutoDispel => true; + public override int TreasureMapLevel => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Gems, 2); + } + + 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(); + } } - - public BronzeElemental(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ore elemental corpse"; - public override string DefaultName => "a bronze elemental"; - - public override bool BleedImmune => true; - public override bool AutoDispel => true; - public override int TreasureMapLevel => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Gems, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Ore Elementals/CopperElemental.cs b/Projects/UOContent/Mobiles/Monsters/Ore Elementals/CopperElemental.cs index 1567dcd3e..52c7319f4 100644 --- a/Projects/UOContent/Mobiles/Monsters/Ore Elementals/CopperElemental.cs +++ b/Projects/UOContent/Mobiles/Monsters/Ore Elementals/CopperElemental.cs @@ -2,76 +2,76 @@ using Server.Items; namespace Server.Mobiles { - public class CopperElemental : BaseCreature - { - [Constructible] - public CopperElemental(int oreAmount = 2) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class CopperElemental : BaseCreature { - Body = 109; - BaseSoundID = 268; + [Constructible] + public CopperElemental(int oreAmount = 2) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 109; + BaseSoundID = 268; - SetStr(226, 255); - SetDex(126, 145); - SetInt(71, 92); + SetStr(226, 255); + SetDex(126, 145); + SetInt(71, 92); - SetHits(136, 153); + SetHits(136, 153); - SetDamage(9, 16); + SetDamage(9, 16); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 30, 40); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 10, 20); + SetResistance(ResistanceType.Physical, 30, 40); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 10, 20); - SetSkill(SkillName.MagicResist, 50.1, 95.0); - SetSkill(SkillName.Tactics, 60.1, 100.0); - SetSkill(SkillName.Wrestling, 60.1, 100.0); + SetSkill(SkillName.MagicResist, 50.1, 95.0); + SetSkill(SkillName.Tactics, 60.1, 100.0); + SetSkill(SkillName.Wrestling, 60.1, 100.0); - Fame = 4800; - Karma = -4800; + Fame = 4800; + Karma = -4800; - VirtualArmor = 26; + VirtualArmor = 26; - Item ore = new CopperOre(oreAmount); - ore.ItemID = 0x19B9; - PackItem(ore); + Item ore = new CopperOre(oreAmount); + ore.ItemID = 0x19B9; + PackItem(ore); + } + + public CopperElemental(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ore elemental corpse"; + public override string DefaultName => "a copper elemental"; + + public override bool BleedImmune => true; + public override bool AutoDispel => true; + public override int TreasureMapLevel => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Gems, 2); + } + + public override void CheckReflect(Mobile caster, ref bool reflect) + { + reflect = true; // Every spell is reflected back to the caster + } + + 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(); + } } - - public CopperElemental(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ore elemental corpse"; - public override string DefaultName => "a copper elemental"; - - public override bool BleedImmune => true; - public override bool AutoDispel => true; - public override int TreasureMapLevel => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Gems, 2); - } - - public override void CheckReflect(Mobile caster, ref bool reflect) - { - reflect = true; // Every spell is reflected back to the caster - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Ore Elementals/DullCopperElemental.cs b/Projects/UOContent/Mobiles/Monsters/Ore Elementals/DullCopperElemental.cs index a2556a71e..6ba9e2e5d 100644 --- a/Projects/UOContent/Mobiles/Monsters/Ore Elementals/DullCopperElemental.cs +++ b/Projects/UOContent/Mobiles/Monsters/Ore Elementals/DullCopperElemental.cs @@ -2,71 +2,71 @@ using Server.Items; namespace Server.Mobiles { - public class DullCopperElemental : BaseCreature - { - [Constructible] - public DullCopperElemental(int oreAmount = 2) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class DullCopperElemental : BaseCreature { - Body = 110; - BaseSoundID = 268; + [Constructible] + public DullCopperElemental(int oreAmount = 2) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 110; + BaseSoundID = 268; - SetStr(226, 255); - SetDex(126, 145); - SetInt(71, 92); + SetStr(226, 255); + SetDex(126, 145); + SetInt(71, 92); - SetHits(136, 153); + SetHits(136, 153); - SetDamage(9, 16); + SetDamage(9, 16); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 30, 40); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 10, 20); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 20, 30); + SetResistance(ResistanceType.Physical, 30, 40); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 20, 30); - SetSkill(SkillName.MagicResist, 50.1, 95.0); - SetSkill(SkillName.Tactics, 60.1, 100.0); - SetSkill(SkillName.Wrestling, 60.1, 100.0); + SetSkill(SkillName.MagicResist, 50.1, 95.0); + SetSkill(SkillName.Tactics, 60.1, 100.0); + SetSkill(SkillName.Wrestling, 60.1, 100.0); - Fame = 3500; - Karma = -3500; + Fame = 3500; + Karma = -3500; - VirtualArmor = 20; + VirtualArmor = 20; - Item ore = new DullCopperOre(oreAmount); - ore.ItemID = 0x19B9; - PackItem(ore); + Item ore = new DullCopperOre(oreAmount); + ore.ItemID = 0x19B9; + PackItem(ore); + } + + public DullCopperElemental(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ore elemental corpse"; + public override string DefaultName => "a dull copper elemental"; + + public override bool AutoDispel => true; + public override bool BleedImmune => true; + public override int TreasureMapLevel => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Gems, 2); + } + + 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(); + } } - - public DullCopperElemental(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ore elemental corpse"; - public override string DefaultName => "a dull copper elemental"; - - public override bool AutoDispel => true; - public override bool BleedImmune => true; - public override int TreasureMapLevel => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Gems, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Ore Elementals/GoldenElemental.cs b/Projects/UOContent/Mobiles/Monsters/Ore Elementals/GoldenElemental.cs index c8c47fb1f..b412dc8de 100644 --- a/Projects/UOContent/Mobiles/Monsters/Ore Elementals/GoldenElemental.cs +++ b/Projects/UOContent/Mobiles/Monsters/Ore Elementals/GoldenElemental.cs @@ -2,71 +2,71 @@ using Server.Items; namespace Server.Mobiles { - public class GoldenElemental : BaseCreature - { - [Constructible] - public GoldenElemental(int oreAmount = 2) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class GoldenElemental : BaseCreature { - Body = 166; - BaseSoundID = 268; + [Constructible] + public GoldenElemental(int oreAmount = 2) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 166; + BaseSoundID = 268; - SetStr(226, 255); - SetDex(126, 145); - SetInt(71, 92); + SetStr(226, 255); + SetDex(126, 145); + SetInt(71, 92); - SetHits(136, 153); + SetHits(136, 153); - SetDamage(9, 16); + SetDamage(9, 16); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 60, 75); - SetResistance(ResistanceType.Fire, 10, 20); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 60, 75); + SetResistance(ResistanceType.Fire, 10, 20); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.MagicResist, 50.1, 95.0); - SetSkill(SkillName.Tactics, 60.1, 100.0); - SetSkill(SkillName.Wrestling, 60.1, 100.0); + SetSkill(SkillName.MagicResist, 50.1, 95.0); + SetSkill(SkillName.Tactics, 60.1, 100.0); + SetSkill(SkillName.Wrestling, 60.1, 100.0); - Fame = 3500; - Karma = -3500; + Fame = 3500; + Karma = -3500; - VirtualArmor = 60; + VirtualArmor = 60; - Item ore = new GoldOre(oreAmount); - ore.ItemID = 0x19B9; - PackItem(ore); + Item ore = new GoldOre(oreAmount); + ore.ItemID = 0x19B9; + PackItem(ore); + } + + public GoldenElemental(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ore elemental corpse"; + public override string DefaultName => "a golden elemental"; + + public override bool AutoDispel => true; + public override bool BleedImmune => true; + public override int TreasureMapLevel => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Gems, 2); + } + + 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(); + } } - - public GoldenElemental(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ore elemental corpse"; - public override string DefaultName => "a golden elemental"; - - public override bool AutoDispel => true; - public override bool BleedImmune => true; - public override int TreasureMapLevel => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Gems, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Ore Elementals/ShadowIronElemental.cs b/Projects/UOContent/Mobiles/Monsters/Ore Elementals/ShadowIronElemental.cs index 19dd65aa2..74caf790b 100644 --- a/Projects/UOContent/Mobiles/Monsters/Ore Elementals/ShadowIronElemental.cs +++ b/Projects/UOContent/Mobiles/Monsters/Ore Elementals/ShadowIronElemental.cs @@ -2,89 +2,89 @@ using Server.Items; namespace Server.Mobiles { - public class ShadowIronElemental : BaseCreature - { - [Constructible] - public ShadowIronElemental(int oreAmount = 2) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class ShadowIronElemental : BaseCreature { - Body = 111; - BaseSoundID = 268; + [Constructible] + public ShadowIronElemental(int oreAmount = 2) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 111; + BaseSoundID = 268; - SetStr(226, 255); - SetDex(126, 145); - SetInt(71, 92); + SetStr(226, 255); + SetDex(126, 145); + SetInt(71, 92); - SetHits(136, 153); + SetHits(136, 153); - SetDamage(9, 16); + SetDamage(9, 16); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 30, 40); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 20, 30); - SetResistance(ResistanceType.Poison, 10, 20); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 30, 40); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 20, 30); + SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.MagicResist, 50.1, 95.0); - SetSkill(SkillName.Tactics, 60.1, 100.0); - SetSkill(SkillName.Wrestling, 60.1, 100.0); + SetSkill(SkillName.MagicResist, 50.1, 95.0); + SetSkill(SkillName.Tactics, 60.1, 100.0); + SetSkill(SkillName.Wrestling, 60.1, 100.0); - Fame = 4500; - Karma = -4500; + Fame = 4500; + Karma = -4500; - VirtualArmor = 23; + VirtualArmor = 23; - Item ore = new ShadowIronOre(oreAmount); - ore.ItemID = 0x19B9; - PackItem(ore); + Item ore = new ShadowIronOre(oreAmount); + ore.ItemID = 0x19B9; + PackItem(ore); + } + + public ShadowIronElemental(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ore elemental corpse"; + public override string DefaultName => "a shadow iron elemental"; + + public override bool AutoDispel => true; + public override bool BleedImmune => true; + public override int TreasureMapLevel => 1; + public override Poison PoisonImmune => Poison.Deadly; + public override bool BreathImmune => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Gems, 2); + } + + public override void AlterMeleeDamageFrom(Mobile from, ref int damage) + { + if (from is BaseCreature bc && (bc.Controlled || bc.BardTarget == this)) + damage = 0; // Immune to pets and provoked creatures + } + + public override void AlterDamageScalarFrom(Mobile caster, ref double scalar) + { + scalar = 0.0; // Immune to magic + } + + public override void AlterSpellDamageFrom(Mobile from, ref int damage) + { + damage = 0; + } + + 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(); + } } - - public ShadowIronElemental(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ore elemental corpse"; - public override string DefaultName => "a shadow iron elemental"; - - public override bool AutoDispel => true; - public override bool BleedImmune => true; - public override int TreasureMapLevel => 1; - public override Poison PoisonImmune => Poison.Deadly; - public override bool BreathImmune => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Gems, 2); - } - - public override void AlterMeleeDamageFrom(Mobile from, ref int damage) - { - if (from is BaseCreature bc && (bc.Controlled || bc.BardTarget == this)) - damage = 0; // Immune to pets and provoked creatures - } - - public override void AlterDamageScalarFrom(Mobile caster, ref double scalar) - { - scalar = 0.0; // Immune to magic - } - - public override void AlterSpellDamageFrom(Mobile from, ref int damage) - { - damage = 0; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Ore Elementals/ValoriteElemental.cs b/Projects/UOContent/Mobiles/Monsters/Ore Elementals/ValoriteElemental.cs index 70904ba3f..879f44ef1 100644 --- a/Projects/UOContent/Mobiles/Monsters/Ore Elementals/ValoriteElemental.cs +++ b/Projects/UOContent/Mobiles/Monsters/Ore Elementals/ValoriteElemental.cs @@ -2,87 +2,87 @@ using Server.Items; namespace Server.Mobiles { - public class ValoriteElemental : BaseCreature - { - [Constructible] - public ValoriteElemental(int oreAmount = 2) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class ValoriteElemental : BaseCreature { - // TODO: Gas attack - Body = 112; - BaseSoundID = 268; + [Constructible] + public ValoriteElemental(int oreAmount = 2) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + // TODO: Gas attack + Body = 112; + BaseSoundID = 268; - SetStr(226, 255); - SetDex(126, 145); - SetInt(71, 92); + SetStr(226, 255); + SetDex(126, 145); + SetInt(71, 92); - SetHits(136, 153); + SetHits(136, 153); - SetDamage(28); + SetDamage(28); - SetDamageType(ResistanceType.Physical, 25); - SetDamageType(ResistanceType.Fire, 25); - SetDamageType(ResistanceType.Cold, 25); - SetDamageType(ResistanceType.Energy, 25); + SetDamageType(ResistanceType.Physical, 25); + SetDamageType(ResistanceType.Fire, 25); + SetDamageType(ResistanceType.Cold, 25); + SetDamageType(ResistanceType.Energy, 25); - SetResistance(ResistanceType.Physical, 65, 75); - SetResistance(ResistanceType.Fire, 50, 60); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 50, 60); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 65, 75); + SetResistance(ResistanceType.Fire, 50, 60); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 50, 60); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.MagicResist, 50.1, 95.0); - SetSkill(SkillName.Tactics, 60.1, 100.0); - SetSkill(SkillName.Wrestling, 60.1, 100.0); + SetSkill(SkillName.MagicResist, 50.1, 95.0); + SetSkill(SkillName.Tactics, 60.1, 100.0); + SetSkill(SkillName.Wrestling, 60.1, 100.0); - Fame = 3500; - Karma = -3500; + Fame = 3500; + Karma = -3500; - VirtualArmor = 38; + VirtualArmor = 38; - Item ore = new ValoriteOre(oreAmount); - ore.ItemID = 0x19B9; - PackItem(ore); + Item ore = new ValoriteOre(oreAmount); + ore.ItemID = 0x19B9; + PackItem(ore); + } + + public ValoriteElemental(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ore elemental corpse"; + public override string DefaultName => "a valorite elemental"; + + public override bool AutoDispel => true; + public override bool BleedImmune => true; + public override int TreasureMapLevel => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.Gems, 4); + } + + public override void AlterMeleeDamageFrom(Mobile from, ref int damage) + { + if (from is BaseCreature bc) + if (bc.Controlled || bc.BardTarget == this) + damage = 0; // Immune to pets and provoked creatures + } + + public override void CheckReflect(Mobile caster, ref bool reflect) + { + reflect = true; // Every spell is reflected back to the caster + } + + 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(); + } } - - public ValoriteElemental(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ore elemental corpse"; - public override string DefaultName => "a valorite elemental"; - - public override bool AutoDispel => true; - public override bool BleedImmune => true; - public override int TreasureMapLevel => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.Gems, 4); - } - - public override void AlterMeleeDamageFrom(Mobile from, ref int damage) - { - if (from is BaseCreature bc) - if (bc.Controlled || bc.BardTarget == this) - damage = 0; // Immune to pets and provoked creatures - } - - public override void CheckReflect(Mobile caster, ref bool reflect) - { - reflect = true; // Every spell is reflected back to the caster - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Ore Elementals/VeriteElemental.cs b/Projects/UOContent/Mobiles/Monsters/Ore Elementals/VeriteElemental.cs index ec00c448e..23ecc6a0e 100644 --- a/Projects/UOContent/Mobiles/Monsters/Ore Elementals/VeriteElemental.cs +++ b/Projects/UOContent/Mobiles/Monsters/Ore Elementals/VeriteElemental.cs @@ -2,72 +2,72 @@ using Server.Items; namespace Server.Mobiles { - public class VeriteElemental : BaseCreature - { - [Constructible] - public VeriteElemental(int oreAmount = 2) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class VeriteElemental : BaseCreature { - Body = 113; - BaseSoundID = 268; + [Constructible] + public VeriteElemental(int oreAmount = 2) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 113; + BaseSoundID = 268; - SetStr(226, 255); - SetDex(126, 145); - SetInt(71, 92); + SetStr(226, 255); + SetDex(126, 145); + SetInt(71, 92); - SetHits(136, 153); + SetHits(136, 153); - SetDamage(9, 16); + SetDamage(9, 16); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Energy, 50); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Energy, 50); - SetResistance(ResistanceType.Physical, 30, 40); - SetResistance(ResistanceType.Fire, 10, 20); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 50, 60); - SetResistance(ResistanceType.Energy, 50, 60); + SetResistance(ResistanceType.Physical, 30, 40); + SetResistance(ResistanceType.Fire, 10, 20); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 50, 60); + SetResistance(ResistanceType.Energy, 50, 60); - SetSkill(SkillName.MagicResist, 50.1, 95.0); - SetSkill(SkillName.Tactics, 60.1, 100.0); - SetSkill(SkillName.Wrestling, 60.1, 100.0); + SetSkill(SkillName.MagicResist, 50.1, 95.0); + SetSkill(SkillName.Tactics, 60.1, 100.0); + SetSkill(SkillName.Wrestling, 60.1, 100.0); - Fame = 3500; - Karma = -3500; + Fame = 3500; + Karma = -3500; - VirtualArmor = 35; + VirtualArmor = 35; - Item ore = new VeriteOre(oreAmount); - ore.ItemID = 0x19B9; - PackItem(ore); + Item ore = new VeriteOre(oreAmount); + ore.ItemID = 0x19B9; + PackItem(ore); + } + + public VeriteElemental(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ore elemental corpse"; + public override string DefaultName => "a verite elemental"; + + public override bool AutoDispel => true; + public override bool BleedImmune => true; + public override int TreasureMapLevel => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.Gems, 2); + } + + 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(); + } } - - public VeriteElemental(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ore elemental corpse"; - public override string DefaultName => "a verite elemental"; - - public override bool AutoDispel => true; - public override bool BleedImmune => true; - public override int TreasureMapLevel => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.Gems, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Plant/Magic/Reaper.cs b/Projects/UOContent/Mobiles/Monsters/Plant/Magic/Reaper.cs index cbb65f89b..ce16242dc 100644 --- a/Projects/UOContent/Mobiles/Monsters/Plant/Magic/Reaper.cs +++ b/Projects/UOContent/Mobiles/Monsters/Plant/Magic/Reaper.cs @@ -2,73 +2,73 @@ using Server.Items; namespace Server.Mobiles { - public class Reaper : BaseCreature - { - [Constructible] - public Reaper() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Reaper : BaseCreature { - Body = 47; - BaseSoundID = 442; + [Constructible] + public Reaper() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 47; + BaseSoundID = 442; - SetStr(66, 215); - SetDex(66, 75); - SetInt(101, 250); + SetStr(66, 215); + SetDex(66, 75); + SetInt(101, 250); - SetHits(40, 129); - SetStam(0); + SetHits(40, 129); + SetStam(0); - SetDamage(9, 11); + SetDamage(9, 11); - SetDamageType(ResistanceType.Physical, 80); - SetDamageType(ResistanceType.Poison, 20); + SetDamageType(ResistanceType.Physical, 80); + SetDamageType(ResistanceType.Poison, 20); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 15, 25); - SetResistance(ResistanceType.Cold, 10, 20); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 15, 25); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.EvalInt, 90.1, 100.0); - SetSkill(SkillName.Magery, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 100.1, 125.0); - SetSkill(SkillName.Tactics, 45.1, 60.0); - SetSkill(SkillName.Wrestling, 50.1, 60.0); + SetSkill(SkillName.EvalInt, 90.1, 100.0); + SetSkill(SkillName.Magery, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 100.1, 125.0); + SetSkill(SkillName.Tactics, 45.1, 60.0); + SetSkill(SkillName.Wrestling, 50.1, 60.0); - Fame = 3500; - Karma = -3500; + Fame = 3500; + Karma = -3500; - VirtualArmor = 40; + VirtualArmor = 40; - PackItem(new Log(10)); - PackItem(new MandrakeRoot(5)); + PackItem(new Log(10)); + PackItem(new MandrakeRoot(5)); + } + + public Reaper(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a reapers corpse"; + public override string DefaultName => "a reaper"; + + public override Poison PoisonImmune => Poison.Greater; + public override int TreasureMapLevel => 2; + public override bool DisallowAllMoves => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + } + + 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(); + } } - - public Reaper(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a reapers corpse"; - public override string DefaultName => "a reaper"; - - public override Poison PoisonImmune => Poison.Greater; - public override int TreasureMapLevel => 2; - public override bool DisallowAllMoves => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Plant/Melee/BogThing.cs b/Projects/UOContent/Mobiles/Monsters/Plant/Melee/BogThing.cs index 685facc85..24f017335 100644 --- a/Projects/UOContent/Mobiles/Monsters/Plant/Melee/BogThing.cs +++ b/Projects/UOContent/Mobiles/Monsters/Plant/Melee/BogThing.cs @@ -3,124 +3,126 @@ using Server.Items; namespace Server.Mobiles { - public class BogThing : BaseCreature - { - [Constructible] - public BogThing() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.6, 1.2) + public class BogThing : BaseCreature { - Body = 780; - - SetStr(801, 900); - SetDex(46, 65); - SetInt(36, 50); - - SetHits(481, 540); - SetMana(0); - - SetDamage(10, 23); - - SetDamageType(ResistanceType.Physical, 60); - SetDamageType(ResistanceType.Poison, 40); - - SetResistance(ResistanceType.Physical, 30, 40); - SetResistance(ResistanceType.Fire, 20, 25); - SetResistance(ResistanceType.Cold, 10, 15); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 20, 25); - - SetSkill(SkillName.MagicResist, 90.1, 95.0); - SetSkill(SkillName.Tactics, 70.1, 85.0); - SetSkill(SkillName.Wrestling, 65.1, 80.0); - - Fame = 8000; - Karma = -8000; - - VirtualArmor = 28; - - if (Utility.RandomDouble() < 0.25) - PackItem(new Board(10)); - else - PackItem(new Log(10)); - - PackReg(3); - PackItem(new Seed()); - PackItem(new Seed()); - } - - public BogThing(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a plant corpse"; - public override string DefaultName => "a bog thing"; - - public override bool BardImmune => !Core.AOS; - public override Poison PoisonImmune => Poison.Lethal; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - - public void SpawnBogling(Mobile m) - { - Map map = Map; - - if (map == null) - return; - - Bogling spawned = new Bogling { Team = Team }; - - spawned.MoveToWorld(map.GetRandomNearbyLocation(Location), map); - spawned.Combatant = m; - } - - public void EatBoglings() - { - IPooledEnumerable eable = GetMobilesInRange(2); - bool sound = true; - - foreach (Bogling bogling in eable) - { - if (Hits >= HitsMax) - break; - - if (sound) + [Constructible] + public BogThing() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.6, 1.2) { - PlaySound(Utility.Random(0x3B, 2)); // Eat sound - sound = false; + Body = 780; + + SetStr(801, 900); + SetDex(46, 65); + SetInt(36, 50); + + SetHits(481, 540); + SetMana(0); + + SetDamage(10, 23); + + SetDamageType(ResistanceType.Physical, 60); + SetDamageType(ResistanceType.Poison, 40); + + SetResistance(ResistanceType.Physical, 30, 40); + SetResistance(ResistanceType.Fire, 20, 25); + SetResistance(ResistanceType.Cold, 10, 15); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 20, 25); + + SetSkill(SkillName.MagicResist, 90.1, 95.0); + SetSkill(SkillName.Tactics, 70.1, 85.0); + SetSkill(SkillName.Wrestling, 65.1, 80.0); + + Fame = 8000; + Karma = -8000; + + VirtualArmor = 28; + + if (Utility.RandomDouble() < 0.25) + PackItem(new Board(10)); + else + PackItem(new Log(10)); + + PackReg(3); + PackItem(new Seed()); + PackItem(new Seed()); } - Hits += bogling.Hits / 2; - bogling.Delete(); - } + public BogThing(Serial serial) : base(serial) + { + } - eable.Free(); + public override string CorpseName => "a plant corpse"; + public override string DefaultName => "a bog thing"; + + public override bool BardImmune => !Core.AOS; + public override Poison PoisonImmune => Poison.Lethal; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average, 2); + } + + 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(); + } + + public void SpawnBogling(Mobile m) + { + var map = Map; + + if (map == null) + return; + + var spawned = new Bogling { Team = Team }; + + spawned.MoveToWorld(map.GetRandomNearbyLocation(Location), map); + spawned.Combatant = m; + } + + public void EatBoglings() + { + var eable = GetMobilesInRange(2); + var sound = true; + + foreach (var bogling in eable) + { + if (Hits >= HitsMax) + break; + + if (sound) + { + PlaySound(Utility.Random(0x3B, 2)); // Eat sound + sound = false; + } + + Hits += bogling.Hits / 2; + bogling.Delete(); + } + + eable.Free(); + } + + public override void OnGotMeleeAttack(Mobile attacker) + { + base.OnGotMeleeAttack(attacker); + + if (Hits > HitsMax / 4) + { + if (Utility.RandomDouble() <= 0.25) + SpawnBogling(attacker); + } + else if (Utility.RandomDouble() <= 0.25) + { + EatBoglings(); + } + } } - - public override void OnGotMeleeAttack(Mobile attacker) - { - base.OnGotMeleeAttack(attacker); - - if (Hits > HitsMax / 4) - { - if (Utility.RandomDouble() <= 0.25) - SpawnBogling(attacker); - } - else if (Utility.RandomDouble() <= 0.25) - EatBoglings(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Plant/Melee/Bogling.cs b/Projects/UOContent/Mobiles/Monsters/Plant/Melee/Bogling.cs index e0e9f3874..acfc3cfae 100644 --- a/Projects/UOContent/Mobiles/Monsters/Plant/Melee/Bogling.cs +++ b/Projects/UOContent/Mobiles/Monsters/Plant/Melee/Bogling.cs @@ -3,68 +3,68 @@ using Server.Items; namespace Server.Mobiles { - public class Bogling : BaseCreature - { - [Constructible] - public Bogling() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Bogling : BaseCreature { - Body = 779; - BaseSoundID = 422; + [Constructible] + public Bogling() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 779; + BaseSoundID = 422; - SetStr(96, 120); - SetDex(91, 115); - SetInt(21, 45); + SetStr(96, 120); + SetDex(91, 115); + SetInt(21, 45); - SetHits(58, 72); + SetHits(58, 72); - SetDamage(5, 7); + SetDamage(5, 7); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 20, 25); - SetResistance(ResistanceType.Fire, 10, 20); - SetResistance(ResistanceType.Cold, 15, 25); - SetResistance(ResistanceType.Poison, 15, 25); - SetResistance(ResistanceType.Energy, 15, 25); + SetResistance(ResistanceType.Physical, 20, 25); + SetResistance(ResistanceType.Fire, 10, 20); + SetResistance(ResistanceType.Cold, 15, 25); + SetResistance(ResistanceType.Poison, 15, 25); + SetResistance(ResistanceType.Energy, 15, 25); - SetSkill(SkillName.MagicResist, 75.1, 100.0); - SetSkill(SkillName.Tactics, 55.1, 80.0); - SetSkill(SkillName.Wrestling, 55.1, 75.0); + SetSkill(SkillName.MagicResist, 75.1, 100.0); + SetSkill(SkillName.Tactics, 55.1, 80.0); + SetSkill(SkillName.Wrestling, 55.1, 75.0); - Fame = 450; - Karma = -450; + Fame = 450; + Karma = -450; - VirtualArmor = 28; + VirtualArmor = 28; - PackItem(new Log(4)); - PackItem(new Seed()); + PackItem(new Log(4)); + PackItem(new Seed()); + } + + public Bogling(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a plant corpse"; + public override string DefaultName => "a bogling"; + + public override int Hides => 6; + public override int Meat => 1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + 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(); + } } - - public Bogling(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a plant corpse"; - public override string DefaultName => "a bogling"; - - public override int Hides => 6; - public override int Meat => 1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Plant/Melee/Corpser.cs b/Projects/UOContent/Mobiles/Monsters/Plant/Melee/Corpser.cs index e2830ed17..3ec4eedb0 100644 --- a/Projects/UOContent/Mobiles/Monsters/Plant/Melee/Corpser.cs +++ b/Projects/UOContent/Mobiles/Monsters/Plant/Melee/Corpser.cs @@ -2,76 +2,76 @@ using Server.Items; namespace Server.Mobiles { - public class Corpser : BaseCreature - { - [Constructible] - public Corpser() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Corpser : BaseCreature { - Body = 8; - BaseSoundID = 684; + [Constructible] + public Corpser() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 8; + BaseSoundID = 684; - SetStr(156, 180); - SetDex(26, 45); - SetInt(26, 40); + SetStr(156, 180); + SetDex(26, 45); + SetInt(26, 40); - SetHits(94, 108); - SetMana(0); + SetHits(94, 108); + SetMana(0); - SetDamage(10, 23); + SetDamage(10, 23); - SetDamageType(ResistanceType.Physical, 60); - SetDamageType(ResistanceType.Poison, 40); + SetDamageType(ResistanceType.Physical, 60); + SetDamageType(ResistanceType.Poison, 40); - SetResistance(ResistanceType.Physical, 15, 20); - SetResistance(ResistanceType.Fire, 15, 25); - SetResistance(ResistanceType.Cold, 10, 20); - SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Physical, 15, 20); + SetResistance(ResistanceType.Fire, 15, 25); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Poison, 20, 30); - SetSkill(SkillName.MagicResist, 15.1, 20.0); - SetSkill(SkillName.Tactics, 45.1, 60.0); - SetSkill(SkillName.Wrestling, 45.1, 60.0); + SetSkill(SkillName.MagicResist, 15.1, 20.0); + SetSkill(SkillName.Tactics, 45.1, 60.0); + SetSkill(SkillName.Wrestling, 45.1, 60.0); - Fame = 1000; - Karma = -1000; + Fame = 1000; + Karma = -1000; - VirtualArmor = 18; + VirtualArmor = 18; - if (Utility.RandomDouble() < 0.25) - PackItem(new Board(10)); - else - PackItem(new Log(10)); + if (Utility.RandomDouble() < 0.25) + PackItem(new Board(10)); + else + PackItem(new Log(10)); - PackItem(new MandrakeRoot(3)); + PackItem(new MandrakeRoot(3)); + } + + public Corpser(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a corpser corpse"; + public override string DefaultName => "a corpser"; + + public override Poison PoisonImmune => Poison.Lesser; + public override bool DisallowAllMoves => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + 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 (BaseSoundID == 352) + BaseSoundID = 684; + } } - - public Corpser(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a corpser corpse"; - public override string DefaultName => "a corpser"; - - public override Poison PoisonImmune => Poison.Lesser; - public override bool DisallowAllMoves => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (BaseSoundID == 352) - BaseSoundID = 684; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Plant/Melee/Quagmire.cs b/Projects/UOContent/Mobiles/Monsters/Plant/Melee/Quagmire.cs index b244ce12e..eda42b053 100644 --- a/Projects/UOContent/Mobiles/Monsters/Plant/Melee/Quagmire.cs +++ b/Projects/UOContent/Mobiles/Monsters/Plant/Melee/Quagmire.cs @@ -1,71 +1,71 @@ namespace Server.Mobiles { - public class Quagmire : BaseCreature - { - [Constructible] - public Quagmire() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.4, 0.8) + public class Quagmire : BaseCreature { - Body = 789; - BaseSoundID = 352; + [Constructible] + public Quagmire() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.4, 0.8) + { + Body = 789; + BaseSoundID = 352; - SetStr(101, 130); - SetDex(66, 85); - SetInt(31, 55); + SetStr(101, 130); + SetDex(66, 85); + SetInt(31, 55); - SetHits(91, 105); + SetHits(91, 105); - SetDamage(10, 14); + SetDamage(10, 14); - SetDamageType(ResistanceType.Physical, 60); - SetDamageType(ResistanceType.Poison, 40); + SetDamageType(ResistanceType.Physical, 60); + SetDamageType(ResistanceType.Poison, 40); - SetResistance(ResistanceType.Physical, 50, 60); - SetResistance(ResistanceType.Fire, 10, 20); - SetResistance(ResistanceType.Cold, 10, 20); - SetResistance(ResistanceType.Poison, 100); - SetResistance(ResistanceType.Energy, 20, 30); + SetResistance(ResistanceType.Physical, 50, 60); + SetResistance(ResistanceType.Fire, 10, 20); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Poison, 100); + SetResistance(ResistanceType.Energy, 20, 30); - SetSkill(SkillName.MagicResist, 65.1, 75.0); - SetSkill(SkillName.Tactics, 50.1, 60.0); - SetSkill(SkillName.Wrestling, 60.1, 80.0); + SetSkill(SkillName.MagicResist, 65.1, 75.0); + SetSkill(SkillName.Tactics, 50.1, 60.0); + SetSkill(SkillName.Wrestling, 60.1, 80.0); - Fame = 1500; - Karma = -1500; + Fame = 1500; + Karma = -1500; - VirtualArmor = 32; + VirtualArmor = 32; + } + + public Quagmire(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a quagmire corpse"; + public override string DefaultName => "a quagmire"; + + public override Poison PoisonImmune => Poison.Lethal; + public override Poison HitPoison => Poison.Lethal; + public override double HitPoisonChance => 0.1; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + } + + public override int GetAngerSound() => 353; + + 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 (BaseSoundID == -1) + BaseSoundID = 352; + } } - - public Quagmire(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a quagmire corpse"; - public override string DefaultName => "a quagmire"; - - public override Poison PoisonImmune => Poison.Lethal; - public override Poison HitPoison => Poison.Lethal; - public override double HitPoisonChance => 0.1; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - } - - public override int GetAngerSound() => 353; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (BaseSoundID == -1) - BaseSoundID = 352; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Plant/Melee/SwampTentacle.cs b/Projects/UOContent/Mobiles/Monsters/Plant/Melee/SwampTentacle.cs index a0a2d0db9..119bc2aa8 100644 --- a/Projects/UOContent/Mobiles/Monsters/Plant/Melee/SwampTentacle.cs +++ b/Projects/UOContent/Mobiles/Monsters/Plant/Melee/SwampTentacle.cs @@ -1,67 +1,67 @@ namespace Server.Mobiles { - public class SwampTentacle : BaseCreature - { - [Constructible] - public SwampTentacle() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class SwampTentacle : BaseCreature { - Body = 66; - BaseSoundID = 352; + [Constructible] + public SwampTentacle() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 66; + BaseSoundID = 352; - SetStr(96, 120); - SetDex(66, 85); - SetInt(16, 30); + SetStr(96, 120); + SetDex(66, 85); + SetInt(16, 30); - SetHits(58, 72); - SetMana(0); + SetHits(58, 72); + SetMana(0); - SetDamage(6, 12); + SetDamage(6, 12); - SetDamageType(ResistanceType.Physical, 40); - SetDamageType(ResistanceType.Poison, 60); + SetDamageType(ResistanceType.Physical, 40); + SetDamageType(ResistanceType.Poison, 60); - SetResistance(ResistanceType.Physical, 25, 35); - SetResistance(ResistanceType.Fire, 10, 20); - SetResistance(ResistanceType.Cold, 10, 20); - SetResistance(ResistanceType.Poison, 60, 80); - SetResistance(ResistanceType.Energy, 10, 20); + SetResistance(ResistanceType.Physical, 25, 35); + SetResistance(ResistanceType.Fire, 10, 20); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Poison, 60, 80); + SetResistance(ResistanceType.Energy, 10, 20); - SetSkill(SkillName.MagicResist, 15.1, 20.0); - SetSkill(SkillName.Tactics, 65.1, 80.0); - SetSkill(SkillName.Wrestling, 65.1, 80.0); + SetSkill(SkillName.MagicResist, 15.1, 20.0); + SetSkill(SkillName.Tactics, 65.1, 80.0); + SetSkill(SkillName.Wrestling, 65.1, 80.0); - Fame = 3000; - Karma = -3000; + Fame = 3000; + Karma = -3000; - VirtualArmor = 28; + VirtualArmor = 28; - PackReg(3); + PackReg(3); + } + + public SwampTentacle(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a swamp tentacle corpse"; + public override string DefaultName => "a swamp tentacle"; + + public override Poison PoisonImmune => Poison.Greater; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + } + + 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(); + } } - - public SwampTentacle(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a swamp tentacle corpse"; - public override string DefaultName => "a swamp tentacle"; - - public override Poison PoisonImmune => Poison.Greater; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Plant/Melee/WhippingVine.cs b/Projects/UOContent/Mobiles/Monsters/Plant/Melee/WhippingVine.cs index 57a40a01f..1c62490cd 100644 --- a/Projects/UOContent/Mobiles/Monsters/Plant/Melee/WhippingVine.cs +++ b/Projects/UOContent/Mobiles/Monsters/Plant/Melee/WhippingVine.cs @@ -2,70 +2,70 @@ using Server.Items; namespace Server.Mobiles { - public class WhippingVine : BaseCreature - { - [Constructible] - public WhippingVine() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class WhippingVine : BaseCreature { - Body = 8; - Hue = 0x851; - BaseSoundID = 352; + [Constructible] + public WhippingVine() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 8; + Hue = 0x851; + BaseSoundID = 352; - SetStr(251, 300); - SetDex(76, 100); - SetInt(26, 40); + SetStr(251, 300); + SetDex(76, 100); + SetInt(26, 40); - SetMana(0); + SetMana(0); - SetDamage(7, 25); + SetDamage(7, 25); - SetDamageType(ResistanceType.Physical, 70); - SetDamageType(ResistanceType.Poison, 30); + SetDamageType(ResistanceType.Physical, 70); + SetDamageType(ResistanceType.Poison, 30); - SetResistance(ResistanceType.Physical, 75, 85); - SetResistance(ResistanceType.Fire, 15, 25); - SetResistance(ResistanceType.Cold, 15, 25); - SetResistance(ResistanceType.Poison, 75, 85); - SetResistance(ResistanceType.Energy, 35, 45); + SetResistance(ResistanceType.Physical, 75, 85); + SetResistance(ResistanceType.Fire, 15, 25); + SetResistance(ResistanceType.Cold, 15, 25); + SetResistance(ResistanceType.Poison, 75, 85); + SetResistance(ResistanceType.Energy, 35, 45); - SetSkill(SkillName.MagicResist, 70.0); - SetSkill(SkillName.Tactics, 70.0); - SetSkill(SkillName.Wrestling, 70.0); + SetSkill(SkillName.MagicResist, 70.0); + SetSkill(SkillName.Tactics, 70.0); + SetSkill(SkillName.Wrestling, 70.0); - Fame = 1000; - Karma = -1000; + Fame = 1000; + Karma = -1000; - VirtualArmor = 45; + VirtualArmor = 45; - PackReg(3); - PackItem(new FertileDirt(Utility.RandomMinMax(1, 10))); + PackReg(3); + PackItem(new FertileDirt(Utility.RandomMinMax(1, 10))); - if (Utility.RandomDouble() <= 0.2) - PackItem(new ExecutionersCap()); + if (Utility.RandomDouble() <= 0.2) + PackItem(new ExecutionersCap()); - PackItem(new Vines()); + PackItem(new Vines()); + } + + public WhippingVine(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a whipping vine corpse"; + public override string DefaultName => "a whipping vine"; + + public override bool BardImmune => !Core.AOS; + public override Poison PoisonImmune => Poison.Lethal; + + 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(); + } } - - public WhippingVine(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a whipping vine corpse"; - public override string DefaultName => "a whipping vine"; - - public override bool BardImmune => !Core.AOS; - public override Poison PoisonImmune => Poison.Lethal; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/AncientWyrm.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/AncientWyrm.cs index f487e7d02..092ce3d13 100644 --- a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/AncientWyrm.cs +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/AncientWyrm.cs @@ -1,83 +1,83 @@ namespace Server.Mobiles { - public class AncientWyrm : BaseCreature - { - [Constructible] - public AncientWyrm() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class AncientWyrm : BaseCreature { - Body = 46; - BaseSoundID = 362; + [Constructible] + public AncientWyrm() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 46; + BaseSoundID = 362; - SetStr(1096, 1185); - SetDex(86, 175); - SetInt(686, 775); + SetStr(1096, 1185); + SetDex(86, 175); + SetInt(686, 775); - SetHits(658, 711); + SetHits(658, 711); - SetDamage(29, 35); + SetDamage(29, 35); - SetDamageType(ResistanceType.Physical, 75); - SetDamageType(ResistanceType.Fire, 25); + SetDamageType(ResistanceType.Physical, 75); + SetDamageType(ResistanceType.Fire, 25); - SetResistance(ResistanceType.Physical, 65, 75); - SetResistance(ResistanceType.Fire, 80, 90); - SetResistance(ResistanceType.Cold, 70, 80); - SetResistance(ResistanceType.Poison, 60, 70); - SetResistance(ResistanceType.Energy, 60, 70); + SetResistance(ResistanceType.Physical, 65, 75); + SetResistance(ResistanceType.Fire, 80, 90); + SetResistance(ResistanceType.Cold, 70, 80); + SetResistance(ResistanceType.Poison, 60, 70); + SetResistance(ResistanceType.Energy, 60, 70); - SetSkill(SkillName.EvalInt, 80.1, 100.0); - SetSkill(SkillName.Magery, 80.1, 100.0); - SetSkill(SkillName.Meditation, 52.5, 75.0); - SetSkill(SkillName.MagicResist, 100.5, 150.0); - SetSkill(SkillName.Tactics, 97.6, 100.0); - SetSkill(SkillName.Wrestling, 97.6, 100.0); + SetSkill(SkillName.EvalInt, 80.1, 100.0); + SetSkill(SkillName.Magery, 80.1, 100.0); + SetSkill(SkillName.Meditation, 52.5, 75.0); + SetSkill(SkillName.MagicResist, 100.5, 150.0); + SetSkill(SkillName.Tactics, 97.6, 100.0); + SetSkill(SkillName.Wrestling, 97.6, 100.0); - Fame = 22500; - Karma = -22500; + Fame = 22500; + Karma = -22500; - VirtualArmor = 70; + VirtualArmor = 70; + } + + public AncientWyrm(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a dragon corpse"; + public override string DefaultName => "an ancient wyrm"; + + public override bool ReacquireOnMovement => true; + public override bool HasBreath => true; // fire breath enabled + public override bool AutoDispel => true; + public override HideType HideType => HideType.Barbed; + public override int Hides => 40; + public override int Meat => 19; + public override int Scales => 12; + public override ScaleType ScaleType => (ScaleType)Utility.Random(4); + public override Poison PoisonImmune => Poison.Regular; + public override Poison HitPoison => Utility.RandomBool() ? Poison.Lesser : Poison.Regular; + public override int TreasureMapLevel => 5; + public override bool CanFly => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 3); + AddLoot(LootPack.Gems, 5); + } + + public override int GetIdleSound() => 0x2D3; + + public override int GetHurtSound() => 0x2D1; + + 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(); + } } - - public AncientWyrm(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a dragon corpse"; - public override string DefaultName => "an ancient wyrm"; - - public override bool ReacquireOnMovement => true; - public override bool HasBreath => true; // fire breath enabled - public override bool AutoDispel => true; - public override HideType HideType => HideType.Barbed; - public override int Hides => 40; - public override int Meat => 19; - public override int Scales => 12; - public override ScaleType ScaleType => (ScaleType)Utility.Random(4); - public override Poison PoisonImmune => Poison.Regular; - public override Poison HitPoison => Utility.RandomBool() ? Poison.Lesser : Poison.Regular; - public override int TreasureMapLevel => 5; - public override bool CanFly => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 3); - AddLoot(LootPack.Gems, 5); - } - - public override int GetIdleSound() => 0x2D3; - - public override int GetHurtSound() => 0x2D1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/DeepSeaSerpent.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/DeepSeaSerpent.cs index b1ae79c97..8218b19c0 100644 --- a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/DeepSeaSerpent.cs +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/DeepSeaSerpent.cs @@ -2,78 +2,78 @@ using Server.Items; namespace Server.Mobiles { - public class DeepSeaSerpent : BaseCreature - { - [Constructible] - public DeepSeaSerpent() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class DeepSeaSerpent : BaseCreature { - Body = 150; - BaseSoundID = 447; + [Constructible] + public DeepSeaSerpent() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 150; + BaseSoundID = 447; - Hue = Utility.Random(0x8A0, 5); + Hue = Utility.Random(0x8A0, 5); - SetStr(251, 425); - SetDex(87, 135); - SetInt(87, 155); + SetStr(251, 425); + SetDex(87, 135); + SetInt(87, 155); - SetHits(151, 255); + SetHits(151, 255); - SetDamage(6, 14); + SetDamage(6, 14); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 30, 40); - SetResistance(ResistanceType.Fire, 70, 80); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 15, 20); + SetResistance(ResistanceType.Physical, 30, 40); + SetResistance(ResistanceType.Fire, 70, 80); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 15, 20); - SetSkill(SkillName.MagicResist, 60.1, 75.0); - SetSkill(SkillName.Tactics, 60.1, 70.0); - SetSkill(SkillName.Wrestling, 60.1, 70.0); + SetSkill(SkillName.MagicResist, 60.1, 75.0); + SetSkill(SkillName.Tactics, 60.1, 70.0); + SetSkill(SkillName.Wrestling, 60.1, 70.0); - Fame = 6000; - Karma = -6000; + Fame = 6000; + Karma = -6000; - VirtualArmor = 60; - CanSwim = true; - CantWalk = true; + VirtualArmor = 60; + CanSwim = true; + CantWalk = true; - if (Utility.RandomBool()) - PackItem(new SulfurousAsh(4)); - else - PackItem(new BlackPearl(4)); + if (Utility.RandomBool()) + PackItem(new SulfurousAsh(4)); + else + PackItem(new BlackPearl(4)); - // PackItem( new SpecialFishingNet() ); + // PackItem( new SpecialFishingNet() ); + } + + public DeepSeaSerpent(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a deep sea serpents corpse"; + public override string DefaultName => "a deep sea serpent"; + + public override bool HasBreath => true; + public override int Meat => 1; + public override int Scales => 8; + public override ScaleType ScaleType => ScaleType.Blue; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + 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(); + } } - - public DeepSeaSerpent(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a deep sea serpents corpse"; - public override string DefaultName => "a deep sea serpent"; - - public override bool HasBreath => true; - public override int Meat => 1; - public override int Scales => 8; - public override ScaleType ScaleType => ScaleType.Blue; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/Dragon.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/Dragon.cs index 7c6c93a23..cfdd61f66 100644 --- a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/Dragon.cs +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/Dragon.cs @@ -1,81 +1,81 @@ namespace Server.Mobiles { - public class Dragon : BaseCreature - { - [Constructible] - public Dragon() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Dragon : BaseCreature { - Body = Utility.RandomList(12, 59); - BaseSoundID = 362; + [Constructible] + public Dragon() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = Utility.RandomList(12, 59); + BaseSoundID = 362; - SetStr(796, 825); - SetDex(86, 105); - SetInt(436, 475); + SetStr(796, 825); + SetDex(86, 105); + SetInt(436, 475); - SetHits(478, 495); + SetHits(478, 495); - SetDamage(16, 22); + SetDamage(16, 22); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 55, 65); - SetResistance(ResistanceType.Fire, 60, 70); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 25, 35); - SetResistance(ResistanceType.Energy, 35, 45); + SetResistance(ResistanceType.Physical, 55, 65); + SetResistance(ResistanceType.Fire, 60, 70); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 25, 35); + SetResistance(ResistanceType.Energy, 35, 45); - SetSkill(SkillName.EvalInt, 30.1, 40.0); - SetSkill(SkillName.Magery, 30.1, 40.0); - SetSkill(SkillName.MagicResist, 99.1, 100.0); - SetSkill(SkillName.Tactics, 97.6, 100.0); - SetSkill(SkillName.Wrestling, 90.1, 92.5); + SetSkill(SkillName.EvalInt, 30.1, 40.0); + SetSkill(SkillName.Magery, 30.1, 40.0); + SetSkill(SkillName.MagicResist, 99.1, 100.0); + SetSkill(SkillName.Tactics, 97.6, 100.0); + SetSkill(SkillName.Wrestling, 90.1, 92.5); - Fame = 15000; - Karma = -15000; + Fame = 15000; + Karma = -15000; - VirtualArmor = 60; + VirtualArmor = 60; - Tamable = true; - ControlSlots = 3; - MinTameSkill = 93.9; + Tamable = true; + ControlSlots = 3; + MinTameSkill = 93.9; + } + + public Dragon(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a dragon corpse"; + public override string DefaultName => "a dragon"; + + public override bool ReacquireOnMovement => !Controlled; + public override bool HasBreath => true; // fire breath enabled + public override bool AutoDispel => !Controlled; + public override int TreasureMapLevel => 4; + public override int Meat => 19; + public override int Hides => 20; + public override HideType HideType => HideType.Barbed; + public override int Scales => 7; + public override ScaleType ScaleType => Body == 12 ? ScaleType.Yellow : ScaleType.Red; + public override FoodType FavoriteFood => FoodType.Meat; + public override bool CanAngerOnTame => true; + public override bool CanFly => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 2); + AddLoot(LootPack.Gems, 8); + } + + 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(); + } } - - public Dragon(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a dragon corpse"; - public override string DefaultName => "a dragon"; - - public override bool ReacquireOnMovement => !Controlled; - public override bool HasBreath => true; // fire breath enabled - public override bool AutoDispel => !Controlled; - public override int TreasureMapLevel => 4; - public override int Meat => 19; - public override int Hides => 20; - public override HideType HideType => HideType.Barbed; - public override int Scales => 7; - public override ScaleType ScaleType => Body == 12 ? ScaleType.Yellow : ScaleType.Red; - public override FoodType FavoriteFood => FoodType.Meat; - public override bool CanAngerOnTame => true; - public override bool CanFly => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 2); - AddLoot(LootPack.Gems, 8); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/Leviathan.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/Leviathan.cs index e15c7e6df..ee77d2c31 100644 --- a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/Leviathan.cs +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/Leviathan.cs @@ -3,167 +3,168 @@ using Server.Items; namespace Server.Mobiles { - public class Leviathan : BaseCreature - { - [Constructible] - public Leviathan(Mobile fisher = null) : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Leviathan : BaseCreature { - Fisher = fisher; + [Constructible] + public Leviathan(Mobile fisher = null) : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Fisher = fisher; - // May not be OSI accurate; mostly copied from krakens - Body = 77; - BaseSoundID = 353; + // May not be OSI accurate; mostly copied from krakens + Body = 77; + BaseSoundID = 353; - Hue = 0x481; + Hue = 0x481; - SetStr(1000); - SetDex(501, 520); - SetInt(501, 515); + SetStr(1000); + SetDex(501, 520); + SetInt(501, 515); - SetHits(1500); + SetHits(1500); - SetDamage(25, 33); + SetDamage(25, 33); - SetDamageType(ResistanceType.Physical, 70); - SetDamageType(ResistanceType.Cold, 30); + SetDamageType(ResistanceType.Physical, 70); + SetDamageType(ResistanceType.Cold, 30); - SetResistance(ResistanceType.Physical, 55, 65); - SetResistance(ResistanceType.Fire, 45, 55); - SetResistance(ResistanceType.Cold, 45, 55); - SetResistance(ResistanceType.Poison, 35, 45); - SetResistance(ResistanceType.Energy, 25, 35); + SetResistance(ResistanceType.Physical, 55, 65); + SetResistance(ResistanceType.Fire, 45, 55); + SetResistance(ResistanceType.Cold, 45, 55); + SetResistance(ResistanceType.Poison, 35, 45); + SetResistance(ResistanceType.Energy, 25, 35); - SetSkill(SkillName.EvalInt, 97.6, 107.5); - SetSkill(SkillName.Magery, 97.6, 107.5); - SetSkill(SkillName.MagicResist, 97.6, 107.5); - SetSkill(SkillName.Meditation, 97.6, 107.5); - SetSkill(SkillName.Tactics, 97.6, 107.5); - SetSkill(SkillName.Wrestling, 97.6, 107.5); + SetSkill(SkillName.EvalInt, 97.6, 107.5); + SetSkill(SkillName.Magery, 97.6, 107.5); + SetSkill(SkillName.MagicResist, 97.6, 107.5); + SetSkill(SkillName.Meditation, 97.6, 107.5); + SetSkill(SkillName.Tactics, 97.6, 107.5); + SetSkill(SkillName.Wrestling, 97.6, 107.5); - Fame = 24000; - Karma = -24000; + Fame = 24000; + Karma = -24000; - VirtualArmor = 50; + VirtualArmor = 50; - CanSwim = true; - CantWalk = true; + CanSwim = true; + CantWalk = true; - PackItem(new MessageInABottle()); + PackItem(new MessageInABottle()); - Rope rope = new Rope(); - rope.ItemID = 0x14F8; - PackItem(rope); + var rope = new Rope(); + rope.ItemID = 0x14F8; + PackItem(rope); - rope = new Rope(); - rope.ItemID = 0x14FA; - PackItem(rope); + rope = new Rope(); + rope.ItemID = 0x14FA; + PackItem(rope); + } + + public Leviathan(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a leviathan corpse"; + + public Mobile Fisher { get; set; } + + public override string DefaultName => "a leviathan"; + + public override bool HasBreath => true; + public override int BreathPhysicalDamage => 70; // TODO: Verify damage type + public override int BreathColdDamage => 30; + public override int BreathFireDamage => 0; + public override int BreathEffectHue => 0x1ED; + public override double BreathDamageScalar => 0.05; + public override double BreathMinDelay => 5.0; + public override double BreathMaxDelay => 7.5; + + public override int TreasureMapLevel => 5; + + public static Type[] Artifacts { get; } = + { + // Decorations + typeof(CandelabraOfSouls), + typeof(GhostShipAnchor), + typeof(GoldBricks), + typeof(PhillipsWoodenSteed), + typeof(SeahorseStatuette), + typeof(ShipModelOfTheHMSCape), + typeof(AdmiralsHeartyRum), + + // Equipment + typeof(AlchemistsBauble), + typeof(ArcticDeathDealer), + typeof(BlazeOfDeath), + typeof(BurglarsBandana), + typeof(CaptainQuacklebushsCutlass), + typeof(CavortingClub), + typeof(DreadPirateHat), + typeof(EnchantedTitanLegBone), + typeof(GwennosHarp), + typeof(IolosLute), + typeof(LunaLance), + typeof(NightsKiss), + typeof(NoxRangersHeavyCrossbow), + typeof(PolarBearMask), + typeof(VioletCourage) + }; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 5); + } + + 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(); + } + + public static void GiveArtifactTo(Mobile m) + { + var item = Loot.Construct(Artifacts); + + if (item == null) + return; + + // TODO: Confirm messages + if (m.AddToBackpack(item)) + m.SendMessage("As a reward for slaying the mighty leviathan, an artifact has been placed in your backpack."); + else + m.SendMessage( + "As your backpack is full, your reward for destroying the legendary leviathan has been placed at your feet." + ); + } + + public override void OnKilledBy(Mobile mob) + { + base.OnKilledBy(mob); + + if (Paragon.CheckArtifactChance(mob, this)) + { + GiveArtifactTo(mob); + + if (mob == Fisher) + Fisher = null; + } + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + if (Fisher != null && Utility.Random(100) < 25) + GiveArtifactTo(Fisher); + + Fisher = null; + } } - - public Leviathan(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a leviathan corpse"; - - public Mobile Fisher { get; set; } - - public override string DefaultName => "a leviathan"; - - public override bool HasBreath => true; - public override int BreathPhysicalDamage => 70; // TODO: Verify damage type - public override int BreathColdDamage => 30; - public override int BreathFireDamage => 0; - public override int BreathEffectHue => 0x1ED; - public override double BreathDamageScalar => 0.05; - public override double BreathMinDelay => 5.0; - public override double BreathMaxDelay => 7.5; - - public override int TreasureMapLevel => 5; - - public static Type[] Artifacts { get; } = - { - // Decorations - typeof(CandelabraOfSouls), - typeof(GhostShipAnchor), - typeof(GoldBricks), - typeof(PhillipsWoodenSteed), - typeof(SeahorseStatuette), - typeof(ShipModelOfTheHMSCape), - typeof(AdmiralsHeartyRum), - - // Equipment - typeof(AlchemistsBauble), - typeof(ArcticDeathDealer), - typeof(BlazeOfDeath), - typeof(BurglarsBandana), - typeof(CaptainQuacklebushsCutlass), - typeof(CavortingClub), - typeof(DreadPirateHat), - typeof(EnchantedTitanLegBone), - typeof(GwennosHarp), - typeof(IolosLute), - typeof(LunaLance), - typeof(NightsKiss), - typeof(NoxRangersHeavyCrossbow), - typeof(PolarBearMask), - typeof(VioletCourage) - }; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 5); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public static void GiveArtifactTo(Mobile m) - { - Item item = Loot.Construct(Artifacts); - - if (item == null) - return; - - // TODO: Confirm messages - if (m.AddToBackpack(item)) - m.SendMessage("As a reward for slaying the mighty leviathan, an artifact has been placed in your backpack."); - else - m.SendMessage( - "As your backpack is full, your reward for destroying the legendary leviathan has been placed at your feet."); - } - - public override void OnKilledBy(Mobile mob) - { - base.OnKilledBy(mob); - - if (Paragon.CheckArtifactChance(mob, this)) - { - GiveArtifactTo(mob); - - if (mob == Fisher) - Fisher = null; - } - } - - public override void OnDeath(Container c) - { - base.OnDeath(c); - - if (Fisher != null && Utility.Random(100) < 25) - GiveArtifactTo(Fisher); - - Fisher = null; - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/OphidianArchmage.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/OphidianArchmage.cs index 3e17443ed..aee35bbdf 100644 --- a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/OphidianArchmage.cs +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/OphidianArchmage.cs @@ -1,79 +1,79 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.OphidianJusticar", "Server.Mobiles.OphidianZealot")] - public class OphidianArchmage : BaseCreature - { - private static readonly string[] m_Names = + [TypeAlias("Server.Mobiles.OphidianJusticar", "Server.Mobiles.OphidianZealot")] + public class OphidianArchmage : BaseCreature { - "an ophidian justicar", - "an ophidian zealot" - }; + private static readonly string[] m_Names = + { + "an ophidian justicar", + "an ophidian zealot" + }; - [Constructible] - public OphidianArchmage() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) - { - Name = m_Names.RandomElement(); - Body = 85; - BaseSoundID = 639; + [Constructible] + public OphidianArchmage() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Name = m_Names.RandomElement(); + Body = 85; + BaseSoundID = 639; - SetStr(281, 305); - SetDex(191, 215); - SetInt(226, 250); + SetStr(281, 305); + SetDex(191, 215); + SetInt(226, 250); - SetHits(169, 183); - SetStam(36, 45); + SetHits(169, 183); + SetStam(36, 45); - SetDamage(5, 10); + SetDamage(5, 10); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 40, 45); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 25, 35); - SetResistance(ResistanceType.Poison, 35, 40); - SetResistance(ResistanceType.Energy, 25, 35); + SetResistance(ResistanceType.Physical, 40, 45); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 25, 35); + SetResistance(ResistanceType.Poison, 35, 40); + SetResistance(ResistanceType.Energy, 25, 35); - SetSkill(SkillName.EvalInt, 95.1, 100.0); - SetSkill(SkillName.Magery, 95.1, 100.0); - SetSkill(SkillName.MagicResist, 75.0, 97.5); - SetSkill(SkillName.Tactics, 65.0, 87.5); - SetSkill(SkillName.Wrestling, 20.2, 60.0); + SetSkill(SkillName.EvalInt, 95.1, 100.0); + SetSkill(SkillName.Magery, 95.1, 100.0); + SetSkill(SkillName.MagicResist, 75.0, 97.5); + SetSkill(SkillName.Tactics, 65.0, 87.5); + SetSkill(SkillName.Wrestling, 20.2, 60.0); - Fame = 11500; - Karma = -11500; + Fame = 11500; + Karma = -11500; - VirtualArmor = 44; + VirtualArmor = 44; - PackReg(5, 15); - PackNecroReg(5, 15); + PackReg(5, 15); + PackNecroReg(5, 15); + } + + public OphidianArchmage(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ophidian corpse"; + + public override int Meat => 1; + + public override OppositionGroup OppositionGroup => OppositionGroup.TerathansAndOphidians; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.MedScrolls, 2); + } + + 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(); + } } - - public OphidianArchmage(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ophidian corpse"; - - public override int Meat => 1; - - public override OppositionGroup OppositionGroup => OppositionGroup.TerathansAndOphidians; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.MedScrolls, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/OphidianMage.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/OphidianMage.cs index c706a4ffd..ddbe1ad58 100644 --- a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/OphidianMage.cs +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/OphidianMage.cs @@ -1,80 +1,80 @@ namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.OphidianShaman")] - public class OphidianMage : BaseCreature - { - private static readonly string[] m_Names = + [TypeAlias("Server.Mobiles.OphidianShaman")] + public class OphidianMage : BaseCreature { - "an ophidian apprentice mage", - "an ophidian shaman" - }; + private static readonly string[] m_Names = + { + "an ophidian apprentice mage", + "an ophidian shaman" + }; - [Constructible] - public OphidianMage() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) - { - Name = m_Names.RandomElement(); - Body = 85; - BaseSoundID = 639; + [Constructible] + public OphidianMage() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Name = m_Names.RandomElement(); + Body = 85; + BaseSoundID = 639; - SetStr(181, 205); - SetDex(191, 215); - SetInt(96, 120); + SetStr(181, 205); + SetDex(191, 215); + SetInt(96, 120); - SetHits(109, 123); + SetHits(109, 123); - SetDamage(5, 10); + SetDamage(5, 10); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 25, 35); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 35, 45); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 35, 45); + SetResistance(ResistanceType.Physical, 25, 35); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 35, 45); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 35, 45); - SetSkill(SkillName.EvalInt, 85.1, 100.0); - SetSkill(SkillName.Magery, 85.1, 100.0); - SetSkill(SkillName.MagicResist, 75.0, 97.5); - SetSkill(SkillName.Tactics, 65.0, 87.5); - SetSkill(SkillName.Wrestling, 20.2, 60.0); + SetSkill(SkillName.EvalInt, 85.1, 100.0); + SetSkill(SkillName.Magery, 85.1, 100.0); + SetSkill(SkillName.MagicResist, 75.0, 97.5); + SetSkill(SkillName.Tactics, 65.0, 87.5); + SetSkill(SkillName.Wrestling, 20.2, 60.0); - Fame = 4000; - Karma = -4000; + Fame = 4000; + Karma = -4000; - VirtualArmor = 30; + VirtualArmor = 30; - PackReg(10); + PackReg(10); + } + + public OphidianMage(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ophidian corpse"; + + public override int Meat => 1; + public override int TreasureMapLevel => 2; + + public override OppositionGroup OppositionGroup => OppositionGroup.TerathansAndOphidians; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.LowScrolls); + AddLoot(LootPack.MedScrolls); + AddLoot(LootPack.Potions); + } + + 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(); + } } - - public OphidianMage(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ophidian corpse"; - - public override int Meat => 1; - public override int TreasureMapLevel => 2; - - public override OppositionGroup OppositionGroup => OppositionGroup.TerathansAndOphidians; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.LowScrolls); - AddLoot(LootPack.MedScrolls); - AddLoot(LootPack.Potions); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/OphidianMatriarch.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/OphidianMatriarch.cs index 1ee4de3cc..4847acc1d 100644 --- a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/OphidianMatriarch.cs +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/OphidianMatriarch.cs @@ -1,71 +1,71 @@ namespace Server.Mobiles { - public class OphidianMatriarch : BaseCreature - { - [Constructible] - public OphidianMatriarch() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class OphidianMatriarch : BaseCreature { - Body = 87; - BaseSoundID = 644; + [Constructible] + public OphidianMatriarch() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 87; + BaseSoundID = 644; - SetStr(416, 505); - SetDex(96, 115); - SetInt(366, 455); + SetStr(416, 505); + SetDex(96, 115); + SetInt(366, 455); - SetHits(250, 303); + SetHits(250, 303); - SetDamage(11, 13); + SetDamage(11, 13); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 35, 45); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 35, 45); + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 35, 45); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 35, 45); - SetSkill(SkillName.EvalInt, 90.1, 100.0); - SetSkill(SkillName.Magery, 90.1, 100.0); - SetSkill(SkillName.Meditation, 5.4, 25.0); - SetSkill(SkillName.MagicResist, 90.1, 100.0); - SetSkill(SkillName.Tactics, 50.1, 70.0); - SetSkill(SkillName.Wrestling, 60.1, 80.0); + SetSkill(SkillName.EvalInt, 90.1, 100.0); + SetSkill(SkillName.Magery, 90.1, 100.0); + SetSkill(SkillName.Meditation, 5.4, 25.0); + SetSkill(SkillName.MagicResist, 90.1, 100.0); + SetSkill(SkillName.Tactics, 50.1, 70.0); + SetSkill(SkillName.Wrestling, 60.1, 80.0); - Fame = 16000; - Karma = -16000; + Fame = 16000; + Karma = -16000; - VirtualArmor = 50; + VirtualArmor = 50; + } + + public OphidianMatriarch(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ophidian corpse"; + public override string DefaultName => "an ophidian matriarch"; + + public override Poison PoisonImmune => Poison.Greater; + public override int TreasureMapLevel => 4; + + public override OppositionGroup OppositionGroup => OppositionGroup.TerathansAndOphidians; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.Average, 2); + AddLoot(LootPack.MedScrolls, 2); + } + + 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(); + } } - - public OphidianMatriarch(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ophidian corpse"; - public override string DefaultName => "an ophidian matriarch"; - - public override Poison PoisonImmune => Poison.Greater; - public override int TreasureMapLevel => 4; - - public override OppositionGroup OppositionGroup => OppositionGroup.TerathansAndOphidians; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.Average, 2); - AddLoot(LootPack.MedScrolls, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/SeaSerpent.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/SeaSerpent.cs index e2fc7a14a..94c72b1e6 100644 --- a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/SeaSerpent.cs +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/SeaSerpent.cs @@ -2,84 +2,84 @@ using Server.Items; namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Seaserpant")] - public class SeaSerpent : BaseCreature - { - [Constructible] - public SeaSerpent() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Seaserpant")] + public class SeaSerpent : BaseCreature { - Body = 150; - BaseSoundID = 447; + [Constructible] + public SeaSerpent() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 150; + BaseSoundID = 447; - Hue = Utility.Random(0x530, 9); + Hue = Utility.Random(0x530, 9); - SetStr(168, 225); - SetDex(58, 85); - SetInt(53, 95); + SetStr(168, 225); + SetDex(58, 85); + SetInt(53, 95); - SetHits(110, 127); + SetHits(110, 127); - SetDamage(7, 13); + SetDamage(7, 13); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 25, 35); - SetResistance(ResistanceType.Fire, 50, 60); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 15, 20); + SetResistance(ResistanceType.Physical, 25, 35); + SetResistance(ResistanceType.Fire, 50, 60); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 15, 20); - SetSkill(SkillName.MagicResist, 60.1, 75.0); - SetSkill(SkillName.Tactics, 60.1, 70.0); - SetSkill(SkillName.Wrestling, 60.1, 70.0); + SetSkill(SkillName.MagicResist, 60.1, 75.0); + SetSkill(SkillName.Tactics, 60.1, 70.0); + SetSkill(SkillName.Wrestling, 60.1, 70.0); - Fame = 6000; - Karma = -6000; + Fame = 6000; + Karma = -6000; - VirtualArmor = 30; - CanSwim = true; - CantWalk = true; + VirtualArmor = 30; + CanSwim = true; + CantWalk = true; - if (Utility.RandomBool()) - PackItem(new SulfurousAsh(4)); - else - PackItem(new BlackPearl(4)); + if (Utility.RandomBool()) + PackItem(new SulfurousAsh(4)); + else + PackItem(new BlackPearl(4)); - PackItem(new RawFishSteak()); + PackItem(new RawFishSteak()); - // PackItem( new SpecialFishingNet() ); + // PackItem( new SpecialFishingNet() ); + } + + public SeaSerpent(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a sea serpents corpse"; + public override string DefaultName => "a sea serpent"; + + public override bool HasBreath => true; + public override int TreasureMapLevel => 2; + + public override int Hides => 10; + public override HideType HideType => HideType.Horned; + public override int Scales => 8; + public override ScaleType ScaleType => ScaleType.Blue; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + 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(); + } } - - public SeaSerpent(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a sea serpents corpse"; - public override string DefaultName => "a sea serpent"; - - public override bool HasBreath => true; - public override int TreasureMapLevel => 2; - - public override int Hides => 10; - public override HideType HideType => HideType.Horned; - public override int Scales => 8; - public override ScaleType ScaleType => ScaleType.Blue; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/SerpentineDragon.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/SerpentineDragon.cs index be71a3be0..45d562f14 100644 --- a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/SerpentineDragon.cs +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/SerpentineDragon.cs @@ -2,105 +2,105 @@ using Server.Engines.Plants; namespace Server.Mobiles { - public class SerpentineDragon : BaseCreature - { - [Constructible] - public SerpentineDragon() : base(AIType.AI_Mage, FightMode.Evil, 10, 1, 0.2, 0.4) + public class SerpentineDragon : BaseCreature { - Body = 103; - BaseSoundID = 362; + [Constructible] + public SerpentineDragon() : base(AIType.AI_Mage, FightMode.Evil, 10, 1, 0.2, 0.4) + { + Body = 103; + BaseSoundID = 362; - SetStr(111, 140); - SetDex(201, 220); - SetInt(1001, 1040); + SetStr(111, 140); + SetDex(201, 220); + SetInt(1001, 1040); - SetHits(480); + SetHits(480); - SetDamage(5, 12); + SetDamage(5, 12); - SetDamageType(ResistanceType.Physical, 75); - SetDamageType(ResistanceType.Poison, 25); + SetDamageType(ResistanceType.Physical, 75); + SetDamageType(ResistanceType.Poison, 25); - SetResistance(ResistanceType.Physical, 35, 40); - SetResistance(ResistanceType.Fire, 25, 35); - SetResistance(ResistanceType.Cold, 25, 35); - SetResistance(ResistanceType.Poison, 25, 35); - SetResistance(ResistanceType.Energy, 25, 35); + SetResistance(ResistanceType.Physical, 35, 40); + SetResistance(ResistanceType.Fire, 25, 35); + SetResistance(ResistanceType.Cold, 25, 35); + SetResistance(ResistanceType.Poison, 25, 35); + SetResistance(ResistanceType.Energy, 25, 35); - SetSkill(SkillName.EvalInt, 100.1, 110.0); - SetSkill(SkillName.Magery, 110.1, 120.0); - SetSkill(SkillName.Meditation, 100.0); - SetSkill(SkillName.MagicResist, 100.0); - SetSkill(SkillName.Tactics, 50.1, 60.0); - SetSkill(SkillName.Wrestling, 30.1, 100.0); + SetSkill(SkillName.EvalInt, 100.1, 110.0); + SetSkill(SkillName.Magery, 110.1, 120.0); + SetSkill(SkillName.Meditation, 100.0); + SetSkill(SkillName.MagicResist, 100.0); + SetSkill(SkillName.Tactics, 50.1, 60.0); + SetSkill(SkillName.Wrestling, 30.1, 100.0); - Fame = 15000; - Karma = 15000; + Fame = 15000; + Karma = 15000; - VirtualArmor = 36; + VirtualArmor = 36; - if (Core.ML && Utility.RandomDouble() < .33) - PackItem(Seed.RandomPeculiarSeed(2)); + if (Core.ML && Utility.RandomDouble() < .33) + PackItem(Seed.RandomPeculiarSeed(2)); + } + + public SerpentineDragon(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a dragon corpse"; + public override string DefaultName => "a serpentine dragon"; + + public override bool ReacquireOnMovement => true; + public override bool HasBreath => true; // fire breath enabled + public override double BonusPetDamageScalar => Core.SE ? 3.0 : 1.0; + + public override bool AutoDispel => true; + public override HideType HideType => HideType.Barbed; + public override int Hides => 20; + public override int Meat => 19; + public override int Scales => 6; + public override ScaleType ScaleType => Utility.RandomBool() ? ScaleType.Black : ScaleType.White; + public override int TreasureMapLevel => 4; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 2); + AddLoot(LootPack.Gems, 2); + } + + public override int GetIdleSound() => 0x2C4; + + public override int GetAttackSound() => 0x2C0; + + public override int GetDeathSound() => 0x2C1; + + public override int GetAngerSound() => 0x2C4; + + public override int GetHurtSound() => 0x2C3; + + public override void OnGotMeleeAttack(Mobile attacker) + { + base.OnGotMeleeAttack(attacker); + + if (!Core.SE && Utility.RandomDouble() < 0.2 && attacker is BaseCreature c && c.Controlled && + c.ControlMaster != null) + { + c.ControlTarget = c.ControlMaster; + c.ControlOrder = OrderType.Attack; + c.Combatant = c.ControlMaster; + } + } + + 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(); + } } - - public SerpentineDragon(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a dragon corpse"; - public override string DefaultName => "a serpentine dragon"; - - public override bool ReacquireOnMovement => true; - public override bool HasBreath => true; // fire breath enabled - public override double BonusPetDamageScalar => Core.SE ? 3.0 : 1.0; - - public override bool AutoDispel => true; - public override HideType HideType => HideType.Barbed; - public override int Hides => 20; - public override int Meat => 19; - public override int Scales => 6; - public override ScaleType ScaleType => Utility.RandomBool() ? ScaleType.Black : ScaleType.White; - public override int TreasureMapLevel => 4; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 2); - AddLoot(LootPack.Gems, 2); - } - - public override int GetIdleSound() => 0x2C4; - - public override int GetAttackSound() => 0x2C0; - - public override int GetDeathSound() => 0x2C1; - - public override int GetAngerSound() => 0x2C4; - - public override int GetHurtSound() => 0x2C3; - - public override void OnGotMeleeAttack(Mobile attacker) - { - base.OnGotMeleeAttack(attacker); - - if (!Core.SE && Utility.RandomDouble() < 0.2 && attacker is BaseCreature c && c.Controlled && - c.ControlMaster != null) - { - c.ControlTarget = c.ControlMaster; - c.ControlOrder = OrderType.Attack; - c.Combatant = c.ControlMaster; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/ShadowWyrm.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/ShadowWyrm.cs index e773f784b..3043112b4 100644 --- a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/ShadowWyrm.cs +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/ShadowWyrm.cs @@ -1,84 +1,84 @@ namespace Server.Mobiles { - public class ShadowWyrm : BaseCreature - { - [Constructible] - public ShadowWyrm() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class ShadowWyrm : BaseCreature { - Body = 106; - BaseSoundID = 362; + [Constructible] + public ShadowWyrm() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 106; + BaseSoundID = 362; - SetStr(898, 1030); - SetDex(68, 200); - SetInt(488, 620); + SetStr(898, 1030); + SetDex(68, 200); + SetInt(488, 620); - SetHits(558, 599); + SetHits(558, 599); - SetDamage(29, 35); + SetDamage(29, 35); - SetDamageType(ResistanceType.Physical, 75); - SetDamageType(ResistanceType.Cold, 25); + SetDamageType(ResistanceType.Physical, 75); + SetDamageType(ResistanceType.Cold, 25); - SetResistance(ResistanceType.Physical, 65, 75); - SetResistance(ResistanceType.Fire, 50, 60); - SetResistance(ResistanceType.Cold, 45, 55); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 50, 60); + SetResistance(ResistanceType.Physical, 65, 75); + SetResistance(ResistanceType.Fire, 50, 60); + SetResistance(ResistanceType.Cold, 45, 55); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 50, 60); - SetSkill(SkillName.EvalInt, 80.1, 100.0); - SetSkill(SkillName.Magery, 80.1, 100.0); - SetSkill(SkillName.Meditation, 52.5, 75.0); - SetSkill(SkillName.MagicResist, 100.3, 130.0); - SetSkill(SkillName.Tactics, 97.6, 100.0); - SetSkill(SkillName.Wrestling, 97.6, 100.0); + SetSkill(SkillName.EvalInt, 80.1, 100.0); + SetSkill(SkillName.Magery, 80.1, 100.0); + SetSkill(SkillName.Meditation, 52.5, 75.0); + SetSkill(SkillName.MagicResist, 100.3, 130.0); + SetSkill(SkillName.Tactics, 97.6, 100.0); + SetSkill(SkillName.Wrestling, 97.6, 100.0); - Fame = 22500; - Karma = -22500; + Fame = 22500; + Karma = -22500; - VirtualArmor = 70; + VirtualArmor = 70; + } + + public ShadowWyrm(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a shadow wyrm corpse"; + public override string DefaultName => "a shadow wyrm"; + + public override bool ReacquireOnMovement => true; + public override bool HasBreath => true; // fire breath enabled + public override bool AutoDispel => true; + public override Poison PoisonImmune => Poison.Deadly; + public override Poison HitPoison => Poison.Deadly; + public override int TreasureMapLevel => 5; + + public override int Meat => 19; + public override int Hides => 20; + public override int Scales => 10; + public override ScaleType ScaleType => ScaleType.Black; + public override HideType HideType => HideType.Barbed; + public override bool CanFly => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 3); + AddLoot(LootPack.Gems, 5); + } + + public override int GetIdleSound() => 0x2D5; + + public override int GetHurtSound() => 0x2D1; + + 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(); + } } - - public ShadowWyrm(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a shadow wyrm corpse"; - public override string DefaultName => "a shadow wyrm"; - - public override bool ReacquireOnMovement => true; - public override bool HasBreath => true; // fire breath enabled - public override bool AutoDispel => true; - public override Poison PoisonImmune => Poison.Deadly; - public override Poison HitPoison => Poison.Deadly; - public override int TreasureMapLevel => 5; - - public override int Meat => 19; - public override int Hides => 20; - public override int Scales => 10; - public override ScaleType ScaleType => ScaleType.Black; - public override HideType HideType => HideType.Barbed; - public override bool CanFly => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 3); - AddLoot(LootPack.Gems, 5); - } - - public override int GetIdleSound() => 0x2D5; - - public override int GetHurtSound() => 0x2D1; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/SkeletalDragon.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/SkeletalDragon.cs index f70306f6f..1ca9c3303 100644 --- a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/SkeletalDragon.cs +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/SkeletalDragon.cs @@ -1,83 +1,83 @@ namespace Server.Mobiles { - public class SkeletalDragon : BaseCreature - { - [Constructible] - public SkeletalDragon() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class SkeletalDragon : BaseCreature { - Body = 104; - BaseSoundID = 0x488; + [Constructible] + public SkeletalDragon() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 104; + BaseSoundID = 0x488; - SetStr(898, 1030); - SetDex(68, 200); - SetInt(488, 620); + SetStr(898, 1030); + SetDex(68, 200); + SetInt(488, 620); - SetHits(558, 599); + SetHits(558, 599); - SetDamage(29, 35); + SetDamage(29, 35); - SetDamageType(ResistanceType.Physical, 75); - SetDamageType(ResistanceType.Fire, 25); + SetDamageType(ResistanceType.Physical, 75); + SetDamageType(ResistanceType.Fire, 25); - SetResistance(ResistanceType.Physical, 75, 80); - SetResistance(ResistanceType.Fire, 40, 60); - SetResistance(ResistanceType.Cold, 40, 60); - SetResistance(ResistanceType.Poison, 70, 80); - SetResistance(ResistanceType.Energy, 40, 60); + SetResistance(ResistanceType.Physical, 75, 80); + SetResistance(ResistanceType.Fire, 40, 60); + SetResistance(ResistanceType.Cold, 40, 60); + SetResistance(ResistanceType.Poison, 70, 80); + SetResistance(ResistanceType.Energy, 40, 60); - SetSkill(SkillName.EvalInt, 80.1, 100.0); - SetSkill(SkillName.Magery, 80.1, 100.0); - SetSkill(SkillName.MagicResist, 100.3, 130.0); - SetSkill(SkillName.Tactics, 97.6, 100.0); - SetSkill(SkillName.Wrestling, 97.6, 100.0); - SetSkill(SkillName.Necromancy, 120.1, 130.0); - SetSkill(SkillName.SpiritSpeak, 120.1, 130.0); + SetSkill(SkillName.EvalInt, 80.1, 100.0); + SetSkill(SkillName.Magery, 80.1, 100.0); + SetSkill(SkillName.MagicResist, 100.3, 130.0); + SetSkill(SkillName.Tactics, 97.6, 100.0); + SetSkill(SkillName.Wrestling, 97.6, 100.0); + SetSkill(SkillName.Necromancy, 120.1, 130.0); + SetSkill(SkillName.SpiritSpeak, 120.1, 130.0); - Fame = 22500; - Karma = -22500; + Fame = 22500; + Karma = -22500; - VirtualArmor = 80; + VirtualArmor = 80; + } + + public SkeletalDragon(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a skeletal dragon corpse"; + public override string DefaultName => "a skeletal dragon"; + + public override bool ReacquireOnMovement => true; + public override bool HasBreath => true; // fire breath enabled + public override int BreathFireDamage => 0; + public override int BreathColdDamage => 100; + public override int BreathEffectHue => 0x480; + + public override double BonusPetDamageScalar => Core.SE ? 3.0 : 1.0; + // TODO: Undead summoning? + + public override bool AutoDispel => true; + public override Poison PoisonImmune => Poison.Lethal; + public override bool BleedImmune => true; + public override int Meat => 19; // where's it hiding these? :) + public override int Hides => 20; + public override HideType HideType => HideType.Barbed; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 4); + AddLoot(LootPack.Gems, 5); + } + + 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(); + } } - - public SkeletalDragon(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a skeletal dragon corpse"; - public override string DefaultName => "a skeletal dragon"; - - public override bool ReacquireOnMovement => true; - public override bool HasBreath => true; // fire breath enabled - public override int BreathFireDamage => 0; - public override int BreathColdDamage => 100; - public override int BreathEffectHue => 0x480; - - public override double BonusPetDamageScalar => Core.SE ? 3.0 : 1.0; - // TODO: Undead summoning? - - public override bool AutoDispel => true; - public override Poison PoisonImmune => Poison.Lethal; - public override bool BleedImmune => true; - public override int Meat => 19; // where's it hiding these? :) - public override int Hides => 20; - public override HideType HideType => HideType.Barbed; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 4); - AddLoot(LootPack.Gems, 5); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/WhiteWyrm.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/WhiteWyrm.cs index 07b8b790f..a3bb53046 100644 --- a/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/WhiteWyrm.cs +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Magic/WhiteWyrm.cs @@ -1,81 +1,81 @@ namespace Server.Mobiles { - public class WhiteWyrm : BaseCreature - { - [Constructible] - public WhiteWyrm() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class WhiteWyrm : BaseCreature { - Body = Utility.RandomBool() ? 180 : 49; - BaseSoundID = 362; + [Constructible] + public WhiteWyrm() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = Utility.RandomBool() ? 180 : 49; + BaseSoundID = 362; - SetStr(721, 760); - SetDex(101, 130); - SetInt(386, 425); + SetStr(721, 760); + SetDex(101, 130); + SetInt(386, 425); - SetHits(433, 456); + SetHits(433, 456); - SetDamage(17, 25); + SetDamage(17, 25); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Cold, 50); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Cold, 50); - SetResistance(ResistanceType.Physical, 55, 70); - SetResistance(ResistanceType.Fire, 15, 25); - SetResistance(ResistanceType.Cold, 80, 90); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 55, 70); + SetResistance(ResistanceType.Fire, 15, 25); + SetResistance(ResistanceType.Cold, 80, 90); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.EvalInt, 99.1, 100.0); - SetSkill(SkillName.Magery, 99.1, 100.0); - SetSkill(SkillName.MagicResist, 99.1, 100.0); - SetSkill(SkillName.Tactics, 97.6, 100.0); - SetSkill(SkillName.Wrestling, 90.1, 100.0); + SetSkill(SkillName.EvalInt, 99.1, 100.0); + SetSkill(SkillName.Magery, 99.1, 100.0); + SetSkill(SkillName.MagicResist, 99.1, 100.0); + SetSkill(SkillName.Tactics, 97.6, 100.0); + SetSkill(SkillName.Wrestling, 90.1, 100.0); - Fame = 18000; - Karma = -18000; + Fame = 18000; + Karma = -18000; - VirtualArmor = 64; + VirtualArmor = 64; - Tamable = true; - ControlSlots = 3; - MinTameSkill = 96.3; + Tamable = true; + ControlSlots = 3; + MinTameSkill = 96.3; + } + + public WhiteWyrm(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a white wyrm corpse"; + public override string DefaultName => "a white wyrm"; + + public override bool ReacquireOnMovement => true; + public override int TreasureMapLevel => 4; + public override int Meat => 19; + public override int Hides => 20; + public override HideType HideType => HideType.Barbed; + public override int Scales => 9; + public override ScaleType ScaleType => ScaleType.White; + public override FoodType FavoriteFood => FoodType.Meat | FoodType.Gold; + public override bool CanAngerOnTame => true; + public override bool CanFly => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 2); + AddLoot(LootPack.Average); + AddLoot(LootPack.Gems, Utility.Random(1, 5)); + } + + 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(); + } } - - public WhiteWyrm(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a white wyrm corpse"; - public override string DefaultName => "a white wyrm"; - - public override bool ReacquireOnMovement => true; - public override int TreasureMapLevel => 4; - public override int Meat => 19; - public override int Hides => 20; - public override HideType HideType => HideType.Barbed; - public override int Scales => 9; - public override ScaleType ScaleType => ScaleType.White; - public override FoodType FavoriteFood => FoodType.Meat | FoodType.Gold; - public override bool CanAngerOnTame => true; - public override bool CanFly => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 2); - AddLoot(LootPack.Average); - AddLoot(LootPack.Gems, Utility.Random(1, 5)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Drake.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Drake.cs index b5b4b4c75..2b4af117b 100644 --- a/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Drake.cs +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Drake.cs @@ -1,80 +1,80 @@ namespace Server.Mobiles { - public class Drake : BaseCreature - { - [Constructible] - public Drake() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Drake : BaseCreature { - Body = Utility.RandomList(60, 61); - BaseSoundID = 362; + [Constructible] + public Drake() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = Utility.RandomList(60, 61); + BaseSoundID = 362; - SetStr(401, 430); - SetDex(133, 152); - SetInt(101, 140); + SetStr(401, 430); + SetDex(133, 152); + SetInt(101, 140); - SetHits(241, 258); + SetHits(241, 258); - SetDamage(11, 17); + SetDamage(11, 17); - SetDamageType(ResistanceType.Physical, 80); - SetDamageType(ResistanceType.Fire, 20); + SetDamageType(ResistanceType.Physical, 80); + SetDamageType(ResistanceType.Fire, 20); - SetResistance(ResistanceType.Physical, 45, 50); - SetResistance(ResistanceType.Fire, 50, 60); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 45, 50); + SetResistance(ResistanceType.Fire, 50, 60); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.MagicResist, 65.1, 80.0); - SetSkill(SkillName.Tactics, 65.1, 90.0); - SetSkill(SkillName.Wrestling, 65.1, 80.0); + SetSkill(SkillName.MagicResist, 65.1, 80.0); + SetSkill(SkillName.Tactics, 65.1, 90.0); + SetSkill(SkillName.Wrestling, 65.1, 80.0); - Fame = 5500; - Karma = -5500; + Fame = 5500; + Karma = -5500; - VirtualArmor = 46; + VirtualArmor = 46; - Tamable = true; - ControlSlots = 2; - MinTameSkill = 84.3; + Tamable = true; + ControlSlots = 2; + MinTameSkill = 84.3; - PackReg(3); + PackReg(3); + } + + public Drake(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a drake corpse"; + public override string DefaultName => "a drake"; + + public override bool ReacquireOnMovement => true; + public override bool HasBreath => true; // fire breath enabled + public override int TreasureMapLevel => 2; + public override int Meat => 10; + public override int Hides => 20; + public override HideType HideType => HideType.Horned; + public override int Scales => 2; + public override ScaleType ScaleType => Body == 60 ? ScaleType.Yellow : ScaleType.Red; + public override FoodType FavoriteFood => FoodType.Meat | FoodType.Fish; + public override bool CanFly => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.MedScrolls, 2); + } + + 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(); + } } - - public Drake(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a drake corpse"; - public override string DefaultName => "a drake"; - - public override bool ReacquireOnMovement => true; - public override bool HasBreath => true; // fire breath enabled - public override int TreasureMapLevel => 2; - public override int Meat => 10; - public override int Hides => 20; - public override HideType HideType => HideType.Horned; - public override int Scales => 2; - public override ScaleType ScaleType => Body == 60 ? ScaleType.Yellow : ScaleType.Red; - public override FoodType FavoriteFood => FoodType.Meat | FoodType.Fish; - public override bool CanFly => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.MedScrolls, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Harpy.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Harpy.cs index ded862587..fe6ca4a7d 100644 --- a/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Harpy.cs +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Harpy.cs @@ -1,77 +1,77 @@ namespace Server.Mobiles { - public class Harpy : BaseCreature - { - [Constructible] - public Harpy() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Harpy : BaseCreature { - Body = 30; - BaseSoundID = 402; + [Constructible] + public Harpy() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 30; + BaseSoundID = 402; - SetStr(96, 120); - SetDex(86, 110); - SetInt(51, 75); + SetStr(96, 120); + SetDex(86, 110); + SetInt(51, 75); - SetHits(58, 72); + SetHits(58, 72); - SetDamage(5, 7); + SetDamage(5, 7); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 25, 30); - SetResistance(ResistanceType.Fire, 10, 20); - SetResistance(ResistanceType.Cold, 10, 30); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 10, 20); + SetResistance(ResistanceType.Physical, 25, 30); + SetResistance(ResistanceType.Fire, 10, 20); + SetResistance(ResistanceType.Cold, 10, 30); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 10, 20); - SetSkill(SkillName.MagicResist, 50.1, 65.0); - SetSkill(SkillName.Tactics, 70.1, 100.0); - SetSkill(SkillName.Wrestling, 60.1, 90.0); + SetSkill(SkillName.MagicResist, 50.1, 65.0); + SetSkill(SkillName.Tactics, 70.1, 100.0); + SetSkill(SkillName.Wrestling, 60.1, 90.0); - Fame = 2500; - Karma = -2500; + Fame = 2500; + Karma = -2500; - VirtualArmor = 28; + VirtualArmor = 28; + } + + public Harpy(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a harpy corpse"; + public override string DefaultName => "a harpy"; + + public override bool CanRummageCorpses => true; + public override int Meat => 4; + public override MeatType MeatType => MeatType.Bird; + public override int Feathers => 50; + public override bool CanFly => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager, 2); + } + + public override int GetAttackSound() => 916; + + public override int GetAngerSound() => 916; + + public override int GetDeathSound() => 917; + + public override int GetHurtSound() => 919; + + public override int GetIdleSound() => 918; + + 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(); + } } - - public Harpy(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a harpy corpse"; - public override string DefaultName => "a harpy"; - - public override bool CanRummageCorpses => true; - public override int Meat => 4; - public override MeatType MeatType => MeatType.Bird; - public override int Feathers => 50; - public override bool CanFly => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager, 2); - } - - public override int GetAttackSound() => 916; - - public override int GetAngerSound() => 916; - - public override int GetDeathSound() => 917; - - public override int GetHurtSound() => 919; - - public override int GetIdleSound() => 918; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Kraken.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Kraken.cs index adae6cd3b..149d3e583 100644 --- a/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Kraken.cs +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Kraken.cs @@ -2,78 +2,78 @@ using Server.Items; namespace Server.Mobiles { - public class Kraken : BaseCreature - { - [Constructible] - public Kraken() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Kraken : BaseCreature { - Body = 77; - BaseSoundID = 353; + [Constructible] + public Kraken() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 77; + BaseSoundID = 353; - SetStr(756, 780); - SetDex(226, 245); - SetInt(26, 40); + SetStr(756, 780); + SetDex(226, 245); + SetInt(26, 40); - SetHits(454, 468); - SetMana(0); + SetHits(454, 468); + SetMana(0); - SetDamage(19, 33); + SetDamage(19, 33); - SetDamageType(ResistanceType.Physical, 70); - SetDamageType(ResistanceType.Cold, 30); + SetDamageType(ResistanceType.Physical, 70); + SetDamageType(ResistanceType.Cold, 30); - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 10, 20); + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 10, 20); - SetSkill(SkillName.MagicResist, 15.1, 20.0); - SetSkill(SkillName.Tactics, 45.1, 60.0); - SetSkill(SkillName.Wrestling, 45.1, 60.0); + SetSkill(SkillName.MagicResist, 15.1, 20.0); + SetSkill(SkillName.Tactics, 45.1, 60.0); + SetSkill(SkillName.Wrestling, 45.1, 60.0); - Fame = 11000; - Karma = -11000; + Fame = 11000; + Karma = -11000; - VirtualArmor = 50; + VirtualArmor = 50; - CanSwim = true; - CantWalk = true; + CanSwim = true; + CantWalk = true; - Rope rope = new Rope(); - rope.ItemID = 0x14F8; - PackItem(rope); + var rope = new Rope(); + rope.ItemID = 0x14F8; + PackItem(rope); - if (Utility.RandomDouble() < .05) - PackItem(new MessageInABottle()); + if (Utility.RandomDouble() < .05) + PackItem(new MessageInABottle()); - PackItem(new SpecialFishingNet()); // Confirm? + PackItem(new SpecialFishingNet()); // Confirm? + } + + public Kraken(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a krakens corpse"; + public override string DefaultName => "a kraken"; + + public override int TreasureMapLevel => 4; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + } + + 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(); + } } - - public Kraken(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a krakens corpse"; - public override string DefaultName => "a kraken"; - - public override int TreasureMapLevel => 4; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Lizardman.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Lizardman.cs index 288771ec9..7b79bf063 100644 --- a/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Lizardman.cs +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Lizardman.cs @@ -2,68 +2,68 @@ using Server.Misc; namespace Server.Mobiles { - public class Lizardman : BaseCreature - { - [Constructible] - public Lizardman() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Lizardman : BaseCreature { - Name = NameList.RandomName("lizardman"); - Body = Utility.RandomList(35, 36); - BaseSoundID = 417; + [Constructible] + public Lizardman() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Name = NameList.RandomName("lizardman"); + Body = Utility.RandomList(35, 36); + BaseSoundID = 417; - SetStr(96, 120); - SetDex(86, 105); - SetInt(36, 60); + SetStr(96, 120); + SetDex(86, 105); + SetInt(36, 60); - SetHits(58, 72); + SetHits(58, 72); - SetDamage(5, 7); + SetDamage(5, 7); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 25, 30); - SetResistance(ResistanceType.Fire, 5, 10); - SetResistance(ResistanceType.Cold, 5, 10); - SetResistance(ResistanceType.Poison, 10, 20); + SetResistance(ResistanceType.Physical, 25, 30); + SetResistance(ResistanceType.Fire, 5, 10); + SetResistance(ResistanceType.Cold, 5, 10); + SetResistance(ResistanceType.Poison, 10, 20); - SetSkill(SkillName.MagicResist, 35.1, 60.0); - SetSkill(SkillName.Tactics, 55.1, 80.0); - SetSkill(SkillName.Wrestling, 50.1, 70.0); + SetSkill(SkillName.MagicResist, 35.1, 60.0); + SetSkill(SkillName.Tactics, 55.1, 80.0); + SetSkill(SkillName.Wrestling, 50.1, 70.0); - Fame = 1500; - Karma = -1500; + Fame = 1500; + Karma = -1500; - VirtualArmor = 28; + VirtualArmor = 28; + } + + public Lizardman(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a lizardman corpse"; + public override InhumanSpeech SpeechType => InhumanSpeech.Lizardman; + + public override bool CanRummageCorpses => true; + public override int Meat => 1; + public override int Hides => 12; + public override HideType HideType => HideType.Spined; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + // TODO: weapon + } + + 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(); + } } - - public Lizardman(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a lizardman corpse"; - public override InhumanSpeech SpeechType => InhumanSpeech.Lizardman; - - public override bool CanRummageCorpses => true; - public override int Meat => 1; - public override int Hides => 12; - public override HideType HideType => HideType.Spined; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - // TODO: weapon - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/OphidianKnight.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/OphidianKnight.cs index 43bb73846..f530a516e 100644 --- a/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/OphidianKnight.cs +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/OphidianKnight.cs @@ -2,81 +2,81 @@ using Server.Items; namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.OphidianAvenger")] - public class OphidianKnight : BaseCreature - { - private static readonly string[] m_Names = + [TypeAlias("Server.Mobiles.OphidianAvenger")] + public class OphidianKnight : BaseCreature { - "an ophidian knight-errant", - "an ophidian avenger" - }; + private static readonly string[] m_Names = + { + "an ophidian knight-errant", + "an ophidian avenger" + }; - [Constructible] - public OphidianKnight() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) - { - Name = m_Names.RandomElement(); - Body = 86; - BaseSoundID = 634; + [Constructible] + public OphidianKnight() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Name = m_Names.RandomElement(); + Body = 86; + BaseSoundID = 634; - SetStr(417, 595); - SetDex(166, 175); - SetInt(46, 70); + SetStr(417, 595); + SetDex(166, 175); + SetInt(46, 70); - SetHits(266, 342); - SetMana(0); + SetHits(266, 342); + SetMana(0); - SetDamage(16, 19); + SetDamage(16, 19); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 35, 40); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 35, 45); - SetResistance(ResistanceType.Poison, 90, 100); - SetResistance(ResistanceType.Energy, 35, 45); + SetResistance(ResistanceType.Physical, 35, 40); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 35, 45); + SetResistance(ResistanceType.Poison, 90, 100); + SetResistance(ResistanceType.Energy, 35, 45); - SetSkill(SkillName.Poisoning, 60.1, 80.0); - SetSkill(SkillName.MagicResist, 65.1, 80.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); - SetSkill(SkillName.Wrestling, 90.1, 100.0); + SetSkill(SkillName.Poisoning, 60.1, 80.0); + SetSkill(SkillName.MagicResist, 65.1, 80.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.Wrestling, 90.1, 100.0); - Fame = 10000; - Karma = -10000; + Fame = 10000; + Karma = -10000; - VirtualArmor = 40; + VirtualArmor = 40; - PackItem(new LesserPoisonPotion()); + PackItem(new LesserPoisonPotion()); + } + + public OphidianKnight(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ophidian corpse"; + + public override int Meat => 2; + + public override Poison PoisonImmune => Poison.Lethal; + public override Poison HitPoison => Poison.Lethal; + public override int TreasureMapLevel => 3; + + public override OppositionGroup OppositionGroup => OppositionGroup.TerathansAndOphidians; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich, 2); + } + + 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(); + } } - - public OphidianKnight(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ophidian corpse"; - - public override int Meat => 2; - - public override Poison PoisonImmune => Poison.Lethal; - public override Poison HitPoison => Poison.Lethal; - public override int TreasureMapLevel => 3; - - public override OppositionGroup OppositionGroup => OppositionGroup.TerathansAndOphidians; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/OphidianWarrior.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/OphidianWarrior.cs index c09071df0..5a76ecb86 100644 --- a/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/OphidianWarrior.cs +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/OphidianWarrior.cs @@ -1,75 +1,75 @@ namespace Server.Mobiles { - public class OphidianWarrior : BaseCreature - { - private static readonly string[] m_Names = + public class OphidianWarrior : BaseCreature { - "an ophidian warrior", - "an ophidian enforcer" - }; + private static readonly string[] m_Names = + { + "an ophidian warrior", + "an ophidian enforcer" + }; - [Constructible] - public OphidianWarrior() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) - { - Name = m_Names.RandomElement(); - Body = 86; - BaseSoundID = 634; + [Constructible] + public OphidianWarrior() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Name = m_Names.RandomElement(); + Body = 86; + BaseSoundID = 634; - SetStr(150, 320); - SetDex(94, 190); - SetInt(64, 160); + SetStr(150, 320); + SetDex(94, 190); + SetInt(64, 160); - SetHits(128, 155); - SetMana(0); + SetHits(128, 155); + SetMana(0); - SetDamage(5, 11); + SetDamage(5, 11); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 35, 40); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 25, 35); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 25, 35); + SetResistance(ResistanceType.Physical, 35, 40); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 25, 35); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 25, 35); - SetSkill(SkillName.MagicResist, 70.1, 85.0); - SetSkill(SkillName.Swords, 60.1, 85.0); - SetSkill(SkillName.Tactics, 75.1, 90.0); + SetSkill(SkillName.MagicResist, 70.1, 85.0); + SetSkill(SkillName.Swords, 60.1, 85.0); + SetSkill(SkillName.Tactics, 75.1, 90.0); - Fame = 4500; - Karma = -4500; + Fame = 4500; + Karma = -4500; - VirtualArmor = 36; + VirtualArmor = 36; + } + + public OphidianWarrior(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an ophidian corpse"; + + public override int Meat => 1; + public override int TreasureMapLevel => 1; + + public override OppositionGroup OppositionGroup => OppositionGroup.TerathansAndOphidians; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + AddLoot(LootPack.Average); + AddLoot(LootPack.Gems); + } + + 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(); + } } - - public OphidianWarrior(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an ophidian corpse"; - - public override int Meat => 1; - public override int TreasureMapLevel => 1; - - public override OppositionGroup OppositionGroup => OppositionGroup.TerathansAndOphidians; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - AddLoot(LootPack.Average); - AddLoot(LootPack.Gems); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Scorpion.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Scorpion.cs index 77a9ae0bb..14db2e1e6 100644 --- a/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Scorpion.cs +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Scorpion.cs @@ -2,77 +2,77 @@ using Server.Items; namespace Server.Mobiles { - public class Scorpion : BaseCreature - { - [Constructible] - public Scorpion() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Scorpion : BaseCreature { - Body = 48; - BaseSoundID = 397; + [Constructible] + public Scorpion() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 48; + BaseSoundID = 397; - SetStr(73, 115); - SetDex(76, 95); - SetInt(16, 30); + SetStr(73, 115); + SetDex(76, 95); + SetInt(16, 30); - SetHits(50, 63); - SetMana(0); + SetHits(50, 63); + SetMana(0); - SetDamage(5, 10); + SetDamage(5, 10); - SetDamageType(ResistanceType.Physical, 60); - SetDamageType(ResistanceType.Poison, 40); + SetDamageType(ResistanceType.Physical, 60); + SetDamageType(ResistanceType.Poison, 40); - SetResistance(ResistanceType.Physical, 20, 25); - SetResistance(ResistanceType.Fire, 10, 15); - SetResistance(ResistanceType.Cold, 20, 25); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 10, 15); + SetResistance(ResistanceType.Physical, 20, 25); + SetResistance(ResistanceType.Fire, 10, 15); + SetResistance(ResistanceType.Cold, 20, 25); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 10, 15); - SetSkill(SkillName.Poisoning, 80.1, 100.0); - SetSkill(SkillName.MagicResist, 30.1, 35.0); - SetSkill(SkillName.Tactics, 60.3, 75.0); - SetSkill(SkillName.Wrestling, 50.3, 65.0); + SetSkill(SkillName.Poisoning, 80.1, 100.0); + SetSkill(SkillName.MagicResist, 30.1, 35.0); + SetSkill(SkillName.Tactics, 60.3, 75.0); + SetSkill(SkillName.Wrestling, 50.3, 65.0); - Fame = 2000; - Karma = -2000; + Fame = 2000; + Karma = -2000; - VirtualArmor = 28; + VirtualArmor = 28; - Tamable = true; - ControlSlots = 1; - MinTameSkill = 47.1; + Tamable = true; + ControlSlots = 1; + MinTameSkill = 47.1; - PackItem(new LesserPoisonPotion()); + PackItem(new LesserPoisonPotion()); + } + + public Scorpion(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a scorpion corpse"; + public override string DefaultName => "a scorpion"; + + public override int Meat => 1; + public override FoodType FavoriteFood => FoodType.Meat; + public override PackInstinct PackInstinct => PackInstinct.Arachnid; + public override Poison PoisonImmune => Poison.Greater; + public override Poison HitPoison => Utility.RandomDouble() <= 0.8 ? Poison.Greater : Poison.Deadly; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + } + + 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(); + } } - - public Scorpion(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a scorpion corpse"; - public override string DefaultName => "a scorpion"; - - public override int Meat => 1; - public override FoodType FavoriteFood => FoodType.Meat; - public override PackInstinct PackInstinct => PackInstinct.Arachnid; - public override Poison PoisonImmune => Poison.Greater; - public override Poison HitPoison => Utility.RandomDouble() <= 0.8 ? Poison.Greater : Poison.Deadly; - - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/StoneHarpy.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/StoneHarpy.cs index b0fc9bd6e..3af776b96 100644 --- a/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/StoneHarpy.cs +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/StoneHarpy.cs @@ -1,78 +1,78 @@ namespace Server.Mobiles { - public class StoneHarpy : BaseCreature - { - [Constructible] - public StoneHarpy() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class StoneHarpy : BaseCreature { - Body = 73; - BaseSoundID = 402; + [Constructible] + public StoneHarpy() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 73; + BaseSoundID = 402; - SetStr(296, 320); - SetDex(86, 110); - SetInt(51, 75); + SetStr(296, 320); + SetDex(86, 110); + SetInt(51, 75); - SetHits(178, 192); - SetMana(0); + SetHits(178, 192); + SetMana(0); - SetDamage(8, 16); + SetDamage(8, 16); - SetDamageType(ResistanceType.Physical, 75); - SetDamageType(ResistanceType.Poison, 25); + SetDamageType(ResistanceType.Physical, 75); + SetDamageType(ResistanceType.Poison, 25); - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 10, 20); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.MagicResist, 50.1, 65.0); - SetSkill(SkillName.Tactics, 70.1, 100.0); - SetSkill(SkillName.Wrestling, 70.1, 100.0); + SetSkill(SkillName.MagicResist, 50.1, 65.0); + SetSkill(SkillName.Tactics, 70.1, 100.0); + SetSkill(SkillName.Wrestling, 70.1, 100.0); - Fame = 4500; - Karma = -4500; + Fame = 4500; + Karma = -4500; - VirtualArmor = 50; + VirtualArmor = 50; + } + + public StoneHarpy(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a stone harpy corpse"; + public override string DefaultName => "a stone harpy"; + + public override int Meat => 1; + public override int Feathers => 50; + public override bool CanFly => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average, 2); + AddLoot(LootPack.Gems, 2); + } + + public override int GetAttackSound() => 916; + + public override int GetAngerSound() => 916; + + public override int GetDeathSound() => 917; + + public override int GetHurtSound() => 919; + + public override int GetIdleSound() => 918; + + 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(); + } } - - public StoneHarpy(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a stone harpy corpse"; - public override string DefaultName => "a stone harpy"; - - public override int Meat => 1; - public override int Feathers => 50; - public override bool CanFly => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average, 2); - AddLoot(LootPack.Gems, 2); - } - - public override int GetAttackSound() => 916; - - public override int GetAngerSound() => 916; - - public override int GetDeathSound() => 917; - - public override int GetHurtSound() => 919; - - public override int GetIdleSound() => 918; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Wyvern.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Wyvern.cs index bbe10e37d..25cb30493 100644 --- a/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Wyvern.cs +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Melee/Wyvern.cs @@ -2,89 +2,89 @@ using Server.Items; namespace Server.Mobiles { - public class Wyvern : BaseCreature - { - [Constructible] - public Wyvern() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Wyvern : BaseCreature { - Body = 62; - BaseSoundID = 362; + [Constructible] + public Wyvern() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 62; + BaseSoundID = 362; - SetStr(202, 240); - SetDex(153, 172); - SetInt(51, 90); + SetStr(202, 240); + SetDex(153, 172); + SetInt(51, 90); - SetHits(125, 141); + SetHits(125, 141); - SetDamage(8, 19); + SetDamage(8, 19); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Poison, 50); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Poison, 50); - SetResistance(ResistanceType.Physical, 35, 45); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 20, 30); - SetResistance(ResistanceType.Poison, 90, 100); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 20, 30); + SetResistance(ResistanceType.Poison, 90, 100); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.Poisoning, 60.1, 80.0); - SetSkill(SkillName.MagicResist, 65.1, 80.0); - SetSkill(SkillName.Tactics, 65.1, 90.0); - SetSkill(SkillName.Wrestling, 65.1, 80.0); + SetSkill(SkillName.Poisoning, 60.1, 80.0); + SetSkill(SkillName.MagicResist, 65.1, 80.0); + SetSkill(SkillName.Tactics, 65.1, 90.0); + SetSkill(SkillName.Wrestling, 65.1, 80.0); - Fame = 4000; - Karma = -4000; + Fame = 4000; + Karma = -4000; - VirtualArmor = 40; + VirtualArmor = 40; - PackItem(new LesserPoisonPotion()); + PackItem(new LesserPoisonPotion()); + } + + public Wyvern(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a wyvern corpse"; + public override string DefaultName => "a wyvern"; + + public override bool ReacquireOnMovement => true; + + public override Poison PoisonImmune => Poison.Deadly; + public override Poison HitPoison => Poison.Deadly; + public override int TreasureMapLevel => 2; + + public override int Meat => 10; + public override int Hides => 20; + public override HideType HideType => HideType.Horned; + public override bool CanFly => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Meager); + AddLoot(LootPack.MedScrolls); + } + + public override int GetAttackSound() => 713; + + public override int GetAngerSound() => 718; + + public override int GetDeathSound() => 716; + + public override int GetHurtSound() => 721; + + public override int GetIdleSound() => 725; + + 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(); + } } - - public Wyvern(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a wyvern corpse"; - public override string DefaultName => "a wyvern"; - - public override bool ReacquireOnMovement => true; - - public override Poison PoisonImmune => Poison.Deadly; - public override Poison HitPoison => Poison.Deadly; - public override int TreasureMapLevel => 2; - - public override int Meat => 10; - public override int Hides => 20; - public override HideType HideType => HideType.Horned; - public override bool CanFly => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Meager); - AddLoot(LootPack.MedScrolls); - } - - public override int GetAttackSound() => 713; - - public override int GetAngerSound() => 718; - - public override int GetDeathSound() => 716; - - public override int GetHurtSound() => 721; - - public override int GetIdleSound() => 725; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/SE/BakeKitsune.cs b/Projects/UOContent/Mobiles/Monsters/SE/BakeKitsune.cs index 4d70fa15f..d864d3123 100644 --- a/Projects/UOContent/Mobiles/Monsters/SE/BakeKitsune.cs +++ b/Projects/UOContent/Mobiles/Monsters/SE/BakeKitsune.cs @@ -5,260 +5,260 @@ using Server.Items; namespace Server.Mobiles { - public class BakeKitsune : BaseCreature - { - private static readonly Dictionary m_Table = new Dictionary(); - - [Constructible] - public BakeKitsune() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class BakeKitsune : BaseCreature { - Body = 246; + private static readonly Dictionary m_Table = new Dictionary(); - SetStr(171, 220); - SetDex(126, 145); - SetInt(376, 425); + private Timer m_DisguiseTimer; - SetHits(301, 350); - - SetDamage(15, 22); - - SetDamageType(ResistanceType.Physical, 70); - SetDamageType(ResistanceType.Energy, 30); - - SetResistance(ResistanceType.Physical, 40, 60); - SetResistance(ResistanceType.Fire, 70, 90); - SetResistance(ResistanceType.Cold, 40, 60); - SetResistance(ResistanceType.Poison, 40, 60); - SetResistance(ResistanceType.Energy, 40, 60); - - SetSkill(SkillName.EvalInt, 80.1, 90.0); - SetSkill(SkillName.Magery, 80.1, 90.0); - SetSkill(SkillName.MagicResist, 80.1, 100.0); - SetSkill(SkillName.Tactics, 70.1, 90.0); - SetSkill(SkillName.Wrestling, 50.1, 55.0); - - Fame = 8000; - Karma = -8000; - - Tamable = true; - ControlSlots = 2; - MinTameSkill = 80.7; - - if (Utility.RandomDouble() < .25) - PackItem(Seed.RandomBonsaiSeed()); - } - - public BakeKitsune(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a bake kitsune corpse"; - public override string DefaultName => "a bake kitsune"; - - public override int Meat => 5; - public override int Hides => 10; - public override HideType HideType => HideType.Barbed; - public override FoodType FavoriteFood => FoodType.Fish; - public override bool ShowFameTitle => false; - public override bool ClickTitle => false; - public override bool PropertyTitle => false; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.Rich); - AddLoot(LootPack.MedScrolls, 2); - } - - public override void OnCombatantChange() - { - if (Combatant == null && !IsBodyMod && !Controlled && m_DisguiseTimer == null && Utility.RandomBool()) - m_DisguiseTimer = Timer.DelayCall(TimeSpan.FromSeconds(Utility.RandomMinMax(15, 30)), Disguise); - } - - public override bool OnBeforeDeath() - { - RemoveDisguise(); - - return base.OnBeforeDeath(); - } - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (Utility.RandomDouble() >= 0.1) - return; - - /* Blood Bath - * Start cliloc 1070826 - * Sound: 0x52B - * 2-3 blood spots - * Damage: 2 hps per second for 5 seconds - * End cliloc: 1070824 - */ - - if (m_Table.TryGetValue(defender, out ExpireTimer timer)) - { - timer.DoExpire(); - defender.SendLocalizedMessage(1070825); // The creature continues to rage! - } - else - { - defender.SendLocalizedMessage(1070826); // The creature goes into a rage, inflicting heavy damage! - } - - timer = new ExpireTimer(defender, this); - timer.Start(); - m_Table[defender] = timer; - } - - public override int GetAngerSound() => 0x4DE; - - public override int GetIdleSound() => 0x4DD; - - public override int GetAttackSound() => 0x4DC; - - public override int GetHurtSound() => 0x4DF; - - public override int GetDeathSound() => 0x4DB; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (version == 0 && PhysicalResistance > 60) - { - SetResistance(ResistanceType.Physical, 40, 60); - SetResistance(ResistanceType.Fire, 70, 90); - SetResistance(ResistanceType.Cold, 40, 60); - SetResistance(ResistanceType.Poison, 40, 60); - SetResistance(ResistanceType.Energy, 40, 60); - } - - Timer.DelayCall(RemoveDisguise); - } - - private class ExpireTimer : Timer - { - private int m_Count; - private readonly Mobile m_From; - private readonly Mobile m_Mobile; - - public ExpireTimer(Mobile m, Mobile from) : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)) - { - m_Mobile = m; - m_From = from; - Priority = TimerPriority.TwoFiftyMS; - } - - public void DoExpire() - { - Stop(); - m_Table.Remove(m_Mobile); - } - - public void DrainLife() - { - if (m_Mobile.Alive) - m_Mobile.Damage(2, m_From); - else - DoExpire(); - } - - protected override void OnTick() - { - DrainLife(); - - if (++m_Count >= 5) + [Constructible] + public BakeKitsune() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) { - DoExpire(); - m_Mobile.SendLocalizedMessage(1070824); // The creature's rage subsides. + Body = 246; + + SetStr(171, 220); + SetDex(126, 145); + SetInt(376, 425); + + SetHits(301, 350); + + SetDamage(15, 22); + + SetDamageType(ResistanceType.Physical, 70); + SetDamageType(ResistanceType.Energy, 30); + + SetResistance(ResistanceType.Physical, 40, 60); + SetResistance(ResistanceType.Fire, 70, 90); + SetResistance(ResistanceType.Cold, 40, 60); + SetResistance(ResistanceType.Poison, 40, 60); + SetResistance(ResistanceType.Energy, 40, 60); + + SetSkill(SkillName.EvalInt, 80.1, 90.0); + SetSkill(SkillName.Magery, 80.1, 90.0); + SetSkill(SkillName.MagicResist, 80.1, 100.0); + SetSkill(SkillName.Tactics, 70.1, 90.0); + SetSkill(SkillName.Wrestling, 50.1, 55.0); + + Fame = 8000; + Karma = -8000; + + Tamable = true; + ControlSlots = 2; + MinTameSkill = 80.7; + + if (Utility.RandomDouble() < .25) + PackItem(Seed.RandomBonsaiSeed()); + } + + public BakeKitsune(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a bake kitsune corpse"; + public override string DefaultName => "a bake kitsune"; + + public override int Meat => 5; + public override int Hides => 10; + public override HideType HideType => HideType.Barbed; + public override FoodType FavoriteFood => FoodType.Fish; + public override bool ShowFameTitle => false; + public override bool ClickTitle => false; + public override bool PropertyTitle => false; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.Rich); + AddLoot(LootPack.MedScrolls, 2); + } + + public override void OnCombatantChange() + { + if (Combatant == null && !IsBodyMod && !Controlled && m_DisguiseTimer == null && Utility.RandomBool()) + m_DisguiseTimer = Timer.DelayCall(TimeSpan.FromSeconds(Utility.RandomMinMax(15, 30)), Disguise); + } + + public override bool OnBeforeDeath() + { + RemoveDisguise(); + + return base.OnBeforeDeath(); + } + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomDouble() >= 0.1) + return; + + /* Blood Bath + * Start cliloc 1070826 + * Sound: 0x52B + * 2-3 blood spots + * Damage: 2 hps per second for 5 seconds + * End cliloc: 1070824 + */ + + if (m_Table.TryGetValue(defender, out var timer)) + { + timer.DoExpire(); + defender.SendLocalizedMessage(1070825); // The creature continues to rage! + } + else + { + defender.SendLocalizedMessage(1070826); // The creature goes into a rage, inflicting heavy damage! + } + + timer = new ExpireTimer(defender, this); + timer.Start(); + m_Table[defender] = timer; + } + + public override int GetAngerSound() => 0x4DE; + + public override int GetIdleSound() => 0x4DD; + + public override int GetAttackSound() => 0x4DC; + + public override int GetHurtSound() => 0x4DF; + + public override int GetDeathSound() => 0x4DB; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + if (version == 0 && PhysicalResistance > 60) + { + SetResistance(ResistanceType.Physical, 40, 60); + SetResistance(ResistanceType.Fire, 70, 90); + SetResistance(ResistanceType.Cold, 40, 60); + SetResistance(ResistanceType.Poison, 40, 60); + SetResistance(ResistanceType.Energy, 40, 60); + } + + Timer.DelayCall(RemoveDisguise); + } + + public void Disguise() + { + if (Combatant != null || IsBodyMod || Controlled) + return; + + FixedEffect(0x376A, 8, 32); + PlaySound(0x1FE); + + Female = Utility.RandomBool(); + + if (Female) + { + BodyMod = 0x191; + Name = NameList.RandomName("female"); + } + else + { + BodyMod = 0x190; + Name = NameList.RandomName("male"); + } + + Title = "the mystic llama herder"; + Hue = Race.Human.RandomSkinHue(); + HairItemID = Race.Human.RandomHair(this); + HairHue = Race.Human.RandomHairHue(); + FacialHairItemID = Race.Human.RandomFacialHair(this); + FacialHairHue = HairHue; + + switch (Utility.Random(4)) + { + case 0: + AddItem(new Shoes(Utility.RandomNeutralHue())); + break; + case 1: + AddItem(new Boots(Utility.RandomNeutralHue())); + break; + case 2: + AddItem(new Sandals(Utility.RandomNeutralHue())); + break; + case 3: + AddItem(new ThighBoots(Utility.RandomNeutralHue())); + break; + } + + AddItem(new Robe(Utility.RandomNondyedHue())); + + m_DisguiseTimer = Timer.DelayCall(TimeSpan.FromSeconds(75), RemoveDisguise); + } + + public void RemoveDisguise() + { + if (!IsBodyMod) + return; + + Name = null; + Title = null; + BodyMod = 0; + Hue = 0; + HairItemID = 0; + HairHue = 0; + FacialHairItemID = 0; + FacialHairHue = 0; + + DeleteItemOnLayer(Layer.OuterTorso); + DeleteItemOnLayer(Layer.Shoes); + + m_DisguiseTimer = null; + } + + public void DeleteItemOnLayer(Layer layer) + { + FindItemOnLayer(layer)?.Delete(); + } + + private class ExpireTimer : Timer + { + private readonly Mobile m_From; + private readonly Mobile m_Mobile; + private int m_Count; + + public ExpireTimer(Mobile m, Mobile from) : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)) + { + m_Mobile = m; + m_From = from; + Priority = TimerPriority.TwoFiftyMS; + } + + public void DoExpire() + { + Stop(); + m_Table.Remove(m_Mobile); + } + + public void DrainLife() + { + if (m_Mobile.Alive) + m_Mobile.Damage(2, m_From); + else + DoExpire(); + } + + protected override void OnTick() + { + DrainLife(); + + if (++m_Count >= 5) + { + DoExpire(); + m_Mobile.SendLocalizedMessage(1070824); // The creature's rage subsides. + } + } } - } } - - private Timer m_DisguiseTimer; - - public void Disguise() - { - if (Combatant != null || IsBodyMod || Controlled) - return; - - FixedEffect(0x376A, 8, 32); - PlaySound(0x1FE); - - Female = Utility.RandomBool(); - - if (Female) - { - BodyMod = 0x191; - Name = NameList.RandomName("female"); - } - else - { - BodyMod = 0x190; - Name = NameList.RandomName("male"); - } - - Title = "the mystic llama herder"; - Hue = Race.Human.RandomSkinHue(); - HairItemID = Race.Human.RandomHair(this); - HairHue = Race.Human.RandomHairHue(); - FacialHairItemID = Race.Human.RandomFacialHair(this); - FacialHairHue = HairHue; - - switch (Utility.Random(4)) - { - case 0: - AddItem(new Shoes(Utility.RandomNeutralHue())); - break; - case 1: - AddItem(new Boots(Utility.RandomNeutralHue())); - break; - case 2: - AddItem(new Sandals(Utility.RandomNeutralHue())); - break; - case 3: - AddItem(new ThighBoots(Utility.RandomNeutralHue())); - break; - } - - AddItem(new Robe(Utility.RandomNondyedHue())); - - m_DisguiseTimer = Timer.DelayCall(TimeSpan.FromSeconds(75), RemoveDisguise); - } - - public void RemoveDisguise() - { - if (!IsBodyMod) - return; - - Name = null; - Title = null; - BodyMod = 0; - Hue = 0; - HairItemID = 0; - HairHue = 0; - FacialHairItemID = 0; - FacialHairHue = 0; - - DeleteItemOnLayer(Layer.OuterTorso); - DeleteItemOnLayer(Layer.Shoes); - - m_DisguiseTimer = null; - } - - public void DeleteItemOnLayer(Layer layer) - { - FindItemOnLayer(layer)?.Delete(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/SE/DeathWatchBeetle.cs b/Projects/UOContent/Mobiles/Monsters/SE/DeathWatchBeetle.cs index d78a40f0c..a9395aa2b 100644 --- a/Projects/UOContent/Mobiles/Monsters/SE/DeathWatchBeetle.cs +++ b/Projects/UOContent/Mobiles/Monsters/SE/DeathWatchBeetle.cs @@ -3,141 +3,141 @@ using Server.Items; namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.DeathWatchBeetle")] - public class DeathwatchBeetle : BaseCreature - { - [Constructible] - public DeathwatchBeetle() : base(AIType.AI_Melee, Core.ML ? FightMode.Aggressor : FightMode.Closest, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.DeathWatchBeetle")] + public class DeathwatchBeetle : BaseCreature { - Body = 242; + [Constructible] + public DeathwatchBeetle() : base(AIType.AI_Melee, Core.ML ? FightMode.Aggressor : FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 242; - SetStr(136, 160); - SetDex(41, 52); - SetInt(31, 40); + SetStr(136, 160); + SetDex(41, 52); + SetInt(31, 40); - SetHits(121, 145); - SetMana(20); + SetHits(121, 145); + SetMana(20); - SetDamage(5, 10); + SetDamage(5, 10); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 35, 40); - SetResistance(ResistanceType.Fire, 15, 30); - SetResistance(ResistanceType.Cold, 15, 30); - SetResistance(ResistanceType.Poison, 50, 80); - SetResistance(ResistanceType.Energy, 20, 35); + SetResistance(ResistanceType.Physical, 35, 40); + SetResistance(ResistanceType.Fire, 15, 30); + SetResistance(ResistanceType.Cold, 15, 30); + SetResistance(ResistanceType.Poison, 50, 80); + SetResistance(ResistanceType.Energy, 20, 35); - SetSkill(SkillName.MagicResist, 50.1, 58.0); - SetSkill(SkillName.Tactics, 67.1, 77.0); - SetSkill(SkillName.Wrestling, 50.1, 60.0); - SetSkill(SkillName.Anatomy, 30.1, 34.0); + SetSkill(SkillName.MagicResist, 50.1, 58.0); + SetSkill(SkillName.Tactics, 67.1, 77.0); + SetSkill(SkillName.Wrestling, 50.1, 60.0); + SetSkill(SkillName.Anatomy, 30.1, 34.0); - Fame = 1400; - Karma = -1400; + Fame = 1400; + Karma = -1400; - switch (Utility.Random(12)) - { - case 0: - PackItem(new LeatherGorget()); - break; - case 1: - PackItem(new LeatherGloves()); - break; - case 2: - PackItem(new LeatherArms()); - break; - case 3: - PackItem(new LeatherLegs()); - break; - case 4: - PackItem(new LeatherCap()); - break; - case 5: - PackItem(new LeatherChest()); - break; - } + switch (Utility.Random(12)) + { + case 0: + PackItem(new LeatherGorget()); + break; + case 1: + PackItem(new LeatherGloves()); + break; + case 2: + PackItem(new LeatherArms()); + break; + case 3: + PackItem(new LeatherLegs()); + break; + case 4: + PackItem(new LeatherCap()); + break; + case 5: + PackItem(new LeatherChest()); + break; + } - if (Utility.RandomDouble() < .5) - PackItem(Seed.RandomBonsaiSeed()); + if (Utility.RandomDouble() < .5) + PackItem(Seed.RandomBonsaiSeed()); - Tamable = true; - MinTameSkill = 41.1; - ControlSlots = 1; + Tamable = true; + MinTameSkill = 41.1; + ControlSlots = 1; + } + + public DeathwatchBeetle(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a deathwatchbeetle corpse"; + + public override string DefaultName => "a deathwatch beetle"; + + public override int Hides => 8; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.CrushingBlow; + + public override int GetAngerSound() => 0x4F3; + + public override int GetIdleSound() => 0x4F2; + + public override int GetAttackSound() => 0x4F1; + + public override int GetHurtSound() => 0x4F4; + + public override int GetDeathSound() => 0x4F0; + + public override void GenerateLoot() + { + AddLoot(LootPack.LowScrolls, 1); + AddLoot(LootPack.Potions, 1); + } + + public override void AlterMeleeDamageTo(Mobile to, ref int damage) + { + if (Utility.RandomBool() && Mana > 14 && to != null) + { + damage = damage + damage / 2; + to.SendLocalizedMessage(1060091); // You take extra damage from the crushing attack! + to.PlaySound(0x1E1); + to.FixedParticles(0x377A, 1, 32, 0x26da, 0, 0, 0); + Mana -= 15; + } + } + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + var combatant = Combatant; + + if (combatant?.Deleted != false || combatant.Map != Map || !InRange(combatant, 12) || + !CanBeHarmful(combatant) || !InLOS(combatant)) + return; + + if (Utility.Random(10) == 0) + PoisonAttack(combatant); + + base.OnDamage(amount, from, willKill); + } + + public void PoisonAttack(Mobile m) + { + DoHarmful(m); + MovingParticles(m, 0x36D4, 1, 0, false, false, 0x3F, 0, 0x1F73, 1, 0, (EffectLayer)255, 0x100); + m.ApplyPoison(this, Poison.Regular); + m.SendLocalizedMessage(1070821, Name); // %s spits a poisonous substance at you! + } + + 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(); + } } - - public DeathwatchBeetle(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a deathwatchbeetle corpse"; - - public override string DefaultName => "a deathwatch beetle"; - - public override int Hides => 8; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.CrushingBlow; - - public override int GetAngerSound() => 0x4F3; - - public override int GetIdleSound() => 0x4F2; - - public override int GetAttackSound() => 0x4F1; - - public override int GetHurtSound() => 0x4F4; - - public override int GetDeathSound() => 0x4F0; - - public override void GenerateLoot() - { - AddLoot(LootPack.LowScrolls, 1); - AddLoot(LootPack.Potions, 1); - } - - public override void AlterMeleeDamageTo(Mobile to, ref int damage) - { - if (Utility.RandomBool() && Mana > 14 && to != null) - { - damage = damage + damage / 2; - to.SendLocalizedMessage(1060091); // You take extra damage from the crushing attack! - to.PlaySound(0x1E1); - to.FixedParticles(0x377A, 1, 32, 0x26da, 0, 0, 0); - Mana -= 15; - } - } - - public override void OnDamage(int amount, Mobile from, bool willKill) - { - Mobile combatant = Combatant; - - if (combatant?.Deleted != false || combatant.Map != Map || !InRange(combatant, 12) || - !CanBeHarmful(combatant) || !InLOS(combatant)) - return; - - if (Utility.Random(10) == 0) - PoisonAttack(combatant); - - base.OnDamage(amount, from, willKill); - } - - public void PoisonAttack(Mobile m) - { - DoHarmful(m); - MovingParticles(m, 0x36D4, 1, 0, false, false, 0x3F, 0, 0x1F73, 1, 0, (EffectLayer)255, 0x100); - m.ApplyPoison(this, Poison.Regular); - m.SendLocalizedMessage(1070821, Name); // %s spits a poisonous substance at you! - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/SE/DeathWatchBeetleHatchling.cs b/Projects/UOContent/Mobiles/Monsters/SE/DeathWatchBeetleHatchling.cs index bf0f2eb0f..07033c5c6 100644 --- a/Projects/UOContent/Mobiles/Monsters/SE/DeathWatchBeetleHatchling.cs +++ b/Projects/UOContent/Mobiles/Monsters/SE/DeathWatchBeetleHatchling.cs @@ -2,104 +2,110 @@ using Server.Items; namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.DeathWatchBeetleHatchling")] - public class DeathwatchBeetleHatchling : BaseCreature - { - [Constructible] - public DeathwatchBeetleHatchling() : base(AIType.AI_Melee, Core.ML ? FightMode.Aggressor : FightMode.Closest, 10, 1, - 0.2, 0.4) + [TypeAlias("Server.Mobiles.DeathWatchBeetleHatchling")] + public class DeathwatchBeetleHatchling : BaseCreature { - Body = 242; + [Constructible] + public DeathwatchBeetleHatchling() : base( + AIType.AI_Melee, + Core.ML ? FightMode.Aggressor : FightMode.Closest, + 10, + 1, + 0.2, + 0.4 + ) + { + Body = 242; - SetStr(26, 50); - SetDex(41, 52); - SetInt(21, 30); + SetStr(26, 50); + SetDex(41, 52); + SetInt(21, 30); - SetHits(51, 60); - SetMana(20); + SetHits(51, 60); + SetMana(20); - SetDamage(2, 8); + SetDamage(2, 8); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 35, 40); - SetResistance(ResistanceType.Fire, 15, 30); - SetResistance(ResistanceType.Cold, 15, 30); - SetResistance(ResistanceType.Poison, 20, 40); - SetResistance(ResistanceType.Energy, 20, 35); + SetResistance(ResistanceType.Physical, 35, 40); + SetResistance(ResistanceType.Fire, 15, 30); + SetResistance(ResistanceType.Cold, 15, 30); + SetResistance(ResistanceType.Poison, 20, 40); + SetResistance(ResistanceType.Energy, 20, 35); - SetSkill(SkillName.Wrestling, 30.1, 40.0); - SetSkill(SkillName.Tactics, 47.1, 57.0); - SetSkill(SkillName.MagicResist, 30.1, 38.0); - SetSkill(SkillName.Anatomy, 20.1, 24.0); + SetSkill(SkillName.Wrestling, 30.1, 40.0); + SetSkill(SkillName.Tactics, 47.1, 57.0); + SetSkill(SkillName.MagicResist, 30.1, 38.0); + SetSkill(SkillName.Anatomy, 20.1, 24.0); - Fame = 700; - Karma = -700; + Fame = 700; + Karma = -700; - if (Utility.RandomBool()) - { - Item i = Loot.RandomReagent(); - i.Amount = 3; - PackItem(i); - } + if (Utility.RandomBool()) + { + var i = Loot.RandomReagent(); + i.Amount = 3; + PackItem(i); + } - switch (Utility.Random(12)) - { - case 0: - PackItem(new LeatherGorget()); - break; - case 1: - PackItem(new LeatherGloves()); - break; - case 2: - PackItem(new LeatherArms()); - break; - case 3: - PackItem(new LeatherLegs()); - break; - case 4: - PackItem(new LeatherCap()); - break; - case 5: - PackItem(new LeatherChest()); - break; - } + switch (Utility.Random(12)) + { + case 0: + PackItem(new LeatherGorget()); + break; + case 1: + PackItem(new LeatherGloves()); + break; + case 2: + PackItem(new LeatherArms()); + break; + case 3: + PackItem(new LeatherLegs()); + break; + case 4: + PackItem(new LeatherCap()); + break; + case 5: + PackItem(new LeatherChest()); + break; + } + } + + public DeathwatchBeetleHatchling(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a deathwatchbeetle hatchling corpse"; + public override string DefaultName => "a deathwatch beetle hatchling"; + public override int Hides => 8; + + public override int GetAngerSound() => 0x4F3; + + public override int GetIdleSound() => 0x4F2; + + public override int GetAttackSound() => 0x4F1; + + public override int GetHurtSound() => 0x4F4; + + public override int GetDeathSound() => 0x4F0; + + public override void GenerateLoot() + { + AddLoot(LootPack.LowScrolls, 1); + AddLoot(LootPack.Potions, 1); + } + + 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(); + } } - - public DeathwatchBeetleHatchling(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a deathwatchbeetle hatchling corpse"; - public override string DefaultName => "a deathwatch beetle hatchling"; - public override int Hides => 8; - - public override int GetAngerSound() => 0x4F3; - - public override int GetIdleSound() => 0x4F2; - - public override int GetAttackSound() => 0x4F1; - - public override int GetHurtSound() => 0x4F4; - - public override int GetDeathSound() => 0x4F0; - - public override void GenerateLoot() - { - AddLoot(LootPack.LowScrolls, 1); - AddLoot(LootPack.Potions, 1); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/SE/EliteNinja.cs b/Projects/UOContent/Mobiles/Monsters/SE/EliteNinja.cs index b07ffc12b..d6703580d 100644 --- a/Projects/UOContent/Mobiles/Monsters/SE/EliteNinja.cs +++ b/Projects/UOContent/Mobiles/Monsters/SE/EliteNinja.cs @@ -2,118 +2,118 @@ using Server.Items; namespace Server.Mobiles { - public class EliteNinja : BaseCreature - { - [Constructible] - public EliteNinja() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class EliteNinja : BaseCreature { - SpeechHue = Utility.RandomDyedHue(); - Hue = Race.Human.RandomSkinHue(); - Female = Utility.RandomBool(); - - Body = Female ? 0x191 : 0x190; - - SetHits(251, 350); - - SetStr(126, 225); - SetDex(81, 95); - SetInt(151, 165); - - SetDamage(12, 20); - - SetDamageType(ResistanceType.Physical, 65); - SetDamageType(ResistanceType.Fire, 15); - SetDamageType(ResistanceType.Poison, 15); - SetDamageType(ResistanceType.Energy, 5); - - SetResistance(ResistanceType.Physical, 35, 65); - SetResistance(ResistanceType.Fire, 40, 60); - SetResistance(ResistanceType.Cold, 25, 45); - SetResistance(ResistanceType.Poison, 40, 60); - SetResistance(ResistanceType.Energy, 35, 55); - - SetSkill(SkillName.Anatomy, 105.0, 120.0); - SetSkill(SkillName.MagicResist, 80.0, 100.0); - SetSkill(SkillName.Tactics, 115.0, 130.0); - SetSkill(SkillName.Wrestling, 95.0, 120.0); - SetSkill(SkillName.Fencing, 95.0, 120.0); - SetSkill(SkillName.Macing, 95.0, 120.0); - SetSkill(SkillName.Swords, 95.0, 120.0); - SetSkill(SkillName.Ninjitsu, 95.0, 120.0); - - Fame = 8500; - Karma = -8500; - - /* TODO: - Uses Smokebombs - Hides - Stealths - Can use Ninjitsu Abilities - Can change weapons during a fight - */ - - AddItem(new NinjaTabi()); - AddItem(new LeatherNinjaJacket()); - AddItem(new LeatherNinjaHood()); - AddItem(new LeatherNinjaPants()); - AddItem(new LeatherNinjaMitts()); - - if (Utility.RandomDouble() < 0.33) - AddItem(new SmokeBomb()); - - AddItem( - Utility.Random(8) switch + [Constructible] + public EliteNinja() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) { - 0 => new Tessen(), - 1 => new Wakizashi(), - 2 => new Nunchaku(), - 3 => new Daisho(), - 4 => new Sai(), - 5 => new Tekagi(), - 6 => new Kama(), - _ => new Katana() // 7 + SpeechHue = Utility.RandomDyedHue(); + Hue = Race.Human.RandomSkinHue(); + Female = Utility.RandomBool(); + + Body = Female ? 0x191 : 0x190; + + SetHits(251, 350); + + SetStr(126, 225); + SetDex(81, 95); + SetInt(151, 165); + + SetDamage(12, 20); + + SetDamageType(ResistanceType.Physical, 65); + SetDamageType(ResistanceType.Fire, 15); + SetDamageType(ResistanceType.Poison, 15); + SetDamageType(ResistanceType.Energy, 5); + + SetResistance(ResistanceType.Physical, 35, 65); + SetResistance(ResistanceType.Fire, 40, 60); + SetResistance(ResistanceType.Cold, 25, 45); + SetResistance(ResistanceType.Poison, 40, 60); + SetResistance(ResistanceType.Energy, 35, 55); + + SetSkill(SkillName.Anatomy, 105.0, 120.0); + SetSkill(SkillName.MagicResist, 80.0, 100.0); + SetSkill(SkillName.Tactics, 115.0, 130.0); + SetSkill(SkillName.Wrestling, 95.0, 120.0); + SetSkill(SkillName.Fencing, 95.0, 120.0); + SetSkill(SkillName.Macing, 95.0, 120.0); + SetSkill(SkillName.Swords, 95.0, 120.0); + SetSkill(SkillName.Ninjitsu, 95.0, 120.0); + + Fame = 8500; + Karma = -8500; + + /* TODO: + Uses Smokebombs + Hides + Stealths + Can use Ninjitsu Abilities + Can change weapons during a fight + */ + + AddItem(new NinjaTabi()); + AddItem(new LeatherNinjaJacket()); + AddItem(new LeatherNinjaHood()); + AddItem(new LeatherNinjaPants()); + AddItem(new LeatherNinjaMitts()); + + if (Utility.RandomDouble() < 0.33) + AddItem(new SmokeBomb()); + + AddItem( + Utility.Random(8) switch + { + 0 => new Tessen(), + 1 => new Wakizashi(), + 2 => new Nunchaku(), + 3 => new Daisho(), + 4 => new Sai(), + 5 => new Tekagi(), + 6 => new Kama(), + _ => new Katana() // 7 + } + ); + + Utility.AssignRandomHair(this); } - ); - Utility.AssignRandomHair(this); + public EliteNinja(Serial serial) : base(serial) + { + } + + public override bool ClickTitle => false; + public override string DefaultName => "an elite ninja"; + + public override bool BardImmune => true; + + public override bool AlwaysMurderer => true; + + public override void OnDeath(Container c) + { + base.OnDeath(c); + c.DropItem(new BookOfNinjitsu()); + } + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.Rich); + AddLoot(LootPack.Gems, 2); + } + + 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 EliteNinja(Serial serial) : base(serial) - { - } - - public override bool ClickTitle => false; - public override string DefaultName => "an elite ninja"; - - public override bool BardImmune => true; - - public override bool AlwaysMurderer => true; - - public override void OnDeath(Container c) - { - base.OnDeath(c); - c.DropItem(new BookOfNinjitsu()); - } - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.Rich); - AddLoot(LootPack.Gems, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/SE/FanDancer.cs b/Projects/UOContent/Mobiles/Monsters/SE/FanDancer.cs index 50b214763..ea73129a6 100644 --- a/Projects/UOContent/Mobiles/Monsters/SE/FanDancer.cs +++ b/Projects/UOContent/Mobiles/Monsters/SE/FanDancer.cs @@ -6,180 +6,211 @@ using Server.Network; namespace Server.Mobiles { - public class FanDancer : BaseCreature - { - private static readonly HashSet m_Table = new HashSet(); - - [Constructible] - public FanDancer() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class FanDancer : BaseCreature { - Body = 247; - BaseSoundID = 0x372; + private static readonly HashSet m_Table = new HashSet(); - SetStr(301, 375); - SetDex(201, 255); - SetInt(21, 25); + [Constructible] + public FanDancer() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 247; + BaseSoundID = 0x372; - SetHits(351, 430); + SetStr(301, 375); + SetDex(201, 255); + SetInt(21, 25); - SetDamage(12, 17); + SetHits(351, 430); - SetDamageType(ResistanceType.Physical, 70); - SetDamageType(ResistanceType.Fire, 10); - SetDamageType(ResistanceType.Cold, 10); - SetDamageType(ResistanceType.Poison, 10); + SetDamage(12, 17); - SetResistance(ResistanceType.Physical, 40, 60); - SetResistance(ResistanceType.Fire, 50, 70); - SetResistance(ResistanceType.Cold, 50, 70); - SetResistance(ResistanceType.Poison, 50, 70); - SetResistance(ResistanceType.Energy, 40, 60); + SetDamageType(ResistanceType.Physical, 70); + SetDamageType(ResistanceType.Fire, 10); + SetDamageType(ResistanceType.Cold, 10); + SetDamageType(ResistanceType.Poison, 10); - SetSkill(SkillName.MagicResist, 100.1, 110.0); - SetSkill(SkillName.Tactics, 85.1, 95.0); - SetSkill(SkillName.Wrestling, 85.1, 95.0); - SetSkill(SkillName.Anatomy, 85.1, 95.0); + SetResistance(ResistanceType.Physical, 40, 60); + SetResistance(ResistanceType.Fire, 50, 70); + SetResistance(ResistanceType.Cold, 50, 70); + SetResistance(ResistanceType.Poison, 50, 70); + SetResistance(ResistanceType.Energy, 40, 60); - Fame = 9000; - Karma = -9000; + SetSkill(SkillName.MagicResist, 100.1, 110.0); + SetSkill(SkillName.Tactics, 85.1, 95.0); + SetSkill(SkillName.Wrestling, 85.1, 95.0); + SetSkill(SkillName.Anatomy, 85.1, 95.0); - if (Utility.RandomDouble() < .33) - PackItem(Seed.RandomBonsaiSeed()); + Fame = 9000; + Karma = -9000; - AddItem(new Tessen()); + if (Utility.RandomDouble() < .33) + PackItem(Seed.RandomBonsaiSeed()); - if (Utility.RandomDouble() <= 0.02) - PackItem(new OrigamiPaper()); - } + AddItem(new Tessen()); - public FanDancer(Serial serial) : base(serial) - { - } + if (Utility.RandomDouble() <= 0.02) + PackItem(new OrigamiPaper()); + } - public override string CorpseName => "a fan dancer corpse"; - public override string DefaultName => "a fan dancer"; + public FanDancer(Serial serial) : base(serial) + { + } - public override bool Uncalmable => true; + public override string CorpseName => "a fan dancer corpse"; + public override string DefaultName => "a fan dancer"; - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.Rich); - AddLoot(LootPack.Gems, 2); - } + public override bool Uncalmable => true; - /* TODO: Repel Magic - * 10% chance of repelling a melee attack (why did they call it repel magic anyway?) - * Cliloc: 1070844 - * Effect: damage is dealt to the attacker, no damage is taken by the fan dancer - */ + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.Rich); + AddLoot(LootPack.Gems, 2); + } - public override void OnDamagedBySpell(Mobile attacker) - { - base.OnDamagedBySpell(attacker); - - if (Utility.RandomDouble() < 0.8 && !attacker.InRange(this, 1)) - { - /* Fan Throw - * Effect: - To: "0x57D4F5B" - ItemId: "0x27A3" - ItemIdName: "Tessen" - FromLocation: "(992 299, 24)" - ToLocation: "(992 308, 22)" - Speed: "10" - Duration: "0" - FixedDirection: "False" - Explode: "False" - Hue: "0x0" - Render: "0x0" - * Damage: 50-65 - */ - Effects.SendPacket(attacker, attacker.Map, - new HuedEffect(EffectType.Moving, Serial.Zero, Serial.Zero, 0x27A3, Location, attacker.Location, 10, 0, - false, false, 0, 0)); - AOS.Damage(attacker, this, Utility.RandomMinMax(50, 65), 100, 0, 0, 0, 0); - } - } - - public override void OnGotMeleeAttack(Mobile attacker) - { - base.OnGotMeleeAttack(attacker); - - if (Utility.RandomDouble() < 0.8 && !attacker.InRange(this, 1)) - { - /* Fan Throw - * Effect: - To: "0x57D4F5B" - ItemId: "0x27A3" - ItemIdName: "Tessen" - FromLocation: "(992 299, 24)" - ToLocation: "(992 308, 22)" - Speed: "10" - Duration: "0" - FixedDirection: "False" - Explode: "False" - Hue: "0x0" - Render: "0x0" - * Damage: 50-65 - */ - Effects.SendPacket(attacker, attacker.Map, - new HuedEffect(EffectType.Moving, Serial.Zero, Serial.Zero, 0x27A3, Location, attacker.Location, 10, 0, - false, false, 0, 0)); - AOS.Damage(attacker, this, Utility.RandomMinMax(50, 65), 100, 0, 0, 0, 0); - } - } - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (!IsFanned(defender) && Utility.RandomDouble() < 0.05) - { - /* Fanning Fire - * Graphic: Type: "3" From: "0x57D4F5B" To: "0x0" ItemId: "0x3709" ItemIdName: "fire column" FromLocation: "(994 325, 16)" ToLocation: "(994 325, 16)" Speed: "10" Duration: "30" FixedDirection: "True" Explode: "False" Hue: "0x0" RenderMode: "0x0" Effect: "0x34" ExplodeEffect: "0x1" ExplodeSound: "0x0" Serial: "0x57D4F5B" Layer: "5" Unknown: "0x0" - * Sound: 0x208 - * Start cliloc: 1070833 - * Effect: Fire res -10% for 10 seconds - * Damage: 35-45, 100% fire - * End cliloc: 1070834 - * Effect does not stack + /* TODO: Repel Magic + * 10% chance of repelling a melee attack (why did they call it repel magic anyway?) + * Cliloc: 1070844 + * Effect: damage is dealt to the attacker, no damage is taken by the fan dancer */ - defender.SendLocalizedMessage( - 1070833); // The creature fans you with fire, reducing your resistance to fire attacks. + public override void OnDamagedBySpell(Mobile attacker) + { + base.OnDamagedBySpell(attacker); - int effect = -(defender.FireResistance / 10); + if (Utility.RandomDouble() < 0.8 && !attacker.InRange(this, 1)) + { + /* Fan Throw + * Effect: - To: "0x57D4F5B" - ItemId: "0x27A3" - ItemIdName: "Tessen" - FromLocation: "(992 299, 24)" - ToLocation: "(992 308, 22)" - Speed: "10" - Duration: "0" - FixedDirection: "False" - Explode: "False" - Hue: "0x0" - Render: "0x0" + * Damage: 50-65 + */ + Effects.SendPacket( + attacker, + attacker.Map, + new HuedEffect( + EffectType.Moving, + Serial.Zero, + Serial.Zero, + 0x27A3, + Location, + attacker.Location, + 10, + 0, + false, + false, + 0, + 0 + ) + ); + AOS.Damage(attacker, this, Utility.RandomMinMax(50, 65), 100, 0, 0, 0, 0); + } + } - ResistanceMod mod = new ResistanceMod(ResistanceType.Fire, effect); + public override void OnGotMeleeAttack(Mobile attacker) + { + base.OnGotMeleeAttack(attacker); - defender.FixedParticles(0x37B9, 10, 30, 0x34, EffectLayer.RightFoot); - defender.PlaySound(0x208); + if (Utility.RandomDouble() < 0.8 && !attacker.InRange(this, 1)) + { + /* Fan Throw + * Effect: - To: "0x57D4F5B" - ItemId: "0x27A3" - ItemIdName: "Tessen" - FromLocation: "(992 299, 24)" - ToLocation: "(992 308, 22)" - Speed: "10" - Duration: "0" - FixedDirection: "False" - Explode: "False" - Hue: "0x0" - Render: "0x0" + * Damage: 50-65 + */ + Effects.SendPacket( + attacker, + attacker.Map, + new HuedEffect( + EffectType.Moving, + Serial.Zero, + Serial.Zero, + 0x27A3, + Location, + attacker.Location, + 10, + 0, + false, + false, + 0, + 0 + ) + ); + AOS.Damage(attacker, this, Utility.RandomMinMax(50, 65), 100, 0, 0, 0, 0); + } + } - // This should be done in place of the normal attack damage. - // AOS.Damage( defender, this, Utility.RandomMinMax( 35, 45 ), 0, 100, 0, 0, 0 ); + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); - defender.AddResistanceMod(mod); + if (!IsFanned(defender) && Utility.RandomDouble() < 0.05) + { + /* Fanning Fire + * Graphic: Type: "3" From: "0x57D4F5B" To: "0x0" ItemId: "0x3709" ItemIdName: "fire column" FromLocation: "(994 325, 16)" ToLocation: "(994 325, 16)" Speed: "10" Duration: "30" FixedDirection: "True" Explode: "False" Hue: "0x0" RenderMode: "0x0" Effect: "0x34" ExplodeEffect: "0x1" ExplodeSound: "0x0" Serial: "0x57D4F5B" Layer: "5" Unknown: "0x0" + * Sound: 0x208 + * Start cliloc: 1070833 + * Effect: Fire res -10% for 10 seconds + * Damage: 35-45, 100% fire + * End cliloc: 1070834 + * Effect does not stack + */ - ExpireTimer timer = new ExpireTimer(defender, mod, TimeSpan.FromSeconds(10.0)); - timer.Start(); - m_Table.Add(defender); - } + defender.SendLocalizedMessage( + 1070833 + ); // The creature fans you with fire, reducing your resistance to fire attacks. + + var effect = -(defender.FireResistance / 10); + + var mod = new ResistanceMod(ResistanceType.Fire, effect); + + defender.FixedParticles(0x37B9, 10, 30, 0x34, EffectLayer.RightFoot); + defender.PlaySound(0x208); + + // This should be done in place of the normal attack damage. + // AOS.Damage( defender, this, Utility.RandomMinMax( 35, 45 ), 0, 100, 0, 0, 0 ); + + defender.AddResistanceMod(mod); + + var timer = new ExpireTimer(defender, mod, TimeSpan.FromSeconds(10.0)); + timer.Start(); + m_Table.Add(defender); + } + } + + public bool IsFanned(Mobile m) => m_Table.Contains(m); + + 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(); + } + + private class ExpireTimer : Timer + { + private readonly Mobile m_Mobile; + private readonly ResistanceMod m_Mod; + + public ExpireTimer(Mobile m, ResistanceMod mod, TimeSpan delay) : base(delay) + { + m_Mobile = m; + m_Mod = mod; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + m_Mobile.SendLocalizedMessage(1070834); // Your resistance to fire attacks has returned. + m_Mobile.RemoveResistanceMod(m_Mod); + Stop(); + m_Table.Remove(m_Mobile); + } + } } - - public bool IsFanned(Mobile m) => m_Table.Contains(m); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private class ExpireTimer : Timer - { - private readonly Mobile m_Mobile; - private readonly ResistanceMod m_Mod; - - public ExpireTimer(Mobile m, ResistanceMod mod, TimeSpan delay) : base(delay) - { - m_Mobile = m; - m_Mod = mod; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - m_Mobile.SendLocalizedMessage(1070834); // Your resistance to fire attacks has returned. - m_Mobile.RemoveResistanceMod(m_Mod); - Stop(); - m_Table.Remove(m_Mobile); - } - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/SE/FireBeetle.cs b/Projects/UOContent/Mobiles/Monsters/SE/FireBeetle.cs index 220d81c5a..49249f6c7 100644 --- a/Projects/UOContent/Mobiles/Monsters/SE/FireBeetle.cs +++ b/Projects/UOContent/Mobiles/Monsters/SE/FireBeetle.cs @@ -3,100 +3,100 @@ using Server.Items; namespace Server.Mobiles { - [Forge] - public class FireBeetle : BaseMount - { - [Constructible] - public FireBeetle() : base("a fire beetle", 0xA9, 0x3E95, AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + [Forge] + public class FireBeetle : BaseMount { - SetStr(300); - SetDex(100); - SetInt(500); + [Constructible] + public FireBeetle() : base("a fire beetle", 0xA9, 0x3E95, AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + SetStr(300); + SetDex(100); + SetInt(500); - SetHits(200); + SetHits(200); - SetDamage(7, 20); + SetDamage(7, 20); - SetDamageType(ResistanceType.Physical, 0); - SetDamageType(ResistanceType.Fire, 100); + SetDamageType(ResistanceType.Physical, 0); + SetDamageType(ResistanceType.Fire, 100); - SetResistance(ResistanceType.Physical, 40); - SetResistance(ResistanceType.Fire, 70, 75); - SetResistance(ResistanceType.Cold, 10); - SetResistance(ResistanceType.Poison, 30); - SetResistance(ResistanceType.Energy, 30); + SetResistance(ResistanceType.Physical, 40); + SetResistance(ResistanceType.Fire, 70, 75); + SetResistance(ResistanceType.Cold, 10); + SetResistance(ResistanceType.Poison, 30); + SetResistance(ResistanceType.Energy, 30); - SetSkill(SkillName.MagicResist, 90.0); - SetSkill(SkillName.Tactics, 100.0); - SetSkill(SkillName.Wrestling, 100.0); + SetSkill(SkillName.MagicResist, 90.0); + SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.Wrestling, 100.0); - Fame = 4000; - Karma = -4000; + Fame = 4000; + Karma = -4000; - Tamable = true; - ControlSlots = 3; - MinTameSkill = 93.9; + Tamable = true; + ControlSlots = 3; + MinTameSkill = 93.9; - PackItem(new SulfurousAsh(Utility.RandomMinMax(16, 25))); - PackItem(new IronIngot(2)); + PackItem(new SulfurousAsh(Utility.RandomMinMax(16, 25))); + PackItem(new IronIngot(2)); - Hue = 0x489; + Hue = 0x489; + } + + public FireBeetle(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a fire beetle corpse"; + public override bool SubdueBeforeTame => true; // Must be beaten into submission + public override bool StatLossAfterTame => true; + public virtual double BoostedSpeed => 0.1; + public override bool ReduceSpeedWithDamage => false; + + public override int Meat => 16; + public override FoodType FavoriteFood => FoodType.Meat; + + public override void OnHarmfulSpell(Mobile from) + { + if (!Controlled && ControlMaster == null) + CurrentSpeed = BoostedSpeed; + } + + public override void OnCombatantChange() + { + if (Combatant == null && !Controlled && ControlMaster == null) + CurrentSpeed = PassiveSpeed; + } + + public override bool OverrideBondingReqs() => true; + + public override int GetAngerSound() => 0x21D; + + public override int GetIdleSound() => 0x21D; + + public override int GetAttackSound() => 0x162; + + public override int GetHurtSound() => 0x163; + + public override int GetDeathSound() => 0x21D; + + public override double GetControlChance(Mobile m, bool useBaseSkill = false) => 1.0; + + 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) + Hue = 0x489; + } } - - public FireBeetle(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a fire beetle corpse"; - public override bool SubdueBeforeTame => true; // Must be beaten into submission - public override bool StatLossAfterTame => true; - public virtual double BoostedSpeed => 0.1; - public override bool ReduceSpeedWithDamage => false; - - public override int Meat => 16; - public override FoodType FavoriteFood => FoodType.Meat; - - public override void OnHarmfulSpell(Mobile from) - { - if (!Controlled && ControlMaster == null) - CurrentSpeed = BoostedSpeed; - } - - public override void OnCombatantChange() - { - if (Combatant == null && !Controlled && ControlMaster == null) - CurrentSpeed = PassiveSpeed; - } - - public override bool OverrideBondingReqs() => true; - - public override int GetAngerSound() => 0x21D; - - public override int GetIdleSound() => 0x21D; - - public override int GetAttackSound() => 0x162; - - public override int GetHurtSound() => 0x163; - - public override int GetDeathSound() => 0x21D; - - public override double GetControlChance(Mobile m, bool useBaseSkill = false) => 1.0; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (version == 0) - Hue = 0x489; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/SE/Kappa.cs b/Projects/UOContent/Mobiles/Monsters/SE/Kappa.cs index 7c961c3eb..120a462e8 100644 --- a/Projects/UOContent/Mobiles/Monsters/SE/Kappa.cs +++ b/Projects/UOContent/Mobiles/Monsters/SE/Kappa.cs @@ -5,188 +5,189 @@ using Server.Items; namespace Server.Mobiles { - public class Kappa : BaseCreature - { - private static readonly Dictionary m_Table = new Dictionary(); - - [Constructible] - public Kappa() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Kappa : BaseCreature { - Body = 240; + private static readonly Dictionary m_Table = new Dictionary(); - SetStr(186, 230); - SetDex(51, 75); - SetInt(41, 55); - - SetMana(30); - - SetHits(151, 180); - - SetDamage(6, 12); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 35, 50); - SetResistance(ResistanceType.Fire, 35, 50); - SetResistance(ResistanceType.Cold, 25, 50); - SetResistance(ResistanceType.Poison, 35, 50); - SetResistance(ResistanceType.Energy, 20, 30); - - SetSkill(SkillName.MagicResist, 60.1, 70.0); - SetSkill(SkillName.Tactics, 79.1, 89.0); - SetSkill(SkillName.Wrestling, 60.1, 70.0); - - Fame = 1700; - Karma = -1700; - - PackItem(new RawFishSteak(3)); - for (int i = 0; i < 2; i++) - switch (Utility.Random(6)) + [Constructible] + public Kappa() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) { - case 0: - PackItem(new Gears()); - break; - case 1: - PackItem(new Hinge()); - break; - case 2: - PackItem(new Axle()); - break; - } - if (Core.ML && Utility.RandomDouble() < .33) - PackItem(Seed.RandomPeculiarSeed(4)); - } + Body = 240; - public Kappa(Serial serial) : base(serial) - { - } + SetStr(186, 230); + SetDex(51, 75); + SetInt(41, 55); - public override string CorpseName => "a kappa corpse"; - public override string DefaultName => "a kappa"; + SetMana(30); - public override void GenerateLoot() - { - AddLoot(LootPack.Meager); - AddLoot(LootPack.Average); - } + SetHits(151, 180); - public override int GetAngerSound() => 0x50B; + SetDamage(6, 12); - public override int GetIdleSound() => 0x50A; + SetDamageType(ResistanceType.Physical, 100); - public override int GetAttackSound() => 0x509; + SetResistance(ResistanceType.Physical, 35, 50); + SetResistance(ResistanceType.Fire, 35, 50); + SetResistance(ResistanceType.Cold, 25, 50); + SetResistance(ResistanceType.Poison, 35, 50); + SetResistance(ResistanceType.Energy, 20, 30); - public override int GetHurtSound() => 0x50C; + SetSkill(SkillName.MagicResist, 60.1, 70.0); + SetSkill(SkillName.Tactics, 79.1, 89.0); + SetSkill(SkillName.Wrestling, 60.1, 70.0); - public override int GetDeathSound() => 0x508; + Fame = 1700; + Karma = -1700; - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); + PackItem(new RawFishSteak(3)); + for (var i = 0; i < 2; i++) + switch (Utility.Random(6)) + { + case 0: + PackItem(new Gears()); + break; + case 1: + PackItem(new Hinge()); + break; + case 2: + PackItem(new Axle()); + break; + } - if (Utility.RandomBool()) - if (!IsBeingDrained(defender) && Mana > 14) - { - defender.SendLocalizedMessage(1070848); // You feel your life force being stolen away. - BeginLifeDrain(defender, this); - Mana -= 15; - } - } - - public static bool IsBeingDrained(Mobile m) => m_Table.ContainsKey(m); - - public static void BeginLifeDrain(Mobile m, Mobile from) - { - m_Table.TryGetValue(m, out InternalTimer timer); - timer?.Stop(); - m_Table[m] = timer = new InternalTimer(from, m); - - timer.Start(); - } - - public static void DrainLife(Mobile m, Mobile from) - { - if (m.Alive) - { - int damageGiven = AOS.Damage(m, from, 5, 0, 0, 0, 0, 100); - from.Hits += damageGiven; - } - else - { - EndLifeDrain(m); - } - } - - public static void EndLifeDrain(Mobile m) - { - if (m_Table.TryGetValue(m, out InternalTimer timer)) - { - timer?.Stop(); - m_Table.Remove(m); - m.SendLocalizedMessage(1070849); // The drain on your life force is gone. - } - } - - public override void OnDamage(int amount, Mobile from, bool willKill) - { - if (from?.Map != null) - { - int amt = 0; - Mobile target = this; - int rand = Utility.Random(1, 100); - if (willKill) amt = (rand % 5 >> 2) + 3; - if (Hits < 100 && rand < 21) - { - target = rand % 2 < 1 ? this : from; - amt++; + if (Core.ML && Utility.RandomDouble() < .33) + PackItem(Seed.RandomPeculiarSeed(4)); } - if (amt > 0) + public Kappa(Serial serial) : base(serial) { - SpillAcid(target, amt); - from.SendLocalizedMessage(1070820); - if (Mana > 14) - Mana -= 15; } - } - base.OnDamage(amount, from, willKill); + public override string CorpseName => "a kappa corpse"; + public override string DefaultName => "a kappa"; + + public override void GenerateLoot() + { + AddLoot(LootPack.Meager); + AddLoot(LootPack.Average); + } + + public override int GetAngerSound() => 0x50B; + + public override int GetIdleSound() => 0x50A; + + public override int GetAttackSound() => 0x509; + + public override int GetHurtSound() => 0x50C; + + public override int GetDeathSound() => 0x508; + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomBool()) + if (!IsBeingDrained(defender) && Mana > 14) + { + defender.SendLocalizedMessage(1070848); // You feel your life force being stolen away. + BeginLifeDrain(defender, this); + Mana -= 15; + } + } + + public static bool IsBeingDrained(Mobile m) => m_Table.ContainsKey(m); + + public static void BeginLifeDrain(Mobile m, Mobile from) + { + m_Table.TryGetValue(m, out var timer); + timer?.Stop(); + m_Table[m] = timer = new InternalTimer(from, m); + + timer.Start(); + } + + public static void DrainLife(Mobile m, Mobile from) + { + if (m.Alive) + { + var damageGiven = AOS.Damage(m, from, 5, 0, 0, 0, 0, 100); + from.Hits += damageGiven; + } + else + { + EndLifeDrain(m); + } + } + + public static void EndLifeDrain(Mobile m) + { + if (m_Table.TryGetValue(m, out var timer)) + { + timer?.Stop(); + m_Table.Remove(m); + m.SendLocalizedMessage(1070849); // The drain on your life force is gone. + } + } + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + if (from?.Map != null) + { + var amt = 0; + Mobile target = this; + var rand = Utility.Random(1, 100); + if (willKill) amt = ((rand % 5) >> 2) + 3; + if (Hits < 100 && rand < 21) + { + target = rand % 2 < 1 ? this : from; + amt++; + } + + if (amt > 0) + { + SpillAcid(target, amt); + from.SendLocalizedMessage(1070820); + if (Mana > 14) + Mana -= 15; + } + } + + base.OnDamage(amount, from, willKill); + } + + public override Item NewHarmfulItem() => new AcidSlime(TimeSpan.FromSeconds(10), 5, 10); + + 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(); + } + + private class InternalTimer : Timer + { + private readonly Mobile m_From; + private readonly Mobile m_Mobile; + private int m_Count; + + public InternalTimer(Mobile from, Mobile m) : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)) + { + m_From = from; + m_Mobile = m; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + DrainLife(m_Mobile, m_From); + + if (Running && ++m_Count == 5) + EndLifeDrain(m_Mobile); + } + } } - - public override Item NewHarmfulItem() => new AcidSlime(TimeSpan.FromSeconds(10), 5, 10); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - - private class InternalTimer : Timer - { - private int m_Count; - private readonly Mobile m_From; - private readonly Mobile m_Mobile; - - public InternalTimer(Mobile from, Mobile m) : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)) - { - m_From = from; - m_Mobile = m; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - DrainLife(m_Mobile, m_From); - - if (Running && ++m_Count == 5) - EndLifeDrain(m_Mobile); - } - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/SE/KazeKemono.cs b/Projects/UOContent/Mobiles/Monsters/SE/KazeKemono.cs index a0471b400..b12cd2d8a 100644 --- a/Projects/UOContent/Mobiles/Monsters/SE/KazeKemono.cs +++ b/Projects/UOContent/Mobiles/Monsters/SE/KazeKemono.cs @@ -3,175 +3,179 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class KazeKemono : BaseCreature - { - private static readonly Dictionary m_FlurryOfTwigsTable = new Dictionary(); - private static readonly Dictionary m_ChlorophylBlastTable = new Dictionary(); - - [Constructible] - public KazeKemono() - : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class KazeKemono : BaseCreature { - Body = 196; - BaseSoundID = 655; + private static readonly Dictionary m_FlurryOfTwigsTable = new Dictionary(); - SetStr(201, 275); - SetDex(101, 155); - SetInt(101, 105); + private static readonly Dictionary m_ChlorophylBlastTable = + new Dictionary(); - SetHits(251, 330); - - SetDamage(15, 20); - - SetDamageType(ResistanceType.Physical, 70); - SetDamageType(ResistanceType.Fire, 10); - SetDamageType(ResistanceType.Cold, 10); - SetDamageType(ResistanceType.Poison, 10); - - SetResistance(ResistanceType.Physical, 50, 70); - SetResistance(ResistanceType.Fire, 30, 60); - SetResistance(ResistanceType.Cold, 30, 60); - SetResistance(ResistanceType.Poison, 50, 70); - SetResistance(ResistanceType.Energy, 60, 80); - - SetSkill(SkillName.MagicResist, 110.1, 125.0); - SetSkill(SkillName.Tactics, 55.1, 65.0); - SetSkill(SkillName.Wrestling, 85.1, 95.0); - SetSkill(SkillName.Anatomy, 25.1, 35.0); - SetSkill(SkillName.Magery, 95.1, 105.0); - - Fame = 8000; - Karma = -8000; - } - - public KazeKemono(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a kaze kemono corpse"; - public override string DefaultName => "a kaze kemono"; - - public override bool BleedImmune => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich, 3); - } - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (Utility.RandomDouble() < 0.1) - { - /* Flurry of Twigs - * Start cliloc: 1070850 - * Effect: Physical resistance -15% for 5 seconds - * End cliloc: 1070852 - * Effect: Type: "3" From: "0x57D4F5B" To: "0x0" ItemId: "0x37B9" ItemIdName: "glow" FromLocation: "(1048 779, 6)" ToLocation: "(1048 779, 6)" Speed: "10" Duration: "5" FixedDirection: "True" Explode: "False" - */ - - if (m_FlurryOfTwigsTable.TryGetValue(defender, out ExpireTimer timer)) + [Constructible] + public KazeKemono() + : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) { - timer.DoExpire(); - defender.SendLocalizedMessage(1070851); // The creature lands another blow in your weakened state. - } - else - { - defender.SendLocalizedMessage( - 1070850); // The creature's flurry of twigs has made you more susceptible to physical attacks! + Body = 196; + BaseSoundID = 655; + + SetStr(201, 275); + SetDex(101, 155); + SetInt(101, 105); + + SetHits(251, 330); + + SetDamage(15, 20); + + SetDamageType(ResistanceType.Physical, 70); + SetDamageType(ResistanceType.Fire, 10); + SetDamageType(ResistanceType.Cold, 10); + SetDamageType(ResistanceType.Poison, 10); + + SetResistance(ResistanceType.Physical, 50, 70); + SetResistance(ResistanceType.Fire, 30, 60); + SetResistance(ResistanceType.Cold, 30, 60); + SetResistance(ResistanceType.Poison, 50, 70); + SetResistance(ResistanceType.Energy, 60, 80); + + SetSkill(SkillName.MagicResist, 110.1, 125.0); + SetSkill(SkillName.Tactics, 55.1, 65.0); + SetSkill(SkillName.Wrestling, 85.1, 95.0); + SetSkill(SkillName.Anatomy, 25.1, 35.0); + SetSkill(SkillName.Magery, 95.1, 105.0); + + Fame = 8000; + Karma = -8000; } - int effect = -(defender.PhysicalResistance * 15 / 100); - - ResistanceMod mod = new ResistanceMod(ResistanceType.Physical, effect); - - defender.FixedEffect(0x37B9, 10, 5); - defender.AddResistanceMod(mod); - - timer = new ExpireTimer(defender, mod, m_FlurryOfTwigsTable, TimeSpan.FromSeconds(5.0)); - timer.Start(); - m_FlurryOfTwigsTable[defender] = timer; - return; - } - - if (Utility.RandomDouble() < 0.05) - { - /* Chlorophyl Blast - * Start cliloc: 1070827 - * Effect: Energy resistance -50% for 10 seconds - * End cliloc: 1070829 - * Effect: Type: "3" From: "0x57D4F5B" To: "0x0" ItemId: "0x37B9" ItemIdName: "glow" FromLocation: "(1048 779, 6)" ToLocation: "(1048 779, 6)" Speed: "10" Duration: "5" FixedDirection: "True" Explode: "False" - */ - - if (m_ChlorophylBlastTable.TryGetValue(defender, out ExpireTimer timer)) + public KazeKemono(Serial serial) + : base(serial) { - timer.DoExpire(); - defender.SendLocalizedMessage(1070828); // The creature continues to hinder your energy resistance! - } - else - { - defender.SendLocalizedMessage( - 1070827); // The creature's attack has made you more susceptible to energy attacks! } - int effect = -(defender.EnergyResistance / 2); + public override string CorpseName => "a kaze kemono corpse"; + public override string DefaultName => "a kaze kemono"; - ResistanceMod mod = new ResistanceMod(ResistanceType.Energy, effect); + public override bool BleedImmune => true; - defender.FixedEffect(0x37B9, 10, 5); - defender.AddResistanceMod(mod); + public override void GenerateLoot() + { + AddLoot(LootPack.Rich, 3); + } - timer = new ExpireTimer(defender, mod, m_ChlorophylBlastTable, TimeSpan.FromSeconds(10.0)); - timer.Start(); - m_ChlorophylBlastTable[defender] = timer; - } + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomDouble() < 0.1) + { + /* Flurry of Twigs + * Start cliloc: 1070850 + * Effect: Physical resistance -15% for 5 seconds + * End cliloc: 1070852 + * Effect: Type: "3" From: "0x57D4F5B" To: "0x0" ItemId: "0x37B9" ItemIdName: "glow" FromLocation: "(1048 779, 6)" ToLocation: "(1048 779, 6)" Speed: "10" Duration: "5" FixedDirection: "True" Explode: "False" + */ + + if (m_FlurryOfTwigsTable.TryGetValue(defender, out var timer)) + { + timer.DoExpire(); + defender.SendLocalizedMessage(1070851); // The creature lands another blow in your weakened state. + } + else + { + defender.SendLocalizedMessage( + 1070850 + ); // The creature's flurry of twigs has made you more susceptible to physical attacks! + } + + var effect = -(defender.PhysicalResistance * 15 / 100); + + var mod = new ResistanceMod(ResistanceType.Physical, effect); + + defender.FixedEffect(0x37B9, 10, 5); + defender.AddResistanceMod(mod); + + timer = new ExpireTimer(defender, mod, m_FlurryOfTwigsTable, TimeSpan.FromSeconds(5.0)); + timer.Start(); + m_FlurryOfTwigsTable[defender] = timer; + return; + } + + if (Utility.RandomDouble() < 0.05) + { + /* Chlorophyl Blast + * Start cliloc: 1070827 + * Effect: Energy resistance -50% for 10 seconds + * End cliloc: 1070829 + * Effect: Type: "3" From: "0x57D4F5B" To: "0x0" ItemId: "0x37B9" ItemIdName: "glow" FromLocation: "(1048 779, 6)" ToLocation: "(1048 779, 6)" Speed: "10" Duration: "5" FixedDirection: "True" Explode: "False" + */ + + if (m_ChlorophylBlastTable.TryGetValue(defender, out var timer)) + { + timer.DoExpire(); + defender.SendLocalizedMessage(1070828); // The creature continues to hinder your energy resistance! + } + else + { + defender.SendLocalizedMessage( + 1070827 + ); // The creature's attack has made you more susceptible to energy attacks! + } + + var effect = -(defender.EnergyResistance / 2); + + var mod = new ResistanceMod(ResistanceType.Energy, effect); + + defender.FixedEffect(0x37B9, 10, 5); + defender.AddResistanceMod(mod); + + timer = new ExpireTimer(defender, mod, m_ChlorophylBlastTable, TimeSpan.FromSeconds(10.0)); + timer.Start(); + m_ChlorophylBlastTable[defender] = timer; + } + } + + 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(); + } + + private class ExpireTimer : Timer + { + private readonly Mobile m_Mobile; + private readonly ResistanceMod m_Mod; + private readonly Dictionary m_Table; + + public ExpireTimer(Mobile m, ResistanceMod mod, Dictionary table, TimeSpan delay) + : base(delay) + { + m_Mobile = m; + m_Mod = mod; + m_Table = table; + Priority = TimerPriority.TwoFiftyMS; + } + + public void DoExpire() + { + m_Mobile.RemoveResistanceMod(m_Mod); + Stop(); + m_Table.Remove(m_Mobile); + } + + protected override void OnTick() + { + if (m_Mod.Type == ResistanceType.Physical) + m_Mobile.SendLocalizedMessage(1070852); // Your resistance to physical attacks has returned. + else + m_Mobile.SendLocalizedMessage(1070829); // Your resistance to energy attacks has returned. + + DoExpire(); + } + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - - private class ExpireTimer : Timer - { - private readonly Mobile m_Mobile; - private readonly ResistanceMod m_Mod; - private readonly Dictionary m_Table; - - public ExpireTimer(Mobile m, ResistanceMod mod, Dictionary table, TimeSpan delay) - : base(delay) - { - m_Mobile = m; - m_Mod = mod; - m_Table = table; - Priority = TimerPriority.TwoFiftyMS; - } - - public void DoExpire() - { - m_Mobile.RemoveResistanceMod(m_Mod); - Stop(); - m_Table.Remove(m_Mobile); - } - - protected override void OnTick() - { - if (m_Mod.Type == ResistanceType.Physical) - m_Mobile.SendLocalizedMessage(1070852); // Your resistance to physical attacks has returned. - else - m_Mobile.SendLocalizedMessage(1070829); // Your resistance to energy attacks has returned. - - DoExpire(); - } - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/SE/LadyOfTheSnow.cs b/Projects/UOContent/Mobiles/Monsters/SE/LadyOfTheSnow.cs index fcf20c56f..ed2a302ea 100644 --- a/Projects/UOContent/Mobiles/Monsters/SE/LadyOfTheSnow.cs +++ b/Projects/UOContent/Mobiles/Monsters/SE/LadyOfTheSnow.cs @@ -5,155 +5,155 @@ using Server.Items; namespace Server.Mobiles { - public class LadyOfTheSnow : BaseCreature - { - private static readonly Dictionary m_Table = new Dictionary(); - - [Constructible] - public LadyOfTheSnow() - : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class LadyOfTheSnow : BaseCreature { - Body = 252; - BaseSoundID = 0x482; + private static readonly Dictionary m_Table = new Dictionary(); - SetStr(276, 305); - SetDex(106, 125); - SetInt(471, 495); - - SetHits(596, 625); - - SetDamage(13, 20); - - SetDamageType(ResistanceType.Physical, 20); - SetDamageType(ResistanceType.Cold, 80); - - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 40, 55); - SetResistance(ResistanceType.Cold, 70, 90); - SetResistance(ResistanceType.Poison, 60, 70); - SetResistance(ResistanceType.Energy, 65, 85); - - SetSkill(SkillName.Magery, 95.1, 110.0); - SetSkill(SkillName.MagicResist, 90.1, 105.0); - SetSkill(SkillName.Tactics, 80.1, 100.0); - SetSkill(SkillName.Wrestling, 80.1, 100.0); - SetSkill(SkillName.Necromancy, 90, 110.0); - SetSkill(SkillName.SpiritSpeak, 90.0, 110.0); - - Fame = 15200; - Karma = -15200; - - PackReg(3); - PackItem(new Necklace()); - - if (Utility.RandomDouble() < 0.25) - PackItem(Seed.RandomBonsaiSeed()); - } - - public LadyOfTheSnow(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a lady of the snow corpse"; - public override string DefaultName => "a lady of the snow"; - - public override bool BleedImmune => true; - public override bool CanRummageCorpses => true; - public override int TreasureMapLevel => 4; - - public override int GetDeathSound() => 0x370; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.Rich); - } - - // TODO: Snowball - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (Utility.RandomDouble() >= 0.1) - return; - - /* Cold Wind - * Graphics: Message - Type: "3" From: "0x57D4F5B" To: "0x0" ItemId: "0x37B9" ItemIdName: "glow" FromLocation: "(928 164, 34)" ToLocation: "(928 164, 34)" Speed: "10" Duration: "5" FixedDirection: "True" Explode: "False" - * Start cliloc: 1070832 - * Damage: 1hp per second for 5 seconds - * End cliloc: 1070830 - * Reset cliloc: 1070831 - */ - - if (m_Table.TryGetValue(defender, out ExpireTimer timer)) - { - timer.DoExpire(); - defender.SendLocalizedMessage(1070831); // The freezing wind continues to blow! - } - else - { - defender.SendLocalizedMessage(1070832); // An icy wind surrounds you, freezing your lungs as you breathe! - } - - timer = new ExpireTimer(defender, this); - timer.Start(); - m_Table[defender] = timer; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private class ExpireTimer : Timer - { - private int m_Count; - private readonly Mobile m_From; - private readonly Mobile m_Mobile; - - public ExpireTimer(Mobile m, Mobile from) - : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)) - { - m_Mobile = m; - m_From = from; - Priority = TimerPriority.TwoFiftyMS; - } - - public void DoExpire() - { - Stop(); - m_Table.Remove(m_Mobile); - } - - public void DrainLife() - { - if (m_Mobile.Alive) - m_Mobile.Damage(2, m_From); - else - DoExpire(); - } - - protected override void OnTick() - { - DrainLife(); - - if (++m_Count >= 5) + [Constructible] + public LadyOfTheSnow() + : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) { - DoExpire(); - m_Mobile.SendLocalizedMessage(1070830); // The icy wind dissipates. + Body = 252; + BaseSoundID = 0x482; + + SetStr(276, 305); + SetDex(106, 125); + SetInt(471, 495); + + SetHits(596, 625); + + SetDamage(13, 20); + + SetDamageType(ResistanceType.Physical, 20); + SetDamageType(ResistanceType.Cold, 80); + + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 40, 55); + SetResistance(ResistanceType.Cold, 70, 90); + SetResistance(ResistanceType.Poison, 60, 70); + SetResistance(ResistanceType.Energy, 65, 85); + + SetSkill(SkillName.Magery, 95.1, 110.0); + SetSkill(SkillName.MagicResist, 90.1, 105.0); + SetSkill(SkillName.Tactics, 80.1, 100.0); + SetSkill(SkillName.Wrestling, 80.1, 100.0); + SetSkill(SkillName.Necromancy, 90, 110.0); + SetSkill(SkillName.SpiritSpeak, 90.0, 110.0); + + Fame = 15200; + Karma = -15200; + + PackReg(3); + PackItem(new Necklace()); + + if (Utility.RandomDouble() < 0.25) + PackItem(Seed.RandomBonsaiSeed()); + } + + public LadyOfTheSnow(Serial serial) + : base(serial) + { + } + + public override string CorpseName => "a lady of the snow corpse"; + public override string DefaultName => "a lady of the snow"; + + public override bool BleedImmune => true; + public override bool CanRummageCorpses => true; + public override int TreasureMapLevel => 4; + + public override int GetDeathSound() => 0x370; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.Rich); + } + + // TODO: Snowball + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomDouble() >= 0.1) + return; + + /* Cold Wind + * Graphics: Message - Type: "3" From: "0x57D4F5B" To: "0x0" ItemId: "0x37B9" ItemIdName: "glow" FromLocation: "(928 164, 34)" ToLocation: "(928 164, 34)" Speed: "10" Duration: "5" FixedDirection: "True" Explode: "False" + * Start cliloc: 1070832 + * Damage: 1hp per second for 5 seconds + * End cliloc: 1070830 + * Reset cliloc: 1070831 + */ + + if (m_Table.TryGetValue(defender, out var timer)) + { + timer.DoExpire(); + defender.SendLocalizedMessage(1070831); // The freezing wind continues to blow! + } + else + { + defender.SendLocalizedMessage(1070832); // An icy wind surrounds you, freezing your lungs as you breathe! + } + + timer = new ExpireTimer(defender, this); + timer.Start(); + m_Table[defender] = timer; + } + + 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(); + } + + private class ExpireTimer : Timer + { + private readonly Mobile m_From; + private readonly Mobile m_Mobile; + private int m_Count; + + public ExpireTimer(Mobile m, Mobile from) + : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)) + { + m_Mobile = m; + m_From = from; + Priority = TimerPriority.TwoFiftyMS; + } + + public void DoExpire() + { + Stop(); + m_Table.Remove(m_Mobile); + } + + public void DrainLife() + { + if (m_Mobile.Alive) + m_Mobile.Damage(2, m_From); + else + DoExpire(); + } + + protected override void OnTick() + { + DrainLife(); + + if (++m_Count >= 5) + { + DoExpire(); + m_Mobile.SendLocalizedMessage(1070830); // The icy wind dissipates. + } + } } - } } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/SE/Oni.cs b/Projects/UOContent/Mobiles/Monsters/SE/Oni.cs index 5e5127bc5..08d108e82 100644 --- a/Projects/UOContent/Mobiles/Monsters/SE/Oni.cs +++ b/Projects/UOContent/Mobiles/Monsters/SE/Oni.cs @@ -2,93 +2,93 @@ using Server.Engines.Plants; namespace Server.Mobiles { - public class Oni : BaseCreature - { - [Constructible] - public Oni() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Oni : BaseCreature { - Body = 241; + [Constructible] + public Oni() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 241; - SetStr(801, 910); - SetDex(151, 300); - SetInt(171, 195); + SetStr(801, 910); + SetDex(151, 300); + SetInt(171, 195); - SetHits(401, 530); + SetHits(401, 530); - SetDamage(14, 20); + SetDamage(14, 20); - SetDamageType(ResistanceType.Physical, 70); - SetDamageType(ResistanceType.Fire, 10); - SetDamageType(ResistanceType.Energy, 20); + SetDamageType(ResistanceType.Physical, 70); + SetDamageType(ResistanceType.Fire, 10); + SetDamageType(ResistanceType.Energy, 20); - SetResistance(ResistanceType.Physical, 65, 80); - SetResistance(ResistanceType.Fire, 50, 70); - SetResistance(ResistanceType.Cold, 35, 50); - SetResistance(ResistanceType.Poison, 45, 70); - SetResistance(ResistanceType.Energy, 45, 65); + SetResistance(ResistanceType.Physical, 65, 80); + SetResistance(ResistanceType.Fire, 50, 70); + SetResistance(ResistanceType.Cold, 35, 50); + SetResistance(ResistanceType.Poison, 45, 70); + SetResistance(ResistanceType.Energy, 45, 65); - SetSkill(SkillName.EvalInt, 100.1, 125.0); - SetSkill(SkillName.Magery, 96.1, 106.0); - SetSkill(SkillName.Anatomy, 85.1, 95.0); - SetSkill(SkillName.MagicResist, 85.1, 100.0); - SetSkill(SkillName.Tactics, 86.1, 101.0); - SetSkill(SkillName.Wrestling, 90.1, 100.0); + SetSkill(SkillName.EvalInt, 100.1, 125.0); + SetSkill(SkillName.Magery, 96.1, 106.0); + SetSkill(SkillName.Anatomy, 85.1, 95.0); + SetSkill(SkillName.MagicResist, 85.1, 100.0); + SetSkill(SkillName.Tactics, 86.1, 101.0); + SetSkill(SkillName.Wrestling, 90.1, 100.0); - Fame = 12000; - Karma = -12000; + Fame = 12000; + Karma = -12000; - if (Utility.RandomDouble() < .33) - PackItem(Seed.RandomBonsaiSeed()); + if (Utility.RandomDouble() < .33) + PackItem(Seed.RandomBonsaiSeed()); - // TODO: Brain (0x1CF0) or Skull (0x1AE3) or Body Part (0x1CE3) + // TODO: Brain (0x1CF0) or Skull (0x1AE3) or Body Part (0x1CE3) + } + + /* TODO: Angry Fire + * cliloc 1070823 + * Action: 4 4 1 true false 1 + * Damage: 50-85, 60 phys, 20 fire, 20 nrgy according to the guide + * With 45/49/70 res I got 48 + * 50: 30/10/10 -> 16 + 5 + 3 = 24 + * 85: 51/17/17 -> 28 + 8 + 5 = 41 + */ + + public Oni(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an oni corpse"; + public override string DefaultName => "an oni"; + + public override bool CanRummageCorpses => true; + public override int TreasureMapLevel => 4; + + public override int GetAngerSound() => 0x4E3; + + public override int GetIdleSound() => 0x4E2; + + public override int GetAttackSound() => 0x4E1; + + public override int GetHurtSound() => 0x4E4; + + public override int GetDeathSound() => 0x4E0; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 3); + } + + 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(); + } } - - /* TODO: Angry Fire - * cliloc 1070823 - * Action: 4 4 1 true false 1 - * Damage: 50-85, 60 phys, 20 fire, 20 nrgy according to the guide - * With 45/49/70 res I got 48 - * 50: 30/10/10 -> 16 + 5 + 3 = 24 - * 85: 51/17/17 -> 28 + 8 + 5 = 41 - */ - - public Oni(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an oni corpse"; - public override string DefaultName => "an oni"; - - public override bool CanRummageCorpses => true; - public override int TreasureMapLevel => 4; - - public override int GetAngerSound() => 0x4E3; - - public override int GetIdleSound() => 0x4E2; - - public override int GetAttackSound() => 0x4E1; - - public override int GetHurtSound() => 0x4E4; - - public override int GetDeathSound() => 0x4E0; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 3); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/SE/RaiJu.cs b/Projects/UOContent/Mobiles/Monsters/SE/RaiJu.cs index 58d48660d..4154ba551 100644 --- a/Projects/UOContent/Mobiles/Monsters/SE/RaiJu.cs +++ b/Projects/UOContent/Mobiles/Monsters/SE/RaiJu.cs @@ -3,123 +3,123 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class RaiJu : BaseCreature - { - private static readonly HashSet m_Table = new HashSet(); - - [Constructible] - public RaiJu() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class RaiJu : BaseCreature { - Body = 199; - BaseSoundID = 0x346; + private static readonly HashSet m_Table = new HashSet(); - SetStr(151, 225); - SetDex(81, 135); - SetInt(176, 180); + [Constructible] + public RaiJu() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 199; + BaseSoundID = 0x346; - SetHits(201, 280); + SetStr(151, 225); + SetDex(81, 135); + SetInt(176, 180); - SetDamage(12, 15); + SetHits(201, 280); - SetDamageType(ResistanceType.Physical, 10); - SetDamageType(ResistanceType.Fire, 10); - SetDamageType(ResistanceType.Cold, 10); - SetDamageType(ResistanceType.Poison, 10); - SetDamageType(ResistanceType.Energy, 60); + SetDamage(12, 15); - SetResistance(ResistanceType.Physical, 45, 65); - SetResistance(ResistanceType.Fire, 70, 85); - SetResistance(ResistanceType.Cold, 30, 60); - SetResistance(ResistanceType.Poison, 50, 70); - SetResistance(ResistanceType.Energy, 60, 80); + SetDamageType(ResistanceType.Physical, 10); + SetDamageType(ResistanceType.Fire, 10); + SetDamageType(ResistanceType.Cold, 10); + SetDamageType(ResistanceType.Poison, 10); + SetDamageType(ResistanceType.Energy, 60); - SetSkill(SkillName.Wrestling, 85.1, 95.0); - SetSkill(SkillName.Tactics, 55.1, 65.0); - SetSkill(SkillName.MagicResist, 110.1, 125.0); - SetSkill(SkillName.Anatomy, 25.1, 35.0); + SetResistance(ResistanceType.Physical, 45, 65); + SetResistance(ResistanceType.Fire, 70, 85); + SetResistance(ResistanceType.Cold, 30, 60); + SetResistance(ResistanceType.Poison, 50, 70); + SetResistance(ResistanceType.Energy, 60, 80); - Fame = 8000; - Karma = -8000; + SetSkill(SkillName.Wrestling, 85.1, 95.0); + SetSkill(SkillName.Tactics, 55.1, 65.0); + SetSkill(SkillName.MagicResist, 110.1, 125.0); + SetSkill(SkillName.Anatomy, 25.1, 35.0); + + Fame = 8000; + Karma = -8000; + } + + public RaiJu(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a rai-ju corpse"; + public override string DefaultName => "a Rai-Ju"; + public override bool BleedImmune => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich, 2); + AddLoot(LootPack.Gems, 2); + } + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomDouble() >= 0.1 || m_Table.Contains(defender)) + return; + + /* Lightning Fist + * Cliloc: 1070839 + * Effect: Type: "3" From: "0x57D4F5B" To: "0x0" ItemId: "0x37B9" ItemIdName: "glow" FromLocation: "(884 715, 10)" ToLocation: "(884 715, 10)" Speed: "10" Duration: "5" FixedDirection: "True" Explode: "False" + * Damage: 35-65, 100% energy, resistable + * Freezes for 4 seconds + * Effect cannot stack + */ + + defender.FixedEffect(0x37B9, 10, 5); + defender.SendLocalizedMessage(1070839); // The creature attacks with stunning force! + + // This should be done in place of the normal attack damage. + // AOS.Damage( defender, this, Utility.RandomMinMax( 35, 65 ), 0, 0, 0, 0, 100 ); + + defender.Frozen = true; + + var timer = new ExpireTimer(defender, TimeSpan.FromSeconds(4.0)); + timer.Start(); + m_Table.Add(defender); + } + + 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(); + } + + private class ExpireTimer : Timer + { + private readonly Mobile m_Mobile; + + public ExpireTimer(Mobile m, TimeSpan delay) : base(delay) + { + m_Mobile = m; + Priority = TimerPriority.TwoFiftyMS; + } + + public void DoExpire() + { + m_Mobile.Frozen = false; + Stop(); + m_Table.Remove(m_Mobile); + } + + protected override void OnTick() + { + m_Mobile.SendLocalizedMessage(1005603); // You can move again! + DoExpire(); + } + } } - - public RaiJu(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a rai-ju corpse"; - public override string DefaultName => "a Rai-Ju"; - public override bool BleedImmune => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich, 2); - AddLoot(LootPack.Gems, 2); - } - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (Utility.RandomDouble() >= 0.1 || m_Table.Contains(defender)) - return; - - /* Lightning Fist - * Cliloc: 1070839 - * Effect: Type: "3" From: "0x57D4F5B" To: "0x0" ItemId: "0x37B9" ItemIdName: "glow" FromLocation: "(884 715, 10)" ToLocation: "(884 715, 10)" Speed: "10" Duration: "5" FixedDirection: "True" Explode: "False" - * Damage: 35-65, 100% energy, resistable - * Freezes for 4 seconds - * Effect cannot stack - */ - - defender.FixedEffect(0x37B9, 10, 5); - defender.SendLocalizedMessage(1070839); // The creature attacks with stunning force! - - // This should be done in place of the normal attack damage. - // AOS.Damage( defender, this, Utility.RandomMinMax( 35, 65 ), 0, 0, 0, 0, 100 ); - - defender.Frozen = true; - - ExpireTimer timer = new ExpireTimer(defender, TimeSpan.FromSeconds(4.0)); - timer.Start(); - m_Table.Add(defender); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private class ExpireTimer : Timer - { - private readonly Mobile m_Mobile; - - public ExpireTimer(Mobile m, TimeSpan delay) : base(delay) - { - m_Mobile = m; - Priority = TimerPriority.TwoFiftyMS; - } - - public void DoExpire() - { - m_Mobile.Frozen = false; - Stop(); - m_Table.Remove(m_Mobile); - } - - protected override void OnTick() - { - m_Mobile.SendLocalizedMessage(1005603); // You can move again! - DoExpire(); - } - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/SE/RevenantLion.cs b/Projects/UOContent/Mobiles/Monsters/SE/RevenantLion.cs index 9a22ea0c9..50e336676 100644 --- a/Projects/UOContent/Mobiles/Monsters/SE/RevenantLion.cs +++ b/Projects/UOContent/Mobiles/Monsters/SE/RevenantLion.cs @@ -2,98 +2,98 @@ using Server.Items; namespace Server.Mobiles { - public class RevenantLion : BaseCreature - { - [Constructible] - public RevenantLion() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class RevenantLion : BaseCreature { - Body = 251; - - SetStr(276, 325); - SetDex(156, 175); - SetInt(76, 105); - - SetHits(251, 280); - - SetDamage(18, 24); - - SetDamageType(ResistanceType.Physical, 30); - SetDamageType(ResistanceType.Cold, 30); - SetDamageType(ResistanceType.Poison, 10); - SetDamageType(ResistanceType.Energy, 30); - - SetResistance(ResistanceType.Physical, 40, 60); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 55, 65); - SetResistance(ResistanceType.Energy, 40, 50); - - SetSkill(SkillName.EvalInt, 80.1, 90.0); - SetSkill(SkillName.Magery, 80.1, 90.0); - SetSkill(SkillName.Poisoning, 120.1, 130.0); - SetSkill(SkillName.MagicResist, 70.1, 90.0); - SetSkill(SkillName.Tactics, 60.1, 80.0); - SetSkill(SkillName.Wrestling, 80.1, 88.0); - - Fame = 4000; - Karma = -4000; - PackNecroReg(6, 8); - - PackItem( - Utility.Random(10) switch + [Constructible] + public RevenantLion() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) { - 0 => new LeftArm(), - 1 => new RightArm(), - 2 => new Torso(), - 3 => new Bone(), - 4 => new RibCage(), - 5 => new RibCage(), - _ => new BonePile() // 6-9 + Body = 251; + + SetStr(276, 325); + SetDex(156, 175); + SetInt(76, 105); + + SetHits(251, 280); + + SetDamage(18, 24); + + SetDamageType(ResistanceType.Physical, 30); + SetDamageType(ResistanceType.Cold, 30); + SetDamageType(ResistanceType.Poison, 10); + SetDamageType(ResistanceType.Energy, 30); + + SetResistance(ResistanceType.Physical, 40, 60); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 55, 65); + SetResistance(ResistanceType.Energy, 40, 50); + + SetSkill(SkillName.EvalInt, 80.1, 90.0); + SetSkill(SkillName.Magery, 80.1, 90.0); + SetSkill(SkillName.Poisoning, 120.1, 130.0); + SetSkill(SkillName.MagicResist, 70.1, 90.0); + SetSkill(SkillName.Tactics, 60.1, 80.0); + SetSkill(SkillName.Wrestling, 80.1, 88.0); + + Fame = 4000; + Karma = -4000; + PackNecroReg(6, 8); + + PackItem( + Utility.Random(10) switch + { + 0 => new LeftArm(), + 1 => new RightArm(), + 2 => new Torso(), + 3 => new Bone(), + 4 => new RibCage(), + 5 => new RibCage(), + _ => new BonePile() // 6-9 + } + ); + } + + public RevenantLion(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a revenant lion corpse"; + public override string DefaultName => "a Revenant Lion"; + + public override bool BleedImmune => true; + public override Poison PoisonImmune => Poison.Greater; + public override Poison HitPoison => Poison.Greater; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.BleedAttack; + + public override int GetAngerSound() => 0x518; + + public override int GetIdleSound() => 0x517; + + public override int GetAttackSound() => 0x516; + + public override int GetHurtSound() => 0x519; + + public override int GetDeathSound() => 0x515; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich, 2); + AddLoot(LootPack.MedScrolls, 2); + + // TODO: Bone Pile + } + + 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(); } - ); } - - public RevenantLion(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a revenant lion corpse"; - public override string DefaultName => "a Revenant Lion"; - - public override bool BleedImmune => true; - public override Poison PoisonImmune => Poison.Greater; - public override Poison HitPoison => Poison.Greater; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.BleedAttack; - - public override int GetAngerSound() => 0x518; - - public override int GetIdleSound() => 0x517; - - public override int GetAttackSound() => 0x516; - - public override int GetHurtSound() => 0x519; - - public override int GetDeathSound() => 0x515; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich, 2); - AddLoot(LootPack.MedScrolls, 2); - - // TODO: Bone Pile - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/SE/Ronin.cs b/Projects/UOContent/Mobiles/Monsters/SE/Ronin.cs index 311eccaad..6982119a1 100644 --- a/Projects/UOContent/Mobiles/Monsters/SE/Ronin.cs +++ b/Projects/UOContent/Mobiles/Monsters/SE/Ronin.cs @@ -2,129 +2,129 @@ using Server.Items; namespace Server.Mobiles { - public class Ronin : BaseCreature - { - [Constructible] - public Ronin() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class Ronin : BaseCreature { - SpeechHue = Utility.RandomDyedHue(); - Hue = Race.Human.RandomSkinHue(); - Female = Utility.RandomBool(); - Body = Female ? 0x191 : 0x190; + [Constructible] + public Ronin() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + SpeechHue = Utility.RandomDyedHue(); + Hue = Race.Human.RandomSkinHue(); + Female = Utility.RandomBool(); + Body = Female ? 0x191 : 0x190; - SetStr(326, 375); - SetDex(31, 45); - SetInt(101, 110); + SetStr(326, 375); + SetDex(31, 45); + SetInt(101, 110); - SetHits(301, 400); - SetMana(101, 110); + SetHits(301, 400); + SetMana(101, 110); - SetDamage(17, 25); + SetDamage(17, 25); - SetDamageType(ResistanceType.Physical, 90); - SetDamageType(ResistanceType.Poison, 10); + SetDamageType(ResistanceType.Physical, 90); + SetDamageType(ResistanceType.Poison, 10); - SetResistance(ResistanceType.Physical, 55, 75); - SetResistance(ResistanceType.Fire, 40, 60); - SetResistance(ResistanceType.Cold, 35, 55); - SetResistance(ResistanceType.Poison, 50, 70); - SetResistance(ResistanceType.Energy, 55, 75); + SetResistance(ResistanceType.Physical, 55, 75); + SetResistance(ResistanceType.Fire, 40, 60); + SetResistance(ResistanceType.Cold, 35, 55); + SetResistance(ResistanceType.Poison, 50, 70); + SetResistance(ResistanceType.Energy, 55, 75); - SetSkill(SkillName.MagicResist, 42.6, 57.5); - SetSkill(SkillName.Tactics, 115.1, 130.0); - SetSkill(SkillName.Wrestling, 92.6, 107.5); - SetSkill(SkillName.Anatomy, 110.1, 125.0); + SetSkill(SkillName.MagicResist, 42.6, 57.5); + SetSkill(SkillName.Tactics, 115.1, 130.0); + SetSkill(SkillName.Wrestling, 92.6, 107.5); + SetSkill(SkillName.Anatomy, 110.1, 125.0); - SetSkill(SkillName.Fencing, 92.6, 107.5); - SetSkill(SkillName.Macing, 92.6, 107.5); - SetSkill(SkillName.Swords, 92.6, 107.5); + SetSkill(SkillName.Fencing, 92.6, 107.5); + SetSkill(SkillName.Macing, 92.6, 107.5); + SetSkill(SkillName.Swords, 92.6, 107.5); - Fame = 8500; - Karma = -8500; + Fame = 8500; + Karma = -8500; - AddItem(new SamuraiTabi()); - AddItem(new LeatherHiroSode()); - AddItem(new LeatherDo()); + AddItem(new SamuraiTabi()); + AddItem(new LeatherHiroSode()); + AddItem(new LeatherDo()); - switch (Utility.Random(4)) - { - case 0: - AddItem(new LightPlateJingasa()); - break; - case 1: - AddItem(new ChainHatsuburi()); - break; - case 2: - AddItem(new DecorativePlateKabuto()); - break; - case 3: - AddItem(new LeatherJingasa()); - break; - } + switch (Utility.Random(4)) + { + case 0: + AddItem(new LightPlateJingasa()); + break; + case 1: + AddItem(new ChainHatsuburi()); + break; + case 2: + AddItem(new DecorativePlateKabuto()); + break; + case 3: + AddItem(new LeatherJingasa()); + break; + } - switch (Utility.Random(3)) - { - case 0: - AddItem(new StuddedHaidate()); - break; - case 1: - AddItem(new LeatherSuneate()); - break; - case 2: - AddItem(new PlateSuneate()); - break; - } + switch (Utility.Random(3)) + { + case 0: + AddItem(new StuddedHaidate()); + break; + case 1: + AddItem(new LeatherSuneate()); + break; + case 2: + AddItem(new PlateSuneate()); + break; + } - if (Utility.RandomDouble() > .2) - AddItem(new NoDachi()); - else - AddItem(new Halberd()); + if (Utility.RandomDouble() > .2) + AddItem(new NoDachi()); + else + AddItem(new Halberd()); - PackItem(new Wakizashi()); - PackItem(new Longsword()); + PackItem(new Wakizashi()); + PackItem(new Longsword()); - Utility.AssignRandomHair(this); + Utility.AssignRandomHair(this); + } + + public Ronin(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a ronin corpse"; + public override bool ClickTitle => false; + public override string DefaultName => "a ronin"; + + public override bool AlwaysMurderer => true; + public override bool BardImmune => true; + public override bool CanRummageCorpses => true; + + public override void OnDeath(Container c) + { + base.OnDeath(c); + c.DropItem(new BookOfBushido()); + } + + // TODO: Bushido abilities + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.Rich); + AddLoot(LootPack.Gems, 2); + } + + 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 Ronin(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a ronin corpse"; - public override bool ClickTitle => false; - public override string DefaultName => "a ronin"; - - public override bool AlwaysMurderer => true; - public override bool BardImmune => true; - public override bool CanRummageCorpses => true; - - public override void OnDeath(Container c) - { - base.OnDeath(c); - c.DropItem(new BookOfBushido()); - } - - // TODO: Bushido abilities - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.Rich); - AddLoot(LootPack.Gems, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/SE/RuneBeetle.cs b/Projects/UOContent/Mobiles/Monsters/SE/RuneBeetle.cs index 8120d8937..c2a037e44 100644 --- a/Projects/UOContent/Mobiles/Monsters/SE/RuneBeetle.cs +++ b/Projects/UOContent/Mobiles/Monsters/SE/RuneBeetle.cs @@ -5,215 +5,235 @@ using Server.Items; namespace Server.Mobiles { - public class RuneBeetle : BaseCreature - { - private static readonly Dictionary m_Table = new Dictionary(); - - [Constructible] - public RuneBeetle() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class RuneBeetle : BaseCreature { - Body = 244; + private static readonly Dictionary m_Table = new Dictionary(); - SetStr(401, 460); - SetDex(121, 170); - SetInt(376, 450); - - SetHits(301, 360); - - SetDamage(15, 22); - - SetDamageType(ResistanceType.Physical, 20); - SetDamageType(ResistanceType.Poison, 10); - SetDamageType(ResistanceType.Energy, 70); - - SetResistance(ResistanceType.Physical, 40, 65); - SetResistance(ResistanceType.Fire, 35, 50); - SetResistance(ResistanceType.Cold, 35, 50); - SetResistance(ResistanceType.Poison, 75, 95); - SetResistance(ResistanceType.Energy, 40, 60); - - SetSkill(SkillName.EvalInt, 100.1, 125.0); - SetSkill(SkillName.Magery, 100.1, 110.0); - SetSkill(SkillName.Poisoning, 120.1, 140.0); - SetSkill(SkillName.MagicResist, 95.1, 110.0); - SetSkill(SkillName.Tactics, 78.1, 93.0); - SetSkill(SkillName.Wrestling, 70.1, 77.5); - - Fame = 15000; - Karma = -15000; - - if (Utility.RandomDouble() < .25) - PackItem(Seed.RandomBonsaiSeed()); - - PackItem( - Utility.Random(10) switch + [Constructible] + public RuneBeetle() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) { - 0 => new LeftArm(), - 1 => new RightArm(), - 2 => new Torso(), - 3 => new Bone(), - 4 => new RibCage(), - 5 => new RibCage(), - _ => new BonePile() // 6-9 + Body = 244; + + SetStr(401, 460); + SetDex(121, 170); + SetInt(376, 450); + + SetHits(301, 360); + + SetDamage(15, 22); + + SetDamageType(ResistanceType.Physical, 20); + SetDamageType(ResistanceType.Poison, 10); + SetDamageType(ResistanceType.Energy, 70); + + SetResistance(ResistanceType.Physical, 40, 65); + SetResistance(ResistanceType.Fire, 35, 50); + SetResistance(ResistanceType.Cold, 35, 50); + SetResistance(ResistanceType.Poison, 75, 95); + SetResistance(ResistanceType.Energy, 40, 60); + + SetSkill(SkillName.EvalInt, 100.1, 125.0); + SetSkill(SkillName.Magery, 100.1, 110.0); + SetSkill(SkillName.Poisoning, 120.1, 140.0); + SetSkill(SkillName.MagicResist, 95.1, 110.0); + SetSkill(SkillName.Tactics, 78.1, 93.0); + SetSkill(SkillName.Wrestling, 70.1, 77.5); + + Fame = 15000; + Karma = -15000; + + if (Utility.RandomDouble() < .25) + PackItem(Seed.RandomBonsaiSeed()); + + PackItem( + Utility.Random(10) switch + { + 0 => new LeftArm(), + 1 => new RightArm(), + 2 => new Torso(), + 3 => new Bone(), + 4 => new RibCage(), + 5 => new RibCage(), + _ => new BonePile() // 6-9 + } + ); + + Tamable = true; + ControlSlots = 3; + MinTameSkill = 93.9; } - ); - Tamable = true; - ControlSlots = 3; - MinTameSkill = 93.9; - } - - public RuneBeetle(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a rune beetle corpse"; - public override string DefaultName => "a rune beetle"; - - public override Poison PoisonImmune => Poison.Greater; - public override Poison HitPoison => Poison.Greater; - public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; - public override bool CanAngerOnTame => true; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.BleedAttack; - - public override int GetAngerSound() => 0x4E8; - - public override int GetIdleSound() => 0x4E7; - - public override int GetAttackSound() => 0x4E6; - - public override int GetHurtSound() => 0x4E9; - - public override int GetDeathSound() => 0x4E5; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 2); - AddLoot(LootPack.MedScrolls, 1); - } - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (Utility.RandomDouble() >= 0.05) - return; - - /* Rune Corruption - * Start cliloc: 1070846 "The creature magically corrupts your armor!" - * Effect: All resistances -70 (lowest 0) for 5 seconds - * End ASCII: "The corruption of your armor has worn off" - */ - - if (m_Table.TryGetValue(defender, out ExpireTimer timer)) - { - timer.DoExpire(); - defender.SendLocalizedMessage(1070845); // The creature continues to corrupt your armor! - } - else - { - defender.SendLocalizedMessage(1070846); // The creature magically corrupts your armor! - } - - List mods = new List(); - - if (Core.ML) - { - if (defender.PhysicalResistance > 0) - mods.Add(new ResistanceMod(ResistanceType.Physical, -(defender.PhysicalResistance / 2))); - - if (defender.FireResistance > 0) - mods.Add(new ResistanceMod(ResistanceType.Fire, -(defender.FireResistance / 2))); - - if (defender.ColdResistance > 0) - mods.Add(new ResistanceMod(ResistanceType.Cold, -(defender.ColdResistance / 2))); - - if (defender.PoisonResistance > 0) - mods.Add(new ResistanceMod(ResistanceType.Poison, -(defender.PoisonResistance / 2))); - - if (defender.EnergyResistance > 0) - mods.Add(new ResistanceMod(ResistanceType.Energy, -(defender.EnergyResistance / 2))); - } - else - { - if (defender.PhysicalResistance > 0) - mods.Add(new ResistanceMod(ResistanceType.Physical, - defender.PhysicalResistance > 70 ? -70 : -defender.PhysicalResistance)); - - if (defender.FireResistance > 0) - mods.Add(new ResistanceMod(ResistanceType.Fire, - defender.FireResistance > 70 ? -70 : -defender.FireResistance)); - - if (defender.ColdResistance > 0) - mods.Add(new ResistanceMod(ResistanceType.Cold, - defender.ColdResistance > 70 ? -70 : -defender.ColdResistance)); - - if (defender.PoisonResistance > 0) - mods.Add(new ResistanceMod(ResistanceType.Poison, - defender.PoisonResistance > 70 ? -70 : -defender.PoisonResistance)); - - if (defender.EnergyResistance > 0) - mods.Add(new ResistanceMod(ResistanceType.Energy, - defender.EnergyResistance > 70 ? -70 : -defender.EnergyResistance)); - } - - for (int i = 0; i < mods.Count; ++i) - defender.AddResistanceMod(mods[i]); - - defender.FixedEffect(0x37B9, 10, 5); - - timer = new ExpireTimer(defender, mods, TimeSpan.FromSeconds(5.0)); - timer.Start(); - m_Table[defender] = timer; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (version < 1) - for (int i = 0; i < Skills.Length; ++i) + public RuneBeetle(Serial serial) : base(serial) { - Skills[i].Cap = Math.Max(100.0, Skills[i].Cap * 0.9); + } - if (Skills[i].Base > Skills[i].Cap) Skills[i].Base = Skills[i].Cap; + public override string CorpseName => "a rune beetle corpse"; + public override string DefaultName => "a rune beetle"; + + public override Poison PoisonImmune => Poison.Greater; + public override Poison HitPoison => Poison.Greater; + public override FoodType FavoriteFood => FoodType.FruitsAndVegies | FoodType.GrainsAndHay; + public override bool CanAngerOnTame => true; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.BleedAttack; + + public override int GetAngerSound() => 0x4E8; + + public override int GetIdleSound() => 0x4E7; + + public override int GetAttackSound() => 0x4E6; + + public override int GetHurtSound() => 0x4E9; + + public override int GetDeathSound() => 0x4E5; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 2); + AddLoot(LootPack.MedScrolls, 1); + } + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomDouble() >= 0.05) + return; + + /* Rune Corruption + * Start cliloc: 1070846 "The creature magically corrupts your armor!" + * Effect: All resistances -70 (lowest 0) for 5 seconds + * End ASCII: "The corruption of your armor has worn off" + */ + + if (m_Table.TryGetValue(defender, out var timer)) + { + timer.DoExpire(); + defender.SendLocalizedMessage(1070845); // The creature continues to corrupt your armor! + } + else + { + defender.SendLocalizedMessage(1070846); // The creature magically corrupts your armor! + } + + var mods = new List(); + + if (Core.ML) + { + if (defender.PhysicalResistance > 0) + mods.Add(new ResistanceMod(ResistanceType.Physical, -(defender.PhysicalResistance / 2))); + + if (defender.FireResistance > 0) + mods.Add(new ResistanceMod(ResistanceType.Fire, -(defender.FireResistance / 2))); + + if (defender.ColdResistance > 0) + mods.Add(new ResistanceMod(ResistanceType.Cold, -(defender.ColdResistance / 2))); + + if (defender.PoisonResistance > 0) + mods.Add(new ResistanceMod(ResistanceType.Poison, -(defender.PoisonResistance / 2))); + + if (defender.EnergyResistance > 0) + mods.Add(new ResistanceMod(ResistanceType.Energy, -(defender.EnergyResistance / 2))); + } + else + { + if (defender.PhysicalResistance > 0) + mods.Add( + new ResistanceMod( + ResistanceType.Physical, + defender.PhysicalResistance > 70 ? -70 : -defender.PhysicalResistance + ) + ); + + if (defender.FireResistance > 0) + mods.Add( + new ResistanceMod( + ResistanceType.Fire, + defender.FireResistance > 70 ? -70 : -defender.FireResistance + ) + ); + + if (defender.ColdResistance > 0) + mods.Add( + new ResistanceMod( + ResistanceType.Cold, + defender.ColdResistance > 70 ? -70 : -defender.ColdResistance + ) + ); + + if (defender.PoisonResistance > 0) + mods.Add( + new ResistanceMod( + ResistanceType.Poison, + defender.PoisonResistance > 70 ? -70 : -defender.PoisonResistance + ) + ); + + if (defender.EnergyResistance > 0) + mods.Add( + new ResistanceMod( + ResistanceType.Energy, + defender.EnergyResistance > 70 ? -70 : -defender.EnergyResistance + ) + ); + } + + for (var i = 0; i < mods.Count; ++i) + defender.AddResistanceMod(mods[i]); + + defender.FixedEffect(0x37B9, 10, 5); + + timer = new ExpireTimer(defender, mods, TimeSpan.FromSeconds(5.0)); + timer.Start(); + m_Table[defender] = timer; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + if (version < 1) + for (var i = 0; i < Skills.Length; ++i) + { + Skills[i].Cap = Math.Max(100.0, Skills[i].Cap * 0.9); + + if (Skills[i].Base > Skills[i].Cap) Skills[i].Base = Skills[i].Cap; + } + } + + private class ExpireTimer : Timer + { + private readonly Mobile m_Mobile; + private readonly List m_Mods; + + public ExpireTimer(Mobile m, List mods, TimeSpan delay) : base(delay) + { + m_Mobile = m; + m_Mods = mods; + Priority = TimerPriority.TwoFiftyMS; + } + + public void DoExpire() + { + for (var i = 0; i < m_Mods.Count; ++i) + m_Mobile.RemoveResistanceMod(m_Mods[i]); + + Stop(); + m_Table.Remove(m_Mobile); + } + + protected override void OnTick() + { + m_Mobile.SendMessage("The corruption of your armor has worn off"); + DoExpire(); + } } } - - private class ExpireTimer : Timer - { - private readonly Mobile m_Mobile; - private readonly List m_Mods; - - public ExpireTimer(Mobile m, List mods, TimeSpan delay) : base(delay) - { - m_Mobile = m; - m_Mods = mods; - Priority = TimerPriority.TwoFiftyMS; - } - - public void DoExpire() - { - for (int i = 0; i < m_Mods.Count; ++i) - m_Mobile.RemoveResistanceMod(m_Mods[i]); - - Stop(); - m_Table.Remove(m_Mobile); - } - - protected override void OnTick() - { - m_Mobile.SendMessage("The corruption of your armor has worn off"); - DoExpire(); - } - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/SE/TsukiWolf.cs b/Projects/UOContent/Mobiles/Monsters/SE/TsukiWolf.cs index 0cd300c2e..93c395d36 100644 --- a/Projects/UOContent/Mobiles/Monsters/SE/TsukiWolf.cs +++ b/Projects/UOContent/Mobiles/Monsters/SE/TsukiWolf.cs @@ -5,170 +5,170 @@ using Server.Items; namespace Server.Mobiles { - public class TsukiWolf : BaseCreature - { - private static readonly Dictionary m_Table = new Dictionary(); - - [Constructible] - public TsukiWolf() - : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class TsukiWolf : BaseCreature { - Body = 250; - Hue = Utility.Random(3) == 0 ? Utility.RandomNeutralHue() : 0; + private static readonly Dictionary m_Table = new Dictionary(); - SetStr(401, 450); - SetDex(151, 200); - SetInt(66, 76); - - SetHits(376, 450); - SetMana(40); - - SetDamage(14, 18); - - SetDamageType(ResistanceType.Physical, 90); - SetDamageType(ResistanceType.Cold, 5); - SetDamageType(ResistanceType.Energy, 5); - - SetResistance(ResistanceType.Physical, 40, 60); - SetResistance(ResistanceType.Fire, 50, 70); - SetResistance(ResistanceType.Cold, 50, 70); - SetResistance(ResistanceType.Poison, 50, 70); - SetResistance(ResistanceType.Energy, 50, 70); - - SetSkill(SkillName.Anatomy, 65.1, 72.0); - SetSkill(SkillName.MagicResist, 65.1, 70.0); - SetSkill(SkillName.Tactics, 95.1, 110.0); - SetSkill(SkillName.Wrestling, 97.6, 107.5); - - Fame = 8500; - Karma = -8500; - - if (Core.ML && Utility.RandomDouble() < .33) - PackItem(Seed.RandomPeculiarSeed(1)); - - PackItem( - Utility.Random(10) switch + [Constructible] + public TsukiWolf() + : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) { - 0 => new LeftArm(), - 1 => new RightArm(), - 2 => new Torso(), - 3 => new Bone(), - 4 => new RibCage(), - 5 => new RibCage(), - _ => new BonePile() // 6-9 + Body = 250; + Hue = Utility.Random(3) == 0 ? Utility.RandomNeutralHue() : 0; + + SetStr(401, 450); + SetDex(151, 200); + SetInt(66, 76); + + SetHits(376, 450); + SetMana(40); + + SetDamage(14, 18); + + SetDamageType(ResistanceType.Physical, 90); + SetDamageType(ResistanceType.Cold, 5); + SetDamageType(ResistanceType.Energy, 5); + + SetResistance(ResistanceType.Physical, 40, 60); + SetResistance(ResistanceType.Fire, 50, 70); + SetResistance(ResistanceType.Cold, 50, 70); + SetResistance(ResistanceType.Poison, 50, 70); + SetResistance(ResistanceType.Energy, 50, 70); + + SetSkill(SkillName.Anatomy, 65.1, 72.0); + SetSkill(SkillName.MagicResist, 65.1, 70.0); + SetSkill(SkillName.Tactics, 95.1, 110.0); + SetSkill(SkillName.Wrestling, 97.6, 107.5); + + Fame = 8500; + Karma = -8500; + + if (Core.ML && Utility.RandomDouble() < .33) + PackItem(Seed.RandomPeculiarSeed(1)); + + PackItem( + Utility.Random(10) switch + { + 0 => new LeftArm(), + 1 => new RightArm(), + 2 => new Torso(), + 3 => new Bone(), + 4 => new RibCage(), + 5 => new RibCage(), + _ => new BonePile() // 6-9 + } + ); } - ); - } - public TsukiWolf(Serial serial) - : base(serial) - { - } - - public override string CorpseName => "a tsuki wolf corpse"; - public override string DefaultName => "a tsuki wolf"; - public override int Meat => 4; - public override int Hides => 25; - public override FoodType FavoriteFood => FoodType.Meat; - - public override void GenerateLoot() - { - AddLoot(LootPack.Average); - AddLoot(LootPack.Rich); - } - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (Utility.RandomDouble() >= 0.1) - return; - - /* Blood Bath - * Start cliloc 1070826 - * Sound: 0x52B - * 2-3 blood spots - * Damage: 2 hps per second for 5 seconds - * End cliloc: 1070824 - */ - - if (m_Table.TryGetValue(defender, out ExpireTimer timer)) - { - timer.DoExpire(); - defender.SendLocalizedMessage(1070825); // The creature continues to rage! - } - else - { - defender.SendLocalizedMessage(1070826); // The creature goes into a rage, inflicting heavy damage! - } - - timer = new ExpireTimer(defender, this); - timer.Start(); - m_Table[defender] = timer; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override int GetAngerSound() => 0x52D; - - public override int GetIdleSound() => 0x52C; - - public override int GetAttackSound() => 0x52B; - - public override int GetHurtSound() => 0x52E; - - public override int GetDeathSound() => 0x52A; - - private class ExpireTimer : Timer - { - private int m_Count; - private readonly Mobile m_From; - private readonly Mobile m_Mobile; - - public ExpireTimer(Mobile m, Mobile from) - : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)) - { - m_Mobile = m; - m_From = from; - Priority = TimerPriority.TwoFiftyMS; - } - - public void DoExpire() - { - Stop(); - m_Table.Remove(m_Mobile); - } - - public void DrainLife() - { - if (m_Mobile.Alive) - m_Mobile.Damage(2, m_From); - else - DoExpire(); - } - - protected override void OnTick() - { - DrainLife(); - - if (++m_Count >= 5) + public TsukiWolf(Serial serial) + : base(serial) { - DoExpire(); - m_Mobile.SendLocalizedMessage(1070824); // The creature's rage subsides. } - } + + public override string CorpseName => "a tsuki wolf corpse"; + public override string DefaultName => "a tsuki wolf"; + public override int Meat => 4; + public override int Hides => 25; + public override FoodType FavoriteFood => FoodType.Meat; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average); + AddLoot(LootPack.Rich); + } + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomDouble() >= 0.1) + return; + + /* Blood Bath + * Start cliloc 1070826 + * Sound: 0x52B + * 2-3 blood spots + * Damage: 2 hps per second for 5 seconds + * End cliloc: 1070824 + */ + + if (m_Table.TryGetValue(defender, out var timer)) + { + timer.DoExpire(); + defender.SendLocalizedMessage(1070825); // The creature continues to rage! + } + else + { + defender.SendLocalizedMessage(1070826); // The creature goes into a rage, inflicting heavy damage! + } + + timer = new ExpireTimer(defender, this); + timer.Start(); + m_Table[defender] = timer; + } + + 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(); + } + + public override int GetAngerSound() => 0x52D; + + public override int GetIdleSound() => 0x52C; + + public override int GetAttackSound() => 0x52B; + + public override int GetHurtSound() => 0x52E; + + public override int GetDeathSound() => 0x52A; + + private class ExpireTimer : Timer + { + private readonly Mobile m_From; + private readonly Mobile m_Mobile; + private int m_Count; + + public ExpireTimer(Mobile m, Mobile from) + : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)) + { + m_Mobile = m; + m_From = from; + Priority = TimerPriority.TwoFiftyMS; + } + + public void DoExpire() + { + Stop(); + m_Table.Remove(m_Mobile); + } + + public void DrainLife() + { + if (m_Mobile.Alive) + m_Mobile.Damage(2, m_From); + else + DoExpire(); + } + + protected override void OnTick() + { + DrainLife(); + + if (++m_Count >= 5) + { + DoExpire(); + m_Mobile.SendLocalizedMessage(1070824); // The creature's rage subsides. + } + } + } } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/SE/Yamandon.cs b/Projects/UOContent/Mobiles/Monsters/SE/Yamandon.cs index ee37dfe77..3c865fd04 100644 --- a/Projects/UOContent/Mobiles/Monsters/SE/Yamandon.cs +++ b/Projects/UOContent/Mobiles/Monsters/SE/Yamandon.cs @@ -3,159 +3,159 @@ using Server.Items; namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Yamadon")] - public class Yamandon : BaseCreature - { - [Constructible] - public Yamandon() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + [TypeAlias("Server.Mobiles.Yamadon")] + public class Yamandon : BaseCreature { - Body = 249; - - SetStr(786, 930); - SetDex(251, 365); - SetInt(101, 115); - - SetHits(1601, 1800); - - SetDamage(19, 35); - - SetDamageType(ResistanceType.Physical, 70); - SetDamageType(ResistanceType.Poison, 20); - SetDamageType(ResistanceType.Energy, 10); - - SetResistance(ResistanceType.Physical, 65, 85); - SetResistance(ResistanceType.Fire, 70, 90); - SetResistance(ResistanceType.Cold, 50, 70); - SetResistance(ResistanceType.Poison, 50, 70); - SetResistance(ResistanceType.Energy, 50, 70); - - SetSkill(SkillName.Anatomy, 115.1, 130.0); - SetSkill(SkillName.MagicResist, 117.6, 132.5); - SetSkill(SkillName.Poisoning, 120.1, 140.0); - SetSkill(SkillName.Tactics, 117.1, 132.0); - SetSkill(SkillName.Wrestling, 112.6, 132.5); - - Fame = 22000; - Karma = -22000; - - if (Utility.RandomDouble() < .50) - PackItem(Seed.RandomBonsaiSeed()); - - PackItem(new Eggs(2)); - } - - public Yamandon(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a yamandon corpse"; - public override string DefaultName => "a yamandon"; - - public override bool ReacquireOnMovement => true; - public override Poison PoisonImmune => Poison.Lethal; - public override Poison HitPoison => Utility.RandomBool() ? Poison.Deadly : Poison.Lethal; - public override int TreasureMapLevel => 5; - public override int Hides => 20; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.DoubleStrike; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich); - AddLoot(LootPack.FilthyRich, 2); - AddLoot(LootPack.Gems, 6); - } - - public override void OnDamagedBySpell(Mobile attacker) - { - base.OnDamagedBySpell(attacker); - - DoCounter(attacker); - } - - public override void OnGotMeleeAttack(Mobile attacker) - { - base.OnGotMeleeAttack(attacker); - - DoCounter(attacker); - } - - private void DoCounter(Mobile attacker) - { - if (Map == null) - return; - - if (attacker is BaseCreature creature && creature.BardProvoked) - return; - - if (Utility.RandomDouble() < 0.2) - { - /* Counterattack with Hit Poison Area - * 20-25 damage, unresistable - * Lethal poison, 100% of the time - * Particle effect: Type: "2" From: "0x4061A107" To: "0x0" ItemId: "0x36BD" ItemIdName: "explosion" FromLocation: "(296 615, 17)" ToLocation: "(296 615, 17)" Speed: "1" Duration: "10" FixedDirection: "True" Explode: "False" Hue: "0xA6" RenderMode: "0x0" Effect: "0x1F78" ExplodeEffect: "0x1" ExplodeSound: "0x0" Serial: "0x4061A107" Layer: "255" Unknown: "0x0" - * Doesn't work on provoked monsters - */ - - Mobile target = null; - - if (attacker is BaseCreature baseCreature) + [Constructible] + public Yamandon() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) { - Mobile m = baseCreature.GetMaster(); + Body = 249; - if (m != null) - target = m; + SetStr(786, 930); + SetDex(251, 365); + SetInt(101, 115); + + SetHits(1601, 1800); + + SetDamage(19, 35); + + SetDamageType(ResistanceType.Physical, 70); + SetDamageType(ResistanceType.Poison, 20); + SetDamageType(ResistanceType.Energy, 10); + + SetResistance(ResistanceType.Physical, 65, 85); + SetResistance(ResistanceType.Fire, 70, 90); + SetResistance(ResistanceType.Cold, 50, 70); + SetResistance(ResistanceType.Poison, 50, 70); + SetResistance(ResistanceType.Energy, 50, 70); + + SetSkill(SkillName.Anatomy, 115.1, 130.0); + SetSkill(SkillName.MagicResist, 117.6, 132.5); + SetSkill(SkillName.Poisoning, 120.1, 140.0); + SetSkill(SkillName.Tactics, 117.1, 132.0); + SetSkill(SkillName.Wrestling, 112.6, 132.5); + + Fame = 22000; + Karma = -22000; + + if (Utility.RandomDouble() < .50) + PackItem(Seed.RandomBonsaiSeed()); + + PackItem(new Eggs(2)); } - if (target?.InRange(this, 18) != true) - target = attacker; - - Animate(10, 4, 1, true, false, 0); - - IPooledEnumerable eable = target.GetMobilesInRange(8); - - foreach (Mobile m in eable) + public Yamandon(Serial serial) : base(serial) { - if (m == this || !(CanBeHarmful(m) || (m.Player && m.Alive))) - continue; - - if (!(m is BaseCreature bc) || !(bc.Controlled || bc.Summoned || bc.Team != Team)) - continue; - - DoHarmful(m); - - AOS.Damage(m, this, Utility.RandomMinMax(20, 25), true, 0, 0, 0, 100, 0); - - m.FixedParticles(0x36BD, 1, 10, 0x1F78, 0xA6, 0, (EffectLayer)255); - m.ApplyPoison(this, Poison.Lethal); } - eable.Free(); - } + public override string CorpseName => "a yamandon corpse"; + public override string DefaultName => "a yamandon"; + + public override bool ReacquireOnMovement => true; + public override Poison PoisonImmune => Poison.Lethal; + public override Poison HitPoison => Utility.RandomBool() ? Poison.Deadly : Poison.Lethal; + public override int TreasureMapLevel => 5; + public override int Hides => 20; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.DoubleStrike; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich); + AddLoot(LootPack.FilthyRich, 2); + AddLoot(LootPack.Gems, 6); + } + + public override void OnDamagedBySpell(Mobile attacker) + { + base.OnDamagedBySpell(attacker); + + DoCounter(attacker); + } + + public override void OnGotMeleeAttack(Mobile attacker) + { + base.OnGotMeleeAttack(attacker); + + DoCounter(attacker); + } + + private void DoCounter(Mobile attacker) + { + if (Map == null) + return; + + if (attacker is BaseCreature creature && creature.BardProvoked) + return; + + if (Utility.RandomDouble() < 0.2) + { + /* Counterattack with Hit Poison Area + * 20-25 damage, unresistable + * Lethal poison, 100% of the time + * Particle effect: Type: "2" From: "0x4061A107" To: "0x0" ItemId: "0x36BD" ItemIdName: "explosion" FromLocation: "(296 615, 17)" ToLocation: "(296 615, 17)" Speed: "1" Duration: "10" FixedDirection: "True" Explode: "False" Hue: "0xA6" RenderMode: "0x0" Effect: "0x1F78" ExplodeEffect: "0x1" ExplodeSound: "0x0" Serial: "0x4061A107" Layer: "255" Unknown: "0x0" + * Doesn't work on provoked monsters + */ + + Mobile target = null; + + if (attacker is BaseCreature baseCreature) + { + var m = baseCreature.GetMaster(); + + if (m != null) + target = m; + } + + if (target?.InRange(this, 18) != true) + target = attacker; + + Animate(10, 4, 1, true, false, 0); + + var eable = target.GetMobilesInRange(8); + + foreach (var m in eable) + { + if (m == this || !(CanBeHarmful(m) || m.Player && m.Alive)) + continue; + + if (!(m is BaseCreature bc) || !(bc.Controlled || bc.Summoned || bc.Team != Team)) + continue; + + DoHarmful(m); + + AOS.Damage(m, this, Utility.RandomMinMax(20, 25), true, 0, 0, 0, 100, 0); + + m.FixedParticles(0x36BD, 1, 10, 0x1F78, 0xA6, 0, (EffectLayer)255); + m.ApplyPoison(this, Poison.Lethal); + } + + eable.Free(); + } + } + + public override int GetAttackSound() => 1260; + + public override int GetAngerSound() => 1262; + + public override int GetDeathSound() => 1259; + + public override int GetHurtSound() => 1263; + + public override int GetIdleSound() => 1261; + + 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(); + } } - - public override int GetAttackSound() => 1260; - - public override int GetAngerSound() => 1262; - - public override int GetDeathSound() => 1259; - - public override int GetHurtSound() => 1263; - - public override int GetIdleSound() => 1261; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Monsters/SE/YomotsuElder.cs b/Projects/UOContent/Mobiles/Monsters/SE/YomotsuElder.cs index 9ce0217cd..f95b3eb98 100644 --- a/Projects/UOContent/Mobiles/Monsters/SE/YomotsuElder.cs +++ b/Projects/UOContent/Mobiles/Monsters/SE/YomotsuElder.cs @@ -4,126 +4,126 @@ using Server.Items; namespace Server.Mobiles { - public class YomotsuElder : BaseCreature - { - [Constructible] - public YomotsuElder() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class YomotsuElder : BaseCreature { - Body = 255; - BaseSoundID = 0x452; - - SetStr(686, 830); - SetDex(251, 365); - SetInt(17, 31); - - SetHits(801, 900); - - SetDamage(19, 27); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 65, 85); - SetResistance(ResistanceType.Fire, 30, 50); - SetResistance(ResistanceType.Cold, 45, 65); - SetResistance(ResistanceType.Poison, 35, 55); - SetResistance(ResistanceType.Energy, 25, 50); - - SetSkill(SkillName.Anatomy, 115.1, 130.0); - SetSkill(SkillName.MagicResist, 100.1, 120.0); - SetSkill(SkillName.Tactics, 115.1, 130.0); - SetSkill(SkillName.Wrestling, 110.1, 130.0); - - Fame = 12000; - Karma = -12000; - - PackItem(new GreenGourd()); - PackItem(new ExecutionersAxe()); - - PackItem( - Utility.Random(3) switch + [Constructible] + public YomotsuElder() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) { - 0 => new LongPants(), - 1 => new ShortPants(), - _ => null // 2 (30%) - } - ); + Body = 255; + BaseSoundID = 0x452; - PackItem( - Utility.Random(6) switch + SetStr(686, 830); + SetDex(251, 365); + SetInt(17, 31); + + SetHits(801, 900); + + SetDamage(19, 27); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 65, 85); + SetResistance(ResistanceType.Fire, 30, 50); + SetResistance(ResistanceType.Cold, 45, 65); + SetResistance(ResistanceType.Poison, 35, 55); + SetResistance(ResistanceType.Energy, 25, 50); + + SetSkill(SkillName.Anatomy, 115.1, 130.0); + SetSkill(SkillName.MagicResist, 100.1, 120.0); + SetSkill(SkillName.Tactics, 115.1, 130.0); + SetSkill(SkillName.Wrestling, 110.1, 130.0); + + Fame = 12000; + Karma = -12000; + + PackItem(new GreenGourd()); + PackItem(new ExecutionersAxe()); + + PackItem( + Utility.Random(3) switch + { + 0 => new LongPants(), + 1 => new ShortPants(), + _ => null // 2 (30%) + } + ); + + PackItem( + Utility.Random(6) switch + { + 0 => new Shoes(), + 1 => new Sandals(), + 2 => new Boots(), + 3 => new ThighBoots(), + _ => null // 4-5 (30%) + } + ); + + if (Utility.RandomDouble() < .25) + PackItem(Seed.RandomBonsaiSeed()); + } + + public YomotsuElder(Serial serial) : base(serial) { - 0 => new Shoes(), - 1 => new Sandals(), - 2 => new Boots(), - 3 => new ThighBoots(), - _ => null // 4-5 (30%) } - ); - if (Utility.RandomDouble() < .25) - PackItem(Seed.RandomBonsaiSeed()); + public override string CorpseName => "a wrinkly yomotsu corpse"; + public override string DefaultName => "a yomotsu elder"; + + public override FoodType FavoriteFood => FoodType.Fish; + + public override int Meat => 1; + + public override bool CanRummageCorpses => true; + public override int TreasureMapLevel => 5; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.DoubleStrike; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 3); + AddLoot(LootPack.Gems, 2); + } + + // TODO: Axe Throw + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomDouble() < 0.1) + { + /* Maniacal laugh + * Cliloc: 1070840 + * Effect: Type: "3" From: "0x57D4F5B" To: "0x0" ItemId: "0x37B9" ItemIdName: "glow" FromLocation: "(884 715, 10)" ToLocation: "(884 715, 10)" Speed: "10" Duration: "5" FixedDirection: "True" Explode: "False" + * Paralyzes for 4 seconds, or until hit + */ + + defender.FixedEffect(0x37B9, 10, 5); + defender.SendLocalizedMessage(1070840); // You are frozen as the creature laughs maniacally. + + defender.Paralyze(TimeSpan.FromSeconds(4.0)); + } + } + + 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(); + } + + public override int GetIdleSound() => 0x42A; + + public override int GetAttackSound() => 0x435; + + public override int GetHurtSound() => 0x436; + + public override int GetDeathSound() => 0x43A; } - - public YomotsuElder(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a wrinkly yomotsu corpse"; - public override string DefaultName => "a yomotsu elder"; - - public override FoodType FavoriteFood => FoodType.Fish; - - public override int Meat => 1; - - public override bool CanRummageCorpses => true; - public override int TreasureMapLevel => 5; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.DoubleStrike; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 3); - AddLoot(LootPack.Gems, 2); - } - - // TODO: Axe Throw - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (Utility.RandomDouble() < 0.1) - { - /* Maniacal laugh - * Cliloc: 1070840 - * Effect: Type: "3" From: "0x57D4F5B" To: "0x0" ItemId: "0x37B9" ItemIdName: "glow" FromLocation: "(884 715, 10)" ToLocation: "(884 715, 10)" Speed: "10" Duration: "5" FixedDirection: "True" Explode: "False" - * Paralyzes for 4 seconds, or until hit - */ - - defender.FixedEffect(0x37B9, 10, 5); - defender.SendLocalizedMessage(1070840); // You are frozen as the creature laughs maniacally. - - defender.Paralyze(TimeSpan.FromSeconds(4.0)); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - - public override int GetIdleSound() => 0x42A; - - public override int GetAttackSound() => 0x435; - - public override int GetHurtSound() => 0x436; - - public override int GetDeathSound() => 0x43A; - } } diff --git a/Projects/UOContent/Mobiles/Monsters/SE/YomotsuPriest.cs b/Projects/UOContent/Mobiles/Monsters/SE/YomotsuPriest.cs index 0d6463c3f..4e27ae6dd 100644 --- a/Projects/UOContent/Mobiles/Monsters/SE/YomotsuPriest.cs +++ b/Projects/UOContent/Mobiles/Monsters/SE/YomotsuPriest.cs @@ -4,133 +4,133 @@ using Server.Items; namespace Server.Mobiles { - public class YomotsuPriest : BaseCreature - { - [Constructible] - public YomotsuPriest() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class YomotsuPriest : BaseCreature { - Body = 253; - BaseSoundID = 0x452; + [Constructible] + public YomotsuPriest() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 253; + BaseSoundID = 0x452; - SetStr(486, 530); - SetDex(101, 115); - SetInt(601, 670); + SetStr(486, 530); + SetDex(101, 115); + SetInt(601, 670); - SetHits(486, 530); + SetHits(486, 530); - SetDamage(8, 10); + SetDamage(8, 10); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 65, 85); - SetResistance(ResistanceType.Fire, 30, 50); - SetResistance(ResistanceType.Cold, 45, 65); - SetResistance(ResistanceType.Poison, 35, 55); - SetResistance(ResistanceType.Energy, 25, 50); + SetResistance(ResistanceType.Physical, 65, 85); + SetResistance(ResistanceType.Fire, 30, 50); + SetResistance(ResistanceType.Cold, 45, 65); + SetResistance(ResistanceType.Poison, 35, 55); + SetResistance(ResistanceType.Energy, 25, 50); - SetSkill(SkillName.EvalInt, 92.6, 107.5); - SetSkill(SkillName.Magery, 105.1, 115.0); - SetSkill(SkillName.Meditation, 100.1, 110.0); - SetSkill(SkillName.MagicResist, 112.6, 122.5); - SetSkill(SkillName.Tactics, 55.1, 105.0); - SetSkill(SkillName.Wrestling, 47.6, 57.5); + SetSkill(SkillName.EvalInt, 92.6, 107.5); + SetSkill(SkillName.Magery, 105.1, 115.0); + SetSkill(SkillName.Meditation, 100.1, 110.0); + SetSkill(SkillName.MagicResist, 112.6, 122.5); + SetSkill(SkillName.Tactics, 55.1, 105.0); + SetSkill(SkillName.Wrestling, 47.6, 57.5); - Fame = 9000; - Karma = -9000; + Fame = 9000; + Karma = -9000; - PackItem(new GreenGourd()); - PackItem(new ExecutionersAxe()); + PackItem(new GreenGourd()); + PackItem(new ExecutionersAxe()); - switch (Utility.Random(3)) - { - case 0: - PackItem(new LongPants()); - break; - case 1: - PackItem(new ShortPants()); - break; - } + switch (Utility.Random(3)) + { + case 0: + PackItem(new LongPants()); + break; + case 1: + PackItem(new ShortPants()); + break; + } - switch (Utility.Random(6)) - { - case 0: - PackItem(new Shoes()); - break; - case 1: - PackItem(new Sandals()); - break; - case 2: - PackItem(new Boots()); - break; - case 3: - PackItem(new ThighBoots()); - break; - } + switch (Utility.Random(6)) + { + case 0: + PackItem(new Shoes()); + break; + case 1: + PackItem(new Sandals()); + break; + case 2: + PackItem(new Boots()); + break; + case 3: + PackItem(new ThighBoots()); + break; + } - if (Utility.RandomDouble() < .25) PackItem(Seed.RandomBonsaiSeed()); + if (Utility.RandomDouble() < .25) PackItem(Seed.RandomBonsaiSeed()); + } + + public YomotsuPriest(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a glowing yomotsu corpse"; + public override string DefaultName => "a yomotsu priest"; + + public override FoodType FavoriteFood => FoodType.Fish; + + public override int Meat => 1; + + public override bool CanRummageCorpses => true; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.DoubleStrike; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.Rich); + AddLoot(LootPack.Gems, 4); + } + + // TODO: Body Transformation + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomDouble() < 0.1) + { + /* Maniacal laugh + * Cliloc: 1070840 + * Effect: Type: "3" From: "0x57D4F5B" To: "0x0" ItemId: "0x37B9" ItemIdName: "glow" FromLocation: "(884 715, 10)" ToLocation: "(884 715, 10)" Speed: "10" Duration: "5" FixedDirection: "True" Explode: "False" + * Paralyzes for 4 seconds, or until hit + */ + + defender.FixedEffect(0x37B9, 10, 5); + defender.SendLocalizedMessage(1070840); // You are frozen as the creature laughs maniacally. + + defender.Paralyze(TimeSpan.FromSeconds(4.0)); + } + } + + 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(); + } + + public override int GetIdleSound() => 0x42A; + + public override int GetAttackSound() => 0x435; + + public override int GetHurtSound() => 0x436; + + public override int GetDeathSound() => 0x43A; } - - public YomotsuPriest(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a glowing yomotsu corpse"; - public override string DefaultName => "a yomotsu priest"; - - public override FoodType FavoriteFood => FoodType.Fish; - - public override int Meat => 1; - - public override bool CanRummageCorpses => true; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.DoubleStrike; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.Rich); - AddLoot(LootPack.Gems, 4); - } - - // TODO: Body Transformation - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (Utility.RandomDouble() < 0.1) - { - /* Maniacal laugh - * Cliloc: 1070840 - * Effect: Type: "3" From: "0x57D4F5B" To: "0x0" ItemId: "0x37B9" ItemIdName: "glow" FromLocation: "(884 715, 10)" ToLocation: "(884 715, 10)" Speed: "10" Duration: "5" FixedDirection: "True" Explode: "False" - * Paralyzes for 4 seconds, or until hit - */ - - defender.FixedEffect(0x37B9, 10, 5); - defender.SendLocalizedMessage(1070840); // You are frozen as the creature laughs maniacally. - - defender.Paralyze(TimeSpan.FromSeconds(4.0)); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - - public override int GetIdleSound() => 0x42A; - - public override int GetAttackSound() => 0x435; - - public override int GetHurtSound() => 0x436; - - public override int GetDeathSound() => 0x43A; - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/SE/YomotsuWarrior.cs b/Projects/UOContent/Mobiles/Monsters/SE/YomotsuWarrior.cs index 42a2fdfbf..7076737b0 100644 --- a/Projects/UOContent/Mobiles/Monsters/SE/YomotsuWarrior.cs +++ b/Projects/UOContent/Mobiles/Monsters/SE/YomotsuWarrior.cs @@ -4,128 +4,128 @@ using Server.Items; namespace Server.Mobiles { - public class YomotsuWarrior : BaseCreature - { - [Constructible] - public YomotsuWarrior() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class YomotsuWarrior : BaseCreature { - Body = 245; - BaseSoundID = 0x452; + [Constructible] + public YomotsuWarrior() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 245; + BaseSoundID = 0x452; - SetStr(486, 530); - SetDex(151, 165); - SetInt(17, 31); + SetStr(486, 530); + SetDex(151, 165); + SetInt(17, 31); - SetHits(486, 530); - SetMana(17, 31); + SetHits(486, 530); + SetMana(17, 31); - SetDamage(8, 10); + SetDamage(8, 10); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 65, 85); - SetResistance(ResistanceType.Fire, 30, 50); - SetResistance(ResistanceType.Cold, 45, 65); - SetResistance(ResistanceType.Poison, 35, 55); - SetResistance(ResistanceType.Energy, 25, 50); + SetResistance(ResistanceType.Physical, 65, 85); + SetResistance(ResistanceType.Fire, 30, 50); + SetResistance(ResistanceType.Cold, 45, 65); + SetResistance(ResistanceType.Poison, 35, 55); + SetResistance(ResistanceType.Energy, 25, 50); - SetSkill(SkillName.Anatomy, 85.1, 95.0); - SetSkill(SkillName.MagicResist, 82.6, 90.5); - SetSkill(SkillName.Tactics, 95.1, 105.0); - SetSkill(SkillName.Wrestling, 97.6, 107.5); + SetSkill(SkillName.Anatomy, 85.1, 95.0); + SetSkill(SkillName.MagicResist, 82.6, 90.5); + SetSkill(SkillName.Tactics, 95.1, 105.0); + SetSkill(SkillName.Wrestling, 97.6, 107.5); - Fame = 4200; - Karma = -4200; + Fame = 4200; + Karma = -4200; - PackItem(new GreenGourd()); - PackItem(new ExecutionersAxe()); + PackItem(new GreenGourd()); + PackItem(new ExecutionersAxe()); - if (Utility.RandomBool()) - PackItem(new LongPants()); - else - PackItem(new ShortPants()); + if (Utility.RandomBool()) + PackItem(new LongPants()); + else + PackItem(new ShortPants()); - switch (Utility.Random(4)) - { - case 0: - PackItem(new Shoes()); - break; - case 1: - PackItem(new Sandals()); - break; - case 2: - PackItem(new Boots()); - break; - case 3: - PackItem(new ThighBoots()); - break; - } + switch (Utility.Random(4)) + { + case 0: + PackItem(new Shoes()); + break; + case 1: + PackItem(new Sandals()); + break; + case 2: + PackItem(new Boots()); + break; + case 3: + PackItem(new ThighBoots()); + break; + } - if (Utility.RandomDouble() < .25) - PackItem(Seed.RandomBonsaiSeed()); + if (Utility.RandomDouble() < .25) + PackItem(Seed.RandomBonsaiSeed()); + } + + public YomotsuWarrior(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a yomotsu corpse"; + public override string DefaultName => "a yomotsu warrior"; + + public override FoodType FavoriteFood => FoodType.Fish; + + public override int Meat => 1; + + public override bool CanRummageCorpses => true; + public override int TreasureMapLevel => 3; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.DoubleStrike; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich, 2); + AddLoot(LootPack.Gems, 2); + } + + // TODO: Throwing Dagger + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomDouble() < 0.1) + { + /* Maniacal laugh + * Cliloc: 1070840 + * Effect: Type: "3" From: "0x57D4F5B" To: "0x0" ItemId: "0x37B9" ItemIdName: "glow" FromLocation: "(884 715, 10)" ToLocation: "(884 715, 10)" Speed: "10" Duration: "5" FixedDirection: "True" Explode: "False" + * Paralyzes for 4 seconds, or until hit + */ + + defender.FixedEffect(0x37B9, 10, 5); + defender.SendLocalizedMessage(1070840); // You are frozen as the creature laughs maniacally. + + defender.Paralyze(TimeSpan.FromSeconds(4.0)); + } + } + + 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(); + } + + public override int GetIdleSound() => 0x42A; + + public override int GetAttackSound() => 0x435; + + public override int GetHurtSound() => 0x436; + + public override int GetDeathSound() => 0x43A; } - - public YomotsuWarrior(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a yomotsu corpse"; - public override string DefaultName => "a yomotsu warrior"; - - public override FoodType FavoriteFood => FoodType.Fish; - - public override int Meat => 1; - - public override bool CanRummageCorpses => true; - public override int TreasureMapLevel => 3; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.DoubleStrike; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich, 2); - AddLoot(LootPack.Gems, 2); - } - - // TODO: Throwing Dagger - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (Utility.RandomDouble() < 0.1) - { - /* Maniacal laugh - * Cliloc: 1070840 - * Effect: Type: "3" From: "0x57D4F5B" To: "0x0" ItemId: "0x37B9" ItemIdName: "glow" FromLocation: "(884 715, 10)" ToLocation: "(884 715, 10)" Speed: "10" Duration: "5" FixedDirection: "True" Explode: "False" - * Paralyzes for 4 seconds, or until hit - */ - - defender.FixedEffect(0x37B9, 10, 5); - defender.SendLocalizedMessage(1070840); // You are frozen as the creature laughs maniacally. - - defender.Paralyze(TimeSpan.FromSeconds(4.0)); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - - public override int GetIdleSound() => 0x42A; - - public override int GetAttackSound() => 0x435; - - public override int GetHurtSound() => 0x436; - - public override int GetDeathSound() => 0x43A; - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Summons/SummonedAirElemental.cs b/Projects/UOContent/Mobiles/Monsters/Summons/SummonedAirElemental.cs index dbe6d792c..ed028e3bc 100644 --- a/Projects/UOContent/Mobiles/Monsters/Summons/SummonedAirElemental.cs +++ b/Projects/UOContent/Mobiles/Monsters/Summons/SummonedAirElemental.cs @@ -1,65 +1,65 @@ namespace Server.Mobiles { - public class SummonedAirElemental : BaseCreature - { - [Constructible] - public SummonedAirElemental() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class SummonedAirElemental : BaseCreature { - Body = 13; - Hue = 0x4001; - BaseSoundID = 655; + [Constructible] + public SummonedAirElemental() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 13; + Hue = 0x4001; + BaseSoundID = 655; - SetStr(200); - SetDex(200); - SetInt(100); + SetStr(200); + SetDex(200); + SetInt(100); - SetHits(150); - SetStam(50); + SetHits(150); + SetStam(50); - SetDamage(6, 9); + SetDamage(6, 9); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Energy, 50); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Energy, 50); - SetResistance(ResistanceType.Physical, 40, 50); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 35, 45); - SetResistance(ResistanceType.Poison, 50, 60); - SetResistance(ResistanceType.Energy, 70, 80); + SetResistance(ResistanceType.Physical, 40, 50); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 35, 45); + SetResistance(ResistanceType.Poison, 50, 60); + SetResistance(ResistanceType.Energy, 70, 80); - SetSkill(SkillName.Meditation, 90.0); - SetSkill(SkillName.EvalInt, 70.0); - SetSkill(SkillName.Magery, 70.0); - SetSkill(SkillName.MagicResist, 60.0); - SetSkill(SkillName.Tactics, 100.0); - SetSkill(SkillName.Wrestling, 80.0); + SetSkill(SkillName.Meditation, 90.0); + SetSkill(SkillName.EvalInt, 70.0); + SetSkill(SkillName.Magery, 70.0); + SetSkill(SkillName.MagicResist, 60.0); + SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.Wrestling, 80.0); - VirtualArmor = 40; - ControlSlots = 2; + VirtualArmor = 40; + ControlSlots = 2; + } + + public SummonedAirElemental(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an air elemental corpse"; + public override double DispelDifficulty => 117.5; + public override double DispelFocus => 45.0; + public override string DefaultName => "an air elemental"; + + 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 (BaseSoundID == 263) + BaseSoundID = 655; + } } - - public SummonedAirElemental(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an air elemental corpse"; - public override double DispelDifficulty => 117.5; - public override double DispelFocus => 45.0; - public override string DefaultName => "an air elemental"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - if (BaseSoundID == 263) - BaseSoundID = 655; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Summons/SummonedDaemon.cs b/Projects/UOContent/Mobiles/Monsters/Summons/SummonedDaemon.cs index 38acfac4d..776d5dba8 100644 --- a/Projects/UOContent/Mobiles/Monsters/Summons/SummonedDaemon.cs +++ b/Projects/UOContent/Mobiles/Monsters/Summons/SummonedDaemon.cs @@ -1,61 +1,61 @@ namespace Server.Mobiles { - public class SummonedDaemon : BaseCreature - { - [Constructible] - public SummonedDaemon() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class SummonedDaemon : BaseCreature { - Name = NameList.RandomName("daemon"); - Body = Core.AOS ? 10 : 9; - BaseSoundID = 357; + [Constructible] + public SummonedDaemon() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Name = NameList.RandomName("daemon"); + Body = Core.AOS ? 10 : 9; + BaseSoundID = 357; - SetStr(200); - SetDex(110); - SetInt(150); + SetStr(200); + SetDex(110); + SetInt(150); - SetDamage(14, 21); + SetDamage(14, 21); - SetDamageType(ResistanceType.Physical, 0); - SetDamageType(ResistanceType.Poison, 100); + SetDamageType(ResistanceType.Physical, 0); + SetDamageType(ResistanceType.Poison, 100); - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 50, 60); - SetResistance(ResistanceType.Cold, 20, 30); - SetResistance(ResistanceType.Poison, 70, 80); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 50, 60); + SetResistance(ResistanceType.Cold, 20, 30); + SetResistance(ResistanceType.Poison, 70, 80); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.EvalInt, 90.1, 100.0); - SetSkill(SkillName.Meditation, 90.1, 100.0); - SetSkill(SkillName.Magery, 90.1, 100.0); - SetSkill(SkillName.MagicResist, 90.1, 100.0); - SetSkill(SkillName.Tactics, 100.0); - SetSkill(SkillName.Wrestling, 98.1, 99.0); + SetSkill(SkillName.EvalInt, 90.1, 100.0); + SetSkill(SkillName.Meditation, 90.1, 100.0); + SetSkill(SkillName.Magery, 90.1, 100.0); + SetSkill(SkillName.MagicResist, 90.1, 100.0); + SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.Wrestling, 98.1, 99.0); - VirtualArmor = 58; - ControlSlots = Core.SE ? 4 : 5; + VirtualArmor = 58; + ControlSlots = Core.SE ? 4 : 5; + } + + public SummonedDaemon(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a daemon corpse"; + public override double DispelDifficulty => 125.0; + public override double DispelFocus => 45.0; + + public override Poison PoisonImmune => Poison.Regular; // TODO: Immune to poison? + public override bool CanFly => true; + + 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(); + } } - - public SummonedDaemon(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a daemon corpse"; - public override double DispelDifficulty => 125.0; - public override double DispelFocus => 45.0; - - public override Poison PoisonImmune => Poison.Regular; // TODO: Immune to poison? - public override bool CanFly => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Summons/SummonedEarthElemental.cs b/Projects/UOContent/Mobiles/Monsters/Summons/SummonedEarthElemental.cs index 2c8649f6e..b7d499ed7 100644 --- a/Projects/UOContent/Mobiles/Monsters/Summons/SummonedEarthElemental.cs +++ b/Projects/UOContent/Mobiles/Monsters/Summons/SummonedEarthElemental.cs @@ -1,56 +1,56 @@ namespace Server.Mobiles { - public class SummonedEarthElemental : BaseCreature - { - [Constructible] - public SummonedEarthElemental() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class SummonedEarthElemental : BaseCreature { - Body = 14; - BaseSoundID = 268; + [Constructible] + public SummonedEarthElemental() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 14; + BaseSoundID = 268; - SetStr(200); - SetDex(70); - SetInt(70); + SetStr(200); + SetDex(70); + SetInt(70); - SetHits(180); + SetHits(180); - SetDamage(14, 21); + SetDamage(14, 21); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 65, 75); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 65, 75); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.MagicResist, 65.0); - SetSkill(SkillName.Tactics, 100.0); - SetSkill(SkillName.Wrestling, 90.0); + SetSkill(SkillName.MagicResist, 65.0); + SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.Wrestling, 90.0); - VirtualArmor = 34; - ControlSlots = 2; + VirtualArmor = 34; + ControlSlots = 2; + } + + public SummonedEarthElemental(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an earth elemental corpse"; + public override double DispelDifficulty => 117.5; + public override double DispelFocus => 45.0; + public override string DefaultName => "an earth elemental"; + + 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(); + } } - - public SummonedEarthElemental(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an earth elemental corpse"; - public override double DispelDifficulty => 117.5; - public override double DispelFocus => 45.0; - public override string DefaultName => "an earth elemental"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Summons/SummonedFireElemental.cs b/Projects/UOContent/Mobiles/Monsters/Summons/SummonedFireElemental.cs index a9e1d4be6..e76e2a472 100644 --- a/Projects/UOContent/Mobiles/Monsters/Summons/SummonedFireElemental.cs +++ b/Projects/UOContent/Mobiles/Monsters/Summons/SummonedFireElemental.cs @@ -2,60 +2,60 @@ using Server.Items; namespace Server.Mobiles { - public class SummonedFireElemental : BaseCreature - { - [Constructible] - public SummonedFireElemental() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class SummonedFireElemental : BaseCreature { - Body = 15; - BaseSoundID = 838; + [Constructible] + public SummonedFireElemental() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 15; + BaseSoundID = 838; - SetStr(200); - SetDex(200); - SetInt(100); + SetStr(200); + SetDex(200); + SetInt(100); - SetDamage(9, 14); + SetDamage(9, 14); - SetDamageType(ResistanceType.Physical, 0); - SetDamageType(ResistanceType.Fire, 100); + SetDamageType(ResistanceType.Physical, 0); + SetDamageType(ResistanceType.Fire, 100); - SetResistance(ResistanceType.Physical, 50, 60); - SetResistance(ResistanceType.Fire, 70, 80); - SetResistance(ResistanceType.Cold, 0, 10); - SetResistance(ResistanceType.Poison, 50, 60); - SetResistance(ResistanceType.Energy, 50, 60); + SetResistance(ResistanceType.Physical, 50, 60); + SetResistance(ResistanceType.Fire, 70, 80); + SetResistance(ResistanceType.Cold, 0, 10); + SetResistance(ResistanceType.Poison, 50, 60); + SetResistance(ResistanceType.Energy, 50, 60); - SetSkill(SkillName.EvalInt, 90.0); - SetSkill(SkillName.Magery, 90.0); - SetSkill(SkillName.MagicResist, 85.0); - SetSkill(SkillName.Tactics, 100.0); - SetSkill(SkillName.Wrestling, 92.0); + SetSkill(SkillName.EvalInt, 90.0); + SetSkill(SkillName.Magery, 90.0); + SetSkill(SkillName.MagicResist, 85.0); + SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.Wrestling, 92.0); - VirtualArmor = 40; - ControlSlots = 4; + VirtualArmor = 40; + ControlSlots = 4; - AddItem(new LightSource()); + AddItem(new LightSource()); + } + + public SummonedFireElemental(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a fire elemental corpse"; + public override double DispelDifficulty => 117.5; + public override double DispelFocus => 45.0; + public override string DefaultName => "a fire elemental"; + + 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(); + } } - - public SummonedFireElemental(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a fire elemental corpse"; - public override double DispelDifficulty => 117.5; - public override double DispelFocus => 45.0; - public override string DefaultName => "a fire elemental"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Monsters/Summons/SummonedWaterElemental.cs b/Projects/UOContent/Mobiles/Monsters/Summons/SummonedWaterElemental.cs index a932ac1db..1228bb03d 100644 --- a/Projects/UOContent/Mobiles/Monsters/Summons/SummonedWaterElemental.cs +++ b/Projects/UOContent/Mobiles/Monsters/Summons/SummonedWaterElemental.cs @@ -1,61 +1,61 @@ namespace Server.Mobiles { - public class SummonedWaterElemental : BaseCreature - { - [Constructible] - public SummonedWaterElemental() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class SummonedWaterElemental : BaseCreature { - Body = 16; - BaseSoundID = 278; + [Constructible] + public SummonedWaterElemental() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 16; + BaseSoundID = 278; - SetStr(200); - SetDex(70); - SetInt(100); + SetStr(200); + SetDex(70); + SetInt(100); - SetHits(165); + SetHits(165); - SetDamage(12, 16); + SetDamage(12, 16); - SetDamageType(ResistanceType.Physical, 0); - SetDamageType(ResistanceType.Cold, 100); + SetDamageType(ResistanceType.Physical, 0); + SetDamageType(ResistanceType.Cold, 100); - SetResistance(ResistanceType.Physical, 50, 60); - SetResistance(ResistanceType.Fire, 20, 30); - SetResistance(ResistanceType.Cold, 70, 80); - SetResistance(ResistanceType.Poison, 45, 55); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 50, 60); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 70, 80); + SetResistance(ResistanceType.Poison, 45, 55); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.Meditation, 90.0); - SetSkill(SkillName.EvalInt, 80.0); - SetSkill(SkillName.Magery, 80.0); - SetSkill(SkillName.MagicResist, 75.0); - SetSkill(SkillName.Tactics, 100.0); - SetSkill(SkillName.Wrestling, 85.0); + SetSkill(SkillName.Meditation, 90.0); + SetSkill(SkillName.EvalInt, 80.0); + SetSkill(SkillName.Magery, 80.0); + SetSkill(SkillName.MagicResist, 75.0); + SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.Wrestling, 85.0); - VirtualArmor = 40; - ControlSlots = 3; - CanSwim = true; + VirtualArmor = 40; + ControlSlots = 3; + CanSwim = true; + } + + public SummonedWaterElemental(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a water elemental corpse"; + public override double DispelDifficulty => 117.5; + public override double DispelFocus => 45.0; + public override string DefaultName => "a water elemental"; + + 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(); + } } - - public SummonedWaterElemental(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a water elemental corpse"; - public override double DispelDifficulty => 117.5; - public override double DispelFocus => 45.0; - public override string DefaultName => "a water elemental"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/PlayerMobile.cs b/Projects/UOContent/Mobiles/PlayerMobile.cs index cde68b4cd..a1210c35a 100644 --- a/Projects/UOContent/Mobiles/PlayerMobile.cs +++ b/Projects/UOContent/Mobiles/PlayerMobile.cs @@ -40,4486 +40,4603 @@ using RankDefinition = Server.Guilds.RankDefinition; namespace Server.Mobiles { - [Flags] - public enum PlayerFlag // First 16 bits are reserved for default-distro use, start custom flags at 0x00010000 - { - None = 0x00000000, - Glassblowing = 0x00000001, - Masonry = 0x00000002, - SandMining = 0x00000004, - StoneMining = 0x00000008, - ToggleMiningStone = 0x00000010, - KarmaLocked = 0x00000020, - AutoRenewInsurance = 0x00000040, - UseOwnFilter = 0x00000080, - PublicMyRunUO = 0x00000100, - PagingSquelched = 0x00000200, - Young = 0x00000400, - AcceptGuildInvites = 0x00000800, - DisplayChampionTitle = 0x00001000, - HasStatReward = 0x00002000, - RefuseTrades = 0x00004000 - } - - public enum NpcGuild - { - None, - MagesGuild, - WarriorsGuild, - ThievesGuild, - RangersGuild, - HealersGuild, - MinersGuild, - MerchantsGuild, - TinkersGuild, - TailorsGuild, - FishermensGuild, - BardsGuild, - BlacksmithsGuild - } - - public enum SolenFriendship - { - None, - Red, - Black - } - - public enum BlockMountType - { - None = -1, - Dazed = 1040024, - BolaRecovery = 1062910, - DismountRecovery = 1070859 - } - - public class PlayerMobile : Mobile, IHonorTarget - { - private static bool m_NoRecursion; - - private List m_AllFollowers; - - private readonly Dictionary> m_AntiMacroTable; - private TimeSpan m_GameTime; - - /* - * a value of zero means, that the mobile is not executing the spell. Otherwise, - * the value should match the BaseMana required - */ - - private RankDefinition m_GuildRank; - - private bool m_IgnoreMobiles; // IgnoreMobiles should be moved to Server.Mobiles - - private Mobile m_InsuranceAward; - private int m_InsuranceBonus; - - private int m_LastGlobalLight = -1, m_LastPersonalLight = -1; - - private bool m_LastProtectedMessage; - private TimeSpan m_LongTermElapse; - - private MountBlock m_MountBlock; - private int m_NextProtectionCheck = 10; - private DateTime m_NextSmithBulkOrder; - private DateTime m_NextTailorBulkOrder; - - private bool m_NoDeltaRecursion; - - private int - m_NonAutoreinsuredItems; // number of items that could not be automatically reinsured because gold in bank was not enough - - private DateTime m_SavagePaintExpiration; - private TimeSpan m_ShortTermElapse; - - public PlayerMobile() + [Flags] + public enum PlayerFlag // First 16 bits are reserved for default-distro use, start custom flags at 0x00010000 { - AutoStabled = new List(); - - VisibilityList = new List(); - PermaFlags = new List(); - m_AntiMacroTable = new Dictionary>(); - RecentlyReported = new List(); - - BOBFilter = new BOBFilter(); - - m_GameTime = TimeSpan.Zero; - m_ShortTermElapse = TimeSpan.FromHours(8.0); - m_LongTermElapse = TimeSpan.FromHours(40.0); - - JusticeProtectors = new List(); - m_GuildRank = RankDefinition.Lowest; - - ChampionTitles = new ChampionTitleInfo(); + None = 0x00000000, + Glassblowing = 0x00000001, + Masonry = 0x00000002, + SandMining = 0x00000004, + StoneMining = 0x00000008, + ToggleMiningStone = 0x00000010, + KarmaLocked = 0x00000020, + AutoRenewInsurance = 0x00000040, + UseOwnFilter = 0x00000080, + PublicMyRunUO = 0x00000100, + PagingSquelched = 0x00000200, + Young = 0x00000400, + AcceptGuildInvites = 0x00000800, + DisplayChampionTitle = 0x00001000, + HasStatReward = 0x00002000, + RefuseTrades = 0x00004000 } - public PlayerMobile(Serial s) : base(s) + public enum NpcGuild { - VisibilityList = new List(); - m_AntiMacroTable = new Dictionary>(); + None, + MagesGuild, + WarriorsGuild, + ThievesGuild, + RangersGuild, + HealersGuild, + MinersGuild, + MerchantsGuild, + TinkersGuild, + TailorsGuild, + FishermensGuild, + BardsGuild, + BlacksmithsGuild } - [CommandProperty(AccessLevel.GameMaster)] - public DateTime AnkhNextUse { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan DisguiseTimeLeft => DisguiseTimers.TimeRemaining(this); - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime PeacedUntil { get; set; } - - public DesignContext DesignContext { get; set; } - - public BlockMountType MountBlockReason => CheckBlock(m_MountBlock) ? m_MountBlock.m_Type : BlockMountType.None; - - public override int MaxWeight => (Core.ML && Race == Race.Human ? 100 : 40) + (int)(3.5 * Str); - - public override double ArmorRating + public enum SolenFriendship { - get - { - // BaseArmor ar; - double rating = 0.0; - - AddArmorRating(ref rating, NeckArmor); - AddArmorRating(ref rating, HandArmor); - AddArmorRating(ref rating, HeadArmor); - AddArmorRating(ref rating, ArmsArmor); - AddArmorRating(ref rating, LegsArmor); - AddArmorRating(ref rating, ChestArmor); - AddArmorRating(ref rating, ShieldArmor); - - return VirtualArmor + VirtualArmorMod + rating; - } + None, + Red, + Black } - public SkillName[] AnimalFormRestrictedSkills { get; } = + public enum BlockMountType { - SkillName.ArmsLore, SkillName.Begging, SkillName.Discordance, SkillName.Forensics, - SkillName.Inscribe, SkillName.ItemID, SkillName.Meditation, SkillName.Peacemaking, - SkillName.Provocation, SkillName.RemoveTrap, SkillName.SpiritSpeak, SkillName.Stealing, - SkillName.TasteID - }; - - public override double RacialSkillBonus - { - get - { - if (Core.ML && Race == Race.Human) - return 20.0; - - return 0; - } + None = -1, + Dazed = 1040024, + BolaRecovery = 1062910, + DismountRecovery = 1070859 } - public List EquipSnapshot { get; private set; } - - public SkillName Learning { get; set; } = (SkillName)(-1); - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan SavagePaintExpiration + public class PlayerMobile : Mobile, IHonorTarget { - get - { - TimeSpan ts = m_SavagePaintExpiration - DateTime.UtcNow; + private static bool m_NoRecursion; - if (ts < TimeSpan.Zero) - ts = TimeSpan.Zero; + private static readonly bool FastwalkPrevention = true; // Is fastwalk prevention enabled? + private static readonly int FastwalkThreshold = 400; // Fastwalk prevention will become active after 0.4 seconds - return ts; - } - set => m_SavagePaintExpiration = DateTime.UtcNow + value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan NextSmithBulkOrder - { - get - { - TimeSpan ts = m_NextSmithBulkOrder - DateTime.UtcNow; - - if (ts < TimeSpan.Zero) - ts = TimeSpan.Zero; - - return ts; - } - set - { - try + private static readonly Point3D[] m_TrammelDeathDestinations = { - m_NextSmithBulkOrder = DateTime.UtcNow + value; + new Point3D(1481, 1612, 20), + new Point3D(2708, 2153, 0), + new Point3D(2249, 1230, 0), + new Point3D(5197, 3994, 37), + new Point3D(1412, 3793, 0), + new Point3D(3688, 2232, 20), + new Point3D(2578, 604, 0), + new Point3D(4397, 1089, 0), + new Point3D(5741, 3218, -2), + new Point3D(2996, 3441, 15), + new Point3D(624, 2225, 0), + new Point3D(1916, 2814, 0), + new Point3D(2929, 854, 0), + new Point3D(545, 967, 0), + new Point3D(3665, 2587, 0) + }; + + private static readonly Point3D[] m_IlshenarDeathDestinations = + { + new Point3D(1216, 468, -13), + new Point3D(723, 1367, -60), + new Point3D(745, 725, -28), + new Point3D(281, 1017, 0), + new Point3D(986, 1011, -32), + new Point3D(1175, 1287, -30), + new Point3D(1533, 1341, -3), + new Point3D(529, 217, -44), + new Point3D(1722, 219, 96) + }; + + private static readonly Point3D[] m_MalasDeathDestinations = + { + new Point3D(2079, 1376, -70), + new Point3D(944, 519, -71) + }; + + private static readonly Point3D[] m_TokunoDeathDestinations = + { + new Point3D(1166, 801, 27), + new Point3D(782, 1228, 25), + new Point3D(268, 624, 15) + }; + + private readonly Dictionary> m_AntiMacroTable; + + private Dictionary m_AcquiredRecipes; + + private List m_AllFollowers; + private int m_BeardModID = -1, m_BeardModHue; + + private Dictionary m_BuffTable; + + private DuelPlayer m_DuelPlayer; + + private Type m_EnemyOfOneType; + private TimeSpan m_GameTime; + + /* + * a value of zero means, that the mobile is not executing the spell. Otherwise, + * the value should match the BaseMana required + */ + + private RankDefinition m_GuildRank; + + private int m_HairModID = -1, m_HairModHue; + private bool m_HasMoved; + + public DateTime m_hontime; + + private bool m_IgnoreMobiles; // IgnoreMobiles should be moved to Server.Mobiles + + private Mobile m_InsuranceAward; + private int m_InsuranceBonus; + + private int m_LastGlobalLight = -1, m_LastPersonalLight = -1; + + private bool m_LastProtectedMessage; + + private DateTime m_LastYoungHeal = DateTime.MinValue; + + private DateTime m_LastYoungMessage = DateTime.MinValue; + private TimeSpan m_LongTermElapse; + + private MountBlock m_MountBlock; + + private DateTime m_NextJustAward; + + private long m_NextMovementTime; + private int m_NextProtectionCheck = 10; + private DateTime m_NextSmithBulkOrder; + private DateTime m_NextTailorBulkOrder; + + private bool m_NoDeltaRecursion; + + private int + m_NonAutoreinsuredItems; // number of items that could not be automatically reinsured because gold in bank was not enough + + private DateTime m_SavagePaintExpiration; + private TimeSpan m_ShortTermElapse; + + private DateTime[] m_StuckMenuUses; + + public PlayerMobile() + { + AutoStabled = new List(); + + VisibilityList = new List(); + PermaFlags = new List(); + m_AntiMacroTable = new Dictionary>(); + RecentlyReported = new List(); + + BOBFilter = new BOBFilter(); + + m_GameTime = TimeSpan.Zero; + m_ShortTermElapse = TimeSpan.FromHours(8.0); + m_LongTermElapse = TimeSpan.FromHours(40.0); + + JusticeProtectors = new List(); + m_GuildRank = RankDefinition.Lowest; + + ChampionTitles = new ChampionTitleInfo(); } - catch + + public PlayerMobile(Serial s) : base(s) { - // ignored + VisibilityList = new List(); + m_AntiMacroTable = new Dictionary>(); } - } - } - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan NextTailorBulkOrder - { - get - { - TimeSpan ts = m_NextTailorBulkOrder - DateTime.UtcNow; + [CommandProperty(AccessLevel.GameMaster)] + public DateTime AnkhNextUse { get; set; } - if (ts < TimeSpan.Zero) - ts = TimeSpan.Zero; + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan DisguiseTimeLeft => DisguiseTimers.TimeRemaining(this); - return ts; - } - set - { - try + [CommandProperty(AccessLevel.GameMaster)] + public DateTime PeacedUntil { get; set; } + + public DesignContext DesignContext { get; set; } + + public BlockMountType MountBlockReason => CheckBlock(m_MountBlock) ? m_MountBlock.m_Type : BlockMountType.None; + + public override int MaxWeight => (Core.ML && Race == Race.Human ? 100 : 40) + (int)(3.5 * Str); + + public override double ArmorRating { - m_NextTailorBulkOrder = DateTime.UtcNow + value; - } - catch - { - // ignored - } - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime LastEscortTime { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime LastPetBallTime { get; set; } - - public List VisibilityList { get; } - - public List PermaFlags { get; private set; } - - public override int Luck => AosAttributes.GetValue(this, AosAttribute.Luck); - - public BOBFilter BOBFilter { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime SessionStart { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan GameTime - { - get - { - if (NetState != null) - return m_GameTime + (DateTime.UtcNow - SessionStart); - return m_GameTime; - } - } - - public override bool NewGuildDisplay => Guilds.Guild.NewGuildSystem; - - public bool BedrollLogout { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public override bool Paralyzed - { - get => base.Paralyzed; - set - { - base.Paralyzed = value; - - if (value) - AddBuff(new BuffInfo(BuffIcon.Paralyze, 1075827)); // Paralyze/You are frozen and can not move - else - RemoveBuff(BuffIcon.Paralyze); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Player EthicPlayer { get; set; } - - public PlayerState FactionPlayerState { get; set; } - - public override void ToggleFlying() - { - if (Race != Race.Gargoyle) return; - - if (Flying) - { - Freeze(TimeSpan.FromSeconds(1)); - Animate(61, 10, 1, true, false, 0); - Flying = false; - BuffInfo.RemoveBuff(this, BuffIcon.Fly); - SendMessage("You have landed."); - - BaseMount.Dismount(this); - return; - } - - BlockMountType type = MountBlockReason; - - if (!Alive) - { - SendLocalizedMessage(1113082); // You may not fly while dead. - } - else if (IsBodyMod && !(BodyMod == 666 || BodyMod == 667)) - { - SendLocalizedMessage(1112453); // You can't fly in your current form! - } - else if (type != BlockMountType.None) - { - switch (type) - { - case BlockMountType.Dazed: - SendLocalizedMessage(1112457); - break; // You are still too dazed to fly. - case BlockMountType.BolaRecovery: - SendLocalizedMessage(1112455); - break; // You cannot fly while recovering from a bola throw. - case BlockMountType.DismountRecovery: - SendLocalizedMessage(1112456); - break; // You cannot fly while recovering from a dismount maneuver. - } - } - else if (Hits < 25) // TODO confirm - { - SendLocalizedMessage(1112454); // You must heal before flying. - } - else - { - if (!Flying) - { - // No message? - if (Spell is FlySpell spell) - spell.Stop(); - - new FlySpell(this).Cast(); - } - else - { - Flying = false; - BuffInfo.RemoveBuff(this, BuffIcon.Fly); - } - } - } - - public static Direction GetDirection4(Point3D from, Point3D to) - { - int dx = from.X - to.X; - int dy = from.Y - to.Y; - - int rx = dx - dy; - int ry = dx + dy; - - Direction ret; - - if (rx >= 0 && ry >= 0) - ret = Direction.West; - else if (rx >= 0 && ry < 0) - ret = Direction.South; - else if (rx < 0 && ry < 0) - ret = Direction.East; - else - ret = Direction.North; - - return ret; - } - - public override bool OnDroppedItemToWorld(Item item, Point3D location) - { - if (!base.OnDroppedItemToWorld(item, location)) - return false; - - if (Core.AOS) - { - IPooledEnumerable mobiles = Map.GetMobilesInRange(location, 0); - - bool found = mobiles.Any(m => - m.Z >= location.Z && m.Z < location.Z + 16 && (!m.Hidden || m.AccessLevel == AccessLevel.Player)); - - mobiles.Free(); - - if (found) - return false; - - mobiles.Free(); - } - - BounceInfo bi = item.GetBounce(); - - if (bi != null) - { - Type type = item.GetType(); - - if (type.IsDefined(typeof(FurnitureAttribute), true) || - type.IsDefined(typeof(DynamicFlipingAttribute), true)) - { - object[] objs = type.GetCustomAttributes(typeof(FlippableAttribute), true); - - if (objs.Length > 0) - if (objs[0] is FlippableAttribute fp) + get { - int[] itemIDs = fp.ItemIDs; + // BaseArmor ar; + var rating = 0.0; - Point3D oldWorldLoc = bi.WorldLoc; - Point3D newWorldLoc = location; + AddArmorRating(ref rating, NeckArmor); + AddArmorRating(ref rating, HandArmor); + AddArmorRating(ref rating, HeadArmor); + AddArmorRating(ref rating, ArmsArmor); + AddArmorRating(ref rating, LegsArmor); + AddArmorRating(ref rating, ChestArmor); + AddArmorRating(ref rating, ShieldArmor); - if (oldWorldLoc.X != newWorldLoc.X || oldWorldLoc.Y != newWorldLoc.Y) - { - Direction dir = GetDirection4(oldWorldLoc, newWorldLoc); - - if (itemIDs.Length == 2) - item.ItemID = dir switch - { - Direction.North => itemIDs[0], - Direction.South => itemIDs[0], - Direction.East => itemIDs[1], - Direction.West => itemIDs[1], - _ => item.ItemID - }; - else if (itemIDs.Length == 4) - item.ItemID = dir switch - { - Direction.South => itemIDs[0], - Direction.East => itemIDs[1], - Direction.North => itemIDs[2], - Direction.West => itemIDs[3], - _ => item.ItemID - }; - } + return VirtualArmor + VirtualArmorMod + rating; } } - } - return true; - } - - public override int GetPacketFlags() - { - int flags = base.GetPacketFlags(); - - if (m_IgnoreMobiles) - flags |= 0x10; - - return flags; - } - - public override int GetOldPacketFlags() - { - int flags = base.GetOldPacketFlags(); - - if (m_IgnoreMobiles) - flags |= 0x10; - - return flags; - } - - public bool GetFlag(PlayerFlag flag) => (Flags & flag) != 0; - - public void SetFlag(PlayerFlag flag, bool value) - { - if (value) - Flags |= flag; - else - Flags &= ~flag; - } - - public static void Initialize() - { - if (FastwalkPrevention) - PacketHandlers.RegisterThrottler(0x02, MovementThrottle_Callback); - - EventSink.Login += OnLogin; - EventSink.Logout += OnLogout; - EventSink.Connected += EventSink_Connected; - EventSink.Disconnected += EventSink_Disconnected; - - EventSink.TargetedSkillUse += TargetedSkillUse; - EventSink.EquipMacro += EquipMacro; - EventSink.UnequipMacro += UnequipMacro; - - if (Core.SE) Timer.DelayCall(CheckPets); - } - - private static void TargetedSkillUse(Mobile from, IEntity target, int skillId) - { - if (from == null || target == null) - return; - - from.TargetLocked = true; - - if (skillId == 35) - AnimalTaming.DisableMessage = true; - // AnimalTaming.DeferredTarget = false; - - if (from.UseSkill(skillId)) - from.Target?.Invoke(from, target); - - if (skillId == 35) - // AnimalTaming.DeferredTarget = true; - AnimalTaming.DisableMessage = false; - - from.TargetLocked = false; - } - - public static void EquipMacro(Mobile m, List list) - { - if (m is PlayerMobile pm && pm.Backpack != null && pm.Alive) - { - Container pack = pm.Backpack; - - foreach (var serial in list) + public SkillName[] AnimalFormRestrictedSkills { get; } = { - Item item = pack.Items.FirstOrDefault(i => i.Serial == serial); - if (item == null) continue; + SkillName.ArmsLore, SkillName.Begging, SkillName.Discordance, SkillName.Forensics, + SkillName.Inscribe, SkillName.ItemID, SkillName.Meditation, SkillName.Peacemaking, + SkillName.Provocation, SkillName.RemoveTrap, SkillName.SpiritSpeak, SkillName.Stealing, + SkillName.TasteID + }; - Item toMove = pm.FindItemOnLayer(item.Layer); - - if (toMove != null) - { - // pack.DropItem(toMove); - toMove.Internalize(); - - if (!pm.EquipItem(item)) - pm.EquipItem(toMove); - else - pack.DropItem(toMove); - } - else - pm.EquipItem(item); - } - } - } - - public static void UnequipMacro(Mobile m, List layers) - { - if (m is PlayerMobile pm && pm.Backpack != null && pm.Alive) - { - Container pack = pm.Backpack; - List eq = m.Items; - - for (var i = eq.Count - 1; i >= 0; i--) + public override double RacialSkillBonus { - var item = eq[i]; - if (layers.Contains(item.Layer)) - pack.TryDropItem(pm, item, false); - } - } - } - - private static void CheckPets() - { - foreach (Mobile m in World.Mobiles.Values) - if (m is PlayerMobile pm && - ((!pm.Mounted || pm.Mount is EtherealMount) && pm.AllFollowers.Count > pm.AutoStabled.Count || - pm.Mounted && pm.AllFollowers.Count > pm.AutoStabled.Count + 1)) - pm.AutoStablePets(); /* autostable checks summons, et al: no need here */ - } - - private static bool CheckBlock(MountBlock block) => block?.m_Timer.Running == true; - - public void SetMountBlock(BlockMountType type, TimeSpan duration, bool dismount) - { - if (dismount) - { - if (Mount != null) - Mount.Rider = null; - else if (AnimalForm.UnderTransformation(this)) - AnimalForm.RemoveContext(this, true); - } - - if (m_MountBlock?.m_Timer.Running != true || m_MountBlock.m_Timer.Next < DateTime.UtcNow + duration) m_MountBlock = new MountBlock(duration, type, this); - } - - public override void OnSkillInvalidated(Skill skill) - { - if (Core.AOS && skill.SkillName == SkillName.MagicResist) - UpdateResistances(); - } - - public override int GetMaxResistance(ResistanceType type) - { - if (AccessLevel > AccessLevel.Player) - return 100; - - int max = base.GetMaxResistance(type); - - if (type != ResistanceType.Physical && max > 60 && CurseSpell.UnderEffect(this)) - max = 60; - - if (Core.ML && Race == Race.Elf && type == ResistanceType.Energy) - max += 5; // Intended to go after the 60 max from curse - - return max; - } - - protected override void OnRaceChange(Race oldRace) - { - ValidateEquipment(); - UpdateResistances(); - } - - public override void OnNetStateChanged() - { - m_LastGlobalLight = -1; - m_LastPersonalLight = -1; - } - - public override void ComputeBaseLightLevels(out int global, out int personal) - { - global = LightCycle.ComputeLevelFor(this); - - bool racialNightSight = Core.ML && Race == Race.Elf; - - if (LightLevel < 21 && (AosAttributes.GetValue(this, AosAttribute.NightSight) > 0 || racialNightSight)) - personal = 21; - else - personal = LightLevel; - } - - public override void CheckLightLevels(bool forceResend) - { - NetState ns = NetState; - - if (ns == null) - return; - - ComputeLightLevels(out int global, out int personal); - - if (!forceResend) - forceResend = global != m_LastGlobalLight || personal != m_LastPersonalLight; - - if (!forceResend) - return; - - m_LastGlobalLight = global; - m_LastPersonalLight = personal; - - ns.Send(GlobalLightLevel.Instantiate(global)); - ns.Send(new PersonalLightLevel(Serial, personal)); - } - - public override int GetMinResistance(ResistanceType type) - { - int magicResist = (int)(Skills.MagicResist.Value * 10); - int min; - - if (magicResist >= 1000) - min = 40 + (magicResist - 1000) / 50; - else if (magicResist >= 400) - min = (magicResist - 400) / 15; - else - min = int.MinValue; - - return Math.Clamp(min, base.GetMinResistance(type), MaxPlayerResistance); - } - - public override void OnManaChange(int oldValue) - { - base.OnManaChange(oldValue); - if (ExecutesLightningStrike > 0) - if (Mana < ExecutesLightningStrike) - SpecialMove.ClearCurrentMove(this); - } - - private static void OnLogin(Mobile from) - { - CheckAtrophies(from); - - if (AccountHandler.LockdownLevel > AccessLevel.Player) - { - string notice; - - if (!(from.Account is Account acct) || !acct.HasAccess(from.NetState)) - { - if (from.AccessLevel == AccessLevel.Player) - notice = "The server is currently under lockdown. No players are allowed to log in at this time."; - else - notice = - "The server is currently under lockdown. You do not have sufficient access level to connect."; - - if (from.NetState != null) - Timer.DelayCall(TimeSpan.FromSeconds(1.0), from.NetState.Dispose); - } - else if (from.AccessLevel >= AccessLevel.Administrator) - { - notice = - "The server is currently under lockdown. As you are an administrator, you may change this from the [Admin gump."; - } - else - { - notice = "The server is currently under lockdown. You have sufficient access level to connect."; - } - - from.SendGump(new NoticeGump(1060637, 30720, notice, 0xFFC000, 300, 140)); - return; - } - - if (from is PlayerMobile mobile) - mobile.ClaimAutoStabledPets(); - } - - public void ValidateEquipment() - { - if (m_NoDeltaRecursion || Map == null || Map == Map.Internal) - return; - - if (Items == null) - return; - - m_NoDeltaRecursion = true; - Timer.DelayCall(ValidateEquipment_Sandbox); - } - - private void ValidateEquipment_Sandbox() - { - try - { - if (Map == null || Map == Map.Internal) - return; - - List items = Items; - - if (items == null) - return; - - bool moved = false; - - int str = Str; - int dex = Dex; - int intel = Int; - - int factionItemCount = 0; - - Mobile from = this; - - Ethic ethic = Ethic.Find(from); - - for (int i = items.Count - 1; i >= 0; --i) - { - if (i >= items.Count) - continue; - - Item item = items[i]; - - if ((item.SavedFlags & 0x100) != 0) - { - if (item.Hue != Ethic.Hero.Definition.PrimaryHue) + get { - item.SavedFlags &= ~0x100; - } - else if (ethic != Ethic.Hero) - { - from.AddToBackpack(item); - moved = true; - continue; - } - } - else if ((item.SavedFlags & 0x200) != 0) - { - if (item.Hue != Ethic.Evil.Definition.PrimaryHue) - { - item.SavedFlags &= ~0x200; - } - else if (ethic != Ethic.Evil) - { - from.AddToBackpack(item); - moved = true; - continue; - } - } + if (Core.ML && Race == Race.Human) + return 20.0; - if (item is BaseWeapon weapon) - { - bool drop = false; - - if (dex < weapon.DexRequirement) - drop = true; - else if (str < AOS.Scale(weapon.StrRequirement, 100 - weapon.GetLowerStatReq())) - drop = true; - else if (intel < weapon.IntRequirement) - drop = true; - else if (weapon.RequiredRace != null && weapon.RequiredRace != Race) - drop = true; - - if (drop) - { - from.SendLocalizedMessage(1062001, weapon.Name ?? $"#{weapon.LabelNumber}"); // You can no longer wield your ~1_WEAPON~ - from.AddToBackpack(weapon); - moved = true; - } - } - else if (item is BaseArmor armor) - { - bool drop = false; - - if (!armor.AllowMaleWearer && !from.Female && from.AccessLevel < AccessLevel.GameMaster) - { - drop = true; - } - else if (!armor.AllowFemaleWearer && from.Female && from.AccessLevel < AccessLevel.GameMaster) - { - drop = true; - } - else if (armor.RequiredRace != null && armor.RequiredRace != Race) - { - drop = true; - } - else - { - int strBonus = armor.ComputeStatBonus(StatType.Str), strReq = armor.ComputeStatReq(StatType.Str); - int dexBonus = armor.ComputeStatBonus(StatType.Dex), dexReq = armor.ComputeStatReq(StatType.Dex); - int intBonus = armor.ComputeStatBonus(StatType.Int), intReq = armor.ComputeStatReq(StatType.Int); - - if (dex < dexReq || dex + dexBonus < 1) - drop = true; - else if (str < strReq || str + strBonus < 1) - drop = true; - else if (intel < intReq || intel + intBonus < 1) - drop = true; - } - - if (drop) - { - string name = armor.Name ?? $"#{armor.LabelNumber}"; - - if (armor is BaseShield) - from.SendLocalizedMessage(1062003, name); // You can no longer equip your ~1_SHIELD~ - else - from.SendLocalizedMessage(1062002, name); // You can no longer wear your ~1_ARMOR~ - - from.AddToBackpack(armor); - moved = true; - } - } - else if (item is BaseClothing clothing) - { - bool drop = false; - - if (!clothing.AllowMaleWearer && !from.Female && from.AccessLevel < AccessLevel.GameMaster) - { - drop = true; - } - else if (!clothing.AllowFemaleWearer && from.Female && from.AccessLevel < AccessLevel.GameMaster) - { - drop = true; - } - else if (clothing.RequiredRace != null && clothing.RequiredRace != Race) - { - drop = true; - } - else - { - int strBonus = clothing.ComputeStatBonus(StatType.Str); - int strReq = clothing.ComputeStatReq(StatType.Str); - - if (str < strReq || str + strBonus < 1) - drop = true; - } - - if (drop) - { - from.SendLocalizedMessage(1062002, clothing.Name ?? $"#{clothing.LabelNumber}"); // You can no longer wear your ~1_ARMOR~ - - from.AddToBackpack(clothing); - moved = true; - } - } - - FactionItem factionItem = FactionItem.Find(item); - - if (factionItem != null) - { - bool drop = false; - - Faction ourFaction = Faction.Find(this); - - if (ourFaction == null || ourFaction != factionItem.Faction) - drop = true; - else if (++factionItemCount > FactionItem.GetMaxWearables(this)) - drop = true; - - if (drop) - { - from.AddToBackpack(item); - moved = true; - } - } - } - - if (moved) - from.SendLocalizedMessage(500647); // Some equipment has been moved to your backpack. - } - catch (Exception e) - { - Console.WriteLine(e); - } - finally - { - m_NoDeltaRecursion = false; - } - } - - public override void Delta(MobileDelta flag) - { - base.Delta(flag); - - if ((flag & MobileDelta.Stat) != 0) - ValidateEquipment(); - } - - private static void OnLogout(Mobile m) - { - (m as PlayerMobile)?.AutoStablePets(); - } - - private static void EventSink_Connected(Mobile m) - { - if (m is PlayerMobile pm) - { - pm.SessionStart = DateTime.UtcNow; - - pm.Quest?.StartTimer(); - - pm.BedrollLogout = false; - pm.LastOnline = DateTime.UtcNow; - } - - DisguiseTimers.StartTimer(m); - - Timer.DelayCall(SpecialMove.ClearAllMoves, m); - } - - private static void EventSink_Disconnected(Mobile from) - { - DesignContext context = DesignContext.Find(from); - - if (context != null) - { - /* Client disconnected - * - Remove design context - * - Eject all from house - * - Restore relocated entities - */ - - // Remove design context - DesignContext.Remove(from); - - // Eject all from house - from.RevealingAction(); - - foreach (Item item in context.Foundation.GetItems()) - item.Location = context.Foundation.BanLocation; - - foreach (Mobile mobile in context.Foundation.GetMobiles()) - mobile.Location = context.Foundation.BanLocation; - - // Restore relocated entities - context.Foundation.RestoreRelocatedEntities(); - } - - if (from is PlayerMobile pm) - { - pm.m_GameTime += DateTime.UtcNow - pm.SessionStart; - - pm.Quest?.StopTimer(); - - pm.SpeechLog = null; - pm.LastOnline = DateTime.UtcNow; - } - - DisguiseTimers.StopTimer(from); - } - - public override void RevealingAction() - { - if (DesignContext != null) - return; - - InvisibilitySpell.RemoveTimer(this); - - base.RevealingAction(); - - IsStealthing = false; // IsStealthing should be moved to Server.Mobiles - } - - public override void OnHiddenChanged() - { - base.OnHiddenChanged(); - - RemoveBuff(BuffIcon - .Invisibility); // Always remove, default to the hiding icon EXCEPT in the invis spell where it's explicitly set - - if (!Hidden) - RemoveBuff(BuffIcon.HidingAndOrStealth); - else // if (!InvisibilitySpell.HasTimer( this )) - BuffInfo.AddBuff(this, - new BuffInfo(BuffIcon.HidingAndOrStealth, 1075655)); // Hidden/Stealthing & You Are Hidden - } - - public override void OnSubItemAdded(Item item) - { - if (AccessLevel < AccessLevel.GameMaster && item.IsChildOf(Backpack)) - { - int maxWeight = WeightOverloading.GetMaxWeight(this); - int curWeight = BodyWeight + TotalWeight; - - if (curWeight > maxWeight) - SendLocalizedMessage(1019035, true, $" : {curWeight} / {maxWeight}"); - } - - base.OnSubItemAdded(item); - } - - public override bool CanBeHarmful(Mobile target, bool message, bool ignoreOurBlessedness) - { - if (DesignContext != null || target is PlayerMobile mobile && mobile.DesignContext != null) - return false; - - if (target is BaseCreature creature && creature.IsInvulnerable || target is PlayerVendor || target is TownCrier) - { - if (message) - { - if (target.Title == null) - SendMessage("{0} cannot be harmed.", target.Name); - else - SendMessage("{0} {1} cannot be harmed.", target.Name, target.Title); - } - - return false; - } - - return base.CanBeHarmful(target, message, ignoreOurBlessedness); - } - - public override bool CanBeBeneficial(Mobile target, bool message, bool allowDead) - { - if (DesignContext != null || target is PlayerMobile mobile && mobile.DesignContext != null) - return false; - - return base.CanBeBeneficial(target, message, allowDead); - } - - public override bool CheckContextMenuDisplay(IEntity target) => DesignContext == null; - - public override void OnItemAdded(Item item) - { - base.OnItemAdded(item); - - if (item is BaseArmor || item is BaseWeapon) - { - Hits = Hits; - Stam = Stam; - Mana = Mana; - } - - if (NetState != null) - CheckLightLevels(false); - } - - public override void OnItemRemoved(Item item) - { - base.OnItemRemoved(item); - - if (item is BaseArmor || item is BaseWeapon) - { - Hits = Hits; - Stam = Stam; - Mana = Mana; - } - - if (NetState != null) - CheckLightLevels(false); - } - - private void AddArmorRating(ref double rating, Item armor) - { - if (armor is BaseArmor ar && (!Core.AOS || ar.ArmorAttributes.MageArmor == 0)) - rating += ar.ArmorRatingScaled; - } - - public override bool Move(Direction d) - { - NetState ns = NetState; - - if (ns != null) - if (HasGump()) - { - if (Alive) - { - CloseGump(); - } - else - { - SendLocalizedMessage(500111); // You are frozen and cannot move. - return false; - } - } - - int speed = ComputeMovementSpeed(d); - - bool res; - - if (!Alive) - MovementImpl.IgnoreMovableImpassables = true; - - res = base.Move(d); - - MovementImpl.IgnoreMovableImpassables = false; - - if (!res) - return false; - - m_NextMovementTime += speed; - - return true; - } - - public override bool CheckMovement(Direction d, out int newZ) - { - DesignContext context = DesignContext; - - if (context == null) - return base.CheckMovement(d, out newZ); - - HouseFoundation foundation = context.Foundation; - - newZ = foundation.Z + HouseFoundation.GetLevelZ(context.Level, context.Foundation); - - int newX = X, newY = Y; - Movement.Movement.Offset(d, ref newX, ref newY); - - int startX = foundation.X + foundation.Components.Min.X + 1; - int startY = foundation.Y + foundation.Components.Min.Y + 1; - int endX = startX + foundation.Components.Width - 1; - int endY = startY + foundation.Components.Height - 2; - - return newX >= startX && newY >= startY && newX < endX && newY < endY && Map == foundation.Map; - } - - public override bool AllowItemUse(Item item) - { - if (DuelContext?.AllowItemUse(this, item) == false) - return false; - - return DesignContext.Check(this); - } - - public override bool AllowSkillUse(SkillName skill) - { - if (AnimalForm.UnderTransformation(this)) - for (int i = 0; i < AnimalFormRestrictedSkills.Length; i++) - if (AnimalFormRestrictedSkills[i] == skill) - { - SendLocalizedMessage(1070771); // You cannot use that skill in this form. - return false; - } - - if (DuelContext?.AllowSkillUse(this, skill) == false) - return false; - - return DesignContext.Check(this); - } - - public virtual void RecheckTownProtection() - { - m_NextProtectionCheck = 10; - - GuardedRegion reg = Region.GetRegion(); - bool isProtected = reg?.IsDisabled() == false; - - if (isProtected != m_LastProtectedMessage) - { - if (isProtected) - SendLocalizedMessage(500112); // You are now under the protection of the town guards. - else - SendLocalizedMessage(500113); // You have left the protection of the town guards. - - m_LastProtectedMessage = isProtected; - } - } - - public override void MoveToWorld(Point3D loc, Map map) - { - base.MoveToWorld(loc, map); - - RecheckTownProtection(); - } - - public override void SetLocation(Point3D loc, bool isTeleport) - { - if (!isTeleport && AccessLevel == AccessLevel.Player) - { - // moving, not teleporting - int zDrop = Location.Z - loc.Z; - - if (zDrop > 20) // we fell more than one story - Hits -= zDrop / 20 * 10 - 5; // deal some damage; does not kill, disrupt, etc - } - - base.SetLocation(loc, isTeleport); - - if (isTeleport || --m_NextProtectionCheck == 0) - RecheckTownProtection(); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (from == this) - { - Quest?.GetContextMenuEntries(list); - - if (Alive) - { - if (InsuranceEnabled) - { - if (Core.SA) - list.Add(new CallbackEntry(1114299, OpenItemInsuranceMenu)); // Open Item Insurance Menu - - list.Add(new CallbackEntry(6201, ToggleItemInsurance)); // Toggle Item Insurance - - if (!Core.SA) - { - if (AutoRenewInsurance) - list.Add(new CallbackEntry(6202, - CancelRenewInventoryInsurance)); // Cancel Renewing Inventory Insurance - else - list.Add(new CallbackEntry(6200, - AutoRenewInventoryInsurance)); // Auto Renew Inventory Insurance - } - } - - if (MLQuestSystem.Enabled) - list.Add(new CallbackEntry(6169, ToggleQuestItem)); // Toggle Quest Item - } - - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (house != null) - { - if (Alive && house.InternalizedVendors.Count > 0 && house.IsOwner(this)) - list.Add(new CallbackEntry(6204, GetVendor)); - - if (house.IsAosRules && !Region.IsPartOf()) // Dueling - list.Add(new CallbackEntry(6207, LeaveHouse)); - } - - if (JusticeProtectors.Count > 0) - list.Add(new CallbackEntry(6157, CancelProtection)); - - if (Alive) - list.Add(new CallbackEntry(6210, ToggleChampionTitleDisplay)); - - if (Core.HS) - { - NetState ns = from.NetState; - - if (ns?.ExtendedStatus == true) - list.Add(new CallbackEntry(RefuseTrades ? 1154112 : 1154113, - ToggleTrades)); // Allow Trades / Refuse Trades - } - } - else - { - if (Core.TOL && from.InRange(this, 2)) list.Add(new CallbackEntry(1077728, () => OpenTrade(from))); // Trade - - if (Alive && Core.Expansion >= Expansion.AOS) - { - Party theirParty = from.Party as Party; - Party ourParty = Party as Party; - - if (theirParty == null && ourParty == null) - { - list.Add(new AddToPartyEntry(from, this)); - } - else if (theirParty != null && theirParty.Leader == from) - { - if (ourParty == null) - list.Add(new AddToPartyEntry(from, this)); - else if (ourParty == theirParty) list.Add(new RemoveFromPartyEntry(from, this)); - } - } - - BaseHouse curhouse = BaseHouse.FindHouseAt(this); - - if (curhouse != null && Alive && Core.Expansion >= Expansion.AOS && curhouse.IsAosRules && curhouse.IsFriend(from)) - list.Add(new EjectPlayerEntry(from, this)); - } - } - - private void CancelProtection() - { - for (int i = 0; i < JusticeProtectors.Count; ++i) - { - Mobile prot = JusticeProtectors[i]; - - string args = $"{Name}\t{prot.Name}"; - - prot.SendLocalizedMessage(1049371, - args); // The protective relationship between ~1_PLAYER1~ and ~2_PLAYER2~ has been ended. - SendLocalizedMessage(1049371, - args); // The protective relationship between ~1_PLAYER1~ and ~2_PLAYER2~ has been ended. - } - - JusticeProtectors.Clear(); - } - - private void ToggleTrades() - { - RefuseTrades = !RefuseTrades; - } - - private void GetVendor() - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (CheckAlive() && house?.IsOwner(this) == true && house.InternalizedVendors.Count > 0) - { - CloseGump(); - SendGump(new ReclaimVendorGump(house)); - } - } - - private void LeaveHouse() - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - if (house != null) - Location = house.BanLocation; - } - - public override void DisruptiveAction() - { - if (Meditating) - RemoveBuff(BuffIcon.ActiveMeditation); - - base.DisruptiveAction(); - } - - public override void OnDoubleClick(Mobile from) - { - if (this == from && !Warmode) - { - IMount mount = Mount; - - if (mount != null && !DesignContext.Check(this)) - return; - } - - base.OnDoubleClick(from); - } - - public override void DisplayPaperdollTo(Mobile to) - { - if (DesignContext.Check(this)) - base.DisplayPaperdollTo(to); - } - - public override bool CheckEquip(Item item) - { - if (!base.CheckEquip(item)) - return false; - - if (DuelContext?.AllowItemEquip(this, item) == false) - return false; - - FactionItem factionItem = FactionItem.Find(item); - - if (factionItem != null) - { - Faction faction = Faction.Find(this); - - if (faction == null) - { - SendLocalizedMessage(1010371); // You cannot equip a faction item! - return false; - } - - if (faction != factionItem.Faction) - { - SendLocalizedMessage(1010372); // You cannot equip an opposing faction's item! - return false; - } - - int maxWearables = FactionItem.GetMaxWearables(this); - - for (int i = 0; i < Items.Count; ++i) - { - Item equipped = Items[i]; - - if (item != equipped && FactionItem.Find(equipped) != null) - if (--maxWearables == 0) - { - SendLocalizedMessage(1010373); // You do not have enough rank to equip more faction items! - return false; + return 0; } } - } - if (AccessLevel < AccessLevel.GameMaster && item.Layer != Layer.Mount && HasTrade) - { - BounceInfo bounce = item.GetBounce(); + public List EquipSnapshot { get; private set; } - if (bounce != null) + public SkillName Learning { get; set; } = (SkillName)(-1); + + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan SavagePaintExpiration { - if (bounce.Parent is Item parent) - { - if (parent == Backpack || parent.IsChildOf(Backpack)) - return true; - } - else if (bounce.Parent == this) - { - return true; - } - } - - SendLocalizedMessage( - 1004042); // You can only equip what you are already carrying while you have a trade pending. - return false; - } - - return true; - } - - public override bool CheckTrade(Mobile to, Item item, SecureTradeContainer cont, bool message, bool checkItems, - int plusItems, int plusWeight) - { - int msgNum = 0; - - if (cont == null) - { - if (to.Holding != null) - msgNum = 1062727; // You cannot trade with someone who is dragging something. - else if (HasTrade) - msgNum = 1062781; // You are already trading with someone else! - else if (to.HasTrade) - msgNum = 1062779; // That person is already involved in a trade - else if (to is PlayerMobile mobile && mobile.RefuseTrades) - msgNum = 1154111; // ~1_NAME~ is refusing all trades. - } - - if (msgNum == 0 && item != null) - { - if (cont != null) - { - plusItems += cont.TotalItems; - plusWeight += cont.TotalWeight; - } - - if (Backpack?.CheckHold(this, item, false, checkItems, plusItems, plusWeight) != true) - msgNum = 1004040; // You would not be able to hold this if the trade failed. - else if (to.Backpack?.CheckHold(to, item, false, checkItems, plusItems, plusWeight) != true) - msgNum = 1004039; // The recipient of this trade would not be able to carry this. - else - msgNum = CheckContentForTrade(item); - } - - if (msgNum != 0) - { - if (message) - { - if (msgNum == 1154111) - SendLocalizedMessage(msgNum, to.Name); - else - SendLocalizedMessage(msgNum); - } - - return false; - } - - return true; - } - - private static int CheckContentForTrade(Item item) - { - if (item is TrappableContainer container && container.TrapType != TrapType.None) - return 1004044; // You may not trade trapped items. - - if (StolenItem.IsStolen(item)) - return 1004043; // You may not trade recently stolen items. - - if (item is Container) - foreach (Item subItem in item.Items) - { - int msg = CheckContentForTrade(subItem); - - if (msg != 0) - return msg; - } - - return 0; - } - - public override bool CheckNonlocalDrop(Mobile from, Item item, Item target) - { - if (!base.CheckNonlocalDrop(from, item, target)) - return false; - - if (from.AccessLevel >= AccessLevel.GameMaster) - return true; - - Container pack = Backpack; - if (from == this && HasTrade && (target == pack || target.IsChildOf(pack))) - { - BounceInfo bounce = item.GetBounce(); - - if (bounce?.Parent is Item parent && (parent == pack || parent.IsChildOf(pack))) - return true; - - SendLocalizedMessage(1004041); // You can't do that while you have a trade pending. - return false; - } - - return true; - } - - protected override void OnLocationChange(Point3D oldLocation) - { - CheckLightLevels(false); - - DuelContext?.OnLocationChanged(this); - - DesignContext context = DesignContext; - - if (context == null || m_NoRecursion) - return; - - m_NoRecursion = true; - - HouseFoundation foundation = context.Foundation; - - int newX = X, newY = Y; - int newZ = foundation.Z + HouseFoundation.GetLevelZ(context.Level, context.Foundation); - - int startX = foundation.X + foundation.Components.Min.X + 1; - int startY = foundation.Y + foundation.Components.Min.Y + 1; - int endX = startX + foundation.Components.Width - 1; - int endY = startY + foundation.Components.Height - 2; - - if (newX >= startX && newY >= startY && newX < endX && newY < endY && Map == foundation.Map) - { - if (Z != newZ) - Location = new Point3D(X, Y, newZ); - - m_NoRecursion = false; - return; - } - - Location = new Point3D(foundation.X, foundation.Y, newZ); - Map = foundation.Map; - - m_NoRecursion = false; - } - - public override bool OnMoveOver(Mobile m) => - m is BaseCreature creature && !creature.Controlled - ? !Alive || !creature.Alive || IsDeadBondedPet || creature.IsDeadBondedPet || - Hidden && AccessLevel > AccessLevel.Player - : Region.IsPartOf() && m is PlayerMobile pm && - (pm.DuelContext == null || pm.DuelPlayer == null || !pm.DuelContext.Started || pm.DuelContext.Finished || - pm.DuelPlayer.Eliminated) || base.OnMoveOver(m); - - public override bool CheckShove(Mobile shoved) => - m_IgnoreMobiles || TransformationSpellHelper.UnderTransformation(shoved, typeof(WraithFormSpell)) || - base.CheckShove(shoved); - - protected override void OnMapChange(Map oldMap) - { - if (Map != Faction.Facet && oldMap == Faction.Facet || Map == Faction.Facet && oldMap != Faction.Facet) - InvalidateProperties(); - - DuelContext?.OnMapChanged(this); - - DesignContext context = DesignContext; - - if (context == null || m_NoRecursion) - return; - - m_NoRecursion = true; - - HouseFoundation foundation = context.Foundation; - - if (Map != foundation.Map) - Map = foundation.Map; - - m_NoRecursion = false; - } - - public override void OnBeneficialAction(Mobile target, bool isCriminal) - { - SentHonorContext?.OnSourceBeneficialAction(target); - - base.OnBeneficialAction(target, isCriminal); - } - - public override void OnDamage(int amount, Mobile from, bool willKill) - { - int disruptThreshold; - - if (!Core.AOS) - disruptThreshold = 0; - else if (from?.Player == true) - disruptThreshold = 18; - else - disruptThreshold = 25; - - if (amount > disruptThreshold) - { - BandageContext c = BandageContext.GetContext(this); - - c?.Slip(); - } - - if (Confidence.IsRegenerating(this)) - Confidence.StopRegenerating(this); - - WeightOverloading.FatigueOnDamage(this, amount); - - ReceivedHonorContext?.OnTargetDamaged(from, amount); - SentHonorContext?.OnSourceDamaged(from, amount); - - if (willKill && from is PlayerMobile mobile) - Timer.DelayCall(TimeSpan.FromSeconds(10), mobile.RecoverAmmo); - - base.OnDamage(amount, from, willKill); - } - - public override void Resurrect() - { - bool wasAlive = Alive; - - base.Resurrect(); - - if (Alive && !wasAlive) - { - Item deathRobe = new DeathRobe(); - - if (!EquipItem(deathRobe)) - deathRobe.Delete(); - } - } - - public override void OnWarmodeChanged() - { - if (!Warmode) - Timer.DelayCall(TimeSpan.FromSeconds(10), RecoverAmmo); - } - - private bool FindItems_Callback(Item item) => - !item.Deleted && (item.LootType == LootType.Blessed || item.Insured) && - Backpack != item.Parent; - - public override bool OnBeforeDeath() - { - NetState state = NetState; - - state?.CancelAllTrades(); - - DropHolding(); - - if (Core.AOS && Backpack?.Deleted == false) Backpack.FindItemsByType(FindItems_Callback).ForEach(item => Backpack.AddItem(item)); - - EquipSnapshot = new List(Items); - - m_NonAutoreinsuredItems = 0; - m_InsuranceAward = FindMostRecentDamager(false); - - if (m_InsuranceAward is BaseCreature creature) - { - Mobile master = creature.GetMaster(); - - if (master != null) - m_InsuranceAward = master; - } - - if (m_InsuranceAward != null && (!m_InsuranceAward.Player || m_InsuranceAward == this)) - m_InsuranceAward = null; - - if (m_InsuranceAward is PlayerMobile mobile) - mobile.m_InsuranceBonus = 0; - - ReceivedHonorContext?.OnTargetKilled(); - SentHonorContext?.OnSourceKilled(); - - RecoverAmmo(); - - return base.OnBeforeDeath(); - } - - private bool CheckInsuranceOnDeath(Item item) - { - if (!InsuranceEnabled || !item.Insured) - return false; - - if (DuelContext?.Registered == true && DuelContext.Started && - m_DuelPlayer?.Eliminated != true) - return true; - - if (AutoRenewInsurance) - { - int cost = GetInsuranceCost(item); - - if (m_InsuranceAward != null) - cost /= 2; - - if (Banker.Withdraw(this, cost)) - { - item.PaidInsurance = true; - SendLocalizedMessage(1060398, - cost.ToString()); // ~1_AMOUNT~ gold has been withdrawn from your bank box. - } - else - { - SendLocalizedMessage(1061079, "", 0x23); // You lack the funds to purchase the insurance - item.PaidInsurance = false; - item.Insured = false; - m_NonAutoreinsuredItems++; - } - } - else - { - item.PaidInsurance = false; - item.Insured = false; - } - - if (m_InsuranceAward != null && Banker.Deposit(m_InsuranceAward, 300) && m_InsuranceAward is PlayerMobile pm) - pm.m_InsuranceBonus += 300; - - return true; - } - - public override DeathMoveResult GetParentMoveResultFor(Item item) - { - // It seems all items are unmarked on death, even blessed/insured ones - if (item.QuestItem) - item.QuestItem = false; - - if (CheckInsuranceOnDeath(item)) - return DeathMoveResult.MoveToBackpack; - - DeathMoveResult res = base.GetParentMoveResultFor(item); - - if (res == DeathMoveResult.MoveToCorpse && item.Movable && Young) - res = DeathMoveResult.MoveToBackpack; - - return res; - } - - public override DeathMoveResult GetInventoryMoveResultFor(Item item) - { - // It seems all items are unmarked on death, even blessed/insured ones - if (item.QuestItem) - item.QuestItem = false; - - if (CheckInsuranceOnDeath(item)) - return DeathMoveResult.MoveToBackpack; - - DeathMoveResult res = base.GetInventoryMoveResultFor(item); - - if (res == DeathMoveResult.MoveToCorpse && item.Movable && Young) - res = DeathMoveResult.MoveToBackpack; - - return res; - } - - public override void OnDeath(Container c) - { - if (m_NonAutoreinsuredItems > 0) SendLocalizedMessage(1061115); - - base.OnDeath(c); - - EquipSnapshot = null; - - HueMod = -1; - NameMod = null; - SavagePaintExpiration = TimeSpan.Zero; - - SetHairMods(-1, -1); - - PolymorphSpell.StopTimer(this); - IncognitoSpell.StopTimer(this); - DisguiseTimers.RemoveTimer(this); - - EndAction(); - EndAction(); - - MeerMage.StopEffect(this, false); - - if (Flying) - { - Flying = false; - BuffInfo.RemoveBuff(this, BuffIcon.Fly); - } - - StolenItem.ReturnOnDeath(this, c); - - if (PermaFlags.Count > 0) - { - PermaFlags.Clear(); - - if (c is Corpse corpse) - corpse.Criminal = true; - - if (Stealing.ClassicMode) - Criminal = true; - } - - if (Kills >= 5 && DateTime.UtcNow >= m_NextJustAward) - { - Mobile m = FindMostRecentDamager(false); - - if (m is BaseCreature bc) - m = bc.GetMaster(); - - if (m != this && m is PlayerMobile) - { - bool gainedPath = false; - - int pointsToGain = 0; - - pointsToGain += (int)Math.Sqrt(GameTime.TotalSeconds * 4); - pointsToGain *= 5; - pointsToGain += (int)Math.Pow(Skills.Total / 250.0, 2); - - if (VirtueHelper.Award(m, VirtueName.Justice, pointsToGain, ref gainedPath)) - { - if (gainedPath) - m.SendLocalizedMessage(1049367); // You have gained a path in Justice! - else - m.SendLocalizedMessage(1049363); // You have gained in Justice. - - m.FixedParticles(0x375A, 9, 20, 5027, EffectLayer.Waist); - m.PlaySound(0x1F7); - - m_NextJustAward = DateTime.UtcNow + TimeSpan.FromMinutes(pointsToGain / 3.0); - } - } - } - - if (m_InsuranceAward is PlayerMobile pm) - if (pm.m_InsuranceBonus > 0) - pm.SendLocalizedMessage(1060397, - pm.m_InsuranceBonus.ToString()); // ~1_AMOUNT~ gold has been deposited into your bank box. - - Mobile killer = FindMostRecentDamager(true); - - if (killer is BaseCreature bcKiller) - { - Mobile master = bcKiller.GetMaster(); - if (master != null) - killer = master; - } - - if (Young && DuelContext == null) - if (YoungDeathTeleport()) - Timer.DelayCall(TimeSpan.FromSeconds(2.5), SendYoungDeathNotice); - - if (DuelContext?.Registered != true || !DuelContext.Started || m_DuelPlayer?.Eliminated != false) - Faction.HandleDeath(this, killer); - - Guilds.Guild.HandleDeath(this, killer); - - MLQuestSystem.HandleDeath(this); - - DuelContext?.OnDeath(this, c); - - if (m_BuffTable != null) - { - List list = new List(); - - foreach (BuffInfo buff in m_BuffTable.Values) - if (!buff.RetainThroughDeath) - list.Add(buff); - - for (int i = 0; i < list.Count; i++) - RemoveBuff(list[i]); - } - } - - public override bool MutateSpeech(List hears, ref string text, ref object context) - { - if (Alive) - return false; - - if (Core.ML && Skills.SpiritSpeak.Value >= 100.0) - return false; - - if (Core.AOS) - for (int i = 0; i < hears.Count; ++i) - { - Mobile m = hears[i]; - - if (m != this && m.Skills.SpiritSpeak.Value >= 100.0) - return false; - } - - return base.MutateSpeech(hears, ref text, ref context); - } - - public override void DoSpeech(string text, int[] keywords, MessageType type, int hue) - { - if (Guilds.Guild.NewGuildSystem && (type == MessageType.Guild || type == MessageType.Alliance)) - { - if (!(Guild is Guild g)) - { - SendLocalizedMessage(1063142); // You are not in a guild! - } - else if (type == MessageType.Alliance) - { - if (g.Alliance?.IsMember(g) == true) - { - // g.Alliance.AllianceTextMessage( hue, "[Alliance][{0}]: {1}", this.Name, text ); - g.Alliance.AllianceChat(this, text); - SendToStaffMessage(this, "[Alliance]: {0}", text); - - AllianceMessageHue = hue; - } - else - { - SendLocalizedMessage(1071020); // You are not in an alliance! - } - } - else // Type == MessageType.Guild - { - GuildMessageHue = hue; - - g.GuildChat(this, text); - SendToStaffMessage(this, "[Guild]: {0}", text); - } - } - else - { - base.DoSpeech(text, keywords, type, hue); - } - } - - private static void SendToStaffMessage(Mobile from, string text) - { - Packet p = null; - - foreach (NetState ns in from.GetClientsInRange(8)) - { - Mobile mob = ns.Mobile; - - if (mob?.AccessLevel >= AccessLevel.GameMaster && mob.AccessLevel > from.AccessLevel) - { - p ??= Packet.Acquire(new UnicodeMessage(from.Serial, from.Body, MessageType.Regular, from.SpeechHue, 3, from.Language, from.Name, text)); - - ns.Send(p); - } - } - - Packet.Release(p); - } - - private static void SendToStaffMessage(Mobile from, string format, params object[] args) - { - SendToStaffMessage(from, string.Format(format, args)); - } - - public override void Damage(int amount, Mobile from) - { - if (EvilOmenSpell.TryEndEffect(this)) - amount = (int)(amount * 1.25); - - Mobile oath = BloodOathSpell.GetBloodOath(from); - - /* Per EA's UO Herald Pub48 (ML): - * ((resist spellsx10)/20 + 10=percentage of damage resisted) - */ - - if (oath == this) - { - amount = (int)(amount * 1.1); - - if (amount > 35 && from is PlayerMobile) /* capped @ 35, seems no expansion */ amount = 35; - - if (Core.ML) - from.Damage((int)(amount * (1 - (from.Skills.MagicResist.Value * .5 + 10) / 100)), this); - else - from.Damage(amount, this); - } - - if (from != null && Talisman is BaseTalisman talisman) - if (talisman.Protection != null && talisman.Protection.Type != null) - { - Type type = talisman.Protection.Type; - - if (type.IsInstanceOfType(from)) - amount = (int)(amount * (1 - (double)talisman.Protection.Amount / 100)); - } - - base.Damage(amount, from); - } - - public override bool IsHarmfulCriminal(Mobile target) - { - if (Stealing.ClassicMode && target is PlayerMobile mobile && mobile.PermaFlags.Count > 0) - { - if (Notoriety.Compute(this, mobile) == Notoriety.Innocent) - mobile.Delta(MobileDelta.Noto); - - return false; - } - - BaseCreature bc = target as BaseCreature; - - if (bc?.InitialInnocent == true && !bc.Controlled) - return false; - - if (Core.ML && bc?.Controlled == true && this == bc.ControlMaster) - return false; - - return base.IsHarmfulCriminal(target); - } - - public bool AntiMacroCheck(Skill skill, object obj) - { - if (obj == null || m_AntiMacroTable == null || AccessLevel != AccessLevel.Player) - return true; - - if (!m_AntiMacroTable.TryGetValue(skill, out Dictionary tbl)) - m_AntiMacroTable[skill] = tbl = new Dictionary(); - - if (tbl.TryGetValue(obj, out CountAndTimeStamp count)) - { - if (count.TimeStamp + SkillCheck.AntiMacroExpire <= DateTime.UtcNow) - { - count.Count = 1; - return true; - } - - ++count.Count; - return count.Count <= SkillCheck.Allowance; - } - - tbl[obj] = count = new CountAndTimeStamp(); - count.Count = 1; - - return true; - } - - private void RevertHair() - { - SetHairMods(-1, -1); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - switch (version) - { - case 29: - { - if (reader.ReadBool()) + get { - m_StuckMenuUses = new DateTime[reader.ReadInt()]; + var ts = m_SavagePaintExpiration - DateTime.UtcNow; - for (int i = 0; i < m_StuckMenuUses.Length; ++i) m_StuckMenuUses[i] = reader.ReadDateTime(); + if (ts < TimeSpan.Zero) + ts = TimeSpan.Zero; + + return ts; } - else + set => m_SavagePaintExpiration = DateTime.UtcNow + value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan NextSmithBulkOrder + { + get { - m_StuckMenuUses = null; + var ts = m_NextSmithBulkOrder - DateTime.UtcNow; + + if (ts < TimeSpan.Zero) + ts = TimeSpan.Zero; + + return ts; } - - goto case 28; - } - case 28: - { - PeacedUntil = reader.ReadDateTime(); - - goto case 27; - } - case 27: - { - AnkhNextUse = reader.ReadDateTime(); - - goto case 26; - } - case 26: - { - AutoStabled = reader.ReadStrongMobileList(); - - goto case 25; - } - case 25: - { - int recipeCount = reader.ReadInt(); - - if (recipeCount > 0) + set { - m_AcquiredRecipes = new Dictionary(); - - for (int i = 0; i < recipeCount; i++) - { - int r = reader.ReadInt(); - if (reader.ReadBool()) // Don't add in recipes which we haven't gotten or have been removed - m_AcquiredRecipes.Add(r, true); - } + try + { + m_NextSmithBulkOrder = DateTime.UtcNow + value; + } + catch + { + // ignored + } } + } - goto case 24; - } - case 24: - { - LastHonorLoss = reader.ReadDeltaTime(); - goto case 23; - } - case 23: - { - ChampionTitles = new ChampionTitleInfo(reader); - goto case 22; - } - case 22: - { - LastValorLoss = reader.ReadDateTime(); - goto case 21; - } - case 21: - { - ToTItemsTurnedIn = reader.ReadEncodedInt(); - ToTTotalMonsterFame = reader.ReadInt(); - goto case 20; - } - case 20: - { - AllianceMessageHue = reader.ReadEncodedInt(); - GuildMessageHue = reader.ReadEncodedInt(); - - goto case 19; - } - case 19: - { - int rank = reader.ReadEncodedInt(); - int maxRank = RankDefinition.Ranks.Length - 1; - if (rank > maxRank) - rank = maxRank; - - m_GuildRank = RankDefinition.Ranks[rank]; - LastOnline = reader.ReadDateTime(); - goto case 18; - } - case 18: - { - SolenFriendship = (SolenFriendship)reader.ReadEncodedInt(); - - goto case 17; - } - case 17: // changed how DoneQuests is serialized - case 16: - { - Quest = QuestSerializer.DeserializeQuest(reader); - - if (Quest != null) - Quest.From = this; - - int count = reader.ReadEncodedInt(); - - if (count > 0) + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan NextTailorBulkOrder + { + get { - DoneQuests = new List(); + var ts = m_NextTailorBulkOrder - DateTime.UtcNow; - for (int i = 0; i < count; ++i) - { - Type questType = QuestSerializer.ReadType(QuestSystem.QuestTypes, reader); - DateTime restartTime; + if (ts < TimeSpan.Zero) + ts = TimeSpan.Zero; - if (version < 17) - restartTime = DateTime.MaxValue; + return ts; + } + set + { + try + { + m_NextTailorBulkOrder = DateTime.UtcNow + value; + } + catch + { + // ignored + } + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime LastEscortTime { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime LastPetBallTime { get; set; } + + public List VisibilityList { get; } + + public List PermaFlags { get; private set; } + + public override int Luck => AosAttributes.GetValue(this, AosAttribute.Luck); + + public BOBFilter BOBFilter { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime SessionStart { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan GameTime + { + get + { + if (NetState != null) + return m_GameTime + (DateTime.UtcNow - SessionStart); + return m_GameTime; + } + } + + public override bool NewGuildDisplay => Guilds.Guild.NewGuildSystem; + + public bool BedrollLogout { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public override bool Paralyzed + { + get => base.Paralyzed; + set + { + base.Paralyzed = value; + + if (value) + AddBuff(new BuffInfo(BuffIcon.Paralyze, 1075827)); // Paralyze/You are frozen and can not move else - restartTime = reader.ReadDateTime(); + RemoveBuff(BuffIcon.Paralyze); + } + } - DoneQuests.Add(new QuestRestartInfo(questType, restartTime)); - } + [CommandProperty(AccessLevel.GameMaster)] + public Player EthicPlayer { get; set; } + + public PlayerState FactionPlayerState { get; set; } + + public List RecentlyReported { get; set; } + + public List AutoStabled { get; private set; } + + public bool NinjaWepCooldown { get; set; } + + public List AllFollowers => m_AllFollowers ?? (m_AllFollowers = new List()); + + public RankDefinition GuildRank + { + get => AccessLevel >= AccessLevel.GameMaster ? RankDefinition.Leader : m_GuildRank; + set => m_GuildRank = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public int GuildMessageHue { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int AllianceMessageHue { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int Profession { get; set; } + + public int StepsTaken { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsStealthing // IsStealthing should be moved to Server.Mobiles + { + get; + set; + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IgnoreMobiles // IgnoreMobiles should be moved to Server.Mobiles + { + get => m_IgnoreMobiles; + set + { + if (m_IgnoreMobiles != value) + { + m_IgnoreMobiles = value; + Delta(MobileDelta.Flags); + } + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public NpcGuild NpcGuild { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime NpcGuildJoinTime { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime NextBODTurnInTime { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime LastOnline { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public long LastMoved => LastMoveTime; + + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan NpcGuildGameTime { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int ToTItemsTurnedIn { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int ToTTotalMonsterFame { get; set; } + + public int ExecutesLightningStrike { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int ToothAche + { + get => CandyCane.GetToothAche(this); + set => CandyCane.SetToothAche(this, value); + } + + public PlayerFlag Flags { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool PagingSquelched + { + get => GetFlag(PlayerFlag.PagingSquelched); + set => SetFlag(PlayerFlag.PagingSquelched, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Glassblowing + { + get => GetFlag(PlayerFlag.Glassblowing); + set => SetFlag(PlayerFlag.Glassblowing, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Masonry + { + get => GetFlag(PlayerFlag.Masonry); + set => SetFlag(PlayerFlag.Masonry, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool SandMining + { + get => GetFlag(PlayerFlag.SandMining); + set => SetFlag(PlayerFlag.SandMining, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool StoneMining + { + get => GetFlag(PlayerFlag.StoneMining); + set => SetFlag(PlayerFlag.StoneMining, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool ToggleMiningStone + { + get => GetFlag(PlayerFlag.ToggleMiningStone); + set => SetFlag(PlayerFlag.ToggleMiningStone, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool KarmaLocked + { + get => GetFlag(PlayerFlag.KarmaLocked); + set => SetFlag(PlayerFlag.KarmaLocked, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool AutoRenewInsurance + { + get => GetFlag(PlayerFlag.AutoRenewInsurance); + set => SetFlag(PlayerFlag.AutoRenewInsurance, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool UseOwnFilter + { + get => GetFlag(PlayerFlag.UseOwnFilter); + set => SetFlag(PlayerFlag.UseOwnFilter, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool PublicMyRunUO + { + get => GetFlag(PlayerFlag.PublicMyRunUO); + set => SetFlag(PlayerFlag.PublicMyRunUO, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool AcceptGuildInvites + { + get => GetFlag(PlayerFlag.AcceptGuildInvites); + set => SetFlag(PlayerFlag.AcceptGuildInvites, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool HasStatReward + { + get => GetFlag(PlayerFlag.HasStatReward); + set => SetFlag(PlayerFlag.HasStatReward, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public bool RefuseTrades + { + get => GetFlag(PlayerFlag.RefuseTrades); + set => SetFlag(PlayerFlag.RefuseTrades, value); + } + + public Dictionary RecoverableAmmo { get; } = new Dictionary(); + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime AcceleratedStart { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public SkillName AcceleratedSkill { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public override int HitsMax + { + get + { + int strBase; + var strOffs = GetStatOffset(StatType.Str); + + if (Core.AOS) + { + strBase = Str; // this.Str already includes GetStatOffset/str + strOffs = AosAttributes.GetValue(this, AosAttribute.BonusHits); + + if (Core.ML && strOffs > 25 && AccessLevel <= AccessLevel.Player) + strOffs = 25; + + if (AnimalForm.UnderTransformation(this, typeof(BakeKitsune)) || + AnimalForm.UnderTransformation(this, typeof(GreyWolf))) + strOffs += 20; + } + else + { + strBase = RawStr; + } + + return strBase / 2 + 50 + strOffs; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public override int StamMax => base.StamMax + AosAttributes.GetValue(this, AosAttribute.BonusStam); + + [CommandProperty(AccessLevel.GameMaster)] + public override int ManaMax => base.ManaMax + AosAttributes.GetValue(this, AosAttribute.BonusMana) + + (Core.ML && Race == Race.Elf ? 20 : 0); + + [CommandProperty(AccessLevel.GameMaster)] + public override int Str + { + get + { + if (Core.ML && AccessLevel == AccessLevel.Player) + return Math.Min(base.Str, 150); + + return base.Str; + } + set => base.Str = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public override int Int + { + get + { + if (Core.ML && AccessLevel == AccessLevel.Player) + return Math.Min(base.Int, 150); + + return base.Int; + } + set => base.Int = value; + } + + [CommandProperty(AccessLevel.GameMaster)] + public override int Dex + { + get + { + if (Core.ML && AccessLevel == AccessLevel.Player) + return Math.Min(base.Dex, 150); + + return base.Dex; + } + set => base.Dex = value; + } + + public DuelContext DuelContext { get; private set; } + + public DuelPlayer DuelPlayer + { + get => m_DuelPlayer; + set + { + var wasInTourney = DuelContext?.Finished == false && DuelContext.m_Tournament != null; + + m_DuelPlayer = value; + + DuelContext = m_DuelPlayer?.Participant.Context; + + var isInTourney = DuelContext?.Finished == false && DuelContext.m_Tournament != null; + + if (wasInTourney != isInTourney) + SendEverything(); + } + } + + public QuestSystem Quest { get; set; } + + public List DoneQuests { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public SolenFriendship SolenFriendship { get; set; } + + public bool ChangedMyRunUO { get; set; } + + public virtual bool UsesFastwalkPrevention => AccessLevel < AccessLevel.Counselor; + + public Type EnemyOfOneType + { + get => m_EnemyOfOneType; + set + { + var oldType = m_EnemyOfOneType; + var newType = value; + + if (oldType == newType) + return; + + m_EnemyOfOneType = value; + + DeltaEnemies(oldType, newType); + } + } + + public bool WaitingForEnemy { get; set; } + + public DateTime LastSacrificeGain { get; set; } + + public DateTime LastSacrificeLoss { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int AvailableResurrects { get; set; } + + public DateTime LastJusticeLoss { get; set; } + + public List JusticeProtectors { get; set; } + + public DateTime LastCompassionLoss { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime NextCompassionDay { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int CompassionGains { get; set; } + + public DateTime LastValorLoss { get; set; } + + public DateTime LastHonorLoss { get; set; } + + public DateTime LastHonorUse { get; set; } + + public bool HonorActive { get; set; } + + public HonorContext SentHonorContext { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Young + { + get => GetFlag(PlayerFlag.Young); + set + { + SetFlag(PlayerFlag.Young, value); + InvalidateProperties(); + } + } + + public SpeechLog SpeechLog { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool DisplayChampionTitle + { + get => GetFlag(PlayerFlag.DisplayChampionTitle); + set => SetFlag(PlayerFlag.DisplayChampionTitle, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public ChampionTitleInfo ChampionTitles { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int KnownRecipes => m_AcquiredRecipes?.Count ?? 0; + + public HonorContext ReceivedHonorContext { get; set; } + + public override void ToggleFlying() + { + if (Race != Race.Gargoyle) return; + + if (Flying) + { + Freeze(TimeSpan.FromSeconds(1)); + Animate(61, 10, 1, true, false, 0); + Flying = false; + BuffInfo.RemoveBuff(this, BuffIcon.Fly); + SendMessage("You have landed."); + + BaseMount.Dismount(this); + return; } - Profession = reader.ReadEncodedInt(); - goto case 15; - } - case 15: - { - LastCompassionLoss = reader.ReadDeltaTime(); - goto case 14; - } - case 14: - { - CompassionGains = reader.ReadEncodedInt(); + var type = MountBlockReason; + + if (!Alive) + { + SendLocalizedMessage(1113082); // You may not fly while dead. + } + else if (IsBodyMod && !(BodyMod == 666 || BodyMod == 667)) + { + SendLocalizedMessage(1112453); // You can't fly in your current form! + } + else if (type != BlockMountType.None) + { + switch (type) + { + case BlockMountType.Dazed: + SendLocalizedMessage(1112457); + break; // You are still too dazed to fly. + case BlockMountType.BolaRecovery: + SendLocalizedMessage(1112455); + break; // You cannot fly while recovering from a bola throw. + case BlockMountType.DismountRecovery: + SendLocalizedMessage(1112456); + break; // You cannot fly while recovering from a dismount maneuver. + } + } + else if (Hits < 25) // TODO confirm + { + SendLocalizedMessage(1112454); // You must heal before flying. + } + else + { + if (!Flying) + { + // No message? + if (Spell is FlySpell spell) + spell.Stop(); + + new FlySpell(this).Cast(); + } + else + { + Flying = false; + BuffInfo.RemoveBuff(this, BuffIcon.Fly); + } + } + } + + public static Direction GetDirection4(Point3D from, Point3D to) + { + var dx = from.X - to.X; + var dy = from.Y - to.Y; + + var rx = dx - dy; + var ry = dx + dy; + + Direction ret; + + if (rx >= 0 && ry >= 0) + ret = Direction.West; + else if (rx >= 0 && ry < 0) + ret = Direction.South; + else if (rx < 0 && ry < 0) + ret = Direction.East; + else + ret = Direction.North; + + return ret; + } + + public override bool OnDroppedItemToWorld(Item item, Point3D location) + { + if (!base.OnDroppedItemToWorld(item, location)) + return false; + + if (Core.AOS) + { + var mobiles = Map.GetMobilesInRange(location, 0); + + var found = mobiles.Any( + m => + m.Z >= location.Z && m.Z < location.Z + 16 && (!m.Hidden || m.AccessLevel == AccessLevel.Player) + ); + + mobiles.Free(); + + if (found) + return false; + + mobiles.Free(); + } + + var bi = item.GetBounce(); + + if (bi != null) + { + var type = item.GetType(); + + if (type.IsDefined(typeof(FurnitureAttribute), true) || + type.IsDefined(typeof(DynamicFlipingAttribute), true)) + { + var objs = type.GetCustomAttributes(typeof(FlippableAttribute), true); + + if (objs.Length > 0) + if (objs[0] is FlippableAttribute fp) + { + var itemIDs = fp.ItemIDs; + + var oldWorldLoc = bi.WorldLoc; + var newWorldLoc = location; + + if (oldWorldLoc.X != newWorldLoc.X || oldWorldLoc.Y != newWorldLoc.Y) + { + var dir = GetDirection4(oldWorldLoc, newWorldLoc); + + if (itemIDs.Length == 2) + item.ItemID = dir switch + { + Direction.North => itemIDs[0], + Direction.South => itemIDs[0], + Direction.East => itemIDs[1], + Direction.West => itemIDs[1], + _ => item.ItemID + }; + else if (itemIDs.Length == 4) + item.ItemID = dir switch + { + Direction.South => itemIDs[0], + Direction.East => itemIDs[1], + Direction.North => itemIDs[2], + Direction.West => itemIDs[3], + _ => item.ItemID + }; + } + } + } + } + + return true; + } + + public override int GetPacketFlags() + { + var flags = base.GetPacketFlags(); + + if (m_IgnoreMobiles) + flags |= 0x10; + + return flags; + } + + public override int GetOldPacketFlags() + { + var flags = base.GetOldPacketFlags(); + + if (m_IgnoreMobiles) + flags |= 0x10; + + return flags; + } + + public bool GetFlag(PlayerFlag flag) => (Flags & flag) != 0; + + public void SetFlag(PlayerFlag flag, bool value) + { + if (value) + Flags |= flag; + else + Flags &= ~flag; + } + + public static void Initialize() + { + if (FastwalkPrevention) + PacketHandlers.RegisterThrottler(0x02, MovementThrottle_Callback); + + EventSink.Login += OnLogin; + EventSink.Logout += OnLogout; + EventSink.Connected += EventSink_Connected; + EventSink.Disconnected += EventSink_Disconnected; + + EventSink.TargetedSkillUse += TargetedSkillUse; + EventSink.EquipMacro += EquipMacro; + EventSink.UnequipMacro += UnequipMacro; + + if (Core.SE) Timer.DelayCall(CheckPets); + } + + private static void TargetedSkillUse(Mobile from, IEntity target, int skillId) + { + if (from == null || target == null) + return; + + from.TargetLocked = true; + + if (skillId == 35) + AnimalTaming.DisableMessage = true; + // AnimalTaming.DeferredTarget = false; + + if (from.UseSkill(skillId)) + from.Target?.Invoke(from, target); + + if (skillId == 35) + // AnimalTaming.DeferredTarget = true; + AnimalTaming.DisableMessage = false; + + from.TargetLocked = false; + } + + public static void EquipMacro(Mobile m, List list) + { + if (m is PlayerMobile pm && pm.Backpack != null && pm.Alive) + { + var pack = pm.Backpack; + + foreach (var serial in list) + { + var item = pack.Items.FirstOrDefault(i => i.Serial == serial); + if (item == null) continue; + + var toMove = pm.FindItemOnLayer(item.Layer); + + if (toMove != null) + { + // pack.DropItem(toMove); + toMove.Internalize(); + + if (!pm.EquipItem(item)) + pm.EquipItem(toMove); + else + pack.DropItem(toMove); + } + else + { + pm.EquipItem(item); + } + } + } + } + + public static void UnequipMacro(Mobile m, List layers) + { + if (m is PlayerMobile pm && pm.Backpack != null && pm.Alive) + { + var pack = pm.Backpack; + var eq = m.Items; + + for (var i = eq.Count - 1; i >= 0; i--) + { + var item = eq[i]; + if (layers.Contains(item.Layer)) + pack.TryDropItem(pm, item, false); + } + } + } + + private static void CheckPets() + { + foreach (var m in World.Mobiles.Values) + if (m is PlayerMobile pm && + ((!pm.Mounted || pm.Mount is EtherealMount) && pm.AllFollowers.Count > pm.AutoStabled.Count || + pm.Mounted && pm.AllFollowers.Count > pm.AutoStabled.Count + 1)) + pm.AutoStablePets(); /* autostable checks summons, et al: no need here */ + } + + private static bool CheckBlock(MountBlock block) => block?.m_Timer.Running == true; + + public void SetMountBlock(BlockMountType type, TimeSpan duration, bool dismount) + { + if (dismount) + { + if (Mount != null) + Mount.Rider = null; + else if (AnimalForm.UnderTransformation(this)) + AnimalForm.RemoveContext(this, true); + } + + if (m_MountBlock?.m_Timer.Running != true || m_MountBlock.m_Timer.Next < DateTime.UtcNow + duration) + m_MountBlock = new MountBlock(duration, type, this); + } + + public override void OnSkillInvalidated(Skill skill) + { + if (Core.AOS && skill.SkillName == SkillName.MagicResist) + UpdateResistances(); + } + + public override int GetMaxResistance(ResistanceType type) + { + if (AccessLevel > AccessLevel.Player) + return 100; + + var max = base.GetMaxResistance(type); + + if (type != ResistanceType.Physical && max > 60 && CurseSpell.UnderEffect(this)) + max = 60; + + if (Core.ML && Race == Race.Elf && type == ResistanceType.Energy) + max += 5; // Intended to go after the 60 max from curse + + return max; + } + + protected override void OnRaceChange(Race oldRace) + { + ValidateEquipment(); + UpdateResistances(); + } + + public override void OnNetStateChanged() + { + m_LastGlobalLight = -1; + m_LastPersonalLight = -1; + } + + public override void ComputeBaseLightLevels(out int global, out int personal) + { + global = LightCycle.ComputeLevelFor(this); + + var racialNightSight = Core.ML && Race == Race.Elf; + + if (LightLevel < 21 && (AosAttributes.GetValue(this, AosAttribute.NightSight) > 0 || racialNightSight)) + personal = 21; + else + personal = LightLevel; + } + + public override void CheckLightLevels(bool forceResend) + { + var ns = NetState; + + if (ns == null) + return; + + ComputeLightLevels(out var global, out var personal); + + if (!forceResend) + forceResend = global != m_LastGlobalLight || personal != m_LastPersonalLight; + + if (!forceResend) + return; + + m_LastGlobalLight = global; + m_LastPersonalLight = personal; + + ns.Send(GlobalLightLevel.Instantiate(global)); + ns.Send(new PersonalLightLevel(Serial, personal)); + } + + public override int GetMinResistance(ResistanceType type) + { + var magicResist = (int)(Skills.MagicResist.Value * 10); + int min; + + if (magicResist >= 1000) + min = 40 + (magicResist - 1000) / 50; + else if (magicResist >= 400) + min = (magicResist - 400) / 15; + else + min = int.MinValue; + + return Math.Clamp(min, base.GetMinResistance(type), MaxPlayerResistance); + } + + public override void OnManaChange(int oldValue) + { + base.OnManaChange(oldValue); + if (ExecutesLightningStrike > 0) + if (Mana < ExecutesLightningStrike) + SpecialMove.ClearCurrentMove(this); + } + + private static void OnLogin(Mobile from) + { + CheckAtrophies(from); + + if (AccountHandler.LockdownLevel > AccessLevel.Player) + { + string notice; + + if (!(from.Account is Account acct) || !acct.HasAccess(from.NetState)) + { + if (from.AccessLevel == AccessLevel.Player) + notice = "The server is currently under lockdown. No players are allowed to log in at this time."; + else + notice = + "The server is currently under lockdown. You do not have sufficient access level to connect."; + + if (from.NetState != null) + Timer.DelayCall(TimeSpan.FromSeconds(1.0), from.NetState.Dispose); + } + else if (from.AccessLevel >= AccessLevel.Administrator) + { + notice = + "The server is currently under lockdown. As you are an administrator, you may change this from the [Admin gump."; + } + else + { + notice = "The server is currently under lockdown. You have sufficient access level to connect."; + } + + from.SendGump(new NoticeGump(1060637, 30720, notice, 0xFFC000, 300, 140)); + return; + } + + if (from is PlayerMobile mobile) + mobile.ClaimAutoStabledPets(); + } + + public void ValidateEquipment() + { + if (m_NoDeltaRecursion || Map == null || Map == Map.Internal) + return; + + if (Items == null) + return; + + m_NoDeltaRecursion = true; + Timer.DelayCall(ValidateEquipment_Sandbox); + } + + private void ValidateEquipment_Sandbox() + { + try + { + if (Map == null || Map == Map.Internal) + return; + + var items = Items; + + if (items == null) + return; + + var moved = false; + + var str = Str; + var dex = Dex; + var intel = Int; + + var factionItemCount = 0; + + Mobile from = this; + + var ethic = Ethic.Find(from); + + for (var i = items.Count - 1; i >= 0; --i) + { + if (i >= items.Count) + continue; + + var item = items[i]; + + if ((item.SavedFlags & 0x100) != 0) + { + if (item.Hue != Ethic.Hero.Definition.PrimaryHue) + { + item.SavedFlags &= ~0x100; + } + else if (ethic != Ethic.Hero) + { + from.AddToBackpack(item); + moved = true; + continue; + } + } + else if ((item.SavedFlags & 0x200) != 0) + { + if (item.Hue != Ethic.Evil.Definition.PrimaryHue) + { + item.SavedFlags &= ~0x200; + } + else if (ethic != Ethic.Evil) + { + from.AddToBackpack(item); + moved = true; + continue; + } + } + + if (item is BaseWeapon weapon) + { + var drop = false; + + if (dex < weapon.DexRequirement) + drop = true; + else if (str < AOS.Scale(weapon.StrRequirement, 100 - weapon.GetLowerStatReq())) + drop = true; + else if (intel < weapon.IntRequirement) + drop = true; + else if (weapon.RequiredRace != null && weapon.RequiredRace != Race) + drop = true; + + if (drop) + { + from.SendLocalizedMessage( + 1062001, + weapon.Name ?? $"#{weapon.LabelNumber}" + ); // You can no longer wield your ~1_WEAPON~ + from.AddToBackpack(weapon); + moved = true; + } + } + else if (item is BaseArmor armor) + { + var drop = false; + + if (!armor.AllowMaleWearer && !from.Female && from.AccessLevel < AccessLevel.GameMaster) + { + drop = true; + } + else if (!armor.AllowFemaleWearer && from.Female && from.AccessLevel < AccessLevel.GameMaster) + { + drop = true; + } + else if (armor.RequiredRace != null && armor.RequiredRace != Race) + { + drop = true; + } + else + { + int strBonus = armor.ComputeStatBonus(StatType.Str), strReq = armor.ComputeStatReq(StatType.Str); + int dexBonus = armor.ComputeStatBonus(StatType.Dex), dexReq = armor.ComputeStatReq(StatType.Dex); + int intBonus = armor.ComputeStatBonus(StatType.Int), intReq = armor.ComputeStatReq(StatType.Int); + + if (dex < dexReq || dex + dexBonus < 1) + drop = true; + else if (str < strReq || str + strBonus < 1) + drop = true; + else if (intel < intReq || intel + intBonus < 1) + drop = true; + } + + if (drop) + { + var name = armor.Name ?? $"#{armor.LabelNumber}"; + + if (armor is BaseShield) + from.SendLocalizedMessage(1062003, name); // You can no longer equip your ~1_SHIELD~ + else + from.SendLocalizedMessage(1062002, name); // You can no longer wear your ~1_ARMOR~ + + from.AddToBackpack(armor); + moved = true; + } + } + else if (item is BaseClothing clothing) + { + var drop = false; + + if (!clothing.AllowMaleWearer && !from.Female && from.AccessLevel < AccessLevel.GameMaster) + { + drop = true; + } + else if (!clothing.AllowFemaleWearer && from.Female && from.AccessLevel < AccessLevel.GameMaster) + { + drop = true; + } + else if (clothing.RequiredRace != null && clothing.RequiredRace != Race) + { + drop = true; + } + else + { + var strBonus = clothing.ComputeStatBonus(StatType.Str); + var strReq = clothing.ComputeStatReq(StatType.Str); + + if (str < strReq || str + strBonus < 1) + drop = true; + } + + if (drop) + { + from.SendLocalizedMessage( + 1062002, + clothing.Name ?? $"#{clothing.LabelNumber}" + ); // You can no longer wear your ~1_ARMOR~ + + from.AddToBackpack(clothing); + moved = true; + } + } + + var factionItem = FactionItem.Find(item); + + if (factionItem != null) + { + var drop = false; + + var ourFaction = Faction.Find(this); + + if (ourFaction == null || ourFaction != factionItem.Faction) + drop = true; + else if (++factionItemCount > FactionItem.GetMaxWearables(this)) + drop = true; + + if (drop) + { + from.AddToBackpack(item); + moved = true; + } + } + } + + if (moved) + from.SendLocalizedMessage(500647); // Some equipment has been moved to your backpack. + } + catch (Exception e) + { + Console.WriteLine(e); + } + finally + { + m_NoDeltaRecursion = false; + } + } + + public override void Delta(MobileDelta flag) + { + base.Delta(flag); + + if ((flag & MobileDelta.Stat) != 0) + ValidateEquipment(); + } + + private static void OnLogout(Mobile m) + { + (m as PlayerMobile)?.AutoStablePets(); + } + + private static void EventSink_Connected(Mobile m) + { + if (m is PlayerMobile pm) + { + pm.SessionStart = DateTime.UtcNow; + + pm.Quest?.StartTimer(); + + pm.BedrollLogout = false; + pm.LastOnline = DateTime.UtcNow; + } + + DisguiseTimers.StartTimer(m); + + Timer.DelayCall(SpecialMove.ClearAllMoves, m); + } + + private static void EventSink_Disconnected(Mobile from) + { + var context = DesignContext.Find(from); + + if (context != null) + { + /* Client disconnected + * - Remove design context + * - Eject all from house + * - Restore relocated entities + */ + + // Remove design context + DesignContext.Remove(from); + + // Eject all from house + from.RevealingAction(); + + foreach (var item in context.Foundation.GetItems()) + item.Location = context.Foundation.BanLocation; + + foreach (var mobile in context.Foundation.GetMobiles()) + mobile.Location = context.Foundation.BanLocation; + + // Restore relocated entities + context.Foundation.RestoreRelocatedEntities(); + } + + if (from is PlayerMobile pm) + { + pm.m_GameTime += DateTime.UtcNow - pm.SessionStart; + + pm.Quest?.StopTimer(); + + pm.SpeechLog = null; + pm.LastOnline = DateTime.UtcNow; + } + + DisguiseTimers.StopTimer(from); + } + + public override void RevealingAction() + { + if (DesignContext != null) + return; + + InvisibilitySpell.RemoveTimer(this); + + base.RevealingAction(); + + IsStealthing = false; // IsStealthing should be moved to Server.Mobiles + } + + public override void OnHiddenChanged() + { + base.OnHiddenChanged(); + + RemoveBuff( + BuffIcon + .Invisibility + ); // Always remove, default to the hiding icon EXCEPT in the invis spell where it's explicitly set + + if (!Hidden) + RemoveBuff(BuffIcon.HidingAndOrStealth); + else // if (!InvisibilitySpell.HasTimer( this )) + BuffInfo.AddBuff( + this, + new BuffInfo(BuffIcon.HidingAndOrStealth, 1075655) + ); // Hidden/Stealthing & You Are Hidden + } + + public override void OnSubItemAdded(Item item) + { + if (AccessLevel < AccessLevel.GameMaster && item.IsChildOf(Backpack)) + { + var maxWeight = WeightOverloading.GetMaxWeight(this); + var curWeight = BodyWeight + TotalWeight; + + if (curWeight > maxWeight) + SendLocalizedMessage(1019035, true, $" : {curWeight} / {maxWeight}"); + } + + base.OnSubItemAdded(item); + } + + public override bool CanBeHarmful(Mobile target, bool message, bool ignoreOurBlessedness) + { + if (DesignContext != null || target is PlayerMobile mobile && mobile.DesignContext != null) + return false; + + if (target is BaseCreature creature && creature.IsInvulnerable || target is PlayerVendor || target is TownCrier) + { + if (message) + { + if (target.Title == null) + SendMessage("{0} cannot be harmed.", target.Name); + else + SendMessage("{0} {1} cannot be harmed.", target.Name, target.Title); + } + + return false; + } + + return base.CanBeHarmful(target, message, ignoreOurBlessedness); + } + + public override bool CanBeBeneficial(Mobile target, bool message, bool allowDead) + { + if (DesignContext != null || target is PlayerMobile mobile && mobile.DesignContext != null) + return false; + + return base.CanBeBeneficial(target, message, allowDead); + } + + public override bool CheckContextMenuDisplay(IEntity target) => DesignContext == null; + + public override void OnItemAdded(Item item) + { + base.OnItemAdded(item); + + if (item is BaseArmor || item is BaseWeapon) + { + Hits = Hits; + Stam = Stam; + Mana = Mana; + } + + if (NetState != null) + CheckLightLevels(false); + } + + public override void OnItemRemoved(Item item) + { + base.OnItemRemoved(item); + + if (item is BaseArmor || item is BaseWeapon) + { + Hits = Hits; + Stam = Stam; + Mana = Mana; + } + + if (NetState != null) + CheckLightLevels(false); + } + + private void AddArmorRating(ref double rating, Item armor) + { + if (armor is BaseArmor ar && (!Core.AOS || ar.ArmorAttributes.MageArmor == 0)) + rating += ar.ArmorRatingScaled; + } + + public override bool Move(Direction d) + { + var ns = NetState; + + if (ns != null) + if (HasGump()) + { + if (Alive) + { + CloseGump(); + } + else + { + SendLocalizedMessage(500111); // You are frozen and cannot move. + return false; + } + } + + var speed = ComputeMovementSpeed(d); + + bool res; + + if (!Alive) + MovementImpl.IgnoreMovableImpassables = true; + + res = base.Move(d); + + MovementImpl.IgnoreMovableImpassables = false; + + if (!res) + return false; + + m_NextMovementTime += speed; + + return true; + } + + public override bool CheckMovement(Direction d, out int newZ) + { + var context = DesignContext; + + if (context == null) + return base.CheckMovement(d, out newZ); + + var foundation = context.Foundation; + + newZ = foundation.Z + HouseFoundation.GetLevelZ(context.Level, context.Foundation); + + int newX = X, newY = Y; + Movement.Movement.Offset(d, ref newX, ref newY); + + var startX = foundation.X + foundation.Components.Min.X + 1; + var startY = foundation.Y + foundation.Components.Min.Y + 1; + var endX = startX + foundation.Components.Width - 1; + var endY = startY + foundation.Components.Height - 2; + + return newX >= startX && newY >= startY && newX < endX && newY < endY && Map == foundation.Map; + } + + public override bool AllowItemUse(Item item) + { + if (DuelContext?.AllowItemUse(this, item) == false) + return false; + + return DesignContext.Check(this); + } + + public override bool AllowSkillUse(SkillName skill) + { + if (AnimalForm.UnderTransformation(this)) + for (var i = 0; i < AnimalFormRestrictedSkills.Length; i++) + if (AnimalFormRestrictedSkills[i] == skill) + { + SendLocalizedMessage(1070771); // You cannot use that skill in this form. + return false; + } + + if (DuelContext?.AllowSkillUse(this, skill) == false) + return false; + + return DesignContext.Check(this); + } + + public virtual void RecheckTownProtection() + { + m_NextProtectionCheck = 10; + + var reg = Region.GetRegion(); + var isProtected = reg?.IsDisabled() == false; + + if (isProtected != m_LastProtectedMessage) + { + if (isProtected) + SendLocalizedMessage(500112); // You are now under the protection of the town guards. + else + SendLocalizedMessage(500113); // You have left the protection of the town guards. + + m_LastProtectedMessage = isProtected; + } + } + + public override void MoveToWorld(Point3D loc, Map map) + { + base.MoveToWorld(loc, map); + + RecheckTownProtection(); + } + + public override void SetLocation(Point3D loc, bool isTeleport) + { + if (!isTeleport && AccessLevel == AccessLevel.Player) + { + // moving, not teleporting + var zDrop = Location.Z - loc.Z; + + if (zDrop > 20) // we fell more than one story + Hits -= zDrop / 20 * 10 - 5; // deal some damage; does not kill, disrupt, etc + } + + base.SetLocation(loc, isTeleport); + + if (isTeleport || --m_NextProtectionCheck == 0) + RecheckTownProtection(); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (from == this) + { + Quest?.GetContextMenuEntries(list); + + if (Alive) + { + if (InsuranceEnabled) + { + if (Core.SA) + list.Add(new CallbackEntry(1114299, OpenItemInsuranceMenu)); // Open Item Insurance Menu + + list.Add(new CallbackEntry(6201, ToggleItemInsurance)); // Toggle Item Insurance + + if (!Core.SA) + { + if (AutoRenewInsurance) + list.Add( + new CallbackEntry( + 6202, + CancelRenewInventoryInsurance + ) + ); // Cancel Renewing Inventory Insurance + else + list.Add( + new CallbackEntry( + 6200, + AutoRenewInventoryInsurance + ) + ); // Auto Renew Inventory Insurance + } + } + + if (MLQuestSystem.Enabled) + list.Add(new CallbackEntry(6169, ToggleQuestItem)); // Toggle Quest Item + } + + var house = BaseHouse.FindHouseAt(this); + + if (house != null) + { + if (Alive && house.InternalizedVendors.Count > 0 && house.IsOwner(this)) + list.Add(new CallbackEntry(6204, GetVendor)); + + if (house.IsAosRules && !Region.IsPartOf()) // Dueling + list.Add(new CallbackEntry(6207, LeaveHouse)); + } + + if (JusticeProtectors.Count > 0) + list.Add(new CallbackEntry(6157, CancelProtection)); + + if (Alive) + list.Add(new CallbackEntry(6210, ToggleChampionTitleDisplay)); + + if (Core.HS) + { + var ns = from.NetState; + + if (ns?.ExtendedStatus == true) + list.Add( + new CallbackEntry( + RefuseTrades ? 1154112 : 1154113, + ToggleTrades + ) + ); // Allow Trades / Refuse Trades + } + } + else + { + if (Core.TOL && from.InRange(this, 2)) list.Add(new CallbackEntry(1077728, () => OpenTrade(from))); // Trade + + if (Alive && Core.Expansion >= Expansion.AOS) + { + var theirParty = from.Party as Party; + var ourParty = Party as Party; + + if (theirParty == null && ourParty == null) + { + list.Add(new AddToPartyEntry(from, this)); + } + else if (theirParty != null && theirParty.Leader == from) + { + if (ourParty == null) + list.Add(new AddToPartyEntry(from, this)); + else if (ourParty == theirParty) list.Add(new RemoveFromPartyEntry(from, this)); + } + } + + var curhouse = BaseHouse.FindHouseAt(this); + + if (curhouse != null && Alive && Core.Expansion >= Expansion.AOS && curhouse.IsAosRules && + curhouse.IsFriend(from)) + list.Add(new EjectPlayerEntry(from, this)); + } + } + + private void CancelProtection() + { + for (var i = 0; i < JusticeProtectors.Count; ++i) + { + var prot = JusticeProtectors[i]; + + var args = $"{Name}\t{prot.Name}"; + + prot.SendLocalizedMessage( + 1049371, + args + ); // The protective relationship between ~1_PLAYER1~ and ~2_PLAYER2~ has been ended. + SendLocalizedMessage( + 1049371, + args + ); // The protective relationship between ~1_PLAYER1~ and ~2_PLAYER2~ has been ended. + } + + JusticeProtectors.Clear(); + } + + private void ToggleTrades() + { + RefuseTrades = !RefuseTrades; + } + + private void GetVendor() + { + var house = BaseHouse.FindHouseAt(this); + + if (CheckAlive() && house?.IsOwner(this) == true && house.InternalizedVendors.Count > 0) + { + CloseGump(); + SendGump(new ReclaimVendorGump(house)); + } + } + + private void LeaveHouse() + { + var house = BaseHouse.FindHouseAt(this); + + if (house != null) + Location = house.BanLocation; + } + + public override void DisruptiveAction() + { + if (Meditating) + RemoveBuff(BuffIcon.ActiveMeditation); + + base.DisruptiveAction(); + } + + public override void OnDoubleClick(Mobile from) + { + if (this == from && !Warmode) + { + var mount = Mount; + + if (mount != null && !DesignContext.Check(this)) + return; + } + + base.OnDoubleClick(from); + } + + public override void DisplayPaperdollTo(Mobile to) + { + if (DesignContext.Check(this)) + base.DisplayPaperdollTo(to); + } + + public override bool CheckEquip(Item item) + { + if (!base.CheckEquip(item)) + return false; + + if (DuelContext?.AllowItemEquip(this, item) == false) + return false; + + var factionItem = FactionItem.Find(item); + + if (factionItem != null) + { + var faction = Faction.Find(this); + + if (faction == null) + { + SendLocalizedMessage(1010371); // You cannot equip a faction item! + return false; + } + + if (faction != factionItem.Faction) + { + SendLocalizedMessage(1010372); // You cannot equip an opposing faction's item! + return false; + } + + var maxWearables = FactionItem.GetMaxWearables(this); + + for (var i = 0; i < Items.Count; ++i) + { + var equipped = Items[i]; + + if (item != equipped && FactionItem.Find(equipped) != null) + if (--maxWearables == 0) + { + SendLocalizedMessage(1010373); // You do not have enough rank to equip more faction items! + return false; + } + } + } + + if (AccessLevel < AccessLevel.GameMaster && item.Layer != Layer.Mount && HasTrade) + { + var bounce = item.GetBounce(); + + if (bounce != null) + { + if (bounce.Parent is Item parent) + { + if (parent == Backpack || parent.IsChildOf(Backpack)) + return true; + } + else if (bounce.Parent == this) + { + return true; + } + } + + SendLocalizedMessage( + 1004042 + ); // You can only equip what you are already carrying while you have a trade pending. + return false; + } + + return true; + } + + public override bool CheckTrade( + Mobile to, Item item, SecureTradeContainer cont, bool message, bool checkItems, + int plusItems, int plusWeight + ) + { + var msgNum = 0; + + if (cont == null) + { + if (to.Holding != null) + msgNum = 1062727; // You cannot trade with someone who is dragging something. + else if (HasTrade) + msgNum = 1062781; // You are already trading with someone else! + else if (to.HasTrade) + msgNum = 1062779; // That person is already involved in a trade + else if (to is PlayerMobile mobile && mobile.RefuseTrades) + msgNum = 1154111; // ~1_NAME~ is refusing all trades. + } + + if (msgNum == 0 && item != null) + { + if (cont != null) + { + plusItems += cont.TotalItems; + plusWeight += cont.TotalWeight; + } + + if (Backpack?.CheckHold(this, item, false, checkItems, plusItems, plusWeight) != true) + msgNum = 1004040; // You would not be able to hold this if the trade failed. + else if (to.Backpack?.CheckHold(to, item, false, checkItems, plusItems, plusWeight) != true) + msgNum = 1004039; // The recipient of this trade would not be able to carry this. + else + msgNum = CheckContentForTrade(item); + } + + if (msgNum != 0) + { + if (message) + { + if (msgNum == 1154111) + SendLocalizedMessage(msgNum, to.Name); + else + SendLocalizedMessage(msgNum); + } + + return false; + } + + return true; + } + + private static int CheckContentForTrade(Item item) + { + if (item is TrappableContainer container && container.TrapType != TrapType.None) + return 1004044; // You may not trade trapped items. + + if (StolenItem.IsStolen(item)) + return 1004043; // You may not trade recently stolen items. + + if (item is Container) + foreach (var subItem in item.Items) + { + var msg = CheckContentForTrade(subItem); + + if (msg != 0) + return msg; + } + + return 0; + } + + public override bool CheckNonlocalDrop(Mobile from, Item item, Item target) + { + if (!base.CheckNonlocalDrop(from, item, target)) + return false; + + if (from.AccessLevel >= AccessLevel.GameMaster) + return true; + + var pack = Backpack; + if (from == this && HasTrade && (target == pack || target.IsChildOf(pack))) + { + var bounce = item.GetBounce(); + + if (bounce?.Parent is Item parent && (parent == pack || parent.IsChildOf(pack))) + return true; + + SendLocalizedMessage(1004041); // You can't do that while you have a trade pending. + return false; + } + + return true; + } + + protected override void OnLocationChange(Point3D oldLocation) + { + CheckLightLevels(false); + + DuelContext?.OnLocationChanged(this); + + var context = DesignContext; + + if (context == null || m_NoRecursion) + return; + + m_NoRecursion = true; + + var foundation = context.Foundation; + + int newX = X, newY = Y; + var newZ = foundation.Z + HouseFoundation.GetLevelZ(context.Level, context.Foundation); + + var startX = foundation.X + foundation.Components.Min.X + 1; + var startY = foundation.Y + foundation.Components.Min.Y + 1; + var endX = startX + foundation.Components.Width - 1; + var endY = startY + foundation.Components.Height - 2; + + if (newX >= startX && newY >= startY && newX < endX && newY < endY && Map == foundation.Map) + { + if (Z != newZ) + Location = new Point3D(X, Y, newZ); + + m_NoRecursion = false; + return; + } + + Location = new Point3D(foundation.X, foundation.Y, newZ); + Map = foundation.Map; + + m_NoRecursion = false; + } + + public override bool OnMoveOver(Mobile m) => + m is BaseCreature creature && !creature.Controlled + ? !Alive || !creature.Alive || IsDeadBondedPet || creature.IsDeadBondedPet || + Hidden && AccessLevel > AccessLevel.Player + : Region.IsPartOf() && m is PlayerMobile pm && + (pm.DuelContext == null || pm.DuelPlayer == null || !pm.DuelContext.Started || pm.DuelContext.Finished || + pm.DuelPlayer.Eliminated) || base.OnMoveOver(m); + + public override bool CheckShove(Mobile shoved) => + m_IgnoreMobiles || TransformationSpellHelper.UnderTransformation(shoved, typeof(WraithFormSpell)) || + base.CheckShove(shoved); + + protected override void OnMapChange(Map oldMap) + { + if (Map != Faction.Facet && oldMap == Faction.Facet || Map == Faction.Facet && oldMap != Faction.Facet) + InvalidateProperties(); + + DuelContext?.OnMapChanged(this); + + var context = DesignContext; + + if (context == null || m_NoRecursion) + return; + + m_NoRecursion = true; + + var foundation = context.Foundation; + + if (Map != foundation.Map) + Map = foundation.Map; + + m_NoRecursion = false; + } + + public override void OnBeneficialAction(Mobile target, bool isCriminal) + { + SentHonorContext?.OnSourceBeneficialAction(target); + + base.OnBeneficialAction(target, isCriminal); + } + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + int disruptThreshold; + + if (!Core.AOS) + disruptThreshold = 0; + else if (from?.Player == true) + disruptThreshold = 18; + else + disruptThreshold = 25; + + if (amount > disruptThreshold) + { + var c = BandageContext.GetContext(this); + + c?.Slip(); + } + + if (Confidence.IsRegenerating(this)) + Confidence.StopRegenerating(this); + + WeightOverloading.FatigueOnDamage(this, amount); + + ReceivedHonorContext?.OnTargetDamaged(from, amount); + SentHonorContext?.OnSourceDamaged(from, amount); + + if (willKill && from is PlayerMobile mobile) + Timer.DelayCall(TimeSpan.FromSeconds(10), mobile.RecoverAmmo); + + base.OnDamage(amount, from, willKill); + } + + public override void Resurrect() + { + var wasAlive = Alive; + + base.Resurrect(); + + if (Alive && !wasAlive) + { + Item deathRobe = new DeathRobe(); + + if (!EquipItem(deathRobe)) + deathRobe.Delete(); + } + } + + public override void OnWarmodeChanged() + { + if (!Warmode) + Timer.DelayCall(TimeSpan.FromSeconds(10), RecoverAmmo); + } + + private bool FindItems_Callback(Item item) => + !item.Deleted && (item.LootType == LootType.Blessed || item.Insured) && + Backpack != item.Parent; + + public override bool OnBeforeDeath() + { + var state = NetState; + + state?.CancelAllTrades(); + + DropHolding(); + + if (Core.AOS && Backpack?.Deleted == false) + Backpack.FindItemsByType(FindItems_Callback).ForEach(item => Backpack.AddItem(item)); + + EquipSnapshot = new List(Items); + + m_NonAutoreinsuredItems = 0; + m_InsuranceAward = FindMostRecentDamager(false); + + if (m_InsuranceAward is BaseCreature creature) + { + var master = creature.GetMaster(); + + if (master != null) + m_InsuranceAward = master; + } + + if (m_InsuranceAward != null && (!m_InsuranceAward.Player || m_InsuranceAward == this)) + m_InsuranceAward = null; + + if (m_InsuranceAward is PlayerMobile mobile) + mobile.m_InsuranceBonus = 0; + + ReceivedHonorContext?.OnTargetKilled(); + SentHonorContext?.OnSourceKilled(); + + RecoverAmmo(); + + return base.OnBeforeDeath(); + } + + private bool CheckInsuranceOnDeath(Item item) + { + if (!InsuranceEnabled || !item.Insured) + return false; + + if (DuelContext?.Registered == true && DuelContext.Started && + m_DuelPlayer?.Eliminated != true) + return true; + + if (AutoRenewInsurance) + { + var cost = GetInsuranceCost(item); + + if (m_InsuranceAward != null) + cost /= 2; + + if (Banker.Withdraw(this, cost)) + { + item.PaidInsurance = true; + SendLocalizedMessage( + 1060398, + cost.ToString() + ); // ~1_AMOUNT~ gold has been withdrawn from your bank box. + } + else + { + SendLocalizedMessage(1061079, "", 0x23); // You lack the funds to purchase the insurance + item.PaidInsurance = false; + item.Insured = false; + m_NonAutoreinsuredItems++; + } + } + else + { + item.PaidInsurance = false; + item.Insured = false; + } + + if (m_InsuranceAward != null && Banker.Deposit(m_InsuranceAward, 300) && m_InsuranceAward is PlayerMobile pm) + pm.m_InsuranceBonus += 300; + + return true; + } + + public override DeathMoveResult GetParentMoveResultFor(Item item) + { + // It seems all items are unmarked on death, even blessed/insured ones + if (item.QuestItem) + item.QuestItem = false; + + if (CheckInsuranceOnDeath(item)) + return DeathMoveResult.MoveToBackpack; + + var res = base.GetParentMoveResultFor(item); + + if (res == DeathMoveResult.MoveToCorpse && item.Movable && Young) + res = DeathMoveResult.MoveToBackpack; + + return res; + } + + public override DeathMoveResult GetInventoryMoveResultFor(Item item) + { + // It seems all items are unmarked on death, even blessed/insured ones + if (item.QuestItem) + item.QuestItem = false; + + if (CheckInsuranceOnDeath(item)) + return DeathMoveResult.MoveToBackpack; + + var res = base.GetInventoryMoveResultFor(item); + + if (res == DeathMoveResult.MoveToCorpse && item.Movable && Young) + res = DeathMoveResult.MoveToBackpack; + + return res; + } + + public override void OnDeath(Container c) + { + if (m_NonAutoreinsuredItems > 0) SendLocalizedMessage(1061115); + + base.OnDeath(c); + + EquipSnapshot = null; + + HueMod = -1; + NameMod = null; + SavagePaintExpiration = TimeSpan.Zero; + + SetHairMods(-1, -1); + + PolymorphSpell.StopTimer(this); + IncognitoSpell.StopTimer(this); + DisguiseTimers.RemoveTimer(this); + + EndAction(); + EndAction(); + + MeerMage.StopEffect(this, false); + + if (Flying) + { + Flying = false; + BuffInfo.RemoveBuff(this, BuffIcon.Fly); + } + + StolenItem.ReturnOnDeath(this, c); + + if (PermaFlags.Count > 0) + { + PermaFlags.Clear(); + + if (c is Corpse corpse) + corpse.Criminal = true; + + if (Stealing.ClassicMode) + Criminal = true; + } + + if (Kills >= 5 && DateTime.UtcNow >= m_NextJustAward) + { + var m = FindMostRecentDamager(false); + + if (m is BaseCreature bc) + m = bc.GetMaster(); + + if (m != this && m is PlayerMobile) + { + var gainedPath = false; + + var pointsToGain = 0; + + pointsToGain += (int)Math.Sqrt(GameTime.TotalSeconds * 4); + pointsToGain *= 5; + pointsToGain += (int)Math.Pow(Skills.Total / 250.0, 2); + + if (VirtueHelper.Award(m, VirtueName.Justice, pointsToGain, ref gainedPath)) + { + if (gainedPath) + m.SendLocalizedMessage(1049367); // You have gained a path in Justice! + else + m.SendLocalizedMessage(1049363); // You have gained in Justice. + + m.FixedParticles(0x375A, 9, 20, 5027, EffectLayer.Waist); + m.PlaySound(0x1F7); + + m_NextJustAward = DateTime.UtcNow + TimeSpan.FromMinutes(pointsToGain / 3.0); + } + } + } + + if (m_InsuranceAward is PlayerMobile pm) + if (pm.m_InsuranceBonus > 0) + pm.SendLocalizedMessage( + 1060397, + pm.m_InsuranceBonus.ToString() + ); // ~1_AMOUNT~ gold has been deposited into your bank box. + + var killer = FindMostRecentDamager(true); + + if (killer is BaseCreature bcKiller) + { + var master = bcKiller.GetMaster(); + if (master != null) + killer = master; + } + + if (Young && DuelContext == null) + if (YoungDeathTeleport()) + Timer.DelayCall(TimeSpan.FromSeconds(2.5), SendYoungDeathNotice); + + if (DuelContext?.Registered != true || !DuelContext.Started || m_DuelPlayer?.Eliminated != false) + Faction.HandleDeath(this, killer); + + Guilds.Guild.HandleDeath(this, killer); + + MLQuestSystem.HandleDeath(this); + + DuelContext?.OnDeath(this, c); + + if (m_BuffTable != null) + { + var list = new List(); + + foreach (var buff in m_BuffTable.Values) + if (!buff.RetainThroughDeath) + list.Add(buff); + + for (var i = 0; i < list.Count; i++) + RemoveBuff(list[i]); + } + } + + public override bool MutateSpeech(List hears, ref string text, ref object context) + { + if (Alive) + return false; + + if (Core.ML && Skills.SpiritSpeak.Value >= 100.0) + return false; + + if (Core.AOS) + for (var i = 0; i < hears.Count; ++i) + { + var m = hears[i]; + + if (m != this && m.Skills.SpiritSpeak.Value >= 100.0) + return false; + } + + return base.MutateSpeech(hears, ref text, ref context); + } + + public override void DoSpeech(string text, int[] keywords, MessageType type, int hue) + { + if (Guilds.Guild.NewGuildSystem && (type == MessageType.Guild || type == MessageType.Alliance)) + { + if (!(Guild is Guild g)) + { + SendLocalizedMessage(1063142); // You are not in a guild! + } + else if (type == MessageType.Alliance) + { + if (g.Alliance?.IsMember(g) == true) + { + // g.Alliance.AllianceTextMessage( hue, "[Alliance][{0}]: {1}", this.Name, text ); + g.Alliance.AllianceChat(this, text); + SendToStaffMessage(this, "[Alliance]: {0}", text); + + AllianceMessageHue = hue; + } + else + { + SendLocalizedMessage(1071020); // You are not in an alliance! + } + } + else // Type == MessageType.Guild + { + GuildMessageHue = hue; + + g.GuildChat(this, text); + SendToStaffMessage(this, "[Guild]: {0}", text); + } + } + else + { + base.DoSpeech(text, keywords, type, hue); + } + } + + private static void SendToStaffMessage(Mobile from, string text) + { + Packet p = null; + + foreach (var ns in from.GetClientsInRange(8)) + { + var mob = ns.Mobile; + + if (mob?.AccessLevel >= AccessLevel.GameMaster && mob.AccessLevel > from.AccessLevel) + { + p ??= Packet.Acquire( + new UnicodeMessage( + from.Serial, + from.Body, + MessageType.Regular, + from.SpeechHue, + 3, + from.Language, + from.Name, + text + ) + ); + + ns.Send(p); + } + } + + Packet.Release(p); + } + + private static void SendToStaffMessage(Mobile from, string format, params object[] args) + { + SendToStaffMessage(from, string.Format(format, args)); + } + + public override void Damage(int amount, Mobile from) + { + if (EvilOmenSpell.TryEndEffect(this)) + amount = (int)(amount * 1.25); + + var oath = BloodOathSpell.GetBloodOath(from); + + /* Per EA's UO Herald Pub48 (ML): + * ((resist spellsx10)/20 + 10=percentage of damage resisted) + */ + + if (oath == this) + { + amount = (int)(amount * 1.1); + + if (amount > 35 && from is PlayerMobile) /* capped @ 35, seems no expansion */ amount = 35; + + if (Core.ML) + from.Damage((int)(amount * (1 - (from.Skills.MagicResist.Value * .5 + 10) / 100)), this); + else + from.Damage(amount, this); + } + + if (from != null && Talisman is BaseTalisman talisman) + if (talisman.Protection != null && talisman.Protection.Type != null) + { + var type = talisman.Protection.Type; + + if (type.IsInstanceOfType(from)) + amount = (int)(amount * (1 - (double)talisman.Protection.Amount / 100)); + } + + base.Damage(amount, from); + } + + public override bool IsHarmfulCriminal(Mobile target) + { + if (Stealing.ClassicMode && target is PlayerMobile mobile && mobile.PermaFlags.Count > 0) + { + if (Notoriety.Compute(this, mobile) == Notoriety.Innocent) + mobile.Delta(MobileDelta.Noto); + + return false; + } + + var bc = target as BaseCreature; + + if (bc?.InitialInnocent == true && !bc.Controlled) + return false; + + if (Core.ML && bc?.Controlled == true && this == bc.ControlMaster) + return false; + + return base.IsHarmfulCriminal(target); + } + + public bool AntiMacroCheck(Skill skill, object obj) + { + if (obj == null || m_AntiMacroTable == null || AccessLevel != AccessLevel.Player) + return true; + + if (!m_AntiMacroTable.TryGetValue(skill, out var tbl)) + m_AntiMacroTable[skill] = tbl = new Dictionary(); + + if (tbl.TryGetValue(obj, out var count)) + { + if (count.TimeStamp + SkillCheck.AntiMacroExpire <= DateTime.UtcNow) + { + count.Count = 1; + return true; + } + + ++count.Count; + return count.Count <= SkillCheck.Allowance; + } + + tbl[obj] = count = new CountAndTimeStamp(); + count.Count = 1; + + return true; + } + + private void RevertHair() + { + SetHairMods(-1, -1); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + switch (version) + { + case 29: + { + if (reader.ReadBool()) + { + m_StuckMenuUses = new DateTime[reader.ReadInt()]; + + for (var i = 0; i < m_StuckMenuUses.Length; ++i) m_StuckMenuUses[i] = reader.ReadDateTime(); + } + else + { + m_StuckMenuUses = null; + } + + goto case 28; + } + case 28: + { + PeacedUntil = reader.ReadDateTime(); + + goto case 27; + } + case 27: + { + AnkhNextUse = reader.ReadDateTime(); + + goto case 26; + } + case 26: + { + AutoStabled = reader.ReadStrongMobileList(); + + goto case 25; + } + case 25: + { + var recipeCount = reader.ReadInt(); + + if (recipeCount > 0) + { + m_AcquiredRecipes = new Dictionary(); + + for (var i = 0; i < recipeCount; i++) + { + var r = reader.ReadInt(); + if (reader.ReadBool()) // Don't add in recipes which we haven't gotten or have been removed + m_AcquiredRecipes.Add(r, true); + } + } + + goto case 24; + } + case 24: + { + LastHonorLoss = reader.ReadDeltaTime(); + goto case 23; + } + case 23: + { + ChampionTitles = new ChampionTitleInfo(reader); + goto case 22; + } + case 22: + { + LastValorLoss = reader.ReadDateTime(); + goto case 21; + } + case 21: + { + ToTItemsTurnedIn = reader.ReadEncodedInt(); + ToTTotalMonsterFame = reader.ReadInt(); + goto case 20; + } + case 20: + { + AllianceMessageHue = reader.ReadEncodedInt(); + GuildMessageHue = reader.ReadEncodedInt(); + + goto case 19; + } + case 19: + { + var rank = reader.ReadEncodedInt(); + var maxRank = RankDefinition.Ranks.Length - 1; + if (rank > maxRank) + rank = maxRank; + + m_GuildRank = RankDefinition.Ranks[rank]; + LastOnline = reader.ReadDateTime(); + goto case 18; + } + case 18: + { + SolenFriendship = (SolenFriendship)reader.ReadEncodedInt(); + + goto case 17; + } + case 17: // changed how DoneQuests is serialized + case 16: + { + Quest = QuestSerializer.DeserializeQuest(reader); + + if (Quest != null) + Quest.From = this; + + var count = reader.ReadEncodedInt(); + + if (count > 0) + { + DoneQuests = new List(); + + for (var i = 0; i < count; ++i) + { + var questType = QuestSerializer.ReadType(QuestSystem.QuestTypes, reader); + DateTime restartTime; + + if (version < 17) + restartTime = DateTime.MaxValue; + else + restartTime = reader.ReadDateTime(); + + DoneQuests.Add(new QuestRestartInfo(questType, restartTime)); + } + } + + Profession = reader.ReadEncodedInt(); + goto case 15; + } + case 15: + { + LastCompassionLoss = reader.ReadDeltaTime(); + goto case 14; + } + case 14: + { + CompassionGains = reader.ReadEncodedInt(); + + if (CompassionGains > 0) + NextCompassionDay = reader.ReadDeltaTime(); + + goto case 13; + } + case 13: // just removed m_PaidInsurance list + case 12: + { + BOBFilter = new BOBFilter(reader); + goto case 11; + } + case 11: + { + if (version < 13) + { + var paid = reader.ReadStrongItemList(); + + for (var i = 0; i < paid.Count; ++i) + paid[i].PaidInsurance = true; + } + + goto case 10; + } + case 10: + { + if (reader.ReadBool()) + { + m_HairModID = reader.ReadInt(); + m_HairModHue = reader.ReadInt(); + m_BeardModID = reader.ReadInt(); + m_BeardModHue = reader.ReadInt(); + } + + goto case 9; + } + case 9: + { + SavagePaintExpiration = reader.ReadTimeSpan(); + + if (SavagePaintExpiration > TimeSpan.Zero) + { + BodyMod = Female ? 184 : 183; + HueMod = 0; + } + + goto case 8; + } + case 8: + { + NpcGuild = (NpcGuild)reader.ReadInt(); + NpcGuildJoinTime = reader.ReadDateTime(); + NpcGuildGameTime = reader.ReadTimeSpan(); + goto case 7; + } + case 7: + { + PermaFlags = reader.ReadStrongMobileList(); + goto case 6; + } + case 6: + { + NextTailorBulkOrder = reader.ReadTimeSpan(); + goto case 5; + } + case 5: + { + NextSmithBulkOrder = reader.ReadTimeSpan(); + goto case 4; + } + case 4: + { + LastJusticeLoss = reader.ReadDeltaTime(); + JusticeProtectors = reader.ReadStrongMobileList(); + goto case 3; + } + case 3: + { + LastSacrificeGain = reader.ReadDeltaTime(); + LastSacrificeLoss = reader.ReadDeltaTime(); + AvailableResurrects = reader.ReadInt(); + goto case 2; + } + case 2: + { + Flags = (PlayerFlag)reader.ReadInt(); + goto case 1; + } + case 1: + { + m_LongTermElapse = reader.ReadTimeSpan(); + m_ShortTermElapse = reader.ReadTimeSpan(); + m_GameTime = reader.ReadTimeSpan(); + goto case 0; + } + case 0: + { + if (version < 26) + AutoStabled = new List(); + break; + } + } + + RecentlyReported ??= new List(); + + // Professions weren't verified on 1.0 RC0 + if (!CharacterCreation.VerifyProfession(Profession)) + Profession = 0; + + PermaFlags ??= new List(); + JusticeProtectors ??= new List(); + BOBFilter ??= new BOBFilter(); + + // Default to member if going from older version to new version (only time it should be null) + m_GuildRank ??= RankDefinition.Member; + + if (LastOnline == DateTime.MinValue && Account != null) + LastOnline = ((Account)Account).LastLogin; + + ChampionTitles ??= new ChampionTitleInfo(); + + if (AccessLevel > AccessLevel.Player) + m_IgnoreMobiles = true; + + var list = Stabled; + + for (var i = 0; i < list.Count; ++i) + if (list[i] is BaseCreature bc) + { + bc.IsStabled = true; + bc.StabledBy = this; + } + + CheckAtrophies(this); + + if (Hidden) // Hiding is the only buff where it has an effect that's serialized. + AddBuff(new BuffInfo(BuffIcon.HidingAndOrStealth, 1075655)); + } + + public override void Serialize(IGenericWriter writer) + { + // cleanup our anti-macro table + foreach (var t in m_AntiMacroTable.Values) + { + var toRemove = t.Where(kvp => kvp.Value.TimeStamp + SkillCheck.AntiMacroExpire <= DateTime.UtcNow) + .Select(kvp => kvp.Key) + .ToList(); + + foreach (var key in toRemove) + t.Remove(key); + } + + CheckKillDecay(); + + CheckAtrophies(this); + + base.Serialize(writer); + + writer.Write(29); // version + + if (m_StuckMenuUses != null) + { + writer.Write(true); + + writer.Write(m_StuckMenuUses.Length); + + for (var i = 0; i < m_StuckMenuUses.Length; ++i) + writer.Write(m_StuckMenuUses[i]); + } + else + { + writer.Write(false); + } + + writer.Write(PeacedUntil); + writer.Write(AnkhNextUse); + writer.Write(AutoStabled, true); + + if (m_AcquiredRecipes == null) + { + writer.Write(0); + } + else + { + writer.Write(m_AcquiredRecipes.Count); + + foreach (var kvp in m_AcquiredRecipes) + { + writer.Write(kvp.Key); + writer.Write(kvp.Value); + } + } + + writer.WriteDeltaTime(LastHonorLoss); + + ChampionTitleInfo.Serialize(writer, ChampionTitles); + + writer.Write(LastValorLoss); + writer.WriteEncodedInt(ToTItemsTurnedIn); + writer.Write(ToTTotalMonsterFame); // This ain't going to be a small #. + + writer.WriteEncodedInt(AllianceMessageHue); + writer.WriteEncodedInt(GuildMessageHue); + + writer.WriteEncodedInt(m_GuildRank.Rank); + writer.Write(LastOnline); + + writer.WriteEncodedInt((int)SolenFriendship); + + QuestSerializer.Serialize(Quest, writer); + + if (DoneQuests == null) + { + writer.WriteEncodedInt(0); + } + else + { + writer.WriteEncodedInt(DoneQuests.Count); + + for (var i = 0; i < DoneQuests.Count; ++i) + { + var restartInfo = DoneQuests[i]; + + QuestSerializer.Write(restartInfo.QuestType, QuestSystem.QuestTypes, writer); + writer.Write(restartInfo.RestartTime); + } + } + + writer.WriteEncodedInt(Profession); + + writer.WriteDeltaTime(LastCompassionLoss); + + writer.WriteEncodedInt(CompassionGains); if (CompassionGains > 0) - NextCompassionDay = reader.ReadDeltaTime(); + writer.WriteDeltaTime(NextCompassionDay); - goto case 13; - } - case 13: // just removed m_PaidInsurance list - case 12: - { - BOBFilter = new BOBFilter(reader); - goto case 11; - } - case 11: - { - if (version < 13) + BOBFilter.Serialize(writer); + + var useMods = m_HairModID != -1 || m_BeardModID != -1; + + writer.Write(useMods); + + if (useMods) { - List paid = reader.ReadStrongItemList(); - - for (int i = 0; i < paid.Count; ++i) - paid[i].PaidInsurance = true; + writer.Write(m_HairModID); + writer.Write(m_HairModHue); + writer.Write(m_BeardModID); + writer.Write(m_BeardModHue); } - goto case 10; - } - case 10: - { - if (reader.ReadBool()) + writer.Write(SavagePaintExpiration); + + writer.Write((int)NpcGuild); + writer.Write(NpcGuildJoinTime); + writer.Write(NpcGuildGameTime); + + writer.Write(PermaFlags, true); + + writer.Write(NextTailorBulkOrder); + + writer.Write(NextSmithBulkOrder); + + writer.WriteDeltaTime(LastJusticeLoss); + writer.Write(JusticeProtectors, true); + + writer.WriteDeltaTime(LastSacrificeGain); + writer.WriteDeltaTime(LastSacrificeLoss); + writer.Write(AvailableResurrects); + + writer.Write((int)Flags); + + writer.Write(m_LongTermElapse); + writer.Write(m_ShortTermElapse); + writer.Write(GameTime); + } + + public static void CheckAtrophies(Mobile m) + { + SacrificeVirtue.CheckAtrophy(m); + JusticeVirtue.CheckAtrophy(m); + CompassionVirtue.CheckAtrophy(m); + ValorVirtue.CheckAtrophy(m); + + if (m is PlayerMobile mobile) + ChampionTitleInfo.CheckAtrophy(mobile); + } + + public void CheckKillDecay() + { + if (m_ShortTermElapse < GameTime) { - m_HairModID = reader.ReadInt(); - m_HairModHue = reader.ReadInt(); - m_BeardModID = reader.ReadInt(); - m_BeardModHue = reader.ReadInt(); + m_ShortTermElapse += TimeSpan.FromHours(8); + if (ShortTermMurders > 0) + --ShortTermMurders; } - goto case 9; - } - case 9: - { - SavagePaintExpiration = reader.ReadTimeSpan(); - - if (SavagePaintExpiration > TimeSpan.Zero) + if (m_LongTermElapse < GameTime) { - BodyMod = Female ? 184 : 183; - HueMod = 0; + m_LongTermElapse += TimeSpan.FromHours(40); + if (Kills > 0) + --Kills; + } + } + + public void ResetKillTime() + { + m_ShortTermElapse = GameTime + TimeSpan.FromHours(8); + m_LongTermElapse = GameTime + TimeSpan.FromHours(40); + } + + public override bool CanSee(Mobile m) + { + if (m is CharacterStatue statue) + statue.OnRequestedAnimation(this); + + if (m is PlayerMobile mobile && mobile.VisibilityList.Contains(this)) + return true; + + if (DuelContext?.Finished == false && DuelContext.m_Tournament != null && m_DuelPlayer?.Eliminated == false) + { + var owner = m; + + if (owner is BaseCreature bc) + { + var master = bc.GetMaster(); + + if (master != null) + owner = master; + } + + if (m.AccessLevel == AccessLevel.Player && owner is PlayerMobile pm && pm.DuelContext != DuelContext) + return false; } - goto case 8; - } - case 8: - { - NpcGuild = (NpcGuild)reader.ReadInt(); - NpcGuildJoinTime = reader.ReadDateTime(); - NpcGuildGameTime = reader.ReadTimeSpan(); - goto case 7; - } - case 7: - { - PermaFlags = reader.ReadStrongMobileList(); - goto case 6; - } - case 6: - { - NextTailorBulkOrder = reader.ReadTimeSpan(); - goto case 5; - } - case 5: - { - NextSmithBulkOrder = reader.ReadTimeSpan(); - goto case 4; - } - case 4: - { - LastJusticeLoss = reader.ReadDeltaTime(); - JusticeProtectors = reader.ReadStrongMobileList(); - goto case 3; - } - case 3: - { - LastSacrificeGain = reader.ReadDeltaTime(); - LastSacrificeLoss = reader.ReadDeltaTime(); - AvailableResurrects = reader.ReadInt(); - goto case 2; - } - case 2: - { - Flags = (PlayerFlag)reader.ReadInt(); - goto case 1; - } - case 1: - { - m_LongTermElapse = reader.ReadTimeSpan(); - m_ShortTermElapse = reader.ReadTimeSpan(); - m_GameTime = reader.ReadTimeSpan(); - goto case 0; - } - case 0: - { - if (version < 26) - AutoStabled = new List(); - break; - } - } - - RecentlyReported ??= new List(); - - // Professions weren't verified on 1.0 RC0 - if (!CharacterCreation.VerifyProfession(Profession)) - Profession = 0; - - PermaFlags ??= new List(); - JusticeProtectors ??= new List(); - BOBFilter ??= new BOBFilter(); - - // Default to member if going from older version to new version (only time it should be null) - m_GuildRank ??= RankDefinition.Member; - - if (LastOnline == DateTime.MinValue && Account != null) - LastOnline = ((Account)Account).LastLogin; - - ChampionTitles ??= new ChampionTitleInfo(); - - if (AccessLevel > AccessLevel.Player) - m_IgnoreMobiles = true; - - List list = Stabled; - - for (int i = 0; i < list.Count; ++i) - if (list[i] is BaseCreature bc) - { - bc.IsStabled = true; - bc.StabledBy = this; + return base.CanSee(m); } - CheckAtrophies(this); - - if (Hidden) // Hiding is the only buff where it has an effect that's serialized. - AddBuff(new BuffInfo(BuffIcon.HidingAndOrStealth, 1075655)); - } - - public override void Serialize(IGenericWriter writer) - { - // cleanup our anti-macro table - foreach (Dictionary t in m_AntiMacroTable.Values) - { - List toRemove = t.Where(kvp => kvp.Value.TimeStamp + SkillCheck.AntiMacroExpire <= DateTime.UtcNow) - .Select(kvp => kvp.Key).ToList(); - - foreach (object key in toRemove) - t.Remove(key); - } - - CheckKillDecay(); - - CheckAtrophies(this); - - base.Serialize(writer); - - writer.Write(29); // version - - if (m_StuckMenuUses != null) - { - writer.Write(true); - - writer.Write(m_StuckMenuUses.Length); - - for (int i = 0; i < m_StuckMenuUses.Length; ++i) - writer.Write(m_StuckMenuUses[i]); - } - else - { - writer.Write(false); - } - - writer.Write(PeacedUntil); - writer.Write(AnkhNextUse); - writer.Write(AutoStabled, true); - - if (m_AcquiredRecipes == null) - { - writer.Write(0); - } - else - { - writer.Write(m_AcquiredRecipes.Count); - - foreach (KeyValuePair kvp in m_AcquiredRecipes) + public virtual void CheckedAnimate(int action, int frameCount, int repeatCount, bool forward, bool repeat, int delay) { - writer.Write(kvp.Key); - writer.Write(kvp.Value); - } - } - - writer.WriteDeltaTime(LastHonorLoss); - - ChampionTitleInfo.Serialize(writer, ChampionTitles); - - writer.Write(LastValorLoss); - writer.WriteEncodedInt(ToTItemsTurnedIn); - writer.Write(ToTTotalMonsterFame); // This ain't going to be a small #. - - writer.WriteEncodedInt(AllianceMessageHue); - writer.WriteEncodedInt(GuildMessageHue); - - writer.WriteEncodedInt(m_GuildRank.Rank); - writer.Write(LastOnline); - - writer.WriteEncodedInt((int)SolenFriendship); - - QuestSerializer.Serialize(Quest, writer); - - if (DoneQuests == null) - { - writer.WriteEncodedInt(0); - } - else - { - writer.WriteEncodedInt(DoneQuests.Count); - - for (int i = 0; i < DoneQuests.Count; ++i) - { - QuestRestartInfo restartInfo = DoneQuests[i]; - - QuestSerializer.Write(restartInfo.QuestType, QuestSystem.QuestTypes, writer); - writer.Write(restartInfo.RestartTime); - } - } - - writer.WriteEncodedInt(Profession); - - writer.WriteDeltaTime(LastCompassionLoss); - - writer.WriteEncodedInt(CompassionGains); - - if (CompassionGains > 0) - writer.WriteDeltaTime(NextCompassionDay); - - BOBFilter.Serialize(writer); - - bool useMods = m_HairModID != -1 || m_BeardModID != -1; - - writer.Write(useMods); - - if (useMods) - { - writer.Write(m_HairModID); - writer.Write(m_HairModHue); - writer.Write(m_BeardModID); - writer.Write(m_BeardModHue); - } - - writer.Write(SavagePaintExpiration); - - writer.Write((int)NpcGuild); - writer.Write(NpcGuildJoinTime); - writer.Write(NpcGuildGameTime); - - writer.Write(PermaFlags, true); - - writer.Write(NextTailorBulkOrder); - - writer.Write(NextSmithBulkOrder); - - writer.WriteDeltaTime(LastJusticeLoss); - writer.Write(JusticeProtectors, true); - - writer.WriteDeltaTime(LastSacrificeGain); - writer.WriteDeltaTime(LastSacrificeLoss); - writer.Write(AvailableResurrects); - - writer.Write((int)Flags); - - writer.Write(m_LongTermElapse); - writer.Write(m_ShortTermElapse); - writer.Write(GameTime); - } - - public static void CheckAtrophies(Mobile m) - { - SacrificeVirtue.CheckAtrophy(m); - JusticeVirtue.CheckAtrophy(m); - CompassionVirtue.CheckAtrophy(m); - ValorVirtue.CheckAtrophy(m); - - if (m is PlayerMobile mobile) - ChampionTitleInfo.CheckAtrophy(mobile); - } - - public void CheckKillDecay() - { - if (m_ShortTermElapse < GameTime) - { - m_ShortTermElapse += TimeSpan.FromHours(8); - if (ShortTermMurders > 0) - --ShortTermMurders; - } - - if (m_LongTermElapse < GameTime) - { - m_LongTermElapse += TimeSpan.FromHours(40); - if (Kills > 0) - --Kills; - } - } - - public void ResetKillTime() - { - m_ShortTermElapse = GameTime + TimeSpan.FromHours(8); - m_LongTermElapse = GameTime + TimeSpan.FromHours(40); - } - - public override bool CanSee(Mobile m) - { - if (m is CharacterStatue statue) - statue.OnRequestedAnimation(this); - - if (m is PlayerMobile mobile && mobile.VisibilityList.Contains(this)) - return true; - - if (DuelContext?.Finished == false && DuelContext.m_Tournament != null && m_DuelPlayer?.Eliminated == false) - { - Mobile owner = m; - - if (owner is BaseCreature bc) - { - Mobile master = bc.GetMaster(); - - if (master != null) - owner = master; + if (!Mounted) + Animate(action, frameCount, repeatCount, forward, repeat, delay); } - if (m.AccessLevel == AccessLevel.Player && owner is PlayerMobile pm && pm.DuelContext != DuelContext) - return false; - } + public override bool CanSee(Item item) => + DesignContext?.Foundation.IsHiddenToCustomizer(item) != true && base.CanSee(item); - return base.CanSee(m); - } - - public virtual void CheckedAnimate(int action, int frameCount, int repeatCount, bool forward, bool repeat, int delay) - { - if (!Mounted) - Animate(action, frameCount, repeatCount, forward, repeat, delay); - } - - public override bool CanSee(Item item) => DesignContext?.Foundation.IsHiddenToCustomizer(item) != true && base.CanSee(item); - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - Faction faction = Faction.Find(this); - - faction?.RemoveMember(this); - - MLQuestSystem.HandleDeletion(this); - - BaseHouse.HandleDeletion(this); - - DisguiseTimers.RemoveTimer(this); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Map == Faction.Facet) - { - PlayerState pl = PlayerState.Find(this); - - if (pl != null) + public override void OnAfterDelete() { - Faction faction = pl.Faction; + base.OnAfterDelete(); - if (faction.Commander == this) - list.Add(1042733, faction.Definition.PropName); // Commanding Lord of the ~1_FACTION_NAME~ - else if (pl.Sheriff != null) - list.Add(1042734, "{0}\t{1}", pl.Sheriff.Definition.FriendlyName, - faction.Definition.PropName); // The Sheriff of ~1_CITY~, ~2_FACTION_NAME~ - else if (pl.Finance != null) - list.Add(1042735, "{0}\t{1}", pl.Finance.Definition.FriendlyName, - faction.Definition.PropName); // The Finance Minister of ~1_CITY~, ~2_FACTION_NAME~ - else if (pl.MerchantTitle != MerchantTitle.None) - list.Add(1060776, "{0}\t{1}", MerchantTitles.GetInfo(pl.MerchantTitle).Title, - faction.Definition.PropName); // ~1_val~, ~2_val~ - else - list.Add(1060776, "{0}\t{1}", pl.Rank.Title, faction.Definition.PropName); // ~1_val~, ~2_val~ + var faction = Faction.Find(this); + + faction?.RemoveMember(this); + + MLQuestSystem.HandleDeletion(this); + + BaseHouse.HandleDeletion(this); + + DisguiseTimers.RemoveTimer(this); } - } - if (Core.ML) - for (int i = AllFollowers.Count - 1; i >= 0; i--) - if (AllFollowers[i] is BaseCreature c && c.ControlOrder == OrderType.Guard) - { - list.Add(501129); // guarded - break; - } - } - - public override void OnSingleClick(Mobile from) - { - if (Map == Faction.Facet) - { - PlayerState pl = PlayerState.Find(this); - - if (pl != null) + public override void GetProperties(ObjectPropertyList list) { - string text; - bool ascii = false; + base.GetProperties(list); - Faction faction = pl.Faction; + if (Map == Faction.Facet) + { + var pl = PlayerState.Find(this); - if (faction.Commander == this) - { - text = $"{(Female ? "(Commanding Lady of the " : "(Commanding Lord of the ")}{faction.Definition.FriendlyName})"; - } - else if (pl.Sheriff != null) - { - text = $"(The Sheriff of {pl.Sheriff.Definition.FriendlyName}, {faction.Definition.FriendlyName})"; - } - else if (pl.Finance != null) - { - text = $"(The Finance Minister of {pl.Finance.Definition.FriendlyName}, {faction.Definition.FriendlyName})"; - } - else - { - ascii = true; + if (pl != null) + { + var faction = pl.Faction; - if (pl.MerchantTitle != MerchantTitle.None) - text = $"({MerchantTitles.GetInfo(pl.MerchantTitle).Title.String}, {faction.Definition.FriendlyName})"; + if (faction.Commander == this) + list.Add(1042733, faction.Definition.PropName); // Commanding Lord of the ~1_FACTION_NAME~ + else if (pl.Sheriff != null) + list.Add( + 1042734, + "{0}\t{1}", + pl.Sheriff.Definition.FriendlyName, + faction.Definition.PropName + ); // The Sheriff of ~1_CITY~, ~2_FACTION_NAME~ + else if (pl.Finance != null) + list.Add( + 1042735, + "{0}\t{1}", + pl.Finance.Definition.FriendlyName, + faction.Definition.PropName + ); // The Finance Minister of ~1_CITY~, ~2_FACTION_NAME~ + else if (pl.MerchantTitle != MerchantTitle.None) + list.Add( + 1060776, + "{0}\t{1}", + MerchantTitles.GetInfo(pl.MerchantTitle).Title, + faction.Definition.PropName + ); // ~1_val~, ~2_val~ + else + list.Add(1060776, "{0}\t{1}", pl.Rank.Title, faction.Definition.PropName); // ~1_val~, ~2_val~ + } + } + + if (Core.ML) + for (var i = AllFollowers.Count - 1; i >= 0; i--) + if (AllFollowers[i] is BaseCreature c && c.ControlOrder == OrderType.Guard) + { + list.Add(501129); // guarded + break; + } + } + + public override void OnSingleClick(Mobile from) + { + if (Map == Faction.Facet) + { + var pl = PlayerState.Find(this); + + if (pl != null) + { + string text; + var ascii = false; + + var faction = pl.Faction; + + if (faction.Commander == this) + { + text = + $"{(Female ? "(Commanding Lady of the " : "(Commanding Lord of the ")}{faction.Definition.FriendlyName})"; + } + else if (pl.Sheriff != null) + { + text = $"(The Sheriff of {pl.Sheriff.Definition.FriendlyName}, {faction.Definition.FriendlyName})"; + } + else if (pl.Finance != null) + { + text = + $"(The Finance Minister of {pl.Finance.Definition.FriendlyName}, {faction.Definition.FriendlyName})"; + } + else + { + ascii = true; + + if (pl.MerchantTitle != MerchantTitle.None) + text = + $"({MerchantTitles.GetInfo(pl.MerchantTitle).Title.String}, {faction.Definition.FriendlyName})"; + else + text = $"({pl.Rank.Title.String}, {faction.Definition.FriendlyName})"; + } + + var hue = Faction.Find(from) == faction ? 98 : 38; + + PrivateOverheadMessage(MessageType.Label, hue, ascii, text, from.NetState); + } + } + + base.OnSingleClick(from); + } + + protected override bool OnMove(Direction d) + { + if (!Core.SE) + return base.OnMove(d); + + if (AccessLevel != AccessLevel.Player) + return true; + + if (Hidden && DesignContext.Find(this) == null) // Hidden & NOT customizing a house + { + if (!Mounted && Skills.Stealth.Value >= 25.0) + { + var running = (d & Direction.Running) != 0; + + if (running) + { + if ((AllowedStealthSteps -= 2) <= 0) + RevealingAction(); + } + else if (AllowedStealthSteps-- <= 0) + { + Stealth.OnUse(this); + } + } + else + { + RevealingAction(); + } + } + + return true; + } + + public void AutoStablePets() + { + if (Core.SE && AllFollowers.Count > 0) + for (var i = m_AllFollowers.Count - 1; i >= 0; --i) + { + if (!(AllFollowers[i] is BaseCreature pet) || pet.ControlMaster == null) + continue; + + if (pet.Summoned) + { + if (pet.Map != Map) + { + pet.PlaySound(pet.GetAngerSound()); + Timer.DelayCall(pet.Delete); + } + + continue; + } + + if ((pet as IMount)?.Rider != null) + continue; + + if ((pet is PackLlama || pet is PackHorse || pet is Beetle) && pet.Backpack?.Items.Count > 0) + continue; + + if (pet is BaseEscortable) + continue; + + pet.ControlTarget = null; + pet.ControlOrder = OrderType.Stay; + pet.Internalize(); + + pet.SetControlMaster(null); + pet.SummonMaster = null; + + pet.IsStabled = true; + pet.StabledBy = this; + + pet.Loyalty = BaseCreature.MaxLoyalty; // Wonderfully happy + + Stabled.Add(pet); + AutoStabled.Add(pet); + } + } + + public void ClaimAutoStabledPets() + { + if (!Core.SE || AutoStabled.Count <= 0) + return; + + if (!Alive) + { + SendLocalizedMessage( + 1076251 + ); // Your pet was unable to join you while you are a ghost. Please re-login once you have ressurected to claim your pets. + return; + } + + for (var i = AutoStabled.Count - 1; i >= 0; --i) + { + if (!(AutoStabled[i] is BaseCreature pet)) + continue; + + if (pet.Deleted) + { + pet.IsStabled = false; + pet.StabledBy = null; + + if (Stabled.Contains(pet)) + Stabled.Remove(pet); + + continue; + } + + if (Followers + pet.ControlSlots <= FollowersMax) + { + pet.SetControlMaster(this); + + if (pet.Summoned) + pet.SummonMaster = this; + + pet.ControlTarget = this; + pet.ControlOrder = OrderType.Follow; + + pet.MoveToWorld(Location, Map); + + pet.IsStabled = false; + pet.StabledBy = null; + + pet.Loyalty = BaseCreature.MaxLoyalty; // Wonderfully Happy + + if (Stabled.Contains(pet)) + Stabled.Remove(pet); + } + else + { + SendLocalizedMessage( + 1049612, + pet.Name + ); // ~1_NAME~ remained in the stables because you have too many followers. + } + } + + AutoStabled.Clear(); + } + + public void RecoverAmmo() + { + if (!Core.SE || !Alive) + return; + + foreach (var kvp in RecoverableAmmo) + if (kvp.Value > 0) + { + Item ammo = null; + + try + { + ammo = ActivatorUtil.CreateInstance(kvp.Key) as Item; + } + catch + { + // ignored + } + + if (ammo == null) + continue; + + ammo.Amount = kvp.Value; + + var name = ammo.Name ?? ammo switch + { + Arrow _ => $"arrow{(ammo.Amount != 1 ? "s" : "")}", + Bolt _ => $"bolt{(ammo.Amount != 1 ? "s" : "")}", + _ => $"#{ammo.LabelNumber}" + }; + + PlaceInBackpack(ammo); + SendLocalizedMessage(1073504, $"{ammo.Amount}\t{name}"); // You recover ~1_NUM~ ~2_AMMO~. + } + + RecoverableAmmo.Clear(); + } + + private static int GetInsuranceCost(Item item) => 600; + + private void ToggleItemInsurance() + { + if (!CheckAlive()) + return; + + BeginTarget(-1, false, TargetFlags.None, ToggleItemInsurance_Callback); + SendLocalizedMessage(1060868); // Target the item you wish to toggle insurance status on to cancel + } + + private bool CanInsure(Item item) + { + if (item is Container && !(item is BaseQuiver) || item is BagOfSending || item is KeyRing || item is PotionKeg || + item is Sigil) + return false; + + if (item.Stackable) + return false; + + if (item.LootType == LootType.Cursed) + return false; + + if (item.ItemID == 0x204E) // death shroud + return false; + + if (item.Layer == Layer.Mount) + return false; + + return item.LootType != LootType.Blessed && item.LootType != LootType.Newbied && item.BlessedFor != this; + } + + private void ToggleItemInsurance_Callback(Mobile from, object obj) + { + if (!CheckAlive()) + return; + + ToggleItemInsurance_Callback(from, obj as Item, true); + } + + private void ToggleItemInsurance_Callback(Mobile from, Item item, bool target) + { + if (item?.IsChildOf(this) != true) + { + if (target) + BeginTarget(-1, false, TargetFlags.None, ToggleItemInsurance_Callback); + + SendLocalizedMessage( + 1060871, + "", + 0x23 + ); // You can only insure items that you have equipped or that are in your backpack + } + else if (item.Insured) + { + item.Insured = false; + + SendLocalizedMessage(1060874, "", 0x35); // You cancel the insurance on the item + + if (target) + { + BeginTarget(-1, false, TargetFlags.None, ToggleItemInsurance_Callback); + SendLocalizedMessage( + 1060868, + "", + 0x23 + ); // Target the item you wish to toggle insurance status on to cancel + } + } + else if (!CanInsure(item)) + { + if (target) + BeginTarget(-1, false, TargetFlags.None, ToggleItemInsurance_Callback); + + SendLocalizedMessage(1060869, "", 0x23); // You cannot insure that + } else - text = $"({pl.Rank.Title.String}, {faction.Definition.FriendlyName})"; - } - - int hue = Faction.Find(from) == faction ? 98 : 38; - - PrivateOverheadMessage(MessageType.Label, hue, ascii, text, from.NetState); - } - } - - base.OnSingleClick(from); - } - - protected override bool OnMove(Direction d) - { - if (!Core.SE) - return base.OnMove(d); - - if (AccessLevel != AccessLevel.Player) - return true; - - if (Hidden && DesignContext.Find(this) == null) // Hidden & NOT customizing a house - { - if (!Mounted && Skills.Stealth.Value >= 25.0) - { - bool running = (d & Direction.Running) != 0; - - if (running) - { - if ((AllowedStealthSteps -= 2) <= 0) - RevealingAction(); - } - else if (AllowedStealthSteps-- <= 0) - { - Stealth.OnUse(this); - } - } - else - { - RevealingAction(); - } - } - - return true; - } - - public void AutoStablePets() - { - if (Core.SE && AllFollowers.Count > 0) - for (int i = m_AllFollowers.Count - 1; i >= 0; --i) - { - if (!(AllFollowers[i] is BaseCreature pet) || pet.ControlMaster == null) - continue; - - if (pet.Summoned) - { - if (pet.Map != Map) { - pet.PlaySound(pet.GetAngerSound()); - Timer.DelayCall(pet.Delete); - } - - continue; - } - - if ((pet as IMount)?.Rider != null) - continue; - - if ((pet is PackLlama || pet is PackHorse || pet is Beetle) && pet.Backpack?.Items.Count > 0) - continue; - - if (pet is BaseEscortable) - continue; - - pet.ControlTarget = null; - pet.ControlOrder = OrderType.Stay; - pet.Internalize(); - - pet.SetControlMaster(null); - pet.SummonMaster = null; - - pet.IsStabled = true; - pet.StabledBy = this; - - pet.Loyalty = BaseCreature.MaxLoyalty; // Wonderfully happy - - Stabled.Add(pet); - AutoStabled.Add(pet); - } - } - - public void ClaimAutoStabledPets() - { - if (!Core.SE || AutoStabled.Count <= 0) - return; - - if (!Alive) - { - SendLocalizedMessage( - 1076251); // Your pet was unable to join you while you are a ghost. Please re-login once you have ressurected to claim your pets. - return; - } - - for (int i = AutoStabled.Count - 1; i >= 0; --i) - { - if (!(AutoStabled[i] is BaseCreature pet)) - continue; - - if (pet.Deleted) - { - pet.IsStabled = false; - pet.StabledBy = null; - - if (Stabled.Contains(pet)) - Stabled.Remove(pet); - - continue; - } - - if (Followers + pet.ControlSlots <= FollowersMax) - { - pet.SetControlMaster(this); - - if (pet.Summoned) - pet.SummonMaster = this; - - pet.ControlTarget = this; - pet.ControlOrder = OrderType.Follow; - - pet.MoveToWorld(Location, Map); - - pet.IsStabled = false; - pet.StabledBy = null; - - pet.Loyalty = BaseCreature.MaxLoyalty; // Wonderfully Happy - - if (Stabled.Contains(pet)) - Stabled.Remove(pet); - } - else - { - SendLocalizedMessage(1049612, - pet.Name); // ~1_NAME~ remained in the stables because you have too many followers. - } - } - - AutoStabled.Clear(); - } - - private class CountAndTimeStamp - { - private int m_Count; - - public DateTime TimeStamp { get; private set; } - - public int Count - { - get => m_Count; - set - { - m_Count = value; - TimeStamp = DateTime.UtcNow; - } - } - } - - private class MountBlock - { - public readonly Timer m_Timer; - public readonly BlockMountType m_Type; - - public MountBlock(TimeSpan duration, BlockMountType type, Mobile mobile) - { - m_Type = type; - - m_Timer = Timer.DelayCall(duration, RemoveBlock, mobile); - } - - private void RemoveBlock(Mobile mobile) - { - if (mobile is PlayerMobile pm) - pm.m_MountBlock = null; - } - } - - private delegate void ContextCallback(); - - private class CallbackEntry : ContextMenuEntry - { - private readonly ContextCallback m_Callback; - - public CallbackEntry(int number, ContextCallback callback) : this(number, -1, callback) - { - } - - public CallbackEntry(int number, int range, ContextCallback callback) : base(number, range) => m_Callback = callback; - - public override void OnClick() - { - m_Callback?.Invoke(); - } - } - - public List RecentlyReported { get; set; } - - public List AutoStabled { get; private set; } - - public bool NinjaWepCooldown { get; set; } - - public List AllFollowers => m_AllFollowers ?? (m_AllFollowers = new List()); - - public RankDefinition GuildRank - { - get => AccessLevel >= AccessLevel.GameMaster ? RankDefinition.Leader : m_GuildRank; - set => m_GuildRank = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int GuildMessageHue { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int AllianceMessageHue { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int Profession { get; set; } - - public int StepsTaken { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsStealthing // IsStealthing should be moved to Server.Mobiles - { - get; - set; - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IgnoreMobiles // IgnoreMobiles should be moved to Server.Mobiles - { - get => m_IgnoreMobiles; - set - { - if (m_IgnoreMobiles != value) - { - m_IgnoreMobiles = value; - Delta(MobileDelta.Flags); - } - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public NpcGuild NpcGuild { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime NpcGuildJoinTime { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime NextBODTurnInTime { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime LastOnline { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public long LastMoved => LastMoveTime; - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan NpcGuildGameTime { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int ToTItemsTurnedIn { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int ToTTotalMonsterFame { get; set; } - - public int ExecutesLightningStrike { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int ToothAche - { - get => CandyCane.GetToothAche(this); - set => CandyCane.SetToothAche(this, value); - } - - public PlayerFlag Flags { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool PagingSquelched - { - get => GetFlag(PlayerFlag.PagingSquelched); - set => SetFlag(PlayerFlag.PagingSquelched, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Glassblowing - { - get => GetFlag(PlayerFlag.Glassblowing); - set => SetFlag(PlayerFlag.Glassblowing, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Masonry - { - get => GetFlag(PlayerFlag.Masonry); - set => SetFlag(PlayerFlag.Masonry, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool SandMining - { - get => GetFlag(PlayerFlag.SandMining); - set => SetFlag(PlayerFlag.SandMining, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool StoneMining - { - get => GetFlag(PlayerFlag.StoneMining); - set => SetFlag(PlayerFlag.StoneMining, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool ToggleMiningStone - { - get => GetFlag(PlayerFlag.ToggleMiningStone); - set => SetFlag(PlayerFlag.ToggleMiningStone, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool KarmaLocked - { - get => GetFlag(PlayerFlag.KarmaLocked); - set => SetFlag(PlayerFlag.KarmaLocked, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool AutoRenewInsurance - { - get => GetFlag(PlayerFlag.AutoRenewInsurance); - set => SetFlag(PlayerFlag.AutoRenewInsurance, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool UseOwnFilter - { - get => GetFlag(PlayerFlag.UseOwnFilter); - set => SetFlag(PlayerFlag.UseOwnFilter, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool PublicMyRunUO - { - get => GetFlag(PlayerFlag.PublicMyRunUO); - set => SetFlag(PlayerFlag.PublicMyRunUO, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool AcceptGuildInvites - { - get => GetFlag(PlayerFlag.AcceptGuildInvites); - set => SetFlag(PlayerFlag.AcceptGuildInvites, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool HasStatReward - { - get => GetFlag(PlayerFlag.HasStatReward); - set => SetFlag(PlayerFlag.HasStatReward, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool RefuseTrades - { - get => GetFlag(PlayerFlag.RefuseTrades); - set => SetFlag(PlayerFlag.RefuseTrades, value); - } - - public Dictionary RecoverableAmmo { get; } = new Dictionary(); - - public void RecoverAmmo() - { - if (!Core.SE || !Alive) - return; - - foreach (KeyValuePair kvp in RecoverableAmmo) - if (kvp.Value > 0) - { - Item ammo = null; - - try - { - ammo = ActivatorUtil.CreateInstance(kvp.Key) as Item; - } - catch - { - // ignored - } - - if (ammo == null) - continue; - - ammo.Amount = kvp.Value; - - string name = ammo.Name ?? ammo switch - { - Arrow _ => $"arrow{(ammo.Amount != 1 ? "s" : "")}", - Bolt _ => $"bolt{(ammo.Amount != 1 ? "s" : "")}", - _ => $"#{ammo.LabelNumber}" - }; - - PlaceInBackpack(ammo); - SendLocalizedMessage(1073504, $"{ammo.Amount}\t{name}"); // You recover ~1_NUM~ ~2_AMMO~. - } - - RecoverableAmmo.Clear(); - } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime AcceleratedStart { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public SkillName AcceleratedSkill { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public override int HitsMax - { - get - { - int strBase; - int strOffs = GetStatOffset(StatType.Str); - - if (Core.AOS) - { - strBase = Str; // this.Str already includes GetStatOffset/str - strOffs = AosAttributes.GetValue(this, AosAttribute.BonusHits); - - if (Core.ML && strOffs > 25 && AccessLevel <= AccessLevel.Player) - strOffs = 25; - - if (AnimalForm.UnderTransformation(this, typeof(BakeKitsune)) || - AnimalForm.UnderTransformation(this, typeof(GreyWolf))) - strOffs += 20; - } - else - { - strBase = RawStr; - } - - return strBase / 2 + 50 + strOffs; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public override int StamMax => base.StamMax + AosAttributes.GetValue(this, AosAttribute.BonusStam); - - [CommandProperty(AccessLevel.GameMaster)] - public override int ManaMax => base.ManaMax + AosAttributes.GetValue(this, AosAttribute.BonusMana) + - (Core.ML && Race == Race.Elf ? 20 : 0); - - [CommandProperty(AccessLevel.GameMaster)] - public override int Str - { - get - { - if (Core.ML && AccessLevel == AccessLevel.Player) - return Math.Min(base.Str, 150); - - return base.Str; - } - set => base.Str = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public override int Int - { - get - { - if (Core.ML && AccessLevel == AccessLevel.Player) - return Math.Min(base.Int, 150); - - return base.Int; - } - set => base.Int = value; - } - - [CommandProperty(AccessLevel.GameMaster)] - public override int Dex - { - get - { - if (Core.ML && AccessLevel == AccessLevel.Player) - return Math.Min(base.Dex, 150); - - return base.Dex; - } - set => base.Dex = value; - } - - private static int GetInsuranceCost(Item item) => 600; - - private void ToggleItemInsurance() - { - if (!CheckAlive()) - return; - - BeginTarget(-1, false, TargetFlags.None, ToggleItemInsurance_Callback); - SendLocalizedMessage(1060868); // Target the item you wish to toggle insurance status on to cancel - } - - private bool CanInsure(Item item) - { - if (item is Container && !(item is BaseQuiver) || item is BagOfSending || item is KeyRing || item is PotionKeg || - item is Sigil) - return false; - - if (item.Stackable) - return false; - - if (item.LootType == LootType.Cursed) - return false; - - if (item.ItemID == 0x204E) // death shroud - return false; - - if (item.Layer == Layer.Mount) - return false; - - return item.LootType != LootType.Blessed && item.LootType != LootType.Newbied && item.BlessedFor != this; - } - - private void ToggleItemInsurance_Callback(Mobile from, object obj) - { - if (!CheckAlive()) - return; - - ToggleItemInsurance_Callback(from, obj as Item, true); - } - - private void ToggleItemInsurance_Callback(Mobile from, Item item, bool target) - { - if (item?.IsChildOf(this) != true) - { - if (target) - BeginTarget(-1, false, TargetFlags.None, ToggleItemInsurance_Callback); - - SendLocalizedMessage(1060871, "", - 0x23); // You can only insure items that you have equipped or that are in your backpack - } - else if (item.Insured) - { - item.Insured = false; - - SendLocalizedMessage(1060874, "", 0x35); // You cancel the insurance on the item - - if (target) - { - BeginTarget(-1, false, TargetFlags.None, ToggleItemInsurance_Callback); - SendLocalizedMessage(1060868, "", - 0x23); // Target the item you wish to toggle insurance status on to cancel - } - } - else if (!CanInsure(item)) - { - if (target) - BeginTarget(-1, false, TargetFlags.None, ToggleItemInsurance_Callback); - - SendLocalizedMessage(1060869, "", 0x23); // You cannot insure that - } - else - { - if (!item.PaidInsurance) - { - int cost = GetInsuranceCost(item); - - if (Banker.Withdraw(from, cost)) - { - SendLocalizedMessage(1060398, - cost.ToString()); // ~1_AMOUNT~ gold has been withdrawn from your bank box. - item.PaidInsurance = true; - } - else - { - SendLocalizedMessage(1061079, "", 0x23); // You lack the funds to purchase the insurance - return; - } - } - - item.Insured = true; - - SendLocalizedMessage(1060873, "", 0x23); // You have insured the item - - if (target) - { - BeginTarget(-1, false, TargetFlags.None, ToggleItemInsurance_Callback); - SendLocalizedMessage(1060868, "", - 0x23); // Target the item you wish to toggle insurance status on to cancel - } - } - } - - private void AutoRenewInventoryInsurance() - { - if (!CheckAlive()) - return; - - SendLocalizedMessage(1060881, "", - 0x23); // You have selected to automatically reinsure all insured items upon death - AutoRenewInsurance = true; - } - - private void CancelRenewInventoryInsurance() - { - if (!CheckAlive()) - return; - - if (Core.SE) - { - if (!HasGump()) - SendGump(new CancelRenewInventoryInsuranceGump(this, null)); - } - else - { - SendLocalizedMessage(1061075, "", - 0x23); // You have cancelled automatically reinsuring all insured items upon death - AutoRenewInsurance = false; - } - } - - private class CancelRenewInventoryInsuranceGump : Gump - { - private readonly ItemInsuranceMenuGump m_InsuranceGump; - private readonly PlayerMobile m_Player; - - public CancelRenewInventoryInsuranceGump(PlayerMobile player, ItemInsuranceMenuGump insuranceGump) : base(250, - 200) - { - m_Player = player; - m_InsuranceGump = insuranceGump; - - AddBackground(0, 0, 240, 142, 0x13BE); - AddImageTiled(6, 6, 228, 100, 0xA40); - AddImageTiled(6, 116, 228, 20, 0xA40); - AddAlphaRegion(6, 6, 228, 142); - - AddHtmlLocalized(8, 8, 228, 100, 1071021, 0x7FFF); // You are about to disable inventory insurance auto-renewal. - - AddButton(6, 116, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(40, 118, 450, 20, 1060051, 0x7FFF); // CANCEL - - AddButton(114, 116, 0xFA5, 0xFA7, 1); - AddHtmlLocalized(148, 118, 450, 20, 1071022, 0x7FFF); // DISABLE IT! - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (!m_Player.CheckAlive()) - return; - - if (info.ButtonID == 1) - { - m_Player.SendLocalizedMessage(1061075, "", - 0x23); // You have cancelled automatically reinsuring all insured items upon death - m_Player.AutoRenewInsurance = false; - } - else - { - m_Player.SendLocalizedMessage(1042021); // Cancelled. - } - - if (m_InsuranceGump != null) - m_Player.SendGump(m_InsuranceGump.NewInstance()); - } - } - - private void OpenItemInsuranceMenu() - { - if (!CheckAlive()) - return; - - List items = new List(); - - foreach (Item item in Items) - if (DisplayInItemInsuranceGump(item)) - items.Add(item); - - Container pack = Backpack; - - if (pack != null) - items.AddRange(pack.FindItemsByType(DisplayInItemInsuranceGump)); - - // TODO: Investigate item sorting - - CloseGump(); - - if (items.Count == 0) - SendLocalizedMessage(1114915, "", 0x35); // None of your current items meet the requirements for insurance. - else - SendGump(new ItemInsuranceMenuGump(this, items.ToArray())); - } - - private bool DisplayInItemInsuranceGump(Item item) => (item.Visible || AccessLevel >= AccessLevel.GameMaster) && (item.Insured || CanInsure(item)); - - private class ItemInsuranceMenuGump : Gump - { - private readonly PlayerMobile m_From; - private readonly bool[] m_Insure; - private readonly Item[] m_Items; - private readonly int m_Page; - - public ItemInsuranceMenuGump(PlayerMobile from, Item[] items, bool[] insure = null, int page = 0) - : base(25, 50) - { - m_From = from; - m_Items = items; - - if (insure == null) - { - insure = new bool[items.Length]; - - for (int i = 0; i < items.Length; ++i) - insure[i] = items[i].Insured; - } - - m_Insure = insure; - m_Page = page; - - AddPage(0); - - AddBackground(0, 0, 520, 510, 0x13BE); - AddImageTiled(10, 10, 500, 30, 0xA40); - AddImageTiled(10, 50, 500, 355, 0xA40); - AddImageTiled(10, 415, 500, 80, 0xA40); - AddAlphaRegion(10, 10, 500, 485); - - AddButton(15, 470, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(50, 472, 80, 20, 1011012, 0x7FFF); // CANCEL - - if (from.AutoRenewInsurance) - AddButton(360, 10, 9723, 9724, 1); - else - AddButton(360, 10, 9720, 9722, 1); - - AddHtmlLocalized(395, 14, 105, 20, 1114122, 0x7FFF); // AUTO REINSURE - - AddButton(395, 470, 0xFA5, 0xFA6, 2); - AddHtmlLocalized(430, 472, 50, 20, 1006044, 0x7FFF); // OK - - AddHtmlLocalized(10, 14, 150, 20, 1114121, 0x7FFF); //
ITEM INSURANCE MENU
- - AddHtmlLocalized(45, 54, 70, 20, 1062214, 0x7FFF); // Item - AddHtmlLocalized(250, 54, 70, 20, 1061038, 0x7FFF); // Cost - AddHtmlLocalized(400, 54, 70, 20, 1114311, 0x7FFF); // Insured - - int balance = Banker.GetBalance(from); - int cost = 0; - - for (int i = 0; i < items.Length; ++i) - if (insure[i]) - cost += GetInsuranceCost(items[i]); - - AddHtmlLocalized(15, 420, 300, 20, 1114310, 0x7FFF); // GOLD AVAILABLE: - AddLabel(215, 420, 0x481, balance.ToString()); - AddHtmlLocalized(15, 435, 300, 20, 1114123, 0x7FFF); // TOTAL COST OF INSURANCE: - AddLabel(215, 435, 0x481, cost.ToString()); - - if (cost != 0) - { - AddHtmlLocalized(15, 450, 300, 20, 1114125, 0x7FFF); // NUMBER OF DEATHS PAYABLE: - AddLabel(215, 450, 0x481, (balance / cost).ToString()); - } - - for (int i = page * 4, y = 72; i < (page + 1) * 4 && i < items.Length; ++i, y += 75) - { - Item item = items[i]; - Rectangle2D b = ItemBounds.Table[item.ItemID]; - - AddImageTiledButton(40, y, 0x918, 0x918, 0, GumpButtonType.Page, 0, item.ItemID, item.Hue, - 40 - b.Width / 2 - b.X, 30 - b.Height / 2 - b.Y); - AddItemProperty(item.Serial); - - if (insure[i]) - { - AddButton(400, y, 9723, 9724, 100 + i); - AddLabel(250, y, 0x481, GetInsuranceCost(item).ToString()); - } - else - { - AddButton(400, y, 9720, 9722, 100 + i); - AddLabel(250, y, 0x66C, GetInsuranceCost(item).ToString()); - } - } - - if (page >= 1) - { - AddButton(15, 380, 0xFAE, 0xFAF, 3); - AddHtmlLocalized(50, 380, 450, 20, 1044044, 0x7FFF); // PREV PAGE - } - - if ((page + 1) * 4 < items.Length) - { - AddButton(400, 380, 0xFA5, 0xFA7, 4); - AddHtmlLocalized(435, 380, 70, 20, 1044045, 0x7FFF); // NEXT PAGE - } - } - - public ItemInsuranceMenuGump NewInstance() => new ItemInsuranceMenuGump(m_From, m_Items, m_Insure, m_Page); - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 0 || !m_From.CheckAlive()) - return; - - switch (info.ButtonID) - { - case 1: // Auto Reinsure - { - if (m_From.AutoRenewInsurance) - { - if (!m_From.HasGump()) - m_From.SendGump(new CancelRenewInventoryInsuranceGump(m_From, this)); - } - else - { - m_From.AutoRenewInventoryInsurance(); - m_From.SendGump(new ItemInsuranceMenuGump(m_From, m_Items, m_Insure, m_Page)); - } - - break; - } - case 2: // OK - { - m_From.SendGump(new ItemInsuranceMenuConfirmGump(m_From, m_Items, m_Insure, m_Page)); - - break; - } - case 3: // Prev - { - if (m_Page >= 1) - m_From.SendGump(new ItemInsuranceMenuGump(m_From, m_Items, m_Insure, m_Page - 1)); - - break; - } - case 4: // Next - { - if ((m_Page + 1) * 4 < m_Items.Length) - m_From.SendGump(new ItemInsuranceMenuGump(m_From, m_Items, m_Insure, m_Page + 1)); - - break; - } - default: - { - int idx = info.ButtonID - 100; - - if (idx >= 0 && idx < m_Items.Length) - m_Insure[idx] = !m_Insure[idx]; - - m_From.SendGump(new ItemInsuranceMenuGump(m_From, m_Items, m_Insure, m_Page)); - - break; + if (!item.PaidInsurance) + { + var cost = GetInsuranceCost(item); + + if (Banker.Withdraw(from, cost)) + { + SendLocalizedMessage( + 1060398, + cost.ToString() + ); // ~1_AMOUNT~ gold has been withdrawn from your bank box. + item.PaidInsurance = true; + } + else + { + SendLocalizedMessage(1061079, "", 0x23); // You lack the funds to purchase the insurance + return; + } + } + + item.Insured = true; + + SendLocalizedMessage(1060873, "", 0x23); // You have insured the item + + if (target) + { + BeginTarget(-1, false, TargetFlags.None, ToggleItemInsurance_Callback); + SendLocalizedMessage( + 1060868, + "", + 0x23 + ); // Target the item you wish to toggle insurance status on to cancel + } } } - } - } - private class ItemInsuranceMenuConfirmGump : Gump - { - private readonly PlayerMobile m_From; - private readonly bool[] m_Insure; - private readonly Item[] m_Items; - private readonly int m_Page; - - public ItemInsuranceMenuConfirmGump(PlayerMobile from, Item[] items, bool[] insure, int page) - : base(250, 200) - { - m_From = from; - m_Items = items; - m_Insure = insure; - m_Page = page; - - AddBackground(0, 0, 240, 142, 0x13BE); - AddImageTiled(6, 6, 228, 100, 0xA40); - AddImageTiled(6, 116, 228, 20, 0xA40); - AddAlphaRegion(6, 6, 228, 142); - - AddHtmlLocalized(8, 8, 228, 100, 1114300, 0x7FFF); // Do you wish to insure all newly selected items? - - AddButton(6, 116, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(40, 118, 450, 20, 1060051, 0x7FFF); // CANCEL - - AddButton(114, 116, 0xFA5, 0xFA7, 1); - AddHtmlLocalized(148, 118, 450, 20, 1073996, 0x7FFF); // ACCEPT - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (!m_From.CheckAlive()) - return; - - if (info.ButtonID == 1) + private void AutoRenewInventoryInsurance() { - for (int i = 0; i < m_Items.Length; ++i) - { - Item item = m_Items[i]; + if (!CheckAlive()) + return; - if (item.Insured != m_Insure[i]) - m_From.ToggleItemInsurance_Callback(m_From, item, false); - } + SendLocalizedMessage( + 1060881, + "", + 0x23 + ); // You have selected to automatically reinsure all insured items upon death + AutoRenewInsurance = true; } - else + + private void CancelRenewInventoryInsurance() { - m_From.SendLocalizedMessage(1042021); // Cancelled. - m_From.SendGump(new ItemInsuranceMenuGump(m_From, m_Items, m_Insure, m_Page)); - } - } - } - - private void ToggleQuestItem() - { - if (!CheckAlive()) - return; - - ToggleQuestItemTarget(); - } - - private void ToggleQuestItemTarget() - { - BaseQuestGump.CloseOtherGumps(this); - CloseGump(); - CloseGump(); - CloseGump(); - // CloseGump( typeof( UnknownGump802 ) ); - // CloseGump( typeof( UnknownGump804 ) ); - - BeginTarget(-1, false, TargetFlags.None, ToggleQuestItem_Callback); - SendLocalizedMessage(1072352); // Target the item you wish to toggle Quest Item status on to cancel - } - - private void ToggleQuestItem_Callback(Mobile from, object obj) - { - if (!CheckAlive()) - return; - - if (!(obj is Item item)) - return; - - if (from.Backpack == null || item.Parent != from.Backpack) - { - SendLocalizedMessage( - 1074769); // An item must be in your backpack (and not in a container within) to be toggled as a quest item. - } - else if (item.QuestItem) - { - item.QuestItem = false; - SendLocalizedMessage(1072354); // You remove Quest Item status from the item - } - else if (MLQuestSystem.MarkQuestItem(this, item)) - { - SendLocalizedMessage(1072353); // You set the item to Quest Item status - } - else - { - SendLocalizedMessage(1072355, "", 0x23); // That item does not match any of your quest criteria - } - - ToggleQuestItemTarget(); - } - - private DateTime[] m_StuckMenuUses; - - public bool CanUseStuckMenu() - { - if (m_StuckMenuUses == null) return true; - - for (int i = 0; i < m_StuckMenuUses.Length; ++i) - if (DateTime.UtcNow - m_StuckMenuUses[i] > TimeSpan.FromDays(1.0)) - return true; - - return false; - } - - public void UsedStuckMenu() - { - if (m_StuckMenuUses == null) m_StuckMenuUses = new DateTime[2]; - - for (int i = 0; i < m_StuckMenuUses.Length; ++i) - if (DateTime.UtcNow - m_StuckMenuUses[i] > TimeSpan.FromDays(1.0)) - { - m_StuckMenuUses[i] = DateTime.UtcNow; - return; - } - } - - public override ApplyPoisonResult ApplyPoison(Mobile from, Poison poison) - { - if (!Alive) - return ApplyPoisonResult.Immune; - - if (EvilOmenSpell.TryEndEffect(this)) - poison = PoisonImpl.IncreaseLevel(poison); - - ApplyPoisonResult result = base.ApplyPoison(from, poison); - - if (from != null && result == ApplyPoisonResult.Poisoned && PoisonTimer is PoisonImpl.PoisonTimer timer) - timer.From = from; - - return result; - } - - public override bool CheckPoisonImmunity(Mobile from, Poison poison) => - Young && (DuelContext?.Started != true || DuelContext.Finished) || base.CheckPoisonImmunity(from, poison); - - public override void OnPoisonImmunity(Mobile from, Poison poison) - { - if (Young && (DuelContext?.Started != true || DuelContext.Finished)) - SendLocalizedMessage( - 502808); // You would have been poisoned, were you not new to the land of Britannia. Be careful in the future. - else - base.OnPoisonImmunity(from, poison); - } - - private DuelPlayer m_DuelPlayer; - - public DuelContext DuelContext { get; private set; } - - public DuelPlayer DuelPlayer - { - get => m_DuelPlayer; - set - { - bool wasInTourney = DuelContext?.Finished == false && DuelContext.m_Tournament != null; - - m_DuelPlayer = value; - - DuelContext = m_DuelPlayer?.Participant.Context; - - bool isInTourney = DuelContext?.Finished == false && DuelContext.m_Tournament != null; - - if (wasInTourney != isInTourney) - SendEverything(); - } - } - - public QuestSystem Quest { get; set; } - - public List DoneQuests { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public SolenFriendship SolenFriendship { get; set; } - - public bool ChangedMyRunUO { get; set; } - - public override void OnKillsChange(int oldValue) - { - if (Young && Kills > oldValue) ((Account)Account)?.RemoveYoungStatus(0); - } - - public override void OnGenderChanged(bool oldFemale) - { - } - - public override void OnGuildChange(BaseGuild oldGuild) - { - } - - public override void OnGuildTitleChange(string oldTitle) - { - } - - public override void OnKarmaChange(int oldValue) - { - } - - public override void OnFameChange(int oldValue) - { - } - - public override void OnSkillChange(SkillName skill, double oldBase) - { - if (Young && SkillsTotal >= 4500) - ((Account)Account) - ?.RemoveYoungStatus( - 1019036); // You have successfully obtained a respectable skill level, and have outgrown your status as a young player! - - if (MLQuestSystem.Enabled) - MLQuestSystem.HandleSkillGain(this, skill); - } - - public override void OnAccessLevelChanged(AccessLevel oldLevel) - { - IgnoreMobiles = AccessLevel != AccessLevel.Player; - } - - public override void OnRawStatChange(StatType stat, int oldValue) - { - } - - public override void OnDelete() - { - ReceivedHonorContext?.Cancel(); - SentHonorContext?.Cancel(); - } - - private static readonly bool FastwalkPrevention = true; // Is fastwalk prevention enabled? - private static readonly int FastwalkThreshold = 400; // Fastwalk prevention will become active after 0.4 seconds - - private long m_NextMovementTime; - private bool m_HasMoved; - - public virtual bool UsesFastwalkPrevention => AccessLevel < AccessLevel.Counselor; - - public override int ComputeMovementSpeed(Direction dir, bool checkTurning) - { - if (checkTurning && (dir & Direction.Mask) != (Direction & Direction.Mask)) - return RunMount; // We are NOT actually moving (just a direction change) - - TransformContext context = TransformationSpellHelper.GetContext(this); - - if (context?.Type == typeof(ReaperFormSpell)) - return WalkFoot; - - bool running = (dir & Direction.Running) != 0; - - bool onHorse = Mount != null; - - AnimalFormContext animalContext = AnimalForm.GetContext(this); - - if (onHorse || animalContext?.SpeedBoost == true) - return running ? RunMount : WalkMount; - - return running ? RunFoot : WalkFoot; - } - - public static TimeSpan MovementThrottle_Callback(NetState ns) - { - if (!(ns.Mobile is PlayerMobile pm) || !pm.UsesFastwalkPrevention) - return TimeSpan.Zero; - - if (!pm.m_HasMoved) - { - // has not yet moved - pm.m_NextMovementTime = Core.TickCount; - pm.m_HasMoved = true; - return TimeSpan.Zero; - } - - long ts = pm.m_NextMovementTime - Core.TickCount; - - if (ts < 0) - { - // been a while since we've last moved - pm.m_NextMovementTime = Core.TickCount; - return TimeSpan.Zero; - } - - return ts < FastwalkThreshold ? TimeSpan.Zero : TimeSpan.FromTicks(ts); - } - - private Type m_EnemyOfOneType; - - public Type EnemyOfOneType - { - get => m_EnemyOfOneType; - set - { - Type oldType = m_EnemyOfOneType; - Type newType = value; - - if (oldType == newType) - return; - - m_EnemyOfOneType = value; - - DeltaEnemies(oldType, newType); - } - } - - public bool WaitingForEnemy { get; set; } - - private void DeltaEnemies(Type oldType, Type newType) - { - foreach (Mobile m in GetMobilesInRange(18)) - { - Type t = m.GetType(); - - if (t == oldType || t == newType) - { - NetState ns = NetState; - - if (ns != null) - { - if (ns.StygianAbyss) - ns.Send(new MobileMoving(m, Notoriety.Compute(this, m))); + if (!CheckAlive()) + return; + + if (Core.SE) + { + if (!HasGump()) + SendGump(new CancelRenewInventoryInsuranceGump(this, null)); + } else - ns.Send(new MobileMovingOld(m, Notoriety.Compute(this, m))); - } - } - } - } - - private int m_HairModID = -1, m_HairModHue; - private int m_BeardModID = -1, m_BeardModHue; - - public void SetHairMods(int hairID, int beardID) - { - if (hairID == -1) - InternalRestoreHair(true, ref m_HairModID, ref m_HairModHue); - else if (hairID != -2) - InternalChangeHair(true, hairID, ref m_HairModID, ref m_HairModHue); - - if (beardID == -1) - InternalRestoreHair(false, ref m_BeardModID, ref m_BeardModHue); - else if (beardID != -2) - InternalChangeHair(false, beardID, ref m_BeardModID, ref m_BeardModHue); - } - - private void CreateHair(bool hair, int id, int hue) - { - if (hair) - { - // TODO Verification? - HairItemID = id; - HairHue = hue; - } - else - { - FacialHairItemID = id; - FacialHairHue = hue; - } - } - - private void InternalRestoreHair(bool hair, ref int id, ref int hue) - { - if (id == -1) - return; - - if (hair) - HairItemID = 0; - else - FacialHairItemID = 0; - - // if (id != 0) - CreateHair(hair, id, hue); - - id = -1; - hue = 0; - } - - private void InternalChangeHair(bool hair, int id, ref int storeID, ref int storeHue) - { - if (storeID == -1) - { - storeID = hair ? HairItemID : FacialHairItemID; - storeHue = hair ? HairHue : FacialHairHue; - } - - CreateHair(hair, id, 0); - } - - public DateTime LastSacrificeGain { get; set; } - - public DateTime LastSacrificeLoss { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int AvailableResurrects { get; set; } - - private DateTime m_NextJustAward; - - public DateTime LastJusticeLoss { get; set; } - - public List JusticeProtectors { get; set; } - - public DateTime LastCompassionLoss { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime NextCompassionDay { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int CompassionGains { get; set; } - - public DateTime LastValorLoss { get; set; } - - public DateTime m_hontime; - - public DateTime LastHonorLoss { get; set; } - - public DateTime LastHonorUse { get; set; } - - public bool HonorActive { get; set; } - - public HonorContext ReceivedHonorContext { get; set; } - - public HonorContext SentHonorContext { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Young - { - get => GetFlag(PlayerFlag.Young); - set - { - SetFlag(PlayerFlag.Young, value); - InvalidateProperties(); - } - } - - public override string ApplyNameSuffix(string suffix) - { - if (Young) suffix = suffix.Length == 0 ? "(Young)" : $"{suffix} (Young)"; - - if (EthicPlayer != null) - { - if (suffix.Length == 0) - suffix = EthicPlayer.Ethic.Definition.Adjunct.String; - else - suffix = $"{suffix} {EthicPlayer.Ethic.Definition.Adjunct.String}"; - } - - if (Core.ML && Map == Faction.Facet) - { - Faction faction = Faction.Find(this); - - if (faction != null) - { - string adjunct = $"[{faction.Definition.Abbreviation}]"; - suffix = suffix.Length == 0 ? adjunct : $"{suffix} {adjunct}"; - } - } - - return base.ApplyNameSuffix(suffix); - } - - public override TimeSpan GetLogoutDelay() - { - if (Young || BedrollLogout || TestCenter.Enabled) - return TimeSpan.Zero; - - return base.GetLogoutDelay(); - } - - private DateTime m_LastYoungMessage = DateTime.MinValue; - - public bool CheckYoungProtection(Mobile from) - { - if (!Young) - return false; - - if (Region is BaseRegion region && !region.YoungProtected) - return false; - - if (from is BaseCreature creature && creature.IgnoreYoungProtection) - return false; - - if (Quest?.IgnoreYoungProtection(from) == true) - return false; - - if (DateTime.UtcNow - m_LastYoungMessage > TimeSpan.FromMinutes(1.0)) - { - m_LastYoungMessage = DateTime.UtcNow; - SendLocalizedMessage( - 1019067); // A monster looks at you menacingly but does not attack. You would be under attack now if not for your status as a new citizen of Britannia. - } - - return true; - } - - private DateTime m_LastYoungHeal = DateTime.MinValue; - - public bool CheckYoungHealTime() - { - if (DateTime.UtcNow - m_LastYoungHeal > TimeSpan.FromMinutes(5.0)) - { - m_LastYoungHeal = DateTime.UtcNow; - return true; - } - - return false; - } - - private static readonly Point3D[] m_TrammelDeathDestinations = - { - new Point3D(1481, 1612, 20), - new Point3D(2708, 2153, 0), - new Point3D(2249, 1230, 0), - new Point3D(5197, 3994, 37), - new Point3D(1412, 3793, 0), - new Point3D(3688, 2232, 20), - new Point3D(2578, 604, 0), - new Point3D(4397, 1089, 0), - new Point3D(5741, 3218, -2), - new Point3D(2996, 3441, 15), - new Point3D(624, 2225, 0), - new Point3D(1916, 2814, 0), - new Point3D(2929, 854, 0), - new Point3D(545, 967, 0), - new Point3D(3665, 2587, 0) - }; - - private static readonly Point3D[] m_IlshenarDeathDestinations = - { - new Point3D(1216, 468, -13), - new Point3D(723, 1367, -60), - new Point3D(745, 725, -28), - new Point3D(281, 1017, 0), - new Point3D(986, 1011, -32), - new Point3D(1175, 1287, -30), - new Point3D(1533, 1341, -3), - new Point3D(529, 217, -44), - new Point3D(1722, 219, 96) - }; - - private static readonly Point3D[] m_MalasDeathDestinations = - { - new Point3D(2079, 1376, -70), - new Point3D(944, 519, -71) - }; - - private static readonly Point3D[] m_TokunoDeathDestinations = - { - new Point3D(1166, 801, 27), - new Point3D(782, 1228, 25), - new Point3D(268, 624, 15) - }; - - public bool YoungDeathTeleport() - { - if (Region.IsPartOf() - || Region.IsPartOf("Samurai start location") - || Region.IsPartOf("Ninja start location") - || Region.IsPartOf("Ninja cave")) - return false; - - Point3D loc; - Map map; - - DungeonRegion dungeon = Region.GetRegion(); - if (dungeon != null && dungeon.EntranceLocation != Point3D.Zero) - { - loc = dungeon.EntranceLocation; - map = dungeon.EntranceMap; - } - else - { - loc = Location; - map = Map; - } - - Point3D[] list; - - if (map == Map.Trammel) - list = m_TrammelDeathDestinations; - else if (map == Map.Ilshenar) - list = m_IlshenarDeathDestinations; - else if (map == Map.Malas) - list = m_MalasDeathDestinations; - else if (map == Map.Tokuno) - list = m_TokunoDeathDestinations; - else - return false; - - Point3D dest = Point3D.Zero; - int sqDistance = int.MaxValue; - - for (int i = 0; i < list.Length; i++) - { - Point3D curDest = list[i]; - - int width = loc.X - curDest.X; - int height = loc.Y - curDest.Y; - int curSqDistance = width * width + height * height; - - if (curSqDistance < sqDistance) - { - dest = curDest; - sqDistance = curSqDistance; - } - } - - MoveToWorld(dest, map); - return true; - } - - private void SendYoungDeathNotice() - { - SendGump(new YoungDeathNotice()); - } - - public SpeechLog SpeechLog { get; private set; } - - public override void OnSpeech(SpeechEventArgs e) - { - if (SpeechLog.Enabled && NetState != null) - { - if (SpeechLog == null) - SpeechLog = new SpeechLog(); - - SpeechLog.Add(e.Mobile, e.Speech); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public bool DisplayChampionTitle - { - get => GetFlag(PlayerFlag.DisplayChampionTitle); - set => SetFlag(PlayerFlag.DisplayChampionTitle, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public ChampionTitleInfo ChampionTitles { get; private set; } - - private void ToggleChampionTitleDisplay() - { - if (!CheckAlive()) - return; - - if (DisplayChampionTitle) - SendLocalizedMessage(1062419, "", 0x23); // You have chosen to hide your monster kill title. - else - SendLocalizedMessage(1062418, "", 0x23); // You have chosen to display your monster kill title. - - DisplayChampionTitle = !DisplayChampionTitle; - } - - [PropertyObject] - public class ChampionTitleInfo - { - public const int LossAmount = 90; - public static TimeSpan LossDelay = TimeSpan.FromDays(1.0); - - private TitleInfo[] m_Values; - - public ChampionTitleInfo() - { - } - - public ChampionTitleInfo(IGenericReader reader) - { - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 0: { - Harrower = reader.ReadEncodedInt(); - - int length = reader.ReadEncodedInt(); - m_Values = new TitleInfo[length]; - - for (int i = 0; i < length; i++) m_Values[i] = new TitleInfo(reader); - - if (m_Values.Length != ChampionSpawnInfo.Table.Length) - { - TitleInfo[] oldValues = m_Values; - m_Values = new TitleInfo[ChampionSpawnInfo.Table.Length]; - - for (int i = 0; i < m_Values.Length && i < oldValues.Length; i++) m_Values[i] = oldValues[i]; - } - - break; + SendLocalizedMessage( + 1061075, + "", + 0x23 + ); // You have cancelled automatically reinsuring all insured items upon death + AutoRenewInsurance = false; } } - } - [CommandProperty(AccessLevel.GameMaster)] - public int Pestilence - { - get => GetValue(ChampionSpawnType.Pestilence); - set => SetValue(ChampionSpawnType.Pestilence, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Abyss - { - get => GetValue(ChampionSpawnType.Abyss); - set => SetValue(ChampionSpawnType.Abyss, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Arachnid - { - get => GetValue(ChampionSpawnType.Arachnid); - set => SetValue(ChampionSpawnType.Arachnid, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public int ColdBlood - { - get => GetValue(ChampionSpawnType.ColdBlood); - set => SetValue(ChampionSpawnType.ColdBlood, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public int ForestLord - { - get => GetValue(ChampionSpawnType.ForestLord); - set => SetValue(ChampionSpawnType.ForestLord, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public int SleepingDragon - { - get => GetValue(ChampionSpawnType.SleepingDragon); - set => SetValue(ChampionSpawnType.SleepingDragon, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public int UnholyTerror - { - get => GetValue(ChampionSpawnType.UnholyTerror); - set => SetValue(ChampionSpawnType.UnholyTerror, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public int VerminHorde - { - get => GetValue(ChampionSpawnType.VerminHorde); - set => SetValue(ChampionSpawnType.VerminHorde, value); - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Harrower { get; set; } - - public int GetValue(ChampionSpawnType type) => GetValue((int)type); - - public void SetValue(ChampionSpawnType type, int value) - { - SetValue((int)type, value); - } - - public void Award(ChampionSpawnType type, int value) - { - Award((int)type, value); - } - - public int GetValue(int index) - { - if (m_Values == null || index < 0 || index >= m_Values.Length) - return 0; - - m_Values[index] ??= new TitleInfo(); - - return m_Values[index].Value; - } - - public DateTime GetLastDecay(int index) - { - if (m_Values == null || index < 0 || index >= m_Values.Length) - return DateTime.MinValue; - - m_Values[index] ??= new TitleInfo(); - - return m_Values[index].LastDecay; - } - - public void SetValue(int index, int value) - { - m_Values ??= new TitleInfo[ChampionSpawnInfo.Table.Length]; - - if (index < 0 || index >= m_Values.Length) - return; - - m_Values[index] ??= new TitleInfo(); - - m_Values[index].Value = Math.Max(value, 0); - } - - public void Award(int index, int value) - { - m_Values ??= new TitleInfo[ChampionSpawnInfo.Table.Length]; - - if (index < 0 || index >= m_Values.Length || value <= 0) - return; - - m_Values[index] ??= new TitleInfo(); - - m_Values[index].Value += value; - } - - public void Atrophy(int index, int value) - { - m_Values ??= new TitleInfo[ChampionSpawnInfo.Table.Length]; - - if (index < 0 || index >= m_Values.Length || value <= 0) - return; - - m_Values[index] ??= new TitleInfo(); - - int before = m_Values[index].Value; - - m_Values[index].Value -= Math.Min(value, m_Values[index].Value); - - if (before != m_Values[index].Value) - m_Values[index].LastDecay = DateTime.UtcNow; - } - - public override string ToString() => "..."; - - public static void Serialize(IGenericWriter writer, ChampionTitleInfo titles) - { - writer.WriteEncodedInt(0); // version - - writer.WriteEncodedInt(titles.Harrower); - - int length = titles.m_Values.Length; - writer.WriteEncodedInt(length); - - for (int i = 0; i < length; i++) + private void OpenItemInsuranceMenu() { - titles.m_Values[i] ??= new TitleInfo(); + if (!CheckAlive()) + return; - TitleInfo.Serialize(writer, titles.m_Values[i]); + var items = new List(); + + foreach (var item in Items) + if (DisplayInItemInsuranceGump(item)) + items.Add(item); + + var pack = Backpack; + + if (pack != null) + items.AddRange(pack.FindItemsByType(DisplayInItemInsuranceGump)); + + // TODO: Investigate item sorting + + CloseGump(); + + if (items.Count == 0) + SendLocalizedMessage(1114915, "", 0x35); // None of your current items meet the requirements for insurance. + else + SendGump(new ItemInsuranceMenuGump(this, items.ToArray())); } - } - public static void CheckAtrophy(PlayerMobile pm) - { - ChampionTitleInfo t = pm.ChampionTitles; - if (t == null) - return; + private bool DisplayInItemInsuranceGump(Item item) => (item.Visible || AccessLevel >= AccessLevel.GameMaster) && + (item.Insured || CanInsure(item)); - t.m_Values ??= new TitleInfo[ChampionSpawnInfo.Table.Length]; + private void ToggleQuestItem() + { + if (!CheckAlive()) + return; - for (int i = 0; i < t.m_Values.Length; i++) - if (t.GetLastDecay(i) + LossDelay < DateTime.UtcNow) - t.Atrophy(i, LossAmount); - } + ToggleQuestItemTarget(); + } - public static void - AwardHarrowerTitle(PlayerMobile pm) // Called when killing a harrower. Will give a minimum of 1 point. - { - ChampionTitleInfo t = pm.ChampionTitles; - if (t == null) - return; + private void ToggleQuestItemTarget() + { + BaseQuestGump.CloseOtherGumps(this); + CloseGump(); + CloseGump(); + CloseGump(); + // CloseGump( typeof( UnknownGump802 ) ); + // CloseGump( typeof( UnknownGump804 ) ); - t.m_Values ??= new TitleInfo[ChampionSpawnInfo.Table.Length]; + BeginTarget(-1, false, TargetFlags.None, ToggleQuestItem_Callback); + SendLocalizedMessage(1072352); // Target the item you wish to toggle Quest Item status on to cancel + } - int count = 1 + t.m_Values.Count(t1 => t1.Value > 900); + private void ToggleQuestItem_Callback(Mobile from, object obj) + { + if (!CheckAlive()) + return; - t.Harrower = Math.Max(count, t.Harrower); // Harrower titles never decay. - } + if (!(obj is Item item)) + return; - private class TitleInfo - { - public TitleInfo() + if (from.Backpack == null || item.Parent != from.Backpack) + { + SendLocalizedMessage( + 1074769 + ); // An item must be in your backpack (and not in a container within) to be toggled as a quest item. + } + else if (item.QuestItem) + { + item.QuestItem = false; + SendLocalizedMessage(1072354); // You remove Quest Item status from the item + } + else if (MLQuestSystem.MarkQuestItem(this, item)) + { + SendLocalizedMessage(1072353); // You set the item to Quest Item status + } + else + { + SendLocalizedMessage(1072355, "", 0x23); // That item does not match any of your quest criteria + } + + ToggleQuestItemTarget(); + } + + public bool CanUseStuckMenu() + { + if (m_StuckMenuUses == null) return true; + + for (var i = 0; i < m_StuckMenuUses.Length; ++i) + if (DateTime.UtcNow - m_StuckMenuUses[i] > TimeSpan.FromDays(1.0)) + return true; + + return false; + } + + public void UsedStuckMenu() + { + if (m_StuckMenuUses == null) m_StuckMenuUses = new DateTime[2]; + + for (var i = 0; i < m_StuckMenuUses.Length; ++i) + if (DateTime.UtcNow - m_StuckMenuUses[i] > TimeSpan.FromDays(1.0)) + { + m_StuckMenuUses[i] = DateTime.UtcNow; + return; + } + } + + public override ApplyPoisonResult ApplyPoison(Mobile from, Poison poison) + { + if (!Alive) + return ApplyPoisonResult.Immune; + + if (EvilOmenSpell.TryEndEffect(this)) + poison = PoisonImpl.IncreaseLevel(poison); + + var result = base.ApplyPoison(from, poison); + + if (from != null && result == ApplyPoisonResult.Poisoned && PoisonTimer is PoisonImpl.PoisonTimer timer) + timer.From = from; + + return result; + } + + public override bool CheckPoisonImmunity(Mobile from, Poison poison) => + Young && (DuelContext?.Started != true || DuelContext.Finished) || base.CheckPoisonImmunity(from, poison); + + public override void OnPoisonImmunity(Mobile from, Poison poison) + { + if (Young && (DuelContext?.Started != true || DuelContext.Finished)) + SendLocalizedMessage( + 502808 + ); // You would have been poisoned, were you not new to the land of Britannia. Be careful in the future. + else + base.OnPoisonImmunity(from, poison); + } + + public override void OnKillsChange(int oldValue) + { + if (Young && Kills > oldValue) ((Account)Account)?.RemoveYoungStatus(0); + } + + public override void OnGenderChanged(bool oldFemale) { } - public TitleInfo(IGenericReader reader) + public override void OnGuildChange(BaseGuild oldGuild) { - int version = reader.ReadEncodedInt(); - - switch (version) - { - case 0: - { - Value = reader.ReadEncodedInt(); - LastDecay = reader.ReadDateTime(); - break; - } - } } - public int Value { get; set; } - - public DateTime LastDecay { get; set; } - - public static void Serialize(IGenericWriter writer, TitleInfo info) + public override void OnGuildTitleChange(string oldTitle) { - writer.WriteEncodedInt(0); // version - - writer.WriteEncodedInt(info.Value); - writer.Write(info.LastDecay); } - } + + public override void OnKarmaChange(int oldValue) + { + } + + public override void OnFameChange(int oldValue) + { + } + + public override void OnSkillChange(SkillName skill, double oldBase) + { + if (Young && SkillsTotal >= 4500) + ((Account)Account) + ?.RemoveYoungStatus( + 1019036 + ); // You have successfully obtained a respectable skill level, and have outgrown your status as a young player! + + if (MLQuestSystem.Enabled) + MLQuestSystem.HandleSkillGain(this, skill); + } + + public override void OnAccessLevelChanged(AccessLevel oldLevel) + { + IgnoreMobiles = AccessLevel != AccessLevel.Player; + } + + public override void OnRawStatChange(StatType stat, int oldValue) + { + } + + public override void OnDelete() + { + ReceivedHonorContext?.Cancel(); + SentHonorContext?.Cancel(); + } + + public override int ComputeMovementSpeed(Direction dir, bool checkTurning) + { + if (checkTurning && (dir & Direction.Mask) != (Direction & Direction.Mask)) + return RunMount; // We are NOT actually moving (just a direction change) + + var context = TransformationSpellHelper.GetContext(this); + + if (context?.Type == typeof(ReaperFormSpell)) + return WalkFoot; + + var running = (dir & Direction.Running) != 0; + + var onHorse = Mount != null; + + var animalContext = AnimalForm.GetContext(this); + + if (onHorse || animalContext?.SpeedBoost == true) + return running ? RunMount : WalkMount; + + return running ? RunFoot : WalkFoot; + } + + public static TimeSpan MovementThrottle_Callback(NetState ns) + { + if (!(ns.Mobile is PlayerMobile pm) || !pm.UsesFastwalkPrevention) + return TimeSpan.Zero; + + if (!pm.m_HasMoved) + { + // has not yet moved + pm.m_NextMovementTime = Core.TickCount; + pm.m_HasMoved = true; + return TimeSpan.Zero; + } + + var ts = pm.m_NextMovementTime - Core.TickCount; + + if (ts < 0) + { + // been a while since we've last moved + pm.m_NextMovementTime = Core.TickCount; + return TimeSpan.Zero; + } + + return ts < FastwalkThreshold ? TimeSpan.Zero : TimeSpan.FromTicks(ts); + } + + private void DeltaEnemies(Type oldType, Type newType) + { + foreach (var m in GetMobilesInRange(18)) + { + var t = m.GetType(); + + if (t == oldType || t == newType) + { + var ns = NetState; + + if (ns != null) + { + if (ns.StygianAbyss) + ns.Send(new MobileMoving(m, Notoriety.Compute(this, m))); + else + ns.Send(new MobileMovingOld(m, Notoriety.Compute(this, m))); + } + } + } + } + + public void SetHairMods(int hairID, int beardID) + { + if (hairID == -1) + InternalRestoreHair(true, ref m_HairModID, ref m_HairModHue); + else if (hairID != -2) + InternalChangeHair(true, hairID, ref m_HairModID, ref m_HairModHue); + + if (beardID == -1) + InternalRestoreHair(false, ref m_BeardModID, ref m_BeardModHue); + else if (beardID != -2) + InternalChangeHair(false, beardID, ref m_BeardModID, ref m_BeardModHue); + } + + private void CreateHair(bool hair, int id, int hue) + { + if (hair) + { + // TODO Verification? + HairItemID = id; + HairHue = hue; + } + else + { + FacialHairItemID = id; + FacialHairHue = hue; + } + } + + private void InternalRestoreHair(bool hair, ref int id, ref int hue) + { + if (id == -1) + return; + + if (hair) + HairItemID = 0; + else + FacialHairItemID = 0; + + // if (id != 0) + CreateHair(hair, id, hue); + + id = -1; + hue = 0; + } + + private void InternalChangeHair(bool hair, int id, ref int storeID, ref int storeHue) + { + if (storeID == -1) + { + storeID = hair ? HairItemID : FacialHairItemID; + storeHue = hair ? HairHue : FacialHairHue; + } + + CreateHair(hair, id, 0); + } + + public override string ApplyNameSuffix(string suffix) + { + if (Young) suffix = suffix.Length == 0 ? "(Young)" : $"{suffix} (Young)"; + + if (EthicPlayer != null) + { + if (suffix.Length == 0) + suffix = EthicPlayer.Ethic.Definition.Adjunct.String; + else + suffix = $"{suffix} {EthicPlayer.Ethic.Definition.Adjunct.String}"; + } + + if (Core.ML && Map == Faction.Facet) + { + var faction = Faction.Find(this); + + if (faction != null) + { + var adjunct = $"[{faction.Definition.Abbreviation}]"; + suffix = suffix.Length == 0 ? adjunct : $"{suffix} {adjunct}"; + } + } + + return base.ApplyNameSuffix(suffix); + } + + public override TimeSpan GetLogoutDelay() + { + if (Young || BedrollLogout || TestCenter.Enabled) + return TimeSpan.Zero; + + return base.GetLogoutDelay(); + } + + public bool CheckYoungProtection(Mobile from) + { + if (!Young) + return false; + + if (Region is BaseRegion region && !region.YoungProtected) + return false; + + if (from is BaseCreature creature && creature.IgnoreYoungProtection) + return false; + + if (Quest?.IgnoreYoungProtection(from) == true) + return false; + + if (DateTime.UtcNow - m_LastYoungMessage > TimeSpan.FromMinutes(1.0)) + { + m_LastYoungMessage = DateTime.UtcNow; + SendLocalizedMessage( + 1019067 + ); // A monster looks at you menacingly but does not attack. You would be under attack now if not for your status as a new citizen of Britannia. + } + + return true; + } + + public bool CheckYoungHealTime() + { + if (DateTime.UtcNow - m_LastYoungHeal > TimeSpan.FromMinutes(5.0)) + { + m_LastYoungHeal = DateTime.UtcNow; + return true; + } + + return false; + } + + public bool YoungDeathTeleport() + { + if (Region.IsPartOf() + || Region.IsPartOf("Samurai start location") + || Region.IsPartOf("Ninja start location") + || Region.IsPartOf("Ninja cave")) + return false; + + Point3D loc; + Map map; + + var dungeon = Region.GetRegion(); + if (dungeon != null && dungeon.EntranceLocation != Point3D.Zero) + { + loc = dungeon.EntranceLocation; + map = dungeon.EntranceMap; + } + else + { + loc = Location; + map = Map; + } + + Point3D[] list; + + if (map == Map.Trammel) + list = m_TrammelDeathDestinations; + else if (map == Map.Ilshenar) + list = m_IlshenarDeathDestinations; + else if (map == Map.Malas) + list = m_MalasDeathDestinations; + else if (map == Map.Tokuno) + list = m_TokunoDeathDestinations; + else + return false; + + var dest = Point3D.Zero; + var sqDistance = int.MaxValue; + + for (var i = 0; i < list.Length; i++) + { + var curDest = list[i]; + + var width = loc.X - curDest.X; + var height = loc.Y - curDest.Y; + var curSqDistance = width * width + height * height; + + if (curSqDistance < sqDistance) + { + dest = curDest; + sqDistance = curSqDistance; + } + } + + MoveToWorld(dest, map); + return true; + } + + private void SendYoungDeathNotice() + { + SendGump(new YoungDeathNotice()); + } + + public override void OnSpeech(SpeechEventArgs e) + { + if (SpeechLog.Enabled && NetState != null) + { + if (SpeechLog == null) + SpeechLog = new SpeechLog(); + + SpeechLog.Add(e.Mobile, e.Speech); + } + } + + private void ToggleChampionTitleDisplay() + { + if (!CheckAlive()) + return; + + if (DisplayChampionTitle) + SendLocalizedMessage(1062419, "", 0x23); // You have chosen to hide your monster kill title. + else + SendLocalizedMessage(1062418, "", 0x23); // You have chosen to display your monster kill title. + + DisplayChampionTitle = !DisplayChampionTitle; + } + + public virtual bool HasRecipe(Recipe r) => r != null && HasRecipe(r.ID); + + public virtual bool HasRecipe(int recipeID) => m_AcquiredRecipes.TryGetValue(recipeID, out var value) && value; + + public virtual void AcquireRecipe(Recipe r) + { + if (r != null) + AcquireRecipe(r.ID); + } + + public virtual void AcquireRecipe(int recipeID) + { + m_AcquiredRecipes ??= new Dictionary(); + + m_AcquiredRecipes[recipeID] = true; + } + + public virtual void ResetRecipes() + { + m_AcquiredRecipes = null; + } + + public void ResendBuffs() + { + if (!BuffInfo.Enabled || m_BuffTable == null) + return; + + if (NetState?.BuffIcon == true) + foreach (var info in m_BuffTable.Values) + NetState.Send(new AddBuffPacket(this, info)); + } + + public void AddBuff(BuffInfo b) + { + if (!BuffInfo.Enabled || b == null) + return; + + RemoveBuff(b); // Check & subsequently remove the old one. + + m_BuffTable ??= new Dictionary(); + + m_BuffTable.Add(b.ID, b); + + if (NetState?.BuffIcon == true) + NetState.Send(new AddBuffPacket(this, b)); + } + + public void RemoveBuff(BuffInfo b) + { + if (b == null) + return; + + RemoveBuff(b.ID); + } + + public void RemoveBuff(BuffIcon b) + { + if (m_BuffTable?.ContainsKey(b) != true) + return; + + var info = m_BuffTable[b]; + + if (info.Timer?.Running == true) + info.Timer.Stop(); + + m_BuffTable.Remove(b); + + if (NetState?.BuffIcon == true) + NetState.Send(new RemoveBuffPacket(this, b)); + + if (m_BuffTable.Count <= 0) + m_BuffTable = null; + } + + private class CountAndTimeStamp + { + private int m_Count; + + public DateTime TimeStamp { get; private set; } + + public int Count + { + get => m_Count; + set + { + m_Count = value; + TimeStamp = DateTime.UtcNow; + } + } + } + + private class MountBlock + { + public readonly Timer m_Timer; + public readonly BlockMountType m_Type; + + public MountBlock(TimeSpan duration, BlockMountType type, Mobile mobile) + { + m_Type = type; + + m_Timer = Timer.DelayCall(duration, RemoveBlock, mobile); + } + + private void RemoveBlock(Mobile mobile) + { + if (mobile is PlayerMobile pm) + pm.m_MountBlock = null; + } + } + + private delegate void ContextCallback(); + + private class CallbackEntry : ContextMenuEntry + { + private readonly ContextCallback m_Callback; + + public CallbackEntry(int number, ContextCallback callback) : this(number, -1, callback) + { + } + + public CallbackEntry(int number, int range, ContextCallback callback) : base(number, range) => + m_Callback = callback; + + public override void OnClick() + { + m_Callback?.Invoke(); + } + } + + private class CancelRenewInventoryInsuranceGump : Gump + { + private readonly ItemInsuranceMenuGump m_InsuranceGump; + private readonly PlayerMobile m_Player; + + public CancelRenewInventoryInsuranceGump(PlayerMobile player, ItemInsuranceMenuGump insuranceGump) : base( + 250, + 200 + ) + { + m_Player = player; + m_InsuranceGump = insuranceGump; + + AddBackground(0, 0, 240, 142, 0x13BE); + AddImageTiled(6, 6, 228, 100, 0xA40); + AddImageTiled(6, 116, 228, 20, 0xA40); + AddAlphaRegion(6, 6, 228, 142); + + AddHtmlLocalized( + 8, + 8, + 228, + 100, + 1071021, + 0x7FFF + ); // You are about to disable inventory insurance auto-renewal. + + AddButton(6, 116, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(40, 118, 450, 20, 1060051, 0x7FFF); // CANCEL + + AddButton(114, 116, 0xFA5, 0xFA7, 1); + AddHtmlLocalized(148, 118, 450, 20, 1071022, 0x7FFF); // DISABLE IT! + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (!m_Player.CheckAlive()) + return; + + if (info.ButtonID == 1) + { + m_Player.SendLocalizedMessage( + 1061075, + "", + 0x23 + ); // You have cancelled automatically reinsuring all insured items upon death + m_Player.AutoRenewInsurance = false; + } + else + { + m_Player.SendLocalizedMessage(1042021); // Cancelled. + } + + if (m_InsuranceGump != null) + m_Player.SendGump(m_InsuranceGump.NewInstance()); + } + } + + private class ItemInsuranceMenuGump : Gump + { + private readonly PlayerMobile m_From; + private readonly bool[] m_Insure; + private readonly Item[] m_Items; + private readonly int m_Page; + + public ItemInsuranceMenuGump(PlayerMobile from, Item[] items, bool[] insure = null, int page = 0) + : base(25, 50) + { + m_From = from; + m_Items = items; + + if (insure == null) + { + insure = new bool[items.Length]; + + for (var i = 0; i < items.Length; ++i) + insure[i] = items[i].Insured; + } + + m_Insure = insure; + m_Page = page; + + AddPage(0); + + AddBackground(0, 0, 520, 510, 0x13BE); + AddImageTiled(10, 10, 500, 30, 0xA40); + AddImageTiled(10, 50, 500, 355, 0xA40); + AddImageTiled(10, 415, 500, 80, 0xA40); + AddAlphaRegion(10, 10, 500, 485); + + AddButton(15, 470, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(50, 472, 80, 20, 1011012, 0x7FFF); // CANCEL + + if (from.AutoRenewInsurance) + AddButton(360, 10, 9723, 9724, 1); + else + AddButton(360, 10, 9720, 9722, 1); + + AddHtmlLocalized(395, 14, 105, 20, 1114122, 0x7FFF); // AUTO REINSURE + + AddButton(395, 470, 0xFA5, 0xFA6, 2); + AddHtmlLocalized(430, 472, 50, 20, 1006044, 0x7FFF); // OK + + AddHtmlLocalized(10, 14, 150, 20, 1114121, 0x7FFF); //
ITEM INSURANCE MENU
+ + AddHtmlLocalized(45, 54, 70, 20, 1062214, 0x7FFF); // Item + AddHtmlLocalized(250, 54, 70, 20, 1061038, 0x7FFF); // Cost + AddHtmlLocalized(400, 54, 70, 20, 1114311, 0x7FFF); // Insured + + var balance = Banker.GetBalance(from); + var cost = 0; + + for (var i = 0; i < items.Length; ++i) + if (insure[i]) + cost += GetInsuranceCost(items[i]); + + AddHtmlLocalized(15, 420, 300, 20, 1114310, 0x7FFF); // GOLD AVAILABLE: + AddLabel(215, 420, 0x481, balance.ToString()); + AddHtmlLocalized(15, 435, 300, 20, 1114123, 0x7FFF); // TOTAL COST OF INSURANCE: + AddLabel(215, 435, 0x481, cost.ToString()); + + if (cost != 0) + { + AddHtmlLocalized(15, 450, 300, 20, 1114125, 0x7FFF); // NUMBER OF DEATHS PAYABLE: + AddLabel(215, 450, 0x481, (balance / cost).ToString()); + } + + for (int i = page * 4, y = 72; i < (page + 1) * 4 && i < items.Length; ++i, y += 75) + { + var item = items[i]; + var b = ItemBounds.Table[item.ItemID]; + + AddImageTiledButton( + 40, + y, + 0x918, + 0x918, + 0, + GumpButtonType.Page, + 0, + item.ItemID, + item.Hue, + 40 - b.Width / 2 - b.X, + 30 - b.Height / 2 - b.Y + ); + AddItemProperty(item.Serial); + + if (insure[i]) + { + AddButton(400, y, 9723, 9724, 100 + i); + AddLabel(250, y, 0x481, GetInsuranceCost(item).ToString()); + } + else + { + AddButton(400, y, 9720, 9722, 100 + i); + AddLabel(250, y, 0x66C, GetInsuranceCost(item).ToString()); + } + } + + if (page >= 1) + { + AddButton(15, 380, 0xFAE, 0xFAF, 3); + AddHtmlLocalized(50, 380, 450, 20, 1044044, 0x7FFF); // PREV PAGE + } + + if ((page + 1) * 4 < items.Length) + { + AddButton(400, 380, 0xFA5, 0xFA7, 4); + AddHtmlLocalized(435, 380, 70, 20, 1044045, 0x7FFF); // NEXT PAGE + } + } + + public ItemInsuranceMenuGump NewInstance() => new ItemInsuranceMenuGump(m_From, m_Items, m_Insure, m_Page); + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 0 || !m_From.CheckAlive()) + return; + + switch (info.ButtonID) + { + case 1: // Auto Reinsure + { + if (m_From.AutoRenewInsurance) + { + if (!m_From.HasGump()) + m_From.SendGump(new CancelRenewInventoryInsuranceGump(m_From, this)); + } + else + { + m_From.AutoRenewInventoryInsurance(); + m_From.SendGump(new ItemInsuranceMenuGump(m_From, m_Items, m_Insure, m_Page)); + } + + break; + } + case 2: // OK + { + m_From.SendGump(new ItemInsuranceMenuConfirmGump(m_From, m_Items, m_Insure, m_Page)); + + break; + } + case 3: // Prev + { + if (m_Page >= 1) + m_From.SendGump(new ItemInsuranceMenuGump(m_From, m_Items, m_Insure, m_Page - 1)); + + break; + } + case 4: // Next + { + if ((m_Page + 1) * 4 < m_Items.Length) + m_From.SendGump(new ItemInsuranceMenuGump(m_From, m_Items, m_Insure, m_Page + 1)); + + break; + } + default: + { + var idx = info.ButtonID - 100; + + if (idx >= 0 && idx < m_Items.Length) + m_Insure[idx] = !m_Insure[idx]; + + m_From.SendGump(new ItemInsuranceMenuGump(m_From, m_Items, m_Insure, m_Page)); + + break; + } + } + } + } + + private class ItemInsuranceMenuConfirmGump : Gump + { + private readonly PlayerMobile m_From; + private readonly bool[] m_Insure; + private readonly Item[] m_Items; + private readonly int m_Page; + + public ItemInsuranceMenuConfirmGump(PlayerMobile from, Item[] items, bool[] insure, int page) + : base(250, 200) + { + m_From = from; + m_Items = items; + m_Insure = insure; + m_Page = page; + + AddBackground(0, 0, 240, 142, 0x13BE); + AddImageTiled(6, 6, 228, 100, 0xA40); + AddImageTiled(6, 116, 228, 20, 0xA40); + AddAlphaRegion(6, 6, 228, 142); + + AddHtmlLocalized(8, 8, 228, 100, 1114300, 0x7FFF); // Do you wish to insure all newly selected items? + + AddButton(6, 116, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(40, 118, 450, 20, 1060051, 0x7FFF); // CANCEL + + AddButton(114, 116, 0xFA5, 0xFA7, 1); + AddHtmlLocalized(148, 118, 450, 20, 1073996, 0x7FFF); // ACCEPT + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (!m_From.CheckAlive()) + return; + + if (info.ButtonID == 1) + { + for (var i = 0; i < m_Items.Length; ++i) + { + var item = m_Items[i]; + + if (item.Insured != m_Insure[i]) + m_From.ToggleItemInsurance_Callback(m_From, item, false); + } + } + else + { + m_From.SendLocalizedMessage(1042021); // Cancelled. + m_From.SendGump(new ItemInsuranceMenuGump(m_From, m_Items, m_Insure, m_Page)); + } + } + } + + [PropertyObject] + public class ChampionTitleInfo + { + public const int LossAmount = 90; + public static TimeSpan LossDelay = TimeSpan.FromDays(1.0); + + private TitleInfo[] m_Values; + + public ChampionTitleInfo() + { + } + + public ChampionTitleInfo(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 0: + { + Harrower = reader.ReadEncodedInt(); + + var length = reader.ReadEncodedInt(); + m_Values = new TitleInfo[length]; + + for (var i = 0; i < length; i++) m_Values[i] = new TitleInfo(reader); + + if (m_Values.Length != ChampionSpawnInfo.Table.Length) + { + var oldValues = m_Values; + m_Values = new TitleInfo[ChampionSpawnInfo.Table.Length]; + + for (var i = 0; i < m_Values.Length && i < oldValues.Length; i++) m_Values[i] = oldValues[i]; + } + + break; + } + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Pestilence + { + get => GetValue(ChampionSpawnType.Pestilence); + set => SetValue(ChampionSpawnType.Pestilence, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Abyss + { + get => GetValue(ChampionSpawnType.Abyss); + set => SetValue(ChampionSpawnType.Abyss, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Arachnid + { + get => GetValue(ChampionSpawnType.Arachnid); + set => SetValue(ChampionSpawnType.Arachnid, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public int ColdBlood + { + get => GetValue(ChampionSpawnType.ColdBlood); + set => SetValue(ChampionSpawnType.ColdBlood, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public int ForestLord + { + get => GetValue(ChampionSpawnType.ForestLord); + set => SetValue(ChampionSpawnType.ForestLord, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public int SleepingDragon + { + get => GetValue(ChampionSpawnType.SleepingDragon); + set => SetValue(ChampionSpawnType.SleepingDragon, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public int UnholyTerror + { + get => GetValue(ChampionSpawnType.UnholyTerror); + set => SetValue(ChampionSpawnType.UnholyTerror, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public int VerminHorde + { + get => GetValue(ChampionSpawnType.VerminHorde); + set => SetValue(ChampionSpawnType.VerminHorde, value); + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Harrower { get; set; } + + public int GetValue(ChampionSpawnType type) => GetValue((int)type); + + public void SetValue(ChampionSpawnType type, int value) + { + SetValue((int)type, value); + } + + public void Award(ChampionSpawnType type, int value) + { + Award((int)type, value); + } + + public int GetValue(int index) + { + if (m_Values == null || index < 0 || index >= m_Values.Length) + return 0; + + m_Values[index] ??= new TitleInfo(); + + return m_Values[index].Value; + } + + public DateTime GetLastDecay(int index) + { + if (m_Values == null || index < 0 || index >= m_Values.Length) + return DateTime.MinValue; + + m_Values[index] ??= new TitleInfo(); + + return m_Values[index].LastDecay; + } + + public void SetValue(int index, int value) + { + m_Values ??= new TitleInfo[ChampionSpawnInfo.Table.Length]; + + if (index < 0 || index >= m_Values.Length) + return; + + m_Values[index] ??= new TitleInfo(); + + m_Values[index].Value = Math.Max(value, 0); + } + + public void Award(int index, int value) + { + m_Values ??= new TitleInfo[ChampionSpawnInfo.Table.Length]; + + if (index < 0 || index >= m_Values.Length || value <= 0) + return; + + m_Values[index] ??= new TitleInfo(); + + m_Values[index].Value += value; + } + + public void Atrophy(int index, int value) + { + m_Values ??= new TitleInfo[ChampionSpawnInfo.Table.Length]; + + if (index < 0 || index >= m_Values.Length || value <= 0) + return; + + m_Values[index] ??= new TitleInfo(); + + var before = m_Values[index].Value; + + m_Values[index].Value -= Math.Min(value, m_Values[index].Value); + + if (before != m_Values[index].Value) + m_Values[index].LastDecay = DateTime.UtcNow; + } + + public override string ToString() => "..."; + + public static void Serialize(IGenericWriter writer, ChampionTitleInfo titles) + { + writer.WriteEncodedInt(0); // version + + writer.WriteEncodedInt(titles.Harrower); + + var length = titles.m_Values.Length; + writer.WriteEncodedInt(length); + + for (var i = 0; i < length; i++) + { + titles.m_Values[i] ??= new TitleInfo(); + + TitleInfo.Serialize(writer, titles.m_Values[i]); + } + } + + public static void CheckAtrophy(PlayerMobile pm) + { + var t = pm.ChampionTitles; + if (t == null) + return; + + t.m_Values ??= new TitleInfo[ChampionSpawnInfo.Table.Length]; + + for (var i = 0; i < t.m_Values.Length; i++) + if (t.GetLastDecay(i) + LossDelay < DateTime.UtcNow) + t.Atrophy(i, LossAmount); + } + + public static void + AwardHarrowerTitle(PlayerMobile pm) // Called when killing a harrower. Will give a minimum of 1 point. + { + var t = pm.ChampionTitles; + if (t == null) + return; + + t.m_Values ??= new TitleInfo[ChampionSpawnInfo.Table.Length]; + + var count = 1 + t.m_Values.Count(t1 => t1.Value > 900); + + t.Harrower = Math.Max(count, t.Harrower); // Harrower titles never decay. + } + + private class TitleInfo + { + public TitleInfo() + { + } + + public TitleInfo(IGenericReader reader) + { + var version = reader.ReadEncodedInt(); + + switch (version) + { + case 0: + { + Value = reader.ReadEncodedInt(); + LastDecay = reader.ReadDateTime(); + break; + } + } + } + + public int Value { get; set; } + + public DateTime LastDecay { get; set; } + + public static void Serialize(IGenericWriter writer, TitleInfo info) + { + writer.WriteEncodedInt(0); // version + + writer.WriteEncodedInt(info.Value); + writer.Write(info.LastDecay); + } + } + } } - - private Dictionary m_AcquiredRecipes; - - public virtual bool HasRecipe(Recipe r) => r != null && HasRecipe(r.ID); - - public virtual bool HasRecipe(int recipeID) => m_AcquiredRecipes.TryGetValue(recipeID, out bool value) && value; - - public virtual void AcquireRecipe(Recipe r) - { - if (r != null) - AcquireRecipe(r.ID); - } - - public virtual void AcquireRecipe(int recipeID) - { - m_AcquiredRecipes ??= new Dictionary(); - - m_AcquiredRecipes[recipeID] = true; - } - - public virtual void ResetRecipes() - { - m_AcquiredRecipes = null; - } - - [CommandProperty(AccessLevel.GameMaster)] - public int KnownRecipes => m_AcquiredRecipes?.Count ?? 0; - - public void ResendBuffs() - { - if (!BuffInfo.Enabled || m_BuffTable == null) - return; - - if (NetState?.BuffIcon == true) - foreach (BuffInfo info in m_BuffTable.Values) - NetState.Send(new AddBuffPacket(this, info)); - } - - private Dictionary m_BuffTable; - - public void AddBuff(BuffInfo b) - { - if (!BuffInfo.Enabled || b == null) - return; - - RemoveBuff(b); // Check & subsequently remove the old one. - - m_BuffTable ??= new Dictionary(); - - m_BuffTable.Add(b.ID, b); - - if (NetState?.BuffIcon == true) - NetState.Send(new AddBuffPacket(this, b)); - } - - public void RemoveBuff(BuffInfo b) - { - if (b == null) - return; - - RemoveBuff(b.ID); - } - - public void RemoveBuff(BuffIcon b) - { - if (m_BuffTable?.ContainsKey(b) != true) - return; - - BuffInfo info = m_BuffTable[b]; - - if (info.Timer?.Running == true) - info.Timer.Stop(); - - m_BuffTable.Remove(b); - - if (NetState?.BuffIcon == true) - NetState.Send(new RemoveBuffPacket(this, b)); - - if (m_BuffTable.Count <= 0) - m_BuffTable = null; - } - } } diff --git a/Projects/UOContent/Mobiles/Special/Barracoon.cs b/Projects/UOContent/Mobiles/Special/Barracoon.cs index c0c82f3cb..f4eacd17c 100644 --- a/Projects/UOContent/Mobiles/Special/Barracoon.cs +++ b/Projects/UOContent/Mobiles/Special/Barracoon.cs @@ -7,218 +7,218 @@ using Server.Spells.Seventh; namespace Server.Mobiles { - public class Barracoon : BaseChampion - { - [Constructible] - public Barracoon() : base(AIType.AI_Melee) + public class Barracoon : BaseChampion { - Title = "the piper"; - Body = 0x190; - Hue = 0x83EC; - - SetStr(305, 425); - SetDex(72, 150); - SetInt(505, 750); - - SetHits(4200); - SetStam(102, 300); - - SetDamage(25, 35); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 60, 70); - SetResistance(ResistanceType.Fire, 50, 60); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 40, 50); - - SetSkill(SkillName.MagicResist, 100.0); - SetSkill(SkillName.Tactics, 97.6, 100.0); - SetSkill(SkillName.Wrestling, 97.6, 100.0); - - Fame = 22500; - Karma = -22500; - - VirtualArmor = 70; - - AddItem(new FancyShirt(Utility.RandomGreenHue())); - AddItem(new LongPants(Utility.RandomYellowHue())); - AddItem(new JesterHat(Utility.RandomPinkHue())); - AddItem(new Cloak(Utility.RandomPinkHue())); - AddItem(new Sandals()); - - HairItemID = 0x203B; // Short Hair - HairHue = 0x94; - } - - public Barracoon(Serial serial) : base(serial) - { - } - - public override ChampionSkullType SkullType => ChampionSkullType.Greed; - - public override Type[] UniqueList => new[] { typeof(FangOfRactus) }; - - public override Type[] SharedList => new[] - { - typeof(EmbroideredOakLeafCloak), - typeof(DjinnisRing), - typeof(DetectiveBoots), - typeof(GuantletsOfAnger) - }; - - public override Type[] DecorativeList => new[] { typeof(SwampTile), typeof(MonsterStatuette) }; - - public override MonsterStatuetteType[] StatueTypes => new[] { MonsterStatuetteType.Slime }; - - public override string DefaultName => "Barracoon"; - - public override bool AlwaysMurderer => true; - public override bool AutoDispel => true; - public override double AutoDispelChance => 1.0; - public override bool BardImmune => !Core.SE; - public override bool Unprovokable => Core.SE; - public override bool Uncalmable => Core.SE; - public override Poison PoisonImmune => Poison.Deadly; - - public override bool ShowFameTitle => false; - public override bool ClickTitle => false; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 3); - } - - public void Polymorph(Mobile m) - { - if (!m.CanBeginAction() || !m.CanBeginAction() || m.IsBodyMod) - return; - - IMount mount = m.Mount; - - if (mount != null) - mount.Rider = null; - - if (m.Mounted) - return; - - if (m.BeginAction()) - { - Item disarm = m.FindItemOnLayer(Layer.OneHanded); - - if (disarm?.Movable == true) - m.AddToBackpack(disarm); - - disarm = m.FindItemOnLayer(Layer.TwoHanded); - - if (disarm?.Movable == true) - m.AddToBackpack(disarm); - - m.BodyMod = 42; - m.HueMod = 0; - - new ExpirePolymorphTimer(m).Start(); - } - } - - public void SpawnRatmen(Mobile target) - { - Map map = Map; - - if (map == null) - return; - - IPooledEnumerable eable = GetMobilesInRange(10); - int rats = eable.Aggregate(0, (c, m) => c + (m is Ratman || m is RatmanArcher || m is RatmanMage ? 1 : 0)); - eable.Free(); - - if (rats >= 16) - return; - - PlaySound(0x3D); - - rats = Utility.RandomMinMax(3, 6); - - for (int i = 0; i < rats; ++i) - { - var rat = Utility.Random(5) switch + [Constructible] + public Barracoon() : base(AIType.AI_Melee) { - 2 => (BaseCreature)new RatmanArcher(), - 3 => new RatmanArcher(), - 4 => new RatmanMage(), - _ => new Ratman() + Title = "the piper"; + Body = 0x190; + Hue = 0x83EC; + + SetStr(305, 425); + SetDex(72, 150); + SetInt(505, 750); + + SetHits(4200); + SetStam(102, 300); + + SetDamage(25, 35); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 60, 70); + SetResistance(ResistanceType.Fire, 50, 60); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 40, 50); + + SetSkill(SkillName.MagicResist, 100.0); + SetSkill(SkillName.Tactics, 97.6, 100.0); + SetSkill(SkillName.Wrestling, 97.6, 100.0); + + Fame = 22500; + Karma = -22500; + + VirtualArmor = 70; + + AddItem(new FancyShirt(Utility.RandomGreenHue())); + AddItem(new LongPants(Utility.RandomYellowHue())); + AddItem(new JesterHat(Utility.RandomPinkHue())); + AddItem(new Cloak(Utility.RandomPinkHue())); + AddItem(new Sandals()); + + HairItemID = 0x203B; // Short Hair + HairHue = 0x94; + } + + public Barracoon(Serial serial) : base(serial) + { + } + + public override ChampionSkullType SkullType => ChampionSkullType.Greed; + + public override Type[] UniqueList => new[] { typeof(FangOfRactus) }; + + public override Type[] SharedList => new[] + { + typeof(EmbroideredOakLeafCloak), + typeof(DjinnisRing), + typeof(DetectiveBoots), + typeof(GuantletsOfAnger) }; - rat.Team = Team; - rat.MoveToWorld(map.GetRandomNearbyLocation(Location), map); - rat.Combatant = target; - } - } + public override Type[] DecorativeList => new[] { typeof(SwampTile), typeof(MonsterStatuette) }; - public void DoSpecialAbility(Mobile target) - { - if (target?.Deleted != false) // sanity - return; + public override MonsterStatuetteType[] StatueTypes => new[] { MonsterStatuetteType.Slime }; - if (Utility.RandomDouble() <= 0.6) // 60% chance to polymorph attacker into a ratman - Polymorph(target); + public override string DefaultName => "Barracoon"; - if (Utility.RandomDouble() <= 0.2) // 20% chance to more ratmen - SpawnRatmen(target); + public override bool AlwaysMurderer => true; + public override bool AutoDispel => true; + public override double AutoDispelChance => 1.0; + public override bool BardImmune => !Core.SE; + public override bool Unprovokable => Core.SE; + public override bool Uncalmable => Core.SE; + public override Poison PoisonImmune => Poison.Deadly; - if (Hits < 500 && !IsBodyMod) // Baracoon is low on life, polymorph into a ratman - Polymorph(this); - } + public override bool ShowFameTitle => false; + public override bool ClickTitle => false; - public override void OnGotMeleeAttack(Mobile attacker) - { - base.OnGotMeleeAttack(attacker); - - DoSpecialAbility(attacker); - } - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - DoSpecialAbility(defender); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private class ExpirePolymorphTimer : Timer - { - private readonly Mobile m_Owner; - - public ExpirePolymorphTimer(Mobile owner) : base(TimeSpan.FromMinutes(3.0)) - { - m_Owner = owner; - - Priority = TimerPriority.OneSecond; - } - - protected override void OnTick() - { - if (!m_Owner.CanBeginAction()) + public override void GenerateLoot() { - m_Owner.BodyMod = 0; - m_Owner.HueMod = -1; - m_Owner.EndAction(); + AddLoot(LootPack.UltraRich, 3); + } + + public void Polymorph(Mobile m) + { + if (!m.CanBeginAction() || !m.CanBeginAction() || m.IsBodyMod) + return; + + var mount = m.Mount; + + if (mount != null) + mount.Rider = null; + + if (m.Mounted) + return; + + if (m.BeginAction()) + { + var disarm = m.FindItemOnLayer(Layer.OneHanded); + + if (disarm?.Movable == true) + m.AddToBackpack(disarm); + + disarm = m.FindItemOnLayer(Layer.TwoHanded); + + if (disarm?.Movable == true) + m.AddToBackpack(disarm); + + m.BodyMod = 42; + m.HueMod = 0; + + new ExpirePolymorphTimer(m).Start(); + } + } + + public void SpawnRatmen(Mobile target) + { + var map = Map; + + if (map == null) + return; + + var eable = GetMobilesInRange(10); + var rats = eable.Aggregate(0, (c, m) => c + (m is Ratman || m is RatmanArcher || m is RatmanMage ? 1 : 0)); + eable.Free(); + + if (rats >= 16) + return; + + PlaySound(0x3D); + + rats = Utility.RandomMinMax(3, 6); + + for (var i = 0; i < rats; ++i) + { + var rat = Utility.Random(5) switch + { + 2 => (BaseCreature)new RatmanArcher(), + 3 => new RatmanArcher(), + 4 => new RatmanMage(), + _ => new Ratman() + }; + + rat.Team = Team; + rat.MoveToWorld(map.GetRandomNearbyLocation(Location), map); + rat.Combatant = target; + } + } + + public void DoSpecialAbility(Mobile target) + { + if (target?.Deleted != false) // sanity + return; + + if (Utility.RandomDouble() <= 0.6) // 60% chance to polymorph attacker into a ratman + Polymorph(target); + + if (Utility.RandomDouble() <= 0.2) // 20% chance to more ratmen + SpawnRatmen(target); + + if (Hits < 500 && !IsBodyMod) // Baracoon is low on life, polymorph into a ratman + Polymorph(this); + } + + public override void OnGotMeleeAttack(Mobile attacker) + { + base.OnGotMeleeAttack(attacker); + + DoSpecialAbility(attacker); + } + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + DoSpecialAbility(defender); + } + + 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(); + } + + private class ExpirePolymorphTimer : Timer + { + private readonly Mobile m_Owner; + + public ExpirePolymorphTimer(Mobile owner) : base(TimeSpan.FromMinutes(3.0)) + { + m_Owner = owner; + + Priority = TimerPriority.OneSecond; + } + + protected override void OnTick() + { + if (!m_Owner.CanBeginAction()) + { + m_Owner.BodyMod = 0; + m_Owner.HueMod = -1; + m_Owner.EndAction(); + } + } } - } } - } } diff --git a/Projects/UOContent/Mobiles/Special/BaseChampion.cs b/Projects/UOContent/Mobiles/Special/BaseChampion.cs index 2979f4b3d..e40701ddc 100644 --- a/Projects/UOContent/Mobiles/Special/BaseChampion.cs +++ b/Projects/UOContent/Mobiles/Special/BaseChampion.cs @@ -5,311 +5,326 @@ using Server.Items; namespace Server.Mobiles { - public abstract class BaseChampion : BaseCreature - { - public BaseChampion(AIType aiType, FightMode mode = FightMode.Closest) : base(aiType, mode, 18, 1, 0.1, 0.2) + public abstract class BaseChampion : BaseCreature { - } - - public BaseChampion(Serial serial) : base(serial) - { - } - - public override bool CanMoveOverObstacles => true; - public override bool CanDestroyObstacles => true; - - public abstract ChampionSkullType SkullType { get; } - - public abstract Type[] UniqueList { get; } - public abstract Type[] SharedList { get; } - public abstract Type[] DecorativeList { get; } - public abstract MonsterStatuetteType[] StatueTypes { get; } - - public virtual bool NoGoodies => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public Item GetArtifact() - { - double random = Utility.RandomDouble(); - if (random <= 0.05) - return CreateArtifact(UniqueList); - if (random <= 0.15) - return CreateArtifact(SharedList); - if (random <= 0.30) - return CreateArtifact(DecorativeList); - - return null; - } - - public Item CreateArtifact(Type[] list) - { - if (list.Length == 0) - return null; - - Type type = list.RandomElement(); - - Item artifact = Loot.Construct(type); - - if (StatueTypes.Length > 0 && artifact is MonsterStatuette statuette) - { - statuette.Type = StatueTypes.RandomElement(); - statuette.LootType = LootType.Regular; - } - - return artifact; - } - - private PowerScroll CreateRandomPowerScroll() - { - int level; - double random = Utility.RandomDouble(); - - if (random <= 0.05) - level = 20; - else if (random <= 0.4) - level = 15; - else - level = 10; - - return PowerScroll.CreateRandomNoCraft(level, level); - } - - public void GivePowerScrolls() - { - if (Map != Map.Felucca) - return; - - List toGive = new List(); - List rights = GetLootingRights(DamageEntries, HitsMax); - - for (int i = rights.Count - 1; i >= 0; --i) - { - DamageStore ds = rights[i]; - - if (ds.m_HasRight) - toGive.Add(ds.m_Mobile); - } - - if (toGive.Count == 0) - return; - - for (int i = 0; i < toGive.Count; i++) - { - Mobile m = toGive[i]; - - if (!(m is PlayerMobile)) - continue; - - bool gainedPath = false; - - int pointsToGain = 800; - - if (VirtueHelper.Award(m, VirtueName.Valor, pointsToGain, ref gainedPath)) + public BaseChampion(AIType aiType, FightMode mode = FightMode.Closest) : base(aiType, mode, 18, 1, 0.1, 0.2) { - if (gainedPath) - m.SendLocalizedMessage(1054032); // You have gained a path in Valor! - else - m.SendLocalizedMessage(1054030); // You have gained in Valor! - - // No delay on Valor gains } - } - // Randomize - toGive.Shuffle(); - - for (int i = 0; i < 6; ++i) - { - Mobile m = toGive[i % toGive.Count]; - - PowerScroll ps = CreateRandomPowerScroll(); - - GivePowerScrollTo(m, ps); - } - } - - public static void GivePowerScrollTo(Mobile m, PowerScroll ps) - { - if (ps == null || m == null) // sanity - return; - - m.SendLocalizedMessage(1049524); // You have received a scroll of power! - - if (!Core.SE || m.Alive) - { - m.AddToBackpack(ps); - } - else - { - if (m.Corpse?.Deleted == false) - m.Corpse.DropItem(ps); - else - m.AddToBackpack(ps); - } - - if (!(m is PlayerMobile pm)) - return; - - for (int j = 0; j < pm.JusticeProtectors.Count; ++j) - { - Mobile prot = pm.JusticeProtectors[j]; - - if (prot.Map != pm.Map || prot.Kills >= 5 || prot.Criminal || !JusticeVirtue.CheckMapRegion(pm, prot)) - continue; - - var chance = VirtueHelper.GetLevel(prot, VirtueName.Justice) switch + public BaseChampion(Serial serial) : base(serial) { - VirtueLevel.Seeker => 60, - VirtueLevel.Follower => 80, - VirtueLevel.Knight => 100, - _ => 0 - }; - - if (chance > Utility.Random(100)) - { - PowerScroll powerScroll = new PowerScroll(ps.Skill, ps.Value); - - prot.SendLocalizedMessage(1049368); // You have been rewarded for your dedication to Justice! - - if (!Core.SE || prot.Alive) - { - prot.AddToBackpack(powerScroll); - } - else - { - if (prot.Corpse?.Deleted == false) - prot.Corpse.DropItem(powerScroll); - else - prot.AddToBackpack(powerScroll); - } } - } - } - public override bool OnBeforeDeath() - { - if (!NoKillAwards) - { - GivePowerScrolls(); + public override bool CanMoveOverObstacles => true; + public override bool CanDestroyObstacles => true; - if (NoGoodies) - return base.OnBeforeDeath(); + public abstract ChampionSkullType SkullType { get; } - Map map = Map; + public abstract Type[] UniqueList { get; } + public abstract Type[] SharedList { get; } + public abstract Type[] DecorativeList { get; } + public abstract MonsterStatuetteType[] StatueTypes { get; } - if (map != null) - for (int x = -12; x <= 12; ++x) - for (int y = -12; y <= 12; ++y) + public virtual bool NoGoodies => 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 Item GetArtifact() + { + var random = Utility.RandomDouble(); + if (random <= 0.05) + return CreateArtifact(UniqueList); + if (random <= 0.15) + return CreateArtifact(SharedList); + if (random <= 0.30) + return CreateArtifact(DecorativeList); + + return null; + } + + public Item CreateArtifact(Type[] list) + { + if (list.Length == 0) + return null; + + var type = list.RandomElement(); + + var artifact = Loot.Construct(type); + + if (StatueTypes.Length > 0 && artifact is MonsterStatuette statuette) { - double dist = Math.Sqrt(x * x + y * y); - - if (dist <= 12) - new GoodiesTimer(map, X + x, Y + y).Start(); + statuette.Type = StatueTypes.RandomElement(); + statuette.LootType = LootType.Regular; } - } - return base.OnBeforeDeath(); - } - - public override void OnDeath(Container c) - { - if (Map == Map.Felucca) - { - // TODO: Confirm SE change or AoS one too? - List rights = GetLootingRights(DamageEntries, HitsMax); - List toGive = new List(); - - for (int i = rights.Count - 1; i >= 0; --i) - { - DamageStore ds = rights[i]; - - if (ds.m_HasRight) - toGive.Add(ds.m_Mobile); + return artifact; } - if (toGive.Count > 0) - toGive.RandomElement().AddToBackpack(new ChampionSkull(SkullType)); - else - c.DropItem(new ChampionSkull(SkullType)); - } - - base.OnDeath(c); - } - - private class GoodiesTimer : Timer - { - private readonly Map m_Map; - private readonly int m_X; - private readonly int m_Y; - - public GoodiesTimer(Map map, int x, int y) : base(TimeSpan.FromSeconds(Utility.RandomDouble() * 10.0)) - { - m_Map = map; - m_X = x; - m_Y = y; - } - - protected override void OnTick() - { - int z = m_Map.GetAverageZ(m_X, m_Y); - bool canFit = m_Map.CanFit(m_X, m_Y, z, 6, false, false); - - for (int i = -3; !canFit && i <= 3; ++i) + private PowerScroll CreateRandomPowerScroll() { - canFit = m_Map.CanFit(m_X, m_Y, z + i, 6, false, false); + int level; + var random = Utility.RandomDouble(); - if (canFit) - z += i; + if (random <= 0.05) + level = 20; + else if (random <= 0.4) + level = 15; + else + level = 10; + + return PowerScroll.CreateRandomNoCraft(level, level); } - if (!canFit) - return; + public void GivePowerScrolls() + { + if (Map != Map.Felucca) + return; - Gold g = new Gold(500, 1000); + var toGive = new List(); + var rights = GetLootingRights(DamageEntries, HitsMax); - g.MoveToWorld(new Point3D(m_X, m_Y, z), m_Map); + for (var i = rights.Count - 1; i >= 0; --i) + { + var ds = rights[i]; - if (Utility.RandomDouble() <= 0.5) - switch (Utility.Random(3)) - { - case 0: // Fire column - { - Effects.SendLocationParticles(EffectItem.Create(g.Location, g.Map, EffectItem.DefaultDuration), - 0x3709, 10, 30, 5052); - Effects.PlaySound(g, g.Map, 0x208); + if (ds.m_HasRight) + toGive.Add(ds.m_Mobile); + } - break; - } - case 1: // Explosion - { - Effects.SendLocationParticles(EffectItem.Create(g.Location, g.Map, EffectItem.DefaultDuration), - 0x36BD, 20, 10, 5044); - Effects.PlaySound(g, g.Map, 0x307); + if (toGive.Count == 0) + return; - break; - } - case 2: // Ball of fire - { - Effects.SendLocationParticles(EffectItem.Create(g.Location, g.Map, EffectItem.DefaultDuration), - 0x36FE, 10, 10, 5052); + for (var i = 0; i < toGive.Count; i++) + { + var m = toGive[i]; - break; - } - } - } + if (!(m is PlayerMobile)) + continue; + + var gainedPath = false; + + var pointsToGain = 800; + + if (VirtueHelper.Award(m, VirtueName.Valor, pointsToGain, ref gainedPath)) + { + if (gainedPath) + m.SendLocalizedMessage(1054032); // You have gained a path in Valor! + else + m.SendLocalizedMessage(1054030); // You have gained in Valor! + + // No delay on Valor gains + } + } + + // Randomize + toGive.Shuffle(); + + for (var i = 0; i < 6; ++i) + { + var m = toGive[i % toGive.Count]; + + var ps = CreateRandomPowerScroll(); + + GivePowerScrollTo(m, ps); + } + } + + public static void GivePowerScrollTo(Mobile m, PowerScroll ps) + { + if (ps == null || m == null) // sanity + return; + + m.SendLocalizedMessage(1049524); // You have received a scroll of power! + + if (!Core.SE || m.Alive) + { + m.AddToBackpack(ps); + } + else + { + if (m.Corpse?.Deleted == false) + m.Corpse.DropItem(ps); + else + m.AddToBackpack(ps); + } + + if (!(m is PlayerMobile pm)) + return; + + for (var j = 0; j < pm.JusticeProtectors.Count; ++j) + { + var prot = pm.JusticeProtectors[j]; + + if (prot.Map != pm.Map || prot.Kills >= 5 || prot.Criminal || !JusticeVirtue.CheckMapRegion(pm, prot)) + continue; + + var chance = VirtueHelper.GetLevel(prot, VirtueName.Justice) switch + { + VirtueLevel.Seeker => 60, + VirtueLevel.Follower => 80, + VirtueLevel.Knight => 100, + _ => 0 + }; + + if (chance > Utility.Random(100)) + { + var powerScroll = new PowerScroll(ps.Skill, ps.Value); + + prot.SendLocalizedMessage(1049368); // You have been rewarded for your dedication to Justice! + + if (!Core.SE || prot.Alive) + { + prot.AddToBackpack(powerScroll); + } + else + { + if (prot.Corpse?.Deleted == false) + prot.Corpse.DropItem(powerScroll); + else + prot.AddToBackpack(powerScroll); + } + } + } + } + + public override bool OnBeforeDeath() + { + if (!NoKillAwards) + { + GivePowerScrolls(); + + if (NoGoodies) + return base.OnBeforeDeath(); + + var map = Map; + + if (map != null) + for (var x = -12; x <= 12; ++x) + for (var y = -12; y <= 12; ++y) + { + var dist = Math.Sqrt(x * x + y * y); + + if (dist <= 12) + new GoodiesTimer(map, X + x, Y + y).Start(); + } + } + + return base.OnBeforeDeath(); + } + + public override void OnDeath(Container c) + { + if (Map == Map.Felucca) + { + // TODO: Confirm SE change or AoS one too? + var rights = GetLootingRights(DamageEntries, HitsMax); + var toGive = new List(); + + for (var i = rights.Count - 1; i >= 0; --i) + { + var ds = rights[i]; + + if (ds.m_HasRight) + toGive.Add(ds.m_Mobile); + } + + if (toGive.Count > 0) + toGive.RandomElement().AddToBackpack(new ChampionSkull(SkullType)); + else + c.DropItem(new ChampionSkull(SkullType)); + } + + base.OnDeath(c); + } + + private class GoodiesTimer : Timer + { + private readonly Map m_Map; + private readonly int m_X; + private readonly int m_Y; + + public GoodiesTimer(Map map, int x, int y) : base(TimeSpan.FromSeconds(Utility.RandomDouble() * 10.0)) + { + m_Map = map; + m_X = x; + m_Y = y; + } + + protected override void OnTick() + { + var z = m_Map.GetAverageZ(m_X, m_Y); + var canFit = m_Map.CanFit(m_X, m_Y, z, 6, false, false); + + for (var i = -3; !canFit && i <= 3; ++i) + { + canFit = m_Map.CanFit(m_X, m_Y, z + i, 6, false, false); + + if (canFit) + z += i; + } + + if (!canFit) + return; + + var g = new Gold(500, 1000); + + g.MoveToWorld(new Point3D(m_X, m_Y, z), m_Map); + + if (Utility.RandomDouble() <= 0.5) + switch (Utility.Random(3)) + { + case 0: // Fire column + { + Effects.SendLocationParticles( + EffectItem.Create(g.Location, g.Map, EffectItem.DefaultDuration), + 0x3709, + 10, + 30, + 5052 + ); + Effects.PlaySound(g, g.Map, 0x208); + + break; + } + case 1: // Explosion + { + Effects.SendLocationParticles( + EffectItem.Create(g.Location, g.Map, EffectItem.DefaultDuration), + 0x36BD, + 20, + 10, + 5044 + ); + Effects.PlaySound(g, g.Map, 0x307); + + break; + } + case 2: // Ball of fire + { + Effects.SendLocationParticles( + EffectItem.Create(g.Location, g.Map, EffectItem.DefaultDuration), + 0x36FE, + 10, + 10, + 5052 + ); + + break; + } + } + } + } } - } } diff --git a/Projects/UOContent/Mobiles/Special/BaseShieldGuard.cs b/Projects/UOContent/Mobiles/Special/BaseShieldGuard.cs index a477d868f..a4d1e005d 100644 --- a/Projects/UOContent/Mobiles/Special/BaseShieldGuard.cs +++ b/Projects/UOContent/Mobiles/Special/BaseShieldGuard.cs @@ -3,160 +3,160 @@ using Server.Items; namespace Server.Mobiles { - public abstract class BaseShieldGuard : BaseCreature - { - public BaseShieldGuard() : base(AIType.AI_Melee, FightMode.Aggressor, 14, 1, 0.8, 1.6) + public abstract class BaseShieldGuard : BaseCreature { - InitStats(1000, 1000, 1000); - Title = "the guard"; - - SpeechHue = Utility.RandomDyedHue(); - - Hue = Race.Human.RandomSkinHue(); - - if (Female = Utility.RandomBool()) - { - Body = 0x191; - Name = NameList.RandomName("female"); - - AddItem(new FemalePlateChest()); - AddItem(new PlateArms()); - AddItem(new PlateLegs()); - - switch (Utility.Random(2)) + public BaseShieldGuard() : base(AIType.AI_Melee, FightMode.Aggressor, 14, 1, 0.8, 1.6) { - case 0: - AddItem(new Doublet(Utility.RandomNondyedHue())); - break; - case 1: - AddItem(new BodySash(Utility.RandomNondyedHue())); - break; + InitStats(1000, 1000, 1000); + Title = "the guard"; + + SpeechHue = Utility.RandomDyedHue(); + + Hue = Race.Human.RandomSkinHue(); + + if (Female = Utility.RandomBool()) + { + Body = 0x191; + Name = NameList.RandomName("female"); + + AddItem(new FemalePlateChest()); + AddItem(new PlateArms()); + AddItem(new PlateLegs()); + + switch (Utility.Random(2)) + { + case 0: + AddItem(new Doublet(Utility.RandomNondyedHue())); + break; + case 1: + AddItem(new BodySash(Utility.RandomNondyedHue())); + break; + } + + switch (Utility.Random(2)) + { + case 0: + AddItem(new Skirt(Utility.RandomNondyedHue())); + break; + case 1: + AddItem(new Kilt(Utility.RandomNondyedHue())); + break; + } + } + else + { + Body = 0x190; + Name = NameList.RandomName("male"); + + AddItem(new PlateChest()); + AddItem(new PlateArms()); + AddItem(new PlateLegs()); + + switch (Utility.Random(3)) + { + case 0: + AddItem(new Doublet(Utility.RandomNondyedHue())); + break; + case 1: + AddItem(new Tunic(Utility.RandomNondyedHue())); + break; + case 2: + AddItem(new BodySash(Utility.RandomNondyedHue())); + break; + } + } + + Utility.AssignRandomHair(this); + if (Utility.RandomBool()) + Utility.AssignRandomFacialHair(this, HairHue); + + var weapon = new VikingSword(); + weapon.Movable = false; + AddItem(weapon); + + var shield = Shield; + shield.Movable = false; + AddItem(shield); + + PackGold(250, 500); + + Skills.Anatomy.Base = 120.0; + Skills.Tactics.Base = 120.0; + Skills.Swords.Base = 120.0; + Skills.MagicResist.Base = 120.0; + Skills.DetectHidden.Base = 100.0; } - switch (Utility.Random(2)) + public BaseShieldGuard(Serial serial) : base(serial) { - case 0: - AddItem(new Skirt(Utility.RandomNondyedHue())); - break; - case 1: - AddItem(new Kilt(Utility.RandomNondyedHue())); - break; } - } - else - { - Body = 0x190; - Name = NameList.RandomName("male"); - AddItem(new PlateChest()); - AddItem(new PlateArms()); - AddItem(new PlateLegs()); + public abstract int Keyword { get; } + public abstract BaseShield Shield { get; } + public abstract int SignupNumber { get; } + public abstract GuildType Type { get; } - switch (Utility.Random(3)) + public override bool HandlesOnSpeech(Mobile from) { - case 0: - AddItem(new Doublet(Utility.RandomNondyedHue())); - break; - case 1: - AddItem(new Tunic(Utility.RandomNondyedHue())); - break; - case 2: - AddItem(new BodySash(Utility.RandomNondyedHue())); - break; + if (from.InRange(Location, 2)) + return true; + + return base.HandlesOnSpeech(from); } - } - Utility.AssignRandomHair(this); - if (Utility.RandomBool()) - Utility.AssignRandomFacialHair(this, HairHue); - - VikingSword weapon = new VikingSword(); - weapon.Movable = false; - AddItem(weapon); - - BaseShield shield = Shield; - shield.Movable = false; - AddItem(shield); - - PackGold(250, 500); - - Skills.Anatomy.Base = 120.0; - Skills.Tactics.Base = 120.0; - Skills.Swords.Base = 120.0; - Skills.MagicResist.Base = 120.0; - Skills.DetectHidden.Base = 100.0; - } - - public BaseShieldGuard(Serial serial) : base(serial) - { - } - - public abstract int Keyword { get; } - public abstract BaseShield Shield { get; } - public abstract int SignupNumber { get; } - public abstract GuildType Type { get; } - - public override bool HandlesOnSpeech(Mobile from) - { - if (from.InRange(Location, 2)) - return true; - - return base.HandlesOnSpeech(from); - } - - public override void OnSpeech(SpeechEventArgs e) - { - if (!e.Handled && e.HasKeyword(Keyword) && e.Mobile.InRange(Location, 2)) - { - e.Handled = true; - - Mobile from = e.Mobile; - - if (!(from.Guild is Guild g) || g.Type != Type) + public override void OnSpeech(SpeechEventArgs e) { - Say(SignupNumber); + if (!e.Handled && e.HasKeyword(Keyword) && e.Mobile.InRange(Location, 2)) + { + e.Handled = true; + + var from = e.Mobile; + + if (!(from.Guild is Guild g) || g.Type != Type) + { + Say(SignupNumber); + } + else + { + var pack = from.Backpack; + var shield = Shield; + var twoHanded = from.FindItemOnLayer(Layer.TwoHanded); + + if (pack?.FindItemByType(shield.GetType()) != null || + twoHanded != null && shield.GetType().IsInstanceOfType(twoHanded)) + { + Say(1007110); // Why dost thou ask about virtue guards when thou art one? + shield.Delete(); + } + else if (from.PlaceInBackpack(shield)) + { + Say(Utility.Random(1007101, 5)); + Say(1007139); // I see you are in need of our shield, Here you go. + from.AddToBackpack(shield); + } + else + { + from.SendLocalizedMessage(502868); // Your backpack is too full. + shield.Delete(); + } + } + } + + base.OnSpeech(e); } - else + + public override void Serialize(IGenericWriter writer) { - Container pack = from.Backpack; - BaseShield shield = Shield; - Item twoHanded = from.FindItemOnLayer(Layer.TwoHanded); + base.Serialize(writer); - if (pack?.FindItemByType(shield.GetType()) != null || - (twoHanded != null && shield.GetType().IsInstanceOfType(twoHanded))) - { - Say(1007110); // Why dost thou ask about virtue guards when thou art one? - shield.Delete(); - } - else if (from.PlaceInBackpack(shield)) - { - Say(Utility.Random(1007101, 5)); - Say(1007139); // I see you are in need of our shield, Here you go. - from.AddToBackpack(shield); - } - else - { - from.SendLocalizedMessage(502868); // Your backpack is too full. - shield.Delete(); - } + writer.Write(0); // version } - } - base.OnSpeech(e); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Special/CapturedHordeMinion.cs b/Projects/UOContent/Mobiles/Special/CapturedHordeMinion.cs index b8f5df17c..97b2ab0fa 100644 --- a/Projects/UOContent/Mobiles/Special/CapturedHordeMinion.cs +++ b/Projects/UOContent/Mobiles/Special/CapturedHordeMinion.cs @@ -1,30 +1,30 @@ namespace Server.Mobiles { - public class CapturedHordeMinion : HordeMinion - { - [Constructible] - public CapturedHordeMinion() => FightMode = FightMode.None; - - public CapturedHordeMinion(Serial serial) : base(serial) + public class CapturedHordeMinion : HordeMinion { + [Constructible] + public CapturedHordeMinion() => FightMode = FightMode.None; + + public CapturedHordeMinion(Serial serial) : base(serial) + { + } + + public override bool InitialInnocent => true; + + public override bool CanBeDamaged() => false; + + 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(); + } } - - public override bool InitialInnocent => true; - - public override bool CanBeDamaged() => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Special/ChaosGuard.cs b/Projects/UOContent/Mobiles/Special/ChaosGuard.cs index 11a0296ea..af6d75a0a 100644 --- a/Projects/UOContent/Mobiles/Special/ChaosGuard.cs +++ b/Projects/UOContent/Mobiles/Special/ChaosGuard.cs @@ -3,36 +3,36 @@ using Server.Items; namespace Server.Mobiles { - public class ChaosGuard : BaseShieldGuard - { - [Constructible] - public ChaosGuard() + public class ChaosGuard : BaseShieldGuard { + [Constructible] + public ChaosGuard() + { + } + + public ChaosGuard(Serial serial) : base(serial) + { + } + + public override int Keyword => 0x22; // *chaos shield* + public override BaseShield Shield => new ChaosShield(); + public override int SignupNumber => 1007140; // Sign up with a guild of chaos if thou art interested. + public override GuildType Type => GuildType.Chaos; + + public override bool BardImmune => true; + + 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 ChaosGuard(Serial serial) : base(serial) - { - } - - public override int Keyword => 0x22; // *chaos shield* - public override BaseShield Shield => new ChaosShield(); - public override int SignupNumber => 1007140; // Sign up with a guild of chaos if thou art interested. - public override GuildType Type => GuildType.Chaos; - - public override bool BardImmune => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Special/DarkGuardian.cs b/Projects/UOContent/Mobiles/Special/DarkGuardian.cs index 7705de954..2e6bbeca2 100644 --- a/Projects/UOContent/Mobiles/Special/DarkGuardian.cs +++ b/Projects/UOContent/Mobiles/Special/DarkGuardian.cs @@ -2,78 +2,78 @@ using Server.Items; namespace Server.Mobiles { - public class DarkGuardian : BaseCreature - { - [Constructible] - public DarkGuardian() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class DarkGuardian : BaseCreature { - Body = 78; - BaseSoundID = 0x3E9; + [Constructible] + public DarkGuardian() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 78; + BaseSoundID = 0x3E9; - SetStr(125, 150); - SetDex(100, 120); - SetInt(200, 235); + SetStr(125, 150); + SetDex(100, 120); + SetInt(200, 235); - SetHits(150, 180); + SetHits(150, 180); - SetDamage(43, 48); + SetDamage(43, 48); - SetDamageType(ResistanceType.Physical, 10); - SetDamageType(ResistanceType.Cold, 40); - SetDamageType(ResistanceType.Energy, 50); + SetDamageType(ResistanceType.Physical, 10); + SetDamageType(ResistanceType.Cold, 40); + SetDamageType(ResistanceType.Energy, 50); - SetResistance(ResistanceType.Physical, 40, 50); - SetResistance(ResistanceType.Fire, 20, 45); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 20, 45); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 40, 50); + SetResistance(ResistanceType.Fire, 20, 45); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 20, 45); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.EvalInt, 40.1, 50); - SetSkill(SkillName.Magery, 50.1, 60.0); - SetSkill(SkillName.Meditation, 85.1, 95.0); - SetSkill(SkillName.MagicResist, 50.1, 70.0); - SetSkill(SkillName.Tactics, 50.1, 70.0); + SetSkill(SkillName.EvalInt, 40.1, 50); + SetSkill(SkillName.Magery, 50.1, 60.0); + SetSkill(SkillName.Meditation, 85.1, 95.0); + SetSkill(SkillName.MagicResist, 50.1, 70.0); + SetSkill(SkillName.Tactics, 50.1, 70.0); - Fame = 5000; - Karma = -5000; + Fame = 5000; + Karma = -5000; - VirtualArmor = 50; - PackNecroReg(15, 25); - PackItem(new DaemonBone(30)); + VirtualArmor = 50; + PackNecroReg(15, 25); + PackItem(new DaemonBone(30)); + } + + public DarkGuardian(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a dark guardians' corpse"; + public override string DefaultName => "a dark guardian"; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override int TreasureMapLevel => 2; + public override bool BleedImmune => true; + public override Poison PoisonImmune => Poison.Lethal; + public override bool Unprovokable => true; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich); + AddLoot(LootPack.MedScrolls, 2); + } + + 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(); + } } - - public DarkGuardian(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a dark guardians' corpse"; - public override string DefaultName => "a dark guardian"; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override int TreasureMapLevel => 2; - public override bool BleedImmune => true; - public override Poison PoisonImmune => Poison.Lethal; - public override bool Unprovokable => true; - - public override void GenerateLoot() - { - AddLoot(LootPack.Rich); - AddLoot(LootPack.MedScrolls, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Special/Dummy.cs b/Projects/UOContent/Mobiles/Special/Dummy.cs index 65ac08fde..80800cf88 100644 --- a/Projects/UOContent/Mobiles/Special/Dummy.cs +++ b/Projects/UOContent/Mobiles/Special/Dummy.cs @@ -3,144 +3,146 @@ using Server.Items; namespace Server.Mobiles { - /// - /// This is a test creature - /// You can set its value in game - /// It die after 5 minutes, so your test server stay clean - /// Create a macro to help your creation "[add Dummy 1 15 7 -1 0.5 2" - /// A iTeam of negative will set a faction at random - /// Say Kill if you want them to die - /// - public class Dummy : BaseCreature - { - public Timer m_Timer; - - [Constructible] - public Dummy(AIType iAI, FightMode iFightMode, int iRangePerception, int iRangeFight, double dActiveSpeed, - double dPassiveSpeed) : base(iAI, iFightMode, iRangePerception, iRangeFight, dActiveSpeed, dPassiveSpeed) + /// + /// This is a test creature + /// You can set its value in game + /// It die after 5 minutes, so your test server stay clean + /// Create a macro to help your creation "[add Dummy 1 15 7 -1 0.5 2" + /// A iTeam of negative will set a faction at random + /// Say Kill if you want them to die + /// + public class Dummy : BaseCreature { - Body = 400 + Utility.Random(2); - Hue = Race.Human.RandomSkinHue(); + public Timer m_Timer; - Skills.DetectHidden.Base = 100; - Skills.MagicResist.Base = 120; - - Team = Utility.Random(3); - - int iHue = 20 + Team * 40; - int jHue = 25 + Team * 40; - - Utility.AssignRandomHair(this, iHue); - - LeatherGloves glv = new LeatherGloves(); - glv.Hue = iHue; - glv.LootType = LootType.Newbied; - AddItem(glv); - - Container pack = new Backpack(); - - pack.Movable = false; - - AddItem(pack); - - m_Timer = new AutokillTimer(this); - m_Timer.Start(); - } - - public Dummy(Serial serial) : base(serial) - { - m_Timer = new AutokillTimer(this); - m_Timer.Start(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override bool HandlesOnSpeech(Mobile from) - { - if (from.AccessLevel >= AccessLevel.GameMaster) - return true; - - return base.HandlesOnSpeech(from); - } - - public override void OnSpeech(SpeechEventArgs e) - { - base.OnSpeech(e); - - if (e.Mobile.AccessLevel >= AccessLevel.GameMaster) - if (e.Speech == "kill") + [Constructible] + public Dummy( + AIType iAI, FightMode iFightMode, int iRangePerception, int iRangeFight, double dActiveSpeed, + double dPassiveSpeed + ) : base(iAI, iFightMode, iRangePerception, iRangeFight, dActiveSpeed, dPassiveSpeed) { - m_Timer.Stop(); - m_Timer.Delay = TimeSpan.FromSeconds(Utility.Random(1, 5)); - m_Timer.Start(); + Body = 400 + Utility.Random(2); + Hue = Race.Human.RandomSkinHue(); + + Skills.DetectHidden.Base = 100; + Skills.MagicResist.Base = 120; + + Team = Utility.Random(3); + + var iHue = 20 + Team * 40; + var jHue = 25 + Team * 40; + + Utility.AssignRandomHair(this, iHue); + + var glv = new LeatherGloves(); + glv.Hue = iHue; + glv.LootType = LootType.Newbied; + AddItem(glv); + + Container pack = new Backpack(); + + pack.Movable = false; + + AddItem(pack); + + m_Timer = new AutokillTimer(this); + m_Timer.Start(); + } + + public Dummy(Serial serial) : base(serial) + { + m_Timer = new AutokillTimer(this); + m_Timer.Start(); + } + + 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 HandlesOnSpeech(Mobile from) + { + if (from.AccessLevel >= AccessLevel.GameMaster) + return true; + + return base.HandlesOnSpeech(from); + } + + public override void OnSpeech(SpeechEventArgs e) + { + base.OnSpeech(e); + + if (e.Mobile.AccessLevel >= AccessLevel.GameMaster) + if (e.Speech == "kill") + { + m_Timer.Stop(); + m_Timer.Delay = TimeSpan.FromSeconds(Utility.Random(1, 5)); + m_Timer.Start(); + } + } + + public override void OnTeamChange() + { + var iHue = 20 + Team * 40; + var jHue = 25 + Team * 40; + + var item = FindItemOnLayer(Layer.OuterTorso); + + if (item != null) + item.Hue = jHue; + + item = FindItemOnLayer(Layer.Helm); + + if (item != null) + item.Hue = iHue; + + item = FindItemOnLayer(Layer.Gloves); + + if (item != null) + item.Hue = iHue; + + item = FindItemOnLayer(Layer.Shoes); + + if (item != null) + item.Hue = iHue; + + HairHue = iHue; + + item = FindItemOnLayer(Layer.MiddleTorso); + + if (item != null) + item.Hue = iHue; + + item = FindItemOnLayer(Layer.OuterLegs); + + if (item != null) + item.Hue = iHue; + } + + private class AutokillTimer : Timer + { + private readonly Dummy m_Owner; + + public AutokillTimer(Dummy owner) : base(TimeSpan.FromMinutes(5.0)) + { + m_Owner = owner; + Priority = TimerPriority.FiveSeconds; + } + + protected override void OnTick() + { + m_Owner.Kill(); + Stop(); + } } } - - public override void OnTeamChange() - { - int iHue = 20 + Team * 40; - int jHue = 25 + Team * 40; - - Item item = FindItemOnLayer(Layer.OuterTorso); - - if (item != null) - item.Hue = jHue; - - item = FindItemOnLayer(Layer.Helm); - - if (item != null) - item.Hue = iHue; - - item = FindItemOnLayer(Layer.Gloves); - - if (item != null) - item.Hue = iHue; - - item = FindItemOnLayer(Layer.Shoes); - - if (item != null) - item.Hue = iHue; - - HairHue = iHue; - - item = FindItemOnLayer(Layer.MiddleTorso); - - if (item != null) - item.Hue = iHue; - - item = FindItemOnLayer(Layer.OuterLegs); - - if (item != null) - item.Hue = iHue; - } - - private class AutokillTimer : Timer - { - private readonly Dummy m_Owner; - - public AutokillTimer(Dummy owner) : base(TimeSpan.FromMinutes(5.0)) - { - m_Owner = owner; - Priority = TimerPriority.FiveSeconds; - } - - protected override void OnTick() - { - m_Owner.Kill(); - Stop(); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Special/DummySpecific.cs b/Projects/UOContent/Mobiles/Special/DummySpecific.cs index 56e01b619..fc064c378 100644 --- a/Projects/UOContent/Mobiles/Special/DummySpecific.cs +++ b/Projects/UOContent/Mobiles/Special/DummySpecific.cs @@ -4,781 +4,781 @@ using Server.Spells.Third; namespace Server.Mobiles { - /// - /// This is a test creature - /// You can set its value in game - /// It die after 5 minutes, so your test server stay clean - /// Create a macro to help your creation "[add Dummy 1 15 7 -1 0.5 2" - /// A iTeam of negative will set a faction at random - /// Say Kill if you want them to die - /// - public class DummyMace : Dummy - { - [Constructible] - public DummyMace() : base(AIType.AI_Melee, FightMode.Closest, 15, 1, 0.2, 0.6) + /// + /// This is a test creature + /// You can set its value in game + /// It die after 5 minutes, so your test server stay clean + /// Create a macro to help your creation "[add Dummy 1 15 7 -1 0.5 2" + /// A iTeam of negative will set a faction at random + /// Say Kill if you want them to die + /// + public class DummyMace : Dummy { - // A Dummy Macer - int iHue = 20 + Team * 40; - int jHue = 25 + Team * 40; + [Constructible] + public DummyMace() : base(AIType.AI_Melee, FightMode.Closest, 15, 1, 0.2, 0.6) + { + // A Dummy Macer + var iHue = 20 + Team * 40; + var jHue = 25 + Team * 40; - // Skills and Stats - InitStats(125, 125, 90); - Skills.Macing.Base = 120; - Skills.Anatomy.Base = 120; - Skills.Healing.Base = 120; - Skills.Tactics.Base = 120; + // Skills and Stats + InitStats(125, 125, 90); + Skills.Macing.Base = 120; + Skills.Anatomy.Base = 120; + Skills.Healing.Base = 120; + Skills.Tactics.Base = 120; - // Equip - WarHammer war = new WarHammer(); - war.Movable = true; - war.Crafter = this; - war.Quality = WeaponQuality.Regular; - AddItem(war); + // Equip + var war = new WarHammer(); + war.Movable = true; + war.Crafter = this; + war.Quality = WeaponQuality.Regular; + AddItem(war); - Boots bts = new Boots(); - bts.Hue = iHue; - AddItem(bts); + var bts = new Boots(); + bts.Hue = iHue; + AddItem(bts); - ChainChest cht = new ChainChest(); - cht.Movable = false; - cht.LootType = LootType.Newbied; - cht.Crafter = this; - cht.Quality = ArmorQuality.Regular; - AddItem(cht); + var cht = new ChainChest(); + cht.Movable = false; + cht.LootType = LootType.Newbied; + cht.Crafter = this; + cht.Quality = ArmorQuality.Regular; + AddItem(cht); - ChainLegs chl = new ChainLegs(); - chl.Movable = false; - chl.LootType = LootType.Newbied; - chl.Crafter = this; - chl.Quality = ArmorQuality.Regular; - AddItem(chl); + var chl = new ChainLegs(); + chl.Movable = false; + chl.LootType = LootType.Newbied; + chl.Crafter = this; + chl.Quality = ArmorQuality.Regular; + AddItem(chl); - PlateArms pla = new PlateArms(); - pla.Movable = false; - pla.LootType = LootType.Newbied; - pla.Crafter = this; - pla.Quality = ArmorQuality.Regular; - AddItem(pla); + var pla = new PlateArms(); + pla.Movable = false; + pla.LootType = LootType.Newbied; + pla.Crafter = this; + pla.Quality = ArmorQuality.Regular; + AddItem(pla); - Bandage band = new Bandage(50); - AddToBackpack(band); + var band = new Bandage(50); + AddToBackpack(band); + } + + public DummyMace(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Macer"; + + 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 DummyMace(Serial serial) : base(serial) + public class DummyFence : Dummy { + [Constructible] + public DummyFence() : base(AIType.AI_Melee, FightMode.Closest, 15, 1, 0.2, 0.6) + { + // A Dummy Fencer + var iHue = 20 + Team * 40; + var jHue = 25 + Team * 40; + + // Skills and Stats + InitStats(125, 125, 90); + Skills.Fencing.Base = 120; + Skills.Anatomy.Base = 120; + Skills.Healing.Base = 120; + Skills.Tactics.Base = 120; + + // Equip + var ssp = new Spear(); + ssp.Movable = true; + ssp.Crafter = this; + ssp.Quality = WeaponQuality.Regular; + AddItem(ssp); + + var snd = new Boots(); + snd.Hue = iHue; + snd.LootType = LootType.Newbied; + AddItem(snd); + + var cht = new ChainChest(); + cht.Movable = false; + cht.LootType = LootType.Newbied; + cht.Crafter = this; + cht.Quality = ArmorQuality.Regular; + AddItem(cht); + + var chl = new ChainLegs(); + chl.Movable = false; + chl.LootType = LootType.Newbied; + chl.Crafter = this; + chl.Quality = ArmorQuality.Regular; + AddItem(chl); + + var pla = new PlateArms(); + pla.Movable = false; + pla.LootType = LootType.Newbied; + pla.Crafter = this; + pla.Quality = ArmorQuality.Regular; + AddItem(pla); + + var band = new Bandage(50); + AddToBackpack(band); + } + + public DummyFence(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Fencer"; + + 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 string DefaultName => "Macer"; - - public override void Serialize(IGenericWriter writer) + public class DummySword : Dummy { - base.Serialize(writer); + [Constructible] + public DummySword() : base(AIType.AI_Melee, FightMode.Closest, 15, 1, 0.2, 0.6) + { + // A Dummy Swordsman + var iHue = 20 + Team * 40; + var jHue = 25 + Team * 40; - writer.Write(0); // version + // Skills and Stats + InitStats(125, 125, 90); + Skills.Swords.Base = 120; + Skills.Anatomy.Base = 120; + Skills.Healing.Base = 120; + Skills.Tactics.Base = 120; + Skills.Parry.Base = 120; + + // Equip + var kat = new Katana(); + kat.Crafter = this; + kat.Movable = true; + kat.Quality = WeaponQuality.Regular; + AddItem(kat); + + var bts = new Boots(); + bts.Hue = iHue; + AddItem(bts); + + var cht = new ChainChest(); + cht.Movable = false; + cht.LootType = LootType.Newbied; + cht.Crafter = this; + cht.Quality = ArmorQuality.Regular; + AddItem(cht); + + var chl = new ChainLegs(); + chl.Movable = false; + chl.LootType = LootType.Newbied; + chl.Crafter = this; + chl.Quality = ArmorQuality.Regular; + AddItem(chl); + + var pla = new PlateArms(); + pla.Movable = false; + pla.LootType = LootType.Newbied; + pla.Crafter = this; + pla.Quality = ArmorQuality.Regular; + AddItem(pla); + + var band = new Bandage(50); + AddToBackpack(band); + } + + public DummySword(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Swordsman"; + + 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 Deserialize(IGenericReader reader) + public class DummyNox : Dummy { - base.Deserialize(reader); + [Constructible] + public DummyNox() : base(AIType.AI_Mage, FightMode.Closest, 15, 1, 0.2, 0.6) + { + // A Dummy Nox or Pure Mage + var iHue = 20 + Team * 40; + var jHue = 25 + Team * 40; - int version = reader.ReadInt(); - } - } + // Skills and Stats + InitStats(90, 90, 125); + Skills.Magery.Base = 120; + Skills.EvalInt.Base = 120; + Skills.Inscribe.Base = 100; + Skills.Wrestling.Base = 120; + Skills.Meditation.Base = 120; + Skills.Poisoning.Base = 100; - public class DummyFence : Dummy - { - [Constructible] - public DummyFence() : base(AIType.AI_Melee, FightMode.Closest, 15, 1, 0.2, 0.6) - { - // A Dummy Fencer - int iHue = 20 + Team * 40; - int jHue = 25 + Team * 40; + // Equip + var book = new Spellbook(); + book.Movable = false; + book.LootType = LootType.Newbied; + book.Content = 0xFFFFFFFFFFFFFFFF; + AddItem(book); - // Skills and Stats - InitStats(125, 125, 90); - Skills.Fencing.Base = 120; - Skills.Anatomy.Base = 120; - Skills.Healing.Base = 120; - Skills.Tactics.Base = 120; + var kilt = new Kilt(); + kilt.Hue = jHue; + AddItem(kilt); - // Equip - Spear ssp = new Spear(); - ssp.Movable = true; - ssp.Crafter = this; - ssp.Quality = WeaponQuality.Regular; - AddItem(ssp); + var snd = new Sandals(); + snd.Hue = iHue; + snd.LootType = LootType.Newbied; + AddItem(snd); - Boots snd = new Boots(); - snd.Hue = iHue; - snd.LootType = LootType.Newbied; - AddItem(snd); + var skc = new SkullCap(); + skc.Hue = iHue; + AddItem(skc); - ChainChest cht = new ChainChest(); - cht.Movable = false; - cht.LootType = LootType.Newbied; - cht.Crafter = this; - cht.Quality = ArmorQuality.Regular; - AddItem(cht); + // Spells + AddSpellAttack(typeof(MagicArrowSpell)); + AddSpellAttack(typeof(WeakenSpell)); + AddSpellAttack(typeof(FireballSpell)); + AddSpellDefense(typeof(WallOfStoneSpell)); + AddSpellDefense(typeof(HealSpell)); + } - ChainLegs chl = new ChainLegs(); - chl.Movable = false; - chl.LootType = LootType.Newbied; - chl.Crafter = this; - chl.Quality = ArmorQuality.Regular; - AddItem(chl); + public DummyNox(Serial serial) : base(serial) + { + } - PlateArms pla = new PlateArms(); - pla.Movable = false; - pla.LootType = LootType.Newbied; - pla.Crafter = this; - pla.Quality = ArmorQuality.Regular; - AddItem(pla); + public override string DefaultName => "Nox Mage"; - Bandage band = new Bandage(50); - AddToBackpack(band); + 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 DummyFence(Serial serial) : base(serial) + public class DummyStun : Dummy { + [Constructible] + public DummyStun() : base(AIType.AI_Mage, FightMode.Closest, 15, 1, 0.2, 0.6) + { + // A Dummy Stun Mage + var iHue = 20 + Team * 40; + var jHue = 25 + Team * 40; + + // Skills and Stats + InitStats(90, 90, 125); + Skills.Magery.Base = 100; + Skills.EvalInt.Base = 120; + Skills.Anatomy.Base = 80; + Skills.Wrestling.Base = 80; + Skills.Meditation.Base = 100; + Skills.Poisoning.Base = 100; + + // Equip + var book = new Spellbook(); + book.Movable = false; + book.LootType = LootType.Newbied; + book.Content = 0xFFFFFFFFFFFFFFFF; + AddItem(book); + + var lea = new LeatherArms(); + lea.Movable = false; + lea.LootType = LootType.Newbied; + lea.Crafter = this; + lea.Quality = ArmorQuality.Regular; + AddItem(lea); + + var lec = new LeatherChest(); + lec.Movable = false; + lec.LootType = LootType.Newbied; + lec.Crafter = this; + lec.Quality = ArmorQuality.Regular; + AddItem(lec); + + var leg = new LeatherGorget(); + leg.Movable = false; + leg.LootType = LootType.Newbied; + leg.Crafter = this; + leg.Quality = ArmorQuality.Regular; + AddItem(leg); + + var lel = new LeatherLegs(); + lel.Movable = false; + lel.LootType = LootType.Newbied; + lel.Crafter = this; + lel.Quality = ArmorQuality.Regular; + AddItem(lel); + + var bts = new Boots(); + bts.Hue = iHue; + AddItem(bts); + + var cap = new Cap(); + cap.Hue = iHue; + AddItem(cap); + + // Spells + AddSpellAttack(typeof(MagicArrowSpell)); + AddSpellAttack(typeof(WeakenSpell)); + AddSpellAttack(typeof(FireballSpell)); + AddSpellDefense(typeof(WallOfStoneSpell)); + AddSpellDefense(typeof(HealSpell)); + } + + public DummyStun(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Stun Mage"; + + 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 string DefaultName => "Fencer"; - - public override void Serialize(IGenericWriter writer) + public class DummySuper : Dummy { - base.Serialize(writer); + [Constructible] + public DummySuper() : base(AIType.AI_Mage, FightMode.Closest, 15, 1, 0.2, 0.6) + { + // A Dummy Super Mage + var iHue = 20 + Team * 40; + var jHue = 25 + Team * 40; - writer.Write(0); // version + // Skills and Stats + InitStats(125, 125, 125); + Skills.Magery.Base = 120; + Skills.EvalInt.Base = 120; + Skills.Anatomy.Base = 120; + Skills.Wrestling.Base = 120; + Skills.Meditation.Base = 120; + Skills.Poisoning.Base = 100; + Skills.Inscribe.Base = 100; + + // Equip + var book = new Spellbook(); + book.Movable = false; + book.LootType = LootType.Newbied; + book.Content = 0xFFFFFFFFFFFFFFFF; + AddItem(book); + + var lea = new LeatherArms(); + lea.Movable = false; + lea.LootType = LootType.Newbied; + lea.Crafter = this; + lea.Quality = ArmorQuality.Regular; + AddItem(lea); + + var lec = new LeatherChest(); + lec.Movable = false; + lec.LootType = LootType.Newbied; + lec.Crafter = this; + lec.Quality = ArmorQuality.Regular; + AddItem(lec); + + var leg = new LeatherGorget(); + leg.Movable = false; + leg.LootType = LootType.Newbied; + leg.Crafter = this; + leg.Quality = ArmorQuality.Regular; + AddItem(leg); + + var lel = new LeatherLegs(); + lel.Movable = false; + lel.LootType = LootType.Newbied; + lel.Crafter = this; + lel.Quality = ArmorQuality.Regular; + AddItem(lel); + + var snd = new Sandals(); + snd.Hue = iHue; + snd.LootType = LootType.Newbied; + AddItem(snd); + + var jhat = new JesterHat(); + jhat.Hue = iHue; + AddItem(jhat); + + var dblt = new Doublet(); + dblt.Hue = iHue; + AddItem(dblt); + + // Spells + AddSpellAttack(typeof(MagicArrowSpell)); + AddSpellAttack(typeof(WeakenSpell)); + AddSpellAttack(typeof(FireballSpell)); + AddSpellDefense(typeof(WallOfStoneSpell)); + AddSpellDefense(typeof(HealSpell)); + } + + public DummySuper(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Super Mage"; + + 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 Deserialize(IGenericReader reader) + public class DummyHealer : Dummy { - base.Deserialize(reader); + [Constructible] + public DummyHealer() : base(AIType.AI_Healer, FightMode.Closest, 15, 1, 0.2, 0.6) + { + // A Dummy Healer Mage + var iHue = 20 + Team * 40; + var jHue = 25 + Team * 40; - int version = reader.ReadInt(); - } - } + // Skills and Stats + InitStats(125, 125, 125); + Skills.Magery.Base = 120; + Skills.EvalInt.Base = 120; + Skills.Anatomy.Base = 120; + Skills.Wrestling.Base = 120; + Skills.Meditation.Base = 120; + Skills.Healing.Base = 100; - public class DummySword : Dummy - { - [Constructible] - public DummySword() : base(AIType.AI_Melee, FightMode.Closest, 15, 1, 0.2, 0.6) - { - // A Dummy Swordsman - int iHue = 20 + Team * 40; - int jHue = 25 + Team * 40; + // Equip + var book = new Spellbook(); + book.Movable = false; + book.LootType = LootType.Newbied; + book.Content = 0xFFFFFFFFFFFFFFFF; + AddItem(book); - // Skills and Stats - InitStats(125, 125, 90); - Skills.Swords.Base = 120; - Skills.Anatomy.Base = 120; - Skills.Healing.Base = 120; - Skills.Tactics.Base = 120; - Skills.Parry.Base = 120; + var lea = new LeatherArms(); + lea.Movable = false; + lea.LootType = LootType.Newbied; + lea.Crafter = this; + lea.Quality = ArmorQuality.Regular; + AddItem(lea); - // Equip - Katana kat = new Katana(); - kat.Crafter = this; - kat.Movable = true; - kat.Quality = WeaponQuality.Regular; - AddItem(kat); + var lec = new LeatherChest(); + lec.Movable = false; + lec.LootType = LootType.Newbied; + lec.Crafter = this; + lec.Quality = ArmorQuality.Regular; + AddItem(lec); - Boots bts = new Boots(); - bts.Hue = iHue; - AddItem(bts); + var leg = new LeatherGorget(); + leg.Movable = false; + leg.LootType = LootType.Newbied; + leg.Crafter = this; + leg.Quality = ArmorQuality.Regular; + AddItem(leg); - ChainChest cht = new ChainChest(); - cht.Movable = false; - cht.LootType = LootType.Newbied; - cht.Crafter = this; - cht.Quality = ArmorQuality.Regular; - AddItem(cht); + var lel = new LeatherLegs(); + lel.Movable = false; + lel.LootType = LootType.Newbied; + lel.Crafter = this; + lel.Quality = ArmorQuality.Regular; + AddItem(lel); - ChainLegs chl = new ChainLegs(); - chl.Movable = false; - chl.LootType = LootType.Newbied; - chl.Crafter = this; - chl.Quality = ArmorQuality.Regular; - AddItem(chl); + var snd = new Sandals(); + snd.Hue = iHue; + snd.LootType = LootType.Newbied; + AddItem(snd); - PlateArms pla = new PlateArms(); - pla.Movable = false; - pla.LootType = LootType.Newbied; - pla.Crafter = this; - pla.Quality = ArmorQuality.Regular; - AddItem(pla); + var cap = new Cap(); + cap.Hue = iHue; + AddItem(cap); - Bandage band = new Bandage(50); - AddToBackpack(band); + var robe = new Robe(); + robe.Hue = iHue; + AddItem(robe); + } + + public DummyHealer(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Healer"; + + 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 DummySword(Serial serial) : base(serial) + public class DummyAssassin : Dummy { + [Constructible] + public DummyAssassin() : base(AIType.AI_Melee, FightMode.Closest, 15, 1, 0.2, 0.6) + { + // A Dummy Hybrid Assassin + var iHue = 20 + Team * 40; + var jHue = 25 + Team * 40; + + // Skills and Stats + InitStats(105, 105, 105); + Skills.Magery.Base = 120; + Skills.EvalInt.Base = 120; + Skills.Swords.Base = 120; + Skills.Tactics.Base = 120; + Skills.Meditation.Base = 120; + Skills.Poisoning.Base = 100; + + // Equip + var book = new Spellbook(); + book.Movable = false; + book.LootType = LootType.Newbied; + book.Content = 0xFFFFFFFFFFFFFFFF; + AddToBackpack(book); + + var kat = new Katana(); + kat.Movable = false; + kat.LootType = LootType.Newbied; + kat.Crafter = this; + kat.Poison = Poison.Deadly; + kat.PoisonCharges = 12; + kat.Quality = WeaponQuality.Regular; + AddToBackpack(kat); + + var lea = new LeatherArms(); + lea.Movable = false; + lea.LootType = LootType.Newbied; + lea.Crafter = this; + lea.Quality = ArmorQuality.Regular; + AddItem(lea); + + var lec = new LeatherChest(); + lec.Movable = false; + lec.LootType = LootType.Newbied; + lec.Crafter = this; + lec.Quality = ArmorQuality.Regular; + AddItem(lec); + + var leg = new LeatherGorget(); + leg.Movable = false; + leg.LootType = LootType.Newbied; + leg.Crafter = this; + leg.Quality = ArmorQuality.Regular; + AddItem(leg); + + var lel = new LeatherLegs(); + lel.Movable = false; + lel.LootType = LootType.Newbied; + lel.Crafter = this; + lel.Quality = ArmorQuality.Regular; + AddItem(lel); + + var snd = new Sandals(); + snd.Hue = iHue; + snd.LootType = LootType.Newbied; + AddItem(snd); + + var cap = new Cap(); + cap.Hue = iHue; + AddItem(cap); + + var robe = new Robe(); + robe.Hue = iHue; + AddItem(robe); + + var pota = new DeadlyPoisonPotion(); + pota.LootType = LootType.Newbied; + AddToBackpack(pota); + + var potb = new DeadlyPoisonPotion(); + potb.LootType = LootType.Newbied; + AddToBackpack(potb); + + var potc = new DeadlyPoisonPotion(); + potc.LootType = LootType.Newbied; + AddToBackpack(potc); + + var potd = new DeadlyPoisonPotion(); + potd.LootType = LootType.Newbied; + AddToBackpack(potd); + + var band = new Bandage(50); + AddToBackpack(band); + } + + public DummyAssassin(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Hybrid Assassin"; + + 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 string DefaultName => "Swordsman"; - - public override void Serialize(IGenericWriter writer) + [TypeAlias("Server.Mobiles.DummyTheif")] + public class DummyThief : Dummy { - base.Serialize(writer); + [Constructible] + public DummyThief() : base(AIType.AI_Thief, FightMode.Closest, 15, 1, 0.2, 0.6) + { + // A Dummy Hybrid Thief + var iHue = 20 + Team * 40; + var jHue = 25 + Team * 40; - writer.Write(0); // version + // Skills and Stats + InitStats(105, 105, 105); + Skills.Healing.Base = 120; + Skills.Anatomy.Base = 120; + Skills.Stealing.Base = 120; + Skills.ArmsLore.Base = 100; + Skills.Meditation.Base = 120; + Skills.Wrestling.Base = 120; + + // Equip + var book = new Spellbook(); + book.Movable = false; + book.LootType = LootType.Newbied; + book.Content = 0xFFFFFFFFFFFFFFFF; + AddItem(book); + + var lea = new LeatherArms(); + lea.Movable = false; + lea.LootType = LootType.Newbied; + lea.Crafter = this; + lea.Quality = ArmorQuality.Regular; + AddItem(lea); + + var lec = new LeatherChest(); + lec.Movable = false; + lec.LootType = LootType.Newbied; + lec.Crafter = this; + lec.Quality = ArmorQuality.Regular; + AddItem(lec); + + var leg = new LeatherGorget(); + leg.Movable = false; + leg.LootType = LootType.Newbied; + leg.Crafter = this; + leg.Quality = ArmorQuality.Regular; + AddItem(leg); + + var lel = new LeatherLegs(); + lel.Movable = false; + lel.LootType = LootType.Newbied; + lel.Crafter = this; + lel.Quality = ArmorQuality.Regular; + AddItem(lel); + + var snd = new Sandals(); + snd.Hue = iHue; + snd.LootType = LootType.Newbied; + AddItem(snd); + + var cap = new Cap(); + cap.Hue = iHue; + AddItem(cap); + + var robe = new Robe(); + robe.Hue = iHue; + AddItem(robe); + + var band = new Bandage(50); + AddToBackpack(band); + } + + public DummyThief(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Hybrid Thief"; + + 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 Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DummyNox : Dummy - { - [Constructible] - public DummyNox() : base(AIType.AI_Mage, FightMode.Closest, 15, 1, 0.2, 0.6) - { - // A Dummy Nox or Pure Mage - int iHue = 20 + Team * 40; - int jHue = 25 + Team * 40; - - // Skills and Stats - InitStats(90, 90, 125); - Skills.Magery.Base = 120; - Skills.EvalInt.Base = 120; - Skills.Inscribe.Base = 100; - Skills.Wrestling.Base = 120; - Skills.Meditation.Base = 120; - Skills.Poisoning.Base = 100; - - // Equip - Spellbook book = new Spellbook(); - book.Movable = false; - book.LootType = LootType.Newbied; - book.Content = 0xFFFFFFFFFFFFFFFF; - AddItem(book); - - Kilt kilt = new Kilt(); - kilt.Hue = jHue; - AddItem(kilt); - - Sandals snd = new Sandals(); - snd.Hue = iHue; - snd.LootType = LootType.Newbied; - AddItem(snd); - - SkullCap skc = new SkullCap(); - skc.Hue = iHue; - AddItem(skc); - - // Spells - AddSpellAttack(typeof(MagicArrowSpell)); - AddSpellAttack(typeof(WeakenSpell)); - AddSpellAttack(typeof(FireballSpell)); - AddSpellDefense(typeof(WallOfStoneSpell)); - AddSpellDefense(typeof(HealSpell)); - } - - public DummyNox(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Nox Mage"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DummyStun : Dummy - { - [Constructible] - public DummyStun() : base(AIType.AI_Mage, FightMode.Closest, 15, 1, 0.2, 0.6) - { - // A Dummy Stun Mage - int iHue = 20 + Team * 40; - int jHue = 25 + Team * 40; - - // Skills and Stats - InitStats(90, 90, 125); - Skills.Magery.Base = 100; - Skills.EvalInt.Base = 120; - Skills.Anatomy.Base = 80; - Skills.Wrestling.Base = 80; - Skills.Meditation.Base = 100; - Skills.Poisoning.Base = 100; - - // Equip - Spellbook book = new Spellbook(); - book.Movable = false; - book.LootType = LootType.Newbied; - book.Content = 0xFFFFFFFFFFFFFFFF; - AddItem(book); - - LeatherArms lea = new LeatherArms(); - lea.Movable = false; - lea.LootType = LootType.Newbied; - lea.Crafter = this; - lea.Quality = ArmorQuality.Regular; - AddItem(lea); - - LeatherChest lec = new LeatherChest(); - lec.Movable = false; - lec.LootType = LootType.Newbied; - lec.Crafter = this; - lec.Quality = ArmorQuality.Regular; - AddItem(lec); - - LeatherGorget leg = new LeatherGorget(); - leg.Movable = false; - leg.LootType = LootType.Newbied; - leg.Crafter = this; - leg.Quality = ArmorQuality.Regular; - AddItem(leg); - - LeatherLegs lel = new LeatherLegs(); - lel.Movable = false; - lel.LootType = LootType.Newbied; - lel.Crafter = this; - lel.Quality = ArmorQuality.Regular; - AddItem(lel); - - Boots bts = new Boots(); - bts.Hue = iHue; - AddItem(bts); - - Cap cap = new Cap(); - cap.Hue = iHue; - AddItem(cap); - - // Spells - AddSpellAttack(typeof(MagicArrowSpell)); - AddSpellAttack(typeof(WeakenSpell)); - AddSpellAttack(typeof(FireballSpell)); - AddSpellDefense(typeof(WallOfStoneSpell)); - AddSpellDefense(typeof(HealSpell)); - } - - public DummyStun(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Stun Mage"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DummySuper : Dummy - { - [Constructible] - public DummySuper() : base(AIType.AI_Mage, FightMode.Closest, 15, 1, 0.2, 0.6) - { - // A Dummy Super Mage - int iHue = 20 + Team * 40; - int jHue = 25 + Team * 40; - - // Skills and Stats - InitStats(125, 125, 125); - Skills.Magery.Base = 120; - Skills.EvalInt.Base = 120; - Skills.Anatomy.Base = 120; - Skills.Wrestling.Base = 120; - Skills.Meditation.Base = 120; - Skills.Poisoning.Base = 100; - Skills.Inscribe.Base = 100; - - // Equip - Spellbook book = new Spellbook(); - book.Movable = false; - book.LootType = LootType.Newbied; - book.Content = 0xFFFFFFFFFFFFFFFF; - AddItem(book); - - LeatherArms lea = new LeatherArms(); - lea.Movable = false; - lea.LootType = LootType.Newbied; - lea.Crafter = this; - lea.Quality = ArmorQuality.Regular; - AddItem(lea); - - LeatherChest lec = new LeatherChest(); - lec.Movable = false; - lec.LootType = LootType.Newbied; - lec.Crafter = this; - lec.Quality = ArmorQuality.Regular; - AddItem(lec); - - LeatherGorget leg = new LeatherGorget(); - leg.Movable = false; - leg.LootType = LootType.Newbied; - leg.Crafter = this; - leg.Quality = ArmorQuality.Regular; - AddItem(leg); - - LeatherLegs lel = new LeatherLegs(); - lel.Movable = false; - lel.LootType = LootType.Newbied; - lel.Crafter = this; - lel.Quality = ArmorQuality.Regular; - AddItem(lel); - - Sandals snd = new Sandals(); - snd.Hue = iHue; - snd.LootType = LootType.Newbied; - AddItem(snd); - - JesterHat jhat = new JesterHat(); - jhat.Hue = iHue; - AddItem(jhat); - - Doublet dblt = new Doublet(); - dblt.Hue = iHue; - AddItem(dblt); - - // Spells - AddSpellAttack(typeof(MagicArrowSpell)); - AddSpellAttack(typeof(WeakenSpell)); - AddSpellAttack(typeof(FireballSpell)); - AddSpellDefense(typeof(WallOfStoneSpell)); - AddSpellDefense(typeof(HealSpell)); - } - - public DummySuper(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Super Mage"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DummyHealer : Dummy - { - [Constructible] - public DummyHealer() : base(AIType.AI_Healer, FightMode.Closest, 15, 1, 0.2, 0.6) - { - // A Dummy Healer Mage - int iHue = 20 + Team * 40; - int jHue = 25 + Team * 40; - - // Skills and Stats - InitStats(125, 125, 125); - Skills.Magery.Base = 120; - Skills.EvalInt.Base = 120; - Skills.Anatomy.Base = 120; - Skills.Wrestling.Base = 120; - Skills.Meditation.Base = 120; - Skills.Healing.Base = 100; - - // Equip - Spellbook book = new Spellbook(); - book.Movable = false; - book.LootType = LootType.Newbied; - book.Content = 0xFFFFFFFFFFFFFFFF; - AddItem(book); - - LeatherArms lea = new LeatherArms(); - lea.Movable = false; - lea.LootType = LootType.Newbied; - lea.Crafter = this; - lea.Quality = ArmorQuality.Regular; - AddItem(lea); - - LeatherChest lec = new LeatherChest(); - lec.Movable = false; - lec.LootType = LootType.Newbied; - lec.Crafter = this; - lec.Quality = ArmorQuality.Regular; - AddItem(lec); - - LeatherGorget leg = new LeatherGorget(); - leg.Movable = false; - leg.LootType = LootType.Newbied; - leg.Crafter = this; - leg.Quality = ArmorQuality.Regular; - AddItem(leg); - - LeatherLegs lel = new LeatherLegs(); - lel.Movable = false; - lel.LootType = LootType.Newbied; - lel.Crafter = this; - lel.Quality = ArmorQuality.Regular; - AddItem(lel); - - Sandals snd = new Sandals(); - snd.Hue = iHue; - snd.LootType = LootType.Newbied; - AddItem(snd); - - Cap cap = new Cap(); - cap.Hue = iHue; - AddItem(cap); - - Robe robe = new Robe(); - robe.Hue = iHue; - AddItem(robe); - } - - public DummyHealer(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Healer"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class DummyAssassin : Dummy - { - [Constructible] - public DummyAssassin() : base(AIType.AI_Melee, FightMode.Closest, 15, 1, 0.2, 0.6) - { - // A Dummy Hybrid Assassin - int iHue = 20 + Team * 40; - int jHue = 25 + Team * 40; - - // Skills and Stats - InitStats(105, 105, 105); - Skills.Magery.Base = 120; - Skills.EvalInt.Base = 120; - Skills.Swords.Base = 120; - Skills.Tactics.Base = 120; - Skills.Meditation.Base = 120; - Skills.Poisoning.Base = 100; - - // Equip - Spellbook book = new Spellbook(); - book.Movable = false; - book.LootType = LootType.Newbied; - book.Content = 0xFFFFFFFFFFFFFFFF; - AddToBackpack(book); - - Katana kat = new Katana(); - kat.Movable = false; - kat.LootType = LootType.Newbied; - kat.Crafter = this; - kat.Poison = Poison.Deadly; - kat.PoisonCharges = 12; - kat.Quality = WeaponQuality.Regular; - AddToBackpack(kat); - - LeatherArms lea = new LeatherArms(); - lea.Movable = false; - lea.LootType = LootType.Newbied; - lea.Crafter = this; - lea.Quality = ArmorQuality.Regular; - AddItem(lea); - - LeatherChest lec = new LeatherChest(); - lec.Movable = false; - lec.LootType = LootType.Newbied; - lec.Crafter = this; - lec.Quality = ArmorQuality.Regular; - AddItem(lec); - - LeatherGorget leg = new LeatherGorget(); - leg.Movable = false; - leg.LootType = LootType.Newbied; - leg.Crafter = this; - leg.Quality = ArmorQuality.Regular; - AddItem(leg); - - LeatherLegs lel = new LeatherLegs(); - lel.Movable = false; - lel.LootType = LootType.Newbied; - lel.Crafter = this; - lel.Quality = ArmorQuality.Regular; - AddItem(lel); - - Sandals snd = new Sandals(); - snd.Hue = iHue; - snd.LootType = LootType.Newbied; - AddItem(snd); - - Cap cap = new Cap(); - cap.Hue = iHue; - AddItem(cap); - - Robe robe = new Robe(); - robe.Hue = iHue; - AddItem(robe); - - DeadlyPoisonPotion pota = new DeadlyPoisonPotion(); - pota.LootType = LootType.Newbied; - AddToBackpack(pota); - - DeadlyPoisonPotion potb = new DeadlyPoisonPotion(); - potb.LootType = LootType.Newbied; - AddToBackpack(potb); - - DeadlyPoisonPotion potc = new DeadlyPoisonPotion(); - potc.LootType = LootType.Newbied; - AddToBackpack(potc); - - DeadlyPoisonPotion potd = new DeadlyPoisonPotion(); - potd.LootType = LootType.Newbied; - AddToBackpack(potd); - - Bandage band = new Bandage(50); - AddToBackpack(band); - } - - public DummyAssassin(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Hybrid Assassin"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - [TypeAlias("Server.Mobiles.DummyTheif")] - public class DummyThief : Dummy - { - [Constructible] - public DummyThief() : base(AIType.AI_Thief, FightMode.Closest, 15, 1, 0.2, 0.6) - { - // A Dummy Hybrid Thief - int iHue = 20 + Team * 40; - int jHue = 25 + Team * 40; - - // Skills and Stats - InitStats(105, 105, 105); - Skills.Healing.Base = 120; - Skills.Anatomy.Base = 120; - Skills.Stealing.Base = 120; - Skills.ArmsLore.Base = 100; - Skills.Meditation.Base = 120; - Skills.Wrestling.Base = 120; - - // Equip - Spellbook book = new Spellbook(); - book.Movable = false; - book.LootType = LootType.Newbied; - book.Content = 0xFFFFFFFFFFFFFFFF; - AddItem(book); - - LeatherArms lea = new LeatherArms(); - lea.Movable = false; - lea.LootType = LootType.Newbied; - lea.Crafter = this; - lea.Quality = ArmorQuality.Regular; - AddItem(lea); - - LeatherChest lec = new LeatherChest(); - lec.Movable = false; - lec.LootType = LootType.Newbied; - lec.Crafter = this; - lec.Quality = ArmorQuality.Regular; - AddItem(lec); - - LeatherGorget leg = new LeatherGorget(); - leg.Movable = false; - leg.LootType = LootType.Newbied; - leg.Crafter = this; - leg.Quality = ArmorQuality.Regular; - AddItem(leg); - - LeatherLegs lel = new LeatherLegs(); - lel.Movable = false; - lel.LootType = LootType.Newbied; - lel.Crafter = this; - lel.Quality = ArmorQuality.Regular; - AddItem(lel); - - Sandals snd = new Sandals(); - snd.Hue = iHue; - snd.LootType = LootType.Newbied; - AddItem(snd); - - Cap cap = new Cap(); - cap.Hue = iHue; - AddItem(cap); - - Robe robe = new Robe(); - robe.Hue = iHue; - AddItem(robe); - - Bandage band = new Bandage(50); - AddToBackpack(band); - } - - public DummyThief(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Hybrid Thief"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Special/Harrower.cs b/Projects/UOContent/Mobiles/Special/Harrower.cs index cdb6ef898..abad1d6ef 100644 --- a/Projects/UOContent/Mobiles/Special/Harrower.cs +++ b/Projects/UOContent/Mobiles/Special/Harrower.cs @@ -6,615 +6,641 @@ using Server.Spells; namespace Server.Mobiles { - public class Harrower : BaseCreature - { - private static readonly SpawnEntry[] m_Entries = + public class Harrower : BaseCreature { - new SpawnEntry(new Point3D(5242, 945, -40), new Point3D(1176, 2638, 0)), // Destard - new SpawnEntry(new Point3D(5225, 798, 0), new Point3D(1176, 2638, 0)), // Destard - new SpawnEntry(new Point3D(5556, 886, 30), new Point3D(1298, 1080, 0)), // Despise - new SpawnEntry(new Point3D(5187, 615, 0), new Point3D(4111, 432, 5)), // Deceit - new SpawnEntry(new Point3D(5319, 583, 0), new Point3D(4111, 432, 5)), // Deceit - new SpawnEntry(new Point3D(5713, 1334, -1), new Point3D(2923, 3407, 8)), // Fire - new SpawnEntry(new Point3D(5860, 1460, -2), new Point3D(2923, 3407, 8)), // Fire - new SpawnEntry(new Point3D(5328, 1620, 0), new Point3D(5451, 3143, -60)), // Terathan Keep - new SpawnEntry(new Point3D(5690, 538, 0), new Point3D(2042, 224, 14)), // Wrong - new SpawnEntry(new Point3D(5609, 195, 0), new Point3D(514, 1561, 0)), // Shame - new SpawnEntry(new Point3D(5475, 187, 0), new Point3D(514, 1561, 0)), // Shame - new SpawnEntry(new Point3D(6085, 179, 0), new Point3D(4721, 3822, 0)), // Hythloth - new SpawnEntry(new Point3D(6084, 66, 0), new Point3D(4721, 3822, 0)), // Hythloth - new SpawnEntry(new Point3D(5499, 2003, 0), new Point3D(2499, 919, 0)), // Covetous - new SpawnEntry(new Point3D(5579, 1858, 0), new Point3D(2499, 919, 0)) // Covetous - }; - - private static readonly double[] m_Offsets = - { - Math.Cos(000.0 / 180.0 * Math.PI), Math.Sin(000.0 / 180.0 * Math.PI), - Math.Cos(040.0 / 180.0 * Math.PI), Math.Sin(040.0 / 180.0 * Math.PI), - Math.Cos(080.0 / 180.0 * Math.PI), Math.Sin(080.0 / 180.0 * Math.PI), - Math.Cos(120.0 / 180.0 * Math.PI), Math.Sin(120.0 / 180.0 * Math.PI), - Math.Cos(160.0 / 180.0 * Math.PI), Math.Sin(160.0 / 180.0 * Math.PI), - Math.Cos(200.0 / 180.0 * Math.PI), Math.Sin(200.0 / 180.0 * Math.PI), - Math.Cos(240.0 / 180.0 * Math.PI), Math.Sin(240.0 / 180.0 * Math.PI), - Math.Cos(280.0 / 180.0 * Math.PI), Math.Sin(280.0 / 180.0 * Math.PI), - Math.Cos(320.0 / 180.0 * Math.PI), Math.Sin(320.0 / 180.0 * Math.PI) - }; - - private Dictionary m_DamageEntries; - private Item m_GateItem; - private List m_Tentacles; - private Timer m_Timer; - - private bool m_TrueForm; - - [Constructible] - public Harrower() : base(AIType.AI_Mage, FightMode.Closest, 18, 1, 0.2, 0.4) - { - Instances.Add(this); - BodyValue = 146; - - SetStr(900, 1000); - SetDex(125, 135); - SetInt(1000, 1200); - - Fame = 22500; - Karma = -22500; - - VirtualArmor = 60; - - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Energy, 50); - - SetResistance(ResistanceType.Physical, 55, 65); - SetResistance(ResistanceType.Fire, 60, 80); - SetResistance(ResistanceType.Cold, 60, 80); - SetResistance(ResistanceType.Poison, 60, 80); - SetResistance(ResistanceType.Energy, 60, 80); - - SetSkill(SkillName.Wrestling, 90.1, 100.0); - SetSkill(SkillName.Tactics, 90.2, 110.0); - SetSkill(SkillName.MagicResist, 120.2, 160.0); - SetSkill(SkillName.Magery, 120.0); - SetSkill(SkillName.EvalInt, 120.0); - SetSkill(SkillName.Meditation, 120.0); - - m_Tentacles = new List(); - - m_Timer = new TeleportTimer(this); - m_Timer.Start(); - } - - public Harrower(Serial serial) : base(serial) - { - Instances.Add(this); - } - - public Type[] UniqueList => new[] { typeof(AcidProofRobe) }; - public Type[] SharedList => new[] { typeof(TheRobeOfBritanniaAri) }; - public Type[] DecorativeList => new[] { typeof(EvilIdolSkull), typeof(SkullPole) }; - - public static List Instances { get; } = new List(); - - public static bool CanSpawn => Instances.Count == 0; - - public override string DefaultName => "the harrower"; - - public override bool AutoDispel => true; - public override bool Unprovokable => true; - public override Poison PoisonImmune => Poison.Lethal; - - [CommandProperty(AccessLevel.GameMaster)] - public override int HitsMax => m_TrueForm ? 65000 : 30000; - - [CommandProperty(AccessLevel.GameMaster)] - public override int ManaMax => 5000; - - public override bool DisallowAllMoves => m_TrueForm; - - public static Harrower Spawn(Point3D platLoc, Map platMap) - { - if (Instances.Count > 0) - return null; - - SpawnEntry entry = m_Entries.RandomElement(); - - Harrower harrower = new Harrower(); - - harrower.MoveToWorld(entry.m_Location, Map.Felucca); - - harrower.m_GateItem = new HarrowerGate(harrower, platLoc, platMap, entry.m_Entrance, Map.Felucca); - - return harrower; - } - - public override void GenerateLoot() - { - AddLoot(LootPack.SuperBoss, 2); - AddLoot(LootPack.Meager); - } - - public void Morph() - { - if (m_TrueForm) - return; - - m_TrueForm = true; - - Name = "the true harrower"; - BodyValue = 780; - Hue = 0x497; - - Hits = HitsMax; - Stam = StamMax; - Mana = ManaMax; - - ProcessDelta(); - - Say(1049499); // Behold my true form! - - Map map = Map; - - if (map != null) - for (int i = 0; i < m_Offsets.Length; i += 2) + private static readonly SpawnEntry[] m_Entries = { - double rx = m_Offsets[i]; - double ry = m_Offsets[i + 1]; + new SpawnEntry(new Point3D(5242, 945, -40), new Point3D(1176, 2638, 0)), // Destard + new SpawnEntry(new Point3D(5225, 798, 0), new Point3D(1176, 2638, 0)), // Destard + new SpawnEntry(new Point3D(5556, 886, 30), new Point3D(1298, 1080, 0)), // Despise + new SpawnEntry(new Point3D(5187, 615, 0), new Point3D(4111, 432, 5)), // Deceit + new SpawnEntry(new Point3D(5319, 583, 0), new Point3D(4111, 432, 5)), // Deceit + new SpawnEntry(new Point3D(5713, 1334, -1), new Point3D(2923, 3407, 8)), // Fire + new SpawnEntry(new Point3D(5860, 1460, -2), new Point3D(2923, 3407, 8)), // Fire + new SpawnEntry(new Point3D(5328, 1620, 0), new Point3D(5451, 3143, -60)), // Terathan Keep + new SpawnEntry(new Point3D(5690, 538, 0), new Point3D(2042, 224, 14)), // Wrong + new SpawnEntry(new Point3D(5609, 195, 0), new Point3D(514, 1561, 0)), // Shame + new SpawnEntry(new Point3D(5475, 187, 0), new Point3D(514, 1561, 0)), // Shame + new SpawnEntry(new Point3D(6085, 179, 0), new Point3D(4721, 3822, 0)), // Hythloth + new SpawnEntry(new Point3D(6084, 66, 0), new Point3D(4721, 3822, 0)), // Hythloth + new SpawnEntry(new Point3D(5499, 2003, 0), new Point3D(2499, 919, 0)), // Covetous + new SpawnEntry(new Point3D(5579, 1858, 0), new Point3D(2499, 919, 0)) // Covetous + }; - int dist = 0; - bool ok = false; - int x = 0, y = 0, z = 0; + private static readonly double[] m_Offsets = + { + Math.Cos(000.0 / 180.0 * Math.PI), Math.Sin(000.0 / 180.0 * Math.PI), + Math.Cos(040.0 / 180.0 * Math.PI), Math.Sin(040.0 / 180.0 * Math.PI), + Math.Cos(080.0 / 180.0 * Math.PI), Math.Sin(080.0 / 180.0 * Math.PI), + Math.Cos(120.0 / 180.0 * Math.PI), Math.Sin(120.0 / 180.0 * Math.PI), + Math.Cos(160.0 / 180.0 * Math.PI), Math.Sin(160.0 / 180.0 * Math.PI), + Math.Cos(200.0 / 180.0 * Math.PI), Math.Sin(200.0 / 180.0 * Math.PI), + Math.Cos(240.0 / 180.0 * Math.PI), Math.Sin(240.0 / 180.0 * Math.PI), + Math.Cos(280.0 / 180.0 * Math.PI), Math.Sin(280.0 / 180.0 * Math.PI), + Math.Cos(320.0 / 180.0 * Math.PI), Math.Sin(320.0 / 180.0 * Math.PI) + }; - while (!ok && dist < 10) - { - int rdist = 10 + dist; + private Dictionary m_DamageEntries; + private Item m_GateItem; + private List m_Tentacles; + private Timer m_Timer; - x = X + (int)(rx * rdist); - y = Y + (int)(ry * rdist); - z = map.GetAverageZ(x, y); + private bool m_TrueForm; - if (!(ok = map.CanFit(x, y, Z, 16, false, false))) - ok = map.CanFit(x, y, z, 16, false, false); + [Constructible] + public Harrower() : base(AIType.AI_Mage, FightMode.Closest, 18, 1, 0.2, 0.4) + { + Instances.Add(this); + BodyValue = 146; - if (dist >= 0) - dist = -(dist + 1); - else - dist = -(dist - 1); - } + SetStr(900, 1000); + SetDex(125, 135); + SetInt(1000, 1200); - if (!ok) - continue; + Fame = 22500; + Karma = -22500; - HarrowerTentacles spawn = new HarrowerTentacles(this) { Team = Team }; + VirtualArmor = 60; - spawn.MoveToWorld(new Point3D(x, y, z), map); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Energy, 50); - m_Tentacles.Add(spawn); - } - } + SetResistance(ResistanceType.Physical, 55, 65); + SetResistance(ResistanceType.Fire, 60, 80); + SetResistance(ResistanceType.Cold, 60, 80); + SetResistance(ResistanceType.Poison, 60, 80); + SetResistance(ResistanceType.Energy, 60, 80); - public override void OnAfterDelete() - { - Instances.Remove(this); + SetSkill(SkillName.Wrestling, 90.1, 100.0); + SetSkill(SkillName.Tactics, 90.2, 110.0); + SetSkill(SkillName.MagicResist, 120.2, 160.0); + SetSkill(SkillName.Magery, 120.0); + SetSkill(SkillName.EvalInt, 120.0); + SetSkill(SkillName.Meditation, 120.0); - base.OnAfterDelete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_TrueForm); - writer.Write(m_GateItem); - writer.WriteMobileList(m_Tentacles); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_TrueForm = reader.ReadBool(); - m_GateItem = reader.ReadItem(); - m_Tentacles = reader.ReadStrongMobileList(); + m_Tentacles = new List(); m_Timer = new TeleportTimer(this); m_Timer.Start(); + } - break; - } - } - } + public Harrower(Serial serial) : base(serial) + { + Instances.Add(this); + } - public void GivePowerScrolls() - { - List toGive = new List(); - List rights = GetLootingRights(DamageEntries, HitsMax); + public Type[] UniqueList => new[] { typeof(AcidProofRobe) }; + public Type[] SharedList => new[] { typeof(TheRobeOfBritanniaAri) }; + public Type[] DecorativeList => new[] { typeof(EvilIdolSkull), typeof(SkullPole) }; - for (int i = rights.Count - 1; i >= 0; --i) - { - DamageStore ds = rights[i]; + public static List Instances { get; } = new List(); - if (ds.m_HasRight) - toGive.Add(ds.m_Mobile); - } + public static bool CanSpawn => Instances.Count == 0; - if (toGive.Count == 0) - return; + public override string DefaultName => "the harrower"; - toGive.Shuffle(); + public override bool AutoDispel => true; + public override bool Unprovokable => true; + public override Poison PoisonImmune => Poison.Lethal; - for (int i = 0; i < 16; ++i) - { - int level; - double random = Utility.RandomDouble(); + [CommandProperty(AccessLevel.GameMaster)] + public override int HitsMax => m_TrueForm ? 65000 : 30000; - if (random <= 0.1) - level = 25; - else if (random <= 0.25) - level = 20; - else if (random <= 0.45) - level = 15; - else if (random <= 0.70) - level = 10; - else - level = 5; + [CommandProperty(AccessLevel.GameMaster)] + public override int ManaMax => 5000; - Mobile m = toGive[i % toGive.Count]; + public override bool DisallowAllMoves => m_TrueForm; - m.SendLocalizedMessage(1049524); // You have received a scroll of power! - m.AddToBackpack(new StatCapScroll(225 + level)); + public static Harrower Spawn(Point3D platLoc, Map platMap) + { + if (Instances.Count > 0) + return null; - if (m is PlayerMobile pm) - for (int j = 0; j < pm.JusticeProtectors.Count; ++j) - { - Mobile prot = pm.JusticeProtectors[j]; + var entry = m_Entries.RandomElement(); - if (prot.Map != pm.Map || prot.Kills >= 5 || prot.Criminal || - !JusticeVirtue.CheckMapRegion(pm, prot)) - continue; + var harrower = new Harrower(); - var chance = VirtueHelper.GetLevel(prot, VirtueName.Justice) switch + harrower.MoveToWorld(entry.m_Location, Map.Felucca); + + harrower.m_GateItem = new HarrowerGate(harrower, platLoc, platMap, entry.m_Entrance, Map.Felucca); + + return harrower; + } + + public override void GenerateLoot() + { + AddLoot(LootPack.SuperBoss, 2); + AddLoot(LootPack.Meager); + } + + public void Morph() + { + if (m_TrueForm) + return; + + m_TrueForm = true; + + Name = "the true harrower"; + BodyValue = 780; + Hue = 0x497; + + Hits = HitsMax; + Stam = StamMax; + Mana = ManaMax; + + ProcessDelta(); + + Say(1049499); // Behold my true form! + + var map = Map; + + if (map != null) + for (var i = 0; i < m_Offsets.Length; i += 2) + { + var rx = m_Offsets[i]; + var ry = m_Offsets[i + 1]; + + var dist = 0; + var ok = false; + int x = 0, y = 0, z = 0; + + while (!ok && dist < 10) + { + var rdist = 10 + dist; + + x = X + (int)(rx * rdist); + y = Y + (int)(ry * rdist); + z = map.GetAverageZ(x, y); + + if (!(ok = map.CanFit(x, y, Z, 16, false, false))) + ok = map.CanFit(x, y, z, 16, false, false); + + if (dist >= 0) + dist = -(dist + 1); + else + dist = -(dist - 1); + } + + if (!ok) + continue; + + var spawn = new HarrowerTentacles(this) { Team = Team }; + + spawn.MoveToWorld(new Point3D(x, y, z), map); + + m_Tentacles.Add(spawn); + } + } + + public override void OnAfterDelete() + { + Instances.Remove(this); + + base.OnAfterDelete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_TrueForm); + writer.Write(m_GateItem); + writer.WriteMobileList(m_Tentacles); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) { - VirtueLevel.Seeker => 60, - VirtueLevel.Follower => 80, - VirtueLevel.Knight => 100, - _ => 0 + case 0: + { + m_TrueForm = reader.ReadBool(); + m_GateItem = reader.ReadItem(); + m_Tentacles = reader.ReadStrongMobileList(); + + m_Timer = new TeleportTimer(this); + m_Timer.Start(); + + break; + } + } + } + + public void GivePowerScrolls() + { + var toGive = new List(); + var rights = GetLootingRights(DamageEntries, HitsMax); + + for (var i = rights.Count - 1; i >= 0; --i) + { + var ds = rights[i]; + + if (ds.m_HasRight) + toGive.Add(ds.m_Mobile); + } + + if (toGive.Count == 0) + return; + + toGive.Shuffle(); + + for (var i = 0; i < 16; ++i) + { + int level; + var random = Utility.RandomDouble(); + + if (random <= 0.1) + level = 25; + else if (random <= 0.25) + level = 20; + else if (random <= 0.45) + level = 15; + else if (random <= 0.70) + level = 10; + else + level = 5; + + var m = toGive[i % toGive.Count]; + + m.SendLocalizedMessage(1049524); // You have received a scroll of power! + m.AddToBackpack(new StatCapScroll(225 + level)); + + if (m is PlayerMobile pm) + for (var j = 0; j < pm.JusticeProtectors.Count; ++j) + { + var prot = pm.JusticeProtectors[j]; + + if (prot.Map != pm.Map || prot.Kills >= 5 || prot.Criminal || + !JusticeVirtue.CheckMapRegion(pm, prot)) + continue; + + var chance = VirtueHelper.GetLevel(prot, VirtueName.Justice) switch + { + VirtueLevel.Seeker => 60, + VirtueLevel.Follower => 80, + VirtueLevel.Knight => 100, + _ => 0 + }; + + if (chance > Utility.Random(100)) + { + prot.SendLocalizedMessage(1049368); // You have been rewarded for your dedication to Justice! + prot.AddToBackpack(new StatCapScroll(225 + level)); + } + } + } + } + + public override bool OnBeforeDeath() + { + if (m_TrueForm) + { + var rights = GetLootingRights(DamageEntries, HitsMax); + + for (var i = rights.Count - 1; i >= 0; --i) + { + var ds = rights[i]; + + if (ds.m_HasRight && ds.m_Mobile is PlayerMobile mobile) + PlayerMobile.ChampionTitleInfo.AwardHarrowerTitle(mobile); + } + + if (!NoKillAwards) + { + GivePowerScrolls(); + + var map = Map; + + if (map != null) + for (var x = -16; x <= 16; ++x) + for (var y = -16; y <= 16; ++y) + { + var dist = Math.Sqrt(x * x + y * y); + + if (dist <= 16) + new GoodiesTimer(map, X + x, Y + y).Start(); + } + + m_DamageEntries = new Dictionary(); + + for (var i = 0; i < m_Tentacles.Count; ++i) + { + Mobile m = m_Tentacles[i]; + + if (!m.Deleted) + m.Kill(); + + RegisterDamageTo(m); + } + + m_Tentacles.Clear(); + + RegisterDamageTo(this); + AwardArtifact(GetArtifact()); + + m_GateItem?.Delete(); + } + + return base.OnBeforeDeath(); + } + + Morph(); + return false; + } + + public virtual void RegisterDamageTo(Mobile m) + { + if (m == null) + return; + + foreach (var de in m.DamageEntries) + { + var damager = de.Damager; + + var master = damager.GetDamageMaster(m); + + if (master != null) + damager = master; + + RegisterDamage(damager, de.DamageGiven); + } + } + + public void RegisterDamage(Mobile from, int amount) + { + if (from?.Player != true) + return; + + m_DamageEntries[from] = amount + (m_DamageEntries.TryGetValue(from, out var value) ? value : 0); + + from.SendMessage($"Total Damage: {m_DamageEntries[from]}"); + } + + public void AwardArtifact(Item artifact) + { + if (artifact == null) + return; + + var totalDamage = 0; + + var validEntries = new Dictionary(); + + foreach (var kvp in m_DamageEntries) + if (IsEligible(kvp.Key, artifact)) + { + validEntries.Add(kvp.Key, kvp.Value); + totalDamage += kvp.Value; + } + + var randomDamage = Utility.RandomMinMax(1, totalDamage); + + totalDamage = 0; + + foreach (var kvp in validEntries) + { + totalDamage += kvp.Value; + + if (totalDamage >= randomDamage) + { + GiveArtifact(kvp.Key, artifact); + return; + } + } + + artifact.Delete(); + } + + public void GiveArtifact(Mobile to, Item artifact) + { + if (to == null || artifact == null) + return; + + var pack = to.Backpack; + + if (pack?.TryDropItem(to, artifact, false) != true) + artifact.Delete(); + else + to.SendLocalizedMessage( + 1062317 + ); // For your valor in combating the fallen beast, a special artifact has been bestowed on you. + } + + public bool IsEligible(Mobile m, Item artifact) => + m.Player && m.Alive && m.InRange(Location, 32) && + m.Backpack?.CheckHold(m, artifact, false) == true; + + public Item GetArtifact() + { + var random = Utility.RandomDouble(); + if (random <= 0.05) + return CreateArtifact(UniqueList); + if (random <= 0.15) + return CreateArtifact(SharedList); + if (random <= 0.30) + return CreateArtifact(DecorativeList); + + return null; + } + + public Item CreateArtifact(Type[] list) => Loot.Construct(list.RandomElement()); + + private class SpawnEntry + { + public readonly Point3D m_Entrance; + public readonly Point3D m_Location; + + public SpawnEntry(Point3D loc, Point3D ent) + { + m_Location = loc; + m_Entrance = ent; + } + } + + private class TeleportTimer : Timer + { + private static readonly int[] m_Offsets = + { + -1, -1, + -1, 0, + -1, 1, + 0, -1, + 0, 1, + 1, -1, + 1, 0, + 1, 1 }; - if (chance > Utility.Random(100)) + private readonly Mobile m_Owner; + + public TeleportTimer(Mobile owner) : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0)) { - prot.SendLocalizedMessage(1049368); // You have been rewarded for your dedication to Justice! - prot.AddToBackpack(new StatCapScroll(225 + level)); + Priority = TimerPriority.TwoFiftyMS; + + m_Owner = owner; } - } - } - } - public override bool OnBeforeDeath() - { - if (m_TrueForm) - { - List rights = GetLootingRights(DamageEntries, HitsMax); + protected override void OnTick() + { + if (m_Owner.Deleted) + { + Stop(); + return; + } - for (int i = rights.Count - 1; i >= 0; --i) - { - DamageStore ds = rights[i]; + var map = m_Owner.Map; - if (ds.m_HasRight && ds.m_Mobile is PlayerMobile mobile) - PlayerMobile.ChampionTitleInfo.AwardHarrowerTitle(mobile); + if (map == null) + return; + + if (Utility.RandomDouble() > 0.25) + return; + + var toTeleport = m_Owner.GetMobilesInRange(16) + .FirstOrDefault(mob => mob != m_Owner && mob.Player && m_Owner.CanBeHarmful(mob) && m_Owner.CanSee(mob)); + + if (toTeleport == null) + return; + + var offset = Utility.Random(8) * 2; + + var to = m_Owner.Location; + + for (var i = 0; i < m_Offsets.Length; i += 2) + { + var x = m_Owner.X + m_Offsets[(offset + i) % m_Offsets.Length]; + var y = m_Owner.Y + m_Offsets[(offset + i + 1) % m_Offsets.Length]; + + if (map.CanSpawnMobile(x, y, m_Owner.Z)) + { + to = new Point3D(x, y, m_Owner.Z); + break; + } + + var z = map.GetAverageZ(x, y); + + if (map.CanSpawnMobile(x, y, z)) + { + to = new Point3D(x, y, z); + break; + } + } + + var m = toTeleport; + + var from = m.Location; + + m.Location = to; + + SpellHelper.Turn(m_Owner, toTeleport); + SpellHelper.Turn(toTeleport, m_Owner); + + m.ProcessDelta(); + + Effects.SendLocationParticles( + EffectItem.Create(from, m.Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 2023 + ); + Effects.SendLocationParticles( + EffectItem.Create(to, m.Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 5023 + ); + + m.PlaySound(0x1FE); + + m_Owner.Combatant = toTeleport; + } } - if (!NoKillAwards) + private class GoodiesTimer : Timer { - GivePowerScrolls(); + private readonly Map m_Map; + private readonly int m_X; + private readonly int m_Y; - Map map = Map; + public GoodiesTimer(Map map, int x, int y) : base(TimeSpan.FromSeconds(Utility.RandomDouble() * 10.0)) + { + Priority = TimerPriority.TwoFiftyMS; - if (map != null) - for (int x = -16; x <= 16; ++x) - for (int y = -16; y <= 16; ++y) - { - double dist = Math.Sqrt(x * x + y * y); + m_Map = map; + m_X = x; + m_Y = y; + } - if (dist <= 16) - new GoodiesTimer(map, X + x, Y + y).Start(); - } + protected override void OnTick() + { + var z = m_Map.GetAverageZ(m_X, m_Y); + var canFit = m_Map.CanFit(m_X, m_Y, z, 6, false, false); - m_DamageEntries = new Dictionary(); + for (var i = -3; !canFit && i <= 3; ++i) + { + canFit = m_Map.CanFit(m_X, m_Y, z + i, 6, false, false); - for (int i = 0; i < m_Tentacles.Count; ++i) - { - Mobile m = m_Tentacles[i]; + if (canFit) + z += i; + } - if (!m.Deleted) - m.Kill(); + if (!canFit) + return; - RegisterDamageTo(m); - } + var g = new Gold(750, 1250); - m_Tentacles.Clear(); + g.MoveToWorld(new Point3D(m_X, m_Y, z), m_Map); - RegisterDamageTo(this); - AwardArtifact(GetArtifact()); + if (Utility.RandomDouble() <= 0.5) + switch (Utility.Random(3)) + { + case 0: // Fire column + { + Effects.SendLocationParticles( + EffectItem.Create(g.Location, g.Map, EffectItem.DefaultDuration), + 0x3709, + 10, + 30, + 5052 + ); + Effects.PlaySound(g, g.Map, 0x208); - m_GateItem?.Delete(); + break; + } + case 1: // Explosion + { + Effects.SendLocationParticles( + EffectItem.Create(g.Location, g.Map, EffectItem.DefaultDuration), + 0x36BD, + 20, + 10, + 5044 + ); + Effects.PlaySound(g, g.Map, 0x307); + + break; + } + case 2: // Ball of fire + { + Effects.SendLocationParticles( + EffectItem.Create(g.Location, g.Map, EffectItem.DefaultDuration), + 0x36FE, + 10, + 10, + 5052 + ); + + break; + } + } + } } - - return base.OnBeforeDeath(); - } - - Morph(); - return false; } - - public virtual void RegisterDamageTo(Mobile m) - { - if (m == null) - return; - - foreach (DamageEntry de in m.DamageEntries) - { - Mobile damager = de.Damager; - - Mobile master = damager.GetDamageMaster(m); - - if (master != null) - damager = master; - - RegisterDamage(damager, de.DamageGiven); - } - } - - public void RegisterDamage(Mobile from, int amount) - { - if (from?.Player != true) - return; - - m_DamageEntries[from] = amount + (m_DamageEntries.TryGetValue(from, out int value) ? value : 0); - - from.SendMessage($"Total Damage: {m_DamageEntries[from]}"); - } - - public void AwardArtifact(Item artifact) - { - if (artifact == null) - return; - - int totalDamage = 0; - - Dictionary validEntries = new Dictionary(); - - foreach (KeyValuePair kvp in m_DamageEntries) - if (IsEligible(kvp.Key, artifact)) - { - validEntries.Add(kvp.Key, kvp.Value); - totalDamage += kvp.Value; - } - - int randomDamage = Utility.RandomMinMax(1, totalDamage); - - totalDamage = 0; - - foreach (KeyValuePair kvp in validEntries) - { - totalDamage += kvp.Value; - - if (totalDamage >= randomDamage) - { - GiveArtifact(kvp.Key, artifact); - return; - } - } - - artifact.Delete(); - } - - public void GiveArtifact(Mobile to, Item artifact) - { - if (to == null || artifact == null) - return; - - Container pack = to.Backpack; - - if (pack?.TryDropItem(to, artifact, false) != true) - artifact.Delete(); - else - to.SendLocalizedMessage( - 1062317); // For your valor in combating the fallen beast, a special artifact has been bestowed on you. - } - - public bool IsEligible(Mobile m, Item artifact) => - m.Player && m.Alive && m.InRange(Location, 32) && - m.Backpack?.CheckHold(m, artifact, false) == true; - - public Item GetArtifact() - { - double random = Utility.RandomDouble(); - if (random <= 0.05) - return CreateArtifact(UniqueList); - if (random <= 0.15) - return CreateArtifact(SharedList); - if (random <= 0.30) - return CreateArtifact(DecorativeList); - - return null; - } - - public Item CreateArtifact(Type[] list) => Loot.Construct(list.RandomElement()); - - private class SpawnEntry - { - public readonly Point3D m_Entrance; - public readonly Point3D m_Location; - - public SpawnEntry(Point3D loc, Point3D ent) - { - m_Location = loc; - m_Entrance = ent; - } - } - - private class TeleportTimer : Timer - { - private static readonly int[] m_Offsets = - { - -1, -1, - -1, 0, - -1, 1, - 0, -1, - 0, 1, - 1, -1, - 1, 0, - 1, 1 - }; - - private readonly Mobile m_Owner; - - public TeleportTimer(Mobile owner) : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0)) - { - Priority = TimerPriority.TwoFiftyMS; - - m_Owner = owner; - } - - protected override void OnTick() - { - if (m_Owner.Deleted) - { - Stop(); - return; - } - - Map map = m_Owner.Map; - - if (map == null) - return; - - if (Utility.RandomDouble() > 0.25) - return; - - Mobile toTeleport = m_Owner.GetMobilesInRange(16) - .FirstOrDefault(mob => mob != m_Owner && mob.Player && m_Owner.CanBeHarmful(mob) && m_Owner.CanSee(mob)); - - if (toTeleport == null) - return; - - int offset = Utility.Random(8) * 2; - - Point3D to = m_Owner.Location; - - for (int i = 0; i < m_Offsets.Length; i += 2) - { - int x = m_Owner.X + m_Offsets[(offset + i) % m_Offsets.Length]; - int y = m_Owner.Y + m_Offsets[(offset + i + 1) % m_Offsets.Length]; - - if (map.CanSpawnMobile(x, y, m_Owner.Z)) - { - to = new Point3D(x, y, m_Owner.Z); - break; - } - - int z = map.GetAverageZ(x, y); - - if (map.CanSpawnMobile(x, y, z)) - { - to = new Point3D(x, y, z); - break; - } - } - - Mobile m = toTeleport; - - Point3D from = m.Location; - - m.Location = to; - - SpellHelper.Turn(m_Owner, toTeleport); - SpellHelper.Turn(toTeleport, m_Owner); - - m.ProcessDelta(); - - Effects.SendLocationParticles(EffectItem.Create(from, m.Map, EffectItem.DefaultDuration), 0x3728, 10, 10, - 2023); - Effects.SendLocationParticles(EffectItem.Create(to, m.Map, EffectItem.DefaultDuration), 0x3728, 10, 10, - 5023); - - m.PlaySound(0x1FE); - - m_Owner.Combatant = toTeleport; - } - } - - private class GoodiesTimer : Timer - { - private readonly Map m_Map; - private readonly int m_X; - private readonly int m_Y; - - public GoodiesTimer(Map map, int x, int y) : base(TimeSpan.FromSeconds(Utility.RandomDouble() * 10.0)) - { - Priority = TimerPriority.TwoFiftyMS; - - m_Map = map; - m_X = x; - m_Y = y; - } - - protected override void OnTick() - { - int z = m_Map.GetAverageZ(m_X, m_Y); - bool canFit = m_Map.CanFit(m_X, m_Y, z, 6, false, false); - - for (int i = -3; !canFit && i <= 3; ++i) - { - canFit = m_Map.CanFit(m_X, m_Y, z + i, 6, false, false); - - if (canFit) - z += i; - } - - if (!canFit) - return; - - Gold g = new Gold(750, 1250); - - g.MoveToWorld(new Point3D(m_X, m_Y, z), m_Map); - - if (Utility.RandomDouble() <= 0.5) - switch (Utility.Random(3)) - { - case 0: // Fire column - { - Effects.SendLocationParticles(EffectItem.Create(g.Location, g.Map, EffectItem.DefaultDuration), - 0x3709, 10, 30, 5052); - Effects.PlaySound(g, g.Map, 0x208); - - break; - } - case 1: // Explosion - { - Effects.SendLocationParticles(EffectItem.Create(g.Location, g.Map, EffectItem.DefaultDuration), - 0x36BD, 20, 10, 5044); - Effects.PlaySound(g, g.Map, 0x307); - - break; - } - case 2: // Ball of fire - { - Effects.SendLocationParticles(EffectItem.Create(g.Location, g.Map, EffectItem.DefaultDuration), - 0x36FE, 10, 10, 5052); - - break; - } - } - } - } - } } diff --git a/Projects/UOContent/Mobiles/Special/HarrowerTentacles.cs b/Projects/UOContent/Mobiles/Special/HarrowerTentacles.cs index abcadd822..def121238 100644 --- a/Projects/UOContent/Mobiles/Special/HarrowerTentacles.cs +++ b/Projects/UOContent/Mobiles/Special/HarrowerTentacles.cs @@ -2,174 +2,174 @@ using System; namespace Server.Mobiles { - public class HarrowerTentacles : BaseCreature - { - private DrainTimer m_Timer; - - [Constructible] - public HarrowerTentacles(Mobile harrower = null) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class HarrowerTentacles : BaseCreature { - Harrower = harrower; - Body = 129; + private DrainTimer m_Timer; - SetStr(901, 1000); - SetDex(126, 140); - SetInt(1001, 1200); + [Constructible] + public HarrowerTentacles(Mobile harrower = null) : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Harrower = harrower; + Body = 129; - SetHits(541, 600); + SetStr(901, 1000); + SetDex(126, 140); + SetInt(1001, 1200); - SetDamage(13, 20); + SetHits(541, 600); - SetDamageType(ResistanceType.Physical, 20); - SetDamageType(ResistanceType.Fire, 20); - SetDamageType(ResistanceType.Cold, 20); - SetDamageType(ResistanceType.Poison, 20); - SetDamageType(ResistanceType.Energy, 20); + SetDamage(13, 20); - SetResistance(ResistanceType.Physical, 55, 65); - SetResistance(ResistanceType.Fire, 35, 45); - SetResistance(ResistanceType.Cold, 35, 45); - SetResistance(ResistanceType.Poison, 35, 45); - SetResistance(ResistanceType.Energy, 35, 45); + SetDamageType(ResistanceType.Physical, 20); + SetDamageType(ResistanceType.Fire, 20); + SetDamageType(ResistanceType.Cold, 20); + SetDamageType(ResistanceType.Poison, 20); + SetDamageType(ResistanceType.Energy, 20); - SetSkill(SkillName.Meditation, 100.0); - SetSkill(SkillName.MagicResist, 120.1, 140.0); - SetSkill(SkillName.Swords, 90.1, 100.0); - SetSkill(SkillName.Tactics, 90.1, 100.0); - SetSkill(SkillName.Wrestling, 90.1, 100.0); + SetResistance(ResistanceType.Physical, 55, 65); + SetResistance(ResistanceType.Fire, 35, 45); + SetResistance(ResistanceType.Cold, 35, 45); + SetResistance(ResistanceType.Poison, 35, 45); + SetResistance(ResistanceType.Energy, 35, 45); - Fame = 15000; - Karma = -15000; + SetSkill(SkillName.Meditation, 100.0); + SetSkill(SkillName.MagicResist, 120.1, 140.0); + SetSkill(SkillName.Swords, 90.1, 100.0); + SetSkill(SkillName.Tactics, 90.1, 100.0); + SetSkill(SkillName.Wrestling, 90.1, 100.0); - VirtualArmor = 60; + Fame = 15000; + Karma = -15000; - m_Timer = new DrainTimer(this); - m_Timer.Start(); - - PackReg(50); - PackNecroReg(15, 75); - } - - public HarrowerTentacles(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a tentacles corpse"; - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Harrower { get; set; } - - public override string DefaultName => "tentacles of the harrower"; - - public override bool AutoDispel => true; - public override bool Unprovokable => true; - public override Poison PoisonImmune => Poison.Lethal; - public override bool DisallowAllMoves => true; - - public override void CheckReflect(Mobile caster, ref bool reflect) - { - reflect = true; - } - - public override int GetIdleSound() => 0x101; - - public override int GetAngerSound() => 0x5E; - - public override int GetDeathSound() => 0x1C2; - - public override int GetAttackSound() => -1; - - public override int GetHurtSound() => 0x289; - - public override void GenerateLoot() - { - AddLoot(LootPack.FilthyRich, 2); - AddLoot(LootPack.MedScrolls, 3); - AddLoot(LootPack.HighScrolls, 2); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(Harrower); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Harrower = reader.ReadMobile(); + VirtualArmor = 60; m_Timer = new DrainTimer(this); m_Timer.Start(); - break; - } - } - } - - public override void OnAfterDelete() - { - m_Timer?.Stop(); - m_Timer = null; - - base.OnAfterDelete(); - } - - private class DrainTimer : Timer - { - private readonly HarrowerTentacles m_Owner; - - public DrainTimer(HarrowerTentacles owner) : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0)) - { - m_Owner = owner; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - if (m_Owner.Deleted) - { - Stop(); - return; + PackReg(50); + PackNecroReg(15, 75); } - IPooledEnumerable eable = m_Owner.GetMobilesInRange(9); - - foreach (Mobile m in eable) + public HarrowerTentacles(Serial serial) : base(serial) { - if (m == m_Owner || !(m_Owner.CanBeHarmful(m) || (m.Player && m.Alive))) - continue; - - if (!(m is BaseCreature bc) || !(bc.Controlled || bc.Summoned || bc.Team != m_Owner.Team)) - continue; - - m_Owner.DoHarmful(m); - - m.FixedParticles(0x374A, 10, 15, 5013, 0x455, 0, EffectLayer.Waist); - m.PlaySound(0x1F1); - - int drain = Utility.RandomMinMax(14, 30); - - m_Owner.Hits += drain; - - if (m_Owner.Harrower != null) - m_Owner.Harrower.Hits += drain; - - m.Damage(drain, m_Owner); } - eable.Free(); - } + public override string CorpseName => "a tentacles corpse"; + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Harrower { get; set; } + + public override string DefaultName => "tentacles of the harrower"; + + public override bool AutoDispel => true; + public override bool Unprovokable => true; + public override Poison PoisonImmune => Poison.Lethal; + public override bool DisallowAllMoves => true; + + public override void CheckReflect(Mobile caster, ref bool reflect) + { + reflect = true; + } + + public override int GetIdleSound() => 0x101; + + public override int GetAngerSound() => 0x5E; + + public override int GetDeathSound() => 0x1C2; + + public override int GetAttackSound() => -1; + + public override int GetHurtSound() => 0x289; + + public override void GenerateLoot() + { + AddLoot(LootPack.FilthyRich, 2); + AddLoot(LootPack.MedScrolls, 3); + AddLoot(LootPack.HighScrolls, 2); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(Harrower); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Harrower = reader.ReadMobile(); + + m_Timer = new DrainTimer(this); + m_Timer.Start(); + + break; + } + } + } + + public override void OnAfterDelete() + { + m_Timer?.Stop(); + m_Timer = null; + + base.OnAfterDelete(); + } + + private class DrainTimer : Timer + { + private readonly HarrowerTentacles m_Owner; + + public DrainTimer(HarrowerTentacles owner) : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0)) + { + m_Owner = owner; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + if (m_Owner.Deleted) + { + Stop(); + return; + } + + var eable = m_Owner.GetMobilesInRange(9); + + foreach (var m in eable) + { + if (m == m_Owner || !(m_Owner.CanBeHarmful(m) || m.Player && m.Alive)) + continue; + + if (!(m is BaseCreature bc) || !(bc.Controlled || bc.Summoned || bc.Team != m_Owner.Team)) + continue; + + m_Owner.DoHarmful(m); + + m.FixedParticles(0x374A, 10, 15, 5013, 0x455, 0, EffectLayer.Waist); + m.PlaySound(0x1F1); + + var drain = Utility.RandomMinMax(14, 30); + + m_Owner.Hits += drain; + + if (m_Owner.Harrower != null) + m_Owner.Harrower.Hits += drain; + + m.Damage(drain, m_Owner); + } + + eable.Free(); + } + } } - } } diff --git a/Projects/UOContent/Mobiles/Special/LordOaks.cs b/Projects/UOContent/Mobiles/Special/LordOaks.cs index 35963009e..e77357396 100644 --- a/Projects/UOContent/Mobiles/Special/LordOaks.cs +++ b/Projects/UOContent/Mobiles/Special/LordOaks.cs @@ -4,201 +4,203 @@ using Server.Items; namespace Server.Mobiles { - public class LordOaks : BaseChampion - { - private BaseCreature m_Queen; - private bool m_SpawnedQueen; - - [Constructible] - public LordOaks() : base(AIType.AI_Mage, FightMode.Evil) + public class LordOaks : BaseChampion { - Body = 175; - SetStr(403, 850); - SetDex(101, 150); - SetInt(503, 800); + private BaseCreature m_Queen; + private bool m_SpawnedQueen; - SetHits(3000); - SetStam(202, 400); + [Constructible] + public LordOaks() : base(AIType.AI_Mage, FightMode.Evil) + { + Body = 175; + SetStr(403, 850); + SetDex(101, 150); + SetInt(503, 800); - SetDamage(21, 33); + SetHits(3000); + SetStam(202, 400); - SetDamageType(ResistanceType.Physical, 75); - SetDamageType(ResistanceType.Fire, 25); + SetDamage(21, 33); - SetResistance(ResistanceType.Physical, 85, 90); - SetResistance(ResistanceType.Fire, 60, 70); - SetResistance(ResistanceType.Cold, 60, 70); - SetResistance(ResistanceType.Poison, 80, 90); - SetResistance(ResistanceType.Energy, 80, 90); + SetDamageType(ResistanceType.Physical, 75); + SetDamageType(ResistanceType.Fire, 25); - SetSkill(SkillName.Anatomy, 75.1, 100.0); - SetSkill(SkillName.EvalInt, 120.1, 130.0); - SetSkill(SkillName.Magery, 120.0); - SetSkill(SkillName.Meditation, 120.1, 130.0); - SetSkill(SkillName.MagicResist, 100.5, 150.0); - SetSkill(SkillName.Tactics, 100.0); - SetSkill(SkillName.Wrestling, 100.0); + SetResistance(ResistanceType.Physical, 85, 90); + SetResistance(ResistanceType.Fire, 60, 70); + SetResistance(ResistanceType.Cold, 60, 70); + SetResistance(ResistanceType.Poison, 80, 90); + SetResistance(ResistanceType.Energy, 80, 90); - Fame = 22500; - Karma = 22500; + SetSkill(SkillName.Anatomy, 75.1, 100.0); + SetSkill(SkillName.EvalInt, 120.1, 130.0); + SetSkill(SkillName.Magery, 120.0); + SetSkill(SkillName.Meditation, 120.1, 130.0); + SetSkill(SkillName.MagicResist, 100.5, 150.0); + SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.Wrestling, 100.0); - VirtualArmor = 100; + Fame = 22500; + Karma = 22500; + + VirtualArmor = 100; + } + + public LordOaks(Serial serial) : base(serial) + { + } + + public override ChampionSkullType SkullType => ChampionSkullType.Enlightenment; + + public override Type[] UniqueList => new[] { typeof(OrcChieftainHelm) }; + + public override Type[] SharedList => new[] + { + typeof(RoyalGuardSurvivalKnife), + typeof(DjinnisRing), + typeof(LieutenantOfTheBritannianRoyalGuard), + typeof(SamaritanRobe), + typeof(DetectiveBoots), + typeof(TheMostKnowledgePerson) + }; + + public override Type[] DecorativeList => new[] + { + typeof(WaterTile), + typeof(WindSpirit), + typeof(Pier), + typeof(DirtPatch) + }; + + public override MonsterStatuetteType[] StatueTypes => new MonsterStatuetteType[] { }; + + public override string DefaultName => "Lord Oaks"; + + public override bool AutoDispel => true; + public override bool CanFly => true; + public override bool BardImmune => !Core.SE; + public override bool Unprovokable => Core.SE; + public override bool Uncalmable => Core.SE; + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override Poison PoisonImmune => Poison.Deadly; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 5); + } + + public void SpawnPixies(Mobile target) + { + var map = Map; + + if (map == null) + return; + + Say(1042154); // You shall never defeat me as long as I have my queen! + + var newPixies = Utility.RandomMinMax(3, 6); + + for (var i = 0; i < newPixies; ++i) + { + var pixie = new Pixie { Team = Team, FightMode = FightMode.Closest }; + + pixie.MoveToWorld(map.GetRandomNearbyLocation(Location), map); + pixie.Combatant = target; + } + } + + public override int GetAngerSound() => 0x2F8; + + public override int GetIdleSound() => 0x2F8; + + public override int GetAttackSound() => Utility.Random(0x2F5, 2); + + public override int GetHurtSound() => 0x2F9; + + public override int GetDeathSound() => 0x2F7; + + public void CheckQueen() + { + if (Map == null) + return; + + if (!m_SpawnedQueen) + { + Say(1042153); // Come forth my queen! + + m_Queen = new Silvani { Team = Team }; + m_Queen.MoveToWorld(Location, Map); + + m_SpawnedQueen = true; + } + else if (m_Queen?.Deleted != false) + { + m_Queen = null; + } + } + + public override void AlterDamageScalarFrom(Mobile caster, ref double scalar) + { + CheckQueen(); + + if (m_Queen != null) + { + scalar *= 0.1; + + if (Utility.RandomDouble() <= 0.1) + SpawnPixies(caster); + } + } + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + defender.Damage(Utility.Random(20, 10), this); + defender.Stam -= Utility.Random(20, 10); + defender.Mana -= Utility.Random(20, 10); + } + + public override void OnGotMeleeAttack(Mobile attacker) + { + base.OnGotMeleeAttack(attacker); + + CheckQueen(); + + if (m_Queen != null && Utility.RandomDouble() <= 0.1) + SpawnPixies(attacker); + + attacker.Damage(Utility.Random(20, 10), this); + attacker.Stam -= Utility.Random(20, 10); + attacker.Mana -= Utility.Random(20, 10); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Queen); + writer.Write(m_SpawnedQueen); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Queen = reader.ReadMobile(); + m_SpawnedQueen = reader.ReadBool(); + + break; + } + } + } } - - public LordOaks(Serial serial) : base(serial) - { - } - - public override ChampionSkullType SkullType => ChampionSkullType.Enlightenment; - - public override Type[] UniqueList => new[] { typeof(OrcChieftainHelm) }; - - public override Type[] SharedList => new[] - { - typeof(RoyalGuardSurvivalKnife), - typeof(DjinnisRing), - typeof(LieutenantOfTheBritannianRoyalGuard), - typeof(SamaritanRobe), - typeof(DetectiveBoots), - typeof(TheMostKnowledgePerson) - }; - - public override Type[] DecorativeList => new[] - { - typeof(WaterTile), - typeof(WindSpirit), - typeof(Pier), - typeof(DirtPatch) - }; - - public override MonsterStatuetteType[] StatueTypes => new MonsterStatuetteType[] { }; - - public override string DefaultName => "Lord Oaks"; - - public override bool AutoDispel => true; - public override bool CanFly => true; - public override bool BardImmune => !Core.SE; - public override bool Unprovokable => Core.SE; - public override bool Uncalmable => Core.SE; - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override Poison PoisonImmune => Poison.Deadly; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 5); - } - - public void SpawnPixies(Mobile target) - { - Map map = Map; - - if (map == null) - return; - - Say(1042154); // You shall never defeat me as long as I have my queen! - - int newPixies = Utility.RandomMinMax(3, 6); - - for (int i = 0; i < newPixies; ++i) - { - Pixie pixie = new Pixie { Team = Team, FightMode = FightMode.Closest }; - - pixie.MoveToWorld(map.GetRandomNearbyLocation(Location), map); - pixie.Combatant = target; - } - } - - public override int GetAngerSound() => 0x2F8; - - public override int GetIdleSound() => 0x2F8; - - public override int GetAttackSound() => Utility.Random(0x2F5, 2); - - public override int GetHurtSound() => 0x2F9; - - public override int GetDeathSound() => 0x2F7; - - public void CheckQueen() - { - if (Map == null) - return; - - if (!m_SpawnedQueen) - { - Say(1042153); // Come forth my queen! - - m_Queen = new Silvani { Team = Team }; - m_Queen.MoveToWorld(Location, Map); - - m_SpawnedQueen = true; - } - else if (m_Queen?.Deleted != false) - m_Queen = null; - } - - public override void AlterDamageScalarFrom(Mobile caster, ref double scalar) - { - CheckQueen(); - - if (m_Queen != null) - { - scalar *= 0.1; - - if (Utility.RandomDouble() <= 0.1) - SpawnPixies(caster); - } - } - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - defender.Damage(Utility.Random(20, 10), this); - defender.Stam -= Utility.Random(20, 10); - defender.Mana -= Utility.Random(20, 10); - } - - public override void OnGotMeleeAttack(Mobile attacker) - { - base.OnGotMeleeAttack(attacker); - - CheckQueen(); - - if (m_Queen != null && Utility.RandomDouble() <= 0.1) - SpawnPixies(attacker); - - attacker.Damage(Utility.Random(20, 10), this); - attacker.Stam -= Utility.Random(20, 10); - attacker.Mana -= Utility.Random(20, 10); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Queen); - writer.Write(m_SpawnedQueen); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Queen = reader.ReadMobile(); - m_SpawnedQueen = reader.ReadBool(); - - break; - } - } - } - } } diff --git a/Projects/UOContent/Mobiles/Special/Mephitis.cs b/Projects/UOContent/Mobiles/Special/Mephitis.cs index 5937dd2a8..f6af38c11 100644 --- a/Projects/UOContent/Mobiles/Special/Mephitis.cs +++ b/Projects/UOContent/Mobiles/Special/Mephitis.cs @@ -4,89 +4,89 @@ using Server.Items; namespace Server.Mobiles { - public class Mephitis : BaseChampion - { - [Constructible] - public Mephitis() : base(AIType.AI_Melee) + public class Mephitis : BaseChampion { - Body = 173; - BaseSoundID = 0x183; + [Constructible] + public Mephitis() : base(AIType.AI_Melee) + { + Body = 173; + BaseSoundID = 0x183; - SetStr(505, 1000); - SetDex(102, 300); - SetInt(402, 600); + SetStr(505, 1000); + SetDex(102, 300); + SetInt(402, 600); - SetHits(3000); - SetStam(105, 600); + SetHits(3000); + SetStam(105, 600); - SetDamage(21, 33); + SetDamage(21, 33); - SetDamageType(ResistanceType.Physical, 50); - SetDamageType(ResistanceType.Poison, 50); + SetDamageType(ResistanceType.Physical, 50); + SetDamageType(ResistanceType.Poison, 50); - SetResistance(ResistanceType.Physical, 75, 80); - SetResistance(ResistanceType.Fire, 60, 70); - SetResistance(ResistanceType.Cold, 60, 70); - SetResistance(ResistanceType.Poison, 100); - SetResistance(ResistanceType.Energy, 60, 70); + SetResistance(ResistanceType.Physical, 75, 80); + SetResistance(ResistanceType.Fire, 60, 70); + SetResistance(ResistanceType.Cold, 60, 70); + SetResistance(ResistanceType.Poison, 100); + SetResistance(ResistanceType.Energy, 60, 70); - SetSkill(SkillName.MagicResist, 70.7, 140.0); - SetSkill(SkillName.Tactics, 97.6, 100.0); - SetSkill(SkillName.Wrestling, 97.6, 100.0); + SetSkill(SkillName.MagicResist, 70.7, 140.0); + SetSkill(SkillName.Tactics, 97.6, 100.0); + SetSkill(SkillName.Wrestling, 97.6, 100.0); - Fame = 22500; - Karma = -22500; + Fame = 22500; + Karma = -22500; - VirtualArmor = 80; + VirtualArmor = 80; + } + + public Mephitis(Serial serial) : base(serial) + { + } + + public override ChampionSkullType SkullType => ChampionSkullType.Venom; + + public override Type[] UniqueList => new[] { typeof(Calm) }; + + public override Type[] SharedList => new[] + { + typeof(OblivionsNeedle), typeof(ANecromancerShroud), typeof(EmbroideredOakLeafCloak), + typeof(TheMostKnowledgePerson) + }; + + public override Type[] DecorativeList => new[] { typeof(Web), typeof(MonsterStatuette) }; + + public override MonsterStatuetteType[] StatueTypes => new[] { MonsterStatuetteType.Spider }; + + public override string DefaultName => "Mephitis"; + + public override Poison PoisonImmune => Poison.Lethal; + public override Poison HitPoison => Poison.Lethal; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 4); + } + + public override void OnGotMeleeAttack(Mobile attacker) + { + base.OnGotMeleeAttack(attacker); + + // TODO: Web ability + } + + 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 Mephitis(Serial serial) : base(serial) - { - } - - public override ChampionSkullType SkullType => ChampionSkullType.Venom; - - public override Type[] UniqueList => new[] { typeof(Calm) }; - - public override Type[] SharedList => new[] - { - typeof(OblivionsNeedle), typeof(ANecromancerShroud), typeof(EmbroideredOakLeafCloak), - typeof(TheMostKnowledgePerson) - }; - - public override Type[] DecorativeList => new[] { typeof(Web), typeof(MonsterStatuette) }; - - public override MonsterStatuetteType[] StatueTypes => new[] { MonsterStatuetteType.Spider }; - - public override string DefaultName => "Mephitis"; - - public override Poison PoisonImmune => Poison.Lethal; - public override Poison HitPoison => Poison.Lethal; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 4); - } - - public override void OnGotMeleeAttack(Mobile attacker) - { - base.OnGotMeleeAttack(attacker); - - // TODO: Web ability - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Special/Neira.cs b/Projects/UOContent/Mobiles/Special/Neira.cs index a4e23da2f..199c80af2 100644 --- a/Projects/UOContent/Mobiles/Special/Neira.cs +++ b/Projects/UOContent/Mobiles/Special/Neira.cs @@ -4,289 +4,289 @@ using Server.Items; namespace Server.Mobiles { - public class Neira : BaseChampion - { - private const double SpeedBoostScalar = 1.2; - - private bool m_SpeedBoost; - - [Constructible] - public Neira() : base(AIType.AI_Mage) + public class Neira : BaseChampion { - Title = "the necromancer"; - Body = 401; - Hue = 0x83EC; + private const double SpeedBoostScalar = 1.2; - SetStr(305, 425); - SetDex(72, 150); - SetInt(505, 750); + private bool m_SpeedBoost; - SetHits(4800); - SetStam(102, 300); - - SetDamage(25, 35); - - SetDamageType(ResistanceType.Physical, 100); - - SetResistance(ResistanceType.Physical, 25, 30); - SetResistance(ResistanceType.Fire, 35, 45); - SetResistance(ResistanceType.Cold, 50, 60); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 20, 30); - - SetSkill(SkillName.EvalInt, 120.0); - SetSkill(SkillName.Magery, 120.0); - SetSkill(SkillName.Meditation, 120.0); - SetSkill(SkillName.MagicResist, 150.0); - SetSkill(SkillName.Tactics, 97.6, 100.0); - SetSkill(SkillName.Wrestling, 97.6, 100.0); - - Fame = 22500; - Karma = -22500; - - VirtualArmor = 30; - Female = true; - - Item shroud = new HoodedShroudOfShadows(); - - shroud.Movable = false; - - AddItem(shroud); - - Scimitar weapon = new Scimitar(); - - weapon.Skill = SkillName.Wrestling; - weapon.Hue = 38; - weapon.Movable = false; - - AddItem(weapon); - - // new SkeletalMount().Rider = this; - AddItem(new VirtualMountItem(this)); - } - - public Neira(Serial serial) : base(serial) - { - } - - public override ChampionSkullType SkullType => ChampionSkullType.Death; - - public override Type[] UniqueList => new[] { typeof(ShroudOfDeciet) }; - - public override Type[] SharedList => new[] - { - typeof(ANecromancerShroud), - - typeof(CaptainJohnsHat) - }; - - public override Type[] DecorativeList => new[] { typeof(WallBlood), typeof(TatteredAncientMummyWrapping) }; - - public override MonsterStatuetteType[] StatueTypes => new MonsterStatuetteType[] { }; - - public override string DefaultName => "Neira"; - - public override bool AlwaysMurderer => true; - public override bool BardImmune => !Core.SE; - public override bool Unprovokable => Core.SE; - public override bool Uncalmable => Core.SE; - public override Poison PoisonImmune => Poison.Deadly; - - public override bool ShowFameTitle => false; - public override bool ClickTitle => false; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 3); - AddLoot(LootPack.Meager); - } - - public override bool OnBeforeDeath() - { - IMount mount = Mount; - - if (mount != null) - mount.Rider = null; - - (mount as Mobile)?.Delete(); - - return base.OnBeforeDeath(); - } - - public override void OnDamage(int amount, Mobile from, bool willKill) - { - CheckSpeedBoost(); - base.OnDamage(amount, from, willKill); - } - - private void CheckSpeedBoost() - { - if (Hits < HitsMax / 4) - { - if (!m_SpeedBoost) + [Constructible] + public Neira() : base(AIType.AI_Mage) { - ActiveSpeed /= SpeedBoostScalar; - PassiveSpeed /= SpeedBoostScalar; - m_SpeedBoost = true; + Title = "the necromancer"; + Body = 401; + Hue = 0x83EC; + + SetStr(305, 425); + SetDex(72, 150); + SetInt(505, 750); + + SetHits(4800); + SetStam(102, 300); + + SetDamage(25, 35); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 25, 30); + SetResistance(ResistanceType.Fire, 35, 45); + SetResistance(ResistanceType.Cold, 50, 60); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 20, 30); + + SetSkill(SkillName.EvalInt, 120.0); + SetSkill(SkillName.Magery, 120.0); + SetSkill(SkillName.Meditation, 120.0); + SetSkill(SkillName.MagicResist, 150.0); + SetSkill(SkillName.Tactics, 97.6, 100.0); + SetSkill(SkillName.Wrestling, 97.6, 100.0); + + Fame = 22500; + Karma = -22500; + + VirtualArmor = 30; + Female = true; + + Item shroud = new HoodedShroudOfShadows(); + + shroud.Movable = false; + + AddItem(shroud); + + var weapon = new Scimitar(); + + weapon.Skill = SkillName.Wrestling; + weapon.Hue = 38; + weapon.Movable = false; + + AddItem(weapon); + + // new SkeletalMount().Rider = this; + AddItem(new VirtualMountItem(this)); } - } - else if (m_SpeedBoost) - { - ActiveSpeed *= SpeedBoostScalar; - PassiveSpeed *= SpeedBoostScalar; - m_SpeedBoost = false; - } - } - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (Utility.RandomDouble() <= 0.1) // 10% chance to drop or throw an unholy bone - AddUnholyBone(defender, 0.25); - - CheckSpeedBoost(); - } - - public override void OnGotMeleeAttack(Mobile attacker) - { - base.OnGotMeleeAttack(attacker); - - if (Utility.RandomDouble() <= 0.1) // 10% chance to drop or throw an unholy bone - AddUnholyBone(attacker, 0.25); - } - - public override void AlterDamageScalarFrom(Mobile caster, ref double scalar) - { - base.AlterDamageScalarFrom(caster, ref scalar); - - if (Utility.RandomDouble() <= 0.1) // 10% chance to throw an unholy bone - AddUnholyBone(caster, 1.0); - } - - public void AddUnholyBone(Mobile target, double chanceToThrow) - { - if (Map == null) - return; - - if (chanceToThrow >= Utility.RandomDouble()) - { - Direction = GetDirectionTo(target); - MovingEffect(target, 0xF7E, 10, 1, true, false, 0x496, 0); - new DelayTimer(this, target).Start(); - } - else - { - new UnholyBone().MoveToWorld(Location, Map); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - writer.Write(m_SpeedBoost); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_SpeedBoost = reader.ReadBool(); - break; - } - } - } - - private class VirtualMount : IMount - { - private readonly VirtualMountItem m_Item; - - public VirtualMount(VirtualMountItem item) => m_Item = item; - - Mobile IMount.Rider - { - get => m_Item.Rider; - set { } - } - - public virtual void OnRiderDamaged(int amount, Mobile from, bool willKill) - { - } - } - - private class VirtualMountItem : Item, IMountItem - { - private readonly VirtualMount m_Mount; - - public VirtualMountItem(Mobile mob) - : base(0x3EBB) - { - Layer = Layer.Mount; - - Movable = false; - - Rider = mob; - m_Mount = new VirtualMount(this); - } - - public VirtualMountItem(Serial serial) - : base(serial) => - m_Mount = new VirtualMount(this); - - public Mobile Rider { get; private set; } - - public IMount Mount => m_Mount; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(Rider); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Rider = reader.ReadMobile(); - - if (Rider == null) - Delete(); - } - } - - private class DelayTimer : Timer - { - private readonly Mobile m_Mobile; - private readonly Mobile m_Target; - - public DelayTimer(Mobile m, Mobile target) : base(TimeSpan.FromSeconds(1.0)) - { - m_Mobile = m; - m_Target = target; - } - - protected override void OnTick() - { - if (m_Mobile.CanBeHarmful(m_Target)) + public Neira(Serial serial) : base(serial) { - m_Mobile.DoHarmful(m_Target); - AOS.Damage(m_Target, m_Mobile, Utility.RandomMinMax(10, 20), 100, 0, 0, 0, 0); - new UnholyBone().MoveToWorld(m_Target.Location, m_Target.Map); } - } + + public override ChampionSkullType SkullType => ChampionSkullType.Death; + + public override Type[] UniqueList => new[] { typeof(ShroudOfDeciet) }; + + public override Type[] SharedList => new[] + { + typeof(ANecromancerShroud), + + typeof(CaptainJohnsHat) + }; + + public override Type[] DecorativeList => new[] { typeof(WallBlood), typeof(TatteredAncientMummyWrapping) }; + + public override MonsterStatuetteType[] StatueTypes => new MonsterStatuetteType[] { }; + + public override string DefaultName => "Neira"; + + public override bool AlwaysMurderer => true; + public override bool BardImmune => !Core.SE; + public override bool Unprovokable => Core.SE; + public override bool Uncalmable => Core.SE; + public override Poison PoisonImmune => Poison.Deadly; + + public override bool ShowFameTitle => false; + public override bool ClickTitle => false; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 3); + AddLoot(LootPack.Meager); + } + + public override bool OnBeforeDeath() + { + var mount = Mount; + + if (mount != null) + mount.Rider = null; + + (mount as Mobile)?.Delete(); + + return base.OnBeforeDeath(); + } + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + CheckSpeedBoost(); + base.OnDamage(amount, from, willKill); + } + + private void CheckSpeedBoost() + { + if (Hits < HitsMax / 4) + { + if (!m_SpeedBoost) + { + ActiveSpeed /= SpeedBoostScalar; + PassiveSpeed /= SpeedBoostScalar; + m_SpeedBoost = true; + } + } + else if (m_SpeedBoost) + { + ActiveSpeed *= SpeedBoostScalar; + PassiveSpeed *= SpeedBoostScalar; + m_SpeedBoost = false; + } + } + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomDouble() <= 0.1) // 10% chance to drop or throw an unholy bone + AddUnholyBone(defender, 0.25); + + CheckSpeedBoost(); + } + + public override void OnGotMeleeAttack(Mobile attacker) + { + base.OnGotMeleeAttack(attacker); + + if (Utility.RandomDouble() <= 0.1) // 10% chance to drop or throw an unholy bone + AddUnholyBone(attacker, 0.25); + } + + public override void AlterDamageScalarFrom(Mobile caster, ref double scalar) + { + base.AlterDamageScalarFrom(caster, ref scalar); + + if (Utility.RandomDouble() <= 0.1) // 10% chance to throw an unholy bone + AddUnholyBone(caster, 1.0); + } + + public void AddUnholyBone(Mobile target, double chanceToThrow) + { + if (Map == null) + return; + + if (chanceToThrow >= Utility.RandomDouble()) + { + Direction = GetDirectionTo(target); + MovingEffect(target, 0xF7E, 10, 1, true, false, 0x496, 0); + new DelayTimer(this, target).Start(); + } + else + { + new UnholyBone().MoveToWorld(Location, Map); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + writer.Write(m_SpeedBoost); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_SpeedBoost = reader.ReadBool(); + break; + } + } + } + + private class VirtualMount : IMount + { + private readonly VirtualMountItem m_Item; + + public VirtualMount(VirtualMountItem item) => m_Item = item; + + Mobile IMount.Rider + { + get => m_Item.Rider; + set { } + } + + public virtual void OnRiderDamaged(int amount, Mobile from, bool willKill) + { + } + } + + private class VirtualMountItem : Item, IMountItem + { + private readonly VirtualMount m_Mount; + + public VirtualMountItem(Mobile mob) + : base(0x3EBB) + { + Layer = Layer.Mount; + + Movable = false; + + Rider = mob; + m_Mount = new VirtualMount(this); + } + + public VirtualMountItem(Serial serial) + : base(serial) => + m_Mount = new VirtualMount(this); + + public Mobile Rider { get; private set; } + + public IMount Mount => m_Mount; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(Rider); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + Rider = reader.ReadMobile(); + + if (Rider == null) + Delete(); + } + } + + private class DelayTimer : Timer + { + private readonly Mobile m_Mobile; + private readonly Mobile m_Target; + + public DelayTimer(Mobile m, Mobile target) : base(TimeSpan.FromSeconds(1.0)) + { + m_Mobile = m; + m_Target = target; + } + + protected override void OnTick() + { + if (m_Mobile.CanBeHarmful(m_Target)) + { + m_Mobile.DoHarmful(m_Target); + AOS.Damage(m_Target, m_Mobile, Utility.RandomMinMax(10, 20), 100, 0, 0, 0, 0); + new UnholyBone().MoveToWorld(m_Target.Location, m_Target.Map); + } + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Special/OrderGuard.cs b/Projects/UOContent/Mobiles/Special/OrderGuard.cs index 69f4ac8c2..41cbcc788 100644 --- a/Projects/UOContent/Mobiles/Special/OrderGuard.cs +++ b/Projects/UOContent/Mobiles/Special/OrderGuard.cs @@ -3,36 +3,36 @@ using Server.Items; namespace Server.Mobiles { - public class OrderGuard : BaseShieldGuard - { - [Constructible] - public OrderGuard() + public class OrderGuard : BaseShieldGuard { + [Constructible] + public OrderGuard() + { + } + + public OrderGuard(Serial serial) : base(serial) + { + } + + public override int Keyword => 0x21; // *order shield* + public override BaseShield Shield => new OrderShield(); + public override int SignupNumber => 1007141; // Sign up with a guild of order if thou art interested. + public override GuildType Type => GuildType.Order; + + public override bool BardImmune => true; + + 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 OrderGuard(Serial serial) : base(serial) - { - } - - public override int Keyword => 0x21; // *order shield* - public override BaseShield Shield => new OrderShield(); - public override int SignupNumber => 1007141; // Sign up with a guild of order if thou art interested. - public override GuildType Type => GuildType.Order; - - public override bool BardImmune => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Special/Paragon.cs b/Projects/UOContent/Mobiles/Special/Paragon.cs index 0d53ba1bb..c5b90076b 100644 --- a/Projects/UOContent/Mobiles/Special/Paragon.cs +++ b/Projects/UOContent/Mobiles/Special/Paragon.cs @@ -4,216 +4,217 @@ using Server.Utilities; namespace Server.Mobiles { - public class Paragon - { - public static double ChestChance = .10; // Chance that a paragon will carry a paragon chest - public static double ChocolateIngredientChance = .20; // Chance that a paragon will drop a chocolatiering ingredient - - public static Map[] Maps = + public class Paragon { - Map.Ilshenar - }; + public static double ChestChance = .10; // Chance that a paragon will carry a paragon chest + public static double ChocolateIngredientChance = .20; // Chance that a paragon will drop a chocolatiering ingredient - private static readonly TimeSpan FastRegenRate = TimeSpan.FromSeconds(.5); - private static readonly TimeSpan CPUSaverRate = TimeSpan.FromSeconds(2); - - public static Type[] Artifacts = - { - typeof(GoldBricks), typeof(PhillipsWoodenSteed), - typeof(AlchemistsBauble), typeof(ArcticDeathDealer), - typeof(BlazeOfDeath), typeof(BowOfTheJukaKing), - typeof(BurglarsBandana), typeof(CavortingClub), - typeof(EnchantedTitanLegBone), typeof(GwennosHarp), - typeof(IolosLute), typeof(LunaLance), - typeof(NightsKiss), typeof(NoxRangersHeavyCrossbow), - typeof(OrcishVisage), typeof(PolarBearMask), - typeof(ShieldOfInvulnerability), typeof(StaffOfPower), - typeof(VioletCourage), typeof(HeartOfTheLion), - typeof(WrathOfTheDryad), typeof(PixieSwatter), - typeof(GlovesOfThePugilist) - }; - - public static int Hue = 0x501; // Paragon hue - - // Buffs - public static double HitsBuff = 5.0; - public static double StrBuff = 1.05; - public static double IntBuff = 1.20; - public static double DexBuff = 1.20; - public static double SkillsBuff = 1.20; - public static double SpeedBuff = 1.20; - public static double FameBuff = 1.40; - public static double KarmaBuff = 1.40; - public static int DamageBuff = 5; - - public static void Convert(BaseCreature bc) - { - if (bc.IsParagon) - return; - - bc.Hue = Hue; - - if (bc.HitsMaxSeed >= 0) - bc.HitsMaxSeed = (int)(bc.HitsMaxSeed * HitsBuff); - - bc.RawStr = (int)(bc.RawStr * StrBuff); - bc.RawInt = (int)(bc.RawInt * IntBuff); - bc.RawDex = (int)(bc.RawDex * DexBuff); - - bc.Hits = bc.HitsMax; - bc.Mana = bc.ManaMax; - bc.Stam = bc.StamMax; - - for (int i = 0; i < bc.Skills.Length; i++) - { - Skill skill = bc.Skills[i]; - - if (skill.Base > 0.0) - skill.Base *= SkillsBuff; - } - - bc.PassiveSpeed /= SpeedBuff; - bc.ActiveSpeed /= SpeedBuff; - bc.CurrentSpeed = bc.PassiveSpeed; - - bc.DamageMin += DamageBuff; - bc.DamageMax += DamageBuff; - - if (bc.Fame > 0) - bc.Fame = (int)(bc.Fame * FameBuff); - - if (bc.Fame > 32000) - bc.Fame = 32000; - - // TODO: Mana regeneration rate = Sqrt( buffedFame ) / 4 - - if (bc.Karma != 0) - { - bc.Karma = (int)(bc.Karma * KarmaBuff); - - if (Math.Abs(bc.Karma) > 32000) - bc.Karma = 32000 * Math.Sign(bc.Karma); - } - - new ParagonStamRegen(bc).Start(); - } - - public static void UnConvert(BaseCreature bc) - { - if (!bc.IsParagon) - return; - - bc.Hue = 0; - - if (bc.HitsMaxSeed >= 0) - bc.HitsMaxSeed = (int)(bc.HitsMaxSeed / HitsBuff); - - bc.RawStr = (int)(bc.RawStr / StrBuff); - bc.RawInt = (int)(bc.RawInt / IntBuff); - bc.RawDex = (int)(bc.RawDex / DexBuff); - - bc.Hits = bc.HitsMax; - bc.Mana = bc.ManaMax; - bc.Stam = bc.StamMax; - - for (int i = 0; i < bc.Skills.Length; i++) - { - Skill skill = bc.Skills[i]; - - if (skill.Base > 0.0) - skill.Base /= SkillsBuff; - } - - bc.PassiveSpeed *= SpeedBuff; - bc.ActiveSpeed *= SpeedBuff; - bc.CurrentSpeed = bc.PassiveSpeed; - - bc.DamageMin -= DamageBuff; - bc.DamageMax -= DamageBuff; - - if (bc.Fame > 0) - bc.Fame = (int)(bc.Fame / FameBuff); - if (bc.Karma != 0) - bc.Karma = (int)(bc.Karma / KarmaBuff); - } - - public static bool CheckConvert(BaseCreature bc) => CheckConvert(bc, bc.Location, bc.Map); - - public static bool CheckConvert(BaseCreature bc, Point3D location, Map m) - { - if (!Core.AOS) - return false; - - if (Array.IndexOf(Maps, m) == -1) - return false; - - if (bc is BaseChampion || bc is Harrower || bc is BaseVendor || bc is BaseEscortable || bc is Clone || - bc.IsParagon) - return false; - - int fame = bc.Fame; - - if (fame > 32000) - fame = 32000; - - double chance = 1 / Math.Round(20.0 - fame / 3200); - - return chance > Utility.RandomDouble(); - } - - public static bool CheckArtifactChance(Mobile m, BaseCreature bc) - { - if (!Core.AOS) - return false; - - double fame = bc.Fame; - - if (fame > 32000) - fame = 32000; - - double chance = - 1 / (Math.Max(10, 100 * (0.83 - Math.Round(Math.Log(Math.Round(fame / 6000, 3) + 0.001, 10), 3))) * - (100 - Math.Sqrt(m.Luck)) / 100.0); - - return chance > Utility.RandomDouble(); - } - - public static void GiveArtifactTo(Mobile m) - { - Item item = (Item)ActivatorUtil.CreateInstance(Artifacts.RandomElement()); - - if (m.AddToBackpack(item)) - m.SendMessage("As a reward for slaying the mighty paragon, an artifact has been placed in your backpack."); - else - m.SendMessage( - "As your backpack is full, your reward for destroying the legendary paragon has been placed at your feet."); - } - - private class ParagonStamRegen : Timer - { - private readonly BaseCreature m_Owner; - - public ParagonStamRegen(Mobile m) - : base(FastRegenRate, FastRegenRate) - { - Priority = TimerPriority.FiftyMS; - - m_Owner = m as BaseCreature; - } - - protected override void OnTick() - { - if (!m_Owner.Deleted && m_Owner.IsParagon && m_Owner.Map != Map.Internal) + public static Map[] Maps = { - m_Owner.Stam++; + Map.Ilshenar + }; - Delay = Interval = m_Owner.Stam < m_Owner.StamMax * .75 ? FastRegenRate : CPUSaverRate; - } - else + private static readonly TimeSpan FastRegenRate = TimeSpan.FromSeconds(.5); + private static readonly TimeSpan CPUSaverRate = TimeSpan.FromSeconds(2); + + public static Type[] Artifacts = { - Stop(); + typeof(GoldBricks), typeof(PhillipsWoodenSteed), + typeof(AlchemistsBauble), typeof(ArcticDeathDealer), + typeof(BlazeOfDeath), typeof(BowOfTheJukaKing), + typeof(BurglarsBandana), typeof(CavortingClub), + typeof(EnchantedTitanLegBone), typeof(GwennosHarp), + typeof(IolosLute), typeof(LunaLance), + typeof(NightsKiss), typeof(NoxRangersHeavyCrossbow), + typeof(OrcishVisage), typeof(PolarBearMask), + typeof(ShieldOfInvulnerability), typeof(StaffOfPower), + typeof(VioletCourage), typeof(HeartOfTheLion), + typeof(WrathOfTheDryad), typeof(PixieSwatter), + typeof(GlovesOfThePugilist) + }; + + public static int Hue = 0x501; // Paragon hue + + // Buffs + public static double HitsBuff = 5.0; + public static double StrBuff = 1.05; + public static double IntBuff = 1.20; + public static double DexBuff = 1.20; + public static double SkillsBuff = 1.20; + public static double SpeedBuff = 1.20; + public static double FameBuff = 1.40; + public static double KarmaBuff = 1.40; + public static int DamageBuff = 5; + + public static void Convert(BaseCreature bc) + { + if (bc.IsParagon) + return; + + bc.Hue = Hue; + + if (bc.HitsMaxSeed >= 0) + bc.HitsMaxSeed = (int)(bc.HitsMaxSeed * HitsBuff); + + bc.RawStr = (int)(bc.RawStr * StrBuff); + bc.RawInt = (int)(bc.RawInt * IntBuff); + bc.RawDex = (int)(bc.RawDex * DexBuff); + + bc.Hits = bc.HitsMax; + bc.Mana = bc.ManaMax; + bc.Stam = bc.StamMax; + + for (var i = 0; i < bc.Skills.Length; i++) + { + var skill = bc.Skills[i]; + + if (skill.Base > 0.0) + skill.Base *= SkillsBuff; + } + + bc.PassiveSpeed /= SpeedBuff; + bc.ActiveSpeed /= SpeedBuff; + bc.CurrentSpeed = bc.PassiveSpeed; + + bc.DamageMin += DamageBuff; + bc.DamageMax += DamageBuff; + + if (bc.Fame > 0) + bc.Fame = (int)(bc.Fame * FameBuff); + + if (bc.Fame > 32000) + bc.Fame = 32000; + + // TODO: Mana regeneration rate = Sqrt( buffedFame ) / 4 + + if (bc.Karma != 0) + { + bc.Karma = (int)(bc.Karma * KarmaBuff); + + if (Math.Abs(bc.Karma) > 32000) + bc.Karma = 32000 * Math.Sign(bc.Karma); + } + + new ParagonStamRegen(bc).Start(); + } + + public static void UnConvert(BaseCreature bc) + { + if (!bc.IsParagon) + return; + + bc.Hue = 0; + + if (bc.HitsMaxSeed >= 0) + bc.HitsMaxSeed = (int)(bc.HitsMaxSeed / HitsBuff); + + bc.RawStr = (int)(bc.RawStr / StrBuff); + bc.RawInt = (int)(bc.RawInt / IntBuff); + bc.RawDex = (int)(bc.RawDex / DexBuff); + + bc.Hits = bc.HitsMax; + bc.Mana = bc.ManaMax; + bc.Stam = bc.StamMax; + + for (var i = 0; i < bc.Skills.Length; i++) + { + var skill = bc.Skills[i]; + + if (skill.Base > 0.0) + skill.Base /= SkillsBuff; + } + + bc.PassiveSpeed *= SpeedBuff; + bc.ActiveSpeed *= SpeedBuff; + bc.CurrentSpeed = bc.PassiveSpeed; + + bc.DamageMin -= DamageBuff; + bc.DamageMax -= DamageBuff; + + if (bc.Fame > 0) + bc.Fame = (int)(bc.Fame / FameBuff); + if (bc.Karma != 0) + bc.Karma = (int)(bc.Karma / KarmaBuff); + } + + public static bool CheckConvert(BaseCreature bc) => CheckConvert(bc, bc.Location, bc.Map); + + public static bool CheckConvert(BaseCreature bc, Point3D location, Map m) + { + if (!Core.AOS) + return false; + + if (Array.IndexOf(Maps, m) == -1) + return false; + + if (bc is BaseChampion || bc is Harrower || bc is BaseVendor || bc is BaseEscortable || bc is Clone || + bc.IsParagon) + return false; + + var fame = bc.Fame; + + if (fame > 32000) + fame = 32000; + + var chance = 1 / Math.Round(20.0 - fame / 3200); + + return chance > Utility.RandomDouble(); + } + + public static bool CheckArtifactChance(Mobile m, BaseCreature bc) + { + if (!Core.AOS) + return false; + + double fame = bc.Fame; + + if (fame > 32000) + fame = 32000; + + var chance = + 1 / (Math.Max(10, 100 * (0.83 - Math.Round(Math.Log(Math.Round(fame / 6000, 3) + 0.001, 10), 3))) * + (100 - Math.Sqrt(m.Luck)) / 100.0); + + return chance > Utility.RandomDouble(); + } + + public static void GiveArtifactTo(Mobile m) + { + var item = (Item)ActivatorUtil.CreateInstance(Artifacts.RandomElement()); + + if (m.AddToBackpack(item)) + m.SendMessage("As a reward for slaying the mighty paragon, an artifact has been placed in your backpack."); + else + m.SendMessage( + "As your backpack is full, your reward for destroying the legendary paragon has been placed at your feet." + ); + } + + private class ParagonStamRegen : Timer + { + private readonly BaseCreature m_Owner; + + public ParagonStamRegen(Mobile m) + : base(FastRegenRate, FastRegenRate) + { + Priority = TimerPriority.FiftyMS; + + m_Owner = m as BaseCreature; + } + + protected override void OnTick() + { + if (!m_Owner.Deleted && m_Owner.IsParagon && m_Owner.Map != Map.Internal) + { + m_Owner.Stam++; + + Delay = Interval = m_Owner.Stam < m_Owner.StamMax * .75 ? FastRegenRate : CPUSaverRate; + } + else + { + Stop(); + } + } } - } } - } } diff --git a/Projects/UOContent/Mobiles/Special/Rikktor.cs b/Projects/UOContent/Mobiles/Special/Rikktor.cs index 48c4dc89d..c829ce608 100644 --- a/Projects/UOContent/Mobiles/Special/Rikktor.cs +++ b/Projects/UOContent/Mobiles/Special/Rikktor.cs @@ -4,148 +4,148 @@ using Server.Items; namespace Server.Mobiles { - public class Rikktor : BaseChampion - { - [Constructible] - public Rikktor() : base(AIType.AI_Melee) + public class Rikktor : BaseChampion { - Body = 172; + [Constructible] + public Rikktor() : base(AIType.AI_Melee) + { + Body = 172; - SetStr(701, 900); - SetDex(201, 350); - SetInt(51, 100); + SetStr(701, 900); + SetDex(201, 350); + SetInt(51, 100); - SetHits(3000); - SetStam(203, 650); + SetHits(3000); + SetStam(203, 650); - SetDamage(28, 55); + SetDamage(28, 55); - SetDamageType(ResistanceType.Physical, 25); - SetDamageType(ResistanceType.Fire, 50); - SetDamageType(ResistanceType.Energy, 25); + SetDamageType(ResistanceType.Physical, 25); + SetDamageType(ResistanceType.Fire, 50); + SetDamageType(ResistanceType.Energy, 25); - SetResistance(ResistanceType.Physical, 80, 90); - SetResistance(ResistanceType.Fire, 80, 90); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 80, 90); - SetResistance(ResistanceType.Energy, 80, 90); + SetResistance(ResistanceType.Physical, 80, 90); + SetResistance(ResistanceType.Fire, 80, 90); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 80, 90); + SetResistance(ResistanceType.Energy, 80, 90); - SetSkill(SkillName.Anatomy, 100.0); - SetSkill(SkillName.MagicResist, 140.2, 160.0); - SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.Anatomy, 100.0); + SetSkill(SkillName.MagicResist, 140.2, 160.0); + SetSkill(SkillName.Tactics, 100.0); - Fame = 22500; - Karma = -22500; + Fame = 22500; + Karma = -22500; - VirtualArmor = 130; + VirtualArmor = 130; + } + + public Rikktor(Serial serial) : base(serial) + { + } + + public override ChampionSkullType SkullType => ChampionSkullType.Power; + + public override Type[] UniqueList => new[] { typeof(CrownOfTalKeesh) }; + + public override Type[] SharedList => new[] + { + typeof(TheMostKnowledgePerson), + typeof(BraveKnightOfTheBritannia), + typeof(LieutenantOfTheBritannianRoyalGuard) + }; + + public override Type[] DecorativeList => new[] + { + typeof(LavaTile), + typeof(MonsterStatuette), + typeof(MonsterStatuette) + }; + + public override MonsterStatuetteType[] StatueTypes => new[] + { + MonsterStatuetteType.OphidianArchMage, + MonsterStatuetteType.OphidianWarrior + }; + + public override string DefaultName => "Rikktor"; + + public override Poison PoisonImmune => Poison.Lethal; + public override ScaleType ScaleType => ScaleType.All; + public override int Scales => 20; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 4); + } + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomDouble() <= 0.2) + Earthquake(); + } + + public void Earthquake() + { + var map = Map; + + if (map == null) + return; + + PlaySound(0x2F3); + + var eable = GetMobilesInRange(8); + + foreach (var m in eable) + { + if (m == this || !(CanBeHarmful(m) || m.Player && m.Alive)) + continue; + + if (!(m is BaseCreature bc) || !(bc.Controlled || bc.Summoned || bc.Team != Team)) + continue; + + var damage = m.Hits * 0.6; + + if (damage < 10.0) + damage = 10.0; + else if (damage > 75.0) + damage = 75.0; + + DoHarmful(m); + + AOS.Damage(m, this, (int)damage, 100, 0, 0, 0, 0); + + if (m.Alive && m.Body.IsHuman && !m.Mounted) + m.Animate(20, 7, 1, true, false, 0); // take hit + } + + eable.Free(); + } + + public override int GetAngerSound() => Utility.Random(0x2CE, 2); + + public override int GetIdleSound() => 0x2D2; + + public override int GetAttackSound() => Utility.Random(0x2C7, 5); + + public override int GetHurtSound() => 0x2D1; + + public override int GetDeathSound() => 0x2CC; + + 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 Rikktor(Serial serial) : base(serial) - { - } - - public override ChampionSkullType SkullType => ChampionSkullType.Power; - - public override Type[] UniqueList => new[] { typeof(CrownOfTalKeesh) }; - - public override Type[] SharedList => new[] - { - typeof(TheMostKnowledgePerson), - typeof(BraveKnightOfTheBritannia), - typeof(LieutenantOfTheBritannianRoyalGuard) - }; - - public override Type[] DecorativeList => new[] - { - typeof(LavaTile), - typeof(MonsterStatuette), - typeof(MonsterStatuette) - }; - - public override MonsterStatuetteType[] StatueTypes => new[] - { - MonsterStatuetteType.OphidianArchMage, - MonsterStatuetteType.OphidianWarrior - }; - - public override string DefaultName => "Rikktor"; - - public override Poison PoisonImmune => Poison.Lethal; - public override ScaleType ScaleType => ScaleType.All; - public override int Scales => 20; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 4); - } - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (Utility.RandomDouble() <= 0.2) - Earthquake(); - } - - public void Earthquake() - { - Map map = Map; - - if (map == null) - return; - - PlaySound(0x2F3); - - IPooledEnumerable eable = GetMobilesInRange(8); - - foreach (Mobile m in eable) - { - if (m == this || !(CanBeHarmful(m) || (m.Player && m.Alive))) - continue; - - if (!(m is BaseCreature bc) || !(bc.Controlled || bc.Summoned || bc.Team != Team)) - continue; - - double damage = m.Hits * 0.6; - - if (damage < 10.0) - damage = 10.0; - else if (damage > 75.0) - damage = 75.0; - - DoHarmful(m); - - AOS.Damage(m, this, (int)damage, 100, 0, 0, 0, 0); - - if (m.Alive && m.Body.IsHuman && !m.Mounted) - m.Animate(20, 7, 1, true, false, 0); // take hit - } - - eable.Free(); - } - - public override int GetAngerSound() => Utility.Random(0x2CE, 2); - - public override int GetIdleSound() => 0x2D2; - - public override int GetAttackSound() => Utility.Random(0x2C7, 5); - - public override int GetHurtSound() => 0x2D1; - - public override int GetDeathSound() => 0x2CC; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Special/Semidar.cs b/Projects/UOContent/Mobiles/Special/Semidar.cs index 576a29b89..dec0495e8 100644 --- a/Projects/UOContent/Mobiles/Special/Semidar.cs +++ b/Projects/UOContent/Mobiles/Special/Semidar.cs @@ -4,140 +4,140 @@ using Server.Items; namespace Server.Mobiles { - public class Semidar : BaseChampion - { - [Constructible] - public Semidar() : base(AIType.AI_Mage) + public class Semidar : BaseChampion { - Body = 174; - BaseSoundID = 0x4B0; + [Constructible] + public Semidar() : base(AIType.AI_Mage) + { + Body = 174; + BaseSoundID = 0x4B0; - SetStr(502, 600); - SetDex(102, 200); - SetInt(601, 750); + SetStr(502, 600); + SetDex(102, 200); + SetInt(601, 750); - SetHits(1500); - SetStam(103, 250); + SetHits(1500); + SetStam(103, 250); - SetDamage(29, 35); + SetDamage(29, 35); - SetDamageType(ResistanceType.Physical, 75); - SetDamageType(ResistanceType.Fire, 25); + SetDamageType(ResistanceType.Physical, 75); + SetDamageType(ResistanceType.Fire, 25); - SetResistance(ResistanceType.Physical, 20, 30); - SetResistance(ResistanceType.Fire, 50, 60); - SetResistance(ResistanceType.Cold, 20, 30); - SetResistance(ResistanceType.Poison, 20, 30); - SetResistance(ResistanceType.Energy, 10, 20); + SetResistance(ResistanceType.Physical, 20, 30); + SetResistance(ResistanceType.Fire, 50, 60); + SetResistance(ResistanceType.Cold, 20, 30); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 10, 20); - SetSkill(SkillName.EvalInt, 95.1, 100.0); - SetSkill(SkillName.Magery, 90.1, 105.0); - SetSkill(SkillName.Meditation, 95.1, 100.0); - SetSkill(SkillName.MagicResist, 120.2, 140.0); - SetSkill(SkillName.Tactics, 90.1, 105.0); - SetSkill(SkillName.Wrestling, 90.1, 105.0); + SetSkill(SkillName.EvalInt, 95.1, 100.0); + SetSkill(SkillName.Magery, 90.1, 105.0); + SetSkill(SkillName.Meditation, 95.1, 100.0); + SetSkill(SkillName.MagicResist, 120.2, 140.0); + SetSkill(SkillName.Tactics, 90.1, 105.0); + SetSkill(SkillName.Wrestling, 90.1, 105.0); - Fame = 24000; - Karma = -24000; + Fame = 24000; + Karma = -24000; - VirtualArmor = 20; + VirtualArmor = 20; + } + + public Semidar(Serial serial) : base(serial) + { + } + + public override ChampionSkullType SkullType => ChampionSkullType.Pain; + + public override Type[] UniqueList => new[] { typeof(GladiatorsCollar) }; + + public override Type[] SharedList => new[] + { typeof(RoyalGuardSurvivalKnife), typeof(ANecromancerShroud), typeof(LieutenantOfTheBritannianRoyalGuard) }; + + public override Type[] DecorativeList => new[] { typeof(LavaTile), typeof(DemonSkull) }; + + public override MonsterStatuetteType[] StatueTypes => new MonsterStatuetteType[] { }; + + public override string DefaultName => "Semidar"; + + public override bool Unprovokable => true; + public override Poison PoisonImmune => Poison.Lethal; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 4); + AddLoot(LootPack.FilthyRich); + } + + public override void CheckReflect(Mobile caster, ref bool reflect) + { + if (caster.Body.IsMale) + reflect = true; // Always reflect if caster isn't female + } + + public override void AlterDamageScalarFrom(Mobile caster, ref double scalar) + { + if (caster.Body.IsMale) + scalar = 20; // Male bodies always reflect.. damage scaled 20x + } + + public void DrainLife() + { + if (Map == null) + return; + + var eable = GetMobilesInRange(2); + + foreach (var m in eable) + { + if (m == this || !(CanBeHarmful(m) || m.Player && m.Alive)) + continue; + + if (!(m is BaseCreature bc) || !(bc.Controlled || bc.Summoned || bc.Team != Team)) + continue; + + DoHarmful(m); + + m.FixedParticles(0x374A, 10, 15, 5013, 0x496, 0, EffectLayer.Waist); + m.PlaySound(0x231); + + m.SendMessage("You feel the life drain out of you!"); + + var toDrain = Utility.RandomMinMax(10, 40); + + Hits += toDrain; + m.Damage(toDrain, this); + } + + eable.Free(); + } + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + if (Utility.RandomDouble() <= 0.25) + DrainLife(); + } + + public override void OnGotMeleeAttack(Mobile attacker) + { + base.OnGotMeleeAttack(attacker); + + if (Utility.RandomDouble() <= 0.25) + DrainLife(); + } + + 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(); + } } - - public Semidar(Serial serial) : base(serial) - { - } - - public override ChampionSkullType SkullType => ChampionSkullType.Pain; - - public override Type[] UniqueList => new[] { typeof(GladiatorsCollar) }; - - public override Type[] SharedList => new[] - { typeof(RoyalGuardSurvivalKnife), typeof(ANecromancerShroud), typeof(LieutenantOfTheBritannianRoyalGuard) }; - - public override Type[] DecorativeList => new[] { typeof(LavaTile), typeof(DemonSkull) }; - - public override MonsterStatuetteType[] StatueTypes => new MonsterStatuetteType[] { }; - - public override string DefaultName => "Semidar"; - - public override bool Unprovokable => true; - public override Poison PoisonImmune => Poison.Lethal; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 4); - AddLoot(LootPack.FilthyRich); - } - - public override void CheckReflect(Mobile caster, ref bool reflect) - { - if (caster.Body.IsMale) - reflect = true; // Always reflect if caster isn't female - } - - public override void AlterDamageScalarFrom(Mobile caster, ref double scalar) - { - if (caster.Body.IsMale) - scalar = 20; // Male bodies always reflect.. damage scaled 20x - } - - public void DrainLife() - { - if (Map == null) - return; - - IPooledEnumerable eable = GetMobilesInRange(2); - - foreach (Mobile m in eable) - { - if (m == this || !(CanBeHarmful(m) || (m.Player && m.Alive))) - continue; - - if (!(m is BaseCreature bc) || !(bc.Controlled || bc.Summoned || bc.Team != Team)) - continue; - - DoHarmful(m); - - m.FixedParticles(0x374A, 10, 15, 5013, 0x496, 0, EffectLayer.Waist); - m.PlaySound(0x231); - - m.SendMessage("You feel the life drain out of you!"); - - int toDrain = Utility.RandomMinMax(10, 40); - - Hits += toDrain; - m.Damage(toDrain, this); - } - - eable.Free(); - } - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - if (Utility.RandomDouble() <= 0.25) - DrainLife(); - } - - public override void OnGotMeleeAttack(Mobile attacker) - { - base.OnGotMeleeAttack(attacker); - - if (Utility.RandomDouble() <= 0.25) - DrainLife(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Special/Serado.cs b/Projects/UOContent/Mobiles/Special/Serado.cs index eb864e8e9..44f558681 100644 --- a/Projects/UOContent/Mobiles/Special/Serado.cs +++ b/Projects/UOContent/Mobiles/Special/Serado.cs @@ -5,178 +5,178 @@ using Server.Items; namespace Server.Mobiles { - public class Serado : BaseChampion - { - [Constructible] - public Serado() : base(AIType.AI_Melee) + public class Serado : BaseChampion { - Title = "the awakened"; + [Constructible] + public Serado() : base(AIType.AI_Melee) + { + Title = "the awakened"; - Body = 249; - Hue = 0x96C; + Body = 249; + Hue = 0x96C; - SetStr(1000); - SetDex(150); - SetInt(300); + SetStr(1000); + SetDex(150); + SetInt(300); - SetHits(9000); - SetMana(300); + SetHits(9000); + SetMana(300); - SetDamage(29, 35); + SetDamage(29, 35); - SetDamageType(ResistanceType.Physical, 70); - SetDamageType(ResistanceType.Poison, 20); - SetDamageType(ResistanceType.Energy, 10); + SetDamageType(ResistanceType.Physical, 70); + SetDamageType(ResistanceType.Poison, 20); + SetDamageType(ResistanceType.Energy, 10); - SetResistance(ResistanceType.Physical, 30); - SetResistance(ResistanceType.Fire, 60); - SetResistance(ResistanceType.Cold, 60); - SetResistance(ResistanceType.Poison, 90); - SetResistance(ResistanceType.Energy, 50); + SetResistance(ResistanceType.Physical, 30); + SetResistance(ResistanceType.Fire, 60); + SetResistance(ResistanceType.Cold, 60); + SetResistance(ResistanceType.Poison, 90); + SetResistance(ResistanceType.Energy, 50); - SetSkill(SkillName.MagicResist, 120.0); - SetSkill(SkillName.Tactics, 120.0); - SetSkill(SkillName.Wrestling, 70.0); - SetSkill(SkillName.Poisoning, 150.0); + SetSkill(SkillName.MagicResist, 120.0); + SetSkill(SkillName.Tactics, 120.0); + SetSkill(SkillName.Wrestling, 70.0); + SetSkill(SkillName.Poisoning, 150.0); - Fame = 22500; - Karma = -22500; + Fame = 22500; + Karma = -22500; - PackItem(Seed.RandomBonsaiSeed()); + PackItem(Seed.RandomBonsaiSeed()); + } + + public Serado(Serial serial) : base(serial) + { + } + + public override ChampionSkullType SkullType => ChampionSkullType.Power; + + public override Type[] UniqueList => new[] { typeof(Pacify) }; + + public override Type[] SharedList => new[] + { + typeof(BraveKnightOfTheBritannia), + typeof(DetectiveBoots), + typeof(EmbroideredOakLeafCloak), + typeof(LieutenantOfTheBritannianRoyalGuard) + }; + + public override Type[] DecorativeList => new[] { typeof(Futon), typeof(SwampTile) }; + + public override MonsterStatuetteType[] StatueTypes => new MonsterStatuetteType[] { }; + + public override string DefaultName => "Serado"; + + public override int TreasureMapLevel => 5; + + public override Poison HitPoison => Poison.Lethal; + public override Poison PoisonImmune => Poison.Lethal; + public override double HitPoisonChance => 0.8; + + public override int Feathers => 30; + + public override bool ShowFameTitle => false; + public override bool ClickTitle => false; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.DoubleStrike; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 4); + AddLoot(LootPack.FilthyRich); + AddLoot(LootPack.Gems, 6); + } + + // TODO: Hit Lightning Area + + public override void OnDamagedBySpell(Mobile attacker) + { + base.OnDamagedBySpell(attacker); + + ScaleResistances(); + DoCounter(attacker); + } + + public override void OnGotMeleeAttack(Mobile attacker) + { + base.OnGotMeleeAttack(attacker); + + ScaleResistances(); + DoCounter(attacker); + } + + private void ScaleResistances() + { + var hitsLost = (HitsMax - Hits) / (double)HitsMax; + + SetResistance(ResistanceType.Physical, 30 + (int)(hitsLost * (95 - 30))); + SetResistance(ResistanceType.Fire, 60 + (int)(hitsLost * (95 - 60))); + SetResistance(ResistanceType.Cold, 60 + (int)(hitsLost * (95 - 60))); + SetResistance(ResistanceType.Poison, 90 + (int)(hitsLost * (95 - 90))); + SetResistance(ResistanceType.Energy, 50 + (int)(hitsLost * (95 - 50))); + } + + private void DoCounter(Mobile attacker) + { + if (Map == null) + return; + + if (!(Utility.RandomDouble() < 0.2)) + return; + + Mobile target = null; + + if (attacker is BaseCreature bcAttacker) + { + if (bcAttacker.BardProvoked) + return; + + target = bcAttacker.GetMaster(); + } + + /* Counterattack with Hit Poison Area + * 20-25 damage, unresistable + * Lethal poison, 100% of the time + * Particle effect: Type: "2" From: "0x4061A107" To: "0x0" ItemId: "0x36BD" ItemIdName: "explosion" FromLocation: "(296 615, 17)" ToLocation: "(296 615, 17)" Speed: "1" Duration: "10" FixedDirection: "True" Explode: "False" Hue: "0xA6" RenderMode: "0x0" Effect: "0x1F78" ExplodeEffect: "0x1" ExplodeSound: "0x0" Serial: "0x4061A107" Layer: "255" Unknown: "0x0" + * Doesn't work on provoked monsters + */ + + if (target?.InRange(this, 25) != true) + target = attacker; + + Animate(10, 4, 1, true, false, 0); + + var eable = target.GetMobilesInRange(8); + + foreach (var m in eable) + { + if (m == this || !(CanBeHarmful(m) || m.Player && m.Alive)) + continue; + + if (!(m is BaseCreature bc) || !(bc.Controlled || bc.Summoned || bc.Team != Team)) + continue; + + DoHarmful(m); + + AOS.Damage(m, this, Utility.RandomMinMax(20, 25), true, 0, 0, 0, 100, 0); + + m.FixedParticles(0x36BD, 1, 10, 0x1F78, 0xA6, 0, (EffectLayer)255); + m.ApplyPoison(this, Poison.Lethal); + } + } + + 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 Serado(Serial serial) : base(serial) - { - } - - public override ChampionSkullType SkullType => ChampionSkullType.Power; - - public override Type[] UniqueList => new[] { typeof(Pacify) }; - - public override Type[] SharedList => new[] - { - typeof(BraveKnightOfTheBritannia), - typeof(DetectiveBoots), - typeof(EmbroideredOakLeafCloak), - typeof(LieutenantOfTheBritannianRoyalGuard) - }; - - public override Type[] DecorativeList => new[] { typeof(Futon), typeof(SwampTile) }; - - public override MonsterStatuetteType[] StatueTypes => new MonsterStatuetteType[] { }; - - public override string DefaultName => "Serado"; - - public override int TreasureMapLevel => 5; - - public override Poison HitPoison => Poison.Lethal; - public override Poison PoisonImmune => Poison.Lethal; - public override double HitPoisonChance => 0.8; - - public override int Feathers => 30; - - public override bool ShowFameTitle => false; - public override bool ClickTitle => false; - - public override WeaponAbility GetWeaponAbility() => WeaponAbility.DoubleStrike; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 4); - AddLoot(LootPack.FilthyRich); - AddLoot(LootPack.Gems, 6); - } - - // TODO: Hit Lightning Area - - public override void OnDamagedBySpell(Mobile attacker) - { - base.OnDamagedBySpell(attacker); - - ScaleResistances(); - DoCounter(attacker); - } - - public override void OnGotMeleeAttack(Mobile attacker) - { - base.OnGotMeleeAttack(attacker); - - ScaleResistances(); - DoCounter(attacker); - } - - private void ScaleResistances() - { - double hitsLost = (HitsMax - Hits) / (double)HitsMax; - - SetResistance(ResistanceType.Physical, 30 + (int)(hitsLost * (95 - 30))); - SetResistance(ResistanceType.Fire, 60 + (int)(hitsLost * (95 - 60))); - SetResistance(ResistanceType.Cold, 60 + (int)(hitsLost * (95 - 60))); - SetResistance(ResistanceType.Poison, 90 + (int)(hitsLost * (95 - 90))); - SetResistance(ResistanceType.Energy, 50 + (int)(hitsLost * (95 - 50))); - } - - private void DoCounter(Mobile attacker) - { - if (Map == null) - return; - - if (!(Utility.RandomDouble() < 0.2)) - return; - - Mobile target = null; - - if (attacker is BaseCreature bcAttacker) - { - if (bcAttacker.BardProvoked) - return; - - target = bcAttacker.GetMaster(); - } - - /* Counterattack with Hit Poison Area - * 20-25 damage, unresistable - * Lethal poison, 100% of the time - * Particle effect: Type: "2" From: "0x4061A107" To: "0x0" ItemId: "0x36BD" ItemIdName: "explosion" FromLocation: "(296 615, 17)" ToLocation: "(296 615, 17)" Speed: "1" Duration: "10" FixedDirection: "True" Explode: "False" Hue: "0xA6" RenderMode: "0x0" Effect: "0x1F78" ExplodeEffect: "0x1" ExplodeSound: "0x0" Serial: "0x4061A107" Layer: "255" Unknown: "0x0" - * Doesn't work on provoked monsters - */ - - if (target?.InRange(this, 25) != true) - target = attacker; - - Animate(10, 4, 1, true, false, 0); - - IPooledEnumerable eable = target.GetMobilesInRange(8); - - foreach (Mobile m in eable) - { - if (m == this || !(CanBeHarmful(m) || (m.Player && m.Alive))) - continue; - - if (!(m is BaseCreature bc) || !(bc.Controlled || bc.Summoned || bc.Team != Team)) - continue; - - DoHarmful(m); - - AOS.Damage(m, this, Utility.RandomMinMax(20, 25), true, 0, 0, 0, 100, 0); - - m.FixedParticles(0x36BD, 1, 10, 0x1F78, 0xA6, 0, (EffectLayer)255); - m.ApplyPoison(this, Poison.Lethal); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Special/ServantOfSemidar.cs b/Projects/UOContent/Mobiles/Special/ServantOfSemidar.cs index 61a572d57..d7cd010ba 100644 --- a/Projects/UOContent/Mobiles/Special/ServantOfSemidar.cs +++ b/Projects/UOContent/Mobiles/Special/ServantOfSemidar.cs @@ -1,41 +1,41 @@ namespace Server.Mobiles { - public class ServantOfSemidar : BaseCreature - { - [Constructible] - public ServantOfSemidar() : base(AIType.AI_Melee, FightMode.None, 10, 1, 0.2, 0.4) => Body = 0x26; - - public ServantOfSemidar(Serial serial) : base(serial) + public class ServantOfSemidar : BaseCreature { + [Constructible] + public ServantOfSemidar() : base(AIType.AI_Melee, FightMode.None, 10, 1, 0.2, 0.4) => Body = 0x26; + + public ServantOfSemidar(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a Servant of Semidar"; + + public override bool DisallowAllMoves => true; + + public override bool InitialInnocent => true; + + public override bool CanBeDamaged() => false; + + public override void AddNameProperties(ObjectPropertyList list) + { + base.AddNameProperties(list); + + list.Add(1005494); // enslaved + } + + 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(); + } } - - public override string DefaultName => "a Servant of Semidar"; - - public override bool DisallowAllMoves => true; - - public override bool InitialInnocent => true; - - public override bool CanBeDamaged() => false; - - public override void AddNameProperties(ObjectPropertyList list) - { - base.AddNameProperties(list); - - list.Add(1005494); // enslaved - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Special/Silvani.cs b/Projects/UOContent/Mobiles/Special/Silvani.cs index b9180b9a1..6f3e3283e 100644 --- a/Projects/UOContent/Mobiles/Special/Silvani.cs +++ b/Projects/UOContent/Mobiles/Special/Silvani.cs @@ -1,114 +1,114 @@ namespace Server.Mobiles { - public class Silvani : BaseCreature - { - [Constructible] - public Silvani() : base(AIType.AI_Mage, FightMode.Evil, 18, 1, 0.1, 0.2) + public class Silvani : BaseCreature { - Body = 176; - BaseSoundID = 0x467; + [Constructible] + public Silvani() : base(AIType.AI_Mage, FightMode.Evil, 18, 1, 0.1, 0.2) + { + Body = 176; + BaseSoundID = 0x467; - SetStr(253, 400); - SetDex(157, 850); - SetInt(503, 800); + SetStr(253, 400); + SetDex(157, 850); + SetInt(503, 800); - SetHits(600); + SetHits(600); - SetDamage(27, 38); + SetDamage(27, 38); - SetDamageType(ResistanceType.Physical, 75); - SetDamageType(ResistanceType.Cold, 25); + SetDamageType(ResistanceType.Physical, 75); + SetDamageType(ResistanceType.Cold, 25); - SetResistance(ResistanceType.Physical, 45, 55); - SetResistance(ResistanceType.Fire, 30, 40); - SetResistance(ResistanceType.Cold, 30, 40); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 45, 55); + SetResistance(ResistanceType.Fire, 30, 40); + SetResistance(ResistanceType.Cold, 30, 40); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.EvalInt, 100.0); - SetSkill(SkillName.Magery, 97.6, 107.5); - SetSkill(SkillName.Meditation, 100.0); - SetSkill(SkillName.MagicResist, 100.5, 150.0); - SetSkill(SkillName.Tactics, 97.6, 100.0); - SetSkill(SkillName.Wrestling, 97.6, 100.0); + SetSkill(SkillName.EvalInt, 100.0); + SetSkill(SkillName.Magery, 97.6, 107.5); + SetSkill(SkillName.Meditation, 100.0); + SetSkill(SkillName.MagicResist, 100.5, 150.0); + SetSkill(SkillName.Tactics, 97.6, 100.0); + SetSkill(SkillName.Wrestling, 97.6, 100.0); - Fame = 20000; - Karma = 20000; + Fame = 20000; + Karma = 20000; - VirtualArmor = 50; + VirtualArmor = 50; + } + + public Silvani(Serial serial) : base(serial) + { + } + + public override string DefaultName => "Silvani"; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + + public override bool CanFly => true; + public override bool Unprovokable => true; + public override Poison PoisonImmune => Poison.Regular; + public override int TreasureMapLevel => 5; + + public override void GenerateLoot() + { + AddLoot(LootPack.UltraRich, 2); + } + + public void SpawnPixies(Mobile target) + { + var map = Map; + + if (map == null) + return; + + var newPixies = Utility.RandomMinMax(3, 6); + + for (var i = 0; i < newPixies; ++i) + { + var pixie = new Pixie { Team = Team, FightMode = FightMode.Closest }; + + pixie.MoveToWorld(map.GetRandomNearbyLocation(Location), map); + pixie.Combatant = target; + } + } + + public override void AlterDamageScalarFrom(Mobile caster, ref double scalar) + { + if (Utility.RandomDouble() <= 0.1) + SpawnPixies(caster); + } + + public override void OnGaveMeleeAttack(Mobile defender) + { + base.OnGaveMeleeAttack(defender); + + defender.Damage(Utility.Random(20, 10), this); + defender.Stam -= Utility.Random(20, 10); + defender.Mana -= Utility.Random(20, 10); + } + + public override void OnGotMeleeAttack(Mobile attacker) + { + base.OnGotMeleeAttack(attacker); + + if (Utility.RandomDouble() <= 0.1) + SpawnPixies(attacker); + } + + 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 Silvani(Serial serial) : base(serial) - { - } - - public override string DefaultName => "Silvani"; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - - public override bool CanFly => true; - public override bool Unprovokable => true; - public override Poison PoisonImmune => Poison.Regular; - public override int TreasureMapLevel => 5; - - public override void GenerateLoot() - { - AddLoot(LootPack.UltraRich, 2); - } - - public void SpawnPixies(Mobile target) - { - Map map = Map; - - if (map == null) - return; - - int newPixies = Utility.RandomMinMax(3, 6); - - for (int i = 0; i < newPixies; ++i) - { - Pixie pixie = new Pixie { Team = Team, FightMode = FightMode.Closest }; - - pixie.MoveToWorld(map.GetRandomNearbyLocation(Location), map); - pixie.Combatant = target; - } - } - - public override void AlterDamageScalarFrom(Mobile caster, ref double scalar) - { - if (Utility.RandomDouble() <= 0.1) - SpawnPixies(caster); - } - - public override void OnGaveMeleeAttack(Mobile defender) - { - base.OnGaveMeleeAttack(defender); - - defender.Damage(Utility.Random(20, 10), this); - defender.Stam -= Utility.Random(20, 10); - defender.Mana -= Utility.Random(20, 10); - } - - public override void OnGotMeleeAttack(Mobile attacker) - { - base.OnGotMeleeAttack(attacker); - - if (Utility.RandomDouble() <= 0.1) - SpawnPixies(attacker); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Special/Wanderer.cs b/Projects/UOContent/Mobiles/Special/Wanderer.cs index bc67e9165..d2fbd0b56 100644 --- a/Projects/UOContent/Mobiles/Special/Wanderer.cs +++ b/Projects/UOContent/Mobiles/Special/Wanderer.cs @@ -2,61 +2,62 @@ using System; namespace Server.Mobiles { - public class Wanderer : Mobile - { - private readonly Timer m_Timer; - - [Constructible] - public Wanderer() + public class Wanderer : Mobile { - Name = "Me"; - Body = 0x1; - AccessLevel = AccessLevel.Counselor; + private readonly Timer m_Timer; - m_Timer = new InternalTimer(this); - m_Timer.Start(); + [Constructible] + public Wanderer() + { + Name = "Me"; + Body = 0x1; + AccessLevel = AccessLevel.Counselor; + + m_Timer = new InternalTimer(this); + m_Timer.Start(); + } + + public Wanderer(Serial serial) : base(serial) + { + m_Timer = new InternalTimer(this); + m_Timer.Start(); + } + + public override void OnDelete() + { + m_Timer.Stop(); + + base.OnDelete(); + } + + 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(); + } + + private class InternalTimer : Timer + { + private readonly Wanderer m_Owner; + private int m_Count; + + public InternalTimer(Wanderer owner) : base(TimeSpan.FromSeconds(0.1), TimeSpan.FromSeconds(0.1)) => + m_Owner = owner; + + protected override void OnTick() + { + if ((m_Count++ & 0x3) == 0) m_Owner.Direction = (Direction)(Utility.Random(8) | 0x80); + + m_Owner.Move(m_Owner.Direction); + } + } } - - public Wanderer(Serial serial) : base(serial) - { - m_Timer = new InternalTimer(this); - m_Timer.Start(); - } - - public override void OnDelete() - { - m_Timer.Stop(); - - base.OnDelete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private class InternalTimer : Timer - { - private int m_Count; - private readonly Wanderer m_Owner; - - public InternalTimer(Wanderer owner) : base(TimeSpan.FromSeconds(0.1), TimeSpan.FromSeconds(0.1)) => m_Owner = owner; - - protected override void OnTick() - { - if ((m_Count++ & 0x3) == 0) m_Owner.Direction = (Direction)(Utility.Random(8) | 0x80); - - m_Owner.Move(m_Owner.Direction); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Townfolk/Actor.cs b/Projects/UOContent/Mobiles/Townfolk/Actor.cs index 12c42a5b0..60feea63f 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Actor.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Actor.cs @@ -2,64 +2,64 @@ using Server.Items; namespace Server.Mobiles { - public class Actor : BaseCreature - { - [Constructible] - public Actor() : base(AIType.AI_Animal, FightMode.None, 10, 1, 0.2, 0.4) + public class Actor : BaseCreature { - InitStats(31, 41, 51); + [Constructible] + public Actor() : base(AIType.AI_Animal, FightMode.None, 10, 1, 0.2, 0.4) + { + InitStats(31, 41, 51); - SpeechHue = Utility.RandomDyedHue(); + SpeechHue = Utility.RandomDyedHue(); - Hue = Race.Human.RandomSkinHue(); + Hue = Race.Human.RandomSkinHue(); - if (Female = Utility.RandomBool()) - { - Body = 0x191; - Name = NameList.RandomName("female"); - AddItem(new FancyDress(Utility.RandomDyedHue())); - Title = "the actress"; - } - else - { - Body = 0x190; - Name = NameList.RandomName("male"); - AddItem(new LongPants(Utility.RandomNeutralHue())); - AddItem(new FancyShirt(Utility.RandomDyedHue())); - Title = "the actor"; - } + if (Female = Utility.RandomBool()) + { + Body = 0x191; + Name = NameList.RandomName("female"); + AddItem(new FancyDress(Utility.RandomDyedHue())); + Title = "the actress"; + } + else + { + Body = 0x190; + Name = NameList.RandomName("male"); + AddItem(new LongPants(Utility.RandomNeutralHue())); + AddItem(new FancyShirt(Utility.RandomDyedHue())); + Title = "the actor"; + } - AddItem(new Boots(Utility.RandomNeutralHue())); + AddItem(new Boots(Utility.RandomNeutralHue())); - Utility.AssignRandomHair(this); + Utility.AssignRandomHair(this); - Container pack = new Backpack(); + Container pack = new Backpack(); - pack.DropItem(new Gold(250, 300)); + pack.DropItem(new Gold(250, 300)); - pack.Movable = false; + pack.Movable = false; - AddItem(pack); + AddItem(pack); + } + + public Actor(Serial serial) : base(serial) + { + } + + public override bool ClickTitle => 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 Actor(Serial serial) : base(serial) - { - } - - public override bool ClickTitle => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Townfolk/Artist.cs b/Projects/UOContent/Mobiles/Townfolk/Artist.cs index 1dd773435..2945fa96b 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Artist.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Artist.cs @@ -2,68 +2,68 @@ using Server.Items; namespace Server.Mobiles { - public class Artist : BaseCreature - { - [Constructible] - public Artist() - : base(AIType.AI_Animal, FightMode.None, 10, 1, 0.2, 0.4) + public class Artist : BaseCreature { - InitStats(31, 41, 51); + [Constructible] + public Artist() + : base(AIType.AI_Animal, FightMode.None, 10, 1, 0.2, 0.4) + { + InitStats(31, 41, 51); - SetSkill(SkillName.Healing, 36, 68); + SetSkill(SkillName.Healing, 36, 68); - SpeechHue = Utility.RandomDyedHue(); - Title = "the artist"; - Hue = Race.Human.RandomSkinHue(); + SpeechHue = Utility.RandomDyedHue(); + Title = "the artist"; + Hue = Race.Human.RandomSkinHue(); - if (Female = Utility.RandomBool()) - { - Body = 0x191; - Name = NameList.RandomName("female"); - } - else - { - Body = 0x190; - Name = NameList.RandomName("male"); - } + if (Female = Utility.RandomBool()) + { + Body = 0x191; + Name = NameList.RandomName("female"); + } + else + { + Body = 0x190; + Name = NameList.RandomName("male"); + } - AddItem(new Doublet(Utility.RandomDyedHue())); - AddItem(new Sandals(Utility.RandomNeutralHue())); - AddItem(new ShortPants(Utility.RandomNeutralHue())); - AddItem(new HalfApron(Utility.RandomDyedHue())); + AddItem(new Doublet(Utility.RandomDyedHue())); + AddItem(new Sandals(Utility.RandomNeutralHue())); + AddItem(new ShortPants(Utility.RandomNeutralHue())); + AddItem(new HalfApron(Utility.RandomDyedHue())); - Utility.AssignRandomHair(this); + Utility.AssignRandomHair(this); - Container pack = new Backpack(); + Container pack = new Backpack(); - pack.DropItem(new Gold(250, 300)); + pack.DropItem(new Gold(250, 300)); - pack.Movable = false; + pack.Movable = false; - AddItem(pack); + AddItem(pack); + } + + public Artist(Serial serial) + : base(serial) + { + } + + public override bool CanTeach => true; + + public override bool ClickTitle => 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 Artist(Serial serial) - : base(serial) - { - } - - public override bool CanTeach => true; - - public override bool ClickTitle => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Townfolk/Banker.cs b/Projects/UOContent/Mobiles/Townfolk/Banker.cs index 172c3fa3d..21224554d 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Banker.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Banker.cs @@ -8,422 +8,430 @@ using Server.Network; namespace Server.Mobiles { - public class Banker : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Banker() : base("the banker") + public class Banker : BaseVendor { - } + private readonly List m_SBInfos = new List(); - public Banker(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override NpcGuild NpcGuild => NpcGuild.MerchantsGuild; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBBanker()); - } - - public static int GetBalance(Mobile m) - { - long balance = 0; - - if (AccountGold.Enabled && m.Account != null) - { - balance = m.Account.GetTotalGold(); - if (balance >= int.MaxValue) return int.MaxValue; - } - - Container bank = m.FindBankNoCreate(); - - if (bank != null) - { - List gold = bank.FindItemsByType(); - List checks = bank.FindItemsByType(); - - balance += gold.Aggregate(0L, (c, t) => c + t.Amount); - if (balance >= int.MaxValue) - return int.MaxValue; - balance += checks.Aggregate(0L, (c, t) => c + t.Worth); - } - - return Math.Max(0, (int)Math.Min(int.MaxValue, balance)); - } - - public static int GetBalance(Mobile m, out Item[] gold, out Item[] checks) - { - long balance = 0; - - if (AccountGold.Enabled && m.Account != null) - { - balance = m.Account.GetTotalGold(); - - if (balance > int.MaxValue) + [Constructible] + public Banker() : base("the banker") { - gold = checks = Array.Empty(); - return int.MaxValue; - } - } - - Container bank = m.FindBankNoCreate(); - - if (bank != null) - { - gold = bank.FindItemsByType(typeof(Gold)); - checks = bank.FindItemsByType(typeof(BankCheck)); - - balance += gold.OfType().Aggregate(0L, (c, t) => c + t.Amount); - if (balance >= int.MaxValue) return int.MaxValue; - balance += checks.OfType().Aggregate(0L, (c, t) => c + t.Worth); - } - else - { - gold = checks = Array.Empty(); - } - - return Math.Max(0, (int)Math.Min(int.MaxValue, balance)); - } - - public static bool Withdraw(Mobile from, int amount) - { - // If for whatever reason the TOL checks fail, we should still try old methods for withdrawing currency. - if (AccountGold.Enabled && from.Account?.WithdrawGold(amount) == true) return true; - - int balance = GetBalance(from, out Item[] gold, out Item[] checks); - - if (balance < amount) return false; - - for (int i = 0; amount > 0 && i < gold.Length; ++i) - if (gold[i].Amount <= amount) - { - amount -= gold[i].Amount; - gold[i].Delete(); - } - else - { - gold[i].Amount -= amount; - amount = 0; } - for (int i = 0; amount > 0 && i < checks.Length; ++i) - { - BankCheck check = (BankCheck)checks[i]; - - if (check.Worth <= amount) + public Banker(Serial serial) : base(serial) { - amount -= check.Worth; - check.Delete(); - } - else - { - check.Worth -= amount; - amount = 0; - } - } - - return true; - } - - public static bool Deposit(Mobile from, int amount) - { - // If for whatever reason the TOL checks fail, we should still try old methods for depositing currency. - if (AccountGold.Enabled && from.Account?.DepositGold(amount) == true) return true; - - BankBox box = from.FindBankNoCreate(); - - if (box == null) return false; - - List items = new List(); - - while (amount > 0) - { - Item item; - if (amount < 5000) - { - item = new Gold(amount); - amount = 0; - } - else if (amount <= 1000000) - { - item = new BankCheck(amount); - amount = 0; - } - else - { - item = new BankCheck(1000000); - amount -= 1000000; } - if (box.TryDropItem(from, item, false)) + protected override List SBInfos => m_SBInfos; + + public override NpcGuild NpcGuild => NpcGuild.MerchantsGuild; + + public override void InitSBInfo() { - items.Add(item); - } - else - { - item.Delete(); - foreach (Item curItem in items) curItem.Delete(); - - return false; - } - } - - return true; - } - - public static int DepositUpTo(Mobile from, int amount) - { - // If for whatever reason the TOL checks fail, we should still try old methods for depositing currency. - if (AccountGold.Enabled && from.Account?.DepositGold(amount) == true) return amount; - - BankBox box = from.FindBankNoCreate(); - - if (box == null) return 0; - - int amountLeft = amount; - while (amountLeft > 0) - { - Item item; - int amountGiven; - - if (amountLeft < 5000) - { - item = new Gold(amountLeft); - amountGiven = amountLeft; - } - else if (amountLeft <= 1000000) - { - item = new BankCheck(amountLeft); - amountGiven = amountLeft; - } - else - { - item = new BankCheck(1000000); - amountGiven = 1000000; + m_SBInfos.Add(new SBBanker()); } - if (box.TryDropItem(from, item, false)) + public static int GetBalance(Mobile m) { - amountLeft -= amountGiven; - } - else - { - item.Delete(); - break; - } - } + long balance = 0; - return amount - amountLeft; - } + if (AccountGold.Enabled && m.Account != null) + { + balance = m.Account.GetTotalGold(); + if (balance >= int.MaxValue) return int.MaxValue; + } - public static void Deposit(Container cont, int amount) - { - while (amount > 0) - { - Item item; + Container bank = m.FindBankNoCreate(); - if (amount < 5000) - { - item = new Gold(amount); - amount = 0; - } - else if (amount <= 1000000) - { - item = new BankCheck(amount); - amount = 0; - } - else - { - item = new BankCheck(1000000); - amount -= 1000000; + if (bank != null) + { + var gold = bank.FindItemsByType(); + var checks = bank.FindItemsByType(); + + balance += gold.Aggregate(0L, (c, t) => c + t.Amount); + if (balance >= int.MaxValue) + return int.MaxValue; + balance += checks.Aggregate(0L, (c, t) => c + t.Worth); + } + + return Math.Max(0, (int)Math.Min(int.MaxValue, balance)); } - cont.DropItem(item); - } - } - - public override bool HandlesOnSpeech(Mobile from) - { - if (from.InRange(Location, 12)) - return true; - - return base.HandlesOnSpeech(from); - } - - public override void OnSpeech(SpeechEventArgs e) - { - if (!e.Handled && e.Mobile.InRange(Location, 12)) - for (int i = 0; i < e.Keywords.Length; ++i) + public static int GetBalance(Mobile m, out Item[] gold, out Item[] checks) { - int keyword = e.Keywords[i]; + long balance = 0; - switch (keyword) - { - case 0x0000: // *withdraw* - { - e.Handled = true; + if (AccountGold.Enabled && m.Account != null) + { + balance = m.Account.GetTotalGold(); - if (e.Mobile.Criminal) + if (balance > int.MaxValue) { - Say(500389); // I will not do business with a criminal! - break; + gold = checks = Array.Empty(); + return int.MaxValue; } + } - string[] split = e.Speech.Split(' '); + Container bank = m.FindBankNoCreate(); - if (split.Length >= 2) + if (bank != null) + { + gold = bank.FindItemsByType(typeof(Gold)); + checks = bank.FindItemsByType(typeof(BankCheck)); + + balance += gold.OfType().Aggregate(0L, (c, t) => c + t.Amount); + if (balance >= int.MaxValue) return int.MaxValue; + balance += checks.OfType().Aggregate(0L, (c, t) => c + t.Worth); + } + else + { + gold = checks = Array.Empty(); + } + + return Math.Max(0, (int)Math.Min(int.MaxValue, balance)); + } + + public static bool Withdraw(Mobile from, int amount) + { + // If for whatever reason the TOL checks fail, we should still try old methods for withdrawing currency. + if (AccountGold.Enabled && from.Account?.WithdrawGold(amount) == true) return true; + + var balance = GetBalance(from, out var gold, out var checks); + + if (balance < amount) return false; + + for (var i = 0; amount > 0 && i < gold.Length; ++i) + if (gold[i].Amount <= amount) { - Container pack = e.Mobile.Backpack; - - if (!int.TryParse(split[1], out int amount)) - break; - - if ((!Core.ML && amount > 5000) || (Core.ML && amount > 60000)) - { - Say(500381); // Thou canst not withdraw so much at one time! - } - else if (pack?.Deleted != false || !(pack.TotalWeight < pack.MaxWeight) || - !(pack.TotalItems < pack.MaxItems)) - { - Say(1048147); // Your backpack can't hold anything else. - } - else if (amount > 0) - { - BankBox box = e.Mobile.FindBankNoCreate(); - - if (box == null || !Withdraw(e.Mobile, amount)) - { - Say(500384); // Ah, art thou trying to fool me? Thou hast not so much gold! - } - else - { - pack.DropItem(new Gold(amount)); - - Say(1010005); // Thou hast withdrawn gold from thy account. - } - } + amount -= gold[i].Amount; + gold[i].Delete(); } - - break; - } - case 0x0001: // *balance* - { - e.Handled = true; - - if (e.Mobile.Criminal) - { - Say(500389); // I will not do business with a criminal! - break; - } - - if (AccountGold.Enabled && e.Mobile.Account != null) - Say(1155855, - $"{e.Mobile.Account.TotalPlat:#,0}\t{e.Mobile.Account.TotalGold:#,0}"); // Thy current bank balance is ~1_AMOUNT~ platinum and ~2_AMOUNT~ gold. else - Say(1042759, - GetBalance(e.Mobile).ToString("#,0")); // Thy current bank balance is ~1_AMOUNT~ gold. - - break; - } - case 0x0002: // *bank* - { - e.Handled = true; - - if (e.Mobile.Criminal) { - Say(500378); // Thou art a criminal and cannot access thy bank box. - break; + gold[i].Amount -= amount; + amount = 0; } - e.Mobile.BankBox.Open(); + for (var i = 0; amount > 0 && i < checks.Length; ++i) + { + var check = (BankCheck)checks[i]; - break; - } - case 0x0003: // *check* - { - e.Handled = true; - - if (AccountGold.Enabled) - break; - - if (e.Mobile.Criminal) + if (check.Worth <= amount) { - Say(500389); // I will not do business with a criminal! - break; + amount -= check.Worth; + check.Delete(); } - - string[] split = e.Speech.Split(' '); - - if (split.Length >= 2) + else { - if (!int.TryParse(split[1], out int amount)) - break; - - if (amount < 5000) - { - Say(1010006); // We cannot create checks for such a paltry amount of gold! - } - else if (amount > 1000000) - { - Say(1010007); // Our policies prevent us from creating checks worth that much! - } - else - { - BankCheck check = new BankCheck(amount); - - BankBox box = e.Mobile.BankBox; - - if (!box.TryDropItem(e.Mobile, check, false)) - { - Say(500386); // There's not enough room in your bankbox for the check! - check.Delete(); - } - else if (!box.ConsumeTotal(typeof(Gold), amount)) - { - Say(500384); // Ah, art thou trying to fool me? Thou hast not so much gold! - check.Delete(); - } - else - { - Say(1042673, AffixType.Append, amount.ToString(), - ""); // Into your bank box I have placed a check in the amount of: - } - } + check.Worth -= amount; + amount = 0; } + } - break; - } - } + return true; } - base.OnSpeech(e); + public static bool Deposit(Mobile from, int amount) + { + // If for whatever reason the TOL checks fail, we should still try old methods for depositing currency. + if (AccountGold.Enabled && from.Account?.DepositGold(amount) == true) return true; + + var box = from.FindBankNoCreate(); + + if (box == null) return false; + + var items = new List(); + + while (amount > 0) + { + Item item; + if (amount < 5000) + { + item = new Gold(amount); + amount = 0; + } + else if (amount <= 1000000) + { + item = new BankCheck(amount); + amount = 0; + } + else + { + item = new BankCheck(1000000); + amount -= 1000000; + } + + if (box.TryDropItem(from, item, false)) + { + items.Add(item); + } + else + { + item.Delete(); + foreach (var curItem in items) curItem.Delete(); + + return false; + } + } + + return true; + } + + public static int DepositUpTo(Mobile from, int amount) + { + // If for whatever reason the TOL checks fail, we should still try old methods for depositing currency. + if (AccountGold.Enabled && from.Account?.DepositGold(amount) == true) return amount; + + var box = from.FindBankNoCreate(); + + if (box == null) return 0; + + var amountLeft = amount; + while (amountLeft > 0) + { + Item item; + int amountGiven; + + if (amountLeft < 5000) + { + item = new Gold(amountLeft); + amountGiven = amountLeft; + } + else if (amountLeft <= 1000000) + { + item = new BankCheck(amountLeft); + amountGiven = amountLeft; + } + else + { + item = new BankCheck(1000000); + amountGiven = 1000000; + } + + if (box.TryDropItem(from, item, false)) + { + amountLeft -= amountGiven; + } + else + { + item.Delete(); + break; + } + } + + return amount - amountLeft; + } + + public static void Deposit(Container cont, int amount) + { + while (amount > 0) + { + Item item; + + if (amount < 5000) + { + item = new Gold(amount); + amount = 0; + } + else if (amount <= 1000000) + { + item = new BankCheck(amount); + amount = 0; + } + else + { + item = new BankCheck(1000000); + amount -= 1000000; + } + + cont.DropItem(item); + } + } + + public override bool HandlesOnSpeech(Mobile from) + { + if (from.InRange(Location, 12)) + return true; + + return base.HandlesOnSpeech(from); + } + + public override void OnSpeech(SpeechEventArgs e) + { + if (!e.Handled && e.Mobile.InRange(Location, 12)) + for (var i = 0; i < e.Keywords.Length; ++i) + { + var keyword = e.Keywords[i]; + + switch (keyword) + { + case 0x0000: // *withdraw* + { + e.Handled = true; + + if (e.Mobile.Criminal) + { + Say(500389); // I will not do business with a criminal! + break; + } + + var split = e.Speech.Split(' '); + + if (split.Length >= 2) + { + var pack = e.Mobile.Backpack; + + if (!int.TryParse(split[1], out var amount)) + break; + + if (!Core.ML && amount > 5000 || Core.ML && amount > 60000) + { + Say(500381); // Thou canst not withdraw so much at one time! + } + else if (pack?.Deleted != false || !(pack.TotalWeight < pack.MaxWeight) || + !(pack.TotalItems < pack.MaxItems)) + { + Say(1048147); // Your backpack can't hold anything else. + } + else if (amount > 0) + { + var box = e.Mobile.FindBankNoCreate(); + + if (box == null || !Withdraw(e.Mobile, amount)) + { + Say(500384); // Ah, art thou trying to fool me? Thou hast not so much gold! + } + else + { + pack.DropItem(new Gold(amount)); + + Say(1010005); // Thou hast withdrawn gold from thy account. + } + } + } + + break; + } + case 0x0001: // *balance* + { + e.Handled = true; + + if (e.Mobile.Criminal) + { + Say(500389); // I will not do business with a criminal! + break; + } + + if (AccountGold.Enabled && e.Mobile.Account != null) + Say( + 1155855, + $"{e.Mobile.Account.TotalPlat:#,0}\t{e.Mobile.Account.TotalGold:#,0}" + ); // Thy current bank balance is ~1_AMOUNT~ platinum and ~2_AMOUNT~ gold. + else + Say( + 1042759, + GetBalance(e.Mobile).ToString("#,0") + ); // Thy current bank balance is ~1_AMOUNT~ gold. + + break; + } + case 0x0002: // *bank* + { + e.Handled = true; + + if (e.Mobile.Criminal) + { + Say(500378); // Thou art a criminal and cannot access thy bank box. + break; + } + + e.Mobile.BankBox.Open(); + + break; + } + case 0x0003: // *check* + { + e.Handled = true; + + if (AccountGold.Enabled) + break; + + if (e.Mobile.Criminal) + { + Say(500389); // I will not do business with a criminal! + break; + } + + var split = e.Speech.Split(' '); + + if (split.Length >= 2) + { + if (!int.TryParse(split[1], out var amount)) + break; + + if (amount < 5000) + { + Say(1010006); // We cannot create checks for such a paltry amount of gold! + } + else if (amount > 1000000) + { + Say(1010007); // Our policies prevent us from creating checks worth that much! + } + else + { + var check = new BankCheck(amount); + + var box = e.Mobile.BankBox; + + if (!box.TryDropItem(e.Mobile, check, false)) + { + Say(500386); // There's not enough room in your bankbox for the check! + check.Delete(); + } + else if (!box.ConsumeTotal(typeof(Gold), amount)) + { + Say(500384); // Ah, art thou trying to fool me? Thou hast not so much gold! + check.Delete(); + } + else + { + Say( + 1042673, + AffixType.Append, + amount.ToString(), + "" + ); // Into your bank box I have placed a check in the amount of: + } + } + } + + break; + } + } + } + + base.OnSpeech(e); + } + + public override void AddCustomContextEntries(Mobile from, List list) + { + if (from.Alive) + list.Add(new OpenBankEntry(from, this)); + + base.AddCustomContextEntries(from, list); + } + + 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 AddCustomContextEntries(Mobile from, List list) - { - if (from.Alive) - list.Add(new OpenBankEntry(from, this)); - - base.AddCustomContextEntries(from, list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Townfolk/BaseEscortable.cs b/Projects/UOContent/Mobiles/Townfolk/BaseEscortable.cs index f5dadcc24..e67521399 100644 --- a/Projects/UOContent/Mobiles/Townfolk/BaseEscortable.cs +++ b/Projects/UOContent/Mobiles/Townfolk/BaseEscortable.cs @@ -12,716 +12,731 @@ using EDI = Server.Mobiles.EscortDestinationInfo; namespace Server.Mobiles { - public class BaseEscortable : BaseCreature - { - public static readonly TimeSpan EscortDelay = TimeSpan.FromMinutes(5.0); - - public static readonly TimeSpan AbandonDelay = - MLQuestSystem.Enabled ? TimeSpan.FromMinutes(1.0) : TimeSpan.FromMinutes(2.0); - - public static readonly TimeSpan DeleteTime = - MLQuestSystem.Enabled ? TimeSpan.FromSeconds(100) : TimeSpan.FromSeconds(30); - - // Classic list - // Used when: !MLQuestSystem.Enabled && !Core.ML - private static readonly string[] m_TownNames = + public class BaseEscortable : BaseCreature { - "Cove", "Britain", "Jhelom", - "Minoc", "Ocllo", "Trinsic", - "Vesper", "Yew", "Skara Brae", - "Nujel'm", "Moonglow", "Magincia" - }; + public static readonly TimeSpan EscortDelay = TimeSpan.FromMinutes(5.0); - // ML list, pre-ML quest system - // Used when: !MLQuestSystem.Enabled && Core.ML - private static readonly string[] m_MLTownNames = - { - "Cove", "Serpent's Hold", "Jhelom", - "Nujel'm" - }; + public static readonly TimeSpan AbandonDelay = + MLQuestSystem.Enabled ? TimeSpan.FromMinutes(1.0) : TimeSpan.FromMinutes(2.0); - // ML quest system general list - // Used when: MLQuestSystem.Enabled && !Region.IsPartOf( "Haven Island" ) - private static readonly Type[] m_MLQuestTypes = - { - typeof(EscortToYew), - typeof(EscortToVesper), - typeof(EscortToTrinsic), - typeof(EscortToSkaraBrae), - typeof(EscortToSerpentsHold), - typeof(EscortToNujelm), - typeof(EscortToMoonglow), - typeof(EscortToMinoc), - typeof(EscortToMagincia), - typeof(EscortToJhelom), - typeof(EscortToCove), - typeof(EscortToBritain) - // Ocllo was removed in pub 56 - // typeof( EscortToOcllo ) - }; + public static readonly TimeSpan DeleteTime = + MLQuestSystem.Enabled ? TimeSpan.FromSeconds(100) : TimeSpan.FromSeconds(30); - // ML quest system New Haven list - // Used when: MLQuestSystem.Enabled && Region.IsPartOf( "Haven Island" ) - private static readonly Type[] m_MLQuestTypesNH = - { - typeof(EscortToNHAlchemist), - typeof(EscortToNHBard), - typeof(EscortToNHWarrior), - typeof(EscortToNHTailor), - typeof(EscortToNHCarpenter), - typeof(EscortToNHMapmaker), - typeof(EscortToNHMage), - typeof(EscortToNHInn), - // Farm destination was removed - // typeof( EscortToNHFarm ), - typeof(EscortToNHDocks), - typeof(EscortToNHBowyer), - typeof(EscortToNHBank) - }; - - private bool m_DeleteCorpse; - - private DateTime m_DeleteTime; - private Timer m_DeleteTimer; - - private EDI m_Destination; - private string m_DestinationString; - - private DateTime m_LastSeenEscorter; - - private MLQuest m_MLQuest; - - [Constructible] - public BaseEscortable() - : base(AIType.AI_Melee, FightMode.Aggressor, 22, 1, 0.2, 1.0) - { - InitBody(); - InitOutfit(); - - Fame = 200; - Karma = 4000; - } - - public BaseEscortable(Serial serial) - : base(serial) - { - } - - public override bool StaticMLQuester => false; // Suppress automatic quest registration on creation/deserialization - - public override bool CanShout => !Controlled && !IsBeingDeleted; - - public bool IsBeingDeleted => m_DeleteTimer != null; - - public override bool Commandable => false; // Our master cannot boss us around! - public override bool DeleteCorpseOnDeath => m_DeleteCorpse; - - [CommandProperty(AccessLevel.GameMaster)] - public string Destination - { - get => m_Destination?.Name; - set - { - m_DestinationString = value; - m_Destination = EDI.Find(value); - } - } - - public static Dictionary EscortTable { get; } = new Dictionary(); - - protected override List ConstructQuestList() - { - if (m_MLQuest == null) - { - Region reg = Region; - Type[] list = reg.IsPartOf("Haven Island") ? m_MLQuestTypesNH : m_MLQuestTypes; - - int randomIdx = Utility.Random(list.Length); - - for (int i = 0; i < list.Length; ++i) + // Classic list + // Used when: !MLQuestSystem.Enabled && !Core.ML + private static readonly string[] m_TownNames = { - Type questType = list[randomIdx]; + "Cove", "Britain", "Jhelom", + "Minoc", "Ocllo", "Trinsic", + "Vesper", "Yew", "Skara Brae", + "Nujel'm", "Moonglow", "Magincia" + }; - MLQuest quest = MLQuestSystem.FindQuest(questType); + // ML list, pre-ML quest system + // Used when: !MLQuestSystem.Enabled && Core.ML + private static readonly string[] m_MLTownNames = + { + "Cove", "Serpent's Hold", "Jhelom", + "Nujel'm" + }; - if (quest != null) - { - bool okay = true; + // ML quest system general list + // Used when: MLQuestSystem.Enabled && !Region.IsPartOf( "Haven Island" ) + private static readonly Type[] m_MLQuestTypes = + { + typeof(EscortToYew), + typeof(EscortToVesper), + typeof(EscortToTrinsic), + typeof(EscortToSkaraBrae), + typeof(EscortToSerpentsHold), + typeof(EscortToNujelm), + typeof(EscortToMoonglow), + typeof(EscortToMinoc), + typeof(EscortToMagincia), + typeof(EscortToJhelom), + typeof(EscortToCove), + typeof(EscortToBritain) + // Ocllo was removed in pub 56 + // typeof( EscortToOcllo ) + }; - foreach (BaseObjective obj in quest.Objectives) - if (obj is EscortObjective objective && objective.Destination.Contains(reg)) - { - okay = false; // We're already there! - break; - } + // ML quest system New Haven list + // Used when: MLQuestSystem.Enabled && Region.IsPartOf( "Haven Island" ) + private static readonly Type[] m_MLQuestTypesNH = + { + typeof(EscortToNHAlchemist), + typeof(EscortToNHBard), + typeof(EscortToNHWarrior), + typeof(EscortToNHTailor), + typeof(EscortToNHCarpenter), + typeof(EscortToNHMapmaker), + typeof(EscortToNHMage), + typeof(EscortToNHInn), + // Farm destination was removed + // typeof( EscortToNHFarm ), + typeof(EscortToNHDocks), + typeof(EscortToNHBowyer), + typeof(EscortToNHBank) + }; - if (okay) + private bool m_DeleteCorpse; + + private DateTime m_DeleteTime; + private Timer m_DeleteTimer; + + private EDI m_Destination; + private string m_DestinationString; + + private DateTime m_LastSeenEscorter; + + private MLQuest m_MLQuest; + + [Constructible] + public BaseEscortable() + : base(AIType.AI_Melee, FightMode.Aggressor, 22, 1, 0.2, 1.0) + { + InitBody(); + InitOutfit(); + + Fame = 200; + Karma = 4000; + } + + public BaseEscortable(Serial serial) + : base(serial) + { + } + + public override bool StaticMLQuester => false; // Suppress automatic quest registration on creation/deserialization + + public override bool CanShout => !Controlled && !IsBeingDeleted; + + public bool IsBeingDeleted => m_DeleteTimer != null; + + public override bool Commandable => false; // Our master cannot boss us around! + public override bool DeleteCorpseOnDeath => m_DeleteCorpse; + + [CommandProperty(AccessLevel.GameMaster)] + public string Destination + { + get => m_Destination?.Name; + set { - m_MLQuest = quest; - break; + m_DestinationString = value; + m_Destination = EDI.Find(value); } - } - else if (MLQuestSystem.Debug) - { - Console.WriteLine("Warning: Escortable cannot be assigned quest type '{0}', it is not registered", - questType.Name); - } - - randomIdx = (randomIdx + 1) % list.Length; } - if (m_MLQuest == null) + public static Dictionary EscortTable { get; } = new Dictionary(); + + protected override List ConstructQuestList() { - if (MLQuestSystem.Debug) - Console.WriteLine("Warning: No suitable quest found for escort {0}", Serial); + if (m_MLQuest == null) + { + var reg = Region; + var list = reg.IsPartOf("Haven Island") ? m_MLQuestTypesNH : m_MLQuestTypes; - return null; - } - } + var randomIdx = Utility.Random(list.Length); - List result = new List { m_MLQuest }; + for (var i = 0; i < list.Length; ++i) + { + var questType = list[randomIdx]; - return result; - } + var quest = MLQuestSystem.FindQuest(questType); - public override void Shout(PlayerMobile pm) - { - /* - * 1072301 - You there! Care to hear how to earn some easy gold? - * 1072302 - Adventurer! I have an offer for you. - * 1072303 - Wait! I have an opportunity for you to make some gold! - */ - MLQuestSystem.Tell(this, pm, Utility.Random(1072301, 3)); - } + if (quest != null) + { + var okay = true; - public virtual void InitBody() - { - SetStr(90, 100); - SetDex(90, 100); - SetInt(15, 25); + foreach (var obj in quest.Objectives) + if (obj is EscortObjective objective && objective.Destination.Contains(reg)) + { + okay = false; // We're already there! + break; + } - Hue = Race.Human.RandomSkinHue(); + if (okay) + { + m_MLQuest = quest; + break; + } + } + else if (MLQuestSystem.Debug) + { + Console.WriteLine( + "Warning: Escortable cannot be assigned quest type '{0}', it is not registered", + questType.Name + ); + } - if (Female = Utility.RandomBool()) - { - Body = 401; - Name = NameList.RandomName("female"); - } - else - { - Body = 400; - Name = NameList.RandomName("male"); - } - } + randomIdx = (randomIdx + 1) % list.Length; + } - public virtual void InitOutfit() - { - AddItem(new FancyShirt(Utility.RandomNeutralHue())); - AddItem(new ShortPants(Utility.RandomNeutralHue())); - AddItem(new Boots(Utility.RandomNeutralHue())); + if (m_MLQuest == null) + { + if (MLQuestSystem.Debug) + Console.WriteLine("Warning: No suitable quest found for escort {0}", Serial); - Utility.AssignRandomHair(this); + return null; + } + } - PackGold(200, 250); - } + var result = new List { m_MLQuest }; - public virtual bool SayDestinationTo(Mobile m) - { - EDI dest = GetDestination(); - - if (dest == null || !m.Alive) - return false; - - Mobile escorter = GetEscorter(); - - if (escorter == null) - { - Say("I am looking to go to {0}, will you take me?", - dest.Name == "Ocllo" && m.Map == Map.Trammel ? "Haven" : dest.Name); - return true; - } - - if (escorter == m) - { - Say("Lead on! Payment will be made when we arrive in {0}.", - dest.Name == "Ocllo" && m.Map == Map.Trammel ? "Haven" : dest.Name); - return true; - } - - return false; - } - - public virtual bool AcceptEscorter(Mobile m) - { - EDI dest = GetDestination(); - - if (dest == null) - return false; - - if (GetEscorter() != null || !m.Alive) - return false; - - if (EscortTable.TryGetValue(m, out BaseEscortable escortable) && escortable?.Deleted == false && escortable.GetEscorter() == m) - { - Say("I see you already have an escort."); - return false; - } - - if (m is PlayerMobile mobile && mobile.LastEscortTime + EscortDelay >= DateTime.UtcNow) - { - int minutes = - (int)Math.Ceiling((mobile.LastEscortTime + EscortDelay - DateTime.UtcNow).TotalMinutes); - - Say("You must rest {0} minute{1} before we set out on this journey.", minutes, minutes == 1 ? "" : "s"); - return false; - } - - if (SetControlMaster(m)) - { - m_LastSeenEscorter = DateTime.UtcNow; - - if (m is PlayerMobile playerMobile) - playerMobile.LastEscortTime = DateTime.UtcNow; - - Say("Lead on! Payment will be made when we arrive in {0}.", - dest.Name == "Ocllo" && m.Map == Map.Trammel ? "Haven" : dest.Name); - EscortTable[m] = this; - StartFollow(); - return true; - } - - return false; - } - - public override bool HandlesOnSpeech(Mobile from) => !MLQuestSystem.Enabled && (from.InRange(Location, 3) || base.HandlesOnSpeech(from)); - - public override void OnSpeech(SpeechEventArgs e) - { - base.OnSpeech(e); - - if (GetDestination() == null || e.Handled || !e.Mobile.InRange(Location, 3)) - return; - - if (e.HasKeyword(0x1D)) // *destination* - e.Handled = SayDestinationTo(e.Mobile); - else if (e.HasKeyword(0x1E)) // *i will take thee* - e.Handled = AcceptEscorter(e.Mobile); - } - - public override void OnAfterDelete() - { - m_DeleteTimer?.Stop(); - - m_DeleteTimer = null; - - base.OnAfterDelete(); - } - - public override void OnThink() - { - base.OnThink(); - CheckAtDestination(); - } - - protected override bool OnMove(Direction d) - { - if (!base.OnMove(d)) - return false; - - CheckAtDestination(); - - return true; - } - - // TODO: Pre-ML methods below, might be mergeable with the ML methods in EscortObjective - - public virtual void StartFollow() - { - StartFollow(GetEscorter()); - } - - public virtual void StartFollow(Mobile escorter) - { - if (escorter == null) - return; - - ActiveSpeed = 0.1; - PassiveSpeed = 0.2; - - ControlOrder = OrderType.Follow; - ControlTarget = escorter; - - if (IsPrisoner && CantWalk) CantWalk = false; - CurrentSpeed = 0.1; - } - - public virtual void StopFollow() - { - ActiveSpeed = 0.2; - PassiveSpeed = 1.0; - - ControlOrder = OrderType.None; - ControlTarget = null; - - CurrentSpeed = 1.0; - } - - public virtual Mobile GetEscorter() - { - if (!Controlled) - return null; - - Mobile master = ControlMaster; - - if (MLQuestSystem.Enabled || master == null) - return master; - - if (master.Deleted || master.Map != Map || !master.InRange(Location, 30) || !master.Alive) - { - StopFollow(); - - TimeSpan lastSeenDelay = DateTime.UtcNow - m_LastSeenEscorter; - - if (lastSeenDelay >= AbandonDelay) - { - master.SendLocalizedMessage(1042473); // You have lost the person you were escorting. - Say(1005653); // Hmmm. I seem to have lost my master. - - SetControlMaster(null); - EscortTable.Remove(master); - - Timer.DelayCall(TimeSpan.FromSeconds(5.0), Delete); - return null; + return result; } - ControlOrder = OrderType.Stay; - return master; - } - - if (ControlOrder != OrderType.Follow) - StartFollow(master); - - m_LastSeenEscorter = DateTime.UtcNow; - return master; - } - - public virtual void BeginDelete() - { - m_DeleteTimer?.Stop(); - - m_DeleteTime = DateTime.UtcNow + DeleteTime; - - m_DeleteTimer = new DeleteTimer(this, m_DeleteTime - DateTime.UtcNow); - m_DeleteTimer.Start(); - } - - public virtual bool CheckAtDestination() - { - if (MLQuestSystem.Enabled) - return false; - - EDI dest = GetDestination(); - - if (dest == null) - return false; - - Mobile escorter = GetEscorter(); - - if (escorter == null) - return false; - - if (dest.Contains(Location)) - { - Say(1042809, - escorter.Name); // We have arrived! I thank thee, ~1_PLAYER_NAME~! I have no further need of thy services. Here is thy pay. - - // not going anywhere - m_Destination = null; - m_DestinationString = null; - - Container cont = escorter.Backpack ?? escorter.BankBox; - - Gold gold = new Gold(500, 1000); - - if (!cont.TryDropItem(escorter, gold, false)) - gold.MoveToWorld(escorter.Location, escorter.Map); - - StopFollow(); - SetControlMaster(null); - EscortTable.Remove(escorter); - BeginDelete(); - - Titles.AwardFame(escorter, 10, true); - - bool gainedPath = false; - - if (escorter is PlayerMobile pm) + public override void Shout(PlayerMobile pm) { - if (pm.CompassionGains > 0 && DateTime.UtcNow > pm.NextCompassionDay) - { - pm.NextCompassionDay = DateTime.MinValue; - pm.CompassionGains = 0; - } + /* + * 1072301 - You there! Care to hear how to earn some easy gold? + * 1072302 - Adventurer! I have an offer for you. + * 1072303 - Wait! I have an opportunity for you to make some gold! + */ + MLQuestSystem.Tell(this, pm, Utility.Random(1072301, 3)); + } - if (pm.CompassionGains >= 5) // have already gained 5 times in one day, can gain no more - { - pm.SendLocalizedMessage( - 1053004); // You must wait about a day before you can gain in compassion again. - } - else if (VirtueHelper.Award(pm, VirtueName.Compassion, IsPrisoner ? 400 : 200, ref gainedPath)) - { - if (gainedPath) - pm.SendLocalizedMessage(1053005); // You have achieved a path in compassion! + public virtual void InitBody() + { + SetStr(90, 100); + SetDex(90, 100); + SetInt(15, 25); + + Hue = Race.Human.RandomSkinHue(); + + if (Female = Utility.RandomBool()) + { + Body = 401; + Name = NameList.RandomName("female"); + } else - pm.SendLocalizedMessage(1053002); // You have gained in compassion. - - pm.NextCompassionDay = - DateTime.UtcNow + TimeSpan.FromDays(1.0); // in one day CompassionGains gets reset to 0 - ++pm.CompassionGains; - - if (pm.CompassionGains >= 5) - pm.SendLocalizedMessage( - 1053004); // You must wait about a day before you can gain in compassion again. - } - else - { - pm.SendLocalizedMessage( - 1053003); // You have achieved the highest path of compassion and can no longer gain any further. - } + { + Body = 400; + Name = NameList.RandomName("male"); + } } - return true; - } - - return false; - } - - public override bool OnBeforeDeath() - { - m_DeleteCorpse = Controlled || IsBeingDeleted; - - return base.OnBeforeDeath(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - EDI dest = GetDestination(); - - writer.Write(dest != null); - - if (dest != null) - writer.Write(dest.Name); - - writer.Write(m_DeleteTimer != null); - - if (m_DeleteTimer != null) - writer.WriteDeltaTime(m_DeleteTime); - - MLQuestSystem.WriteQuestRef(writer, StaticMLQuester ? null : m_MLQuest); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (reader.ReadBool()) - m_DestinationString = - reader.ReadString(); // NOTE: We cannot EDI.Find here, regions have not yet been loaded :-( - - if (reader.ReadBool()) - { - m_DeleteTime = reader.ReadDeltaTime(); - m_DeleteTimer = new DeleteTimer(this, m_DeleteTime - DateTime.UtcNow); - m_DeleteTimer.Start(); - } - - if (version >= 1) - { - MLQuest quest = MLQuestSystem.ReadQuestRef(reader); - - if (MLQuestSystem.Enabled && quest != null && !StaticMLQuester) - m_MLQuest = quest; - } - } - - public override bool CanBeRenamedBy(Mobile from) => from.AccessLevel >= AccessLevel.GameMaster; - - public override void AddCustomContextEntries(Mobile from, List list) - { - if (from.Alive) - { - Mobile escorter = GetEscorter(); - - if (!MLQuestSystem.Enabled && GetDestination() != null) + public virtual void InitOutfit() { - if (escorter == null || escorter == from) - list.Add(new AskDestinationEntry(this, from)); + AddItem(new FancyShirt(Utility.RandomNeutralHue())); + AddItem(new ShortPants(Utility.RandomNeutralHue())); + AddItem(new Boots(Utility.RandomNeutralHue())); - if (escorter == null) - list.Add(new AcceptEscortEntry(this, from)); + Utility.AssignRandomHair(this); + + PackGold(200, 250); } - if (escorter == from) - list.Add(new AbandonEscortEntry(this)); - } + public virtual bool SayDestinationTo(Mobile m) + { + var dest = GetDestination(); - base.AddCustomContextEntries(from, list); + if (dest == null || !m.Alive) + return false; + + var escorter = GetEscorter(); + + if (escorter == null) + { + Say( + "I am looking to go to {0}, will you take me?", + dest.Name == "Ocllo" && m.Map == Map.Trammel ? "Haven" : dest.Name + ); + return true; + } + + if (escorter == m) + { + Say( + "Lead on! Payment will be made when we arrive in {0}.", + dest.Name == "Ocllo" && m.Map == Map.Trammel ? "Haven" : dest.Name + ); + return true; + } + + return false; + } + + public virtual bool AcceptEscorter(Mobile m) + { + var dest = GetDestination(); + + if (dest == null) + return false; + + if (GetEscorter() != null || !m.Alive) + return false; + + if (EscortTable.TryGetValue(m, out var escortable) && escortable?.Deleted == false && + escortable.GetEscorter() == m) + { + Say("I see you already have an escort."); + return false; + } + + if (m is PlayerMobile mobile && mobile.LastEscortTime + EscortDelay >= DateTime.UtcNow) + { + var minutes = + (int)Math.Ceiling((mobile.LastEscortTime + EscortDelay - DateTime.UtcNow).TotalMinutes); + + Say("You must rest {0} minute{1} before we set out on this journey.", minutes, minutes == 1 ? "" : "s"); + return false; + } + + if (SetControlMaster(m)) + { + m_LastSeenEscorter = DateTime.UtcNow; + + if (m is PlayerMobile playerMobile) + playerMobile.LastEscortTime = DateTime.UtcNow; + + Say( + "Lead on! Payment will be made when we arrive in {0}.", + dest.Name == "Ocllo" && m.Map == Map.Trammel ? "Haven" : dest.Name + ); + EscortTable[m] = this; + StartFollow(); + return true; + } + + return false; + } + + public override bool HandlesOnSpeech(Mobile from) => + !MLQuestSystem.Enabled && (from.InRange(Location, 3) || base.HandlesOnSpeech(from)); + + public override void OnSpeech(SpeechEventArgs e) + { + base.OnSpeech(e); + + if (GetDestination() == null || e.Handled || !e.Mobile.InRange(Location, 3)) + return; + + if (e.HasKeyword(0x1D)) // *destination* + e.Handled = SayDestinationTo(e.Mobile); + else if (e.HasKeyword(0x1E)) // *i will take thee* + e.Handled = AcceptEscorter(e.Mobile); + } + + public override void OnAfterDelete() + { + m_DeleteTimer?.Stop(); + + m_DeleteTimer = null; + + base.OnAfterDelete(); + } + + public override void OnThink() + { + base.OnThink(); + CheckAtDestination(); + } + + protected override bool OnMove(Direction d) + { + if (!base.OnMove(d)) + return false; + + CheckAtDestination(); + + return true; + } + + // TODO: Pre-ML methods below, might be mergeable with the ML methods in EscortObjective + + public virtual void StartFollow() + { + StartFollow(GetEscorter()); + } + + public virtual void StartFollow(Mobile escorter) + { + if (escorter == null) + return; + + ActiveSpeed = 0.1; + PassiveSpeed = 0.2; + + ControlOrder = OrderType.Follow; + ControlTarget = escorter; + + if (IsPrisoner && CantWalk) CantWalk = false; + CurrentSpeed = 0.1; + } + + public virtual void StopFollow() + { + ActiveSpeed = 0.2; + PassiveSpeed = 1.0; + + ControlOrder = OrderType.None; + ControlTarget = null; + + CurrentSpeed = 1.0; + } + + public virtual Mobile GetEscorter() + { + if (!Controlled) + return null; + + var master = ControlMaster; + + if (MLQuestSystem.Enabled || master == null) + return master; + + if (master.Deleted || master.Map != Map || !master.InRange(Location, 30) || !master.Alive) + { + StopFollow(); + + var lastSeenDelay = DateTime.UtcNow - m_LastSeenEscorter; + + if (lastSeenDelay >= AbandonDelay) + { + master.SendLocalizedMessage(1042473); // You have lost the person you were escorting. + Say(1005653); // Hmmm. I seem to have lost my master. + + SetControlMaster(null); + EscortTable.Remove(master); + + Timer.DelayCall(TimeSpan.FromSeconds(5.0), Delete); + return null; + } + + ControlOrder = OrderType.Stay; + return master; + } + + if (ControlOrder != OrderType.Follow) + StartFollow(master); + + m_LastSeenEscorter = DateTime.UtcNow; + return master; + } + + public virtual void BeginDelete() + { + m_DeleteTimer?.Stop(); + + m_DeleteTime = DateTime.UtcNow + DeleteTime; + + m_DeleteTimer = new DeleteTimer(this, m_DeleteTime - DateTime.UtcNow); + m_DeleteTimer.Start(); + } + + public virtual bool CheckAtDestination() + { + if (MLQuestSystem.Enabled) + return false; + + var dest = GetDestination(); + + if (dest == null) + return false; + + var escorter = GetEscorter(); + + if (escorter == null) + return false; + + if (dest.Contains(Location)) + { + Say( + 1042809, + escorter.Name + ); // We have arrived! I thank thee, ~1_PLAYER_NAME~! I have no further need of thy services. Here is thy pay. + + // not going anywhere + m_Destination = null; + m_DestinationString = null; + + var cont = escorter.Backpack ?? escorter.BankBox; + + var gold = new Gold(500, 1000); + + if (!cont.TryDropItem(escorter, gold, false)) + gold.MoveToWorld(escorter.Location, escorter.Map); + + StopFollow(); + SetControlMaster(null); + EscortTable.Remove(escorter); + BeginDelete(); + + Titles.AwardFame(escorter, 10, true); + + var gainedPath = false; + + if (escorter is PlayerMobile pm) + { + if (pm.CompassionGains > 0 && DateTime.UtcNow > pm.NextCompassionDay) + { + pm.NextCompassionDay = DateTime.MinValue; + pm.CompassionGains = 0; + } + + if (pm.CompassionGains >= 5) // have already gained 5 times in one day, can gain no more + { + pm.SendLocalizedMessage( + 1053004 + ); // You must wait about a day before you can gain in compassion again. + } + else if (VirtueHelper.Award(pm, VirtueName.Compassion, IsPrisoner ? 400 : 200, ref gainedPath)) + { + if (gainedPath) + pm.SendLocalizedMessage(1053005); // You have achieved a path in compassion! + else + pm.SendLocalizedMessage(1053002); // You have gained in compassion. + + pm.NextCompassionDay = + DateTime.UtcNow + TimeSpan.FromDays(1.0); // in one day CompassionGains gets reset to 0 + ++pm.CompassionGains; + + if (pm.CompassionGains >= 5) + pm.SendLocalizedMessage( + 1053004 + ); // You must wait about a day before you can gain in compassion again. + } + else + { + pm.SendLocalizedMessage( + 1053003 + ); // You have achieved the highest path of compassion and can no longer gain any further. + } + } + + return true; + } + + return false; + } + + public override bool OnBeforeDeath() + { + m_DeleteCorpse = Controlled || IsBeingDeleted; + + return base.OnBeforeDeath(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + var dest = GetDestination(); + + writer.Write(dest != null); + + if (dest != null) + writer.Write(dest.Name); + + writer.Write(m_DeleteTimer != null); + + if (m_DeleteTimer != null) + writer.WriteDeltaTime(m_DeleteTime); + + MLQuestSystem.WriteQuestRef(writer, StaticMLQuester ? null : m_MLQuest); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + if (reader.ReadBool()) + m_DestinationString = + reader.ReadString(); // NOTE: We cannot EDI.Find here, regions have not yet been loaded :-( + + if (reader.ReadBool()) + { + m_DeleteTime = reader.ReadDeltaTime(); + m_DeleteTimer = new DeleteTimer(this, m_DeleteTime - DateTime.UtcNow); + m_DeleteTimer.Start(); + } + + if (version >= 1) + { + var quest = MLQuestSystem.ReadQuestRef(reader); + + if (MLQuestSystem.Enabled && quest != null && !StaticMLQuester) + m_MLQuest = quest; + } + } + + public override bool CanBeRenamedBy(Mobile from) => from.AccessLevel >= AccessLevel.GameMaster; + + public override void AddCustomContextEntries(Mobile from, List list) + { + if (from.Alive) + { + var escorter = GetEscorter(); + + if (!MLQuestSystem.Enabled && GetDestination() != null) + { + if (escorter == null || escorter == from) + list.Add(new AskDestinationEntry(this, from)); + + if (escorter == null) + list.Add(new AcceptEscortEntry(this, from)); + } + + if (escorter == from) + list.Add(new AbandonEscortEntry(this)); + } + + base.AddCustomContextEntries(from, list); + } + + public virtual string[] GetPossibleDestinations() => Core.ML ? m_MLTownNames : m_TownNames; + + public virtual string PickRandomDestination() + { + if (Map.Felucca.Regions.Count == 0 || Map == null || Map == Map.Internal || Location == Point3D.Zero) + return null; // Not yet fully initialized + + var possible = GetPossibleDestinations(); + string picked = null; + + while (picked == null) + { + picked = possible.RandomElement(); + var test = EDI.Find(picked); + + if (test.Contains(Location)) + picked = null; + } + + return picked; + } + + public EDI GetDestination() + { + if (MLQuestSystem.Enabled) + return null; + + if (m_DestinationString == null && m_DeleteTimer == null) + m_DestinationString = PickRandomDestination(); + + if (m_Destination != null && m_Destination.Name == m_DestinationString) + return m_Destination; + + if (Map.Felucca.Regions.Count > 0) + return m_Destination = EDI.Find(m_DestinationString); + + return m_Destination = null; + } + + private class DeleteTimer : Timer + { + private readonly Mobile m_Mobile; + + public DeleteTimer(Mobile m, TimeSpan delay) + : base(delay) + { + m_Mobile = m; + + Priority = TimerPriority.OneSecond; + } + + protected override void OnTick() + { + m_Mobile.Delete(); + } + } } - public virtual string[] GetPossibleDestinations() => Core.ML ? m_MLTownNames : m_TownNames; - - public virtual string PickRandomDestination() + public class EscortDestinationInfo { - if (Map.Felucca.Regions.Count == 0 || Map == null || Map == Map.Internal || Location == Point3D.Zero) - return null; // Not yet fully initialized + private static Dictionary m_Table; - string[] possible = GetPossibleDestinations(); - string picked = null; + public EscortDestinationInfo(string name, Region region) + { + Name = name; + Region = region; + } - while (picked == null) - { - picked = possible.RandomElement(); - EDI test = EDI.Find(picked); + public string Name { get; } - if (test.Contains(Location)) - picked = null; - } + public Region Region { get; } - return picked; + public bool Contains(Point3D p) => Region.Contains(p); + + public static void LoadTable() + { + ICollection list = Map.Felucca.Regions.Values; + + if (list.Count == 0) + return; + + m_Table = new Dictionary(); + + foreach (Region r in list) + if (r.Name != null && (r is DungeonRegion || r is TownRegion)) + m_Table[r.Name] = new EscortDestinationInfo(r.Name, r); + } + + public static EDI Find(string name) + { + if (m_Table == null) + LoadTable(); + + if (name == null || m_Table == null) + return null; + + m_Table.TryGetValue(name, out var info); + return info; + } } - public EDI GetDestination() + public class AskDestinationEntry : ContextMenuEntry { - if (MLQuestSystem.Enabled) - return null; + private readonly Mobile m_From; + private readonly BaseEscortable m_Mobile; - if (m_DestinationString == null && m_DeleteTimer == null) - m_DestinationString = PickRandomDestination(); + public AskDestinationEntry(BaseEscortable m, Mobile from) + : base(6100, 3) + { + m_Mobile = m; + m_From = from; + } - if (m_Destination != null && m_Destination.Name == m_DestinationString) - return m_Destination; - - if (Map.Felucca.Regions.Count > 0) - return m_Destination = EDI.Find(m_DestinationString); - - return m_Destination = null; + public override void OnClick() + { + m_Mobile.SayDestinationTo(m_From); + } } - private class DeleteTimer : Timer + public class AcceptEscortEntry : ContextMenuEntry { - private readonly Mobile m_Mobile; + private readonly Mobile m_From; + private readonly BaseEscortable m_Mobile; - public DeleteTimer(Mobile m, TimeSpan delay) - : base(delay) - { - m_Mobile = m; + public AcceptEscortEntry(BaseEscortable m, Mobile from) + : base(6101, 3) + { + m_Mobile = m; + m_From = from; + } - Priority = TimerPriority.OneSecond; - } - - protected override void OnTick() - { - m_Mobile.Delete(); - } + public override void OnClick() + { + m_Mobile.AcceptEscorter(m_From); + } } - } - public class EscortDestinationInfo - { - private static Dictionary m_Table; - - public EscortDestinationInfo(string name, Region region) + public class AbandonEscortEntry : ContextMenuEntry { - Name = name; - Region = region; + private readonly BaseEscortable m_Mobile; + + public AbandonEscortEntry(BaseEscortable m) + : base(6102, 3) => + m_Mobile = m; + + public override void OnClick() + { + m_Mobile.Delete(); // OSI just seems to delete instantly + } } - - public string Name { get; } - - public Region Region { get; } - - public bool Contains(Point3D p) => Region.Contains(p); - - public static void LoadTable() - { - ICollection list = Map.Felucca.Regions.Values; - - if (list.Count == 0) - return; - - m_Table = new Dictionary(); - - foreach (Region r in list) - if (r.Name != null && (r is DungeonRegion || r is TownRegion)) - m_Table[r.Name] = new EscortDestinationInfo(r.Name, r); - } - - public static EDI Find(string name) - { - if (m_Table == null) - LoadTable(); - - if (name == null || m_Table == null) - return null; - - m_Table.TryGetValue(name, out EscortDestinationInfo info); - return info; - } - } - - public class AskDestinationEntry : ContextMenuEntry - { - private readonly Mobile m_From; - private readonly BaseEscortable m_Mobile; - - public AskDestinationEntry(BaseEscortable m, Mobile from) - : base(6100, 3) - { - m_Mobile = m; - m_From = from; - } - - public override void OnClick() - { - m_Mobile.SayDestinationTo(m_From); - } - } - - public class AcceptEscortEntry : ContextMenuEntry - { - private readonly Mobile m_From; - private readonly BaseEscortable m_Mobile; - - public AcceptEscortEntry(BaseEscortable m, Mobile from) - : base(6101, 3) - { - m_Mobile = m; - m_From = from; - } - - public override void OnClick() - { - m_Mobile.AcceptEscorter(m_From); - } - } - - public class AbandonEscortEntry : ContextMenuEntry - { - private readonly BaseEscortable m_Mobile; - - public AbandonEscortEntry(BaseEscortable m) - : base(6102, 3) => - m_Mobile = m; - - public override void OnClick() - { - m_Mobile.Delete(); // OSI just seems to delete instantly - } - } } diff --git a/Projects/UOContent/Mobiles/Townfolk/BrideGroom.cs b/Projects/UOContent/Mobiles/Townfolk/BrideGroom.cs index 6bba5eba5..19a385499 100644 --- a/Projects/UOContent/Mobiles/Townfolk/BrideGroom.cs +++ b/Projects/UOContent/Mobiles/Townfolk/BrideGroom.cs @@ -2,76 +2,76 @@ using Server.Items; namespace Server.Mobiles { - public class BrideGroom : BaseEscortable - { - [Constructible] - public BrideGroom() + public class BrideGroom : BaseEscortable { - if (Female) - Title = "the bride"; - else - Title = "the groom"; + [Constructible] + public BrideGroom() + { + if (Female) + Title = "the bride"; + else + Title = "the groom"; + } + + public BrideGroom(Serial serial) : base(serial) + { + } + + public override bool CanTeach => true; + public override bool ClickTitle => false; // Do not display 'the groom' when single-clicking + + private static int GetRandomHue() + { + return Utility.Random(6) switch + { + 0 => 0, + 1 => Utility.RandomBlueHue(), + 2 => Utility.RandomGreenHue(), + 3 => Utility.RandomRedHue(), + 4 => Utility.RandomYellowHue(), + 5 => Utility.RandomNeutralHue(), + _ => 0 + }; + } + + public override void InitOutfit() + { + if (Female) + AddItem(new FancyDress()); + else + AddItem(new FancyShirt()); + + var lowHue = GetRandomHue(); + + AddItem(new LongPants(lowHue)); + + if (Female) + AddItem(new Shoes(lowHue)); + else + AddItem(new Boots(lowHue)); + + if (Utility.RandomBool()) + HairItemID = 0x203B; + else + HairItemID = 0x203C; + + HairHue = Race.RandomHairHue(); + + PackGold(200, 250); + } + + 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 BrideGroom(Serial serial) : base(serial) - { - } - - public override bool CanTeach => true; - public override bool ClickTitle => false; // Do not display 'the groom' when single-clicking - - private static int GetRandomHue() - { - return Utility.Random(6) switch - { - 0 => 0, - 1 => Utility.RandomBlueHue(), - 2 => Utility.RandomGreenHue(), - 3 => Utility.RandomRedHue(), - 4 => Utility.RandomYellowHue(), - 5 => Utility.RandomNeutralHue(), - _ => 0 - }; - } - - public override void InitOutfit() - { - if (Female) - AddItem(new FancyDress()); - else - AddItem(new FancyShirt()); - - int lowHue = GetRandomHue(); - - AddItem(new LongPants(lowHue)); - - if (Female) - AddItem(new Shoes(lowHue)); - else - AddItem(new Boots(lowHue)); - - if (Utility.RandomBool()) - HairItemID = 0x203B; - else - HairItemID = 0x203C; - - HairHue = Race.RandomHairHue(); - - PackGold(200, 250); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Townfolk/EscortableMage.cs b/Projects/UOContent/Mobiles/Townfolk/EscortableMage.cs index fe5b7a67f..b5a001c3b 100644 --- a/Projects/UOContent/Mobiles/Townfolk/EscortableMage.cs +++ b/Projects/UOContent/Mobiles/Townfolk/EscortableMage.cs @@ -2,70 +2,70 @@ using Server.Items; namespace Server.Mobiles { - public class EscortableMage : BaseEscortable - { - [Constructible] - public EscortableMage() + public class EscortableMage : BaseEscortable { - Title = "the mage"; + [Constructible] + public EscortableMage() + { + Title = "the mage"; - SetSkill(SkillName.EvalInt, 80.0, 100.0); - SetSkill(SkillName.Inscribe, 80.0, 100.0); - SetSkill(SkillName.Magery, 80.0, 100.0); - SetSkill(SkillName.Meditation, 80.0, 100.0); - SetSkill(SkillName.MagicResist, 80.0, 100.0); + SetSkill(SkillName.EvalInt, 80.0, 100.0); + SetSkill(SkillName.Inscribe, 80.0, 100.0); + SetSkill(SkillName.Magery, 80.0, 100.0); + SetSkill(SkillName.Meditation, 80.0, 100.0); + SetSkill(SkillName.MagicResist, 80.0, 100.0); + } + + public EscortableMage(Serial serial) : base(serial) + { + } + + public override bool CanTeach => true; + public override bool ClickTitle => false; // Do not display 'the mage' when single-clicking + + private static int GetRandomHue() + { + return Utility.Random(5) switch + { + 0 => Utility.RandomBlueHue(), + 1 => Utility.RandomGreenHue(), + 2 => Utility.RandomRedHue(), + 3 => Utility.RandomYellowHue(), + 4 => Utility.RandomNeutralHue(), + _ => Utility.RandomBlueHue() + }; + } + + public override void InitOutfit() + { + AddItem(new Robe(GetRandomHue())); + + var lowHue = GetRandomHue(); + + AddItem(new ShortPants(lowHue)); + + if (Female) + AddItem(new ThighBoots(lowHue)); + else + AddItem(new Boots(lowHue)); + + Utility.AssignRandomHair(this); + + PackGold(200, 250); + } + + 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 EscortableMage(Serial serial) : base(serial) - { - } - - public override bool CanTeach => true; - public override bool ClickTitle => false; // Do not display 'the mage' when single-clicking - - private static int GetRandomHue() - { - return Utility.Random(5) switch - { - 0 => Utility.RandomBlueHue(), - 1 => Utility.RandomGreenHue(), - 2 => Utility.RandomRedHue(), - 3 => Utility.RandomYellowHue(), - 4 => Utility.RandomNeutralHue(), - _ => Utility.RandomBlueHue() - }; - } - - public override void InitOutfit() - { - AddItem(new Robe(GetRandomHue())); - - int lowHue = GetRandomHue(); - - AddItem(new ShortPants(lowHue)); - - if (Female) - AddItem(new ThighBoots(lowHue)); - else - AddItem(new Boots(lowHue)); - - Utility.AssignRandomHair(this); - - PackGold(200, 250); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Townfolk/Gypsy.cs b/Projects/UOContent/Mobiles/Townfolk/Gypsy.cs index 9da5c9f9c..ca5ee2ed6 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Gypsy.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Gypsy.cs @@ -2,75 +2,75 @@ using Server.Items; namespace Server.Mobiles { - public class Gypsy : BaseCreature - { - [Constructible] - public Gypsy() - : base(AIType.AI_Animal, FightMode.None, 10, 1, 0.2, 0.4) + public class Gypsy : BaseCreature { - InitStats(31, 41, 51); + [Constructible] + public Gypsy() + : base(AIType.AI_Animal, FightMode.None, 10, 1, 0.2, 0.4) + { + InitStats(31, 41, 51); - SpeechHue = Utility.RandomDyedHue(); + SpeechHue = Utility.RandomDyedHue(); - SetSkill(SkillName.Cooking, 65, 88); - SetSkill(SkillName.Snooping, 65, 88); - SetSkill(SkillName.Stealing, 65, 88); + SetSkill(SkillName.Cooking, 65, 88); + SetSkill(SkillName.Snooping, 65, 88); + SetSkill(SkillName.Stealing, 65, 88); - Hue = Race.Human.RandomSkinHue(); + Hue = Race.Human.RandomSkinHue(); - if (Female = Utility.RandomBool()) - { - Body = 0x191; - Name = NameList.RandomName("female"); - AddItem(new Kilt(Utility.RandomDyedHue())); - AddItem(new Shirt(Utility.RandomDyedHue())); - AddItem(new ThighBoots()); - Title = "the gypsy"; - } - else - { - Body = 0x190; - Name = NameList.RandomName("male"); - AddItem(new ShortPants(Utility.RandomNeutralHue())); - AddItem(new Shirt(Utility.RandomDyedHue())); - AddItem(new Sandals()); - Title = "the gypsy"; - } + if (Female = Utility.RandomBool()) + { + Body = 0x191; + Name = NameList.RandomName("female"); + AddItem(new Kilt(Utility.RandomDyedHue())); + AddItem(new Shirt(Utility.RandomDyedHue())); + AddItem(new ThighBoots()); + Title = "the gypsy"; + } + else + { + Body = 0x190; + Name = NameList.RandomName("male"); + AddItem(new ShortPants(Utility.RandomNeutralHue())); + AddItem(new Shirt(Utility.RandomDyedHue())); + AddItem(new Sandals()); + Title = "the gypsy"; + } - AddItem(new Bandana(Utility.RandomDyedHue())); - AddItem(new Dagger()); + AddItem(new Bandana(Utility.RandomDyedHue())); + AddItem(new Dagger()); - Utility.AssignRandomHair(this); + Utility.AssignRandomHair(this); - Container pack = new Backpack(); + Container pack = new Backpack(); - pack.DropItem(new Gold(250, 300)); + pack.DropItem(new Gold(250, 300)); - pack.Movable = false; + pack.Movable = false; - AddItem(pack); + AddItem(pack); + } + + public Gypsy(Serial serial) + : base(serial) + { + } + + public override bool CanTeach => true; + public override bool ClickTitle => 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 Gypsy(Serial serial) - : base(serial) - { - } - - public override bool CanTeach => true; - public override bool ClickTitle => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Townfolk/HarborMaster.cs b/Projects/UOContent/Mobiles/Townfolk/HarborMaster.cs index a83a1e452..2d03f6099 100644 --- a/Projects/UOContent/Mobiles/Townfolk/HarborMaster.cs +++ b/Projects/UOContent/Mobiles/Townfolk/HarborMaster.cs @@ -2,70 +2,70 @@ using Server.Items; namespace Server.Mobiles { - public class HarborMaster : BaseCreature - { - [Constructible] - public HarborMaster() - : base(AIType.AI_Animal, FightMode.None, 10, 1, 0.2, 0.4) + public class HarborMaster : BaseCreature { - InitStats(31, 41, 51); + [Constructible] + public HarborMaster() + : base(AIType.AI_Animal, FightMode.None, 10, 1, 0.2, 0.4) + { + InitStats(31, 41, 51); - SetSkill(SkillName.Mining, 36, 68); + SetSkill(SkillName.Mining, 36, 68); - SpeechHue = Utility.RandomDyedHue(); - Hue = Race.Human.RandomSkinHue(); - Blessed = true; + SpeechHue = Utility.RandomDyedHue(); + Hue = Race.Human.RandomSkinHue(); + Blessed = true; - if (Female = Utility.RandomBool()) - { - Body = 0x191; - Name = NameList.RandomName("female"); - Title = "the Harbor Mistress"; - } - else - { - Body = 0x190; - Name = NameList.RandomName("male"); - Title = "the Harbor Master"; - } + if (Female = Utility.RandomBool()) + { + Body = 0x191; + Name = NameList.RandomName("female"); + Title = "the Harbor Mistress"; + } + else + { + Body = 0x190; + Name = NameList.RandomName("male"); + Title = "the Harbor Master"; + } - AddItem(new Shirt(Utility.RandomDyedHue())); - AddItem(new Boots()); - AddItem(new LongPants(Utility.RandomNeutralHue())); - AddItem(new QuarterStaff()); + AddItem(new Shirt(Utility.RandomDyedHue())); + AddItem(new Boots()); + AddItem(new LongPants(Utility.RandomNeutralHue())); + AddItem(new QuarterStaff()); - Utility.AssignRandomHair(this); + Utility.AssignRandomHair(this); - Container pack = new Backpack(); + Container pack = new Backpack(); - pack.DropItem(new Gold(250, 300)); + pack.DropItem(new Gold(250, 300)); - pack.Movable = false; + pack.Movable = false; - AddItem(pack); + AddItem(pack); + } + + public HarborMaster(Serial serial) + : base(serial) + { + } + + public override bool CanTeach => false; + + public override bool ClickTitle => 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 HarborMaster(Serial serial) - : base(serial) - { - } - - public override bool CanTeach => false; - - public override bool ClickTitle => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Townfolk/Merchant.cs b/Projects/UOContent/Mobiles/Townfolk/Merchant.cs index f8ea9c287..6f46f9631 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Merchant.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Merchant.cs @@ -2,78 +2,78 @@ using Server.Items; namespace Server.Mobiles { - public class Merchant : BaseEscortable - { - [Constructible] - public Merchant() + public class Merchant : BaseEscortable { - Title = "the merchant"; - SetSkill(SkillName.ItemID, 55.0, 78.0); - SetSkill(SkillName.ArmsLore, 55, 78); + [Constructible] + public Merchant() + { + Title = "the merchant"; + SetSkill(SkillName.ItemID, 55.0, 78.0); + SetSkill(SkillName.ArmsLore, 55, 78); + } + + public Merchant(Serial serial) + : base(serial) + { + } + + public override bool CanTeach => true; + public override bool ClickTitle => false; // Do not display 'the merchant' when single-clicking + + private static int GetRandomHue() + { + return Utility.Random(6) switch + { + 0 => 0, + 1 => Utility.RandomBlueHue(), + 2 => Utility.RandomGreenHue(), + 3 => Utility.RandomRedHue(), + 4 => Utility.RandomYellowHue(), + 5 => Utility.RandomNeutralHue(), + _ => 0 + }; + } + + public override void InitOutfit() + { + if (Female) + AddItem(new PlainDress()); + else + AddItem(new Shirt(GetRandomHue())); + + var lowHue = GetRandomHue(); + + AddItem(new ThighBoots()); + + if (Female) + AddItem(new FancyDress(lowHue)); + else + AddItem(new FancyShirt(lowHue)); + AddItem(new LongPants(lowHue)); + + if (!Female) + AddItem(new BodySash(lowHue)); + + // if (!Female) + // AddItem( new Longsword() ); + + Utility.AssignRandomHair(this); + + PackGold(200, 250); + } + + 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 Merchant(Serial serial) - : base(serial) - { - } - - public override bool CanTeach => true; - public override bool ClickTitle => false; // Do not display 'the merchant' when single-clicking - - private static int GetRandomHue() - { - return Utility.Random(6) switch - { - 0 => 0, - 1 => Utility.RandomBlueHue(), - 2 => Utility.RandomGreenHue(), - 3 => Utility.RandomRedHue(), - 4 => Utility.RandomYellowHue(), - 5 => Utility.RandomNeutralHue(), - _ => 0 - }; - } - - public override void InitOutfit() - { - if (Female) - AddItem(new PlainDress()); - else - AddItem(new Shirt(GetRandomHue())); - - int lowHue = GetRandomHue(); - - AddItem(new ThighBoots()); - - if (Female) - AddItem(new FancyDress(lowHue)); - else - AddItem(new FancyShirt(lowHue)); - AddItem(new LongPants(lowHue)); - - if (!Female) - AddItem(new BodySash(lowHue)); - - // if (!Female) - // AddItem( new Longsword() ); - - Utility.AssignRandomHair(this); - - PackGold(200, 250); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Townfolk/Messenger.cs b/Projects/UOContent/Mobiles/Townfolk/Messenger.cs index 83968d27c..90ee2a1a4 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Messenger.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Messenger.cs @@ -2,68 +2,68 @@ using Server.Items; namespace Server.Mobiles { - public class Messenger : BaseEscortable - { - [Constructible] - public Messenger() => Title = "the messenger"; - - public Messenger(Serial serial) : base(serial) + public class Messenger : BaseEscortable { + [Constructible] + public Messenger() => Title = "the messenger"; + + public Messenger(Serial serial) : base(serial) + { + } + + public override bool CanTeach => true; + public override bool ClickTitle => false; // Do not display 'the messenger' when single-clicking + + private static int GetRandomHue() + { + return Utility.Random(6) switch + { + 0 => 0, + 1 => Utility.RandomBlueHue(), + 2 => Utility.RandomGreenHue(), + 3 => Utility.RandomRedHue(), + 4 => Utility.RandomYellowHue(), + 5 => Utility.RandomNeutralHue(), + _ => 0 + }; + } + + public override void InitOutfit() + { + if (Female) + AddItem(new PlainDress()); + else + AddItem(new Shirt(GetRandomHue())); + + var lowHue = GetRandomHue(); + + AddItem(new ShortPants(lowHue)); + + if (Female) + AddItem(new Boots(lowHue)); + else + AddItem(new Shoes(lowHue)); + + var randomHair = Utility.Random(4); + HairItemID = randomHair == 4 ? 0x203B : 0x2048 + randomHair; + + HairHue = Race.RandomHairHue(); + + PackGold(200, 250); + } + + 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 CanTeach => true; - public override bool ClickTitle => false; // Do not display 'the messenger' when single-clicking - - private static int GetRandomHue() - { - return Utility.Random(6) switch - { - 0 => 0, - 1 => Utility.RandomBlueHue(), - 2 => Utility.RandomGreenHue(), - 3 => Utility.RandomRedHue(), - 4 => Utility.RandomYellowHue(), - 5 => Utility.RandomNeutralHue(), - _ => 0 - }; - } - - public override void InitOutfit() - { - if (Female) - AddItem(new PlainDress()); - else - AddItem(new Shirt(GetRandomHue())); - - int lowHue = GetRandomHue(); - - AddItem(new ShortPants(lowHue)); - - if (Female) - AddItem(new Boots(lowHue)); - else - AddItem(new Shoes(lowHue)); - - int randomHair = Utility.Random(4); - HairItemID = randomHair == 4 ? 0x203B : 0x2048 + randomHair; - - HairHue = Race.RandomHairHue(); - - PackGold(200, 250); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Townfolk/Minter.cs b/Projects/UOContent/Mobiles/Townfolk/Minter.cs index 84d20881c..7cac3ab7b 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Minter.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Minter.cs @@ -1,28 +1,28 @@ namespace Server.Mobiles { - public class Minter : Banker - { - [Constructible] - public Minter() => Title = "the minter"; - - public Minter(Serial serial) : base(serial) + public class Minter : Banker { + [Constructible] + public Minter() => Title = "the minter"; + + public Minter(Serial serial) : base(serial) + { + } + + public override NpcGuild NpcGuild => NpcGuild.MerchantsGuild; + + 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 NpcGuild NpcGuild => NpcGuild.MerchantsGuild; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Townfolk/Ninja.cs b/Projects/UOContent/Mobiles/Townfolk/Ninja.cs index 212f005fa..fd7c64c7b 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Ninja.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Ninja.cs @@ -2,74 +2,74 @@ using Server.Items; namespace Server.Mobiles { - public class Ninja : BaseCreature - { - [Constructible] - public Ninja() : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Ninja : BaseCreature { - Title = "the ninja"; + [Constructible] + public Ninja() : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Title = "the ninja"; - InitStats(100, 100, 25); + InitStats(100, 100, 25); - SetSkill(SkillName.Fencing, 64.0, 80.0); - SetSkill(SkillName.Macing, 64.0, 80.0); - SetSkill(SkillName.Ninjitsu, 60.0, 80.0); - SetSkill(SkillName.Parry, 64.0, 80.0); - SetSkill(SkillName.Tactics, 64.0, 85.0); - SetSkill(SkillName.Swords, 64.0, 85.0); + SetSkill(SkillName.Fencing, 64.0, 80.0); + SetSkill(SkillName.Macing, 64.0, 80.0); + SetSkill(SkillName.Ninjitsu, 60.0, 80.0); + SetSkill(SkillName.Parry, 64.0, 80.0); + SetSkill(SkillName.Tactics, 64.0, 85.0); + SetSkill(SkillName.Swords, 64.0, 85.0); - SpeechHue = Utility.RandomDyedHue(); + SpeechHue = Utility.RandomDyedHue(); - Hue = Race.Human.RandomSkinHue(); + Hue = Race.Human.RandomSkinHue(); - if (Female = Utility.RandomBool()) - { - Body = 0x191; - Name = NameList.RandomName("female"); - } - else - { - Body = 0x190; - Name = NameList.RandomName("male"); - } + if (Female = Utility.RandomBool()) + { + Body = 0x191; + Name = NameList.RandomName("female"); + } + else + { + Body = 0x190; + Name = NameList.RandomName("male"); + } - if (!Female) - AddItem(new LeatherNinjaHood()); + if (!Female) + AddItem(new LeatherNinjaHood()); - AddItem(new LeatherNinjaPants()); - AddItem(new LeatherNinjaBelt()); - AddItem(new LeatherNinjaJacket()); - AddItem(new NinjaTabi()); + AddItem(new LeatherNinjaPants()); + AddItem(new LeatherNinjaBelt()); + AddItem(new LeatherNinjaJacket()); + AddItem(new NinjaTabi()); - int hairHue = Utility.RandomNondyedHue(); + var hairHue = Utility.RandomNondyedHue(); - Utility.AssignRandomHair(this, hairHue); + Utility.AssignRandomHair(this, hairHue); - if (Utility.Random(7) != 0) - Utility.AssignRandomFacialHair(this, hairHue); + if (Utility.Random(7) != 0) + Utility.AssignRandomFacialHair(this, hairHue); - PackGold(250, 300); + PackGold(250, 300); + } + + public Ninja(Serial serial) : base(serial) + { + } + + public override bool CanTeach => true; + public override bool ClickTitle => false; + + 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(); + } } - - public Ninja(Serial serial) : base(serial) - { - } - - public override bool CanTeach => true; - public override bool ClickTitle => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Townfolk/Noble.cs b/Projects/UOContent/Mobiles/Townfolk/Noble.cs index 25390b992..c5f0b4417 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Noble.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Noble.cs @@ -2,80 +2,80 @@ using Server.Items; namespace Server.Mobiles { - public class Noble : BaseEscortable - { - [Constructible] - public Noble() + public class Noble : BaseEscortable { - Title = "the noble"; + [Constructible] + public Noble() + { + Title = "the noble"; - SetSkill(SkillName.Parry, 80.0, 100.0); - SetSkill(SkillName.Swords, 80.0, 100.0); - SetSkill(SkillName.Tactics, 80.0, 100.0); + SetSkill(SkillName.Parry, 80.0, 100.0); + SetSkill(SkillName.Swords, 80.0, 100.0); + SetSkill(SkillName.Tactics, 80.0, 100.0); + } + + public Noble(Serial serial) : base(serial) + { + } + + public override bool CanTeach => true; + public override bool ClickTitle => false; // Do not display 'the noble' when single-clicking + + private static int GetRandomHue() + { + return Utility.Random(6) switch + { + 0 => 0, + 1 => Utility.RandomBlueHue(), + 2 => Utility.RandomGreenHue(), + 3 => Utility.RandomRedHue(), + 4 => Utility.RandomYellowHue(), + 5 => Utility.RandomNeutralHue(), + _ => 0 + }; + } + + public override void InitOutfit() + { + if (Female) + AddItem(new FancyDress()); + else + AddItem(new FancyShirt(GetRandomHue())); + + var lowHue = GetRandomHue(); + + AddItem(new ShortPants(lowHue)); + + if (Female) + AddItem(new ThighBoots(lowHue)); + else + AddItem(new Boots(lowHue)); + + if (!Female) + AddItem(new BodySash(lowHue)); + + AddItem(new Cloak(GetRandomHue())); + + if (!Female) + AddItem(new Longsword()); + + Utility.AssignRandomHair(this); + + PackGold(200, 250); + } + + 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 Noble(Serial serial) : base(serial) - { - } - - public override bool CanTeach => true; - public override bool ClickTitle => false; // Do not display 'the noble' when single-clicking - - private static int GetRandomHue() - { - return Utility.Random(6) switch - { - 0 => 0, - 1 => Utility.RandomBlueHue(), - 2 => Utility.RandomGreenHue(), - 3 => Utility.RandomRedHue(), - 4 => Utility.RandomYellowHue(), - 5 => Utility.RandomNeutralHue(), - _ => 0 - }; - } - - public override void InitOutfit() - { - if (Female) - AddItem(new FancyDress()); - else - AddItem(new FancyShirt(GetRandomHue())); - - int lowHue = GetRandomHue(); - - AddItem(new ShortPants(lowHue)); - - if (Female) - AddItem(new ThighBoots(lowHue)); - else - AddItem(new Boots(lowHue)); - - if (!Female) - AddItem(new BodySash(lowHue)); - - AddItem(new Cloak(GetRandomHue())); - - if (!Female) - AddItem(new Longsword()); - - Utility.AssignRandomHair(this); - - PackGold(200, 250); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Townfolk/Peasant.cs b/Projects/UOContent/Mobiles/Townfolk/Peasant.cs index 5d2659010..4f9108e7a 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Peasant.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Peasant.cs @@ -2,73 +2,73 @@ using Server.Items; namespace Server.Mobiles { - public class Peasant : BaseEscortable - { - [Constructible] - public Peasant() => Title = "the peasant"; - - public Peasant(Serial serial) : base(serial) + public class Peasant : BaseEscortable { + [Constructible] + public Peasant() => Title = "the peasant"; + + public Peasant(Serial serial) : base(serial) + { + } + + public override bool CanTeach => true; + public override bool ClickTitle => false; // Do not display 'the peasant' when single-clicking + + private static int GetRandomHue() + { + return Utility.Random(6) switch + { + 0 => 0, + 1 => Utility.RandomBlueHue(), + 2 => Utility.RandomGreenHue(), + 3 => Utility.RandomRedHue(), + 4 => Utility.RandomYellowHue(), + 5 => Utility.RandomNeutralHue(), + _ => 0 + }; + } + + public override void InitOutfit() + { + if (Female) + AddItem(new PlainDress()); + else + AddItem(new Shirt(GetRandomHue())); + + var lowHue = GetRandomHue(); + + AddItem(new ShortPants(lowHue)); + + if (Female) + AddItem(new Boots(lowHue)); + else + AddItem(new Shoes(lowHue)); + + // if (!Female) + // AddItem( new BodySash( lowHue ) ); + + // AddItem( new Cloak( GetRandomHue() ) ); + + // if (!Female) + // AddItem( new Longsword() ); + + Utility.AssignRandomHair(this); + + PackGold(200, 250); + } + + 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 CanTeach => true; - public override bool ClickTitle => false; // Do not display 'the peasant' when single-clicking - - private static int GetRandomHue() - { - return Utility.Random(6) switch - { - 0 => 0, - 1 => Utility.RandomBlueHue(), - 2 => Utility.RandomGreenHue(), - 3 => Utility.RandomRedHue(), - 4 => Utility.RandomYellowHue(), - 5 => Utility.RandomNeutralHue(), - _ => 0 - }; - } - - public override void InitOutfit() - { - if (Female) - AddItem(new PlainDress()); - else - AddItem(new Shirt(GetRandomHue())); - - int lowHue = GetRandomHue(); - - AddItem(new ShortPants(lowHue)); - - if (Female) - AddItem(new Boots(lowHue)); - else - AddItem(new Shoes(lowHue)); - - // if (!Female) - // AddItem( new BodySash( lowHue ) ); - - // AddItem( new Cloak( GetRandomHue() ) ); - - // if (!Female) - // AddItem( new Longsword() ); - - Utility.AssignRandomHair(this); - - PackGold(200, 250); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Townfolk/Prisoner.cs b/Projects/UOContent/Mobiles/Townfolk/Prisoner.cs index d680384a3..adb36e885 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Prisoner.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Prisoner.cs @@ -3,80 +3,80 @@ using Server.Items; namespace Server.Mobiles.Townfolk { - public class Prisoner : BaseEscortable - { - [Constructible] - public Prisoner() + public class Prisoner : BaseEscortable { - Title = Female ? "the noblewoman" : "the nobleman"; + [Constructible] + public Prisoner() + { + Title = Female ? "the noblewoman" : "the nobleman"; - CantWalk = true; - IsPrisoner = true; + CantWalk = true; + IsPrisoner = true; + } + + public Prisoner(Serial serial) + : base(serial) + { + } + + public override bool CanTeach => true; + public override bool ClickTitle => false; + + public override void InitOutfit() + { + if (Female) + { + AddItem(new FancyDress(Utility.RandomNondyedHue())); + } + else + { + AddItem(new FancyShirt(Utility.RandomNondyedHue())); + AddItem(new LongPants(Utility.RandomNondyedHue())); + } + + if (Utility.RandomBool()) + AddItem(new Boots()); + else + AddItem(new ThighBoots()); + + Utility.AssignRandomHair(this); + Utility.AssignRandomFacialHair(this, HairHue); + } + + public override void Shout(PlayerMobile pm) + { + /* + * 502261 - HELP! + * 502262 - Help me! + * 502263 - Canst thou aid me?! + * 502264 - Help a poor prisoner! + * 502265 - Help! Please! + * 502266 - Aaah! Help me! + * 502267 - Go and get some help! + */ + MLQuestSystem.Tell(this, pm, Utility.Random(502261, 7)); + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + base.OnMovement(m, oldLocation); + + if (CantWalk && InRange(m, 1) && !InRange(oldLocation, 1) && (!m.Hidden || m.AccessLevel == AccessLevel.Player)) + Say(502268); // Quickly, I beg thee! Unlock my chains! If thou dost look at me close thou canst see them. + } + + 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 Prisoner(Serial serial) - : base(serial) - { - } - - public override bool CanTeach => true; - public override bool ClickTitle => false; - - public override void InitOutfit() - { - if (Female) - { - AddItem(new FancyDress(Utility.RandomNondyedHue())); - } - else - { - AddItem(new FancyShirt(Utility.RandomNondyedHue())); - AddItem(new LongPants(Utility.RandomNondyedHue())); - } - - if (Utility.RandomBool()) - AddItem(new Boots()); - else - AddItem(new ThighBoots()); - - Utility.AssignRandomHair(this); - Utility.AssignRandomFacialHair(this, HairHue); - } - - public override void Shout(PlayerMobile pm) - { - /* - * 502261 - HELP! - * 502262 - Help me! - * 502263 - Canst thou aid me?! - * 502264 - Help a poor prisoner! - * 502265 - Help! Please! - * 502266 - Aaah! Help me! - * 502267 - Go and get some help! - */ - MLQuestSystem.Tell(this, pm, Utility.Random(502261, 7)); - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - base.OnMovement(m, oldLocation); - - if (CantWalk && InRange(m, 1) && !InRange(oldLocation, 1) && (!m.Hidden || m.AccessLevel == AccessLevel.Player)) - Say(502268); // Quickly, I beg thee! Unlock my chains! If thou dost look at me close thou canst see them. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Townfolk/Samurai.cs b/Projects/UOContent/Mobiles/Townfolk/Samurai.cs index d4585325e..1450d6467 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Samurai.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Samurai.cs @@ -2,110 +2,110 @@ using Server.Items; namespace Server.Mobiles { - public class Samurai : BaseCreature - { - [Constructible] - public Samurai() : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + public class Samurai : BaseCreature { - Title = "the samurai"; + [Constructible] + public Samurai() : base(AIType.AI_Melee, FightMode.Aggressor, 10, 1, 0.2, 0.4) + { + Title = "the samurai"; - InitStats(100, 100, 25); + InitStats(100, 100, 25); - SetSkill(SkillName.ArmsLore, 64.0, 80.0); - SetSkill(SkillName.Bushido, 64.0, 85.0); - SetSkill(SkillName.Parry, 64.0, 80.0); - SetSkill(SkillName.Swords, 64.0, 85.0); + SetSkill(SkillName.ArmsLore, 64.0, 80.0); + SetSkill(SkillName.Bushido, 64.0, 85.0); + SetSkill(SkillName.Parry, 64.0, 80.0); + SetSkill(SkillName.Swords, 64.0, 85.0); - SpeechHue = Utility.RandomDyedHue(); + SpeechHue = Utility.RandomDyedHue(); - Hue = Race.Human.RandomSkinHue(); + Hue = Race.Human.RandomSkinHue(); - if (Female = Utility.RandomBool()) - { - Body = 0x191; - Name = NameList.RandomName("female"); - } - else - { - Body = 0x190; - Name = NameList.RandomName("male"); - } + if (Female = Utility.RandomBool()) + { + Body = 0x191; + Name = NameList.RandomName("female"); + } + else + { + Body = 0x190; + Name = NameList.RandomName("male"); + } - switch (Utility.Random(3)) - { - case 0: - AddItem(new Lajatang()); - break; - case 1: - AddItem(new Wakizashi()); - break; - case 2: - AddItem(new NoDachi()); - break; - } + switch (Utility.Random(3)) + { + case 0: + AddItem(new Lajatang()); + break; + case 1: + AddItem(new Wakizashi()); + break; + case 2: + AddItem(new NoDachi()); + break; + } - switch (Utility.Random(3)) - { - case 0: - AddItem(new LeatherSuneate()); - break; - case 1: - AddItem(new PlateSuneate()); - break; - case 2: - AddItem(new StuddedHaidate()); - break; - } + switch (Utility.Random(3)) + { + case 0: + AddItem(new LeatherSuneate()); + break; + case 1: + AddItem(new PlateSuneate()); + break; + case 2: + AddItem(new StuddedHaidate()); + break; + } - switch (Utility.Random(4)) - { - case 0: - AddItem(new LeatherJingasa()); - break; - case 1: - AddItem(new ChainHatsuburi()); - break; - case 2: - AddItem(new HeavyPlateJingasa()); - break; - case 3: - AddItem(new DecorativePlateKabuto()); - break; - } + switch (Utility.Random(4)) + { + case 0: + AddItem(new LeatherJingasa()); + break; + case 1: + AddItem(new ChainHatsuburi()); + break; + case 2: + AddItem(new HeavyPlateJingasa()); + break; + case 3: + AddItem(new DecorativePlateKabuto()); + break; + } - AddItem(new LeatherDo()); - AddItem(new LeatherHiroSode()); - AddItem(new SamuraiTabi(Utility.RandomNondyedHue())); // TODO: Hue + AddItem(new LeatherDo()); + AddItem(new LeatherHiroSode()); + AddItem(new SamuraiTabi(Utility.RandomNondyedHue())); // TODO: Hue - int hairHue = Utility.RandomNondyedHue(); + var hairHue = Utility.RandomNondyedHue(); - Utility.AssignRandomHair(this, hairHue); + Utility.AssignRandomHair(this, hairHue); - if (Utility.Random(7) != 0) - Utility.AssignRandomFacialHair(this, hairHue); + if (Utility.Random(7) != 0) + Utility.AssignRandomFacialHair(this, hairHue); - PackGold(250, 300); + PackGold(250, 300); + } + + public Samurai(Serial serial) : base(serial) + { + } + + public override bool CanTeach => true; + public override bool ClickTitle => false; + + 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(); + } } - - public Samurai(Serial serial) : base(serial) - { - } - - public override bool CanTeach => true; - public override bool ClickTitle => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Townfolk/Sculptor.cs b/Projects/UOContent/Mobiles/Townfolk/Sculptor.cs index 78a81ba23..00b6de015 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Sculptor.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Sculptor.cs @@ -2,64 +2,64 @@ using Server.Items; namespace Server.Mobiles { - public class Sculptor : BaseCreature - { - [Constructible] - public Sculptor() - : base(AIType.AI_Animal, FightMode.None, 10, 1, 0.2, 0.4) + public class Sculptor : BaseCreature { - InitStats(31, 41, 51); + [Constructible] + public Sculptor() + : base(AIType.AI_Animal, FightMode.None, 10, 1, 0.2, 0.4) + { + InitStats(31, 41, 51); - SpeechHue = Utility.RandomDyedHue(); - Title = "the sculptor"; - Hue = Race.Human.RandomSkinHue(); + SpeechHue = Utility.RandomDyedHue(); + Title = "the sculptor"; + Hue = Race.Human.RandomSkinHue(); - if (Female = Utility.RandomBool()) - { - Body = 0x191; - Name = NameList.RandomName("female"); - AddItem(new Kilt(Utility.RandomNeutralHue())); - } - else - { - Body = 0x190; - Name = NameList.RandomName("male"); - AddItem(new LongPants(Utility.RandomNeutralHue())); - } + if (Female = Utility.RandomBool()) + { + Body = 0x191; + Name = NameList.RandomName("female"); + AddItem(new Kilt(Utility.RandomNeutralHue())); + } + else + { + Body = 0x190; + Name = NameList.RandomName("male"); + AddItem(new LongPants(Utility.RandomNeutralHue())); + } - AddItem(new Doublet(Utility.RandomNeutralHue())); - AddItem(new HalfApron()); + AddItem(new Doublet(Utility.RandomNeutralHue())); + AddItem(new HalfApron()); - Utility.AssignRandomHair(this); + Utility.AssignRandomHair(this); - Container pack = new Backpack(); + Container pack = new Backpack(); - pack.DropItem(new Gold(250, 300)); + pack.DropItem(new Gold(250, 300)); - pack.Movable = false; + pack.Movable = false; - AddItem(pack); + AddItem(pack); + } + + public Sculptor(Serial serial) + : base(serial) + { + } + + public override bool ClickTitle => 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 Sculptor(Serial serial) - : base(serial) - { - } - - public override bool ClickTitle => false; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Townfolk/SeekerOfAdventure.cs b/Projects/UOContent/Mobiles/Townfolk/SeekerOfAdventure.cs index 6b6723979..ab39de4ad 100644 --- a/Projects/UOContent/Mobiles/Townfolk/SeekerOfAdventure.cs +++ b/Projects/UOContent/Mobiles/Townfolk/SeekerOfAdventure.cs @@ -2,91 +2,91 @@ using Server.Items; namespace Server.Mobiles { - public class SeekerOfAdventure : BaseEscortable - { - private static readonly string[] m_Dungeons = + public class SeekerOfAdventure : BaseEscortable { - "Covetous", "Deceit", "Despise", - "Destard", "Hythloth", "Shame", // Old Code for Pre-ML shards. - "Wrong" - }; + private static readonly string[] m_Dungeons = + { + "Covetous", "Deceit", "Despise", + "Destard", "Hythloth", "Shame", // Old Code for Pre-ML shards. + "Wrong" + }; - private static readonly string[] m_MLDestinations = - { - "Cove", "Serpent's Hold", "Jhelom", // ML List - "Nujel'm" - }; + private static readonly string[] m_MLDestinations = + { + "Cove", "Serpent's Hold", "Jhelom", // ML List + "Nujel'm" + }; - [Constructible] - public SeekerOfAdventure() => Title = "the seeker of adventure"; + [Constructible] + public SeekerOfAdventure() => Title = "the seeker of adventure"; - public SeekerOfAdventure(Serial serial) : base(serial) - { + public SeekerOfAdventure(Serial serial) : base(serial) + { + } + + public override bool ClickTitle => false; // Do not display 'the seeker of adventure' when single-clicking + + public override string[] GetPossibleDestinations() + { + if (Core.ML) + return m_MLDestinations; + return m_Dungeons; + } + + private static int GetRandomHue() + { + return Utility.Random(6) switch + { + 0 => 0, + 1 => Utility.RandomBlueHue(), + 2 => Utility.RandomGreenHue(), + 3 => Utility.RandomRedHue(), + 4 => Utility.RandomYellowHue(), + 5 => Utility.RandomNeutralHue(), + _ => 0 + }; + } + + public override void InitOutfit() + { + if (Female) + AddItem(new FancyDress(GetRandomHue())); + else + AddItem(new FancyShirt(GetRandomHue())); + + var lowHue = GetRandomHue(); + + AddItem(new ShortPants(lowHue)); + + if (Female) + AddItem(new ThighBoots(lowHue)); + else + AddItem(new Boots(lowHue)); + + if (!Female) + AddItem(new BodySash(lowHue)); + + AddItem(new Cloak(GetRandomHue())); + + AddItem(new Longsword()); + + Utility.AssignRandomHair(this); + + PackGold(100, 150); + } + + 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 ClickTitle => false; // Do not display 'the seeker of adventure' when single-clicking - - public override string[] GetPossibleDestinations() - { - if (Core.ML) - return m_MLDestinations; - return m_Dungeons; - } - - private static int GetRandomHue() - { - return Utility.Random(6) switch - { - 0 => 0, - 1 => Utility.RandomBlueHue(), - 2 => Utility.RandomGreenHue(), - 3 => Utility.RandomRedHue(), - 4 => Utility.RandomYellowHue(), - 5 => Utility.RandomNeutralHue(), - _ => 0 - }; - } - - public override void InitOutfit() - { - if (Female) - AddItem(new FancyDress(GetRandomHue())); - else - AddItem(new FancyShirt(GetRandomHue())); - - int lowHue = GetRandomHue(); - - AddItem(new ShortPants(lowHue)); - - if (Female) - AddItem(new ThighBoots(lowHue)); - else - AddItem(new Boots(lowHue)); - - if (!Female) - AddItem(new BodySash(lowHue)); - - AddItem(new Cloak(GetRandomHue())); - - AddItem(new Longsword()); - - Utility.AssignRandomHair(this); - - PackGold(100, 150); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Townfolk/TownCrier.cs b/Projects/UOContent/Mobiles/Townfolk/TownCrier.cs index 567abf5b0..e005e917d 100644 --- a/Projects/UOContent/Mobiles/Townfolk/TownCrier.cs +++ b/Projects/UOContent/Mobiles/Townfolk/TownCrier.cs @@ -8,493 +8,499 @@ using Server.Prompts; namespace Server.Mobiles { - public interface ITownCrierEntryList - { - List Entries { get; } - TownCrierEntry GetRandomEntry(); - TownCrierEntry AddEntry(string[] lines, TimeSpan duration); - void RemoveEntry(TownCrierEntry entry); - } - - public class GlobalTownCrierEntryList : ITownCrierEntryList - { - private static GlobalTownCrierEntryList m_Instance; - - public static GlobalTownCrierEntryList Instance => m_Instance ?? (m_Instance = new GlobalTownCrierEntryList()); - - public bool IsEmpty => Entries == null || Entries.Count == 0; - - public List Entries { get; private set; } - - public TownCrierEntry GetRandomEntry() + public interface ITownCrierEntryList { - if (Entries == null || Entries.Count == 0) - return null; - - for (int i = Entries.Count - 1; Entries != null && i >= 0; --i) - { - if (i >= Entries.Count) - continue; - - TownCrierEntry tce = Entries[i]; - - if (tce.Expired) - RemoveEntry(tce); - } - - return Entries.RandomElement(); + List Entries { get; } + TownCrierEntry GetRandomEntry(); + TownCrierEntry AddEntry(string[] lines, TimeSpan duration); + void RemoveEntry(TownCrierEntry entry); } - public TownCrierEntry AddEntry(string[] lines, TimeSpan duration) + public class GlobalTownCrierEntryList : ITownCrierEntryList { - Entries ??= new List(); + private static GlobalTownCrierEntryList m_Instance; - TownCrierEntry tce = new TownCrierEntry(lines, duration); + public static GlobalTownCrierEntryList Instance => m_Instance ?? (m_Instance = new GlobalTownCrierEntryList()); - Entries.Add(tce); + public bool IsEmpty => Entries == null || Entries.Count == 0; - List instances = TownCrier.Instances; + public List Entries { get; private set; } - for (int i = 0; i < instances.Count; ++i) - instances[i].ForceBeginAutoShout(); - - return tce; - } - - public void RemoveEntry(TownCrierEntry tce) - { - if (Entries == null) - return; - - Entries.Remove(tce); - - if (Entries.Count == 0) - Entries = null; - } - - public static void Initialize() - { - CommandSystem.Register("TownCriers", AccessLevel.GameMaster, TownCriers_OnCommand); - } - - [Usage("TownCriers")] - [Description("Manages the global town crier list.")] - public static void TownCriers_OnCommand(CommandEventArgs e) - { - e.Mobile.SendGump(new TownCrierGump(e.Mobile, Instance)); - } - } - - public class TownCrierEntry - { - public TownCrierEntry(string[] lines, TimeSpan duration) - { - Lines = lines; - - if (duration < TimeSpan.Zero) - duration = TimeSpan.Zero; - else if (duration > TimeSpan.FromDays(365.0)) - duration = TimeSpan.FromDays(365.0); - - ExpireTime = DateTime.UtcNow + duration; - } - - public string[] Lines { get; } - - public DateTime ExpireTime { get; } - - public bool Expired => DateTime.UtcNow >= ExpireTime; - } - - public class TownCrierDurationPrompt : Prompt - { - private readonly ITownCrierEntryList m_Owner; - - public TownCrierDurationPrompt(ITownCrierEntryList owner) => m_Owner = owner; - - public override void OnResponse(Mobile from, string text) - { - if (!TimeSpan.TryParse(text, out TimeSpan ts)) - { - from.SendMessage("Value was not properly formatted. Use: "); - from.SendGump(new TownCrierGump(from, m_Owner)); - return; - } - - if (ts < TimeSpan.Zero) - ts = TimeSpan.Zero; - - from.SendMessage("Duration set to: {0}", ts); - from.SendMessage("Enter the first line to shout:"); - - from.Prompt = new TownCrierLinesPrompt(m_Owner, null, new List(), ts); - } - - public override void OnCancel(Mobile from) - { - from.SendLocalizedMessage(502980); // Message entry cancelled. - from.SendGump(new TownCrierGump(from, m_Owner)); - } - } - - public class TownCrierLinesPrompt : Prompt - { - private readonly TimeSpan m_Duration; - private readonly TownCrierEntry m_Entry; - private readonly List m_Lines; - private readonly ITownCrierEntryList m_Owner; - - public TownCrierLinesPrompt(ITownCrierEntryList owner, TownCrierEntry entry, List lines, TimeSpan duration) - { - m_Owner = owner; - m_Entry = entry; - m_Lines = lines; - m_Duration = duration; - } - - public override void OnResponse(Mobile from, string text) - { - m_Lines.Add(text); - - from.SendMessage("Enter the next line to shout, or press if the message is finished."); - from.Prompt = new TownCrierLinesPrompt(m_Owner, m_Entry, m_Lines, m_Duration); - } - - public override void OnCancel(Mobile from) - { - if (m_Entry != null) - m_Owner.RemoveEntry(m_Entry); - - if (m_Lines.Count > 0) - { - m_Owner.AddEntry(m_Lines.ToArray(), m_Duration); - from.SendMessage("Message has been set."); - } - else - { - if (m_Entry != null) - from.SendMessage("Message deleted."); - else - from.SendLocalizedMessage(502980); // Message entry cancelled. - } - - from.SendGump(new TownCrierGump(from, m_Owner)); - } - } - - public class TownCrierGump : Gump - { - private readonly Mobile m_From; - private readonly ITownCrierEntryList m_Owner; - - public TownCrierGump(Mobile from, ITownCrierEntryList owner) : base(50, 50) - { - m_From = from; - m_Owner = owner; - - from.CloseGump(); - - AddPage(0); - - List entries = owner.Entries; - - owner.GetRandomEntry(); // force expiration checks - - int count = entries?.Count ?? 0; - - AddImageTiled(0, 0, 300, 38 + (count == 0 ? 20 : count * 85), 0xA40); - AddAlphaRegion(1, 1, 298, 36 + (count == 0 ? 20 : count * 85)); - - AddHtml(8, 8, 300 - 8 - 30, 20, "
TOWN CRIER MESSAGES
"); - - AddButton(300 - 8 - 30, 8, 0xFAB, 0xFAD, 1); - - if (count == 0) - AddHtml(8, 30, 284, 20, "The crier has no news."); - else - for (int i = 0; i < entries.Count; ++i) + public TownCrierEntry GetRandomEntry() { - TownCrierEntry tce = entries[i]; + if (Entries == null || Entries.Count == 0) + return null; - TimeSpan toExpire = tce.ExpireTime - DateTime.UtcNow; + for (var i = Entries.Count - 1; Entries != null && i >= 0; --i) + { + if (i >= Entries.Count) + continue; - if (toExpire < TimeSpan.Zero) - toExpire = TimeSpan.Zero; + var tce = Entries[i]; - StringBuilder sb = new StringBuilder(); + if (tce.Expired) + RemoveEntry(tce); + } - sb.Append("[Expires: "); + return Entries.RandomElement(); + } - if (toExpire.TotalHours >= 1) - { - sb.Append((int)toExpire.TotalHours); - sb.Append(':'); - sb.Append(toExpire.Minutes.ToString("D2")); - } - else - { - sb.Append(toExpire.Minutes); - } + public TownCrierEntry AddEntry(string[] lines, TimeSpan duration) + { + Entries ??= new List(); - sb.Append(':'); - sb.Append(toExpire.Seconds.ToString("D2")); + var tce = new TownCrierEntry(lines, duration); - sb.Append("] "); + Entries.Add(tce); - for (int j = 0; j < tce.Lines.Length; ++j) - { - if (j > 0) - sb.Append("
"); + var instances = TownCrier.Instances; - sb.Append(tce.Lines[j]); - } + for (var i = 0; i < instances.Count; ++i) + instances[i].ForceBeginAutoShout(); - AddHtml(8, 35 + i * 85, 254, 80, sb.ToString(), true, true); + return tce; + } - AddButton(300 - 8 - 26, 35 + i * 85, 0x15E1, 0x15E5, 2 + i); + public void RemoveEntry(TownCrierEntry tce) + { + if (Entries == null) + return; + + Entries.Remove(tce); + + if (Entries.Count == 0) + Entries = null; + } + + public static void Initialize() + { + CommandSystem.Register("TownCriers", AccessLevel.GameMaster, TownCriers_OnCommand); + } + + [Usage("TownCriers")] + [Description("Manages the global town crier list.")] + public static void TownCriers_OnCommand(CommandEventArgs e) + { + e.Mobile.SendGump(new TownCrierGump(e.Mobile, Instance)); } } - public override void OnResponse(NetState sender, RelayInfo info) + public class TownCrierEntry { - if (info.ButtonID == 1) - { - m_From.SendMessage("Enter the duration for the new message. Format: "); - m_From.Prompt = new TownCrierDurationPrompt(m_Owner); - } - else if (info.ButtonID > 1) - { - List entries = m_Owner.Entries; - int index = info.ButtonID - 2; - - if (entries != null && index < entries.Count) + public TownCrierEntry(string[] lines, TimeSpan duration) { - TownCrierEntry tce = entries[index]; - TimeSpan ts = tce.ExpireTime - DateTime.UtcNow; + Lines = lines; - if (ts < TimeSpan.Zero) - ts = TimeSpan.Zero; + if (duration < TimeSpan.Zero) + duration = TimeSpan.Zero; + else if (duration > TimeSpan.FromDays(365.0)) + duration = TimeSpan.FromDays(365.0); - m_From.SendMessage("Editing entry #{0}.", index + 1); - m_From.SendMessage("Enter the first line to shout:"); - m_From.Prompt = new TownCrierLinesPrompt(m_Owner, tce, new List(), ts); + ExpireTime = DateTime.UtcNow + duration; } - } - } - } - public class TownCrier : Mobile, ITownCrierEntryList - { - private Timer m_AutoShoutTimer; - private Timer m_NewsTimer; + public string[] Lines { get; } - [Constructible] - public TownCrier() - { - Instances.Add(this); + public DateTime ExpireTime { get; } - InitStats(100, 100, 25); - - Title = "the town crier"; - Hue = Race.Human.RandomSkinHue(); - - if (!Core.AOS) - NameHue = 0x35; - - if (Female = Utility.RandomBool()) - { - Body = 0x191; - Name = NameList.RandomName("female"); - } - else - { - Body = 0x190; - Name = NameList.RandomName("male"); - } - - AddItem(new FancyShirt(Utility.RandomBlueHue())); - - var skirt = Utility.Random(2) switch - { - 0 => (Item)new Skirt(), - 1 => new Kilt(), - _ => new Kilt() - }; - - skirt.Hue = Utility.RandomGreenHue(); - - AddItem(skirt); - - AddItem(new FeatheredHat(Utility.RandomGreenHue())); - - var boots = Utility.Random(2) switch - { - 0 => (Item)new Boots(), - 1 => new ThighBoots(), - _ => new ThighBoots() - }; - - AddItem(boots); - - Utility.AssignRandomHair(this); + public bool Expired => DateTime.UtcNow >= ExpireTime; } - public TownCrier(Serial serial) : base(serial) + public class TownCrierDurationPrompt : Prompt { - Instances.Add(this); - } + private readonly ITownCrierEntryList m_Owner; - public static List Instances { get; } = new List(); + public TownCrierDurationPrompt(ITownCrierEntryList owner) => m_Owner = owner; - public List Entries { get; private set; } - - public TownCrierEntry GetRandomEntry() - { - if (Entries == null || Entries.Count == 0) - return GlobalTownCrierEntryList.Instance.GetRandomEntry(); - - for (int i = Entries.Count - 1; Entries != null && i >= 0; --i) - { - if (i >= Entries.Count) - continue; - - TownCrierEntry tce = Entries[i]; - - if (tce.Expired) - RemoveEntry(tce); - } - - if (Entries == null || Entries.Count == 0) - return GlobalTownCrierEntryList.Instance.GetRandomEntry(); - - TownCrierEntry entry = GlobalTownCrierEntryList.Instance.GetRandomEntry(); - - return entry ?? (Utility.RandomBool() ? Entries.RandomElement() : null); - } - - public TownCrierEntry AddEntry(string[] lines, TimeSpan duration) - { - Entries ??= new List(); - - TownCrierEntry tce = new TownCrierEntry(lines, duration); - - Entries.Add(tce); - - m_AutoShoutTimer ??= Timer.DelayCall(TimeSpan.FromSeconds(5.0), TimeSpan.FromMinutes(1.0), AutoShout_Callback); - - return tce; - } - - public void RemoveEntry(TownCrierEntry tce) - { - if (Entries == null) - return; - - Entries.Remove(tce); - - if (Entries.Count == 0) - Entries = null; - - if (Entries == null && GlobalTownCrierEntryList.Instance.IsEmpty) - { - m_AutoShoutTimer?.Stop(); - - m_AutoShoutTimer = null; - } - } - - public void ForceBeginAutoShout() - { - m_AutoShoutTimer ??= Timer.DelayCall(TimeSpan.FromSeconds(5.0), TimeSpan.FromMinutes(1.0), AutoShout_Callback); - } - - private void AutoShout_Callback() - { - TownCrierEntry tce = GetRandomEntry(); - - if (tce == null) - { - m_AutoShoutTimer?.Stop(); - - m_AutoShoutTimer = null; - } - else if (m_NewsTimer == null) - { - m_NewsTimer = Timer.DelayCall(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(3.0), - () => ShoutNews_Callback(tce, 0)); - - PublicOverheadMessage(MessageType.Regular, 0x3B2, 502976); // Hear ye! Hear ye! - } - } - - private void ShoutNews_Callback(TownCrierEntry tce, int index) - { - if (index < 0 || index >= tce.Lines.Length) - { - m_NewsTimer?.Stop(); - m_NewsTimer = null; - } - else - { - PublicOverheadMessage(MessageType.Regular, 0x3B2, false, tce.Lines[index]); - } - } - - public override void OnDoubleClick(Mobile from) - { - if (from.AccessLevel >= AccessLevel.GameMaster) - from.SendGump(new TownCrierGump(from, this)); - else - base.OnDoubleClick(from); - } - - public override bool HandlesOnSpeech(Mobile from) => m_NewsTimer == null && from.Alive && InRange(from, 12); - - public override void OnSpeech(SpeechEventArgs e) - { - if (m_NewsTimer == null && e.HasKeyword(0x30) && e.Mobile.Alive && InRange(e.Mobile, 12)) // *news* - { - Direction = GetDirectionTo(e.Mobile); - - TownCrierEntry tce = GetRandomEntry(); - - if (tce == null) + public override void OnResponse(Mobile from, string text) { - PublicOverheadMessage(MessageType.Regular, 0x3B2, 1005643); // I have no news at this time. + if (!TimeSpan.TryParse(text, out var ts)) + { + from.SendMessage("Value was not properly formatted. Use: "); + from.SendGump(new TownCrierGump(from, m_Owner)); + return; + } + + if (ts < TimeSpan.Zero) + ts = TimeSpan.Zero; + + from.SendMessage("Duration set to: {0}", ts); + from.SendMessage("Enter the first line to shout:"); + + from.Prompt = new TownCrierLinesPrompt(m_Owner, null, new List(), ts); } - else + + public override void OnCancel(Mobile from) { - m_NewsTimer = Timer.DelayCall(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(3.0), - () => ShoutNews_Callback(tce, 0)); - - PublicOverheadMessage(MessageType.Regular, 0x3B2, 502978); // Some of the latest news! + from.SendLocalizedMessage(502980); // Message entry cancelled. + from.SendGump(new TownCrierGump(from, m_Owner)); } - } } - public override bool CanBeDamaged() => false; - - public override void OnDelete() + public class TownCrierLinesPrompt : Prompt { - Instances.Remove(this); - base.OnDelete(); + private readonly TimeSpan m_Duration; + private readonly TownCrierEntry m_Entry; + private readonly List m_Lines; + private readonly ITownCrierEntryList m_Owner; + + public TownCrierLinesPrompt(ITownCrierEntryList owner, TownCrierEntry entry, List lines, TimeSpan duration) + { + m_Owner = owner; + m_Entry = entry; + m_Lines = lines; + m_Duration = duration; + } + + public override void OnResponse(Mobile from, string text) + { + m_Lines.Add(text); + + from.SendMessage("Enter the next line to shout, or press if the message is finished."); + from.Prompt = new TownCrierLinesPrompt(m_Owner, m_Entry, m_Lines, m_Duration); + } + + public override void OnCancel(Mobile from) + { + if (m_Entry != null) + m_Owner.RemoveEntry(m_Entry); + + if (m_Lines.Count > 0) + { + m_Owner.AddEntry(m_Lines.ToArray(), m_Duration); + from.SendMessage("Message has been set."); + } + else + { + if (m_Entry != null) + from.SendMessage("Message deleted."); + else + from.SendLocalizedMessage(502980); // Message entry cancelled. + } + + from.SendGump(new TownCrierGump(from, m_Owner)); + } } - public override void Serialize(IGenericWriter writer) + public class TownCrierGump : Gump { - base.Serialize(writer); + private readonly Mobile m_From; + private readonly ITownCrierEntryList m_Owner; - writer.Write(0); // version + public TownCrierGump(Mobile from, ITownCrierEntryList owner) : base(50, 50) + { + m_From = from; + m_Owner = owner; + + from.CloseGump(); + + AddPage(0); + + var entries = owner.Entries; + + owner.GetRandomEntry(); // force expiration checks + + var count = entries?.Count ?? 0; + + AddImageTiled(0, 0, 300, 38 + (count == 0 ? 20 : count * 85), 0xA40); + AddAlphaRegion(1, 1, 298, 36 + (count == 0 ? 20 : count * 85)); + + AddHtml(8, 8, 300 - 8 - 30, 20, "
TOWN CRIER MESSAGES
"); + + AddButton(300 - 8 - 30, 8, 0xFAB, 0xFAD, 1); + + if (count == 0) + AddHtml(8, 30, 284, 20, "The crier has no news."); + else + for (var i = 0; i < entries.Count; ++i) + { + var tce = entries[i]; + + var toExpire = tce.ExpireTime - DateTime.UtcNow; + + if (toExpire < TimeSpan.Zero) + toExpire = TimeSpan.Zero; + + var sb = new StringBuilder(); + + sb.Append("[Expires: "); + + if (toExpire.TotalHours >= 1) + { + sb.Append((int)toExpire.TotalHours); + sb.Append(':'); + sb.Append(toExpire.Minutes.ToString("D2")); + } + else + { + sb.Append(toExpire.Minutes); + } + + sb.Append(':'); + sb.Append(toExpire.Seconds.ToString("D2")); + + sb.Append("] "); + + for (var j = 0; j < tce.Lines.Length; ++j) + { + if (j > 0) + sb.Append("
"); + + sb.Append(tce.Lines[j]); + } + + AddHtml(8, 35 + i * 85, 254, 80, sb.ToString(), true, true); + + AddButton(300 - 8 - 26, 35 + i * 85, 0x15E1, 0x15E5, 2 + i); + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 1) + { + m_From.SendMessage("Enter the duration for the new message. Format: "); + m_From.Prompt = new TownCrierDurationPrompt(m_Owner); + } + else if (info.ButtonID > 1) + { + var entries = m_Owner.Entries; + var index = info.ButtonID - 2; + + if (entries != null && index < entries.Count) + { + var tce = entries[index]; + var ts = tce.ExpireTime - DateTime.UtcNow; + + if (ts < TimeSpan.Zero) + ts = TimeSpan.Zero; + + m_From.SendMessage("Editing entry #{0}.", index + 1); + m_From.SendMessage("Enter the first line to shout:"); + m_From.Prompt = new TownCrierLinesPrompt(m_Owner, tce, new List(), ts); + } + } + } } - public override void Deserialize(IGenericReader reader) + public class TownCrier : Mobile, ITownCrierEntryList { - base.Deserialize(reader); + private Timer m_AutoShoutTimer; + private Timer m_NewsTimer; - int version = reader.ReadInt(); + [Constructible] + public TownCrier() + { + Instances.Add(this); - if (Core.AOS && NameHue == 0x35) - NameHue = -1; + InitStats(100, 100, 25); + + Title = "the town crier"; + Hue = Race.Human.RandomSkinHue(); + + if (!Core.AOS) + NameHue = 0x35; + + if (Female = Utility.RandomBool()) + { + Body = 0x191; + Name = NameList.RandomName("female"); + } + else + { + Body = 0x190; + Name = NameList.RandomName("male"); + } + + AddItem(new FancyShirt(Utility.RandomBlueHue())); + + var skirt = Utility.Random(2) switch + { + 0 => (Item)new Skirt(), + 1 => new Kilt(), + _ => new Kilt() + }; + + skirt.Hue = Utility.RandomGreenHue(); + + AddItem(skirt); + + AddItem(new FeatheredHat(Utility.RandomGreenHue())); + + var boots = Utility.Random(2) switch + { + 0 => (Item)new Boots(), + 1 => new ThighBoots(), + _ => new ThighBoots() + }; + + AddItem(boots); + + Utility.AssignRandomHair(this); + } + + public TownCrier(Serial serial) : base(serial) + { + Instances.Add(this); + } + + public static List Instances { get; } = new List(); + + public List Entries { get; private set; } + + public TownCrierEntry GetRandomEntry() + { + if (Entries == null || Entries.Count == 0) + return GlobalTownCrierEntryList.Instance.GetRandomEntry(); + + for (var i = Entries.Count - 1; Entries != null && i >= 0; --i) + { + if (i >= Entries.Count) + continue; + + var tce = Entries[i]; + + if (tce.Expired) + RemoveEntry(tce); + } + + if (Entries == null || Entries.Count == 0) + return GlobalTownCrierEntryList.Instance.GetRandomEntry(); + + var entry = GlobalTownCrierEntryList.Instance.GetRandomEntry(); + + return entry ?? (Utility.RandomBool() ? Entries.RandomElement() : null); + } + + public TownCrierEntry AddEntry(string[] lines, TimeSpan duration) + { + Entries ??= new List(); + + var tce = new TownCrierEntry(lines, duration); + + Entries.Add(tce); + + m_AutoShoutTimer ??= Timer.DelayCall(TimeSpan.FromSeconds(5.0), TimeSpan.FromMinutes(1.0), AutoShout_Callback); + + return tce; + } + + public void RemoveEntry(TownCrierEntry tce) + { + if (Entries == null) + return; + + Entries.Remove(tce); + + if (Entries.Count == 0) + Entries = null; + + if (Entries == null && GlobalTownCrierEntryList.Instance.IsEmpty) + { + m_AutoShoutTimer?.Stop(); + + m_AutoShoutTimer = null; + } + } + + public void ForceBeginAutoShout() + { + m_AutoShoutTimer ??= Timer.DelayCall(TimeSpan.FromSeconds(5.0), TimeSpan.FromMinutes(1.0), AutoShout_Callback); + } + + private void AutoShout_Callback() + { + var tce = GetRandomEntry(); + + if (tce == null) + { + m_AutoShoutTimer?.Stop(); + + m_AutoShoutTimer = null; + } + else if (m_NewsTimer == null) + { + m_NewsTimer = Timer.DelayCall( + TimeSpan.FromSeconds(1.0), + TimeSpan.FromSeconds(3.0), + () => ShoutNews_Callback(tce, 0) + ); + + PublicOverheadMessage(MessageType.Regular, 0x3B2, 502976); // Hear ye! Hear ye! + } + } + + private void ShoutNews_Callback(TownCrierEntry tce, int index) + { + if (index < 0 || index >= tce.Lines.Length) + { + m_NewsTimer?.Stop(); + m_NewsTimer = null; + } + else + { + PublicOverheadMessage(MessageType.Regular, 0x3B2, false, tce.Lines[index]); + } + } + + public override void OnDoubleClick(Mobile from) + { + if (from.AccessLevel >= AccessLevel.GameMaster) + from.SendGump(new TownCrierGump(from, this)); + else + base.OnDoubleClick(from); + } + + public override bool HandlesOnSpeech(Mobile from) => m_NewsTimer == null && from.Alive && InRange(from, 12); + + public override void OnSpeech(SpeechEventArgs e) + { + if (m_NewsTimer == null && e.HasKeyword(0x30) && e.Mobile.Alive && InRange(e.Mobile, 12)) // *news* + { + Direction = GetDirectionTo(e.Mobile); + + var tce = GetRandomEntry(); + + if (tce == null) + { + PublicOverheadMessage(MessageType.Regular, 0x3B2, 1005643); // I have no news at this time. + } + else + { + m_NewsTimer = Timer.DelayCall( + TimeSpan.FromSeconds(1.0), + TimeSpan.FromSeconds(3.0), + () => ShoutNews_Callback(tce, 0) + ); + + PublicOverheadMessage(MessageType.Regular, 0x3B2, 502978); // Some of the latest news! + } + } + } + + public override bool CanBeDamaged() => false; + + public override void OnDelete() + { + Instances.Remove(this); + base.OnDelete(); + } + + 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 (Core.AOS && NameHue == 0x35) + NameHue = -1; + } } - } } diff --git a/Projects/UOContent/Mobiles/Vendors/AnimalBuy.cs b/Projects/UOContent/Mobiles/Vendors/AnimalBuy.cs index 876415fa1..6517f4053 100644 --- a/Projects/UOContent/Mobiles/Vendors/AnimalBuy.cs +++ b/Projects/UOContent/Mobiles/Vendors/AnimalBuy.cs @@ -2,17 +2,30 @@ using System; namespace Server.Mobiles { - public class AnimalBuyInfo : GenericBuyInfo - { - public AnimalBuyInfo(int controlSlots, Type type, int price, int amount, int itemID, int hue) : this(controlSlots, - null, type, price, amount, itemID, hue) + public class AnimalBuyInfo : GenericBuyInfo { + public AnimalBuyInfo(int controlSlots, Type type, int price, int amount, int itemID, int hue) : this( + controlSlots, + null, + type, + price, + amount, + itemID, + hue + ) + { + } + + public AnimalBuyInfo(int controlSlots, string name, Type type, int price, int amount, int itemID, int hue) : base( + name, + type, + price, + amount, + itemID, + hue + ) => + ControlSlots = controlSlots; + + public override int ControlSlots { get; } } - - public AnimalBuyInfo(int controlSlots, string name, Type type, int price, int amount, int itemID, int hue) : base( - name, type, price, amount, itemID, hue) => - ControlSlots = controlSlots; - - public override int ControlSlots { get; } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/BaseVendor.cs b/Projects/UOContent/Mobiles/Vendors/BaseVendor.cs index 3b78db228..91f46ba9a 100644 --- a/Projects/UOContent/Mobiles/Vendors/BaseVendor.cs +++ b/Projects/UOContent/Mobiles/Vendors/BaseVendor.cs @@ -11,1339 +11,1371 @@ using Server.Regions; namespace Server.Mobiles { - public enum VendorShoeType - { - None, - Shoes, - Boots, - Sandals, - ThighBoots - } - - public abstract class BaseVendor : BaseCreature, IVendor - { - private const int MaxSell = 500; - - private static readonly TimeSpan InventoryDecayTime = TimeSpan.FromHours(1.0); - - private readonly List m_ArmorBuyInfo = new List(); - private readonly List m_ArmorSellInfo = new List(); - - public BaseVendor(string title = null) - : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) + public enum VendorShoeType { - LoadSBInfo(); - - Title = title; - InitBody(); - InitOutfit(); - - // these packs MUST exist, or the client will crash when the packets are sent - Container pack = new Backpack { Layer = Layer.ShopBuy, Movable = false, Visible = false }; - AddItem(pack); - - pack = new Backpack { Layer = Layer.ShopResale, Movable = false, Visible = false }; - AddItem(pack); - - LastRestock = DateTime.UtcNow; + None, + Shoes, + Boots, + Sandals, + ThighBoots } - public BaseVendor(Serial serial) - : base(serial) + public abstract class BaseVendor : BaseCreature, IVendor { - } + private const int MaxSell = 500; - protected abstract List SBInfos { get; } + private static readonly TimeSpan InventoryDecayTime = TimeSpan.FromHours(1.0); - public override bool CanTeach => true; + private readonly List m_ArmorBuyInfo = new List(); + private readonly List m_ArmorSellInfo = new List(); - public override bool BardImmune => true; - - public override bool PlayerRangeSensitive => true; - - public virtual bool IsActiveVendor => true; - public virtual bool IsActiveBuyer => IsActiveVendor; // response to vendor SELL - public virtual bool IsActiveSeller => IsActiveVendor; // response to vendor BUY - - public virtual NpcGuild NpcGuild => NpcGuild.None; - - public override bool IsInvulnerable => true; - - public virtual DateTime NextTrickOrTreat { get; set; } - - public override bool ShowFameTitle => false; - - public Container BuyPack - { - get - { - if (!(FindItemOnLayer(Layer.ShopBuy) is Container pack)) + public BaseVendor(string title = null) + : base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2) { - pack = new Backpack { Layer = Layer.ShopBuy, Visible = false }; - AddItem(pack); + LoadSBInfo(); + + Title = title; + InitBody(); + InitOutfit(); + + // these packs MUST exist, or the client will crash when the packets are sent + Container pack = new Backpack { Layer = Layer.ShopBuy, Movable = false, Visible = false }; + AddItem(pack); + + pack = new Backpack { Layer = Layer.ShopResale, Movable = false, Visible = false }; + AddItem(pack); + + LastRestock = DateTime.UtcNow; } - return pack; - } - } - - public virtual bool IsTokunoVendor => Map == Map.Tokuno; - - public virtual VendorShoeType ShoeType => VendorShoeType.Shoes; - - public DateTime LastRestock { get; set; } - - public virtual TimeSpan RestockDelay => TimeSpan.FromHours(1); - - public virtual void Restock() - { - LastRestock = DateTime.UtcNow; - - IBuyItemInfo[] buyInfo = GetBuyInfo(); - - foreach (IBuyItemInfo bii in buyInfo) - bii.OnRestock(); - } - - public virtual bool OnBuyItems(Mobile buyer, List list) - { - if (!IsActiveSeller) - return false; - - if (!buyer.CheckAlive()) - return false; - - if (!CheckVendorAccess(buyer)) - { - Say(501522); // I shall not treat with scum like thee! - return false; - } - - UpdateBuyInfo(); - - // IBuyItemInfo[] buyInfo = this.GetBuyInfo(); - IShopSellInfo[] info = GetSellInfo(); - int totalCost = 0; - List validBuy = new List(list.Count); - bool bought; - bool fromBank = false; - bool fullPurchase = true; - int controlSlots = buyer.FollowersMax - buyer.Followers; - - foreach (BuyItemResponse buy in list) - { - Serial ser = buy.Serial; - int amount = buy.Amount; - - if (ser.IsItem) + public BaseVendor(Serial serial) + : base(serial) { - Item item = World.FindItem(ser); - - if (item == null) - continue; - - GenericBuyInfo gbi = LookupDisplayObject(item); - - if (gbi != null) - { - ProcessSinglePurchase(buy, gbi, validBuy, ref controlSlots, ref fullPurchase, ref totalCost); - } - else if (item != BuyPack && item.IsChildOf(BuyPack)) - { - if (amount > item.Amount) - amount = item.Amount; - - if (amount <= 0) - continue; - - foreach (IShopSellInfo ssi in info) - if (ssi.IsSellable(item)) - if (ssi.IsResellable(item)) - { - totalCost += ssi.GetBuyPriceFor(item) * amount; - validBuy.Add(buy); - break; - } - } } - else if (ser.IsMobile) + + protected abstract List SBInfos { get; } + + public override bool CanTeach => true; + + public override bool BardImmune => true; + + public override bool PlayerRangeSensitive => true; + + public virtual bool IsActiveVendor => true; + public virtual bool IsActiveBuyer => IsActiveVendor; // response to vendor SELL + public virtual bool IsActiveSeller => IsActiveVendor; // response to vendor BUY + + public virtual NpcGuild NpcGuild => NpcGuild.None; + + public override bool IsInvulnerable => true; + + public virtual DateTime NextTrickOrTreat { get; set; } + + public override bool ShowFameTitle => false; + + public Container BuyPack { - Mobile mob = World.FindMobile(ser); - - if (mob == null) - continue; - - GenericBuyInfo gbi = LookupDisplayObject(mob); - - if (gbi != null) - ProcessSinglePurchase(buy, gbi, validBuy, ref controlSlots, ref fullPurchase, ref totalCost); - } - } // foreach - - if (fullPurchase && validBuy.Count == 0) - SayTo(buyer, 500190); // Thou hast bought nothing! - else if (validBuy.Count == 0) - SayTo(buyer, 500187); // Your order cannot be fulfilled, please try again. - - if (validBuy.Count == 0) - return false; - - bought = buyer.AccessLevel >= AccessLevel.GameMaster; - - Container cont = buyer.Backpack; - if (!bought && cont != null) - { - if (cont.ConsumeTotal(typeof(Gold), totalCost)) - bought = true; - else if (totalCost < 2000) - SayTo(buyer, 500192); // Begging thy pardon, but thou canst not afford that. - } - - if (!bought && totalCost >= 2000) - { - cont = buyer.FindBankNoCreate(); - if (cont?.ConsumeTotal(typeof(Gold), totalCost) == true) - { - bought = true; - fromBank = true; - } - else - { - SayTo(buyer, 500191); // Begging thy pardon, but thy bank account lacks these funds. - } - } - - if (!bought) - return false; - - buyer.PlaySound(0x32); - - cont = buyer.Backpack ?? buyer.BankBox; - - foreach (BuyItemResponse buy in validBuy) - { - Serial ser = buy.Serial; - int amount = buy.Amount; - - if (amount < 1) - continue; - - if (ser.IsItem) - { - Item item = World.FindItem(ser); - - if (item == null) - continue; - - GenericBuyInfo gbi = LookupDisplayObject(item); - - if (gbi != null) - { - ProcessValidPurchase(amount, gbi, buyer, cont); - } - else - { - if (amount > item.Amount) - amount = item.Amount; - - foreach (IShopSellInfo ssi in info) - if (ssi.IsSellable(item)) - if (ssi.IsResellable(item)) - { - Item buyItem; - if (amount >= item.Amount) - buyItem = item; - else - buyItem = LiftItemDupe(item, item.Amount - amount) ?? item; - - if (cont?.TryDropItem(buyer, buyItem, false) != true) - buyItem.MoveToWorld(buyer.Location, buyer.Map); - - break; - } - } - } - else if (ser.IsMobile) - { - Mobile mob = World.FindMobile(ser); - - if (mob == null) - continue; - - GenericBuyInfo gbi = LookupDisplayObject(mob); - - if (gbi != null) - ProcessValidPurchase(amount, gbi, buyer, cont); - } - } // foreach - - if (fullPurchase) - { - if (buyer.AccessLevel >= AccessLevel.GameMaster) - SayTo(buyer, true, "I would not presume to charge thee anything. Here are the goods you requested."); - else if (fromBank) - SayTo(buyer, 1151638, - totalCost - .ToString()); // The total of your purchase is ~1_val~ gold, which has been drawn from your bank account. My thanks for the patronage. - else - SayTo(buyer, 1151639, - totalCost.ToString()); // The total of your purchase is ~1_val~ gold. My thanks for the patronage. - } - else - { - if (buyer.AccessLevel >= AccessLevel.GameMaster) - SayTo(buyer, true, - "I would not presume to charge thee anything. Unfortunately, I could not sell you all the goods you requested."); - else if (fromBank) - SayTo(buyer, true, - "The total of thy purchase is {0} gold, which has been withdrawn from your bank account. My thanks for the patronage. Unfortunately, I could not sell you all the goods you requested.", - totalCost); - else - SayTo(buyer, true, - "The total of thy purchase is {0} gold. My thanks for the patronage. Unfortunately, I could not sell you all the goods you requested.", - totalCost); - } - - return true; - } - - public virtual bool OnSellItems(Mobile seller, List list) - { - if (!IsActiveBuyer) - return false; - - if (!seller.CheckAlive()) - return false; - - if (!CheckVendorAccess(seller)) - { - Say(501522); // I shall not treat with scum like thee! - return false; - } - - seller.PlaySound(0x32); - - IShopSellInfo[] info = GetSellInfo(); - IBuyItemInfo[] buyInfo = GetBuyInfo(); - int GiveGold = 0; - int Sold = 0; - - foreach (SellItemResponse resp in list) - { - if (resp.Item.RootParent != seller || resp.Amount <= 0 || !resp.Item.IsStandardLoot() || - !resp.Item.Movable || (resp.Item is Container container && container.Items.Count != 0)) - continue; - - foreach (IShopSellInfo ssi in info) - if (ssi.IsSellable(resp.Item)) - { - Sold++; - break; - } - } - - if (Sold > MaxSell) - { - SayTo(seller, true, "You may only sell {0} items at a time!", MaxSell); - return false; - } - - if (Sold == 0) return true; - - foreach (SellItemResponse resp in list) - { - if (resp.Item.RootParent != seller || resp.Amount <= 0 || !resp.Item.IsStandardLoot() || - !resp.Item.Movable || (resp.Item is Container container && container.Items.Count != 0)) - continue; - - foreach (IShopSellInfo ssi in info) - if (ssi.IsSellable(resp.Item)) - { - int amount = resp.Amount; - - if (amount > resp.Item.Amount) - amount = resp.Item.Amount; - - if (ssi.IsResellable(resp.Item)) + get { - bool found = false; - - foreach (IBuyItemInfo bii in buyInfo) - if (bii.Restock(resp.Item, amount)) + if (!(FindItemOnLayer(Layer.ShopBuy) is Container pack)) { - resp.Item.Consume(amount); - found = true; - - break; + pack = new Backpack { Layer = Layer.ShopBuy, Visible = false }; + AddItem(pack); } - if (!found) - { - Container cont = BuyPack; + return pack; + } + } - if (amount < resp.Item.Amount) + public virtual bool IsTokunoVendor => Map == Map.Tokuno; + + public virtual VendorShoeType ShoeType => VendorShoeType.Shoes; + + public DateTime LastRestock { get; set; } + + public virtual TimeSpan RestockDelay => TimeSpan.FromHours(1); + + public virtual void Restock() + { + LastRestock = DateTime.UtcNow; + + var buyInfo = GetBuyInfo(); + + foreach (var bii in buyInfo) + bii.OnRestock(); + } + + public virtual bool OnBuyItems(Mobile buyer, List list) + { + if (!IsActiveSeller) + return false; + + if (!buyer.CheckAlive()) + return false; + + if (!CheckVendorAccess(buyer)) + { + Say(501522); // I shall not treat with scum like thee! + return false; + } + + UpdateBuyInfo(); + + // IBuyItemInfo[] buyInfo = this.GetBuyInfo(); + var info = GetSellInfo(); + var totalCost = 0; + var validBuy = new List(list.Count); + bool bought; + var fromBank = false; + var fullPurchase = true; + var controlSlots = buyer.FollowersMax - buyer.Followers; + + foreach (var buy in list) + { + var ser = buy.Serial; + var amount = buy.Amount; + + if (ser.IsItem) { - Item item = LiftItemDupe(resp.Item, resp.Item.Amount - amount); + var item = World.FindItem(ser); - if (item != null) - { - item.SetLastMoved(); - cont.DropItem(item); - } - else - { - resp.Item.SetLastMoved(); - cont.DropItem(resp.Item); - } + if (item == null) + continue; + + var gbi = LookupDisplayObject(item); + + if (gbi != null) + { + ProcessSinglePurchase(buy, gbi, validBuy, ref controlSlots, ref fullPurchase, ref totalCost); + } + else if (item != BuyPack && item.IsChildOf(BuyPack)) + { + if (amount > item.Amount) + amount = item.Amount; + + if (amount <= 0) + continue; + + foreach (var ssi in info) + if (ssi.IsSellable(item)) + if (ssi.IsResellable(item)) + { + totalCost += ssi.GetBuyPriceFor(item) * amount; + validBuy.Add(buy); + break; + } + } + } + else if (ser.IsMobile) + { + var mob = World.FindMobile(ser); + + if (mob == null) + continue; + + var gbi = LookupDisplayObject(mob); + + if (gbi != null) + ProcessSinglePurchase(buy, gbi, validBuy, ref controlSlots, ref fullPurchase, ref totalCost); + } + } // foreach + + if (fullPurchase && validBuy.Count == 0) + SayTo(buyer, 500190); // Thou hast bought nothing! + else if (validBuy.Count == 0) + SayTo(buyer, 500187); // Your order cannot be fulfilled, please try again. + + if (validBuy.Count == 0) + return false; + + bought = buyer.AccessLevel >= AccessLevel.GameMaster; + + var cont = buyer.Backpack; + if (!bought && cont != null) + { + if (cont.ConsumeTotal(typeof(Gold), totalCost)) + bought = true; + else if (totalCost < 2000) + SayTo(buyer, 500192); // Begging thy pardon, but thou canst not afford that. + } + + if (!bought && totalCost >= 2000) + { + cont = buyer.FindBankNoCreate(); + if (cont?.ConsumeTotal(typeof(Gold), totalCost) == true) + { + bought = true; + fromBank = true; } else { - resp.Item.SetLastMoved(); - cont.DropItem(resp.Item); + SayTo(buyer, 500191); // Begging thy pardon, but thy bank account lacks these funds. } - } + } + + if (!bought) + return false; + + buyer.PlaySound(0x32); + + cont = buyer.Backpack ?? buyer.BankBox; + + foreach (var buy in validBuy) + { + var ser = buy.Serial; + var amount = buy.Amount; + + if (amount < 1) + continue; + + if (ser.IsItem) + { + var item = World.FindItem(ser); + + if (item == null) + continue; + + var gbi = LookupDisplayObject(item); + + if (gbi != null) + { + ProcessValidPurchase(amount, gbi, buyer, cont); + } + else + { + if (amount > item.Amount) + amount = item.Amount; + + foreach (var ssi in info) + if (ssi.IsSellable(item)) + if (ssi.IsResellable(item)) + { + Item buyItem; + if (amount >= item.Amount) + buyItem = item; + else + buyItem = LiftItemDupe(item, item.Amount - amount) ?? item; + + if (cont?.TryDropItem(buyer, buyItem, false) != true) + buyItem.MoveToWorld(buyer.Location, buyer.Map); + + break; + } + } + } + else if (ser.IsMobile) + { + var mob = World.FindMobile(ser); + + if (mob == null) + continue; + + var gbi = LookupDisplayObject(mob); + + if (gbi != null) + ProcessValidPurchase(amount, gbi, buyer, cont); + } + } // foreach + + if (fullPurchase) + { + if (buyer.AccessLevel >= AccessLevel.GameMaster) + SayTo(buyer, true, "I would not presume to charge thee anything. Here are the goods you requested."); + else if (fromBank) + SayTo( + buyer, + 1151638, + totalCost + .ToString() + ); // The total of your purchase is ~1_val~ gold, which has been drawn from your bank account. My thanks for the patronage. + else + SayTo( + buyer, + 1151639, + totalCost.ToString() + ); // The total of your purchase is ~1_val~ gold. My thanks for the patronage. } else { - if (amount < resp.Item.Amount) - resp.Item.Amount -= amount; - else - resp.Item.Delete(); + if (buyer.AccessLevel >= AccessLevel.GameMaster) + SayTo( + buyer, + true, + "I would not presume to charge thee anything. Unfortunately, I could not sell you all the goods you requested." + ); + else if (fromBank) + SayTo( + buyer, + true, + "The total of thy purchase is {0} gold, which has been withdrawn from your bank account. My thanks for the patronage. Unfortunately, I could not sell you all the goods you requested.", + totalCost + ); + else + SayTo( + buyer, + true, + "The total of thy purchase is {0} gold. My thanks for the patronage. Unfortunately, I could not sell you all the goods you requested.", + totalCost + ); } - GiveGold += ssi.GetSellPriceFor(resp.Item) * amount; - break; - } - } - - if (GiveGold > 0) - { - while (GiveGold > 60000) - { - seller.AddToBackpack(new Gold(60000)); - GiveGold -= 60000; + return true; } - seller.AddToBackpack(new Gold(GiveGold)); - - seller.PlaySound(0x0037); // Gold dropping sound - - if (SupportsBulkOrders(seller)) + public virtual bool OnSellItems(Mobile seller, List list) { - Item bulkOrder = CreateBulkOrder(seller, false); + if (!IsActiveBuyer) + return false; - if (bulkOrder is LargeBOD largeBod) - seller.SendGump(new LargeBODAcceptGump(seller, largeBod)); - else if (bulkOrder is SmallBOD smallBod) - seller.SendGump(new SmallBODAcceptGump(seller, smallBod)); - } - } - // no cliloc for this? - // SayTo( seller, true, "Thank you! I bought {0} item{1}. Here is your {2}gp.", Sold, (Sold > 1 ? "s" : ""), GiveGold ); + if (!seller.CheckAlive()) + return false; - return true; - } - - public virtual bool IsValidBulkOrder(Item item) => false; - - public virtual Item CreateBulkOrder(Mobile from, bool fromContextMenu) => null; - - public virtual bool SupportsBulkOrders(Mobile from) => false; - - public virtual TimeSpan GetNextBulkOrder(Mobile from) => TimeSpan.Zero; - - public virtual void OnSuccessfulBulkOrderReceive(Mobile from) - { - } - - public abstract void InitSBInfo(); - - protected void LoadSBInfo() - { - LastRestock = DateTime.UtcNow; - - for (int i = 0; i < m_ArmorBuyInfo.Count; ++i) - if (m_ArmorBuyInfo[i] is GenericBuyInfo buy) - buy.DeleteDisplayEntity(); - - SBInfos.Clear(); - - InitSBInfo(); - - m_ArmorBuyInfo.Clear(); - m_ArmorSellInfo.Clear(); - - for (int i = 0; i < SBInfos.Count; i++) - { - SBInfo sbInfo = SBInfos[i]; - m_ArmorBuyInfo.AddRange(sbInfo.BuyInfo); - m_ArmorSellInfo.Add(sbInfo.SellInfo); - } - } - - public virtual bool GetGender() => Utility.RandomBool(); - - public virtual void InitBody() - { - InitStats(100, 100, 25); - - SpeechHue = Utility.RandomDyedHue(); - Hue = Race.Human.RandomSkinHue(); - - if (Female = GetGender()) - { - Body = 0x191; - Name = NameList.RandomName("female"); - } - else - { - Body = 0x190; - Name = NameList.RandomName("male"); - } - } - - public virtual int GetRandomHue() - { - return Utility.Random(5) switch - { - 0 => Utility.RandomBlueHue(), - 1 => Utility.RandomGreenHue(), - 2 => Utility.RandomRedHue(), - 3 => Utility.RandomYellowHue(), - _ => Utility.RandomNeutralHue() // 4 - }; - } - - public virtual int GetShoeHue() => Utility.RandomDouble() < 0.1 ? 0 : Utility.RandomNeutralHue(); - - public virtual void CheckMorph() - { - if (CheckGargoyle()) - return; - - if (CheckNecromancer()) - return; - - CheckTokuno(); - } - - public virtual bool CheckTokuno() - { - if (Map != Map.Tokuno) - return false; - - NameList n = NameList.GetNameList(Female ? "tokuno female" : "tokuno male"); - - if (!n.ContainsName(Name)) - TurnToTokuno(); - - return true; - } - - public virtual void TurnToTokuno() - { - Name = NameList.RandomName(Female ? "tokuno female" : "tokuno male"); - } - - public virtual bool CheckGargoyle() - { - Map map = Map; - - if (map != Map.Ilshenar) - return false; - - if (!Region.IsPartOf("Gargoyle City")) - return false; - - if (Body != 0x2F6 || (Hue & 0x8000) == 0) - TurnToGargoyle(); - - return true; - } - - public virtual bool CheckNecromancer() - { - Map map = Map; - - if (map != Map.Malas) - return false; - - if (!Region.IsPartOf("Umbra")) - return false; - - if (Hue != 0x83E8) - TurnToNecromancer(); - - return true; - } - - public override void OnAfterSpawn() - { - CheckMorph(); - } - - protected override void OnMapChange(Map oldMap) - { - base.OnMapChange(oldMap); - - CheckMorph(); - - LoadSBInfo(); - } - - public virtual int GetRandomNecromancerHue() - { - return Utility.Random(20) switch - { - 0 => 0, - 1 => 0x4E9, - _ => Utility.RandomList(0x485, 0x497) - }; - } - - public virtual void TurnToNecromancer() - { - for (int i = 0; i < Items.Count; ++i) - { - Item item = Items[i]; - if (item is BaseClothing || item is BaseWeapon || item is BaseArmor || item is BaseTool) - item.Hue = GetRandomNecromancerHue(); - } - - HairHue = 0; - FacialHairHue = 0; - - Hue = 0x83E8; - } - - public virtual void TurnToGargoyle() - { - for (int i = 0; i < Items.Count; ++i) - { - Item item = Items[i]; - - if (item is BaseClothing) - item.Delete(); - } - - HairItemID = 0; - FacialHairItemID = 0; - - Body = 0x2F6; - Hue = Utility.RandomBrightHue() | 0x8000; - Name = NameList.RandomName("gargoyle vendor"); - - CapitalizeTitle(); - } - - public virtual void CapitalizeTitle() - { - string title = Title; - - if (title == null) - return; - - string[] split = title.Split(' '); - - for (int i = 0; i < split.Length; ++i) - { - if (Insensitive.Equals(split[i], "the")) - continue; - - if (split[i].Length > 1) - split[i] = char.ToUpper(split[i][0]) + split[i].Substring(1); - else if (split[i].Length > 0) - split[i] = char.ToUpper(split[i][0]).ToString(); - } - - Title = string.Join(" ", split); - } - - public virtual int GetHairHue() => Race.RandomHairHue(); - - public virtual void InitOutfit() - { - AddItem( - Utility.Random(3) switch - { - 0 => new FancyShirt(GetRandomHue()), - 1 => new Doublet(GetRandomHue()), - _ => new Shirt(GetRandomHue()) // 2 - } - ); - - AddItem( - ShoeType switch - { - VendorShoeType.Shoes => new Shoes(GetShoeHue()), - VendorShoeType.Boots => new Boots(GetShoeHue()), - VendorShoeType.Sandals => new Sandals(GetShoeHue()), - _ => new ThighBoots(GetShoeHue()) // ThighBoots - } - ); - - int hairHue = GetHairHue(); - - Utility.AssignRandomHair(this, hairHue); - Utility.AssignRandomFacialHair(this, hairHue); - - if (Female) - AddItem( - Utility.Random(6) switch - { - 0 => new ShortPants(GetRandomHue()), - 1 => new Kilt(GetRandomHue()), - 2 => new Kilt(GetRandomHue()), - _ => new Skirt(GetRandomHue()) // 3-5 - } - ); - else - AddItem(Utility.RandomBool() ? (Item)new LongPants(GetRandomHue()) : new ShortPants(GetRandomHue())); - - PackGold(100, 200); - } - - public virtual void VendorBuy(Mobile from) - { - if (!IsActiveSeller) - return; - - if (!from.CheckAlive()) - return; - - if (!CheckVendorAccess(from)) - { - Say(501522); // I shall not treat with scum like thee! - return; - } - - if (DateTime.UtcNow - LastRestock > RestockDelay) - Restock(); - - UpdateBuyInfo(); - - IBuyItemInfo[] buyInfo = GetBuyInfo(); - IShopSellInfo[] sellInfo = GetSellInfo(); - - List list = new List(buyInfo.Length); - Container cont = BuyPack; - - List opls = new List(); - - for (int idx = 0; idx < buyInfo.Length; idx++) - { - IBuyItemInfo buyItem = buyInfo[idx]; - - if (buyItem.Amount <= 0 || list.Count >= 250) - continue; - - if (!(buyItem is GenericBuyInfo gbi)) - return; - - IEntity disp = gbi.GetDisplayEntity(); - - list.Add(new BuyItemState(buyItem.Name, cont.Serial, disp?.Serial ?? (Serial)0x7FC0FFEE, buyItem.Price, - buyItem.Amount, buyItem.ItemID, buyItem.Hue)); - - if (disp is Item item) - opls.Add(item.PropertyList); - else if (disp is Mobile mobile) - opls.Add(mobile.PropertyList); - } - - List playerItems = cont.Items; - - for (int i = playerItems.Count - 1; i >= 0; --i) - { - if (i >= playerItems.Count) - continue; - - Item item = playerItems[i]; - - if (item.LastMoved + InventoryDecayTime <= DateTime.UtcNow) - item.Delete(); - } - - for (int i = 0; i < playerItems.Count; ++i) - { - Item item = playerItems[i]; - - int price = 0; - string name = null; - - foreach (IShopSellInfo ssi in sellInfo) - if (ssi.IsSellable(item)) - { - price = ssi.GetBuyPriceFor(item); - name = ssi.GetNameFor(item); - break; - } - - if (name != null && list.Count < 250) - { - list.Add(new BuyItemState(name, cont.Serial, item.Serial, price, item.Amount, item.ItemID, item.Hue)); - opls.Add(item.PropertyList); - } - } - - // one (not all) of the packets uses a byte to describe number of items in the list. Osi = dumb. - // if (list.Count > 255) - // Console.WriteLine( "Vendor Warning: Vendor {0} has more than 255 buy items, may cause client errors!", this ); - - if (list.Count <= 0) - return; - - list.Sort(new BuyItemStateComparer()); - - SendPacksTo(from); - - NetState ns = from.NetState; - - if (ns == null) - return; - - if (ns.ContainerGridLines) - from.Send(new VendorBuyContent6017(list)); - else - from.Send(new VendorBuyContent(list)); - - from.Send(new VendorBuyList(this, list)); - - if (ns.HighSeas) - from.Send(new DisplayBuyListHS(this)); - else - from.Send(new DisplayBuyList(this)); - - from.Send(new MobileStatusExtended(from)); // make sure their gold amount is sent - - for (int i = 0; i < opls.Count; ++i) - from.Send(opls[i]); - - SayTo(from, 500186); // Greetings. Have a look around. - } - - public virtual void SendPacksTo(Mobile from) - { - Item pack = FindItemOnLayer(Layer.ShopBuy); - - if (pack == null) - { - pack = new Backpack { Layer = Layer.ShopBuy, Movable = false, Visible = false }; - AddItem(pack); - } - - from.Send(new EquipUpdate(pack)); - - pack = FindItemOnLayer(Layer.ShopSell); - - if (pack != null) - from.Send(new EquipUpdate(pack)); - - pack = FindItemOnLayer(Layer.ShopResale); - - if (pack == null) - { - pack = new Backpack { Layer = Layer.ShopResale, Movable = false, Visible = false }; - AddItem(pack); - } - - from.Send(new EquipUpdate(pack)); - } - - public virtual void VendorSell(Mobile from) - { - if (!IsActiveBuyer) - return; - - if (!from.CheckAlive()) - return; - - if (!CheckVendorAccess(from)) - { - Say(501522); // I shall not treat with scum like thee! - return; - } - - Container pack = from.Backpack; - - if (pack == null) - return; - - IShopSellInfo[] info = GetSellInfo(); - - List list = new List(); - - foreach (IShopSellInfo ssi in info) - foreach (Item item in pack.FindItemsByType(ssi.Types)) - { - if (item is Container container && container.Items.Count != 0) - continue; - - if (item.IsStandardLoot() && item.Movable && ssi.IsSellable(item)) - list.Add(new SellItemState(item, ssi.GetSellPriceFor(item), ssi.GetNameFor(item))); - } - - if (list.Count > 0) - { - SendPacksTo(from); - - from.Send(new VendorSellList(this, list)); - } - else - { - Say(true, "You have nothing I would be interested in."); - } - } - - public override bool OnDragDrop(Mobile from, Item dropped) - { - /* TODO: Thou art giving me? and fame/karma for gold gifts */ - - SmallBOD smallBod = dropped as SmallBOD; - LargeBOD largeBod = dropped as LargeBOD; - - if (!(smallBod != null || largeBod != null)) - return base.OnDragDrop(from, dropped); - - PlayerMobile pm = from as PlayerMobile; - - if (Core.ML && pm?.NextBODTurnInTime > DateTime.UtcNow) - { - SayTo(from, 1079976); // You'll have to wait a few seconds while I inspect the last order. - return false; - } - - if (!IsValidBulkOrder(dropped)) - { - SayTo(from, 1045130); // That order is for some other shopkeeper. - return false; - } - - if (smallBod?.Complete == false || largeBod?.Complete == false) - { - SayTo(from, 1045131); // You have not completed the order yet. - return false; - } - - Item reward; - int gold, fame; - - if (smallBod != null) - smallBod.GetRewards(out reward, out gold, out fame); - else - largeBod.GetRewards(out reward, out gold, out fame); - - from.SendSound(0x3D); - - SayTo(from, 1045132); // Thank you so much! Here is a reward for your effort. - - if (reward != null) - from.AddToBackpack(reward); - - if (gold > 1000) - from.AddToBackpack(new BankCheck(gold)); - else if (gold > 0) - from.AddToBackpack(new Gold(gold)); - - Titles.AwardFame(from, fame, true); - - OnSuccessfulBulkOrderReceive(from); - - if (Core.ML && pm != null) - pm.NextBODTurnInTime = DateTime.UtcNow + TimeSpan.FromSeconds(10.0); - - dropped.Delete(); - return true; - } - - private GenericBuyInfo LookupDisplayObject(object obj) - { - IBuyItemInfo[] buyInfo = GetBuyInfo(); - - for (int i = 0; i < buyInfo.Length; ++i) - if (buyInfo[i] is GenericBuyInfo gbi && gbi.GetDisplayEntity() == obj) - return gbi; - - return null; - } - - private void ProcessSinglePurchase(BuyItemResponse buy, IBuyItemInfo bii, List validBuy, - ref int controlSlots, ref bool fullPurchase, ref int totalCost) - { - int amount = buy.Amount; - - if (amount > bii.Amount) - amount = bii.Amount; - - if (amount <= 0) - return; - - int slots = bii.ControlSlots * amount; - - if (controlSlots >= slots) - { - controlSlots -= slots; - } - else - { - fullPurchase = false; - return; - } - - totalCost += bii.Price * amount; - validBuy.Add(buy); - } - - private void ProcessValidPurchase(int amount, IBuyItemInfo bii, Mobile buyer, Container cont) - { - if (amount > bii.Amount) - amount = bii.Amount; - - if (amount < 1) - return; - - bii.Amount -= amount; - - IEntity o = bii.GetEntity(); - - if (o is Item item) - { - if (item.Stackable) - { - item.Amount = amount; - - if (cont?.TryDropItem(buyer, item, false) != true) - item.MoveToWorld(buyer.Location, buyer.Map); - } - else - { - item.Amount = 1; - - if (cont?.TryDropItem(buyer, item, false) != true) - item.MoveToWorld(buyer.Location, buyer.Map); - - for (int i = 1; i < amount; i++) - if (bii.GetEntity() is Item newItem) + if (!CheckVendorAccess(seller)) { - newItem.Amount = 1; - - if (cont?.TryDropItem(buyer, newItem, false) != true) - newItem.MoveToWorld(buyer.Location, buyer.Map); + Say(501522); // I shall not treat with scum like thee! + return false; } - } - } - else if (o is Mobile m) - { - m.Direction = (Direction)Utility.Random(8); - m.MoveToWorld(buyer.Location, buyer.Map); - m.PlaySound(m.GetIdleSound()); - if (m is BaseCreature bc) - { - bc.SetControlMaster(buyer); - bc.ControlOrder = OrderType.Stop; - } + seller.PlaySound(0x32); - for (int i = 1; i < amount; ++i) - if (bii.GetEntity() is Mobile newMobile) - { - newMobile.Direction = (Direction)Utility.Random(8); - newMobile.MoveToWorld(buyer.Location, buyer.Map); + var info = GetSellInfo(); + var buyInfo = GetBuyInfo(); + var GiveGold = 0; + var Sold = 0; - if (newMobile is BaseCreature newBc) + foreach (var resp in list) { - newBc.SetControlMaster(buyer); - newBc.ControlOrder = OrderType.Stop; - } - } - } - } + if (resp.Item.RootParent != seller || resp.Amount <= 0 || !resp.Item.IsStandardLoot() || + !resp.Item.Movable || resp.Item is Container container && container.Items.Count != 0) + continue; - public virtual bool CheckVendorAccess(Mobile from) => - Region.GetRegion()?.CheckVendorAccess(this, from) != false || - (Region != from.Region && from.Region.GetRegion()?.CheckVendorAccess(this, from) != false); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - List sbInfos = SBInfos; - - for (int i = 0; sbInfos != null && i < sbInfos.Count; ++i) - { - SBInfo sbInfo = sbInfos[i]; - List buyInfo = sbInfo.BuyInfo; - - for (int j = 0; buyInfo != null && j < buyInfo.Count; ++j) - { - GenericBuyInfo gbi = buyInfo[j]; - - int maxAmount = gbi.MaxAmount; - - var doubled = maxAmount switch - { - 40 => 1, - 80 => 2, - 160 => 3, - 320 => 4, - 640 => 5, - 999 => 6, - _ => 0 - }; - - if (doubled > 0) - { - writer.WriteEncodedInt(1 + j * sbInfos.Count + i); - writer.WriteEncodedInt(doubled); - } - } - } - - writer.WriteEncodedInt(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - LoadSBInfo(); - - List sbInfos = SBInfos; - - switch (version) - { - case 1: - { - int index; - - while ((index = reader.ReadEncodedInt()) > 0) - { - int doubled = reader.ReadEncodedInt(); - - if (sbInfos != null) - { - index -= 1; - int sbInfoIndex = index % sbInfos.Count; - int buyInfoIndex = index / sbInfos.Count; - - if (sbInfoIndex >= 0 && sbInfoIndex < sbInfos.Count) - { - SBInfo sbInfo = sbInfos[sbInfoIndex]; - List buyInfo = sbInfo.BuyInfo; - - if (buyInfo != null && buyInfoIndex >= 0 && buyInfoIndex < buyInfo.Count) - { - GenericBuyInfo gbi = buyInfo[buyInfoIndex]; - - var amount = doubled switch + foreach (var ssi in info) + if (ssi.IsSellable(resp.Item)) { - 1 => 40, - 2 => 80, - 3 => 160, - 4 => 320, - 5 => 640, - 6 => 999, - _ => 20 + Sold++; + break; + } + } + + if (Sold > MaxSell) + { + SayTo(seller, true, "You may only sell {0} items at a time!", MaxSell); + return false; + } + + if (Sold == 0) return true; + + foreach (var resp in list) + { + if (resp.Item.RootParent != seller || resp.Amount <= 0 || !resp.Item.IsStandardLoot() || + !resp.Item.Movable || resp.Item is Container container && container.Items.Count != 0) + continue; + + foreach (var ssi in info) + if (ssi.IsSellable(resp.Item)) + { + var amount = resp.Amount; + + if (amount > resp.Item.Amount) + amount = resp.Item.Amount; + + if (ssi.IsResellable(resp.Item)) + { + var found = false; + + foreach (var bii in buyInfo) + if (bii.Restock(resp.Item, amount)) + { + resp.Item.Consume(amount); + found = true; + + break; + } + + if (!found) + { + var cont = BuyPack; + + if (amount < resp.Item.Amount) + { + var item = LiftItemDupe(resp.Item, resp.Item.Amount - amount); + + if (item != null) + { + item.SetLastMoved(); + cont.DropItem(item); + } + else + { + resp.Item.SetLastMoved(); + cont.DropItem(resp.Item); + } + } + else + { + resp.Item.SetLastMoved(); + cont.DropItem(resp.Item); + } + } + } + else + { + if (amount < resp.Item.Amount) + resp.Item.Amount -= amount; + else + resp.Item.Delete(); + } + + GiveGold += ssi.GetSellPriceFor(resp.Item) * amount; + break; + } + } + + if (GiveGold > 0) + { + while (GiveGold > 60000) + { + seller.AddToBackpack(new Gold(60000)); + GiveGold -= 60000; + } + + seller.AddToBackpack(new Gold(GiveGold)); + + seller.PlaySound(0x0037); // Gold dropping sound + + if (SupportsBulkOrders(seller)) + { + var bulkOrder = CreateBulkOrder(seller, false); + + if (bulkOrder is LargeBOD largeBod) + seller.SendGump(new LargeBODAcceptGump(seller, largeBod)); + else if (bulkOrder is SmallBOD smallBod) + seller.SendGump(new SmallBODAcceptGump(seller, smallBod)); + } + } + // no cliloc for this? + // SayTo( seller, true, "Thank you! I bought {0} item{1}. Here is your {2}gp.", Sold, (Sold > 1 ? "s" : ""), GiveGold ); + + return true; + } + + public virtual bool IsValidBulkOrder(Item item) => false; + + public virtual Item CreateBulkOrder(Mobile from, bool fromContextMenu) => null; + + public virtual bool SupportsBulkOrders(Mobile from) => false; + + public virtual TimeSpan GetNextBulkOrder(Mobile from) => TimeSpan.Zero; + + public virtual void OnSuccessfulBulkOrderReceive(Mobile from) + { + } + + public abstract void InitSBInfo(); + + protected void LoadSBInfo() + { + LastRestock = DateTime.UtcNow; + + for (var i = 0; i < m_ArmorBuyInfo.Count; ++i) + if (m_ArmorBuyInfo[i] is GenericBuyInfo buy) + buy.DeleteDisplayEntity(); + + SBInfos.Clear(); + + InitSBInfo(); + + m_ArmorBuyInfo.Clear(); + m_ArmorSellInfo.Clear(); + + for (var i = 0; i < SBInfos.Count; i++) + { + var sbInfo = SBInfos[i]; + m_ArmorBuyInfo.AddRange(sbInfo.BuyInfo); + m_ArmorSellInfo.Add(sbInfo.SellInfo); + } + } + + public virtual bool GetGender() => Utility.RandomBool(); + + public virtual void InitBody() + { + InitStats(100, 100, 25); + + SpeechHue = Utility.RandomDyedHue(); + Hue = Race.Human.RandomSkinHue(); + + if (Female = GetGender()) + { + Body = 0x191; + Name = NameList.RandomName("female"); + } + else + { + Body = 0x190; + Name = NameList.RandomName("male"); + } + } + + public virtual int GetRandomHue() + { + return Utility.Random(5) switch + { + 0 => Utility.RandomBlueHue(), + 1 => Utility.RandomGreenHue(), + 2 => Utility.RandomRedHue(), + 3 => Utility.RandomYellowHue(), + _ => Utility.RandomNeutralHue() // 4 + }; + } + + public virtual int GetShoeHue() => Utility.RandomDouble() < 0.1 ? 0 : Utility.RandomNeutralHue(); + + public virtual void CheckMorph() + { + if (CheckGargoyle()) + return; + + if (CheckNecromancer()) + return; + + CheckTokuno(); + } + + public virtual bool CheckTokuno() + { + if (Map != Map.Tokuno) + return false; + + var n = NameList.GetNameList(Female ? "tokuno female" : "tokuno male"); + + if (!n.ContainsName(Name)) + TurnToTokuno(); + + return true; + } + + public virtual void TurnToTokuno() + { + Name = NameList.RandomName(Female ? "tokuno female" : "tokuno male"); + } + + public virtual bool CheckGargoyle() + { + var map = Map; + + if (map != Map.Ilshenar) + return false; + + if (!Region.IsPartOf("Gargoyle City")) + return false; + + if (Body != 0x2F6 || (Hue & 0x8000) == 0) + TurnToGargoyle(); + + return true; + } + + public virtual bool CheckNecromancer() + { + var map = Map; + + if (map != Map.Malas) + return false; + + if (!Region.IsPartOf("Umbra")) + return false; + + if (Hue != 0x83E8) + TurnToNecromancer(); + + return true; + } + + public override void OnAfterSpawn() + { + CheckMorph(); + } + + protected override void OnMapChange(Map oldMap) + { + base.OnMapChange(oldMap); + + CheckMorph(); + + LoadSBInfo(); + } + + public virtual int GetRandomNecromancerHue() + { + return Utility.Random(20) switch + { + 0 => 0, + 1 => 0x4E9, + _ => Utility.RandomList(0x485, 0x497) + }; + } + + public virtual void TurnToNecromancer() + { + for (var i = 0; i < Items.Count; ++i) + { + var item = Items[i]; + if (item is BaseClothing || item is BaseWeapon || item is BaseArmor || item is BaseTool) + item.Hue = GetRandomNecromancerHue(); + } + + HairHue = 0; + FacialHairHue = 0; + + Hue = 0x83E8; + } + + public virtual void TurnToGargoyle() + { + for (var i = 0; i < Items.Count; ++i) + { + var item = Items[i]; + + if (item is BaseClothing) + item.Delete(); + } + + HairItemID = 0; + FacialHairItemID = 0; + + Body = 0x2F6; + Hue = Utility.RandomBrightHue() | 0x8000; + Name = NameList.RandomName("gargoyle vendor"); + + CapitalizeTitle(); + } + + public virtual void CapitalizeTitle() + { + var title = Title; + + if (title == null) + return; + + var split = title.Split(' '); + + for (var i = 0; i < split.Length; ++i) + { + if (Insensitive.Equals(split[i], "the")) + continue; + + if (split[i].Length > 1) + split[i] = char.ToUpper(split[i][0]) + split[i].Substring(1); + else if (split[i].Length > 0) + split[i] = char.ToUpper(split[i][0]).ToString(); + } + + Title = string.Join(" ", split); + } + + public virtual int GetHairHue() => Race.RandomHairHue(); + + public virtual void InitOutfit() + { + AddItem( + Utility.Random(3) switch + { + 0 => new FancyShirt(GetRandomHue()), + 1 => new Doublet(GetRandomHue()), + _ => new Shirt(GetRandomHue()) // 2 + } + ); + + AddItem( + ShoeType switch + { + VendorShoeType.Shoes => new Shoes(GetShoeHue()), + VendorShoeType.Boots => new Boots(GetShoeHue()), + VendorShoeType.Sandals => new Sandals(GetShoeHue()), + _ => new ThighBoots(GetShoeHue()) // ThighBoots + } + ); + + var hairHue = GetHairHue(); + + Utility.AssignRandomHair(this, hairHue); + Utility.AssignRandomFacialHair(this, hairHue); + + if (Female) + AddItem( + Utility.Random(6) switch + { + 0 => new ShortPants(GetRandomHue()), + 1 => new Kilt(GetRandomHue()), + 2 => new Kilt(GetRandomHue()), + _ => new Skirt(GetRandomHue()) // 3-5 + } + ); + else + AddItem(Utility.RandomBool() ? (Item)new LongPants(GetRandomHue()) : new ShortPants(GetRandomHue())); + + PackGold(100, 200); + } + + public virtual void VendorBuy(Mobile from) + { + if (!IsActiveSeller) + return; + + if (!from.CheckAlive()) + return; + + if (!CheckVendorAccess(from)) + { + Say(501522); // I shall not treat with scum like thee! + return; + } + + if (DateTime.UtcNow - LastRestock > RestockDelay) + Restock(); + + UpdateBuyInfo(); + + var buyInfo = GetBuyInfo(); + var sellInfo = GetSellInfo(); + + var list = new List(buyInfo.Length); + var cont = BuyPack; + + var opls = new List(); + + for (var idx = 0; idx < buyInfo.Length; idx++) + { + var buyItem = buyInfo[idx]; + + if (buyItem.Amount <= 0 || list.Count >= 250) + continue; + + if (!(buyItem is GenericBuyInfo gbi)) + return; + + var disp = gbi.GetDisplayEntity(); + + list.Add( + new BuyItemState( + buyItem.Name, + cont.Serial, + disp?.Serial ?? (Serial)0x7FC0FFEE, + buyItem.Price, + buyItem.Amount, + buyItem.ItemID, + buyItem.Hue + ) + ); + + if (disp is Item item) + opls.Add(item.PropertyList); + else if (disp is Mobile mobile) + opls.Add(mobile.PropertyList); + } + + var playerItems = cont.Items; + + for (var i = playerItems.Count - 1; i >= 0; --i) + { + if (i >= playerItems.Count) + continue; + + var item = playerItems[i]; + + if (item.LastMoved + InventoryDecayTime <= DateTime.UtcNow) + item.Delete(); + } + + for (var i = 0; i < playerItems.Count; ++i) + { + var item = playerItems[i]; + + var price = 0; + string name = null; + + foreach (var ssi in sellInfo) + if (ssi.IsSellable(item)) + { + price = ssi.GetBuyPriceFor(item); + name = ssi.GetNameFor(item); + break; + } + + if (name != null && list.Count < 250) + { + list.Add(new BuyItemState(name, cont.Serial, item.Serial, price, item.Amount, item.ItemID, item.Hue)); + opls.Add(item.PropertyList); + } + } + + // one (not all) of the packets uses a byte to describe number of items in the list. Osi = dumb. + // if (list.Count > 255) + // Console.WriteLine( "Vendor Warning: Vendor {0} has more than 255 buy items, may cause client errors!", this ); + + if (list.Count <= 0) + return; + + list.Sort(new BuyItemStateComparer()); + + SendPacksTo(from); + + var ns = from.NetState; + + if (ns == null) + return; + + if (ns.ContainerGridLines) + from.Send(new VendorBuyContent6017(list)); + else + from.Send(new VendorBuyContent(list)); + + from.Send(new VendorBuyList(this, list)); + + if (ns.HighSeas) + from.Send(new DisplayBuyListHS(this)); + else + from.Send(new DisplayBuyList(this)); + + from.Send(new MobileStatusExtended(from)); // make sure their gold amount is sent + + for (var i = 0; i < opls.Count; ++i) + from.Send(opls[i]); + + SayTo(from, 500186); // Greetings. Have a look around. + } + + public virtual void SendPacksTo(Mobile from) + { + var pack = FindItemOnLayer(Layer.ShopBuy); + + if (pack == null) + { + pack = new Backpack { Layer = Layer.ShopBuy, Movable = false, Visible = false }; + AddItem(pack); + } + + from.Send(new EquipUpdate(pack)); + + pack = FindItemOnLayer(Layer.ShopSell); + + if (pack != null) + from.Send(new EquipUpdate(pack)); + + pack = FindItemOnLayer(Layer.ShopResale); + + if (pack == null) + { + pack = new Backpack { Layer = Layer.ShopResale, Movable = false, Visible = false }; + AddItem(pack); + } + + from.Send(new EquipUpdate(pack)); + } + + public virtual void VendorSell(Mobile from) + { + if (!IsActiveBuyer) + return; + + if (!from.CheckAlive()) + return; + + if (!CheckVendorAccess(from)) + { + Say(501522); // I shall not treat with scum like thee! + return; + } + + var pack = from.Backpack; + + if (pack == null) + return; + + var info = GetSellInfo(); + + var list = new List(); + + foreach (var ssi in info) + foreach (var item in pack.FindItemsByType(ssi.Types)) + { + if (item is Container container && container.Items.Count != 0) + continue; + + if (item.IsStandardLoot() && item.Movable && ssi.IsSellable(item)) + list.Add(new SellItemState(item, ssi.GetSellPriceFor(item), ssi.GetNameFor(item))); + } + + if (list.Count > 0) + { + SendPacksTo(from); + + from.Send(new VendorSellList(this, list)); + } + else + { + Say(true, "You have nothing I would be interested in."); + } + } + + public override bool OnDragDrop(Mobile from, Item dropped) + { + /* TODO: Thou art giving me? and fame/karma for gold gifts */ + + var smallBod = dropped as SmallBOD; + var largeBod = dropped as LargeBOD; + + if (!(smallBod != null || largeBod != null)) + return base.OnDragDrop(from, dropped); + + var pm = from as PlayerMobile; + + if (Core.ML && pm?.NextBODTurnInTime > DateTime.UtcNow) + { + SayTo(from, 1079976); // You'll have to wait a few seconds while I inspect the last order. + return false; + } + + if (!IsValidBulkOrder(dropped)) + { + SayTo(from, 1045130); // That order is for some other shopkeeper. + return false; + } + + if (smallBod?.Complete == false || largeBod?.Complete == false) + { + SayTo(from, 1045131); // You have not completed the order yet. + return false; + } + + Item reward; + int gold, fame; + + if (smallBod != null) + smallBod.GetRewards(out reward, out gold, out fame); + else + largeBod.GetRewards(out reward, out gold, out fame); + + from.SendSound(0x3D); + + SayTo(from, 1045132); // Thank you so much! Here is a reward for your effort. + + if (reward != null) + from.AddToBackpack(reward); + + if (gold > 1000) + from.AddToBackpack(new BankCheck(gold)); + else if (gold > 0) + from.AddToBackpack(new Gold(gold)); + + Titles.AwardFame(from, fame, true); + + OnSuccessfulBulkOrderReceive(from); + + if (Core.ML && pm != null) + pm.NextBODTurnInTime = DateTime.UtcNow + TimeSpan.FromSeconds(10.0); + + dropped.Delete(); + return true; + } + + private GenericBuyInfo LookupDisplayObject(object obj) + { + var buyInfo = GetBuyInfo(); + + for (var i = 0; i < buyInfo.Length; ++i) + if (buyInfo[i] is GenericBuyInfo gbi && gbi.GetDisplayEntity() == obj) + return gbi; + + return null; + } + + private void ProcessSinglePurchase( + BuyItemResponse buy, IBuyItemInfo bii, List validBuy, + ref int controlSlots, ref bool fullPurchase, ref int totalCost + ) + { + var amount = buy.Amount; + + if (amount > bii.Amount) + amount = bii.Amount; + + if (amount <= 0) + return; + + var slots = bii.ControlSlots * amount; + + if (controlSlots >= slots) + { + controlSlots -= slots; + } + else + { + fullPurchase = false; + return; + } + + totalCost += bii.Price * amount; + validBuy.Add(buy); + } + + private void ProcessValidPurchase(int amount, IBuyItemInfo bii, Mobile buyer, Container cont) + { + if (amount > bii.Amount) + amount = bii.Amount; + + if (amount < 1) + return; + + bii.Amount -= amount; + + var o = bii.GetEntity(); + + if (o is Item item) + { + if (item.Stackable) + { + item.Amount = amount; + + if (cont?.TryDropItem(buyer, item, false) != true) + item.MoveToWorld(buyer.Location, buyer.Map); + } + else + { + item.Amount = 1; + + if (cont?.TryDropItem(buyer, item, false) != true) + item.MoveToWorld(buyer.Location, buyer.Map); + + for (var i = 1; i < amount; i++) + if (bii.GetEntity() is Item newItem) + { + newItem.Amount = 1; + + if (cont?.TryDropItem(buyer, newItem, false) != true) + newItem.MoveToWorld(buyer.Location, buyer.Map); + } + } + } + else if (o is Mobile m) + { + m.Direction = (Direction)Utility.Random(8); + m.MoveToWorld(buyer.Location, buyer.Map); + m.PlaySound(m.GetIdleSound()); + + if (m is BaseCreature bc) + { + bc.SetControlMaster(buyer); + bc.ControlOrder = OrderType.Stop; + } + + for (var i = 1; i < amount; ++i) + if (bii.GetEntity() is Mobile newMobile) + { + newMobile.Direction = (Direction)Utility.Random(8); + newMobile.MoveToWorld(buyer.Location, buyer.Map); + + if (newMobile is BaseCreature newBc) + { + newBc.SetControlMaster(buyer); + newBc.ControlOrder = OrderType.Stop; + } + } + } + } + + public virtual bool CheckVendorAccess(Mobile from) => + Region.GetRegion()?.CheckVendorAccess(this, from) != false || + Region != @from.Region && @from.Region.GetRegion()?.CheckVendorAccess(this, @from) != false; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + var sbInfos = SBInfos; + + for (var i = 0; sbInfos != null && i < sbInfos.Count; ++i) + { + var sbInfo = sbInfos[i]; + var buyInfo = sbInfo.BuyInfo; + + for (var j = 0; buyInfo != null && j < buyInfo.Count; ++j) + { + var gbi = buyInfo[j]; + + var maxAmount = gbi.MaxAmount; + + var doubled = maxAmount switch + { + 40 => 1, + 80 => 2, + 160 => 3, + 320 => 4, + 640 => 5, + 999 => 6, + _ => 0 }; - gbi.Amount = gbi.MaxAmount = amount; - } + if (doubled > 0) + { + writer.WriteEncodedInt(1 + j * sbInfos.Count + i); + writer.WriteEncodedInt(doubled); + } } - } } - break; - } - } - - if (IsParagon) - IsParagon = false; - - Timer.DelayCall(CheckMorph); - } - - public override void AddCustomContextEntries(Mobile from, List list) - { - if (from.Alive && IsActiveVendor) - { - if (SupportsBulkOrders(from)) - list.Add(new BulkOrderInfoEntry(from, this)); - - if (IsActiveSeller) - list.Add(new VendorBuyEntry(from, this)); - - if (IsActiveBuyer) - list.Add(new VendorSellEntry(from, this)); - } - - base.AddCustomContextEntries(from, list); - } - - public virtual IShopSellInfo[] GetSellInfo() => m_ArmorSellInfo.ToArray(); - - public virtual IBuyItemInfo[] GetBuyInfo() => m_ArmorBuyInfo.ToArray(); - - private class BulkOrderInfoEntry : ContextMenuEntry - { - private readonly Mobile m_From; - private readonly BaseVendor m_Vendor; - - public BulkOrderInfoEntry(Mobile from, BaseVendor vendor) - : base(6152) - { - m_From = from; - m_Vendor = vendor; - } - - public override void OnClick() - { - if (m_Vendor.SupportsBulkOrders(m_From)) - { - TimeSpan ts = m_Vendor.GetNextBulkOrder(m_From); - - int totalSeconds = (int)ts.TotalSeconds; - int totalHours = (totalSeconds + 3599) / 3600; - int totalMinutes = (totalSeconds + 59) / 60; - - if (Core.SE ? totalMinutes == 0 : totalHours == 0) - { - m_From.SendLocalizedMessage(1049038); // You can get an order now. - - if (Core.AOS) - { - Item bulkOrder = m_Vendor.CreateBulkOrder(m_From, true); - - if (bulkOrder is LargeBOD bod) - m_From.SendGump(new LargeBODAcceptGump(m_From, bod)); - else if (bulkOrder is SmallBOD smallBod) - m_From.SendGump(new SmallBODAcceptGump(m_From, smallBod)); - } - } - else - { - int oldSpeechHue = m_Vendor.SpeechHue; - m_Vendor.SpeechHue = 0x3B2; - - if (Core.SE) - m_Vendor.SayTo(m_From, 1072058, - totalMinutes.ToString()); // An offer may be available in about ~1_minutes~ minutes. - else - m_Vendor.SayTo(m_From, 1049039, - totalHours.ToString()); // An offer may be available in about ~1_hours~ hours. - - m_Vendor.SpeechHue = oldSpeechHue; - } + writer.WriteEncodedInt(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + LoadSBInfo(); + + var sbInfos = SBInfos; + + switch (version) + { + case 1: + { + int index; + + while ((index = reader.ReadEncodedInt()) > 0) + { + var doubled = reader.ReadEncodedInt(); + + if (sbInfos != null) + { + index -= 1; + var sbInfoIndex = index % sbInfos.Count; + var buyInfoIndex = index / sbInfos.Count; + + if (sbInfoIndex >= 0 && sbInfoIndex < sbInfos.Count) + { + var sbInfo = sbInfos[sbInfoIndex]; + var buyInfo = sbInfo.BuyInfo; + + if (buyInfo != null && buyInfoIndex >= 0 && buyInfoIndex < buyInfo.Count) + { + var gbi = buyInfo[buyInfoIndex]; + + var amount = doubled switch + { + 1 => 40, + 2 => 80, + 3 => 160, + 4 => 320, + 5 => 640, + 6 => 999, + _ => 20 + }; + + gbi.Amount = gbi.MaxAmount = amount; + } + } + } + } + + break; + } + } + + if (IsParagon) + IsParagon = false; + + Timer.DelayCall(CheckMorph); + } + + public override void AddCustomContextEntries(Mobile from, List list) + { + if (from.Alive && IsActiveVendor) + { + if (SupportsBulkOrders(from)) + list.Add(new BulkOrderInfoEntry(from, this)); + + if (IsActiveSeller) + list.Add(new VendorBuyEntry(from, this)); + + if (IsActiveBuyer) + list.Add(new VendorSellEntry(from, this)); + } + + base.AddCustomContextEntries(from, list); + } + + public virtual IShopSellInfo[] GetSellInfo() => m_ArmorSellInfo.ToArray(); + + public virtual IBuyItemInfo[] GetBuyInfo() => m_ArmorBuyInfo.ToArray(); + + public virtual int GetPriceScalar() => 100 + Town.FromRegion(Region)?.Tax ?? 0; + + public void UpdateBuyInfo() + { + var priceScalar = GetPriceScalar(); + + foreach (var info in m_ArmorBuyInfo.ToArray()) + info.PriceScalar = priceScalar; + } + + private class BulkOrderInfoEntry : ContextMenuEntry + { + private readonly Mobile m_From; + private readonly BaseVendor m_Vendor; + + public BulkOrderInfoEntry(Mobile from, BaseVendor vendor) + : base(6152) + { + m_From = from; + m_Vendor = vendor; + } + + public override void OnClick() + { + if (m_Vendor.SupportsBulkOrders(m_From)) + { + var ts = m_Vendor.GetNextBulkOrder(m_From); + + var totalSeconds = (int)ts.TotalSeconds; + var totalHours = (totalSeconds + 3599) / 3600; + var totalMinutes = (totalSeconds + 59) / 60; + + if (Core.SE ? totalMinutes == 0 : totalHours == 0) + { + m_From.SendLocalizedMessage(1049038); // You can get an order now. + + if (Core.AOS) + { + var bulkOrder = m_Vendor.CreateBulkOrder(m_From, true); + + if (bulkOrder is LargeBOD bod) + m_From.SendGump(new LargeBODAcceptGump(m_From, bod)); + else if (bulkOrder is SmallBOD smallBod) + m_From.SendGump(new SmallBODAcceptGump(m_From, smallBod)); + } + } + else + { + var oldSpeechHue = m_Vendor.SpeechHue; + m_Vendor.SpeechHue = 0x3B2; + + if (Core.SE) + m_Vendor.SayTo( + m_From, + 1072058, + totalMinutes.ToString() + ); // An offer may be available in about ~1_minutes~ minutes. + else + m_Vendor.SayTo( + m_From, + 1049039, + totalHours.ToString() + ); // An offer may be available in about ~1_hours~ hours. + + m_Vendor.SpeechHue = oldSpeechHue; + } + } + } } - } } - - public virtual int GetPriceScalar() => 100 + Town.FromRegion(Region)?.Tax ?? 0; - - public void UpdateBuyInfo() - { - int priceScalar = GetPriceScalar(); - - foreach (IBuyItemInfo info in m_ArmorBuyInfo.ToArray()) - info.PriceScalar = priceScalar; - } - } } namespace Server.ContextMenus { - public class VendorBuyEntry : ContextMenuEntry - { - private readonly BaseVendor m_Vendor; - - public VendorBuyEntry(Mobile from, BaseVendor vendor) - : base(6103, 8) + public class VendorBuyEntry : ContextMenuEntry { - m_Vendor = vendor; - Enabled = vendor.CheckVendorAccess(from); + private readonly BaseVendor m_Vendor; + + public VendorBuyEntry(Mobile from, BaseVendor vendor) + : base(6103, 8) + { + m_Vendor = vendor; + Enabled = vendor.CheckVendorAccess(from); + } + + public override void OnClick() + { + m_Vendor.VendorBuy(Owner.From); + } } - public override void OnClick() + public class VendorSellEntry : ContextMenuEntry { - m_Vendor.VendorBuy(Owner.From); - } - } + private readonly BaseVendor m_Vendor; - public class VendorSellEntry : ContextMenuEntry - { - private readonly BaseVendor m_Vendor; + public VendorSellEntry(Mobile from, BaseVendor vendor) + : base(6104, 8) + { + m_Vendor = vendor; + Enabled = vendor.CheckVendorAccess(from); + } - public VendorSellEntry(Mobile from, BaseVendor vendor) - : base(6104, 8) - { - m_Vendor = vendor; - Enabled = vendor.CheckVendorAccess(from); + public override void OnClick() + { + m_Vendor.VendorSell(Owner.From); + } } - - public override void OnClick() - { - m_Vendor.VendorSell(Owner.From); - } - } } namespace Server { - public interface IShopSellInfo - { - // What do we sell? - Type[] Types { get; } + public interface IShopSellInfo + { + // What do we sell? + Type[] Types { get; } - // get display name for an item - string GetNameFor(Item item); + // get display name for an item + string GetNameFor(Item item); - // get price for an item which the player is selling - int GetSellPriceFor(Item item); + // get price for an item which the player is selling + int GetSellPriceFor(Item item); - // get price for an item which the player is buying - int GetBuyPriceFor(Item item); + // get price for an item which the player is buying + int GetBuyPriceFor(Item item); - // can we sell this item to this vendor? - bool IsSellable(Item item); + // can we sell this item to this vendor? + bool IsSellable(Item item); - // does the vendor resell this item? - bool IsResellable(Item item); - } + // does the vendor resell this item? + bool IsResellable(Item item); + } - public interface IBuyItemInfo - { - int ControlSlots { get; } + public interface IBuyItemInfo + { + int ControlSlots { get; } - int PriceScalar { get; set; } + int PriceScalar { get; set; } - // display price of the item - int Price { get; } + // display price of the item + int Price { get; } - // display name of the item - string Name { get; } + // display name of the item + string Name { get; } - // display hue - int Hue { get; } + // display hue + int Hue { get; } - // display id - int ItemID { get; } + // display id + int ItemID { get; } - // amount in stock - int Amount { get; set; } + // amount in stock + int Amount { get; set; } - // max amount in stock - int MaxAmount { get; } + // max amount in stock + int MaxAmount { get; } - // get a new instance of an object (we just bought it) - IEntity GetEntity(); + // get a new instance of an object (we just bought it) + IEntity GetEntity(); - // Attempt to restock with item, (return true if restock successful) - bool Restock(Item item, int amount); + // Attempt to restock with item, (return true if restock successful) + bool Restock(Item item, int amount); - // called when its time for the whole shop to restock - void OnRestock(); - } + // called when its time for the whole shop to restock + void OnRestock(); + } } diff --git a/Projects/UOContent/Mobiles/Vendors/BeverageBuy.cs b/Projects/UOContent/Mobiles/Vendors/BeverageBuy.cs index 9a148401c..b5648579a 100644 --- a/Projects/UOContent/Mobiles/Vendors/BeverageBuy.cs +++ b/Projects/UOContent/Mobiles/Vendors/BeverageBuy.cs @@ -4,29 +4,37 @@ using Server.Utilities; namespace Server.Mobiles { - public class BeverageBuyInfo : GenericBuyInfo - { - private readonly BeverageType m_Content; - - public BeverageBuyInfo(Type type, BeverageType content, int price, int amount, int itemID, int hue) : this(null, - type, content, price, amount, itemID, hue) + public class BeverageBuyInfo : GenericBuyInfo { + private readonly BeverageType m_Content; + + public BeverageBuyInfo(Type type, BeverageType content, int price, int amount, int itemID, int hue) : this( + null, + type, + content, + price, + amount, + itemID, + hue + ) + { + } + + public BeverageBuyInfo(string name, Type type, BeverageType content, int price, int amount, int itemID, int hue) : + base(name, type, price, amount, itemID, hue) + { + m_Content = content; + + if (type == typeof(Pitcher)) + Name = (1048128 + (int)content).ToString(); + else if (type == typeof(BeverageBottle)) + Name = (1042959 + (int)content).ToString(); + else if (type == typeof(Jug)) + Name = (1042965 + (int)content).ToString(); + } + + public override bool CanCacheDisplay => false; + + public override IEntity GetEntity() => (IEntity)ActivatorUtil.CreateInstance(Type, m_Content); } - - public BeverageBuyInfo(string name, Type type, BeverageType content, int price, int amount, int itemID, int hue) : base(name, type, price, amount, itemID, hue) - { - m_Content = content; - - if (type == typeof(Pitcher)) - Name = (1048128 + (int)content).ToString(); - else if (type == typeof(BeverageBottle)) - Name = (1042959 + (int)content).ToString(); - else if (type == typeof(Jug)) - Name = (1042965 + (int)content).ToString(); - } - - public override bool CanCacheDisplay => false; - - public override IEntity GetEntity() => (IEntity)ActivatorUtil.CreateInstance(Type, m_Content); - } } diff --git a/Projects/UOContent/Mobiles/Vendors/GenericBuy.cs b/Projects/UOContent/Mobiles/Vendors/GenericBuy.cs index 0175ca548..74856f263 100644 --- a/Projects/UOContent/Mobiles/Vendors/GenericBuy.cs +++ b/Projects/UOContent/Mobiles/Vendors/GenericBuy.cs @@ -5,265 +5,272 @@ using Server.Utilities; namespace Server.Mobiles { - public class GenericBuyInfo : IBuyItemInfo - { - private int m_Amount; - private IEntity m_DisplayEntity; - - private int m_Price; - - public GenericBuyInfo(Type type, int price, int amount, int itemID, int hue, object[] args = null) : this(null, type, price, - amount, itemID, hue, args) + public class GenericBuyInfo : IBuyItemInfo { - } + private int m_Amount; + private IEntity m_DisplayEntity; - public GenericBuyInfo(string name, Type type, int price, int amount, int itemID, int hue, object[] args = null) - { - Type = type; - m_Price = price; - MaxAmount = m_Amount = amount; - ItemID = itemID; - Hue = hue; - Args = args; + private int m_Price; - Name = name ?? (itemID < 0x4000 ? (1020000 + itemID).ToString() : (1078872 + itemID).ToString()); - } - - public virtual bool CanCacheDisplay => false; - - public Type Type { get; set; } - - public int DefaultPrice { get; private set; } - - public object[] Args { get; set; } - - public virtual int ControlSlots => 0; - - public string Name { get; set; } - - public int PriceScalar - { - get => DefaultPrice; - set => DefaultPrice = value; - } - - public int Price - { - get - { - if (DefaultPrice != 0) + public GenericBuyInfo(Type type, int price, int amount, int itemID, int hue, object[] args = null) : this( + null, + type, + price, + amount, + itemID, + hue, + args + ) { - if (m_Price > 5000000) - { - long price = m_Price; - - price *= DefaultPrice; - price += 50; - price /= 100; - - if (price > int.MaxValue) - price = int.MaxValue; - - return (int)price; - } - - return (m_Price * DefaultPrice + 50) / 100; } - return m_Price; - } - set => m_Price = value; - } - - public int ItemID { get; set; } - - public int Hue { get; set; } - - public int Amount - { - get => m_Amount; - set => m_Amount = Math.Max(value, 0); - } - - public int MaxAmount { get; set; } - - // get a new instance of an object (we just bought it) - public virtual IEntity GetEntity() - { - if (Args == null || Args.Length == 0) - return (IEntity)ActivatorUtil.CreateInstance(Type); - - return (IEntity)ActivatorUtil.CreateInstance(Type, Args); - // return (Item)ActivatorUtil.CreateInstance( m_Type ); - } - - // Attempt to restock with item, (return true if restock successful) - public bool Restock(Item item, int amount) => false; - - public void OnRestock() - { - if (m_Amount <= 0) - { - /* - Core.ML using this vendor system is undefined behavior, so being - as it lends itself to an abusable exploit to cause ingame havok - and the stackable items are not found to be over 20 items, this is - changed until there is a better solution. - */ - - object Obj_Disp = GetDisplayEntity(); - - if (Core.ML && Obj_Disp is Item item && !item.Stackable) - MaxAmount = Math.Min(20, MaxAmount); - else - MaxAmount = Math.Min(999, MaxAmount * 2); - } - else - { - /* NOTE: According to UO.com, the quantity is halved if the item does not reach 0 - * Here we implement differently: the quantity is halved only if less than half - * of the maximum quantity was bought. That is, if more than half is sold, then - * there's clearly a demand and we should not cut down on the stock. - */ - - int halfQuantity = MaxAmount; - - if (halfQuantity >= 999) - halfQuantity = 640; - else if (halfQuantity > 20) - halfQuantity /= 2; - - if (m_Amount >= halfQuantity) - MaxAmount = halfQuantity; - } - - m_Amount = MaxAmount; - } - - private bool IsDeleted(IEntity obj) => obj.Deleted; - - public void DeleteDisplayEntity() - { - if (m_DisplayEntity == null) - return; - - m_DisplayEntity.Delete(); - m_DisplayEntity = null; - } - - public IEntity GetDisplayEntity() - { - if (m_DisplayEntity != null && !IsDeleted(m_DisplayEntity)) - return m_DisplayEntity; - - bool canCache = CanCacheDisplay; - - if (canCache) - m_DisplayEntity = DisplayCache.Cache.Lookup(Type); - - if (m_DisplayEntity == null || IsDeleted(m_DisplayEntity)) - m_DisplayEntity = GetEntity(); - - DisplayCache.Cache.Store(Type, m_DisplayEntity, canCache); - - return m_DisplayEntity; - } - - private class DisplayCache : Container - { - private static DisplayCache m_Cache; - private List m_Mobiles; - - private Dictionary m_Table; - - public DisplayCache() : base(0) - { - m_Table = new Dictionary(); - m_Mobiles = new List(); - } - - public DisplayCache(Serial serial) : base(serial) - { - } - - public static DisplayCache Cache - { - get + public GenericBuyInfo(string name, Type type, int price, int amount, int itemID, int hue, object[] args = null) { - if (m_Cache?.Deleted != false) - m_Cache = new DisplayCache(); + Type = type; + m_Price = price; + MaxAmount = m_Amount = amount; + ItemID = itemID; + Hue = hue; + Args = args; - return m_Cache; + Name = name ?? (itemID < 0x4000 ? (1020000 + itemID).ToString() : (1078872 + itemID).ToString()); } - } - public IEntity Lookup(Type key) - { - m_Table.TryGetValue(key, out IEntity e); - return e; - } + public virtual bool CanCacheDisplay => false; - public void Store(Type key, IEntity obj, bool cache) - { - if (cache) - m_Table[key] = obj; + public Type Type { get; set; } - if (obj is Item item) - AddItem(item); - else if (obj is Mobile mobile) - m_Mobiles.Add(mobile); - } + public int DefaultPrice { get; private set; } - public override void OnAfterDelete() - { - base.OnAfterDelete(); + public object[] Args { get; set; } - for (int i = 0; i < m_Mobiles.Count; ++i) - m_Mobiles[i].Delete(); + public virtual int ControlSlots => 0; - m_Mobiles.Clear(); + public string Name { get; set; } - for (int i = Items.Count - 1; i >= 0; --i) - if (i < Items.Count) - Items[i].Delete(); + public int PriceScalar + { + get => DefaultPrice; + set => DefaultPrice = value; + } - if (m_Cache == this) - m_Cache = null; - } + public int Price + { + get + { + if (DefaultPrice != 0) + { + if (m_Price > 5000000) + { + long price = m_Price; - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + price *= DefaultPrice; + price += 50; + price /= 100; - writer.Write(0); // version + if (price > int.MaxValue) + price = int.MaxValue; - writer.Write(m_Mobiles); - } + return (int)price; + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + return (m_Price * DefaultPrice + 50) / 100; + } - int version = reader.ReadInt(); + return m_Price; + } + set => m_Price = value; + } - m_Mobiles = reader.ReadStrongMobileList(); + public int ItemID { get; set; } - for (int i = 0; i < m_Mobiles.Count; ++i) - m_Mobiles[i].Delete(); + public int Hue { get; set; } - m_Mobiles.Clear(); + public int Amount + { + get => m_Amount; + set => m_Amount = Math.Max(value, 0); + } - for (int i = Items.Count - 1; i >= 0; --i) - if (i < Items.Count) - Items[i].Delete(); + public int MaxAmount { get; set; } - if (m_Cache == null) - m_Cache = this; - else - Delete(); + // get a new instance of an object (we just bought it) + public virtual IEntity GetEntity() + { + if (Args == null || Args.Length == 0) + return (IEntity)ActivatorUtil.CreateInstance(Type); - m_Table = new Dictionary(); - } + return (IEntity)ActivatorUtil.CreateInstance(Type, Args); + // return (Item)ActivatorUtil.CreateInstance( m_Type ); + } + + // Attempt to restock with item, (return true if restock successful) + public bool Restock(Item item, int amount) => false; + + public void OnRestock() + { + if (m_Amount <= 0) + { + /* + Core.ML using this vendor system is undefined behavior, so being + as it lends itself to an abusable exploit to cause ingame havok + and the stackable items are not found to be over 20 items, this is + changed until there is a better solution. + */ + + object Obj_Disp = GetDisplayEntity(); + + if (Core.ML && Obj_Disp is Item item && !item.Stackable) + MaxAmount = Math.Min(20, MaxAmount); + else + MaxAmount = Math.Min(999, MaxAmount * 2); + } + else + { + /* NOTE: According to UO.com, the quantity is halved if the item does not reach 0 + * Here we implement differently: the quantity is halved only if less than half + * of the maximum quantity was bought. That is, if more than half is sold, then + * there's clearly a demand and we should not cut down on the stock. + */ + + var halfQuantity = MaxAmount; + + if (halfQuantity >= 999) + halfQuantity = 640; + else if (halfQuantity > 20) + halfQuantity /= 2; + + if (m_Amount >= halfQuantity) + MaxAmount = halfQuantity; + } + + m_Amount = MaxAmount; + } + + private bool IsDeleted(IEntity obj) => obj.Deleted; + + public void DeleteDisplayEntity() + { + if (m_DisplayEntity == null) + return; + + m_DisplayEntity.Delete(); + m_DisplayEntity = null; + } + + public IEntity GetDisplayEntity() + { + if (m_DisplayEntity != null && !IsDeleted(m_DisplayEntity)) + return m_DisplayEntity; + + var canCache = CanCacheDisplay; + + if (canCache) + m_DisplayEntity = DisplayCache.Cache.Lookup(Type); + + if (m_DisplayEntity == null || IsDeleted(m_DisplayEntity)) + m_DisplayEntity = GetEntity(); + + DisplayCache.Cache.Store(Type, m_DisplayEntity, canCache); + + return m_DisplayEntity; + } + + private class DisplayCache : Container + { + private static DisplayCache m_Cache; + private List m_Mobiles; + + private Dictionary m_Table; + + public DisplayCache() : base(0) + { + m_Table = new Dictionary(); + m_Mobiles = new List(); + } + + public DisplayCache(Serial serial) : base(serial) + { + } + + public static DisplayCache Cache + { + get + { + if (m_Cache?.Deleted != false) + m_Cache = new DisplayCache(); + + return m_Cache; + } + } + + public IEntity Lookup(Type key) + { + m_Table.TryGetValue(key, out var e); + return e; + } + + public void Store(Type key, IEntity obj, bool cache) + { + if (cache) + m_Table[key] = obj; + + if (obj is Item item) + AddItem(item); + else if (obj is Mobile mobile) + m_Mobiles.Add(mobile); + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + for (var i = 0; i < m_Mobiles.Count; ++i) + m_Mobiles[i].Delete(); + + m_Mobiles.Clear(); + + for (var i = Items.Count - 1; i >= 0; --i) + if (i < Items.Count) + Items[i].Delete(); + + if (m_Cache == this) + m_Cache = null; + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Mobiles); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + m_Mobiles = reader.ReadStrongMobileList(); + + for (var i = 0; i < m_Mobiles.Count; ++i) + m_Mobiles[i].Delete(); + + m_Mobiles.Clear(); + + for (var i = Items.Count - 1; i >= 0; --i) + if (i < Items.Count) + Items[i].Delete(); + + if (m_Cache == null) + m_Cache = this; + else + Delete(); + + m_Table = new Dictionary(); + } + } } - } } diff --git a/Projects/UOContent/Mobiles/Vendors/GenericSell.cs b/Projects/UOContent/Mobiles/Vendors/GenericSell.cs index 6c93b535a..e15ec1d7a 100644 --- a/Projects/UOContent/Mobiles/Vendors/GenericSell.cs +++ b/Projects/UOContent/Mobiles/Vendors/GenericSell.cs @@ -4,114 +4,123 @@ using Server.Items; namespace Server.Mobiles { - public class GenericSellInfo : IShopSellInfo - { - private readonly Dictionary m_Table = new Dictionary(); - private Type[] m_Types; - - public void Add(Type type, int price) + public class GenericSellInfo : IShopSellInfo { - m_Table[type] = price; - m_Types = null; - } + private readonly Dictionary m_Table = new Dictionary(); + private Type[] m_Types; - public int GetSellPriceFor(Item item) - { - m_Table.TryGetValue(item.GetType(), out int price); - - if (item is BaseArmor armor) - { - if (armor.Quality == ArmorQuality.Low) - price = (int)(price * 0.60); - else if (armor.Quality == ArmorQuality.Exceptional) - price = (int)(price * 1.25); - - price += 100 * (int)armor.Durability; - - price += 100 * (int)armor.ProtectionLevel; - - if (price < 1) - price = 1; - } - else if (item is BaseWeapon weapon) - { - if (weapon.Quality == WeaponQuality.Low) - price = (int)(price * 0.60); - else if (weapon.Quality == WeaponQuality.Exceptional) - price = (int)(price * 1.25); - - price += 100 * (int)weapon.DurabilityLevel; - - price += 100 * (int)weapon.DamageLevel; - - if (price < 1) - price = 1; - } - else if (item is BaseBeverage bev) - { - int price1 = price, price2 = price; - - if (bev is Pitcher) - { price1 = 3; price2 = 5; } - else if (bev is BeverageBottle) - { price1 = 3; price2 = 3; } - else if (bev is Jug) - { price1 = 6; price2 = 6; } - - if (bev.IsEmpty || bev.Content == BeverageType.Milk) - price = price1; - else - price = price2; - } - - return price; - } - - public int GetBuyPriceFor(Item item) => (int)(1.90 * GetSellPriceFor(item)); - - public Type[] Types - { - get - { - if (m_Types == null) + public int GetSellPriceFor(Item item) { - m_Types = new Type[m_Table.Keys.Count]; - m_Table.Keys.CopyTo(m_Types, 0); + m_Table.TryGetValue(item.GetType(), out var price); + + if (item is BaseArmor armor) + { + if (armor.Quality == ArmorQuality.Low) + price = (int)(price * 0.60); + else if (armor.Quality == ArmorQuality.Exceptional) + price = (int)(price * 1.25); + + price += 100 * (int)armor.Durability; + + price += 100 * (int)armor.ProtectionLevel; + + if (price < 1) + price = 1; + } + else if (item is BaseWeapon weapon) + { + if (weapon.Quality == WeaponQuality.Low) + price = (int)(price * 0.60); + else if (weapon.Quality == WeaponQuality.Exceptional) + price = (int)(price * 1.25); + + price += 100 * (int)weapon.DurabilityLevel; + + price += 100 * (int)weapon.DamageLevel; + + if (price < 1) + price = 1; + } + else if (item is BaseBeverage bev) + { + int price1 = price, price2 = price; + + if (bev is Pitcher) + { + price1 = 3; + price2 = 5; + } + else if (bev is BeverageBottle) + { + price1 = 3; + price2 = 3; + } + else if (bev is Jug) + { + price1 = 6; + price2 = 6; + } + + if (bev.IsEmpty || bev.Content == BeverageType.Milk) + price = price1; + else + price = price2; + } + + return price; } - return m_Types; - } + public int GetBuyPriceFor(Item item) => (int)(1.90 * GetSellPriceFor(item)); + + public Type[] Types + { + get + { + if (m_Types == null) + { + m_Types = new Type[m_Table.Keys.Count]; + m_Table.Keys.CopyTo(m_Types, 0); + } + + return m_Types; + } + } + + public string GetNameFor(Item item) + { + if (item.Name != null) + return item.Name; + return item.LabelNumber.ToString(); + } + + public bool IsSellable(Item item) + { + if (item.Nontransferable) + return false; + + // if (item.Hue != 0) + // return false; + + return IsInList(item.GetType()); + } + + public bool IsResellable(Item item) + { + if (item.Nontransferable) + return false; + + // if (item.Hue != 0) + // return false; + + return IsInList(item.GetType()); + } + + public void Add(Type type, int price) + { + m_Table[type] = price; + m_Types = null; + } + + public bool IsInList(Type type) => m_Table.ContainsKey(type); } - - public string GetNameFor(Item item) - { - if (item.Name != null) - return item.Name; - return item.LabelNumber.ToString(); - } - - public bool IsSellable(Item item) - { - if (item.Nontransferable) - return false; - - // if (item.Hue != 0) - // return false; - - return IsInList(item.GetType()); - } - - public bool IsResellable(Item item) - { - if (item.Nontransferable) - return false; - - // if (item.Hue != 0) - // return false; - - return IsInList(item.GetType()); - } - - public bool IsInList(Type type) => m_Table.ContainsKey(type); - } } diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Alchemist.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Alchemist.cs index b3dc81da4..e9947ceec 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Alchemist.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Alchemist.cs @@ -3,51 +3,51 @@ using Server.Items; namespace Server.Mobiles { - public class Alchemist : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Alchemist() : base("the alchemist") + public class Alchemist : BaseVendor { - SetSkill(SkillName.Alchemy, 85.0, 100.0); - SetSkill(SkillName.TasteID, 65.0, 88.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Alchemist() : base("the alchemist") + { + SetSkill(SkillName.Alchemy, 85.0, 100.0); + SetSkill(SkillName.TasteID, 65.0, 88.0); + } + + public Alchemist(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override NpcGuild NpcGuild => NpcGuild.MagesGuild; + + public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Shoes : VendorShoeType.Sandals; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBAlchemist()); + } + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new Robe(Utility.RandomPinkHue())); + } + + 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 Alchemist(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override NpcGuild NpcGuild => NpcGuild.MagesGuild; - - public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Shoes : VendorShoeType.Sandals; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBAlchemist()); - } - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new Robe(Utility.RandomPinkHue())); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/AnimalTrainer.cs b/Projects/UOContent/Mobiles/Vendors/NPC/AnimalTrainer.cs index c7440e008..435eab8ab 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/AnimalTrainer.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/AnimalTrainer.cs @@ -7,456 +7,459 @@ using Server.Targeting; namespace Server.Mobiles { - public class AnimalTrainer : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public AnimalTrainer() : base("the animal trainer") + public class AnimalTrainer : BaseVendor { - SetSkill(SkillName.AnimalLore, 64.0, 100.0); - SetSkill(SkillName.AnimalTaming, 90.0, 100.0); - SetSkill(SkillName.Veterinary, 65.0, 88.0); - } + private readonly List m_SBInfos = new List(); - public AnimalTrainer(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override VendorShoeType ShoeType => Female ? VendorShoeType.ThighBoots : VendorShoeType.Boots; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBAnimalTrainer()); - } - - public override int GetShoeHue() => 0; - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(Utility.RandomBool() ? new QuarterStaff() : (Item)new ShepherdsCrook()); - } - - public override void AddCustomContextEntries(Mobile from, List list) - { - if (from.Alive) - { - list.Add(new StableEntry(this, from)); - - if (from.Stabled.Count > 0) - list.Add(new ClaimAllEntry(this, from)); - } - - base.AddCustomContextEntries(from, list); - } - - public static int GetMaxStabled(Mobile from) - { - double taming = from.Skills.AnimalTaming.Value; - double anlore = from.Skills.AnimalLore.Value; - double vetern = from.Skills.Veterinary.Value; - double sklsum = taming + anlore + vetern; - - int max; - - if (sklsum >= 240.0) - max = 5; - else if (sklsum >= 200.0) - max = 4; - else if (sklsum >= 160.0) - max = 3; - else - max = 2; - - if (taming >= 100.0) - max += (int)((taming - 90.0) / 10); - - if (anlore >= 100.0) - max += (int)((anlore - 90.0) / 10); - - if (vetern >= 100.0) - max += (int)((vetern - 90.0) / 10); - - return max; - } - - private void CloseClaimList(Mobile from) - { - from.CloseGump(); - } - - public void BeginClaimList(Mobile from) - { - if (Deleted || !from.CheckAlive()) - return; - - List list = new List(); - - for (int i = 0; i < from.Stabled.Count; ++i) - { - BaseCreature pet = from.Stabled[i] as BaseCreature; - - if (pet?.Deleted != false) + [Constructible] + public AnimalTrainer() : base("the animal trainer") { - if (pet != null) - { + SetSkill(SkillName.AnimalLore, 64.0, 100.0); + SetSkill(SkillName.AnimalTaming, 90.0, 100.0); + SetSkill(SkillName.Veterinary, 65.0, 88.0); + } + + public AnimalTrainer(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override VendorShoeType ShoeType => Female ? VendorShoeType.ThighBoots : VendorShoeType.Boots; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBAnimalTrainer()); + } + + public override int GetShoeHue() => 0; + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(Utility.RandomBool() ? new QuarterStaff() : (Item)new ShepherdsCrook()); + } + + public override void AddCustomContextEntries(Mobile from, List list) + { + if (from.Alive) + { + list.Add(new StableEntry(this, from)); + + if (from.Stabled.Count > 0) + list.Add(new ClaimAllEntry(this, from)); + } + + base.AddCustomContextEntries(from, list); + } + + public static int GetMaxStabled(Mobile from) + { + var taming = from.Skills.AnimalTaming.Value; + var anlore = from.Skills.AnimalLore.Value; + var vetern = from.Skills.Veterinary.Value; + var sklsum = taming + anlore + vetern; + + int max; + + if (sklsum >= 240.0) + max = 5; + else if (sklsum >= 200.0) + max = 4; + else if (sklsum >= 160.0) + max = 3; + else + max = 2; + + if (taming >= 100.0) + max += (int)((taming - 90.0) / 10); + + if (anlore >= 100.0) + max += (int)((anlore - 90.0) / 10); + + if (vetern >= 100.0) + max += (int)((vetern - 90.0) / 10); + + return max; + } + + private void CloseClaimList(Mobile from) + { + from.CloseGump(); + } + + public void BeginClaimList(Mobile from) + { + if (Deleted || !from.CheckAlive()) + return; + + var list = new List(); + + for (var i = 0; i < from.Stabled.Count; ++i) + { + var pet = from.Stabled[i] as BaseCreature; + + if (pet?.Deleted != false) + { + if (pet != null) + { + pet.IsStabled = false; + pet.StabledBy = null; + } + + from.Stabled.RemoveAt(i); + --i; + continue; + } + + list.Add(pet); + } + + if (list.Count > 0) + from.SendGump(new ClaimListGump(this, from, list)); + else + SayTo(from, 502671); // But I have no animals stabled with me at the moment! + } + + public void EndClaimList(Mobile from, BaseCreature pet) + { + if (pet?.Deleted != false || from.Map != Map || !from.Stabled.Contains(pet) || !from.CheckAlive()) + return; + + if (!from.InRange(this, 14)) + { + from.SendLocalizedMessage(500446); // That is too far away. + return; + } + + if (CanClaim(from, pet)) + { + DoClaim(from, pet); + + from.Stabled.Remove(pet); + + (from as PlayerMobile)?.AutoStabled.Remove(pet); + } + else + { + SayTo(from, 1049612, pet.Name); // ~1_NAME~ remained in the stables because you have too many followers. + } + } + + public void BeginStable(Mobile from) + { + if (Deleted || !from.CheckAlive()) + return; + + Container bank = from.FindBankNoCreate(); + + if (!(from.Backpack?.GetAmount(typeof(Gold)) >= 30) && + !(bank?.GetAmount(typeof(Gold)) >= 30)) + { + SayTo(from, 1042556); // Thou dost not have enough gold, not even in thy bank account. + } + else + { + /* I charge 30 gold per pet for a real week's stable time. + * I will withdraw it from thy bank account. + * Which animal wouldst thou like to stable here? + */ + from.SendLocalizedMessage(1042558); + + from.Target = new StableTarget(this); + } + } + + public void EndStable(Mobile from, BaseCreature pet) + { + if (Deleted || !from.CheckAlive()) + return; + + if (pet.Body.IsHuman) + { + SayTo(from, 502672); // HA HA HA! Sorry, I am not an inn. + } + else if (!pet.Controlled) + { + SayTo(from, 1048053); // You can't stable that! + } + else if (pet.ControlMaster != from) + { + SayTo(from, 1042562); // You do not own that pet! + } + else if (pet.IsDeadPet) + { + SayTo(from, 1049668); // Living pets only, please. + } + else if (pet.Summoned) + { + SayTo(from, 502673); // I can not stable summoned creatures. + } + /* + else if (pet.Allured) + { + SayTo( from, 1048053 ); // You can't stable that! + } + */ + else if ((pet is PackLlama || pet is PackHorse || pet is Beetle) && pet.Backpack?.Items.Count > 0) + { + SayTo(from, 1042563); // You need to unload your pet. + } + else if (pet.Combatant != null && pet.InRange(pet.Combatant, 12) && pet.Map == pet.Combatant.Map) + { + SayTo(from, 1042564); // I'm sorry. Your pet seems to be busy. + } + else if (from.Stabled.Count >= GetMaxStabled(from)) + { + SayTo(from, 1042565); // You have too many pets in the stables! + } + else + { + Container bank = from.FindBankNoCreate(); + + if (from.Backpack?.ConsumeTotal(typeof(Gold), 30) == true || + bank?.ConsumeTotal(typeof(Gold), 30) == true) + { + pet.ControlTarget = null; + pet.ControlOrder = OrderType.Stay; + pet.Internalize(); + + pet.SetControlMaster(null); + pet.SummonMaster = null; + + pet.IsStabled = true; + pet.StabledBy = from; + + if (Core.SE) + pet.Loyalty = MaxLoyalty; // Wonderfully happy + + from.Stabled.Add(pet); + + SayTo( + from, + Core.AOS + ? 1049677 + : 502679 + ); // [AOS: Your pet has been stabled.] Very well, thy pet is stabled. Thou mayst recover it by saying 'claim' to me. In one real world week, I shall sell it off if it is not claimed! + } + else + { + SayTo(from, 502677); // But thou hast not the funds in thy bank account! + } + } + } + + public void Claim(Mobile from, string petName = null) + { + if (Deleted || !from.CheckAlive()) + return; + + var claimed = false; + var stabled = 0; + + var claimByName = petName != null; + + for (var i = 0; i < from.Stabled.Count; ++i) + { + var pet = from.Stabled[i] as BaseCreature; + + if (pet?.Deleted != false) + { + pet.IsStabled = false; + pet.StabledBy = null; + from.Stabled.RemoveAt(i); + --i; + continue; + } + + ++stabled; + + if (claimByName && !Insensitive.Equals(pet.Name, petName)) + continue; + + if (CanClaim(from, pet)) + { + DoClaim(from, pet); + + from.Stabled.RemoveAt(i); + + (from as PlayerMobile)?.AutoStabled.Remove(pet); + + --i; + + claimed = true; + } + else + { + SayTo(from, 1049612, pet.Name); // ~1_NAME~ remained in the stables because you have too many followers. + } + } + + if (claimed) + SayTo(from, 1042559); // Here you go... and good day to you! + else if (stabled == 0) + SayTo(from, 502671); // But I have no animals stabled with me at the moment! + else if (claimByName) + BeginClaimList(from); + } + + public bool CanClaim(Mobile from, BaseCreature pet) => from.Followers + pet.ControlSlots <= from.FollowersMax; + + private void DoClaim(Mobile from, BaseCreature pet) + { + pet.SetControlMaster(from); + + if (pet.Summoned) + pet.SummonMaster = from; + + pet.ControlTarget = from; + pet.ControlOrder = OrderType.Follow; + + pet.MoveToWorld(from.Location, from.Map); + pet.IsStabled = false; pet.StabledBy = null; - } - from.Stabled.RemoveAt(i); - --i; - continue; + + if (Core.SE) + pet.Loyalty = MaxLoyalty; // Wonderfully Happy } - list.Add(pet); - } + public override bool HandlesOnSpeech(Mobile from) => true; - if (list.Count > 0) - from.SendGump(new ClaimListGump(this, from, list)); - else - SayTo(from, 502671); // But I have no animals stabled with me at the moment! - } - - public void EndClaimList(Mobile from, BaseCreature pet) - { - if (pet?.Deleted != false || from.Map != Map || !from.Stabled.Contains(pet) || !from.CheckAlive()) - return; - - if (!from.InRange(this, 14)) - { - from.SendLocalizedMessage(500446); // That is too far away. - return; - } - - if (CanClaim(from, pet)) - { - DoClaim(from, pet); - - from.Stabled.Remove(pet); - - (from as PlayerMobile)?.AutoStabled.Remove(pet); - } - else - { - SayTo(from, 1049612, pet.Name); // ~1_NAME~ remained in the stables because you have too many followers. - } - } - - public void BeginStable(Mobile from) - { - if (Deleted || !from.CheckAlive()) - return; - - Container bank = from.FindBankNoCreate(); - - if (!(from.Backpack?.GetAmount(typeof(Gold)) >= 30) && - !(bank?.GetAmount(typeof(Gold)) >= 30)) - { - SayTo(from, 1042556); // Thou dost not have enough gold, not even in thy bank account. - } - else - { - /* I charge 30 gold per pet for a real week's stable time. - * I will withdraw it from thy bank account. - * Which animal wouldst thou like to stable here? - */ - from.SendLocalizedMessage(1042558); - - from.Target = new StableTarget(this); - } - } - - public void EndStable(Mobile from, BaseCreature pet) - { - if (Deleted || !from.CheckAlive()) - return; - - if (pet.Body.IsHuman) - { - SayTo(from, 502672); // HA HA HA! Sorry, I am not an inn. - } - else if (!pet.Controlled) - { - SayTo(from, 1048053); // You can't stable that! - } - else if (pet.ControlMaster != from) - { - SayTo(from, 1042562); // You do not own that pet! - } - else if (pet.IsDeadPet) - { - SayTo(from, 1049668); // Living pets only, please. - } - else if (pet.Summoned) - { - SayTo(from, 502673); // I can not stable summoned creatures. - } - /* - else if (pet.Allured) + public override void OnSpeech(SpeechEventArgs e) + { + if (!e.Handled && e.HasKeyword(0x0008)) // *stable* { - SayTo( from, 1048053 ); // You can't stable that! + e.Handled = true; + + CloseClaimList(e.Mobile); + BeginStable(e.Mobile); } - */ - else if ((pet is PackLlama || pet is PackHorse || pet is Beetle) && pet.Backpack?.Items.Count > 0) - { - SayTo(from, 1042563); // You need to unload your pet. - } - else if (pet.Combatant != null && pet.InRange(pet.Combatant, 12) && pet.Map == pet.Combatant.Map) - { - SayTo(from, 1042564); // I'm sorry. Your pet seems to be busy. - } - else if (from.Stabled.Count >= GetMaxStabled(from)) - { - SayTo(from, 1042565); // You have too many pets in the stables! - } - else - { - Container bank = from.FindBankNoCreate(); + else if (!e.Handled && e.HasKeyword(0x0009)) // *claim* + { + e.Handled = true; - if (from.Backpack?.ConsumeTotal(typeof(Gold), 30) == true || - bank?.ConsumeTotal(typeof(Gold), 30) == true) - { - pet.ControlTarget = null; - pet.ControlOrder = OrderType.Stay; - pet.Internalize(); + CloseClaimList(e.Mobile); - pet.SetControlMaster(null); - pet.SummonMaster = null; + var index = e.Speech.IndexOf(' '); - pet.IsStabled = true; - pet.StabledBy = from; - - if (Core.SE) - pet.Loyalty = MaxLoyalty; // Wonderfully happy - - from.Stabled.Add(pet); - - SayTo(from, - Core.AOS - ? 1049677 - : 502679); // [AOS: Your pet has been stabled.] Very well, thy pet is stabled. Thou mayst recover it by saying 'claim' to me. In one real world week, I shall sell it off if it is not claimed! - } - else - { - SayTo(from, 502677); // But thou hast not the funds in thy bank account! - } - } - } - - public void Claim(Mobile from, string petName = null) - { - if (Deleted || !from.CheckAlive()) - return; - - bool claimed = false; - int stabled = 0; - - bool claimByName = petName != null; - - for (int i = 0; i < from.Stabled.Count; ++i) - { - BaseCreature pet = from.Stabled[i] as BaseCreature; - - if (pet?.Deleted != false) - { - pet.IsStabled = false; - pet.StabledBy = null; - from.Stabled.RemoveAt(i); - --i; - continue; + if (index != -1) + Claim(e.Mobile, e.Speech.Substring(index).Trim()); + else + Claim(e.Mobile); + } + else + { + base.OnSpeech(e); + } } - ++stabled; - - if (claimByName && !Insensitive.Equals(pet.Name, petName)) - continue; - - if (CanClaim(from, pet)) + public override void Serialize(IGenericWriter writer) { - DoClaim(from, pet); + base.Serialize(writer); - from.Stabled.RemoveAt(i); - - (from as PlayerMobile)?.AutoStabled.Remove(pet); - - --i; - - claimed = true; + writer.Write(0); // version } - else + + public override void Deserialize(IGenericReader reader) { - SayTo(from, 1049612, pet.Name); // ~1_NAME~ remained in the stables because you have too many followers. + base.Deserialize(reader); + + var version = reader.ReadInt(); } - } - if (claimed) - SayTo(from, 1042559); // Here you go... and good day to you! - else if (stabled == 0) - SayTo(from, 502671); // But I have no animals stabled with me at the moment! - else if (claimByName) - BeginClaimList(from); - } - - public bool CanClaim(Mobile from, BaseCreature pet) => from.Followers + pet.ControlSlots <= from.FollowersMax; - - private void DoClaim(Mobile from, BaseCreature pet) - { - pet.SetControlMaster(from); - - if (pet.Summoned) - pet.SummonMaster = from; - - pet.ControlTarget = from; - pet.ControlOrder = OrderType.Follow; - - pet.MoveToWorld(from.Location, from.Map); - - pet.IsStabled = false; - pet.StabledBy = null; - - if (Core.SE) - pet.Loyalty = MaxLoyalty; // Wonderfully Happy - } - - public override bool HandlesOnSpeech(Mobile from) => true; - - public override void OnSpeech(SpeechEventArgs e) - { - if (!e.Handled && e.HasKeyword(0x0008)) // *stable* - { - e.Handled = true; - - CloseClaimList(e.Mobile); - BeginStable(e.Mobile); - } - else if (!e.Handled && e.HasKeyword(0x0009)) // *claim* - { - e.Handled = true; - - CloseClaimList(e.Mobile); - - int index = e.Speech.IndexOf(' '); - - if (index != -1) - Claim(e.Mobile, e.Speech.Substring(index).Trim()); - else - Claim(e.Mobile); - } - else - { - base.OnSpeech(e); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private class StableEntry : ContextMenuEntry - { - private readonly Mobile m_From; - private readonly AnimalTrainer m_Trainer; - - public StableEntry(AnimalTrainer trainer, Mobile from) : base(6126, 12) - { - m_Trainer = trainer; - m_From = from; - } - - public override void OnClick() - { - m_Trainer.BeginStable(m_From); - } - } - - private class ClaimListGump : Gump - { - private readonly Mobile m_From; - private readonly List m_List; - private readonly AnimalTrainer m_Trainer; - - public ClaimListGump(AnimalTrainer trainer, Mobile from, List list) : base(50, 50) - { - m_Trainer = trainer; - m_From = from; - m_List = list; - - from.CloseGump(); - - AddPage(0); - - AddBackground(0, 0, 325, 50 + list.Count * 20, 9250); - AddAlphaRegion(5, 5, 315, 40 + list.Count * 20); - - AddHtml(15, 15, 275, 20, "Select a pet to retrieve from the stables:"); - - for (int i = 0; i < list.Count; ++i) + private class StableEntry : ContextMenuEntry { - BaseCreature pet = list[i]; + private readonly Mobile m_From; + private readonly AnimalTrainer m_Trainer; - if (pet?.Deleted != false) - continue; + public StableEntry(AnimalTrainer trainer, Mobile from) : base(6126, 12) + { + m_Trainer = trainer; + m_From = from; + } - AddButton(15, 39 + i * 20, 10006, 10006, i + 1); - AddHtml(32, 35 + i * 20, 275, 18, $"{pet.Name}"); + public override void OnClick() + { + m_Trainer.BeginStable(m_From); + } } - } - public override void OnResponse(NetState sender, RelayInfo info) - { - int index = info.ButtonID - 1; + private class ClaimListGump : Gump + { + private readonly Mobile m_From; + private readonly List m_List; + private readonly AnimalTrainer m_Trainer; - if (index >= 0 && index < m_List.Count) - m_Trainer.EndClaimList(m_From, m_List[index]); - } + public ClaimListGump(AnimalTrainer trainer, Mobile from, List list) : base(50, 50) + { + m_Trainer = trainer; + m_From = from; + m_List = list; + + from.CloseGump(); + + AddPage(0); + + AddBackground(0, 0, 325, 50 + list.Count * 20, 9250); + AddAlphaRegion(5, 5, 315, 40 + list.Count * 20); + + AddHtml(15, 15, 275, 20, "Select a pet to retrieve from the stables:"); + + for (var i = 0; i < list.Count; ++i) + { + var pet = list[i]; + + if (pet?.Deleted != false) + continue; + + AddButton(15, 39 + i * 20, 10006, 10006, i + 1); + AddHtml(32, 35 + i * 20, 275, 18, $"{pet.Name}"); + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var index = info.ButtonID - 1; + + if (index >= 0 && index < m_List.Count) + m_Trainer.EndClaimList(m_From, m_List[index]); + } + } + + private class ClaimAllEntry : ContextMenuEntry + { + private readonly Mobile m_From; + private readonly AnimalTrainer m_Trainer; + + public ClaimAllEntry(AnimalTrainer trainer, Mobile from) : base(6127, 12) + { + m_Trainer = trainer; + m_From = from; + } + + public override void OnClick() + { + m_Trainer.Claim(m_From); + } + } + + private class StableTarget : Target + { + private readonly AnimalTrainer m_Trainer; + + public StableTarget(AnimalTrainer trainer) : base(12, false, TargetFlags.None) => m_Trainer = trainer; + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted is BaseCreature creature) + m_Trainer.EndStable(from, creature); + else if (targeted == from) + m_Trainer.SayTo(from, 502672); // HA HA HA! Sorry, I am not an inn. + else + m_Trainer.SayTo(from, 1048053); // You can't stable that! + } + } } - - private class ClaimAllEntry : ContextMenuEntry - { - private readonly Mobile m_From; - private readonly AnimalTrainer m_Trainer; - - public ClaimAllEntry(AnimalTrainer trainer, Mobile from) : base(6127, 12) - { - m_Trainer = trainer; - m_From = from; - } - - public override void OnClick() - { - m_Trainer.Claim(m_From); - } - } - - private class StableTarget : Target - { - private readonly AnimalTrainer m_Trainer; - - public StableTarget(AnimalTrainer trainer) : base(12, false, TargetFlags.None) => m_Trainer = trainer; - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is BaseCreature creature) - m_Trainer.EndStable(from, creature); - else if (targeted == from) - m_Trainer.SayTo(from, 502672); // HA HA HA! Sorry, I am not an inn. - else - m_Trainer.SayTo(from, 1048053); // You can't stable that! - } - } - } } diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Architect.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Architect.cs index 7bc898f0f..182fa2d4c 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Architect.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Architect.cs @@ -2,43 +2,43 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class Architect : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Architect() : base("the architect") + public class Architect : BaseVendor { + private readonly List m_SBInfos = new List(); + + [Constructible] + public Architect() : base("the architect") + { + } + + public Architect(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override NpcGuild NpcGuild => NpcGuild.TinkersGuild; + + public override void InitSBInfo() + { + if (!Core.AOS) + m_SBInfos.Add(new SBHouseDeed()); + + m_SBInfos.Add(new SBArchitect()); + } + + 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 Architect(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override NpcGuild NpcGuild => NpcGuild.TinkersGuild; - - public override void InitSBInfo() - { - if (!Core.AOS) - m_SBInfos.Add(new SBHouseDeed()); - - m_SBInfos.Add(new SBArchitect()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Armorer.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Armorer.cs index 3ed091ad0..2034e4a59 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Armorer.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Armorer.cs @@ -3,92 +3,92 @@ using Server.Items; namespace Server.Mobiles { - public class Armorer : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Armorer() : base("the armorer") + public class Armorer : BaseVendor { - SetSkill(SkillName.ArmsLore, 64.0, 100.0); - SetSkill(SkillName.Blacksmith, 60.0, 83.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Armorer() : base("the armorer") + { + SetSkill(SkillName.ArmsLore, 64.0, 100.0); + SetSkill(SkillName.Blacksmith, 60.0, 83.0); + } + + public Armorer(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override VendorShoeType ShoeType => VendorShoeType.Boots; + + public override void InitSBInfo() + { + switch (Utility.Random(4)) + { + case 0: + { + m_SBInfos.Add(new SBLeatherArmor()); + m_SBInfos.Add(new SBStuddedArmor()); + m_SBInfos.Add(new SBMetalShields()); + m_SBInfos.Add(new SBPlateArmor()); + m_SBInfos.Add(new SBHelmetArmor()); + m_SBInfos.Add(new SBChainmailArmor()); + m_SBInfos.Add(new SBRingmailArmor()); + break; + } + case 1: + { + m_SBInfos.Add(new SBStuddedArmor()); + m_SBInfos.Add(new SBLeatherArmor()); + m_SBInfos.Add(new SBMetalShields()); + m_SBInfos.Add(new SBHelmetArmor()); + break; + } + case 2: + { + m_SBInfos.Add(new SBMetalShields()); + m_SBInfos.Add(new SBPlateArmor()); + m_SBInfos.Add(new SBHelmetArmor()); + m_SBInfos.Add(new SBChainmailArmor()); + m_SBInfos.Add(new SBRingmailArmor()); + break; + } + case 3: + { + m_SBInfos.Add(new SBMetalShields()); + m_SBInfos.Add(new SBHelmetArmor()); + break; + } + } + + if (IsTokunoVendor) + { + m_SBInfos.Add(new SBSELeatherArmor()); + m_SBInfos.Add(new SBSEArmor()); + } + } + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new HalfApron(Utility.RandomYellowHue())); + AddItem(new Bascinet()); + } + + 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 Armorer(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override VendorShoeType ShoeType => VendorShoeType.Boots; - - public override void InitSBInfo() - { - switch (Utility.Random(4)) - { - case 0: - { - m_SBInfos.Add(new SBLeatherArmor()); - m_SBInfos.Add(new SBStuddedArmor()); - m_SBInfos.Add(new SBMetalShields()); - m_SBInfos.Add(new SBPlateArmor()); - m_SBInfos.Add(new SBHelmetArmor()); - m_SBInfos.Add(new SBChainmailArmor()); - m_SBInfos.Add(new SBRingmailArmor()); - break; - } - case 1: - { - m_SBInfos.Add(new SBStuddedArmor()); - m_SBInfos.Add(new SBLeatherArmor()); - m_SBInfos.Add(new SBMetalShields()); - m_SBInfos.Add(new SBHelmetArmor()); - break; - } - case 2: - { - m_SBInfos.Add(new SBMetalShields()); - m_SBInfos.Add(new SBPlateArmor()); - m_SBInfos.Add(new SBHelmetArmor()); - m_SBInfos.Add(new SBChainmailArmor()); - m_SBInfos.Add(new SBRingmailArmor()); - break; - } - case 3: - { - m_SBInfos.Add(new SBMetalShields()); - m_SBInfos.Add(new SBHelmetArmor()); - break; - } - } - - if (IsTokunoVendor) - { - m_SBInfos.Add(new SBSELeatherArmor()); - m_SBInfos.Add(new SBSEArmor()); - } - } - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new HalfApron(Utility.RandomYellowHue())); - AddItem(new Bascinet()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Baker.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Baker.cs index 16435648e..c0081235f 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Baker.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Baker.cs @@ -2,40 +2,40 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class Baker : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Baker() : base("the baker") + public class Baker : BaseVendor { - SetSkill(SkillName.Cooking, 75.0, 98.0); - SetSkill(SkillName.TasteID, 36.0, 68.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Baker() : base("the baker") + { + SetSkill(SkillName.Cooking, 75.0, 98.0); + SetSkill(SkillName.TasteID, 36.0, 68.0); + } + + public Baker(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBBaker()); + } + + 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 Baker(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBBaker()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Bard.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Bard.cs index 35dd2ca81..dd69cba3c 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Bard.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Bard.cs @@ -2,46 +2,46 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class Bard : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Bard() : base("the bard") + public class Bard : BaseVendor { - SetSkill(SkillName.Discordance, 64.0, 100.0); - SetSkill(SkillName.Musicianship, 64.0, 100.0); - SetSkill(SkillName.Peacemaking, 65.0, 88.0); - SetSkill(SkillName.Provocation, 60.0, 83.0); - SetSkill(SkillName.Archery, 36.0, 68.0); - SetSkill(SkillName.Swords, 36.0, 68.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Bard() : base("the bard") + { + SetSkill(SkillName.Discordance, 64.0, 100.0); + SetSkill(SkillName.Musicianship, 64.0, 100.0); + SetSkill(SkillName.Peacemaking, 65.0, 88.0); + SetSkill(SkillName.Provocation, 60.0, 83.0); + SetSkill(SkillName.Archery, 36.0, 68.0); + SetSkill(SkillName.Swords, 36.0, 68.0); + } + + public Bard(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override NpcGuild NpcGuild => NpcGuild.BardsGuild; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBBard()); + } + + 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 Bard(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override NpcGuild NpcGuild => NpcGuild.BardsGuild; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBBard()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Barkeeper.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Barkeeper.cs index 9b274ccde..b5aa3201f 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Barkeeper.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Barkeeper.cs @@ -3,47 +3,47 @@ using Server.Items; namespace Server.Mobiles { - public class Barkeeper : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Barkeeper() : base("the barkeeper") + public class Barkeeper : BaseVendor { + private readonly List m_SBInfos = new List(); + + [Constructible] + public Barkeeper() : base("the barkeeper") + { + } + + public Barkeeper(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.ThighBoots : VendorShoeType.Boots; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBBarkeeper()); + } + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new HalfApron(Utility.RandomBrightHue())); + } + + 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 Barkeeper(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.ThighBoots : VendorShoeType.Boots; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBBarkeeper()); - } - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new HalfApron(Utility.RandomBrightHue())); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Beekeeper.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Beekeeper.cs index 7aa1eb001..4c2f88291 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Beekeeper.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Beekeeper.cs @@ -2,40 +2,40 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class Beekeeper : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Beekeeper() : base("the beekeeper") + public class Beekeeper : BaseVendor { + private readonly List m_SBInfos = new List(); + + [Constructible] + public Beekeeper() : base("the beekeeper") + { + } + + public Beekeeper(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override VendorShoeType ShoeType => VendorShoeType.Boots; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBBeekeeper()); + } + + 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 Beekeeper(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override VendorShoeType ShoeType => VendorShoeType.Boots; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBBeekeeper()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Blacksmith.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Blacksmith.cs index c8de219b3..c0b041a2b 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Blacksmith.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Blacksmith.cs @@ -5,132 +5,133 @@ using Server.Items; namespace Server.Mobiles { - public class Blacksmith : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Blacksmith() : base("the blacksmith") + public class Blacksmith : BaseVendor { - SetSkill(SkillName.ArmsLore, 36.0, 68.0); - SetSkill(SkillName.Blacksmith, 65.0, 88.0); - SetSkill(SkillName.Fencing, 60.0, 83.0); - SetSkill(SkillName.Macing, 61.0, 93.0); - SetSkill(SkillName.Swords, 60.0, 83.0); - SetSkill(SkillName.Tactics, 60.0, 83.0); - SetSkill(SkillName.Parry, 61.0, 93.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Blacksmith() : base("the blacksmith") + { + SetSkill(SkillName.ArmsLore, 36.0, 68.0); + SetSkill(SkillName.Blacksmith, 65.0, 88.0); + SetSkill(SkillName.Fencing, 60.0, 83.0); + SetSkill(SkillName.Macing, 61.0, 93.0); + SetSkill(SkillName.Swords, 60.0, 83.0); + SetSkill(SkillName.Tactics, 60.0, 83.0); + SetSkill(SkillName.Parry, 61.0, 93.0); + } + + public Blacksmith(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override NpcGuild NpcGuild => NpcGuild.BlacksmithsGuild; + + public override VendorShoeType ShoeType => VendorShoeType.None; + + public override void InitSBInfo() + { + /*m_SBInfos.Add( new SBSmithTools() ); + + m_SBInfos.Add( new SBMetalShields() ); + m_SBInfos.Add( new SBWoodenShields() ); + + m_SBInfos.Add( new SBPlateArmor() ); + + m_SBInfos.Add( new SBHelmetArmor() ); + m_SBInfos.Add( new SBChainmailArmor() ); + m_SBInfos.Add( new SBRingmailArmor() ); + m_SBInfos.Add( new SBAxeWeapon() ); + m_SBInfos.Add( new SBPoleArmWeapon() ); + m_SBInfos.Add( new SBRangedWeapon() ); + + m_SBInfos.Add( new SBKnifeWeapon() ); + m_SBInfos.Add( new SBMaceWeapon() ); + m_SBInfos.Add( new SBSpearForkWeapon() ); + m_SBInfos.Add( new SBSwordWeapon() );*/ + + m_SBInfos.Add(new SBBlacksmith()); + if (IsTokunoVendor) + { + m_SBInfos.Add(new SBSEArmor()); + m_SBInfos.Add(new SBSEWeapons()); + } + } + + public override void InitOutfit() + { + base.InitOutfit(); + + Item item = Utility.RandomBool() ? null : new RingmailChest(); + + if (item != null && !EquipItem(item)) + { + item.Delete(); + item = null; + } + + if (item == null) + AddItem(new FullApron()); + + AddItem(new Bascinet()); + AddItem(new SmithHammer()); + } + + 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 Item CreateBulkOrder(Mobile from, bool fromContextMenu) + { + if (from is PlayerMobile pm && pm.NextSmithBulkOrder == TimeSpan.Zero && + (fromContextMenu || Utility.RandomDouble() < 0.2)) + { + var theirSkill = pm.Skills.Blacksmith.Base; + + if (theirSkill >= 70.1) + pm.NextSmithBulkOrder = TimeSpan.FromHours(6.0); + else if (theirSkill >= 50.1) + pm.NextSmithBulkOrder = TimeSpan.FromHours(2.0); + else + pm.NextSmithBulkOrder = TimeSpan.FromHours(1.0); + + if (theirSkill >= 70.1 && (theirSkill - 40.0) / 300.0 > Utility.RandomDouble()) + return new LargeSmithBOD(); + + return SmallSmithBOD.CreateRandomFor(from); + } + + return null; + } + + public override bool IsValidBulkOrder(Item item) => item is SmallSmithBOD || item is LargeSmithBOD; + + public override bool SupportsBulkOrders(Mobile from) => from is PlayerMobile && from.Skills.Blacksmith.Base > 0; + + public override TimeSpan GetNextBulkOrder(Mobile from) + { + if (from is PlayerMobile mobile) + return mobile.NextSmithBulkOrder; + + return TimeSpan.Zero; + } + + public override void OnSuccessfulBulkOrderReceive(Mobile from) + { + if (Core.SE && from is PlayerMobile mobile) + mobile.NextSmithBulkOrder = TimeSpan.Zero; + } } - - public Blacksmith(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override NpcGuild NpcGuild => NpcGuild.BlacksmithsGuild; - - public override VendorShoeType ShoeType => VendorShoeType.None; - - public override void InitSBInfo() - { - /*m_SBInfos.Add( new SBSmithTools() ); - - m_SBInfos.Add( new SBMetalShields() ); - m_SBInfos.Add( new SBWoodenShields() ); - - m_SBInfos.Add( new SBPlateArmor() ); - - m_SBInfos.Add( new SBHelmetArmor() ); - m_SBInfos.Add( new SBChainmailArmor() ); - m_SBInfos.Add( new SBRingmailArmor() ); - m_SBInfos.Add( new SBAxeWeapon() ); - m_SBInfos.Add( new SBPoleArmWeapon() ); - m_SBInfos.Add( new SBRangedWeapon() ); - - m_SBInfos.Add( new SBKnifeWeapon() ); - m_SBInfos.Add( new SBMaceWeapon() ); - m_SBInfos.Add( new SBSpearForkWeapon() ); - m_SBInfos.Add( new SBSwordWeapon() );*/ - - m_SBInfos.Add(new SBBlacksmith()); - if (IsTokunoVendor) - { - m_SBInfos.Add(new SBSEArmor()); - m_SBInfos.Add(new SBSEWeapons()); - } - } - - public override void InitOutfit() - { - base.InitOutfit(); - - Item item = Utility.RandomBool() ? null : new RingmailChest(); - - if (item != null && !EquipItem(item)) - { - item.Delete(); - item = null; - } - - if (item == null) - AddItem(new FullApron()); - - AddItem(new Bascinet()); - AddItem(new SmithHammer()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override Item CreateBulkOrder(Mobile from, bool fromContextMenu) - { - if (from is PlayerMobile pm && pm.NextSmithBulkOrder == TimeSpan.Zero && (fromContextMenu || Utility.RandomDouble() < 0.2)) - { - double theirSkill = pm.Skills.Blacksmith.Base; - - if (theirSkill >= 70.1) - pm.NextSmithBulkOrder = TimeSpan.FromHours(6.0); - else if (theirSkill >= 50.1) - pm.NextSmithBulkOrder = TimeSpan.FromHours(2.0); - else - pm.NextSmithBulkOrder = TimeSpan.FromHours(1.0); - - if (theirSkill >= 70.1 && (theirSkill - 40.0) / 300.0 > Utility.RandomDouble()) - return new LargeSmithBOD(); - - return SmallSmithBOD.CreateRandomFor(from); - } - - return null; - } - - public override bool IsValidBulkOrder(Item item) => item is SmallSmithBOD || item is LargeSmithBOD; - - public override bool SupportsBulkOrders(Mobile from) => from is PlayerMobile && from.Skills.Blacksmith.Base > 0; - - public override TimeSpan GetNextBulkOrder(Mobile from) - { - if (from is PlayerMobile mobile) - return mobile.NextSmithBulkOrder; - - return TimeSpan.Zero; - } - - public override void OnSuccessfulBulkOrderReceive(Mobile from) - { - if (Core.SE && from is PlayerMobile mobile) - mobile.NextSmithBulkOrder = TimeSpan.Zero; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Bowyer.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Bowyer.cs index 35a70e325..0d7dcc91c 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Bowyer.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Bowyer.cs @@ -3,57 +3,57 @@ using Server.Items; namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.Bower")] - public class Bowyer : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Bowyer() : base("the bowyer") + [TypeAlias("Server.Mobiles.Bower")] + public class Bowyer : BaseVendor { - SetSkill(SkillName.Fletching, 80.0, 100.0); - SetSkill(SkillName.Archery, 80.0, 100.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Bowyer() : base("the bowyer") + { + SetSkill(SkillName.Fletching, 80.0, 100.0); + SetSkill(SkillName.Archery, 80.0, 100.0); + } + + public Bowyer(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override VendorShoeType ShoeType => Female ? VendorShoeType.ThighBoots : VendorShoeType.Boots; + + public override int GetShoeHue() => 0; + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new Bow()); + AddItem(new LeatherGorget()); + } + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBBowyer()); + m_SBInfos.Add(new SBRangedWeapon()); + + if (IsTokunoVendor) + m_SBInfos.Add(new SBSEBowyer()); + } + + 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 Bowyer(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override VendorShoeType ShoeType => Female ? VendorShoeType.ThighBoots : VendorShoeType.Boots; - - public override int GetShoeHue() => 0; - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new Bow()); - AddItem(new LeatherGorget()); - } - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBBowyer()); - m_SBInfos.Add(new SBRangedWeapon()); - - if (IsTokunoVendor) - m_SBInfos.Add(new SBSEBowyer()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Butcher.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Butcher.cs index 77061794d..db4838d2e 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Butcher.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Butcher.cs @@ -3,47 +3,47 @@ using Server.Items; namespace Server.Mobiles { - public class Butcher : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Butcher() : base("the butcher") + public class Butcher : BaseVendor { - SetSkill(SkillName.Anatomy, 45.0, 68.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Butcher() : base("the butcher") + { + SetSkill(SkillName.Anatomy, 45.0, 68.0); + } + + public Butcher(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBButcher()); + } + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new HalfApron()); + AddItem(new Cleaver()); + } + + 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 Butcher(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBButcher()); - } - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new HalfApron()); - AddItem(new Cleaver()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Carpenter.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Carpenter.cs index 1b9280d1a..2ca799bef 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Carpenter.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Carpenter.cs @@ -3,54 +3,54 @@ using Server.Items; namespace Server.Mobiles { - public class Carpenter : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Carpenter() : base("the carpenter") + public class Carpenter : BaseVendor { - SetSkill(SkillName.Carpentry, 85.0, 100.0); - SetSkill(SkillName.Lumberjacking, 60.0, 83.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Carpenter() : base("the carpenter") + { + SetSkill(SkillName.Carpentry, 85.0, 100.0); + SetSkill(SkillName.Lumberjacking, 60.0, 83.0); + } + + public Carpenter(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override NpcGuild NpcGuild => NpcGuild.TinkersGuild; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBStavesWeapon()); + m_SBInfos.Add(new SBCarpenter()); + m_SBInfos.Add(new SBWoodenShields()); + + if (IsTokunoVendor) + m_SBInfos.Add(new SBSECarpenter()); + } + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new HalfApron()); + } + + 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 Carpenter(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override NpcGuild NpcGuild => NpcGuild.TinkersGuild; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBStavesWeapon()); - m_SBInfos.Add(new SBCarpenter()); - m_SBInfos.Add(new SBWoodenShields()); - - if (IsTokunoVendor) - m_SBInfos.Add(new SBSECarpenter()); - } - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new HalfApron()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Cobbler.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Cobbler.cs index cac37ec27..8696a286c 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Cobbler.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Cobbler.cs @@ -2,41 +2,41 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class Cobbler : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Cobbler() : base("the cobbler") + public class Cobbler : BaseVendor { - SetSkill(SkillName.Tailoring, 60.0, 83.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Cobbler() : base("the cobbler") + { + SetSkill(SkillName.Tailoring, 60.0, 83.0); + } + + public Cobbler(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Sandals : VendorShoeType.Shoes; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBCobbler()); + } + + 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 Cobbler(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Sandals : VendorShoeType.Shoes; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBCobbler()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Cook.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Cook.cs index c9e8001ee..a83de7b47 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Cook.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Cook.cs @@ -3,52 +3,52 @@ using Server.Items; namespace Server.Mobiles { - public class Cook : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Cook() : base("the cook") + public class Cook : BaseVendor { - SetSkill(SkillName.Cooking, 90.0, 100.0); - SetSkill(SkillName.TasteID, 75.0, 98.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Cook() : base("the cook") + { + SetSkill(SkillName.Cooking, 90.0, 100.0); + SetSkill(SkillName.TasteID, 75.0, 98.0); + } + + public Cook(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Sandals : VendorShoeType.Shoes; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBCook()); + + if (IsTokunoVendor) + m_SBInfos.Add(new SBSECook()); + } + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new HalfApron()); + } + + 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 Cook(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Sandals : VendorShoeType.Shoes; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBCook()); - - if (IsTokunoVendor) - m_SBInfos.Add(new SBSECook()); - } - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new HalfApron()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/CustomHairstylist.cs b/Projects/UOContent/Mobiles/Vendors/NPC/CustomHairstylist.cs index ef16c45af..710d57ea5 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/CustomHairstylist.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/CustomHairstylist.cs @@ -7,562 +7,639 @@ using Server.Utilities; namespace Server.Mobiles { - public class CustomHairstylist : BaseVendor - { - public static readonly object From = new object(); - public static readonly object Vendor = new object(); - public static readonly object Price = new object(); - - private static readonly HairstylistBuyInfo[] m_SellList = + public class CustomHairstylist : BaseVendor { - new HairstylistBuyInfo(1018357, 50000, false, typeof(ChangeHairstyleGump), new[] - { From, Vendor, Price, false, ChangeHairstyleEntry.HairEntries }), - new HairstylistBuyInfo(1018358, 50000, true, typeof(ChangeHairstyleGump), new[] - { From, Vendor, Price, true, ChangeHairstyleEntry.BeardEntries }), - new HairstylistBuyInfo(1018359, 50, false, typeof(ChangeHairHueGump), new[] - { From, Vendor, Price, true, true, ChangeHairHueEntry.RegularEntries }), - new HairstylistBuyInfo(1018360, 500000, false, typeof(ChangeHairHueGump), new[] - { From, Vendor, Price, true, true, ChangeHairHueEntry.BrightEntries }), - new HairstylistBuyInfo(1018361, 30000, false, typeof(ChangeHairHueGump), new[] - { From, Vendor, Price, true, false, ChangeHairHueEntry.RegularEntries }), - new HairstylistBuyInfo(1018362, 30000, true, typeof(ChangeHairHueGump), new[] - { From, Vendor, Price, false, true, ChangeHairHueEntry.RegularEntries }), - new HairstylistBuyInfo(1018363, 500000, false, typeof(ChangeHairHueGump), new[] - { From, Vendor, Price, true, false, ChangeHairHueEntry.BrightEntries }), - new HairstylistBuyInfo(1018364, 500000, true, typeof(ChangeHairHueGump), new[] - { From, Vendor, Price, false, true, ChangeHairHueEntry.BrightEntries }) - }; + public static readonly object From = new object(); + public static readonly object Vendor = new object(); + public static readonly object Price = new object(); - [Constructible] - public CustomHairstylist() : base("the hairstylist") - { - } - - public CustomHairstylist(Serial serial) : base(serial) - { - } - - protected override List SBInfos { get; } = new List(); - - public override bool ClickTitle => false; - - public override bool IsActiveBuyer => false; - public override bool IsActiveSeller => true; - - public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Shoes : VendorShoeType.Sandals; - - public override bool OnBuyItems(Mobile buyer, List list) => false; - - public override void VendorBuy(Mobile from) - { - from.SendGump(new HairstylistBuyGump(from, this, m_SellList)); - } - - public override int GetHairHue() => Utility.RandomBrightHue(); - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new Robe(Utility.RandomPinkHue())); - } - - public override void InitSBInfo() - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class HairstylistBuyInfo - { - public HairstylistBuyInfo(int title, int price, bool facialHair, Type gumpType, object[] args) - { - Title = title; - Price = price; - FacialHair = facialHair; - GumpType = gumpType; - GumpArgs = args; - } - - public HairstylistBuyInfo(string title, int price, bool facialHair, Type gumpType, object[] args) - { - TitleString = title; - Price = price; - FacialHair = facialHair; - GumpType = gumpType; - GumpArgs = args; - } - - public int Title { get; } - - public string TitleString { get; } - - public int Price { get; } - - public bool FacialHair { get; } - - public Type GumpType { get; } - - public object[] GumpArgs { get; } - } - - public class HairstylistBuyGump : Gump - { - private readonly Mobile m_From; - private readonly HairstylistBuyInfo[] m_SellList; - private readonly Mobile m_Vendor; - - public HairstylistBuyGump(Mobile from, Mobile vendor, HairstylistBuyInfo[] sellList) : base(50, 50) - { - m_From = from; - m_Vendor = vendor; - m_SellList = sellList; - - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - - bool isFemale = from.Female || from.Body.IsFemale; - - int balance = Banker.GetBalance(from); - int canAfford = 0; - - for (int i = 0; i < sellList.Length; ++i) - if (balance >= sellList[i].Price && (!sellList[i].FacialHair || !isFemale)) - ++canAfford; - - AddPage(0); - - AddBackground(50, 10, 450, 100 + canAfford * 25, 2600); - - AddHtmlLocalized(100, 40, 350, 20, 1018356); // Choose your hairstyle change: - - int index = 0; - - for (int i = 0; i < sellList.Length; ++i) - if (balance >= sellList[i].Price && (!sellList[i].FacialHair || !isFemale)) + private static readonly HairstylistBuyInfo[] m_SellList = { - if (sellList[i].TitleString != null) - AddHtml(140, 75 + index * 25, 300, 20, sellList[i].TitleString); - else - AddHtmlLocalized(140, 75 + index * 25, 300, 20, sellList[i].Title); + new HairstylistBuyInfo( + 1018357, + 50000, + false, + typeof(ChangeHairstyleGump), + new[] + { From, Vendor, Price, false, ChangeHairstyleEntry.HairEntries } + ), + new HairstylistBuyInfo( + 1018358, + 50000, + true, + typeof(ChangeHairstyleGump), + new[] + { From, Vendor, Price, true, ChangeHairstyleEntry.BeardEntries } + ), + new HairstylistBuyInfo( + 1018359, + 50, + false, + typeof(ChangeHairHueGump), + new[] + { From, Vendor, Price, true, true, ChangeHairHueEntry.RegularEntries } + ), + new HairstylistBuyInfo( + 1018360, + 500000, + false, + typeof(ChangeHairHueGump), + new[] + { From, Vendor, Price, true, true, ChangeHairHueEntry.BrightEntries } + ), + new HairstylistBuyInfo( + 1018361, + 30000, + false, + typeof(ChangeHairHueGump), + new[] + { From, Vendor, Price, true, false, ChangeHairHueEntry.RegularEntries } + ), + new HairstylistBuyInfo( + 1018362, + 30000, + true, + typeof(ChangeHairHueGump), + new[] + { From, Vendor, Price, false, true, ChangeHairHueEntry.RegularEntries } + ), + new HairstylistBuyInfo( + 1018363, + 500000, + false, + typeof(ChangeHairHueGump), + new[] + { From, Vendor, Price, true, false, ChangeHairHueEntry.BrightEntries } + ), + new HairstylistBuyInfo( + 1018364, + 500000, + true, + typeof(ChangeHairHueGump), + new[] + { From, Vendor, Price, false, true, ChangeHairHueEntry.BrightEntries } + ) + }; - AddButton(100, 75 + index++ * 25, 4005, 4007, 1 + i); + [Constructible] + public CustomHairstylist() : base("the hairstylist") + { + } + + public CustomHairstylist(Serial serial) : base(serial) + { + } + + protected override List SBInfos { get; } = new List(); + + public override bool ClickTitle => false; + + public override bool IsActiveBuyer => false; + public override bool IsActiveSeller => true; + + public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Shoes : VendorShoeType.Sandals; + + public override bool OnBuyItems(Mobile buyer, List list) => false; + + public override void VendorBuy(Mobile from) + { + from.SendGump(new HairstylistBuyGump(from, this, m_SellList)); + } + + public override int GetHairHue() => Utility.RandomBrightHue(); + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new Robe(Utility.RandomPinkHue())); + } + + public override void InitSBInfo() + { + } + + 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 OnResponse(NetState sender, RelayInfo info) + public class HairstylistBuyInfo { - int index = info.ButtonID - 1; - - if (index >= 0 && index < m_SellList.Length) - { - HairstylistBuyInfo buyInfo = m_SellList[index]; - - int balance = Banker.GetBalance(m_From); - - bool isFemale = m_From.Female || m_From.Body.IsFemale; - - if (buyInfo.FacialHair && isFemale) - m_Vendor.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1010639, m_From.NetState); - else if (balance >= buyInfo.Price) - try - { - object[] origArgs = buyInfo.GumpArgs; - object[] args = new object[origArgs.Length]; - - for (int i = 0; i < args.Length; ++i) - if (origArgs[i] == CustomHairstylist.Price) - args[i] = m_SellList[index].Price; - else if (origArgs[i] == CustomHairstylist.From) - args[i] = m_From; - else if (origArgs[i] == CustomHairstylist.Vendor) - args[i] = m_Vendor; - else - args[i] = origArgs[i]; - - Gump g = ActivatorUtil.CreateInstance(buyInfo.GumpType, args) as Gump; - - m_From.SendGump(g); - } - catch - { - // ignored - } - else - m_Vendor.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1042293, m_From.NetState); - } - } - } - - public class ChangeHairHueEntry - { - public static readonly ChangeHairHueEntry[] BrightEntries = - { - new ChangeHairHueEntry("*****", 12, 10), - new ChangeHairHueEntry("*****", 32, 5), - new ChangeHairHueEntry("*****", 38, 8), - new ChangeHairHueEntry("*****", 54, 3), - new ChangeHairHueEntry("*****", 62, 10), - new ChangeHairHueEntry("*****", 81, 2), - new ChangeHairHueEntry("*****", 89, 2), - new ChangeHairHueEntry("*****", 1153, 2) - }; - - public static readonly ChangeHairHueEntry[] RegularEntries = - { - new ChangeHairHueEntry("*****", 1602, 26), - new ChangeHairHueEntry("*****", 1628, 27), - new ChangeHairHueEntry("*****", 1502, 32), - new ChangeHairHueEntry("*****", 1302, 32), - new ChangeHairHueEntry("*****", 1402, 32), - new ChangeHairHueEntry("*****", 1202, 24), - new ChangeHairHueEntry("*****", 2402, 29), - new ChangeHairHueEntry("*****", 2213, 6), - new ChangeHairHueEntry("*****", 1102, 8), - new ChangeHairHueEntry("*****", 1110, 8), - new ChangeHairHueEntry("*****", 1118, 16), - new ChangeHairHueEntry("*****", 1134, 16) - }; - - public ChangeHairHueEntry(string name, int[] hues) - { - Name = name; - Hues = hues; - } - - public ChangeHairHueEntry(string name, int start, int count) - { - Name = name; - - Hues = new int[count]; - - for (int i = 0; i < count; ++i) - Hues[i] = start + i; - } - - public string Name { get; } - - public int[] Hues { get; } - } - - public class ChangeHairHueGump : Gump - { - private readonly ChangeHairHueEntry[] m_Entries; - private readonly bool m_FacialHair; - private readonly Mobile m_From; - private readonly bool m_Hair; - private readonly int m_Price; - private readonly Mobile m_Vendor; - - public ChangeHairHueGump(Mobile from, Mobile vendor, int price, bool hair, bool facialHair, - ChangeHairHueEntry[] entries) : base(50, 50) - { - m_From = from; - m_Vendor = vendor; - m_Price = price; - m_Hair = hair; - m_FacialHair = facialHair; - m_Entries = entries; - - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - - AddPage(0); - - AddBackground(100, 10, 350, 370, 2600); - AddBackground(120, 54, 110, 270, 5100); - - AddHtmlLocalized(155, 25, 240, 30, 1011013); //
Hair Color Selection Menu
- - AddHtmlLocalized(150, 330, 220, 35, 1011014); // Dye my hair this color! - AddButton(380, 330, 4005, 4007, 1); - - for (int i = 0; i < entries.Length; ++i) - { - ChangeHairHueEntry entry = entries[i]; - - AddLabel(130, 59 + i * 22, entry.Hues[0] - 1, entry.Name); - AddButton(207, 60 + i * 22, 5224, 5224, 0, GumpButtonType.Page, 1 + i); - } - - for (int i = 0; i < entries.Length; ++i) - { - ChangeHairHueEntry entry = entries[i]; - int[] hues = entry.Hues; - string name = entry.Name; - - AddPage(1 + i); - - for (int j = 0; j < hues.Length; ++j) + public HairstylistBuyInfo(int title, int price, bool facialHair, Type gumpType, object[] args) { - AddLabel(278 + j / 16 * 80, 52 + j % 16 * 17, hues[j] - 1, name); - AddRadio(260 + j / 16 * 80, 52 + j % 16 * 17, 210, 211, false, j * entries.Length + i); + Title = title; + Price = price; + FacialHair = facialHair; + GumpType = gumpType; + GumpArgs = args; } - } + + public HairstylistBuyInfo(string title, int price, bool facialHair, Type gumpType, object[] args) + { + TitleString = title; + Price = price; + FacialHair = facialHair; + GumpType = gumpType; + GumpArgs = args; + } + + public int Title { get; } + + public string TitleString { get; } + + public int Price { get; } + + public bool FacialHair { get; } + + public Type GumpType { get; } + + public object[] GumpArgs { get; } } - public override void OnResponse(NetState sender, RelayInfo info) + public class HairstylistBuyGump : Gump { - if (info.ButtonID == 1) - { - int[] switches = info.Switches; + private readonly Mobile m_From; + private readonly HairstylistBuyInfo[] m_SellList; + private readonly Mobile m_Vendor; - if (switches.Length > 0) + public HairstylistBuyGump(Mobile from, Mobile vendor, HairstylistBuyInfo[] sellList) : base(50, 50) { - int index = switches[0] % m_Entries.Length; - int offset = switches[0] / m_Entries.Length; + m_From = from; + m_Vendor = vendor; + m_SellList = sellList; - if (index >= 0 && index < m_Entries.Length) - if (offset >= 0 && offset < m_Entries[index].Hues.Length) - { - if ((m_Hair && m_From.HairItemID > 0) || (m_FacialHair && m_From.FacialHairItemID > 0)) - { - if (!Banker.Withdraw(m_From, m_Price)) + from.CloseGump(); + from.CloseGump(); + from.CloseGump(); + + var isFemale = from.Female || from.Body.IsFemale; + + var balance = Banker.GetBalance(from); + var canAfford = 0; + + for (var i = 0; i < sellList.Length; ++i) + if (balance >= sellList[i].Price && (!sellList[i].FacialHair || !isFemale)) + ++canAfford; + + AddPage(0); + + AddBackground(50, 10, 450, 100 + canAfford * 25, 2600); + + AddHtmlLocalized(100, 40, 350, 20, 1018356); // Choose your hairstyle change: + + var index = 0; + + for (var i = 0; i < sellList.Length; ++i) + if (balance >= sellList[i].Price && (!sellList[i].FacialHair || !isFemale)) { - m_Vendor.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1042293, - m_From.NetState); // You cannot afford my services for that style. - return; + if (sellList[i].TitleString != null) + AddHtml(140, 75 + index * 25, 300, 20, sellList[i].TitleString); + else + AddHtmlLocalized(140, 75 + index * 25, 300, 20, sellList[i].Title); + + AddButton(100, 75 + index++ * 25, 4005, 4007, 1 + i); } + } - int hue = m_Entries[index].Hues[offset]; + public override void OnResponse(NetState sender, RelayInfo info) + { + var index = info.ButtonID - 1; - if (m_Hair) - m_From.HairHue = hue; + if (index >= 0 && index < m_SellList.Length) + { + var buyInfo = m_SellList[index]; - if (m_FacialHair) - m_From.FacialHairHue = hue; - } - else - { - m_Vendor.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 502623, - m_From.NetState); // You have no hair to dye and you cannot use this. - } + var balance = Banker.GetBalance(m_From); + + var isFemale = m_From.Female || m_From.Body.IsFemale; + + if (buyInfo.FacialHair && isFemale) + m_Vendor.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1010639, m_From.NetState); + else if (balance >= buyInfo.Price) + try + { + var origArgs = buyInfo.GumpArgs; + var args = new object[origArgs.Length]; + + for (var i = 0; i < args.Length; ++i) + if (origArgs[i] == CustomHairstylist.Price) + args[i] = m_SellList[index].Price; + else if (origArgs[i] == CustomHairstylist.From) + args[i] = m_From; + else if (origArgs[i] == CustomHairstylist.Vendor) + args[i] = m_Vendor; + else + args[i] = origArgs[i]; + + var g = ActivatorUtil.CreateInstance(buyInfo.GumpType, args) as Gump; + + m_From.SendGump(g); + } + catch + { + // ignored + } + else + m_Vendor.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1042293, m_From.NetState); } } - else - { - // You decide not to change your hairstyle. - m_Vendor.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1013009, m_From.NetState); - } - } - else - { - // You decide not to change your hairstyle. - m_Vendor.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1013009, m_From.NetState); - } - } - } - - public class ChangeHairstyleEntry - { - public static readonly ChangeHairstyleEntry[] HairEntries = - { - new ChangeHairstyleEntry(50700, 70 - 137, 20 - 60, 0x203B), - new ChangeHairstyleEntry(60710, 193 - 260, 18 - 60, 0x2045), - new ChangeHairstyleEntry(50703, 316 - 383, 25 - 60, 0x2044), - new ChangeHairstyleEntry(60708, 70 - 137, 75 - 125, 0x203C), - new ChangeHairstyleEntry(60900, 193 - 260, 85 - 125, 0x2047), - new ChangeHairstyleEntry(60713, 320 - 383, 85 - 125, 0x204A), - new ChangeHairstyleEntry(60702, 70 - 137, 140 - 190, 0x203D), - new ChangeHairstyleEntry(60707, 193 - 260, 140 - 190, 0x2049), - new ChangeHairstyleEntry(60901, 315 - 383, 150 - 190, 0x2048), - new ChangeHairstyleEntry(0, 0, 0, 0) - }; - - public static readonly ChangeHairstyleEntry[] BeardEntries = - { - new ChangeHairstyleEntry(50800, 120 - 187, 30 - 80, 0x2040), - new ChangeHairstyleEntry(50904, 243 - 310, 33 - 80, 0x204B), - new ChangeHairstyleEntry(50906, 120 - 187, 100 - 150, 0x204D), - new ChangeHairstyleEntry(50801, 243 - 310, 95 - 150, 0x203E), - new ChangeHairstyleEntry(50802, 120 - 187, 173 - 220, 0x203F), - new ChangeHairstyleEntry(50905, 243 - 310, 165 - 220, 0x204C), - new ChangeHairstyleEntry(50808, 120 - 187, 242 - 290, 0x2041), - new ChangeHairstyleEntry(0, 0, 0, 0) - }; - - public ChangeHairstyleEntry(int gumpID, int x, int y, int itemID) - { - GumpID = gumpID; - X = x; - Y = y; - ItemID = itemID; } - public int ItemID { get; } - - public int GumpID { get; } - - public int X { get; } - - public int Y { get; } - } - - public class ChangeHairstyleGump : Gump - { - private readonly ChangeHairstyleEntry[] m_Entries; - private readonly bool m_FacialHair; - private readonly Mobile m_From; - private readonly int m_Price; - private readonly Mobile m_Vendor; - - public ChangeHairstyleGump(Mobile from, Mobile vendor, int price, bool facialHair, ChangeHairstyleEntry[] entries) : base(50, 50) + public class ChangeHairHueEntry { - m_From = from; - m_Vendor = vendor; - m_Price = price; - m_FacialHair = facialHair; - m_Entries = entries; - - from.CloseGump(); - from.CloseGump(); - from.CloseGump(); - - int tableWidth = m_FacialHair ? 2 : 3; - int tableHeight = (entries.Length + tableWidth - (m_FacialHair ? 1 : 2)) / tableWidth; - int offsetWidth = 123; - int offsetHeight = m_FacialHair ? 70 : 65; - - AddPage(0); - - AddBackground(0, 0, 81 + tableWidth * offsetWidth, 105 + tableHeight * offsetHeight, 2600); - - AddButton(45, 45 + tableHeight * offsetHeight, 4005, 4007, 1); - AddHtmlLocalized(77, 45 + tableHeight * offsetHeight, 90, 35, 1006044); // Ok - - AddButton(81 + tableWidth * offsetWidth - 180, 45 + tableHeight * offsetHeight, 4005, 4007, 0); - AddHtmlLocalized(81 + tableWidth * offsetWidth - 148, 45 + tableHeight * offsetHeight, 90, 35, 1006045); // Cancel - - if (!facialHair) - AddHtmlLocalized(50, 15, 350, 20, 1018353); //
New Hairstyle
- else - AddHtmlLocalized(55, 15, 200, 20, 1018354); //
New Beard
- - for (int i = 0; i < entries.Length; ++i) - { - int xTable = i % tableWidth; - int yTable = i / tableWidth; - - if (entries[i].GumpID != 0) + public static readonly ChangeHairHueEntry[] BrightEntries = { - AddRadio(40 + xTable * offsetWidth, 70 + yTable * offsetHeight, 208, 209, false, i); - AddBackground(87 + xTable * offsetWidth, 50 + yTable * offsetHeight, 50, 50, 2620); - AddImage(87 + xTable * offsetWidth + entries[i].X, 50 + yTable * offsetHeight + entries[i].Y, - entries[i].GumpID); - } - else if (!facialHair) + new ChangeHairHueEntry("*****", 12, 10), + new ChangeHairHueEntry("*****", 32, 5), + new ChangeHairHueEntry("*****", 38, 8), + new ChangeHairHueEntry("*****", 54, 3), + new ChangeHairHueEntry("*****", 62, 10), + new ChangeHairHueEntry("*****", 81, 2), + new ChangeHairHueEntry("*****", 89, 2), + new ChangeHairHueEntry("*****", 1153, 2) + }; + + public static readonly ChangeHairHueEntry[] RegularEntries = { - AddRadio(40 + (xTable + 1) * offsetWidth, 240, 208, 209, false, i); - AddHtmlLocalized(60 + (xTable + 1) * offsetWidth, 240, 85, 35, 1011064); // Bald - } - else + new ChangeHairHueEntry("*****", 1602, 26), + new ChangeHairHueEntry("*****", 1628, 27), + new ChangeHairHueEntry("*****", 1502, 32), + new ChangeHairHueEntry("*****", 1302, 32), + new ChangeHairHueEntry("*****", 1402, 32), + new ChangeHairHueEntry("*****", 1202, 24), + new ChangeHairHueEntry("*****", 2402, 29), + new ChangeHairHueEntry("*****", 2213, 6), + new ChangeHairHueEntry("*****", 1102, 8), + new ChangeHairHueEntry("*****", 1110, 8), + new ChangeHairHueEntry("*****", 1118, 16), + new ChangeHairHueEntry("*****", 1134, 16) + }; + + public ChangeHairHueEntry(string name, int[] hues) { - AddRadio(40 + xTable * offsetWidth, 70 + yTable * offsetHeight, 208, 209, false, i); - AddHtmlLocalized(60 + xTable * offsetWidth, 70 + yTable * offsetHeight, 85, 35, 1011064); // Bald + Name = name; + Hues = hues; } - } + + public ChangeHairHueEntry(string name, int start, int count) + { + Name = name; + + Hues = new int[count]; + + for (var i = 0; i < count; ++i) + Hues[i] = start + i; + } + + public string Name { get; } + + public int[] Hues { get; } } - public override void OnResponse(NetState sender, RelayInfo info) + public class ChangeHairHueGump : Gump { - if (m_FacialHair && (m_From.Female || m_From.Body.IsFemale)) - return; + private readonly ChangeHairHueEntry[] m_Entries; + private readonly bool m_FacialHair; + private readonly Mobile m_From; + private readonly bool m_Hair; + private readonly int m_Price; + private readonly Mobile m_Vendor; - if (m_From.Race == Race.Elf) - { - m_From.SendMessage("This isn't implemented for elves yet. Sorry!"); - return; - } - - if (info.ButtonID == 1) - { - int[] switches = info.Switches; - - if (switches.Length > 0) + public ChangeHairHueGump( + Mobile from, Mobile vendor, int price, bool hair, bool facialHair, + ChangeHairHueEntry[] entries + ) : base(50, 50) { - int index = switches[0]; + m_From = from; + m_Vendor = vendor; + m_Price = price; + m_Hair = hair; + m_FacialHair = facialHair; + m_Entries = entries; - if (index >= 0 && index < m_Entries.Length) - { - ChangeHairstyleEntry entry = m_Entries[index]; + from.CloseGump(); + from.CloseGump(); + from.CloseGump(); - (m_From as PlayerMobile)?.SetHairMods(-1, -1); + AddPage(0); - int hairID = m_From.HairItemID; - int facialHairID = m_From.FacialHairItemID; + AddBackground(100, 10, 350, 370, 2600); + AddBackground(120, 54, 110, 270, 5100); - if (entry.ItemID == 0) + AddHtmlLocalized(155, 25, 240, 30, 1011013); //
Hair Color Selection Menu
+ + AddHtmlLocalized(150, 330, 220, 35, 1011014); // Dye my hair this color! + AddButton(380, 330, 4005, 4007, 1); + + for (var i = 0; i < entries.Length; ++i) { - if (m_FacialHair ? facialHairID == 0 : hairID == 0) - return; + var entry = entries[i]; - if (Banker.Withdraw(m_From, m_Price)) - { - if (m_FacialHair) - m_From.FacialHairItemID = 0; + AddLabel(130, 59 + i * 22, entry.Hues[0] - 1, entry.Name); + AddButton(207, 60 + i * 22, 5224, 5224, 0, GumpButtonType.Page, 1 + i); + } + + for (var i = 0; i < entries.Length; ++i) + { + var entry = entries[i]; + var hues = entry.Hues; + var name = entry.Name; + + AddPage(1 + i); + + for (var j = 0; j < hues.Length; ++j) + { + AddLabel(278 + j / 16 * 80, 52 + j % 16 * 17, hues[j] - 1, name); + AddRadio(260 + j / 16 * 80, 52 + j % 16 * 17, 210, 211, false, j * entries.Length + i); + } + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 1) + { + var switches = info.Switches; + + if (switches.Length > 0) + { + var index = switches[0] % m_Entries.Length; + var offset = switches[0] / m_Entries.Length; + + if (index >= 0 && index < m_Entries.Length) + if (offset >= 0 && offset < m_Entries[index].Hues.Length) + { + if (m_Hair && m_From.HairItemID > 0 || m_FacialHair && m_From.FacialHairItemID > 0) + { + if (!Banker.Withdraw(m_From, m_Price)) + { + m_Vendor.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 1042293, + m_From.NetState + ); // You cannot afford my services for that style. + return; + } + + var hue = m_Entries[index].Hues[offset]; + + if (m_Hair) + m_From.HairHue = hue; + + if (m_FacialHair) + m_From.FacialHairHue = hue; + } + else + { + m_Vendor.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 502623, + m_From.NetState + ); // You have no hair to dye and you cannot use this. + } + } + } else - m_From.HairItemID = 0; - } - else - { - m_Vendor.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1042293, - m_From.NetState); // You cannot afford my services for that style. - } + { + // You decide not to change your hairstyle. + m_Vendor.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1013009, m_From.NetState); + } } else { - if (m_FacialHair) - { - if (facialHairID > 0 && facialHairID == entry.ItemID) - return; - } - else - { - if (hairID > 0 && hairID == entry.ItemID) - return; - } - - if (Banker.Withdraw(m_From, m_Price)) - { - if (m_FacialHair) - m_From.FacialHairItemID = entry.ItemID; - else - m_From.HairItemID = entry.ItemID; - } - else - { - m_Vendor.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1042293, - m_From.NetState); // You cannot afford my services for that style. - } + // You decide not to change your hairstyle. + m_Vendor.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1013009, m_From.NetState); + } + } + } + + public class ChangeHairstyleEntry + { + public static readonly ChangeHairstyleEntry[] HairEntries = + { + new ChangeHairstyleEntry(50700, 70 - 137, 20 - 60, 0x203B), + new ChangeHairstyleEntry(60710, 193 - 260, 18 - 60, 0x2045), + new ChangeHairstyleEntry(50703, 316 - 383, 25 - 60, 0x2044), + new ChangeHairstyleEntry(60708, 70 - 137, 75 - 125, 0x203C), + new ChangeHairstyleEntry(60900, 193 - 260, 85 - 125, 0x2047), + new ChangeHairstyleEntry(60713, 320 - 383, 85 - 125, 0x204A), + new ChangeHairstyleEntry(60702, 70 - 137, 140 - 190, 0x203D), + new ChangeHairstyleEntry(60707, 193 - 260, 140 - 190, 0x2049), + new ChangeHairstyleEntry(60901, 315 - 383, 150 - 190, 0x2048), + new ChangeHairstyleEntry(0, 0, 0, 0) + }; + + public static readonly ChangeHairstyleEntry[] BeardEntries = + { + new ChangeHairstyleEntry(50800, 120 - 187, 30 - 80, 0x2040), + new ChangeHairstyleEntry(50904, 243 - 310, 33 - 80, 0x204B), + new ChangeHairstyleEntry(50906, 120 - 187, 100 - 150, 0x204D), + new ChangeHairstyleEntry(50801, 243 - 310, 95 - 150, 0x203E), + new ChangeHairstyleEntry(50802, 120 - 187, 173 - 220, 0x203F), + new ChangeHairstyleEntry(50905, 243 - 310, 165 - 220, 0x204C), + new ChangeHairstyleEntry(50808, 120 - 187, 242 - 290, 0x2041), + new ChangeHairstyleEntry(0, 0, 0, 0) + }; + + public ChangeHairstyleEntry(int gumpID, int x, int y, int itemID) + { + GumpID = gumpID; + X = x; + Y = y; + ItemID = itemID; + } + + public int ItemID { get; } + + public int GumpID { get; } + + public int X { get; } + + public int Y { get; } + } + + public class ChangeHairstyleGump : Gump + { + private readonly ChangeHairstyleEntry[] m_Entries; + private readonly bool m_FacialHair; + private readonly Mobile m_From; + private readonly int m_Price; + private readonly Mobile m_Vendor; + + public ChangeHairstyleGump( + Mobile from, Mobile vendor, int price, bool facialHair, ChangeHairstyleEntry[] entries + ) : base(50, 50) + { + m_From = from; + m_Vendor = vendor; + m_Price = price; + m_FacialHair = facialHair; + m_Entries = entries; + + from.CloseGump(); + from.CloseGump(); + from.CloseGump(); + + var tableWidth = m_FacialHair ? 2 : 3; + var tableHeight = (entries.Length + tableWidth - (m_FacialHair ? 1 : 2)) / tableWidth; + var offsetWidth = 123; + var offsetHeight = m_FacialHair ? 70 : 65; + + AddPage(0); + + AddBackground(0, 0, 81 + tableWidth * offsetWidth, 105 + tableHeight * offsetHeight, 2600); + + AddButton(45, 45 + tableHeight * offsetHeight, 4005, 4007, 1); + AddHtmlLocalized(77, 45 + tableHeight * offsetHeight, 90, 35, 1006044); // Ok + + AddButton(81 + tableWidth * offsetWidth - 180, 45 + tableHeight * offsetHeight, 4005, 4007, 0); + AddHtmlLocalized( + 81 + tableWidth * offsetWidth - 148, + 45 + tableHeight * offsetHeight, + 90, + 35, + 1006045 + ); // Cancel + + if (!facialHair) + AddHtmlLocalized(50, 15, 350, 20, 1018353); //
New Hairstyle
+ else + AddHtmlLocalized(55, 15, 200, 20, 1018354); //
New Beard
+ + for (var i = 0; i < entries.Length; ++i) + { + var xTable = i % tableWidth; + var yTable = i / tableWidth; + + if (entries[i].GumpID != 0) + { + AddRadio(40 + xTable * offsetWidth, 70 + yTable * offsetHeight, 208, 209, false, i); + AddBackground(87 + xTable * offsetWidth, 50 + yTable * offsetHeight, 50, 50, 2620); + AddImage( + 87 + xTable * offsetWidth + entries[i].X, + 50 + yTable * offsetHeight + entries[i].Y, + entries[i].GumpID + ); + } + else if (!facialHair) + { + AddRadio(40 + (xTable + 1) * offsetWidth, 240, 208, 209, false, i); + AddHtmlLocalized(60 + (xTable + 1) * offsetWidth, 240, 85, 35, 1011064); // Bald + } + else + { + AddRadio(40 + xTable * offsetWidth, 70 + yTable * offsetHeight, 208, 209, false, i); + AddHtmlLocalized(60 + xTable * offsetWidth, 70 + yTable * offsetHeight, 85, 35, 1011064); // Bald + } + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (m_FacialHair && (m_From.Female || m_From.Body.IsFemale)) + return; + + if (m_From.Race == Race.Elf) + { + m_From.SendMessage("This isn't implemented for elves yet. Sorry!"); + return; + } + + if (info.ButtonID == 1) + { + var switches = info.Switches; + + if (switches.Length > 0) + { + var index = switches[0]; + + if (index >= 0 && index < m_Entries.Length) + { + var entry = m_Entries[index]; + + (m_From as PlayerMobile)?.SetHairMods(-1, -1); + + var hairID = m_From.HairItemID; + var facialHairID = m_From.FacialHairItemID; + + if (entry.ItemID == 0) + { + if (m_FacialHair ? facialHairID == 0 : hairID == 0) + return; + + if (Banker.Withdraw(m_From, m_Price)) + { + if (m_FacialHair) + m_From.FacialHairItemID = 0; + else + m_From.HairItemID = 0; + } + else + { + m_Vendor.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 1042293, + m_From.NetState + ); // You cannot afford my services for that style. + } + } + else + { + if (m_FacialHair) + { + if (facialHairID > 0 && facialHairID == entry.ItemID) + return; + } + else + { + if (hairID > 0 && hairID == entry.ItemID) + return; + } + + if (Banker.Withdraw(m_From, m_Price)) + { + if (m_FacialHair) + m_From.FacialHairItemID = entry.ItemID; + else + m_From.HairItemID = entry.ItemID; + } + else + { + m_Vendor.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 1042293, + m_From.NetState + ); // You cannot afford my services for that style. + } + } + } + } + else + { + // You decide not to change your hairstyle. + m_Vendor.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1013009, m_From.NetState); + } + } + else + { + // You decide not to change your hairstyle. + m_Vendor.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1013009, m_From.NetState); } - } } - else - { - // You decide not to change your hairstyle. - m_Vendor.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1013009, m_From.NetState); - } - } - else - { - // You decide not to change your hairstyle. - m_Vendor.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1013009, m_From.NetState); - } } - } } diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Farmer.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Farmer.cs index 84a4dce08..e16efa7fc 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Farmer.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Farmer.cs @@ -3,52 +3,52 @@ using Server.Items; namespace Server.Mobiles { - public class Farmer : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Farmer() : base("the farmer") + public class Farmer : BaseVendor { - SetSkill(SkillName.Lumberjacking, 36.0, 68.0); - SetSkill(SkillName.TasteID, 36.0, 68.0); - SetSkill(SkillName.Cooking, 36.0, 68.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Farmer() : base("the farmer") + { + SetSkill(SkillName.Lumberjacking, 36.0, 68.0); + SetSkill(SkillName.TasteID, 36.0, 68.0); + SetSkill(SkillName.Cooking, 36.0, 68.0); + } + + public Farmer(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override VendorShoeType ShoeType => VendorShoeType.ThighBoots; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBFarmer()); + } + + public override int GetShoeHue() => 0; + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new WideBrimHat(Utility.RandomNeutralHue())); + } + + 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 Farmer(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override VendorShoeType ShoeType => VendorShoeType.ThighBoots; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBFarmer()); - } - - public override int GetShoeHue() => 0; - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new WideBrimHat(Utility.RandomNeutralHue())); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Fisherman.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Fisherman.cs index 314842473..056b9a1c4 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Fisherman.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Fisherman.cs @@ -3,48 +3,48 @@ using Server.Items; namespace Server.Mobiles { - public class Fisherman : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Fisherman() : base("the fisher") + public class Fisherman : BaseVendor { - SetSkill(SkillName.Fishing, 75.0, 98.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Fisherman() : base("the fisher") + { + SetSkill(SkillName.Fishing, 75.0, 98.0); + } + + public Fisherman(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override NpcGuild NpcGuild => NpcGuild.FishermensGuild; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBFisherman()); + } + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new FishingPole()); + } + + 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 Fisherman(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override NpcGuild NpcGuild => NpcGuild.FishermensGuild; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBFisherman()); - } - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new FishingPole()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Furtrader.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Furtrader.cs index 361c598b3..6c27ad5a8 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Furtrader.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Furtrader.cs @@ -2,43 +2,43 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class Furtrader : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Furtrader() : base("the furtrader") + public class Furtrader : BaseVendor { - SetSkill(SkillName.Camping, 55.0, 78.0); - // SetSkill( SkillName.Alchemy, 60.0, 83.0 ); - SetSkill(SkillName.AnimalLore, 85.0, 100.0); - SetSkill(SkillName.Cooking, 45.0, 68.0); - SetSkill(SkillName.Tracking, 36.0, 68.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Furtrader() : base("the furtrader") + { + SetSkill(SkillName.Camping, 55.0, 78.0); + // SetSkill( SkillName.Alchemy, 60.0, 83.0 ); + SetSkill(SkillName.AnimalLore, 85.0, 100.0); + SetSkill(SkillName.Cooking, 45.0, 68.0); + SetSkill(SkillName.Tracking, 36.0, 68.0); + } + + public Furtrader(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBFurtrader()); + } + + 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 Furtrader(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBFurtrader()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Glassblower.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Glassblower.cs index 022b03cca..9a8ad25df 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Glassblower.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Glassblower.cs @@ -2,47 +2,47 @@ using System.Collections.Generic; namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.GargoyleAlchemist")] - public class Glassblower : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Glassblower() : base("the alchemist") + [TypeAlias("Server.Mobiles.GargoyleAlchemist")] + public class Glassblower : BaseVendor { - SetSkill(SkillName.Alchemy, 85.0, 100.0); - SetSkill(SkillName.TasteID, 85.0, 100.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Glassblower() : base("the alchemist") + { + SetSkill(SkillName.Alchemy, 85.0, 100.0); + SetSkill(SkillName.TasteID, 85.0, 100.0); + } + + public Glassblower(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override NpcGuild NpcGuild => NpcGuild.MagesGuild; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBGlassblower()); + m_SBInfos.Add(new SBAlchemist()); + } + + 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 (Body == 0x2F2) + Body = 0x2F6; + } } - - public Glassblower(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override NpcGuild NpcGuild => NpcGuild.MagesGuild; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBGlassblower()); - m_SBInfos.Add(new SBAlchemist()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Body == 0x2F2) - Body = 0x2F6; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/GolemCrafter.cs b/Projects/UOContent/Mobiles/Vendors/NPC/GolemCrafter.cs index 22ab43579..4358dae5e 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/GolemCrafter.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/GolemCrafter.cs @@ -2,42 +2,42 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class GolemCrafter : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public GolemCrafter() : base("the golem crafter") + public class GolemCrafter : BaseVendor { - SetSkill(SkillName.Lockpicking, 60.0, 83.0); - SetSkill(SkillName.RemoveTrap, 75.0, 98.0); - SetSkill(SkillName.Tinkering, 64.0, 100.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public GolemCrafter() : base("the golem crafter") + { + SetSkill(SkillName.Lockpicking, 60.0, 83.0); + SetSkill(SkillName.RemoveTrap, 75.0, 98.0); + SetSkill(SkillName.Tinkering, 64.0, 100.0); + } + + public GolemCrafter(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBTinker()); + m_SBInfos.Add(new SBVagabond()); + } + + 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 GolemCrafter(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBTinker()); - m_SBInfos.Add(new SBVagabond()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/BardGuildmaster.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/BardGuildmaster.cs index ff3e7d0db..1df1f50fc 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/BardGuildmaster.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/BardGuildmaster.cs @@ -1,36 +1,36 @@ namespace Server.Mobiles { - public class BardGuildmaster : BaseGuildmaster - { - [Constructible] - public BardGuildmaster() : base("bard") + public class BardGuildmaster : BaseGuildmaster { - SetSkill(SkillName.Archery, 80.0, 100.0); - SetSkill(SkillName.Discordance, 80.0, 100.0); - SetSkill(SkillName.Musicianship, 80.0, 100.0); - SetSkill(SkillName.Peacemaking, 80.0, 100.0); - SetSkill(SkillName.Provocation, 80.0, 100.0); - SetSkill(SkillName.Swords, 80.0, 100.0); + [Constructible] + public BardGuildmaster() : base("bard") + { + SetSkill(SkillName.Archery, 80.0, 100.0); + SetSkill(SkillName.Discordance, 80.0, 100.0); + SetSkill(SkillName.Musicianship, 80.0, 100.0); + SetSkill(SkillName.Peacemaking, 80.0, 100.0); + SetSkill(SkillName.Provocation, 80.0, 100.0); + SetSkill(SkillName.Swords, 80.0, 100.0); + } + + public BardGuildmaster(Serial serial) : base(serial) + { + } + + public override NpcGuild NpcGuild => NpcGuild.BardsGuild; + + 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 BardGuildmaster(Serial serial) : base(serial) - { - } - - public override NpcGuild NpcGuild => NpcGuild.BardsGuild; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/BaseGuildmaster.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/BaseGuildmaster.cs index dc96702b0..6fb290e92 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/BaseGuildmaster.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/BaseGuildmaster.cs @@ -5,153 +5,169 @@ using Server.Network; namespace Server.Mobiles { - public abstract class BaseGuildmaster : BaseVendor - { - public BaseGuildmaster(string title) : base(title) => Title = $"the {title} {(Female ? "guildmistress" : "guildmaster")}"; - - public BaseGuildmaster(Serial serial) : base(serial) + public abstract class BaseGuildmaster : BaseVendor { - } + public BaseGuildmaster(string title) : base(title) => + Title = $"the {title} {(Female ? "guildmistress" : "guildmaster")}"; - protected override List SBInfos { get; } = new List(); - - public override bool IsActiveVendor => false; - - public override bool ClickTitle => false; - - public virtual int JoinCost => 500; - - public virtual TimeSpan JoinAge => TimeSpan.FromDays(0.0); - public virtual TimeSpan JoinGameAge => TimeSpan.FromDays(2.0); - public virtual TimeSpan QuitAge => TimeSpan.FromDays(7.0); - public virtual TimeSpan QuitGameAge => TimeSpan.FromDays(4.0); - - public override void InitSBInfo() - { - } - - public virtual bool CheckCustomReqs(PlayerMobile pm) => true; - - public virtual void SayGuildTo(Mobile m) - { - SayTo(m, 1008055 + (int)NpcGuild); - } - - public virtual void SayWelcomeTo(Mobile m) - { - SayTo(m, 1008054); // Welcome to the guild! Thou shalt find that fellow members shall grant thee lower prices in shops. - } - - public virtual void SayPriceTo(Mobile m) - { - m.Send(new MessageLocalizedAffix(Serial, Body, MessageType.Regular, SpeechHue, 3, 1008052, Name, - AffixType.Append, JoinCost.ToString(), "")); - } - - public virtual bool WasNamed(string speech) - { - string name = Name; - - return name != null && Insensitive.StartsWith(speech, name); - } - - public override bool HandlesOnSpeech(Mobile from) - { - if (from.InRange(Location, 2)) - return true; - - return base.HandlesOnSpeech(from); - } - - public override void OnSpeech(SpeechEventArgs e) - { - Mobile from = e.Mobile; - - if (!e.Handled && from is PlayerMobile pm && pm.InRange(Location, 2) && WasNamed(e.Speech)) - { - if (e.HasKeyword(0x0004)) // *join* | *member* + public BaseGuildmaster(Serial serial) : base(serial) { - if (pm.NpcGuild == NpcGuild) - SayTo(pm, 501047); // Thou art already a member of our guild. - else if (pm.NpcGuild != NpcGuild.None) - SayTo(pm, 501046); // Thou must resign from thy other guild first. - else if (pm.GameTime < JoinGameAge || pm.CreationTime + JoinAge > DateTime.UtcNow) - SayTo(pm, 501048); // You are too young to join my guild... - else if (CheckCustomReqs(pm)) - SayPriceTo(pm); - - e.Handled = true; - } - else if (e.HasKeyword(0x0005)) // *resign* | *quit* - { - if (pm.NpcGuild != NpcGuild) - { - SayTo(pm, 501052); // Thou dost not belong to my guild! - } - else if (pm.NpcGuildJoinTime + QuitAge > DateTime.UtcNow || - pm.NpcGuildGameTime + QuitGameAge > pm.GameTime) - { - SayTo(pm, 501053); // You just joined my guild! You must wait a week to resign. - } - else - { - SayTo(pm, 501054); // I accept thy resignation. - pm.NpcGuild = NpcGuild.None; - } - - e.Handled = true; - } - } - - base.OnSpeech(e); - } - - public override bool OnGoldGiven(Mobile from, Gold dropped) - { - if (from is PlayerMobile pm && dropped.Amount == JoinCost) - { - if (pm.NpcGuild == NpcGuild) - { - SayTo(pm, 501047); // Thou art already a member of our guild. - } - else if (pm.NpcGuild != NpcGuild.None) - { - SayTo(pm, 501046); // Thou must resign from thy other guild first. - } - else if (pm.GameTime < JoinGameAge || pm.CreationTime + JoinAge > DateTime.UtcNow) - { - SayTo(pm, 501048); // You are too young to join my guild... - } - else if (CheckCustomReqs(pm)) - { - SayWelcomeTo(pm); - - pm.NpcGuild = NpcGuild; - pm.NpcGuildJoinTime = DateTime.UtcNow; - pm.NpcGuildGameTime = pm.GameTime; - - dropped.Delete(); - return true; } - return false; - } + protected override List SBInfos { get; } = new List(); - return base.OnGoldGiven(from, dropped); + public override bool IsActiveVendor => false; + + public override bool ClickTitle => false; + + public virtual int JoinCost => 500; + + public virtual TimeSpan JoinAge => TimeSpan.FromDays(0.0); + public virtual TimeSpan JoinGameAge => TimeSpan.FromDays(2.0); + public virtual TimeSpan QuitAge => TimeSpan.FromDays(7.0); + public virtual TimeSpan QuitGameAge => TimeSpan.FromDays(4.0); + + public override void InitSBInfo() + { + } + + public virtual bool CheckCustomReqs(PlayerMobile pm) => true; + + public virtual void SayGuildTo(Mobile m) + { + SayTo(m, 1008055 + (int)NpcGuild); + } + + public virtual void SayWelcomeTo(Mobile m) + { + SayTo( + m, + 1008054 + ); // Welcome to the guild! Thou shalt find that fellow members shall grant thee lower prices in shops. + } + + public virtual void SayPriceTo(Mobile m) + { + m.Send( + new MessageLocalizedAffix( + Serial, + Body, + MessageType.Regular, + SpeechHue, + 3, + 1008052, + Name, + AffixType.Append, + JoinCost.ToString(), + "" + ) + ); + } + + public virtual bool WasNamed(string speech) + { + var name = Name; + + return name != null && Insensitive.StartsWith(speech, name); + } + + public override bool HandlesOnSpeech(Mobile from) + { + if (from.InRange(Location, 2)) + return true; + + return base.HandlesOnSpeech(from); + } + + public override void OnSpeech(SpeechEventArgs e) + { + var from = e.Mobile; + + if (!e.Handled && from is PlayerMobile pm && pm.InRange(Location, 2) && WasNamed(e.Speech)) + { + if (e.HasKeyword(0x0004)) // *join* | *member* + { + if (pm.NpcGuild == NpcGuild) + SayTo(pm, 501047); // Thou art already a member of our guild. + else if (pm.NpcGuild != NpcGuild.None) + SayTo(pm, 501046); // Thou must resign from thy other guild first. + else if (pm.GameTime < JoinGameAge || pm.CreationTime + JoinAge > DateTime.UtcNow) + SayTo(pm, 501048); // You are too young to join my guild... + else if (CheckCustomReqs(pm)) + SayPriceTo(pm); + + e.Handled = true; + } + else if (e.HasKeyword(0x0005)) // *resign* | *quit* + { + if (pm.NpcGuild != NpcGuild) + { + SayTo(pm, 501052); // Thou dost not belong to my guild! + } + else if (pm.NpcGuildJoinTime + QuitAge > DateTime.UtcNow || + pm.NpcGuildGameTime + QuitGameAge > pm.GameTime) + { + SayTo(pm, 501053); // You just joined my guild! You must wait a week to resign. + } + else + { + SayTo(pm, 501054); // I accept thy resignation. + pm.NpcGuild = NpcGuild.None; + } + + e.Handled = true; + } + } + + base.OnSpeech(e); + } + + public override bool OnGoldGiven(Mobile from, Gold dropped) + { + if (from is PlayerMobile pm && dropped.Amount == JoinCost) + { + if (pm.NpcGuild == NpcGuild) + { + SayTo(pm, 501047); // Thou art already a member of our guild. + } + else if (pm.NpcGuild != NpcGuild.None) + { + SayTo(pm, 501046); // Thou must resign from thy other guild first. + } + else if (pm.GameTime < JoinGameAge || pm.CreationTime + JoinAge > DateTime.UtcNow) + { + SayTo(pm, 501048); // You are too young to join my guild... + } + else if (CheckCustomReqs(pm)) + { + SayWelcomeTo(pm); + + pm.NpcGuild = NpcGuild; + pm.NpcGuildJoinTime = DateTime.UtcNow; + pm.NpcGuildGameTime = pm.GameTime; + + dropped.Delete(); + return true; + } + + return false; + } + + return base.OnGoldGiven(from, dropped); + } + + 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 Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/BlacksmithGuildmaster.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/BlacksmithGuildmaster.cs index 8fa637db7..7b3e63e39 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/BlacksmithGuildmaster.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/BlacksmithGuildmaster.cs @@ -2,65 +2,65 @@ using Server.Items; namespace Server.Mobiles { - public class BlacksmithGuildmaster : BaseGuildmaster - { - [Constructible] - public BlacksmithGuildmaster() : base("blacksmith") + public class BlacksmithGuildmaster : BaseGuildmaster { - SetSkill(SkillName.ArmsLore, 65.0, 88.0); - SetSkill(SkillName.Blacksmith, 90.0, 100.0); - SetSkill(SkillName.Macing, 36.0, 68.0); - SetSkill(SkillName.Parry, 36.0, 68.0); + [Constructible] + public BlacksmithGuildmaster() : base("blacksmith") + { + SetSkill(SkillName.ArmsLore, 65.0, 88.0); + SetSkill(SkillName.Blacksmith, 90.0, 100.0); + SetSkill(SkillName.Macing, 36.0, 68.0); + SetSkill(SkillName.Parry, 36.0, 68.0); + } + + public BlacksmithGuildmaster(Serial serial) : base(serial) + { + } + + public override NpcGuild NpcGuild => NpcGuild.BlacksmithsGuild; + + public override bool IsActiveVendor => true; + + public override bool ClickTitle => true; + + public override VendorShoeType ShoeType => VendorShoeType.ThighBoots; + + public override void InitSBInfo() + { + SBInfos.Add(new SBBlacksmith()); + } + + public override void InitOutfit() + { + base.InitOutfit(); + + Item item = Utility.RandomBool() ? null : new RingmailChest(); + + if (item != null && !EquipItem(item)) + { + item.Delete(); + item = null; + } + + if (item == null) + AddItem(new FullApron()); + + AddItem(new Bascinet()); + AddItem(new SmithHammer()); + } + + 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 BlacksmithGuildmaster(Serial serial) : base(serial) - { - } - - public override NpcGuild NpcGuild => NpcGuild.BlacksmithsGuild; - - public override bool IsActiveVendor => true; - - public override bool ClickTitle => true; - - public override VendorShoeType ShoeType => VendorShoeType.ThighBoots; - - public override void InitSBInfo() - { - SBInfos.Add(new SBBlacksmith()); - } - - public override void InitOutfit() - { - base.InitOutfit(); - - Item item = Utility.RandomBool() ? null : new RingmailChest(); - - if (item != null && !EquipItem(item)) - { - item.Delete(); - item = null; - } - - if (item == null) - AddItem(new FullApron()); - - AddItem(new Bascinet()); - AddItem(new SmithHammer()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/FisherGuildmaster.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/FisherGuildmaster.cs index f83d5ffca..03a4ff217 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/FisherGuildmaster.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/FisherGuildmaster.cs @@ -1,31 +1,31 @@ namespace Server.Mobiles { - public class FisherGuildmaster : BaseGuildmaster - { - [Constructible] - public FisherGuildmaster() : base("fisher") + public class FisherGuildmaster : BaseGuildmaster { - SetSkill(SkillName.Fishing, 80.0, 100.0); + [Constructible] + public FisherGuildmaster() : base("fisher") + { + SetSkill(SkillName.Fishing, 80.0, 100.0); + } + + public FisherGuildmaster(Serial serial) : base(serial) + { + } + + public override NpcGuild NpcGuild => NpcGuild.FishermensGuild; + + 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 FisherGuildmaster(Serial serial) : base(serial) - { - } - - public override NpcGuild NpcGuild => NpcGuild.FishermensGuild; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/HealerGuildmaster.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/HealerGuildmaster.cs index c923709d4..0b19e11bf 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/HealerGuildmaster.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/HealerGuildmaster.cs @@ -2,45 +2,45 @@ using Server.Items; namespace Server.Mobiles { - public class HealerGuildmaster : BaseGuildmaster - { - [Constructible] - public HealerGuildmaster() : base("healer") + public class HealerGuildmaster : BaseGuildmaster { - SetSkill(SkillName.Anatomy, 85.0, 100.0); - SetSkill(SkillName.Healing, 90.0, 100.0); - SetSkill(SkillName.Forensics, 75.0, 98.0); - SetSkill(SkillName.MagicResist, 75.0, 98.0); - SetSkill(SkillName.SpiritSpeak, 65.0, 88.0); + [Constructible] + public HealerGuildmaster() : base("healer") + { + SetSkill(SkillName.Anatomy, 85.0, 100.0); + SetSkill(SkillName.Healing, 90.0, 100.0); + SetSkill(SkillName.Forensics, 75.0, 98.0); + SetSkill(SkillName.MagicResist, 75.0, 98.0); + SetSkill(SkillName.SpiritSpeak, 65.0, 88.0); + } + + public HealerGuildmaster(Serial serial) : base(serial) + { + } + + public override NpcGuild NpcGuild => NpcGuild.HealersGuild; + + public override VendorShoeType ShoeType => VendorShoeType.Sandals; + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new Robe(Utility.RandomYellowHue())); + } + + 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 HealerGuildmaster(Serial serial) : base(serial) - { - } - - public override NpcGuild NpcGuild => NpcGuild.HealersGuild; - - public override VendorShoeType ShoeType => VendorShoeType.Sandals; - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new Robe(Utility.RandomYellowHue())); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/MageGuildmaster.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/MageGuildmaster.cs index 1d094753f..c4e65addd 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/MageGuildmaster.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/MageGuildmaster.cs @@ -2,48 +2,48 @@ using Server.Items; namespace Server.Mobiles { - public class MageGuildmaster : BaseGuildmaster - { - [Constructible] - public MageGuildmaster() : base("mage") + public class MageGuildmaster : BaseGuildmaster { - SetSkill(SkillName.EvalInt, 85.0, 100.0); - SetSkill(SkillName.Inscribe, 65.0, 88.0); - SetSkill(SkillName.MagicResist, 64.0, 100.0); - SetSkill(SkillName.Magery, 90.0, 100.0); - SetSkill(SkillName.Wrestling, 60.0, 83.0); - SetSkill(SkillName.Meditation, 85.0, 100.0); - SetSkill(SkillName.Macing, 36.0, 68.0); + [Constructible] + public MageGuildmaster() : base("mage") + { + SetSkill(SkillName.EvalInt, 85.0, 100.0); + SetSkill(SkillName.Inscribe, 65.0, 88.0); + SetSkill(SkillName.MagicResist, 64.0, 100.0); + SetSkill(SkillName.Magery, 90.0, 100.0); + SetSkill(SkillName.Wrestling, 60.0, 83.0); + SetSkill(SkillName.Meditation, 85.0, 100.0); + SetSkill(SkillName.Macing, 36.0, 68.0); + } + + public MageGuildmaster(Serial serial) : base(serial) + { + } + + public override NpcGuild NpcGuild => NpcGuild.MagesGuild; + + public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Shoes : VendorShoeType.Sandals; + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new Robe(Utility.RandomBlueHue())); + AddItem(new GnarledStaff()); + } + + 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 MageGuildmaster(Serial serial) : base(serial) - { - } - - public override NpcGuild NpcGuild => NpcGuild.MagesGuild; - - public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Shoes : VendorShoeType.Sandals; - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new Robe(Utility.RandomBlueHue())); - AddItem(new GnarledStaff()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/MerchantGuildmaster.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/MerchantGuildmaster.cs index e5ad113e2..64ddbebde 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/MerchantGuildmaster.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/MerchantGuildmaster.cs @@ -1,32 +1,32 @@ namespace Server.Mobiles { - public class MerchantGuildmaster : BaseGuildmaster - { - [Constructible] - public MerchantGuildmaster() : base("merchant") + public class MerchantGuildmaster : BaseGuildmaster { - SetSkill(SkillName.ItemID, 85.0, 100.0); - SetSkill(SkillName.ArmsLore, 85.0, 100.0); + [Constructible] + public MerchantGuildmaster() : base("merchant") + { + SetSkill(SkillName.ItemID, 85.0, 100.0); + SetSkill(SkillName.ArmsLore, 85.0, 100.0); + } + + public MerchantGuildmaster(Serial serial) : base(serial) + { + } + + public override NpcGuild NpcGuild => NpcGuild.MerchantsGuild; + + 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 MerchantGuildmaster(Serial serial) : base(serial) - { - } - - public override NpcGuild NpcGuild => NpcGuild.MerchantsGuild; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/MinerGuildmaster.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/MinerGuildmaster.cs index d6fb1b0f1..a0cfdcc2f 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/MinerGuildmaster.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/MinerGuildmaster.cs @@ -1,32 +1,32 @@ namespace Server.Mobiles { - public class MinerGuildmaster : BaseGuildmaster - { - [Constructible] - public MinerGuildmaster() : base("miner") + public class MinerGuildmaster : BaseGuildmaster { - SetSkill(SkillName.ItemID, 60.0, 83.0); - SetSkill(SkillName.Mining, 90.0, 100.0); + [Constructible] + public MinerGuildmaster() : base("miner") + { + SetSkill(SkillName.ItemID, 60.0, 83.0); + SetSkill(SkillName.Mining, 90.0, 100.0); + } + + public MinerGuildmaster(Serial serial) : base(serial) + { + } + + public override NpcGuild NpcGuild => NpcGuild.MinersGuild; + + 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 MinerGuildmaster(Serial serial) : base(serial) - { - } - - public override NpcGuild NpcGuild => NpcGuild.MinersGuild; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/RangerGuildmaster.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/RangerGuildmaster.cs index aab3fee6d..f77318d54 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/RangerGuildmaster.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/RangerGuildmaster.cs @@ -1,41 +1,41 @@ namespace Server.Mobiles { - public class RangerGuildmaster : BaseGuildmaster - { - [Constructible] - public RangerGuildmaster() : base("ranger") + public class RangerGuildmaster : BaseGuildmaster { - SetSkill(SkillName.AnimalLore, 64.0, 100.0); - SetSkill(SkillName.Camping, 75.0, 98.0); - SetSkill(SkillName.Hiding, 75.0, 98.0); - SetSkill(SkillName.MagicResist, 75.0, 98.0); - SetSkill(SkillName.Tactics, 65.0, 88.0); - SetSkill(SkillName.Archery, 90.0, 100.0); - SetSkill(SkillName.Tracking, 90.0, 100.0); - SetSkill(SkillName.Stealth, 60.0, 83.0); - SetSkill(SkillName.Fencing, 36.0, 68.0); - SetSkill(SkillName.Herding, 36.0, 68.0); - SetSkill(SkillName.Swords, 45.0, 68.0); + [Constructible] + public RangerGuildmaster() : base("ranger") + { + SetSkill(SkillName.AnimalLore, 64.0, 100.0); + SetSkill(SkillName.Camping, 75.0, 98.0); + SetSkill(SkillName.Hiding, 75.0, 98.0); + SetSkill(SkillName.MagicResist, 75.0, 98.0); + SetSkill(SkillName.Tactics, 65.0, 88.0); + SetSkill(SkillName.Archery, 90.0, 100.0); + SetSkill(SkillName.Tracking, 90.0, 100.0); + SetSkill(SkillName.Stealth, 60.0, 83.0); + SetSkill(SkillName.Fencing, 36.0, 68.0); + SetSkill(SkillName.Herding, 36.0, 68.0); + SetSkill(SkillName.Swords, 45.0, 68.0); + } + + public RangerGuildmaster(Serial serial) : base(serial) + { + } + + public override NpcGuild NpcGuild => NpcGuild.RangersGuild; + + 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 RangerGuildmaster(Serial serial) : base(serial) - { - } - - public override NpcGuild NpcGuild => NpcGuild.RangersGuild; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/TailorGuildmaster.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/TailorGuildmaster.cs index 567663ddd..713afdf80 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/TailorGuildmaster.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/TailorGuildmaster.cs @@ -1,31 +1,31 @@ namespace Server.Mobiles { - public class TailorGuildmaster : BaseGuildmaster - { - [Constructible] - public TailorGuildmaster() : base("tailor") + public class TailorGuildmaster : BaseGuildmaster { - SetSkill(SkillName.Tailoring, 90.0, 100.0); + [Constructible] + public TailorGuildmaster() : base("tailor") + { + SetSkill(SkillName.Tailoring, 90.0, 100.0); + } + + public TailorGuildmaster(Serial serial) : base(serial) + { + } + + public override NpcGuild NpcGuild => NpcGuild.TailorsGuild; + + 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 TailorGuildmaster(Serial serial) : base(serial) - { - } - - public override NpcGuild NpcGuild => NpcGuild.TailorsGuild; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/ThiefGuildmaster.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/ThiefGuildmaster.cs index 59194dc70..2ca32d518 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/ThiefGuildmaster.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/ThiefGuildmaster.cs @@ -3,119 +3,119 @@ using Server.Items; namespace Server.Mobiles { - public class ThiefGuildmaster : BaseGuildmaster - { - [Constructible] - public ThiefGuildmaster() : base("thief") + public class ThiefGuildmaster : BaseGuildmaster { - SetSkill(SkillName.DetectHidden, 75.0, 98.0); - SetSkill(SkillName.Hiding, 65.0, 88.0); - SetSkill(SkillName.Lockpicking, 85.0, 100.0); - SetSkill(SkillName.Snooping, 90.0, 100.0); - SetSkill(SkillName.Poisoning, 60.0, 83.0); - SetSkill(SkillName.Stealing, 90.0, 100.0); - SetSkill(SkillName.Fencing, 75.0, 98.0); - SetSkill(SkillName.Stealth, 85.0, 100.0); - SetSkill(SkillName.RemoveTrap, 85.0, 100.0); - } - - public ThiefGuildmaster(Serial serial) : base(serial) - { - } - - public override NpcGuild NpcGuild => NpcGuild.ThievesGuild; - - public override TimeSpan JoinAge => TimeSpan.FromDays(7.0); - - public override void InitOutfit() - { - base.InitOutfit(); - - if (Utility.RandomBool()) - AddItem(new Kryss()); - else - AddItem(new Dagger()); - } - - public override bool CheckCustomReqs(PlayerMobile pm) - { - if (pm.Young) - { - SayTo(pm, 502089); // You cannot be a member of the Thieves' Guild while you are Young. - return false; - } - - if (pm.Kills > 0) - { - SayTo(pm, 501050); // This guild is for cunning thieves, not oafish cutthroats. - return false; - } - - if (pm.Skills.Stealing.Base < 60.0) - { - SayTo(pm, 501051); // You must be at least a journeyman pickpocket to join this elite organization. - return false; - } - - return true; - } - - public override void SayWelcomeTo(Mobile m) - { - SayTo(m, 1008053); // Welcome to the guild! Stay to the shadows, friend. - } - - public override bool HandlesOnSpeech(Mobile from) - { - if (from.InRange(Location, 2)) - return true; - - return base.HandlesOnSpeech(from); - } - - public override void OnSpeech(SpeechEventArgs e) - { - Mobile from = e.Mobile; - - if (!e.Handled && from is PlayerMobile pm && pm.InRange(Location, 2) && e.HasKeyword(0x1F)) // *disguise* - { - if (pm.NpcGuild == NpcGuild.ThievesGuild) - SayTo(pm, 501839); // That particular item costs 700 gold pieces. - else - SayTo(pm, 501838); // I don't know what you're talking about. - - e.Handled = true; - } - - base.OnSpeech(e); - } - - public override bool OnGoldGiven(Mobile from, Gold dropped) - { - if (from is PlayerMobile pm && dropped.Amount == 700) - if (pm.NpcGuild == NpcGuild.ThievesGuild) + [Constructible] + public ThiefGuildmaster() : base("thief") { - pm.AddToBackpack(new DisguiseKit()); - - dropped.Delete(); - return true; + SetSkill(SkillName.DetectHidden, 75.0, 98.0); + SetSkill(SkillName.Hiding, 65.0, 88.0); + SetSkill(SkillName.Lockpicking, 85.0, 100.0); + SetSkill(SkillName.Snooping, 90.0, 100.0); + SetSkill(SkillName.Poisoning, 60.0, 83.0); + SetSkill(SkillName.Stealing, 90.0, 100.0); + SetSkill(SkillName.Fencing, 75.0, 98.0); + SetSkill(SkillName.Stealth, 85.0, 100.0); + SetSkill(SkillName.RemoveTrap, 85.0, 100.0); } - return base.OnGoldGiven(from, dropped); + public ThiefGuildmaster(Serial serial) : base(serial) + { + } + + public override NpcGuild NpcGuild => NpcGuild.ThievesGuild; + + public override TimeSpan JoinAge => TimeSpan.FromDays(7.0); + + public override void InitOutfit() + { + base.InitOutfit(); + + if (Utility.RandomBool()) + AddItem(new Kryss()); + else + AddItem(new Dagger()); + } + + public override bool CheckCustomReqs(PlayerMobile pm) + { + if (pm.Young) + { + SayTo(pm, 502089); // You cannot be a member of the Thieves' Guild while you are Young. + return false; + } + + if (pm.Kills > 0) + { + SayTo(pm, 501050); // This guild is for cunning thieves, not oafish cutthroats. + return false; + } + + if (pm.Skills.Stealing.Base < 60.0) + { + SayTo(pm, 501051); // You must be at least a journeyman pickpocket to join this elite organization. + return false; + } + + return true; + } + + public override void SayWelcomeTo(Mobile m) + { + SayTo(m, 1008053); // Welcome to the guild! Stay to the shadows, friend. + } + + public override bool HandlesOnSpeech(Mobile from) + { + if (from.InRange(Location, 2)) + return true; + + return base.HandlesOnSpeech(from); + } + + public override void OnSpeech(SpeechEventArgs e) + { + var from = e.Mobile; + + if (!e.Handled && from is PlayerMobile pm && pm.InRange(Location, 2) && e.HasKeyword(0x1F)) // *disguise* + { + if (pm.NpcGuild == NpcGuild.ThievesGuild) + SayTo(pm, 501839); // That particular item costs 700 gold pieces. + else + SayTo(pm, 501838); // I don't know what you're talking about. + + e.Handled = true; + } + + base.OnSpeech(e); + } + + public override bool OnGoldGiven(Mobile from, Gold dropped) + { + if (from is PlayerMobile pm && dropped.Amount == 700) + if (pm.NpcGuild == NpcGuild.ThievesGuild) + { + pm.AddToBackpack(new DisguiseKit()); + + dropped.Delete(); + return true; + } + + return base.OnGoldGiven(from, dropped); + } + + 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 Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/TinkerGuildmaster.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/TinkerGuildmaster.cs index 73439e2f7..8f8b5ae71 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/TinkerGuildmaster.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/TinkerGuildmaster.cs @@ -4,82 +4,83 @@ using Server.Items; namespace Server.Mobiles { - public class TinkerGuildmaster : BaseGuildmaster - { - [Constructible] - public TinkerGuildmaster() : base("tinker") + public class TinkerGuildmaster : BaseGuildmaster { - SetSkill(SkillName.Lockpicking, 65.0, 88.0); - SetSkill(SkillName.Tinkering, 90.0, 100.0); - SetSkill(SkillName.RemoveTrap, 85.0, 100.0); - } - - public TinkerGuildmaster(Serial serial) : base(serial) - { - } - - public override NpcGuild NpcGuild => NpcGuild.TinkersGuild; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void AddCustomContextEntries(Mobile from, List list) - { - if (Core.ML && from.Alive) - { - RechargeEntry entry = new RechargeEntry(from, this); - - if (WeaponEngravingTool.Find(from) == null) - entry.Enabled = false; - - list.Add(entry); - } - - base.AddCustomContextEntries(from, list); - } - - private class RechargeEntry : ContextMenuEntry - { - private readonly Mobile m_From; - private readonly Mobile m_Vendor; - - public RechargeEntry(Mobile from, Mobile vendor) : base(6271, 6) - { - m_From = from; - m_Vendor = vendor; - } - - public override void OnClick() - { - if (!Core.ML || m_Vendor?.Deleted != false) - return; - - WeaponEngravingTool tool = WeaponEngravingTool.Find(m_From); - - if (tool?.UsesRemaining <= 0) + [Constructible] + public TinkerGuildmaster() : base("tinker") { - if (Banker.GetBalance(m_From) >= 100000) - m_From.SendGump(new WeaponEngravingTool.ConfirmGump(tool, m_Vendor)); - else - m_Vendor.Say(1076167); // You need a 100,000 gold and a blue diamond to recharge the weapon engraver. + SetSkill(SkillName.Lockpicking, 65.0, 88.0); + SetSkill(SkillName.Tinkering, 90.0, 100.0); + SetSkill(SkillName.RemoveTrap, 85.0, 100.0); } - else + + public TinkerGuildmaster(Serial serial) : base(serial) { - m_Vendor.Say( - 1076164); // I can only help with this if you are carrying an engraving tool that needs repair. } - } + + public override NpcGuild NpcGuild => NpcGuild.TinkersGuild; + + 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 AddCustomContextEntries(Mobile from, List list) + { + if (Core.ML && from.Alive) + { + var entry = new RechargeEntry(from, this); + + if (WeaponEngravingTool.Find(from) == null) + entry.Enabled = false; + + list.Add(entry); + } + + base.AddCustomContextEntries(from, list); + } + + private class RechargeEntry : ContextMenuEntry + { + private readonly Mobile m_From; + private readonly Mobile m_Vendor; + + public RechargeEntry(Mobile from, Mobile vendor) : base(6271, 6) + { + m_From = from; + m_Vendor = vendor; + } + + public override void OnClick() + { + if (!Core.ML || m_Vendor?.Deleted != false) + return; + + var tool = WeaponEngravingTool.Find(m_From); + + if (tool?.UsesRemaining <= 0) + { + if (Banker.GetBalance(m_From) >= 100000) + m_From.SendGump(new WeaponEngravingTool.ConfirmGump(tool, m_Vendor)); + else + m_Vendor.Say(1076167); // You need a 100,000 gold and a blue diamond to recharge the weapon engraver. + } + else + { + m_Vendor.Say( + 1076164 + ); // I can only help with this if you are carrying an engraving tool that needs repair. + } + } + } } - } } diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/WarriorGuildmaster.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/WarriorGuildmaster.cs index 5c96f0ad7..4b9be9a1e 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/WarriorGuildmaster.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/WarriorGuildmaster.cs @@ -1,37 +1,37 @@ namespace Server.Mobiles { - public class WarriorGuildmaster : BaseGuildmaster - { - [Constructible] - public WarriorGuildmaster() : base("warrior") + public class WarriorGuildmaster : BaseGuildmaster { - SetSkill(SkillName.ArmsLore, 75.0, 98.0); - SetSkill(SkillName.Parry, 85.0, 100.0); - SetSkill(SkillName.MagicResist, 60.0, 83.0); - SetSkill(SkillName.Tactics, 85.0, 100.0); - SetSkill(SkillName.Swords, 90.0, 100.0); - SetSkill(SkillName.Macing, 60.0, 83.0); - SetSkill(SkillName.Fencing, 60.0, 83.0); + [Constructible] + public WarriorGuildmaster() : base("warrior") + { + SetSkill(SkillName.ArmsLore, 75.0, 98.0); + SetSkill(SkillName.Parry, 85.0, 100.0); + SetSkill(SkillName.MagicResist, 60.0, 83.0); + SetSkill(SkillName.Tactics, 85.0, 100.0); + SetSkill(SkillName.Swords, 90.0, 100.0); + SetSkill(SkillName.Macing, 60.0, 83.0); + SetSkill(SkillName.Fencing, 60.0, 83.0); + } + + public WarriorGuildmaster(Serial serial) : base(serial) + { + } + + public override NpcGuild NpcGuild => NpcGuild.WarriorsGuild; + + 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 WarriorGuildmaster(Serial serial) : base(serial) - { - } - - public override NpcGuild NpcGuild => NpcGuild.WarriorsGuild; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/GypsyAnimalTrainer.cs b/Projects/UOContent/Mobiles/Vendors/NPC/GypsyAnimalTrainer.cs index e8aa216e7..712ba1243 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/GypsyAnimalTrainer.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/GypsyAnimalTrainer.cs @@ -1,71 +1,71 @@ namespace Server.Mobiles { - public class GypsyAnimalTrainer : AnimalTrainer - { - [Constructible] - public GypsyAnimalTrainer() + public class GypsyAnimalTrainer : AnimalTrainer { - if (Utility.RandomBool()) - Title = "the gypsy animal trainer"; - else - Title = "the gypsy animal herder"; + [Constructible] + public GypsyAnimalTrainer() + { + if (Utility.RandomBool()) + Title = "the gypsy animal trainer"; + else + Title = "the gypsy animal herder"; + } + + public GypsyAnimalTrainer(Serial serial) : base(serial) + { + } + + public override VendorShoeType ShoeType => Female ? VendorShoeType.ThighBoots : VendorShoeType.Boots; + + public override int GetShoeHue() => 0; + + public override void InitOutfit() + { + base.InitOutfit(); + + var item = FindItemOnLayer(Layer.Pants); + + if (item != null) + item.Hue = Utility.RandomBrightHue(); + + item = FindItemOnLayer(Layer.OuterLegs); + + if (item != null) + item.Hue = Utility.RandomBrightHue(); + + item = FindItemOnLayer(Layer.InnerLegs); + + if (item != null) + item.Hue = Utility.RandomBrightHue(); + + item = FindItemOnLayer(Layer.OuterTorso); + + if (item != null) + item.Hue = Utility.RandomBrightHue(); + + item = FindItemOnLayer(Layer.InnerTorso); + + if (item != null) + item.Hue = Utility.RandomBrightHue(); + + item = FindItemOnLayer(Layer.Shirt); + + if (item != null) + item.Hue = Utility.RandomBrightHue(); + } + + 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 GypsyAnimalTrainer(Serial serial) : base(serial) - { - } - - public override VendorShoeType ShoeType => Female ? VendorShoeType.ThighBoots : VendorShoeType.Boots; - - public override int GetShoeHue() => 0; - - public override void InitOutfit() - { - base.InitOutfit(); - - Item item = FindItemOnLayer(Layer.Pants); - - if (item != null) - item.Hue = Utility.RandomBrightHue(); - - item = FindItemOnLayer(Layer.OuterLegs); - - if (item != null) - item.Hue = Utility.RandomBrightHue(); - - item = FindItemOnLayer(Layer.InnerLegs); - - if (item != null) - item.Hue = Utility.RandomBrightHue(); - - item = FindItemOnLayer(Layer.OuterTorso); - - if (item != null) - item.Hue = Utility.RandomBrightHue(); - - item = FindItemOnLayer(Layer.InnerTorso); - - if (item != null) - item.Hue = Utility.RandomBrightHue(); - - item = FindItemOnLayer(Layer.Shirt); - - if (item != null) - item.Hue = Utility.RandomBrightHue(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/GypsyBanker.cs b/Projects/UOContent/Mobiles/Vendors/NPC/GypsyBanker.cs index 2b4212a2d..ab491fc28 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/GypsyBanker.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/GypsyBanker.cs @@ -2,81 +2,81 @@ using Server.Items; namespace Server.Mobiles { - public class GypsyBanker : Banker - { - [Constructible] - public GypsyBanker() => Title = "the gypsy banker"; - - public GypsyBanker(Serial serial) : base(serial) + public class GypsyBanker : Banker { - } + [Constructible] + public GypsyBanker() => Title = "the gypsy banker"; - public override bool IsActiveVendor => false; - public override NpcGuild NpcGuild => NpcGuild.None; - public override bool ClickTitle => false; - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem( - Utility.Random(4) switch + public GypsyBanker(Serial serial) : base(serial) { - 0 => new JesterHat(Utility.RandomBrightHue()), - 1 => new Bandana(Utility.RandomBrightHue()), - 2 => new SkullCap(Utility.RandomBrightHue()), - _ => null // 3 } - ); - Item item = FindItemOnLayer(Layer.Pants); + public override bool IsActiveVendor => false; + public override NpcGuild NpcGuild => NpcGuild.None; + public override bool ClickTitle => false; - if (item != null) - item.Hue = Utility.RandomBrightHue(); + public override void InitOutfit() + { + base.InitOutfit(); - item = FindItemOnLayer(Layer.Shoes); + AddItem( + Utility.Random(4) switch + { + 0 => new JesterHat(Utility.RandomBrightHue()), + 1 => new Bandana(Utility.RandomBrightHue()), + 2 => new SkullCap(Utility.RandomBrightHue()), + _ => null // 3 + } + ); - if (item != null) - item.Hue = Utility.RandomBrightHue(); + var item = FindItemOnLayer(Layer.Pants); - item = FindItemOnLayer(Layer.OuterLegs); + if (item != null) + item.Hue = Utility.RandomBrightHue(); - if (item != null) - item.Hue = Utility.RandomBrightHue(); + item = FindItemOnLayer(Layer.Shoes); - item = FindItemOnLayer(Layer.InnerLegs); + if (item != null) + item.Hue = Utility.RandomBrightHue(); - if (item != null) - item.Hue = Utility.RandomBrightHue(); + item = FindItemOnLayer(Layer.OuterLegs); - item = FindItemOnLayer(Layer.OuterTorso); + if (item != null) + item.Hue = Utility.RandomBrightHue(); - if (item != null) - item.Hue = Utility.RandomBrightHue(); + item = FindItemOnLayer(Layer.InnerLegs); - item = FindItemOnLayer(Layer.InnerTorso); + if (item != null) + item.Hue = Utility.RandomBrightHue(); - if (item != null) - item.Hue = Utility.RandomBrightHue(); + item = FindItemOnLayer(Layer.OuterTorso); - item = FindItemOnLayer(Layer.Shirt); + if (item != null) + item.Hue = Utility.RandomBrightHue(); - if (item != null) - item.Hue = Utility.RandomBrightHue(); + item = FindItemOnLayer(Layer.InnerTorso); + + if (item != null) + item.Hue = Utility.RandomBrightHue(); + + item = FindItemOnLayer(Layer.Shirt); + + if (item != null) + item.Hue = Utility.RandomBrightHue(); + } + + 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 Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/GypsyMaiden.cs b/Projects/UOContent/Mobiles/Vendors/NPC/GypsyMaiden.cs index a43a9ea8e..aec77c170 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/GypsyMaiden.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/GypsyMaiden.cs @@ -3,73 +3,73 @@ using Server.Items; namespace Server.Mobiles { - public class GypsyMaiden : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public GypsyMaiden() : base("the gypsy maiden") + public class GypsyMaiden : BaseVendor { - } + private readonly List m_SBInfos = new List(); - public GypsyMaiden(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override bool GetGender() => true; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBProvisioner()); - } - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem( - Utility.Random(4) switch + [Constructible] + public GypsyMaiden() : base("the gypsy maiden") { - 0 => new JesterHat(Utility.RandomBrightHue()), - 1 => new Bandana(Utility.RandomBrightHue()), - 2 => new SkullCap(Utility.RandomBrightHue()), - _ => null // 3 } - ); - if (Utility.RandomBool()) - AddItem(new HalfApron(Utility.RandomBrightHue())); + public GypsyMaiden(Serial serial) : base(serial) + { + } - Item item = FindItemOnLayer(Layer.Pants); + protected override List SBInfos => m_SBInfos; - if (item != null) - item.Hue = Utility.RandomBrightHue(); + public override bool GetGender() => true; - item = FindItemOnLayer(Layer.OuterLegs); + public override void InitSBInfo() + { + m_SBInfos.Add(new SBProvisioner()); + } - if (item != null) - item.Hue = Utility.RandomBrightHue(); + public override void InitOutfit() + { + base.InitOutfit(); - item = FindItemOnLayer(Layer.InnerLegs); + AddItem( + Utility.Random(4) switch + { + 0 => new JesterHat(Utility.RandomBrightHue()), + 1 => new Bandana(Utility.RandomBrightHue()), + 2 => new SkullCap(Utility.RandomBrightHue()), + _ => null // 3 + } + ); - if (item != null) - item.Hue = Utility.RandomBrightHue(); + if (Utility.RandomBool()) + AddItem(new HalfApron(Utility.RandomBrightHue())); + + var item = FindItemOnLayer(Layer.Pants); + + if (item != null) + item.Hue = Utility.RandomBrightHue(); + + item = FindItemOnLayer(Layer.OuterLegs); + + if (item != null) + item.Hue = Utility.RandomBrightHue(); + + item = FindItemOnLayer(Layer.InnerLegs); + + if (item != null) + item.Hue = Utility.RandomBrightHue(); + } + + 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 Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/HairStylist.cs b/Projects/UOContent/Mobiles/Vendors/NPC/HairStylist.cs index 6d056414a..a96727ab4 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/HairStylist.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/HairStylist.cs @@ -2,41 +2,41 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class HairStylist : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public HairStylist() : base("the hair stylist") + public class HairStylist : BaseVendor { - SetSkill(SkillName.Alchemy, 80.0, 100.0); - SetSkill(SkillName.Magery, 90.0, 110.0); - SetSkill(SkillName.TasteID, 85.0, 100.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public HairStylist() : base("the hair stylist") + { + SetSkill(SkillName.Alchemy, 80.0, 100.0); + SetSkill(SkillName.Magery, 90.0, 110.0); + SetSkill(SkillName.TasteID, 85.0, 100.0); + } + + public HairStylist(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBHairStylist()); + } + + 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 HairStylist(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBHairStylist()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Herbalist.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Herbalist.cs index 9f81dc196..e6aa4a87e 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Herbalist.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Herbalist.cs @@ -2,45 +2,45 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class Herbalist : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Herbalist() : base("the herbalist") + public class Herbalist : BaseVendor { - SetSkill(SkillName.Alchemy, 80.0, 100.0); - SetSkill(SkillName.Cooking, 80.0, 100.0); - SetSkill(SkillName.TasteID, 80.0, 100.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Herbalist() : base("the herbalist") + { + SetSkill(SkillName.Alchemy, 80.0, 100.0); + SetSkill(SkillName.Cooking, 80.0, 100.0); + SetSkill(SkillName.TasteID, 80.0, 100.0); + } + + public Herbalist(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override NpcGuild NpcGuild => NpcGuild.MagesGuild; + + public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Shoes : VendorShoeType.Sandals; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBHerbalist()); + } + + 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 Herbalist(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override NpcGuild NpcGuild => NpcGuild.MagesGuild; - - public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Shoes : VendorShoeType.Sandals; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBHerbalist()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/HolyMage.cs b/Projects/UOContent/Mobiles/Vendors/NPC/HolyMage.cs index 0eee4a40b..732c09f31 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/HolyMage.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/HolyMage.cs @@ -3,80 +3,80 @@ using Server.Items; namespace Server.Mobiles { - public class HolyMage : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public HolyMage() : base("the Holy Mage") + public class HolyMage : BaseVendor { - SetSkill(SkillName.EvalInt, 65.0, 88.0); - SetSkill(SkillName.Inscribe, 60.0, 83.0); - SetSkill(SkillName.Magery, 64.0, 100.0); - SetSkill(SkillName.Meditation, 60.0, 83.0); - SetSkill(SkillName.MagicResist, 65.0, 88.0); - SetSkill(SkillName.Wrestling, 36.0, 68.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public HolyMage() : base("the Holy Mage") + { + SetSkill(SkillName.EvalInt, 65.0, 88.0); + SetSkill(SkillName.Inscribe, 60.0, 83.0); + SetSkill(SkillName.Magery, 64.0, 100.0); + SetSkill(SkillName.Meditation, 60.0, 83.0); + SetSkill(SkillName.MagicResist, 65.0, 88.0); + SetSkill(SkillName.Wrestling, 36.0, 68.0); + } + + public HolyMage(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBHolyMage()); + } + + public Item ApplyHue(Item item, int hue) + { + item.Hue = hue; + + return item; + } + + public override void InitOutfit() + { + AddItem(ApplyHue(new Robe(), 0x47E)); + AddItem(ApplyHue(new ThighBoots(), 0x47E)); + AddItem(ApplyHue(new BlackStaff(), 0x47E)); + + if (Female) + { + AddItem(ApplyHue(new LeatherGloves(), 0x47E)); + AddItem(ApplyHue(new GoldNecklace(), 0x47E)); + } + else + { + AddItem(ApplyHue(new PlateGloves(), 0x47E)); + AddItem(ApplyHue(new PlateGorget(), 0x47E)); + } + + HairItemID = Utility.Random(Female ? 2 : 1) switch + { + 0 => 0x203C, + 1 => 0x203D, + _ => HairItemID + }; + + HairHue = 0x47E; + + PackGold(100, 200); + } + + 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 HolyMage(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBHolyMage()); - } - - public Item ApplyHue(Item item, int hue) - { - item.Hue = hue; - - return item; - } - - public override void InitOutfit() - { - AddItem(ApplyHue(new Robe(), 0x47E)); - AddItem(ApplyHue(new ThighBoots(), 0x47E)); - AddItem(ApplyHue(new BlackStaff(), 0x47E)); - - if (Female) - { - AddItem(ApplyHue(new LeatherGloves(), 0x47E)); - AddItem(ApplyHue(new GoldNecklace(), 0x47E)); - } - else - { - AddItem(ApplyHue(new PlateGloves(), 0x47E)); - AddItem(ApplyHue(new PlateGorget(), 0x47E)); - } - - HairItemID = Utility.Random(Female ? 2 : 1) switch - { - 0 => 0x203C, - 1 => 0x203D, - _ => HairItemID - }; - - HairHue = 0x47E; - - PackGold(100, 200); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/InnKeeper.cs b/Projects/UOContent/Mobiles/Vendors/NPC/InnKeeper.cs index e8db43d15..a982be220 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/InnKeeper.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/InnKeeper.cs @@ -2,43 +2,43 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class InnKeeper : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public InnKeeper() : base("the innkeeper") + public class InnKeeper : BaseVendor { + private readonly List m_SBInfos = new List(); + + [Constructible] + public InnKeeper() : base("the innkeeper") + { + } + + public InnKeeper(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Sandals : VendorShoeType.Shoes; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBInnKeeper()); + + if (IsTokunoVendor) + m_SBInfos.Add(new SBSEFood()); + } + + 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 InnKeeper(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Sandals : VendorShoeType.Shoes; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBInnKeeper()); - - if (IsTokunoVendor) - m_SBInfos.Add(new SBSEFood()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/IronWorker.cs b/Projects/UOContent/Mobiles/Vendors/NPC/IronWorker.cs index e9c2dbcbb..e3c069720 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/IronWorker.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/IronWorker.cs @@ -3,117 +3,117 @@ using Server.Items; namespace Server.Mobiles { - public class IronWorker : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public IronWorker() : base("the iron worker") + public class IronWorker : BaseVendor { - SetSkill(SkillName.ArmsLore, 36.0, 68.0); - SetSkill(SkillName.Blacksmith, 65.0, 88.0); - SetSkill(SkillName.Fencing, 60.0, 83.0); - SetSkill(SkillName.Macing, 61.0, 93.0); - SetSkill(SkillName.Swords, 60.0, 83.0); - SetSkill(SkillName.Tactics, 60.0, 83.0); - SetSkill(SkillName.Parry, 61.0, 93.0); - } + private readonly List m_SBInfos = new List(); - public IronWorker(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override VendorShoeType ShoeType => VendorShoeType.None; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBAxeWeapon()); - m_SBInfos.Add(new SBKnifeWeapon()); - m_SBInfos.Add(new SBMaceWeapon()); - m_SBInfos.Add(new SBSmithTools()); - m_SBInfos.Add(new SBPoleArmWeapon()); - m_SBInfos.Add(new SBSpearForkWeapon()); - m_SBInfos.Add(new SBSwordWeapon()); - - m_SBInfos.Add(new SBMetalShields()); - - m_SBInfos.Add(new SBHelmetArmor()); - m_SBInfos.Add(new SBPlateArmor()); - m_SBInfos.Add(new SBChainmailArmor()); - m_SBInfos.Add(new SBRingmailArmor()); - m_SBInfos.Add(new SBStuddedArmor()); - m_SBInfos.Add(new SBLeatherArmor()); - } - - public override void InitOutfit() - { - base.InitOutfit(); - - Item item = Utility.RandomBool() ? null : new RingmailChest(); - - if (item != null && !EquipItem(item)) - { - item.Delete(); - - AddItem(new FullApron(Utility.RandomBrightHue())); - } - - AddItem( - Utility.Random(3) switch + [Constructible] + public IronWorker() : base("the iron worker") { - 0 => new Bandana(Utility.RandomBrightHue()), - _ => new JesterHat(Utility.RandomBrightHue()), // 1-2 + SetSkill(SkillName.ArmsLore, 36.0, 68.0); + SetSkill(SkillName.Blacksmith, 65.0, 88.0); + SetSkill(SkillName.Fencing, 60.0, 83.0); + SetSkill(SkillName.Macing, 61.0, 93.0); + SetSkill(SkillName.Swords, 60.0, 83.0); + SetSkill(SkillName.Tactics, 60.0, 83.0); + SetSkill(SkillName.Parry, 61.0, 93.0); } - ); - AddItem(new Bascinet()); - AddItem(new SmithHammer()); + public IronWorker(Serial serial) : base(serial) + { + } - item = FindItemOnLayer(Layer.Pants); + protected override List SBInfos => m_SBInfos; - if (item != null) - item.Hue = Utility.RandomBrightHue(); + public override VendorShoeType ShoeType => VendorShoeType.None; - item = FindItemOnLayer(Layer.OuterLegs); + public override void InitSBInfo() + { + m_SBInfos.Add(new SBAxeWeapon()); + m_SBInfos.Add(new SBKnifeWeapon()); + m_SBInfos.Add(new SBMaceWeapon()); + m_SBInfos.Add(new SBSmithTools()); + m_SBInfos.Add(new SBPoleArmWeapon()); + m_SBInfos.Add(new SBSpearForkWeapon()); + m_SBInfos.Add(new SBSwordWeapon()); - if (item != null) - item.Hue = Utility.RandomBrightHue(); + m_SBInfos.Add(new SBMetalShields()); - item = FindItemOnLayer(Layer.InnerLegs); + m_SBInfos.Add(new SBHelmetArmor()); + m_SBInfos.Add(new SBPlateArmor()); + m_SBInfos.Add(new SBChainmailArmor()); + m_SBInfos.Add(new SBRingmailArmor()); + m_SBInfos.Add(new SBStuddedArmor()); + m_SBInfos.Add(new SBLeatherArmor()); + } - if (item != null) - item.Hue = Utility.RandomBrightHue(); + public override void InitOutfit() + { + base.InitOutfit(); - item = FindItemOnLayer(Layer.OuterTorso); + Item item = Utility.RandomBool() ? null : new RingmailChest(); - if (item != null) - item.Hue = Utility.RandomBrightHue(); + if (item != null && !EquipItem(item)) + { + item.Delete(); - item = FindItemOnLayer(Layer.InnerTorso); + AddItem(new FullApron(Utility.RandomBrightHue())); + } - if (item != null) - item.Hue = Utility.RandomBrightHue(); + AddItem( + Utility.Random(3) switch + { + 0 => new Bandana(Utility.RandomBrightHue()), + _ => new JesterHat(Utility.RandomBrightHue()) // 1-2 + } + ); - item = FindItemOnLayer(Layer.Shirt); + AddItem(new Bascinet()); + AddItem(new SmithHammer()); - if (item != null) - item.Hue = Utility.RandomBrightHue(); + item = FindItemOnLayer(Layer.Pants); + + if (item != null) + item.Hue = Utility.RandomBrightHue(); + + item = FindItemOnLayer(Layer.OuterLegs); + + if (item != null) + item.Hue = Utility.RandomBrightHue(); + + item = FindItemOnLayer(Layer.InnerLegs); + + if (item != null) + item.Hue = Utility.RandomBrightHue(); + + item = FindItemOnLayer(Layer.OuterTorso); + + if (item != null) + item.Hue = Utility.RandomBrightHue(); + + item = FindItemOnLayer(Layer.InnerTorso); + + if (item != null) + item.Hue = Utility.RandomBrightHue(); + + item = FindItemOnLayer(Layer.Shirt); + + if (item != null) + item.Hue = Utility.RandomBrightHue(); + } + + 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 Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Jeweler.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Jeweler.cs index 26919a56a..d5c5732a9 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Jeweler.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Jeweler.cs @@ -2,39 +2,39 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class Jeweler : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Jeweler() : base("the jeweler") + public class Jeweler : BaseVendor { - SetSkill(SkillName.ItemID, 64.0, 100.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Jeweler() : base("the jeweler") + { + SetSkill(SkillName.ItemID, 64.0, 100.0); + } + + public Jeweler(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBJewel()); + } + + 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 Jeweler(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBJewel()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/KeeperOfChivalry.cs b/Projects/UOContent/Mobiles/Vendors/NPC/KeeperOfChivalry.cs index bef639ca9..f47928505 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/KeeperOfChivalry.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/KeeperOfChivalry.cs @@ -3,78 +3,78 @@ using Server.Items; namespace Server.Mobiles { - public class KeeperOfChivalry : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public KeeperOfChivalry() : base("the Keeper of Chivalry") + public class KeeperOfChivalry : BaseVendor { - SetSkill(SkillName.Fencing, 75.0, 85.0); - SetSkill(SkillName.Macing, 75.0, 85.0); - SetSkill(SkillName.Swords, 75.0, 85.0); - SetSkill(SkillName.Chivalry, 100.0); - } + private readonly List m_SBInfos = new List(); - public KeeperOfChivalry(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBKeeperOfChivalry()); - } - - public override void InitOutfit() - { - AddItem(new PlateArms()); - AddItem(new PlateChest()); - AddItem(new PlateGloves()); - AddItem(new StuddedGorget()); - AddItem(new PlateLegs()); - - AddItem( - Utility.Random(4) switch + [Constructible] + public KeeperOfChivalry() : base("the Keeper of Chivalry") { - 0 => new PlateHelm(), - 1 => new NorseHelm(), - 2 => new CloseHelm(), - _ => new Helmet() // 3 + SetSkill(SkillName.Fencing, 75.0, 85.0); + SetSkill(SkillName.Macing, 75.0, 85.0); + SetSkill(SkillName.Swords, 75.0, 85.0); + SetSkill(SkillName.Chivalry, 100.0); } - ); - AddItem( - Utility.Random(3) switch + public KeeperOfChivalry(Serial serial) : base(serial) { - 0 => new BodySash(0x482), - 1 => new Doublet(0x482), - _ => new Tunic(0x482) // 2 } - ); - AddItem(new Broadsword()); + protected override List SBInfos => m_SBInfos; - AddItem(new MetalKiteShield{Hue = Utility.RandomNondyedHue()}); + public override void InitSBInfo() + { + m_SBInfos.Add(new SBKeeperOfChivalry()); + } - AddItem(Utility.RandomBool() ? (Item)new Boots() : new ThighBoots()); + public override void InitOutfit() + { + AddItem(new PlateArms()); + AddItem(new PlateChest()); + AddItem(new PlateGloves()); + AddItem(new StuddedGorget()); + AddItem(new PlateLegs()); - PackGold(100, 200); + AddItem( + Utility.Random(4) switch + { + 0 => new PlateHelm(), + 1 => new NorseHelm(), + 2 => new CloseHelm(), + _ => new Helmet() // 3 + } + ); + + AddItem( + Utility.Random(3) switch + { + 0 => new BodySash(0x482), + 1 => new Doublet(0x482), + _ => new Tunic(0x482) // 2 + } + ); + + AddItem(new Broadsword()); + + AddItem(new MetalKiteShield { Hue = Utility.RandomNondyedHue() }); + + AddItem(Utility.RandomBool() ? (Item)new Boots() : new ThighBoots()); + + PackGold(100, 200); + } + + 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 Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/LeatherWorker.cs b/Projects/UOContent/Mobiles/Vendors/NPC/LeatherWorker.cs index be828b159..510372561 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/LeatherWorker.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/LeatherWorker.cs @@ -2,40 +2,40 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class LeatherWorker : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public LeatherWorker() : base("the leather worker") + public class LeatherWorker : BaseVendor { + private readonly List m_SBInfos = new List(); + + [Constructible] + public LeatherWorker() : base("the leather worker") + { + } + + public LeatherWorker(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBLeatherArmor()); + m_SBInfos.Add(new SBStuddedArmor()); + m_SBInfos.Add(new SBLeatherWorker()); + } + + 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 LeatherWorker(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBLeatherArmor()); - m_SBInfos.Add(new SBStuddedArmor()); - m_SBInfos.Add(new SBLeatherWorker()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Mage.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Mage.cs index 2e69f2a5b..07263f309 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Mage.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Mage.cs @@ -3,55 +3,55 @@ using Server.Items; namespace Server.Mobiles { - public class Mage : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Mage() : base("the mage") + public class Mage : BaseVendor { - SetSkill(SkillName.EvalInt, 65.0, 88.0); - SetSkill(SkillName.Inscribe, 60.0, 83.0); - SetSkill(SkillName.Magery, 64.0, 100.0); - SetSkill(SkillName.Meditation, 60.0, 83.0); - SetSkill(SkillName.MagicResist, 65.0, 88.0); - SetSkill(SkillName.Wrestling, 36.0, 68.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Mage() : base("the mage") + { + SetSkill(SkillName.EvalInt, 65.0, 88.0); + SetSkill(SkillName.Inscribe, 60.0, 83.0); + SetSkill(SkillName.Magery, 64.0, 100.0); + SetSkill(SkillName.Meditation, 60.0, 83.0); + SetSkill(SkillName.MagicResist, 65.0, 88.0); + SetSkill(SkillName.Wrestling, 36.0, 68.0); + } + + public Mage(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override NpcGuild NpcGuild => NpcGuild.MagesGuild; + + public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Shoes : VendorShoeType.Sandals; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBMage()); + } + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new Robe(Utility.RandomBlueHue())); + } + + 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 Mage(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override NpcGuild NpcGuild => NpcGuild.MagesGuild; - - public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Shoes : VendorShoeType.Sandals; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBMage()); - } - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new Robe(Utility.RandomBlueHue())); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Mapmaker.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Mapmaker.cs index 9354f4736..72fe68e20 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Mapmaker.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Mapmaker.cs @@ -2,39 +2,39 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class Mapmaker : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Mapmaker() : base("the mapmaker") + public class Mapmaker : BaseVendor { - SetSkill(SkillName.Cartography, 90.0, 100.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Mapmaker() : base("the mapmaker") + { + SetSkill(SkillName.Cartography, 90.0, 100.0); + } + + public Mapmaker(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBMapmaker()); + } + + 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 Mapmaker(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBMapmaker()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Miller.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Miller.cs index ca37393fb..1ade9d9f0 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Miller.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Miller.cs @@ -2,38 +2,38 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class Miller : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Miller() : base("the miller") + public class Miller : BaseVendor { + private readonly List m_SBInfos = new List(); + + [Constructible] + public Miller() : base("the miller") + { + } + + public Miller(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBMiller()); + } + + 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 Miller(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBMiller()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Miner.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Miner.cs index bc6d922dc..9fd1b2b17 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Miner.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Miner.cs @@ -3,49 +3,49 @@ using Server.Items; namespace Server.Mobiles { - public class Miner : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Miner() : base("the miner") + public class Miner : BaseVendor { - SetSkill(SkillName.Mining, 65.0, 88.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Miner() : base("the miner") + { + SetSkill(SkillName.Mining, 65.0, 88.0); + } + + public Miner(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBMiner()); + } + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new FancyShirt(0x3E4)); + AddItem(new LongPants(0x192)); + AddItem(new Pickaxe()); + AddItem(new ThighBoots(0x283)); + } + + 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 Miner(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBMiner()); - } - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new FancyShirt(0x3E4)); - AddItem(new LongPants(0x192)); - AddItem(new Pickaxe()); - AddItem(new ThighBoots(0x283)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Monk.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Monk.cs index 3d4062d62..c1d4fdd4e 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Monk.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Monk.cs @@ -3,49 +3,49 @@ using Server.Items; namespace Server.Mobiles { - public class Monk : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Monk() : base("the Monk") + public class Monk : BaseVendor { - SetSkill(SkillName.EvalInt, 100.0); - SetSkill(SkillName.Tactics, 70.0, 90.0); - SetSkill(SkillName.Wrestling, 70.0, 90.0); - SetSkill(SkillName.MagicResist, 70.0, 90.0); - SetSkill(SkillName.Macing, 70.0, 90.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Monk() : base("the Monk") + { + SetSkill(SkillName.EvalInt, 100.0); + SetSkill(SkillName.Tactics, 70.0, 90.0); + SetSkill(SkillName.Wrestling, 70.0, 90.0); + SetSkill(SkillName.MagicResist, 70.0, 90.0); + SetSkill(SkillName.Macing, 70.0, 90.0); + } + + public Monk(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBMonk()); + } + + public override void InitOutfit() + { + AddItem(new Sandals()); + AddItem(new MonkRobe()); + } + + 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 Monk(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBMonk()); - } - - public override void InitOutfit() - { - AddItem(new Sandals()); - AddItem(new MonkRobe()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Provisioner.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Provisioner.cs index 6dc84eb63..1a842e84e 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Provisioner.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Provisioner.cs @@ -2,43 +2,43 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class Provisioner : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Provisioner() : base("the provisioner") + public class Provisioner : BaseVendor { - SetSkill(SkillName.Camping, 45.0, 68.0); - SetSkill(SkillName.Tactics, 45.0, 68.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Provisioner() : base("the provisioner") + { + SetSkill(SkillName.Camping, 45.0, 68.0); + SetSkill(SkillName.Tactics, 45.0, 68.0); + } + + public Provisioner(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBProvisioner()); + + if (IsTokunoVendor) + m_SBInfos.Add(new SBSEHats()); + } + + 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 Provisioner(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBProvisioner()); - - if (IsTokunoVendor) - m_SBInfos.Add(new SBSEHats()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Rancher.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Rancher.cs index c58e7b87e..7ede7641e 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Rancher.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Rancher.cs @@ -2,42 +2,42 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class Rancher : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Rancher() : base("the rancher") + public class Rancher : BaseVendor { - SetSkill(SkillName.AnimalLore, 55.0, 78.0); - SetSkill(SkillName.AnimalTaming, 55.0, 78.0); - SetSkill(SkillName.Herding, 64.0, 100.0); - SetSkill(SkillName.Veterinary, 60.0, 83.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Rancher() : base("the rancher") + { + SetSkill(SkillName.AnimalLore, 55.0, 78.0); + SetSkill(SkillName.AnimalTaming, 55.0, 78.0); + SetSkill(SkillName.Herding, 64.0, 100.0); + SetSkill(SkillName.Veterinary, 60.0, 83.0); + } + + public Rancher(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBRancher()); + } + + 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 Rancher(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBRancher()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Ranger.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Ranger.cs index 007b6160e..f39845359 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Ranger.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Ranger.cs @@ -3,54 +3,54 @@ using Server.Items; namespace Server.Mobiles { - public class Ranger : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Ranger() : base("the ranger") + public class Ranger : BaseVendor { - SetSkill(SkillName.Camping, 55.0, 78.0); - SetSkill(SkillName.DetectHidden, 65.0, 88.0); - SetSkill(SkillName.Hiding, 45.0, 68.0); - SetSkill(SkillName.Archery, 65.0, 88.0); - SetSkill(SkillName.Tracking, 65.0, 88.0); - SetSkill(SkillName.Veterinary, 60.0, 83.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Ranger() : base("the ranger") + { + SetSkill(SkillName.Camping, 55.0, 78.0); + SetSkill(SkillName.DetectHidden, 65.0, 88.0); + SetSkill(SkillName.Hiding, 45.0, 68.0); + SetSkill(SkillName.Archery, 65.0, 88.0); + SetSkill(SkillName.Tracking, 65.0, 88.0); + SetSkill(SkillName.Veterinary, 60.0, 83.0); + } + + public Ranger(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBRanger()); + } + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new Shirt(Utility.RandomNeutralHue())); + AddItem(new LongPants(Utility.RandomNeutralHue())); + AddItem(new Bow()); + AddItem(new ThighBoots(Utility.RandomNeutralHue())); + } + + 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 Ranger(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBRanger()); - } - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new Shirt(Utility.RandomNeutralHue())); - AddItem(new LongPants(Utility.RandomNeutralHue())); - AddItem(new Bow()); - AddItem(new ThighBoots(Utility.RandomNeutralHue())); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/RealEstateBroker.cs b/Projects/UOContent/Mobiles/Vendors/NPC/RealEstateBroker.cs index 9ced050bf..101448ca6 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/RealEstateBroker.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/RealEstateBroker.cs @@ -1,179 +1,182 @@ using System; using System.Collections.Generic; -using Server.Items; using Server.Multis.Deeds; using Server.Network; using Server.Targeting; namespace Server.Mobiles { - public class RealEstateBroker : BaseVendor - { - private DateTime m_NextCheckPack; - private readonly List m_SBInfos = new List(); - - [Constructible] - public RealEstateBroker() : base("the real estate broker") + public class RealEstateBroker : BaseVendor { - } + private readonly List m_SBInfos = new List(); + private DateTime m_NextCheckPack; - public RealEstateBroker(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override bool HandlesOnSpeech(Mobile from) - { - if (from.Alive && from.InRange(this, 3)) - return true; - - return base.HandlesOnSpeech(from); - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - if (DateTime.UtcNow > m_NextCheckPack && InRange(m, 4) && !InRange(oldLocation, 4) && m.Player) - { - Container pack = m.Backpack; - - if (pack != null) + [Constructible] + public RealEstateBroker() : base("the real estate broker") { - m_NextCheckPack = DateTime.UtcNow + TimeSpan.FromSeconds(2.0); - - if (pack.FindItemByType(false) != null) - { - // If you have a deed, I can appraise it or buy it from you... - PrivateOverheadMessage(MessageType.Regular, 0x3B2, 500605, m.NetState); - - // Simply hand me a deed to sell it. - PrivateOverheadMessage(MessageType.Regular, 0x3B2, 500606, m.NetState); - } - } - } - - base.OnMovement(m, oldLocation); - } - - public override void OnSpeech(SpeechEventArgs e) - { - if (!e.Handled && e.Mobile.Alive && e.HasKeyword(0x38)) // *appraise* - { - PublicOverheadMessage(MessageType.Regular, 0x3B2, 500608); // Which deed would you like appraised? - e.Mobile.BeginTarget(12, false, TargetFlags.None, Appraise_OnTarget); - e.Handled = true; - } - - base.OnSpeech(e); - } - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (dropped is HouseDeed deed) - { - int price = ComputePriceFor(deed); - - if (price > 0) - { - if (Banker.Deposit(from, price)) - { - // For the deed I have placed gold in your bankbox : - PublicOverheadMessage(MessageType.Regular, 0x3B2, 1008000, AffixType.Append, price.ToString()); - - deed.Delete(); - return true; - } - - PublicOverheadMessage(MessageType.Regular, 0x3B2, 500390); // Your bank box is full. - return false; } - PublicOverheadMessage(MessageType.Regular, 0x3B2, 500607); // I'm not interested in that. - return false; - } - - return base.OnDragDrop(from, dropped); - } - - public void Appraise_OnTarget(Mobile from, object obj) - { - if (obj is HouseDeed deed) - { - int price = ComputePriceFor(deed); - - if (price > 0) + public RealEstateBroker(Serial serial) : base(serial) { - // I will pay you gold for this deed : - PublicOverheadMessage(MessageType.Regular, 0x3B2, 1008001, AffixType.Append, price.ToString()); - - PublicOverheadMessage(MessageType.Regular, 0x3B2, - 500610); // Simply hand me the deed if you wish to sell it. } - else + + protected override List SBInfos => m_SBInfos; + + public override bool HandlesOnSpeech(Mobile from) { - PublicOverheadMessage(MessageType.Regular, 0x3B2, 500607); // I'm not interested in that. + if (from.Alive && from.InRange(this, 3)) + return true; + + return base.HandlesOnSpeech(from); + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (DateTime.UtcNow > m_NextCheckPack && InRange(m, 4) && !InRange(oldLocation, 4) && m.Player) + { + var pack = m.Backpack; + + if (pack != null) + { + m_NextCheckPack = DateTime.UtcNow + TimeSpan.FromSeconds(2.0); + + if (pack.FindItemByType(false) != null) + { + // If you have a deed, I can appraise it or buy it from you... + PrivateOverheadMessage(MessageType.Regular, 0x3B2, 500605, m.NetState); + + // Simply hand me a deed to sell it. + PrivateOverheadMessage(MessageType.Regular, 0x3B2, 500606, m.NetState); + } + } + } + + base.OnMovement(m, oldLocation); + } + + public override void OnSpeech(SpeechEventArgs e) + { + if (!e.Handled && e.Mobile.Alive && e.HasKeyword(0x38)) // *appraise* + { + PublicOverheadMessage(MessageType.Regular, 0x3B2, 500608); // Which deed would you like appraised? + e.Mobile.BeginTarget(12, false, TargetFlags.None, Appraise_OnTarget); + e.Handled = true; + } + + base.OnSpeech(e); + } + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (dropped is HouseDeed deed) + { + var price = ComputePriceFor(deed); + + if (price > 0) + { + if (Banker.Deposit(from, price)) + { + // For the deed I have placed gold in your bankbox : + PublicOverheadMessage(MessageType.Regular, 0x3B2, 1008000, AffixType.Append, price.ToString()); + + deed.Delete(); + return true; + } + + PublicOverheadMessage(MessageType.Regular, 0x3B2, 500390); // Your bank box is full. + return false; + } + + PublicOverheadMessage(MessageType.Regular, 0x3B2, 500607); // I'm not interested in that. + return false; + } + + return base.OnDragDrop(from, dropped); + } + + public void Appraise_OnTarget(Mobile from, object obj) + { + if (obj is HouseDeed deed) + { + var price = ComputePriceFor(deed); + + if (price > 0) + { + // I will pay you gold for this deed : + PublicOverheadMessage(MessageType.Regular, 0x3B2, 1008001, AffixType.Append, price.ToString()); + + PublicOverheadMessage( + MessageType.Regular, + 0x3B2, + 500610 + ); // Simply hand me the deed if you wish to sell it. + } + else + { + PublicOverheadMessage(MessageType.Regular, 0x3B2, 500607); // I'm not interested in that. + } + } + else + { + PublicOverheadMessage(MessageType.Regular, 0x3B2, 500609); // I can't appraise things I know nothing about... + } + } + + public int ComputePriceFor(HouseDeed deed) + { + var price = 0; + + if (deed is SmallBrickHouseDeed || deed is StonePlasterHouseDeed || deed is FieldStoneHouseDeed || + deed is WoodHouseDeed || deed is WoodPlasterHouseDeed || + deed is ThatchedRoofCottageDeed) + price = 43800; + else if (deed is BrickHouseDeed) + price = 144500; + else if (deed is TwoStoryWoodPlasterHouseDeed || deed is TwoStoryStonePlasterHouseDeed) + price = 192400; + else if (deed is TowerDeed) + price = 433200; + else if (deed is KeepDeed) + price = 665200; + else if (deed is CastleDeed) + price = 1022800; + else if (deed is LargePatioDeed) + price = 152800; + else if (deed is LargeMarbleDeed) + price = 192800; + else if (deed is SmallTowerDeed) + price = 88500; + else if (deed is LogCabinDeed) + price = 97800; + else if (deed is SandstonePatioDeed) + price = 90900; + else if (deed is VillaDeed) + price = 136500; + else if (deed is StoneWorkshopDeed) + price = 60600; + else if (deed is MarbleWorkshopDeed) + price = 60300; + + return AOS.Scale(price, 80); // refunds 80% of the purchase price + } + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBRealEstateBroker()); + } + + 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(); } - } - else - { - PublicOverheadMessage(MessageType.Regular, 0x3B2, 500609); // I can't appraise things I know nothing about... - } } - - public int ComputePriceFor(HouseDeed deed) - { - int price = 0; - - if (deed is SmallBrickHouseDeed || deed is StonePlasterHouseDeed || deed is FieldStoneHouseDeed || deed is WoodHouseDeed || deed is WoodPlasterHouseDeed || - deed is ThatchedRoofCottageDeed) - price = 43800; - else if (deed is BrickHouseDeed) - price = 144500; - else if (deed is TwoStoryWoodPlasterHouseDeed || deed is TwoStoryStonePlasterHouseDeed) - price = 192400; - else if (deed is TowerDeed) - price = 433200; - else if (deed is KeepDeed) - price = 665200; - else if (deed is CastleDeed) - price = 1022800; - else if (deed is LargePatioDeed) - price = 152800; - else if (deed is LargeMarbleDeed) - price = 192800; - else if (deed is SmallTowerDeed) - price = 88500; - else if (deed is LogCabinDeed) - price = 97800; - else if (deed is SandstonePatioDeed) - price = 90900; - else if (deed is VillaDeed) - price = 136500; - else if (deed is StoneWorkshopDeed) - price = 60600; - else if (deed is MarbleWorkshopDeed) - price = 60300; - - return AOS.Scale(price, 80); // refunds 80% of the purchase price - } - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBRealEstateBroker()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Scribe.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Scribe.cs index 9905c8689..690ccdccc 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Scribe.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Scribe.cs @@ -5,72 +5,72 @@ using Server.Network; namespace Server.Mobiles { - public class Scribe : BaseVendor - { - public static readonly TimeSpan ShushDelay = TimeSpan.FromMinutes(1); - - private DateTime m_NextShush; - private readonly List m_SBInfos = new List(); - - [Constructible] - public Scribe() : base("the scribe") + public class Scribe : BaseVendor { - SetSkill(SkillName.EvalInt, 60.0, 83.0); - SetSkill(SkillName.Inscribe, 90.0, 100.0); + public static readonly TimeSpan ShushDelay = TimeSpan.FromMinutes(1); + private readonly List m_SBInfos = new List(); + + private DateTime m_NextShush; + + [Constructible] + public Scribe() : base("the scribe") + { + SetSkill(SkillName.EvalInt, 60.0, 83.0); + SetSkill(SkillName.Inscribe, 90.0, 100.0); + } + + public Scribe(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override NpcGuild NpcGuild => NpcGuild.MagesGuild; + + public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Shoes : VendorShoeType.Sandals; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBScribe()); + } + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new Robe(Utility.RandomNeutralHue())); + } + + public override bool HandlesOnSpeech(Mobile from) => from.Player; + + public override void OnSpeech(SpeechEventArgs e) + { + base.OnSpeech(e); + + if (!e.Handled && m_NextShush <= DateTime.UtcNow && InLOS(e.Mobile)) + { + Direction = GetDirectionTo(e.Mobile); + + PlaySound(Female ? 0x32F : 0x441); + PublicOverheadMessage(MessageType.Regular, 0x3B2, 1073990); // Shhhh! + + m_NextShush = DateTime.UtcNow + ShushDelay; + e.Handled = true; + } + } + + 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 Scribe(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override NpcGuild NpcGuild => NpcGuild.MagesGuild; - - public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Shoes : VendorShoeType.Sandals; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBScribe()); - } - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new Robe(Utility.RandomNeutralHue())); - } - - public override bool HandlesOnSpeech(Mobile from) => from.Player; - - public override void OnSpeech(SpeechEventArgs e) - { - base.OnSpeech(e); - - if (!e.Handled && m_NextShush <= DateTime.UtcNow && InLOS(e.Mobile)) - { - Direction = GetDirectionTo(e.Mobile); - - PlaySound(Female ? 0x32F : 0x441); - PublicOverheadMessage(MessageType.Regular, 0x3B2, 1073990); // Shhhh! - - m_NextShush = DateTime.UtcNow + ShushDelay; - e.Handled = true; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Shipwright.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Shipwright.cs index d4d1326d8..c9c0874b8 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Shipwright.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Shipwright.cs @@ -3,47 +3,47 @@ using Server.Items; namespace Server.Mobiles { - public class Shipwright : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Shipwright() : base("the shipwright") + public class Shipwright : BaseVendor { - SetSkill(SkillName.Carpentry, 60.0, 83.0); - SetSkill(SkillName.Macing, 36.0, 68.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Shipwright() : base("the shipwright") + { + SetSkill(SkillName.Carpentry, 60.0, 83.0); + SetSkill(SkillName.Macing, 36.0, 68.0); + } + + public Shipwright(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBShipwright()); + } + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new SmithHammer()); + } + + 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 Shipwright(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBShipwright()); - } - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new SmithHammer()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/StoneCrafter.cs b/Projects/UOContent/Mobiles/Vendors/NPC/StoneCrafter.cs index e8ba3769a..48eb59dc2 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/StoneCrafter.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/StoneCrafter.cs @@ -2,48 +2,48 @@ using System.Collections.Generic; namespace Server.Mobiles { - [TypeAlias("Server.Mobiles.GargoyleStonecrafter")] - public class StoneCrafter : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public StoneCrafter() : base("the stone crafter") + [TypeAlias("Server.Mobiles.GargoyleStonecrafter")] + public class StoneCrafter : BaseVendor { - SetSkill(SkillName.Carpentry, 85.0, 100.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public StoneCrafter() : base("the stone crafter") + { + SetSkill(SkillName.Carpentry, 85.0, 100.0); + } + + public StoneCrafter(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override NpcGuild NpcGuild => NpcGuild.TinkersGuild; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBStoneCrafter()); + m_SBInfos.Add(new SBStavesWeapon()); + m_SBInfos.Add(new SBCarpenter()); + m_SBInfos.Add(new SBWoodenShields()); + } + + 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 (Title == "the stonecrafter") + Title = "the stone crafter"; + } } - - public StoneCrafter(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override NpcGuild NpcGuild => NpcGuild.TinkersGuild; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBStoneCrafter()); - m_SBInfos.Add(new SBStavesWeapon()); - m_SBInfos.Add(new SBCarpenter()); - m_SBInfos.Add(new SBWoodenShields()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Title == "the stonecrafter") - Title = "the stone crafter"; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Tailor.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Tailor.cs index 118d90898..f4780b269 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Tailor.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Tailor.cs @@ -4,83 +4,84 @@ using Server.Engines.BulkOrders; namespace Server.Mobiles { - public class Tailor : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Tailor() : base("the tailor") + public class Tailor : BaseVendor { - SetSkill(SkillName.Tailoring, 64.0, 100.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Tailor() : base("the tailor") + { + SetSkill(SkillName.Tailoring, 64.0, 100.0); + } + + public Tailor(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override NpcGuild NpcGuild => NpcGuild.TailorsGuild; + + public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Sandals : VendorShoeType.Shoes; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBTailor()); + } + + 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 Item CreateBulkOrder(Mobile from, bool fromContextMenu) + { + if (from is PlayerMobile pm && pm.NextTailorBulkOrder == TimeSpan.Zero && + (fromContextMenu || Utility.RandomDouble() < 0.2)) + { + var theirSkill = pm.Skills.Tailoring.Base; + + if (theirSkill >= 70.1) + pm.NextTailorBulkOrder = TimeSpan.FromHours(6.0); + else if (theirSkill >= 50.1) + pm.NextTailorBulkOrder = TimeSpan.FromHours(2.0); + else + pm.NextTailorBulkOrder = TimeSpan.FromHours(1.0); + + if (theirSkill >= 70.1 && (theirSkill - 40.0) / 300.0 > Utility.RandomDouble()) + return new LargeTailorBOD(); + + return SmallTailorBOD.CreateRandomFor(from); + } + + return null; + } + + public override bool IsValidBulkOrder(Item item) => item is SmallTailorBOD || item is LargeTailorBOD; + + public override bool SupportsBulkOrders(Mobile from) => from is PlayerMobile && from.Skills.Tailoring.Base > 0; + + public override TimeSpan GetNextBulkOrder(Mobile from) + { + if (from is PlayerMobile mobile) + return mobile.NextTailorBulkOrder; + + return TimeSpan.Zero; + } + + public override void OnSuccessfulBulkOrderReceive(Mobile from) + { + if (Core.SE && from is PlayerMobile mobile) + mobile.NextTailorBulkOrder = TimeSpan.Zero; + } } - - public Tailor(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override NpcGuild NpcGuild => NpcGuild.TailorsGuild; - - public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Sandals : VendorShoeType.Shoes; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBTailor()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override Item CreateBulkOrder(Mobile from, bool fromContextMenu) - { - if (from is PlayerMobile pm && pm.NextTailorBulkOrder == TimeSpan.Zero && (fromContextMenu || Utility.RandomDouble() < 0.2)) - { - double theirSkill = pm.Skills.Tailoring.Base; - - if (theirSkill >= 70.1) - pm.NextTailorBulkOrder = TimeSpan.FromHours(6.0); - else if (theirSkill >= 50.1) - pm.NextTailorBulkOrder = TimeSpan.FromHours(2.0); - else - pm.NextTailorBulkOrder = TimeSpan.FromHours(1.0); - - if (theirSkill >= 70.1 && (theirSkill - 40.0) / 300.0 > Utility.RandomDouble()) - return new LargeTailorBOD(); - - return SmallTailorBOD.CreateRandomFor(from); - } - - return null; - } - - public override bool IsValidBulkOrder(Item item) => item is SmallTailorBOD || item is LargeTailorBOD; - - public override bool SupportsBulkOrders(Mobile from) => from is PlayerMobile && from.Skills.Tailoring.Base > 0; - - public override TimeSpan GetNextBulkOrder(Mobile from) - { - if (from is PlayerMobile mobile) - return mobile.NextTailorBulkOrder; - - return TimeSpan.Zero; - } - - public override void OnSuccessfulBulkOrderReceive(Mobile from) - { - if (Core.SE && from is PlayerMobile mobile) - mobile.NextTailorBulkOrder = TimeSpan.Zero; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Tanner.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Tanner.cs index e96e4d236..f2edfc24b 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Tanner.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Tanner.cs @@ -2,39 +2,39 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class Tanner : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Tanner() : base("the tanner") + public class Tanner : BaseVendor { - SetSkill(SkillName.Tailoring, 36.0, 68.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Tanner() : base("the tanner") + { + SetSkill(SkillName.Tailoring, 36.0, 68.0); + } + + public Tanner(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBTanner()); + } + + 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 Tanner(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBTanner()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/TavernKeeper.cs b/Projects/UOContent/Mobiles/Vendors/NPC/TavernKeeper.cs index e6c1698a2..515b1f1e6 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/TavernKeeper.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/TavernKeeper.cs @@ -3,45 +3,45 @@ using Server.Items; namespace Server.Mobiles { - public class TavernKeeper : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public TavernKeeper() : base("the tavern keeper") + public class TavernKeeper : BaseVendor { + private readonly List m_SBInfos = new List(); + + [Constructible] + public TavernKeeper() : base("the tavern keeper") + { + } + + public TavernKeeper(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBTavernKeeper()); + } + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new HalfApron()); + } + + 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 TavernKeeper(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBTavernKeeper()); - } - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new HalfApron()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Thief.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Thief.cs index 11f4f1879..5342257fa 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Thief.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Thief.cs @@ -3,54 +3,54 @@ using Server.Items; namespace Server.Mobiles { - public class Thief : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Thief() : base("the thief") + public class Thief : BaseVendor { - SetSkill(SkillName.Camping, 55.0, 78.0); - SetSkill(SkillName.DetectHidden, 65.0, 88.0); - SetSkill(SkillName.Hiding, 45.0, 68.0); - SetSkill(SkillName.Archery, 65.0, 88.0); - SetSkill(SkillName.Tracking, 65.0, 88.0); - SetSkill(SkillName.Veterinary, 60.0, 83.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Thief() : base("the thief") + { + SetSkill(SkillName.Camping, 55.0, 78.0); + SetSkill(SkillName.DetectHidden, 65.0, 88.0); + SetSkill(SkillName.Hiding, 45.0, 68.0); + SetSkill(SkillName.Archery, 65.0, 88.0); + SetSkill(SkillName.Tracking, 65.0, 88.0); + SetSkill(SkillName.Veterinary, 60.0, 83.0); + } + + public Thief(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBThief()); + } + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new Shirt(Utility.RandomNeutralHue())); + AddItem(new LongPants(Utility.RandomNeutralHue())); + AddItem(new Dagger()); + AddItem(new ThighBoots(Utility.RandomNeutralHue())); + } + + 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 Thief(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBThief()); - } - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new Shirt(Utility.RandomNeutralHue())); - AddItem(new LongPants(Utility.RandomNeutralHue())); - AddItem(new Dagger()); - AddItem(new ThighBoots(Utility.RandomNeutralHue())); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Tinker.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Tinker.cs index c71c82ad6..87a583da4 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Tinker.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Tinker.cs @@ -2,43 +2,43 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class Tinker : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Tinker() : base("the tinker") + public class Tinker : BaseVendor { - SetSkill(SkillName.Lockpicking, 60.0, 83.0); - SetSkill(SkillName.RemoveTrap, 75.0, 98.0); - SetSkill(SkillName.Tinkering, 64.0, 100.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Tinker() : base("the tinker") + { + SetSkill(SkillName.Lockpicking, 60.0, 83.0); + SetSkill(SkillName.RemoveTrap, 75.0, 98.0); + SetSkill(SkillName.Tinkering, 64.0, 100.0); + } + + public Tinker(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override NpcGuild NpcGuild => NpcGuild.TinkersGuild; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBTinker()); + } + + 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 Tinker(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override NpcGuild NpcGuild => NpcGuild.TinkersGuild; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBTinker()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Vagabond.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Vagabond.cs index f0958f66c..11f68ef3d 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Vagabond.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Vagabond.cs @@ -3,59 +3,61 @@ using Server.Items; namespace Server.Mobiles { - public class Vagabond : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Vagabond() : base("the vagabond") + public class Vagabond : BaseVendor { - SetSkill(SkillName.ItemID, 60.0, 83.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Vagabond() : base("the vagabond") + { + SetSkill(SkillName.ItemID, 60.0, 83.0); + } + + public Vagabond(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBTinker()); + m_SBInfos.Add(new SBVagabond()); + } + + public override void InitOutfit() + { + AddItem(new FancyShirt(Utility.RandomBrightHue())); + AddItem(new Shoes(GetShoeHue())); + AddItem(new LongPants(GetRandomHue())); + + if (Utility.RandomBool()) + AddItem(new Cloak(Utility.RandomBrightHue())); + + AddItem( + Utility.RandomBool() + ? (Item)new SkullCap(Utility.RandomNeutralHue()) + : new Bandana(Utility.RandomNeutralHue()) + ); + + Utility.AssignRandomHair(this); + Utility.AssignRandomFacialHair(this, HairHue); + + PackGold(100, 200); + } + + 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 Vagabond(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBTinker()); - m_SBInfos.Add(new SBVagabond()); - } - - public override void InitOutfit() - { - AddItem(new FancyShirt(Utility.RandomBrightHue())); - AddItem(new Shoes(GetShoeHue())); - AddItem(new LongPants(GetRandomHue())); - - if (Utility.RandomBool()) - AddItem(new Cloak(Utility.RandomBrightHue())); - - AddItem( - Utility.RandomBool() ? (Item)new SkullCap(Utility.RandomNeutralHue()) : new Bandana(Utility.RandomNeutralHue()) - ); - - Utility.AssignRandomHair(this); - Utility.AssignRandomFacialHair(this, HairHue); - - PackGold(100, 200); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/VarietyDealer.cs b/Projects/UOContent/Mobiles/Vendors/NPC/VarietyDealer.cs index d86908601..a00c96eec 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/VarietyDealer.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/VarietyDealer.cs @@ -2,38 +2,38 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class VarietyDealer : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public VarietyDealer() : base("the variety dealer") + public class VarietyDealer : BaseVendor { + private readonly List m_SBInfos = new List(); + + [Constructible] + public VarietyDealer() : base("the variety dealer") + { + } + + public VarietyDealer(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBVarietyDealer()); + } + + 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 VarietyDealer(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBVarietyDealer()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Veterinarian.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Veterinarian.cs index 4e65f4978..ae84d61a9 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Veterinarian.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Veterinarian.cs @@ -2,40 +2,40 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class Veterinarian : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Veterinarian() : base("the vet") + public class Veterinarian : BaseVendor { - SetSkill(SkillName.AnimalLore, 85.0, 100.0); - SetSkill(SkillName.Veterinary, 90.0, 100.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Veterinarian() : base("the vet") + { + SetSkill(SkillName.AnimalLore, 85.0, 100.0); + SetSkill(SkillName.Veterinary, 90.0, 100.0); + } + + public Veterinarian(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBVeterinarian()); + } + + 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 Veterinarian(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBVeterinarian()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Waiter.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Waiter.cs index 92a9358fe..106bd3520 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Waiter.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Waiter.cs @@ -3,46 +3,46 @@ using Server.Items; namespace Server.Mobiles { - public class Waiter : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Waiter() : base("the waiter") + public class Waiter : BaseVendor { - SetSkill(SkillName.Discordance, 36.0, 68.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Waiter() : base("the waiter") + { + SetSkill(SkillName.Discordance, 36.0, 68.0); + } + + public Waiter(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBWaiter()); + } + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new HalfApron()); + } + + 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 Waiter(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBWaiter()); - } - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new HalfApron()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Weaponsmith.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Weaponsmith.cs index 977c01a98..12e2950a4 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Weaponsmith.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Weaponsmith.cs @@ -5,98 +5,100 @@ using Server.Items; namespace Server.Mobiles { - public class Weaponsmith : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Weaponsmith() : base("the weaponsmith") + public class Weaponsmith : BaseVendor { - SetSkill(SkillName.ArmsLore, 64.0, 100.0); - SetSkill(SkillName.Blacksmith, 65.0, 88.0); - SetSkill(SkillName.Fencing, 45.0, 68.0); - SetSkill(SkillName.Macing, 45.0, 68.0); - SetSkill(SkillName.Swords, 45.0, 68.0); - SetSkill(SkillName.Tactics, 36.0, 68.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Weaponsmith() : base("the weaponsmith") + { + SetSkill(SkillName.ArmsLore, 64.0, 100.0); + SetSkill(SkillName.Blacksmith, 65.0, 88.0); + SetSkill(SkillName.Fencing, 45.0, 68.0); + SetSkill(SkillName.Macing, 45.0, 68.0); + SetSkill(SkillName.Swords, 45.0, 68.0); + SetSkill(SkillName.Tactics, 36.0, 68.0); + } + + public Weaponsmith(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Boots : VendorShoeType.ThighBoots; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBWeaponSmith()); + + if (IsTokunoVendor) + m_SBInfos.Add(new SBSEWeapons()); + } + + public override int GetShoeHue() => 0; + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new HalfApron()); + } + + 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 Item CreateBulkOrder(Mobile from, bool fromContextMenu) + { + if (from is PlayerMobile pm && pm.NextSmithBulkOrder == TimeSpan.Zero && + (fromContextMenu || Utility.RandomDouble() < 0.2)) + { + var theirSkill = pm.Skills.Blacksmith.Base; + + if (theirSkill >= 70.1) + pm.NextSmithBulkOrder = TimeSpan.FromHours(6.0); + else if (theirSkill >= 50.1) + pm.NextSmithBulkOrder = TimeSpan.FromHours(2.0); + else + pm.NextSmithBulkOrder = TimeSpan.FromHours(1.0); + + if (theirSkill >= 70.1 && (theirSkill - 40.0) / 300.0 > Utility.RandomDouble()) + return new LargeSmithBOD(); + + return SmallSmithBOD.CreateRandomFor(from); + } + + return null; + } + + public override bool IsValidBulkOrder(Item item) => item is SmallSmithBOD || item is LargeSmithBOD; + + public override bool SupportsBulkOrders(Mobile from) => + from is PlayerMobile && Core.AOS && from.Skills.Blacksmith.Base > 0; + + public override TimeSpan GetNextBulkOrder(Mobile from) + { + if (from is PlayerMobile mobile) + return mobile.NextSmithBulkOrder; + + return TimeSpan.Zero; + } + + public override void OnSuccessfulBulkOrderReceive(Mobile from) + { + if (Core.SE && from is PlayerMobile mobile) + mobile.NextSmithBulkOrder = TimeSpan.Zero; + } } - - public Weaponsmith(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.Boots : VendorShoeType.ThighBoots; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBWeaponSmith()); - - if (IsTokunoVendor) - m_SBInfos.Add(new SBSEWeapons()); - } - - public override int GetShoeHue() => 0; - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new HalfApron()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override Item CreateBulkOrder(Mobile from, bool fromContextMenu) - { - if (from is PlayerMobile pm && pm.NextSmithBulkOrder == TimeSpan.Zero && (fromContextMenu || Utility.RandomDouble() < 0.2)) - { - double theirSkill = pm.Skills.Blacksmith.Base; - - if (theirSkill >= 70.1) - pm.NextSmithBulkOrder = TimeSpan.FromHours(6.0); - else if (theirSkill >= 50.1) - pm.NextSmithBulkOrder = TimeSpan.FromHours(2.0); - else - pm.NextSmithBulkOrder = TimeSpan.FromHours(1.0); - - if (theirSkill >= 70.1 && (theirSkill - 40.0) / 300.0 > Utility.RandomDouble()) - return new LargeSmithBOD(); - - return SmallSmithBOD.CreateRandomFor(from); - } - - return null; - } - - public override bool IsValidBulkOrder(Item item) => item is SmallSmithBOD || item is LargeSmithBOD; - - public override bool SupportsBulkOrders(Mobile from) => from is PlayerMobile && Core.AOS && from.Skills.Blacksmith.Base > 0; - - public override TimeSpan GetNextBulkOrder(Mobile from) - { - if (from is PlayerMobile mobile) - return mobile.NextSmithBulkOrder; - - return TimeSpan.Zero; - } - - public override void OnSuccessfulBulkOrderReceive(Mobile from) - { - if (Core.SE && from is PlayerMobile mobile) - mobile.NextSmithBulkOrder = TimeSpan.Zero; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Weaver.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Weaver.cs index d44a77873..a0907ca9d 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Weaver.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Weaver.cs @@ -4,83 +4,84 @@ using Server.Engines.BulkOrders; namespace Server.Mobiles { - public class Weaver : BaseVendor - { - private readonly List m_SBInfos = new List(); - - [Constructible] - public Weaver() : base("the weaver") + public class Weaver : BaseVendor { - SetSkill(SkillName.Tailoring, 65.0, 88.0); + private readonly List m_SBInfos = new List(); + + [Constructible] + public Weaver() : base("the weaver") + { + SetSkill(SkillName.Tailoring, 65.0, 88.0); + } + + public Weaver(Serial serial) : base(serial) + { + } + + protected override List SBInfos => m_SBInfos; + + public override NpcGuild NpcGuild => NpcGuild.TailorsGuild; + + public override VendorShoeType ShoeType => VendorShoeType.Sandals; + + public override void InitSBInfo() + { + m_SBInfos.Add(new SBWeaver()); + } + + 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 Item CreateBulkOrder(Mobile from, bool fromContextMenu) + { + if (from is PlayerMobile pm && pm.NextTailorBulkOrder == TimeSpan.Zero && + (fromContextMenu || Utility.RandomDouble() < 0.2)) + { + var theirSkill = pm.Skills.Tailoring.Base; + + if (theirSkill >= 70.1) + pm.NextTailorBulkOrder = TimeSpan.FromHours(6.0); + else if (theirSkill >= 50.1) + pm.NextTailorBulkOrder = TimeSpan.FromHours(2.0); + else + pm.NextTailorBulkOrder = TimeSpan.FromHours(1.0); + + if (theirSkill >= 70.1 && (theirSkill - 40.0) / 300.0 > Utility.RandomDouble()) + return new LargeTailorBOD(); + + return SmallTailorBOD.CreateRandomFor(from); + } + + return null; + } + + public override bool IsValidBulkOrder(Item item) => item is SmallTailorBOD || item is LargeTailorBOD; + + public override bool SupportsBulkOrders(Mobile from) => from is PlayerMobile && from.Skills.Tailoring.Base > 0; + + public override TimeSpan GetNextBulkOrder(Mobile from) + { + if (from is PlayerMobile mobile) + return mobile.NextTailorBulkOrder; + + return TimeSpan.Zero; + } + + public override void OnSuccessfulBulkOrderReceive(Mobile from) + { + if (Core.SE && from is PlayerMobile mobile) + mobile.NextTailorBulkOrder = TimeSpan.Zero; + } } - - public Weaver(Serial serial) : base(serial) - { - } - - protected override List SBInfos => m_SBInfos; - - public override NpcGuild NpcGuild => NpcGuild.TailorsGuild; - - public override VendorShoeType ShoeType => VendorShoeType.Sandals; - - public override void InitSBInfo() - { - m_SBInfos.Add(new SBWeaver()); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override Item CreateBulkOrder(Mobile from, bool fromContextMenu) - { - if (from is PlayerMobile pm && pm.NextTailorBulkOrder == TimeSpan.Zero && (fromContextMenu || Utility.RandomDouble() < 0.2)) - { - double theirSkill = pm.Skills.Tailoring.Base; - - if (theirSkill >= 70.1) - pm.NextTailorBulkOrder = TimeSpan.FromHours(6.0); - else if (theirSkill >= 50.1) - pm.NextTailorBulkOrder = TimeSpan.FromHours(2.0); - else - pm.NextTailorBulkOrder = TimeSpan.FromHours(1.0); - - if (theirSkill >= 70.1 && (theirSkill - 40.0) / 300.0 > Utility.RandomDouble()) - return new LargeTailorBOD(); - - return SmallTailorBOD.CreateRandomFor(from); - } - - return null; - } - - public override bool IsValidBulkOrder(Item item) => item is SmallTailorBOD || item is LargeTailorBOD; - - public override bool SupportsBulkOrders(Mobile from) => from is PlayerMobile && from.Skills.Tailoring.Base > 0; - - public override TimeSpan GetNextBulkOrder(Mobile from) - { - if (from is PlayerMobile mobile) - return mobile.NextTailorBulkOrder; - - return TimeSpan.Zero; - } - - public override void OnSuccessfulBulkOrderReceive(Mobile from) - { - if (Core.SE && from is PlayerMobile mobile) - mobile.NextTailorBulkOrder = TimeSpan.Zero; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/PlayerBarkeeper.cs b/Projects/UOContent/Mobiles/Vendors/PlayerBarkeeper.cs index efebbad17..354c38b78 100644 --- a/Projects/UOContent/Mobiles/Vendors/PlayerBarkeeper.cs +++ b/Projects/UOContent/Mobiles/Vendors/PlayerBarkeeper.cs @@ -9,1032 +9,1069 @@ using Server.Prompts; namespace Server.Mobiles { - public class ChangeRumorMessagePrompt : Prompt - { - private readonly PlayerBarkeeper m_Barkeeper; - private readonly int m_RumorIndex; - - public ChangeRumorMessagePrompt(PlayerBarkeeper barkeeper, int rumorIndex) + public class ChangeRumorMessagePrompt : Prompt { - m_Barkeeper = barkeeper; - m_RumorIndex = rumorIndex; - } + private readonly PlayerBarkeeper m_Barkeeper; + private readonly int m_RumorIndex; - public override void OnCancel(Mobile from) - { - OnResponse(from, ""); - } - - public override void OnResponse(Mobile from, string text) - { - if (text.Length > 130) - text = text.Substring(0, 130); - - m_Barkeeper.EndChangeRumor(from, m_RumorIndex, text); - } - } - - public class ChangeRumorKeywordPrompt : Prompt - { - private readonly PlayerBarkeeper m_Barkeeper; - private readonly int m_RumorIndex; - - public ChangeRumorKeywordPrompt(PlayerBarkeeper barkeeper, int rumorIndex) - { - m_Barkeeper = barkeeper; - m_RumorIndex = rumorIndex; - } - - public override void OnCancel(Mobile from) - { - OnResponse(from, ""); - } - - public override void OnResponse(Mobile from, string text) - { - if (text.Length > 130) - text = text.Substring(0, 130); - - m_Barkeeper.EndChangeKeyword(from, m_RumorIndex, text); - } - } - - public class ChangeTipMessagePrompt : Prompt - { - private readonly PlayerBarkeeper m_Barkeeper; - - public ChangeTipMessagePrompt(PlayerBarkeeper barkeeper) => m_Barkeeper = barkeeper; - - public override void OnCancel(Mobile from) - { - OnResponse(from, ""); - } - - public override void OnResponse(Mobile from, string text) - { - if (text.Length > 130) - text = text.Substring(0, 130); - - m_Barkeeper.EndChangeTip(from, text); - } - } - - public class BarkeeperRumor - { - public BarkeeperRumor(string message, string keyword) - { - Message = message; - Keyword = keyword; - } - - public string Message { get; set; } - - public string Keyword { get; set; } - - public static BarkeeperRumor Deserialize(IGenericReader reader) - { - if (!reader.ReadBool()) - return null; - - return new BarkeeperRumor(reader.ReadString(), reader.ReadString()); - } - - public static void Serialize(IGenericWriter writer, BarkeeperRumor rumor) - { - if (rumor == null) - { - writer.Write(false); - } - else - { - writer.Write(true); - writer.Write(rumor.Message); - writer.Write(rumor.Keyword); - } - } - } - - public class ManageBarkeeperEntry : ContextMenuEntry - { - private readonly PlayerBarkeeper m_Barkeeper; - private readonly Mobile m_From; - - public ManageBarkeeperEntry(Mobile from, PlayerBarkeeper barkeeper) : base(6151, 12) - { - m_From = from; - m_Barkeeper = barkeeper; - } - - public override void OnClick() - { - m_Barkeeper.BeginManagement(m_From); - } - } - - public class PlayerBarkeeper : BaseVendor - { - private BaseHouse m_House; - - private Timer m_NewsTimer; - - private readonly List m_SBInfos = new List(); - - public PlayerBarkeeper(Mobile owner, BaseHouse house) : base("the barkeeper") - { - Owner = owner; - House = house; - Rumors = new BarkeeperRumor[3]; - - LoadSBInfo(); - } - - public PlayerBarkeeper(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Owner { get; set; } - - public BaseHouse House - { - get => m_House; - set - { - m_House?.PlayerBarkeepers.Remove(this); - - value?.PlayerBarkeepers.Add(this); - - m_House = value; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public string TipMessage { get; set; } - - public override bool IsActiveBuyer => false; - public override bool IsActiveSeller => m_SBInfos.Count > 0; - - public override bool DisallowAllMoves => true; - public override bool NoHouseRestrictions => true; - - public BarkeeperRumor[] Rumors { get; private set; } - - public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.ThighBoots : VendorShoeType.Boots; - protected override List SBInfos => m_SBInfos; - - public override bool GetGender() => false; - - public override void InitOutfit() - { - base.InitOutfit(); - - AddItem(new HalfApron(Utility.RandomBrightHue())); - - Container pack = Backpack; - - pack?.Delete(); - } - - public override void InitBody() - { - base.InitBody(); - - if (BodyValue == 0x340 || BodyValue == 0x402) - Hue = 0; - else - Hue = 0x83F4; // hue is not random - - Container pack = Backpack; - - pack?.Delete(); - } - - public override bool HandlesOnSpeech(Mobile from) => InRange(from, 3) || base.HandlesOnSpeech(from); - - private void ShoutNews_Callback(TownCrierEntry tce, int index) - { - if (index < 0 || index >= tce.Lines.Length) - { - m_NewsTimer?.Stop(); - m_NewsTimer = null; - } - else - { - PublicOverheadMessage(MessageType.Regular, 0x3B2, false, tce.Lines[index]); - } - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - House = null; - } - - public override bool OnBeforeDeath() - { - if (!base.OnBeforeDeath()) - return false; - - Item shoes = FindItemOnLayer(Layer.Shoes); - - if (shoes is Sandals) - shoes.Hue = 0; - - return true; - } - - public override void OnSpeech(SpeechEventArgs e) - { - base.OnSpeech(e); - - if (!e.Handled && InRange(e.Mobile, 3)) - { - if (m_NewsTimer == null && e.HasKeyword(0x30)) // *news* + public ChangeRumorMessagePrompt(PlayerBarkeeper barkeeper, int rumorIndex) { - TownCrierEntry tce = GlobalTownCrierEntryList.Instance.GetRandomEntry(); - - if (tce == null) - { - PublicOverheadMessage(MessageType.Regular, 0x3B2, 1005643); // I have no news at this time. - } - else - { - int index = 0; - m_NewsTimer = Timer.DelayCall(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(3.0), - () => ShoutNews_Callback(tce, index)); - - PublicOverheadMessage(MessageType.Regular, 0x3B2, 502978); // Some of the latest news! - } + m_Barkeeper = barkeeper; + m_RumorIndex = rumorIndex; } - for (int i = 0; i < Rumors.Length; ++i) + public override void OnCancel(Mobile from) { - BarkeeperRumor rumor = Rumors[i]; - - string keyword = rumor?.Keyword; - - if (keyword == null || (keyword = keyword.Trim()).Length == 0) - continue; - - if (Insensitive.Equals(keyword, e.Speech)) - { - string message = rumor.Message; - - if (message == null || (message = message.Trim()).Length == 0) - continue; - - PublicOverheadMessage(MessageType.Regular, 0x3B2, false, message); - } + OnResponse(from, ""); } - } - } - public override bool CheckGold(Mobile from, Item dropped) - { - if (!(dropped is Gold g)) - return false; - - if (g.Amount > 50) - { - PrivateOverheadMessage(MessageType.Regular, 0x3B2, false, "I cannot accept so large a tip!", - from.NetState); - } - else - { - string tip = TipMessage; - - if (tip == null || (tip = tip.Trim()).Length == 0) + public override void OnResponse(Mobile from, string text) { - PrivateOverheadMessage(MessageType.Regular, 0x3B2, false, - "It would not be fair of me to take your money and not offer you information in return.", - from.NetState); + if (text.Length > 130) + text = text.Substring(0, 130); + + m_Barkeeper.EndChangeRumor(from, m_RumorIndex, text); } - else + } + + public class ChangeRumorKeywordPrompt : Prompt + { + private readonly PlayerBarkeeper m_Barkeeper; + private readonly int m_RumorIndex; + + public ChangeRumorKeywordPrompt(PlayerBarkeeper barkeeper, int rumorIndex) { - Direction = GetDirectionTo(from); - PrivateOverheadMessage(MessageType.Regular, 0x3B2, false, tip, from.NetState); - - g.Delete(); - return true; + m_Barkeeper = barkeeper; + m_RumorIndex = rumorIndex; } - } - return false; - } - - public bool IsOwner(Mobile from) - { - if (from?.Deleted != false || Deleted) - return false; - - if (from.AccessLevel > AccessLevel.GameMaster) - return true; - - return Owner == from; - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (IsOwner(from) && from.InLOS(this)) - list.Add(new ManageBarkeeperEntry(from, this)); - } - - public void BeginManagement(Mobile from) - { - if (!IsOwner(from)) - return; - - from.SendGump(new BarkeeperGump(from, this)); - } - - public void Dismiss() - { - Delete(); - } - - public void BeginChangeRumor(Mobile from, int index) - { - if (index < 0 || index >= Rumors.Length) - return; - - from.Prompt = new ChangeRumorMessagePrompt(this, index); - PrivateOverheadMessage(MessageType.Regular, 0x3B2, false, "Say what news you would like me to tell our guests.", - from.NetState); - } - - public void EndChangeRumor(Mobile from, int index, string text) - { - if (index < 0 || index >= Rumors.Length) - return; - - if (Rumors[index] == null) - Rumors[index] = new BarkeeperRumor(text, null); - else - Rumors[index].Message = text; - - from.Prompt = new ChangeRumorKeywordPrompt(this, index); - PrivateOverheadMessage(MessageType.Regular, 0x3B2, false, - "What keyword should a guest say to me to get this news?", from.NetState); - } - - public void EndChangeKeyword(Mobile from, int index, string text) - { - if (index < 0 || index >= Rumors.Length) - return; - - if (Rumors[index] == null) - Rumors[index] = new BarkeeperRumor(null, text); - else - Rumors[index].Keyword = text; - - PrivateOverheadMessage(MessageType.Regular, 0x3B2, false, "I'll pass on the message.", from.NetState); - } - - public void RemoveRumor(Mobile from, int index) - { - if (index < 0 || index >= Rumors.Length) - return; - - Rumors[index] = null; - } - - public void BeginChangeTip(Mobile from) - { - from.Prompt = new ChangeTipMessagePrompt(this); - PrivateOverheadMessage(MessageType.Regular, 0x3B2, false, - "Say what you want me to tell guests when they give me a good tip.", from.NetState); - } - - public void EndChangeTip(Mobile from, string text) - { - TipMessage = text; - PrivateOverheadMessage(MessageType.Regular, 0x3B2, false, "I'll say that to anyone who gives me a good tip.", - from.NetState); - } - - public void RemoveTip(Mobile from) - { - TipMessage = null; - } - - public void BeginChangeTitle(Mobile from) - { - from.SendGump(new BarkeeperTitleGump(from, this)); - } - - public void EndChangeTitle(Mobile from, string title, bool vendor) - { - Title = title; - - LoadSBInfo(); - } - - public void CancelChangeTitle(Mobile from) - { - from.SendGump(new BarkeeperGump(from, this)); - } - - public void BeginChangeAppearance(Mobile from) - { - from.CloseGump(); - from.SendGump(new PlayerVendorCustomizeGump(this, from)); - } - - public void ChangeGender(Mobile from) - { - Female = !Female; - - if (Female) - { - Body = 401; - Name = NameList.RandomName("female"); - - FacialHairItemID = 0; - } - else - { - Body = 400; - Name = NameList.RandomName("male"); - } - } - - public override void InitSBInfo() - { - if (Title == "the waiter" || Title == "the barkeeper" || Title == "the baker" || Title == "the innkeeper" || - Title == "the chef") - { - if (m_SBInfos.Count == 0) - m_SBInfos.Add(new SBPlayerBarkeeper()); - } - else - { - m_SBInfos.Clear(); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version; - - writer.Write(m_House); - - writer.Write(Owner); - - writer.WriteEncodedInt(Rumors.Length); - - for (int i = 0; i < Rumors.Length; ++i) - BarkeeperRumor.Serialize(writer, Rumors[i]); - - writer.Write(TipMessage); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - House = (BaseHouse)reader.ReadItem(); - - goto case 0; - } - case 0: - { - Owner = reader.ReadMobile(); - - Rumors = new BarkeeperRumor[reader.ReadEncodedInt()]; - - for (int i = 0; i < Rumors.Length; ++i) - Rumors[i] = BarkeeperRumor.Deserialize(reader); - - TipMessage = reader.ReadString(); - - break; - } - } - - if (version < 1) - Timer.DelayCall(UpgradeFromVersion0); - } - - private void UpgradeFromVersion0() - { - House = BaseHouse.FindHouseAt(this); - } - } - - public class BarkeeperTitleGump : Gump - { - private static readonly Entry[] m_Entries = - { - new Entry("Alchemist"), - new Entry("Animal Tamer"), - new Entry("Apothecary"), - new Entry("Artist"), - new Entry("Baker", true), - new Entry("Bard"), - new Entry("Barkeep", "the barkeeper", true), - new Entry("Beggar"), - new Entry("Blacksmith"), - new Entry("Bounty Hunter"), - new Entry("Brigand"), - new Entry("Butler"), - new Entry("Carpenter"), - new Entry("Chef", true), - new Entry("Commander"), - new Entry("Curator"), - new Entry("Drunkard"), - new Entry("Farmer"), - new Entry("Fisherman"), - new Entry("Gambler"), - new Entry("Gypsy"), - new Entry("Herald"), - new Entry("Herbalist"), - new Entry("Hermit"), - new Entry("Innkeeper", true), - new Entry("Jailor"), - new Entry("Jester"), - new Entry("Librarian"), - new Entry("Mage"), - new Entry("Mercenary"), - new Entry("Merchant"), - new Entry("Messenger"), - new Entry("Miner"), - new Entry("Monk"), - new Entry("Noble"), - new Entry("Paladin"), - new Entry("Peasant"), - new Entry("Pirate"), - new Entry("Prisoner"), - new Entry("Prophet"), - new Entry("Ranger"), - new Entry("Sage"), - new Entry("Sailor"), - new Entry("Scholar"), - new Entry("Scribe"), - new Entry("Sentry"), - new Entry("Servant"), - new Entry("Shepherd"), - new Entry("Soothsayer"), - new Entry("Stoic"), - new Entry("Storyteller"), - new Entry("Tailor"), - new Entry("Thief"), - new Entry("Tinker"), - new Entry("Town Crier"), - new Entry("Treasure Hunter"), - new Entry("Waiter", true), - new Entry("Warrior"), - new Entry("Watchman"), - new Entry("No Title", null) - }; - - private readonly PlayerBarkeeper m_Barkeeper; - private readonly Mobile m_From; - - public BarkeeperTitleGump(Mobile from, PlayerBarkeeper barkeeper) : base(0, 0) - { - m_From = from; - m_Barkeeper = barkeeper; - - from.CloseGump(); - from.CloseGump(); - - Entry[] entries = m_Entries; - - RenderBackground(); - - int pageCount = (entries.Length + 19) / 20; - - for (int i = 0; i < pageCount; ++i) - RenderPage(entries, i); - } - - private void RenderBackground() - { - AddPage(0); - - AddBackground(30, 40, 585, 410, 5054); - - AddImage(30, 40, 9251); - AddImage(180, 40, 9251); - AddImage(30, 40, 9253); - AddImage(30, 130, 9253); - AddImage(598, 40, 9255); - AddImage(598, 130, 9255); - AddImage(30, 433, 9257); - AddImage(180, 433, 9257); - AddImage(30, 40, 9250); - AddImage(598, 40, 9252); - AddImage(598, 433, 9258); - AddImage(30, 433, 9256); - - AddItem(30, 40, 6816); - AddItem(30, 125, 6817); - AddItem(30, 233, 6817); - AddItem(30, 341, 6817); - AddItem(580, 40, 6814); - AddItem(588, 125, 6815); - AddItem(588, 233, 6815); - AddItem(588, 341, 6815); - - AddImage(560, 20, 1417); - AddItem(580, 44, 4033); - - AddBackground(183, 25, 280, 30, 5054); - - AddImage(180, 25, 10460); - AddImage(434, 25, 10460); - - AddHtml(223, 32, 200, 40, "BARKEEP CUSTOMIZATION MENU"); - AddBackground(243, 433, 150, 30, 5054); - - AddImage(240, 433, 10460); - AddImage(375, 433, 10460); - - AddImage(80, 398, 2151); - AddItem(72, 406, 2543); - - AddHtml(110, 412, 180, 25, "sells food and drink"); - } - - private void RenderPage(Entry[] entries, int page) - { - AddPage(1 + page); - - AddHtml(430, 70, 180, 25, $"Page {page + 1} of {(entries.Length + 19) / 20}"); - - for (int count = 0, i = page * 20; count < 20 && i < entries.Length; ++count, ++i) - { - Entry entry = entries[i]; - - AddButton(80 + count / 10 * 260, 100 + count % 10 * 30, 4005, 4007, 2 + i); - AddHtml(120 + count / 10 * 260, 100 + count % 10 * 30, entry.m_Vendor ? 148 : 180, 25, entry.m_Description, - true); - - if (entry.m_Vendor) + public override void OnCancel(Mobile from) { - AddImage(270 + count / 10 * 260, 98 + count % 10 * 30, 2151); - AddItem(262 + count / 10 * 260, 106 + count % 10 * 30, 2543); + OnResponse(from, ""); } - } - AddButton(340, 400, 4005, 4007, 0, GumpButtonType.Page, 1 + (page + 1) % ((entries.Length + 19) / 20)); - AddHtml(380, 400, 180, 25, "More Job Titles"); - - AddButton(338, 437, 4014, 4016, 1); - AddHtml(290, 440, 35, 40, "Back"); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - int buttonID = info.ButtonID; - - if (buttonID > 0) - { - --buttonID; - - if (buttonID > 0) + public override void OnResponse(Mobile from, string text) { - --buttonID; + if (text.Length > 130) + text = text.Substring(0, 130); - if (buttonID >= 0 && buttonID < m_Entries.Length) - m_Barkeeper.EndChangeTitle(m_From, m_Entries[buttonID].m_Title, m_Entries[buttonID].m_Vendor); + m_Barkeeper.EndChangeKeyword(from, m_RumorIndex, text); } - else + } + + public class ChangeTipMessagePrompt : Prompt + { + private readonly PlayerBarkeeper m_Barkeeper; + + public ChangeTipMessagePrompt(PlayerBarkeeper barkeeper) => m_Barkeeper = barkeeper; + + public override void OnCancel(Mobile from) { - m_Barkeeper.CancelChangeTitle(m_From); + OnResponse(from, ""); + } + + public override void OnResponse(Mobile from, string text) + { + if (text.Length > 130) + text = text.Substring(0, 130); + + m_Barkeeper.EndChangeTip(from, text); } - } } - private class Entry + public class BarkeeperRumor { - public readonly string m_Description; - public readonly string m_Title; - public readonly bool m_Vendor; + public BarkeeperRumor(string message, string keyword) + { + Message = message; + Keyword = keyword; + } - public Entry(string desc, bool vendor = false) : this(desc, $"the {desc.ToLower()}", vendor) - { - } + public string Message { get; set; } - public Entry(string desc, string title, bool vendor = false) - { - m_Description = desc; - m_Title = title; - m_Vendor = vendor; - } - } - } + public string Keyword { get; set; } - public class BarkeeperGump : Gump - { - private readonly PlayerBarkeeper m_Barkeeper; - private readonly Mobile m_From; + public static BarkeeperRumor Deserialize(IGenericReader reader) + { + if (!reader.ReadBool()) + return null; - public BarkeeperGump(Mobile from, PlayerBarkeeper barkeeper) : base(0, 0) - { - m_From = from; - m_Barkeeper = barkeeper; + return new BarkeeperRumor(reader.ReadString(), reader.ReadString()); + } - from.CloseGump(); - from.CloseGump(); - - RenderBackground(); - RenderCategories(); - RenderMessageManagement(); - RenderDismissConfirmation(); - RenderMessageManagement_Message_AddOrChange(); - RenderMessageManagement_Message_Remove(); - RenderMessageManagement_Tip_AddOrChange(); - RenderMessageManagement_Tip_Remove(); - RenderAppearanceCategories(); - } - - public void RenderBackground() - { - AddPage(0); - - AddBackground(30, 40, 585, 410, 5054); - - AddImage(30, 40, 9251); - AddImage(180, 40, 9251); - AddImage(30, 40, 9253); - AddImage(30, 130, 9253); - AddImage(598, 40, 9255); - AddImage(598, 130, 9255); - AddImage(30, 433, 9257); - AddImage(180, 433, 9257); - AddImage(30, 40, 9250); - AddImage(598, 40, 9252); - AddImage(598, 433, 9258); - AddImage(30, 433, 9256); - - AddItem(30, 40, 6816); - AddItem(30, 125, 6817); - AddItem(30, 233, 6817); - AddItem(30, 341, 6817); - AddItem(580, 40, 6814); - AddItem(588, 125, 6815); - AddItem(588, 233, 6815); - AddItem(588, 341, 6815); - - AddBackground(183, 25, 280, 30, 5054); - - AddImage(180, 25, 10460); - AddImage(434, 25, 10460); - AddImage(560, 20, 1417); - - AddHtml(223, 32, 200, 40, "BARKEEP CUSTOMIZATION MENU"); - AddBackground(243, 433, 150, 30, 5054); - - AddImage(240, 433, 10460); - AddImage(375, 433, 10460); - } - - public void RenderCategories() - { - AddPage(1); - - AddButton(130, 120, 4005, 4007, 0, GumpButtonType.Page, 2); - AddHtml(170, 120, 200, 40, "Message Control"); - - AddButton(130, 200, 4005, 4007, 0, GumpButtonType.Page, 8); - AddHtml(170, 200, 200, 40, "Customize your barkeep"); - - AddButton(130, 280, 4005, 4007, 0, GumpButtonType.Page, 3); - AddHtml(170, 280, 200, 40, "Dismiss your barkeep"); - - AddButton(338, 437, 4014, 4016, 0); - AddHtml(290, 440, 35, 40, "Back"); - - AddItem(574, 43, 5360); - } - - public void RenderMessageManagement() - { - AddPage(2); - - AddButton(130, 120, 4005, 4007, 0, GumpButtonType.Page, 4); - AddHtml(170, 120, 380, 20, "Add or change a message and keyword"); - - AddButton(130, 200, 4005, 4007, 0, GumpButtonType.Page, 5); - AddHtml(170, 200, 380, 20, "Remove a message and keyword from your barkeep"); - - AddButton(130, 280, 4005, 4007, 0, GumpButtonType.Page, 6); - AddHtml(170, 280, 380, 20, "Add or change your barkeeper's tip message"); - - AddButton(130, 360, 4005, 4007, 0, GumpButtonType.Page, 7); - AddHtml(170, 360, 380, 20, "Delete your barkeepers tip message"); - - AddButton(338, 437, 4014, 4016, 0, GumpButtonType.Page, 1); - AddHtml(290, 440, 35, 40, "Back"); - - AddItem(580, 46, 4030); - } - - public void RenderDismissConfirmation() - { - AddPage(3); - - AddHtml(170, 160, 380, 20, "Are you sure you want to dismiss your barkeeper?"); - - AddButton(205, 280, 4005, 4007, GetButtonID(0, 0)); - AddHtml(240, 280, 100, 20, @"Yes"); - - AddButton(395, 280, 4005, 4007, 0); - AddHtml(430, 280, 100, 20, "No"); - - AddButton(338, 437, 4014, 4016, 0, GumpButtonType.Page, 1); - AddHtml(290, 440, 35, 40, "Back"); - - AddItem(574, 43, 5360); - AddItem(584, 34, 6579); - } - - public void RenderMessageManagement_Message_AddOrChange() - { - AddPage(4); - - AddHtml(250, 60, 500, 25, "Add or change a message"); - - BarkeeperRumor[] rumors = m_Barkeeper.Rumors; - - for (int i = 0; i < rumors.Length; ++i) - { - BarkeeperRumor rumor = rumors[i]; - - AddHtml(100, 70 + i * 120, 50, 20, "Message"); - AddHtml(100, 90 + i * 120, 450, 40, rumor == null ? "No current message" : rumor.Message, true); - AddHtml(100, 130 + i * 120, 50, 20, "Keyword"); - AddHtml(100, 150 + i * 120, 450, 40, rumor == null ? "None" : rumor.Keyword, true); - - AddButton(60, 90 + i * 120, 4005, 4007, GetButtonID(1, i)); - } - - AddButton(338, 437, 4014, 4016, 0, GumpButtonType.Page, 2); - AddHtml(290, 440, 35, 40, "Back"); - - AddItem(580, 46, 4030); - } - - public void RenderMessageManagement_Message_Remove() - { - AddPage(5); - - AddHtml(190, 60, 500, 25, "Choose the message you would like to remove"); - - BarkeeperRumor[] rumors = m_Barkeeper.Rumors; - - for (int i = 0; i < rumors.Length; ++i) - { - BarkeeperRumor rumor = rumors[i]; - - AddHtml(100, 70 + i * 120, 50, 20, "Message"); - AddHtml(100, 90 + i * 120, 450, 40, rumor == null ? "No current message" : rumor.Message, true); - AddHtml(100, 130 + i * 120, 50, 20, "Keyword"); - AddHtml(100, 150 + i * 120, 450, 40, rumor == null ? "None" : rumor.Keyword, true); - - AddButton(60, 90 + i * 120, 4005, 4007, GetButtonID(2, i)); - } - - AddButton(338, 437, 4014, 4016, 0, GumpButtonType.Page, 2); - AddHtml(290, 440, 35, 40, "Back"); - - AddItem(580, 46, 4030); - } - - private int GetButtonID(int type, int index) => 1 + index * 6 + type; - - private void RenderMessageManagement_Tip_AddOrChange() - { - AddPage(6); - - AddHtml(250, 95, 500, 20, "Change this tip message"); - AddHtml(100, 190, 50, 20, "Message"); - AddHtml(100, 210, 450, 40, m_Barkeeper.TipMessage ?? "No current message", true); - - AddButton(60, 210, 4005, 4007, GetButtonID(3, 0)); - - AddButton(338, 437, 4014, 4016, 0, GumpButtonType.Page, 2); - AddHtml(290, 440, 35, 40, "Back"); - - AddItem(580, 46, 4030); - } - - private void RenderMessageManagement_Tip_Remove() - { - AddPage(7); - - AddHtml(250, 95, 500, 20, "Remove this tip message"); - AddHtml(100, 190, 50, 20, "Message"); - AddHtml(100, 210, 450, 40, m_Barkeeper.TipMessage ?? "No current message", true); - - AddButton(60, 210, 4005, 4007, GetButtonID(4, 0)); - - AddButton(338, 437, 4014, 4016, 0, GumpButtonType.Page, 2); - AddHtml(290, 440, 35, 40, "Back"); - - AddItem(580, 46, 4030); - } - - private void RenderAppearanceCategories() - { - AddPage(8); - - AddButton(130, 120, 4005, 4007, GetButtonID(5, 0)); - AddHtml(170, 120, 120, 20, "Title"); - - if (m_Barkeeper.BodyValue != 0x340 && m_Barkeeper.BodyValue != 0x402) - { - AddButton(130, 200, 4005, 4007, GetButtonID(5, 1)); - AddHtml(170, 200, 120, 20, "Appearance"); - - AddButton(130, 280, 4005, 4007, GetButtonID(5, 2)); - AddHtml(170, 280, 120, 20, "Male / Female"); - - AddButton(338, 437, 4014, 4016, 0, GumpButtonType.Page, 1); - AddHtml(290, 440, 35, 40, "Back"); - } - - AddItem(580, 44, 4033); - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (!m_Barkeeper.IsOwner(m_From)) - return; - - int index = info.ButtonID - 1; - - if (index < 0) - return; - - int type = index % 6; - index /= 6; - - switch (type) - { - case 0: // Controls - { - switch (index) + public static void Serialize(IGenericWriter writer, BarkeeperRumor rumor) + { + if (rumor == null) { - case 0: // Dismiss + writer.Write(false); + } + else + { + writer.Write(true); + writer.Write(rumor.Message); + writer.Write(rumor.Keyword); + } + } + } + + public class ManageBarkeeperEntry : ContextMenuEntry + { + private readonly PlayerBarkeeper m_Barkeeper; + private readonly Mobile m_From; + + public ManageBarkeeperEntry(Mobile from, PlayerBarkeeper barkeeper) : base(6151, 12) + { + m_From = from; + m_Barkeeper = barkeeper; + } + + public override void OnClick() + { + m_Barkeeper.BeginManagement(m_From); + } + } + + public class PlayerBarkeeper : BaseVendor + { + private readonly List m_SBInfos = new List(); + private BaseHouse m_House; + + private Timer m_NewsTimer; + + public PlayerBarkeeper(Mobile owner, BaseHouse house) : base("the barkeeper") + { + Owner = owner; + House = house; + Rumors = new BarkeeperRumor[3]; + + LoadSBInfo(); + } + + public PlayerBarkeeper(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Owner { get; set; } + + public BaseHouse House + { + get => m_House; + set + { + m_House?.PlayerBarkeepers.Remove(this); + + value?.PlayerBarkeepers.Add(this); + + m_House = value; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public string TipMessage { get; set; } + + public override bool IsActiveBuyer => false; + public override bool IsActiveSeller => m_SBInfos.Count > 0; + + public override bool DisallowAllMoves => true; + public override bool NoHouseRestrictions => true; + + public BarkeeperRumor[] Rumors { get; private set; } + + public override VendorShoeType ShoeType => Utility.RandomBool() ? VendorShoeType.ThighBoots : VendorShoeType.Boots; + protected override List SBInfos => m_SBInfos; + + public override bool GetGender() => false; + + public override void InitOutfit() + { + base.InitOutfit(); + + AddItem(new HalfApron(Utility.RandomBrightHue())); + + var pack = Backpack; + + pack?.Delete(); + } + + public override void InitBody() + { + base.InitBody(); + + if (BodyValue == 0x340 || BodyValue == 0x402) + Hue = 0; + else + Hue = 0x83F4; // hue is not random + + var pack = Backpack; + + pack?.Delete(); + } + + public override bool HandlesOnSpeech(Mobile from) => InRange(from, 3) || base.HandlesOnSpeech(from); + + private void ShoutNews_Callback(TownCrierEntry tce, int index) + { + if (index < 0 || index >= tce.Lines.Length) + { + m_NewsTimer?.Stop(); + m_NewsTimer = null; + } + else + { + PublicOverheadMessage(MessageType.Regular, 0x3B2, false, tce.Lines[index]); + } + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + House = null; + } + + public override bool OnBeforeDeath() + { + if (!base.OnBeforeDeath()) + return false; + + var shoes = FindItemOnLayer(Layer.Shoes); + + if (shoes is Sandals) + shoes.Hue = 0; + + return true; + } + + public override void OnSpeech(SpeechEventArgs e) + { + base.OnSpeech(e); + + if (!e.Handled && InRange(e.Mobile, 3)) + { + if (m_NewsTimer == null && e.HasKeyword(0x30)) // *news* { - m_Barkeeper.Dismiss(); - break; + var tce = GlobalTownCrierEntryList.Instance.GetRandomEntry(); + + if (tce == null) + { + PublicOverheadMessage(MessageType.Regular, 0x3B2, 1005643); // I have no news at this time. + } + else + { + var index = 0; + m_NewsTimer = Timer.DelayCall( + TimeSpan.FromSeconds(1.0), + TimeSpan.FromSeconds(3.0), + () => ShoutNews_Callback(tce, index) + ); + + PublicOverheadMessage(MessageType.Regular, 0x3B2, 502978); // Some of the latest news! + } + } + + for (var i = 0; i < Rumors.Length; ++i) + { + var rumor = Rumors[i]; + + var keyword = rumor?.Keyword; + + if (keyword == null || (keyword = keyword.Trim()).Length == 0) + continue; + + if (Insensitive.Equals(keyword, e.Speech)) + { + var message = rumor.Message; + + if (message == null || (message = message.Trim()).Length == 0) + continue; + + PublicOverheadMessage(MessageType.Regular, 0x3B2, false, message); + } + } + } + } + + public override bool CheckGold(Mobile from, Item dropped) + { + if (!(dropped is Gold g)) + return false; + + if (g.Amount > 50) + { + PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + false, + "I cannot accept so large a tip!", + from.NetState + ); + } + else + { + var tip = TipMessage; + + if (tip == null || (tip = tip.Trim()).Length == 0) + { + PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + false, + "It would not be fair of me to take your money and not offer you information in return.", + from.NetState + ); + } + else + { + Direction = GetDirectionTo(from); + PrivateOverheadMessage(MessageType.Regular, 0x3B2, false, tip, from.NetState); + + g.Delete(); + return true; } } - break; - } - case 1: // Change message - { - m_Barkeeper.BeginChangeRumor(m_From, index); - break; - } - case 2: // Remove message - { - m_Barkeeper.RemoveRumor(m_From, index); - break; - } - case 3: // Change tip - { - m_Barkeeper.BeginChangeTip(m_From); - break; - } - case 4: // Remove tip - { - m_Barkeeper.RemoveTip(m_From); - break; - } - case 5: // Appearance category selection - { - switch (index) + return false; + } + + public bool IsOwner(Mobile from) + { + if (from?.Deleted != false || Deleted) + return false; + + if (from.AccessLevel > AccessLevel.GameMaster) + return true; + + return Owner == from; + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (IsOwner(from) && from.InLOS(this)) + list.Add(new ManageBarkeeperEntry(from, this)); + } + + public void BeginManagement(Mobile from) + { + if (!IsOwner(from)) + return; + + from.SendGump(new BarkeeperGump(from, this)); + } + + public void Dismiss() + { + Delete(); + } + + public void BeginChangeRumor(Mobile from, int index) + { + if (index < 0 || index >= Rumors.Length) + return; + + from.Prompt = new ChangeRumorMessagePrompt(this, index); + PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + false, + "Say what news you would like me to tell our guests.", + from.NetState + ); + } + + public void EndChangeRumor(Mobile from, int index, string text) + { + if (index < 0 || index >= Rumors.Length) + return; + + if (Rumors[index] == null) + Rumors[index] = new BarkeeperRumor(text, null); + else + Rumors[index].Message = text; + + from.Prompt = new ChangeRumorKeywordPrompt(this, index); + PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + false, + "What keyword should a guest say to me to get this news?", + from.NetState + ); + } + + public void EndChangeKeyword(Mobile from, int index, string text) + { + if (index < 0 || index >= Rumors.Length) + return; + + if (Rumors[index] == null) + Rumors[index] = new BarkeeperRumor(null, text); + else + Rumors[index].Keyword = text; + + PrivateOverheadMessage(MessageType.Regular, 0x3B2, false, "I'll pass on the message.", from.NetState); + } + + public void RemoveRumor(Mobile from, int index) + { + if (index < 0 || index >= Rumors.Length) + return; + + Rumors[index] = null; + } + + public void BeginChangeTip(Mobile from) + { + from.Prompt = new ChangeTipMessagePrompt(this); + PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + false, + "Say what you want me to tell guests when they give me a good tip.", + from.NetState + ); + } + + public void EndChangeTip(Mobile from, string text) + { + TipMessage = text; + PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + false, + "I'll say that to anyone who gives me a good tip.", + from.NetState + ); + } + + public void RemoveTip(Mobile from) + { + TipMessage = null; + } + + public void BeginChangeTitle(Mobile from) + { + from.SendGump(new BarkeeperTitleGump(from, this)); + } + + public void EndChangeTitle(Mobile from, string title, bool vendor) + { + Title = title; + + LoadSBInfo(); + } + + public void CancelChangeTitle(Mobile from) + { + from.SendGump(new BarkeeperGump(from, this)); + } + + public void BeginChangeAppearance(Mobile from) + { + from.CloseGump(); + from.SendGump(new PlayerVendorCustomizeGump(this, from)); + } + + public void ChangeGender(Mobile from) + { + Female = !Female; + + if (Female) { - case 0: - m_Barkeeper.BeginChangeTitle(m_From); - break; - case 1: - m_Barkeeper.BeginChangeAppearance(m_From); - break; - case 2: - m_Barkeeper.ChangeGender(m_From); - break; + Body = 401; + Name = NameList.RandomName("female"); + + FacialHairItemID = 0; + } + else + { + Body = 400; + Name = NameList.RandomName("male"); + } + } + + public override void InitSBInfo() + { + if (Title == "the waiter" || Title == "the barkeeper" || Title == "the baker" || Title == "the innkeeper" || + Title == "the chef") + { + if (m_SBInfos.Count == 0) + m_SBInfos.Add(new SBPlayerBarkeeper()); + } + else + { + m_SBInfos.Clear(); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version; + + writer.Write(m_House); + + writer.Write(Owner); + + writer.WriteEncodedInt(Rumors.Length); + + for (var i = 0; i < Rumors.Length; ++i) + BarkeeperRumor.Serialize(writer, Rumors[i]); + + writer.Write(TipMessage); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + House = (BaseHouse)reader.ReadItem(); + + goto case 0; + } + case 0: + { + Owner = reader.ReadMobile(); + + Rumors = new BarkeeperRumor[reader.ReadEncodedInt()]; + + for (var i = 0; i < Rumors.Length; ++i) + Rumors[i] = BarkeeperRumor.Deserialize(reader); + + TipMessage = reader.ReadString(); + + break; + } } - break; - } - } + if (version < 1) + Timer.DelayCall(UpgradeFromVersion0); + } + + private void UpgradeFromVersion0() + { + House = BaseHouse.FindHouseAt(this); + } + } + + public class BarkeeperTitleGump : Gump + { + private static readonly Entry[] m_Entries = + { + new Entry("Alchemist"), + new Entry("Animal Tamer"), + new Entry("Apothecary"), + new Entry("Artist"), + new Entry("Baker", true), + new Entry("Bard"), + new Entry("Barkeep", "the barkeeper", true), + new Entry("Beggar"), + new Entry("Blacksmith"), + new Entry("Bounty Hunter"), + new Entry("Brigand"), + new Entry("Butler"), + new Entry("Carpenter"), + new Entry("Chef", true), + new Entry("Commander"), + new Entry("Curator"), + new Entry("Drunkard"), + new Entry("Farmer"), + new Entry("Fisherman"), + new Entry("Gambler"), + new Entry("Gypsy"), + new Entry("Herald"), + new Entry("Herbalist"), + new Entry("Hermit"), + new Entry("Innkeeper", true), + new Entry("Jailor"), + new Entry("Jester"), + new Entry("Librarian"), + new Entry("Mage"), + new Entry("Mercenary"), + new Entry("Merchant"), + new Entry("Messenger"), + new Entry("Miner"), + new Entry("Monk"), + new Entry("Noble"), + new Entry("Paladin"), + new Entry("Peasant"), + new Entry("Pirate"), + new Entry("Prisoner"), + new Entry("Prophet"), + new Entry("Ranger"), + new Entry("Sage"), + new Entry("Sailor"), + new Entry("Scholar"), + new Entry("Scribe"), + new Entry("Sentry"), + new Entry("Servant"), + new Entry("Shepherd"), + new Entry("Soothsayer"), + new Entry("Stoic"), + new Entry("Storyteller"), + new Entry("Tailor"), + new Entry("Thief"), + new Entry("Tinker"), + new Entry("Town Crier"), + new Entry("Treasure Hunter"), + new Entry("Waiter", true), + new Entry("Warrior"), + new Entry("Watchman"), + new Entry("No Title", null) + }; + + private readonly PlayerBarkeeper m_Barkeeper; + private readonly Mobile m_From; + + public BarkeeperTitleGump(Mobile from, PlayerBarkeeper barkeeper) : base(0, 0) + { + m_From = from; + m_Barkeeper = barkeeper; + + from.CloseGump(); + from.CloseGump(); + + var entries = m_Entries; + + RenderBackground(); + + var pageCount = (entries.Length + 19) / 20; + + for (var i = 0; i < pageCount; ++i) + RenderPage(entries, i); + } + + private void RenderBackground() + { + AddPage(0); + + AddBackground(30, 40, 585, 410, 5054); + + AddImage(30, 40, 9251); + AddImage(180, 40, 9251); + AddImage(30, 40, 9253); + AddImage(30, 130, 9253); + AddImage(598, 40, 9255); + AddImage(598, 130, 9255); + AddImage(30, 433, 9257); + AddImage(180, 433, 9257); + AddImage(30, 40, 9250); + AddImage(598, 40, 9252); + AddImage(598, 433, 9258); + AddImage(30, 433, 9256); + + AddItem(30, 40, 6816); + AddItem(30, 125, 6817); + AddItem(30, 233, 6817); + AddItem(30, 341, 6817); + AddItem(580, 40, 6814); + AddItem(588, 125, 6815); + AddItem(588, 233, 6815); + AddItem(588, 341, 6815); + + AddImage(560, 20, 1417); + AddItem(580, 44, 4033); + + AddBackground(183, 25, 280, 30, 5054); + + AddImage(180, 25, 10460); + AddImage(434, 25, 10460); + + AddHtml(223, 32, 200, 40, "BARKEEP CUSTOMIZATION MENU"); + AddBackground(243, 433, 150, 30, 5054); + + AddImage(240, 433, 10460); + AddImage(375, 433, 10460); + + AddImage(80, 398, 2151); + AddItem(72, 406, 2543); + + AddHtml(110, 412, 180, 25, "sells food and drink"); + } + + private void RenderPage(Entry[] entries, int page) + { + AddPage(1 + page); + + AddHtml(430, 70, 180, 25, $"Page {page + 1} of {(entries.Length + 19) / 20}"); + + for (int count = 0, i = page * 20; count < 20 && i < entries.Length; ++count, ++i) + { + var entry = entries[i]; + + AddButton(80 + count / 10 * 260, 100 + count % 10 * 30, 4005, 4007, 2 + i); + AddHtml( + 120 + count / 10 * 260, + 100 + count % 10 * 30, + entry.m_Vendor ? 148 : 180, + 25, + entry.m_Description, + true + ); + + if (entry.m_Vendor) + { + AddImage(270 + count / 10 * 260, 98 + count % 10 * 30, 2151); + AddItem(262 + count / 10 * 260, 106 + count % 10 * 30, 2543); + } + } + + AddButton(340, 400, 4005, 4007, 0, GumpButtonType.Page, 1 + (page + 1) % ((entries.Length + 19) / 20)); + AddHtml(380, 400, 180, 25, "More Job Titles"); + + AddButton(338, 437, 4014, 4016, 1); + AddHtml(290, 440, 35, 40, "Back"); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var buttonID = info.ButtonID; + + if (buttonID > 0) + { + --buttonID; + + if (buttonID > 0) + { + --buttonID; + + if (buttonID >= 0 && buttonID < m_Entries.Length) + m_Barkeeper.EndChangeTitle(m_From, m_Entries[buttonID].m_Title, m_Entries[buttonID].m_Vendor); + } + else + { + m_Barkeeper.CancelChangeTitle(m_From); + } + } + } + + private class Entry + { + public readonly string m_Description; + public readonly string m_Title; + public readonly bool m_Vendor; + + public Entry(string desc, bool vendor = false) : this(desc, $"the {desc.ToLower()}", vendor) + { + } + + public Entry(string desc, string title, bool vendor = false) + { + m_Description = desc; + m_Title = title; + m_Vendor = vendor; + } + } + } + + public class BarkeeperGump : Gump + { + private readonly PlayerBarkeeper m_Barkeeper; + private readonly Mobile m_From; + + public BarkeeperGump(Mobile from, PlayerBarkeeper barkeeper) : base(0, 0) + { + m_From = from; + m_Barkeeper = barkeeper; + + from.CloseGump(); + from.CloseGump(); + + RenderBackground(); + RenderCategories(); + RenderMessageManagement(); + RenderDismissConfirmation(); + RenderMessageManagement_Message_AddOrChange(); + RenderMessageManagement_Message_Remove(); + RenderMessageManagement_Tip_AddOrChange(); + RenderMessageManagement_Tip_Remove(); + RenderAppearanceCategories(); + } + + public void RenderBackground() + { + AddPage(0); + + AddBackground(30, 40, 585, 410, 5054); + + AddImage(30, 40, 9251); + AddImage(180, 40, 9251); + AddImage(30, 40, 9253); + AddImage(30, 130, 9253); + AddImage(598, 40, 9255); + AddImage(598, 130, 9255); + AddImage(30, 433, 9257); + AddImage(180, 433, 9257); + AddImage(30, 40, 9250); + AddImage(598, 40, 9252); + AddImage(598, 433, 9258); + AddImage(30, 433, 9256); + + AddItem(30, 40, 6816); + AddItem(30, 125, 6817); + AddItem(30, 233, 6817); + AddItem(30, 341, 6817); + AddItem(580, 40, 6814); + AddItem(588, 125, 6815); + AddItem(588, 233, 6815); + AddItem(588, 341, 6815); + + AddBackground(183, 25, 280, 30, 5054); + + AddImage(180, 25, 10460); + AddImage(434, 25, 10460); + AddImage(560, 20, 1417); + + AddHtml(223, 32, 200, 40, "BARKEEP CUSTOMIZATION MENU"); + AddBackground(243, 433, 150, 30, 5054); + + AddImage(240, 433, 10460); + AddImage(375, 433, 10460); + } + + public void RenderCategories() + { + AddPage(1); + + AddButton(130, 120, 4005, 4007, 0, GumpButtonType.Page, 2); + AddHtml(170, 120, 200, 40, "Message Control"); + + AddButton(130, 200, 4005, 4007, 0, GumpButtonType.Page, 8); + AddHtml(170, 200, 200, 40, "Customize your barkeep"); + + AddButton(130, 280, 4005, 4007, 0, GumpButtonType.Page, 3); + AddHtml(170, 280, 200, 40, "Dismiss your barkeep"); + + AddButton(338, 437, 4014, 4016, 0); + AddHtml(290, 440, 35, 40, "Back"); + + AddItem(574, 43, 5360); + } + + public void RenderMessageManagement() + { + AddPage(2); + + AddButton(130, 120, 4005, 4007, 0, GumpButtonType.Page, 4); + AddHtml(170, 120, 380, 20, "Add or change a message and keyword"); + + AddButton(130, 200, 4005, 4007, 0, GumpButtonType.Page, 5); + AddHtml(170, 200, 380, 20, "Remove a message and keyword from your barkeep"); + + AddButton(130, 280, 4005, 4007, 0, GumpButtonType.Page, 6); + AddHtml(170, 280, 380, 20, "Add or change your barkeeper's tip message"); + + AddButton(130, 360, 4005, 4007, 0, GumpButtonType.Page, 7); + AddHtml(170, 360, 380, 20, "Delete your barkeepers tip message"); + + AddButton(338, 437, 4014, 4016, 0, GumpButtonType.Page, 1); + AddHtml(290, 440, 35, 40, "Back"); + + AddItem(580, 46, 4030); + } + + public void RenderDismissConfirmation() + { + AddPage(3); + + AddHtml(170, 160, 380, 20, "Are you sure you want to dismiss your barkeeper?"); + + AddButton(205, 280, 4005, 4007, GetButtonID(0, 0)); + AddHtml(240, 280, 100, 20, @"Yes"); + + AddButton(395, 280, 4005, 4007, 0); + AddHtml(430, 280, 100, 20, "No"); + + AddButton(338, 437, 4014, 4016, 0, GumpButtonType.Page, 1); + AddHtml(290, 440, 35, 40, "Back"); + + AddItem(574, 43, 5360); + AddItem(584, 34, 6579); + } + + public void RenderMessageManagement_Message_AddOrChange() + { + AddPage(4); + + AddHtml(250, 60, 500, 25, "Add or change a message"); + + var rumors = m_Barkeeper.Rumors; + + for (var i = 0; i < rumors.Length; ++i) + { + var rumor = rumors[i]; + + AddHtml(100, 70 + i * 120, 50, 20, "Message"); + AddHtml(100, 90 + i * 120, 450, 40, rumor == null ? "No current message" : rumor.Message, true); + AddHtml(100, 130 + i * 120, 50, 20, "Keyword"); + AddHtml(100, 150 + i * 120, 450, 40, rumor == null ? "None" : rumor.Keyword, true); + + AddButton(60, 90 + i * 120, 4005, 4007, GetButtonID(1, i)); + } + + AddButton(338, 437, 4014, 4016, 0, GumpButtonType.Page, 2); + AddHtml(290, 440, 35, 40, "Back"); + + AddItem(580, 46, 4030); + } + + public void RenderMessageManagement_Message_Remove() + { + AddPage(5); + + AddHtml(190, 60, 500, 25, "Choose the message you would like to remove"); + + var rumors = m_Barkeeper.Rumors; + + for (var i = 0; i < rumors.Length; ++i) + { + var rumor = rumors[i]; + + AddHtml(100, 70 + i * 120, 50, 20, "Message"); + AddHtml(100, 90 + i * 120, 450, 40, rumor == null ? "No current message" : rumor.Message, true); + AddHtml(100, 130 + i * 120, 50, 20, "Keyword"); + AddHtml(100, 150 + i * 120, 450, 40, rumor == null ? "None" : rumor.Keyword, true); + + AddButton(60, 90 + i * 120, 4005, 4007, GetButtonID(2, i)); + } + + AddButton(338, 437, 4014, 4016, 0, GumpButtonType.Page, 2); + AddHtml(290, 440, 35, 40, "Back"); + + AddItem(580, 46, 4030); + } + + private int GetButtonID(int type, int index) => 1 + index * 6 + type; + + private void RenderMessageManagement_Tip_AddOrChange() + { + AddPage(6); + + AddHtml(250, 95, 500, 20, "Change this tip message"); + AddHtml(100, 190, 50, 20, "Message"); + AddHtml(100, 210, 450, 40, m_Barkeeper.TipMessage ?? "No current message", true); + + AddButton(60, 210, 4005, 4007, GetButtonID(3, 0)); + + AddButton(338, 437, 4014, 4016, 0, GumpButtonType.Page, 2); + AddHtml(290, 440, 35, 40, "Back"); + + AddItem(580, 46, 4030); + } + + private void RenderMessageManagement_Tip_Remove() + { + AddPage(7); + + AddHtml(250, 95, 500, 20, "Remove this tip message"); + AddHtml(100, 190, 50, 20, "Message"); + AddHtml(100, 210, 450, 40, m_Barkeeper.TipMessage ?? "No current message", true); + + AddButton(60, 210, 4005, 4007, GetButtonID(4, 0)); + + AddButton(338, 437, 4014, 4016, 0, GumpButtonType.Page, 2); + AddHtml(290, 440, 35, 40, "Back"); + + AddItem(580, 46, 4030); + } + + private void RenderAppearanceCategories() + { + AddPage(8); + + AddButton(130, 120, 4005, 4007, GetButtonID(5, 0)); + AddHtml(170, 120, 120, 20, "Title"); + + if (m_Barkeeper.BodyValue != 0x340 && m_Barkeeper.BodyValue != 0x402) + { + AddButton(130, 200, 4005, 4007, GetButtonID(5, 1)); + AddHtml(170, 200, 120, 20, "Appearance"); + + AddButton(130, 280, 4005, 4007, GetButtonID(5, 2)); + AddHtml(170, 280, 120, 20, "Male / Female"); + + AddButton(338, 437, 4014, 4016, 0, GumpButtonType.Page, 1); + AddHtml(290, 440, 35, 40, "Back"); + } + + AddItem(580, 44, 4033); + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (!m_Barkeeper.IsOwner(m_From)) + return; + + var index = info.ButtonID - 1; + + if (index < 0) + return; + + var type = index % 6; + index /= 6; + + switch (type) + { + case 0: // Controls + { + switch (index) + { + case 0: // Dismiss + { + m_Barkeeper.Dismiss(); + break; + } + } + + break; + } + case 1: // Change message + { + m_Barkeeper.BeginChangeRumor(m_From, index); + break; + } + case 2: // Remove message + { + m_Barkeeper.RemoveRumor(m_From, index); + break; + } + case 3: // Change tip + { + m_Barkeeper.BeginChangeTip(m_From); + break; + } + case 4: // Remove tip + { + m_Barkeeper.RemoveTip(m_From); + break; + } + case 5: // Appearance category selection + { + switch (index) + { + case 0: + m_Barkeeper.BeginChangeTitle(m_From); + break; + case 1: + m_Barkeeper.BeginChangeAppearance(m_From); + break; + case 2: + m_Barkeeper.ChangeGender(m_From); + break; + } + + break; + } + } + } } - } } diff --git a/Projects/UOContent/Mobiles/Vendors/PlayerVendor.cs b/Projects/UOContent/Mobiles/Vendors/PlayerVendor.cs index 7bb7c2e95..956755bb3 100644 --- a/Projects/UOContent/Mobiles/Vendors/PlayerVendor.cs +++ b/Projects/UOContent/Mobiles/Vendors/PlayerVendor.cs @@ -14,1515 +14,1535 @@ using Server.Targeting; namespace Server.Mobiles { - [AttributeUsage(AttributeTargets.Class)] - public class PlayerVendorTargetAttribute : Attribute - { - } - - public class VendorItem - { - private string m_Description; - - public VendorItem(Item item, int price, string description, DateTime created) - { - Item = item; - Price = price; - m_Description = description ?? ""; - Created = created; - Valid = true; - } - - public Item Item { get; } - - public int Price { get; } - - public string FormattedPrice - { - get - { - if (Core.ML) - return Price.ToString("N0", CultureInfo.GetCultureInfo("en-US")); - - return Price.ToString(); - } - } - - public string Description - { - get => m_Description; - set - { - m_Description = value ?? ""; - - if (Valid) - Item.InvalidateProperties(); - } - } - - public DateTime Created { get; } - - public bool IsForSale => Price >= 0; - public bool IsForFree => Price == 0; - - public bool Valid { get; private set; } - - public void Invalidate() - { - Valid = false; - } - } - - public class VendorBackpack : Backpack - { - public VendorBackpack() - { - Layer = Layer.Backpack; - Weight = 1.0; - } - - public VendorBackpack(Serial serial) : base(serial) + [AttributeUsage(AttributeTargets.Class)] + public class PlayerVendorTargetAttribute : Attribute { } - public override int DefaultMaxWeight => 0; - - public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight) + public class VendorItem { - if (!base.CheckHold(m, item, message, checkItems, plusItems, plusWeight)) - return false; + private string m_Description; - if (Ethic.IsImbued(item, true)) - { - if (message) - m.SendMessage("Imbued items may not be sold here."); - - return false; - } - - if (!BaseHouse.NewVendorSystem && Parent is PlayerVendor vendor) - { - BaseHouse house = vendor.House; - - if (house?.IsAosRules == true && !house.CheckAosStorage(1 + item.TotalItems + plusItems)) + public VendorItem(Item item, int price, string description, DateTime created) { - if (message) - m.SendLocalizedMessage(1061839); // This action would exceed the secure storage limit of the house. - - return false; - } - } - - return true; - } - - public override bool IsAccessibleTo(Mobile m) => true; - - public override bool CheckItemUse(Mobile from, Item item) - { - if (!base.CheckItemUse(from, item)) - return false; - - if (item is Container || item is BulkOrderBook) - return true; - - from.SendLocalizedMessage(500447); // That is not accessible. - return false; - } - - public override bool CheckTarget(Mobile from, Target targ, object targeted) => - base.CheckTarget(from, targ, targeted) && - (from.AccessLevel >= AccessLevel.GameMaster || - targ.GetType().IsDefined(typeof(PlayerVendorTargetAttribute), false)); - - public override void GetChildContextMenuEntries(Mobile from, List list, Item item) - { - base.GetChildContextMenuEntries(from, list, item); - - if (!(RootParent is PlayerVendor pv) || pv.IsOwner(from)) - return; - - VendorItem vi = pv.GetVendorItem(item); - - if (vi != null) - list.Add(new BuyEntry(item)); - } - - public override void GetChildNameProperties(ObjectPropertyList list, Item item) - { - base.GetChildNameProperties(list, item); - - PlayerVendor pv = RootParent as PlayerVendor; - - VendorItem vi = pv?.GetVendorItem(item); - - if (vi == null) - return; - - if (!vi.IsForSale) - list.Add(1043307); // Price: Not for sale. - else if (vi.IsForFree) - list.Add(1043306); // Price: FREE! - else - list.Add(1043304, vi.FormattedPrice); // Price: ~1_COST~ - } - - public override void GetChildProperties(ObjectPropertyList list, Item item) - { - base.GetChildProperties(list, item); - - PlayerVendor pv = RootParent as PlayerVendor; - - VendorItem vi = pv?.GetVendorItem(item); - - if (vi?.Description != null && vi.Description.Length > 0) - list.Add(1043305, vi.Description); //
Seller's Description:
"~1_DESC~" - } - - public override void OnSingleClickContained(Mobile from, Item item) - { - if (RootParent is PlayerVendor vendor) - { - VendorItem vi = vendor.GetVendorItem(item); - - if (vi != null) - { - if (!vi.IsForSale) - item.LabelTo(from, 1043307); // Price: Not for sale. - else if (vi.IsForFree) - item.LabelTo(from, 1043306); // Price: FREE! - else - item.LabelTo(from, 1043304, vi.FormattedPrice); // Price: ~1_COST~ - - if (!string.IsNullOrEmpty(vi.Description)) item.LabelTo(from, "Description: {0}", vi.Description); - } - } - - base.OnSingleClickContained(from, item); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - private class BuyEntry : ContextMenuEntry - { - private readonly Item m_Item; - - public BuyEntry(Item item) : base(6103) => m_Item = item; - - public override bool NonLocalUse => true; - - public override void OnClick() - { - if (m_Item.Deleted) - return; - - PlayerVendor.TryToBuy(m_Item, Owner.From); - } - } - } - - public class PlayerVendor : Mobile - { - private BaseHouse m_House; - - private Timer m_PayTimer; - private Dictionary m_SellItems; - - private string m_ShopName; - - public PlayerVendor(Mobile owner, BaseHouse house) - { - Owner = owner; - House = house; - - if (BaseHouse.NewVendorSystem) - { - BankAccount = 0; - HoldGold = 4; - } - else - { - BankAccount = 1000; - HoldGold = 0; - } - - ShopName = "Shop Not Yet Named"; - - m_SellItems = new Dictionary(); - - CantWalk = true; - - if (!Core.AOS) - NameHue = 0x35; - - InitStats(100, 100, 25); - InitBody(); - InitOutfit(); - - TimeSpan delay = PayTimer.GetInterval(); - - m_PayTimer = new PayTimer(this, delay); - m_PayTimer.Start(); - - NextPayTime = DateTime.UtcNow + delay; - } - - public PlayerVendor(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Owner { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int BankAccount { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int HoldGold { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public string ShopName - { - get => m_ShopName; - set - { - m_ShopName = value ?? ""; - - InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime NextPayTime { get; private set; } - - public PlayerVendorPlaceholder Placeholder { get; set; } - - public BaseHouse House - { - get => m_House; - set - { - m_House?.PlayerVendors.Remove(this); - - value?.PlayerVendors.Add(this); - - m_House = value; - } - } - - public int ChargePerDay - { - get - { - if (BaseHouse.NewVendorSystem) return ChargePerRealWorldDay / 12; - - long total = m_SellItems.Values.Aggregate(0, (current, vi) => - current + vi.Price) - 500; - - return (int)(20 + Math.Max(total, 0) / 500); - } - } - - public int ChargePerRealWorldDay - { - get - { - if (BaseHouse.NewVendorSystem) - { - long total = m_SellItems.Values.Aggregate(0, (current, vi) => current + vi.Price); - - return (int)(60 + total / 500 * 3); + Item = item; + Price = price; + m_Description = description ?? ""; + Created = created; + Valid = true; } - return ChargePerDay * 12; - } - } + public Item Item { get; } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public int Price { get; } - writer.Write(2); // version - - writer.Write(BaseHouse.NewVendorSystem); - writer.Write(m_ShopName); - writer.WriteDeltaTime(NextPayTime); - writer.Write(House); - - writer.Write(Owner); - writer.Write(BankAccount); - writer.Write(HoldGold); - - writer.Write(m_SellItems.Count); - foreach (VendorItem vi in m_SellItems.Values) - { - writer.Write(vi.Item); - writer.Write(vi.Price); - writer.Write(vi.Description); - - writer.Write(vi.Created); - } - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - bool newVendorSystem = false; - - switch (version) - { - case 2: - case 1: - { - newVendorSystem = reader.ReadBool(); - m_ShopName = reader.ReadString(); - NextPayTime = reader.ReadDeltaTime(); - House = (BaseHouse)reader.ReadItem(); - - goto case 0; - } - case 0: - { - Owner = reader.ReadMobile(); - BankAccount = reader.ReadInt(); - HoldGold = reader.ReadInt(); - - int count = reader.ReadInt(); - - m_SellItems = new Dictionary(count); - - for (int i = 0; i < count; i++) + public string FormattedPrice + { + get { - Item item = reader.ReadItem(); + if (Core.ML) + return Price.ToString("N0", CultureInfo.GetCultureInfo("en-US")); - int price = reader.ReadInt(); - if (price > 100000000) - price = 100000000; + return Price.ToString(); + } + } - string description = reader.ReadString(); + public string Description + { + get => m_Description; + set + { + m_Description = value ?? ""; - DateTime created = version < 1 ? DateTime.UtcNow : reader.ReadDateTime(); + if (Valid) + Item.InvalidateProperties(); + } + } - if (item != null) SetVendorItem(item, version < 1 && price <= 0 ? -1 : price, description, created); + public DateTime Created { get; } + + public bool IsForSale => Price >= 0; + public bool IsForFree => Price == 0; + + public bool Valid { get; private set; } + + public void Invalidate() + { + Valid = false; + } + } + + public class VendorBackpack : Backpack + { + public VendorBackpack() + { + Layer = Layer.Backpack; + Weight = 1.0; + } + + public VendorBackpack(Serial serial) : base(serial) + { + } + + public override int DefaultMaxWeight => 0; + + public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight) + { + if (!base.CheckHold(m, item, message, checkItems, plusItems, plusWeight)) + return false; + + if (Ethic.IsImbued(item, true)) + { + if (message) + m.SendMessage("Imbued items may not be sold here."); + + return false; } - break; - } - } - - bool newVendorSystemActivated = BaseHouse.NewVendorSystem && !newVendorSystem; - - if (version < 1 || newVendorSystemActivated) - { - if (version < 1) - { - m_ShopName = "Shop Not Yet Named"; - Timer.DelayCall(UpgradeFromVersion0, newVendorSystemActivated); - } - else - { - Timer.DelayCall(FixDresswear); - } - - NextPayTime = DateTime.UtcNow + PayTimer.GetInterval(); - - if (newVendorSystemActivated) - { - HoldGold += BankAccount; - BankAccount = 0; - } - } - - if (version < 2 && RawStr == 75 && RawDex == 75 && RawInt == 75) - InitStats(100, 100, 25); - - TimeSpan delay = NextPayTime - DateTime.UtcNow; - - m_PayTimer = new PayTimer(this, delay > TimeSpan.Zero ? delay : TimeSpan.Zero); - m_PayTimer.Start(); - - Blessed = false; - - if (Core.AOS && NameHue == 0x35) - NameHue = -1; - } - - private void UpgradeFromVersion0(bool newVendorSystem) - { - List toRemove = new List(); - - foreach (VendorItem vi in m_SellItems.Values) - if (!CanBeVendorItem(vi.Item)) - toRemove.Add(vi.Item); - else - vi.Description = Utility.FixHtml(vi.Description); - - foreach (Item item in toRemove) - RemoveVendorItem(item); - - House = BaseHouse.FindHouseAt(this); - - if (newVendorSystem) - ActivateNewVendorSystem(); - } - - private void ActivateNewVendorSystem() - { - FixDresswear(); - - if (House?.IsOwner(Owner) == false) - Destroy(false); - } - - public void InitBody() - { - Hue = Race.Human.RandomSkinHue(); - SpeechHue = 0x3B2; - - if (!Core.AOS) - NameHue = 0x35; - - if (Female = Utility.RandomBool()) - { - Body = 0x191; - Name = NameList.RandomName("female"); - } - else - { - Body = 0x190; - Name = NameList.RandomName("male"); - } - } - - public virtual void InitOutfit() - { - Item item = new FancyShirt(Utility.RandomNeutralHue()); - item.Layer = Layer.InnerTorso; - AddItem(item); - AddItem(new LongPants(Utility.RandomNeutralHue())); - AddItem(new BodySash(Utility.RandomNeutralHue())); - AddItem(new Boots(Utility.RandomNeutralHue())); - AddItem(new Cloak(Utility.RandomNeutralHue())); - - Utility.AssignRandomHair(this); - - Container pack = new VendorBackpack(); - pack.Movable = false; - AddItem(pack); - } - - public virtual bool IsOwner(Mobile m) - { - if (m.AccessLevel >= AccessLevel.GameMaster) - return true; - - if (BaseHouse.NewVendorSystem && House != null) return House.IsOwner(m); - - return m == Owner; - } - - protected List GetItems() - { - List list = new List(); - - foreach (Item item in Items) - if (item.Movable && item != Backpack && item.Layer != Layer.Hair && item.Layer != Layer.FacialHair) - list.Add(item); - - if (Backpack != null) - list.AddRange(Backpack.Items); - - return list; - } - - public virtual void Destroy(bool toBackpack) - { - Return(); - - if (!BaseHouse.NewVendorSystem) - FixDresswear(); - - /* Possible cases regarding item return: - * - * 1. No item must be returned - * -> do nothing. - * 2. ( toBackpack is false OR the vendor is in the internal map ) AND the vendor is associated with a AOS house - * -> put the items into the moving crate or a vendor inventory, - * depending on whether the vendor owner is also the house owner. - * 3. ( toBackpack is true OR the vendor isn't associated with any AOS house ) AND the vendor isn't in the internal map - * -> put the items into a backpack. - * 4. The vendor isn't associated with any house AND it's in the internal map - * -> do nothing (we can't do anything). - */ - - List list = GetItems(); - - if (list.Count > 0 || HoldGold > 0) // No case 1 - { - if ((!toBackpack || Map == Map.Internal) && House?.IsAosRules == true) // Case 2 - { - if (House.IsOwner(Owner)) // Move to moving crate - { - House.MovingCrate ??= new MovingCrate(House); - - if (HoldGold > 0) - Banker.Deposit(House.MovingCrate, HoldGold); - - foreach (Item item in list) House.MovingCrate.DropItem(item); - } - else // Move to vendor inventory - { - VendorInventory inventory = new VendorInventory(House, Owner, Name, ShopName); - inventory.Gold = HoldGold; - - foreach (Item item in list) inventory.AddItem(item); - - House.VendorInventories.Add(inventory); - } - } - else if ((toBackpack || House?.IsAosRules != true) && Map != Map.Internal) // Case 3 - Move to backpack - { - Container backpack = new Backpack(); - - if (HoldGold > 0) - Banker.Deposit(backpack, HoldGold); - - foreach (Item item in list) backpack.DropItem(item); - - backpack.MoveToWorld(Location, Map); - } - } - - Delete(); - } - - private void FixDresswear() - { - for (int i = 0; i < Items.Count; ++i) - { - Item item = Items[i]; - - if (item is BaseHat) - { - item.Layer = Layer.Helm; - } - else if (item is BaseMiddleTorso) - { - item.Layer = Layer.MiddleTorso; - } - else if (item is BaseOuterLegs) - { - item.Layer = Layer.OuterLegs; - } - else if (item is BaseOuterTorso) - { - item.Layer = Layer.OuterTorso; - } - else if (item is BasePants) - { - item.Layer = Layer.Pants; - } - else if (item is BaseShirt) - { - item.Layer = Layer.Shirt; - } - else if (item is BaseWaist) - { - item.Layer = Layer.Waist; - } - else if (item is BaseShoes) - { - if (item is Sandals) - item.Hue = 0; - - item.Layer = Layer.Shoes; - } - } - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_PayTimer.Stop(); - - House = null; - - Placeholder?.Delete(); - } - - public override bool IsSnoop(Mobile from) => false; - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (BaseHouse.NewVendorSystem) list.Add(1062449, ShopName); // Shop Name: ~1_NAME~ - } - - public VendorItem GetVendorItem(Item item) - { - m_SellItems.TryGetValue(item, out VendorItem v); - return v; - } - - private VendorItem SetVendorItem(Item item, int price, string description) => SetVendorItem(item, price, description, DateTime.UtcNow); - - private VendorItem SetVendorItem(Item item, int price, string description, DateTime created) - { - RemoveVendorItem(item); - - VendorItem vi = new VendorItem(item, price, description, created); - m_SellItems[item] = vi; - - item.InvalidateProperties(); - - return vi; - } - - private void RemoveVendorItem(Item item) - { - VendorItem vi = GetVendorItem(item); - - if (vi != null) - { - vi.Invalidate(); - m_SellItems.Remove(item); - - foreach (Item subItem in item.Items) RemoveVendorItem(subItem); - - item.InvalidateProperties(); - } - } - - private bool CanBeVendorItem(Item item) - { - Item parent = item.Parent as Item; - - if (parent == Backpack) - return true; - - if (parent is Container) - { - VendorItem parentVI = GetVendorItem(parent); - - if (parentVI != null) - return !parentVI.IsForSale; - } - - return false; - } - - public override void OnSubItemAdded(Item item) - { - base.OnSubItemAdded(item); - - if (GetVendorItem(item) == null && CanBeVendorItem(item)) SetVendorItem(item, 999, ""); - } - - public override void OnSubItemRemoved(Item item) - { - base.OnSubItemRemoved(item); - - if (item.GetBounce() == null) - RemoveVendorItem(item); - } - - public override void OnSubItemBounceCleared(Item item) - { - base.OnSubItemBounceCleared(item); - - if (!CanBeVendorItem(item)) - RemoveVendorItem(item); - } - - public override void OnItemRemoved(Item item) - { - base.OnItemRemoved(item); - - if (item == Backpack) - foreach (Item subItem in item.Items) - RemoveVendorItem(subItem); - } - - public override bool OnDragDrop(Mobile from, Item item) - { - if (!IsOwner(from)) - { - SayTo(from, 503209); // I can only take item from the shop owner. - return false; - } - - if (item is Gold) - { - if (BaseHouse.NewVendorSystem) - { - if (HoldGold < 1000000) - { - SayTo(from, 503210); // I'll take that to fund my services. - - HoldGold += item.Amount; - item.Delete(); + if (!BaseHouse.NewVendorSystem && Parent is PlayerVendor vendor) + { + var house = vendor.House; + + if (house?.IsAosRules == true && !house.CheckAosStorage(1 + item.TotalItems + plusItems)) + { + if (message) + m.SendLocalizedMessage(1061839); // This action would exceed the secure storage limit of the house. + + return false; + } + } return true; - } - - from.SendLocalizedMessage( - 1062493); // Your vendor has sufficient funds for operation and cannot accept this gold. - - return false; } - if (BankAccount < 1000000) + public override bool IsAccessibleTo(Mobile m) => true; + + public override bool CheckItemUse(Mobile from, Item item) { - SayTo(from, 503210); // I'll take that to fund my services. + if (!base.CheckItemUse(from, item)) + return false; - BankAccount += item.Amount; - item.Delete(); + if (item is Container || item is BulkOrderBook) + return true; - return true; + from.SendLocalizedMessage(500447); // That is not accessible. + return false; } - from.SendLocalizedMessage( - 1062493); // Your vendor has sufficient funds for operation and cannot accept this gold. + public override bool CheckTarget(Mobile from, Target targ, object targeted) => + base.CheckTarget(from, targ, targeted) && + (from.AccessLevel >= AccessLevel.GameMaster || + targ.GetType().IsDefined(typeof(PlayerVendorTargetAttribute), false)); - return false; - } - - bool newItem = GetVendorItem(item) == null; - - if (Backpack?.TryDropItem(from, item, false) == true) - { - if (newItem) - OnItemGiven(from, item); - - return true; - } - - SayTo(from, 503211); // I can't carry any more. - return false; - } - - public override bool CheckNonlocalDrop(Mobile from, Item item, Item target) - { - if (IsOwner(from)) - { - if (GetVendorItem(item) == null) - Timer.DelayCall(OnItemGiven, from, item); - - return true; - } - - SayTo(from, 503209); // I can only take item from the shop owner. - return false; - } - - private void OnItemGiven(Mobile from, Item item) - { - VendorItem vi = GetVendorItem(item); - - if (vi == null) - return; - - string name = item.Name.IsNullOrDefault($"#{item.LabelNumber}"); - - from.SendLocalizedMessage(1043303, name); // Type in a price and description for ~1_ITEM~ (ESC=not for sale) - from.Prompt = new VendorPricePrompt(this, vi); - } - - public override bool AllowEquipFrom(Mobile from) => - BaseHouse.NewVendorSystem && IsOwner(from) || base.AllowEquipFrom(from); - - public override bool CheckNonlocalLift(Mobile from, Item item) - { - if (item.IsChildOf(Backpack)) - { - if (IsOwner(from)) return true; - - SayTo(from, 503223); // If you'd like to purchase an item, just ask. - return false; - } - - if (BaseHouse.NewVendorSystem && IsOwner(from)) return true; - - return base.CheckNonlocalLift(from, item); - } - - public bool CanInteractWith(Mobile from, bool ownerOnly) - { - if (!from.CanSee(this) || !Utility.InUpdateRange(from, this) || !from.CheckAlive()) - return false; - - if (ownerOnly) - return IsOwner(from); - - if (House?.IsBanned(from) == true && !IsOwner(from)) - { - from.SendLocalizedMessage( - 1062674); // You can't shop from this home as you have been banned from this establishment. - return false; - } - - return true; - } - - public override void OnDoubleClick(Mobile from) - { - if (IsOwner(from)) - SendOwnerGump(from); - else if (CanInteractWith(from, false)) OpenBackpack(from); - } - - public override void DisplayPaperdollTo(Mobile m) - { - if (BaseHouse.NewVendorSystem) - base.DisplayPaperdollTo(m); - else if (CanInteractWith(m, false)) OpenBackpack(m); - } - - public void SendOwnerGump(Mobile to) - { - if (BaseHouse.NewVendorSystem) - { - to.CloseGump(); - to.CloseGump(); - - to.SendGump(new NewPlayerVendorOwnerGump(this)); - } - else - { - to.CloseGump(); - to.CloseGump(); - - to.SendGump(new PlayerVendorOwnerGump(this)); - } - } - - public void OpenBackpack(Mobile from) - { - if (Backpack != null) - { - SayTo(from, IsOwner(from) ? 1010642 : 503208); // Take a look at my/your goods. - - Backpack.DisplayTo(from); - } - } - - public static void TryToBuy(Item item, Mobile from) - { - if (!(item.RootParent is PlayerVendor vendor) || !vendor.CanInteractWith(from, false)) - return; - - if (vendor.IsOwner(from)) - { - vendor.SayTo(from, 503212); // You own this shop, just take what you want. - return; - } - - VendorItem vi = vendor.GetVendorItem(item); - - if (vi == null) - { - vendor.SayTo(from, 503216); // You can't buy that. - } - else if (!vi.IsForSale) - { - vendor.SayTo(from, 503202); // This item is not for sale. - } - else if (vi.Created + TimeSpan.FromMinutes(1.0) > DateTime.UtcNow) - { - from.SendMessage("You cannot buy this item right now. Please wait one minute and try again."); - } - else - { - from.CloseGump(); - from.SendGump(new PlayerVendorBuyGump(vendor, vi)); - } - } - - public void CollectGold(Mobile to) - { - if (HoldGold > 0) - { - SayTo(to, "How much of the {0} that I'm holding would you like?", HoldGold.ToString()); - to.SendMessage("Enter the amount of gold you wish to withdraw (ESC = CANCEL):"); - - to.Prompt = new CollectGoldPrompt(this); - } - else - { - SayTo(to, 503215); // I am holding no gold for you. - } - } - - public int GiveGold(Mobile to, int amount) - { - if (amount <= 0) - return 0; - - if (amount > HoldGold) - { - SayTo(to, "I'm sorry, but I'm only holding {0} gold for you.", HoldGold.ToString()); - return 0; - } - - int amountGiven = Banker.DepositUpTo(to, amount); - HoldGold -= amountGiven; - - if (amountGiven > 0) - to.SendLocalizedMessage(1060397, - amountGiven.ToString()); // ~1_AMOUNT~ gold has been deposited into your bank box. - - if (amountGiven == 0) - SayTo(to, 1070755); // Your bank box cannot hold the gold you are requesting. I will keep the gold until you can take it. - else if (amount > amountGiven) - SayTo(to, 1070756); // I can only give you part of the gold now, as your bank box is too full to hold the full amount. - else if (HoldGold > 0) - SayTo(to, 1042639); // Your gold has been transferred. - else - SayTo(to, 503234); // All the gold I have been carrying for you has been deposited into your bank account. - - return amountGiven; - } - - public void Dismiss(Mobile from) - { - Container pack = Backpack; - - if (pack?.Items.Count > 0) - { - SayTo(from, 1038325); // You cannot dismiss me while I am holding your goods. - return; - } - - if (HoldGold > 0) - { - GiveGold(from, HoldGold); - - if (HoldGold > 0) - return; - } - - Destroy(true); - } - - public void Rename(Mobile from) - { - from.SendLocalizedMessage(1062494); // Enter a new name for your vendor (20 characters max): - - from.Prompt = new VendorNamePrompt(this); - } - - public void RenameShop(Mobile from) - { - from.SendLocalizedMessage(1062433); // Enter a new name for your shop (20 chars max): - - from.Prompt = new ShopNamePrompt(this); - } - - public bool CheckTeleport(Mobile to) - { - if (Deleted || !IsOwner(to) || House == null || Map == Map.Internal) - return false; - - if (House.IsInside(to) || to.Map != House.Map || !House.InRange(to, 5)) - return false; - - if (Placeholder == null) - { - Placeholder = new PlayerVendorPlaceholder(this); - Placeholder.MoveToWorld(Location, Map); - - MoveToWorld(to.Location, to.Map); - - to.SendLocalizedMessage( - 1062431); // This vendor has been moved out of the house to your current location temporarily. The vendor will return home automatically after two minutes have passed once you are done managing its inventory or customizing it. - } - else - { - Placeholder.RestartTimer(); - - to.SendLocalizedMessage( - 1062430); // This vendor is currently temporarily in a location outside its house. The vendor will return home automatically after two minutes have passed once you are done managing its inventory or customizing it. - } - - return true; - } - - public void Return() - { - Placeholder?.Delete(); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - if (from.Alive && Placeholder != null && IsOwner(from)) list.Add(new ReturnVendorEntry(this)); - - base.GetContextMenuEntries(from, list); - } - - public override bool HandlesOnSpeech(Mobile from) => from.Alive && from.GetDistanceToSqrt(this) <= 3; - - public bool WasNamed(string speech) => Name != null && Insensitive.StartsWith(speech, Name); - - public override void OnSpeech(SpeechEventArgs e) - { - Mobile from = e.Mobile; - - if (e.Handled || !from.Alive || from.GetDistanceToSqrt(this) > 3) - return; - - if (e.HasKeyword(0x3C) || (e.HasKeyword(0x171) && WasNamed(e.Speech))) // vendor buy, *buy* - { - if (IsOwner(from)) + public override void GetChildContextMenuEntries(Mobile from, List list, Item item) { - SayTo(from, 503212); // You own this shop, just take what you want. - } - else if (House?.IsBanned(from) != true) - { - from.SendLocalizedMessage(503213); // Select the item you wish to buy. - from.Target = new PVBuyTarget(); + base.GetChildContextMenuEntries(from, list, item); - e.Handled = true; - } - } - else if (e.HasKeyword(0x3D) || (e.HasKeyword(0x172) && WasNamed(e.Speech))) // vendor browse, *browse - { - if (House?.IsBanned(from) == true && !IsOwner(from)) - { - SayTo(from, 1062674); // You can't shop from this home as you have been banned from this establishment. - } - else - { - if (WasNamed(e.Speech)) - { - OpenBackpack(from); - } - else - { - IPooledEnumerable mobiles = e.Mobile.GetMobilesInRange(2); + if (!(RootParent is PlayerVendor pv) || pv.IsOwner(from)) + return; - foreach (PlayerVendor m in mobiles) - if (m.CanSee(e.Mobile) && m.InLOS(e.Mobile)) - m.OpenBackpack(from); + var vi = pv.GetVendorItem(item); - mobiles.Free(); - } - - e.Handled = true; - } - } - else if (e.HasKeyword(0x3E) || (e.HasKeyword(0x173) && WasNamed(e.Speech))) // vendor collect, *collect - { - if (IsOwner(from)) - { - CollectGold(from); - - e.Handled = true; - } - } - else if (e.HasKeyword(0x3F) || (e.HasKeyword(0x174) && WasNamed(e.Speech))) // vendor status, *status - { - if (IsOwner(from)) - { - SendOwnerGump(from); - - e.Handled = true; - } - else - { - SayTo(from, 503226); // What do you care? You don't run this shop. - } - } - else if (e.HasKeyword(0x40) || (e.HasKeyword(0x175) && WasNamed(e.Speech))) // vendor dismiss, *dismiss - { - if (IsOwner(from)) - { - Dismiss(from); - - e.Handled = true; - } - } - else if (e.HasKeyword(0x41) || (e.HasKeyword(0x176) && WasNamed(e.Speech))) // vendor cycle, *cycle - { - if (IsOwner(from)) - { - Direction = GetDirectionTo(from); - - e.Handled = true; - } - } - } - - public override bool CanBeDamaged() => false; - - private class ReturnVendorEntry : ContextMenuEntry - { - private readonly PlayerVendor m_Vendor; - - public ReturnVendorEntry(PlayerVendor vendor) : base(6214) => m_Vendor = vendor; - - public override void OnClick() - { - Mobile from = Owner.From; - - if (!m_Vendor.Deleted && m_Vendor.IsOwner(from) && from.CheckAlive()) - m_Vendor.Return(); - } - } - - private class PayTimer : Timer - { - private readonly PlayerVendor m_Vendor; - - public PayTimer(PlayerVendor vendor, TimeSpan delay) : base(delay, GetInterval()) - { - m_Vendor = vendor; - - Priority = TimerPriority.OneMinute; - } - - public static TimeSpan GetInterval() - { - if (BaseHouse.NewVendorSystem) - return TimeSpan.FromDays(1.0); - return TimeSpan.FromMinutes(Clock.MinutesPerUODay); - } - - protected override void OnTick() - { - m_Vendor.NextPayTime = DateTime.UtcNow + Interval; - - int pay; - int totalGold; - if (BaseHouse.NewVendorSystem) - { - pay = m_Vendor.ChargePerRealWorldDay; - totalGold = m_Vendor.HoldGold; - } - else - { - pay = m_Vendor.ChargePerDay; - totalGold = m_Vendor.BankAccount + m_Vendor.HoldGold; + if (vi != null) + list.Add(new BuyEntry(item)); } - if (pay > totalGold) + public override void GetChildNameProperties(ObjectPropertyList list, Item item) { - m_Vendor.Destroy(!BaseHouse.NewVendorSystem); + base.GetChildNameProperties(list, item); + + var pv = RootParent as PlayerVendor; + + var vi = pv?.GetVendorItem(item); + + if (vi == null) + return; + + if (!vi.IsForSale) + list.Add(1043307); // Price: Not for sale. + else if (vi.IsForFree) + list.Add(1043306); // Price: FREE! + else + list.Add(1043304, vi.FormattedPrice); // Price: ~1_COST~ } - else + + public override void GetChildProperties(ObjectPropertyList list, Item item) { - if (!BaseHouse.NewVendorSystem) - { - if (m_Vendor.BankAccount >= pay) + base.GetChildProperties(list, item); + + var pv = RootParent as PlayerVendor; + + var vi = pv?.GetVendorItem(item); + + if (vi?.Description != null && vi.Description.Length > 0) + list.Add(1043305, vi.Description); //
Seller's Description:
"~1_DESC~" + } + + public override void OnSingleClickContained(Mobile from, Item item) + { + if (RootParent is PlayerVendor vendor) { - m_Vendor.BankAccount -= pay; - pay = 0; + var vi = vendor.GetVendorItem(item); + + if (vi != null) + { + if (!vi.IsForSale) + item.LabelTo(from, 1043307); // Price: Not for sale. + else if (vi.IsForFree) + item.LabelTo(from, 1043306); // Price: FREE! + else + item.LabelTo(from, 1043304, vi.FormattedPrice); // Price: ~1_COST~ + + if (!string.IsNullOrEmpty(vi.Description)) item.LabelTo(from, "Description: {0}", vi.Description); + } + } + + base.OnSingleClickContained(from, item); + } + + 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(); + } + + private class BuyEntry : ContextMenuEntry + { + private readonly Item m_Item; + + public BuyEntry(Item item) : base(6103) => m_Item = item; + + public override bool NonLocalUse => true; + + public override void OnClick() + { + if (m_Item.Deleted) + return; + + PlayerVendor.TryToBuy(m_Item, Owner.From); + } + } + } + + public class PlayerVendor : Mobile + { + private BaseHouse m_House; + + private Timer m_PayTimer; + private Dictionary m_SellItems; + + private string m_ShopName; + + public PlayerVendor(Mobile owner, BaseHouse house) + { + Owner = owner; + House = house; + + if (BaseHouse.NewVendorSystem) + { + BankAccount = 0; + HoldGold = 4; } else { - pay -= m_Vendor.BankAccount; - m_Vendor.BankAccount = 0; + BankAccount = 1000; + HoldGold = 0; } - } - m_Vendor.HoldGold -= pay; - } - } - } + ShopName = "Shop Not Yet Named"; - [PlayerVendorTarget] - private class PVBuyTarget : Target - { - public PVBuyTarget() : base(3, false, TargetFlags.None) => AllowNonlocal = true; + m_SellItems = new Dictionary(); - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is Item item) - TryToBuy(item, from); - } - } + CantWalk = true; - private class VendorPricePrompt : Prompt - { - private readonly PlayerVendor m_Vendor; - private readonly VendorItem m_VI; + if (!Core.AOS) + NameHue = 0x35; - public VendorPricePrompt(PlayerVendor vendor, VendorItem vi) - { - m_Vendor = vendor; - m_VI = vi; - } + InitStats(100, 100, 25); + InitBody(); + InitOutfit(); - public override void OnResponse(Mobile from, string text) - { - if (!m_VI.Valid || !m_Vendor.CanInteractWith(from, true)) - return; + var delay = PayTimer.GetInterval(); - string firstWord; + m_PayTimer = new PayTimer(this, delay); + m_PayTimer.Start(); - int sep = text.IndexOfAny(new[] { ' ', ',' }); - if (sep >= 0) - firstWord = text.Substring(0, sep); - else - firstWord = text; - - string description; - - if (int.TryParse(firstWord, out int price)) - { - if (sep >= 0) - description = text.Substring(sep + 1).Trim(); - else - description = ""; - } - else - { - price = -1; - description = text.Trim(); + NextPayTime = DateTime.UtcNow + delay; } - SetInfo(from, price, Utility.FixHtml(description)); - } - - public override void OnCancel(Mobile from) - { - if (!m_VI.Valid || !m_Vendor.CanInteractWith(from, true)) - return; - - SetInfo(from, -1, ""); - } - - private void SetInfo(Mobile from, int price, string description) - { - Item item = m_VI.Item; - - bool setPrice = false; - - if (price < 0) // Not for sale + public PlayerVendor(Serial serial) : base(serial) { - price = -1; + } - if (item is Container) - { - if (item is LockableContainer container && container.Locked) - m_Vendor.SayTo(from, 1043298); // Locked items may not be made not-for-sale. - else if (item.Items.Count > 0) - m_Vendor.SayTo(from, 1043299); // To be not for sale, all items in a container must be for sale. + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Owner { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int BankAccount { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int HoldGold { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public string ShopName + { + get => m_ShopName; + set + { + m_ShopName = value ?? ""; + + InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime NextPayTime { get; private set; } + + public PlayerVendorPlaceholder Placeholder { get; set; } + + public BaseHouse House + { + get => m_House; + set + { + m_House?.PlayerVendors.Remove(this); + + value?.PlayerVendors.Add(this); + + m_House = value; + } + } + + public int ChargePerDay + { + get + { + if (BaseHouse.NewVendorSystem) return ChargePerRealWorldDay / 12; + + var total = m_SellItems.Values.Aggregate( + 0, + (current, vi) => + current + vi.Price + ) - 500; + + return (int)(20 + Math.Max(total, 0) / 500); + } + } + + public int ChargePerRealWorldDay + { + get + { + if (BaseHouse.NewVendorSystem) + { + var total = m_SellItems.Values.Aggregate(0, (current, vi) => current + vi.Price); + + return (int)(60 + total / 500 * 3); + } + + return ChargePerDay * 12; + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(2); // version + + writer.Write(BaseHouse.NewVendorSystem); + writer.Write(m_ShopName); + writer.WriteDeltaTime(NextPayTime); + writer.Write(House); + + writer.Write(Owner); + writer.Write(BankAccount); + writer.Write(HoldGold); + + writer.Write(m_SellItems.Count); + foreach (var vi in m_SellItems.Values) + { + writer.Write(vi.Item); + writer.Write(vi.Price); + writer.Write(vi.Description); + + writer.Write(vi.Created); + } + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + var newVendorSystem = false; + + switch (version) + { + case 2: + case 1: + { + newVendorSystem = reader.ReadBool(); + m_ShopName = reader.ReadString(); + NextPayTime = reader.ReadDeltaTime(); + House = (BaseHouse)reader.ReadItem(); + + goto case 0; + } + case 0: + { + Owner = reader.ReadMobile(); + BankAccount = reader.ReadInt(); + HoldGold = reader.ReadInt(); + + var count = reader.ReadInt(); + + m_SellItems = new Dictionary(count); + + for (var i = 0; i < count; i++) + { + var item = reader.ReadItem(); + + var price = reader.ReadInt(); + if (price > 100000000) + price = 100000000; + + var description = reader.ReadString(); + + var created = version < 1 ? DateTime.UtcNow : reader.ReadDateTime(); + + if (item != null) + SetVendorItem(item, version < 1 && price <= 0 ? -1 : price, description, created); + } + + break; + } + } + + var newVendorSystemActivated = BaseHouse.NewVendorSystem && !newVendorSystem; + + if (version < 1 || newVendorSystemActivated) + { + if (version < 1) + { + m_ShopName = "Shop Not Yet Named"; + Timer.DelayCall(UpgradeFromVersion0, newVendorSystemActivated); + } + else + { + Timer.DelayCall(FixDresswear); + } + + NextPayTime = DateTime.UtcNow + PayTimer.GetInterval(); + + if (newVendorSystemActivated) + { + HoldGold += BankAccount; + BankAccount = 0; + } + } + + if (version < 2 && RawStr == 75 && RawDex == 75 && RawInt == 75) + InitStats(100, 100, 25); + + var delay = NextPayTime - DateTime.UtcNow; + + m_PayTimer = new PayTimer(this, delay > TimeSpan.Zero ? delay : TimeSpan.Zero); + m_PayTimer.Start(); + + Blessed = false; + + if (Core.AOS && NameHue == 0x35) + NameHue = -1; + } + + private void UpgradeFromVersion0(bool newVendorSystem) + { + var toRemove = new List(); + + foreach (var vi in m_SellItems.Values) + if (!CanBeVendorItem(vi.Item)) + toRemove.Add(vi.Item); + else + vi.Description = Utility.FixHtml(vi.Description); + + foreach (var item in toRemove) + RemoveVendorItem(item); + + House = BaseHouse.FindHouseAt(this); + + if (newVendorSystem) + ActivateNewVendorSystem(); + } + + private void ActivateNewVendorSystem() + { + FixDresswear(); + + if (House?.IsOwner(Owner) == false) + Destroy(false); + } + + public void InitBody() + { + Hue = Race.Human.RandomSkinHue(); + SpeechHue = 0x3B2; + + if (!Core.AOS) + NameHue = 0x35; + + if (Female = Utility.RandomBool()) + { + Body = 0x191; + Name = NameList.RandomName("female"); + } else - setPrice = true; - } - else if (item is BaseBook || item is BulkOrderBook) - { - setPrice = true; - } - else - { - m_Vendor.SayTo(from, - 1043301); // Only the following may be made not-for-sale: books, containers, keyrings, and items in for-sale containers. - } + { + Body = 0x190; + Name = NameList.RandomName("male"); + } } - else + + public virtual void InitOutfit() { - if (price > 100000000) - { - price = 100000000; - from.SendMessage("You cannot price items above 100,000,000 gold. The price has been adjusted."); - } + Item item = new FancyShirt(Utility.RandomNeutralHue()); + item.Layer = Layer.InnerTorso; + AddItem(item); + AddItem(new LongPants(Utility.RandomNeutralHue())); + AddItem(new BodySash(Utility.RandomNeutralHue())); + AddItem(new Boots(Utility.RandomNeutralHue())); + AddItem(new Cloak(Utility.RandomNeutralHue())); - setPrice = true; + Utility.AssignRandomHair(this); + + Container pack = new VendorBackpack(); + pack.Movable = false; + AddItem(pack); } - if (setPrice) - m_Vendor.SetVendorItem(item, price, description); - else - m_VI.Description = description; - } - } - - private class CollectGoldPrompt : Prompt - { - private readonly PlayerVendor m_Vendor; - - public CollectGoldPrompt(PlayerVendor vendor) => m_Vendor = vendor; - - public override void OnResponse(Mobile from, string text) - { - if (!m_Vendor.CanInteractWith(from, true)) - return; - - text = text.Trim(); - - if (!int.TryParse(text, out int amount)) - amount = 0; - - GiveGold(from, amount); - } - - public override void OnCancel(Mobile from) - { - if (!m_Vendor.CanInteractWith(from, true)) - return; - - GiveGold(from, 0); - } - - private void GiveGold(Mobile to, int amount) - { - if (amount <= 0) - m_Vendor.SayTo(to, "Very well. I will hold on to the money for now then."); - else - m_Vendor.GiveGold(to, amount); - } - } - - private class VendorNamePrompt : Prompt - { - private readonly PlayerVendor m_Vendor; - - public VendorNamePrompt(PlayerVendor vendor) => m_Vendor = vendor; - - public override void OnResponse(Mobile from, string text) - { - if (!m_Vendor.CanInteractWith(from, true)) - return; - - string name = text.Trim(); - - if (!NameVerification.Validate(name, 1, 20, true, true, true, 0, NameVerification.Empty)) + public virtual bool IsOwner(Mobile m) { - m_Vendor.SayTo(from, "That name is unacceptable."); - return; + if (m.AccessLevel >= AccessLevel.GameMaster) + return true; + + if (BaseHouse.NewVendorSystem && House != null) return House.IsOwner(m); + + return m == Owner; } - m_Vendor.Name = Utility.FixHtml(name); - - from.SendLocalizedMessage(1062496); // Your vendor has been renamed. - - from.SendGump(new NewPlayerVendorOwnerGump(m_Vendor)); - } - } - - private class ShopNamePrompt : Prompt - { - private readonly PlayerVendor m_Vendor; - - public ShopNamePrompt(PlayerVendor vendor) => m_Vendor = vendor; - - public override void OnResponse(Mobile from, string text) - { - if (!m_Vendor.CanInteractWith(from, true)) - return; - - string name = text.Trim(); - - if (!NameVerification.Validate(name, 1, 20, true, true, true, 0, NameVerification.Empty)) + protected List GetItems() { - m_Vendor.SayTo(from, "That name is unacceptable."); - return; + var list = new List(); + + foreach (var item in Items) + if (item.Movable && item != Backpack && item.Layer != Layer.Hair && item.Layer != Layer.FacialHair) + list.Add(item); + + if (Backpack != null) + list.AddRange(Backpack.Items); + + return list; } - m_Vendor.ShopName = Utility.FixHtml(name); + public virtual void Destroy(bool toBackpack) + { + Return(); - from.SendGump(new NewPlayerVendorOwnerGump(m_Vendor)); - } + if (!BaseHouse.NewVendorSystem) + FixDresswear(); + + /* Possible cases regarding item return: + * + * 1. No item must be returned + * -> do nothing. + * 2. ( toBackpack is false OR the vendor is in the internal map ) AND the vendor is associated with a AOS house + * -> put the items into the moving crate or a vendor inventory, + * depending on whether the vendor owner is also the house owner. + * 3. ( toBackpack is true OR the vendor isn't associated with any AOS house ) AND the vendor isn't in the internal map + * -> put the items into a backpack. + * 4. The vendor isn't associated with any house AND it's in the internal map + * -> do nothing (we can't do anything). + */ + + var list = GetItems(); + + if (list.Count > 0 || HoldGold > 0) // No case 1 + { + if ((!toBackpack || Map == Map.Internal) && House?.IsAosRules == true) // Case 2 + { + if (House.IsOwner(Owner)) // Move to moving crate + { + House.MovingCrate ??= new MovingCrate(House); + + if (HoldGold > 0) + Banker.Deposit(House.MovingCrate, HoldGold); + + foreach (var item in list) House.MovingCrate.DropItem(item); + } + else // Move to vendor inventory + { + var inventory = new VendorInventory(House, Owner, Name, ShopName); + inventory.Gold = HoldGold; + + foreach (var item in list) inventory.AddItem(item); + + House.VendorInventories.Add(inventory); + } + } + else if ((toBackpack || House?.IsAosRules != true) && Map != Map.Internal) // Case 3 - Move to backpack + { + Container backpack = new Backpack(); + + if (HoldGold > 0) + Banker.Deposit(backpack, HoldGold); + + foreach (var item in list) backpack.DropItem(item); + + backpack.MoveToWorld(Location, Map); + } + } + + Delete(); + } + + private void FixDresswear() + { + for (var i = 0; i < Items.Count; ++i) + { + var item = Items[i]; + + if (item is BaseHat) + { + item.Layer = Layer.Helm; + } + else if (item is BaseMiddleTorso) + { + item.Layer = Layer.MiddleTorso; + } + else if (item is BaseOuterLegs) + { + item.Layer = Layer.OuterLegs; + } + else if (item is BaseOuterTorso) + { + item.Layer = Layer.OuterTorso; + } + else if (item is BasePants) + { + item.Layer = Layer.Pants; + } + else if (item is BaseShirt) + { + item.Layer = Layer.Shirt; + } + else if (item is BaseWaist) + { + item.Layer = Layer.Waist; + } + else if (item is BaseShoes) + { + if (item is Sandals) + item.Hue = 0; + + item.Layer = Layer.Shoes; + } + } + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_PayTimer.Stop(); + + House = null; + + Placeholder?.Delete(); + } + + public override bool IsSnoop(Mobile from) => false; + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (BaseHouse.NewVendorSystem) list.Add(1062449, ShopName); // Shop Name: ~1_NAME~ + } + + public VendorItem GetVendorItem(Item item) + { + m_SellItems.TryGetValue(item, out var v); + return v; + } + + private VendorItem SetVendorItem(Item item, int price, string description) => + SetVendorItem(item, price, description, DateTime.UtcNow); + + private VendorItem SetVendorItem(Item item, int price, string description, DateTime created) + { + RemoveVendorItem(item); + + var vi = new VendorItem(item, price, description, created); + m_SellItems[item] = vi; + + item.InvalidateProperties(); + + return vi; + } + + private void RemoveVendorItem(Item item) + { + var vi = GetVendorItem(item); + + if (vi != null) + { + vi.Invalidate(); + m_SellItems.Remove(item); + + foreach (var subItem in item.Items) RemoveVendorItem(subItem); + + item.InvalidateProperties(); + } + } + + private bool CanBeVendorItem(Item item) + { + var parent = item.Parent as Item; + + if (parent == Backpack) + return true; + + if (parent is Container) + { + var parentVI = GetVendorItem(parent); + + if (parentVI != null) + return !parentVI.IsForSale; + } + + return false; + } + + public override void OnSubItemAdded(Item item) + { + base.OnSubItemAdded(item); + + if (GetVendorItem(item) == null && CanBeVendorItem(item)) SetVendorItem(item, 999, ""); + } + + public override void OnSubItemRemoved(Item item) + { + base.OnSubItemRemoved(item); + + if (item.GetBounce() == null) + RemoveVendorItem(item); + } + + public override void OnSubItemBounceCleared(Item item) + { + base.OnSubItemBounceCleared(item); + + if (!CanBeVendorItem(item)) + RemoveVendorItem(item); + } + + public override void OnItemRemoved(Item item) + { + base.OnItemRemoved(item); + + if (item == Backpack) + foreach (var subItem in item.Items) + RemoveVendorItem(subItem); + } + + public override bool OnDragDrop(Mobile from, Item item) + { + if (!IsOwner(from)) + { + SayTo(from, 503209); // I can only take item from the shop owner. + return false; + } + + if (item is Gold) + { + if (BaseHouse.NewVendorSystem) + { + if (HoldGold < 1000000) + { + SayTo(from, 503210); // I'll take that to fund my services. + + HoldGold += item.Amount; + item.Delete(); + + return true; + } + + from.SendLocalizedMessage( + 1062493 + ); // Your vendor has sufficient funds for operation and cannot accept this gold. + + return false; + } + + if (BankAccount < 1000000) + { + SayTo(from, 503210); // I'll take that to fund my services. + + BankAccount += item.Amount; + item.Delete(); + + return true; + } + + from.SendLocalizedMessage( + 1062493 + ); // Your vendor has sufficient funds for operation and cannot accept this gold. + + return false; + } + + var newItem = GetVendorItem(item) == null; + + if (Backpack?.TryDropItem(from, item, false) == true) + { + if (newItem) + OnItemGiven(from, item); + + return true; + } + + SayTo(from, 503211); // I can't carry any more. + return false; + } + + public override bool CheckNonlocalDrop(Mobile from, Item item, Item target) + { + if (IsOwner(from)) + { + if (GetVendorItem(item) == null) + Timer.DelayCall(OnItemGiven, from, item); + + return true; + } + + SayTo(from, 503209); // I can only take item from the shop owner. + return false; + } + + private void OnItemGiven(Mobile from, Item item) + { + var vi = GetVendorItem(item); + + if (vi == null) + return; + + var name = item.Name.IsNullOrDefault($"#{item.LabelNumber}"); + + from.SendLocalizedMessage(1043303, name); // Type in a price and description for ~1_ITEM~ (ESC=not for sale) + from.Prompt = new VendorPricePrompt(this, vi); + } + + public override bool AllowEquipFrom(Mobile from) => + BaseHouse.NewVendorSystem && IsOwner(from) || base.AllowEquipFrom(from); + + public override bool CheckNonlocalLift(Mobile from, Item item) + { + if (item.IsChildOf(Backpack)) + { + if (IsOwner(from)) return true; + + SayTo(from, 503223); // If you'd like to purchase an item, just ask. + return false; + } + + if (BaseHouse.NewVendorSystem && IsOwner(from)) return true; + + return base.CheckNonlocalLift(from, item); + } + + public bool CanInteractWith(Mobile from, bool ownerOnly) + { + if (!from.CanSee(this) || !Utility.InUpdateRange(from, this) || !from.CheckAlive()) + return false; + + if (ownerOnly) + return IsOwner(from); + + if (House?.IsBanned(from) == true && !IsOwner(from)) + { + from.SendLocalizedMessage( + 1062674 + ); // You can't shop from this home as you have been banned from this establishment. + return false; + } + + return true; + } + + public override void OnDoubleClick(Mobile from) + { + if (IsOwner(from)) + SendOwnerGump(from); + else if (CanInteractWith(from, false)) OpenBackpack(from); + } + + public override void DisplayPaperdollTo(Mobile m) + { + if (BaseHouse.NewVendorSystem) + base.DisplayPaperdollTo(m); + else if (CanInteractWith(m, false)) OpenBackpack(m); + } + + public void SendOwnerGump(Mobile to) + { + if (BaseHouse.NewVendorSystem) + { + to.CloseGump(); + to.CloseGump(); + + to.SendGump(new NewPlayerVendorOwnerGump(this)); + } + else + { + to.CloseGump(); + to.CloseGump(); + + to.SendGump(new PlayerVendorOwnerGump(this)); + } + } + + public void OpenBackpack(Mobile from) + { + if (Backpack != null) + { + SayTo(from, IsOwner(from) ? 1010642 : 503208); // Take a look at my/your goods. + + Backpack.DisplayTo(from); + } + } + + public static void TryToBuy(Item item, Mobile from) + { + if (!(item.RootParent is PlayerVendor vendor) || !vendor.CanInteractWith(from, false)) + return; + + if (vendor.IsOwner(from)) + { + vendor.SayTo(from, 503212); // You own this shop, just take what you want. + return; + } + + var vi = vendor.GetVendorItem(item); + + if (vi == null) + { + vendor.SayTo(from, 503216); // You can't buy that. + } + else if (!vi.IsForSale) + { + vendor.SayTo(from, 503202); // This item is not for sale. + } + else if (vi.Created + TimeSpan.FromMinutes(1.0) > DateTime.UtcNow) + { + from.SendMessage("You cannot buy this item right now. Please wait one minute and try again."); + } + else + { + from.CloseGump(); + from.SendGump(new PlayerVendorBuyGump(vendor, vi)); + } + } + + public void CollectGold(Mobile to) + { + if (HoldGold > 0) + { + SayTo(to, "How much of the {0} that I'm holding would you like?", HoldGold.ToString()); + to.SendMessage("Enter the amount of gold you wish to withdraw (ESC = CANCEL):"); + + to.Prompt = new CollectGoldPrompt(this); + } + else + { + SayTo(to, 503215); // I am holding no gold for you. + } + } + + public int GiveGold(Mobile to, int amount) + { + if (amount <= 0) + return 0; + + if (amount > HoldGold) + { + SayTo(to, "I'm sorry, but I'm only holding {0} gold for you.", HoldGold.ToString()); + return 0; + } + + var amountGiven = Banker.DepositUpTo(to, amount); + HoldGold -= amountGiven; + + if (amountGiven > 0) + to.SendLocalizedMessage( + 1060397, + amountGiven.ToString() + ); // ~1_AMOUNT~ gold has been deposited into your bank box. + + if (amountGiven == 0) + SayTo( + to, + 1070755 + ); // Your bank box cannot hold the gold you are requesting. I will keep the gold until you can take it. + else if (amount > amountGiven) + SayTo( + to, + 1070756 + ); // I can only give you part of the gold now, as your bank box is too full to hold the full amount. + else if (HoldGold > 0) + SayTo(to, 1042639); // Your gold has been transferred. + else + SayTo(to, 503234); // All the gold I have been carrying for you has been deposited into your bank account. + + return amountGiven; + } + + public void Dismiss(Mobile from) + { + var pack = Backpack; + + if (pack?.Items.Count > 0) + { + SayTo(from, 1038325); // You cannot dismiss me while I am holding your goods. + return; + } + + if (HoldGold > 0) + { + GiveGold(from, HoldGold); + + if (HoldGold > 0) + return; + } + + Destroy(true); + } + + public void Rename(Mobile from) + { + from.SendLocalizedMessage(1062494); // Enter a new name for your vendor (20 characters max): + + from.Prompt = new VendorNamePrompt(this); + } + + public void RenameShop(Mobile from) + { + from.SendLocalizedMessage(1062433); // Enter a new name for your shop (20 chars max): + + from.Prompt = new ShopNamePrompt(this); + } + + public bool CheckTeleport(Mobile to) + { + if (Deleted || !IsOwner(to) || House == null || Map == Map.Internal) + return false; + + if (House.IsInside(to) || to.Map != House.Map || !House.InRange(to, 5)) + return false; + + if (Placeholder == null) + { + Placeholder = new PlayerVendorPlaceholder(this); + Placeholder.MoveToWorld(Location, Map); + + MoveToWorld(to.Location, to.Map); + + to.SendLocalizedMessage( + 1062431 + ); // This vendor has been moved out of the house to your current location temporarily. The vendor will return home automatically after two minutes have passed once you are done managing its inventory or customizing it. + } + else + { + Placeholder.RestartTimer(); + + to.SendLocalizedMessage( + 1062430 + ); // This vendor is currently temporarily in a location outside its house. The vendor will return home automatically after two minutes have passed once you are done managing its inventory or customizing it. + } + + return true; + } + + public void Return() + { + Placeholder?.Delete(); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + if (from.Alive && Placeholder != null && IsOwner(from)) list.Add(new ReturnVendorEntry(this)); + + base.GetContextMenuEntries(from, list); + } + + public override bool HandlesOnSpeech(Mobile from) => from.Alive && from.GetDistanceToSqrt(this) <= 3; + + public bool WasNamed(string speech) => Name != null && Insensitive.StartsWith(speech, Name); + + public override void OnSpeech(SpeechEventArgs e) + { + var from = e.Mobile; + + if (e.Handled || !from.Alive || from.GetDistanceToSqrt(this) > 3) + return; + + if (e.HasKeyword(0x3C) || e.HasKeyword(0x171) && WasNamed(e.Speech)) // vendor buy, *buy* + { + if (IsOwner(from)) + { + SayTo(from, 503212); // You own this shop, just take what you want. + } + else if (House?.IsBanned(from) != true) + { + from.SendLocalizedMessage(503213); // Select the item you wish to buy. + from.Target = new PVBuyTarget(); + + e.Handled = true; + } + } + else if (e.HasKeyword(0x3D) || e.HasKeyword(0x172) && WasNamed(e.Speech)) // vendor browse, *browse + { + if (House?.IsBanned(from) == true && !IsOwner(from)) + { + SayTo(from, 1062674); // You can't shop from this home as you have been banned from this establishment. + } + else + { + if (WasNamed(e.Speech)) + { + OpenBackpack(from); + } + else + { + var mobiles = e.Mobile.GetMobilesInRange(2); + + foreach (var m in mobiles) + if (m.CanSee(e.Mobile) && m.InLOS(e.Mobile)) + m.OpenBackpack(from); + + mobiles.Free(); + } + + e.Handled = true; + } + } + else if (e.HasKeyword(0x3E) || e.HasKeyword(0x173) && WasNamed(e.Speech)) // vendor collect, *collect + { + if (IsOwner(from)) + { + CollectGold(from); + + e.Handled = true; + } + } + else if (e.HasKeyword(0x3F) || e.HasKeyword(0x174) && WasNamed(e.Speech)) // vendor status, *status + { + if (IsOwner(from)) + { + SendOwnerGump(from); + + e.Handled = true; + } + else + { + SayTo(from, 503226); // What do you care? You don't run this shop. + } + } + else if (e.HasKeyword(0x40) || e.HasKeyword(0x175) && WasNamed(e.Speech)) // vendor dismiss, *dismiss + { + if (IsOwner(from)) + { + Dismiss(from); + + e.Handled = true; + } + } + else if (e.HasKeyword(0x41) || e.HasKeyword(0x176) && WasNamed(e.Speech)) // vendor cycle, *cycle + { + if (IsOwner(from)) + { + Direction = GetDirectionTo(from); + + e.Handled = true; + } + } + } + + public override bool CanBeDamaged() => false; + + private class ReturnVendorEntry : ContextMenuEntry + { + private readonly PlayerVendor m_Vendor; + + public ReturnVendorEntry(PlayerVendor vendor) : base(6214) => m_Vendor = vendor; + + public override void OnClick() + { + var from = Owner.From; + + if (!m_Vendor.Deleted && m_Vendor.IsOwner(from) && from.CheckAlive()) + m_Vendor.Return(); + } + } + + private class PayTimer : Timer + { + private readonly PlayerVendor m_Vendor; + + public PayTimer(PlayerVendor vendor, TimeSpan delay) : base(delay, GetInterval()) + { + m_Vendor = vendor; + + Priority = TimerPriority.OneMinute; + } + + public static TimeSpan GetInterval() + { + if (BaseHouse.NewVendorSystem) + return TimeSpan.FromDays(1.0); + return TimeSpan.FromMinutes(Clock.MinutesPerUODay); + } + + protected override void OnTick() + { + m_Vendor.NextPayTime = DateTime.UtcNow + Interval; + + int pay; + int totalGold; + if (BaseHouse.NewVendorSystem) + { + pay = m_Vendor.ChargePerRealWorldDay; + totalGold = m_Vendor.HoldGold; + } + else + { + pay = m_Vendor.ChargePerDay; + totalGold = m_Vendor.BankAccount + m_Vendor.HoldGold; + } + + if (pay > totalGold) + { + m_Vendor.Destroy(!BaseHouse.NewVendorSystem); + } + else + { + if (!BaseHouse.NewVendorSystem) + { + if (m_Vendor.BankAccount >= pay) + { + m_Vendor.BankAccount -= pay; + pay = 0; + } + else + { + pay -= m_Vendor.BankAccount; + m_Vendor.BankAccount = 0; + } + } + + m_Vendor.HoldGold -= pay; + } + } + } + + [PlayerVendorTarget] + private class PVBuyTarget : Target + { + public PVBuyTarget() : base(3, false, TargetFlags.None) => AllowNonlocal = true; + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted is Item item) + TryToBuy(item, from); + } + } + + private class VendorPricePrompt : Prompt + { + private readonly PlayerVendor m_Vendor; + private readonly VendorItem m_VI; + + public VendorPricePrompt(PlayerVendor vendor, VendorItem vi) + { + m_Vendor = vendor; + m_VI = vi; + } + + public override void OnResponse(Mobile from, string text) + { + if (!m_VI.Valid || !m_Vendor.CanInteractWith(from, true)) + return; + + string firstWord; + + var sep = text.IndexOfAny(new[] { ' ', ',' }); + if (sep >= 0) + firstWord = text.Substring(0, sep); + else + firstWord = text; + + string description; + + if (int.TryParse(firstWord, out var price)) + { + if (sep >= 0) + description = text.Substring(sep + 1).Trim(); + else + description = ""; + } + else + { + price = -1; + description = text.Trim(); + } + + SetInfo(from, price, Utility.FixHtml(description)); + } + + public override void OnCancel(Mobile from) + { + if (!m_VI.Valid || !m_Vendor.CanInteractWith(from, true)) + return; + + SetInfo(from, -1, ""); + } + + private void SetInfo(Mobile from, int price, string description) + { + var item = m_VI.Item; + + var setPrice = false; + + if (price < 0) // Not for sale + { + price = -1; + + if (item is Container) + { + if (item is LockableContainer container && container.Locked) + m_Vendor.SayTo(from, 1043298); // Locked items may not be made not-for-sale. + else if (item.Items.Count > 0) + m_Vendor.SayTo(from, 1043299); // To be not for sale, all items in a container must be for sale. + else + setPrice = true; + } + else if (item is BaseBook || item is BulkOrderBook) + { + setPrice = true; + } + else + { + m_Vendor.SayTo( + from, + 1043301 + ); // Only the following may be made not-for-sale: books, containers, keyrings, and items in for-sale containers. + } + } + else + { + if (price > 100000000) + { + price = 100000000; + from.SendMessage("You cannot price items above 100,000,000 gold. The price has been adjusted."); + } + + setPrice = true; + } + + if (setPrice) + m_Vendor.SetVendorItem(item, price, description); + else + m_VI.Description = description; + } + } + + private class CollectGoldPrompt : Prompt + { + private readonly PlayerVendor m_Vendor; + + public CollectGoldPrompt(PlayerVendor vendor) => m_Vendor = vendor; + + public override void OnResponse(Mobile from, string text) + { + if (!m_Vendor.CanInteractWith(from, true)) + return; + + text = text.Trim(); + + if (!int.TryParse(text, out var amount)) + amount = 0; + + GiveGold(from, amount); + } + + public override void OnCancel(Mobile from) + { + if (!m_Vendor.CanInteractWith(from, true)) + return; + + GiveGold(from, 0); + } + + private void GiveGold(Mobile to, int amount) + { + if (amount <= 0) + m_Vendor.SayTo(to, "Very well. I will hold on to the money for now then."); + else + m_Vendor.GiveGold(to, amount); + } + } + + private class VendorNamePrompt : Prompt + { + private readonly PlayerVendor m_Vendor; + + public VendorNamePrompt(PlayerVendor vendor) => m_Vendor = vendor; + + public override void OnResponse(Mobile from, string text) + { + if (!m_Vendor.CanInteractWith(from, true)) + return; + + var name = text.Trim(); + + if (!NameVerification.Validate(name, 1, 20, true, true, true, 0, NameVerification.Empty)) + { + m_Vendor.SayTo(from, "That name is unacceptable."); + return; + } + + m_Vendor.Name = Utility.FixHtml(name); + + from.SendLocalizedMessage(1062496); // Your vendor has been renamed. + + from.SendGump(new NewPlayerVendorOwnerGump(m_Vendor)); + } + } + + private class ShopNamePrompt : Prompt + { + private readonly PlayerVendor m_Vendor; + + public ShopNamePrompt(PlayerVendor vendor) => m_Vendor = vendor; + + public override void OnResponse(Mobile from, string text) + { + if (!m_Vendor.CanInteractWith(from, true)) + return; + + var name = text.Trim(); + + if (!NameVerification.Validate(name, 1, 20, true, true, true, 0, NameVerification.Empty)) + { + m_Vendor.SayTo(from, "That name is unacceptable."); + return; + } + + m_Vendor.ShopName = Utility.FixHtml(name); + + from.SendGump(new NewPlayerVendorOwnerGump(m_Vendor)); + } + } } - } - public class PlayerVendorPlaceholder : Item - { - private readonly ExpireTimer m_Timer; - - public PlayerVendorPlaceholder(PlayerVendor vendor) : base(0x1F28) + public class PlayerVendorPlaceholder : Item { - Hue = 0x672; - Movable = false; + private readonly ExpireTimer m_Timer; - Vendor = vendor; + public PlayerVendorPlaceholder(PlayerVendor vendor) : base(0x1F28) + { + Hue = 0x672; + Movable = false; - m_Timer = new ExpireTimer(this); - m_Timer.Start(); + Vendor = vendor; + + m_Timer = new ExpireTimer(this); + m_Timer.Start(); + } + + public PlayerVendorPlaceholder(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public PlayerVendor Vendor { get; private set; } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + if (Vendor != null) + list.Add(1062498, Vendor.Name); // reserved for vendor ~1_NAME~ + } + + public void RestartTimer() + { + m_Timer.Stop(); + m_Timer.Start(); + } + + public override void OnDelete() + { + if (Vendor?.Deleted == false) + { + Vendor.MoveToWorld(Location, Map); + Vendor.Placeholder = null; + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); + + writer.Write(Vendor); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + Vendor = (PlayerVendor)reader.ReadMobile(); + + Timer.DelayCall(Delete); + } + + private class ExpireTimer : Timer + { + private readonly PlayerVendorPlaceholder m_Placeholder; + + public ExpireTimer(PlayerVendorPlaceholder placeholder) : base(TimeSpan.FromMinutes(2.0)) + { + m_Placeholder = placeholder; + + Priority = TimerPriority.FiveSeconds; + } + + protected override void OnTick() + { + m_Placeholder.Delete(); + } + } } - - public PlayerVendorPlaceholder(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public PlayerVendor Vendor { get; private set; } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - if (Vendor != null) - list.Add(1062498, Vendor.Name); // reserved for vendor ~1_NAME~ - } - - public void RestartTimer() - { - m_Timer.Stop(); - m_Timer.Start(); - } - - public override void OnDelete() - { - if (Vendor?.Deleted == false) - { - Vendor.MoveToWorld(Location, Map); - Vendor.Placeholder = null; - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); - - writer.Write(Vendor); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - Vendor = (PlayerVendor)reader.ReadMobile(); - - Timer.DelayCall(Delete); - } - - private class ExpireTimer : Timer - { - private readonly PlayerVendorPlaceholder m_Placeholder; - - public ExpireTimer(PlayerVendorPlaceholder placeholder) : base(TimeSpan.FromMinutes(2.0)) - { - m_Placeholder = placeholder; - - Priority = TimerPriority.FiveSeconds; - } - - protected override void OnTick() - { - m_Placeholder.Delete(); - } - } - } } diff --git a/Projects/UOContent/Mobiles/Vendors/PresetMapBuy.cs b/Projects/UOContent/Mobiles/Vendors/PresetMapBuy.cs index 85bfd04bc..5c0a97b20 100644 --- a/Projects/UOContent/Mobiles/Vendors/PresetMapBuy.cs +++ b/Projects/UOContent/Mobiles/Vendors/PresetMapBuy.cs @@ -2,16 +2,22 @@ using Server.Items; namespace Server.Mobiles { - public class PresetMapBuyInfo : GenericBuyInfo - { - private readonly PresetMapEntry m_Entry; + public class PresetMapBuyInfo : GenericBuyInfo + { + private readonly PresetMapEntry m_Entry; - public PresetMapBuyInfo(PresetMapEntry entry, int price, int amount) : base(entry.Name.ToString(), null, price, - amount, 0x14EC, 0) => - m_Entry = entry; + public PresetMapBuyInfo(PresetMapEntry entry, int price, int amount) : base( + entry.Name.ToString(), + null, + price, + amount, + 0x14EC, + 0 + ) => + m_Entry = entry; - public override bool CanCacheDisplay => false; + public override bool CanCacheDisplay => false; - public override IEntity GetEntity() => new PresetMap(m_Entry); - } -} \ No newline at end of file + public override IEntity GetEntity() => new PresetMap(m_Entry); + } +} diff --git a/Projects/UOContent/Mobiles/Vendors/RentedVendor.cs b/Projects/UOContent/Mobiles/Vendors/RentedVendor.cs index 1b70051a2..85504d06d 100644 --- a/Projects/UOContent/Mobiles/Vendors/RentedVendor.cs +++ b/Projects/UOContent/Mobiles/Vendors/RentedVendor.cs @@ -8,350 +8,359 @@ using Server.Prompts; namespace Server.Mobiles { - public class VendorRentalDuration - { - public static readonly VendorRentalDuration[] Instances = + public class VendorRentalDuration { - new VendorRentalDuration(TimeSpan.FromDays(7.0), 1062361), // 1 Week - new VendorRentalDuration(TimeSpan.FromDays(14.0), 1062362), // 2 Weeks - new VendorRentalDuration(TimeSpan.FromDays(21.0), 1062363), // 3 Weeks - new VendorRentalDuration(TimeSpan.FromDays(28.0), 1062364) // 1 Month - }; - - private VendorRentalDuration(TimeSpan duration, int name) - { - Duration = duration; - Name = name; - } - - public TimeSpan Duration { get; } - - public int Name { get; } - - public int ID - { - get - { - for (int i = 0; i < Instances.Length; i++) - if (Instances[i] == this) - return i; - - return 0; - } - } - } - - public class RentedVendor : PlayerVendor - { - private Timer m_RentalExpireTimer; - - public RentedVendor(Mobile owner, BaseHouse house, VendorRentalDuration duration, int rentalPrice, - bool landlordRenew, int rentalGold) : base(owner, house) - { - RentalDuration = duration; - RentalPrice = RenewalPrice = rentalPrice; - LandlordRenew = landlordRenew; - RenterRenew = false; - - RentalGold = rentalGold; - - RentalExpireTime = DateTime.UtcNow + duration.Duration; - m_RentalExpireTimer = new RentalExpireTimer(this, duration.Duration); - m_RentalExpireTimer.Start(); - } - - public RentedVendor(Serial serial) : base(serial) - { - } - - public VendorRentalDuration RentalDuration { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int RentalPrice { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool LandlordRenew { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool RenterRenew { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Renew => LandlordRenew && RenterRenew && House != null && House.DecayType != DecayType.Condemned; - - [CommandProperty(AccessLevel.GameMaster)] - public int RenewalPrice { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public int RentalGold { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime RentalExpireTime { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Landlord => House?.Owner; - - public override bool IsOwner(Mobile m) => m == Owner || m.AccessLevel >= AccessLevel.GameMaster || (Core.ML && AccountHandler.CheckAccount(m, Owner)); - - public bool IsLandlord(Mobile m) => House?.IsOwner(m) == true; - - public void ComputeRentalExpireDelay(out int days, out int hours) - { - TimeSpan delay = RentalExpireTime - DateTime.UtcNow; - - if (delay <= TimeSpan.Zero) - { - days = 0; - hours = 0; - } - else - { - days = delay.Days; - hours = delay.Hours; - } - } - - public void SendRentalExpireMessage(Mobile to) - { - ComputeRentalExpireDelay(out int days, out int hours); - - to.SendLocalizedMessage(1062464, - $"{days}\t{hours}"); // The rental contract on this vendor will expire in ~1_DAY~ day(s) and ~2_HOUR~ hour(s). - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_RentalExpireTimer.Stop(); - } - - public override void Destroy(bool toBackpack) - { - if (RentalGold > 0 && House?.IsAosRules == true) - { - House.MovingCrate ??= new MovingCrate(House); - - Banker.Deposit(House.MovingCrate, RentalGold); - RentalGold = 0; - } - - base.Destroy(toBackpack); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - if (from.Alive) - { - if (IsOwner(from)) + public static readonly VendorRentalDuration[] Instances = { - list.Add(new ContractOptionsEntry(this)); - } - else if (IsLandlord(from)) + new VendorRentalDuration(TimeSpan.FromDays(7.0), 1062361), // 1 Week + new VendorRentalDuration(TimeSpan.FromDays(14.0), 1062362), // 2 Weeks + new VendorRentalDuration(TimeSpan.FromDays(21.0), 1062363), // 3 Weeks + new VendorRentalDuration(TimeSpan.FromDays(28.0), 1062364) // 1 Month + }; + + private VendorRentalDuration(TimeSpan duration, int name) { - if (RentalGold > 0) - list.Add(new CollectRentEntry(this)); - - list.Add(new TerminateContractEntry(this)); - list.Add(new ContractOptionsEntry(this)); + Duration = duration; + Name = name; } - } - base.GetContextMenuEntries(from, list); + public TimeSpan Duration { get; } + + public int Name { get; } + + public int ID + { + get + { + for (var i = 0; i < Instances.Length; i++) + if (Instances[i] == this) + return i; + + return 0; + } + } } - public override void Serialize(IGenericWriter writer) + public class RentedVendor : PlayerVendor { - base.Serialize(writer); + private Timer m_RentalExpireTimer; - writer.WriteEncodedInt(0); // version + public RentedVendor( + Mobile owner, BaseHouse house, VendorRentalDuration duration, int rentalPrice, + bool landlordRenew, int rentalGold + ) : base(owner, house) + { + RentalDuration = duration; + RentalPrice = RenewalPrice = rentalPrice; + LandlordRenew = landlordRenew; + RenterRenew = false; - writer.WriteEncodedInt(RentalDuration.ID); + RentalGold = rentalGold; - writer.Write(RentalPrice); - writer.Write(LandlordRenew); - writer.Write(RenterRenew); - writer.Write(RenewalPrice); + RentalExpireTime = DateTime.UtcNow + duration.Duration; + m_RentalExpireTimer = new RentalExpireTimer(this, duration.Duration); + m_RentalExpireTimer.Start(); + } - writer.Write(RentalGold); + public RentedVendor(Serial serial) : base(serial) + { + } - writer.WriteDeltaTime(RentalExpireTime); + public VendorRentalDuration RentalDuration { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int RentalPrice { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool LandlordRenew { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool RenterRenew { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Renew => LandlordRenew && RenterRenew && House != null && House.DecayType != DecayType.Condemned; + + [CommandProperty(AccessLevel.GameMaster)] + public int RenewalPrice { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int RentalGold { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime RentalExpireTime { get; private set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Landlord => House?.Owner; + + public override bool IsOwner(Mobile m) => m == Owner || m.AccessLevel >= AccessLevel.GameMaster || + Core.ML && AccountHandler.CheckAccount(m, Owner); + + public bool IsLandlord(Mobile m) => House?.IsOwner(m) == true; + + public void ComputeRentalExpireDelay(out int days, out int hours) + { + var delay = RentalExpireTime - DateTime.UtcNow; + + if (delay <= TimeSpan.Zero) + { + days = 0; + hours = 0; + } + else + { + days = delay.Days; + hours = delay.Hours; + } + } + + public void SendRentalExpireMessage(Mobile to) + { + ComputeRentalExpireDelay(out var days, out var hours); + + to.SendLocalizedMessage( + 1062464, + $"{days}\t{hours}" + ); // The rental contract on this vendor will expire in ~1_DAY~ day(s) and ~2_HOUR~ hour(s). + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_RentalExpireTimer.Stop(); + } + + public override void Destroy(bool toBackpack) + { + if (RentalGold > 0 && House?.IsAosRules == true) + { + House.MovingCrate ??= new MovingCrate(House); + + Banker.Deposit(House.MovingCrate, RentalGold); + RentalGold = 0; + } + + base.Destroy(toBackpack); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + if (from.Alive) + { + if (IsOwner(from)) + { + list.Add(new ContractOptionsEntry(this)); + } + else if (IsLandlord(from)) + { + if (RentalGold > 0) + list.Add(new CollectRentEntry(this)); + + list.Add(new TerminateContractEntry(this)); + list.Add(new ContractOptionsEntry(this)); + } + } + + base.GetContextMenuEntries(from, list); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.WriteEncodedInt(RentalDuration.ID); + + writer.Write(RentalPrice); + writer.Write(LandlordRenew); + writer.Write(RenterRenew); + writer.Write(RenewalPrice); + + writer.Write(RentalGold); + + writer.WriteDeltaTime(RentalExpireTime); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + var durationID = reader.ReadEncodedInt(); + if (durationID < VendorRentalDuration.Instances.Length) + RentalDuration = VendorRentalDuration.Instances[durationID]; + else + RentalDuration = VendorRentalDuration.Instances[0]; + + RentalPrice = reader.ReadInt(); + LandlordRenew = reader.ReadBool(); + RenterRenew = reader.ReadBool(); + RenewalPrice = reader.ReadInt(); + + RentalGold = reader.ReadInt(); + + RentalExpireTime = reader.ReadDeltaTime(); + + var delay = RentalExpireTime - DateTime.UtcNow; + m_RentalExpireTimer = new RentalExpireTimer(this, delay > TimeSpan.Zero ? delay : TimeSpan.Zero); + m_RentalExpireTimer.Start(); + } + + private class ContractOptionsEntry : ContextMenuEntry + { + private readonly RentedVendor m_Vendor; + + public ContractOptionsEntry(RentedVendor vendor) : base(6209) => m_Vendor = vendor; + + public override void OnClick() + { + var from = Owner.From; + + if (m_Vendor.Deleted || !from.CheckAlive()) + return; + + if (m_Vendor.IsOwner(from)) + { + from.CloseGump(); + from.SendGump(new RenterVendorRentalGump(m_Vendor)); + + m_Vendor.SendRentalExpireMessage(from); + } + else if (m_Vendor.IsLandlord(from)) + { + from.CloseGump(); + from.SendGump(new LandlordVendorRentalGump(m_Vendor)); + + m_Vendor.SendRentalExpireMessage(from); + } + } + } + + private class CollectRentEntry : ContextMenuEntry + { + private readonly RentedVendor m_Vendor; + + public CollectRentEntry(RentedVendor vendor) : base(6212) => m_Vendor = vendor; + + public override void OnClick() + { + var from = Owner.From; + + if (m_Vendor.Deleted || !from.CheckAlive() || !m_Vendor.IsLandlord(from)) + return; + + if (m_Vendor.RentalGold > 0) + { + var depositedGold = Banker.DepositUpTo(from, m_Vendor.RentalGold); + m_Vendor.RentalGold -= depositedGold; + + if (depositedGold > 0) + from.SendLocalizedMessage( + 1060397, + depositedGold.ToString() + ); // ~1_AMOUNT~ gold has been deposited into your bank box. + + if (m_Vendor.RentalGold > 0) + from.SendLocalizedMessage(500390); // Your bank box is full. + } + } + } + + private class TerminateContractEntry : ContextMenuEntry + { + private readonly RentedVendor m_Vendor; + + public TerminateContractEntry(RentedVendor vendor) : base(6218) => m_Vendor = vendor; + + public override void OnClick() + { + var from = Owner.From; + + if (m_Vendor.Deleted || !from.CheckAlive() || !m_Vendor.IsLandlord(from)) + return; + + from.SendLocalizedMessage( + 1062503 + ); // Enter the amount of gold you wish to offer the renter in exchange for immediate termination of this contract? + from.Prompt = new RefundOfferPrompt(m_Vendor); + } + } + + private class RefundOfferPrompt : Prompt + { + private readonly RentedVendor m_Vendor; + + public RefundOfferPrompt(RentedVendor vendor) => m_Vendor = vendor; + + public override void OnResponse(Mobile from, string text) + { + if (!m_Vendor.CanInteractWith(from, false) || !m_Vendor.IsLandlord(from)) + return; + + text = text.Trim(); + + if (!int.TryParse(text, out var amount)) + amount = -1; + + var owner = m_Vendor.Owner; + if (owner == null) + return; + + if (amount < 0) + { + from.SendLocalizedMessage(1062506); // You did not enter a valid amount. Offer canceled. + } + else if (Banker.GetBalance(from) < amount) + { + from.SendLocalizedMessage(1062507); // You do not have that much money in your bank account. + } + else if (owner.Map != m_Vendor.Map || !owner.InRange(m_Vendor, 5)) + { + from.SendLocalizedMessage( + 1062505 + ); // The renter must be closer to the vendor in order for you to make this offer. + } + else + { + from.SendLocalizedMessage(1062504); // Please wait while the renter considers your offer. + + owner.CloseGump(); + owner.SendGump(new VendorRentalRefundGump(m_Vendor, from, amount)); + } + } + } + + private class RentalExpireTimer : Timer + { + private readonly RentedVendor m_Vendor; + + public RentalExpireTimer(RentedVendor vendor, TimeSpan delay) : base(delay, vendor.RentalDuration.Duration) + { + m_Vendor = vendor; + + Priority = TimerPriority.OneMinute; + } + + protected override void OnTick() + { + var renewalPrice = m_Vendor.RenewalPrice; + + if (m_Vendor.Renew && m_Vendor.HoldGold >= renewalPrice) + { + m_Vendor.HoldGold -= renewalPrice; + m_Vendor.RentalGold += renewalPrice; + + m_Vendor.RentalPrice = renewalPrice; + + m_Vendor.RentalExpireTime = DateTime.UtcNow + m_Vendor.RentalDuration.Duration; + } + else + { + m_Vendor.Destroy(false); + } + } + } } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - int durationID = reader.ReadEncodedInt(); - if (durationID < VendorRentalDuration.Instances.Length) - RentalDuration = VendorRentalDuration.Instances[durationID]; - else - RentalDuration = VendorRentalDuration.Instances[0]; - - RentalPrice = reader.ReadInt(); - LandlordRenew = reader.ReadBool(); - RenterRenew = reader.ReadBool(); - RenewalPrice = reader.ReadInt(); - - RentalGold = reader.ReadInt(); - - RentalExpireTime = reader.ReadDeltaTime(); - - TimeSpan delay = RentalExpireTime - DateTime.UtcNow; - m_RentalExpireTimer = new RentalExpireTimer(this, delay > TimeSpan.Zero ? delay : TimeSpan.Zero); - m_RentalExpireTimer.Start(); - } - - private class ContractOptionsEntry : ContextMenuEntry - { - private readonly RentedVendor m_Vendor; - - public ContractOptionsEntry(RentedVendor vendor) : base(6209) => m_Vendor = vendor; - - public override void OnClick() - { - Mobile from = Owner.From; - - if (m_Vendor.Deleted || !from.CheckAlive()) - return; - - if (m_Vendor.IsOwner(from)) - { - from.CloseGump(); - from.SendGump(new RenterVendorRentalGump(m_Vendor)); - - m_Vendor.SendRentalExpireMessage(from); - } - else if (m_Vendor.IsLandlord(from)) - { - from.CloseGump(); - from.SendGump(new LandlordVendorRentalGump(m_Vendor)); - - m_Vendor.SendRentalExpireMessage(from); - } - } - } - - private class CollectRentEntry : ContextMenuEntry - { - private readonly RentedVendor m_Vendor; - - public CollectRentEntry(RentedVendor vendor) : base(6212) => m_Vendor = vendor; - - public override void OnClick() - { - Mobile from = Owner.From; - - if (m_Vendor.Deleted || !from.CheckAlive() || !m_Vendor.IsLandlord(from)) - return; - - if (m_Vendor.RentalGold > 0) - { - int depositedGold = Banker.DepositUpTo(from, m_Vendor.RentalGold); - m_Vendor.RentalGold -= depositedGold; - - if (depositedGold > 0) - from.SendLocalizedMessage(1060397, - depositedGold.ToString()); // ~1_AMOUNT~ gold has been deposited into your bank box. - - if (m_Vendor.RentalGold > 0) - from.SendLocalizedMessage(500390); // Your bank box is full. - } - } - } - - private class TerminateContractEntry : ContextMenuEntry - { - private readonly RentedVendor m_Vendor; - - public TerminateContractEntry(RentedVendor vendor) : base(6218) => m_Vendor = vendor; - - public override void OnClick() - { - Mobile from = Owner.From; - - if (m_Vendor.Deleted || !from.CheckAlive() || !m_Vendor.IsLandlord(from)) - return; - - from.SendLocalizedMessage( - 1062503); // Enter the amount of gold you wish to offer the renter in exchange for immediate termination of this contract? - from.Prompt = new RefundOfferPrompt(m_Vendor); - } - } - - private class RefundOfferPrompt : Prompt - { - private readonly RentedVendor m_Vendor; - - public RefundOfferPrompt(RentedVendor vendor) => m_Vendor = vendor; - - public override void OnResponse(Mobile from, string text) - { - if (!m_Vendor.CanInteractWith(from, false) || !m_Vendor.IsLandlord(from)) - return; - - text = text.Trim(); - - if (!int.TryParse(text, out int amount)) - amount = -1; - - Mobile owner = m_Vendor.Owner; - if (owner == null) - return; - - if (amount < 0) - { - from.SendLocalizedMessage(1062506); // You did not enter a valid amount. Offer canceled. - } - else if (Banker.GetBalance(from) < amount) - { - from.SendLocalizedMessage(1062507); // You do not have that much money in your bank account. - } - else if (owner.Map != m_Vendor.Map || !owner.InRange(m_Vendor, 5)) - { - from.SendLocalizedMessage( - 1062505); // The renter must be closer to the vendor in order for you to make this offer. - } - else - { - from.SendLocalizedMessage(1062504); // Please wait while the renter considers your offer. - - owner.CloseGump(); - owner.SendGump(new VendorRentalRefundGump(m_Vendor, from, amount)); - } - } - } - - private class RentalExpireTimer : Timer - { - private readonly RentedVendor m_Vendor; - - public RentalExpireTimer(RentedVendor vendor, TimeSpan delay) : base(delay, vendor.RentalDuration.Duration) - { - m_Vendor = vendor; - - Priority = TimerPriority.OneMinute; - } - - protected override void OnTick() - { - int renewalPrice = m_Vendor.RenewalPrice; - - if (m_Vendor.Renew && m_Vendor.HoldGold >= renewalPrice) - { - m_Vendor.HoldGold -= renewalPrice; - m_Vendor.RentalGold += renewalPrice; - - m_Vendor.RentalPrice = renewalPrice; - - m_Vendor.RentalExpireTime = DateTime.UtcNow + m_Vendor.RentalDuration.Duration; - } - else - { - m_Vendor.Destroy(false); - } - } - } - } } diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBChainmailArmor.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBChainmailArmor.cs index c445f2503..5eda846d9 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBChainmailArmor.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBChainmailArmor.cs @@ -3,30 +3,30 @@ using Server.Items; namespace Server.Mobiles { - public class SBChainmailArmor : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBChainmailArmor : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(ChainCoif), 17, 20, 0x13BB, 0)); - Add(new GenericBuyInfo(typeof(ChainChest), 143, 20, 0x13BF, 0)); - Add(new GenericBuyInfo(typeof(ChainLegs), 149, 20, 0x13BE, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(ChainCoif), 6); - Add(typeof(ChainChest), 71); - Add(typeof(ChainLegs), 74); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(ChainCoif), 17, 20, 0x13BB, 0)); + Add(new GenericBuyInfo(typeof(ChainChest), 143, 20, 0x13BF, 0)); + Add(new GenericBuyInfo(typeof(ChainLegs), 149, 20, 0x13BE, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(ChainCoif), 6); + Add(typeof(ChainChest), 71); + Add(typeof(ChainLegs), 74); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBHelmetArmor.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBHelmetArmor.cs index c5bcc494e..0e1b42343 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBHelmetArmor.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBHelmetArmor.cs @@ -3,38 +3,38 @@ using Server.Items; namespace Server.Mobiles { - public class SBHelmetArmor : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBHelmetArmor : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(PlateHelm), 21, 20, 0x1412, 0)); - Add(new GenericBuyInfo(typeof(CloseHelm), 18, 20, 0x1408, 0)); - Add(new GenericBuyInfo(typeof(CloseHelm), 18, 20, 0x1409, 0)); - Add(new GenericBuyInfo(typeof(Helmet), 31, 20, 0x140A, 0)); - Add(new GenericBuyInfo(typeof(Helmet), 18, 20, 0x140B, 0)); - Add(new GenericBuyInfo(typeof(NorseHelm), 18, 20, 0x140E, 0)); - Add(new GenericBuyInfo(typeof(NorseHelm), 18, 20, 0x140F, 0)); - Add(new GenericBuyInfo(typeof(Bascinet), 18, 20, 0x140C, 0)); - Add(new GenericBuyInfo(typeof(PlateHelm), 21, 20, 0x1419, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Bascinet), 9); - Add(typeof(CloseHelm), 9); - Add(typeof(Helmet), 9); - Add(typeof(NorseHelm), 9); - Add(typeof(PlateHelm), 10); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(PlateHelm), 21, 20, 0x1412, 0)); + Add(new GenericBuyInfo(typeof(CloseHelm), 18, 20, 0x1408, 0)); + Add(new GenericBuyInfo(typeof(CloseHelm), 18, 20, 0x1409, 0)); + Add(new GenericBuyInfo(typeof(Helmet), 31, 20, 0x140A, 0)); + Add(new GenericBuyInfo(typeof(Helmet), 18, 20, 0x140B, 0)); + Add(new GenericBuyInfo(typeof(NorseHelm), 18, 20, 0x140E, 0)); + Add(new GenericBuyInfo(typeof(NorseHelm), 18, 20, 0x140F, 0)); + Add(new GenericBuyInfo(typeof(Bascinet), 18, 20, 0x140C, 0)); + Add(new GenericBuyInfo(typeof(PlateHelm), 21, 20, 0x1419, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Bascinet), 9); + Add(typeof(CloseHelm), 9); + Add(typeof(Helmet), 9); + Add(typeof(NorseHelm), 9); + Add(typeof(PlateHelm), 10); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBLeatherArmor.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBLeatherArmor.cs index 02df138b0..fa971b4fc 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBLeatherArmor.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBLeatherArmor.cs @@ -3,47 +3,47 @@ using Server.Items; namespace Server.Mobiles { - public class SBLeatherArmor : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBLeatherArmor : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(LeatherArms), 80, 20, 0x13CD, 0)); - Add(new GenericBuyInfo(typeof(LeatherChest), 101, 20, 0x13CC, 0)); - Add(new GenericBuyInfo(typeof(LeatherGloves), 60, 20, 0x13C6, 0)); - Add(new GenericBuyInfo(typeof(LeatherGorget), 74, 20, 0x13C7, 0)); - Add(new GenericBuyInfo(typeof(LeatherLegs), 80, 20, 0x13cb, 0)); - Add(new GenericBuyInfo(typeof(LeatherCap), 10, 20, 0x1DB9, 0)); - Add(new GenericBuyInfo(typeof(FemaleLeatherChest), 116, 20, 0x1C06, 0)); - Add(new GenericBuyInfo(typeof(LeatherBustierArms), 97, 20, 0x1C0A, 0)); - Add(new GenericBuyInfo(typeof(LeatherShorts), 86, 20, 0x1C00, 0)); - Add(new GenericBuyInfo(typeof(LeatherSkirt), 87, 20, 0x1C08, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(LeatherArms), 40); - Add(typeof(LeatherChest), 52); - Add(typeof(LeatherGloves), 30); - Add(typeof(LeatherGorget), 37); - Add(typeof(LeatherLegs), 40); - Add(typeof(LeatherCap), 5); + public override List BuyInfo { get; } = new InternalBuyInfo(); - Add(typeof(FemaleLeatherChest), 18); - Add(typeof(FemaleStuddedChest), 25); - Add(typeof(LeatherShorts), 14); - Add(typeof(LeatherSkirt), 11); - Add(typeof(LeatherBustierArms), 11); - Add(typeof(StuddedBustierArms), 27); - } + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(LeatherArms), 80, 20, 0x13CD, 0)); + Add(new GenericBuyInfo(typeof(LeatherChest), 101, 20, 0x13CC, 0)); + Add(new GenericBuyInfo(typeof(LeatherGloves), 60, 20, 0x13C6, 0)); + Add(new GenericBuyInfo(typeof(LeatherGorget), 74, 20, 0x13C7, 0)); + Add(new GenericBuyInfo(typeof(LeatherLegs), 80, 20, 0x13cb, 0)); + Add(new GenericBuyInfo(typeof(LeatherCap), 10, 20, 0x1DB9, 0)); + Add(new GenericBuyInfo(typeof(FemaleLeatherChest), 116, 20, 0x1C06, 0)); + Add(new GenericBuyInfo(typeof(LeatherBustierArms), 97, 20, 0x1C0A, 0)); + Add(new GenericBuyInfo(typeof(LeatherShorts), 86, 20, 0x1C00, 0)); + Add(new GenericBuyInfo(typeof(LeatherSkirt), 87, 20, 0x1C08, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(LeatherArms), 40); + Add(typeof(LeatherChest), 52); + Add(typeof(LeatherGloves), 30); + Add(typeof(LeatherGorget), 37); + Add(typeof(LeatherLegs), 40); + Add(typeof(LeatherCap), 5); + + Add(typeof(FemaleLeatherChest), 18); + Add(typeof(FemaleStuddedChest), 25); + Add(typeof(LeatherShorts), 14); + Add(typeof(LeatherSkirt), 11); + Add(typeof(LeatherBustierArms), 11); + Add(typeof(StuddedBustierArms), 27); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBMetalShields.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBMetalShields.cs index c4dbd05bb..9eb281e8c 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBMetalShields.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBMetalShields.cs @@ -3,36 +3,36 @@ using Server.Items; namespace Server.Mobiles { - public class SBMetalShields : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBMetalShields : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(BronzeShield), 66, 20, 0x1B72, 0)); - Add(new GenericBuyInfo(typeof(Buckler), 50, 20, 0x1B73, 0)); - Add(new GenericBuyInfo(typeof(MetalKiteShield), 123, 20, 0x1B74, 0)); - Add(new GenericBuyInfo(typeof(HeaterShield), 231, 20, 0x1B76, 0)); - Add(new GenericBuyInfo(typeof(WoodenKiteShield), 70, 20, 0x1B78, 0)); - Add(new GenericBuyInfo(typeof(MetalShield), 121, 20, 0x1B7B, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Buckler), 25); - Add(typeof(BronzeShield), 33); - Add(typeof(MetalShield), 60); - Add(typeof(MetalKiteShield), 62); - Add(typeof(HeaterShield), 115); - Add(typeof(WoodenKiteShield), 35); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(BronzeShield), 66, 20, 0x1B72, 0)); + Add(new GenericBuyInfo(typeof(Buckler), 50, 20, 0x1B73, 0)); + Add(new GenericBuyInfo(typeof(MetalKiteShield), 123, 20, 0x1B74, 0)); + Add(new GenericBuyInfo(typeof(HeaterShield), 231, 20, 0x1B76, 0)); + Add(new GenericBuyInfo(typeof(WoodenKiteShield), 70, 20, 0x1B78, 0)); + Add(new GenericBuyInfo(typeof(MetalShield), 121, 20, 0x1B7B, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Buckler), 25); + Add(typeof(BronzeShield), 33); + Add(typeof(MetalShield), 60); + Add(typeof(MetalKiteShield), 62); + Add(typeof(HeaterShield), 115); + Add(typeof(WoodenKiteShield), 35); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBPlateArmor.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBPlateArmor.cs index de4c11961..b1d329e07 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBPlateArmor.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBPlateArmor.cs @@ -3,36 +3,36 @@ using Server.Items; namespace Server.Mobiles { - public class SBPlateArmor : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBPlateArmor : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(PlateGorget), 104, 20, 0x1413, 0)); - Add(new GenericBuyInfo(typeof(PlateChest), 243, 20, 0x1415, 0)); - Add(new GenericBuyInfo(typeof(PlateLegs), 218, 20, 0x1411, 0)); - Add(new GenericBuyInfo(typeof(PlateArms), 188, 20, 0x1410, 0)); - Add(new GenericBuyInfo(typeof(PlateGloves), 155, 20, 0x1414, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(PlateArms), 94); - Add(typeof(PlateChest), 121); - Add(typeof(PlateGloves), 72); - Add(typeof(PlateGorget), 52); - Add(typeof(PlateLegs), 109); + public override List BuyInfo { get; } = new InternalBuyInfo(); - Add(typeof(FemalePlateChest), 113); - } + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(PlateGorget), 104, 20, 0x1413, 0)); + Add(new GenericBuyInfo(typeof(PlateChest), 243, 20, 0x1415, 0)); + Add(new GenericBuyInfo(typeof(PlateLegs), 218, 20, 0x1411, 0)); + Add(new GenericBuyInfo(typeof(PlateArms), 188, 20, 0x1410, 0)); + Add(new GenericBuyInfo(typeof(PlateGloves), 155, 20, 0x1414, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(PlateArms), 94); + Add(typeof(PlateChest), 121); + Add(typeof(PlateGloves), 72); + Add(typeof(PlateGorget), 52); + Add(typeof(PlateLegs), 109); + + Add(typeof(FemalePlateChest), 113); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBRingmailArmor.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBRingmailArmor.cs index 3ab0664de..6b4f4fcaa 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBRingmailArmor.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBRingmailArmor.cs @@ -3,32 +3,32 @@ using Server.Items; namespace Server.Mobiles { - public class SBRingmailArmor : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBRingmailArmor : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(RingmailChest), 121, 20, 0x13ec, 0)); - Add(new GenericBuyInfo(typeof(RingmailLegs), 90, 20, 0x13F0, 0)); - Add(new GenericBuyInfo(typeof(RingmailArms), 85, 20, 0x13EE, 0)); - Add(new GenericBuyInfo(typeof(RingmailGloves), 93, 20, 0x13eb, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(RingmailArms), 42); - Add(typeof(RingmailChest), 60); - Add(typeof(RingmailGloves), 26); - Add(typeof(RingmailLegs), 45); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(RingmailChest), 121, 20, 0x13ec, 0)); + Add(new GenericBuyInfo(typeof(RingmailLegs), 90, 20, 0x13F0, 0)); + Add(new GenericBuyInfo(typeof(RingmailArms), 85, 20, 0x13EE, 0)); + Add(new GenericBuyInfo(typeof(RingmailGloves), 93, 20, 0x13eb, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(RingmailArms), 42); + Add(typeof(RingmailChest), 60); + Add(typeof(RingmailGloves), 26); + Add(typeof(RingmailLegs), 45); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBStuddedArmor.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBStuddedArmor.cs index 7eeedcd04..0bbf8e762 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBStuddedArmor.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBStuddedArmor.cs @@ -3,38 +3,38 @@ using Server.Items; namespace Server.Mobiles { - public class SBStuddedArmor : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBStuddedArmor : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(StuddedArms), 87, 20, 0x13DC, 0)); - Add(new GenericBuyInfo(typeof(StuddedChest), 128, 20, 0x13DB, 0)); - Add(new GenericBuyInfo(typeof(StuddedGloves), 79, 20, 0x13D5, 0)); - Add(new GenericBuyInfo(typeof(StuddedGorget), 73, 20, 0x13D6, 0)); - Add(new GenericBuyInfo(typeof(StuddedLegs), 103, 20, 0x13DA, 0)); - Add(new GenericBuyInfo(typeof(FemaleStuddedChest), 142, 20, 0x1C02, 0)); - Add(new GenericBuyInfo(typeof(StuddedBustierArms), 120, 20, 0x1c0c, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(StuddedArms), 43); - Add(typeof(StuddedChest), 64); - Add(typeof(StuddedGloves), 39); - Add(typeof(StuddedGorget), 36); - Add(typeof(StuddedLegs), 51); - Add(typeof(FemaleStuddedChest), 71); - Add(typeof(StuddedBustierArms), 60); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(StuddedArms), 87, 20, 0x13DC, 0)); + Add(new GenericBuyInfo(typeof(StuddedChest), 128, 20, 0x13DB, 0)); + Add(new GenericBuyInfo(typeof(StuddedGloves), 79, 20, 0x13D5, 0)); + Add(new GenericBuyInfo(typeof(StuddedGorget), 73, 20, 0x13D6, 0)); + Add(new GenericBuyInfo(typeof(StuddedLegs), 103, 20, 0x13DA, 0)); + Add(new GenericBuyInfo(typeof(FemaleStuddedChest), 142, 20, 0x1C02, 0)); + Add(new GenericBuyInfo(typeof(StuddedBustierArms), 120, 20, 0x1c0c, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(StuddedArms), 43); + Add(typeof(StuddedChest), 64); + Add(typeof(StuddedGloves), 39); + Add(typeof(StuddedGorget), 36); + Add(typeof(StuddedLegs), 51); + Add(typeof(FemaleStuddedChest), 71); + Add(typeof(StuddedBustierArms), 60); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBWoodenShields.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBWoodenShields.cs index fcd1571f4..aac508499 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBWoodenShields.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/Armors/SBWoodenShields.cs @@ -3,26 +3,26 @@ using Server.Items; namespace Server.Mobiles { - public class SBWoodenShields : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBWoodenShields : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(WoodenShield), 30, 20, 0x1B7A, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(WoodenShield), 15); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(WoodenShield), 30, 20, 0x1B7A, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(WoodenShield), 15); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBAlchemist.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBAlchemist.cs index 6b386016e..36bad91d3 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBAlchemist.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBAlchemist.cs @@ -3,67 +3,67 @@ using Server.Items; namespace Server.Mobiles { - public class SBAlchemist : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBAlchemist : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(RefreshPotion), 15, 10, 0xF0B, 0)); - Add(new GenericBuyInfo(typeof(AgilityPotion), 15, 10, 0xF08, 0)); - Add(new GenericBuyInfo(typeof(NightSightPotion), 15, 10, 0xF06, 0)); - Add(new GenericBuyInfo(typeof(LesserHealPotion), 15, 10, 0xF0C, 0)); - Add(new GenericBuyInfo(typeof(StrengthPotion), 15, 10, 0xF09, 0)); - Add(new GenericBuyInfo(typeof(LesserPoisonPotion), 15, 10, 0xF0A, 0)); - Add(new GenericBuyInfo(typeof(LesserCurePotion), 15, 10, 0xF07, 0)); - Add(new GenericBuyInfo(typeof(LesserExplosionPotion), 21, 10, 0xF0D, 0)); - Add(new GenericBuyInfo(typeof(MortarPestle), 8, 10, 0xE9B, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - Add(new GenericBuyInfo(typeof(BlackPearl), 5, 20, 0xF7A, 0)); - Add(new GenericBuyInfo(typeof(Bloodmoss), 5, 20, 0xF7B, 0)); - Add(new GenericBuyInfo(typeof(Garlic), 3, 20, 0xF84, 0)); - Add(new GenericBuyInfo(typeof(Ginseng), 3, 20, 0xF85, 0)); - Add(new GenericBuyInfo(typeof(MandrakeRoot), 3, 20, 0xF86, 0)); - Add(new GenericBuyInfo(typeof(Nightshade), 3, 20, 0xF88, 0)); - Add(new GenericBuyInfo(typeof(SpidersSilk), 3, 20, 0xF8D, 0)); - Add(new GenericBuyInfo(typeof(SulfurousAsh), 3, 20, 0xF8C, 0)); + public override List BuyInfo { get; } = new InternalBuyInfo(); - Add(new GenericBuyInfo(typeof(Bottle), 5, 100, 0xF0E, 0)); - Add(new GenericBuyInfo(typeof(HeatingStand), 2, 100, 0x1849, 0)); + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(RefreshPotion), 15, 10, 0xF0B, 0)); + Add(new GenericBuyInfo(typeof(AgilityPotion), 15, 10, 0xF08, 0)); + Add(new GenericBuyInfo(typeof(NightSightPotion), 15, 10, 0xF06, 0)); + Add(new GenericBuyInfo(typeof(LesserHealPotion), 15, 10, 0xF0C, 0)); + Add(new GenericBuyInfo(typeof(StrengthPotion), 15, 10, 0xF09, 0)); + Add(new GenericBuyInfo(typeof(LesserPoisonPotion), 15, 10, 0xF0A, 0)); + Add(new GenericBuyInfo(typeof(LesserCurePotion), 15, 10, 0xF07, 0)); + Add(new GenericBuyInfo(typeof(LesserExplosionPotion), 21, 10, 0xF0D, 0)); + Add(new GenericBuyInfo(typeof(MortarPestle), 8, 10, 0xE9B, 0)); - Add(new GenericBuyInfo("1041060", typeof(HairDye), 37, 10, 0xEFF, 0)); - } + Add(new GenericBuyInfo(typeof(BlackPearl), 5, 20, 0xF7A, 0)); + Add(new GenericBuyInfo(typeof(Bloodmoss), 5, 20, 0xF7B, 0)); + Add(new GenericBuyInfo(typeof(Garlic), 3, 20, 0xF84, 0)); + Add(new GenericBuyInfo(typeof(Ginseng), 3, 20, 0xF85, 0)); + Add(new GenericBuyInfo(typeof(MandrakeRoot), 3, 20, 0xF86, 0)); + Add(new GenericBuyInfo(typeof(Nightshade), 3, 20, 0xF88, 0)); + Add(new GenericBuyInfo(typeof(SpidersSilk), 3, 20, 0xF8D, 0)); + Add(new GenericBuyInfo(typeof(SulfurousAsh), 3, 20, 0xF8C, 0)); + + Add(new GenericBuyInfo(typeof(Bottle), 5, 100, 0xF0E, 0)); + Add(new GenericBuyInfo(typeof(HeatingStand), 2, 100, 0x1849, 0)); + + Add(new GenericBuyInfo("1041060", typeof(HairDye), 37, 10, 0xEFF, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(BlackPearl), 3); + Add(typeof(Bloodmoss), 3); + Add(typeof(MandrakeRoot), 2); + Add(typeof(Garlic), 2); + Add(typeof(Ginseng), 2); + Add(typeof(Nightshade), 2); + Add(typeof(SpidersSilk), 2); + Add(typeof(SulfurousAsh), 2); + Add(typeof(Bottle), 3); + Add(typeof(MortarPestle), 4); + Add(typeof(HairDye), 19); + + Add(typeof(NightSightPotion), 7); + Add(typeof(AgilityPotion), 7); + Add(typeof(StrengthPotion), 7); + Add(typeof(RefreshPotion), 7); + Add(typeof(LesserCurePotion), 7); + Add(typeof(LesserHealPotion), 7); + Add(typeof(LesserPoisonPotion), 7); + Add(typeof(LesserExplosionPotion), 10); + } + } } - - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(BlackPearl), 3); - Add(typeof(Bloodmoss), 3); - Add(typeof(MandrakeRoot), 2); - Add(typeof(Garlic), 2); - Add(typeof(Ginseng), 2); - Add(typeof(Nightshade), 2); - Add(typeof(SpidersSilk), 2); - Add(typeof(SulfurousAsh), 2); - Add(typeof(Bottle), 3); - Add(typeof(MortarPestle), 4); - Add(typeof(HairDye), 19); - - Add(typeof(NightSightPotion), 7); - Add(typeof(AgilityPotion), 7); - Add(typeof(StrengthPotion), 7); - Add(typeof(RefreshPotion), 7); - Add(typeof(LesserCurePotion), 7); - Add(typeof(LesserHealPotion), 7); - Add(typeof(LesserPoisonPotion), 7); - Add(typeof(LesserExplosionPotion), 10); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBAnimalTrainer.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBAnimalTrainer.cs index ae49208d7..7f3155b3d 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBAnimalTrainer.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBAnimalTrainer.cs @@ -2,37 +2,37 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class SBAnimalTrainer : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBAnimalTrainer : SBInfo { - public InternalBuyInfo() - { - Add(new AnimalBuyInfo(1, typeof(Cat), 132, 10, 201, 0)); - Add(new AnimalBuyInfo(1, typeof(Dog), 170, 10, 217, 0)); - Add(new AnimalBuyInfo(1, typeof(Horse), 550, 10, 204, 0)); - Add(new AnimalBuyInfo(1, typeof(PackHorse), 631, 10, 291, 0)); - Add(new AnimalBuyInfo(1, typeof(PackLlama), 565, 10, 292, 0)); - Add(new AnimalBuyInfo(1, typeof(Rabbit), 106, 10, 205, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - if (!Core.AOS) + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List { - Add(new AnimalBuyInfo(1, typeof(Eagle), 402, 10, 5, 0)); - Add(new AnimalBuyInfo(1, typeof(BrownBear), 855, 10, 167, 0)); - Add(new AnimalBuyInfo(1, typeof(GrizzlyBear), 1767, 10, 212, 0)); - Add(new AnimalBuyInfo(1, typeof(Panther), 1271, 10, 214, 0)); - Add(new AnimalBuyInfo(1, typeof(TimberWolf), 768, 10, 225, 0)); - Add(new AnimalBuyInfo(1, typeof(Rat), 107, 10, 238, 0)); - } - } - } + public InternalBuyInfo() + { + Add(new AnimalBuyInfo(1, typeof(Cat), 132, 10, 201, 0)); + Add(new AnimalBuyInfo(1, typeof(Dog), 170, 10, 217, 0)); + Add(new AnimalBuyInfo(1, typeof(Horse), 550, 10, 204, 0)); + Add(new AnimalBuyInfo(1, typeof(PackHorse), 631, 10, 291, 0)); + Add(new AnimalBuyInfo(1, typeof(PackLlama), 565, 10, 292, 0)); + Add(new AnimalBuyInfo(1, typeof(Rabbit), 106, 10, 205, 0)); - public class InternalSellInfo : GenericSellInfo - { + if (!Core.AOS) + { + Add(new AnimalBuyInfo(1, typeof(Eagle), 402, 10, 5, 0)); + Add(new AnimalBuyInfo(1, typeof(BrownBear), 855, 10, 167, 0)); + Add(new AnimalBuyInfo(1, typeof(GrizzlyBear), 1767, 10, 212, 0)); + Add(new AnimalBuyInfo(1, typeof(Panther), 1271, 10, 214, 0)); + Add(new AnimalBuyInfo(1, typeof(TimberWolf), 768, 10, 225, 0)); + Add(new AnimalBuyInfo(1, typeof(Rat), 107, 10, 238, 0)); + } + } + } + + public class InternalSellInfo : GenericSellInfo + { + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBArchitect.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBArchitect.cs index 460fd2d7c..b6d294473 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBArchitect.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBArchitect.cs @@ -3,31 +3,31 @@ using Server.Items; namespace Server.Mobiles { - public class SBArchitect : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBArchitect : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo("1041280", typeof(InteriorDecorator), 10001, 20, 0xFC1, 0)); - if (Core.AOS) - Add(new GenericBuyInfo("1060651", typeof(HousePlacementTool), 627, 20, 0x14F6, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(InteriorDecorator), 5000); + public override List BuyInfo { get; } = new InternalBuyInfo(); - if (Core.AOS) - Add(typeof(HousePlacementTool), 301); - } + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo("1041280", typeof(InteriorDecorator), 10001, 20, 0xFC1, 0)); + if (Core.AOS) + Add(new GenericBuyInfo("1060651", typeof(HousePlacementTool), 627, 20, 0x14F6, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(InteriorDecorator), 5000); + + if (Core.AOS) + Add(typeof(HousePlacementTool), 301); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBaker.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBaker.cs index 0aa528ba7..00c92ad5b 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBaker.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBaker.cs @@ -3,49 +3,49 @@ using Server.Items; namespace Server.Mobiles { - public class SBBaker : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBBaker : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(BreadLoaf), 6, 20, 0x103B, 0)); - Add(new GenericBuyInfo(typeof(BreadLoaf), 5, 20, 0x103C, 0)); - Add(new GenericBuyInfo(typeof(ApplePie), 7, 20, 0x1041, 0)); // OSI just has Pie, not Apple/Fruit/Meat - Add(new GenericBuyInfo(typeof(Cake), 13, 20, 0x9E9, 0)); - Add(new GenericBuyInfo(typeof(Muffins), 3, 20, 0x9EA, 0)); - Add(new GenericBuyInfo(typeof(SackFlour), 3, 20, 0x1039, 0)); - Add(new GenericBuyInfo(typeof(FrenchBread), 5, 20, 0x98C, 0)); - Add(new GenericBuyInfo(typeof(Cookies), 3, 20, 0x160b, 0)); - Add(new GenericBuyInfo(typeof(CheesePizza), 8, 10, 0x1040, 0)); // OSI just has Pizza - Add(new GenericBuyInfo(typeof(JarHoney), 3, 20, 0x9ec, 0)); - Add(new GenericBuyInfo(typeof(BowlFlour), 7, 20, 0xA1E, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(BreadLoaf), 3); - Add(typeof(FrenchBread), 1); - Add(typeof(Cake), 5); - Add(typeof(Cookies), 3); - Add(typeof(Muffins), 2); - Add(typeof(CheesePizza), 4); - Add(typeof(ApplePie), 5); - Add(typeof(PeachCobbler), 5); - Add(typeof(Quiche), 6); - Add(typeof(Dough), 4); - Add(typeof(JarHoney), 1); - Add(typeof(Pitcher), 5); - Add(typeof(SackFlour), 1); - Add(typeof(Eggs), 1); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(BreadLoaf), 6, 20, 0x103B, 0)); + Add(new GenericBuyInfo(typeof(BreadLoaf), 5, 20, 0x103C, 0)); + Add(new GenericBuyInfo(typeof(ApplePie), 7, 20, 0x1041, 0)); // OSI just has Pie, not Apple/Fruit/Meat + Add(new GenericBuyInfo(typeof(Cake), 13, 20, 0x9E9, 0)); + Add(new GenericBuyInfo(typeof(Muffins), 3, 20, 0x9EA, 0)); + Add(new GenericBuyInfo(typeof(SackFlour), 3, 20, 0x1039, 0)); + Add(new GenericBuyInfo(typeof(FrenchBread), 5, 20, 0x98C, 0)); + Add(new GenericBuyInfo(typeof(Cookies), 3, 20, 0x160b, 0)); + Add(new GenericBuyInfo(typeof(CheesePizza), 8, 10, 0x1040, 0)); // OSI just has Pizza + Add(new GenericBuyInfo(typeof(JarHoney), 3, 20, 0x9ec, 0)); + Add(new GenericBuyInfo(typeof(BowlFlour), 7, 20, 0xA1E, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(BreadLoaf), 3); + Add(typeof(FrenchBread), 1); + Add(typeof(Cake), 5); + Add(typeof(Cookies), 3); + Add(typeof(Muffins), 2); + Add(typeof(CheesePizza), 4); + Add(typeof(ApplePie), 5); + Add(typeof(PeachCobbler), 5); + Add(typeof(Quiche), 6); + Add(typeof(Dough), 4); + Add(typeof(JarHoney), 1); + Add(typeof(Pitcher), 5); + Add(typeof(SackFlour), 1); + Add(typeof(Eggs), 1); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBanker.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBanker.cs index e97a824d8..723a66f85 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBanker.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBanker.cs @@ -4,26 +4,26 @@ using Server.Multis; namespace Server.Mobiles { - public class SBBanker : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBBanker : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo("1041243", typeof(ContractOfEmployment), 1252, 20, 0x14F0, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - if (BaseHouse.NewVendorSystem) - Add(new GenericBuyInfo("1062332", typeof(VendorRentalContract), 1252, 20, 0x14F0, 0x672)); - Add(new GenericBuyInfo("1047016", typeof(CommodityDeed), 5, 20, 0x14F0, 0x47)); - } - } + public override List BuyInfo { get; } = new InternalBuyInfo(); - public class InternalSellInfo : GenericSellInfo - { + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo("1041243", typeof(ContractOfEmployment), 1252, 20, 0x14F0, 0)); + + if (BaseHouse.NewVendorSystem) + Add(new GenericBuyInfo("1062332", typeof(VendorRentalContract), 1252, 20, 0x14F0, 0x672)); + Add(new GenericBuyInfo("1047016", typeof(CommodityDeed), 5, 20, 0x14F0, 0x47)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBard.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBard.cs index f3a359e66..920a31916 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBard.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBard.cs @@ -3,33 +3,33 @@ using Server.Items; namespace Server.Mobiles { - public class SBBard : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBBard : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Drums), 21, 10, 0x0E9C, 0)); - Add(new GenericBuyInfo(typeof(Tambourine), 21, 10, 0x0E9E, 0)); - Add(new GenericBuyInfo(typeof(LapHarp), 21, 10, 0x0EB2, 0)); - Add(new GenericBuyInfo(typeof(Lute), 21, 10, 0x0EB3, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(LapHarp), 10); - Add(typeof(Lute), 10); - Add(typeof(Drums), 10); - Add(typeof(Harp), 10); - Add(typeof(Tambourine), 10); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Drums), 21, 10, 0x0E9C, 0)); + Add(new GenericBuyInfo(typeof(Tambourine), 21, 10, 0x0E9E, 0)); + Add(new GenericBuyInfo(typeof(LapHarp), 21, 10, 0x0EB2, 0)); + Add(new GenericBuyInfo(typeof(Lute), 21, 10, 0x0EB3, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(LapHarp), 10); + Add(typeof(Lute), 10); + Add(typeof(Drums), 10); + Add(typeof(Harp), 10); + Add(typeof(Tambourine), 10); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBarkeeper.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBarkeeper.cs index 047a21d06..df6a02df4 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBarkeeper.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBarkeeper.cs @@ -4,100 +4,100 @@ using Server.Multis; namespace Server.Mobiles { - public class SBBarkeeper : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBBarkeeper : SBInfo { - public InternalBuyInfo() - { - Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Ale, 7, 20, 0x99F, 0)); - Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Wine, 7, 20, 0x9C7, 0)); - Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Liquor, 7, 20, 0x99B, 0)); - Add(new BeverageBuyInfo(typeof(Jug), BeverageType.Cider, 13, 20, 0x9C8, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Milk, 7, 20, 0x9F0, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Ale, 11, 20, 0x1F95, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Cider, 11, 20, 0x1F97, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Liquor, 11, 20, 0x1F99, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Wine, 11, 20, 0x1F9B, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Water, 11, 20, 0x1F9D, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - Add(new GenericBuyInfo(typeof(BreadLoaf), 6, 10, 0x103B, 0)); - Add(new GenericBuyInfo(typeof(CheeseWheel), 21, 10, 0x97E, 0)); - Add(new GenericBuyInfo(typeof(CookedBird), 17, 20, 0x9B7, 0)); - Add(new GenericBuyInfo(typeof(LambLeg), 8, 20, 0x160A, 0)); + public override List BuyInfo { get; } = new InternalBuyInfo(); - Add(new GenericBuyInfo(typeof(WoodenBowlOfCarrots), 3, 20, 0x15F9, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfCorn), 3, 20, 0x15FA, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfLettuce), 3, 20, 0x15FB, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfPeas), 3, 20, 0x15FC, 0)); - Add(new GenericBuyInfo(typeof(EmptyPewterBowl), 2, 20, 0x15FD, 0)); - Add(new GenericBuyInfo(typeof(PewterBowlOfCorn), 3, 20, 0x15FE, 0)); - Add(new GenericBuyInfo(typeof(PewterBowlOfLettuce), 3, 20, 0x15FF, 0)); - Add(new GenericBuyInfo(typeof(PewterBowlOfPeas), 3, 20, 0x1600, 0)); - Add(new GenericBuyInfo(typeof(PewterBowlOfPotatos), 3, 20, 0x1601, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfStew), 3, 20, 0x1604, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfTomatoSoup), 3, 20, 0x1606, 0)); + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Ale, 7, 20, 0x99F, 0)); + Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Wine, 7, 20, 0x9C7, 0)); + Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Liquor, 7, 20, 0x99B, 0)); + Add(new BeverageBuyInfo(typeof(Jug), BeverageType.Cider, 13, 20, 0x9C8, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Milk, 7, 20, 0x9F0, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Ale, 11, 20, 0x1F95, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Cider, 11, 20, 0x1F97, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Liquor, 11, 20, 0x1F99, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Wine, 11, 20, 0x1F9B, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Water, 11, 20, 0x1F9D, 0)); - Add(new GenericBuyInfo(typeof(ApplePie), 7, 20, 0x1041, 0)); // OSI just has Pie, not Apple/Fruit/Meat + Add(new GenericBuyInfo(typeof(BreadLoaf), 6, 10, 0x103B, 0)); + Add(new GenericBuyInfo(typeof(CheeseWheel), 21, 10, 0x97E, 0)); + Add(new GenericBuyInfo(typeof(CookedBird), 17, 20, 0x9B7, 0)); + Add(new GenericBuyInfo(typeof(LambLeg), 8, 20, 0x160A, 0)); - Add(new GenericBuyInfo("1016450", typeof(Chessboard), 2, 20, 0xFA6, 0)); - Add(new GenericBuyInfo("1016449", typeof(CheckerBoard), 2, 20, 0xFA6, 0)); - Add(new GenericBuyInfo(typeof(Backgammon), 2, 20, 0xE1C, 0)); - Add(new GenericBuyInfo(typeof(Dices), 2, 20, 0xFA7, 0)); - Add(new GenericBuyInfo("1041243", typeof(ContractOfEmployment), 1252, 20, 0x14F0, 0)); - Add(new GenericBuyInfo("a barkeep contract", typeof(BarkeepContract), 1252, 20, 0x14F0, 0)); - if (BaseHouse.NewVendorSystem) - Add(new GenericBuyInfo("1062332", typeof(VendorRentalContract), 1252, 20, 0x14F0, 0x672)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfCarrots), 3, 20, 0x15F9, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfCorn), 3, 20, 0x15FA, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfLettuce), 3, 20, 0x15FB, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfPeas), 3, 20, 0x15FC, 0)); + Add(new GenericBuyInfo(typeof(EmptyPewterBowl), 2, 20, 0x15FD, 0)); + Add(new GenericBuyInfo(typeof(PewterBowlOfCorn), 3, 20, 0x15FE, 0)); + Add(new GenericBuyInfo(typeof(PewterBowlOfLettuce), 3, 20, 0x15FF, 0)); + Add(new GenericBuyInfo(typeof(PewterBowlOfPeas), 3, 20, 0x1600, 0)); + Add(new GenericBuyInfo(typeof(PewterBowlOfPotatos), 3, 20, 0x1601, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfStew), 3, 20, 0x1604, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfTomatoSoup), 3, 20, 0x1606, 0)); - /*if (Map == Tokuno) - { - Add( new GenericBuyInfo( typeof( Wasabi ), 2, 20, 0x24E8, 0 ) ); - Add( new GenericBuyInfo( typeof( Wasabi ), 2, 20, 0x24E9, 0 ) ); - Add( new GenericBuyInfo( typeof( BentoBox ), 6, 20, 0x2836, 0 ) ); - Add( new GenericBuyInfo( typeof( BentoBox ), 6, 20, 0x2837, 0 ) ); - Add( new GenericBuyInfo( typeof( GreenTeaBasket ), 2, 20, 0x284B, 0 ) ); - }*/ - } + Add(new GenericBuyInfo(typeof(ApplePie), 7, 20, 0x1041, 0)); // OSI just has Pie, not Apple/Fruit/Meat + + Add(new GenericBuyInfo("1016450", typeof(Chessboard), 2, 20, 0xFA6, 0)); + Add(new GenericBuyInfo("1016449", typeof(CheckerBoard), 2, 20, 0xFA6, 0)); + Add(new GenericBuyInfo(typeof(Backgammon), 2, 20, 0xE1C, 0)); + Add(new GenericBuyInfo(typeof(Dices), 2, 20, 0xFA7, 0)); + Add(new GenericBuyInfo("1041243", typeof(ContractOfEmployment), 1252, 20, 0x14F0, 0)); + Add(new GenericBuyInfo("a barkeep contract", typeof(BarkeepContract), 1252, 20, 0x14F0, 0)); + if (BaseHouse.NewVendorSystem) + Add(new GenericBuyInfo("1062332", typeof(VendorRentalContract), 1252, 20, 0x14F0, 0x672)); + + /*if (Map == Tokuno) + { + Add( new GenericBuyInfo( typeof( Wasabi ), 2, 20, 0x24E8, 0 ) ); + Add( new GenericBuyInfo( typeof( Wasabi ), 2, 20, 0x24E9, 0 ) ); + Add( new GenericBuyInfo( typeof( BentoBox ), 6, 20, 0x2836, 0 ) ); + Add( new GenericBuyInfo( typeof( BentoBox ), 6, 20, 0x2837, 0 ) ); + Add( new GenericBuyInfo( typeof( GreenTeaBasket ), 2, 20, 0x284B, 0 ) ); + }*/ + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(WoodenBowlOfCarrots), 1); + Add(typeof(WoodenBowlOfCorn), 1); + Add(typeof(WoodenBowlOfLettuce), 1); + Add(typeof(WoodenBowlOfPeas), 1); + Add(typeof(EmptyPewterBowl), 1); + Add(typeof(PewterBowlOfCorn), 1); + Add(typeof(PewterBowlOfLettuce), 1); + Add(typeof(PewterBowlOfPeas), 1); + Add(typeof(PewterBowlOfPotatos), 1); + Add(typeof(WoodenBowlOfStew), 1); + Add(typeof(WoodenBowlOfTomatoSoup), 1); + Add(typeof(BeverageBottle), 3); + Add(typeof(Jug), 6); + Add(typeof(Pitcher), 5); + Add(typeof(GlassMug), 1); + Add(typeof(BreadLoaf), 3); + Add(typeof(CheeseWheel), 12); + Add(typeof(Ribs), 6); + Add(typeof(Peach), 1); + Add(typeof(Pear), 1); + Add(typeof(Grapes), 1); + Add(typeof(Apple), 1); + Add(typeof(Banana), 1); + Add(typeof(Candle), 3); + Add(typeof(Chessboard), 1); + Add(typeof(CheckerBoard), 1); + Add(typeof(Backgammon), 1); + Add(typeof(Dices), 1); + Add(typeof(ContractOfEmployment), 626); + } + } } - - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(WoodenBowlOfCarrots), 1); - Add(typeof(WoodenBowlOfCorn), 1); - Add(typeof(WoodenBowlOfLettuce), 1); - Add(typeof(WoodenBowlOfPeas), 1); - Add(typeof(EmptyPewterBowl), 1); - Add(typeof(PewterBowlOfCorn), 1); - Add(typeof(PewterBowlOfLettuce), 1); - Add(typeof(PewterBowlOfPeas), 1); - Add(typeof(PewterBowlOfPotatos), 1); - Add(typeof(WoodenBowlOfStew), 1); - Add(typeof(WoodenBowlOfTomatoSoup), 1); - Add(typeof(BeverageBottle), 3); - Add(typeof(Jug), 6); - Add(typeof(Pitcher), 5); - Add(typeof(GlassMug), 1); - Add(typeof(BreadLoaf), 3); - Add(typeof(CheeseWheel), 12); - Add(typeof(Ribs), 6); - Add(typeof(Peach), 1); - Add(typeof(Pear), 1); - Add(typeof(Grapes), 1); - Add(typeof(Apple), 1); - Add(typeof(Banana), 1); - Add(typeof(Candle), 3); - Add(typeof(Chessboard), 1); - Add(typeof(CheckerBoard), 1); - Add(typeof(Backgammon), 1); - Add(typeof(Dices), 1); - Add(typeof(ContractOfEmployment), 626); - } - } - } } diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBeekeeper.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBeekeeper.cs index 12f86fe2c..b35cd75e1 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBeekeeper.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBeekeeper.cs @@ -3,28 +3,28 @@ using Server.Items; namespace Server.Mobiles { - public class SBBeekeeper : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBBeekeeper : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(JarHoney), 3, 20, 0x9EC, 0)); - Add(new GenericBuyInfo(typeof(Beeswax), 2, 20, 0x1422, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(JarHoney), 1); - Add(typeof(Beeswax), 1); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(JarHoney), 3, 20, 0x9EC, 0)); + Add(new GenericBuyInfo(typeof(Beeswax), 2, 20, 0x1422, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(JarHoney), 1); + Add(typeof(Beeswax), 1); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBlacksmith.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBlacksmith.cs index e28c2200c..f65323c08 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBlacksmith.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBlacksmith.cs @@ -3,223 +3,223 @@ using Server.Items; namespace Server.Mobiles { - public class SBBlacksmith : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBBlacksmith : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(IronIngot), 5, 16, 0x1BF2, 0)); - Add(new GenericBuyInfo(typeof(Tongs), 13, 14, 0xFBB, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - Add(new GenericBuyInfo(typeof(BronzeShield), 66, 20, 0x1B72, 0)); - Add(new GenericBuyInfo(typeof(Buckler), 50, 20, 0x1B73, 0)); - Add(new GenericBuyInfo(typeof(MetalKiteShield), 123, 20, 0x1B74, 0)); - Add(new GenericBuyInfo(typeof(HeaterShield), 231, 20, 0x1B76, 0)); - Add(new GenericBuyInfo(typeof(WoodenKiteShield), 70, 20, 0x1B78, 0)); - Add(new GenericBuyInfo(typeof(MetalShield), 121, 20, 0x1B7B, 0)); + public override List BuyInfo { get; } = new InternalBuyInfo(); - Add(new GenericBuyInfo(typeof(WoodenShield), 30, 20, 0x1B7A, 0)); - - Add(new GenericBuyInfo(typeof(PlateGorget), 104, 20, 0x1413, 0)); - Add(new GenericBuyInfo(typeof(PlateChest), 243, 20, 0x1415, 0)); - Add(new GenericBuyInfo(typeof(PlateLegs), 218, 20, 0x1411, 0)); - Add(new GenericBuyInfo(typeof(PlateArms), 188, 20, 0x1410, 0)); - Add(new GenericBuyInfo(typeof(PlateGloves), 155, 20, 0x1414, 0)); - - Add(new GenericBuyInfo(typeof(PlateHelm), 21, 20, 0x1412, 0)); - Add(new GenericBuyInfo(typeof(CloseHelm), 18, 20, 0x1408, 0)); - Add(new GenericBuyInfo(typeof(CloseHelm), 18, 20, 0x1409, 0)); - Add(new GenericBuyInfo(typeof(Helmet), 31, 20, 0x140A, 0)); - Add(new GenericBuyInfo(typeof(Helmet), 18, 20, 0x140B, 0)); - Add(new GenericBuyInfo(typeof(NorseHelm), 18, 20, 0x140E, 0)); - Add(new GenericBuyInfo(typeof(NorseHelm), 18, 20, 0x140F, 0)); - Add(new GenericBuyInfo(typeof(Bascinet), 18, 20, 0x140C, 0)); - Add(new GenericBuyInfo(typeof(PlateHelm), 21, 20, 0x1419, 0)); - - Add(new GenericBuyInfo(typeof(ChainCoif), 17, 20, 0x13BB, 0)); - Add(new GenericBuyInfo(typeof(ChainChest), 143, 20, 0x13BF, 0)); - Add(new GenericBuyInfo(typeof(ChainLegs), 149, 20, 0x13BE, 0)); - - Add(new GenericBuyInfo(typeof(RingmailChest), 121, 20, 0x13ec, 0)); - Add(new GenericBuyInfo(typeof(RingmailLegs), 90, 20, 0x13F0, 0)); - Add(new GenericBuyInfo(typeof(RingmailArms), 85, 20, 0x13EE, 0)); - Add(new GenericBuyInfo(typeof(RingmailGloves), 93, 20, 0x13eb, 0)); - - Add(new GenericBuyInfo(typeof(ExecutionersAxe), 30, 20, 0xF45, 0)); - Add(new GenericBuyInfo(typeof(Bardiche), 60, 20, 0xF4D, 0)); - Add(new GenericBuyInfo(typeof(BattleAxe), 26, 20, 0xF47, 0)); - Add(new GenericBuyInfo(typeof(TwoHandedAxe), 32, 20, 0x1443, 0)); - Add(new GenericBuyInfo(typeof(Bow), 35, 20, 0x13B2, 0)); - Add(new GenericBuyInfo(typeof(ButcherKnife), 14, 20, 0x13F6, 0)); - Add(new GenericBuyInfo(typeof(Crossbow), 46, 20, 0xF50, 0)); - Add(new GenericBuyInfo(typeof(HeavyCrossbow), 55, 20, 0x13FD, 0)); - Add(new GenericBuyInfo(typeof(Cutlass), 24, 20, 0x1441, 0)); - Add(new GenericBuyInfo(typeof(Dagger), 21, 20, 0xF52, 0)); - Add(new GenericBuyInfo(typeof(Halberd), 42, 20, 0x143E, 0)); - Add(new GenericBuyInfo(typeof(HammerPick), 26, 20, 0x143D, 0)); - Add(new GenericBuyInfo(typeof(Katana), 33, 20, 0x13FF, 0)); - Add(new GenericBuyInfo(typeof(Kryss), 32, 20, 0x1401, 0)); - Add(new GenericBuyInfo(typeof(Broadsword), 35, 20, 0xF5E, 0)); - Add(new GenericBuyInfo(typeof(Longsword), 55, 20, 0xF61, 0)); - Add(new GenericBuyInfo(typeof(ThinLongsword), 27, 20, 0x13B8, 0)); - Add(new GenericBuyInfo(typeof(VikingSword), 55, 20, 0x13B9, 0)); - Add(new GenericBuyInfo(typeof(Cleaver), 15, 20, 0xEC3, 0)); - Add(new GenericBuyInfo(typeof(Axe), 40, 20, 0xF49, 0)); - Add(new GenericBuyInfo(typeof(DoubleAxe), 52, 20, 0xF4B, 0)); - Add(new GenericBuyInfo(typeof(Pickaxe), 22, 20, 0xE86, 0)); - Add(new GenericBuyInfo(typeof(Pitchfork), 19, 20, 0xE87, 0)); - Add(new GenericBuyInfo(typeof(Scimitar), 36, 20, 0x13B6, 0)); - Add(new GenericBuyInfo(typeof(SkinningKnife), 14, 20, 0xEC4, 0)); - Add(new GenericBuyInfo(typeof(LargeBattleAxe), 33, 20, 0x13FB, 0)); - Add(new GenericBuyInfo(typeof(WarAxe), 29, 20, 0x13B0, 0)); - - if (Core.AOS) + public class InternalBuyInfo : List { - Add(new GenericBuyInfo(typeof(BoneHarvester), 35, 20, 0x26BB, 0)); - Add(new GenericBuyInfo(typeof(CrescentBlade), 37, 20, 0x26C1, 0)); - Add(new GenericBuyInfo(typeof(DoubleBladedStaff), 35, 20, 0x26BF, 0)); - Add(new GenericBuyInfo(typeof(Lance), 34, 20, 0x26C0, 0)); - Add(new GenericBuyInfo(typeof(Pike), 39, 20, 0x26BE, 0)); - Add(new GenericBuyInfo(typeof(Scythe), 39, 20, 0x26BA, 0)); - Add(new GenericBuyInfo(typeof(CompositeBow), 50, 20, 0x26C2, 0)); - Add(new GenericBuyInfo(typeof(RepeatingCrossbow), 57, 20, 0x26C3, 0)); + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(IronIngot), 5, 16, 0x1BF2, 0)); + Add(new GenericBuyInfo(typeof(Tongs), 13, 14, 0xFBB, 0)); + + Add(new GenericBuyInfo(typeof(BronzeShield), 66, 20, 0x1B72, 0)); + Add(new GenericBuyInfo(typeof(Buckler), 50, 20, 0x1B73, 0)); + Add(new GenericBuyInfo(typeof(MetalKiteShield), 123, 20, 0x1B74, 0)); + Add(new GenericBuyInfo(typeof(HeaterShield), 231, 20, 0x1B76, 0)); + Add(new GenericBuyInfo(typeof(WoodenKiteShield), 70, 20, 0x1B78, 0)); + Add(new GenericBuyInfo(typeof(MetalShield), 121, 20, 0x1B7B, 0)); + + Add(new GenericBuyInfo(typeof(WoodenShield), 30, 20, 0x1B7A, 0)); + + Add(new GenericBuyInfo(typeof(PlateGorget), 104, 20, 0x1413, 0)); + Add(new GenericBuyInfo(typeof(PlateChest), 243, 20, 0x1415, 0)); + Add(new GenericBuyInfo(typeof(PlateLegs), 218, 20, 0x1411, 0)); + Add(new GenericBuyInfo(typeof(PlateArms), 188, 20, 0x1410, 0)); + Add(new GenericBuyInfo(typeof(PlateGloves), 155, 20, 0x1414, 0)); + + Add(new GenericBuyInfo(typeof(PlateHelm), 21, 20, 0x1412, 0)); + Add(new GenericBuyInfo(typeof(CloseHelm), 18, 20, 0x1408, 0)); + Add(new GenericBuyInfo(typeof(CloseHelm), 18, 20, 0x1409, 0)); + Add(new GenericBuyInfo(typeof(Helmet), 31, 20, 0x140A, 0)); + Add(new GenericBuyInfo(typeof(Helmet), 18, 20, 0x140B, 0)); + Add(new GenericBuyInfo(typeof(NorseHelm), 18, 20, 0x140E, 0)); + Add(new GenericBuyInfo(typeof(NorseHelm), 18, 20, 0x140F, 0)); + Add(new GenericBuyInfo(typeof(Bascinet), 18, 20, 0x140C, 0)); + Add(new GenericBuyInfo(typeof(PlateHelm), 21, 20, 0x1419, 0)); + + Add(new GenericBuyInfo(typeof(ChainCoif), 17, 20, 0x13BB, 0)); + Add(new GenericBuyInfo(typeof(ChainChest), 143, 20, 0x13BF, 0)); + Add(new GenericBuyInfo(typeof(ChainLegs), 149, 20, 0x13BE, 0)); + + Add(new GenericBuyInfo(typeof(RingmailChest), 121, 20, 0x13ec, 0)); + Add(new GenericBuyInfo(typeof(RingmailLegs), 90, 20, 0x13F0, 0)); + Add(new GenericBuyInfo(typeof(RingmailArms), 85, 20, 0x13EE, 0)); + Add(new GenericBuyInfo(typeof(RingmailGloves), 93, 20, 0x13eb, 0)); + + Add(new GenericBuyInfo(typeof(ExecutionersAxe), 30, 20, 0xF45, 0)); + Add(new GenericBuyInfo(typeof(Bardiche), 60, 20, 0xF4D, 0)); + Add(new GenericBuyInfo(typeof(BattleAxe), 26, 20, 0xF47, 0)); + Add(new GenericBuyInfo(typeof(TwoHandedAxe), 32, 20, 0x1443, 0)); + Add(new GenericBuyInfo(typeof(Bow), 35, 20, 0x13B2, 0)); + Add(new GenericBuyInfo(typeof(ButcherKnife), 14, 20, 0x13F6, 0)); + Add(new GenericBuyInfo(typeof(Crossbow), 46, 20, 0xF50, 0)); + Add(new GenericBuyInfo(typeof(HeavyCrossbow), 55, 20, 0x13FD, 0)); + Add(new GenericBuyInfo(typeof(Cutlass), 24, 20, 0x1441, 0)); + Add(new GenericBuyInfo(typeof(Dagger), 21, 20, 0xF52, 0)); + Add(new GenericBuyInfo(typeof(Halberd), 42, 20, 0x143E, 0)); + Add(new GenericBuyInfo(typeof(HammerPick), 26, 20, 0x143D, 0)); + Add(new GenericBuyInfo(typeof(Katana), 33, 20, 0x13FF, 0)); + Add(new GenericBuyInfo(typeof(Kryss), 32, 20, 0x1401, 0)); + Add(new GenericBuyInfo(typeof(Broadsword), 35, 20, 0xF5E, 0)); + Add(new GenericBuyInfo(typeof(Longsword), 55, 20, 0xF61, 0)); + Add(new GenericBuyInfo(typeof(ThinLongsword), 27, 20, 0x13B8, 0)); + Add(new GenericBuyInfo(typeof(VikingSword), 55, 20, 0x13B9, 0)); + Add(new GenericBuyInfo(typeof(Cleaver), 15, 20, 0xEC3, 0)); + Add(new GenericBuyInfo(typeof(Axe), 40, 20, 0xF49, 0)); + Add(new GenericBuyInfo(typeof(DoubleAxe), 52, 20, 0xF4B, 0)); + Add(new GenericBuyInfo(typeof(Pickaxe), 22, 20, 0xE86, 0)); + Add(new GenericBuyInfo(typeof(Pitchfork), 19, 20, 0xE87, 0)); + Add(new GenericBuyInfo(typeof(Scimitar), 36, 20, 0x13B6, 0)); + Add(new GenericBuyInfo(typeof(SkinningKnife), 14, 20, 0xEC4, 0)); + Add(new GenericBuyInfo(typeof(LargeBattleAxe), 33, 20, 0x13FB, 0)); + Add(new GenericBuyInfo(typeof(WarAxe), 29, 20, 0x13B0, 0)); + + if (Core.AOS) + { + Add(new GenericBuyInfo(typeof(BoneHarvester), 35, 20, 0x26BB, 0)); + Add(new GenericBuyInfo(typeof(CrescentBlade), 37, 20, 0x26C1, 0)); + Add(new GenericBuyInfo(typeof(DoubleBladedStaff), 35, 20, 0x26BF, 0)); + Add(new GenericBuyInfo(typeof(Lance), 34, 20, 0x26C0, 0)); + Add(new GenericBuyInfo(typeof(Pike), 39, 20, 0x26BE, 0)); + Add(new GenericBuyInfo(typeof(Scythe), 39, 20, 0x26BA, 0)); + Add(new GenericBuyInfo(typeof(CompositeBow), 50, 20, 0x26C2, 0)); + Add(new GenericBuyInfo(typeof(RepeatingCrossbow), 57, 20, 0x26C3, 0)); + } + + Add(new GenericBuyInfo(typeof(BlackStaff), 22, 20, 0xDF1, 0)); + Add(new GenericBuyInfo(typeof(Club), 16, 20, 0x13B4, 0)); + Add(new GenericBuyInfo(typeof(GnarledStaff), 16, 20, 0x13F8, 0)); + Add(new GenericBuyInfo(typeof(Mace), 28, 20, 0xF5C, 0)); + Add(new GenericBuyInfo(typeof(Maul), 21, 20, 0x143B, 0)); + Add(new GenericBuyInfo(typeof(QuarterStaff), 19, 20, 0xE89, 0)); + Add(new GenericBuyInfo(typeof(ShepherdsCrook), 20, 20, 0xE81, 0)); + Add(new GenericBuyInfo(typeof(SmithHammer), 21, 20, 0x13E3, 0)); + Add(new GenericBuyInfo(typeof(ShortSpear), 23, 20, 0x1403, 0)); + Add(new GenericBuyInfo(typeof(Spear), 31, 20, 0xF62, 0)); + Add(new GenericBuyInfo(typeof(WarHammer), 25, 20, 0x1439, 0)); + Add(new GenericBuyInfo(typeof(WarMace), 31, 20, 0x1407, 0)); + + if (Core.AOS) + { + Add(new GenericBuyInfo(typeof(Scepter), 39, 20, 0x26BC, 0)); + Add(new GenericBuyInfo(typeof(BladedStaff), 40, 20, 0x26BD, 0)); + } + } } - Add(new GenericBuyInfo(typeof(BlackStaff), 22, 20, 0xDF1, 0)); - Add(new GenericBuyInfo(typeof(Club), 16, 20, 0x13B4, 0)); - Add(new GenericBuyInfo(typeof(GnarledStaff), 16, 20, 0x13F8, 0)); - Add(new GenericBuyInfo(typeof(Mace), 28, 20, 0xF5C, 0)); - Add(new GenericBuyInfo(typeof(Maul), 21, 20, 0x143B, 0)); - Add(new GenericBuyInfo(typeof(QuarterStaff), 19, 20, 0xE89, 0)); - Add(new GenericBuyInfo(typeof(ShepherdsCrook), 20, 20, 0xE81, 0)); - Add(new GenericBuyInfo(typeof(SmithHammer), 21, 20, 0x13E3, 0)); - Add(new GenericBuyInfo(typeof(ShortSpear), 23, 20, 0x1403, 0)); - Add(new GenericBuyInfo(typeof(Spear), 31, 20, 0xF62, 0)); - Add(new GenericBuyInfo(typeof(WarHammer), 25, 20, 0x1439, 0)); - Add(new GenericBuyInfo(typeof(WarMace), 31, 20, 0x1407, 0)); - - if (Core.AOS) + public class InternalSellInfo : GenericSellInfo { - Add(new GenericBuyInfo(typeof(Scepter), 39, 20, 0x26BC, 0)); - Add(new GenericBuyInfo(typeof(BladedStaff), 40, 20, 0x26BD, 0)); + public InternalSellInfo() + { + Add(typeof(Tongs), 7); + Add(typeof(IronIngot), 4); + + Add(typeof(Buckler), 25); + Add(typeof(BronzeShield), 33); + Add(typeof(MetalShield), 60); + Add(typeof(MetalKiteShield), 62); + Add(typeof(HeaterShield), 115); + Add(typeof(WoodenKiteShield), 35); + + Add(typeof(WoodenShield), 15); + + Add(typeof(PlateArms), 94); + Add(typeof(PlateChest), 121); + Add(typeof(PlateGloves), 72); + Add(typeof(PlateGorget), 52); + Add(typeof(PlateLegs), 109); + + Add(typeof(FemalePlateChest), 113); + Add(typeof(FemaleLeatherChest), 18); + Add(typeof(FemaleStuddedChest), 25); + Add(typeof(LeatherShorts), 14); + Add(typeof(LeatherSkirt), 11); + Add(typeof(LeatherBustierArms), 11); + Add(typeof(StuddedBustierArms), 27); + + Add(typeof(Bascinet), 9); + Add(typeof(CloseHelm), 9); + Add(typeof(Helmet), 9); + Add(typeof(NorseHelm), 9); + Add(typeof(PlateHelm), 10); + + Add(typeof(ChainCoif), 6); + Add(typeof(ChainChest), 71); + Add(typeof(ChainLegs), 74); + + Add(typeof(RingmailArms), 42); + Add(typeof(RingmailChest), 60); + Add(typeof(RingmailGloves), 26); + Add(typeof(RingmailLegs), 45); + + Add(typeof(BattleAxe), 13); + Add(typeof(DoubleAxe), 26); + Add(typeof(ExecutionersAxe), 15); + Add(typeof(LargeBattleAxe), 16); + Add(typeof(Pickaxe), 11); + Add(typeof(TwoHandedAxe), 16); + Add(typeof(WarAxe), 14); + Add(typeof(Axe), 20); + + Add(typeof(Bardiche), 30); + Add(typeof(Halberd), 21); + + Add(typeof(ButcherKnife), 7); + Add(typeof(Cleaver), 7); + Add(typeof(Dagger), 10); + Add(typeof(SkinningKnife), 7); + + Add(typeof(Club), 8); + Add(typeof(HammerPick), 13); + Add(typeof(Mace), 14); + Add(typeof(Maul), 10); + Add(typeof(WarHammer), 12); + Add(typeof(WarMace), 15); + + Add(typeof(HeavyCrossbow), 27); + Add(typeof(Bow), 17); + Add(typeof(Crossbow), 23); + + if (Core.AOS) + { + Add(typeof(CompositeBow), 25); + Add(typeof(RepeatingCrossbow), 28); + Add(typeof(Scepter), 20); + Add(typeof(BladedStaff), 20); + Add(typeof(Scythe), 19); + Add(typeof(BoneHarvester), 17); + Add(typeof(Scepter), 18); + Add(typeof(BladedStaff), 16); + Add(typeof(Pike), 19); + Add(typeof(DoubleBladedStaff), 17); + Add(typeof(Lance), 17); + Add(typeof(CrescentBlade), 18); + } + + Add(typeof(Spear), 15); + Add(typeof(Pitchfork), 9); + Add(typeof(ShortSpear), 11); + + Add(typeof(BlackStaff), 11); + Add(typeof(GnarledStaff), 8); + Add(typeof(QuarterStaff), 9); + Add(typeof(ShepherdsCrook), 10); + + Add(typeof(SmithHammer), 10); + + Add(typeof(Broadsword), 17); + Add(typeof(Cutlass), 12); + Add(typeof(Katana), 16); + Add(typeof(Kryss), 16); + Add(typeof(Longsword), 27); + Add(typeof(Scimitar), 18); + Add(typeof(ThinLongsword), 13); + Add(typeof(VikingSword), 27); + } } - } } - - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Tongs), 7); - Add(typeof(IronIngot), 4); - - Add(typeof(Buckler), 25); - Add(typeof(BronzeShield), 33); - Add(typeof(MetalShield), 60); - Add(typeof(MetalKiteShield), 62); - Add(typeof(HeaterShield), 115); - Add(typeof(WoodenKiteShield), 35); - - Add(typeof(WoodenShield), 15); - - Add(typeof(PlateArms), 94); - Add(typeof(PlateChest), 121); - Add(typeof(PlateGloves), 72); - Add(typeof(PlateGorget), 52); - Add(typeof(PlateLegs), 109); - - Add(typeof(FemalePlateChest), 113); - Add(typeof(FemaleLeatherChest), 18); - Add(typeof(FemaleStuddedChest), 25); - Add(typeof(LeatherShorts), 14); - Add(typeof(LeatherSkirt), 11); - Add(typeof(LeatherBustierArms), 11); - Add(typeof(StuddedBustierArms), 27); - - Add(typeof(Bascinet), 9); - Add(typeof(CloseHelm), 9); - Add(typeof(Helmet), 9); - Add(typeof(NorseHelm), 9); - Add(typeof(PlateHelm), 10); - - Add(typeof(ChainCoif), 6); - Add(typeof(ChainChest), 71); - Add(typeof(ChainLegs), 74); - - Add(typeof(RingmailArms), 42); - Add(typeof(RingmailChest), 60); - Add(typeof(RingmailGloves), 26); - Add(typeof(RingmailLegs), 45); - - Add(typeof(BattleAxe), 13); - Add(typeof(DoubleAxe), 26); - Add(typeof(ExecutionersAxe), 15); - Add(typeof(LargeBattleAxe), 16); - Add(typeof(Pickaxe), 11); - Add(typeof(TwoHandedAxe), 16); - Add(typeof(WarAxe), 14); - Add(typeof(Axe), 20); - - Add(typeof(Bardiche), 30); - Add(typeof(Halberd), 21); - - Add(typeof(ButcherKnife), 7); - Add(typeof(Cleaver), 7); - Add(typeof(Dagger), 10); - Add(typeof(SkinningKnife), 7); - - Add(typeof(Club), 8); - Add(typeof(HammerPick), 13); - Add(typeof(Mace), 14); - Add(typeof(Maul), 10); - Add(typeof(WarHammer), 12); - Add(typeof(WarMace), 15); - - Add(typeof(HeavyCrossbow), 27); - Add(typeof(Bow), 17); - Add(typeof(Crossbow), 23); - - if (Core.AOS) - { - Add(typeof(CompositeBow), 25); - Add(typeof(RepeatingCrossbow), 28); - Add(typeof(Scepter), 20); - Add(typeof(BladedStaff), 20); - Add(typeof(Scythe), 19); - Add(typeof(BoneHarvester), 17); - Add(typeof(Scepter), 18); - Add(typeof(BladedStaff), 16); - Add(typeof(Pike), 19); - Add(typeof(DoubleBladedStaff), 17); - Add(typeof(Lance), 17); - Add(typeof(CrescentBlade), 18); - } - - Add(typeof(Spear), 15); - Add(typeof(Pitchfork), 9); - Add(typeof(ShortSpear), 11); - - Add(typeof(BlackStaff), 11); - Add(typeof(GnarledStaff), 8); - Add(typeof(QuarterStaff), 9); - Add(typeof(ShepherdsCrook), 10); - - Add(typeof(SmithHammer), 10); - - Add(typeof(Broadsword), 17); - Add(typeof(Cutlass), 12); - Add(typeof(Katana), 16); - Add(typeof(Kryss), 16); - Add(typeof(Longsword), 27); - Add(typeof(Scimitar), 18); - Add(typeof(ThinLongsword), 13); - Add(typeof(VikingSword), 27); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBowyer.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBowyer.cs index 340154b95..bd7a48fe0 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBowyer.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBBowyer.cs @@ -3,26 +3,26 @@ using Server.Items; namespace Server.Mobiles { - public class SBBowyer : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBBowyer : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(FletcherTools), 2, 20, 0x1022, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(FletcherTools), 1); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(FletcherTools), 2, 20, 0x1022, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(FletcherTools), 1); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBButcher.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBButcher.cs index bf0a4fcfe..dc18659e5 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBButcher.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBButcher.cs @@ -3,44 +3,44 @@ using Server.Items; namespace Server.Mobiles { - public class SBButcher : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBButcher : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Bacon), 7, 20, 0x979, 0)); - Add(new GenericBuyInfo(typeof(Ham), 26, 20, 0x9C9, 0)); - Add(new GenericBuyInfo(typeof(Sausage), 18, 20, 0x9C0, 0)); - Add(new GenericBuyInfo(typeof(RawChickenLeg), 6, 20, 0x1607, 0)); - Add(new GenericBuyInfo(typeof(RawBird), 9, 20, 0x9B9, 0)); - Add(new GenericBuyInfo(typeof(RawLambLeg), 9, 20, 0x1609, 0)); - Add(new GenericBuyInfo(typeof(RawRibs), 16, 20, 0x9F1, 0)); - Add(new GenericBuyInfo(typeof(ButcherKnife), 13, 20, 0x13F6, 0)); - Add(new GenericBuyInfo(typeof(Cleaver), 13, 20, 0xEC3, 0)); - Add(new GenericBuyInfo(typeof(SkinningKnife), 13, 20, 0xEC4, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(RawRibs), 8); - Add(typeof(RawLambLeg), 4); - Add(typeof(RawChickenLeg), 3); - Add(typeof(RawBird), 4); - Add(typeof(Bacon), 3); - Add(typeof(Sausage), 9); - Add(typeof(Ham), 13); - Add(typeof(ButcherKnife), 7); - Add(typeof(Cleaver), 7); - Add(typeof(SkinningKnife), 7); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Bacon), 7, 20, 0x979, 0)); + Add(new GenericBuyInfo(typeof(Ham), 26, 20, 0x9C9, 0)); + Add(new GenericBuyInfo(typeof(Sausage), 18, 20, 0x9C0, 0)); + Add(new GenericBuyInfo(typeof(RawChickenLeg), 6, 20, 0x1607, 0)); + Add(new GenericBuyInfo(typeof(RawBird), 9, 20, 0x9B9, 0)); + Add(new GenericBuyInfo(typeof(RawLambLeg), 9, 20, 0x1609, 0)); + Add(new GenericBuyInfo(typeof(RawRibs), 16, 20, 0x9F1, 0)); + Add(new GenericBuyInfo(typeof(ButcherKnife), 13, 20, 0x13F6, 0)); + Add(new GenericBuyInfo(typeof(Cleaver), 13, 20, 0xEC3, 0)); + Add(new GenericBuyInfo(typeof(SkinningKnife), 13, 20, 0xEC4, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(RawRibs), 8); + Add(typeof(RawLambLeg), 4); + Add(typeof(RawChickenLeg), 3); + Add(typeof(RawBird), 4); + Add(typeof(Bacon), 3); + Add(typeof(Sausage), 9); + Add(typeof(Ham), 13); + Add(typeof(ButcherKnife), 7); + Add(typeof(Cleaver), 7); + Add(typeof(SkinningKnife), 7); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBCarpenter.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBCarpenter.cs index 530128383..2be18aecc 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBCarpenter.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBCarpenter.cs @@ -3,83 +3,83 @@ using Server.Items; namespace Server.Mobiles { - public class SBCarpenter : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBCarpenter : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Nails), 3, 20, 0x102E, 0)); - Add(new GenericBuyInfo(typeof(Axle), 2, 20, 0x105B, 0)); - Add(new GenericBuyInfo(typeof(Board), 3, 20, 0x1BD7, 0)); - Add(new GenericBuyInfo(typeof(DrawKnife), 10, 20, 0x10E4, 0)); - Add(new GenericBuyInfo(typeof(Froe), 10, 20, 0x10E5, 0)); - Add(new GenericBuyInfo(typeof(Scorp), 10, 20, 0x10E7, 0)); - Add(new GenericBuyInfo(typeof(Inshave), 10, 20, 0x10E6, 0)); - Add(new GenericBuyInfo(typeof(DovetailSaw), 12, 20, 0x1028, 0)); - Add(new GenericBuyInfo(typeof(Saw), 15, 20, 0x1034, 0)); - Add(new GenericBuyInfo(typeof(Hammer), 17, 20, 0x102A, 0)); - Add(new GenericBuyInfo(typeof(MouldingPlane), 11, 20, 0x102C, 0)); - Add(new GenericBuyInfo(typeof(SmoothingPlane), 10, 20, 0x1032, 0)); - Add(new GenericBuyInfo(typeof(JointingPlane), 11, 20, 0x1030, 0)); - Add(new GenericBuyInfo(typeof(Drums), 21, 20, 0xE9C, 0)); - Add(new GenericBuyInfo(typeof(Tambourine), 21, 20, 0xE9D, 0)); - Add(new GenericBuyInfo(typeof(LapHarp), 21, 20, 0xEB2, 0)); - Add(new GenericBuyInfo(typeof(Lute), 21, 20, 0xEB3, 0)); - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); + + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Nails), 3, 20, 0x102E, 0)); + Add(new GenericBuyInfo(typeof(Axle), 2, 20, 0x105B, 0)); + Add(new GenericBuyInfo(typeof(Board), 3, 20, 0x1BD7, 0)); + Add(new GenericBuyInfo(typeof(DrawKnife), 10, 20, 0x10E4, 0)); + Add(new GenericBuyInfo(typeof(Froe), 10, 20, 0x10E5, 0)); + Add(new GenericBuyInfo(typeof(Scorp), 10, 20, 0x10E7, 0)); + Add(new GenericBuyInfo(typeof(Inshave), 10, 20, 0x10E6, 0)); + Add(new GenericBuyInfo(typeof(DovetailSaw), 12, 20, 0x1028, 0)); + Add(new GenericBuyInfo(typeof(Saw), 15, 20, 0x1034, 0)); + Add(new GenericBuyInfo(typeof(Hammer), 17, 20, 0x102A, 0)); + Add(new GenericBuyInfo(typeof(MouldingPlane), 11, 20, 0x102C, 0)); + Add(new GenericBuyInfo(typeof(SmoothingPlane), 10, 20, 0x1032, 0)); + Add(new GenericBuyInfo(typeof(JointingPlane), 11, 20, 0x1030, 0)); + Add(new GenericBuyInfo(typeof(Drums), 21, 20, 0xE9C, 0)); + Add(new GenericBuyInfo(typeof(Tambourine), 21, 20, 0xE9D, 0)); + Add(new GenericBuyInfo(typeof(LapHarp), 21, 20, 0xEB2, 0)); + Add(new GenericBuyInfo(typeof(Lute), 21, 20, 0xEB3, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(WoodenBox), 7); + Add(typeof(SmallCrate), 5); + Add(typeof(MediumCrate), 6); + Add(typeof(LargeCrate), 7); + Add(typeof(WoodenChest), 15); + + Add(typeof(LargeTable), 10); + Add(typeof(Nightstand), 7); + Add(typeof(YewWoodTable), 10); + + Add(typeof(Throne), 24); + Add(typeof(WoodenThrone), 6); + Add(typeof(Stool), 6); + Add(typeof(FootStool), 6); + + Add(typeof(FancyWoodenChairCushion), 12); + Add(typeof(WoodenChairCushion), 10); + Add(typeof(WoodenChair), 8); + Add(typeof(BambooChair), 6); + Add(typeof(WoodenBench), 6); + + Add(typeof(Saw), 9); + Add(typeof(Scorp), 6); + Add(typeof(SmoothingPlane), 6); + Add(typeof(DrawKnife), 6); + Add(typeof(Froe), 6); + Add(typeof(Hammer), 14); + Add(typeof(Inshave), 6); + Add(typeof(JointingPlane), 6); + Add(typeof(MouldingPlane), 6); + Add(typeof(DovetailSaw), 7); + Add(typeof(Board), 2); + Add(typeof(Axle), 1); + + Add(typeof(Club), 13); + + Add(typeof(Lute), 10); + Add(typeof(LapHarp), 10); + Add(typeof(Tambourine), 10); + Add(typeof(Drums), 10); + + Add(typeof(Log), 1); + } + } } - - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(WoodenBox), 7); - Add(typeof(SmallCrate), 5); - Add(typeof(MediumCrate), 6); - Add(typeof(LargeCrate), 7); - Add(typeof(WoodenChest), 15); - - Add(typeof(LargeTable), 10); - Add(typeof(Nightstand), 7); - Add(typeof(YewWoodTable), 10); - - Add(typeof(Throne), 24); - Add(typeof(WoodenThrone), 6); - Add(typeof(Stool), 6); - Add(typeof(FootStool), 6); - - Add(typeof(FancyWoodenChairCushion), 12); - Add(typeof(WoodenChairCushion), 10); - Add(typeof(WoodenChair), 8); - Add(typeof(BambooChair), 6); - Add(typeof(WoodenBench), 6); - - Add(typeof(Saw), 9); - Add(typeof(Scorp), 6); - Add(typeof(SmoothingPlane), 6); - Add(typeof(DrawKnife), 6); - Add(typeof(Froe), 6); - Add(typeof(Hammer), 14); - Add(typeof(Inshave), 6); - Add(typeof(JointingPlane), 6); - Add(typeof(MouldingPlane), 6); - Add(typeof(DovetailSaw), 7); - Add(typeof(Board), 2); - Add(typeof(Axle), 1); - - Add(typeof(Club), 13); - - Add(typeof(Lute), 10); - Add(typeof(LapHarp), 10); - Add(typeof(Tambourine), 10); - Add(typeof(Drums), 10); - - Add(typeof(Log), 1); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBCobbler.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBCobbler.cs index 713f4d41c..de7e1b59d 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBCobbler.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBCobbler.cs @@ -3,32 +3,32 @@ using Server.Items; namespace Server.Mobiles { - public class SBCobbler : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBCobbler : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(ThighBoots), 15, 20, 0x1711, Utility.RandomNeutralHue())); - Add(new GenericBuyInfo(typeof(Shoes), 8, 20, 0x170f, Utility.RandomNeutralHue())); - Add(new GenericBuyInfo(typeof(Boots), 10, 20, 0x170b, Utility.RandomNeutralHue())); - Add(new GenericBuyInfo(typeof(Sandals), 5, 20, 0x170d, Utility.RandomNeutralHue())); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Shoes), 4); - Add(typeof(Boots), 5); - Add(typeof(ThighBoots), 7); - Add(typeof(Sandals), 2); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(ThighBoots), 15, 20, 0x1711, Utility.RandomNeutralHue())); + Add(new GenericBuyInfo(typeof(Shoes), 8, 20, 0x170f, Utility.RandomNeutralHue())); + Add(new GenericBuyInfo(typeof(Boots), 10, 20, 0x170b, Utility.RandomNeutralHue())); + Add(new GenericBuyInfo(typeof(Sandals), 5, 20, 0x170d, Utility.RandomNeutralHue())); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Shoes), 4); + Add(typeof(Boots), 5); + Add(typeof(ThighBoots), 7); + Add(typeof(Sandals), 2); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBCook.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBCook.cs index 2cd960046..c33304de2 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBCook.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBCook.cs @@ -3,79 +3,79 @@ using Server.Items; namespace Server.Mobiles { - public class SBCook : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBCook : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(BreadLoaf), 5, 20, 0x103B, 0)); - Add(new GenericBuyInfo(typeof(BreadLoaf), 5, 20, 0x103C, 0)); - Add(new GenericBuyInfo(typeof(ApplePie), 7, 20, 0x1041, 0)); // OSI just has Pie, not Apple/Fruit/Meat - Add(new GenericBuyInfo(typeof(Cake), 13, 20, 0x9E9, 0)); - Add(new GenericBuyInfo(typeof(Muffins), 3, 20, 0x9EA, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - Add(new GenericBuyInfo(typeof(CheeseWheel), 21, 10, 0x97E, 0)); - Add(new GenericBuyInfo(typeof(CookedBird), 17, 20, 0x9B7, 0)); - Add(new GenericBuyInfo(typeof(LambLeg), 8, 20, 0x160A, 0)); - Add(new GenericBuyInfo(typeof(ChickenLeg), 5, 20, 0x1608, 0)); + public override List BuyInfo { get; } = new InternalBuyInfo(); - Add(new GenericBuyInfo(typeof(WoodenBowlOfCarrots), 3, 20, 0x15F9, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfCorn), 3, 20, 0x15FA, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfLettuce), 3, 20, 0x15FB, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfPeas), 3, 20, 0x15FC, 0)); - Add(new GenericBuyInfo(typeof(EmptyPewterBowl), 2, 20, 0x15FD, 0)); - Add(new GenericBuyInfo(typeof(PewterBowlOfCorn), 3, 20, 0x15FE, 0)); - Add(new GenericBuyInfo(typeof(PewterBowlOfLettuce), 3, 20, 0x15FF, 0)); - Add(new GenericBuyInfo(typeof(PewterBowlOfPeas), 3, 20, 0x1600, 0)); - Add(new GenericBuyInfo(typeof(PewterBowlOfPotatos), 3, 20, 0x1601, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfStew), 3, 20, 0x1604, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfTomatoSoup), 3, 20, 0x1606, 0)); + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(BreadLoaf), 5, 20, 0x103B, 0)); + Add(new GenericBuyInfo(typeof(BreadLoaf), 5, 20, 0x103C, 0)); + Add(new GenericBuyInfo(typeof(ApplePie), 7, 20, 0x1041, 0)); // OSI just has Pie, not Apple/Fruit/Meat + Add(new GenericBuyInfo(typeof(Cake), 13, 20, 0x9E9, 0)); + Add(new GenericBuyInfo(typeof(Muffins), 3, 20, 0x9EA, 0)); - Add(new GenericBuyInfo(typeof(RoastPig), 106, 20, 0x9BB, 0)); - Add(new GenericBuyInfo(typeof(SackFlour), 3, 20, 0x1039, 0)); - Add(new GenericBuyInfo(typeof(JarHoney), 3, 20, 0x9EC, 0)); - Add(new GenericBuyInfo(typeof(RollingPin), 2, 20, 0x1043, 0)); - Add(new GenericBuyInfo(typeof(FlourSifter), 2, 20, 0x103E, 0)); - Add(new GenericBuyInfo("1044567", typeof(Skillet), 3, 20, 0x97F, 0)); - } + Add(new GenericBuyInfo(typeof(CheeseWheel), 21, 10, 0x97E, 0)); + Add(new GenericBuyInfo(typeof(CookedBird), 17, 20, 0x9B7, 0)); + Add(new GenericBuyInfo(typeof(LambLeg), 8, 20, 0x160A, 0)); + Add(new GenericBuyInfo(typeof(ChickenLeg), 5, 20, 0x1608, 0)); + + Add(new GenericBuyInfo(typeof(WoodenBowlOfCarrots), 3, 20, 0x15F9, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfCorn), 3, 20, 0x15FA, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfLettuce), 3, 20, 0x15FB, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfPeas), 3, 20, 0x15FC, 0)); + Add(new GenericBuyInfo(typeof(EmptyPewterBowl), 2, 20, 0x15FD, 0)); + Add(new GenericBuyInfo(typeof(PewterBowlOfCorn), 3, 20, 0x15FE, 0)); + Add(new GenericBuyInfo(typeof(PewterBowlOfLettuce), 3, 20, 0x15FF, 0)); + Add(new GenericBuyInfo(typeof(PewterBowlOfPeas), 3, 20, 0x1600, 0)); + Add(new GenericBuyInfo(typeof(PewterBowlOfPotatos), 3, 20, 0x1601, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfStew), 3, 20, 0x1604, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfTomatoSoup), 3, 20, 0x1606, 0)); + + Add(new GenericBuyInfo(typeof(RoastPig), 106, 20, 0x9BB, 0)); + Add(new GenericBuyInfo(typeof(SackFlour), 3, 20, 0x1039, 0)); + Add(new GenericBuyInfo(typeof(JarHoney), 3, 20, 0x9EC, 0)); + Add(new GenericBuyInfo(typeof(RollingPin), 2, 20, 0x1043, 0)); + Add(new GenericBuyInfo(typeof(FlourSifter), 2, 20, 0x103E, 0)); + Add(new GenericBuyInfo("1044567", typeof(Skillet), 3, 20, 0x97F, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(CheeseWheel), 12); + Add(typeof(CookedBird), 8); + Add(typeof(RoastPig), 53); + Add(typeof(Cake), 5); + Add(typeof(JarHoney), 1); + Add(typeof(SackFlour), 1); + Add(typeof(BreadLoaf), 2); + Add(typeof(ChickenLeg), 3); + Add(typeof(LambLeg), 4); + Add(typeof(Skillet), 1); + Add(typeof(FlourSifter), 1); + Add(typeof(RollingPin), 1); + Add(typeof(Muffins), 1); + Add(typeof(ApplePie), 3); + + Add(typeof(WoodenBowlOfCarrots), 1); + Add(typeof(WoodenBowlOfCorn), 1); + Add(typeof(WoodenBowlOfLettuce), 1); + Add(typeof(WoodenBowlOfPeas), 1); + Add(typeof(EmptyPewterBowl), 1); + Add(typeof(PewterBowlOfCorn), 1); + Add(typeof(PewterBowlOfLettuce), 1); + Add(typeof(PewterBowlOfPeas), 1); + Add(typeof(PewterBowlOfPotatos), 1); + Add(typeof(WoodenBowlOfStew), 1); + Add(typeof(WoodenBowlOfTomatoSoup), 1); + } + } } - - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(CheeseWheel), 12); - Add(typeof(CookedBird), 8); - Add(typeof(RoastPig), 53); - Add(typeof(Cake), 5); - Add(typeof(JarHoney), 1); - Add(typeof(SackFlour), 1); - Add(typeof(BreadLoaf), 2); - Add(typeof(ChickenLeg), 3); - Add(typeof(LambLeg), 4); - Add(typeof(Skillet), 1); - Add(typeof(FlourSifter), 1); - Add(typeof(RollingPin), 1); - Add(typeof(Muffins), 1); - Add(typeof(ApplePie), 3); - - Add(typeof(WoodenBowlOfCarrots), 1); - Add(typeof(WoodenBowlOfCorn), 1); - Add(typeof(WoodenBowlOfLettuce), 1); - Add(typeof(WoodenBowlOfPeas), 1); - Add(typeof(EmptyPewterBowl), 1); - Add(typeof(PewterBowlOfCorn), 1); - Add(typeof(PewterBowlOfLettuce), 1); - Add(typeof(PewterBowlOfPeas), 1); - Add(typeof(PewterBowlOfPotatos), 1); - Add(typeof(WoodenBowlOfStew), 1); - Add(typeof(WoodenBowlOfTomatoSoup), 1); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBFarmer.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBFarmer.cs index 17abb0a99..9161490aa 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBFarmer.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBFarmer.cs @@ -3,66 +3,66 @@ using Server.Items; namespace Server.Mobiles { - public class SBFarmer : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBFarmer : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Cabbage), 5, 20, 0xC7B, 0)); - Add(new GenericBuyInfo(typeof(Cantaloupe), 6, 20, 0xC79, 0)); - Add(new GenericBuyInfo(typeof(Carrot), 3, 20, 0xC78, 0)); - Add(new GenericBuyInfo(typeof(HoneydewMelon), 7, 20, 0xC74, 0)); - Add(new GenericBuyInfo(typeof(Squash), 3, 20, 0xC72, 0)); - Add(new GenericBuyInfo(typeof(Lettuce), 5, 20, 0xC70, 0)); - Add(new GenericBuyInfo(typeof(Onion), 3, 20, 0xC6D, 0)); - Add(new GenericBuyInfo(typeof(Pumpkin), 11, 20, 0xC6A, 0)); - Add(new GenericBuyInfo(typeof(GreenGourd), 3, 20, 0xC66, 0)); - Add(new GenericBuyInfo(typeof(YellowGourd), 3, 20, 0xC64, 0)); - // Add( new GenericBuyInfo( typeof( Turnip ), 6, 20, XXXXXX, 0 ) ); - Add(new GenericBuyInfo(typeof(Watermelon), 7, 20, 0xC5C, 0)); - // Add( new GenericBuyInfo( typeof( EarOfCorn ), 3, 20, XXXXXX, 0 ) ); - Add(new GenericBuyInfo(typeof(Eggs), 3, 20, 0x9B5, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Milk, 7, 20, 0x9AD, 0)); - Add(new GenericBuyInfo(typeof(Peach), 3, 20, 0x9D2, 0)); - Add(new GenericBuyInfo(typeof(Pear), 3, 20, 0x994, 0)); - Add(new GenericBuyInfo(typeof(Lemon), 3, 20, 0x1728, 0)); - Add(new GenericBuyInfo(typeof(Lime), 3, 20, 0x172A, 0)); - Add(new GenericBuyInfo(typeof(Grapes), 3, 20, 0x9D1, 0)); - Add(new GenericBuyInfo(typeof(Apple), 3, 20, 0x9D0, 0)); - Add(new GenericBuyInfo(typeof(SheafOfHay), 2, 20, 0xF36, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Pitcher), 5); - Add(typeof(Eggs), 1); - Add(typeof(Apple), 1); - Add(typeof(Grapes), 1); - Add(typeof(Watermelon), 3); - Add(typeof(YellowGourd), 1); - Add(typeof(GreenGourd), 1); - Add(typeof(Pumpkin), 5); - Add(typeof(Onion), 1); - Add(typeof(Lettuce), 2); - Add(typeof(Squash), 1); - Add(typeof(Carrot), 1); - Add(typeof(HoneydewMelon), 3); - Add(typeof(Cantaloupe), 3); - Add(typeof(Cabbage), 2); - Add(typeof(Lemon), 1); - Add(typeof(Lime), 1); - Add(typeof(Peach), 1); - Add(typeof(Pear), 1); - Add(typeof(SheafOfHay), 1); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Cabbage), 5, 20, 0xC7B, 0)); + Add(new GenericBuyInfo(typeof(Cantaloupe), 6, 20, 0xC79, 0)); + Add(new GenericBuyInfo(typeof(Carrot), 3, 20, 0xC78, 0)); + Add(new GenericBuyInfo(typeof(HoneydewMelon), 7, 20, 0xC74, 0)); + Add(new GenericBuyInfo(typeof(Squash), 3, 20, 0xC72, 0)); + Add(new GenericBuyInfo(typeof(Lettuce), 5, 20, 0xC70, 0)); + Add(new GenericBuyInfo(typeof(Onion), 3, 20, 0xC6D, 0)); + Add(new GenericBuyInfo(typeof(Pumpkin), 11, 20, 0xC6A, 0)); + Add(new GenericBuyInfo(typeof(GreenGourd), 3, 20, 0xC66, 0)); + Add(new GenericBuyInfo(typeof(YellowGourd), 3, 20, 0xC64, 0)); + // Add( new GenericBuyInfo( typeof( Turnip ), 6, 20, XXXXXX, 0 ) ); + Add(new GenericBuyInfo(typeof(Watermelon), 7, 20, 0xC5C, 0)); + // Add( new GenericBuyInfo( typeof( EarOfCorn ), 3, 20, XXXXXX, 0 ) ); + Add(new GenericBuyInfo(typeof(Eggs), 3, 20, 0x9B5, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Milk, 7, 20, 0x9AD, 0)); + Add(new GenericBuyInfo(typeof(Peach), 3, 20, 0x9D2, 0)); + Add(new GenericBuyInfo(typeof(Pear), 3, 20, 0x994, 0)); + Add(new GenericBuyInfo(typeof(Lemon), 3, 20, 0x1728, 0)); + Add(new GenericBuyInfo(typeof(Lime), 3, 20, 0x172A, 0)); + Add(new GenericBuyInfo(typeof(Grapes), 3, 20, 0x9D1, 0)); + Add(new GenericBuyInfo(typeof(Apple), 3, 20, 0x9D0, 0)); + Add(new GenericBuyInfo(typeof(SheafOfHay), 2, 20, 0xF36, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Pitcher), 5); + Add(typeof(Eggs), 1); + Add(typeof(Apple), 1); + Add(typeof(Grapes), 1); + Add(typeof(Watermelon), 3); + Add(typeof(YellowGourd), 1); + Add(typeof(GreenGourd), 1); + Add(typeof(Pumpkin), 5); + Add(typeof(Onion), 1); + Add(typeof(Lettuce), 2); + Add(typeof(Squash), 1); + Add(typeof(Carrot), 1); + Add(typeof(HoneydewMelon), 3); + Add(typeof(Cantaloupe), 3); + Add(typeof(Cabbage), 2); + Add(typeof(Lemon), 1); + Add(typeof(Lime), 1); + Add(typeof(Peach), 1); + Add(typeof(Pear), 1); + Add(typeof(SheafOfHay), 1); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBFisherman.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBFisherman.cs index 34108dbb3..77448c93e 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBFisherman.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBFisherman.cs @@ -3,44 +3,44 @@ using Server.Items; namespace Server.Mobiles { - public class SBFisherman : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBFisherman : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(RawFishSteak), 3, 20, 0x97A, 0)); - // TODO: Add( new GenericBuyInfo( typeof( SmallFish ), 3, 20, 0xDD6, 0 ) ); - // TODO: Add( new GenericBuyInfo( typeof( SmallFish ), 3, 20, 0xDD7, 0 ) ); - Add(new GenericBuyInfo(typeof(Fish), 6, 80, 0x9CC, 0)); - Add(new GenericBuyInfo(typeof(Fish), 6, 80, 0x9CD, 0)); - Add(new GenericBuyInfo(typeof(Fish), 6, 80, 0x9CE, 0)); - Add(new GenericBuyInfo(typeof(Fish), 6, 80, 0x9CF, 0)); - Add(new GenericBuyInfo(typeof(FishingPole), 15, 20, 0xDC0, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - Add(new GenericBuyInfo(typeof(AquariumFishNet), 250, 20, 0xDC8, 0x240)); - Add(new GenericBuyInfo(typeof(AquariumFood), 62, 20, 0xEFC, 0)); - Add(new GenericBuyInfo(typeof(FishBowl), 6312, 20, 0x241C, 0x482)); - Add(new GenericBuyInfo(typeof(VacationWafer), 67, 20, 0x971, 0)); - Add(new GenericBuyInfo(typeof(AquariumNorthDeed), 250002, 20, 0x14F0, 0)); - Add(new GenericBuyInfo(typeof(AquariumEastDeed), 250002, 20, 0x14F0, 0)); - Add(new GenericBuyInfo(typeof(NewAquariumBook), 15, 20, 0xFF2, 0)); - } - } + public override List BuyInfo { get; } = new InternalBuyInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(RawFishSteak), 1); - Add(typeof(Fish), 1); - // TODO: Add( typeof( SmallFish ), 1 ); - Add(typeof(FishingPole), 7); - } + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(RawFishSteak), 3, 20, 0x97A, 0)); + // TODO: Add( new GenericBuyInfo( typeof( SmallFish ), 3, 20, 0xDD6, 0 ) ); + // TODO: Add( new GenericBuyInfo( typeof( SmallFish ), 3, 20, 0xDD7, 0 ) ); + Add(new GenericBuyInfo(typeof(Fish), 6, 80, 0x9CC, 0)); + Add(new GenericBuyInfo(typeof(Fish), 6, 80, 0x9CD, 0)); + Add(new GenericBuyInfo(typeof(Fish), 6, 80, 0x9CE, 0)); + Add(new GenericBuyInfo(typeof(Fish), 6, 80, 0x9CF, 0)); + Add(new GenericBuyInfo(typeof(FishingPole), 15, 20, 0xDC0, 0)); + + Add(new GenericBuyInfo(typeof(AquariumFishNet), 250, 20, 0xDC8, 0x240)); + Add(new GenericBuyInfo(typeof(AquariumFood), 62, 20, 0xEFC, 0)); + Add(new GenericBuyInfo(typeof(FishBowl), 6312, 20, 0x241C, 0x482)); + Add(new GenericBuyInfo(typeof(VacationWafer), 67, 20, 0x971, 0)); + Add(new GenericBuyInfo(typeof(AquariumNorthDeed), 250002, 20, 0x14F0, 0)); + Add(new GenericBuyInfo(typeof(AquariumEastDeed), 250002, 20, 0x14F0, 0)); + Add(new GenericBuyInfo(typeof(NewAquariumBook), 15, 20, 0xFF2, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(RawFishSteak), 1); + Add(typeof(Fish), 1); + // TODO: Add( typeof( SmallFish ), 1 ); + Add(typeof(FishingPole), 7); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBFortuneTeller.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBFortuneTeller.cs index 6e8a5ed35..ab0e288de 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBFortuneTeller.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBFortuneTeller.cs @@ -3,26 +3,26 @@ using Server.Items; namespace Server.Mobiles { - public class SBFortuneTeller : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBFortuneTeller : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Bandage), 5, 20, 0xE21, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Bandage), 1); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Bandage), 5, 20, 0xE21, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Bandage), 1); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBFurtrader.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBFurtrader.cs index e0e3ca6b5..bea64807e 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBFurtrader.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBFurtrader.cs @@ -3,26 +3,26 @@ using Server.Items; namespace Server.Mobiles { - public class SBFurtrader : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBFurtrader : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Hides), 3, 40, 0x1079, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Hides), 2); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Hides), 3, 40, 0x1079, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Hides), 2); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBGlassblower.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBGlassblower.cs index b52ac0ab7..b7513a061 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBGlassblower.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBGlassblower.cs @@ -3,74 +3,74 @@ using Server.Items; namespace Server.Mobiles { - public class SBGlassblower : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBGlassblower : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(RefreshPotion), 15, 10, 0xF0B, 0)); - Add(new GenericBuyInfo(typeof(AgilityPotion), 15, 10, 0xF08, 0)); - Add(new GenericBuyInfo(typeof(NightSightPotion), 15, 10, 0xF06, 0)); - Add(new GenericBuyInfo(typeof(LesserHealPotion), 15, 10, 0xF0C, 0)); - Add(new GenericBuyInfo(typeof(StrengthPotion), 15, 10, 0xF09, 0)); - Add(new GenericBuyInfo(typeof(LesserPoisonPotion), 15, 10, 0xF0A, 0)); - Add(new GenericBuyInfo(typeof(LesserCurePotion), 15, 10, 0xF07, 0)); - Add(new GenericBuyInfo(typeof(LesserExplosionPotion), 21, 10, 0xF0D, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - Add(new GenericBuyInfo(typeof(MortarPestle), 8, 10, 0xE9B, 0)); + public override List BuyInfo { get; } = new InternalBuyInfo(); - Add(new GenericBuyInfo(typeof(BlackPearl), 5, 20, 0xF7A, 0)); - Add(new GenericBuyInfo(typeof(Bloodmoss), 5, 20, 0xF7B, 0)); - Add(new GenericBuyInfo(typeof(Garlic), 3, 20, 0xF84, 0)); - Add(new GenericBuyInfo(typeof(Ginseng), 3, 20, 0xF85, 0)); - Add(new GenericBuyInfo(typeof(MandrakeRoot), 3, 20, 0xF86, 0)); - Add(new GenericBuyInfo(typeof(Nightshade), 3, 20, 0xF88, 0)); - Add(new GenericBuyInfo(typeof(SpidersSilk), 3, 20, 0xF8D, 0)); - Add(new GenericBuyInfo(typeof(SulfurousAsh), 3, 20, 0xF8C, 0)); + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(RefreshPotion), 15, 10, 0xF0B, 0)); + Add(new GenericBuyInfo(typeof(AgilityPotion), 15, 10, 0xF08, 0)); + Add(new GenericBuyInfo(typeof(NightSightPotion), 15, 10, 0xF06, 0)); + Add(new GenericBuyInfo(typeof(LesserHealPotion), 15, 10, 0xF0C, 0)); + Add(new GenericBuyInfo(typeof(StrengthPotion), 15, 10, 0xF09, 0)); + Add(new GenericBuyInfo(typeof(LesserPoisonPotion), 15, 10, 0xF0A, 0)); + Add(new GenericBuyInfo(typeof(LesserCurePotion), 15, 10, 0xF07, 0)); + Add(new GenericBuyInfo(typeof(LesserExplosionPotion), 21, 10, 0xF0D, 0)); - Add(new GenericBuyInfo(typeof(Bottle), 5, 100, 0xF0E, 0)); + Add(new GenericBuyInfo(typeof(MortarPestle), 8, 10, 0xE9B, 0)); - Add(new GenericBuyInfo(typeof(HeatingStand), 2, 100, 0x1849, 0)); + Add(new GenericBuyInfo(typeof(BlackPearl), 5, 20, 0xF7A, 0)); + Add(new GenericBuyInfo(typeof(Bloodmoss), 5, 20, 0xF7B, 0)); + Add(new GenericBuyInfo(typeof(Garlic), 3, 20, 0xF84, 0)); + Add(new GenericBuyInfo(typeof(Ginseng), 3, 20, 0xF85, 0)); + Add(new GenericBuyInfo(typeof(MandrakeRoot), 3, 20, 0xF86, 0)); + Add(new GenericBuyInfo(typeof(Nightshade), 3, 20, 0xF88, 0)); + Add(new GenericBuyInfo(typeof(SpidersSilk), 3, 20, 0xF8D, 0)); + Add(new GenericBuyInfo(typeof(SulfurousAsh), 3, 20, 0xF8C, 0)); - Add(new GenericBuyInfo("Crafting Glass With Glassblowing", typeof(GlassblowingBook), 10637, 30, 0xFF4, 0)); - Add(new GenericBuyInfo("Finding Glass-Quality Sand", typeof(SandMiningBook), 10637, 30, 0xFF4, 0)); - Add(new GenericBuyInfo("1044608", typeof(Blowpipe), 21, 100, 0xE8A, 0x3B9)); - } + Add(new GenericBuyInfo(typeof(Bottle), 5, 100, 0xF0E, 0)); + + Add(new GenericBuyInfo(typeof(HeatingStand), 2, 100, 0x1849, 0)); + + Add(new GenericBuyInfo("Crafting Glass With Glassblowing", typeof(GlassblowingBook), 10637, 30, 0xFF4, 0)); + Add(new GenericBuyInfo("Finding Glass-Quality Sand", typeof(SandMiningBook), 10637, 30, 0xFF4, 0)); + Add(new GenericBuyInfo("1044608", typeof(Blowpipe), 21, 100, 0xE8A, 0x3B9)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(BlackPearl), 3); + Add(typeof(Bloodmoss), 3); + Add(typeof(MandrakeRoot), 2); + Add(typeof(Garlic), 2); + Add(typeof(Ginseng), 2); + Add(typeof(Nightshade), 2); + Add(typeof(SpidersSilk), 2); + Add(typeof(SulfurousAsh), 2); + Add(typeof(Bottle), 3); + Add(typeof(MortarPestle), 4); + + Add(typeof(NightSightPotion), 7); + Add(typeof(AgilityPotion), 7); + Add(typeof(StrengthPotion), 7); + Add(typeof(RefreshPotion), 7); + Add(typeof(LesserCurePotion), 7); + Add(typeof(LesserHealPotion), 7); + Add(typeof(LesserPoisonPotion), 7); + Add(typeof(LesserExplosionPotion), 10); + + Add(typeof(GlassblowingBook), 5000); + Add(typeof(SandMiningBook), 5000); + Add(typeof(Blowpipe), 10); + } + } } - - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(BlackPearl), 3); - Add(typeof(Bloodmoss), 3); - Add(typeof(MandrakeRoot), 2); - Add(typeof(Garlic), 2); - Add(typeof(Ginseng), 2); - Add(typeof(Nightshade), 2); - Add(typeof(SpidersSilk), 2); - Add(typeof(SulfurousAsh), 2); - Add(typeof(Bottle), 3); - Add(typeof(MortarPestle), 4); - - Add(typeof(NightSightPotion), 7); - Add(typeof(AgilityPotion), 7); - Add(typeof(StrengthPotion), 7); - Add(typeof(RefreshPotion), 7); - Add(typeof(LesserCurePotion), 7); - Add(typeof(LesserHealPotion), 7); - Add(typeof(LesserPoisonPotion), 7); - Add(typeof(LesserExplosionPotion), 10); - - Add(typeof(GlassblowingBook), 5000); - Add(typeof(SandMiningBook), 5000); - Add(typeof(Blowpipe), 10); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBHairStylist.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBHairStylist.cs index 3b178856d..26a517360 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBHairStylist.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBHairStylist.cs @@ -3,30 +3,30 @@ using Server.Items; namespace Server.Mobiles { - public class SBHairStylist : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBHairStylist : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo("special beard dye", typeof(SpecialBeardDye), 500000, 20, 0xE26, 0)); - Add(new GenericBuyInfo("special hair dye", typeof(SpecialHairDye), 500000, 20, 0xE26, 0)); - Add(new GenericBuyInfo("1041060", typeof(HairDye), 60, 20, 0xEFF, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(HairDye), 30); - Add(typeof(SpecialBeardDye), 250000); - Add(typeof(SpecialHairDye), 250000); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo("special beard dye", typeof(SpecialBeardDye), 500000, 20, 0xE26, 0)); + Add(new GenericBuyInfo("special hair dye", typeof(SpecialHairDye), 500000, 20, 0xE26, 0)); + Add(new GenericBuyInfo("1041060", typeof(HairDye), 60, 20, 0xEFF, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(HairDye), 30); + Add(typeof(SpecialBeardDye), 250000); + Add(typeof(SpecialHairDye), 250000); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBHealer.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBHealer.cs index 2a143af80..4f53b54c4 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBHealer.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBHealer.cs @@ -3,34 +3,34 @@ using Server.Items; namespace Server.Mobiles { - public class SBHealer : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBHealer : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Bandage), 5, 20, 0xE21, 0)); - Add(new GenericBuyInfo(typeof(LesserHealPotion), 15, 20, 0xF0C, 0)); - Add(new GenericBuyInfo(typeof(Ginseng), 3, 20, 0xF85, 0)); - Add(new GenericBuyInfo(typeof(Garlic), 3, 20, 0xF84, 0)); - Add(new GenericBuyInfo(typeof(RefreshPotion), 15, 20, 0xF0B, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Bandage), 1); - Add(typeof(LesserHealPotion), 7); - Add(typeof(RefreshPotion), 7); - Add(typeof(Garlic), 2); - Add(typeof(Ginseng), 2); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Bandage), 5, 20, 0xE21, 0)); + Add(new GenericBuyInfo(typeof(LesserHealPotion), 15, 20, 0xF0C, 0)); + Add(new GenericBuyInfo(typeof(Ginseng), 3, 20, 0xF85, 0)); + Add(new GenericBuyInfo(typeof(Garlic), 3, 20, 0xF84, 0)); + Add(new GenericBuyInfo(typeof(RefreshPotion), 15, 20, 0xF0B, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Bandage), 1); + Add(typeof(LesserHealPotion), 7); + Add(typeof(RefreshPotion), 7); + Add(typeof(Garlic), 2); + Add(typeof(Ginseng), 2); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBHerbalist.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBHerbalist.cs index 686ac0075..81a076115 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBHerbalist.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBHerbalist.cs @@ -3,38 +3,38 @@ using Server.Items; namespace Server.Mobiles { - public class SBHerbalist : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBHerbalist : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Ginseng), 3, 20, 0xF85, 0)); - Add(new GenericBuyInfo(typeof(Garlic), 3, 20, 0xF84, 0)); - Add(new GenericBuyInfo(typeof(MandrakeRoot), 3, 20, 0xF86, 0)); - Add(new GenericBuyInfo(typeof(Nightshade), 3, 20, 0xF88, 0)); - Add(new GenericBuyInfo(typeof(Bloodmoss), 5, 20, 0xF7B, 0)); - Add(new GenericBuyInfo(typeof(MortarPestle), 8, 20, 0xE9B, 0)); - Add(new GenericBuyInfo(typeof(Bottle), 5, 20, 0xF0E, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Bloodmoss), 3); - Add(typeof(MandrakeRoot), 2); - Add(typeof(Garlic), 2); - Add(typeof(Ginseng), 2); - Add(typeof(Nightshade), 2); - Add(typeof(Bottle), 3); - Add(typeof(MortarPestle), 4); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Ginseng), 3, 20, 0xF85, 0)); + Add(new GenericBuyInfo(typeof(Garlic), 3, 20, 0xF84, 0)); + Add(new GenericBuyInfo(typeof(MandrakeRoot), 3, 20, 0xF86, 0)); + Add(new GenericBuyInfo(typeof(Nightshade), 3, 20, 0xF88, 0)); + Add(new GenericBuyInfo(typeof(Bloodmoss), 5, 20, 0xF7B, 0)); + Add(new GenericBuyInfo(typeof(MortarPestle), 8, 20, 0xE9B, 0)); + Add(new GenericBuyInfo(typeof(Bottle), 5, 20, 0xF0E, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Bloodmoss), 3); + Add(typeof(MandrakeRoot), 2); + Add(typeof(Garlic), 2); + Add(typeof(Ginseng), 2); + Add(typeof(Nightshade), 2); + Add(typeof(Bottle), 3); + Add(typeof(MortarPestle), 4); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBHolyMage.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBHolyMage.cs index 2df1114b5..da9f7d9ec 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBHolyMage.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBHolyMage.cs @@ -1,87 +1,86 @@ -using System; using System.Collections.Generic; using Server.Items; namespace Server.Mobiles { - public class SBHolyMage : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBHolyMage : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Spellbook), 18, 10, 0xEFA, 0)); - Add(new GenericBuyInfo(typeof(ScribesPen), 8, 10, 0xFBF, 0)); - Add(new GenericBuyInfo(typeof(BlankScroll), 5, 20, 0x0E34, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - Add(new GenericBuyInfo("1041072", typeof(MagicWizardsHat), 11, 10, 0x1718, Utility.RandomDyedHue())); + public override List BuyInfo { get; } = new InternalBuyInfo(); - Add(new GenericBuyInfo(typeof(RecallRune), 15, 10, 0x1f14, 0)); - - Add(new GenericBuyInfo(typeof(RefreshPotion), 15, 20, 0xF0B, 0)); - Add(new GenericBuyInfo(typeof(AgilityPotion), 15, 20, 0xF08, 0)); - Add(new GenericBuyInfo(typeof(NightSightPotion), 15, 20, 0xF06, 0)); - Add(new GenericBuyInfo(typeof(LesserHealPotion), 15, 20, 0xF0C, 0)); - Add(new GenericBuyInfo(typeof(StrengthPotion), 15, 20, 0xF09, 0)); - Add(new GenericBuyInfo(typeof(LesserCurePotion), 15, 20, 0xF07, 0)); - - Add(new GenericBuyInfo(typeof(BlackPearl), 5, 20, 0xF7A, 0)); - Add(new GenericBuyInfo(typeof(Bloodmoss), 5, 20, 0xF7B, 0)); - Add(new GenericBuyInfo(typeof(Garlic), 3, 20, 0xF84, 0)); - Add(new GenericBuyInfo(typeof(Ginseng), 3, 20, 0xF85, 0)); - Add(new GenericBuyInfo(typeof(MandrakeRoot), 3, 20, 0xF86, 0)); - Add(new GenericBuyInfo(typeof(Nightshade), 3, 20, 0xF88, 0)); - Add(new GenericBuyInfo(typeof(SpidersSilk), 3, 20, 0xF8D, 0)); - Add(new GenericBuyInfo(typeof(SulfurousAsh), 3, 20, 0xF8C, 0)); - - Type[] types = Loot.RegularScrollTypes; - - for (int i = 0; i < types.Length && i < 8; ++i) + public class InternalBuyInfo : List { - int itemID = 0x1F2E + i; + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Spellbook), 18, 10, 0xEFA, 0)); + Add(new GenericBuyInfo(typeof(ScribesPen), 8, 10, 0xFBF, 0)); + Add(new GenericBuyInfo(typeof(BlankScroll), 5, 20, 0x0E34, 0)); - if (i == 6) - itemID = 0x1F2D; - else if (i > 6) - --itemID; + Add(new GenericBuyInfo("1041072", typeof(MagicWizardsHat), 11, 10, 0x1718, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(types[i], 12 + i / 8 * 10, 20, itemID, 0)); + Add(new GenericBuyInfo(typeof(RecallRune), 15, 10, 0x1f14, 0)); + + Add(new GenericBuyInfo(typeof(RefreshPotion), 15, 20, 0xF0B, 0)); + Add(new GenericBuyInfo(typeof(AgilityPotion), 15, 20, 0xF08, 0)); + Add(new GenericBuyInfo(typeof(NightSightPotion), 15, 20, 0xF06, 0)); + Add(new GenericBuyInfo(typeof(LesserHealPotion), 15, 20, 0xF0C, 0)); + Add(new GenericBuyInfo(typeof(StrengthPotion), 15, 20, 0xF09, 0)); + Add(new GenericBuyInfo(typeof(LesserCurePotion), 15, 20, 0xF07, 0)); + + Add(new GenericBuyInfo(typeof(BlackPearl), 5, 20, 0xF7A, 0)); + Add(new GenericBuyInfo(typeof(Bloodmoss), 5, 20, 0xF7B, 0)); + Add(new GenericBuyInfo(typeof(Garlic), 3, 20, 0xF84, 0)); + Add(new GenericBuyInfo(typeof(Ginseng), 3, 20, 0xF85, 0)); + Add(new GenericBuyInfo(typeof(MandrakeRoot), 3, 20, 0xF86, 0)); + Add(new GenericBuyInfo(typeof(Nightshade), 3, 20, 0xF88, 0)); + Add(new GenericBuyInfo(typeof(SpidersSilk), 3, 20, 0xF8D, 0)); + Add(new GenericBuyInfo(typeof(SulfurousAsh), 3, 20, 0xF8C, 0)); + + var types = Loot.RegularScrollTypes; + + for (var i = 0; i < types.Length && i < 8; ++i) + { + var itemID = 0x1F2E + i; + + if (i == 6) + itemID = 0x1F2D; + else if (i > 6) + --itemID; + + Add(new GenericBuyInfo(types[i], 12 + i / 8 * 10, 20, itemID, 0)); + } + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(BlackPearl), 3); + Add(typeof(Bloodmoss), 3); + Add(typeof(MandrakeRoot), 2); + Add(typeof(Garlic), 2); + Add(typeof(Ginseng), 2); + Add(typeof(Nightshade), 2); + Add(typeof(SpidersSilk), 2); + Add(typeof(SulfurousAsh), 2); + Add(typeof(RecallRune), 8); + Add(typeof(Spellbook), 9); + Add(typeof(BlankScroll), 3); + + Add(typeof(NightSightPotion), 7); + Add(typeof(AgilityPotion), 7); + Add(typeof(StrengthPotion), 7); + Add(typeof(RefreshPotion), 7); + Add(typeof(LesserCurePotion), 7); + Add(typeof(LesserHealPotion), 7); + + var types = Loot.RegularScrollTypes; + + for (var i = 0; i < types.Length; ++i) + Add(types[i], (i / 8 + 2) * 2); + } } - } } - - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(BlackPearl), 3); - Add(typeof(Bloodmoss), 3); - Add(typeof(MandrakeRoot), 2); - Add(typeof(Garlic), 2); - Add(typeof(Ginseng), 2); - Add(typeof(Nightshade), 2); - Add(typeof(SpidersSilk), 2); - Add(typeof(SulfurousAsh), 2); - Add(typeof(RecallRune), 8); - Add(typeof(Spellbook), 9); - Add(typeof(BlankScroll), 3); - - Add(typeof(NightSightPotion), 7); - Add(typeof(AgilityPotion), 7); - Add(typeof(StrengthPotion), 7); - Add(typeof(RefreshPotion), 7); - Add(typeof(LesserCurePotion), 7); - Add(typeof(LesserHealPotion), 7); - - Type[] types = Loot.RegularScrollTypes; - - for (int i = 0; i < types.Length; ++i) - Add(types[i], (i / 8 + 2) * 2); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBHouseDeed.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBHouseDeed.cs index b7ff5c7ed..97b93e2ac 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBHouseDeed.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBHouseDeed.cs @@ -3,45 +3,85 @@ using Server.Multis.Deeds; namespace Server.Mobiles { - public class SBHouseDeed : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBHouseDeed : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo("deed to a stone-and-plaster house", typeof(StonePlasterHouseDeed), 43800, 20, 0x14F0, - 0)); - Add(new GenericBuyInfo("deed to a field stone house", typeof(FieldStoneHouseDeed), 43800, 20, 0x14F0, 0)); - Add(new GenericBuyInfo("deed to a small brick house", typeof(SmallBrickHouseDeed), 43800, 20, 0x14F0, 0)); - Add(new GenericBuyInfo("deed to a wooden house", typeof(WoodHouseDeed), 43800, 20, 0x14F0, 0)); - Add(new GenericBuyInfo("deed to a wood-and-plaster house", typeof(WoodPlasterHouseDeed), 43800, 20, 0x14F0, - 0)); - Add(new GenericBuyInfo("deed to a thatched-roof cottage", typeof(ThatchedRoofCottageDeed), 43800, 20, 0x14F0, - 0)); - Add(new GenericBuyInfo("deed to a brick house", typeof(BrickHouseDeed), 144500, 20, 0x14F0, 0)); - Add(new GenericBuyInfo("deed to a two-story wood-and-plaster house", typeof(TwoStoryWoodPlasterHouseDeed), - 192400, 20, 0x14F0, 0)); - Add(new GenericBuyInfo("deed to a tower", typeof(TowerDeed), 433200, 20, 0x14F0, 0)); - Add(new GenericBuyInfo("deed to a small stone keep", typeof(KeepDeed), 665200, 20, 0x14F0, 0)); - Add(new GenericBuyInfo("deed to a castle", typeof(CastleDeed), 1022800, 20, 0x14F0, 0)); - Add(new GenericBuyInfo("deed to a large house with patio", typeof(LargePatioDeed), 152800, 20, 0x14F0, 0)); - Add(new GenericBuyInfo("deed to a marble house with patio", typeof(LargeMarbleDeed), 192000, 20, 0x14F0, 0)); - Add(new GenericBuyInfo("deed to a small stone tower", typeof(SmallTowerDeed), 88500, 20, 0x14F0, 0)); - Add(new GenericBuyInfo("deed to a two story log cabin", typeof(LogCabinDeed), 97800, 20, 0x14F0, 0)); - Add(new GenericBuyInfo("deed to a sandstone house with patio", typeof(SandstonePatioDeed), 90900, 20, 0x14F0, - 0)); - Add(new GenericBuyInfo("deed to a two story villa", typeof(VillaDeed), 136500, 20, 0x14F0, 0)); - Add(new GenericBuyInfo("deed to a small stone workshop", typeof(StoneWorkshopDeed), 60600, 20, 0x14F0, 0)); - Add(new GenericBuyInfo("deed to a small marble workshop", typeof(MarbleWorkshopDeed), 63000, 20, 0x14F0, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add( + new GenericBuyInfo( + "deed to a stone-and-plaster house", + typeof(StonePlasterHouseDeed), + 43800, + 20, + 0x14F0, + 0 + ) + ); + Add(new GenericBuyInfo("deed to a field stone house", typeof(FieldStoneHouseDeed), 43800, 20, 0x14F0, 0)); + Add(new GenericBuyInfo("deed to a small brick house", typeof(SmallBrickHouseDeed), 43800, 20, 0x14F0, 0)); + Add(new GenericBuyInfo("deed to a wooden house", typeof(WoodHouseDeed), 43800, 20, 0x14F0, 0)); + Add( + new GenericBuyInfo( + "deed to a wood-and-plaster house", + typeof(WoodPlasterHouseDeed), + 43800, + 20, + 0x14F0, + 0 + ) + ); + Add( + new GenericBuyInfo( + "deed to a thatched-roof cottage", + typeof(ThatchedRoofCottageDeed), + 43800, + 20, + 0x14F0, + 0 + ) + ); + Add(new GenericBuyInfo("deed to a brick house", typeof(BrickHouseDeed), 144500, 20, 0x14F0, 0)); + Add( + new GenericBuyInfo( + "deed to a two-story wood-and-plaster house", + typeof(TwoStoryWoodPlasterHouseDeed), + 192400, + 20, + 0x14F0, + 0 + ) + ); + Add(new GenericBuyInfo("deed to a tower", typeof(TowerDeed), 433200, 20, 0x14F0, 0)); + Add(new GenericBuyInfo("deed to a small stone keep", typeof(KeepDeed), 665200, 20, 0x14F0, 0)); + Add(new GenericBuyInfo("deed to a castle", typeof(CastleDeed), 1022800, 20, 0x14F0, 0)); + Add(new GenericBuyInfo("deed to a large house with patio", typeof(LargePatioDeed), 152800, 20, 0x14F0, 0)); + Add(new GenericBuyInfo("deed to a marble house with patio", typeof(LargeMarbleDeed), 192000, 20, 0x14F0, 0)); + Add(new GenericBuyInfo("deed to a small stone tower", typeof(SmallTowerDeed), 88500, 20, 0x14F0, 0)); + Add(new GenericBuyInfo("deed to a two story log cabin", typeof(LogCabinDeed), 97800, 20, 0x14F0, 0)); + Add( + new GenericBuyInfo( + "deed to a sandstone house with patio", + typeof(SandstonePatioDeed), + 90900, + 20, + 0x14F0, + 0 + ) + ); + Add(new GenericBuyInfo("deed to a two story villa", typeof(VillaDeed), 136500, 20, 0x14F0, 0)); + Add(new GenericBuyInfo("deed to a small stone workshop", typeof(StoneWorkshopDeed), 60600, 20, 0x14F0, 0)); + Add(new GenericBuyInfo("deed to a small marble workshop", typeof(MarbleWorkshopDeed), 63000, 20, 0x14F0, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBInfo.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBInfo.cs index c4dc33a68..c2bcd851c 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBInfo.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBInfo.cs @@ -2,11 +2,11 @@ using System.Collections.Generic; namespace Server.Mobiles { - public abstract class SBInfo - { - public static readonly List Empty = new List(); + public abstract class SBInfo + { + public static readonly List Empty = new List(); - public abstract IShopSellInfo SellInfo { get; } - public abstract List BuyInfo { get; } - } -} \ No newline at end of file + public abstract IShopSellInfo SellInfo { get; } + public abstract List BuyInfo { get; } + } +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBInnKeeper.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBInnKeeper.cs index 4ac84dd33..daa16a5ab 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBInnKeeper.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBInnKeeper.cs @@ -4,106 +4,106 @@ using Server.Multis; namespace Server.Mobiles { - public class SBInnKeeper : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBInnKeeper : SBInfo { - public InternalBuyInfo() - { - Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Ale, 7, 20, 0x99F, 0)); - Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Wine, 7, 20, 0x9C7, 0)); - Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Liquor, 7, 20, 0x99B, 0)); - Add(new BeverageBuyInfo(typeof(Jug), BeverageType.Cider, 13, 20, 0x9C8, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Milk, 7, 20, 0x9F0, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Ale, 11, 20, 0x1F95, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Cider, 11, 20, 0x1F97, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Liquor, 11, 20, 0x1F99, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Wine, 11, 20, 0x1F9B, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Water, 11, 20, 0x1F9D, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - Add(new GenericBuyInfo(typeof(BreadLoaf), 6, 10, 0x103B, 0)); - Add(new GenericBuyInfo(typeof(CheeseWheel), 21, 10, 0x97E, 0)); - Add(new GenericBuyInfo(typeof(CookedBird), 17, 20, 0x9B7, 0)); - Add(new GenericBuyInfo(typeof(LambLeg), 8, 20, 0x160A, 0)); - Add(new GenericBuyInfo(typeof(ChickenLeg), 5, 20, 0x1608, 0)); - Add(new GenericBuyInfo(typeof(Ribs), 7, 20, 0x9F2, 0)); + public override List BuyInfo { get; } = new InternalBuyInfo(); - Add(new GenericBuyInfo(typeof(WoodenBowlOfCarrots), 3, 20, 0x15F9, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfCorn), 3, 20, 0x15FA, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfLettuce), 3, 20, 0x15FB, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfPeas), 3, 20, 0x15FC, 0)); - Add(new GenericBuyInfo(typeof(EmptyPewterBowl), 2, 20, 0x15FD, 0)); - Add(new GenericBuyInfo(typeof(PewterBowlOfCorn), 3, 20, 0x15FE, 0)); - Add(new GenericBuyInfo(typeof(PewterBowlOfLettuce), 3, 20, 0x15FF, 0)); - Add(new GenericBuyInfo(typeof(PewterBowlOfPeas), 3, 20, 0x1600, 0)); - Add(new GenericBuyInfo(typeof(PewterBowlOfPotatos), 3, 20, 0x1601, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfStew), 3, 20, 0x1604, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfTomatoSoup), 3, 20, 0x1606, 0)); + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Ale, 7, 20, 0x99F, 0)); + Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Wine, 7, 20, 0x9C7, 0)); + Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Liquor, 7, 20, 0x99B, 0)); + Add(new BeverageBuyInfo(typeof(Jug), BeverageType.Cider, 13, 20, 0x9C8, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Milk, 7, 20, 0x9F0, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Ale, 11, 20, 0x1F95, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Cider, 11, 20, 0x1F97, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Liquor, 11, 20, 0x1F99, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Wine, 11, 20, 0x1F9B, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Water, 11, 20, 0x1F9D, 0)); - Add(new GenericBuyInfo(typeof(ApplePie), 7, 20, 0x1041, 0)); // OSI just has Pie, not Apple/Fruit/Meat + Add(new GenericBuyInfo(typeof(BreadLoaf), 6, 10, 0x103B, 0)); + Add(new GenericBuyInfo(typeof(CheeseWheel), 21, 10, 0x97E, 0)); + Add(new GenericBuyInfo(typeof(CookedBird), 17, 20, 0x9B7, 0)); + Add(new GenericBuyInfo(typeof(LambLeg), 8, 20, 0x160A, 0)); + Add(new GenericBuyInfo(typeof(ChickenLeg), 5, 20, 0x1608, 0)); + Add(new GenericBuyInfo(typeof(Ribs), 7, 20, 0x9F2, 0)); - Add(new GenericBuyInfo(typeof(Peach), 3, 20, 0x9D2, 0)); - Add(new GenericBuyInfo(typeof(Pear), 3, 20, 0x994, 0)); - Add(new GenericBuyInfo(typeof(Grapes), 3, 20, 0x9D1, 0)); - Add(new GenericBuyInfo(typeof(Apple), 3, 20, 0x9D0, 0)); - Add(new GenericBuyInfo(typeof(Banana), 2, 20, 0x171F, 0)); - Add(new GenericBuyInfo(typeof(Torch), 7, 20, 0xF6B, 0)); - Add(new GenericBuyInfo(typeof(Candle), 6, 20, 0xA28, 0)); - Add(new GenericBuyInfo(typeof(Beeswax), 1, 20, 0x1422, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfCarrots), 3, 20, 0x15F9, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfCorn), 3, 20, 0x15FA, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfLettuce), 3, 20, 0x15FB, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfPeas), 3, 20, 0x15FC, 0)); + Add(new GenericBuyInfo(typeof(EmptyPewterBowl), 2, 20, 0x15FD, 0)); + Add(new GenericBuyInfo(typeof(PewterBowlOfCorn), 3, 20, 0x15FE, 0)); + Add(new GenericBuyInfo(typeof(PewterBowlOfLettuce), 3, 20, 0x15FF, 0)); + Add(new GenericBuyInfo(typeof(PewterBowlOfPeas), 3, 20, 0x1600, 0)); + Add(new GenericBuyInfo(typeof(PewterBowlOfPotatos), 3, 20, 0x1601, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfStew), 3, 20, 0x1604, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfTomatoSoup), 3, 20, 0x1606, 0)); - Add(new GenericBuyInfo(typeof(Backpack), 15, 20, 0x9B2, 0)); - Add(new GenericBuyInfo("1016450", typeof(Chessboard), 2, 20, 0xFA6, 0)); - Add(new GenericBuyInfo("1016449", typeof(CheckerBoard), 2, 20, 0xFA6, 0)); - Add(new GenericBuyInfo(typeof(Backgammon), 2, 20, 0xE1C, 0)); - Add(new GenericBuyInfo(typeof(Dices), 2, 20, 0xFA7, 0)); - Add(new GenericBuyInfo("1041243", typeof(ContractOfEmployment), 1252, 20, 0x14F0, 0)); - Add(new GenericBuyInfo("a barkeep contract", typeof(BarkeepContract), 1252, 20, 0x14F0, 0)); + Add(new GenericBuyInfo(typeof(ApplePie), 7, 20, 0x1041, 0)); // OSI just has Pie, not Apple/Fruit/Meat - if (BaseHouse.NewVendorSystem) - Add(new GenericBuyInfo("1062332", typeof(VendorRentalContract), 1252, 20, 0x14F0, 0x672)); - } + Add(new GenericBuyInfo(typeof(Peach), 3, 20, 0x9D2, 0)); + Add(new GenericBuyInfo(typeof(Pear), 3, 20, 0x994, 0)); + Add(new GenericBuyInfo(typeof(Grapes), 3, 20, 0x9D1, 0)); + Add(new GenericBuyInfo(typeof(Apple), 3, 20, 0x9D0, 0)); + Add(new GenericBuyInfo(typeof(Banana), 2, 20, 0x171F, 0)); + Add(new GenericBuyInfo(typeof(Torch), 7, 20, 0xF6B, 0)); + Add(new GenericBuyInfo(typeof(Candle), 6, 20, 0xA28, 0)); + Add(new GenericBuyInfo(typeof(Beeswax), 1, 20, 0x1422, 0)); + + Add(new GenericBuyInfo(typeof(Backpack), 15, 20, 0x9B2, 0)); + Add(new GenericBuyInfo("1016450", typeof(Chessboard), 2, 20, 0xFA6, 0)); + Add(new GenericBuyInfo("1016449", typeof(CheckerBoard), 2, 20, 0xFA6, 0)); + Add(new GenericBuyInfo(typeof(Backgammon), 2, 20, 0xE1C, 0)); + Add(new GenericBuyInfo(typeof(Dices), 2, 20, 0xFA7, 0)); + Add(new GenericBuyInfo("1041243", typeof(ContractOfEmployment), 1252, 20, 0x14F0, 0)); + Add(new GenericBuyInfo("a barkeep contract", typeof(BarkeepContract), 1252, 20, 0x14F0, 0)); + + if (BaseHouse.NewVendorSystem) + Add(new GenericBuyInfo("1062332", typeof(VendorRentalContract), 1252, 20, 0x14F0, 0x672)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(BeverageBottle), 3); + Add(typeof(Jug), 6); + Add(typeof(Pitcher), 5); + Add(typeof(GlassMug), 1); + Add(typeof(BreadLoaf), 3); + Add(typeof(CheeseWheel), 12); + Add(typeof(Ribs), 6); + Add(typeof(Peach), 1); + Add(typeof(Pear), 1); + Add(typeof(Grapes), 1); + Add(typeof(Apple), 1); + Add(typeof(Banana), 1); + Add(typeof(Torch), 3); + Add(typeof(Candle), 3); + Add(typeof(Chessboard), 1); + Add(typeof(CheckerBoard), 1); + Add(typeof(Backgammon), 1); + Add(typeof(Dices), 1); + Add(typeof(ContractOfEmployment), 626); + Add(typeof(Beeswax), 1); + Add(typeof(WoodenBowlOfCarrots), 1); + Add(typeof(WoodenBowlOfCorn), 1); + Add(typeof(WoodenBowlOfLettuce), 1); + Add(typeof(WoodenBowlOfPeas), 1); + Add(typeof(EmptyPewterBowl), 1); + Add(typeof(PewterBowlOfCorn), 1); + Add(typeof(PewterBowlOfLettuce), 1); + Add(typeof(PewterBowlOfPeas), 1); + Add(typeof(PewterBowlOfPotatos), 1); + Add(typeof(WoodenBowlOfStew), 1); + Add(typeof(WoodenBowlOfTomatoSoup), 1); + } + } } - - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(BeverageBottle), 3); - Add(typeof(Jug), 6); - Add(typeof(Pitcher), 5); - Add(typeof(GlassMug), 1); - Add(typeof(BreadLoaf), 3); - Add(typeof(CheeseWheel), 12); - Add(typeof(Ribs), 6); - Add(typeof(Peach), 1); - Add(typeof(Pear), 1); - Add(typeof(Grapes), 1); - Add(typeof(Apple), 1); - Add(typeof(Banana), 1); - Add(typeof(Torch), 3); - Add(typeof(Candle), 3); - Add(typeof(Chessboard), 1); - Add(typeof(CheckerBoard), 1); - Add(typeof(Backgammon), 1); - Add(typeof(Dices), 1); - Add(typeof(ContractOfEmployment), 626); - Add(typeof(Beeswax), 1); - Add(typeof(WoodenBowlOfCarrots), 1); - Add(typeof(WoodenBowlOfCorn), 1); - Add(typeof(WoodenBowlOfLettuce), 1); - Add(typeof(WoodenBowlOfPeas), 1); - Add(typeof(EmptyPewterBowl), 1); - Add(typeof(PewterBowlOfCorn), 1); - Add(typeof(PewterBowlOfLettuce), 1); - Add(typeof(PewterBowlOfPeas), 1); - Add(typeof(PewterBowlOfPotatos), 1); - Add(typeof(WoodenBowlOfStew), 1); - Add(typeof(WoodenBowlOfTomatoSoup), 1); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBJewel.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBJewel.cs index 18b828bef..69de493bb 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBJewel.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBJewel.cs @@ -3,71 +3,98 @@ using Server.Items; namespace Server.Mobiles { - public class SBJewel : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBJewel : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(GoldRing), 27, 20, 0x108A, 0)); - Add(new GenericBuyInfo(typeof(Necklace), 26, 20, 0x1085, 0)); - Add(new GenericBuyInfo(typeof(GoldNecklace), 27, 20, 0x1088, 0)); - Add(new GenericBuyInfo(typeof(GoldBeadNecklace), 27, 20, 0x1089, 0)); - Add(new GenericBuyInfo(typeof(Beads), 27, 20, 0x108B, 0)); - Add(new GenericBuyInfo(typeof(GoldBracelet), 27, 20, 0x1086, 0)); - Add(new GenericBuyInfo(typeof(GoldEarrings), 27, 20, 0x1087, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - Add(new GenericBuyInfo("1060740", typeof(BroadcastCrystal), 68, 20, 0x1ED0, 0, - new object[] { 500 })); // 500 charges - Add(new GenericBuyInfo("1060740", typeof(BroadcastCrystal), 131, 20, 0x1ED0, 0, - new object[] { 1000 })); // 1000 charges - Add(new GenericBuyInfo("1060740", typeof(BroadcastCrystal), 256, 20, 0x1ED0, 0, - new object[] { 2000 })); // 2000 charges + public override List BuyInfo { get; } = new InternalBuyInfo(); - Add(new GenericBuyInfo("1060740", typeof(ReceiverCrystal), 6, 20, 0x1ED0, 0)); + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(GoldRing), 27, 20, 0x108A, 0)); + Add(new GenericBuyInfo(typeof(Necklace), 26, 20, 0x1085, 0)); + Add(new GenericBuyInfo(typeof(GoldNecklace), 27, 20, 0x1088, 0)); + Add(new GenericBuyInfo(typeof(GoldBeadNecklace), 27, 20, 0x1089, 0)); + Add(new GenericBuyInfo(typeof(Beads), 27, 20, 0x108B, 0)); + Add(new GenericBuyInfo(typeof(GoldBracelet), 27, 20, 0x1086, 0)); + Add(new GenericBuyInfo(typeof(GoldEarrings), 27, 20, 0x1087, 0)); - Add(new GenericBuyInfo(typeof(StarSapphire), 125, 20, 0xF21, 0)); - Add(new GenericBuyInfo(typeof(Emerald), 100, 20, 0xF10, 0)); - Add(new GenericBuyInfo(typeof(Sapphire), 100, 20, 0xF19, 0)); - Add(new GenericBuyInfo(typeof(Ruby), 75, 20, 0xF13, 0)); - Add(new GenericBuyInfo(typeof(Citrine), 50, 20, 0xF15, 0)); - Add(new GenericBuyInfo(typeof(Amethyst), 100, 20, 0xF16, 0)); - Add(new GenericBuyInfo(typeof(Tourmaline), 75, 20, 0xF2D, 0)); - Add(new GenericBuyInfo(typeof(Amber), 50, 20, 0xF25, 0)); - Add(new GenericBuyInfo(typeof(Diamond), 200, 20, 0xF26, 0)); - } + Add( + new GenericBuyInfo( + "1060740", + typeof(BroadcastCrystal), + 68, + 20, + 0x1ED0, + 0, + new object[] { 500 } + ) + ); // 500 charges + Add( + new GenericBuyInfo( + "1060740", + typeof(BroadcastCrystal), + 131, + 20, + 0x1ED0, + 0, + new object[] { 1000 } + ) + ); // 1000 charges + Add( + new GenericBuyInfo( + "1060740", + typeof(BroadcastCrystal), + 256, + 20, + 0x1ED0, + 0, + new object[] { 2000 } + ) + ); // 2000 charges + + Add(new GenericBuyInfo("1060740", typeof(ReceiverCrystal), 6, 20, 0x1ED0, 0)); + + Add(new GenericBuyInfo(typeof(StarSapphire), 125, 20, 0xF21, 0)); + Add(new GenericBuyInfo(typeof(Emerald), 100, 20, 0xF10, 0)); + Add(new GenericBuyInfo(typeof(Sapphire), 100, 20, 0xF19, 0)); + Add(new GenericBuyInfo(typeof(Ruby), 75, 20, 0xF13, 0)); + Add(new GenericBuyInfo(typeof(Citrine), 50, 20, 0xF15, 0)); + Add(new GenericBuyInfo(typeof(Amethyst), 100, 20, 0xF16, 0)); + Add(new GenericBuyInfo(typeof(Tourmaline), 75, 20, 0xF2D, 0)); + Add(new GenericBuyInfo(typeof(Amber), 50, 20, 0xF25, 0)); + Add(new GenericBuyInfo(typeof(Diamond), 200, 20, 0xF26, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Amber), 25); + Add(typeof(Amethyst), 50); + Add(typeof(Citrine), 25); + Add(typeof(Diamond), 100); + Add(typeof(Emerald), 50); + Add(typeof(Ruby), 37); + Add(typeof(Sapphire), 50); + Add(typeof(StarSapphire), 62); + Add(typeof(Tourmaline), 47); + Add(typeof(GoldRing), 13); + Add(typeof(SilverRing), 10); + Add(typeof(Necklace), 13); + Add(typeof(GoldNecklace), 13); + Add(typeof(GoldBeadNecklace), 13); + Add(typeof(SilverNecklace), 10); + Add(typeof(SilverBeadNecklace), 10); + Add(typeof(Beads), 13); + Add(typeof(GoldBracelet), 13); + Add(typeof(SilverBracelet), 10); + Add(typeof(GoldEarrings), 13); + Add(typeof(SilverEarrings), 10); + } + } } - - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Amber), 25); - Add(typeof(Amethyst), 50); - Add(typeof(Citrine), 25); - Add(typeof(Diamond), 100); - Add(typeof(Emerald), 50); - Add(typeof(Ruby), 37); - Add(typeof(Sapphire), 50); - Add(typeof(StarSapphire), 62); - Add(typeof(Tourmaline), 47); - Add(typeof(GoldRing), 13); - Add(typeof(SilverRing), 10); - Add(typeof(Necklace), 13); - Add(typeof(GoldNecklace), 13); - Add(typeof(GoldBeadNecklace), 13); - Add(typeof(SilverNecklace), 10); - Add(typeof(SilverBeadNecklace), 10); - Add(typeof(Beads), 13); - Add(typeof(GoldBracelet), 13); - Add(typeof(SilverBracelet), 10); - Add(typeof(GoldEarrings), 13); - Add(typeof(SilverEarrings), 10); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBKeeperOfChivalry.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBKeeperOfChivalry.cs index 45df94151..20e53b5f5 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBKeeperOfChivalry.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBKeeperOfChivalry.cs @@ -3,22 +3,22 @@ using Server.Items; namespace Server.Mobiles { - public class SBKeeperOfChivalry : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBKeeperOfChivalry : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(BookOfChivalry), 140, 20, 0x2252, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(BookOfChivalry), 140, 20, 0x2252, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBLeatherWorker.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBLeatherWorker.cs index f3ed2c1ea..0f4a935e6 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBLeatherWorker.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBLeatherWorker.cs @@ -3,28 +3,28 @@ using Server.Items; namespace Server.Mobiles { - public class SBLeatherWorker : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBLeatherWorker : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Hides), 4, 999, 0x1078, 0)); - Add(new GenericBuyInfo(typeof(ThighBoots), 56, 10, 0x1711, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Hides), 2); - Add(typeof(ThighBoots), 28); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Hides), 4, 999, 0x1078, 0)); + Add(new GenericBuyInfo(typeof(ThighBoots), 56, 10, 0x1711, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Hides), 2); + Add(typeof(ThighBoots), 28); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBMage.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBMage.cs index adcf1eff4..ff57978c8 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBMage.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBMage.cs @@ -1,129 +1,128 @@ -using System; using System.Collections.Generic; using Server.Items; namespace Server.Mobiles { - public class SBMage : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBMage : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Spellbook), 18, 10, 0xEFA, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - if (Core.AOS) - Add(new GenericBuyInfo(typeof(NecromancerSpellbook), 115, 10, 0x2253, 0)); + public override List BuyInfo { get; } = new InternalBuyInfo(); - Add(new GenericBuyInfo(typeof(ScribesPen), 8, 10, 0xFBF, 0)); - - Add(new GenericBuyInfo(typeof(BlankScroll), 5, 20, 0x0E34, 0)); - - Add(new GenericBuyInfo("1041072", typeof(MagicWizardsHat), 11, 10, 0x1718, Utility.RandomDyedHue())); - - Add(new GenericBuyInfo(typeof(RecallRune), 15, 10, 0x1F14, 0)); - - Add(new GenericBuyInfo(typeof(RefreshPotion), 15, 10, 0xF0B, 0)); - Add(new GenericBuyInfo(typeof(AgilityPotion), 15, 10, 0xF08, 0)); - Add(new GenericBuyInfo(typeof(NightSightPotion), 15, 10, 0xF06, 0)); - Add(new GenericBuyInfo(typeof(LesserHealPotion), 15, 10, 0xF0C, 0)); - Add(new GenericBuyInfo(typeof(StrengthPotion), 15, 10, 0xF09, 0)); - Add(new GenericBuyInfo(typeof(LesserPoisonPotion), 15, 10, 0xF0A, 0)); - Add(new GenericBuyInfo(typeof(LesserCurePotion), 15, 10, 0xF07, 0)); - Add(new GenericBuyInfo(typeof(LesserExplosionPotion), 21, 10, 0xF0D, 0)); - - Add(new GenericBuyInfo(typeof(BlackPearl), 5, 20, 0xF7A, 0)); - Add(new GenericBuyInfo(typeof(Bloodmoss), 5, 20, 0xF7B, 0)); - Add(new GenericBuyInfo(typeof(Garlic), 3, 20, 0xF84, 0)); - Add(new GenericBuyInfo(typeof(Ginseng), 3, 20, 0xF85, 0)); - Add(new GenericBuyInfo(typeof(MandrakeRoot), 3, 20, 0xF86, 0)); - Add(new GenericBuyInfo(typeof(Nightshade), 3, 20, 0xF88, 0)); - Add(new GenericBuyInfo(typeof(SpidersSilk), 3, 20, 0xF8D, 0)); - Add(new GenericBuyInfo(typeof(SulfurousAsh), 3, 20, 0xF8C, 0)); - - if (Core.AOS) + public class InternalBuyInfo : List { - Add(new GenericBuyInfo(typeof(BatWing), 3, 999, 0xF78, 0)); - Add(new GenericBuyInfo(typeof(DaemonBlood), 6, 999, 0xF7D, 0)); - Add(new GenericBuyInfo(typeof(PigIron), 5, 999, 0xF8A, 0)); - Add(new GenericBuyInfo(typeof(NoxCrystal), 6, 999, 0xF8E, 0)); - Add(new GenericBuyInfo(typeof(GraveDust), 3, 999, 0xF8F, 0)); + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Spellbook), 18, 10, 0xEFA, 0)); + + if (Core.AOS) + Add(new GenericBuyInfo(typeof(NecromancerSpellbook), 115, 10, 0x2253, 0)); + + Add(new GenericBuyInfo(typeof(ScribesPen), 8, 10, 0xFBF, 0)); + + Add(new GenericBuyInfo(typeof(BlankScroll), 5, 20, 0x0E34, 0)); + + Add(new GenericBuyInfo("1041072", typeof(MagicWizardsHat), 11, 10, 0x1718, Utility.RandomDyedHue())); + + Add(new GenericBuyInfo(typeof(RecallRune), 15, 10, 0x1F14, 0)); + + Add(new GenericBuyInfo(typeof(RefreshPotion), 15, 10, 0xF0B, 0)); + Add(new GenericBuyInfo(typeof(AgilityPotion), 15, 10, 0xF08, 0)); + Add(new GenericBuyInfo(typeof(NightSightPotion), 15, 10, 0xF06, 0)); + Add(new GenericBuyInfo(typeof(LesserHealPotion), 15, 10, 0xF0C, 0)); + Add(new GenericBuyInfo(typeof(StrengthPotion), 15, 10, 0xF09, 0)); + Add(new GenericBuyInfo(typeof(LesserPoisonPotion), 15, 10, 0xF0A, 0)); + Add(new GenericBuyInfo(typeof(LesserCurePotion), 15, 10, 0xF07, 0)); + Add(new GenericBuyInfo(typeof(LesserExplosionPotion), 21, 10, 0xF0D, 0)); + + Add(new GenericBuyInfo(typeof(BlackPearl), 5, 20, 0xF7A, 0)); + Add(new GenericBuyInfo(typeof(Bloodmoss), 5, 20, 0xF7B, 0)); + Add(new GenericBuyInfo(typeof(Garlic), 3, 20, 0xF84, 0)); + Add(new GenericBuyInfo(typeof(Ginseng), 3, 20, 0xF85, 0)); + Add(new GenericBuyInfo(typeof(MandrakeRoot), 3, 20, 0xF86, 0)); + Add(new GenericBuyInfo(typeof(Nightshade), 3, 20, 0xF88, 0)); + Add(new GenericBuyInfo(typeof(SpidersSilk), 3, 20, 0xF8D, 0)); + Add(new GenericBuyInfo(typeof(SulfurousAsh), 3, 20, 0xF8C, 0)); + + if (Core.AOS) + { + Add(new GenericBuyInfo(typeof(BatWing), 3, 999, 0xF78, 0)); + Add(new GenericBuyInfo(typeof(DaemonBlood), 6, 999, 0xF7D, 0)); + Add(new GenericBuyInfo(typeof(PigIron), 5, 999, 0xF8A, 0)); + Add(new GenericBuyInfo(typeof(NoxCrystal), 6, 999, 0xF8E, 0)); + Add(new GenericBuyInfo(typeof(GraveDust), 3, 999, 0xF8F, 0)); + } + + var types = Loot.RegularScrollTypes; + + var circles = 3; + + for (var i = 0; i < circles * 8 && i < types.Length; ++i) + { + var itemID = 0x1F2E + i; + + if (i == 6) + itemID = 0x1F2D; + else if (i > 6) + --itemID; + + Add(new GenericBuyInfo(types[i], 12 + i / 8 * 10, 20, itemID, 0)); + } + } } - Type[] types = Loot.RegularScrollTypes; - - int circles = 3; - - for (int i = 0; i < circles * 8 && i < types.Length; ++i) + public class InternalSellInfo : GenericSellInfo { - int itemID = 0x1F2E + i; + public InternalSellInfo() + { + Add(typeof(WizardsHat), 15); + Add(typeof(BlackPearl), 3); + Add(typeof(Bloodmoss), 4); + Add(typeof(MandrakeRoot), 2); + Add(typeof(Garlic), 2); + Add(typeof(Ginseng), 2); + Add(typeof(Nightshade), 2); + Add(typeof(SpidersSilk), 2); + Add(typeof(SulfurousAsh), 2); - if (i == 6) - itemID = 0x1F2D; - else if (i > 6) - --itemID; + if (Core.AOS) + { + Add(typeof(BatWing), 1); + Add(typeof(DaemonBlood), 3); + Add(typeof(PigIron), 2); + Add(typeof(NoxCrystal), 3); + Add(typeof(GraveDust), 1); + } - Add(new GenericBuyInfo(types[i], 12 + i / 8 * 10, 20, itemID, 0)); + Add(typeof(RecallRune), 13); + Add(typeof(Spellbook), 25); + + var types = Loot.RegularScrollTypes; + + for (var i = 0; i < types.Length; ++i) + Add(types[i], (i / 8 + 2) * 2); + + if (Core.SE) + { + Add(typeof(ExorcismScroll), 3); + Add(typeof(AnimateDeadScroll), 8); + Add(typeof(BloodOathScroll), 8); + Add(typeof(CorpseSkinScroll), 8); + Add(typeof(CurseWeaponScroll), 8); + Add(typeof(EvilOmenScroll), 8); + Add(typeof(PainSpikeScroll), 8); + Add(typeof(SummonFamiliarScroll), 8); + Add(typeof(HorrificBeastScroll), 8); + Add(typeof(MindRotScroll), 10); + Add(typeof(PoisonStrikeScroll), 10); + Add(typeof(WraithFormScroll), 15); + Add(typeof(LichFormScroll), 16); + Add(typeof(StrangleScroll), 16); + Add(typeof(WitherScroll), 16); + Add(typeof(VampiricEmbraceScroll), 20); + Add(typeof(VengefulSpiritScroll), 20); + } + } } - } } - - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(WizardsHat), 15); - Add(typeof(BlackPearl), 3); - Add(typeof(Bloodmoss), 4); - Add(typeof(MandrakeRoot), 2); - Add(typeof(Garlic), 2); - Add(typeof(Ginseng), 2); - Add(typeof(Nightshade), 2); - Add(typeof(SpidersSilk), 2); - Add(typeof(SulfurousAsh), 2); - - if (Core.AOS) - { - Add(typeof(BatWing), 1); - Add(typeof(DaemonBlood), 3); - Add(typeof(PigIron), 2); - Add(typeof(NoxCrystal), 3); - Add(typeof(GraveDust), 1); - } - - Add(typeof(RecallRune), 13); - Add(typeof(Spellbook), 25); - - Type[] types = Loot.RegularScrollTypes; - - for (int i = 0; i < types.Length; ++i) - Add(types[i], (i / 8 + 2) * 2); - - if (Core.SE) - { - Add(typeof(ExorcismScroll), 3); - Add(typeof(AnimateDeadScroll), 8); - Add(typeof(BloodOathScroll), 8); - Add(typeof(CorpseSkinScroll), 8); - Add(typeof(CurseWeaponScroll), 8); - Add(typeof(EvilOmenScroll), 8); - Add(typeof(PainSpikeScroll), 8); - Add(typeof(SummonFamiliarScroll), 8); - Add(typeof(HorrificBeastScroll), 8); - Add(typeof(MindRotScroll), 10); - Add(typeof(PoisonStrikeScroll), 10); - Add(typeof(WraithFormScroll), 15); - Add(typeof(LichFormScroll), 16); - Add(typeof(StrangleScroll), 16); - Add(typeof(WitherScroll), 16); - Add(typeof(VampiricEmbraceScroll), 20); - Add(typeof(VengefulSpiritScroll), 20); - } - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBMapmaker.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBMapmaker.cs index fce4e58c9..d342634b0 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBMapmaker.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBMapmaker.cs @@ -3,38 +3,38 @@ using Server.Items; namespace Server.Mobiles { - public class SBMapmaker : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBMapmaker : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(BlankMap), 5, 40, 0x14EC, 0)); - Add(new GenericBuyInfo(typeof(MapmakersPen), 8, 20, 0x0FBF, 0)); - Add(new GenericBuyInfo(typeof(BlankScroll), 12, 40, 0xEF3, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - for (int i = 0; i < PresetMapEntry.Table.Length; ++i) - Add(new PresetMapBuyInfo(PresetMapEntry.Table[i], Utility.RandomMinMax(7, 10), 20)); - } - } + public override List BuyInfo { get; } = new InternalBuyInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(BlankScroll), 6); - Add(typeof(MapmakersPen), 4); - Add(typeof(BlankMap), 2); - Add(typeof(CityMap), 3); - Add(typeof(LocalMap), 3); - Add(typeof(WorldMap), 3); - Add(typeof(PresetMapEntry), 3); - // TODO: Buy back maps that the mapmaker sells!!! - } + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(BlankMap), 5, 40, 0x14EC, 0)); + Add(new GenericBuyInfo(typeof(MapmakersPen), 8, 20, 0x0FBF, 0)); + Add(new GenericBuyInfo(typeof(BlankScroll), 12, 40, 0xEF3, 0)); + + for (var i = 0; i < PresetMapEntry.Table.Length; ++i) + Add(new PresetMapBuyInfo(PresetMapEntry.Table[i], Utility.RandomMinMax(7, 10), 20)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(BlankScroll), 6); + Add(typeof(MapmakersPen), 4); + Add(typeof(BlankMap), 2); + Add(typeof(CityMap), 3); + Add(typeof(LocalMap), 3); + Add(typeof(WorldMap), 3); + Add(typeof(PresetMapEntry), 3); + // TODO: Buy back maps that the mapmaker sells!!! + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBMiller.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBMiller.cs index d757e3cdc..0bffa30eb 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBMiller.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBMiller.cs @@ -3,28 +3,28 @@ using Server.Items; namespace Server.Mobiles { - public class SBMiller : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBMiller : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(SackFlour), 3, 20, 0x1039, 0)); - Add(new GenericBuyInfo(typeof(SheafOfHay), 2, 20, 0xF36, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(SackFlour), 1); - Add(typeof(SheafOfHay), 1); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(SackFlour), 3, 20, 0x1039, 0)); + Add(new GenericBuyInfo(typeof(SheafOfHay), 2, 20, 0xF36, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(SackFlour), 1); + Add(typeof(SheafOfHay), 1); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBMiner.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBMiner.cs index 5cc29fcec..6fb3ef438 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBMiner.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBMiner.cs @@ -3,38 +3,38 @@ using Server.Items; namespace Server.Mobiles { - public class SBMiner : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBMiner : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Bag), 6, 20, 0xE76, 0)); - Add(new GenericBuyInfo(typeof(Candle), 6, 10, 0xA28, 0)); - Add(new GenericBuyInfo(typeof(Torch), 8, 10, 0xF6B, 0)); - Add(new GenericBuyInfo(typeof(Lantern), 2, 10, 0xA25, 0)); - // Add( new GenericBuyInfo( typeof( OilFlask ), 8, 10, 0x####, 0 ) ); - Add(new GenericBuyInfo(typeof(Pickaxe), 25, 10, 0xE86, 0)); - Add(new GenericBuyInfo(typeof(Shovel), 12, 10, 0xF39, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Pickaxe), 12); - Add(typeof(Shovel), 6); - Add(typeof(Lantern), 1); - // Add( typeof( OilFlask ), 4 ); - Add(typeof(Torch), 3); - Add(typeof(Bag), 3); - Add(typeof(Candle), 3); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Bag), 6, 20, 0xE76, 0)); + Add(new GenericBuyInfo(typeof(Candle), 6, 10, 0xA28, 0)); + Add(new GenericBuyInfo(typeof(Torch), 8, 10, 0xF6B, 0)); + Add(new GenericBuyInfo(typeof(Lantern), 2, 10, 0xA25, 0)); + // Add( new GenericBuyInfo( typeof( OilFlask ), 8, 10, 0x####, 0 ) ); + Add(new GenericBuyInfo(typeof(Pickaxe), 25, 10, 0xE86, 0)); + Add(new GenericBuyInfo(typeof(Shovel), 12, 10, 0xF39, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Pickaxe), 12); + Add(typeof(Shovel), 6); + Add(typeof(Lantern), 1); + // Add( typeof( OilFlask ), 4 ); + Add(typeof(Torch), 3); + Add(typeof(Bag), 3); + Add(typeof(Candle), 3); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBMonk.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBMonk.cs index c09e086f9..36679ceec 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBMonk.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBMonk.cs @@ -3,22 +3,22 @@ using Server.Items; namespace Server.Mobiles { - public class SBMonk : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBMonk : SBInfo { - public InternalBuyInfo() - { - if (Core.AOS) Add(new GenericBuyInfo(typeof(MonkRobe), 136, 20, 0x2687, 0x21E)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + if (Core.AOS) Add(new GenericBuyInfo(typeof(MonkRobe), 136, 20, 0x2687, 0x21E)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBNinja.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBNinja.cs index 0ed1e96b9..84761c405 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBNinja.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBNinja.cs @@ -3,22 +3,22 @@ using Server.Items; namespace Server.Mobiles { - public class SBNinja : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBNinja : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(BookOfNinjitsu), 335, 20, 0x23A0, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(BookOfNinjitsu), 335, 20, 0x23A0, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBPlayerBarkeeper.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBPlayerBarkeeper.cs index b99bee276..6014e96f2 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBPlayerBarkeeper.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBPlayerBarkeeper.cs @@ -3,37 +3,37 @@ using Server.Items; namespace Server.Mobiles { - public class SBPlayerBarkeeper : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBPlayerBarkeeper : SBInfo { - public InternalBuyInfo() - { - Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Ale, 7, 20, 0x99F, 0)); - Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Wine, 7, 20, 0x9C7, 0)); - Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Liquor, 7, 20, 0x99B, 0)); - Add(new BeverageBuyInfo(typeof(Jug), BeverageType.Cider, 13, 20, 0x9C8, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Milk, 7, 20, 0x9F0, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Ale, 11, 20, 0x1F95, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Cider, 11, 20, 0x1F97, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Liquor, 11, 20, 0x1F99, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Wine, 11, 20, 0x1F9B, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Water, 11, 20, 0x1F9D, 0)); - // TODO: pizza - // TODO: bowl of *, tomato soup - Add(new GenericBuyInfo("1016450", typeof(Chessboard), 2, 20, 0xFA6, 0)); - Add(new GenericBuyInfo("1016449", typeof(CheckerBoard), 2, 20, 0xFA6, 0)); - Add(new GenericBuyInfo(typeof(Backgammon), 2, 20, 0xE1C, 0)); - Add(new GenericBuyInfo(typeof(Dices), 2, 20, 0xFA7, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Ale, 7, 20, 0x99F, 0)); + Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Wine, 7, 20, 0x9C7, 0)); + Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Liquor, 7, 20, 0x99B, 0)); + Add(new BeverageBuyInfo(typeof(Jug), BeverageType.Cider, 13, 20, 0x9C8, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Milk, 7, 20, 0x9F0, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Ale, 11, 20, 0x1F95, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Cider, 11, 20, 0x1F97, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Liquor, 11, 20, 0x1F99, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Wine, 11, 20, 0x1F9B, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Water, 11, 20, 0x1F9D, 0)); + // TODO: pizza + // TODO: bowl of *, tomato soup + Add(new GenericBuyInfo("1016450", typeof(Chessboard), 2, 20, 0xFA6, 0)); + Add(new GenericBuyInfo("1016449", typeof(CheckerBoard), 2, 20, 0xFA6, 0)); + Add(new GenericBuyInfo(typeof(Backgammon), 2, 20, 0xE1C, 0)); + Add(new GenericBuyInfo(typeof(Dices), 2, 20, 0xFA7, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBProvisioner.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBProvisioner.cs index 5a9df3144..3fe85289b 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBProvisioner.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBProvisioner.cs @@ -7,163 +7,163 @@ using Server.Multis; namespace Server.Mobiles { - public class SBProvisioner : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBProvisioner : SBInfo { - public InternalBuyInfo() - { - if (Core.ML) - Add(new GenericBuyInfo("1079931", typeof(SalvageBag), 1255, 20, 0xE76, Utility.RandomBlueHue())); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - Add(new GenericBuyInfo("1060834", typeof(PlantBowl), 2, 20, 0x15FD, 0)); + public override List BuyInfo { get; } = new InternalBuyInfo(); - Add(new GenericBuyInfo(typeof(Arrow), 2, 20, 0xF3F, 0)); - Add(new GenericBuyInfo(typeof(Bolt), 5, 20, 0x1BFB, 0)); - - Add(new GenericBuyInfo(typeof(Backpack), 15, 20, 0x9B2, 0)); - Add(new GenericBuyInfo(typeof(Pouch), 6, 20, 0xE79, 0)); - Add(new GenericBuyInfo(typeof(Bag), 6, 20, 0xE76, 0)); - - Add(new GenericBuyInfo(typeof(Candle), 6, 20, 0xA28, 0)); - Add(new GenericBuyInfo(typeof(Torch), 8, 20, 0xF6B, 0)); - Add(new GenericBuyInfo(typeof(Lantern), 2, 20, 0xA25, 0)); - - // TODO: Oil Flask @ 8GP - - Add(new GenericBuyInfo(typeof(Lockpick), 12, 20, 0x14FC, 0)); - - Add(new GenericBuyInfo(typeof(FloppyHat), 7, 20, 0x1713, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(WideBrimHat), 8, 20, 0x1714, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(Cap), 10, 20, 0x1715, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(TallStrawHat), 8, 20, 0x1716, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(StrawHat), 7, 20, 0x1717, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(WizardsHat), 11, 20, 0x1718, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(LeatherCap), 10, 20, 0x1DB9, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(FeatheredHat), 10, 20, 0x171A, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(TricorneHat), 8, 20, 0x171B, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(Bandana), 6, 20, 0x1540, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(SkullCap), 7, 20, 0x1544, Utility.RandomDyedHue())); - - Add(new GenericBuyInfo(typeof(BreadLoaf), 6, 10, 0x103B, 0)); - Add(new GenericBuyInfo(typeof(LambLeg), 8, 20, 0x160A, 0)); - Add(new GenericBuyInfo(typeof(ChickenLeg), 5, 20, 0x1608, 0)); - Add(new GenericBuyInfo(typeof(CookedBird), 17, 20, 0x9B7, 0)); - - Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Ale, 7, 20, 0x99F, 0)); - Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Wine, 7, 20, 0x9C7, 0)); - Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Liquor, 7, 20, 0x99B, 0)); - Add(new BeverageBuyInfo(typeof(Jug), BeverageType.Cider, 13, 20, 0x9C8, 0)); - - Add(new GenericBuyInfo(typeof(Pear), 3, 20, 0x994, 0)); - Add(new GenericBuyInfo(typeof(Apple), 3, 20, 0x9D0, 0)); - - Add(new GenericBuyInfo(typeof(Beeswax), 1, 20, 0x1422, 0)); - - Add(new GenericBuyInfo(typeof(Garlic), 3, 20, 0xF84, 0)); - Add(new GenericBuyInfo(typeof(Ginseng), 3, 20, 0xF85, 0)); - - Add(new GenericBuyInfo(typeof(Bottle), 5, 20, 0xF0E, 0)); - - Add(new GenericBuyInfo(typeof(RedBook), 15, 20, 0xFF1, 0)); - Add(new GenericBuyInfo(typeof(BlueBook), 15, 20, 0xFF2, 0)); - Add(new GenericBuyInfo(typeof(TanBook), 15, 20, 0xFF0, 0)); - - Add(new GenericBuyInfo(typeof(WoodenBox), 14, 20, 0xE7D, 0)); - Add(new GenericBuyInfo(typeof(Key), 2, 20, 0x100E, 0)); - - Add(new GenericBuyInfo(typeof(Bedroll), 5, 20, 0xA59, 0)); - Add(new GenericBuyInfo(typeof(Kindling), 2, 20, 0xDE1, 0)); - - Add(new GenericBuyInfo("1041205", typeof(SmallBoatDeed), 10177, 20, 0x14F2, 0)); - - Add(new GenericBuyInfo("1041060", typeof(HairDye), 60, 20, 0xEFF, 0)); - - Add(new GenericBuyInfo("1016450", typeof(Chessboard), 2, 20, 0xFA6, 0)); - Add(new GenericBuyInfo("1016449", typeof(CheckerBoard), 2, 20, 0xFA6, 0)); - Add(new GenericBuyInfo(typeof(Backgammon), 2, 20, 0xE1C, 0)); - if (Core.AOS) - Add(new GenericBuyInfo(typeof(MahjongGame), 6, 20, 0xFAA, 0)); - Add(new GenericBuyInfo(typeof(Dices), 2, 20, 0xFA7, 0)); - - if (Core.AOS) + public class InternalBuyInfo : List { - Add(new GenericBuyInfo(typeof(SmallBagBall), 3, 20, 0x2256, 0)); - Add(new GenericBuyInfo(typeof(LargeBagBall), 3, 20, 0x2257, 0)); + public InternalBuyInfo() + { + if (Core.ML) + Add(new GenericBuyInfo("1079931", typeof(SalvageBag), 1255, 20, 0xE76, Utility.RandomBlueHue())); + + Add(new GenericBuyInfo("1060834", typeof(PlantBowl), 2, 20, 0x15FD, 0)); + + Add(new GenericBuyInfo(typeof(Arrow), 2, 20, 0xF3F, 0)); + Add(new GenericBuyInfo(typeof(Bolt), 5, 20, 0x1BFB, 0)); + + Add(new GenericBuyInfo(typeof(Backpack), 15, 20, 0x9B2, 0)); + Add(new GenericBuyInfo(typeof(Pouch), 6, 20, 0xE79, 0)); + Add(new GenericBuyInfo(typeof(Bag), 6, 20, 0xE76, 0)); + + Add(new GenericBuyInfo(typeof(Candle), 6, 20, 0xA28, 0)); + Add(new GenericBuyInfo(typeof(Torch), 8, 20, 0xF6B, 0)); + Add(new GenericBuyInfo(typeof(Lantern), 2, 20, 0xA25, 0)); + + // TODO: Oil Flask @ 8GP + + Add(new GenericBuyInfo(typeof(Lockpick), 12, 20, 0x14FC, 0)); + + Add(new GenericBuyInfo(typeof(FloppyHat), 7, 20, 0x1713, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(WideBrimHat), 8, 20, 0x1714, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(Cap), 10, 20, 0x1715, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(TallStrawHat), 8, 20, 0x1716, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(StrawHat), 7, 20, 0x1717, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(WizardsHat), 11, 20, 0x1718, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(LeatherCap), 10, 20, 0x1DB9, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(FeatheredHat), 10, 20, 0x171A, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(TricorneHat), 8, 20, 0x171B, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(Bandana), 6, 20, 0x1540, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(SkullCap), 7, 20, 0x1544, Utility.RandomDyedHue())); + + Add(new GenericBuyInfo(typeof(BreadLoaf), 6, 10, 0x103B, 0)); + Add(new GenericBuyInfo(typeof(LambLeg), 8, 20, 0x160A, 0)); + Add(new GenericBuyInfo(typeof(ChickenLeg), 5, 20, 0x1608, 0)); + Add(new GenericBuyInfo(typeof(CookedBird), 17, 20, 0x9B7, 0)); + + Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Ale, 7, 20, 0x99F, 0)); + Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Wine, 7, 20, 0x9C7, 0)); + Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Liquor, 7, 20, 0x99B, 0)); + Add(new BeverageBuyInfo(typeof(Jug), BeverageType.Cider, 13, 20, 0x9C8, 0)); + + Add(new GenericBuyInfo(typeof(Pear), 3, 20, 0x994, 0)); + Add(new GenericBuyInfo(typeof(Apple), 3, 20, 0x9D0, 0)); + + Add(new GenericBuyInfo(typeof(Beeswax), 1, 20, 0x1422, 0)); + + Add(new GenericBuyInfo(typeof(Garlic), 3, 20, 0xF84, 0)); + Add(new GenericBuyInfo(typeof(Ginseng), 3, 20, 0xF85, 0)); + + Add(new GenericBuyInfo(typeof(Bottle), 5, 20, 0xF0E, 0)); + + Add(new GenericBuyInfo(typeof(RedBook), 15, 20, 0xFF1, 0)); + Add(new GenericBuyInfo(typeof(BlueBook), 15, 20, 0xFF2, 0)); + Add(new GenericBuyInfo(typeof(TanBook), 15, 20, 0xFF0, 0)); + + Add(new GenericBuyInfo(typeof(WoodenBox), 14, 20, 0xE7D, 0)); + Add(new GenericBuyInfo(typeof(Key), 2, 20, 0x100E, 0)); + + Add(new GenericBuyInfo(typeof(Bedroll), 5, 20, 0xA59, 0)); + Add(new GenericBuyInfo(typeof(Kindling), 2, 20, 0xDE1, 0)); + + Add(new GenericBuyInfo("1041205", typeof(SmallBoatDeed), 10177, 20, 0x14F2, 0)); + + Add(new GenericBuyInfo("1041060", typeof(HairDye), 60, 20, 0xEFF, 0)); + + Add(new GenericBuyInfo("1016450", typeof(Chessboard), 2, 20, 0xFA6, 0)); + Add(new GenericBuyInfo("1016449", typeof(CheckerBoard), 2, 20, 0xFA6, 0)); + Add(new GenericBuyInfo(typeof(Backgammon), 2, 20, 0xE1C, 0)); + if (Core.AOS) + Add(new GenericBuyInfo(typeof(MahjongGame), 6, 20, 0xFAA, 0)); + Add(new GenericBuyInfo(typeof(Dices), 2, 20, 0xFA7, 0)); + + if (Core.AOS) + { + Add(new GenericBuyInfo(typeof(SmallBagBall), 3, 20, 0x2256, 0)); + Add(new GenericBuyInfo(typeof(LargeBagBall), 3, 20, 0x2257, 0)); + } + + if (!Guild.NewGuildSystem) + Add(new GenericBuyInfo("1041055", typeof(GuildDeed), 12450, 20, 0x14F0, 0)); + } } - if (!Guild.NewGuildSystem) - Add(new GenericBuyInfo("1041055", typeof(GuildDeed), 12450, 20, 0x14F0, 0)); - } + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Arrow), 1); + Add(typeof(Bolt), 2); + Add(typeof(Backpack), 7); + Add(typeof(Pouch), 3); + Add(typeof(Bag), 3); + Add(typeof(Candle), 3); + Add(typeof(Torch), 4); + Add(typeof(Lantern), 1); + Add(typeof(Lockpick), 6); + Add(typeof(FloppyHat), 3); + Add(typeof(WideBrimHat), 4); + Add(typeof(Cap), 5); + Add(typeof(TallStrawHat), 4); + Add(typeof(StrawHat), 3); + Add(typeof(WizardsHat), 5); + Add(typeof(LeatherCap), 5); + Add(typeof(FeatheredHat), 5); + Add(typeof(TricorneHat), 4); + Add(typeof(Bandana), 3); + Add(typeof(SkullCap), 3); + Add(typeof(Bottle), 3); + Add(typeof(RedBook), 7); + Add(typeof(BlueBook), 7); + Add(typeof(TanBook), 7); + Add(typeof(WoodenBox), 7); + Add(typeof(Kindling), 1); + Add(typeof(HairDye), 30); + Add(typeof(Chessboard), 1); + Add(typeof(CheckerBoard), 1); + Add(typeof(Backgammon), 1); + Add(typeof(Dices), 1); + + Add(typeof(Beeswax), 1); + + Add(typeof(Amber), 25); + Add(typeof(Amethyst), 50); + Add(typeof(Citrine), 25); + Add(typeof(Diamond), 100); + Add(typeof(Emerald), 50); + Add(typeof(Ruby), 37); + Add(typeof(Sapphire), 50); + Add(typeof(StarSapphire), 62); + Add(typeof(Tourmaline), 47); + Add(typeof(GoldRing), 13); + Add(typeof(SilverRing), 10); + Add(typeof(Necklace), 13); + Add(typeof(GoldNecklace), 13); + Add(typeof(GoldBeadNecklace), 13); + Add(typeof(SilverNecklace), 10); + Add(typeof(SilverBeadNecklace), 10); + Add(typeof(Beads), 13); + Add(typeof(GoldBracelet), 13); + Add(typeof(SilverBracelet), 10); + Add(typeof(GoldEarrings), 13); + Add(typeof(SilverEarrings), 10); + + if (!Guild.NewGuildSystem) + Add(typeof(GuildDeed), 6225); + } + } } - - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Arrow), 1); - Add(typeof(Bolt), 2); - Add(typeof(Backpack), 7); - Add(typeof(Pouch), 3); - Add(typeof(Bag), 3); - Add(typeof(Candle), 3); - Add(typeof(Torch), 4); - Add(typeof(Lantern), 1); - Add(typeof(Lockpick), 6); - Add(typeof(FloppyHat), 3); - Add(typeof(WideBrimHat), 4); - Add(typeof(Cap), 5); - Add(typeof(TallStrawHat), 4); - Add(typeof(StrawHat), 3); - Add(typeof(WizardsHat), 5); - Add(typeof(LeatherCap), 5); - Add(typeof(FeatheredHat), 5); - Add(typeof(TricorneHat), 4); - Add(typeof(Bandana), 3); - Add(typeof(SkullCap), 3); - Add(typeof(Bottle), 3); - Add(typeof(RedBook), 7); - Add(typeof(BlueBook), 7); - Add(typeof(TanBook), 7); - Add(typeof(WoodenBox), 7); - Add(typeof(Kindling), 1); - Add(typeof(HairDye), 30); - Add(typeof(Chessboard), 1); - Add(typeof(CheckerBoard), 1); - Add(typeof(Backgammon), 1); - Add(typeof(Dices), 1); - - Add(typeof(Beeswax), 1); - - Add(typeof(Amber), 25); - Add(typeof(Amethyst), 50); - Add(typeof(Citrine), 25); - Add(typeof(Diamond), 100); - Add(typeof(Emerald), 50); - Add(typeof(Ruby), 37); - Add(typeof(Sapphire), 50); - Add(typeof(StarSapphire), 62); - Add(typeof(Tourmaline), 47); - Add(typeof(GoldRing), 13); - Add(typeof(SilverRing), 10); - Add(typeof(Necklace), 13); - Add(typeof(GoldNecklace), 13); - Add(typeof(GoldBeadNecklace), 13); - Add(typeof(SilverNecklace), 10); - Add(typeof(SilverBeadNecklace), 10); - Add(typeof(Beads), 13); - Add(typeof(GoldBracelet), 13); - Add(typeof(SilverBracelet), 10); - Add(typeof(GoldEarrings), 13); - Add(typeof(SilverEarrings), 10); - - if (!Guild.NewGuildSystem) - Add(typeof(GuildDeed), 6225); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBRancher.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBRancher.cs index 63ed3ff91..209b161f2 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBRancher.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBRancher.cs @@ -2,22 +2,22 @@ using System.Collections.Generic; namespace Server.Mobiles { - public class SBRancher : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBRancher : SBInfo { - public InternalBuyInfo() - { - Add(new AnimalBuyInfo(1, typeof(PackHorse), 631, 10, 291, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new AnimalBuyInfo(1, typeof(PackHorse), 631, 10, 291, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBRanger.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBRanger.cs index 603a126a8..ed1850589 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBRanger.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBRanger.cs @@ -3,26 +3,26 @@ using Server.Items; namespace Server.Mobiles { - public class SBRanger : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBRanger : SBInfo { - public InternalBuyInfo() - { - Add(new AnimalBuyInfo(1, typeof(Cat), 138, 20, 201, 0)); - Add(new AnimalBuyInfo(1, typeof(Dog), 181, 20, 217, 0)); - Add(new AnimalBuyInfo(1, typeof(PackLlama), 491, 20, 292, 0)); - Add(new AnimalBuyInfo(1, typeof(PackHorse), 606, 20, 291, 0)); - Add(new GenericBuyInfo(typeof(Bandage), 5, 20, 0xE21, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new AnimalBuyInfo(1, typeof(Cat), 138, 20, 201, 0)); + Add(new AnimalBuyInfo(1, typeof(Dog), 181, 20, 217, 0)); + Add(new AnimalBuyInfo(1, typeof(PackLlama), 491, 20, 292, 0)); + Add(new AnimalBuyInfo(1, typeof(PackHorse), 606, 20, 291, 0)); + Add(new GenericBuyInfo(typeof(Bandage), 5, 20, 0xE21, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBRealEstateBroker.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBRealEstateBroker.cs index 606f73bec..4946f5972 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBRealEstateBroker.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBRealEstateBroker.cs @@ -3,28 +3,28 @@ using Server.Items; namespace Server.Mobiles { - public class SBRealEstateBroker : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBRealEstateBroker : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(BlankScroll), 5, 20, 0x0E34, 0)); - Add(new GenericBuyInfo(typeof(ScribesPen), 8, 20, 0xFBF, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(ScribesPen), 4); - Add(typeof(BlankScroll), 2); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(BlankScroll), 5, 20, 0x0E34, 0)); + Add(new GenericBuyInfo(typeof(ScribesPen), 8, 20, 0xFBF, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(ScribesPen), 4); + Add(typeof(BlankScroll), 2); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBSECook.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBSECook.cs index a6eccaac7..8ba98f560 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBSECook.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBSECook.cs @@ -3,44 +3,44 @@ using Server.Items; namespace Server.Mobiles { - public class SBSECook : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBSECook : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Wasabi), 2, 20, 0x24E8, 0)); - Add(new GenericBuyInfo(typeof(Wasabi), 2, 20, 0x24E9, 0)); - Add(new GenericBuyInfo(typeof(SushiRolls), 3, 20, 0x283E, 0)); - Add(new GenericBuyInfo(typeof(SushiPlatter), 3, 20, 0x2840, 0)); - Add(new GenericBuyInfo(typeof(GreenTea), 3, 20, 0x284C, 0)); - Add(new GenericBuyInfo(typeof(MisoSoup), 3, 20, 0x284D, 0)); - Add(new GenericBuyInfo(typeof(WhiteMisoSoup), 3, 20, 0x284E, 0)); - Add(new GenericBuyInfo(typeof(RedMisoSoup), 3, 20, 0x284F, 0)); - Add(new GenericBuyInfo(typeof(AwaseMisoSoup), 3, 20, 0x2850, 0)); - Add(new GenericBuyInfo(typeof(BentoBox), 6, 20, 0x2836, 0)); - Add(new GenericBuyInfo(typeof(BentoBox), 6, 20, 0x2837, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Wasabi), 1); - Add(typeof(BentoBox), 3); - Add(typeof(GreenTea), 1); - Add(typeof(SushiRolls), 1); - Add(typeof(SushiPlatter), 2); - Add(typeof(MisoSoup), 1); - Add(typeof(RedMisoSoup), 1); - Add(typeof(WhiteMisoSoup), 1); - Add(typeof(AwaseMisoSoup), 1); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Wasabi), 2, 20, 0x24E8, 0)); + Add(new GenericBuyInfo(typeof(Wasabi), 2, 20, 0x24E9, 0)); + Add(new GenericBuyInfo(typeof(SushiRolls), 3, 20, 0x283E, 0)); + Add(new GenericBuyInfo(typeof(SushiPlatter), 3, 20, 0x2840, 0)); + Add(new GenericBuyInfo(typeof(GreenTea), 3, 20, 0x284C, 0)); + Add(new GenericBuyInfo(typeof(MisoSoup), 3, 20, 0x284D, 0)); + Add(new GenericBuyInfo(typeof(WhiteMisoSoup), 3, 20, 0x284E, 0)); + Add(new GenericBuyInfo(typeof(RedMisoSoup), 3, 20, 0x284F, 0)); + Add(new GenericBuyInfo(typeof(AwaseMisoSoup), 3, 20, 0x2850, 0)); + Add(new GenericBuyInfo(typeof(BentoBox), 6, 20, 0x2836, 0)); + Add(new GenericBuyInfo(typeof(BentoBox), 6, 20, 0x2837, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Wasabi), 1); + Add(typeof(BentoBox), 3); + Add(typeof(GreenTea), 1); + Add(typeof(SushiRolls), 1); + Add(typeof(SushiPlatter), 2); + Add(typeof(MisoSoup), 1); + Add(typeof(RedMisoSoup), 1); + Add(typeof(WhiteMisoSoup), 1); + Add(typeof(AwaseMisoSoup), 1); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBSEHats.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBSEHats.cs index a72cd448d..023258f01 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBSEHats.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBSEHats.cs @@ -3,30 +3,30 @@ using Server.Items; namespace Server.Mobiles { - public class SBSEHats : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBSEHats : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Kasa), 31, 20, 0x2798, 0)); - Add(new GenericBuyInfo(typeof(LeatherJingasa), 11, 20, 0x2776, 0)); - Add(new GenericBuyInfo(typeof(ClothNinjaHood), 33, 20, 0x278F, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Kasa), 15); - Add(typeof(LeatherJingasa), 5); - Add(typeof(ClothNinjaHood), 16); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Kasa), 31, 20, 0x2798, 0)); + Add(new GenericBuyInfo(typeof(LeatherJingasa), 11, 20, 0x2776, 0)); + Add(new GenericBuyInfo(typeof(ClothNinjaHood), 33, 20, 0x278F, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Kasa), 15); + Add(typeof(LeatherJingasa), 5); + Add(typeof(ClothNinjaHood), 16); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBSamurai.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBSamurai.cs index 1be4ac760..b1a0c0b9b 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBSamurai.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBSamurai.cs @@ -3,22 +3,22 @@ using Server.Items; namespace Server.Mobiles { - public class SBSamurai : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBSamurai : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(BookOfBushido), 280, 20, 0x238C, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(BookOfBushido), 280, 20, 0x238C, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBScribe.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBScribe.cs index 82a88dafb..f3aba4cd6 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBScribe.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBScribe.cs @@ -3,36 +3,36 @@ using Server.Items; namespace Server.Mobiles { - public class SBScribe : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBScribe : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(ScribesPen), 8, 20, 0xFBF, 0)); - Add(new GenericBuyInfo(typeof(BlankScroll), 5, 999, 0x0E34, 0)); - Add(new GenericBuyInfo(typeof(ScribesPen), 8, 20, 0xFC0, 0)); - Add(new GenericBuyInfo(typeof(BrownBook), 15, 10, 0xFEF, 0)); - Add(new GenericBuyInfo(typeof(TanBook), 15, 10, 0xFF0, 0)); - Add(new GenericBuyInfo(typeof(BlueBook), 15, 10, 0xFF2, 0)); - // Add( new GenericBuyInfo( "1041267", typeof( Runebook ), 3500, 10, 0xEFA, 0x461 ) ); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(ScribesPen), 4); - Add(typeof(BrownBook), 7); - Add(typeof(TanBook), 7); - Add(typeof(BlueBook), 7); - Add(typeof(BlankScroll), 3); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(ScribesPen), 8, 20, 0xFBF, 0)); + Add(new GenericBuyInfo(typeof(BlankScroll), 5, 999, 0x0E34, 0)); + Add(new GenericBuyInfo(typeof(ScribesPen), 8, 20, 0xFC0, 0)); + Add(new GenericBuyInfo(typeof(BrownBook), 15, 10, 0xFEF, 0)); + Add(new GenericBuyInfo(typeof(TanBook), 15, 10, 0xFF0, 0)); + Add(new GenericBuyInfo(typeof(BlueBook), 15, 10, 0xFF2, 0)); + // Add( new GenericBuyInfo( "1041267", typeof( Runebook ), 3500, 10, 0xEFA, 0x461 ) ); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(ScribesPen), 4); + Add(typeof(BrownBook), 7); + Add(typeof(TanBook), 7); + Add(typeof(BlueBook), 7); + Add(typeof(BlankScroll), 3); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBShipwright.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBShipwright.cs index 61714a15e..564e8b68f 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBShipwright.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBShipwright.cs @@ -3,27 +3,27 @@ using Server.Multis; namespace Server.Mobiles { - public class SBShipwright : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBShipwright : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo("1041205", typeof(SmallBoatDeed), 10177, 20, 0x14F2, 0)); - Add(new GenericBuyInfo("1041206", typeof(SmallDragonBoatDeed), 10177, 20, 0x14F2, 0)); - Add(new GenericBuyInfo("1041207", typeof(MediumBoatDeed), 11552, 20, 0x14F2, 0)); - Add(new GenericBuyInfo("1041208", typeof(MediumDragonBoatDeed), 11552, 20, 0x14F2, 0)); - Add(new GenericBuyInfo("1041209", typeof(LargeBoatDeed), 12927, 20, 0x14F2, 0)); - Add(new GenericBuyInfo("1041210", typeof(LargeDragonBoatDeed), 12927, 20, 0x14F2, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo("1041205", typeof(SmallBoatDeed), 10177, 20, 0x14F2, 0)); + Add(new GenericBuyInfo("1041206", typeof(SmallDragonBoatDeed), 10177, 20, 0x14F2, 0)); + Add(new GenericBuyInfo("1041207", typeof(MediumBoatDeed), 11552, 20, 0x14F2, 0)); + Add(new GenericBuyInfo("1041208", typeof(MediumDragonBoatDeed), 11552, 20, 0x14F2, 0)); + Add(new GenericBuyInfo("1041209", typeof(LargeBoatDeed), 12927, 20, 0x14F2, 0)); + Add(new GenericBuyInfo("1041210", typeof(LargeDragonBoatDeed), 12927, 20, 0x14F2, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBSmithTools.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBSmithTools.cs index 288864540..a33806500 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBSmithTools.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBSmithTools.cs @@ -3,28 +3,28 @@ using Server.Items; namespace Server.Mobiles { - public class SBSmithTools : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBSmithTools : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(IronIngot), 5, 16, 0x1BF2, 0)); - Add(new GenericBuyInfo(typeof(Tongs), 13, 14, 0xFBB, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Tongs), 7); - Add(typeof(IronIngot), 4); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(IronIngot), 5, 16, 0x1BF2, 0)); + Add(new GenericBuyInfo(typeof(Tongs), 13, 14, 0xFBB, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Tongs), 7); + Add(typeof(IronIngot), 4); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBStoneCrafter.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBStoneCrafter.cs index 70a48239c..4164898f4 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBStoneCrafter.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBStoneCrafter.cs @@ -3,87 +3,87 @@ using Server.Items; namespace Server.Mobiles { - public class SBStoneCrafter : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBStoneCrafter : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Nails), 3, 20, 0x102E, 0)); - Add(new GenericBuyInfo(typeof(Axle), 2, 20, 0x105B, 0)); - Add(new GenericBuyInfo(typeof(Board), 3, 20, 0x1BD7, 0)); - Add(new GenericBuyInfo(typeof(DrawKnife), 10, 20, 0x10E4, 0)); - Add(new GenericBuyInfo(typeof(Froe), 10, 20, 0x10E5, 0)); - Add(new GenericBuyInfo(typeof(Scorp), 10, 20, 0x10E7, 0)); - Add(new GenericBuyInfo(typeof(Inshave), 10, 20, 0x10E6, 0)); - Add(new GenericBuyInfo(typeof(DovetailSaw), 12, 20, 0x1028, 0)); - Add(new GenericBuyInfo(typeof(Saw), 15, 20, 0x1034, 0)); - Add(new GenericBuyInfo(typeof(Hammer), 17, 20, 0x102A, 0)); - Add(new GenericBuyInfo(typeof(MouldingPlane), 11, 20, 0x102C, 0)); - Add(new GenericBuyInfo(typeof(SmoothingPlane), 10, 20, 0x1032, 0)); - Add(new GenericBuyInfo(typeof(JointingPlane), 11, 20, 0x1030, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - Add(new GenericBuyInfo("Making Valuables With Stonecrafting", typeof(MasonryBook), 10625, 10, 0xFBE, 0)); - Add(new GenericBuyInfo("Mining For Quality Stone", typeof(StoneMiningBook), 10625, 10, 0xFBE, 0)); - Add(new GenericBuyInfo("1044515", typeof(MalletAndChisel), 3, 50, 0x12B3, 0)); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Nails), 3, 20, 0x102E, 0)); + Add(new GenericBuyInfo(typeof(Axle), 2, 20, 0x105B, 0)); + Add(new GenericBuyInfo(typeof(Board), 3, 20, 0x1BD7, 0)); + Add(new GenericBuyInfo(typeof(DrawKnife), 10, 20, 0x10E4, 0)); + Add(new GenericBuyInfo(typeof(Froe), 10, 20, 0x10E5, 0)); + Add(new GenericBuyInfo(typeof(Scorp), 10, 20, 0x10E7, 0)); + Add(new GenericBuyInfo(typeof(Inshave), 10, 20, 0x10E6, 0)); + Add(new GenericBuyInfo(typeof(DovetailSaw), 12, 20, 0x1028, 0)); + Add(new GenericBuyInfo(typeof(Saw), 15, 20, 0x1034, 0)); + Add(new GenericBuyInfo(typeof(Hammer), 17, 20, 0x102A, 0)); + Add(new GenericBuyInfo(typeof(MouldingPlane), 11, 20, 0x102C, 0)); + Add(new GenericBuyInfo(typeof(SmoothingPlane), 10, 20, 0x1032, 0)); + Add(new GenericBuyInfo(typeof(JointingPlane), 11, 20, 0x1030, 0)); + + Add(new GenericBuyInfo("Making Valuables With Stonecrafting", typeof(MasonryBook), 10625, 10, 0xFBE, 0)); + Add(new GenericBuyInfo("Mining For Quality Stone", typeof(StoneMiningBook), 10625, 10, 0xFBE, 0)); + Add(new GenericBuyInfo("1044515", typeof(MalletAndChisel), 3, 50, 0x12B3, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(MasonryBook), 5000); + Add(typeof(StoneMiningBook), 5000); + Add(typeof(MalletAndChisel), 1); + + Add(typeof(WoodenBox), 7); + Add(typeof(SmallCrate), 5); + Add(typeof(MediumCrate), 6); + Add(typeof(LargeCrate), 7); + Add(typeof(WoodenChest), 15); + + Add(typeof(LargeTable), 10); + Add(typeof(Nightstand), 7); + Add(typeof(YewWoodTable), 10); + + Add(typeof(Throne), 24); + Add(typeof(WoodenThrone), 6); + Add(typeof(Stool), 6); + Add(typeof(FootStool), 6); + + Add(typeof(FancyWoodenChairCushion), 12); + Add(typeof(WoodenChairCushion), 10); + Add(typeof(WoodenChair), 8); + Add(typeof(BambooChair), 6); + Add(typeof(WoodenBench), 6); + + Add(typeof(Saw), 9); + Add(typeof(Scorp), 6); + Add(typeof(SmoothingPlane), 6); + Add(typeof(DrawKnife), 6); + Add(typeof(Froe), 6); + Add(typeof(Hammer), 14); + Add(typeof(Inshave), 6); + Add(typeof(JointingPlane), 6); + Add(typeof(MouldingPlane), 6); + Add(typeof(DovetailSaw), 7); + Add(typeof(Board), 2); + Add(typeof(Axle), 1); + + Add(typeof(WoodenShield), 31); + Add(typeof(BlackStaff), 24); + Add(typeof(GnarledStaff), 12); + Add(typeof(QuarterStaff), 15); + Add(typeof(ShepherdsCrook), 12); + Add(typeof(Club), 13); + + Add(typeof(Log), 1); + } + } } - - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(MasonryBook), 5000); - Add(typeof(StoneMiningBook), 5000); - Add(typeof(MalletAndChisel), 1); - - Add(typeof(WoodenBox), 7); - Add(typeof(SmallCrate), 5); - Add(typeof(MediumCrate), 6); - Add(typeof(LargeCrate), 7); - Add(typeof(WoodenChest), 15); - - Add(typeof(LargeTable), 10); - Add(typeof(Nightstand), 7); - Add(typeof(YewWoodTable), 10); - - Add(typeof(Throne), 24); - Add(typeof(WoodenThrone), 6); - Add(typeof(Stool), 6); - Add(typeof(FootStool), 6); - - Add(typeof(FancyWoodenChairCushion), 12); - Add(typeof(WoodenChairCushion), 10); - Add(typeof(WoodenChair), 8); - Add(typeof(BambooChair), 6); - Add(typeof(WoodenBench), 6); - - Add(typeof(Saw), 9); - Add(typeof(Scorp), 6); - Add(typeof(SmoothingPlane), 6); - Add(typeof(DrawKnife), 6); - Add(typeof(Froe), 6); - Add(typeof(Hammer), 14); - Add(typeof(Inshave), 6); - Add(typeof(JointingPlane), 6); - Add(typeof(MouldingPlane), 6); - Add(typeof(DovetailSaw), 7); - Add(typeof(Board), 2); - Add(typeof(Axle), 1); - - Add(typeof(WoodenShield), 31); - Add(typeof(BlackStaff), 24); - Add(typeof(GnarledStaff), 12); - Add(typeof(QuarterStaff), 15); - Add(typeof(ShepherdsCrook), 12); - Add(typeof(Club), 13); - - Add(typeof(Log), 1); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBTailor.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBTailor.cs index 22a21cd0d..c81e7208a 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBTailor.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBTailor.cs @@ -3,113 +3,113 @@ using Server.Items; namespace Server.Mobiles { - public class SBTailor : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBTailor : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(SewingKit), 3, 20, 0xF9D, 0)); - Add(new GenericBuyInfo(typeof(Scissors), 11, 20, 0xF9F, 0)); - Add(new GenericBuyInfo(typeof(DyeTub), 8, 20, 0xFAB, 0)); - Add(new GenericBuyInfo(typeof(Dyes), 8, 20, 0xFA9, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - Add(new GenericBuyInfo(typeof(Shirt), 12, 20, 0x1517, 0)); - Add(new GenericBuyInfo(typeof(ShortPants), 7, 20, 0x152E, 0)); - Add(new GenericBuyInfo(typeof(FancyShirt), 21, 20, 0x1EFD, 0)); - Add(new GenericBuyInfo(typeof(LongPants), 10, 20, 0x1539, 0)); - Add(new GenericBuyInfo(typeof(FancyDress), 26, 20, 0x1EFF, 0)); - Add(new GenericBuyInfo(typeof(PlainDress), 13, 20, 0x1F01, 0)); - Add(new GenericBuyInfo(typeof(Kilt), 11, 20, 0x1537, 0)); - Add(new GenericBuyInfo(typeof(Kilt), 11, 20, 0x1537, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(HalfApron), 10, 20, 0x153b, 0)); - Add(new GenericBuyInfo(typeof(Robe), 18, 20, 0x1F03, 0)); - Add(new GenericBuyInfo(typeof(Cloak), 8, 20, 0x1515, 0)); - Add(new GenericBuyInfo(typeof(Cloak), 8, 20, 0x1515, 0)); - Add(new GenericBuyInfo(typeof(Doublet), 13, 20, 0x1F7B, 0)); - Add(new GenericBuyInfo(typeof(Tunic), 18, 20, 0x1FA1, 0)); - Add(new GenericBuyInfo(typeof(JesterSuit), 26, 20, 0x1F9F, 0)); + public override List BuyInfo { get; } = new InternalBuyInfo(); - Add(new GenericBuyInfo(typeof(JesterHat), 12, 20, 0x171C, 0)); - Add(new GenericBuyInfo(typeof(FloppyHat), 7, 20, 0x1713, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(WideBrimHat), 8, 20, 0x1714, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(Cap), 10, 20, 0x1715, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(TallStrawHat), 8, 20, 0x1716, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(StrawHat), 7, 20, 0x1717, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(WizardsHat), 11, 20, 0x1718, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(LeatherCap), 10, 20, 0x1DB9, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(FeatheredHat), 10, 20, 0x171A, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(TricorneHat), 8, 20, 0x171B, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(Bandana), 6, 20, 0x1540, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(SkullCap), 7, 20, 0x1544, Utility.RandomDyedHue())); + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(SewingKit), 3, 20, 0xF9D, 0)); + Add(new GenericBuyInfo(typeof(Scissors), 11, 20, 0xF9F, 0)); + Add(new GenericBuyInfo(typeof(DyeTub), 8, 20, 0xFAB, 0)); + Add(new GenericBuyInfo(typeof(Dyes), 8, 20, 0xFA9, 0)); - Add(new GenericBuyInfo(typeof(BoltOfCloth), 100, 20, 0xf95, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(Shirt), 12, 20, 0x1517, 0)); + Add(new GenericBuyInfo(typeof(ShortPants), 7, 20, 0x152E, 0)); + Add(new GenericBuyInfo(typeof(FancyShirt), 21, 20, 0x1EFD, 0)); + Add(new GenericBuyInfo(typeof(LongPants), 10, 20, 0x1539, 0)); + Add(new GenericBuyInfo(typeof(FancyDress), 26, 20, 0x1EFF, 0)); + Add(new GenericBuyInfo(typeof(PlainDress), 13, 20, 0x1F01, 0)); + Add(new GenericBuyInfo(typeof(Kilt), 11, 20, 0x1537, 0)); + Add(new GenericBuyInfo(typeof(Kilt), 11, 20, 0x1537, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(HalfApron), 10, 20, 0x153b, 0)); + Add(new GenericBuyInfo(typeof(Robe), 18, 20, 0x1F03, 0)); + Add(new GenericBuyInfo(typeof(Cloak), 8, 20, 0x1515, 0)); + Add(new GenericBuyInfo(typeof(Cloak), 8, 20, 0x1515, 0)); + Add(new GenericBuyInfo(typeof(Doublet), 13, 20, 0x1F7B, 0)); + Add(new GenericBuyInfo(typeof(Tunic), 18, 20, 0x1FA1, 0)); + Add(new GenericBuyInfo(typeof(JesterSuit), 26, 20, 0x1F9F, 0)); - Add(new GenericBuyInfo(typeof(Cloth), 2, 20, 0x1766, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(UncutCloth), 2, 20, 0x1767, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(JesterHat), 12, 20, 0x171C, 0)); + Add(new GenericBuyInfo(typeof(FloppyHat), 7, 20, 0x1713, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(WideBrimHat), 8, 20, 0x1714, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(Cap), 10, 20, 0x1715, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(TallStrawHat), 8, 20, 0x1716, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(StrawHat), 7, 20, 0x1717, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(WizardsHat), 11, 20, 0x1718, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(LeatherCap), 10, 20, 0x1DB9, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(FeatheredHat), 10, 20, 0x171A, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(TricorneHat), 8, 20, 0x171B, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(Bandana), 6, 20, 0x1540, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(SkullCap), 7, 20, 0x1544, Utility.RandomDyedHue())); - Add(new GenericBuyInfo(typeof(Cotton), 102, 20, 0xDF9, 0)); - Add(new GenericBuyInfo(typeof(Wool), 62, 20, 0xDF8, 0)); - Add(new GenericBuyInfo(typeof(Flax), 102, 20, 0x1A9C, 0)); - Add(new GenericBuyInfo(typeof(SpoolOfThread), 18, 20, 0xFA0, 0)); - } + Add(new GenericBuyInfo(typeof(BoltOfCloth), 100, 20, 0xf95, Utility.RandomDyedHue())); + + Add(new GenericBuyInfo(typeof(Cloth), 2, 20, 0x1766, Utility.RandomDyedHue())); + Add(new GenericBuyInfo(typeof(UncutCloth), 2, 20, 0x1767, Utility.RandomDyedHue())); + + Add(new GenericBuyInfo(typeof(Cotton), 102, 20, 0xDF9, 0)); + Add(new GenericBuyInfo(typeof(Wool), 62, 20, 0xDF8, 0)); + Add(new GenericBuyInfo(typeof(Flax), 102, 20, 0x1A9C, 0)); + Add(new GenericBuyInfo(typeof(SpoolOfThread), 18, 20, 0xFA0, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Scissors), 6); + Add(typeof(SewingKit), 1); + Add(typeof(Dyes), 4); + Add(typeof(DyeTub), 4); + + Add(typeof(BoltOfCloth), 50); + + Add(typeof(FancyShirt), 10); + Add(typeof(Shirt), 6); + + Add(typeof(ShortPants), 3); + Add(typeof(LongPants), 5); + + Add(typeof(Cloak), 4); + Add(typeof(FancyDress), 12); + Add(typeof(Robe), 9); + Add(typeof(PlainDress), 7); + + Add(typeof(Skirt), 5); + Add(typeof(Kilt), 5); + + Add(typeof(Doublet), 7); + Add(typeof(Tunic), 9); + Add(typeof(JesterSuit), 13); + + Add(typeof(FullApron), 5); + Add(typeof(HalfApron), 5); + + Add(typeof(JesterHat), 6); + Add(typeof(FloppyHat), 3); + Add(typeof(WideBrimHat), 4); + Add(typeof(Cap), 5); + Add(typeof(SkullCap), 3); + Add(typeof(Bandana), 3); + Add(typeof(TallStrawHat), 4); + Add(typeof(StrawHat), 4); + Add(typeof(WizardsHat), 5); + Add(typeof(Bonnet), 4); + Add(typeof(FeatheredHat), 5); + Add(typeof(TricorneHat), 4); + + Add(typeof(SpoolOfThread), 9); + + Add(typeof(Flax), 51); + Add(typeof(Cotton), 51); + Add(typeof(Wool), 31); + } + } } - - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Scissors), 6); - Add(typeof(SewingKit), 1); - Add(typeof(Dyes), 4); - Add(typeof(DyeTub), 4); - - Add(typeof(BoltOfCloth), 50); - - Add(typeof(FancyShirt), 10); - Add(typeof(Shirt), 6); - - Add(typeof(ShortPants), 3); - Add(typeof(LongPants), 5); - - Add(typeof(Cloak), 4); - Add(typeof(FancyDress), 12); - Add(typeof(Robe), 9); - Add(typeof(PlainDress), 7); - - Add(typeof(Skirt), 5); - Add(typeof(Kilt), 5); - - Add(typeof(Doublet), 7); - Add(typeof(Tunic), 9); - Add(typeof(JesterSuit), 13); - - Add(typeof(FullApron), 5); - Add(typeof(HalfApron), 5); - - Add(typeof(JesterHat), 6); - Add(typeof(FloppyHat), 3); - Add(typeof(WideBrimHat), 4); - Add(typeof(Cap), 5); - Add(typeof(SkullCap), 3); - Add(typeof(Bandana), 3); - Add(typeof(TallStrawHat), 4); - Add(typeof(StrawHat), 4); - Add(typeof(WizardsHat), 5); - Add(typeof(Bonnet), 4); - Add(typeof(FeatheredHat), 5); - Add(typeof(TricorneHat), 4); - - Add(typeof(SpoolOfThread), 9); - - Add(typeof(Flax), 51); - Add(typeof(Cotton), 51); - Add(typeof(Wool), 31); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBTanner.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBTanner.cs index d1a326909..95d9a2435 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBTanner.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBTanner.cs @@ -3,83 +3,83 @@ using Server.Items; namespace Server.Mobiles { - public class SBTanner : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBTanner : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(LeatherGorget), 31, 20, 0x13C7, 0)); - Add(new GenericBuyInfo(typeof(LeatherCap), 10, 20, 0x1DB9, 0)); - Add(new GenericBuyInfo(typeof(LeatherArms), 37, 20, 0x13CD, 0)); - Add(new GenericBuyInfo(typeof(LeatherChest), 47, 20, 0x13CC, 0)); - Add(new GenericBuyInfo(typeof(LeatherLegs), 36, 20, 0x13CB, 0)); - Add(new GenericBuyInfo(typeof(LeatherGloves), 31, 20, 0x13C6, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - Add(new GenericBuyInfo(typeof(StuddedGorget), 50, 20, 0x13D6, 0)); - Add(new GenericBuyInfo(typeof(StuddedArms), 57, 20, 0x13DC, 0)); - Add(new GenericBuyInfo(typeof(StuddedChest), 75, 20, 0x13DB, 0)); - Add(new GenericBuyInfo(typeof(StuddedLegs), 67, 20, 0x13DA, 0)); - Add(new GenericBuyInfo(typeof(StuddedGloves), 45, 20, 0x13D5, 0)); + public override List BuyInfo { get; } = new InternalBuyInfo(); - Add(new GenericBuyInfo(typeof(FemaleStuddedChest), 62, 20, 0x1C02, 0)); - Add(new GenericBuyInfo(typeof(FemalePlateChest), 207, 20, 0x1C04, 0)); - Add(new GenericBuyInfo(typeof(FemaleLeatherChest), 36, 20, 0x1C06, 0)); - Add(new GenericBuyInfo(typeof(LeatherShorts), 28, 20, 0x1C00, 0)); - Add(new GenericBuyInfo(typeof(LeatherSkirt), 25, 20, 0x1C08, 0)); - Add(new GenericBuyInfo(typeof(LeatherBustierArms), 25, 20, 0x1C0A, 0)); - Add(new GenericBuyInfo(typeof(LeatherBustierArms), 30, 20, 0x1C0B, 0)); - Add(new GenericBuyInfo(typeof(StuddedBustierArms), 50, 20, 0x1C0C, 0)); - Add(new GenericBuyInfo(typeof(StuddedBustierArms), 47, 20, 0x1C0D, 0)); + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(LeatherGorget), 31, 20, 0x13C7, 0)); + Add(new GenericBuyInfo(typeof(LeatherCap), 10, 20, 0x1DB9, 0)); + Add(new GenericBuyInfo(typeof(LeatherArms), 37, 20, 0x13CD, 0)); + Add(new GenericBuyInfo(typeof(LeatherChest), 47, 20, 0x13CC, 0)); + Add(new GenericBuyInfo(typeof(LeatherLegs), 36, 20, 0x13CB, 0)); + Add(new GenericBuyInfo(typeof(LeatherGloves), 31, 20, 0x13C6, 0)); - Add(new GenericBuyInfo(typeof(Bag), 6, 20, 0xE76, 0)); - Add(new GenericBuyInfo(typeof(Pouch), 6, 20, 0xE79, 0)); - Add(new GenericBuyInfo(typeof(Backpack), 15, 20, 0x9B2, 0)); - Add(new GenericBuyInfo(typeof(Leather), 6, 20, 0x1081, 0)); + Add(new GenericBuyInfo(typeof(StuddedGorget), 50, 20, 0x13D6, 0)); + Add(new GenericBuyInfo(typeof(StuddedArms), 57, 20, 0x13DC, 0)); + Add(new GenericBuyInfo(typeof(StuddedChest), 75, 20, 0x13DB, 0)); + Add(new GenericBuyInfo(typeof(StuddedLegs), 67, 20, 0x13DA, 0)); + Add(new GenericBuyInfo(typeof(StuddedGloves), 45, 20, 0x13D5, 0)); - Add(new GenericBuyInfo(typeof(SkinningKnife), 15, 20, 0xEC4, 0)); + Add(new GenericBuyInfo(typeof(FemaleStuddedChest), 62, 20, 0x1C02, 0)); + Add(new GenericBuyInfo(typeof(FemalePlateChest), 207, 20, 0x1C04, 0)); + Add(new GenericBuyInfo(typeof(FemaleLeatherChest), 36, 20, 0x1C06, 0)); + Add(new GenericBuyInfo(typeof(LeatherShorts), 28, 20, 0x1C00, 0)); + Add(new GenericBuyInfo(typeof(LeatherSkirt), 25, 20, 0x1C08, 0)); + Add(new GenericBuyInfo(typeof(LeatherBustierArms), 25, 20, 0x1C0A, 0)); + Add(new GenericBuyInfo(typeof(LeatherBustierArms), 30, 20, 0x1C0B, 0)); + Add(new GenericBuyInfo(typeof(StuddedBustierArms), 50, 20, 0x1C0C, 0)); + Add(new GenericBuyInfo(typeof(StuddedBustierArms), 47, 20, 0x1C0D, 0)); - Add(new GenericBuyInfo("1041279", typeof(TaxidermyKit), 100000, 20, 0x1EBA, 0)); - } + Add(new GenericBuyInfo(typeof(Bag), 6, 20, 0xE76, 0)); + Add(new GenericBuyInfo(typeof(Pouch), 6, 20, 0xE79, 0)); + Add(new GenericBuyInfo(typeof(Backpack), 15, 20, 0x9B2, 0)); + Add(new GenericBuyInfo(typeof(Leather), 6, 20, 0x1081, 0)); + + Add(new GenericBuyInfo(typeof(SkinningKnife), 15, 20, 0xEC4, 0)); + + Add(new GenericBuyInfo("1041279", typeof(TaxidermyKit), 100000, 20, 0x1EBA, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Bag), 3); + Add(typeof(Pouch), 3); + Add(typeof(Backpack), 7); + + Add(typeof(Leather), 5); + + Add(typeof(SkinningKnife), 7); + + Add(typeof(LeatherArms), 18); + Add(typeof(LeatherChest), 23); + Add(typeof(LeatherGloves), 15); + Add(typeof(LeatherGorget), 15); + Add(typeof(LeatherLegs), 18); + Add(typeof(LeatherCap), 5); + + Add(typeof(StuddedArms), 43); + Add(typeof(StuddedChest), 37); + Add(typeof(StuddedGloves), 39); + Add(typeof(StuddedGorget), 22); + Add(typeof(StuddedLegs), 33); + + Add(typeof(FemaleStuddedChest), 31); + Add(typeof(StuddedBustierArms), 23); + Add(typeof(FemalePlateChest), 103); + Add(typeof(FemaleLeatherChest), 18); + Add(typeof(LeatherBustierArms), 12); + Add(typeof(LeatherShorts), 14); + Add(typeof(LeatherSkirt), 12); + } + } } - - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Bag), 3); - Add(typeof(Pouch), 3); - Add(typeof(Backpack), 7); - - Add(typeof(Leather), 5); - - Add(typeof(SkinningKnife), 7); - - Add(typeof(LeatherArms), 18); - Add(typeof(LeatherChest), 23); - Add(typeof(LeatherGloves), 15); - Add(typeof(LeatherGorget), 15); - Add(typeof(LeatherLegs), 18); - Add(typeof(LeatherCap), 5); - - Add(typeof(StuddedArms), 43); - Add(typeof(StuddedChest), 37); - Add(typeof(StuddedGloves), 39); - Add(typeof(StuddedGorget), 22); - Add(typeof(StuddedLegs), 33); - - Add(typeof(FemaleStuddedChest), 31); - Add(typeof(StuddedBustierArms), 23); - Add(typeof(FemalePlateChest), 103); - Add(typeof(FemaleLeatherChest), 18); - Add(typeof(LeatherBustierArms), 12); - Add(typeof(LeatherShorts), 14); - Add(typeof(LeatherSkirt), 12); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBTavernKeeper.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBTavernKeeper.cs index 1b51adf2c..9751934d1 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBTavernKeeper.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBTavernKeeper.cs @@ -4,103 +4,103 @@ using Server.Multis; namespace Server.Mobiles { - public class SBTavernKeeper : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBTavernKeeper : SBInfo { - public InternalBuyInfo() - { - Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Ale, 7, 20, 0x99F, 0)); - Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Wine, 7, 20, 0x9C7, 0)); - Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Liquor, 7, 20, 0x99B, 0)); - Add(new BeverageBuyInfo(typeof(Jug), BeverageType.Cider, 13, 20, 0x9C8, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Milk, 7, 20, 0x9F0, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Ale, 11, 20, 0x1F95, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Cider, 11, 20, 0x1F97, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Liquor, 11, 20, 0x1F99, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Wine, 11, 20, 0x1F9B, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Water, 11, 20, 0x1F9D, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - Add(new GenericBuyInfo(typeof(BreadLoaf), 6, 10, 0x103B, 0)); - Add(new GenericBuyInfo(typeof(CheeseWheel), 21, 10, 0x97E, 0)); - Add(new GenericBuyInfo(typeof(CookedBird), 17, 20, 0x9B7, 0)); - Add(new GenericBuyInfo(typeof(LambLeg), 8, 20, 0x160A, 0)); - Add(new GenericBuyInfo(typeof(ChickenLeg), 5, 20, 0x1608, 0)); - Add(new GenericBuyInfo(typeof(Ribs), 7, 20, 0x9F2, 0)); + public override List BuyInfo { get; } = new InternalBuyInfo(); - Add(new GenericBuyInfo(typeof(WoodenBowlOfCarrots), 3, 20, 0x15F9, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfCorn), 3, 20, 0x15FA, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfLettuce), 3, 20, 0x15FB, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfPeas), 3, 20, 0x15FC, 0)); - Add(new GenericBuyInfo(typeof(EmptyPewterBowl), 2, 20, 0x15FD, 0)); - Add(new GenericBuyInfo(typeof(PewterBowlOfCorn), 3, 20, 0x15FE, 0)); - Add(new GenericBuyInfo(typeof(PewterBowlOfLettuce), 3, 20, 0x15FF, 0)); - Add(new GenericBuyInfo(typeof(PewterBowlOfPeas), 3, 20, 0x1600, 0)); - Add(new GenericBuyInfo(typeof(PewterBowlOfPotatos), 3, 20, 0x1601, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfStew), 3, 20, 0x1604, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfTomatoSoup), 3, 20, 0x1606, 0)); + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Ale, 7, 20, 0x99F, 0)); + Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Wine, 7, 20, 0x9C7, 0)); + Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Liquor, 7, 20, 0x99B, 0)); + Add(new BeverageBuyInfo(typeof(Jug), BeverageType.Cider, 13, 20, 0x9C8, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Milk, 7, 20, 0x9F0, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Ale, 11, 20, 0x1F95, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Cider, 11, 20, 0x1F97, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Liquor, 11, 20, 0x1F99, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Wine, 11, 20, 0x1F9B, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Water, 11, 20, 0x1F9D, 0)); - Add(new GenericBuyInfo(typeof(ApplePie), 7, 20, 0x1041, 0)); // OSI just has Pie, not Apple/Fruit/Meat + Add(new GenericBuyInfo(typeof(BreadLoaf), 6, 10, 0x103B, 0)); + Add(new GenericBuyInfo(typeof(CheeseWheel), 21, 10, 0x97E, 0)); + Add(new GenericBuyInfo(typeof(CookedBird), 17, 20, 0x9B7, 0)); + Add(new GenericBuyInfo(typeof(LambLeg), 8, 20, 0x160A, 0)); + Add(new GenericBuyInfo(typeof(ChickenLeg), 5, 20, 0x1608, 0)); + Add(new GenericBuyInfo(typeof(Ribs), 7, 20, 0x9F2, 0)); - Add(new GenericBuyInfo("1016450", typeof(Chessboard), 2, 20, 0xFA6, 0)); - Add(new GenericBuyInfo("1016449", typeof(CheckerBoard), 2, 20, 0xFA6, 0)); - Add(new GenericBuyInfo(typeof(Backgammon), 2, 20, 0xE1C, 0)); - Add(new GenericBuyInfo(typeof(Dices), 2, 20, 0xFA7, 0)); - Add(new GenericBuyInfo("1041243", typeof(ContractOfEmployment), 1252, 20, 0x14F0, 0)); - Add(new GenericBuyInfo("a barkeep contract", typeof(BarkeepContract), 1252, 20, 0x14F0, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfCarrots), 3, 20, 0x15F9, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfCorn), 3, 20, 0x15FA, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfLettuce), 3, 20, 0x15FB, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfPeas), 3, 20, 0x15FC, 0)); + Add(new GenericBuyInfo(typeof(EmptyPewterBowl), 2, 20, 0x15FD, 0)); + Add(new GenericBuyInfo(typeof(PewterBowlOfCorn), 3, 20, 0x15FE, 0)); + Add(new GenericBuyInfo(typeof(PewterBowlOfLettuce), 3, 20, 0x15FF, 0)); + Add(new GenericBuyInfo(typeof(PewterBowlOfPeas), 3, 20, 0x1600, 0)); + Add(new GenericBuyInfo(typeof(PewterBowlOfPotatos), 3, 20, 0x1601, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfStew), 3, 20, 0x1604, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfTomatoSoup), 3, 20, 0x1606, 0)); - if (BaseHouse.NewVendorSystem) - Add(new GenericBuyInfo("1062332", typeof(VendorRentalContract), 1252, 20, 0x14F0, 0x672)); + Add(new GenericBuyInfo(typeof(ApplePie), 7, 20, 0x1041, 0)); // OSI just has Pie, not Apple/Fruit/Meat - /*if (Map == Tokuno) - { - Add( new GenericBuyInfo( typeof( Wasabi ), 2, 20, 0x24E8, 0 ) ); - Add( new GenericBuyInfo( typeof( Wasabi ), 2, 20, 0x24E9, 0 ) ); - Add( new GenericBuyInfo( typeof( BentoBox ), 6, 20, 0x2836, 0 ) ); - Add( new GenericBuyInfo( typeof( BentoBox ), 6, 20, 0x2837, 0 ) ); - Add( new GenericBuyInfo( typeof( GreenTeaBasket ), 2, 20, 0x284B, 0 ) ); - }*/ - } + Add(new GenericBuyInfo("1016450", typeof(Chessboard), 2, 20, 0xFA6, 0)); + Add(new GenericBuyInfo("1016449", typeof(CheckerBoard), 2, 20, 0xFA6, 0)); + Add(new GenericBuyInfo(typeof(Backgammon), 2, 20, 0xE1C, 0)); + Add(new GenericBuyInfo(typeof(Dices), 2, 20, 0xFA7, 0)); + Add(new GenericBuyInfo("1041243", typeof(ContractOfEmployment), 1252, 20, 0x14F0, 0)); + Add(new GenericBuyInfo("a barkeep contract", typeof(BarkeepContract), 1252, 20, 0x14F0, 0)); + + if (BaseHouse.NewVendorSystem) + Add(new GenericBuyInfo("1062332", typeof(VendorRentalContract), 1252, 20, 0x14F0, 0x672)); + + /*if (Map == Tokuno) + { + Add( new GenericBuyInfo( typeof( Wasabi ), 2, 20, 0x24E8, 0 ) ); + Add( new GenericBuyInfo( typeof( Wasabi ), 2, 20, 0x24E9, 0 ) ); + Add( new GenericBuyInfo( typeof( BentoBox ), 6, 20, 0x2836, 0 ) ); + Add( new GenericBuyInfo( typeof( BentoBox ), 6, 20, 0x2837, 0 ) ); + Add( new GenericBuyInfo( typeof( GreenTeaBasket ), 2, 20, 0x284B, 0 ) ); + }*/ + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(WoodenBowlOfCarrots), 1); + Add(typeof(WoodenBowlOfCorn), 1); + Add(typeof(WoodenBowlOfLettuce), 1); + Add(typeof(WoodenBowlOfPeas), 1); + Add(typeof(EmptyPewterBowl), 1); + Add(typeof(PewterBowlOfCorn), 1); + Add(typeof(PewterBowlOfLettuce), 1); + Add(typeof(PewterBowlOfPeas), 1); + Add(typeof(PewterBowlOfPotatos), 1); + Add(typeof(WoodenBowlOfStew), 1); + Add(typeof(WoodenBowlOfTomatoSoup), 1); + Add(typeof(BeverageBottle), 3); + Add(typeof(Jug), 6); + Add(typeof(Pitcher), 5); + Add(typeof(GlassMug), 1); + Add(typeof(BreadLoaf), 3); + Add(typeof(CheeseWheel), 12); + Add(typeof(Ribs), 6); + Add(typeof(Peach), 1); + Add(typeof(Pear), 1); + Add(typeof(Grapes), 1); + Add(typeof(Apple), 1); + Add(typeof(Banana), 1); + Add(typeof(Candle), 3); + Add(typeof(Chessboard), 1); + Add(typeof(CheckerBoard), 1); + Add(typeof(Backgammon), 1); + Add(typeof(Dices), 1); + Add(typeof(ContractOfEmployment), 626); + } + } } - - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(WoodenBowlOfCarrots), 1); - Add(typeof(WoodenBowlOfCorn), 1); - Add(typeof(WoodenBowlOfLettuce), 1); - Add(typeof(WoodenBowlOfPeas), 1); - Add(typeof(EmptyPewterBowl), 1); - Add(typeof(PewterBowlOfCorn), 1); - Add(typeof(PewterBowlOfLettuce), 1); - Add(typeof(PewterBowlOfPeas), 1); - Add(typeof(PewterBowlOfPotatos), 1); - Add(typeof(WoodenBowlOfStew), 1); - Add(typeof(WoodenBowlOfTomatoSoup), 1); - Add(typeof(BeverageBottle), 3); - Add(typeof(Jug), 6); - Add(typeof(Pitcher), 5); - Add(typeof(GlassMug), 1); - Add(typeof(BreadLoaf), 3); - Add(typeof(CheeseWheel), 12); - Add(typeof(Ribs), 6); - Add(typeof(Peach), 1); - Add(typeof(Pear), 1); - Add(typeof(Grapes), 1); - Add(typeof(Apple), 1); - Add(typeof(Banana), 1); - Add(typeof(Candle), 3); - Add(typeof(Chessboard), 1); - Add(typeof(CheckerBoard), 1); - Add(typeof(Backgammon), 1); - Add(typeof(Dices), 1); - Add(typeof(ContractOfEmployment), 626); - } - } - } } diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBThief.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBThief.cs index 272f31420..703277908 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBThief.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBThief.cs @@ -3,41 +3,41 @@ using Server.Items; namespace Server.Mobiles { - public class SBThief : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBThief : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Backpack), 15, 20, 0x9B2, 0)); - Add(new GenericBuyInfo(typeof(Pouch), 6, 20, 0xE79, 0)); - Add(new GenericBuyInfo(typeof(Torch), 8, 20, 0xF6B, 0)); - Add(new GenericBuyInfo(typeof(Lantern), 2, 20, 0xA25, 0)); - // Add( new GenericBuyInfo( typeof( OilFlask ), 8, 20, 0x####, 0 ) ); - Add(new GenericBuyInfo(typeof(Lockpick), 12, 20, 0x14FC, 0)); - Add(new GenericBuyInfo(typeof(WoodenBox), 14, 20, 0x9AA, 0)); - Add(new GenericBuyInfo(typeof(Key), 2, 20, 0x100E, 0)); - Add(new GenericBuyInfo(typeof(HairDye), 37, 20, 0xEFF, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Backpack), 7); - Add(typeof(Pouch), 3); - Add(typeof(Torch), 3); - Add(typeof(Lantern), 1); - // Add( typeof( OilFlask ), 4 ); - Add(typeof(Lockpick), 6); - Add(typeof(WoodenBox), 7); - Add(typeof(HairDye), 19); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Backpack), 15, 20, 0x9B2, 0)); + Add(new GenericBuyInfo(typeof(Pouch), 6, 20, 0xE79, 0)); + Add(new GenericBuyInfo(typeof(Torch), 8, 20, 0xF6B, 0)); + Add(new GenericBuyInfo(typeof(Lantern), 2, 20, 0xA25, 0)); + // Add( new GenericBuyInfo( typeof( OilFlask ), 8, 20, 0x####, 0 ) ); + Add(new GenericBuyInfo(typeof(Lockpick), 12, 20, 0x14FC, 0)); + Add(new GenericBuyInfo(typeof(WoodenBox), 14, 20, 0x9AA, 0)); + Add(new GenericBuyInfo(typeof(Key), 2, 20, 0x100E, 0)); + Add(new GenericBuyInfo(typeof(HairDye), 37, 20, 0xEFF, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Backpack), 7); + Add(typeof(Pouch), 3); + Add(typeof(Torch), 3); + Add(typeof(Lantern), 1); + // Add( typeof( OilFlask ), 4 ); + Add(typeof(Lockpick), 6); + Add(typeof(WoodenBox), 7); + Add(typeof(HairDye), 19); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBTinker.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBTinker.cs index a7e1a203b..c4d6f0a94 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBTinker.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBTinker.cs @@ -3,120 +3,120 @@ using Server.Items; namespace Server.Mobiles { - public class SBTinker : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBTinker : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Clock), 22, 20, 0x104B, 0)); - Add(new GenericBuyInfo(typeof(Nails), 3, 20, 0x102E, 0)); - Add(new GenericBuyInfo(typeof(ClockParts), 3, 20, 0x104F, 0)); - Add(new GenericBuyInfo(typeof(AxleGears), 3, 20, 0x1051, 0)); - Add(new GenericBuyInfo(typeof(Gears), 2, 20, 0x1053, 0)); - Add(new GenericBuyInfo(typeof(Hinge), 2, 20, 0x1055, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - Add(new GenericBuyInfo(typeof(Sextant), 13, 20, 0x1057, 0)); - Add(new GenericBuyInfo(typeof(SextantParts), 5, 20, 0x1059, 0)); - Add(new GenericBuyInfo(typeof(Axle), 2, 20, 0x105B, 0)); - Add(new GenericBuyInfo(typeof(Springs), 3, 20, 0x105D, 0)); + public override List BuyInfo { get; } = new InternalBuyInfo(); - Add(new GenericBuyInfo("1024111", typeof(Key), 8, 20, 0x100F, 0)); - Add(new GenericBuyInfo("1024112", typeof(Key), 8, 20, 0x1010, 0)); - Add(new GenericBuyInfo("1024115", typeof(Key), 8, 20, 0x1013, 0)); - Add(new GenericBuyInfo(typeof(KeyRing), 8, 20, 0x1010, 0)); - Add(new GenericBuyInfo(typeof(Lockpick), 12, 20, 0x14FC, 0)); + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Clock), 22, 20, 0x104B, 0)); + Add(new GenericBuyInfo(typeof(Nails), 3, 20, 0x102E, 0)); + Add(new GenericBuyInfo(typeof(ClockParts), 3, 20, 0x104F, 0)); + Add(new GenericBuyInfo(typeof(AxleGears), 3, 20, 0x1051, 0)); + Add(new GenericBuyInfo(typeof(Gears), 2, 20, 0x1053, 0)); + Add(new GenericBuyInfo(typeof(Hinge), 2, 20, 0x1055, 0)); - Add(new GenericBuyInfo(typeof(TinkersTools), 7, 20, 0x1EBC, 0)); - Add(new GenericBuyInfo(typeof(Board), 3, 20, 0x1BD7, 0)); - Add(new GenericBuyInfo(typeof(IronIngot), 5, 16, 0x1BF2, 0)); - Add(new GenericBuyInfo(typeof(SewingKit), 3, 20, 0xF9D, 0)); + Add(new GenericBuyInfo(typeof(Sextant), 13, 20, 0x1057, 0)); + Add(new GenericBuyInfo(typeof(SextantParts), 5, 20, 0x1059, 0)); + Add(new GenericBuyInfo(typeof(Axle), 2, 20, 0x105B, 0)); + Add(new GenericBuyInfo(typeof(Springs), 3, 20, 0x105D, 0)); - Add(new GenericBuyInfo(typeof(DrawKnife), 10, 20, 0x10E4, 0)); - Add(new GenericBuyInfo(typeof(Froe), 10, 20, 0x10E5, 0)); - Add(new GenericBuyInfo(typeof(Scorp), 10, 20, 0x10E7, 0)); - Add(new GenericBuyInfo(typeof(Inshave), 10, 20, 0x10E6, 0)); + Add(new GenericBuyInfo("1024111", typeof(Key), 8, 20, 0x100F, 0)); + Add(new GenericBuyInfo("1024112", typeof(Key), 8, 20, 0x1010, 0)); + Add(new GenericBuyInfo("1024115", typeof(Key), 8, 20, 0x1013, 0)); + Add(new GenericBuyInfo(typeof(KeyRing), 8, 20, 0x1010, 0)); + Add(new GenericBuyInfo(typeof(Lockpick), 12, 20, 0x14FC, 0)); - Add(new GenericBuyInfo(typeof(ButcherKnife), 13, 20, 0x13F6, 0)); + Add(new GenericBuyInfo(typeof(TinkersTools), 7, 20, 0x1EBC, 0)); + Add(new GenericBuyInfo(typeof(Board), 3, 20, 0x1BD7, 0)); + Add(new GenericBuyInfo(typeof(IronIngot), 5, 16, 0x1BF2, 0)); + Add(new GenericBuyInfo(typeof(SewingKit), 3, 20, 0xF9D, 0)); - Add(new GenericBuyInfo(typeof(Scissors), 11, 20, 0xF9F, 0)); + Add(new GenericBuyInfo(typeof(DrawKnife), 10, 20, 0x10E4, 0)); + Add(new GenericBuyInfo(typeof(Froe), 10, 20, 0x10E5, 0)); + Add(new GenericBuyInfo(typeof(Scorp), 10, 20, 0x10E7, 0)); + Add(new GenericBuyInfo(typeof(Inshave), 10, 20, 0x10E6, 0)); - Add(new GenericBuyInfo(typeof(Tongs), 13, 14, 0xFBB, 0)); + Add(new GenericBuyInfo(typeof(ButcherKnife), 13, 20, 0x13F6, 0)); - Add(new GenericBuyInfo(typeof(DovetailSaw), 12, 20, 0x1028, 0)); - Add(new GenericBuyInfo(typeof(Saw), 15, 20, 0x1034, 0)); + Add(new GenericBuyInfo(typeof(Scissors), 11, 20, 0xF9F, 0)); - Add(new GenericBuyInfo(typeof(Hammer), 17, 20, 0x102A, 0)); - Add(new GenericBuyInfo(typeof(SmithHammer), 23, 20, 0x13E3, 0)); - // TODO: Sledgehammer + Add(new GenericBuyInfo(typeof(Tongs), 13, 14, 0xFBB, 0)); - Add(new GenericBuyInfo(typeof(Shovel), 12, 20, 0xF39, 0)); + Add(new GenericBuyInfo(typeof(DovetailSaw), 12, 20, 0x1028, 0)); + Add(new GenericBuyInfo(typeof(Saw), 15, 20, 0x1034, 0)); - Add(new GenericBuyInfo(typeof(MouldingPlane), 11, 20, 0x102C, 0)); - Add(new GenericBuyInfo(typeof(JointingPlane), 10, 20, 0x1030, 0)); - Add(new GenericBuyInfo(typeof(SmoothingPlane), 11, 20, 0x1032, 0)); + Add(new GenericBuyInfo(typeof(Hammer), 17, 20, 0x102A, 0)); + Add(new GenericBuyInfo(typeof(SmithHammer), 23, 20, 0x13E3, 0)); + // TODO: Sledgehammer - Add(new GenericBuyInfo(typeof(Pickaxe), 25, 20, 0xE86, 0)); + Add(new GenericBuyInfo(typeof(Shovel), 12, 20, 0xF39, 0)); - Add(new GenericBuyInfo(typeof(Drums), 21, 20, 0x0E9C, 0)); - Add(new GenericBuyInfo(typeof(Tambourine), 21, 20, 0x0E9E, 0)); - Add(new GenericBuyInfo(typeof(LapHarp), 21, 20, 0x0EB2, 0)); - Add(new GenericBuyInfo(typeof(Lute), 21, 20, 0x0EB3, 0)); - } + Add(new GenericBuyInfo(typeof(MouldingPlane), 11, 20, 0x102C, 0)); + Add(new GenericBuyInfo(typeof(JointingPlane), 10, 20, 0x1030, 0)); + Add(new GenericBuyInfo(typeof(SmoothingPlane), 11, 20, 0x1032, 0)); + + Add(new GenericBuyInfo(typeof(Pickaxe), 25, 20, 0xE86, 0)); + + Add(new GenericBuyInfo(typeof(Drums), 21, 20, 0x0E9C, 0)); + Add(new GenericBuyInfo(typeof(Tambourine), 21, 20, 0x0E9E, 0)); + Add(new GenericBuyInfo(typeof(LapHarp), 21, 20, 0x0EB2, 0)); + Add(new GenericBuyInfo(typeof(Lute), 21, 20, 0x0EB3, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Drums), 10); + Add(typeof(Tambourine), 10); + Add(typeof(LapHarp), 10); + Add(typeof(Lute), 10); + + Add(typeof(Shovel), 6); + Add(typeof(SewingKit), 1); + Add(typeof(Scissors), 6); + Add(typeof(Tongs), 7); + Add(typeof(Key), 1); + + Add(typeof(DovetailSaw), 6); + Add(typeof(MouldingPlane), 6); + Add(typeof(Nails), 1); + Add(typeof(JointingPlane), 6); + Add(typeof(SmoothingPlane), 6); + Add(typeof(Saw), 7); + + Add(typeof(Clock), 11); + Add(typeof(ClockParts), 1); + Add(typeof(AxleGears), 1); + Add(typeof(Gears), 1); + Add(typeof(Hinge), 1); + Add(typeof(Sextant), 6); + Add(typeof(SextantParts), 2); + Add(typeof(Axle), 1); + Add(typeof(Springs), 1); + + Add(typeof(DrawKnife), 5); + Add(typeof(Froe), 5); + Add(typeof(Inshave), 5); + Add(typeof(Scorp), 5); + + Add(typeof(Lockpick), 6); + Add(typeof(TinkerTools), 3); + + Add(typeof(Board), 1); + Add(typeof(Log), 1); + + Add(typeof(Pickaxe), 16); + Add(typeof(Hammer), 3); + Add(typeof(SmithHammer), 11); + Add(typeof(ButcherKnife), 6); + } + } } - - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Drums), 10); - Add(typeof(Tambourine), 10); - Add(typeof(LapHarp), 10); - Add(typeof(Lute), 10); - - Add(typeof(Shovel), 6); - Add(typeof(SewingKit), 1); - Add(typeof(Scissors), 6); - Add(typeof(Tongs), 7); - Add(typeof(Key), 1); - - Add(typeof(DovetailSaw), 6); - Add(typeof(MouldingPlane), 6); - Add(typeof(Nails), 1); - Add(typeof(JointingPlane), 6); - Add(typeof(SmoothingPlane), 6); - Add(typeof(Saw), 7); - - Add(typeof(Clock), 11); - Add(typeof(ClockParts), 1); - Add(typeof(AxleGears), 1); - Add(typeof(Gears), 1); - Add(typeof(Hinge), 1); - Add(typeof(Sextant), 6); - Add(typeof(SextantParts), 2); - Add(typeof(Axle), 1); - Add(typeof(Springs), 1); - - Add(typeof(DrawKnife), 5); - Add(typeof(Froe), 5); - Add(typeof(Inshave), 5); - Add(typeof(Scorp), 5); - - Add(typeof(Lockpick), 6); - Add(typeof(TinkerTools), 3); - - Add(typeof(Board), 1); - Add(typeof(Log), 1); - - Add(typeof(Pickaxe), 16); - Add(typeof(Hammer), 3); - Add(typeof(SmithHammer), 11); - Add(typeof(ButcherKnife), 6); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBVagabond.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBVagabond.cs index 7ff2cea44..0703b076f 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBVagabond.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBVagabond.cs @@ -3,68 +3,68 @@ using Server.Items; namespace Server.Mobiles { - public class SBVagabond : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBVagabond : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(GoldRing), 27, 20, 0x108A, 0)); - Add(new GenericBuyInfo(typeof(Necklace), 26, 20, 0x1085, 0)); - Add(new GenericBuyInfo(typeof(GoldNecklace), 27, 20, 0x1088, 0)); - Add(new GenericBuyInfo(typeof(GoldBeadNecklace), 27, 20, 0x1089, 0)); - Add(new GenericBuyInfo(typeof(Beads), 27, 20, 0x108B, 0)); - Add(new GenericBuyInfo(typeof(GoldBracelet), 27, 20, 0x1086, 0)); - Add(new GenericBuyInfo(typeof(GoldEarrings), 27, 20, 0x1087, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - Add(new GenericBuyInfo(typeof(Board), 3, 20, 0x1BD7, 0)); - Add(new GenericBuyInfo(typeof(IronIngot), 6, 20, 0x1BF2, 0)); + public override List BuyInfo { get; } = new InternalBuyInfo(); - Add(new GenericBuyInfo(typeof(StarSapphire), 125, 20, 0xF21, 0)); - Add(new GenericBuyInfo(typeof(Emerald), 100, 20, 0xF10, 0)); - Add(new GenericBuyInfo(typeof(Sapphire), 100, 20, 0xF19, 0)); - Add(new GenericBuyInfo(typeof(Ruby), 75, 20, 0xF13, 0)); - Add(new GenericBuyInfo(typeof(Citrine), 50, 20, 0xF15, 0)); - Add(new GenericBuyInfo(typeof(Amethyst), 100, 20, 0xF16, 0)); - Add(new GenericBuyInfo(typeof(Tourmaline), 75, 20, 0xF2D, 0)); - Add(new GenericBuyInfo(typeof(Amber), 50, 20, 0xF25, 0)); - Add(new GenericBuyInfo(typeof(Diamond), 200, 20, 0xF26, 0)); - } + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(GoldRing), 27, 20, 0x108A, 0)); + Add(new GenericBuyInfo(typeof(Necklace), 26, 20, 0x1085, 0)); + Add(new GenericBuyInfo(typeof(GoldNecklace), 27, 20, 0x1088, 0)); + Add(new GenericBuyInfo(typeof(GoldBeadNecklace), 27, 20, 0x1089, 0)); + Add(new GenericBuyInfo(typeof(Beads), 27, 20, 0x108B, 0)); + Add(new GenericBuyInfo(typeof(GoldBracelet), 27, 20, 0x1086, 0)); + Add(new GenericBuyInfo(typeof(GoldEarrings), 27, 20, 0x1087, 0)); + + Add(new GenericBuyInfo(typeof(Board), 3, 20, 0x1BD7, 0)); + Add(new GenericBuyInfo(typeof(IronIngot), 6, 20, 0x1BF2, 0)); + + Add(new GenericBuyInfo(typeof(StarSapphire), 125, 20, 0xF21, 0)); + Add(new GenericBuyInfo(typeof(Emerald), 100, 20, 0xF10, 0)); + Add(new GenericBuyInfo(typeof(Sapphire), 100, 20, 0xF19, 0)); + Add(new GenericBuyInfo(typeof(Ruby), 75, 20, 0xF13, 0)); + Add(new GenericBuyInfo(typeof(Citrine), 50, 20, 0xF15, 0)); + Add(new GenericBuyInfo(typeof(Amethyst), 100, 20, 0xF16, 0)); + Add(new GenericBuyInfo(typeof(Tourmaline), 75, 20, 0xF2D, 0)); + Add(new GenericBuyInfo(typeof(Amber), 50, 20, 0xF25, 0)); + Add(new GenericBuyInfo(typeof(Diamond), 200, 20, 0xF26, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Board), 1); + Add(typeof(IronIngot), 3); + + Add(typeof(Amber), 25); + Add(typeof(Amethyst), 50); + Add(typeof(Citrine), 25); + Add(typeof(Diamond), 100); + Add(typeof(Emerald), 50); + Add(typeof(Ruby), 37); + Add(typeof(Sapphire), 50); + Add(typeof(StarSapphire), 62); + Add(typeof(Tourmaline), 47); + Add(typeof(GoldRing), 13); + Add(typeof(SilverRing), 10); + Add(typeof(Necklace), 13); + Add(typeof(GoldNecklace), 13); + Add(typeof(GoldBeadNecklace), 13); + Add(typeof(SilverNecklace), 10); + Add(typeof(SilverBeadNecklace), 10); + Add(typeof(Beads), 13); + Add(typeof(GoldBracelet), 13); + Add(typeof(SilverBracelet), 10); + Add(typeof(GoldEarrings), 13); + Add(typeof(SilverEarrings), 10); + } + } } - - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Board), 1); - Add(typeof(IronIngot), 3); - - Add(typeof(Amber), 25); - Add(typeof(Amethyst), 50); - Add(typeof(Citrine), 25); - Add(typeof(Diamond), 100); - Add(typeof(Emerald), 50); - Add(typeof(Ruby), 37); - Add(typeof(Sapphire), 50); - Add(typeof(StarSapphire), 62); - Add(typeof(Tourmaline), 47); - Add(typeof(GoldRing), 13); - Add(typeof(SilverRing), 10); - Add(typeof(Necklace), 13); - Add(typeof(GoldNecklace), 13); - Add(typeof(GoldBeadNecklace), 13); - Add(typeof(SilverNecklace), 10); - Add(typeof(SilverBeadNecklace), 10); - Add(typeof(Beads), 13); - Add(typeof(GoldBracelet), 13); - Add(typeof(SilverBracelet), 10); - Add(typeof(GoldEarrings), 13); - Add(typeof(SilverEarrings), 10); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBVarietyDealer.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBVarietyDealer.cs index d225f290f..0297dcc2a 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBVarietyDealer.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBVarietyDealer.cs @@ -1,130 +1,129 @@ -using System; using System.Collections.Generic; using Server.Items; namespace Server.Mobiles { - public class SBVarietyDealer : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBVarietyDealer : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Bandage), 5, 20, 0xE21, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - Add(new GenericBuyInfo(typeof(BlankScroll), 5, 999, 0x0E34, 0)); + public override List BuyInfo { get; } = new InternalBuyInfo(); - Add(new GenericBuyInfo(typeof(NightSightPotion), 15, 10, 0xF06, 0)); - Add(new GenericBuyInfo(typeof(AgilityPotion), 15, 10, 0xF08, 0)); - Add(new GenericBuyInfo(typeof(StrengthPotion), 15, 10, 0xF09, 0)); - Add(new GenericBuyInfo(typeof(RefreshPotion), 15, 10, 0xF0B, 0)); - Add(new GenericBuyInfo(typeof(LesserCurePotion), 15, 10, 0xF07, 0)); - Add(new GenericBuyInfo(typeof(LesserHealPotion), 15, 10, 0xF0C, 0)); - Add(new GenericBuyInfo(typeof(LesserPoisonPotion), 15, 10, 0xF0A, 0)); - Add(new GenericBuyInfo(typeof(LesserExplosionPotion), 21, 10, 0xF0D, 0)); - - Add(new GenericBuyInfo(typeof(Bolt), 6, Utility.Random(30, 60), 0x1BFB, 0)); - Add(new GenericBuyInfo(typeof(Arrow), 3, Utility.Random(30, 60), 0xF3F, 0)); - - Add(new GenericBuyInfo(typeof(BlackPearl), 5, 999, 0xF7A, 0)); - Add(new GenericBuyInfo(typeof(Bloodmoss), 5, 999, 0xF7B, 0)); - Add(new GenericBuyInfo(typeof(MandrakeRoot), 3, 999, 0xF86, 0)); - Add(new GenericBuyInfo(typeof(Garlic), 3, 999, 0xF84, 0)); - Add(new GenericBuyInfo(typeof(Ginseng), 3, 999, 0xF85, 0)); - Add(new GenericBuyInfo(typeof(Nightshade), 3, 999, 0xF88, 0)); - Add(new GenericBuyInfo(typeof(SpidersSilk), 3, 999, 0xF8D, 0)); - Add(new GenericBuyInfo(typeof(SulfurousAsh), 3, 999, 0xF8C, 0)); - - Add(new GenericBuyInfo(typeof(BreadLoaf), 7, 10, 0x103B, 0)); - Add(new GenericBuyInfo(typeof(Backpack), 15, 20, 0x9B2, 0)); - - Type[] types = Loot.RegularScrollTypes; - - int circles = 3; - - for (int i = 0; i < circles * 8 && i < types.Length; ++i) + public class InternalBuyInfo : List { - int itemID = 0x1F2E + i; + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Bandage), 5, 20, 0xE21, 0)); - if (i == 6) - itemID = 0x1F2D; - else if (i > 6) - --itemID; + Add(new GenericBuyInfo(typeof(BlankScroll), 5, 999, 0x0E34, 0)); - Add(new GenericBuyInfo(types[i], 12 + i / 8 * 10, 20, itemID, 0)); + Add(new GenericBuyInfo(typeof(NightSightPotion), 15, 10, 0xF06, 0)); + Add(new GenericBuyInfo(typeof(AgilityPotion), 15, 10, 0xF08, 0)); + Add(new GenericBuyInfo(typeof(StrengthPotion), 15, 10, 0xF09, 0)); + Add(new GenericBuyInfo(typeof(RefreshPotion), 15, 10, 0xF0B, 0)); + Add(new GenericBuyInfo(typeof(LesserCurePotion), 15, 10, 0xF07, 0)); + Add(new GenericBuyInfo(typeof(LesserHealPotion), 15, 10, 0xF0C, 0)); + Add(new GenericBuyInfo(typeof(LesserPoisonPotion), 15, 10, 0xF0A, 0)); + Add(new GenericBuyInfo(typeof(LesserExplosionPotion), 21, 10, 0xF0D, 0)); + + Add(new GenericBuyInfo(typeof(Bolt), 6, Utility.Random(30, 60), 0x1BFB, 0)); + Add(new GenericBuyInfo(typeof(Arrow), 3, Utility.Random(30, 60), 0xF3F, 0)); + + Add(new GenericBuyInfo(typeof(BlackPearl), 5, 999, 0xF7A, 0)); + Add(new GenericBuyInfo(typeof(Bloodmoss), 5, 999, 0xF7B, 0)); + Add(new GenericBuyInfo(typeof(MandrakeRoot), 3, 999, 0xF86, 0)); + Add(new GenericBuyInfo(typeof(Garlic), 3, 999, 0xF84, 0)); + Add(new GenericBuyInfo(typeof(Ginseng), 3, 999, 0xF85, 0)); + Add(new GenericBuyInfo(typeof(Nightshade), 3, 999, 0xF88, 0)); + Add(new GenericBuyInfo(typeof(SpidersSilk), 3, 999, 0xF8D, 0)); + Add(new GenericBuyInfo(typeof(SulfurousAsh), 3, 999, 0xF8C, 0)); + + Add(new GenericBuyInfo(typeof(BreadLoaf), 7, 10, 0x103B, 0)); + Add(new GenericBuyInfo(typeof(Backpack), 15, 20, 0x9B2, 0)); + + var types = Loot.RegularScrollTypes; + + var circles = 3; + + for (var i = 0; i < circles * 8 && i < types.Length; ++i) + { + var itemID = 0x1F2E + i; + + if (i == 6) + itemID = 0x1F2D; + else if (i > 6) + --itemID; + + Add(new GenericBuyInfo(types[i], 12 + i / 8 * 10, 20, itemID, 0)); + } + + if (Core.AOS) + { + Add(new GenericBuyInfo(typeof(BatWing), 3, 999, 0xF78, 0)); + Add(new GenericBuyInfo(typeof(GraveDust), 3, 999, 0xF8F, 0)); + Add(new GenericBuyInfo(typeof(DaemonBlood), 6, 999, 0xF7D, 0)); + Add(new GenericBuyInfo(typeof(NoxCrystal), 6, 999, 0xF8E, 0)); + Add(new GenericBuyInfo(typeof(PigIron), 5, 999, 0xF8A, 0)); + + Add(new GenericBuyInfo(typeof(NecromancerSpellbook), 115, 10, 0x2253, 0)); + } + + Add(new GenericBuyInfo(typeof(RecallRune), 15, 10, 0x1f14, 0)); + Add(new GenericBuyInfo(typeof(Spellbook), 18, 10, 0xEFA, 0)); + + Add(new GenericBuyInfo("1041072", typeof(MagicWizardsHat), 11, 10, 0x1718, 0)); + } } - if (Core.AOS) + public class InternalSellInfo : GenericSellInfo { - Add(new GenericBuyInfo(typeof(BatWing), 3, 999, 0xF78, 0)); - Add(new GenericBuyInfo(typeof(GraveDust), 3, 999, 0xF8F, 0)); - Add(new GenericBuyInfo(typeof(DaemonBlood), 6, 999, 0xF7D, 0)); - Add(new GenericBuyInfo(typeof(NoxCrystal), 6, 999, 0xF8E, 0)); - Add(new GenericBuyInfo(typeof(PigIron), 5, 999, 0xF8A, 0)); + public InternalSellInfo() + { + Add(typeof(Bandage), 1); - Add(new GenericBuyInfo(typeof(NecromancerSpellbook), 115, 10, 0x2253, 0)); + Add(typeof(BlankScroll), 3); + + Add(typeof(NightSightPotion), 7); + Add(typeof(AgilityPotion), 7); + Add(typeof(StrengthPotion), 7); + Add(typeof(RefreshPotion), 7); + Add(typeof(LesserCurePotion), 7); + Add(typeof(LesserHealPotion), 7); + Add(typeof(LesserPoisonPotion), 7); + Add(typeof(LesserExplosionPotion), 10); + + Add(typeof(Bolt), 3); + Add(typeof(Arrow), 2); + + Add(typeof(BlackPearl), 3); + Add(typeof(Bloodmoss), 3); + Add(typeof(MandrakeRoot), 2); + Add(typeof(Garlic), 2); + Add(typeof(Ginseng), 2); + Add(typeof(Nightshade), 2); + Add(typeof(SpidersSilk), 2); + Add(typeof(SulfurousAsh), 2); + + Add(typeof(BreadLoaf), 3); + Add(typeof(Backpack), 7); + Add(typeof(RecallRune), 8); + Add(typeof(Spellbook), 9); + Add(typeof(BlankScroll), 3); + + if (Core.AOS) + { + Add(typeof(BatWing), 2); + Add(typeof(GraveDust), 2); + Add(typeof(DaemonBlood), 3); + Add(typeof(NoxCrystal), 3); + Add(typeof(PigIron), 3); + } + + var types = Loot.RegularScrollTypes; + + for (var i = 0; i < types.Length; ++i) + Add(types[i], (i / 8 + 2) * 5); + } } - - Add(new GenericBuyInfo(typeof(RecallRune), 15, 10, 0x1f14, 0)); - Add(new GenericBuyInfo(typeof(Spellbook), 18, 10, 0xEFA, 0)); - - Add(new GenericBuyInfo("1041072", typeof(MagicWizardsHat), 11, 10, 0x1718, 0)); - } } - - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Bandage), 1); - - Add(typeof(BlankScroll), 3); - - Add(typeof(NightSightPotion), 7); - Add(typeof(AgilityPotion), 7); - Add(typeof(StrengthPotion), 7); - Add(typeof(RefreshPotion), 7); - Add(typeof(LesserCurePotion), 7); - Add(typeof(LesserHealPotion), 7); - Add(typeof(LesserPoisonPotion), 7); - Add(typeof(LesserExplosionPotion), 10); - - Add(typeof(Bolt), 3); - Add(typeof(Arrow), 2); - - Add(typeof(BlackPearl), 3); - Add(typeof(Bloodmoss), 3); - Add(typeof(MandrakeRoot), 2); - Add(typeof(Garlic), 2); - Add(typeof(Ginseng), 2); - Add(typeof(Nightshade), 2); - Add(typeof(SpidersSilk), 2); - Add(typeof(SulfurousAsh), 2); - - Add(typeof(BreadLoaf), 3); - Add(typeof(Backpack), 7); - Add(typeof(RecallRune), 8); - Add(typeof(Spellbook), 9); - Add(typeof(BlankScroll), 3); - - if (Core.AOS) - { - Add(typeof(BatWing), 2); - Add(typeof(GraveDust), 2); - Add(typeof(DaemonBlood), 3); - Add(typeof(NoxCrystal), 3); - Add(typeof(PigIron), 3); - } - - Type[] types = Loot.RegularScrollTypes; - - for (int i = 0; i < types.Length; ++i) - Add(types[i], (i / 8 + 2) * 5); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBVeterinarian.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBVeterinarian.cs index 830d965c0..146548533 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBVeterinarian.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBVeterinarian.cs @@ -3,30 +3,30 @@ using Server.Items; namespace Server.Mobiles { - public class SBVeterinarian : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBVeterinarian : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Bandage), 6, 20, 0xE21, 0)); - Add(new AnimalBuyInfo(1, typeof(PackHorse), 616, 10, 291, 0)); - Add(new AnimalBuyInfo(1, typeof(PackLlama), 523, 10, 292, 0)); - Add(new AnimalBuyInfo(1, typeof(Dog), 158, 10, 217, 0)); - Add(new AnimalBuyInfo(1, typeof(Cat), 131, 10, 201, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Bandage), 1); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Bandage), 6, 20, 0xE21, 0)); + Add(new AnimalBuyInfo(1, typeof(PackHorse), 616, 10, 291, 0)); + Add(new AnimalBuyInfo(1, typeof(PackLlama), 523, 10, 292, 0)); + Add(new AnimalBuyInfo(1, typeof(Dog), 158, 10, 217, 0)); + Add(new AnimalBuyInfo(1, typeof(Cat), 131, 10, 201, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Bandage), 1); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBWaiter.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBWaiter.cs index d63885804..2a695207a 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBWaiter.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBWaiter.cs @@ -3,50 +3,50 @@ using Server.Items; namespace Server.Mobiles { - public class SBWaiter : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBWaiter : SBInfo { - public InternalBuyInfo() - { - Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Ale, 7, 20, 0x99F, 0)); - Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Wine, 7, 20, 0x9C7, 0)); - Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Liquor, 7, 20, 0x99B, 0)); - Add(new BeverageBuyInfo(typeof(Jug), BeverageType.Cider, 13, 20, 0x9C8, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Milk, 7, 20, 0x9F0, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Ale, 11, 20, 0x1F95, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Cider, 11, 20, 0x1F97, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Liquor, 11, 20, 0x1F99, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Wine, 11, 20, 0x1F9B, 0)); - Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Water, 11, 20, 0x1F9D, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - Add(new GenericBuyInfo(typeof(BreadLoaf), 6, 10, 0x103B, 0)); - Add(new GenericBuyInfo(typeof(CheeseWheel), 21, 10, 0x97E, 0)); - Add(new GenericBuyInfo(typeof(CookedBird), 17, 20, 0x9B7, 0)); - Add(new GenericBuyInfo(typeof(LambLeg), 8, 20, 0x160A, 0)); + public override List BuyInfo { get; } = new InternalBuyInfo(); - Add(new GenericBuyInfo(typeof(WoodenBowlOfCarrots), 3, 20, 0x15F9, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfCorn), 3, 20, 0x15FA, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfLettuce), 3, 20, 0x15FB, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfPeas), 3, 20, 0x15FC, 0)); - Add(new GenericBuyInfo(typeof(EmptyPewterBowl), 2, 20, 0x15FD, 0)); - Add(new GenericBuyInfo(typeof(PewterBowlOfCorn), 3, 20, 0x15FE, 0)); - Add(new GenericBuyInfo(typeof(PewterBowlOfLettuce), 3, 20, 0x15FF, 0)); - Add(new GenericBuyInfo(typeof(PewterBowlOfPeas), 3, 20, 0x1600, 0)); - Add(new GenericBuyInfo(typeof(PewterBowlOfPotatos), 3, 20, 0x1601, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfStew), 3, 20, 0x1604, 0)); - Add(new GenericBuyInfo(typeof(WoodenBowlOfTomatoSoup), 3, 20, 0x1606, 0)); + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Ale, 7, 20, 0x99F, 0)); + Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Wine, 7, 20, 0x9C7, 0)); + Add(new BeverageBuyInfo(typeof(BeverageBottle), BeverageType.Liquor, 7, 20, 0x99B, 0)); + Add(new BeverageBuyInfo(typeof(Jug), BeverageType.Cider, 13, 20, 0x9C8, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Milk, 7, 20, 0x9F0, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Ale, 11, 20, 0x1F95, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Cider, 11, 20, 0x1F97, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Liquor, 11, 20, 0x1F99, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Wine, 11, 20, 0x1F9B, 0)); + Add(new BeverageBuyInfo(typeof(Pitcher), BeverageType.Water, 11, 20, 0x1F9D, 0)); - Add(new GenericBuyInfo(typeof(ApplePie), 7, 20, 0x1041, 0)); // OSI just has Pie, not Apple/Fruit/Meat - } + Add(new GenericBuyInfo(typeof(BreadLoaf), 6, 10, 0x103B, 0)); + Add(new GenericBuyInfo(typeof(CheeseWheel), 21, 10, 0x97E, 0)); + Add(new GenericBuyInfo(typeof(CookedBird), 17, 20, 0x9B7, 0)); + Add(new GenericBuyInfo(typeof(LambLeg), 8, 20, 0x160A, 0)); + + Add(new GenericBuyInfo(typeof(WoodenBowlOfCarrots), 3, 20, 0x15F9, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfCorn), 3, 20, 0x15FA, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfLettuce), 3, 20, 0x15FB, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfPeas), 3, 20, 0x15FC, 0)); + Add(new GenericBuyInfo(typeof(EmptyPewterBowl), 2, 20, 0x15FD, 0)); + Add(new GenericBuyInfo(typeof(PewterBowlOfCorn), 3, 20, 0x15FE, 0)); + Add(new GenericBuyInfo(typeof(PewterBowlOfLettuce), 3, 20, 0x15FF, 0)); + Add(new GenericBuyInfo(typeof(PewterBowlOfPeas), 3, 20, 0x1600, 0)); + Add(new GenericBuyInfo(typeof(PewterBowlOfPotatos), 3, 20, 0x1601, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfStew), 3, 20, 0x1604, 0)); + Add(new GenericBuyInfo(typeof(WoodenBowlOfTomatoSoup), 3, 20, 0x1606, 0)); + + Add(new GenericBuyInfo(typeof(ApplePie), 7, 20, 0x1041, 0)); // OSI just has Pie, not Apple/Fruit/Meat + } + } + + public class InternalSellInfo : GenericSellInfo + { + } } - - public class InternalSellInfo : GenericSellInfo - { - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBWeaponSmith.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBWeaponSmith.cs index be30565a9..96a8cc902 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBWeaponSmith.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBWeaponSmith.cs @@ -3,171 +3,171 @@ using Server.Items; namespace Server.Mobiles { - public class SBWeaponSmith : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBWeaponSmith : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(BlackStaff), 22, 20, 0xDF1, 0)); - Add(new GenericBuyInfo(typeof(Club), 16, 20, 0x13B4, 0)); - Add(new GenericBuyInfo(typeof(GnarledStaff), 16, 20, 0x13F8, 0)); - Add(new GenericBuyInfo(typeof(Mace), 28, 20, 0xF5C, 0)); - Add(new GenericBuyInfo(typeof(Maul), 21, 20, 0x143B, 0)); - Add(new GenericBuyInfo(typeof(QuarterStaff), 19, 20, 0xE89, 0)); - Add(new GenericBuyInfo(typeof(ShepherdsCrook), 20, 20, 0xE81, 0)); - Add(new GenericBuyInfo(typeof(SmithHammer), 21, 20, 0x13E3, 0)); - Add(new GenericBuyInfo(typeof(ShortSpear), 23, 20, 0x1403, 0)); - Add(new GenericBuyInfo(typeof(Spear), 31, 20, 0xF62, 0)); - Add(new GenericBuyInfo(typeof(WarHammer), 25, 20, 0x1439, 0)); - Add(new GenericBuyInfo(typeof(WarMace), 31, 20, 0x1407, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - if (Core.AOS) + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List { - Add(new GenericBuyInfo(typeof(Scepter), 39, 20, 0x26BC, 0)); - Add(new GenericBuyInfo(typeof(BladedStaff), 40, 20, 0x26BD, 0)); - } - - Add(new GenericBuyInfo(typeof(Hatchet), 25, 20, 0xF44, 0)); - Add(new GenericBuyInfo(typeof(Hatchet), 27, 20, 0xF43, 0)); - Add(new GenericBuyInfo(typeof(WarFork), 32, 20, 0x1405, 0)); - - switch (Utility.Random(3)) - { - case 0: + public InternalBuyInfo() { - Add(new GenericBuyInfo(typeof(ExecutionersAxe), 30, 20, 0xF45, 0)); - Add(new GenericBuyInfo(typeof(Bardiche), 60, 20, 0xF4D, 0)); - Add(new GenericBuyInfo(typeof(BattleAxe), 26, 20, 0xF47, 0)); - Add(new GenericBuyInfo(typeof(TwoHandedAxe), 32, 20, 0x1443, 0)); + Add(new GenericBuyInfo(typeof(BlackStaff), 22, 20, 0xDF1, 0)); + Add(new GenericBuyInfo(typeof(Club), 16, 20, 0x13B4, 0)); + Add(new GenericBuyInfo(typeof(GnarledStaff), 16, 20, 0x13F8, 0)); + Add(new GenericBuyInfo(typeof(Mace), 28, 20, 0xF5C, 0)); + Add(new GenericBuyInfo(typeof(Maul), 21, 20, 0x143B, 0)); + Add(new GenericBuyInfo(typeof(QuarterStaff), 19, 20, 0xE89, 0)); + Add(new GenericBuyInfo(typeof(ShepherdsCrook), 20, 20, 0xE81, 0)); + Add(new GenericBuyInfo(typeof(SmithHammer), 21, 20, 0x13E3, 0)); + Add(new GenericBuyInfo(typeof(ShortSpear), 23, 20, 0x1403, 0)); + Add(new GenericBuyInfo(typeof(Spear), 31, 20, 0xF62, 0)); + Add(new GenericBuyInfo(typeof(WarHammer), 25, 20, 0x1439, 0)); + Add(new GenericBuyInfo(typeof(WarMace), 31, 20, 0x1407, 0)); - Add(new GenericBuyInfo(typeof(Bow), 35, 20, 0x13B2, 0)); + if (Core.AOS) + { + Add(new GenericBuyInfo(typeof(Scepter), 39, 20, 0x26BC, 0)); + Add(new GenericBuyInfo(typeof(BladedStaff), 40, 20, 0x26BD, 0)); + } - Add(new GenericBuyInfo(typeof(ButcherKnife), 14, 20, 0x13F6, 0)); + Add(new GenericBuyInfo(typeof(Hatchet), 25, 20, 0xF44, 0)); + Add(new GenericBuyInfo(typeof(Hatchet), 27, 20, 0xF43, 0)); + Add(new GenericBuyInfo(typeof(WarFork), 32, 20, 0x1405, 0)); - Add(new GenericBuyInfo(typeof(Crossbow), 46, 20, 0xF50, 0)); - Add(new GenericBuyInfo(typeof(HeavyCrossbow), 55, 20, 0x13FD, 0)); + switch (Utility.Random(3)) + { + case 0: + { + Add(new GenericBuyInfo(typeof(ExecutionersAxe), 30, 20, 0xF45, 0)); + Add(new GenericBuyInfo(typeof(Bardiche), 60, 20, 0xF4D, 0)); + Add(new GenericBuyInfo(typeof(BattleAxe), 26, 20, 0xF47, 0)); + Add(new GenericBuyInfo(typeof(TwoHandedAxe), 32, 20, 0x1443, 0)); - Add(new GenericBuyInfo(typeof(Cutlass), 24, 20, 0x1441, 0)); - Add(new GenericBuyInfo(typeof(Dagger), 21, 20, 0xF52, 0)); - Add(new GenericBuyInfo(typeof(Halberd), 42, 20, 0x143E, 0)); + Add(new GenericBuyInfo(typeof(Bow), 35, 20, 0x13B2, 0)); - Add(new GenericBuyInfo(typeof(HammerPick), 26, 20, 0x143D, 0)); + Add(new GenericBuyInfo(typeof(ButcherKnife), 14, 20, 0x13F6, 0)); - Add(new GenericBuyInfo(typeof(Katana), 33, 20, 0x13FF, 0)); - Add(new GenericBuyInfo(typeof(Kryss), 32, 20, 0x1401, 0)); - Add(new GenericBuyInfo(typeof(Broadsword), 35, 20, 0xF5E, 0)); - Add(new GenericBuyInfo(typeof(Longsword), 55, 20, 0xF61, 0)); - Add(new GenericBuyInfo(typeof(ThinLongsword), 27, 20, 0x13B8, 0)); - Add(new GenericBuyInfo(typeof(VikingSword), 55, 20, 0x13B9, 0)); + Add(new GenericBuyInfo(typeof(Crossbow), 46, 20, 0xF50, 0)); + Add(new GenericBuyInfo(typeof(HeavyCrossbow), 55, 20, 0x13FD, 0)); - Add(new GenericBuyInfo(typeof(Cleaver), 15, 20, 0xEC3, 0)); - Add(new GenericBuyInfo(typeof(Axe), 40, 20, 0xF49, 0)); - Add(new GenericBuyInfo(typeof(DoubleAxe), 52, 20, 0xF4B, 0)); - Add(new GenericBuyInfo(typeof(Pickaxe), 22, 20, 0xE86, 0)); + Add(new GenericBuyInfo(typeof(Cutlass), 24, 20, 0x1441, 0)); + Add(new GenericBuyInfo(typeof(Dagger), 21, 20, 0xF52, 0)); + Add(new GenericBuyInfo(typeof(Halberd), 42, 20, 0x143E, 0)); - Add(new GenericBuyInfo(typeof(Pitchfork), 19, 20, 0xE87, 0)); + Add(new GenericBuyInfo(typeof(HammerPick), 26, 20, 0x143D, 0)); - Add(new GenericBuyInfo(typeof(Scimitar), 36, 20, 0x13B6, 0)); + Add(new GenericBuyInfo(typeof(Katana), 33, 20, 0x13FF, 0)); + Add(new GenericBuyInfo(typeof(Kryss), 32, 20, 0x1401, 0)); + Add(new GenericBuyInfo(typeof(Broadsword), 35, 20, 0xF5E, 0)); + Add(new GenericBuyInfo(typeof(Longsword), 55, 20, 0xF61, 0)); + Add(new GenericBuyInfo(typeof(ThinLongsword), 27, 20, 0x13B8, 0)); + Add(new GenericBuyInfo(typeof(VikingSword), 55, 20, 0x13B9, 0)); - Add(new GenericBuyInfo(typeof(SkinningKnife), 14, 20, 0xEC4, 0)); + Add(new GenericBuyInfo(typeof(Cleaver), 15, 20, 0xEC3, 0)); + Add(new GenericBuyInfo(typeof(Axe), 40, 20, 0xF49, 0)); + Add(new GenericBuyInfo(typeof(DoubleAxe), 52, 20, 0xF4B, 0)); + Add(new GenericBuyInfo(typeof(Pickaxe), 22, 20, 0xE86, 0)); - Add(new GenericBuyInfo(typeof(LargeBattleAxe), 33, 20, 0x13FB, 0)); - Add(new GenericBuyInfo(typeof(WarAxe), 29, 20, 0x13B0, 0)); + Add(new GenericBuyInfo(typeof(Pitchfork), 19, 20, 0xE87, 0)); - if (Core.AOS) - { - Add(new GenericBuyInfo(typeof(BoneHarvester), 35, 20, 0x26BB, 0)); - Add(new GenericBuyInfo(typeof(CrescentBlade), 37, 20, 0x26C1, 0)); - Add(new GenericBuyInfo(typeof(DoubleBladedStaff), 35, 20, 0x26BF, 0)); - Add(new GenericBuyInfo(typeof(Lance), 34, 20, 0x26C0, 0)); - Add(new GenericBuyInfo(typeof(Pike), 39, 20, 0x26BE, 0)); - Add(new GenericBuyInfo(typeof(Scythe), 39, 20, 0x26BA, 0)); - Add(new GenericBuyInfo(typeof(CompositeBow), 50, 20, 0x26C2, 0)); - Add(new GenericBuyInfo(typeof(RepeatingCrossbow), 57, 20, 0x26C3, 0)); - } + Add(new GenericBuyInfo(typeof(Scimitar), 36, 20, 0x13B6, 0)); - break; + Add(new GenericBuyInfo(typeof(SkinningKnife), 14, 20, 0xEC4, 0)); + + Add(new GenericBuyInfo(typeof(LargeBattleAxe), 33, 20, 0x13FB, 0)); + Add(new GenericBuyInfo(typeof(WarAxe), 29, 20, 0x13B0, 0)); + + if (Core.AOS) + { + Add(new GenericBuyInfo(typeof(BoneHarvester), 35, 20, 0x26BB, 0)); + Add(new GenericBuyInfo(typeof(CrescentBlade), 37, 20, 0x26C1, 0)); + Add(new GenericBuyInfo(typeof(DoubleBladedStaff), 35, 20, 0x26BF, 0)); + Add(new GenericBuyInfo(typeof(Lance), 34, 20, 0x26C0, 0)); + Add(new GenericBuyInfo(typeof(Pike), 39, 20, 0x26BE, 0)); + Add(new GenericBuyInfo(typeof(Scythe), 39, 20, 0x26BA, 0)); + Add(new GenericBuyInfo(typeof(CompositeBow), 50, 20, 0x26C2, 0)); + Add(new GenericBuyInfo(typeof(RepeatingCrossbow), 57, 20, 0x26C3, 0)); + } + + break; + } + } } } - } - } - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(BattleAxe), 13); - Add(typeof(DoubleAxe), 26); - Add(typeof(ExecutionersAxe), 15); - Add(typeof(LargeBattleAxe), 16); - Add(typeof(Pickaxe), 11); - Add(typeof(TwoHandedAxe), 16); - Add(typeof(WarAxe), 14); - Add(typeof(Axe), 20); - - Add(typeof(Bardiche), 30); - Add(typeof(Halberd), 21); - - Add(typeof(ButcherKnife), 7); - Add(typeof(Cleaver), 7); - Add(typeof(Dagger), 10); - Add(typeof(SkinningKnife), 7); - - Add(typeof(Club), 8); - Add(typeof(HammerPick), 13); - Add(typeof(Mace), 14); - Add(typeof(Maul), 10); - Add(typeof(WarHammer), 12); - Add(typeof(WarMace), 15); - - Add(typeof(HeavyCrossbow), 27); - Add(typeof(Bow), 17); - Add(typeof(Crossbow), 23); - - if (Core.AOS) + public class InternalSellInfo : GenericSellInfo { - Add(typeof(CompositeBow), 25); - Add(typeof(RepeatingCrossbow), 28); - Add(typeof(Scepter), 20); - Add(typeof(BladedStaff), 20); - Add(typeof(Scythe), 19); - Add(typeof(BoneHarvester), 17); - Add(typeof(Scepter), 18); - Add(typeof(BladedStaff), 16); - Add(typeof(Pike), 19); - Add(typeof(DoubleBladedStaff), 17); - Add(typeof(Lance), 17); - Add(typeof(CrescentBlade), 18); + public InternalSellInfo() + { + Add(typeof(BattleAxe), 13); + Add(typeof(DoubleAxe), 26); + Add(typeof(ExecutionersAxe), 15); + Add(typeof(LargeBattleAxe), 16); + Add(typeof(Pickaxe), 11); + Add(typeof(TwoHandedAxe), 16); + Add(typeof(WarAxe), 14); + Add(typeof(Axe), 20); + + Add(typeof(Bardiche), 30); + Add(typeof(Halberd), 21); + + Add(typeof(ButcherKnife), 7); + Add(typeof(Cleaver), 7); + Add(typeof(Dagger), 10); + Add(typeof(SkinningKnife), 7); + + Add(typeof(Club), 8); + Add(typeof(HammerPick), 13); + Add(typeof(Mace), 14); + Add(typeof(Maul), 10); + Add(typeof(WarHammer), 12); + Add(typeof(WarMace), 15); + + Add(typeof(HeavyCrossbow), 27); + Add(typeof(Bow), 17); + Add(typeof(Crossbow), 23); + + if (Core.AOS) + { + Add(typeof(CompositeBow), 25); + Add(typeof(RepeatingCrossbow), 28); + Add(typeof(Scepter), 20); + Add(typeof(BladedStaff), 20); + Add(typeof(Scythe), 19); + Add(typeof(BoneHarvester), 17); + Add(typeof(Scepter), 18); + Add(typeof(BladedStaff), 16); + Add(typeof(Pike), 19); + Add(typeof(DoubleBladedStaff), 17); + Add(typeof(Lance), 17); + Add(typeof(CrescentBlade), 18); + } + + Add(typeof(Spear), 15); + Add(typeof(Pitchfork), 9); + Add(typeof(ShortSpear), 11); + + Add(typeof(BlackStaff), 11); + Add(typeof(GnarledStaff), 8); + Add(typeof(QuarterStaff), 9); + Add(typeof(ShepherdsCrook), 10); + + Add(typeof(SmithHammer), 10); + + Add(typeof(Broadsword), 17); + Add(typeof(Cutlass), 12); + Add(typeof(Katana), 16); + Add(typeof(Kryss), 16); + Add(typeof(Longsword), 27); + Add(typeof(Scimitar), 18); + Add(typeof(ThinLongsword), 13); + Add(typeof(VikingSword), 27); + + Add(typeof(Hatchet), 13); + Add(typeof(WarFork), 16); + } } - - Add(typeof(Spear), 15); - Add(typeof(Pitchfork), 9); - Add(typeof(ShortSpear), 11); - - Add(typeof(BlackStaff), 11); - Add(typeof(GnarledStaff), 8); - Add(typeof(QuarterStaff), 9); - Add(typeof(ShepherdsCrook), 10); - - Add(typeof(SmithHammer), 10); - - Add(typeof(Broadsword), 17); - Add(typeof(Cutlass), 12); - Add(typeof(Katana), 16); - Add(typeof(Kryss), 16); - Add(typeof(Longsword), 27); - Add(typeof(Scimitar), 18); - Add(typeof(ThinLongsword), 13); - Add(typeof(VikingSword), 27); - - Add(typeof(Hatchet), 13); - Add(typeof(WarFork), 16); - } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBWeaver.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBWeaver.cs index 28af88a86..b6990adfa 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SBWeaver.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SBWeaver.cs @@ -3,50 +3,50 @@ using Server.Items; namespace Server.Mobiles { - public class SBWeaver : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBWeaver : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Dyes), 8, 20, 0xFA9, 0)); - Add(new GenericBuyInfo(typeof(DyeTub), 8, 20, 0xFAB, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - Add(new GenericBuyInfo(typeof(UncutCloth), 3, 20, 0x1761, 0)); - Add(new GenericBuyInfo(typeof(UncutCloth), 3, 20, 0x1762, 0)); - Add(new GenericBuyInfo(typeof(UncutCloth), 3, 20, 0x1763, 0)); - Add(new GenericBuyInfo(typeof(UncutCloth), 3, 20, 0x1764, 0)); + public override List BuyInfo { get; } = new InternalBuyInfo(); - Add(new GenericBuyInfo(typeof(BoltOfCloth), 100, 20, 0xf9B, 0)); - Add(new GenericBuyInfo(typeof(BoltOfCloth), 100, 20, 0xf9C, 0)); - Add(new GenericBuyInfo(typeof(BoltOfCloth), 100, 20, 0xf96, 0)); - Add(new GenericBuyInfo(typeof(BoltOfCloth), 100, 20, 0xf97, 0)); + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Dyes), 8, 20, 0xFA9, 0)); + Add(new GenericBuyInfo(typeof(DyeTub), 8, 20, 0xFAB, 0)); - Add(new GenericBuyInfo(typeof(DarkYarn), 18, 20, 0xE1D, 0)); - Add(new GenericBuyInfo(typeof(LightYarn), 18, 20, 0xE1E, 0)); - Add(new GenericBuyInfo(typeof(LightYarnUnraveled), 18, 20, 0xE1F, 0)); + Add(new GenericBuyInfo(typeof(UncutCloth), 3, 20, 0x1761, 0)); + Add(new GenericBuyInfo(typeof(UncutCloth), 3, 20, 0x1762, 0)); + Add(new GenericBuyInfo(typeof(UncutCloth), 3, 20, 0x1763, 0)); + Add(new GenericBuyInfo(typeof(UncutCloth), 3, 20, 0x1764, 0)); - Add(new GenericBuyInfo(typeof(Scissors), 11, 20, 0xF9F, 0)); - } + Add(new GenericBuyInfo(typeof(BoltOfCloth), 100, 20, 0xf9B, 0)); + Add(new GenericBuyInfo(typeof(BoltOfCloth), 100, 20, 0xf9C, 0)); + Add(new GenericBuyInfo(typeof(BoltOfCloth), 100, 20, 0xf96, 0)); + Add(new GenericBuyInfo(typeof(BoltOfCloth), 100, 20, 0xf97, 0)); + + Add(new GenericBuyInfo(typeof(DarkYarn), 18, 20, 0xE1D, 0)); + Add(new GenericBuyInfo(typeof(LightYarn), 18, 20, 0xE1E, 0)); + Add(new GenericBuyInfo(typeof(LightYarnUnraveled), 18, 20, 0xE1F, 0)); + + Add(new GenericBuyInfo(typeof(Scissors), 11, 20, 0xF9F, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Scissors), 6); + Add(typeof(Dyes), 4); + Add(typeof(DyeTub), 4); + Add(typeof(UncutCloth), 1); + Add(typeof(BoltOfCloth), 50); + Add(typeof(LightYarnUnraveled), 9); + Add(typeof(LightYarn), 9); + Add(typeof(DarkYarn), 9); + } + } } - - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Scissors), 6); - Add(typeof(Dyes), 4); - Add(typeof(DyeTub), 4); - Add(typeof(UncutCloth), 1); - Add(typeof(BoltOfCloth), 50); - Add(typeof(LightYarnUnraveled), 9); - Add(typeof(LightYarn), 9); - Add(typeof(DarkYarn), 9); - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSEArmor.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSEArmor.cs index 1d3271eb1..6b08ae95d 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSEArmor.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSEArmor.cs @@ -3,40 +3,40 @@ using Server.Items; namespace Server.Mobiles { - public class SBSEArmor : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBSEArmor : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(PlateHatsuburi), 76, 20, 0x2775, 0)); - Add(new GenericBuyInfo(typeof(HeavyPlateJingasa), 76, 20, 0x2777, 0)); - Add(new GenericBuyInfo(typeof(DecorativePlateKabuto), 95, 20, 0x2778, 0)); - Add(new GenericBuyInfo(typeof(PlateDo), 310, 20, 0x277D, 0)); - Add(new GenericBuyInfo(typeof(PlateHiroSode), 222, 20, 0x2780, 0)); - Add(new GenericBuyInfo(typeof(PlateSuneate), 224, 20, 0x2788, 0)); - Add(new GenericBuyInfo(typeof(PlateHaidate), 235, 20, 0x278D, 0)); - Add(new GenericBuyInfo(typeof(ChainHatsuburi), 76, 20, 0x2774, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(PlateHatsuburi), 38); - Add(typeof(HeavyPlateJingasa), 38); - Add(typeof(DecorativePlateKabuto), 47); - Add(typeof(PlateDo), 155); - Add(typeof(PlateHiroSode), 111); - Add(typeof(PlateSuneate), 112); - Add(typeof(PlateHaidate), 117); - Add(typeof(ChainHatsuburi), 38); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(PlateHatsuburi), 76, 20, 0x2775, 0)); + Add(new GenericBuyInfo(typeof(HeavyPlateJingasa), 76, 20, 0x2777, 0)); + Add(new GenericBuyInfo(typeof(DecorativePlateKabuto), 95, 20, 0x2778, 0)); + Add(new GenericBuyInfo(typeof(PlateDo), 310, 20, 0x277D, 0)); + Add(new GenericBuyInfo(typeof(PlateHiroSode), 222, 20, 0x2780, 0)); + Add(new GenericBuyInfo(typeof(PlateSuneate), 224, 20, 0x2788, 0)); + Add(new GenericBuyInfo(typeof(PlateHaidate), 235, 20, 0x278D, 0)); + Add(new GenericBuyInfo(typeof(ChainHatsuburi), 76, 20, 0x2774, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(PlateHatsuburi), 38); + Add(typeof(HeavyPlateJingasa), 38); + Add(typeof(DecorativePlateKabuto), 47); + Add(typeof(PlateDo), 155); + Add(typeof(PlateHiroSode), 111); + Add(typeof(PlateSuneate), 112); + Add(typeof(PlateHaidate), 117); + Add(typeof(ChainHatsuburi), 38); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSEBowyer.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSEBowyer.cs index 32b3a7095..6be6fe262 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSEBowyer.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSEBowyer.cs @@ -3,34 +3,34 @@ using Server.Items; namespace Server.Mobiles { - public class SBSEBowyer : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBSEBowyer : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Yumi), 53, 20, 0x27A5, 0)); - Add(new GenericBuyInfo(typeof(Fukiya), 20, 20, 0x27AA, 0)); - Add(new GenericBuyInfo(typeof(Nunchaku), 35, 20, 0x27AE, 0)); - Add(new GenericBuyInfo(typeof(FukiyaDarts), 3, 20, 0x2806, 0)); - Add(new GenericBuyInfo(typeof(Bokuto), 21, 20, 0x27A8, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Yumi), 26); - Add(typeof(Fukiya), 10); - Add(typeof(Nunchaku), 17); - Add(typeof(FukiyaDarts), 1); - Add(typeof(Bokuto), 10); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Yumi), 53, 20, 0x27A5, 0)); + Add(new GenericBuyInfo(typeof(Fukiya), 20, 20, 0x27AA, 0)); + Add(new GenericBuyInfo(typeof(Nunchaku), 35, 20, 0x27AE, 0)); + Add(new GenericBuyInfo(typeof(FukiyaDarts), 3, 20, 0x2806, 0)); + Add(new GenericBuyInfo(typeof(Bokuto), 21, 20, 0x27A8, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Yumi), 26); + Add(typeof(Fukiya), 10); + Add(typeof(Nunchaku), 17); + Add(typeof(FukiyaDarts), 1); + Add(typeof(Bokuto), 10); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSECarpenter.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSECarpenter.cs index 4973007de..80b3c17d0 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSECarpenter.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSECarpenter.cs @@ -3,33 +3,33 @@ using Server.Items; namespace Server.Mobiles { - public class SBSECarpenter : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBSECarpenter : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Bokuto), 21, 20, 0x27A8, 0)); - Add(new GenericBuyInfo(typeof(Tetsubo), 43, 20, 0x27A6, 0)); - Add(new GenericBuyInfo(typeof(Fukiya), 20, 20, 0x27AA, 0)); - Add(new GenericBuyInfo(typeof(BambooFlute), 21, 20, 0x2805, 0)); - Add(new GenericBuyInfo(typeof(BambooFlute), 21, 20, 0x2805, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Tetsubo), 21); - Add(typeof(Fukiya), 10); - Add(typeof(BambooFlute), 10); - Add(typeof(Bokuto), 10); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Bokuto), 21, 20, 0x27A8, 0)); + Add(new GenericBuyInfo(typeof(Tetsubo), 43, 20, 0x27A6, 0)); + Add(new GenericBuyInfo(typeof(Fukiya), 20, 20, 0x27AA, 0)); + Add(new GenericBuyInfo(typeof(BambooFlute), 21, 20, 0x2805, 0)); + Add(new GenericBuyInfo(typeof(BambooFlute), 21, 20, 0x2805, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Tetsubo), 21); + Add(typeof(Fukiya), 10); + Add(typeof(BambooFlute), 10); + Add(typeof(Bokuto), 10); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSEFood.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSEFood.cs index 04e404133..3916d19f3 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSEFood.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSEFood.cs @@ -3,32 +3,32 @@ using Server.Items; namespace Server.Mobiles { - public class SBSEFood : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBSEFood : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Wasabi), 2, 20, 0x24E8, 0)); - Add(new GenericBuyInfo(typeof(Wasabi), 2, 20, 0x24E9, 0)); - Add(new GenericBuyInfo(typeof(BentoBox), 6, 20, 0x2836, 0)); - Add(new GenericBuyInfo(typeof(BentoBox), 6, 20, 0x2837, 0)); - Add(new GenericBuyInfo(typeof(GreenTeaBasket), 2, 20, 0x284B, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Wasabi), 1); - Add(typeof(BentoBox), 3); - Add(typeof(GreenTeaBasket), 1); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Wasabi), 2, 20, 0x24E8, 0)); + Add(new GenericBuyInfo(typeof(Wasabi), 2, 20, 0x24E9, 0)); + Add(new GenericBuyInfo(typeof(BentoBox), 6, 20, 0x2836, 0)); + Add(new GenericBuyInfo(typeof(BentoBox), 6, 20, 0x2837, 0)); + Add(new GenericBuyInfo(typeof(GreenTeaBasket), 2, 20, 0x284B, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Wasabi), 1); + Add(typeof(BentoBox), 3); + Add(typeof(GreenTeaBasket), 1); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSELeatherArmor.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSELeatherArmor.cs index 172a2a330..1d6eac3c1 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSELeatherArmor.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSELeatherArmor.cs @@ -3,49 +3,49 @@ using Server.Items; namespace Server.Mobiles { - public class SBSELeatherArmor : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBSELeatherArmor : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(LeatherJingasa), 11, 20, 0x2776, 0)); - Add(new GenericBuyInfo(typeof(LeatherDo), 87, 20, 0x277B, 0)); - Add(new GenericBuyInfo(typeof(LeatherHiroSode), 49, 20, 0x277E, 0)); - Add(new GenericBuyInfo(typeof(LeatherSuneate), 55, 20, 0x2786, 0)); - Add(new GenericBuyInfo(typeof(LeatherHaidate), 54, 20, 0x278A, 0)); - Add(new GenericBuyInfo(typeof(LeatherNinjaPants), 49, 20, 0x2791, 0)); - Add(new GenericBuyInfo(typeof(LeatherNinjaJacket), 51, 20, 0x2793, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - Add(new GenericBuyInfo(typeof(StuddedMempo), 61, 20, 0x279D, 0)); - Add(new GenericBuyInfo(typeof(StuddedDo), 130, 20, 0x277C, 0)); - Add(new GenericBuyInfo(typeof(StuddedHiroSode), 73, 20, 0x277F, 0)); - Add(new GenericBuyInfo(typeof(StuddedSuneate), 78, 20, 0x2787, 0)); - Add(new GenericBuyInfo(typeof(StuddedHaidate), 76, 20, 0x278B, 0)); - } - } + public override List BuyInfo { get; } = new InternalBuyInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(LeatherJingasa), 5); - Add(typeof(LeatherDo), 42); - Add(typeof(LeatherHiroSode), 23); - Add(typeof(LeatherSuneate), 26); - Add(typeof(LeatherHaidate), 28); - Add(typeof(LeatherNinjaPants), 25); - Add(typeof(LeatherNinjaJacket), 26); - Add(typeof(StuddedMempo), 28); - Add(typeof(StuddedDo), 66); - Add(typeof(StuddedHiroSode), 32); - Add(typeof(StuddedSuneate), 40); - Add(typeof(StuddedHaidate), 37); - } + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(LeatherJingasa), 11, 20, 0x2776, 0)); + Add(new GenericBuyInfo(typeof(LeatherDo), 87, 20, 0x277B, 0)); + Add(new GenericBuyInfo(typeof(LeatherHiroSode), 49, 20, 0x277E, 0)); + Add(new GenericBuyInfo(typeof(LeatherSuneate), 55, 20, 0x2786, 0)); + Add(new GenericBuyInfo(typeof(LeatherHaidate), 54, 20, 0x278A, 0)); + Add(new GenericBuyInfo(typeof(LeatherNinjaPants), 49, 20, 0x2791, 0)); + Add(new GenericBuyInfo(typeof(LeatherNinjaJacket), 51, 20, 0x2793, 0)); + + Add(new GenericBuyInfo(typeof(StuddedMempo), 61, 20, 0x279D, 0)); + Add(new GenericBuyInfo(typeof(StuddedDo), 130, 20, 0x277C, 0)); + Add(new GenericBuyInfo(typeof(StuddedHiroSode), 73, 20, 0x277F, 0)); + Add(new GenericBuyInfo(typeof(StuddedSuneate), 78, 20, 0x2787, 0)); + Add(new GenericBuyInfo(typeof(StuddedHaidate), 76, 20, 0x278B, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(LeatherJingasa), 5); + Add(typeof(LeatherDo), 42); + Add(typeof(LeatherHiroSode), 23); + Add(typeof(LeatherSuneate), 26); + Add(typeof(LeatherHaidate), 28); + Add(typeof(LeatherNinjaPants), 25); + Add(typeof(LeatherNinjaJacket), 26); + Add(typeof(StuddedMempo), 28); + Add(typeof(StuddedDo), 66); + Add(typeof(StuddedHiroSode), 32); + Add(typeof(StuddedSuneate), 40); + Add(typeof(StuddedHaidate), 37); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSEWeapons.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSEWeapons.cs index 46511bd57..68ebd912b 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSEWeapons.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/SE/SBSEWeapons.cs @@ -3,44 +3,44 @@ using Server.Items; namespace Server.Mobiles { - public class SBSEWeapons : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBSEWeapons : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(NoDachi), 82, 20, 0x27A2, 0)); - Add(new GenericBuyInfo(typeof(Tessen), 83, 20, 0x27A3, 0)); - Add(new GenericBuyInfo(typeof(Wakizashi), 38, 20, 0x27A4, 0)); - Add(new GenericBuyInfo(typeof(Tetsubo), 43, 20, 0x27A6, 0)); - Add(new GenericBuyInfo(typeof(Lajatang), 108, 20, 0x27A7, 0)); - Add(new GenericBuyInfo(typeof(Daisho), 66, 20, 0x27A9, 0)); - Add(new GenericBuyInfo(typeof(Tekagi), 55, 20, 0x27AB, 0)); - Add(new GenericBuyInfo(typeof(Shuriken), 18, 20, 0x27AC, 0)); - Add(new GenericBuyInfo(typeof(Kama), 61, 20, 0x27AD, 0)); - Add(new GenericBuyInfo(typeof(Sai), 56, 20, 0x27AF, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(NoDachi), 41); - Add(typeof(Tessen), 41); - Add(typeof(Wakizashi), 19); - Add(typeof(Tetsubo), 21); - Add(typeof(Lajatang), 54); - Add(typeof(Daisho), 33); - Add(typeof(Tekagi), 22); - Add(typeof(Shuriken), 9); - Add(typeof(Kama), 30); - Add(typeof(Sai), 28); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(NoDachi), 82, 20, 0x27A2, 0)); + Add(new GenericBuyInfo(typeof(Tessen), 83, 20, 0x27A3, 0)); + Add(new GenericBuyInfo(typeof(Wakizashi), 38, 20, 0x27A4, 0)); + Add(new GenericBuyInfo(typeof(Tetsubo), 43, 20, 0x27A6, 0)); + Add(new GenericBuyInfo(typeof(Lajatang), 108, 20, 0x27A7, 0)); + Add(new GenericBuyInfo(typeof(Daisho), 66, 20, 0x27A9, 0)); + Add(new GenericBuyInfo(typeof(Tekagi), 55, 20, 0x27AB, 0)); + Add(new GenericBuyInfo(typeof(Shuriken), 18, 20, 0x27AC, 0)); + Add(new GenericBuyInfo(typeof(Kama), 61, 20, 0x27AD, 0)); + Add(new GenericBuyInfo(typeof(Sai), 56, 20, 0x27AF, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(NoDachi), 41); + Add(typeof(Tessen), 41); + Add(typeof(Wakizashi), 19); + Add(typeof(Tetsubo), 21); + Add(typeof(Lajatang), 54); + Add(typeof(Daisho), 33); + Add(typeof(Tekagi), 22); + Add(typeof(Shuriken), 9); + Add(typeof(Kama), 30); + Add(typeof(Sai), 28); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBAxeWeapon.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBAxeWeapon.cs index 329e0581f..513564ce9 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBAxeWeapon.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBAxeWeapon.cs @@ -3,40 +3,40 @@ using Server.Items; namespace Server.Mobiles { - public class SBAxeWeapon : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBAxeWeapon : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(ExecutionersAxe), 30, 20, 0xF45, 0)); - Add(new GenericBuyInfo(typeof(BattleAxe), 26, 20, 0xF47, 0)); - Add(new GenericBuyInfo(typeof(TwoHandedAxe), 32, 20, 0x1443, 0)); - Add(new GenericBuyInfo(typeof(Axe), 40, 20, 0xF49, 0)); - Add(new GenericBuyInfo(typeof(DoubleAxe), 52, 20, 0xF4B, 0)); - Add(new GenericBuyInfo(typeof(Pickaxe), 22, 20, 0xE86, 0)); - Add(new GenericBuyInfo(typeof(LargeBattleAxe), 33, 20, 0x13FB, 0)); - Add(new GenericBuyInfo(typeof(WarAxe), 29, 20, 0x13B0, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(BattleAxe), 13); - Add(typeof(DoubleAxe), 26); - Add(typeof(ExecutionersAxe), 15); - Add(typeof(LargeBattleAxe), 16); - Add(typeof(Pickaxe), 11); - Add(typeof(TwoHandedAxe), 16); - Add(typeof(WarAxe), 14); - Add(typeof(Axe), 20); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(ExecutionersAxe), 30, 20, 0xF45, 0)); + Add(new GenericBuyInfo(typeof(BattleAxe), 26, 20, 0xF47, 0)); + Add(new GenericBuyInfo(typeof(TwoHandedAxe), 32, 20, 0x1443, 0)); + Add(new GenericBuyInfo(typeof(Axe), 40, 20, 0xF49, 0)); + Add(new GenericBuyInfo(typeof(DoubleAxe), 52, 20, 0xF4B, 0)); + Add(new GenericBuyInfo(typeof(Pickaxe), 22, 20, 0xE86, 0)); + Add(new GenericBuyInfo(typeof(LargeBattleAxe), 33, 20, 0x13FB, 0)); + Add(new GenericBuyInfo(typeof(WarAxe), 29, 20, 0x13B0, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(BattleAxe), 13); + Add(typeof(DoubleAxe), 26); + Add(typeof(ExecutionersAxe), 15); + Add(typeof(LargeBattleAxe), 16); + Add(typeof(Pickaxe), 11); + Add(typeof(TwoHandedAxe), 16); + Add(typeof(WarAxe), 14); + Add(typeof(Axe), 20); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBKnifeWeapon.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBKnifeWeapon.cs index 1b76eebdf..8193f9931 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBKnifeWeapon.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBKnifeWeapon.cs @@ -3,32 +3,32 @@ using Server.Items; namespace Server.Mobiles { - public class SBKnifeWeapon : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBKnifeWeapon : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(ButcherKnife), 14, 20, 0x13F6, 0)); - Add(new GenericBuyInfo(typeof(Dagger), 21, 20, 0xF52, 0)); - Add(new GenericBuyInfo(typeof(Cleaver), 15, 20, 0xEC3, 0)); - Add(new GenericBuyInfo(typeof(SkinningKnife), 14, 20, 0xEC4, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(ButcherKnife), 7); - Add(typeof(Cleaver), 7); - Add(typeof(Dagger), 10); - Add(typeof(SkinningKnife), 7); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(ButcherKnife), 14, 20, 0x13F6, 0)); + Add(new GenericBuyInfo(typeof(Dagger), 21, 20, 0xF52, 0)); + Add(new GenericBuyInfo(typeof(Cleaver), 15, 20, 0xEC3, 0)); + Add(new GenericBuyInfo(typeof(SkinningKnife), 14, 20, 0xEC4, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(ButcherKnife), 7); + Add(typeof(Cleaver), 7); + Add(typeof(Dagger), 10); + Add(typeof(SkinningKnife), 7); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBMaceWeapon.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBMaceWeapon.cs index d88f87b2f..860defd42 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBMaceWeapon.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBMaceWeapon.cs @@ -3,36 +3,36 @@ using Server.Items; namespace Server.Mobiles { - public class SBMaceWeapon : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBMaceWeapon : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(HammerPick), 26, 20, 0x143D, 0)); - Add(new GenericBuyInfo(typeof(Club), 16, 20, 0x13B4, 0)); - Add(new GenericBuyInfo(typeof(Mace), 28, 20, 0xF5C, 0)); - Add(new GenericBuyInfo(typeof(Maul), 21, 20, 0x143B, 0)); - Add(new GenericBuyInfo(typeof(WarHammer), 25, 20, 0x1439, 0)); - Add(new GenericBuyInfo(typeof(WarMace), 31, 20, 0x1407, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Club), 8); - Add(typeof(HammerPick), 13); - Add(typeof(Mace), 14); - Add(typeof(Maul), 10); - Add(typeof(WarHammer), 12); - Add(typeof(WarMace), 15); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(HammerPick), 26, 20, 0x143D, 0)); + Add(new GenericBuyInfo(typeof(Club), 16, 20, 0x13B4, 0)); + Add(new GenericBuyInfo(typeof(Mace), 28, 20, 0xF5C, 0)); + Add(new GenericBuyInfo(typeof(Maul), 21, 20, 0x143B, 0)); + Add(new GenericBuyInfo(typeof(WarHammer), 25, 20, 0x1439, 0)); + Add(new GenericBuyInfo(typeof(WarMace), 31, 20, 0x1407, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Club), 8); + Add(typeof(HammerPick), 13); + Add(typeof(Mace), 14); + Add(typeof(Maul), 10); + Add(typeof(WarHammer), 12); + Add(typeof(WarMace), 15); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBPoleArmWeapon.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBPoleArmWeapon.cs index 38d6714d4..bac4ff990 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBPoleArmWeapon.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBPoleArmWeapon.cs @@ -3,28 +3,28 @@ using Server.Items; namespace Server.Mobiles { - public class SBPoleArmWeapon : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBPoleArmWeapon : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Bardiche), 60, 20, 0xF4D, 0)); - Add(new GenericBuyInfo(typeof(Halberd), 42, 20, 0x143E, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Bardiche), 30); - Add(typeof(Halberd), 21); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Bardiche), 60, 20, 0xF4D, 0)); + Add(new GenericBuyInfo(typeof(Halberd), 42, 20, 0x143E, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Bardiche), 30); + Add(typeof(Halberd), 21); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBRangedWeapon.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBRangedWeapon.cs index 2bdc3ab78..4103e59db 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBRangedWeapon.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBRangedWeapon.cs @@ -3,51 +3,51 @@ using Server.Items; namespace Server.Mobiles { - public class SBRangedWeapon : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBRangedWeapon : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Crossbow), 55, 20, 0xF50, 0)); - Add(new GenericBuyInfo(typeof(HeavyCrossbow), 55, 20, 0x13FD, 0)); - if (Core.AOS) + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); + + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List { - Add(new GenericBuyInfo(typeof(RepeatingCrossbow), 46, 20, 0x26C3, 0)); - Add(new GenericBuyInfo(typeof(CompositeBow), 45, 20, 0x26C2, 0)); + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Crossbow), 55, 20, 0xF50, 0)); + Add(new GenericBuyInfo(typeof(HeavyCrossbow), 55, 20, 0x13FD, 0)); + if (Core.AOS) + { + Add(new GenericBuyInfo(typeof(RepeatingCrossbow), 46, 20, 0x26C3, 0)); + Add(new GenericBuyInfo(typeof(CompositeBow), 45, 20, 0x26C2, 0)); + } + + Add(new GenericBuyInfo(typeof(Bolt), 2, Utility.Random(30, 60), 0x1BFB, 0)); + Add(new GenericBuyInfo(typeof(Bow), 40, 20, 0x13B2, 0)); + Add(new GenericBuyInfo(typeof(Arrow), 2, Utility.Random(30, 60), 0xF3F, 0)); + Add(new GenericBuyInfo(typeof(Feather), 2, Utility.Random(30, 60), 0x1BD1, 0)); + Add(new GenericBuyInfo(typeof(Shaft), 3, Utility.Random(30, 60), 0x1BD4, 0)); + } } - Add(new GenericBuyInfo(typeof(Bolt), 2, Utility.Random(30, 60), 0x1BFB, 0)); - Add(new GenericBuyInfo(typeof(Bow), 40, 20, 0x13B2, 0)); - Add(new GenericBuyInfo(typeof(Arrow), 2, Utility.Random(30, 60), 0xF3F, 0)); - Add(new GenericBuyInfo(typeof(Feather), 2, Utility.Random(30, 60), 0x1BD1, 0)); - Add(new GenericBuyInfo(typeof(Shaft), 3, Utility.Random(30, 60), 0x1BD4, 0)); - } - } - - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Bolt), 1); - Add(typeof(Arrow), 1); - Add(typeof(Shaft), 1); - Add(typeof(Feather), 1); - - Add(typeof(HeavyCrossbow), 27); - Add(typeof(Bow), 17); - Add(typeof(Crossbow), 25); - - if (Core.AOS) + public class InternalSellInfo : GenericSellInfo { - Add(typeof(CompositeBow), 23); - Add(typeof(RepeatingCrossbow), 22); + public InternalSellInfo() + { + Add(typeof(Bolt), 1); + Add(typeof(Arrow), 1); + Add(typeof(Shaft), 1); + Add(typeof(Feather), 1); + + Add(typeof(HeavyCrossbow), 27); + Add(typeof(Bow), 17); + Add(typeof(Crossbow), 25); + + if (Core.AOS) + { + Add(typeof(CompositeBow), 23); + Add(typeof(RepeatingCrossbow), 22); + } + } } - } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBSpearForkWeapon.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBSpearForkWeapon.cs index 65d3d75da..ce83fe793 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBSpearForkWeapon.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBSpearForkWeapon.cs @@ -3,30 +3,30 @@ using Server.Items; namespace Server.Mobiles { - public class SBSpearForkWeapon : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBSpearForkWeapon : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Pitchfork), 19, 20, 0xE87, 0)); - Add(new GenericBuyInfo(typeof(ShortSpear), 23, 20, 0x1403, 0)); - Add(new GenericBuyInfo(typeof(Spear), 31, 20, 0xF62, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Spear), 15); - Add(typeof(Pitchfork), 9); - Add(typeof(ShortSpear), 11); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Pitchfork), 19, 20, 0xE87, 0)); + Add(new GenericBuyInfo(typeof(ShortSpear), 23, 20, 0x1403, 0)); + Add(new GenericBuyInfo(typeof(Spear), 31, 20, 0xF62, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(Spear), 15); + Add(typeof(Pitchfork), 9); + Add(typeof(ShortSpear), 11); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBStavesWeapon.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBStavesWeapon.cs index b4986561e..c976699cc 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBStavesWeapon.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBStavesWeapon.cs @@ -3,32 +3,32 @@ using Server.Items; namespace Server.Mobiles { - public class SBStavesWeapon : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBStavesWeapon : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(BlackStaff), 22, 20, 0xDF1, 0)); - Add(new GenericBuyInfo(typeof(GnarledStaff), 16, 20, 0x13F8, 0)); - Add(new GenericBuyInfo(typeof(QuarterStaff), 19, 20, 0xE89, 0)); - Add(new GenericBuyInfo(typeof(ShepherdsCrook), 20, 20, 0xE81, 0)); - } - } + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(BlackStaff), 11); - Add(typeof(GnarledStaff), 8); - Add(typeof(QuarterStaff), 9); - Add(typeof(ShepherdsCrook), 10); - } + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List + { + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(BlackStaff), 22, 20, 0xDF1, 0)); + Add(new GenericBuyInfo(typeof(GnarledStaff), 16, 20, 0x13F8, 0)); + Add(new GenericBuyInfo(typeof(QuarterStaff), 19, 20, 0xE89, 0)); + Add(new GenericBuyInfo(typeof(ShepherdsCrook), 20, 20, 0xE81, 0)); + } + } + + public class InternalSellInfo : GenericSellInfo + { + public InternalSellInfo() + { + Add(typeof(BlackStaff), 11); + Add(typeof(GnarledStaff), 8); + Add(typeof(QuarterStaff), 9); + Add(typeof(ShepherdsCrook), 10); + } + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBSwordWeapon.cs b/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBSwordWeapon.cs index 2aab52245..84b0e4641 100644 --- a/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBSwordWeapon.cs +++ b/Projects/UOContent/Mobiles/Vendors/SBInfo/Weapons/SBSwordWeapon.cs @@ -3,62 +3,62 @@ using Server.Items; namespace Server.Mobiles { - public class SBSwordWeapon : SBInfo - { - public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - - public override List BuyInfo { get; } = new InternalBuyInfo(); - - public class InternalBuyInfo : List + public class SBSwordWeapon : SBInfo { - public InternalBuyInfo() - { - Add(new GenericBuyInfo(typeof(Cutlass), 24, 20, 0x1441, 0)); - Add(new GenericBuyInfo(typeof(Katana), 33, 20, 0x13FF, 0)); - Add(new GenericBuyInfo(typeof(Kryss), 32, 20, 0x1401, 0)); - Add(new GenericBuyInfo(typeof(Broadsword), 35, 20, 0xF5E, 0)); - Add(new GenericBuyInfo(typeof(Longsword), 55, 20, 0xF61, 0)); - Add(new GenericBuyInfo(typeof(ThinLongsword), 27, 20, 0x13B8, 0)); - Add(new GenericBuyInfo(typeof(VikingSword), 55, 20, 0x13B9, 0)); - Add(new GenericBuyInfo(typeof(Scimitar), 36, 20, 0x13B6, 0)); + public override IShopSellInfo SellInfo { get; } = new InternalSellInfo(); - if (Core.AOS) + public override List BuyInfo { get; } = new InternalBuyInfo(); + + public class InternalBuyInfo : List { - Add(new GenericBuyInfo(typeof(BoneHarvester), 35, 20, 0x26BB, 0)); - Add(new GenericBuyInfo(typeof(CrescentBlade), 37, 20, 0x26C1, 0)); - Add(new GenericBuyInfo(typeof(DoubleBladedStaff), 35, 20, 0x26BF, 0)); - Add(new GenericBuyInfo(typeof(Lance), 34, 20, 0x26C0, 0)); - Add(new GenericBuyInfo(typeof(Pike), 39, 20, 0x26BE, 0)); - Add(new GenericBuyInfo(typeof(Scythe), 39, 20, 0x26BA, 0)); + public InternalBuyInfo() + { + Add(new GenericBuyInfo(typeof(Cutlass), 24, 20, 0x1441, 0)); + Add(new GenericBuyInfo(typeof(Katana), 33, 20, 0x13FF, 0)); + Add(new GenericBuyInfo(typeof(Kryss), 32, 20, 0x1401, 0)); + Add(new GenericBuyInfo(typeof(Broadsword), 35, 20, 0xF5E, 0)); + Add(new GenericBuyInfo(typeof(Longsword), 55, 20, 0xF61, 0)); + Add(new GenericBuyInfo(typeof(ThinLongsword), 27, 20, 0x13B8, 0)); + Add(new GenericBuyInfo(typeof(VikingSword), 55, 20, 0x13B9, 0)); + Add(new GenericBuyInfo(typeof(Scimitar), 36, 20, 0x13B6, 0)); + + if (Core.AOS) + { + Add(new GenericBuyInfo(typeof(BoneHarvester), 35, 20, 0x26BB, 0)); + Add(new GenericBuyInfo(typeof(CrescentBlade), 37, 20, 0x26C1, 0)); + Add(new GenericBuyInfo(typeof(DoubleBladedStaff), 35, 20, 0x26BF, 0)); + Add(new GenericBuyInfo(typeof(Lance), 34, 20, 0x26C0, 0)); + Add(new GenericBuyInfo(typeof(Pike), 39, 20, 0x26BE, 0)); + Add(new GenericBuyInfo(typeof(Scythe), 39, 20, 0x26BA, 0)); + } + } } - } - } - public class InternalSellInfo : GenericSellInfo - { - public InternalSellInfo() - { - Add(typeof(Broadsword), 17); - Add(typeof(Cutlass), 12); - Add(typeof(Katana), 16); - Add(typeof(Kryss), 16); - Add(typeof(Longsword), 27); - Add(typeof(Scimitar), 18); - Add(typeof(ThinLongsword), 13); - Add(typeof(VikingSword), 27); - - if (Core.AOS) + public class InternalSellInfo : GenericSellInfo { - Add(typeof(Scythe), 19); - Add(typeof(BoneHarvester), 17); - Add(typeof(Scepter), 18); - Add(typeof(BladedStaff), 16); - Add(typeof(Pike), 19); - Add(typeof(DoubleBladedStaff), 17); - Add(typeof(Lance), 17); - Add(typeof(CrescentBlade), 18); + public InternalSellInfo() + { + Add(typeof(Broadsword), 17); + Add(typeof(Cutlass), 12); + Add(typeof(Katana), 16); + Add(typeof(Kryss), 16); + Add(typeof(Longsword), 27); + Add(typeof(Scimitar), 18); + Add(typeof(ThinLongsword), 13); + Add(typeof(VikingSword), 27); + + if (Core.AOS) + { + Add(typeof(Scythe), 19); + Add(typeof(BoneHarvester), 17); + Add(typeof(Scepter), 18); + Add(typeof(BladedStaff), 16); + Add(typeof(Pike), 19); + Add(typeof(DoubleBladedStaff), 17); + Add(typeof(Lance), 17); + Add(typeof(CrescentBlade), 18); + } + } } - } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Mobiles/Vendors/VendorInventory.cs b/Projects/UOContent/Mobiles/Vendors/VendorInventory.cs index 6e9f380cf..8cbc37910 100644 --- a/Projects/UOContent/Mobiles/Vendors/VendorInventory.cs +++ b/Projects/UOContent/Mobiles/Vendors/VendorInventory.cs @@ -4,133 +4,133 @@ using Server.Multis; namespace Server.Mobiles { - public class VendorInventory - { - public static readonly TimeSpan GracePeriod = TimeSpan.FromDays(7.0); - - private readonly Timer m_ExpireTimer; - - public VendorInventory(BaseHouse house, Mobile owner, string vendorName, string shopName) + public class VendorInventory { - House = house; - Owner = owner; - VendorName = vendorName; - ShopName = shopName; + public static readonly TimeSpan GracePeriod = TimeSpan.FromDays(7.0); - Items = new List(); + private readonly Timer m_ExpireTimer; - ExpireTime = DateTime.UtcNow + GracePeriod; - m_ExpireTimer = new ExpireTimer(this, GracePeriod); - m_ExpireTimer.Start(); - } - - public VendorInventory(BaseHouse house, IGenericReader reader) - { - House = house; - - int version = reader.ReadEncodedInt(); - - Owner = reader.ReadMobile(); - VendorName = reader.ReadString(); - ShopName = reader.ReadString(); - - Items = reader.ReadStrongItemList(); - Gold = reader.ReadInt(); - - ExpireTime = reader.ReadDeltaTime(); - - if (Items.Count == 0 && Gold == 0) - { - Timer.DelayCall(Delete); - } - else - { - TimeSpan delay = ExpireTime - DateTime.UtcNow; - m_ExpireTimer = new ExpireTimer(this, delay > TimeSpan.Zero ? delay : TimeSpan.Zero); - m_ExpireTimer.Start(); - } - } - - public BaseHouse House { get; set; } - - public string VendorName { get; set; } - - public string ShopName { get; set; } - - public Mobile Owner { get; set; } - - public List Items { get; } - - public int Gold { get; set; } - - public DateTime ExpireTime { get; } - - public void AddItem(Item item) - { - item.Internalize(); - Items.Add(item); - } - - public void Delete() - { - foreach (Item item in Items) item.Delete(); - - Items.Clear(); - Gold = 0; - - House?.VendorInventories.Remove(this); - - m_ExpireTimer.Stop(); - } - - public void Serialize(IGenericWriter writer) - { - writer.WriteEncodedInt(0); // version - - writer.Write(Owner); - writer.Write(VendorName); - writer.Write(ShopName); - - writer.Write(Items, true); - writer.Write(Gold); - - writer.WriteDeltaTime(ExpireTime); - } - - private class ExpireTimer : Timer - { - private readonly VendorInventory m_Inventory; - - public ExpireTimer(VendorInventory inventory, TimeSpan delay) : base(delay) - { - m_Inventory = inventory; - - Priority = TimerPriority.OneMinute; - } - - protected override void OnTick() - { - BaseHouse house = m_Inventory.House; - - if (house != null) + public VendorInventory(BaseHouse house, Mobile owner, string vendorName, string shopName) { - if (m_Inventory.Gold > 0) - { - house.MovingCrate ??= new MovingCrate(house); + House = house; + Owner = owner; + VendorName = vendorName; + ShopName = shopName; - Banker.Deposit(house.MovingCrate, m_Inventory.Gold); - } + Items = new List(); - foreach (Item item in m_Inventory.Items) - if (!item.Deleted) - house.DropToMovingCrate(item); - - m_Inventory.Gold = 0; - m_Inventory.Items.Clear(); + ExpireTime = DateTime.UtcNow + GracePeriod; + m_ExpireTimer = new ExpireTimer(this, GracePeriod); + m_ExpireTimer.Start(); } - m_Inventory.Delete(); - } + public VendorInventory(BaseHouse house, IGenericReader reader) + { + House = house; + + var version = reader.ReadEncodedInt(); + + Owner = reader.ReadMobile(); + VendorName = reader.ReadString(); + ShopName = reader.ReadString(); + + Items = reader.ReadStrongItemList(); + Gold = reader.ReadInt(); + + ExpireTime = reader.ReadDeltaTime(); + + if (Items.Count == 0 && Gold == 0) + { + Timer.DelayCall(Delete); + } + else + { + var delay = ExpireTime - DateTime.UtcNow; + m_ExpireTimer = new ExpireTimer(this, delay > TimeSpan.Zero ? delay : TimeSpan.Zero); + m_ExpireTimer.Start(); + } + } + + public BaseHouse House { get; set; } + + public string VendorName { get; set; } + + public string ShopName { get; set; } + + public Mobile Owner { get; set; } + + public List Items { get; } + + public int Gold { get; set; } + + public DateTime ExpireTime { get; } + + public void AddItem(Item item) + { + item.Internalize(); + Items.Add(item); + } + + public void Delete() + { + foreach (var item in Items) item.Delete(); + + Items.Clear(); + Gold = 0; + + House?.VendorInventories.Remove(this); + + m_ExpireTimer.Stop(); + } + + public void Serialize(IGenericWriter writer) + { + writer.WriteEncodedInt(0); // version + + writer.Write(Owner); + writer.Write(VendorName); + writer.Write(ShopName); + + writer.Write(Items, true); + writer.Write(Gold); + + writer.WriteDeltaTime(ExpireTime); + } + + private class ExpireTimer : Timer + { + private readonly VendorInventory m_Inventory; + + public ExpireTimer(VendorInventory inventory, TimeSpan delay) : base(delay) + { + m_Inventory = inventory; + + Priority = TimerPriority.OneMinute; + } + + protected override void OnTick() + { + var house = m_Inventory.House; + + if (house != null) + { + if (m_Inventory.Gold > 0) + { + house.MovingCrate ??= new MovingCrate(house); + + Banker.Deposit(house.MovingCrate, m_Inventory.Gold); + } + + foreach (var item in m_Inventory.Items) + if (!item.Deleted) + house.DropToMovingCrate(item); + + m_Inventory.Gold = 0; + m_Inventory.Items.Clear(); + } + + m_Inventory.Delete(); + } + } } - } } diff --git a/Projects/UOContent/Multis/BaseHouse.cs b/Projects/UOContent/Multis/BaseHouse.cs index 87eacee8e..07b78c04c 100644 --- a/Projects/UOContent/Multis/BaseHouse.cs +++ b/Projects/UOContent/Multis/BaseHouse.cs @@ -16,3677 +16,3726 @@ using Server.Targeting; namespace Server.Multis { - public abstract class BaseHouse : BaseMulti - { - public const int MaxCoOwners = 15; - - public const bool DecayEnabled = true; - - public const int MaximumBarkeepCount = 2; - - private static readonly Dictionary> m_Table = new Dictionary>(); - - private DecayLevel m_LastDecayLevel; - - private Mobile m_Owner; - - private bool m_Public; - - private HouseRegion m_Region; - - private Point3D m_RelativeBanLocation; - private TrashBarrel m_Trash; - - public BaseHouse(int multiID, Mobile owner, int maxLockDown, int maxSecure) : base(multiID) + public abstract class BaseHouse : BaseMulti { - AllHouses.Add(this); + public const int MaxCoOwners = 15; - LastRefreshed = DateTime.UtcNow; + public const bool DecayEnabled = true; - BuiltOn = DateTime.UtcNow; - LastTraded = DateTime.MinValue; + public const int MaximumBarkeepCount = 2; - Doors = new List(); - LockDowns = new List(); - Secures = new List(); - Addons = new List(); + private static readonly Dictionary> m_Table = new Dictionary>(); - CoOwners = new List(); - Friends = new List(); - Bans = new List(); - Access = new List(); + private DecayLevel m_CurrentStage; - VendorRentalContracts = new List(); - InternalizedVendors = new List(); + private DecayLevel m_LastDecayLevel; - m_Owner = owner; + private Mobile m_Owner; - MaxLockDowns = maxLockDown; - MaxSecures = maxSecure; + private bool m_Public; - m_RelativeBanLocation = BaseBanLocation; + private HouseRegion m_Region; - UpdateRegion(); + private Point3D m_RelativeBanLocation; + private TrashBarrel m_Trash; - if (owner != null) - { - if (!m_Table.TryGetValue(owner, out List list)) - m_Table[owner] = list = new List(); - - list.Add(this); - } - - Movable = false; - } - - public BaseHouse(Serial serial) : base(serial) - { - AllHouses.Add(this); - } - - public static bool NewVendorSystem // Is new player vendor system enabled? - => Core.AOS; - - public static int MaxFriends => !Core.AOS ? 50 : 140; - public static int MaxBans => !Core.AOS ? 50 : 140; - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime LastRefreshed { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool RestrictDecay { get; set; } - - public virtual TimeSpan DecayPeriod => TimeSpan.FromDays(5.0); - - public virtual DecayType DecayType - { - get - { - if (RestrictDecay || !DecayEnabled || DecayPeriod == TimeSpan.Zero) - return DecayType.Ageless; - - if (m_Owner == null) - return Core.AOS ? DecayType.Condemned : DecayType.ManualRefresh; - - if (!(m_Owner.Account is Account acct)) - return Core.AOS ? DecayType.Condemned : DecayType.ManualRefresh; - - if (acct.AccessLevel >= AccessLevel.GameMaster) - return DecayType.Ageless; - - for (int i = 0; i < acct.Length; ++i) + public BaseHouse(int multiID, Mobile owner, int maxLockDown, int maxSecure) : base(multiID) { - Mobile mob = acct[i]; + AllHouses.Add(this); - if (mob?.AccessLevel >= AccessLevel.GameMaster) - return DecayType.Ageless; - } + LastRefreshed = DateTime.UtcNow; - if (!Core.AOS) - return DecayType.ManualRefresh; + BuiltOn = DateTime.UtcNow; + LastTraded = DateTime.MinValue; - if (acct.Inactive) - return DecayType.Condemned; + Doors = new List(); + LockDowns = new List(); + Secures = new List(); + Addons = new List(); - List allHouses = new List(); + CoOwners = new List(); + Friends = new List(); + Bans = new List(); + Access = new List(); - for (int i = 0; i < acct.Length; ++i) - { - Mobile mob = acct[i]; + VendorRentalContracts = new List(); + InternalizedVendors = new List(); - if (mob != null) - allHouses.AddRange(GetHouses(mob)); - } + m_Owner = owner; - BaseHouse newest = null; + MaxLockDowns = maxLockDown; + MaxSecures = maxSecure; - for (int i = 0; i < allHouses.Count; ++i) - { - BaseHouse check = allHouses[i]; - - if (newest == null || IsNewer(check, newest)) - newest = check; - } - - if (this == newest) - return DecayType.AutoRefresh; - - return DecayType.ManualRefresh; - } - } - - public virtual bool CanDecay - { - get - { - DecayType type = DecayType; - - return type == DecayType.Condemned || type == DecayType.ManualRefresh; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public virtual DecayLevel DecayLevel - { - get - { - DecayLevel result; - - if (!CanDecay) - { - if (DynamicDecay.Enabled) - ResetDynamicDecay(); - - LastRefreshed = DateTime.UtcNow; - result = DecayLevel.Ageless; - } - else if (DynamicDecay.Enabled) - { - DecayLevel stage = m_CurrentStage; - - if (stage == DecayLevel.Ageless || (DynamicDecay.Decays(stage) && NextDecayStage <= DateTime.UtcNow)) - SetDynamicDecay(++stage); - - if (stage == DecayLevel.Collapsed && (HasRentedVendors || VendorInventories.Count > 0)) - result = DecayLevel.DemolitionPending; - else - result = stage; - } - else - { - result = GetOldDecayLevel(); - } - - if (result != m_LastDecayLevel) - { - m_LastDecayLevel = result; - - if (Sign?.GettingProperties == false) - Sign.InvalidateProperties(); - } - - return result; - } - } - - public virtual TimeSpan RestrictedPlacingTime => TimeSpan.FromHours(1.0); - - [CommandProperty(AccessLevel.GameMaster)] - public virtual double BonusStorageScalar => Core.ML ? 1.2 : 1.0; - - public virtual bool IsAosRules => Core.AOS; - - public virtual bool IsActive => true; - - public bool HasPersonalVendors - { - get - { - foreach (PlayerVendor vendor in PlayerVendors) - if (!(vendor is RentedVendor)) - return true; - - return false; - } - } - - public bool HasRentedVendors - { - get - { - foreach (PlayerVendor vendor in PlayerVendors) - if (vendor is RentedVendor) - return true; - - return false; - } - } - - public bool HasAddonContainers - { - get - { - foreach (Item item in Addons) - if (item is BaseAddonContainer) - return true; - - return false; - } - } - - public static List AllHouses { get; } = new List(); - - public abstract Rectangle2D[] Area { get; } - public abstract Point3D BaseBanLocation { get; } - - public override bool Decays => false; - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Owner - { - get => m_Owner; - set - { - if (m_Owner != null) - { - if (!m_Table.TryGetValue(m_Owner, out List list)) - m_Table[m_Owner] = list = new List(); - - list.Remove(this); - m_Owner.Delta(MobileDelta.Noto); - } - - m_Owner = value; - - if (m_Owner != null) - { - if (!m_Table.TryGetValue(m_Owner, out List list)) - m_Table[m_Owner] = list = new List(); - - list.Add(this); - m_Owner.Delta(MobileDelta.Noto); - } - - Sign?.InvalidateProperties(); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int Visits { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool Public - { - get => m_Public; - set - { - if (m_Public != value) - { - m_Public = value; - - if (!m_Public) // Privatizing the house, change to brass sign - ChangeSignType(0xBD2); - - Sign?.InvalidateProperties(); - } - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxSecures { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D BanLocation - { - get - { - if (m_Region != null) - return m_Region.GoLocation; - - Point3D rel = m_RelativeBanLocation; - return new Point3D(X + rel.X, Y + rel.Y, Z + rel.Z); - } - set => RelativeBanLocation = new Point3D(value.X - X, value.Y - Y, value.Z - Z); - } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D RelativeBanLocation - { - get => m_RelativeBanLocation; - set - { - m_RelativeBanLocation = value; - - if (m_Region != null) - m_Region.GoLocation = new Point3D(X + value.X, Y + value.Y, Z + value.Z); - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public int MaxLockDowns { get; set; } - - public Region Region => m_Region; - public List CoOwners { get; set; } - - public List Friends { get; set; } - - public List Access { get; set; } - - public List Bans { get; set; } - - public List Doors { get; set; } - - public int LockDownCount - { - get - { - int count = 0; - - count += GetLockdowns(); - - if (Secures != null) - for (int i = 0; i < Secures.Count; ++i) - { - SecureInfo info = Secures[i]; - - if (info.Item.Deleted) - continue; - if (info.Item is StrongBox) - count += 1; - else - count += 125; - } - - return count; - } - } - - public int SecureCount - { - get - { - int count = 0; - - if (Secures != null) - for (int i = 0; i < Secures.Count; i++) - { - SecureInfo info = Secures[i]; - - if (info.Item.Deleted) - continue; - if (!(info.Item is StrongBox)) - count += 1; - } - - return count; - } - } - - public List Addons { get; set; } - - public List LockDowns { get; private set; } - - public List Secures { get; private set; } - - public HouseSign Sign { get; set; } - - public List PlayerVendors { get; } = new List(); - - public List PlayerBarkeepers { get; } = new List(); - - public List VendorRentalContracts { get; private set; } - - public List VendorInventories { get; } = new List(); - - public List RelocatedEntities { get; } = new List(); - - public MovingCrate MovingCrate { get; set; } - - public List InternalizedVendors { get; private set; } - - public DateTime BuiltOn { get; set; } - - public DateTime LastTraded { get; set; } - - public virtual HousePlacementEntry ConvertEntry => null; - public virtual int ConvertOffsetX => 0; - public virtual int ConvertOffsetY => 0; - public virtual int ConvertOffsetZ => 0; - - public virtual int DefaultPrice => 0; - - [CommandProperty(AccessLevel.GameMaster)] - public int Price { get; set; } - - public static void Decay_OnTick() - { - for (int i = 0; i < AllHouses.Count; ++i) - AllHouses[i].CheckDecay(); - } - - public bool IsNewer(BaseHouse check, BaseHouse house) - { - DateTime checkTime = check.LastTraded > check.BuiltOn ? check.LastTraded : check.BuiltOn; - DateTime houseTime = house.LastTraded > house.BuiltOn ? house.LastTraded : house.BuiltOn; - - return checkTime > houseTime; - } - - public DecayLevel GetOldDecayLevel() - { - TimeSpan timeAfterRefresh = DateTime.UtcNow - LastRefreshed; - int percent = (int)(timeAfterRefresh.Ticks * 1000 / DecayPeriod.Ticks); - - if (percent >= 1000) // 100.0% - return HasRentedVendors || VendorInventories.Count > 0 ? DecayLevel.DemolitionPending : DecayLevel.Collapsed; - if (percent >= 950) // 95.0% - 99.9% - return DecayLevel.IDOC; - if (percent >= 750) // 75.0% - 94.9% - return DecayLevel.Greatly; - if (percent >= 500) // 50.0% - 74.9% - return DecayLevel.Fairly; - if (percent >= 250) // 25.0% - 49.9% - return DecayLevel.Somewhat; - if (percent >= 005) // 00.5% - 24.9% - return DecayLevel.Slightly; - - return DecayLevel.LikeNew; - } - - public virtual bool RefreshDecay() - { - if (DecayType == DecayType.Condemned) - return false; - - DecayLevel oldLevel = DecayLevel; - - LastRefreshed = DateTime.UtcNow; - - if (DynamicDecay.Enabled) - ResetDynamicDecay(); - - Sign?.InvalidateProperties(); - - return oldLevel > DecayLevel.LikeNew; - } - - public virtual bool CheckDecay() - { - if (!Deleted && DecayLevel == DecayLevel.Collapsed) - { - Timer.DelayCall(Decay_Sandbox); - return true; - } - - return false; - } - - public virtual void KillVendors() - { - foreach (PlayerVendor vendor in PlayerVendors.ToList()) - vendor.Destroy(true); - - foreach (PlayerBarkeeper barkeeper in PlayerBarkeepers.ToList()) - barkeeper.Delete(); - } - - public virtual void Decay_Sandbox() - { - if (Deleted) - return; - - if (Core.ML) - new TempNoHousingRegion(this, null); - - KillVendors(); - Delete(); - } - - public virtual HousePlacementEntry GetAosEntry() => HousePlacementEntry.Find(this); - - public virtual int GetAosMaxSecures() - { - HousePlacementEntry hpe = GetAosEntry(); - - if (hpe == null) - return 0; - - return (int)(hpe.Storage * BonusStorageScalar); - } - - public virtual int GetAosMaxLockdowns() - { - HousePlacementEntry hpe = GetAosEntry(); - - if (hpe == null) - return 0; - - return (int)(hpe.Lockdowns * BonusStorageScalar); - } - - public virtual int GetAosCurSecures(out int fromSecures, out int fromVendors, out int fromLockdowns, - out int fromMovingCrate) - { - fromSecures = 0; - fromVendors = 0; - fromLockdowns = 0; - fromMovingCrate = 0; - - List list = Secures; - - if (list != null) - { - for (int i = 0; i < list.Count; ++i) - { - SecureInfo si = list[i]; - - fromSecures += si.Item.TotalItems; - } - - fromLockdowns += list.Count; - } - - fromLockdowns += GetLockdowns(); - - if (!NewVendorSystem) - foreach (PlayerVendor vendor in PlayerVendors) - if (vendor.Backpack != null) - fromVendors += vendor.Backpack.TotalItems; - - if (MovingCrate != null) - { - fromMovingCrate += MovingCrate.TotalItems; - - foreach (Item item in MovingCrate.Items) - if (item is PackingBox) - fromMovingCrate--; - } - - return fromSecures + fromVendors + fromLockdowns + fromMovingCrate; - } - - public override bool InRange(IPoint2D from, int range) - { - return Region?.Area.Any(rect => - from.X >= rect.Start.X - range && from.Y >= rect.Start.Y - range && from.X < rect.End.X + range && from.Y < rect.End.Y + range) == true; - } - - public virtual int GetNewVendorSystemMaxVendors() - { - HousePlacementEntry hpe = GetAosEntry(); - - if (hpe == null) - return 0; - - return (int)(hpe.Vendors * BonusStorageScalar); - } - - public virtual bool CanPlaceNewVendor() => - !IsAosRules || (!NewVendorSystem - ? CheckAosLockdowns(10) - : PlayerVendors.Count + VendorRentalContracts.Count < GetNewVendorSystemMaxVendors()); - - public virtual bool CanPlaceNewBarkeep() => PlayerBarkeepers.Count < MaximumBarkeepCount; - - public static void IsThereVendor(Point3D location, Map map, out bool vendor, out bool rentalContract) - { - vendor = false; - rentalContract = false; - - IPooledEnumerable eable = map.GetObjectsInRange(location, 0); - - foreach (IEntity entity in eable) - if (Math.Abs(location.Z - entity.Z) <= 16) - { - if (entity is PlayerVendor || entity is PlayerBarkeeper || entity is PlayerVendorPlaceholder) - { - vendor = true; - break; - } - - if (entity is VendorRentalContract) - { - rentalContract = true; - break; - } - } - - eable.Free(); - } - - public List AvailableVendorsFor(Mobile m) => - PlayerVendors.Where(vendor => vendor.CanInteractWith(m, false)).ToList(); - - public bool AreThereAvailableVendorsFor(Mobile m) => - PlayerVendors.Any(vendor => vendor.CanInteractWith(m, false)); - - public void MoveAllToCrate() - { - RelocatedEntities.Clear(); - - MovingCrate?.Hide(); - - if (m_Trash != null) - { - m_Trash.Delete(); - m_Trash = null; - } - - foreach (Item item in LockDowns) - if (!item.Deleted) - { - item.IsLockedDown = false; - item.IsSecure = false; - item.Movable = true; - - if (item.Parent == null) - DropToMovingCrate(item); - } - - LockDowns.Clear(); - - foreach (Item item in VendorRentalContracts) - if (!item.Deleted) - { - item.IsLockedDown = false; - item.IsSecure = false; - item.Movable = true; - - if (item.Parent == null) - DropToMovingCrate(item); - } - - VendorRentalContracts.Clear(); - - foreach (SecureInfo info in Secures) - { - Item item = info.Item; - - if (!item.Deleted) - { - if (item is StrongBox box) - item = box.ConvertToStandardContainer(); - - item.IsLockedDown = false; - item.IsSecure = false; - item.Movable = true; - - if (item.Parent == null) - DropToMovingCrate(item); - } - } - - Secures.Clear(); - - foreach (Item addon in Addons) - if (!addon.Deleted) - { - Item deed = null; - bool retainDeedHue = false; // if the items aren't hued but the deed itself is - int hue = 0; - - BaseAddon ba = addon as BaseAddon; - - if (addon is IAddon baseAddon) - { - deed = baseAddon.Deed; - - // There are things that are IAddon which aren't BaseAddon - if (ba?.RetainDeedHue == true) - { - retainDeedHue = true; - - for (int i = 0; hue == 0 && i < ba.Components.Count; ++i) - { - AddonComponent c = ba.Components[i]; - - if (c.Hue != 0) - hue = c.Hue; - } - } - } - - if (deed != null) - { - if (deed is BaseAddonContainerDeed containerDeed && addon is BaseAddonContainer c) - { - c.DropItemsToGround(); - containerDeed.Resource = c.Resource; - } - else if (deed is BaseAddonDeed addonDeed && ba != null) - { - addonDeed.Resource = ba.Resource; - } - - addon.Delete(); - - if (retainDeedHue) - deed.Hue = hue; - - DropToMovingCrate(deed); - } - else - { - DropToMovingCrate(addon); - } - } - - Addons.Clear(); - - foreach (PlayerVendor mobile in PlayerVendors) - { - mobile.Return(); - mobile.Internalize(); - InternalizedVendors.Add(mobile); - } - - foreach (PlayerBarkeeper mobile in PlayerBarkeepers) - { - mobile.Internalize(); - InternalizedVendors.Add(mobile); - } - } - - public List GetHouseEntities() - { - List list = new List(); - - MovingCrate?.Hide(); - - if (m_Trash != null && m_Trash.Map != Map.Internal) - list.Add(m_Trash); - - list.AddRange(LockDowns.Where(item => item.Parent == null && item.Map != Map.Internal)); - list.AddRange(VendorRentalContracts.Where(item => item.Parent == null && item.Map != Map.Internal)); - list.AddRange(Secures.Select(info => info.Item).Where(item => item.Parent == null && item.Map != Map.Internal)); - list.AddRange(Addons.Where(item => item.Parent == null && item.Map != Map.Internal)); - - foreach (PlayerVendor mobile in PlayerVendors) - { - mobile.Return(); - - if (mobile.Map != Map.Internal) - list.Add(mobile); - } - - list.AddRange(PlayerBarkeepers.Where(mobile => mobile.Map != Map.Internal)); - - return list; - } - - public void RelocateEntities() - { - foreach (IEntity entity in GetHouseEntities()) - { - Point3D relLoc = new Point3D(entity.X - X, entity.Y - Y, entity.Z - Z); - RelocatedEntity relocEntity = new RelocatedEntity(entity, relLoc); - - RelocatedEntities.Add(relocEntity); - - if (entity is Item item) - item.Internalize(); - else if (entity is Mobile mobile) - mobile.Internalize(); - } - } - - public void RestoreRelocatedEntities() - { - foreach (RelocatedEntity relocEntity in RelocatedEntities) - { - Point3D relLoc = relocEntity.RelativeLocation; - Point3D location = new Point3D(relLoc.X + X, relLoc.Y + Y, relLoc.Z + Z); - - IEntity entity = relocEntity.Entity; - if (entity is Item item) - { - if (!item.Deleted) - { - IAddon addon = item as IAddon; - if (addon != null) - { - if (addon.CouldFit(location, Map)) - { - item.MoveToWorld(location, Map); - continue; - } - } - else - { - int height; - bool requireSurface; - if (item is VendorRentalContract) - { - height = 16; - requireSurface = true; - } - else - { - height = item.ItemData.Height; - requireSurface = false; - } - - if (Map.CanFit(location.X, location.Y, location.Z, height, false, false, requireSurface)) - { - item.MoveToWorld(location, Map); - continue; - } - } - - // The item can't fit - - if (item is TrashBarrel) - { - item.Delete(); // Trash barrels don't go to the moving crate - } - else - { - SetLockdown(item, false); - item.IsSecure = false; - item.Movable = true; - - Item relocateItem = item; - - if (item is StrongBox box) - relocateItem = box.ConvertToStandardContainer(); - - if (addon != null) - { - Item deed = addon.Deed; - bool retainDeedHue = false; // if the items aren't hued but the deed itself is - int hue = 0; - - if (item is BaseAddon ba && ba.RetainDeedHue) // There are things that are IAddon which aren't BaseAddon - { - retainDeedHue = true; - - for (int i = 0; hue == 0 && i < ba.Components.Count; ++i) - { - AddonComponent c = ba.Components[i]; - - if (c.Hue != 0) - hue = c.Hue; - } - } - - if (deed != null) - { - if (deed is BaseAddonContainerDeed containerDeed && item is BaseAddonContainer c) - { - c.DropItemsToGround(); - - containerDeed.Resource = c.Resource; - } - else if (deed is BaseAddonDeed addonDeed && item is BaseAddon baseAddon) - addonDeed.Resource = baseAddon.Resource; - - if (retainDeedHue) - deed.Hue = hue; - } - - relocateItem = deed; - item.Delete(); - } - - if (relocateItem != null) - DropToMovingCrate(relocateItem); - } - } - - if (m_Trash == item) - m_Trash = null; - - LockDowns.Remove(item); - if (item is VendorRentalContract contract) - VendorRentalContracts.Remove(contract); - Addons.Remove(item); - for (int i = Secures.Count - 1; i >= 0; i--) - if (Secures[i].Item == item) - Secures.RemoveAt(i); - } - else if (entity is Mobile mobile && !mobile.Deleted) - { - if (Map.CanFit(location, 16, false, false)) - mobile.MoveToWorld(location, Map); - else - InternalizedVendors.Add(mobile); - } - } - - RelocatedEntities.Clear(); - } - - public void DropToMovingCrate(Item item) - { - MovingCrate ??= new MovingCrate(this); - - MovingCrate.DropItem(item); - } - - public List GetItems() - { - if (Map == null || Map == Map.Internal) - return new List(); - - Point2D start = new Point2D(X + Components.Min.X, Y + Components.Min.Y); - Point2D end = new Point2D(X + Components.Max.X + 1, Y + Components.Max.Y + 1); - Rectangle2D rect = new Rectangle2D(start, end); - - IPooledEnumerable eable = Map.GetItemsInBounds(rect); - List list = eable.Where(item => item.Movable && IsInside(item)).ToList(); - - eable.Free(); - - return list; - } - - public List GetMobiles() - { - if (Map == null || Map == Map.Internal) - return new List(); - - List list = new List(); - - foreach (Mobile mobile in Region.GetMobiles()) - if (IsInside(mobile)) - list.Add(mobile); - - return list; - } - - public virtual bool CheckAosLockdowns(int need) => GetAosCurLockdowns() + need <= GetAosMaxLockdowns(); - - public virtual bool CheckAosStorage(int need) => - GetAosCurSecures(out int fromSecures, out int fromVendors, out int fromLockdowns, out int fromMovingCrate) + need <= - GetAosMaxSecures(); - - public static void Configure() - { - LockedDownFlag = 1; - SecureFlag = 2; - - Timer.DelayCall(TimeSpan.FromMinutes(1.0), TimeSpan.FromMinutes(1.0), Decay_OnTick); - } - - public virtual int GetAosCurLockdowns() - { - int v = 0; - - v += GetLockdowns(); - - if (Secures != null) - v += Secures.Count; - - if (!NewVendorSystem) - v += PlayerVendors.Count * 10; - - return v; - } - - public static bool CheckLockedDown(Item item) => FindHouseAt(item)?.HasLockedDownItem(item) == true; - - public static bool CheckSecured(Item item) => FindHouseAt(item)?.HasSecureItem(item) == true; - - public static bool CheckLockedDownOrSecured(Item item) - { - BaseHouse house = FindHouseAt(item); - return house != null && (house.HasSecureItem(item) || house.HasLockedDownItem(item)); - } - - public static List GetHouses(Mobile m) - { - List list = new List(); - - if (m != null) - if (m_Table.TryGetValue(m, out List exists)) - for (int i = 0; i < exists.Count; ++i) - { - BaseHouse house = exists[i]; - - if (house?.Deleted == false && house.Owner == m) - list.Add(house); - } - - return list; - } - - public static bool CheckHold(Mobile m, Container cont, Item item, bool message, bool checkItems, int plusItems, - int plusWeight) - { - BaseHouse house = FindHouseAt(cont); - - if (house?.IsAosRules != true) - return true; - - if (house.HasSecureItem(cont) && !house.CheckAosStorage(1 + item.TotalItems + plusItems)) - { - if (message) - m.SendLocalizedMessage(1061839); // This action would exceed the secure storage limit of the house. - - return false; - } - - return true; - } - - public static bool CheckAccessible(Mobile m, Item item) - { - if (m.AccessLevel >= AccessLevel.GameMaster) - return true; // Staff can access anything - - BaseHouse house = FindHouseAt(item); - - if (house == null) - return true; - - SecureAccessResult res = house.CheckSecureAccess(m, item); - - switch (res) - { - case SecureAccessResult.Insecure: break; - case SecureAccessResult.Accessible: return true; - case SecureAccessResult.Inaccessible: return false; - } - - if (house.HasLockedDownItem(item)) - return house.IsCoOwner(m) && item is Container; - - return true; - } - - public static BaseHouse FindHouseAt(Mobile m) - { - if (m?.Deleted != false) - return null; - - return FindHouseAt(m.Location, m.Map, 16); - } - - public static BaseHouse FindHouseAt(Item item) => - item?.Deleted != false ? null : - FindHouseAt(item.GetWorldLocation(), item.Map, item.ItemData.Height); - - public static BaseHouse FindHouseAt(Point3D loc, Map map, int height) - { - if (map == null || map == Map.Internal) - return null; - - Sector sector = map.GetSector(loc); - - for (int i = 0; i < sector.Multis.Count; ++i) - if (sector.Multis[i] is BaseHouse house && house.IsInside(loc, height)) - return house; - - return null; - } - - public bool IsInside(Mobile m) => m?.Deleted == false && m.Map == Map && IsInside(m.Location, 16); - - public bool IsInside(Item item) => item?.Deleted == false && item.Map == Map && IsInside(item.Location, item.ItemData.Height); - - public bool CheckAccessibility(Item item, Mobile from) - { - SecureAccessResult res = CheckSecureAccess(from, item); - - switch (res) - { - case SecureAccessResult.Insecure: break; - case SecureAccessResult.Accessible: return true; - case SecureAccessResult.Inaccessible: return false; - } - - if (!HasLockedDownItem(item)) - return true; - if (from.AccessLevel >= AccessLevel.GameMaster) - return true; - if (item is Runebook) - return true; - if (item is ISecurable securable) - return HasSecureAccess(from, securable.Level); - if (item is Container) - return IsCoOwner(from); - if (item.Stackable) - return true; - if (item is BaseLight) - return IsFriend(from); - if (item is PotionKeg) - return IsFriend(from); - if (item is Dices) - return true; - if (item is RecallRune) - return true; - if (item is TreasureMap) - return true; - if (item is Clock) - return true; - if (item is BaseInstrument) - return true; - if (item is Dyes) - return true; - if (item is VendorRentalContract) - return true; - if (item is RewardBrazier) - return true; - - return false; - } - - public virtual bool IsInside(Point3D p, int height) - { - if (Deleted) - return false; - - MultiComponentList mcl = Components; - - int x = p.X - (X + mcl.Min.X); - int y = p.Y - (Y + mcl.Min.Y); - - if (x < 0 || x >= mcl.Width || y < 0 || y >= mcl.Height) - return false; - - if (this is HouseFoundation && y < mcl.Height - 1 && p.Z >= Z) - return true; - - StaticTile[] tiles = mcl.Tiles[x][y]; - - for (int j = 0; j < tiles.Length; ++j) - { - StaticTile tile = tiles[j]; - int id = tile.ID & TileData.MaxItemValue; - ItemData data = TileData.ItemTable[id]; - - // Slanted roofs do not count; they overhang blocking south and east sides of the multi - if ((data.Flags & TileFlag.Roof) != 0) - continue; - - // Signs and signposts are not considered part of the multi - if ((id >= 0xB95 && id <= 0xC0E) || (id >= 0xC43 && id <= 0xC44)) - continue; - - int tileZ = tile.Z + Z; - - if (p.Z == tileZ || p.Z + height > tileZ) - return true; - } - - return false; - } - - public SecureAccessResult CheckSecureAccess(Mobile m, Item item) - { - if (Secures == null || !(item is Container)) - return SecureAccessResult.Insecure; - - for (int i = 0; i < Secures.Count; ++i) - { - SecureInfo info = Secures[i]; - - if (info.Item == item) - return HasSecureAccess(m, info.Level) ? SecureAccessResult.Accessible : SecureAccessResult.Inaccessible; - } - - return SecureAccessResult.Insecure; - } - - public override void OnMapChange() - { - if (LockDowns == null) - return; - - UpdateRegion(); - - if (Sign?.Deleted == false) - Sign.Map = Map; - - if (Doors != null) - foreach (BaseDoor item in Doors) - item.Map = Map; - - foreach (IEntity entity in GetHouseEntities()) - if (entity is Item item) - item.Map = Map; - else if (entity is Mobile mobile) - mobile.Map = Map; - } - - public virtual void ChangeSignType(int itemID) - { - if (Sign != null) - Sign.ItemID = itemID; - } - - public virtual void UpdateRegion() - { - m_Region?.Unregister(); - - if (Map != null) - { - m_Region = new HouseRegion(this); - m_Region.Register(); - } - else - { - m_Region = null; - } - } - - public override void OnLocationChange(Point3D oldLocation) - { - if (LockDowns == null) - return; - - int x = Location.X - oldLocation.X; - int y = Location.Y - oldLocation.Y; - int z = Location.Z - oldLocation.Z; - - if (Sign?.Deleted == false) - Sign.Location = new Point3D(Sign.X + x, Sign.Y + y, Sign.Z + z); - - UpdateRegion(); - - if (Doors != null) - foreach (BaseDoor item in Doors) - if (!item.Deleted) - item.Location = new Point3D(item.X + x, item.Y + y, item.Z + z); - - foreach (IEntity entity in GetHouseEntities()) - { - Point3D newLocation = new Point3D(entity.X + x, entity.Y + y, entity.Z + z); - - if (entity is Item item) - item.Location = newLocation; - else if (entity is Mobile mobile) - mobile.Location = newLocation; - } - } - - public BaseDoor AddEastDoor(int x, int y, int z) => AddEastDoor(true, x, y, z); - - public BaseDoor AddEastDoor(bool wood, int x, int y, int z) - { - BaseDoor door = MakeDoor(wood, DoorFacing.SouthCW); - - AddDoor(door, x, y, z); - - return door; - } - - public BaseDoor AddSouthDoor(int x, int y, int z) => AddSouthDoor(true, x, y, z); - - public BaseDoor AddSouthDoor(bool wood, int x, int y, int z) - { - BaseDoor door = MakeDoor(wood, DoorFacing.WestCW); - - AddDoor(door, x, y, z); - - return door; - } - - public BaseDoor AddEastDoor(int x, int y, int z, uint k) => AddEastDoor(true, x, y, z, k); - - public BaseDoor AddEastDoor(bool wood, int x, int y, int z, uint k) - { - BaseDoor door = MakeDoor(wood, DoorFacing.SouthCW); - - door.Locked = true; - door.KeyValue = k; - - AddDoor(door, x, y, z); - - return door; - } - - public BaseDoor AddSouthDoor(int x, int y, int z, uint k) => AddSouthDoor(true, x, y, z, k); - - public BaseDoor AddSouthDoor(bool wood, int x, int y, int z, uint k) - { - BaseDoor door = MakeDoor(wood, DoorFacing.WestCW); - - door.Locked = true; - door.KeyValue = k; - - AddDoor(door, x, y, z); - - return door; - } - - public BaseDoor[] AddSouthDoors(int x, int y, int z, uint k) => AddSouthDoors(true, x, y, z, k); - - public BaseDoor[] AddSouthDoors(bool wood, int x, int y, int z, uint k) - { - BaseDoor westDoor = MakeDoor(wood, DoorFacing.WestCW); - BaseDoor eastDoor = MakeDoor(wood, DoorFacing.EastCCW); - - westDoor.Locked = true; - eastDoor.Locked = true; - - westDoor.KeyValue = k; - eastDoor.KeyValue = k; - - westDoor.Link = eastDoor; - eastDoor.Link = westDoor; - - AddDoor(westDoor, x, y, z); - AddDoor(eastDoor, x + 1, y, z); - - return new[] { westDoor, eastDoor }; - } - - protected BaseDoor AddDoor(int itemID, int xOffset, int yOffset, int zOffset) => - AddDoor(null, itemID, xOffset, yOffset, zOffset); - - protected BaseDoor AddDoor(Mobile from, int itemID, int xOffset, int yOffset, int zOffset) - { - BaseDoor door = null; - - if (itemID >= 0x675 && itemID < 0x6F5) - { - int type = (itemID - 0x675) / 16; - DoorFacing facing = (DoorFacing)((itemID - 0x675) / 2 % 8); - - door = type switch - { - 0 => new GenericHouseDoor(facing, 0x675, 0xEC, 0xF3), - 1 => new GenericHouseDoor(facing, 0x685, 0xEC, 0xF3), - 2 => new GenericHouseDoor(facing, 0x695, 0xEB, 0xF2), - 3 => new GenericHouseDoor(facing, 0x6A5, 0xEA, 0xF1), - 4 => new GenericHouseDoor(facing, 0x6B5, 0xEA, 0xF1), - 5 => new GenericHouseDoor(facing, 0x6C5, 0xEC, 0xF3), - 6 => new GenericHouseDoor(facing, 0x6D5, 0xEA, 0xF1), - 7 => new GenericHouseDoor(facing, 0x6E5, 0xEA, 0xF1), - _ => null - }; - } - else if (itemID >= 0x314 && itemID < 0x364) - { - int type = (itemID - 0x314) / 16; - DoorFacing facing = (DoorFacing)((itemID - 0x314) / 2 % 8); - door = new GenericHouseDoor(facing, 0x314 + (type * 16), 0xED, 0xF4); - } - else if (itemID >= 0x824 && itemID < 0x834) - { - DoorFacing facing = (DoorFacing)((itemID - 0x824) / 2 % 8); - door = new GenericHouseDoor(facing, 0x824, 0xEC, 0xF3); - } - else if (itemID >= 0x839 && itemID < 0x849) - { - DoorFacing facing = (DoorFacing)((itemID - 0x839) / 2 % 8); - door = new GenericHouseDoor(facing, 0x839, 0xEB, 0xF2); - } - else if (itemID >= 0x84C && itemID < 0x85C) - { - DoorFacing facing = (DoorFacing)((itemID - 0x84C) / 2 % 8); - door = new GenericHouseDoor(facing, 0x84C, 0xEC, 0xF3); - } - else if (itemID >= 0x866 && itemID < 0x876) - { - DoorFacing facing = (DoorFacing)((itemID - 0x866) / 2 % 8); - door = new GenericHouseDoor(facing, 0x866, 0xEB, 0xF2); - } - else if (itemID >= 0xE8 && itemID < 0xF8) - { - DoorFacing facing = (DoorFacing)((itemID - 0xE8) / 2 % 8); - door = new GenericHouseDoor(facing, 0xE8, 0xED, 0xF4); - } - else if (itemID >= 0x1FED && itemID < 0x1FFD) - { - DoorFacing facing = (DoorFacing)((itemID - 0x1FED) / 2 % 8); - door = new GenericHouseDoor(facing, 0x1FED, 0xEC, 0xF3); - } - else if (itemID >= 0x241F && itemID < 0x2421) - { - // DoorFacing facing = (DoorFacing)(((itemID - 0x241F) / 2) % 8); - door = new GenericHouseDoor(DoorFacing.NorthCCW, 0x2415, -1, -1); - } - else if (itemID >= 0x2423 && itemID < 0x2425) - { - // DoorFacing facing = (DoorFacing)(((itemID - 0x241F) / 2) % 8); - // This one and the above one are 'special' cases, ie: OSI had the ItemID pattern discombobulated for these - door = new GenericHouseDoor(DoorFacing.WestCW, 0x2423, -1, -1); - } - else if (itemID >= 0x2A05 && itemID < 0x2A1D) - { - DoorFacing facing = (DoorFacing)(((itemID - 0x2A05) / 2 % 4) + 8); - - int sound = (itemID >= 0x2A0D && itemID < 0x2a15) ? 0x539 : -1; - - door = new GenericHouseDoor(facing, 0x29F5 + (8 * ((itemID - 0x2A05) / 8)), sound, sound); - } - else if (itemID == 0x2D46) - { - door = new GenericHouseDoor(DoorFacing.NorthCW, 0x2D46, 0xEA, 0xF1, false); - } - else if (itemID == 0x2D48 || itemID == 0x2FE2) - { - door = new GenericHouseDoor(DoorFacing.SouthCCW, itemID, 0xEA, 0xF1, false); - } - else if (itemID >= 0x2D63 && itemID < 0x2D70) - { - int mod = (itemID - 0x2D63) / 2 % 2; - DoorFacing facing = (mod == 0) ? DoorFacing.SouthCCW : DoorFacing.WestCCW; - - int type = (itemID - 0x2D63) / 4; - - door = new GenericHouseDoor(facing, 0x2D63 + 4 * type + mod * 2, 0xEA, 0xF1, false); - } - else if (itemID == 0x2FE4 || itemID == 0x31AE) - { - door = new GenericHouseDoor(DoorFacing.WestCCW, itemID, 0xEA, 0xF1, false); - } - else if (itemID >= 0x319C && itemID < 0x31AE) - { - // special case for 0x31aa <-> 0x31a8 (a9) - int mod = (itemID - 0x319C) / 2 % 2; - - var facing = itemID switch - { - 0x31AA => (mod == 0) ? DoorFacing.NorthCW : DoorFacing.EastCW, - 0x31A8 => (mod == 0) ? DoorFacing.NorthCW : DoorFacing.EastCW, - _ => (mod == 0) ? DoorFacing.EastCW : DoorFacing.NorthCW - }; - - int type = (itemID - 0x319C) / 4; - - door = new GenericHouseDoor(facing, 0x319C + 4 * type + mod * 2, 0xEA, 0xF1, false); - } - else if (itemID >= 0x367B && itemID < 0x369B) - { - int type = (itemID - 0x367B) / 16; - DoorFacing facing = (DoorFacing)((itemID - 0x367B) / 2 % 8); - - door = type switch - { - 0 => new GenericHouseDoor(facing, 0x367B, 0xED, 0xF4), - 1 => new GenericHouseDoor(facing, 0x368B, 0xEC, 0x3E7), - _ => null - }; - } - else if (itemID >= 0x409B && itemID < 0x40A3) - { - door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x409B), itemID, 0xEA, 0xF1, false); - } - else if (itemID >= 0x410C && itemID < 0x4114) - { - door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x410C), itemID, 0xEA, 0xF1, false); - } - else if (itemID >= 0x41C2 && itemID < 0x41CA) - { - door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x41C2), itemID, 0xEA, 0xF1, false); - } - else if (itemID >= 0x41CF && itemID < 0x41D7) - { - door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x41CF), itemID, 0xEA, 0xF1, false); - } - else if (itemID >= 0x436E && itemID < 0x437E) - { - /* These ones had to be different... - * Offset 0 2 4 6 8 10 12 14 - * DoorFacing 2 3 2 3 6 7 6 7 - */ - int offset = itemID - 0x436E; - DoorFacing facing = (DoorFacing)((offset / 2 + 2 * ((1 + offset / 4) % 2)) % 8); - door = new GenericHouseDoor(facing, itemID, 0xEA, 0xF1, false); - } - else if (itemID >= 0x46DD && itemID < 0x46E5) - { - door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x46DD), itemID, 0xEB, 0xF2, false); - } - else if (itemID >= 0x4D22 && itemID < 0x4D2A) - { - door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x4D22), itemID, 0xEA, 0xF1, false); - } - else if (itemID >= 0x50C8 && itemID < 0x50D0) - { - door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x50C8), itemID, 0xEA, 0xF1, false); - } - else if (itemID >= 0x50D0 && itemID < 0x50D8) - { - door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x50D0), itemID, 0xEA, 0xF1, false); - } - else if (itemID >= 0x5142 && itemID < 0x514A) - { - door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x5142), itemID, 0xF0, 0xEF, false); - } - else if (itemID >= 0x9AD7 && itemID <= 0x9AE6) - { - int type = (itemID - 0x9AD7) / 16; - DoorFacing facing = (DoorFacing)((itemID - 0x9AD7) / 2 % 8); - door = new GenericHouseDoor(facing, 0x9AD7 + (type * 16), 0xED, 0xF4); - } - else if (itemID >= 0x9B3C && itemID <= 0x9B4B) - { - int type = (itemID - 0x9B3C) / 16; - DoorFacing facing = (DoorFacing)((itemID - 0x9B3C) / 2 % 8); - door = new GenericHouseDoor(facing, 0x9B3C + (type * 16), 0xED, 0xF4); - } - - if (door != null) - { - if (from != null) door.KeyValue = CreateKeys(from); - - AddDoor(door, xOffset, yOffset, zOffset); - } - else - { - Console.WriteLine("BaseHouse: Door ItemID {0} not supported.", itemID); - } - - return door; - } - - /* Offset 0 2 4 6 - * DoorFacing 2 3 6 7 - */ - private static DoorFacing GetSADoorFacing(int offset) => (DoorFacing)((offset / 2 + 2 * (1 + offset / 4)) % 8); - - public uint CreateKeys(Mobile m) - { - uint value = Key.RandomValue(); - - if (!IsAosRules) - { - Key packKey = new Key(KeyType.Gold); - Key bankKey = new Key(KeyType.Gold); - - packKey.KeyValue = value; - bankKey.KeyValue = value; - - packKey.LootType = LootType.Newbied; - bankKey.LootType = LootType.Newbied; - - BankBox box = m.BankBox; - - if (!box.TryDropItem(m, bankKey, false)) - bankKey.Delete(); - - m.AddToBackpack(packKey); - } - - return value; - } - - public BaseDoor[] AddSouthDoors(int x, int y, int z) => AddSouthDoors(true, x, y, z, false); - - public BaseDoor[] AddSouthDoors(bool wood, int x, int y, int z, bool inv) - { - BaseDoor westDoor = MakeDoor(wood, inv ? DoorFacing.WestCCW : DoorFacing.WestCW); - BaseDoor eastDoor = MakeDoor(wood, inv ? DoorFacing.EastCW : DoorFacing.EastCCW); - - westDoor.Link = eastDoor; - eastDoor.Link = westDoor; - - AddDoor(westDoor, x, y, z); - AddDoor(eastDoor, x + 1, y, z); - - return new[] { westDoor, eastDoor }; - } - - public BaseDoor MakeDoor(bool wood, DoorFacing facing) - { - if (wood) - return new DarkWoodHouseDoor(facing); - return new MetalHouseDoor(facing); - } - - public void AddDoor(BaseDoor door, int xoff, int yoff, int zoff) - { - door.MoveToWorld(new Point3D(xoff + X, yoff + Y, zoff + Z), Map); - Doors.Add(door); - } - - public void AddTrashBarrel(Mobile from) - { - if (!IsActive) - return; - - for (int i = 0; Doors != null && i < Doors.Count; ++i) - { - BaseDoor door = Doors[i]; - Point3D p = door.Location; - - if (door.Open) - p = new Point3D(p.X - door.Offset.X, p.Y - door.Offset.Y, p.Z - door.Offset.Z); - - if (from.Z + 16 >= p.Z && p.Z + 16 >= from.Z) - if (from.InRange(p, 1)) - { - from.SendLocalizedMessage(502120); // You cannot place a trash barrel near a door or near steps. - return; - } - } - - if (m_Trash?.Deleted != false) - { - m_Trash = new TrashBarrel { Movable = false }; - m_Trash.MoveToWorld(from.Location, from.Map); - - /* You have a new trash barrel. - * Three minutes after you put something in the barrel, the trash will be emptied. - * Be forewarned, this is permanent! - */ - from.SendLocalizedMessage(502121); - } - else - { - from.SendLocalizedMessage(502117); // You already have a trash barrel! - } - } - - public void SetSign(int xoff, int yoff, int zoff) - { - Sign = new HouseSign(this); - Sign.MoveToWorld(new Point3D(X + xoff, Y + yoff, Z + zoff), Map); - } - - private void SetLockdown(Item i, bool locked, bool checkContains = false) - { - if (LockDowns == null) - return; - - if (i is BaseAddonContainer) - i.Movable = false; - else - i.Movable = !locked; - - i.IsLockedDown = locked; - - if (locked) - { - if (i is VendorRentalContract contract) - { - if (!VendorRentalContracts.Contains(contract)) - VendorRentalContracts.Add(contract); - } - else - { - if (!checkContains || !LockDowns.Contains(i)) - LockDowns.Add(i); - } - } - else - { - if (i is VendorRentalContract contract) - VendorRentalContracts.Remove(contract); - LockDowns.Remove(i); - } - - if (!locked) - i.SetLastMoved(); - - if (i is Container && (!locked || !(i is BaseBoard || i is Aquarium || i is FishBowl))) - foreach (Item c in i.Items) - SetLockdown(c, locked, checkContains); - } - - public bool LockDown(Mobile m, Item item) => LockDown(m, item, true); - - public bool LockDown(Mobile m, Item item, bool checkIsInside) - { - if (!IsCoOwner(m) || !IsActive) - return false; - - if (item is BaseAddonContainer || (item.Movable && !HasSecureItem(item))) - { - int amt = 1 + item.TotalItems; - - Item rootItem = item.RootParent as Item; - Item parentItem = item.Parent as Item; - - if (checkIsInside && item.RootParent is Mobile) - { - m.SendLocalizedMessage(1005525); // That is not in your house - } - else if (checkIsInside && !IsInside(item.GetWorldLocation(), item.ItemData.Height)) - { - m.SendLocalizedMessage(1005525); // That is not in your house - } - else if (Ethic.IsImbued(item)) - { - m.SendLocalizedMessage(1005377); // You cannot lock that down - } - else if (HasSecureItem(rootItem)) - { - m.SendLocalizedMessage(501737); // You need not lock down items in a secure container. - } - else if (parentItem != null && !HasLockedDownItem(parentItem)) - { - m.SendLocalizedMessage(501736); // You must lockdown the container first! - } - else if (!(item is VendorRentalContract) && (IsAosRules - ? !CheckAosLockdowns(amt) || !CheckAosStorage(amt) - : LockDownCount + amt > MaxLockDowns)) - { - m.SendLocalizedMessage(1005379); // That would exceed the maximum lock down limit for this house - } - else - { - SetLockdown(item, true); - return true; - } - } - else if (LockDowns.IndexOf(item) != -1) - { - m.LocalOverheadMessage(MessageType.Regular, 0x3E9, 1005526); // That is already locked down - return true; - } - else if (item is HouseSign || item is Static) - { - m.LocalOverheadMessage(MessageType.Regular, 0x3E9, 1005526); // This is already locked down. - } - else - { - m.SendLocalizedMessage(1005377); // You cannot lock that down - } - - return false; - } - - public bool CheckTransferPosition(Mobile from, Mobile to) - { - bool isValid = true; - Item sign = Sign; - Point3D p = sign?.GetWorldLocation() ?? Point3D.Zero; - - if (from.Map != Map || to.Map != Map) - isValid = false; - else if (sign == null) - isValid = false; - else if (from.Map != sign.Map || to.Map != sign.Map) - isValid = false; - else if (IsInside(from)) - isValid = false; - else if (IsInside(to)) - isValid = false; - else if (!from.InRange(p, 2)) - isValid = false; - else if (!to.InRange(p, 2)) - isValid = false; - - if (!isValid) - from.SendLocalizedMessage( - 1062067); // In order to transfer the house, you and the recipient must both be outside the building and within two paces of the house sign. - - return isValid; - } - - public void BeginConfirmTransfer(Mobile from, Mobile to) - { - if (Deleted || !from.CheckAlive() || !IsOwner(from)) - return; - - if (NewVendorSystem && HasPersonalVendors) - { - from.SendLocalizedMessage( - 1062467); // You cannot trade this house while you still have personal vendors inside. - } - else if (DecayLevel == DecayLevel.DemolitionPending) - { - from.SendLocalizedMessage( - 1005321); // This house has been marked for demolition, and it cannot be transferred. - } - else if (from == to) - { - from.SendLocalizedMessage(1005330); // You cannot transfer a house to yourself, silly. - } - else if (to.Player) - { - if (HasAccountHouse(to)) - { - from.SendLocalizedMessage(501388); // You cannot transfer ownership to another house owner or co-owner! - } - else if (CheckTransferPosition(from, to)) - { - from.SendLocalizedMessage(1005326); // Please wait while the other player verifies the transfer. - - if (HasRentedVendors) - { - /* You are about to be traded a home that has active vendor contracts. - * While there are active vendor contracts in this house, you - * cannot demolish OR customize the home. - * When you accept this house, you also accept landlordship for every - * contract vendor in the house. - */ - to.SendGump( - new WarningGump(1060635, 30720, 1062487, 32512, 420, 280, okay => ConfirmTransfer_Callback(to, okay, from))); - } - else - { - to.CloseGump(); - to.SendGump(new HouseTransferGump(from, to, this)); - } - } - } - else - { - from.SendLocalizedMessage(501384); // Only a player can own a house! - } - } - - private void ConfirmTransfer_Callback(Mobile to, bool ok, Mobile from) - { - if (!ok || Deleted || !from.CheckAlive() || !IsOwner(from)) - return; - - if (CheckTransferPosition(from, to)) - { - to.CloseGump(); - to.SendGump(new HouseTransferGump(from, to, this)); - } - } - - public void EndConfirmTransfer(Mobile from, Mobile to) - { - if (Deleted || !from.CheckAlive() || !IsOwner(from)) - return; - - if (NewVendorSystem && HasPersonalVendors) - { - from.SendLocalizedMessage( - 1062467); // You cannot trade this house while you still have personal vendors inside. - } - else if (DecayLevel == DecayLevel.DemolitionPending) - { - from.SendLocalizedMessage( - 1005321); // This house has been marked for demolition, and it cannot be transferred. - } - else if (from == to) - { - from.SendLocalizedMessage(1005330); // You cannot transfer a house to yourself, silly. - } - else if (to.Player) - { - if (HasAccountHouse(to)) - { - from.SendLocalizedMessage(501388); // You cannot transfer ownership to another house owner or co-owner! - } - else if (CheckTransferPosition(from, to)) - { - NetState fromState = from.NetState, toState = to.NetState; - - if (fromState != null && toState != null) - { - if (from.HasTrade) - { - from.SendLocalizedMessage( - 1062071); // You cannot trade a house while you have other trades pending. - } - else if (to.HasTrade) - { - to.SendLocalizedMessage( - 1062071); // You cannot trade a house while you have other trades pending. - } - else if (!to.Alive) - { - // TODO: Check if the message is correct. - from.SendLocalizedMessage(1062069); // You cannot transfer this house to that person. - } - else - { - Container c = fromState.AddTrade(toState); - - c.DropItem(new TransferItem(this)); - } - } - } - } - else - { - from.SendLocalizedMessage(501384); // Only a player can own a house! - } - } - - public void Release(Mobile m, Item item) - { - if (!IsCoOwner(m) || !IsActive) - return; - - if (HasLockedDownItem(item)) - { - item.PublicOverheadMessage(MessageType.Label, 0x3B2, 501657); // [no longer locked down] - SetLockdown(item, false); - // TidyItemList( m_LockDowns ); - - (item as RewardBrazier)?.TurnOff(); - } - else if (HasSecureItem(item)) - { - ReleaseSecure(m, item); - } - else - { - m.LocalOverheadMessage(MessageType.Regular, 0x3E9, 1010416); // This is not locked down or secured. - } - } - - public void AddSecure(Mobile m, Item item) - { - if (Secures == null || !IsOwner(m) || !IsActive) - return; - - if (!IsInside(item)) - { - m.SendLocalizedMessage(1005525); // That is not in your house - } - else if (HasLockedDownItem(item)) - { - m.SendLocalizedMessage(1010550); // This is already locked down and cannot be secured. - } - else if (!(item is Container)) - { - LockDown(m, item); - } - else - { - SecureInfo info = null; - - for (int i = 0; info == null && i < Secures.Count; ++i) - if (Secures[i].Item == item) - info = Secures[i]; - - if (info != null) - { - m.CloseGump(); - m.SendGump(new SetSecureLevelGump(m_Owner, info, this)); - } - else if (item.Parent != null) - { - m.SendLocalizedMessage(1010423); // You cannot secure this, place it on the ground first. - } - // Mondain's Legacy mod - else if (!(item is BaseAddonContainer) && !item.Movable) - { - m.SendLocalizedMessage(1010424); // You cannot secure this. - } - else if (!IsAosRules && SecureCount >= MaxSecures) - { - // The maximum number of secure items has been reached : - m.SendLocalizedMessage(1008142, true, MaxSecures.ToString()); - } - else if (IsAosRules ? !CheckAosLockdowns(1) : LockDownCount + 125 >= MaxLockDowns) - { - m.SendLocalizedMessage(1005379); // That would exceed the maximum lock down limit for this house - } - else if (IsAosRules && !CheckAosStorage(item.TotalItems)) - { - m.SendLocalizedMessage(1061839); // This action would exceed the secure storage limit of the house. - } - else - { - info = new SecureInfo((Container)item, SecureLevel.Owner); - - item.IsLockedDown = false; - item.IsSecure = true; - - Secures.Add(info); - LockDowns.Remove(item); - item.Movable = false; - - m.CloseGump(); - m.SendGump(new SetSecureLevelGump(m_Owner, info, this)); - } - } - } - - public virtual bool IsCombatRestricted(Mobile m) - { - if (m?.Player != true || m.AccessLevel >= AccessLevel.GameMaster || !IsAosRules || (m_Owner != null && m_Owner.AccessLevel >= AccessLevel.GameMaster)) - return false; - - for (int i = 0; i < m.Aggressed.Count; ++i) - { - AggressorInfo info = m.Aggressed[i]; - - if (info.Defender.Player && info.Defender.Alive && - DateTime.UtcNow - info.LastCombatTime < HouseRegion.CombatHeatDelay && - (!(m.Guild is Guild attackerGuild) || !(info.Defender.Guild is Guild defenderGuild) || - (defenderGuild != attackerGuild && !defenderGuild.IsEnemy(attackerGuild)))) - return true; - } - - return false; - } - - public bool HasSecureAccess(Mobile m, SecureLevel level) - { - if (m.AccessLevel >= AccessLevel.GameMaster) - return true; - - if (IsCombatRestricted(m)) - return false; - - return level switch - { - SecureLevel.Owner => IsOwner(m), - SecureLevel.CoOwners => IsCoOwner(m), - SecureLevel.Friends => IsFriend(m), - SecureLevel.Anyone => true, - SecureLevel.Guild => IsGuildMember(m), - _ => false - }; - } - - public void ReleaseSecure(Mobile m, Item item) - { - if (Secures == null || !IsOwner(m) || item is StrongBox || !IsActive) - return; - - for (int i = 0; i < Secures.Count; ++i) - { - SecureInfo info = Secures[i]; - - if (info.Item == item && HasSecureAccess(m, info.Level)) - { - item.IsLockedDown = false; - item.IsSecure = false; - - if (item is BaseAddonContainer) - item.Movable = false; - else - item.Movable = true; - item.SetLastMoved(); - item.PublicOverheadMessage(MessageType.Label, 0x3B2, 501656); // [no longer secure] - Secures.RemoveAt(i); - return; - } - } - - m.SendLocalizedMessage(501717); // This isn't secure... - } - - public void AddStrongBox(Mobile from) - { - if (!IsCoOwner(from) || !IsActive) - return; - - if (from == Owner) - { - from.SendLocalizedMessage(502109); // Owners don't get a strong box - return; - } - - if (IsAosRules ? !CheckAosLockdowns(1) : LockDownCount + 1 > MaxLockDowns) - { - from.SendLocalizedMessage(1005379); // That would exceed the maximum lock down limit for this house - return; - } - - foreach (SecureInfo info in Secures) - { - Container c = info.Item; - - if (!c.Deleted && c is StrongBox box && box.Owner == from) - { - from.SendLocalizedMessage(502112); // You already have a strong box - return; - } - } - - for (int i = 0; Doors != null && i < Doors.Count; ++i) - { - BaseDoor door = Doors[i]; - Point3D p = door.Location; - - if (door.Open) - p = new Point3D(p.X - door.Offset.X, p.Y - door.Offset.Y, p.Z - door.Offset.Z); - - if (from.Z + 16 >= p.Z && p.Z + 16 >= from.Z) - if (from.InRange(p, 1)) - { - from.SendLocalizedMessage(502113); // You cannot place a strongbox near a door or near steps. - return; - } - } - - StrongBox sb = new StrongBox(from, this) { Movable = false, IsLockedDown = false, IsSecure = true }; - Secures.Add(new SecureInfo(sb, SecureLevel.CoOwners)); - sb.MoveToWorld(from.Location, from.Map); - } - - public void Kick(Mobile from, Mobile targ) - { - if (!IsFriend(from) || Friends == null) - return; - - if (targ.AccessLevel > AccessLevel.Player && from.AccessLevel <= targ.AccessLevel) - { - from.SendLocalizedMessage(501346); // Uh oh...a bigger boot may be required! - } - else if (IsFriend(targ) && !Core.ML) - { - from.SendLocalizedMessage(501348); // You cannot eject a friend of the house! - } - else if (targ is PlayerVendor) - { - from.SendLocalizedMessage(501351); // You cannot eject a vendor. - } - else if (!IsInside(targ)) - { - from.SendLocalizedMessage(501352); // You may not eject someone who is not in your house! - } - else if (targ is BaseCreature creature && creature.NoHouseRestrictions) - { - from.SendLocalizedMessage(501347); // You cannot eject that from the house! - } - else - { - targ.MoveToWorld(BanLocation, Map); - - from.SendLocalizedMessage(1042840, targ.Name); // ~1_PLAYER NAME~ has been ejected from this house. - /* You have been ejected from this house. - * If you persist in entering, you may be banned from the house. - */ - targ.SendLocalizedMessage(501341); - } - } - - public void RemoveAccess(Mobile from, Mobile targ) - { - if (!IsFriend(from) || Access == null) - return; - - if (Access.Contains(targ)) - { - Access.Remove(targ); - - if (!HasAccess(targ) && IsInside(targ)) - { - targ.Location = BanLocation; - targ.SendLocalizedMessage(1060734); // Your access to this house has been revoked. - } - - from.SendLocalizedMessage(1050051); // The invitation has been revoked. - } - } - - public void RemoveBan(Mobile from, Mobile targ) - { - if (!IsCoOwner(from) || Bans == null) - return; - - if (Bans.Contains(targ)) - { - Bans.Remove(targ); - - from.SendLocalizedMessage(501297); // The ban is lifted. - } - } - - public void Ban(Mobile from, Mobile targ) - { - if (!IsFriend(from) || Bans == null) - return; - - if (targ.AccessLevel > AccessLevel.Player && from.AccessLevel <= targ.AccessLevel) - { - from.SendLocalizedMessage(501354); // Uh oh...a bigger boot may be required. - } - else if (IsFriend(targ)) - { - from.SendLocalizedMessage(501348); // You cannot eject a friend of the house! - } - else if (targ is PlayerVendor) - { - from.SendLocalizedMessage(501351); // You cannot eject a vendor. - } - else if (Bans.Count >= MaxBans) - { - from.SendLocalizedMessage(501355); // The ban limit for this house has been reached! - } - else if (IsBanned(targ)) - { - from.SendLocalizedMessage(501356); // This person is already banned! - } - else if (!IsInside(targ)) - { - from.SendLocalizedMessage(501352); // You may not eject someone who is not in your house! - } - else if (!Public && IsAosRules) - { - from.SendLocalizedMessage( - 1062521); // You cannot ban someone from a private house. Revoke their access instead. - } - else if (targ is BaseCreature bc && bc.NoHouseRestrictions) - { - from.SendLocalizedMessage(1062040); // You cannot ban that. - } - else - { - Bans.Add(targ); - - from.SendLocalizedMessage(1042839, targ.Name); // ~1_PLAYER_NAME~ has been banned from this house. - targ.SendLocalizedMessage(501340); // You have been banned from this house. - - targ.MoveToWorld(BanLocation, Map); - } - } - - public void GrantAccess(Mobile from, Mobile targ) - { - if (!IsFriend(from) || Access == null) - return; - - if (HasAccess(targ)) - { - from.SendLocalizedMessage(1060729); // That person already has access to this house. - } - else if (!targ.Player) - { - from.SendLocalizedMessage(1060712); // That is not a player. - } - else if (IsBanned(targ)) - { - from.SendLocalizedMessage(501367); // This person is banned! Unban them first. - } - else - { - Access.Add(targ); - - targ.SendLocalizedMessage(1060735); // You have been granted access to this house. - } - } - - public void AddCoOwner(Mobile from, Mobile targ) - { - if (!IsOwner(from) || CoOwners == null || Friends == null) - return; - - if (IsOwner(targ)) - { - from.SendLocalizedMessage(501360); // This person is already the house owner! - } - else if (Friends.Contains(targ)) - { - from.SendLocalizedMessage(501361); // This person is a friend of the house. Remove them first. - } - else if (!targ.Player) - { - from.SendLocalizedMessage(501362); // That can't be a co-owner of the house. - } - else if (!Core.AOS && HasAccountHouse(targ)) - { - from.SendLocalizedMessage(501364); // That person is already a house owner. - } - else if (IsBanned(targ)) - { - from.SendLocalizedMessage(501367); // This person is banned! Unban them first. - } - else if (CoOwners.Count >= MaxCoOwners) - { - from.SendLocalizedMessage(501368); // Your co-owner list is full! - } - else if (CoOwners.Contains(targ)) - { - from.SendLocalizedMessage(501369); // This person is already on your co-owner list! - } - else - { - CoOwners.Add(targ); - - targ.Delta(MobileDelta.Noto); - targ.SendLocalizedMessage(501343); // You have been made a co-owner of this house. - } - } - - public void RemoveCoOwner(Mobile from, Mobile targ) - { - if (!IsOwner(from) || CoOwners == null) - return; - - if (CoOwners.Contains(targ)) - { - CoOwners.Remove(targ); - - targ.Delta(MobileDelta.Noto); - - from.SendLocalizedMessage(501299); // Co-owner removed from list. - targ.SendLocalizedMessage(501300); // You have been removed as a house co-owner. - - foreach (SecureInfo info in Secures) - { - Container c = info.Item; - - if (c is StrongBox box && box.Owner == targ) - { - box.IsLockedDown = false; - box.IsSecure = false; - Secures.Remove(info); - box.Destroy(); - break; - } - } - } - } - - public void AddFriend(Mobile from, Mobile targ) - { - if (!IsCoOwner(from) || Friends == null || CoOwners == null) - return; - - if (IsOwner(targ)) - { - from.SendLocalizedMessage(501370); // This person is already an owner of the house! - } - else if (CoOwners.Contains(targ)) - { - from.SendLocalizedMessage(501369); // This person is already on your co-owner list! - } - else if (!targ.Player) - { - from.SendLocalizedMessage(501371); // That can't be a friend of the house. - } - else if (IsBanned(targ)) - { - from.SendLocalizedMessage(501374); // This person is banned! Unban them first. - } - else if (Friends.Count >= MaxFriends) - { - from.SendLocalizedMessage(501375); // Your friends list is full! - } - else if (Friends.Contains(targ)) - { - from.SendLocalizedMessage(501376); // This person is already on your friends list! - } - else - { - Friends.Add(targ); - - targ.Delta(MobileDelta.Noto); - targ.SendLocalizedMessage(501337); // You have been made a friend of this house. - } - } - - public void RemoveFriend(Mobile from, Mobile targ) - { - if (!IsCoOwner(from) || Friends == null) - return; - - if (Friends.Contains(targ)) - { - Friends.Remove(targ); - - targ.Delta(MobileDelta.Noto); - - from.SendLocalizedMessage(501298); // Friend removed from list. - targ.SendLocalizedMessage(1060751); // You are no longer a friend of this house. - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(15); // version - - if (!DynamicDecay.Enabled) - { - writer.Write(-1); - } - else - { - writer.Write((int)m_CurrentStage); - writer.Write(NextDecayStage); - } - - writer.Write(m_RelativeBanLocation); - - writer.WriteItemList(VendorRentalContracts, true); - writer.WriteMobileList(InternalizedVendors, true); - - writer.WriteEncodedInt(RelocatedEntities.Count); - foreach (RelocatedEntity relEntity in RelocatedEntities) - { - writer.Write(relEntity.RelativeLocation); - - if (relEntity.Entity.Deleted) - writer.Write(Serial.MinusOne); - else - writer.Write(relEntity.Entity.Serial); - } - - writer.WriteEncodedInt(VendorInventories.Count); - for (int i = 0; i < VendorInventories.Count; i++) - { - VendorInventory inventory = VendorInventories[i]; - inventory.Serialize(writer); - } - - writer.Write(LastRefreshed); - writer.Write(RestrictDecay); - - writer.Write(Visits); - - writer.Write(Price); - - writer.WriteMobileList(Access); - - writer.Write(BuiltOn); - writer.Write(LastTraded); - - writer.WriteItemList(Addons, true); - - writer.Write(Secures.Count); - - for (int i = 0; i < Secures.Count; ++i) - Secures[i].Serialize(writer); - - writer.Write(m_Public); - - // writer.Write( BanLocation ); - - writer.Write(m_Owner); - - // Version 5 no longer serializes region coords - /*writer.Write( (int)m_Region.Coords.Count ); - foreach( Rectangle2D rect in m_Region.Coords ) - { - writer.Write( rect ); - }*/ - - writer.WriteMobileList(CoOwners, true); - writer.WriteMobileList(Friends, true); - writer.WriteMobileList(Bans, true); - - writer.Write(Sign); - writer.Write(m_Trash); - - writer.WriteItemList(Doors, true); - writer.WriteItemList(LockDowns, true); - // writer.WriteItemList( m_Secures, true ); - - writer.Write(MaxLockDowns); - writer.Write(MaxSecures); - - // Items in locked down containers that aren't locked down themselves must decay! - for (int i = 0; i < LockDowns.Count; ++i) - { - Item item = LockDowns[i]; - - if (item is Container cont && !(cont is BaseBoard || cont is Aquarium || cont is FishBowl)) - { - List children = cont.Items; - - for (int j = 0; j < children.Count; ++j) - { - Item child = children[j]; - - if (child.Decays && !child.IsLockedDown && !child.IsSecure && - child.LastMoved + child.DecayTime <= DateTime.UtcNow) - Timer.DelayCall(child.Delete); - } - } - } - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - int count; - bool loadedDynamicDecay = false; - - switch (version) - { - case 15: - { - int stage = reader.ReadInt(); - - if (stage != -1) - { - m_CurrentStage = (DecayLevel)stage; - NextDecayStage = reader.ReadDateTime(); - loadedDynamicDecay = true; - } - - goto case 14; - } - case 14: - { - m_RelativeBanLocation = reader.ReadPoint3D(); - goto case 13; - } - case 13: // removed ban location serialization - case 12: - { - VendorRentalContracts = reader.ReadStrongItemList(); - InternalizedVendors = reader.ReadStrongMobileList(); - - int relocatedCount = reader.ReadEncodedInt(); - for (int i = 0; i < relocatedCount; i++) - { - Point3D relLocation = reader.ReadPoint3D(); - IEntity entity = World.FindEntity(reader.ReadUInt()); - - if (entity != null) - RelocatedEntities.Add(new RelocatedEntity(entity, relLocation)); - } - - int inventoryCount = reader.ReadEncodedInt(); - for (int i = 0; i < inventoryCount; i++) - { - VendorInventory inventory = new VendorInventory(this, reader); - VendorInventories.Add(inventory); - } - - goto case 11; - } - case 11: - { - LastRefreshed = reader.ReadDateTime(); - RestrictDecay = reader.ReadBool(); - goto case 10; - } - case 10: // just a signal for updates - case 9: - { - Visits = reader.ReadInt(); - goto case 8; - } - case 8: - { - Price = reader.ReadInt(); - goto case 7; - } - case 7: - { - Access = reader.ReadStrongMobileList(); - goto case 6; - } - case 6: - { - BuiltOn = reader.ReadDateTime(); - LastTraded = reader.ReadDateTime(); - goto case 5; - } - case 5: // just removed fields - case 4: - { - Addons = reader.ReadStrongItemList(); - goto case 3; - } - case 3: - { - count = reader.ReadInt(); - Secures = new List(count); - - for (int i = 0; i < count; ++i) - { - SecureInfo info = new SecureInfo(reader); - - if (info.Item != null) - { - info.Item.IsSecure = true; - Secures.Add(info); - } - } - - goto case 2; - } - case 2: - { - m_Public = reader.ReadBool(); - goto case 1; - } - case 1: - { - if (version < 13) - reader.ReadPoint3D(); // house ban location - goto case 0; - } - case 0: - { - if (version < 14) - m_RelativeBanLocation = BaseBanLocation; - - if (version < 12) - { - VendorRentalContracts = new List(); - InternalizedVendors = new List(); - } - - if (version < 4) - Addons = new List(); - - if (version < 7) - Access = new List(); - - if (version < 8) - Price = DefaultPrice; - - m_Owner = reader.ReadMobile(); - - if (version < 5) - { - count = reader.ReadInt(); - - for (int i = 0; i < count; i++) - reader.ReadRect2D(); - } + m_RelativeBanLocation = BaseBanLocation; UpdateRegion(); - CoOwners = reader.ReadStrongMobileList(); - Friends = reader.ReadStrongMobileList(); - Bans = reader.ReadStrongMobileList(); - - Sign = reader.ReadItem() as HouseSign; - m_Trash = reader.ReadItem() as TrashBarrel; - - Doors = reader.ReadStrongItemList(); - LockDowns = reader.ReadStrongItemList(); - - for (int i = 0; i < LockDowns.Count; ++i) - LockDowns[i].IsLockedDown = true; - - for (int i = 0; i < VendorRentalContracts.Count; ++i) - VendorRentalContracts[i].IsLockedDown = true; - - if (version < 3) + if (owner != null) { - List items = reader.ReadStrongItemList(); - Secures = new List(items.Count); + if (!m_Table.TryGetValue(owner, out var list)) + m_Table[owner] = list = new List(); - for (int i = 0; i < items.Count; ++i) - if (items[i] is Container c) + list.Add(this); + } + + Movable = false; + } + + public BaseHouse(Serial serial) : base(serial) + { + AllHouses.Add(this); + } + + public static bool NewVendorSystem // Is new player vendor system enabled? + => Core.AOS; + + public static int MaxFriends => !Core.AOS ? 50 : 140; + public static int MaxBans => !Core.AOS ? 50 : 140; + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime LastRefreshed { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool RestrictDecay { get; set; } + + public virtual TimeSpan DecayPeriod => TimeSpan.FromDays(5.0); + + public virtual DecayType DecayType + { + get + { + if (RestrictDecay || !DecayEnabled || DecayPeriod == TimeSpan.Zero) + return DecayType.Ageless; + + if (m_Owner == null) + return Core.AOS ? DecayType.Condemned : DecayType.ManualRefresh; + + if (!(m_Owner.Account is Account acct)) + return Core.AOS ? DecayType.Condemned : DecayType.ManualRefresh; + + if (acct.AccessLevel >= AccessLevel.GameMaster) + return DecayType.Ageless; + + for (var i = 0; i < acct.Length; ++i) { - c.IsSecure = true; - Secures.Add(new SecureInfo(c, SecureLevel.CoOwners)); + var mob = acct[i]; + + if (mob?.AccessLevel >= AccessLevel.GameMaster) + return DecayType.Ageless; + } + + if (!Core.AOS) + return DecayType.ManualRefresh; + + if (acct.Inactive) + return DecayType.Condemned; + + var allHouses = new List(); + + for (var i = 0; i < acct.Length; ++i) + { + var mob = acct[i]; + + if (mob != null) + allHouses.AddRange(GetHouses(mob)); + } + + BaseHouse newest = null; + + for (var i = 0; i < allHouses.Count; ++i) + { + var check = allHouses[i]; + + if (newest == null || IsNewer(check, newest)) + newest = check; + } + + if (this == newest) + return DecayType.AutoRefresh; + + return DecayType.ManualRefresh; + } + } + + public virtual bool CanDecay + { + get + { + var type = DecayType; + + return type == DecayType.Condemned || type == DecayType.ManualRefresh; + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public virtual DecayLevel DecayLevel + { + get + { + DecayLevel result; + + if (!CanDecay) + { + if (DynamicDecay.Enabled) + ResetDynamicDecay(); + + LastRefreshed = DateTime.UtcNow; + result = DecayLevel.Ageless; + } + else if (DynamicDecay.Enabled) + { + var stage = m_CurrentStage; + + if (stage == DecayLevel.Ageless || DynamicDecay.Decays(stage) && NextDecayStage <= DateTime.UtcNow) + SetDynamicDecay(++stage); + + if (stage == DecayLevel.Collapsed && (HasRentedVendors || VendorInventories.Count > 0)) + result = DecayLevel.DemolitionPending; + else + result = stage; + } + else + { + result = GetOldDecayLevel(); + } + + if (result != m_LastDecayLevel) + { + m_LastDecayLevel = result; + + if (Sign?.GettingProperties == false) + Sign.InvalidateProperties(); + } + + return result; + } + } + + public virtual TimeSpan RestrictedPlacingTime => TimeSpan.FromHours(1.0); + + [CommandProperty(AccessLevel.GameMaster)] + public virtual double BonusStorageScalar => Core.ML ? 1.2 : 1.0; + + public virtual bool IsAosRules => Core.AOS; + + public virtual bool IsActive => true; + + public bool HasPersonalVendors + { + get + { + foreach (var vendor in PlayerVendors) + if (!(vendor is RentedVendor)) + return true; + + return false; + } + } + + public bool HasRentedVendors + { + get + { + foreach (var vendor in PlayerVendors) + if (vendor is RentedVendor) + return true; + + return false; + } + } + + public bool HasAddonContainers + { + get + { + foreach (var item in Addons) + if (item is BaseAddonContainer) + return true; + + return false; + } + } + + public static List AllHouses { get; } = new List(); + + public abstract Rectangle2D[] Area { get; } + public abstract Point3D BaseBanLocation { get; } + + public override bool Decays => false; + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Owner + { + get => m_Owner; + set + { + if (m_Owner != null) + { + if (!m_Table.TryGetValue(m_Owner, out var list)) + m_Table[m_Owner] = list = new List(); + + list.Remove(this); + m_Owner.Delta(MobileDelta.Noto); + } + + m_Owner = value; + + if (m_Owner != null) + { + if (!m_Table.TryGetValue(m_Owner, out var list)) + m_Table[m_Owner] = list = new List(); + + list.Add(this); + m_Owner.Delta(MobileDelta.Noto); + } + + Sign?.InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int Visits { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool Public + { + get => m_Public; + set + { + if (m_Public != value) + { + m_Public = value; + + if (!m_Public) // Privatizing the house, change to brass sign + ChangeSignType(0xBD2); + + Sign?.InvalidateProperties(); + } + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxSecures { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D BanLocation + { + get + { + if (m_Region != null) + return m_Region.GoLocation; + + var rel = m_RelativeBanLocation; + return new Point3D(X + rel.X, Y + rel.Y, Z + rel.Z); + } + set => RelativeBanLocation = new Point3D(value.X - X, value.Y - Y, value.Z - Z); + } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D RelativeBanLocation + { + get => m_RelativeBanLocation; + set + { + m_RelativeBanLocation = value; + + if (m_Region != null) + m_Region.GoLocation = new Point3D(X + value.X, Y + value.Y, Z + value.Z); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public int MaxLockDowns { get; set; } + + public Region Region => m_Region; + public List CoOwners { get; set; } + + public List Friends { get; set; } + + public List Access { get; set; } + + public List Bans { get; set; } + + public List Doors { get; set; } + + public int LockDownCount + { + get + { + var count = 0; + + count += GetLockdowns(); + + if (Secures != null) + for (var i = 0; i < Secures.Count; ++i) + { + var info = Secures[i]; + + if (info.Item.Deleted) + continue; + if (info.Item is StrongBox) + count += 1; + else + count += 125; + } + + return count; + } + } + + public int SecureCount + { + get + { + var count = 0; + + if (Secures != null) + for (var i = 0; i < Secures.Count; i++) + { + var info = Secures[i]; + + if (info.Item.Deleted) + continue; + if (!(info.Item is StrongBox)) + count += 1; + } + + return count; + } + } + + public List Addons { get; set; } + + public List LockDowns { get; private set; } + + public List Secures { get; private set; } + + public HouseSign Sign { get; set; } + + public List PlayerVendors { get; } = new List(); + + public List PlayerBarkeepers { get; } = new List(); + + public List VendorRentalContracts { get; private set; } + + public List VendorInventories { get; } = new List(); + + public List RelocatedEntities { get; } = new List(); + + public MovingCrate MovingCrate { get; set; } + + public List InternalizedVendors { get; private set; } + + public DateTime BuiltOn { get; set; } + + public DateTime LastTraded { get; set; } + + public virtual HousePlacementEntry ConvertEntry => null; + public virtual int ConvertOffsetX => 0; + public virtual int ConvertOffsetY => 0; + public virtual int ConvertOffsetZ => 0; + + public virtual int DefaultPrice => 0; + + [CommandProperty(AccessLevel.GameMaster)] + public int Price { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime NextDecayStage { get; set; } + + public static void Decay_OnTick() + { + for (var i = 0; i < AllHouses.Count; ++i) + AllHouses[i].CheckDecay(); + } + + public bool IsNewer(BaseHouse check, BaseHouse house) + { + var checkTime = check.LastTraded > check.BuiltOn ? check.LastTraded : check.BuiltOn; + var houseTime = house.LastTraded > house.BuiltOn ? house.LastTraded : house.BuiltOn; + + return checkTime > houseTime; + } + + public DecayLevel GetOldDecayLevel() + { + var timeAfterRefresh = DateTime.UtcNow - LastRefreshed; + var percent = (int)(timeAfterRefresh.Ticks * 1000 / DecayPeriod.Ticks); + + if (percent >= 1000) // 100.0% + return HasRentedVendors || VendorInventories.Count > 0 ? DecayLevel.DemolitionPending : DecayLevel.Collapsed; + if (percent >= 950) // 95.0% - 99.9% + return DecayLevel.IDOC; + if (percent >= 750) // 75.0% - 94.9% + return DecayLevel.Greatly; + if (percent >= 500) // 50.0% - 74.9% + return DecayLevel.Fairly; + if (percent >= 250) // 25.0% - 49.9% + return DecayLevel.Somewhat; + if (percent >= 005) // 00.5% - 24.9% + return DecayLevel.Slightly; + + return DecayLevel.LikeNew; + } + + public virtual bool RefreshDecay() + { + if (DecayType == DecayType.Condemned) + return false; + + var oldLevel = DecayLevel; + + LastRefreshed = DateTime.UtcNow; + + if (DynamicDecay.Enabled) + ResetDynamicDecay(); + + Sign?.InvalidateProperties(); + + return oldLevel > DecayLevel.LikeNew; + } + + public virtual bool CheckDecay() + { + if (!Deleted && DecayLevel == DecayLevel.Collapsed) + { + Timer.DelayCall(Decay_Sandbox); + return true; + } + + return false; + } + + public virtual void KillVendors() + { + foreach (var vendor in PlayerVendors.ToList()) + vendor.Destroy(true); + + foreach (var barkeeper in PlayerBarkeepers.ToList()) + barkeeper.Delete(); + } + + public virtual void Decay_Sandbox() + { + if (Deleted) + return; + + if (Core.ML) + new TempNoHousingRegion(this, null); + + KillVendors(); + Delete(); + } + + public virtual HousePlacementEntry GetAosEntry() => HousePlacementEntry.Find(this); + + public virtual int GetAosMaxSecures() + { + var hpe = GetAosEntry(); + + if (hpe == null) + return 0; + + return (int)(hpe.Storage * BonusStorageScalar); + } + + public virtual int GetAosMaxLockdowns() + { + var hpe = GetAosEntry(); + + if (hpe == null) + return 0; + + return (int)(hpe.Lockdowns * BonusStorageScalar); + } + + public virtual int GetAosCurSecures( + out int fromSecures, out int fromVendors, out int fromLockdowns, + out int fromMovingCrate + ) + { + fromSecures = 0; + fromVendors = 0; + fromLockdowns = 0; + fromMovingCrate = 0; + + var list = Secures; + + if (list != null) + { + for (var i = 0; i < list.Count; ++i) + { + var si = list[i]; + + fromSecures += si.Item.TotalItems; + } + + fromLockdowns += list.Count; + } + + fromLockdowns += GetLockdowns(); + + if (!NewVendorSystem) + foreach (var vendor in PlayerVendors) + if (vendor.Backpack != null) + fromVendors += vendor.Backpack.TotalItems; + + if (MovingCrate != null) + { + fromMovingCrate += MovingCrate.TotalItems; + + foreach (var item in MovingCrate.Items) + if (item is PackingBox) + fromMovingCrate--; + } + + return fromSecures + fromVendors + fromLockdowns + fromMovingCrate; + } + + public override bool InRange(IPoint2D from, int range) + { + return Region?.Area.Any( + rect => + from.X >= rect.Start.X - range && from.Y >= rect.Start.Y - range && from.X < rect.End.X + range && + from.Y < rect.End.Y + range + ) == true; + } + + public virtual int GetNewVendorSystemMaxVendors() + { + var hpe = GetAosEntry(); + + if (hpe == null) + return 0; + + return (int)(hpe.Vendors * BonusStorageScalar); + } + + public virtual bool CanPlaceNewVendor() => + !IsAosRules || (!NewVendorSystem + ? CheckAosLockdowns(10) + : PlayerVendors.Count + VendorRentalContracts.Count < GetNewVendorSystemMaxVendors()); + + public virtual bool CanPlaceNewBarkeep() => PlayerBarkeepers.Count < MaximumBarkeepCount; + + public static void IsThereVendor(Point3D location, Map map, out bool vendor, out bool rentalContract) + { + vendor = false; + rentalContract = false; + + var eable = map.GetObjectsInRange(location, 0); + + foreach (var entity in eable) + if (Math.Abs(location.Z - entity.Z) <= 16) + { + if (entity is PlayerVendor || entity is PlayerBarkeeper || entity is PlayerVendorPlaceholder) + { + vendor = true; + break; + } + + if (entity is VendorRentalContract) + { + rentalContract = true; + break; + } + } + + eable.Free(); + } + + public List AvailableVendorsFor(Mobile m) => + PlayerVendors.Where(vendor => vendor.CanInteractWith(m, false)).ToList(); + + public bool AreThereAvailableVendorsFor(Mobile m) => + PlayerVendors.Any(vendor => vendor.CanInteractWith(m, false)); + + public void MoveAllToCrate() + { + RelocatedEntities.Clear(); + + MovingCrate?.Hide(); + + if (m_Trash != null) + { + m_Trash.Delete(); + m_Trash = null; + } + + foreach (var item in LockDowns) + if (!item.Deleted) + { + item.IsLockedDown = false; + item.IsSecure = false; + item.Movable = true; + + if (item.Parent == null) + DropToMovingCrate(item); + } + + LockDowns.Clear(); + + foreach (Item item in VendorRentalContracts) + if (!item.Deleted) + { + item.IsLockedDown = false; + item.IsSecure = false; + item.Movable = true; + + if (item.Parent == null) + DropToMovingCrate(item); + } + + VendorRentalContracts.Clear(); + + foreach (var info in Secures) + { + Item item = info.Item; + + if (!item.Deleted) + { + if (item is StrongBox box) + item = box.ConvertToStandardContainer(); + + item.IsLockedDown = false; + item.IsSecure = false; + item.Movable = true; + + if (item.Parent == null) + DropToMovingCrate(item); } } - MaxLockDowns = reader.ReadInt(); - MaxSecures = reader.ReadInt(); + Secures.Clear(); - if ((Map == null || Map == Map.Internal) && Location == Point3D.Zero) - Delete(); + foreach (var addon in Addons) + if (!addon.Deleted) + { + Item deed = null; + var retainDeedHue = false; // if the items aren't hued but the deed itself is + var hue = 0; + + var ba = addon as BaseAddon; + + if (addon is IAddon baseAddon) + { + deed = baseAddon.Deed; + + // There are things that are IAddon which aren't BaseAddon + if (ba?.RetainDeedHue == true) + { + retainDeedHue = true; + + for (var i = 0; hue == 0 && i < ba.Components.Count; ++i) + { + var c = ba.Components[i]; + + if (c.Hue != 0) + hue = c.Hue; + } + } + } + + if (deed != null) + { + if (deed is BaseAddonContainerDeed containerDeed && addon is BaseAddonContainer c) + { + c.DropItemsToGround(); + containerDeed.Resource = c.Resource; + } + else if (deed is BaseAddonDeed addonDeed && ba != null) + { + addonDeed.Resource = ba.Resource; + } + + addon.Delete(); + + if (retainDeedHue) + deed.Hue = hue; + + DropToMovingCrate(deed); + } + else + { + DropToMovingCrate(addon); + } + } + + Addons.Clear(); + + foreach (var mobile in PlayerVendors) + { + mobile.Return(); + mobile.Internalize(); + InternalizedVendors.Add(mobile); + } + + foreach (var mobile in PlayerBarkeepers) + { + mobile.Internalize(); + InternalizedVendors.Add(mobile); + } + } + + public List GetHouseEntities() + { + var list = new List(); + + MovingCrate?.Hide(); + + if (m_Trash != null && m_Trash.Map != Map.Internal) + list.Add(m_Trash); + + list.AddRange(LockDowns.Where(item => item.Parent == null && item.Map != Map.Internal)); + list.AddRange(VendorRentalContracts.Where(item => item.Parent == null && item.Map != Map.Internal)); + list.AddRange(Secures.Select(info => info.Item).Where(item => item.Parent == null && item.Map != Map.Internal)); + list.AddRange(Addons.Where(item => item.Parent == null && item.Map != Map.Internal)); + + foreach (var mobile in PlayerVendors) + { + mobile.Return(); + + if (mobile.Map != Map.Internal) + list.Add(mobile); + } + + list.AddRange(PlayerBarkeepers.Where(mobile => mobile.Map != Map.Internal)); + + return list; + } + + public void RelocateEntities() + { + foreach (var entity in GetHouseEntities()) + { + var relLoc = new Point3D(entity.X - X, entity.Y - Y, entity.Z - Z); + var relocEntity = new RelocatedEntity(entity, relLoc); + + RelocatedEntities.Add(relocEntity); + + if (entity is Item item) + item.Internalize(); + else if (entity is Mobile mobile) + mobile.Internalize(); + } + } + + public void RestoreRelocatedEntities() + { + foreach (var relocEntity in RelocatedEntities) + { + var relLoc = relocEntity.RelativeLocation; + var location = new Point3D(relLoc.X + X, relLoc.Y + Y, relLoc.Z + Z); + + var entity = relocEntity.Entity; + if (entity is Item item) + { + if (!item.Deleted) + { + var addon = item as IAddon; + if (addon != null) + { + if (addon.CouldFit(location, Map)) + { + item.MoveToWorld(location, Map); + continue; + } + } + else + { + int height; + bool requireSurface; + if (item is VendorRentalContract) + { + height = 16; + requireSurface = true; + } + else + { + height = item.ItemData.Height; + requireSurface = false; + } + + if (Map.CanFit(location.X, location.Y, location.Z, height, false, false, requireSurface)) + { + item.MoveToWorld(location, Map); + continue; + } + } + + // The item can't fit + + if (item is TrashBarrel) + { + item.Delete(); // Trash barrels don't go to the moving crate + } + else + { + SetLockdown(item, false); + item.IsSecure = false; + item.Movable = true; + + var relocateItem = item; + + if (item is StrongBox box) + relocateItem = box.ConvertToStandardContainer(); + + if (addon != null) + { + var deed = addon.Deed; + var retainDeedHue = false; // if the items aren't hued but the deed itself is + var hue = 0; + + if (item is BaseAddon ba && ba.RetainDeedHue + ) // There are things that are IAddon which aren't BaseAddon + { + retainDeedHue = true; + + for (var i = 0; hue == 0 && i < ba.Components.Count; ++i) + { + var c = ba.Components[i]; + + if (c.Hue != 0) + hue = c.Hue; + } + } + + if (deed != null) + { + if (deed is BaseAddonContainerDeed containerDeed && item is BaseAddonContainer c) + { + c.DropItemsToGround(); + + containerDeed.Resource = c.Resource; + } + else if (deed is BaseAddonDeed addonDeed && item is BaseAddon baseAddon) + { + addonDeed.Resource = baseAddon.Resource; + } + + if (retainDeedHue) + deed.Hue = hue; + } + + relocateItem = deed; + item.Delete(); + } + + if (relocateItem != null) + DropToMovingCrate(relocateItem); + } + } + + if (m_Trash == item) + m_Trash = null; + + LockDowns.Remove(item); + if (item is VendorRentalContract contract) + VendorRentalContracts.Remove(contract); + Addons.Remove(item); + for (var i = Secures.Count - 1; i >= 0; i--) + if (Secures[i].Item == item) + Secures.RemoveAt(i); + } + else if (entity is Mobile mobile && !mobile.Deleted) + { + if (Map.CanFit(location, 16, false, false)) + mobile.MoveToWorld(location, Map); + else + InternalizedVendors.Add(mobile); + } + } + + RelocatedEntities.Clear(); + } + + public void DropToMovingCrate(Item item) + { + MovingCrate ??= new MovingCrate(this); + + MovingCrate.DropItem(item); + } + + public List GetItems() + { + if (Map == null || Map == Map.Internal) + return new List(); + + var start = new Point2D(X + Components.Min.X, Y + Components.Min.Y); + var end = new Point2D(X + Components.Max.X + 1, Y + Components.Max.Y + 1); + var rect = new Rectangle2D(start, end); + + var eable = Map.GetItemsInBounds(rect); + var list = eable.Where(item => item.Movable && IsInside(item)).ToList(); + + eable.Free(); + + return list; + } + + public List GetMobiles() + { + if (Map == null || Map == Map.Internal) + return new List(); + + var list = new List(); + + foreach (var mobile in Region.GetMobiles()) + if (IsInside(mobile)) + list.Add(mobile); + + return list; + } + + public virtual bool CheckAosLockdowns(int need) => GetAosCurLockdowns() + need <= GetAosMaxLockdowns(); + + public virtual bool CheckAosStorage(int need) => + GetAosCurSecures( + out var fromSecures, + out var fromVendors, + out var fromLockdowns, + out var fromMovingCrate + ) + need <= + GetAosMaxSecures(); + + public static void Configure() + { + LockedDownFlag = 1; + SecureFlag = 2; + + Timer.DelayCall(TimeSpan.FromMinutes(1.0), TimeSpan.FromMinutes(1.0), Decay_OnTick); + } + + public virtual int GetAosCurLockdowns() + { + var v = 0; + + v += GetLockdowns(); + + if (Secures != null) + v += Secures.Count; + + if (!NewVendorSystem) + v += PlayerVendors.Count * 10; + + return v; + } + + public static bool CheckLockedDown(Item item) => FindHouseAt(item)?.HasLockedDownItem(item) == true; + + public static bool CheckSecured(Item item) => FindHouseAt(item)?.HasSecureItem(item) == true; + + public static bool CheckLockedDownOrSecured(Item item) + { + var house = FindHouseAt(item); + return house != null && (house.HasSecureItem(item) || house.HasLockedDownItem(item)); + } + + public static List GetHouses(Mobile m) + { + var list = new List(); + + if (m != null) + if (m_Table.TryGetValue(m, out var exists)) + for (var i = 0; i < exists.Count; ++i) + { + var house = exists[i]; + + if (house?.Deleted == false && house.Owner == m) + list.Add(house); + } + + return list; + } + + public static bool CheckHold( + Mobile m, Container cont, Item item, bool message, bool checkItems, int plusItems, + int plusWeight + ) + { + var house = FindHouseAt(cont); + + if (house?.IsAosRules != true) + return true; + + if (house.HasSecureItem(cont) && !house.CheckAosStorage(1 + item.TotalItems + plusItems)) + { + if (message) + m.SendLocalizedMessage(1061839); // This action would exceed the secure storage limit of the house. + + return false; + } + + return true; + } + + public static bool CheckAccessible(Mobile m, Item item) + { + if (m.AccessLevel >= AccessLevel.GameMaster) + return true; // Staff can access anything + + var house = FindHouseAt(item); + + if (house == null) + return true; + + var res = house.CheckSecureAccess(m, item); + + switch (res) + { + case SecureAccessResult.Insecure: break; + case SecureAccessResult.Accessible: return true; + case SecureAccessResult.Inaccessible: return false; + } + + if (house.HasLockedDownItem(item)) + return house.IsCoOwner(m) && item is Container; + + return true; + } + + public static BaseHouse FindHouseAt(Mobile m) + { + if (m?.Deleted != false) + return null; + + return FindHouseAt(m.Location, m.Map, 16); + } + + public static BaseHouse FindHouseAt(Item item) => + item?.Deleted != false ? null : FindHouseAt(item.GetWorldLocation(), item.Map, item.ItemData.Height); + + public static BaseHouse FindHouseAt(Point3D loc, Map map, int height) + { + if (map == null || map == Map.Internal) + return null; + + var sector = map.GetSector(loc); + + for (var i = 0; i < sector.Multis.Count; ++i) + if (sector.Multis[i] is BaseHouse house && house.IsInside(loc, height)) + return house; + + return null; + } + + public bool IsInside(Mobile m) => m?.Deleted == false && m.Map == Map && IsInside(m.Location, 16); + + public bool IsInside(Item item) => + item?.Deleted == false && item.Map == Map && IsInside(item.Location, item.ItemData.Height); + + public bool CheckAccessibility(Item item, Mobile from) + { + var res = CheckSecureAccess(from, item); + + switch (res) + { + case SecureAccessResult.Insecure: break; + case SecureAccessResult.Accessible: return true; + case SecureAccessResult.Inaccessible: return false; + } + + if (!HasLockedDownItem(item)) + return true; + if (from.AccessLevel >= AccessLevel.GameMaster) + return true; + if (item is Runebook) + return true; + if (item is ISecurable securable) + return HasSecureAccess(from, securable.Level); + if (item is Container) + return IsCoOwner(from); + if (item.Stackable) + return true; + if (item is BaseLight) + return IsFriend(from); + if (item is PotionKeg) + return IsFriend(from); + if (item is Dices) + return true; + if (item is RecallRune) + return true; + if (item is TreasureMap) + return true; + if (item is Clock) + return true; + if (item is BaseInstrument) + return true; + if (item is Dyes) + return true; + if (item is VendorRentalContract) + return true; + if (item is RewardBrazier) + return true; + + return false; + } + + public virtual bool IsInside(Point3D p, int height) + { + if (Deleted) + return false; + + var mcl = Components; + + var x = p.X - (X + mcl.Min.X); + var y = p.Y - (Y + mcl.Min.Y); + + if (x < 0 || x >= mcl.Width || y < 0 || y >= mcl.Height) + return false; + + if (this is HouseFoundation && y < mcl.Height - 1 && p.Z >= Z) + return true; + + var tiles = mcl.Tiles[x][y]; + + for (var j = 0; j < tiles.Length; ++j) + { + var tile = tiles[j]; + var id = tile.ID & TileData.MaxItemValue; + var data = TileData.ItemTable[id]; + + // Slanted roofs do not count; they overhang blocking south and east sides of the multi + if ((data.Flags & TileFlag.Roof) != 0) + continue; + + // Signs and signposts are not considered part of the multi + if (id >= 0xB95 && id <= 0xC0E || id >= 0xC43 && id <= 0xC44) + continue; + + var tileZ = tile.Z + Z; + + if (p.Z == tileZ || p.Z + height > tileZ) + return true; + } + + return false; + } + + public SecureAccessResult CheckSecureAccess(Mobile m, Item item) + { + if (Secures == null || !(item is Container)) + return SecureAccessResult.Insecure; + + for (var i = 0; i < Secures.Count; ++i) + { + var info = Secures[i]; + + if (info.Item == item) + return HasSecureAccess(m, info.Level) ? SecureAccessResult.Accessible : SecureAccessResult.Inaccessible; + } + + return SecureAccessResult.Insecure; + } + + public override void OnMapChange() + { + if (LockDowns == null) + return; + + UpdateRegion(); + + if (Sign?.Deleted == false) + Sign.Map = Map; + + if (Doors != null) + foreach (var item in Doors) + item.Map = Map; + + foreach (var entity in GetHouseEntities()) + if (entity is Item item) + item.Map = Map; + else if (entity is Mobile mobile) + mobile.Map = Map; + } + + public virtual void ChangeSignType(int itemID) + { + if (Sign != null) + Sign.ItemID = itemID; + } + + public virtual void UpdateRegion() + { + m_Region?.Unregister(); + + if (Map != null) + { + m_Region = new HouseRegion(this); + m_Region.Register(); + } + else + { + m_Region = null; + } + } + + public override void OnLocationChange(Point3D oldLocation) + { + if (LockDowns == null) + return; + + var x = Location.X - oldLocation.X; + var y = Location.Y - oldLocation.Y; + var z = Location.Z - oldLocation.Z; + + if (Sign?.Deleted == false) + Sign.Location = new Point3D(Sign.X + x, Sign.Y + y, Sign.Z + z); + + UpdateRegion(); + + if (Doors != null) + foreach (var item in Doors) + if (!item.Deleted) + item.Location = new Point3D(item.X + x, item.Y + y, item.Z + z); + + foreach (var entity in GetHouseEntities()) + { + var newLocation = new Point3D(entity.X + x, entity.Y + y, entity.Z + z); + + if (entity is Item item) + item.Location = newLocation; + else if (entity is Mobile mobile) + mobile.Location = newLocation; + } + } + + public BaseDoor AddEastDoor(int x, int y, int z) => AddEastDoor(true, x, y, z); + + public BaseDoor AddEastDoor(bool wood, int x, int y, int z) + { + var door = MakeDoor(wood, DoorFacing.SouthCW); + + AddDoor(door, x, y, z); + + return door; + } + + public BaseDoor AddSouthDoor(int x, int y, int z) => AddSouthDoor(true, x, y, z); + + public BaseDoor AddSouthDoor(bool wood, int x, int y, int z) + { + var door = MakeDoor(wood, DoorFacing.WestCW); + + AddDoor(door, x, y, z); + + return door; + } + + public BaseDoor AddEastDoor(int x, int y, int z, uint k) => AddEastDoor(true, x, y, z, k); + + public BaseDoor AddEastDoor(bool wood, int x, int y, int z, uint k) + { + var door = MakeDoor(wood, DoorFacing.SouthCW); + + door.Locked = true; + door.KeyValue = k; + + AddDoor(door, x, y, z); + + return door; + } + + public BaseDoor AddSouthDoor(int x, int y, int z, uint k) => AddSouthDoor(true, x, y, z, k); + + public BaseDoor AddSouthDoor(bool wood, int x, int y, int z, uint k) + { + var door = MakeDoor(wood, DoorFacing.WestCW); + + door.Locked = true; + door.KeyValue = k; + + AddDoor(door, x, y, z); + + return door; + } + + public BaseDoor[] AddSouthDoors(int x, int y, int z, uint k) => AddSouthDoors(true, x, y, z, k); + + public BaseDoor[] AddSouthDoors(bool wood, int x, int y, int z, uint k) + { + var westDoor = MakeDoor(wood, DoorFacing.WestCW); + var eastDoor = MakeDoor(wood, DoorFacing.EastCCW); + + westDoor.Locked = true; + eastDoor.Locked = true; + + westDoor.KeyValue = k; + eastDoor.KeyValue = k; + + westDoor.Link = eastDoor; + eastDoor.Link = westDoor; + + AddDoor(westDoor, x, y, z); + AddDoor(eastDoor, x + 1, y, z); + + return new[] { westDoor, eastDoor }; + } + + protected BaseDoor AddDoor(int itemID, int xOffset, int yOffset, int zOffset) => + AddDoor(null, itemID, xOffset, yOffset, zOffset); + + protected BaseDoor AddDoor(Mobile from, int itemID, int xOffset, int yOffset, int zOffset) + { + BaseDoor door = null; + + if (itemID >= 0x675 && itemID < 0x6F5) + { + var type = (itemID - 0x675) / 16; + var facing = (DoorFacing)((itemID - 0x675) / 2 % 8); + + door = type switch + { + 0 => new GenericHouseDoor(facing, 0x675, 0xEC, 0xF3), + 1 => new GenericHouseDoor(facing, 0x685, 0xEC, 0xF3), + 2 => new GenericHouseDoor(facing, 0x695, 0xEB, 0xF2), + 3 => new GenericHouseDoor(facing, 0x6A5, 0xEA, 0xF1), + 4 => new GenericHouseDoor(facing, 0x6B5, 0xEA, 0xF1), + 5 => new GenericHouseDoor(facing, 0x6C5, 0xEC, 0xF3), + 6 => new GenericHouseDoor(facing, 0x6D5, 0xEA, 0xF1), + 7 => new GenericHouseDoor(facing, 0x6E5, 0xEA, 0xF1), + _ => null + }; + } + else if (itemID >= 0x314 && itemID < 0x364) + { + var type = (itemID - 0x314) / 16; + var facing = (DoorFacing)((itemID - 0x314) / 2 % 8); + door = new GenericHouseDoor(facing, 0x314 + type * 16, 0xED, 0xF4); + } + else if (itemID >= 0x824 && itemID < 0x834) + { + var facing = (DoorFacing)((itemID - 0x824) / 2 % 8); + door = new GenericHouseDoor(facing, 0x824, 0xEC, 0xF3); + } + else if (itemID >= 0x839 && itemID < 0x849) + { + var facing = (DoorFacing)((itemID - 0x839) / 2 % 8); + door = new GenericHouseDoor(facing, 0x839, 0xEB, 0xF2); + } + else if (itemID >= 0x84C && itemID < 0x85C) + { + var facing = (DoorFacing)((itemID - 0x84C) / 2 % 8); + door = new GenericHouseDoor(facing, 0x84C, 0xEC, 0xF3); + } + else if (itemID >= 0x866 && itemID < 0x876) + { + var facing = (DoorFacing)((itemID - 0x866) / 2 % 8); + door = new GenericHouseDoor(facing, 0x866, 0xEB, 0xF2); + } + else if (itemID >= 0xE8 && itemID < 0xF8) + { + var facing = (DoorFacing)((itemID - 0xE8) / 2 % 8); + door = new GenericHouseDoor(facing, 0xE8, 0xED, 0xF4); + } + else if (itemID >= 0x1FED && itemID < 0x1FFD) + { + var facing = (DoorFacing)((itemID - 0x1FED) / 2 % 8); + door = new GenericHouseDoor(facing, 0x1FED, 0xEC, 0xF3); + } + else if (itemID >= 0x241F && itemID < 0x2421) + { + // DoorFacing facing = (DoorFacing)(((itemID - 0x241F) / 2) % 8); + door = new GenericHouseDoor(DoorFacing.NorthCCW, 0x2415, -1, -1); + } + else if (itemID >= 0x2423 && itemID < 0x2425) + { + // DoorFacing facing = (DoorFacing)(((itemID - 0x241F) / 2) % 8); + // This one and the above one are 'special' cases, ie: OSI had the ItemID pattern discombobulated for these + door = new GenericHouseDoor(DoorFacing.WestCW, 0x2423, -1, -1); + } + else if (itemID >= 0x2A05 && itemID < 0x2A1D) + { + var facing = (DoorFacing)((itemID - 0x2A05) / 2 % 4 + 8); + + var sound = itemID >= 0x2A0D && itemID < 0x2a15 ? 0x539 : -1; + + door = new GenericHouseDoor(facing, 0x29F5 + 8 * ((itemID - 0x2A05) / 8), sound, sound); + } + else if (itemID == 0x2D46) + { + door = new GenericHouseDoor(DoorFacing.NorthCW, 0x2D46, 0xEA, 0xF1, false); + } + else if (itemID == 0x2D48 || itemID == 0x2FE2) + { + door = new GenericHouseDoor(DoorFacing.SouthCCW, itemID, 0xEA, 0xF1, false); + } + else if (itemID >= 0x2D63 && itemID < 0x2D70) + { + var mod = (itemID - 0x2D63) / 2 % 2; + var facing = mod == 0 ? DoorFacing.SouthCCW : DoorFacing.WestCCW; + + var type = (itemID - 0x2D63) / 4; + + door = new GenericHouseDoor(facing, 0x2D63 + 4 * type + mod * 2, 0xEA, 0xF1, false); + } + else if (itemID == 0x2FE4 || itemID == 0x31AE) + { + door = new GenericHouseDoor(DoorFacing.WestCCW, itemID, 0xEA, 0xF1, false); + } + else if (itemID >= 0x319C && itemID < 0x31AE) + { + // special case for 0x31aa <-> 0x31a8 (a9) + var mod = (itemID - 0x319C) / 2 % 2; + + var facing = itemID switch + { + 0x31AA => mod == 0 ? DoorFacing.NorthCW : DoorFacing.EastCW, + 0x31A8 => mod == 0 ? DoorFacing.NorthCW : DoorFacing.EastCW, + _ => mod == 0 ? DoorFacing.EastCW : DoorFacing.NorthCW + }; + + var type = (itemID - 0x319C) / 4; + + door = new GenericHouseDoor(facing, 0x319C + 4 * type + mod * 2, 0xEA, 0xF1, false); + } + else if (itemID >= 0x367B && itemID < 0x369B) + { + var type = (itemID - 0x367B) / 16; + var facing = (DoorFacing)((itemID - 0x367B) / 2 % 8); + + door = type switch + { + 0 => new GenericHouseDoor(facing, 0x367B, 0xED, 0xF4), + 1 => new GenericHouseDoor(facing, 0x368B, 0xEC, 0x3E7), + _ => null + }; + } + else if (itemID >= 0x409B && itemID < 0x40A3) + { + door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x409B), itemID, 0xEA, 0xF1, false); + } + else if (itemID >= 0x410C && itemID < 0x4114) + { + door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x410C), itemID, 0xEA, 0xF1, false); + } + else if (itemID >= 0x41C2 && itemID < 0x41CA) + { + door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x41C2), itemID, 0xEA, 0xF1, false); + } + else if (itemID >= 0x41CF && itemID < 0x41D7) + { + door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x41CF), itemID, 0xEA, 0xF1, false); + } + else if (itemID >= 0x436E && itemID < 0x437E) + { + /* These ones had to be different... + * Offset 0 2 4 6 8 10 12 14 + * DoorFacing 2 3 2 3 6 7 6 7 + */ + var offset = itemID - 0x436E; + var facing = (DoorFacing)((offset / 2 + 2 * ((1 + offset / 4) % 2)) % 8); + door = new GenericHouseDoor(facing, itemID, 0xEA, 0xF1, false); + } + else if (itemID >= 0x46DD && itemID < 0x46E5) + { + door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x46DD), itemID, 0xEB, 0xF2, false); + } + else if (itemID >= 0x4D22 && itemID < 0x4D2A) + { + door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x4D22), itemID, 0xEA, 0xF1, false); + } + else if (itemID >= 0x50C8 && itemID < 0x50D0) + { + door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x50C8), itemID, 0xEA, 0xF1, false); + } + else if (itemID >= 0x50D0 && itemID < 0x50D8) + { + door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x50D0), itemID, 0xEA, 0xF1, false); + } + else if (itemID >= 0x5142 && itemID < 0x514A) + { + door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x5142), itemID, 0xF0, 0xEF, false); + } + else if (itemID >= 0x9AD7 && itemID <= 0x9AE6) + { + var type = (itemID - 0x9AD7) / 16; + var facing = (DoorFacing)((itemID - 0x9AD7) / 2 % 8); + door = new GenericHouseDoor(facing, 0x9AD7 + type * 16, 0xED, 0xF4); + } + else if (itemID >= 0x9B3C && itemID <= 0x9B4B) + { + var type = (itemID - 0x9B3C) / 16; + var facing = (DoorFacing)((itemID - 0x9B3C) / 2 % 8); + door = new GenericHouseDoor(facing, 0x9B3C + type * 16, 0xED, 0xF4); + } + + if (door != null) + { + if (from != null) door.KeyValue = CreateKeys(from); + + AddDoor(door, xOffset, yOffset, zOffset); + } + else + { + Console.WriteLine("BaseHouse: Door ItemID {0} not supported.", itemID); + } + + return door; + } + + /* Offset 0 2 4 6 + * DoorFacing 2 3 6 7 + */ + private static DoorFacing GetSADoorFacing(int offset) => (DoorFacing)((offset / 2 + 2 * (1 + offset / 4)) % 8); + + public uint CreateKeys(Mobile m) + { + var value = Key.RandomValue(); + + if (!IsAosRules) + { + var packKey = new Key(KeyType.Gold); + var bankKey = new Key(KeyType.Gold); + + packKey.KeyValue = value; + bankKey.KeyValue = value; + + packKey.LootType = LootType.Newbied; + bankKey.LootType = LootType.Newbied; + + var box = m.BankBox; + + if (!box.TryDropItem(m, bankKey, false)) + bankKey.Delete(); + + m.AddToBackpack(packKey); + } + + return value; + } + + public BaseDoor[] AddSouthDoors(int x, int y, int z) => AddSouthDoors(true, x, y, z, false); + + public BaseDoor[] AddSouthDoors(bool wood, int x, int y, int z, bool inv) + { + var westDoor = MakeDoor(wood, inv ? DoorFacing.WestCCW : DoorFacing.WestCW); + var eastDoor = MakeDoor(wood, inv ? DoorFacing.EastCW : DoorFacing.EastCCW); + + westDoor.Link = eastDoor; + eastDoor.Link = westDoor; + + AddDoor(westDoor, x, y, z); + AddDoor(eastDoor, x + 1, y, z); + + return new[] { westDoor, eastDoor }; + } + + public BaseDoor MakeDoor(bool wood, DoorFacing facing) + { + if (wood) + return new DarkWoodHouseDoor(facing); + return new MetalHouseDoor(facing); + } + + public void AddDoor(BaseDoor door, int xoff, int yoff, int zoff) + { + door.MoveToWorld(new Point3D(xoff + X, yoff + Y, zoff + Z), Map); + Doors.Add(door); + } + + public void AddTrashBarrel(Mobile from) + { + if (!IsActive) + return; + + for (var i = 0; Doors != null && i < Doors.Count; ++i) + { + var door = Doors[i]; + var p = door.Location; + + if (door.Open) + p = new Point3D(p.X - door.Offset.X, p.Y - door.Offset.Y, p.Z - door.Offset.Z); + + if (from.Z + 16 >= p.Z && p.Z + 16 >= from.Z) + if (from.InRange(p, 1)) + { + from.SendLocalizedMessage(502120); // You cannot place a trash barrel near a door or near steps. + return; + } + } + + if (m_Trash?.Deleted != false) + { + m_Trash = new TrashBarrel { Movable = false }; + m_Trash.MoveToWorld(from.Location, from.Map); + + /* You have a new trash barrel. + * Three minutes after you put something in the barrel, the trash will be emptied. + * Be forewarned, this is permanent! + */ + from.SendLocalizedMessage(502121); + } + else + { + from.SendLocalizedMessage(502117); // You already have a trash barrel! + } + } + + public void SetSign(int xoff, int yoff, int zoff) + { + Sign = new HouseSign(this); + Sign.MoveToWorld(new Point3D(X + xoff, Y + yoff, Z + zoff), Map); + } + + private void SetLockdown(Item i, bool locked, bool checkContains = false) + { + if (LockDowns == null) + return; + + if (i is BaseAddonContainer) + i.Movable = false; + else + i.Movable = !locked; + + i.IsLockedDown = locked; + + if (locked) + { + if (i is VendorRentalContract contract) + { + if (!VendorRentalContracts.Contains(contract)) + VendorRentalContracts.Add(contract); + } + else + { + if (!checkContains || !LockDowns.Contains(i)) + LockDowns.Add(i); + } + } + else + { + if (i is VendorRentalContract contract) + VendorRentalContracts.Remove(contract); + LockDowns.Remove(i); + } + + if (!locked) + i.SetLastMoved(); + + if (i is Container && (!locked || !(i is BaseBoard || i is Aquarium || i is FishBowl))) + foreach (var c in i.Items) + SetLockdown(c, locked, checkContains); + } + + public bool LockDown(Mobile m, Item item) => LockDown(m, item, true); + + public bool LockDown(Mobile m, Item item, bool checkIsInside) + { + if (!IsCoOwner(m) || !IsActive) + return false; + + if (item is BaseAddonContainer || item.Movable && !HasSecureItem(item)) + { + var amt = 1 + item.TotalItems; + + var rootItem = item.RootParent as Item; + var parentItem = item.Parent as Item; + + if (checkIsInside && item.RootParent is Mobile) + { + m.SendLocalizedMessage(1005525); // That is not in your house + } + else if (checkIsInside && !IsInside(item.GetWorldLocation(), item.ItemData.Height)) + { + m.SendLocalizedMessage(1005525); // That is not in your house + } + else if (Ethic.IsImbued(item)) + { + m.SendLocalizedMessage(1005377); // You cannot lock that down + } + else if (HasSecureItem(rootItem)) + { + m.SendLocalizedMessage(501737); // You need not lock down items in a secure container. + } + else if (parentItem != null && !HasLockedDownItem(parentItem)) + { + m.SendLocalizedMessage(501736); // You must lockdown the container first! + } + else if (!(item is VendorRentalContract) && (IsAosRules + ? !CheckAosLockdowns(amt) || !CheckAosStorage(amt) + : LockDownCount + amt > MaxLockDowns)) + { + m.SendLocalizedMessage(1005379); // That would exceed the maximum lock down limit for this house + } + else + { + SetLockdown(item, true); + return true; + } + } + else if (LockDowns.IndexOf(item) != -1) + { + m.LocalOverheadMessage(MessageType.Regular, 0x3E9, 1005526); // That is already locked down + return true; + } + else if (item is HouseSign || item is Static) + { + m.LocalOverheadMessage(MessageType.Regular, 0x3E9, 1005526); // This is already locked down. + } + else + { + m.SendLocalizedMessage(1005377); // You cannot lock that down + } + + return false; + } + + public bool CheckTransferPosition(Mobile from, Mobile to) + { + var isValid = true; + Item sign = Sign; + var p = sign?.GetWorldLocation() ?? Point3D.Zero; + + if (from.Map != Map || to.Map != Map) + isValid = false; + else if (sign == null) + isValid = false; + else if (from.Map != sign.Map || to.Map != sign.Map) + isValid = false; + else if (IsInside(from)) + isValid = false; + else if (IsInside(to)) + isValid = false; + else if (!from.InRange(p, 2)) + isValid = false; + else if (!to.InRange(p, 2)) + isValid = false; + + if (!isValid) + from.SendLocalizedMessage( + 1062067 + ); // In order to transfer the house, you and the recipient must both be outside the building and within two paces of the house sign. + + return isValid; + } + + public void BeginConfirmTransfer(Mobile from, Mobile to) + { + if (Deleted || !from.CheckAlive() || !IsOwner(from)) + return; + + if (NewVendorSystem && HasPersonalVendors) + { + from.SendLocalizedMessage( + 1062467 + ); // You cannot trade this house while you still have personal vendors inside. + } + else if (DecayLevel == DecayLevel.DemolitionPending) + { + from.SendLocalizedMessage( + 1005321 + ); // This house has been marked for demolition, and it cannot be transferred. + } + else if (from == to) + { + from.SendLocalizedMessage(1005330); // You cannot transfer a house to yourself, silly. + } + else if (to.Player) + { + if (HasAccountHouse(to)) + { + from.SendLocalizedMessage(501388); // You cannot transfer ownership to another house owner or co-owner! + } + else if (CheckTransferPosition(from, to)) + { + from.SendLocalizedMessage(1005326); // Please wait while the other player verifies the transfer. + + if (HasRentedVendors) + { + /* You are about to be traded a home that has active vendor contracts. + * While there are active vendor contracts in this house, you + * cannot demolish OR customize the home. + * When you accept this house, you also accept landlordship for every + * contract vendor in the house. + */ + to.SendGump( + new WarningGump( + 1060635, + 30720, + 1062487, + 32512, + 420, + 280, + okay => ConfirmTransfer_Callback(to, okay, from) + ) + ); + } + else + { + to.CloseGump(); + to.SendGump(new HouseTransferGump(from, to, this)); + } + } + } + else + { + from.SendLocalizedMessage(501384); // Only a player can own a house! + } + } + + private void ConfirmTransfer_Callback(Mobile to, bool ok, Mobile from) + { + if (!ok || Deleted || !from.CheckAlive() || !IsOwner(from)) + return; + + if (CheckTransferPosition(from, to)) + { + to.CloseGump(); + to.SendGump(new HouseTransferGump(from, to, this)); + } + } + + public void EndConfirmTransfer(Mobile from, Mobile to) + { + if (Deleted || !from.CheckAlive() || !IsOwner(from)) + return; + + if (NewVendorSystem && HasPersonalVendors) + { + from.SendLocalizedMessage( + 1062467 + ); // You cannot trade this house while you still have personal vendors inside. + } + else if (DecayLevel == DecayLevel.DemolitionPending) + { + from.SendLocalizedMessage( + 1005321 + ); // This house has been marked for demolition, and it cannot be transferred. + } + else if (from == to) + { + from.SendLocalizedMessage(1005330); // You cannot transfer a house to yourself, silly. + } + else if (to.Player) + { + if (HasAccountHouse(to)) + { + from.SendLocalizedMessage(501388); // You cannot transfer ownership to another house owner or co-owner! + } + else if (CheckTransferPosition(from, to)) + { + NetState fromState = from.NetState, toState = to.NetState; + + if (fromState != null && toState != null) + { + if (from.HasTrade) + { + from.SendLocalizedMessage( + 1062071 + ); // You cannot trade a house while you have other trades pending. + } + else if (to.HasTrade) + { + to.SendLocalizedMessage( + 1062071 + ); // You cannot trade a house while you have other trades pending. + } + else if (!to.Alive) + { + // TODO: Check if the message is correct. + from.SendLocalizedMessage(1062069); // You cannot transfer this house to that person. + } + else + { + Container c = fromState.AddTrade(toState); + + c.DropItem(new TransferItem(this)); + } + } + } + } + else + { + from.SendLocalizedMessage(501384); // Only a player can own a house! + } + } + + public void Release(Mobile m, Item item) + { + if (!IsCoOwner(m) || !IsActive) + return; + + if (HasLockedDownItem(item)) + { + item.PublicOverheadMessage(MessageType.Label, 0x3B2, 501657); // [no longer locked down] + SetLockdown(item, false); + // TidyItemList( m_LockDowns ); + + (item as RewardBrazier)?.TurnOff(); + } + else if (HasSecureItem(item)) + { + ReleaseSecure(m, item); + } + else + { + m.LocalOverheadMessage(MessageType.Regular, 0x3E9, 1010416); // This is not locked down or secured. + } + } + + public void AddSecure(Mobile m, Item item) + { + if (Secures == null || !IsOwner(m) || !IsActive) + return; + + if (!IsInside(item)) + { + m.SendLocalizedMessage(1005525); // That is not in your house + } + else if (HasLockedDownItem(item)) + { + m.SendLocalizedMessage(1010550); // This is already locked down and cannot be secured. + } + else if (!(item is Container)) + { + LockDown(m, item); + } + else + { + SecureInfo info = null; + + for (var i = 0; info == null && i < Secures.Count; ++i) + if (Secures[i].Item == item) + info = Secures[i]; + + if (info != null) + { + m.CloseGump(); + m.SendGump(new SetSecureLevelGump(m_Owner, info, this)); + } + else if (item.Parent != null) + { + m.SendLocalizedMessage(1010423); // You cannot secure this, place it on the ground first. + } + // Mondain's Legacy mod + else if (!(item is BaseAddonContainer) && !item.Movable) + { + m.SendLocalizedMessage(1010424); // You cannot secure this. + } + else if (!IsAosRules && SecureCount >= MaxSecures) + { + // The maximum number of secure items has been reached : + m.SendLocalizedMessage(1008142, true, MaxSecures.ToString()); + } + else if (IsAosRules ? !CheckAosLockdowns(1) : LockDownCount + 125 >= MaxLockDowns) + { + m.SendLocalizedMessage(1005379); // That would exceed the maximum lock down limit for this house + } + else if (IsAosRules && !CheckAosStorage(item.TotalItems)) + { + m.SendLocalizedMessage(1061839); // This action would exceed the secure storage limit of the house. + } + else + { + info = new SecureInfo((Container)item, SecureLevel.Owner); + + item.IsLockedDown = false; + item.IsSecure = true; + + Secures.Add(info); + LockDowns.Remove(item); + item.Movable = false; + + m.CloseGump(); + m.SendGump(new SetSecureLevelGump(m_Owner, info, this)); + } + } + } + + public virtual bool IsCombatRestricted(Mobile m) + { + if (m?.Player != true || m.AccessLevel >= AccessLevel.GameMaster || !IsAosRules || + m_Owner != null && m_Owner.AccessLevel >= AccessLevel.GameMaster) + return false; + + for (var i = 0; i < m.Aggressed.Count; ++i) + { + var info = m.Aggressed[i]; + + if (info.Defender.Player && info.Defender.Alive && + DateTime.UtcNow - info.LastCombatTime < HouseRegion.CombatHeatDelay && + (!(m.Guild is Guild attackerGuild) || !(info.Defender.Guild is Guild defenderGuild) || + defenderGuild != attackerGuild && !defenderGuild.IsEnemy(attackerGuild))) + return true; + } + + return false; + } + + public bool HasSecureAccess(Mobile m, SecureLevel level) + { + if (m.AccessLevel >= AccessLevel.GameMaster) + return true; + + if (IsCombatRestricted(m)) + return false; + + return level switch + { + SecureLevel.Owner => IsOwner(m), + SecureLevel.CoOwners => IsCoOwner(m), + SecureLevel.Friends => IsFriend(m), + SecureLevel.Anyone => true, + SecureLevel.Guild => IsGuildMember(m), + _ => false + }; + } + + public void ReleaseSecure(Mobile m, Item item) + { + if (Secures == null || !IsOwner(m) || item is StrongBox || !IsActive) + return; + + for (var i = 0; i < Secures.Count; ++i) + { + var info = Secures[i]; + + if (info.Item == item && HasSecureAccess(m, info.Level)) + { + item.IsLockedDown = false; + item.IsSecure = false; + + if (item is BaseAddonContainer) + item.Movable = false; + else + item.Movable = true; + item.SetLastMoved(); + item.PublicOverheadMessage(MessageType.Label, 0x3B2, 501656); // [no longer secure] + Secures.RemoveAt(i); + return; + } + } + + m.SendLocalizedMessage(501717); // This isn't secure... + } + + public void AddStrongBox(Mobile from) + { + if (!IsCoOwner(from) || !IsActive) + return; + + if (from == Owner) + { + from.SendLocalizedMessage(502109); // Owners don't get a strong box + return; + } + + if (IsAosRules ? !CheckAosLockdowns(1) : LockDownCount + 1 > MaxLockDowns) + { + from.SendLocalizedMessage(1005379); // That would exceed the maximum lock down limit for this house + return; + } + + foreach (var info in Secures) + { + var c = info.Item; + + if (!c.Deleted && c is StrongBox box && box.Owner == from) + { + from.SendLocalizedMessage(502112); // You already have a strong box + return; + } + } + + for (var i = 0; Doors != null && i < Doors.Count; ++i) + { + var door = Doors[i]; + var p = door.Location; + + if (door.Open) + p = new Point3D(p.X - door.Offset.X, p.Y - door.Offset.Y, p.Z - door.Offset.Z); + + if (from.Z + 16 >= p.Z && p.Z + 16 >= from.Z) + if (from.InRange(p, 1)) + { + from.SendLocalizedMessage(502113); // You cannot place a strongbox near a door or near steps. + return; + } + } + + var sb = new StrongBox(from, this) { Movable = false, IsLockedDown = false, IsSecure = true }; + Secures.Add(new SecureInfo(sb, SecureLevel.CoOwners)); + sb.MoveToWorld(from.Location, from.Map); + } + + public void Kick(Mobile from, Mobile targ) + { + if (!IsFriend(from) || Friends == null) + return; + + if (targ.AccessLevel > AccessLevel.Player && from.AccessLevel <= targ.AccessLevel) + { + from.SendLocalizedMessage(501346); // Uh oh...a bigger boot may be required! + } + else if (IsFriend(targ) && !Core.ML) + { + from.SendLocalizedMessage(501348); // You cannot eject a friend of the house! + } + else if (targ is PlayerVendor) + { + from.SendLocalizedMessage(501351); // You cannot eject a vendor. + } + else if (!IsInside(targ)) + { + from.SendLocalizedMessage(501352); // You may not eject someone who is not in your house! + } + else if (targ is BaseCreature creature && creature.NoHouseRestrictions) + { + from.SendLocalizedMessage(501347); // You cannot eject that from the house! + } + else + { + targ.MoveToWorld(BanLocation, Map); + + from.SendLocalizedMessage(1042840, targ.Name); // ~1_PLAYER NAME~ has been ejected from this house. + /* You have been ejected from this house. + * If you persist in entering, you may be banned from the house. + */ + targ.SendLocalizedMessage(501341); + } + } + + public void RemoveAccess(Mobile from, Mobile targ) + { + if (!IsFriend(from) || Access == null) + return; + + if (Access.Contains(targ)) + { + Access.Remove(targ); + + if (!HasAccess(targ) && IsInside(targ)) + { + targ.Location = BanLocation; + targ.SendLocalizedMessage(1060734); // Your access to this house has been revoked. + } + + from.SendLocalizedMessage(1050051); // The invitation has been revoked. + } + } + + public void RemoveBan(Mobile from, Mobile targ) + { + if (!IsCoOwner(from) || Bans == null) + return; + + if (Bans.Contains(targ)) + { + Bans.Remove(targ); + + from.SendLocalizedMessage(501297); // The ban is lifted. + } + } + + public void Ban(Mobile from, Mobile targ) + { + if (!IsFriend(from) || Bans == null) + return; + + if (targ.AccessLevel > AccessLevel.Player && from.AccessLevel <= targ.AccessLevel) + { + from.SendLocalizedMessage(501354); // Uh oh...a bigger boot may be required. + } + else if (IsFriend(targ)) + { + from.SendLocalizedMessage(501348); // You cannot eject a friend of the house! + } + else if (targ is PlayerVendor) + { + from.SendLocalizedMessage(501351); // You cannot eject a vendor. + } + else if (Bans.Count >= MaxBans) + { + from.SendLocalizedMessage(501355); // The ban limit for this house has been reached! + } + else if (IsBanned(targ)) + { + from.SendLocalizedMessage(501356); // This person is already banned! + } + else if (!IsInside(targ)) + { + from.SendLocalizedMessage(501352); // You may not eject someone who is not in your house! + } + else if (!Public && IsAosRules) + { + from.SendLocalizedMessage( + 1062521 + ); // You cannot ban someone from a private house. Revoke their access instead. + } + else if (targ is BaseCreature bc && bc.NoHouseRestrictions) + { + from.SendLocalizedMessage(1062040); // You cannot ban that. + } + else + { + Bans.Add(targ); + + from.SendLocalizedMessage(1042839, targ.Name); // ~1_PLAYER_NAME~ has been banned from this house. + targ.SendLocalizedMessage(501340); // You have been banned from this house. + + targ.MoveToWorld(BanLocation, Map); + } + } + + public void GrantAccess(Mobile from, Mobile targ) + { + if (!IsFriend(from) || Access == null) + return; + + if (HasAccess(targ)) + { + from.SendLocalizedMessage(1060729); // That person already has access to this house. + } + else if (!targ.Player) + { + from.SendLocalizedMessage(1060712); // That is not a player. + } + else if (IsBanned(targ)) + { + from.SendLocalizedMessage(501367); // This person is banned! Unban them first. + } + else + { + Access.Add(targ); + + targ.SendLocalizedMessage(1060735); // You have been granted access to this house. + } + } + + public void AddCoOwner(Mobile from, Mobile targ) + { + if (!IsOwner(from) || CoOwners == null || Friends == null) + return; + + if (IsOwner(targ)) + { + from.SendLocalizedMessage(501360); // This person is already the house owner! + } + else if (Friends.Contains(targ)) + { + from.SendLocalizedMessage(501361); // This person is a friend of the house. Remove them first. + } + else if (!targ.Player) + { + from.SendLocalizedMessage(501362); // That can't be a co-owner of the house. + } + else if (!Core.AOS && HasAccountHouse(targ)) + { + from.SendLocalizedMessage(501364); // That person is already a house owner. + } + else if (IsBanned(targ)) + { + from.SendLocalizedMessage(501367); // This person is banned! Unban them first. + } + else if (CoOwners.Count >= MaxCoOwners) + { + from.SendLocalizedMessage(501368); // Your co-owner list is full! + } + else if (CoOwners.Contains(targ)) + { + from.SendLocalizedMessage(501369); // This person is already on your co-owner list! + } + else + { + CoOwners.Add(targ); + + targ.Delta(MobileDelta.Noto); + targ.SendLocalizedMessage(501343); // You have been made a co-owner of this house. + } + } + + public void RemoveCoOwner(Mobile from, Mobile targ) + { + if (!IsOwner(from) || CoOwners == null) + return; + + if (CoOwners.Contains(targ)) + { + CoOwners.Remove(targ); + + targ.Delta(MobileDelta.Noto); + + from.SendLocalizedMessage(501299); // Co-owner removed from list. + targ.SendLocalizedMessage(501300); // You have been removed as a house co-owner. + + foreach (var info in Secures) + { + var c = info.Item; + + if (c is StrongBox box && box.Owner == targ) + { + box.IsLockedDown = false; + box.IsSecure = false; + Secures.Remove(info); + box.Destroy(); + break; + } + } + } + } + + public void AddFriend(Mobile from, Mobile targ) + { + if (!IsCoOwner(from) || Friends == null || CoOwners == null) + return; + + if (IsOwner(targ)) + { + from.SendLocalizedMessage(501370); // This person is already an owner of the house! + } + else if (CoOwners.Contains(targ)) + { + from.SendLocalizedMessage(501369); // This person is already on your co-owner list! + } + else if (!targ.Player) + { + from.SendLocalizedMessage(501371); // That can't be a friend of the house. + } + else if (IsBanned(targ)) + { + from.SendLocalizedMessage(501374); // This person is banned! Unban them first. + } + else if (Friends.Count >= MaxFriends) + { + from.SendLocalizedMessage(501375); // Your friends list is full! + } + else if (Friends.Contains(targ)) + { + from.SendLocalizedMessage(501376); // This person is already on your friends list! + } + else + { + Friends.Add(targ); + + targ.Delta(MobileDelta.Noto); + targ.SendLocalizedMessage(501337); // You have been made a friend of this house. + } + } + + public void RemoveFriend(Mobile from, Mobile targ) + { + if (!IsCoOwner(from) || Friends == null) + return; + + if (Friends.Contains(targ)) + { + Friends.Remove(targ); + + targ.Delta(MobileDelta.Noto); + + from.SendLocalizedMessage(501298); // Friend removed from list. + targ.SendLocalizedMessage(1060751); // You are no longer a friend of this house. + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(15); // version + + if (!DynamicDecay.Enabled) + { + writer.Write(-1); + } + else + { + writer.Write((int)m_CurrentStage); + writer.Write(NextDecayStage); + } + + writer.Write(m_RelativeBanLocation); + + writer.WriteItemList(VendorRentalContracts, true); + writer.WriteMobileList(InternalizedVendors, true); + + writer.WriteEncodedInt(RelocatedEntities.Count); + foreach (var relEntity in RelocatedEntities) + { + writer.Write(relEntity.RelativeLocation); + + if (relEntity.Entity.Deleted) + writer.Write(Serial.MinusOne); + else + writer.Write(relEntity.Entity.Serial); + } + + writer.WriteEncodedInt(VendorInventories.Count); + for (var i = 0; i < VendorInventories.Count; i++) + { + var inventory = VendorInventories[i]; + inventory.Serialize(writer); + } + + writer.Write(LastRefreshed); + writer.Write(RestrictDecay); + + writer.Write(Visits); + + writer.Write(Price); + + writer.WriteMobileList(Access); + + writer.Write(BuiltOn); + writer.Write(LastTraded); + + writer.WriteItemList(Addons, true); + + writer.Write(Secures.Count); + + for (var i = 0; i < Secures.Count; ++i) + Secures[i].Serialize(writer); + + writer.Write(m_Public); + + // writer.Write( BanLocation ); + + writer.Write(m_Owner); + + // Version 5 no longer serializes region coords + /*writer.Write( (int)m_Region.Coords.Count ); + foreach( Rectangle2D rect in m_Region.Coords ) + { + writer.Write( rect ); + }*/ + + writer.WriteMobileList(CoOwners, true); + writer.WriteMobileList(Friends, true); + writer.WriteMobileList(Bans, true); + + writer.Write(Sign); + writer.Write(m_Trash); + + writer.WriteItemList(Doors, true); + writer.WriteItemList(LockDowns, true); + // writer.WriteItemList( m_Secures, true ); + + writer.Write(MaxLockDowns); + writer.Write(MaxSecures); + + // Items in locked down containers that aren't locked down themselves must decay! + for (var i = 0; i < LockDowns.Count; ++i) + { + var item = LockDowns[i]; + + if (item is Container cont && !(cont is BaseBoard || cont is Aquarium || cont is FishBowl)) + { + var children = cont.Items; + + for (var j = 0; j < children.Count; ++j) + { + var child = children[j]; + + if (child.Decays && !child.IsLockedDown && !child.IsSecure && + child.LastMoved + child.DecayTime <= DateTime.UtcNow) + Timer.DelayCall(child.Delete); + } + } + } + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + int count; + var loadedDynamicDecay = false; + + switch (version) + { + case 15: + { + var stage = reader.ReadInt(); + + if (stage != -1) + { + m_CurrentStage = (DecayLevel)stage; + NextDecayStage = reader.ReadDateTime(); + loadedDynamicDecay = true; + } + + goto case 14; + } + case 14: + { + m_RelativeBanLocation = reader.ReadPoint3D(); + goto case 13; + } + case 13: // removed ban location serialization + case 12: + { + VendorRentalContracts = reader.ReadStrongItemList(); + InternalizedVendors = reader.ReadStrongMobileList(); + + var relocatedCount = reader.ReadEncodedInt(); + for (var i = 0; i < relocatedCount; i++) + { + var relLocation = reader.ReadPoint3D(); + var entity = World.FindEntity(reader.ReadUInt()); + + if (entity != null) + RelocatedEntities.Add(new RelocatedEntity(entity, relLocation)); + } + + var inventoryCount = reader.ReadEncodedInt(); + for (var i = 0; i < inventoryCount; i++) + { + var inventory = new VendorInventory(this, reader); + VendorInventories.Add(inventory); + } + + goto case 11; + } + case 11: + { + LastRefreshed = reader.ReadDateTime(); + RestrictDecay = reader.ReadBool(); + goto case 10; + } + case 10: // just a signal for updates + case 9: + { + Visits = reader.ReadInt(); + goto case 8; + } + case 8: + { + Price = reader.ReadInt(); + goto case 7; + } + case 7: + { + Access = reader.ReadStrongMobileList(); + goto case 6; + } + case 6: + { + BuiltOn = reader.ReadDateTime(); + LastTraded = reader.ReadDateTime(); + goto case 5; + } + case 5: // just removed fields + case 4: + { + Addons = reader.ReadStrongItemList(); + goto case 3; + } + case 3: + { + count = reader.ReadInt(); + Secures = new List(count); + + for (var i = 0; i < count; ++i) + { + var info = new SecureInfo(reader); + + if (info.Item != null) + { + info.Item.IsSecure = true; + Secures.Add(info); + } + } + + goto case 2; + } + case 2: + { + m_Public = reader.ReadBool(); + goto case 1; + } + case 1: + { + if (version < 13) + reader.ReadPoint3D(); // house ban location + goto case 0; + } + case 0: + { + if (version < 14) + m_RelativeBanLocation = BaseBanLocation; + + if (version < 12) + { + VendorRentalContracts = new List(); + InternalizedVendors = new List(); + } + + if (version < 4) + Addons = new List(); + + if (version < 7) + Access = new List(); + + if (version < 8) + Price = DefaultPrice; + + m_Owner = reader.ReadMobile(); + + if (version < 5) + { + count = reader.ReadInt(); + + for (var i = 0; i < count; i++) + reader.ReadRect2D(); + } + + UpdateRegion(); + + CoOwners = reader.ReadStrongMobileList(); + Friends = reader.ReadStrongMobileList(); + Bans = reader.ReadStrongMobileList(); + + Sign = reader.ReadItem() as HouseSign; + m_Trash = reader.ReadItem() as TrashBarrel; + + Doors = reader.ReadStrongItemList(); + LockDowns = reader.ReadStrongItemList(); + + for (var i = 0; i < LockDowns.Count; ++i) + LockDowns[i].IsLockedDown = true; + + for (var i = 0; i < VendorRentalContracts.Count; ++i) + VendorRentalContracts[i].IsLockedDown = true; + + if (version < 3) + { + var items = reader.ReadStrongItemList(); + Secures = new List(items.Count); + + for (var i = 0; i < items.Count; ++i) + if (items[i] is Container c) + { + c.IsSecure = true; + Secures.Add(new SecureInfo(c, SecureLevel.CoOwners)); + } + } + + MaxLockDowns = reader.ReadInt(); + MaxSecures = reader.ReadInt(); + + if ((Map == null || Map == Map.Internal) && Location == Point3D.Zero) + Delete(); + + if (m_Owner != null) + { + if (!m_Table.TryGetValue(m_Owner, out var list)) + m_Table[m_Owner] = list = new List(); + + list.Add(this); + } + + break; + } + } + + if (version <= 1) + ChangeSignType(0xBD2); // private house, plain brass sign + + if (version < 10) Timer.DelayCall(FixLockdowns_Sandbox); + + if (version < 11) + LastRefreshed = DateTime.UtcNow + TimeSpan.FromHours(24 * Utility.RandomDouble()); + + if (DynamicDecay.Enabled && !loadedDynamicDecay) + { + var old = GetOldDecayLevel(); + + if (old == DecayLevel.DemolitionPending) + old = DecayLevel.Collapsed; + + SetDynamicDecay(old); + } + + if (!CheckDecay()) + { + if (RelocatedEntities.Count > 0) + Timer.DelayCall(RestoreRelocatedEntities); + + if (m_Owner == null && Friends.Count == 0 && CoOwners.Count == 0) + Timer.DelayCall(TimeSpan.FromSeconds(10.0), Delete); + } + } + + private void FixLockdowns_Sandbox() + { + var conts = LockDowns?.Where(item => item is Container).ToList(); + + if (conts == null) + return; + + foreach (var cont in conts) + SetLockdown(cont, true, true); + } + + public static void HandleDeletion(Mobile mob) + { + var houses = GetHouses(mob); + + if (houses.Count == 0) + return; + + var acct = mob.Account as Account; + Mobile trans = null; + + if (acct != null) + for (var i = 0; i < acct.Length; ++i) + if (acct[i] != null && acct[i] != mob) + trans = acct[i]; + + for (var i = 0; i < houses.Count; ++i) + { + var house = houses[i]; + + if (trans == null && house.CoOwners.Count == 0) + Timer.DelayCall(house.Delete); + else + house.Owner = trans; + } + } + + public int GetLockdowns() + { + var count = 0; + + if (LockDowns != null) + for (var i = 0; i < LockDowns.Count; ++i) + { + if (LockDowns[i] != null) + { + var item = LockDowns[i]; + + if (!(item is Container)) + count += item.TotalItems; + } + + count++; + } + + return count; + } + + public override void OnDelete() + { + RestoreRelocatedEntities(); + + new FixColumnTimer(this).Start(); + + base.OnDelete(); + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); if (m_Owner != null) { - if (!m_Table.TryGetValue(m_Owner, out List list)) - m_Table[m_Owner] = list = new List(); + if (!m_Table.TryGetValue(m_Owner, out var list)) + m_Table[m_Owner] = list = new List(); - list.Add(this); + list.Remove(this); } - break; - } - } - - if (version <= 1) - ChangeSignType(0xBD2); // private house, plain brass sign - - if (version < 10) Timer.DelayCall(FixLockdowns_Sandbox); - - if (version < 11) - LastRefreshed = DateTime.UtcNow + TimeSpan.FromHours(24 * Utility.RandomDouble()); - - if (DynamicDecay.Enabled && !loadedDynamicDecay) - { - DecayLevel old = GetOldDecayLevel(); - - if (old == DecayLevel.DemolitionPending) - old = DecayLevel.Collapsed; - - SetDynamicDecay(old); - } - - if (!CheckDecay()) - { - if (RelocatedEntities.Count > 0) - Timer.DelayCall(RestoreRelocatedEntities); - - if (m_Owner == null && Friends.Count == 0 && CoOwners.Count == 0) - Timer.DelayCall(TimeSpan.FromSeconds(10.0), Delete); - } - } - - private void FixLockdowns_Sandbox() - { - List conts = LockDowns?.Where(item => item is Container).ToList(); - - if (conts == null) - return; - - foreach (Item cont in conts) - SetLockdown(cont, true, true); - } - - public static void HandleDeletion(Mobile mob) - { - List houses = GetHouses(mob); - - if (houses.Count == 0) - return; - - Account acct = mob.Account as Account; - Mobile trans = null; - - if (acct != null) - for (int i = 0; i < acct.Length; ++i) - if (acct[i] != null && acct[i] != mob) - trans = acct[i]; - - for (int i = 0; i < houses.Count; ++i) - { - BaseHouse house = houses[i]; - - if (trans == null && house.CoOwners.Count == 0) - Timer.DelayCall(house.Delete); - else - house.Owner = trans; - } - } - - public int GetLockdowns() - { - int count = 0; - - if (LockDowns != null) - for (int i = 0; i < LockDowns.Count; ++i) - { - if (LockDowns[i] != null) - { - Item item = LockDowns[i]; - - if (!(item is Container)) - count += item.TotalItems; - } - - count++; - } - - return count; - } - - public override void OnDelete() - { - RestoreRelocatedEntities(); - - new FixColumnTimer(this).Start(); - - base.OnDelete(); - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - if (m_Owner != null) - { - if (!m_Table.TryGetValue(m_Owner, out List list)) - m_Table[m_Owner] = list = new List(); - - list.Remove(this); - } - - if (m_Region != null) - { - m_Region.Unregister(); - m_Region = null; - } - - Sign?.Delete(); - - m_Trash?.Delete(); - - if (Doors != null) - { - for (int i = 0; i < Doors.Count; ++i) - { - Item item = Doors[i]; - - item?.Delete(); - } - - Doors.Clear(); - } - - if (LockDowns != null) - { - for (int i = 0; i < LockDowns.Count; ++i) - { - Item item = LockDowns[i]; - - if (item != null) - { - item.IsLockedDown = false; - item.IsSecure = false; - item.Movable = true; - item.SetLastMoved(); - } - } - - LockDowns.Clear(); - } - - if (VendorRentalContracts != null) - { - for (int i = 0; i < VendorRentalContracts.Count; ++i) - { - Item item = VendorRentalContracts[i]; - - if (item != null) - { - item.IsLockedDown = false; - item.IsSecure = false; - item.Movable = true; - item.SetLastMoved(); - } - } - - VendorRentalContracts.Clear(); - } - - if (Secures != null) - { - for (int i = 0; i < Secures.Count; ++i) - { - SecureInfo info = Secures[i]; - - if (info.Item is StrongBox) - { - info.Item.Destroy(); - } - else - { - info.Item.IsLockedDown = false; - info.Item.IsSecure = false; - info.Item.Movable = true; - info.Item.SetLastMoved(); - } - } - - Secures.Clear(); - } - - if (Addons != null) - { - for (int i = 0; i < Addons.Count; ++i) - { - Item item = Addons[i]; - - if (item != null) - { - if (!item.Deleted && item is IAddon addon) + if (m_Region != null) { - Item deed = addon.Deed; - bool retainDeedHue = false; // if the items aren't hued but the deed itself is - int hue = 0; + m_Region.Unregister(); + m_Region = null; + } - if (addon is BaseAddon ba && ba.RetainDeedHue) // There are things that are IAddon which aren't BaseAddon - { - retainDeedHue = true; + Sign?.Delete(); - for (int j = 0; hue == 0 && j < ba.Components.Count; ++j) + m_Trash?.Delete(); + + if (Doors != null) + { + for (var i = 0; i < Doors.Count; ++i) { - AddonComponent c = ba.Components[j]; + Item item = Doors[i]; - if (c.Hue != 0) - hue = c.Hue; + item?.Delete(); } - } - if (deed != null) - { - if (retainDeedHue) - deed.Hue = hue; - deed.MoveToWorld(item.Location, item.Map); - } + Doors.Clear(); } - item.Delete(); - } - } - - Addons.Clear(); - } - - foreach (VendorInventory inventory in VendorInventories.ToList()) - inventory.Delete(); - - MovingCrate?.Delete(); - - KillVendors(); - - AllHouses.Remove(this); - } - - public static bool HasHouse(Mobile m) => - m != null && m_Table.TryGetValue(m, out List list) && list.Any(h => !h.Deleted); - - public static bool HasAccountHouse(Mobile m) - { - if (!(m.Account is Account a)) - return false; - - for (int i = 0; i < a.Length; ++i) - if (a[i] != null && HasHouse(a[i])) - return true; - - return false; - } - - public bool IsOwner(Mobile m) => - m != null && (m == m_Owner || m.AccessLevel >= AccessLevel.GameMaster || - (IsAosRules && AccountHandler.CheckAccount(m, m_Owner))); - - public bool IsCoOwner(Mobile m) => - m != null && CoOwners != null && - (IsOwner(m) || CoOwners.Contains(m) || (!IsAosRules && AccountHandler.CheckAccount(m, m_Owner))); - - public bool IsGuildMember(Mobile m) => m != null && Owner?.Guild != null && m.Guild == Owner.Guild; - - public void RemoveKeys(Mobile m) - { - if (Doors != null) - { - uint keyValue = 0; - - for (int i = 0; keyValue == 0 && i < Doors.Count; ++i) - keyValue = Doors[i].KeyValue; - - Key.RemoveKeys(m, keyValue); - } - } - - public void ChangeLocks(Mobile m) - { - uint keyValue = CreateKeys(m); - - if (Doors != null) - for (int i = 0; i < Doors.Count; ++i) - Doors[i].KeyValue = keyValue; - } - - public void RemoveLocks() - { - if (Doors != null) - for (int i = 0; i < Doors.Count; ++i) - { - BaseDoor door = Doors[i]; - door.KeyValue = 0; - door.Locked = false; - } - } - - public virtual HouseDeed GetDeed() => null; - - public bool IsFriend(Mobile m) => m != null && Friends != null && (IsCoOwner(m) || Friends.Contains(m)); - - public bool IsBanned(Mobile m) - { - if (m == null || m == Owner || m.AccessLevel > AccessLevel.Player || Bans == null) - return false; - - Account theirAccount = m.Account as Account; - - for (int i = 0; i < Bans.Count; ++i) - { - Mobile c = Bans[i]; - - if (c == m) - return true; - - if (c.Account is Account bannedAccount && bannedAccount == theirAccount) - return true; - } - - return false; - } - - public bool HasAccess(Mobile m) - { - if (m == null) - return false; - - if (m.AccessLevel > AccessLevel.Player || IsFriend(m) || Access?.Contains(m) == true) - return true; - - if (!(m is BaseCreature bc)) - return false; - - if (bc.NoHouseRestrictions) - return true; - - if (!(bc.Controlled || bc.Summoned)) - return false; - - m = bc.ControlMaster ?? bc.SummonMaster; - - return m != null && (m.AccessLevel > AccessLevel.Player || IsFriend(m) || Access?.Contains(m) == true); - } - - public bool HasLockedDownItem(Item check) => - LockDowns?.Contains(check) == true || - (check is VendorRentalContract contract && VendorRentalContracts.Contains(contract)); - - public bool HasSecureItem(Item item) - { - if (item == null) - return false; - - for (int i = 0; i < Secures?.Count; ++i) - if (Secures[i].Item == item) - return true; - - return false; - } - - public virtual Guildstone FindGuildstone() - { - Map map = Map; - - if (map == null) - return null; - - MultiComponentList mcl = Components; - IPooledEnumerable eable = - map.GetItemsInBounds(new Rectangle2D(X + mcl.Min.X, Y + mcl.Min.Y, mcl.Width, mcl.Height)); - - Guildstone item = eable.FirstOrDefault(Contains); - eable.Free(); - return item; - } - - private class TransferItem : Item - { - private readonly BaseHouse m_House; - - public TransferItem(BaseHouse house) : base(0x14F0) - { - m_House = house; - - Hue = 0x480; - Movable = false; - } - - public TransferItem(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a house transfer contract"; - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - string houseName = m_House == null ? "an unnamed house" : m_House.Sign.GetName(); - string owner = m_House?.Owner?.Name ?? "nobody"; - - int xLong = 0, yLat = 0, xMins = 0, yMins = 0; - bool xEast = false, ySouth = false; - - bool valid = m_House != null && Sextant.Format(m_House.Location, m_House.Map, ref xLong, ref yLat, ref xMins, - ref yMins, ref xEast, ref ySouth); - - string location = - valid ? $"{yLat}° {yMins}'{(ySouth ? "S" : "N")}, {xLong}° {xMins}'{(xEast ? "E" : "W")}" : "unknown"; - - list.Add(1061112, Utility.FixHtml(houseName)); // House Name: ~1_val~ - list.Add(1061113, owner); // Owner: ~1_val~ - list.Add(1061114, location); // Location: ~1_val~ - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - Delete(); - } - - public override bool AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted) - { - if (!base.AllowSecureTrade(from, to, newOwner, accepted)) - return false; - if (!accepted) - return true; - - if (Deleted || m_House?.Deleted != false || !m_House.IsOwner(from) || !from.CheckAlive() || - !to.CheckAlive()) - return false; - - if (HasAccountHouse(to)) - { - from.SendLocalizedMessage(501388); // You cannot transfer ownership to another house owner or co-owner! - return false; - } - - return m_House.CheckTransferPosition(from, to); - } - - public override void OnSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted) - { - if (Deleted) - return; - - Delete(); - - if (m_House?.Deleted != false || !m_House.IsOwner(from) || !from.CheckAlive() || !to.CheckAlive()) - return; - - if (!accepted) - return; - - from.SendLocalizedMessage(501338); // You have transferred ownership of the house. - - /* You are now the owner of this house. - * The house's co-owner, friend, ban, and access lists have been cleared. - * You should double-check the security settings on any doors and teleporters in the house. - */ - to.SendLocalizedMessage(501339); - - m_House.RemoveKeys(from); - m_House.Owner = to; - m_House.Bans.Clear(); - m_House.Friends.Clear(); - m_House.CoOwners.Clear(); - m_House.ChangeLocks(to); - m_House.LastTraded = DateTime.UtcNow; - } - } - - private class FixColumnTimer : Timer - { - private readonly Map m_Map; - private readonly int m_StartX; - private readonly int m_StartY; - private readonly int m_EndX; - private readonly int m_EndY; - - public FixColumnTimer(BaseMulti multi) : base(TimeSpan.Zero) - { - m_Map = multi.Map; - - MultiComponentList mcl = multi.Components; - - m_StartX = multi.X + mcl.Min.X; - m_StartY = multi.Y + mcl.Min.Y; - m_EndX = multi.X + mcl.Max.X; - m_EndY = multi.Y + mcl.Max.Y; - } - - protected override void OnTick() - { - if (m_Map == null) - return; - - for (int x = m_StartX; x <= m_EndX; ++x) - for (int y = m_StartY; y <= m_EndY; ++y) - m_Map.FixColumn(x, y); - } - } - - private DecayLevel m_CurrentStage; - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime NextDecayStage { get; set; } - - public void ResetDynamicDecay() - { - m_CurrentStage = DecayLevel.Ageless; - NextDecayStage = DateTime.MinValue; - } - - public void SetDynamicDecay(DecayLevel level) - { - m_CurrentStage = level; - - if (DynamicDecay.Decays(level)) - NextDecayStage = DateTime.UtcNow + DynamicDecay.GetRandomDuration(level); - else - NextDecayStage = DateTime.MinValue; - } - } - - public enum DecayType - { - Ageless, - AutoRefresh, - ManualRefresh, - Condemned - } - - public enum DecayLevel - { - Ageless, - LikeNew, - Slightly, - Somewhat, - Fairly, - Greatly, - IDOC, - Collapsed, - DemolitionPending - } - - public enum SecureAccessResult - { - Insecure, - Accessible, - Inaccessible - } - - public enum SecureLevel - { - Owner, - CoOwners, - Friends, - Anyone, - Guild - } - - public class SecureInfo : ISecurable - { - public SecureInfo(Container item, SecureLevel level) - { - Item = item; - Level = level; - } - - public SecureInfo(IGenericReader reader) - { - Item = reader.ReadItem() as Container; - Level = (SecureLevel)reader.ReadByte(); - } - - public Container Item { get; } - - public SecureLevel Level { get; set; } - - public void Serialize(IGenericWriter writer) - { - writer.Write(Item); - writer.Write((byte)Level); - } - } - - public class RelocatedEntity - { - public RelocatedEntity(IEntity entity, Point3D relativeLocation) - { - Entity = entity; - RelativeLocation = relativeLocation; - } - - public IEntity Entity { get; } - - public Point3D RelativeLocation { get; } - } - - public class LockdownTarget : Target - { - private readonly BaseHouse m_House; - private readonly bool m_Release; - - public LockdownTarget(bool release, BaseHouse house) : base(12, false, TargetFlags.None) - { - CheckLOS = false; - - m_Release = release; - m_House = house; - } - - protected override void OnTargetNotAccessible(Mobile from, object targeted) - { - OnTarget(from, targeted); - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (!from.Alive || m_House.Deleted || !m_House.IsCoOwner(from)) - return; - - if (targeted is Item item) - { - if (m_Release) - { - if (item is AddonContainerComponent component) - { - if (component.Addon != null) - m_House.Release(from, component.Addon); - } - else - { - m_House.Release(from, item); - } - } - else - { - if (item is VendorRentalContract) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1062392); // You must double click the contract in your pack to lock it down. - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 501732); // I cannot lock this down! - } - else if (item is AddonComponent) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 501727); // You cannot lock that down! - from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 501732); // I cannot lock this down! - } - else - { - if (item is AddonContainerComponent component) + if (LockDowns != null) + { + for (var i = 0; i < LockDowns.Count; ++i) + { + var item = LockDowns[i]; + + if (item != null) + { + item.IsLockedDown = false; + item.IsSecure = false; + item.Movable = true; + item.SetLastMoved(); + } + } + + LockDowns.Clear(); + } + + if (VendorRentalContracts != null) + { + for (var i = 0; i < VendorRentalContracts.Count; ++i) + { + Item item = VendorRentalContracts[i]; + + if (item != null) + { + item.IsLockedDown = false; + item.IsSecure = false; + item.Movable = true; + item.SetLastMoved(); + } + } + + VendorRentalContracts.Clear(); + } + + if (Secures != null) + { + for (var i = 0; i < Secures.Count; ++i) + { + var info = Secures[i]; + + if (info.Item is StrongBox) + { + info.Item.Destroy(); + } + else + { + info.Item.IsLockedDown = false; + info.Item.IsSecure = false; + info.Item.Movable = true; + info.Item.SetLastMoved(); + } + } + + Secures.Clear(); + } + + if (Addons != null) + { + for (var i = 0; i < Addons.Count; ++i) + { + var item = Addons[i]; + + if (item != null) + { + if (!item.Deleted && item is IAddon addon) + { + var deed = addon.Deed; + var retainDeedHue = false; // if the items aren't hued but the deed itself is + var hue = 0; + + if (addon is BaseAddon ba && ba.RetainDeedHue + ) // There are things that are IAddon which aren't BaseAddon + { + retainDeedHue = true; + + for (var j = 0; hue == 0 && j < ba.Components.Count; ++j) + { + var c = ba.Components[j]; + + if (c.Hue != 0) + hue = c.Hue; + } + } + + if (deed != null) + { + if (retainDeedHue) + deed.Hue = hue; + deed.MoveToWorld(item.Location, item.Map); + } + } + + item.Delete(); + } + } + + Addons.Clear(); + } + + foreach (var inventory in VendorInventories.ToList()) + inventory.Delete(); + + MovingCrate?.Delete(); + + KillVendors(); + + AllHouses.Remove(this); + } + + public static bool HasHouse(Mobile m) => + m != null && m_Table.TryGetValue(m, out var list) && list.Any(h => !h.Deleted); + + public static bool HasAccountHouse(Mobile m) + { + if (!(m.Account is Account a)) + return false; + + for (var i = 0; i < a.Length; ++i) + if (a[i] != null && HasHouse(a[i])) + return true; + + return false; + } + + public bool IsOwner(Mobile m) => + m != null && (m == m_Owner || m.AccessLevel >= AccessLevel.GameMaster || + IsAosRules && AccountHandler.CheckAccount(m, m_Owner)); + + public bool IsCoOwner(Mobile m) => + m != null && CoOwners != null && + (IsOwner(m) || CoOwners.Contains(m) || !IsAosRules && AccountHandler.CheckAccount(m, m_Owner)); + + public bool IsGuildMember(Mobile m) => m != null && Owner?.Guild != null && m.Guild == Owner.Guild; + + public void RemoveKeys(Mobile m) + { + if (Doors != null) + { + uint keyValue = 0; + + for (var i = 0; keyValue == 0 && i < Doors.Count; ++i) + keyValue = Doors[i].KeyValue; + + Key.RemoveKeys(m, keyValue); + } + } + + public void ChangeLocks(Mobile m) + { + var keyValue = CreateKeys(m); + + if (Doors != null) + for (var i = 0; i < Doors.Count; ++i) + Doors[i].KeyValue = keyValue; + } + + public void RemoveLocks() + { + if (Doors != null) + for (var i = 0; i < Doors.Count; ++i) + { + var door = Doors[i]; + door.KeyValue = 0; + door.Locked = false; + } + } + + public virtual HouseDeed GetDeed() => null; + + public bool IsFriend(Mobile m) => m != null && Friends != null && (IsCoOwner(m) || Friends.Contains(m)); + + public bool IsBanned(Mobile m) + { + if (m == null || m == Owner || m.AccessLevel > AccessLevel.Player || Bans == null) + return false; + + var theirAccount = m.Account as Account; + + for (var i = 0; i < Bans.Count; ++i) + { + var c = Bans[i]; + + if (c == m) + return true; + + if (c.Account is Account bannedAccount && bannedAccount == theirAccount) + return true; + } + + return false; + } + + public bool HasAccess(Mobile m) + { + if (m == null) + return false; + + if (m.AccessLevel > AccessLevel.Player || IsFriend(m) || Access?.Contains(m) == true) + return true; + + if (!(m is BaseCreature bc)) + return false; + + if (bc.NoHouseRestrictions) + return true; + + if (!(bc.Controlled || bc.Summoned)) + return false; + + m = bc.ControlMaster ?? bc.SummonMaster; + + return m != null && (m.AccessLevel > AccessLevel.Player || IsFriend(m) || Access?.Contains(m) == true); + } + + public bool HasLockedDownItem(Item check) => + LockDowns?.Contains(check) == true || + check is VendorRentalContract contract && VendorRentalContracts.Contains(contract); + + public bool HasSecureItem(Item item) + { + if (item == null) + return false; + + for (var i = 0; i < Secures?.Count; ++i) + if (Secures[i].Item == item) + return true; + + return false; + } + + public virtual Guildstone FindGuildstone() + { + var map = Map; + + if (map == null) + return null; + + var mcl = Components; + var eable = + map.GetItemsInBounds(new Rectangle2D(X + mcl.Min.X, Y + mcl.Min.Y, mcl.Width, mcl.Height)); + + var item = eable.FirstOrDefault(Contains); + eable.Free(); + return item; + } + + public void ResetDynamicDecay() + { + m_CurrentStage = DecayLevel.Ageless; + NextDecayStage = DateTime.MinValue; + } + + public void SetDynamicDecay(DecayLevel level) + { + m_CurrentStage = level; + + if (DynamicDecay.Decays(level)) + NextDecayStage = DateTime.UtcNow + DynamicDecay.GetRandomDuration(level); + else + NextDecayStage = DateTime.MinValue; + } + + private class TransferItem : Item + { + private readonly BaseHouse m_House; + + public TransferItem(BaseHouse house) : base(0x14F0) + { + m_House = house; + + Hue = 0x480; + Movable = false; + } + + public TransferItem(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a house transfer contract"; + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + var houseName = m_House == null ? "an unnamed house" : m_House.Sign.GetName(); + var owner = m_House?.Owner?.Name ?? "nobody"; + + int xLong = 0, yLat = 0, xMins = 0, yMins = 0; + bool xEast = false, ySouth = false; + + var valid = m_House != null && Sextant.Format( + m_House.Location, + m_House.Map, + ref xLong, + ref yLat, + ref xMins, + ref yMins, + ref xEast, + ref ySouth + ); + + var location = + valid ? $"{yLat}° {yMins}'{(ySouth ? "S" : "N")}, {xLong}° {xMins}'{(xEast ? "E" : "W")}" : "unknown"; + + list.Add(1061112, Utility.FixHtml(houseName)); // House Name: ~1_val~ + list.Add(1061113, owner); // Owner: ~1_val~ + list.Add(1061114, location); // Location: ~1_val~ + } + + 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(); + + Delete(); + } + + public override bool AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted) + { + if (!base.AllowSecureTrade(from, to, newOwner, accepted)) + return false; + if (!accepted) + return true; + + if (Deleted || m_House?.Deleted != false || !m_House.IsOwner(from) || !from.CheckAlive() || + !to.CheckAlive()) + return false; + + if (HasAccountHouse(to)) + { + from.SendLocalizedMessage(501388); // You cannot transfer ownership to another house owner or co-owner! + return false; + } + + return m_House.CheckTransferPosition(from, to); + } + + public override void OnSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted) + { + if (Deleted) + return; + + Delete(); + + if (m_House?.Deleted != false || !m_House.IsOwner(from) || !from.CheckAlive() || !to.CheckAlive()) + return; + + if (!accepted) + return; + + from.SendLocalizedMessage(501338); // You have transferred ownership of the house. + + /* You are now the owner of this house. + * The house's co-owner, friend, ban, and access lists have been cleared. + * You should double-check the security settings on any doors and teleporters in the house. + */ + to.SendLocalizedMessage(501339); + + m_House.RemoveKeys(from); + m_House.Owner = to; + m_House.Bans.Clear(); + m_House.Friends.Clear(); + m_House.CoOwners.Clear(); + m_House.ChangeLocks(to); + m_House.LastTraded = DateTime.UtcNow; + } + } + + private class FixColumnTimer : Timer + { + private readonly int m_EndX; + private readonly int m_EndY; + private readonly Map m_Map; + private readonly int m_StartX; + private readonly int m_StartY; + + public FixColumnTimer(BaseMulti multi) : base(TimeSpan.Zero) + { + m_Map = multi.Map; + + var mcl = multi.Components; + + m_StartX = multi.X + mcl.Min.X; + m_StartY = multi.Y + mcl.Min.Y; + m_EndX = multi.X + mcl.Max.X; + m_EndY = multi.Y + mcl.Max.Y; + } + + protected override void OnTick() + { + if (m_Map == null) + return; + + for (var x = m_StartX; x <= m_EndX; ++x) + for (var y = m_StartY; y <= m_EndY; ++y) + m_Map.FixColumn(x, y); + } + } + } + + public enum DecayType + { + Ageless, + AutoRefresh, + ManualRefresh, + Condemned + } + + public enum DecayLevel + { + Ageless, + LikeNew, + Slightly, + Somewhat, + Fairly, + Greatly, + IDOC, + Collapsed, + DemolitionPending + } + + public enum SecureAccessResult + { + Insecure, + Accessible, + Inaccessible + } + + public enum SecureLevel + { + Owner, + CoOwners, + Friends, + Anyone, + Guild + } + + public class SecureInfo : ISecurable + { + public SecureInfo(Container item, SecureLevel level) + { + Item = item; + Level = level; + } + + public SecureInfo(IGenericReader reader) + { + Item = reader.ReadItem() as Container; + Level = (SecureLevel)reader.ReadByte(); + } + + public Container Item { get; } + + public SecureLevel Level { get; set; } + + public void Serialize(IGenericWriter writer) + { + writer.Write(Item); + writer.Write((byte)Level); + } + } + + public class RelocatedEntity + { + public RelocatedEntity(IEntity entity, Point3D relativeLocation) + { + Entity = entity; + RelativeLocation = relativeLocation; + } + + public IEntity Entity { get; } + + public Point3D RelativeLocation { get; } + } + + public class LockdownTarget : Target + { + private readonly BaseHouse m_House; + private readonly bool m_Release; + + public LockdownTarget(bool release, BaseHouse house) : base(12, false, TargetFlags.None) + { + CheckLOS = false; + + m_Release = release; + m_House = house; + } + + protected override void OnTargetNotAccessible(Mobile from, object targeted) + { + OnTarget(from, targeted); + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (!from.Alive || m_House.Deleted || !m_House.IsCoOwner(from)) + return; + + if (targeted is Item item) + { + if (m_Release) + { + if (item is AddonContainerComponent component) + { + if (component.Addon != null) + m_House.Release(from, component.Addon); + } + else + { + m_House.Release(from, item); + } + } + else + { + if (item is VendorRentalContract) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1062392 + ); // You must double click the contract in your pack to lock it down. + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 501732); // I cannot lock this down! + } + else if (item is AddonComponent) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 501727); // You cannot lock that down! + from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 501732); // I cannot lock this down! + } + else + { + if (item is AddonContainerComponent component) + { + if (component.Addon != null) + m_House.LockDown(from, component.Addon); + } + else + { + m_House.LockDown(from, item); + } + } + } + } + else if (targeted is StaticTarget) { - if (component.Addon != null) - m_House.LockDown(from, component.Addon); } else { - m_House.LockDown(from, item); + from.SendLocalizedMessage(1005377); // You cannot lock that down } - } } - } - else if (targeted is StaticTarget) - { - } - else - { - from.SendLocalizedMessage(1005377); // You cannot lock that down - } - } - } - - public class SecureTarget : Target - { - private readonly BaseHouse m_House; - private readonly bool m_Release; - - public SecureTarget(bool release, BaseHouse house) : base(12, false, TargetFlags.None) - { - CheckLOS = false; - - m_Release = release; - m_House = house; } - protected override void OnTargetNotAccessible(Mobile from, object targeted) + public class SecureTarget : Target { - OnTarget(from, targeted); - } + private readonly BaseHouse m_House; + private readonly bool m_Release; - protected override void OnTarget(Mobile from, object targeted) - { - if (!from.Alive || m_House.Deleted || !m_House.IsCoOwner(from)) - return; - - if (targeted is Item item) - { - if (m_Release) + public SecureTarget(bool release, BaseHouse house) : base(12, false, TargetFlags.None) { - if (item is AddonContainerComponent component) - { - if (component.Addon != null) - m_House.ReleaseSecure(from, component.Addon); - } - else - { - m_House.ReleaseSecure(from, item); - } + CheckLOS = false; + + m_Release = release; + m_House = house; } - else + + protected override void OnTargetNotAccessible(Mobile from, object targeted) { - if (item is VendorRentalContract) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1062392); // You must double click the contract in your pack to lock it down. - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 501732); // I cannot lock this down! - } - else - { - if (item is AddonContainerComponent component) + OnTarget(from, targeted); + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (!from.Alive || m_House.Deleted || !m_House.IsCoOwner(from)) + return; + + if (targeted is Item item) { - if (component.Addon != null) - m_House.AddSecure(from, component.Addon); + if (m_Release) + { + if (item is AddonContainerComponent component) + { + if (component.Addon != null) + m_House.ReleaseSecure(from, component.Addon); + } + else + { + m_House.ReleaseSecure(from, item); + } + } + else + { + if (item is VendorRentalContract) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1062392 + ); // You must double click the contract in your pack to lock it down. + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 501732); // I cannot lock this down! + } + else + { + if (item is AddonContainerComponent component) + { + if (component.Addon != null) + m_House.AddSecure(from, component.Addon); + } + else + { + m_House.AddSecure(from, item); + } + } + } } else { - m_House.AddSecure(from, item); + from.SendLocalizedMessage(1010424); // You cannot secure this } - } } - } - else - { - from.SendLocalizedMessage(1010424); // You cannot secure this - } - } - } - - public class HouseKickTarget : Target - { - private readonly BaseHouse m_House; - - public HouseKickTarget(BaseHouse house) : base(-1, false, TargetFlags.None) - { - CheckLOS = false; - - m_House = house; } - protected override void OnTarget(Mobile from, object targeted) + public class HouseKickTarget : Target { - if (!from.Alive || m_House.Deleted || !m_House.IsFriend(from)) - return; + private readonly BaseHouse m_House; - if (targeted is Mobile mobile) - m_House.Kick(from, mobile); - else - from.SendLocalizedMessage(501347); // You cannot eject that from the house! - } - } - - public class HouseBanTarget : Target - { - private readonly bool m_Banning; - private readonly BaseHouse m_House; - - public HouseBanTarget(bool ban, BaseHouse house) : base(-1, false, TargetFlags.None) - { - CheckLOS = false; - - m_House = house; - m_Banning = ban; - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (!from.Alive || m_House.Deleted || !m_House.IsFriend(from)) - return; - - if (targeted is Mobile mobile) - { - if (m_Banning) - m_House.Ban(from, mobile); - else - m_House.RemoveBan(from, mobile); - } - else - { - from.SendLocalizedMessage(501347); // You cannot eject that from the house! - } - } - } - - public class HouseAccessTarget : Target - { - private readonly BaseHouse m_House; - - public HouseAccessTarget(BaseHouse house) : base(-1, false, TargetFlags.None) - { - CheckLOS = false; - - m_House = house; - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (!from.Alive || m_House.Deleted || !m_House.IsFriend(from)) - return; - - if (targeted is Mobile mobile) - m_House.GrantAccess(from, mobile); - else - from.SendLocalizedMessage(1060712); // That is not a player. - } - } - - public class CoOwnerTarget : Target - { - private readonly bool m_Add; - private readonly BaseHouse m_House; - - public CoOwnerTarget(bool add, BaseHouse house) : base(12, false, TargetFlags.None) - { - CheckLOS = false; - - m_House = house; - m_Add = add; - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (!from.Alive || m_House.Deleted || !m_House.IsOwner(from)) - return; - - if (targeted is Mobile mobile) - { - if (m_Add) - m_House.AddCoOwner(from, mobile); - else - m_House.RemoveCoOwner(from, mobile); - } - else - { - from.SendLocalizedMessage(501362); // That can't be a coowner - } - } - } - - public class HouseFriendTarget : Target - { - private readonly bool m_Add; - private readonly BaseHouse m_House; - - public HouseFriendTarget(bool add, BaseHouse house) : base(12, false, TargetFlags.None) - { - CheckLOS = false; - - m_House = house; - m_Add = add; - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (!from.Alive || m_House.Deleted || !m_House.IsCoOwner(from)) - return; - - if (targeted is Mobile mobile) - { - if (m_Add) - m_House.AddFriend(from, mobile); - else - m_House.RemoveFriend(from, mobile); - } - else - { - from.SendLocalizedMessage(501371); // That can't be a friend - } - } - } - - public class HouseOwnerTarget : Target - { - private readonly BaseHouse m_House; - - public HouseOwnerTarget(BaseHouse house) : base(12, false, TargetFlags.None) - { - CheckLOS = false; - - m_House = house; - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is Mobile mobile) - m_House.BeginConfirmTransfer(from, mobile); - else - from.SendLocalizedMessage(501384); // Only a player can own a house! - } - } - - public class SetSecureLevelEntry : ContextMenuEntry - { - private readonly Item m_Item; - private ISecurable m_Securable; - - public SetSecureLevelEntry(Item item, ISecurable securable) : base(6203, 6) - { - m_Item = item; - m_Securable = securable; - } - - public static ISecurable GetSecurable(Mobile from, Item item) - { - BaseHouse house = BaseHouse.FindHouseAt(item); - - if (house?.IsOwner(from) != true || !house.IsAosRules) - return null; - - ISecurable sec = null; - - if (item is ISecurable securable) - { - bool isOwned = item is BaseDoor door && house.Doors.Contains(door); - - if (!isOwned) - isOwned = house is HouseFoundation foundation && foundation.IsFixture(item); - - if (!isOwned) - isOwned = house.HasLockedDownItem(item); - - if (isOwned) - sec = securable; - } - else - { - List list = house.Secures; - - for (int i = 0; sec == null && list != null && i < list.Count; ++i) + public HouseKickTarget(BaseHouse house) : base(-1, false, TargetFlags.None) { - SecureInfo si = list[i]; + CheckLOS = false; - if (si.Item == item) - sec = si; + m_House = house; } - } - return sec; + protected override void OnTarget(Mobile from, object targeted) + { + if (!from.Alive || m_House.Deleted || !m_House.IsFriend(from)) + return; + + if (targeted is Mobile mobile) + m_House.Kick(from, mobile); + else + from.SendLocalizedMessage(501347); // You cannot eject that from the house! + } } - public static void AddTo(Mobile from, Item item, List list) + public class HouseBanTarget : Target { - ISecurable sec = GetSecurable(from, item); + private readonly bool m_Banning; + private readonly BaseHouse m_House; - if (sec != null) - list.Add(new SetSecureLevelEntry(item, sec)); + public HouseBanTarget(bool ban, BaseHouse house) : base(-1, false, TargetFlags.None) + { + CheckLOS = false; + + m_House = house; + m_Banning = ban; + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (!from.Alive || m_House.Deleted || !m_House.IsFriend(from)) + return; + + if (targeted is Mobile mobile) + { + if (m_Banning) + m_House.Ban(from, mobile); + else + m_House.RemoveBan(from, mobile); + } + else + { + from.SendLocalizedMessage(501347); // You cannot eject that from the house! + } + } } - public override void OnClick() + public class HouseAccessTarget : Target { - ISecurable sec = GetSecurable(Owner.From, m_Item); + private readonly BaseHouse m_House; - if (sec != null) - { - Owner.From.CloseGump(); - Owner.From.SendGump(new SetSecureLevelGump(Owner.From, sec, BaseHouse.FindHouseAt(m_Item))); - } + public HouseAccessTarget(BaseHouse house) : base(-1, false, TargetFlags.None) + { + CheckLOS = false; + + m_House = house; + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (!from.Alive || m_House.Deleted || !m_House.IsFriend(from)) + return; + + if (targeted is Mobile mobile) + m_House.GrantAccess(from, mobile); + else + from.SendLocalizedMessage(1060712); // That is not a player. + } } - } - public class TempNoHousingRegion : BaseRegion - { - private readonly Mobile m_RegionOwner; - - public TempNoHousingRegion(BaseHouse house, Mobile regionowner) - : base(null, house.Map, DefaultPriority, house.Region.Area) + public class CoOwnerTarget : Target { - Register(); + private readonly bool m_Add; + private readonly BaseHouse m_House; - m_RegionOwner = regionowner; + public CoOwnerTarget(bool add, BaseHouse house) : base(12, false, TargetFlags.None) + { + CheckLOS = false; - Timer.DelayCall(house.RestrictedPlacingTime, Unregister); + m_House = house; + m_Add = add; + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (!from.Alive || m_House.Deleted || !m_House.IsOwner(from)) + return; + + if (targeted is Mobile mobile) + { + if (m_Add) + m_House.AddCoOwner(from, mobile); + else + m_House.RemoveCoOwner(from, mobile); + } + else + { + from.SendLocalizedMessage(501362); // That can't be a coowner + } + } } - public override bool AllowHousing(Mobile from, Point3D p) => from == m_RegionOwner || AccountHandler.CheckAccount(from, m_RegionOwner); - } + public class HouseFriendTarget : Target + { + private readonly bool m_Add; + private readonly BaseHouse m_House; + + public HouseFriendTarget(bool add, BaseHouse house) : base(12, false, TargetFlags.None) + { + CheckLOS = false; + + m_House = house; + m_Add = add; + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (!from.Alive || m_House.Deleted || !m_House.IsCoOwner(from)) + return; + + if (targeted is Mobile mobile) + { + if (m_Add) + m_House.AddFriend(from, mobile); + else + m_House.RemoveFriend(from, mobile); + } + else + { + from.SendLocalizedMessage(501371); // That can't be a friend + } + } + } + + public class HouseOwnerTarget : Target + { + private readonly BaseHouse m_House; + + public HouseOwnerTarget(BaseHouse house) : base(12, false, TargetFlags.None) + { + CheckLOS = false; + + m_House = house; + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted is Mobile mobile) + m_House.BeginConfirmTransfer(from, mobile); + else + from.SendLocalizedMessage(501384); // Only a player can own a house! + } + } + + public class SetSecureLevelEntry : ContextMenuEntry + { + private readonly Item m_Item; + private ISecurable m_Securable; + + public SetSecureLevelEntry(Item item, ISecurable securable) : base(6203, 6) + { + m_Item = item; + m_Securable = securable; + } + + public static ISecurable GetSecurable(Mobile from, Item item) + { + var house = BaseHouse.FindHouseAt(item); + + if (house?.IsOwner(from) != true || !house.IsAosRules) + return null; + + ISecurable sec = null; + + if (item is ISecurable securable) + { + var isOwned = item is BaseDoor door && house.Doors.Contains(door); + + if (!isOwned) + isOwned = house is HouseFoundation foundation && foundation.IsFixture(item); + + if (!isOwned) + isOwned = house.HasLockedDownItem(item); + + if (isOwned) + sec = securable; + } + else + { + var list = house.Secures; + + for (var i = 0; sec == null && list != null && i < list.Count; ++i) + { + var si = list[i]; + + if (si.Item == item) + sec = si; + } + } + + return sec; + } + + public static void AddTo(Mobile from, Item item, List list) + { + var sec = GetSecurable(from, item); + + if (sec != null) + list.Add(new SetSecureLevelEntry(item, sec)); + } + + public override void OnClick() + { + var sec = GetSecurable(Owner.From, m_Item); + + if (sec != null) + { + Owner.From.CloseGump(); + Owner.From.SendGump(new SetSecureLevelGump(Owner.From, sec, BaseHouse.FindHouseAt(m_Item))); + } + } + } + + public class TempNoHousingRegion : BaseRegion + { + private readonly Mobile m_RegionOwner; + + public TempNoHousingRegion(BaseHouse house, Mobile regionowner) + : base(null, house.Map, DefaultPriority, house.Region.Area) + { + Register(); + + m_RegionOwner = regionowner; + + Timer.DelayCall(house.RestrictedPlacingTime, Unregister); + } + + public override bool AllowHousing(Mobile from, Point3D p) => + from == m_RegionOwner || AccountHandler.CheckAccount(from, m_RegionOwner); + } } diff --git a/Projects/UOContent/Multis/Boats/BaseBoat.cs b/Projects/UOContent/Multis/Boats/BaseBoat.cs index fcab9877d..9757ad686 100644 --- a/Projects/UOContent/Multis/Boats/BaseBoat.cs +++ b/Projects/UOContent/Multis/Boats/BaseBoat.cs @@ -7,1866 +7,1898 @@ using Server.Network; namespace Server.Multis { - public enum BoatOrder - { - Move, - Course, - Single - } - - public abstract class BaseBoat : BaseMulti - { - public enum DryDockResult + public enum BoatOrder { - Valid, - Dead, - NoKey, - NotAnchored, - Mobiles, - Items, - Hold, - Decaying + Move, + Course, + Single } - private static readonly Rectangle2D[] m_BritWrap = - { new Rectangle2D(16, 16, 5120 - 32, 4096 - 32), new Rectangle2D(5136, 2320, 992, 1760) }; - - private static readonly Rectangle2D[] m_IlshWrap = { new Rectangle2D(16, 16, 2304 - 32, 1600 - 32) }; - private static readonly Rectangle2D[] m_TokunoWrap = { new Rectangle2D(16, 16, 1448 - 32, 1448 - 32) }; - - private static readonly TimeSpan BoatDecayDelay = TimeSpan.FromDays(9.0); - - private static readonly TimeSpan SlowInterval = TimeSpan.FromSeconds(NewBoatMovement ? 0.50 : 0.75); - private static readonly TimeSpan FastInterval = TimeSpan.FromSeconds(NewBoatMovement ? 0.25 : 0.75); - - private static readonly int SlowSpeed = 1; - private static readonly int FastSpeed = NewBoatMovement ? 1 : 3; - - private static readonly TimeSpan SlowDriftInterval = TimeSpan.FromSeconds(NewBoatMovement ? 0.50 : 1.50); - private static readonly TimeSpan FastDriftInterval = TimeSpan.FromSeconds(NewBoatMovement ? 0.25 : 0.75); - - private static readonly int SlowDriftSpeed = 1; - private static readonly int FastDriftSpeed = 1; - - private static readonly Direction Forward = Direction.North; - private static readonly Direction ForwardLeft = Direction.Up; - private static readonly Direction ForwardRight = Direction.Right; - private static readonly Direction Backward = Direction.South; - private static readonly Direction BackwardLeft = Direction.Left; - private static readonly Direction BackwardRight = Direction.Down; - private static readonly Direction Left = Direction.West; - private static readonly Direction Right = Direction.East; - private static Direction Port = Left; - private static Direction Starboard = Right; - - private int m_ClientSpeed; - - private bool m_Decaying; - - private DateTime m_DecayTime; - - private Direction m_Facing; - private Timer m_MoveTimer; - - private string m_ShipName; - - private Timer m_TurnTimer; - - public BaseBoat() : base(0x0) + public abstract class BaseBoat : BaseMulti { - m_DecayTime = DateTime.UtcNow + BoatDecayDelay; + public enum DryDockResult + { + Valid, + Dead, + NoKey, + NotAnchored, + Mobiles, + Items, + Hold, + Decaying + } - TillerMan = new TillerMan(this); - Hold = new Hold(this); + private static readonly Rectangle2D[] m_BritWrap = + { new Rectangle2D(16, 16, 5120 - 32, 4096 - 32), new Rectangle2D(5136, 2320, 992, 1760) }; - PPlank = new Plank(this, PlankSide.Port, 0); - SPlank = new Plank(this, PlankSide.Starboard, 0); + private static readonly Rectangle2D[] m_IlshWrap = { new Rectangle2D(16, 16, 2304 - 32, 1600 - 32) }; + private static readonly Rectangle2D[] m_TokunoWrap = { new Rectangle2D(16, 16, 1448 - 32, 1448 - 32) }; - PPlank.MoveToWorld(new Point3D(X + PortOffset.X, Y + PortOffset.Y, Z), Map); - SPlank.MoveToWorld(new Point3D(X + StarboardOffset.X, Y + StarboardOffset.Y, Z), Map); + private static readonly TimeSpan BoatDecayDelay = TimeSpan.FromDays(9.0); - Facing = Direction.North; + private static readonly TimeSpan SlowInterval = TimeSpan.FromSeconds(NewBoatMovement ? 0.50 : 0.75); + private static readonly TimeSpan FastInterval = TimeSpan.FromSeconds(NewBoatMovement ? 0.25 : 0.75); - NextNavPoint = -1; + private static readonly int SlowSpeed = 1; + private static readonly int FastSpeed = NewBoatMovement ? 1 : 3; - Movable = false; + private static readonly TimeSpan SlowDriftInterval = TimeSpan.FromSeconds(NewBoatMovement ? 0.50 : 1.50); + private static readonly TimeSpan FastDriftInterval = TimeSpan.FromSeconds(NewBoatMovement ? 0.25 : 0.75); - Boats.Add(this); - } + private static readonly int SlowDriftSpeed = 1; + private static readonly int FastDriftSpeed = 1; - public BaseBoat(Serial serial) : base(serial) - { - } + private static readonly Direction Forward = Direction.North; + private static readonly Direction ForwardLeft = Direction.Up; + private static readonly Direction ForwardRight = Direction.Right; + private static readonly Direction Backward = Direction.South; + private static readonly Direction BackwardLeft = Direction.Left; + private static readonly Direction BackwardRight = Direction.Down; + private static readonly Direction Left = Direction.West; + private static readonly Direction Right = Direction.East; + private static Direction Port = Left; + private static Direction Starboard = Right; - [CommandProperty(AccessLevel.GameMaster)] - public Hold Hold { get; set; } + private int m_ClientSpeed; - [CommandProperty(AccessLevel.GameMaster)] - public TillerMan TillerMan { get; set; } + private bool m_Decaying; - [CommandProperty(AccessLevel.GameMaster)] - public Plank PPlank { get; set; } + private DateTime m_DecayTime; - [CommandProperty(AccessLevel.GameMaster)] - public Plank SPlank { get; set; } + private Direction m_Facing; + private Timer m_MoveTimer; - [CommandProperty(AccessLevel.GameMaster)] - public Mobile Owner { get; set; } + private string m_ShipName; - [CommandProperty(AccessLevel.GameMaster)] - public Direction Facing - { - get => m_Facing; - set => SetFacing(value); - } + private Timer m_TurnTimer; - [CommandProperty(AccessLevel.GameMaster)] - public Direction Moving { get; set; } + public BaseBoat() : base(0x0) + { + m_DecayTime = DateTime.UtcNow + BoatDecayDelay; - [CommandProperty(AccessLevel.GameMaster)] - public bool IsMoving => m_MoveTimer != null; + TillerMan = new TillerMan(this); + Hold = new Hold(this); - [CommandProperty(AccessLevel.GameMaster)] - public int Speed { get; set; } + PPlank = new Plank(this, PlankSide.Port, 0); + SPlank = new Plank(this, PlankSide.Starboard, 0); - [CommandProperty(AccessLevel.GameMaster)] - public bool Anchored { get; set; } + PPlank.MoveToWorld(new Point3D(X + PortOffset.X, Y + PortOffset.Y, Z), Map); + SPlank.MoveToWorld(new Point3D(X + StarboardOffset.X, Y + StarboardOffset.Y, Z), Map); - [CommandProperty(AccessLevel.GameMaster)] - public string ShipName - { - get => m_ShipName; - set - { - m_ShipName = value; - TillerMan?.InvalidateProperties(); - } - } + Facing = Direction.North; - [CommandProperty(AccessLevel.GameMaster)] - public BoatOrder Order { get; set; } + NextNavPoint = -1; - [CommandProperty(AccessLevel.GameMaster)] - public MapItem MapItem { get; set; } + Movable = false; - [CommandProperty(AccessLevel.GameMaster)] - public int NextNavPoint { get; set; } + Boats.Add(this); + } - [CommandProperty(AccessLevel.GameMaster)] - public DateTime TimeOfDecay - { - get => m_DecayTime; - set - { - m_DecayTime = value; - TillerMan?.InvalidateProperties(); - } - } + public BaseBoat(Serial serial) : base(serial) + { + } - public int Status - { - get - { - DateTime start = TimeOfDecay - BoatDecayDelay; + [CommandProperty(AccessLevel.GameMaster)] + public Hold Hold { get; set; } - if (DateTime.UtcNow - start < TimeSpan.FromHours(1.0)) - return 1043010; // This structure is like new. + [CommandProperty(AccessLevel.GameMaster)] + public TillerMan TillerMan { get; set; } - if (DateTime.UtcNow - start < TimeSpan.FromDays(2.0)) - return 1043011; // This structure is slightly worn. + [CommandProperty(AccessLevel.GameMaster)] + public Plank PPlank { get; set; } - if (DateTime.UtcNow - start < TimeSpan.FromDays(3.0)) - return 1043012; // This structure is somewhat worn. + [CommandProperty(AccessLevel.GameMaster)] + public Plank SPlank { get; set; } - if (DateTime.UtcNow - start < TimeSpan.FromDays(4.0)) - return 1043013; // This structure is fairly worn. + [CommandProperty(AccessLevel.GameMaster)] + public Mobile Owner { get; set; } - if (DateTime.UtcNow - start < TimeSpan.FromDays(5.0)) - return 1043014; // This structure is greatly worn. + [CommandProperty(AccessLevel.GameMaster)] + public Direction Facing + { + get => m_Facing; + set => SetFacing(value); + } - return 1043015; // This structure is in danger of collapsing. - } - } + [CommandProperty(AccessLevel.GameMaster)] + public Direction Moving { get; set; } - public virtual int NorthID => 0; - public virtual int EastID => 0; - public virtual int SouthID => 0; - public virtual int WestID => 0; + [CommandProperty(AccessLevel.GameMaster)] + public bool IsMoving => m_MoveTimer != null; - public virtual int HoldDistance => 0; - public virtual int TillerManDistance => 0; - public virtual Point2D StarboardOffset => Point2D.Zero; - public virtual Point2D PortOffset => Point2D.Zero; - public virtual Point3D MarkOffset => Point3D.Zero; + [CommandProperty(AccessLevel.GameMaster)] + public int Speed { get; set; } - public virtual BaseDockedBoat DockedBoat => null; + [CommandProperty(AccessLevel.GameMaster)] + public bool Anchored { get; set; } - public static List Boats { get; } = new List(); - - /* - * Intervals: - * drift forward - * fast | 0.25| 0.25 - * slow | 0.50| 0.50 - * - * Speed: - * drift forward - * fast | 0x4| 0x4 - * slow | 0x3| 0x3 - * - * Tiles (per interval): - * drift forward - * fast | 1| 1 - * slow | 1| 1 - * - * 'walking' in piloting mode has a 1s interval, speed 0x2 - */ - - private static bool NewBoatMovement => Core.HS; - - public override bool HandlesOnSpeech => true; - - public static BaseBoat FindBoatAt(IPoint2D loc, Map map) - { - Sector sector = map.GetSector(loc); - - for (int i = 0; i < sector.Multis.Count; i++) - if (sector.Multis[i] is BaseBoat boat && boat.Contains(loc.X, loc.Y)) - return boat; - - return null; - } - - public Point3D GetRotatedLocation(int x, int y) - { - Point3D p = new Point3D(X + x, Y + y, Z); - - return Rotate(p, (int)m_Facing / 2); - } - - public void UpdateComponents() - { - if (PPlank != null) - { - PPlank.MoveToWorld(GetRotatedLocation(PortOffset.X, PortOffset.Y), Map); - PPlank.SetFacing(m_Facing); - } - - if (SPlank != null) - { - SPlank.MoveToWorld(GetRotatedLocation(StarboardOffset.X, StarboardOffset.Y), Map); - SPlank.SetFacing(m_Facing); - } - - int xOffset = 0, yOffset = 0; - Movement.Movement.Offset(m_Facing, ref xOffset, ref yOffset); - - if (TillerMan != null) - { - TillerMan.Location = new Point3D(X + xOffset * TillerManDistance + (m_Facing == Direction.North ? 1 : 0), - Y + yOffset * TillerManDistance, TillerMan.Z); - TillerMan.SetFacing(m_Facing); - TillerMan.InvalidateProperties(); - } - - if (Hold != null) - { - Hold.Location = new Point3D(X + xOffset * HoldDistance, Y + yOffset * HoldDistance, Hold.Z); - Hold.SetFacing(m_Facing); - } - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(3); - - writer.Write(MapItem); - writer.Write(NextNavPoint); - - writer.Write((int)m_Facing); - - writer.WriteDeltaTime(m_DecayTime); - - writer.Write(Owner); - writer.Write(PPlank); - writer.Write(SPlank); - writer.Write(TillerMan); - writer.Write(Hold); - writer.Write(Anchored); - writer.Write(m_ShipName); - - CheckDecay(); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 3: - { - MapItem = (MapItem)reader.ReadItem(); - NextNavPoint = reader.ReadInt(); - - goto case 2; - } - case 2: - { - m_Facing = (Direction)reader.ReadInt(); - - goto case 1; - } - case 1: - { - m_DecayTime = reader.ReadDeltaTime(); - - goto case 0; - } - case 0: - { - if (version < 3) - NextNavPoint = -1; - - if (version < 2) + [CommandProperty(AccessLevel.GameMaster)] + public string ShipName + { + get => m_ShipName; + set { - if (ItemID == NorthID) - m_Facing = Direction.North; - else if (ItemID == SouthID) - m_Facing = Direction.South; - else if (ItemID == EastID) - m_Facing = Direction.East; - else if (ItemID == WestID) - m_Facing = Direction.West; + m_ShipName = value; + TillerMan?.InvalidateProperties(); + } + } + + [CommandProperty(AccessLevel.GameMaster)] + public BoatOrder Order { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public MapItem MapItem { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public int NextNavPoint { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime TimeOfDecay + { + get => m_DecayTime; + set + { + m_DecayTime = value; + TillerMan?.InvalidateProperties(); + } + } + + public int Status + { + get + { + var start = TimeOfDecay - BoatDecayDelay; + + if (DateTime.UtcNow - start < TimeSpan.FromHours(1.0)) + return 1043010; // This structure is like new. + + if (DateTime.UtcNow - start < TimeSpan.FromDays(2.0)) + return 1043011; // This structure is slightly worn. + + if (DateTime.UtcNow - start < TimeSpan.FromDays(3.0)) + return 1043012; // This structure is somewhat worn. + + if (DateTime.UtcNow - start < TimeSpan.FromDays(4.0)) + return 1043013; // This structure is fairly worn. + + if (DateTime.UtcNow - start < TimeSpan.FromDays(5.0)) + return 1043014; // This structure is greatly worn. + + return 1043015; // This structure is in danger of collapsing. + } + } + + public virtual int NorthID => 0; + public virtual int EastID => 0; + public virtual int SouthID => 0; + public virtual int WestID => 0; + + public virtual int HoldDistance => 0; + public virtual int TillerManDistance => 0; + public virtual Point2D StarboardOffset => Point2D.Zero; + public virtual Point2D PortOffset => Point2D.Zero; + public virtual Point3D MarkOffset => Point3D.Zero; + + public virtual BaseDockedBoat DockedBoat => null; + + public static List Boats { get; } = new List(); + + /* + * Intervals: + * drift forward + * fast | 0.25| 0.25 + * slow | 0.50| 0.50 + * + * Speed: + * drift forward + * fast | 0x4| 0x4 + * slow | 0x3| 0x3 + * + * Tiles (per interval): + * drift forward + * fast | 1| 1 + * slow | 1| 1 + * + * 'walking' in piloting mode has a 1s interval, speed 0x2 + */ + + private static bool NewBoatMovement => Core.HS; + + public override bool HandlesOnSpeech => true; + + public override bool AllowsRelativeDrop => true; + + public static BaseBoat FindBoatAt(IPoint2D loc, Map map) + { + var sector = map.GetSector(loc); + + for (var i = 0; i < sector.Multis.Count; i++) + if (sector.Multis[i] is BaseBoat boat && boat.Contains(loc.X, loc.Y)) + return boat; + + return null; + } + + public Point3D GetRotatedLocation(int x, int y) + { + var p = new Point3D(X + x, Y + y, Z); + + return Rotate(p, (int)m_Facing / 2); + } + + public void UpdateComponents() + { + if (PPlank != null) + { + PPlank.MoveToWorld(GetRotatedLocation(PortOffset.X, PortOffset.Y), Map); + PPlank.SetFacing(m_Facing); } - Owner = reader.ReadMobile(); - PPlank = reader.ReadItem() as Plank; - SPlank = reader.ReadItem() as Plank; - TillerMan = reader.ReadItem() as TillerMan; - Hold = reader.ReadItem() as Hold; - Anchored = reader.ReadBool(); - m_ShipName = reader.ReadString(); - - if (version < 1) - Refresh(); - - break; - } - } - - Boats.Add(this); - } - - public void RemoveKeys(Mobile m) - { - uint keyValue = 0; - - if (PPlank != null) - keyValue = PPlank.KeyValue; - - if (keyValue == 0 && SPlank != null) - keyValue = SPlank.KeyValue; - - Key.RemoveKeys(m, keyValue); - } - - public uint CreateKeys(Mobile m) - { - uint value = Key.RandomValue(); - - Key packKey = new Key(KeyType.Gold, value, this); - Key bankKey = new Key(KeyType.Gold, value, this); - - packKey.MaxRange = 10; - bankKey.MaxRange = 10; - - packKey.Name = "a ship key"; - bankKey.Name = "a ship key"; - - BankBox box = m.BankBox; - - if (!box.TryDropItem(m, bankKey, false)) - bankKey.Delete(); - else - m.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502484); // A ship's key is now in my safety deposit box. - - if (m.AddToBackpack(packKey)) - m.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502485); // A ship's key is now in my backpack. - else - m.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502483); // A ship's key is now at my feet. - - return value; - } - - public override void OnAfterDelete() - { - TillerMan?.Delete(); - - Hold?.Delete(); - - PPlank?.Delete(); - - SPlank?.Delete(); - - m_TurnTimer?.Stop(); - - m_MoveTimer?.Stop(); - - Boats.Remove(this); - } - - public override void OnLocationChange(Point3D old) - { - if (TillerMan != null) - TillerMan.Location = new Point3D(X + (TillerMan.X - old.X), Y + (TillerMan.Y - old.Y), - Z + (TillerMan.Z - old.Z)); - - if (Hold != null) - Hold.Location = new Point3D(X + (Hold.X - old.X), Y + (Hold.Y - old.Y), Z + (Hold.Z - old.Z)); - - if (PPlank != null) - PPlank.Location = new Point3D(X + (PPlank.X - old.X), Y + (PPlank.Y - old.Y), Z + (PPlank.Z - old.Z)); - - if (SPlank != null) - SPlank.Location = new Point3D(X + (SPlank.X - old.X), Y + (SPlank.Y - old.Y), Z + (SPlank.Z - old.Z)); - } - - public override void OnMapChange() - { - if (TillerMan != null) - TillerMan.Map = Map; - - if (Hold != null) - Hold.Map = Map; - - if (PPlank != null) - PPlank.Map = Map; - - if (SPlank != null) - SPlank.Map = Map; - } - - public bool CanCommand(Mobile m) => true; - - public Point3D GetMarkedLocation() - { - Point3D p = new Point3D(X + MarkOffset.X, Y + MarkOffset.Y, Z + MarkOffset.Z); - - return Rotate(p, (int)m_Facing / 2); - } - - public bool CheckKey(uint keyValue) => SPlank?.KeyValue == keyValue || PPlank?.KeyValue == keyValue; - - public void Refresh() - { - m_DecayTime = DateTime.UtcNow + BoatDecayDelay; - - TillerMan?.InvalidateProperties(); - } - - public bool CheckDecay() - { - if (m_Decaying) - return true; - - if (!IsMoving && DateTime.UtcNow >= m_DecayTime) - { - new DecayTimer(this).Start(); - - m_Decaying = true; - - return true; - } - - return false; - } - - public bool LowerAnchor(bool message) - { - if (CheckDecay()) - return false; - - if (Anchored) - { - if (message) - TillerMan?.Say(501445); // Ar, the anchor was already dropped sir. - - return false; - } - - StopMove(false); - - Anchored = true; - - if (message) - TillerMan?.Say(501444); // Ar, anchor dropped sir. - - return true; - } - - public bool RaiseAnchor(bool message) - { - if (CheckDecay()) - return false; - - if (!Anchored) - { - if (message) - TillerMan?.Say(501447); // Ar, the anchor has not been dropped sir. - - return false; - } - - Anchored = false; - - if (message) - TillerMan?.Say(501446); // Ar, anchor raised sir. - - return true; - } - - public bool StartMove(Direction dir, bool fast) - { - if (CheckDecay()) - return false; - - bool drift = dir != Forward && dir != ForwardLeft && dir != ForwardRight; - TimeSpan interval = fast ? drift ? FastDriftInterval : FastInterval : drift ? SlowDriftInterval : SlowInterval; - int speed = fast ? drift ? FastDriftSpeed : FastSpeed : drift ? SlowDriftSpeed : SlowSpeed; - int clientSpeed = fast ? 0x4 : 0x3; - - if (StartMove(dir, speed, clientSpeed, interval, false, true)) - { - TillerMan?.Say(501429); // Aye aye sir. - - return true; - } - - return false; - } - - public bool OneMove(Direction dir) - { - if (CheckDecay()) - return false; - - bool drift = dir != Forward; - TimeSpan interval = drift ? FastDriftInterval : FastInterval; - int speed = drift ? FastDriftSpeed : FastSpeed; - - if (StartMove(dir, speed, 0x1, interval, true, true)) - { - TillerMan?.Say(501429); // Aye aye sir. - - return true; - } - - return false; - } - - public void BeginRename(Mobile from) - { - if (CheckDecay()) - return; - - if (from.AccessLevel < AccessLevel.GameMaster && from != Owner) - { - TillerMan?.Say(Utility.Random(1042876, - 4)); // Arr, don't do that! | Arr, leave me alone! | Arr, watch what thour'rt doing, matey! | Arr! Do that again and I’ll throw ye overhead! - - return; - } - - TillerMan?.Say(502580); // What dost thou wish to name thy ship? - - from.Prompt = new RenameBoatPrompt(this); - } - - public void EndRename(Mobile from, string newName) - { - if (Deleted || CheckDecay()) - return; - - if (from.AccessLevel < AccessLevel.GameMaster && from != Owner) - { - TillerMan?.Say(1042880); // Arr! Only the owner of the ship may change its name! - - return; - } - - if (!from.Alive) - { - TillerMan?.Say(502582); // You appear to be dead. - - return; - } - - Rename(newName.Trim().IsNullOrDefault(null)); - } - - public DryDockResult CheckDryDock(Mobile from) - { - if (CheckDecay()) - return DryDockResult.Decaying; - - if (!from.Alive) - return DryDockResult.Dead; - - Container pack = from.Backpack; - if ((SPlank == null || !Key.ContainsKey(pack, SPlank.KeyValue)) && - (PPlank == null || !Key.ContainsKey(pack, PPlank.KeyValue))) - return DryDockResult.NoKey; - - if (!Anchored) - return DryDockResult.NotAnchored; - - if (Hold != null && Hold.Items.Count > 0) - return DryDockResult.Hold; - - Map map = Map; - - if (map == null || map == Map.Internal) - return DryDockResult.Items; - - List ents = GetMovingEntities(); - - if (ents.Count >= 1) - return ents[0] is Mobile ? DryDockResult.Mobiles : DryDockResult.Items; - - return DryDockResult.Valid; - } - - public void BeginDryDock(Mobile from) - { - if (CheckDecay()) - return; - - DryDockResult result = CheckDryDock(from); - - if (result == DryDockResult.Dead) - from.SendLocalizedMessage(502493); // You appear to be dead. - else if (result == DryDockResult.NoKey) - from.SendLocalizedMessage(502494); // You must have a key to the ship to dock the boat. - else if (result == DryDockResult.NotAnchored) - from.SendLocalizedMessage(1010570); // You must lower the anchor to dock the boat. - else if (result == DryDockResult.Mobiles) - from.SendLocalizedMessage(502495); // You cannot dock the ship with beings on board! - else if (result == DryDockResult.Items) - from.SendLocalizedMessage(502496); // You cannot dock the ship with a cluttered deck. - else if (result == DryDockResult.Hold) - from.SendLocalizedMessage(502497); // Make sure your hold is empty, and try again! - else if (result == DryDockResult.Valid) - from.SendGump(new ConfirmDryDockGump(from, this)); - } - - public void EndDryDock(Mobile from) - { - if (Deleted || CheckDecay()) - return; - - DryDockResult result = CheckDryDock(from); - - if (result == DryDockResult.Dead) - from.SendLocalizedMessage(502493); // You appear to be dead. - else if (result == DryDockResult.NoKey) - from.SendLocalizedMessage(502494); // You must have a key to the ship to dock the boat. - else if (result == DryDockResult.NotAnchored) - from.SendLocalizedMessage(1010570); // You must lower the anchor to dock the boat. - else if (result == DryDockResult.Mobiles) - from.SendLocalizedMessage(502495); // You cannot dock the ship with beings on board! - else if (result == DryDockResult.Items) - from.SendLocalizedMessage(502496); // You cannot dock the ship with a cluttered deck. - else if (result == DryDockResult.Hold) - from.SendLocalizedMessage(502497); // Make sure your hold is empty, and try again! - - if (result != DryDockResult.Valid) - return; - - BaseDockedBoat boat = DockedBoat; - - if (boat == null) - return; - - RemoveKeys(from); - - from.AddToBackpack(boat); - Delete(); - } - - public void SetName(SpeechEventArgs e) - { - if (CheckDecay()) - return; - - if (e.Mobile.AccessLevel < AccessLevel.GameMaster && e.Mobile != Owner) - { - TillerMan?.Say(1042880); // Arr! Only the owner of the ship may change its name! - - return; - } - - if (!e.Mobile.Alive) - { - TillerMan?.Say(502582); // You appear to be dead. - - return; - } - - if (e.Speech.Length > 8) - Rename(e.Speech.Substring(8).Trim().IsNullOrDefault(null)); - } - - public void Rename(string newName) - { - if (CheckDecay()) - return; - - if (newName?.Length > 40) - newName = newName.Substring(0, 40); - - if (m_ShipName == newName) - { - TillerMan?.Say(502531); // Yes, sir. - - return; - } - - ShipName = newName; - - if (TillerMan != null && m_ShipName != null) - TillerMan.Say(1042885, m_ShipName); // This ship is now called the ~1_NEW_SHIP_NAME~. - else - TillerMan?.Say(502534); // This ship now has no name. - } - - public void RemoveName(Mobile m) - { - if (CheckDecay()) - return; - - if (m.AccessLevel < AccessLevel.GameMaster && m != Owner) - { - TillerMan?.Say(1042880); // Arr! Only the owner of the ship may change its name! - - return; - } - - if (!m.Alive) - { - TillerMan?.Say(502582); // You appear to be dead. - - return; - } - - if (m_ShipName == null) - { - TillerMan?.Say(502526); // Ar, this ship has no name. - - return; - } - - ShipName = null; - - TillerMan?.Say(502534); // This ship now has no name. - } - - public void GiveName(Mobile m) - { - if (TillerMan == null || CheckDecay()) - return; - - if (m_ShipName == null) - TillerMan.Say(502526); // Ar, this ship has no name. - else - TillerMan.Say(1042881, m_ShipName); // This is the ~1_BOAT_NAME~. - } - - public void GiveNavPoint() - { - if (TillerMan == null || CheckDecay()) - return; - - if (NextNavPoint < 0) - TillerMan.Say(1042882); // I have no current nav point. - else - TillerMan.Say(1042883, - (NextNavPoint + 1).ToString()); // My current destination navpoint is nav ~1_NAV_POINT_NUM~. - } - - public void AssociateMap(MapItem map) - { - if (CheckDecay()) - return; - - if (map is BlankMap) - { - TillerMan?.Say(502575); // Ar, that is not a map, tis but a blank piece of paper! - } - else if (map.Pins.Count == 0) - { - TillerMan?.Say(502576); // Arrrr, this map has no course on it! - } - else - { - StopMove(false); - - MapItem = map; - NextNavPoint = -1; - - TillerMan?.Say(502577); // A map! - } - } - - public bool StartCourse(string navPoint, bool single, bool message) - { - int number = -1; - - int start = -1; - for (int i = 0; i < navPoint.Length; i++) - if (char.IsDigit(navPoint[i])) - { - start = i; - break; - } - - if (start != -1) - { - string sNumber = navPoint.Substring(start); - - if (!int.TryParse(sNumber, out number)) - number = -1; - - if (number != -1) - { - number--; - - if (MapItem == null || number < 0 || number >= MapItem.Pins.Count) number = -1; - } - } - - if (number == -1) - { - if (message) - TillerMan?.Say(1042551); // I don't see that navpoint, sir. - - return false; - } - - NextNavPoint = number; - return StartCourse(single, message); - } - - public bool StartCourse(bool single, bool message) - { - if (CheckDecay()) - return false; - - if (Anchored) - { - if (message) - TillerMan?.Say(501419); // Ar, the anchor is down sir! - - return false; - } - - if (MapItem?.Deleted != false) - { - if (message) - TillerMan?.Say(502513); // I have seen no map, sir. - - return false; - } - - if (Map != MapItem.Map || !Contains(MapItem.GetWorldLocation())) - { - if (message) - TillerMan?.Say(502514); // The map is too far away from me, sir. - - return false; - } - - if ((Map != Map.Trammel && Map != Map.Felucca) || NextNavPoint < 0 || NextNavPoint >= MapItem.Pins.Count) - { - if (message) - TillerMan?.Say(1042551); // I don't see that navpoint, sir. - - return false; - } - - Speed = FastSpeed; - Order = single ? BoatOrder.Single : BoatOrder.Course; - - m_MoveTimer?.Stop(); - - m_MoveTimer = new MoveTimer(this, FastInterval, false); - m_MoveTimer.Start(); - - if (message) - TillerMan?.Say(501429); // Aye aye sir. - - return true; - } - - public override void OnSpeech(SpeechEventArgs e) - { - if (CheckDecay()) - return; - - Mobile from = e.Mobile; - - if (CanCommand(from) && Contains(from)) - for (int i = 0; i < e.Keywords.Length; ++i) - { - int keyword = e.Keywords[i]; - - if (keyword >= 0x42 && keyword <= 0x6B) - { - switch (keyword) + if (SPlank != null) { - case 0x42: - SetName(e); - break; - case 0x43: - RemoveName(e.Mobile); - break; - case 0x44: - GiveName(e.Mobile); - break; - case 0x45: - StartMove(Forward, true); - break; - case 0x46: - StartMove(Backward, true); - break; - case 0x47: - StartMove(Left, true); - break; - case 0x48: - StartMove(Right, true); - break; - case 0x4B: - StartMove(ForwardLeft, true); - break; - case 0x4C: - StartMove(ForwardRight, true); - break; - case 0x4D: - StartMove(BackwardLeft, true); - break; - case 0x4E: - StartMove(BackwardRight, true); - break; - case 0x4F: - StopMove(true); - break; - case 0x50: - StartMove(Left, false); - break; - case 0x51: - StartMove(Right, false); - break; - case 0x52: - StartMove(Forward, false); - break; - case 0x53: - StartMove(Backward, false); - break; - case 0x54: - StartMove(ForwardLeft, false); - break; - case 0x55: - StartMove(ForwardRight, false); - break; - case 0x56: - StartMove(BackwardRight, false); - break; - case 0x57: - StartMove(BackwardLeft, false); - break; - case 0x58: - OneMove(Left); - break; - case 0x59: - OneMove(Right); - break; - case 0x5A: - OneMove(Forward); - break; - case 0x5B: - OneMove(Backward); - break; - case 0x5C: - OneMove(ForwardLeft); - break; - case 0x5D: - OneMove(ForwardRight); - break; - case 0x5E: - OneMove(BackwardRight); - break; - case 0x5F: - OneMove(BackwardLeft); - break; - case 0x49: - case 0x65: - StartTurn(2, true); - break; // turn right - case 0x4A: - case 0x66: - StartTurn(-2, true); - break; // turn left - case 0x67: - StartTurn(-4, true); - break; // turn around, come about - case 0x68: - StartMove(Forward, true); - break; - case 0x69: - StopMove(true); - break; - case 0x6A: - LowerAnchor(true); - break; - case 0x6B: - RaiseAnchor(true); - break; - case 0x60: - GiveNavPoint(); - break; // nav - case 0x61: - NextNavPoint = 0; - StartCourse(false, true); - break; // start - case 0x62: - StartCourse(false, true); - break; // continue - case 0x63: - StartCourse(e.Speech, false, true); - break; // goto* - case 0x64: - StartCourse(e.Speech, true, true); - break; // single* + SPlank.MoveToWorld(GetRotatedLocation(StarboardOffset.X, StarboardOffset.Y), Map); + SPlank.SetFacing(m_Facing); } - break; - } - } - } + int xOffset = 0, yOffset = 0; + Movement.Movement.Offset(m_Facing, ref xOffset, ref yOffset); - public bool StartTurn(int offset, bool message) - { - if (CheckDecay()) - return false; - - if (Anchored) - { - if (message) - TillerMan.Say(501419); // Ar, the anchor is down sir! - - return false; - } - - if (m_MoveTimer != null && Order != BoatOrder.Move) - { - m_MoveTimer.Stop(); - m_MoveTimer = null; - } - - m_TurnTimer?.Stop(); - - m_TurnTimer = new TurnTimer(this, offset); - m_TurnTimer.Start(); - - if (message) - TillerMan?.Say(501429); // Aye aye sir. - - return true; - } - - public bool Turn(int offset, bool message) - { - if (m_TurnTimer != null) - { - m_TurnTimer.Stop(); - m_TurnTimer = null; - } - - if (CheckDecay()) - return false; - - if (Anchored) - { - if (message) - TillerMan.Say(501419); // Ar, the anchor is down sir! - - return false; - } - - if (SetFacing((Direction)((int)m_Facing + offset & 0x7))) return true; - if (message) - TillerMan.Say(501423); // Ar, can't turn sir. - - return false; - } - - public bool StartMove(Direction dir, int speed, int clientSpeed, TimeSpan interval, bool single, bool message) - { - if (CheckDecay()) - return false; - - if (Anchored) - { - if (message) - TillerMan?.Say(501419); // Ar, the anchor is down sir! - - return false; - } - - Moving = dir; - Speed = speed; - m_ClientSpeed = clientSpeed; - Order = BoatOrder.Move; - - m_MoveTimer?.Stop(); - - m_MoveTimer = new MoveTimer(this, interval, single); - m_MoveTimer.Start(); - - return true; - } - - public bool StopMove(bool message) - { - if (CheckDecay()) - return false; - - if (m_MoveTimer == null) - { - if (message) - TillerMan?.Say(501443); // Er, the ship is not moving sir. - - return false; - } - - Moving = Direction.North; - Speed = 0; - m_ClientSpeed = 0; - m_MoveTimer.Stop(); - m_MoveTimer = null; - - if (message) - TillerMan?.Say(501429); // Aye aye sir. - - return true; - } - - public bool CanFit(Point3D p, Map map, int itemID) - { - if (map == null || map == Map.Internal || Deleted || CheckDecay()) - return false; - - MultiComponentList newComponents = MultiData.GetComponents(itemID); - - for (int x = 0; x < newComponents.Width; ++x) - for (int y = 0; y < newComponents.Height; ++y) - { - int tx = p.X + newComponents.Min.X + x; - int ty = p.Y + newComponents.Min.Y + y; - - if (newComponents.Tiles[x][y].Length == 0 || Contains(tx, ty)) - continue; - - LandTile landTile = map.Tiles.GetLandTile(tx, ty); - StaticTile[] tiles = map.Tiles.GetStaticTiles(tx, ty, true); - - bool hasWater = landTile.Z == p.Z && - ((landTile.ID >= 168 && landTile.ID <= 171) || (landTile.ID >= 310 && landTile.ID <= 311)); - - // int z = p.Z; - - // int landZ = 0, landAvg = 0, landTop = 0; - - // map.GetAverageZ( tx, ty, ref landZ, ref landAvg, ref landTop ); - - // if (!landTile.Ignored && top > landZ && landTop > z) - // return false; - - for (int i = 0; i < tiles.Length; ++i) - { - StaticTile tile = tiles[i]; - bool isWater = tile.ID >= 0x1796 && tile.ID <= 0x17B2; - - if (tile.Z == p.Z && isWater) - hasWater = true; - else if (tile.Z >= p.Z && !isWater) - return false; - } - - if (!hasWater) - return false; - } - - IPooledEnumerable eable = map.GetItemsInBounds(new Rectangle2D(p.X + newComponents.Min.X, - p.Y + newComponents.Min.Y, newComponents.Width, newComponents.Height)); - - bool canFit = eable.All(item => - { - if (item is BaseMulti || item.ItemID > TileData.MaxItemValue || item.Z < p.Z || !item.Visible) - return true; - - int x = item.X - p.X + newComponents.Min.X; - int y = item.Y - p.Y + newComponents.Min.Y; - - return x >= 0 && x < newComponents.Width && y >= 0 && y < newComponents.Height && - newComponents.Tiles[x][y].Length == 0 || Contains(item); - }); - - eable.Free(); - return canFit; - } - - public Point3D Rotate(Point3D p, int count) - { - int rx = p.X - Location.X; - int ry = p.Y - Location.Y; - - for (int i = 0; i < count; ++i) - { - int temp = rx; - rx = -ry; - ry = temp; - } - - return new Point3D(Location.X + rx, Location.Y + ry, p.Z); - } - - public override bool Contains(int x, int y) => - base.Contains(x, y) || - (TillerMan?.X == x && y == TillerMan.Y) || - (Hold?.X == x && Hold.Y == y) || - (PPlank?.X == x && PPlank.Y == y) || - (SPlank?.X == x && SPlank.Y == y); - - public static bool IsValidLocation(Point3D p, Map map) - { - Rectangle2D[] wrap = GetWrapFor(map); - - for (int i = 0; i < wrap.Length; ++i) - if (wrap[i].Contains(p)) - return true; - - return false; - } - - public static Rectangle2D[] GetWrapFor(Map m) => m == Map.Ilshenar ? m_IlshWrap : m == Map.Tokuno ? m_TokunoWrap : m_BritWrap; - - public Direction GetMovementFor(int x, int y, out int maxSpeed) - { - int dx = x - X; - int dy = y - Y; - - int adx = Math.Abs(dx); - int ady = Math.Abs(dy); - - Direction dir = Utility.GetDirection(this, new Point2D(x, y)); - int iDir = (int)dir; - - // Compute the maximum distance we can travel without going too far away - if (iDir % 2 == 0) // North, East, South and West - maxSpeed = Math.Abs(adx - ady); - else // Right, Down, Left and Up - maxSpeed = Math.Min(adx, ady); - - return (Direction)(iDir - (int)Facing & 0x7); - } - - public bool DoMovement(bool message) - { - Direction dir; - int speed, clientSpeed; - - if (Order == BoatOrder.Move) - { - dir = Moving; - speed = Speed; - clientSpeed = m_ClientSpeed; - } - else if (MapItem?.Deleted != false) - { - if (message) - TillerMan?.Say(502513); // I have seen no map, sir. - - return false; - } - else if (Map != MapItem.Map || !Contains(MapItem.GetWorldLocation())) - { - if (message) - TillerMan?.Say(502514); // The map is too far away from me, sir. - - return false; - } - else if ((Map != Map.Trammel && Map != Map.Felucca) || NextNavPoint < 0 || NextNavPoint >= MapItem.Pins.Count) - { - if (message) - TillerMan?.Say(1042551); // I don't see that navpoint, sir. - - return false; - } - else - { - Point2D dest = MapItem.Pins[NextNavPoint]; - - MapItem.ConvertToWorld(dest.X, dest.Y, out int x, out int y); - - dir = GetMovementFor(x, y, out int maxSpeed); - - if (maxSpeed == 0) - { - if (message && Order == BoatOrder.Single) - TillerMan?.Say(1042874, - (NextNavPoint + 1).ToString()); // We have arrived at nav point ~1_POINT_NUM~ , sir. - - if (NextNavPoint + 1 < MapItem.Pins.Count) - { - NextNavPoint++; - - if (Order == BoatOrder.Course) + if (TillerMan != null) { - if (message) - TillerMan?.Say(1042875, - (NextNavPoint + 1).ToString()); // Heading to nav point ~1_POINT_NUM~, sir. + TillerMan.Location = new Point3D( + X + xOffset * TillerManDistance + (m_Facing == Direction.North ? 1 : 0), + Y + yOffset * TillerManDistance, + TillerMan.Z + ); + TillerMan.SetFacing(m_Facing); + TillerMan.InvalidateProperties(); + } - return true; + if (Hold != null) + { + Hold.Location = new Point3D(X + xOffset * HoldDistance, Y + yOffset * HoldDistance, Hold.Z); + Hold.SetFacing(m_Facing); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(3); + + writer.Write(MapItem); + writer.Write(NextNavPoint); + + writer.Write((int)m_Facing); + + writer.WriteDeltaTime(m_DecayTime); + + writer.Write(Owner); + writer.Write(PPlank); + writer.Write(SPlank); + writer.Write(TillerMan); + writer.Write(Hold); + writer.Write(Anchored); + writer.Write(m_ShipName); + + CheckDecay(); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 3: + { + MapItem = (MapItem)reader.ReadItem(); + NextNavPoint = reader.ReadInt(); + + goto case 2; + } + case 2: + { + m_Facing = (Direction)reader.ReadInt(); + + goto case 1; + } + case 1: + { + m_DecayTime = reader.ReadDeltaTime(); + + goto case 0; + } + case 0: + { + if (version < 3) + NextNavPoint = -1; + + if (version < 2) + { + if (ItemID == NorthID) + m_Facing = Direction.North; + else if (ItemID == SouthID) + m_Facing = Direction.South; + else if (ItemID == EastID) + m_Facing = Direction.East; + else if (ItemID == WestID) + m_Facing = Direction.West; + } + + Owner = reader.ReadMobile(); + PPlank = reader.ReadItem() as Plank; + SPlank = reader.ReadItem() as Plank; + TillerMan = reader.ReadItem() as TillerMan; + Hold = reader.ReadItem() as Hold; + Anchored = reader.ReadBool(); + m_ShipName = reader.ReadString(); + + if (version < 1) + Refresh(); + + break; + } + } + + Boats.Add(this); + } + + public void RemoveKeys(Mobile m) + { + uint keyValue = 0; + + if (PPlank != null) + keyValue = PPlank.KeyValue; + + if (keyValue == 0 && SPlank != null) + keyValue = SPlank.KeyValue; + + Key.RemoveKeys(m, keyValue); + } + + public uint CreateKeys(Mobile m) + { + var value = Key.RandomValue(); + + var packKey = new Key(KeyType.Gold, value, this); + var bankKey = new Key(KeyType.Gold, value, this); + + packKey.MaxRange = 10; + bankKey.MaxRange = 10; + + packKey.Name = "a ship key"; + bankKey.Name = "a ship key"; + + var box = m.BankBox; + + if (!box.TryDropItem(m, bankKey, false)) + bankKey.Delete(); + else + m.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502484); // A ship's key is now in my safety deposit box. + + if (m.AddToBackpack(packKey)) + m.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502485); // A ship's key is now in my backpack. + else + m.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502483); // A ship's key is now at my feet. + + return value; + } + + public override void OnAfterDelete() + { + TillerMan?.Delete(); + + Hold?.Delete(); + + PPlank?.Delete(); + + SPlank?.Delete(); + + m_TurnTimer?.Stop(); + + m_MoveTimer?.Stop(); + + Boats.Remove(this); + } + + public override void OnLocationChange(Point3D old) + { + if (TillerMan != null) + TillerMan.Location = new Point3D( + X + (TillerMan.X - old.X), + Y + (TillerMan.Y - old.Y), + Z + (TillerMan.Z - old.Z) + ); + + if (Hold != null) + Hold.Location = new Point3D(X + (Hold.X - old.X), Y + (Hold.Y - old.Y), Z + (Hold.Z - old.Z)); + + if (PPlank != null) + PPlank.Location = new Point3D(X + (PPlank.X - old.X), Y + (PPlank.Y - old.Y), Z + (PPlank.Z - old.Z)); + + if (SPlank != null) + SPlank.Location = new Point3D(X + (SPlank.X - old.X), Y + (SPlank.Y - old.Y), Z + (SPlank.Z - old.Z)); + } + + public override void OnMapChange() + { + if (TillerMan != null) + TillerMan.Map = Map; + + if (Hold != null) + Hold.Map = Map; + + if (PPlank != null) + PPlank.Map = Map; + + if (SPlank != null) + SPlank.Map = Map; + } + + public bool CanCommand(Mobile m) => true; + + public Point3D GetMarkedLocation() + { + var p = new Point3D(X + MarkOffset.X, Y + MarkOffset.Y, Z + MarkOffset.Z); + + return Rotate(p, (int)m_Facing / 2); + } + + public bool CheckKey(uint keyValue) => SPlank?.KeyValue == keyValue || PPlank?.KeyValue == keyValue; + + public void Refresh() + { + m_DecayTime = DateTime.UtcNow + BoatDecayDelay; + + TillerMan?.InvalidateProperties(); + } + + public bool CheckDecay() + { + if (m_Decaying) + return true; + + if (!IsMoving && DateTime.UtcNow >= m_DecayTime) + { + new DecayTimer(this).Start(); + + m_Decaying = true; + + return true; } return false; - } - - NextNavPoint = -1; - - if (message && Order == BoatOrder.Course) - TillerMan?.Say(502515); // The course is completed, sir. - - return false; } - if (dir == Left || dir == BackwardLeft || dir == Backward) - return Turn(-2, true); - if (dir == Right || dir == BackwardRight) - return Turn(2, true); - - speed = Math.Min(Speed, maxSpeed); - clientSpeed = 0x4; - } - - return Move(dir, speed, clientSpeed, true); - } - - public bool Move(Direction dir, int speed, int clientSpeed, bool message) - { - Map map = Map; - - if (map == null || Deleted || CheckDecay()) - return false; - - if (Anchored) - { - if (message) - TillerMan?.Say(501419); // Ar, the anchor is down sir! - - return false; - } - - int rx = 0, ry = 0; - Direction d = (Direction)((int)m_Facing + (int)dir & 0x7); - Movement.Movement.Offset(d, ref rx, ref ry); - - for (int i = 1; i <= speed; ++i) - if (!CanFit(new Point3D(X + i * rx, Y + i * ry, Z), Map, ItemID)) + public bool LowerAnchor(bool message) { - if (i == 1) - { + if (CheckDecay()) + return false; + + if (Anchored) + { + if (message) + TillerMan?.Say(501445); // Ar, the anchor was already dropped sir. + + return false; + } + + StopMove(false); + + Anchored = true; + if (message) - TillerMan?.Say(501424); // Ar, we've stopped sir. + TillerMan?.Say(501444); // Ar, anchor dropped sir. - return false; - } - - speed = i - 1; - break; + return true; } - int xOffset = speed * rx; - int yOffset = speed * ry; - - int newX = X + xOffset; - int newY = Y + yOffset; - - Rectangle2D[] wrap = GetWrapFor(map); - - for (int i = 0; i < wrap.Length; ++i) - { - Rectangle2D rect = wrap[i]; - - if (rect.Contains(new Point2D(X, Y)) && !rect.Contains(new Point2D(newX, newY))) + public bool RaiseAnchor(bool message) { - if (newX < rect.X) - newX = rect.X + rect.Width - 1; - else if (newX >= rect.X + rect.Width) - newX = rect.X; + if (CheckDecay()) + return false; - if (newY < rect.Y) - newY = rect.Y + rect.Height - 1; - else if (newY >= rect.Y + rect.Height) - newY = rect.Y; - - for (int j = 1; j <= speed; ++j) - if (!CanFit(new Point3D(newX + j * rx, newY + j * ry, Z), Map, ItemID)) + if (!Anchored) { - if (message) - TillerMan?.Say(501424); // Ar, we've stopped sir. + if (message) + TillerMan?.Say(501447); // Ar, the anchor has not been dropped sir. - return false; + return false; } - xOffset = newX - X; - yOffset = newY - Y; + Anchored = false; + + if (message) + TillerMan?.Say(501446); // Ar, anchor raised sir. + + return true; } - } - if (!NewBoatMovement || Math.Abs(xOffset) > 1 || Math.Abs(yOffset) > 1) - { - Teleport(xOffset, yOffset, 0); - } - else - { - List toMove = GetMovingEntities(); - - SafeAdd(TillerMan, toMove); - SafeAdd(Hold, toMove); - SafeAdd(PPlank, toMove); - SafeAdd(SPlank, toMove); - - // Packet must be sent before actual locations are changed - foreach (NetState ns in Map.GetClientsInRange(Location, GetMaxUpdateRange())) + public bool StartMove(Direction dir, bool fast) { - Mobile m = ns.Mobile; + if (CheckDecay()) + return false; - if (ns.HighSeas && m.CanSee(this) && m.InRange(Location, GetUpdateRange(m))) - ns.Send(new MoveBoatHS(m, this, d, clientSpeed, toMove, xOffset, yOffset)); + var drift = dir != Forward && dir != ForwardLeft && dir != ForwardRight; + var interval = fast ? drift ? FastDriftInterval : FastInterval : + drift ? SlowDriftInterval : SlowInterval; + var speed = fast ? drift ? FastDriftSpeed : FastSpeed : + drift ? SlowDriftSpeed : SlowSpeed; + var clientSpeed = fast ? 0x4 : 0x3; + + if (StartMove(dir, speed, clientSpeed, interval, false, true)) + { + TillerMan?.Say(501429); // Aye aye sir. + + return true; + } + + return false; } - foreach (IEntity e in toMove) - if (e is Item item) - { - item.NoMoveHS = true; - - if (!(item is TillerMan || item is Hold || item is Plank)) - item.Location = new Point3D(item.X + xOffset, item.Y + yOffset, item.Z); - } - else if (e is Mobile m) - { - m.NoMoveHS = true; - m.Location = new Point3D(m.X + xOffset, m.Y + yOffset, m.Z); - } - - NoMoveHS = true; - Location = new Point3D(X + xOffset, Y + yOffset, Z); - - foreach (IEntity e in toMove) - if (e is Item item) - item.NoMoveHS = false; - else if (e is Mobile mobile) - mobile.NoMoveHS = false; - - NoMoveHS = false; - } - - return true; - } - - private static void SafeAdd(Item item, List toMove) - { - if (item != null) - toMove.Add(item); - } - - public void Teleport(int xOffset, int yOffset, int zOffset) - { - List toMove = GetMovingEntities(); - - for (int i = 0; i < toMove.Count; ++i) - { - IEntity e = toMove[i]; - - if (e is Item item) - item.Location = new Point3D(item.X + xOffset, item.Y + yOffset, item.Z + zOffset); - else if (e is Mobile m) m.Location = new Point3D(m.X + xOffset, m.Y + yOffset, m.Z + zOffset); - } - - Location = new Point3D(X + xOffset, Y + yOffset, Z + zOffset); - } - - public List GetMovingEntities() - { - List list = new List(); - - Map map = Map; - - if (map == null || map == Map.Internal) - return list; - - MultiComponentList mcl = Components; - - foreach (IEntity o in map.GetObjectsInBounds(new Rectangle2D(X + mcl.Min.X, Y + mcl.Min.Y, mcl.Width, mcl.Height))) - { - if (o == this || o is TillerMan || o is Hold || o is Plank) - continue; - - if (o is Item item) + public bool OneMove(Direction dir) { - if (Contains(item) && item.Visible && item.Z >= Z) - list.Add(item); + if (CheckDecay()) + return false; + + var drift = dir != Forward; + var interval = drift ? FastDriftInterval : FastInterval; + var speed = drift ? FastDriftSpeed : FastSpeed; + + if (StartMove(dir, speed, 0x1, interval, true, true)) + { + TillerMan?.Say(501429); // Aye aye sir. + + return true; + } + + return false; } - else if (o is Mobile m) + + public void BeginRename(Mobile from) { - if (Contains(m)) - list.Add(m); + if (CheckDecay()) + return; + + if (from.AccessLevel < AccessLevel.GameMaster && from != Owner) + { + TillerMan?.Say( + Utility.Random( + 1042876, + 4 + ) + ); // Arr, don't do that! | Arr, leave me alone! | Arr, watch what thour'rt doing, matey! | Arr! Do that again and I’ll throw ye overhead! + + return; + } + + TillerMan?.Say(502580); // What dost thou wish to name thy ship? + + from.Prompt = new RenameBoatPrompt(this); } - } - return list; - } - - public bool SetFacing(Direction facing) - { - if (Parent != null || Map == null) - return false; - - if (CheckDecay()) - return false; - - if (Map != Map.Internal) - switch (facing) + public void EndRename(Mobile from, string newName) { - case Direction.North: - if (!CanFit(Location, Map, NorthID)) return false; - break; - case Direction.East: - if (!CanFit(Location, Map, EastID)) return false; - break; - case Direction.South: - if (!CanFit(Location, Map, SouthID)) return false; - break; - case Direction.West: - if (!CanFit(Location, Map, WestID)) return false; - break; + if (Deleted || CheckDecay()) + return; + + if (from.AccessLevel < AccessLevel.GameMaster && from != Owner) + { + TillerMan?.Say(1042880); // Arr! Only the owner of the ship may change its name! + + return; + } + + if (!from.Alive) + { + TillerMan?.Say(502582); // You appear to be dead. + + return; + } + + Rename(newName.Trim().IsNullOrDefault(null)); } - Direction old = m_Facing; - - m_Facing = facing; - - TillerMan?.SetFacing(facing); - - Hold?.SetFacing(facing); - - PPlank?.SetFacing(facing); - - SPlank?.SetFacing(facing); - - List toMove = GetMovingEntities(); - - toMove.Add(PPlank); - toMove.Add(SPlank); - - int xOffset = 0, yOffset = 0; - Movement.Movement.Offset(facing, ref xOffset, ref yOffset); - - if (TillerMan != null) - TillerMan.Location = new Point3D(X + xOffset * TillerManDistance + (facing == Direction.North ? 1 : 0), - Y + yOffset * TillerManDistance, TillerMan.Z); - - if (Hold != null) - Hold.Location = new Point3D(X + xOffset * HoldDistance, Y + yOffset * HoldDistance, Hold.Z); - - int count = m_Facing - old & 0x7; - count /= 2; - - for (int i = 0; i < toMove.Count; ++i) - { - IEntity e = toMove[i]; - - if (e is Item item) + public DryDockResult CheckDryDock(Mobile from) { - item.Location = Rotate(item.Location, count); + if (CheckDecay()) + return DryDockResult.Decaying; + + if (!from.Alive) + return DryDockResult.Dead; + + var pack = from.Backpack; + if ((SPlank == null || !Key.ContainsKey(pack, SPlank.KeyValue)) && + (PPlank == null || !Key.ContainsKey(pack, PPlank.KeyValue))) + return DryDockResult.NoKey; + + if (!Anchored) + return DryDockResult.NotAnchored; + + if (Hold != null && Hold.Items.Count > 0) + return DryDockResult.Hold; + + var map = Map; + + if (map == null || map == Map.Internal) + return DryDockResult.Items; + + var ents = GetMovingEntities(); + + if (ents.Count >= 1) + return ents[0] is Mobile ? DryDockResult.Mobiles : DryDockResult.Items; + + return DryDockResult.Valid; } - else if (e is Mobile m) + + public void BeginDryDock(Mobile from) { - m.Direction = m.Direction - old + facing & Direction.Mask; - m.Location = Rotate(m.Location, count); + if (CheckDecay()) + return; + + var result = CheckDryDock(from); + + if (result == DryDockResult.Dead) + from.SendLocalizedMessage(502493); // You appear to be dead. + else if (result == DryDockResult.NoKey) + from.SendLocalizedMessage(502494); // You must have a key to the ship to dock the boat. + else if (result == DryDockResult.NotAnchored) + from.SendLocalizedMessage(1010570); // You must lower the anchor to dock the boat. + else if (result == DryDockResult.Mobiles) + from.SendLocalizedMessage(502495); // You cannot dock the ship with beings on board! + else if (result == DryDockResult.Items) + from.SendLocalizedMessage(502496); // You cannot dock the ship with a cluttered deck. + else if (result == DryDockResult.Hold) + from.SendLocalizedMessage(502497); // Make sure your hold is empty, and try again! + else if (result == DryDockResult.Valid) + from.SendGump(new ConfirmDryDockGump(from, this)); } - } - ItemID = facing switch - { - Direction.North => NorthID, - Direction.East => EastID, - Direction.South => SouthID, - Direction.West => WestID, - _ => ItemID - }; - - return true; - } - - public static void UpdateAllComponents() - { - for (int i = Boats.Count - 1; i >= 0; --i) - Boats[i].UpdateComponents(); - } - - public static void Initialize() - { - new UpdateAllTimer().Start(); - EventSink.WorldSave += EventSink_WorldSave; - } - - private static void EventSink_WorldSave(bool message) - { - new UpdateAllTimer().Start(); - } - - private class DecayTimer : Timer - { - private readonly BaseBoat m_Boat; - private int m_Count; - - public DecayTimer(BaseBoat boat) : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(5.0)) - { - m_Boat = boat; - - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - if (m_Count == 5) + public void EndDryDock(Mobile from) { - m_Boat.Delete(); - Stop(); + if (Deleted || CheckDecay()) + return; + + var result = CheckDryDock(from); + + if (result == DryDockResult.Dead) + from.SendLocalizedMessage(502493); // You appear to be dead. + else if (result == DryDockResult.NoKey) + from.SendLocalizedMessage(502494); // You must have a key to the ship to dock the boat. + else if (result == DryDockResult.NotAnchored) + from.SendLocalizedMessage(1010570); // You must lower the anchor to dock the boat. + else if (result == DryDockResult.Mobiles) + from.SendLocalizedMessage(502495); // You cannot dock the ship with beings on board! + else if (result == DryDockResult.Items) + from.SendLocalizedMessage(502496); // You cannot dock the ship with a cluttered deck. + else if (result == DryDockResult.Hold) + from.SendLocalizedMessage(502497); // Make sure your hold is empty, and try again! + + if (result != DryDockResult.Valid) + return; + + var boat = DockedBoat; + + if (boat == null) + return; + + RemoveKeys(from); + + from.AddToBackpack(boat); + Delete(); } - else + + public void SetName(SpeechEventArgs e) { - m_Boat.Location = new Point3D(m_Boat.X, m_Boat.Y, m_Boat.Z - 1); + if (CheckDecay()) + return; - m_Boat.TillerMan?.Say(1007168 + m_Count); + if (e.Mobile.AccessLevel < AccessLevel.GameMaster && e.Mobile != Owner) + { + TillerMan?.Say(1042880); // Arr! Only the owner of the ship may change its name! - ++m_Count; + return; + } + + if (!e.Mobile.Alive) + { + TillerMan?.Say(502582); // You appear to be dead. + + return; + } + + if (e.Speech.Length > 8) + Rename(e.Speech.Substring(8).Trim().IsNullOrDefault(null)); } - } - } - private class TurnTimer : Timer - { - private readonly BaseBoat m_Boat; - private readonly int m_Offset; - - public TurnTimer(BaseBoat boat, int offset) : base(TimeSpan.FromSeconds(0.5)) - { - m_Boat = boat; - m_Offset = offset; - - Priority = TimerPriority.TenMS; - } - - protected override void OnTick() - { - if (!m_Boat.Deleted) - m_Boat.Turn(m_Offset, true); - } - } - - private class MoveTimer : Timer - { - private readonly BaseBoat m_Boat; - - public MoveTimer(BaseBoat boat, TimeSpan interval, bool single) : base(interval, interval, single ? 1 : 0) - { - m_Boat = boat; - Priority = TimerPriority.TwentyFiveMS; - } - - protected override void OnTick() - { - if (!m_Boat.DoMovement(true)) - m_Boat.StopMove(false); - } - } - - public class UpdateAllTimer : Timer - { - public UpdateAllTimer() : base(TimeSpan.FromSeconds(1.0)) - { - } - - protected override void OnTick() - { - UpdateAllComponents(); - } - } - - public override bool AllowsRelativeDrop => true; - - /* - * OSI sends the 0xF7 packet instead, holding 0xF3 packets - * for every entity on the boat. Though, the regular 0xF3 - * packets are still being sent as well as entities come - * into sight. Do we really need it? - */ - /* - protected override Packet GetWorldPacketFor( NetState state ) - { - if (NewBoatMovement && state.HighSeas) - return new DisplayBoatHS( state.Mobile, this ); - else - return base.GetWorldPacketFor( state ); - } - */ - - public sealed class MoveBoatHS : Packet - { - public MoveBoatHS(Mobile beholder, BaseBoat boat, Direction d, int speed, List ents, int xOffset, - int yOffset) - : base(0xF6) - { - EnsureCapacity(3 + 15 + ents.Count * 10); - - Stream.Write(boat.Serial); - Stream.Write((byte)speed); - Stream.Write((byte)d); - Stream.Write((byte)boat.Facing); - Stream.Write((short)(boat.X + xOffset)); - Stream.Write((short)(boat.Y + yOffset)); - Stream.Write((short)boat.Z); - Stream.Write((short)0); // count placeholder - - int count = 0; - - foreach (IEntity ent in ents) + public void Rename(string newName) { - if (!beholder.CanSee(ent)) - continue; + if (CheckDecay()) + return; - Stream.Write(ent.Serial); - Stream.Write((short)(ent.X + xOffset)); - Stream.Write((short)(ent.Y + yOffset)); - Stream.Write((short)ent.Z); - ++count; + if (newName?.Length > 40) + newName = newName.Substring(0, 40); + + if (m_ShipName == newName) + { + TillerMan?.Say(502531); // Yes, sir. + + return; + } + + ShipName = newName; + + if (TillerMan != null && m_ShipName != null) + TillerMan.Say(1042885, m_ShipName); // This ship is now called the ~1_NEW_SHIP_NAME~. + else + TillerMan?.Say(502534); // This ship now has no name. } - Stream.Seek(16, SeekOrigin.Begin); - Stream.Write((short)count); - } - } - - public sealed class DisplayBoatHS : Packet - { - public DisplayBoatHS(Mobile beholder, BaseBoat boat) - : base(0xF7) - { - List ents = boat.GetMovingEntities(); - - SafeAdd(boat.TillerMan, ents); - SafeAdd(boat.Hold, ents); - SafeAdd(boat.PPlank, ents); - SafeAdd(boat.SPlank, ents); - - ents.Add(boat); - - EnsureCapacity(3 + 2 + ents.Count * 26); - - Stream.Write((short)0); // count placeholder - - int count = 0; - - foreach (IEntity ent in ents) + public void RemoveName(Mobile m) { - if (!beholder.CanSee(ent)) - continue; + if (CheckDecay()) + return; - // Embedded WorldItemHS packets - Stream.Write((byte)0xF3); - Stream.Write((short)0x1); + if (m.AccessLevel < AccessLevel.GameMaster && m != Owner) + { + TillerMan?.Say(1042880); // Arr! Only the owner of the ship may change its name! - if (ent is BaseMulti bm) - { - Stream.Write((byte)0x02); - Stream.Write(bm.Serial); - // TODO: Mask no longer needed, merge with Item case? - Stream.Write((ushort)(bm.ItemID & 0x3FFF)); - Stream.Write((byte)0); + return; + } - Stream.Write((short)bm.Amount); - Stream.Write((short)bm.Amount); + if (!m.Alive) + { + TillerMan?.Say(502582); // You appear to be dead. - Stream.Write((short)(bm.X & 0x7FFF)); - Stream.Write((short)(bm.Y & 0x3FFF)); - Stream.Write((sbyte)bm.Z); + return; + } - Stream.Write((byte)bm.Light); - Stream.Write((short)bm.Hue); - Stream.Write((byte)bm.GetPacketFlags()); - } - else if (ent is Mobile m) - { - Stream.Write((byte)0x01); - Stream.Write(m.Serial); - Stream.Write((short)m.Body); - Stream.Write((byte)0); + if (m_ShipName == null) + { + TillerMan?.Say(502526); // Ar, this ship has no name. - Stream.Write((short)1); - Stream.Write((short)1); + return; + } - Stream.Write((short)(m.X & 0x7FFF)); - Stream.Write((short)(m.Y & 0x3FFF)); - Stream.Write((sbyte)m.Z); + ShipName = null; - Stream.Write((byte)m.Direction); - Stream.Write((short)m.Hue); - Stream.Write((byte)m.GetPacketFlags()); - } - else if (ent is Item item) - { - Stream.Write((byte)0x00); - Stream.Write(item.Serial); - Stream.Write((ushort)(item.ItemID & 0xFFFF)); - Stream.Write((byte)0); - - Stream.Write((short)item.Amount); - Stream.Write((short)item.Amount); - - Stream.Write((short)(item.X & 0x7FFF)); - Stream.Write((short)(item.Y & 0x3FFF)); - Stream.Write((sbyte)item.Z); - - Stream.Write((byte)item.Light); - Stream.Write((short)item.Hue); - Stream.Write((byte)item.GetPacketFlags()); - } - - Stream.Write((short)0x00); - ++count; + TillerMan?.Say(502534); // This ship now has no name. } - Stream.Seek(3, SeekOrigin.Begin); - Stream.Write((short)count); - } + public void GiveName(Mobile m) + { + if (TillerMan == null || CheckDecay()) + return; + + if (m_ShipName == null) + TillerMan.Say(502526); // Ar, this ship has no name. + else + TillerMan.Say(1042881, m_ShipName); // This is the ~1_BOAT_NAME~. + } + + public void GiveNavPoint() + { + if (TillerMan == null || CheckDecay()) + return; + + if (NextNavPoint < 0) + TillerMan.Say(1042882); // I have no current nav point. + else + TillerMan.Say( + 1042883, + (NextNavPoint + 1).ToString() + ); // My current destination navpoint is nav ~1_NAV_POINT_NUM~. + } + + public void AssociateMap(MapItem map) + { + if (CheckDecay()) + return; + + if (map is BlankMap) + { + TillerMan?.Say(502575); // Ar, that is not a map, tis but a blank piece of paper! + } + else if (map.Pins.Count == 0) + { + TillerMan?.Say(502576); // Arrrr, this map has no course on it! + } + else + { + StopMove(false); + + MapItem = map; + NextNavPoint = -1; + + TillerMan?.Say(502577); // A map! + } + } + + public bool StartCourse(string navPoint, bool single, bool message) + { + var number = -1; + + var start = -1; + for (var i = 0; i < navPoint.Length; i++) + if (char.IsDigit(navPoint[i])) + { + start = i; + break; + } + + if (start != -1) + { + var sNumber = navPoint.Substring(start); + + if (!int.TryParse(sNumber, out number)) + number = -1; + + if (number != -1) + { + number--; + + if (MapItem == null || number < 0 || number >= MapItem.Pins.Count) number = -1; + } + } + + if (number == -1) + { + if (message) + TillerMan?.Say(1042551); // I don't see that navpoint, sir. + + return false; + } + + NextNavPoint = number; + return StartCourse(single, message); + } + + public bool StartCourse(bool single, bool message) + { + if (CheckDecay()) + return false; + + if (Anchored) + { + if (message) + TillerMan?.Say(501419); // Ar, the anchor is down sir! + + return false; + } + + if (MapItem?.Deleted != false) + { + if (message) + TillerMan?.Say(502513); // I have seen no map, sir. + + return false; + } + + if (Map != MapItem.Map || !Contains(MapItem.GetWorldLocation())) + { + if (message) + TillerMan?.Say(502514); // The map is too far away from me, sir. + + return false; + } + + if (Map != Map.Trammel && Map != Map.Felucca || NextNavPoint < 0 || NextNavPoint >= MapItem.Pins.Count) + { + if (message) + TillerMan?.Say(1042551); // I don't see that navpoint, sir. + + return false; + } + + Speed = FastSpeed; + Order = single ? BoatOrder.Single : BoatOrder.Course; + + m_MoveTimer?.Stop(); + + m_MoveTimer = new MoveTimer(this, FastInterval, false); + m_MoveTimer.Start(); + + if (message) + TillerMan?.Say(501429); // Aye aye sir. + + return true; + } + + public override void OnSpeech(SpeechEventArgs e) + { + if (CheckDecay()) + return; + + var from = e.Mobile; + + if (CanCommand(from) && Contains(from)) + for (var i = 0; i < e.Keywords.Length; ++i) + { + var keyword = e.Keywords[i]; + + if (keyword >= 0x42 && keyword <= 0x6B) + { + switch (keyword) + { + case 0x42: + SetName(e); + break; + case 0x43: + RemoveName(e.Mobile); + break; + case 0x44: + GiveName(e.Mobile); + break; + case 0x45: + StartMove(Forward, true); + break; + case 0x46: + StartMove(Backward, true); + break; + case 0x47: + StartMove(Left, true); + break; + case 0x48: + StartMove(Right, true); + break; + case 0x4B: + StartMove(ForwardLeft, true); + break; + case 0x4C: + StartMove(ForwardRight, true); + break; + case 0x4D: + StartMove(BackwardLeft, true); + break; + case 0x4E: + StartMove(BackwardRight, true); + break; + case 0x4F: + StopMove(true); + break; + case 0x50: + StartMove(Left, false); + break; + case 0x51: + StartMove(Right, false); + break; + case 0x52: + StartMove(Forward, false); + break; + case 0x53: + StartMove(Backward, false); + break; + case 0x54: + StartMove(ForwardLeft, false); + break; + case 0x55: + StartMove(ForwardRight, false); + break; + case 0x56: + StartMove(BackwardRight, false); + break; + case 0x57: + StartMove(BackwardLeft, false); + break; + case 0x58: + OneMove(Left); + break; + case 0x59: + OneMove(Right); + break; + case 0x5A: + OneMove(Forward); + break; + case 0x5B: + OneMove(Backward); + break; + case 0x5C: + OneMove(ForwardLeft); + break; + case 0x5D: + OneMove(ForwardRight); + break; + case 0x5E: + OneMove(BackwardRight); + break; + case 0x5F: + OneMove(BackwardLeft); + break; + case 0x49: + case 0x65: + StartTurn(2, true); + break; // turn right + case 0x4A: + case 0x66: + StartTurn(-2, true); + break; // turn left + case 0x67: + StartTurn(-4, true); + break; // turn around, come about + case 0x68: + StartMove(Forward, true); + break; + case 0x69: + StopMove(true); + break; + case 0x6A: + LowerAnchor(true); + break; + case 0x6B: + RaiseAnchor(true); + break; + case 0x60: + GiveNavPoint(); + break; // nav + case 0x61: + NextNavPoint = 0; + StartCourse(false, true); + break; // start + case 0x62: + StartCourse(false, true); + break; // continue + case 0x63: + StartCourse(e.Speech, false, true); + break; // goto* + case 0x64: + StartCourse(e.Speech, true, true); + break; // single* + } + + break; + } + } + } + + public bool StartTurn(int offset, bool message) + { + if (CheckDecay()) + return false; + + if (Anchored) + { + if (message) + TillerMan.Say(501419); // Ar, the anchor is down sir! + + return false; + } + + if (m_MoveTimer != null && Order != BoatOrder.Move) + { + m_MoveTimer.Stop(); + m_MoveTimer = null; + } + + m_TurnTimer?.Stop(); + + m_TurnTimer = new TurnTimer(this, offset); + m_TurnTimer.Start(); + + if (message) + TillerMan?.Say(501429); // Aye aye sir. + + return true; + } + + public bool Turn(int offset, bool message) + { + if (m_TurnTimer != null) + { + m_TurnTimer.Stop(); + m_TurnTimer = null; + } + + if (CheckDecay()) + return false; + + if (Anchored) + { + if (message) + TillerMan.Say(501419); // Ar, the anchor is down sir! + + return false; + } + + if (SetFacing((Direction)(((int)m_Facing + offset) & 0x7))) return true; + if (message) + TillerMan.Say(501423); // Ar, can't turn sir. + + return false; + } + + public bool StartMove(Direction dir, int speed, int clientSpeed, TimeSpan interval, bool single, bool message) + { + if (CheckDecay()) + return false; + + if (Anchored) + { + if (message) + TillerMan?.Say(501419); // Ar, the anchor is down sir! + + return false; + } + + Moving = dir; + Speed = speed; + m_ClientSpeed = clientSpeed; + Order = BoatOrder.Move; + + m_MoveTimer?.Stop(); + + m_MoveTimer = new MoveTimer(this, interval, single); + m_MoveTimer.Start(); + + return true; + } + + public bool StopMove(bool message) + { + if (CheckDecay()) + return false; + + if (m_MoveTimer == null) + { + if (message) + TillerMan?.Say(501443); // Er, the ship is not moving sir. + + return false; + } + + Moving = Direction.North; + Speed = 0; + m_ClientSpeed = 0; + m_MoveTimer.Stop(); + m_MoveTimer = null; + + if (message) + TillerMan?.Say(501429); // Aye aye sir. + + return true; + } + + public bool CanFit(Point3D p, Map map, int itemID) + { + if (map == null || map == Map.Internal || Deleted || CheckDecay()) + return false; + + var newComponents = MultiData.GetComponents(itemID); + + for (var x = 0; x < newComponents.Width; ++x) + for (var y = 0; y < newComponents.Height; ++y) + { + var tx = p.X + newComponents.Min.X + x; + var ty = p.Y + newComponents.Min.Y + y; + + if (newComponents.Tiles[x][y].Length == 0 || Contains(tx, ty)) + continue; + + var landTile = map.Tiles.GetLandTile(tx, ty); + var tiles = map.Tiles.GetStaticTiles(tx, ty, true); + + var hasWater = landTile.Z == p.Z && + (landTile.ID >= 168 && landTile.ID <= 171 || landTile.ID >= 310 && landTile.ID <= 311); + + // int z = p.Z; + + // int landZ = 0, landAvg = 0, landTop = 0; + + // map.GetAverageZ( tx, ty, ref landZ, ref landAvg, ref landTop ); + + // if (!landTile.Ignored && top > landZ && landTop > z) + // return false; + + for (var i = 0; i < tiles.Length; ++i) + { + var tile = tiles[i]; + var isWater = tile.ID >= 0x1796 && tile.ID <= 0x17B2; + + if (tile.Z == p.Z && isWater) + hasWater = true; + else if (tile.Z >= p.Z && !isWater) + return false; + } + + if (!hasWater) + return false; + } + + var eable = map.GetItemsInBounds( + new Rectangle2D( + p.X + newComponents.Min.X, + p.Y + newComponents.Min.Y, + newComponents.Width, + newComponents.Height + ) + ); + + var canFit = eable.All( + item => + { + if (item is BaseMulti || item.ItemID > TileData.MaxItemValue || item.Z < p.Z || !item.Visible) + return true; + + var x = item.X - p.X + newComponents.Min.X; + var y = item.Y - p.Y + newComponents.Min.Y; + + return x >= 0 && x < newComponents.Width && y >= 0 && y < newComponents.Height && + newComponents.Tiles[x][y].Length == 0 || Contains(item); + } + ); + + eable.Free(); + return canFit; + } + + public Point3D Rotate(Point3D p, int count) + { + var rx = p.X - Location.X; + var ry = p.Y - Location.Y; + + for (var i = 0; i < count; ++i) + { + var temp = rx; + rx = -ry; + ry = temp; + } + + return new Point3D(Location.X + rx, Location.Y + ry, p.Z); + } + + public override bool Contains(int x, int y) => + base.Contains(x, y) || + TillerMan?.X == x && y == TillerMan.Y || + Hold?.X == x && Hold.Y == y || + PPlank?.X == x && PPlank.Y == y || + SPlank?.X == x && SPlank.Y == y; + + public static bool IsValidLocation(Point3D p, Map map) + { + var wrap = GetWrapFor(map); + + for (var i = 0; i < wrap.Length; ++i) + if (wrap[i].Contains(p)) + return true; + + return false; + } + + public static Rectangle2D[] GetWrapFor(Map m) => m == Map.Ilshenar ? m_IlshWrap : + m == Map.Tokuno ? m_TokunoWrap : m_BritWrap; + + public Direction GetMovementFor(int x, int y, out int maxSpeed) + { + var dx = x - X; + var dy = y - Y; + + var adx = Math.Abs(dx); + var ady = Math.Abs(dy); + + var dir = Utility.GetDirection(this, new Point2D(x, y)); + var iDir = (int)dir; + + // Compute the maximum distance we can travel without going too far away + if (iDir % 2 == 0) // North, East, South and West + maxSpeed = Math.Abs(adx - ady); + else // Right, Down, Left and Up + maxSpeed = Math.Min(adx, ady); + + return (Direction)((iDir - (int)Facing) & 0x7); + } + + public bool DoMovement(bool message) + { + Direction dir; + int speed, clientSpeed; + + if (Order == BoatOrder.Move) + { + dir = Moving; + speed = Speed; + clientSpeed = m_ClientSpeed; + } + else if (MapItem?.Deleted != false) + { + if (message) + TillerMan?.Say(502513); // I have seen no map, sir. + + return false; + } + else if (Map != MapItem.Map || !Contains(MapItem.GetWorldLocation())) + { + if (message) + TillerMan?.Say(502514); // The map is too far away from me, sir. + + return false; + } + else if (Map != Map.Trammel && Map != Map.Felucca || NextNavPoint < 0 || NextNavPoint >= MapItem.Pins.Count) + { + if (message) + TillerMan?.Say(1042551); // I don't see that navpoint, sir. + + return false; + } + else + { + var dest = MapItem.Pins[NextNavPoint]; + + MapItem.ConvertToWorld(dest.X, dest.Y, out var x, out var y); + + dir = GetMovementFor(x, y, out var maxSpeed); + + if (maxSpeed == 0) + { + if (message && Order == BoatOrder.Single) + TillerMan?.Say( + 1042874, + (NextNavPoint + 1).ToString() + ); // We have arrived at nav point ~1_POINT_NUM~ , sir. + + if (NextNavPoint + 1 < MapItem.Pins.Count) + { + NextNavPoint++; + + if (Order == BoatOrder.Course) + { + if (message) + TillerMan?.Say( + 1042875, + (NextNavPoint + 1).ToString() + ); // Heading to nav point ~1_POINT_NUM~, sir. + + return true; + } + + return false; + } + + NextNavPoint = -1; + + if (message && Order == BoatOrder.Course) + TillerMan?.Say(502515); // The course is completed, sir. + + return false; + } + + if (dir == Left || dir == BackwardLeft || dir == Backward) + return Turn(-2, true); + if (dir == Right || dir == BackwardRight) + return Turn(2, true); + + speed = Math.Min(Speed, maxSpeed); + clientSpeed = 0x4; + } + + return Move(dir, speed, clientSpeed, true); + } + + public bool Move(Direction dir, int speed, int clientSpeed, bool message) + { + var map = Map; + + if (map == null || Deleted || CheckDecay()) + return false; + + if (Anchored) + { + if (message) + TillerMan?.Say(501419); // Ar, the anchor is down sir! + + return false; + } + + int rx = 0, ry = 0; + var d = (Direction)(((int)m_Facing + (int)dir) & 0x7); + Movement.Movement.Offset(d, ref rx, ref ry); + + for (var i = 1; i <= speed; ++i) + if (!CanFit(new Point3D(X + i * rx, Y + i * ry, Z), Map, ItemID)) + { + if (i == 1) + { + if (message) + TillerMan?.Say(501424); // Ar, we've stopped sir. + + return false; + } + + speed = i - 1; + break; + } + + var xOffset = speed * rx; + var yOffset = speed * ry; + + var newX = X + xOffset; + var newY = Y + yOffset; + + var wrap = GetWrapFor(map); + + for (var i = 0; i < wrap.Length; ++i) + { + var rect = wrap[i]; + + if (rect.Contains(new Point2D(X, Y)) && !rect.Contains(new Point2D(newX, newY))) + { + if (newX < rect.X) + newX = rect.X + rect.Width - 1; + else if (newX >= rect.X + rect.Width) + newX = rect.X; + + if (newY < rect.Y) + newY = rect.Y + rect.Height - 1; + else if (newY >= rect.Y + rect.Height) + newY = rect.Y; + + for (var j = 1; j <= speed; ++j) + if (!CanFit(new Point3D(newX + j * rx, newY + j * ry, Z), Map, ItemID)) + { + if (message) + TillerMan?.Say(501424); // Ar, we've stopped sir. + + return false; + } + + xOffset = newX - X; + yOffset = newY - Y; + } + } + + if (!NewBoatMovement || Math.Abs(xOffset) > 1 || Math.Abs(yOffset) > 1) + { + Teleport(xOffset, yOffset, 0); + } + else + { + var toMove = GetMovingEntities(); + + SafeAdd(TillerMan, toMove); + SafeAdd(Hold, toMove); + SafeAdd(PPlank, toMove); + SafeAdd(SPlank, toMove); + + // Packet must be sent before actual locations are changed + foreach (var ns in Map.GetClientsInRange(Location, GetMaxUpdateRange())) + { + var m = ns.Mobile; + + if (ns.HighSeas && m.CanSee(this) && m.InRange(Location, GetUpdateRange(m))) + ns.Send(new MoveBoatHS(m, this, d, clientSpeed, toMove, xOffset, yOffset)); + } + + foreach (var e in toMove) + if (e is Item item) + { + item.NoMoveHS = true; + + if (!(item is TillerMan || item is Hold || item is Plank)) + item.Location = new Point3D(item.X + xOffset, item.Y + yOffset, item.Z); + } + else if (e is Mobile m) + { + m.NoMoveHS = true; + m.Location = new Point3D(m.X + xOffset, m.Y + yOffset, m.Z); + } + + NoMoveHS = true; + Location = new Point3D(X + xOffset, Y + yOffset, Z); + + foreach (var e in toMove) + if (e is Item item) + item.NoMoveHS = false; + else if (e is Mobile mobile) + mobile.NoMoveHS = false; + + NoMoveHS = false; + } + + return true; + } + + private static void SafeAdd(Item item, List toMove) + { + if (item != null) + toMove.Add(item); + } + + public void Teleport(int xOffset, int yOffset, int zOffset) + { + var toMove = GetMovingEntities(); + + for (var i = 0; i < toMove.Count; ++i) + { + var e = toMove[i]; + + if (e is Item item) + item.Location = new Point3D(item.X + xOffset, item.Y + yOffset, item.Z + zOffset); + else if (e is Mobile m) m.Location = new Point3D(m.X + xOffset, m.Y + yOffset, m.Z + zOffset); + } + + Location = new Point3D(X + xOffset, Y + yOffset, Z + zOffset); + } + + public List GetMovingEntities() + { + var list = new List(); + + var map = Map; + + if (map == null || map == Map.Internal) + return list; + + var mcl = Components; + + foreach (var o in map.GetObjectsInBounds(new Rectangle2D(X + mcl.Min.X, Y + mcl.Min.Y, mcl.Width, mcl.Height))) + { + if (o == this || o is TillerMan || o is Hold || o is Plank) + continue; + + if (o is Item item) + { + if (Contains(item) && item.Visible && item.Z >= Z) + list.Add(item); + } + else if (o is Mobile m) + { + if (Contains(m)) + list.Add(m); + } + } + + return list; + } + + public bool SetFacing(Direction facing) + { + if (Parent != null || Map == null) + return false; + + if (CheckDecay()) + return false; + + if (Map != Map.Internal) + switch (facing) + { + case Direction.North: + if (!CanFit(Location, Map, NorthID)) return false; + break; + case Direction.East: + if (!CanFit(Location, Map, EastID)) return false; + break; + case Direction.South: + if (!CanFit(Location, Map, SouthID)) return false; + break; + case Direction.West: + if (!CanFit(Location, Map, WestID)) return false; + break; + } + + var old = m_Facing; + + m_Facing = facing; + + TillerMan?.SetFacing(facing); + + Hold?.SetFacing(facing); + + PPlank?.SetFacing(facing); + + SPlank?.SetFacing(facing); + + var toMove = GetMovingEntities(); + + toMove.Add(PPlank); + toMove.Add(SPlank); + + int xOffset = 0, yOffset = 0; + Movement.Movement.Offset(facing, ref xOffset, ref yOffset); + + if (TillerMan != null) + TillerMan.Location = new Point3D( + X + xOffset * TillerManDistance + (facing == Direction.North ? 1 : 0), + Y + yOffset * TillerManDistance, + TillerMan.Z + ); + + if (Hold != null) + Hold.Location = new Point3D(X + xOffset * HoldDistance, Y + yOffset * HoldDistance, Hold.Z); + + var count = (m_Facing - old) & 0x7; + count /= 2; + + for (var i = 0; i < toMove.Count; ++i) + { + var e = toMove[i]; + + if (e is Item item) + { + item.Location = Rotate(item.Location, count); + } + else if (e is Mobile m) + { + m.Direction = (m.Direction - old + facing) & Direction.Mask; + m.Location = Rotate(m.Location, count); + } + } + + ItemID = facing switch + { + Direction.North => NorthID, + Direction.East => EastID, + Direction.South => SouthID, + Direction.West => WestID, + _ => ItemID + }; + + return true; + } + + public static void UpdateAllComponents() + { + for (var i = Boats.Count - 1; i >= 0; --i) + Boats[i].UpdateComponents(); + } + + public static void Initialize() + { + new UpdateAllTimer().Start(); + EventSink.WorldSave += EventSink_WorldSave; + } + + private static void EventSink_WorldSave(bool message) + { + new UpdateAllTimer().Start(); + } + + private class DecayTimer : Timer + { + private readonly BaseBoat m_Boat; + private int m_Count; + + public DecayTimer(BaseBoat boat) : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(5.0)) + { + m_Boat = boat; + + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + if (m_Count == 5) + { + m_Boat.Delete(); + Stop(); + } + else + { + m_Boat.Location = new Point3D(m_Boat.X, m_Boat.Y, m_Boat.Z - 1); + + m_Boat.TillerMan?.Say(1007168 + m_Count); + + ++m_Count; + } + } + } + + private class TurnTimer : Timer + { + private readonly BaseBoat m_Boat; + private readonly int m_Offset; + + public TurnTimer(BaseBoat boat, int offset) : base(TimeSpan.FromSeconds(0.5)) + { + m_Boat = boat; + m_Offset = offset; + + Priority = TimerPriority.TenMS; + } + + protected override void OnTick() + { + if (!m_Boat.Deleted) + m_Boat.Turn(m_Offset, true); + } + } + + private class MoveTimer : Timer + { + private readonly BaseBoat m_Boat; + + public MoveTimer(BaseBoat boat, TimeSpan interval, bool single) : base(interval, interval, single ? 1 : 0) + { + m_Boat = boat; + Priority = TimerPriority.TwentyFiveMS; + } + + protected override void OnTick() + { + if (!m_Boat.DoMovement(true)) + m_Boat.StopMove(false); + } + } + + public class UpdateAllTimer : Timer + { + public UpdateAllTimer() : base(TimeSpan.FromSeconds(1.0)) + { + } + + protected override void OnTick() + { + UpdateAllComponents(); + } + } + + /* + * OSI sends the 0xF7 packet instead, holding 0xF3 packets + * for every entity on the boat. Though, the regular 0xF3 + * packets are still being sent as well as entities come + * into sight. Do we really need it? + */ + /* + protected override Packet GetWorldPacketFor( NetState state ) + { + if (NewBoatMovement && state.HighSeas) + return new DisplayBoatHS( state.Mobile, this ); + else + return base.GetWorldPacketFor( state ); + } + */ + + public sealed class MoveBoatHS : Packet + { + public MoveBoatHS( + Mobile beholder, BaseBoat boat, Direction d, int speed, List ents, int xOffset, + int yOffset + ) + : base(0xF6) + { + EnsureCapacity(3 + 15 + ents.Count * 10); + + Stream.Write(boat.Serial); + Stream.Write((byte)speed); + Stream.Write((byte)d); + Stream.Write((byte)boat.Facing); + Stream.Write((short)(boat.X + xOffset)); + Stream.Write((short)(boat.Y + yOffset)); + Stream.Write((short)boat.Z); + Stream.Write((short)0); // count placeholder + + var count = 0; + + foreach (var ent in ents) + { + if (!beholder.CanSee(ent)) + continue; + + Stream.Write(ent.Serial); + Stream.Write((short)(ent.X + xOffset)); + Stream.Write((short)(ent.Y + yOffset)); + Stream.Write((short)ent.Z); + ++count; + } + + Stream.Seek(16, SeekOrigin.Begin); + Stream.Write((short)count); + } + } + + public sealed class DisplayBoatHS : Packet + { + public DisplayBoatHS(Mobile beholder, BaseBoat boat) + : base(0xF7) + { + var ents = boat.GetMovingEntities(); + + SafeAdd(boat.TillerMan, ents); + SafeAdd(boat.Hold, ents); + SafeAdd(boat.PPlank, ents); + SafeAdd(boat.SPlank, ents); + + ents.Add(boat); + + EnsureCapacity(3 + 2 + ents.Count * 26); + + Stream.Write((short)0); // count placeholder + + var count = 0; + + foreach (var ent in ents) + { + if (!beholder.CanSee(ent)) + continue; + + // Embedded WorldItemHS packets + Stream.Write((byte)0xF3); + Stream.Write((short)0x1); + + if (ent is BaseMulti bm) + { + Stream.Write((byte)0x02); + Stream.Write(bm.Serial); + // TODO: Mask no longer needed, merge with Item case? + Stream.Write((ushort)(bm.ItemID & 0x3FFF)); + Stream.Write((byte)0); + + Stream.Write((short)bm.Amount); + Stream.Write((short)bm.Amount); + + Stream.Write((short)(bm.X & 0x7FFF)); + Stream.Write((short)(bm.Y & 0x3FFF)); + Stream.Write((sbyte)bm.Z); + + Stream.Write((byte)bm.Light); + Stream.Write((short)bm.Hue); + Stream.Write((byte)bm.GetPacketFlags()); + } + else if (ent is Mobile m) + { + Stream.Write((byte)0x01); + Stream.Write(m.Serial); + Stream.Write((short)m.Body); + Stream.Write((byte)0); + + Stream.Write((short)1); + Stream.Write((short)1); + + Stream.Write((short)(m.X & 0x7FFF)); + Stream.Write((short)(m.Y & 0x3FFF)); + Stream.Write((sbyte)m.Z); + + Stream.Write((byte)m.Direction); + Stream.Write((short)m.Hue); + Stream.Write((byte)m.GetPacketFlags()); + } + else if (ent is Item item) + { + Stream.Write((byte)0x00); + Stream.Write(item.Serial); + Stream.Write((ushort)(item.ItemID & 0xFFFF)); + Stream.Write((byte)0); + + Stream.Write((short)item.Amount); + Stream.Write((short)item.Amount); + + Stream.Write((short)(item.X & 0x7FFF)); + Stream.Write((short)(item.Y & 0x3FFF)); + Stream.Write((sbyte)item.Z); + + Stream.Write((byte)item.Light); + Stream.Write((short)item.Hue); + Stream.Write((byte)item.GetPacketFlags()); + } + + Stream.Write((short)0x00); + ++count; + } + + Stream.Seek(3, SeekOrigin.Begin); + Stream.Write((short)count); + } + } } - } } diff --git a/Projects/UOContent/Multis/Boats/BaseBoatDeed.cs b/Projects/UOContent/Multis/Boats/BaseBoatDeed.cs index 7eab36161..1ae18162f 100644 --- a/Projects/UOContent/Multis/Boats/BaseBoatDeed.cs +++ b/Projects/UOContent/Multis/Boats/BaseBoatDeed.cs @@ -5,168 +5,171 @@ using Server.Targeting; namespace Server.Multis { - public abstract class BaseBoatDeed : Item - { - public BaseBoatDeed(int id, Point3D offset) : base(0x14F2) + public abstract class BaseBoatDeed : Item { - Weight = 1.0; - - if (!Core.AOS) - LootType = LootType.Newbied; - - MultiID = id; - Offset = offset; - } - - public BaseBoatDeed(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int MultiID { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D Offset { get; set; } - - public abstract BaseBoat Boat { get; } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(MultiID); - writer.Write(Offset); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - MultiID = reader.ReadInt(); - Offset = reader.ReadPoint3D(); - - break; - } - } - - if (Weight == 0.0) - Weight = 1.0; - } - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (from.AccessLevel < AccessLevel.GameMaster && (from.Map == Map.Ilshenar || from.Map == Map.Malas)) - { - from.SendLocalizedMessage(1010567, null, 0x25); // You may not place a boat from this location. - } - else - { - if (Core.SE) - from.SendLocalizedMessage(502482); // Where do you wish to place the ship? - else - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502482); // Where do you wish to place the ship? - - from.Target = new InternalTarget(this); - } - } - - public void OnPlacement(Mobile from, Point3D p) - { - if (Deleted) return; - - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else - { - Map map = from.Map; - - if (map == null) - return; - - if (from.AccessLevel < AccessLevel.GameMaster && (map == Map.Ilshenar || map == Map.Malas)) + public BaseBoatDeed(int id, Point3D offset) : base(0x14F2) { - from.SendLocalizedMessage(1043284); // A ship can not be created here. - return; + Weight = 1.0; + + if (!Core.AOS) + LootType = LootType.Newbied; + + MultiID = id; + Offset = offset; } - if (from.Region.IsPartOf() || BaseBoat.FindBoatAt(from, from.Map) != null) + public BaseBoatDeed(Serial serial) : base(serial) { - from.SendLocalizedMessage(1010568, null, - 0x25); // You may not place a ship while on another ship or inside a house. - return; } - BaseBoat boat = Boat; + [CommandProperty(AccessLevel.GameMaster)] + public int MultiID { get; set; } - if (boat == null) - return; + [CommandProperty(AccessLevel.GameMaster)] + public Point3D Offset { get; set; } - p = new Point3D(p.X - Offset.X, p.Y - Offset.Y, p.Z - Offset.Z); + public abstract BaseBoat Boat { get; } - if (BaseBoat.IsValidLocation(p, map) && boat.CanFit(p, map, boat.ItemID)) + public override void Serialize(IGenericWriter writer) { - Delete(); + base.Serialize(writer); - boat.Owner = from; - boat.Anchored = true; + writer.Write(0); // version - uint keyValue = boat.CreateKeys(from); - - if (boat.PPlank != null) - boat.PPlank.KeyValue = keyValue; - - if (boat.SPlank != null) - boat.SPlank.KeyValue = keyValue; - - boat.MoveToWorld(p, map); + writer.Write(MultiID); + writer.Write(Offset); } - else + + public override void Deserialize(IGenericReader reader) { - boat.Delete(); - from.SendLocalizedMessage(1043284); // A ship can not be created here. + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + MultiID = reader.ReadInt(); + Offset = reader.ReadPoint3D(); + + break; + } + } + + if (Weight == 0.0) + Weight = 1.0; + } + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else if (from.AccessLevel < AccessLevel.GameMaster && (from.Map == Map.Ilshenar || from.Map == Map.Malas)) + { + from.SendLocalizedMessage(1010567, null, 0x25); // You may not place a boat from this location. + } + else + { + if (Core.SE) + from.SendLocalizedMessage(502482); // Where do you wish to place the ship? + else + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502482); // Where do you wish to place the ship? + + from.Target = new InternalTarget(this); + } + } + + public void OnPlacement(Mobile from, Point3D p) + { + if (Deleted) return; + + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else + { + var map = from.Map; + + if (map == null) + return; + + if (from.AccessLevel < AccessLevel.GameMaster && (map == Map.Ilshenar || map == Map.Malas)) + { + from.SendLocalizedMessage(1043284); // A ship can not be created here. + return; + } + + if (from.Region.IsPartOf() || BaseBoat.FindBoatAt(from, from.Map) != null) + { + from.SendLocalizedMessage( + 1010568, + null, + 0x25 + ); // You may not place a ship while on another ship or inside a house. + return; + } + + var boat = Boat; + + if (boat == null) + return; + + p = new Point3D(p.X - Offset.X, p.Y - Offset.Y, p.Z - Offset.Z); + + if (BaseBoat.IsValidLocation(p, map) && boat.CanFit(p, map, boat.ItemID)) + { + Delete(); + + boat.Owner = from; + boat.Anchored = true; + + var keyValue = boat.CreateKeys(from); + + if (boat.PPlank != null) + boat.PPlank.KeyValue = keyValue; + + if (boat.SPlank != null) + boat.SPlank.KeyValue = keyValue; + + boat.MoveToWorld(p, map); + } + else + { + boat.Delete(); + from.SendLocalizedMessage(1043284); // A ship can not be created here. + } + } + } + + private class InternalTarget : MultiTarget + { + private readonly BaseBoatDeed m_Deed; + + public InternalTarget(BaseBoatDeed deed) : base(deed.MultiID, deed.Offset) => m_Deed = deed; + + protected override void OnTarget(Mobile from, object o) + { + if (o is IPoint3D ip) + { + if (ip is Item item) + ip = item.GetWorldTop(); + + var p = new Point3D(ip); + + var region = Region.Find(p, from.Map); + + if (region.IsPartOf()) + from.SendLocalizedMessage(502488); // You can not place a ship inside a dungeon. + else if (region.IsPartOf() || region.IsPartOf()) + from.SendLocalizedMessage(1042549); // A boat may not be placed in this area. + else + m_Deed.OnPlacement(from, p); + } + } } - } } - - private class InternalTarget : MultiTarget - { - private readonly BaseBoatDeed m_Deed; - - public InternalTarget(BaseBoatDeed deed) : base(deed.MultiID, deed.Offset) => m_Deed = deed; - - protected override void OnTarget(Mobile from, object o) - { - if (o is IPoint3D ip) - { - if (ip is Item item) - ip = item.GetWorldTop(); - - Point3D p = new Point3D(ip); - - Region region = Region.Find(p, from.Map); - - if (region.IsPartOf()) - from.SendLocalizedMessage(502488); // You can not place a ship inside a dungeon. - else if (region.IsPartOf() || region.IsPartOf()) - from.SendLocalizedMessage(1042549); // A boat may not be placed in this area. - else - m_Deed.OnPlacement(from, p); - } - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Multis/Boats/BaseDockedBoat.cs b/Projects/UOContent/Multis/Boats/BaseDockedBoat.cs index 126445bcd..03dfdb2f5 100644 --- a/Projects/UOContent/Multis/Boats/BaseDockedBoat.cs +++ b/Projects/UOContent/Multis/Boats/BaseDockedBoat.cs @@ -4,188 +4,188 @@ using Server.Targeting; namespace Server.Multis { - public abstract class BaseDockedBoat : Item - { - private string m_ShipName; - - public BaseDockedBoat(int id, Point3D offset, BaseBoat boat) : base(0x14F4) + public abstract class BaseDockedBoat : Item { - Weight = 1.0; - LootType = LootType.Blessed; + private string m_ShipName; - MultiID = id; - Offset = offset; - - m_ShipName = boat.ShipName; - } - - public BaseDockedBoat(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int MultiID { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D Offset { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public string ShipName - { - get => m_ShipName; - set - { - m_ShipName = value; - InvalidateProperties(); - } - } - - public abstract BaseBoat Boat { get; } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(MultiID); - writer.Write(Offset); - writer.Write(m_ShipName); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - case 0: - { - MultiID = reader.ReadInt(); - Offset = reader.ReadPoint3D(); - m_ShipName = reader.ReadString(); - - if (version == 0) - reader.ReadUInt(); - - break; - } - } - - if (LootType == LootType.Newbied) - LootType = LootType.Blessed; - - if (Weight == 0.0) - Weight = 1.0; - } - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else - { - from.SendLocalizedMessage(502482); // Where do you wish to place the ship? - - from.Target = new InternalTarget(this); - } - } - - public override void AddNameProperty(ObjectPropertyList list) - { - if (m_ShipName != null) - list.Add(m_ShipName); - else - base.AddNameProperty(list); - } - - public override void OnSingleClick(Mobile from) - { - if (m_ShipName != null) - LabelTo(from, m_ShipName); - else - base.OnSingleClick(from); - } - - public void OnPlacement(Mobile from, Point3D p) - { - if (Deleted) return; - - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else - { - Map map = from.Map; - - if (map == null) - return; - - BaseBoat boat = Boat; - - if (boat == null) - return; - - p = new Point3D(p.X - Offset.X, p.Y - Offset.Y, p.Z - Offset.Z); - - if (BaseBoat.IsValidLocation(p, map) && boat.CanFit(p, map, boat.ItemID) && map != Map.Ilshenar && - map != Map.Malas) + public BaseDockedBoat(int id, Point3D offset, BaseBoat boat) : base(0x14F4) { - Delete(); + Weight = 1.0; + LootType = LootType.Blessed; - boat.Owner = from; - boat.Anchored = true; - boat.ShipName = m_ShipName; + MultiID = id; + Offset = offset; - uint keyValue = boat.CreateKeys(from); - - if (boat.PPlank != null) - boat.PPlank.KeyValue = keyValue; - - if (boat.SPlank != null) - boat.SPlank.KeyValue = keyValue; - - boat.MoveToWorld(p, map); + m_ShipName = boat.ShipName; } - else + + public BaseDockedBoat(Serial serial) : base(serial) { - boat.Delete(); - from.SendLocalizedMessage(1043284); // A ship can not be created here. } - } - } - private class InternalTarget : MultiTarget - { - private readonly BaseDockedBoat m_Model; + [CommandProperty(AccessLevel.GameMaster)] + public int MultiID { get; set; } - public InternalTarget(BaseDockedBoat model) : base(model.MultiID, model.Offset) => m_Model = model; + [CommandProperty(AccessLevel.GameMaster)] + public Point3D Offset { get; set; } - protected override void OnTarget(Mobile from, object o) - { - if (o is IPoint3D ip) + [CommandProperty(AccessLevel.GameMaster)] + public string ShipName { - if (ip is Item item) - ip = item.GetWorldTop(); - - Point3D p = new Point3D(ip); - - Region region = Region.Find(p, from.Map); - - if (region.IsPartOf()) - from.SendLocalizedMessage(502488); // You can not place a ship inside a dungeon. - else if (region.IsPartOf() || region.IsPartOf()) - from.SendLocalizedMessage(1042549); // A boat may not be placed in this area. - else - m_Model.OnPlacement(from, p); + get => m_ShipName; + set + { + m_ShipName = value; + InvalidateProperties(); + } + } + + public abstract BaseBoat Boat { get; } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(MultiID); + writer.Write(Offset); + writer.Write(m_ShipName); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + case 0: + { + MultiID = reader.ReadInt(); + Offset = reader.ReadPoint3D(); + m_ShipName = reader.ReadString(); + + if (version == 0) + reader.ReadUInt(); + + break; + } + } + + if (LootType == LootType.Newbied) + LootType = LootType.Blessed; + + if (Weight == 0.0) + Weight = 1.0; + } + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else + { + from.SendLocalizedMessage(502482); // Where do you wish to place the ship? + + from.Target = new InternalTarget(this); + } + } + + public override void AddNameProperty(ObjectPropertyList list) + { + if (m_ShipName != null) + list.Add(m_ShipName); + else + base.AddNameProperty(list); + } + + public override void OnSingleClick(Mobile from) + { + if (m_ShipName != null) + LabelTo(from, m_ShipName); + else + base.OnSingleClick(from); + } + + public void OnPlacement(Mobile from, Point3D p) + { + if (Deleted) return; + + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else + { + var map = from.Map; + + if (map == null) + return; + + var boat = Boat; + + if (boat == null) + return; + + p = new Point3D(p.X - Offset.X, p.Y - Offset.Y, p.Z - Offset.Z); + + if (BaseBoat.IsValidLocation(p, map) && boat.CanFit(p, map, boat.ItemID) && map != Map.Ilshenar && + map != Map.Malas) + { + Delete(); + + boat.Owner = from; + boat.Anchored = true; + boat.ShipName = m_ShipName; + + var keyValue = boat.CreateKeys(from); + + if (boat.PPlank != null) + boat.PPlank.KeyValue = keyValue; + + if (boat.SPlank != null) + boat.SPlank.KeyValue = keyValue; + + boat.MoveToWorld(p, map); + } + else + { + boat.Delete(); + from.SendLocalizedMessage(1043284); // A ship can not be created here. + } + } + } + + private class InternalTarget : MultiTarget + { + private readonly BaseDockedBoat m_Model; + + public InternalTarget(BaseDockedBoat model) : base(model.MultiID, model.Offset) => m_Model = model; + + protected override void OnTarget(Mobile from, object o) + { + if (o is IPoint3D ip) + { + if (ip is Item item) + ip = item.GetWorldTop(); + + var p = new Point3D(ip); + + var region = Region.Find(p, from.Map); + + if (region.IsPartOf()) + from.SendLocalizedMessage(502488); // You can not place a ship inside a dungeon. + else if (region.IsPartOf() || region.IsPartOf()) + from.SendLocalizedMessage(1042549); // A boat may not be placed in this area. + else + m_Model.OnPlacement(from, p); + } + } } - } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Multis/Boats/ConfirmDryDockGump.cs b/Projects/UOContent/Multis/Boats/ConfirmDryDockGump.cs index 63738d1cd..5c8dc29f0 100644 --- a/Projects/UOContent/Multis/Boats/ConfirmDryDockGump.cs +++ b/Projects/UOContent/Multis/Boats/ConfirmDryDockGump.cs @@ -3,36 +3,36 @@ using Server.Network; namespace Server.Multis { - public class ConfirmDryDockGump : Gump - { - private readonly BaseBoat m_Boat; - private readonly Mobile m_From; - - public ConfirmDryDockGump(Mobile from, BaseBoat boat) : base(150, 200) + public class ConfirmDryDockGump : Gump { - m_From = from; - m_Boat = boat; + private readonly BaseBoat m_Boat; + private readonly Mobile m_From; - m_From.CloseGump(); + public ConfirmDryDockGump(Mobile from, BaseBoat boat) : base(150, 200) + { + m_From = from; + m_Boat = boat; - AddPage(0); + m_From.CloseGump(); - AddBackground(0, 0, 220, 170, 5054); - AddBackground(10, 10, 200, 150, 3000); + AddPage(0); - AddHtmlLocalized(20, 20, 180, 80, 1018319, true); // Do you wish to dry dock this boat? + AddBackground(0, 0, 220, 170, 5054); + AddBackground(10, 10, 200, 150, 3000); - AddHtmlLocalized(55, 100, 140, 25, 1011011); // CONTINUE - AddButton(20, 100, 4005, 4007, 2); + AddHtmlLocalized(20, 20, 180, 80, 1018319, true); // Do you wish to dry dock this boat? - AddHtmlLocalized(55, 125, 140, 25, 1011012); // CANCEL - AddButton(20, 125, 4005, 4007, 1); + AddHtmlLocalized(55, 100, 140, 25, 1011011); // CONTINUE + AddButton(20, 100, 4005, 4007, 2); + + AddHtmlLocalized(55, 125, 140, 25, 1011012); // CANCEL + AddButton(20, 125, 4005, 4007, 1); + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (info.ButtonID == 2) + m_Boat.EndDryDock(m_From); + } } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (info.ButtonID == 2) - m_Boat.EndDryDock(m_From); - } - } } diff --git a/Projects/UOContent/Multis/Boats/Hold.cs b/Projects/UOContent/Multis/Boats/Hold.cs index 3447578ad..f69f39ebb 100644 --- a/Projects/UOContent/Multis/Boats/Hold.cs +++ b/Projects/UOContent/Multis/Boats/Hold.cs @@ -3,110 +3,110 @@ using Server.Network; namespace Server.Items { - public class Hold : Container - { - private BaseBoat m_Boat; - - public Hold(BaseBoat boat) : base(0x3EAE) + public class Hold : Container { - m_Boat = boat; - Movable = false; - } - - public Hold(Serial serial) : base(serial) - { - } - - public override bool IsDecoContainer => false; - - public void SetFacing(Direction dir) - { - ItemID = dir switch - { - Direction.East => 0x3E65, - Direction.West => 0x3E93, - Direction.North => 0x3EAE, - Direction.South => 0x3EB9, - _ => ItemID - }; - } - - public override bool OnDragDrop(Mobile from, Item item) - { - if (m_Boat?.Contains(from) != true || m_Boat.IsMoving) - return false; - - return base.OnDragDrop(from, item); - } - - public override bool OnDragDropInto(Mobile from, Item item, Point3D p) - { - if (m_Boat?.Contains(from) != true || m_Boat.IsMoving) - return false; - - return base.OnDragDropInto(from, item, p); - } - - public override bool CheckItemUse(Mobile from, Item item) - { - if (item != this && (m_Boat?.Contains(from) != true || m_Boat.IsMoving)) - return false; - - return base.CheckItemUse(from, item); - } - - public override bool CheckLift(Mobile from, Item item, ref LRReason reject) - { - if (m_Boat?.Contains(from) != true || m_Boat.IsMoving) - return false; - - return base.CheckLift(from, item, ref reject); - } - - public override void OnAfterDelete() - { - m_Boat?.Delete(); - } - - public override void OnDoubleClick(Mobile from) - { - if (m_Boat?.Contains(from) != true) - m_Boat.TillerMan?.Say(502490); // You must be on the ship to open the hold. - else if (m_Boat.IsMoving) - m_Boat.TillerMan?.Say(502491); // I can not open the hold while the ship is moving. - else - base.OnDoubleClick(from); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - - writer.Write(m_Boat); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Boat = reader.ReadItem() as BaseBoat; - - if (m_Boat == null || Parent != null) - Delete(); + private BaseBoat m_Boat; + public Hold(BaseBoat boat) : base(0x3EAE) + { + m_Boat = boat; Movable = false; + } - break; - } - } + public Hold(Serial serial) : base(serial) + { + } + + public override bool IsDecoContainer => false; + + public void SetFacing(Direction dir) + { + ItemID = dir switch + { + Direction.East => 0x3E65, + Direction.West => 0x3E93, + Direction.North => 0x3EAE, + Direction.South => 0x3EB9, + _ => ItemID + }; + } + + public override bool OnDragDrop(Mobile from, Item item) + { + if (m_Boat?.Contains(from) != true || m_Boat.IsMoving) + return false; + + return base.OnDragDrop(from, item); + } + + public override bool OnDragDropInto(Mobile from, Item item, Point3D p) + { + if (m_Boat?.Contains(from) != true || m_Boat.IsMoving) + return false; + + return base.OnDragDropInto(from, item, p); + } + + public override bool CheckItemUse(Mobile from, Item item) + { + if (item != this && (m_Boat?.Contains(from) != true || m_Boat.IsMoving)) + return false; + + return base.CheckItemUse(from, item); + } + + public override bool CheckLift(Mobile from, Item item, ref LRReason reject) + { + if (m_Boat?.Contains(from) != true || m_Boat.IsMoving) + return false; + + return base.CheckLift(from, item, ref reject); + } + + public override void OnAfterDelete() + { + m_Boat?.Delete(); + } + + public override void OnDoubleClick(Mobile from) + { + if (m_Boat?.Contains(from) != true) + m_Boat.TillerMan?.Say(502490); // You must be on the ship to open the hold. + else if (m_Boat.IsMoving) + m_Boat.TillerMan?.Say(502491); // I can not open the hold while the ship is moving. + else + base.OnDoubleClick(from); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + + writer.Write(m_Boat); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Boat = reader.ReadItem() as BaseBoat; + + if (m_Boat == null || Parent != null) + Delete(); + + Movable = false; + + break; + } + } + } } - } } diff --git a/Projects/UOContent/Multis/Boats/LargeBoat.cs b/Projects/UOContent/Multis/Boats/LargeBoat.cs index d1e26ffc8..64151ae81 100644 --- a/Projects/UOContent/Multis/Boats/LargeBoat.cs +++ b/Projects/UOContent/Multis/Boats/LargeBoat.cs @@ -1,99 +1,99 @@ namespace Server.Multis { - public class LargeBoat : BaseBoat - { - [Constructible] - public LargeBoat() + public class LargeBoat : BaseBoat { + [Constructible] + public LargeBoat() + { + } + + public LargeBoat(Serial serial) : base(serial) + { + } + + public override int NorthID => 0x10; + public override int EastID => 0x11; + public override int SouthID => 0x12; + public override int WestID => 0x13; + + public override int HoldDistance => 5; + public override int TillerManDistance => -5; + + public override Point2D StarboardOffset => new Point2D(2, -1); + public override Point2D PortOffset => new Point2D(-2, -1); + + public override Point3D MarkOffset => new Point3D(0, 0, 3); + + public override BaseDockedBoat DockedBoat => new LargeDockedBoat(this); + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + } } - public LargeBoat(Serial serial) : base(serial) + public class LargeBoatDeed : BaseBoatDeed { + [Constructible] + public LargeBoatDeed() : base(0x10, new Point3D(0, -1, 0)) + { + } + + public LargeBoatDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041209; // large ship deed + public override BaseBoat Boat => new LargeBoat(); + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + } } - public override int NorthID => 0x10; - public override int EastID => 0x11; - public override int SouthID => 0x12; - public override int WestID => 0x13; - - public override int HoldDistance => 5; - public override int TillerManDistance => -5; - - public override Point2D StarboardOffset => new Point2D(2, -1); - public override Point2D PortOffset => new Point2D(-2, -1); - - public override Point3D MarkOffset => new Point3D(0, 0, 3); - - public override BaseDockedBoat DockedBoat => new LargeDockedBoat(this); - - public override void Deserialize(IGenericReader reader) + public class LargeDockedBoat : BaseDockedBoat { - base.Deserialize(reader); + public LargeDockedBoat(BaseBoat boat) : base(0x10, new Point3D(0, -1, 0), boat) + { + } - int version = reader.ReadInt(); + public LargeDockedBoat(Serial serial) : base(serial) + { + } + + public override BaseBoat Boat => new LargeBoat(); + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - } - - public class LargeBoatDeed : BaseBoatDeed - { - [Constructible] - public LargeBoatDeed() : base(0x10, new Point3D(0, -1, 0)) - { - } - - public LargeBoatDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041209; // large ship deed - public override BaseBoat Boat => new LargeBoat(); - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - } - - public class LargeDockedBoat : BaseDockedBoat - { - public LargeDockedBoat(BaseBoat boat) : base(0x10, new Point3D(0, -1, 0), boat) - { - } - - public LargeDockedBoat(Serial serial) : base(serial) - { - } - - public override BaseBoat Boat => new LargeBoat(); - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Multis/Boats/LargeDragonBoat.cs b/Projects/UOContent/Multis/Boats/LargeDragonBoat.cs index 097927b75..64b39bf47 100644 --- a/Projects/UOContent/Multis/Boats/LargeDragonBoat.cs +++ b/Projects/UOContent/Multis/Boats/LargeDragonBoat.cs @@ -1,99 +1,99 @@ namespace Server.Multis { - public class LargeDragonBoat : BaseBoat - { - [Constructible] - public LargeDragonBoat() + public class LargeDragonBoat : BaseBoat { + [Constructible] + public LargeDragonBoat() + { + } + + public LargeDragonBoat(Serial serial) : base(serial) + { + } + + public override int NorthID => 0x14; + public override int EastID => 0x15; + public override int SouthID => 0x16; + public override int WestID => 0x17; + + public override int HoldDistance => 5; + public override int TillerManDistance => -5; + + public override Point2D StarboardOffset => new Point2D(2, -1); + public override Point2D PortOffset => new Point2D(-2, -1); + + public override Point3D MarkOffset => new Point3D(0, 0, 3); + + public override BaseDockedBoat DockedBoat => new LargeDockedDragonBoat(this); + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + } } - public LargeDragonBoat(Serial serial) : base(serial) + public class LargeDragonBoatDeed : BaseBoatDeed { + [Constructible] + public LargeDragonBoatDeed() : base(0x14, new Point3D(0, -1, 0)) + { + } + + public LargeDragonBoatDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041210; // large dragon ship deed + public override BaseBoat Boat => new LargeDragonBoat(); + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + } } - public override int NorthID => 0x14; - public override int EastID => 0x15; - public override int SouthID => 0x16; - public override int WestID => 0x17; - - public override int HoldDistance => 5; - public override int TillerManDistance => -5; - - public override Point2D StarboardOffset => new Point2D(2, -1); - public override Point2D PortOffset => new Point2D(-2, -1); - - public override Point3D MarkOffset => new Point3D(0, 0, 3); - - public override BaseDockedBoat DockedBoat => new LargeDockedDragonBoat(this); - - public override void Deserialize(IGenericReader reader) + public class LargeDockedDragonBoat : BaseDockedBoat { - base.Deserialize(reader); + public LargeDockedDragonBoat(BaseBoat boat) : base(0x14, new Point3D(0, -1, 0), boat) + { + } - int version = reader.ReadInt(); + public LargeDockedDragonBoat(Serial serial) : base(serial) + { + } + + public override BaseBoat Boat => new LargeDragonBoat(); + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - } - - public class LargeDragonBoatDeed : BaseBoatDeed - { - [Constructible] - public LargeDragonBoatDeed() : base(0x14, new Point3D(0, -1, 0)) - { - } - - public LargeDragonBoatDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041210; // large dragon ship deed - public override BaseBoat Boat => new LargeDragonBoat(); - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - } - - public class LargeDockedDragonBoat : BaseDockedBoat - { - public LargeDockedDragonBoat(BaseBoat boat) : base(0x14, new Point3D(0, -1, 0), boat) - { - } - - public LargeDockedDragonBoat(Serial serial) : base(serial) - { - } - - public override BaseBoat Boat => new LargeDragonBoat(); - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Multis/Boats/MediumBoat.cs b/Projects/UOContent/Multis/Boats/MediumBoat.cs index 0b7084064..ae9d5c23b 100644 --- a/Projects/UOContent/Multis/Boats/MediumBoat.cs +++ b/Projects/UOContent/Multis/Boats/MediumBoat.cs @@ -1,99 +1,99 @@ namespace Server.Multis { - public class MediumBoat : BaseBoat - { - [Constructible] - public MediumBoat() + public class MediumBoat : BaseBoat { + [Constructible] + public MediumBoat() + { + } + + public MediumBoat(Serial serial) : base(serial) + { + } + + public override int NorthID => 0x8; + public override int EastID => 0x9; + public override int SouthID => 0xA; + public override int WestID => 0xB; + + public override int HoldDistance => 4; + public override int TillerManDistance => -5; + + public override Point2D StarboardOffset => new Point2D(2, 0); + public override Point2D PortOffset => new Point2D(-2, 0); + + public override Point3D MarkOffset => new Point3D(0, 1, 3); + + public override BaseDockedBoat DockedBoat => new MediumDockedBoat(this); + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + } } - public MediumBoat(Serial serial) : base(serial) + public class MediumBoatDeed : BaseBoatDeed { + [Constructible] + public MediumBoatDeed() : base(0x8, Point3D.Zero) + { + } + + public MediumBoatDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041207; // medium ship deed + public override BaseBoat Boat => new MediumBoat(); + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + } } - public override int NorthID => 0x8; - public override int EastID => 0x9; - public override int SouthID => 0xA; - public override int WestID => 0xB; - - public override int HoldDistance => 4; - public override int TillerManDistance => -5; - - public override Point2D StarboardOffset => new Point2D(2, 0); - public override Point2D PortOffset => new Point2D(-2, 0); - - public override Point3D MarkOffset => new Point3D(0, 1, 3); - - public override BaseDockedBoat DockedBoat => new MediumDockedBoat(this); - - public override void Deserialize(IGenericReader reader) + public class MediumDockedBoat : BaseDockedBoat { - base.Deserialize(reader); + public MediumDockedBoat(BaseBoat boat) : base(0x8, Point3D.Zero, boat) + { + } - int version = reader.ReadInt(); + public MediumDockedBoat(Serial serial) : base(serial) + { + } + + public override BaseBoat Boat => new MediumBoat(); + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - } - - public class MediumBoatDeed : BaseBoatDeed - { - [Constructible] - public MediumBoatDeed() : base(0x8, Point3D.Zero) - { - } - - public MediumBoatDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041207; // medium ship deed - public override BaseBoat Boat => new MediumBoat(); - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - } - - public class MediumDockedBoat : BaseDockedBoat - { - public MediumDockedBoat(BaseBoat boat) : base(0x8, Point3D.Zero, boat) - { - } - - public MediumDockedBoat(Serial serial) : base(serial) - { - } - - public override BaseBoat Boat => new MediumBoat(); - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Multis/Boats/MediumDragonBoat.cs b/Projects/UOContent/Multis/Boats/MediumDragonBoat.cs index e53beaf13..a13b776e5 100644 --- a/Projects/UOContent/Multis/Boats/MediumDragonBoat.cs +++ b/Projects/UOContent/Multis/Boats/MediumDragonBoat.cs @@ -1,99 +1,99 @@ namespace Server.Multis { - public class MediumDragonBoat : BaseBoat - { - [Constructible] - public MediumDragonBoat() + public class MediumDragonBoat : BaseBoat { + [Constructible] + public MediumDragonBoat() + { + } + + public MediumDragonBoat(Serial serial) : base(serial) + { + } + + public override int NorthID => 0xC; + public override int EastID => 0xD; + public override int SouthID => 0xE; + public override int WestID => 0xF; + + public override int HoldDistance => 4; + public override int TillerManDistance => -5; + + public override Point2D StarboardOffset => new Point2D(2, 0); + public override Point2D PortOffset => new Point2D(-2, 0); + + public override Point3D MarkOffset => new Point3D(0, 1, 3); + + public override BaseDockedBoat DockedBoat => new MediumDockedDragonBoat(this); + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + } } - public MediumDragonBoat(Serial serial) : base(serial) + public class MediumDragonBoatDeed : BaseBoatDeed { + [Constructible] + public MediumDragonBoatDeed() : base(0xC, Point3D.Zero) + { + } + + public MediumDragonBoatDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041208; // medium dragon ship deed + public override BaseBoat Boat => new MediumDragonBoat(); + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + } } - public override int NorthID => 0xC; - public override int EastID => 0xD; - public override int SouthID => 0xE; - public override int WestID => 0xF; - - public override int HoldDistance => 4; - public override int TillerManDistance => -5; - - public override Point2D StarboardOffset => new Point2D(2, 0); - public override Point2D PortOffset => new Point2D(-2, 0); - - public override Point3D MarkOffset => new Point3D(0, 1, 3); - - public override BaseDockedBoat DockedBoat => new MediumDockedDragonBoat(this); - - public override void Deserialize(IGenericReader reader) + public class MediumDockedDragonBoat : BaseDockedBoat { - base.Deserialize(reader); + public MediumDockedDragonBoat(BaseBoat boat) : base(0xC, Point3D.Zero, boat) + { + } - int version = reader.ReadInt(); + public MediumDockedDragonBoat(Serial serial) : base(serial) + { + } + + public override BaseBoat Boat => new MediumDragonBoat(); + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - } - - public class MediumDragonBoatDeed : BaseBoatDeed - { - [Constructible] - public MediumDragonBoatDeed() : base(0xC, Point3D.Zero) - { - } - - public MediumDragonBoatDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041208; // medium dragon ship deed - public override BaseBoat Boat => new MediumDragonBoat(); - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - } - - public class MediumDockedDragonBoat : BaseDockedBoat - { - public MediumDockedDragonBoat(BaseBoat boat) : base(0xC, Point3D.Zero, boat) - { - } - - public MediumDockedDragonBoat(Serial serial) : base(serial) - { - } - - public override BaseBoat Boat => new MediumDragonBoat(); - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Multis/Boats/Plank.cs b/Projects/UOContent/Multis/Boats/Plank.cs index 2e1827dad..215db71c3 100644 --- a/Projects/UOContent/Multis/Boats/Plank.cs +++ b/Projects/UOContent/Multis/Boats/Plank.cs @@ -7,292 +7,298 @@ using Server.Spells; namespace Server.Items { - public enum PlankSide - { - Port, - Starboard - } - - public class Plank : Item, ILockable - { - private Timer m_CloseTimer; - - public Plank(BaseBoat boat, PlankSide side, uint keyValue) : base(0x3EB1 + (int)side) + public enum PlankSide { - Boat = boat; - Side = side; - KeyValue = keyValue; - Locked = true; - - Movable = false; + Port, + Starboard } - public Plank(Serial serial) : base(serial) + public class Plank : Item, ILockable { - } + private Timer m_CloseTimer; - [CommandProperty(AccessLevel.GameMaster)] - public BaseBoat Boat { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public PlankSide Side { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool IsOpen => ItemID == 0x3ED5 || ItemID == 0x3ED4 || ItemID == 0x3E84 || ItemID == 0x3E89; - - [CommandProperty(AccessLevel.GameMaster)] - public bool Starboard => Side == PlankSide.Starboard; - - [CommandProperty(AccessLevel.GameMaster)] - public bool Locked { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public uint KeyValue { get; set; } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(Boat); - writer.Write((int)Side); - writer.Write(Locked); - writer.Write(KeyValue); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Boat = reader.ReadItem() as BaseBoat; - Side = (PlankSide)reader.ReadInt(); - Locked = reader.ReadBool(); - KeyValue = reader.ReadUInt(); - - if (Boat == null) - Delete(); - - break; - } - } - - if (IsOpen) - { - m_CloseTimer = new CloseTimer(this); - m_CloseTimer.Start(); - } - } - - public void SetFacing(Direction dir) - { - if (IsOpen) - ItemID = dir switch + public Plank(BaseBoat boat, PlankSide side, uint keyValue) : base(0x3EB1 + (int)side) { - Direction.North => Starboard ? 0x3ED4 : 0x3ED5, - Direction.East => Starboard ? 0x3E84 : 0x3E89, - Direction.South => Starboard ? 0x3ED5 : 0x3ED4, - Direction.West => Starboard ? 0x3E89 : 0x3E84, - _ => ItemID - }; - else - ItemID = dir switch - { - Direction.North => Starboard ? 0x3EB2 : 0x3EB1, - Direction.East => Starboard ? 0x3E85 : 0x3E8A, - Direction.South => Starboard ? 0x3EB1 : 0x3EB2, - Direction.West => Starboard ? 0x3E8A : 0x3E85, - _ => ItemID - }; - } + Boat = boat; + Side = side; + KeyValue = keyValue; + Locked = true; - public void Open() - { - if (IsOpen || Deleted) - return; - - m_CloseTimer?.Stop(); - - m_CloseTimer = new CloseTimer(this); - m_CloseTimer.Start(); - - ItemID = ItemID switch - { - 0x3EB1 => 0x3ED5, - 0x3E8A => 0x3E89, - 0x3EB2 => 0x3ED4, - 0x3E85 => 0x3E84, - _ => ItemID - }; - - Boat?.Refresh(); - } - - public override bool OnMoveOver(Mobile from) - { - if (IsOpen) - { - if (from is BaseFactionGuard) - return false; - - if ((from.Direction & Direction.Running) != 0 || Boat?.Contains(from) == false) - return true; - - Map map = Map; - - if (map == null) - return false; - - int rx = 0, ry = 0; - - if (ItemID == 0x3ED4) - rx = 1; - else if (ItemID == 0x3ED5) - rx = -1; - else if (ItemID == 0x3E84) - ry = 1; - else if (ItemID == 0x3E89) - ry = -1; - - for (int i = 1; i <= 6; ++i) - { - int x = X + i * rx; - int y = Y + i * ry; - int z; - - for (int j = -8; j <= 8; ++j) - { - z = from.Z + j; - - if (map.CanFit(x, y, z, 16, false, false) && !SpellHelper.CheckMulti(new Point3D(x, y, z), map) && - !Region.Find(new Point3D(x, y, z), map).IsPartOf()) - { - if (i == 1 && j >= -2 && j <= 2) - return true; - - from.Location = new Point3D(x, y, z); - return false; - } - } - - z = map.GetAverageZ(x, y); - - if (map.CanFit(x, y, z, 16, false, false) && !SpellHelper.CheckMulti(new Point3D(x, y, z), map) && - !Region.Find(new Point3D(x, y, z), map).IsPartOf()) - { - if (i == 1) - return true; - - from.Location = new Point3D(x, y, z); - return false; - } + Movable = false; } - return true; - } - - return false; - } - - public bool CanClose() => Map != null && !Deleted && GetObjectsInRange(0).All(o => o == this); - - public void Close() - { - if (!IsOpen || !CanClose() || Deleted) - return; - - m_CloseTimer?.Stop(); - - m_CloseTimer = null; - - ItemID = ItemID switch - { - 0x3ED5 => 0x3EB1, - 0x3E89 => 0x3E8A, - 0x3ED4 => 0x3EB2, - 0x3E84 => 0x3E85, - _ => ItemID - }; - - Boat?.Refresh(); - } - - public override void OnDoubleClickDead(Mobile from) - { - OnDoubleClick(from); - } - - public override void OnDoubleClick(Mobile from) - { - if (Boat == null) - return; - - if (from.InRange(GetWorldLocation(), 8)) - { - if (Boat.Contains(from)) + public Plank(Serial serial) : base(serial) { - if (IsOpen) - Close(); - else - Open(); } - else + + [CommandProperty(AccessLevel.GameMaster)] + public BaseBoat Boat { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public PlankSide Side { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public bool IsOpen => ItemID == 0x3ED5 || ItemID == 0x3ED4 || ItemID == 0x3E84 || ItemID == 0x3E89; + + [CommandProperty(AccessLevel.GameMaster)] + public bool Starboard => Side == PlankSide.Starboard; + + [CommandProperty(AccessLevel.GameMaster)] + public bool Locked { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public uint KeyValue { get; set; } + + public override void Serialize(IGenericWriter writer) { - if (!IsOpen) - { - if (!Locked) + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(Boat); + writer.Write((int)Side); + writer.Write(Locked); + writer.Write(KeyValue); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) { - Open(); + case 0: + { + Boat = reader.ReadItem() as BaseBoat; + Side = (PlankSide)reader.ReadInt(); + Locked = reader.ReadBool(); + KeyValue = reader.ReadUInt(); + + if (Boat == null) + Delete(); + + break; + } } - else if (from.AccessLevel >= AccessLevel.GameMaster) + + if (IsOpen) { - from.LocalOverheadMessage(MessageType.Regular, 0x00, - 502502); // That is locked but your godly powers allow access - Open(); + m_CloseTimer = new CloseTimer(this); + m_CloseTimer.Start(); } + } + + public void SetFacing(Direction dir) + { + if (IsOpen) + ItemID = dir switch + { + Direction.North => Starboard ? 0x3ED4 : 0x3ED5, + Direction.East => Starboard ? 0x3E84 : 0x3E89, + Direction.South => Starboard ? 0x3ED5 : 0x3ED4, + Direction.West => Starboard ? 0x3E89 : 0x3E84, + _ => ItemID + }; else - { - from.LocalOverheadMessage(MessageType.Regular, 0x00, 502503); // That is locked. - } - } - else if (!Locked) - { - from.Location = new Point3D(X, Y, Z + 3); - } - else if (from.AccessLevel >= AccessLevel.GameMaster) - { - from.LocalOverheadMessage(MessageType.Regular, 0x00, - 502502); // That is locked but your godly powers allow access - from.Location = new Point3D(X, Y, Z + 3); - } - else - { - from.LocalOverheadMessage(MessageType.Regular, 0x00, 502503); // That is locked. - } + ItemID = dir switch + { + Direction.North => Starboard ? 0x3EB2 : 0x3EB1, + Direction.East => Starboard ? 0x3E85 : 0x3E8A, + Direction.South => Starboard ? 0x3EB1 : 0x3EB2, + Direction.West => Starboard ? 0x3E8A : 0x3E85, + _ => ItemID + }; + } + + public void Open() + { + if (IsOpen || Deleted) + return; + + m_CloseTimer?.Stop(); + + m_CloseTimer = new CloseTimer(this); + m_CloseTimer.Start(); + + ItemID = ItemID switch + { + 0x3EB1 => 0x3ED5, + 0x3E8A => 0x3E89, + 0x3EB2 => 0x3ED4, + 0x3E85 => 0x3E84, + _ => ItemID + }; + + Boat?.Refresh(); + } + + public override bool OnMoveOver(Mobile from) + { + if (IsOpen) + { + if (from is BaseFactionGuard) + return false; + + if ((from.Direction & Direction.Running) != 0 || Boat?.Contains(from) == false) + return true; + + var map = Map; + + if (map == null) + return false; + + int rx = 0, ry = 0; + + if (ItemID == 0x3ED4) + rx = 1; + else if (ItemID == 0x3ED5) + rx = -1; + else if (ItemID == 0x3E84) + ry = 1; + else if (ItemID == 0x3E89) + ry = -1; + + for (var i = 1; i <= 6; ++i) + { + var x = X + i * rx; + var y = Y + i * ry; + int z; + + for (var j = -8; j <= 8; ++j) + { + z = from.Z + j; + + if (map.CanFit(x, y, z, 16, false, false) && !SpellHelper.CheckMulti(new Point3D(x, y, z), map) && + !Region.Find(new Point3D(x, y, z), map).IsPartOf()) + { + if (i == 1 && j >= -2 && j <= 2) + return true; + + from.Location = new Point3D(x, y, z); + return false; + } + } + + z = map.GetAverageZ(x, y); + + if (map.CanFit(x, y, z, 16, false, false) && !SpellHelper.CheckMulti(new Point3D(x, y, z), map) && + !Region.Find(new Point3D(x, y, z), map).IsPartOf()) + { + if (i == 1) + return true; + + from.Location = new Point3D(x, y, z); + return false; + } + } + + return true; + } + + return false; + } + + public bool CanClose() => Map != null && !Deleted && GetObjectsInRange(0).All(o => o == this); + + public void Close() + { + if (!IsOpen || !CanClose() || Deleted) + return; + + m_CloseTimer?.Stop(); + + m_CloseTimer = null; + + ItemID = ItemID switch + { + 0x3ED5 => 0x3EB1, + 0x3E89 => 0x3E8A, + 0x3ED4 => 0x3EB2, + 0x3E84 => 0x3E85, + _ => ItemID + }; + + Boat?.Refresh(); + } + + public override void OnDoubleClickDead(Mobile from) + { + OnDoubleClick(from); + } + + public override void OnDoubleClick(Mobile from) + { + if (Boat == null) + return; + + if (from.InRange(GetWorldLocation(), 8)) + { + if (Boat.Contains(from)) + { + if (IsOpen) + Close(); + else + Open(); + } + else + { + if (!IsOpen) + { + if (!Locked) + { + Open(); + } + else if (from.AccessLevel >= AccessLevel.GameMaster) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x00, + 502502 + ); // That is locked but your godly powers allow access + Open(); + } + else + { + from.LocalOverheadMessage(MessageType.Regular, 0x00, 502503); // That is locked. + } + } + else if (!Locked) + { + from.Location = new Point3D(X, Y, Z + 3); + } + else if (from.AccessLevel >= AccessLevel.GameMaster) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x00, + 502502 + ); // That is locked but your godly powers allow access + from.Location = new Point3D(X, Y, Z + 3); + } + else + { + from.LocalOverheadMessage(MessageType.Regular, 0x00, 502503); // That is locked. + } + } + } + } + + private class CloseTimer : Timer + { + private readonly Plank m_Plank; + + public CloseTimer(Plank plank) : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0)) + { + m_Plank = plank; + Priority = TimerPriority.OneSecond; + } + + protected override void OnTick() + { + m_Plank.Close(); + } } - } } - - private class CloseTimer : Timer - { - private readonly Plank m_Plank; - - public CloseTimer(Plank plank) : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0)) - { - m_Plank = plank; - Priority = TimerPriority.OneSecond; - } - - protected override void OnTick() - { - m_Plank.Close(); - } - } - } } diff --git a/Projects/UOContent/Multis/Boats/RenameBoatPrompt.cs b/Projects/UOContent/Multis/Boats/RenameBoatPrompt.cs index 70bbcf3fe..5635d317b 100644 --- a/Projects/UOContent/Multis/Boats/RenameBoatPrompt.cs +++ b/Projects/UOContent/Multis/Boats/RenameBoatPrompt.cs @@ -2,15 +2,15 @@ using Server.Prompts; namespace Server.Multis { - public class RenameBoatPrompt : Prompt - { - private readonly BaseBoat m_Boat; - - public RenameBoatPrompt(BaseBoat boat) => m_Boat = boat; - - public override void OnResponse(Mobile from, string text) + public class RenameBoatPrompt : Prompt { - m_Boat.EndRename(from, text); + private readonly BaseBoat m_Boat; + + public RenameBoatPrompt(BaseBoat boat) => m_Boat = boat; + + public override void OnResponse(Mobile from, string text) + { + m_Boat.EndRename(from, text); + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Multis/Boats/SmallBoat.cs b/Projects/UOContent/Multis/Boats/SmallBoat.cs index 6071004f3..13c2a3913 100644 --- a/Projects/UOContent/Multis/Boats/SmallBoat.cs +++ b/Projects/UOContent/Multis/Boats/SmallBoat.cs @@ -1,99 +1,99 @@ namespace Server.Multis { - public class SmallBoat : BaseBoat - { - [Constructible] - public SmallBoat() + public class SmallBoat : BaseBoat { + [Constructible] + public SmallBoat() + { + } + + public SmallBoat(Serial serial) : base(serial) + { + } + + public override int NorthID => 0x0; + public override int EastID => 0x1; + public override int SouthID => 0x2; + public override int WestID => 0x3; + + public override int HoldDistance => 4; + public override int TillerManDistance => -4; + + public override Point2D StarboardOffset => new Point2D(2, 0); + public override Point2D PortOffset => new Point2D(-2, 0); + + public override Point3D MarkOffset => new Point3D(0, 1, 3); + + public override BaseDockedBoat DockedBoat => new SmallDockedBoat(this); + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + } } - public SmallBoat(Serial serial) : base(serial) + public class SmallBoatDeed : BaseBoatDeed { + [Constructible] + public SmallBoatDeed() : base(0x0, Point3D.Zero) + { + } + + public SmallBoatDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041205; // small ship deed + public override BaseBoat Boat => new SmallBoat(); + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + } } - public override int NorthID => 0x0; - public override int EastID => 0x1; - public override int SouthID => 0x2; - public override int WestID => 0x3; - - public override int HoldDistance => 4; - public override int TillerManDistance => -4; - - public override Point2D StarboardOffset => new Point2D(2, 0); - public override Point2D PortOffset => new Point2D(-2, 0); - - public override Point3D MarkOffset => new Point3D(0, 1, 3); - - public override BaseDockedBoat DockedBoat => new SmallDockedBoat(this); - - public override void Deserialize(IGenericReader reader) + public class SmallDockedBoat : BaseDockedBoat { - base.Deserialize(reader); + public SmallDockedBoat(BaseBoat boat) : base(0x0, Point3D.Zero, boat) + { + } - int version = reader.ReadInt(); + public SmallDockedBoat(Serial serial) : base(serial) + { + } + + public override BaseBoat Boat => new SmallBoat(); + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - } - - public class SmallBoatDeed : BaseBoatDeed - { - [Constructible] - public SmallBoatDeed() : base(0x0, Point3D.Zero) - { - } - - public SmallBoatDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041205; // small ship deed - public override BaseBoat Boat => new SmallBoat(); - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - } - - public class SmallDockedBoat : BaseDockedBoat - { - public SmallDockedBoat(BaseBoat boat) : base(0x0, Point3D.Zero, boat) - { - } - - public SmallDockedBoat(Serial serial) : base(serial) - { - } - - public override BaseBoat Boat => new SmallBoat(); - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Multis/Boats/SmallDragonBoat.cs b/Projects/UOContent/Multis/Boats/SmallDragonBoat.cs index 415fa8a17..39b4902e4 100644 --- a/Projects/UOContent/Multis/Boats/SmallDragonBoat.cs +++ b/Projects/UOContent/Multis/Boats/SmallDragonBoat.cs @@ -1,99 +1,99 @@ namespace Server.Multis { - public class SmallDragonBoat : BaseBoat - { - [Constructible] - public SmallDragonBoat() + public class SmallDragonBoat : BaseBoat { + [Constructible] + public SmallDragonBoat() + { + } + + public SmallDragonBoat(Serial serial) : base(serial) + { + } + + public override int NorthID => 0x4; + public override int EastID => 0x5; + public override int SouthID => 0x6; + public override int WestID => 0x7; + + public override int HoldDistance => 4; + public override int TillerManDistance => -4; + + public override Point2D StarboardOffset => new Point2D(2, 0); + public override Point2D PortOffset => new Point2D(-2, 0); + + public override Point3D MarkOffset => new Point3D(0, 1, 3); + + public override BaseDockedBoat DockedBoat => new SmallDockedDragonBoat(this); + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + } } - public SmallDragonBoat(Serial serial) : base(serial) + public class SmallDragonBoatDeed : BaseBoatDeed { + [Constructible] + public SmallDragonBoatDeed() : base(0x4, Point3D.Zero) + { + } + + public SmallDragonBoatDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041206; // small dragon ship deed + public override BaseBoat Boat => new SmallDragonBoat(); + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + } } - public override int NorthID => 0x4; - public override int EastID => 0x5; - public override int SouthID => 0x6; - public override int WestID => 0x7; - - public override int HoldDistance => 4; - public override int TillerManDistance => -4; - - public override Point2D StarboardOffset => new Point2D(2, 0); - public override Point2D PortOffset => new Point2D(-2, 0); - - public override Point3D MarkOffset => new Point3D(0, 1, 3); - - public override BaseDockedBoat DockedBoat => new SmallDockedDragonBoat(this); - - public override void Deserialize(IGenericReader reader) + public class SmallDockedDragonBoat : BaseDockedBoat { - base.Deserialize(reader); + public SmallDockedDragonBoat(BaseBoat boat) : base(0x4, Point3D.Zero, boat) + { + } - int version = reader.ReadInt(); + public SmallDockedDragonBoat(Serial serial) : base(serial) + { + } + + public override BaseBoat Boat => new SmallDragonBoat(); + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); + } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - } - - public class SmallDragonBoatDeed : BaseBoatDeed - { - [Constructible] - public SmallDragonBoatDeed() : base(0x4, Point3D.Zero) - { - } - - public SmallDragonBoatDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041206; // small dragon ship deed - public override BaseBoat Boat => new SmallDragonBoat(); - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - } - - public class SmallDockedDragonBoat : BaseDockedBoat - { - public SmallDockedDragonBoat(BaseBoat boat) : base(0x4, Point3D.Zero, boat) - { - } - - public SmallDockedDragonBoat(Serial serial) : base(serial) - { - } - - public override BaseBoat Boat => new SmallDragonBoat(); - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Multis/Boats/Strandedness.cs b/Projects/UOContent/Multis/Boats/Strandedness.cs index a9bdf0a40..039b999a2 100644 --- a/Projects/UOContent/Multis/Boats/Strandedness.cs +++ b/Projects/UOContent/Multis/Boats/Strandedness.cs @@ -1,176 +1,176 @@ namespace Server.Misc { - public class Strandedness - { - private static readonly Point2D[] m_Felucca = + public class Strandedness { - new Point2D(2528, 3568), new Point2D(2376, 3400), new Point2D(2528, 3896), - new Point2D(2168, 3904), new Point2D(1136, 3416), new Point2D(1432, 3648), - new Point2D(1416, 4000), new Point2D(4512, 3936), new Point2D(4440, 3120), - new Point2D(4192, 3672), new Point2D(4720, 3472), new Point2D(3744, 2768), - new Point2D(3480, 2432), new Point2D(3560, 2136), new Point2D(3792, 2112), - new Point2D(2800, 2296), new Point2D(2736, 2016), new Point2D(4576, 1456), - new Point2D(4680, 1152), new Point2D(4304, 1104), new Point2D(4496, 984), - new Point2D(4248, 696), new Point2D(4040, 616), new Point2D(3896, 248), - new Point2D(4176, 384), new Point2D(3672, 1104), new Point2D(3520, 1152), - new Point2D(3720, 1360), new Point2D(2184, 2152), new Point2D(1952, 2088), - new Point2D(2056, 1936), new Point2D(1720, 1992), new Point2D(472, 2064), - new Point2D(656, 2096), new Point2D(3008, 3592), new Point2D(2784, 3472), - new Point2D(5456, 2400), new Point2D(5976, 2424), new Point2D(5328, 3112), - new Point2D(5792, 3152), new Point2D(2120, 3616), new Point2D(2136, 3128), - new Point2D(1632, 3528), new Point2D(1328, 3160), new Point2D(1072, 3136), - new Point2D(1128, 2976), new Point2D(960, 2576), new Point2D(752, 1832), - new Point2D(184, 1488), new Point2D(592, 1440), new Point2D(368, 1216), - new Point2D(232, 752), new Point2D(696, 744), new Point2D(304, 1000), - new Point2D(840, 376), new Point2D(1192, 624), new Point2D(1200, 192), - new Point2D(1512, 240), new Point2D(1336, 456), new Point2D(1536, 648), - new Point2D(1104, 952), new Point2D(1864, 264), new Point2D(2136, 200), - new Point2D(2160, 528), new Point2D(1904, 512), new Point2D(2240, 784), - new Point2D(2536, 776), new Point2D(2488, 216), new Point2D(2336, 72), - new Point2D(2648, 288), new Point2D(2680, 576), new Point2D(2896, 88), - new Point2D(2840, 344), new Point2D(3136, 72), new Point2D(2968, 520), - new Point2D(3192, 328), new Point2D(3448, 208), new Point2D(3432, 608), - new Point2D(3184, 752), new Point2D(2800, 704), new Point2D(2768, 1016), - new Point2D(2448, 1232), new Point2D(2272, 920), new Point2D(2072, 1080), - new Point2D(2048, 1264), new Point2D(1808, 1528), new Point2D(1496, 1880), - new Point2D(1656, 2168), new Point2D(2096, 2320), new Point2D(1816, 2528), - new Point2D(1840, 2640), new Point2D(1928, 2952), new Point2D(2120, 2712) - }; - - private static readonly Point2D[] m_Trammel = m_Felucca; - - private static readonly Point2D[] m_Ilshenar = - { - new Point2D(1252, 1180), new Point2D(1562, 1090), new Point2D(1444, 1016), - new Point2D(1324, 968), new Point2D(1418, 806), new Point2D(1722, 874), - new Point2D(1456, 684), new Point2D(1036, 866), new Point2D(612, 476), - new Point2D(1476, 372), new Point2D(762, 472), new Point2D(812, 1162), - new Point2D(1422, 1144), new Point2D(1254, 1066), new Point2D(1598, 870), - new Point2D(1358, 866), new Point2D(510, 302), new Point2D(510, 392) - }; - - private static readonly Point2D[] m_Tokuno = - { - // Makoto-Jima - new Point2D(837, 1351), new Point2D(941, 1241), new Point2D(959, 1185), - new Point2D(923, 1091), new Point2D(904, 983), new Point2D(845, 944), - new Point2D(829, 896), new Point2D(794, 852), new Point2D(766, 821), - new Point2D(695, 814), new Point2D(576, 835), new Point2D(518, 840), - new Point2D(519, 902), new Point2D(502, 950), new Point2D(503, 1045), - new Point2D(547, 1131), new Point2D(518, 1204), new Point2D(506, 1243), - new Point2D(526, 1271), new Point2D(562, 1295), new Point2D(616, 1335), - new Point2D(789, 1347), new Point2D(712, 1359), - - // Homare-Jima - new Point2D(202, 498), new Point2D(116, 600), new Point2D(107, 699), - new Point2D(162, 799), new Point2D(158, 889), new Point2D(169, 989), - new Point2D(194, 1101), new Point2D(250, 1163), new Point2D(295, 1176), - new Point2D(280, 1194), new Point2D(286, 1102), new Point2D(250, 1000), - new Point2D(260, 906), new Point2D(360, 838), new Point2D(389, 763), - new Point2D(415, 662), new Point2D(500, 597), new Point2D(570, 572), - new Point2D(631, 577), new Point2D(692, 500), new Point2D(723, 445), - new Point2D(672, 379), new Point2D(626, 332), new Point2D(494, 291), - new Point2D(371, 336), new Point2D(324, 334), new Point2D(270, 362), - - // Isamu-Jima - new Point2D(1240, 1076), new Point2D(1189, 1115), new Point2D(1046, 1039), - new Point2D(1025, 885), new Point2D(907, 809), new Point2D(840, 506), - new Point2D(799, 396), new Point2D(720, 258), new Point2D(744, 158), - new Point2D(904, 37), new Point2D(974, 91), new Point2D(1020, 187), - new Point2D(1035, 288), new Point2D(1104, 395), new Point2D(1215, 462), - new Point2D(1275, 488), new Point2D(1348, 611), new Point2D(1363, 739), - new Point2D(1364, 765), new Point2D(1364, 876), new Point2D(1300, 936), - new Point2D(1240, 1003) - }; - - public static void Initialize() - { - EventSink.Login += EventSink_Login; - } - - private static bool IsStranded(Mobile from) - { - Map map = from.Map; - - if (map == null) - return false; - - object surface = map.GetTopSurface(from.Location); - - if (surface is LandTile tile) - { - int id = tile.ID; - - return (id >= 168 && id <= 171) - || (id >= 310 && id <= 311); - } - - if (surface is StaticTile staticTile) - { - int id = staticTile.ID; - - return id >= 0x1796 && id <= 0x17B2; - } - - return false; - } - - public static void EventSink_Login(Mobile from) - { - if (!IsStranded(from)) - return; - - Map map = from.Map; - - Point2D[] list; - - if (map == Map.Felucca) - list = m_Felucca; - else if (map == Map.Trammel) - list = m_Trammel; - else if (map == Map.Ilshenar) - list = m_Ilshenar; - else if (map == Map.Tokuno) - list = m_Tokuno; - else - return; - - Point2D p = Point2D.Zero; - double pdist = double.MaxValue; - - for (int i = 0; i < list.Length; ++i) - { - double dist = from.GetDistanceToSqrt(list[i]); - - if (dist < pdist) + private static readonly Point2D[] m_Felucca = { - p = list[i]; - pdist = dist; + new Point2D(2528, 3568), new Point2D(2376, 3400), new Point2D(2528, 3896), + new Point2D(2168, 3904), new Point2D(1136, 3416), new Point2D(1432, 3648), + new Point2D(1416, 4000), new Point2D(4512, 3936), new Point2D(4440, 3120), + new Point2D(4192, 3672), new Point2D(4720, 3472), new Point2D(3744, 2768), + new Point2D(3480, 2432), new Point2D(3560, 2136), new Point2D(3792, 2112), + new Point2D(2800, 2296), new Point2D(2736, 2016), new Point2D(4576, 1456), + new Point2D(4680, 1152), new Point2D(4304, 1104), new Point2D(4496, 984), + new Point2D(4248, 696), new Point2D(4040, 616), new Point2D(3896, 248), + new Point2D(4176, 384), new Point2D(3672, 1104), new Point2D(3520, 1152), + new Point2D(3720, 1360), new Point2D(2184, 2152), new Point2D(1952, 2088), + new Point2D(2056, 1936), new Point2D(1720, 1992), new Point2D(472, 2064), + new Point2D(656, 2096), new Point2D(3008, 3592), new Point2D(2784, 3472), + new Point2D(5456, 2400), new Point2D(5976, 2424), new Point2D(5328, 3112), + new Point2D(5792, 3152), new Point2D(2120, 3616), new Point2D(2136, 3128), + new Point2D(1632, 3528), new Point2D(1328, 3160), new Point2D(1072, 3136), + new Point2D(1128, 2976), new Point2D(960, 2576), new Point2D(752, 1832), + new Point2D(184, 1488), new Point2D(592, 1440), new Point2D(368, 1216), + new Point2D(232, 752), new Point2D(696, 744), new Point2D(304, 1000), + new Point2D(840, 376), new Point2D(1192, 624), new Point2D(1200, 192), + new Point2D(1512, 240), new Point2D(1336, 456), new Point2D(1536, 648), + new Point2D(1104, 952), new Point2D(1864, 264), new Point2D(2136, 200), + new Point2D(2160, 528), new Point2D(1904, 512), new Point2D(2240, 784), + new Point2D(2536, 776), new Point2D(2488, 216), new Point2D(2336, 72), + new Point2D(2648, 288), new Point2D(2680, 576), new Point2D(2896, 88), + new Point2D(2840, 344), new Point2D(3136, 72), new Point2D(2968, 520), + new Point2D(3192, 328), new Point2D(3448, 208), new Point2D(3432, 608), + new Point2D(3184, 752), new Point2D(2800, 704), new Point2D(2768, 1016), + new Point2D(2448, 1232), new Point2D(2272, 920), new Point2D(2072, 1080), + new Point2D(2048, 1264), new Point2D(1808, 1528), new Point2D(1496, 1880), + new Point2D(1656, 2168), new Point2D(2096, 2320), new Point2D(1816, 2528), + new Point2D(1840, 2640), new Point2D(1928, 2952), new Point2D(2120, 2712) + }; + + private static readonly Point2D[] m_Trammel = m_Felucca; + + private static readonly Point2D[] m_Ilshenar = + { + new Point2D(1252, 1180), new Point2D(1562, 1090), new Point2D(1444, 1016), + new Point2D(1324, 968), new Point2D(1418, 806), new Point2D(1722, 874), + new Point2D(1456, 684), new Point2D(1036, 866), new Point2D(612, 476), + new Point2D(1476, 372), new Point2D(762, 472), new Point2D(812, 1162), + new Point2D(1422, 1144), new Point2D(1254, 1066), new Point2D(1598, 870), + new Point2D(1358, 866), new Point2D(510, 302), new Point2D(510, 392) + }; + + private static readonly Point2D[] m_Tokuno = + { + // Makoto-Jima + new Point2D(837, 1351), new Point2D(941, 1241), new Point2D(959, 1185), + new Point2D(923, 1091), new Point2D(904, 983), new Point2D(845, 944), + new Point2D(829, 896), new Point2D(794, 852), new Point2D(766, 821), + new Point2D(695, 814), new Point2D(576, 835), new Point2D(518, 840), + new Point2D(519, 902), new Point2D(502, 950), new Point2D(503, 1045), + new Point2D(547, 1131), new Point2D(518, 1204), new Point2D(506, 1243), + new Point2D(526, 1271), new Point2D(562, 1295), new Point2D(616, 1335), + new Point2D(789, 1347), new Point2D(712, 1359), + + // Homare-Jima + new Point2D(202, 498), new Point2D(116, 600), new Point2D(107, 699), + new Point2D(162, 799), new Point2D(158, 889), new Point2D(169, 989), + new Point2D(194, 1101), new Point2D(250, 1163), new Point2D(295, 1176), + new Point2D(280, 1194), new Point2D(286, 1102), new Point2D(250, 1000), + new Point2D(260, 906), new Point2D(360, 838), new Point2D(389, 763), + new Point2D(415, 662), new Point2D(500, 597), new Point2D(570, 572), + new Point2D(631, 577), new Point2D(692, 500), new Point2D(723, 445), + new Point2D(672, 379), new Point2D(626, 332), new Point2D(494, 291), + new Point2D(371, 336), new Point2D(324, 334), new Point2D(270, 362), + + // Isamu-Jima + new Point2D(1240, 1076), new Point2D(1189, 1115), new Point2D(1046, 1039), + new Point2D(1025, 885), new Point2D(907, 809), new Point2D(840, 506), + new Point2D(799, 396), new Point2D(720, 258), new Point2D(744, 158), + new Point2D(904, 37), new Point2D(974, 91), new Point2D(1020, 187), + new Point2D(1035, 288), new Point2D(1104, 395), new Point2D(1215, 462), + new Point2D(1275, 488), new Point2D(1348, 611), new Point2D(1363, 739), + new Point2D(1364, 765), new Point2D(1364, 876), new Point2D(1300, 936), + new Point2D(1240, 1003) + }; + + public static void Initialize() + { + EventSink.Login += EventSink_Login; } - } - int x = p.X, y = p.Y; - int z; - bool canFit; + private static bool IsStranded(Mobile from) + { + var map = from.Map; - z = map.GetAverageZ(x, y); - canFit = map.CanSpawnMobile(x, y, z); + if (map == null) + return false; - for (int i = 1; !canFit && i <= 40; i += 2) - for (int xo = -1; !canFit && xo <= 1; ++xo) - for (int yo = -1; !canFit && yo <= 1; ++yo) - { - if (xo == 0 && yo == 0) - continue; + var surface = map.GetTopSurface(from.Location); + + if (surface is LandTile tile) + { + var id = tile.ID; + + return id >= 168 && id <= 171 + || id >= 310 && id <= 311; + } + + if (surface is StaticTile staticTile) + { + var id = staticTile.ID; + + return id >= 0x1796 && id <= 0x17B2; + } + + return false; + } + + public static void EventSink_Login(Mobile from) + { + if (!IsStranded(from)) + return; + + var map = from.Map; + + Point2D[] list; + + if (map == Map.Felucca) + list = m_Felucca; + else if (map == Map.Trammel) + list = m_Trammel; + else if (map == Map.Ilshenar) + list = m_Ilshenar; + else if (map == Map.Tokuno) + list = m_Tokuno; + else + return; + + var p = Point2D.Zero; + var pdist = double.MaxValue; + + for (var i = 0; i < list.Length; ++i) + { + var dist = from.GetDistanceToSqrt(list[i]); + + if (dist < pdist) + { + p = list[i]; + pdist = dist; + } + } + + int x = p.X, y = p.Y; + int z; + bool canFit; - x = p.X + xo * i; - y = p.Y + yo * i; z = map.GetAverageZ(x, y); canFit = map.CanSpawnMobile(x, y, z); - } - if (canFit) - from.Location = new Point3D(x, y, z); + for (var i = 1; !canFit && i <= 40; i += 2) + for (var xo = -1; !canFit && xo <= 1; ++xo) + for (var yo = -1; !canFit && yo <= 1; ++yo) + { + if (xo == 0 && yo == 0) + continue; + + x = p.X + xo * i; + y = p.Y + yo * i; + z = map.GetAverageZ(x, y); + canFit = map.CanSpawnMobile(x, y, z); + } + + if (canFit) + from.Location = new Point3D(x, y, z); + } } - } } diff --git a/Projects/UOContent/Multis/Boats/TillerMan.cs b/Projects/UOContent/Multis/Boats/TillerMan.cs index 010cee450..50dad2627 100644 --- a/Projects/UOContent/Multis/Boats/TillerMan.cs +++ b/Projects/UOContent/Multis/Boats/TillerMan.cs @@ -3,113 +3,113 @@ using Server.Network; namespace Server.Items { - public class TillerMan : Item - { - private BaseBoat m_Boat; - - public TillerMan(BaseBoat boat) : base(0x3E4E) + public class TillerMan : Item { - m_Boat = boat; - Movable = false; + private BaseBoat m_Boat; + + public TillerMan(BaseBoat boat) : base(0x3E4E) + { + m_Boat = boat; + Movable = false; + } + + public TillerMan(Serial serial) : base(serial) + { + } + + public void SetFacing(Direction dir) + { + ItemID = dir switch + { + Direction.South => 0x3E4B, + Direction.North => 0x3E4E, + Direction.West => 0x3E50, + Direction.East => 0x3E55, + _ => ItemID + }; + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(m_Boat.Status); + } + + public void Say(int number) + { + PublicOverheadMessage(MessageType.Regular, 0x3B2, number); + } + + public void Say(int number, string args) + { + PublicOverheadMessage(MessageType.Regular, 0x3B2, number, args); + } + + public override void AddNameProperty(ObjectPropertyList list) + { + if (m_Boat?.ShipName != null) + list.Add(1042884, m_Boat.ShipName); // the tiller man of the ~1_SHIP_NAME~ + else + base.AddNameProperty(list); + } + + public override void OnSingleClick(Mobile from) + { + if (m_Boat?.ShipName != null) + LabelTo(from, 1042884, m_Boat.ShipName); // the tiller man of the ~1_SHIP_NAME~ + else + base.OnSingleClick(from); + } + + public override void OnDoubleClick(Mobile from) + { + if (m_Boat?.Contains(from) == true) + m_Boat.BeginRename(from); + else + m_Boat?.BeginDryDock(from); + } + + public override bool OnDragDrop(Mobile from, Item dropped) + { + if (dropped is MapItem item && m_Boat?.CanCommand(from) == true && m_Boat.Contains(from)) + m_Boat.AssociateMap(item); + + return false; + } + + public override void OnAfterDelete() + { + m_Boat?.Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Boat); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Boat = reader.ReadItem() as BaseBoat; + + if (m_Boat == null) + Delete(); + + break; + } + } + } } - - public TillerMan(Serial serial) : base(serial) - { - } - - public void SetFacing(Direction dir) - { - ItemID = dir switch - { - Direction.South => 0x3E4B, - Direction.North => 0x3E4E, - Direction.West => 0x3E50, - Direction.East => 0x3E55, - _ => ItemID - }; - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(m_Boat.Status); - } - - public void Say(int number) - { - PublicOverheadMessage(MessageType.Regular, 0x3B2, number); - } - - public void Say(int number, string args) - { - PublicOverheadMessage(MessageType.Regular, 0x3B2, number, args); - } - - public override void AddNameProperty(ObjectPropertyList list) - { - if (m_Boat?.ShipName != null) - list.Add(1042884, m_Boat.ShipName); // the tiller man of the ~1_SHIP_NAME~ - else - base.AddNameProperty(list); - } - - public override void OnSingleClick(Mobile from) - { - if (m_Boat?.ShipName != null) - LabelTo(from, 1042884, m_Boat.ShipName); // the tiller man of the ~1_SHIP_NAME~ - else - base.OnSingleClick(from); - } - - public override void OnDoubleClick(Mobile from) - { - if (m_Boat?.Contains(from) == true) - m_Boat.BeginRename(from); - else - m_Boat?.BeginDryDock(from); - } - - public override bool OnDragDrop(Mobile from, Item dropped) - { - if (dropped is MapItem item && m_Boat?.CanCommand(from) == true && m_Boat.Contains(from)) - m_Boat.AssociateMap(item); - - return false; - } - - public override void OnAfterDelete() - { - m_Boat?.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Boat); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Boat = reader.ReadItem() as BaseBoat; - - if (m_Boat == null) - Delete(); - - break; - } - } - } - } } diff --git a/Projects/UOContent/Multis/Camps/BankerCamp.cs b/Projects/UOContent/Multis/Camps/BankerCamp.cs index 7adf38559..3b2666439 100644 --- a/Projects/UOContent/Multis/Camps/BankerCamp.cs +++ b/Projects/UOContent/Multis/Camps/BankerCamp.cs @@ -3,45 +3,45 @@ using Server.Mobiles; namespace Server.Multis { - public class BankerCamp : BaseCamp - { - [Constructible] - public BankerCamp() : base(0x1F6) + public class BankerCamp : BaseCamp { + [Constructible] + public BankerCamp() : base(0x1F6) + { + } + + public BankerCamp(Serial serial) : base(serial) + { + } + + public override void AddComponents() + { + BaseDoor west, east; + + AddItem(west = new LightWoodGate(DoorFacing.WestCW), -4, 4, 7); + AddItem(east = new LightWoodGate(DoorFacing.EastCCW), -3, 4, 7); + + west.Link = east; + east.Link = west; + + AddItem(new Sign(SignType.Bank, SignFacing.West), -5, 5, -4); + + AddMobile(new Banker(), 4, -4, 3, 7); + AddMobile(new Banker(), 5, 4, -2, 0); + } + + 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 BankerCamp(Serial serial) : base(serial) - { - } - - public override void AddComponents() - { - BaseDoor west, east; - - AddItem(west = new LightWoodGate(DoorFacing.WestCW), -4, 4, 7); - AddItem(east = new LightWoodGate(DoorFacing.EastCCW), -3, 4, 7); - - west.Link = east; - east.Link = west; - - AddItem(new Sign(SignType.Bank, SignFacing.West), -5, 5, -4); - - AddMobile(new Banker(), 4, -4, 3, 7); - AddMobile(new Banker(), 5, 4, -2, 0); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Multis/Camps/BaseCamp.cs b/Projects/UOContent/Multis/Camps/BaseCamp.cs index 094495df4..d72843959 100644 --- a/Projects/UOContent/Multis/Camps/BaseCamp.cs +++ b/Projects/UOContent/Multis/Camps/BaseCamp.cs @@ -5,193 +5,193 @@ using Server.Mobiles; namespace Server.Multis { - public abstract class BaseCamp : BaseMulti - { - private TimeSpan m_DecayDelay; - private DateTime m_DecayTime; - private Timer m_DecayTimer; - private List m_Items; - private List m_Mobiles; - - public BaseCamp(int multiID) : base(multiID) + public abstract class BaseCamp : BaseMulti { - m_Items = new List(); - m_Mobiles = new List(); - m_DecayDelay = TimeSpan.FromMinutes(30.0); - RefreshDecay(true); + private TimeSpan m_DecayDelay; + private DateTime m_DecayTime; + private Timer m_DecayTimer; + private List m_Items; + private List m_Mobiles; - Timer.DelayCall(CheckAddComponents); + public BaseCamp(int multiID) : base(multiID) + { + m_Items = new List(); + m_Mobiles = new List(); + m_DecayDelay = TimeSpan.FromMinutes(30.0); + RefreshDecay(true); + + Timer.DelayCall(CheckAddComponents); + } + + public BaseCamp(Serial serial) : base(serial) + { + } + + public virtual int EventRange => 10; + + public virtual TimeSpan DecayDelay + { + get => m_DecayDelay; + set + { + m_DecayDelay = value; + RefreshDecay(true); + } + } + + public override bool HandlesOnMovement => true; + + public void CheckAddComponents() + { + if (Deleted) + return; + + AddComponents(); + } + + public virtual void AddComponents() + { + } + + public virtual void RefreshDecay(bool setDecayTime) + { + if (Deleted) + return; + + m_DecayTimer?.Stop(); + + if (setDecayTime) + m_DecayTime = DateTime.UtcNow + DecayDelay; + + m_DecayTimer = Timer.DelayCall(DecayDelay, Delete); + } + + public virtual void AddItem(Item item, int xOffset, int yOffset, int zOffset) + { + m_Items.Add(item); + + var zavg = Map.GetAverageZ(X + xOffset, Y + yOffset); + item.MoveToWorld(new Point3D(X + xOffset, Y + yOffset, zavg + zOffset), Map); + } + + public virtual void AddMobile(Mobile m, int wanderRange, int xOffset, int yOffset, int zOffset) + { + m_Mobiles.Add(m); + + var zavg = Map.GetAverageZ(X + xOffset, Y + yOffset); + var loc = new Point3D(X + xOffset, Y + yOffset, zavg + zOffset); + + if (m is BaseCreature bc) + { + bc.RangeHome = wanderRange; + bc.Home = loc; + } + + if (m is BaseVendor) + m.Direction = Direction.South; + + m.MoveToWorld(loc, Map); + } + + public virtual void OnEnter(Mobile m) + { + RefreshDecay(true); + } + + public virtual void OnExit(Mobile m) + { + RefreshDecay(true); + } + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + var inOldRange = Utility.InRange(oldLocation, Location, EventRange); + var inNewRange = Utility.InRange(m.Location, Location, EventRange); + + if (inNewRange && !inOldRange) + OnEnter(m); + else if (inOldRange && !inNewRange) + OnExit(m); + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + for (var i = 0; i < m_Items.Count; ++i) + m_Items[i].Delete(); + + for (var i = 0; i < m_Mobiles.Count; ++i) + { + var bc = (BaseCreature)m_Mobiles[i]; + + if (bc.IsPrisoner == false) + m_Mobiles[i].Delete(); + else if (m_Mobiles[i].CantWalk) + m_Mobiles[i].Delete(); + } + + m_Items.Clear(); + m_Mobiles.Clear(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Items, true); + writer.Write(m_Mobiles, true); + writer.WriteDeltaTime(m_DecayTime); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Items = reader.ReadStrongItemList(); + m_Mobiles = reader.ReadStrongMobileList(); + m_DecayTime = reader.ReadDeltaTime(); + + RefreshDecay(false); + + break; + } + } + } } - public BaseCamp(Serial serial) : base(serial) + public class LockableBarrel : LockableContainer { + [Constructible] + public LockableBarrel() : base(0xE77) => Weight = 1.0; + + public LockableBarrel(Serial serial) : base(serial) + { + } + + 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 (Weight == 8.0) + Weight = 1.0; + } } - - public virtual int EventRange => 10; - - public virtual TimeSpan DecayDelay - { - get => m_DecayDelay; - set - { - m_DecayDelay = value; - RefreshDecay(true); - } - } - - public override bool HandlesOnMovement => true; - - public void CheckAddComponents() - { - if (Deleted) - return; - - AddComponents(); - } - - public virtual void AddComponents() - { - } - - public virtual void RefreshDecay(bool setDecayTime) - { - if (Deleted) - return; - - m_DecayTimer?.Stop(); - - if (setDecayTime) - m_DecayTime = DateTime.UtcNow + DecayDelay; - - m_DecayTimer = Timer.DelayCall(DecayDelay, Delete); - } - - public virtual void AddItem(Item item, int xOffset, int yOffset, int zOffset) - { - m_Items.Add(item); - - int zavg = Map.GetAverageZ(X + xOffset, Y + yOffset); - item.MoveToWorld(new Point3D(X + xOffset, Y + yOffset, zavg + zOffset), Map); - } - - public virtual void AddMobile(Mobile m, int wanderRange, int xOffset, int yOffset, int zOffset) - { - m_Mobiles.Add(m); - - int zavg = Map.GetAverageZ(X + xOffset, Y + yOffset); - Point3D loc = new Point3D(X + xOffset, Y + yOffset, zavg + zOffset); - - if (m is BaseCreature bc) - { - bc.RangeHome = wanderRange; - bc.Home = loc; - } - - if (m is BaseVendor) - m.Direction = Direction.South; - - m.MoveToWorld(loc, Map); - } - - public virtual void OnEnter(Mobile m) - { - RefreshDecay(true); - } - - public virtual void OnExit(Mobile m) - { - RefreshDecay(true); - } - - public override void OnMovement(Mobile m, Point3D oldLocation) - { - bool inOldRange = Utility.InRange(oldLocation, Location, EventRange); - bool inNewRange = Utility.InRange(m.Location, Location, EventRange); - - if (inNewRange && !inOldRange) - OnEnter(m); - else if (inOldRange && !inNewRange) - OnExit(m); - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - for (int i = 0; i < m_Items.Count; ++i) - m_Items[i].Delete(); - - for (int i = 0; i < m_Mobiles.Count; ++i) - { - BaseCreature bc = (BaseCreature)m_Mobiles[i]; - - if (bc.IsPrisoner == false) - m_Mobiles[i].Delete(); - else if (m_Mobiles[i].CantWalk) - m_Mobiles[i].Delete(); - } - - m_Items.Clear(); - m_Mobiles.Clear(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Items, true); - writer.Write(m_Mobiles, true); - writer.WriteDeltaTime(m_DecayTime); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Items = reader.ReadStrongItemList(); - m_Mobiles = reader.ReadStrongMobileList(); - m_DecayTime = reader.ReadDeltaTime(); - - RefreshDecay(false); - - break; - } - } - } - } - - public class LockableBarrel : LockableContainer - { - [Constructible] - public LockableBarrel() : base(0xE77) => Weight = 1.0; - - public LockableBarrel(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 8.0) - Weight = 1.0; - } - } } diff --git a/Projects/UOContent/Multis/Camps/BrigandCamp.cs b/Projects/UOContent/Multis/Camps/BrigandCamp.cs index abc6d1b75..7c4cc9f2f 100644 --- a/Projects/UOContent/Multis/Camps/BrigandCamp.cs +++ b/Projects/UOContent/Multis/Camps/BrigandCamp.cs @@ -4,177 +4,177 @@ using Server.Mobiles; namespace Server.Multis { - public class BrigandCamp : BaseCamp - { - private Mobile m_Prisoner; - - [Constructible] - public BrigandCamp() : base(0x10EE) // dummy garbage at center + public class BrigandCamp : BaseCamp { - } + private Mobile m_Prisoner; - public BrigandCamp(Serial serial) : base(serial) - { - } - - public virtual Mobile Brigands => new Brigand(); - public virtual Mobile Executioners => new Executioner(); - - public override void AddComponents() - { - Visible = false; - DecayDelay = TimeSpan.FromMinutes(5.0); - - AddItem(new Static(0x10ee), 0, 0, 0); - AddItem(new Static(0xfac), 0, 7, 0); - - switch (Utility.Random(3)) - { - case 0: - { - AddItem(new Item(0xDE3), 0, 7, 0); // Campfire - AddItem(new Item(0x974), 0, 7, 1); // Cauldron - break; - } - case 1: - { - AddItem(new Item(0x1E95), 0, 7, 1); // Rabbit on a spit - break; - } - default: - { - AddItem(new Item(0x1E94), 0, 7, 1); // Chicken on a spit - break; - } - } - - AddCampChests(); - - for (int i = 0; i < 4; i++) AddMobile(Brigands, 6, Utility.RandomMinMax(-7, 7), Utility.RandomMinMax(-7, 7), 0); - - BaseCreature bc = Utility.Random(2) switch - { - 0 => new Noble(), - _ => new SeekerOfAdventure() - }; - - bc.IsPrisoner = true; - bc.CantWalk = true; - m_Prisoner = bc; - - m_Prisoner.YellHue = Utility.RandomList(0x57, 0x67, 0x77, 0x87, 0x117); - AddMobile(m_Prisoner, 2, Utility.RandomMinMax(-2, 2), Utility.RandomMinMax(-2, 2), 0); - } - - private void AddCampChests() - { - LockableContainer chest = Utility.Random(3) switch - { - 0 => new MetalChest(), - 1 => new MetalGoldenChest(), - _ => new WoodenChest() - }; - - chest.LiftOverride = true; - - TreasureMapChest.Fill(chest, 1); - - AddItem(chest, -2, -2, 0); - - LockableContainer crates = Utility.Random(4) switch - { - 0 => new SmallCrate(), - 1 => new MediumCrate(), - 2 => new LargeCrate(), - _ => new LockableBarrel() - }; - - crates.TrapType = TrapType.ExplosionTrap; - crates.TrapPower = Utility.RandomMinMax(30, 40); - crates.TrapLevel = 2; - - crates.RequiredSkill = 76; - crates.LockLevel = 66; - crates.MaxLockLevel = 116; - crates.Locked = true; - - crates.DropItem(new Gold(Utility.RandomMinMax(100, 400))); - crates.DropItem(new Arrow(10)); - crates.DropItem(new Bolt(10)); - - crates.LiftOverride = true; - - crates.DropItem( - Utility.Random(5) switch + [Constructible] + public BrigandCamp() : base(0x10EE) // dummy garbage at center { - 0 => new LesserCurePotion(), - 1 => new LesserExplosionPotion(), - 2 => new LesserHealPotion(), - 3 => new LesserPoisonPotion(), - _ => null // 4 } - ); - AddItem(crates, 2, 2, 0); - } - - // Don't refresh decay timer - public override void OnEnter(Mobile m) - { - if (m.Player && m_Prisoner?.CantWalk == true) - { - var number = Utility.Random(8) switch + public BrigandCamp(Serial serial) : base(serial) { - 0 => 502261, - 1 => 502262, - 2 => 502263, - 3 => 502264, - 4 => 502265, - 5 => 502266, - 6 => 502267, - _ => 502268 - }; + } - m_Prisoner.Yell(number); - } + public virtual Mobile Brigands => new Brigand(); + public virtual Mobile Executioners => new Executioner(); + + public override void AddComponents() + { + Visible = false; + DecayDelay = TimeSpan.FromMinutes(5.0); + + AddItem(new Static(0x10ee), 0, 0, 0); + AddItem(new Static(0xfac), 0, 7, 0); + + switch (Utility.Random(3)) + { + case 0: + { + AddItem(new Item(0xDE3), 0, 7, 0); // Campfire + AddItem(new Item(0x974), 0, 7, 1); // Cauldron + break; + } + case 1: + { + AddItem(new Item(0x1E95), 0, 7, 1); // Rabbit on a spit + break; + } + default: + { + AddItem(new Item(0x1E94), 0, 7, 1); // Chicken on a spit + break; + } + } + + AddCampChests(); + + for (var i = 0; i < 4; i++) AddMobile(Brigands, 6, Utility.RandomMinMax(-7, 7), Utility.RandomMinMax(-7, 7), 0); + + BaseCreature bc = Utility.Random(2) switch + { + 0 => new Noble(), + _ => new SeekerOfAdventure() + }; + + bc.IsPrisoner = true; + bc.CantWalk = true; + m_Prisoner = bc; + + m_Prisoner.YellHue = Utility.RandomList(0x57, 0x67, 0x77, 0x87, 0x117); + AddMobile(m_Prisoner, 2, Utility.RandomMinMax(-2, 2), Utility.RandomMinMax(-2, 2), 0); + } + + private void AddCampChests() + { + LockableContainer chest = Utility.Random(3) switch + { + 0 => new MetalChest(), + 1 => new MetalGoldenChest(), + _ => new WoodenChest() + }; + + chest.LiftOverride = true; + + TreasureMapChest.Fill(chest, 1); + + AddItem(chest, -2, -2, 0); + + LockableContainer crates = Utility.Random(4) switch + { + 0 => new SmallCrate(), + 1 => new MediumCrate(), + 2 => new LargeCrate(), + _ => new LockableBarrel() + }; + + crates.TrapType = TrapType.ExplosionTrap; + crates.TrapPower = Utility.RandomMinMax(30, 40); + crates.TrapLevel = 2; + + crates.RequiredSkill = 76; + crates.LockLevel = 66; + crates.MaxLockLevel = 116; + crates.Locked = true; + + crates.DropItem(new Gold(Utility.RandomMinMax(100, 400))); + crates.DropItem(new Arrow(10)); + crates.DropItem(new Bolt(10)); + + crates.LiftOverride = true; + + crates.DropItem( + Utility.Random(5) switch + { + 0 => new LesserCurePotion(), + 1 => new LesserExplosionPotion(), + 2 => new LesserHealPotion(), + 3 => new LesserPoisonPotion(), + _ => null // 4 + } + ); + + AddItem(crates, 2, 2, 0); + } + + // Don't refresh decay timer + public override void OnEnter(Mobile m) + { + if (m.Player && m_Prisoner?.CantWalk == true) + { + var number = Utility.Random(8) switch + { + 0 => 502261, + 1 => 502262, + 2 => 502263, + 3 => 502264, + 4 => 502265, + 5 => 502266, + 6 => 502267, + _ => 502268 + }; + + m_Prisoner.Yell(number); + } + } + + // Don't refresh decay timer + public override void OnExit(Mobile m) + { + } + + public override void AddItem(Item item, int xOffset, int yOffset, int zOffset) + { + if (item != null) + item.Movable = false; + + base.AddItem(item, xOffset, yOffset, zOffset); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Prisoner); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Prisoner = reader.ReadMobile(); + break; + } + } + } } - - // Don't refresh decay timer - public override void OnExit(Mobile m) - { - } - - public override void AddItem(Item item, int xOffset, int yOffset, int zOffset) - { - if (item != null) - item.Movable = false; - - base.AddItem(item, xOffset, yOffset, zOffset); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Prisoner); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Prisoner = reader.ReadMobile(); - break; - } - } - } - } } diff --git a/Projects/UOContent/Multis/Camps/HealerCamp.cs b/Projects/UOContent/Multis/Camps/HealerCamp.cs index 768cf4815..8d461bb0f 100644 --- a/Projects/UOContent/Multis/Camps/HealerCamp.cs +++ b/Projects/UOContent/Multis/Camps/HealerCamp.cs @@ -3,45 +3,45 @@ using Server.Mobiles; namespace Server.Multis { - public class HealerCamp : BaseCamp - { - [Constructible] - public HealerCamp() : base(0x1F4) + public class HealerCamp : BaseCamp { + [Constructible] + public HealerCamp() : base(0x1F4) + { + } + + public HealerCamp(Serial serial) : base(serial) + { + } + + public override void AddComponents() + { + BaseDoor west, east; + + AddItem(west = new LightWoodGate(DoorFacing.WestCW), -4, 4, 7); + AddItem(east = new LightWoodGate(DoorFacing.EastCCW), -3, 4, 7); + + west.Link = east; + east.Link = west; + + AddItem(new Sign(SignType.Healer, SignFacing.West), -5, 5, -4); + + AddMobile(new Healer(), 4, -4, 3, 7); + AddMobile(new Healer(), 5, 4, -2, 0); + } + + 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 HealerCamp(Serial serial) : base(serial) - { - } - - public override void AddComponents() - { - BaseDoor west, east; - - AddItem(west = new LightWoodGate(DoorFacing.WestCW), -4, 4, 7); - AddItem(east = new LightWoodGate(DoorFacing.EastCCW), -3, 4, 7); - - west.Link = east; - east.Link = west; - - AddItem(new Sign(SignType.Healer, SignFacing.West), -5, 5, -4); - - AddMobile(new Healer(), 4, -4, 3, 7); - AddMobile(new Healer(), 5, 4, -2, 0); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Multis/Camps/LizardmenCamp.cs b/Projects/UOContent/Multis/Camps/LizardmenCamp.cs index 873807617..d9a9bb5a5 100644 --- a/Projects/UOContent/Multis/Camps/LizardmenCamp.cs +++ b/Projects/UOContent/Multis/Camps/LizardmenCamp.cs @@ -4,189 +4,189 @@ using Server.Mobiles; namespace Server.Multis { - public class LizardmenCamp : BaseCamp - { - private Mobile m_Prisoner; - - [Constructible] - public LizardmenCamp() : base(0x10EE) // dummy garbage at center + public class LizardmenCamp : BaseCamp { - } + private Mobile m_Prisoner; - public LizardmenCamp(Serial serial) : base(serial) - { - } - - public virtual Mobile Lizardmen => new Lizardman(); - - public override void AddComponents() - { - BaseCreature bc; - // BaseEscortable be; - - Visible = false; - DecayDelay = TimeSpan.FromMinutes(5.0); - AddItem(new Static(0x10ee), 0, 0, 0); - AddItem(new Static(0xfac), 0, 7, 0); - - switch (Utility.Random(3)) - { - case 0: - { - AddItem(new Item(0xDE3), 0, 7, 0); // Campfire - AddItem(new Item(0x974), 0, 7, 1); // Cauldron - break; - } - case 1: - { - AddItem(new Item(0x1E95), 0, 7, 1); // Rabbit on a spit - break; - } - default: - { - AddItem(new Item(0x1E94), 0, 7, 1); // Chicken on a spit - break; - } - } - - AddItem(new Item(0x41F), 4, 4, 0); // Gruesome Standart South - - AddCampChests(); - - for (int i = 0; i < 4; i++) AddMobile(Lizardmen, 6, Utility.RandomMinMax(-7, 7), Utility.RandomMinMax(-7, 7), 0); - - m_Prisoner = Utility.Random(2) switch - { - 0 => (Mobile)new Noble(), - _ => new SeekerOfAdventure() - }; - - // be = (BaseEscortable)m_Prisoner; - // be.m_Captive = true; - - bc = (BaseCreature)m_Prisoner; - bc.IsPrisoner = true; - bc.CantWalk = true; - - m_Prisoner.YellHue = Utility.RandomList(0x57, 0x67, 0x77, 0x87, 0x117); - AddMobile(m_Prisoner, 2, Utility.RandomMinMax(-2, 2), Utility.RandomMinMax(-2, 2), 0); - } - - private void AddCampChests() - { - var chest = Utility.Random(3) switch - { - 0 => (LockableContainer)new MetalChest(), - 1 => new MetalGoldenChest(), - _ => new WoodenChest() - }; - - chest.LiftOverride = true; - - TreasureMapChest.Fill(chest, 1); - - AddItem(chest, 2, -2, 0); - - var crates = Utility.Random(4) switch - { - 0 => (LockableContainer)new SmallCrate(), - 1 => new MediumCrate(), - 2 => new LargeCrate(), - _ => new LockableBarrel() - }; - - crates.TrapType = TrapType.ExplosionTrap; - crates.TrapPower = Utility.RandomMinMax(30, 40); - crates.TrapLevel = 2; - - crates.RequiredSkill = 76; - crates.LockLevel = 66; - crates.MaxLockLevel = 116; - crates.Locked = true; - - crates.DropItem(new Gold(Utility.RandomMinMax(100, 400))); - crates.DropItem(new Arrow(10)); - crates.DropItem(new Bolt(10)); - - crates.LiftOverride = true; - - if (Utility.RandomDouble() < 0.8) - switch (Utility.Random(4)) + [Constructible] + public LizardmenCamp() : base(0x10EE) // dummy garbage at center { - case 0: - crates.DropItem(new LesserCurePotion()); - break; - case 1: - crates.DropItem(new LesserExplosionPotion()); - break; - case 2: - crates.DropItem(new LesserHealPotion()); - break; - default: - crates.DropItem(new LesserPoisonPotion()); - break; } - AddItem(crates, -2, 2, 0); - } - - // Don't refresh decay timer - public override void OnEnter(Mobile m) - { - if (m.Player && m_Prisoner?.CantWalk == true) - { - var number = Utility.Random(8) switch + public LizardmenCamp(Serial serial) : base(serial) { - 0 => 502261, - 1 => 502262, - 2 => 502263, - 3 => 502264, - 4 => 502265, - 5 => 502266, - 6 => 502267, - _ => 502268 - }; + } - m_Prisoner.Yell(number); - } + public virtual Mobile Lizardmen => new Lizardman(); + + public override void AddComponents() + { + BaseCreature bc; + // BaseEscortable be; + + Visible = false; + DecayDelay = TimeSpan.FromMinutes(5.0); + AddItem(new Static(0x10ee), 0, 0, 0); + AddItem(new Static(0xfac), 0, 7, 0); + + switch (Utility.Random(3)) + { + case 0: + { + AddItem(new Item(0xDE3), 0, 7, 0); // Campfire + AddItem(new Item(0x974), 0, 7, 1); // Cauldron + break; + } + case 1: + { + AddItem(new Item(0x1E95), 0, 7, 1); // Rabbit on a spit + break; + } + default: + { + AddItem(new Item(0x1E94), 0, 7, 1); // Chicken on a spit + break; + } + } + + AddItem(new Item(0x41F), 4, 4, 0); // Gruesome Standart South + + AddCampChests(); + + for (var i = 0; i < 4; i++) AddMobile(Lizardmen, 6, Utility.RandomMinMax(-7, 7), Utility.RandomMinMax(-7, 7), 0); + + m_Prisoner = Utility.Random(2) switch + { + 0 => new Noble(), + _ => new SeekerOfAdventure() + }; + + // be = (BaseEscortable)m_Prisoner; + // be.m_Captive = true; + + bc = (BaseCreature)m_Prisoner; + bc.IsPrisoner = true; + bc.CantWalk = true; + + m_Prisoner.YellHue = Utility.RandomList(0x57, 0x67, 0x77, 0x87, 0x117); + AddMobile(m_Prisoner, 2, Utility.RandomMinMax(-2, 2), Utility.RandomMinMax(-2, 2), 0); + } + + private void AddCampChests() + { + var chest = Utility.Random(3) switch + { + 0 => (LockableContainer)new MetalChest(), + 1 => new MetalGoldenChest(), + _ => new WoodenChest() + }; + + chest.LiftOverride = true; + + TreasureMapChest.Fill(chest, 1); + + AddItem(chest, 2, -2, 0); + + var crates = Utility.Random(4) switch + { + 0 => (LockableContainer)new SmallCrate(), + 1 => new MediumCrate(), + 2 => new LargeCrate(), + _ => new LockableBarrel() + }; + + crates.TrapType = TrapType.ExplosionTrap; + crates.TrapPower = Utility.RandomMinMax(30, 40); + crates.TrapLevel = 2; + + crates.RequiredSkill = 76; + crates.LockLevel = 66; + crates.MaxLockLevel = 116; + crates.Locked = true; + + crates.DropItem(new Gold(Utility.RandomMinMax(100, 400))); + crates.DropItem(new Arrow(10)); + crates.DropItem(new Bolt(10)); + + crates.LiftOverride = true; + + if (Utility.RandomDouble() < 0.8) + switch (Utility.Random(4)) + { + case 0: + crates.DropItem(new LesserCurePotion()); + break; + case 1: + crates.DropItem(new LesserExplosionPotion()); + break; + case 2: + crates.DropItem(new LesserHealPotion()); + break; + default: + crates.DropItem(new LesserPoisonPotion()); + break; + } + + AddItem(crates, -2, 2, 0); + } + + // Don't refresh decay timer + public override void OnEnter(Mobile m) + { + if (m.Player && m_Prisoner?.CantWalk == true) + { + var number = Utility.Random(8) switch + { + 0 => 502261, + 1 => 502262, + 2 => 502263, + 3 => 502264, + 4 => 502265, + 5 => 502266, + 6 => 502267, + _ => 502268 + }; + + m_Prisoner.Yell(number); + } + } + + // Don't refresh decay timer + public override void OnExit(Mobile m) + { + } + + public override void AddItem(Item item, int xOffset, int yOffset, int zOffset) + { + if (item != null) + item.Movable = false; + + base.AddItem(item, xOffset, yOffset, zOffset); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Prisoner); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Prisoner = reader.ReadMobile(); + break; + } + } + } } - - // Don't refresh decay timer - public override void OnExit(Mobile m) - { - } - - public override void AddItem(Item item, int xOffset, int yOffset, int zOffset) - { - if (item != null) - item.Movable = false; - - base.AddItem(item, xOffset, yOffset, zOffset); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Prisoner); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Prisoner = reader.ReadMobile(); - break; - } - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Multis/Camps/MageCamp.cs b/Projects/UOContent/Multis/Camps/MageCamp.cs index 47dd0222b..71ce784cd 100644 --- a/Projects/UOContent/Multis/Camps/MageCamp.cs +++ b/Projects/UOContent/Multis/Camps/MageCamp.cs @@ -3,45 +3,45 @@ using Server.Mobiles; namespace Server.Multis { - public class MageCamp : BaseCamp - { - [Constructible] - public MageCamp() : base(0x1F5) + public class MageCamp : BaseCamp { + [Constructible] + public MageCamp() : base(0x1F5) + { + } + + public MageCamp(Serial serial) : base(serial) + { + } + + public override void AddComponents() + { + BaseDoor west, east; + + AddItem(west = new LightWoodGate(DoorFacing.WestCW), -4, 4, 7); + AddItem(east = new LightWoodGate(DoorFacing.EastCCW), -3, 4, 7); + + west.Link = east; + east.Link = west; + + AddItem(new Sign(SignType.Mage, SignFacing.West), -5, 5, -4); + + AddMobile(new Mage(), 4, -4, 3, 7); + AddMobile(new Mage(), 5, 4, -2, 0); + } + + 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 MageCamp(Serial serial) : base(serial) - { - } - - public override void AddComponents() - { - BaseDoor west, east; - - AddItem(west = new LightWoodGate(DoorFacing.WestCW), -4, 4, 7); - AddItem(east = new LightWoodGate(DoorFacing.EastCCW), -3, 4, 7); - - west.Link = east; - east.Link = west; - - AddItem(new Sign(SignType.Mage, SignFacing.West), -5, 5, -4); - - AddMobile(new Mage(), 4, -4, 3, 7); - AddMobile(new Mage(), 5, 4, -2, 0); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Multis/Camps/OrcCamp.cs b/Projects/UOContent/Multis/Camps/OrcCamp.cs index c9d1916ac..42e39ad98 100644 --- a/Projects/UOContent/Multis/Camps/OrcCamp.cs +++ b/Projects/UOContent/Multis/Camps/OrcCamp.cs @@ -4,196 +4,196 @@ using Server.Mobiles; namespace Server.Multis { - public class OrcCamp : BaseCamp - { - private Mobile m_Prisoner; - - [Constructible] - public OrcCamp() : base(0x10EE) // dummy garbage at center + public class OrcCamp : BaseCamp { - } + private Mobile m_Prisoner; - public OrcCamp(Serial serial) : base(serial) - { - } - - public virtual Mobile Orcs => new Orc(); - - public override void AddComponents() - { - BaseCreature bc; - // BaseEscortable be; - - Visible = false; - DecayDelay = TimeSpan.FromMinutes(5.0); - AddItem(new Static(0x10ee), 0, 0, 0); - AddItem(new Static(0xfac), 0, 7, 0); - - switch (Utility.Random(3)) - { - case 0: - { - AddItem(new Item(0xDE3), 0, 7, 0); // Campfire - AddItem(new Item(0x974), 0, 7, 1); // Cauldron - break; - } - case 1: - { - AddItem(new Item(0x1E95), 0, 7, 1); // Rabbit on a spit - break; - } - default: - { - AddItem(new Item(0x1E94), 0, 7, 1); // Chicken on a spit - break; - } - } - - AddItem(new Item(0x428), -5, -4, 0); // Gruesome Standart West - - AddCampChests(); - - for (int i = 0; i < 3; i++) AddMobile(Orcs, 6, Utility.RandomMinMax(-7, 7), Utility.RandomMinMax(-7, 7), 0); - AddMobile(new OrcCaptain(), 2, Utility.RandomMinMax(-7, 7), Utility.RandomMinMax(-7, 7), 0); - - m_Prisoner = Utility.Random(2) switch - { - 0 => (Mobile)new Noble(), - _ => new SeekerOfAdventure() - }; - - // be = (BaseEscortable)m_Prisoner; - // be.m_Captive = true; - - bc = (BaseCreature)m_Prisoner; - bc.IsPrisoner = true; - bc.CantWalk = true; - - m_Prisoner.YellHue = Utility.RandomList(0x57, 0x67, 0x77, 0x87, 0x117); - AddMobile(m_Prisoner, 2, Utility.RandomMinMax(-2, 2), Utility.RandomMinMax(-2, 2), 0); - } - - private void AddCampChests() - { - var chest = Utility.Random(3) switch - { - 0 => (LockableContainer)new MetalChest(), - 1 => new MetalGoldenChest(), - _ => new WoodenChest() - }; - - chest.LiftOverride = true; - - TreasureMapChest.Fill(chest, 1); - - AddItem(chest, -2, 2, 0); - - var crates = Utility.Random(4) switch - { - 0 => (LockableContainer)new SmallCrate(), - 1 => new MediumCrate(), - 2 => new LargeCrate(), - _ => new LockableBarrel() - }; - - crates.TrapType = TrapType.ExplosionTrap; - crates.TrapPower = Utility.RandomMinMax(30, 40); - crates.TrapLevel = 2; - - crates.RequiredSkill = 76; - crates.LockLevel = 66; - crates.MaxLockLevel = 116; - crates.Locked = true; - - crates.DropItem(new Gold(Utility.RandomMinMax(100, 400))); - crates.DropItem(new Arrow(10)); - crates.DropItem(new Bolt(10)); - - crates.LiftOverride = true; - - if (Utility.RandomDouble() < 0.8) - switch (Utility.Random(4)) + [Constructible] + public OrcCamp() : base(0x10EE) // dummy garbage at center { - case 0: - crates.DropItem(new LesserCurePotion()); - break; - case 1: - crates.DropItem(new LesserExplosionPotion()); - break; - case 2: - crates.DropItem(new LesserHealPotion()); - break; - default: - crates.DropItem(new LesserPoisonPotion()); - break; } - AddItem(crates, 2, -2, 0); - } - - // Don't refresh decay timer - public override void OnEnter(Mobile m) - { - if (m.Player && m_Prisoner?.CantWalk == true) - { - var number = Utility.Random(8) switch + public OrcCamp(Serial serial) : base(serial) { - 0 => 502261, - 1 => 502262, - 2 => 502263, - 3 => 502264, - 4 => 502265, - 5 => 502266, - 6 => 502267, - _ => 502268 - }; + } - m_Prisoner.Yell(number); - } + public virtual Mobile Orcs => new Orc(); + + public override void AddComponents() + { + BaseCreature bc; + // BaseEscortable be; + + Visible = false; + DecayDelay = TimeSpan.FromMinutes(5.0); + AddItem(new Static(0x10ee), 0, 0, 0); + AddItem(new Static(0xfac), 0, 7, 0); + + switch (Utility.Random(3)) + { + case 0: + { + AddItem(new Item(0xDE3), 0, 7, 0); // Campfire + AddItem(new Item(0x974), 0, 7, 1); // Cauldron + break; + } + case 1: + { + AddItem(new Item(0x1E95), 0, 7, 1); // Rabbit on a spit + break; + } + default: + { + AddItem(new Item(0x1E94), 0, 7, 1); // Chicken on a spit + break; + } + } + + AddItem(new Item(0x428), -5, -4, 0); // Gruesome Standart West + + AddCampChests(); + + for (var i = 0; i < 3; i++) AddMobile(Orcs, 6, Utility.RandomMinMax(-7, 7), Utility.RandomMinMax(-7, 7), 0); + AddMobile(new OrcCaptain(), 2, Utility.RandomMinMax(-7, 7), Utility.RandomMinMax(-7, 7), 0); + + m_Prisoner = Utility.Random(2) switch + { + 0 => new Noble(), + _ => new SeekerOfAdventure() + }; + + // be = (BaseEscortable)m_Prisoner; + // be.m_Captive = true; + + bc = (BaseCreature)m_Prisoner; + bc.IsPrisoner = true; + bc.CantWalk = true; + + m_Prisoner.YellHue = Utility.RandomList(0x57, 0x67, 0x77, 0x87, 0x117); + AddMobile(m_Prisoner, 2, Utility.RandomMinMax(-2, 2), Utility.RandomMinMax(-2, 2), 0); + } + + private void AddCampChests() + { + var chest = Utility.Random(3) switch + { + 0 => (LockableContainer)new MetalChest(), + 1 => new MetalGoldenChest(), + _ => new WoodenChest() + }; + + chest.LiftOverride = true; + + TreasureMapChest.Fill(chest, 1); + + AddItem(chest, -2, 2, 0); + + var crates = Utility.Random(4) switch + { + 0 => (LockableContainer)new SmallCrate(), + 1 => new MediumCrate(), + 2 => new LargeCrate(), + _ => new LockableBarrel() + }; + + crates.TrapType = TrapType.ExplosionTrap; + crates.TrapPower = Utility.RandomMinMax(30, 40); + crates.TrapLevel = 2; + + crates.RequiredSkill = 76; + crates.LockLevel = 66; + crates.MaxLockLevel = 116; + crates.Locked = true; + + crates.DropItem(new Gold(Utility.RandomMinMax(100, 400))); + crates.DropItem(new Arrow(10)); + crates.DropItem(new Bolt(10)); + + crates.LiftOverride = true; + + if (Utility.RandomDouble() < 0.8) + switch (Utility.Random(4)) + { + case 0: + crates.DropItem(new LesserCurePotion()); + break; + case 1: + crates.DropItem(new LesserExplosionPotion()); + break; + case 2: + crates.DropItem(new LesserHealPotion()); + break; + default: + crates.DropItem(new LesserPoisonPotion()); + break; + } + + AddItem(crates, 2, -2, 0); + } + + // Don't refresh decay timer + public override void OnEnter(Mobile m) + { + if (m.Player && m_Prisoner?.CantWalk == true) + { + var number = Utility.Random(8) switch + { + 0 => 502261, + 1 => 502262, + 2 => 502263, + 3 => 502264, + 4 => 502265, + 5 => 502266, + 6 => 502267, + _ => 502268 + }; + + m_Prisoner.Yell(number); + } + } + + // Don't refresh decay timer + public override void OnExit(Mobile m) + { + } + + public override void AddItem(Item item, int xOffset, int yOffset, int zOffset) + { + if (item != null) + item.Movable = false; + + base.AddItem(item, xOffset, yOffset, zOffset); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(m_Prisoner); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_Prisoner = reader.ReadMobile(); + break; + } + case 0: + { + m_Prisoner = reader.ReadMobile(); + reader.ReadItem(); + break; + } + } + } } - - // Don't refresh decay timer - public override void OnExit(Mobile m) - { - } - - public override void AddItem(Item item, int xOffset, int yOffset, int zOffset) - { - if (item != null) - item.Movable = false; - - base.AddItem(item, xOffset, yOffset, zOffset); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(m_Prisoner); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_Prisoner = reader.ReadMobile(); - break; - } - case 0: - { - m_Prisoner = reader.ReadMobile(); - reader.ReadItem(); - break; - } - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Multis/Camps/RatCamp.cs b/Projects/UOContent/Multis/Camps/RatCamp.cs index 2cd7ce4c7..43ace4b5b 100644 --- a/Projects/UOContent/Multis/Camps/RatCamp.cs +++ b/Projects/UOContent/Multis/Camps/RatCamp.cs @@ -4,195 +4,195 @@ using Server.Mobiles; namespace Server.Multis { - public class RatCamp : BaseCamp - { - private Mobile m_Prisoner; - - [Constructible] - public RatCamp() : base(0x10EE) // dummy garbage at center + public class RatCamp : BaseCamp { - } + private Mobile m_Prisoner; - public RatCamp(Serial serial) : base(serial) - { - } - - public virtual Mobile Ratmen => new Ratman(); - - public override void AddComponents() - { - BaseCreature bc; - // BaseEscortable be; - - Visible = false; - DecayDelay = TimeSpan.FromMinutes(5.0); - AddItem(new Static(0x10ee), 0, 0, 0); - AddItem(new Static(0xfac), 0, 6, 0); - - switch (Utility.Random(3)) - { - case 0: - { - AddItem(new Item(0xDE3), 0, 6, 0); // Campfire - AddItem(new Item(0x974), 0, 6, 1); // Cauldron - break; - } - case 1: - { - AddItem(new Item(0x1E95), 0, 6, 1); // Rabbit on a spit - break; - } - default: - { - AddItem(new Item(0x1E94), 0, 6, 1); // Chicken on a spit - break; - } - } - - AddItem(new Item(0x41F), 5, 5, 0); // Gruesome Standart South - - AddCampChests(); - - for (int i = 0; i < 4; i++) AddMobile(Ratmen, 6, Utility.RandomMinMax(-7, 7), Utility.RandomMinMax(-7, 7), 0); - - m_Prisoner = Utility.Random(2) switch - { - 0 => (Mobile)new Noble(), - _ => new SeekerOfAdventure() - }; - - // be = (BaseEscortable)m_Prisoner; - // be.m_Captive = true; - - bc = (BaseCreature)m_Prisoner; - bc.IsPrisoner = true; - bc.CantWalk = true; - - m_Prisoner.YellHue = Utility.RandomList(0x57, 0x67, 0x77, 0x87, 0x117); - AddMobile(m_Prisoner, 2, Utility.RandomMinMax(-2, 2), Utility.RandomMinMax(-2, 2), 0); - } - - private void AddCampChests() - { - var chest = Utility.Random(3) switch - { - 0 => (LockableContainer)new MetalChest(), - 1 => new MetalGoldenChest(), - _ => new WoodenChest() - }; - - chest.LiftOverride = true; - - TreasureMapChest.Fill(chest, 1); - - AddItem(chest, -2, -2, 0); - - var crates = Utility.Random(4) switch - { - 0 => (LockableContainer)new SmallCrate(), - 1 => new MediumCrate(), - 2 => new LargeCrate(), - _ => new LockableBarrel() - }; - - crates.TrapType = TrapType.ExplosionTrap; - crates.TrapPower = Utility.RandomMinMax(30, 40); - crates.TrapLevel = 2; - - crates.RequiredSkill = 76; - crates.LockLevel = 66; - crates.MaxLockLevel = 116; - crates.Locked = true; - - crates.DropItem(new Gold(Utility.RandomMinMax(100, 400))); - crates.DropItem(new Arrow(10)); - crates.DropItem(new Bolt(10)); - - crates.LiftOverride = true; - - if (Utility.RandomDouble() < 0.8) - switch (Utility.Random(4)) + [Constructible] + public RatCamp() : base(0x10EE) // dummy garbage at center { - case 0: - crates.DropItem(new LesserCurePotion()); - break; - case 1: - crates.DropItem(new LesserExplosionPotion()); - break; - case 2: - crates.DropItem(new LesserHealPotion()); - break; - default: - crates.DropItem(new LesserPoisonPotion()); - break; } - AddItem(crates, 2, 2, 0); - } - - // Don't refresh decay timer - public override void OnEnter(Mobile m) - { - if (m.Player && m_Prisoner?.CantWalk == true) - { - var number = Utility.Random(8) switch + public RatCamp(Serial serial) : base(serial) { - 0 => 502261, - 1 => 502262, - 2 => 502263, - 3 => 502264, - 4 => 502265, - 5 => 502266, - 6 => 502267, - _ => 502268 - }; + } - m_Prisoner.Yell(number); - } + public virtual Mobile Ratmen => new Ratman(); + + public override void AddComponents() + { + BaseCreature bc; + // BaseEscortable be; + + Visible = false; + DecayDelay = TimeSpan.FromMinutes(5.0); + AddItem(new Static(0x10ee), 0, 0, 0); + AddItem(new Static(0xfac), 0, 6, 0); + + switch (Utility.Random(3)) + { + case 0: + { + AddItem(new Item(0xDE3), 0, 6, 0); // Campfire + AddItem(new Item(0x974), 0, 6, 1); // Cauldron + break; + } + case 1: + { + AddItem(new Item(0x1E95), 0, 6, 1); // Rabbit on a spit + break; + } + default: + { + AddItem(new Item(0x1E94), 0, 6, 1); // Chicken on a spit + break; + } + } + + AddItem(new Item(0x41F), 5, 5, 0); // Gruesome Standart South + + AddCampChests(); + + for (var i = 0; i < 4; i++) AddMobile(Ratmen, 6, Utility.RandomMinMax(-7, 7), Utility.RandomMinMax(-7, 7), 0); + + m_Prisoner = Utility.Random(2) switch + { + 0 => new Noble(), + _ => new SeekerOfAdventure() + }; + + // be = (BaseEscortable)m_Prisoner; + // be.m_Captive = true; + + bc = (BaseCreature)m_Prisoner; + bc.IsPrisoner = true; + bc.CantWalk = true; + + m_Prisoner.YellHue = Utility.RandomList(0x57, 0x67, 0x77, 0x87, 0x117); + AddMobile(m_Prisoner, 2, Utility.RandomMinMax(-2, 2), Utility.RandomMinMax(-2, 2), 0); + } + + private void AddCampChests() + { + var chest = Utility.Random(3) switch + { + 0 => (LockableContainer)new MetalChest(), + 1 => new MetalGoldenChest(), + _ => new WoodenChest() + }; + + chest.LiftOverride = true; + + TreasureMapChest.Fill(chest, 1); + + AddItem(chest, -2, -2, 0); + + var crates = Utility.Random(4) switch + { + 0 => (LockableContainer)new SmallCrate(), + 1 => new MediumCrate(), + 2 => new LargeCrate(), + _ => new LockableBarrel() + }; + + crates.TrapType = TrapType.ExplosionTrap; + crates.TrapPower = Utility.RandomMinMax(30, 40); + crates.TrapLevel = 2; + + crates.RequiredSkill = 76; + crates.LockLevel = 66; + crates.MaxLockLevel = 116; + crates.Locked = true; + + crates.DropItem(new Gold(Utility.RandomMinMax(100, 400))); + crates.DropItem(new Arrow(10)); + crates.DropItem(new Bolt(10)); + + crates.LiftOverride = true; + + if (Utility.RandomDouble() < 0.8) + switch (Utility.Random(4)) + { + case 0: + crates.DropItem(new LesserCurePotion()); + break; + case 1: + crates.DropItem(new LesserExplosionPotion()); + break; + case 2: + crates.DropItem(new LesserHealPotion()); + break; + default: + crates.DropItem(new LesserPoisonPotion()); + break; + } + + AddItem(crates, 2, 2, 0); + } + + // Don't refresh decay timer + public override void OnEnter(Mobile m) + { + if (m.Player && m_Prisoner?.CantWalk == true) + { + var number = Utility.Random(8) switch + { + 0 => 502261, + 1 => 502262, + 2 => 502263, + 3 => 502264, + 4 => 502265, + 5 => 502266, + 6 => 502267, + _ => 502268 + }; + + m_Prisoner.Yell(number); + } + } + + // Don't refresh decay timer + public override void OnExit(Mobile m) + { + } + + public override void AddItem(Item item, int xOffset, int yOffset, int zOffset) + { + if (item != null) + item.Movable = false; + + base.AddItem(item, xOffset, yOffset, zOffset); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(m_Prisoner); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_Prisoner = reader.ReadMobile(); + break; + } + case 0: + { + m_Prisoner = reader.ReadMobile(); + reader.ReadItem(); + break; + } + } + } } - - // Don't refresh decay timer - public override void OnExit(Mobile m) - { - } - - public override void AddItem(Item item, int xOffset, int yOffset, int zOffset) - { - if (item != null) - item.Movable = false; - - base.AddItem(item, xOffset, yOffset, zOffset); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(m_Prisoner); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - m_Prisoner = reader.ReadMobile(); - break; - } - case 0: - { - m_Prisoner = reader.ReadMobile(); - reader.ReadItem(); - break; - } - } - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Multis/ComponentVerification.cs b/Projects/UOContent/Multis/ComponentVerification.cs index 752e1b0c8..4418a7a66 100644 --- a/Projects/UOContent/Multis/ComponentVerification.cs +++ b/Projects/UOContent/Multis/ComponentVerification.cs @@ -4,199 +4,296 @@ using System.IO; namespace Server.Multis { - public class ComponentVerification - { - private readonly int[] m_ItemTable; - private readonly int[] m_MultiTable; - - public ComponentVerification() + public class ComponentVerification { - m_ItemTable = CreateTable(TileData.MaxItemValue); - m_MultiTable = CreateTable(0x4000); + private readonly int[] m_ItemTable; + private readonly int[] m_MultiTable; - LoadItems("Data/Components/walls.txt", "South1", "South2", "South3", "Corner", "East1", "East2", "East3", "Post", - "WindowS", "AltWindowS", "WindowE", "AltWindowE", "SecondAltWindowS", "SecondAltWindowE"); - LoadItems("Data/Components/teleprts.txt", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", - "F12", "F13", "F14", "F15", "F16"); - LoadItems("Data/Components/stairs.txt", "Block", "North", "East", "South", "West", "Squared1", "Squared2", - "Rounded1", "Rounded2"); - LoadItems("Data/Components/roof.txt", "North", "East", "South", "West", "NSCrosspiece", "EWCrosspiece", "NDent", - "EDent", "SDent", "WDent", "NTPiece", "ETPiece", "STPiece", "WTPiece", "XPiece", "Extra Piece"); - LoadItems("Data/Components/floors.txt", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", - "F12", "F13", "F14", "F15", "F16"); - LoadItems("Data/Components/misc.txt", "Piece1", "Piece2", "Piece3", "Piece4", "Piece5", "Piece6", "Piece7", - "Piece8"); - LoadItems("Data/Components/doors.txt", "Piece1", "Piece2", "Piece3", "Piece4", "Piece5", "Piece6", "Piece7", - "Piece8"); - - LoadMultis("Data/Components/stairs.txt", "MultiNorth", "MultiEast", "MultiSouth", "MultiWest"); - } - - public bool IsItemValid(int itemID) => itemID > 0 && itemID < m_ItemTable.Length && CheckValidity(m_ItemTable[itemID]); - - public bool IsMultiValid(int multiID) => multiID > 0 && multiID < m_MultiTable.Length && CheckValidity(m_MultiTable[multiID]); - - public bool CheckValidity(int val) => val != -1 && (val == 0 || ((int)ExpansionInfo.CoreExpansion.CustomHousingFlag & val) != 0); - - private int[] CreateTable(int length) - { - int[] table = new int[length]; - - for (int i = 0; i < table.Length; ++i) - table[i] = -1; - - return table; - } - - private void LoadItems(string path, params string[] itemColumns) - { - LoadSpreadsheet(m_ItemTable, path, itemColumns); - } - - private void LoadMultis(string path, params string[] multiColumns) - { - LoadSpreadsheet(m_MultiTable, path, multiColumns); - } - - private void LoadSpreadsheet(int[] table, string path, params string[] tileColumns) - { - Spreadsheet ss = new Spreadsheet(path); - - int[] tileCIDs = new int[tileColumns.Length]; - - for (int i = 0; i < tileColumns.Length; ++i) - tileCIDs[i] = ss.GetColumnID(tileColumns[i]); - - int featureCID = ss.GetColumnID("FeatureMask"); - - for (int i = 0; i < ss.Records.Length; ++i) - { - DataRecord record = ss.Records[i]; - - int fid = record.GetInt32(featureCID); - - for (int j = 0; j < tileCIDs.Length; ++j) + public ComponentVerification() { - int itemID = record.GetInt32(tileCIDs[j]); + m_ItemTable = CreateTable(TileData.MaxItemValue); + m_MultiTable = CreateTable(0x4000); - if (itemID <= 0 || itemID >= table.Length) - continue; + LoadItems( + "Data/Components/walls.txt", + "South1", + "South2", + "South3", + "Corner", + "East1", + "East2", + "East3", + "Post", + "WindowS", + "AltWindowS", + "WindowE", + "AltWindowE", + "SecondAltWindowS", + "SecondAltWindowE" + ); + LoadItems( + "Data/Components/teleprts.txt", + "F1", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "F9", + "F10", + "F11", + "F12", + "F13", + "F14", + "F15", + "F16" + ); + LoadItems( + "Data/Components/stairs.txt", + "Block", + "North", + "East", + "South", + "West", + "Squared1", + "Squared2", + "Rounded1", + "Rounded2" + ); + LoadItems( + "Data/Components/roof.txt", + "North", + "East", + "South", + "West", + "NSCrosspiece", + "EWCrosspiece", + "NDent", + "EDent", + "SDent", + "WDent", + "NTPiece", + "ETPiece", + "STPiece", + "WTPiece", + "XPiece", + "Extra Piece" + ); + LoadItems( + "Data/Components/floors.txt", + "F1", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "F9", + "F10", + "F11", + "F12", + "F13", + "F14", + "F15", + "F16" + ); + LoadItems( + "Data/Components/misc.txt", + "Piece1", + "Piece2", + "Piece3", + "Piece4", + "Piece5", + "Piece6", + "Piece7", + "Piece8" + ); + LoadItems( + "Data/Components/doors.txt", + "Piece1", + "Piece2", + "Piece3", + "Piece4", + "Piece5", + "Piece6", + "Piece7", + "Piece8" + ); - table[itemID] = fid; - } - } - } - } - - public class Spreadsheet - { - private readonly ColumnInfo[] m_Columns; - - public Spreadsheet(string path) - { - using StreamReader ip = new StreamReader(path); - string[] types = ReadLine(ip); - string[] names = ReadLine(ip); - - m_Columns = new ColumnInfo[types.Length]; - - for (int i = 0; i < m_Columns.Length; ++i) - m_Columns[i] = new ColumnInfo(i, types[i], names[i]); - - List records = new List(); - - string[] values; - - while ((values = ReadLine(ip)) != null) - { - object[] data = new object[m_Columns.Length]; - - for (int i = 0; i < m_Columns.Length; ++i) - { - ColumnInfo ci = m_Columns[i]; - - switch (ci.m_Type) - { - case "int": - { - data[i] = Utility.ToInt32(values[ci.m_DataIndex]); - break; - } - case "string": - { - data[i] = values[ci.m_DataIndex]; - break; - } - } + LoadMultis("Data/Components/stairs.txt", "MultiNorth", "MultiEast", "MultiSouth", "MultiWest"); } - records.Add(new DataRecord(this, data)); - } + public bool IsItemValid(int itemID) => + itemID > 0 && itemID < m_ItemTable.Length && CheckValidity(m_ItemTable[itemID]); - Records = records.ToArray(); + public bool IsMultiValid(int multiID) => + multiID > 0 && multiID < m_MultiTable.Length && CheckValidity(m_MultiTable[multiID]); + + public bool CheckValidity(int val) => + val != -1 && (val == 0 || ((int)ExpansionInfo.CoreExpansion.CustomHousingFlag & val) != 0); + + private int[] CreateTable(int length) + { + var table = new int[length]; + + for (var i = 0; i < table.Length; ++i) + table[i] = -1; + + return table; + } + + private void LoadItems(string path, params string[] itemColumns) + { + LoadSpreadsheet(m_ItemTable, path, itemColumns); + } + + private void LoadMultis(string path, params string[] multiColumns) + { + LoadSpreadsheet(m_MultiTable, path, multiColumns); + } + + private void LoadSpreadsheet(int[] table, string path, params string[] tileColumns) + { + var ss = new Spreadsheet(path); + + var tileCIDs = new int[tileColumns.Length]; + + for (var i = 0; i < tileColumns.Length; ++i) + tileCIDs[i] = ss.GetColumnID(tileColumns[i]); + + var featureCID = ss.GetColumnID("FeatureMask"); + + for (var i = 0; i < ss.Records.Length; ++i) + { + var record = ss.Records[i]; + + var fid = record.GetInt32(featureCID); + + for (var j = 0; j < tileCIDs.Length; ++j) + { + var itemID = record.GetInt32(tileCIDs[j]); + + if (itemID <= 0 || itemID >= table.Length) + continue; + + table[itemID] = fid; + } + } + } } - public DataRecord[] Records { get; } - - public int GetColumnID(string name) + public class Spreadsheet { - for (int i = 0; i < m_Columns.Length; ++i) - if (m_Columns[i].m_Name == name) - return i; + private readonly ColumnInfo[] m_Columns; - return -1; + public Spreadsheet(string path) + { + using var ip = new StreamReader(path); + var types = ReadLine(ip); + var names = ReadLine(ip); + + m_Columns = new ColumnInfo[types.Length]; + + for (var i = 0; i < m_Columns.Length; ++i) + m_Columns[i] = new ColumnInfo(i, types[i], names[i]); + + var records = new List(); + + string[] values; + + while ((values = ReadLine(ip)) != null) + { + var data = new object[m_Columns.Length]; + + for (var i = 0; i < m_Columns.Length; ++i) + { + var ci = m_Columns[i]; + + switch (ci.m_Type) + { + case "int": + { + data[i] = Utility.ToInt32(values[ci.m_DataIndex]); + break; + } + case "string": + { + data[i] = values[ci.m_DataIndex]; + break; + } + } + } + + records.Add(new DataRecord(this, data)); + } + + Records = records.ToArray(); + } + + public DataRecord[] Records { get; } + + public int GetColumnID(string name) + { + for (var i = 0; i < m_Columns.Length; ++i) + if (m_Columns[i].m_Name == name) + return i; + + return -1; + } + + private string[] ReadLine(StreamReader ip) + { + string line; + + while ((line = ip.ReadLine()) != null) + if (line.Length > 0) + return line.Split('\t'); + + return null; + } + + private class ColumnInfo + { + public readonly int m_DataIndex; + public readonly string m_Name; + + public readonly string m_Type; + + public ColumnInfo(int dataIndex, string type, string name) + { + m_DataIndex = dataIndex; + + m_Type = type; + m_Name = name; + } + } } - private string[] ReadLine(StreamReader ip) + public class DataRecord { - string line; + public DataRecord(Spreadsheet ss, object[] data) + { + Spreadsheet = ss; + Data = data; + } - while ((line = ip.ReadLine()) != null) - if (line.Length > 0) - return line.Split('\t'); + public Spreadsheet Spreadsheet { get; } - return null; + public object[] Data { get; } + + public object this[string name] => this[Spreadsheet.GetColumnID(name)]; + + public object this[int id] => id < 0 ? null : Data[id]; + + public int GetInt32(string name) => GetInt32(this[name]); + + public int GetInt32(int id) => GetInt32(this[id]); + + public int GetInt32(object obj) => Convert.ToInt32(obj); + + public string GetString(string name) => this[name] as string; } - - private class ColumnInfo - { - public readonly int m_DataIndex; - public readonly string m_Name; - - public readonly string m_Type; - - public ColumnInfo(int dataIndex, string type, string name) - { - m_DataIndex = dataIndex; - - m_Type = type; - m_Name = name; - } - } - } - - public class DataRecord - { - public DataRecord(Spreadsheet ss, object[] data) - { - Spreadsheet = ss; - Data = data; - } - - public Spreadsheet Spreadsheet { get; } - - public object[] Data { get; } - - public object this[string name] => this[Spreadsheet.GetColumnID(name)]; - - public object this[int id] => id < 0 ? null : Data[id]; - - public int GetInt32(string name) => GetInt32(this[name]); - - public int GetInt32(int id) => GetInt32(this[id]); - - public int GetInt32(object obj) => Convert.ToInt32(obj); - - public string GetString(string name) => this[name] as string; - } } diff --git a/Projects/UOContent/Multis/ContestHouses.cs b/Projects/UOContent/Multis/ContestHouses.cs index c762735b0..8ed17a1c7 100644 --- a/Projects/UOContent/Multis/ContestHouses.cs +++ b/Projects/UOContent/Multis/ContestHouses.cs @@ -1,710 +1,724 @@ using System; -using System.Linq; using System.Collections.Generic; - +using System.Linq; using Server.Items; namespace Server.Multis { - public enum ContestHouseType - { - Keep, - Castle, - Other - } - - public class BaseContestHouse : BaseHouse - { - public ContestHouseType HouseType { get; set; } - public List Fixtures { get; private set; } - - public virtual int SignPostID => 9; - - public override Point3D BaseBanLocation => new Point3D(Components.Min.X, Components.Height - 1 - Components.Center.Y, 0); - - public override Rectangle2D[] Area + public enum ContestHouseType { - get - { - MultiComponentList mcl = Components; - return new[] { new Rectangle2D(mcl.Min.X, mcl.Min.Y, mcl.Width, mcl.Height) }; - } + Keep, + Castle, + Other } - public BaseContestHouse(ContestHouseType type, int multiID, Mobile owner, int maxLockDown, int maxSecure) - : base(multiID, owner, maxLockDown, maxSecure) + public class BaseContestHouse : BaseHouse { - HouseType = type; - - AutoAddFixtures(); - } - - protected void SetSign(int xOffset, int yOffset, int zOffset, bool post) - { - SetSign(xOffset, yOffset, zOffset); - - var hanger = new Static(0xB9E); - hanger.MoveToWorld(new Point3D(X + xOffset, Y + yOffset, Z + zOffset), Map); - - AddFixture(hanger); - - if (post) - { - var signPost = new Static(SignPostID); - signPost.MoveToWorld(new Point3D(X + xOffset, Y + yOffset - 1, Z + zOffset), Map); - - AddFixture(signPost); - } - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - if (Fixtures == null) return; - - foreach (var item in Fixtures) - item.Delete(); - } - - public override void OnLocationChange(Point3D oldLocation) - { - base.OnLocationChange(oldLocation); - - int x = Location.X - oldLocation.X; - int y = Location.Y - oldLocation.Y; - int z = Location.Z - oldLocation.Z; - - if (Fixtures == null) return; - - foreach (var item in Fixtures) - item.Location = new Point3D(item.X + x, item.Y + y, item.Z + z); - } - - public override void OnMapChange() - { - base.OnMapChange(); - - if (Fixtures == null) return; - - foreach (var item in Fixtures) - item.Map = Map; - } - - public void AddTeleporters(int id, Point3D offset1, Point3D offset2) - { - var tele1 = new HouseTeleporter(id); - var tele2 = new HouseTeleporter(id); - - tele1.Target = tele2; - tele2.Target = tele1; - - tele1.MoveToWorld(new Point3D(X + offset1.X, Y + offset1.Y, offset1.Z), Map); - tele2.MoveToWorld(new Point3D(X + offset2.X, Y + offset2.Y, offset2.Z), Map); - - AddFixture(tele1); - AddFixture(tele2); - } - - public void AddFixture(Item item) - { - Fixtures ??= new List(); - - Fixtures.Add(item); - } - - public override bool IsInside(Point3D p, int height) => - base.IsInside(p, height) || Fixtures?.OfType().Any(fix => fix.Location == p) == true; - - public virtual void AutoAddFixtures() - { - var components = MultiData.GetComponents(ItemID); - - var teleporters = new Dictionary>(); - - foreach (var entry in components.List.Where(e => e.Flags == 0)) - // Teleporters - if (entry.ItemId >= 0x181D && entry.ItemId <= 0x1828) + public BaseContestHouse(ContestHouseType type, int multiID, Mobile owner, int maxLockDown, int maxSecure) + : base(multiID, owner, maxLockDown, maxSecure) { - if (teleporters.ContainsKey(entry.ItemId)) - teleporters[entry.ItemId].Add(entry); - else - teleporters[entry.ItemId] = new List { entry }; - } - else - { - ItemData data = TileData.ItemTable[entry.ItemId & TileData.MaxItemValue]; + HouseType = type; - // door - if ((data.Flags & TileFlag.Door) != 0) - AddDoor(entry.ItemId, entry.OffsetX, entry.OffsetY, entry.OffsetZ); - else - { - Item st = new Static((int)entry.ItemId); - - st.MoveToWorld(new Point3D(X + entry.OffsetX, Y + entry.OffsetY, entry.OffsetZ), Map); - AddFixture(st); - } + AutoAddFixtures(); } - foreach (var door in Doors) - foreach (var check in Doors.Where(d => d != door)) - if (door.InRange(check.Location, 1)) - { - door.Link = check; - check.Link = door; - } - - foreach (var (key, value) in teleporters) - { - if (value.Count > 2) - Console.WriteLine("Warning: More than 2 teleporters detected for {0:X}!", key); - else if (value.Count <= 1) + public BaseContestHouse(Serial serial) : base(serial) { - Console.WriteLine("Warning: 1 or less teleporters detected for {0:X}!", key); - - continue; } - AddTeleporters( - key, - new Point3D(value[0].OffsetX, value[0].OffsetY, value[0].OffsetZ), - new Point3D(value[1].OffsetX, value[1].OffsetY, value[1].OffsetZ)); - } + public ContestHouseType HouseType { get; set; } + public List Fixtures { get; private set; } - teleporters.Clear(); - } - - public BaseContestHouse(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - - writer.Write((int)HouseType); - - if (Fixtures != null) - writer.WriteItemList(Fixtures, true); - else - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - HouseType = (ContestHouseType)reader.ReadInt(); - - int count = reader.ReadInt(); - - for (int i = 0; i < count; i++) - AddFixture(reader.ReadItem()); - } - } - - public class TrinsicKeep : BaseContestHouse - { - public static Rectangle2D[] AreaArray = { - new Rectangle2D(-11, -11, 23, 23), new Rectangle2D(-10, 13, 6, 1), - new Rectangle2D(-2, 13, 6, 1), new Rectangle2D(6, 13, 7, 1) - }; - - public TrinsicKeep(Mobile owner) - : base(ContestHouseType.Keep, 0x147E, owner, 2113, 18) - { - SetSign(-11, 13, 7, false); - } - - public TrinsicKeep(Serial serial) : base(serial) - { - } - - public override Rectangle2D[] Area => AreaArray; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class GothicRoseCastle : BaseContestHouse - { - public static Rectangle2D[] AreaArray = { - new Rectangle2D(-15, -15, 31, 31), - new Rectangle2D(-14, 16, 11, 1), - new Rectangle2D(-2, 16, 6, 1), - new Rectangle2D(5, 16, 11, 1) - }; - - public GothicRoseCastle(Mobile owner) - : base(ContestHouseType.Castle, 0x147F, owner, 3281, 28) - { - SetSign(-15, 16, 7, false); - } - - public GothicRoseCastle(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class ElsaCastle : BaseContestHouse - { - public ElsaCastle(Mobile owner) - : base(ContestHouseType.Castle, 0x1480, owner, 3281, 28) - { - SetSign(-15, 16, 7, false); - } - - public ElsaCastle(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class Spires : BaseContestHouse - { - public Spires(Mobile owner) - : base(ContestHouseType.Castle, 0x1481, owner, 3281, 28) - { - SetSign(-15, 16, 7, false); - } - - public Spires(Serial serial) : base(serial) - { - } + public virtual int SignPostID => 9; - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class CastleOfOceania : BaseContestHouse - { - public CastleOfOceania(Mobile owner) - : base(ContestHouseType.Castle, 0x1482, owner, 3281, 28) - { - SetSign(-15, 16, 7, false); - } - - public CastleOfOceania(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class FeudalCastle : BaseContestHouse - { - public static Rectangle2D[] AreaArray = { - new Rectangle2D(-15, -15, 31, 31), - new Rectangle2D(5, 16, 1, 1), - new Rectangle2D(7, 16, 4, 1), - new Rectangle2D(12, 16, 1, 1) - }; - - public FeudalCastle(Mobile owner) - : base(ContestHouseType.Castle, 0x1483, owner, 3281, 28) - { - SetSign(-15, 16, 7, true); - } - - public FeudalCastle(Serial serial) : base(serial) - { - } - - public override Rectangle2D[] Area => AreaArray; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } + public override Point3D BaseBanLocation => new Point3D( + Components.Min.X, + Components.Height - 1 - Components.Center.Y, + 0 + ); - public class RobinsNest : BaseContestHouse - { - public RobinsNest(Mobile owner) - : base(ContestHouseType.Keep, 0x1484, owner, 2113, 18) - { - SetSign(-11, 13, 7, false); - } - - public RobinsNest(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class TraditionalKeep : BaseContestHouse - { - public static Rectangle2D[] AreaArray = { - new Rectangle2D(-11, -11, 23, 23), - new Rectangle2D(-10, 13, 6, 1), - new Rectangle2D(-2, 13, 6, 1), - new Rectangle2D(6, 13, 7, 1), - }; - - public TraditionalKeep(Mobile owner) - : base(ContestHouseType.Keep, 0x1485, owner, 2113, 18) - { - SetSign(-11, 13, 7, false); - } - - public TraditionalKeep(Serial serial) : base(serial) - { - } - - public override Rectangle2D[] Area => AreaArray; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class VillaCrowley : BaseContestHouse - { - public VillaCrowley(Mobile owner) - : base(ContestHouseType.Keep, 0x1486, owner, 2113, 18) - { - SetSign(-11, 13, 7, true); - } - - public VillaCrowley(Serial serial) : base(serial) - { - } + public override Rectangle2D[] Area + { + get + { + var mcl = Components; + return new[] { new Rectangle2D(mcl.Min.X, mcl.Min.Y, mcl.Width, mcl.Height) }; + } + } + + protected void SetSign(int xOffset, int yOffset, int zOffset, bool post) + { + SetSign(xOffset, yOffset, zOffset); + + var hanger = new Static(0xB9E); + hanger.MoveToWorld(new Point3D(X + xOffset, Y + yOffset, Z + zOffset), Map); + + AddFixture(hanger); + + if (post) + { + var signPost = new Static(SignPostID); + signPost.MoveToWorld(new Point3D(X + xOffset, Y + yOffset - 1, Z + zOffset), Map); + + AddFixture(signPost); + } + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + if (Fixtures == null) return; + + foreach (var item in Fixtures) + item.Delete(); + } + + public override void OnLocationChange(Point3D oldLocation) + { + base.OnLocationChange(oldLocation); + + var x = Location.X - oldLocation.X; + var y = Location.Y - oldLocation.Y; + var z = Location.Z - oldLocation.Z; + + if (Fixtures == null) return; + + foreach (var item in Fixtures) + item.Location = new Point3D(item.X + x, item.Y + y, item.Z + z); + } + + public override void OnMapChange() + { + base.OnMapChange(); + + if (Fixtures == null) return; + + foreach (var item in Fixtures) + item.Map = Map; + } + + public void AddTeleporters(int id, Point3D offset1, Point3D offset2) + { + var tele1 = new HouseTeleporter(id); + var tele2 = new HouseTeleporter(id); + + tele1.Target = tele2; + tele2.Target = tele1; + + tele1.MoveToWorld(new Point3D(X + offset1.X, Y + offset1.Y, offset1.Z), Map); + tele2.MoveToWorld(new Point3D(X + offset2.X, Y + offset2.Y, offset2.Z), Map); + + AddFixture(tele1); + AddFixture(tele2); + } + + public void AddFixture(Item item) + { + Fixtures ??= new List(); + + Fixtures.Add(item); + } + + public override bool IsInside(Point3D p, int height) => + base.IsInside(p, height) || Fixtures?.OfType().Any(fix => fix.Location == p) == true; + + public virtual void AutoAddFixtures() + { + var components = MultiData.GetComponents(ItemID); + + var teleporters = new Dictionary>(); + + foreach (var entry in components.List.Where(e => e.Flags == 0)) + // Teleporters + if (entry.ItemId >= 0x181D && entry.ItemId <= 0x1828) + { + if (teleporters.ContainsKey(entry.ItemId)) + teleporters[entry.ItemId].Add(entry); + else + teleporters[entry.ItemId] = new List { entry }; + } + else + { + var data = TileData.ItemTable[entry.ItemId & TileData.MaxItemValue]; + + // door + if ((data.Flags & TileFlag.Door) != 0) + { + AddDoor(entry.ItemId, entry.OffsetX, entry.OffsetY, entry.OffsetZ); + } + else + { + Item st = new Static((int)entry.ItemId); + + st.MoveToWorld(new Point3D(X + entry.OffsetX, Y + entry.OffsetY, entry.OffsetZ), Map); + AddFixture(st); + } + } + + foreach (var door in Doors) + foreach (var check in Doors.Where(d => d != door)) + if (door.InRange(check.Location, 1)) + { + door.Link = check; + check.Link = door; + } + + foreach (var (key, value) in teleporters) + { + if (value.Count > 2) + { + Console.WriteLine("Warning: More than 2 teleporters detected for {0:X}!", key); + } + else if (value.Count <= 1) + { + Console.WriteLine("Warning: 1 or less teleporters detected for {0:X}!", key); + + continue; + } + + AddTeleporters( + key, + new Point3D(value[0].OffsetX, value[0].OffsetY, value[0].OffsetZ), + new Point3D(value[1].OffsetX, value[1].OffsetY, value[1].OffsetZ) + ); + } + + teleporters.Clear(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(0); // version + + writer.Write((int)HouseType); + + if (Fixtures != null) + writer.WriteItemList(Fixtures, true); + else + writer.Write(0); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + HouseType = (ContestHouseType)reader.ReadInt(); + + var count = reader.ReadInt(); + + for (var i = 0; i < count; i++) + AddFixture(reader.ReadItem()); + } + } + + public class TrinsicKeep : BaseContestHouse + { + public static Rectangle2D[] AreaArray = + { + new Rectangle2D(-11, -11, 23, 23), new Rectangle2D(-10, 13, 6, 1), + new Rectangle2D(-2, 13, 6, 1), new Rectangle2D(6, 13, 7, 1) + }; + + public TrinsicKeep(Mobile owner) + : base(ContestHouseType.Keep, 0x147E, owner, 2113, 18) + { + SetSign(-11, 13, 7, false); + } + + public TrinsicKeep(Serial serial) : base(serial) + { + } + + public override Rectangle2D[] Area => AreaArray; + + 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 class GothicRoseCastle : BaseContestHouse + { + public static Rectangle2D[] AreaArray = + { + new Rectangle2D(-15, -15, 31, 31), + new Rectangle2D(-14, 16, 11, 1), + new Rectangle2D(-2, 16, 6, 1), + new Rectangle2D(5, 16, 11, 1) + }; + + public GothicRoseCastle(Mobile owner) + : base(ContestHouseType.Castle, 0x147F, owner, 3281, 28) + { + SetSign(-15, 16, 7, false); + } + + public GothicRoseCastle(Serial serial) : base(serial) + { + } + + 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 class ElsaCastle : BaseContestHouse + { + public ElsaCastle(Mobile owner) + : base(ContestHouseType.Castle, 0x1480, owner, 3281, 28) + { + SetSign(-15, 16, 7, false); + } + + public ElsaCastle(Serial serial) : base(serial) + { + } - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class DarkthornKeep : BaseContestHouse - { - public DarkthornKeep(Mobile owner) - : base(ContestHouseType.Keep, 0x1487, owner, 2113, 18) - { - SetSign(-11, 13, 7, false); - } - - public DarkthornKeep(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class SandalwoodKeep : BaseContestHouse - { - public override int SignPostID => 353; - - public SandalwoodKeep(Mobile owner) - : base(ContestHouseType.Keep, 0x1488, owner, 2113, 18) - { - SetSign(-11, 13, 7, true); - } - - public SandalwoodKeep(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class CasaMoga : BaseContestHouse - { - public CasaMoga(Mobile owner) - : base(ContestHouseType.Keep, 0x1489, owner, 2113, 18) - { - SetSign(-11, 13, 7, false); - } - - public CasaMoga(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class RobinsRoost : BaseContestHouse - { - public RobinsRoost(Mobile owner) - : base(ContestHouseType.Castle, 0x148A, owner, 3281, 28) - { - SetSign(-15, 16, 7, true); - } - - public RobinsRoost(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class Camelot : BaseContestHouse - { - public Camelot(Mobile owner) - : base(ContestHouseType.Castle, 0x148B, owner, 3281, 28) - { - SetSign(-15, 16, 7, false); - } - - public Camelot(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class LacrimaeInCaelo : BaseContestHouse - { - public LacrimaeInCaelo(Mobile owner) - : base(ContestHouseType.Castle, 0x148C, owner, 3281, 28) - { - SetSign(-15, 16, 7, false); - } - - public LacrimaeInCaelo(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class OkinawaSweetDreamCastle : BaseContestHouse - { - public static Rectangle2D[] AreaArray = { - new Rectangle2D(-15, -15, 31, 31), - new Rectangle2D(-14, 16, 6, 1), - new Rectangle2D(-7, 16, 8, 1), - new Rectangle2D(10, 16, 5, 1) - }; - - public override Rectangle2D[] Area => AreaArray; - - public OkinawaSweetDreamCastle(Mobile owner) - : base(ContestHouseType.Castle, 0x148D, owner, 3281, 28) - { - SetSign(-15, 16, 7, true); - } - - public OkinawaSweetDreamCastle(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class TheSandstoneCastle : BaseContestHouse - { - public TheSandstoneCastle(Mobile owner) - : base(ContestHouseType.Castle, 0x148E, owner, 3281, 28) - { - SetSign(-15, 16, 7, true); - } - - public TheSandstoneCastle(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class GrimswindSisters : BaseContestHouse - { - public static Rectangle2D[] AreaArray = { - new Rectangle2D(-15, -15, 31, 31), - new Rectangle2D(-14, 16, 9, 1), - new Rectangle2D(-3, 16, 8, 1), - new Rectangle2D(7, 16, 9, 1) - }; - - public override Rectangle2D[] Area => AreaArray; - - public GrimswindSisters(Mobile owner) - : base(ContestHouseType.Castle, 0x148F, owner, 3281, 28) - { - SetSign(-15, 16, 7, false); - } - - public GrimswindSisters(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } + 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 class Spires : BaseContestHouse + { + public Spires(Mobile owner) + : base(ContestHouseType.Castle, 0x1481, owner, 3281, 28) + { + SetSign(-15, 16, 7, false); + } + + public Spires(Serial serial) : base(serial) + { + } + + 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 class CastleOfOceania : BaseContestHouse + { + public CastleOfOceania(Mobile owner) + : base(ContestHouseType.Castle, 0x1482, owner, 3281, 28) + { + SetSign(-15, 16, 7, false); + } + + public CastleOfOceania(Serial serial) : base(serial) + { + } + + 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 class FeudalCastle : BaseContestHouse + { + public static Rectangle2D[] AreaArray = + { + new Rectangle2D(-15, -15, 31, 31), + new Rectangle2D(5, 16, 1, 1), + new Rectangle2D(7, 16, 4, 1), + new Rectangle2D(12, 16, 1, 1) + }; + + public FeudalCastle(Mobile owner) + : base(ContestHouseType.Castle, 0x1483, owner, 3281, 28) + { + SetSign(-15, 16, 7, true); + } + + public FeudalCastle(Serial serial) : base(serial) + { + } + + public override Rectangle2D[] Area => AreaArray; + + 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 class RobinsNest : BaseContestHouse + { + public RobinsNest(Mobile owner) + : base(ContestHouseType.Keep, 0x1484, owner, 2113, 18) + { + SetSign(-11, 13, 7, false); + } + + public RobinsNest(Serial serial) : base(serial) + { + } + + 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 class TraditionalKeep : BaseContestHouse + { + public static Rectangle2D[] AreaArray = + { + new Rectangle2D(-11, -11, 23, 23), + new Rectangle2D(-10, 13, 6, 1), + new Rectangle2D(-2, 13, 6, 1), + new Rectangle2D(6, 13, 7, 1) + }; + + public TraditionalKeep(Mobile owner) + : base(ContestHouseType.Keep, 0x1485, owner, 2113, 18) + { + SetSign(-11, 13, 7, false); + } + + public TraditionalKeep(Serial serial) : base(serial) + { + } + + public override Rectangle2D[] Area => AreaArray; + + 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 class VillaCrowley : BaseContestHouse + { + public VillaCrowley(Mobile owner) + : base(ContestHouseType.Keep, 0x1486, owner, 2113, 18) + { + SetSign(-11, 13, 7, true); + } + + public VillaCrowley(Serial serial) : base(serial) + { + } + + 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 class DarkthornKeep : BaseContestHouse + { + public DarkthornKeep(Mobile owner) + : base(ContestHouseType.Keep, 0x1487, owner, 2113, 18) + { + SetSign(-11, 13, 7, false); + } + + public DarkthornKeep(Serial serial) : base(serial) + { + } + + 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 class SandalwoodKeep : BaseContestHouse + { + public SandalwoodKeep(Mobile owner) + : base(ContestHouseType.Keep, 0x1488, owner, 2113, 18) + { + SetSign(-11, 13, 7, true); + } + + public SandalwoodKeep(Serial serial) : base(serial) + { + } + + public override int SignPostID => 353; - public override void Deserialize(IGenericReader reader) + 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 class CasaMoga : BaseContestHouse { - base.Deserialize(reader); - int version = reader.ReadInt(); + public CasaMoga(Mobile owner) + : base(ContestHouseType.Keep, 0x1489, owner, 2113, 18) + { + SetSign(-11, 13, 7, false); + } + + public CasaMoga(Serial serial) : base(serial) + { + } + + 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 class RobinsRoost : BaseContestHouse + { + public RobinsRoost(Mobile owner) + : base(ContestHouseType.Castle, 0x148A, owner, 3281, 28) + { + SetSign(-15, 16, 7, true); + } + + public RobinsRoost(Serial serial) : base(serial) + { + } + + 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 class Camelot : BaseContestHouse + { + public Camelot(Mobile owner) + : base(ContestHouseType.Castle, 0x148B, owner, 3281, 28) + { + SetSign(-15, 16, 7, false); + } + + public Camelot(Serial serial) : base(serial) + { + } + + 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 class LacrimaeInCaelo : BaseContestHouse + { + public LacrimaeInCaelo(Mobile owner) + : base(ContestHouseType.Castle, 0x148C, owner, 3281, 28) + { + SetSign(-15, 16, 7, false); + } + + public LacrimaeInCaelo(Serial serial) : base(serial) + { + } + + 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 class OkinawaSweetDreamCastle : BaseContestHouse + { + public static Rectangle2D[] AreaArray = + { + new Rectangle2D(-15, -15, 31, 31), + new Rectangle2D(-14, 16, 6, 1), + new Rectangle2D(-7, 16, 8, 1), + new Rectangle2D(10, 16, 5, 1) + }; + + public OkinawaSweetDreamCastle(Mobile owner) + : base(ContestHouseType.Castle, 0x148D, owner, 3281, 28) + { + SetSign(-15, 16, 7, true); + } + + public OkinawaSweetDreamCastle(Serial serial) : base(serial) + { + } + + public override Rectangle2D[] Area => AreaArray; + + 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 class TheSandstoneCastle : BaseContestHouse + { + public TheSandstoneCastle(Mobile owner) + : base(ContestHouseType.Castle, 0x148E, owner, 3281, 28) + { + SetSign(-15, 16, 7, true); + } + + public TheSandstoneCastle(Serial serial) : base(serial) + { + } + + 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 class GrimswindSisters : BaseContestHouse + { + public static Rectangle2D[] AreaArray = + { + new Rectangle2D(-15, -15, 31, 31), + new Rectangle2D(-14, 16, 9, 1), + new Rectangle2D(-3, 16, 8, 1), + new Rectangle2D(7, 16, 9, 1) + }; + + public GrimswindSisters(Mobile owner) + : base(ContestHouseType.Castle, 0x148F, owner, 3281, 28) + { + SetSign(-15, 16, 7, false); + } + + public GrimswindSisters(Serial serial) : base(serial) + { + } + + public override Rectangle2D[] Area => AreaArray; + + 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(); + } } - } } diff --git a/Projects/UOContent/Multis/Deeds.cs b/Projects/UOContent/Multis/Deeds.cs index e183bd023..c4386310c 100644 --- a/Projects/UOContent/Multis/Deeds.cs +++ b/Projects/UOContent/Multis/Deeds.cs @@ -1,817 +1,822 @@ -using System.Collections.Generic; using Server.Regions; using Server.Targeting; namespace Server.Multis.Deeds { - public class HousePlacementTarget : MultiTarget - { - private readonly HouseDeed m_Deed; - - public HousePlacementTarget(HouseDeed deed) : base(deed.MultiID, deed.Offset) => m_Deed = deed; - - protected override void OnTarget(Mobile from, object o) + public class HousePlacementTarget : MultiTarget { - if (o is IPoint3D ip) - { - if (ip is Item item) - ip = item.GetWorldTop(); + private readonly HouseDeed m_Deed; - Point3D p = new Point3D(ip); + public HousePlacementTarget(HouseDeed deed) : base(deed.MultiID, deed.Offset) => m_Deed = deed; - Region reg = Region.Find(new Point3D(p), from.Map); - - if (from.AccessLevel >= AccessLevel.GameMaster || reg.AllowHousing(from, p)) - m_Deed.OnPlacement(from, p); - else if (reg.IsPartOf()) - from.SendLocalizedMessage( - 501270); // Lord British has decreed a 'no build' period, thus you cannot build this house at this time. - else if (reg.IsPartOf() || reg.IsPartOf()) - from.SendLocalizedMessage( - 1043287); // The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain. - else if (reg.IsPartOf()) - from.SendLocalizedMessage(1150493); // You must have a deed for this plot of land in order to build here. - else - from.SendLocalizedMessage(501265); // Housing can not be created in this area. - } - } - } - - public abstract class HouseDeed : Item - { - public HouseDeed(int id, Point3D offset) : base(0x14F0) - { - Weight = 1.0; - LootType = LootType.Newbied; - - MultiID = id; - Offset = offset; - } - - public HouseDeed(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int MultiID { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public Point3D Offset { get; set; } - - public abstract Rectangle2D[] Area { get; } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(Offset); - - writer.Write(MultiID); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - Offset = reader.ReadPoint3D(); - - goto case 0; - } - case 0: - { - MultiID = reader.ReadInt(); - - break; - } - } - - if (Weight == 0.0) - Weight = 1.0; - } - - public override void OnDoubleClick(Mobile from) - { - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (from.AccessLevel < AccessLevel.GameMaster && BaseHouse.HasAccountHouse(from)) - { - from.SendLocalizedMessage(501271); // You already own a house, you may not place another! - } - else - { - /* House placement cancellation could result in a - * 60 second delay in the return of your deed. - */ - from.SendLocalizedMessage(1010433); - - from.Target = new HousePlacementTarget(this); - } - } - - public abstract BaseHouse GetHouse(Mobile owner); - - public void OnPlacement(Mobile from, Point3D p) - { - if (Deleted) - return; - - if (!IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - else if (from.AccessLevel < AccessLevel.GameMaster && BaseHouse.HasAccountHouse(from)) - { - from.SendLocalizedMessage(501271); // You already own a house, you may not place another! - } - else - { - Point3D center = new Point3D(p.X - Offset.X, p.Y - Offset.Y, p.Z - Offset.Z); - HousePlacementResult res = HousePlacement.Check(from, MultiID, center, out List toMove); - - switch (res) + protected override void OnTarget(Mobile from, object o) { - case HousePlacementResult.Valid: + if (o is IPoint3D ip) { - BaseHouse house = GetHouse(from); - house.MoveToWorld(center, from.Map); - Delete(); + if (ip is Item item) + ip = item.GetWorldTop(); - for (int i = 0; i < toMove.Count; ++i) - { - object o = toMove[i]; + var p = new Point3D(ip); - if (o is Mobile mobile) - mobile.Location = house.BanLocation; - else if (o is Item item) - item.Location = house.BanLocation; - } + var reg = Region.Find(new Point3D(p), from.Map); - break; - } - case HousePlacementResult.BadItem: - case HousePlacementResult.BadLand: - case HousePlacementResult.BadStatic: - case HousePlacementResult.BadRegionHidden: - { - from.SendLocalizedMessage( - 1043287); // The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain. - break; - } - case HousePlacementResult.NoSurface: - { - from.SendMessage( - "The house could not be created here. Part of the foundation would not be on any surface."); - break; - } - case HousePlacementResult.BadRegion: - { - from.SendLocalizedMessage(501265); // Housing cannot be created in this area. - break; - } - case HousePlacementResult.BadRegionTemp: - { - from.SendLocalizedMessage( - 501270); // Lord British has decreed a 'no build' period, thus you cannot build this house at this time. - break; - } - case HousePlacementResult.BadRegionRaffle: - { - from.SendLocalizedMessage( - 1150493); // You must have a deed for this plot of land in order to build here. - break; + if (from.AccessLevel >= AccessLevel.GameMaster || reg.AllowHousing(from, p)) + m_Deed.OnPlacement(from, p); + else if (reg.IsPartOf()) + from.SendLocalizedMessage( + 501270 + ); // Lord British has decreed a 'no build' period, thus you cannot build this house at this time. + else if (reg.IsPartOf() || reg.IsPartOf()) + from.SendLocalizedMessage( + 1043287 + ); // The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain. + else if (reg.IsPartOf()) + from.SendLocalizedMessage(1150493); // You must have a deed for this plot of land in order to build here. + else + from.SendLocalizedMessage(501265); // Housing can not be created in this area. } } - } } - } - public class StonePlasterHouseDeed : HouseDeed - { - [Constructible] - public StonePlasterHouseDeed() : base(0x64, new Point3D(0, 4, 0)) - { - } + public abstract class HouseDeed : Item + { + public HouseDeed(int id, Point3D offset) : base(0x14F0) + { + Weight = 1.0; + LootType = LootType.Newbied; + + MultiID = id; + Offset = offset; + } + + public HouseDeed(Serial serial) : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public int MultiID { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public Point3D Offset { get; set; } + + public abstract Rectangle2D[] Area { get; } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(Offset); + + writer.Write(MultiID); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + Offset = reader.ReadPoint3D(); + + goto case 0; + } + case 0: + { + MultiID = reader.ReadInt(); + + break; + } + } + + if (Weight == 0.0) + Weight = 1.0; + } + + public override void OnDoubleClick(Mobile from) + { + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else if (from.AccessLevel < AccessLevel.GameMaster && BaseHouse.HasAccountHouse(from)) + { + from.SendLocalizedMessage(501271); // You already own a house, you may not place another! + } + else + { + /* House placement cancellation could result in a + * 60 second delay in the return of your deed. + */ + from.SendLocalizedMessage(1010433); + + from.Target = new HousePlacementTarget(this); + } + } + + public abstract BaseHouse GetHouse(Mobile owner); + + public void OnPlacement(Mobile from, Point3D p) + { + if (Deleted) + return; + + if (!IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } + else if (from.AccessLevel < AccessLevel.GameMaster && BaseHouse.HasAccountHouse(from)) + { + from.SendLocalizedMessage(501271); // You already own a house, you may not place another! + } + else + { + var center = new Point3D(p.X - Offset.X, p.Y - Offset.Y, p.Z - Offset.Z); + var res = HousePlacement.Check(from, MultiID, center, out var toMove); + + switch (res) + { + case HousePlacementResult.Valid: + { + var house = GetHouse(from); + house.MoveToWorld(center, from.Map); + Delete(); + + for (var i = 0; i < toMove.Count; ++i) + { + object o = toMove[i]; + + if (o is Mobile mobile) + mobile.Location = house.BanLocation; + else if (o is Item item) + item.Location = house.BanLocation; + } + + break; + } + case HousePlacementResult.BadItem: + case HousePlacementResult.BadLand: + case HousePlacementResult.BadStatic: + case HousePlacementResult.BadRegionHidden: + { + from.SendLocalizedMessage( + 1043287 + ); // The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain. + break; + } + case HousePlacementResult.NoSurface: + { + from.SendMessage( + "The house could not be created here. Part of the foundation would not be on any surface." + ); + break; + } + case HousePlacementResult.BadRegion: + { + from.SendLocalizedMessage(501265); // Housing cannot be created in this area. + break; + } + case HousePlacementResult.BadRegionTemp: + { + from.SendLocalizedMessage( + 501270 + ); // Lord British has decreed a 'no build' period, thus you cannot build this house at this time. + break; + } + case HousePlacementResult.BadRegionRaffle: + { + from.SendLocalizedMessage( + 1150493 + ); // You must have a deed for this plot of land in order to build here. + break; + } + } + } + } + } + + public class StonePlasterHouseDeed : HouseDeed + { + [Constructible] + public StonePlasterHouseDeed() : base(0x64, new Point3D(0, 4, 0)) + { + } + + public StonePlasterHouseDeed(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1041211; + public override Rectangle2D[] Area => SmallOldHouse.AreaArray; + + public override BaseHouse GetHouse(Mobile owner) => new SmallOldHouse(owner, 0x64); + + 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 class FieldStoneHouseDeed : HouseDeed + { + [Constructible] + public FieldStoneHouseDeed() : base(0x66, new Point3D(0, 4, 0)) + { + } - public StonePlasterHouseDeed(Serial serial) : base(serial) - { - } + public FieldStoneHouseDeed(Serial serial) : base(serial) + { + } - public override int LabelNumber => 1041211; - public override Rectangle2D[] Area => SmallOldHouse.AreaArray; + public override int LabelNumber => 1041212; + public override Rectangle2D[] Area => SmallOldHouse.AreaArray; - public override BaseHouse GetHouse(Mobile owner) => new SmallOldHouse(owner, 0x64); + public override BaseHouse GetHouse(Mobile owner) => new SmallOldHouse(owner, 0x66); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); + } } - } - public class FieldStoneHouseDeed : HouseDeed - { - [Constructible] - public FieldStoneHouseDeed() : base(0x66, new Point3D(0, 4, 0)) + public class SmallBrickHouseDeed : HouseDeed { - } + [Constructible] + public SmallBrickHouseDeed() : base(0x68, new Point3D(0, 4, 0)) + { + } - public FieldStoneHouseDeed(Serial serial) : base(serial) - { - } + public SmallBrickHouseDeed(Serial serial) : base(serial) + { + } - public override int LabelNumber => 1041212; - public override Rectangle2D[] Area => SmallOldHouse.AreaArray; + public override int LabelNumber => 1041213; + public override Rectangle2D[] Area => SmallOldHouse.AreaArray; - public override BaseHouse GetHouse(Mobile owner) => new SmallOldHouse(owner, 0x66); + public override BaseHouse GetHouse(Mobile owner) => new SmallOldHouse(owner, 0x68); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); + } } - } - public class SmallBrickHouseDeed : HouseDeed - { - [Constructible] - public SmallBrickHouseDeed() : base(0x68, new Point3D(0, 4, 0)) + public class WoodHouseDeed : HouseDeed { - } + [Constructible] + public WoodHouseDeed() : base(0x6A, new Point3D(0, 4, 0)) + { + } - public SmallBrickHouseDeed(Serial serial) : base(serial) - { - } + public WoodHouseDeed(Serial serial) : base(serial) + { + } - public override int LabelNumber => 1041213; - public override Rectangle2D[] Area => SmallOldHouse.AreaArray; + public override int LabelNumber => 1041214; + public override Rectangle2D[] Area => SmallOldHouse.AreaArray; - public override BaseHouse GetHouse(Mobile owner) => new SmallOldHouse(owner, 0x68); + public override BaseHouse GetHouse(Mobile owner) => new SmallOldHouse(owner, 0x6A); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); + } } - } - public class WoodHouseDeed : HouseDeed - { - [Constructible] - public WoodHouseDeed() : base(0x6A, new Point3D(0, 4, 0)) + public class WoodPlasterHouseDeed : HouseDeed { - } + [Constructible] + public WoodPlasterHouseDeed() : base(0x6C, new Point3D(0, 4, 0)) + { + } - public WoodHouseDeed(Serial serial) : base(serial) - { - } + public WoodPlasterHouseDeed(Serial serial) : base(serial) + { + } - public override int LabelNumber => 1041214; - public override Rectangle2D[] Area => SmallOldHouse.AreaArray; + public override int LabelNumber => 1041215; + public override Rectangle2D[] Area => SmallOldHouse.AreaArray; - public override BaseHouse GetHouse(Mobile owner) => new SmallOldHouse(owner, 0x6A); + public override BaseHouse GetHouse(Mobile owner) => new SmallOldHouse(owner, 0x6C); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); + } } - } - public class WoodPlasterHouseDeed : HouseDeed - { - [Constructible] - public WoodPlasterHouseDeed() : base(0x6C, new Point3D(0, 4, 0)) + public class ThatchedRoofCottageDeed : HouseDeed { - } + [Constructible] + public ThatchedRoofCottageDeed() : base(0x6E, new Point3D(0, 4, 0)) + { + } - public WoodPlasterHouseDeed(Serial serial) : base(serial) - { - } + public ThatchedRoofCottageDeed(Serial serial) : base(serial) + { + } - public override int LabelNumber => 1041215; - public override Rectangle2D[] Area => SmallOldHouse.AreaArray; + public override int LabelNumber => 1041216; + public override Rectangle2D[] Area => SmallOldHouse.AreaArray; - public override BaseHouse GetHouse(Mobile owner) => new SmallOldHouse(owner, 0x6C); + public override BaseHouse GetHouse(Mobile owner) => new SmallOldHouse(owner, 0x6E); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); + } } - } - public class ThatchedRoofCottageDeed : HouseDeed - { - [Constructible] - public ThatchedRoofCottageDeed() : base(0x6E, new Point3D(0, 4, 0)) + public class BrickHouseDeed : HouseDeed { - } + [Constructible] + public BrickHouseDeed() : base(0x74, new Point3D(-1, 7, 0)) + { + } - public ThatchedRoofCottageDeed(Serial serial) : base(serial) - { - } + public BrickHouseDeed(Serial serial) : base(serial) + { + } - public override int LabelNumber => 1041216; - public override Rectangle2D[] Area => SmallOldHouse.AreaArray; + public override int LabelNumber => 1041219; + public override Rectangle2D[] Area => GuildHouse.AreaArray; - public override BaseHouse GetHouse(Mobile owner) => new SmallOldHouse(owner, 0x6E); + public override BaseHouse GetHouse(Mobile owner) => new GuildHouse(owner); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); + } } - } - public class BrickHouseDeed : HouseDeed - { - [Constructible] - public BrickHouseDeed() : base(0x74, new Point3D(-1, 7, 0)) + public class TwoStoryWoodPlasterHouseDeed : HouseDeed { - } + [Constructible] + public TwoStoryWoodPlasterHouseDeed() : base(0x76, new Point3D(-3, 7, 0)) + { + } - public BrickHouseDeed(Serial serial) : base(serial) - { - } + public TwoStoryWoodPlasterHouseDeed(Serial serial) : base(serial) + { + } - public override int LabelNumber => 1041219; - public override Rectangle2D[] Area => GuildHouse.AreaArray; + public override int LabelNumber => 1041220; + public override Rectangle2D[] Area => TwoStoryHouse.AreaArray; - public override BaseHouse GetHouse(Mobile owner) => new GuildHouse(owner); + public override BaseHouse GetHouse(Mobile owner) => new TwoStoryHouse(owner, 0x76); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); + } } - } - public class TwoStoryWoodPlasterHouseDeed : HouseDeed - { - [Constructible] - public TwoStoryWoodPlasterHouseDeed() : base(0x76, new Point3D(-3, 7, 0)) + public class TwoStoryStonePlasterHouseDeed : HouseDeed { - } + [Constructible] + public TwoStoryStonePlasterHouseDeed() : base(0x78, new Point3D(-3, 7, 0)) + { + } - public TwoStoryWoodPlasterHouseDeed(Serial serial) : base(serial) - { - } + public TwoStoryStonePlasterHouseDeed(Serial serial) : base(serial) + { + } - public override int LabelNumber => 1041220; - public override Rectangle2D[] Area => TwoStoryHouse.AreaArray; + public override int LabelNumber => 1041221; + public override Rectangle2D[] Area => TwoStoryHouse.AreaArray; - public override BaseHouse GetHouse(Mobile owner) => new TwoStoryHouse(owner, 0x76); + public override BaseHouse GetHouse(Mobile owner) => new TwoStoryHouse(owner, 0x78); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); + } } - } - public class TwoStoryStonePlasterHouseDeed : HouseDeed - { - [Constructible] - public TwoStoryStonePlasterHouseDeed() : base(0x78, new Point3D(-3, 7, 0)) + public class TowerDeed : HouseDeed { - } + [Constructible] + public TowerDeed() : base(0x7A, new Point3D(0, 7, 0)) + { + } - public TwoStoryStonePlasterHouseDeed(Serial serial) : base(serial) - { - } + public TowerDeed(Serial serial) : base(serial) + { + } - public override int LabelNumber => 1041221; - public override Rectangle2D[] Area => TwoStoryHouse.AreaArray; + public override int LabelNumber => 1041222; + public override Rectangle2D[] Area => Tower.AreaArray; - public override BaseHouse GetHouse(Mobile owner) => new TwoStoryHouse(owner, 0x78); + public override BaseHouse GetHouse(Mobile owner) => new Tower(owner); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); + } } - } - public class TowerDeed : HouseDeed - { - [Constructible] - public TowerDeed() : base(0x7A, new Point3D(0, 7, 0)) + public class KeepDeed : HouseDeed { - } + [Constructible] + public KeepDeed() : base(0x7C, new Point3D(0, 11, 0)) + { + } - public TowerDeed(Serial serial) : base(serial) - { - } + public KeepDeed(Serial serial) : base(serial) + { + } - public override int LabelNumber => 1041222; - public override Rectangle2D[] Area => Tower.AreaArray; + public override int LabelNumber => 1041223; + public override Rectangle2D[] Area => Keep.AreaArray; - public override BaseHouse GetHouse(Mobile owner) => new Tower(owner); + public override BaseHouse GetHouse(Mobile owner) => new Keep(owner); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); + } } - } - public class KeepDeed : HouseDeed - { - [Constructible] - public KeepDeed() : base(0x7C, new Point3D(0, 11, 0)) + public class CastleDeed : HouseDeed { - } + [Constructible] + public CastleDeed() : base(0x7E, new Point3D(0, 16, 0)) + { + } - public KeepDeed(Serial serial) : base(serial) - { - } + public CastleDeed(Serial serial) : base(serial) + { + } - public override int LabelNumber => 1041223; - public override Rectangle2D[] Area => Keep.AreaArray; + public override int LabelNumber => 1041224; + public override Rectangle2D[] Area => Castle.AreaArray; - public override BaseHouse GetHouse(Mobile owner) => new Keep(owner); + public override BaseHouse GetHouse(Mobile owner) => new Castle(owner); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); + } } - } - public class CastleDeed : HouseDeed - { - [Constructible] - public CastleDeed() : base(0x7E, new Point3D(0, 16, 0)) + public class LargePatioDeed : HouseDeed { - } + [Constructible] + public LargePatioDeed() : base(0x8C, new Point3D(-4, 7, 0)) + { + } - public CastleDeed(Serial serial) : base(serial) - { - } + public LargePatioDeed(Serial serial) : base(serial) + { + } - public override int LabelNumber => 1041224; - public override Rectangle2D[] Area => Castle.AreaArray; + public override int LabelNumber => 1041231; + public override Rectangle2D[] Area => LargePatioHouse.AreaArray; - public override BaseHouse GetHouse(Mobile owner) => new Castle(owner); + public override BaseHouse GetHouse(Mobile owner) => new LargePatioHouse(owner); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); + } } - } - public class LargePatioDeed : HouseDeed - { - [Constructible] - public LargePatioDeed() : base(0x8C, new Point3D(-4, 7, 0)) + public class LargeMarbleDeed : HouseDeed { - } + [Constructible] + public LargeMarbleDeed() : base(0x96, new Point3D(-4, 7, 0)) + { + } - public LargePatioDeed(Serial serial) : base(serial) - { - } + public LargeMarbleDeed(Serial serial) : base(serial) + { + } - public override int LabelNumber => 1041231; - public override Rectangle2D[] Area => LargePatioHouse.AreaArray; + public override int LabelNumber => 1041236; + public override Rectangle2D[] Area => LargeMarbleHouse.AreaArray; - public override BaseHouse GetHouse(Mobile owner) => new LargePatioHouse(owner); + public override BaseHouse GetHouse(Mobile owner) => new LargeMarbleHouse(owner); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); + } } - } - public class LargeMarbleDeed : HouseDeed - { - [Constructible] - public LargeMarbleDeed() : base(0x96, new Point3D(-4, 7, 0)) + public class SmallTowerDeed : HouseDeed { - } + [Constructible] + public SmallTowerDeed() : base(0x98, new Point3D(3, 4, 0)) + { + } - public LargeMarbleDeed(Serial serial) : base(serial) - { - } + public SmallTowerDeed(Serial serial) : base(serial) + { + } - public override int LabelNumber => 1041236; - public override Rectangle2D[] Area => LargeMarbleHouse.AreaArray; + public override int LabelNumber => 1041237; + public override Rectangle2D[] Area => SmallTower.AreaArray; - public override BaseHouse GetHouse(Mobile owner) => new LargeMarbleHouse(owner); + public override BaseHouse GetHouse(Mobile owner) => new SmallTower(owner); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); + } } - } - public class SmallTowerDeed : HouseDeed - { - [Constructible] - public SmallTowerDeed() : base(0x98, new Point3D(3, 4, 0)) + public class LogCabinDeed : HouseDeed { - } + [Constructible] + public LogCabinDeed() : base(0x9A, new Point3D(1, 6, 0)) + { + } - public SmallTowerDeed(Serial serial) : base(serial) - { - } + public LogCabinDeed(Serial serial) : base(serial) + { + } - public override int LabelNumber => 1041237; - public override Rectangle2D[] Area => SmallTower.AreaArray; + public override int LabelNumber => 1041238; + public override Rectangle2D[] Area => LogCabin.AreaArray; - public override BaseHouse GetHouse(Mobile owner) => new SmallTower(owner); + public override BaseHouse GetHouse(Mobile owner) => new LogCabin(owner); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); + } } - } - public class LogCabinDeed : HouseDeed - { - [Constructible] - public LogCabinDeed() : base(0x9A, new Point3D(1, 6, 0)) + public class SandstonePatioDeed : HouseDeed { - } + [Constructible] + public SandstonePatioDeed() : base(0x9C, new Point3D(-1, 4, 0)) + { + } - public LogCabinDeed(Serial serial) : base(serial) - { - } + public SandstonePatioDeed(Serial serial) : base(serial) + { + } - public override int LabelNumber => 1041238; - public override Rectangle2D[] Area => LogCabin.AreaArray; + public override int LabelNumber => 1041239; + public override Rectangle2D[] Area => SandStonePatio.AreaArray; - public override BaseHouse GetHouse(Mobile owner) => new LogCabin(owner); + public override BaseHouse GetHouse(Mobile owner) => new SandStonePatio(owner); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); + } } - } - public class SandstonePatioDeed : HouseDeed - { - [Constructible] - public SandstonePatioDeed() : base(0x9C, new Point3D(-1, 4, 0)) + public class VillaDeed : HouseDeed { - } + [Constructible] + public VillaDeed() : base(0x9E, new Point3D(3, 6, 0)) + { + } - public SandstonePatioDeed(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1041239; - public override Rectangle2D[] Area => SandStonePatio.AreaArray; - - public override BaseHouse GetHouse(Mobile owner) => new SandStonePatio(owner); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } - - public class VillaDeed : HouseDeed - { - [Constructible] - public VillaDeed() : base(0x9E, new Point3D(3, 6, 0)) - { - } - - public VillaDeed(Serial serial) : base(serial) - { - } + public VillaDeed(Serial serial) : base(serial) + { + } - public override int LabelNumber => 1041240; - public override Rectangle2D[] Area => TwoStoryVilla.AreaArray; + public override int LabelNumber => 1041240; + public override Rectangle2D[] Area => TwoStoryVilla.AreaArray; - public override BaseHouse GetHouse(Mobile owner) => new TwoStoryVilla(owner); + public override BaseHouse GetHouse(Mobile owner) => new TwoStoryVilla(owner); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); + } } - } - public class StoneWorkshopDeed : HouseDeed - { - [Constructible] - public StoneWorkshopDeed() : base(0xA0, new Point3D(-1, 4, 0)) + public class StoneWorkshopDeed : HouseDeed { - } + [Constructible] + public StoneWorkshopDeed() : base(0xA0, new Point3D(-1, 4, 0)) + { + } - public StoneWorkshopDeed(Serial serial) : base(serial) - { - } + public StoneWorkshopDeed(Serial serial) : base(serial) + { + } - public override int LabelNumber => 1041241; - public override Rectangle2D[] Area => SmallShop.AreaArray2; + public override int LabelNumber => 1041241; + public override Rectangle2D[] Area => SmallShop.AreaArray2; - public override BaseHouse GetHouse(Mobile owner) => new SmallShop(owner, 0xA0); + public override BaseHouse GetHouse(Mobile owner) => new SmallShop(owner, 0xA0); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); + } } - } - public class MarbleWorkshopDeed : HouseDeed - { - [Constructible] - public MarbleWorkshopDeed() : base(0xA2, new Point3D(-1, 4, 0)) + public class MarbleWorkshopDeed : HouseDeed { - } + [Constructible] + public MarbleWorkshopDeed() : base(0xA2, new Point3D(-1, 4, 0)) + { + } - public MarbleWorkshopDeed(Serial serial) : base(serial) - { - } + public MarbleWorkshopDeed(Serial serial) : base(serial) + { + } - public override int LabelNumber => 1041242; - public override Rectangle2D[] Area => SmallShop.AreaArray1; + public override int LabelNumber => 1041242; + public override Rectangle2D[] Area => SmallShop.AreaArray1; - public override BaseHouse GetHouse(Mobile owner) => new SmallShop(owner, 0xA2); + public override BaseHouse GetHouse(Mobile owner) => new SmallShop(owner, 0xA2); - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); - writer.Write(0); // version - } + writer.Write(0); // version + } - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); - int version = reader.ReadInt(); + var version = reader.ReadInt(); + } } - } } diff --git a/Projects/UOContent/Multis/DynamicDecay.cs b/Projects/UOContent/Multis/DynamicDecay.cs index e568e88a3..2992d64fa 100644 --- a/Projects/UOContent/Multis/DynamicDecay.cs +++ b/Projects/UOContent/Multis/DynamicDecay.cs @@ -3,53 +3,53 @@ using System.Collections.Generic; namespace Server.Multis { - public class DynamicDecay - { - private static readonly Dictionary m_Stages; - - static DynamicDecay() + public class DynamicDecay { - m_Stages = new Dictionary(); + private static readonly Dictionary m_Stages; - Register(DecayLevel.LikeNew, TimeSpan.FromHours(1), TimeSpan.FromHours(1)); - Register(DecayLevel.Slightly, TimeSpan.FromDays(1), TimeSpan.FromDays(2)); - Register(DecayLevel.Somewhat, TimeSpan.FromDays(1), TimeSpan.FromDays(2)); - Register(DecayLevel.Fairly, TimeSpan.FromDays(1), TimeSpan.FromDays(2)); - Register(DecayLevel.Greatly, TimeSpan.FromDays(1), TimeSpan.FromDays(2)); - Register(DecayLevel.IDOC, TimeSpan.FromHours(12), TimeSpan.FromHours(24)); + static DynamicDecay() + { + m_Stages = new Dictionary(); + + Register(DecayLevel.LikeNew, TimeSpan.FromHours(1), TimeSpan.FromHours(1)); + Register(DecayLevel.Slightly, TimeSpan.FromDays(1), TimeSpan.FromDays(2)); + Register(DecayLevel.Somewhat, TimeSpan.FromDays(1), TimeSpan.FromDays(2)); + Register(DecayLevel.Fairly, TimeSpan.FromDays(1), TimeSpan.FromDays(2)); + Register(DecayLevel.Greatly, TimeSpan.FromDays(1), TimeSpan.FromDays(2)); + Register(DecayLevel.IDOC, TimeSpan.FromHours(12), TimeSpan.FromHours(24)); + } + + public static bool Enabled => Core.ML; + + public static void Register(DecayLevel level, TimeSpan min, TimeSpan max) + { + m_Stages[level] = new DecayStageInfo(min, max); + } + + public static bool Decays(DecayLevel level) => m_Stages.ContainsKey(level); + + public static TimeSpan GetRandomDuration(DecayLevel level) + { + if (!m_Stages.TryGetValue(level, out var info)) + return TimeSpan.Zero; + + var min = info.MinDuration.Ticks; + var max = info.MaxDuration.Ticks; + + return TimeSpan.FromTicks(min + (long)(Utility.RandomDouble() * (max - min))); + } } - public static bool Enabled => Core.ML; - - public static void Register(DecayLevel level, TimeSpan min, TimeSpan max) + public class DecayStageInfo { - m_Stages[level] = new DecayStageInfo(min, max); + public DecayStageInfo(TimeSpan min, TimeSpan max) + { + MinDuration = min; + MaxDuration = max; + } + + public TimeSpan MinDuration { get; } + + public TimeSpan MaxDuration { get; } } - - public static bool Decays(DecayLevel level) => m_Stages.ContainsKey(level); - - public static TimeSpan GetRandomDuration(DecayLevel level) - { - if (!m_Stages.TryGetValue(level, out DecayStageInfo info)) - return TimeSpan.Zero; - - long min = info.MinDuration.Ticks; - long max = info.MaxDuration.Ticks; - - return TimeSpan.FromTicks(min + (long)(Utility.RandomDouble() * (max - min))); - } - } - - public class DecayStageInfo - { - public DecayStageInfo(TimeSpan min, TimeSpan max) - { - MinDuration = min; - MaxDuration = max; - } - - public TimeSpan MinDuration { get; } - - public TimeSpan MaxDuration { get; } - } } diff --git a/Projects/UOContent/Multis/HouseFoundation.cs b/Projects/UOContent/Multis/HouseFoundation.cs index 23b44e426..76d848332 100644 --- a/Projects/UOContent/Multis/HouseFoundation.cs +++ b/Projects/UOContent/Multis/HouseFoundation.cs @@ -14,2516 +14,2547 @@ using Server.Spells; namespace Server.Multis { - public enum FoundationType - { - Stone, - DarkWood, - LightWood, - Dungeon, - Brick, - ElvenGrey, - ElvenNatural, - Crystal, - Shadow - } - - public class HouseFoundation : BaseHouse - { - private static ComponentVerification m_Verification; - - public static readonly bool AllowStairSectioning = true; - - /* Stair block IDs - * (sorted ascending) - */ - private static readonly int[] m_BlockIDs = + public enum FoundationType { - 0x3EE, 0x709, 0x71E, 0x721, - 0x738, 0x750, 0x76C, 0x788, - 0x7A3, 0x7BA, 0x35D2, 0x3609, - 0x4317, 0x4318, 0x4B07, 0x7807 - }; - - /* Stair sequence IDs - * (sorted ascending) - * Use this for stairs in the proper N,W,S,E sequence - */ - private static readonly int[] m_StairSeqs = - { - 0x3EF, 0x70A, 0x722, 0x739, - 0x751, 0x76D, 0x789, 0x7A4 - }; - - /* Other stair IDs - * Listed in order: north, west, south, east - * Use this for stairs not in the proper sequence - */ - private static readonly int[] m_StairIDs = - { - 0x71F, 0x736, 0x737, 0x749, - 0x35D4, 0x35D3, 0x35D6, 0x35D5, - 0x360B, 0x360A, 0x360D, 0x360C, - 0x4360, 0x435E, 0x435F, 0x4361, - 0x435C, 0x435A, 0x435B, 0x435D, - 0x4364, 0x4362, 0x4363, 0x4365, - 0x4B05, 0x4B04, 0x4B34, 0x4B33, - 0x7809, 0x7808, 0x780A, 0x780B, - 0x7BB, 0x7BC - }; - - private DesignState m_Backup; // State at last user backup. - private DesignState m_Current; // State which is currently visible. - - private int m_DefaultPrice; - private DesignState m_Design; // State of current design. - - public HouseFoundation(Mobile owner, int multiID, int maxLockdowns, int maxSecures) - : base(multiID, owner, maxLockdowns, maxSecures) - { - SignpostGraphic = 9; - - Fixtures = new List(); - - int x = Components.Min.X; - int y = Components.Height - 1 - Components.Center.Y; - - SignHanger = new Static(0xB98); - SignHanger.MoveToWorld(new Point3D(X + x, Y + y, Z + 7), Map); - - CheckSignpost(); - - SetSign(x, y, 7); + Stone, + DarkWood, + LightWood, + Dungeon, + Brick, + ElvenGrey, + ElvenNatural, + Crystal, + Shadow } - public HouseFoundation(Serial serial) - : base(serial) + public class HouseFoundation : BaseHouse { - } + private static ComponentVerification m_Verification; - public FoundationType Type { get; set; } + public static readonly bool AllowStairSectioning = true; - public int LastRevision { get; set; } - - public List Fixtures { get; private set; } - - public Item SignHanger { get; private set; } - - public Item Signpost { get; private set; } - - public int SignpostGraphic { get; set; } - - public Mobile Customizer { get; set; } - - public override bool IsAosRules => true; - - public override bool IsActive => Customizer == null; - - public virtual int CustomizationCost => Core.AOS ? 0 : 10000; - - public override MultiComponentList Components - { - get - { - if (m_Current == null) - SetInitialState(); - - return m_Current.Components; - } - } - - public DesignState CurrentState - { - get - { - if (m_Current == null) SetInitialState(); - return m_Current; - } - set => m_Current = value; - } - - public DesignState DesignState - { - get - { - if (m_Design == null) SetInitialState(); - return m_Design; - } - set => m_Design = value; - } - - public DesignState BackupState - { - get - { - if (m_Backup == null) SetInitialState(); - return m_Backup; - } - set => m_Backup = value; - } - - public override Rectangle2D[] Area - { - get - { - MultiComponentList mcl = Components; - - return new[] { new Rectangle2D(mcl.Min.X, mcl.Min.Y, mcl.Width, mcl.Height) }; - } - } - - public override Point3D BaseBanLocation => - new Point3D(Components.Min.X, Components.Height - 1 - Components.Center.Y, 0); - - public override int DefaultPrice => m_DefaultPrice; - - public int MaxLevels - { - get - { - MultiComponentList mcl = Components; - - if (mcl.Width >= 14 || mcl.Height >= 14) - return 4; - return 3; - } - } - - public static ComponentVerification Verification => m_Verification ?? (m_Verification = new ComponentVerification()); - - public bool IsFixture(Item item) => Fixtures.Contains(item); - - public override int GetMaxUpdateRange() => 24; - - public override int GetUpdateRange(Mobile m) - { - int w = CurrentState.Components.Width; - int h = CurrentState.Components.Height - 1; - int v = 18 + (w > h ? w : h) / 2; - - if (v > 24) - v = 24; - else if (v < 18) - v = 18; - - return v; - } - - public void SetInitialState() - { - // This is a new house, it has not yet loaded a design state - m_Current = new DesignState(this, GetEmptyFoundation()); - m_Design = new DesignState(m_Current); - m_Backup = new DesignState(m_Current); - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - SignHanger?.Delete(); - - Signpost?.Delete(); - - if (Fixtures == null) - return; - - for (int i = 0; i < Fixtures.Count; ++i) - { - Item item = Fixtures[i]; - - item?.Delete(); - } - - Fixtures.Clear(); - } - - public override void OnLocationChange(Point3D oldLocation) - { - base.OnLocationChange(oldLocation); - - int x = Location.X - oldLocation.X; - int y = Location.Y - oldLocation.Y; - int z = Location.Z - oldLocation.Z; - - SignHanger?.MoveToWorld(new Point3D(SignHanger.X + x, SignHanger.Y + y, SignHanger.Z + z), Map); - - Signpost?.MoveToWorld(new Point3D(Signpost.X + x, Signpost.Y + y, Signpost.Z + z), Map); - - if (Fixtures == null) - return; - - for (int i = 0; i < Fixtures.Count; ++i) - { - Item item = Fixtures[i]; - - if (item is BaseDoor door && Doors.Contains(door)) - continue; - - item.MoveToWorld(new Point3D(item.X + x, item.Y + y, item.Z + z), Map); - } - } - - public override void OnMapChange() - { - base.OnMapChange(); - - if (SignHanger != null) - SignHanger.Map = Map; - - if (Signpost != null) - Signpost.Map = Map; - - if (Fixtures == null) - return; - - for (int i = 0; i < Fixtures.Count; ++i) - Fixtures[i].Map = Map; - } - - public void ClearFixtures(Mobile from) - { - if (Fixtures == null) - return; - - RemoveKeys(from); - - for (int i = 0; i < Fixtures.Count; ++i) - { - Item item = Fixtures[i]; - item.Delete(); - - if (item is BaseDoor door) - Doors.Remove(door); - } - - Fixtures.Clear(); - } - - public void AddFixtures(Mobile from, MultiTileEntry[] list) - { - Fixtures ??= new List(); - - uint keyValue = 0; - - for (int i = 0; i < list.Length; ++i) - { - MultiTileEntry mte = list[i]; - int itemID = mte.ItemId; - - if (itemID >= 0x181D && itemID < 0x1829) + /* Stair block IDs + * (sorted ascending) + */ + private static readonly int[] m_BlockIDs = { - HouseTeleporter tp = new HouseTeleporter(itemID); + 0x3EE, 0x709, 0x71E, 0x721, + 0x738, 0x750, 0x76C, 0x788, + 0x7A3, 0x7BA, 0x35D2, 0x3609, + 0x4317, 0x4318, 0x4B07, 0x7807 + }; - AddFixture(tp, mte); + /* Stair sequence IDs + * (sorted ascending) + * Use this for stairs in the proper N,W,S,E sequence + */ + private static readonly int[] m_StairSeqs = + { + 0x3EF, 0x70A, 0x722, 0x739, + 0x751, 0x76D, 0x789, 0x7A4 + }; + + /* Other stair IDs + * Listed in order: north, west, south, east + * Use this for stairs not in the proper sequence + */ + private static readonly int[] m_StairIDs = + { + 0x71F, 0x736, 0x737, 0x749, + 0x35D4, 0x35D3, 0x35D6, 0x35D5, + 0x360B, 0x360A, 0x360D, 0x360C, + 0x4360, 0x435E, 0x435F, 0x4361, + 0x435C, 0x435A, 0x435B, 0x435D, + 0x4364, 0x4362, 0x4363, 0x4365, + 0x4B05, 0x4B04, 0x4B34, 0x4B33, + 0x7809, 0x7808, 0x780A, 0x780B, + 0x7BB, 0x7BC + }; + + private DesignState m_Backup; // State at last user backup. + private DesignState m_Current; // State which is currently visible. + + private int m_DefaultPrice; + private DesignState m_Design; // State of current design. + + public HouseFoundation(Mobile owner, int multiID, int maxLockdowns, int maxSecures) + : base(multiID, owner, maxLockdowns, maxSecures) + { + SignpostGraphic = 9; + + Fixtures = new List(); + + var x = Components.Min.X; + var y = Components.Height - 1 - Components.Center.Y; + + SignHanger = new Static(0xB98); + SignHanger.MoveToWorld(new Point3D(X + x, Y + y, Z + 7), Map); + + CheckSignpost(); + + SetSign(x, y, 7); } - else + + public HouseFoundation(Serial serial) + : base(serial) { - BaseDoor door = null; + } - if (itemID >= 0x675 && itemID < 0x6F5) - { - int type = (itemID - 0x675) / 16; - DoorFacing facing = (DoorFacing)((itemID - 0x675) / 2 % 8); + public FoundationType Type { get; set; } - door = type switch + public int LastRevision { get; set; } + + public List Fixtures { get; private set; } + + public Item SignHanger { get; private set; } + + public Item Signpost { get; private set; } + + public int SignpostGraphic { get; set; } + + public Mobile Customizer { get; set; } + + public override bool IsAosRules => true; + + public override bool IsActive => Customizer == null; + + public virtual int CustomizationCost => Core.AOS ? 0 : 10000; + + public override MultiComponentList Components + { + get { - 0 => new GenericHouseDoor(facing, 0x675, 0xEC, 0xF3), - 1 => new GenericHouseDoor(facing, 0x685, 0xEC, 0xF3), - 2 => new GenericHouseDoor(facing, 0x695, 0xEB, 0xF2), - 3 => new GenericHouseDoor(facing, 0x6A5, 0xEA, 0xF1), - 4 => new GenericHouseDoor(facing, 0x6B5, 0xEA, 0xF1), - 5 => new GenericHouseDoor(facing, 0x6C5, 0xEC, 0xF3), - 6 => new GenericHouseDoor(facing, 0x6D5, 0xEA, 0xF1), - 7 => new GenericHouseDoor(facing, 0x6E5, 0xEA, 0xF1), - _ => door - }; - } - else if (itemID >= 0x314 && itemID < 0x364) - { - int type = (itemID - 0x314) / 16; - DoorFacing facing = (DoorFacing)((itemID - 0x314) / 2 % 8); - door = new GenericHouseDoor(facing, 0x314 + type * 16, 0xED, 0xF4); - } - else if (itemID >= 0x824 && itemID < 0x834) - { - DoorFacing facing = (DoorFacing)((itemID - 0x824) / 2 % 8); - door = new GenericHouseDoor(facing, 0x824, 0xEC, 0xF3); - } - else if (itemID >= 0x839 && itemID < 0x849) - { - DoorFacing facing = (DoorFacing)((itemID - 0x839) / 2 % 8); - door = new GenericHouseDoor(facing, 0x839, 0xEB, 0xF2); - } - else if (itemID >= 0x84C && itemID < 0x85C) - { - DoorFacing facing = (DoorFacing)((itemID - 0x84C) / 2 % 8); - door = new GenericHouseDoor(facing, 0x84C, 0xEC, 0xF3); - } - else if (itemID >= 0x866 && itemID < 0x876) - { - DoorFacing facing = (DoorFacing)((itemID - 0x866) / 2 % 8); - door = new GenericHouseDoor(facing, 0x866, 0xEB, 0xF2); - } - else if (itemID >= 0xE8 && itemID < 0xF8) - { - DoorFacing facing = (DoorFacing)((itemID - 0xE8) / 2 % 8); - door = new GenericHouseDoor(facing, 0xE8, 0xED, 0xF4); - } - else if (itemID >= 0x1FED && itemID < 0x1FFD) - { - DoorFacing facing = (DoorFacing)((itemID - 0x1FED) / 2 % 8); - door = new GenericHouseDoor(facing, 0x1FED, 0xEC, 0xF3); - } - else if (itemID >= 0x241F && itemID < 0x2421) - { - // DoorFacing facing = (DoorFacing)(((itemID - 0x241F) / 2) % 8); - door = new GenericHouseDoor(DoorFacing.NorthCCW, 0x2415, -1, -1); - } - else if (itemID >= 0x2423 && itemID < 0x2425) - { - // DoorFacing facing = (DoorFacing)(((itemID - 0x241F) / 2) % 8); - // This one and the above one are 'special' cases, ie: OSI had the ItemID pattern discombobulated for these - door = new GenericHouseDoor(DoorFacing.WestCW, 0x2423, -1, -1); - } - else if (itemID >= 0x2A05 && itemID < 0x2A1D) - { - DoorFacing facing = (DoorFacing)((itemID - 0x2A05) / 2 % 4 + 8); + if (m_Current == null) + SetInitialState(); - int sound = itemID >= 0x2A0D && itemID < 0x2a15 ? 0x539 : -1; + return m_Current.Components; + } + } - door = new GenericHouseDoor(facing, 0x29F5 + 8 * ((itemID - 0x2A05) / 8), sound, sound); - } - else if (itemID == 0x2D46) - { - door = new GenericHouseDoor(DoorFacing.NorthCW, 0x2D46, 0xEA, 0xF1, false); - } - else if (itemID == 0x2D48 || itemID == 0x2FE2) - { - door = new GenericHouseDoor(DoorFacing.SouthCCW, itemID, 0xEA, 0xF1, false); - } - else if (itemID >= 0x2D63 && itemID < 0x2D70) - { - int mod = (itemID - 0x2D63) / 2 % 2; - DoorFacing facing = mod == 0 ? DoorFacing.SouthCCW : DoorFacing.WestCCW; + public DesignState CurrentState + { + get + { + if (m_Current == null) SetInitialState(); + return m_Current; + } + set => m_Current = value; + } - int type = (itemID - 0x2D63) / 4; + public DesignState DesignState + { + get + { + if (m_Design == null) SetInitialState(); + return m_Design; + } + set => m_Design = value; + } - door = new GenericHouseDoor(facing, 0x2D63 + 4 * type + mod * 2, 0xEA, 0xF1, false); - } - else if (itemID == 0x2FE4 || itemID == 0x31AE) - { - door = new GenericHouseDoor(DoorFacing.WestCCW, itemID, 0xEA, 0xF1, false); - } - else if (itemID >= 0x319C && itemID < 0x31AE) - { - // special case for 0x31aa <-> 0x31a8 (a9) + public DesignState BackupState + { + get + { + if (m_Backup == null) SetInitialState(); + return m_Backup; + } + set => m_Backup = value; + } - int mod = (itemID - 0x319C) / 2 % 2; + public override Rectangle2D[] Area + { + get + { + var mcl = Components; - bool specialCase = itemID == 0x31AA || itemID == 0x31A8; + return new[] { new Rectangle2D(mcl.Min.X, mcl.Min.Y, mcl.Width, mcl.Height) }; + } + } - DoorFacing facing; + public override Point3D BaseBanLocation => + new Point3D(Components.Min.X, Components.Height - 1 - Components.Center.Y, 0); - if (itemID == 0x31AA || itemID == 0x31A8) - facing = mod == 0 ? DoorFacing.NorthCW : DoorFacing.EastCW; + public override int DefaultPrice => m_DefaultPrice; + + public int MaxLevels + { + get + { + var mcl = Components; + + if (mcl.Width >= 14 || mcl.Height >= 14) + return 4; + return 3; + } + } + + public static ComponentVerification Verification => m_Verification ?? (m_Verification = new ComponentVerification()); + + public bool IsFixture(Item item) => Fixtures.Contains(item); + + public override int GetMaxUpdateRange() => 24; + + public override int GetUpdateRange(Mobile m) + { + var w = CurrentState.Components.Width; + var h = CurrentState.Components.Height - 1; + var v = 18 + (w > h ? w : h) / 2; + + if (v > 24) + v = 24; + else if (v < 18) + v = 18; + + return v; + } + + public void SetInitialState() + { + // This is a new house, it has not yet loaded a design state + m_Current = new DesignState(this, GetEmptyFoundation()); + m_Design = new DesignState(m_Current); + m_Backup = new DesignState(m_Current); + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + SignHanger?.Delete(); + + Signpost?.Delete(); + + if (Fixtures == null) + return; + + for (var i = 0; i < Fixtures.Count; ++i) + { + var item = Fixtures[i]; + + item?.Delete(); + } + + Fixtures.Clear(); + } + + public override void OnLocationChange(Point3D oldLocation) + { + base.OnLocationChange(oldLocation); + + var x = Location.X - oldLocation.X; + var y = Location.Y - oldLocation.Y; + var z = Location.Z - oldLocation.Z; + + SignHanger?.MoveToWorld(new Point3D(SignHanger.X + x, SignHanger.Y + y, SignHanger.Z + z), Map); + + Signpost?.MoveToWorld(new Point3D(Signpost.X + x, Signpost.Y + y, Signpost.Z + z), Map); + + if (Fixtures == null) + return; + + for (var i = 0; i < Fixtures.Count; ++i) + { + var item = Fixtures[i]; + + if (item is BaseDoor door && Doors.Contains(door)) + continue; + + item.MoveToWorld(new Point3D(item.X + x, item.Y + y, item.Z + z), Map); + } + } + + public override void OnMapChange() + { + base.OnMapChange(); + + if (SignHanger != null) + SignHanger.Map = Map; + + if (Signpost != null) + Signpost.Map = Map; + + if (Fixtures == null) + return; + + for (var i = 0; i < Fixtures.Count; ++i) + Fixtures[i].Map = Map; + } + + public void ClearFixtures(Mobile from) + { + if (Fixtures == null) + return; + + RemoveKeys(from); + + for (var i = 0; i < Fixtures.Count; ++i) + { + var item = Fixtures[i]; + item.Delete(); + + if (item is BaseDoor door) + Doors.Remove(door); + } + + Fixtures.Clear(); + } + + public void AddFixtures(Mobile from, MultiTileEntry[] list) + { + Fixtures ??= new List(); + + uint keyValue = 0; + + for (var i = 0; i < list.Length; ++i) + { + var mte = list[i]; + int itemID = mte.ItemId; + + if (itemID >= 0x181D && itemID < 0x1829) + { + var tp = new HouseTeleporter(itemID); + + AddFixture(tp, mte); + } + else + { + BaseDoor door = null; + + if (itemID >= 0x675 && itemID < 0x6F5) + { + var type = (itemID - 0x675) / 16; + var facing = (DoorFacing)((itemID - 0x675) / 2 % 8); + + door = type switch + { + 0 => new GenericHouseDoor(facing, 0x675, 0xEC, 0xF3), + 1 => new GenericHouseDoor(facing, 0x685, 0xEC, 0xF3), + 2 => new GenericHouseDoor(facing, 0x695, 0xEB, 0xF2), + 3 => new GenericHouseDoor(facing, 0x6A5, 0xEA, 0xF1), + 4 => new GenericHouseDoor(facing, 0x6B5, 0xEA, 0xF1), + 5 => new GenericHouseDoor(facing, 0x6C5, 0xEC, 0xF3), + 6 => new GenericHouseDoor(facing, 0x6D5, 0xEA, 0xF1), + 7 => new GenericHouseDoor(facing, 0x6E5, 0xEA, 0xF1), + _ => door + }; + } + else if (itemID >= 0x314 && itemID < 0x364) + { + var type = (itemID - 0x314) / 16; + var facing = (DoorFacing)((itemID - 0x314) / 2 % 8); + door = new GenericHouseDoor(facing, 0x314 + type * 16, 0xED, 0xF4); + } + else if (itemID >= 0x824 && itemID < 0x834) + { + var facing = (DoorFacing)((itemID - 0x824) / 2 % 8); + door = new GenericHouseDoor(facing, 0x824, 0xEC, 0xF3); + } + else if (itemID >= 0x839 && itemID < 0x849) + { + var facing = (DoorFacing)((itemID - 0x839) / 2 % 8); + door = new GenericHouseDoor(facing, 0x839, 0xEB, 0xF2); + } + else if (itemID >= 0x84C && itemID < 0x85C) + { + var facing = (DoorFacing)((itemID - 0x84C) / 2 % 8); + door = new GenericHouseDoor(facing, 0x84C, 0xEC, 0xF3); + } + else if (itemID >= 0x866 && itemID < 0x876) + { + var facing = (DoorFacing)((itemID - 0x866) / 2 % 8); + door = new GenericHouseDoor(facing, 0x866, 0xEB, 0xF2); + } + else if (itemID >= 0xE8 && itemID < 0xF8) + { + var facing = (DoorFacing)((itemID - 0xE8) / 2 % 8); + door = new GenericHouseDoor(facing, 0xE8, 0xED, 0xF4); + } + else if (itemID >= 0x1FED && itemID < 0x1FFD) + { + var facing = (DoorFacing)((itemID - 0x1FED) / 2 % 8); + door = new GenericHouseDoor(facing, 0x1FED, 0xEC, 0xF3); + } + else if (itemID >= 0x241F && itemID < 0x2421) + { + // DoorFacing facing = (DoorFacing)(((itemID - 0x241F) / 2) % 8); + door = new GenericHouseDoor(DoorFacing.NorthCCW, 0x2415, -1, -1); + } + else if (itemID >= 0x2423 && itemID < 0x2425) + { + // DoorFacing facing = (DoorFacing)(((itemID - 0x241F) / 2) % 8); + // This one and the above one are 'special' cases, ie: OSI had the ItemID pattern discombobulated for these + door = new GenericHouseDoor(DoorFacing.WestCW, 0x2423, -1, -1); + } + else if (itemID >= 0x2A05 && itemID < 0x2A1D) + { + var facing = (DoorFacing)((itemID - 0x2A05) / 2 % 4 + 8); + + var sound = itemID >= 0x2A0D && itemID < 0x2a15 ? 0x539 : -1; + + door = new GenericHouseDoor(facing, 0x29F5 + 8 * ((itemID - 0x2A05) / 8), sound, sound); + } + else if (itemID == 0x2D46) + { + door = new GenericHouseDoor(DoorFacing.NorthCW, 0x2D46, 0xEA, 0xF1, false); + } + else if (itemID == 0x2D48 || itemID == 0x2FE2) + { + door = new GenericHouseDoor(DoorFacing.SouthCCW, itemID, 0xEA, 0xF1, false); + } + else if (itemID >= 0x2D63 && itemID < 0x2D70) + { + var mod = (itemID - 0x2D63) / 2 % 2; + var facing = mod == 0 ? DoorFacing.SouthCCW : DoorFacing.WestCCW; + + var type = (itemID - 0x2D63) / 4; + + door = new GenericHouseDoor(facing, 0x2D63 + 4 * type + mod * 2, 0xEA, 0xF1, false); + } + else if (itemID == 0x2FE4 || itemID == 0x31AE) + { + door = new GenericHouseDoor(DoorFacing.WestCCW, itemID, 0xEA, 0xF1, false); + } + else if (itemID >= 0x319C && itemID < 0x31AE) + { + // special case for 0x31aa <-> 0x31a8 (a9) + + var mod = (itemID - 0x319C) / 2 % 2; + + var specialCase = itemID == 0x31AA || itemID == 0x31A8; + + DoorFacing facing; + + if (itemID == 0x31AA || itemID == 0x31A8) + facing = mod == 0 ? DoorFacing.NorthCW : DoorFacing.EastCW; + else + facing = mod == 0 ? DoorFacing.EastCW : DoorFacing.NorthCW; + + var type = (itemID - 0x319C) / 4; + + door = new GenericHouseDoor(facing, 0x319C + 4 * type + mod * 2, 0xEA, 0xF1, false); + } + else if (itemID >= 0x367B && itemID < 0x369B) + { + var type = (itemID - 0x367B) / 16; + var facing = (DoorFacing)((itemID - 0x367B) / 2 % 8); + + door = type switch + { + 0 => new GenericHouseDoor(facing, 0x367B, 0xED, 0xF4), + 1 => new GenericHouseDoor(facing, 0x368B, 0xEC, 0x3E7), + _ => door + }; + } + else if (itemID >= 0x409B && itemID < 0x40A3) + { + door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x409B), itemID, 0xEA, 0xF1, false); + } + else if (itemID >= 0x410C && itemID < 0x4114) + { + door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x410C), itemID, 0xEA, 0xF1, false); + } + else if (itemID >= 0x41C2 && itemID < 0x41CA) + { + door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x41C2), itemID, 0xEA, 0xF1, false); + } + else if (itemID >= 0x41CF && itemID < 0x41D7) + { + door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x41CF), itemID, 0xEA, 0xF1, false); + } + else if (itemID >= 0x436E && itemID < 0x437E) + { + /* These ones had to be different... + * Offset 0 2 4 6 8 10 12 14 + * DoorFacing 2 3 2 3 6 7 6 7 + */ + var offset = itemID - 0x436E; + var facing = (DoorFacing)((offset / 2 + 2 * ((1 + offset / 4) % 2)) % 8); + door = new GenericHouseDoor(facing, itemID, 0xEA, 0xF1, false); + } + else if (itemID >= 0x46DD && itemID < 0x46E5) + { + door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x46DD), itemID, 0xEB, 0xF2, false); + } + else if (itemID >= 0x4D22 && itemID < 0x4D2A) + { + door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x4D22), itemID, 0xEA, 0xF1, false); + } + else if (itemID >= 0x50C8 && itemID < 0x50D0) + { + door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x50C8), itemID, 0xEA, 0xF1, false); + } + else if (itemID >= 0x50D0 && itemID < 0x50D8) + { + door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x50D0), itemID, 0xEA, 0xF1, false); + } + else if (itemID >= 0x5142 && itemID < 0x514A) + { + door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x5142), itemID, 0xF0, 0xEF, false); + } + + if (door != null) + { + if (keyValue == 0) + keyValue = CreateKeys(from); + + door.Locked = true; + door.KeyValue = keyValue; + + AddDoor(door, mte.OffsetX, mte.OffsetY, mte.OffsetZ); + Fixtures.Add(door); + } + } + } + + for (var i = 0; i < Fixtures.Count; ++i) + { + var fixture = Fixtures[i]; + + if (fixture is HouseTeleporter tp) + { + for (var j = 1; j <= Fixtures.Count; ++j) + if (Fixtures[(i + j) % Fixtures.Count] is HouseTeleporter check && check.ItemID == tp.ItemID) + { + tp.Target = check; + break; + } + } + else if (fixture is BaseHouseDoor door) + { + if (door.Link != null) + continue; + + DoorFacing linkFacing; + int xOffset, yOffset; + + switch (door.Facing) + { + default: + linkFacing = DoorFacing.EastCCW; + xOffset = 1; + yOffset = 0; + break; + case DoorFacing.EastCCW: + linkFacing = DoorFacing.WestCW; + xOffset = -1; + yOffset = 0; + break; + case DoorFacing.WestCCW: + linkFacing = DoorFacing.EastCW; + xOffset = 1; + yOffset = 0; + break; + case DoorFacing.EastCW: + linkFacing = DoorFacing.WestCCW; + xOffset = -1; + yOffset = 0; + break; + case DoorFacing.SouthCW: + linkFacing = DoorFacing.NorthCCW; + xOffset = 0; + yOffset = -1; + break; + case DoorFacing.NorthCCW: + linkFacing = DoorFacing.SouthCW; + xOffset = 0; + yOffset = 1; + break; + case DoorFacing.SouthCCW: + linkFacing = DoorFacing.NorthCW; + xOffset = 0; + yOffset = -1; + break; + case DoorFacing.NorthCW: + linkFacing = DoorFacing.SouthCCW; + xOffset = 0; + yOffset = 1; + break; + case DoorFacing.SouthSW: + linkFacing = DoorFacing.SouthSE; + xOffset = 1; + yOffset = 0; + break; + case DoorFacing.SouthSE: + linkFacing = DoorFacing.SouthSW; + xOffset = -1; + yOffset = 0; + break; + case DoorFacing.WestSN: + linkFacing = DoorFacing.WestSS; + xOffset = 0; + yOffset = 1; + break; + case DoorFacing.WestSS: + linkFacing = DoorFacing.WestSN; + xOffset = 0; + yOffset = -1; + break; + } + + for (var j = i + 1; j < Fixtures.Count; ++j) + if (Fixtures[j] is BaseHouseDoor check && check.Link == null && check.Facing == linkFacing && + check.X - door.X == xOffset && check.Y - door.Y == yOffset && check.Z == door.Z) + { + check.Link = door; + door.Link = check; + break; + } + } + } + } + + private static DoorFacing GetSADoorFacing(int offset) => (DoorFacing)((offset / 2 + 2 * (1 + offset / 4)) % 8); + + public void AddFixture(Item item, MultiTileEntry mte) + { + Fixtures.Add(item); + item.MoveToWorld(new Point3D(X + mte.OffsetX, Y + mte.OffsetY, Z + mte.OffsetZ), Map); + } + + public static void GetFoundationGraphics( + FoundationType type, out int east, out int south, out int post, + out int corner + ) + { + switch (type) + { + default: + corner = 0x0014; + east = 0x0015; + south = 0x0016; + post = 0x0017; + break; + case FoundationType.LightWood: + corner = 0x00BD; + east = 0x00BE; + south = 0x00BF; + post = 0x00C0; + break; + case FoundationType.Dungeon: + corner = 0x02FD; + east = 0x02FF; + south = 0x02FE; + post = 0x0300; + break; + case FoundationType.Brick: + corner = 0x0041; + east = 0x0043; + south = 0x0042; + post = 0x0044; + break; + case FoundationType.Stone: + corner = 0x0065; + east = 0x0064; + south = 0x0063; + post = 0x0066; + break; + + case FoundationType.ElvenGrey: + corner = 0x2DF7; + east = 0x2DF9; + south = 0x2DFA; + post = 0x2DF8; + break; + case FoundationType.ElvenNatural: + corner = 0x2DFB; + east = 0x2DFD; + south = 0x2DFE; + post = 0x2DFC; + break; + + case FoundationType.Crystal: + corner = 0x3672; + east = 0x3671; + south = 0x3670; + post = 0x3673; + break; + case FoundationType.Shadow: + corner = 0x3676; + east = 0x3675; + south = 0x3674; + post = 0x3677; + break; + } + } + + public static void ApplyFoundation(FoundationType type, MultiComponentList mcl) + { + GetFoundationGraphics(type, out var east, out var south, out var post, out var corner); + + var xCenter = mcl.Center.X; + var yCenter = mcl.Center.Y; + + mcl.Add(post, 0 - xCenter, 0 - yCenter, 0); + mcl.Add(corner, mcl.Width - 1 - xCenter, mcl.Height - 2 - yCenter, 0); + + for (var x = 1; x < mcl.Width; ++x) + { + mcl.Add(south, x - xCenter, 0 - yCenter, 0); + + if (x < mcl.Width - 1) + mcl.Add(south, x - xCenter, mcl.Height - 2 - yCenter, 0); + } + + for (var y = 1; y < mcl.Height - 1; ++y) + { + mcl.Add(east, 0 - xCenter, y - yCenter, 0); + + if (y < mcl.Height - 2) + mcl.Add(east, mcl.Width - 1 - xCenter, y - yCenter, 0); + } + } + + public static void AddStairsTo(ref MultiComponentList mcl) + { + // copy the original.. + mcl = new MultiComponentList(mcl); + + mcl.Resize(mcl.Width, mcl.Height + 1); + + var xCenter = mcl.Center.X; + var yCenter = mcl.Center.Y; + var y = mcl.Height - 1; + + for (var x = 0; x < mcl.Width; ++x) + mcl.Add(0x63, x - xCenter, y - yCenter, 0); + } + + public MultiComponentList GetEmptyFoundation() + { + // Copy original foundation layout + var mcl = new MultiComponentList(MultiData.GetComponents(ItemID)); + + mcl.Resize(mcl.Width, mcl.Height + 1); + + var xCenter = mcl.Center.X; + var yCenter = mcl.Center.Y; + var y = mcl.Height - 1; + + ApplyFoundation(Type, mcl); + + for (var x = 1; x < mcl.Width; ++x) + mcl.Add(0x751, x - xCenter, y - yCenter, 0); + + return mcl; + } + + public void CheckSignpost() + { + var mcl = Components; + + var x = mcl.Min.X; + var y = mcl.Height - 2 - mcl.Center.Y; + + if (CheckWall(mcl, x, y)) + { + Signpost?.Delete(); + + Signpost = null; + } + else if (Signpost == null) + { + Signpost = new Static(SignpostGraphic); + Signpost.MoveToWorld(new Point3D(X + x, Y + y, Z + 7), Map); + } else - facing = mod == 0 ? DoorFacing.EastCW : DoorFacing.NorthCW; - - int type = (itemID - 0x319C) / 4; - - door = new GenericHouseDoor(facing, 0x319C + 4 * type + mod * 2, 0xEA, 0xF1, false); - } - else if (itemID >= 0x367B && itemID < 0x369B) - { - int type = (itemID - 0x367B) / 16; - DoorFacing facing = (DoorFacing)((itemID - 0x367B) / 2 % 8); - - door = type switch { - 0 => new GenericHouseDoor(facing, 0x367B, 0xED, 0xF4), - 1 => new GenericHouseDoor(facing, 0x368B, 0xEC, 0x3E7), - _ => door - }; - } - else if (itemID >= 0x409B && itemID < 0x40A3) - { - door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x409B), itemID, 0xEA, 0xF1, false); - } - else if (itemID >= 0x410C && itemID < 0x4114) - { - door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x410C), itemID, 0xEA, 0xF1, false); - } - else if (itemID >= 0x41C2 && itemID < 0x41CA) - { - door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x41C2), itemID, 0xEA, 0xF1, false); - } - else if (itemID >= 0x41CF && itemID < 0x41D7) - { - door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x41CF), itemID, 0xEA, 0xF1, false); - } - else if (itemID >= 0x436E && itemID < 0x437E) - { - /* These ones had to be different... - * Offset 0 2 4 6 8 10 12 14 - * DoorFacing 2 3 2 3 6 7 6 7 - */ - int offset = itemID - 0x436E; - DoorFacing facing = (DoorFacing)((offset / 2 + 2 * ((1 + offset / 4) % 2)) % 8); - door = new GenericHouseDoor(facing, itemID, 0xEA, 0xF1, false); - } - else if (itemID >= 0x46DD && itemID < 0x46E5) - { - door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x46DD), itemID, 0xEB, 0xF2, false); - } - else if (itemID >= 0x4D22 && itemID < 0x4D2A) - { - door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x4D22), itemID, 0xEA, 0xF1, false); - } - else if (itemID >= 0x50C8 && itemID < 0x50D0) - { - door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x50C8), itemID, 0xEA, 0xF1, false); - } - else if (itemID >= 0x50D0 && itemID < 0x50D8) - { - door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x50D0), itemID, 0xEA, 0xF1, false); - } - else if (itemID >= 0x5142 && itemID < 0x514A) - { - door = new GenericHouseDoor(GetSADoorFacing(itemID - 0x5142), itemID, 0xF0, 0xEF, false); - } - - if (door != null) - { - if (keyValue == 0) - keyValue = CreateKeys(from); - - door.Locked = true; - door.KeyValue = keyValue; - - AddDoor(door, mte.OffsetX, mte.OffsetY, mte.OffsetZ); - Fixtures.Add(door); - } - } - } - - for (int i = 0; i < Fixtures.Count; ++i) - { - Item fixture = Fixtures[i]; - - if (fixture is HouseTeleporter tp) - { - for (int j = 1; j <= Fixtures.Count; ++j) - if (Fixtures[(i + j) % Fixtures.Count] is HouseTeleporter check && check.ItemID == tp.ItemID) - { - tp.Target = check; - break; + Signpost.ItemID = SignpostGraphic; + Signpost.MoveToWorld(new Point3D(X + x, Y + y, Z + 7), Map); } } - else if (fixture is BaseHouseDoor door) + + public bool CheckWall(MultiComponentList mcl, int x, int y) { - if (door.Link != null) - continue; + x += mcl.Center.X; + y += mcl.Center.Y; - DoorFacing linkFacing; - int xOffset, yOffset; - - switch (door.Facing) - { - default: - linkFacing = DoorFacing.EastCCW; - xOffset = 1; - yOffset = 0; - break; - case DoorFacing.EastCCW: - linkFacing = DoorFacing.WestCW; - xOffset = -1; - yOffset = 0; - break; - case DoorFacing.WestCCW: - linkFacing = DoorFacing.EastCW; - xOffset = 1; - yOffset = 0; - break; - case DoorFacing.EastCW: - linkFacing = DoorFacing.WestCCW; - xOffset = -1; - yOffset = 0; - break; - case DoorFacing.SouthCW: - linkFacing = DoorFacing.NorthCCW; - xOffset = 0; - yOffset = -1; - break; - case DoorFacing.NorthCCW: - linkFacing = DoorFacing.SouthCW; - xOffset = 0; - yOffset = 1; - break; - case DoorFacing.SouthCCW: - linkFacing = DoorFacing.NorthCW; - xOffset = 0; - yOffset = -1; - break; - case DoorFacing.NorthCW: - linkFacing = DoorFacing.SouthCCW; - xOffset = 0; - yOffset = 1; - break; - case DoorFacing.SouthSW: - linkFacing = DoorFacing.SouthSE; - xOffset = 1; - yOffset = 0; - break; - case DoorFacing.SouthSE: - linkFacing = DoorFacing.SouthSW; - xOffset = -1; - yOffset = 0; - break; - case DoorFacing.WestSN: - linkFacing = DoorFacing.WestSS; - xOffset = 0; - yOffset = 1; - break; - case DoorFacing.WestSS: - linkFacing = DoorFacing.WestSN; - xOffset = 0; - yOffset = -1; - break; - } - - for (int j = i + 1; j < Fixtures.Count; ++j) - if (Fixtures[j] is BaseHouseDoor check && check.Link == null && check.Facing == linkFacing && - check.X - door.X == xOffset && check.Y - door.Y == yOffset && check.Z == door.Z) + if (x >= 0 && x < mcl.Width && y >= 0 && y < mcl.Height) { - check.Link = door; - door.Link = check; - break; + var tiles = mcl.Tiles[x][y]; + + for (var i = 0; i < tiles.Length; ++i) + { + var tile = tiles[i]; + + if (tile.Z == 7 && tile.Height == 20) + return true; + } + } + + return false; + } + + public void BeginCustomize(Mobile m) + { + if (!m.CheckAlive()) + return; + + if (SpellHelper.CheckCombat(m)) + { + m.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle?? + return; + } + + RelocateEntities(); + + foreach (var item in GetItems()) item.Location = BanLocation; + + foreach (var mobile in GetMobiles()) + if (mobile != m) + mobile.Location = BanLocation; + + DesignContext.Add(m, this); + m.Send(new BeginHouseCustomization(this)); + + var ns = m.NetState; + if (ns != null) + SendInfoTo(ns); + + DesignState.SendDetailedInfoTo(ns); + } + + public override void SendInfoTo(NetState state, bool sendOplPacket) + { + base.SendInfoTo(state, sendOplPacket); + + var stateToSend = DesignContext.Find(state.Mobile)?.Foundation == this ? DesignState : CurrentState; + stateToSend.SendGeneralInfoTo(state); + } + + public override void Serialize(IGenericWriter writer) + { + writer.Write(5); // version + + writer.Write(Signpost); + writer.Write(SignpostGraphic); + + writer.Write((int)Type); + + writer.Write(SignHanger); + + writer.Write(LastRevision); + writer.Write(Fixtures, true); + + CurrentState.Serialize(writer); + DesignState.Serialize(writer); + BackupState.Serialize(writer); + + base.Serialize(writer); + } + + public override void Deserialize(IGenericReader reader) + { + var version = reader.ReadInt(); + + switch (version) + { + case 5: + case 4: + { + Signpost = reader.ReadItem(); + SignpostGraphic = reader.ReadInt(); + + goto case 3; + } + case 3: + { + Type = (FoundationType)reader.ReadInt(); + + goto case 2; + } + case 2: + { + SignHanger = reader.ReadItem(); + + goto case 1; + } + case 1: + { + if (version < 5) + m_DefaultPrice = reader.ReadInt(); + + goto case 0; + } + case 0: + { + if (version < 3) + Type = FoundationType.Stone; + + if (version < 4) + SignpostGraphic = 9; + + LastRevision = reader.ReadInt(); + Fixtures = reader.ReadStrongItemList(); + + m_Current = new DesignState(this, reader); + m_Design = new DesignState(this, reader); + m_Backup = new DesignState(this, reader); + + break; + } + } + + base.Deserialize(reader); + } + + public bool IsHiddenToCustomizer(Item item) => + item == Signpost || item == SignHanger || item == Sign || IsFixture(item); + + public static void Initialize() + { + PacketHandlers.RegisterExtended(0x1E, true, QueryDesignDetails); + + PacketHandlers.RegisterEncoded(0x02, true, Designer_Backup); + PacketHandlers.RegisterEncoded(0x03, true, Designer_Restore); + PacketHandlers.RegisterEncoded(0x04, true, Designer_Commit); + PacketHandlers.RegisterEncoded(0x05, true, Designer_Delete); + PacketHandlers.RegisterEncoded(0x06, true, Designer_Build); + PacketHandlers.RegisterEncoded(0x0C, true, Designer_Close); + PacketHandlers.RegisterEncoded(0x0D, true, Designer_Stairs); + PacketHandlers.RegisterEncoded(0x0E, true, Designer_Sync); + PacketHandlers.RegisterEncoded(0x10, true, Designer_Clear); + PacketHandlers.RegisterEncoded(0x12, true, Designer_Level); + + PacketHandlers.RegisterEncoded(0x13, true, Designer_Roof); // Samurai Empire roof + PacketHandlers.RegisterEncoded(0x14, true, Designer_RoofDelete); // Samurai Empire roof + + PacketHandlers.RegisterEncoded(0x1A, true, Designer_Revert); + + EventSink.Speech += EventSink_Speech; + } + + private static void EventSink_Speech(SpeechEventArgs e) + { + if (DesignContext.Find(e.Mobile) != null) + { + e.Mobile.SendLocalizedMessage(1061925); // You cannot speak while customizing your house. + e.Blocked = true; } } - } - } - private static DoorFacing GetSADoorFacing(int offset) => (DoorFacing)((offset / 2 + 2 * (1 + offset / 4)) % 8); - - public void AddFixture(Item item, MultiTileEntry mte) - { - Fixtures.Add(item); - item.MoveToWorld(new Point3D(X + mte.OffsetX, Y + mte.OffsetY, Z + mte.OffsetZ), Map); - } - - public static void GetFoundationGraphics(FoundationType type, out int east, out int south, out int post, - out int corner) - { - switch (type) - { - default: - corner = 0x0014; - east = 0x0015; - south = 0x0016; - post = 0x0017; - break; - case FoundationType.LightWood: - corner = 0x00BD; - east = 0x00BE; - south = 0x00BF; - post = 0x00C0; - break; - case FoundationType.Dungeon: - corner = 0x02FD; - east = 0x02FF; - south = 0x02FE; - post = 0x0300; - break; - case FoundationType.Brick: - corner = 0x0041; - east = 0x0043; - south = 0x0042; - post = 0x0044; - break; - case FoundationType.Stone: - corner = 0x0065; - east = 0x0064; - south = 0x0063; - post = 0x0066; - break; - - case FoundationType.ElvenGrey: - corner = 0x2DF7; - east = 0x2DF9; - south = 0x2DFA; - post = 0x2DF8; - break; - case FoundationType.ElvenNatural: - corner = 0x2DFB; - east = 0x2DFD; - south = 0x2DFE; - post = 0x2DFC; - break; - - case FoundationType.Crystal: - corner = 0x3672; - east = 0x3671; - south = 0x3670; - post = 0x3673; - break; - case FoundationType.Shadow: - corner = 0x3676; - east = 0x3675; - south = 0x3674; - post = 0x3677; - break; - } - } - - public static void ApplyFoundation(FoundationType type, MultiComponentList mcl) - { - GetFoundationGraphics(type, out int east, out int south, out int post, out int corner); - - int xCenter = mcl.Center.X; - int yCenter = mcl.Center.Y; - - mcl.Add(post, 0 - xCenter, 0 - yCenter, 0); - mcl.Add(corner, mcl.Width - 1 - xCenter, mcl.Height - 2 - yCenter, 0); - - for (int x = 1; x < mcl.Width; ++x) - { - mcl.Add(south, x - xCenter, 0 - yCenter, 0); - - if (x < mcl.Width - 1) - mcl.Add(south, x - xCenter, mcl.Height - 2 - yCenter, 0); - } - - for (int y = 1; y < mcl.Height - 1; ++y) - { - mcl.Add(east, 0 - xCenter, y - yCenter, 0); - - if (y < mcl.Height - 2) - mcl.Add(east, mcl.Width - 1 - xCenter, y - yCenter, 0); - } - } - - public static void AddStairsTo(ref MultiComponentList mcl) - { - // copy the original.. - mcl = new MultiComponentList(mcl); - - mcl.Resize(mcl.Width, mcl.Height + 1); - - int xCenter = mcl.Center.X; - int yCenter = mcl.Center.Y; - int y = mcl.Height - 1; - - for (int x = 0; x < mcl.Width; ++x) - mcl.Add(0x63, x - xCenter, y - yCenter, 0); - } - - public MultiComponentList GetEmptyFoundation() - { - // Copy original foundation layout - MultiComponentList mcl = new MultiComponentList(MultiData.GetComponents(ItemID)); - - mcl.Resize(mcl.Width, mcl.Height + 1); - - int xCenter = mcl.Center.X; - int yCenter = mcl.Center.Y; - int y = mcl.Height - 1; - - ApplyFoundation(Type, mcl); - - for (int x = 1; x < mcl.Width; ++x) - mcl.Add(0x751, x - xCenter, y - yCenter, 0); - - return mcl; - } - - public void CheckSignpost() - { - MultiComponentList mcl = Components; - - int x = mcl.Min.X; - int y = mcl.Height - 2 - mcl.Center.Y; - - if (CheckWall(mcl, x, y)) - { - Signpost?.Delete(); - - Signpost = null; - } - else if (Signpost == null) - { - Signpost = new Static(SignpostGraphic); - Signpost.MoveToWorld(new Point3D(X + x, Y + y, Z + 7), Map); - } - else - { - Signpost.ItemID = SignpostGraphic; - Signpost.MoveToWorld(new Point3D(X + x, Y + y, Z + 7), Map); - } - } - - public bool CheckWall(MultiComponentList mcl, int x, int y) - { - x += mcl.Center.X; - y += mcl.Center.Y; - - if (x >= 0 && x < mcl.Width && y >= 0 && y < mcl.Height) - { - StaticTile[] tiles = mcl.Tiles[x][y]; - - for (int i = 0; i < tiles.Length; ++i) + public static void Designer_Sync(NetState state, IEntity e, EncodedReader pvSrc) { - StaticTile tile = tiles[i]; + var from = state.Mobile; + + /* Client requested state synchronization + * - Resend full house state + */ + + // Resend full house state + DesignContext.Find(from)?.Foundation.DesignState.SendDetailedInfoTo(state); + } + + public static void Designer_Clear(NetState state, IEntity e, EncodedReader pvSrc) + { + var from = state.Mobile; + var context = DesignContext.Find(from); + + if (context == null) + return; + + /* Client chose to clear the design + * - Restore empty foundation + * - Construct new design state from empty foundation + * - Assign constructed state to foundation + * - Update revision + * - Update client with new state + */ + + // Restore empty foundation : Construct new design state from empty foundation + var newDesign = new DesignState(context.Foundation, context.Foundation.GetEmptyFoundation()); + + // Restore empty foundation : Assign constructed state to foundation + context.Foundation.DesignState = newDesign; + + // Update revision + newDesign.OnRevised(); + + // Update client with new state + context.Foundation.SendInfoTo(state); + newDesign.SendDetailedInfoTo(state); + } + + public static void Designer_Restore(NetState state, IEntity e, EncodedReader pvSrc) + { + var from = state.Mobile; + var context = DesignContext.Find(from); + + if (context == null) + return; + + /* Client chose to restore design to the last backup state + * - Restore backup + * - Construct new design state from backup state + * - Assign constructed state to foundation + * - Update revision + * - Update client with new state + */ + + // Restore backup : Construct new design state from backup state + var backupDesign = new DesignState(context.Foundation.BackupState); + + // Restore backup : Assign constructed state to foundation + context.Foundation.DesignState = backupDesign; + + // Update revision; + backupDesign.OnRevised(); + + // Update client with new state + context.Foundation.SendInfoTo(state); + backupDesign.SendDetailedInfoTo(state); + } + + public static void Designer_Backup(NetState state, IEntity e, EncodedReader pvSrc) + { + var from = state.Mobile; + var context = DesignContext.Find(from); + + if (context == null) + return; + + /* Client chose to backup design state + * - Construct a copy of the current design state + * - Assign constructed state to backup state field + */ + + // Construct a copy of the current design state + var copyState = new DesignState(context.Foundation.DesignState); + + // Assign constructed state to backup state field + context.Foundation.BackupState = copyState; + } + + public static void Designer_Revert(NetState state, IEntity e, EncodedReader pvSrc) + { + var from = state.Mobile; + var context = DesignContext.Find(from); + + if (context == null) + return; + + /* Client chose to revert design state to currently visible state + * - Revert design state + * - Construct a copy of the current visible state + * - Freeze fixtures in constructed state + * - Assign constructed state to foundation + * - If a signpost is needed, add it + * - Update revision + * - Update client with new state + */ + + // Revert design state : Construct a copy of the current visible state + var copyState = new DesignState(context.Foundation.CurrentState); + + // Revert design state : Freeze fixtures in constructed state + copyState.FreezeFixtures(); + + // Revert design state : Assign constructed state to foundation + context.Foundation.DesignState = copyState; + + // Revert design state : If a signpost is needed, add it + context.Foundation.CheckSignpost(); + + // Update revision + copyState.OnRevised(); + + // Update client with new state + context.Foundation.SendInfoTo(state); + copyState.SendDetailedInfoTo(state); + } + + public void EndConfirmCommit(Mobile from) + { + var oldPrice = Price; + var newPrice = oldPrice + CustomizationCost + + (DesignState.Components.List.Length - + (CurrentState.Components.List.Length + CurrentState.Fixtures.Length)) * 500; + var cost = newPrice - oldPrice; + + if (!Deleted) + { + // Temporary Fix. We should be booting a client out of customization mode in the delete handler. + if (from.AccessLevel >= AccessLevel.GameMaster && cost != 0) + { + from.SendMessage( + "{0} gold would have been {1} your bank if you were not a GM.", + cost.ToString(), + cost > 0 ? "withdrawn from" : "deposited into" + ); + } + else + { + if (cost > 0) + { + if (Banker.Withdraw(from, cost)) + { + from.SendLocalizedMessage( + 1060398, + cost.ToString() + ); // ~1_AMOUNT~ gold has been withdrawn from your bank box. + } + else + { + from.SendLocalizedMessage( + 1061903 + ); // You cannot commit this house design, because you do not have the necessary funds in your bank box to pay for the upgrade. Please back up your design, obtain the required funds, and commit your design again. + return; + } + } + else if (cost < 0) + { + if (Banker.Deposit(from, -cost)) + from.SendLocalizedMessage( + 1060397, + (-cost).ToString() + ); // ~1_AMOUNT~ gold has been deposited into your bank box. + else + return; + } + } + } + + /* Client chose to commit current design state + * - Commit design state + * - Construct a copy of the current design state + * - Clear visible fixtures + * - Melt fixtures from constructed state + * - Add melted fixtures from constructed state + * - Assign constructed state to foundation + * - Update house price + * - Remove design context + * - Notify the client that customization has ended + * - Notify the core that the foundation has changed and should be resent to all clients + * - If a signpost is needed, add it + * - Eject all from house + * - Restore relocated entities + */ + + // Commit design state : Construct a copy of the current design state + var copyState = new DesignState(DesignState); + + // Commit design state : Clear visible fixtures + ClearFixtures(from); + + // Commit design state : Melt fixtures from constructed state + copyState.MeltFixtures(); + + // Commit design state : Add melted fixtures from constructed state + AddFixtures(from, copyState.Fixtures); + + // Commit design state : Assign constructed state to foundation + CurrentState = copyState; + + // Update house price + Price = newPrice - CustomizationCost; + + // Remove design context + DesignContext.Remove(from); + + // Notify the client that customization has ended + from.Send(new EndHouseCustomization(this)); + + // Notify the core that the foundation has changed and should be resent to all clients + Delta(ItemDelta.Update); + ProcessDelta(); + CurrentState.SendDetailedInfoTo(from.NetState); + + // If a signpost is needed, add it + CheckSignpost(); + + // Eject all from house + from.RevealingAction(); + + foreach (var item in GetItems()) + item.Location = BanLocation; + + foreach (var mobile in GetMobiles()) + mobile.Location = BanLocation; + + // Restore relocated entities + RestoreRelocatedEntities(); + } + + public static void Designer_Commit(NetState state, IEntity e, EncodedReader pvSrc) + { + var from = state.Mobile; + var context = DesignContext.Find(from); + + if (context != null) + { + var oldPrice = context.Foundation.Price; + var newPrice = oldPrice + context.Foundation.CustomizationCost + + (context.Foundation.DesignState.Components.List.Length - + (context.Foundation.CurrentState.Components.List.Length + + context.Foundation.Fixtures.Count)) * 500; + var bankBalance = Banker.GetBalance(from); + + from.SendGump(new ConfirmCommitGump(from, context.Foundation, bankBalance, oldPrice, newPrice)); + } + } + + public static int GetLevelZ(int level, HouseFoundation house) + { + if (level < 1 || level > house.MaxLevels) + level = 1; + + return (level - 1) * 20 + 7; + } + + public static int GetZLevel(int z, HouseFoundation house) + { + var level = (z - 7) / 20 + 1; + + if (level < 1 || level > house.MaxLevels) + level = 1; + + return level; + } + + public static bool ValidPiece(int itemID, bool roof = false) + { + itemID &= TileData.MaxItemValue; + return roof != ((TileData.ItemTable[itemID].Flags & TileFlag.Roof) == 0) && Verification.IsItemValid(itemID); + } + + public static bool IsStairBlock(int id) + { + var delta = -1; + + for (var i = 0; delta < 0 && i < m_BlockIDs.Length; ++i) + delta = m_BlockIDs[i] - id; + + return delta == 0; + } + + public static bool IsStair(int id, ref int dir) + { + // dir n=0 w=1 s=2 e=3 + var delta = -4; + + for (var i = 0; delta < -3 && i < m_StairSeqs.Length; ++i) + delta = m_StairSeqs[i] - id; + + if (delta >= -3 && delta <= 0) + { + dir = -delta; + return true; + } + + for (var i = 0; i < m_StairIDs.Length; ++i) + if (m_StairIDs[i] == id) + { + dir = i % 4; + return true; + } + + return false; + } + + public static bool DeleteStairs(MultiComponentList mcl, int id, int x, int y, int z) + { + var ax = x + mcl.Center.X; + var ay = y + mcl.Center.Y; + + if (ax < 0 || ay < 0 || ax >= mcl.Width || ay >= mcl.Height - 1 || z < 7 || (z - 7) % 5 != 0) + return false; + + if (IsStairBlock(id)) + { + var tiles = mcl.Tiles[ax][ay]; + + for (var i = 0; i < tiles.Length; ++i) + { + var tile = tiles[i]; + + if (tile.Z == z + 5) + { + id = tile.ID; + z = tile.Z; + + if (!IsStairBlock(id)) + break; + } + } + } + + var dir = 0; + + if (!IsStair(id, ref dir)) + return false; + + if (AllowStairSectioning) + return true; // skip deletion + + var height = (z - 7) % 20 / 5; + + int xStart, yStart; + int xInc, yInc; + + switch (dir) + { + default: + { + xStart = x; + yStart = y + height; + xInc = 0; + yInc = -1; + break; + } + case 1: // West + { + xStart = x + height; + yStart = y; + xInc = -1; + yInc = 0; + break; + } + case 2: // South + { + xStart = x; + yStart = y - height; + xInc = 0; + yInc = 1; + break; + } + case 3: // East + { + xStart = x - height; + yStart = y; + xInc = 1; + yInc = 0; + break; + } + } + + var zStart = z - height * 5; + + for (var i = 0; i < 4; ++i) + { + x = xStart + i * xInc; + y = yStart + i * yInc; + + for (var j = 0; j <= i; ++j) + mcl.RemoveXYZH(x, y, zStart + j * 5, 5); + + ax = x + mcl.Center.X; + ay = y + mcl.Center.Y; + + if (ax >= 1 && ax < mcl.Width && ay >= 1 && ay < mcl.Height - 1) + { + var tiles = mcl.Tiles[ax][ay]; + + var hasBaseFloor = false; + + for (var j = 0; !hasBaseFloor && j < tiles.Length; ++j) + hasBaseFloor = tiles[j].Z == 7 && tiles[j].ID != 1; + + if (!hasBaseFloor) + mcl.Add(0x31F4, x, y, 7); + } + } - if (tile.Z == 7 && tile.Height == 20) return true; } - } - return false; - } - - public void BeginCustomize(Mobile m) - { - if (!m.CheckAlive()) - return; - - if (SpellHelper.CheckCombat(m)) - { - m.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle?? - return; - } - - RelocateEntities(); - - foreach (Item item in GetItems()) item.Location = BanLocation; - - foreach (Mobile mobile in GetMobiles()) - if (mobile != m) - mobile.Location = BanLocation; - - DesignContext.Add(m, this); - m.Send(new BeginHouseCustomization(this)); - - NetState ns = m.NetState; - if (ns != null) - SendInfoTo(ns); - - DesignState.SendDetailedInfoTo(ns); - } - - public override void SendInfoTo(NetState state, bool sendOplPacket) - { - base.SendInfoTo(state, sendOplPacket); - - DesignState stateToSend = DesignContext.Find(state.Mobile)?.Foundation == this ? DesignState : CurrentState; - stateToSend.SendGeneralInfoTo(state); - } - - public override void Serialize(IGenericWriter writer) - { - writer.Write(5); // version - - writer.Write(Signpost); - writer.Write(SignpostGraphic); - - writer.Write((int)Type); - - writer.Write(SignHanger); - - writer.Write(LastRevision); - writer.Write(Fixtures, true); - - CurrentState.Serialize(writer); - DesignState.Serialize(writer); - BackupState.Serialize(writer); - - base.Serialize(writer); - } - - public override void Deserialize(IGenericReader reader) - { - int version = reader.ReadInt(); - - switch (version) - { - case 5: - case 4: - { - Signpost = reader.ReadItem(); - SignpostGraphic = reader.ReadInt(); - - goto case 3; - } - case 3: - { - Type = (FoundationType)reader.ReadInt(); - - goto case 2; - } - case 2: - { - SignHanger = reader.ReadItem(); - - goto case 1; - } - case 1: - { - if (version < 5) - m_DefaultPrice = reader.ReadInt(); - - goto case 0; - } - case 0: - { - if (version < 3) - Type = FoundationType.Stone; - - if (version < 4) - SignpostGraphic = 9; - - LastRevision = reader.ReadInt(); - Fixtures = reader.ReadStrongItemList(); - - m_Current = new DesignState(this, reader); - m_Design = new DesignState(this, reader); - m_Backup = new DesignState(this, reader); - - break; - } - } - - base.Deserialize(reader); - } - - public bool IsHiddenToCustomizer(Item item) => item == Signpost || item == SignHanger || item == Sign || IsFixture(item); - - public static void Initialize() - { - PacketHandlers.RegisterExtended(0x1E, true, QueryDesignDetails); - - PacketHandlers.RegisterEncoded(0x02, true, Designer_Backup); - PacketHandlers.RegisterEncoded(0x03, true, Designer_Restore); - PacketHandlers.RegisterEncoded(0x04, true, Designer_Commit); - PacketHandlers.RegisterEncoded(0x05, true, Designer_Delete); - PacketHandlers.RegisterEncoded(0x06, true, Designer_Build); - PacketHandlers.RegisterEncoded(0x0C, true, Designer_Close); - PacketHandlers.RegisterEncoded(0x0D, true, Designer_Stairs); - PacketHandlers.RegisterEncoded(0x0E, true, Designer_Sync); - PacketHandlers.RegisterEncoded(0x10, true, Designer_Clear); - PacketHandlers.RegisterEncoded(0x12, true, Designer_Level); - - PacketHandlers.RegisterEncoded(0x13, true, Designer_Roof); // Samurai Empire roof - PacketHandlers.RegisterEncoded(0x14, true, Designer_RoofDelete); // Samurai Empire roof - - PacketHandlers.RegisterEncoded(0x1A, true, Designer_Revert); - - EventSink.Speech += EventSink_Speech; - } - - private static void EventSink_Speech(SpeechEventArgs e) - { - if (DesignContext.Find(e.Mobile) != null) - { - e.Mobile.SendLocalizedMessage(1061925); // You cannot speak while customizing your house. - e.Blocked = true; - } - } - - public static void Designer_Sync(NetState state, IEntity e, EncodedReader pvSrc) - { - Mobile from = state.Mobile; - - /* Client requested state synchronization - * - Resend full house state - */ - - // Resend full house state - DesignContext.Find(from)?.Foundation.DesignState.SendDetailedInfoTo(state); - } - - public static void Designer_Clear(NetState state, IEntity e, EncodedReader pvSrc) - { - Mobile from = state.Mobile; - DesignContext context = DesignContext.Find(from); - - if (context == null) - return; - - /* Client chose to clear the design - * - Restore empty foundation - * - Construct new design state from empty foundation - * - Assign constructed state to foundation - * - Update revision - * - Update client with new state - */ - - // Restore empty foundation : Construct new design state from empty foundation - DesignState newDesign = new DesignState(context.Foundation, context.Foundation.GetEmptyFoundation()); - - // Restore empty foundation : Assign constructed state to foundation - context.Foundation.DesignState = newDesign; - - // Update revision - newDesign.OnRevised(); - - // Update client with new state - context.Foundation.SendInfoTo(state); - newDesign.SendDetailedInfoTo(state); - } - - public static void Designer_Restore(NetState state, IEntity e, EncodedReader pvSrc) - { - Mobile from = state.Mobile; - DesignContext context = DesignContext.Find(from); - - if (context == null) - return; - - /* Client chose to restore design to the last backup state - * - Restore backup - * - Construct new design state from backup state - * - Assign constructed state to foundation - * - Update revision - * - Update client with new state - */ - - // Restore backup : Construct new design state from backup state - DesignState backupDesign = new DesignState(context.Foundation.BackupState); - - // Restore backup : Assign constructed state to foundation - context.Foundation.DesignState = backupDesign; - - // Update revision; - backupDesign.OnRevised(); - - // Update client with new state - context.Foundation.SendInfoTo(state); - backupDesign.SendDetailedInfoTo(state); - } - - public static void Designer_Backup(NetState state, IEntity e, EncodedReader pvSrc) - { - Mobile from = state.Mobile; - DesignContext context = DesignContext.Find(from); - - if (context == null) - return; - - /* Client chose to backup design state - * - Construct a copy of the current design state - * - Assign constructed state to backup state field - */ - - // Construct a copy of the current design state - DesignState copyState = new DesignState(context.Foundation.DesignState); - - // Assign constructed state to backup state field - context.Foundation.BackupState = copyState; - } - - public static void Designer_Revert(NetState state, IEntity e, EncodedReader pvSrc) - { - Mobile from = state.Mobile; - DesignContext context = DesignContext.Find(from); - - if (context == null) - return; - - /* Client chose to revert design state to currently visible state - * - Revert design state - * - Construct a copy of the current visible state - * - Freeze fixtures in constructed state - * - Assign constructed state to foundation - * - If a signpost is needed, add it - * - Update revision - * - Update client with new state - */ - - // Revert design state : Construct a copy of the current visible state - DesignState copyState = new DesignState(context.Foundation.CurrentState); - - // Revert design state : Freeze fixtures in constructed state - copyState.FreezeFixtures(); - - // Revert design state : Assign constructed state to foundation - context.Foundation.DesignState = copyState; - - // Revert design state : If a signpost is needed, add it - context.Foundation.CheckSignpost(); - - // Update revision - copyState.OnRevised(); - - // Update client with new state - context.Foundation.SendInfoTo(state); - copyState.SendDetailedInfoTo(state); - } - - public void EndConfirmCommit(Mobile from) - { - int oldPrice = Price; - int newPrice = oldPrice + CustomizationCost + - (DesignState.Components.List.Length - - (CurrentState.Components.List.Length + CurrentState.Fixtures.Length)) * 500; - int cost = newPrice - oldPrice; - - if (!Deleted) - { - // Temporary Fix. We should be booting a client out of customization mode in the delete handler. - if (from.AccessLevel >= AccessLevel.GameMaster && cost != 0) + public static void Designer_Delete(NetState state, IEntity e, EncodedReader pvSrc) { - from.SendMessage("{0} gold would have been {1} your bank if you were not a GM.", cost.ToString(), - cost > 0 ? "withdrawn from" : "deposited into"); - } - else - { - if (cost > 0) - { - if (Banker.Withdraw(from, cost)) + var from = state.Mobile; + var context = DesignContext.Find(from); + + if (context == null) + return; + + /* Client chose to delete a component + * - Read data detailing which component to delete + * - Verify component is deletable + * - Remove the component + * - If needed, replace removed component with a dirt tile + * - Update revision + */ + + // Read data detailing which component to delete + var itemID = pvSrc.ReadInt32(); + var x = pvSrc.ReadInt32(); + var y = pvSrc.ReadInt32(); + var z = pvSrc.ReadInt32(); + + // Verify component is deletable + var design = context.Foundation.DesignState; + var mcl = design.Components; + + var ax = x + mcl.Center.X; + var ay = y + mcl.Center.Y; + + if (z == 0 && ax >= 0 && ax < mcl.Width && ay >= 0 && ay < mcl.Height - 1) { - from.SendLocalizedMessage(1060398, - cost.ToString()); // ~1_AMOUNT~ gold has been withdrawn from your bank box. + /* Component is not deletable + * - Resend design state + * - Return without further processing + */ + + design.SendDetailedInfoTo(state); + return; + } + + var fixState = false; + + // Remove the component + if (AllowStairSectioning) + { + if (DeleteStairs(mcl, itemID, x, y, z)) + fixState = true; // The client removes the entire set of stairs locally, resend state + + mcl.Remove(itemID, x, y, z); } else { - from.SendLocalizedMessage( - 1061903); // You cannot commit this house design, because you do not have the necessary funds in your bank box to pay for the upgrade. Please back up your design, obtain the required funds, and commit your design again. - return; + if (!DeleteStairs(mcl, itemID, x, y, z)) + mcl.Remove(itemID, x, y, z); } - } - else if (cost < 0) - { - if (Banker.Deposit(from, -cost)) - from.SendLocalizedMessage(1060397, - (-cost).ToString()); // ~1_AMOUNT~ gold has been deposited into your bank box. - else - return; - } - } - } - /* Client chose to commit current design state - * - Commit design state - * - Construct a copy of the current design state - * - Clear visible fixtures - * - Melt fixtures from constructed state - * - Add melted fixtures from constructed state - * - Assign constructed state to foundation - * - Update house price - * - Remove design context - * - Notify the client that customization has ended - * - Notify the core that the foundation has changed and should be resent to all clients - * - If a signpost is needed, add it - * - Eject all from house - * - Restore relocated entities - */ - - // Commit design state : Construct a copy of the current design state - DesignState copyState = new DesignState(DesignState); - - // Commit design state : Clear visible fixtures - ClearFixtures(from); - - // Commit design state : Melt fixtures from constructed state - copyState.MeltFixtures(); - - // Commit design state : Add melted fixtures from constructed state - AddFixtures(from, copyState.Fixtures); - - // Commit design state : Assign constructed state to foundation - CurrentState = copyState; - - // Update house price - Price = newPrice - CustomizationCost; - - // Remove design context - DesignContext.Remove(from); - - // Notify the client that customization has ended - from.Send(new EndHouseCustomization(this)); - - // Notify the core that the foundation has changed and should be resent to all clients - Delta(ItemDelta.Update); - ProcessDelta(); - CurrentState.SendDetailedInfoTo(from.NetState); - - // If a signpost is needed, add it - CheckSignpost(); - - // Eject all from house - from.RevealingAction(); - - foreach (Item item in GetItems()) - item.Location = BanLocation; - - foreach (Mobile mobile in GetMobiles()) - mobile.Location = BanLocation; - - // Restore relocated entities - RestoreRelocatedEntities(); - } - - public static void Designer_Commit(NetState state, IEntity e, EncodedReader pvSrc) - { - Mobile from = state.Mobile; - DesignContext context = DesignContext.Find(from); - - if (context != null) - { - int oldPrice = context.Foundation.Price; - int newPrice = oldPrice + context.Foundation.CustomizationCost + - (context.Foundation.DesignState.Components.List.Length - - (context.Foundation.CurrentState.Components.List.Length + - context.Foundation.Fixtures.Count)) * 500; - int bankBalance = Banker.GetBalance(from); - - from.SendGump(new ConfirmCommitGump(from, context.Foundation, bankBalance, oldPrice, newPrice)); - } - } - - public static int GetLevelZ(int level, HouseFoundation house) - { - if (level < 1 || level > house.MaxLevels) - level = 1; - - return (level - 1) * 20 + 7; - } - - public static int GetZLevel(int z, HouseFoundation house) - { - int level = (z - 7) / 20 + 1; - - if (level < 1 || level > house.MaxLevels) - level = 1; - - return level; - } - - public static bool ValidPiece(int itemID, bool roof = false) - { - itemID &= TileData.MaxItemValue; - return roof != ((TileData.ItemTable[itemID].Flags & TileFlag.Roof) == 0) && Verification.IsItemValid(itemID); - } - - public static bool IsStairBlock(int id) - { - int delta = -1; - - for (int i = 0; delta < 0 && i < m_BlockIDs.Length; ++i) - delta = m_BlockIDs[i] - id; - - return delta == 0; - } - - public static bool IsStair(int id, ref int dir) - { - // dir n=0 w=1 s=2 e=3 - int delta = -4; - - for (int i = 0; delta < -3 && i < m_StairSeqs.Length; ++i) - delta = m_StairSeqs[i] - id; - - if (delta >= -3 && delta <= 0) - { - dir = -delta; - return true; - } - - for (int i = 0; i < m_StairIDs.Length; ++i) - if (m_StairIDs[i] == id) - { - dir = i % 4; - return true; - } - - return false; - } - - public static bool DeleteStairs(MultiComponentList mcl, int id, int x, int y, int z) - { - int ax = x + mcl.Center.X; - int ay = y + mcl.Center.Y; - - if (ax < 0 || ay < 0 || ax >= mcl.Width || ay >= mcl.Height - 1 || z < 7 || (z - 7) % 5 != 0) - return false; - - if (IsStairBlock(id)) - { - StaticTile[] tiles = mcl.Tiles[ax][ay]; - - for (int i = 0; i < tiles.Length; ++i) - { - StaticTile tile = tiles[i]; - - if (tile.Z == z + 5) - { - id = tile.ID; - z = tile.Z; - - if (!IsStairBlock(id)) - break; - } - } - } - - int dir = 0; - - if (!IsStair(id, ref dir)) - return false; - - if (AllowStairSectioning) - return true; // skip deletion - - int height = (z - 7) % 20 / 5; - - int xStart, yStart; - int xInc, yInc; - - switch (dir) - { - default: - { - xStart = x; - yStart = y + height; - xInc = 0; - yInc = -1; - break; - } - case 1: // West - { - xStart = x + height; - yStart = y; - xInc = -1; - yInc = 0; - break; - } - case 2: // South - { - xStart = x; - yStart = y - height; - xInc = 0; - yInc = 1; - break; - } - case 3: // East - { - xStart = x - height; - yStart = y; - xInc = 1; - yInc = 0; - break; - } - } - - int zStart = z - height * 5; - - for (int i = 0; i < 4; ++i) - { - x = xStart + i * xInc; - y = yStart + i * yInc; - - for (int j = 0; j <= i; ++j) - mcl.RemoveXYZH(x, y, zStart + j * 5, 5); - - ax = x + mcl.Center.X; - ay = y + mcl.Center.Y; - - if (ax >= 1 && ax < mcl.Width && ay >= 1 && ay < mcl.Height - 1) - { - StaticTile[] tiles = mcl.Tiles[ax][ay]; - - bool hasBaseFloor = false; - - for (int j = 0; !hasBaseFloor && j < tiles.Length; ++j) - hasBaseFloor = tiles[j].Z == 7 && tiles[j].ID != 1; - - if (!hasBaseFloor) - mcl.Add(0x31F4, x, y, 7); - } - } - - return true; - } - - public static void Designer_Delete(NetState state, IEntity e, EncodedReader pvSrc) - { - Mobile from = state.Mobile; - DesignContext context = DesignContext.Find(from); - - if (context == null) - return; - - /* Client chose to delete a component - * - Read data detailing which component to delete - * - Verify component is deletable - * - Remove the component - * - If needed, replace removed component with a dirt tile - * - Update revision - */ - - // Read data detailing which component to delete - int itemID = pvSrc.ReadInt32(); - int x = pvSrc.ReadInt32(); - int y = pvSrc.ReadInt32(); - int z = pvSrc.ReadInt32(); - - // Verify component is deletable - DesignState design = context.Foundation.DesignState; - MultiComponentList mcl = design.Components; - - int ax = x + mcl.Center.X; - int ay = y + mcl.Center.Y; - - if (z == 0 && ax >= 0 && ax < mcl.Width && ay >= 0 && ay < mcl.Height - 1) - { - /* Component is not deletable - * - Resend design state - * - Return without further processing - */ - - design.SendDetailedInfoTo(state); - return; - } - - bool fixState = false; - - // Remove the component - if (AllowStairSectioning) - { - if (DeleteStairs(mcl, itemID, x, y, z)) - fixState = true; // The client removes the entire set of stairs locally, resend state - - mcl.Remove(itemID, x, y, z); - } - else - { - if (!DeleteStairs(mcl, itemID, x, y, z)) - mcl.Remove(itemID, x, y, z); - } - - // If needed, replace removed component with a dirt tile - if (ax >= 1 && ax < mcl.Width && ay >= 1 && ay < mcl.Height - 1) - { - StaticTile[] tiles = mcl.Tiles[ax][ay]; - - bool hasBaseFloor = false; - - for (int i = 0; !hasBaseFloor && i < tiles.Length; ++i) - hasBaseFloor = tiles[i].Z == 7 && tiles[i].ID != 1; - - if (!hasBaseFloor) mcl.Add(0x31F4, x, y, 7); - } - - // Update revision - design.OnRevised(); - - // Resend design state - if (fixState) - design.SendDetailedInfoTo(state); - } - - public static void Designer_Stairs(NetState state, IEntity e, EncodedReader pvSrc) - { - Mobile from = state.Mobile; - DesignContext context = DesignContext.Find(from); - - if (context == null) - return; - - /* Client chose to add stairs - * - Read data detailing stair type and location - * - Validate stair multi ID - * - Add the stairs - * - Load data describing the stair components - * - Insert described components - * - Update revision - */ - - // Read data detailing stair type and location - int itemID = pvSrc.ReadInt32(); - int x = pvSrc.ReadInt32(); - int y = pvSrc.ReadInt32(); - - // Validate stair multi ID - DesignState design = context.Foundation.DesignState; - - if (!Verification.IsMultiValid(itemID)) - { - /* Specified multi ID is not a stair - * - Resend design state - * - Return without further processing - */ - - TraceValidity(state, itemID); - design.SendDetailedInfoTo(state); - return; - } - - // Add the stairs - MultiComponentList mcl = design.Components; - - // Add the stairs : Load data describing stair components - MultiComponentList stairs = MultiData.GetComponents(itemID); - - // Add the stairs : Insert described components - int z = GetLevelZ(context.Level, context.Foundation); - - for (int i = 0; i < stairs.List.Length; ++i) - { - MultiTileEntry entry = stairs.List[i]; - - if (entry.ItemId != 1) - mcl.Add(entry.ItemId, x + entry.OffsetX, y + entry.OffsetY, z + entry.OffsetZ); - } - - // Update revision - design.OnRevised(); - } - - private static void TraceValidity(NetState state, int itemID) - { - try - { - using StreamWriter op = new StreamWriter("comp_val.log", true); - op.WriteLine("{0}\t{1}\tInvalid ItemID 0x{2:X4}", state, state.Mobile, itemID); - } - catch - { - // ignored - } - } - - public static void Designer_Build(NetState state, IEntity e, EncodedReader pvSrc) - { - Mobile from = state.Mobile; - DesignContext context = DesignContext.Find(from); - - if (context == null) - return; - - /* Client chose to add a component - * - Read data detailing component graphic and location - * - Add component - * - Update revision - */ - - // Read data detailing component graphic and location - int itemID = pvSrc.ReadInt32(); - int x = pvSrc.ReadInt32(); - int y = pvSrc.ReadInt32(); - - // Add component - DesignState design = context.Foundation.DesignState; - - if (from.AccessLevel < AccessLevel.GameMaster && !ValidPiece(itemID)) - { - TraceValidity(state, itemID); - design.SendDetailedInfoTo(state); - return; - } - - MultiComponentList mcl = design.Components; - - int z = GetLevelZ(context.Level, context.Foundation); - - if (y + mcl.Center.Y == mcl.Height - 1) - z = 0; // Tiles placed on the far-south of the house are at 0 Z - - mcl.Add(itemID, x, y, z); - - // Update revision - design.OnRevised(); - } - - public static void Designer_Close(NetState state, IEntity e, EncodedReader pvSrc) - { - Mobile from = state.Mobile; - DesignContext context = DesignContext.Find(from); - - if (context == null) - return; - - /* Client closed his house design window - * - Remove design context - * - Notify the client that customization has ended - * - Refresh client with current visible design state - * - If a signpost is needed, add it - * - Eject all from house - * - Restore relocated entities - */ - - // Remove design context - DesignContext.Remove(from); - - // Notify the client that customization has ended - from.Send(new EndHouseCustomization(context.Foundation)); - - // Refresh client with current visible design state - context.Foundation.SendInfoTo(state); - context.Foundation.CurrentState.SendDetailedInfoTo(state); - - // If a signpost is needed, add it - context.Foundation.CheckSignpost(); - - // Eject all from house - from.RevealingAction(); - - foreach (Item item in context.Foundation.GetItems()) - item.Location = context.Foundation.BanLocation; - - foreach (Mobile mobile in context.Foundation.GetMobiles()) - mobile.Location = context.Foundation.BanLocation; - - // Restore relocated entities - context.Foundation.RestoreRelocatedEntities(); - } - - public static void Designer_Level(NetState state, IEntity e, EncodedReader pvSrc) - { - Mobile from = state.Mobile; - DesignContext context = DesignContext.Find(from); - - if (context == null) - return; - - /* Client is moving to a new floor level - * - Read data detailing the target level - * - Validate target level - * - Update design context with new level - * - Teleport mobile to new level - * - Update client - * - */ - - // Read data detailing the target level - int newLevel = pvSrc.ReadInt32(); - - // Validate target level - if (newLevel < 1 || newLevel > context.MaxLevels) - newLevel = 1; - - // Update design context with new level - context.Level = newLevel; - - // Teleport mobile to new level - from.Location = new Point3D(from.X, from.Y, context.Foundation.Z + GetLevelZ(newLevel, context.Foundation)); - - // Update client - context.Foundation.SendInfoTo(state); - } - - public static void QueryDesignDetails(NetState state, PacketReader pvSrc) - { - Mobile from = state.Mobile; - - if (World.FindItem(pvSrc.ReadUInt32()) is HouseFoundation foundation && from.Map == foundation.Map && from.InRange(foundation.GetWorldLocation(), 24) && - from.CanSee(foundation)) - { - DesignState stateToSend = DesignContext.Find(from)?.Foundation == foundation ? foundation.DesignState : foundation.CurrentState; - stateToSend.SendDetailedInfoTo(state); - } - } - - public static void Designer_Roof(NetState state, IEntity e, EncodedReader pvSrc) - { - Mobile from = state.Mobile; - DesignContext context = DesignContext.Find(from); - - if (context == null || (!Core.SE && from.AccessLevel < AccessLevel.GameMaster)) - return; - - // Read data detailing component graphic and location - int itemID = pvSrc.ReadInt32(); - int x = pvSrc.ReadInt32(); - int y = pvSrc.ReadInt32(); - int z = pvSrc.ReadInt32(); - - // Add component - DesignState design = context.Foundation.DesignState; - - if (from.AccessLevel < AccessLevel.GameMaster && !ValidPiece(itemID, true)) - { - TraceValidity(state, itemID); - design.SendDetailedInfoTo(state); - return; - } - - MultiComponentList mcl = design.Components; - - if (z < -3 || z > 12 || z % 3 != 0) - z = -3; - z += GetLevelZ(context.Level, context.Foundation); - - MultiTileEntry[] list = mcl.List; - for (int i = 0; i < list.Length; i++) - { - MultiTileEntry mte = list[i]; - - if (mte.OffsetX == x && mte.OffsetY == y && - GetZLevel(mte.OffsetZ, context.Foundation) == context.Level && - (TileData.ItemTable[mte.ItemId & TileData.MaxItemValue].Flags & TileFlag.Roof) != 0) - mcl.Remove(mte.ItemId, x, y, mte.OffsetZ); - } - - mcl.Add(itemID, x, y, z); - - // Update revision - design.OnRevised(); - } - - public static void Designer_RoofDelete(NetState state, IEntity e, EncodedReader pvSrc) - { - Mobile from = state.Mobile; - DesignContext context = DesignContext.Find(from); - - // No need to check for Core.SE if trying to remove something that shouldn't be able to be placed anyways - if (context == null) - return; - - // Read data detailing which component to delete - int itemID = pvSrc.ReadInt32(); - int x = pvSrc.ReadInt32(); - int y = pvSrc.ReadInt32(); - int z = pvSrc.ReadInt32(); - - // Verify component is deletable - DesignState design = context.Foundation.DesignState; - MultiComponentList mcl = design.Components; - - if ((TileData.ItemTable[itemID & TileData.MaxItemValue].Flags & TileFlag.Roof) == 0) - { - design.SendDetailedInfoTo(state); - return; - } - - mcl.Remove(itemID, x, y, z); - - design.OnRevised(); - } - } - - public class DesignState - { - private Packet m_PacketCache; - - public DesignState(HouseFoundation foundation, MultiComponentList components) - { - Foundation = foundation; - Components = components; - Fixtures = Array.Empty(); - } - - public DesignState(DesignState toCopy) - { - Foundation = toCopy.Foundation; - Components = new MultiComponentList(toCopy.Components); - Revision = toCopy.Revision; - Fixtures = new MultiTileEntry[toCopy.Fixtures.Length]; - - for (int i = 0; i < Fixtures.Length; ++i) - Fixtures[i] = toCopy.Fixtures[i]; - } - - public DesignState(HouseFoundation foundation, IGenericReader reader) - { - Foundation = foundation; - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Components = new MultiComponentList(reader); - - int length = reader.ReadInt(); - - Fixtures = new MultiTileEntry[length]; - - for (int i = 0; i < length; ++i) + // If needed, replace removed component with a dirt tile + if (ax >= 1 && ax < mcl.Width && ay >= 1 && ay < mcl.Height - 1) { - Fixtures[i].ItemId = reader.ReadUShort(); - Fixtures[i].OffsetX = reader.ReadShort(); - Fixtures[i].OffsetY = reader.ReadShort(); - Fixtures[i].OffsetZ = reader.ReadShort(); - Fixtures[i].Flags = (TileFlag)reader.ReadInt(); + var tiles = mcl.Tiles[ax][ay]; + + var hasBaseFloor = false; + + for (var i = 0; !hasBaseFloor && i < tiles.Length; ++i) + hasBaseFloor = tiles[i].Z == 7 && tiles[i].ID != 1; + + if (!hasBaseFloor) mcl.Add(0x31F4, x, y, 7); } - Revision = reader.ReadInt(); + // Update revision + design.OnRevised(); - break; - } - } - } - - public Packet PacketCache - { - get => m_PacketCache; - set - { - if (m_PacketCache == value) - return; - - m_PacketCache?.Release(); - - m_PacketCache = value; - } - } - - public HouseFoundation Foundation { get; } - - public MultiComponentList Components { get; } - - public MultiTileEntry[] Fixtures { get; private set; } - - public int Revision { get; set; } - - public void Serialize(IGenericWriter writer) - { - writer.Write(0); // version - - Components.Serialize(writer); - - writer.Write(Fixtures.Length); - - for (int i = 0; i < Fixtures.Length; ++i) - { - MultiTileEntry ent = Fixtures[i]; - - writer.Write(ent.ItemId); - writer.Write(ent.OffsetX); - writer.Write(ent.OffsetY); - writer.Write(ent.OffsetZ); - writer.Write((int)ent.Flags); - } - - writer.Write(Revision); - } - - public void OnRevised() - { - lock (this) - { - Revision = ++Foundation.LastRevision; - - m_PacketCache?.Release(); - - m_PacketCache = null; - } - } - - public void SendGeneralInfoTo(NetState state) - { - state?.Send(new DesignStateGeneral(Foundation, this)); - } - - public void SendDetailedInfoTo(NetState state) - { - if (state != null) - lock (this) - { - if (m_PacketCache == null) - DesignStateDetailed.SendDetails(state, Foundation, this); - else - state.Send(m_PacketCache); + // Resend design state + if (fixState) + design.SendDetailedInfoTo(state); } - } - public void FreezeFixtures() - { - OnRevised(); - - for (int i = 0; i < Fixtures.Length; ++i) - { - MultiTileEntry mte = Fixtures[i]; - - Components.Add(mte.ItemId, mte.OffsetX, mte.OffsetY, mte.OffsetZ); - } - - Fixtures = Array.Empty(); - } - - public void MeltFixtures() - { - OnRevised(); - - MultiTileEntry[] list = Components.List; - int length = 0; - - for (int i = list.Length - 1; i >= 0; --i) - { - MultiTileEntry mte = list[i]; - - if (IsFixture(mte.ItemId)) - ++length; - } - - Fixtures = new MultiTileEntry[length]; - - for (int i = list.Length - 1; i >= 0; --i) - { - MultiTileEntry mte = list[i]; - - if (IsFixture(mte.ItemId)) + public static void Designer_Stairs(NetState state, IEntity e, EncodedReader pvSrc) { - Fixtures[--length] = mte; - Components.Remove(mte.ItemId, mte.OffsetX, mte.OffsetY, mte.OffsetZ); - } - } - } - - public static bool IsFixture(int itemID) - { - if (itemID >= 0x675 && itemID < 0x6F5) - return true; - if (itemID >= 0x314 && itemID < 0x364) - return true; - if (itemID >= 0x824 && itemID < 0x834) - return true; - if (itemID >= 0x839 && itemID < 0x849) - return true; - if (itemID >= 0x84C && itemID < 0x85C) - return true; - if (itemID >= 0x866 && itemID < 0x876) - return true; - if (itemID >= 0x0E8 && itemID < 0x0F8) - return true; - if (itemID >= 0x1FED && itemID < 0x1FFD) - return true; - if (itemID >= 0x181D && itemID < 0x1829) - return true; - if (itemID >= 0x241F && itemID < 0x2421) - return true; - if (itemID >= 0x2423 && itemID < 0x2425) - return true; - if (itemID >= 0x2A05 && itemID < 0x2A1D) - return true; - if (itemID >= 0x319C && itemID < 0x31B0) - return true; - // ML doors - if (itemID == 0x2D46 || itemID == 0x2D48 || itemID == 0x2FE2 || itemID == 0x2FE4) - return true; - if (itemID >= 0x2D63 && itemID < 0x2D70) - return true; - if (itemID >= 0x319C && itemID < 0x31AF) - return true; - if (itemID >= 0x367B && itemID < 0x369B) - return true; - // SA doors - if (itemID >= 0x409B && itemID < 0x40A3) - return true; - if (itemID >= 0x410C && itemID < 0x4114) - return true; - if (itemID >= 0x41C2 && itemID < 0x41CA) - return true; - if (itemID >= 0x41CF && itemID < 0x41D7) - return true; - if (itemID >= 0x436E && itemID < 0x437E) - return true; - if (itemID >= 0x46DD && itemID < 0x46E5) - return true; - if (itemID >= 0x4D22 && itemID < 0x4D2A) - return true; - if (itemID >= 0x50C8 && itemID < 0x50D8) - return true; - if (itemID >= 0x5142 && itemID < 0x514A) - return true; - // TOL doors - if (itemID >= 0x9AD7 && itemID < 0x9AE7) - return true; - - return itemID >= 0x9B3C && itemID < 0x9B4C; - } - } - - public class ConfirmCommitGump : Gump - { - private readonly HouseFoundation m_Foundation; - - public ConfirmCommitGump(Mobile from, HouseFoundation foundation, int bankBalance, int oldPrice, int newPrice) - : base(50, 50) - { - m_Foundation = foundation; - - AddPage(0); - - AddBackground(0, 0, 320, 320, 5054); - - AddImageTiled(10, 10, 300, 20, 2624); - AddImageTiled(10, 40, 300, 240, 2624); - AddImageTiled(10, 290, 300, 20, 2624); - - AddAlphaRegion(10, 10, 300, 300); - - AddHtmlLocalized(10, 10, 300, 20, 1062060, 32736); //
COMMIT DESIGN
- - AddHtmlLocalized(10, 40, 300, 140, newPrice - oldPrice <= bankBalance ? 1061898 : 1061903, 1023, false, true); - - AddHtmlLocalized(10, 190, 150, 20, 1061902, 32736); // Bank Balance: - AddLabel(170, 190, 55, bankBalance.ToString()); - - AddHtmlLocalized(10, 215, 150, 20, 1061899, 1023); // Old Value: - AddLabel(170, 215, 90, oldPrice.ToString()); - - AddHtmlLocalized(10, 235, 150, 20, 1061900, 1023); // Cost To Commit: - AddLabel(170, 235, 90, newPrice.ToString()); - - if (newPrice - oldPrice < 0) - { - AddHtmlLocalized(10, 260, 150, 20, 1062059, 992); // Your Refund: - AddLabel(170, 260, 70, (oldPrice - newPrice).ToString()); - } - else - { - AddHtmlLocalized(10, 260, 150, 20, 1061901, 31744); // Your Cost: - AddLabel(170, 260, 40, (newPrice - oldPrice).ToString()); - } - - AddButton(10, 290, 4005, 4007, 1); - AddHtmlLocalized(45, 290, 55, 20, 1011036, 32767); // OKAY - - AddButton(170, 290, 4005, 4007, 0); - AddHtmlLocalized(195, 290, 55, 20, 1011012, 32767); // CANCEL - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (info.ButtonID == 1) - m_Foundation.EndConfirmCommit(sender.Mobile); - } - } - - public class DesignContext - { - public DesignContext(HouseFoundation foundation) - { - Foundation = foundation; - Level = 1; - } - - public HouseFoundation Foundation { get; } - - public int Level { get; set; } - - public int MaxLevels => Foundation.MaxLevels; - - public static Dictionary Table { get; } = new Dictionary(); - - public static DesignContext Find(Mobile from) - { - if (from == null) - return null; - - Table.TryGetValue(from, out DesignContext d); - - return d; - } - - public static bool Check(Mobile m) - { - if (Find(m) == null) - return true; - - m.SendLocalizedMessage(1062206); // You cannot do that while customizing a house. - return false; - } - - public static void Add(Mobile from, HouseFoundation foundation) - { - if (from == null) - return; - - DesignContext c = new DesignContext(foundation); - - Table[from] = c; - - if (from is PlayerMobile pm) - pm.DesignContext = c; - - foundation.Customizer = from; - - from.Hidden = true; - from.Location = new Point3D(foundation.X, foundation.Y, foundation.Z + 7); - - NetState state = from.NetState; - - if (state == null) - return; - - List fixtures = foundation.Fixtures; - - for (int i = 0; fixtures != null && i < fixtures.Count; ++i) - { - Item item = fixtures[i]; - - state.Send(item.RemovePacket); - } - - if (foundation.Signpost != null) - state.Send(foundation.Signpost.RemovePacket); - - if (foundation.SignHanger != null) - state.Send(foundation.SignHanger.RemovePacket); - - if (foundation.Sign != null) - state.Send(foundation.Sign.RemovePacket); - } - - public static void Remove(Mobile from) - { - DesignContext context = Find(from); - - if (context == null) - return; - - Table.Remove(from); - - if (from is PlayerMobile pm) - pm.DesignContext = null; - - context.Foundation.Customizer = null; - - NetState state = from.NetState; - - if (state == null) - return; - - List fixtures = context.Foundation.Fixtures; - - for (int i = 0; fixtures != null && i < fixtures.Count; ++i) - { - Item item = fixtures[i]; - - item.SendInfoTo(state); - } - - context.Foundation.Signpost?.SendInfoTo(state); - - context.Foundation.SignHanger?.SendInfoTo(state); - - context.Foundation.Sign?.SendInfoTo(state); - } - } - - public class BeginHouseCustomization : Packet - { - public BeginHouseCustomization(HouseFoundation house) - : base(0xBF) - { - EnsureCapacity(17); - - Stream.Write((short)0x20); - Stream.Write(house.Serial); - Stream.Write((byte)0x04); - Stream.Write((ushort)0x0000); - Stream.Write((ushort)0xFFFF); - Stream.Write((ushort)0xFFFF); - Stream.Write((byte)0xFF); - } - } - - public class EndHouseCustomization : Packet - { - public EndHouseCustomization(HouseFoundation house) - : base(0xBF) - { - EnsureCapacity(17); - - Stream.Write((short)0x20); - Stream.Write(house.Serial); - Stream.Write((byte)0x05); - Stream.Write((ushort)0x0000); - Stream.Write((ushort)0xFFFF); - Stream.Write((ushort)0xFFFF); - Stream.Write((byte)0xFF); - } - } - - public sealed class DesignStateGeneral : Packet - { - public DesignStateGeneral(HouseFoundation house, DesignState state) - : base(0xBF) - { - EnsureCapacity(13); - - Stream.Write((short)0x1D); - Stream.Write(house.Serial); - Stream.Write(state.Revision); - } - } - - public sealed class DesignStateDetailed : Packet - { - public const int MaxItemsPerStairBuffer = 750; - - private static readonly ConcurrentQueue m_SendQueue; - private static readonly AutoResetEvent m_Sync; - - private readonly byte[][] m_PlaneBuffers; - - private readonly bool[] m_PlaneUsed = new bool[9]; - private readonly byte[] m_PrimBuffer = new byte[4]; - private readonly byte[][] m_StairBuffers; - - static DesignStateDetailed() - { - m_SendQueue = new ConcurrentQueue(); - m_Sync = new AutoResetEvent(false); - - Task.Run(ProcessCompression); - } - - public DesignStateDetailed(uint serial, int revision, int xMin, int yMin, int xMax, int yMax, MultiTileEntry[] tiles) - : base(0xD8) - { - EnsureCapacity(17 + tiles.Length * 5); - - Write((byte)0x03); // Compression Type - Write((byte)0x00); // Unknown - Write(serial); - Write(revision); - Write((short)tiles.Length); - Write((short)0); // Buffer length : reserved - Write((byte)0); // Plane count : reserved - - int totalLength = 1; // includes plane count - - int width = xMax - xMin + 1; - int height = yMax - yMin + 1; - - m_PlaneBuffers = new byte[9][]; - - for (int i = 0; i < m_PlaneBuffers.Length; ++i) - m_PlaneBuffers[i] = ArrayPool.Shared.Rent(0x400); - - m_StairBuffers = new byte[6][]; - - for (int i = 0; i < m_StairBuffers.Length; ++i) - m_StairBuffers[i] = ArrayPool.Shared.Rent(MaxItemsPerStairBuffer * 5); - - Clear(m_PlaneBuffers[0], width * height * 2); - - for (int i = 0; i < 4; ++i) - { - Clear(m_PlaneBuffers[1 + i], (width - 1) * (height - 2) * 2); - Clear(m_PlaneBuffers[5 + i], width * (height - 1) * 2); - } - - int totalStairsUsed = 0; - - for (int i = 0; i < tiles.Length; ++i) - { - MultiTileEntry mte = tiles[i]; - int x = mte.OffsetX - xMin; - int y = mte.OffsetY - yMin; - int z = mte.OffsetZ; - bool floor = TileData.ItemTable[mte.ItemId & TileData.MaxItemValue].Height <= 0; - int plane, size; - - switch (z) - { - case 0: - plane = 0; - break; - case 7: - plane = 1; - break; - case 27: - plane = 2; - break; - case 47: - plane = 3; - break; - case 67: - plane = 4; - break; - default: + var from = state.Mobile; + var context = DesignContext.Find(from); + + if (context == null) + return; + + /* Client chose to add stairs + * - Read data detailing stair type and location + * - Validate stair multi ID + * - Add the stairs + * - Load data describing the stair components + * - Insert described components + * - Update revision + */ + + // Read data detailing stair type and location + var itemID = pvSrc.ReadInt32(); + var x = pvSrc.ReadInt32(); + var y = pvSrc.ReadInt32(); + + // Validate stair multi ID + var design = context.Foundation.DesignState; + + if (!Verification.IsMultiValid(itemID)) { - int stairBufferIndex = totalStairsUsed / MaxItemsPerStairBuffer; - byte[] stairBuffer = m_StairBuffers[stairBufferIndex]; + /* Specified multi ID is not a stair + * - Resend design state + * - Return without further processing + */ - int byteIndex = totalStairsUsed % MaxItemsPerStairBuffer * 5; - - stairBuffer[byteIndex++] = (byte)(mte.ItemId >> 8); - stairBuffer[byteIndex++] = (byte)mte.ItemId; - - stairBuffer[byteIndex++] = (byte)mte.OffsetX; - stairBuffer[byteIndex++] = (byte)mte.OffsetY; - stairBuffer[byteIndex++] = (byte)mte.OffsetZ; - - ++totalStairsUsed; - - continue; + TraceValidity(state, itemID); + design.SendDetailedInfoTo(state); + return; } - } - if (plane == 0) - { - size = height; - } - else if (floor) - { - size = height - 2; - x -= 1; - y -= 1; - } - else - { - size = height - 1; - plane += 4; - } + // Add the stairs + var mcl = design.Components; - int index = (x * size + y) * 2; + // Add the stairs : Load data describing stair components + var stairs = MultiData.GetComponents(itemID); - if (x < 0 || y < 0 || y >= size || index + 1 >= 0x400) - { - int stairBufferIndex = totalStairsUsed / MaxItemsPerStairBuffer; - byte[] stairBuffer = m_StairBuffers[stairBufferIndex]; + // Add the stairs : Insert described components + var z = GetLevelZ(context.Level, context.Foundation); - int byteIndex = totalStairsUsed % MaxItemsPerStairBuffer * 5; - - stairBuffer[byteIndex++] = (byte)(mte.ItemId >> 8); - stairBuffer[byteIndex++] = (byte)mte.ItemId; - - stairBuffer[byteIndex++] = (byte)mte.OffsetX; - stairBuffer[byteIndex++] = (byte)mte.OffsetY; - stairBuffer[byteIndex++] = (byte)mte.OffsetZ; - - ++totalStairsUsed; - } - else - { - m_PlaneUsed[plane] = true; - m_PlaneBuffers[plane][index] = (byte)(mte.ItemId >> 8); - m_PlaneBuffers[plane][index + 1] = (byte)mte.ItemId; - } - } - - int planeCount = 0; - - byte[] m_DeflatedBuffer = ArrayPool.Shared.Rent(0x2000); - - for (int i = 0; i < m_PlaneBuffers.Length; ++i) - { - if (!m_PlaneUsed[i]) - { - ArrayPool.Shared.Return(m_PlaneBuffers[i]); - continue; - } - - ++planeCount; - - int size; - - if (i == 0) - size = width * height * 2; - else if (i < 5) - size = (width - 1) * (height - 2) * 2; - else - size = width * (height - 1) * 2; - - byte[] inflatedBuffer = m_PlaneBuffers[i]; - - int deflatedLength = m_DeflatedBuffer.Length; - ZlibError ce = Zlib.Pack(m_DeflatedBuffer, ref deflatedLength, inflatedBuffer, size, - ZlibQuality.Default); - - if (ce != ZlibError.Okay) - { - Console.WriteLine("ZLib error: {0} (#{1})", ce, (int)ce); - deflatedLength = 0; - size = 0; - } - - Write((byte)(0x20 | i)); - Write((byte)size); - Write((byte)deflatedLength); - Write((byte)(size >> 4 & 0xF0 | deflatedLength >> 8 & 0xF)); - Write(m_DeflatedBuffer, 0, deflatedLength); - - totalLength += 4 + deflatedLength; - ArrayPool.Shared.Return(inflatedBuffer); - } - - int totalStairBuffersUsed = (totalStairsUsed + (MaxItemsPerStairBuffer - 1)) / MaxItemsPerStairBuffer; - - for (int i = 0; i < totalStairBuffersUsed; ++i) - { - ++planeCount; - - int count = totalStairsUsed - i * MaxItemsPerStairBuffer; - - if (count > MaxItemsPerStairBuffer) - count = MaxItemsPerStairBuffer; - - int size = count * 5; - - byte[] inflatedBuffer = m_StairBuffers[i]; - - int deflatedLength = m_DeflatedBuffer.Length; - ZlibError ce = Zlib.Pack(m_DeflatedBuffer, ref deflatedLength, inflatedBuffer, size, - ZlibQuality.Default); - - if (ce != ZlibError.Okay) - { - Console.WriteLine("ZLib error: {0} (#{1})", ce, (int)ce); - deflatedLength = 0; - size = 0; - } - - Write((byte)(9 + i)); - Write((byte)size); - Write((byte)deflatedLength); - Write((byte)(size >> 4 & 0xF0 | deflatedLength >> 8 & 0xF)); - Write(m_DeflatedBuffer, 0, deflatedLength); - - totalLength += 4 + deflatedLength; - } - - for (int i = 0; i < m_StairBuffers.Length; ++i) - ArrayPool.Shared.Return(m_StairBuffers[i]); - - ArrayPool.Shared.Return(m_DeflatedBuffer); - - Stream.Seek(15, SeekOrigin.Begin); - - Write((short)totalLength); // Buffer length - Write((byte)planeCount); // Plane count - } - - public void Write(int value) - { - m_PrimBuffer[0] = (byte)(value >> 24); - m_PrimBuffer[1] = (byte)(value >> 16); - m_PrimBuffer[2] = (byte)(value >> 8); - m_PrimBuffer[3] = (byte)value; - - Stream.UnderlyingStream.Write(m_PrimBuffer, 0, 4); - } - - public void Write(uint value) - { - m_PrimBuffer[0] = (byte)(value >> 24); - m_PrimBuffer[1] = (byte)(value >> 16); - m_PrimBuffer[2] = (byte)(value >> 8); - m_PrimBuffer[3] = (byte)value; - - Stream.UnderlyingStream.Write(m_PrimBuffer, 0, 4); - } - - public void Write(short value) - { - m_PrimBuffer[0] = (byte)(value >> 8); - m_PrimBuffer[1] = (byte)value; - - Stream.UnderlyingStream.Write(m_PrimBuffer, 0, 2); - } - - public void Write(byte value) - { - Stream.UnderlyingStream.WriteByte(value); - } - - public void Write(byte[] buffer, int offset, int size) - { - Stream.UnderlyingStream.Write(buffer, offset, size); - } - - public static void Clear(byte[] buffer, int size) - { - for (int i = 0; i < size; ++i) - buffer[i] = 0; - } - - public static void ProcessCompression() - { - while (!Core.Closing) - { - m_Sync.WaitOne(); - - int count = m_SendQueue.Count; - - while (count > 0 && m_SendQueue.TryDequeue(out SendQueueEntry sqe)) - try - { - Packet p; - - lock (sqe.m_Root) + for (var i = 0; i < stairs.List.Length; ++i) { - p = sqe.m_Root.PacketCache; + var entry = stairs.List[i]; + + if (entry.ItemId != 1) + mcl.Add(entry.ItemId, x + entry.OffsetX, y + entry.OffsetY, z + entry.OffsetZ); } - if (p == null) - { - p = new DesignStateDetailed(sqe.m_Serial, sqe.m_Revision, sqe.m_xMin, sqe.m_yMin, sqe.m_xMax, - sqe.m_yMax, sqe.m_Tiles); - p.SetStatic(); - - lock (sqe.m_Root) - { - if (sqe.m_Revision == sqe.m_Root.Revision) - sqe.m_Root.PacketCache = p; - } - } - - sqe.m_NetState.Send(p); - } - catch (Exception e) - { - Console.WriteLine(e); + // Update revision + design.OnRevised(); + } + private static void TraceValidity(NetState state, int itemID) + { try { - using StreamWriter op = new StreamWriter("dsd_exceptions.txt", true); - op.WriteLine(e); + using var op = new StreamWriter("comp_val.log", true); + op.WriteLine("{0}\t{1}\tInvalid ItemID 0x{2:X4}", state, state.Mobile, itemID); } catch { - // ignored + // ignored } - } - finally - { - count = m_SendQueue.Count; - } - } + } + + public static void Designer_Build(NetState state, IEntity e, EncodedReader pvSrc) + { + var from = state.Mobile; + var context = DesignContext.Find(from); + + if (context == null) + return; + + /* Client chose to add a component + * - Read data detailing component graphic and location + * - Add component + * - Update revision + */ + + // Read data detailing component graphic and location + var itemID = pvSrc.ReadInt32(); + var x = pvSrc.ReadInt32(); + var y = pvSrc.ReadInt32(); + + // Add component + var design = context.Foundation.DesignState; + + if (from.AccessLevel < AccessLevel.GameMaster && !ValidPiece(itemID)) + { + TraceValidity(state, itemID); + design.SendDetailedInfoTo(state); + return; + } + + var mcl = design.Components; + + var z = GetLevelZ(context.Level, context.Foundation); + + if (y + mcl.Center.Y == mcl.Height - 1) + z = 0; // Tiles placed on the far-south of the house are at 0 Z + + mcl.Add(itemID, x, y, z); + + // Update revision + design.OnRevised(); + } + + public static void Designer_Close(NetState state, IEntity e, EncodedReader pvSrc) + { + var from = state.Mobile; + var context = DesignContext.Find(from); + + if (context == null) + return; + + /* Client closed his house design window + * - Remove design context + * - Notify the client that customization has ended + * - Refresh client with current visible design state + * - If a signpost is needed, add it + * - Eject all from house + * - Restore relocated entities + */ + + // Remove design context + DesignContext.Remove(from); + + // Notify the client that customization has ended + from.Send(new EndHouseCustomization(context.Foundation)); + + // Refresh client with current visible design state + context.Foundation.SendInfoTo(state); + context.Foundation.CurrentState.SendDetailedInfoTo(state); + + // If a signpost is needed, add it + context.Foundation.CheckSignpost(); + + // Eject all from house + from.RevealingAction(); + + foreach (var item in context.Foundation.GetItems()) + item.Location = context.Foundation.BanLocation; + + foreach (var mobile in context.Foundation.GetMobiles()) + mobile.Location = context.Foundation.BanLocation; + + // Restore relocated entities + context.Foundation.RestoreRelocatedEntities(); + } + + public static void Designer_Level(NetState state, IEntity e, EncodedReader pvSrc) + { + var from = state.Mobile; + var context = DesignContext.Find(from); + + if (context == null) + return; + + /* Client is moving to a new floor level + * - Read data detailing the target level + * - Validate target level + * - Update design context with new level + * - Teleport mobile to new level + * - Update client + * + */ + + // Read data detailing the target level + var newLevel = pvSrc.ReadInt32(); + + // Validate target level + if (newLevel < 1 || newLevel > context.MaxLevels) + newLevel = 1; + + // Update design context with new level + context.Level = newLevel; + + // Teleport mobile to new level + from.Location = new Point3D(from.X, from.Y, context.Foundation.Z + GetLevelZ(newLevel, context.Foundation)); + + // Update client + context.Foundation.SendInfoTo(state); + } + + public static void QueryDesignDetails(NetState state, PacketReader pvSrc) + { + var from = state.Mobile; + + if (World.FindItem(pvSrc.ReadUInt32()) is HouseFoundation foundation && from.Map == foundation.Map && + from.InRange(foundation.GetWorldLocation(), 24) && + from.CanSee(foundation)) + { + var stateToSend = DesignContext.Find(from)?.Foundation == foundation + ? foundation.DesignState + : foundation.CurrentState; + stateToSend.SendDetailedInfoTo(state); + } + } + + public static void Designer_Roof(NetState state, IEntity e, EncodedReader pvSrc) + { + var from = state.Mobile; + var context = DesignContext.Find(from); + + if (context == null || !Core.SE && from.AccessLevel < AccessLevel.GameMaster) + return; + + // Read data detailing component graphic and location + var itemID = pvSrc.ReadInt32(); + var x = pvSrc.ReadInt32(); + var y = pvSrc.ReadInt32(); + var z = pvSrc.ReadInt32(); + + // Add component + var design = context.Foundation.DesignState; + + if (from.AccessLevel < AccessLevel.GameMaster && !ValidPiece(itemID, true)) + { + TraceValidity(state, itemID); + design.SendDetailedInfoTo(state); + return; + } + + var mcl = design.Components; + + if (z < -3 || z > 12 || z % 3 != 0) + z = -3; + z += GetLevelZ(context.Level, context.Foundation); + + var list = mcl.List; + for (var i = 0; i < list.Length; i++) + { + var mte = list[i]; + + if (mte.OffsetX == x && mte.OffsetY == y && + GetZLevel(mte.OffsetZ, context.Foundation) == context.Level && + (TileData.ItemTable[mte.ItemId & TileData.MaxItemValue].Flags & TileFlag.Roof) != 0) + mcl.Remove(mte.ItemId, x, y, mte.OffsetZ); + } + + mcl.Add(itemID, x, y, z); + + // Update revision + design.OnRevised(); + } + + public static void Designer_RoofDelete(NetState state, IEntity e, EncodedReader pvSrc) + { + var from = state.Mobile; + var context = DesignContext.Find(from); + + // No need to check for Core.SE if trying to remove something that shouldn't be able to be placed anyways + if (context == null) + return; + + // Read data detailing which component to delete + var itemID = pvSrc.ReadInt32(); + var x = pvSrc.ReadInt32(); + var y = pvSrc.ReadInt32(); + var z = pvSrc.ReadInt32(); + + // Verify component is deletable + var design = context.Foundation.DesignState; + var mcl = design.Components; + + if ((TileData.ItemTable[itemID & TileData.MaxItemValue].Flags & TileFlag.Roof) == 0) + { + design.SendDetailedInfoTo(state); + return; + } + + mcl.Remove(itemID, x, y, z); + + design.OnRevised(); + } } - public static void SendDetails(NetState ns, HouseFoundation house, DesignState state) + public class DesignState { - m_SendQueue.Enqueue(new SendQueueEntry(ns, house, state)); + private Packet m_PacketCache; - m_Sync.Set(); + public DesignState(HouseFoundation foundation, MultiComponentList components) + { + Foundation = foundation; + Components = components; + Fixtures = Array.Empty(); + } + + public DesignState(DesignState toCopy) + { + Foundation = toCopy.Foundation; + Components = new MultiComponentList(toCopy.Components); + Revision = toCopy.Revision; + Fixtures = new MultiTileEntry[toCopy.Fixtures.Length]; + + for (var i = 0; i < Fixtures.Length; ++i) + Fixtures[i] = toCopy.Fixtures[i]; + } + + public DesignState(HouseFoundation foundation, IGenericReader reader) + { + Foundation = foundation; + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Components = new MultiComponentList(reader); + + var length = reader.ReadInt(); + + Fixtures = new MultiTileEntry[length]; + + for (var i = 0; i < length; ++i) + { + Fixtures[i].ItemId = reader.ReadUShort(); + Fixtures[i].OffsetX = reader.ReadShort(); + Fixtures[i].OffsetY = reader.ReadShort(); + Fixtures[i].OffsetZ = reader.ReadShort(); + Fixtures[i].Flags = (TileFlag)reader.ReadInt(); + } + + Revision = reader.ReadInt(); + + break; + } + } + } + + public Packet PacketCache + { + get => m_PacketCache; + set + { + if (m_PacketCache == value) + return; + + m_PacketCache?.Release(); + + m_PacketCache = value; + } + } + + public HouseFoundation Foundation { get; } + + public MultiComponentList Components { get; } + + public MultiTileEntry[] Fixtures { get; private set; } + + public int Revision { get; set; } + + public void Serialize(IGenericWriter writer) + { + writer.Write(0); // version + + Components.Serialize(writer); + + writer.Write(Fixtures.Length); + + for (var i = 0; i < Fixtures.Length; ++i) + { + var ent = Fixtures[i]; + + writer.Write(ent.ItemId); + writer.Write(ent.OffsetX); + writer.Write(ent.OffsetY); + writer.Write(ent.OffsetZ); + writer.Write((int)ent.Flags); + } + + writer.Write(Revision); + } + + public void OnRevised() + { + lock (this) + { + Revision = ++Foundation.LastRevision; + + m_PacketCache?.Release(); + + m_PacketCache = null; + } + } + + public void SendGeneralInfoTo(NetState state) + { + state?.Send(new DesignStateGeneral(Foundation, this)); + } + + public void SendDetailedInfoTo(NetState state) + { + if (state != null) + lock (this) + { + if (m_PacketCache == null) + DesignStateDetailed.SendDetails(state, Foundation, this); + else + state.Send(m_PacketCache); + } + } + + public void FreezeFixtures() + { + OnRevised(); + + for (var i = 0; i < Fixtures.Length; ++i) + { + var mte = Fixtures[i]; + + Components.Add(mte.ItemId, mte.OffsetX, mte.OffsetY, mte.OffsetZ); + } + + Fixtures = Array.Empty(); + } + + public void MeltFixtures() + { + OnRevised(); + + var list = Components.List; + var length = 0; + + for (var i = list.Length - 1; i >= 0; --i) + { + var mte = list[i]; + + if (IsFixture(mte.ItemId)) + ++length; + } + + Fixtures = new MultiTileEntry[length]; + + for (var i = list.Length - 1; i >= 0; --i) + { + var mte = list[i]; + + if (IsFixture(mte.ItemId)) + { + Fixtures[--length] = mte; + Components.Remove(mte.ItemId, mte.OffsetX, mte.OffsetY, mte.OffsetZ); + } + } + } + + public static bool IsFixture(int itemID) + { + if (itemID >= 0x675 && itemID < 0x6F5) + return true; + if (itemID >= 0x314 && itemID < 0x364) + return true; + if (itemID >= 0x824 && itemID < 0x834) + return true; + if (itemID >= 0x839 && itemID < 0x849) + return true; + if (itemID >= 0x84C && itemID < 0x85C) + return true; + if (itemID >= 0x866 && itemID < 0x876) + return true; + if (itemID >= 0x0E8 && itemID < 0x0F8) + return true; + if (itemID >= 0x1FED && itemID < 0x1FFD) + return true; + if (itemID >= 0x181D && itemID < 0x1829) + return true; + if (itemID >= 0x241F && itemID < 0x2421) + return true; + if (itemID >= 0x2423 && itemID < 0x2425) + return true; + if (itemID >= 0x2A05 && itemID < 0x2A1D) + return true; + if (itemID >= 0x319C && itemID < 0x31B0) + return true; + // ML doors + if (itemID == 0x2D46 || itemID == 0x2D48 || itemID == 0x2FE2 || itemID == 0x2FE4) + return true; + if (itemID >= 0x2D63 && itemID < 0x2D70) + return true; + if (itemID >= 0x319C && itemID < 0x31AF) + return true; + if (itemID >= 0x367B && itemID < 0x369B) + return true; + // SA doors + if (itemID >= 0x409B && itemID < 0x40A3) + return true; + if (itemID >= 0x410C && itemID < 0x4114) + return true; + if (itemID >= 0x41C2 && itemID < 0x41CA) + return true; + if (itemID >= 0x41CF && itemID < 0x41D7) + return true; + if (itemID >= 0x436E && itemID < 0x437E) + return true; + if (itemID >= 0x46DD && itemID < 0x46E5) + return true; + if (itemID >= 0x4D22 && itemID < 0x4D2A) + return true; + if (itemID >= 0x50C8 && itemID < 0x50D8) + return true; + if (itemID >= 0x5142 && itemID < 0x514A) + return true; + // TOL doors + if (itemID >= 0x9AD7 && itemID < 0x9AE7) + return true; + + return itemID >= 0x9B3C && itemID < 0x9B4C; + } } - private class SendQueueEntry + public class ConfirmCommitGump : Gump { - public readonly NetState m_NetState; - public readonly DesignState m_Root; - public readonly int m_Revision; - public readonly uint m_Serial; - public readonly MultiTileEntry[] m_Tiles; - public readonly int m_xMin; - public readonly int m_yMin; - public readonly int m_xMax; - public readonly int m_yMax; + private readonly HouseFoundation m_Foundation; - public SendQueueEntry(NetState ns, HouseFoundation foundation, DesignState state) - { - m_NetState = ns; - m_Serial = foundation.Serial; - m_Revision = state.Revision; - m_Root = state; + public ConfirmCommitGump(Mobile from, HouseFoundation foundation, int bankBalance, int oldPrice, int newPrice) + : base(50, 50) + { + m_Foundation = foundation; - MultiComponentList mcl = state.Components; + AddPage(0); - m_xMin = mcl.Min.X; - m_yMin = mcl.Min.Y; - m_xMax = mcl.Max.X; - m_yMax = mcl.Max.Y; + AddBackground(0, 0, 320, 320, 5054); - m_Tiles = mcl.List; - } + AddImageTiled(10, 10, 300, 20, 2624); + AddImageTiled(10, 40, 300, 240, 2624); + AddImageTiled(10, 290, 300, 20, 2624); + + AddAlphaRegion(10, 10, 300, 300); + + AddHtmlLocalized(10, 10, 300, 20, 1062060, 32736); //
COMMIT DESIGN
+ + AddHtmlLocalized(10, 40, 300, 140, newPrice - oldPrice <= bankBalance ? 1061898 : 1061903, 1023, false, true); + + AddHtmlLocalized(10, 190, 150, 20, 1061902, 32736); // Bank Balance: + AddLabel(170, 190, 55, bankBalance.ToString()); + + AddHtmlLocalized(10, 215, 150, 20, 1061899, 1023); // Old Value: + AddLabel(170, 215, 90, oldPrice.ToString()); + + AddHtmlLocalized(10, 235, 150, 20, 1061900, 1023); // Cost To Commit: + AddLabel(170, 235, 90, newPrice.ToString()); + + if (newPrice - oldPrice < 0) + { + AddHtmlLocalized(10, 260, 150, 20, 1062059, 992); // Your Refund: + AddLabel(170, 260, 70, (oldPrice - newPrice).ToString()); + } + else + { + AddHtmlLocalized(10, 260, 150, 20, 1061901, 31744); // Your Cost: + AddLabel(170, 260, 40, (newPrice - oldPrice).ToString()); + } + + AddButton(10, 290, 4005, 4007, 1); + AddHtmlLocalized(45, 290, 55, 20, 1011036, 32767); // OKAY + + AddButton(170, 290, 4005, 4007, 0); + AddHtmlLocalized(195, 290, 55, 20, 1011012, 32767); // CANCEL + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 1) + m_Foundation.EndConfirmCommit(sender.Mobile); + } + } + + public class DesignContext + { + public DesignContext(HouseFoundation foundation) + { + Foundation = foundation; + Level = 1; + } + + public HouseFoundation Foundation { get; } + + public int Level { get; set; } + + public int MaxLevels => Foundation.MaxLevels; + + public static Dictionary Table { get; } = new Dictionary(); + + public static DesignContext Find(Mobile from) + { + if (from == null) + return null; + + Table.TryGetValue(from, out var d); + + return d; + } + + public static bool Check(Mobile m) + { + if (Find(m) == null) + return true; + + m.SendLocalizedMessage(1062206); // You cannot do that while customizing a house. + return false; + } + + public static void Add(Mobile from, HouseFoundation foundation) + { + if (from == null) + return; + + var c = new DesignContext(foundation); + + Table[from] = c; + + if (from is PlayerMobile pm) + pm.DesignContext = c; + + foundation.Customizer = from; + + from.Hidden = true; + from.Location = new Point3D(foundation.X, foundation.Y, foundation.Z + 7); + + var state = from.NetState; + + if (state == null) + return; + + var fixtures = foundation.Fixtures; + + for (var i = 0; fixtures != null && i < fixtures.Count; ++i) + { + var item = fixtures[i]; + + state.Send(item.RemovePacket); + } + + if (foundation.Signpost != null) + state.Send(foundation.Signpost.RemovePacket); + + if (foundation.SignHanger != null) + state.Send(foundation.SignHanger.RemovePacket); + + if (foundation.Sign != null) + state.Send(foundation.Sign.RemovePacket); + } + + public static void Remove(Mobile from) + { + var context = Find(from); + + if (context == null) + return; + + Table.Remove(from); + + if (from is PlayerMobile pm) + pm.DesignContext = null; + + context.Foundation.Customizer = null; + + var state = from.NetState; + + if (state == null) + return; + + var fixtures = context.Foundation.Fixtures; + + for (var i = 0; fixtures != null && i < fixtures.Count; ++i) + { + var item = fixtures[i]; + + item.SendInfoTo(state); + } + + context.Foundation.Signpost?.SendInfoTo(state); + + context.Foundation.SignHanger?.SendInfoTo(state); + + context.Foundation.Sign?.SendInfoTo(state); + } + } + + public class BeginHouseCustomization : Packet + { + public BeginHouseCustomization(HouseFoundation house) + : base(0xBF) + { + EnsureCapacity(17); + + Stream.Write((short)0x20); + Stream.Write(house.Serial); + Stream.Write((byte)0x04); + Stream.Write((ushort)0x0000); + Stream.Write((ushort)0xFFFF); + Stream.Write((ushort)0xFFFF); + Stream.Write((byte)0xFF); + } + } + + public class EndHouseCustomization : Packet + { + public EndHouseCustomization(HouseFoundation house) + : base(0xBF) + { + EnsureCapacity(17); + + Stream.Write((short)0x20); + Stream.Write(house.Serial); + Stream.Write((byte)0x05); + Stream.Write((ushort)0x0000); + Stream.Write((ushort)0xFFFF); + Stream.Write((ushort)0xFFFF); + Stream.Write((byte)0xFF); + } + } + + public sealed class DesignStateGeneral : Packet + { + public DesignStateGeneral(HouseFoundation house, DesignState state) + : base(0xBF) + { + EnsureCapacity(13); + + Stream.Write((short)0x1D); + Stream.Write(house.Serial); + Stream.Write(state.Revision); + } + } + + public sealed class DesignStateDetailed : Packet + { + public const int MaxItemsPerStairBuffer = 750; + + private static readonly ConcurrentQueue m_SendQueue; + private static readonly AutoResetEvent m_Sync; + + private readonly byte[][] m_PlaneBuffers; + + private readonly bool[] m_PlaneUsed = new bool[9]; + private readonly byte[] m_PrimBuffer = new byte[4]; + private readonly byte[][] m_StairBuffers; + + static DesignStateDetailed() + { + m_SendQueue = new ConcurrentQueue(); + m_Sync = new AutoResetEvent(false); + + Task.Run(ProcessCompression); + } + + public DesignStateDetailed(uint serial, int revision, int xMin, int yMin, int xMax, int yMax, MultiTileEntry[] tiles) + : base(0xD8) + { + EnsureCapacity(17 + tiles.Length * 5); + + Write((byte)0x03); // Compression Type + Write((byte)0x00); // Unknown + Write(serial); + Write(revision); + Write((short)tiles.Length); + Write((short)0); // Buffer length : reserved + Write((byte)0); // Plane count : reserved + + var totalLength = 1; // includes plane count + + var width = xMax - xMin + 1; + var height = yMax - yMin + 1; + + m_PlaneBuffers = new byte[9][]; + + for (var i = 0; i < m_PlaneBuffers.Length; ++i) + m_PlaneBuffers[i] = ArrayPool.Shared.Rent(0x400); + + m_StairBuffers = new byte[6][]; + + for (var i = 0; i < m_StairBuffers.Length; ++i) + m_StairBuffers[i] = ArrayPool.Shared.Rent(MaxItemsPerStairBuffer * 5); + + Clear(m_PlaneBuffers[0], width * height * 2); + + for (var i = 0; i < 4; ++i) + { + Clear(m_PlaneBuffers[1 + i], (width - 1) * (height - 2) * 2); + Clear(m_PlaneBuffers[5 + i], width * (height - 1) * 2); + } + + var totalStairsUsed = 0; + + for (var i = 0; i < tiles.Length; ++i) + { + var mte = tiles[i]; + var x = mte.OffsetX - xMin; + var y = mte.OffsetY - yMin; + int z = mte.OffsetZ; + var floor = TileData.ItemTable[mte.ItemId & TileData.MaxItemValue].Height <= 0; + int plane, size; + + switch (z) + { + case 0: + plane = 0; + break; + case 7: + plane = 1; + break; + case 27: + plane = 2; + break; + case 47: + plane = 3; + break; + case 67: + plane = 4; + break; + default: + { + var stairBufferIndex = totalStairsUsed / MaxItemsPerStairBuffer; + var stairBuffer = m_StairBuffers[stairBufferIndex]; + + var byteIndex = totalStairsUsed % MaxItemsPerStairBuffer * 5; + + stairBuffer[byteIndex++] = (byte)(mte.ItemId >> 8); + stairBuffer[byteIndex++] = (byte)mte.ItemId; + + stairBuffer[byteIndex++] = (byte)mte.OffsetX; + stairBuffer[byteIndex++] = (byte)mte.OffsetY; + stairBuffer[byteIndex++] = (byte)mte.OffsetZ; + + ++totalStairsUsed; + + continue; + } + } + + if (plane == 0) + { + size = height; + } + else if (floor) + { + size = height - 2; + x -= 1; + y -= 1; + } + else + { + size = height - 1; + plane += 4; + } + + var index = (x * size + y) * 2; + + if (x < 0 || y < 0 || y >= size || index + 1 >= 0x400) + { + var stairBufferIndex = totalStairsUsed / MaxItemsPerStairBuffer; + var stairBuffer = m_StairBuffers[stairBufferIndex]; + + var byteIndex = totalStairsUsed % MaxItemsPerStairBuffer * 5; + + stairBuffer[byteIndex++] = (byte)(mte.ItemId >> 8); + stairBuffer[byteIndex++] = (byte)mte.ItemId; + + stairBuffer[byteIndex++] = (byte)mte.OffsetX; + stairBuffer[byteIndex++] = (byte)mte.OffsetY; + stairBuffer[byteIndex++] = (byte)mte.OffsetZ; + + ++totalStairsUsed; + } + else + { + m_PlaneUsed[plane] = true; + m_PlaneBuffers[plane][index] = (byte)(mte.ItemId >> 8); + m_PlaneBuffers[plane][index + 1] = (byte)mte.ItemId; + } + } + + var planeCount = 0; + + var m_DeflatedBuffer = ArrayPool.Shared.Rent(0x2000); + + for (var i = 0; i < m_PlaneBuffers.Length; ++i) + { + if (!m_PlaneUsed[i]) + { + ArrayPool.Shared.Return(m_PlaneBuffers[i]); + continue; + } + + ++planeCount; + + int size; + + if (i == 0) + size = width * height * 2; + else if (i < 5) + size = (width - 1) * (height - 2) * 2; + else + size = width * (height - 1) * 2; + + var inflatedBuffer = m_PlaneBuffers[i]; + + var deflatedLength = m_DeflatedBuffer.Length; + var ce = Zlib.Pack( + m_DeflatedBuffer, + ref deflatedLength, + inflatedBuffer, + size, + ZlibQuality.Default + ); + + if (ce != ZlibError.Okay) + { + Console.WriteLine("ZLib error: {0} (#{1})", ce, (int)ce); + deflatedLength = 0; + size = 0; + } + + Write((byte)(0x20 | i)); + Write((byte)size); + Write((byte)deflatedLength); + Write((byte)(((size >> 4) & 0xF0) | ((deflatedLength >> 8) & 0xF))); + Write(m_DeflatedBuffer, 0, deflatedLength); + + totalLength += 4 + deflatedLength; + ArrayPool.Shared.Return(inflatedBuffer); + } + + var totalStairBuffersUsed = (totalStairsUsed + (MaxItemsPerStairBuffer - 1)) / MaxItemsPerStairBuffer; + + for (var i = 0; i < totalStairBuffersUsed; ++i) + { + ++planeCount; + + var count = totalStairsUsed - i * MaxItemsPerStairBuffer; + + if (count > MaxItemsPerStairBuffer) + count = MaxItemsPerStairBuffer; + + var size = count * 5; + + var inflatedBuffer = m_StairBuffers[i]; + + var deflatedLength = m_DeflatedBuffer.Length; + var ce = Zlib.Pack( + m_DeflatedBuffer, + ref deflatedLength, + inflatedBuffer, + size, + ZlibQuality.Default + ); + + if (ce != ZlibError.Okay) + { + Console.WriteLine("ZLib error: {0} (#{1})", ce, (int)ce); + deflatedLength = 0; + size = 0; + } + + Write((byte)(9 + i)); + Write((byte)size); + Write((byte)deflatedLength); + Write((byte)(((size >> 4) & 0xF0) | ((deflatedLength >> 8) & 0xF))); + Write(m_DeflatedBuffer, 0, deflatedLength); + + totalLength += 4 + deflatedLength; + } + + for (var i = 0; i < m_StairBuffers.Length; ++i) + ArrayPool.Shared.Return(m_StairBuffers[i]); + + ArrayPool.Shared.Return(m_DeflatedBuffer); + + Stream.Seek(15, SeekOrigin.Begin); + + Write((short)totalLength); // Buffer length + Write((byte)planeCount); // Plane count + } + + public void Write(int value) + { + m_PrimBuffer[0] = (byte)(value >> 24); + m_PrimBuffer[1] = (byte)(value >> 16); + m_PrimBuffer[2] = (byte)(value >> 8); + m_PrimBuffer[3] = (byte)value; + + Stream.UnderlyingStream.Write(m_PrimBuffer, 0, 4); + } + + public void Write(uint value) + { + m_PrimBuffer[0] = (byte)(value >> 24); + m_PrimBuffer[1] = (byte)(value >> 16); + m_PrimBuffer[2] = (byte)(value >> 8); + m_PrimBuffer[3] = (byte)value; + + Stream.UnderlyingStream.Write(m_PrimBuffer, 0, 4); + } + + public void Write(short value) + { + m_PrimBuffer[0] = (byte)(value >> 8); + m_PrimBuffer[1] = (byte)value; + + Stream.UnderlyingStream.Write(m_PrimBuffer, 0, 2); + } + + public void Write(byte value) + { + Stream.UnderlyingStream.WriteByte(value); + } + + public void Write(byte[] buffer, int offset, int size) + { + Stream.UnderlyingStream.Write(buffer, offset, size); + } + + public static void Clear(byte[] buffer, int size) + { + for (var i = 0; i < size; ++i) + buffer[i] = 0; + } + + public static void ProcessCompression() + { + while (!Core.Closing) + { + m_Sync.WaitOne(); + + var count = m_SendQueue.Count; + + while (count > 0 && m_SendQueue.TryDequeue(out var sqe)) + try + { + Packet p; + + lock (sqe.m_Root) + { + p = sqe.m_Root.PacketCache; + } + + if (p == null) + { + p = new DesignStateDetailed( + sqe.m_Serial, + sqe.m_Revision, + sqe.m_xMin, + sqe.m_yMin, + sqe.m_xMax, + sqe.m_yMax, + sqe.m_Tiles + ); + p.SetStatic(); + + lock (sqe.m_Root) + { + if (sqe.m_Revision == sqe.m_Root.Revision) + sqe.m_Root.PacketCache = p; + } + } + + sqe.m_NetState.Send(p); + } + catch (Exception e) + { + Console.WriteLine(e); + + try + { + using var op = new StreamWriter("dsd_exceptions.txt", true); + op.WriteLine(e); + } + catch + { + // ignored + } + } + finally + { + count = m_SendQueue.Count; + } + } + } + + public static void SendDetails(NetState ns, HouseFoundation house, DesignState state) + { + m_SendQueue.Enqueue(new SendQueueEntry(ns, house, state)); + + m_Sync.Set(); + } + + private class SendQueueEntry + { + public readonly NetState m_NetState; + public readonly int m_Revision; + public readonly DesignState m_Root; + public readonly uint m_Serial; + public readonly MultiTileEntry[] m_Tiles; + public readonly int m_xMax; + public readonly int m_xMin; + public readonly int m_yMax; + public readonly int m_yMin; + + public SendQueueEntry(NetState ns, HouseFoundation foundation, DesignState state) + { + m_NetState = ns; + m_Serial = foundation.Serial; + m_Revision = state.Revision; + m_Root = state; + + var mcl = state.Components; + + m_xMin = mcl.Min.X; + m_yMin = mcl.Min.Y; + m_xMax = mcl.Max.X; + m_yMax = mcl.Max.Y; + + m_Tiles = mcl.List; + } + } } - } } diff --git a/Projects/UOContent/Multis/HousePlacement.cs b/Projects/UOContent/Multis/HousePlacement.cs index b929bae9e..c7a3bdcb3 100644 --- a/Projects/UOContent/Multis/HousePlacement.cs +++ b/Projects/UOContent/Multis/HousePlacement.cs @@ -4,358 +4,358 @@ using Server.Spells; namespace Server.Multis { - public enum HousePlacementResult - { - Valid, - BadRegion, - BadLand, - BadStatic, - BadItem, - NoSurface, - BadRegionHidden, - BadRegionTemp, - InvalidCastleKeep, - BadRegionRaffle - } - - public class HousePlacement - { - private const int YardSize = 5; - - // Any land tile which matches one of these ID numbers is considered a road and cannot be placed over. - private static readonly int[] m_RoadIDs = + public enum HousePlacementResult { - 0x0071, 0x0078, - 0x00E8, 0x00EB, - 0x07AE, 0x07B1, - 0x3FF4, 0x3FF4, - 0x3FF8, 0x3FFB, - 0x0442, 0x0479, // Sand stones - 0x0501, 0x0510, // Sand stones - 0x0009, 0x0015, // Furrows - 0x0150, 0x015C // Furrows - }; + Valid, + BadRegion, + BadLand, + BadStatic, + BadItem, + NoSurface, + BadRegionHidden, + BadRegionTemp, + InvalidCastleKeep, + BadRegionRaffle + } - public static HousePlacementResult Check(Mobile from, int multiID, Point3D center, out List toMove) + public class HousePlacement { - // If this spot is considered valid, every item and mobile in this list will be moved under the house sign - toMove = new List(); + private const int YardSize = 5; - Map map = from.Map; - - if (map == null || map == Map.Internal) - return HousePlacementResult.BadLand; // A house cannot go here - - if (from.AccessLevel >= AccessLevel.GameMaster) - return HousePlacementResult.Valid; // Staff can place anywhere - - if (map == Map.Ilshenar || SpellHelper.IsFeluccaT2A(map, center)) - return HousePlacementResult.BadRegion; // No houses in Ilshenar/T2A - - if (map == Map.Malas && (multiID == 0x007C || multiID == 0x007E)) - return HousePlacementResult.InvalidCastleKeep; - - if (Region.Find(center, map).IsPartOf()) - return HousePlacementResult.BadRegion; - - // This holds data describing the internal structure of the house - MultiComponentList mcl = MultiData.GetComponents(multiID); - - if (multiID >= 0x13EC && multiID < 0x1D00) - HouseFoundation.AddStairsTo(ref mcl); // this is a AOS house, add the stairs - - // Location of the nortwest-most corner of the house - Point3D start = new Point3D(center.X + mcl.Min.X, center.Y + mcl.Min.Y, center.Z); - - // These are storage lists. They hold items and mobiles found in the map for further processing - List items = new List(); - List mobiles = new List(); - - // These are also storage lists. They hold location values indicating the yard and border locations. - List yard = new List(), borders = new List(); - - /* RULES: - * - * 1) All tiles which are around the -outside- of the foundation must not have anything impassable. - * 2) No impassable object or land tile may come in direct contact with any part of the house. - * 3) Five tiles from the front and back of the house must be completely clear of all house tiles. - * 4) The foundation must rest flatly on a surface. Any bumps around the foundation are not allowed. - * 5) No foundation tile may reside over terrain which is viewed as a road. - */ - - for (int x = 0; x < mcl.Width; ++x) - for (int y = 0; y < mcl.Height; ++y) + // Any land tile which matches one of these ID numbers is considered a road and cannot be placed over. + private static readonly int[] m_RoadIDs = { - int tileX = start.X + x; - int tileY = start.Y + y; + 0x0071, 0x0078, + 0x00E8, 0x00EB, + 0x07AE, 0x07B1, + 0x3FF4, 0x3FF4, + 0x3FF8, 0x3FFB, + 0x0442, 0x0479, // Sand stones + 0x0501, 0x0510, // Sand stones + 0x0009, 0x0015, // Furrows + 0x0150, 0x015C // Furrows + }; - StaticTile[] addTiles = mcl.Tiles[x][y]; + public static HousePlacementResult Check(Mobile from, int multiID, Point3D center, out List toMove) + { + // If this spot is considered valid, every item and mobile in this list will be moved under the house sign + toMove = new List(); - if (addTiles.Length == 0) - continue; // There are no tiles here, continue checking somewhere else + var map = from.Map; - Point3D testPoint = new Point3D(tileX, tileY, center.Z); + if (map == null || map == Map.Internal) + return HousePlacementResult.BadLand; // A house cannot go here - Region reg = Region.Find(testPoint, map); + if (from.AccessLevel >= AccessLevel.GameMaster) + return HousePlacementResult.Valid; // Staff can place anywhere - if (!reg.AllowHousing(from, testPoint)) // Cannot place houses in dungeons, towns, treasure map areas etc - { - if (reg.IsPartOf()) - return HousePlacementResult.BadRegionTemp; + if (map == Map.Ilshenar || SpellHelper.IsFeluccaT2A(map, center)) + return HousePlacementResult.BadRegion; // No houses in Ilshenar/T2A - if (reg.IsPartOf() || reg.IsPartOf()) - return HousePlacementResult.BadRegionHidden; + if (map == Map.Malas && (multiID == 0x007C || multiID == 0x007E)) + return HousePlacementResult.InvalidCastleKeep; - if (reg.IsPartOf()) - return HousePlacementResult.BadRegionRaffle; + if (Region.Find(center, map).IsPartOf()) + return HousePlacementResult.BadRegion; - return HousePlacementResult.BadRegion; - } + // This holds data describing the internal structure of the house + var mcl = MultiData.GetComponents(multiID); - LandTile landTile = map.Tiles.GetLandTile(tileX, tileY); - int landID = landTile.ID & TileData.MaxLandValue; + if (multiID >= 0x13EC && multiID < 0x1D00) + HouseFoundation.AddStairsTo(ref mcl); // this is a AOS house, add the stairs - StaticTile[] oldTiles = map.Tiles.GetStaticTiles(tileX, tileY, true); + // Location of the nortwest-most corner of the house + var start = new Point3D(center.X + mcl.Min.X, center.Y + mcl.Min.Y, center.Z); - Sector sector = map.GetSector(tileX, tileY); + // These are storage lists. They hold items and mobiles found in the map for further processing + var items = new List(); + var mobiles = new List(); - items.Clear(); + // These are also storage lists. They hold location values indicating the yard and border locations. + List yard = new List(), borders = new List(); - for (int i = 0; i < sector.Items.Count; ++i) - { - Item item = sector.Items[i]; + /* RULES: + * + * 1) All tiles which are around the -outside- of the foundation must not have anything impassable. + * 2) No impassable object or land tile may come in direct contact with any part of the house. + * 3) Five tiles from the front and back of the house must be completely clear of all house tiles. + * 4) The foundation must rest flatly on a surface. Any bumps around the foundation are not allowed. + * 5) No foundation tile may reside over terrain which is viewed as a road. + */ - if (item.Visible && item.X == tileX && item.Y == tileY) - items.Add(item); - } - - mobiles.Clear(); - - for (int i = 0; i < sector.Mobiles.Count; ++i) - { - Mobile m = sector.Mobiles[i]; - - if (m.X == tileX && m.Y == tileY) - mobiles.Add(m); - } - - int landStartZ = 0, landAvgZ = 0, landTopZ = 0; - - map.GetAverageZ(tileX, tileY, ref landStartZ, ref landAvgZ, ref landTopZ); - - bool hasFoundation = false; - - for (int i = 0; i < addTiles.Length; ++i) - { - StaticTile addTile = addTiles[i]; - - if (addTile.ID == 0x1) // Nodraw - continue; - - TileFlag addTileFlags = TileData.ItemTable[addTile.ID & TileData.MaxItemValue].Flags; - - bool isFoundation = addTile.Z == 0 && (addTileFlags & TileFlag.Wall) != 0; - bool hasSurface = false; - - if (isFoundation) - hasFoundation = true; - - int addTileZ = center.Z + addTile.Z; - int addTileTop = addTileZ + addTile.Height; - - if ((addTileFlags & TileFlag.Surface) != 0) - addTileTop += 16; - - if (addTileTop > landStartZ && landAvgZ > addTileZ) - return HousePlacementResult.BadLand; // Broke rule #2 - - if (isFoundation && - (TileData.LandTable[landTile.ID & TileData.MaxLandValue].Flags & TileFlag.Impassable) == 0 && - landAvgZ == center.Z) - hasSurface = true; - - for (int j = 0; j < oldTiles.Length; ++j) - { - StaticTile oldTile = oldTiles[j]; - ItemData id = TileData.ItemTable[oldTile.ID & TileData.MaxItemValue]; - - if ((id.Impassable || (id.Surface && (id.Flags & TileFlag.Background) == 0)) && - addTileTop > oldTile.Z && oldTile.Z + id.CalcHeight > addTileZ) - return HousePlacementResult.BadStatic; // Broke rule #2 - /*else if (isFoundation && !hasSurface && (id.Flags & TileFlag.Surface) != 0 && (oldTile.Z + id.CalcHeight) == center.Z) - hasSurface = true;*/ - } - - for (int j = 0; j < items.Count; ++j) - { - Item item = items[j]; - ItemData id = item.ItemData; - - if (addTileTop > item.Z && item.Z + id.CalcHeight > addTileZ) - { - if (item.Movable) - toMove.Add(item); - else if (id.Impassable || (id.Surface && (id.Flags & TileFlag.Background) == 0)) - return HousePlacementResult.BadItem; // Broke rule #2 - } - - /*else if (isFoundation && !hasSurface && (id.Flags & TileFlag.Surface) != 0 && (item.Z + id.CalcHeight) == center.Z) + for (var x = 0; x < mcl.Width; ++x) + for (var y = 0; y < mcl.Height; ++y) { - hasSurface = true; - }*/ - } + var tileX = start.X + x; + var tileY = start.Y + y; - if (isFoundation && !hasSurface) - return HousePlacementResult.NoSurface; // Broke rule #4 + var addTiles = mcl.Tiles[x][y]; - for (int j = 0; j < mobiles.Count; ++j) - { - Mobile m = mobiles[j]; + if (addTiles.Length == 0) + continue; // There are no tiles here, continue checking somewhere else - if (addTileTop > m.Z && m.Z + 16 > addTileZ) - toMove.Add(m); - } - } + var testPoint = new Point3D(tileX, tileY, center.Z); - for (int i = 0; i < m_RoadIDs.Length; i += 2) - if (landID >= m_RoadIDs[i] && landID <= m_RoadIDs[i + 1]) - return HousePlacementResult.BadLand; // Broke rule #5 + var reg = Region.Find(testPoint, map); - if (hasFoundation) - { - for (int xOffset = -1; xOffset <= 1; ++xOffset) - for (int yOffset = -YardSize; yOffset <= YardSize; ++yOffset) - { - Point2D yardPoint = new Point2D(tileX + xOffset, tileY + yOffset); + if (!reg.AllowHousing(from, testPoint)) // Cannot place houses in dungeons, towns, treasure map areas etc + { + if (reg.IsPartOf()) + return HousePlacementResult.BadRegionTemp; - if (!yard.Contains(yardPoint)) - yard.Add(yardPoint); - } + if (reg.IsPartOf() || reg.IsPartOf()) + return HousePlacementResult.BadRegionHidden; - for (int xOffset = -1; xOffset <= 1; ++xOffset) - for (int yOffset = -1; yOffset <= 1; ++yOffset) - { - if (xOffset == 0 && yOffset == 0) - continue; + if (reg.IsPartOf()) + return HousePlacementResult.BadRegionRaffle; - // To ease this rule, we will not add to the border list if the tile here is under a base floor (z<=8) + return HousePlacementResult.BadRegion; + } - int vx = x + xOffset; - int vy = y + yOffset; + var landTile = map.Tiles.GetLandTile(tileX, tileY); + var landID = landTile.ID & TileData.MaxLandValue; - if (vx >= 0 && vx < mcl.Width && vy >= 0 && vy < mcl.Height) - { - StaticTile[] breakTiles = mcl.Tiles[vx][vy]; - bool shouldBreak = false; + var oldTiles = map.Tiles.GetStaticTiles(tileX, tileY, true); - for (int i = 0; !shouldBreak && i < breakTiles.Length; ++i) - { - StaticTile breakTile = breakTiles[i]; + var sector = map.GetSector(tileX, tileY); - if (breakTile.Height == 0 && breakTile.Z <= 8 && - TileData.ItemTable[breakTile.ID & TileData.MaxItemValue].Surface) - shouldBreak = true; - } + items.Clear(); - if (shouldBreak) - continue; + for (var i = 0; i < sector.Items.Count; ++i) + { + var item = sector.Items[i]; + + if (item.Visible && item.X == tileX && item.Y == tileY) + items.Add(item); + } + + mobiles.Clear(); + + for (var i = 0; i < sector.Mobiles.Count; ++i) + { + var m = sector.Mobiles[i]; + + if (m.X == tileX && m.Y == tileY) + mobiles.Add(m); + } + + int landStartZ = 0, landAvgZ = 0, landTopZ = 0; + + map.GetAverageZ(tileX, tileY, ref landStartZ, ref landAvgZ, ref landTopZ); + + var hasFoundation = false; + + for (var i = 0; i < addTiles.Length; ++i) + { + var addTile = addTiles[i]; + + if (addTile.ID == 0x1) // Nodraw + continue; + + var addTileFlags = TileData.ItemTable[addTile.ID & TileData.MaxItemValue].Flags; + + var isFoundation = addTile.Z == 0 && (addTileFlags & TileFlag.Wall) != 0; + var hasSurface = false; + + if (isFoundation) + hasFoundation = true; + + var addTileZ = center.Z + addTile.Z; + var addTileTop = addTileZ + addTile.Height; + + if ((addTileFlags & TileFlag.Surface) != 0) + addTileTop += 16; + + if (addTileTop > landStartZ && landAvgZ > addTileZ) + return HousePlacementResult.BadLand; // Broke rule #2 + + if (isFoundation && + (TileData.LandTable[landTile.ID & TileData.MaxLandValue].Flags & TileFlag.Impassable) == 0 && + landAvgZ == center.Z) + hasSurface = true; + + for (var j = 0; j < oldTiles.Length; ++j) + { + var oldTile = oldTiles[j]; + var id = TileData.ItemTable[oldTile.ID & TileData.MaxItemValue]; + + if ((id.Impassable || id.Surface && (id.Flags & TileFlag.Background) == 0) && + addTileTop > oldTile.Z && oldTile.Z + id.CalcHeight > addTileZ) + return HousePlacementResult.BadStatic; // Broke rule #2 + /*else if (isFoundation && !hasSurface && (id.Flags & TileFlag.Surface) != 0 && (oldTile.Z + id.CalcHeight) == center.Z) + hasSurface = true;*/ + } + + for (var j = 0; j < items.Count; ++j) + { + var item = items[j]; + var id = item.ItemData; + + if (addTileTop > item.Z && item.Z + id.CalcHeight > addTileZ) + { + if (item.Movable) + toMove.Add(item); + else if (id.Impassable || id.Surface && (id.Flags & TileFlag.Background) == 0) + return HousePlacementResult.BadItem; // Broke rule #2 + } + + /*else if (isFoundation && !hasSurface && (id.Flags & TileFlag.Surface) != 0 && (item.Z + id.CalcHeight) == center.Z) + { + hasSurface = true; + }*/ + } + + if (isFoundation && !hasSurface) + return HousePlacementResult.NoSurface; // Broke rule #4 + + for (var j = 0; j < mobiles.Count; ++j) + { + var m = mobiles[j]; + + if (addTileTop > m.Z && m.Z + 16 > addTileZ) + toMove.Add(m); + } + } + + for (var i = 0; i < m_RoadIDs.Length; i += 2) + if (landID >= m_RoadIDs[i] && landID <= m_RoadIDs[i + 1]) + return HousePlacementResult.BadLand; // Broke rule #5 + + if (hasFoundation) + { + for (var xOffset = -1; xOffset <= 1; ++xOffset) + for (var yOffset = -YardSize; yOffset <= YardSize; ++yOffset) + { + var yardPoint = new Point2D(tileX + xOffset, tileY + yOffset); + + if (!yard.Contains(yardPoint)) + yard.Add(yardPoint); + } + + for (var xOffset = -1; xOffset <= 1; ++xOffset) + for (var yOffset = -1; yOffset <= 1; ++yOffset) + { + if (xOffset == 0 && yOffset == 0) + continue; + + // To ease this rule, we will not add to the border list if the tile here is under a base floor (z<=8) + + var vx = x + xOffset; + var vy = y + yOffset; + + if (vx >= 0 && vx < mcl.Width && vy >= 0 && vy < mcl.Height) + { + var breakTiles = mcl.Tiles[vx][vy]; + var shouldBreak = false; + + for (var i = 0; !shouldBreak && i < breakTiles.Length; ++i) + { + var breakTile = breakTiles[i]; + + if (breakTile.Height == 0 && breakTile.Z <= 8 && + TileData.ItemTable[breakTile.ID & TileData.MaxItemValue].Surface) + shouldBreak = true; + } + + if (shouldBreak) + continue; + } + + var borderPoint = new Point2D(tileX + xOffset, tileY + yOffset); + + if (!borders.Contains(borderPoint)) + borders.Add(borderPoint); + } + } } - Point2D borderPoint = new Point2D(tileX + xOffset, tileY + yOffset); + for (var i = 0; i < borders.Count; ++i) + { + var borderPoint = borders[i]; - if (!borders.Contains(borderPoint)) - borders.Add(borderPoint); + var landTile = map.Tiles.GetLandTile(borderPoint.X, borderPoint.Y); + var landID = landTile.ID & TileData.MaxLandValue; + + if ((TileData.LandTable[landID].Flags & TileFlag.Impassable) != 0) + return HousePlacementResult.BadLand; + + for (var j = 0; j < m_RoadIDs.Length; j += 2) + if (landID >= m_RoadIDs[j] && landID <= m_RoadIDs[j + 1]) + return HousePlacementResult.BadLand; // Broke rule #5 + + var tiles = map.Tiles.GetStaticTiles(borderPoint.X, borderPoint.Y, true); + + for (var j = 0; j < tiles.Length; ++j) + { + var tile = tiles[j]; + var id = TileData.ItemTable[tile.ID & TileData.MaxItemValue]; + + if (id.Impassable || id.Surface && (id.Flags & TileFlag.Background) == 0 && + tile.Z + id.CalcHeight > center.Z + 2) + return HousePlacementResult.BadStatic; // Broke rule #1 + } + + var sector = map.GetSector(borderPoint.X, borderPoint.Y); + var sectorItems = sector.Items; + + for (var j = 0; j < sectorItems.Count; ++j) + { + var item = sectorItems[j]; + + if (item.X != borderPoint.X || item.Y != borderPoint.Y || item.Movable) + continue; + + var id = item.ItemData; + + if (id.Impassable || id.Surface && (id.Flags & TileFlag.Background) == 0 && + item.Z + id.CalcHeight > center.Z + 2) + return HousePlacementResult.BadItem; // Broke rule #1 + } + } + + var _sectors = new List(); + var _houses = new List(); + + for (var i = 0; i < yard.Count; i++) + { + var sector = map.GetSector(yard[i]); + + if (!_sectors.Contains(sector)) + { + _sectors.Add(sector); + + for (var j = 0; j < sector.Multis?.Count; j++) + if (sector.Multis[j] is BaseHouse) + { + var _house = (BaseHouse)sector.Multis[j]; + if (!_houses.Contains(_house)) _houses.Add(_house); + } + } + } + + for (var i = 0; i < yard.Count; ++i) + foreach (var b in _houses) + if (b.Contains(yard[i])) + return HousePlacementResult.BadStatic; // Broke rule #3 + /*Point2D yardPoint = yard[i]; + + IPooledEnumerable eable = map.GetMultiTilesAt( yardPoint.X, yardPoint.Y ); + + foreach ( StaticTile[] tile in eable ) + { + for ( int j = 0; j < tile.Length; ++j ) + { + if ((TileData.ItemTable[tile[j].ID & TileData.MaxItemValue].Flags & (TileFlag.Impassable | TileFlag.Surface)) != 0) + { + eable.Free(); + return HousePlacementResult.BadStatic; // Broke rule #3 + } + } } - } + + eable.Free();*/ + + return HousePlacementResult.Valid; } - - for (int i = 0; i < borders.Count; ++i) - { - Point2D borderPoint = borders[i]; - - LandTile landTile = map.Tiles.GetLandTile(borderPoint.X, borderPoint.Y); - int landID = landTile.ID & TileData.MaxLandValue; - - if ((TileData.LandTable[landID].Flags & TileFlag.Impassable) != 0) - return HousePlacementResult.BadLand; - - for (int j = 0; j < m_RoadIDs.Length; j += 2) - if (landID >= m_RoadIDs[j] && landID <= m_RoadIDs[j + 1]) - return HousePlacementResult.BadLand; // Broke rule #5 - - StaticTile[] tiles = map.Tiles.GetStaticTiles(borderPoint.X, borderPoint.Y, true); - - for (int j = 0; j < tiles.Length; ++j) - { - StaticTile tile = tiles[j]; - ItemData id = TileData.ItemTable[tile.ID & TileData.MaxItemValue]; - - if (id.Impassable || (id.Surface && (id.Flags & TileFlag.Background) == 0 && - tile.Z + id.CalcHeight > center.Z + 2)) - return HousePlacementResult.BadStatic; // Broke rule #1 - } - - Sector sector = map.GetSector(borderPoint.X, borderPoint.Y); - List sectorItems = sector.Items; - - for (int j = 0; j < sectorItems.Count; ++j) - { - Item item = sectorItems[j]; - - if (item.X != borderPoint.X || item.Y != borderPoint.Y || item.Movable) - continue; - - ItemData id = item.ItemData; - - if (id.Impassable || (id.Surface && (id.Flags & TileFlag.Background) == 0 && - item.Z + id.CalcHeight > center.Z + 2)) - return HousePlacementResult.BadItem; // Broke rule #1 - } - } - - List _sectors = new List(); - List _houses = new List(); - - for (int i = 0; i < yard.Count; i++) - { - Sector sector = map.GetSector(yard[i]); - - if (!_sectors.Contains(sector)) - { - _sectors.Add(sector); - - for (int j = 0; j < sector.Multis?.Count; j++) - if (sector.Multis[j] is BaseHouse) - { - BaseHouse _house = (BaseHouse)sector.Multis[j]; - if (!_houses.Contains(_house)) _houses.Add(_house); - } - } - } - - for (int i = 0; i < yard.Count; ++i) - foreach (BaseHouse b in _houses) - if (b.Contains(yard[i])) - return HousePlacementResult.BadStatic; // Broke rule #3 - /*Point2D yardPoint = yard[i]; - - IPooledEnumerable eable = map.GetMultiTilesAt( yardPoint.X, yardPoint.Y ); - - foreach ( StaticTile[] tile in eable ) - { - for ( int j = 0; j < tile.Length; ++j ) - { - if ((TileData.ItemTable[tile[j].ID & TileData.MaxItemValue].Flags & (TileFlag.Impassable | TileFlag.Surface)) != 0) - { - eable.Free(); - return HousePlacementResult.BadStatic; // Broke rule #3 - } - } - } - - eable.Free();*/ - - return HousePlacementResult.Valid; } - } } diff --git a/Projects/UOContent/Multis/HousePlacementTool.cs b/Projects/UOContent/Multis/HousePlacementTool.cs index fbfbf19fb..78b826611 100644 --- a/Projects/UOContent/Multis/HousePlacementTool.cs +++ b/Projects/UOContent/Multis/HousePlacementTool.cs @@ -11,891 +11,2238 @@ using Server.Utilities; namespace Server.Items { - public class HousePlacementTool : Item - { - [Constructible] - public HousePlacementTool() : base(0x14F6) + public class HousePlacementTool : Item { - Weight = 3.0; - LootType = LootType.Blessed; - } - - public HousePlacementTool(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1060651; // a house placement tool - - public override void OnDoubleClick(Mobile from) - { - if (IsChildOf(from.Backpack)) - from.SendGump(new HousePlacementCategoryGump(from)); - else - from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - if (Weight == 0.0) - Weight = 3.0; - } - } - - public class HousePlacementCategoryGump : Gump - { - private const int LabelColor = 0x7FFF; - private const int LabelColorDisabled = 0x4210; - private readonly Mobile m_From; - - public HousePlacementCategoryGump(Mobile from) : base(50, 50) - { - m_From = from; - - from.CloseGump(); - from.CloseGump(); - - AddPage(0); - - AddBackground(0, 0, 270, 145, 5054); - - AddImageTiled(10, 10, 250, 125, 2624); - AddAlphaRegion(10, 10, 250, 125); - - AddHtmlLocalized(10, 10, 250, 20, 1060239, LabelColor); //
HOUSE PLACEMENT TOOL
- - AddButton(10, 110, 4017, 4019, 0); - AddHtmlLocalized(45, 110, 150, 20, 3000363, LabelColor); // Close - - AddButton(10, 40, 4005, 4007, 1); - AddHtmlLocalized(45, 40, 200, 20, 1060390, LabelColor); // Classic Houses - - AddButton(10, 60, 4005, 4007, 2); - AddHtmlLocalized(45, 60, 200, 20, 1060391, LabelColor); // 2-Story Customizable Houses - - AddButton(10, 80, 4005, 4007, 3); - AddHtmlLocalized(45, 80, 200, 20, 1060392, LabelColor); // 3-Story Customizable Houses - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (!m_From.CheckAlive() || m_From.Backpack?.FindItemByType() == null) - return; - - switch (info.ButtonID) - { - case 1: // Classic Houses - { - // TODO: Add flag to use ClassicHouses or EJ - m_From.SendGump(new HousePlacementListGump(m_From, HousePlacementEntry.HousesEJ)); - break; - } - case 2: // 2-Story Customizable Houses - { - m_From.SendGump(new HousePlacementListGump(m_From, HousePlacementEntry.TwoStoryFoundations)); - break; - } - case 3: // 3-Story Customizable Houses - { - m_From.SendGump(new HousePlacementListGump(m_From, HousePlacementEntry.ThreeStoryFoundations)); - break; - } - } - } - } - - public class HousePlacementListGump : Gump - { - private const int LabelColor = 0x7FFF; - private const int LabelHue = 0x480; - private readonly HousePlacementEntry[] m_Entries; - private readonly Mobile m_From; - - public HousePlacementListGump(Mobile from, HousePlacementEntry[] entries) : base(50, 50) - { - m_From = from; - m_Entries = entries; - - from.CloseGump(); - from.CloseGump(); - - AddPage(0); - - AddBackground(0, 0, 520, 420, 5054); - - AddImageTiled(10, 10, 500, 20, 2624); - AddAlphaRegion(10, 10, 500, 20); - - AddHtmlLocalized(10, 10, 500, 20, 1060239, LabelColor); //
HOUSE PLACEMENT TOOL
- - AddImageTiled(10, 40, 500, 20, 2624); - AddAlphaRegion(10, 40, 500, 20); - - AddHtmlLocalized(50, 40, 225, 20, 1060235, LabelColor); // House Description - AddHtmlLocalized(275, 40, 75, 20, 1060236, LabelColor); // Storage - AddHtmlLocalized(350, 40, 75, 20, 1060237, LabelColor); // Lockdowns - AddHtmlLocalized(425, 40, 75, 20, 1060034, LabelColor); // Cost - - AddImageTiled(10, 70, 500, 280, 2624); - AddAlphaRegion(10, 70, 500, 280); - - AddImageTiled(10, 360, 500, 20, 2624); - AddAlphaRegion(10, 360, 500, 20); - - AddHtmlLocalized(10, 360, 250, 20, 1060645, LabelColor); // Bank Balance: - AddLabel(250, 360, LabelHue, Banker.GetBalance(from).ToString()); - - AddImageTiled(10, 390, 500, 20, 2624); - AddAlphaRegion(10, 390, 500, 20); - - AddButton(10, 390, 4017, 4019, 0); - AddHtmlLocalized(50, 390, 100, 20, 3000363, LabelColor); // Close - - for (int i = 0; i < entries.Length; ++i) - { - int page = 1 + i / 14; - int index = i % 14; - - if (index == 0) + [Constructible] + public HousePlacementTool() : base(0x14F6) { - if (page > 1) - { - AddButton(450, 390, 4005, 4007, 0, GumpButtonType.Page, page); - AddHtmlLocalized(400, 390, 100, 20, 3000406, LabelColor); // Next - } - - AddPage(page); - - if (page > 1) - { - AddButton(200, 390, 4014, 4016, 0, GumpButtonType.Page, page - 1); - AddHtmlLocalized(250, 390, 100, 20, 3000405, LabelColor); // Previous - } + Weight = 3.0; + LootType = LootType.Blessed; } - HousePlacementEntry entry = entries[i]; + public HousePlacementTool(Serial serial) : base(serial) + { + } - int y = 70 + index * 20; + public override int LabelNumber => 1060651; // a house placement tool - AddButton(10, y, 4005, 4007, 1 + i); - AddHtmlLocalized(50, y, 225, 20, entry.Description, LabelColor); - AddLabel(275, y, LabelHue, entry.Storage.ToString()); - AddLabel(350, y, LabelHue, entry.Lockdowns.ToString()); - AddLabel(425, y, LabelHue, entry.Cost.ToString()); - } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - if (!m_From.CheckAlive() || m_From.Backpack?.FindItemByType() == null) - return; - - int index = info.ButtonID - 1; - - if (index >= 0 && index < m_Entries.Length) - { - if (m_From.AccessLevel < AccessLevel.GameMaster && BaseHouse.HasAccountHouse(m_From)) - m_From.SendLocalizedMessage(501271); // You already own a house, you may not place another! - else - m_From.Target = new NewHousePlacementTarget(m_Entries, m_Entries[index]); - } - else - { - m_From.SendGump(new HousePlacementCategoryGump(m_From)); - } - } - } - - public class NewHousePlacementTarget : MultiTarget - { - private readonly HousePlacementEntry[] m_Entries; - private readonly HousePlacementEntry m_Entry; - - private bool m_Placed; - - public NewHousePlacementTarget(HousePlacementEntry[] entries, HousePlacementEntry entry) : base(entry.MultiID, - entry.Offset) - { - Range = 14; - - m_Entries = entries; - m_Entry = entry; - } - - protected override void OnTarget(Mobile from, object o) - { - if (!from.CheckAlive() || from.Backpack?.FindItemByType() == null) - return; - - if (o is IPoint3D ip) - { - if (ip is Item item) - ip = item.GetWorldTop(); - - Point3D p = new Point3D(ip); - - Region reg = Region.Find(new Point3D(p), from.Map); - - if (from.AccessLevel >= AccessLevel.GameMaster || reg.AllowHousing(from, p)) - m_Placed = m_Entry.OnPlacement(from, p); - else if (reg.IsPartOf()) - from.SendLocalizedMessage( - 501270); // Lord British has decreed a 'no build' period, thus you cannot build this house at this time. - else if (reg.IsPartOf() || reg.IsPartOf()) - from.SendLocalizedMessage( - 1043287); // The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain. - else if (reg.IsPartOf()) - from.SendLocalizedMessage(1150493); // You must have a deed for this plot of land in order to build here. - else - from.SendLocalizedMessage(501265); // Housing can not be created in this area. - } - } - - protected override void OnTargetFinish(Mobile from) - { - if (!from.CheckAlive() || from.Backpack?.FindItemByType() == null) - return; - - if (!m_Placed) - from.SendGump(new HousePlacementListGump(from, m_Entries)); - } - } - - public class HousePlacementEntry - { - private static readonly Dictionary m_Table; - private readonly int m_Lockdowns; - private readonly int m_NewLockdowns; - private readonly int m_NewStorage; - private readonly int m_Storage; - - static HousePlacementEntry() - { - m_Table = new Dictionary(); - - FillTable(ClassicHouses); - FillTable(TwoStoryFoundations); - FillTable(ThreeStoryFoundations); - } - - public HousePlacementEntry(Type type, int description, int storage, int lockdowns, int newStorage, int newLockdowns, - int vendors, int cost, int xOffset, int yOffset, int zOffset, int multiID) - { - Type = type; - Description = description; - m_Storage = storage; - m_Lockdowns = lockdowns; - m_NewStorage = newStorage; - m_NewLockdowns = newLockdowns; - Vendors = vendors; - Cost = cost; - - Offset = new Point3D(xOffset, yOffset, zOffset); - - MultiID = multiID; - } - - public Type Type { get; } - - public int Description { get; } - - public int Storage => BaseHouse.NewVendorSystem ? m_NewStorage : m_Storage; - public int Lockdowns => BaseHouse.NewVendorSystem ? m_NewLockdowns : m_Lockdowns; - public int Vendors { get; } - - public int Cost { get; } - - public int MultiID { get; } - - public Point3D Offset { get; } - - public static HousePlacementEntry[] ClassicHouses { get; } = - { - new HousePlacementEntry(typeof(SmallOldHouse), 1011303, 425, 212, 489, 244, 10, 37000, 0, 4, 0, 0x0064), - new HousePlacementEntry(typeof(SmallOldHouse), 1011304, 425, 212, 489, 244, 10, 37000, 0, 4, 0, 0x0066), - new HousePlacementEntry(typeof(SmallOldHouse), 1011305, 425, 212, 489, 244, 10, 36750, 0, 4, 0, 0x0068), - new HousePlacementEntry(typeof(SmallOldHouse), 1011306, 425, 212, 489, 244, 10, 35250, 0, 4, 0, 0x006A), - new HousePlacementEntry(typeof(SmallOldHouse), 1011307, 425, 212, 489, 244, 10, 36750, 0, 4, 0, 0x006C), - new HousePlacementEntry(typeof(SmallOldHouse), 1011308, 425, 212, 489, 244, 10, 36750, 0, 4, 0, 0x006E), - new HousePlacementEntry(typeof(SmallShop), 1011321, 425, 212, 489, 244, 10, 50500, -1, 4, 0, 0x00A0), - new HousePlacementEntry(typeof(SmallShop), 1011322, 425, 212, 489, 244, 10, 52500, 0, 4, 0, 0x00A2), - new HousePlacementEntry(typeof(SmallTower), 1011317, 580, 290, 667, 333, 14, 73500, 3, 4, 0, 0x0098), - new HousePlacementEntry(typeof(TwoStoryVilla), 1011319, 1100, 550, 1265, 632, 24, 113750, 3, 6, 0, 0x009E), - new HousePlacementEntry(typeof(SandStonePatio), 1011320, 850, 425, 1265, 632, 24, 76500, -1, 4, 0, 0x009C), - new HousePlacementEntry(typeof(LogCabin), 1011318, 1100, 550, 1265, 632, 24, 81750, 1, 6, 0, 0x009A), - new HousePlacementEntry(typeof(GuildHouse), 1011309, 1370, 685, 1576, 788, 28, 131500, -1, 7, 0, 0x0074), - new HousePlacementEntry(typeof(TwoStoryHouse), 1011310, 1370, 685, 1576, 788, 28, 162750, -3, 7, 0, 0x0076), - new HousePlacementEntry(typeof(TwoStoryHouse), 1011311, 1370, 685, 1576, 788, 28, 162000, -3, 7, 0, 0x0078), - new HousePlacementEntry(typeof(LargePatioHouse), 1011315, 1370, 685, 1576, 788, 28, 129250, -4, 7, 0, 0x008C), - new HousePlacementEntry(typeof(LargeMarbleHouse), 1011316, 1370, 685, 1576, 788, 28, 160500, -4, 7, 0, 0x0096), - new HousePlacementEntry(typeof(Tower), 1011312, 2119, 1059, 2437, 1218, 42, 366500, 0, 7, 0, 0x007A), - new HousePlacementEntry(typeof(Keep), 1011313, 2625, 1312, 3019, 1509, 52, 572750, 0, 11, 0, 0x007C), - new HousePlacementEntry(typeof(Castle), 1011314, 4076, 2038, 4688, 2344, 78, 865250, 0, 16, 0, 0x007E) - }; - - public static HousePlacementEntry[] HousesEJ { get; } = { - new HousePlacementEntry(typeof(SmallOldHouse), 1011303, 425, 212, 489, 244, 10, 36750, 0, 4, 0, 0x0064), - new HousePlacementEntry(typeof(SmallOldHouse), 1011304, 425, 212, 489, 244, 10, 36750, 0, 4, 0, 0x0066), - new HousePlacementEntry(typeof(SmallOldHouse), 1011305, 425, 212, 489, 244, 10, 36500, 0, 4, 0, 0x0068), - new HousePlacementEntry(typeof(SmallOldHouse), 1011306, 425, 212, 489, 244, 10, 35000, 0, 4, 0, 0x006A), - new HousePlacementEntry(typeof(SmallOldHouse), 1011307, 425, 212, 489, 244, 10, 36500, 0, 4, 0, 0x006C), - new HousePlacementEntry(typeof(SmallOldHouse), 1011308, 425, 212, 489, 244, 10, 36500, 0, 4, 0, 0x006E), - new HousePlacementEntry(typeof(SmallShop), 1011321, 425, 212, 489, 244, 10, 50250, -1, 4, 0, 0x00A0), - new HousePlacementEntry(typeof(SmallShop), 1011322, 425, 212, 489, 244, 10, 52250, 0, 4, 0, 0x00A2), - new HousePlacementEntry(typeof(SmallTower), 1011317, 580, 290, 667, 333, 14, 73250, 3, 4, 0, 0x0098), - new HousePlacementEntry(typeof(TwoStoryVilla), 1011319, 1100, 550, 1265, 632, 24, 113500, 3, 6, 0, 0x009E), - new HousePlacementEntry(typeof(SandStonePatio), 1011320, 850, 425, 1265, 632, 24, 76250, -1, 4, 0, 0x009C), - new HousePlacementEntry(typeof(LogCabin), 1011318, 1100, 550, 1265, 632, 24, 81250, 1, 6, 0, 0x009A), - new HousePlacementEntry(typeof(GuildHouse), 1011309, 1370, 685, 1576, 788, 28, 131250, -1, 7, 0, 0x0074), - new HousePlacementEntry(typeof(TwoStoryHouse), 1011310, 1370, 685, 1576, 788, 28, 162500, -3, 7, 0, 0x0076), - new HousePlacementEntry(typeof(TwoStoryHouse), 1011311, 1370, 685, 1576, 788, 28, 162750, -3, 7, 0, 0x0078), - new HousePlacementEntry(typeof(LargePatioHouse), 1011315, 1370, 685, 1576, 788, 28, 129000, -4, 7, 0, 0x008C), - new HousePlacementEntry(typeof(LargeMarbleHouse), 1011316, 1370, 685, 1576, 788, 28, 160250, -4, 7, 0, 0x0096), - new HousePlacementEntry(typeof(Tower), 1011312, 2119, 1059, 2437, 1218, 42, 366250, 0, 7, 0, 0x007A), - new HousePlacementEntry(typeof(Keep), 1011313, 2625, 1312, 3019, 1509, 52, 562500, 0, 11, 0, 0x007C), - new HousePlacementEntry(typeof(Castle), 1011314, 4076, 2038, 4688, 2344, 78, 865000, 0, 16, 0, 0x007E), - - new HousePlacementEntry(typeof(TrinsicKeep), 1158748, 2625, 1312, 3019, 1509, 52, 29643750, 0, 11, 0, 0x147E), - new HousePlacementEntry(typeof(GothicRoseCastle), 1158749, 4076, 2038, 4688, 2344, 78, 44808750, 0, 16, 0, 0x147F), - new HousePlacementEntry(typeof(ElsaCastle), 1158750, 4076, 2038, 4688, 2344, 78, 45450000, 0, 16, 0, 0x1480), - new HousePlacementEntry(typeof(Spires), 1158761, 4076, 2038, 4688, 2344, 78, 47025000, 0, 16, 0, 0x1481), - new HousePlacementEntry(typeof(CastleOfOceania), 1158760, 4076, 2038, 4688, 2344, 78, 48971250, 0, 16, 0, 0x1482), - new HousePlacementEntry(typeof(FeudalCastle), 1158762, 4076, 2038, 4688, 2344, 78, 27337500, 0, 16, 0, 0x1483), - new HousePlacementEntry(typeof(RobinsNest), 1158850, 2625, 1312, 3019, 1509, 52, 25301250, 0, 11, 0, 0x1484), - new HousePlacementEntry(typeof(TraditionalKeep), 1158851, 2625, 1312, 3019, 1509, 52, 26685000, 0, 11, 0, 0x1485), - new HousePlacementEntry(typeof(VillaCrowley), 1158852, 2625, 1312, 3019, 1509, 52, 21813750, 0, 11, 0, 0x1486), - new HousePlacementEntry(typeof(DarkthornKeep), 1158853, 2625, 1312, 3019, 1509, 52, 27990000, 0, 11, 0, 0x1487), - new HousePlacementEntry(typeof(SandalwoodKeep), 1158854, 2625, 1312, 3019, 1509, 52, 23456250, 0, 11, 0, 0x1488), - new HousePlacementEntry(typeof(CasaMoga), 1158855, 2625, 1312, 3019, 1509, 52, 26313750, 0, 11, 0, 0x1489), - - new HousePlacementEntry(typeof(RobinsRoost), 1158960, 4076, 2038, 4688, 2344, 78, 43863750, 0, 16, 0, 0x148A), - new HousePlacementEntry(typeof(Camelot), 1158961, 4076, 2038, 4688, 2344, 78, 47092500, 0, 16, 0, 0x148B), - new HousePlacementEntry(typeof(LacrimaeInCaelo), 1158962, 4076, 2038, 4688, 2344, 78, 45315000, 0, 16, 0, 0x148C), - new HousePlacementEntry(typeof(OkinawaSweetDreamCastle), 1158963, 4076, 2038, 4688, 2344, 78, 40128750, 0, 16, 0, 0x148D), - new HousePlacementEntry(typeof(TheSandstoneCastle), 1158964, 4076, 2038, 4688, 2344, 78, 48690000, 0, 16, 0, 0x148E), - new HousePlacementEntry(typeof(GrimswindSisters), 1158965, 4076, 2038, 4688, 2344, 78, 42142500, 0, 16, 0, 0x148F) - }; - - public static HousePlacementEntry[] TwoStoryFoundations { get; } = - { - new HousePlacementEntry(typeof(HouseFoundation), 1060241, 425, 212, 489, 244, 10, 30500, 0, 4, 0, - 0x13EC), // 7x7 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060242, 580, 290, 667, 333, 14, 34500, 0, 5, 0, - 0x13ED), // 7x8 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060243, 650, 325, 748, 374, 16, 38500, 0, 5, 0, - 0x13EE), // 7x9 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060244, 700, 350, 805, 402, 16, 42500, 0, 6, 0, - 0x13EF), // 7x10 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060245, 750, 375, 863, 431, 16, 46500, 0, 6, 0, - 0x13F0), // 7x11 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060246, 800, 400, 920, 460, 18, 50500, 0, 7, 0, - 0x13F1), // 7x12 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060253, 580, 290, 667, 333, 14, 34500, 0, 4, 0, - 0x13F8), // 8x7 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060254, 650, 325, 748, 374, 16, 39000, 0, 5, 0, - 0x13F9), // 8x8 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060255, 700, 350, 805, 402, 16, 43500, 0, 5, 0, - 0x13FA), // 8x9 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060256, 750, 375, 863, 431, 16, 48000, 0, 6, 0, - 0x13FB), // 8x10 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060257, 800, 400, 920, 460, 18, 52500, 0, 6, 0, - 0x13FC), // 8x11 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060258, 850, 425, 1265, 632, 24, 57000, 0, 7, 0, - 0x13FD), // 8x12 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060259, 1100, 550, 1265, 632, 24, 61500, 0, 7, 0, - 0x13FE), // 8x13 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060265, 650, 325, 748, 374, 16, 38500, 0, 4, 0, - 0x1404), // 9x7 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060266, 700, 350, 805, 402, 16, 43500, 0, 5, 0, - 0x1405), // 9x8 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060267, 750, 375, 863, 431, 16, 48500, 0, 5, 0, - 0x1406), // 9x9 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060268, 800, 400, 920, 460, 18, 53500, 0, 6, 0, - 0x1407), // 9x10 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060269, 850, 425, 1265, 632, 24, 58500, 0, 6, 0, - 0x1408), // 9x11 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060270, 1100, 550, 1265, 632, 24, 63500, 0, 7, 0, - 0x1409), // 9x12 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060271, 1100, 550, 1265, 632, 24, 68500, 0, 7, 0, - 0x140A), // 9x13 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060277, 700, 350, 805, 402, 16, 42500, 0, 4, 0, - 0x1410), // 10x7 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060278, 750, 375, 863, 431, 16, 48000, 0, 5, 0, - 0x1411), // 10x8 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060279, 800, 400, 920, 460, 18, 53500, 0, 5, 0, - 0x1412), // 10x9 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060280, 850, 425, 1265, 632, 24, 59000, 0, 6, 0, - 0x1413), // 10x10 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060281, 1100, 550, 1265, 632, 24, 64500, 0, 6, 0, - 0x1414), // 10x11 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060282, 1100, 550, 1265, 632, 24, 70000, 0, 7, 0, - 0x1415), // 10x12 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060283, 1150, 575, 1323, 661, 24, 75500, 0, 7, 0, - 0x1416), // 10x13 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060289, 750, 375, 863, 431, 16, 46500, 0, 4, 0, - 0x141C), // 11x7 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060290, 800, 400, 920, 460, 18, 52500, 0, 5, 0, - 0x141D), // 11x8 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060291, 850, 425, 1265, 632, 24, 58500, 0, 5, 0, - 0x141E), // 11x9 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060292, 1100, 550, 1265, 632, 24, 64500, 0, 6, 0, - 0x141F), // 11x10 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060293, 1100, 550, 1265, 632, 24, 70500, 0, 6, 0, - 0x1420), // 11x11 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060294, 1150, 575, 1323, 661, 24, 76500, 0, 7, 0, - 0x1421), // 11x12 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060295, 1200, 600, 1380, 690, 26, 82500, 0, 7, 0, - 0x1422), // 11x13 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060301, 800, 400, 920, 460, 18, 50500, 0, 4, 0, - 0x1428), // 12x7 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060302, 850, 425, 1265, 632, 24, 57000, 0, 5, 0, - 0x1429), // 12x8 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060303, 1100, 550, 1265, 632, 24, 63500, 0, 5, 0, - 0x142A), // 12x9 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060304, 1100, 550, 1265, 632, 24, 70000, 0, 6, 0, - 0x142B), // 12x10 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060305, 1150, 575, 1323, 661, 24, 76500, 0, 6, 0, - 0x142C), // 12x11 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060306, 1200, 600, 1380, 690, 26, 83000, 0, 7, 0, - 0x142D), // 12x12 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060307, 1250, 625, 1438, 719, 26, 89500, 0, 7, 0, - 0x142E), // 12x13 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060314, 1100, 550, 1265, 632, 24, 61500, 0, 5, 0, - 0x1435), // 13x8 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060315, 1100, 550, 1265, 632, 24, 68500, 0, 5, 0, - 0x1436), // 13x9 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060316, 1150, 575, 1323, 661, 24, 75500, 0, 6, 0, - 0x1437), // 13x10 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060317, 1200, 600, 1380, 690, 26, 82500, 0, 6, 0, - 0x1438), // 13x11 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060318, 1250, 625, 1438, 719, 26, 89500, 0, 7, 0, - 0x1439), // 13x12 2-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060319, 1300, 650, 1495, 747, 28, 96500, 0, 7, 0, - 0x143A) // 13x13 2-Story Customizable House - }; - - public static HousePlacementEntry[] ThreeStoryFoundations { get; } = - { - new HousePlacementEntry(typeof(HouseFoundation), 1060272, 1150, 575, 1323, 661, 24, 73500, 0, 8, 0, - 0x140B), // 9x14 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060284, 1200, 600, 1380, 690, 26, 81000, 0, 8, 0, - 0x1417), // 10x14 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060285, 1250, 625, 1438, 719, 26, 86500, 0, 8, 0, - 0x1418), // 10x15 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060296, 1250, 625, 1438, 719, 26, 88500, 0, 8, 0, - 0x1423), // 11x14 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060297, 1300, 650, 1495, 747, 28, 94500, 0, 8, 0, - 0x1424), // 11x15 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060298, 1350, 675, 1553, 776, 28, 100500, 0, 9, 0, - 0x1425), // 11x16 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060308, 1300, 650, 1495, 747, 28, 96000, 0, 8, 0, - 0x142F), // 12x14 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060309, 1350, 675, 1553, 776, 28, 102500, 0, 8, 0, - 0x1430), // 12x15 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060310, 1370, 685, 1576, 788, 28, 109000, 0, 9, 0, - 0x1431), // 12x16 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060311, 1370, 685, 1576, 788, 28, 115500, 0, 9, 0, - 0x1432), // 12x17 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060320, 1350, 675, 1553, 776, 28, 103500, 0, 8, 0, - 0x143B), // 13x14 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060321, 1370, 685, 1576, 788, 28, 110500, 0, 8, 0, - 0x143C), // 13x15 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060322, 1370, 685, 1576, 788, 28, 117500, 0, 9, 0, - 0x143D), // 13x16 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060323, 2119, 1059, 2437, 1218, 42, 124500, 0, 9, 0, - 0x143E), // 13x17 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060324, 2119, 1059, 2437, 1218, 42, 131500, 0, 10, 0, - 0x143F), // 13x18 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060327, 1150, 575, 1323, 661, 24, 73500, 0, 5, 0, - 0x1442), // 14x9 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060328, 1200, 600, 1380, 690, 26, 81000, 0, 6, 0, - 0x1443), // 14x10 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060329, 1250, 625, 1438, 719, 26, 88500, 0, 6, 0, - 0x1444), // 14x11 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060330, 1300, 650, 1495, 747, 28, 96000, 0, 7, 0, - 0x1445), // 14x12 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060331, 1350, 675, 1553, 776, 28, 103500, 0, 7, 0, - 0x1446), // 14x13 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060332, 1370, 685, 1576, 788, 28, 111000, 0, 8, 0, - 0x1447), // 14x14 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060333, 1370, 685, 1576, 788, 28, 118500, 0, 8, 0, - 0x1448), // 14x15 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060334, 2119, 1059, 2437, 1218, 42, 126000, 0, 9, 0, - 0x1449), // 14x16 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060335, 2119, 1059, 2437, 1218, 42, 133500, 0, 9, 0, - 0x144A), // 14x17 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060336, 2119, 1059, 2437, 1218, 42, 141000, 0, 10, 0, - 0x144B), // 14x18 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060340, 1250, 625, 1438, 719, 26, 86500, 0, 6, 0, - 0x144F), // 15x10 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060341, 1300, 650, 1495, 747, 28, 94500, 0, 6, 0, - 0x1450), // 15x11 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060342, 1350, 675, 1553, 776, 28, 102500, 0, 7, 0, - 0x1451), // 15x12 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060343, 1370, 685, 1576, 788, 28, 110500, 0, 7, 0, - 0x1452), // 15x13 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060344, 1370, 685, 1576, 788, 28, 118500, 0, 8, 0, - 0x1453), // 15x14 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060345, 2119, 1059, 2437, 1218, 42, 126500, 0, 8, 0, - 0x1454), // 15x15 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060346, 2119, 1059, 2437, 1218, 42, 134500, 0, 9, 0, - 0x1455), // 15x16 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060347, 2119, 1059, 2437, 1218, 42, 142500, 0, 9, 0, - 0x1456), // 15x17 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060348, 2119, 1059, 2437, 1218, 42, 150500, 0, 10, 0, - 0x1457), // 15x18 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060353, 1350, 675, 1553, 776, 28, 100500, 0, 6, 0, - 0x145C), // 16x11 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060354, 1370, 685, 1576, 788, 28, 109000, 0, 7, 0, - 0x145D), // 16x12 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060355, 1370, 685, 1576, 788, 28, 117500, 0, 7, 0, - 0x145E), // 16x13 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060356, 2119, 1059, 2437, 1218, 42, 126000, 0, 8, 0, - 0x145F), // 16x14 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060357, 2119, 1059, 2437, 1218, 42, 134500, 0, 8, 0, - 0x1460), // 16x15 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060358, 2119, 1059, 2437, 1218, 42, 143000, 0, 9, 0, - 0x1461), // 16x16 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060359, 2119, 1059, 2437, 1218, 42, 151500, 0, 9, 0, - 0x1462), // 16x17 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060360, 2119, 1059, 2437, 1218, 42, 160000, 0, 10, 0, - 0x1463), // 16x18 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060366, 1370, 685, 1576, 788, 28, 115500, 0, 7, 0, - 0x1469), // 17x12 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060367, 2119, 1059, 2437, 1218, 42, 124500, 0, 7, 0, - 0x146A), // 17x13 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060368, 2119, 1059, 2437, 1218, 42, 133500, 0, 8, 0, - 0x146B), // 17x14 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060369, 2119, 1059, 2437, 1218, 42, 142500, 0, 8, 0, - 0x146C), // 17x15 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060370, 2119, 1059, 2437, 1218, 42, 151500, 0, 9, 0, - 0x146D), // 17x16 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060371, 2119, 1059, 2437, 1218, 42, 160500, 0, 9, 0, - 0x146E), // 17x17 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060372, 2119, 1059, 2437, 1218, 42, 169500, 0, 10, 0, - 0x146F), // 17x18 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060379, 2119, 1059, 2437, 1218, 42, 131500, 0, 7, 0, - 0x1476), // 18x13 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060380, 2119, 1059, 2437, 1218, 42, 141000, 0, 8, 0, - 0x1477), // 18x14 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060381, 2119, 1059, 2437, 1218, 42, 150500, 0, 8, 0, - 0x1478), // 18x15 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060382, 2119, 1059, 2437, 1218, 42, 160000, 0, 9, 0, - 0x1479), // 18x16 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060383, 2119, 1059, 2437, 1218, 42, 169500, 0, 9, 0, - 0x147A), // 18x17 3-Story Customizable House - new HousePlacementEntry(typeof(HouseFoundation), 1060384, 2119, 1059, 2437, 1218, 42, 179000, 0, 10, 0, - 0x147B) // 18x18 3-Story Customizable House - }; - - public BaseHouse ConstructHouse(Mobile from) - { - try - { - object[] args; - - if (Type == typeof(HouseFoundation)) - args = new object[] { from, MultiID, m_Storage, m_Lockdowns }; - else if (Type == typeof(SmallOldHouse) || Type == typeof(SmallShop) || Type == typeof(TwoStoryHouse)) - args = new object[] { from, MultiID }; - else - args = new object[] { from }; - - return ActivatorUtil.CreateInstance(Type, args) as BaseHouse; - } - catch - { - // ignored - } - - return null; - } - - public void PlacementWarning_Callback(Mobile from, bool okay, PreviewHouse prevHouse) - { - if (!from.CheckAlive() || from.Backpack?.FindItemByType() == null) - return; - - if (!okay) - { - prevHouse.Delete(); - return; - } - - if (prevHouse.Deleted) - { - /* Too much time has passed and the test house you created has been deleted. - * Please try again! - */ - from.SendGump(new NoticeGump(1060637, 30720, 1060647, 32512, 320, 180)); - - return; - } - - Point3D center = prevHouse.Location; - - prevHouse.Delete(); - - // Point3D center = new Point3D( p.X - m_Offset.X, p.Y - m_Offset.Y, p.Z - m_Offset.Z ); - HousePlacementResult res = HousePlacement.Check(from, MultiID, center, out List toMove); - - switch (res) - { - case HousePlacementResult.Valid: - { - if (from.AccessLevel < AccessLevel.GameMaster && BaseHouse.HasAccountHouse(from)) - { - from.SendLocalizedMessage(501271); // You already own a house, you may not place another! - } + public override void OnDoubleClick(Mobile from) + { + if (IsChildOf(from.Backpack)) + from.SendGump(new HousePlacementCategoryGump(from)); else - { - BaseHouse house = ConstructHouse(from); + from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. + } - if (house == null) + 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 (Weight == 0.0) + Weight = 3.0; + } + } + + public class HousePlacementCategoryGump : Gump + { + private const int LabelColor = 0x7FFF; + private const int LabelColorDisabled = 0x4210; + private readonly Mobile m_From; + + public HousePlacementCategoryGump(Mobile from) : base(50, 50) + { + m_From = from; + + from.CloseGump(); + from.CloseGump(); + + AddPage(0); + + AddBackground(0, 0, 270, 145, 5054); + + AddImageTiled(10, 10, 250, 125, 2624); + AddAlphaRegion(10, 10, 250, 125); + + AddHtmlLocalized(10, 10, 250, 20, 1060239, LabelColor); //
HOUSE PLACEMENT TOOL
+ + AddButton(10, 110, 4017, 4019, 0); + AddHtmlLocalized(45, 110, 150, 20, 3000363, LabelColor); // Close + + AddButton(10, 40, 4005, 4007, 1); + AddHtmlLocalized(45, 40, 200, 20, 1060390, LabelColor); // Classic Houses + + AddButton(10, 60, 4005, 4007, 2); + AddHtmlLocalized(45, 60, 200, 20, 1060391, LabelColor); // 2-Story Customizable Houses + + AddButton(10, 80, 4005, 4007, 3); + AddHtmlLocalized(45, 80, 200, 20, 1060392, LabelColor); // 3-Story Customizable Houses + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (!m_From.CheckAlive() || m_From.Backpack?.FindItemByType() == null) return; - house.Price = Cost; - - if (from.AccessLevel >= AccessLevel.GameMaster) - { - from.SendMessage("{0} gold would have been withdrawn from your bank if you were not a GM.", - Cost.ToString()); - } - else - { - if (Banker.Withdraw(from, Cost)) - { - from.SendLocalizedMessage(1060398, - Cost.ToString()); // ~1_AMOUNT~ gold has been withdrawn from your bank box. - } - else - { - house.RemoveKeys(from); - house.Delete(); - from.SendLocalizedMessage( - 1060646); // You do not have the funds available in your bank box to purchase this house. Try placing a smaller house, or adding gold or checks to your bank box. - return; - } - } - - house.MoveToWorld(center, from.Map); - - for (int i = 0; i < toMove.Count; ++i) - { - object o = toMove[i]; - - if (o is Mobile mobile) - mobile.Location = house.BanLocation; - else if (o is Item item) - item.Location = house.BanLocation; - } + switch (info.ButtonID) + { + case 1: // Classic Houses + { + // TODO: Add flag to use ClassicHouses or EJ + m_From.SendGump(new HousePlacementListGump(m_From, HousePlacementEntry.HousesEJ)); + break; + } + case 2: // 2-Story Customizable Houses + { + m_From.SendGump(new HousePlacementListGump(m_From, HousePlacementEntry.TwoStoryFoundations)); + break; + } + case 3: // 3-Story Customizable Houses + { + m_From.SendGump(new HousePlacementListGump(m_From, HousePlacementEntry.ThreeStoryFoundations)); + break; + } } - - break; - } - case HousePlacementResult.BadItem: - case HousePlacementResult.BadLand: - case HousePlacementResult.BadStatic: - case HousePlacementResult.BadRegionHidden: - case HousePlacementResult.NoSurface: - { - from.SendLocalizedMessage( - 1043287); // The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain. - break; - } - case HousePlacementResult.BadRegion: - { - from.SendLocalizedMessage(501265); // Housing cannot be created in this area. - break; - } - case HousePlacementResult.BadRegionTemp: - { - from.SendLocalizedMessage( - 501270); // Lord British has decreed a 'no build' period, thus you cannot build this house at this time. - break; - } - case HousePlacementResult.BadRegionRaffle: - { - from.SendLocalizedMessage(1150493); // You must have a deed for this plot of land in order to build here. - break; - } - case HousePlacementResult.InvalidCastleKeep: - { - from.SendLocalizedMessage(1061122); // Castles and keeps cannot be created here. - break; - } - } + } } - public bool OnPlacement(Mobile from, Point3D p) + public class HousePlacementListGump : Gump { - if (!from.CheckAlive() || from.Backpack?.FindItemByType() == null) - return false; + private const int LabelColor = 0x7FFF; + private const int LabelHue = 0x480; + private readonly HousePlacementEntry[] m_Entries; + private readonly Mobile m_From; - Point3D center = new Point3D(p.X - Offset.X, p.Y - Offset.Y, p.Z - Offset.Z); - HousePlacementResult res = HousePlacement.Check(from, MultiID, center, out List toMove); + public HousePlacementListGump(Mobile from, HousePlacementEntry[] entries) : base(50, 50) + { + m_From = from; + m_Entries = entries; - switch (res) - { - case HousePlacementResult.Valid: - { - if (from.AccessLevel < AccessLevel.GameMaster && BaseHouse.HasAccountHouse(from)) + from.CloseGump(); + from.CloseGump(); + + AddPage(0); + + AddBackground(0, 0, 520, 420, 5054); + + AddImageTiled(10, 10, 500, 20, 2624); + AddAlphaRegion(10, 10, 500, 20); + + AddHtmlLocalized(10, 10, 500, 20, 1060239, LabelColor); //
HOUSE PLACEMENT TOOL
+ + AddImageTiled(10, 40, 500, 20, 2624); + AddAlphaRegion(10, 40, 500, 20); + + AddHtmlLocalized(50, 40, 225, 20, 1060235, LabelColor); // House Description + AddHtmlLocalized(275, 40, 75, 20, 1060236, LabelColor); // Storage + AddHtmlLocalized(350, 40, 75, 20, 1060237, LabelColor); // Lockdowns + AddHtmlLocalized(425, 40, 75, 20, 1060034, LabelColor); // Cost + + AddImageTiled(10, 70, 500, 280, 2624); + AddAlphaRegion(10, 70, 500, 280); + + AddImageTiled(10, 360, 500, 20, 2624); + AddAlphaRegion(10, 360, 500, 20); + + AddHtmlLocalized(10, 360, 250, 20, 1060645, LabelColor); // Bank Balance: + AddLabel(250, 360, LabelHue, Banker.GetBalance(from).ToString()); + + AddImageTiled(10, 390, 500, 20, 2624); + AddAlphaRegion(10, 390, 500, 20); + + AddButton(10, 390, 4017, 4019, 0); + AddHtmlLocalized(50, 390, 100, 20, 3000363, LabelColor); // Close + + for (var i = 0; i < entries.Length; ++i) { - from.SendLocalizedMessage(501271); // You already own a house, you may not place another! + var page = 1 + i / 14; + var index = i % 14; + + if (index == 0) + { + if (page > 1) + { + AddButton(450, 390, 4005, 4007, 0, GumpButtonType.Page, page); + AddHtmlLocalized(400, 390, 100, 20, 3000406, LabelColor); // Next + } + + AddPage(page); + + if (page > 1) + { + AddButton(200, 390, 4014, 4016, 0, GumpButtonType.Page, page - 1); + AddHtmlLocalized(250, 390, 100, 20, 3000405, LabelColor); // Previous + } + } + + var entry = entries[i]; + + var y = 70 + index * 20; + + AddButton(10, y, 4005, 4007, 1 + i); + AddHtmlLocalized(50, y, 225, 20, entry.Description, LabelColor); + AddLabel(275, y, LabelHue, entry.Storage.ToString()); + AddLabel(350, y, LabelHue, entry.Lockdowns.ToString()); + AddLabel(425, y, LabelHue, entry.Cost.ToString()); + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (!m_From.CheckAlive() || m_From.Backpack?.FindItemByType() == null) + return; + + var index = info.ButtonID - 1; + + if (index >= 0 && index < m_Entries.Length) + { + if (m_From.AccessLevel < AccessLevel.GameMaster && BaseHouse.HasAccountHouse(m_From)) + m_From.SendLocalizedMessage(501271); // You already own a house, you may not place another! + else + m_From.Target = new NewHousePlacementTarget(m_Entries, m_Entries[index]); } else { - from.SendLocalizedMessage(1011576); // This is a valid location. + m_From.SendGump(new HousePlacementCategoryGump(m_From)); + } + } + } - PreviewHouse prev = new PreviewHouse(MultiID); + public class NewHousePlacementTarget : MultiTarget + { + private readonly HousePlacementEntry[] m_Entries; + private readonly HousePlacementEntry m_Entry; - MultiComponentList mcl = prev.Components; + private bool m_Placed; - Point3D banLoc = new Point3D(center.X + mcl.Min.X, center.Y + mcl.Max.Y + 1, center.Z); + public NewHousePlacementTarget(HousePlacementEntry[] entries, HousePlacementEntry entry) : base( + entry.MultiID, + entry.Offset + ) + { + Range = 14; - for (int i = 0; i < mcl.List.Length; ++i) - { - MultiTileEntry entry = mcl.List[i]; + m_Entries = entries; + m_Entry = entry; + } - int itemID = entry.ItemId; + protected override void OnTarget(Mobile from, object o) + { + if (!from.CheckAlive() || from.Backpack?.FindItemByType() == null) + return; - if (itemID >= 0xBA3 && itemID <= 0xC0E) - { - banLoc = new Point3D(center.X + entry.OffsetX, center.Y + entry.OffsetY, center.Z); - break; - } - } + if (o is IPoint3D ip) + { + if (ip is Item item) + ip = item.GetWorldTop(); - for (int i = 0; i < toMove.Count; ++i) - { - object o = toMove[i]; + var p = new Point3D(ip); - if (o is Mobile mobile) - mobile.Location = banLoc; - else if (o is Item item) - item.Location = banLoc; - } + var reg = Region.Find(new Point3D(p), from.Map); - prev.MoveToWorld(center, from.Map); + if (from.AccessLevel >= AccessLevel.GameMaster || reg.AllowHousing(from, p)) + m_Placed = m_Entry.OnPlacement(from, p); + else if (reg.IsPartOf()) + from.SendLocalizedMessage( + 501270 + ); // Lord British has decreed a 'no build' period, thus you cannot build this house at this time. + else if (reg.IsPartOf() || reg.IsPartOf()) + from.SendLocalizedMessage( + 1043287 + ); // The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain. + else if (reg.IsPartOf()) + from.SendLocalizedMessage(1150493); // You must have a deed for this plot of land in order to build here. + else + from.SendLocalizedMessage(501265); // Housing can not be created in this area. + } + } - /* You are about to place a new house. - * Placing this house will condemn any and all of your other houses that you may have. - * All of your houses on all shards will be affected. - * - * In addition, you will not be able to place another house or have one transferred to you for one (1) real-life week. - * - * Once you accept these terms, these effects cannot be reversed. - * Re-deeding or transferring your new house will not uncondemn your other house(s) nor will the one week timer be removed. - * - * If you are absolutely certain you wish to proceed, click the button next to OKAY below. - * If you do not wish to trade for this house, click CANCEL. - */ - from.SendGump(new WarningGump(1060635, 30720, 1049583, 32512, 420, 280, okay => PlacementWarning_Callback(from, okay, prev))); + protected override void OnTargetFinish(Mobile from) + { + if (!from.CheckAlive() || from.Backpack?.FindItemByType() == null) + return; - return true; + if (!m_Placed) + from.SendGump(new HousePlacementListGump(from, m_Entries)); + } + } + + public class HousePlacementEntry + { + private static readonly Dictionary m_Table; + private readonly int m_Lockdowns; + private readonly int m_NewLockdowns; + private readonly int m_NewStorage; + private readonly int m_Storage; + + static HousePlacementEntry() + { + m_Table = new Dictionary(); + + FillTable(ClassicHouses); + FillTable(TwoStoryFoundations); + FillTable(ThreeStoryFoundations); + } + + public HousePlacementEntry( + Type type, int description, int storage, int lockdowns, int newStorage, int newLockdowns, + int vendors, int cost, int xOffset, int yOffset, int zOffset, int multiID + ) + { + Type = type; + Description = description; + m_Storage = storage; + m_Lockdowns = lockdowns; + m_NewStorage = newStorage; + m_NewLockdowns = newLockdowns; + Vendors = vendors; + Cost = cost; + + Offset = new Point3D(xOffset, yOffset, zOffset); + + MultiID = multiID; + } + + public Type Type { get; } + + public int Description { get; } + + public int Storage => BaseHouse.NewVendorSystem ? m_NewStorage : m_Storage; + public int Lockdowns => BaseHouse.NewVendorSystem ? m_NewLockdowns : m_Lockdowns; + public int Vendors { get; } + + public int Cost { get; } + + public int MultiID { get; } + + public Point3D Offset { get; } + + public static HousePlacementEntry[] ClassicHouses { get; } = + { + new HousePlacementEntry(typeof(SmallOldHouse), 1011303, 425, 212, 489, 244, 10, 37000, 0, 4, 0, 0x0064), + new HousePlacementEntry(typeof(SmallOldHouse), 1011304, 425, 212, 489, 244, 10, 37000, 0, 4, 0, 0x0066), + new HousePlacementEntry(typeof(SmallOldHouse), 1011305, 425, 212, 489, 244, 10, 36750, 0, 4, 0, 0x0068), + new HousePlacementEntry(typeof(SmallOldHouse), 1011306, 425, 212, 489, 244, 10, 35250, 0, 4, 0, 0x006A), + new HousePlacementEntry(typeof(SmallOldHouse), 1011307, 425, 212, 489, 244, 10, 36750, 0, 4, 0, 0x006C), + new HousePlacementEntry(typeof(SmallOldHouse), 1011308, 425, 212, 489, 244, 10, 36750, 0, 4, 0, 0x006E), + new HousePlacementEntry(typeof(SmallShop), 1011321, 425, 212, 489, 244, 10, 50500, -1, 4, 0, 0x00A0), + new HousePlacementEntry(typeof(SmallShop), 1011322, 425, 212, 489, 244, 10, 52500, 0, 4, 0, 0x00A2), + new HousePlacementEntry(typeof(SmallTower), 1011317, 580, 290, 667, 333, 14, 73500, 3, 4, 0, 0x0098), + new HousePlacementEntry(typeof(TwoStoryVilla), 1011319, 1100, 550, 1265, 632, 24, 113750, 3, 6, 0, 0x009E), + new HousePlacementEntry(typeof(SandStonePatio), 1011320, 850, 425, 1265, 632, 24, 76500, -1, 4, 0, 0x009C), + new HousePlacementEntry(typeof(LogCabin), 1011318, 1100, 550, 1265, 632, 24, 81750, 1, 6, 0, 0x009A), + new HousePlacementEntry(typeof(GuildHouse), 1011309, 1370, 685, 1576, 788, 28, 131500, -1, 7, 0, 0x0074), + new HousePlacementEntry(typeof(TwoStoryHouse), 1011310, 1370, 685, 1576, 788, 28, 162750, -3, 7, 0, 0x0076), + new HousePlacementEntry(typeof(TwoStoryHouse), 1011311, 1370, 685, 1576, 788, 28, 162000, -3, 7, 0, 0x0078), + new HousePlacementEntry(typeof(LargePatioHouse), 1011315, 1370, 685, 1576, 788, 28, 129250, -4, 7, 0, 0x008C), + new HousePlacementEntry(typeof(LargeMarbleHouse), 1011316, 1370, 685, 1576, 788, 28, 160500, -4, 7, 0, 0x0096), + new HousePlacementEntry(typeof(Tower), 1011312, 2119, 1059, 2437, 1218, 42, 366500, 0, 7, 0, 0x007A), + new HousePlacementEntry(typeof(Keep), 1011313, 2625, 1312, 3019, 1509, 52, 572750, 0, 11, 0, 0x007C), + new HousePlacementEntry(typeof(Castle), 1011314, 4076, 2038, 4688, 2344, 78, 865250, 0, 16, 0, 0x007E) + }; + + public static HousePlacementEntry[] HousesEJ { get; } = + { + new HousePlacementEntry(typeof(SmallOldHouse), 1011303, 425, 212, 489, 244, 10, 36750, 0, 4, 0, 0x0064), + new HousePlacementEntry(typeof(SmallOldHouse), 1011304, 425, 212, 489, 244, 10, 36750, 0, 4, 0, 0x0066), + new HousePlacementEntry(typeof(SmallOldHouse), 1011305, 425, 212, 489, 244, 10, 36500, 0, 4, 0, 0x0068), + new HousePlacementEntry(typeof(SmallOldHouse), 1011306, 425, 212, 489, 244, 10, 35000, 0, 4, 0, 0x006A), + new HousePlacementEntry(typeof(SmallOldHouse), 1011307, 425, 212, 489, 244, 10, 36500, 0, 4, 0, 0x006C), + new HousePlacementEntry(typeof(SmallOldHouse), 1011308, 425, 212, 489, 244, 10, 36500, 0, 4, 0, 0x006E), + new HousePlacementEntry(typeof(SmallShop), 1011321, 425, 212, 489, 244, 10, 50250, -1, 4, 0, 0x00A0), + new HousePlacementEntry(typeof(SmallShop), 1011322, 425, 212, 489, 244, 10, 52250, 0, 4, 0, 0x00A2), + new HousePlacementEntry(typeof(SmallTower), 1011317, 580, 290, 667, 333, 14, 73250, 3, 4, 0, 0x0098), + new HousePlacementEntry(typeof(TwoStoryVilla), 1011319, 1100, 550, 1265, 632, 24, 113500, 3, 6, 0, 0x009E), + new HousePlacementEntry(typeof(SandStonePatio), 1011320, 850, 425, 1265, 632, 24, 76250, -1, 4, 0, 0x009C), + new HousePlacementEntry(typeof(LogCabin), 1011318, 1100, 550, 1265, 632, 24, 81250, 1, 6, 0, 0x009A), + new HousePlacementEntry(typeof(GuildHouse), 1011309, 1370, 685, 1576, 788, 28, 131250, -1, 7, 0, 0x0074), + new HousePlacementEntry(typeof(TwoStoryHouse), 1011310, 1370, 685, 1576, 788, 28, 162500, -3, 7, 0, 0x0076), + new HousePlacementEntry(typeof(TwoStoryHouse), 1011311, 1370, 685, 1576, 788, 28, 162750, -3, 7, 0, 0x0078), + new HousePlacementEntry(typeof(LargePatioHouse), 1011315, 1370, 685, 1576, 788, 28, 129000, -4, 7, 0, 0x008C), + new HousePlacementEntry(typeof(LargeMarbleHouse), 1011316, 1370, 685, 1576, 788, 28, 160250, -4, 7, 0, 0x0096), + new HousePlacementEntry(typeof(Tower), 1011312, 2119, 1059, 2437, 1218, 42, 366250, 0, 7, 0, 0x007A), + new HousePlacementEntry(typeof(Keep), 1011313, 2625, 1312, 3019, 1509, 52, 562500, 0, 11, 0, 0x007C), + new HousePlacementEntry(typeof(Castle), 1011314, 4076, 2038, 4688, 2344, 78, 865000, 0, 16, 0, 0x007E), + + new HousePlacementEntry(typeof(TrinsicKeep), 1158748, 2625, 1312, 3019, 1509, 52, 29643750, 0, 11, 0, 0x147E), + new HousePlacementEntry( + typeof(GothicRoseCastle), + 1158749, + 4076, + 2038, + 4688, + 2344, + 78, + 44808750, + 0, + 16, + 0, + 0x147F + ), + new HousePlacementEntry(typeof(ElsaCastle), 1158750, 4076, 2038, 4688, 2344, 78, 45450000, 0, 16, 0, 0x1480), + new HousePlacementEntry(typeof(Spires), 1158761, 4076, 2038, 4688, 2344, 78, 47025000, 0, 16, 0, 0x1481), + new HousePlacementEntry( + typeof(CastleOfOceania), + 1158760, + 4076, + 2038, + 4688, + 2344, + 78, + 48971250, + 0, + 16, + 0, + 0x1482 + ), + new HousePlacementEntry(typeof(FeudalCastle), 1158762, 4076, 2038, 4688, 2344, 78, 27337500, 0, 16, 0, 0x1483), + new HousePlacementEntry(typeof(RobinsNest), 1158850, 2625, 1312, 3019, 1509, 52, 25301250, 0, 11, 0, 0x1484), + new HousePlacementEntry( + typeof(TraditionalKeep), + 1158851, + 2625, + 1312, + 3019, + 1509, + 52, + 26685000, + 0, + 11, + 0, + 0x1485 + ), + new HousePlacementEntry(typeof(VillaCrowley), 1158852, 2625, 1312, 3019, 1509, 52, 21813750, 0, 11, 0, 0x1486), + new HousePlacementEntry(typeof(DarkthornKeep), 1158853, 2625, 1312, 3019, 1509, 52, 27990000, 0, 11, 0, 0x1487), + new HousePlacementEntry(typeof(SandalwoodKeep), 1158854, 2625, 1312, 3019, 1509, 52, 23456250, 0, 11, 0, 0x1488), + new HousePlacementEntry(typeof(CasaMoga), 1158855, 2625, 1312, 3019, 1509, 52, 26313750, 0, 11, 0, 0x1489), + + new HousePlacementEntry(typeof(RobinsRoost), 1158960, 4076, 2038, 4688, 2344, 78, 43863750, 0, 16, 0, 0x148A), + new HousePlacementEntry(typeof(Camelot), 1158961, 4076, 2038, 4688, 2344, 78, 47092500, 0, 16, 0, 0x148B), + new HousePlacementEntry( + typeof(LacrimaeInCaelo), + 1158962, + 4076, + 2038, + 4688, + 2344, + 78, + 45315000, + 0, + 16, + 0, + 0x148C + ), + new HousePlacementEntry( + typeof(OkinawaSweetDreamCastle), + 1158963, + 4076, + 2038, + 4688, + 2344, + 78, + 40128750, + 0, + 16, + 0, + 0x148D + ), + new HousePlacementEntry( + typeof(TheSandstoneCastle), + 1158964, + 4076, + 2038, + 4688, + 2344, + 78, + 48690000, + 0, + 16, + 0, + 0x148E + ), + new HousePlacementEntry( + typeof(GrimswindSisters), + 1158965, + 4076, + 2038, + 4688, + 2344, + 78, + 42142500, + 0, + 16, + 0, + 0x148F + ) + }; + + public static HousePlacementEntry[] TwoStoryFoundations { get; } = + { + new HousePlacementEntry( + typeof(HouseFoundation), + 1060241, + 425, + 212, + 489, + 244, + 10, + 30500, + 0, + 4, + 0, + 0x13EC + ), // 7x7 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060242, + 580, + 290, + 667, + 333, + 14, + 34500, + 0, + 5, + 0, + 0x13ED + ), // 7x8 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060243, + 650, + 325, + 748, + 374, + 16, + 38500, + 0, + 5, + 0, + 0x13EE + ), // 7x9 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060244, + 700, + 350, + 805, + 402, + 16, + 42500, + 0, + 6, + 0, + 0x13EF + ), // 7x10 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060245, + 750, + 375, + 863, + 431, + 16, + 46500, + 0, + 6, + 0, + 0x13F0 + ), // 7x11 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060246, + 800, + 400, + 920, + 460, + 18, + 50500, + 0, + 7, + 0, + 0x13F1 + ), // 7x12 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060253, + 580, + 290, + 667, + 333, + 14, + 34500, + 0, + 4, + 0, + 0x13F8 + ), // 8x7 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060254, + 650, + 325, + 748, + 374, + 16, + 39000, + 0, + 5, + 0, + 0x13F9 + ), // 8x8 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060255, + 700, + 350, + 805, + 402, + 16, + 43500, + 0, + 5, + 0, + 0x13FA + ), // 8x9 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060256, + 750, + 375, + 863, + 431, + 16, + 48000, + 0, + 6, + 0, + 0x13FB + ), // 8x10 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060257, + 800, + 400, + 920, + 460, + 18, + 52500, + 0, + 6, + 0, + 0x13FC + ), // 8x11 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060258, + 850, + 425, + 1265, + 632, + 24, + 57000, + 0, + 7, + 0, + 0x13FD + ), // 8x12 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060259, + 1100, + 550, + 1265, + 632, + 24, + 61500, + 0, + 7, + 0, + 0x13FE + ), // 8x13 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060265, + 650, + 325, + 748, + 374, + 16, + 38500, + 0, + 4, + 0, + 0x1404 + ), // 9x7 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060266, + 700, + 350, + 805, + 402, + 16, + 43500, + 0, + 5, + 0, + 0x1405 + ), // 9x8 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060267, + 750, + 375, + 863, + 431, + 16, + 48500, + 0, + 5, + 0, + 0x1406 + ), // 9x9 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060268, + 800, + 400, + 920, + 460, + 18, + 53500, + 0, + 6, + 0, + 0x1407 + ), // 9x10 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060269, + 850, + 425, + 1265, + 632, + 24, + 58500, + 0, + 6, + 0, + 0x1408 + ), // 9x11 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060270, + 1100, + 550, + 1265, + 632, + 24, + 63500, + 0, + 7, + 0, + 0x1409 + ), // 9x12 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060271, + 1100, + 550, + 1265, + 632, + 24, + 68500, + 0, + 7, + 0, + 0x140A + ), // 9x13 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060277, + 700, + 350, + 805, + 402, + 16, + 42500, + 0, + 4, + 0, + 0x1410 + ), // 10x7 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060278, + 750, + 375, + 863, + 431, + 16, + 48000, + 0, + 5, + 0, + 0x1411 + ), // 10x8 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060279, + 800, + 400, + 920, + 460, + 18, + 53500, + 0, + 5, + 0, + 0x1412 + ), // 10x9 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060280, + 850, + 425, + 1265, + 632, + 24, + 59000, + 0, + 6, + 0, + 0x1413 + ), // 10x10 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060281, + 1100, + 550, + 1265, + 632, + 24, + 64500, + 0, + 6, + 0, + 0x1414 + ), // 10x11 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060282, + 1100, + 550, + 1265, + 632, + 24, + 70000, + 0, + 7, + 0, + 0x1415 + ), // 10x12 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060283, + 1150, + 575, + 1323, + 661, + 24, + 75500, + 0, + 7, + 0, + 0x1416 + ), // 10x13 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060289, + 750, + 375, + 863, + 431, + 16, + 46500, + 0, + 4, + 0, + 0x141C + ), // 11x7 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060290, + 800, + 400, + 920, + 460, + 18, + 52500, + 0, + 5, + 0, + 0x141D + ), // 11x8 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060291, + 850, + 425, + 1265, + 632, + 24, + 58500, + 0, + 5, + 0, + 0x141E + ), // 11x9 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060292, + 1100, + 550, + 1265, + 632, + 24, + 64500, + 0, + 6, + 0, + 0x141F + ), // 11x10 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060293, + 1100, + 550, + 1265, + 632, + 24, + 70500, + 0, + 6, + 0, + 0x1420 + ), // 11x11 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060294, + 1150, + 575, + 1323, + 661, + 24, + 76500, + 0, + 7, + 0, + 0x1421 + ), // 11x12 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060295, + 1200, + 600, + 1380, + 690, + 26, + 82500, + 0, + 7, + 0, + 0x1422 + ), // 11x13 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060301, + 800, + 400, + 920, + 460, + 18, + 50500, + 0, + 4, + 0, + 0x1428 + ), // 12x7 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060302, + 850, + 425, + 1265, + 632, + 24, + 57000, + 0, + 5, + 0, + 0x1429 + ), // 12x8 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060303, + 1100, + 550, + 1265, + 632, + 24, + 63500, + 0, + 5, + 0, + 0x142A + ), // 12x9 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060304, + 1100, + 550, + 1265, + 632, + 24, + 70000, + 0, + 6, + 0, + 0x142B + ), // 12x10 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060305, + 1150, + 575, + 1323, + 661, + 24, + 76500, + 0, + 6, + 0, + 0x142C + ), // 12x11 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060306, + 1200, + 600, + 1380, + 690, + 26, + 83000, + 0, + 7, + 0, + 0x142D + ), // 12x12 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060307, + 1250, + 625, + 1438, + 719, + 26, + 89500, + 0, + 7, + 0, + 0x142E + ), // 12x13 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060314, + 1100, + 550, + 1265, + 632, + 24, + 61500, + 0, + 5, + 0, + 0x1435 + ), // 13x8 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060315, + 1100, + 550, + 1265, + 632, + 24, + 68500, + 0, + 5, + 0, + 0x1436 + ), // 13x9 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060316, + 1150, + 575, + 1323, + 661, + 24, + 75500, + 0, + 6, + 0, + 0x1437 + ), // 13x10 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060317, + 1200, + 600, + 1380, + 690, + 26, + 82500, + 0, + 6, + 0, + 0x1438 + ), // 13x11 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060318, + 1250, + 625, + 1438, + 719, + 26, + 89500, + 0, + 7, + 0, + 0x1439 + ), // 13x12 2-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060319, + 1300, + 650, + 1495, + 747, + 28, + 96500, + 0, + 7, + 0, + 0x143A + ) // 13x13 2-Story Customizable House + }; + + public static HousePlacementEntry[] ThreeStoryFoundations { get; } = + { + new HousePlacementEntry( + typeof(HouseFoundation), + 1060272, + 1150, + 575, + 1323, + 661, + 24, + 73500, + 0, + 8, + 0, + 0x140B + ), // 9x14 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060284, + 1200, + 600, + 1380, + 690, + 26, + 81000, + 0, + 8, + 0, + 0x1417 + ), // 10x14 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060285, + 1250, + 625, + 1438, + 719, + 26, + 86500, + 0, + 8, + 0, + 0x1418 + ), // 10x15 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060296, + 1250, + 625, + 1438, + 719, + 26, + 88500, + 0, + 8, + 0, + 0x1423 + ), // 11x14 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060297, + 1300, + 650, + 1495, + 747, + 28, + 94500, + 0, + 8, + 0, + 0x1424 + ), // 11x15 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060298, + 1350, + 675, + 1553, + 776, + 28, + 100500, + 0, + 9, + 0, + 0x1425 + ), // 11x16 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060308, + 1300, + 650, + 1495, + 747, + 28, + 96000, + 0, + 8, + 0, + 0x142F + ), // 12x14 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060309, + 1350, + 675, + 1553, + 776, + 28, + 102500, + 0, + 8, + 0, + 0x1430 + ), // 12x15 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060310, + 1370, + 685, + 1576, + 788, + 28, + 109000, + 0, + 9, + 0, + 0x1431 + ), // 12x16 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060311, + 1370, + 685, + 1576, + 788, + 28, + 115500, + 0, + 9, + 0, + 0x1432 + ), // 12x17 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060320, + 1350, + 675, + 1553, + 776, + 28, + 103500, + 0, + 8, + 0, + 0x143B + ), // 13x14 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060321, + 1370, + 685, + 1576, + 788, + 28, + 110500, + 0, + 8, + 0, + 0x143C + ), // 13x15 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060322, + 1370, + 685, + 1576, + 788, + 28, + 117500, + 0, + 9, + 0, + 0x143D + ), // 13x16 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060323, + 2119, + 1059, + 2437, + 1218, + 42, + 124500, + 0, + 9, + 0, + 0x143E + ), // 13x17 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060324, + 2119, + 1059, + 2437, + 1218, + 42, + 131500, + 0, + 10, + 0, + 0x143F + ), // 13x18 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060327, + 1150, + 575, + 1323, + 661, + 24, + 73500, + 0, + 5, + 0, + 0x1442 + ), // 14x9 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060328, + 1200, + 600, + 1380, + 690, + 26, + 81000, + 0, + 6, + 0, + 0x1443 + ), // 14x10 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060329, + 1250, + 625, + 1438, + 719, + 26, + 88500, + 0, + 6, + 0, + 0x1444 + ), // 14x11 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060330, + 1300, + 650, + 1495, + 747, + 28, + 96000, + 0, + 7, + 0, + 0x1445 + ), // 14x12 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060331, + 1350, + 675, + 1553, + 776, + 28, + 103500, + 0, + 7, + 0, + 0x1446 + ), // 14x13 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060332, + 1370, + 685, + 1576, + 788, + 28, + 111000, + 0, + 8, + 0, + 0x1447 + ), // 14x14 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060333, + 1370, + 685, + 1576, + 788, + 28, + 118500, + 0, + 8, + 0, + 0x1448 + ), // 14x15 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060334, + 2119, + 1059, + 2437, + 1218, + 42, + 126000, + 0, + 9, + 0, + 0x1449 + ), // 14x16 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060335, + 2119, + 1059, + 2437, + 1218, + 42, + 133500, + 0, + 9, + 0, + 0x144A + ), // 14x17 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060336, + 2119, + 1059, + 2437, + 1218, + 42, + 141000, + 0, + 10, + 0, + 0x144B + ), // 14x18 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060340, + 1250, + 625, + 1438, + 719, + 26, + 86500, + 0, + 6, + 0, + 0x144F + ), // 15x10 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060341, + 1300, + 650, + 1495, + 747, + 28, + 94500, + 0, + 6, + 0, + 0x1450 + ), // 15x11 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060342, + 1350, + 675, + 1553, + 776, + 28, + 102500, + 0, + 7, + 0, + 0x1451 + ), // 15x12 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060343, + 1370, + 685, + 1576, + 788, + 28, + 110500, + 0, + 7, + 0, + 0x1452 + ), // 15x13 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060344, + 1370, + 685, + 1576, + 788, + 28, + 118500, + 0, + 8, + 0, + 0x1453 + ), // 15x14 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060345, + 2119, + 1059, + 2437, + 1218, + 42, + 126500, + 0, + 8, + 0, + 0x1454 + ), // 15x15 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060346, + 2119, + 1059, + 2437, + 1218, + 42, + 134500, + 0, + 9, + 0, + 0x1455 + ), // 15x16 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060347, + 2119, + 1059, + 2437, + 1218, + 42, + 142500, + 0, + 9, + 0, + 0x1456 + ), // 15x17 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060348, + 2119, + 1059, + 2437, + 1218, + 42, + 150500, + 0, + 10, + 0, + 0x1457 + ), // 15x18 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060353, + 1350, + 675, + 1553, + 776, + 28, + 100500, + 0, + 6, + 0, + 0x145C + ), // 16x11 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060354, + 1370, + 685, + 1576, + 788, + 28, + 109000, + 0, + 7, + 0, + 0x145D + ), // 16x12 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060355, + 1370, + 685, + 1576, + 788, + 28, + 117500, + 0, + 7, + 0, + 0x145E + ), // 16x13 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060356, + 2119, + 1059, + 2437, + 1218, + 42, + 126000, + 0, + 8, + 0, + 0x145F + ), // 16x14 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060357, + 2119, + 1059, + 2437, + 1218, + 42, + 134500, + 0, + 8, + 0, + 0x1460 + ), // 16x15 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060358, + 2119, + 1059, + 2437, + 1218, + 42, + 143000, + 0, + 9, + 0, + 0x1461 + ), // 16x16 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060359, + 2119, + 1059, + 2437, + 1218, + 42, + 151500, + 0, + 9, + 0, + 0x1462 + ), // 16x17 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060360, + 2119, + 1059, + 2437, + 1218, + 42, + 160000, + 0, + 10, + 0, + 0x1463 + ), // 16x18 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060366, + 1370, + 685, + 1576, + 788, + 28, + 115500, + 0, + 7, + 0, + 0x1469 + ), // 17x12 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060367, + 2119, + 1059, + 2437, + 1218, + 42, + 124500, + 0, + 7, + 0, + 0x146A + ), // 17x13 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060368, + 2119, + 1059, + 2437, + 1218, + 42, + 133500, + 0, + 8, + 0, + 0x146B + ), // 17x14 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060369, + 2119, + 1059, + 2437, + 1218, + 42, + 142500, + 0, + 8, + 0, + 0x146C + ), // 17x15 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060370, + 2119, + 1059, + 2437, + 1218, + 42, + 151500, + 0, + 9, + 0, + 0x146D + ), // 17x16 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060371, + 2119, + 1059, + 2437, + 1218, + 42, + 160500, + 0, + 9, + 0, + 0x146E + ), // 17x17 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060372, + 2119, + 1059, + 2437, + 1218, + 42, + 169500, + 0, + 10, + 0, + 0x146F + ), // 17x18 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060379, + 2119, + 1059, + 2437, + 1218, + 42, + 131500, + 0, + 7, + 0, + 0x1476 + ), // 18x13 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060380, + 2119, + 1059, + 2437, + 1218, + 42, + 141000, + 0, + 8, + 0, + 0x1477 + ), // 18x14 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060381, + 2119, + 1059, + 2437, + 1218, + 42, + 150500, + 0, + 8, + 0, + 0x1478 + ), // 18x15 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060382, + 2119, + 1059, + 2437, + 1218, + 42, + 160000, + 0, + 9, + 0, + 0x1479 + ), // 18x16 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060383, + 2119, + 1059, + 2437, + 1218, + 42, + 169500, + 0, + 9, + 0, + 0x147A + ), // 18x17 3-Story Customizable House + new HousePlacementEntry( + typeof(HouseFoundation), + 1060384, + 2119, + 1059, + 2437, + 1218, + 42, + 179000, + 0, + 10, + 0, + 0x147B + ) // 18x18 3-Story Customizable House + }; + + public BaseHouse ConstructHouse(Mobile from) + { + try + { + object[] args; + + if (Type == typeof(HouseFoundation)) + args = new object[] { from, MultiID, m_Storage, m_Lockdowns }; + else if (Type == typeof(SmallOldHouse) || Type == typeof(SmallShop) || Type == typeof(TwoStoryHouse)) + args = new object[] { from, MultiID }; + else + args = new object[] { from }; + + return ActivatorUtil.CreateInstance(Type, args) as BaseHouse; + } + catch + { + // ignored } - break; - } - case HousePlacementResult.BadItem: - case HousePlacementResult.BadLand: - case HousePlacementResult.BadStatic: - case HousePlacementResult.BadRegionHidden: - case HousePlacementResult.NoSurface: - { - from.SendLocalizedMessage( - 1043287); // The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain. - break; - } - case HousePlacementResult.BadRegion: - { - from.SendLocalizedMessage(501265); // Housing cannot be created in this area. - break; - } - case HousePlacementResult.BadRegionTemp: - { - from.SendLocalizedMessage( - 501270); // Lord British has decreed a 'no build' period, thus you cannot build this house at this time. - break; - } - case HousePlacementResult.BadRegionRaffle: - { - from.SendLocalizedMessage(1150493); // You must have a deed for this plot of land in order to build here. - break; - } - case HousePlacementResult.InvalidCastleKeep: - { - from.SendLocalizedMessage(1061122); // Castles and keeps cannot be created here. - break; - } - } + return null; + } - return false; + public void PlacementWarning_Callback(Mobile from, bool okay, PreviewHouse prevHouse) + { + if (!from.CheckAlive() || from.Backpack?.FindItemByType() == null) + return; + + if (!okay) + { + prevHouse.Delete(); + return; + } + + if (prevHouse.Deleted) + { + /* Too much time has passed and the test house you created has been deleted. + * Please try again! + */ + from.SendGump(new NoticeGump(1060637, 30720, 1060647, 32512, 320, 180)); + + return; + } + + var center = prevHouse.Location; + + prevHouse.Delete(); + + // Point3D center = new Point3D( p.X - m_Offset.X, p.Y - m_Offset.Y, p.Z - m_Offset.Z ); + var res = HousePlacement.Check(from, MultiID, center, out var toMove); + + switch (res) + { + case HousePlacementResult.Valid: + { + if (from.AccessLevel < AccessLevel.GameMaster && BaseHouse.HasAccountHouse(from)) + { + from.SendLocalizedMessage(501271); // You already own a house, you may not place another! + } + else + { + var house = ConstructHouse(from); + + if (house == null) + return; + + house.Price = Cost; + + if (from.AccessLevel >= AccessLevel.GameMaster) + { + from.SendMessage( + "{0} gold would have been withdrawn from your bank if you were not a GM.", + Cost.ToString() + ); + } + else + { + if (Banker.Withdraw(from, Cost)) + { + from.SendLocalizedMessage( + 1060398, + Cost.ToString() + ); // ~1_AMOUNT~ gold has been withdrawn from your bank box. + } + else + { + house.RemoveKeys(from); + house.Delete(); + from.SendLocalizedMessage( + 1060646 + ); // You do not have the funds available in your bank box to purchase this house. Try placing a smaller house, or adding gold or checks to your bank box. + return; + } + } + + house.MoveToWorld(center, from.Map); + + for (var i = 0; i < toMove.Count; ++i) + { + object o = toMove[i]; + + if (o is Mobile mobile) + mobile.Location = house.BanLocation; + else if (o is Item item) + item.Location = house.BanLocation; + } + } + + break; + } + case HousePlacementResult.BadItem: + case HousePlacementResult.BadLand: + case HousePlacementResult.BadStatic: + case HousePlacementResult.BadRegionHidden: + case HousePlacementResult.NoSurface: + { + from.SendLocalizedMessage( + 1043287 + ); // The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain. + break; + } + case HousePlacementResult.BadRegion: + { + from.SendLocalizedMessage(501265); // Housing cannot be created in this area. + break; + } + case HousePlacementResult.BadRegionTemp: + { + from.SendLocalizedMessage( + 501270 + ); // Lord British has decreed a 'no build' period, thus you cannot build this house at this time. + break; + } + case HousePlacementResult.BadRegionRaffle: + { + from.SendLocalizedMessage( + 1150493 + ); // You must have a deed for this plot of land in order to build here. + break; + } + case HousePlacementResult.InvalidCastleKeep: + { + from.SendLocalizedMessage(1061122); // Castles and keeps cannot be created here. + break; + } + } + } + + public bool OnPlacement(Mobile from, Point3D p) + { + if (!from.CheckAlive() || from.Backpack?.FindItemByType() == null) + return false; + + var center = new Point3D(p.X - Offset.X, p.Y - Offset.Y, p.Z - Offset.Z); + var res = HousePlacement.Check(from, MultiID, center, out var toMove); + + switch (res) + { + case HousePlacementResult.Valid: + { + if (from.AccessLevel < AccessLevel.GameMaster && BaseHouse.HasAccountHouse(from)) + { + from.SendLocalizedMessage(501271); // You already own a house, you may not place another! + } + else + { + from.SendLocalizedMessage(1011576); // This is a valid location. + + var prev = new PreviewHouse(MultiID); + + var mcl = prev.Components; + + var banLoc = new Point3D(center.X + mcl.Min.X, center.Y + mcl.Max.Y + 1, center.Z); + + for (var i = 0; i < mcl.List.Length; ++i) + { + var entry = mcl.List[i]; + + int itemID = entry.ItemId; + + if (itemID >= 0xBA3 && itemID <= 0xC0E) + { + banLoc = new Point3D(center.X + entry.OffsetX, center.Y + entry.OffsetY, center.Z); + break; + } + } + + for (var i = 0; i < toMove.Count; ++i) + { + object o = toMove[i]; + + if (o is Mobile mobile) + mobile.Location = banLoc; + else if (o is Item item) + item.Location = banLoc; + } + + prev.MoveToWorld(center, from.Map); + + /* You are about to place a new house. + * Placing this house will condemn any and all of your other houses that you may have. + * All of your houses on all shards will be affected. + * + * In addition, you will not be able to place another house or have one transferred to you for one (1) real-life week. + * + * Once you accept these terms, these effects cannot be reversed. + * Re-deeding or transferring your new house will not uncondemn your other house(s) nor will the one week timer be removed. + * + * If you are absolutely certain you wish to proceed, click the button next to OKAY below. + * If you do not wish to trade for this house, click CANCEL. + */ + from.SendGump( + new WarningGump( + 1060635, + 30720, + 1049583, + 32512, + 420, + 280, + okay => PlacementWarning_Callback(from, okay, prev) + ) + ); + + return true; + } + + break; + } + case HousePlacementResult.BadItem: + case HousePlacementResult.BadLand: + case HousePlacementResult.BadStatic: + case HousePlacementResult.BadRegionHidden: + case HousePlacementResult.NoSurface: + { + from.SendLocalizedMessage( + 1043287 + ); // The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain. + break; + } + case HousePlacementResult.BadRegion: + { + from.SendLocalizedMessage(501265); // Housing cannot be created in this area. + break; + } + case HousePlacementResult.BadRegionTemp: + { + from.SendLocalizedMessage( + 501270 + ); // Lord British has decreed a 'no build' period, thus you cannot build this house at this time. + break; + } + case HousePlacementResult.BadRegionRaffle: + { + from.SendLocalizedMessage( + 1150493 + ); // You must have a deed for this plot of land in order to build here. + break; + } + case HousePlacementResult.InvalidCastleKeep: + { + from.SendLocalizedMessage(1061122); // Castles and keeps cannot be created here. + break; + } + } + + return false; + } + + public static HousePlacementEntry Find(BaseHouse house) + { + m_Table.TryGetValue(house.GetType(), out var obj); + + if (obj is HousePlacementEntry entry) + return entry; + + if (obj is List list) + return list.FirstOrDefault(e => e.MultiID == house.ItemID); + + if (obj is Dictionary table) + return table[house.ItemID]; + + return null; + } + + private static void FillTable(HousePlacementEntry[] entries) + { + for (var i = 0; i < entries.Length; ++i) + { + var e = entries[i]; + + if (!m_Table.TryGetValue(e.Type, out var obj)) + { + m_Table[e.Type] = e; + } + else if (obj is HousePlacementEntry entry) + { + var list = new List { entry, e }; + + m_Table[e.Type] = list; + } + else if (obj is List list) + { + if (list.Count == 8) + { + var table = new Dictionary(); + + foreach (var t in list) + table[t.MultiID] = t; + + table[e.MultiID] = e; + + m_Table[e.Type] = table; + } + else + { + list.Add(e); + } + } + else if (obj is Dictionary table) + { + table[e.MultiID] = e; + } + } + } } - - public static HousePlacementEntry Find(BaseHouse house) - { - m_Table.TryGetValue(house.GetType(), out object obj); - - if (obj is HousePlacementEntry entry) - return entry; - - if (obj is List list) - return list.FirstOrDefault(e => e.MultiID == house.ItemID); - - if (obj is Dictionary table) - return table[house.ItemID]; - - return null; - } - - private static void FillTable(HousePlacementEntry[] entries) - { - for (int i = 0; i < entries.Length; ++i) - { - HousePlacementEntry e = entries[i]; - - if (!m_Table.TryGetValue(e.Type, out object obj)) - { - m_Table[e.Type] = e; - } - else if (obj is HousePlacementEntry entry) - { - List list = new List { entry, e }; - - m_Table[e.Type] = list; - } - else if (obj is List list) - { - if (list.Count == 8) - { - Dictionary table = new Dictionary(); - - foreach (HousePlacementEntry t in list) - table[t.MultiID] = t; - - table[e.MultiID] = e; - - m_Table[e.Type] = table; - } - else - list.Add(e); - } - else if (obj is Dictionary table) - { - table[e.MultiID] = e; - } - } - } - } } diff --git a/Projects/UOContent/Multis/HouseSign.cs b/Projects/UOContent/Multis/HouseSign.cs index 0e847c56e..3e13e389a 100644 --- a/Projects/UOContent/Multis/HouseSign.cs +++ b/Projects/UOContent/Multis/HouseSign.cs @@ -5,248 +5,252 @@ using Server.Gumps; namespace Server.Multis { - public class HouseSign : Item - { - public HouseSign(BaseHouse owner) : base(0xBD2) + public class HouseSign : Item { - Owner = owner; - OriginalOwner = Owner.Owner; - Movable = false; - } - - public HouseSign(Serial serial) : base(serial) - { - } - - public BaseHouse Owner { get; private set; } - - [CommandProperty(AccessLevel.GameMaster)] - public bool RestrictDecay - { - get => Owner?.RestrictDecay == true; - set - { - if (Owner != null) - Owner.RestrictDecay = value; - } - } - - [CommandProperty(AccessLevel.GameMaster)] - public Mobile OriginalOwner { get; private set; } - - public override bool ForceShowProperties => ObjectPropertyList.Enabled; - - public bool GettingProperties { get; private set; } - - public string GetName() => Name ?? "An Unnamed House"; - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - if (Owner?.Deleted == false) - Owner.Delete(); - } - - public override void AddNameProperty(ObjectPropertyList list) - { - list.Add(1061638); // A House Sign - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1061639, Utility.FixHtml(GetName())); // Name: ~1_NAME~ - list.Add(1061640, Owner?.Owner == null ? "nobody" : Owner.Owner.Name); // Owner: ~1_OWNER~ - - if (Owner != null) - { - list.Add(Owner.Public ? 1061641 : 1061642); // This House is Open to the Public : This is a Private Home - - GettingProperties = true; - DecayLevel level = Owner.DecayLevel; - GettingProperties = false; - - if (level == DecayLevel.DemolitionPending) + public HouseSign(BaseHouse owner) : base(0xBD2) { - list.Add(1062497); // Demolition Pending - } - else if (level != DecayLevel.Ageless) - { - if (level == DecayLevel.Collapsed) - level = DecayLevel.IDOC; - - list.Add(1062028, $"#{1043009 + (int)level}"); // Condition: This structure is ... - } - } - } - - public override void OnSingleClick(Mobile from) - { - if (Owner != null && BaseHouse.DecayEnabled && Owner.DecayPeriod != TimeSpan.Zero) - { - var message = Owner.DecayLevel switch - { - DecayLevel.Ageless => "ageless", - DecayLevel.Fairly => "fairly worn", - DecayLevel.Greatly => "greatly worn", - DecayLevel.LikeNew => "like new", - DecayLevel.Slightly => "slightly worn", - DecayLevel.Somewhat => "somewhat worn", - _ => "in danger of collapsing" - }; - - LabelTo(from, "This house is {0}.", message); - } - - base.OnSingleClick(from); - } - - public void ShowSign(Mobile m) - { - if (Owner != null) - { - if (Owner.IsFriend(m) && m.AccessLevel < AccessLevel.GameMaster) - { - if ((Core.ML && Owner.IsOwner(m)) || !Core.ML) - Owner.RefreshDecay(); - - if (!Core.AOS) - m.SendLocalizedMessage(501293); // Welcome back to the house, friend! + Owner = owner; + OriginalOwner = Owner.Owner; + Movable = false; } - if (Owner.IsAosRules) - m.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Information, m, Owner)); - else - m.SendGump(new HouseGump(m, Owner)); - } - } - - public void ClaimGump_Callback(Mobile from, bool okay) - { - if (okay && Owner != null && Owner.Owner == null && Owner.DecayLevel != DecayLevel.DemolitionPending) - { - bool canClaim = (Owner.CoOwners?.Count > 0 && Owner.IsCoOwner(from)) || Owner.IsFriend(from); - - if (canClaim && !BaseHouse.HasAccountHouse(from)) + public HouseSign(Serial serial) : base(serial) { - Owner.Owner = from; - Owner.LastTraded = DateTime.UtcNow; } - } - ShowSign(from); - } + public BaseHouse Owner { get; private set; } - public override void OnDoubleClick(Mobile m) - { - if (Owner == null) - return; - - if (m.AccessLevel < AccessLevel.GameMaster && Owner.Owner == null && - Owner.DecayLevel != DecayLevel.DemolitionPending) - { - bool canClaim = (Owner?.CoOwners.Count > 0 && Owner.IsCoOwner(m)) || Owner.IsFriend(m); - - if (canClaim && !BaseHouse.HasAccountHouse(m)) - m.SendGump(new WarningGump(501036, 32512, 1049719, 32512, 420, 280, okay => ClaimGump_Callback(m, okay))); - } - - ShowSign(m); - } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - - if (!BaseHouse.NewVendorSystem || !from.Alive || Owner?.IsAosRules != true) - return; - - if (Owner.AreThereAvailableVendorsFor(from)) - list.Add(new VendorsEntry(this)); - - if (Owner.VendorInventories.Count > 0) - list.Add(new ReclaimVendorInventoryEntry(this)); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(Owner); - writer.Write(OriginalOwner); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - Owner = reader.ReadItem() as BaseHouse; - OriginalOwner = reader.ReadMobile(); - - break; - } - } - - if (Name == "a house sign") - Name = null; - } - - private class VendorsEntry : ContextMenuEntry - { - private readonly HouseSign m_Sign; - - public VendorsEntry(HouseSign sign) : base(6211) => m_Sign = sign; - - public override void OnClick() - { - Mobile from = Owner.From; - - if (!from.CheckAlive() || m_Sign.Deleted || m_Sign.Owner?.AreThereAvailableVendorsFor(from) != true) - return; - - if (from.Map != m_Sign.Map || !from.InRange(m_Sign, 5)) - from.SendLocalizedMessage( - 1062429); // You must be within five paces of the house sign to use this option. - else - from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Vendors, from, m_Sign.Owner)); - } - } - - private class ReclaimVendorInventoryEntry : ContextMenuEntry - { - private readonly HouseSign m_Sign; - - public ReclaimVendorInventoryEntry(HouseSign sign) : base(6213) => m_Sign = sign; - - public override void OnClick() - { - Mobile from = Owner.From; - - if (m_Sign.Deleted || m_Sign.Owner == null || m_Sign.Owner.VendorInventories.Count == 0 || - !from.CheckAlive()) - return; - - if (from.Map != m_Sign.Map || !from.InRange(m_Sign, 5)) + [CommandProperty(AccessLevel.GameMaster)] + public bool RestrictDecay { - from.SendLocalizedMessage( - 1062429); // You must be within five paces of the house sign to use this option. + get => Owner?.RestrictDecay == true; + set + { + if (Owner != null) + Owner.RestrictDecay = value; + } } - else + + [CommandProperty(AccessLevel.GameMaster)] + public Mobile OriginalOwner { get; private set; } + + public override bool ForceShowProperties => ObjectPropertyList.Enabled; + + public bool GettingProperties { get; private set; } + + public string GetName() => Name ?? "An Unnamed House"; + + public override void OnAfterDelete() { - from.CloseGump(); - from.SendGump(new VendorInventoryGump(m_Sign.Owner, from)); + base.OnAfterDelete(); + + if (Owner?.Deleted == false) + Owner.Delete(); + } + + public override void AddNameProperty(ObjectPropertyList list) + { + list.Add(1061638); // A House Sign + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1061639, Utility.FixHtml(GetName())); // Name: ~1_NAME~ + list.Add(1061640, Owner?.Owner == null ? "nobody" : Owner.Owner.Name); // Owner: ~1_OWNER~ + + if (Owner != null) + { + list.Add(Owner.Public ? 1061641 : 1061642); // This House is Open to the Public : This is a Private Home + + GettingProperties = true; + var level = Owner.DecayLevel; + GettingProperties = false; + + if (level == DecayLevel.DemolitionPending) + { + list.Add(1062497); // Demolition Pending + } + else if (level != DecayLevel.Ageless) + { + if (level == DecayLevel.Collapsed) + level = DecayLevel.IDOC; + + list.Add(1062028, $"#{1043009 + (int)level}"); // Condition: This structure is ... + } + } + } + + public override void OnSingleClick(Mobile from) + { + if (Owner != null && BaseHouse.DecayEnabled && Owner.DecayPeriod != TimeSpan.Zero) + { + var message = Owner.DecayLevel switch + { + DecayLevel.Ageless => "ageless", + DecayLevel.Fairly => "fairly worn", + DecayLevel.Greatly => "greatly worn", + DecayLevel.LikeNew => "like new", + DecayLevel.Slightly => "slightly worn", + DecayLevel.Somewhat => "somewhat worn", + _ => "in danger of collapsing" + }; + + LabelTo(from, "This house is {0}.", message); + } + + base.OnSingleClick(from); + } + + public void ShowSign(Mobile m) + { + if (Owner != null) + { + if (Owner.IsFriend(m) && m.AccessLevel < AccessLevel.GameMaster) + { + if (Core.ML && Owner.IsOwner(m) || !Core.ML) + Owner.RefreshDecay(); + + if (!Core.AOS) + m.SendLocalizedMessage(501293); // Welcome back to the house, friend! + } + + if (Owner.IsAosRules) + m.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Information, m, Owner)); + else + m.SendGump(new HouseGump(m, Owner)); + } + } + + public void ClaimGump_Callback(Mobile from, bool okay) + { + if (okay && Owner != null && Owner.Owner == null && Owner.DecayLevel != DecayLevel.DemolitionPending) + { + var canClaim = Owner.CoOwners?.Count > 0 && Owner.IsCoOwner(@from) || Owner.IsFriend(from); + + if (canClaim && !BaseHouse.HasAccountHouse(from)) + { + Owner.Owner = from; + Owner.LastTraded = DateTime.UtcNow; + } + } + + ShowSign(from); + } + + public override void OnDoubleClick(Mobile m) + { + if (Owner == null) + return; + + if (m.AccessLevel < AccessLevel.GameMaster && Owner.Owner == null && + Owner.DecayLevel != DecayLevel.DemolitionPending) + { + var canClaim = Owner?.CoOwners.Count > 0 && Owner.IsCoOwner(m) || Owner.IsFriend(m); + + if (canClaim && !BaseHouse.HasAccountHouse(m)) + m.SendGump( + new WarningGump(501036, 32512, 1049719, 32512, 420, 280, okay => ClaimGump_Callback(m, okay)) + ); + } + + ShowSign(m); + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + + if (!BaseHouse.NewVendorSystem || !from.Alive || Owner?.IsAosRules != true) + return; + + if (Owner.AreThereAvailableVendorsFor(from)) + list.Add(new VendorsEntry(this)); + + if (Owner.VendorInventories.Count > 0) + list.Add(new ReclaimVendorInventoryEntry(this)); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(Owner); + writer.Write(OriginalOwner); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + Owner = reader.ReadItem() as BaseHouse; + OriginalOwner = reader.ReadMobile(); + + break; + } + } + + if (Name == "a house sign") + Name = null; + } + + private class VendorsEntry : ContextMenuEntry + { + private readonly HouseSign m_Sign; + + public VendorsEntry(HouseSign sign) : base(6211) => m_Sign = sign; + + public override void OnClick() + { + var from = Owner.From; + + if (!from.CheckAlive() || m_Sign.Deleted || m_Sign.Owner?.AreThereAvailableVendorsFor(from) != true) + return; + + if (from.Map != m_Sign.Map || !from.InRange(m_Sign, 5)) + from.SendLocalizedMessage( + 1062429 + ); // You must be within five paces of the house sign to use this option. + else + from.SendGump(new HouseGumpAOS(HouseGumpPageAOS.Vendors, from, m_Sign.Owner)); + } + } + + private class ReclaimVendorInventoryEntry : ContextMenuEntry + { + private readonly HouseSign m_Sign; + + public ReclaimVendorInventoryEntry(HouseSign sign) : base(6213) => m_Sign = sign; + + public override void OnClick() + { + var from = Owner.From; + + if (m_Sign.Deleted || m_Sign.Owner == null || m_Sign.Owner.VendorInventories.Count == 0 || + !from.CheckAlive()) + return; + + if (from.Map != m_Sign.Map || !from.InRange(m_Sign, 5)) + { + from.SendLocalizedMessage( + 1062429 + ); // You must be within five paces of the house sign to use this option. + } + else + { + from.CloseGump(); + from.SendGump(new VendorInventoryGump(m_Sign.Owner, from)); + } + } } - } } - } } diff --git a/Projects/UOContent/Multis/HouseTeleporter.cs b/Projects/UOContent/Multis/HouseTeleporter.cs index d83ca6471..48790dd12 100644 --- a/Projects/UOContent/Multis/HouseTeleporter.cs +++ b/Projects/UOContent/Multis/HouseTeleporter.cs @@ -7,166 +7,182 @@ using Server.Multis; namespace Server.Items { - public class HouseTeleporter : Item, ISecurable - { - public HouseTeleporter(int itemID, Item target = null) : base(itemID) + public class HouseTeleporter : Item, ISecurable { - Movable = false; - - Level = SecureLevel.Anyone; - - Target = target; - } - - public HouseTeleporter(Serial serial) : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public Item Target { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public SecureLevel Level { get; set; } - - public bool CheckAccess(Mobile m) - { - BaseHouse house = BaseHouse.FindHouseAt(this); - - return (house == null || (house.Public && !house.IsBanned(m)) || house.HasAccess(m)) && - house?.HasSecureAccess(m, Level) == true; - } - - public override bool OnMoveOver(Mobile m) - { - if (Target?.Deleted == false) - { - if (CheckAccess(m)) + public HouseTeleporter(int itemID, Item target = null) : base(itemID) { - if (!m.Hidden || m.AccessLevel == AccessLevel.Player) - new EffectTimer(Location, Map, 2023, 0x1F0, TimeSpan.FromSeconds(0.4)).Start(); + Movable = false; - new DelayTimer(this, m).Start(); + Level = SecureLevel.Anyone; + + Target = target; } - else + + public HouseTeleporter(Serial serial) : base(serial) { - m.SendLocalizedMessage(1061637); // You are not allowed to access this. } - } - return true; + [CommandProperty(AccessLevel.GameMaster)] + public Item Target { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public SecureLevel Level { get; set; } + + public bool CheckAccess(Mobile m) + { + var house = BaseHouse.FindHouseAt(this); + + return (house == null || house.Public && !house.IsBanned(m) || house.HasAccess(m)) && + house?.HasSecureAccess(m, Level) == true; + } + + public override bool OnMoveOver(Mobile m) + { + if (Target?.Deleted == false) + { + if (CheckAccess(m)) + { + if (!m.Hidden || m.AccessLevel == AccessLevel.Player) + new EffectTimer(Location, Map, 2023, 0x1F0, TimeSpan.FromSeconds(0.4)).Start(); + + new DelayTimer(this, m).Start(); + } + else + { + m.SendLocalizedMessage(1061637); // You are not allowed to access this. + } + } + + return true; + } + + public override void GetContextMenuEntries(Mobile from, List list) + { + base.GetContextMenuEntries(from, list); + SetSecureLevelEntry.AddTo(from, this, list); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write((int)Level); + + writer.Write(Target); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + Level = (SecureLevel)reader.ReadInt(); + goto case 0; + } + case 0: + { + Target = reader.ReadItem(); + + if (version < 1) + Level = SecureLevel.Anyone; + + break; + } + } + } + + private class EffectTimer : Timer + { + private readonly int m_EffectID; + private readonly Point3D m_Location; + private readonly Map m_Map; + private readonly int m_SoundID; + + public EffectTimer(Point3D p, Map map, int effectID, int soundID, TimeSpan delay) : base(delay) + { + m_Location = p; + m_Map = map; + m_EffectID = effectID; + m_SoundID = soundID; + } + + protected override void OnTick() + { + Effects.SendLocationParticles( + EffectItem.Create(m_Location, m_Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + m_EffectID, + 0 + ); + + if (m_SoundID != -1) + Effects.PlaySound(m_Location, m_Map, m_SoundID); + } + } + + private class DelayTimer : Timer + { + private readonly Mobile m_Mobile; + private readonly HouseTeleporter m_Teleporter; + + public DelayTimer(HouseTeleporter tp, Mobile m) : base(TimeSpan.FromSeconds(1.0)) + { + m_Teleporter = tp; + m_Mobile = m; + } + + protected override void OnTick() + { + var target = m_Teleporter.Target; + + if (target?.Deleted != false) + return; + + var m = m_Mobile; + + if (m.Location != m_Teleporter.Location || m.Map != m_Teleporter.Map) + return; + + var p = target.GetWorldTop(); + var map = target.Map; + + BaseCreature.TeleportPets(m, p, map); + + m.MoveToWorld(p, map); + + if (m.Hidden && m.AccessLevel != AccessLevel.Player) + return; + + Effects.PlaySound(target.Location, target.Map, 0x1FE); + + Effects.SendLocationParticles( + EffectItem.Create(m_Teleporter.Location, m_Teleporter.Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 2023, + 0 + ); + Effects.SendLocationParticles( + EffectItem.Create(target.Location, target.Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 5023, + 0 + ); + + new EffectTimer(target.Location, target.Map, 2023, -1, TimeSpan.FromSeconds(0.4)).Start(); + } + } } - - public override void GetContextMenuEntries(Mobile from, List list) - { - base.GetContextMenuEntries(from, list); - SetSecureLevelEntry.AddTo(from, this, list); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write((int)Level); - - writer.Write(Target); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 1: - { - Level = (SecureLevel)reader.ReadInt(); - goto case 0; - } - case 0: - { - Target = reader.ReadItem(); - - if (version < 1) - Level = SecureLevel.Anyone; - - break; - } - } - } - - private class EffectTimer : Timer - { - private readonly int m_EffectID; - private readonly Point3D m_Location; - private readonly Map m_Map; - private readonly int m_SoundID; - - public EffectTimer(Point3D p, Map map, int effectID, int soundID, TimeSpan delay) : base(delay) - { - m_Location = p; - m_Map = map; - m_EffectID = effectID; - m_SoundID = soundID; - } - - protected override void OnTick() - { - Effects.SendLocationParticles(EffectItem.Create(m_Location, m_Map, EffectItem.DefaultDuration), 0x3728, 10, - 10, m_EffectID, 0); - - if (m_SoundID != -1) - Effects.PlaySound(m_Location, m_Map, m_SoundID); - } - } - - private class DelayTimer : Timer - { - private readonly Mobile m_Mobile; - private readonly HouseTeleporter m_Teleporter; - - public DelayTimer(HouseTeleporter tp, Mobile m) : base(TimeSpan.FromSeconds(1.0)) - { - m_Teleporter = tp; - m_Mobile = m; - } - - protected override void OnTick() - { - Item target = m_Teleporter.Target; - - if (target?.Deleted != false) - return; - - Mobile m = m_Mobile; - - if (m.Location != m_Teleporter.Location || m.Map != m_Teleporter.Map) - return; - - Point3D p = target.GetWorldTop(); - Map map = target.Map; - - BaseCreature.TeleportPets(m, p, map); - - m.MoveToWorld(p, map); - - if (m.Hidden && m.AccessLevel != AccessLevel.Player) - return; - - Effects.PlaySound(target.Location, target.Map, 0x1FE); - - Effects.SendLocationParticles( - EffectItem.Create(m_Teleporter.Location, m_Teleporter.Map, EffectItem.DefaultDuration), - 0x3728, 10, 10, 2023, 0); - Effects.SendLocationParticles( - EffectItem.Create(target.Location, target.Map, EffectItem.DefaultDuration), 0x3728, 10, 10, - 5023, 0); - - new EffectTimer(target.Location, target.Map, 2023, -1, TimeSpan.FromSeconds(0.4)).Start(); - } - } - } } diff --git a/Projects/UOContent/Multis/Houses.cs b/Projects/UOContent/Multis/Houses.cs index 32d7dceb3..7a2e43bf0 100644 --- a/Projects/UOContent/Multis/Houses.cs +++ b/Projects/UOContent/Multis/Houses.cs @@ -3,582 +3,582 @@ using Server.Multis.Deeds; namespace Server.Multis { - public class SmallOldHouse : BaseHouse - { - public static Rectangle2D[] AreaArray = { new Rectangle2D(-3, -3, 7, 7), new Rectangle2D(-1, 4, 3, 1) }; - - public SmallOldHouse(Mobile owner, int id) : base(id, owner, 425, 3) + public class SmallOldHouse : BaseHouse { - uint keyValue = CreateKeys(owner); + public static Rectangle2D[] AreaArray = { new Rectangle2D(-3, -3, 7, 7), new Rectangle2D(-1, 4, 3, 1) }; - AddSouthDoor(0, 3, 7, keyValue); + public SmallOldHouse(Mobile owner, int id) : base(id, owner, 425, 3) + { + var keyValue = CreateKeys(owner); - SetSign(2, 4, 5); + AddSouthDoor(0, 3, 7, keyValue); + + SetSign(2, 4, 5); + } + + public SmallOldHouse(Serial serial) : base(serial) + { + } + + public override Rectangle2D[] Area => AreaArray; + public override Point3D BaseBanLocation => new Point3D(2, 4, 0); + + public override int DefaultPrice => 43800; + + public override HousePlacementEntry ConvertEntry => HousePlacementEntry.TwoStoryFoundations[0]; + + public override HouseDeed GetDeed() + { + return ItemID switch + { + 0x64 => new StonePlasterHouseDeed(), + 0x66 => new FieldStoneHouseDeed(), + 0x68 => new SmallBrickHouseDeed(), + 0x6A => new WoodHouseDeed(), + 0x6C => new WoodPlasterHouseDeed(), + 0x6E => new ThatchedRoofCottageDeed(), + _ => new ThatchedRoofCottageDeed() + }; + } + + 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 SmallOldHouse(Serial serial) : base(serial) + public class GuildHouse : BaseHouse { + public static Rectangle2D[] AreaArray = { new Rectangle2D(-7, -7, 14, 14), new Rectangle2D(-2, 7, 4, 1) }; + + public GuildHouse(Mobile owner) : base(0x74, owner, 1100, 8) + { + var keyValue = CreateKeys(owner); + + AddSouthDoors(-1, 6, 7, keyValue); + + SetSign(4, 8, 16); + + AddSouthDoor(-3, -1, 7); + AddSouthDoor(3, -1, 7); + } + + public GuildHouse(Serial serial) : base(serial) + { + } + + public override int DefaultPrice => 144500; + + public override HousePlacementEntry ConvertEntry => HousePlacementEntry.ThreeStoryFoundations[20]; + public override int ConvertOffsetX => -1; + public override int ConvertOffsetY => -1; + + public override Rectangle2D[] Area => AreaArray; + public override Point3D BaseBanLocation => new Point3D(4, 8, 0); + + public override HouseDeed GetDeed() => new BrickHouseDeed(); + + 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 Rectangle2D[] Area => AreaArray; - public override Point3D BaseBanLocation => new Point3D(2, 4, 0); - - public override int DefaultPrice => 43800; - - public override HousePlacementEntry ConvertEntry => HousePlacementEntry.TwoStoryFoundations[0]; - - public override HouseDeed GetDeed() + public class TwoStoryHouse : BaseHouse { - return ItemID switch - { - 0x64 => (HouseDeed)new StonePlasterHouseDeed(), - 0x66 => new FieldStoneHouseDeed(), - 0x68 => new SmallBrickHouseDeed(), - 0x6A => new WoodHouseDeed(), - 0x6C => new WoodPlasterHouseDeed(), - 0x6E => new ThatchedRoofCottageDeed(), - _ => new ThatchedRoofCottageDeed() - }; + public static Rectangle2D[] AreaArray = + { new Rectangle2D(-7, 0, 14, 7), new Rectangle2D(-7, -7, 9, 7), new Rectangle2D(-4, 7, 4, 1) }; + + public TwoStoryHouse(Mobile owner, int id) : base(id, owner, 1370, 10) + { + var keyValue = CreateKeys(owner); + + AddSouthDoors(-3, 6, 7, keyValue); + + SetSign(2, 8, 16); + + AddSouthDoor(-3, 0, 7); + AddSouthDoor(id == 0x76 ? -2 : -3, 0, 27); + } + + public TwoStoryHouse(Serial serial) : base(serial) + { + } + + public override Rectangle2D[] Area => AreaArray; + public override Point3D BaseBanLocation => new Point3D(2, 8, 0); + + public override int DefaultPrice => 192400; + + public override HouseDeed GetDeed() + { + return ItemID switch + { + 0x76 => new TwoStoryWoodPlasterHouseDeed(), + 0x78 => new TwoStoryStonePlasterHouseDeed(), + _ => new TwoStoryStonePlasterHouseDeed() + }; + } + + 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 Serialize(IGenericWriter writer) + public class Tower : BaseHouse { - base.Serialize(writer); - writer.Write(0); // version + public static Rectangle2D[] AreaArray = + { + new Rectangle2D(-7, -7, 16, 14), new Rectangle2D(-1, 7, 4, 2), new Rectangle2D(-11, 0, 4, 7), + new Rectangle2D(9, 0, 4, 7) + }; + + public Tower(Mobile owner) : base(0x7A, owner, 2119, 15) + { + var keyValue = CreateKeys(owner); + + AddSouthDoors(false, 0, 6, 6, keyValue); + + SetSign(5, 8, 16); + + AddSouthDoor(false, 3, -2, 6); + AddEastDoor(false, 1, 4, 26); + AddEastDoor(false, 1, 4, 46); + } + + public Tower(Serial serial) : base(serial) + { + } + + public override int DefaultPrice => 433200; + + public override HousePlacementEntry ConvertEntry => HousePlacementEntry.ThreeStoryFoundations[37]; + public override int ConvertOffsetY => -1; + + public override Rectangle2D[] Area => AreaArray; + public override Point3D BaseBanLocation => new Point3D(5, 8, 0); + + public override HouseDeed GetDeed() => new TowerDeed(); + + 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 Deserialize(IGenericReader reader) + public class Keep : BaseHouse // warning: ODD shape! { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } + public static Rectangle2D[] AreaArray = + { + new Rectangle2D(-11, -11, 7, 8), new Rectangle2D(-11, 5, 7, 8), new Rectangle2D(6, -11, 7, 8), + new Rectangle2D(6, 5, 7, 8), new Rectangle2D(-9, -3, 5, 8), new Rectangle2D(6, -3, 5, 8), + new Rectangle2D(-4, -9, 10, 20), new Rectangle2D(-1, 11, 4, 1) + }; - public class GuildHouse : BaseHouse - { - public static Rectangle2D[] AreaArray = { new Rectangle2D(-7, -7, 14, 14), new Rectangle2D(-2, 7, 4, 1) }; + public Keep(Mobile owner) : base(0x7C, owner, 2625, 18) + { + var keyValue = CreateKeys(owner); - public GuildHouse(Mobile owner) : base(0x74, owner, 1100, 8) - { - uint keyValue = CreateKeys(owner); + AddSouthDoors(false, 0, 10, 6, keyValue); - AddSouthDoors(-1, 6, 7, keyValue); + SetSign(5, 12, 16); + } - SetSign(4, 8, 16); + public Keep(Serial serial) : base(serial) + { + } - AddSouthDoor(-3, -1, 7); - AddSouthDoor(3, -1, 7); + public override int DefaultPrice => 665200; + + public override Rectangle2D[] Area => AreaArray; + public override Point3D BaseBanLocation => new Point3D(5, 13, 0); + + public override HouseDeed GetDeed() => new KeepDeed(); + + 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 GuildHouse(Serial serial) : base(serial) + public class Castle : BaseHouse { + public static Rectangle2D[] AreaArray = { new Rectangle2D(-15, -15, 31, 31), new Rectangle2D(-1, 16, 4, 1) }; + + public Castle(Mobile owner) : base(0x7E, owner, 4076, 28) + { + var keyValue = CreateKeys(owner); + + AddSouthDoors(false, 0, 15, 6, keyValue); + + SetSign(5, 17, 16); + + AddSouthDoors(false, 0, 11, 6, true); + AddSouthDoors(false, 0, 5, 6, false); + AddSouthDoors(false, -1, -11, 6, false); + } + + public Castle(Serial serial) : base(serial) + { + } + + public override int DefaultPrice => 1022800; + + public override Rectangle2D[] Area => AreaArray; + public override Point3D BaseBanLocation => new Point3D(5, 17, 0); + + public override HouseDeed GetDeed() => new CastleDeed(); + + 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 int DefaultPrice => 144500; - - public override HousePlacementEntry ConvertEntry => HousePlacementEntry.ThreeStoryFoundations[20]; - public override int ConvertOffsetX => -1; - public override int ConvertOffsetY => -1; - - public override Rectangle2D[] Area => AreaArray; - public override Point3D BaseBanLocation => new Point3D(4, 8, 0); - - public override HouseDeed GetDeed() => new BrickHouseDeed(); - - public override void Serialize(IGenericWriter writer) + public class LargePatioHouse : BaseHouse { - base.Serialize(writer); - writer.Write(0); // version + public static Rectangle2D[] AreaArray = { new Rectangle2D(-7, -7, 15, 14), new Rectangle2D(-5, 7, 4, 1) }; + + public LargePatioHouse(Mobile owner) : base(0x8C, owner, 1100, 8) + { + var keyValue = CreateKeys(owner); + + AddSouthDoors(-4, 6, 7, keyValue); + + SetSign(1, 8, 16); + + AddEastDoor(1, 4, 7); + AddEastDoor(1, -4, 7); + AddSouthDoor(4, -1, 7); + } + + public LargePatioHouse(Serial serial) : base(serial) + { + } + + public override int DefaultPrice => 152800; + + public override HousePlacementEntry ConvertEntry => HousePlacementEntry.ThreeStoryFoundations[29]; + public override int ConvertOffsetY => -1; + + public override Rectangle2D[] Area => AreaArray; + public override Point3D BaseBanLocation => new Point3D(1, 8, 0); + + public override HouseDeed GetDeed() => new LargePatioDeed(); + + 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 Deserialize(IGenericReader reader) + public class LargeMarbleHouse : BaseHouse { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } + public static Rectangle2D[] AreaArray = { new Rectangle2D(-7, -7, 15, 14), new Rectangle2D(-6, 7, 6, 1) }; - public class TwoStoryHouse : BaseHouse - { - public static Rectangle2D[] AreaArray = - { new Rectangle2D(-7, 0, 14, 7), new Rectangle2D(-7, -7, 9, 7), new Rectangle2D(-4, 7, 4, 1) }; + public LargeMarbleHouse(Mobile owner) : base(0x96, owner, 1370, 10) + { + var keyValue = CreateKeys(owner); - public TwoStoryHouse(Mobile owner, int id) : base(id, owner, 1370, 10) - { - uint keyValue = CreateKeys(owner); + AddSouthDoors(false, -4, 3, 4, keyValue); - AddSouthDoors(-3, 6, 7, keyValue); + SetSign(1, 8, 11); + } - SetSign(2, 8, 16); + public LargeMarbleHouse(Serial serial) : base(serial) + { + } - AddSouthDoor(-3, 0, 7); - AddSouthDoor(id == 0x76 ? -2 : -3, 0, 27); + public override int DefaultPrice => 192000; + + public override HousePlacementEntry ConvertEntry => HousePlacementEntry.ThreeStoryFoundations[29]; + public override int ConvertOffsetY => -1; + + public override Rectangle2D[] Area => AreaArray; + public override Point3D BaseBanLocation => new Point3D(1, 8, 0); + + public override HouseDeed GetDeed() => new LargeMarbleDeed(); + + 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 TwoStoryHouse(Serial serial) : base(serial) + public class SmallTower : BaseHouse { + public static Rectangle2D[] AreaArray = { new Rectangle2D(-3, -3, 8, 7), new Rectangle2D(2, 4, 3, 1) }; + + public SmallTower(Mobile owner) : base(0x98, owner, 580, 4) + { + var keyValue = CreateKeys(owner); + + AddSouthDoor(false, 3, 3, 6, keyValue); + + SetSign(1, 4, 5); + } + + public SmallTower(Serial serial) : base(serial) + { + } + + public override int DefaultPrice => 88500; + + public override HousePlacementEntry ConvertEntry => HousePlacementEntry.TwoStoryFoundations[6]; + + public override Rectangle2D[] Area => AreaArray; + public override Point3D BaseBanLocation => new Point3D(1, 4, 0); + + public override HouseDeed GetDeed() => new SmallTowerDeed(); + + 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 Rectangle2D[] Area => AreaArray; - public override Point3D BaseBanLocation => new Point3D(2, 8, 0); - - public override int DefaultPrice => 192400; - - public override HouseDeed GetDeed() + public class LogCabin : BaseHouse { - return ItemID switch - { - 0x76 => (HouseDeed)new TwoStoryWoodPlasterHouseDeed(), - 0x78 => new TwoStoryStonePlasterHouseDeed(), - _ => new TwoStoryStonePlasterHouseDeed() - }; + public static Rectangle2D[] AreaArray = { new Rectangle2D(-3, -6, 8, 13) }; + + public LogCabin(Mobile owner) : base(0x9A, owner, 1100, 8) + { + var keyValue = CreateKeys(owner); + + AddSouthDoor(1, 4, 8, keyValue); + + SetSign(5, 8, 20); + + AddSouthDoor(1, 0, 29); + } + + public LogCabin(Serial serial) : base(serial) + { + } + + public override int DefaultPrice => 97800; + + public override HousePlacementEntry ConvertEntry => HousePlacementEntry.TwoStoryFoundations[12]; + + public override Rectangle2D[] Area => AreaArray; + public override Point3D BaseBanLocation => new Point3D(5, 8, 0); + + public override HouseDeed GetDeed() => new LogCabinDeed(); + + 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 Serialize(IGenericWriter writer) + public class SandStonePatio : BaseHouse { - base.Serialize(writer); - writer.Write(0); // version + public static Rectangle2D[] AreaArray = { new Rectangle2D(-5, -4, 12, 8), new Rectangle2D(-2, 4, 3, 1) }; + + public SandStonePatio(Mobile owner) : base(0x9C, owner, 850, 6) + { + var keyValue = CreateKeys(owner); + + AddSouthDoor(-1, 3, 6, keyValue); + + SetSign(4, 6, 24); + } + + public SandStonePatio(Serial serial) : base(serial) + { + } + + public override int DefaultPrice => 90900; + + public override HousePlacementEntry ConvertEntry => HousePlacementEntry.TwoStoryFoundations[35]; + public override int ConvertOffsetY => -1; + + public override Rectangle2D[] Area => AreaArray; + public override Point3D BaseBanLocation => new Point3D(4, 6, 0); + + public override HouseDeed GetDeed() => new SandstonePatioDeed(); + + 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 Deserialize(IGenericReader reader) + public class TwoStoryVilla : BaseHouse { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } + public static Rectangle2D[] AreaArray = { new Rectangle2D(-5, -5, 11, 11), new Rectangle2D(2, 6, 4, 1) }; - public class Tower : BaseHouse - { - public static Rectangle2D[] AreaArray = - { - new Rectangle2D(-7, -7, 16, 14), new Rectangle2D(-1, 7, 4, 2), new Rectangle2D(-11, 0, 4, 7), - new Rectangle2D(9, 0, 4, 7) - }; + public TwoStoryVilla(Mobile owner) : base(0x9E, owner, 1100, 8) + { + var keyValue = CreateKeys(owner); - public Tower(Mobile owner) : base(0x7A, owner, 2119, 15) - { - uint keyValue = CreateKeys(owner); + AddSouthDoors(3, 1, 5, keyValue); - AddSouthDoors(false, 0, 6, 6, keyValue); + SetSign(3, 8, 24); - SetSign(5, 8, 16); + AddEastDoor(1, 0, 25); + AddSouthDoor(-3, -1, 25); + } - AddSouthDoor(false, 3, -2, 6); - AddEastDoor(false, 1, 4, 26); - AddEastDoor(false, 1, 4, 46); + public TwoStoryVilla(Serial serial) : base(serial) + { + } + + public override int DefaultPrice => 136500; + + public override HousePlacementEntry ConvertEntry => HousePlacementEntry.TwoStoryFoundations[31]; + + public override Rectangle2D[] Area => AreaArray; + public override Point3D BaseBanLocation => new Point3D(3, 8, 0); + + public override HouseDeed GetDeed() => new VillaDeed(); + + 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 Tower(Serial serial) : base(serial) + public class SmallShop : BaseHouse { + public static Rectangle2D[] AreaArray1 = { new Rectangle2D(-3, -3, 7, 7), new Rectangle2D(-1, 4, 4, 1) }; + public static Rectangle2D[] AreaArray2 = { new Rectangle2D(-3, -3, 7, 7), new Rectangle2D(-2, 4, 3, 1) }; + + public SmallShop(Mobile owner, int id) : base(id, owner, 425, 3) + { + var keyValue = CreateKeys(owner); + + var door = MakeDoor(false, DoorFacing.EastCW); + + door.Locked = true; + door.KeyValue = keyValue; + + if (door is BaseHouseDoor houseDoor) + houseDoor.Facing = DoorFacing.EastCCW; + + AddDoor(door, -2, 0, id == 0xA2 ? 24 : 27); + + // AddSouthDoor( false, -2, 0, 27 - (id == 0xA2 ? 3 : 0), keyValue ); + + SetSign(3, 4, 7 - (id == 0xA2 ? 2 : 0)); + } + + public SmallShop(Serial serial) : base(serial) + { + } + + public override Rectangle2D[] Area => ItemID == 0x40A2 ? AreaArray1 : AreaArray2; + public override Point3D BaseBanLocation => new Point3D(3, 4, 0); + + public override int DefaultPrice => 63000; + + public override HousePlacementEntry ConvertEntry => HousePlacementEntry.TwoStoryFoundations[0]; + + public override HouseDeed GetDeed() + { + return ItemID switch + { + 0xA0 => new StoneWorkshopDeed(), + 0xA2 => new MarbleWorkshopDeed(), + _ => new MarbleWorkshopDeed() + }; + } + + 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 int DefaultPrice => 433200; - - public override HousePlacementEntry ConvertEntry => HousePlacementEntry.ThreeStoryFoundations[37]; - public override int ConvertOffsetY => -1; - - public override Rectangle2D[] Area => AreaArray; - public override Point3D BaseBanLocation => new Point3D(5, 8, 0); - - public override HouseDeed GetDeed() => new TowerDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class Keep : BaseHouse // warning: ODD shape! - { - public static Rectangle2D[] AreaArray = - { - new Rectangle2D(-11, -11, 7, 8), new Rectangle2D(-11, 5, 7, 8), new Rectangle2D(6, -11, 7, 8), - new Rectangle2D(6, 5, 7, 8), new Rectangle2D(-9, -3, 5, 8), new Rectangle2D(6, -3, 5, 8), - new Rectangle2D(-4, -9, 10, 20), new Rectangle2D(-1, 11, 4, 1) - }; - - public Keep(Mobile owner) : base(0x7C, owner, 2625, 18) - { - uint keyValue = CreateKeys(owner); - - AddSouthDoors(false, 0, 10, 6, keyValue); - - SetSign(5, 12, 16); - } - - public Keep(Serial serial) : base(serial) - { - } - - public override int DefaultPrice => 665200; - - public override Rectangle2D[] Area => AreaArray; - public override Point3D BaseBanLocation => new Point3D(5, 13, 0); - - public override HouseDeed GetDeed() => new KeepDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class Castle : BaseHouse - { - public static Rectangle2D[] AreaArray = { new Rectangle2D(-15, -15, 31, 31), new Rectangle2D(-1, 16, 4, 1) }; - - public Castle(Mobile owner) : base(0x7E, owner, 4076, 28) - { - uint keyValue = CreateKeys(owner); - - AddSouthDoors(false, 0, 15, 6, keyValue); - - SetSign(5, 17, 16); - - AddSouthDoors(false, 0, 11, 6, true); - AddSouthDoors(false, 0, 5, 6, false); - AddSouthDoors(false, -1, -11, 6, false); - } - - public Castle(Serial serial) : base(serial) - { - } - - public override int DefaultPrice => 1022800; - - public override Rectangle2D[] Area => AreaArray; - public override Point3D BaseBanLocation => new Point3D(5, 17, 0); - - public override HouseDeed GetDeed() => new CastleDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class LargePatioHouse : BaseHouse - { - public static Rectangle2D[] AreaArray = { new Rectangle2D(-7, -7, 15, 14), new Rectangle2D(-5, 7, 4, 1) }; - - public LargePatioHouse(Mobile owner) : base(0x8C, owner, 1100, 8) - { - uint keyValue = CreateKeys(owner); - - AddSouthDoors(-4, 6, 7, keyValue); - - SetSign(1, 8, 16); - - AddEastDoor(1, 4, 7); - AddEastDoor(1, -4, 7); - AddSouthDoor(4, -1, 7); - } - - public LargePatioHouse(Serial serial) : base(serial) - { - } - - public override int DefaultPrice => 152800; - - public override HousePlacementEntry ConvertEntry => HousePlacementEntry.ThreeStoryFoundations[29]; - public override int ConvertOffsetY => -1; - - public override Rectangle2D[] Area => AreaArray; - public override Point3D BaseBanLocation => new Point3D(1, 8, 0); - - public override HouseDeed GetDeed() => new LargePatioDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class LargeMarbleHouse : BaseHouse - { - public static Rectangle2D[] AreaArray = { new Rectangle2D(-7, -7, 15, 14), new Rectangle2D(-6, 7, 6, 1) }; - - public LargeMarbleHouse(Mobile owner) : base(0x96, owner, 1370, 10) - { - uint keyValue = CreateKeys(owner); - - AddSouthDoors(false, -4, 3, 4, keyValue); - - SetSign(1, 8, 11); - } - - public LargeMarbleHouse(Serial serial) : base(serial) - { - } - - public override int DefaultPrice => 192000; - - public override HousePlacementEntry ConvertEntry => HousePlacementEntry.ThreeStoryFoundations[29]; - public override int ConvertOffsetY => -1; - - public override Rectangle2D[] Area => AreaArray; - public override Point3D BaseBanLocation => new Point3D(1, 8, 0); - - public override HouseDeed GetDeed() => new LargeMarbleDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class SmallTower : BaseHouse - { - public static Rectangle2D[] AreaArray = { new Rectangle2D(-3, -3, 8, 7), new Rectangle2D(2, 4, 3, 1) }; - - public SmallTower(Mobile owner) : base(0x98, owner, 580, 4) - { - uint keyValue = CreateKeys(owner); - - AddSouthDoor(false, 3, 3, 6, keyValue); - - SetSign(1, 4, 5); - } - - public SmallTower(Serial serial) : base(serial) - { - } - - public override int DefaultPrice => 88500; - - public override HousePlacementEntry ConvertEntry => HousePlacementEntry.TwoStoryFoundations[6]; - - public override Rectangle2D[] Area => AreaArray; - public override Point3D BaseBanLocation => new Point3D(1, 4, 0); - - public override HouseDeed GetDeed() => new SmallTowerDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class LogCabin : BaseHouse - { - public static Rectangle2D[] AreaArray = { new Rectangle2D(-3, -6, 8, 13) }; - - public LogCabin(Mobile owner) : base(0x9A, owner, 1100, 8) - { - uint keyValue = CreateKeys(owner); - - AddSouthDoor(1, 4, 8, keyValue); - - SetSign(5, 8, 20); - - AddSouthDoor(1, 0, 29); - } - - public LogCabin(Serial serial) : base(serial) - { - } - - public override int DefaultPrice => 97800; - - public override HousePlacementEntry ConvertEntry => HousePlacementEntry.TwoStoryFoundations[12]; - - public override Rectangle2D[] Area => AreaArray; - public override Point3D BaseBanLocation => new Point3D(5, 8, 0); - - public override HouseDeed GetDeed() => new LogCabinDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class SandStonePatio : BaseHouse - { - public static Rectangle2D[] AreaArray = { new Rectangle2D(-5, -4, 12, 8), new Rectangle2D(-2, 4, 3, 1) }; - - public SandStonePatio(Mobile owner) : base(0x9C, owner, 850, 6) - { - uint keyValue = CreateKeys(owner); - - AddSouthDoor(-1, 3, 6, keyValue); - - SetSign(4, 6, 24); - } - - public SandStonePatio(Serial serial) : base(serial) - { - } - - public override int DefaultPrice => 90900; - - public override HousePlacementEntry ConvertEntry => HousePlacementEntry.TwoStoryFoundations[35]; - public override int ConvertOffsetY => -1; - - public override Rectangle2D[] Area => AreaArray; - public override Point3D BaseBanLocation => new Point3D(4, 6, 0); - - public override HouseDeed GetDeed() => new SandstonePatioDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class TwoStoryVilla : BaseHouse - { - public static Rectangle2D[] AreaArray = { new Rectangle2D(-5, -5, 11, 11), new Rectangle2D(2, 6, 4, 1) }; - - public TwoStoryVilla(Mobile owner) : base(0x9E, owner, 1100, 8) - { - uint keyValue = CreateKeys(owner); - - AddSouthDoors(3, 1, 5, keyValue); - - SetSign(3, 8, 24); - - AddEastDoor(1, 0, 25); - AddSouthDoor(-3, -1, 25); - } - - public TwoStoryVilla(Serial serial) : base(serial) - { - } - - public override int DefaultPrice => 136500; - - public override HousePlacementEntry ConvertEntry => HousePlacementEntry.TwoStoryFoundations[31]; - - public override Rectangle2D[] Area => AreaArray; - public override Point3D BaseBanLocation => new Point3D(3, 8, 0); - - public override HouseDeed GetDeed() => new VillaDeed(); - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } - - public class SmallShop : BaseHouse - { - public static Rectangle2D[] AreaArray1 = { new Rectangle2D(-3, -3, 7, 7), new Rectangle2D(-1, 4, 4, 1) }; - public static Rectangle2D[] AreaArray2 = { new Rectangle2D(-3, -3, 7, 7), new Rectangle2D(-2, 4, 3, 1) }; - - public SmallShop(Mobile owner, int id) : base(id, owner, 425, 3) - { - uint keyValue = CreateKeys(owner); - - BaseDoor door = MakeDoor(false, DoorFacing.EastCW); - - door.Locked = true; - door.KeyValue = keyValue; - - if (door is BaseHouseDoor houseDoor) - houseDoor.Facing = DoorFacing.EastCCW; - - AddDoor(door, -2, 0, id == 0xA2 ? 24 : 27); - - // AddSouthDoor( false, -2, 0, 27 - (id == 0xA2 ? 3 : 0), keyValue ); - - SetSign(3, 4, 7 - (id == 0xA2 ? 2 : 0)); - } - - public SmallShop(Serial serial) : base(serial) - { - } - - public override Rectangle2D[] Area => ItemID == 0x40A2 ? AreaArray1 : AreaArray2; - public override Point3D BaseBanLocation => new Point3D(3, 4, 0); - - public override int DefaultPrice => 63000; - - public override HousePlacementEntry ConvertEntry => HousePlacementEntry.TwoStoryFoundations[0]; - - public override HouseDeed GetDeed() - { - return ItemID switch - { - 0xA0 => (HouseDeed)new StoneWorkshopDeed(), - 0xA2 => new MarbleWorkshopDeed(), - _ => new MarbleWorkshopDeed() - }; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Multis/MovingCrate.cs b/Projects/UOContent/Multis/MovingCrate.cs index 037d1d750..e88fc0b81 100644 --- a/Projects/UOContent/Multis/MovingCrate.cs +++ b/Projects/UOContent/Multis/MovingCrate.cs @@ -5,301 +5,303 @@ using Server.Network; namespace Server.Multis { - public class MovingCrate : Container - { - public static readonly int MaxItemsPerSubcontainer = 20; - public static readonly int Rows = 3; - public static readonly int Columns = 5; - public static readonly int HorizontalSpacing = 25; - public static readonly int VerticalSpacing = 25; - - private Timer m_InternalizeTimer; - - public MovingCrate(BaseHouse house) : base(0xE3D) + public class MovingCrate : Container { - Hue = 0x8A5; - Movable = false; + public static readonly int MaxItemsPerSubcontainer = 20; + public static readonly int Rows = 3; + public static readonly int Columns = 5; + public static readonly int HorizontalSpacing = 25; + public static readonly int VerticalSpacing = 25; - House = house; - } + private Timer m_InternalizeTimer; - public MovingCrate(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061690; // Packing Crate - - public BaseHouse House { get; set; } - - public override int DefaultMaxItems => 0; - public override int DefaultMaxWeight => 0; - - public override bool IsDecoContainer => false; - - /* - public override void AddNameProperties( ObjectPropertyList list ) - { - base.AddNameProperties( list ); - - if (House != null && House.InternalizedVendors.Count > 0) - list.Add( 1061833, House.InternalizedVendors.Count.ToString() ); // This packing crate contains ~1_COUNT~ vendors/barkeepers. - } - */ - - public override void DropItem(Item dropped) - { - // 1. Try to stack the item - foreach (Item item in Items) - if (item is PackingBox) + public MovingCrate(BaseHouse house) : base(0xE3D) { - List subItems = item.Items; + Hue = 0x8A5; + Movable = false; - for (int i = 0; i < subItems.Count; i++) - { - Item subItem = subItems[i]; - - if (!(subItem is Container) && subItem.StackWith(null, dropped, false)) - return; - } + House = house; } - // 2. Try to drop the item into an existing container - foreach (Item item in Items) - if (item is PackingBox packingBox) + public MovingCrate(Serial serial) : base(serial) { - Container box = packingBox; - List subItems = box.Items; - - if (subItems.Count < MaxItemsPerSubcontainer) - { - box.DropItem(dropped); - return; - } } - // 3. Drop the item into a new container - Container subContainer = new PackingBox(); - subContainer.DropItem(dropped); + public override int LabelNumber => 1061690; // Packing Crate - Point3D location = GetFreeLocation(); - if (location != Point3D.Zero) - { - AddItem(subContainer); - subContainer.Location = location; - } - else - { - base.DropItem(subContainer); - } - } + public BaseHouse House { get; set; } - private Point3D GetFreeLocation() - { - bool[,] positions = new bool[Rows, Columns]; + public override int DefaultMaxItems => 0; + public override int DefaultMaxWeight => 0; - foreach (Item item in Items) - if (item is PackingBox) + public override bool IsDecoContainer => false; + + /* + public override void AddNameProperties( ObjectPropertyList list ) { - int i = (item.Y - Bounds.Y) / VerticalSpacing; - if (i < 0) - i = 0; - else if (i >= Rows) - i = Rows - 1; + base.AddNameProperties( list ); + + if (House != null && House.InternalizedVendors.Count > 0) + list.Add( 1061833, House.InternalizedVendors.Count.ToString() ); // This packing crate contains ~1_COUNT~ vendors/barkeepers. + } + */ - int j = (item.X - Bounds.X) / HorizontalSpacing; - if (j < 0) - j = 0; - else if (j >= Columns) - j = Columns - 1; + public override void DropItem(Item dropped) + { + // 1. Try to stack the item + foreach (var item in Items) + if (item is PackingBox) + { + var subItems = item.Items; - positions[i, j] = true; + for (var i = 0; i < subItems.Count; i++) + { + var subItem = subItems[i]; + + if (!(subItem is Container) && subItem.StackWith(null, dropped, false)) + return; + } + } + + // 2. Try to drop the item into an existing container + foreach (var item in Items) + if (item is PackingBox packingBox) + { + Container box = packingBox; + var subItems = box.Items; + + if (subItems.Count < MaxItemsPerSubcontainer) + { + box.DropItem(dropped); + return; + } + } + + // 3. Drop the item into a new container + Container subContainer = new PackingBox(); + subContainer.DropItem(dropped); + + var location = GetFreeLocation(); + if (location != Point3D.Zero) + { + AddItem(subContainer); + subContainer.Location = location; + } + else + { + base.DropItem(subContainer); + } } - for (int i = 0; i < Rows; i++) - for (int j = 0; j < Columns; j++) - if (!positions[i, j]) - { - int x = Bounds.X + j * HorizontalSpacing; - int y = Bounds.Y + i * VerticalSpacing; + private Point3D GetFreeLocation() + { + var positions = new bool[Rows, Columns]; - return new Point3D(x, y, 0); - } + foreach (var item in Items) + if (item is PackingBox) + { + var i = (item.Y - Bounds.Y) / VerticalSpacing; + if (i < 0) + i = 0; + else if (i >= Rows) + i = Rows - 1; - return Point3D.Zero; + var j = (item.X - Bounds.X) / HorizontalSpacing; + if (j < 0) + j = 0; + else if (j >= Columns) + j = Columns - 1; + + positions[i, j] = true; + } + + for (var i = 0; i < Rows; i++) + for (var j = 0; j < Columns; j++) + if (!positions[i, j]) + { + var x = Bounds.X + j * HorizontalSpacing; + var y = Bounds.Y + i * VerticalSpacing; + + return new Point3D(x, y, 0); + } + + return Point3D.Zero; + } + + public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight) + { + if (m.AccessLevel < AccessLevel.GameMaster) + { + m.SendLocalizedMessage(1061145); // You cannot place items into a house moving crate. + return false; + } + + return base.CheckHold(m, item, message, checkItems, plusItems, plusWeight); + } + + public override bool CheckLift(Mobile from, Item item, ref LRReason reject) => House?.Deleted == false && + base.CheckLift(from, item, ref reject) && House.IsOwner(from); + + public override bool CheckItemUse(Mobile from, Item item) => + House?.Deleted == false && base.CheckItemUse(from, item) && House.IsOwner(from); + + public override void OnItemRemoved(Item item) + { + base.OnItemRemoved(item); + + if (TotalItems == 0) + Delete(); + } + + public void RestartTimer() + { + if (m_InternalizeTimer == null) + { + m_InternalizeTimer = new InternalizeTimer(this); + m_InternalizeTimer.Start(); + } + else + { + m_InternalizeTimer.Stop(); + m_InternalizeTimer.Start(); + } + } + + public void Hide() + { + if (m_InternalizeTimer != null) + { + m_InternalizeTimer.Stop(); + m_InternalizeTimer = null; + } + + var toRemove = new List(); + foreach (var item in Items) + if (item is PackingBox && item.Items.Count == 0) + toRemove.Add(item); + + foreach (var item in toRemove) + item.Delete(); + + if (TotalItems == 0) + Delete(); + else + Internalize(); + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + if (House?.MovingCrate == this) + House.MovingCrate = null; + + m_InternalizeTimer?.Stop(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(1); + + writer.Write(House); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + House = reader.ReadItem() as BaseHouse; + + if (House != null) + { + House.MovingCrate = this; + Timer.DelayCall(Hide); + } + else + { + Timer.DelayCall(Delete); + } + + if (version == 0) + MaxItems = -1; // reset to default + } + + public class InternalizeTimer : Timer + { + private readonly MovingCrate m_Crate; + + public InternalizeTimer(MovingCrate crate) : base(TimeSpan.FromMinutes(5.0)) + { + m_Crate = crate; + + Priority = TimerPriority.FiveSeconds; + } + + protected override void OnTick() + { + m_Crate.Hide(); + } + } } - public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight) + public class PackingBox : BaseContainer { - if (m.AccessLevel < AccessLevel.GameMaster) - { - m.SendLocalizedMessage(1061145); // You cannot place items into a house moving crate. - return false; - } + public PackingBox() : base(0x9A8) => Movable = false; - return base.CheckHold(m, item, message, checkItems, plusItems, plusWeight); + public PackingBox(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1061690; // Packing Crate + + public override int DefaultGumpID => 0x4B; + public override int DefaultDropSound => 0x42; + + public override Rectangle2D Bounds => new Rectangle2D(16, 51, 168, 73); + + public override int DefaultMaxItems => 0; + public override int DefaultMaxWeight => 0; + + public override void SendCantStoreMessage(Mobile to, Item item) + { + to.SendLocalizedMessage(1061145); // You cannot place items into a house moving crate. + } + + public override void OnItemRemoved(Item item) + { + base.OnItemRemoved(item); + + if (item.GetBounce() == null && TotalItems == 0) + Delete(); + } + + public override void OnItemBounceCleared(Item item) + { + base.OnItemBounceCleared(item); + + if (TotalItems == 0) + Delete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(1); // version + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + if (version == 0) + MaxItems = -1; // reset to default + } } - - public override bool CheckLift(Mobile from, Item item, ref LRReason reject) => House?.Deleted == false && base.CheckLift(from, item, ref reject) && House.IsOwner(from); - - public override bool CheckItemUse(Mobile from, Item item) => House?.Deleted == false && base.CheckItemUse(from, item) && House.IsOwner(from); - - public override void OnItemRemoved(Item item) - { - base.OnItemRemoved(item); - - if (TotalItems == 0) - Delete(); - } - - public void RestartTimer() - { - if (m_InternalizeTimer == null) - { - m_InternalizeTimer = new InternalizeTimer(this); - m_InternalizeTimer.Start(); - } - else - { - m_InternalizeTimer.Stop(); - m_InternalizeTimer.Start(); - } - } - - public void Hide() - { - if (m_InternalizeTimer != null) - { - m_InternalizeTimer.Stop(); - m_InternalizeTimer = null; - } - - List toRemove = new List(); - foreach (Item item in Items) - if (item is PackingBox && item.Items.Count == 0) - toRemove.Add(item); - - foreach (Item item in toRemove) - item.Delete(); - - if (TotalItems == 0) - Delete(); - else - Internalize(); - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - if (House?.MovingCrate == this) - House.MovingCrate = null; - - m_InternalizeTimer?.Stop(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(1); - - writer.Write(House); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - House = reader.ReadItem() as BaseHouse; - - if (House != null) - { - House.MovingCrate = this; - Timer.DelayCall(Hide); - } - else - { - Timer.DelayCall(Delete); - } - - if (version == 0) - MaxItems = -1; // reset to default - } - - public class InternalizeTimer : Timer - { - private readonly MovingCrate m_Crate; - - public InternalizeTimer(MovingCrate crate) : base(TimeSpan.FromMinutes(5.0)) - { - m_Crate = crate; - - Priority = TimerPriority.FiveSeconds; - } - - protected override void OnTick() - { - m_Crate.Hide(); - } - } - } - - public class PackingBox : BaseContainer - { - public PackingBox() : base(0x9A8) => Movable = false; - - public PackingBox(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1061690; // Packing Crate - - public override int DefaultGumpID => 0x4B; - public override int DefaultDropSound => 0x42; - - public override Rectangle2D Bounds => new Rectangle2D(16, 51, 168, 73); - - public override int DefaultMaxItems => 0; - public override int DefaultMaxWeight => 0; - - public override void SendCantStoreMessage(Mobile to, Item item) - { - to.SendLocalizedMessage(1061145); // You cannot place items into a house moving crate. - } - - public override void OnItemRemoved(Item item) - { - base.OnItemRemoved(item); - - if (item.GetBounce() == null && TotalItems == 0) - Delete(); - } - - public override void OnItemBounceCleared(Item item) - { - base.OnItemBounceCleared(item); - - if (TotalItems == 0) - Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(1); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - if (version == 0) - MaxItems = -1; // reset to default - } - } } diff --git a/Projects/UOContent/Multis/PreviewHouse.cs b/Projects/UOContent/Multis/PreviewHouse.cs index 6d02992aa..f6408e5fb 100644 --- a/Projects/UOContent/Multis/PreviewHouse.cs +++ b/Projects/UOContent/Multis/PreviewHouse.cs @@ -4,139 +4,139 @@ using Server.Items; namespace Server.Multis { - public class PreviewHouse : BaseMulti - { - private List m_Components; - private Timer m_Timer; - - public PreviewHouse(int multiID) : base(multiID) + public class PreviewHouse : BaseMulti { - m_Components = new List(); + private List m_Components; + private Timer m_Timer; - MultiComponentList mcl = Components; - - for (int i = 1; i < mcl.List.Length; ++i) - { - MultiTileEntry entry = mcl.List[i]; - - if (entry.Flags == 0) + public PreviewHouse(int multiID) : base(multiID) { - Item item = new Static((int)entry.ItemId); + m_Components = new List(); - item.MoveToWorld(new Point3D(X + entry.OffsetX, Y + entry.OffsetY, Z + entry.OffsetZ), Map); + var mcl = Components; - m_Components.Add(item); + for (var i = 1; i < mcl.List.Length; ++i) + { + var entry = mcl.List[i]; + + if (entry.Flags == 0) + { + Item item = new Static((int)entry.ItemId); + + item.MoveToWorld(new Point3D(X + entry.OffsetX, Y + entry.OffsetY, Z + entry.OffsetZ), Map); + + m_Components.Add(item); + } + } + + m_Timer = new DecayTimer(this); + m_Timer.Start(); } - } - m_Timer = new DecayTimer(this); - m_Timer.Start(); + public PreviewHouse(Serial serial) : base(serial) + { + } + + public override void OnLocationChange(Point3D oldLocation) + { + base.OnLocationChange(oldLocation); + + if (m_Components == null) + return; + + var xOffset = X - oldLocation.X; + var yOffset = Y - oldLocation.Y; + var zOffset = Z - oldLocation.Z; + + for (var i = 0; i < m_Components.Count; ++i) + { + var item = m_Components[i]; + + item.MoveToWorld(new Point3D(item.X + xOffset, item.Y + yOffset, item.Z + zOffset), Map); + } + } + + public override void OnMapChange() + { + base.OnMapChange(); + + if (m_Components == null) + return; + + for (var i = 0; i < m_Components.Count; ++i) + { + var item = m_Components[i]; + + item.Map = Map; + } + } + + public override void OnDelete() + { + base.OnDelete(); + + if (m_Components == null) + return; + + for (var i = 0; i < m_Components.Count; ++i) + { + var item = m_Components[i]; + + item.Delete(); + } + } + + public override void OnAfterDelete() + { + m_Timer?.Stop(); + + m_Timer = null; + + base.OnAfterDelete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Components); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Components = reader.ReadStrongItemList(); + + break; + } + } + + Timer.DelayCall(Delete); + } + + private class DecayTimer : Timer + { + private readonly Item m_Item; + + public DecayTimer(Item item) : base(TimeSpan.FromSeconds(20.0)) + { + m_Item = item; + Priority = TimerPriority.OneSecond; + } + + protected override void OnTick() + { + m_Item.Delete(); + } + } } - - public PreviewHouse(Serial serial) : base(serial) - { - } - - public override void OnLocationChange(Point3D oldLocation) - { - base.OnLocationChange(oldLocation); - - if (m_Components == null) - return; - - int xOffset = X - oldLocation.X; - int yOffset = Y - oldLocation.Y; - int zOffset = Z - oldLocation.Z; - - for (int i = 0; i < m_Components.Count; ++i) - { - Item item = m_Components[i]; - - item.MoveToWorld(new Point3D(item.X + xOffset, item.Y + yOffset, item.Z + zOffset), Map); - } - } - - public override void OnMapChange() - { - base.OnMapChange(); - - if (m_Components == null) - return; - - for (int i = 0; i < m_Components.Count; ++i) - { - Item item = m_Components[i]; - - item.Map = Map; - } - } - - public override void OnDelete() - { - base.OnDelete(); - - if (m_Components == null) - return; - - for (int i = 0; i < m_Components.Count; ++i) - { - Item item = m_Components[i]; - - item.Delete(); - } - } - - public override void OnAfterDelete() - { - m_Timer?.Stop(); - - m_Timer = null; - - base.OnAfterDelete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Components); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_Components = reader.ReadStrongItemList(); - - break; - } - } - - Timer.DelayCall(Delete); - } - - private class DecayTimer : Timer - { - private readonly Item m_Item; - - public DecayTimer(Item item) : base(TimeSpan.FromSeconds(20.0)) - { - m_Item = item; - Priority = TimerPriority.OneSecond; - } - - protected override void OnTick() - { - m_Item.Delete(); - } - } - } } diff --git a/Projects/UOContent/Regions/BaseRegion.cs b/Projects/UOContent/Regions/BaseRegion.cs index 6d28f5b33..c65e23996 100644 --- a/Projects/UOContent/Regions/BaseRegion.cs +++ b/Projects/UOContent/Regions/BaseRegion.cs @@ -8,158 +8,160 @@ using Server.Spells; namespace Server.Regions { - public class BaseRegion : Region - { - private static readonly List m_RectBuffer1 = new List(); - private static readonly List m_RectBuffer2 = new List(); - - public bool ExcludeFromParentSpawns { get; set; } - - public Rectangle3D[] Rectangles { get; private set; } - public int[] RectangleWeights { get; private set; } - - private string m_RuneName; - public int TotalWeight { get; private set; } - - public BaseRegion(string name, Map map, int priority, params Rectangle2D[] area) : base(name, map, priority, area) + public class BaseRegion : Region { - } + private static readonly List m_RectBuffer1 = new List(); + private static readonly List m_RectBuffer2 = new List(); - public BaseRegion(string name, Map map, int priority, params Rectangle3D[] area) : base(name, map, priority, area) - { - } - - public BaseRegion(string name, Map map, Region parent, params Rectangle2D[] area) : base(name, map, parent, area) - { - } - - public BaseRegion(string name, Map map, Region parent, params Rectangle3D[] area) : base(name, map, parent, area) - { - } - - public BaseRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) - { - if (json.data.TryGetValue("rune", out var runeName)) - m_RuneName = runeName.GetString(); - - NoLogoutDelay = json.data.TryGetValue("logoutDelay", out var logoutDelay) && !logoutDelay.GetBoolean(); - } - - public virtual bool YoungProtected => true; - public virtual bool YoungMayEnter => true; - public virtual bool MountsAllowed => true; - public virtual bool DeadMayEnter => true; - public virtual bool ResurrectionAllowed => true; - public virtual bool LogoutAllowed => true; - - public string RuneName - { - get => m_RuneName; - set => m_RuneName = value; - } - - public bool NoLogoutDelay { get; set; } - - public static void Configure() - { - DefaultRegionType = typeof(BaseRegion); - } - - public static string GetRuneNameFor(Region region) - { - while (region != null) - { - BaseRegion br = region as BaseRegion; - - if (br?.m_RuneName != null) - return br.m_RuneName; - - region = region.Parent; - } - - return null; - } - - public override TimeSpan GetLogoutDelay(Mobile m) => - NoLogoutDelay && m.Aggressors.Count == 0 && m.Aggressed.Count == 0 && !m.Criminal - ? TimeSpan.Zero - : base.GetLogoutDelay(m); - - public override void OnEnter(Mobile m) - { - if (m is PlayerMobile mobile && mobile.Young && !YoungProtected) - mobile.SendGump(new YoungDungeonWarning()); - } - - public override bool AcceptsSpawnsFrom(Region region) => - (region == this || !ExcludeFromParentSpawns) && base.AcceptsSpawnsFrom(region); - - // TODO: Clean this up - public void InitRectangles() - { - if (Rectangles != null) - return; - - // Test if area rectangles are overlapping, and in that case break them into smaller non overlapping rectangles - for (int i = 0; i < Area.Length; i++) - { - m_RectBuffer2.Add(Area[i]); - - for (int j = 0; j < m_RectBuffer1.Count && m_RectBuffer2.Count > 0; j++) + public BaseRegion(string name, Map map, int priority, params Rectangle2D[] area) : base(name, map, priority, area) { - Rectangle3D comp = m_RectBuffer1[j]; - - for (int k = m_RectBuffer2.Count - 1; k >= 0; k--) - { - Rectangle3D rect = m_RectBuffer2[k]; - - int l1 = rect.Start.X, r1 = rect.End.X, t1 = rect.Start.Y, b1 = rect.End.Y; - int l2 = comp.Start.X, r2 = comp.End.X, t2 = comp.Start.Y, b2 = comp.End.Y; - - if (l1 < r2 && r1 > l2 && t1 < b2 && b1 > t2) - { - m_RectBuffer2.RemoveAt(k); - - int sz = rect.Start.Z; - int ez = rect.End.X; - - if (l1 < l2) - m_RectBuffer2.Add(new Rectangle3D(new Point3D(l1, t1, sz), new Point3D(l2, b1, ez))); - - if (r1 > r2) - m_RectBuffer2.Add(new Rectangle3D(new Point3D(r2, t1, sz), new Point3D(r1, b1, ez))); - - if (t1 < t2) - m_RectBuffer2.Add(new Rectangle3D(new Point3D(Math.Max(l1, l2), t1, sz), - new Point3D(Math.Min(r1, r2), t2, ez))); - - if (b1 > b2) - m_RectBuffer2.Add(new Rectangle3D(new Point3D(Math.Max(l1, l2), b2, sz), - new Point3D(Math.Min(r1, r2), b1, ez))); - } - } } - m_RectBuffer1.AddRange(m_RectBuffer2); - m_RectBuffer2.Clear(); - } + public BaseRegion(string name, Map map, int priority, params Rectangle3D[] area) : base(name, map, priority, area) + { + } - Rectangles = m_RectBuffer1.ToArray(); - m_RectBuffer1.Clear(); + public BaseRegion(string name, Map map, Region parent, params Rectangle2D[] area) : base(name, map, parent, area) + { + } - RectangleWeights = new int[Rectangles.Length]; - for (int i = 0; i < Rectangles.Length; i++) - { - Rectangle3D rect = Rectangles[i]; - int weight = rect.Width * rect.Height; + public BaseRegion(string name, Map map, Region parent, params Rectangle3D[] area) : base(name, map, parent, area) + { + } - RectangleWeights[i] = weight; - TotalWeight += weight; - } + public BaseRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) + { + if (json.data.TryGetValue("rune", out var runeName)) + RuneName = runeName.GetString(); + + NoLogoutDelay = json.data.TryGetValue("logoutDelay", out var logoutDelay) && !logoutDelay.GetBoolean(); + } + + public bool ExcludeFromParentSpawns { get; set; } + + public Rectangle3D[] Rectangles { get; private set; } + public int[] RectangleWeights { get; private set; } + public int TotalWeight { get; private set; } + + public virtual bool YoungProtected => true; + public virtual bool YoungMayEnter => true; + public virtual bool MountsAllowed => true; + public virtual bool DeadMayEnter => true; + public virtual bool ResurrectionAllowed => true; + public virtual bool LogoutAllowed => true; + + public string RuneName { get; set; } + + public bool NoLogoutDelay { get; set; } + + public static void Configure() + { + DefaultRegionType = typeof(BaseRegion); + } + + public static string GetRuneNameFor(Region region) + { + while (region != null) + { + var br = region as BaseRegion; + + if (br?.RuneName != null) + return br.RuneName; + + region = region.Parent; + } + + return null; + } + + public override TimeSpan GetLogoutDelay(Mobile m) => + NoLogoutDelay && m.Aggressors.Count == 0 && m.Aggressed.Count == 0 && !m.Criminal + ? TimeSpan.Zero + : base.GetLogoutDelay(m); + + public override void OnEnter(Mobile m) + { + if (m is PlayerMobile mobile && mobile.Young && !YoungProtected) + mobile.SendGump(new YoungDungeonWarning()); + } + + public override bool AcceptsSpawnsFrom(Region region) => + (region == this || !ExcludeFromParentSpawns) && base.AcceptsSpawnsFrom(region); + + // TODO: Clean this up + public void InitRectangles() + { + if (Rectangles != null) + return; + + // Test if area rectangles are overlapping, and in that case break them into smaller non overlapping rectangles + for (var i = 0; i < Area.Length; i++) + { + m_RectBuffer2.Add(Area[i]); + + for (var j = 0; j < m_RectBuffer1.Count && m_RectBuffer2.Count > 0; j++) + { + var comp = m_RectBuffer1[j]; + + for (var k = m_RectBuffer2.Count - 1; k >= 0; k--) + { + var rect = m_RectBuffer2[k]; + + int l1 = rect.Start.X, r1 = rect.End.X, t1 = rect.Start.Y, b1 = rect.End.Y; + int l2 = comp.Start.X, r2 = comp.End.X, t2 = comp.Start.Y, b2 = comp.End.Y; + + if (l1 < r2 && r1 > l2 && t1 < b2 && b1 > t2) + { + m_RectBuffer2.RemoveAt(k); + + var sz = rect.Start.Z; + var ez = rect.End.X; + + if (l1 < l2) + m_RectBuffer2.Add(new Rectangle3D(new Point3D(l1, t1, sz), new Point3D(l2, b1, ez))); + + if (r1 > r2) + m_RectBuffer2.Add(new Rectangle3D(new Point3D(r2, t1, sz), new Point3D(r1, b1, ez))); + + if (t1 < t2) + m_RectBuffer2.Add( + new Rectangle3D( + new Point3D(Math.Max(l1, l2), t1, sz), + new Point3D(Math.Min(r1, r2), t2, ez) + ) + ); + + if (b1 > b2) + m_RectBuffer2.Add( + new Rectangle3D( + new Point3D(Math.Max(l1, l2), b2, sz), + new Point3D(Math.Min(r1, r2), b1, ez) + ) + ); + } + } + } + + m_RectBuffer1.AddRange(m_RectBuffer2); + m_RectBuffer2.Clear(); + } + + Rectangles = m_RectBuffer1.ToArray(); + m_RectBuffer1.Clear(); + + RectangleWeights = new int[Rectangles.Length]; + for (var i = 0; i < Rectangles.Length; i++) + { + var rect = Rectangles[i]; + var weight = rect.Width * rect.Height; + + RectangleWeights[i] = weight; + TotalWeight += weight; + } + } + + public override string ToString() => Name ?? RuneName ?? GetType().Name; + + public virtual bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType) => true; } - - public override string ToString() => Name ?? RuneName ?? GetType().Name; - - public virtual bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType) => true; - } } diff --git a/Projects/UOContent/Regions/DungeonRegion.cs b/Projects/UOContent/Regions/DungeonRegion.cs index 0bb10ef21..7d2d0974d 100644 --- a/Projects/UOContent/Regions/DungeonRegion.cs +++ b/Projects/UOContent/Regions/DungeonRegion.cs @@ -3,30 +3,30 @@ using Server.Json; namespace Server.Regions { - public class DungeonRegion : BaseRegion - { - public DungeonRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) + public class DungeonRegion : BaseRegion { - if (json.GetProperty("map", options, out Map map)) - EntranceMap = map; + public DungeonRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) + { + if (json.GetProperty("map", options, out Map map)) + EntranceMap = map; - if (json.GetProperty("entrance", options, out Point3D entrance)) - EntranceLocation = entrance; + if (json.GetProperty("entrance", options, out Point3D entrance)) + EntranceLocation = entrance; + } + + public override bool YoungProtected => false; + + public Point3D EntranceLocation { get; set; } + + public Map EntranceMap { get; set; } + + public override bool AllowHousing(Mobile from, Point3D p) => false; + + public override void AlterLightLevel(Mobile m, ref int global, ref int personal) + { + global = LightCycle.DungeonLevel; + } + + public override bool CanUseStuckMenu(Mobile m) => Map != Map.Felucca && base.CanUseStuckMenu(m); } - - public override bool YoungProtected => false; - - public Point3D EntranceLocation { get; set; } - - public Map EntranceMap { get; set; } - - public override bool AllowHousing(Mobile from, Point3D p) => false; - - public override void AlterLightLevel(Mobile m, ref int global, ref int personal) - { - global = LightCycle.DungeonLevel; - } - - public override bool CanUseStuckMenu(Mobile m) => Map != Map.Felucca && base.CanUseStuckMenu(m); - } } diff --git a/Projects/UOContent/Regions/GreenAcresRegion.cs b/Projects/UOContent/Regions/GreenAcresRegion.cs index 5d85d4747..c7b7fc985 100644 --- a/Projects/UOContent/Regions/GreenAcresRegion.cs +++ b/Projects/UOContent/Regions/GreenAcresRegion.cs @@ -5,27 +5,27 @@ using Server.Spells.Sixth; namespace Server.Regions { - public class GreenAcresRegion : BaseRegion - { - public GreenAcresRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) + public class GreenAcresRegion : BaseRegion { + public GreenAcresRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) + { + } + + public override bool AllowHousing(Mobile from, Point3D p) => + from.AccessLevel != AccessLevel.Player && base.AllowHousing(from, p); + + public override bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType) => + m.AccessLevel != AccessLevel.Player; + + public override bool OnBeginSpellCast(Mobile m, ISpell s) + { + if (m.AccessLevel == AccessLevel.Player && s is MarkSpell) + { + m.SendLocalizedMessage(501802); // Thy spell doth not appear to work... + return false; + } + + return base.OnBeginSpellCast(m, s); + } } - - public override bool AllowHousing(Mobile from, Point3D p) => - from.AccessLevel != AccessLevel.Player && base.AllowHousing(from, p); - - public override bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType) => - m.AccessLevel != AccessLevel.Player; - - public override bool OnBeginSpellCast(Mobile m, ISpell s) - { - if (m.AccessLevel == AccessLevel.Player && s is MarkSpell) - { - m.SendLocalizedMessage(501802); // Thy spell doth not appear to work... - return false; - } - - return base.OnBeginSpellCast(m, s); - } - } } diff --git a/Projects/UOContent/Regions/GuardedRegion.cs b/Projects/UOContent/Regions/GuardedRegion.cs index d6b92a20d..3e8872079 100644 --- a/Projects/UOContent/Regions/GuardedRegion.cs +++ b/Projects/UOContent/Regions/GuardedRegion.cs @@ -8,329 +8,346 @@ using Server.Utilities; namespace Server.Regions { - public class GuardedRegion : BaseRegion - { - private static readonly object[] m_GuardParams = new object[1]; - - private readonly Dictionary m_GuardCandidates = new Dictionary(); - private readonly Type m_GuardType; - - public GuardedRegion(string name, Map map, int priority, params Rectangle3D[] area) : base(name, map, priority, area) => - m_GuardType = DefaultGuardType; - - public GuardedRegion(string name, Map map, int priority, params Rectangle2D[] area) : base(name, map, priority, area) => - m_GuardType = DefaultGuardType; - - public GuardedRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) + public class GuardedRegion : BaseRegion { - if (json.GetProperty("guardsType", options, out string guardType)) - { - m_GuardType = AssemblyHandler.FindFirstTypeForName(guardType); + private static readonly object[] m_GuardParams = new object[1]; - if (!typeof(BaseGuard).IsAssignableFrom(m_GuardType)) + private readonly Dictionary m_GuardCandidates = new Dictionary(); + private readonly Type m_GuardType; + + public GuardedRegion(string name, Map map, int priority, params Rectangle3D[] area) : + base(name, map, priority, area) => + m_GuardType = DefaultGuardType; + + public GuardedRegion(string name, Map map, int priority, params Rectangle2D[] area) : + base(name, map, priority, area) => + m_GuardType = DefaultGuardType; + + public GuardedRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) { - Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine("Invalid guard type for region '{0}'", this); - Console.ResetColor(); - m_GuardType = DefaultGuardType; - } - } - else - { - m_GuardType = DefaultGuardType; - } - - Disabled = json.GetProperty("guardsDisabled", options, out bool disabled) && disabled; - } - - public bool Disabled { get; set; } - - public virtual bool AllowReds => Core.AOS; - - public virtual Type DefaultGuardType - { - get - { - if (Map == Map.Ilshenar || Map == Map.Malas) - return typeof(ArcherGuard); - return typeof(WarriorGuard); - } - } - - public virtual bool IsDisabled() => Disabled; - - public static void Initialize() - { - CommandSystem.Register("CheckGuarded", AccessLevel.GameMaster, CheckGuarded_OnCommand); - CommandSystem.Register("SetGuarded", AccessLevel.Administrator, SetGuarded_OnCommand); - CommandSystem.Register("ToggleGuarded", AccessLevel.Administrator, ToggleGuarded_OnCommand); - } - - [Usage("CheckGuarded")] - [Description("Returns a value indicating if the current region is guarded or not.")] - private static void CheckGuarded_OnCommand(CommandEventArgs e) - { - Mobile from = e.Mobile; - GuardedRegion reg = from.Region.GetRegion(); - - if (reg == null) - from.SendMessage("You are not in a guardable region."); - else if (reg.Disabled) - from.SendMessage("The guards in this region have been disabled."); - else - from.SendMessage("This region is actively guarded."); - } - - [Usage("SetGuarded ")] - [Description("Enables or disables guards for the current region.")] - private static void SetGuarded_OnCommand(CommandEventArgs e) - { - Mobile from = e.Mobile; - - if (e.Length == 1) - { - GuardedRegion reg = from.Region.GetRegion(); - - if (reg == null) - { - from.SendMessage("You are not in a guardable region."); - } - else - { - reg.Disabled = !e.GetBoolean(0); - - from.SendMessage(reg.Disabled - ? "The guards in this region have been disabled." - : "The guards in this region have been enabled."); - } - } - else - { - from.SendMessage("Format: SetGuarded "); - } - } - - [Usage("ToggleGuarded")] - [Description("Toggles the state of guards for the current region.")] - private static void ToggleGuarded_OnCommand(CommandEventArgs e) - { - Mobile from = e.Mobile; - GuardedRegion reg = from.Region.GetRegion(); - - if (reg == null) - { - from.SendMessage("You are not in a guardable region."); - } - else - { - reg.Disabled = !reg.Disabled; - - from.SendMessage(reg.Disabled - ? "The guards in this region have been disabled." - : "The guards in this region have been enabled."); - } - } - - public static GuardedRegion Disable(GuardedRegion reg) - { - reg.Disabled = true; - return reg; - } - - public virtual bool CheckVendorAccess(BaseVendor vendor, Mobile from) => - from.AccessLevel >= AccessLevel.GameMaster || IsDisabled() || from.Kills < 5; - - public override bool OnBeginSpellCast(Mobile m, ISpell s) - { - if (!IsDisabled() && !s.OnCastInTown(this)) - { - m.SendLocalizedMessage(500946); // You cannot cast this in town! - return false; - } - - return base.OnBeginSpellCast(m, s); - } - - public override bool AllowHousing(Mobile from, Point3D p) => false; - - public override void MakeGuard(Mobile focus) - { - IPooledEnumerable eable = focus.GetMobilesInRange(8); - BaseGuard useGuard = eable.FirstOrDefault(m => m.Focus == null); - - eable.Free(); - - if (useGuard == null) - { - m_GuardParams[0] = focus; - - try - { - ActivatorUtil.CreateInstance(m_GuardType, m_GuardParams); - } - catch - { - // ignored - } - } - else - { - useGuard.Focus = focus; - } - } - - public override void OnEnter(Mobile m) - { - if (IsDisabled()) - return; - - if (!AllowReds && m.Kills >= 5) - CheckGuardCandidate(m); - } - - public override void OnExit(Mobile m) - { - } - - public override void OnSpeech(SpeechEventArgs args) - { - base.OnSpeech(args); - - if (IsDisabled()) - return; - - if (args.Mobile.Alive && args.HasKeyword(0x0007)) // *guards* - CallGuards(args.Mobile.Location); - } - - public override void OnAggressed(Mobile aggressor, Mobile aggressed, bool criminal) - { - base.OnAggressed(aggressor, aggressed, criminal); - - if (!IsDisabled() && aggressor != aggressed && criminal) - CheckGuardCandidate(aggressor); - } - - public override void OnGotBeneficialAction(Mobile helper, Mobile helped) - { - base.OnGotBeneficialAction(helper, helped); - - if (IsDisabled()) - return; - - int noto = Notoriety.Compute(helper, helped); - - if (helper != helped && (noto == Notoriety.Criminal || noto == Notoriety.Murderer)) - CheckGuardCandidate(helper); - } - - public override void OnCriminalAction(Mobile m, bool message) - { - base.OnCriminalAction(m, message); - - if (!IsDisabled()) - CheckGuardCandidate(m); - } - - public void CheckGuardCandidate(Mobile m) - { - if (IsDisabled() || !IsGuardCandidate(m)) - return; - - if (!m_GuardCandidates.TryGetValue(m, out GuardTimer timer)) - { - timer = new GuardTimer(m, m_GuardCandidates); - timer.Start(); - - m_GuardCandidates[m] = timer; - m.SendLocalizedMessage(502275); // Guards can now be called on you! - - Map map = m.Map; - - if (map == null) - return; - - Mobile fakeCall = null; - double prio = 0.0; - - foreach (Mobile v in m.GetMobilesInRange(8)) - if (!v.Player && v != m && !IsGuardCandidate(v) && - ((v as BaseCreature)?.IsHumanInTown() ?? v.Body.IsHuman && v.Region.IsPartOf(this))) - { - double dist = m.GetDistanceToSqrt(v); - - if (fakeCall == null || dist < prio) + if (json.GetProperty("guardsType", options, out string guardType)) { - fakeCall = v; - prio = dist; + m_GuardType = AssemblyHandler.FindFirstTypeForName(guardType); + + if (!typeof(BaseGuard).IsAssignableFrom(m_GuardType)) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine("Invalid guard type for region '{0}'", this); + Console.ResetColor(); + m_GuardType = DefaultGuardType; + } + } + else + { + m_GuardType = DefaultGuardType; } - } - if (fakeCall != null) - { - fakeCall.Say(Utility.RandomList(1007037, 501603, 1013037, 1013038, 1013039, 1013041, 1013042, - 1013043, 1013052)); - MakeGuard(m); - timer.Stop(); - m_GuardCandidates.Remove(m); - m.SendLocalizedMessage(502276); // Guards can no longer be called on you. - } - } - else - { - timer.Stop(); - timer.Start(); - } - } - - public void CallGuards(Point3D p) - { - if (IsDisabled()) - return; - - IPooledEnumerable eable = Map.GetMobilesInRange(p, 14); - - foreach (Mobile m in eable) - if (IsGuardCandidate(m) && - (!AllowReds && m.Kills >= 5 && m.Region.IsPartOf(this) || m_GuardCandidates.ContainsKey(m))) - { - if (m_GuardCandidates.TryGetValue(m, out GuardTimer timer)) - { - timer.Stop(); - m_GuardCandidates.Remove(m); - } - - MakeGuard(m); - m.SendLocalizedMessage(502276); // Guards can no longer be called on you. - break; + Disabled = json.GetProperty("guardsDisabled", options, out bool disabled) && disabled; } - eable.Free(); + public bool Disabled { get; set; } + + public virtual bool AllowReds => Core.AOS; + + public virtual Type DefaultGuardType + { + get + { + if (Map == Map.Ilshenar || Map == Map.Malas) + return typeof(ArcherGuard); + return typeof(WarriorGuard); + } + } + + public virtual bool IsDisabled() => Disabled; + + public static void Initialize() + { + CommandSystem.Register("CheckGuarded", AccessLevel.GameMaster, CheckGuarded_OnCommand); + CommandSystem.Register("SetGuarded", AccessLevel.Administrator, SetGuarded_OnCommand); + CommandSystem.Register("ToggleGuarded", AccessLevel.Administrator, ToggleGuarded_OnCommand); + } + + [Usage("CheckGuarded")] + [Description("Returns a value indicating if the current region is guarded or not.")] + private static void CheckGuarded_OnCommand(CommandEventArgs e) + { + var from = e.Mobile; + var reg = from.Region.GetRegion(); + + if (reg == null) + from.SendMessage("You are not in a guardable region."); + else if (reg.Disabled) + from.SendMessage("The guards in this region have been disabled."); + else + from.SendMessage("This region is actively guarded."); + } + + [Usage("SetGuarded ")] + [Description("Enables or disables guards for the current region.")] + private static void SetGuarded_OnCommand(CommandEventArgs e) + { + var from = e.Mobile; + + if (e.Length == 1) + { + var reg = from.Region.GetRegion(); + + if (reg == null) + { + from.SendMessage("You are not in a guardable region."); + } + else + { + reg.Disabled = !e.GetBoolean(0); + + from.SendMessage( + reg.Disabled + ? "The guards in this region have been disabled." + : "The guards in this region have been enabled." + ); + } + } + else + { + from.SendMessage("Format: SetGuarded "); + } + } + + [Usage("ToggleGuarded")] + [Description("Toggles the state of guards for the current region.")] + private static void ToggleGuarded_OnCommand(CommandEventArgs e) + { + var from = e.Mobile; + var reg = from.Region.GetRegion(); + + if (reg == null) + { + from.SendMessage("You are not in a guardable region."); + } + else + { + reg.Disabled = !reg.Disabled; + + from.SendMessage( + reg.Disabled + ? "The guards in this region have been disabled." + : "The guards in this region have been enabled." + ); + } + } + + public static GuardedRegion Disable(GuardedRegion reg) + { + reg.Disabled = true; + return reg; + } + + public virtual bool CheckVendorAccess(BaseVendor vendor, Mobile from) => + from.AccessLevel >= AccessLevel.GameMaster || IsDisabled() || from.Kills < 5; + + public override bool OnBeginSpellCast(Mobile m, ISpell s) + { + if (!IsDisabled() && !s.OnCastInTown(this)) + { + m.SendLocalizedMessage(500946); // You cannot cast this in town! + return false; + } + + return base.OnBeginSpellCast(m, s); + } + + public override bool AllowHousing(Mobile from, Point3D p) => false; + + public override void MakeGuard(Mobile focus) + { + var eable = focus.GetMobilesInRange(8); + var useGuard = eable.FirstOrDefault(m => m.Focus == null); + + eable.Free(); + + if (useGuard == null) + { + m_GuardParams[0] = focus; + + try + { + ActivatorUtil.CreateInstance(m_GuardType, m_GuardParams); + } + catch + { + // ignored + } + } + else + { + useGuard.Focus = focus; + } + } + + public override void OnEnter(Mobile m) + { + if (IsDisabled()) + return; + + if (!AllowReds && m.Kills >= 5) + CheckGuardCandidate(m); + } + + public override void OnExit(Mobile m) + { + } + + public override void OnSpeech(SpeechEventArgs args) + { + base.OnSpeech(args); + + if (IsDisabled()) + return; + + if (args.Mobile.Alive && args.HasKeyword(0x0007)) // *guards* + CallGuards(args.Mobile.Location); + } + + public override void OnAggressed(Mobile aggressor, Mobile aggressed, bool criminal) + { + base.OnAggressed(aggressor, aggressed, criminal); + + if (!IsDisabled() && aggressor != aggressed && criminal) + CheckGuardCandidate(aggressor); + } + + public override void OnGotBeneficialAction(Mobile helper, Mobile helped) + { + base.OnGotBeneficialAction(helper, helped); + + if (IsDisabled()) + return; + + var noto = Notoriety.Compute(helper, helped); + + if (helper != helped && (noto == Notoriety.Criminal || noto == Notoriety.Murderer)) + CheckGuardCandidate(helper); + } + + public override void OnCriminalAction(Mobile m, bool message) + { + base.OnCriminalAction(m, message); + + if (!IsDisabled()) + CheckGuardCandidate(m); + } + + public void CheckGuardCandidate(Mobile m) + { + if (IsDisabled() || !IsGuardCandidate(m)) + return; + + if (!m_GuardCandidates.TryGetValue(m, out var timer)) + { + timer = new GuardTimer(m, m_GuardCandidates); + timer.Start(); + + m_GuardCandidates[m] = timer; + m.SendLocalizedMessage(502275); // Guards can now be called on you! + + var map = m.Map; + + if (map == null) + return; + + Mobile fakeCall = null; + var prio = 0.0; + + foreach (var v in m.GetMobilesInRange(8)) + if (!v.Player && v != m && !IsGuardCandidate(v) && + ((v as BaseCreature)?.IsHumanInTown() ?? v.Body.IsHuman && v.Region.IsPartOf(this))) + { + var dist = m.GetDistanceToSqrt(v); + + if (fakeCall == null || dist < prio) + { + fakeCall = v; + prio = dist; + } + } + + if (fakeCall != null) + { + fakeCall.Say( + Utility.RandomList( + 1007037, + 501603, + 1013037, + 1013038, + 1013039, + 1013041, + 1013042, + 1013043, + 1013052 + ) + ); + MakeGuard(m); + timer.Stop(); + m_GuardCandidates.Remove(m); + m.SendLocalizedMessage(502276); // Guards can no longer be called on you. + } + } + else + { + timer.Stop(); + timer.Start(); + } + } + + public void CallGuards(Point3D p) + { + if (IsDisabled()) + return; + + var eable = Map.GetMobilesInRange(p, 14); + + foreach (var m in eable) + if (IsGuardCandidate(m) && + (!AllowReds && m.Kills >= 5 && m.Region.IsPartOf(this) || m_GuardCandidates.ContainsKey(m))) + { + if (m_GuardCandidates.TryGetValue(m, out var timer)) + { + timer.Stop(); + m_GuardCandidates.Remove(m); + } + + MakeGuard(m); + m.SendLocalizedMessage(502276); // Guards can no longer be called on you. + break; + } + + eable.Free(); + } + + public bool IsGuardCandidate(Mobile m) => + !(m is BaseGuard) && m.Alive && m.AccessLevel <= AccessLevel.Player && !m.Blessed && + (!(m is BaseCreature creature) || !creature.IsInvulnerable) && !IsDisabled() && + (!AllowReds && m.Kills >= 5 || m.Criminal); + + private class GuardTimer : Timer + { + private readonly Mobile m_Mobile; + private readonly Dictionary m_Table; + + public GuardTimer(Mobile m, Dictionary table) : base(TimeSpan.FromSeconds(15.0)) + { + Priority = TimerPriority.TwoFiftyMS; + + m_Mobile = m; + m_Table = table; + } + + protected override void OnTick() + { + if (m_Table.Remove(m_Mobile)) + m_Mobile.SendLocalizedMessage(502276); // Guards can no longer be called on you. + } + } } - - public bool IsGuardCandidate(Mobile m) => - !(m is BaseGuard) && m.Alive && m.AccessLevel <= AccessLevel.Player && !m.Blessed && - (!(m is BaseCreature creature) || !creature.IsInvulnerable) && !IsDisabled() && - (!AllowReds && m.Kills >= 5 || m.Criminal); - - private class GuardTimer : Timer - { - private readonly Mobile m_Mobile; - private readonly Dictionary m_Table; - - public GuardTimer(Mobile m, Dictionary table) : base(TimeSpan.FromSeconds(15.0)) - { - Priority = TimerPriority.TwoFiftyMS; - - m_Mobile = m; - m_Table = table; - } - - protected override void OnTick() - { - if (m_Table.Remove(m_Mobile)) - m_Mobile.SendLocalizedMessage(502276); // Guards can no longer be called on you. - } - } - } } diff --git a/Projects/UOContent/Regions/HouseRegion.cs b/Projects/UOContent/Regions/HouseRegion.cs index 88c3e84ec..ebaef4350 100644 --- a/Projects/UOContent/Regions/HouseRegion.cs +++ b/Projects/UOContent/Regions/HouseRegion.cs @@ -7,334 +7,338 @@ using Server.Multis; namespace Server.Regions { - public class HouseRegion : BaseRegion - { - public static readonly int HousePriority = DefaultPriority + 1; - - public static TimeSpan CombatHeatDelay = TimeSpan.FromSeconds(30.0); - - private bool m_Recursion; - - public HouseRegion(BaseHouse house) : base(null, house.Map, HousePriority, GetArea(house)) + public class HouseRegion : BaseRegion { - House = house; + public static readonly int HousePriority = DefaultPriority + 1; - Point3D ban = house.RelativeBanLocation; + public static TimeSpan CombatHeatDelay = TimeSpan.FromSeconds(30.0); - GoLocation = new Point3D(house.X + ban.X, house.Y + ban.Y, house.Z + ban.Z); + private bool m_Recursion; + + public HouseRegion(BaseHouse house) : base(null, house.Map, HousePriority, GetArea(house)) + { + House = house; + + var ban = house.RelativeBanLocation; + + GoLocation = new Point3D(house.X + ban.X, house.Y + ban.Y, house.Z + ban.Z); + } + + public BaseHouse House { get; } + + public static void Initialize() + { + EventSink.Login += OnLogin; + } + + public static void OnLogin(Mobile m) + { + var house = BaseHouse.FindHouseAt(m); + + if (house?.Public == false && !house.IsFriend(m)) + m.Location = house.BanLocation; + } + + public override bool AllowHousing(Mobile from, Point3D p) => false; + + private static Rectangle3D[] GetArea(BaseHouse house) + { + var x = house.X; + var y = house.Y; + // int z = house.Z; + + var houseArea = house.Area; + var area = new Rectangle3D[houseArea.Length]; + + for (var i = 0; i < area.Length; i++) + { + var rect = houseArea[i]; + area[i] = ConvertTo3D(new Rectangle2D(x + rect.Start.X, y + rect.Start.Y, rect.Width, rect.Height)); + } + + return area; + } + + public override bool SendInaccessibleMessage(Item item, Mobile from) + { + if (item is Container) + item.SendLocalizedMessageTo(from, 501647); // That is secure. + else + item.SendLocalizedMessageTo(from, 1061637); // You are not allowed to access this. + + return true; + } + + public override bool CheckAccessibility(Item item, Mobile from) => House.CheckAccessibility(item, from); + + // Use OnLocationChanged instead of OnEnter because it can be that we enter a house region even though we're not actually inside the house + public override void OnLocationChanged(Mobile m, Point3D oldLocation) + { + if (m_Recursion) + return; + + base.OnLocationChanged(m, oldLocation); + + m_Recursion = true; + + var bc = m as BaseCreature; + + if (bc?.NoHouseRestrictions != true && + (bc?.IsHouseSummonable != true || BaseCreature.Summoning || House.IsInside(oldLocation, 16))) + { + if ((House.Public || !House.IsAosRules) && House.IsBanned(m) && House.IsInside(m)) + { + m.Location = House.BanLocation; + + if (!Core.SE) + m.SendLocalizedMessage(501284); // You may not enter. + } + else if (House.IsAosRules && !House.Public && !House.HasAccess(m) && House.IsInside(m)) + { + m.Location = House.BanLocation; + + if (!Core.SE) + m.SendLocalizedMessage(501284); // You may not enter. + } + else if (House.IsCombatRestricted(m) && House.IsInside(m) && !House.IsInside(oldLocation, 16)) + { + m.Location = House.BanLocation; + m.SendLocalizedMessage(1061637); // You are not allowed to access this. + } + else if (House is HouseFoundation foundation && foundation?.Customizer != null && + foundation.Customizer != m && + House.IsInside(m)) + { + m.Location = House.BanLocation; + } + } + + if (House.InternalizedVendors.Count > 0 && House.IsInside(m) && !House.IsInside(oldLocation, 16) && + House.IsOwner(m) && m.Alive && !m.HasGump()) + m.SendGump(new NoticeGump(1060635, 30720, 1061826, 32512, 320, 180)); + + m_Recursion = false; + } + + public override bool OnMoveInto(Mobile from, Direction d, Point3D newLocation, Point3D oldLocation) + { + if (!base.OnMoveInto(from, d, newLocation, oldLocation)) + return false; + + var bc = from as BaseCreature; + + if (bc?.NoHouseRestrictions != true) + { + if (bc?.Controlled == false) // Untamed creatures cannot enter public houses + return false; + + if (bc?.IsHouseSummonable == true && + !(BaseCreature.Summoning || House.IsInside(oldLocation, 16))) + return false; + if (bc?.Controlled == false && House.IsAosRules && !House.Public) + return false; + if ((House.Public || !House.IsAosRules) && House.IsBanned(from) && House.IsInside(newLocation, 16)) + { + from.Location = House.BanLocation; + + if (!Core.SE) + from.SendLocalizedMessage(501284); // You may not enter. + + return false; + } + + if (House.IsAosRules && !House.Public && !House.HasAccess(from) && House.IsInside(newLocation, 16)) + { + if (!Core.SE) + from.SendLocalizedMessage(501284); // You may not enter. + + return false; + } + + if (House.IsCombatRestricted(from) && !House.IsInside(oldLocation, 16) && House.IsInside(newLocation, 16)) + { + from.SendLocalizedMessage(1061637); // You are not allowed to access this. + return false; + } + + if (House is HouseFoundation foundation && foundation.Customizer != null && foundation.Customizer != from && + House.IsInside(newLocation, 16)) + return false; + } + + if (House.InternalizedVendors.Count > 0 && House.IsInside(from) && !House.IsInside(oldLocation, 16) && + House.IsOwner(from) && from.Alive && + !from.HasGump()) + from.SendGump(new NoticeGump(1060635, 30720, 1061826, 32512, 320, 180)); + + return true; + } + + public override bool OnDecay(Item item) => + (!House.HasLockedDownItem(item) && !House.HasSecureItem(item) || !House.IsInside(item)) && base.OnDecay(item); + + public override TimeSpan GetLogoutDelay(Mobile m) => + House.IsFriend(m) && House.IsInside(m) + ? m.Aggressed.Any(info => info.Defender.Player && DateTime.UtcNow - info.LastCombatTime < CombatHeatDelay) ? + base.GetLogoutDelay(m) : TimeSpan.Zero + : base.GetLogoutDelay(m); + + public override void OnSpeech(SpeechEventArgs e) + { + base.OnSpeech(e); + + var from = e.Mobile; + Item sign = House.Sign; + + var isOwner = House.IsOwner(from); + var isCoOwner = isOwner || House.IsCoOwner(from); + var isFriend = isCoOwner || House.IsFriend(from); + + if (!isFriend) + return; + + if (!from.Alive) + return; + + if (Core.ML && Insensitive.Equals(e.Speech, "I wish to resize my house")) + { + if (from.Map != sign.Map || !from.InRange(sign, 0)) + { + from.SendLocalizedMessage(500295); // you are too far away to do that. + } + else if (DateTime.UtcNow <= House.BuiltOn.AddHours(1)) + { + from.SendLocalizedMessage(1080178); // You must wait one hour between each house demolition. + } + else if (isOwner) + { + from.CloseGump(); + from.CloseGump(); + from.SendGump(new ConfirmHouseResize(from, House)); + } + else + { + from.SendLocalizedMessage(501320); // Only the house owner may do this. + } + } + + if (!House.IsInside(from) || !House.IsActive) + return; + if (e.HasKeyword(0x33)) // remove thyself + { + from.SendLocalizedMessage(501326); // Target the individual to eject from this house. + from.Target = new HouseKickTarget(House); + } + else if (e.HasKeyword(0x34)) // I ban thee + { + if (!House.Public && House.IsAosRules) + { + from.SendLocalizedMessage( + 1062521 + ); // You cannot ban someone from a private house. Revoke their access instead. + } + else + { + from.SendLocalizedMessage(501325); // Target the individual to ban from this house. + from.Target = new HouseBanTarget(true, House); + } + } + else if (e.HasKeyword(0x23)) // I wish to lock this down + { + if (isCoOwner) + { + from.SendLocalizedMessage(502097); // Lock what down? + from.Target = new LockdownTarget(false, House); + } + else + { + from.SendLocalizedMessage(1010587); // You are not a co-owner of this house. + } + } + else if (e.HasKeyword(0x24)) // I wish to release this + { + if (isCoOwner) + { + from.SendLocalizedMessage(502100); // Choose the item you wish to release + from.Target = new LockdownTarget(true, House); + } + else + { + from.SendLocalizedMessage(1010587); // You are not a co-owner of this house. + } + } + else if (e.HasKeyword(0x25)) // I wish to secure this + { + if (isOwner) + { + from.SendLocalizedMessage(502103); // Choose the item you wish to secure + from.Target = new SecureTarget(false, House); + } + else + { + from.SendLocalizedMessage(502094); // You must be in your house to do this. + } + } + else if (e.HasKeyword(0x26)) // I wish to unsecure this + { + if (isOwner) + { + from.SendLocalizedMessage(502106); // Choose the item you wish to unsecure + from.Target = new SecureTarget(true, House); + } + else + { + from.SendLocalizedMessage(502094); // You must be in your house to do this. + } + } + else if (e.HasKeyword(0x27)) // I wish to place a strongbox + { + if (isOwner) + from.SendLocalizedMessage(502109); // Owners do not get a strongbox of their own. + else if (isCoOwner) + House.AddStrongBox(from); + else + from.SendLocalizedMessage(1010587); // You are not a co-owner of this house. + } + else if (e.HasKeyword(0x28)) // trash barrel + { + if (isCoOwner) + House.AddTrashBarrel(from); + else + from.SendLocalizedMessage(1010587); // You are not a co-owner of this house. + } + } + + public override bool OnDoubleClick(Mobile from, object o) + { + if (o is Container c) + { + var res = House.CheckSecureAccess(from, c); + + if (res == SecureAccessResult.Accessible) + return true; + + if (res == SecureAccessResult.Inaccessible) + { + c.SendLocalizedMessageTo(from, 1010563); + return false; + } + } + + return base.OnDoubleClick(from, o); + } + + public override bool OnSingleClick(Mobile from, object o) + { + if (o is Item item) + { + if (House.HasLockedDownItem(item)) + item.LabelTo(from, 501643); // [locked down] + else if (House.HasSecureItem(item)) + item.LabelTo(from, 501644); // [locked down & secure] + } + + return base.OnSingleClick(from, o); + } } - - public BaseHouse House { get; } - - public static void Initialize() - { - EventSink.Login += OnLogin; - } - - public static void OnLogin(Mobile m) - { - BaseHouse house = BaseHouse.FindHouseAt(m); - - if (house?.Public == false && !house.IsFriend(m)) - m.Location = house.BanLocation; - } - - public override bool AllowHousing(Mobile from, Point3D p) => false; - - private static Rectangle3D[] GetArea(BaseHouse house) - { - int x = house.X; - int y = house.Y; - // int z = house.Z; - - Rectangle2D[] houseArea = house.Area; - Rectangle3D[] area = new Rectangle3D[houseArea.Length]; - - for (int i = 0; i < area.Length; i++) - { - Rectangle2D rect = houseArea[i]; - area[i] = ConvertTo3D(new Rectangle2D(x + rect.Start.X, y + rect.Start.Y, rect.Width, rect.Height)); - } - - return area; - } - - public override bool SendInaccessibleMessage(Item item, Mobile from) - { - if (item is Container) - item.SendLocalizedMessageTo(from, 501647); // That is secure. - else - item.SendLocalizedMessageTo(from, 1061637); // You are not allowed to access this. - - return true; - } - - public override bool CheckAccessibility(Item item, Mobile from) => House.CheckAccessibility(item, from); - - // Use OnLocationChanged instead of OnEnter because it can be that we enter a house region even though we're not actually inside the house - public override void OnLocationChanged(Mobile m, Point3D oldLocation) - { - if (m_Recursion) - return; - - base.OnLocationChanged(m, oldLocation); - - m_Recursion = true; - - BaseCreature bc = m as BaseCreature; - - if (bc?.NoHouseRestrictions != true && - (bc?.IsHouseSummonable != true || BaseCreature.Summoning || House.IsInside(oldLocation, 16))) - { - if ((House.Public || !House.IsAosRules) && House.IsBanned(m) && House.IsInside(m)) - { - m.Location = House.BanLocation; - - if (!Core.SE) - m.SendLocalizedMessage(501284); // You may not enter. - } - else if (House.IsAosRules && !House.Public && !House.HasAccess(m) && House.IsInside(m)) - { - m.Location = House.BanLocation; - - if (!Core.SE) - m.SendLocalizedMessage(501284); // You may not enter. - } - else if (House.IsCombatRestricted(m) && House.IsInside(m) && !House.IsInside(oldLocation, 16)) - { - m.Location = House.BanLocation; - m.SendLocalizedMessage(1061637); // You are not allowed to access this. - } - else if (House is HouseFoundation foundation && foundation?.Customizer != null && foundation.Customizer != m && - House.IsInside(m)) - { - m.Location = House.BanLocation; - } - } - - if (House.InternalizedVendors.Count > 0 && House.IsInside(m) && !House.IsInside(oldLocation, 16) && - House.IsOwner(m) && m.Alive && !m.HasGump()) - m.SendGump(new NoticeGump(1060635, 30720, 1061826, 32512, 320, 180)); - - m_Recursion = false; - } - - public override bool OnMoveInto(Mobile from, Direction d, Point3D newLocation, Point3D oldLocation) - { - if (!base.OnMoveInto(from, d, newLocation, oldLocation)) - return false; - - BaseCreature bc = from as BaseCreature; - - if (bc?.NoHouseRestrictions != true) - { - if (bc?.Controlled == false) // Untamed creatures cannot enter public houses - return false; - - if (bc?.IsHouseSummonable == true && - !(BaseCreature.Summoning || House.IsInside(oldLocation, 16))) - return false; - if (bc?.Controlled == false && House.IsAosRules && !House.Public) - return false; - if ((House.Public || !House.IsAosRules) && House.IsBanned(from) && House.IsInside(newLocation, 16)) - { - from.Location = House.BanLocation; - - if (!Core.SE) - from.SendLocalizedMessage(501284); // You may not enter. - - return false; - } - if (House.IsAosRules && !House.Public && !House.HasAccess(from) && House.IsInside(newLocation, 16)) - { - if (!Core.SE) - from.SendLocalizedMessage(501284); // You may not enter. - - return false; - } - if (House.IsCombatRestricted(from) && !House.IsInside(oldLocation, 16) && House.IsInside(newLocation, 16)) - { - from.SendLocalizedMessage(1061637); // You are not allowed to access this. - return false; - } - - if (House is HouseFoundation foundation && foundation.Customizer != null && foundation.Customizer != from && - House.IsInside(newLocation, 16)) - return false; - } - - if (House.InternalizedVendors.Count > 0 && House.IsInside(from) && !House.IsInside(oldLocation, 16) && - House.IsOwner(from) && from.Alive && - !from.HasGump()) - from.SendGump(new NoticeGump(1060635, 30720, 1061826, 32512, 320, 180)); - - return true; - } - - public override bool OnDecay(Item item) => - (!House.HasLockedDownItem(item) && !House.HasSecureItem(item) || !House.IsInside(item)) && base.OnDecay(item); - - public override TimeSpan GetLogoutDelay(Mobile m) => - House.IsFriend(m) && House.IsInside(m) - ? m.Aggressed.Any(info => info.Defender.Player && DateTime.UtcNow - info.LastCombatTime < CombatHeatDelay) - ? base.GetLogoutDelay(m) : TimeSpan.Zero - : base.GetLogoutDelay(m); - - public override void OnSpeech(SpeechEventArgs e) - { - base.OnSpeech(e); - - Mobile from = e.Mobile; - Item sign = House.Sign; - - bool isOwner = House.IsOwner(from); - bool isCoOwner = isOwner || House.IsCoOwner(from); - bool isFriend = isCoOwner || House.IsFriend(from); - - if (!isFriend) - return; - - if (!from.Alive) - return; - - if (Core.ML && Insensitive.Equals(e.Speech, "I wish to resize my house")) - { - if (from.Map != sign.Map || !from.InRange(sign, 0)) - { - from.SendLocalizedMessage(500295); // you are too far away to do that. - } - else if (DateTime.UtcNow <= House.BuiltOn.AddHours(1)) - { - from.SendLocalizedMessage(1080178); // You must wait one hour between each house demolition. - } - else if (isOwner) - { - from.CloseGump(); - from.CloseGump(); - from.SendGump(new ConfirmHouseResize(from, House)); - } - else - { - from.SendLocalizedMessage(501320); // Only the house owner may do this. - } - } - - if (!House.IsInside(from) || !House.IsActive) - return; - if (e.HasKeyword(0x33)) // remove thyself - { - from.SendLocalizedMessage(501326); // Target the individual to eject from this house. - from.Target = new HouseKickTarget(House); - } - else if (e.HasKeyword(0x34)) // I ban thee - { - if (!House.Public && House.IsAosRules) - { - from.SendLocalizedMessage( - 1062521); // You cannot ban someone from a private house. Revoke their access instead. - } - else - { - from.SendLocalizedMessage(501325); // Target the individual to ban from this house. - from.Target = new HouseBanTarget(true, House); - } - } - else if (e.HasKeyword(0x23)) // I wish to lock this down - { - if (isCoOwner) - { - from.SendLocalizedMessage(502097); // Lock what down? - from.Target = new LockdownTarget(false, House); - } - else - { - from.SendLocalizedMessage(1010587); // You are not a co-owner of this house. - } - } - else if (e.HasKeyword(0x24)) // I wish to release this - { - if (isCoOwner) - { - from.SendLocalizedMessage(502100); // Choose the item you wish to release - from.Target = new LockdownTarget(true, House); - } - else - { - from.SendLocalizedMessage(1010587); // You are not a co-owner of this house. - } - } - else if (e.HasKeyword(0x25)) // I wish to secure this - { - if (isOwner) - { - from.SendLocalizedMessage(502103); // Choose the item you wish to secure - from.Target = new SecureTarget(false, House); - } - else - { - from.SendLocalizedMessage(502094); // You must be in your house to do this. - } - } - else if (e.HasKeyword(0x26)) // I wish to unsecure this - { - if (isOwner) - { - from.SendLocalizedMessage(502106); // Choose the item you wish to unsecure - from.Target = new SecureTarget(true, House); - } - else - { - from.SendLocalizedMessage(502094); // You must be in your house to do this. - } - } - else if (e.HasKeyword(0x27)) // I wish to place a strongbox - { - if (isOwner) - from.SendLocalizedMessage(502109); // Owners do not get a strongbox of their own. - else if (isCoOwner) - House.AddStrongBox(from); - else - from.SendLocalizedMessage(1010587); // You are not a co-owner of this house. - } - else if (e.HasKeyword(0x28)) // trash barrel - { - if (isCoOwner) - House.AddTrashBarrel(from); - else - from.SendLocalizedMessage(1010587); // You are not a co-owner of this house. - } - } - - public override bool OnDoubleClick(Mobile from, object o) - { - if (o is Container c) - { - SecureAccessResult res = House.CheckSecureAccess(from, c); - - if (res == SecureAccessResult.Accessible) - return true; - - if (res == SecureAccessResult.Inaccessible) - { - c.SendLocalizedMessageTo(from, 1010563); - return false; - } - } - - return base.OnDoubleClick(from, o); - } - - public override bool OnSingleClick(Mobile from, object o) - { - if (o is Item item) - { - if (House.HasLockedDownItem(item)) - item.LabelTo(from, 501643); // [locked down] - else if (House.HasSecureItem(item)) - item.LabelTo(from, 501644); // [locked down & secure] - } - - return base.OnSingleClick(from, o); - } - } } diff --git a/Projects/UOContent/Regions/JailRegion.cs b/Projects/UOContent/Regions/JailRegion.cs index aa19d7cb9..5b78604fa 100644 --- a/Projects/UOContent/Regions/JailRegion.cs +++ b/Projects/UOContent/Regions/JailRegion.cs @@ -4,74 +4,74 @@ using Server.Spells; namespace Server.Regions { - public class JailRegion : BaseRegion - { - public JailRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) + public class JailRegion : BaseRegion { + public JailRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) + { + } + + public override bool AllowBeneficial(Mobile from, Mobile target) + { + if (from.AccessLevel == AccessLevel.Player) + { + from.SendMessage("You may not do that in jail."); + return false; + } + + return true; + } + + public override bool AllowHarmful(Mobile from, Mobile target) + { + if (from.AccessLevel == AccessLevel.Player) + { + from.SendMessage("You may not do that in jail."); + return false; + } + + return true; + } + + public override bool AllowHousing(Mobile from, Point3D p) => false; + + public override void AlterLightLevel(Mobile m, ref int global, ref int personal) + { + global = LightCycle.JailLevel; + } + + public override bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType) + { + if (m?.AccessLevel == AccessLevel.Player) + { + m.SendLocalizedMessage(1114345); // You'll need a better jailbreak plan than that! + return false; + } + + return base.CheckTravel(m, newLocation, travelType); + } + + public override bool OnBeginSpellCast(Mobile from, ISpell s) + { + if (from.AccessLevel == AccessLevel.Player) + { + from.SendLocalizedMessage(502629); // You cannot cast spells here. + return false; + } + + return true; + } + + public override bool OnSkillUse(Mobile from, int Skill) + { + if (from.AccessLevel == AccessLevel.Player) + { + from.SendMessage("You may not use skills in jail."); + return false; + } + + return true; + } + + public override bool OnCombatantChange(Mobile from, Mobile Old, Mobile New) => from.AccessLevel > AccessLevel.Player; } - - public override bool AllowBeneficial(Mobile from, Mobile target) - { - if (from.AccessLevel == AccessLevel.Player) - { - from.SendMessage("You may not do that in jail."); - return false; - } - - return true; - } - - public override bool AllowHarmful(Mobile from, Mobile target) - { - if (from.AccessLevel == AccessLevel.Player) - { - from.SendMessage("You may not do that in jail."); - return false; - } - - return true; - } - - public override bool AllowHousing(Mobile from, Point3D p) => false; - - public override void AlterLightLevel(Mobile m, ref int global, ref int personal) - { - global = LightCycle.JailLevel; - } - - public override bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType) - { - if (m?.AccessLevel == AccessLevel.Player) - { - m.SendLocalizedMessage(1114345); // You'll need a better jailbreak plan than that! - return false; - } - - return base.CheckTravel(m, newLocation, travelType); - } - - public override bool OnBeginSpellCast(Mobile from, ISpell s) - { - if (from.AccessLevel == AccessLevel.Player) - { - from.SendLocalizedMessage(502629); // You cannot cast spells here. - return false; - } - - return true; - } - - public override bool OnSkillUse(Mobile from, int Skill) - { - if (from.AccessLevel == AccessLevel.Player) - { - from.SendMessage("You may not use skills in jail."); - return false; - } - - return true; - } - - public override bool OnCombatantChange(Mobile from, Mobile Old, Mobile New) => from.AccessLevel > AccessLevel.Player; - } } diff --git a/Projects/UOContent/Regions/MondainRegion.cs b/Projects/UOContent/Regions/MondainRegion.cs index 2a26d094c..c998085d5 100644 --- a/Projects/UOContent/Regions/MondainRegion.cs +++ b/Projects/UOContent/Regions/MondainRegion.cs @@ -4,21 +4,21 @@ using Server.Spells.Sixth; namespace Server.Regions { - public class MondainRegion : NoTravelSpellsAllowedRegion - { - public MondainRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) + public class MondainRegion : NoTravelSpellsAllowedRegion { - } + public MondainRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) + { + } - public override bool OnBeginSpellCast(Mobile m, ISpell s) - { - if (m.Player && s is MarkSpell) - { - m.SendLocalizedMessage(501802); // Thy spell doth not appear to work... - return false; - } + public override bool OnBeginSpellCast(Mobile m, ISpell s) + { + if (m.Player && s is MarkSpell) + { + m.SendLocalizedMessage(501802); // Thy spell doth not appear to work... + return false; + } - return base.OnBeginSpellCast(m, s); + return base.OnBeginSpellCast(m, s); + } } - } } diff --git a/Projects/UOContent/Regions/NewMaginciaRegion.cs b/Projects/UOContent/Regions/NewMaginciaRegion.cs index dbbf86fdd..8e3bf2706 100644 --- a/Projects/UOContent/Regions/NewMaginciaRegion.cs +++ b/Projects/UOContent/Regions/NewMaginciaRegion.cs @@ -4,10 +4,10 @@ using Server.Regions; namespace Server.Engines.NewMagincia { - public class NewMaginciaRegion : TownRegion - { - public NewMaginciaRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) + public class NewMaginciaRegion : TownRegion { + public NewMaginciaRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) + { + } } - } } diff --git a/Projects/UOContent/Regions/NoHousingRegion.cs b/Projects/UOContent/Regions/NoHousingRegion.cs index 3e3c96711..537d11960 100644 --- a/Projects/UOContent/Regions/NoHousingRegion.cs +++ b/Projects/UOContent/Regions/NoHousingRegion.cs @@ -3,16 +3,16 @@ using Server.Json; namespace Server.Regions { - public class NoHousingRegion : BaseRegion - { - /* False: this uses 'stupid OSI' house placement checking: part of the house may be placed here provided that the center is not in the region - * True: this uses 'smart RunUO' house placement checking: no part of the house may be in the region - */ - public bool SmartChecking { get; } + public class NoHousingRegion : BaseRegion + { + public NoHousingRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) => + SmartChecking = json.GetProperty("smartNoHousing", options, out bool smartNoHousing) && smartNoHousing; - public NoHousingRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) => - SmartChecking = json.GetProperty("smartNoHousing", options, out bool smartNoHousing) && smartNoHousing; + /* False: this uses 'stupid OSI' house placement checking: part of the house may be placed here provided that the center is not in the region + * True: this uses 'smart RunUO' house placement checking: no part of the house may be in the region + */ + public bool SmartChecking { get; } - public override bool AllowHousing(Mobile from, Point3D p) => SmartChecking; - } + public override bool AllowHousing(Mobile from, Point3D p) => SmartChecking; + } } diff --git a/Projects/UOContent/Regions/NoTravelSpellsAllowedRegion.cs b/Projects/UOContent/Regions/NoTravelSpellsAllowedRegion.cs index aa324ec74..46429f4c9 100644 --- a/Projects/UOContent/Regions/NoTravelSpellsAllowedRegion.cs +++ b/Projects/UOContent/Regions/NoTravelSpellsAllowedRegion.cs @@ -6,10 +6,10 @@ using Server.Spells; public class NoTravelSpellsAllowedRegion : DungeonRegion { - public NoTravelSpellsAllowedRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) - { - } + public NoTravelSpellsAllowedRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) + { + } - public override bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType) => - m.AccessLevel == AccessLevel.Player; + public override bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType) => + m.AccessLevel == AccessLevel.Player; } diff --git a/Projects/UOContent/Regions/TownRegion.cs b/Projects/UOContent/Regions/TownRegion.cs index 7095f8951..9ae78f6de 100644 --- a/Projects/UOContent/Regions/TownRegion.cs +++ b/Projects/UOContent/Regions/TownRegion.cs @@ -3,10 +3,10 @@ using Server.Json; namespace Server.Regions { - public class TownRegion : GuardedRegion - { - public TownRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) + public class TownRegion : GuardedRegion { + public TownRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) + { + } } - } } diff --git a/Projects/UOContent/Regions/TwistedWealdDesertRegion.cs b/Projects/UOContent/Regions/TwistedWealdDesertRegion.cs index 32fd6f25e..9c3996f1f 100644 --- a/Projects/UOContent/Regions/TwistedWealdDesertRegion.cs +++ b/Projects/UOContent/Regions/TwistedWealdDesertRegion.cs @@ -1,41 +1,41 @@ using System.Text.Json; +using Server.Json; using Server.Network; using Server.Spells; using Server.Spells.Ninjitsu; -using Server.Json; namespace Server.Regions { - public class TwistedWealdDesertRegion : MondainRegion - { - public TwistedWealdDesertRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) + public class TwistedWealdDesertRegion : MondainRegion { - } + public TwistedWealdDesertRegion(DynamicJson json, JsonSerializerOptions options) : base(json, options) + { + } - public static void Initialize() - { - EventSink.Login += Desert_OnLogin; - } + public static void Initialize() + { + EventSink.Login += Desert_OnLogin; + } - public override void OnEnter(Mobile m) - { - NetState ns = m.NetState; - if (ns != null && !TransformationSpellHelper.UnderTransformation(m, typeof(AnimalForm)) && - m.AccessLevel == AccessLevel.Player) - ns.Send(SpeedControl.WalkSpeed); - } + public override void OnEnter(Mobile m) + { + var ns = m.NetState; + if (ns != null && !TransformationSpellHelper.UnderTransformation(m, typeof(AnimalForm)) && + m.AccessLevel == AccessLevel.Player) + ns.Send(SpeedControl.WalkSpeed); + } - public override void OnExit(Mobile m) - { - NetState ns = m.NetState; - if (ns != null && !TransformationSpellHelper.UnderTransformation(m, typeof(AnimalForm))) - ns.Send(SpeedControl.Disable); - } + public override void OnExit(Mobile m) + { + var ns = m.NetState; + if (ns != null && !TransformationSpellHelper.UnderTransformation(m, typeof(AnimalForm))) + ns.Send(SpeedControl.Disable); + } - private static void Desert_OnLogin(Mobile m) - { - if (m.Region.IsPartOf() && m.AccessLevel == AccessLevel.Player) - m.NetState.Send(SpeedControl.WalkSpeed); + private static void Desert_OnLogin(Mobile m) + { + if (m.Region.IsPartOf() && m.AccessLevel == AccessLevel.Player) + m.NetState.Send(SpeedControl.WalkSpeed); + } } - } } diff --git a/Projects/UOContent/Skills/Anatomy.cs b/Projects/UOContent/Skills/Anatomy.cs index b3eb2a15a..0981a6eab 100644 --- a/Projects/UOContent/Skills/Anatomy.cs +++ b/Projects/UOContent/Skills/Anatomy.cs @@ -5,87 +5,110 @@ using Server.Targeting; namespace Server.SkillHandlers { - public static class Anatomy - { - public static void Initialize() + public static class Anatomy { - SkillInfo.Table[(int)SkillName.Anatomy].Callback = OnUse; + public static void Initialize() + { + SkillInfo.Table[(int)SkillName.Anatomy].Callback = OnUse; + } + + public static TimeSpan OnUse(Mobile m) + { + m.Target = new InternalTarget(); + + m.SendLocalizedMessage(500321); // Whom shall I examine? + + return TimeSpan.FromSeconds(1.0); + } + + private class InternalTarget : Target + { + public InternalTarget() : base(8, false, TargetFlags.None) + { + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (from == targeted) + { + from.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 500324 + ); // You know yourself quite well enough already. + } + else if (targeted is TownCrier crier) + { + crier.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 500322, + from.NetState + ); // This person looks fine to me, though he may have some news... + } + else if (targeted is BaseVendor vendor && vendor.IsInvulnerable) + { + vendor.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 500326, + from.NetState + ); // That can not be inspected. + } + else if (targeted is Mobile targ) + { + var marginOfError = Math.Max(0, 25 - (int)(from.Skills.Anatomy.Value / 4)); + + var str = targ.Str + Utility.RandomMinMax(-marginOfError, +marginOfError); + var dex = targ.Dex + Utility.RandomMinMax(-marginOfError, +marginOfError); + var stm = targ.Stam * 100 / Math.Max(targ.StamMax, 1) + + Utility.RandomMinMax(-marginOfError, +marginOfError); + + var strMod = str / 10; + var dexMod = dex / 10; + var stmMod = stm / 10; + + if (strMod < 0) strMod = 0; + else if (strMod > 10) strMod = 10; + + if (dexMod < 0) dexMod = 0; + else if (dexMod > 10) dexMod = 10; + + if (stmMod > 10) stmMod = 10; + else if (stmMod < 0) stmMod = 0; + + if (from.CheckTargetSkill(SkillName.Anatomy, targ, 0, 100)) + { + targ.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 1038045 + strMod * 11 + dexMod, + from.NetState + ); // That looks [strong] and [dexterous]. + + if (from.Skills.Anatomy.Base >= 65.0) + targ.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 1038303 + stmMod, + from.NetState + ); // That being is at [10,20,...] percent endurance. + } + else + { + targ.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 1042666, + from.NetState + ); // You can not quite get a sense of their physical characteristics. + } + } + else + { + (targeted as Item)?.SendLocalizedMessageTo(from, 500323, ""); // Only living things have anatomies! + } + } + } } - - public static TimeSpan OnUse(Mobile m) - { - m.Target = new InternalTarget(); - - m.SendLocalizedMessage(500321); // Whom shall I examine? - - return TimeSpan.FromSeconds(1.0); - } - - private class InternalTarget : Target - { - public InternalTarget() : base(8, false, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (from == targeted) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 500324); // You know yourself quite well enough already. - } - else if (targeted is TownCrier crier) - { - crier.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 500322, - from.NetState); // This person looks fine to me, though he may have some news... - } - else if (targeted is BaseVendor vendor && vendor.IsInvulnerable) - { - vendor.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 500326, - from.NetState); // That can not be inspected. - } - else if (targeted is Mobile targ) - { - int marginOfError = Math.Max(0, 25 - (int)(from.Skills.Anatomy.Value / 4)); - - int str = targ.Str + Utility.RandomMinMax(-marginOfError, +marginOfError); - int dex = targ.Dex + Utility.RandomMinMax(-marginOfError, +marginOfError); - int stm = targ.Stam * 100 / Math.Max(targ.StamMax, 1) + - Utility.RandomMinMax(-marginOfError, +marginOfError); - - int strMod = str / 10; - int dexMod = dex / 10; - int stmMod = stm / 10; - - if (strMod < 0) strMod = 0; - else if (strMod > 10) strMod = 10; - - if (dexMod < 0) dexMod = 0; - else if (dexMod > 10) dexMod = 10; - - if (stmMod > 10) stmMod = 10; - else if (stmMod < 0) stmMod = 0; - - if (from.CheckTargetSkill(SkillName.Anatomy, targ, 0, 100)) - { - targ.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1038045 + strMod * 11 + dexMod, - from.NetState); // That looks [strong] and [dexterous]. - - if (from.Skills.Anatomy.Base >= 65.0) - targ.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1038303 + stmMod, - from.NetState); // That being is at [10,20,...] percent endurance. - } - else - { - targ.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1042666, - from.NetState); // You can not quite get a sense of their physical characteristics. - } - } - else - { - (targeted as Item)?.SendLocalizedMessageTo(from, 500323, ""); // Only living things have anatomies! - } - } - } - } } diff --git a/Projects/UOContent/Skills/AnimalLore.cs b/Projects/UOContent/Skills/AnimalLore.cs index 2700226d3..6b07423c8 100644 --- a/Projects/UOContent/Skills/AnimalLore.cs +++ b/Projects/UOContent/Skills/AnimalLore.cs @@ -6,366 +6,380 @@ using Server.Targeting; namespace Server.SkillHandlers { - public static class AnimalLore - { - public static void Initialize() + public static class AnimalLore { - SkillInfo.Table[(int)SkillName.AnimalLore].Callback = OnUse; - } - - public static TimeSpan OnUse(Mobile m) - { - m.Target = new InternalTarget(); - - m.SendLocalizedMessage(500328); // What animal should I look at? - - return TimeSpan.FromSeconds(1.0); - } - - private class InternalTarget : Target - { - public InternalTarget() : base(8, false, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (!from.Alive) + public static void Initialize() { - from.SendLocalizedMessage(500331); // The spirits of the dead are not the province of animal lore. + SkillInfo.Table[(int)SkillName.AnimalLore].Callback = OnUse; } - else if (targeted is BaseCreature c) + + public static TimeSpan OnUse(Mobile m) { - if (!c.IsDeadPet) - { - if (c.Body.IsAnimal || c.Body.IsMonster || c.Body.IsSea) + m.Target = new InternalTarget(); + + m.SendLocalizedMessage(500328); // What animal should I look at? + + return TimeSpan.FromSeconds(1.0); + } + + private class InternalTarget : Target + { + public InternalTarget() : base(8, false, TargetFlags.None) { - if (!c.Controlled && from.Skills.AnimalLore.Value < 100.0) - { - from.SendLocalizedMessage( - 1049674); // At your skill level, you can only lore tamed creatures. - } - else if (!c.Controlled && !c.Tamable && from.Skills.AnimalLore.Value < 110.0) - { - from.SendLocalizedMessage( - 1049675); // At your skill level, you can only lore tamed or tameable creatures. - } - else if (!from.CheckTargetSkill(SkillName.AnimalLore, c, 0.0, 120.0)) - { - from.SendLocalizedMessage(500334); // You can't think of anything you know offhand. - } - else - { - from.CloseGump(); - from.SendGump(new AnimalLoreGump(c)); - } + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (!from.Alive) + { + from.SendLocalizedMessage(500331); // The spirits of the dead are not the province of animal lore. + } + else if (targeted is BaseCreature c) + { + if (!c.IsDeadPet) + { + if (c.Body.IsAnimal || c.Body.IsMonster || c.Body.IsSea) + { + if (!c.Controlled && from.Skills.AnimalLore.Value < 100.0) + { + from.SendLocalizedMessage( + 1049674 + ); // At your skill level, you can only lore tamed creatures. + } + else if (!c.Controlled && !c.Tamable && from.Skills.AnimalLore.Value < 110.0) + { + from.SendLocalizedMessage( + 1049675 + ); // At your skill level, you can only lore tamed or tameable creatures. + } + else if (!from.CheckTargetSkill(SkillName.AnimalLore, c, 0.0, 120.0)) + { + from.SendLocalizedMessage(500334); // You can't think of anything you know offhand. + } + else + { + from.CloseGump(); + from.SendGump(new AnimalLoreGump(c)); + } + } + else + { + from.SendLocalizedMessage(500329); // That's not an animal! + } + } + else + { + from.SendLocalizedMessage(500331); // The spirits of the dead are not the province of animal lore. + } + } + else + { + from.SendLocalizedMessage(500329); // That's not an animal! + } + } + } + } + + public class AnimalLoreGump : Gump + { + private const int LabelColor = 0x24E5; + + public AnimalLoreGump(BaseCreature c) : base(250, 50) + { + AddPage(0); + + AddImage(100, 100, 2080); + AddImage(118, 137, 2081); + AddImage(118, 207, 2081); + AddImage(118, 277, 2081); + AddImage(118, 347, 2083); + + AddHtml(147, 108, 210, 18, $"
{c.Name}
"); + + AddButton(240, 77, 2093, 2093, 2); + + AddImage(140, 138, 2091); + AddImage(140, 335, 2091); + + var pages = Core.AOS ? 5 : 3; + var page = 0; + + AddPage(++page); + + AddImage(128, 152, 2086); + AddHtmlLocalized(147, 150, 160, 18, 1049593, 200); // Attributes + + AddHtmlLocalized(153, 168, 160, 18, 1049578, LabelColor); // Hits + AddHtml(280, 168, 75, 18, FormatAttributes(c.Hits, c.HitsMax)); + + AddHtmlLocalized(153, 186, 160, 18, 1049579, LabelColor); // Stamina + AddHtml(280, 186, 75, 18, FormatAttributes(c.Stam, c.StamMax)); + + AddHtmlLocalized(153, 204, 160, 18, 1049580, LabelColor); // Mana + AddHtml(280, 204, 75, 18, FormatAttributes(c.Mana, c.ManaMax)); + + AddHtmlLocalized(153, 222, 160, 18, 1028335, LabelColor); // Strength + AddHtml(320, 222, 35, 18, FormatStat(c.Str)); + + AddHtmlLocalized(153, 240, 160, 18, 3000113, LabelColor); // Dexterity + AddHtml(320, 240, 35, 18, FormatStat(c.Dex)); + + AddHtmlLocalized(153, 258, 160, 18, 3000112, LabelColor); // Intelligence + AddHtml(320, 258, 35, 18, FormatStat(c.Int)); + + if (Core.AOS) + { + var y = 276; + + if (Core.SE) + { + var bd = BaseInstrument.GetBaseDifficulty(c); + if (c.Uncalmable) + bd = 0; + + AddHtmlLocalized(153, 276, 160, 18, 1070793, LabelColor); // Barding Difficulty + AddHtml(320, y, 35, 18, FormatDouble(bd)); + + y += 18; + } + + AddImage(128, y + 2, 2086); + AddHtmlLocalized(147, y, 160, 18, 1049594, 200); // Loyalty Rating + y += 18; + + AddHtmlLocalized( + 153, + y, + 160, + 18, + !c.Controlled || c.Loyalty == 0 ? 1061643 : 1049595 + c.Loyalty / 10, + LabelColor + ); } else { - from.SendLocalizedMessage(500329); // That's not an animal! + AddImage(128, 278, 2086); + AddHtmlLocalized(147, 276, 160, 18, 3001016, 200); // Miscellaneous + + AddHtmlLocalized(153, 294, 160, 18, 1049581, LabelColor); // Armor Rating + AddHtml(320, 294, 35, 18, FormatStat(c.VirtualArmor)); } - } - else - { - from.SendLocalizedMessage(500331); // The spirits of the dead are not the province of animal lore. - } + + AddButton(340, 358, 5601, 5605, 0, GumpButtonType.Page, page + 1); + AddButton(317, 358, 5603, 5607, 0, GumpButtonType.Page, pages); + + if (Core.AOS) + { + AddPage(++page); + + AddImage(128, 152, 2086); + AddHtmlLocalized(147, 150, 160, 18, 1061645, 200); // Resistances + + AddHtmlLocalized(153, 168, 160, 18, 1061646, LabelColor); // Physical + AddHtml(320, 168, 35, 18, FormatElement(c.PhysicalResistance)); + + AddHtmlLocalized(153, 186, 160, 18, 1061647, LabelColor); // Fire + AddHtml(320, 186, 35, 18, FormatElement(c.FireResistance)); + + AddHtmlLocalized(153, 204, 160, 18, 1061648, LabelColor); // Cold + AddHtml(320, 204, 35, 18, FormatElement(c.ColdResistance)); + + AddHtmlLocalized(153, 222, 160, 18, 1061649, LabelColor); // Poison + AddHtml(320, 222, 35, 18, FormatElement(c.PoisonResistance)); + + AddHtmlLocalized(153, 240, 160, 18, 1061650, LabelColor); // Energy + AddHtml(320, 240, 35, 18, FormatElement(c.EnergyResistance)); + + AddButton(340, 358, 5601, 5605, 0, GumpButtonType.Page, page + 1); + AddButton(317, 358, 5603, 5607, 0, GumpButtonType.Page, page - 1); + } + + if (Core.AOS) + { + AddPage(++page); + + AddImage(128, 152, 2086); + AddHtmlLocalized(147, 150, 160, 18, 1017319, 200); // Damage + + AddHtmlLocalized(153, 168, 160, 18, 1061646, LabelColor); // Physical + AddHtml(320, 168, 35, 18, FormatElement(c.PhysicalDamage)); + + AddHtmlLocalized(153, 186, 160, 18, 1061647, LabelColor); // Fire + AddHtml(320, 186, 35, 18, FormatElement(c.FireDamage)); + + AddHtmlLocalized(153, 204, 160, 18, 1061648, LabelColor); // Cold + AddHtml(320, 204, 35, 18, FormatElement(c.ColdDamage)); + + AddHtmlLocalized(153, 222, 160, 18, 1061649, LabelColor); // Poison + AddHtml(320, 222, 35, 18, FormatElement(c.PoisonDamage)); + + AddHtmlLocalized(153, 240, 160, 18, 1061650, LabelColor); // Energy + AddHtml(320, 240, 35, 18, FormatElement(c.EnergyDamage)); + + if (Core.ML) + { + AddHtmlLocalized(153, 258, 160, 18, 1076750, LabelColor); // Base Damage + AddHtml(300, 258, 55, 18, FormatDamage(c.DamageMin, c.DamageMax)); + } + + AddButton(340, 358, 5601, 5605, 0, GumpButtonType.Page, page + 1); + AddButton(317, 358, 5603, 5607, 0, GumpButtonType.Page, page - 1); + } + + AddPage(++page); + + AddImage(128, 152, 2086); + AddHtmlLocalized(147, 150, 160, 18, 3001030, 200); // Combat Ratings + + AddHtmlLocalized(153, 168, 160, 18, 1044103, LabelColor); // Wrestling + AddHtml(320, 168, 35, 18, FormatSkill(c, SkillName.Wrestling)); + + AddHtmlLocalized(153, 186, 160, 18, 1044087, LabelColor); // Tactics + AddHtml(320, 186, 35, 18, FormatSkill(c, SkillName.Tactics)); + + AddHtmlLocalized(153, 204, 160, 18, 1044086, LabelColor); // Magic Resistance + AddHtml(320, 204, 35, 18, FormatSkill(c, SkillName.MagicResist)); + + AddHtmlLocalized(153, 222, 160, 18, 1044061, LabelColor); // Anatomy + AddHtml(320, 222, 35, 18, FormatSkill(c, SkillName.Anatomy)); + + if (c is CuSidhe) + { + AddHtmlLocalized(153, 240, 160, 18, 1044077, LabelColor); // Healing + AddHtml(320, 240, 35, 18, FormatSkill(c, SkillName.Healing)); + } + else + { + AddHtmlLocalized(153, 240, 160, 18, 1044090, LabelColor); // Poisoning + AddHtml(320, 240, 35, 18, FormatSkill(c, SkillName.Poisoning)); + } + + AddImage(128, 260, 2086); + AddHtmlLocalized(147, 258, 160, 18, 3001032, 200); // Lore & Knowledge + + AddHtmlLocalized(153, 276, 160, 18, 1044085, LabelColor); // Magery + AddHtml(320, 276, 35, 18, FormatSkill(c, SkillName.Magery)); + + AddHtmlLocalized(153, 294, 160, 18, 1044076, LabelColor); // Evaluating Intelligence + AddHtml(320, 294, 35, 18, FormatSkill(c, SkillName.EvalInt)); + + AddHtmlLocalized(153, 312, 160, 18, 1044106, LabelColor); // Meditation + AddHtml(320, 312, 35, 18, FormatSkill(c, SkillName.Meditation)); + + AddButton(340, 358, 5601, 5605, 0, GumpButtonType.Page, page + 1); + AddButton(317, 358, 5603, 5607, 0, GumpButtonType.Page, page - 1); + + AddPage(++page); + + AddImage(128, 152, 2086); + AddHtmlLocalized(147, 150, 160, 18, 1049563, 200); // Preferred Foods + + var foodPref = 3000340; + + if ((c.FavoriteFood & FoodType.FruitsAndVegies) != 0) + foodPref = 1049565; // Fruits and Vegetables + else if ((c.FavoriteFood & FoodType.GrainsAndHay) != 0) + foodPref = 1049566; // Grains and Hay + else if ((c.FavoriteFood & FoodType.Fish) != 0) + foodPref = 1049568; // Fish + else if ((c.FavoriteFood & FoodType.Meat) != 0) + foodPref = 1049564; // Meat + else if ((c.FavoriteFood & FoodType.Eggs) != 0) + foodPref = 1044477; // Eggs + + AddHtmlLocalized(153, 168, 160, 18, foodPref, LabelColor); + + AddImage(128, 188, 2086); + AddHtmlLocalized(147, 186, 160, 18, 1049569, 200); // Pack Instincts + + var packInstinct = 3000340; + + if ((c.PackInstinct & PackInstinct.Canine) != 0) + packInstinct = 1049570; // Canine + else if ((c.PackInstinct & PackInstinct.Ostard) != 0) + packInstinct = 1049571; // Ostard + else if ((c.PackInstinct & PackInstinct.Feline) != 0) + packInstinct = 1049572; // Feline + else if ((c.PackInstinct & PackInstinct.Arachnid) != 0) + packInstinct = 1049573; // Arachnid + else if ((c.PackInstinct & PackInstinct.Daemon) != 0) + packInstinct = 1049574; // Daemon + else if ((c.PackInstinct & PackInstinct.Bear) != 0) + packInstinct = 1049575; // Bear + else if ((c.PackInstinct & PackInstinct.Equine) != 0) + packInstinct = 1049576; // Equine + else if ((c.PackInstinct & PackInstinct.Bull) != 0) + packInstinct = 1049577; // Bull + + AddHtmlLocalized(153, 204, 160, 18, packInstinct, LabelColor); + + if (!Core.AOS) + { + AddImage(128, 224, 2086); + AddHtmlLocalized(147, 222, 160, 18, 1049594, 200); // Loyalty Rating + + AddHtmlLocalized( + 153, + 240, + 160, + 18, + !c.Controlled || c.Loyalty == 0 ? 1061643 : 1049595 + c.Loyalty / 10, + LabelColor + ); + } + + AddButton(340, 358, 5601, 5605, 0, GumpButtonType.Page, 1); + AddButton(317, 358, 5603, 5607, 0, GumpButtonType.Page, page - 1); } - else + + private static string FormatSkill(BaseCreature c, SkillName name) { - from.SendLocalizedMessage(500329); // That's not an animal! + var skill = c.Skills[name]; + + if (skill.Base < 10.0) + return "
---
"; + + return $"
{skill.Value:F1}
"; } - } - } - } - public class AnimalLoreGump : Gump - { - private const int LabelColor = 0x24E5; - - public AnimalLoreGump(BaseCreature c) : base(250, 50) - { - AddPage(0); - - AddImage(100, 100, 2080); - AddImage(118, 137, 2081); - AddImage(118, 207, 2081); - AddImage(118, 277, 2081); - AddImage(118, 347, 2083); - - AddHtml(147, 108, 210, 18, $"
{c.Name}
"); - - AddButton(240, 77, 2093, 2093, 2); - - AddImage(140, 138, 2091); - AddImage(140, 335, 2091); - - int pages = Core.AOS ? 5 : 3; - int page = 0; - - AddPage(++page); - - AddImage(128, 152, 2086); - AddHtmlLocalized(147, 150, 160, 18, 1049593, 200); // Attributes - - AddHtmlLocalized(153, 168, 160, 18, 1049578, LabelColor); // Hits - AddHtml(280, 168, 75, 18, FormatAttributes(c.Hits, c.HitsMax)); - - AddHtmlLocalized(153, 186, 160, 18, 1049579, LabelColor); // Stamina - AddHtml(280, 186, 75, 18, FormatAttributes(c.Stam, c.StamMax)); - - AddHtmlLocalized(153, 204, 160, 18, 1049580, LabelColor); // Mana - AddHtml(280, 204, 75, 18, FormatAttributes(c.Mana, c.ManaMax)); - - AddHtmlLocalized(153, 222, 160, 18, 1028335, LabelColor); // Strength - AddHtml(320, 222, 35, 18, FormatStat(c.Str)); - - AddHtmlLocalized(153, 240, 160, 18, 3000113, LabelColor); // Dexterity - AddHtml(320, 240, 35, 18, FormatStat(c.Dex)); - - AddHtmlLocalized(153, 258, 160, 18, 3000112, LabelColor); // Intelligence - AddHtml(320, 258, 35, 18, FormatStat(c.Int)); - - if (Core.AOS) - { - int y = 276; - - if (Core.SE) + private static string FormatAttributes(int cur, int max) { - double bd = BaseInstrument.GetBaseDifficulty(c); - if (c.Uncalmable) - bd = 0; + if (max == 0) + return "
---
"; - AddHtmlLocalized(153, 276, 160, 18, 1070793, LabelColor); // Barding Difficulty - AddHtml(320, y, 35, 18, FormatDouble(bd)); - - y += 18; + return $"
{cur}/{max}
"; } - AddImage(128, y + 2, 2086); - AddHtmlLocalized(147, y, 160, 18, 1049594, 200); // Loyalty Rating - y += 18; - - AddHtmlLocalized(153, y, 160, 18, !c.Controlled || c.Loyalty == 0 ? 1061643 : 1049595 + c.Loyalty / 10, - LabelColor); - } - else - { - AddImage(128, 278, 2086); - AddHtmlLocalized(147, 276, 160, 18, 3001016, 200); // Miscellaneous - - AddHtmlLocalized(153, 294, 160, 18, 1049581, LabelColor); // Armor Rating - AddHtml(320, 294, 35, 18, FormatStat(c.VirtualArmor)); - } - - AddButton(340, 358, 5601, 5605, 0, GumpButtonType.Page, page + 1); - AddButton(317, 358, 5603, 5607, 0, GumpButtonType.Page, pages); - - if (Core.AOS) - { - AddPage(++page); - - AddImage(128, 152, 2086); - AddHtmlLocalized(147, 150, 160, 18, 1061645, 200); // Resistances - - AddHtmlLocalized(153, 168, 160, 18, 1061646, LabelColor); // Physical - AddHtml(320, 168, 35, 18, FormatElement(c.PhysicalResistance)); - - AddHtmlLocalized(153, 186, 160, 18, 1061647, LabelColor); // Fire - AddHtml(320, 186, 35, 18, FormatElement(c.FireResistance)); - - AddHtmlLocalized(153, 204, 160, 18, 1061648, LabelColor); // Cold - AddHtml(320, 204, 35, 18, FormatElement(c.ColdResistance)); - - AddHtmlLocalized(153, 222, 160, 18, 1061649, LabelColor); // Poison - AddHtml(320, 222, 35, 18, FormatElement(c.PoisonResistance)); - - AddHtmlLocalized(153, 240, 160, 18, 1061650, LabelColor); // Energy - AddHtml(320, 240, 35, 18, FormatElement(c.EnergyResistance)); - - AddButton(340, 358, 5601, 5605, 0, GumpButtonType.Page, page + 1); - AddButton(317, 358, 5603, 5607, 0, GumpButtonType.Page, page - 1); - } - - if (Core.AOS) - { - AddPage(++page); - - AddImage(128, 152, 2086); - AddHtmlLocalized(147, 150, 160, 18, 1017319, 200); // Damage - - AddHtmlLocalized(153, 168, 160, 18, 1061646, LabelColor); // Physical - AddHtml(320, 168, 35, 18, FormatElement(c.PhysicalDamage)); - - AddHtmlLocalized(153, 186, 160, 18, 1061647, LabelColor); // Fire - AddHtml(320, 186, 35, 18, FormatElement(c.FireDamage)); - - AddHtmlLocalized(153, 204, 160, 18, 1061648, LabelColor); // Cold - AddHtml(320, 204, 35, 18, FormatElement(c.ColdDamage)); - - AddHtmlLocalized(153, 222, 160, 18, 1061649, LabelColor); // Poison - AddHtml(320, 222, 35, 18, FormatElement(c.PoisonDamage)); - - AddHtmlLocalized(153, 240, 160, 18, 1061650, LabelColor); // Energy - AddHtml(320, 240, 35, 18, FormatElement(c.EnergyDamage)); - - if (Core.ML) + private static string FormatStat(int val) { - AddHtmlLocalized(153, 258, 160, 18, 1076750, LabelColor); // Base Damage - AddHtml(300, 258, 55, 18, FormatDamage(c.DamageMin, c.DamageMax)); + if (val == 0) + return "
---
"; + + return $"
{val}
"; } - AddButton(340, 358, 5601, 5605, 0, GumpButtonType.Page, page + 1); - AddButton(317, 358, 5603, 5607, 0, GumpButtonType.Page, page - 1); - } + private static string FormatDouble(double val) + { + if (val == 0) + return "
---
"; - AddPage(++page); + return $"
{val:F1}
"; + } - AddImage(128, 152, 2086); - AddHtmlLocalized(147, 150, 160, 18, 3001030, 200); // Combat Ratings + private static string FormatElement(int val) + { + if (val <= 0) + return "
---
"; - AddHtmlLocalized(153, 168, 160, 18, 1044103, LabelColor); // Wrestling - AddHtml(320, 168, 35, 18, FormatSkill(c, SkillName.Wrestling)); + return $"
{val}%
"; + } - AddHtmlLocalized(153, 186, 160, 18, 1044087, LabelColor); // Tactics - AddHtml(320, 186, 35, 18, FormatSkill(c, SkillName.Tactics)); + private static string FormatDamage(int min, int max) + { + if (min <= 0 || max <= 0) + return "
---
"; - AddHtmlLocalized(153, 204, 160, 18, 1044086, LabelColor); // Magic Resistance - AddHtml(320, 204, 35, 18, FormatSkill(c, SkillName.MagicResist)); - - AddHtmlLocalized(153, 222, 160, 18, 1044061, LabelColor); // Anatomy - AddHtml(320, 222, 35, 18, FormatSkill(c, SkillName.Anatomy)); - - if (c is CuSidhe) - { - AddHtmlLocalized(153, 240, 160, 18, 1044077, LabelColor); // Healing - AddHtml(320, 240, 35, 18, FormatSkill(c, SkillName.Healing)); - } - else - { - AddHtmlLocalized(153, 240, 160, 18, 1044090, LabelColor); // Poisoning - AddHtml(320, 240, 35, 18, FormatSkill(c, SkillName.Poisoning)); - } - - AddImage(128, 260, 2086); - AddHtmlLocalized(147, 258, 160, 18, 3001032, 200); // Lore & Knowledge - - AddHtmlLocalized(153, 276, 160, 18, 1044085, LabelColor); // Magery - AddHtml(320, 276, 35, 18, FormatSkill(c, SkillName.Magery)); - - AddHtmlLocalized(153, 294, 160, 18, 1044076, LabelColor); // Evaluating Intelligence - AddHtml(320, 294, 35, 18, FormatSkill(c, SkillName.EvalInt)); - - AddHtmlLocalized(153, 312, 160, 18, 1044106, LabelColor); // Meditation - AddHtml(320, 312, 35, 18, FormatSkill(c, SkillName.Meditation)); - - AddButton(340, 358, 5601, 5605, 0, GumpButtonType.Page, page + 1); - AddButton(317, 358, 5603, 5607, 0, GumpButtonType.Page, page - 1); - - AddPage(++page); - - AddImage(128, 152, 2086); - AddHtmlLocalized(147, 150, 160, 18, 1049563, 200); // Preferred Foods - - int foodPref = 3000340; - - if ((c.FavoriteFood & FoodType.FruitsAndVegies) != 0) - foodPref = 1049565; // Fruits and Vegetables - else if ((c.FavoriteFood & FoodType.GrainsAndHay) != 0) - foodPref = 1049566; // Grains and Hay - else if ((c.FavoriteFood & FoodType.Fish) != 0) - foodPref = 1049568; // Fish - else if ((c.FavoriteFood & FoodType.Meat) != 0) - foodPref = 1049564; // Meat - else if ((c.FavoriteFood & FoodType.Eggs) != 0) - foodPref = 1044477; // Eggs - - AddHtmlLocalized(153, 168, 160, 18, foodPref, LabelColor); - - AddImage(128, 188, 2086); - AddHtmlLocalized(147, 186, 160, 18, 1049569, 200); // Pack Instincts - - int packInstinct = 3000340; - - if ((c.PackInstinct & PackInstinct.Canine) != 0) - packInstinct = 1049570; // Canine - else if ((c.PackInstinct & PackInstinct.Ostard) != 0) - packInstinct = 1049571; // Ostard - else if ((c.PackInstinct & PackInstinct.Feline) != 0) - packInstinct = 1049572; // Feline - else if ((c.PackInstinct & PackInstinct.Arachnid) != 0) - packInstinct = 1049573; // Arachnid - else if ((c.PackInstinct & PackInstinct.Daemon) != 0) - packInstinct = 1049574; // Daemon - else if ((c.PackInstinct & PackInstinct.Bear) != 0) - packInstinct = 1049575; // Bear - else if ((c.PackInstinct & PackInstinct.Equine) != 0) - packInstinct = 1049576; // Equine - else if ((c.PackInstinct & PackInstinct.Bull) != 0) - packInstinct = 1049577; // Bull - - AddHtmlLocalized(153, 204, 160, 18, packInstinct, LabelColor); - - if (!Core.AOS) - { - AddImage(128, 224, 2086); - AddHtmlLocalized(147, 222, 160, 18, 1049594, 200); // Loyalty Rating - - AddHtmlLocalized(153, 240, 160, 18, !c.Controlled || c.Loyalty == 0 ? 1061643 : 1049595 + c.Loyalty / 10, - LabelColor); - } - - AddButton(340, 358, 5601, 5605, 0, GumpButtonType.Page, 1); - AddButton(317, 358, 5603, 5607, 0, GumpButtonType.Page, page - 1); + return $"
{min}-{max}
"; + } } - - private static string FormatSkill(BaseCreature c, SkillName name) - { - Skill skill = c.Skills[name]; - - if (skill.Base < 10.0) - return "
---
"; - - return $"
{skill.Value:F1}
"; - } - - private static string FormatAttributes(int cur, int max) - { - if (max == 0) - return "
---
"; - - return $"
{cur}/{max}
"; - } - - private static string FormatStat(int val) - { - if (val == 0) - return "
---
"; - - return $"
{val}
"; - } - - private static string FormatDouble(double val) - { - if (val == 0) - return "
---
"; - - return $"
{val:F1}
"; - } - - private static string FormatElement(int val) - { - if (val <= 0) - return "
---
"; - - return $"
{val}%
"; - } - - private static string FormatDamage(int min, int max) - { - if (min <= 0 || max <= 0) - return "
---
"; - - return $"
{min}-{max}
"; - } - } } diff --git a/Projects/UOContent/Skills/AnimalTaming.cs b/Projects/UOContent/Skills/AnimalTaming.cs index c615af135..95b7ff377 100644 --- a/Projects/UOContent/Skills/AnimalTaming.cs +++ b/Projects/UOContent/Skills/AnimalTaming.cs @@ -10,414 +10,513 @@ using Server.Targeting; namespace Server.SkillHandlers { - public static class AnimalTaming - { - private static readonly HashSet m_BeingTamed = new HashSet(); - - public static bool DisableMessage { get; set; } - - public static void Initialize() + public static class AnimalTaming { - SkillInfo.Table[(int)SkillName.AnimalTaming].Callback = OnUse; - } + private static readonly HashSet m_BeingTamed = new HashSet(); - public static TimeSpan OnUse(Mobile m) - { - m.RevealingAction(); + public static bool DisableMessage { get; set; } - m.Target = new InternalTarget(); - m.RevealingAction(); - - if (!DisableMessage) - m.SendLocalizedMessage(502789); // Tame which animal? - - return TimeSpan.FromHours(6.0); - } - - public static bool CheckMastery(Mobile tamer, BaseCreature creature) => - SummonFamiliarSpell.Table.TryGetValue(tamer, out BaseCreature bc) && bc is DarkWolfFamiliar familiar && - !familiar.Deleted && (creature is DireWolf || creature is GreyWolf || creature is TimberWolf || - creature is WhiteWolf || - creature is BakeKitsune); - - public static bool MustBeSubdued(BaseCreature bc) => bc.Owners.Count <= 0 && bc.SubdueBeforeTame && bc.Hits > bc.HitsMax / 10; - - public static void ScaleStats(BaseCreature bc, double scalar) - { - if (bc.RawStr > 0) - bc.RawStr = (int)Math.Max(1, bc.RawStr * scalar); - - if (bc.RawDex > 0) - bc.RawDex = (int)Math.Max(1, bc.RawDex * scalar); - - if (bc.RawInt > 0) - bc.RawInt = (int)Math.Max(1, bc.RawInt * scalar); - - if (bc.HitsMaxSeed > 0) - { - bc.HitsMaxSeed = (int)Math.Max(1, bc.HitsMaxSeed * scalar); - bc.Hits = bc.Hits; - } - - if (bc.StamMaxSeed > 0) - { - bc.StamMaxSeed = (int)Math.Max(1, bc.StamMaxSeed * scalar); - bc.Stam = bc.Stam; - } - } - - public static void ScaleSkills(BaseCreature bc, double scalar) - { - ScaleSkills(bc, scalar, scalar); - } - - public static void ScaleSkills(BaseCreature bc, double scalar, double capScalar) - { - for (int i = 0; i < bc.Skills.Length; ++i) - { - bc.Skills[i].Base *= scalar; - - bc.Skills[i].Cap = Math.Max(100.0, bc.Skills[i].Cap * capScalar); - - if (bc.Skills[i].Base > bc.Skills[i].Cap) bc.Skills[i].Cap = bc.Skills[i].Base; - } - } - - private class InternalTarget : Target - { - private bool m_SetSkillTime = true; - - public InternalTarget() : base(Core.AOS ? 3 : 2, false, TargetFlags.None) - { - } - - protected override void OnTargetFinish(Mobile from) - { - if (m_SetSkillTime) - from.NextSkillTime = Core.TickCount; - } - - protected override void OnTarget(Mobile from, object targeted) - { - from.RevealingAction(); - - if (!(targeted is Mobile mobile)) + public static void Initialize() { - from.SendLocalizedMessage(502801); // You can't tame that! - return; + SkillInfo.Table[(int)SkillName.AnimalTaming].Callback = OnUse; } - if (!(mobile is BaseCreature creature)) + public static TimeSpan OnUse(Mobile m) { - mobile.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 502469, - from.NetState); // That being cannot be tamed. - return; + m.RevealingAction(); + + m.Target = new InternalTarget(); + m.RevealingAction(); + + if (!DisableMessage) + m.SendLocalizedMessage(502789); // Tame which animal? + + return TimeSpan.FromHours(6.0); } - if (!creature.Tamable) + public static bool CheckMastery(Mobile tamer, BaseCreature creature) => + SummonFamiliarSpell.Table.TryGetValue(tamer, out var bc) && bc is DarkWolfFamiliar familiar && + !familiar.Deleted && (creature is DireWolf || creature is GreyWolf || creature is TimberWolf || + creature is WhiteWolf || + creature is BakeKitsune); + + public static bool MustBeSubdued(BaseCreature bc) => + bc.Owners.Count <= 0 && bc.SubdueBeforeTame && bc.Hits > bc.HitsMax / 10; + + public static void ScaleStats(BaseCreature bc, double scalar) { - creature.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1049655, - from.NetState); // That creature cannot be tamed. - return; - } + if (bc.RawStr > 0) + bc.RawStr = (int)Math.Max(1, bc.RawStr * scalar); - if (creature.Controlled) - { - creature.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 502804, - from.NetState); // That animal looks tame already. - return; - } + if (bc.RawDex > 0) + bc.RawDex = (int)Math.Max(1, bc.RawDex * scalar); - if (from.Female && !creature.AllowFemaleTamer) - { - creature.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1049653, - from.NetState); // That creature can only be tamed by males. - return; - } + if (bc.RawInt > 0) + bc.RawInt = (int)Math.Max(1, bc.RawInt * scalar); - if (!from.Female && !creature.AllowMaleTamer) - { - creature.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1049652, - from.NetState); // That creature can only be tamed by females. - return; - } - - if (creature is CuSidhe && from.Race != Race.Elf) - { - creature.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 502801, - from.NetState); // You can't tame that! - return; - } - - if (from.Followers + creature.ControlSlots > from.FollowersMax) - { - from.SendLocalizedMessage(1049611); // You have too many followers to tame that creature. - return; - } - if (creature.Owners.Count >= BaseCreature.MaxOwners && !creature.Owners.Contains(from)) - { - creature.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1005615, - from.NetState); // This animal has had too many owners and is too upset for you to tame. - return; - } - if (MustBeSubdued(creature)) - { - creature.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1054025, - from.NetState); // You must subdue this creature before you can tame it! - return; - } - - if (!(CheckMastery(from, creature) || from.Skills.AnimalTaming.Value >= creature.MinTameSkill)) - { - creature.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 502806, - from.NetState); // You have no chance of taming this creature. - return; - } - - if (creature is FactionWarHorse warHorse) - { - Faction faction = Faction.Find(from); - - if (faction == null || faction != warHorse.Faction) - { - creature.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1042590, - from.NetState); // You cannot tame this creature. - return; - } - } - - if (m_BeingTamed.Contains(creature)) - { - creature.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 502802, - from.NetState); // Someone else is already taming this. - } - else if (creature.CanAngerOnTame && Utility.RandomDouble() <= 0.95) - { - creature.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 502805, - from.NetState); // You seem to anger the beast! - creature.PlaySound(creature.GetAngerSound()); - creature.Direction = creature.GetDirectionTo(from); - - if (creature.BardPacified && Utility.RandomDouble() > .24) - Timer.DelayCall(TimeSpan.FromSeconds(2.0), Pacify, creature); - else - creature.BardEndTime = DateTime.UtcNow; - - creature.BardPacified = false; - - creature.AIObject?.DoMove(creature.Direction); - - if (from is PlayerMobile pm && - !(pm.HonorActive || - TransformationSpellHelper.UnderTransformation(pm, typeof(EtherealVoyageSpell)))) - creature.Combatant = pm; - } - else - { - m_BeingTamed.Add(creature); - - from.LocalOverheadMessage(MessageType.Emote, 0x59, - 1010597); // You start to tame the creature. - from.NonlocalOverheadMessage(MessageType.Emote, 0x59, - 1010598); // *begins taming a creature.* - - new InternalTimer(from, creature, Utility.Random(3, 2)).Start(); - - m_SetSkillTime = false; - } - } - - private static void Pacify(BaseCreature bc) => bc.BardPacified = true; // Should use bc.Pacify with an end time? - - private class InternalTimer : Timer - { - private int m_Count; - private readonly BaseCreature m_Creature; - private readonly int m_MaxCount; - private bool m_Paralyzed; - private readonly DateTime m_StartTime; - private readonly Mobile m_Tamer; - - public InternalTimer(Mobile tamer, BaseCreature creature, int count) : base(TimeSpan.FromSeconds(3.0), - TimeSpan.FromSeconds(3.0), count) - { - m_Tamer = tamer; - m_Creature = creature; - m_MaxCount = count; - m_Paralyzed = creature.Paralyzed; - m_StartTime = DateTime.UtcNow; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - m_Count++; - - DamageEntry de = m_Creature.FindMostRecentDamageEntry(false); - bool alreadyOwned = m_Creature.Owners.Contains(m_Tamer); - - if (!m_Tamer.InRange(m_Creature, Core.AOS ? 7 : 6)) - { - m_BeingTamed.Remove(m_Creature); - m_Tamer.NextSkillTime = Core.TickCount; - m_Creature.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 502795, - m_Tamer.NetState); // You are too far away to continue taming. - Stop(); - } - else if (!m_Tamer.CheckAlive()) - { - m_BeingTamed.Remove(m_Creature); - m_Tamer.NextSkillTime = Core.TickCount; - m_Creature.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 502796, - m_Tamer.NetState); // You are dead, and cannot continue taming. - Stop(); - } - else if (!m_Tamer.CanSee(m_Creature) || !m_Tamer.InLOS(m_Creature) || !CanPath()) - { - m_BeingTamed.Remove(m_Creature); - m_Tamer.NextSkillTime = Core.TickCount; - m_Tamer.SendLocalizedMessage( - 1049654); // You do not have a clear path to the animal you are taming, and must cease your attempt. - Stop(); - } - else if (!m_Creature.Tamable) - { - m_BeingTamed.Remove(m_Creature); - m_Tamer.NextSkillTime = Core.TickCount; - m_Creature.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1049655, - m_Tamer.NetState); // That creature cannot be tamed. - Stop(); - } - else if (m_Creature.Controlled) - { - m_BeingTamed.Remove(m_Creature); - m_Tamer.NextSkillTime = Core.TickCount; - m_Creature.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 502804, - m_Tamer.NetState); // That animal looks tame already. - Stop(); - } - else if (m_Creature.Owners.Count >= BaseCreature.MaxOwners && !m_Creature.Owners.Contains(m_Tamer)) - { - m_BeingTamed.Remove(m_Creature); - m_Tamer.NextSkillTime = Core.TickCount; - m_Creature.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1005615, - m_Tamer.NetState); // This animal has had too many owners and is too upset for you to tame. - Stop(); - } - else if (MustBeSubdued(m_Creature)) - { - m_BeingTamed.Remove(m_Creature); - m_Tamer.NextSkillTime = Core.TickCount; - m_Creature.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1054025, - m_Tamer.NetState); // You must subdue this creature before you can tame it! - Stop(); - } - else if (de?.LastDamage > m_StartTime) - { - m_BeingTamed.Remove(m_Creature); - m_Tamer.NextSkillTime = Core.TickCount; - m_Creature.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 502794, - m_Tamer.NetState); // The animal is too angry to continue taming. - Stop(); - } - else if (m_Count < m_MaxCount) - { - m_Tamer.RevealingAction(); - - switch (Utility.Random(3)) + if (bc.HitsMaxSeed > 0) { - case 0: - m_Tamer.PublicOverheadMessage(MessageType.Regular, 0x3B2, Utility.Random(502790, 4)); - break; - case 1: - m_Tamer.PublicOverheadMessage(MessageType.Regular, 0x3B2, Utility.Random(1005608, 6)); - break; - case 2: - m_Tamer.PublicOverheadMessage(MessageType.Regular, 0x3B2, Utility.Random(1010593, 4)); - break; + bc.HitsMaxSeed = (int)Math.Max(1, bc.HitsMaxSeed * scalar); + bc.Hits = bc.Hits; } - if (!alreadyOwned) // Passively check animal lore for gain - m_Tamer.CheckTargetSkill(SkillName.AnimalLore, m_Creature, 0.0, 120.0); - - if (m_Creature.Paralyzed) - m_Paralyzed = true; - } - else - { - m_Tamer.RevealingAction(); - m_Tamer.NextSkillTime = Core.TickCount; - m_BeingTamed.Remove(m_Creature); - - if (m_Creature.Paralyzed) - m_Paralyzed = true; - - if (!alreadyOwned) // Passively check animal lore for gain - m_Tamer.CheckTargetSkill(SkillName.AnimalLore, m_Creature, 0.0, 120.0); - - double minSkill = m_Creature.MinTameSkill + m_Creature.Owners.Count * 6.0; - - if (minSkill > -24.9 && CheckMastery(m_Tamer, m_Creature)) - minSkill = -24.9; // 50% at 0.0? - - minSkill += 24.9; - - if (CheckMastery(m_Tamer, m_Creature) || alreadyOwned || - m_Tamer.CheckTargetSkill(SkillName.AnimalTaming, m_Creature, minSkill - 25.0, minSkill + 25.0)) + if (bc.StamMaxSeed > 0) { - if (m_Creature.Owners.Count == 0) // First tame - { - if (m_Creature is GreaterDragon) + bc.StamMaxSeed = (int)Math.Max(1, bc.StamMaxSeed * scalar); + bc.Stam = bc.Stam; + } + } + + public static void ScaleSkills(BaseCreature bc, double scalar) + { + ScaleSkills(bc, scalar, scalar); + } + + public static void ScaleSkills(BaseCreature bc, double scalar, double capScalar) + { + for (var i = 0; i < bc.Skills.Length; ++i) + { + bc.Skills[i].Base *= scalar; + + bc.Skills[i].Cap = Math.Max(100.0, bc.Skills[i].Cap * capScalar); + + if (bc.Skills[i].Base > bc.Skills[i].Cap) bc.Skills[i].Cap = bc.Skills[i].Base; + } + } + + private class InternalTarget : Target + { + private bool m_SetSkillTime = true; + + public InternalTarget() : base(Core.AOS ? 3 : 2, false, TargetFlags.None) + { + } + + protected override void OnTargetFinish(Mobile from) + { + if (m_SetSkillTime) + from.NextSkillTime = Core.TickCount; + } + + protected override void OnTarget(Mobile from, object targeted) + { + from.RevealingAction(); + + if (!(targeted is Mobile mobile)) { - ScaleSkills(m_Creature, 0.72, 0.90); // 72% of original skills trainable to 90% - m_Creature.Skills.Magery.Base = - m_Creature.Skills.Magery - .Cap; // Greater dragons have a 90% cap reduction and 90% skill reduction on magery + from.SendLocalizedMessage(502801); // You can't tame that! + return; } - else if (m_Paralyzed) + + if (!(mobile is BaseCreature creature)) { - ScaleSkills(m_Creature, - 0.86); // 86% of original skills if they were paralyzed during the taming + mobile.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 502469, + from.NetState + ); // That being cannot be tamed. + return; + } + + if (!creature.Tamable) + { + creature.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 1049655, + from.NetState + ); // That creature cannot be tamed. + return; + } + + if (creature.Controlled) + { + creature.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 502804, + from.NetState + ); // That animal looks tame already. + return; + } + + if (from.Female && !creature.AllowFemaleTamer) + { + creature.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 1049653, + from.NetState + ); // That creature can only be tamed by males. + return; + } + + if (!from.Female && !creature.AllowMaleTamer) + { + creature.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 1049652, + from.NetState + ); // That creature can only be tamed by females. + return; + } + + if (creature is CuSidhe && from.Race != Race.Elf) + { + creature.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 502801, + from.NetState + ); // You can't tame that! + return; + } + + if (from.Followers + creature.ControlSlots > from.FollowersMax) + { + from.SendLocalizedMessage(1049611); // You have too many followers to tame that creature. + return; + } + + if (creature.Owners.Count >= BaseCreature.MaxOwners && !creature.Owners.Contains(from)) + { + creature.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 1005615, + from.NetState + ); // This animal has had too many owners and is too upset for you to tame. + return; + } + + if (MustBeSubdued(creature)) + { + creature.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 1054025, + from.NetState + ); // You must subdue this creature before you can tame it! + return; + } + + if (!(CheckMastery(from, creature) || from.Skills.AnimalTaming.Value >= creature.MinTameSkill)) + { + creature.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 502806, + from.NetState + ); // You have no chance of taming this creature. + return; + } + + if (creature is FactionWarHorse warHorse) + { + var faction = Faction.Find(from); + + if (faction == null || faction != warHorse.Faction) + { + creature.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 1042590, + from.NetState + ); // You cannot tame this creature. + return; + } + } + + if (m_BeingTamed.Contains(creature)) + { + creature.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 502802, + from.NetState + ); // Someone else is already taming this. + } + else if (creature.CanAngerOnTame && Utility.RandomDouble() <= 0.95) + { + creature.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 502805, + from.NetState + ); // You seem to anger the beast! + creature.PlaySound(creature.GetAngerSound()); + creature.Direction = creature.GetDirectionTo(from); + + if (creature.BardPacified && Utility.RandomDouble() > .24) + Timer.DelayCall(TimeSpan.FromSeconds(2.0), Pacify, creature); + else + creature.BardEndTime = DateTime.UtcNow; + + creature.BardPacified = false; + + creature.AIObject?.DoMove(creature.Direction); + + if (from is PlayerMobile pm && + !(pm.HonorActive || + TransformationSpellHelper.UnderTransformation(pm, typeof(EtherealVoyageSpell)))) + creature.Combatant = pm; } else { - ScaleSkills(m_Creature, 0.90); // 90% of original skills + m_BeingTamed.Add(creature); + + from.LocalOverheadMessage( + MessageType.Emote, + 0x59, + 1010597 + ); // You start to tame the creature. + from.NonlocalOverheadMessage( + MessageType.Emote, + 0x59, + 1010598 + ); // *begins taming a creature.* + + new InternalTimer(from, creature, Utility.Random(3, 2)).Start(); + + m_SetSkillTime = false; + } + } + + private static void Pacify(BaseCreature bc) => bc.BardPacified = true; // Should use bc.Pacify with an end time? + + private class InternalTimer : Timer + { + private readonly BaseCreature m_Creature; + private readonly int m_MaxCount; + private readonly DateTime m_StartTime; + private readonly Mobile m_Tamer; + private int m_Count; + private bool m_Paralyzed; + + public InternalTimer(Mobile tamer, BaseCreature creature, int count) : base( + TimeSpan.FromSeconds(3.0), + TimeSpan.FromSeconds(3.0), + count + ) + { + m_Tamer = tamer; + m_Creature = creature; + m_MaxCount = count; + m_Paralyzed = creature.Paralyzed; + m_StartTime = DateTime.UtcNow; + Priority = TimerPriority.TwoFiftyMS; } - if (m_Creature.StatLossAfterTame) - ScaleStats(m_Creature, 0.50); - } + protected override void OnTick() + { + m_Count++; - if (alreadyOwned) - { - m_Tamer.SendLocalizedMessage(502797); // That wasn't even challenging. - } - else - { - m_Creature.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 502799, - m_Tamer.NetState); // It seems to accept you as master. - m_Creature.Owners.Add(m_Tamer); - } + var de = m_Creature.FindMostRecentDamageEntry(false); + var alreadyOwned = m_Creature.Owners.Contains(m_Tamer); - m_Creature.SetControlMaster(m_Tamer); - m_Creature.IsBonded = false; + if (!m_Tamer.InRange(m_Creature, Core.AOS ? 7 : 6)) + { + m_BeingTamed.Remove(m_Creature); + m_Tamer.NextSkillTime = Core.TickCount; + m_Creature.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 502795, + m_Tamer.NetState + ); // You are too far away to continue taming. + Stop(); + } + else if (!m_Tamer.CheckAlive()) + { + m_BeingTamed.Remove(m_Creature); + m_Tamer.NextSkillTime = Core.TickCount; + m_Creature.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 502796, + m_Tamer.NetState + ); // You are dead, and cannot continue taming. + Stop(); + } + else if (!m_Tamer.CanSee(m_Creature) || !m_Tamer.InLOS(m_Creature) || !CanPath()) + { + m_BeingTamed.Remove(m_Creature); + m_Tamer.NextSkillTime = Core.TickCount; + m_Tamer.SendLocalizedMessage( + 1049654 + ); // You do not have a clear path to the animal you are taming, and must cease your attempt. + Stop(); + } + else if (!m_Creature.Tamable) + { + m_BeingTamed.Remove(m_Creature); + m_Tamer.NextSkillTime = Core.TickCount; + m_Creature.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 1049655, + m_Tamer.NetState + ); // That creature cannot be tamed. + Stop(); + } + else if (m_Creature.Controlled) + { + m_BeingTamed.Remove(m_Creature); + m_Tamer.NextSkillTime = Core.TickCount; + m_Creature.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 502804, + m_Tamer.NetState + ); // That animal looks tame already. + Stop(); + } + else if (m_Creature.Owners.Count >= BaseCreature.MaxOwners && !m_Creature.Owners.Contains(m_Tamer)) + { + m_BeingTamed.Remove(m_Creature); + m_Tamer.NextSkillTime = Core.TickCount; + m_Creature.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 1005615, + m_Tamer.NetState + ); // This animal has had too many owners and is too upset for you to tame. + Stop(); + } + else if (MustBeSubdued(m_Creature)) + { + m_BeingTamed.Remove(m_Creature); + m_Tamer.NextSkillTime = Core.TickCount; + m_Creature.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 1054025, + m_Tamer.NetState + ); // You must subdue this creature before you can tame it! + Stop(); + } + else if (de?.LastDamage > m_StartTime) + { + m_BeingTamed.Remove(m_Creature); + m_Tamer.NextSkillTime = Core.TickCount; + m_Creature.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 502794, + m_Tamer.NetState + ); // The animal is too angry to continue taming. + Stop(); + } + else if (m_Count < m_MaxCount) + { + m_Tamer.RevealingAction(); + + switch (Utility.Random(3)) + { + case 0: + m_Tamer.PublicOverheadMessage(MessageType.Regular, 0x3B2, Utility.Random(502790, 4)); + break; + case 1: + m_Tamer.PublicOverheadMessage(MessageType.Regular, 0x3B2, Utility.Random(1005608, 6)); + break; + case 2: + m_Tamer.PublicOverheadMessage(MessageType.Regular, 0x3B2, Utility.Random(1010593, 4)); + break; + } + + if (!alreadyOwned) // Passively check animal lore for gain + m_Tamer.CheckTargetSkill(SkillName.AnimalLore, m_Creature, 0.0, 120.0); + + if (m_Creature.Paralyzed) + m_Paralyzed = true; + } + else + { + m_Tamer.RevealingAction(); + m_Tamer.NextSkillTime = Core.TickCount; + m_BeingTamed.Remove(m_Creature); + + if (m_Creature.Paralyzed) + m_Paralyzed = true; + + if (!alreadyOwned) // Passively check animal lore for gain + m_Tamer.CheckTargetSkill(SkillName.AnimalLore, m_Creature, 0.0, 120.0); + + var minSkill = m_Creature.MinTameSkill + m_Creature.Owners.Count * 6.0; + + if (minSkill > -24.9 && CheckMastery(m_Tamer, m_Creature)) + minSkill = -24.9; // 50% at 0.0? + + minSkill += 24.9; + + if (CheckMastery(m_Tamer, m_Creature) || alreadyOwned || + m_Tamer.CheckTargetSkill(SkillName.AnimalTaming, m_Creature, minSkill - 25.0, minSkill + 25.0)) + { + if (m_Creature.Owners.Count == 0) // First tame + { + if (m_Creature is GreaterDragon) + { + ScaleSkills(m_Creature, 0.72, 0.90); // 72% of original skills trainable to 90% + m_Creature.Skills.Magery.Base = + m_Creature.Skills.Magery + .Cap; // Greater dragons have a 90% cap reduction and 90% skill reduction on magery + } + else if (m_Paralyzed) + { + ScaleSkills( + m_Creature, + 0.86 + ); // 86% of original skills if they were paralyzed during the taming + } + else + { + ScaleSkills(m_Creature, 0.90); // 90% of original skills + } + + if (m_Creature.StatLossAfterTame) + ScaleStats(m_Creature, 0.50); + } + + if (alreadyOwned) + { + m_Tamer.SendLocalizedMessage(502797); // That wasn't even challenging. + } + else + { + m_Creature.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 502799, + m_Tamer.NetState + ); // It seems to accept you as master. + m_Creature.Owners.Add(m_Tamer); + } + + m_Creature.SetControlMaster(m_Tamer); + m_Creature.IsBonded = false; + } + else + { + m_Creature.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 502798, + m_Tamer.NetState + ); // You fail to tame the creature. + } + } + } + + private bool CanPath() + { + IPoint3D p = m_Tamer; + + return p != null && (m_Creature.InRange(new Point3D(p), 1) || + new MovementPath(m_Creature, new Point3D(p)).Success); + } } - else - { - m_Creature.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 502798, - m_Tamer.NetState); // You fail to tame the creature. - } - } } - - private bool CanPath() - { - IPoint3D p = m_Tamer; - - return p != null && (m_Creature.InRange(new Point3D(p), 1) || - new MovementPath(m_Creature, new Point3D(p)).Success); - } - } } - } } diff --git a/Projects/UOContent/Skills/ArmsLore.cs b/Projects/UOContent/Skills/ArmsLore.cs index 92cd8baf9..13b9fb583 100644 --- a/Projects/UOContent/Skills/ArmsLore.cs +++ b/Projects/UOContent/Skills/ArmsLore.cs @@ -6,110 +6,110 @@ using Server.Targeting; namespace Server.SkillHandlers { - public static class ArmsLore - { - public static void Initialize() + public static class ArmsLore { - SkillInfo.Table[(int)SkillName.ArmsLore].Callback = OnUse; - } - - public static TimeSpan OnUse(Mobile m) - { - m.Target = new InternalTarget(); - - m.SendLocalizedMessage(500349); // What item do you wish to get information about? - - return TimeSpan.FromSeconds(1.0); - } - - [PlayerVendorTarget] - private class InternalTarget : Target - { - public InternalTarget() : base(2, false, TargetFlags.None) => AllowNonlocal = true; - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is BaseWeapon weap) + public static void Initialize() { - if (from.CheckTargetSkill(SkillName.ArmsLore, weap, 0, 100)) - { - if (weap.MaxHitPoints != 0) + SkillInfo.Table[(int)SkillName.ArmsLore].Callback = OnUse; + } + + public static TimeSpan OnUse(Mobile m) + { + m.Target = new InternalTarget(); + + m.SendLocalizedMessage(500349); // What item do you wish to get information about? + + return TimeSpan.FromSeconds(1.0); + } + + [PlayerVendorTarget] + private class InternalTarget : Target + { + public InternalTarget() : base(2, false, TargetFlags.None) => AllowNonlocal = true; + + protected override void OnTarget(Mobile from, object targeted) { - int hp = Math.Clamp((int)(weap.HitPoints / (double)weap.MaxHitPoints * 10), 0, 9); + if (targeted is BaseWeapon weap) + { + if (from.CheckTargetSkill(SkillName.ArmsLore, weap, 0, 100)) + { + if (weap.MaxHitPoints != 0) + { + var hp = Math.Clamp((int)(weap.HitPoints / (double)weap.MaxHitPoints * 10), 0, 9); - from.SendLocalizedMessage(1038285 + hp); + from.SendLocalizedMessage(1038285 + hp); + } + + var damage = (weap.MaxDamage + weap.MinDamage) / 2; + var hand = weap.Layer == Layer.OneHanded ? 0 : 1; + + if (damage < 3) + damage = 0; + else + damage = (int)Math.Ceiling(Math.Min(damage, 30) / 5.0); + + var type = weap.Type; + + if (type == WeaponType.Ranged) + from.SendLocalizedMessage(1038224 + damage * 9); + else if (type == WeaponType.Piercing) + from.SendLocalizedMessage(1038218 + hand + damage * 9); + else if (type == WeaponType.Slashing) + from.SendLocalizedMessage(1038220 + hand + damage * 9); + else if (type == WeaponType.Bashing) + from.SendLocalizedMessage(1038222 + hand + damage * 9); + else + from.SendLocalizedMessage(1038216 + hand + damage * 9); + + if (weap.Poison != null && weap.PoisonCharges > 0) + from.SendLocalizedMessage(1038284); // It appears to have poison smeared on it. + } + else + { + from.SendLocalizedMessage(500353); // You are not certain... + } + } + else if (targeted is BaseArmor arm) + { + if (from.CheckTargetSkill(SkillName.ArmsLore, arm, 0, 100)) + { + if (arm.MaxHitPoints != 0) + { + var hp = Math.Clamp((int)(arm.HitPoints / (double)arm.MaxHitPoints * 10), 0, 9); + + from.SendLocalizedMessage(1038285 + hp); + } + + from.SendLocalizedMessage(1038295 + (int)Math.Ceiling(Math.Min(arm.ArmorRating, 35) / 5.0)); + } + else + { + from.SendLocalizedMessage(500353); // You are not certain... + } + } + else if (targeted is SwampDragon pet && pet.HasBarding) + { + if (from.CheckTargetSkill(SkillName.ArmsLore, pet, 0, 100)) + { + var perc = 4 * pet.BardingHP / pet.BardingMaxHP; + + if (perc < 0) + perc = 0; + else if (perc > 4) + perc = 4; + + pet.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1053021 - perc, from.NetState); + } + else + { + from.SendLocalizedMessage(500353); // You are not certain... + } + } + else + { + from.SendLocalizedMessage(500352); // This is neither weapon nor armor. + } } - - int damage = (weap.MaxDamage + weap.MinDamage) / 2; - int hand = weap.Layer == Layer.OneHanded ? 0 : 1; - - if (damage < 3) - damage = 0; - else - damage = (int)Math.Ceiling(Math.Min(damage, 30) / 5.0); - - WeaponType type = weap.Type; - - if (type == WeaponType.Ranged) - from.SendLocalizedMessage(1038224 + damage * 9); - else if (type == WeaponType.Piercing) - from.SendLocalizedMessage(1038218 + hand + damage * 9); - else if (type == WeaponType.Slashing) - from.SendLocalizedMessage(1038220 + hand + damage * 9); - else if (type == WeaponType.Bashing) - from.SendLocalizedMessage(1038222 + hand + damage * 9); - else - from.SendLocalizedMessage(1038216 + hand + damage * 9); - - if (weap.Poison != null && weap.PoisonCharges > 0) - from.SendLocalizedMessage(1038284); // It appears to have poison smeared on it. - } - else - { - from.SendLocalizedMessage(500353); // You are not certain... - } } - else if (targeted is BaseArmor arm) - { - if (from.CheckTargetSkill(SkillName.ArmsLore, arm, 0, 100)) - { - if (arm.MaxHitPoints != 0) - { - int hp = Math.Clamp((int)(arm.HitPoints / (double)arm.MaxHitPoints * 10), 0, 9); - - from.SendLocalizedMessage(1038285 + hp); - } - - from.SendLocalizedMessage(1038295 + (int)Math.Ceiling(Math.Min(arm.ArmorRating, 35) / 5.0)); - } - else - { - from.SendLocalizedMessage(500353); // You are not certain... - } - } - else if (targeted is SwampDragon pet && pet.HasBarding) - { - if (from.CheckTargetSkill(SkillName.ArmsLore, pet, 0, 100)) - { - int perc = 4 * pet.BardingHP / pet.BardingMaxHP; - - if (perc < 0) - perc = 0; - else if (perc > 4) - perc = 4; - - pet.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1053021 - perc, from.NetState); - } - else - { - from.SendLocalizedMessage(500353); // You are not certain... - } - } - else - { - from.SendLocalizedMessage(500352); // This is neither weapon nor armor. - } - } } - } } diff --git a/Projects/UOContent/Skills/Begging.cs b/Projects/UOContent/Skills/Begging.cs index 5a4714307..eb63b2af3 100644 --- a/Projects/UOContent/Skills/Begging.cs +++ b/Projects/UOContent/Skills/Begging.cs @@ -6,172 +6,185 @@ using Server.Targeting; namespace Server.SkillHandlers { - public static class Begging - { - public static void Initialize() + public static class Begging { - SkillInfo.Table[(int)SkillName.Begging].Callback = OnUse; - } - - public static TimeSpan OnUse(Mobile m) - { - m.RevealingAction(); - - m.Target = new InternalTarget(); - m.RevealingAction(); - - m.SendLocalizedMessage(500397); // To whom do you wish to grovel? - - return TimeSpan.FromHours(6.0); - } - - private class InternalTarget : Target - { - private bool m_SetSkillTime = true; - - public InternalTarget() : base(12, false, TargetFlags.None) - { - } - - protected override void OnTargetFinish(Mobile from) - { - if (m_SetSkillTime) - from.NextSkillTime = Core.TickCount; - } - - protected override void OnTarget(Mobile from, object targeted) - { - from.RevealingAction(); - - int number = -1; - - if (targeted is Mobile targ) + public static void Initialize() { - if (targ.Player) // We can't beg from players - { - number = 500398; // Perhaps just asking would work better. - } - else if (!targ.Body.IsHuman) // Make sure the NPC is human - { - number = 500399; // There is little chance of getting money from that! - } - else if (!from.InRange(targ, 2)) - { - if (!targ.Female) - number = 500401; // You are too far away to beg from him. - else - number = 500402; // You are too far away to beg from her. - } - else if (!Core.ML && from.Mounted) // If we're on a mount, who would give us money? TODO: guessed it's removed since ML - { - number = 500404; // They seem unwilling to give you any money. - } - else - { - // Face each other - from.Direction = from.GetDirectionTo(targ); - targ.Direction = targ.GetDirectionTo(from); - - from.Animate(32, 5, 1, true, false, 0); // Bow - - new InternalTimer(from, targ).Start(); - - m_SetSkillTime = false; - } - } - else // Not a Mobile - { - number = 500399; // There is little chance of getting money from that! + SkillInfo.Table[(int)SkillName.Begging].Callback = OnUse; } - if (number != -1) - from.SendLocalizedMessage(number); - } - - private class InternalTimer : Timer - { - private readonly Mobile m_From; - private readonly Mobile m_Target; - - public InternalTimer(Mobile from, Mobile target) : base(TimeSpan.FromSeconds(2.0)) + public static TimeSpan OnUse(Mobile m) { - m_From = from; - m_Target = target; - Priority = TimerPriority.TwoFiftyMS; + m.RevealingAction(); + + m.Target = new InternalTarget(); + m.RevealingAction(); + + m.SendLocalizedMessage(500397); // To whom do you wish to grovel? + + return TimeSpan.FromHours(6.0); } - protected override void OnTick() + private class InternalTarget : Target { - Container theirPack = m_Target.Backpack; + private bool m_SetSkillTime = true; - double badKarmaChance = 0.5 - (double)m_From.Karma / 8570; - - if (theirPack == null) - { - m_From.SendLocalizedMessage(500404); // They seem unwilling to give you any money. - } - else if (m_From.Karma < 0 && badKarmaChance > Utility.RandomDouble()) - { - m_Target.PublicOverheadMessage(MessageType.Regular, m_Target.SpeechHue, - 500406); // Thou dost not look trustworthy... no gold for thee today! - } - else if (m_From.CheckTargetSkill(SkillName.Begging, m_Target, 0.0, 100.0)) - { - int toConsume = theirPack.GetAmount(typeof(Gold)) / 10; - int max = 10 + m_From.Fame / 2500; - - if (max > 14) - max = 14; - else if (max < 10) - max = 10; - - if (toConsume > max) - toConsume = max; - - if (toConsume > 0) + public InternalTarget() : base(12, false, TargetFlags.None) { - int consumed = theirPack.ConsumeUpTo(typeof(Gold), toConsume); + } - if (consumed > 0) - { - m_Target.PublicOverheadMessage(MessageType.Regular, m_Target.SpeechHue, - 500405); // I feel sorry for thee... + protected override void OnTargetFinish(Mobile from) + { + if (m_SetSkillTime) + from.NextSkillTime = Core.TickCount; + } - Gold gold = new Gold(consumed); + protected override void OnTarget(Mobile from, object targeted) + { + from.RevealingAction(); - m_From.AddToBackpack(gold); - m_From.PlaySound(gold.GetDropSound()); + var number = -1; - if (m_From.Karma > -3000) + if (targeted is Mobile targ) { - int toLose = m_From.Karma + 3000; + if (targ.Player) // We can't beg from players + { + number = 500398; // Perhaps just asking would work better. + } + else if (!targ.Body.IsHuman) // Make sure the NPC is human + { + number = 500399; // There is little chance of getting money from that! + } + else if (!from.InRange(targ, 2)) + { + if (!targ.Female) + number = 500401; // You are too far away to beg from him. + else + number = 500402; // You are too far away to beg from her. + } + else if (!Core.ML && from.Mounted + ) // If we're on a mount, who would give us money? TODO: guessed it's removed since ML + { + number = 500404; // They seem unwilling to give you any money. + } + else + { + // Face each other + from.Direction = from.GetDirectionTo(targ); + targ.Direction = targ.GetDirectionTo(from); - if (toLose > 40) - toLose = 40; + from.Animate(32, 5, 1, true, false, 0); // Bow - Titles.AwardKarma(m_From, -toLose, true); + new InternalTimer(from, targ).Start(); + + m_SetSkillTime = false; + } + } + else // Not a Mobile + { + number = 500399; // There is little chance of getting money from that! } - } - else - { - m_Target.PublicOverheadMessage(MessageType.Regular, m_Target.SpeechHue, - 500407); // I have not enough money to give thee any! - } - } - else - { - m_Target.PublicOverheadMessage(MessageType.Regular, m_Target.SpeechHue, - 500407); // I have not enough money to give thee any! - } - } - else - { - m_Target.SendLocalizedMessage(500404); // They seem unwilling to give you any money. - } - m_From.NextSkillTime = Core.TickCount + 10000; + if (number != -1) + from.SendLocalizedMessage(number); + } + + private class InternalTimer : Timer + { + private readonly Mobile m_From; + private readonly Mobile m_Target; + + public InternalTimer(Mobile from, Mobile target) : base(TimeSpan.FromSeconds(2.0)) + { + m_From = from; + m_Target = target; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + var theirPack = m_Target.Backpack; + + var badKarmaChance = 0.5 - (double)m_From.Karma / 8570; + + if (theirPack == null) + { + m_From.SendLocalizedMessage(500404); // They seem unwilling to give you any money. + } + else if (m_From.Karma < 0 && badKarmaChance > Utility.RandomDouble()) + { + m_Target.PublicOverheadMessage( + MessageType.Regular, + m_Target.SpeechHue, + 500406 + ); // Thou dost not look trustworthy... no gold for thee today! + } + else if (m_From.CheckTargetSkill(SkillName.Begging, m_Target, 0.0, 100.0)) + { + var toConsume = theirPack.GetAmount(typeof(Gold)) / 10; + var max = 10 + m_From.Fame / 2500; + + if (max > 14) + max = 14; + else if (max < 10) + max = 10; + + if (toConsume > max) + toConsume = max; + + if (toConsume > 0) + { + var consumed = theirPack.ConsumeUpTo(typeof(Gold), toConsume); + + if (consumed > 0) + { + m_Target.PublicOverheadMessage( + MessageType.Regular, + m_Target.SpeechHue, + 500405 + ); // I feel sorry for thee... + + var gold = new Gold(consumed); + + m_From.AddToBackpack(gold); + m_From.PlaySound(gold.GetDropSound()); + + if (m_From.Karma > -3000) + { + var toLose = m_From.Karma + 3000; + + if (toLose > 40) + toLose = 40; + + Titles.AwardKarma(m_From, -toLose, true); + } + } + else + { + m_Target.PublicOverheadMessage( + MessageType.Regular, + m_Target.SpeechHue, + 500407 + ); // I have not enough money to give thee any! + } + } + else + { + m_Target.PublicOverheadMessage( + MessageType.Regular, + m_Target.SpeechHue, + 500407 + ); // I have not enough money to give thee any! + } + } + else + { + m_Target.SendLocalizedMessage(500404); // They seem unwilling to give you any money. + } + + m_From.NextSkillTime = Core.TickCount + 10000; + } + } } - } } - } } diff --git a/Projects/UOContent/Skills/DetectHidden.cs b/Projects/UOContent/Skills/DetectHidden.cs index 907e582ae..2227f295c 100644 --- a/Projects/UOContent/Skills/DetectHidden.cs +++ b/Projects/UOContent/Skills/DetectHidden.cs @@ -6,99 +6,102 @@ using Server.Targeting; namespace Server.SkillHandlers { - public static class DetectHidden - { - public static void Initialize() + public static class DetectHidden { - SkillInfo.Table[(int)SkillName.DetectHidden].Callback = OnUse; - } - - public static TimeSpan OnUse(Mobile src) - { - src.SendLocalizedMessage(500819); // Where will you search? - src.Target = new InternalTarget(); - - return TimeSpan.FromSeconds(6.0); - } - - private class InternalTarget : Target - { - public InternalTarget() : base(12, true, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile src, object targ) - { - bool foundAnyone = false; - - Point3D p; - if (targ is Mobile mobile) - p = mobile.Location; - else if (targ is Item item) - p = item.Location; - else if (targ is IPoint3D d) - p = new Point3D(d); - else - p = src.Location; - - double srcSkill = src.Skills.DetectHidden.Value; - int range = (int)(srcSkill / 10.0); - - if (!src.CheckSkill(SkillName.DetectHidden, 0.0, 100.0)) - range /= 2; - - BaseHouse house = BaseHouse.FindHouseAt(p, src.Map, 16); - - bool inHouse = house?.IsFriend(src) == true; - - if (inHouse) - range = 22; - - if (range > 0) + public static void Initialize() { - IPooledEnumerable inRange = src.Map.GetMobilesInRange(p, range); - - foreach (Mobile trg in inRange) - if (trg.Hidden && src != trg) - { - double ss = srcSkill + Utility.Random(21) - 10; - double ts = trg.Skills.Hiding.Value + Utility.Random(21) - 10; - - if (src.AccessLevel >= trg.AccessLevel && (ss >= ts || (inHouse && house.IsInside(trg)))) - { - if (trg is ShadowKnight && (trg.X != p.X || trg.Y != p.Y)) - continue; - - trg.RevealingAction(); - trg.SendLocalizedMessage(500814); // You have been revealed! - foundAnyone = true; - } - } - - inRange.Free(); - - if (Faction.Find(src) != null) - { - IPooledEnumerable itemsInRange = src.Map.GetItemsInRange(p, range); - - foreach (BaseFactionTrap trap in itemsInRange) - if (src.CheckTargetSkill(SkillName.DetectHidden, trap, 80.0, 100.0)) - { - src.SendLocalizedMessage(1042712, true, - $" {(trap.Faction == null ? "" : trap.Faction.Definition.FriendlyName)}"); // You reveal a trap placed by a faction: - - trap.Visible = true; - trap.BeginConceal(); - - foundAnyone = true; - } - - itemsInRange.Free(); - } + SkillInfo.Table[(int)SkillName.DetectHidden].Callback = OnUse; } - if (!foundAnyone) src.SendLocalizedMessage(500817); // You can see nothing hidden there. - } + public static TimeSpan OnUse(Mobile src) + { + src.SendLocalizedMessage(500819); // Where will you search? + src.Target = new InternalTarget(); + + return TimeSpan.FromSeconds(6.0); + } + + private class InternalTarget : Target + { + public InternalTarget() : base(12, true, TargetFlags.None) + { + } + + protected override void OnTarget(Mobile src, object targ) + { + var foundAnyone = false; + + Point3D p; + if (targ is Mobile mobile) + p = mobile.Location; + else if (targ is Item item) + p = item.Location; + else if (targ is IPoint3D d) + p = new Point3D(d); + else + p = src.Location; + + var srcSkill = src.Skills.DetectHidden.Value; + var range = (int)(srcSkill / 10.0); + + if (!src.CheckSkill(SkillName.DetectHidden, 0.0, 100.0)) + range /= 2; + + var house = BaseHouse.FindHouseAt(p, src.Map, 16); + + var inHouse = house?.IsFriend(src) == true; + + if (inHouse) + range = 22; + + if (range > 0) + { + var inRange = src.Map.GetMobilesInRange(p, range); + + foreach (var trg in inRange) + if (trg.Hidden && src != trg) + { + var ss = srcSkill + Utility.Random(21) - 10; + var ts = trg.Skills.Hiding.Value + Utility.Random(21) - 10; + + if (src.AccessLevel >= trg.AccessLevel && (ss >= ts || inHouse && house.IsInside(trg))) + { + if (trg is ShadowKnight && (trg.X != p.X || trg.Y != p.Y)) + continue; + + trg.RevealingAction(); + trg.SendLocalizedMessage(500814); // You have been revealed! + foundAnyone = true; + } + } + + inRange.Free(); + + if (Faction.Find(src) != null) + { + var itemsInRange = src.Map.GetItemsInRange(p, range); + + foreach (var trap in itemsInRange) + if (src.CheckTargetSkill(SkillName.DetectHidden, trap, 80.0, 100.0)) + { + src.SendLocalizedMessage( + 1042712, + true, + $" {(trap.Faction == null ? "" : trap.Faction.Definition.FriendlyName)}" + ); // You reveal a trap placed by a faction: + + trap.Visible = true; + trap.BeginConceal(); + + foundAnyone = true; + } + + itemsInRange.Free(); + } + } + + if (!foundAnyone) src.SendLocalizedMessage(500817); // You can see nothing hidden there. + } + } } - } } diff --git a/Projects/UOContent/Skills/Discordance.cs b/Projects/UOContent/Skills/Discordance.cs index 4cf97798b..82b555dfa 100644 --- a/Projects/UOContent/Skills/Discordance.cs +++ b/Projects/UOContent/Skills/Discordance.cs @@ -6,259 +6,285 @@ using Server.Targeting; namespace Server.SkillHandlers { - public static class Discordance - { - private static readonly Dictionary m_Table = new Dictionary(); - - public static void Initialize() + public static class Discordance { - SkillInfo.Table[(int)SkillName.Discordance].Callback = OnUse; - } + private static readonly Dictionary m_Table = new Dictionary(); - public static TimeSpan OnUse(Mobile m) - { - m.RevealingAction(); - - BaseInstrument.PickInstrument(m, OnPickedInstrument); - - return TimeSpan.FromSeconds(1.0); // Cannot use another skill for 1 second - } - - public static void OnPickedInstrument(Mobile from, BaseInstrument instrument) - { - from.RevealingAction(); - from.SendLocalizedMessage(1049541); // Choose the target for your song of discordance. - from.Target = new DiscordanceTarget(from, instrument); - from.NextSkillTime = Core.TickCount + 6000; - } - - public static bool GetEffect(Mobile targ, ref int effect) - { - if (!m_Table.TryGetValue(targ, out DiscordanceInfo info)) - return false; - - effect = info.m_Effect; - return true; - } - - private static void ProcessDiscordance(DiscordanceInfo info) - { - Mobile from = info.m_From; - Mobile targ = info.m_Creature; - bool ends = false; - - // According to uoherald bard must remain alive, visible, and - // within range of the target or the effect ends in 15 seconds. - if (!targ.Alive || targ.Deleted || !from.Alive || from.Hidden) - { - ends = true; - } - else - { - int range = (int)targ.GetDistanceToSqrt(from); - int maxRange = BaseInstrument.GetBardRange(from, SkillName.Discordance); - - if (from.Map != targ.Map || range > maxRange) - ends = true; - } - - if (ends && info.m_Ending && info.m_EndTime < DateTime.UtcNow) - { - info.m_Timer?.Stop(); - - info.Clear(); - m_Table.Remove(targ); - } - else - { - if (ends && !info.m_Ending) + public static void Initialize() { - info.m_Ending = true; - info.m_EndTime = DateTime.UtcNow + TimeSpan.FromSeconds(15); - } - else if (!ends) - { - info.m_Ending = false; - info.m_EndTime = DateTime.UtcNow; + SkillInfo.Table[(int)SkillName.Discordance].Callback = OnUse; } - targ.FixedEffect(0x376A, 1, 32); - } - } - - private class DiscordanceInfo - { - public readonly Mobile m_Creature; - public readonly int m_Effect; - public bool m_Ending; - public DateTime m_EndTime; - public readonly Mobile m_From; - public readonly List m_Mods; - public Timer m_Timer; - - public DiscordanceInfo(Mobile from, Mobile creature, int effect, List mods) - { - m_From = from; - m_Creature = creature; - m_EndTime = DateTime.UtcNow; - m_Ending = false; - m_Effect = effect; - m_Mods = mods; - - Apply(); - } - - public void Apply() - { - for (int i = 0; i < m_Mods.Count; ++i) + public static TimeSpan OnUse(Mobile m) { - object mod = m_Mods[i]; + m.RevealingAction(); - if (mod is ResistanceMod resistanceMod) - m_Creature.AddResistanceMod(resistanceMod); - else if (mod is StatMod statMod) - m_Creature.AddStatMod(statMod); - else if (mod is SkillMod skillMod) - m_Creature.AddSkillMod(skillMod); + BaseInstrument.PickInstrument(m, OnPickedInstrument); + + return TimeSpan.FromSeconds(1.0); // Cannot use another skill for 1 second } - } - public void Clear() - { - for (int i = 0; i < m_Mods.Count; ++i) + public static void OnPickedInstrument(Mobile from, BaseInstrument instrument) { - object mod = m_Mods[i]; - - if (mod is ResistanceMod resistanceMod) - m_Creature.RemoveResistanceMod(resistanceMod); - else if (mod is StatMod statMod) - m_Creature.RemoveStatMod(statMod.Name); - else if (mod is SkillMod skillMod) - m_Creature.RemoveSkillMod(skillMod); + from.RevealingAction(); + from.SendLocalizedMessage(1049541); // Choose the target for your song of discordance. + from.Target = new DiscordanceTarget(from, instrument); + from.NextSkillTime = Core.TickCount + 6000; } - } - } - public class DiscordanceTarget : Target - { - private readonly BaseInstrument m_Instrument; - - public DiscordanceTarget(Mobile from, BaseInstrument inst) : base( - BaseInstrument.GetBardRange(from, SkillName.Discordance), false, TargetFlags.None) => - m_Instrument = inst; - - protected override void OnTarget(Mobile from, object target) - { - from.RevealingAction(); - from.NextSkillTime = Core.TickCount + 1000; - - if (!m_Instrument.IsChildOf(from.Backpack)) + public static bool GetEffect(Mobile targ, ref int effect) { - from.SendLocalizedMessage( - 1062488); // The instrument you are trying to play is no longer in your backpack! + if (!m_Table.TryGetValue(targ, out var info)) + return false; + + effect = info.m_Effect; + return true; } - else if (target is Mobile targ) + + private static void ProcessDiscordance(DiscordanceInfo info) { - if (targ == from || (targ is BaseCreature bc && - (bc.BardImmune || !from.CanBeHarmful(bc, false)) && - bc.ControlMaster != from)) - { - from.SendLocalizedMessage(1049535); // A song of discord would have no effect on that. - } - else if (m_Table.ContainsKey(targ)) // Already discorded - { - from.SendLocalizedMessage(1049537); // Your target is already in discord. - } - else if (!targ.Player) - { - double diff = m_Instrument.GetDifficultyFor(targ) - 10.0; - double music = from.Skills.Musicianship.Value; + var from = info.m_From; + var targ = info.m_Creature; + var ends = false; - if (music > 100.0) - diff -= (music - 100.0) * 0.5; - - if (!BaseInstrument.CheckMusicianship(from)) + // According to uoherald bard must remain alive, visible, and + // within range of the target or the effect ends in 15 seconds. + if (!targ.Alive || targ.Deleted || !from.Alive || from.Hidden) { - from.SendLocalizedMessage(500612); // You play poorly, and there is no effect. - m_Instrument.PlayInstrumentBadly(from); - m_Instrument.ConsumeUse(from); - } - else if (from.CheckTargetSkill(SkillName.Discordance, targ, diff - 25.0, diff + 25.0)) - { - from.SendLocalizedMessage(1049539); // You play the song surpressing your targets strength - m_Instrument.PlayInstrumentWell(from); - m_Instrument.ConsumeUse(from); - - List mods = new List(); - int effect; - double scalar; - - if (Core.AOS) - { - double discord = from.Skills.Discordance.Value; - - if (discord > 100.0) - effect = -20 + (int)((discord - 100.0) / -2.5); - else - effect = (int)(discord / -5.0); - - if (Core.SE && BaseInstrument.GetBaseDifficulty(targ) >= 160.0) - effect /= 2; - - scalar = effect * 0.01; - - mods.Add(new ResistanceMod(ResistanceType.Physical, effect)); - mods.Add(new ResistanceMod(ResistanceType.Fire, effect)); - mods.Add(new ResistanceMod(ResistanceType.Cold, effect)); - mods.Add(new ResistanceMod(ResistanceType.Poison, effect)); - mods.Add(new ResistanceMod(ResistanceType.Energy, effect)); - - for (int i = 0; i < targ.Skills.Length; ++i) - if (targ.Skills[i].Value > 0) - mods.Add(new DefaultSkillMod((SkillName)i, true, targ.Skills[i].Value * scalar)); - } - else - { - effect = (int)(from.Skills.Discordance.Value / -5.0); - scalar = effect * 0.01; - - mods.Add(new StatMod(StatType.Str, "DiscordanceStr", (int)(targ.RawStr * scalar), - TimeSpan.Zero)); - mods.Add(new StatMod(StatType.Int, "DiscordanceInt", (int)(targ.RawInt * scalar), - TimeSpan.Zero)); - mods.Add(new StatMod(StatType.Dex, "DiscordanceDex", (int)(targ.RawDex * scalar), - TimeSpan.Zero)); - - for (int i = 0; i < targ.Skills.Length; ++i) - if (targ.Skills[i].Value > 0) - mods.Add(new DefaultSkillMod((SkillName)i, true, targ.Skills[i].Value * scalar)); - } - - DiscordanceInfo info = new DiscordanceInfo(from, targ, Math.Abs(effect), mods); - info.m_Timer = Timer.DelayCall(TimeSpan.Zero, TimeSpan.FromSeconds(1.25), ProcessDiscordance, - info); - - m_Table[targ] = info; + ends = true; } else { - from.SendLocalizedMessage(1049540); // You fail to disrupt your target - m_Instrument.PlayInstrumentBadly(from); - m_Instrument.ConsumeUse(from); + var range = (int)targ.GetDistanceToSqrt(from); + var maxRange = BaseInstrument.GetBardRange(from, SkillName.Discordance); + + if (from.Map != targ.Map || range > maxRange) + ends = true; } - from.NextSkillTime = Core.TickCount + 12000; - } - else - { - m_Instrument.PlayInstrumentBadly(from); - } + if (ends && info.m_Ending && info.m_EndTime < DateTime.UtcNow) + { + info.m_Timer?.Stop(); + + info.Clear(); + m_Table.Remove(targ); + } + else + { + if (ends && !info.m_Ending) + { + info.m_Ending = true; + info.m_EndTime = DateTime.UtcNow + TimeSpan.FromSeconds(15); + } + else if (!ends) + { + info.m_Ending = false; + info.m_EndTime = DateTime.UtcNow; + } + + targ.FixedEffect(0x376A, 1, 32); + } } - else + + private class DiscordanceInfo { - from.SendLocalizedMessage(1049535); // A song of discord would have no effect on that. + public readonly Mobile m_Creature; + public readonly int m_Effect; + public readonly Mobile m_From; + public readonly List m_Mods; + public bool m_Ending; + public DateTime m_EndTime; + public Timer m_Timer; + + public DiscordanceInfo(Mobile from, Mobile creature, int effect, List mods) + { + m_From = from; + m_Creature = creature; + m_EndTime = DateTime.UtcNow; + m_Ending = false; + m_Effect = effect; + m_Mods = mods; + + Apply(); + } + + public void Apply() + { + for (var i = 0; i < m_Mods.Count; ++i) + { + var mod = m_Mods[i]; + + if (mod is ResistanceMod resistanceMod) + m_Creature.AddResistanceMod(resistanceMod); + else if (mod is StatMod statMod) + m_Creature.AddStatMod(statMod); + else if (mod is SkillMod skillMod) + m_Creature.AddSkillMod(skillMod); + } + } + + public void Clear() + { + for (var i = 0; i < m_Mods.Count; ++i) + { + var mod = m_Mods[i]; + + if (mod is ResistanceMod resistanceMod) + m_Creature.RemoveResistanceMod(resistanceMod); + else if (mod is StatMod statMod) + m_Creature.RemoveStatMod(statMod.Name); + else if (mod is SkillMod skillMod) + m_Creature.RemoveSkillMod(skillMod); + } + } + } + + public class DiscordanceTarget : Target + { + private readonly BaseInstrument m_Instrument; + + public DiscordanceTarget(Mobile from, BaseInstrument inst) : base( + BaseInstrument.GetBardRange(from, SkillName.Discordance), + false, + TargetFlags.None + ) => + m_Instrument = inst; + + protected override void OnTarget(Mobile from, object target) + { + from.RevealingAction(); + from.NextSkillTime = Core.TickCount + 1000; + + if (!m_Instrument.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage( + 1062488 + ); // The instrument you are trying to play is no longer in your backpack! + } + else if (target is Mobile targ) + { + if (targ == from || targ is BaseCreature bc && + (bc.BardImmune || !@from.CanBeHarmful(bc, false)) && + bc.ControlMaster != @from) + { + from.SendLocalizedMessage(1049535); // A song of discord would have no effect on that. + } + else if (m_Table.ContainsKey(targ)) // Already discorded + { + from.SendLocalizedMessage(1049537); // Your target is already in discord. + } + else if (!targ.Player) + { + var diff = m_Instrument.GetDifficultyFor(targ) - 10.0; + var music = from.Skills.Musicianship.Value; + + if (music > 100.0) + diff -= (music - 100.0) * 0.5; + + if (!BaseInstrument.CheckMusicianship(from)) + { + from.SendLocalizedMessage(500612); // You play poorly, and there is no effect. + m_Instrument.PlayInstrumentBadly(from); + m_Instrument.ConsumeUse(from); + } + else if (from.CheckTargetSkill(SkillName.Discordance, targ, diff - 25.0, diff + 25.0)) + { + from.SendLocalizedMessage(1049539); // You play the song surpressing your targets strength + m_Instrument.PlayInstrumentWell(from); + m_Instrument.ConsumeUse(from); + + var mods = new List(); + int effect; + double scalar; + + if (Core.AOS) + { + var discord = from.Skills.Discordance.Value; + + if (discord > 100.0) + effect = -20 + (int)((discord - 100.0) / -2.5); + else + effect = (int)(discord / -5.0); + + if (Core.SE && BaseInstrument.GetBaseDifficulty(targ) >= 160.0) + effect /= 2; + + scalar = effect * 0.01; + + mods.Add(new ResistanceMod(ResistanceType.Physical, effect)); + mods.Add(new ResistanceMod(ResistanceType.Fire, effect)); + mods.Add(new ResistanceMod(ResistanceType.Cold, effect)); + mods.Add(new ResistanceMod(ResistanceType.Poison, effect)); + mods.Add(new ResistanceMod(ResistanceType.Energy, effect)); + + for (var i = 0; i < targ.Skills.Length; ++i) + if (targ.Skills[i].Value > 0) + mods.Add(new DefaultSkillMod((SkillName)i, true, targ.Skills[i].Value * scalar)); + } + else + { + effect = (int)(from.Skills.Discordance.Value / -5.0); + scalar = effect * 0.01; + + mods.Add( + new StatMod( + StatType.Str, + "DiscordanceStr", + (int)(targ.RawStr * scalar), + TimeSpan.Zero + ) + ); + mods.Add( + new StatMod( + StatType.Int, + "DiscordanceInt", + (int)(targ.RawInt * scalar), + TimeSpan.Zero + ) + ); + mods.Add( + new StatMod( + StatType.Dex, + "DiscordanceDex", + (int)(targ.RawDex * scalar), + TimeSpan.Zero + ) + ); + + for (var i = 0; i < targ.Skills.Length; ++i) + if (targ.Skills[i].Value > 0) + mods.Add(new DefaultSkillMod((SkillName)i, true, targ.Skills[i].Value * scalar)); + } + + var info = new DiscordanceInfo(from, targ, Math.Abs(effect), mods); + info.m_Timer = Timer.DelayCall( + TimeSpan.Zero, + TimeSpan.FromSeconds(1.25), + ProcessDiscordance, + info + ); + + m_Table[targ] = info; + } + else + { + from.SendLocalizedMessage(1049540); // You fail to disrupt your target + m_Instrument.PlayInstrumentBadly(from); + m_Instrument.ConsumeUse(from); + } + + from.NextSkillTime = Core.TickCount + 12000; + } + else + { + m_Instrument.PlayInstrumentBadly(from); + } + } + else + { + from.SendLocalizedMessage(1049535); // A song of discord would have no effect on that. + } + } } - } } - } } diff --git a/Projects/UOContent/Skills/EvalInt.cs b/Projects/UOContent/Skills/EvalInt.cs index 4d05ee59f..2f80ce09a 100644 --- a/Projects/UOContent/Skills/EvalInt.cs +++ b/Projects/UOContent/Skills/EvalInt.cs @@ -5,83 +5,106 @@ using Server.Targeting; namespace Server.SkillHandlers { - public static class EvalInt - { - public static void Initialize() + public static class EvalInt { - SkillInfo.Table[16].Callback = OnUse; + public static void Initialize() + { + SkillInfo.Table[16].Callback = OnUse; + } + + public static TimeSpan OnUse(Mobile m) + { + m.Target = new InternalTarget(); + + m.SendLocalizedMessage(500906); // What do you wish to evaluate? + + return TimeSpan.FromSeconds(1.0); + } + + private class InternalTarget : Target + { + public InternalTarget() : base(8, false, TargetFlags.None) + { + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (from == targeted) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500910); // Hmm, that person looks really silly. + } + else if (targeted is TownCrier crier) + { + crier.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 500907, + from.NetState + ); // He looks smart enough to remember the news. Ask him about it. + } + else if (targeted is BaseVendor vendor && vendor.IsInvulnerable) + { + vendor.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 500909, + from.NetState + ); // That person could probably calculate the cost of what you buy from them. + } + else if (targeted is Mobile targ) + { + var marginOfError = Math.Max(0, 20 - (int)(from.Skills.EvalInt.Value / 5)); + + var intel = targ.Int + Utility.RandomMinMax(-marginOfError, +marginOfError); + var mana = targ.Mana * 100 / Math.Max(targ.ManaMax, 1) + + Utility.RandomMinMax(-marginOfError, +marginOfError); + + var intMod = Math.Clamp(intel / 10, 0, 10); + var mnMod = Math.Clamp(mana / 10, 0, 10); + + int body; + + if (targ.Body.IsHuman) + body = targ.Female ? 11 : 0; + else + body = 22; + + if (from.CheckTargetSkill(SkillName.EvalInt, targ, 0.0, 120.0)) + { + targ.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 1038169 + intMod + body, + from.NetState + ); // He/She/It looks [slighly less intelligent than a rock.] [Of Average intellect] [etc...] + + if (from.Skills.EvalInt.Base >= 76.0) + targ.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 1038202 + mnMod, + from.NetState + ); // That being is at [10,20,...] percent mental strength. + } + else + { + targ.PrivateOverheadMessage( + MessageType.Regular, + 0x3B2, + 1038166 + body / 11, + from.NetState + ); // You cannot judge his/her/its mental abilities. + } + } + else + { + (targeted as Item)?.SendLocalizedMessageTo( + from, + 500908, + "" + ); // It looks smarter than a rock, but dumber than a piece of wood. + } + } + } } - - public static TimeSpan OnUse(Mobile m) - { - m.Target = new InternalTarget(); - - m.SendLocalizedMessage(500906); // What do you wish to evaluate? - - return TimeSpan.FromSeconds(1.0); - } - - private class InternalTarget : Target - { - public InternalTarget() : base(8, false, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (from == targeted) - { - from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500910); // Hmm, that person looks really silly. - } - else if (targeted is TownCrier crier) - { - crier.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 500907, - from.NetState); // He looks smart enough to remember the news. Ask him about it. - } - else if (targeted is BaseVendor vendor && vendor.IsInvulnerable) - { - vendor.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 500909, - from.NetState); // That person could probably calculate the cost of what you buy from them. - } - else if (targeted is Mobile targ) - { - int marginOfError = Math.Max(0, 20 - (int)(from.Skills.EvalInt.Value / 5)); - - int intel = targ.Int + Utility.RandomMinMax(-marginOfError, +marginOfError); - int mana = targ.Mana * 100 / Math.Max(targ.ManaMax, 1) + - Utility.RandomMinMax(-marginOfError, +marginOfError); - - int intMod = Math.Clamp(intel / 10, 0, 10); - int mnMod = Math.Clamp(mana / 10, 0, 10); - - int body; - - if (targ.Body.IsHuman) - body = targ.Female ? 11 : 0; - else - body = 22; - - if (from.CheckTargetSkill(SkillName.EvalInt, targ, 0.0, 120.0)) - { - targ.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1038169 + intMod + body, - from.NetState); // He/She/It looks [slighly less intelligent than a rock.] [Of Average intellect] [etc...] - - if (from.Skills.EvalInt.Base >= 76.0) - targ.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1038202 + mnMod, - from.NetState); // That being is at [10,20,...] percent mental strength. - } - else - { - targ.PrivateOverheadMessage(MessageType.Regular, 0x3B2, 1038166 + body / 11, - from.NetState); // You cannot judge his/her/its mental abilities. - } - } - else - { - (targeted as Item)?.SendLocalizedMessageTo(from, 500908, - ""); // It looks smarter than a rock, but dumber than a piece of wood. - } - } - } - } } diff --git a/Projects/UOContent/Skills/ForensicEval.cs b/Projects/UOContent/Skills/ForensicEval.cs index 5c71b90b0..0a26ac3e1 100644 --- a/Projects/UOContent/Skills/ForensicEval.cs +++ b/Projects/UOContent/Skills/ForensicEval.cs @@ -6,90 +6,96 @@ using Server.Targeting; namespace Server.SkillHandlers { - public static class ForensicEvaluation - { - public static void Initialize() + public static class ForensicEvaluation { - SkillInfo.Table[(int)SkillName.Forensics].Callback = OnUse; - } - - public static TimeSpan OnUse(Mobile m) - { - m.Target = new ForensicTarget(); - m.RevealingAction(); - - m.SendLocalizedMessage(501000); // Show me the crime. - - return TimeSpan.FromSeconds(1.0); - } - - public class ForensicTarget : Target - { - public ForensicTarget() : base(10, false, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object target) - { - if (target is Mobile) + public static void Initialize() { - if (from.CheckTargetSkill(SkillName.Forensics, target, 40.0, 100.0)) - { - if (target is PlayerMobile pm && pm.NpcGuild == NpcGuild.ThievesGuild) - from.SendLocalizedMessage(501004); // That individual is a thief! - else - from.SendLocalizedMessage(501003); // You notice nothing unusual. - } - else - { - from.SendLocalizedMessage(501001); // You cannot determain anything useful. - } + SkillInfo.Table[(int)SkillName.Forensics].Callback = OnUse; } - else if (target is Corpse c) + + public static TimeSpan OnUse(Mobile m) { - if (from.CheckTargetSkill(SkillName.Forensics, c, 0.0, 100.0)) - { - if (c.m_Forensicist != null) - from.SendLocalizedMessage(1042750, - c.m_Forensicist); // The forensicist ~1_NAME~ has already discovered that: - else - c.m_Forensicist = from.Name; + m.Target = new ForensicTarget(); + m.RevealingAction(); - if (((Body)c.Amount).IsHuman) - from.SendLocalizedMessage(1042751, - c.Killer == null ? "no one" : c.Killer.Name); // This person was killed by ~1_KILLER_NAME~ + m.SendLocalizedMessage(501000); // Show me the crime. - if (c.Looters.Count > 0) + return TimeSpan.FromSeconds(1.0); + } + + public class ForensicTarget : Target + { + public ForensicTarget() : base(10, false, TargetFlags.None) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < c.Looters.Count; i++) - { - if (i > 0) - sb.Append(", "); - sb.Append(c.Looters[i].Name); - } + } - from.SendLocalizedMessage(1042752, - sb.ToString()); // This body has been distrubed by ~1_PLAYER_NAMES~ - } - else + protected override void OnTarget(Mobile from, object target) { - from.SendLocalizedMessage(501002); // The corpse has not be desecrated. + if (target is Mobile) + { + if (from.CheckTargetSkill(SkillName.Forensics, target, 40.0, 100.0)) + { + if (target is PlayerMobile pm && pm.NpcGuild == NpcGuild.ThievesGuild) + from.SendLocalizedMessage(501004); // That individual is a thief! + else + from.SendLocalizedMessage(501003); // You notice nothing unusual. + } + else + { + from.SendLocalizedMessage(501001); // You cannot determain anything useful. + } + } + else if (target is Corpse c) + { + if (from.CheckTargetSkill(SkillName.Forensics, c, 0.0, 100.0)) + { + if (c.m_Forensicist != null) + from.SendLocalizedMessage( + 1042750, + c.m_Forensicist + ); // The forensicist ~1_NAME~ has already discovered that: + else + c.m_Forensicist = from.Name; + + if (((Body)c.Amount).IsHuman) + from.SendLocalizedMessage( + 1042751, + c.Killer == null ? "no one" : c.Killer.Name + ); // This person was killed by ~1_KILLER_NAME~ + + if (c.Looters.Count > 0) + { + var sb = new StringBuilder(); + for (var i = 0; i < c.Looters.Count; i++) + { + if (i > 0) + sb.Append(", "); + sb.Append(c.Looters[i].Name); + } + + from.SendLocalizedMessage( + 1042752, + sb.ToString() + ); // This body has been distrubed by ~1_PLAYER_NAMES~ + } + else + { + from.SendLocalizedMessage(501002); // The corpse has not be desecrated. + } + } + else + { + from.SendLocalizedMessage(501001); // You cannot determain anything useful. + } + } + else if (target is ILockpickable p) + { + if (p.Picker != null) + from.SendLocalizedMessage(1042749, p.Picker.Name); // This lock was opened by ~1_PICKER_NAME~ + else + from.SendLocalizedMessage(501003); // You notice nothing unusual. + } } - } - else - { - from.SendLocalizedMessage(501001); // You cannot determain anything useful. - } } - else if (target is ILockpickable p) - { - if (p.Picker != null) - from.SendLocalizedMessage(1042749, p.Picker.Name); // This lock was opened by ~1_PICKER_NAME~ - else - from.SendLocalizedMessage(501003); // You notice nothing unusual. - } - } } - } } diff --git a/Projects/UOContent/Skills/Hiding.cs b/Projects/UOContent/Skills/Hiding.cs index 65a13ad23..c0531a436 100644 --- a/Projects/UOContent/Skills/Hiding.cs +++ b/Projects/UOContent/Skills/Hiding.cs @@ -6,82 +6,86 @@ using Server.Targeting; namespace Server.SkillHandlers { - public static class Hiding - { - public static bool CombatOverride { get; set; } - - public static void Initialize() + public static class Hiding { - SkillInfo.Table[21].Callback = OnUse; + public static bool CombatOverride { get; set; } + + public static void Initialize() + { + SkillInfo.Table[21].Callback = OnUse; + } + + public static TimeSpan OnUse(Mobile m) + { + if (m.Spell != null) + { + m.SendLocalizedMessage(501238); // You are busy doing something else and cannot hide. + return TimeSpan.FromSeconds(1.0); + } + + if (Core.ML && m.Target != null) Target.Cancel(m); + + var bonus = 0.0; + + var house = BaseHouse.FindHouseAt(m); + + if (house?.IsFriend(m) == true) + { + bonus = 100.0; + } + else if (!Core.AOS) + { + house ??= BaseHouse.FindHouseAt(new Point3D(m.X - 1, m.Y, 127), m.Map, 16) ?? + BaseHouse.FindHouseAt(new Point3D(m.X + 1, m.Y, 127), m.Map, 16) ?? + BaseHouse.FindHouseAt(new Point3D(m.X, m.Y - 1, 127), m.Map, 16) ?? + BaseHouse.FindHouseAt(new Point3D(m.X, m.Y + 1, 127), m.Map, 16); + + if (house != null) + bonus = 50.0; + } + + // int range = 18 - (int)(m.Skills.Hiding.Value / 10); + var range = Math.Min( + (int)((100 - m.Skills.Hiding.Value) / 2) + 8, + 18 + ); // Cap of 18 not OSI-exact, intentional difference + + var badCombat = !CombatOverride && m.Combatant != null && m.InRange(m.Combatant.Location, range) && + m.Combatant.InLOS(m); + var ok = !badCombat; + + if (ok) + { + if (!CombatOverride) + if (m.GetMobilesInRange(range).Any(check => check.InLOS(m) && check.Combatant == m)) + badCombat = true; + + ok = !badCombat && m.CheckSkill(SkillName.Hiding, 0.0 - bonus, 100.0 - bonus); + } + + if (badCombat) + { + m.RevealingAction(); + + m.LocalOverheadMessage(MessageType.Regular, 0x22, 501237); // You can't seem to hide right now. + + return TimeSpan.FromSeconds(1.0); + } + + if (ok) + { + m.Hidden = true; + m.Warmode = false; + m.LocalOverheadMessage(MessageType.Regular, 0x1F4, 501240); // You have hidden yourself well. + } + else + { + m.RevealingAction(); + + m.LocalOverheadMessage(MessageType.Regular, 0x22, 501241); // You can't seem to hide here. + } + + return TimeSpan.FromSeconds(10.0); + } } - - public static TimeSpan OnUse(Mobile m) - { - if (m.Spell != null) - { - m.SendLocalizedMessage(501238); // You are busy doing something else and cannot hide. - return TimeSpan.FromSeconds(1.0); - } - - if (Core.ML && m.Target != null) Target.Cancel(m); - - double bonus = 0.0; - - BaseHouse house = BaseHouse.FindHouseAt(m); - - if (house?.IsFriend(m) == true) - bonus = 100.0; - else if (!Core.AOS) - { - house ??= BaseHouse.FindHouseAt(new Point3D(m.X - 1, m.Y, 127), m.Map, 16) ?? - BaseHouse.FindHouseAt(new Point3D(m.X + 1, m.Y, 127), m.Map, 16) ?? - BaseHouse.FindHouseAt(new Point3D(m.X, m.Y - 1, 127), m.Map, 16) ?? - BaseHouse.FindHouseAt(new Point3D(m.X, m.Y + 1, 127), m.Map, 16); - - if (house != null) - bonus = 50.0; - } - - // int range = 18 - (int)(m.Skills.Hiding.Value / 10); - int range = Math.Min((int)((100 - m.Skills.Hiding.Value) / 2) + 8, - 18); // Cap of 18 not OSI-exact, intentional difference - - bool badCombat = !CombatOverride && m.Combatant != null && m.InRange(m.Combatant.Location, range) && - m.Combatant.InLOS(m); - bool ok = !badCombat; - - if (ok) - { - if (!CombatOverride) - if (m.GetMobilesInRange(range).Any(check => check.InLOS(m) && check.Combatant == m)) - badCombat = true; - - ok = !badCombat && m.CheckSkill(SkillName.Hiding, 0.0 - bonus, 100.0 - bonus); - } - - if (badCombat) - { - m.RevealingAction(); - - m.LocalOverheadMessage(MessageType.Regular, 0x22, 501237); // You can't seem to hide right now. - - return TimeSpan.FromSeconds(1.0); - } - - if (ok) - { - m.Hidden = true; - m.Warmode = false; - m.LocalOverheadMessage(MessageType.Regular, 0x1F4, 501240); // You have hidden yourself well. - } - else - { - m.RevealingAction(); - - m.LocalOverheadMessage(MessageType.Regular, 0x22, 501241); // You can't seem to hide here. - } - - return TimeSpan.FromSeconds(10.0); - } - } } diff --git a/Projects/UOContent/Skills/Inscribe.cs b/Projects/UOContent/Skills/Inscribe.cs index 29f7b88fc..9f940d0fe 100644 --- a/Projects/UOContent/Skills/Inscribe.cs +++ b/Projects/UOContent/Skills/Inscribe.cs @@ -6,162 +6,164 @@ using Server.Targeting; namespace Server.SkillHandlers { - public static class Inscribe - { - private static readonly Dictionary m_UseTable = new Dictionary(); - - public static void Initialize() + public static class Inscribe { - SkillInfo.Table[(int)SkillName.Inscribe].Callback = OnUse; + private static readonly Dictionary m_UseTable = new Dictionary(); + + public static void Initialize() + { + SkillInfo.Table[(int)SkillName.Inscribe].Callback = OnUse; + } + + public static TimeSpan OnUse(Mobile m) + { + Target target = new InternalTargetSrc(); + m.Target = target; + m.SendLocalizedMessage(1046295); // Target the book you wish to copy. + target.BeginTimeout(m, TimeSpan.FromMinutes(1.0)); + + return TimeSpan.FromSeconds(1.0); + } + + private static void SetUser(BaseBook book, Mobile mob) + { + m_UseTable[book] = mob; + } + + private static void CancelUser(BaseBook book) + { + m_UseTable.Remove(book); + } + + public static Mobile GetUser(BaseBook book) + { + m_UseTable.TryGetValue(book, out var m); + return m; + } + + public static bool IsEmpty(BaseBook book) + { + return book.Pages.SelectMany(page => page.Lines).All(line => line.Trim().Length == 0); + } + + public static void Copy(BaseBook bookSrc, BaseBook bookDst) + { + bookDst.Title = bookSrc.Title; + bookDst.Author = bookSrc.Author; + + var pagesSrc = bookSrc.Pages; + var pagesDst = bookDst.Pages; + for (var i = 0; i < pagesSrc.Length && i < pagesDst.Length; i++) + { + var pageSrc = pagesSrc[i]; + var pageDst = pagesDst[i]; + + var length = pageSrc.Lines.Length; + pageDst.Lines = new string[length]; + + for (var j = 0; j < length; j++) + pageDst.Lines[j] = pageSrc.Lines[j]; + } + } + + private class InternalTargetSrc : Target + { + public InternalTargetSrc() : base(3, false, TargetFlags.None) + { + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (!(targeted is BaseBook book)) + { + from.SendLocalizedMessage(1046296); // That is not a book + } + else if (IsEmpty(book)) + { + from.SendLocalizedMessage(501611); // Can't copy an empty book. + } + else if (GetUser(book) != null) + { + from.SendLocalizedMessage(501621); // Someone else is inscribing that item. + } + else + { + Target target = new InternalTargetDst(book); + from.Target = target; + from.SendLocalizedMessage(501612); // Select a book to copy this to. + target.BeginTimeout(from, TimeSpan.FromMinutes(1.0)); + SetUser(book, from); + } + } + + protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType) + { + if (cancelType == TargetCancelType.Timeout) + from.SendLocalizedMessage( + 501619 + ); // You have waited too long to make your inscribe selection, your inscription attempt has timed out. + } + } + + private class InternalTargetDst : Target + { + private readonly BaseBook m_BookSrc; + + public InternalTargetDst(BaseBook bookSrc) : base(3, false, TargetFlags.None) => m_BookSrc = bookSrc; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_BookSrc.Deleted) + return; + + if (!(targeted is BaseBook bookDst)) + { + from.SendLocalizedMessage(1046296); // That is not a book + } + else if (IsEmpty(m_BookSrc)) + { + from.SendLocalizedMessage(501611); // Can't copy an empty book. + } + else if (bookDst == m_BookSrc) + { + from.SendLocalizedMessage(501616); // Cannot copy a book onto itself. + } + else if (!bookDst.Writable) + { + from.SendLocalizedMessage(501614); // Cannot write into that book. + } + else if (GetUser(bookDst) != null) + { + from.SendLocalizedMessage(501621); // Someone else is inscribing that item. + } + else + { + if (from.CheckTargetSkill(SkillName.Inscribe, bookDst, 0, 50)) + { + Copy(m_BookSrc, bookDst); + + from.SendLocalizedMessage(501618); // You make a copy of the book. + from.PlaySound(0x249); + } + else + { + from.SendLocalizedMessage(501617); // You fail to make a copy of the book. + } + } + } + + protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType) + { + if (cancelType == TargetCancelType.Timeout) + from.SendLocalizedMessage( + 501619 + ); // You have waited too long to make your inscribe selection, your inscription attempt has timed out. + } + + protected override void OnTargetFinish(Mobile from) + { + CancelUser(m_BookSrc); + } + } } - - public static TimeSpan OnUse(Mobile m) - { - Target target = new InternalTargetSrc(); - m.Target = target; - m.SendLocalizedMessage(1046295); // Target the book you wish to copy. - target.BeginTimeout(m, TimeSpan.FromMinutes(1.0)); - - return TimeSpan.FromSeconds(1.0); - } - - private static void SetUser(BaseBook book, Mobile mob) - { - m_UseTable[book] = mob; - } - - private static void CancelUser(BaseBook book) - { - m_UseTable.Remove(book); - } - - public static Mobile GetUser(BaseBook book) - { - m_UseTable.TryGetValue(book, out Mobile m); - return m; - } - - public static bool IsEmpty(BaseBook book) - { - return book.Pages.SelectMany(page => page.Lines).All(line => line.Trim().Length == 0); - } - - public static void Copy(BaseBook bookSrc, BaseBook bookDst) - { - bookDst.Title = bookSrc.Title; - bookDst.Author = bookSrc.Author; - - BookPageInfo[] pagesSrc = bookSrc.Pages; - BookPageInfo[] pagesDst = bookDst.Pages; - for (int i = 0; i < pagesSrc.Length && i < pagesDst.Length; i++) - { - BookPageInfo pageSrc = pagesSrc[i]; - BookPageInfo pageDst = pagesDst[i]; - - int length = pageSrc.Lines.Length; - pageDst.Lines = new string[length]; - - for (int j = 0; j < length; j++) - pageDst.Lines[j] = pageSrc.Lines[j]; - } - } - - private class InternalTargetSrc : Target - { - public InternalTargetSrc() : base(3, false, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (!(targeted is BaseBook book)) - { - from.SendLocalizedMessage(1046296); // That is not a book - } - else if (IsEmpty(book)) - { - from.SendLocalizedMessage(501611); // Can't copy an empty book. - } - else if (GetUser(book) != null) - { - from.SendLocalizedMessage(501621); // Someone else is inscribing that item. - } - else - { - Target target = new InternalTargetDst(book); - from.Target = target; - from.SendLocalizedMessage(501612); // Select a book to copy this to. - target.BeginTimeout(from, TimeSpan.FromMinutes(1.0)); - SetUser(book, from); - } - } - - protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType) - { - if (cancelType == TargetCancelType.Timeout) - from.SendLocalizedMessage( - 501619); // You have waited too long to make your inscribe selection, your inscription attempt has timed out. - } - } - - private class InternalTargetDst : Target - { - private readonly BaseBook m_BookSrc; - - public InternalTargetDst(BaseBook bookSrc) : base(3, false, TargetFlags.None) => m_BookSrc = bookSrc; - - protected override void OnTarget(Mobile from, object targeted) - { - if (m_BookSrc.Deleted) - return; - - if (!(targeted is BaseBook bookDst)) - { - from.SendLocalizedMessage(1046296); // That is not a book - } - else if (IsEmpty(m_BookSrc)) - { - from.SendLocalizedMessage(501611); // Can't copy an empty book. - } - else if (bookDst == m_BookSrc) - { - from.SendLocalizedMessage(501616); // Cannot copy a book onto itself. - } - else if (!bookDst.Writable) - { - from.SendLocalizedMessage(501614); // Cannot write into that book. - } - else if (GetUser(bookDst) != null) - { - from.SendLocalizedMessage(501621); // Someone else is inscribing that item. - } - else - { - if (from.CheckTargetSkill(SkillName.Inscribe, bookDst, 0, 50)) - { - Copy(m_BookSrc, bookDst); - - from.SendLocalizedMessage(501618); // You make a copy of the book. - from.PlaySound(0x249); - } - else - { - from.SendLocalizedMessage(501617); // You fail to make a copy of the book. - } - } - } - - protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType) - { - if (cancelType == TargetCancelType.Timeout) - from.SendLocalizedMessage( - 501619); // You have waited too long to make your inscribe selection, your inscription attempt has timed out. - } - - protected override void OnTargetFinish(Mobile from) - { - CancelUser(m_BookSrc); - } - } - } } diff --git a/Projects/UOContent/Skills/ItemIdentification.cs b/Projects/UOContent/Skills/ItemIdentification.cs index 20b3e6a82..6e87b8ad7 100644 --- a/Projects/UOContent/Skills/ItemIdentification.cs +++ b/Projects/UOContent/Skills/ItemIdentification.cs @@ -4,54 +4,54 @@ using Server.Targeting; namespace Server.Items { - public static class ItemIdentification - { - public static void Initialize() + public static class ItemIdentification { - SkillInfo.Table[(int)SkillName.ItemID].Callback = OnUse; - } - - public static TimeSpan OnUse(Mobile from) - { - from.SendLocalizedMessage(500343); // What do you wish to appraise and identify? - from.Target = new InternalTarget(); - - return TimeSpan.FromSeconds(1.0); - } - - [PlayerVendorTarget] - private class InternalTarget : Target - { - public InternalTarget() : base(8, false, TargetFlags.None) => AllowNonlocal = true; - - protected override void OnTarget(Mobile from, object o) - { - if (o is Item item) + public static void Initialize() { - if (from.CheckTargetSkill(SkillName.ItemID, item, 0, 100)) - { - if (item is BaseWeapon weapon) - weapon.Identified = true; - else if (item is BaseArmor armor) - armor.Identified = true; + SkillInfo.Table[(int)SkillName.ItemID].Callback = OnUse; + } - if (!Core.AOS) - item.OnSingleClick(from); - } - else - { - from.SendLocalizedMessage(500353); // You are not certain... - } - } - else if (o is Mobile mobile) + public static TimeSpan OnUse(Mobile from) { - mobile.OnSingleClick(from); + from.SendLocalizedMessage(500343); // What do you wish to appraise and identify? + from.Target = new InternalTarget(); + + return TimeSpan.FromSeconds(1.0); } - else + + [PlayerVendorTarget] + private class InternalTarget : Target { - from.SendLocalizedMessage(500353); // You are not certain... + public InternalTarget() : base(8, false, TargetFlags.None) => AllowNonlocal = true; + + protected override void OnTarget(Mobile from, object o) + { + if (o is Item item) + { + if (from.CheckTargetSkill(SkillName.ItemID, item, 0, 100)) + { + if (item is BaseWeapon weapon) + weapon.Identified = true; + else if (item is BaseArmor armor) + armor.Identified = true; + + if (!Core.AOS) + item.OnSingleClick(from); + } + else + { + from.SendLocalizedMessage(500353); // You are not certain... + } + } + else if (o is Mobile mobile) + { + mobile.OnSingleClick(from); + } + else + { + from.SendLocalizedMessage(500353); // You are not certain... + } + } } - } } - } } diff --git a/Projects/UOContent/Skills/Meditation.cs b/Projects/UOContent/Skills/Meditation.cs index a945e6bd0..45249db7f 100644 --- a/Projects/UOContent/Skills/Meditation.cs +++ b/Projects/UOContent/Skills/Meditation.cs @@ -4,100 +4,100 @@ using Server.Misc; namespace Server.SkillHandlers { - internal static class Meditation - { - public static void Initialize() + internal static class Meditation { - SkillInfo.Table[46].Callback = OnUse; + public static void Initialize() + { + SkillInfo.Table[46].Callback = OnUse; + } + + public static bool CheckOkayHolding(Item item) + { + if (item == null) + return true; + + if (item is Spellbook || item is Runebook) + return true; + + if (Core.AOS && item is BaseWeapon weapon && weapon.Attributes.SpellChanneling != 0) + return true; + + if (Core.AOS && item is BaseArmor armor && armor.Attributes.SpellChanneling != 0) + return true; + + return false; + } + + public static TimeSpan OnUse(Mobile m) + { + m.RevealingAction(); + + if (m.Target != null) + { + m.SendLocalizedMessage(501845); // You are busy doing something else and cannot focus. + + return TimeSpan.FromSeconds(5.0); + } + + if (!Core.AOS && m.Hits < m.HitsMax / 10) // Less than 10% health + { + m.SendLocalizedMessage(501849); // The mind is strong but the body is weak. + + return TimeSpan.FromSeconds(5.0); + } + + if (m.Mana >= m.ManaMax) + { + m.SendLocalizedMessage(501846); // You are at peace. + + return TimeSpan.FromSeconds(Core.AOS ? 10.0 : 5.0); + } + + if (Core.AOS && RegenRates.GetArmorOffset(m) > 0) + { + m.SendLocalizedMessage(500135); // Regenerative forces cannot penetrate your armor! + + return TimeSpan.FromSeconds(10.0); + } + + var oneHanded = m.FindItemOnLayer(Layer.OneHanded); + var twoHanded = m.FindItemOnLayer(Layer.TwoHanded); + + if (Core.AOS && m.Player) + { + if (!CheckOkayHolding(oneHanded)) + m.AddToBackpack(oneHanded); + + if (!CheckOkayHolding(twoHanded)) + m.AddToBackpack(twoHanded); + } + else if (!CheckOkayHolding(oneHanded) || !CheckOkayHolding(twoHanded)) + { + m.SendLocalizedMessage(502626); // Your hands must be free to cast spells or meditate. + + return TimeSpan.FromSeconds(2.5); + } + + var skillVal = m.Skills.Meditation.Value; + var chance = (50.0 + (skillVal - (m.ManaMax - m.Mana)) * 2) / 100; + + if (chance > Utility.RandomDouble()) + { + m.CheckSkill(SkillName.Meditation, 0.0, 100.0); + + m.SendLocalizedMessage(501851); // You enter a meditative trance. + m.Meditating = true; + BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.ActiveMeditation, 1075657)); + + if (m.Player || m.Body.IsHuman) + m.PlaySound(0xF9); + } + else + { + m.SendLocalizedMessage(501850); // You cannot focus your concentration. + } + + return TimeSpan.FromSeconds(10.0); + } } - - public static bool CheckOkayHolding(Item item) - { - if (item == null) - return true; - - if (item is Spellbook || item is Runebook) - return true; - - if (Core.AOS && item is BaseWeapon weapon && weapon.Attributes.SpellChanneling != 0) - return true; - - if (Core.AOS && item is BaseArmor armor && armor.Attributes.SpellChanneling != 0) - return true; - - return false; - } - - public static TimeSpan OnUse(Mobile m) - { - m.RevealingAction(); - - if (m.Target != null) - { - m.SendLocalizedMessage(501845); // You are busy doing something else and cannot focus. - - return TimeSpan.FromSeconds(5.0); - } - - if (!Core.AOS && m.Hits < m.HitsMax / 10) // Less than 10% health - { - m.SendLocalizedMessage(501849); // The mind is strong but the body is weak. - - return TimeSpan.FromSeconds(5.0); - } - - if (m.Mana >= m.ManaMax) - { - m.SendLocalizedMessage(501846); // You are at peace. - - return TimeSpan.FromSeconds(Core.AOS ? 10.0 : 5.0); - } - - if (Core.AOS && RegenRates.GetArmorOffset(m) > 0) - { - m.SendLocalizedMessage(500135); // Regenerative forces cannot penetrate your armor! - - return TimeSpan.FromSeconds(10.0); - } - - Item oneHanded = m.FindItemOnLayer(Layer.OneHanded); - Item twoHanded = m.FindItemOnLayer(Layer.TwoHanded); - - if (Core.AOS && m.Player) - { - if (!CheckOkayHolding(oneHanded)) - m.AddToBackpack(oneHanded); - - if (!CheckOkayHolding(twoHanded)) - m.AddToBackpack(twoHanded); - } - else if (!CheckOkayHolding(oneHanded) || !CheckOkayHolding(twoHanded)) - { - m.SendLocalizedMessage(502626); // Your hands must be free to cast spells or meditate. - - return TimeSpan.FromSeconds(2.5); - } - - double skillVal = m.Skills.Meditation.Value; - double chance = (50.0 + (skillVal - (m.ManaMax - m.Mana)) * 2) / 100; - - if (chance > Utility.RandomDouble()) - { - m.CheckSkill(SkillName.Meditation, 0.0, 100.0); - - m.SendLocalizedMessage(501851); // You enter a meditative trance. - m.Meditating = true; - BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.ActiveMeditation, 1075657)); - - if (m.Player || m.Body.IsHuman) - m.PlaySound(0xF9); - } - else - { - m.SendLocalizedMessage(501850); // You cannot focus your concentration. - } - - return TimeSpan.FromSeconds(10.0); - } - } } diff --git a/Projects/UOContent/Skills/Peacemaking.cs b/Projects/UOContent/Skills/Peacemaking.cs index 1eccd9ed8..9f9b1ce9d 100644 --- a/Projects/UOContent/Skills/Peacemaking.cs +++ b/Projects/UOContent/Skills/Peacemaking.cs @@ -6,202 +6,209 @@ using Server.Targeting; namespace Server.SkillHandlers { - public static class Peacemaking - { - public static void Initialize() + public static class Peacemaking { - SkillInfo.Table[(int)SkillName.Peacemaking].Callback = OnUse; - } - - public static TimeSpan OnUse(Mobile m) - { - m.RevealingAction(); - - BaseInstrument.PickInstrument(m, OnPickedInstrument); - - return TimeSpan.FromSeconds(1.0); // Cannot use another skill for 1 second - } - - public static void OnPickedInstrument(Mobile from, BaseInstrument instrument) - { - from.RevealingAction(); - from.SendLocalizedMessage(1049525); // Whom do you wish to calm? - from.Target = new InternalTarget(from, instrument); - from.NextSkillTime = Core.TickCount + 21600000; - } - - private class InternalTarget : Target - { - private readonly BaseInstrument m_Instrument; - private bool m_SetSkillTime = true; - - public InternalTarget(Mobile from, BaseInstrument instrument) : base( - BaseInstrument.GetBardRange(from, SkillName.Peacemaking), false, TargetFlags.None) => - m_Instrument = instrument; - - protected override void OnTargetFinish(Mobile from) - { - if (m_SetSkillTime) - from.NextSkillTime = Core.TickCount; - } - - protected override void OnTarget(Mobile from, object targeted) - { - from.RevealingAction(); - - if (!(targeted is Mobile targ)) + public static void Initialize() { - from.SendLocalizedMessage(1049528); // You cannot calm that! + SkillInfo.Table[(int)SkillName.Peacemaking].Callback = OnUse; } - else if (from.Region.IsPartOf()) - { - from.SendMessage("You may not peacemake in this area."); - } - else if (targ.Region.IsPartOf()) - { - from.SendMessage("You may not peacemake there."); - } - else if (!m_Instrument.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage( - 1062488); // The instrument you are trying to play is no longer in your backpack! - } - else - { - m_SetSkillTime = false; - from.NextSkillTime = Core.TickCount + 10000; - if (targeted == from) - { - // Standard mode : reset combatants for everyone in the area + public static TimeSpan OnUse(Mobile m) + { + m.RevealingAction(); - if (!BaseInstrument.CheckMusicianship(from)) + BaseInstrument.PickInstrument(m, OnPickedInstrument); + + return TimeSpan.FromSeconds(1.0); // Cannot use another skill for 1 second + } + + public static void OnPickedInstrument(Mobile from, BaseInstrument instrument) + { + from.RevealingAction(); + from.SendLocalizedMessage(1049525); // Whom do you wish to calm? + from.Target = new InternalTarget(from, instrument); + from.NextSkillTime = Core.TickCount + 21600000; + } + + private class InternalTarget : Target + { + private readonly BaseInstrument m_Instrument; + private bool m_SetSkillTime = true; + + public InternalTarget(Mobile from, BaseInstrument instrument) : base( + BaseInstrument.GetBardRange(from, SkillName.Peacemaking), + false, + TargetFlags.None + ) => + m_Instrument = instrument; + + protected override void OnTargetFinish(Mobile from) { - from.SendLocalizedMessage(500612); // You play poorly, and there is no effect. - m_Instrument.PlayInstrumentBadly(from); - m_Instrument.ConsumeUse(from); + if (m_SetSkillTime) + from.NextSkillTime = Core.TickCount; } - else if (!from.CheckSkill(SkillName.Peacemaking, 0.0, 120.0)) + + protected override void OnTarget(Mobile from, object targeted) { - from.SendLocalizedMessage(500613); // You attempt to calm everyone, but fail. - m_Instrument.PlayInstrumentBadly(from); - m_Instrument.ConsumeUse(from); - } - else - { - from.NextSkillTime = Core.TickCount + 5000; - m_Instrument.PlayInstrumentWell(from); - m_Instrument.ConsumeUse(from); + from.RevealingAction(); - Map map = from.Map; - - if (map != null) - { - int range = BaseInstrument.GetBardRange(from, SkillName.Peacemaking); - - bool calmed = false; - - foreach (Mobile m in from.GetMobilesInRange(range)) + if (!(targeted is Mobile targ)) { - BaseCreature bc = m as BaseCreature; - if (bc?.Uncalmable == true || bc?.AreaPeaceImmune == true || m == from || - !from.CanBeHarmful(m, false)) - continue; - - calmed = true; - - m.SendLocalizedMessage( - 500616); // You hear lovely music, and forget to continue battling! - m.Combatant = null; - m.Warmode = false; - - if (bc?.BardPacified == false) - bc.Pacify(from, DateTime.UtcNow + TimeSpan.FromSeconds(1.0)); + from.SendLocalizedMessage(1049528); // You cannot calm that! } - - if (!calmed) - from.SendLocalizedMessage( - 1049648); // You play hypnotic music, but there is nothing in range for you to calm. - else - from.SendLocalizedMessage(500615); // You play your hypnotic music, stopping the battle. - } - } - } - else - { - // Target mode : pacify a single target for a longer duration - BaseCreature bc = targ as BaseCreature; - - if (!from.CanBeHarmful(targ, false)) - { - from.SendLocalizedMessage(1049528); - m_SetSkillTime = true; - } - else if (bc?.Uncalmable == true) - { - from.SendLocalizedMessage(1049526); // You have no chance of calming that creature. - m_SetSkillTime = true; - } - else if (bc?.BardPacified == true) - { - from.SendLocalizedMessage(1049527); // That creature is already being calmed. - m_SetSkillTime = true; - } - else if (!BaseInstrument.CheckMusicianship(from)) - { - from.SendLocalizedMessage(500612); // You play poorly, and there is no effect. - from.NextSkillTime = Core.TickCount + 5000; - m_Instrument.PlayInstrumentBadly(from); - m_Instrument.ConsumeUse(from); - } - else - { - double diff = m_Instrument.GetDifficultyFor(targ) - 10.0; - double music = from.Skills.Musicianship.Value; - - if (music > 100.0) - diff -= (music - 100.0) * 0.5; - - if (!from.CheckTargetSkill(SkillName.Peacemaking, targ, diff - 25.0, diff + 25.0)) - { - from.SendLocalizedMessage(1049531); // You attempt to calm your target, but fail. - m_Instrument.PlayInstrumentBadly(from); - m_Instrument.ConsumeUse(from); - } - else - { - m_Instrument.PlayInstrumentWell(from); - m_Instrument.ConsumeUse(from); - - from.NextSkillTime = Core.TickCount + 5000; - targ.Combatant = null; - targ.Warmode = false; - - if (bc != null) + else if (from.Region.IsPartOf()) { - from.SendLocalizedMessage(1049532); // You play hypnotic music, calming your target. - - double seconds = 100 - diff / 1.5; - - if (seconds > 120) - seconds = 120; - else if (seconds < 10) - seconds = 10; - - bc.Pacify(from, DateTime.UtcNow + TimeSpan.FromSeconds(seconds)); + from.SendMessage("You may not peacemake in this area."); + } + else if (targ.Region.IsPartOf()) + { + from.SendMessage("You may not peacemake there."); + } + else if (!m_Instrument.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage( + 1062488 + ); // The instrument you are trying to play is no longer in your backpack! } else { - from.SendLocalizedMessage(1049532); // You play hypnotic music, calming your target. + m_SetSkillTime = false; + from.NextSkillTime = Core.TickCount + 10000; - targ.SendLocalizedMessage( - 500616); // You hear lovely music, and forget to continue battling! + if (targeted == from) + { + // Standard mode : reset combatants for everyone in the area + + if (!BaseInstrument.CheckMusicianship(from)) + { + from.SendLocalizedMessage(500612); // You play poorly, and there is no effect. + m_Instrument.PlayInstrumentBadly(from); + m_Instrument.ConsumeUse(from); + } + else if (!from.CheckSkill(SkillName.Peacemaking, 0.0, 120.0)) + { + from.SendLocalizedMessage(500613); // You attempt to calm everyone, but fail. + m_Instrument.PlayInstrumentBadly(from); + m_Instrument.ConsumeUse(from); + } + else + { + from.NextSkillTime = Core.TickCount + 5000; + m_Instrument.PlayInstrumentWell(from); + m_Instrument.ConsumeUse(from); + + var map = from.Map; + + if (map != null) + { + var range = BaseInstrument.GetBardRange(from, SkillName.Peacemaking); + + var calmed = false; + + foreach (var m in from.GetMobilesInRange(range)) + { + var bc = m as BaseCreature; + if (bc?.Uncalmable == true || bc?.AreaPeaceImmune == true || m == from || + !from.CanBeHarmful(m, false)) + continue; + + calmed = true; + + m.SendLocalizedMessage( + 500616 + ); // You hear lovely music, and forget to continue battling! + m.Combatant = null; + m.Warmode = false; + + if (bc?.BardPacified == false) + bc.Pacify(from, DateTime.UtcNow + TimeSpan.FromSeconds(1.0)); + } + + if (!calmed) + from.SendLocalizedMessage( + 1049648 + ); // You play hypnotic music, but there is nothing in range for you to calm. + else + from.SendLocalizedMessage(500615); // You play your hypnotic music, stopping the battle. + } + } + } + else + { + // Target mode : pacify a single target for a longer duration + var bc = targ as BaseCreature; + + if (!from.CanBeHarmful(targ, false)) + { + from.SendLocalizedMessage(1049528); + m_SetSkillTime = true; + } + else if (bc?.Uncalmable == true) + { + from.SendLocalizedMessage(1049526); // You have no chance of calming that creature. + m_SetSkillTime = true; + } + else if (bc?.BardPacified == true) + { + from.SendLocalizedMessage(1049527); // That creature is already being calmed. + m_SetSkillTime = true; + } + else if (!BaseInstrument.CheckMusicianship(from)) + { + from.SendLocalizedMessage(500612); // You play poorly, and there is no effect. + from.NextSkillTime = Core.TickCount + 5000; + m_Instrument.PlayInstrumentBadly(from); + m_Instrument.ConsumeUse(from); + } + else + { + var diff = m_Instrument.GetDifficultyFor(targ) - 10.0; + var music = from.Skills.Musicianship.Value; + + if (music > 100.0) + diff -= (music - 100.0) * 0.5; + + if (!from.CheckTargetSkill(SkillName.Peacemaking, targ, diff - 25.0, diff + 25.0)) + { + from.SendLocalizedMessage(1049531); // You attempt to calm your target, but fail. + m_Instrument.PlayInstrumentBadly(from); + m_Instrument.ConsumeUse(from); + } + else + { + m_Instrument.PlayInstrumentWell(from); + m_Instrument.ConsumeUse(from); + + from.NextSkillTime = Core.TickCount + 5000; + targ.Combatant = null; + targ.Warmode = false; + + if (bc != null) + { + from.SendLocalizedMessage(1049532); // You play hypnotic music, calming your target. + + var seconds = 100 - diff / 1.5; + + if (seconds > 120) + seconds = 120; + else if (seconds < 10) + seconds = 10; + + bc.Pacify(from, DateTime.UtcNow + TimeSpan.FromSeconds(seconds)); + } + else + { + from.SendLocalizedMessage(1049532); // You play hypnotic music, calming your target. + + targ.SendLocalizedMessage( + 500616 + ); // You hear lovely music, and forget to continue battling! + } + } + } + } } - } } - } } - } } - } } diff --git a/Projects/UOContent/Skills/Poisoning.cs b/Projects/UOContent/Skills/Poisoning.cs index 4a6aa9962..9dd8b7197 100644 --- a/Projects/UOContent/Skills/Poisoning.cs +++ b/Projects/UOContent/Skills/Poisoning.cs @@ -6,166 +6,174 @@ using Server.Targeting; namespace Server.SkillHandlers { - public static class Poisoning - { - public static void Initialize() + public static class Poisoning { - SkillInfo.Table[(int)SkillName.Poisoning].Callback = OnUse; - } - - public static TimeSpan OnUse(Mobile m) - { - m.Target = new InternalTargetPoison(); - - m.SendLocalizedMessage(502137); // Select the poison you wish to use - - return TimeSpan.FromSeconds(10.0); // 10 second delay before being able to re-use a skill - } - - private class InternalTargetPoison : Target - { - public InternalTargetPoison() : base(2, false, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is BasePoisonPotion potion) + public static void Initialize() { - from.SendLocalizedMessage(502142); // To what do you wish to apply the poison? - from.Target = new InternalTarget(potion); + SkillInfo.Table[(int)SkillName.Poisoning].Callback = OnUse; } - else // Not a Poison Potion + + public static TimeSpan OnUse(Mobile m) { - from.SendLocalizedMessage(502139); // That is not a poison potion. + m.Target = new InternalTargetPoison(); + + m.SendLocalizedMessage(502137); // Select the poison you wish to use + + return TimeSpan.FromSeconds(10.0); // 10 second delay before being able to re-use a skill } - } - private class InternalTarget : Target - { - private readonly BasePoisonPotion m_Potion; - - public InternalTarget(BasePoisonPotion potion) : base(2, false, TargetFlags.None) => m_Potion = potion; - - protected override void OnTarget(Mobile from, object targeted) + private class InternalTargetPoison : Target { - if (m_Potion.Deleted) - return; - - bool startTimer = false; - - if (targeted is Food || targeted is FukiyaDarts || targeted is Shuriken) - { - startTimer = true; - } - else if (targeted is BaseWeapon weapon) - { - if (Core.AOS) - startTimer = weapon.PrimaryAbility == WeaponAbility.InfectiousStrike || - weapon.SecondaryAbility == WeaponAbility.InfectiousStrike; - else if (weapon.Layer == Layer.OneHanded) - startTimer = weapon.Type == WeaponType.Slashing || weapon.Type == WeaponType.Piercing; - } - - if (startTimer) - { - new InternalTimer(from, (Item)targeted, m_Potion).Start(); - - from.PlaySound(0x4F); - - if (!DuelContext.IsFreeConsume(from)) + public InternalTargetPoison() : base(2, false, TargetFlags.None) { - m_Potion.Consume(); - from.AddToBackpack(new Bottle()); } - } - else // Target can't be poisoned - { - if (Core.AOS) - from.SendLocalizedMessage( - 1060204); // You cannot poison that! You can only poison infectious weapons, food or drink. - else - from.SendLocalizedMessage( - 502145); // You cannot poison that! You can only poison bladed or piercing weapons, food or drink. - } - } - private class InternalTimer : Timer - { - private readonly Mobile m_From; - private readonly double m_MinSkill; - private readonly double m_MaxSkill; - private readonly Poison m_Poison; - private readonly Item m_Target; - - public InternalTimer(Mobile from, Item target, BasePoisonPotion potion) : base(TimeSpan.FromSeconds(2.0)) - { - m_From = from; - m_Target = target; - m_Poison = potion.Poison; - m_MinSkill = potion.MinPoisoningSkill; - m_MaxSkill = potion.MaxPoisoningSkill; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - if (m_From.CheckTargetSkill(SkillName.Poisoning, m_Target, m_MinSkill, m_MaxSkill)) + protected override void OnTarget(Mobile from, object targeted) { - if (m_Target is Food food) - { - food.Poison = m_Poison; - } - else if (m_Target is BaseWeapon weapon) - { - weapon.Poison = m_Poison; - weapon.PoisonCharges = 18 - m_Poison.Level * 2; - } - else if (m_Target is FukiyaDarts darts) - { - darts.Poison = m_Poison; - darts.PoisonCharges = Math.Min(18 - m_Poison.Level * 2, - darts.UsesRemaining); - } - else if (m_Target is Shuriken shuriken) - { - shuriken.Poison = m_Poison; - shuriken.PoisonCharges = Math.Min(18 - m_Poison.Level * 2, - shuriken.UsesRemaining); - } - - m_From.SendLocalizedMessage(1010517); // You apply the poison - - Titles.AwardKarma(m_From, -20, true); - } - else // Failed - { - // 5% of chance of getting poisoned if failed - if (m_From.Skills.Poisoning.Base < 80.0 && Utility.Random(20) == 0) - { - m_From.SendLocalizedMessage(502148); // You make a grave mistake while applying the poison. - m_From.ApplyPoison(m_From, m_Poison); - } - else - { - if (m_Target is BaseWeapon weapon) + if (targeted is BasePoisonPotion potion) { - if (weapon.Type == WeaponType.Slashing) - m_From.SendLocalizedMessage( - 1010516); // You fail to apply a sufficient dose of poison on the blade - else - m_From.SendLocalizedMessage( - 1010518); // You fail to apply a sufficient dose of poison + from.SendLocalizedMessage(502142); // To what do you wish to apply the poison? + from.Target = new InternalTarget(potion); } - else + else // Not a Poison Potion { - m_From.SendLocalizedMessage(1010518); // You fail to apply a sufficient dose of poison + from.SendLocalizedMessage(502139); // That is not a poison potion. + } + } + + private class InternalTarget : Target + { + private readonly BasePoisonPotion m_Potion; + + public InternalTarget(BasePoisonPotion potion) : base(2, false, TargetFlags.None) => m_Potion = potion; + + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Potion.Deleted) + return; + + var startTimer = false; + + if (targeted is Food || targeted is FukiyaDarts || targeted is Shuriken) + { + startTimer = true; + } + else if (targeted is BaseWeapon weapon) + { + if (Core.AOS) + startTimer = weapon.PrimaryAbility == WeaponAbility.InfectiousStrike || + weapon.SecondaryAbility == WeaponAbility.InfectiousStrike; + else if (weapon.Layer == Layer.OneHanded) + startTimer = weapon.Type == WeaponType.Slashing || weapon.Type == WeaponType.Piercing; + } + + if (startTimer) + { + new InternalTimer(from, (Item)targeted, m_Potion).Start(); + + from.PlaySound(0x4F); + + if (!DuelContext.IsFreeConsume(from)) + { + m_Potion.Consume(); + from.AddToBackpack(new Bottle()); + } + } + else // Target can't be poisoned + { + if (Core.AOS) + from.SendLocalizedMessage( + 1060204 + ); // You cannot poison that! You can only poison infectious weapons, food or drink. + else + from.SendLocalizedMessage( + 502145 + ); // You cannot poison that! You can only poison bladed or piercing weapons, food or drink. + } + } + + private class InternalTimer : Timer + { + private readonly Mobile m_From; + private readonly double m_MaxSkill; + private readonly double m_MinSkill; + private readonly Poison m_Poison; + private readonly Item m_Target; + + public InternalTimer(Mobile from, Item target, BasePoisonPotion potion) : base(TimeSpan.FromSeconds(2.0)) + { + m_From = from; + m_Target = target; + m_Poison = potion.Poison; + m_MinSkill = potion.MinPoisoningSkill; + m_MaxSkill = potion.MaxPoisoningSkill; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + if (m_From.CheckTargetSkill(SkillName.Poisoning, m_Target, m_MinSkill, m_MaxSkill)) + { + if (m_Target is Food food) + { + food.Poison = m_Poison; + } + else if (m_Target is BaseWeapon weapon) + { + weapon.Poison = m_Poison; + weapon.PoisonCharges = 18 - m_Poison.Level * 2; + } + else if (m_Target is FukiyaDarts darts) + { + darts.Poison = m_Poison; + darts.PoisonCharges = Math.Min( + 18 - m_Poison.Level * 2, + darts.UsesRemaining + ); + } + else if (m_Target is Shuriken shuriken) + { + shuriken.Poison = m_Poison; + shuriken.PoisonCharges = Math.Min( + 18 - m_Poison.Level * 2, + shuriken.UsesRemaining + ); + } + + m_From.SendLocalizedMessage(1010517); // You apply the poison + + Titles.AwardKarma(m_From, -20, true); + } + else // Failed + { + // 5% of chance of getting poisoned if failed + if (m_From.Skills.Poisoning.Base < 80.0 && Utility.Random(20) == 0) + { + m_From.SendLocalizedMessage(502148); // You make a grave mistake while applying the poison. + m_From.ApplyPoison(m_From, m_Poison); + } + else + { + if (m_Target is BaseWeapon weapon) + { + if (weapon.Type == WeaponType.Slashing) + m_From.SendLocalizedMessage( + 1010516 + ); // You fail to apply a sufficient dose of poison on the blade + else + m_From.SendLocalizedMessage( + 1010518 + ); // You fail to apply a sufficient dose of poison + } + else + { + m_From.SendLocalizedMessage(1010518); // You fail to apply a sufficient dose of poison + } + } + } + } } - } } - } } - } } - } } diff --git a/Projects/UOContent/Skills/Provocation.cs b/Projects/UOContent/Skills/Provocation.cs index 70d9df6ed..a60ed28ab 100644 --- a/Projects/UOContent/Skills/Provocation.cs +++ b/Projects/UOContent/Skills/Provocation.cs @@ -5,161 +5,173 @@ using Server.Targeting; namespace Server.SkillHandlers { - public static class Provocation - { - public static void Initialize() + public static class Provocation { - SkillInfo.Table[(int)SkillName.Provocation].Callback = OnUse; - } - - public static TimeSpan OnUse(Mobile m) - { - m.RevealingAction(); - - BaseInstrument.PickInstrument(m, OnPickedInstrument); - - return TimeSpan.FromSeconds(1.0); // Cannot use another skill for 1 second - } - - public static void OnPickedInstrument(Mobile from, BaseInstrument instrument) - { - from.RevealingAction(); - from.SendLocalizedMessage(501587); // Whom do you wish to incite? - from.Target = new InternalFirstTarget(from, instrument); - } - - private class InternalFirstTarget : Target - { - private readonly BaseInstrument m_Instrument; - - public InternalFirstTarget(Mobile from, BaseInstrument instrument) : base( - BaseInstrument.GetBardRange(from, SkillName.Provocation), false, TargetFlags.None) => - m_Instrument = instrument; - - protected override void OnTarget(Mobile from, object targeted) - { - from.RevealingAction(); - - if (targeted is BaseCreature creature && from.CanBeHarmful(creature, true)) + public static void Initialize() + { + SkillInfo.Table[(int)SkillName.Provocation].Callback = OnUse; + } + + public static TimeSpan OnUse(Mobile m) + { + m.RevealingAction(); + + BaseInstrument.PickInstrument(m, OnPickedInstrument); + + return TimeSpan.FromSeconds(1.0); // Cannot use another skill for 1 second + } + + public static void OnPickedInstrument(Mobile from, BaseInstrument instrument) { - if (!m_Instrument.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage( - 1062488); // The instrument you are trying to play is no longer in your backpack! - } - else if (creature.Controlled) - { - from.SendLocalizedMessage(501590); // They are too loyal to their master to be provoked. - } - else if (creature.IsParagon && BaseInstrument.GetBaseDifficulty(creature) >= 160.0) - { - from.SendLocalizedMessage(1049446); // You have no chance of provoking those creatures. - } - else - { from.RevealingAction(); - m_Instrument.PlayInstrumentWell(from); - from.SendLocalizedMessage( - 1008085); // You play your music and your target becomes angered. Whom do you wish them to attack? - from.Target = new InternalSecondTarget(from, m_Instrument, creature); - } + from.SendLocalizedMessage(501587); // Whom do you wish to incite? + from.Target = new InternalFirstTarget(from, instrument); } - else + + private class InternalFirstTarget : Target { - from.SendLocalizedMessage(501589); // You can't incite that! - } - } - } + private readonly BaseInstrument m_Instrument; - private class InternalSecondTarget : Target - { - private readonly BaseCreature m_Creature; - private readonly BaseInstrument m_Instrument; + public InternalFirstTarget(Mobile from, BaseInstrument instrument) : base( + BaseInstrument.GetBardRange(from, SkillName.Provocation), + false, + TargetFlags.None + ) => + m_Instrument = instrument; - public InternalSecondTarget(Mobile from, BaseInstrument instrument, BaseCreature creature) : base( - BaseInstrument.GetBardRange(from, SkillName.Provocation), false, TargetFlags.None) - { - m_Instrument = instrument; - m_Creature = creature; - } - - protected override void OnTarget(Mobile from, object targeted) - { - from.RevealingAction(); - - if (targeted is BaseCreature creature) - { - if (!m_Instrument.IsChildOf(from.Backpack)) - { - from.SendLocalizedMessage( - 1062488); // The instrument you are trying to play is no longer in your backpack! - } - else if (m_Creature.Unprovokable) - { - from.SendLocalizedMessage(1049446); // You have no chance of provoking those creatures. - } - else if (creature.Unprovokable && !(creature is DemonKnight)) - { - from.SendLocalizedMessage(1049446); // You have no chance of provoking those creatures. - } - else if (m_Creature.Map != creature.Map || !m_Creature.InRange(creature, - BaseInstrument.GetBardRange(from, SkillName.Provocation))) - { - from.SendLocalizedMessage( - 1049450); // The creatures you are trying to provoke are too far away from each other for your music to have an effect. - } - else if (m_Creature != creature) - { - from.NextSkillTime = Core.TickCount + 10000; - - double diff = (m_Instrument.GetDifficultyFor(m_Creature) + m_Instrument.GetDifficultyFor(creature)) * - 0.5 - 5.0; - double music = from.Skills.Musicianship.Value; - - if (music > 100.0) - diff -= (music - 100.0) * 0.5; - - if (from.CanBeHarmful(m_Creature, true) && from.CanBeHarmful(creature, true)) + protected override void OnTarget(Mobile from, object targeted) { - if (!BaseInstrument.CheckMusicianship(from)) - { - from.NextSkillTime = Core.TickCount + 5000; - from.SendLocalizedMessage(500612); // You play poorly, and there is no effect. - m_Instrument.PlayInstrumentBadly(from); - m_Instrument.ConsumeUse(from); - } - else - { - // from.DoHarmful( m_Creature ); - // from.DoHarmful( creature ); + from.RevealingAction(); - if (!from.CheckTargetSkill(SkillName.Provocation, creature, diff - 25.0, diff + 25.0)) + if (targeted is BaseCreature creature && from.CanBeHarmful(creature, true)) { - from.NextSkillTime = Core.TickCount + 5000; - from.SendLocalizedMessage(501599); // Your music fails to incite enough anger. - m_Instrument.PlayInstrumentBadly(from); - m_Instrument.ConsumeUse(from); + if (!m_Instrument.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage( + 1062488 + ); // The instrument you are trying to play is no longer in your backpack! + } + else if (creature.Controlled) + { + from.SendLocalizedMessage(501590); // They are too loyal to their master to be provoked. + } + else if (creature.IsParagon && BaseInstrument.GetBaseDifficulty(creature) >= 160.0) + { + from.SendLocalizedMessage(1049446); // You have no chance of provoking those creatures. + } + else + { + from.RevealingAction(); + m_Instrument.PlayInstrumentWell(from); + from.SendLocalizedMessage( + 1008085 + ); // You play your music and your target becomes angered. Whom do you wish them to attack? + from.Target = new InternalSecondTarget(from, m_Instrument, creature); + } } else { - from.SendLocalizedMessage(501602); // Your music succeeds, as you start a fight. - m_Instrument.PlayInstrumentWell(from); - m_Instrument.ConsumeUse(from); - m_Creature.Provoke(from, creature, true); + from.SendLocalizedMessage(501589); // You can't incite that! } - } } - } - else - { - from.SendLocalizedMessage(501593); // You can't tell someone to attack themselves! - } } - else + + private class InternalSecondTarget : Target { - from.SendLocalizedMessage(501589); // You can't incite that! + private readonly BaseCreature m_Creature; + private readonly BaseInstrument m_Instrument; + + public InternalSecondTarget(Mobile from, BaseInstrument instrument, BaseCreature creature) : base( + BaseInstrument.GetBardRange(from, SkillName.Provocation), + false, + TargetFlags.None + ) + { + m_Instrument = instrument; + m_Creature = creature; + } + + protected override void OnTarget(Mobile from, object targeted) + { + from.RevealingAction(); + + if (targeted is BaseCreature creature) + { + if (!m_Instrument.IsChildOf(from.Backpack)) + { + from.SendLocalizedMessage( + 1062488 + ); // The instrument you are trying to play is no longer in your backpack! + } + else if (m_Creature.Unprovokable) + { + from.SendLocalizedMessage(1049446); // You have no chance of provoking those creatures. + } + else if (creature.Unprovokable && !(creature is DemonKnight)) + { + from.SendLocalizedMessage(1049446); // You have no chance of provoking those creatures. + } + else if (m_Creature.Map != creature.Map || !m_Creature.InRange( + creature, + BaseInstrument.GetBardRange(from, SkillName.Provocation) + )) + { + from.SendLocalizedMessage( + 1049450 + ); // The creatures you are trying to provoke are too far away from each other for your music to have an effect. + } + else if (m_Creature != creature) + { + from.NextSkillTime = Core.TickCount + 10000; + + var diff = (m_Instrument.GetDifficultyFor(m_Creature) + m_Instrument.GetDifficultyFor(creature)) * + 0.5 - 5.0; + var music = from.Skills.Musicianship.Value; + + if (music > 100.0) + diff -= (music - 100.0) * 0.5; + + if (from.CanBeHarmful(m_Creature, true) && from.CanBeHarmful(creature, true)) + { + if (!BaseInstrument.CheckMusicianship(from)) + { + from.NextSkillTime = Core.TickCount + 5000; + from.SendLocalizedMessage(500612); // You play poorly, and there is no effect. + m_Instrument.PlayInstrumentBadly(from); + m_Instrument.ConsumeUse(from); + } + else + { + // from.DoHarmful( m_Creature ); + // from.DoHarmful( creature ); + + if (!from.CheckTargetSkill(SkillName.Provocation, creature, diff - 25.0, diff + 25.0)) + { + from.NextSkillTime = Core.TickCount + 5000; + from.SendLocalizedMessage(501599); // Your music fails to incite enough anger. + m_Instrument.PlayInstrumentBadly(from); + m_Instrument.ConsumeUse(from); + } + else + { + from.SendLocalizedMessage(501602); // Your music succeeds, as you start a fight. + m_Instrument.PlayInstrumentWell(from); + m_Instrument.ConsumeUse(from); + m_Creature.Provoke(from, creature, true); + } + } + } + } + else + { + from.SendLocalizedMessage(501593); // You can't tell someone to attack themselves! + } + } + else + { + from.SendLocalizedMessage(501589); // You can't incite that! + } + } } - } } - } } diff --git a/Projects/UOContent/Skills/RemoveTrap.cs b/Projects/UOContent/Skills/RemoveTrap.cs index 21ae5536a..0dc418327 100644 --- a/Projects/UOContent/Skills/RemoveTrap.cs +++ b/Projects/UOContent/Skills/RemoveTrap.cs @@ -6,124 +6,134 @@ using Server.Targeting; namespace Server.SkillHandlers { - public static class RemoveTrap - { - public static void Initialize() + public static class RemoveTrap { - SkillInfo.Table[(int)SkillName.RemoveTrap].Callback = OnUse; - } - - public static TimeSpan OnUse(Mobile m) - { - if (m.Skills.Lockpicking.Value < 50) - { - m.SendLocalizedMessage(502366); // You do not know enough about locks. Become better at picking locks. - } - else if (m.Skills.DetectHidden.Value < 50) - { - m.SendLocalizedMessage(502367); // You are not perceptive enough. Become better at detect hidden. - } - else - { - m.Target = new InternalTarget(); - - m.SendLocalizedMessage(502368); // Which trap will you attempt to disarm? - } - - return TimeSpan.FromSeconds(10.0); // 10 second delay before being able to re-use a skill - } - - private class InternalTarget : Target - { - public InternalTarget() : base(2, false, TargetFlags.None) - { - } - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is Mobile) + public static void Initialize() { - from.SendLocalizedMessage(502816); // You feel that such an action would be inappropriate + SkillInfo.Table[(int)SkillName.RemoveTrap].Callback = OnUse; } - else if (targeted is TrappableContainer targ) + + public static TimeSpan OnUse(Mobile m) { - from.Direction = from.GetDirectionTo(targ); - - if (targ.TrapType == TrapType.None) - { - from.SendLocalizedMessage(502373); // That doesn't appear to be trapped - return; - } - - from.PlaySound(0x241); - - if (from.CheckTargetSkill(SkillName.RemoveTrap, targ, targ.TrapPower, targ.TrapPower + 30)) - { - targ.TrapPower = 0; - targ.TrapLevel = 0; - targ.TrapType = TrapType.None; - from.SendLocalizedMessage(502377); // You successfully render the trap harmless - } - else - { - from.SendLocalizedMessage(502372); // You fail to disarm the trap... but you don't set it off - } - } - else if (targeted is BaseFactionTrap trap) - { - Faction faction = Faction.Find(from); - FactionTrapRemovalKit kit = from.Backpack?.FindItemByType(); - - bool isOwner = trap.Placer == from || trap.Faction?.IsCommander(from) == true; - - if (faction == null) - { - from.SendLocalizedMessage( - 1010538); // You may not disarm faction traps unless you are in an opposing faction - } - else if (trap.Faction != null && faction == trap.Faction && !isOwner) - { - from.SendLocalizedMessage(1010537); // You may not disarm traps set by your own faction! - } - else if (!isOwner && kit == null) - { - from.SendLocalizedMessage( - 1042530); // You must have a trap removal kit at the base level of your pack to disarm a faction trap. - } - else - { - if ((Core.ML && isOwner) || (from.CheckTargetSkill(SkillName.RemoveTrap, trap, 80.0, 100.0) && - from.CheckTargetSkill(SkillName.Tinkering, trap, 80.0, 100.0))) + if (m.Skills.Lockpicking.Value < 50) { - from.PrivateOverheadMessage(MessageType.Regular, trap.MessageHue, trap.DisarmMessage, - from.NetState); - - if (!isOwner) - { - int silver = faction.AwardSilver(from, trap.SilverFromDisarm); - - if (silver > 0) - from.SendLocalizedMessage(1008113, true, - silver.ToString( - "N0")); // You have been granted faction silver for removing the enemy trap : - } - - trap.Delete(); + m.SendLocalizedMessage(502366); // You do not know enough about locks. Become better at picking locks. + } + else if (m.Skills.DetectHidden.Value < 50) + { + m.SendLocalizedMessage(502367); // You are not perceptive enough. Become better at detect hidden. } else { - from.SendLocalizedMessage(502372); // You fail to disarm the trap... but you don't set it off + m.Target = new InternalTarget(); + + m.SendLocalizedMessage(502368); // Which trap will you attempt to disarm? } - if (!isOwner) - kit.ConsumeCharge(from); - } + return TimeSpan.FromSeconds(10.0); // 10 second delay before being able to re-use a skill } - else + + private class InternalTarget : Target { - from.SendLocalizedMessage(502373); // That doesn't appear to be trapped + public InternalTarget() : base(2, false, TargetFlags.None) + { + } + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted is Mobile) + { + from.SendLocalizedMessage(502816); // You feel that such an action would be inappropriate + } + else if (targeted is TrappableContainer targ) + { + from.Direction = from.GetDirectionTo(targ); + + if (targ.TrapType == TrapType.None) + { + from.SendLocalizedMessage(502373); // That doesn't appear to be trapped + return; + } + + from.PlaySound(0x241); + + if (from.CheckTargetSkill(SkillName.RemoveTrap, targ, targ.TrapPower, targ.TrapPower + 30)) + { + targ.TrapPower = 0; + targ.TrapLevel = 0; + targ.TrapType = TrapType.None; + from.SendLocalizedMessage(502377); // You successfully render the trap harmless + } + else + { + from.SendLocalizedMessage(502372); // You fail to disarm the trap... but you don't set it off + } + } + else if (targeted is BaseFactionTrap trap) + { + var faction = Faction.Find(from); + var kit = from.Backpack?.FindItemByType(); + + var isOwner = trap.Placer == from || trap.Faction?.IsCommander(from) == true; + + if (faction == null) + { + from.SendLocalizedMessage( + 1010538 + ); // You may not disarm faction traps unless you are in an opposing faction + } + else if (trap.Faction != null && faction == trap.Faction && !isOwner) + { + from.SendLocalizedMessage(1010537); // You may not disarm traps set by your own faction! + } + else if (!isOwner && kit == null) + { + from.SendLocalizedMessage( + 1042530 + ); // You must have a trap removal kit at the base level of your pack to disarm a faction trap. + } + else + { + if (Core.ML && isOwner || @from.CheckTargetSkill(SkillName.RemoveTrap, trap, 80.0, 100.0) && + @from.CheckTargetSkill(SkillName.Tinkering, trap, 80.0, 100.0)) + { + from.PrivateOverheadMessage( + MessageType.Regular, + trap.MessageHue, + trap.DisarmMessage, + from.NetState + ); + + if (!isOwner) + { + var silver = faction.AwardSilver(from, trap.SilverFromDisarm); + + if (silver > 0) + from.SendLocalizedMessage( + 1008113, + true, + silver.ToString( + "N0" + ) + ); // You have been granted faction silver for removing the enemy trap : + } + + trap.Delete(); + } + else + { + from.SendLocalizedMessage(502372); // You fail to disarm the trap... but you don't set it off + } + + if (!isOwner) + kit.ConsumeCharge(from); + } + } + else + { + from.SendLocalizedMessage(502373); // That doesn't appear to be trapped + } + } } - } } - } } diff --git a/Projects/UOContent/Skills/Snooping.cs b/Projects/UOContent/Skills/Snooping.cs index 93f04eab1..fceecf898 100644 --- a/Projects/UOContent/Skills/Snooping.cs +++ b/Projects/UOContent/Skills/Snooping.cs @@ -1,98 +1,97 @@ using Server.Items; using Server.Misc; using Server.Mobiles; -using Server.Network; using Server.Regions; namespace Server.SkillHandlers { - public static class Snooping - { - public static void Configure() + public static class Snooping { - Container.SnoopHandler = Container_Snoop; + public static void Configure() + { + Container.SnoopHandler = Container_Snoop; + } + + public static bool CheckSnoopAllowed(Mobile from, Mobile to) + { + var map = from.Map; + + if (to.Player) + return from.CanBeHarmful(to, false, true); // normal restrictions + + if ((map?.Rules & MapRules.HarmfulRestrictions) == 0) + return true; // felucca you can snoop anybody + + var reg = to.Region.GetRegion(); + + if (reg?.IsDisabled() != true) + return true; // not in town? we can snoop any npc + + return !to.Body.IsHuman || to is BaseCreature cret && (cret.AlwaysAttackable || cret.AlwaysMurderer); + } + + public static void Container_Snoop(Container cont, Mobile from) + { + if (from.AccessLevel > AccessLevel.Player || from.InRange(cont.GetWorldLocation(), 1)) + { + var root = cont.RootParent as Mobile; + + if (root?.Alive == false) + return; + + if (root?.AccessLevel > AccessLevel.Player && from.AccessLevel == AccessLevel.Player) + { + from.SendLocalizedMessage(500209); // You can not peek into the container. + return; + } + + if (root?.AccessLevel == AccessLevel.Player && !CheckSnoopAllowed(from, root)) + { + from.SendLocalizedMessage(1001018); // You cannot perform negative acts on your target. + return; + } + + if (root?.AccessLevel == AccessLevel.Player && + from.Skills.Snooping.Value < Utility.Random(100)) + { + var map = from.Map; + + if (map != null) + { + var message = $"You notice {from.Name} attempting to peek into {root.Name}'s belongings."; + + var eable = map.GetClientsInRange(from.Location, 8); + + foreach (var ns in eable) + if (ns.Mobile != from) + ns.Mobile.SendMessage(message); + + eable.Free(); + } + } + + if (from.AccessLevel == AccessLevel.Player) + Titles.AwardKarma(from, -4, true); + + if (from.AccessLevel > AccessLevel.Player || from.CheckTargetSkill(SkillName.Snooping, cont, 0.0, 100.0)) + { + if (cont is TrappableContainer container && container.ExecuteTrap(from)) + return; + + cont.DisplayTo(from); + } + else + { + from.SendLocalizedMessage(500210); // You failed to peek into the container. + + if (from.Skills.Hiding.Value / 2 < Utility.Random(100)) + from.RevealingAction(); + } + } + else + { + from.SendLocalizedMessage(500446); // That is too far away. + } + } } - - public static bool CheckSnoopAllowed(Mobile from, Mobile to) - { - Map map = from.Map; - - if (to.Player) - return from.CanBeHarmful(to, false, true); // normal restrictions - - if ((map?.Rules & MapRules.HarmfulRestrictions) == 0) - return true; // felucca you can snoop anybody - - GuardedRegion reg = to.Region.GetRegion(); - - if (reg?.IsDisabled() != true) - return true; // not in town? we can snoop any npc - - return !to.Body.IsHuman || (to is BaseCreature cret && (cret.AlwaysAttackable || cret.AlwaysMurderer)); - } - - public static void Container_Snoop(Container cont, Mobile from) - { - if (from.AccessLevel > AccessLevel.Player || from.InRange(cont.GetWorldLocation(), 1)) - { - Mobile root = cont.RootParent as Mobile; - - if (root?.Alive == false) - return; - - if (root?.AccessLevel > AccessLevel.Player && from.AccessLevel == AccessLevel.Player) - { - from.SendLocalizedMessage(500209); // You can not peek into the container. - return; - } - - if (root?.AccessLevel == AccessLevel.Player && !CheckSnoopAllowed(from, root)) - { - from.SendLocalizedMessage(1001018); // You cannot perform negative acts on your target. - return; - } - - if (root?.AccessLevel == AccessLevel.Player && - from.Skills.Snooping.Value < Utility.Random(100)) - { - Map map = from.Map; - - if (map != null) - { - string message = $"You notice {from.Name} attempting to peek into {root.Name}'s belongings."; - - IPooledEnumerable eable = map.GetClientsInRange(from.Location, 8); - - foreach (NetState ns in eable) - if (ns.Mobile != from) - ns.Mobile.SendMessage(message); - - eable.Free(); - } - } - - if (from.AccessLevel == AccessLevel.Player) - Titles.AwardKarma(from, -4, true); - - if (from.AccessLevel > AccessLevel.Player || from.CheckTargetSkill(SkillName.Snooping, cont, 0.0, 100.0)) - { - if (cont is TrappableContainer container && container.ExecuteTrap(from)) - return; - - cont.DisplayTo(from); - } - else - { - from.SendLocalizedMessage(500210); // You failed to peek into the container. - - if (from.Skills.Hiding.Value / 2 < Utility.Random(100)) - from.RevealingAction(); - } - } - else - { - from.SendLocalizedMessage(500446); // That is too far away. - } - } - } } diff --git a/Projects/UOContent/Skills/SpiritSpeak.cs b/Projects/UOContent/Skills/SpiritSpeak.cs index e698d7ded..73953f8fc 100644 --- a/Projects/UOContent/Skills/SpiritSpeak.cs +++ b/Projects/UOContent/Skills/SpiritSpeak.cs @@ -6,180 +6,180 @@ using Server.Spells; namespace Server.SkillHandlers { - public static class SpiritSpeak - { - public static void Initialize() + public static class SpiritSpeak { - SkillInfo.Table[32].Callback = OnUse; - } - - public static TimeSpan OnUse(Mobile m) - { - if (Core.AOS) - { - Spell spell = new SpiritSpeakSpell(m); - - spell.Cast(); - - if (spell.IsCasting) - return TimeSpan.FromSeconds(5.0); - - return TimeSpan.Zero; - } - - m.RevealingAction(); - - if (m.CheckSkill(SkillName.SpiritSpeak, 0, 100)) - { - if (!m.CanHearGhosts) + public static void Initialize() { - Timer t = new SpiritSpeakTimer(m); - double secs = m.Skills.SpiritSpeak.Base / 50; - secs *= 90; - if (secs < 15) - secs = 15; - - t.Delay = TimeSpan.FromSeconds(secs); // 15seconds to 3 minutes - t.Start(); - m.CanHearGhosts = true; + SkillInfo.Table[32].Callback = OnUse; } - m.PlaySound(0x24A); - m.SendLocalizedMessage(502444); // You contact the neitherworld. - } - else - { - m.SendLocalizedMessage(502443); // You fail to contact the neitherworld. - m.CanHearGhosts = false; - } - - return TimeSpan.FromSeconds(1.0); - } - - private class SpiritSpeakTimer : Timer - { - private readonly Mobile m_Owner; - - public SpiritSpeakTimer(Mobile m) : base(TimeSpan.FromMinutes(2.0)) - { - m_Owner = m; - Priority = TimerPriority.FiveSeconds; - } - - protected override void OnTick() - { - m_Owner.CanHearGhosts = false; - m_Owner.SendLocalizedMessage(502445); // You feel your contact with the neitherworld fading. - } - } - - private class SpiritSpeakSpell : Spell - { - private static readonly SpellInfo m_Info = new SpellInfo("Spirit Speak", "", 269); - - public SpiritSpeakSpell(Mobile caster) : base(caster, null, m_Info) - { - } - - public override bool BlockedByHorrificBeast => false; - - public override bool ClearHandsOnCast => false; - - public override double CastDelayFastScalar => 0; - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.0); - - public override bool CheckNextSpellTime => false; - - public override int GetMana() => 0; - - public override void OnCasterHurt() - { - if (IsCasting) - Disturb(DisturbType.Hurt, false, true); - } - - public override bool ConsumeReagents() => true; - - public override bool CheckFizzle() => true; - - public override void OnDisturb(DisturbType type, bool message) - { - Caster.NextSkillTime = Core.TickCount; - - base.OnDisturb(type, message); - } - - public override bool CheckDisturb(DisturbType type, bool checkFirst, bool resistable) - { - if (type == DisturbType.EquipRequest || type == DisturbType.UseRequest) - return false; - - return true; - } - - public override void SayMantra() - { - // Anh Mi Sah Ko - Caster.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1062074, "", false); - Caster.PlaySound(0x24A); - } - - public override void OnCast() - { - IPooledEnumerable eable = Caster.GetItemsInRange(3); - Corpse toChannel = eable.FirstOrDefault(corpse => !corpse.Channeled); - eable.Free(); - - int min = 1 + (int)(Caster.Skills.SpiritSpeak.Value * 0.25); - int max = min + 4; - - int mana, number; - - if (toChannel != null) + public static TimeSpan OnUse(Mobile m) { - mana = 0; - number = 1061287; // You channel energy from a nearby corpse to heal your wounds. - } - else - { - mana = 10; - number = 1061286; // You channel your own spiritual energy to heal your wounds. - } - - if (Caster.Mana < mana) - { - Caster.SendLocalizedMessage(1061285); // You lack the mana required to use this skill. - } - else - { - Caster.CheckSkill(SkillName.SpiritSpeak, 0.0, 120.0); - - if (Utility.RandomDouble() > Caster.Skills.SpiritSpeak.Value / 100.0) - { - Caster.SendLocalizedMessage(502443); // You fail your attempt at contacting the netherworld. - } - else - { - if (toChannel != null) + if (Core.AOS) { - toChannel.Channeled = true; - toChannel.Hue = 0x835; + Spell spell = new SpiritSpeakSpell(m); + + spell.Cast(); + + if (spell.IsCasting) + return TimeSpan.FromSeconds(5.0); + + return TimeSpan.Zero; } - Caster.Mana -= mana; - Caster.SendLocalizedMessage(number); + m.RevealingAction(); - if (min > max) - min = max; + if (m.CheckSkill(SkillName.SpiritSpeak, 0, 100)) + { + if (!m.CanHearGhosts) + { + Timer t = new SpiritSpeakTimer(m); + var secs = m.Skills.SpiritSpeak.Base / 50; + secs *= 90; + if (secs < 15) + secs = 15; - Caster.Hits += Utility.RandomMinMax(min, max); + t.Delay = TimeSpan.FromSeconds(secs); // 15seconds to 3 minutes + t.Start(); + m.CanHearGhosts = true; + } - Caster.FixedParticles(0x375A, 1, 15, 9501, 2100, 4, EffectLayer.Waist); - } + m.PlaySound(0x24A); + m.SendLocalizedMessage(502444); // You contact the neitherworld. + } + else + { + m.SendLocalizedMessage(502443); // You fail to contact the neitherworld. + m.CanHearGhosts = false; + } + + return TimeSpan.FromSeconds(1.0); } - FinishSequence(); - } + private class SpiritSpeakTimer : Timer + { + private readonly Mobile m_Owner; + + public SpiritSpeakTimer(Mobile m) : base(TimeSpan.FromMinutes(2.0)) + { + m_Owner = m; + Priority = TimerPriority.FiveSeconds; + } + + protected override void OnTick() + { + m_Owner.CanHearGhosts = false; + m_Owner.SendLocalizedMessage(502445); // You feel your contact with the neitherworld fading. + } + } + + private class SpiritSpeakSpell : Spell + { + private static readonly SpellInfo m_Info = new SpellInfo("Spirit Speak", "", 269); + + public SpiritSpeakSpell(Mobile caster) : base(caster, null, m_Info) + { + } + + public override bool BlockedByHorrificBeast => false; + + public override bool ClearHandsOnCast => false; + + public override double CastDelayFastScalar => 0; + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.0); + + public override bool CheckNextSpellTime => false; + + public override int GetMana() => 0; + + public override void OnCasterHurt() + { + if (IsCasting) + Disturb(DisturbType.Hurt, false, true); + } + + public override bool ConsumeReagents() => true; + + public override bool CheckFizzle() => true; + + public override void OnDisturb(DisturbType type, bool message) + { + Caster.NextSkillTime = Core.TickCount; + + base.OnDisturb(type, message); + } + + public override bool CheckDisturb(DisturbType type, bool checkFirst, bool resistable) + { + if (type == DisturbType.EquipRequest || type == DisturbType.UseRequest) + return false; + + return true; + } + + public override void SayMantra() + { + // Anh Mi Sah Ko + Caster.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1062074, "", false); + Caster.PlaySound(0x24A); + } + + public override void OnCast() + { + var eable = Caster.GetItemsInRange(3); + var toChannel = eable.FirstOrDefault(corpse => !corpse.Channeled); + eable.Free(); + + var min = 1 + (int)(Caster.Skills.SpiritSpeak.Value * 0.25); + var max = min + 4; + + int mana, number; + + if (toChannel != null) + { + mana = 0; + number = 1061287; // You channel energy from a nearby corpse to heal your wounds. + } + else + { + mana = 10; + number = 1061286; // You channel your own spiritual energy to heal your wounds. + } + + if (Caster.Mana < mana) + { + Caster.SendLocalizedMessage(1061285); // You lack the mana required to use this skill. + } + else + { + Caster.CheckSkill(SkillName.SpiritSpeak, 0.0, 120.0); + + if (Utility.RandomDouble() > Caster.Skills.SpiritSpeak.Value / 100.0) + { + Caster.SendLocalizedMessage(502443); // You fail your attempt at contacting the netherworld. + } + else + { + if (toChannel != null) + { + toChannel.Channeled = true; + toChannel.Hue = 0x835; + } + + Caster.Mana -= mana; + Caster.SendLocalizedMessage(number); + + if (min > max) + min = max; + + Caster.Hits += Utility.RandomMinMax(min, max); + + Caster.FixedParticles(0x375A, 1, 15, 9501, 2100, 4, EffectLayer.Waist); + } + } + + FinishSequence(); + } + } } - } } diff --git a/Projects/UOContent/Skills/Stealing.cs b/Projects/UOContent/Skills/Stealing.cs index 789181b37..8fdaf7318 100644 --- a/Projects/UOContent/Skills/Stealing.cs +++ b/Projects/UOContent/Skills/Stealing.cs @@ -4,7 +4,6 @@ using Server.Engines.ConPVP; using Server.Factions; using Server.Items; using Server.Mobiles; -using Server.Network; using Server.Spells; using Server.Spells.Fifth; using Server.Spells.Ninjitsu; @@ -13,451 +12,469 @@ using Server.Targeting; namespace Server.SkillHandlers { - public static class Stealing - { - public static readonly bool ClassicMode = false; - public static readonly bool SuspendOnMurder = false; - - public static void Initialize() + public static class Stealing { - SkillInfo.Table[33].Callback = OnUse; - } + public static readonly bool ClassicMode = false; + public static readonly bool SuspendOnMurder = false; - public static bool IsInGuild(Mobile m) => m is PlayerMobile mobile && mobile.NpcGuild == NpcGuild.ThievesGuild; - - public static bool IsInnocentTo(Mobile from, Mobile to) => Notoriety.Compute(from, to) == Notoriety.Innocent; - - public static bool IsEmptyHanded(Mobile from) - { - if (from.FindItemOnLayer(Layer.OneHanded) != null) - return false; - - if (from.FindItemOnLayer(Layer.TwoHanded) != null) - return false; - - return true; - } - - public static TimeSpan OnUse(Mobile m) - { - if (!IsEmptyHanded(m)) - { - m.SendLocalizedMessage(1005584); // Both hands must be free to steal. - } - else if (m.Region.IsPartOf()) - { - m.SendMessage("You may not steal in this area."); - } - else - { - m.Target = new StealingTarget(m); - m.RevealingAction(); - - m.SendLocalizedMessage(502698); // Which item do you want to steal? - } - - return TimeSpan.FromSeconds(10.0); - } - - private class StealingTarget : Target - { - private readonly Mobile m_Thief; - - public StealingTarget(Mobile thief) : base(1, false, TargetFlags.None) - { - m_Thief = thief; - AllowNonlocal = true; - } - - private Item TryStealItem(Item toSteal, ref bool caught) - { - Item stolen = null; - - IEntity root = toSteal.RootParent; - Mobile mobRoot = root as Mobile; - - StealableArtifactsSpawner.StealableInstance si = null; - if (toSteal.Parent == null || !toSteal.Movable) - si = StealableArtifactsSpawner.GetStealableInstance(toSteal); - - if (!IsEmptyHanded(m_Thief)) + public static void Initialize() { - m_Thief.SendLocalizedMessage(1005584); // Both hands must be free to steal. + SkillInfo.Table[33].Callback = OnUse; } - else if (m_Thief.Region.IsPartOf()) - { - m_Thief.SendMessage("You may not steal in this area."); - } - else if (mobRoot?.Player == true && !IsInGuild(m_Thief)) - { - m_Thief.SendLocalizedMessage(1005596); // You must be in the thieves guild to steal from other players. - } - else if (SuspendOnMurder && mobRoot?.Player == true && IsInGuild(m_Thief) && - m_Thief.Kills > 0) - { - m_Thief.SendLocalizedMessage(502706); // You are currently suspended from the thieves guild. - } - else if (root is BaseVendor vendor && vendor.IsInvulnerable) - { - m_Thief.SendLocalizedMessage(1005598); // You can't steal from shopkeepers. - } - else if (root is PlayerVendor) - { - m_Thief.SendLocalizedMessage(502709); // You can't steal from vendors. - } - else if (!m_Thief.CanSee(toSteal)) - { - m_Thief.SendLocalizedMessage(500237); // Target can not be seen. - } - else if (m_Thief.Backpack?.CheckHold(m_Thief, toSteal, false, true) != true) - { - m_Thief.SendLocalizedMessage(1048147); // Your backpack can't hold anything else. - } - else if (toSteal is Sigil sig) - { - PlayerState pl = PlayerState.Find(m_Thief); - Faction faction = pl?.Faction; - if (!m_Thief.InRange(sig.GetWorldLocation(), 1)) - { - m_Thief.SendLocalizedMessage(502703); // You must be standing next to an item to steal it. - } - else if (root != null) // not on the ground - { - m_Thief.SendLocalizedMessage(502710); // You can't steal that! - } - else if (faction != null) - { - if (!m_Thief.CanBeginAction()) - { - m_Thief.SendLocalizedMessage(1010581); // You cannot steal the sigil when you are incognito - } - else if (DisguiseTimers.IsDisguised(m_Thief)) - { - m_Thief.SendLocalizedMessage(1010583); // You cannot steal the sigil while disguised - } - else if (!m_Thief.CanBeginAction()) - { - m_Thief.SendLocalizedMessage(1010582); // You cannot steal the sigil while polymorphed - } - else if (TransformationSpellHelper.UnderTransformation(m_Thief)) - { - m_Thief.SendLocalizedMessage(1061622); // You cannot steal the sigil while in that form. - } - else if (AnimalForm.UnderTransformation(m_Thief)) - { - m_Thief.SendLocalizedMessage(1063222); // You cannot steal the sigil while mimicking an animal. - } - else if (pl.IsLeaving) - { - m_Thief.SendLocalizedMessage( - 1005589); // You are currently quitting a faction and cannot steal the town sigil - } - else if (sig.IsBeingCorrupted && sig.LastMonolith.Faction == faction) - { - m_Thief.SendLocalizedMessage(1005590); // You cannot steal your own sigil - } - else if (sig.IsPurifying) - { - m_Thief.SendLocalizedMessage(1005592); // You cannot steal this sigil until it has been purified - } - else if (m_Thief.CheckTargetSkill(SkillName.Stealing, toSteal, 80.0, 80.0)) - { - if (Sigil.ExistsOn(m_Thief)) - { - m_Thief.SendLocalizedMessage( - 1010258); // The sigil has gone back to its home location because you already have a sigil. - } - else if (m_Thief?.Backpack.CheckHold(m_Thief, sig, false, true) != true) - { - m_Thief.SendLocalizedMessage( - 1010259); // The sigil has gone home because your backpack is full - } - else - { - if (sig.IsBeingCorrupted) - sig.GraceStart = DateTime.UtcNow; // begin grace period + public static bool IsInGuild(Mobile m) => m is PlayerMobile mobile && mobile.NpcGuild == NpcGuild.ThievesGuild; - m_Thief.SendLocalizedMessage(1010586); // YOU STOLE THE SIGIL!!! (woah, calm down now) + public static bool IsInnocentTo(Mobile from, Mobile to) => Notoriety.Compute(from, to) == Notoriety.Innocent; - if (sig.LastMonolith?.Sigil != null) + public static bool IsEmptyHanded(Mobile from) + { + if (from.FindItemOnLayer(Layer.OneHanded) != null) + return false; + + if (from.FindItemOnLayer(Layer.TwoHanded) != null) + return false; + + return true; + } + + public static TimeSpan OnUse(Mobile m) + { + if (!IsEmptyHanded(m)) + { + m.SendLocalizedMessage(1005584); // Both hands must be free to steal. + } + else if (m.Region.IsPartOf()) + { + m.SendMessage("You may not steal in this area."); + } + else + { + m.Target = new StealingTarget(m); + m.RevealingAction(); + + m.SendLocalizedMessage(502698); // Which item do you want to steal? + } + + return TimeSpan.FromSeconds(10.0); + } + + private class StealingTarget : Target + { + private readonly Mobile m_Thief; + + public StealingTarget(Mobile thief) : base(1, false, TargetFlags.None) + { + m_Thief = thief; + AllowNonlocal = true; + } + + private Item TryStealItem(Item toSteal, ref bool caught) + { + Item stolen = null; + + var root = toSteal.RootParent; + var mobRoot = root as Mobile; + + StealableArtifactsSpawner.StealableInstance si = null; + if (toSteal.Parent == null || !toSteal.Movable) + si = StealableArtifactsSpawner.GetStealableInstance(toSteal); + + if (!IsEmptyHanded(m_Thief)) { - sig.LastMonolith.Sigil = null; - sig.LastStolen = DateTime.UtcNow; + m_Thief.SendLocalizedMessage(1005584); // Both hands must be free to steal. + } + else if (m_Thief.Region.IsPartOf()) + { + m_Thief.SendMessage("You may not steal in this area."); + } + else if (mobRoot?.Player == true && !IsInGuild(m_Thief)) + { + m_Thief.SendLocalizedMessage(1005596); // You must be in the thieves guild to steal from other players. + } + else if (SuspendOnMurder && mobRoot?.Player == true && IsInGuild(m_Thief) && + m_Thief.Kills > 0) + { + m_Thief.SendLocalizedMessage(502706); // You are currently suspended from the thieves guild. + } + else if (root is BaseVendor vendor && vendor.IsInvulnerable) + { + m_Thief.SendLocalizedMessage(1005598); // You can't steal from shopkeepers. + } + else if (root is PlayerVendor) + { + m_Thief.SendLocalizedMessage(502709); // You can't steal from vendors. + } + else if (!m_Thief.CanSee(toSteal)) + { + m_Thief.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (m_Thief.Backpack?.CheckHold(m_Thief, toSteal, false, true) != true) + { + m_Thief.SendLocalizedMessage(1048147); // Your backpack can't hold anything else. + } + else if (toSteal is Sigil sig) + { + var pl = PlayerState.Find(m_Thief); + var faction = pl?.Faction; + + if (!m_Thief.InRange(sig.GetWorldLocation(), 1)) + { + m_Thief.SendLocalizedMessage(502703); // You must be standing next to an item to steal it. + } + else if (root != null) // not on the ground + { + m_Thief.SendLocalizedMessage(502710); // You can't steal that! + } + else if (faction != null) + { + if (!m_Thief.CanBeginAction()) + { + m_Thief.SendLocalizedMessage(1010581); // You cannot steal the sigil when you are incognito + } + else if (DisguiseTimers.IsDisguised(m_Thief)) + { + m_Thief.SendLocalizedMessage(1010583); // You cannot steal the sigil while disguised + } + else if (!m_Thief.CanBeginAction()) + { + m_Thief.SendLocalizedMessage(1010582); // You cannot steal the sigil while polymorphed + } + else if (TransformationSpellHelper.UnderTransformation(m_Thief)) + { + m_Thief.SendLocalizedMessage(1061622); // You cannot steal the sigil while in that form. + } + else if (AnimalForm.UnderTransformation(m_Thief)) + { + m_Thief.SendLocalizedMessage(1063222); // You cannot steal the sigil while mimicking an animal. + } + else if (pl.IsLeaving) + { + m_Thief.SendLocalizedMessage( + 1005589 + ); // You are currently quitting a faction and cannot steal the town sigil + } + else if (sig.IsBeingCorrupted && sig.LastMonolith.Faction == faction) + { + m_Thief.SendLocalizedMessage(1005590); // You cannot steal your own sigil + } + else if (sig.IsPurifying) + { + m_Thief.SendLocalizedMessage(1005592); // You cannot steal this sigil until it has been purified + } + else if (m_Thief.CheckTargetSkill(SkillName.Stealing, toSteal, 80.0, 80.0)) + { + if (Sigil.ExistsOn(m_Thief)) + { + m_Thief.SendLocalizedMessage( + 1010258 + ); // The sigil has gone back to its home location because you already have a sigil. + } + else if (m_Thief?.Backpack.CheckHold(m_Thief, sig, false, true) != true) + { + m_Thief.SendLocalizedMessage( + 1010259 + ); // The sigil has gone home because your backpack is full + } + else + { + if (sig.IsBeingCorrupted) + sig.GraceStart = DateTime.UtcNow; // begin grace period + + m_Thief.SendLocalizedMessage(1010586); // YOU STOLE THE SIGIL!!! (woah, calm down now) + + if (sig.LastMonolith?.Sigil != null) + { + sig.LastMonolith.Sigil = null; + sig.LastStolen = DateTime.UtcNow; + } + + return sig; + } + } + else + { + m_Thief.SendLocalizedMessage(1005594); // You do not have enough skill to steal the sigil + } + } + else + { + m_Thief.SendLocalizedMessage(1005588); // You must join a faction to do that + } + } + else if (si == null && (toSteal.Parent == null || !toSteal.Movable)) + { + m_Thief.SendLocalizedMessage(502710); // You can't steal that! + } + else if (toSteal.LootType == LootType.Newbied || toSteal.CheckBlessed(mobRoot)) + { + m_Thief.SendLocalizedMessage(502710); // You can't steal that! + } + else if (Core.AOS && si == null && toSteal is Container) + { + m_Thief.SendLocalizedMessage(502710); // You can't steal that! + } + else if (!m_Thief.InRange(toSteal.GetWorldLocation(), 1)) + { + m_Thief.SendLocalizedMessage(502703); // You must be standing next to an item to steal it. + } + else if (si != null && m_Thief.Skills.Stealing.Value < 100.0) + { + m_Thief.SendLocalizedMessage( + 1060025, + "", + 0x66D + ); // You're not skilled enough to attempt the theft of this item. + } + else if (toSteal.Parent is Mobile) + { + m_Thief.SendLocalizedMessage(1005585); // You cannot steal items which are equipped. + } + else if (root == m_Thief) + { + m_Thief.SendLocalizedMessage(502704); // You catch yourself red-handed. + } + else if (mobRoot?.AccessLevel > AccessLevel.Player) + { + m_Thief.SendLocalizedMessage(502710); // You can't steal that! + } + else if (mobRoot != null && !m_Thief.CanBeHarmful(mobRoot)) + { + } + else if (root is Corpse) + { + m_Thief.SendLocalizedMessage(502710); // You can't steal that! + } + else + { + var w = toSteal.Weight + toSteal.TotalWeight; + + if (w > 10) + { + m_Thief.SendMessage("That is too heavy to steal."); + } + else + { + if (toSteal.Stackable && toSteal.Amount > 1) + { + var maxAmount = Math.Clamp( + (int)(m_Thief.Skills.Stealing.Value / 10.0 / toSteal.Weight), + 1, + toSteal.Amount + ); + + var amount = Utility.RandomMinMax(1, maxAmount); + + if (amount >= toSteal.Amount) + { + var pileWeight = (int)Math.Ceiling(toSteal.Weight * toSteal.Amount); + pileWeight *= 10; + + if (m_Thief.CheckTargetSkill( + SkillName.Stealing, + toSteal, + pileWeight - 22.5, + pileWeight + 27.5 + )) + stolen = toSteal; + } + else + { + var pileWeight = (int)Math.Ceiling(toSteal.Weight * amount); + pileWeight *= 10; + + if (m_Thief.CheckTargetSkill( + SkillName.Stealing, + toSteal, + pileWeight - 22.5, + pileWeight + 27.5 + )) + stolen = Mobile.LiftItemDupe(toSteal, toSteal.Amount - amount) ?? toSteal; + } + } + else + { + var iw = (int)Math.Ceiling(w); + iw *= 10; + + if (m_Thief.CheckTargetSkill(SkillName.Stealing, toSteal, iw - 22.5, iw + 27.5)) + stolen = toSteal; + } + + if (stolen != null) + { + m_Thief.SendLocalizedMessage(502724); // You successfully steal the item. + + if (si != null) + { + toSteal.Movable = true; + si.Item = null; + } + } + else + { + m_Thief.SendLocalizedMessage(502723); // You fail to steal the item. + } + + caught = m_Thief.Skills.Stealing.Value < Utility.Random(150); + } } - return sig; - } + return stolen; } - else + + protected override void OnTarget(Mobile from, object target) { - m_Thief.SendLocalizedMessage(1005594); // You do not have enough skill to steal the sigil - } - } - else - { - m_Thief.SendLocalizedMessage(1005588); // You must join a faction to do that - } - } - else if (si == null && (toSteal.Parent == null || !toSteal.Movable)) - { - m_Thief.SendLocalizedMessage(502710); // You can't steal that! - } - else if (toSteal.LootType == LootType.Newbied || toSteal.CheckBlessed(mobRoot)) - { - m_Thief.SendLocalizedMessage(502710); // You can't steal that! - } - else if (Core.AOS && si == null && toSteal is Container) - { - m_Thief.SendLocalizedMessage(502710); // You can't steal that! - } - else if (!m_Thief.InRange(toSteal.GetWorldLocation(), 1)) - { - m_Thief.SendLocalizedMessage(502703); // You must be standing next to an item to steal it. - } - else if (si != null && m_Thief.Skills.Stealing.Value < 100.0) - { - m_Thief.SendLocalizedMessage(1060025, "", - 0x66D); // You're not skilled enough to attempt the theft of this item. - } - else if (toSteal.Parent is Mobile) - { - m_Thief.SendLocalizedMessage(1005585); // You cannot steal items which are equipped. - } - else if (root == m_Thief) - { - m_Thief.SendLocalizedMessage(502704); // You catch yourself red-handed. - } - else if (mobRoot?.AccessLevel > AccessLevel.Player) - { - m_Thief.SendLocalizedMessage(502710); // You can't steal that! - } - else if (mobRoot != null && !m_Thief.CanBeHarmful(mobRoot)) - { - } - else if (root is Corpse) - { - m_Thief.SendLocalizedMessage(502710); // You can't steal that! - } - else - { - double w = toSteal.Weight + toSteal.TotalWeight; + from.RevealingAction(); - if (w > 10) - { - m_Thief.SendMessage("That is too heavy to steal."); - } - else - { - if (toSteal.Stackable && toSteal.Amount > 1) + Item stolen = null; + IEntity root = null; + var caught = false; + + if (target is Item item) + { + root = item.RootParent; + stolen = TryStealItem(item, ref caught); + } + else if (target is Mobile mobile) + { + var pack = mobile.Backpack; + + if (pack?.Items.Count > 0) + { + root = mobile; + stolen = TryStealItem(pack.Items.RandomElement(), ref caught); + } + } + else + { + m_Thief.SendLocalizedMessage(502710); // You can't steal that! + } + + var mobRoot = root as Mobile; + + if (stolen != null) + { + from.AddToBackpack(stolen); + + if (!(stolen is Container || stolen.Stackable)) + StolenItem.Add(stolen, m_Thief, mobRoot); + } + + var corpse = root as Corpse; + + if (caught) + { + if (root == null || corpse?.IsCriminalAction(m_Thief) == true) + { + m_Thief.CriminalAction(false); + } + else if (mobRoot != null) + { + if (!IsInGuild(mobRoot) && IsInnocentTo(m_Thief, mobRoot)) + m_Thief.CriminalAction(false); + + var message = $"You notice {m_Thief.Name} trying to steal from {mobRoot.Name}."; + + foreach (var ns in m_Thief.GetClientsInRange(8)) + if (ns.Mobile != m_Thief) + ns.Mobile.SendMessage(message); + } + } + else if (corpse?.IsCriminalAction(m_Thief) == true) + { + m_Thief.CriminalAction(false); + } + + if (mobRoot?.Player == true && m_Thief is PlayerMobile pm && + IsInnocentTo(pm, mobRoot) && !IsInGuild(mobRoot)) + { + pm.PermaFlags.Add(mobRoot); + pm.Delta(MobileDelta.Noto); + } + } + } + } + + public class StolenItem + { + public static readonly TimeSpan StealTime = TimeSpan.FromMinutes(2.0); + + private static readonly Queue m_Queue = new Queue(); + + public StolenItem(Item stolen, Mobile thief, Mobile victim) + { + Stolen = stolen; + Thief = thief; + Victim = victim; + + Expires = DateTime.UtcNow + StealTime; + } + + public Item Stolen { get; } + + public Mobile Thief { get; } + + public Mobile Victim { get; } + + public DateTime Expires { get; private set; } + + public bool IsExpired => DateTime.UtcNow >= Expires; + + public static void Add(Item item, Mobile thief, Mobile victim) + { + Clean(); + + m_Queue.Enqueue(new StolenItem(item, thief, victim)); + } + + public static bool IsStolen(Item item) + { + Mobile victim = null; + + return IsStolen(item, ref victim); + } + + public static bool IsStolen(Item item, ref Mobile victim) + { + Clean(); + + foreach (var si in m_Queue) + if (si.Stolen == item && !si.IsExpired) + { + victim = si.Victim; + return true; + } + + return false; + } + + public static void ReturnOnDeath(Mobile killed, Container corpse) + { + Clean(); + + foreach (var si in m_Queue) + if (si.Stolen.RootParent == corpse && si.Victim != null && !si.IsExpired) + { + if (si.Victim.AddToBackpack(si.Stolen)) + si.Victim.SendLocalizedMessage(1010464); // the item that was stolen is returned to you. + else + si.Victim.SendLocalizedMessage(1010463); // the item that was stolen from you falls to the ground. + + si.Expires = DateTime.UtcNow; // such a hack + } + } + + public static void Clean() + { + while (m_Queue.Count > 0) { - int maxAmount = Math.Clamp((int)(m_Thief.Skills.Stealing.Value / 10.0 / toSteal.Weight), 1, toSteal.Amount); + var si = m_Queue.Peek(); - int amount = Utility.RandomMinMax(1, maxAmount); - - if (amount >= toSteal.Amount) - { - int pileWeight = (int)Math.Ceiling(toSteal.Weight * toSteal.Amount); - pileWeight *= 10; - - if (m_Thief.CheckTargetSkill(SkillName.Stealing, toSteal, pileWeight - 22.5, - pileWeight + 27.5)) - stolen = toSteal; - } - else - { - int pileWeight = (int)Math.Ceiling(toSteal.Weight * amount); - pileWeight *= 10; - - if (m_Thief.CheckTargetSkill(SkillName.Stealing, toSteal, pileWeight - 22.5, - pileWeight + 27.5)) - stolen = Mobile.LiftItemDupe(toSteal, toSteal.Amount - amount) ?? toSteal; - } + if (si.IsExpired) + m_Queue.Dequeue(); + else + break; } - else - { - int iw = (int)Math.Ceiling(w); - iw *= 10; - - if (m_Thief.CheckTargetSkill(SkillName.Stealing, toSteal, iw - 22.5, iw + 27.5)) - stolen = toSteal; - } - - if (stolen != null) - { - m_Thief.SendLocalizedMessage(502724); // You successfully steal the item. - - if (si != null) - { - toSteal.Movable = true; - si.Item = null; - } - } - else - { - m_Thief.SendLocalizedMessage(502723); // You fail to steal the item. - } - - caught = m_Thief.Skills.Stealing.Value < Utility.Random(150); - } - } - - return stolen; - } - - protected override void OnTarget(Mobile from, object target) - { - from.RevealingAction(); - - Item stolen = null; - IEntity root = null; - bool caught = false; - - if (target is Item item) - { - root = item.RootParent; - stolen = TryStealItem(item, ref caught); - } - else if (target is Mobile mobile) - { - Container pack = mobile.Backpack; - - if (pack?.Items.Count > 0) - { - root = mobile; - stolen = TryStealItem(pack.Items.RandomElement(), ref caught); - } - } - else - { - m_Thief.SendLocalizedMessage(502710); // You can't steal that! - } - - Mobile mobRoot = root as Mobile; - - if (stolen != null) - { - from.AddToBackpack(stolen); - - if (!(stolen is Container || stolen.Stackable)) - StolenItem.Add(stolen, m_Thief, mobRoot); - } - - Corpse corpse = root as Corpse; - - if (caught) - { - if (root == null || corpse?.IsCriminalAction(m_Thief) == true) - { - m_Thief.CriminalAction(false); - } - else if (mobRoot != null) - { - if (!IsInGuild(mobRoot) && IsInnocentTo(m_Thief, mobRoot)) - m_Thief.CriminalAction(false); - - string message = $"You notice {m_Thief.Name} trying to steal from {mobRoot.Name}."; - - foreach (NetState ns in m_Thief.GetClientsInRange(8)) - if (ns.Mobile != m_Thief) - ns.Mobile.SendMessage(message); - } - } - else if (corpse?.IsCriminalAction(m_Thief) == true) - { - m_Thief.CriminalAction(false); - } - - if (mobRoot?.Player == true && m_Thief is PlayerMobile pm && - IsInnocentTo(pm, mobRoot) && !IsInGuild(mobRoot)) - { - pm.PermaFlags.Add(mobRoot); - pm.Delta(MobileDelta.Noto); - } - } - } - } - - public class StolenItem - { - public static readonly TimeSpan StealTime = TimeSpan.FromMinutes(2.0); - - private static readonly Queue m_Queue = new Queue(); - - public StolenItem(Item stolen, Mobile thief, Mobile victim) - { - Stolen = stolen; - Thief = thief; - Victim = victim; - - Expires = DateTime.UtcNow + StealTime; - } - - public Item Stolen { get; } - - public Mobile Thief { get; } - - public Mobile Victim { get; } - - public DateTime Expires { get; private set; } - - public bool IsExpired => DateTime.UtcNow >= Expires; - - public static void Add(Item item, Mobile thief, Mobile victim) - { - Clean(); - - m_Queue.Enqueue(new StolenItem(item, thief, victim)); - } - - public static bool IsStolen(Item item) - { - Mobile victim = null; - - return IsStolen(item, ref victim); - } - - public static bool IsStolen(Item item, ref Mobile victim) - { - Clean(); - - foreach (StolenItem si in m_Queue) - if (si.Stolen == item && !si.IsExpired) - { - victim = si.Victim; - return true; - } - - return false; - } - - public static void ReturnOnDeath(Mobile killed, Container corpse) - { - Clean(); - - foreach (StolenItem si in m_Queue) - if (si.Stolen.RootParent == corpse && si.Victim != null && !si.IsExpired) - { - if (si.Victim.AddToBackpack(si.Stolen)) - si.Victim.SendLocalizedMessage(1010464); // the item that was stolen is returned to you. - else - si.Victim.SendLocalizedMessage(1010463); // the item that was stolen from you falls to the ground. - - si.Expires = DateTime.UtcNow; // such a hack } } - - public static void Clean() - { - while (m_Queue.Count > 0) - { - StolenItem si = m_Queue.Peek(); - - if (si.IsExpired) - m_Queue.Dequeue(); - else - break; - } - } - } } diff --git a/Projects/UOContent/Skills/Stealth.cs b/Projects/UOContent/Skills/Stealth.cs index ebf276c06..1dfd846d3 100644 --- a/Projects/UOContent/Skills/Stealth.cs +++ b/Projects/UOContent/Skills/Stealth.cs @@ -4,105 +4,109 @@ using Server.Mobiles; namespace Server.SkillHandlers { - // Stealth cannot be static because its used as a generic for CanBeginAction. + // Stealth cannot be static because its used as a generic for CanBeginAction. #pragma warning disable CA1052 // Static holder types should be Static or NotInheritable - public class Stealth - { - public static double HidingRequirement => Core.ML ? 30.0 : Core.SE ? 50.0 : 80.0; - - // TODO: Move to configuration - public static int[,] ArmorTable { get; } = + public class Stealth { - // Gorget Glove Helmet Arms Legs Chest Shield - /* Cloth */ { 0, 0, 0, 0, 0, 0, 0 }, - /* Leather */ { 0, 0, 0, 0, 0, 0, 0 }, - /* Studded */ { 2, 2, 0, 4, 6, 10, 0 }, - /* Bone */ { 0, 5, 10, 10, 15, 25, 0 }, - /* Spined */ { 0, 0, 0, 0, 0, 0, 0 }, - /* Horned */ { 0, 0, 0, 0, 0, 0, 0 }, - /* Barbed */ { 0, 0, 0, 0, 0, 0, 0 }, - /* Ring */ { 0, 5, 0, 10, 15, 25, 0 }, - /* Chain */ { 0, 0, 10, 0, 15, 25, 0 }, - /* Plate */ { 5, 5, 10, 10, 15, 25, 0 }, - /* Dragon */ { 0, 5, 10, 10, 15, 25, 0 } - }; + public static double HidingRequirement => Core.ML ? 30.0 : + Core.SE ? 50.0 : 80.0; - public static void Initialize() - { - SkillInfo.Table[(int)SkillName.Stealth].Callback = OnUse; - } - - public static int GetArmorRating(Mobile m) - { - if (!Core.AOS) - return (int)m.ArmorRating; - - int ar = 0; - - for (int i = 0; i < m.Items.Count; i++) - { - if (!(m.Items[i] is BaseArmor armor)) - continue; - - int materialType = (int)armor.MaterialType; - int bodyPosition = (int)armor.BodyPosition; - - if (materialType >= ArmorTable.GetLength(0) || bodyPosition >= ArmorTable.GetLength(1)) - continue; - - if (armor.ArmorAttributes.MageArmor == 0) - ar += ArmorTable[materialType, bodyPosition]; - } - - return ar; - } - - public static TimeSpan OnUse(Mobile m) - { - if (!m.Hidden) - { - m.SendLocalizedMessage(502725); // You must hide first - } - else if (m.Skills.Hiding.Base < HidingRequirement) - { - m.SendLocalizedMessage(502726); // You are not hidden well enough. Become better at hiding. - m.RevealingAction(); - } - else if (!m.CanBeginAction()) - { - m.SendLocalizedMessage(1063086); // You cannot use this skill right now. - m.RevealingAction(); - } - else - { - int armorRating = GetArmorRating(m); - - if (armorRating >= (Core.AOS ? 42 : 26)) // I have a hunch '42' was chosen cause someone's a fan of DNA + // TODO: Move to configuration + public static int[,] ArmorTable { get; } = { - m.SendLocalizedMessage(502727); // You could not hope to move quietly wearing this much armor. - m.RevealingAction(); - } - else if (m.CheckSkill(SkillName.Stealth, -20.0 + armorRating * 2, - (Core.AOS ? 60.0 : 80.0) + armorRating * 2)) + // Gorget Glove Helmet Arms Legs Chest Shield + /* Cloth */ { 0, 0, 0, 0, 0, 0, 0 }, + /* Leather */ { 0, 0, 0, 0, 0, 0, 0 }, + /* Studded */ { 2, 2, 0, 4, 6, 10, 0 }, + /* Bone */ { 0, 5, 10, 10, 15, 25, 0 }, + /* Spined */ { 0, 0, 0, 0, 0, 0, 0 }, + /* Horned */ { 0, 0, 0, 0, 0, 0, 0 }, + /* Barbed */ { 0, 0, 0, 0, 0, 0, 0 }, + /* Ring */ { 0, 5, 0, 10, 15, 25, 0 }, + /* Chain */ { 0, 0, 10, 0, 15, 25, 0 }, + /* Plate */ { 5, 5, 10, 10, 15, 25, 0 }, + /* Dragon */ { 0, 5, 10, 10, 15, 25, 0 } + }; + + public static void Initialize() { - m.AllowedStealthSteps = Math.Max((int)(m.Skills.Stealth.Value / (Core.AOS ? 5.0 : 10.0)), 1); - - if (m is PlayerMobile pm) - pm.IsStealthing = true; - - m.SendLocalizedMessage(502730); // You begin to move quietly. - - return TimeSpan.FromSeconds(10.0); + SkillInfo.Table[(int)SkillName.Stealth].Callback = OnUse; } - else + + public static int GetArmorRating(Mobile m) { - m.SendLocalizedMessage(502731); // You fail in your attempt to move unnoticed. - m.RevealingAction(); - } - } + if (!Core.AOS) + return (int)m.ArmorRating; - return TimeSpan.FromSeconds(10.0); + var ar = 0; + + for (var i = 0; i < m.Items.Count; i++) + { + if (!(m.Items[i] is BaseArmor armor)) + continue; + + var materialType = (int)armor.MaterialType; + var bodyPosition = (int)armor.BodyPosition; + + if (materialType >= ArmorTable.GetLength(0) || bodyPosition >= ArmorTable.GetLength(1)) + continue; + + if (armor.ArmorAttributes.MageArmor == 0) + ar += ArmorTable[materialType, bodyPosition]; + } + + return ar; + } + + public static TimeSpan OnUse(Mobile m) + { + if (!m.Hidden) + { + m.SendLocalizedMessage(502725); // You must hide first + } + else if (m.Skills.Hiding.Base < HidingRequirement) + { + m.SendLocalizedMessage(502726); // You are not hidden well enough. Become better at hiding. + m.RevealingAction(); + } + else if (!m.CanBeginAction()) + { + m.SendLocalizedMessage(1063086); // You cannot use this skill right now. + m.RevealingAction(); + } + else + { + var armorRating = GetArmorRating(m); + + if (armorRating >= (Core.AOS ? 42 : 26)) // I have a hunch '42' was chosen cause someone's a fan of DNA + { + m.SendLocalizedMessage(502727); // You could not hope to move quietly wearing this much armor. + m.RevealingAction(); + } + else if (m.CheckSkill( + SkillName.Stealth, + -20.0 + armorRating * 2, + (Core.AOS ? 60.0 : 80.0) + armorRating * 2 + )) + { + m.AllowedStealthSteps = Math.Max((int)(m.Skills.Stealth.Value / (Core.AOS ? 5.0 : 10.0)), 1); + + if (m is PlayerMobile pm) + pm.IsStealthing = true; + + m.SendLocalizedMessage(502730); // You begin to move quietly. + + return TimeSpan.FromSeconds(10.0); + } + else + { + m.SendLocalizedMessage(502731); // You fail in your attempt to move unnoticed. + m.RevealingAction(); + } + } + + return TimeSpan.FromSeconds(10.0); + } } - } #pragma warning restore CA1052 // Static holder types should be Static or NotInheritable } diff --git a/Projects/UOContent/Skills/TasteID.cs b/Projects/UOContent/Skills/TasteID.cs index 60781c69f..5d15dc16e 100644 --- a/Projects/UOContent/Skills/TasteID.cs +++ b/Projects/UOContent/Skills/TasteID.cs @@ -5,76 +5,76 @@ using Server.Targeting; namespace Server.SkillHandlers { - public static class TasteID - { - public static void Initialize() + public static class TasteID { - SkillInfo.Table[(int)SkillName.TasteID].Callback = OnUse; + public static void Initialize() + { + SkillInfo.Table[(int)SkillName.TasteID].Callback = OnUse; + } + + public static TimeSpan OnUse(Mobile m) + { + m.Target = new InternalTarget(); + + m.SendLocalizedMessage(502807); // What would you like to taste? + + return TimeSpan.FromSeconds(1.0); + } + + [PlayerVendorTarget] + private class InternalTarget : Target + { + public InternalTarget() : base(2, false, TargetFlags.None) => AllowNonlocal = true; + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted is Mobile) + { + from.SendLocalizedMessage(502816); // You feel that such an action would be inappropriate. + } + else if (targeted is Food food) + { + if (from.CheckTargetSkill(SkillName.TasteID, food, 0, 100)) + { + if (food.Poison != null) + food.SendLocalizedMessageTo(from, 1038284); // It appears to have poison smeared on it. + else + food.SendLocalizedMessageTo(from, 1010600); // You detect nothing unusual about this substance. + } + else + { + // Skill check failed + food.SendLocalizedMessageTo(from, 502823); // You cannot discern anything about this substance. + } + } + else if (targeted is BasePotion potion) + { + potion.SendLocalizedMessageTo(from, 502813); // You already know what kind of potion that is. + potion.SendLocalizedMessageTo(from, potion.LabelNumber); + } + else if (targeted is PotionKeg keg) + { + if (keg.Held <= 0) + { + keg.SendLocalizedMessageTo(from, 502228); // There is nothing in the keg to taste! + } + else + { + keg.SendLocalizedMessageTo(from, 502229); // You are already familiar with this keg's contents. + keg.SendLocalizedMessageTo(from, keg.LabelNumber); + } + } + else + { + // The target is not food or potion or potion keg. + from.SendLocalizedMessage(502820); // That's not something you can taste. + } + } + + protected override void OnTargetOutOfRange(Mobile from, object targeted) + { + from.SendLocalizedMessage(502815); // You are too far away to taste that. + } + } } - - public static TimeSpan OnUse(Mobile m) - { - m.Target = new InternalTarget(); - - m.SendLocalizedMessage(502807); // What would you like to taste? - - return TimeSpan.FromSeconds(1.0); - } - - [PlayerVendorTarget] - private class InternalTarget : Target - { - public InternalTarget() : base(2, false, TargetFlags.None) => AllowNonlocal = true; - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is Mobile) - { - from.SendLocalizedMessage(502816); // You feel that such an action would be inappropriate. - } - else if (targeted is Food food) - { - if (from.CheckTargetSkill(SkillName.TasteID, food, 0, 100)) - { - if (food.Poison != null) - food.SendLocalizedMessageTo(from, 1038284); // It appears to have poison smeared on it. - else - food.SendLocalizedMessageTo(from, 1010600); // You detect nothing unusual about this substance. - } - else - { - // Skill check failed - food.SendLocalizedMessageTo(from, 502823); // You cannot discern anything about this substance. - } - } - else if (targeted is BasePotion potion) - { - potion.SendLocalizedMessageTo(from, 502813); // You already know what kind of potion that is. - potion.SendLocalizedMessageTo(from, potion.LabelNumber); - } - else if (targeted is PotionKeg keg) - { - if (keg.Held <= 0) - { - keg.SendLocalizedMessageTo(from, 502228); // There is nothing in the keg to taste! - } - else - { - keg.SendLocalizedMessageTo(from, 502229); // You are already familiar with this keg's contents. - keg.SendLocalizedMessageTo(from, keg.LabelNumber); - } - } - else - { - // The target is not food or potion or potion keg. - from.SendLocalizedMessage(502820); // That's not something you can taste. - } - } - - protected override void OnTargetOutOfRange(Mobile from, object targeted) - { - from.SendLocalizedMessage(502815); // You are too far away to taste that. - } - } - } } diff --git a/Projects/UOContent/Skills/Tracking.cs b/Projects/UOContent/Skills/Tracking.cs index 44ec271df..7e1141c85 100644 --- a/Projects/UOContent/Skills/Tracking.cs +++ b/Projects/UOContent/Skills/Tracking.cs @@ -8,370 +8,376 @@ using Server.Spells.Necromancy; namespace Server.SkillHandlers { - public static class Tracking - { - private static readonly Dictionary m_Table = new Dictionary(); - - public static void Initialize() + public static class Tracking { - SkillInfo.Table[(int)SkillName.Tracking].Callback = OnUse; - } + private static readonly Dictionary m_Table = new Dictionary(); - public static TimeSpan OnUse(Mobile m) - { - m.SendLocalizedMessage(1011350); // What do you wish to track? - - m.CloseGump(); - m.CloseGump(); - m.SendGump(new TrackWhatGump(m)); - - return TimeSpan.FromSeconds(10.0); // 10 second delay before being able to re-use a skill - } - - public static void AddInfo(Mobile tracker, Mobile target) - { - TrackingInfo info = new TrackingInfo(tracker, target); - m_Table[tracker] = info; - } - - public static double GetStalkingBonus(Mobile tracker, Mobile target) - { - if (!m_Table.TryGetValue(tracker, out TrackingInfo info) || info.m_Target != target || info.m_Map != target.Map) - return 0.0; - - int xDelta = info.m_Location.X - target.X; - int yDelta = info.m_Location.Y - target.Y; - - double bonus = Math.Sqrt(xDelta * xDelta + yDelta * yDelta); - - m_Table.Remove(tracker); // Reset as of Pub 40, counting it as bug for Core.SE. - - return Core.ML ? Math.Min(bonus, 10 + tracker.Skills.Tracking.Value / 10) : bonus; - } - - public static void ClearTrackingInfo(Mobile tracker) - { - m_Table.Remove(tracker); - } - - public class TrackingInfo - { - public Point2D m_Location; - public Map m_Map; - public Mobile m_Target; - public Mobile m_Tracker; - - public TrackingInfo(Mobile tracker, Mobile target) - { - m_Tracker = tracker; - m_Target = target; - m_Location = new Point2D(target.X, target.Y); - m_Map = target.Map; - } - } - } - - public class TrackWhatGump : Gump - { - private readonly Mobile m_From; - private readonly bool m_Success; - - public TrackWhatGump(Mobile from) : base(20, 30) - { - m_From = from; - m_Success = from.CheckSkill(SkillName.Tracking, 0.0, 21.1); - - AddPage(0); - - AddBackground(0, 0, 440, 135, 5054); - - AddBackground(10, 10, 420, 75, 2620); - AddBackground(10, 85, 420, 25, 3000); - - AddItem(20, 20, 9682); - AddButton(20, 110, 4005, 4007, 1); - AddHtmlLocalized(20, 90, 100, 20, 1018087); // Animals - - AddItem(120, 20, 9607); - AddButton(120, 110, 4005, 4007, 2); - AddHtmlLocalized(120, 90, 100, 20, 1018088); // Monsters - - AddItem(220, 20, 8454); - AddButton(220, 110, 4005, 4007, 3); - AddHtmlLocalized(220, 90, 100, 20, 1018089); // Human NPCs - - AddItem(320, 20, 8455); - AddButton(320, 110, 4005, 4007, 4); - AddHtmlLocalized(320, 90, 100, 20, 1018090); // Players - } - - public override void OnResponse(NetState state, RelayInfo info) - { - if (info.ButtonID >= 1 && info.ButtonID <= 4) - TrackWhoGump.DisplayTo(m_Success, m_From, info.ButtonID - 1); - } - } - - public delegate bool TrackTypeDelegate(Mobile m); - - public class TrackWhoGump : Gump - { - private static readonly TrackTypeDelegate[] m_Delegates = - { - IsAnimal, - IsMonster, - IsHumanNPC, - IsPlayer - }; - - private readonly Mobile m_From; - - private readonly List m_List; - private readonly int m_Range; - - private TrackWhoGump(Mobile from, List list, int range) : base(20, 30) - { - m_From = from; - m_List = list; - m_Range = range; - - AddPage(0); - - AddBackground(0, 0, 440, 155, 5054); - - AddBackground(10, 10, 420, 75, 2620); - AddBackground(10, 85, 420, 45, 3000); - - if (list.Count > 4) - { - AddBackground(0, 155, 440, 155, 5054); - - AddBackground(10, 165, 420, 75, 2620); - AddBackground(10, 240, 420, 45, 3000); - - if (list.Count > 8) + public static void Initialize() { - AddBackground(0, 310, 440, 155, 5054); - - AddBackground(10, 320, 420, 75, 2620); - AddBackground(10, 395, 420, 45, 3000); + SkillInfo.Table[(int)SkillName.Tracking].Callback = OnUse; } - } - for (int i = 0; i < list.Count && i < 12; ++i) - { - Mobile m = list[i]; + public static TimeSpan OnUse(Mobile m) + { + m.SendLocalizedMessage(1011350); // What do you wish to track? - AddItem(20 + i % 4 * 100, 20 + i / 4 * 155, ShrinkTable.Lookup(m)); - AddButton(20 + i % 4 * 100, 130 + i / 4 * 155, 4005, 4007, i + 1); + m.CloseGump(); + m.CloseGump(); + m.SendGump(new TrackWhatGump(m)); - if (m.Name != null) - AddHtml(20 + i % 4 * 100, 90 + i / 4 * 155, 90, 40, m.Name); - } + return TimeSpan.FromSeconds(10.0); // 10 second delay before being able to re-use a skill + } + + public static void AddInfo(Mobile tracker, Mobile target) + { + var info = new TrackingInfo(tracker, target); + m_Table[tracker] = info; + } + + public static double GetStalkingBonus(Mobile tracker, Mobile target) + { + if (!m_Table.TryGetValue(tracker, out var info) || info.m_Target != target || info.m_Map != target.Map) + return 0.0; + + var xDelta = info.m_Location.X - target.X; + var yDelta = info.m_Location.Y - target.Y; + + var bonus = Math.Sqrt(xDelta * xDelta + yDelta * yDelta); + + m_Table.Remove(tracker); // Reset as of Pub 40, counting it as bug for Core.SE. + + return Core.ML ? Math.Min(bonus, 10 + tracker.Skills.Tracking.Value / 10) : bonus; + } + + public static void ClearTrackingInfo(Mobile tracker) + { + m_Table.Remove(tracker); + } + + public class TrackingInfo + { + public Point2D m_Location; + public Map m_Map; + public Mobile m_Target; + public Mobile m_Tracker; + + public TrackingInfo(Mobile tracker, Mobile target) + { + m_Tracker = tracker; + m_Target = target; + m_Location = new Point2D(target.X, target.Y); + m_Map = target.Map; + } + } } - public static void DisplayTo(bool success, Mobile from, int type) + public class TrackWhatGump : Gump { - if (!success) - { - from.SendLocalizedMessage(1018092); // You see no evidence of those in the area. - return; - } + private readonly Mobile m_From; + private readonly bool m_Success; - Map map = from.Map; + public TrackWhatGump(Mobile from) : base(20, 30) + { + m_From = from; + m_Success = from.CheckSkill(SkillName.Tracking, 0.0, 21.1); - if (map == null) - return; + AddPage(0); - TrackTypeDelegate check = m_Delegates[type]; + AddBackground(0, 0, 440, 135, 5054); - from.CheckSkill(SkillName.Tracking, 21.1, 100.0); // Passive gain + AddBackground(10, 10, 420, 75, 2620); + AddBackground(10, 85, 420, 25, 3000); - int range = 10 + (int)(from.Skills.Tracking.Value / 10); + AddItem(20, 20, 9682); + AddButton(20, 110, 4005, 4007, 1); + AddHtmlLocalized(20, 90, 100, 20, 1018087); // Animals - List list = from.GetMobilesInRange(range) - .Where(m => m != from && (!Core.AOS || m.Alive) && (!m.Hidden || m.AccessLevel == AccessLevel.Player || from.AccessLevel > m.AccessLevel) && check(m) && CheckDifficulty(from, m)) - .ToList(); + AddItem(120, 20, 9607); + AddButton(120, 110, 4005, 4007, 2); + AddHtmlLocalized(120, 90, 100, 20, 1018088); // Monsters - if (list.Count > 0) - { - list.Sort(new InternalSorter(from)); + AddItem(220, 20, 8454); + AddButton(220, 110, 4005, 4007, 3); + AddHtmlLocalized(220, 90, 100, 20, 1018089); // Human NPCs - from.SendGump(new TrackWhoGump(from, list, range)); - from.SendLocalizedMessage(1018093); // Select the one you would like to track. - } - else - { - if (type == 0) - from.SendLocalizedMessage(502991); // You see no evidence of animals in the area. - else if (type == 1) - from.SendLocalizedMessage(502993); // You see no evidence of creatures in the area. - else - from.SendLocalizedMessage(502995); // You see no evidence of people in the area. - } + AddItem(320, 20, 8455); + AddButton(320, 110, 4005, 4007, 4); + AddHtmlLocalized(320, 90, 100, 20, 1018090); // Players + } + + public override void OnResponse(NetState state, RelayInfo info) + { + if (info.ButtonID >= 1 && info.ButtonID <= 4) + TrackWhoGump.DisplayTo(m_Success, m_From, info.ButtonID - 1); + } } - // Tracking players uses tracking and detect hidden vs. hiding and stealth - private static bool CheckDifficulty(Mobile from, Mobile m) + public delegate bool TrackTypeDelegate(Mobile m); + + public class TrackWhoGump : Gump { - if (!Core.AOS || !m.Player) - return true; + private static readonly TrackTypeDelegate[] m_Delegates = + { + IsAnimal, + IsMonster, + IsHumanNPC, + IsPlayer + }; - int tracking = from.Skills.Tracking.Fixed; - int detectHidden = from.Skills.DetectHidden.Fixed; + private readonly Mobile m_From; - if (Core.ML && m.Race == Race.Elf) - tracking /= 2; // The 'Guide' says that it requires twice as Much tracking SKILL to track an elf. Not the total difficulty to track. + private readonly List m_List; + private readonly int m_Range; - int hiding = m.Skills.Hiding.Fixed; - int stealth = m.Skills.Stealth.Fixed; - int divisor = hiding + stealth; + private TrackWhoGump(Mobile from, List list, int range) : base(20, 30) + { + m_From = from; + m_List = list; + m_Range = range; - // Necromancy forms affect tracking difficulty - if (TransformationSpellHelper.UnderTransformation(m, typeof(HorrificBeastSpell))) - divisor -= 200; - else if (TransformationSpellHelper.UnderTransformation(m, typeof(VampiricEmbraceSpell)) && divisor < 500) - divisor = 500; - else if (TransformationSpellHelper.UnderTransformation(m, typeof(WraithFormSpell)) && divisor <= 2000) - divisor += 200; + AddPage(0); - int chance; - if (divisor > 0) - { - if (Core.SE) - chance = 50 * (tracking * 2 + detectHidden) / divisor; - else - chance = 50 * (tracking + detectHidden + 10 * Utility.RandomMinMax(1, 20)) / divisor; - } - else - { - chance = 100; - } + AddBackground(0, 0, 440, 155, 5054); - return chance > Utility.Random(100); + AddBackground(10, 10, 420, 75, 2620); + AddBackground(10, 85, 420, 45, 3000); + + if (list.Count > 4) + { + AddBackground(0, 155, 440, 155, 5054); + + AddBackground(10, 165, 420, 75, 2620); + AddBackground(10, 240, 420, 45, 3000); + + if (list.Count > 8) + { + AddBackground(0, 310, 440, 155, 5054); + + AddBackground(10, 320, 420, 75, 2620); + AddBackground(10, 395, 420, 45, 3000); + } + } + + for (var i = 0; i < list.Count && i < 12; ++i) + { + var m = list[i]; + + AddItem(20 + i % 4 * 100, 20 + i / 4 * 155, ShrinkTable.Lookup(m)); + AddButton(20 + i % 4 * 100, 130 + i / 4 * 155, 4005, 4007, i + 1); + + if (m.Name != null) + AddHtml(20 + i % 4 * 100, 90 + i / 4 * 155, 90, 40, m.Name); + } + } + + public static void DisplayTo(bool success, Mobile from, int type) + { + if (!success) + { + from.SendLocalizedMessage(1018092); // You see no evidence of those in the area. + return; + } + + var map = from.Map; + + if (map == null) + return; + + var check = m_Delegates[type]; + + from.CheckSkill(SkillName.Tracking, 21.1, 100.0); // Passive gain + + var range = 10 + (int)(from.Skills.Tracking.Value / 10); + + var list = from.GetMobilesInRange(range) + .Where( + m => m != from && (!Core.AOS || m.Alive) && + (!m.Hidden || m.AccessLevel == AccessLevel.Player || from.AccessLevel > m.AccessLevel) && + check(m) && CheckDifficulty(from, m) + ) + .ToList(); + + if (list.Count > 0) + { + list.Sort(new InternalSorter(from)); + + from.SendGump(new TrackWhoGump(from, list, range)); + from.SendLocalizedMessage(1018093); // Select the one you would like to track. + } + else + { + if (type == 0) + from.SendLocalizedMessage(502991); // You see no evidence of animals in the area. + else if (type == 1) + from.SendLocalizedMessage(502993); // You see no evidence of creatures in the area. + else + from.SendLocalizedMessage(502995); // You see no evidence of people in the area. + } + } + + // Tracking players uses tracking and detect hidden vs. hiding and stealth + private static bool CheckDifficulty(Mobile from, Mobile m) + { + if (!Core.AOS || !m.Player) + return true; + + var tracking = from.Skills.Tracking.Fixed; + var detectHidden = from.Skills.DetectHidden.Fixed; + + if (Core.ML && m.Race == Race.Elf) + tracking /= 2; // The 'Guide' says that it requires twice as Much tracking SKILL to track an elf. Not the total difficulty to track. + + var hiding = m.Skills.Hiding.Fixed; + var stealth = m.Skills.Stealth.Fixed; + var divisor = hiding + stealth; + + // Necromancy forms affect tracking difficulty + if (TransformationSpellHelper.UnderTransformation(m, typeof(HorrificBeastSpell))) + divisor -= 200; + else if (TransformationSpellHelper.UnderTransformation(m, typeof(VampiricEmbraceSpell)) && divisor < 500) + divisor = 500; + else if (TransformationSpellHelper.UnderTransformation(m, typeof(WraithFormSpell)) && divisor <= 2000) + divisor += 200; + + int chance; + if (divisor > 0) + { + if (Core.SE) + chance = 50 * (tracking * 2 + detectHidden) / divisor; + else + chance = 50 * (tracking + detectHidden + 10 * Utility.RandomMinMax(1, 20)) / divisor; + } + else + { + chance = 100; + } + + return chance > Utility.Random(100); + } + + private static bool IsAnimal(Mobile m) => !m.Player && m.Body.IsAnimal; + + private static bool IsMonster(Mobile m) => !m.Player && m.Body.IsMonster; + + private static bool IsHumanNPC(Mobile m) => !m.Player && m.Body.IsHuman; + + private static bool IsPlayer(Mobile m) => m.Player; + + public override void OnResponse(NetState state, RelayInfo info) + { + var index = info.ButtonID - 1; + + if (index >= 0 && index < m_List.Count && index < 12) + { + var m = m_List[index]; + + m_From.QuestArrow = new TrackArrow(m_From, m, m_Range * 2); + + if (Core.SE) + Tracking.AddInfo(m_From, m); + } + } + + private class InternalSorter : IComparer + { + private readonly Mobile m_From; + + public InternalSorter(Mobile from) => m_From = from; + + public int Compare(Mobile x, Mobile y) + { + if (x == null && y == null) + return 0; + if (x == null) + return -1; + if (y == null) + return 1; + + return m_From.GetDistanceToSqrt(x).CompareTo(m_From.GetDistanceToSqrt(y)); + } + } } - private static bool IsAnimal(Mobile m) => !m.Player && m.Body.IsAnimal; - - private static bool IsMonster(Mobile m) => !m.Player && m.Body.IsMonster; - - private static bool IsHumanNPC(Mobile m) => !m.Player && m.Body.IsHuman; - - private static bool IsPlayer(Mobile m) => m.Player; - - public override void OnResponse(NetState state, RelayInfo info) + public class TrackArrow : QuestArrow { - int index = info.ButtonID - 1; + private readonly Timer m_Timer; + private Mobile m_From; - if (index >= 0 && index < m_List.Count && index < 12) - { - Mobile m = m_List[index]; + public TrackArrow(Mobile from, Mobile target, int range) : base(from, target) + { + m_From = from; + m_Timer = new TrackTimer(from, target, range, this); + m_Timer.Start(); + } - m_From.QuestArrow = new TrackArrow(m_From, m, m_Range * 2); + public override void OnClick(bool rightClick) + { + if (rightClick) + { + Tracking.ClearTrackingInfo(m_From); - if (Core.SE) - Tracking.AddInfo(m_From, m); - } + m_From = null; + + Stop(); + } + } + + public override void OnStop() + { + m_Timer.Stop(); + + if (m_From != null) + { + Tracking.ClearTrackingInfo(m_From); + + m_From.SendLocalizedMessage(503177); // You have lost your quarry. + } + } } - private class InternalSorter : IComparer + public class TrackTimer : Timer { - private readonly Mobile m_From; + private readonly QuestArrow m_Arrow; + private readonly Mobile m_From; + private readonly int m_Range; + private readonly Mobile m_Target; + private int m_LastX, m_LastY; - public InternalSorter(Mobile from) => m_From = from; + public TrackTimer(Mobile from, Mobile target, int range, QuestArrow arrow) : base( + TimeSpan.FromSeconds(0.25), + TimeSpan.FromSeconds(2.5) + ) + { + m_From = from; + m_Target = target; + m_Range = range; - public int Compare(Mobile x, Mobile y) - { - if (x == null && y == null) - return 0; - if (x == null) - return -1; - if (y == null) - return 1; + m_Arrow = arrow; + } - return m_From.GetDistanceToSqrt(x).CompareTo(m_From.GetDistanceToSqrt(y)); - } + protected override void OnTick() + { + if (!m_Arrow.Running) + { + Stop(); + return; + } + + if (m_From.NetState == null || m_From.Deleted || m_Target.Deleted || m_From.Map != m_Target.Map || + !m_From.InRange(m_Target, m_Range) || m_Target.Hidden && m_Target.AccessLevel > m_From.AccessLevel) + { + m_Arrow.Stop(); + Stop(); + return; + } + + if (m_LastX != m_Target.X || m_LastY != m_Target.Y) + { + m_LastX = m_Target.X; + m_LastY = m_Target.Y; + + m_Arrow.Update(); + } + } } - } - - public class TrackArrow : QuestArrow - { - private Mobile m_From; - private readonly Timer m_Timer; - - public TrackArrow(Mobile from, Mobile target, int range) : base(from, target) - { - m_From = from; - m_Timer = new TrackTimer(from, target, range, this); - m_Timer.Start(); - } - - public override void OnClick(bool rightClick) - { - if (rightClick) - { - Tracking.ClearTrackingInfo(m_From); - - m_From = null; - - Stop(); - } - } - - public override void OnStop() - { - m_Timer.Stop(); - - if (m_From != null) - { - Tracking.ClearTrackingInfo(m_From); - - m_From.SendLocalizedMessage(503177); // You have lost your quarry. - } - } - } - - public class TrackTimer : Timer - { - private readonly QuestArrow m_Arrow; - private readonly Mobile m_From; - private readonly Mobile m_Target; - private int m_LastX, m_LastY; - private readonly int m_Range; - - public TrackTimer(Mobile from, Mobile target, int range, QuestArrow arrow) : base(TimeSpan.FromSeconds(0.25), - TimeSpan.FromSeconds(2.5)) - { - m_From = from; - m_Target = target; - m_Range = range; - - m_Arrow = arrow; - } - - protected override void OnTick() - { - if (!m_Arrow.Running) - { - Stop(); - return; - } - - if (m_From.NetState == null || m_From.Deleted || m_Target.Deleted || m_From.Map != m_Target.Map || - !m_From.InRange(m_Target, m_Range) || (m_Target.Hidden && m_Target.AccessLevel > m_From.AccessLevel)) - { - m_Arrow.Stop(); - Stop(); - return; - } - - if (m_LastX != m_Target.X || m_LastY != m_Target.Y) - { - m_LastX = m_Target.X; - m_LastY = m_Target.Y; - - m_Arrow.Update(); - } - } - } } diff --git a/Projects/UOContent/SpecialSystems/Engines/GiftGiving.cs b/Projects/UOContent/SpecialSystems/Engines/GiftGiving.cs index 8daf73707..98f9e8a12 100644 --- a/Projects/UOContent/SpecialSystems/Engines/GiftGiving.cs +++ b/Projects/UOContent/SpecialSystems/Engines/GiftGiving.cs @@ -4,73 +4,73 @@ using Server.Accounting; namespace Server.Misc { - public enum GiftResult - { - Backpack, - BankBox - } - - public class GiftGiving - { - private static readonly List m_Givers = new List(); - - public static void Register(GiftGiver giver) + public enum GiftResult { - m_Givers.Add(giver); + Backpack, + BankBox } - public static void Initialize() + public class GiftGiving { - EventSink.Login += EventSink_Login; + private static readonly List m_Givers = new List(); + + public static void Register(GiftGiver giver) + { + m_Givers.Add(giver); + } + + public static void Initialize() + { + EventSink.Login += EventSink_Login; + } + + private static void EventSink_Login(Mobile m) + { + if (!(m.Account is Account acct)) + return; + + var now = DateTime.UtcNow; + + for (var i = 0; i < m_Givers.Count; ++i) + { + var giver = m_Givers[i]; + + if (now < giver.Start || now >= giver.Finish) + continue; // not in the correct time frame + + if (acct.Created > giver.Start - giver.MinimumAge) + continue; // newly created account + + if (acct.LastLogin >= giver.Start) + continue; // already got one + + giver.DelayGiveGift(TimeSpan.FromSeconds(5.0), m); + } + + acct.LastLogin = now; + } } - private static void EventSink_Login(Mobile m) + public abstract class GiftGiver { - if (!(m.Account is Account acct)) - return; + public virtual TimeSpan MinimumAge => TimeSpan.FromDays(30.0); - DateTime now = DateTime.UtcNow; + public abstract DateTime Start { get; } + public abstract DateTime Finish { get; } + public abstract void GiveGift(Mobile mob); - for (int i = 0; i < m_Givers.Count; ++i) - { - GiftGiver giver = m_Givers[i]; + public virtual void DelayGiveGift(TimeSpan delay, Mobile mob) + { + Timer.DelayCall(delay, GiveGift, mob); + } - if (now < giver.Start || now >= giver.Finish) - continue; // not in the correct time frame + public virtual GiftResult GiveGift(Mobile mob, Item item) + { + if (mob.PlaceInBackpack(item) && !WeightOverloading.IsOverloaded(mob)) + return GiftResult.Backpack; - if (acct.Created > giver.Start - giver.MinimumAge) - continue; // newly created account - - if (acct.LastLogin >= giver.Start) - continue; // already got one - - giver.DelayGiveGift(TimeSpan.FromSeconds(5.0), m); - } - - acct.LastLogin = now; + mob.BankBox.DropItem(item); + return GiftResult.BankBox; + } } - } - - public abstract class GiftGiver - { - public virtual TimeSpan MinimumAge => TimeSpan.FromDays(30.0); - - public abstract DateTime Start { get; } - public abstract DateTime Finish { get; } - public abstract void GiveGift(Mobile mob); - - public virtual void DelayGiveGift(TimeSpan delay, Mobile mob) - { - Timer.DelayCall(delay, GiveGift, mob); - } - - public virtual GiftResult GiveGift(Mobile mob, Item item) - { - if (mob.PlaceInBackpack(item) && !WeightOverloading.IsOverloaded(mob)) - return GiftResult.Backpack; - - mob.BankBox.DropItem(item); - return GiftResult.BankBox; - } - } } diff --git a/Projects/UOContent/SpecialSystems/Engines/ItemFixes.cs b/Projects/UOContent/SpecialSystems/Engines/ItemFixes.cs index 805dfba21..45addc6b9 100644 --- a/Projects/UOContent/SpecialSystems/Engines/ItemFixes.cs +++ b/Projects/UOContent/SpecialSystems/Engines/ItemFixes.cs @@ -1,16 +1,16 @@ namespace Server.Misc { - public static class ItemFixes - { - public static void Initialize() + public static class ItemFixes { - // Missing NoShoot flags - TileData.ItemTable[0x2A0].Flags |= TileFlag.NoShoot; - TileData.ItemTable[0x3E0].Flags |= TileFlag.NoShoot; - TileData.ItemTable[0x3E1].Flags |= TileFlag.NoShoot; + public static void Initialize() + { + // Missing NoShoot flags + TileData.ItemTable[0x2A0].Flags |= TileFlag.NoShoot; + TileData.ItemTable[0x3E0].Flags |= TileFlag.NoShoot; + TileData.ItemTable[0x3E1].Flags |= TileFlag.NoShoot; - // Incorrect height - TileData.ItemTable[0x34D2].Height = 0; + // Incorrect height + TileData.ItemTable[0x34D2].Height = 0; + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/SpecialSystems/Engines/PreventInaccess.cs b/Projects/UOContent/SpecialSystems/Engines/PreventInaccess.cs index 286dbf8c9..e7c945525 100644 --- a/Projects/UOContent/SpecialSystems/Engines/PreventInaccess.cs +++ b/Projects/UOContent/SpecialSystems/Engines/PreventInaccess.cs @@ -2,80 +2,83 @@ using System.Collections.Generic; namespace Server.Misc { - /* - * This system prevents the inability for server staff to - * access their server due to data overflows during login. - * - * Whenever a staff character's NetState is disposed right after - * the login process, the character is moved to and logged out - * at a "safe" alternative. - * - * The location the character was moved from will be reported - * to the player upon the next successful login. - * - * This system does not affect non-staff players. - */ - public static class PreventInaccess - { - public static readonly bool Enabled = true; - - private static readonly LocationInfo[] m_Destinations = + /* + * This system prevents the inability for server staff to + * access their server due to data overflows during login. + * + * Whenever a staff character's NetState is disposed right after + * the login process, the character is moved to and logged out + * at a "safe" alternative. + * + * The location the character was moved from will be reported + * to the player upon the next successful login. + * + * This system does not affect non-staff players. + */ + public static class PreventInaccess { - new LocationInfo(new Point3D(5275, 1163, 0), Map.Felucca), // Jail - new LocationInfo(new Point3D(5275, 1163, 0), Map.Trammel), - new LocationInfo(new Point3D(5445, 1153, 0), Map.Felucca), // Green acres - new LocationInfo(new Point3D(5445, 1153, 0), Map.Trammel) - }; + public static readonly bool Enabled = true; - private static Dictionary m_MoveHistory; + private static readonly LocationInfo[] m_Destinations = + { + new LocationInfo(new Point3D(5275, 1163, 0), Map.Felucca), // Jail + new LocationInfo(new Point3D(5275, 1163, 0), Map.Trammel), + new LocationInfo(new Point3D(5445, 1153, 0), Map.Felucca), // Green acres + new LocationInfo(new Point3D(5445, 1153, 0), Map.Trammel) + }; - public static void Initialize() - { - m_MoveHistory = new Dictionary(); + private static Dictionary m_MoveHistory; - if (Enabled) - EventSink.Login += OnLogin; + public static void Initialize() + { + m_MoveHistory = new Dictionary(); + + if (Enabled) + EventSink.Login += OnLogin; + } + + public static void OnLogin(Mobile from) + { + if (from == null || from.AccessLevel < AccessLevel.Counselor) + return; + + if (HasDisconnected(from)) + { + if (!m_MoveHistory.ContainsKey(from)) + m_MoveHistory[from] = new LocationInfo(from.Location, from.Map); + + var dest = GetRandomDestination(); + + from.Location = dest.Location; + from.Map = dest.Map; + } + else if (m_MoveHistory.TryGetValue(from, out var orig)) + { + from.SendMessage( + "Your character was moved from {0} ({1}) due to a detected client crash.", + orig.Location, + orig.Map + ); + + m_MoveHistory.Remove(from); + } + } + + private static bool HasDisconnected(Mobile m) => m.NetState?.Connection == null; + + private static LocationInfo GetRandomDestination() => m_Destinations.RandomElement(); + + private class LocationInfo + { + public LocationInfo(Point3D loc, Map map) + { + Location = loc; + Map = map; + } + + public Point3D Location { get; } + + public Map Map { get; } + } } - - public static void OnLogin(Mobile from) - { - if (from == null || from.AccessLevel < AccessLevel.Counselor) - return; - - if (HasDisconnected(from)) - { - if (!m_MoveHistory.ContainsKey(from)) - m_MoveHistory[from] = new LocationInfo(from.Location, from.Map); - - LocationInfo dest = GetRandomDestination(); - - from.Location = dest.Location; - from.Map = dest.Map; - } - else if (m_MoveHistory.TryGetValue(from, out LocationInfo orig)) - { - from.SendMessage("Your character was moved from {0} ({1}) due to a detected client crash.", orig.Location, - orig.Map); - - m_MoveHistory.Remove(from); - } - } - - private static bool HasDisconnected(Mobile m) => m.NetState?.Connection == null; - - private static LocationInfo GetRandomDestination() => m_Destinations.RandomElement(); - - private class LocationInfo - { - public LocationInfo(Point3D loc, Map map) - { - Location = loc; - Map = map; - } - - public Point3D Location { get; } - - public Map Map { get; } - } - } } diff --git a/Projects/UOContent/SpecialSystems/Engines/TestCenter.cs b/Projects/UOContent/SpecialSystems/Engines/TestCenter.cs index 661809520..c853d6a77 100644 --- a/Projects/UOContent/SpecialSystems/Engines/TestCenter.cs +++ b/Projects/UOContent/SpecialSystems/Engines/TestCenter.cs @@ -6,229 +6,251 @@ using Server.Network; namespace Server.Misc { - public class TestCenter - { - public static bool Enabled { get; private set; } - - public static void Configure() + public class TestCenter { - Enabled = ServerConfiguration.GetOrUpdateSetting("testCenter.enable", false); - } + public static bool Enabled { get; private set; } - public static void Initialize() - { - // Register our speech handler - if (Enabled) - EventSink.Speech += EventSink_Speech; - } - - private static void EventSink_Speech(SpeechEventArgs args) - { - if (args.Handled) - return; - - if (Insensitive.StartsWith(args.Speech, "set")) - { - Mobile from = args.Mobile; - - string[] split = args.Speech.Split(' '); - - if (split.Length == 3) - try - { - string name = split[1]; - double value = Convert.ToDouble(split[2]); - - if (Insensitive.Equals(name, "str")) - ChangeStrength(from, (int)value); - else if (Insensitive.Equals(name, "dex")) - ChangeDexterity(from, (int)value); - else if (Insensitive.Equals(name, "int")) - ChangeIntelligence(from, (int)value); - else - ChangeSkill(from, name, value); - } - catch - { - // ignored - } - } - else if (Insensitive.Equals(args.Speech, "help")) - { - args.Mobile.SendGump(new TCHelpGump()); - args.Handled = true; - } - } - - private static void ChangeStrength(Mobile from, int value) - { - if (value < 10 || value > 125) - { - from.SendLocalizedMessage(1005628); // Stats range between 10 and 125. - } - else - { - if (value + from.RawDex + from.RawInt > from.StatCap) + public static void Configure() { - from.SendLocalizedMessage( - 1005629); // You can not exceed the stat cap. Try setting another stat lower first. + Enabled = ServerConfiguration.GetOrUpdateSetting("testCenter.enable", false); } - else + + public static void Initialize() { - from.RawStr = value; - from.SendLocalizedMessage(1005630); // Your stats have been adjusted. + // Register our speech handler + if (Enabled) + EventSink.Speech += EventSink_Speech; } - } - } - private static void ChangeDexterity(Mobile from, int value) - { - if (value < 10 || value > 125) - { - from.SendLocalizedMessage(1005628); // Stats range between 10 and 125. - } - else - { - if (from.RawStr + value + from.RawInt > from.StatCap) + private static void EventSink_Speech(SpeechEventArgs args) { - from.SendLocalizedMessage( - 1005629); // You can not exceed the stat cap. Try setting another stat lower first. - } - else - { - from.RawDex = value; - from.SendLocalizedMessage(1005630); // Your stats have been adjusted. - } - } - } + if (args.Handled) + return; - private static void ChangeIntelligence(Mobile from, int value) - { - if (value < 10 || value > 125) - { - from.SendLocalizedMessage(1005628); // Stats range between 10 and 125. - } - else - { - if (from.RawStr + from.RawDex + value > from.StatCap) - { - from.SendLocalizedMessage( - 1005629); // You can not exceed the stat cap. Try setting another stat lower first. - } - else - { - from.RawInt = value; - from.SendLocalizedMessage(1005630); // Your stats have been adjusted. - } - } - } - - private static void ChangeSkill(Mobile from, string name, double value) - { - if (!Enum.TryParse(name, true, out SkillName index) || (!Core.SE && (int)index > 51) || (!Core.AOS && (int)index > 48)) - { - from.SendLocalizedMessage(1005631); // You have specified an invalid skill to set. - return; - } - - Skill skill = from.Skills[index]; - - if (skill != null) - { - if (value < 0 || value > skill.Cap) - { - from.SendMessage($"Your skill in {skill.Info.Name} is capped at {skill.Cap:F1}."); - } - else - { - int newFixedPoint = (int)(value * 10.0); - int oldFixedPoint = skill.BaseFixedPoint; - - if (skill.Owner.Total - oldFixedPoint + newFixedPoint > skill.Owner.Cap) - from.SendMessage("You can not exceed the skill cap. Try setting another skill lower first."); - else - skill.BaseFixedPoint = newFixedPoint; - } - } - else - { - from.SendLocalizedMessage(1005631); // You have specified an invalid skill to set. - } - } - - public class TCHelpGump : Gump - { - public TCHelpGump() : base(40, 40) - { - AddPage(0); - AddBackground(0, 0, 160, 120, 5054); - - AddButton(10, 10, 0xFB7, 0xFB9, 1); - AddLabel(45, 10, 0x34, "ModernUO"); - - AddButton(10, 35, 0xFB7, 0xFB9, 2); - AddLabel(45, 35, 0x34, "List of skills"); - - AddButton(10, 60, 0xFB7, 0xFB9, 3); - AddLabel(45, 60, 0x34, "Command list"); - - AddButton(10, 85, 0xFB1, 0xFB3, 0); - AddLabel(45, 85, 0x34, "Close"); - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - switch (info.ButtonID) - { - case 1: // RunUO + if (Insensitive.StartsWith(args.Speech, "set")) { - sender.LaunchBrowser("https://github.com/runuo/"); - break; + var from = args.Mobile; + + var split = args.Speech.Split(' '); + + if (split.Length == 3) + try + { + var name = split[1]; + var value = Convert.ToDouble(split[2]); + + if (Insensitive.Equals(name, "str")) + ChangeStrength(from, (int)value); + else if (Insensitive.Equals(name, "dex")) + ChangeDexterity(from, (int)value); + else if (Insensitive.Equals(name, "int")) + ChangeIntelligence(from, (int)value); + else + ChangeSkill(from, name, value); + } + catch + { + // ignored + } } - case 2: // List of skills + else if (Insensitive.Equals(args.Speech, "help")) { - string[] strings = Enum.GetNames(typeof(SkillName)); + args.Mobile.SendGump(new TCHelpGump()); + args.Handled = true; + } + } - Array.Sort(strings); - - StringBuilder sb = new StringBuilder(); - - if (strings.Length > 0) - sb.Append(strings[0]); - - for (int i = 1; i < strings.Length; ++i) - { - string v = strings[i]; - - if (sb.Length + 1 + v.Length >= 256) + private static void ChangeStrength(Mobile from, int value) + { + if (value < 10 || value > 125) + { + from.SendLocalizedMessage(1005628); // Stats range between 10 and 125. + } + else + { + if (value + from.RawDex + from.RawInt > from.StatCap) { - sender.Send(new AsciiMessage(Server.Serial.MinusOne, -1, MessageType.Label, 0x35, 3, - "System", sb.ToString())); - sb = new StringBuilder(); - sb.Append(v); + from.SendLocalizedMessage( + 1005629 + ); // You can not exceed the stat cap. Try setting another stat lower first. } else { - sb.Append(' '); - sb.Append(v); + from.RawStr = value; + from.SendLocalizedMessage(1005630); // Your stats have been adjusted. + } + } + } + + private static void ChangeDexterity(Mobile from, int value) + { + if (value < 10 || value > 125) + { + from.SendLocalizedMessage(1005628); // Stats range between 10 and 125. + } + else + { + if (from.RawStr + value + from.RawInt > from.StatCap) + { + from.SendLocalizedMessage( + 1005629 + ); // You can not exceed the stat cap. Try setting another stat lower first. + } + else + { + from.RawDex = value; + from.SendLocalizedMessage(1005630); // Your stats have been adjusted. + } + } + } + + private static void ChangeIntelligence(Mobile from, int value) + { + if (value < 10 || value > 125) + { + from.SendLocalizedMessage(1005628); // Stats range between 10 and 125. + } + else + { + if (from.RawStr + from.RawDex + value > from.StatCap) + { + from.SendLocalizedMessage( + 1005629 + ); // You can not exceed the stat cap. Try setting another stat lower first. + } + else + { + from.RawInt = value; + from.SendLocalizedMessage(1005630); // Your stats have been adjusted. + } + } + } + + private static void ChangeSkill(Mobile from, string name, double value) + { + if (!Enum.TryParse(name, true, out SkillName index) || !Core.SE && (int)index > 51 || + !Core.AOS && (int)index > 48) + { + from.SendLocalizedMessage(1005631); // You have specified an invalid skill to set. + return; + } + + var skill = from.Skills[index]; + + if (skill != null) + { + if (value < 0 || value > skill.Cap) + { + from.SendMessage($"Your skill in {skill.Info.Name} is capped at {skill.Cap:F1}."); + } + else + { + var newFixedPoint = (int)(value * 10.0); + var oldFixedPoint = skill.BaseFixedPoint; + + if (skill.Owner.Total - oldFixedPoint + newFixedPoint > skill.Owner.Cap) + from.SendMessage("You can not exceed the skill cap. Try setting another skill lower first."); + else + skill.BaseFixedPoint = newFixedPoint; + } + } + else + { + from.SendLocalizedMessage(1005631); // You have specified an invalid skill to set. + } + } + + public class TCHelpGump : Gump + { + public TCHelpGump() : base(40, 40) + { + AddPage(0); + AddBackground(0, 0, 160, 120, 5054); + + AddButton(10, 10, 0xFB7, 0xFB9, 1); + AddLabel(45, 10, 0x34, "ModernUO"); + + AddButton(10, 35, 0xFB7, 0xFB9, 2); + AddLabel(45, 35, 0x34, "List of skills"); + + AddButton(10, 60, 0xFB7, 0xFB9, 3); + AddLabel(45, 60, 0x34, "Command list"); + + AddButton(10, 85, 0xFB1, 0xFB3, 0); + AddLabel(45, 85, 0x34, "Close"); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + switch (info.ButtonID) + { + case 1: // RunUO + { + sender.LaunchBrowser("https://github.com/runuo/"); + break; + } + case 2: // List of skills + { + var strings = Enum.GetNames(typeof(SkillName)); + + Array.Sort(strings); + + var sb = new StringBuilder(); + + if (strings.Length > 0) + sb.Append(strings[0]); + + for (var i = 1; i < strings.Length; ++i) + { + var v = strings[i]; + + if (sb.Length + 1 + v.Length >= 256) + { + sender.Send( + new AsciiMessage( + Server.Serial.MinusOne, + -1, + MessageType.Label, + 0x35, + 3, + "System", + sb.ToString() + ) + ); + sb = new StringBuilder(); + sb.Append(v); + } + else + { + sb.Append(' '); + sb.Append(v); + } + } + + if (sb.Length > 0) + sender.Send( + new AsciiMessage( + Server.Serial.MinusOne, + -1, + MessageType.Label, + 0x35, + 3, + "System", + sb.ToString() + ) + ); + + break; + } + case 3: // Command list + { + sender.Mobile.SendAsciiMessage(0x482, "The command prefix is \"{0}\"", CommandSystem.Prefix); + CommandHandlers.Help_OnCommand(new CommandEventArgs(sender.Mobile, "help", "", new string[0])); + + break; + } } - } - - if (sb.Length > 0) - sender.Send(new AsciiMessage(Server.Serial.MinusOne, -1, MessageType.Label, 0x35, 3, "System", - sb.ToString())); - - break; - } - case 3: // Command list - { - sender.Mobile.SendAsciiMessage(0x482, "The command prefix is \"{0}\"", CommandSystem.Prefix); - CommandHandlers.Help_OnCommand(new CommandEventArgs(sender.Mobile, "help", "", new string[0])); - - break; } } - } } - } } diff --git a/Projects/UOContent/SpecialSystems/Items/Resurrection/ResGate.cs b/Projects/UOContent/SpecialSystems/Items/Resurrection/ResGate.cs index c2b0c061c..2eca59b51 100644 --- a/Projects/UOContent/SpecialSystems/Items/Resurrection/ResGate.cs +++ b/Projects/UOContent/SpecialSystems/Items/Resurrection/ResGate.cs @@ -2,52 +2,52 @@ using Server.Gumps; namespace Server.Items { - public class ResGate : Item - { - [Constructible] - public ResGate() : base(0xF6C) + public class ResGate : Item { - Movable = false; - Hue = 0x2D1; - Light = LightType.Circle300; + [Constructible] + public ResGate() : base(0xF6C) + { + Movable = false; + Hue = 0x2D1; + Light = LightType.Circle300; + } + + public ResGate(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a resurrection gate"; + + public override bool OnMoveOver(Mobile m) + { + if (!m.Alive && m.Map?.CanFit(m.Location, 16, false, false) == true) + { + m.PlaySound(0x214); + m.FixedEffect(0x376A, 10, 16); + + m.CloseGump(); + m.SendGump(new ResurrectGump(m)); + } + else + { + m.SendLocalizedMessage(502391); // Thou can not be resurrected there! + } + + return 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 ResGate(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a resurrection gate"; - - public override bool OnMoveOver(Mobile m) - { - if (!m.Alive && m.Map?.CanFit(m.Location, 16, false, false) == true) - { - m.PlaySound(0x214); - m.FixedEffect(0x376A, 10, 16); - - m.CloseGump(); - m.SendGump(new ResurrectGump(m)); - } - else - { - m.SendLocalizedMessage(502391); // Thou can not be resurrected there! - } - - return false; - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/SpecialSystems/Items/Stones/AlchemyStone.cs b/Projects/UOContent/SpecialSystems/Items/Stones/AlchemyStone.cs index 3d39dda1f..6976eff11 100644 --- a/Projects/UOContent/SpecialSystems/Items/Stones/AlchemyStone.cs +++ b/Projects/UOContent/SpecialSystems/Items/Stones/AlchemyStone.cs @@ -1,40 +1,40 @@ namespace Server.Items { - public class AlchemyStone : Item - { - [Constructible] - public AlchemyStone() : base(0xED4) + public class AlchemyStone : Item { - Movable = false; - Hue = 0x250; + [Constructible] + public AlchemyStone() : base(0xED4) + { + Movable = false; + Hue = 0x250; + } + + public AlchemyStone(Serial serial) : base(serial) + { + } + + public override string DefaultName => "an Alchemist Supply Stone"; + + public override void OnDoubleClick(Mobile from) + { + var alcBag = new AlchemyBag(); + + if (!from.AddToBackpack(alcBag)) + alcBag.Delete(); + } + + 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 AlchemyStone(Serial serial) : base(serial) - { - } - - public override string DefaultName => "an Alchemist Supply Stone"; - - public override void OnDoubleClick(Mobile from) - { - AlchemyBag alcBag = new AlchemyBag(); - - if (!from.AddToBackpack(alcBag)) - alcBag.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/SpecialSystems/Items/Stones/GamblingStone.cs b/Projects/UOContent/SpecialSystems/Items/Stones/GamblingStone.cs index 7315c4917..076ef0d77 100644 --- a/Projects/UOContent/SpecialSystems/Items/Stones/GamblingStone.cs +++ b/Projects/UOContent/SpecialSystems/Items/Stones/GamblingStone.cs @@ -1,126 +1,126 @@ namespace Server.Items { - public class GamblingStone : Item - { - private int m_GamblePot = 2500; - - [Constructible] - public GamblingStone() - : base(0xED4) + public class GamblingStone : Item { - Movable = false; - Hue = 0x56; - } + private int m_GamblePot = 2500; - public GamblingStone(Serial serial) - : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public int GamblePot - { - get => m_GamblePot; - set - { - m_GamblePot = value; - InvalidateProperties(); - } - } - - public override string DefaultName => "a gambling stone"; - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add("Jackpot: {0}gp", m_GamblePot); - } - - public override void OnSingleClick(Mobile from) - { - base.OnSingleClick(from); - LabelTo(from, "Jackpot: {0}gp", m_GamblePot); - } - - public override void OnDoubleClick(Mobile from) - { - Container pack = from.Backpack; - - if (pack?.ConsumeTotal(typeof(Gold), 250) == true) - { - m_GamblePot += 150; - InvalidateProperties(); - - int roll = Utility.Random(1200); - - if (roll == 0) // Jackpot + [Constructible] + public GamblingStone() + : base(0xED4) { - int maxCheck = 1000000; - - from.SendMessage(0x35, "You win the {0}gp jackpot!", m_GamblePot); - - while (m_GamblePot > maxCheck) - { - from.AddToBackpack(new BankCheck(maxCheck)); - - m_GamblePot -= maxCheck; - } - - from.AddToBackpack(new BankCheck(m_GamblePot)); - - m_GamblePot = 2500; + Movable = false; + Hue = 0x56; } - else if (roll <= 20) // Chance for a regbag + + public GamblingStone(Serial serial) + : base(serial) { - from.SendMessage(0x35, "You win a bag of reagents!"); - from.AddToBackpack(new BagOfReagents()); } - else if (roll <= 40) // Chance for gold + + [CommandProperty(AccessLevel.GameMaster)] + public int GamblePot { - from.SendMessage(0x35, "You win 1500gp!"); - from.AddToBackpack(new BankCheck(1500)); + get => m_GamblePot; + set + { + m_GamblePot = value; + InvalidateProperties(); + } } - else if (roll <= 100) // Another chance for gold + + public override string DefaultName => "a gambling stone"; + + public override void GetProperties(ObjectPropertyList list) { - from.SendMessage(0x35, "You win 1000gp!"); - from.AddToBackpack(new BankCheck(1000)); + base.GetProperties(list); + + list.Add("Jackpot: {0}gp", m_GamblePot); } - else // Loser! + + public override void OnSingleClick(Mobile from) { - from.SendMessage(0x22, "You lose!"); + base.OnSingleClick(from); + LabelTo(from, "Jackpot: {0}gp", m_GamblePot); + } + + public override void OnDoubleClick(Mobile from) + { + var pack = from.Backpack; + + if (pack?.ConsumeTotal(typeof(Gold), 250) == true) + { + m_GamblePot += 150; + InvalidateProperties(); + + var roll = Utility.Random(1200); + + if (roll == 0) // Jackpot + { + var maxCheck = 1000000; + + from.SendMessage(0x35, "You win the {0}gp jackpot!", m_GamblePot); + + while (m_GamblePot > maxCheck) + { + from.AddToBackpack(new BankCheck(maxCheck)); + + m_GamblePot -= maxCheck; + } + + from.AddToBackpack(new BankCheck(m_GamblePot)); + + m_GamblePot = 2500; + } + else if (roll <= 20) // Chance for a regbag + { + from.SendMessage(0x35, "You win a bag of reagents!"); + from.AddToBackpack(new BagOfReagents()); + } + else if (roll <= 40) // Chance for gold + { + from.SendMessage(0x35, "You win 1500gp!"); + from.AddToBackpack(new BankCheck(1500)); + } + else if (roll <= 100) // Another chance for gold + { + from.SendMessage(0x35, "You win 1000gp!"); + from.AddToBackpack(new BankCheck(1000)); + } + else // Loser! + { + from.SendMessage(0x22, "You lose!"); + } + } + else + { + from.SendMessage(0x22, "You need at least 250gp in your backpack to use this."); + } + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_GamblePot); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_GamblePot = reader.ReadInt(); + + break; + } + } } - } - else - { - from.SendMessage(0x22, "You need at least 250gp in your backpack to use this."); - } } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_GamblePot); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 0: - { - m_GamblePot = reader.ReadInt(); - - break; - } - } - } - } } diff --git a/Projects/UOContent/SpecialSystems/Items/Stones/IngotStone.cs b/Projects/UOContent/SpecialSystems/Items/Stones/IngotStone.cs index ecbe5619a..2ac1b509b 100644 --- a/Projects/UOContent/SpecialSystems/Items/Stones/IngotStone.cs +++ b/Projects/UOContent/SpecialSystems/Items/Stones/IngotStone.cs @@ -1,40 +1,40 @@ namespace Server.Items { - public class IngotStone : Item - { - [Constructible] - public IngotStone() : base(0xED4) + public class IngotStone : Item { - Movable = false; - Hue = 0x480; + [Constructible] + public IngotStone() : base(0xED4) + { + Movable = false; + Hue = 0x480; + } + + public IngotStone(Serial serial) : base(serial) + { + } + + public override string DefaultName => "an Ingot stone"; + + public override void OnDoubleClick(Mobile from) + { + var ingotBag = new BagOfingots(); + + if (!from.AddToBackpack(ingotBag)) + ingotBag.Delete(); + } + + 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 IngotStone(Serial serial) : base(serial) - { - } - - public override string DefaultName => "an Ingot stone"; - - public override void OnDoubleClick(Mobile from) - { - BagOfingots ingotBag = new BagOfingots(); - - if (!from.AddToBackpack(ingotBag)) - ingotBag.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/SpecialSystems/Items/Stones/RegStone.cs b/Projects/UOContent/SpecialSystems/Items/Stones/RegStone.cs index c7a7f8fd3..ea7a06ee1 100644 --- a/Projects/UOContent/SpecialSystems/Items/Stones/RegStone.cs +++ b/Projects/UOContent/SpecialSystems/Items/Stones/RegStone.cs @@ -1,40 +1,40 @@ namespace Server.Items { - public class RegStone : Item - { - [Constructible] - public RegStone() : base(0xED4) + public class RegStone : Item { - Movable = false; - Hue = 0x2D1; + [Constructible] + public RegStone() : base(0xED4) + { + Movable = false; + Hue = 0x2D1; + } + + public RegStone(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a reagent stone"; + + public override void OnDoubleClick(Mobile from) + { + var regBag = new BagOfReagents(); + + if (!from.AddToBackpack(regBag)) + regBag.Delete(); + } + + 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 RegStone(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a reagent stone"; - - public override void OnDoubleClick(Mobile from) - { - BagOfReagents regBag = new BagOfReagents(); - - if (!from.AddToBackpack(regBag)) - regBag.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/SpecialSystems/Items/Stones/ScribeStone.cs b/Projects/UOContent/SpecialSystems/Items/Stones/ScribeStone.cs index 31187a765..3ae0ba49b 100644 --- a/Projects/UOContent/SpecialSystems/Items/Stones/ScribeStone.cs +++ b/Projects/UOContent/SpecialSystems/Items/Stones/ScribeStone.cs @@ -1,40 +1,40 @@ namespace Server.Items { - public class ScribeStone : Item - { - [Constructible] - public ScribeStone() : base(0xED4) + public class ScribeStone : Item { - Movable = false; - Hue = 0x105; + [Constructible] + public ScribeStone() : base(0xED4) + { + Movable = false; + Hue = 0x105; + } + + public ScribeStone(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a Scribe Supply Stone"; + + public override void OnDoubleClick(Mobile from) + { + var scribeBag = new ScribeBag(); + + if (!from.AddToBackpack(scribeBag)) + scribeBag.Delete(); + } + + 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 ScribeStone(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a Scribe Supply Stone"; - - public override void OnDoubleClick(Mobile from) - { - ScribeBag scribeBag = new ScribeBag(); - - if (!from.AddToBackpack(scribeBag)) - scribeBag.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/SpecialSystems/Items/Stones/SmithStone.cs b/Projects/UOContent/SpecialSystems/Items/Stones/SmithStone.cs index 7b575c287..bfc294963 100644 --- a/Projects/UOContent/SpecialSystems/Items/Stones/SmithStone.cs +++ b/Projects/UOContent/SpecialSystems/Items/Stones/SmithStone.cs @@ -1,40 +1,40 @@ namespace Server.Items { - public class SmithStone : Item - { - [Constructible] - public SmithStone() : base(0xED4) + public class SmithStone : Item { - Movable = false; - Hue = 0x476; + [Constructible] + public SmithStone() : base(0xED4) + { + Movable = false; + Hue = 0x476; + } + + public SmithStone(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a Blacksmith Supply Stone"; + + public override void OnDoubleClick(Mobile from) + { + var SmithBag = new SmithBag(); + + if (!from.AddToBackpack(SmithBag)) + SmithBag.Delete(); + } + + 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 SmithStone(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a Blacksmith Supply Stone"; - - public override void OnDoubleClick(Mobile from) - { - SmithBag SmithBag = new SmithBag(); - - if (!from.AddToBackpack(SmithBag)) - SmithBag.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/SpecialSystems/Items/Stones/TailorStone.cs b/Projects/UOContent/SpecialSystems/Items/Stones/TailorStone.cs index 71cba6fd6..e166b18a5 100644 --- a/Projects/UOContent/SpecialSystems/Items/Stones/TailorStone.cs +++ b/Projects/UOContent/SpecialSystems/Items/Stones/TailorStone.cs @@ -1,40 +1,40 @@ namespace Server.Items { - public class TailorStone : Item - { - [Constructible] - public TailorStone() : base(0xED4) + public class TailorStone : Item { - Movable = false; - Hue = 0x315; + [Constructible] + public TailorStone() : base(0xED4) + { + Movable = false; + Hue = 0x315; + } + + public TailorStone(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a Tailor Supply Stone"; + + public override void OnDoubleClick(Mobile from) + { + var tailorBag = new TailorBag(); + + if (!from.AddToBackpack(tailorBag)) + tailorBag.Delete(); + } + + 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 TailorStone(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a Tailor Supply Stone"; - - public override void OnDoubleClick(Mobile from) - { - TailorBag tailorBag = new TailorBag(); - - if (!from.AddToBackpack(tailorBag)) - tailorBag.Delete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/SpecialSystems/Items/SupplyBags/AlchemyBag.cs b/Projects/UOContent/SpecialSystems/Items/SupplyBags/AlchemyBag.cs index beb9d00cf..68c63d911 100644 --- a/Projects/UOContent/SpecialSystems/Items/SupplyBags/AlchemyBag.cs +++ b/Projects/UOContent/SpecialSystems/Items/SupplyBags/AlchemyBag.cs @@ -2,35 +2,35 @@ using System; namespace Server.Items { - public class AlchemyBag : Bag - { - [Constructible] - public AlchemyBag(int amount = 5000) + public class AlchemyBag : Bag { - Hue = 0x250; - DropItem(new MortarPestle(Math.Max(amount / 1000, 1))); - DropItem(new BagOfReagents(5000)); - DropItem(new Bottle(5000)); + [Constructible] + public AlchemyBag(int amount = 5000) + { + Hue = 0x250; + DropItem(new MortarPestle(Math.Max(amount / 1000, 1))); + DropItem(new BagOfReagents(5000)); + DropItem(new Bottle(5000)); + } + + public AlchemyBag(Serial serial) : base(serial) + { + } + + public override string DefaultName => "an Alchemy Kit"; + + 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 AlchemyBag(Serial serial) : base(serial) - { - } - - public override string DefaultName => "an Alchemy Kit"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/SpecialSystems/Items/SupplyBags/BagOfIngots.cs b/Projects/UOContent/SpecialSystems/Items/SupplyBags/BagOfIngots.cs index 74a074ac1..1ec7b80e5 100644 --- a/Projects/UOContent/SpecialSystems/Items/SupplyBags/BagOfIngots.cs +++ b/Projects/UOContent/SpecialSystems/Items/SupplyBags/BagOfIngots.cs @@ -1,39 +1,39 @@ namespace Server.Items { - public class BagOfingots : Bag - { - [Constructible] - public BagOfingots(int amount = 5000) + public class BagOfingots : Bag { - DropItem(new DullCopperIngot(amount)); - DropItem(new ShadowIronIngot(amount)); - DropItem(new CopperIngot(amount)); - DropItem(new BronzeIngot(amount)); - DropItem(new GoldIngot(amount)); - DropItem(new AgapiteIngot(amount)); - DropItem(new VeriteIngot(amount)); - DropItem(new ValoriteIngot(amount)); - DropItem(new IronIngot(amount)); - DropItem(new Tongs()); - DropItem(new TinkerTools()); + [Constructible] + public BagOfingots(int amount = 5000) + { + DropItem(new DullCopperIngot(amount)); + DropItem(new ShadowIronIngot(amount)); + DropItem(new CopperIngot(amount)); + DropItem(new BronzeIngot(amount)); + DropItem(new GoldIngot(amount)); + DropItem(new AgapiteIngot(amount)); + DropItem(new VeriteIngot(amount)); + DropItem(new ValoriteIngot(amount)); + DropItem(new IronIngot(amount)); + DropItem(new Tongs()); + DropItem(new TinkerTools()); + } + + public BagOfingots(Serial serial) : base(serial) + { + } + + 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 BagOfingots(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/SpecialSystems/Items/SupplyBags/ScribeBag.cs b/Projects/UOContent/SpecialSystems/Items/SupplyBags/ScribeBag.cs index 0be49c6d7..5c81d98f5 100644 --- a/Projects/UOContent/SpecialSystems/Items/SupplyBags/ScribeBag.cs +++ b/Projects/UOContent/SpecialSystems/Items/SupplyBags/ScribeBag.cs @@ -1,33 +1,33 @@ namespace Server.Items { - public class ScribeBag : Bag - { - [Constructible] - public ScribeBag(int amount = 5000) + public class ScribeBag : Bag { - Hue = 0x105; - DropItem(new BagOfReagents(amount)); - DropItem(new BlankScroll(amount)); + [Constructible] + public ScribeBag(int amount = 5000) + { + Hue = 0x105; + DropItem(new BagOfReagents(amount)); + DropItem(new BlankScroll(amount)); + } + + public ScribeBag(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a Scribe Kit"; + + 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 ScribeBag(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a Scribe Kit"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/SpecialSystems/Items/SupplyBags/SmithBag.cs b/Projects/UOContent/SpecialSystems/Items/SupplyBags/SmithBag.cs index 3b90f7adf..fe2cc2b94 100644 --- a/Projects/UOContent/SpecialSystems/Items/SupplyBags/SmithBag.cs +++ b/Projects/UOContent/SpecialSystems/Items/SupplyBags/SmithBag.cs @@ -1,39 +1,39 @@ namespace Server.Items { - public class SmithBag : Bag - { - [Constructible] - public SmithBag(int amount = 5000) + public class SmithBag : Bag { - DropItem(new DullCopperIngot(amount)); - DropItem(new ShadowIronIngot(amount)); - DropItem(new CopperIngot(amount)); - DropItem(new BronzeIngot(amount)); - DropItem(new GoldIngot(amount)); - DropItem(new AgapiteIngot(amount)); - DropItem(new VeriteIngot(amount)); - DropItem(new ValoriteIngot(amount)); - DropItem(new IronIngot(amount)); - DropItem(new Tongs(amount)); - DropItem(new TinkerTools(amount)); + [Constructible] + public SmithBag(int amount = 5000) + { + DropItem(new DullCopperIngot(amount)); + DropItem(new ShadowIronIngot(amount)); + DropItem(new CopperIngot(amount)); + DropItem(new BronzeIngot(amount)); + DropItem(new GoldIngot(amount)); + DropItem(new AgapiteIngot(amount)); + DropItem(new VeriteIngot(amount)); + DropItem(new ValoriteIngot(amount)); + DropItem(new IronIngot(amount)); + DropItem(new Tongs(amount)); + DropItem(new TinkerTools(amount)); + } + + public SmithBag(Serial serial) : base(serial) + { + } + + 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 SmithBag(Serial serial) : base(serial) - { - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/SpecialSystems/Items/SupplyBags/TailorBag.cs b/Projects/UOContent/SpecialSystems/Items/SupplyBags/TailorBag.cs index 4525dde42..0f8764feb 100644 --- a/Projects/UOContent/SpecialSystems/Items/SupplyBags/TailorBag.cs +++ b/Projects/UOContent/SpecialSystems/Items/SupplyBags/TailorBag.cs @@ -2,40 +2,40 @@ using System; namespace Server.Items { - public class TailorBag : Bag - { - [Constructible] - public TailorBag(int amount = 500) + public class TailorBag : Bag { - Hue = 0x315; - DropItem(new SewingKit(Math.Max(amount / 100, 1))); - DropItem(new Scissors()); - DropItem(new Hides(amount)); - DropItem(new BoltOfCloth(Math.Max(amount / 25, 1))); - DropItem(new DyeTub()); - DropItem(new DyeTub()); - DropItem(new BlackDyeTub()); - DropItem(new Dyes()); + [Constructible] + public TailorBag(int amount = 500) + { + Hue = 0x315; + DropItem(new SewingKit(Math.Max(amount / 100, 1))); + DropItem(new Scissors()); + DropItem(new Hides(amount)); + DropItem(new BoltOfCloth(Math.Max(amount / 25, 1))); + DropItem(new DyeTub()); + DropItem(new DyeTub()); + DropItem(new BlackDyeTub()); + DropItem(new Dyes()); + } + + public TailorBag(Serial serial) : base(serial) + { + } + + public override string DefaultName => "a Tailoring Kit"; + + 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 TailorBag(Serial serial) : base(serial) - { - } - - public override string DefaultName => "a Tailoring Kit"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - } } diff --git a/Projects/UOContent/Spells/Base/DisturbType.cs b/Projects/UOContent/Spells/Base/DisturbType.cs index 87c3d76c5..a34204d74 100644 --- a/Projects/UOContent/Spells/Base/DisturbType.cs +++ b/Projects/UOContent/Spells/Base/DisturbType.cs @@ -1,12 +1,12 @@ namespace Server.Spells { - public enum DisturbType - { - Unspecified, - EquipRequest, - UseRequest, - Hurt, - Kill, - NewCast - } -} \ No newline at end of file + public enum DisturbType + { + Unspecified, + EquipRequest, + UseRequest, + Hurt, + Kill, + NewCast + } +} diff --git a/Projects/UOContent/Spells/Base/MagerySpell.cs b/Projects/UOContent/Spells/Base/MagerySpell.cs index 2029f3fe5..147e1521f 100644 --- a/Projects/UOContent/Spells/Base/MagerySpell.cs +++ b/Projects/UOContent/Spells/Base/MagerySpell.cs @@ -3,84 +3,85 @@ using Server.Items; namespace Server.Spells { - public abstract class MagerySpell : Spell - { - private const double ChanceOffset = 20.0, ChanceLength = 100.0 / 7.0; - - private static readonly int[] m_ManaTable = { 4, 6, 9, 11, 14, 20, 40, 50 }; - - public MagerySpell(Mobile caster, Item scroll, SpellInfo info) - : base(caster, scroll, info) + public abstract class MagerySpell : Spell { + private const double ChanceOffset = 20.0, ChanceLength = 100.0 / 7.0; + + private static readonly int[] m_ManaTable = { 4, 6, 9, 11, 14, 20, 40, 50 }; + + public MagerySpell(Mobile caster, Item scroll, SpellInfo info) + : base(caster, scroll, info) + { + } + + public abstract SpellCircle Circle { get; } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds((3 + (int)Circle) * CastDelaySecondsPerTick); + + public override bool ConsumeReagents() => + base.ConsumeReagents() || ArcaneGem.ConsumeCharges(Caster, Core.SE ? 1 : 1 + (int)Circle); + + public override void GetCastSkills(out double min, out double max) + { + var circle = (int)Circle; + + if (Scroll != null) + circle -= 2; + + var avg = ChanceLength * circle; + + min = avg - ChanceOffset; + max = avg + ChanceOffset; + } + + public override int GetMana() => Scroll is BaseWand ? 0 : m_ManaTable[(int)Circle]; + + public override double GetResistSkill(Mobile m) + { + var maxSkill = (1 + (int)Circle) * 10; + maxSkill += (1 + (int)Circle / 6) * 25; + + if (m.Skills.MagicResist.Value < maxSkill) + m.CheckSkill(SkillName.MagicResist, 0.0, m.Skills.MagicResist.Cap); + + return m.Skills.MagicResist.Value; + } + + public virtual bool CheckResisted(Mobile target) + { + var n = GetResistPercent(target); + + n /= 100.0; + + if (n <= 0.0) + return false; + + if (n >= 1.0) + return true; + + var maxSkill = (1 + (int)Circle) * 10; + maxSkill += (1 + (int)Circle / 6) * 25; + + if (target.Skills.MagicResist.Value < maxSkill) + target.CheckSkill(SkillName.MagicResist, 0.0, target.Skills.MagicResist.Cap); + + return n >= Utility.RandomDouble(); + } + + public virtual double GetResistPercentForCircle(Mobile target, SpellCircle circle) + { + var firstPercent = target.Skills.MagicResist.Value / 5.0; + var secondPercent = target.Skills.MagicResist.Value - + ((Caster.Skills[CastSkill].Value - 20.0) / 5.0 + (1 + (int)circle) * 5.0); + + return (firstPercent > secondPercent ? firstPercent : secondPercent) / + 2.0; // Seems should be about half of what stratics says. + } + + public virtual double GetResistPercent(Mobile target) => GetResistPercentForCircle(target, Circle); + + public override TimeSpan GetCastDelay() => + !Core.ML && Scroll is BaseWand ? TimeSpan.Zero : + !Core.AOS ? TimeSpan.FromSeconds(0.5 + 0.25 * (int)Circle) : base.GetCastDelay(); } - - public abstract SpellCircle Circle { get; } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds((3 + (int)Circle) * CastDelaySecondsPerTick); - - public override bool ConsumeReagents() => base.ConsumeReagents() || ArcaneGem.ConsumeCharges(Caster, Core.SE ? 1 : 1 + (int)Circle); - - public override void GetCastSkills(out double min, out double max) - { - int circle = (int)Circle; - - if (Scroll != null) - circle -= 2; - - double avg = ChanceLength * circle; - - min = avg - ChanceOffset; - max = avg + ChanceOffset; - } - - public override int GetMana() => Scroll is BaseWand ? 0 : m_ManaTable[(int)Circle]; - - public override double GetResistSkill(Mobile m) - { - int maxSkill = (1 + (int)Circle) * 10; - maxSkill += (1 + (int)Circle / 6) * 25; - - if (m.Skills.MagicResist.Value < maxSkill) - m.CheckSkill(SkillName.MagicResist, 0.0, m.Skills.MagicResist.Cap); - - return m.Skills.MagicResist.Value; - } - - public virtual bool CheckResisted(Mobile target) - { - double n = GetResistPercent(target); - - n /= 100.0; - - if (n <= 0.0) - return false; - - if (n >= 1.0) - return true; - - int maxSkill = (1 + (int)Circle) * 10; - maxSkill += (1 + (int)Circle / 6) * 25; - - if (target.Skills.MagicResist.Value < maxSkill) - target.CheckSkill(SkillName.MagicResist, 0.0, target.Skills.MagicResist.Cap); - - return n >= Utility.RandomDouble(); - } - - public virtual double GetResistPercentForCircle(Mobile target, SpellCircle circle) - { - double firstPercent = target.Skills.MagicResist.Value / 5.0; - double secondPercent = target.Skills.MagicResist.Value - - ((Caster.Skills[CastSkill].Value - 20.0) / 5.0 + (1 + (int)circle) * 5.0); - - return (firstPercent > secondPercent ? firstPercent : secondPercent) / - 2.0; // Seems should be about half of what stratics says. - } - - public virtual double GetResistPercent(Mobile target) => GetResistPercentForCircle(target, Circle); - - public override TimeSpan GetCastDelay() => - !Core.ML && Scroll is BaseWand ? TimeSpan.Zero : - !Core.AOS ? TimeSpan.FromSeconds(0.5 + 0.25 * (int)Circle) : base.GetCastDelay(); - } } diff --git a/Projects/UOContent/Spells/Base/SpecialMove.cs b/Projects/UOContent/Spells/Base/SpecialMove.cs index 853df7b80..24a09c8cd 100644 --- a/Projects/UOContent/Spells/Base/SpecialMove.cs +++ b/Projects/UOContent/Spells/Base/SpecialMove.cs @@ -9,305 +9,311 @@ using Server.Spells.Ninjitsu; namespace Server.Spells { - public abstract class SpecialMove - { - private static readonly Dictionary m_PlayersTable = new Dictionary(); - - public virtual int BaseMana => 0; - - public virtual SkillName MoveSkill => SkillName.Bushido; - public virtual double RequiredSkill => 0.0; - - public virtual TextDefinition AbilityMessage => 0; - - public virtual bool BlockedByAnimalForm => true; - public virtual bool DelayedContext => false; - - public static Dictionary Table { get; } = new Dictionary(); - - public virtual bool ValidatesDuringHit => true; - - public virtual int GetAccuracyBonus(Mobile attacker) => 0; - - public virtual double GetDamageScalar(Mobile attacker, Mobile defender) => 1.0; - - // Called before swinging, to make sure the accuracy scalar is to be computed. - public virtual bool OnBeforeSwing(Mobile attacker, Mobile defender) => true; - - // Called when a hit connects, but before damage is calculated. - public virtual bool OnBeforeDamage(Mobile attacker, Mobile defender) => true; - - // Called as soon as the ability is used. - public virtual void OnUse(Mobile from) + public abstract class SpecialMove { - } + private static readonly Dictionary m_PlayersTable = + new Dictionary(); - // Called when a hit connects, at the end of the weapon.OnHit() method. - public virtual void OnHit(Mobile attacker, Mobile defender, int damage) - { - } + public virtual int BaseMana => 0; - // Called when a hit misses. - public virtual void OnMiss(Mobile attacker, Mobile defender) - { - } + public virtual SkillName MoveSkill => SkillName.Bushido; + public virtual double RequiredSkill => 0.0; - // Called when the move is cleared. - public virtual void OnClearMove(Mobile from) - { - } + public virtual TextDefinition AbilityMessage => 0; - public virtual bool IgnoreArmor(Mobile attacker) => false; + public virtual bool BlockedByAnimalForm => true; + public virtual bool DelayedContext => false; - public virtual double GetPropertyBonus(Mobile attacker) => 1.0; + public static Dictionary Table { get; } = new Dictionary(); - public virtual bool CheckSkills(Mobile m) - { - if (m.Skills[MoveSkill].Value < RequiredSkill) - { - string args = $"{RequiredSkill:F1}\t{MoveSkill.ToString()}\t "; - m.SendLocalizedMessage(1063013, - args); // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability. - return false; - } + public virtual bool ValidatesDuringHit => true; - return true; - } + public virtual int GetAccuracyBonus(Mobile attacker) => 0; - public virtual int ScaleMana(Mobile m, int mana) - { - double scalar = 1.0; + public virtual double GetDamageScalar(Mobile attacker, Mobile defender) => 1.0; - if (!MindRotSpell.GetMindRotScalar(m, ref scalar)) - scalar = 1.0; + // Called before swinging, to make sure the accuracy scalar is to be computed. + public virtual bool OnBeforeSwing(Mobile attacker, Mobile defender) => true; - // Lower Mana Cost = 40% - int lmc = Math.Min(AosAttributes.GetValue(m, AosAttribute.LowerManaCost), 40); + // Called when a hit connects, but before damage is calculated. + public virtual bool OnBeforeDamage(Mobile attacker, Mobile defender) => true; - scalar -= (double)lmc / 100; - - int total = (int)(mana * scalar); - - if (m.Skills[MoveSkill].Value < 50.0 && GetContext(m) != null) - total *= 2; - - return total; - } - - public virtual bool CheckMana(Mobile from, bool consume) - { - int mana = ScaleMana(from, BaseMana); - - if (from.Mana < mana) - { - from.SendLocalizedMessage(1060181, - mana.ToString()); // You need ~1_MANA_REQUIREMENT~ mana to perform that attack - return false; - } - - if (consume) - { - if (!DelayedContext) - SetContext(from); - - from.Mana -= mana; - } - - return true; - } - - public virtual void SetContext(Mobile from) - { - if (GetContext(from) == null) - if (DelayedContext || from.Skills[MoveSkill].Value < 50.0) + // Called as soon as the ability is used. + public virtual void OnUse(Mobile from) { - Timer timer = new SpecialMoveTimer(from); - timer.Start(); + } - AddContext(from, new SpecialMoveContext(timer, GetType())); + // Called when a hit connects, at the end of the weapon.OnHit() method. + public virtual void OnHit(Mobile attacker, Mobile defender, int damage) + { + } + + // Called when a hit misses. + public virtual void OnMiss(Mobile attacker, Mobile defender) + { + } + + // Called when the move is cleared. + public virtual void OnClearMove(Mobile from) + { + } + + public virtual bool IgnoreArmor(Mobile attacker) => false; + + public virtual double GetPropertyBonus(Mobile attacker) => 1.0; + + public virtual bool CheckSkills(Mobile m) + { + if (m.Skills[MoveSkill].Value < RequiredSkill) + { + var args = $"{RequiredSkill:F1}\t{MoveSkill.ToString()}\t "; + m.SendLocalizedMessage( + 1063013, + args + ); // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability. + return false; + } + + return true; + } + + public virtual int ScaleMana(Mobile m, int mana) + { + var scalar = 1.0; + + if (!MindRotSpell.GetMindRotScalar(m, ref scalar)) + scalar = 1.0; + + // Lower Mana Cost = 40% + var lmc = Math.Min(AosAttributes.GetValue(m, AosAttribute.LowerManaCost), 40); + + scalar -= (double)lmc / 100; + + var total = (int)(mana * scalar); + + if (m.Skills[MoveSkill].Value < 50.0 && GetContext(m) != null) + total *= 2; + + return total; + } + + public virtual bool CheckMana(Mobile from, bool consume) + { + var mana = ScaleMana(from, BaseMana); + + if (from.Mana < mana) + { + from.SendLocalizedMessage( + 1060181, + mana.ToString() + ); // You need ~1_MANA_REQUIREMENT~ mana to perform that attack + return false; + } + + if (consume) + { + if (!DelayedContext) + SetContext(from); + + from.Mana -= mana; + } + + return true; + } + + public virtual void SetContext(Mobile from) + { + if (GetContext(from) == null) + if (DelayedContext || from.Skills[MoveSkill].Value < 50.0) + { + Timer timer = new SpecialMoveTimer(from); + timer.Start(); + + AddContext(from, new SpecialMoveContext(timer, GetType())); + } + } + + public virtual bool Validate(Mobile from) + { + if (!from.Player) + return true; + + if (HonorableExecution.IsUnderPenalty(from)) + { + from.SendLocalizedMessage(1063024); // You cannot perform this special move right now. + return false; + } + + if (AnimalForm.UnderTransformation(from)) + { + from.SendLocalizedMessage(1063024); // You cannot perform this special move right now. + return false; + } + + string option = null; + + if (this is Backstab) + option = "Backstab"; + else if (this is DeathStrike) + option = "Death Strike"; + else if (this is FocusAttack) + option = "Focus Attack"; + else if (this is KiAttack) + option = "Ki Attack"; + else if (this is SurpriseAttack) + option = "Surprise Attack"; + else if (this is HonorableExecution) + option = "Honorable Execution"; + else if (this is LightningStrike) + option = "Lightning Strike"; + else if (this is MomentumStrike) + option = "Momentum Strike"; + + if (option != null && !DuelContext.AllowSpecialMove(from, option, this)) + return false; + + return CheckSkills(from) && CheckMana(from, false); + } + + public virtual void CheckGain(Mobile m) + { + m.CheckSkill(MoveSkill, RequiredSkill, RequiredSkill + 37.5); + } + + public static void ClearAllMoves(Mobile m) + { + foreach (var kvp in SpellRegistry.SpecialMoves) + { + var moveID = kvp.Key; + + if (moveID != -1) + m.Send(new ToggleSpecialAbility(moveID + 1, false)); + } + } + + public static SpecialMove GetCurrentMove(Mobile m) + { + if (m == null) + return null; + + if (!Core.SE) + { + ClearCurrentMove(m); + return null; + } + + if (Table.TryGetValue(m, out var move) && move.ValidatesDuringHit && !move.Validate(m)) + { + ClearCurrentMove(m); + return null; + } + + return move; + } + + public static bool SetCurrentMove(Mobile m, SpecialMove move) + { + if (!Core.SE) + { + ClearCurrentMove(m); + return false; + } + + if (move?.Validate(m) == false) + { + ClearCurrentMove(m); + return false; + } + + var sameMove = move == GetCurrentMove(m); + + ClearCurrentMove(m); + + if (sameMove) + return true; + + if (move != null) + { + WeaponAbility.ClearCurrentAbility(m); + + Table[m] = move; + + move.OnUse(m); + + var moveID = SpellRegistry.GetRegistryNumber(move); + + if (moveID > 0) + m.Send(new ToggleSpecialAbility(moveID + 1, true)); + + TextDefinition.SendMessageTo(m, move.AbilityMessage); + } + + return true; + } + + public static void ClearCurrentMove(Mobile m) + { + if (Table.TryGetValue(m, out var move)) + { + move.OnClearMove(m); + + var moveID = SpellRegistry.GetRegistryNumber(move); + + if (moveID > 0) + m.Send(new ToggleSpecialAbility(moveID + 1, false)); + } + + Table.Remove(m); + } + + private static void AddContext(Mobile m, SpecialMoveContext context) + { + m_PlayersTable[m] = context; + } + + private static void RemoveContext(Mobile m) + { + var context = GetContext(m); + + if (context != null) + { + m_PlayersTable.Remove(m); + + context.Timer.Stop(); + } + } + + private static SpecialMoveContext GetContext(Mobile m) => + m_PlayersTable.TryGetValue(m, out var context) ? context : null; + + private class SpecialMoveTimer : Timer + { + private readonly Mobile m_Mobile; + + public SpecialMoveTimer(Mobile from) : base(TimeSpan.FromSeconds(3.0)) + { + m_Mobile = from; + + Priority = TimerPriority.TwentyFiveMS; + } + + protected override void OnTick() + { + RemoveContext(m_Mobile); + } + } + + public class SpecialMoveContext + { + public SpecialMoveContext(Timer timer, Type type) + { + Timer = timer; + Type = type; + } + + public Timer Timer { get; } + + public Type Type { get; } } } - - public virtual bool Validate(Mobile from) - { - if (!from.Player) - return true; - - if (HonorableExecution.IsUnderPenalty(from)) - { - from.SendLocalizedMessage(1063024); // You cannot perform this special move right now. - return false; - } - - if (AnimalForm.UnderTransformation(from)) - { - from.SendLocalizedMessage(1063024); // You cannot perform this special move right now. - return false; - } - - string option = null; - - if (this is Backstab) - option = "Backstab"; - else if (this is DeathStrike) - option = "Death Strike"; - else if (this is FocusAttack) - option = "Focus Attack"; - else if (this is KiAttack) - option = "Ki Attack"; - else if (this is SurpriseAttack) - option = "Surprise Attack"; - else if (this is HonorableExecution) - option = "Honorable Execution"; - else if (this is LightningStrike) - option = "Lightning Strike"; - else if (this is MomentumStrike) - option = "Momentum Strike"; - - if (option != null && !DuelContext.AllowSpecialMove(from, option, this)) - return false; - - return CheckSkills(from) && CheckMana(from, false); - } - - public virtual void CheckGain(Mobile m) - { - m.CheckSkill(MoveSkill, RequiredSkill, RequiredSkill + 37.5); - } - - public static void ClearAllMoves(Mobile m) - { - foreach (KeyValuePair kvp in SpellRegistry.SpecialMoves) - { - int moveID = kvp.Key; - - if (moveID != -1) - m.Send(new ToggleSpecialAbility(moveID + 1, false)); - } - } - - public static SpecialMove GetCurrentMove(Mobile m) - { - if (m == null) - return null; - - if (!Core.SE) - { - ClearCurrentMove(m); - return null; - } - - if (Table.TryGetValue(m, out SpecialMove move) && move.ValidatesDuringHit && !move.Validate(m)) - { - ClearCurrentMove(m); - return null; - } - - return move; - } - - public static bool SetCurrentMove(Mobile m, SpecialMove move) - { - if (!Core.SE) - { - ClearCurrentMove(m); - return false; - } - - if (move?.Validate(m) == false) - { - ClearCurrentMove(m); - return false; - } - - bool sameMove = move == GetCurrentMove(m); - - ClearCurrentMove(m); - - if (sameMove) - return true; - - if (move != null) - { - WeaponAbility.ClearCurrentAbility(m); - - Table[m] = move; - - move.OnUse(m); - - int moveID = SpellRegistry.GetRegistryNumber(move); - - if (moveID > 0) - m.Send(new ToggleSpecialAbility(moveID + 1, true)); - - TextDefinition.SendMessageTo(m, move.AbilityMessage); - } - - return true; - } - - public static void ClearCurrentMove(Mobile m) - { - if (Table.TryGetValue(m, out SpecialMove move)) - { - move.OnClearMove(m); - - int moveID = SpellRegistry.GetRegistryNumber(move); - - if (moveID > 0) - m.Send(new ToggleSpecialAbility(moveID + 1, false)); - } - - Table.Remove(m); - } - - private static void AddContext(Mobile m, SpecialMoveContext context) - { - m_PlayersTable[m] = context; - } - - private static void RemoveContext(Mobile m) - { - SpecialMoveContext context = GetContext(m); - - if (context != null) - { - m_PlayersTable.Remove(m); - - context.Timer.Stop(); - } - } - - private static SpecialMoveContext GetContext(Mobile m) => m_PlayersTable.TryGetValue(m, out SpecialMoveContext context) ? context : null; - - private class SpecialMoveTimer : Timer - { - private readonly Mobile m_Mobile; - - public SpecialMoveTimer(Mobile from) : base(TimeSpan.FromSeconds(3.0)) - { - m_Mobile = from; - - Priority = TimerPriority.TwentyFiveMS; - } - - protected override void OnTick() - { - RemoveContext(m_Mobile); - } - } - - public class SpecialMoveContext - { - public SpecialMoveContext(Timer timer, Type type) - { - Timer = timer; - Type = type; - } - - public Timer Timer { get; } - - public Type Type { get; } - } - } } diff --git a/Projects/UOContent/Spells/Base/Spell.cs b/Projects/UOContent/Spells/Base/Spell.cs index 3ceda3c63..f55ea9b47 100644 --- a/Projects/UOContent/Spells/Base/Spell.cs +++ b/Projects/UOContent/Spells/Base/Spell.cs @@ -14,800 +14,811 @@ using Server.Targeting; namespace Server.Spells { - public abstract class Spell : ISpell - { - private static readonly TimeSpan NextSpellDelay = TimeSpan.FromSeconds(0.75); - - private static readonly TimeSpan AnimateDelay = TimeSpan.FromSeconds(1.5); - // In reality, it's ANY delayed Damage spell Post-AoS that can't stack, but, only - // Expo & Magic Arrow have enough delay and a short enough cast time to bring up - // the possibility of stacking 'em. Note that a MA & an Explosion will stack, but - // of course, two MA's won't. - - private static readonly Dictionary m_ContextTable = - new Dictionary(); - - private AnimTimer m_AnimTimer; - - private CastTimer m_CastTimer; - - public Spell(Mobile caster, Item scroll, SpellInfo info) + public abstract class Spell : ISpell { - Caster = caster; - Scroll = scroll; - Info = info; - } + private static readonly TimeSpan NextSpellDelay = TimeSpan.FromSeconds(0.75); - public SpellState State { get; set; } + private static readonly TimeSpan AnimateDelay = TimeSpan.FromSeconds(1.5); + // In reality, it's ANY delayed Damage spell Post-AoS that can't stack, but, only + // Expo & Magic Arrow have enough delay and a short enough cast time to bring up + // the possibility of stacking 'em. Note that a MA & an Explosion will stack, but + // of course, two MA's won't. - public Mobile Caster { get; } + private static readonly Dictionary m_ContextTable = + new Dictionary(); - public SpellInfo Info { get; } + private AnimTimer m_AnimTimer; - public string Name => Info.Name; - public string Mantra => Info.Mantra; - public Type[] Reagents => Info.Reagents; - public Item Scroll { get; } + private CastTimer m_CastTimer; - public long StartCastTime { get; private set; } - - public virtual SkillName CastSkill => SkillName.Magery; - public virtual SkillName DamageSkill => SkillName.EvalInt; - - public virtual bool RevealOnCast => true; - public virtual bool ClearHandsOnCast => true; - public virtual bool ShowHandMovement => true; - - public virtual bool DelayedDamage => false; - - public virtual bool DelayedDamageStacking => true; - - public virtual bool BlockedByHorrificBeast => true; - public virtual bool BlockedByAnimalForm => true; - public virtual bool BlocksMovement => true; - - public virtual bool CheckNextSpellTime => !(Scroll is BaseWand); - - public virtual int CastRecoveryBase => 6; - public virtual int CastRecoveryFastScalar => 1; - public virtual int CastRecoveryPerSecond => 4; - public virtual int CastRecoveryMinimum => 0; - - public abstract TimeSpan CastDelayBase { get; } - - public virtual double CastDelayFastScalar => 1; - public virtual double CastDelaySecondsPerTick => 0.25; - public virtual TimeSpan CastDelayMinimum => TimeSpan.FromSeconds(0.25); - - public virtual bool IsCasting => State == SpellState.Casting; - - public virtual void OnCasterHurt() - { - // Confirm: Monsters and pets cannot be disturbed. - if (Caster.Player && IsCasting && ProtectionSpell.Registry.TryGetValue(Caster, out double d) && - d <= Utility.RandomDouble() * 100.0) - Disturb(DisturbType.Hurt, false, true); - } - - public virtual void OnCasterKilled() - { - Disturb(DisturbType.Kill); - } - - public virtual void OnConnectionChanged() - { - FinishSequence(); - } - - public virtual bool OnCasterMoving(Direction d) - { - if (IsCasting && BlocksMovement) - { - Caster.SendLocalizedMessage(500111); // You are frozen and can not move. - return false; - } - - return true; - } - - public virtual bool OnCasterEquipping(Item item) - { - if (IsCasting) - Disturb(DisturbType.EquipRequest); - - return true; - } - - public virtual bool OnCasterUsingObject(IEntity entity) - { - if (State == SpellState.Sequencing) - Disturb(DisturbType.UseRequest); - - return true; - } - - public virtual bool OnCastInTown(Region r) => Info.AllowTown; - - public void StartDelayedDamageContext(Mobile m, Timer t) - { - if (DelayedDamageStacking) - return; // Sanity - - if (!m_ContextTable.TryGetValue(GetType(), out DelayedDamageContextWrapper contexts)) - m_ContextTable[GetType()] = contexts = new DelayedDamageContextWrapper(); - - contexts.Add(m, t); - } - - public void RemoveDelayedDamageContext(Mobile m) - { - if (m_ContextTable.TryGetValue(GetType(), out DelayedDamageContextWrapper contexts)) - contexts.Remove(m); - } - - public void HarmfulSpell(Mobile m) - { - (m as BaseCreature)?.OnHarmfulSpell(Caster); - } - - public virtual int GetNewAosDamage(int bonus, uint dice, uint sides, Mobile singleTarget) - { - if (singleTarget != null) - return GetNewAosDamage(bonus, dice, sides, Caster.Player && singleTarget.Player, - GetDamageScalar(singleTarget)); - - return GetNewAosDamage(bonus, dice, sides, false); - } - - public virtual int GetNewAosDamage(int bonus, uint dice, uint sides, bool playerVsPlayer) => GetNewAosDamage(bonus, dice, sides, playerVsPlayer, 1.0); - - public virtual int GetNewAosDamage(int bonus, uint dice, uint sides, bool playerVsPlayer, double scalar) - { - int damage = Utility.Dice(dice, sides, bonus) * 100; - - int inscribeSkill = GetInscribeFixed(Caster); - int inscribeBonus = (inscribeSkill + 1000 * (inscribeSkill / 1000)) / 200; - int damageBonus = inscribeBonus; - - int intBonus = Caster.Int / 10; - damageBonus += intBonus; - - int sdiBonus = AosAttributes.GetValue(Caster, AosAttribute.SpellDamage); - // PvP spell damage increase cap of 15% from an item�s magic property - if (playerVsPlayer && sdiBonus > 15) - sdiBonus = 15; - - damageBonus += sdiBonus; - - TransformContext context = TransformationSpellHelper.GetContext(Caster); - - if (context?.Spell is ReaperFormSpell spell) - damageBonus += spell.SpellDamageBonus; - - damage = AOS.Scale(damage, 100 + damageBonus); - - int evalSkill = GetDamageFixed(Caster); - int evalScale = 30 + 9 * evalSkill / 100; - - damage = AOS.Scale(damage, evalScale); - - damage = AOS.Scale(damage, (int)(scalar * 100)); - - return damage / 100; - } - - public virtual bool ConsumeReagents() => - Scroll != null || !Caster.Player || - AosAttributes.GetValue(Caster, AosAttribute.LowerRegCost) > Utility.Random(100) || - DuelContext.IsFreeConsume(Caster) || Caster.Backpack?.ConsumeTotal(Info.Reagents, Info.Amounts) == -1; - - public virtual double GetInscribeSkill(Mobile m) => m.Skills.Inscribe.Value; - - public virtual int GetInscribeFixed(Mobile m) => m.Skills.Inscribe.Fixed; - - public virtual int GetDamageFixed(Mobile m) => m.Skills[DamageSkill].Fixed; - - public virtual double GetDamageSkill(Mobile m) => m.Skills[DamageSkill].Value; - - public virtual double GetResistSkill(Mobile m) => m.Skills.MagicResist.Value; - - public virtual double GetDamageScalar(Mobile target) - { - double scalar = 1.0; - - if (!Core.AOS) // EvalInt stuff for AoS is handled elsewhere - { - double casterEI = Caster.Skills[DamageSkill].Value; - double targetRS = target.Skills.MagicResist.Value; - - /* - if (Core.AOS) - targetRS = 0; - */ - - // m_Caster.CheckSkill( DamageSkill, 0.0, 120.0 ); - - if (casterEI > targetRS) - scalar = 1.0 + (casterEI - targetRS) / 500.0; - else - scalar = 1.0 + (casterEI - targetRS) / 200.0; - - // magery damage bonus, -25% at 0 skill, +0% at 100 skill, +5% at 120 skill - scalar += (Caster.Skills[CastSkill].Value - 100.0) / 400.0; - - if (!target.Player && !target.Body.IsHuman /*&& !Core.AOS*/) - scalar *= 2.0; // Double magery damage to monsters/animals if not AOS - } - - (target as BaseCreature)?.AlterDamageScalarFrom(Caster, ref scalar); - - (Caster as BaseCreature)?.AlterDamageScalarTo(target, ref scalar); - - if (Core.SE) - scalar *= GetSlayerDamageScalar(target); - - target.Region.SpellDamageScalar(Caster, target, ref scalar); - - if (Evasion.CheckSpellEvasion(target)) // Only single target spells an be evaded - scalar = 0; - - return scalar; - } - - public virtual double GetSlayerDamageScalar(Mobile defender) - { - Spellbook atkBook = Spellbook.FindEquippedSpellbook(Caster); - - double scalar = 1.0; - if (atkBook != null) - { - SlayerEntry atkSlayer = SlayerGroup.GetEntryByName(atkBook.Slayer); - SlayerEntry atkSlayer2 = SlayerGroup.GetEntryByName(atkBook.Slayer2); - - if (atkSlayer?.Slays(defender) == true || atkSlayer2?.Slays(defender) == true) + public Spell(Mobile caster, Item scroll, SpellInfo info) { - defender.FixedEffect(0x37B9, 10, 5); // TODO: Confirm this displays on OSIs - scalar = 2.0; + Caster = caster; + Scroll = scroll; + Info = info; } - TransformContext context = TransformationSpellHelper.GetContext(defender); + public SpellState State { get; set; } - if ((atkBook.Slayer == SlayerName.Silver || atkBook.Slayer2 == SlayerName.Silver) && context != null && - context.Type != typeof(HorrificBeastSpell)) - scalar += .25; // Every necromancer transformation other than horrific beast take an additional 25% damage + public Mobile Caster { get; } - if (scalar != 1.0) - return scalar; - } + public SpellInfo Info { get; } - ISlayer defISlayer = Spellbook.FindEquippedSpellbook(defender) ?? defender.Weapon as ISlayer; + public string Name => Info.Name; + public string Mantra => Info.Mantra; + public Type[] Reagents => Info.Reagents; + public Item Scroll { get; } - if (defISlayer != null) - { - SlayerEntry defSlayer = SlayerGroup.GetEntryByName(defISlayer.Slayer); - SlayerEntry defSlayer2 = SlayerGroup.GetEntryByName(defISlayer.Slayer2); + public long StartCastTime { get; private set; } - if (defSlayer?.Group.OppositionSuperSlays(Caster) == true || - defSlayer2?.Group.OppositionSuperSlays(Caster) == true) - scalar = 2.0; - } + public virtual SkillName CastSkill => SkillName.Magery; + public virtual SkillName DamageSkill => SkillName.EvalInt; - return scalar; - } + public virtual bool RevealOnCast => true; + public virtual bool ClearHandsOnCast => true; + public virtual bool ShowHandMovement => true; - public virtual void DoFizzle() - { - Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502632); // The spell fizzles. + public virtual bool DelayedDamage => false; - if (Caster.Player) - { - if (Core.AOS) - Caster.FixedParticles(0x3735, 1, 30, 9503, EffectLayer.Waist); - else - Caster.FixedEffect(0x3735, 6, 30); + public virtual bool DelayedDamageStacking => true; - Caster.PlaySound(0x5C); - } - } + public virtual bool BlockedByHorrificBeast => true; + public virtual bool BlockedByAnimalForm => true; + public virtual bool BlocksMovement => true; - public virtual bool CheckDisturb(DisturbType type, bool firstCircle, bool resistable) => !(resistable && Scroll is BaseWand); + public virtual bool CheckNextSpellTime => !(Scroll is BaseWand); - public void Disturb(DisturbType type, bool firstCircle = true, bool resistable = false) - { - if (!CheckDisturb(type, firstCircle, resistable)) - return; + public virtual int CastRecoveryBase => 6; + public virtual int CastRecoveryFastScalar => 1; + public virtual int CastRecoveryPerSecond => 4; + public virtual int CastRecoveryMinimum => 0; - if (State == SpellState.Casting) - { - if (!firstCircle && !Core.AOS && this is MagerySpell && ((MagerySpell)this).Circle == SpellCircle.First) - return; + public abstract TimeSpan CastDelayBase { get; } - State = SpellState.None; - Caster.Spell = null; + public virtual double CastDelayFastScalar => 1; + public virtual double CastDelaySecondsPerTick => 0.25; + public virtual TimeSpan CastDelayMinimum => TimeSpan.FromSeconds(0.25); - OnDisturb(type, true); + public virtual bool IsCasting => State == SpellState.Casting; - m_CastTimer?.Stop(); - - m_AnimTimer?.Stop(); - - if (Core.AOS && Caster.Player && type == DisturbType.Hurt) - DoHurtFizzle(); - - Caster.NextSpellTime = Core.TickCount + (int)GetDisturbRecovery().TotalMilliseconds; - } - else if (State == SpellState.Sequencing) - { - if (!firstCircle && !Core.AOS && this is MagerySpell && ((MagerySpell)this).Circle == SpellCircle.First) - return; - - State = SpellState.None; - Caster.Spell = null; - - OnDisturb(type, false); - - Target.Cancel(Caster); - - if (Core.AOS && Caster.Player && type == DisturbType.Hurt) - DoHurtFizzle(); - } - } - - public virtual void DoHurtFizzle() - { - Caster.FixedEffect(0x3735, 6, 30); - Caster.PlaySound(0x5C); - } - - public virtual void OnDisturb(DisturbType type, bool message) - { - if (message) - Caster.SendLocalizedMessage(500641); // Your concentration is disturbed, thus ruining thy spell. - } - - public virtual bool CheckCast() => true; - - public virtual void SayMantra() - { - if (Scroll is BaseWand) - return; - - if (!string.IsNullOrEmpty(Info.Mantra) && Caster.Player) - Caster.PublicOverheadMessage(MessageType.Spell, Caster.SpeechHue, true, Info.Mantra, false); - } - - public bool Cast() - { - StartCastTime = Core.TickCount; - - if (Core.AOS && Caster.Spell is Spell spell && spell.State == SpellState.Sequencing) - spell.Disturb(DisturbType.NewCast); - - if (!Caster.CheckAlive()) return false; - - if (Scroll is BaseWand && Caster.Spell?.IsCasting == true) - { - Caster.SendLocalizedMessage(502643); // You can not cast a spell while frozen. - } - else if (Caster.Spell?.IsCasting == true) - { - Caster.SendLocalizedMessage(502642); // You are already casting a spell. - } - else if (BlockedByHorrificBeast && - TransformationSpellHelper.UnderTransformation(Caster, typeof(HorrificBeastSpell)) || - BlockedByAnimalForm && AnimalForm.UnderTransformation(Caster)) - { - Caster.SendLocalizedMessage(1061091); // You cannot cast that spell in this form. - } - else if (!(Scroll is BaseWand) && (Caster.Paralyzed || Caster.Frozen)) - { - Caster.SendLocalizedMessage(502643); // You can not cast a spell while frozen. - } - else if (CheckNextSpellTime && Core.TickCount - Caster.NextSpellTime < 0) - { - Caster.SendLocalizedMessage(502644); // You have not yet recovered from casting a spell. - } - else if (Caster is PlayerMobile mobile && mobile.PeacedUntil > DateTime.UtcNow) - { - mobile.SendLocalizedMessage(1072060); // You cannot cast a spell while calmed. - } - else if ((Caster as PlayerMobile)?.DuelContext?.AllowSpellCast(Caster, this) == false) - { - } - else if (Caster.Mana >= ScaleMana(GetMana())) - { - if (Caster.Spell == null && Caster.CheckSpellCast(this) && CheckCast() && - Caster.Region.OnBeginSpellCast(Caster, this)) + public virtual void OnCasterHurt() { - State = SpellState.Casting; - Caster.Spell = this; + // Confirm: Monsters and pets cannot be disturbed. + if (Caster.Player && IsCasting && ProtectionSpell.Registry.TryGetValue(Caster, out var d) && + d <= Utility.RandomDouble() * 100.0) + Disturb(DisturbType.Hurt, false, true); + } - if (!(Scroll is BaseWand) && RevealOnCast) - Caster.RevealingAction(); + public virtual void OnCasterKilled() + { + Disturb(DisturbType.Kill); + } - SayMantra(); + public virtual void OnConnectionChanged() + { + FinishSequence(); + } - TimeSpan castDelay = GetCastDelay(); - - if (ShowHandMovement && (Caster.Body.IsHuman || (Caster.Player && Caster.Body.IsMonster))) - { - int count = (int)Math.Ceiling(castDelay.TotalSeconds / AnimateDelay.TotalSeconds); - - if (count != 0) + public virtual bool OnCasterMoving(Direction d) + { + if (IsCasting && BlocksMovement) { - m_AnimTimer = new AnimTimer(this, count); - m_AnimTimer.Start(); + Caster.SendLocalizedMessage(500111); // You are frozen and can not move. + return false; } - if (Info.LeftHandEffect > 0) - Caster.FixedParticles(0, 10, 5, Info.LeftHandEffect, EffectLayer.LeftHand); - - if (Info.RightHandEffect > 0) - Caster.FixedParticles(0, 10, 5, Info.RightHandEffect, EffectLayer.RightHand); - } - - if (ClearHandsOnCast) - Caster.ClearHands(); - - if (Core.ML) - WeaponAbility.ClearCurrentAbility(Caster); - - m_CastTimer = new CastTimer(this, castDelay); - // m_CastTimer.Start(); - - OnBeginCast(); - - if (castDelay > TimeSpan.Zero) - m_CastTimer.Start(); - else - m_CastTimer.Tick(); - - return true; + return true; } - return false; - } - else - { - Caster.LocalOverheadMessage(MessageType.Regular, 0x22, 502625); // Insufficient mana - } - - return false; - } - - public abstract void OnCast(); - - public virtual void OnBeginCast() - { - } - - public virtual void GetCastSkills(out double min, out double max) - { - min = max = 0; // Intended but not required for overriding. - } - - public virtual bool CheckFizzle() - { - if (Scroll is BaseWand) - return true; - - GetCastSkills(out double minSkill, out double maxSkill); - - if (DamageSkill != CastSkill) - Caster.CheckSkill(DamageSkill, 0.0, Caster.Skills[DamageSkill].Cap); - - return Caster.CheckSkill(CastSkill, minSkill, maxSkill); - } - - public abstract int GetMana(); - - public virtual int ScaleMana(int mana) - { - double scalar = 1.0; - - if (!MindRotSpell.GetMindRotScalar(Caster, ref scalar)) - scalar = 1.0; - - // Lower Mana Cost = 40% - int lmc = AosAttributes.GetValue(Caster, AosAttribute.LowerManaCost); - if (lmc > 40) - lmc = 40; - - scalar -= (double)lmc / 100; - - return (int)(mana * scalar); - } - - public virtual TimeSpan GetDisturbRecovery() - { - if (Core.AOS) - return TimeSpan.Zero; - - double delay = Math.Max(1.0 - Math.Sqrt((Core.TickCount - StartCastTime) / 1000.0 / GetCastDelay().TotalSeconds), 0.2); - - return TimeSpan.FromSeconds(delay); - } - - public virtual TimeSpan GetCastRecovery() - { - if (!Core.AOS) - return NextSpellDelay; - - int fcr = AosAttributes.GetValue(Caster, AosAttribute.CastRecovery) - ThunderstormSpell.GetCastRecoveryMalus(Caster); - - int fcrDelay = -(CastRecoveryFastScalar * fcr); - - int delay = CastRecoveryBase + fcrDelay; - - if (delay < CastRecoveryMinimum) - delay = CastRecoveryMinimum; - - return TimeSpan.FromSeconds((double)delay / CastRecoveryPerSecond); - } - - // public virtual int CastDelayBase{ get{ return 3; } } - // public virtual int CastDelayFastScalar{ get{ return 1; } } - // public virtual int CastDelayPerSecond{ get{ return 4; } } - // public virtual int CastDelayMinimum{ get{ return 1; } } - - public virtual TimeSpan GetCastDelay() - { - if (Scroll is BaseWand) - return Core.ML ? CastDelayBase : TimeSpan.Zero; // TODO: Should FC apply to wands? - - // Faster casting cap of 2 (if not using the protection spell) - // Faster casting cap of 0 (if using the protection spell) - // Paladin spells are subject to a faster casting cap of 4 - // Paladins with magery of 70.0 or above are subject to a faster casting cap of 2 - int fcMax = 4; - - if (CastSkill == SkillName.Magery || CastSkill == SkillName.Necromancy || - CastSkill == SkillName.Chivalry && Caster.Skills.Magery.Value >= 70.0) - fcMax = 2; - - int fc = Math.Min(AosAttributes.GetValue(Caster, AosAttribute.CastSpeed), fcMax); - - if (ProtectionSpell.Registry.ContainsKey(Caster)) - fc -= 2; - - if (EssenceOfWindSpell.IsDebuffed(Caster)) - fc -= EssenceOfWindSpell.GetFCMalus(Caster); - - TimeSpan fcDelay = TimeSpan.FromSeconds(-(CastDelayFastScalar * fc * CastDelaySecondsPerTick)); - - return (CastDelayBase + fcDelay).Max(CastDelayMinimum); - } - - public virtual void FinishSequence() - { - State = SpellState.None; - - if (Caster.Spell == this) - Caster.Spell = null; - } - - public virtual int ComputeKarmaAward() => 0; - - public virtual bool CheckSequence() - { - int mana = ScaleMana(GetMana()); - - if (Caster.Deleted || !Caster.Alive || Caster.Spell != this || State != SpellState.Sequencing) - { - DoFizzle(); - } - else if (Scroll != null && !(Scroll is Runebook) && - (Scroll.Amount <= 0 || Scroll.Deleted || Scroll.RootParent != Caster || Scroll is BaseWand baseWand && - (baseWand.Charges <= 0 || baseWand.Parent != Caster))) - { - DoFizzle(); - } - else if (!ConsumeReagents()) - { - Caster.LocalOverheadMessage(MessageType.Regular, 0x22, 502630); // More reagents are needed for this spell. - } - else if (Caster.Mana < mana) - { - Caster.LocalOverheadMessage(MessageType.Regular, 0x22, 502625); // Insufficient mana for this spell. - } - else if (Core.AOS && (Caster.Frozen || Caster.Paralyzed)) - { - Caster.SendLocalizedMessage(502646); // You cannot cast a spell while frozen. - DoFizzle(); - } - else if (Caster is PlayerMobile mobile && mobile.PeacedUntil > DateTime.UtcNow) - { - mobile.SendLocalizedMessage(1072060); // You cannot cast a spell while calmed. - DoFizzle(); - } - else if (CheckFizzle()) - { - Caster.Mana -= mana; - - if (Scroll is SpellScroll) + public virtual bool OnCasterEquipping(Item item) { - Scroll.Consume(); + if (IsCasting) + Disturb(DisturbType.EquipRequest); + + return true; } - else if (Scroll is BaseWand wand) + + public virtual bool OnCasterUsingObject(IEntity entity) { - wand.ConsumeCharge(Caster); - Caster.RevealingAction(); + if (State == SpellState.Sequencing) + Disturb(DisturbType.UseRequest); + + return true; } - if (Scroll is BaseWand) + public virtual bool OnCastInTown(Region r) => Info.AllowTown; + + public virtual void FinishSequence() { - bool m = Scroll.Movable; + State = SpellState.None; - Scroll.Movable = false; - - if (ClearHandsOnCast) - Caster.ClearHands(); - - Scroll.Movable = m; + if (Caster.Spell == this) + Caster.Spell = null; } - else + + public void StartDelayedDamageContext(Mobile m, Timer t) { - if (ClearHandsOnCast) - Caster.ClearHands(); + if (DelayedDamageStacking) + return; // Sanity + + if (!m_ContextTable.TryGetValue(GetType(), out var contexts)) + m_ContextTable[GetType()] = contexts = new DelayedDamageContextWrapper(); + + contexts.Add(m, t); } - int karma = ComputeKarmaAward(); - - if (karma != 0) - Titles.AwardKarma(Caster, karma, true); - - if (TransformationSpellHelper.UnderTransformation(Caster, typeof(VampiricEmbraceSpell))) + public void RemoveDelayedDamageContext(Mobile m) { - bool garlic = false; - - for (int i = 0; !garlic && i < Info.Reagents.Length; ++i) - garlic = Info.Reagents[i] == Reagent.Garlic; - - if (garlic) - { - Caster.SendLocalizedMessage(1061651); // The garlic burns you! - AOS.Damage(Caster, Utility.RandomMinMax(17, 23), 100, 0, 0, 0, 0); - } + if (m_ContextTable.TryGetValue(GetType(), out var contexts)) + contexts.Remove(m); } - return true; - } - else - { - DoFizzle(); - } + public void HarmfulSpell(Mobile m) + { + (m as BaseCreature)?.OnHarmfulSpell(Caster); + } - return false; + public virtual int GetNewAosDamage(int bonus, uint dice, uint sides, Mobile singleTarget) + { + if (singleTarget != null) + return GetNewAosDamage( + bonus, + dice, + sides, + Caster.Player && singleTarget.Player, + GetDamageScalar(singleTarget) + ); + + return GetNewAosDamage(bonus, dice, sides, false); + } + + public virtual int GetNewAosDamage(int bonus, uint dice, uint sides, bool playerVsPlayer) => + GetNewAosDamage(bonus, dice, sides, playerVsPlayer, 1.0); + + public virtual int GetNewAosDamage(int bonus, uint dice, uint sides, bool playerVsPlayer, double scalar) + { + var damage = Utility.Dice(dice, sides, bonus) * 100; + + var inscribeSkill = GetInscribeFixed(Caster); + var inscribeBonus = (inscribeSkill + 1000 * (inscribeSkill / 1000)) / 200; + var damageBonus = inscribeBonus; + + var intBonus = Caster.Int / 10; + damageBonus += intBonus; + + var sdiBonus = AosAttributes.GetValue(Caster, AosAttribute.SpellDamage); + // PvP spell damage increase cap of 15% from an item�s magic property + if (playerVsPlayer && sdiBonus > 15) + sdiBonus = 15; + + damageBonus += sdiBonus; + + var context = TransformationSpellHelper.GetContext(Caster); + + if (context?.Spell is ReaperFormSpell spell) + damageBonus += spell.SpellDamageBonus; + + damage = AOS.Scale(damage, 100 + damageBonus); + + var evalSkill = GetDamageFixed(Caster); + var evalScale = 30 + 9 * evalSkill / 100; + + damage = AOS.Scale(damage, evalScale); + + damage = AOS.Scale(damage, (int)(scalar * 100)); + + return damage / 100; + } + + public virtual bool ConsumeReagents() => + Scroll != null || !Caster.Player || + AosAttributes.GetValue(Caster, AosAttribute.LowerRegCost) > Utility.Random(100) || + DuelContext.IsFreeConsume(Caster) || Caster.Backpack?.ConsumeTotal(Info.Reagents, Info.Amounts) == -1; + + public virtual double GetInscribeSkill(Mobile m) => m.Skills.Inscribe.Value; + + public virtual int GetInscribeFixed(Mobile m) => m.Skills.Inscribe.Fixed; + + public virtual int GetDamageFixed(Mobile m) => m.Skills[DamageSkill].Fixed; + + public virtual double GetDamageSkill(Mobile m) => m.Skills[DamageSkill].Value; + + public virtual double GetResistSkill(Mobile m) => m.Skills.MagicResist.Value; + + public virtual double GetDamageScalar(Mobile target) + { + var scalar = 1.0; + + if (!Core.AOS) // EvalInt stuff for AoS is handled elsewhere + { + var casterEI = Caster.Skills[DamageSkill].Value; + var targetRS = target.Skills.MagicResist.Value; + + /* + if (Core.AOS) + targetRS = 0; + */ + + // m_Caster.CheckSkill( DamageSkill, 0.0, 120.0 ); + + if (casterEI > targetRS) + scalar = 1.0 + (casterEI - targetRS) / 500.0; + else + scalar = 1.0 + (casterEI - targetRS) / 200.0; + + // magery damage bonus, -25% at 0 skill, +0% at 100 skill, +5% at 120 skill + scalar += (Caster.Skills[CastSkill].Value - 100.0) / 400.0; + + if (!target.Player && !target.Body.IsHuman /*&& !Core.AOS*/) + scalar *= 2.0; // Double magery damage to monsters/animals if not AOS + } + + (target as BaseCreature)?.AlterDamageScalarFrom(Caster, ref scalar); + + (Caster as BaseCreature)?.AlterDamageScalarTo(target, ref scalar); + + if (Core.SE) + scalar *= GetSlayerDamageScalar(target); + + target.Region.SpellDamageScalar(Caster, target, ref scalar); + + if (Evasion.CheckSpellEvasion(target)) // Only single target spells an be evaded + scalar = 0; + + return scalar; + } + + public virtual double GetSlayerDamageScalar(Mobile defender) + { + var atkBook = Spellbook.FindEquippedSpellbook(Caster); + + var scalar = 1.0; + if (atkBook != null) + { + var atkSlayer = SlayerGroup.GetEntryByName(atkBook.Slayer); + var atkSlayer2 = SlayerGroup.GetEntryByName(atkBook.Slayer2); + + if (atkSlayer?.Slays(defender) == true || atkSlayer2?.Slays(defender) == true) + { + defender.FixedEffect(0x37B9, 10, 5); // TODO: Confirm this displays on OSIs + scalar = 2.0; + } + + var context = TransformationSpellHelper.GetContext(defender); + + if ((atkBook.Slayer == SlayerName.Silver || atkBook.Slayer2 == SlayerName.Silver) && context != null && + context.Type != typeof(HorrificBeastSpell)) + scalar += .25; // Every necromancer transformation other than horrific beast take an additional 25% damage + + if (scalar != 1.0) + return scalar; + } + + var defISlayer = Spellbook.FindEquippedSpellbook(defender) ?? defender.Weapon as ISlayer; + + if (defISlayer != null) + { + var defSlayer = SlayerGroup.GetEntryByName(defISlayer.Slayer); + var defSlayer2 = SlayerGroup.GetEntryByName(defISlayer.Slayer2); + + if (defSlayer?.Group.OppositionSuperSlays(Caster) == true || + defSlayer2?.Group.OppositionSuperSlays(Caster) == true) + scalar = 2.0; + } + + return scalar; + } + + public virtual void DoFizzle() + { + Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502632); // The spell fizzles. + + if (Caster.Player) + { + if (Core.AOS) + Caster.FixedParticles(0x3735, 1, 30, 9503, EffectLayer.Waist); + else + Caster.FixedEffect(0x3735, 6, 30); + + Caster.PlaySound(0x5C); + } + } + + public virtual bool CheckDisturb(DisturbType type, bool firstCircle, bool resistable) => + !(resistable && Scroll is BaseWand); + + public void Disturb(DisturbType type, bool firstCircle = true, bool resistable = false) + { + if (!CheckDisturb(type, firstCircle, resistable)) + return; + + if (State == SpellState.Casting) + { + if (!firstCircle && !Core.AOS && this is MagerySpell && ((MagerySpell)this).Circle == SpellCircle.First) + return; + + State = SpellState.None; + Caster.Spell = null; + + OnDisturb(type, true); + + m_CastTimer?.Stop(); + + m_AnimTimer?.Stop(); + + if (Core.AOS && Caster.Player && type == DisturbType.Hurt) + DoHurtFizzle(); + + Caster.NextSpellTime = Core.TickCount + (int)GetDisturbRecovery().TotalMilliseconds; + } + else if (State == SpellState.Sequencing) + { + if (!firstCircle && !Core.AOS && this is MagerySpell && ((MagerySpell)this).Circle == SpellCircle.First) + return; + + State = SpellState.None; + Caster.Spell = null; + + OnDisturb(type, false); + + Target.Cancel(Caster); + + if (Core.AOS && Caster.Player && type == DisturbType.Hurt) + DoHurtFizzle(); + } + } + + public virtual void DoHurtFizzle() + { + Caster.FixedEffect(0x3735, 6, 30); + Caster.PlaySound(0x5C); + } + + public virtual void OnDisturb(DisturbType type, bool message) + { + if (message) + Caster.SendLocalizedMessage(500641); // Your concentration is disturbed, thus ruining thy spell. + } + + public virtual bool CheckCast() => true; + + public virtual void SayMantra() + { + if (Scroll is BaseWand) + return; + + if (!string.IsNullOrEmpty(Info.Mantra) && Caster.Player) + Caster.PublicOverheadMessage(MessageType.Spell, Caster.SpeechHue, true, Info.Mantra, false); + } + + public bool Cast() + { + StartCastTime = Core.TickCount; + + if (Core.AOS && Caster.Spell is Spell spell && spell.State == SpellState.Sequencing) + spell.Disturb(DisturbType.NewCast); + + if (!Caster.CheckAlive()) return false; + + if (Scroll is BaseWand && Caster.Spell?.IsCasting == true) + { + Caster.SendLocalizedMessage(502643); // You can not cast a spell while frozen. + } + else if (Caster.Spell?.IsCasting == true) + { + Caster.SendLocalizedMessage(502642); // You are already casting a spell. + } + else if (BlockedByHorrificBeast && + TransformationSpellHelper.UnderTransformation(Caster, typeof(HorrificBeastSpell)) || + BlockedByAnimalForm && AnimalForm.UnderTransformation(Caster)) + { + Caster.SendLocalizedMessage(1061091); // You cannot cast that spell in this form. + } + else if (!(Scroll is BaseWand) && (Caster.Paralyzed || Caster.Frozen)) + { + Caster.SendLocalizedMessage(502643); // You can not cast a spell while frozen. + } + else if (CheckNextSpellTime && Core.TickCount - Caster.NextSpellTime < 0) + { + Caster.SendLocalizedMessage(502644); // You have not yet recovered from casting a spell. + } + else if (Caster is PlayerMobile mobile && mobile.PeacedUntil > DateTime.UtcNow) + { + mobile.SendLocalizedMessage(1072060); // You cannot cast a spell while calmed. + } + else if ((Caster as PlayerMobile)?.DuelContext?.AllowSpellCast(Caster, this) == false) + { + } + else if (Caster.Mana >= ScaleMana(GetMana())) + { + if (Caster.Spell == null && Caster.CheckSpellCast(this) && CheckCast() && + Caster.Region.OnBeginSpellCast(Caster, this)) + { + State = SpellState.Casting; + Caster.Spell = this; + + if (!(Scroll is BaseWand) && RevealOnCast) + Caster.RevealingAction(); + + SayMantra(); + + var castDelay = GetCastDelay(); + + if (ShowHandMovement && (Caster.Body.IsHuman || Caster.Player && Caster.Body.IsMonster)) + { + var count = (int)Math.Ceiling(castDelay.TotalSeconds / AnimateDelay.TotalSeconds); + + if (count != 0) + { + m_AnimTimer = new AnimTimer(this, count); + m_AnimTimer.Start(); + } + + if (Info.LeftHandEffect > 0) + Caster.FixedParticles(0, 10, 5, Info.LeftHandEffect, EffectLayer.LeftHand); + + if (Info.RightHandEffect > 0) + Caster.FixedParticles(0, 10, 5, Info.RightHandEffect, EffectLayer.RightHand); + } + + if (ClearHandsOnCast) + Caster.ClearHands(); + + if (Core.ML) + WeaponAbility.ClearCurrentAbility(Caster); + + m_CastTimer = new CastTimer(this, castDelay); + // m_CastTimer.Start(); + + OnBeginCast(); + + if (castDelay > TimeSpan.Zero) + m_CastTimer.Start(); + else + m_CastTimer.Tick(); + + return true; + } + + return false; + } + else + { + Caster.LocalOverheadMessage(MessageType.Regular, 0x22, 502625); // Insufficient mana + } + + return false; + } + + public abstract void OnCast(); + + public virtual void OnBeginCast() + { + } + + public virtual void GetCastSkills(out double min, out double max) + { + min = max = 0; // Intended but not required for overriding. + } + + public virtual bool CheckFizzle() + { + if (Scroll is BaseWand) + return true; + + GetCastSkills(out var minSkill, out var maxSkill); + + if (DamageSkill != CastSkill) + Caster.CheckSkill(DamageSkill, 0.0, Caster.Skills[DamageSkill].Cap); + + return Caster.CheckSkill(CastSkill, minSkill, maxSkill); + } + + public abstract int GetMana(); + + public virtual int ScaleMana(int mana) + { + var scalar = 1.0; + + if (!MindRotSpell.GetMindRotScalar(Caster, ref scalar)) + scalar = 1.0; + + // Lower Mana Cost = 40% + var lmc = AosAttributes.GetValue(Caster, AosAttribute.LowerManaCost); + if (lmc > 40) + lmc = 40; + + scalar -= (double)lmc / 100; + + return (int)(mana * scalar); + } + + public virtual TimeSpan GetDisturbRecovery() + { + if (Core.AOS) + return TimeSpan.Zero; + + var delay = Math.Max( + 1.0 - Math.Sqrt((Core.TickCount - StartCastTime) / 1000.0 / GetCastDelay().TotalSeconds), + 0.2 + ); + + return TimeSpan.FromSeconds(delay); + } + + public virtual TimeSpan GetCastRecovery() + { + if (!Core.AOS) + return NextSpellDelay; + + var fcr = AosAttributes.GetValue(Caster, AosAttribute.CastRecovery) - + ThunderstormSpell.GetCastRecoveryMalus(Caster); + + var fcrDelay = -(CastRecoveryFastScalar * fcr); + + var delay = CastRecoveryBase + fcrDelay; + + if (delay < CastRecoveryMinimum) + delay = CastRecoveryMinimum; + + return TimeSpan.FromSeconds((double)delay / CastRecoveryPerSecond); + } + + // public virtual int CastDelayBase{ get{ return 3; } } + // public virtual int CastDelayFastScalar{ get{ return 1; } } + // public virtual int CastDelayPerSecond{ get{ return 4; } } + // public virtual int CastDelayMinimum{ get{ return 1; } } + + public virtual TimeSpan GetCastDelay() + { + if (Scroll is BaseWand) + return Core.ML ? CastDelayBase : TimeSpan.Zero; // TODO: Should FC apply to wands? + + // Faster casting cap of 2 (if not using the protection spell) + // Faster casting cap of 0 (if using the protection spell) + // Paladin spells are subject to a faster casting cap of 4 + // Paladins with magery of 70.0 or above are subject to a faster casting cap of 2 + var fcMax = 4; + + if (CastSkill == SkillName.Magery || CastSkill == SkillName.Necromancy || + CastSkill == SkillName.Chivalry && Caster.Skills.Magery.Value >= 70.0) + fcMax = 2; + + var fc = Math.Min(AosAttributes.GetValue(Caster, AosAttribute.CastSpeed), fcMax); + + if (ProtectionSpell.Registry.ContainsKey(Caster)) + fc -= 2; + + if (EssenceOfWindSpell.IsDebuffed(Caster)) + fc -= EssenceOfWindSpell.GetFCMalus(Caster); + + var fcDelay = TimeSpan.FromSeconds(-(CastDelayFastScalar * fc * CastDelaySecondsPerTick)); + + return (CastDelayBase + fcDelay).Max(CastDelayMinimum); + } + + public virtual int ComputeKarmaAward() => 0; + + public virtual bool CheckSequence() + { + var mana = ScaleMana(GetMana()); + + if (Caster.Deleted || !Caster.Alive || Caster.Spell != this || State != SpellState.Sequencing) + { + DoFizzle(); + } + else if (Scroll != null && !(Scroll is Runebook) && + (Scroll.Amount <= 0 || Scroll.Deleted || Scroll.RootParent != Caster || Scroll is BaseWand baseWand && + (baseWand.Charges <= 0 || baseWand.Parent != Caster))) + { + DoFizzle(); + } + else if (!ConsumeReagents()) + { + Caster.LocalOverheadMessage(MessageType.Regular, 0x22, 502630); // More reagents are needed for this spell. + } + else if (Caster.Mana < mana) + { + Caster.LocalOverheadMessage(MessageType.Regular, 0x22, 502625); // Insufficient mana for this spell. + } + else if (Core.AOS && (Caster.Frozen || Caster.Paralyzed)) + { + Caster.SendLocalizedMessage(502646); // You cannot cast a spell while frozen. + DoFizzle(); + } + else if (Caster is PlayerMobile mobile && mobile.PeacedUntil > DateTime.UtcNow) + { + mobile.SendLocalizedMessage(1072060); // You cannot cast a spell while calmed. + DoFizzle(); + } + else if (CheckFizzle()) + { + Caster.Mana -= mana; + + if (Scroll is SpellScroll) + { + Scroll.Consume(); + } + else if (Scroll is BaseWand wand) + { + wand.ConsumeCharge(Caster); + Caster.RevealingAction(); + } + + if (Scroll is BaseWand) + { + var m = Scroll.Movable; + + Scroll.Movable = false; + + if (ClearHandsOnCast) + Caster.ClearHands(); + + Scroll.Movable = m; + } + else + { + if (ClearHandsOnCast) + Caster.ClearHands(); + } + + var karma = ComputeKarmaAward(); + + if (karma != 0) + Titles.AwardKarma(Caster, karma, true); + + if (TransformationSpellHelper.UnderTransformation(Caster, typeof(VampiricEmbraceSpell))) + { + var garlic = false; + + for (var i = 0; !garlic && i < Info.Reagents.Length; ++i) + garlic = Info.Reagents[i] == Reagent.Garlic; + + if (garlic) + { + Caster.SendLocalizedMessage(1061651); // The garlic burns you! + AOS.Damage(Caster, Utility.RandomMinMax(17, 23), 100, 0, 0, 0, 0); + } + } + + return true; + } + else + { + DoFizzle(); + } + + return false; + } + + public bool CheckBSequence(Mobile target) => CheckBSequence(target, false); + + public bool CheckBSequence(Mobile target, bool allowDead) + { + if (!target.Alive && !allowDead) + { + Caster.SendLocalizedMessage(501857); // This spell won't work on that! + return false; + } + + if (Caster.CanBeBeneficial(target, true, allowDead) && CheckSequence()) + { + Caster.DoBeneficial(target); + return true; + } + + return false; + } + + public bool CheckHSequence(Mobile target) + { + if (!target.Alive) + { + Caster.SendLocalizedMessage(501857); // This spell won't work on that! + return false; + } + + if (Caster.CanBeHarmful(target) && CheckSequence()) + { + Caster.DoHarmful(target); + return true; + } + + return false; + } + + private class DelayedDamageContextWrapper + { + private readonly Dictionary m_Contexts = new Dictionary(); + + public void Add(Mobile m, Timer t) + { + if (m_Contexts.TryGetValue(m, out var oldTimer)) + { + oldTimer.Stop(); + m_Contexts.Remove(m); + } + + m_Contexts.Add(m, t); + } + + public void Remove(Mobile m) + { + m_Contexts.Remove(m); + } + } + + private class AnimTimer : Timer + { + private readonly Spell m_Spell; + + public AnimTimer(Spell spell, int count) : base(TimeSpan.Zero, AnimateDelay, count) + { + m_Spell = spell; + + Priority = TimerPriority.FiftyMS; + } + + protected override void OnTick() + { + if (m_Spell.State != SpellState.Casting || m_Spell.Caster.Spell != m_Spell) + { + Stop(); + return; + } + + if (!m_Spell.Caster.Mounted && m_Spell.Info.Action >= 0) + { + if (m_Spell.Caster.Body.IsHuman) + m_Spell.Caster.Animate(m_Spell.Info.Action, 7, 1, true, false, 0); + else if (m_Spell.Caster.Player && m_Spell.Caster.Body.IsMonster) + m_Spell.Caster.Animate(12, 7, 1, true, false, 0); + } + + if (!Running) + m_Spell.m_AnimTimer = null; + } + } + + private class CastTimer : Timer + { + private readonly Spell m_Spell; + + public CastTimer(Spell spell, TimeSpan castDelay) : base(castDelay) + { + m_Spell = spell; + + Priority = TimerPriority.TwentyFiveMS; + } + + protected override void OnTick() + { + if (m_Spell?.Caster == null) return; + + if (m_Spell.State == SpellState.Casting && m_Spell.Caster.Spell == m_Spell) + { + m_Spell.State = SpellState.Sequencing; + m_Spell.m_CastTimer = null; + m_Spell.Caster.OnSpellCast(m_Spell); + m_Spell.Caster.Region?.OnSpellCast(m_Spell.Caster, m_Spell); + m_Spell.Caster.NextSpellTime = + Core.TickCount + (int)m_Spell.GetCastRecovery().TotalMilliseconds; // Spell.NextSpellDelay; + + var originalTarget = m_Spell.Caster.Target; + + m_Spell.OnCast(); + + if (m_Spell.Caster.Player && m_Spell.Caster.Target != originalTarget) + m_Spell.Caster.Target?.BeginTimeout(m_Spell.Caster, TimeSpan.FromSeconds(30.0)); + + m_Spell.m_CastTimer = null; + } + } + + public void Tick() + { + OnTick(); + } + } } - - public bool CheckBSequence(Mobile target) => CheckBSequence(target, false); - - public bool CheckBSequence(Mobile target, bool allowDead) - { - if (!target.Alive && !allowDead) - { - Caster.SendLocalizedMessage(501857); // This spell won't work on that! - return false; - } - - if (Caster.CanBeBeneficial(target, true, allowDead) && CheckSequence()) - { - Caster.DoBeneficial(target); - return true; - } - - return false; - } - - public bool CheckHSequence(Mobile target) - { - if (!target.Alive) - { - Caster.SendLocalizedMessage(501857); // This spell won't work on that! - return false; - } - - if (Caster.CanBeHarmful(target) && CheckSequence()) - { - Caster.DoHarmful(target); - return true; - } - - return false; - } - - private class DelayedDamageContextWrapper - { - private readonly Dictionary m_Contexts = new Dictionary(); - - public void Add(Mobile m, Timer t) - { - if (m_Contexts.TryGetValue(m, out Timer oldTimer)) - { - oldTimer.Stop(); - m_Contexts.Remove(m); - } - - m_Contexts.Add(m, t); - } - - public void Remove(Mobile m) - { - m_Contexts.Remove(m); - } - } - - private class AnimTimer : Timer - { - private readonly Spell m_Spell; - - public AnimTimer(Spell spell, int count) : base(TimeSpan.Zero, AnimateDelay, count) - { - m_Spell = spell; - - Priority = TimerPriority.FiftyMS; - } - - protected override void OnTick() - { - if (m_Spell.State != SpellState.Casting || m_Spell.Caster.Spell != m_Spell) - { - Stop(); - return; - } - - if (!m_Spell.Caster.Mounted && m_Spell.Info.Action >= 0) - { - if (m_Spell.Caster.Body.IsHuman) - m_Spell.Caster.Animate(m_Spell.Info.Action, 7, 1, true, false, 0); - else if (m_Spell.Caster.Player && m_Spell.Caster.Body.IsMonster) - m_Spell.Caster.Animate(12, 7, 1, true, false, 0); - } - - if (!Running) - m_Spell.m_AnimTimer = null; - } - } - - private class CastTimer : Timer - { - private readonly Spell m_Spell; - - public CastTimer(Spell spell, TimeSpan castDelay) : base(castDelay) - { - m_Spell = spell; - - Priority = TimerPriority.TwentyFiveMS; - } - - protected override void OnTick() - { - if (m_Spell?.Caster == null) return; - - if (m_Spell.State == SpellState.Casting && m_Spell.Caster.Spell == m_Spell) - { - m_Spell.State = SpellState.Sequencing; - m_Spell.m_CastTimer = null; - m_Spell.Caster.OnSpellCast(m_Spell); - m_Spell.Caster.Region?.OnSpellCast(m_Spell.Caster, m_Spell); - m_Spell.Caster.NextSpellTime = - Core.TickCount + (int)m_Spell.GetCastRecovery().TotalMilliseconds; // Spell.NextSpellDelay; - - Target originalTarget = m_Spell.Caster.Target; - - m_Spell.OnCast(); - - if (m_Spell.Caster.Player && m_Spell.Caster.Target != originalTarget) - m_Spell.Caster.Target?.BeginTimeout(m_Spell.Caster, TimeSpan.FromSeconds(30.0)); - - m_Spell.m_CastTimer = null; - } - } - - public void Tick() - { - OnTick(); - } - } - } } diff --git a/Projects/UOContent/Spells/Base/SpellCircle.cs b/Projects/UOContent/Spells/Base/SpellCircle.cs index 38e932db4..f0a6435f0 100644 --- a/Projects/UOContent/Spells/Base/SpellCircle.cs +++ b/Projects/UOContent/Spells/Base/SpellCircle.cs @@ -1,14 +1,14 @@ namespace Server.Spells { - public enum SpellCircle - { - First, - Second, - Third, - Fourth, - Fifth, - Sixth, - Seventh, - Eighth - } -} \ No newline at end of file + public enum SpellCircle + { + First, + Second, + Third, + Fourth, + Fifth, + Sixth, + Seventh, + Eighth + } +} diff --git a/Projects/UOContent/Spells/Base/SpellHelper.cs b/Projects/UOContent/Spells/Base/SpellHelper.cs index 344a39b83..68d07f96e 100644 --- a/Projects/UOContent/Spells/Base/SpellHelper.cs +++ b/Projects/UOContent/Spells/Base/SpellHelper.cs @@ -18,1276 +18,1318 @@ using Server.Targeting; namespace Server { - public class DefensiveSpell - { - public static void Nullify(Mobile from) + public class DefensiveSpell { - if (!from.CanBeginAction()) - new InternalTimer(from).Start(); + public static void Nullify(Mobile from) + { + if (!from.CanBeginAction()) + new InternalTimer(from).Start(); + } + + private class InternalTimer : Timer + { + private readonly Mobile m_Mobile; + + public InternalTimer(Mobile m) + : base(TimeSpan.FromMinutes(1.0)) + { + m_Mobile = m; + + Priority = TimerPriority.OneSecond; + } + + protected override void OnTick() + { + m_Mobile.EndAction(); + } + } } - - private class InternalTimer : Timer - { - private readonly Mobile m_Mobile; - - public InternalTimer(Mobile m) - : base(TimeSpan.FromMinutes(1.0)) - { - m_Mobile = m; - - Priority = TimerPriority.OneSecond; - } - - protected override void OnTick() - { - m_Mobile.EndAction(); - } - } - } } namespace Server.Spells { - public enum TravelCheckType - { - RecallFrom, - RecallTo, - GateFrom, - GateTo, - Mark, - TeleportFrom, - TeleportTo - } - - public class SpellHelper - { - private static readonly TimeSpan AosDamageDelay = TimeSpan.FromSeconds(1.0); - private static readonly TimeSpan OldDamageDelay = TimeSpan.FromSeconds(0.5); - - private static readonly TimeSpan CombatHeatDelay = TimeSpan.FromSeconds(30.0); - private static readonly bool RestrictTravelCombat = true; - - private static readonly int[] m_Offsets = + public enum TravelCheckType { - -1, -1, - -1, 0, - -1, 1, - 0, -1, - 0, 1, - 1, -1, - 1, 0, - 1, 1 - }; - - private static readonly TravelValidator[] m_Validators = - { - IsFeluccaT2A, - IsKhaldun, - IsIlshenar, - IsTrammelWind, - IsFeluccaWind, - IsFeluccaDungeon, - IsTrammelSolenHive, - IsFeluccaSolenHive, - IsCrystalCave, - IsDoomGauntlet, - IsDoomFerry, - IsSafeZone, - IsFactionStronghold, - IsChampionSpawn, - IsTokunoDungeon, - IsLampRoom, - IsGuardianRoom, - IsHeartwood, - IsMLDungeon - }; - - // TODO: Move to configuration - private static readonly bool[,] m_Rules = - { - /* T2A(Fel), Khaldun, Ilshenar, Wind(Tram), Wind(Fel), Dungeons(Fel), Solen(Tram), Solen(Fel), CrystalCave(Malas), Gauntlet(Malas), Gauntlet(Ferry), SafeZone, Stronghold, ChampionSpawn, Dungeons(Tokuno[Malas]), LampRoom(Doom), GuardianRoom(Doom), Heartwood, MLDungeons */ - /* Recall From */ - { - false, false, true, true, false, false, true, false, false, false, false, true, true, false, true, false, - false, false, false - }, - /* Recall To */ - { - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false - }, - /* Gate From */ - { - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false - }, - /* Gate To */ - { - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false - }, - /* Mark In */ - { - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false - }, - /* Tele From */ - { - true, true, true, true, true, true, true, true, false, true, true, true, false, true, true, true, true, - false, true - }, - /* Tele To */ - { - true, true, true, true, true, true, true, true, false, true, false, false, false, true, true, true, true, - false, false - } - }; - - private static Mobile m_TravelCaster; - private static TravelCheckType m_TravelType; - - public static bool DisableSkillCheck { get; set; } - - public static TimeSpan GetDamageDelayForSpell(Spell sp) => - !sp.DelayedDamage ? TimeSpan.Zero : Core.AOS ? AosDamageDelay : OldDamageDelay; - - public static bool CheckMulti(Point3D p, Map map, bool houses = true, int housingrange = 0) - { - if (map == null || map == Map.Internal) - return false; - - Sector sector = map.GetSector(p.X, p.Y); - - for (int i = 0; i < sector.Multis.Count; ++i) - { - BaseMulti multi = sector.Multis[i]; - - if (multi is BaseHouse bh) - { - if (houses && bh.IsInside(p, 16) || housingrange > 0 && bh.InRange(p, housingrange)) - return true; - } - else if (multi.Contains(p)) - { - return true; - } - } - - return false; + RecallFrom, + RecallTo, + GateFrom, + GateTo, + Mark, + TeleportFrom, + TeleportTo } - public static void Turn(Mobile from, object to) + public class SpellHelper { - if (!(to is IPoint3D target)) - return; + private static readonly TimeSpan AosDamageDelay = TimeSpan.FromSeconds(1.0); + private static readonly TimeSpan OldDamageDelay = TimeSpan.FromSeconds(0.5); - if (target is Item item) - { - if (item.RootParent != from) - from.Direction = from.GetDirectionTo(item.GetWorldLocation()); - } - else if (from != target) - { - from.Direction = from.GetDirectionTo(target); - } - } + private static readonly TimeSpan CombatHeatDelay = TimeSpan.FromSeconds(30.0); + private static readonly bool RestrictTravelCombat = true; - public static bool CheckCombat(Mobile m) - { - if (!RestrictTravelCombat) - return false; - - for (int i = 0; i < m.Aggressed.Count; ++i) - { - AggressorInfo info = m.Aggressed[i]; - - if (info.Defender.Player && DateTime.UtcNow - info.LastCombatTime < CombatHeatDelay) - return true; - } - - if (Core.Expansion == Expansion.AOS) - for (int i = 0; i < m.Aggressors.Count; ++i) + private static readonly int[] m_Offsets = { - AggressorInfo info = m.Aggressors[i]; + -1, -1, + -1, 0, + -1, 1, + 0, -1, + 0, 1, + 1, -1, + 1, 0, + 1, 1 + }; + + private static readonly TravelValidator[] m_Validators = + { + IsFeluccaT2A, + IsKhaldun, + IsIlshenar, + IsTrammelWind, + IsFeluccaWind, + IsFeluccaDungeon, + IsTrammelSolenHive, + IsFeluccaSolenHive, + IsCrystalCave, + IsDoomGauntlet, + IsDoomFerry, + IsSafeZone, + IsFactionStronghold, + IsChampionSpawn, + IsTokunoDungeon, + IsLampRoom, + IsGuardianRoom, + IsHeartwood, + IsMLDungeon + }; + + // TODO: Move to configuration + private static readonly bool[,] m_Rules = + { + /* T2A(Fel), Khaldun, Ilshenar, Wind(Tram), Wind(Fel), Dungeons(Fel), Solen(Tram), Solen(Fel), CrystalCave(Malas), Gauntlet(Malas), Gauntlet(Ferry), SafeZone, Stronghold, ChampionSpawn, Dungeons(Tokuno[Malas]), LampRoom(Doom), GuardianRoom(Doom), Heartwood, MLDungeons */ + /* Recall From */ + { + false, false, true, true, false, false, true, false, false, false, false, true, true, false, true, false, + false, false, false + }, + /* Recall To */ + { + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false + }, + /* Gate From */ + { + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false + }, + /* Gate To */ + { + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false + }, + /* Mark In */ + { + false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, + false, false, false, false + }, + /* Tele From */ + { + true, true, true, true, true, true, true, true, false, true, true, true, false, true, true, true, true, + false, true + }, + /* Tele To */ + { + true, true, true, true, true, true, true, true, false, true, false, false, false, true, true, true, true, + false, false + } + }; + + private static Mobile m_TravelCaster; + private static TravelCheckType m_TravelType; + + public static bool DisableSkillCheck { get; set; } + + public static TimeSpan GetDamageDelayForSpell(Spell sp) => + !sp.DelayedDamage ? TimeSpan.Zero : + Core.AOS ? AosDamageDelay : OldDamageDelay; + + public static bool CheckMulti(Point3D p, Map map, bool houses = true, int housingrange = 0) + { + if (map == null || map == Map.Internal) + return false; + + var sector = map.GetSector(p.X, p.Y); + + for (var i = 0; i < sector.Multis.Count; ++i) + { + var multi = sector.Multis[i]; + + if (multi is BaseHouse bh) + { + if (houses && bh.IsInside(p, 16) || housingrange > 0 && bh.InRange(p, housingrange)) + return true; + } + else if (multi.Contains(p)) + { + return true; + } + } + + return false; + } + + public static void Turn(Mobile from, object to) + { + if (!(to is IPoint3D target)) + return; + + if (target is Item item) + { + if (item.RootParent != from) + from.Direction = from.GetDirectionTo(item.GetWorldLocation()); + } + else if (from != target) + { + from.Direction = from.GetDirectionTo(target); + } + } + + public static bool CheckCombat(Mobile m) + { + if (!RestrictTravelCombat) + return false; + + for (var i = 0; i < m.Aggressed.Count; ++i) + { + var info = m.Aggressed[i]; + + if (info.Defender.Player && DateTime.UtcNow - info.LastCombatTime < CombatHeatDelay) + return true; + } + + if (Core.Expansion == Expansion.AOS) + for (var i = 0; i < m.Aggressors.Count; ++i) + { + var info = m.Aggressors[i]; + + if (info.Attacker.Player && DateTime.UtcNow - info.LastCombatTime < CombatHeatDelay) + return true; + } + + return false; + } + + public static bool AdjustField(ref Point3D p, Map map, int height, bool mobsBlock) + { + if (map == null) + return false; + + for (var offset = 0; offset < 10; ++offset) + { + var loc = new Point3D(p.X, p.Y, p.Z - offset); + + if (map.CanFit(loc, height, true, mobsBlock)) + { + p = loc; + return true; + } + } + + return false; + } + + public static bool CanRevealCaster(Mobile m) => m is BaseCreature c && !c.Controlled; + + public static void GetSurfaceTop(ref IPoint3D p) + { + if (p is Item item) + { + p = item.GetSurfaceTop(); + } + else if (p is StaticTarget t) + { + var z = t.Z; + + if ((t.Flags & TileFlag.Surface) == 0) + z -= TileData.ItemTable[t.ItemID & TileData.MaxItemValue].CalcHeight; + + p = new Point3D(t.X, t.Y, z); + } + } + + public static bool AddStatOffset(Mobile m, StatType type, int offset, TimeSpan duration) => + offset > 0 + ? AddStatBonus(m, m, type, offset, duration) + : offset >= 0 || AddStatCurse(m, m, type, -offset, duration); + + public static bool AddStatBonus(Mobile caster, Mobile target, StatType type) => AddStatBonus( + caster, + target, + type, + GetOffset(caster, target, type, false), + GetDuration(caster, target) + ); + + public static bool AddStatBonus(Mobile caster, Mobile target, StatType type, int bonus, TimeSpan duration) + { + var offset = bonus; + var name = $"[Magic] {type} Offset"; + + var mod = target.GetStatMod(name); + + if (mod?.Offset < 0) + { + target.AddStatMod(new StatMod(type, name, mod.Offset + offset, duration)); + return true; + } + + if (mod == null || mod.Offset < offset) + { + target.AddStatMod(new StatMod(type, name, offset, duration)); + return true; + } + + return false; + } + + public static bool AddStatCurse(Mobile caster, Mobile target, StatType type) => AddStatCurse( + caster, + target, + type, + GetOffset(caster, target, type, true), + GetDuration(caster, target) + ); + + public static bool AddStatCurse(Mobile caster, Mobile target, StatType type, int curse, TimeSpan duration) + { + var offset = -curse; + var name = $"[Magic] {type} Offset"; + + var mod = target.GetStatMod(name); + + if (mod?.Offset > 0) + { + target.AddStatMod(new StatMod(type, name, mod.Offset + offset, duration)); + return true; + } + + if (mod == null || mod.Offset > offset) + { + target.AddStatMod(new StatMod(type, name, offset, duration)); + return true; + } + + return false; + } + + public static TimeSpan GetDuration(Mobile caster, Mobile target) => + Core.AOS + ? TimeSpan.FromSeconds(6 * caster.Skills.EvalInt.Fixed / 50 + 1) + : TimeSpan.FromSeconds(caster.Skills.Magery.Value * 1.2); + + public static double GetOffsetScalar(Mobile caster, Mobile target, bool curse) + { + double percent; + + if (curse) + percent = 8 + caster.Skills.EvalInt.Fixed / 100 - target.Skills.MagicResist.Fixed / 100; + else + percent = 1 + caster.Skills.EvalInt.Fixed / 100; + + percent *= 0.01; + + return Math.Max(percent, 0); + } + + public static int GetOffset(Mobile caster, Mobile target, StatType type, bool curse) + { + if (Core.AOS) + { + if (!DisableSkillCheck) + { + caster.CheckSkill(SkillName.EvalInt, 0.0, 120.0); + + if (curse) + target.CheckSkill(SkillName.MagicResist, 0.0, 120.0); + } + + var percent = GetOffsetScalar(caster, target, curse); + + switch (type) + { + case StatType.Str: + return (int)(target.RawStr * percent); + case StatType.Dex: + return (int)(target.RawDex * percent); + case StatType.Int: + return (int)(target.RawInt * percent); + } + } + + return 1 + (int)(caster.Skills.Magery.Value * 0.1); + } + + public static Guild GetGuildFor(Mobile m) + { + var g = m.Guild as Guild; + + if (g == null && m is BaseCreature c) + { + m = c.ControlMaster; + + if (m != null) + g = m.Guild as Guild; + + if (g == null) + { + m = c.SummonMaster; + + if (m != null) + g = m.Guild as Guild; + } + } + + return g; + } + + public static bool ValidIndirectTarget(Mobile from, Mobile to) + { + if (from == to) + return true; + + if (to.Hidden && to.AccessLevel > from.AccessLevel) + return false; + + var bcFrom = from as BaseCreature; + var bcTarg = to as BaseCreature; + + PlayerMobile pmFrom; + PlayerMobile pmTarg; + + if (bcFrom?.Summoned == true) + pmFrom = bcFrom.SummonMaster as PlayerMobile; + else + pmFrom = from as PlayerMobile; + + if (bcTarg?.Summoned == true) + pmTarg = bcTarg.SummonMaster as PlayerMobile; + else + pmTarg = to as PlayerMobile; + + if (pmFrom?.DuelContext != null && pmFrom.DuelContext == pmTarg?.DuelContext && pmFrom.DuelContext.Started && + pmFrom.DuelPlayer != null && pmTarg?.DuelPlayer != null) + return pmFrom.DuelPlayer.Participant != pmTarg.DuelPlayer.Participant; + + var fromGuild = GetGuildFor(from); + var toGuild = GetGuildFor(to); + + if (fromGuild != null && toGuild != null && (fromGuild == toGuild || fromGuild.IsAlly(toGuild))) + return false; + + var p = Party.Get(from); + + if (p?.Contains(to) == true) + return false; + + if (bcTarg != null && (bcTarg.Controlled || bcTarg.Summoned)) + { + if (bcTarg.ControlMaster == from || bcTarg.SummonMaster == from) + return false; + + if (p != null && (p.Contains(bcTarg.ControlMaster) || p.Contains(bcTarg.SummonMaster))) + return false; + } + + if (bcFrom != null && (bcFrom.Controlled || bcFrom.Summoned)) + { + if (bcFrom.ControlMaster == to || bcFrom.SummonMaster == to) + return false; + + p = Party.Get(to); + + if (p != null && (p.Contains(bcFrom.ControlMaster) || p.Contains(bcFrom.SummonMaster))) + return false; + } + + return bcTarg?.Controlled == false && bcTarg.InitialInnocent || + Notoriety.Compute(from, to) != Notoriety.Innocent || from.Kills >= 5; + } + + public static void Summon( + BaseCreature creature, Mobile caster, int sound, TimeSpan duration, bool scaleDuration, + bool scaleStats + ) + { + var map = caster.Map; + + if (map == null) + return; + + var scale = 1.0 + (caster.Skills.Magery.Value - 100.0) / 200.0; + + if (scaleDuration) + duration = TimeSpan.FromSeconds(duration.TotalSeconds * scale); + + if (scaleStats) + { + creature.RawStr = (int)(creature.RawStr * scale); + creature.Hits = creature.HitsMax; + + creature.RawDex = (int)(creature.RawDex * scale); + creature.Stam = creature.StamMax; + + creature.RawInt = (int)(creature.RawInt * scale); + creature.Mana = creature.ManaMax; + } + + var p = new Point3D(caster); + + if (FindValidSpawnLocation(map, ref p, true)) + { + BaseCreature.Summon(creature, caster, p, sound, duration); + return; + } + + /* + int offset = Utility.Random( 8 ) * 2; + + for ( int i = 0; i < m_Offsets.Length; i += 2 ) + { + int x = caster.X + m_Offsets[(offset + i) % m_Offsets.Length]; + int y = caster.Y + m_Offsets[(offset + i + 1) % m_Offsets.Length]; + + if (map.CanSpawnMobile( x, y, caster.Z )) + { + BaseCreature.Summon( creature, caster, new Point3D( x, y, caster.Z ), sound, duration ); + return; + } + else + { + int z = map.GetAverageZ( x, y ); + + if (map.CanSpawnMobile( x, y, z )) + { + BaseCreature.Summon( creature, caster, new Point3D( x, y, z ), sound, duration ); + return; + } + } + } + * */ + + creature.Delete(); + caster.SendLocalizedMessage(501942); // That location is blocked. + } + + public static bool FindValidSpawnLocation(Map map, ref Point3D p, bool surroundingsOnly) + { + if (map == null) // sanity + return false; + + if (!surroundingsOnly) + { + if (map.CanSpawnMobile(p)) // p's fine. + { + p = new Point3D(p); + return true; + } + + var z = map.GetAverageZ(p.X, p.Y); + + if (map.CanSpawnMobile(p.X, p.Y, z)) + { + p = new Point3D(p.X, p.Y, z); + return true; + } + } + + var offset = Utility.Random(8) * 2; + + for (var i = 0; i < m_Offsets.Length; i += 2) + { + var x = p.X + m_Offsets[(offset + i) % m_Offsets.Length]; + var y = p.Y + m_Offsets[(offset + i + 1) % m_Offsets.Length]; + + if (map.CanSpawnMobile(x, y, p.Z)) + { + p = new Point3D(x, y, p.Z); + return true; + } + + var z = map.GetAverageZ(x, y); + + if (map.CanSpawnMobile(x, y, z)) + { + p = new Point3D(x, y, z); + return true; + } + } + + return false; + } + + public static void SendInvalidMessage(Mobile caster, TravelCheckType type) + { + if (type == TravelCheckType.RecallTo || type == TravelCheckType.GateTo) + caster.SendLocalizedMessage(1019004); // You are not allowed to travel there. + else if (type == TravelCheckType.TeleportTo) + caster.SendLocalizedMessage(501035); // You cannot teleport from here to the destination. + else + caster.SendLocalizedMessage(501802); // Thy spell doth not appear to work... + } + + public static bool CheckTravel(Mobile caster, TravelCheckType type) => + CheckTravel(caster, caster.Map, caster.Location, type); + + public static bool CheckTravel(Map map, Point3D loc, TravelCheckType type) => CheckTravel(null, map, loc, type); + + public static bool CheckTravel(Mobile caster, Map map, Point3D loc, TravelCheckType type) + { + if (IsInvalid(map, loc)) // null, internal, out of bounds + { + if (caster != null) + SendInvalidMessage(caster, type); + + return false; + } + + // Always allow monsters to teleport + if (caster is BaseCreature bc && !bc.Controlled && !bc.Summoned && + (type == TravelCheckType.TeleportTo || type == TravelCheckType.TeleportFrom)) + return true; + + m_TravelCaster = caster; + m_TravelType = type; + + var v = (int)type; + var isValid = true; + + if (caster != null) + { + var destination = Region.Find(loc, map) as BaseRegion; + var current = Region.Find(caster.Location, map) as BaseRegion; + + if (destination?.CheckTravel(caster, loc, type) == false || current?.CheckTravel(caster, loc, type) == false) + isValid = false; + } + + for (var i = 0; isValid && i < m_Validators.Length; ++i) + isValid = m_Rules[v, i] || !m_Validators[i](map, loc); + + if (!isValid && caster != null) + SendInvalidMessage(caster, type); + + return isValid; + } + + public static bool IsWindLoc(Point3D loc) + { + int x = loc.X, y = loc.Y; + + return x >= 5120 && y >= 0 && x < 5376 && y < 256; + } + + public static bool IsFeluccaWind(Map map, Point3D loc) => map == Map.Felucca && IsWindLoc(loc); + + public static bool IsTrammelWind(Map map, Point3D loc) => map == Map.Trammel && IsWindLoc(loc); + + public static bool IsIlshenar(Map map, Point3D loc) => map == Map.Ilshenar; + + public static bool IsSolenHiveLoc(Point3D loc) + { + int x = loc.X, y = loc.Y; + + return x >= 5640 && y >= 1776 && x < 5935 && y < 2039; + } + + public static bool IsTrammelSolenHive(Map map, Point3D loc) => map == Map.Trammel && IsSolenHiveLoc(loc); + + public static bool IsFeluccaSolenHive(Map map, Point3D loc) => map == Map.Felucca && IsSolenHiveLoc(loc); + + public static bool IsFeluccaT2A(Map map, Point3D loc) + { + int x = loc.X, y = loc.Y; + + return map == Map.Felucca && x >= 5120 && y >= 2304 && x < 6144 && y < 4096; + } + + public static bool IsAnyT2A(Map map, Point3D loc) + { + int x = loc.X, y = loc.Y; + + return (map == Map.Trammel || map == Map.Felucca) && x >= 5120 && y >= 2304 && x < 6144 && y < 4096; + } + + public static bool IsFeluccaDungeon(Map map, Point3D loc) + { + var region = Region.Find(loc, map); + return region.IsPartOf() && region.Map == Map.Felucca; + } + + public static bool IsKhaldun(Map map, Point3D loc) => Region.Find(loc, map).Name == "Khaldun"; + + public static bool IsCrystalCave(Map map, Point3D loc) + { + if (map != Map.Malas || loc.Z >= -80) + return false; + + int x = loc.X, y = loc.Y; + + return x >= 1182 && y >= 437 && x < 1211 && y < 470 + || x >= 1156 && y >= 470 && x < 1211 && y < 503 + || x >= 1176 && y >= 503 && x < 1208 && y < 509 + || x >= 1188 && y >= 509 && x < 1201 && y < 513; + } + + public static bool IsSafeZone(Map map, Point3D loc) => + Region.Find(loc, map).IsPartOf() && + (m_TravelType == TravelCheckType.TeleportTo || m_TravelType == TravelCheckType.TeleportFrom) + && (m_TravelCaster as PlayerMobile)?.DuelPlayer?.Eliminated == false; + + public static bool IsFactionStronghold(Map map, Point3D loc) => Region.Find(loc, map).IsPartOf(); + + public static bool IsChampionSpawn(Map map, Point3D loc) => Region.Find(loc, map).IsPartOf(); + + public static bool IsDoomFerry(Map map, Point3D loc) + { + if (map != Map.Malas) + return false; + + int x = loc.X, y = loc.Y; + + return x >= 426 && y >= 314 && x <= 430 && y <= 331 || x >= 406 && y >= 247 && x <= 410 && y <= 264; + } + + public static bool IsTokunoDungeon(Map map, Point3D loc) + { + // The tokuno dungeons are really inside malas + if (map != Map.Malas) + return false; + + int x = loc.X, y = loc.Y, z = loc.Z; + + var r1 = x >= 0 && y >= 0 && x <= 128 && y <= 128; + var r2 = x >= 45 && y >= 320 && x < 195 && y < 710; + + return r1 || r2; + } + + public static bool IsDoomGauntlet(Map map, Point3D loc) + { + if (map != Map.Malas) + return false; + + int x = loc.X - 256, y = loc.Y - 304; + + return x >= 0 && y >= 0 && x < 256 && y < 256; + } + + public static bool IsLampRoom(Map map, Point3D loc) + { + if (map != Map.Malas) + return false; + + int x = loc.X, y = loc.Y; + + return x >= 465 && y >= 92 && x < 474 && y < 102; + } + + public static bool IsGuardianRoom(Map map, Point3D loc) + { + if (map != Map.Malas) + return false; + + int x = loc.X, y = loc.Y; + + return x >= 356 && y >= 5 && x < 375 && y < 25; + } + + public static bool IsHeartwood(Map map, Point3D loc) + { + int x = loc.X, y = loc.Y; + + return (map == Map.Trammel || map == Map.Felucca) && x >= 6911 && y >= 254 && x < 7167 && y < 511; + } + + public static bool IsMLDungeon(Map map, Point3D loc) => MondainsLegacy.IsMLRegion(Region.Find(loc, map)); + + public static bool IsInvalid(Map map, Point3D loc) + { + if (map == null || map == Map.Internal) + return true; + + int x = loc.X, y = loc.Y; + + return x < 0 || y < 0 || x >= map.Width || y >= map.Height; + } + + // towns + public static bool IsTown(IPoint3D ip, Mobile caster) + { + if (ip is Item item) + ip = item.GetWorldLocation(); + + return IsTown(new Point3D(ip), caster); + } + + public static bool IsTown(Point3D loc, Mobile caster) + { + var map = caster.Map; + + if (map == null) + return false; + + if (Region.Find(loc, map).GetRegion() != null) + if (caster is PlayerMobile pm && (pm.DuelContext?.Started != true || pm.DuelPlayer?.Eliminated != false)) + return true; + + var reg = Region.Find(loc, map).GetRegion(); + + return reg?.IsDisabled() == false; + } + + public static bool CheckTown(IPoint3D ip, Mobile caster) + { + if (ip is Item item) + ip = item.GetWorldLocation(); + + return CheckTown(new Point3D(ip), caster); + } + + public static bool CheckTown(Point3D loc, Mobile caster) + { + if (IsTown(loc, caster)) + { + caster.SendLocalizedMessage(500946); // You cannot cast this in town! + return false; + } - if (info.Attacker.Player && DateTime.UtcNow - info.LastCombatTime < CombatHeatDelay) return true; } - return false; - } - - public static bool AdjustField(ref Point3D p, Map map, int height, bool mobsBlock) - { - if (map == null) - return false; - - for (int offset = 0; offset < 10; ++offset) - { - Point3D loc = new Point3D(p.X, p.Y, p.Z - offset); - - if (map.CanFit(loc, height, true, mobsBlock)) + // magic reflection + public static void CheckReflect(int circle, Mobile caster, ref Mobile target) { - p = loc; - return true; - } - } - - return false; - } - - public static bool CanRevealCaster(Mobile m) => m is BaseCreature c && !c.Controlled; - - public static void GetSurfaceTop(ref IPoint3D p) - { - if (p is Item item) - { - p = item.GetSurfaceTop(); - } - else if (p is StaticTarget t) - { - int z = t.Z; - - if ((t.Flags & TileFlag.Surface) == 0) - z -= TileData.ItemTable[t.ItemID & TileData.MaxItemValue].CalcHeight; - - p = new Point3D(t.X, t.Y, z); - } - } - - public static bool AddStatOffset(Mobile m, StatType type, int offset, TimeSpan duration) => - offset > 0 - ? AddStatBonus(m, m, type, offset, duration) - : offset >= 0 || AddStatCurse(m, m, type, -offset, duration); - - public static bool AddStatBonus(Mobile caster, Mobile target, StatType type) => AddStatBonus(caster, target, type, GetOffset(caster, target, type, false), GetDuration(caster, target)); - - public static bool AddStatBonus(Mobile caster, Mobile target, StatType type, int bonus, TimeSpan duration) - { - int offset = bonus; - string name = $"[Magic] {type} Offset"; - - StatMod mod = target.GetStatMod(name); - - if (mod?.Offset < 0) - { - target.AddStatMod(new StatMod(type, name, mod.Offset + offset, duration)); - return true; - } - - if (mod == null || mod.Offset < offset) - { - target.AddStatMod(new StatMod(type, name, offset, duration)); - return true; - } - - return false; - } - - public static bool AddStatCurse(Mobile caster, Mobile target, StatType type) => AddStatCurse(caster, target, type, GetOffset(caster, target, type, true), GetDuration(caster, target)); - - public static bool AddStatCurse(Mobile caster, Mobile target, StatType type, int curse, TimeSpan duration) - { - int offset = -curse; - string name = $"[Magic] {type} Offset"; - - StatMod mod = target.GetStatMod(name); - - if (mod?.Offset > 0) - { - target.AddStatMod(new StatMod(type, name, mod.Offset + offset, duration)); - return true; - } - - if (mod == null || mod.Offset > offset) - { - target.AddStatMod(new StatMod(type, name, offset, duration)); - return true; - } - - return false; - } - - public static TimeSpan GetDuration(Mobile caster, Mobile target) => - Core.AOS ? TimeSpan.FromSeconds(6 * caster.Skills.EvalInt.Fixed / 50 + 1) : TimeSpan.FromSeconds(caster.Skills.Magery.Value * 1.2); - - public static double GetOffsetScalar(Mobile caster, Mobile target, bool curse) - { - double percent; - - if (curse) - percent = 8 + caster.Skills.EvalInt.Fixed / 100 - target.Skills.MagicResist.Fixed / 100; - else - percent = 1 + caster.Skills.EvalInt.Fixed / 100; - - percent *= 0.01; - - return Math.Max(percent, 0); - } - - public static int GetOffset(Mobile caster, Mobile target, StatType type, bool curse) - { - if (Core.AOS) - { - if (!DisableSkillCheck) - { - caster.CheckSkill(SkillName.EvalInt, 0.0, 120.0); - - if (curse) - target.CheckSkill(SkillName.MagicResist, 0.0, 120.0); + CheckReflect(circle, ref caster, ref target); } - double percent = GetOffsetScalar(caster, target, curse); - - switch (type) + public static void CheckReflect(int circle, ref Mobile caster, ref Mobile target) { - case StatType.Str: - return (int)(target.RawStr * percent); - case StatType.Dex: - return (int)(target.RawDex * percent); - case StatType.Int: - return (int)(target.RawInt * percent); - } - } + if (target.MagicDamageAbsorb > 0) + { + ++circle; - return 1 + (int)(caster.Skills.Magery.Value * 0.1); - } + target.MagicDamageAbsorb -= circle; - public static Guild GetGuildFor(Mobile m) - { - Guild g = m.Guild as Guild; + // This order isn't very intuitive, but you have to nullify reflect before target gets switched - if (g == null && m is BaseCreature c) - { - m = c.ControlMaster; + var reflect = target.MagicDamageAbsorb >= 0; - if (m != null) - g = m.Guild as Guild; + (target as BaseCreature)?.CheckReflect(caster, ref reflect); - if (g == null) - { - m = c.SummonMaster; + if (target.MagicDamageAbsorb <= 0) + { + target.MagicDamageAbsorb = 0; + DefensiveSpell.Nullify(target); + } - if (m != null) - g = m.Guild as Guild; - } - } + if (reflect) + { + target.FixedEffect(0x37B9, 10, 5); - return g; - } + var temp = caster; + caster = target; + target = temp; + } + } + else if (target is BaseCreature creature) + { + var reflect = false; - public static bool ValidIndirectTarget(Mobile from, Mobile to) - { - if (from == to) - return true; + creature.CheckReflect(caster, ref reflect); - if (to.Hidden && to.AccessLevel > from.AccessLevel) - return false; + if (reflect) + { + creature.FixedEffect(0x37B9, 10, 5); - BaseCreature bcFrom = from as BaseCreature; - BaseCreature bcTarg = to as BaseCreature; - - PlayerMobile pmFrom; - PlayerMobile pmTarg; - - if (bcFrom?.Summoned == true) - pmFrom = bcFrom.SummonMaster as PlayerMobile; - else - pmFrom = from as PlayerMobile; - - if (bcTarg?.Summoned == true) - pmTarg = bcTarg.SummonMaster as PlayerMobile; - else - pmTarg = to as PlayerMobile; - - if (pmFrom?.DuelContext != null && pmFrom.DuelContext == pmTarg?.DuelContext && pmFrom.DuelContext.Started && - pmFrom.DuelPlayer != null && pmTarg?.DuelPlayer != null) - return pmFrom.DuelPlayer.Participant != pmTarg.DuelPlayer.Participant; - - Guild fromGuild = GetGuildFor(from); - Guild toGuild = GetGuildFor(to); - - if (fromGuild != null && toGuild != null && (fromGuild == toGuild || fromGuild.IsAlly(toGuild))) - return false; - - Party p = Party.Get(from); - - if (p?.Contains(to) == true) - return false; - - if (bcTarg != null && (bcTarg.Controlled || bcTarg.Summoned)) - { - if (bcTarg.ControlMaster == from || bcTarg.SummonMaster == from) - return false; - - if (p != null && (p.Contains(bcTarg.ControlMaster) || p.Contains(bcTarg.SummonMaster))) - return false; - } - - if (bcFrom != null && (bcFrom.Controlled || bcFrom.Summoned)) - { - if (bcFrom.ControlMaster == to || bcFrom.SummonMaster == to) - return false; - - p = Party.Get(to); - - if (p != null && (p.Contains(bcFrom.ControlMaster) || p.Contains(bcFrom.SummonMaster))) - return false; - } - - return bcTarg?.Controlled == false && bcTarg.InitialInnocent || - Notoriety.Compute(from, to) != Notoriety.Innocent || from.Kills >= 5; - } - - public static void Summon(BaseCreature creature, Mobile caster, int sound, TimeSpan duration, bool scaleDuration, - bool scaleStats) - { - Map map = caster.Map; - - if (map == null) - return; - - double scale = 1.0 + (caster.Skills.Magery.Value - 100.0) / 200.0; - - if (scaleDuration) - duration = TimeSpan.FromSeconds(duration.TotalSeconds * scale); - - if (scaleStats) - { - creature.RawStr = (int)(creature.RawStr * scale); - creature.Hits = creature.HitsMax; - - creature.RawDex = (int)(creature.RawDex * scale); - creature.Stam = creature.StamMax; - - creature.RawInt = (int)(creature.RawInt * scale); - creature.Mana = creature.ManaMax; - } - - Point3D p = new Point3D(caster); - - if (FindValidSpawnLocation(map, ref p, true)) - { - BaseCreature.Summon(creature, caster, p, sound, duration); - return; - } - - /* - int offset = Utility.Random( 8 ) * 2; - - for ( int i = 0; i < m_Offsets.Length; i += 2 ) - { - int x = caster.X + m_Offsets[(offset + i) % m_Offsets.Length]; - int y = caster.Y + m_Offsets[(offset + i + 1) % m_Offsets.Length]; - - if (map.CanSpawnMobile( x, y, caster.Z )) - { - BaseCreature.Summon( creature, caster, new Point3D( x, y, caster.Z ), sound, duration ); - return; - } - else - { - int z = map.GetAverageZ( x, y ); - - if (map.CanSpawnMobile( x, y, z )) - { - BaseCreature.Summon( creature, caster, new Point3D( x, y, z ), sound, duration ); - return; - } - } - } - * */ - - creature.Delete(); - caster.SendLocalizedMessage(501942); // That location is blocked. - } - - public static bool FindValidSpawnLocation(Map map, ref Point3D p, bool surroundingsOnly) - { - if (map == null) // sanity - return false; - - if (!surroundingsOnly) - { - if (map.CanSpawnMobile(p)) // p's fine. - { - p = new Point3D(p); - return true; + var temp = caster; + caster = creature; + target = temp; + } + } } - int z = map.GetAverageZ(p.X, p.Y); - - if (map.CanSpawnMobile(p.X, p.Y, z)) + public static void Damage(Spell spell, Mobile target, double damage) { - p = new Point3D(p.X, p.Y, z); - return true; - } - } + var ts = GetDamageDelayForSpell(spell); - int offset = Utility.Random(8) * 2; - - for (int i = 0; i < m_Offsets.Length; i += 2) - { - int x = p.X + m_Offsets[(offset + i) % m_Offsets.Length]; - int y = p.Y + m_Offsets[(offset + i + 1) % m_Offsets.Length]; - - if (map.CanSpawnMobile(x, y, p.Z)) - { - p = new Point3D(x, y, p.Z); - return true; + Damage(spell, ts, target, spell.Caster, damage); } - int z = map.GetAverageZ(x, y); - - if (map.CanSpawnMobile(x, y, z)) + public static void Damage(TimeSpan delay, Mobile target, double damage) { - p = new Point3D(x, y, z); - return true; - } - } - - return false; - } - - public static void SendInvalidMessage(Mobile caster, TravelCheckType type) - { - if (type == TravelCheckType.RecallTo || type == TravelCheckType.GateTo) - caster.SendLocalizedMessage(1019004); // You are not allowed to travel there. - else if (type == TravelCheckType.TeleportTo) - caster.SendLocalizedMessage(501035); // You cannot teleport from here to the destination. - else - caster.SendLocalizedMessage(501802); // Thy spell doth not appear to work... - } - - public static bool CheckTravel(Mobile caster, TravelCheckType type) => CheckTravel(caster, caster.Map, caster.Location, type); - - public static bool CheckTravel(Map map, Point3D loc, TravelCheckType type) => CheckTravel(null, map, loc, type); - - public static bool CheckTravel(Mobile caster, Map map, Point3D loc, TravelCheckType type) - { - if (IsInvalid(map, loc)) // null, internal, out of bounds - { - if (caster != null) - SendInvalidMessage(caster, type); - - return false; - } - - // Always allow monsters to teleport - if (caster is BaseCreature bc && !bc.Controlled && !bc.Summoned && (type == TravelCheckType.TeleportTo || type == TravelCheckType.TeleportFrom)) - return true; - - m_TravelCaster = caster; - m_TravelType = type; - - int v = (int)type; - bool isValid = true; - - if (caster != null) - { - BaseRegion destination = Region.Find(loc, map) as BaseRegion; - BaseRegion current = Region.Find(caster.Location, map) as BaseRegion; - - if (destination?.CheckTravel(caster, loc, type) == false || current?.CheckTravel(caster, loc, type) == false) - isValid = false; - } - - for (int i = 0; isValid && i < m_Validators.Length; ++i) - isValid = m_Rules[v, i] || !m_Validators[i](map, loc); - - if (!isValid && caster != null) - SendInvalidMessage(caster, type); - - return isValid; - } - - public static bool IsWindLoc(Point3D loc) - { - int x = loc.X, y = loc.Y; - - return x >= 5120 && y >= 0 && x < 5376 && y < 256; - } - - public static bool IsFeluccaWind(Map map, Point3D loc) => map == Map.Felucca && IsWindLoc(loc); - - public static bool IsTrammelWind(Map map, Point3D loc) => map == Map.Trammel && IsWindLoc(loc); - - public static bool IsIlshenar(Map map, Point3D loc) => map == Map.Ilshenar; - - public static bool IsSolenHiveLoc(Point3D loc) - { - int x = loc.X, y = loc.Y; - - return x >= 5640 && y >= 1776 && x < 5935 && y < 2039; - } - - public static bool IsTrammelSolenHive(Map map, Point3D loc) => map == Map.Trammel && IsSolenHiveLoc(loc); - - public static bool IsFeluccaSolenHive(Map map, Point3D loc) => map == Map.Felucca && IsSolenHiveLoc(loc); - - public static bool IsFeluccaT2A(Map map, Point3D loc) - { - int x = loc.X, y = loc.Y; - - return map == Map.Felucca && x >= 5120 && y >= 2304 && x < 6144 && y < 4096; - } - - public static bool IsAnyT2A(Map map, Point3D loc) - { - int x = loc.X, y = loc.Y; - - return (map == Map.Trammel || map == Map.Felucca) && x >= 5120 && y >= 2304 && x < 6144 && y < 4096; - } - - public static bool IsFeluccaDungeon(Map map, Point3D loc) - { - Region region = Region.Find(loc, map); - return region.IsPartOf() && region.Map == Map.Felucca; - } - - public static bool IsKhaldun(Map map, Point3D loc) => Region.Find(loc, map).Name == "Khaldun"; - - public static bool IsCrystalCave(Map map, Point3D loc) - { - if (map != Map.Malas || loc.Z >= -80) - return false; - - int x = loc.X, y = loc.Y; - - return x >= 1182 && y >= 437 && x < 1211 && y < 470 - || x >= 1156 && y >= 470 && x < 1211 && y < 503 - || x >= 1176 && y >= 503 && x < 1208 && y < 509 - || x >= 1188 && y >= 509 && x < 1201 && y < 513; - } - - public static bool IsSafeZone(Map map, Point3D loc) => - Region.Find(loc, map).IsPartOf() && - (m_TravelType == TravelCheckType.TeleportTo || m_TravelType == TravelCheckType.TeleportFrom) - && (m_TravelCaster as PlayerMobile)?.DuelPlayer?.Eliminated == false; - - public static bool IsFactionStronghold(Map map, Point3D loc) => Region.Find(loc, map).IsPartOf(); - - public static bool IsChampionSpawn(Map map, Point3D loc) => Region.Find(loc, map).IsPartOf(); - - public static bool IsDoomFerry(Map map, Point3D loc) - { - if (map != Map.Malas) - return false; - - int x = loc.X, y = loc.Y; - - return x >= 426 && y >= 314 && x <= 430 && y <= 331 || x >= 406 && y >= 247 && x <= 410 && y <= 264; - } - - public static bool IsTokunoDungeon(Map map, Point3D loc) - { - // The tokuno dungeons are really inside malas - if (map != Map.Malas) - return false; - - int x = loc.X, y = loc.Y, z = loc.Z; - - bool r1 = x >= 0 && y >= 0 && x <= 128 && y <= 128; - bool r2 = x >= 45 && y >= 320 && x < 195 && y < 710; - - return r1 || r2; - } - - public static bool IsDoomGauntlet(Map map, Point3D loc) - { - if (map != Map.Malas) - return false; - - int x = loc.X - 256, y = loc.Y - 304; - - return x >= 0 && y >= 0 && x < 256 && y < 256; - } - - public static bool IsLampRoom(Map map, Point3D loc) - { - if (map != Map.Malas) - return false; - - int x = loc.X, y = loc.Y; - - return x >= 465 && y >= 92 && x < 474 && y < 102; - } - - public static bool IsGuardianRoom(Map map, Point3D loc) - { - if (map != Map.Malas) - return false; - - int x = loc.X, y = loc.Y; - - return x >= 356 && y >= 5 && x < 375 && y < 25; - } - - public static bool IsHeartwood(Map map, Point3D loc) - { - int x = loc.X, y = loc.Y; - - return (map == Map.Trammel || map == Map.Felucca) && x >= 6911 && y >= 254 && x < 7167 && y < 511; - } - - public static bool IsMLDungeon(Map map, Point3D loc) => MondainsLegacy.IsMLRegion(Region.Find(loc, map)); - - public static bool IsInvalid(Map map, Point3D loc) - { - if (map == null || map == Map.Internal) - return true; - - int x = loc.X, y = loc.Y; - - return x < 0 || y < 0 || x >= map.Width || y >= map.Height; - } - - // towns - public static bool IsTown(IPoint3D ip, Mobile caster) - { - if (ip is Item item) - ip = item.GetWorldLocation(); - - return IsTown(new Point3D(ip), caster); - } - - public static bool IsTown(Point3D loc, Mobile caster) - { - Map map = caster.Map; - - if (map == null) - return false; - - if (Region.Find(loc, map).GetRegion() != null) - if (caster is PlayerMobile pm && (pm.DuelContext?.Started != true || pm.DuelPlayer?.Eliminated != false)) - return true; - - GuardedRegion reg = Region.Find(loc, map).GetRegion(); - - return reg?.IsDisabled() == false; - } - - public static bool CheckTown(IPoint3D ip, Mobile caster) - { - if (ip is Item item) - ip = item.GetWorldLocation(); - - return CheckTown(new Point3D(ip), caster); - } - - public static bool CheckTown(Point3D loc, Mobile caster) - { - if (IsTown(loc, caster)) - { - caster.SendLocalizedMessage(500946); // You cannot cast this in town! - return false; - } - - return true; - } - - // magic reflection - public static void CheckReflect(int circle, Mobile caster, ref Mobile target) - { - CheckReflect(circle, ref caster, ref target); - } - - public static void CheckReflect(int circle, ref Mobile caster, ref Mobile target) - { - if (target.MagicDamageAbsorb > 0) - { - ++circle; - - target.MagicDamageAbsorb -= circle; - - // This order isn't very intuitive, but you have to nullify reflect before target gets switched - - bool reflect = target.MagicDamageAbsorb >= 0; - - (target as BaseCreature)?.CheckReflect(caster, ref reflect); - - if (target.MagicDamageAbsorb <= 0) - { - target.MagicDamageAbsorb = 0; - DefensiveSpell.Nullify(target); + Damage(delay, target, null, damage); } - if (reflect) + public static void Damage(TimeSpan delay, Mobile target, Mobile from, double damage) { - target.FixedEffect(0x37B9, 10, 5); - - Mobile temp = caster; - caster = target; - target = temp; - } - } - else if (target is BaseCreature creature) - { - bool reflect = false; - - creature.CheckReflect(caster, ref reflect); - - if (reflect) - { - creature.FixedEffect(0x37B9, 10, 5); - - Mobile temp = caster; - caster = creature; - target = temp; - } - } - } - - public static void Damage(Spell spell, Mobile target, double damage) - { - TimeSpan ts = GetDamageDelayForSpell(spell); - - Damage(spell, ts, target, spell.Caster, damage); - } - - public static void Damage(TimeSpan delay, Mobile target, double damage) - { - Damage(delay, target, null, damage); - } - - public static void Damage(TimeSpan delay, Mobile target, Mobile from, double damage) - { - Damage(null, delay, target, from, damage); - } - - public static void Damage(Spell spell, TimeSpan delay, Mobile target, Mobile from, double damage) - { - int iDamage = (int)damage; - - if (delay == TimeSpan.Zero) - { - (from as BaseCreature)?.AlterSpellDamageTo(target, ref iDamage); - - (target as BaseCreature)?.AlterSpellDamageFrom(from, ref iDamage); - - target.Damage(iDamage, from); - } - else - { - new SpellDamageTimer(spell, target, from, iDamage, delay).Start(); - } - - if (target is BaseCreature c && from != null && delay == TimeSpan.Zero) - { - c.OnHarmfulSpell(from); - c.OnDamagedBySpell(from); - } - } - - public static void Damage(Spell spell, Mobile target, double damage, int phys, int fire, int cold, int pois, - int nrgy, int chaos = 0, DFAlgorithm dfa = DFAlgorithm.Standard) - { - Damage(spell, GetDamageDelayForSpell(spell), target, spell.Caster, damage, phys, fire, cold, pois, nrgy, chaos, dfa); - } - - public static void Damage(TimeSpan delay, Mobile target, double damage, int phys, int fire, int cold, int pois, - int nrgy, int chaos = 0, DFAlgorithm dfa = DFAlgorithm.Standard) - { - Damage(delay, target, null, damage, phys, fire, cold, pois, nrgy, chaos, dfa); - } - - public static void Damage(TimeSpan delay, Mobile target, Mobile from, double damage, int phys, int fire, int cold, - int pois, int nrgy, int chaos = 0, DFAlgorithm dfa = DFAlgorithm.Standard) - { - Damage(null, delay, target, from, damage, phys, fire, cold, pois, nrgy, chaos, dfa); - } - - public static void Damage(Spell spell, TimeSpan delay, Mobile target, Mobile from, double damage, int phys, int fire, - int cold, int pois, int nrgy, int chaos = 0, DFAlgorithm dfa = DFAlgorithm.Standard) - { - int dmg = (int)damage; - - if (delay == TimeSpan.Zero) - { - (from as BaseCreature)?.AlterSpellDamageTo(target, ref dmg); - - (target as BaseCreature)?.AlterSpellDamageFrom(from, ref dmg); - - WeightOverloading.DFA = dfa; - - int damageGiven = AOS.Damage(target, from, dmg, phys, fire, cold, pois, nrgy, chaos); - - if (from != null) // sanity check - DoLeech(damageGiven, from, target); - - WeightOverloading.DFA = DFAlgorithm.Standard; - } - else - { - new SpellDamageTimerAOS(spell, delay, target, from, dmg, phys, fire, cold, pois, nrgy, chaos, dfa).Start(); - } - - if (target is BaseCreature c && from != null && delay == TimeSpan.Zero) - { - c.OnHarmfulSpell(from); - c.OnDamagedBySpell(from); - } - } - - public static void DoLeech(int damageGiven, Mobile from, Mobile target) - { - TransformContext context = TransformationSpellHelper.GetContext(from); - - if (context == null) /* cleanup */ - return; - - if (context.Type == typeof(WraithFormSpell)) - { - int wraithLeech = - 5 + (int)(15 * from.Skills.SpiritSpeak.Value / 100); // Wraith form gives 5-20% mana leech - int manaLeech = AOS.Scale(damageGiven, wraithLeech); - - if (manaLeech != 0) - { - from.Mana += manaLeech; - from.PlaySound(0x44D); - } - } - else if (context.Type == typeof(VampiricEmbraceSpell)) - { - from.Hits += AOS.Scale(damageGiven, 20); - from.PlaySound(0x44D); - } - } - - public static void Heal(int amount, Mobile target, Mobile from, bool message = true) - { - // TODO: All Healing *spells* go through ArcaneEmpowerment - target.Heal(amount, from, message); - } - - private delegate bool TravelValidator(Map map, Point3D loc); - - private class SpellDamageTimer : Timer - { - private int m_Damage; - private readonly Spell m_Spell; - private readonly Mobile m_Target; - private readonly Mobile m_From; - - public SpellDamageTimer(Spell s, Mobile target, Mobile from, int damage, TimeSpan delay) - : base(delay) - { - m_Target = target; - m_From = from; - m_Damage = damage; - m_Spell = s; - - if (m_Spell?.DelayedDamage == true && !m_Spell.DelayedDamageStacking) - m_Spell.StartDelayedDamageContext(target, this); - - Priority = TimerPriority.TwentyFiveMS; - } - - protected override void OnTick() - { - (m_From as BaseCreature)?.AlterSpellDamageTo(m_Target, ref m_Damage); - - (m_Target as BaseCreature)?.AlterSpellDamageFrom(m_From, ref m_Damage); - - m_Target.Damage(m_Damage); - m_Spell?.RemoveDelayedDamageContext(m_Target); - } - } - - private class SpellDamageTimerAOS : Timer - { - private int m_Damage; - private readonly DFAlgorithm m_DFA; - private readonly int m_Phys; - private readonly int m_Fire; - private readonly int m_Cold; - private readonly int m_Pois; - private readonly int m_Nrgy; - private readonly int m_Chaos; - private readonly Spell m_Spell; - private readonly Mobile m_Target; - private readonly Mobile m_From; - - public SpellDamageTimerAOS(Spell s, TimeSpan delay, Mobile target, Mobile from, int damage, int phys, int fire, int cold, - int pois, int nrgy, int chaos, DFAlgorithm dfa) - : base(delay) - { - m_Target = target; - m_From = from; - m_Damage = damage; - m_Phys = phys; - m_Fire = fire; - m_Cold = cold; - m_Pois = pois; - m_Nrgy = nrgy; - m_Chaos = chaos; - m_DFA = dfa; - m_Spell = s; - if (m_Spell?.DelayedDamage == true && !m_Spell.DelayedDamageStacking) - m_Spell.StartDelayedDamageContext(target, this); - - Priority = TimerPriority.TwentyFiveMS; - } - - protected override void OnTick() - { - BaseCreature bcFrom = m_From as BaseCreature; - BaseCreature bcTarg = m_Target as BaseCreature; - - if (bcFrom != null && m_Target != null) - bcFrom.AlterSpellDamageTo(m_Target, ref m_Damage); - - if (bcTarg != null && m_From != null) - bcTarg.AlterSpellDamageFrom(m_From, ref m_Damage); - - WeightOverloading.DFA = m_DFA; - - int damageGiven = AOS.Damage(m_Target, m_From, m_Damage, m_Phys, m_Fire, m_Cold, m_Pois, m_Nrgy, m_Chaos); - - if (m_From != null) // sanity check - DoLeech(damageGiven, m_From, m_Target); - - WeightOverloading.DFA = DFAlgorithm.Standard; - - if (bcTarg != null && m_From != null) - { - bcTarg.OnHarmfulSpell(m_From); - bcTarg.OnDamagedBySpell(m_From); + Damage(null, delay, target, from, damage); } - m_Spell?.RemoveDelayedDamageContext(m_Target); - } - } - } - - public class TransformationSpellHelper - { - public static bool CheckCast(Mobile caster, Spell spell) - { - if (Sigil.ExistsOn(caster)) - { - caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. - return false; - } - - if (!caster.CanBeginAction()) - { - caster.SendLocalizedMessage(1061628); // You can't do that while polymorphed. - return false; - } - - if (AnimalForm.UnderTransformation(caster)) - { - caster.SendLocalizedMessage(1061091); // You cannot cast that spell in this form. - return false; - } - - return true; - } - - public static bool OnCast(Mobile caster, Spell spell) - { - if (!(spell is ITransformationSpell transformSpell)) - return false; - - if (Sigil.ExistsOn(caster)) - { - caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. - } - else if (!caster.CanBeginAction()) - { - caster.SendLocalizedMessage(1061628); // You can't do that while polymorphed. - } - else if (DisguiseTimers.IsDisguised(caster)) - { - caster.SendLocalizedMessage(1061631); // You can't do that while disguised. - return false; - } - else if (AnimalForm.UnderTransformation(caster)) - { - caster.SendLocalizedMessage(1061091); // You cannot cast that spell in this form. - } - else if (!caster.CanBeginAction() || caster.IsBodyMod && GetContext(caster) == null) - { - spell.DoFizzle(); - } - else if (spell.CheckSequence()) - { - TransformContext context = GetContext(caster); - Type ourType = spell.GetType(); - - bool wasTransformed = context != null; - bool ourTransform = wasTransformed && context.Type == ourType; - - if (wasTransformed) + public static void Damage(Spell spell, TimeSpan delay, Mobile target, Mobile from, double damage) { - RemoveContext(caster, context, ourTransform); + var iDamage = (int)damage; - if (ourTransform) - { - caster.PlaySound(0xFA); - caster.FixedParticles(0x3728, 1, 13, 5042, EffectLayer.Waist); - } + if (delay == TimeSpan.Zero) + { + (from as BaseCreature)?.AlterSpellDamageTo(target, ref iDamage); + + (target as BaseCreature)?.AlterSpellDamageFrom(from, ref iDamage); + + target.Damage(iDamage, from); + } + else + { + new SpellDamageTimer(spell, target, from, iDamage, delay).Start(); + } + + if (target is BaseCreature c && from != null && delay == TimeSpan.Zero) + { + c.OnHarmfulSpell(from); + c.OnDamagedBySpell(from); + } } - if (!ourTransform) + public static void Damage( + Spell spell, Mobile target, double damage, int phys, int fire, int cold, int pois, + int nrgy, int chaos = 0, DFAlgorithm dfa = DFAlgorithm.Standard + ) { - List mods = new List(); - - if (transformSpell.PhysResistOffset != 0) - mods.Add(new ResistanceMod(ResistanceType.Physical, transformSpell.PhysResistOffset)); - - if (transformSpell.FireResistOffset != 0) - mods.Add(new ResistanceMod(ResistanceType.Fire, transformSpell.FireResistOffset)); - - if (transformSpell.ColdResistOffset != 0) - mods.Add(new ResistanceMod(ResistanceType.Cold, transformSpell.ColdResistOffset)); - - if (transformSpell.PoisResistOffset != 0) - mods.Add(new ResistanceMod(ResistanceType.Poison, transformSpell.PoisResistOffset)); - - if (transformSpell.NrgyResistOffset != 0) - mods.Add(new ResistanceMod(ResistanceType.Energy, transformSpell.NrgyResistOffset)); - - if (!((Body)transformSpell.Body).IsHuman) - { - IMount mt = caster.Mount; - - if (mt != null) - mt.Rider = null; - } - - caster.BodyMod = transformSpell.Body; - caster.HueMod = transformSpell.Hue; - - for (int i = 0; i < mods.Count; ++i) - caster.AddResistanceMod(mods[i]); - - transformSpell.DoEffect(caster); - - Timer timer = new TransformTimer(caster, transformSpell); - timer.Start(); - - AddContext(caster, new TransformContext(timer, mods, ourType, transformSpell)); - return true; + Damage( + spell, + GetDamageDelayForSpell(spell), + target, + spell.Caster, + damage, + phys, + fire, + cold, + pois, + nrgy, + chaos, + dfa + ); } - } - return false; + public static void Damage( + TimeSpan delay, Mobile target, double damage, int phys, int fire, int cold, int pois, + int nrgy, int chaos = 0, DFAlgorithm dfa = DFAlgorithm.Standard + ) + { + Damage(delay, target, null, damage, phys, fire, cold, pois, nrgy, chaos, dfa); + } + + public static void Damage( + TimeSpan delay, Mobile target, Mobile from, double damage, int phys, int fire, int cold, + int pois, int nrgy, int chaos = 0, DFAlgorithm dfa = DFAlgorithm.Standard + ) + { + Damage(null, delay, target, from, damage, phys, fire, cold, pois, nrgy, chaos, dfa); + } + + public static void Damage( + Spell spell, TimeSpan delay, Mobile target, Mobile from, double damage, int phys, int fire, + int cold, int pois, int nrgy, int chaos = 0, DFAlgorithm dfa = DFAlgorithm.Standard + ) + { + var dmg = (int)damage; + + if (delay == TimeSpan.Zero) + { + (from as BaseCreature)?.AlterSpellDamageTo(target, ref dmg); + + (target as BaseCreature)?.AlterSpellDamageFrom(from, ref dmg); + + WeightOverloading.DFA = dfa; + + var damageGiven = AOS.Damage(target, from, dmg, phys, fire, cold, pois, nrgy, chaos); + + if (from != null) // sanity check + DoLeech(damageGiven, from, target); + + WeightOverloading.DFA = DFAlgorithm.Standard; + } + else + { + new SpellDamageTimerAOS(spell, delay, target, from, dmg, phys, fire, cold, pois, nrgy, chaos, dfa).Start(); + } + + if (target is BaseCreature c && from != null && delay == TimeSpan.Zero) + { + c.OnHarmfulSpell(from); + c.OnDamagedBySpell(from); + } + } + + public static void DoLeech(int damageGiven, Mobile from, Mobile target) + { + var context = TransformationSpellHelper.GetContext(from); + + if (context == null) /* cleanup */ + return; + + if (context.Type == typeof(WraithFormSpell)) + { + var wraithLeech = + 5 + (int)(15 * from.Skills.SpiritSpeak.Value / 100); // Wraith form gives 5-20% mana leech + var manaLeech = AOS.Scale(damageGiven, wraithLeech); + + if (manaLeech != 0) + { + from.Mana += manaLeech; + from.PlaySound(0x44D); + } + } + else if (context.Type == typeof(VampiricEmbraceSpell)) + { + from.Hits += AOS.Scale(damageGiven, 20); + from.PlaySound(0x44D); + } + } + + public static void Heal(int amount, Mobile target, Mobile from, bool message = true) + { + // TODO: All Healing *spells* go through ArcaneEmpowerment + target.Heal(amount, from, message); + } + + private delegate bool TravelValidator(Map map, Point3D loc); + + private class SpellDamageTimer : Timer + { + private readonly Mobile m_From; + private readonly Spell m_Spell; + private readonly Mobile m_Target; + private int m_Damage; + + public SpellDamageTimer(Spell s, Mobile target, Mobile from, int damage, TimeSpan delay) + : base(delay) + { + m_Target = target; + m_From = from; + m_Damage = damage; + m_Spell = s; + + if (m_Spell?.DelayedDamage == true && !m_Spell.DelayedDamageStacking) + m_Spell.StartDelayedDamageContext(target, this); + + Priority = TimerPriority.TwentyFiveMS; + } + + protected override void OnTick() + { + (m_From as BaseCreature)?.AlterSpellDamageTo(m_Target, ref m_Damage); + + (m_Target as BaseCreature)?.AlterSpellDamageFrom(m_From, ref m_Damage); + + m_Target.Damage(m_Damage); + m_Spell?.RemoveDelayedDamageContext(m_Target); + } + } + + private class SpellDamageTimerAOS : Timer + { + private readonly int m_Chaos; + private readonly int m_Cold; + private readonly DFAlgorithm m_DFA; + private readonly int m_Fire; + private readonly Mobile m_From; + private readonly int m_Nrgy; + private readonly int m_Phys; + private readonly int m_Pois; + private readonly Spell m_Spell; + private readonly Mobile m_Target; + private int m_Damage; + + public SpellDamageTimerAOS( + Spell s, TimeSpan delay, Mobile target, Mobile from, int damage, int phys, int fire, int cold, + int pois, int nrgy, int chaos, DFAlgorithm dfa + ) + : base(delay) + { + m_Target = target; + m_From = from; + m_Damage = damage; + m_Phys = phys; + m_Fire = fire; + m_Cold = cold; + m_Pois = pois; + m_Nrgy = nrgy; + m_Chaos = chaos; + m_DFA = dfa; + m_Spell = s; + if (m_Spell?.DelayedDamage == true && !m_Spell.DelayedDamageStacking) + m_Spell.StartDelayedDamageContext(target, this); + + Priority = TimerPriority.TwentyFiveMS; + } + + protected override void OnTick() + { + var bcFrom = m_From as BaseCreature; + var bcTarg = m_Target as BaseCreature; + + if (bcFrom != null && m_Target != null) + bcFrom.AlterSpellDamageTo(m_Target, ref m_Damage); + + if (bcTarg != null && m_From != null) + bcTarg.AlterSpellDamageFrom(m_From, ref m_Damage); + + WeightOverloading.DFA = m_DFA; + + var damageGiven = AOS.Damage(m_Target, m_From, m_Damage, m_Phys, m_Fire, m_Cold, m_Pois, m_Nrgy, m_Chaos); + + if (m_From != null) // sanity check + DoLeech(damageGiven, m_From, m_Target); + + WeightOverloading.DFA = DFAlgorithm.Standard; + + if (bcTarg != null && m_From != null) + { + bcTarg.OnHarmfulSpell(m_From); + bcTarg.OnDamagedBySpell(m_From); + } + + m_Spell?.RemoveDelayedDamageContext(m_Target); + } + } } - private static readonly Dictionary m_Table = new Dictionary(); - - public static void AddContext(Mobile m, TransformContext context) + public class TransformationSpellHelper { - m_Table[m] = context; + private static readonly Dictionary m_Table = new Dictionary(); + + public static bool CheckCast(Mobile caster, Spell spell) + { + if (Sigil.ExistsOn(caster)) + { + caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. + return false; + } + + if (!caster.CanBeginAction()) + { + caster.SendLocalizedMessage(1061628); // You can't do that while polymorphed. + return false; + } + + if (AnimalForm.UnderTransformation(caster)) + { + caster.SendLocalizedMessage(1061091); // You cannot cast that spell in this form. + return false; + } + + return true; + } + + public static bool OnCast(Mobile caster, Spell spell) + { + if (!(spell is ITransformationSpell transformSpell)) + return false; + + if (Sigil.ExistsOn(caster)) + { + caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. + } + else if (!caster.CanBeginAction()) + { + caster.SendLocalizedMessage(1061628); // You can't do that while polymorphed. + } + else if (DisguiseTimers.IsDisguised(caster)) + { + caster.SendLocalizedMessage(1061631); // You can't do that while disguised. + return false; + } + else if (AnimalForm.UnderTransformation(caster)) + { + caster.SendLocalizedMessage(1061091); // You cannot cast that spell in this form. + } + else if (!caster.CanBeginAction() || caster.IsBodyMod && GetContext(caster) == null) + { + spell.DoFizzle(); + } + else if (spell.CheckSequence()) + { + var context = GetContext(caster); + var ourType = spell.GetType(); + + var wasTransformed = context != null; + var ourTransform = wasTransformed && context.Type == ourType; + + if (wasTransformed) + { + RemoveContext(caster, context, ourTransform); + + if (ourTransform) + { + caster.PlaySound(0xFA); + caster.FixedParticles(0x3728, 1, 13, 5042, EffectLayer.Waist); + } + } + + if (!ourTransform) + { + var mods = new List(); + + if (transformSpell.PhysResistOffset != 0) + mods.Add(new ResistanceMod(ResistanceType.Physical, transformSpell.PhysResistOffset)); + + if (transformSpell.FireResistOffset != 0) + mods.Add(new ResistanceMod(ResistanceType.Fire, transformSpell.FireResistOffset)); + + if (transformSpell.ColdResistOffset != 0) + mods.Add(new ResistanceMod(ResistanceType.Cold, transformSpell.ColdResistOffset)); + + if (transformSpell.PoisResistOffset != 0) + mods.Add(new ResistanceMod(ResistanceType.Poison, transformSpell.PoisResistOffset)); + + if (transformSpell.NrgyResistOffset != 0) + mods.Add(new ResistanceMod(ResistanceType.Energy, transformSpell.NrgyResistOffset)); + + if (!((Body)transformSpell.Body).IsHuman) + { + var mt = caster.Mount; + + if (mt != null) + mt.Rider = null; + } + + caster.BodyMod = transformSpell.Body; + caster.HueMod = transformSpell.Hue; + + for (var i = 0; i < mods.Count; ++i) + caster.AddResistanceMod(mods[i]); + + transformSpell.DoEffect(caster); + + Timer timer = new TransformTimer(caster, transformSpell); + timer.Start(); + + AddContext(caster, new TransformContext(timer, mods, ourType, transformSpell)); + return true; + } + } + + return false; + } + + public static void AddContext(Mobile m, TransformContext context) + { + m_Table[m] = context; + } + + public static void RemoveContext(Mobile m, bool resetGraphics) + { + var context = GetContext(m); + + if (context != null) + RemoveContext(m, context, resetGraphics); + } + + public static void RemoveContext(Mobile m, TransformContext context, bool resetGraphics) + { + if (!m_Table.ContainsKey(m)) + return; + + m_Table.Remove(m); + + var mods = context.Mods; + + for (var i = 0; i < mods.Count; ++i) + m.RemoveResistanceMod(mods[i]); + + if (resetGraphics) + { + m.HueMod = -1; + m.BodyMod = 0; + } + + context.Timer.Stop(); + context.Spell.RemoveEffect(m); + } + + public static TransformContext GetContext(Mobile m) + { + m_Table.TryGetValue(m, out var context); + + return context; + } + + public static bool UnderTransformation(Mobile m) => GetContext(m) != null; + + public static bool UnderTransformation(Mobile m, Type type) => GetContext(m)?.Type == type; } - public static void RemoveContext(Mobile m, bool resetGraphics) + public interface ITransformationSpell { - TransformContext context = GetContext(m); + int Body { get; } + int Hue { get; } - if (context != null) - RemoveContext(m, context, resetGraphics); + int PhysResistOffset { get; } + int FireResistOffset { get; } + int ColdResistOffset { get; } + int PoisResistOffset { get; } + int NrgyResistOffset { get; } + + double TickRate { get; } + void OnTick(Mobile m); + + void DoEffect(Mobile m); + void RemoveEffect(Mobile m); } - public static void RemoveContext(Mobile m, TransformContext context, bool resetGraphics) + public class TransformContext { - if (!m_Table.ContainsKey(m)) - return; + public TransformContext(Timer timer, List mods, Type type, ITransformationSpell spell) + { + Timer = timer; + Mods = mods; + Type = type; + Spell = spell; + } - m_Table.Remove(m); + public Timer Timer { get; } - List mods = context.Mods; + public List Mods { get; } - for (int i = 0; i < mods.Count; ++i) - m.RemoveResistanceMod(mods[i]); + public Type Type { get; } - if (resetGraphics) - { - m.HueMod = -1; - m.BodyMod = 0; - } - - context.Timer.Stop(); - context.Spell.RemoveEffect(m); + public ITransformationSpell Spell { get; } } - public static TransformContext GetContext(Mobile m) + public class TransformTimer : Timer { - m_Table.TryGetValue(m, out TransformContext context); + private readonly Mobile m_Mobile; + private readonly ITransformationSpell m_Spell; - return context; + public TransformTimer(Mobile from, ITransformationSpell spell) + : base(TimeSpan.FromSeconds(spell.TickRate), TimeSpan.FromSeconds(spell.TickRate)) + { + m_Mobile = from; + m_Spell = spell; + + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + if (m_Mobile.Deleted || !m_Mobile.Alive || m_Mobile.Body != m_Spell.Body || m_Mobile.Hue != m_Spell.Hue) + { + TransformationSpellHelper.RemoveContext(m_Mobile, true); + Stop(); + } + else + { + m_Spell.OnTick(m_Mobile); + } + } } - - public static bool UnderTransformation(Mobile m) => GetContext(m) != null; - - public static bool UnderTransformation(Mobile m, Type type) => GetContext(m)?.Type == type; - } - - public interface ITransformationSpell - { - int Body { get; } - int Hue { get; } - - int PhysResistOffset { get; } - int FireResistOffset { get; } - int ColdResistOffset { get; } - int PoisResistOffset { get; } - int NrgyResistOffset { get; } - - double TickRate { get; } - void OnTick(Mobile m); - - void DoEffect(Mobile m); - void RemoveEffect(Mobile m); - } - - public class TransformContext - { - public TransformContext(Timer timer, List mods, Type type, ITransformationSpell spell) - { - Timer = timer; - Mods = mods; - Type = type; - Spell = spell; - } - - public Timer Timer { get; } - - public List Mods { get; } - - public Type Type { get; } - - public ITransformationSpell Spell { get; } - } - - public class TransformTimer : Timer - { - private readonly Mobile m_Mobile; - private readonly ITransformationSpell m_Spell; - - public TransformTimer(Mobile from, ITransformationSpell spell) - : base(TimeSpan.FromSeconds(spell.TickRate), TimeSpan.FromSeconds(spell.TickRate)) - { - m_Mobile = from; - m_Spell = spell; - - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - if (m_Mobile.Deleted || !m_Mobile.Alive || m_Mobile.Body != m_Spell.Body || m_Mobile.Hue != m_Spell.Hue) - { - TransformationSpellHelper.RemoveContext(m_Mobile, true); - Stop(); - } - else - { - m_Spell.OnTick(m_Mobile); - } - } - } } diff --git a/Projects/UOContent/Spells/Base/SpellInfo.cs b/Projects/UOContent/Spells/Base/SpellInfo.cs index 8ade3c3fd..4f8b8c341 100644 --- a/Projects/UOContent/Spells/Base/SpellInfo.cs +++ b/Projects/UOContent/Spells/Base/SpellInfo.cs @@ -2,69 +2,106 @@ using System; namespace Server.Spells { - public class SpellInfo - { - public SpellInfo(string name, string mantra, params Type[] regs) : this(name, mantra, 16, 0, 0, true, regs) + public class SpellInfo { + public SpellInfo(string name, string mantra, params Type[] regs) : this(name, mantra, 16, 0, 0, true, regs) + { + } + + public SpellInfo(string name, string mantra, bool allowTown, params Type[] regs) : this( + name, + mantra, + 16, + 0, + 0, + allowTown, + regs + ) + { + } + + public SpellInfo(string name, string mantra, int action, params Type[] regs) : this( + name, + mantra, + action, + 0, + 0, + true, + regs + ) + { + } + + public SpellInfo(string name, string mantra, int action, bool allowTown, params Type[] regs) : this( + name, + mantra, + action, + 0, + 0, + allowTown, + regs + ) + { + } + + public SpellInfo(string name, string mantra, int action, int handEffect, params Type[] regs) : this( + name, + mantra, + action, + handEffect, + handEffect, + true, + regs + ) + { + } + + public SpellInfo(string name, string mantra, int action, int handEffect, bool allowTown, params Type[] regs) : this( + name, + mantra, + action, + handEffect, + handEffect, + allowTown, + regs + ) + { + } + + public SpellInfo( + string name, string mantra, int action, int leftHandEffect, int rightHandEffect, bool allowTown, + params Type[] regs + ) + { + Name = name; + Mantra = mantra; + Action = action; + Reagents = regs; + AllowTown = allowTown; + + LeftHandEffect = leftHandEffect; + RightHandEffect = rightHandEffect; + + Amounts = new int[regs.Length]; + + for (var i = 0; i < regs.Length; ++i) + Amounts[i] = 1; + } + + public int Action { get; set; } + + public bool AllowTown { get; set; } + + public int[] Amounts { get; set; } + + public string Mantra { get; set; } + + public string Name { get; set; } + + public Type[] Reagents { get; set; } + + public int LeftHandEffect { get; set; } + + public int RightHandEffect { get; set; } } - - public SpellInfo(string name, string mantra, bool allowTown, params Type[] regs) : this(name, mantra, 16, 0, 0, - allowTown, regs) - { - } - - public SpellInfo(string name, string mantra, int action, params Type[] regs) : this(name, mantra, action, 0, 0, true, - regs) - { - } - - public SpellInfo(string name, string mantra, int action, bool allowTown, params Type[] regs) : this(name, mantra, - action, 0, 0, allowTown, regs) - { - } - - public SpellInfo(string name, string mantra, int action, int handEffect, params Type[] regs) : this(name, mantra, - action, handEffect, handEffect, true, regs) - { - } - - public SpellInfo(string name, string mantra, int action, int handEffect, bool allowTown, params Type[] regs) : this( - name, mantra, action, handEffect, handEffect, allowTown, regs) - { - } - - public SpellInfo(string name, string mantra, int action, int leftHandEffect, int rightHandEffect, bool allowTown, - params Type[] regs) - { - Name = name; - Mantra = mantra; - Action = action; - Reagents = regs; - AllowTown = allowTown; - - LeftHandEffect = leftHandEffect; - RightHandEffect = rightHandEffect; - - Amounts = new int[regs.Length]; - - for (int i = 0; i < regs.Length; ++i) - Amounts[i] = 1; - } - - public int Action { get; set; } - - public bool AllowTown { get; set; } - - public int[] Amounts { get; set; } - - public string Mantra { get; set; } - - public string Name { get; set; } - - public Type[] Reagents { get; set; } - - public int LeftHandEffect { get; set; } - - public int RightHandEffect { get; set; } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Spells/Base/SpellRegistry.cs b/Projects/UOContent/Spells/Base/SpellRegistry.cs index 40d20bf5a..a8345029a 100644 --- a/Projects/UOContent/Spells/Base/SpellRegistry.cs +++ b/Projects/UOContent/Spells/Base/SpellRegistry.cs @@ -4,160 +4,160 @@ using Server.Utilities; namespace Server.Spells { - public class SpellRegistry - { - private static readonly Type[] m_Types = new Type[700]; - private static int m_Count; - - private static readonly Dictionary m_IDsFromTypes = new Dictionary(m_Types.Length); - - private static readonly object[] m_Params = new object[2]; - - private static readonly string[] m_CircleNames = + public class SpellRegistry { - "First", - "Second", - "Third", - "Fourth", - "Fifth", - "Sixth", - "Seventh", - "Eighth", - "Necromancy", - "Chivalry", - "Bushido", - "Ninjitsu", - "Spellweaving" - }; + private static readonly Type[] m_Types = new Type[700]; + private static int m_Count; - public static Type[] Types - { - get - { - m_Count = -1; - return m_Types; - } - } + private static readonly Dictionary m_IDsFromTypes = new Dictionary(m_Types.Length); - // What IS this used for anyways. - public static int Count - { - get - { - if (m_Count == -1) + private static readonly object[] m_Params = new object[2]; + + private static readonly string[] m_CircleNames = { - m_Count = 0; + "First", + "Second", + "Third", + "Fourth", + "Fifth", + "Sixth", + "Seventh", + "Eighth", + "Necromancy", + "Chivalry", + "Bushido", + "Ninjitsu", + "Spellweaving" + }; - for (int i = 0; i < m_Types.Length; ++i) - if (m_Types[i] != null) - ++m_Count; + public static Type[] Types + { + get + { + m_Count = -1; + return m_Types; + } } - return m_Count; - } - } - - public static Dictionary SpecialMoves { get; } = new Dictionary(); - - public static int GetRegistryNumber(ISpell s) => GetRegistryNumber(s.GetType()); - - public static int GetRegistryNumber(SpecialMove s) => GetRegistryNumber(s.GetType()); - - public static int GetRegistryNumber(Type type) => m_IDsFromTypes.TryGetValue(type, out int value) ? value : -1; - - public static void Register(int spellID, Type type) - { - if (spellID < 0 || spellID >= m_Types.Length) - return; - - if (m_Types[spellID] == null) - ++m_Count; - - m_Types[spellID] = type; - - if (!m_IDsFromTypes.ContainsKey(type)) - m_IDsFromTypes.Add(type, spellID); - - if (type.IsSubclassOf(typeof(SpecialMove))) - { - SpecialMove spm = null; - - try + // What IS this used for anyways. + public static int Count { - spm = ActivatorUtil.CreateInstance(type) as SpecialMove; - } - catch - { - // ignored + get + { + if (m_Count == -1) + { + m_Count = 0; + + for (var i = 0; i < m_Types.Length; ++i) + if (m_Types[i] != null) + ++m_Count; + } + + return m_Count; + } } - if (spm != null) - SpecialMoves.Add(spellID, spm); - } - } + public static Dictionary SpecialMoves { get; } = new Dictionary(); - public static SpecialMove GetSpecialMove(int spellID) - { - if (spellID < 0 || spellID >= m_Types.Length) - return null; + public static int GetRegistryNumber(ISpell s) => GetRegistryNumber(s.GetType()); - Type t = m_Types[spellID]; + public static int GetRegistryNumber(SpecialMove s) => GetRegistryNumber(s.GetType()); - if (t == null || !t.IsSubclassOf(typeof(SpecialMove))) - return null; + public static int GetRegistryNumber(Type type) => m_IDsFromTypes.TryGetValue(type, out var value) ? value : -1; - SpecialMoves.TryGetValue(spellID, out SpecialMove move); - return move; - } - - public static Spell NewSpell(int spellID, Mobile caster, Item scroll) - { - if (spellID < 0 || spellID >= m_Types.Length) - return null; - - Type t = m_Types[spellID]; - - if (t?.IsSubclassOf(typeof(SpecialMove)) == false) - { - m_Params[0] = caster; - m_Params[1] = scroll; - - try + public static void Register(int spellID, Type type) { - return (Spell)ActivatorUtil.CreateInstance(t, m_Params); + if (spellID < 0 || spellID >= m_Types.Length) + return; + + if (m_Types[spellID] == null) + ++m_Count; + + m_Types[spellID] = type; + + if (!m_IDsFromTypes.ContainsKey(type)) + m_IDsFromTypes.Add(type, spellID); + + if (type.IsSubclassOf(typeof(SpecialMove))) + { + SpecialMove spm = null; + + try + { + spm = ActivatorUtil.CreateInstance(type) as SpecialMove; + } + catch + { + // ignored + } + + if (spm != null) + SpecialMoves.Add(spellID, spm); + } } - catch + + public static SpecialMove GetSpecialMove(int spellID) { - // ignored + if (spellID < 0 || spellID >= m_Types.Length) + return null; + + var t = m_Types[spellID]; + + if (t == null || !t.IsSubclassOf(typeof(SpecialMove))) + return null; + + SpecialMoves.TryGetValue(spellID, out var move); + return move; } - } - return null; - } - - public static Spell NewSpell(string name, Mobile caster, Item scroll) - { - for (int i = 0; i < m_CircleNames.Length; ++i) - { - Type t = AssemblyHandler.FindFirstTypeForName($"Server.Spells.{m_CircleNames[i]}.{name}"); - - if (t?.IsSubclassOf(typeof(SpecialMove)) == false) + public static Spell NewSpell(int spellID, Mobile caster, Item scroll) { - m_Params[0] = caster; - m_Params[1] = scroll; + if (spellID < 0 || spellID >= m_Types.Length) + return null; - try - { - return (Spell)ActivatorUtil.CreateInstance(t, m_Params); - } - catch - { - // ignored - } + var t = m_Types[spellID]; + + if (t?.IsSubclassOf(typeof(SpecialMove)) == false) + { + m_Params[0] = caster; + m_Params[1] = scroll; + + try + { + return (Spell)ActivatorUtil.CreateInstance(t, m_Params); + } + catch + { + // ignored + } + } + + return null; } - } - return null; + public static Spell NewSpell(string name, Mobile caster, Item scroll) + { + for (var i = 0; i < m_CircleNames.Length; ++i) + { + var t = AssemblyHandler.FindFirstTypeForName($"Server.Spells.{m_CircleNames[i]}.{name}"); + + if (t?.IsSubclassOf(typeof(SpecialMove)) == false) + { + m_Params[0] = caster; + m_Params[1] = scroll; + + try + { + return (Spell)ActivatorUtil.CreateInstance(t, m_Params); + } + catch + { + // ignored + } + } + } + + return null; + } } - } } diff --git a/Projects/UOContent/Spells/Base/SpellState.cs b/Projects/UOContent/Spells/Base/SpellState.cs index f9567fc86..f2f79dc91 100644 --- a/Projects/UOContent/Spells/Base/SpellState.cs +++ b/Projects/UOContent/Spells/Base/SpellState.cs @@ -1,13 +1,13 @@ namespace Server.Spells { - public enum SpellState - { - None = 0, + public enum SpellState + { + None = 0, - Casting = - 1, // We are in the process of casting (that is, waiting GetCastTime() and doing animations). Spell casting may be interupted in this state. + Casting = + 1, // We are in the process of casting (that is, waiting GetCastTime() and doing animations). Spell casting may be interupted in this state. - Sequencing = - 2 // Casting completed, but the full spell sequence isn't. Usually waiting for a target response. Some actions are restricted in this state (using skills for example). - } -} \ No newline at end of file + Sequencing = + 2 // Casting completed, but the full spell sequence isn't. Usually waiting for a target response. Some actions are restricted in this state (using skills for example). + } +} diff --git a/Projects/UOContent/Spells/Bushido/Confidence.cs b/Projects/UOContent/Spells/Bushido/Confidence.cs index d511f9640..27e000a9b 100644 --- a/Projects/UOContent/Spells/Bushido/Confidence.cs +++ b/Projects/UOContent/Spells/Bushido/Confidence.cs @@ -3,135 +3,137 @@ using System.Collections.Generic; namespace Server.Spells.Bushido { - public class Confidence : SamuraiSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Confidence", null, - -1, - 9002); - - private static readonly Dictionary m_Table = new Dictionary(); - private static readonly Dictionary m_RegenTable = new Dictionary(); - - public Confidence(Mobile caster, Item scroll) : base(caster, scroll, m_Info) + public class Confidence : SamuraiSpell { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Confidence", + null, + -1, + 9002 + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(0.25); + private static readonly Dictionary m_Table = new Dictionary(); + private static readonly Dictionary m_RegenTable = new Dictionary(); - public override double RequiredSkill => 25.0; - public override int RequiredMana => 10; - - public override void OnBeginCast() - { - base.OnBeginCast(); - - Caster.FixedEffect(0x37C4, 10, 7, 4, 3); - } - - public override void OnCast() - { - if (CheckSequence()) - { - Caster.SendLocalizedMessage(1063115); // You exude confidence. - - Caster.FixedParticles(0x375A, 1, 17, 0x7DA, 0x960, 0x3, EffectLayer.Waist); - Caster.PlaySound(0x51A); - - OnCastSuccessful(Caster); - - BeginConfidence(Caster); - BeginRegenerating(Caster); - } - - FinishSequence(); - } - - public static bool IsConfident(Mobile m) => m_Table.ContainsKey(m); - - public static void BeginConfidence(Mobile m) - { - m_Table.TryGetValue(m, out Timer timer); - timer?.Stop(); - m_Table[m] = timer = new InternalTimer(m); - - timer.Start(); - } - - public static void EndConfidence(Mobile m) - { - if (m_Table.TryGetValue(m, out Timer timer)) - { - timer.Stop(); - m_Table.Remove(m); - } - - OnEffectEnd(m, typeof(Confidence)); - } - - public static bool IsRegenerating(Mobile m) => m_RegenTable.ContainsKey(m); - - public static void BeginRegenerating(Mobile m) - { - m_RegenTable.TryGetValue(m, out Timer timer); - timer?.Stop(); - - m_RegenTable[m] = timer = new RegenTimer(m); - - timer.Start(); - } - - public static void StopRegenerating(Mobile m) - { - if (m_RegenTable.TryGetValue(m, out Timer timer)) - { - timer.Stop(); - m_RegenTable.Remove(m); - } - } - - private class InternalTimer : Timer - { - private readonly Mobile m_Mobile; - - public InternalTimer(Mobile m) : base(TimeSpan.FromSeconds(15.0)) - { - m_Mobile = m; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - EndConfidence(m_Mobile); - m_Mobile.SendLocalizedMessage(1063116); // Your confidence wanes. - } - } - - private class RegenTimer : Timer - { - private readonly int m_Hits; - private readonly Mobile m_Mobile; - private int m_Ticks; - - public RegenTimer(Mobile m) : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)) - { - m_Mobile = m; - m_Hits = 15 + m.Skills.Bushido.Fixed * m.Skills.Bushido.Fixed / 57600; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - ++m_Ticks; - - if (m_Ticks >= 5) + public Confidence(Mobile caster, Item scroll) : base(caster, scroll, m_Info) { - m_Mobile.Hits += m_Hits - m_Hits * 4 / 5; - StopRegenerating(m_Mobile); } - m_Mobile.Hits += m_Hits / 5; - } + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(0.25); + + public override double RequiredSkill => 25.0; + public override int RequiredMana => 10; + + public override void OnBeginCast() + { + base.OnBeginCast(); + + Caster.FixedEffect(0x37C4, 10, 7, 4, 3); + } + + public override void OnCast() + { + if (CheckSequence()) + { + Caster.SendLocalizedMessage(1063115); // You exude confidence. + + Caster.FixedParticles(0x375A, 1, 17, 0x7DA, 0x960, 0x3, EffectLayer.Waist); + Caster.PlaySound(0x51A); + + OnCastSuccessful(Caster); + + BeginConfidence(Caster); + BeginRegenerating(Caster); + } + + FinishSequence(); + } + + public static bool IsConfident(Mobile m) => m_Table.ContainsKey(m); + + public static void BeginConfidence(Mobile m) + { + m_Table.TryGetValue(m, out var timer); + timer?.Stop(); + m_Table[m] = timer = new InternalTimer(m); + + timer.Start(); + } + + public static void EndConfidence(Mobile m) + { + if (m_Table.TryGetValue(m, out var timer)) + { + timer.Stop(); + m_Table.Remove(m); + } + + OnEffectEnd(m, typeof(Confidence)); + } + + public static bool IsRegenerating(Mobile m) => m_RegenTable.ContainsKey(m); + + public static void BeginRegenerating(Mobile m) + { + m_RegenTable.TryGetValue(m, out var timer); + timer?.Stop(); + + m_RegenTable[m] = timer = new RegenTimer(m); + + timer.Start(); + } + + public static void StopRegenerating(Mobile m) + { + if (m_RegenTable.TryGetValue(m, out var timer)) + { + timer.Stop(); + m_RegenTable.Remove(m); + } + } + + private class InternalTimer : Timer + { + private readonly Mobile m_Mobile; + + public InternalTimer(Mobile m) : base(TimeSpan.FromSeconds(15.0)) + { + m_Mobile = m; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + EndConfidence(m_Mobile); + m_Mobile.SendLocalizedMessage(1063116); // Your confidence wanes. + } + } + + private class RegenTimer : Timer + { + private readonly int m_Hits; + private readonly Mobile m_Mobile; + private int m_Ticks; + + public RegenTimer(Mobile m) : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)) + { + m_Mobile = m; + m_Hits = 15 + m.Skills.Bushido.Fixed * m.Skills.Bushido.Fixed / 57600; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + ++m_Ticks; + + if (m_Ticks >= 5) + { + m_Mobile.Hits += m_Hits - m_Hits * 4 / 5; + StopRegenerating(m_Mobile); + } + + m_Mobile.Hits += m_Hits / 5; + } + } } - } } diff --git a/Projects/UOContent/Spells/Bushido/CounterAttack.cs b/Projects/UOContent/Spells/Bushido/CounterAttack.cs index afdd56141..9fb48b224 100644 --- a/Projects/UOContent/Spells/Bushido/CounterAttack.cs +++ b/Projects/UOContent/Spells/Bushido/CounterAttack.cs @@ -4,101 +4,103 @@ using Server.Items; namespace Server.Spells.Bushido { - public class CounterAttack : SamuraiSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "CounterAttack", null, - -1, - 9002); - - private static readonly Dictionary m_Table = new Dictionary(); - - public CounterAttack(Mobile caster, Item scroll) : base(caster, scroll, m_Info) + public class CounterAttack : SamuraiSpell { + private static readonly SpellInfo m_Info = new SpellInfo( + "CounterAttack", + null, + -1, + 9002 + ); + + private static readonly Dictionary m_Table = new Dictionary(); + + public CounterAttack(Mobile caster, Item scroll) : base(caster, scroll, m_Info) + { + } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(0.25); + + public override double RequiredSkill => 40.0; + public override int RequiredMana => 5; + + public override bool CheckCast() + { + if (!base.CheckCast()) + return false; + + if (Caster.FindItemOnLayer(Layer.TwoHanded) is BaseShield) + return true; + + if (Caster.FindItemOnLayer(Layer.OneHanded) is BaseWeapon) + return true; + + if (Caster.FindItemOnLayer(Layer.TwoHanded) is BaseWeapon) + return true; + + Caster.SendLocalizedMessage(1062944); // You must have a weapon or a shield equipped to use this ability! + return false; + } + + public override void OnBeginCast() + { + base.OnBeginCast(); + + Caster.FixedEffect(0x37C4, 10, 7, 4, 3); + } + + public override void OnCast() + { + if (CheckSequence()) + { + Caster.SendLocalizedMessage(1063118); // You prepare to respond immediately to the next blocked blow. + + OnCastSuccessful(Caster); + + StartCountering(Caster); + } + + FinishSequence(); + } + + public static bool IsCountering(Mobile m) => m_Table.ContainsKey(m); + + public static void StartCountering(Mobile m) + { + m_Table.TryGetValue(m, out var timer); + timer?.Stop(); + + m_Table[m] = timer = new InternalTimer(m); + + timer.Start(); + } + + public static void StopCountering(Mobile m) + { + if (m_Table.TryGetValue(m, out var timer)) + { + timer.Stop(); + m_Table.Remove(m); + } + + OnEffectEnd(m, typeof(CounterAttack)); + } + + private class InternalTimer : Timer + { + private readonly Mobile m_Mobile; + + public InternalTimer(Mobile m) : base(TimeSpan.FromSeconds(30.0)) + { + m_Mobile = m; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + StopCountering(m_Mobile); + m_Mobile.SendLocalizedMessage(1063119); // You return to your normal stance. + } + } } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(0.25); - - public override double RequiredSkill => 40.0; - public override int RequiredMana => 5; - - public override bool CheckCast() - { - if (!base.CheckCast()) - return false; - - if (Caster.FindItemOnLayer(Layer.TwoHanded) is BaseShield) - return true; - - if (Caster.FindItemOnLayer(Layer.OneHanded) is BaseWeapon) - return true; - - if (Caster.FindItemOnLayer(Layer.TwoHanded) is BaseWeapon) - return true; - - Caster.SendLocalizedMessage(1062944); // You must have a weapon or a shield equipped to use this ability! - return false; - } - - public override void OnBeginCast() - { - base.OnBeginCast(); - - Caster.FixedEffect(0x37C4, 10, 7, 4, 3); - } - - public override void OnCast() - { - if (CheckSequence()) - { - Caster.SendLocalizedMessage(1063118); // You prepare to respond immediately to the next blocked blow. - - OnCastSuccessful(Caster); - - StartCountering(Caster); - } - - FinishSequence(); - } - - public static bool IsCountering(Mobile m) => m_Table.ContainsKey(m); - - public static void StartCountering(Mobile m) - { - m_Table.TryGetValue(m, out Timer timer); - timer?.Stop(); - - m_Table[m] = timer = new InternalTimer(m); - - timer.Start(); - } - - public static void StopCountering(Mobile m) - { - if (m_Table.TryGetValue(m, out Timer timer)) - { - timer.Stop(); - m_Table.Remove(m); - } - - OnEffectEnd(m, typeof(CounterAttack)); - } - - private class InternalTimer : Timer - { - private readonly Mobile m_Mobile; - - public InternalTimer(Mobile m) : base(TimeSpan.FromSeconds(30.0)) - { - m_Mobile = m; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - StopCountering(m_Mobile); - m_Mobile.SendLocalizedMessage(1063119); // You return to your normal stance. - } - } - } } diff --git a/Projects/UOContent/Spells/Bushido/Evasion.cs b/Projects/UOContent/Spells/Bushido/Evasion.cs index f6f0c1f3e..7dff6688c 100644 --- a/Projects/UOContent/Spells/Bushido/Evasion.cs +++ b/Projects/UOContent/Spells/Bushido/Evasion.cs @@ -4,203 +4,208 @@ using Server.Items; namespace Server.Spells.Bushido { - public class Evasion : SamuraiSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Evasion", null, - -1, - 9002); - - private static readonly Dictionary m_Table = new Dictionary(); - - public Evasion(Mobile caster, Item scroll) - : base(caster, scroll, m_Info) + public class Evasion : SamuraiSpell { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Evasion", + null, + -1, + 9002 + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(0.25); + private static readonly Dictionary m_Table = new Dictionary(); - public override double RequiredSkill => 60.0; - public override int RequiredMana => 10; - - public override bool CheckCast() => VerifyCast(Caster, true) && base.CheckCast(); - - public static bool VerifyCast(Mobile caster, bool messages) - { - if (caster == null) // Sanity - return false; - - if (!(caster.FindItemOnLayer(Layer.OneHanded) is BaseWeapon weap)) - weap = caster.FindItemOnLayer(Layer.TwoHanded) as BaseWeapon; - - if (weap != null) - { - if (Core.ML && caster.Skills[weap.Skill].Base < 50) + public Evasion(Mobile caster, Item scroll) + : base(caster, scroll, m_Info) { - if (messages) - caster.SendLocalizedMessage( - 1076206); // Your skill with your equipped weapon must be 50 or higher to use Evasion. - return false; } - } - else if (!(caster.FindItemOnLayer(Layer.TwoHanded) is BaseShield)) - { - if (messages) - caster.SendLocalizedMessage(1062944); // You must have a weapon or a shield equipped to use this ability! - return false; - } - if (!caster.CanBeginAction()) - { - if (messages) caster.SendLocalizedMessage(501789); // You must wait before trying again. - return false; - } + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(0.25); - return true; - } + public override double RequiredSkill => 60.0; + public override int RequiredMana => 10; - public static bool CheckSpellEvasion(Mobile defender) - { - if (!(defender.FindItemOnLayer(Layer.OneHanded) is BaseWeapon weap)) - weap = defender.FindItemOnLayer(Layer.TwoHanded) as BaseWeapon; + public override bool CheckCast() => VerifyCast(Caster, true) && base.CheckCast(); - if (Core.ML) - { - if (defender.Spell?.IsCasting == true) return false; - - if (weap != null) + public static bool VerifyCast(Mobile caster, bool messages) { - if (defender.Skills[weap.Skill].Base < 50) return false; + if (caster == null) // Sanity + return false; + + if (!(caster.FindItemOnLayer(Layer.OneHanded) is BaseWeapon weap)) + weap = caster.FindItemOnLayer(Layer.TwoHanded) as BaseWeapon; + + if (weap != null) + { + if (Core.ML && caster.Skills[weap.Skill].Base < 50) + { + if (messages) + caster.SendLocalizedMessage( + 1076206 + ); // Your skill with your equipped weapon must be 50 or higher to use Evasion. + return false; + } + } + else if (!(caster.FindItemOnLayer(Layer.TwoHanded) is BaseShield)) + { + if (messages) + caster.SendLocalizedMessage(1062944); // You must have a weapon or a shield equipped to use this ability! + return false; + } + + if (!caster.CanBeginAction()) + { + if (messages) caster.SendLocalizedMessage(501789); // You must wait before trying again. + return false; + } + + return true; } - else if (!(defender.FindItemOnLayer(Layer.TwoHanded) is BaseShield)) + + public static bool CheckSpellEvasion(Mobile defender) { - return false; + if (!(defender.FindItemOnLayer(Layer.OneHanded) is BaseWeapon weap)) + weap = defender.FindItemOnLayer(Layer.TwoHanded) as BaseWeapon; + + if (Core.ML) + { + if (defender.Spell?.IsCasting == true) return false; + + if (weap != null) + { + if (defender.Skills[weap.Skill].Base < 50) return false; + } + else if (!(defender.FindItemOnLayer(Layer.TwoHanded) is BaseShield)) + { + return false; + } + } + + if (IsEvading(defender) && BaseWeapon.CheckParry(defender)) + { + defender.Emote("*evades*"); // Yes. Eew. Blame OSI. + defender.FixedEffect(0x37B9, 10, 16); + return true; + } + + return false; } - } - if (IsEvading(defender) && BaseWeapon.CheckParry(defender)) - { - defender.Emote("*evades*"); // Yes. Eew. Blame OSI. - defender.FixedEffect(0x37B9, 10, 16); - return true; - } + public override void OnBeginCast() + { + base.OnBeginCast(); - return false; + Caster.FixedEffect(0x37C4, 10, 7, 4, 3); + } + + public override void OnCast() + { + if (CheckSequence()) + { + Caster.SendLocalizedMessage(1063120); // You feel that you might be able to deflect any attack! + Caster.FixedParticles(0x376A, 1, 20, 0x7F5, 0x960, 3, EffectLayer.Waist); + Caster.PlaySound(0x51B); + + OnCastSuccessful(Caster); + + BeginEvasion(Caster); + + Caster.BeginAction(); + Timer.DelayCall(TimeSpan.FromSeconds(20.0), Caster.EndAction); + } + + FinishSequence(); + } + + public static bool IsEvading(Mobile m) => m_Table.ContainsKey(m); + + public static TimeSpan GetEvadeDuration(Mobile m) + { + /* Evasion duration now scales with Bushido skill + * + * If the player has higher than GM Bushido, and GM Tactics and Anatomy, they get a 1 second bonus + * Evasion duration range: + * o 3-6 seconds w/o tactics/anatomy + * o 6-7 seconds w/ GM+ Bushido and GM tactics/anatomy + */ + + if (!Core.ML) + return TimeSpan.FromSeconds(8.0); + + double seconds = 3; + + if (m.Skills.Bushido.Value > 60) + seconds += (m.Skills.Bushido.Value - 60) / 20; + + if (m.Skills.Anatomy.Value >= 100.0 && m.Skills.Tactics.Value >= 100.0 && m.Skills.Bushido.Value > 100.0 + ) // Bushido being HIGHER than 100 for bonus is intended + seconds++; + + return TimeSpan.FromSeconds((int)seconds); + } + + public static double GetParryScalar(Mobile m) + { + /* Evasion modifier to parry now scales with Bushido skill + * + * If the player has higher than GM Bushido, and at least GM Tactics and Anatomy, they get a bonus to their evasion modifier (10% bonus to the evasion modifier to parry NOT 10% to the final parry chance) + * + * Bonus modifier to parry range: (these are the ranges for the evasion modifier) + * o 16-40% bonus w/o tactics/anatomy + * o 42-50% bonus w/ GM+ bushido and GM tactics/anatomy + */ + + if (!Core.ML) + return 1.5; + + double bonus = 0; + + if (m.Skills.Bushido.Value >= 60) + bonus += (m.Skills.Bushido.Value - 60) * .004 + 0.16; + + if (m.Skills.Anatomy.Value >= 100 && m.Skills.Tactics.Value >= 100 && m.Skills.Bushido.Value > 100 + ) // Bushido being HIGHER than 100 for bonus is intended + bonus += 0.10; + + return 1.0 + bonus; + } + + public static void BeginEvasion(Mobile m) + { + m_Table.TryGetValue(m, out var timer); + timer?.Stop(); + + m_Table[m] = timer = new InternalTimer(m, GetEvadeDuration(m)); + timer.Start(); + } + + public static void EndEvasion(Mobile m) + { + if (m_Table.TryGetValue(m, out var timer)) + { + timer.Stop(); + m_Table.Remove(m); + } + + OnEffectEnd(m, typeof(Evasion)); + } + + private class InternalTimer : Timer + { + private readonly Mobile m_Mobile; + + public InternalTimer(Mobile m, TimeSpan delay) + : base(delay) + { + m_Mobile = m; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + EndEvasion(m_Mobile); + m_Mobile.SendLocalizedMessage(1063121); // You no longer feel that you could deflect any attack. + } + } } - - public override void OnBeginCast() - { - base.OnBeginCast(); - - Caster.FixedEffect(0x37C4, 10, 7, 4, 3); - } - - public override void OnCast() - { - if (CheckSequence()) - { - Caster.SendLocalizedMessage(1063120); // You feel that you might be able to deflect any attack! - Caster.FixedParticles(0x376A, 1, 20, 0x7F5, 0x960, 3, EffectLayer.Waist); - Caster.PlaySound(0x51B); - - OnCastSuccessful(Caster); - - BeginEvasion(Caster); - - Caster.BeginAction(); - Timer.DelayCall(TimeSpan.FromSeconds(20.0), Caster.EndAction); - } - - FinishSequence(); - } - - public static bool IsEvading(Mobile m) => m_Table.ContainsKey(m); - - public static TimeSpan GetEvadeDuration(Mobile m) - { - /* Evasion duration now scales with Bushido skill - * - * If the player has higher than GM Bushido, and GM Tactics and Anatomy, they get a 1 second bonus - * Evasion duration range: - * o 3-6 seconds w/o tactics/anatomy - * o 6-7 seconds w/ GM+ Bushido and GM tactics/anatomy - */ - - if (!Core.ML) - return TimeSpan.FromSeconds(8.0); - - double seconds = 3; - - if (m.Skills.Bushido.Value > 60) - seconds += (m.Skills.Bushido.Value - 60) / 20; - - if (m.Skills.Anatomy.Value >= 100.0 && m.Skills.Tactics.Value >= 100.0 && m.Skills.Bushido.Value > 100.0) // Bushido being HIGHER than 100 for bonus is intended - seconds++; - - return TimeSpan.FromSeconds((int)seconds); - } - - public static double GetParryScalar(Mobile m) - { - /* Evasion modifier to parry now scales with Bushido skill - * - * If the player has higher than GM Bushido, and at least GM Tactics and Anatomy, they get a bonus to their evasion modifier (10% bonus to the evasion modifier to parry NOT 10% to the final parry chance) - * - * Bonus modifier to parry range: (these are the ranges for the evasion modifier) - * o 16-40% bonus w/o tactics/anatomy - * o 42-50% bonus w/ GM+ bushido and GM tactics/anatomy - */ - - if (!Core.ML) - return 1.5; - - double bonus = 0; - - if (m.Skills.Bushido.Value >= 60) - bonus += (m.Skills.Bushido.Value - 60) * .004 + 0.16; - - if (m.Skills.Anatomy.Value >= 100 && m.Skills.Tactics.Value >= 100 && m.Skills.Bushido.Value > 100) // Bushido being HIGHER than 100 for bonus is intended - bonus += 0.10; - - return 1.0 + bonus; - } - - public static void BeginEvasion(Mobile m) - { - m_Table.TryGetValue(m, out Timer timer); - timer?.Stop(); - - m_Table[m] = timer = new InternalTimer(m, GetEvadeDuration(m)); - timer.Start(); - } - - public static void EndEvasion(Mobile m) - { - if (m_Table.TryGetValue(m, out Timer timer)) - { - timer.Stop(); - m_Table.Remove(m); - } - - OnEffectEnd(m, typeof(Evasion)); - } - - private class InternalTimer : Timer - { - private readonly Mobile m_Mobile; - - public InternalTimer(Mobile m, TimeSpan delay) - : base(delay) - { - m_Mobile = m; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - EndEvasion(m_Mobile); - m_Mobile.SendLocalizedMessage(1063121); // You no longer feel that you could deflect any attack. - } - } - } } diff --git a/Projects/UOContent/Spells/Bushido/HonorableExecution.cs b/Projects/UOContent/Spells/Bushido/HonorableExecution.cs index 82bed7349..2e09403c3 100644 --- a/Projects/UOContent/Spells/Bushido/HonorableExecution.cs +++ b/Projects/UOContent/Spells/Bushido/HonorableExecution.cs @@ -3,144 +3,145 @@ using System.Collections.Generic; namespace Server.Spells.Bushido { - public class HonorableExecution : SamuraiMove - { - private static readonly Dictionary m_Table = new Dictionary(); - - public override int BaseMana => 0; - public override double RequiredSkill => 25.0; - - public override TextDefinition AbilityMessage => - new TextDefinition(1063122); // You better kill your enemy with your next hit or you'll be rather sorry... - - public override double GetDamageScalar(Mobile attacker, Mobile defender) + public class HonorableExecution : SamuraiMove { - double bushido = attacker.Skills.Bushido.Value; + private static readonly Dictionary m_Table = + new Dictionary(); - // TODO: 20 -> Perfection - return 1.0 + bushido * 20 / 10000; - } + public override int BaseMana => 0; + public override double RequiredSkill => 25.0; - public override void OnHit(Mobile attacker, Mobile defender, int damage) - { - if (!Validate(attacker) || !CheckMana(attacker, true)) - return; + public override TextDefinition AbilityMessage => + new TextDefinition(1063122); // You better kill your enemy with your next hit or you'll be rather sorry... - ClearCurrentMove(attacker); - - if (m_Table.TryGetValue(attacker, out HonorableExecutionInfo info)) - { - info.Clear(); - info.m_Timer?.Stop(); - } - - if (!defender.Alive) - { - attacker.FixedParticles(0x373A, 1, 17, 0x7E2, EffectLayer.Waist); - - double bushido = attacker.Skills.Bushido.Value; - - attacker.Hits += 20 + (int)(bushido * bushido / 480.0); - - int swingBonus = Math.Max((int)(bushido * bushido / 720.0), 1); - - info = new HonorableExecutionInfo(attacker, swingBonus); - info.m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(20.0), RemovePenalty, info.m_Mobile); - - m_Table[attacker] = info; - } - else - { - List mods = new List + public override double GetDamageScalar(Mobile attacker, Mobile defender) { - new ResistanceMod(ResistanceType.Physical, -40), - new ResistanceMod(ResistanceType.Fire, -40), - new ResistanceMod(ResistanceType.Cold, -40), - new ResistanceMod(ResistanceType.Poison, -40), - new ResistanceMod(ResistanceType.Energy, -40) - }; + var bushido = attacker.Skills.Bushido.Value; - double resSpells = attacker.Skills.MagicResist.Value; - - if (resSpells > 0.0) - mods.Add(new DefaultSkillMod(SkillName.MagicResist, true, -resSpells)); - - info = new HonorableExecutionInfo(attacker, mods); - info.m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(7.0), RemovePenalty, info.m_Mobile); - - m_Table[attacker] = info; - } - - CheckGain(attacker); - } - - public static int GetSwingBonus(Mobile target) => m_Table.TryGetValue(target, out HonorableExecutionInfo info) ? info.m_SwingBonus : 0; - - public static bool IsUnderPenalty(Mobile target) => m_Table.TryGetValue(target, out HonorableExecutionInfo info) && info.m_Penalty; - - public static void RemovePenalty(Mobile target) - { - if (!m_Table.TryGetValue(target, out HonorableExecutionInfo info) || !info.m_Penalty) - return; - - info.Clear(); - info.m_Timer?.Stop(); - m_Table.Remove(target); - } - - private class HonorableExecutionInfo - { - public readonly Mobile m_Mobile; - public readonly List m_Mods; - public readonly bool m_Penalty; - public readonly int m_SwingBonus; - public Timer m_Timer; - - public HonorableExecutionInfo(Mobile from, List mods) : this(from, 0, mods, mods != null) - { - } - - public HonorableExecutionInfo(Mobile from, int swingBonus, List mods = null, bool penalty = false) - { - m_Mobile = from; - m_SwingBonus = swingBonus; - m_Mods = mods; - m_Penalty = penalty; - - Apply(); - } - - public void Apply() - { - if (m_Mods == null) - return; - - for (int i = 0; i < m_Mods.Count; ++i) - { - object mod = m_Mods[i]; - - if (mod is ResistanceMod resistanceMod) - m_Mobile.AddResistanceMod(resistanceMod); - else if (mod is SkillMod skillMod) - m_Mobile.AddSkillMod(skillMod); + // TODO: 20 -> Perfection + return 1.0 + bushido * 20 / 10000; } - } - public void Clear() - { - if (m_Mods == null) - return; - - for (int i = 0; i < m_Mods.Count; ++i) + public override void OnHit(Mobile attacker, Mobile defender, int damage) { - object mod = m_Mods[i]; + if (!Validate(attacker) || !CheckMana(attacker, true)) + return; - if (mod is ResistanceMod resistanceMod) - m_Mobile.RemoveResistanceMod(resistanceMod); - else if (mod is SkillMod skillMod) - m_Mobile.RemoveSkillMod(skillMod); + ClearCurrentMove(attacker); + + if (m_Table.TryGetValue(attacker, out var info)) + { + info.Clear(); + info.m_Timer?.Stop(); + } + + if (!defender.Alive) + { + attacker.FixedParticles(0x373A, 1, 17, 0x7E2, EffectLayer.Waist); + + var bushido = attacker.Skills.Bushido.Value; + + attacker.Hits += 20 + (int)(bushido * bushido / 480.0); + + var swingBonus = Math.Max((int)(bushido * bushido / 720.0), 1); + + info = new HonorableExecutionInfo(attacker, swingBonus); + info.m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(20.0), RemovePenalty, info.m_Mobile); + + m_Table[attacker] = info; + } + else + { + var mods = new List + { + new ResistanceMod(ResistanceType.Physical, -40), + new ResistanceMod(ResistanceType.Fire, -40), + new ResistanceMod(ResistanceType.Cold, -40), + new ResistanceMod(ResistanceType.Poison, -40), + new ResistanceMod(ResistanceType.Energy, -40) + }; + + var resSpells = attacker.Skills.MagicResist.Value; + + if (resSpells > 0.0) + mods.Add(new DefaultSkillMod(SkillName.MagicResist, true, -resSpells)); + + info = new HonorableExecutionInfo(attacker, mods); + info.m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(7.0), RemovePenalty, info.m_Mobile); + + m_Table[attacker] = info; + } + + CheckGain(attacker); + } + + public static int GetSwingBonus(Mobile target) => m_Table.TryGetValue(target, out var info) ? info.m_SwingBonus : 0; + + public static bool IsUnderPenalty(Mobile target) => m_Table.TryGetValue(target, out var info) && info.m_Penalty; + + public static void RemovePenalty(Mobile target) + { + if (!m_Table.TryGetValue(target, out var info) || !info.m_Penalty) + return; + + info.Clear(); + info.m_Timer?.Stop(); + m_Table.Remove(target); + } + + private class HonorableExecutionInfo + { + public readonly Mobile m_Mobile; + public readonly List m_Mods; + public readonly bool m_Penalty; + public readonly int m_SwingBonus; + public Timer m_Timer; + + public HonorableExecutionInfo(Mobile from, List mods) : this(from, 0, mods, mods != null) + { + } + + public HonorableExecutionInfo(Mobile from, int swingBonus, List mods = null, bool penalty = false) + { + m_Mobile = from; + m_SwingBonus = swingBonus; + m_Mods = mods; + m_Penalty = penalty; + + Apply(); + } + + public void Apply() + { + if (m_Mods == null) + return; + + for (var i = 0; i < m_Mods.Count; ++i) + { + var mod = m_Mods[i]; + + if (mod is ResistanceMod resistanceMod) + m_Mobile.AddResistanceMod(resistanceMod); + else if (mod is SkillMod skillMod) + m_Mobile.AddSkillMod(skillMod); + } + } + + public void Clear() + { + if (m_Mods == null) + return; + + for (var i = 0; i < m_Mods.Count; ++i) + { + var mod = m_Mods[i]; + + if (mod is ResistanceMod resistanceMod) + m_Mobile.RemoveResistanceMod(resistanceMod); + else if (mod is SkillMod skillMod) + m_Mobile.RemoveSkillMod(skillMod); + } + } } - } } - } } diff --git a/Projects/UOContent/Spells/Bushido/LightningStrike.cs b/Projects/UOContent/Spells/Bushido/LightningStrike.cs index b8e3a8c15..db5cb51c6 100644 --- a/Projects/UOContent/Spells/Bushido/LightningStrike.cs +++ b/Projects/UOContent/Spells/Bushido/LightningStrike.cs @@ -2,65 +2,65 @@ using Server.Mobiles; namespace Server.Spells.Bushido { - public class LightningStrike : SamuraiMove - { - public override int BaseMana => 5; - public override double RequiredSkill => 50.0; - - public override TextDefinition AbilityMessage => new TextDefinition(1063167); // You prepare to strike quickly. - - public override bool DelayedContext => true; - - public override bool ValidatesDuringHit => false; - - public override int GetAccuracyBonus(Mobile attacker) => 50; - - public override bool Validate(Mobile from) + public class LightningStrike : SamuraiMove { - bool isValid = base.Validate(from); - if (isValid) - { - PlayerMobile ThePlayer = from as PlayerMobile; - ThePlayer.ExecutesLightningStrike = BaseMana; - } + public override int BaseMana => 5; + public override double RequiredSkill => 50.0; - return isValid; - } + public override TextDefinition AbilityMessage => new TextDefinition(1063167); // You prepare to strike quickly. - public override bool IgnoreArmor(Mobile attacker) - { - double bushido = attacker.Skills.Bushido.Value; - double criticalChance = bushido * bushido / 72000.0; - return criticalChance >= Utility.RandomDouble(); - } + public override bool DelayedContext => true; - public override bool OnBeforeSwing(Mobile attacker, Mobile defender) - { - /* no mana drain before actual hit */ - bool enoughMana = CheckMana(attacker, false); - return Validate(attacker); - } + public override bool ValidatesDuringHit => false; - public override void OnHit(Mobile attacker, Mobile defender, int damage) - { - ClearCurrentMove(attacker); - if (CheckMana(attacker, true)) - { - attacker.SendLocalizedMessage(1063168); // You attack with lightning precision! - defender.SendLocalizedMessage(1063169); // Your opponent's quick strike causes extra damage! - defender.FixedParticles(0x3818, 1, 11, 0x13A8, 0, 0, EffectLayer.Waist); - defender.PlaySound(0x51D); - CheckGain(attacker); - SetContext(attacker); - } - } + public override int GetAccuracyBonus(Mobile attacker) => 50; - public override void OnClearMove(Mobile attacker) - { - PlayerMobile - ThePlayer = - attacker as PlayerMobile; // this can be deletet if the PlayerMobile parts are moved to Server.Mobile - ThePlayer.ExecutesLightningStrike = 0; + public override bool Validate(Mobile from) + { + var isValid = base.Validate(from); + if (isValid) + { + var ThePlayer = from as PlayerMobile; + ThePlayer.ExecutesLightningStrike = BaseMana; + } + + return isValid; + } + + public override bool IgnoreArmor(Mobile attacker) + { + var bushido = attacker.Skills.Bushido.Value; + var criticalChance = bushido * bushido / 72000.0; + return criticalChance >= Utility.RandomDouble(); + } + + public override bool OnBeforeSwing(Mobile attacker, Mobile defender) + { + /* no mana drain before actual hit */ + var enoughMana = CheckMana(attacker, false); + return Validate(attacker); + } + + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + ClearCurrentMove(attacker); + if (CheckMana(attacker, true)) + { + attacker.SendLocalizedMessage(1063168); // You attack with lightning precision! + defender.SendLocalizedMessage(1063169); // Your opponent's quick strike causes extra damage! + defender.FixedParticles(0x3818, 1, 11, 0x13A8, 0, 0, EffectLayer.Waist); + defender.PlaySound(0x51D); + CheckGain(attacker); + SetContext(attacker); + } + } + + public override void OnClearMove(Mobile attacker) + { + var + ThePlayer = + attacker as PlayerMobile; // this can be deletet if the PlayerMobile parts are moved to Server.Mobile + ThePlayer.ExecutesLightningStrike = 0; + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Spells/Bushido/MomentumStrike.cs b/Projects/UOContent/Spells/Bushido/MomentumStrike.cs index 73f405c07..2ece6c6ef 100644 --- a/Projects/UOContent/Spells/Bushido/MomentumStrike.cs +++ b/Projects/UOContent/Spells/Bushido/MomentumStrike.cs @@ -1,59 +1,60 @@ -using System.Collections.Generic; using System.Linq; namespace Server.Spells.Bushido { - public class MomentumStrike : SamuraiMove - { - public override int BaseMana => 10; - public override double RequiredSkill => 70.0; - - public override TextDefinition AbilityMessage => - new TextDefinition(1070757); // You prepare to strike two enemies with one blow. - - public override void OnHit(Mobile attacker, Mobile defender, int damage) + public class MomentumStrike : SamuraiMove { - if (!Validate(attacker) || !CheckMana(attacker, false)) - return; + public override int BaseMana => 10; + public override double RequiredSkill => 70.0; - ClearCurrentMove(attacker); + public override TextDefinition AbilityMessage => + new TextDefinition(1070757); // You prepare to strike two enemies with one blow. - IWeapon weapon = attacker.Weapon; + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + if (!Validate(attacker) || !CheckMana(attacker, false)) + return; - List targets = attacker.GetMobilesInRange(weapon.MaxRange) - .Where(m => m != defender).Where(m => m.Combatant == attacker).ToList(); + ClearCurrentMove(attacker); - if (targets.Count <= 0) - { - attacker.SendLocalizedMessage(1063123); // There are no valid targets to attack! - return; - } + var weapon = attacker.Weapon; - if (!CheckMana(attacker, true)) - return; + var targets = attacker.GetMobilesInRange(weapon.MaxRange) + .Where(m => m != defender) + .Where(m => m.Combatant == attacker) + .ToList(); - Mobile target = targets.RandomElement(); + if (targets.Count <= 0) + { + attacker.SendLocalizedMessage(1063123); // There are no valid targets to attack! + return; + } - double damageBonus = attacker.Skills.Bushido.Value / 100.0; + if (!CheckMana(attacker, true)) + return; - if (!defender.Alive) - damageBonus *= 1.5; + var target = targets.RandomElement(); - attacker.SendLocalizedMessage(1063171); // You transfer the momentum of your weapon into another enemy! - target.SendLocalizedMessage(1063172); // You were hit by the momentum of a Samurai's weapon! + var damageBonus = attacker.Skills.Bushido.Value / 100.0; - target.FixedParticles(0x37B9, 1, 4, 0x251D, 0, 0, EffectLayer.Waist); + if (!defender.Alive) + damageBonus *= 1.5; - attacker.PlaySound(0x510); + attacker.SendLocalizedMessage(1063171); // You transfer the momentum of your weapon into another enemy! + target.SendLocalizedMessage(1063172); // You were hit by the momentum of a Samurai's weapon! - weapon.OnSwing(attacker, target, damageBonus); + target.FixedParticles(0x37B9, 1, 4, 0x251D, 0, 0, EffectLayer.Waist); - CheckGain(attacker); + attacker.PlaySound(0x510); + + weapon.OnSwing(attacker, target, damageBonus); + + CheckGain(attacker); + } + + public override void CheckGain(Mobile m) + { + m.CheckSkill(MoveSkill, RequiredSkill, 120.0); + } } - - public override void CheckGain(Mobile m) - { - m.CheckSkill(MoveSkill, RequiredSkill, 120.0); - } - } } diff --git a/Projects/UOContent/Spells/Bushido/SamuraiMove.cs b/Projects/UOContent/Spells/Bushido/SamuraiMove.cs index a745ad297..4470a1919 100644 --- a/Projects/UOContent/Spells/Bushido/SamuraiMove.cs +++ b/Projects/UOContent/Spells/Bushido/SamuraiMove.cs @@ -1,12 +1,12 @@ namespace Server.Spells { - public class SamuraiMove : SpecialMove - { - public override SkillName MoveSkill => SkillName.Bushido; - - public override void CheckGain(Mobile m) + public class SamuraiMove : SpecialMove { - m.CheckSkill(MoveSkill, RequiredSkill - 12.5, RequiredSkill + 37.5); // Per five on friday 02/16/07 + public override SkillName MoveSkill => SkillName.Bushido; + + public override void CheckGain(Mobile m) + { + m.CheckSkill(MoveSkill, RequiredSkill - 12.5, RequiredSkill + 37.5); // Per five on friday 02/16/07 + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Spells/Bushido/SamuraiSpell.cs b/Projects/UOContent/Spells/Bushido/SamuraiSpell.cs index f89267acb..856ac7382 100644 --- a/Projects/UOContent/Spells/Bushido/SamuraiSpell.cs +++ b/Projects/UOContent/Spells/Bushido/SamuraiSpell.cs @@ -4,117 +4,126 @@ using Server.Network; namespace Server.Spells.Bushido { - public abstract class SamuraiSpell : Spell - { - public SamuraiSpell(Mobile caster, Item scroll, SpellInfo info) : base(caster, scroll, info) + public abstract class SamuraiSpell : Spell { + public SamuraiSpell(Mobile caster, Item scroll, SpellInfo info) : base(caster, scroll, info) + { + } + + public abstract double RequiredSkill { get; } + public abstract int RequiredMana { get; } + + public override SkillName CastSkill => SkillName.Bushido; + public override SkillName DamageSkill => SkillName.Bushido; + + public override bool ClearHandsOnCast => false; + public override bool BlocksMovement => false; + public override bool ShowHandMovement => false; + + // public override int CastDelayBase => 1; + public override double CastDelayFastScalar => 0; + + public override int CastRecoveryBase => 7; + + public static bool CheckExpansion(Mobile from) => + (from as PlayerMobile)?.NetState?.SupportsExpansion(Expansion.SE) == true; + + public override bool CheckCast() + { + var mana = ScaleMana(RequiredMana); + + if (!base.CheckCast()) + return false; + + if (!CheckExpansion(Caster)) + { + Caster.SendLocalizedMessage(1063456); // You must upgrade to Samurai Empire in order to use that ability. + return false; + } + + if (Caster.Skills[CastSkill].Value < RequiredSkill) + { + var args = $"{RequiredSkill:F1}\t{CastSkill.ToString()}\t "; + Caster.SendLocalizedMessage( + 1063013, + args + ); // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability. + return false; + } + + if (Caster.Mana < mana) + { + Caster.SendLocalizedMessage( + 1060174, + mana.ToString() + ); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability. + return false; + } + + return true; + } + + public override bool CheckFizzle() + { + var mana = ScaleMana(RequiredMana); + + if (Caster.Skills[CastSkill].Value < RequiredSkill) + { + Caster.SendLocalizedMessage( + 1070768, + RequiredSkill.ToString("F1") + ); // You need ~1_SKILL_REQUIREMENT~ Bushido skill to perform that attack! + return false; + } + + if (Caster.Mana < mana) + { + Caster.SendLocalizedMessage( + 1060174, + mana.ToString() + ); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability. + return false; + } + + if (!base.CheckFizzle()) + return false; + + Caster.Mana -= mana; + + return true; + } + + public override void GetCastSkills(out double min, out double max) + { + min = RequiredSkill - 12.5; // per 5 on friday, 2/16/07 + max = RequiredSkill + 37.5; + } + + public override int GetMana() => 0; + + public virtual void OnCastSuccessful(Mobile caster) + { + if (Evasion.IsEvading(caster)) + Evasion.EndEvasion(caster); + + if (Confidence.IsConfident(caster)) + Confidence.EndConfidence(caster); + + if (CounterAttack.IsCountering(caster)) + CounterAttack.StopCountering(caster); + + var spellID = SpellRegistry.GetRegistryNumber(this); + + if (spellID > 0) + caster.Send(new ToggleSpecialAbility(spellID + 1, true)); + } + + public static void OnEffectEnd(Mobile caster, Type type) + { + var spellID = SpellRegistry.GetRegistryNumber(type); + + if (spellID > 0) + caster.Send(new ToggleSpecialAbility(spellID + 1, false)); + } } - - public abstract double RequiredSkill { get; } - public abstract int RequiredMana { get; } - - public override SkillName CastSkill => SkillName.Bushido; - public override SkillName DamageSkill => SkillName.Bushido; - - public override bool ClearHandsOnCast => false; - public override bool BlocksMovement => false; - public override bool ShowHandMovement => false; - - // public override int CastDelayBase => 1; - public override double CastDelayFastScalar => 0; - - public override int CastRecoveryBase => 7; - - public static bool CheckExpansion(Mobile from) => (from as PlayerMobile)?.NetState?.SupportsExpansion(Expansion.SE) == true; - - public override bool CheckCast() - { - int mana = ScaleMana(RequiredMana); - - if (!base.CheckCast()) - return false; - - if (!CheckExpansion(Caster)) - { - Caster.SendLocalizedMessage(1063456); // You must upgrade to Samurai Empire in order to use that ability. - return false; - } - - if (Caster.Skills[CastSkill].Value < RequiredSkill) - { - string args = $"{RequiredSkill:F1}\t{CastSkill.ToString()}\t "; - Caster.SendLocalizedMessage(1063013, - args); // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability. - return false; - } - - if (Caster.Mana < mana) - { - Caster.SendLocalizedMessage(1060174, - mana.ToString()); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability. - return false; - } - - return true; - } - - public override bool CheckFizzle() - { - int mana = ScaleMana(RequiredMana); - - if (Caster.Skills[CastSkill].Value < RequiredSkill) - { - Caster.SendLocalizedMessage(1070768, - RequiredSkill.ToString("F1")); // You need ~1_SKILL_REQUIREMENT~ Bushido skill to perform that attack! - return false; - } - - if (Caster.Mana < mana) - { - Caster.SendLocalizedMessage(1060174, - mana.ToString()); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability. - return false; - } - - if (!base.CheckFizzle()) - return false; - - Caster.Mana -= mana; - - return true; - } - - public override void GetCastSkills(out double min, out double max) - { - min = RequiredSkill - 12.5; // per 5 on friday, 2/16/07 - max = RequiredSkill + 37.5; - } - - public override int GetMana() => 0; - - public virtual void OnCastSuccessful(Mobile caster) - { - if (Evasion.IsEvading(caster)) - Evasion.EndEvasion(caster); - - if (Confidence.IsConfident(caster)) - Confidence.EndConfidence(caster); - - if (CounterAttack.IsCountering(caster)) - CounterAttack.StopCountering(caster); - - int spellID = SpellRegistry.GetRegistryNumber(this); - - if (spellID > 0) - caster.Send(new ToggleSpecialAbility(spellID + 1, true)); - } - - public static void OnEffectEnd(Mobile caster, Type type) - { - int spellID = SpellRegistry.GetRegistryNumber(type); - - if (spellID > 0) - caster.Send(new ToggleSpecialAbility(spellID + 1, false)); - } - } } diff --git a/Projects/UOContent/Spells/Chivalry/CleanseByFire.cs b/Projects/UOContent/Spells/Chivalry/CleanseByFire.cs index 0c271bb1e..6b35de5fe 100644 --- a/Projects/UOContent/Spells/Chivalry/CleanseByFire.cs +++ b/Projects/UOContent/Spells/Chivalry/CleanseByFire.cs @@ -4,96 +4,114 @@ using Server.Targeting; namespace Server.Spells.Chivalry { - public class CleanseByFireSpell : PaladinSpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Cleanse By Fire", "Expor Flamus", - -1, - 9002); - - public CleanseByFireSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class CleanseByFireSpell : PaladinSpell, ISpellTargetingMobile { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Cleanse By Fire", + "Expor Flamus", + -1, + 9002 + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.0); - - public override double RequiredSkill => 5.0; - public override int RequiredMana => 10; - public override int RequiredTithing => 10; - public override int MantraNumber => 1060718; // Expor Flamus - - public override bool CheckCast() - { - if (DuelContext.CheckSuddenDeath(Caster)) - { - Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); - return false; - } - - return base.CheckCast(); - } - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!m.Poisoned) - Caster.SendLocalizedMessage(1060176); // That creature is not poisoned! - else if (CheckBSequence(m)) - { - SpellHelper.Turn(Caster, m); - - /* Cures the target of poisons, but causes the caster to be burned by fire damage for 13-55 hit points. - * The amount of fire damage is lessened if the caster has high Karma. - */ - - Poison p = m.Poison; - - if (p != null) + public CleanseByFireSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - // Cleanse by fire is now difficulty based - int chanceToCure = 10000 + (int)(Caster.Skills.Chivalry.Value * 75) - (p.Level + 1) * 2000; - chanceToCure /= 100; - - if (chanceToCure > Utility.Random(100)) - { - if (m.CurePoison(Caster)) - { - if (Caster != m) - Caster.SendLocalizedMessage(1010058); // You have cured the target of all poisons! - - m.SendLocalizedMessage(1010059); // You have been cured of all poisons. - } - } - else - { - m.SendLocalizedMessage(1010060); // You have failed to cure your target! - } } - m.PlaySound(0x1E0); - m.FixedParticles(0x373A, 1, 15, 5012, 3, 2, EffectLayer.Waist); + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.0); - IEntity from = new Entity(Serial.Zero, new Point3D(m.X, m.Y, m.Z - 5), m.Map); - IEntity to = new Entity(Serial.Zero, new Point3D(m.X, m.Y, m.Z + 45), m.Map); - Effects.SendMovingParticles(from, to, 0x374B, 1, 0, false, false, 63, 2, 9501, 1, 0, EffectLayer.Head, - 0x100); + public override double RequiredSkill => 5.0; + public override int RequiredMana => 10; + public override int RequiredTithing => 10; + public override int MantraNumber => 1060718; // Expor Flamus - Caster.PlaySound(0x208); - Caster.FixedParticles(0x3709, 1, 30, 9934, 0, 7, EffectLayer.Waist); + public void Target(Mobile m) + { + if (m == null) + return; - int damage = Math.Clamp(50 - ComputePowerValue(4), 13, 55); + if (!m.Poisoned) + { + Caster.SendLocalizedMessage(1060176); // That creature is not poisoned! + } + else if (CheckBSequence(m)) + { + SpellHelper.Turn(Caster, m); - AOS.Damage(Caster, Caster, damage, 0, 100, 0, 0, 0, true); - } + /* Cures the target of poisons, but causes the caster to be burned by fire damage for 13-55 hit points. + * The amount of fire damage is lessened if the caster has high Karma. + */ - FinishSequence(); + var p = m.Poison; + + if (p != null) + { + // Cleanse by fire is now difficulty based + var chanceToCure = 10000 + (int)(Caster.Skills.Chivalry.Value * 75) - (p.Level + 1) * 2000; + chanceToCure /= 100; + + if (chanceToCure > Utility.Random(100)) + { + if (m.CurePoison(Caster)) + { + if (Caster != m) + Caster.SendLocalizedMessage(1010058); // You have cured the target of all poisons! + + m.SendLocalizedMessage(1010059); // You have been cured of all poisons. + } + } + else + { + m.SendLocalizedMessage(1010060); // You have failed to cure your target! + } + } + + m.PlaySound(0x1E0); + m.FixedParticles(0x373A, 1, 15, 5012, 3, 2, EffectLayer.Waist); + + IEntity from = new Entity(Serial.Zero, new Point3D(m.X, m.Y, m.Z - 5), m.Map); + IEntity to = new Entity(Serial.Zero, new Point3D(m.X, m.Y, m.Z + 45), m.Map); + Effects.SendMovingParticles( + from, + to, + 0x374B, + 1, + 0, + false, + false, + 63, + 2, + 9501, + 1, + 0, + EffectLayer.Head, + 0x100 + ); + + Caster.PlaySound(0x208); + Caster.FixedParticles(0x3709, 1, 30, 9934, 0, 7, EffectLayer.Waist); + + var damage = Math.Clamp(50 - ComputePowerValue(4), 13, 55); + + AOS.Damage(Caster, Caster, damage, 0, 100, 0, 0, 0, true); + } + + FinishSequence(); + } + + public override bool CheckCast() + { + if (DuelContext.CheckSuddenDeath(Caster)) + { + Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); + return false; + } + + return base.CheckCast(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, Core.ML ? 10 : 12); + } } - } } diff --git a/Projects/UOContent/Spells/Chivalry/CloseWounds.cs b/Projects/UOContent/Spells/Chivalry/CloseWounds.cs index 9db2e45a8..d270eec61 100644 --- a/Projects/UOContent/Spells/Chivalry/CloseWounds.cs +++ b/Projects/UOContent/Spells/Chivalry/CloseWounds.cs @@ -7,80 +7,94 @@ using Server.Targeting; namespace Server.Spells.Chivalry { - public class CloseWoundsSpell : PaladinSpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Close Wounds", "Obsu Vulni", - -1, - 9002); - - public CloseWoundsSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class CloseWoundsSpell : PaladinSpell, ISpellTargetingMobile { + private static readonly SpellInfo m_Info = new SpellInfo( + "Close Wounds", + "Obsu Vulni", + -1, + 9002 + ); + + public CloseWoundsSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); + + public override double RequiredSkill => 0.0; + public override int RequiredMana => 10; + public override int RequiredTithing => 10; + public override int MantraNumber => 1060719; // Obsu Vulni + + public void Target(Mobile m) + { + if (m == null) + return; + + if (!Caster.InRange(m, 2)) + { + Caster.SendLocalizedMessage(1060178); // You are too far away to perform that action! + } + else if (m is BaseCreature creature && creature.IsAnimatedDead) + { + Caster.SendLocalizedMessage(1061654); // You cannot heal that which is not alive. + } + else if (m.IsDeadBondedPet) + { + Caster.SendLocalizedMessage(1060177); // You cannot heal a creature that is already dead! + } + else if (m.Hits >= m.HitsMax) + { + Caster.SendLocalizedMessage(500955); // That being is not damaged! + } + else if (m.Poisoned || MortalStrike.IsWounded(m)) + { + Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, Caster == m ? 1005000 : 1010398); + } + else if (CheckBSequence(m)) + { + SpellHelper.Turn(Caster, m); + + /* Heals the target for 7 to 39 points of damage. + * The caster's Karma affects the amount of damage healed. + */ + + // TODO: Should caps be applied? + var toHeal = Math.Clamp(ComputePowerValue(6) + Utility.RandomMinMax(0, 2), 7, 39); + + if (m.Hits + toHeal > m.HitsMax) + toHeal = m.HitsMax - m.Hits; + + SpellHelper.Heal(toHeal, m, Caster, false); + + m.SendLocalizedMessage( + 1060203, + toHeal.ToString() + ); // You have had ~1_HEALED_AMOUNT~ hit points of damage healed. + + m.PlaySound(0x202); + m.FixedParticles(0x376A, 1, 62, 9923, 3, 3, EffectLayer.Waist); + m.FixedParticles(0x3779, 1, 46, 9502, 5, 3, EffectLayer.Waist); + } + + FinishSequence(); + } + + public override bool CheckCast() + { + if (DuelContext.CheckSuddenDeath(Caster)) + { + Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); + return false; + } + + return base.CheckCast(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial); + } } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); - - public override double RequiredSkill => 0.0; - public override int RequiredMana => 10; - public override int RequiredTithing => 10; - public override int MantraNumber => 1060719; // Obsu Vulni - - public override bool CheckCast() - { - if (DuelContext.CheckSuddenDeath(Caster)) - { - Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); - return false; - } - - return base.CheckCast(); - } - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.InRange(m, 2)) - Caster.SendLocalizedMessage(1060178); // You are too far away to perform that action! - else if (m is BaseCreature creature && creature.IsAnimatedDead) - Caster.SendLocalizedMessage(1061654); // You cannot heal that which is not alive. - else if (m.IsDeadBondedPet) - Caster.SendLocalizedMessage(1060177); // You cannot heal a creature that is already dead! - else if (m.Hits >= m.HitsMax) - Caster.SendLocalizedMessage(500955); // That being is not damaged! - else if (m.Poisoned || MortalStrike.IsWounded(m)) - Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, Caster == m ? 1005000 : 1010398); - else if (CheckBSequence(m)) - { - SpellHelper.Turn(Caster, m); - - /* Heals the target for 7 to 39 points of damage. - * The caster's Karma affects the amount of damage healed. - */ - - // TODO: Should caps be applied? - int toHeal = Math.Clamp(ComputePowerValue(6) + Utility.RandomMinMax(0, 2), 7, 39); - - if (m.Hits + toHeal > m.HitsMax) - toHeal = m.HitsMax - m.Hits; - - SpellHelper.Heal(toHeal, m, Caster, false); - - m.SendLocalizedMessage(1060203, - toHeal.ToString()); // You have had ~1_HEALED_AMOUNT~ hit points of damage healed. - - m.PlaySound(0x202); - m.FixedParticles(0x376A, 1, 62, 9923, 3, 3, EffectLayer.Waist); - m.FixedParticles(0x3779, 1, 46, 9502, 5, 3, EffectLayer.Waist); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Chivalry/ConsecrateWeapon.cs b/Projects/UOContent/Spells/Chivalry/ConsecrateWeapon.cs index 53542984f..0646f20c7 100644 --- a/Projects/UOContent/Spells/Chivalry/ConsecrateWeapon.cs +++ b/Projects/UOContent/Spells/Chivalry/ConsecrateWeapon.cs @@ -4,101 +4,117 @@ using Server.Items; namespace Server.Spells.Chivalry { - public class ConsecrateWeaponSpell : PaladinSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Consecrate Weapon", "Consecrus Arma", - -1, - 9002); - - private static readonly Dictionary m_Table = new Dictionary(); - - public ConsecrateWeaponSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class ConsecrateWeaponSpell : PaladinSpell { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Consecrate Weapon", + "Consecrus Arma", + -1, + 9002 + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(0.5); + private static readonly Dictionary m_Table = new Dictionary(); - public override double RequiredSkill => 15.0; - public override int RequiredMana => 10; - public override int RequiredTithing => 10; - public override int MantraNumber => 1060720; // Consecrus Arma - public override bool BlocksMovement => false; - - public override void OnCast() - { - if (!(Caster.Weapon is BaseWeapon weapon) || weapon is Fists) - { - Caster.SendLocalizedMessage(501078); // You must be holding a weapon. - } - else if (CheckSequence()) - { - /* Temporarily enchants the weapon the caster is currently wielding. - * The type of damage the weapon inflicts when hitting a target will - * be converted to the target's worst Resistance type. - * Duration of the effect is affected by the caster's Karma and lasts for 3 to 11 seconds. - */ - - int itemID, soundID; - - switch (weapon.Skill) + public ConsecrateWeaponSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - case SkillName.Macing: - itemID = 0xFB4; - soundID = 0x232; - break; - case SkillName.Archery: - itemID = 0x13B1; - soundID = 0x145; - break; - default: - itemID = 0xF5F; - soundID = 0x56; - break; } - Caster.PlaySound(0x20C); - Caster.PlaySound(soundID); - Caster.FixedParticles(0x3779, 1, 30, 9964, 3, 3, EffectLayer.Waist); + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(0.5); - IEntity from = new Entity(Serial.Zero, new Point3D(Caster.X, Caster.Y, Caster.Z), Caster.Map); - IEntity to = new Entity(Serial.Zero, new Point3D(Caster.X, Caster.Y, Caster.Z + 50), Caster.Map); - Effects.SendMovingParticles(from, to, itemID, 1, 0, false, false, 33, 3, 9501, 1, 0, EffectLayer.Head, - 0x100); + public override double RequiredSkill => 15.0; + public override int RequiredMana => 10; + public override int RequiredTithing => 10; + public override int MantraNumber => 1060720; // Consecrus Arma + public override bool BlocksMovement => false; - double seconds = Math.Clamp(ComputePowerValue(20), 3.0, 11.0); + public override void OnCast() + { + if (!(Caster.Weapon is BaseWeapon weapon) || weapon is Fists) + { + Caster.SendLocalizedMessage(501078); // You must be holding a weapon. + } + else if (CheckSequence()) + { + /* Temporarily enchants the weapon the caster is currently wielding. + * The type of damage the weapon inflicts when hitting a target will + * be converted to the target's worst Resistance type. + * Duration of the effect is affected by the caster's Karma and lasts for 3 to 11 seconds. + */ - TimeSpan duration = TimeSpan.FromSeconds(seconds); + int itemID, soundID; - m_Table.TryGetValue(weapon, out ExpireTimer timer); - timer?.Stop(); + switch (weapon.Skill) + { + case SkillName.Macing: + itemID = 0xFB4; + soundID = 0x232; + break; + case SkillName.Archery: + itemID = 0x13B1; + soundID = 0x145; + break; + default: + itemID = 0xF5F; + soundID = 0x56; + break; + } - weapon.Consecrated = true; + Caster.PlaySound(0x20C); + Caster.PlaySound(soundID); + Caster.FixedParticles(0x3779, 1, 30, 9964, 3, 3, EffectLayer.Waist); - m_Table[weapon] = timer = new ExpireTimer(weapon, duration); + IEntity from = new Entity(Serial.Zero, new Point3D(Caster.X, Caster.Y, Caster.Z), Caster.Map); + IEntity to = new Entity(Serial.Zero, new Point3D(Caster.X, Caster.Y, Caster.Z + 50), Caster.Map); + Effects.SendMovingParticles( + from, + to, + itemID, + 1, + 0, + false, + false, + 33, + 3, + 9501, + 1, + 0, + EffectLayer.Head, + 0x100 + ); - timer.Start(); - } + var seconds = Math.Clamp(ComputePowerValue(20), 3.0, 11.0); - FinishSequence(); + var duration = TimeSpan.FromSeconds(seconds); + + m_Table.TryGetValue(weapon, out var timer); + timer?.Stop(); + + weapon.Consecrated = true; + + m_Table[weapon] = timer = new ExpireTimer(weapon, duration); + + timer.Start(); + } + + FinishSequence(); + } + + private class ExpireTimer : Timer + { + private readonly BaseWeapon m_Weapon; + + public ExpireTimer(BaseWeapon weapon, TimeSpan delay) : base(delay) + { + m_Weapon = weapon; + Priority = TimerPriority.FiftyMS; + } + + protected override void OnTick() + { + m_Weapon.Consecrated = false; + Effects.PlaySound(m_Weapon.GetWorldLocation(), m_Weapon.Map, 0x1F8); + m_Table.Remove(m_Weapon); + } + } } - - private class ExpireTimer : Timer - { - private readonly BaseWeapon m_Weapon; - - public ExpireTimer(BaseWeapon weapon, TimeSpan delay) : base(delay) - { - m_Weapon = weapon; - Priority = TimerPriority.FiftyMS; - } - - protected override void OnTick() - { - m_Weapon.Consecrated = false; - Effects.PlaySound(m_Weapon.GetWorldLocation(), m_Weapon.Map, 0x1F8); - m_Table.Remove(m_Weapon); - } - } - } } diff --git a/Projects/UOContent/Spells/Chivalry/DispelEvil.cs b/Projects/UOContent/Spells/Chivalry/DispelEvil.cs index 3922643a5..5d52aba2f 100644 --- a/Projects/UOContent/Spells/Chivalry/DispelEvil.cs +++ b/Projects/UOContent/Spells/Chivalry/DispelEvil.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using Server.Items; using Server.Mobiles; @@ -7,98 +6,105 @@ using Server.Spells.Necromancy; namespace Server.Spells.Chivalry { - public class DispelEvilSpell : PaladinSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Dispel Evil", "Dispiro Malas", - -1, - 9002); - - public DispelEvilSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class DispelEvilSpell : PaladinSpell { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Dispel Evil", + "Dispiro Malas", + -1, + 9002 + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(0.25); - - public override double RequiredSkill => 35.0; - public override int RequiredMana => 10; - public override int RequiredTithing => 10; - public override int MantraNumber => 1060721; // Dispiro Malas - public override bool BlocksMovement => false; - - public override bool DelayedDamage => false; - - public override void SendCastEffect() - { - Caster.FixedEffect(0x37C4, 10, 7, 4, 3); // At player - } - - public override void OnCast() - { - if (CheckSequence()) - { - Caster.PlaySound(0xF5); - Caster.PlaySound(0x299); - Caster.FixedParticles(0x37C4, 1, 25, 9922, 14, 3, EffectLayer.Head); - - int dispelSkill = ComputePowerValue(2); - - double chiv = Caster.Skills.Chivalry.Value; - - IEnumerable targets = Caster.GetMobilesInRange(8) - .Where(m => Caster != m && SpellHelper.ValidIndirectTarget(Caster, m) && Caster.CanBeHarmful(m, false)); - - foreach (Mobile m in targets) + public DispelEvilSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - if (m is BaseCreature bc) - { - if (bc.Summoned && !bc.IsAnimatedDead) - { - double dispelChance = (50.0 + 100 * (chiv - bc.DispelDifficulty) / (bc.DispelFocus * 2)) / 100; - dispelChance *= dispelSkill / 100.0; - - if (dispelChance > Utility.RandomDouble()) - { - Effects.SendLocationParticles( - EffectItem.Create(m.Location, m.Map, EffectItem.DefaultDuration), 0x3728, 8, 20, 5042); - Effects.PlaySound(m, m.Map, 0x201); - - m.Delete(); - continue; - } - } - - bool evil = !bc.Controlled && bc.Karma < 0; - - if (evil) - { - // TODO: Is this right? - double fleeChance = (100 - Math.Sqrt(m.Fame / 2.0)) * chiv * dispelSkill; - fleeChance /= 1000000; - - if (fleeChance > Utility.RandomDouble()) bc.BeginFlee(TimeSpan.FromSeconds(30.0)); - } - } - - TransformContext context = TransformationSpellHelper.GetContext(m); - if (context?.Spell is NecromancerSpell) // Trees are not evil! TODO: OSI confirm? - { - // transformed .. - - double drainChance = 0.5 * (Caster.Skills.Chivalry.Value / Math.Max(m.Skills.Necromancy.Value, 1)); - - if (drainChance > Utility.RandomDouble()) - { - int drain = 5 * dispelSkill / 100; - - m.Stam -= drain; - m.Mana -= drain; - } - } } - } - FinishSequence(); + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(0.25); + + public override double RequiredSkill => 35.0; + public override int RequiredMana => 10; + public override int RequiredTithing => 10; + public override int MantraNumber => 1060721; // Dispiro Malas + public override bool BlocksMovement => false; + + public override bool DelayedDamage => false; + + public override void SendCastEffect() + { + Caster.FixedEffect(0x37C4, 10, 7, 4, 3); // At player + } + + public override void OnCast() + { + if (CheckSequence()) + { + Caster.PlaySound(0xF5); + Caster.PlaySound(0x299); + Caster.FixedParticles(0x37C4, 1, 25, 9922, 14, 3, EffectLayer.Head); + + var dispelSkill = ComputePowerValue(2); + + var chiv = Caster.Skills.Chivalry.Value; + + var targets = Caster.GetMobilesInRange(8) + .Where(m => Caster != m && SpellHelper.ValidIndirectTarget(Caster, m) && Caster.CanBeHarmful(m, false)); + + foreach (var m in targets) + { + if (m is BaseCreature bc) + { + if (bc.Summoned && !bc.IsAnimatedDead) + { + var dispelChance = (50.0 + 100 * (chiv - bc.DispelDifficulty) / (bc.DispelFocus * 2)) / 100; + dispelChance *= dispelSkill / 100.0; + + if (dispelChance > Utility.RandomDouble()) + { + Effects.SendLocationParticles( + EffectItem.Create(m.Location, m.Map, EffectItem.DefaultDuration), + 0x3728, + 8, + 20, + 5042 + ); + Effects.PlaySound(m, m.Map, 0x201); + + m.Delete(); + continue; + } + } + + var evil = !bc.Controlled && bc.Karma < 0; + + if (evil) + { + // TODO: Is this right? + var fleeChance = (100 - Math.Sqrt(m.Fame / 2.0)) * chiv * dispelSkill; + fleeChance /= 1000000; + + if (fleeChance > Utility.RandomDouble()) bc.BeginFlee(TimeSpan.FromSeconds(30.0)); + } + } + + var context = TransformationSpellHelper.GetContext(m); + if (context?.Spell is NecromancerSpell) // Trees are not evil! TODO: OSI confirm? + { + // transformed .. + + var drainChance = 0.5 * (Caster.Skills.Chivalry.Value / Math.Max(m.Skills.Necromancy.Value, 1)); + + if (drainChance > Utility.RandomDouble()) + { + var drain = 5 * dispelSkill / 100; + + m.Stam -= drain; + m.Mana -= drain; + } + } + } + } + + FinishSequence(); + } } - } } diff --git a/Projects/UOContent/Spells/Chivalry/DivineFury.cs b/Projects/UOContent/Spells/Chivalry/DivineFury.cs index 31e010c4f..16cd4aec0 100644 --- a/Projects/UOContent/Spells/Chivalry/DivineFury.cs +++ b/Projects/UOContent/Spells/Chivalry/DivineFury.cs @@ -3,61 +3,65 @@ using System.Collections.Generic; namespace Server.Spells.Chivalry { - public class DivineFurySpell : PaladinSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Divine Fury", "Divinum Furis", - -1, - 9002); - - private static readonly Dictionary m_Table = new Dictionary(); - - public DivineFurySpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class DivineFurySpell : PaladinSpell { + private static readonly SpellInfo m_Info = new SpellInfo( + "Divine Fury", + "Divinum Furis", + -1, + 9002 + ); + + private static readonly Dictionary m_Table = new Dictionary(); + + public DivineFurySpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.0); + + public override double RequiredSkill => 25.0; + public override int RequiredMana => 15; + public override int RequiredTithing => 10; + public override int MantraNumber => 1060722; // Divinum Furis + public override bool BlocksMovement => false; + + public override void OnCast() + { + if (CheckSequence()) + { + Caster.PlaySound(0x20F); + Caster.PlaySound(Caster.Female ? 0x338 : 0x44A); + Caster.FixedParticles(0x376A, 1, 31, 9961, 1160, 0, EffectLayer.Waist); + Caster.FixedParticles(0x37C4, 1, 31, 9502, 43, 2, EffectLayer.Waist); + + Caster.Stam = Caster.StamMax; + + m_Table.TryGetValue(Caster, out var timer); + timer?.Stop(); + + var delay = Math.Clamp(ComputePowerValue(10), 7, 24); + + m_Table[Caster] = Timer.DelayCall(TimeSpan.FromSeconds(delay), Expire_Callback, Caster); + Caster.Delta(MobileDelta.WeaponDamage); + + BuffInfo.AddBuff( + Caster, + new BuffInfo(BuffIcon.DivineFury, 1060589, 1075634, TimeSpan.FromSeconds(delay), Caster) + ); + } + + FinishSequence(); + } + + public static bool UnderEffect(Mobile m) => m_Table.ContainsKey(m); + + private static void Expire_Callback(Mobile m) + { + m_Table.Remove(m); + + m.Delta(MobileDelta.WeaponDamage); + m.PlaySound(0xF8); + } } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.0); - - public override double RequiredSkill => 25.0; - public override int RequiredMana => 15; - public override int RequiredTithing => 10; - public override int MantraNumber => 1060722; // Divinum Furis - public override bool BlocksMovement => false; - - public override void OnCast() - { - if (CheckSequence()) - { - Caster.PlaySound(0x20F); - Caster.PlaySound(Caster.Female ? 0x338 : 0x44A); - Caster.FixedParticles(0x376A, 1, 31, 9961, 1160, 0, EffectLayer.Waist); - Caster.FixedParticles(0x37C4, 1, 31, 9502, 43, 2, EffectLayer.Waist); - - Caster.Stam = Caster.StamMax; - - m_Table.TryGetValue(Caster, out Timer timer); - timer?.Stop(); - - int delay = Math.Clamp(ComputePowerValue(10), 7, 24); - - m_Table[Caster] = Timer.DelayCall(TimeSpan.FromSeconds(delay), Expire_Callback, Caster); - Caster.Delta(MobileDelta.WeaponDamage); - - BuffInfo.AddBuff(Caster, - new BuffInfo(BuffIcon.DivineFury, 1060589, 1075634, TimeSpan.FromSeconds(delay), Caster)); - } - - FinishSequence(); - } - - public static bool UnderEffect(Mobile m) => m_Table.ContainsKey(m); - - private static void Expire_Callback(Mobile m) - { - m_Table.Remove(m); - - m.Delta(MobileDelta.WeaponDamage); - m.PlaySound(0xF8); - } - } } diff --git a/Projects/UOContent/Spells/Chivalry/EnemyOfOne.cs b/Projects/UOContent/Spells/Chivalry/EnemyOfOne.cs index 1cd1796d8..c926b6a58 100644 --- a/Projects/UOContent/Spells/Chivalry/EnemyOfOne.cs +++ b/Projects/UOContent/Spells/Chivalry/EnemyOfOne.cs @@ -4,67 +4,71 @@ using Server.Mobiles; namespace Server.Spells.Chivalry { - public class EnemyOfOneSpell : PaladinSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Enemy of One", "Forul Solum", - -1, - 9002); - - private static readonly Dictionary m_Table = new Dictionary(); - - public EnemyOfOneSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class EnemyOfOneSpell : PaladinSpell { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Enemy of One", + "Forul Solum", + -1, + 9002 + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(0.5); + private static readonly Dictionary m_Table = new Dictionary(); - public override double RequiredSkill => 45.0; - public override int RequiredMana => 20; - public override int RequiredTithing => 10; - public override int MantraNumber => 1060723; // Forul Solum - public override bool BlocksMovement => false; - - public override void OnCast() - { - if (CheckSequence()) - { - Caster.PlaySound(0x0F5); - Caster.PlaySound(0x1ED); - Caster.FixedParticles(0x375A, 1, 30, 9966, 33, 2, EffectLayer.Head); - Caster.FixedParticles(0x37B9, 1, 30, 9502, 43, 3, EffectLayer.Head); - - m_Table.TryGetValue(Caster, out Timer timer); - timer?.Stop(); - - double delay = Math.Clamp(ComputePowerValue(1) / 60.0, 1.5, 3.5); - - m_Table[Caster] = Timer.DelayCall(TimeSpan.FromMinutes(delay), Expire_Callback, Caster); - - if (Caster is PlayerMobile mobile) + public EnemyOfOneSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - mobile.EnemyOfOneType = null; - mobile.WaitingForEnemy = true; - - BuffInfo.AddBuff(mobile, - new BuffInfo(BuffIcon.EnemyOfOne, 1075653, 1044111, TimeSpan.FromMinutes(delay), mobile)); } - } - FinishSequence(); + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(0.5); + + public override double RequiredSkill => 45.0; + public override int RequiredMana => 20; + public override int RequiredTithing => 10; + public override int MantraNumber => 1060723; // Forul Solum + public override bool BlocksMovement => false; + + public override void OnCast() + { + if (CheckSequence()) + { + Caster.PlaySound(0x0F5); + Caster.PlaySound(0x1ED); + Caster.FixedParticles(0x375A, 1, 30, 9966, 33, 2, EffectLayer.Head); + Caster.FixedParticles(0x37B9, 1, 30, 9502, 43, 3, EffectLayer.Head); + + m_Table.TryGetValue(Caster, out var timer); + timer?.Stop(); + + var delay = Math.Clamp(ComputePowerValue(1) / 60.0, 1.5, 3.5); + + m_Table[Caster] = Timer.DelayCall(TimeSpan.FromMinutes(delay), Expire_Callback, Caster); + + if (Caster is PlayerMobile mobile) + { + mobile.EnemyOfOneType = null; + mobile.WaitingForEnemy = true; + + BuffInfo.AddBuff( + mobile, + new BuffInfo(BuffIcon.EnemyOfOne, 1075653, 1044111, TimeSpan.FromMinutes(delay), mobile) + ); + } + } + + FinishSequence(); + } + + private static void Expire_Callback(Mobile m) + { + m_Table.Remove(m); + + m.PlaySound(0x1F8); + + if (m is PlayerMobile mobile) + { + mobile.EnemyOfOneType = null; + mobile.WaitingForEnemy = false; + } + } } - - private static void Expire_Callback(Mobile m) - { - m_Table.Remove(m); - - m.PlaySound(0x1F8); - - if (m is PlayerMobile mobile) - { - mobile.EnemyOfOneType = null; - mobile.WaitingForEnemy = false; - } - } - } } diff --git a/Projects/UOContent/Spells/Chivalry/HolyLight.cs b/Projects/UOContent/Spells/Chivalry/HolyLight.cs index 6bf4805dd..976a2771d 100644 --- a/Projects/UOContent/Spells/Chivalry/HolyLight.cs +++ b/Projects/UOContent/Spells/Chivalry/HolyLight.cs @@ -1,58 +1,76 @@ using System; -using System.Collections.Generic; using System.Linq; using Server.Items; namespace Server.Spells.Chivalry { - public class HolyLightSpell : PaladinSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Holy Light", "Augus Luminos", - -1, - 9002); - - public HolyLightSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class HolyLightSpell : PaladinSpell { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Holy Light", + "Augus Luminos", + -1, + 9002 + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.75); - - public override double RequiredSkill => 55.0; - public override int RequiredMana => 10; - public override int RequiredTithing => 10; - public override int MantraNumber => 1060724; // Augus Luminos - public override bool BlocksMovement => false; - - public override bool DelayedDamage => false; - - public override void OnCast() - { - if (CheckSequence()) - { - Caster.PlaySound(0x212); - Caster.PlaySound(0x206); - - Effects.SendLocationParticles(EffectItem.Create(Caster.Location, Caster.Map, EffectItem.DefaultDuration), - 0x376A, 1, 29, 0x47D, 2, 9962, 0); - Effects.SendLocationParticles( - EffectItem.Create(new Point3D(Caster.X, Caster.Y, Caster.Z - 7), Caster.Map, EffectItem.DefaultDuration), - 0x37C4, 1, 29, 0x47D, 2, 9502, 0); - - IEnumerable targets = Caster.GetMobilesInRange(3) - .Where(m => Caster != m && SpellHelper.ValidIndirectTarget(Caster, m) && Caster.CanBeHarmful(m, false) && - (!Core.AOS || Caster.InLOS(m))); - - foreach (Mobile m in targets) + public HolyLightSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - int damage = Math.Clamp(ComputePowerValue(10) + Utility.RandomMinMax(0, 2), 8, 24); - - Caster.DoHarmful(m); - SpellHelper.Damage(this, m, damage, 0, 0, 0, 0, 100); } - } - FinishSequence(); + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.75); + + public override double RequiredSkill => 55.0; + public override int RequiredMana => 10; + public override int RequiredTithing => 10; + public override int MantraNumber => 1060724; // Augus Luminos + public override bool BlocksMovement => false; + + public override bool DelayedDamage => false; + + public override void OnCast() + { + if (CheckSequence()) + { + Caster.PlaySound(0x212); + Caster.PlaySound(0x206); + + Effects.SendLocationParticles( + EffectItem.Create(Caster.Location, Caster.Map, EffectItem.DefaultDuration), + 0x376A, + 1, + 29, + 0x47D, + 2, + 9962, + 0 + ); + Effects.SendLocationParticles( + EffectItem.Create(new Point3D(Caster.X, Caster.Y, Caster.Z - 7), Caster.Map, EffectItem.DefaultDuration), + 0x37C4, + 1, + 29, + 0x47D, + 2, + 9502, + 0 + ); + + var targets = Caster.GetMobilesInRange(3) + .Where( + m => Caster != m && SpellHelper.ValidIndirectTarget(Caster, m) && Caster.CanBeHarmful(m, false) && + (!Core.AOS || Caster.InLOS(m)) + ); + + foreach (var m in targets) + { + var damage = Math.Clamp(ComputePowerValue(10) + Utility.RandomMinMax(0, 2), 8, 24); + + Caster.DoHarmful(m); + SpellHelper.Damage(this, m, damage, 0, 0, 0, 0, 100); + } + } + + FinishSequence(); + } } - } } diff --git a/Projects/UOContent/Spells/Chivalry/NobleSacrifice.cs b/Projects/UOContent/Spells/Chivalry/NobleSacrifice.cs index 3e601a35b..9e3cb9f5a 100644 --- a/Projects/UOContent/Spells/Chivalry/NobleSacrifice.cs +++ b/Projects/UOContent/Spells/Chivalry/NobleSacrifice.cs @@ -6,157 +6,160 @@ using Server.Spells.Necromancy; namespace Server.Spells.Chivalry { - public class NobleSacrificeSpell : PaladinSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Noble Sacrifice", "Dium Prostra", - -1, - 9002); - - public NobleSacrificeSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class NobleSacrificeSpell : PaladinSpell { + private static readonly SpellInfo m_Info = new SpellInfo( + "Noble Sacrifice", + "Dium Prostra", + -1, + 9002 + ); + + public NobleSacrificeSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); + + public override double RequiredSkill => 65.0; + public override int RequiredMana => 20; + public override int RequiredTithing => 30; + public override int MantraNumber => 1060725; // Dium Prostra + public override bool BlocksMovement => false; + + public override void OnCast() + { + if (CheckSequence()) + { + var targets = new List(); + + foreach (var m in Caster.GetMobilesInRange(3)) // TODO: Validate range + { + if (m is BaseCreature creature && creature.IsAnimatedDead) + continue; + + if (Caster != m && m.InLOS(Caster) && Caster.CanBeBeneficial(m, false, true) && !(m is Golem)) + targets.Add(m); + } + + Caster.PlaySound(0x244); + Caster.FixedParticles(0x3709, 1, 30, 9965, 5, 7, EffectLayer.Waist); + Caster.FixedParticles(0x376A, 1, 30, 9502, 5, 3, EffectLayer.Waist); + + /* Attempts to Resurrect, Cure and Heal all targets in a radius around the caster. + * If any target is successfully assisted, the Paladin's current + * Hit Points, Mana and Stamina are set to 1. + * Amount of damage healed is affected by the Caster's Karma, from 8 to 24 hit points. + */ + + var sacrifice = false; + + // TODO: Is there really a resurrection chance? + var resChance = 0.1 + 0.9 * Caster.Karma / 10000.0d; + + for (var i = 0; i < targets.Count; ++i) + { + var m = targets[i]; + + if (!m.Alive) + { + if (m.Region?.IsPartOf("Khaldun") == true) + { + Caster.SendLocalizedMessage( + 1010395 + ); // The veil of death in this area is too strong and resists thy efforts to restore life. + } + else if (resChance > Utility.RandomDouble()) + { + m.FixedParticles(0x375A, 1, 15, 5005, 5, 3, EffectLayer.Head); + m.CloseGump(); + m.SendGump(new ResurrectGump(m, Caster)); + sacrifice = true; + } + } + else + { + var sendEffect = false; + + if (m.Poisoned && m.CurePoison(Caster)) + { + Caster.DoBeneficial(m); + + if (Caster != m) + Caster.SendLocalizedMessage(1010058); // You have cured the target of all poisons! + + m.SendLocalizedMessage(1010059); // You have been cured of all poisons. + sendEffect = true; + sacrifice = true; + } + + if (m.Hits < m.HitsMax) + { + var toHeal = Math.Clamp(ComputePowerValue(10) + Utility.RandomMinMax(0, 2), 8, 24); + + Caster.DoBeneficial(m); + m.Heal(toHeal, Caster); + sendEffect = true; + } + + StatMod mod; + + mod = m.GetStatMod("[Magic] Str Offset"); + if (mod?.Offset < 0) + { + m.RemoveStatMod("[Magic] Str Offset"); + sendEffect = true; + } + + mod = m.GetStatMod("[Magic] Dex Offset"); + if (mod?.Offset < 0) + { + m.RemoveStatMod("[Magic] Dex Offset"); + sendEffect = true; + } + + mod = m.GetStatMod("[Magic] Int Offset"); + if (mod?.Offset < 0) + { + m.RemoveStatMod("[Magic] Int Offset"); + sendEffect = true; + } + + if (m.Paralyzed) + { + m.Paralyzed = false; + sendEffect = true; + } + + if (EvilOmenSpell.TryEndEffect(m)) + sendEffect = true; + + if (StrangleSpell.RemoveCurse(m)) + sendEffect = true; + + if (CorpseSkinSpell.RemoveCurse(m)) + sendEffect = true; + + // TODO: Should this remove blood oath? Pain spike? + + if (sendEffect) + { + m.FixedParticles(0x375A, 1, 15, 5005, 5, 3, EffectLayer.Head); + sacrifice = true; + } + } + } + + if (sacrifice) + { + Caster.PlaySound(Caster.Body.IsFemale ? 0x150 : 0x423); + Caster.Hits = 1; + Caster.Stam = 1; + Caster.Mana = 1; + } + } + + FinishSequence(); + } } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); - - public override double RequiredSkill => 65.0; - public override int RequiredMana => 20; - public override int RequiredTithing => 30; - public override int MantraNumber => 1060725; // Dium Prostra - public override bool BlocksMovement => false; - - public override void OnCast() - { - if (CheckSequence()) - { - List targets = new List(); - - foreach (Mobile m in Caster.GetMobilesInRange(3)) // TODO: Validate range - { - if (m is BaseCreature creature && creature.IsAnimatedDead) - continue; - - if (Caster != m && m.InLOS(Caster) && Caster.CanBeBeneficial(m, false, true) && !(m is Golem)) - targets.Add(m); - } - - Caster.PlaySound(0x244); - Caster.FixedParticles(0x3709, 1, 30, 9965, 5, 7, EffectLayer.Waist); - Caster.FixedParticles(0x376A, 1, 30, 9502, 5, 3, EffectLayer.Waist); - - /* Attempts to Resurrect, Cure and Heal all targets in a radius around the caster. - * If any target is successfully assisted, the Paladin's current - * Hit Points, Mana and Stamina are set to 1. - * Amount of damage healed is affected by the Caster's Karma, from 8 to 24 hit points. - */ - - bool sacrifice = false; - - // TODO: Is there really a resurrection chance? - double resChance = 0.1 + 0.9 * Caster.Karma / 10000.0d; - - for (int i = 0; i < targets.Count; ++i) - { - Mobile m = targets[i]; - - if (!m.Alive) - { - if (m.Region?.IsPartOf("Khaldun") == true) - { - Caster.SendLocalizedMessage( - 1010395); // The veil of death in this area is too strong and resists thy efforts to restore life. - } - else if (resChance > Utility.RandomDouble()) - { - m.FixedParticles(0x375A, 1, 15, 5005, 5, 3, EffectLayer.Head); - m.CloseGump(); - m.SendGump(new ResurrectGump(m, Caster)); - sacrifice = true; - } - } - else - { - bool sendEffect = false; - - if (m.Poisoned && m.CurePoison(Caster)) - { - Caster.DoBeneficial(m); - - if (Caster != m) - Caster.SendLocalizedMessage(1010058); // You have cured the target of all poisons! - - m.SendLocalizedMessage(1010059); // You have been cured of all poisons. - sendEffect = true; - sacrifice = true; - } - - if (m.Hits < m.HitsMax) - { - int toHeal = Math.Clamp(ComputePowerValue(10) + Utility.RandomMinMax(0, 2), 8, 24); - - Caster.DoBeneficial(m); - m.Heal(toHeal, Caster); - sendEffect = true; - } - - StatMod mod; - - mod = m.GetStatMod("[Magic] Str Offset"); - if (mod?.Offset < 0) - { - m.RemoveStatMod("[Magic] Str Offset"); - sendEffect = true; - } - - mod = m.GetStatMod("[Magic] Dex Offset"); - if (mod?.Offset < 0) - { - m.RemoveStatMod("[Magic] Dex Offset"); - sendEffect = true; - } - - mod = m.GetStatMod("[Magic] Int Offset"); - if (mod?.Offset < 0) - { - m.RemoveStatMod("[Magic] Int Offset"); - sendEffect = true; - } - - if (m.Paralyzed) - { - m.Paralyzed = false; - sendEffect = true; - } - - if (EvilOmenSpell.TryEndEffect(m)) - sendEffect = true; - - if (StrangleSpell.RemoveCurse(m)) - sendEffect = true; - - if (CorpseSkinSpell.RemoveCurse(m)) - sendEffect = true; - - // TODO: Should this remove blood oath? Pain spike? - - if (sendEffect) - { - m.FixedParticles(0x375A, 1, 15, 5005, 5, 3, EffectLayer.Head); - sacrifice = true; - } - } - } - - if (sacrifice) - { - Caster.PlaySound(Caster.Body.IsFemale ? 0x150 : 0x423); - Caster.Hits = 1; - Caster.Stam = 1; - Caster.Mana = 1; - } - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Chivalry/PaladinSpell.cs b/Projects/UOContent/Spells/Chivalry/PaladinSpell.cs index 5d3318e2e..294f83998 100644 --- a/Projects/UOContent/Spells/Chivalry/PaladinSpell.cs +++ b/Projects/UOContent/Spells/Chivalry/PaladinSpell.cs @@ -3,139 +3,147 @@ using Server.Network; namespace Server.Spells.Chivalry { - public abstract class PaladinSpell : Spell - { - public PaladinSpell(Mobile caster, Item scroll, SpellInfo info) : base(caster, scroll, info) + public abstract class PaladinSpell : Spell { + public PaladinSpell(Mobile caster, Item scroll, SpellInfo info) : base(caster, scroll, info) + { + } + + public abstract double RequiredSkill { get; } + public abstract int RequiredMana { get; } + public abstract int RequiredTithing { get; } + public abstract int MantraNumber { get; } + + public override SkillName CastSkill => SkillName.Chivalry; + public override SkillName DamageSkill => SkillName.Chivalry; + + public override bool ClearHandsOnCast => false; + + // public override int CastDelayBase => 1; + + public override int CastRecoveryBase => 7; + + public override bool CheckCast() + { + var mana = ScaleMana(RequiredMana); + + if (!base.CheckCast()) + return false; + + if (Caster.TithingPoints < RequiredTithing) + { + Caster.SendLocalizedMessage( + 1060173, + RequiredTithing + .ToString() + ); // You must have at least ~1_TITHE_REQUIREMENT~ Tithing Points to use this ability, + return false; + } + + if (Caster.Mana < mana) + { + Caster.SendLocalizedMessage( + 1060174, + mana.ToString() + ); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability. + return false; + } + + return true; + } + + public override bool CheckFizzle() + { + var requiredTithing = RequiredTithing; + + if (AosAttributes.GetValue(Caster, AosAttribute.LowerRegCost) > Utility.Random(100)) + requiredTithing = 0; + + var mana = ScaleMana(RequiredMana); + + if (Caster.TithingPoints < requiredTithing) + { + Caster.SendLocalizedMessage( + 1060173, + RequiredTithing + .ToString() + ); // You must have at least ~1_TITHE_REQUIREMENT~ Tithing Points to use this ability, + return false; + } + + if (Caster.Mana < mana) + { + Caster.SendLocalizedMessage( + 1060174, + mana.ToString() + ); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability. + return false; + } + + Caster.TithingPoints -= requiredTithing; + + if (!base.CheckFizzle()) + return false; + + Caster.Mana -= mana; + + return true; + } + + public override void SayMantra() + { + Caster.PublicOverheadMessage(MessageType.Regular, 0x3B2, MantraNumber, "", false); + } + + public override void DoFizzle() + { + Caster.PlaySound(0x1D6); + Caster.NextSpellTime = Core.TickCount; + } + + public override void DoHurtFizzle() + { + Caster.PlaySound(0x1D6); + } + + public override void OnDisturb(DisturbType type, bool message) + { + base.OnDisturb(type, message); + + if (message) + Caster.PlaySound(0x1D6); + } + + public override void OnBeginCast() + { + base.OnBeginCast(); + + SendCastEffect(); + } + + public virtual void SendCastEffect() + { + Caster.FixedEffect(0x37C4, 10, (int)(GetCastDelay().TotalSeconds * 28), 4, 3); + } + + public override void GetCastSkills(out double min, out double max) + { + min = RequiredSkill; + max = RequiredSkill + 50.0; + } + + public override int GetMana() => 0; + + public int ComputePowerValue(int div) => ComputePowerValue(Caster, div); + + public static int ComputePowerValue(Mobile from, int div) + { + if (from == null) + return 0; + + var v = (int)Math.Sqrt(from.Karma + 20000 + from.Skills.Chivalry.Fixed * 10); + + return v / div; + } } - - public abstract double RequiredSkill { get; } - public abstract int RequiredMana { get; } - public abstract int RequiredTithing { get; } - public abstract int MantraNumber { get; } - - public override SkillName CastSkill => SkillName.Chivalry; - public override SkillName DamageSkill => SkillName.Chivalry; - - public override bool ClearHandsOnCast => false; - - // public override int CastDelayBase => 1; - - public override int CastRecoveryBase => 7; - - public override bool CheckCast() - { - int mana = ScaleMana(RequiredMana); - - if (!base.CheckCast()) - return false; - - if (Caster.TithingPoints < RequiredTithing) - { - Caster.SendLocalizedMessage(1060173, - RequiredTithing - .ToString()); // You must have at least ~1_TITHE_REQUIREMENT~ Tithing Points to use this ability, - return false; - } - - if (Caster.Mana < mana) - { - Caster.SendLocalizedMessage(1060174, - mana.ToString()); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability. - return false; - } - - return true; - } - - public override bool CheckFizzle() - { - int requiredTithing = RequiredTithing; - - if (AosAttributes.GetValue(Caster, AosAttribute.LowerRegCost) > Utility.Random(100)) - requiredTithing = 0; - - int mana = ScaleMana(RequiredMana); - - if (Caster.TithingPoints < requiredTithing) - { - Caster.SendLocalizedMessage(1060173, - RequiredTithing - .ToString()); // You must have at least ~1_TITHE_REQUIREMENT~ Tithing Points to use this ability, - return false; - } - - if (Caster.Mana < mana) - { - Caster.SendLocalizedMessage(1060174, - mana.ToString()); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability. - return false; - } - - Caster.TithingPoints -= requiredTithing; - - if (!base.CheckFizzle()) - return false; - - Caster.Mana -= mana; - - return true; - } - - public override void SayMantra() - { - Caster.PublicOverheadMessage(MessageType.Regular, 0x3B2, MantraNumber, "", false); - } - - public override void DoFizzle() - { - Caster.PlaySound(0x1D6); - Caster.NextSpellTime = Core.TickCount; - } - - public override void DoHurtFizzle() - { - Caster.PlaySound(0x1D6); - } - - public override void OnDisturb(DisturbType type, bool message) - { - base.OnDisturb(type, message); - - if (message) - Caster.PlaySound(0x1D6); - } - - public override void OnBeginCast() - { - base.OnBeginCast(); - - SendCastEffect(); - } - - public virtual void SendCastEffect() - { - Caster.FixedEffect(0x37C4, 10, (int)(GetCastDelay().TotalSeconds * 28), 4, 3); - } - - public override void GetCastSkills(out double min, out double max) - { - min = RequiredSkill; - max = RequiredSkill + 50.0; - } - - public override int GetMana() => 0; - - public int ComputePowerValue(int div) => ComputePowerValue(Caster, div); - - public static int ComputePowerValue(Mobile from, int div) - { - if (from == null) - return 0; - - int v = (int)Math.Sqrt(from.Karma + 20000 + from.Skills.Chivalry.Fixed * 10); - - return v / div; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Spells/Chivalry/RemoveCurse.cs b/Projects/UOContent/Spells/Chivalry/RemoveCurse.cs index e458f65c4..623ba2fc7 100644 --- a/Projects/UOContent/Spells/Chivalry/RemoveCurse.cs +++ b/Projects/UOContent/Spells/Chivalry/RemoveCurse.cs @@ -7,116 +7,132 @@ using Server.Targeting; namespace Server.Spells.Chivalry { - public class RemoveCurseSpell : PaladinSpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Remove Curse", "Extermo Vomica", - -1, - 9002); - - public RemoveCurseSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class RemoveCurseSpell : PaladinSpell, ISpellTargetingMobile { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Remove Curse", + "Extermo Vomica", + -1, + 9002 + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); - - public override double RequiredSkill => 5.0; - public override int RequiredMana => 20; - public override int RequiredTithing => 10; - public override int MantraNumber => 1060726; // Extermo Vomica - - public override bool CheckCast() - { - if (DuelContext.CheckSuddenDeath(Caster)) - { - Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); - return false; - } - - return base.CheckCast(); - } - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (CheckBSequence(m)) - { - SpellHelper.Turn(Caster, m); - - /* Attempts to remove all Curse effects from Target. - * Curses include Mage spells such as Clumsy, Weaken, Feeblemind and Paralyze - * as well as all Necromancer curses. - * Chance of removing curse is affected by Caster's Karma. - */ - - int chance; - - if (Caster.Karma < -5000) - chance = 0; - else if (Caster.Karma < 0) - chance = (int)Math.Sqrt(20000 + Caster.Karma) - 122; - else if (Caster.Karma < 5625) - chance = (int)Math.Sqrt(Caster.Karma) + 25; - else - chance = 100; - - if (chance > Utility.Random(100)) + public RemoveCurseSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - m.PlaySound(0xF6); - m.PlaySound(0x1F7); - m.FixedParticles(0x3709, 1, 30, 9963, 13, 3, EffectLayer.Head); - - IEntity from = new Entity(Serial.Zero, new Point3D(m.X, m.Y, m.Z - 10), Caster.Map); - IEntity to = new Entity(Serial.Zero, new Point3D(m.X, m.Y, m.Z + 50), Caster.Map); - Effects.SendMovingParticles(from, to, 0x2255, 1, 0, false, false, 13, 3, 9501, 1, 0, EffectLayer.Head, - 0x100); - - StatMod mod = m.GetStatMod("[Magic] Str Offset"); - if (mod?.Offset < 0) - m.RemoveStatMod("[Magic] Str Offset"); - - mod = m.GetStatMod("[Magic] Dex Offset"); - if (mod?.Offset < 0) - m.RemoveStatMod("[Magic] Dex Offset"); - - mod = m.GetStatMod("[Magic] Int Offset"); - if (mod?.Offset < 0) - m.RemoveStatMod("[Magic] Int Offset"); - - m.Paralyzed = false; - - EvilOmenSpell.TryEndEffect(m); - StrangleSpell.RemoveCurse(m); - CorpseSkinSpell.RemoveCurse(m); - CurseSpell.RemoveEffect(m); - MortalStrike.EndWound(m); - if (Core.ML) BloodOathSpell.RemoveCurse(m); - MindRotSpell.ClearMindRotScalar(m); - - BuffInfo.RemoveBuff(m, BuffIcon.Clumsy); - BuffInfo.RemoveBuff(m, BuffIcon.FeebleMind); - BuffInfo.RemoveBuff(m, BuffIcon.Weaken); - BuffInfo.RemoveBuff(m, BuffIcon.Curse); - BuffInfo.RemoveBuff(m, BuffIcon.MassCurse); - BuffInfo.RemoveBuff(m, BuffIcon.MortalStrike); - BuffInfo.RemoveBuff(m, BuffIcon.Mindrot); - - // TODO: Should this remove blood oath? Pain spike? } - else + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); + + public override double RequiredSkill => 5.0; + public override int RequiredMana => 20; + public override int RequiredTithing => 10; + public override int MantraNumber => 1060726; // Extermo Vomica + + public void Target(Mobile m) { - m.PlaySound(0x1DF); - } - } + if (m == null) + return; - FinishSequence(); + if (CheckBSequence(m)) + { + SpellHelper.Turn(Caster, m); + + /* Attempts to remove all Curse effects from Target. + * Curses include Mage spells such as Clumsy, Weaken, Feeblemind and Paralyze + * as well as all Necromancer curses. + * Chance of removing curse is affected by Caster's Karma. + */ + + int chance; + + if (Caster.Karma < -5000) + chance = 0; + else if (Caster.Karma < 0) + chance = (int)Math.Sqrt(20000 + Caster.Karma) - 122; + else if (Caster.Karma < 5625) + chance = (int)Math.Sqrt(Caster.Karma) + 25; + else + chance = 100; + + if (chance > Utility.Random(100)) + { + m.PlaySound(0xF6); + m.PlaySound(0x1F7); + m.FixedParticles(0x3709, 1, 30, 9963, 13, 3, EffectLayer.Head); + + IEntity from = new Entity(Serial.Zero, new Point3D(m.X, m.Y, m.Z - 10), Caster.Map); + IEntity to = new Entity(Serial.Zero, new Point3D(m.X, m.Y, m.Z + 50), Caster.Map); + Effects.SendMovingParticles( + from, + to, + 0x2255, + 1, + 0, + false, + false, + 13, + 3, + 9501, + 1, + 0, + EffectLayer.Head, + 0x100 + ); + + var mod = m.GetStatMod("[Magic] Str Offset"); + if (mod?.Offset < 0) + m.RemoveStatMod("[Magic] Str Offset"); + + mod = m.GetStatMod("[Magic] Dex Offset"); + if (mod?.Offset < 0) + m.RemoveStatMod("[Magic] Dex Offset"); + + mod = m.GetStatMod("[Magic] Int Offset"); + if (mod?.Offset < 0) + m.RemoveStatMod("[Magic] Int Offset"); + + m.Paralyzed = false; + + EvilOmenSpell.TryEndEffect(m); + StrangleSpell.RemoveCurse(m); + CorpseSkinSpell.RemoveCurse(m); + CurseSpell.RemoveEffect(m); + MortalStrike.EndWound(m); + if (Core.ML) BloodOathSpell.RemoveCurse(m); + MindRotSpell.ClearMindRotScalar(m); + + BuffInfo.RemoveBuff(m, BuffIcon.Clumsy); + BuffInfo.RemoveBuff(m, BuffIcon.FeebleMind); + BuffInfo.RemoveBuff(m, BuffIcon.Weaken); + BuffInfo.RemoveBuff(m, BuffIcon.Curse); + BuffInfo.RemoveBuff(m, BuffIcon.MassCurse); + BuffInfo.RemoveBuff(m, BuffIcon.MortalStrike); + BuffInfo.RemoveBuff(m, BuffIcon.Mindrot); + + // TODO: Should this remove blood oath? Pain spike? + } + else + { + m.PlaySound(0x1DF); + } + } + + FinishSequence(); + } + + public override bool CheckCast() + { + if (DuelContext.CheckSuddenDeath(Caster)) + { + Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); + return false; + } + + return base.CheckCast(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, Core.ML ? 10 : 12); + } } - } } diff --git a/Projects/UOContent/Spells/Chivalry/SacredJourney.cs b/Projects/UOContent/Spells/Chivalry/SacredJourney.cs index 31605c292..0b06aaacc 100644 --- a/Projects/UOContent/Spells/Chivalry/SacredJourney.cs +++ b/Projects/UOContent/Spells/Chivalry/SacredJourney.cs @@ -6,135 +6,144 @@ using Server.Mobiles; namespace Server.Spells.Chivalry { - public class SacredJourneySpell : PaladinSpell, IRecallSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Sacred Journey", "Sanctum Viatas", - -1, - 9002); - - private readonly Runebook m_Book; - - private readonly RunebookEntry m_Entry; - - public SacredJourneySpell(Mobile caster, RunebookEntry entry = null, Runebook book = null, Item scroll = null) : base(caster, scroll, m_Info) + public class SacredJourneySpell : PaladinSpell, IRecallSpell { - m_Entry = entry; - m_Book = book; + private static readonly SpellInfo m_Info = new SpellInfo( + "Sacred Journey", + "Sanctum Viatas", + -1, + 9002 + ); + + private readonly Runebook m_Book; + + private readonly RunebookEntry m_Entry; + + public SacredJourneySpell( + Mobile caster, RunebookEntry entry = null, Runebook book = null, Item scroll = null + ) : base(caster, scroll, m_Info) + { + m_Entry = entry; + m_Book = book; + } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); + + public override double RequiredSkill => 15.0; + public override int RequiredMana => 10; + public override int RequiredTithing => 15; + public override int MantraNumber => 1060727; // Sanctum Viatas + public override bool BlocksMovement => false; + + public void Effect(Point3D loc, Map map, bool checkMulti) + { + if (Sigil.ExistsOn(Caster)) + { + Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. + } + else if (map == null || !Core.AOS && Caster.Map != map) + { + Caster.SendLocalizedMessage(1005569); // You can not recall to another facet. + } + else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.RecallFrom)) + { + } + else if (!SpellHelper.CheckTravel(Caster, map, loc, TravelCheckType.RecallTo)) + { + } + else if (map == Map.Felucca && Caster is PlayerMobile mobile && mobile.Young) + { + mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young. + } + else if (Caster.Kills >= 5 && map != Map.Felucca) + { + Caster.SendLocalizedMessage(1019004); // You are not allowed to travel there. + } + else if (Caster.Criminal) + { + Caster.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily. + } + else if (SpellHelper.CheckCombat(Caster)) + { + Caster.SendLocalizedMessage(1061282); // You cannot use the Sacred Journey ability to flee from combat. + } + else if (WeightOverloading.IsOverloaded(Caster)) + { + Caster.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move. + } + else if (!map.CanSpawnMobile(loc.X, loc.Y, loc.Z)) + { + Caster.SendLocalizedMessage(501942); // That location is blocked. + } + else if (checkMulti && SpellHelper.CheckMulti(loc, map)) + { + Caster.SendLocalizedMessage(501942); // That location is blocked. + } + else if (m_Book != null && m_Book.CurCharges <= 0) + { + Caster.SendLocalizedMessage(502412); // There are no charges left on that item. + } + else if (CheckSequence()) + { + BaseCreature.TeleportPets(Caster, loc, map, true); + + if (m_Book != null) + --m_Book.CurCharges; + + Effects.SendLocationParticles( + EffectItem.Create(Caster.Location, Caster.Map, EffectItem.DefaultDuration), + 0, + 0, + 0, + 5033 + ); + + Caster.PlaySound(0x1FC); + Caster.MoveToWorld(loc, map); + Caster.PlaySound(0x1FC); + } + + FinishSequence(); + } + + public override void OnCast() + { + if (m_Entry == null) + Caster.Target = new RecallSpellTarget(this); + else + Effect(m_Entry.Location, m_Entry.Map, true); + } + + public override bool CheckCast() + { + if (!base.CheckCast()) + return false; + + if (Sigil.ExistsOn(Caster)) + { + Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. + return false; + } + + if (Caster.Criminal) + { + Caster.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily. + return false; + } + + if (SpellHelper.CheckCombat(Caster)) + { + Caster.SendLocalizedMessage(1061282); // You cannot use the Sacred Journey ability to flee from combat. + return false; + } + + if (WeightOverloading.IsOverloaded(Caster)) + { + Caster.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move. + return false; + } + + return SpellHelper.CheckTravel(Caster, TravelCheckType.RecallFrom); + } } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); - - public override double RequiredSkill => 15.0; - public override int RequiredMana => 10; - public override int RequiredTithing => 15; - public override int MantraNumber => 1060727; // Sanctum Viatas - public override bool BlocksMovement => false; - - public override void OnCast() - { - if (m_Entry == null) - Caster.Target = new RecallSpellTarget(this); - else - Effect(m_Entry.Location, m_Entry.Map, true); - } - - public override bool CheckCast() - { - if (!base.CheckCast()) - return false; - - if (Sigil.ExistsOn(Caster)) - { - Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. - return false; - } - - if (Caster.Criminal) - { - Caster.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily. - return false; - } - - if (SpellHelper.CheckCombat(Caster)) - { - Caster.SendLocalizedMessage(1061282); // You cannot use the Sacred Journey ability to flee from combat. - return false; - } - - if (WeightOverloading.IsOverloaded(Caster)) - { - Caster.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move. - return false; - } - - return SpellHelper.CheckTravel(Caster, TravelCheckType.RecallFrom); - } - - public void Effect(Point3D loc, Map map, bool checkMulti) - { - if (Sigil.ExistsOn(Caster)) - { - Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. - } - else if (map == null || (!Core.AOS && Caster.Map != map)) - { - Caster.SendLocalizedMessage(1005569); // You can not recall to another facet. - } - else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.RecallFrom)) - { - } - else if (!SpellHelper.CheckTravel(Caster, map, loc, TravelCheckType.RecallTo)) - { - } - else if (map == Map.Felucca && Caster is PlayerMobile mobile && mobile.Young) - { - mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young. - } - else if (Caster.Kills >= 5 && map != Map.Felucca) - { - Caster.SendLocalizedMessage(1019004); // You are not allowed to travel there. - } - else if (Caster.Criminal) - { - Caster.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily. - } - else if (SpellHelper.CheckCombat(Caster)) - { - Caster.SendLocalizedMessage(1061282); // You cannot use the Sacred Journey ability to flee from combat. - } - else if (WeightOverloading.IsOverloaded(Caster)) - { - Caster.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move. - } - else if (!map.CanSpawnMobile(loc.X, loc.Y, loc.Z)) - { - Caster.SendLocalizedMessage(501942); // That location is blocked. - } - else if (checkMulti && SpellHelper.CheckMulti(loc, map)) - { - Caster.SendLocalizedMessage(501942); // That location is blocked. - } - else if (m_Book != null && m_Book.CurCharges <= 0) - { - Caster.SendLocalizedMessage(502412); // There are no charges left on that item. - } - else if (CheckSequence()) - { - BaseCreature.TeleportPets(Caster, loc, map, true); - - if (m_Book != null) - --m_Book.CurCharges; - - Effects.SendLocationParticles(EffectItem.Create(Caster.Location, Caster.Map, EffectItem.DefaultDuration), 0, - 0, 0, 5033); - - Caster.PlaySound(0x1FC); - Caster.MoveToWorld(loc, map); - Caster.PlaySound(0x1FC); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Eighth/AirElemental.cs b/Projects/UOContent/Spells/Eighth/AirElemental.cs index 01c315020..d4a459283 100644 --- a/Projects/UOContent/Spells/Eighth/AirElemental.cs +++ b/Projects/UOContent/Spells/Eighth/AirElemental.cs @@ -3,50 +3,52 @@ using Server.Mobiles; namespace Server.Spells.Eighth { - public class AirElementalSpell : MagerySpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Air Elemental", "Kal Vas Xen Hur", - 269, - 9010, - false, - Reagent.Bloodmoss, - Reagent.MandrakeRoot, - Reagent.SpidersSilk); - - public AirElementalSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class AirElementalSpell : MagerySpell { + private static readonly SpellInfo m_Info = new SpellInfo( + "Air Elemental", + "Kal Vas Xen Hur", + 269, + 9010, + false, + Reagent.Bloodmoss, + Reagent.MandrakeRoot, + Reagent.SpidersSilk + ); + + public AirElementalSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.Eighth; + + public override bool CheckCast() + { + if (!base.CheckCast()) + return false; + + if (Caster.Followers + 2 > Caster.FollowersMax) + { + Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. + return false; + } + + return true; + } + + public override void OnCast() + { + if (CheckSequence()) + { + var duration = TimeSpan.FromSeconds(2 * Caster.Skills.Magery.Fixed / 5.0); + + if (Core.AOS) + SpellHelper.Summon(new SummonedAirElemental(), Caster, 0x217, duration, false, false); + else + SpellHelper.Summon(new AirElemental(), Caster, 0x217, duration, false, false); + } + + FinishSequence(); + } } - - public override SpellCircle Circle => SpellCircle.Eighth; - - public override bool CheckCast() - { - if (!base.CheckCast()) - return false; - - if (Caster.Followers + 2 > Caster.FollowersMax) - { - Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. - return false; - } - - return true; - } - - public override void OnCast() - { - if (CheckSequence()) - { - TimeSpan duration = TimeSpan.FromSeconds(2 * Caster.Skills.Magery.Fixed / 5.0); - - if (Core.AOS) - SpellHelper.Summon(new SummonedAirElemental(), Caster, 0x217, duration, false, false); - else - SpellHelper.Summon(new AirElemental(), Caster, 0x217, duration, false, false); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Eighth/EarthElemental.cs b/Projects/UOContent/Spells/Eighth/EarthElemental.cs index cfc467769..9f1ddef9d 100644 --- a/Projects/UOContent/Spells/Eighth/EarthElemental.cs +++ b/Projects/UOContent/Spells/Eighth/EarthElemental.cs @@ -3,50 +3,52 @@ using Server.Mobiles; namespace Server.Spells.Eighth { - public class EarthElementalSpell : MagerySpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Earth Elemental", "Kal Vas Xen Ylem", - 269, - 9020, - false, - Reagent.Bloodmoss, - Reagent.MandrakeRoot, - Reagent.SpidersSilk); - - public EarthElementalSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class EarthElementalSpell : MagerySpell { + private static readonly SpellInfo m_Info = new SpellInfo( + "Earth Elemental", + "Kal Vas Xen Ylem", + 269, + 9020, + false, + Reagent.Bloodmoss, + Reagent.MandrakeRoot, + Reagent.SpidersSilk + ); + + public EarthElementalSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.Eighth; + + public override bool CheckCast() + { + if (!base.CheckCast()) + return false; + + if (Caster.Followers + 2 > Caster.FollowersMax) + { + Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. + return false; + } + + return true; + } + + public override void OnCast() + { + if (CheckSequence()) + { + var duration = TimeSpan.FromSeconds(2 * Caster.Skills.Magery.Fixed / 5.0); + + if (Core.AOS) + SpellHelper.Summon(new SummonedEarthElemental(), Caster, 0x217, duration, false, false); + else + SpellHelper.Summon(new EarthElemental(), Caster, 0x217, duration, false, false); + } + + FinishSequence(); + } } - - public override SpellCircle Circle => SpellCircle.Eighth; - - public override bool CheckCast() - { - if (!base.CheckCast()) - return false; - - if (Caster.Followers + 2 > Caster.FollowersMax) - { - Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. - return false; - } - - return true; - } - - public override void OnCast() - { - if (CheckSequence()) - { - TimeSpan duration = TimeSpan.FromSeconds(2 * Caster.Skills.Magery.Fixed / 5.0); - - if (Core.AOS) - SpellHelper.Summon(new SummonedEarthElemental(), Caster, 0x217, duration, false, false); - else - SpellHelper.Summon(new EarthElemental(), Caster, 0x217, duration, false, false); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Eighth/Earthquake.cs b/Projects/UOContent/Spells/Eighth/Earthquake.cs index c09b88ea5..6ca41b687 100644 --- a/Projects/UOContent/Spells/Eighth/Earthquake.cs +++ b/Projects/UOContent/Spells/Eighth/Earthquake.cs @@ -1,73 +1,77 @@ using System; -using System.Collections.Generic; using System.Linq; namespace Server.Spells.Eighth { - public class EarthquakeSpell : MagerySpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Earthquake", "In Vas Por", - 233, - 9012, - false, - Reagent.Bloodmoss, - Reagent.Ginseng, - Reagent.MandrakeRoot, - Reagent.SulfurousAsh); - - public EarthquakeSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class EarthquakeSpell : MagerySpell { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Earthquake", + "In Vas Por", + 233, + 9012, + false, + Reagent.Bloodmoss, + Reagent.Ginseng, + Reagent.MandrakeRoot, + Reagent.SulfurousAsh + ); - public override SpellCircle Circle => SpellCircle.Eighth; - - public override bool DelayedDamage => !Core.AOS; - - public override void OnCast() - { - if (SpellHelper.CheckTown(Caster, Caster) && CheckSequence()) - { - Caster.PlaySound(0x220); - - if (Caster.Map == null) + public EarthquakeSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - FinishSequence(); - return; } - IEnumerable targets = Caster.GetMobilesInRange(1 + (int)(Caster.Skills.Magery.Value / 15.0)) - .Where(m => Caster != m && SpellHelper.ValidIndirectTarget(Caster, m) && Caster.CanBeHarmful(m, false) && (!Core.AOS || Caster.InLOS(m))); + public override SpellCircle Circle => SpellCircle.Eighth; - foreach (Mobile m in targets) + public override bool DelayedDamage => !Core.AOS; + + public override void OnCast() { - int damage; + if (SpellHelper.CheckTown(Caster, Caster) && CheckSequence()) + { + Caster.PlaySound(0x220); - if (Core.AOS) - { - damage = m.Hits / 2; + if (Caster.Map == null) + { + FinishSequence(); + return; + } - if (!m.Player) - damage = Math.Clamp(damage, 15, 100); + var targets = Caster.GetMobilesInRange(1 + (int)(Caster.Skills.Magery.Value / 15.0)) + .Where( + m => Caster != m && SpellHelper.ValidIndirectTarget(Caster, m) && Caster.CanBeHarmful(m, false) && + (!Core.AOS || Caster.InLOS(m)) + ); - damage += Utility.RandomMinMax(0, 15); - } - else - { - damage = m.Hits * 6 / 10; + foreach (var m in targets) + { + int damage; - if (!m.Player && damage < 10) - damage = 10; - else if (damage > 75) - damage = 75; - } + if (Core.AOS) + { + damage = m.Hits / 2; - Caster.DoHarmful(m); - SpellHelper.Damage(TimeSpan.Zero, m, Caster, damage, 100, 0, 0, 0, 0); + if (!m.Player) + damage = Math.Clamp(damage, 15, 100); + + damage += Utility.RandomMinMax(0, 15); + } + else + { + damage = m.Hits * 6 / 10; + + if (!m.Player && damage < 10) + damage = 10; + else if (damage > 75) + damage = 75; + } + + Caster.DoHarmful(m); + SpellHelper.Damage(TimeSpan.Zero, m, Caster, damage, 100, 0, 0, 0, 0); + } + } + + FinishSequence(); } - } - - FinishSequence(); } - } } diff --git a/Projects/UOContent/Spells/Eighth/EnergyVortex.cs b/Projects/UOContent/Spells/Eighth/EnergyVortex.cs index 8271888fd..a47c02204 100644 --- a/Projects/UOContent/Spells/Eighth/EnergyVortex.cs +++ b/Projects/UOContent/Spells/Eighth/EnergyVortex.cs @@ -3,66 +3,68 @@ using Server.Mobiles; namespace Server.Spells.Eighth { - public class EnergyVortexSpell : MagerySpell, ISpellTargetingPoint3D - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Energy Vortex", "Vas Corp Por", - 260, - 9032, - false, - Reagent.Bloodmoss, - Reagent.BlackPearl, - Reagent.MandrakeRoot, - Reagent.Nightshade); - - public EnergyVortexSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class EnergyVortexSpell : MagerySpell, ISpellTargetingPoint3D { + private static readonly SpellInfo m_Info = new SpellInfo( + "Energy Vortex", + "Vas Corp Por", + 260, + 9032, + false, + Reagent.Bloodmoss, + Reagent.BlackPearl, + Reagent.MandrakeRoot, + Reagent.Nightshade + ); + + public EnergyVortexSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.Eighth; + + public void Target(IPoint3D p) + { + var map = Caster.Map; + + SpellHelper.GetSurfaceTop(ref p); + + if (map?.CanSpawnMobile(p.X, p.Y, p.Z) != true) + { + Caster.SendLocalizedMessage(501942); // That location is blocked. + } + else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) + { + TimeSpan duration; + + if (Core.AOS) + duration = TimeSpan.FromSeconds(90.0); + else + duration = TimeSpan.FromSeconds(Utility.Random(80, 40)); + + BaseCreature.Summon(new EnergyVortex(), false, Caster, new Point3D(p), 0x212, duration); + } + + FinishSequence(); + } + + public override bool CheckCast() + { + if (!base.CheckCast()) + return false; + + if (Caster.Followers + (Core.SE ? 2 : 1) > Caster.FollowersMax) + { + Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. + return false; + } + + return true; + } + + public override void OnCast() + { + Caster.Target = new SpellTargetPoint3D(this); + } } - - public override SpellCircle Circle => SpellCircle.Eighth; - - public override bool CheckCast() - { - if (!base.CheckCast()) - return false; - - if (Caster.Followers + (Core.SE ? 2 : 1) > Caster.FollowersMax) - { - Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. - return false; - } - - return true; - } - - public override void OnCast() - { - Caster.Target = new SpellTargetPoint3D(this); - } - - public void Target(IPoint3D p) - { - Map map = Caster.Map; - - SpellHelper.GetSurfaceTop(ref p); - - if (map?.CanSpawnMobile(p.X, p.Y, p.Z) != true) - { - Caster.SendLocalizedMessage(501942); // That location is blocked. - } - else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) - { - TimeSpan duration; - - if (Core.AOS) - duration = TimeSpan.FromSeconds(90.0); - else - duration = TimeSpan.FromSeconds(Utility.Random(80, 40)); - - BaseCreature.Summon(new EnergyVortex(), false, Caster, new Point3D(p), 0x212, duration); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Eighth/FireElemental.cs b/Projects/UOContent/Spells/Eighth/FireElemental.cs index e14ec815d..a99636c3e 100644 --- a/Projects/UOContent/Spells/Eighth/FireElemental.cs +++ b/Projects/UOContent/Spells/Eighth/FireElemental.cs @@ -3,51 +3,53 @@ using Server.Mobiles; namespace Server.Spells.Eighth { - public class FireElementalSpell : MagerySpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Fire Elemental", "Kal Vas Xen Flam", - 269, - 9050, - false, - Reagent.Bloodmoss, - Reagent.MandrakeRoot, - Reagent.SpidersSilk, - Reagent.SulfurousAsh); - - public FireElementalSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class FireElementalSpell : MagerySpell { + private static readonly SpellInfo m_Info = new SpellInfo( + "Fire Elemental", + "Kal Vas Xen Flam", + 269, + 9050, + false, + Reagent.Bloodmoss, + Reagent.MandrakeRoot, + Reagent.SpidersSilk, + Reagent.SulfurousAsh + ); + + public FireElementalSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.Eighth; + + public override bool CheckCast() + { + if (!base.CheckCast()) + return false; + + if (Caster.Followers + 4 > Caster.FollowersMax) + { + Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. + return false; + } + + return true; + } + + public override void OnCast() + { + if (CheckSequence()) + { + var duration = TimeSpan.FromSeconds(2 * Caster.Skills.Magery.Fixed / 5); + + if (Core.AOS) + SpellHelper.Summon(new SummonedFireElemental(), Caster, 0x217, duration, false, false); + else + SpellHelper.Summon(new FireElemental(), Caster, 0x217, duration, false, false); + } + + FinishSequence(); + } } - - public override SpellCircle Circle => SpellCircle.Eighth; - - public override bool CheckCast() - { - if (!base.CheckCast()) - return false; - - if (Caster.Followers + 4 > Caster.FollowersMax) - { - Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. - return false; - } - - return true; - } - - public override void OnCast() - { - if (CheckSequence()) - { - TimeSpan duration = TimeSpan.FromSeconds(2 * Caster.Skills.Magery.Fixed / 5); - - if (Core.AOS) - SpellHelper.Summon(new SummonedFireElemental(), Caster, 0x217, duration, false, false); - else - SpellHelper.Summon(new FireElemental(), Caster, 0x217, duration, false, false); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Eighth/Resurrection.cs b/Projects/UOContent/Spells/Eighth/Resurrection.cs index e28ffc23e..e09a2c3c0 100644 --- a/Projects/UOContent/Spells/Eighth/Resurrection.cs +++ b/Projects/UOContent/Spells/Eighth/Resurrection.cs @@ -4,75 +4,92 @@ using Server.Targeting; namespace Server.Spells.Eighth { - public class ResurrectionSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Resurrection", "An Corp", - 245, - 9062, - Reagent.Bloodmoss, - Reagent.Garlic, - Reagent.Ginseng); - - public ResurrectionSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class ResurrectionSpell : MagerySpell, ISpellTargetingMobile { + private static readonly SpellInfo m_Info = new SpellInfo( + "Resurrection", + "An Corp", + 245, + 9062, + Reagent.Bloodmoss, + Reagent.Garlic, + Reagent.Ginseng + ); + + public ResurrectionSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.Eighth; + + public void Target(Mobile m) + { + if (m == null) + return; + + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (m == Caster) + { + Caster.SendLocalizedMessage(501039); // Thou can not resurrect thyself. + } + else if (!Caster.Alive) + { + Caster.SendLocalizedMessage(501040); // The resurrecter must be alive. + } + else if (m.Alive) + { + Caster.SendLocalizedMessage(501041); // Target is not dead. + } + else if (!Caster.InRange(m, 1)) + { + Caster.SendLocalizedMessage(501042); // Target is not close enough. + } + else if (!m.Player) + { + Caster.SendLocalizedMessage(501043); // Target is not a being. + } + else if (m.Map?.CanFit(m.Location, 16, false, false) != true) + { + Caster.SendLocalizedMessage(501042); // Target can not be resurrected at that location. + m.SendLocalizedMessage(502391); // Thou can not be resurrected there! + } + else if (m.Region?.IsPartOf("Khaldun") == true) + { + Caster.SendLocalizedMessage( + 1010395 + ); // The veil of death in this area is too strong and resists thy efforts to restore life. + } + else if (CheckBSequence(m, true)) + { + SpellHelper.Turn(Caster, m); + + m.PlaySound(0x214); + m.FixedEffect(0x376A, 10, 16); + + m.CloseGump(); + m.SendGump(new ResurrectGump(m, Caster)); + } + + FinishSequence(); + } + + public override bool CheckCast() + { + if (DuelContext.CheckSuddenDeath(Caster)) + { + Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); + return false; + } + + return base.CheckCast(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, 1); + } } - - public override SpellCircle Circle => SpellCircle.Eighth; - - public override bool CheckCast() - { - if (DuelContext.CheckSuddenDeath(Caster)) - { - Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); - return false; - } - - return base.CheckCast(); - } - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, 1); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (m == Caster) - Caster.SendLocalizedMessage(501039); // Thou can not resurrect thyself. - else if (!Caster.Alive) - Caster.SendLocalizedMessage(501040); // The resurrecter must be alive. - else if (m.Alive) - Caster.SendLocalizedMessage(501041); // Target is not dead. - else if (!Caster.InRange(m, 1)) - Caster.SendLocalizedMessage(501042); // Target is not close enough. - else if (!m.Player) - Caster.SendLocalizedMessage(501043); // Target is not a being. - else if (m.Map?.CanFit(m.Location, 16, false, false) != true) - { - Caster.SendLocalizedMessage(501042); // Target can not be resurrected at that location. - m.SendLocalizedMessage(502391); // Thou can not be resurrected there! - } - else if (m.Region?.IsPartOf("Khaldun") == true) - Caster.SendLocalizedMessage( - 1010395); // The veil of death in this area is too strong and resists thy efforts to restore life. - else if (CheckBSequence(m, true)) - { - SpellHelper.Turn(Caster, m); - - m.PlaySound(0x214); - m.FixedEffect(0x376A, 10, 16); - - m.CloseGump(); - m.SendGump(new ResurrectGump(m, Caster)); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Eighth/SummonDaemon.cs b/Projects/UOContent/Spells/Eighth/SummonDaemon.cs index a14c42920..def7c3044 100644 --- a/Projects/UOContent/Spells/Eighth/SummonDaemon.cs +++ b/Projects/UOContent/Spells/Eighth/SummonDaemon.cs @@ -3,57 +3,59 @@ using Server.Mobiles; namespace Server.Spells.Eighth { - public class SummonDaemonSpell : MagerySpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Summon Daemon", "Kal Vas Xen Corp", - 269, - 9050, - false, - Reagent.Bloodmoss, - Reagent.MandrakeRoot, - Reagent.SpidersSilk, - Reagent.SulfurousAsh); - - public SummonDaemonSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class SummonDaemonSpell : MagerySpell { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Summon Daemon", + "Kal Vas Xen Corp", + 269, + 9050, + false, + Reagent.Bloodmoss, + Reagent.MandrakeRoot, + Reagent.SpidersSilk, + Reagent.SulfurousAsh + ); - public override SpellCircle Circle => SpellCircle.Eighth; - - public override bool CheckCast() - { - if (!base.CheckCast()) - return false; - - if (Caster.Followers + (Core.SE ? 4 : 5) > Caster.FollowersMax) - { - Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. - return false; - } - - return true; - } - - public override void OnCast() - { - if (CheckSequence()) - { - TimeSpan duration = TimeSpan.FromSeconds(2 * Caster.Skills.Magery.Fixed / 5); - - if (Core.AOS) /* Why two diff daemons? TODO: solve this */ + public SummonDaemonSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - BaseCreature m_Daemon = new SummonedDaemon(); - SpellHelper.Summon(m_Daemon, Caster, 0x216, duration, false, false); - m_Daemon.FixedParticles(0x3728, 8, 20, 5042, EffectLayer.Head); } - else - { - SpellHelper.Summon(new Daemon(), Caster, 0x216, duration, false, false); - } - } - FinishSequence(); + public override SpellCircle Circle => SpellCircle.Eighth; + + public override bool CheckCast() + { + if (!base.CheckCast()) + return false; + + if (Caster.Followers + (Core.SE ? 4 : 5) > Caster.FollowersMax) + { + Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. + return false; + } + + return true; + } + + public override void OnCast() + { + if (CheckSequence()) + { + var duration = TimeSpan.FromSeconds(2 * Caster.Skills.Magery.Fixed / 5); + + if (Core.AOS) /* Why two diff daemons? TODO: solve this */ + { + BaseCreature m_Daemon = new SummonedDaemon(); + SpellHelper.Summon(m_Daemon, Caster, 0x216, duration, false, false); + m_Daemon.FixedParticles(0x3728, 8, 20, 5042, EffectLayer.Head); + } + else + { + SpellHelper.Summon(new Daemon(), Caster, 0x216, duration, false, false); + } + } + + FinishSequence(); + } } - } } diff --git a/Projects/UOContent/Spells/Eighth/WaterElemental.cs b/Projects/UOContent/Spells/Eighth/WaterElemental.cs index a6c248888..bcd6b9bb6 100644 --- a/Projects/UOContent/Spells/Eighth/WaterElemental.cs +++ b/Projects/UOContent/Spells/Eighth/WaterElemental.cs @@ -3,50 +3,52 @@ using Server.Mobiles; namespace Server.Spells.Eighth { - public class WaterElementalSpell : MagerySpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Water Elemental", "Kal Vas Xen An Flam", - 269, - 9070, - false, - Reagent.Bloodmoss, - Reagent.MandrakeRoot, - Reagent.SpidersSilk); - - public WaterElementalSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class WaterElementalSpell : MagerySpell { + private static readonly SpellInfo m_Info = new SpellInfo( + "Water Elemental", + "Kal Vas Xen An Flam", + 269, + 9070, + false, + Reagent.Bloodmoss, + Reagent.MandrakeRoot, + Reagent.SpidersSilk + ); + + public WaterElementalSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.Eighth; + + public override bool CheckCast() + { + if (!base.CheckCast()) + return false; + + if (Caster.Followers + 3 > Caster.FollowersMax) + { + Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. + return false; + } + + return true; + } + + public override void OnCast() + { + if (CheckSequence()) + { + var duration = TimeSpan.FromSeconds(2 * Caster.Skills.Magery.Fixed / 5); + + if (Core.AOS) + SpellHelper.Summon(new SummonedWaterElemental(), Caster, 0x217, duration, false, false); + else + SpellHelper.Summon(new WaterElemental(), Caster, 0x217, duration, false, false); + } + + FinishSequence(); + } } - - public override SpellCircle Circle => SpellCircle.Eighth; - - public override bool CheckCast() - { - if (!base.CheckCast()) - return false; - - if (Caster.Followers + 3 > Caster.FollowersMax) - { - Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. - return false; - } - - return true; - } - - public override void OnCast() - { - if (CheckSequence()) - { - TimeSpan duration = TimeSpan.FromSeconds(2 * Caster.Skills.Magery.Fixed / 5); - - if (Core.AOS) - SpellHelper.Summon(new SummonedWaterElemental(), Caster, 0x217, duration, false, false); - else - SpellHelper.Summon(new WaterElemental(), Caster, 0x217, duration, false, false); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Fifth/BladeSpirits.cs b/Projects/UOContent/Spells/Fifth/BladeSpirits.cs index b95989cb9..dfd8a729a 100644 --- a/Projects/UOContent/Spells/Fifth/BladeSpirits.cs +++ b/Projects/UOContent/Spells/Fifth/BladeSpirits.cs @@ -3,73 +3,75 @@ using Server.Mobiles; namespace Server.Spells.Fifth { - public class BladeSpiritsSpell : MagerySpell, ISpellTargetingPoint3D - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Blade Spirits", "In Jux Hur Ylem", - 266, - 9040, - false, - Reagent.BlackPearl, - Reagent.MandrakeRoot, - Reagent.Nightshade); - - public BladeSpiritsSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class BladeSpiritsSpell : MagerySpell, ISpellTargetingPoint3D { + private static readonly SpellInfo m_Info = new SpellInfo( + "Blade Spirits", + "In Jux Hur Ylem", + 266, + 9040, + false, + Reagent.BlackPearl, + Reagent.MandrakeRoot, + Reagent.Nightshade + ); + + public BladeSpiritsSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.Fifth; + + public void Target(IPoint3D p) + { + var map = Caster.Map; + + SpellHelper.GetSurfaceTop(ref p); + + if (map?.CanSpawnMobile(p.X, p.Y, p.Z) != true) + { + Caster.SendLocalizedMessage(501942); // That location is blocked. + } + else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) + { + TimeSpan duration; + + if (Core.AOS) + duration = TimeSpan.FromSeconds(120); + else + duration = TimeSpan.FromSeconds(Utility.Random(80, 40)); + + BaseCreature.Summon(new BladeSpirits(), false, Caster, new Point3D(p), 0x212, duration); + } + + FinishSequence(); + } + + public override TimeSpan GetCastDelay() + { + if (Core.AOS) + return TimeSpan.FromTicks(base.GetCastDelay().Ticks * (Core.SE ? 3 : 5)); + + return base.GetCastDelay() + TimeSpan.FromSeconds(6.0); + } + + public override bool CheckCast() + { + if (!base.CheckCast()) + return false; + + if (Caster.Followers + (Core.SE ? 2 : 1) > Caster.FollowersMax) + { + Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. + return false; + } + + return true; + } + + public override void OnCast() + { + Caster.Target = new SpellTargetPoint3D(this); + } } - - public override SpellCircle Circle => SpellCircle.Fifth; - - public override TimeSpan GetCastDelay() - { - if (Core.AOS) - return TimeSpan.FromTicks(base.GetCastDelay().Ticks * (Core.SE ? 3 : 5)); - - return base.GetCastDelay() + TimeSpan.FromSeconds(6.0); - } - - public override bool CheckCast() - { - if (!base.CheckCast()) - return false; - - if (Caster.Followers + (Core.SE ? 2 : 1) > Caster.FollowersMax) - { - Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. - return false; - } - - return true; - } - - public override void OnCast() - { - Caster.Target = new SpellTargetPoint3D(this); - } - - public void Target(IPoint3D p) - { - Map map = Caster.Map; - - SpellHelper.GetSurfaceTop(ref p); - - if (map?.CanSpawnMobile(p.X, p.Y, p.Z) != true) - { - Caster.SendLocalizedMessage(501942); // That location is blocked. - } - else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) - { - TimeSpan duration; - - if (Core.AOS) - duration = TimeSpan.FromSeconds(120); - else - duration = TimeSpan.FromSeconds(Utility.Random(80, 40)); - - BaseCreature.Summon(new BladeSpirits(), false, Caster, new Point3D(p), 0x212, duration); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Fifth/DispelField.cs b/Projects/UOContent/Spells/Fifth/DispelField.cs index 1dc01975a..177772e86 100644 --- a/Projects/UOContent/Spells/Fifth/DispelField.cs +++ b/Projects/UOContent/Spells/Fifth/DispelField.cs @@ -4,50 +4,65 @@ using Server.Targeting; namespace Server.Spells.Fifth { - public class DispelFieldSpell : MagerySpell, ISpellTargetingItem - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Dispel Field", "An Grav", - 206, - 9002, - Reagent.BlackPearl, - Reagent.SpidersSilk, - Reagent.SulfurousAsh, - Reagent.Garlic); - - public DispelFieldSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class DispelFieldSpell : MagerySpell, ISpellTargetingItem { + private static readonly SpellInfo m_Info = new SpellInfo( + "Dispel Field", + "An Grav", + 206, + 9002, + Reagent.BlackPearl, + Reagent.SpidersSilk, + Reagent.SulfurousAsh, + Reagent.Garlic + ); + + public DispelFieldSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.Fifth; + + public void Target(Item item) + { + if (item == null) + { + Caster.SendLocalizedMessage(1005049); // That cannot be dispelled. + } + else if (!Caster.CanSee(item)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (!item.GetType().IsDefined(typeof(DispellableFieldAttribute), false)) + { + Caster.SendLocalizedMessage(1005049); // That cannot be dispelled. + } + else if (item is Moongate moongate && !moongate.Dispellable) + { + Caster.SendLocalizedMessage(1005047); // That magic is too chaotic + } + else if (CheckSequence()) + { + SpellHelper.Turn(Caster, item); + + Effects.SendLocationParticles( + EffectItem.Create(item.Location, item.Map, EffectItem.DefaultDuration), + 0x376A, + 9, + 20, + 5042 + ); + Effects.PlaySound(item.GetWorldLocation(), item.Map, 0x201); + + item.Delete(); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetItem(this, TargetFlags.None, Core.ML ? 10 : 12); + } } - - public override SpellCircle Circle => SpellCircle.Fifth; - - public override void OnCast() - { - Caster.Target = new SpellTargetItem(this, TargetFlags.None, Core.ML ? 10 : 12); - } - - public void Target(Item item) - { - if (item == null) - Caster.SendLocalizedMessage(1005049); // That cannot be dispelled. - else if (!Caster.CanSee(item)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (!item.GetType().IsDefined(typeof(DispellableFieldAttribute), false)) - Caster.SendLocalizedMessage(1005049); // That cannot be dispelled. - else if (item is Moongate moongate && !moongate.Dispellable) - Caster.SendLocalizedMessage(1005047); // That magic is too chaotic - else if (CheckSequence()) - { - SpellHelper.Turn(Caster, item); - - Effects.SendLocationParticles(EffectItem.Create(item.Location, item.Map, EffectItem.DefaultDuration), 0x376A, - 9, 20, 5042); - Effects.PlaySound(item.GetWorldLocation(), item.Map, 0x201); - - item.Delete(); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Fifth/Incognito.cs b/Projects/UOContent/Spells/Fifth/Incognito.cs index 12d49cb3b..b16c3b769 100644 --- a/Projects/UOContent/Spells/Fifth/Incognito.cs +++ b/Projects/UOContent/Spells/Fifth/Incognito.cs @@ -7,162 +7,164 @@ using Server.Spells.Seventh; namespace Server.Spells.Fifth { - public class IncognitoSpell : MagerySpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Incognito", "Kal In Ex", - 206, - 9002, - Reagent.Bloodmoss, - Reagent.Garlic, - Reagent.Nightshade); - - private static readonly Dictionary m_Timers = new Dictionary(); - - public IncognitoSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class IncognitoSpell : MagerySpell { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Incognito", + "Kal In Ex", + 206, + 9002, + Reagent.Bloodmoss, + Reagent.Garlic, + Reagent.Nightshade + ); - public override SpellCircle Circle => SpellCircle.Fifth; + private static readonly Dictionary m_Timers = new Dictionary(); - public override bool CheckCast() - { - if (Sigil.ExistsOn(Caster)) - { - Caster.SendLocalizedMessage(1010445); // You cannot incognito if you have a sigil - return false; - } - - if (!Caster.CanBeginAction()) - { - Caster.SendLocalizedMessage(1005559); // This spell is already in effect. - return false; - } - - if (Caster.BodyMod == 183 || Caster.BodyMod == 184) - { - Caster.SendLocalizedMessage(1042402); // You cannot use incognito while wearing body paint - return false; - } - - return true; - } - - public override void OnCast() - { - if (Sigil.ExistsOn(Caster)) - { - Caster.SendLocalizedMessage(1010445); // You cannot incognito if you have a sigil - } - else if (!Caster.CanBeginAction()) - { - Caster.SendLocalizedMessage(1005559); // This spell is already in effect. - } - else if (Caster.BodyMod == 183 || Caster.BodyMod == 184) - { - Caster.SendLocalizedMessage(1042402); // You cannot use incognito while wearing body paint - } - else if (DisguiseTimers.IsDisguised(Caster)) - { - Caster.SendLocalizedMessage(1061631); // You can't do that while disguised. - } - else if (!Caster.CanBeginAction() || Caster.IsBodyMod) - { - DoFizzle(); - } - else if (CheckSequence()) - { - if (Caster.BeginAction()) + public IncognitoSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - DisguiseTimers.StopTimer(Caster); - - Caster.HueMod = Caster.Race.RandomSkinHue(); - Caster.NameMod = Caster.Female ? NameList.RandomName("female") : NameList.RandomName("male"); - - PlayerMobile pm = Caster as PlayerMobile; - - if (pm?.Race != null) - { - pm.SetHairMods(pm.Race.RandomHair(pm.Female), pm.Race.RandomFacialHair(pm.Female)); - pm.HairHue = pm.Race.RandomHairHue(); - pm.FacialHairHue = pm.Race.RandomHairHue(); - } - - Caster.FixedParticles(0x373A, 10, 15, 5036, EffectLayer.Head); - Caster.PlaySound(0x3BD); - - BaseArmor.ValidateMobile(Caster); - BaseClothing.ValidateMobile(Caster); - - StopTimer(Caster); - - int timeVal = 6 * Caster.Skills.Magery.Fixed / 50 + 1; - - if (timeVal > 144) - timeVal = 144; - - TimeSpan length = TimeSpan.FromSeconds(timeVal); - - InternalTimer t = new InternalTimer(Caster, length); - m_Timers[Caster] = t; - - t.Start(); - - BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.Incognito, 1075819, length, Caster)); } - else + + public override SpellCircle Circle => SpellCircle.Fifth; + + public override bool CheckCast() { - Caster.SendLocalizedMessage(1079022); // You're already incognitoed! + if (Sigil.ExistsOn(Caster)) + { + Caster.SendLocalizedMessage(1010445); // You cannot incognito if you have a sigil + return false; + } + + if (!Caster.CanBeginAction()) + { + Caster.SendLocalizedMessage(1005559); // This spell is already in effect. + return false; + } + + if (Caster.BodyMod == 183 || Caster.BodyMod == 184) + { + Caster.SendLocalizedMessage(1042402); // You cannot use incognito while wearing body paint + return false; + } + + return true; } - } - FinishSequence(); + public override void OnCast() + { + if (Sigil.ExistsOn(Caster)) + { + Caster.SendLocalizedMessage(1010445); // You cannot incognito if you have a sigil + } + else if (!Caster.CanBeginAction()) + { + Caster.SendLocalizedMessage(1005559); // This spell is already in effect. + } + else if (Caster.BodyMod == 183 || Caster.BodyMod == 184) + { + Caster.SendLocalizedMessage(1042402); // You cannot use incognito while wearing body paint + } + else if (DisguiseTimers.IsDisguised(Caster)) + { + Caster.SendLocalizedMessage(1061631); // You can't do that while disguised. + } + else if (!Caster.CanBeginAction() || Caster.IsBodyMod) + { + DoFizzle(); + } + else if (CheckSequence()) + { + if (Caster.BeginAction()) + { + DisguiseTimers.StopTimer(Caster); + + Caster.HueMod = Caster.Race.RandomSkinHue(); + Caster.NameMod = Caster.Female ? NameList.RandomName("female") : NameList.RandomName("male"); + + var pm = Caster as PlayerMobile; + + if (pm?.Race != null) + { + pm.SetHairMods(pm.Race.RandomHair(pm.Female), pm.Race.RandomFacialHair(pm.Female)); + pm.HairHue = pm.Race.RandomHairHue(); + pm.FacialHairHue = pm.Race.RandomHairHue(); + } + + Caster.FixedParticles(0x373A, 10, 15, 5036, EffectLayer.Head); + Caster.PlaySound(0x3BD); + + BaseArmor.ValidateMobile(Caster); + BaseClothing.ValidateMobile(Caster); + + StopTimer(Caster); + + var timeVal = 6 * Caster.Skills.Magery.Fixed / 50 + 1; + + if (timeVal > 144) + timeVal = 144; + + var length = TimeSpan.FromSeconds(timeVal); + + var t = new InternalTimer(Caster, length); + m_Timers[Caster] = t; + + t.Start(); + + BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.Incognito, 1075819, length, Caster)); + } + else + { + Caster.SendLocalizedMessage(1079022); // You're already incognitoed! + } + } + + FinishSequence(); + } + + public static void StopTimer(Mobile m) + { + if (!m_Timers.TryGetValue(m, out var t)) + return; + + t.Stop(); + m_Timers.Remove(m); + BuffInfo.RemoveBuff(m, BuffIcon.Incognito); + } + + private class InternalTimer : Timer + { + private readonly Mobile m_Owner; + + public InternalTimer(Mobile owner, TimeSpan length) : base(length) + { + m_Owner = owner; + + /* + int val = ((6 * owner.Skills.Magery.Fixed) / 50) + 1; + + if (val > 144) + val = 144; + + Delay = TimeSpan.FromSeconds( val ); + * */ + Priority = TimerPriority.OneSecond; + } + + protected override void OnTick() + { + if (m_Owner.CanBeginAction()) + return; + + (m_Owner as PlayerMobile)?.SetHairMods(-1, -1); + + m_Owner.BodyMod = 0; + m_Owner.HueMod = -1; + m_Owner.NameMod = null; + m_Owner.EndAction(); + + BaseArmor.ValidateMobile(m_Owner); + BaseClothing.ValidateMobile(m_Owner); + } + } } - - public static void StopTimer(Mobile m) - { - if (!m_Timers.TryGetValue(m, out InternalTimer t)) - return; - - t.Stop(); - m_Timers.Remove(m); - BuffInfo.RemoveBuff(m, BuffIcon.Incognito); - } - - private class InternalTimer : Timer - { - private readonly Mobile m_Owner; - - public InternalTimer(Mobile owner, TimeSpan length) : base(length) - { - m_Owner = owner; - - /* - int val = ((6 * owner.Skills.Magery.Fixed) / 50) + 1; - - if (val > 144) - val = 144; - - Delay = TimeSpan.FromSeconds( val ); - * */ - Priority = TimerPriority.OneSecond; - } - - protected override void OnTick() - { - if (m_Owner.CanBeginAction()) - return; - - (m_Owner as PlayerMobile)?.SetHairMods(-1, -1); - - m_Owner.BodyMod = 0; - m_Owner.HueMod = -1; - m_Owner.NameMod = null; - m_Owner.EndAction(); - - BaseArmor.ValidateMobile(m_Owner); - BaseClothing.ValidateMobile(m_Owner); - } - } - } } diff --git a/Projects/UOContent/Spells/Fifth/MagicReflect.cs b/Projects/UOContent/Spells/Fifth/MagicReflect.cs index decf379f9..29ea60180 100644 --- a/Projects/UOContent/Spells/Fifth/MagicReflect.cs +++ b/Projects/UOContent/Spells/Fifth/MagicReflect.cs @@ -2,143 +2,145 @@ using System.Collections.Generic; namespace Server.Spells.Fifth { - public class MagicReflectSpell : MagerySpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Magic Reflection", "In Jux Sanct", - 242, - 9012, - Reagent.Garlic, - Reagent.MandrakeRoot, - Reagent.SpidersSilk); - - private static readonly Dictionary m_Table = new Dictionary(); - - public MagicReflectSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class MagicReflectSpell : MagerySpell { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Magic Reflection", + "In Jux Sanct", + 242, + 9012, + Reagent.Garlic, + Reagent.MandrakeRoot, + Reagent.SpidersSilk + ); - public override SpellCircle Circle => SpellCircle.Fifth; + private static readonly Dictionary m_Table = new Dictionary(); - public override bool CheckCast() - { - if (Core.AOS) - return true; - - if (Caster.MagicDamageAbsorb > 0) - { - Caster.SendLocalizedMessage(1005559); // This spell is already in effect. - return false; - } - - if (!Caster.CanBeginAction()) - { - Caster.SendLocalizedMessage(1005385); // The spell will not adhere to you at this time. - return false; - } - - return true; - } - - public override void OnCast() - { - if (Core.AOS) - { - /* The magic reflection spell decreases the caster's physical resistance, while increasing the caster's elemental resistances. - * Physical decrease = 25 - (Inscription/20). - * Elemental resistance = +10 (-20 physical, +10 elemental at GM Inscription) - * The magic reflection spell has an indefinite duration, becoming active when cast, and deactivated when re-cast. - * Reactive Armor, Protection, and Magic Reflection will stay on�even after logging out, even after dying�until you �turn them off� by casting them again. - */ - - if (CheckSequence()) + public MagicReflectSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - Mobile targ = Caster; + } - if (m_Table.TryGetValue(targ, out ResistanceMod[] mods)) - { - targ.PlaySound(0x1ED); - targ.FixedParticles(0x375A, 10, 15, 5037, EffectLayer.Waist); + public override SpellCircle Circle => SpellCircle.Fifth; - m_Table.Remove(targ); + public override bool CheckCast() + { + if (Core.AOS) + return true; - for (int i = 0; i < mods.Length; ++i) - targ.RemoveResistanceMod(mods[i]); - - BuffInfo.RemoveBuff(targ, BuffIcon.MagicReflection); - } - else - { - targ.PlaySound(0x1E9); - targ.FixedParticles(0x375A, 10, 15, 5037, EffectLayer.Waist); - - int physiMod = -25 + (int)(targ.Skills.Inscribe.Value / 20); - int otherMod = 10; - - mods = new[] + if (Caster.MagicDamageAbsorb > 0) { - new ResistanceMod(ResistanceType.Physical, physiMod), - new ResistanceMod(ResistanceType.Fire, otherMod), - new ResistanceMod(ResistanceType.Cold, otherMod), - new ResistanceMod(ResistanceType.Poison, otherMod), - new ResistanceMod(ResistanceType.Energy, otherMod) - }; + Caster.SendLocalizedMessage(1005559); // This spell is already in effect. + return false; + } - m_Table[targ] = mods; + if (!Caster.CanBeginAction()) + { + Caster.SendLocalizedMessage(1005385); // The spell will not adhere to you at this time. + return false; + } - for (int i = 0; i < mods.Length; ++i) - targ.AddResistanceMod(mods[i]); - - string buffFormat = $"{physiMod}\t+{otherMod}\t+{otherMod}\t+{otherMod}\t+{otherMod}"; - - BuffInfo.AddBuff(targ, new BuffInfo(BuffIcon.MagicReflection, 1075817, buffFormat, true)); - } + return true; } - FinishSequence(); - } - else - { - if (Caster.MagicDamageAbsorb > 0) + public override void OnCast() { - Caster.SendLocalizedMessage(1005559); // This spell is already in effect. + if (Core.AOS) + { + /* The magic reflection spell decreases the caster's physical resistance, while increasing the caster's elemental resistances. + * Physical decrease = 25 - (Inscription/20). + * Elemental resistance = +10 (-20 physical, +10 elemental at GM Inscription) + * The magic reflection spell has an indefinite duration, becoming active when cast, and deactivated when re-cast. + * Reactive Armor, Protection, and Magic Reflection will stay on�even after logging out, even after dying�until you �turn them off� by casting them again. + */ + + if (CheckSequence()) + { + var targ = Caster; + + if (m_Table.TryGetValue(targ, out var mods)) + { + targ.PlaySound(0x1ED); + targ.FixedParticles(0x375A, 10, 15, 5037, EffectLayer.Waist); + + m_Table.Remove(targ); + + for (var i = 0; i < mods.Length; ++i) + targ.RemoveResistanceMod(mods[i]); + + BuffInfo.RemoveBuff(targ, BuffIcon.MagicReflection); + } + else + { + targ.PlaySound(0x1E9); + targ.FixedParticles(0x375A, 10, 15, 5037, EffectLayer.Waist); + + var physiMod = -25 + (int)(targ.Skills.Inscribe.Value / 20); + var otherMod = 10; + + mods = new[] + { + new ResistanceMod(ResistanceType.Physical, physiMod), + new ResistanceMod(ResistanceType.Fire, otherMod), + new ResistanceMod(ResistanceType.Cold, otherMod), + new ResistanceMod(ResistanceType.Poison, otherMod), + new ResistanceMod(ResistanceType.Energy, otherMod) + }; + + m_Table[targ] = mods; + + for (var i = 0; i < mods.Length; ++i) + targ.AddResistanceMod(mods[i]); + + var buffFormat = $"{physiMod}\t+{otherMod}\t+{otherMod}\t+{otherMod}\t+{otherMod}"; + + BuffInfo.AddBuff(targ, new BuffInfo(BuffIcon.MagicReflection, 1075817, buffFormat, true)); + } + } + + FinishSequence(); + } + else + { + if (Caster.MagicDamageAbsorb > 0) + { + Caster.SendLocalizedMessage(1005559); // This spell is already in effect. + } + else if (!Caster.CanBeginAction()) + { + Caster.SendLocalizedMessage(1005385); // The spell will not adhere to you at this time. + } + else if (CheckSequence()) + { + if (Caster.BeginAction()) + { + var value = (int)(Caster.Skills.Magery.Value + Caster.Skills.Inscribe.Value); + value = (int)(8 + value / 200.0 * 7.0); // absorb from 8 to 15 "circles" + + Caster.MagicDamageAbsorb = value; + + Caster.FixedParticles(0x375A, 10, 15, 5037, EffectLayer.Waist); + Caster.PlaySound(0x1E9); + } + else + { + Caster.SendLocalizedMessage(1005385); // The spell will not adhere to you at this time. + } + } + + FinishSequence(); + } } - else if (!Caster.CanBeginAction()) + + public static void EndReflect(Mobile m) { - Caster.SendLocalizedMessage(1005385); // The spell will not adhere to you at this time. + if (!m_Table.TryGetValue(m, out var mods)) + return; + + for (var i = 0; i < mods?.Length; ++i) + m.RemoveResistanceMod(mods[i]); + + m_Table.Remove(m); + BuffInfo.RemoveBuff(m, BuffIcon.MagicReflection); } - else if (CheckSequence()) - { - if (Caster.BeginAction()) - { - int value = (int)(Caster.Skills.Magery.Value + Caster.Skills.Inscribe.Value); - value = (int)(8 + value / 200.0 * 7.0); // absorb from 8 to 15 "circles" - - Caster.MagicDamageAbsorb = value; - - Caster.FixedParticles(0x375A, 10, 15, 5037, EffectLayer.Waist); - Caster.PlaySound(0x1E9); - } - else - { - Caster.SendLocalizedMessage(1005385); // The spell will not adhere to you at this time. - } - } - - FinishSequence(); - } } - - public static void EndReflect(Mobile m) - { - if (!m_Table.TryGetValue(m, out ResistanceMod[] mods)) - return; - - for (int i = 0; i < mods?.Length; ++i) - m.RemoveResistanceMod(mods[i]); - - m_Table.Remove(m); - BuffInfo.RemoveBuff(m, BuffIcon.MagicReflection); - } - } } diff --git a/Projects/UOContent/Spells/Fifth/MindBlast.cs b/Projects/UOContent/Spells/Fifth/MindBlast.cs index fc70392b1..073de939c 100644 --- a/Projects/UOContent/Spells/Fifth/MindBlast.cs +++ b/Projects/UOContent/Spells/Fifth/MindBlast.cs @@ -3,115 +3,125 @@ using Server.Targeting; namespace Server.Spells.Fifth { - public class MindBlastSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Mind Blast", "Por Corp Wis", - 218, - Core.AOS ? 9002 : 9032, - Reagent.BlackPearl, - Reagent.MandrakeRoot, - Reagent.Nightshade, - Reagent.SulfurousAsh); - - public MindBlastSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class MindBlastSpell : MagerySpell, ISpellTargetingMobile { - if (Core.AOS) - m_Info.LeftHandEffect = m_Info.RightHandEffect = 9002; - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Mind Blast", + "Por Corp Wis", + 218, + Core.AOS ? 9002 : 9032, + Reagent.BlackPearl, + Reagent.MandrakeRoot, + Reagent.Nightshade, + Reagent.SulfurousAsh + ); - public override SpellCircle Circle => SpellCircle.Fifth; - - public override bool DelayedDamage => !Core.AOS; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - private void AosDelay_Callback(Mobile caster, Mobile target, Mobile defender, int damage) - { - if (caster.HarmfulCheck(defender)) - { - SpellHelper.Damage(this, target, Utility.RandomMinMax(damage, damage + 4), 0, 0, 100, 0, 0); - - target.FixedParticles(0x374A, 10, 15, 5038, 1181, 2, EffectLayer.Head); - target.PlaySound(0x213); - } - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (Core.AOS) - { - if (Caster.CanBeHarmful(m) && CheckSequence()) + public MindBlastSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - Mobile from = Caster, target = m; - - SpellHelper.Turn(from, target); - - SpellHelper.CheckReflect((int)Circle, ref from, ref target); - - int damage = Math.Min((int)((Caster.Skills.Magery.Value + Caster.Int) / 5), 60); - - Timer.DelayCall(TimeSpan.FromSeconds(1.0), - AosDelay_Callback, Caster, target, m, damage); - } - } - else if (CheckHSequence(m)) - { - Mobile from = Caster, target = m; - - SpellHelper.Turn(from, target); - - SpellHelper.CheckReflect((int)Circle, ref from, ref target); - - // Algorithm: (highestStat - lowestStat) / 2 [- 50% if resisted] - - int highestStat = target.Str, lowestStat = target.Str; - - if (target.Dex > highestStat) - highestStat = target.Dex; - - if (target.Dex < lowestStat) - lowestStat = target.Dex; - - if (target.Int > highestStat) - highestStat = target.Int; - - if (target.Int < lowestStat) - lowestStat = target.Int; - - if (highestStat > 150) - highestStat = 150; - - if (lowestStat > 150) - lowestStat = 150; - - double damage = Math.Min(GetDamageScalar(m) * (highestStat - lowestStat) / 2, 45); // Many users prefer 3 or 4 - - if (CheckResisted(target)) - { - damage /= 2; - target.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + if (Core.AOS) + m_Info.LeftHandEffect = m_Info.RightHandEffect = 9002; } - from.FixedParticles(0x374A, 10, 15, 2038, EffectLayer.Head); + public override SpellCircle Circle => SpellCircle.Fifth; - target.FixedParticles(0x374A, 10, 15, 5038, EffectLayer.Head); - target.PlaySound(0x213); + public override bool DelayedDamage => !Core.AOS; - SpellHelper.Damage(this, target, damage, 0, 0, 100, 0, 0); - } + public void Target(Mobile m) + { + if (m == null) + return; - FinishSequence(); + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (Core.AOS) + { + if (Caster.CanBeHarmful(m) && CheckSequence()) + { + Mobile from = Caster, target = m; + + SpellHelper.Turn(from, target); + + SpellHelper.CheckReflect((int)Circle, ref from, ref target); + + var damage = Math.Min((int)((Caster.Skills.Magery.Value + Caster.Int) / 5), 60); + + Timer.DelayCall( + TimeSpan.FromSeconds(1.0), + AosDelay_Callback, + Caster, + target, + m, + damage + ); + } + } + else if (CheckHSequence(m)) + { + Mobile from = Caster, target = m; + + SpellHelper.Turn(from, target); + + SpellHelper.CheckReflect((int)Circle, ref from, ref target); + + // Algorithm: (highestStat - lowestStat) / 2 [- 50% if resisted] + + int highestStat = target.Str, lowestStat = target.Str; + + if (target.Dex > highestStat) + highestStat = target.Dex; + + if (target.Dex < lowestStat) + lowestStat = target.Dex; + + if (target.Int > highestStat) + highestStat = target.Int; + + if (target.Int < lowestStat) + lowestStat = target.Int; + + if (highestStat > 150) + highestStat = 150; + + if (lowestStat > 150) + lowestStat = 150; + + var damage = Math.Min(GetDamageScalar(m) * (highestStat - lowestStat) / 2, 45); // Many users prefer 3 or 4 + + if (CheckResisted(target)) + { + damage /= 2; + target.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + } + + from.FixedParticles(0x374A, 10, 15, 2038, EffectLayer.Head); + + target.FixedParticles(0x374A, 10, 15, 5038, EffectLayer.Head); + target.PlaySound(0x213); + + SpellHelper.Damage(this, target, damage, 0, 0, 100, 0, 0); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } + + private void AosDelay_Callback(Mobile caster, Mobile target, Mobile defender, int damage) + { + if (caster.HarmfulCheck(defender)) + { + SpellHelper.Damage(this, target, Utility.RandomMinMax(damage, damage + 4), 0, 0, 100, 0, 0); + + target.FixedParticles(0x374A, 10, 15, 5038, 1181, 2, EffectLayer.Head); + target.PlaySound(0x213); + } + } + + public override double GetSlayerDamageScalar(Mobile target) => 1.0; } - - public override double GetSlayerDamageScalar(Mobile target) => 1.0; - } } diff --git a/Projects/UOContent/Spells/Fifth/Paralyze.cs b/Projects/UOContent/Spells/Fifth/Paralyze.cs index 89ac9915a..286cb65d0 100644 --- a/Projects/UOContent/Spells/Fifth/Paralyze.cs +++ b/Projects/UOContent/Spells/Fifth/Paralyze.cs @@ -5,84 +5,88 @@ using Server.Targeting; namespace Server.Spells.Fifth { - public class ParalyzeSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Paralyze", "An Ex Por", - 218, - 9012, - Reagent.Garlic, - Reagent.MandrakeRoot, - Reagent.SpidersSilk); - - public ParalyzeSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class ParalyzeSpell : MagerySpell, ISpellTargetingMobile { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Paralyze", + "An Ex Por", + 218, + 9012, + Reagent.Garlic, + Reagent.MandrakeRoot, + Reagent.SpidersSilk + ); - public override SpellCircle Circle => SpellCircle.Fifth; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (Core.AOS && (m.Frozen || m.Paralyzed || - (m.Spell?.IsCasting == true && !(m.Spell is PaladinSpell)))) - { - Caster.SendLocalizedMessage(1061923); // The target is already frozen. - } - else if (CheckHSequence(m)) - { - SpellHelper.Turn(Caster, m); - - SpellHelper.CheckReflect((int)Circle, Caster, ref m); - - double duration; - - if (Core.AOS) + public ParalyzeSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - int secs = (int)(GetDamageSkill(Caster) / 10 - GetResistSkill(m) / 10); - - if (!Core.SE) - secs += 2; - - if (!m.Player) - secs *= 3; - - duration = Math.Max(secs, 0); - } - else - { - // Algorithm: ((20% of magery) + 7) seconds [- 50% if resisted] - - duration = 7.0 + Caster.Skills.Magery.Value * 0.2; - - if (CheckResisted(m)) - duration *= 0.75; } - if (m is PlagueBeastLord lord) + public override SpellCircle Circle => SpellCircle.Fifth; + + public void Target(Mobile m) { - lord.OnParalyzed(Caster); - duration = 120; + if (m == null) + return; + + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (Core.AOS && (m.Frozen || m.Paralyzed || + m.Spell?.IsCasting == true && !(m.Spell is PaladinSpell))) + { + Caster.SendLocalizedMessage(1061923); // The target is already frozen. + } + else if (CheckHSequence(m)) + { + SpellHelper.Turn(Caster, m); + + SpellHelper.CheckReflect((int)Circle, Caster, ref m); + + double duration; + + if (Core.AOS) + { + var secs = (int)(GetDamageSkill(Caster) / 10 - GetResistSkill(m) / 10); + + if (!Core.SE) + secs += 2; + + if (!m.Player) + secs *= 3; + + duration = Math.Max(secs, 0); + } + else + { + // Algorithm: ((20% of magery) + 7) seconds [- 50% if resisted] + + duration = 7.0 + Caster.Skills.Magery.Value * 0.2; + + if (CheckResisted(m)) + duration *= 0.75; + } + + if (m is PlagueBeastLord lord) + { + lord.OnParalyzed(Caster); + duration = 120; + } + + m.Paralyze(TimeSpan.FromSeconds(duration)); + + m.PlaySound(0x204); + m.FixedEffect(0x376A, 6, 1); + + HarmfulSpell(m); + } + + FinishSequence(); } - m.Paralyze(TimeSpan.FromSeconds(duration)); - - m.PlaySound(0x204); - m.FixedEffect(0x376A, 6, 1); - - HarmfulSpell(m); - } - - FinishSequence(); + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } } - } } diff --git a/Projects/UOContent/Spells/Fifth/PoisonField.cs b/Projects/UOContent/Spells/Fifth/PoisonField.cs index decec0b0e..e62c7cd66 100644 --- a/Projects/UOContent/Spells/Fifth/PoisonField.cs +++ b/Projects/UOContent/Spells/Fifth/PoisonField.cs @@ -7,267 +7,280 @@ using Server.Targeting; namespace Server.Spells.Fifth { - public class PoisonFieldSpell : MagerySpell, ISpellTargetingPoint3D - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Poison Field", "In Nox Grav", - 230, - 9052, - false, - Reagent.BlackPearl, - Reagent.Nightshade, - Reagent.SpidersSilk); - - public PoisonFieldSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class PoisonFieldSpell : MagerySpell, ISpellTargetingPoint3D { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Poison Field", + "In Nox Grav", + 230, + 9052, + false, + Reagent.BlackPearl, + Reagent.Nightshade, + Reagent.SpidersSilk + ); - public override SpellCircle Circle => SpellCircle.Fifth; - - public override void OnCast() - { - Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12, false); - } - - public void Target(IPoint3D p) - { - if (!Caster.CanSee(p)) - { - Caster.SendLocalizedMessage(500237); // Target can not be seen. - } - else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) - { - SpellHelper.Turn(Caster, p); - - SpellHelper.GetSurfaceTop(ref p); - - int dx = Caster.Location.X - p.X; - int dy = Caster.Location.Y - p.Y; - int rx = (dx - dy) * 44; - int ry = (dx + dy) * 44; - - bool eastToWest; - - if (rx >= 0 && ry >= 0) - eastToWest = false; - else if (rx >= 0) - eastToWest = true; - else if (ry >= 0) - eastToWest = true; - else - eastToWest = false; - - Effects.PlaySound(p, Caster.Map, 0x20B); - - int itemID = eastToWest ? 0x3915 : 0x3922; - - TimeSpan duration = TimeSpan.FromSeconds(3 + Caster.Skills.Magery.Fixed / 25); - - for (int i = -2; i <= 2; ++i) + public PoisonFieldSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - Point3D loc = new Point3D(eastToWest ? p.X + i : p.X, eastToWest ? p.Y : p.Y + i, p.Z); - - new InternalItem(itemID, loc, Caster, Caster.Map, duration, i); } - } - FinishSequence(); - } + public override SpellCircle Circle => SpellCircle.Fifth; - [DispellableField] - public class InternalItem : Item - { - private Mobile m_Caster; - private DateTime m_End; - private Timer m_Timer; - - public InternalItem(int itemID, Point3D loc, Mobile caster, Map map, TimeSpan duration, int val) : base(itemID) - { - bool canFit = SpellHelper.AdjustField(ref loc, map, 12, false); - - Visible = false; - Movable = false; - Light = LightType.Circle300; - - MoveToWorld(loc, map); - - m_Caster = caster; - - m_End = DateTime.UtcNow + duration; - - m_Timer = new InternalTimer(this, TimeSpan.FromSeconds(Math.Abs(val) * 0.2), caster.InLOS(this), canFit); - m_Timer.Start(); - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public override bool BlocksFit => true; - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Timer?.Stop(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.Write(m_Caster); - writer.WriteDeltaTime(m_End); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) + public void Target(IPoint3D p) { - case 1: + if (!Caster.CanSee(p)) { - m_Caster = reader.ReadMobile(); - - goto case 0; + Caster.SendLocalizedMessage(500237); // Target can not be seen. } - case 0: + else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) { - m_End = reader.ReadDeltaTime(); + SpellHelper.Turn(Caster, p); - m_Timer = new InternalTimer(this, TimeSpan.Zero, true, true); - m_Timer.Start(); + SpellHelper.GetSurfaceTop(ref p); - break; + var dx = Caster.Location.X - p.X; + var dy = Caster.Location.Y - p.Y; + var rx = (dx - dy) * 44; + var ry = (dx + dy) * 44; + + bool eastToWest; + + if (rx >= 0 && ry >= 0) + eastToWest = false; + else if (rx >= 0) + eastToWest = true; + else if (ry >= 0) + eastToWest = true; + else + eastToWest = false; + + Effects.PlaySound(p, Caster.Map, 0x20B); + + var itemID = eastToWest ? 0x3915 : 0x3922; + + var duration = TimeSpan.FromSeconds(3 + Caster.Skills.Magery.Fixed / 25); + + for (var i = -2; i <= 2; ++i) + { + var loc = new Point3D(eastToWest ? p.X + i : p.X, eastToWest ? p.Y : p.Y + i, p.Z); + + new InternalItem(itemID, loc, Caster, Caster.Map, duration, i); + } + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12, false); + } + + [DispellableField] + public class InternalItem : Item + { + private Mobile m_Caster; + private DateTime m_End; + private Timer m_Timer; + + public InternalItem(int itemID, Point3D loc, Mobile caster, Map map, TimeSpan duration, int val) : base(itemID) + { + var canFit = SpellHelper.AdjustField(ref loc, map, 12, false); + + Visible = false; + Movable = false; + Light = LightType.Circle300; + + MoveToWorld(loc, map); + + m_Caster = caster; + + m_End = DateTime.UtcNow + duration; + + m_Timer = new InternalTimer(this, TimeSpan.FromSeconds(Math.Abs(val) * 0.2), caster.InLOS(this), canFit); + m_Timer.Start(); + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override bool BlocksFit => true; + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Timer?.Stop(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.Write(m_Caster); + writer.WriteDeltaTime(m_End); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_Caster = reader.ReadMobile(); + + goto case 0; + } + case 0: + { + m_End = reader.ReadDeltaTime(); + + m_Timer = new InternalTimer(this, TimeSpan.Zero, true, true); + m_Timer.Start(); + + break; + } + } + } + + public void ApplyPoisonTo(Mobile m) + { + if (m_Caster == null) + return; + + Poison p; + + if (Core.AOS) + { + var total = (m_Caster.Skills.Magery.Fixed + m_Caster.Skills.Poisoning.Fixed) / 2; + + if (total >= 1000) + p = Poison.Deadly; + else if (total > 850) + p = Poison.Greater; + else if (total > 650) + p = Poison.Regular; + else + p = Poison.Lesser; + } + else + { + p = Poison.Regular; + } + + if (m.ApplyPoison(m_Caster, p) == ApplyPoisonResult.Poisoned) + if (SpellHelper.CanRevealCaster(m)) + m_Caster.RevealingAction(); + + (m as BaseCreature)?.OnHarmfulSpell(m_Caster); + } + + public override bool OnMoveOver(Mobile m) + { + if (Visible && m_Caster != null && (!Core.AOS || m != m_Caster) && + SpellHelper.ValidIndirectTarget(m_Caster, m) && m_Caster.CanBeHarmful(m, false)) + { + m_Caster.DoHarmful(m); + + ApplyPoisonTo(m); + m.PlaySound(0x474); + } + + return true; + } + + private class InternalTimer : Timer + { + private static readonly Queue m_Queue = new Queue(); + private readonly bool m_CanFit; + private readonly bool m_InLOS; + private readonly InternalItem m_Item; + + public InternalTimer(InternalItem item, TimeSpan delay, bool inLOS, bool canFit) : base( + delay, + TimeSpan.FromSeconds(1.5) + ) + { + m_Item = item; + m_InLOS = inLOS; + m_CanFit = canFit; + + Priority = TimerPriority.FiftyMS; + } + + protected override void OnTick() + { + if (m_Item.Deleted) + return; + + if (!m_Item.Visible) + { + if (m_InLOS && m_CanFit) + m_Item.Visible = true; + else + m_Item.Delete(); + + if (!m_Item.Deleted) + { + m_Item.ProcessDelta(); + Effects.SendLocationParticles( + EffectItem.Create(m_Item.Location, m_Item.Map, EffectItem.DefaultDuration), + 0x376A, + 9, + 10, + 5040 + ); + } + } + else if (DateTime.UtcNow > m_Item.m_End) + { + m_Item.Delete(); + Stop(); + } + else + { + var map = m_Item.Map; + var caster = m_Item.m_Caster; + + if (map != null && caster != null) + { + var eastToWest = m_Item.ItemID == 0x3915; + var eable = map.GetMobilesInBounds( + new Rectangle2D( + m_Item.X - (eastToWest ? 0 : 1), + m_Item.Y - (eastToWest ? 1 : 0), + eastToWest ? 1 : 2, + eastToWest ? 2 : 1 + ) + ); + + foreach (var m in eable) + if (m.Z + 16 > m_Item.Z && m_Item.Z + 12 > m.Z && (!Core.AOS || m != caster) && + SpellHelper.ValidIndirectTarget(caster, m) && caster.CanBeHarmful(m, false)) + m_Queue.Enqueue(m); + + eable.Free(); + + while (m_Queue.Count > 0) + { + var m = m_Queue.Dequeue(); + + caster.DoHarmful(m); + + m_Item.ApplyPoisonTo(m); + m.PlaySound(0x474); + } + } + } + } } } - } - - public void ApplyPoisonTo(Mobile m) - { - if (m_Caster == null) - return; - - Poison p; - - if (Core.AOS) - { - int total = (m_Caster.Skills.Magery.Fixed + m_Caster.Skills.Poisoning.Fixed) / 2; - - if (total >= 1000) - p = Poison.Deadly; - else if (total > 850) - p = Poison.Greater; - else if (total > 650) - p = Poison.Regular; - else - p = Poison.Lesser; - } - else - { - p = Poison.Regular; - } - - if (m.ApplyPoison(m_Caster, p) == ApplyPoisonResult.Poisoned) - if (SpellHelper.CanRevealCaster(m)) - m_Caster.RevealingAction(); - - (m as BaseCreature)?.OnHarmfulSpell(m_Caster); - } - - public override bool OnMoveOver(Mobile m) - { - if (Visible && m_Caster != null && (!Core.AOS || m != m_Caster) && - SpellHelper.ValidIndirectTarget(m_Caster, m) && m_Caster.CanBeHarmful(m, false)) - { - m_Caster.DoHarmful(m); - - ApplyPoisonTo(m); - m.PlaySound(0x474); - } - - return true; - } - - private class InternalTimer : Timer - { - private static readonly Queue m_Queue = new Queue(); - private readonly bool m_InLOS; - private readonly bool m_CanFit; - private readonly InternalItem m_Item; - - public InternalTimer(InternalItem item, TimeSpan delay, bool inLOS, bool canFit) : base(delay, - TimeSpan.FromSeconds(1.5)) - { - m_Item = item; - m_InLOS = inLOS; - m_CanFit = canFit; - - Priority = TimerPriority.FiftyMS; - } - - protected override void OnTick() - { - if (m_Item.Deleted) - return; - - if (!m_Item.Visible) - { - if (m_InLOS && m_CanFit) - m_Item.Visible = true; - else - m_Item.Delete(); - - if (!m_Item.Deleted) - { - m_Item.ProcessDelta(); - Effects.SendLocationParticles( - EffectItem.Create(m_Item.Location, m_Item.Map, EffectItem.DefaultDuration), 0x376A, 9, 10, - 5040); - } - } - else if (DateTime.UtcNow > m_Item.m_End) - { - m_Item.Delete(); - Stop(); - } - else - { - Map map = m_Item.Map; - Mobile caster = m_Item.m_Caster; - - if (map != null && caster != null) - { - bool eastToWest = m_Item.ItemID == 0x3915; - IPooledEnumerable eable = map.GetMobilesInBounds( - new Rectangle2D(m_Item.X - (eastToWest ? 0 : 1), m_Item.Y - (eastToWest ? 1 : 0), - eastToWest ? 1 : 2, eastToWest ? 2 : 1)); - - foreach (Mobile m in eable) - if (m.Z + 16 > m_Item.Z && m_Item.Z + 12 > m.Z && (!Core.AOS || m != caster) && - SpellHelper.ValidIndirectTarget(caster, m) && caster.CanBeHarmful(m, false)) - m_Queue.Enqueue(m); - - eable.Free(); - - while (m_Queue.Count > 0) - { - Mobile m = m_Queue.Dequeue(); - - caster.DoHarmful(m); - - m_Item.ApplyPoisonTo(m); - m.PlaySound(0x474); - } - } - } - } - } } - } } diff --git a/Projects/UOContent/Spells/Fifth/SummonCreature.cs b/Projects/UOContent/Spells/Fifth/SummonCreature.cs index dded925bf..6ee542462 100644 --- a/Projects/UOContent/Spells/Fifth/SummonCreature.cs +++ b/Projects/UOContent/Spells/Fifth/SummonCreature.cs @@ -4,92 +4,94 @@ using Server.Utilities; namespace Server.Spells.Fifth { - public class SummonCreatureSpell : MagerySpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Summon Creature", "Kal Xen", - 16, - false, - Reagent.Bloodmoss, - Reagent.MandrakeRoot, - Reagent.SpidersSilk); - - // NOTE: Creature list based on 1hr of summon/release on OSI. - - private static readonly Type[] m_Types = + public class SummonCreatureSpell : MagerySpell { - typeof(PolarBear), - typeof(GrizzlyBear), - typeof(BlackBear), - typeof(Horse), - typeof(Walrus), - typeof(Chicken), - typeof(Scorpion), - typeof(GiantSerpent), - typeof(Llama), - typeof(Alligator), - typeof(GreyWolf), - typeof(Slime), - typeof(Eagle), - typeof(Gorilla), - typeof(SnowLeopard), - typeof(Pig), - typeof(Hind), - typeof(Rabbit) - }; + private static readonly SpellInfo m_Info = new SpellInfo( + "Summon Creature", + "Kal Xen", + 16, + false, + Reagent.Bloodmoss, + Reagent.MandrakeRoot, + Reagent.SpidersSilk + ); - public SummonCreatureSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) - { - } + // NOTE: Creature list based on 1hr of summon/release on OSI. - public override SpellCircle Circle => SpellCircle.Fifth; - - public override bool CheckCast() - { - if (!base.CheckCast()) - return false; - - if (Caster.Followers + 2 > Caster.FollowersMax) - { - Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. - return false; - } - - return true; - } - - public override void OnCast() - { - if (CheckSequence()) - try + private static readonly Type[] m_Types = { - BaseCreature creature = (BaseCreature)ActivatorUtil.CreateInstance(m_Types.RandomElement()); + typeof(PolarBear), + typeof(GrizzlyBear), + typeof(BlackBear), + typeof(Horse), + typeof(Walrus), + typeof(Chicken), + typeof(Scorpion), + typeof(GiantSerpent), + typeof(Llama), + typeof(Alligator), + typeof(GreyWolf), + typeof(Slime), + typeof(Eagle), + typeof(Gorilla), + typeof(SnowLeopard), + typeof(Pig), + typeof(Hind), + typeof(Rabbit) + }; - // creature.ControlSlots = 2; - - TimeSpan duration; - - if (Core.AOS) - duration = TimeSpan.FromSeconds(2 * Caster.Skills.Magery.Fixed / 5.0); - else - duration = TimeSpan.FromSeconds(4.0 * Caster.Skills.Magery.Value); - - SpellHelper.Summon(creature, Caster, 0x215, duration, false, false); - } - catch + public SummonCreatureSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - // ignored } - FinishSequence(); - } + public override SpellCircle Circle => SpellCircle.Fifth; - public override TimeSpan GetCastDelay() - { - if (Core.AOS) - return TimeSpan.FromTicks(base.GetCastDelay().Ticks * 5); + public override bool CheckCast() + { + if (!base.CheckCast()) + return false; - return base.GetCastDelay() + TimeSpan.FromSeconds(6.0); + if (Caster.Followers + 2 > Caster.FollowersMax) + { + Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. + return false; + } + + return true; + } + + public override void OnCast() + { + if (CheckSequence()) + try + { + var creature = (BaseCreature)ActivatorUtil.CreateInstance(m_Types.RandomElement()); + + // creature.ControlSlots = 2; + + TimeSpan duration; + + if (Core.AOS) + duration = TimeSpan.FromSeconds(2 * Caster.Skills.Magery.Fixed / 5.0); + else + duration = TimeSpan.FromSeconds(4.0 * Caster.Skills.Magery.Value); + + SpellHelper.Summon(creature, Caster, 0x215, duration, false, false); + } + catch + { + // ignored + } + + FinishSequence(); + } + + public override TimeSpan GetCastDelay() + { + if (Core.AOS) + return TimeSpan.FromTicks(base.GetCastDelay().Ticks * 5); + + return base.GetCastDelay() + TimeSpan.FromSeconds(6.0); + } } - } } diff --git a/Projects/UOContent/Spells/First/Clumsy.cs b/Projects/UOContent/Spells/First/Clumsy.cs index a8af48129..a8ebc2fdf 100644 --- a/Projects/UOContent/Spells/First/Clumsy.cs +++ b/Projects/UOContent/Spells/First/Clumsy.cs @@ -1,61 +1,62 @@ -using System; using Server.Targeting; namespace Server.Spells.First { - public class ClumsySpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Clumsy", "Uus Jux", - 212, - 9031, - Reagent.Bloodmoss, - Reagent.Nightshade); - - public ClumsySpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class ClumsySpell : MagerySpell, ISpellTargetingMobile { + private static readonly SpellInfo m_Info = new SpellInfo( + "Clumsy", + "Uus Jux", + 212, + 9031, + Reagent.Bloodmoss, + Reagent.Nightshade + ); + + public ClumsySpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.First; + + public void Target(Mobile m) + { + if (m == null) + return; + + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckHSequence(m)) + { + SpellHelper.Turn(Caster, m); + + SpellHelper.CheckReflect((int)Circle, Caster, ref m); + + SpellHelper.AddStatCurse(Caster, m, StatType.Dex); + + m.Spell?.OnCasterHurt(); + + m.Paralyzed = false; + + m.FixedParticles(0x3779, 10, 15, 5002, EffectLayer.Head); + m.PlaySound(0x1DF); + + var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100); + var length = SpellHelper.GetDuration(Caster, m); + + BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Clumsy, 1075831, length, m, percentage.ToString())); + + HarmfulSpell(m); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } } - - public override SpellCircle Circle => SpellCircle.First; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - { - Caster.SendLocalizedMessage(500237); // Target can not be seen. - } - else if (CheckHSequence(m)) - { - SpellHelper.Turn(Caster, m); - - SpellHelper.CheckReflect((int)Circle, Caster, ref m); - - SpellHelper.AddStatCurse(Caster, m, StatType.Dex); - - m.Spell?.OnCasterHurt(); - - m.Paralyzed = false; - - m.FixedParticles(0x3779, 10, 15, 5002, EffectLayer.Head); - m.PlaySound(0x1DF); - - int percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100); - TimeSpan length = SpellHelper.GetDuration(Caster, m); - - BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Clumsy, 1075831, length, m, percentage.ToString())); - - HarmfulSpell(m); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/First/CreateFood.cs b/Projects/UOContent/Spells/First/CreateFood.cs index 04cc697f8..f41b54b13 100644 --- a/Projects/UOContent/Spells/First/CreateFood.cs +++ b/Projects/UOContent/Spells/First/CreateFood.cs @@ -4,85 +4,87 @@ using Server.Utilities; namespace Server.Spells.First { - public class CreateFoodSpell : MagerySpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Create Food", "In Mani Ylem", - 224, - 9011, - Reagent.Garlic, - Reagent.Ginseng, - Reagent.MandrakeRoot); - - private static readonly FoodInfo[] m_Food = + public class CreateFoodSpell : MagerySpell { - new FoodInfo(typeof(Grapes), "a grape bunch"), - new FoodInfo(typeof(Ham), "a ham"), - new FoodInfo(typeof(CheeseWedge), "a wedge of cheese"), - new FoodInfo(typeof(Muffins), "muffins"), - new FoodInfo(typeof(FishSteak), "a fish steak"), - new FoodInfo(typeof(Ribs), "cut of ribs"), - new FoodInfo(typeof(CookedBird), "a cooked bird"), - new FoodInfo(typeof(Sausage), "sausage"), - new FoodInfo(typeof(Apple), "an apple"), - new FoodInfo(typeof(Peach), "a peach") - }; + private static readonly SpellInfo m_Info = new SpellInfo( + "Create Food", + "In Mani Ylem", + 224, + 9011, + Reagent.Garlic, + Reagent.Ginseng, + Reagent.MandrakeRoot + ); - public CreateFoodSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) - { - } - - public override SpellCircle Circle => SpellCircle.First; - - public override void OnCast() - { - if (CheckSequence()) - { - FoodInfo foodInfo = m_Food.RandomElement(); - Item food = foodInfo.Create(); - - if (food != null) + private static readonly FoodInfo[] m_Food = { - Caster.AddToBackpack(food); + new FoodInfo(typeof(Grapes), "a grape bunch"), + new FoodInfo(typeof(Ham), "a ham"), + new FoodInfo(typeof(CheeseWedge), "a wedge of cheese"), + new FoodInfo(typeof(Muffins), "muffins"), + new FoodInfo(typeof(FishSteak), "a fish steak"), + new FoodInfo(typeof(Ribs), "cut of ribs"), + new FoodInfo(typeof(CookedBird), "a cooked bird"), + new FoodInfo(typeof(Sausage), "sausage"), + new FoodInfo(typeof(Apple), "an apple"), + new FoodInfo(typeof(Peach), "a peach") + }; - // You magically create food in your backpack: - Caster.SendLocalizedMessage(1042695, true, $" {foodInfo.Name}"); - - Caster.FixedParticles(0, 10, 5, 2003, EffectLayer.RightHand); - Caster.PlaySound(0x1E2); + public CreateFoodSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { } - } - FinishSequence(); + public override SpellCircle Circle => SpellCircle.First; + + public override void OnCast() + { + if (CheckSequence()) + { + var foodInfo = m_Food.RandomElement(); + var food = foodInfo.Create(); + + if (food != null) + { + Caster.AddToBackpack(food); + + // You magically create food in your backpack: + Caster.SendLocalizedMessage(1042695, true, $" {foodInfo.Name}"); + + Caster.FixedParticles(0, 10, 5, 2003, EffectLayer.RightHand); + Caster.PlaySound(0x1E2); + } + } + + FinishSequence(); + } } - } - public class FoodInfo - { - public FoodInfo(Type type, string name) + public class FoodInfo { - Type = type; - Name = name; + public FoodInfo(Type type, string name) + { + Type = type; + Name = name; + } + + public Type Type { get; set; } + + public string Name { get; set; } + + public Item Create() + { + Item item; + + try + { + item = (Item)ActivatorUtil.CreateInstance(Type); + } + catch + { + item = null; + } + + return item; + } } - - public Type Type { get; set; } - - public string Name { get; set; } - - public Item Create() - { - Item item; - - try - { - item = (Item)ActivatorUtil.CreateInstance(Type); - } - catch - { - item = null; - } - - return item; - } - } } diff --git a/Projects/UOContent/Spells/First/Feeblemind.cs b/Projects/UOContent/Spells/First/Feeblemind.cs index c1e63edc4..21e60a1c6 100644 --- a/Projects/UOContent/Spells/First/Feeblemind.cs +++ b/Projects/UOContent/Spells/First/Feeblemind.cs @@ -1,59 +1,62 @@ -using System; using Server.Targeting; namespace Server.Spells.First { - public class FeeblemindSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Feeblemind", "Rel Wis", - 212, - 9031, - Reagent.Ginseng, - Reagent.Nightshade); - - public FeeblemindSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class FeeblemindSpell : MagerySpell, ISpellTargetingMobile { + private static readonly SpellInfo m_Info = new SpellInfo( + "Feeblemind", + "Rel Wis", + 212, + 9031, + Reagent.Ginseng, + Reagent.Nightshade + ); + + public FeeblemindSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.First; + + public void Target(Mobile m) + { + if (m == null) + return; + + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckHSequence(m)) + { + SpellHelper.Turn(Caster, m); + + SpellHelper.CheckReflect((int)Circle, Caster, ref m); + + SpellHelper.AddStatCurse(Caster, m, StatType.Int); + + m.Spell?.OnCasterHurt(); + + m.Paralyzed = false; + + m.FixedParticles(0x3779, 10, 15, 5004, EffectLayer.Head); + m.PlaySound(0x1E4); + + var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100); + var length = SpellHelper.GetDuration(Caster, m); + + BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.FeebleMind, 1075833, length, m, percentage.ToString())); + + HarmfulSpell(m); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } } - - public override SpellCircle Circle => SpellCircle.First; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (CheckHSequence(m)) - { - SpellHelper.Turn(Caster, m); - - SpellHelper.CheckReflect((int)Circle, Caster, ref m); - - SpellHelper.AddStatCurse(Caster, m, StatType.Int); - - m.Spell?.OnCasterHurt(); - - m.Paralyzed = false; - - m.FixedParticles(0x3779, 10, 15, 5004, EffectLayer.Head); - m.PlaySound(0x1E4); - - int percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100); - TimeSpan length = SpellHelper.GetDuration(Caster, m); - - BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.FeebleMind, 1075833, length, m, percentage.ToString())); - - HarmfulSpell(m); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/First/Heal.cs b/Projects/UOContent/Spells/First/Heal.cs index 8c9d474e2..fb89a1076 100644 --- a/Projects/UOContent/Spells/First/Heal.cs +++ b/Projects/UOContent/Spells/First/Heal.cs @@ -6,91 +6,93 @@ using Server.Targeting; namespace Server.Spells.First { - public class HealSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Heal", "In Mani", - 224, - 9061, - Reagent.Garlic, - Reagent.Ginseng, - Reagent.SpidersSilk); - - public HealSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class HealSpell : MagerySpell, ISpellTargetingMobile { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Heal", + "In Mani", + 224, + 9061, + Reagent.Garlic, + Reagent.Ginseng, + Reagent.SpidersSilk + ); - public override SpellCircle Circle => SpellCircle.First; - - public override bool CheckCast() - { - if (DuelContext.CheckSuddenDeath(Caster)) - { - Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); - return false; - } - - return base.CheckCast(); - } - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - { - Caster.SendLocalizedMessage(500237); // Target can not be seen. - } - else if (m.IsDeadBondedPet) - { - Caster.SendLocalizedMessage(1060177); // You cannot heal a creature that is already dead! - } - else if (m is BaseCreature creature && creature.IsAnimatedDead) - { - Caster.SendLocalizedMessage(1061654); // You cannot heal that which is not alive. - } - else if (m is Golem) - { - Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500951); // You cannot heal that. - } - else if (m.Poisoned || MortalStrike.IsWounded(m)) - { - Caster.LocalOverheadMessage(MessageType.Regular, 0x22, Caster == m ? 1005000 : 1010398); - } - else if (CheckBSequence(m)) - { - SpellHelper.Turn(Caster, m); - - int toHeal; - - if (Core.AOS) + public HealSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - toHeal = Caster.Skills.Magery.Fixed / 120; - toHeal += Utility.RandomMinMax(1, 4); - - if (Core.SE && Caster != m) - toHeal = (int)(toHeal * 1.5); - } - else - { - toHeal = (int)(Caster.Skills.Magery.Value * 0.1); - toHeal += Utility.Random(1, 5); } - // m.Heal( toHeal, Caster ); - SpellHelper.Heal(toHeal, m, Caster); + public override SpellCircle Circle => SpellCircle.First; - m.FixedParticles(0x376A, 9, 32, 5005, EffectLayer.Waist); - m.PlaySound(0x1F2); - } + public void Target(Mobile m) + { + if (m == null) + return; - FinishSequence(); + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (m.IsDeadBondedPet) + { + Caster.SendLocalizedMessage(1060177); // You cannot heal a creature that is already dead! + } + else if (m is BaseCreature creature && creature.IsAnimatedDead) + { + Caster.SendLocalizedMessage(1061654); // You cannot heal that which is not alive. + } + else if (m is Golem) + { + Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500951); // You cannot heal that. + } + else if (m.Poisoned || MortalStrike.IsWounded(m)) + { + Caster.LocalOverheadMessage(MessageType.Regular, 0x22, Caster == m ? 1005000 : 1010398); + } + else if (CheckBSequence(m)) + { + SpellHelper.Turn(Caster, m); + + int toHeal; + + if (Core.AOS) + { + toHeal = Caster.Skills.Magery.Fixed / 120; + toHeal += Utility.RandomMinMax(1, 4); + + if (Core.SE && Caster != m) + toHeal = (int)(toHeal * 1.5); + } + else + { + toHeal = (int)(Caster.Skills.Magery.Value * 0.1); + toHeal += Utility.Random(1, 5); + } + + // m.Heal( toHeal, Caster ); + SpellHelper.Heal(toHeal, m, Caster); + + m.FixedParticles(0x376A, 9, 32, 5005, EffectLayer.Waist); + m.PlaySound(0x1F2); + } + + FinishSequence(); + } + + public override bool CheckCast() + { + if (DuelContext.CheckSuddenDeath(Caster)) + { + Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); + return false; + } + + return base.CheckCast(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, Core.ML ? 10 : 12); + } } - } } diff --git a/Projects/UOContent/Spells/First/MagicArrow.cs b/Projects/UOContent/Spells/First/MagicArrow.cs index 853a3fe1f..098796386 100644 --- a/Projects/UOContent/Spells/First/MagicArrow.cs +++ b/Projects/UOContent/Spells/First/MagicArrow.cs @@ -2,71 +2,75 @@ using Server.Targeting; namespace Server.Spells.First { - public class MagicArrowSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Magic Arrow", "In Por Ylem", - 212, - 9041, - Reagent.SulfurousAsh); - - public MagicArrowSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class MagicArrowSpell : MagerySpell, ISpellTargetingMobile { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Magic Arrow", + "In Por Ylem", + 212, + 9041, + Reagent.SulfurousAsh + ); - public override SpellCircle Circle => SpellCircle.First; - - public override bool DelayedDamageStacking => !Core.AOS; - - public override bool DelayedDamage => true; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (CheckHSequence(m)) - { - Mobile source = Caster; - - SpellHelper.Turn(source, m); - - SpellHelper.CheckReflect((int)Circle, ref source, ref m); - - double damage; - - if (Core.AOS) + public MagicArrowSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - damage = GetNewAosDamage(10, 1, 4, m); - } - else - { - damage = Utility.Random(4, 4); - - if (CheckResisted(m)) - { - damage *= 0.75; - - m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. - } - - damage *= GetDamageScalar(m); } - source.MovingParticles(m, 0x36E4, 5, 0, false, false, 3006, 0, 0); - source.PlaySound(0x1E5); + public override SpellCircle Circle => SpellCircle.First; - SpellHelper.Damage(this, m, damage, 0, 100, 0, 0, 0); - } + public override bool DelayedDamageStacking => !Core.AOS; - FinishSequence(); + public override bool DelayedDamage => true; + + public void Target(Mobile m) + { + if (m == null) + return; + + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckHSequence(m)) + { + var source = Caster; + + SpellHelper.Turn(source, m); + + SpellHelper.CheckReflect((int)Circle, ref source, ref m); + + double damage; + + if (Core.AOS) + { + damage = GetNewAosDamage(10, 1, 4, m); + } + else + { + damage = Utility.Random(4, 4); + + if (CheckResisted(m)) + { + damage *= 0.75; + + m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + } + + damage *= GetDamageScalar(m); + } + + source.MovingParticles(m, 0x36E4, 5, 0, false, false, 3006, 0, 0); + source.PlaySound(0x1E5); + + SpellHelper.Damage(this, m, damage, 0, 100, 0, 0, 0); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } } - } } diff --git a/Projects/UOContent/Spells/First/NightSight.cs b/Projects/UOContent/Spells/First/NightSight.cs index ebe62cbdc..55046f36a 100644 --- a/Projects/UOContent/Spells/First/NightSight.cs +++ b/Projects/UOContent/Spells/First/NightSight.cs @@ -3,68 +3,72 @@ using Server.Targeting; namespace Server.Spells.First { - public class NightSightSpell : MagerySpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Night Sight", "In Lor", - 236, - 9031, - Reagent.SulfurousAsh, - Reagent.SpidersSilk); - - public NightSightSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class NightSightSpell : MagerySpell { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Night Sight", + "In Lor", + 236, + 9031, + Reagent.SulfurousAsh, + Reagent.SpidersSilk + ); - public override SpellCircle Circle => SpellCircle.First; - - public override void OnCast() - { - Caster.Target = new NightSightTarget(this); - } - - private class NightSightTarget : Target - { - private readonly Spell m_Spell; - - public NightSightTarget(Spell spell) : base(12, false, TargetFlags.Beneficial) => m_Spell = spell; - - protected override void OnTarget(Mobile from, object targeted) - { - if (targeted is Mobile targ && m_Spell.CheckBSequence(targ)) + public NightSightSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - SpellHelper.Turn(m_Spell.Caster, targ); - - if (targ.BeginAction()) - { - new LightCycle.NightSightTimer(targ).Start(); - int level = - (int)(LightCycle.DungeonLevel * - ((Core.AOS - ? targ.Skills.Magery.Value - : from.Skills.Magery.Value) / 100)); - - targ.LightLevel = Math.Max(level, 0); - - targ.FixedParticles(0x376A, 9, 32, 5007, EffectLayer.Waist); - targ.PlaySound(0x1E3); - - BuffInfo.AddBuff(targ, - new BuffInfo(BuffIcon.NightSight, 1075643)); // Night Sight/You ignore lighting effects - } - else - { - from.SendMessage("{0} already have nightsight.", from == targ ? "You" : "They"); - } } - m_Spell.FinishSequence(); - } + public override SpellCircle Circle => SpellCircle.First; - protected override void OnTargetFinish(Mobile from) - { - m_Spell.FinishSequence(); - } + public override void OnCast() + { + Caster.Target = new NightSightTarget(this); + } + + private class NightSightTarget : Target + { + private readonly Spell m_Spell; + + public NightSightTarget(Spell spell) : base(12, false, TargetFlags.Beneficial) => m_Spell = spell; + + protected override void OnTarget(Mobile from, object targeted) + { + if (targeted is Mobile targ && m_Spell.CheckBSequence(targ)) + { + SpellHelper.Turn(m_Spell.Caster, targ); + + if (targ.BeginAction()) + { + new LightCycle.NightSightTimer(targ).Start(); + var level = + (int)(LightCycle.DungeonLevel * + ((Core.AOS + ? targ.Skills.Magery.Value + : from.Skills.Magery.Value) / 100)); + + targ.LightLevel = Math.Max(level, 0); + + targ.FixedParticles(0x376A, 9, 32, 5007, EffectLayer.Waist); + targ.PlaySound(0x1E3); + + BuffInfo.AddBuff( + targ, + new BuffInfo(BuffIcon.NightSight, 1075643) + ); // Night Sight/You ignore lighting effects + } + else + { + from.SendMessage("{0} already have nightsight.", from == targ ? "You" : "They"); + } + } + + m_Spell.FinishSequence(); + } + + protected override void OnTargetFinish(Mobile from) + { + m_Spell.FinishSequence(); + } + } } - } } diff --git a/Projects/UOContent/Spells/First/ReactiveArmor.cs b/Projects/UOContent/Spells/First/ReactiveArmor.cs index 21684a66e..081ed6c83 100644 --- a/Projects/UOContent/Spells/First/ReactiveArmor.cs +++ b/Projects/UOContent/Spells/First/ReactiveArmor.cs @@ -3,145 +3,151 @@ using System.Collections.Generic; namespace Server.Spells.First { - public class ReactiveArmorSpell : MagerySpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Reactive Armor", "Flam Sanct", - 236, - 9011, - Reagent.Garlic, - Reagent.SpidersSilk, - Reagent.SulfurousAsh); - - private static readonly Dictionary m_Table = new Dictionary(); - - public ReactiveArmorSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class ReactiveArmorSpell : MagerySpell { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Reactive Armor", + "Flam Sanct", + 236, + 9011, + Reagent.Garlic, + Reagent.SpidersSilk, + Reagent.SulfurousAsh + ); - public override SpellCircle Circle => SpellCircle.First; + private static readonly Dictionary m_Table = new Dictionary(); - public override bool CheckCast() - { - if (Core.AOS) - return true; - - if (Caster.MeleeDamageAbsorb > 0) - { - Caster.SendLocalizedMessage(1005559); // This spell is already in effect. - return false; - } - - if (!Caster.CanBeginAction()) - { - Caster.SendLocalizedMessage(1005385); // The spell will not adhere to you at this time. - return false; - } - - return true; - } - - public override void OnCast() - { - if (Core.AOS) - { - /* The reactive armor spell increases the caster's physical resistance, while lowering the caster's elemental resistances. - * 15 + (Inscription/20) Physcial bonus - * -5 Elemental - * The reactive armor spell has an indefinite duration, becoming active when cast, and deactivated when re-cast. - * Reactive Armor, Protection, and Magic Reflection will stay on�even after logging out, even after dying�until you �turn them off� by casting them again. - * (+20 physical -5 elemental at 100 Inscription) - */ - - if (CheckSequence()) + public ReactiveArmorSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - Mobile targ = Caster; + } - if (m_Table.TryGetValue(targ, out ResistanceMod[] mods)) - { - targ.PlaySound(0x1ED); - targ.FixedParticles(0x376A, 9, 32, 5008, EffectLayer.Waist); + public override SpellCircle Circle => SpellCircle.First; - m_Table.Remove(targ); + public override bool CheckCast() + { + if (Core.AOS) + return true; - for (int i = 0; i < mods.Length; ++i) - targ.RemoveResistanceMod(mods[i]); - - BuffInfo.RemoveBuff(Caster, BuffIcon.ReactiveArmor); - } - else - { - targ.PlaySound(0x1E9); - targ.FixedParticles(0x376A, 9, 32, 5008, EffectLayer.Waist); - - mods = new[] + if (Caster.MeleeDamageAbsorb > 0) { - new ResistanceMod(ResistanceType.Physical, - 15 + (int)(targ.Skills.Inscribe.Value / 20)), - new ResistanceMod(ResistanceType.Fire, -5), - new ResistanceMod(ResistanceType.Cold, -5), - new ResistanceMod(ResistanceType.Poison, -5), - new ResistanceMod(ResistanceType.Energy, -5) - }; + Caster.SendLocalizedMessage(1005559); // This spell is already in effect. + return false; + } - m_Table[targ] = mods; + if (!Caster.CanBeginAction()) + { + Caster.SendLocalizedMessage(1005385); // The spell will not adhere to you at this time. + return false; + } - for (int i = 0; i < mods.Length; ++i) - targ.AddResistanceMod(mods[i]); - - int physresist = 15 + (int)(targ.Skills.Inscribe.Value / 20); - string args = $"{physresist}\t{5}\t{5}\t{5}\t{5}"; - - BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.ReactiveArmor, 1075812, 1075813, args)); - } + return true; } - FinishSequence(); - } - else - { - if (Caster.MeleeDamageAbsorb > 0) + public override void OnCast() { - Caster.SendLocalizedMessage(1005559); // This spell is already in effect. + if (Core.AOS) + { + /* The reactive armor spell increases the caster's physical resistance, while lowering the caster's elemental resistances. + * 15 + (Inscription/20) Physcial bonus + * -5 Elemental + * The reactive armor spell has an indefinite duration, becoming active when cast, and deactivated when re-cast. + * Reactive Armor, Protection, and Magic Reflection will stay on�even after logging out, even after dying�until you �turn them off� by casting them again. + * (+20 physical -5 elemental at 100 Inscription) + */ + + if (CheckSequence()) + { + var targ = Caster; + + if (m_Table.TryGetValue(targ, out var mods)) + { + targ.PlaySound(0x1ED); + targ.FixedParticles(0x376A, 9, 32, 5008, EffectLayer.Waist); + + m_Table.Remove(targ); + + for (var i = 0; i < mods.Length; ++i) + targ.RemoveResistanceMod(mods[i]); + + BuffInfo.RemoveBuff(Caster, BuffIcon.ReactiveArmor); + } + else + { + targ.PlaySound(0x1E9); + targ.FixedParticles(0x376A, 9, 32, 5008, EffectLayer.Waist); + + mods = new[] + { + new ResistanceMod( + ResistanceType.Physical, + 15 + (int)(targ.Skills.Inscribe.Value / 20) + ), + new ResistanceMod(ResistanceType.Fire, -5), + new ResistanceMod(ResistanceType.Cold, -5), + new ResistanceMod(ResistanceType.Poison, -5), + new ResistanceMod(ResistanceType.Energy, -5) + }; + + m_Table[targ] = mods; + + for (var i = 0; i < mods.Length; ++i) + targ.AddResistanceMod(mods[i]); + + var physresist = 15 + (int)(targ.Skills.Inscribe.Value / 20); + var args = $"{physresist}\t{5}\t{5}\t{5}\t{5}"; + + BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.ReactiveArmor, 1075812, 1075813, args)); + } + } + + FinishSequence(); + } + else + { + if (Caster.MeleeDamageAbsorb > 0) + { + Caster.SendLocalizedMessage(1005559); // This spell is already in effect. + } + else if (!Caster.CanBeginAction()) + { + Caster.SendLocalizedMessage(1005385); // The spell will not adhere to you at this time. + } + else if (CheckSequence()) + { + if (Caster.BeginAction()) + { + var value = Math.Clamp( + (int)(Caster.Skills.Magery.Value + Caster.Skills.Meditation.Value + + Caster.Skills.Inscribe.Value) / 3, + 1, + 75 + ); + + Caster.MeleeDamageAbsorb = value; + + Caster.FixedParticles(0x376A, 9, 32, 5008, EffectLayer.Waist); + Caster.PlaySound(0x1F2); + } + else + { + Caster.SendLocalizedMessage(1005385); // The spell will not adhere to you at this time. + } + } + + FinishSequence(); + } } - else if (!Caster.CanBeginAction()) + + public static void EndArmor(Mobile m) { - Caster.SendLocalizedMessage(1005385); // The spell will not adhere to you at this time. + if (!m_Table.TryGetValue(m, out var mods)) + return; + + for (var i = 0; i < mods?.Length; ++i) + m.RemoveResistanceMod(mods[i]); + + m_Table.Remove(m); + BuffInfo.RemoveBuff(m, BuffIcon.ReactiveArmor); } - else if (CheckSequence()) - { - if (Caster.BeginAction()) - { - int value = Math.Clamp( - (int)(Caster.Skills.Magery.Value + Caster.Skills.Meditation.Value + - Caster.Skills.Inscribe.Value) / 3, 1, 75 - ); - - Caster.MeleeDamageAbsorb = value; - - Caster.FixedParticles(0x376A, 9, 32, 5008, EffectLayer.Waist); - Caster.PlaySound(0x1F2); - } - else - { - Caster.SendLocalizedMessage(1005385); // The spell will not adhere to you at this time. - } - } - - FinishSequence(); - } } - - public static void EndArmor(Mobile m) - { - if (!m_Table.TryGetValue(m, out ResistanceMod[] mods)) - return; - - for (int i = 0; i < mods?.Length; ++i) - m.RemoveResistanceMod(mods[i]); - - m_Table.Remove(m); - BuffInfo.RemoveBuff(m, BuffIcon.ReactiveArmor); - } - } } diff --git a/Projects/UOContent/Spells/First/Weaken.cs b/Projects/UOContent/Spells/First/Weaken.cs index 2edc13160..a298b9211 100644 --- a/Projects/UOContent/Spells/First/Weaken.cs +++ b/Projects/UOContent/Spells/First/Weaken.cs @@ -1,59 +1,62 @@ -using System; using Server.Targeting; namespace Server.Spells.First { - public class WeakenSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Weaken", "Des Mani", - 212, - 9031, - Reagent.Garlic, - Reagent.Nightshade); - - public WeakenSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class WeakenSpell : MagerySpell, ISpellTargetingMobile { + private static readonly SpellInfo m_Info = new SpellInfo( + "Weaken", + "Des Mani", + 212, + 9031, + Reagent.Garlic, + Reagent.Nightshade + ); + + public WeakenSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.First; + + public void Target(Mobile m) + { + if (m == null) + return; + + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckHSequence(m)) + { + SpellHelper.Turn(Caster, m); + + SpellHelper.CheckReflect((int)Circle, Caster, ref m); + + SpellHelper.AddStatCurse(Caster, m, StatType.Str); + + m.Spell?.OnCasterHurt(); + + m.Paralyzed = false; + + m.FixedParticles(0x3779, 10, 15, 5009, EffectLayer.Waist); + m.PlaySound(0x1E6); + + var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100); + var length = SpellHelper.GetDuration(Caster, m); + + BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Weaken, 1075837, length, m, percentage.ToString())); + + HarmfulSpell(m); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } } - - public override SpellCircle Circle => SpellCircle.First; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (CheckHSequence(m)) - { - SpellHelper.Turn(Caster, m); - - SpellHelper.CheckReflect((int)Circle, Caster, ref m); - - SpellHelper.AddStatCurse(Caster, m, StatType.Str); - - m.Spell?.OnCasterHurt(); - - m.Paralyzed = false; - - m.FixedParticles(0x3779, 10, 15, 5009, EffectLayer.Waist); - m.PlaySound(0x1E6); - - int percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100); - TimeSpan length = SpellHelper.GetDuration(Caster, m); - - BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Weaken, 1075837, length, m, percentage.ToString())); - - HarmfulSpell(m); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Fourth/ArchCure.cs b/Projects/UOContent/Spells/Fourth/ArchCure.cs index c8b6272ba..ac00f82e3 100644 --- a/Projects/UOContent/Spells/Fourth/ArchCure.cs +++ b/Projects/UOContent/Spells/Fourth/ArchCure.cs @@ -6,143 +6,145 @@ using Server.Targeting; namespace Server.Spells.Fourth { - public class ArchCureSpell : MagerySpell, ISpellTargetingPoint3D - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Arch Cure", "Vas An Nox", - 215, - 9061, - Reagent.Garlic, - Reagent.Ginseng, - Reagent.MandrakeRoot); - - public ArchCureSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class ArchCureSpell : MagerySpell, ISpellTargetingPoint3D { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Arch Cure", + "Vas An Nox", + 215, + 9061, + Reagent.Garlic, + Reagent.Ginseng, + Reagent.MandrakeRoot + ); - public override SpellCircle Circle => SpellCircle.Fourth; - - // Arch cure is now 1/4th of a second faster - public override TimeSpan CastDelayBase => base.CastDelayBase - TimeSpan.FromSeconds(0.25); - - public override void OnCast() - { - Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); - } - - public void Target(IPoint3D p) - { - if (!Caster.CanSee(p)) - { - Caster.SendLocalizedMessage(500237); // Target can not be seen. - } - else if (CheckSequence()) - { - SpellHelper.Turn(Caster, p); - - SpellHelper.GetSurfaceTop(ref p); - - List targets = new List(); - - Map map = Caster.Map; - Mobile directTarget = p as Mobile; - - if (map != null) + public ArchCureSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - bool feluccaRules = map.Rules == MapRules.FeluccaRules; - - // You can target any living mobile directly, beneficial checks apply - if (directTarget != null && Caster.CanBeBeneficial(directTarget, false)) - targets.Add(directTarget); - - IPooledEnumerable eable = map.GetMobilesInRange(new Point3D(p), 2); - targets.AddRange(eable.Where(m => m != directTarget).Where(m => AreaCanTarget(m, feluccaRules))); - - eable.Free(); } - Effects.PlaySound(p, Caster.Map, 0x299); + public override SpellCircle Circle => SpellCircle.Fourth; - if (targets.Count > 0) + // Arch cure is now 1/4th of a second faster + public override TimeSpan CastDelayBase => base.CastDelayBase - TimeSpan.FromSeconds(0.25); + + public void Target(IPoint3D p) { - int cured = 0; - - for (int i = 0; i < targets.Count; ++i) - { - Mobile m = targets[i]; - - Caster.DoBeneficial(m); - - Poison poison = m.Poison; - - if (poison != null) + if (!Caster.CanSee(p)) { - int chanceToCure = 10000 + (int)(Caster.Skills.Magery.Value * 75) - - (poison.Level + 1) * 1750; - chanceToCure /= 100; - chanceToCure -= 1; + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckSequence()) + { + SpellHelper.Turn(Caster, p); - if (chanceToCure > Utility.Random(100) && m.CurePoison(Caster)) - ++cured; + SpellHelper.GetSurfaceTop(ref p); + + var targets = new List(); + + var map = Caster.Map; + var directTarget = p as Mobile; + + if (map != null) + { + var feluccaRules = map.Rules == MapRules.FeluccaRules; + + // You can target any living mobile directly, beneficial checks apply + if (directTarget != null && Caster.CanBeBeneficial(directTarget, false)) + targets.Add(directTarget); + + var eable = map.GetMobilesInRange(new Point3D(p), 2); + targets.AddRange(eable.Where(m => m != directTarget).Where(m => AreaCanTarget(m, feluccaRules))); + + eable.Free(); + } + + Effects.PlaySound(p, Caster.Map, 0x299); + + if (targets.Count > 0) + { + var cured = 0; + + for (var i = 0; i < targets.Count; ++i) + { + var m = targets[i]; + + Caster.DoBeneficial(m); + + var poison = m.Poison; + + if (poison != null) + { + var chanceToCure = 10000 + (int)(Caster.Skills.Magery.Value * 75) - + (poison.Level + 1) * 1750; + chanceToCure /= 100; + chanceToCure -= 1; + + if (chanceToCure > Utility.Random(100) && m.CurePoison(Caster)) + ++cured; + } + + m.FixedParticles(0x373A, 10, 15, 5012, EffectLayer.Waist); + m.PlaySound(0x1E0); + } + + if (cured > 0) + Caster.SendLocalizedMessage(1010058); // You have cured the target of all poisons! + } } - m.FixedParticles(0x373A, 10, 15, 5012, EffectLayer.Waist); - m.PlaySound(0x1E0); - } - - if (cured > 0) - Caster.SendLocalizedMessage(1010058); // You have cured the target of all poisons! + FinishSequence(); } - } - FinishSequence(); + public override void OnCast() + { + Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); + } + + private bool AreaCanTarget(Mobile target, bool feluccaRules) + { + /* Arch cure area effect won't cure aggressors, victims, murderers, criminals or monsters. + * In Felucca, it will also not cure summons and pets. + * For red players it will only cure themselves and guild members. + */ + + if (!Caster.CanBeBeneficial(target, false)) + return false; + + if (Core.AOS && target != Caster) + { + if (IsAggressor(target) || IsAggressed(target)) + return false; + + if ((!IsInnocentTo(Caster, target) || !IsInnocentTo(target, Caster)) && !IsAllyTo(Caster, target)) + return false; + + if (feluccaRules && !(target is PlayerMobile)) + return false; + } + + return true; + } + + private bool IsAggressor(Mobile m) + { + foreach (var info in Caster.Aggressors) + if (m == info.Attacker && !info.Expired) + return true; + + return false; + } + + private bool IsAggressed(Mobile m) + { + foreach (var info in Caster.Aggressed) + if (m == info.Defender && !info.Expired) + return true; + + return false; + } + + private static bool IsInnocentTo(Mobile from, Mobile to) => Notoriety.Compute(from, to) == Notoriety.Innocent; + + private static bool IsAllyTo(Mobile from, Mobile to) => Notoriety.Compute(from, to) == Notoriety.Ally; } - - private bool AreaCanTarget(Mobile target, bool feluccaRules) - { - /* Arch cure area effect won't cure aggressors, victims, murderers, criminals or monsters. - * In Felucca, it will also not cure summons and pets. - * For red players it will only cure themselves and guild members. - */ - - if (!Caster.CanBeBeneficial(target, false)) - return false; - - if (Core.AOS && target != Caster) - { - if (IsAggressor(target) || IsAggressed(target)) - return false; - - if ((!IsInnocentTo(Caster, target) || !IsInnocentTo(target, Caster)) && !IsAllyTo(Caster, target)) - return false; - - if (feluccaRules && !(target is PlayerMobile)) - return false; - } - - return true; - } - - private bool IsAggressor(Mobile m) - { - foreach (AggressorInfo info in Caster.Aggressors) - if (m == info.Attacker && !info.Expired) - return true; - - return false; - } - - private bool IsAggressed(Mobile m) - { - foreach (AggressorInfo info in Caster.Aggressed) - if (m == info.Defender && !info.Expired) - return true; - - return false; - } - - private static bool IsInnocentTo(Mobile from, Mobile to) => Notoriety.Compute(from, to) == Notoriety.Innocent; - - private static bool IsAllyTo(Mobile from, Mobile to) => Notoriety.Compute(from, to) == Notoriety.Ally; - } } diff --git a/Projects/UOContent/Spells/Fourth/ArchProtection.cs b/Projects/UOContent/Spells/Fourth/ArchProtection.cs index 7644e3c1d..f848292d3 100644 --- a/Projects/UOContent/Spells/Fourth/ArchProtection.cs +++ b/Projects/UOContent/Spells/Fourth/ArchProtection.cs @@ -7,121 +7,123 @@ using Server.Targeting; namespace Server.Spells.Fourth { - public class ArchProtectionSpell : MagerySpell, ISpellTargetingPoint3D - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Arch Protection", "Vas Uus Sanct", - Core.AOS ? 239 : 215, - 9011, - Reagent.Garlic, - Reagent.Ginseng, - Reagent.MandrakeRoot, - Reagent.SulfurousAsh); - - private static readonly Dictionary _Table = new Dictionary(); - - public ArchProtectionSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class ArchProtectionSpell : MagerySpell, ISpellTargetingPoint3D { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Arch Protection", + "Vas Uus Sanct", + Core.AOS ? 239 : 215, + 9011, + Reagent.Garlic, + Reagent.Ginseng, + Reagent.MandrakeRoot, + Reagent.SulfurousAsh + ); - public override SpellCircle Circle => SpellCircle.Fourth; + private static readonly Dictionary _Table = new Dictionary(); - public override void OnCast() - { - Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); - } - - public void Target(IPoint3D p) - { - if (!Caster.CanSee(p)) - { - Caster.SendLocalizedMessage(500237); // Target can not be seen. - } - else if (CheckSequence()) - { - SpellHelper.Turn(Caster, p); - - SpellHelper.GetSurfaceTop(ref p); - - if (!Core.AOS) - Effects.PlaySound(p, Caster.Map, 0x299); - - if (Caster.Map == null) + public ArchProtectionSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - FinishSequence(); - return; } - IEnumerable targets = Caster.Map.GetMobilesInRange(new Point3D(p), Core.AOS ? 2 : 3) - .Where(m => Caster.CanBeBeneficial(m, false)); + public override SpellCircle Circle => SpellCircle.Fourth; - if (Core.AOS) + public void Target(IPoint3D p) { - Party party = Party.Get(Caster); - - foreach (Mobile m in targets) - if (m == Caster || party?.Contains(m) == true) + if (!Caster.CanSee(p)) { - Caster.DoBeneficial(m); - ProtectionSpell.Toggle(Caster, m); + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckSequence()) + { + SpellHelper.Turn(Caster, p); + + SpellHelper.GetSurfaceTop(ref p); + + if (!Core.AOS) + Effects.PlaySound(p, Caster.Map, 0x299); + + if (Caster.Map == null) + { + FinishSequence(); + return; + } + + var targets = Caster.Map.GetMobilesInRange(new Point3D(p), Core.AOS ? 2 : 3) + .Where(m => Caster.CanBeBeneficial(m, false)); + + if (Core.AOS) + { + var party = Party.Get(Caster); + + foreach (var m in targets) + if (m == Caster || party?.Contains(m) == true) + { + Caster.DoBeneficial(m); + ProtectionSpell.Toggle(Caster, m); + } + } + else + { + var val = (int)(Caster.Skills.Magery.Value / 10.0 + 1); + + foreach (var m in targets) + if (m.BeginAction()) + { + Caster.DoBeneficial(m); + m.VirtualArmorMod += val; + + AddEntry(m, val); + new InternalTimer(m, Caster).Start(); + + m.FixedParticles(0x375A, 9, 20, 5027, EffectLayer.Waist); + m.PlaySound(0x1F7); + } + } + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); + } + + private static void AddEntry(Mobile m, int v) + { + _Table[m] = v; + } + + public static void RemoveEntry(Mobile m) + { + if (_Table.TryGetValue(m, out var v)) + { + _Table.Remove(m); + m.EndAction(); + m.VirtualArmorMod -= Math.Min(v, m.VirtualArmorMod); } } - else + + private class InternalTimer : Timer { - int val = (int)(Caster.Skills.Magery.Value / 10.0 + 1); + private readonly Mobile m_Owner; - foreach (Mobile m in targets) - if (m.BeginAction()) + public InternalTimer(Mobile target, Mobile caster) : base(TimeSpan.FromSeconds(0)) { - Caster.DoBeneficial(m); - m.VirtualArmorMod += val; + var time = caster.Skills.Magery.Value * 1.2; + if (time > 144) + time = 144; + Delay = TimeSpan.FromSeconds(time); + Priority = TimerPriority.OneSecond; - AddEntry(m, val); - new InternalTimer(m, Caster).Start(); + m_Owner = target; + } - m.FixedParticles(0x375A, 9, 20, 5027, EffectLayer.Waist); - m.PlaySound(0x1F7); + protected override void OnTick() + { + RemoveEntry(m_Owner); } } - } - - FinishSequence(); } - - private static void AddEntry(Mobile m, int v) - { - _Table[m] = v; - } - - public static void RemoveEntry(Mobile m) - { - if (_Table.TryGetValue(m, out int v)) - { - _Table.Remove(m); - m.EndAction(); - m.VirtualArmorMod -= Math.Min(v, m.VirtualArmorMod); - } - } - - private class InternalTimer : Timer - { - private readonly Mobile m_Owner; - - public InternalTimer(Mobile target, Mobile caster) : base(TimeSpan.FromSeconds(0)) - { - double time = caster.Skills.Magery.Value * 1.2; - if (time > 144) - time = 144; - Delay = TimeSpan.FromSeconds(time); - Priority = TimerPriority.OneSecond; - - m_Owner = target; - } - - protected override void OnTick() - { - RemoveEntry(m_Owner); - } - } - } } diff --git a/Projects/UOContent/Spells/Fourth/Curse.cs b/Projects/UOContent/Spells/Fourth/Curse.cs index 8cef1d04f..a2a6b3026 100644 --- a/Projects/UOContent/Spells/Fourth/Curse.cs +++ b/Projects/UOContent/Spells/Fourth/Curse.cs @@ -1,86 +1,90 @@ -using System; using System.Collections.Generic; using Server.Targeting; namespace Server.Spells.Fourth { - public class CurseSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Curse", "Des Sanct", - 227, - 9031, - Reagent.Nightshade, - Reagent.Garlic, - Reagent.SulfurousAsh); - - private static readonly HashSet m_UnderEffect = new HashSet(); - - public CurseSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class CurseSpell : MagerySpell, ISpellTargetingMobile { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Curse", + "Des Sanct", + 227, + 9031, + Reagent.Nightshade, + Reagent.Garlic, + Reagent.SulfurousAsh + ); - public override SpellCircle Circle => SpellCircle.Fourth; + private static readonly HashSet m_UnderEffect = new HashSet(); - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - public static void RemoveEffect(Mobile m) - { - m_UnderEffect.Remove(m); - - m.UpdateResistances(); - } - - public static bool UnderEffect(Mobile m) => m_UnderEffect.Contains(m); - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (CheckHSequence(m)) - { - SpellHelper.Turn(Caster, m); - - SpellHelper.CheckReflect((int)Circle, Caster, ref m); - - SpellHelper.AddStatCurse(Caster, m, StatType.Str); - SpellHelper.DisableSkillCheck = true; - SpellHelper.AddStatCurse(Caster, m, StatType.Dex); - SpellHelper.AddStatCurse(Caster, m, StatType.Int); - SpellHelper.DisableSkillCheck = false; - - if (Caster.Player && m.Player /*&& Caster != m */ && !UnderEffect(m)) // On OSI you CAN curse yourself and get this effect. + public CurseSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - TimeSpan duration = SpellHelper.GetDuration(Caster, m); - m_UnderEffect.Add(m); - Timer.DelayCall(duration, RemoveEffect, m); - m.UpdateResistances(); } - m.Spell?.OnCasterHurt(); + public override SpellCircle Circle => SpellCircle.Fourth; - m.Paralyzed = false; + public void Target(Mobile m) + { + if (m == null) + return; - m.FixedParticles(0x374A, 10, 15, 5028, EffectLayer.Waist); - m.PlaySound(0x1E1); + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckHSequence(m)) + { + SpellHelper.Turn(Caster, m); - int percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100); - TimeSpan length = SpellHelper.GetDuration(Caster, m); + SpellHelper.CheckReflect((int)Circle, Caster, ref m); - string args = $"{percentage}\t{percentage}\t{percentage}\t{10}\t{10}\t{10}\t{10}"; + SpellHelper.AddStatCurse(Caster, m, StatType.Str); + SpellHelper.DisableSkillCheck = true; + SpellHelper.AddStatCurse(Caster, m, StatType.Dex); + SpellHelper.AddStatCurse(Caster, m, StatType.Int); + SpellHelper.DisableSkillCheck = false; - BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Curse, 1075835, 1075836, length, m, args)); + if (Caster.Player && m.Player /*&& Caster != m */ && !UnderEffect(m) + ) // On OSI you CAN curse yourself and get this effect. + { + var duration = SpellHelper.GetDuration(Caster, m); + m_UnderEffect.Add(m); + Timer.DelayCall(duration, RemoveEffect, m); + m.UpdateResistances(); + } - HarmfulSpell(m); - } + m.Spell?.OnCasterHurt(); - FinishSequence(); + m.Paralyzed = false; + + m.FixedParticles(0x374A, 10, 15, 5028, EffectLayer.Waist); + m.PlaySound(0x1E1); + + var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, true) * 100); + var length = SpellHelper.GetDuration(Caster, m); + + var args = $"{percentage}\t{percentage}\t{percentage}\t{10}\t{10}\t{10}\t{10}"; + + BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Curse, 1075835, 1075836, length, m, args)); + + HarmfulSpell(m); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } + + public static void RemoveEffect(Mobile m) + { + m_UnderEffect.Remove(m); + + m.UpdateResistances(); + } + + public static bool UnderEffect(Mobile m) => m_UnderEffect.Contains(m); } - } } diff --git a/Projects/UOContent/Spells/Fourth/FireField.cs b/Projects/UOContent/Spells/Fourth/FireField.cs index e8df93a8a..e99cf9658 100644 --- a/Projects/UOContent/Spells/Fourth/FireField.cs +++ b/Projects/UOContent/Spells/Fourth/FireField.cs @@ -7,274 +7,284 @@ using Server.Targeting; namespace Server.Spells.Fourth { - public class FireFieldSpell : MagerySpell, ISpellTargetingPoint3D - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Fire Field", "In Flam Grav", - 215, - 9041, - false, - Reagent.BlackPearl, - Reagent.SpidersSilk, - Reagent.SulfurousAsh); - - public FireFieldSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class FireFieldSpell : MagerySpell, ISpellTargetingPoint3D { + private static readonly SpellInfo m_Info = new SpellInfo( + "Fire Field", + "In Flam Grav", + 215, + 9041, + false, + Reagent.BlackPearl, + Reagent.SpidersSilk, + Reagent.SulfurousAsh + ); + + public FireFieldSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.Fourth; + + public void Target(IPoint3D p) + { + if (!Caster.CanSee(p)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) + { + SpellHelper.Turn(Caster, p); + + SpellHelper.GetSurfaceTop(ref p); + + var dx = Caster.Location.X - p.X; + var dy = Caster.Location.Y - p.Y; + var rx = (dx - dy) * 44; + var ry = (dx + dy) * 44; + + bool eastToWest; + + if (rx >= 0 && ry >= 0) + eastToWest = false; + else if (rx >= 0) + eastToWest = true; + else if (ry >= 0) + eastToWest = true; + else + eastToWest = false; + + Effects.PlaySound(p, Caster.Map, 0x20C); + + var itemID = eastToWest ? 0x398C : 0x3996; + + TimeSpan duration; + + if (Core.AOS) + duration = TimeSpan.FromSeconds((15 + Caster.Skills.Magery.Fixed / 5.0) / 4.0); + else + duration = TimeSpan.FromSeconds(4.0 + Caster.Skills.Magery.Value * 0.5); + + for (var i = -2; i <= 2; ++i) + { + var loc = new Point3D(eastToWest ? p.X + i : p.X, eastToWest ? p.Y : p.Y + i, p.Z); + + new FireFieldItem(itemID, loc, Caster, Caster.Map, duration, i); + } + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); + } + + [DispellableField] + public class FireFieldItem : Item + { + private Mobile m_Caster; + private int m_Damage; + private DateTime m_End; + private Timer m_Timer; + + public FireFieldItem( + int itemID, Point3D loc, Mobile caster, Map map, TimeSpan duration, int val, + int damage = 2 + ) : base(itemID) + { + var canFit = SpellHelper.AdjustField(ref loc, map, 12, false); + + Visible = false; + Movable = false; + Light = LightType.Circle300; + + MoveToWorld(loc, map); + + m_Caster = caster; + + m_Damage = damage; + + m_End = DateTime.UtcNow + duration; + + m_Timer = new InternalTimer(this, TimeSpan.FromSeconds(Math.Abs(val) * 0.2), caster.InLOS(this), canFit); + m_Timer.Start(); + } + + public FireFieldItem(Serial serial) : base(serial) + { + } + + public override bool BlocksFit => true; + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Timer?.Stop(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(2); // version + + writer.Write(m_Damage); + writer.Write(m_Caster); + writer.WriteDeltaTime(m_End); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 2: + { + m_Damage = reader.ReadInt(); + goto case 1; + } + case 1: + { + m_Caster = reader.ReadMobile(); + + goto case 0; + } + case 0: + { + m_End = reader.ReadDeltaTime(); + + m_Timer = new InternalTimer(this, TimeSpan.Zero, true, true); + m_Timer.Start(); + + break; + } + } + + if (version < 2) + m_Damage = 2; + } + + public override bool OnMoveOver(Mobile m) + { + if (Visible && m_Caster != null && (!Core.AOS || m != m_Caster) && + SpellHelper.ValidIndirectTarget(m_Caster, m) && m_Caster.CanBeHarmful(m, false)) + { + if (SpellHelper.CanRevealCaster(m)) + m_Caster.RevealingAction(); + + m_Caster.DoHarmful(m); + + var damage = m_Damage; + + if (!Core.AOS && m.CheckSkill(SkillName.MagicResist, 0.0, 30.0)) + { + damage = 1; + + m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + } + + AOS.Damage(m, m_Caster, damage, 0, 100, 0, 0, 0); + m.PlaySound(0x208); + + (m as BaseCreature)?.OnHarmfulSpell(m_Caster); + } + + return true; + } + + private class InternalTimer : Timer + { + private static readonly Queue m_Queue = new Queue(); + private readonly bool m_CanFit; + private readonly bool m_InLOS; + private readonly FireFieldItem m_Item; + + public InternalTimer(FireFieldItem item, TimeSpan delay, bool inLOS, bool canFit) : base( + delay, + TimeSpan.FromSeconds(1.0) + ) + { + m_Item = item; + m_InLOS = inLOS; + m_CanFit = canFit; + + Priority = TimerPriority.FiftyMS; + } + + protected override void OnTick() + { + if (m_Item.Deleted) + return; + + if (!m_Item.Visible) + { + if (m_InLOS && m_CanFit) + m_Item.Visible = true; + else + m_Item.Delete(); + + if (!m_Item.Deleted) + { + m_Item.ProcessDelta(); + Effects.SendLocationParticles( + EffectItem.Create(m_Item.Location, m_Item.Map, EffectItem.DefaultDuration), + 0x376A, + 9, + 10, + 5029 + ); + } + } + else if (DateTime.UtcNow > m_Item.m_End) + { + m_Item.Delete(); + Stop(); + } + else + { + var map = m_Item.Map; + var caster = m_Item.m_Caster; + + if (map == null || caster == null) + return; + + foreach (var m in m_Item.GetMobilesInRange(0)) + if (m.Z + 16 > m_Item.Z && m_Item.Z + 12 > m.Z && (!Core.AOS || m != caster) && + SpellHelper.ValidIndirectTarget(caster, m) && caster.CanBeHarmful(m, false)) + m_Queue.Enqueue(m); + + while (m_Queue.Count > 0) + { + var m = (Mobile)m_Queue.Dequeue(); + + if (SpellHelper.CanRevealCaster(m)) + caster.RevealingAction(); + + caster.DoHarmful(m); + + var damage = m_Item.m_Damage; + + if (!Core.AOS && m.CheckSkill(SkillName.MagicResist, 0.0, 30.0)) + { + damage = 1; + + m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + } + + AOS.Damage(m, caster, damage, 0, 100, 0, 0, 0); + m.PlaySound(0x208); + + (m as BaseCreature)?.OnHarmfulSpell(caster); + } + } + } + } + } } - - public override SpellCircle Circle => SpellCircle.Fourth; - - public override void OnCast() - { - Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); - } - - public void Target(IPoint3D p) - { - if (!Caster.CanSee(p)) - { - Caster.SendLocalizedMessage(500237); // Target can not be seen. - } - else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) - { - SpellHelper.Turn(Caster, p); - - SpellHelper.GetSurfaceTop(ref p); - - int dx = Caster.Location.X - p.X; - int dy = Caster.Location.Y - p.Y; - int rx = (dx - dy) * 44; - int ry = (dx + dy) * 44; - - bool eastToWest; - - if (rx >= 0 && ry >= 0) - eastToWest = false; - else if (rx >= 0) - eastToWest = true; - else if (ry >= 0) - eastToWest = true; - else - eastToWest = false; - - Effects.PlaySound(p, Caster.Map, 0x20C); - - int itemID = eastToWest ? 0x398C : 0x3996; - - TimeSpan duration; - - if (Core.AOS) - duration = TimeSpan.FromSeconds((15 + Caster.Skills.Magery.Fixed / 5.0) / 4.0); - else - duration = TimeSpan.FromSeconds(4.0 + Caster.Skills.Magery.Value * 0.5); - - for (int i = -2; i <= 2; ++i) - { - Point3D loc = new Point3D(eastToWest ? p.X + i : p.X, eastToWest ? p.Y : p.Y + i, p.Z); - - new FireFieldItem(itemID, loc, Caster, Caster.Map, duration, i); - } - } - - FinishSequence(); - } - - [DispellableField] - public class FireFieldItem : Item - { - private Mobile m_Caster; - private int m_Damage; - private DateTime m_End; - private Timer m_Timer; - - public FireFieldItem(int itemID, Point3D loc, Mobile caster, Map map, TimeSpan duration, int val, - int damage = 2) : base(itemID) - { - bool canFit = SpellHelper.AdjustField(ref loc, map, 12, false); - - Visible = false; - Movable = false; - Light = LightType.Circle300; - - MoveToWorld(loc, map); - - m_Caster = caster; - - m_Damage = damage; - - m_End = DateTime.UtcNow + duration; - - m_Timer = new InternalTimer(this, TimeSpan.FromSeconds(Math.Abs(val) * 0.2), caster.InLOS(this), canFit); - m_Timer.Start(); - } - - public FireFieldItem(Serial serial) : base(serial) - { - } - - public override bool BlocksFit => true; - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Timer?.Stop(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(2); // version - - writer.Write(m_Damage); - writer.Write(m_Caster); - writer.WriteDeltaTime(m_End); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) - { - case 2: - { - m_Damage = reader.ReadInt(); - goto case 1; - } - case 1: - { - m_Caster = reader.ReadMobile(); - - goto case 0; - } - case 0: - { - m_End = reader.ReadDeltaTime(); - - m_Timer = new InternalTimer(this, TimeSpan.Zero, true, true); - m_Timer.Start(); - - break; - } - } - - if (version < 2) - m_Damage = 2; - } - - public override bool OnMoveOver(Mobile m) - { - if (Visible && m_Caster != null && (!Core.AOS || m != m_Caster) && - SpellHelper.ValidIndirectTarget(m_Caster, m) && m_Caster.CanBeHarmful(m, false)) - { - if (SpellHelper.CanRevealCaster(m)) - m_Caster.RevealingAction(); - - m_Caster.DoHarmful(m); - - int damage = m_Damage; - - if (!Core.AOS && m.CheckSkill(SkillName.MagicResist, 0.0, 30.0)) - { - damage = 1; - - m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. - } - - AOS.Damage(m, m_Caster, damage, 0, 100, 0, 0, 0); - m.PlaySound(0x208); - - (m as BaseCreature)?.OnHarmfulSpell(m_Caster); - } - - return true; - } - - private class InternalTimer : Timer - { - private static readonly Queue m_Queue = new Queue(); - private readonly bool m_InLOS; - private readonly bool m_CanFit; - private readonly FireFieldItem m_Item; - - public InternalTimer(FireFieldItem item, TimeSpan delay, bool inLOS, bool canFit) : base(delay, - TimeSpan.FromSeconds(1.0)) - { - m_Item = item; - m_InLOS = inLOS; - m_CanFit = canFit; - - Priority = TimerPriority.FiftyMS; - } - - protected override void OnTick() - { - if (m_Item.Deleted) - return; - - if (!m_Item.Visible) - { - if (m_InLOS && m_CanFit) - m_Item.Visible = true; - else - m_Item.Delete(); - - if (!m_Item.Deleted) - { - m_Item.ProcessDelta(); - Effects.SendLocationParticles( - EffectItem.Create(m_Item.Location, m_Item.Map, EffectItem.DefaultDuration), 0x376A, 9, 10, - 5029); - } - } - else if (DateTime.UtcNow > m_Item.m_End) - { - m_Item.Delete(); - Stop(); - } - else - { - Map map = m_Item.Map; - Mobile caster = m_Item.m_Caster; - - if (map == null || caster == null) - return; - - foreach (Mobile m in m_Item.GetMobilesInRange(0)) - if (m.Z + 16 > m_Item.Z && m_Item.Z + 12 > m.Z && (!Core.AOS || m != caster) && - SpellHelper.ValidIndirectTarget(caster, m) && caster.CanBeHarmful(m, false)) - m_Queue.Enqueue(m); - - while (m_Queue.Count > 0) - { - Mobile m = (Mobile)m_Queue.Dequeue(); - - if (SpellHelper.CanRevealCaster(m)) - caster.RevealingAction(); - - caster.DoHarmful(m); - - int damage = m_Item.m_Damage; - - if (!Core.AOS && m.CheckSkill(SkillName.MagicResist, 0.0, 30.0)) - { - damage = 1; - - m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. - } - - AOS.Damage(m, caster, damage, 0, 100, 0, 0, 0); - m.PlaySound(0x208); - - (m as BaseCreature)?.OnHarmfulSpell(caster); - } - } - } - } - } - } } diff --git a/Projects/UOContent/Spells/Fourth/GreaterHeal.cs b/Projects/UOContent/Spells/Fourth/GreaterHeal.cs index 0c9b101e1..8131c5908 100644 --- a/Projects/UOContent/Spells/Fourth/GreaterHeal.cs +++ b/Projects/UOContent/Spells/Fourth/GreaterHeal.cs @@ -6,79 +6,83 @@ using Server.Targeting; namespace Server.Spells.Fourth { - public class GreaterHealSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Greater Heal", "In Vas Mani", - 204, - 9061, - Reagent.Garlic, - Reagent.Ginseng, - Reagent.MandrakeRoot, - Reagent.SpidersSilk); - - public GreaterHealSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class GreaterHealSpell : MagerySpell, ISpellTargetingMobile { + private static readonly SpellInfo m_Info = new SpellInfo( + "Greater Heal", + "In Vas Mani", + 204, + 9061, + Reagent.Garlic, + Reagent.Ginseng, + Reagent.MandrakeRoot, + Reagent.SpidersSilk + ); + + public GreaterHealSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.Fourth; + + public void Target(Mobile m) + { + if (m == null) + return; + + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (m is BaseCreature creature && creature.IsAnimatedDead) + { + Caster.SendLocalizedMessage(1061654); // You cannot heal that which is not alive. + } + else if (m.IsDeadBondedPet) + { + Caster.SendLocalizedMessage(1060177); // You cannot heal a creature that is already dead! + } + else if (m is Golem) + { + Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500951); // You cannot heal that. + } + else if (m.Poisoned || MortalStrike.IsWounded(m)) + { + Caster.LocalOverheadMessage(MessageType.Regular, 0x22, Caster == m ? 1005000 : 1010398); + } + else if (CheckBSequence(m)) + { + SpellHelper.Turn(Caster, m); + + // Algorithm: (40% of magery) + (1-10) + + var toHeal = (int)(Caster.Skills.Magery.Value * 0.4); + toHeal += Utility.Random(1, 10); + + // m.Heal( toHeal, Caster ); + SpellHelper.Heal(toHeal, m, Caster); + + m.FixedParticles(0x376A, 9, 32, 5030, EffectLayer.Waist); + m.PlaySound(0x202); + } + + FinishSequence(); + } + + public override bool CheckCast() + { + if (DuelContext.CheckSuddenDeath(Caster)) + { + Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); + return false; + } + + return base.CheckCast(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, Core.ML ? 10 : 12); + } } - - public override SpellCircle Circle => SpellCircle.Fourth; - - public override bool CheckCast() - { - if (DuelContext.CheckSuddenDeath(Caster)) - { - Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); - return false; - } - - return base.CheckCast(); - } - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (m is BaseCreature creature && creature.IsAnimatedDead) - { - Caster.SendLocalizedMessage(1061654); // You cannot heal that which is not alive. - } - else if (m.IsDeadBondedPet) - { - Caster.SendLocalizedMessage(1060177); // You cannot heal a creature that is already dead! - } - else if (m is Golem) - { - Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, 500951); // You cannot heal that. - } - else if (m.Poisoned || MortalStrike.IsWounded(m)) - { - Caster.LocalOverheadMessage(MessageType.Regular, 0x22, Caster == m ? 1005000 : 1010398); - } - else if (CheckBSequence(m)) - { - SpellHelper.Turn(Caster, m); - - // Algorithm: (40% of magery) + (1-10) - - int toHeal = (int)(Caster.Skills.Magery.Value * 0.4); - toHeal += Utility.Random(1, 10); - - // m.Heal( toHeal, Caster ); - SpellHelper.Heal(toHeal, m, Caster); - - m.FixedParticles(0x376A, 9, 32, 5030, EffectLayer.Waist); - m.PlaySound(0x202); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Fourth/Lightning.cs b/Projects/UOContent/Spells/Fourth/Lightning.cs index 707b4fbe2..64d329d4b 100644 --- a/Projects/UOContent/Spells/Fourth/Lightning.cs +++ b/Projects/UOContent/Spells/Fourth/Lightning.cs @@ -2,67 +2,71 @@ using Server.Targeting; namespace Server.Spells.Fourth { - public class LightningSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Lightning", "Por Ort Grav", - 239, - 9021, - Reagent.MandrakeRoot, - Reagent.SulfurousAsh); - - public LightningSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class LightningSpell : MagerySpell, ISpellTargetingMobile { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Lightning", + "Por Ort Grav", + 239, + 9021, + Reagent.MandrakeRoot, + Reagent.SulfurousAsh + ); - public override SpellCircle Circle => SpellCircle.Fourth; - - public override bool DelayedDamage => false; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (CheckHSequence(m)) - { - SpellHelper.Turn(Caster, m); - - SpellHelper.CheckReflect((int)Circle, Caster, ref m); - - double damage; - - if (Core.AOS) + public LightningSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - damage = GetNewAosDamage(23, 1, 4, m); - } - else - { - damage = Utility.Random(12, 9); - - if (CheckResisted(m)) - { - damage *= 0.75; - - m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. - } - - damage *= GetDamageScalar(m); } - m.BoltEffect(0); + public override SpellCircle Circle => SpellCircle.Fourth; - SpellHelper.Damage(this, m, damage, 0, 0, 0, 0, 100); - } + public override bool DelayedDamage => false; - FinishSequence(); + public void Target(Mobile m) + { + if (m == null) + return; + + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckHSequence(m)) + { + SpellHelper.Turn(Caster, m); + + SpellHelper.CheckReflect((int)Circle, Caster, ref m); + + double damage; + + if (Core.AOS) + { + damage = GetNewAosDamage(23, 1, 4, m); + } + else + { + damage = Utility.Random(12, 9); + + if (CheckResisted(m)) + { + damage *= 0.75; + + m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + } + + damage *= GetDamageScalar(m); + } + + m.BoltEffect(0); + + SpellHelper.Damage(this, m, damage, 0, 0, 0, 0, 100); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } } - } } diff --git a/Projects/UOContent/Spells/Fourth/ManaDrain.cs b/Projects/UOContent/Spells/Fourth/ManaDrain.cs index 3f83a2a41..1e42ce598 100644 --- a/Projects/UOContent/Spells/Fourth/ManaDrain.cs +++ b/Projects/UOContent/Spells/Fourth/ManaDrain.cs @@ -4,96 +4,100 @@ using Server.Targeting; namespace Server.Spells.Fourth { - public class ManaDrainSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Mana Drain", "Ort Rel", - 215, - 9031, - Reagent.BlackPearl, - Reagent.MandrakeRoot, - Reagent.SpidersSilk); - - private static readonly HashSet m_Table = new HashSet(); - - public ManaDrainSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class ManaDrainSpell : MagerySpell, ISpellTargetingMobile { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Mana Drain", + "Ort Rel", + 215, + 9031, + Reagent.BlackPearl, + Reagent.MandrakeRoot, + Reagent.SpidersSilk + ); - public override SpellCircle Circle => SpellCircle.Fourth; + private static readonly HashSet m_Table = new HashSet(); - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - private void AosDelay_Callback(Mobile m, int mana) - { - if (m.Alive && !m.IsDeadBondedPet) - { - m.Mana += mana; - - m.FixedEffect(0x3779, 10, 25); - m.PlaySound(0x28E); - } - - m_Table.Remove(m); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (CheckHSequence(m)) - { - SpellHelper.Turn(Caster, m); - - SpellHelper.CheckReflect((int)Circle, Caster, ref m); - - m.Spell?.OnCasterHurt(); - - m.Paralyzed = false; - - if (Core.AOS) + public ManaDrainSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - int toDrain = Math.Clamp(40 + (int)(GetDamageSkill(Caster) - GetResistSkill(m)), 0, m.Mana); - - if (m_Table.Contains(m)) - toDrain = 0; - - m.FixedParticles(0x3789, 10, 25, 5032, EffectLayer.Head); - m.PlaySound(0x1F8); - - if (toDrain > 0) - { - m.Mana -= toDrain; - - m_Table.Add(m); - Timer.DelayCall(TimeSpan.FromSeconds(5.0), AosDelay_Callback, m, toDrain); - } - } - else - { - if (CheckResisted(m)) - m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. - else if (m.Mana >= 100) - m.Mana -= Utility.Random(1, 100); - else - m.Mana -= Utility.Random(1, m.Mana); - - m.FixedParticles(0x374A, 10, 15, 5032, EffectLayer.Head); - m.PlaySound(0x1F8); } - HarmfulSpell(m); - } + public override SpellCircle Circle => SpellCircle.Fourth; - FinishSequence(); + public void Target(Mobile m) + { + if (m == null) + return; + + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckHSequence(m)) + { + SpellHelper.Turn(Caster, m); + + SpellHelper.CheckReflect((int)Circle, Caster, ref m); + + m.Spell?.OnCasterHurt(); + + m.Paralyzed = false; + + if (Core.AOS) + { + var toDrain = Math.Clamp(40 + (int)(GetDamageSkill(Caster) - GetResistSkill(m)), 0, m.Mana); + + if (m_Table.Contains(m)) + toDrain = 0; + + m.FixedParticles(0x3789, 10, 25, 5032, EffectLayer.Head); + m.PlaySound(0x1F8); + + if (toDrain > 0) + { + m.Mana -= toDrain; + + m_Table.Add(m); + Timer.DelayCall(TimeSpan.FromSeconds(5.0), AosDelay_Callback, m, toDrain); + } + } + else + { + if (CheckResisted(m)) + m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + else if (m.Mana >= 100) + m.Mana -= Utility.Random(1, 100); + else + m.Mana -= Utility.Random(1, m.Mana); + + m.FixedParticles(0x374A, 10, 15, 5032, EffectLayer.Head); + m.PlaySound(0x1F8); + } + + HarmfulSpell(m); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } + + private void AosDelay_Callback(Mobile m, int mana) + { + if (m.Alive && !m.IsDeadBondedPet) + { + m.Mana += mana; + + m.FixedEffect(0x3779, 10, 25); + m.PlaySound(0x28E); + } + + m_Table.Remove(m); + } + + public override double GetResistPercent(Mobile target) => 99.0; } - - public override double GetResistPercent(Mobile target) => 99.0; - } } diff --git a/Projects/UOContent/Spells/Fourth/Recall.cs b/Projects/UOContent/Spells/Fourth/Recall.cs index 6a504f4e4..5c2c51cd2 100644 --- a/Projects/UOContent/Spells/Fourth/Recall.cs +++ b/Projects/UOContent/Spells/Fourth/Recall.cs @@ -6,136 +6,142 @@ using Server.Spells.Necromancy; namespace Server.Spells.Fourth { - public class RecallSpell : MagerySpell, IRecallSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Recall", "Kal Ort Por", - 239, - 9031, - Reagent.BlackPearl, - Reagent.Bloodmoss, - Reagent.MandrakeRoot); - - private readonly Runebook m_Book; - - private readonly RunebookEntry m_Entry; - - public RecallSpell(Mobile caster, RunebookEntry entry = null, Runebook book = null, Item scroll = null) : base(caster, scroll, m_Info) + public class RecallSpell : MagerySpell, IRecallSpell { - m_Entry = entry; - m_Book = book; + private static readonly SpellInfo m_Info = new SpellInfo( + "Recall", + "Kal Ort Por", + 239, + 9031, + Reagent.BlackPearl, + Reagent.Bloodmoss, + Reagent.MandrakeRoot + ); + + private readonly Runebook m_Book; + + private readonly RunebookEntry m_Entry; + + public RecallSpell(Mobile caster, RunebookEntry entry = null, Runebook book = null, Item scroll = null) : base( + caster, + scroll, + m_Info + ) + { + m_Entry = entry; + m_Book = book; + } + + public override SpellCircle Circle => SpellCircle.Fourth; + + public void Effect(Point3D loc, Map map, bool checkMulti) + { + if (Sigil.ExistsOn(Caster)) + { + Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. + } + else if (map == null || !Core.AOS && Caster.Map != map) + { + Caster.SendLocalizedMessage(1005569); // You can not recall to another facet. + } + else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.RecallFrom)) + { + } + else if (!SpellHelper.CheckTravel(Caster, map, loc, TravelCheckType.RecallTo)) + { + } + else if (map == Map.Felucca && Caster is PlayerMobile mobile && mobile.Young) + { + mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young. + } + else if (Caster.Kills >= 5 && map != Map.Felucca) + { + Caster.SendLocalizedMessage(1019004); // You are not allowed to travel there. + } + else if (Caster.Criminal) + { + Caster.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily. + } + else if (SpellHelper.CheckCombat(Caster)) + { + Caster.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle?? + } + else if (WeightOverloading.IsOverloaded(Caster)) + { + Caster.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move. + } + else if (!map.CanSpawnMobile(loc.X, loc.Y, loc.Z)) + { + Caster.SendLocalizedMessage(501942); // That location is blocked. + } + else if (checkMulti && SpellHelper.CheckMulti(loc, map)) + { + Caster.SendLocalizedMessage(501942); // That location is blocked. + } + else if (m_Book != null && m_Book.CurCharges <= 0) + { + Caster.SendLocalizedMessage(502412); // There are no charges left on that item. + } + else if (CheckSequence()) + { + BaseCreature.TeleportPets(Caster, loc, map, true); + + if (m_Book != null) + --m_Book.CurCharges; + + Caster.PlaySound(0x1FC); + Caster.MoveToWorld(loc, map); + Caster.PlaySound(0x1FC); + } + + FinishSequence(); + } + + public override void GetCastSkills(out double min, out double max) + { + if (TransformationSpellHelper.UnderTransformation(Caster, typeof(WraithFormSpell))) + min = max = 0; + else if (Core.SE && m_Book != null) // recall using Runebook charge + min = max = 0; + else + base.GetCastSkills(out min, out max); + } + + public override void OnCast() + { + if (m_Entry == null) + Caster.Target = new RecallSpellTarget(this); + else + Effect(m_Entry.Location, m_Entry.Map, true); + } + + public override bool CheckCast() + { + if (Sigil.ExistsOn(Caster)) + { + Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. + return false; + } + + if (Caster.Criminal) + { + Caster.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily. + return false; + } + + if (SpellHelper.CheckCombat(Caster)) + { + Caster.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle?? + return false; + } + + if (WeightOverloading.IsOverloaded(Caster)) + { + Caster.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move. + return false; + } + + return SpellHelper.CheckTravel(Caster, TravelCheckType.RecallFrom); + } } - - public override SpellCircle Circle => SpellCircle.Fourth; - - public override void GetCastSkills(out double min, out double max) - { - if (TransformationSpellHelper.UnderTransformation(Caster, typeof(WraithFormSpell))) - min = max = 0; - else if (Core.SE && m_Book != null) // recall using Runebook charge - min = max = 0; - else - base.GetCastSkills(out min, out max); - } - - public override void OnCast() - { - if (m_Entry == null) - Caster.Target = new RecallSpellTarget(this); - else - Effect(m_Entry.Location, m_Entry.Map, true); - } - - public override bool CheckCast() - { - if (Sigil.ExistsOn(Caster)) - { - Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. - return false; - } - - if (Caster.Criminal) - { - Caster.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily. - return false; - } - - if (SpellHelper.CheckCombat(Caster)) - { - Caster.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle?? - return false; - } - - if (WeightOverloading.IsOverloaded(Caster)) - { - Caster.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move. - return false; - } - - return SpellHelper.CheckTravel(Caster, TravelCheckType.RecallFrom); - } - - public void Effect(Point3D loc, Map map, bool checkMulti) - { - if (Sigil.ExistsOn(Caster)) - { - Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. - } - else if (map == null || (!Core.AOS && Caster.Map != map)) - { - Caster.SendLocalizedMessage(1005569); // You can not recall to another facet. - } - else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.RecallFrom)) - { - } - else if (!SpellHelper.CheckTravel(Caster, map, loc, TravelCheckType.RecallTo)) - { - } - else if (map == Map.Felucca && Caster is PlayerMobile mobile && mobile.Young) - { - mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young. - } - else if (Caster.Kills >= 5 && map != Map.Felucca) - { - Caster.SendLocalizedMessage(1019004); // You are not allowed to travel there. - } - else if (Caster.Criminal) - { - Caster.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily. - } - else if (SpellHelper.CheckCombat(Caster)) - { - Caster.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle?? - } - else if (WeightOverloading.IsOverloaded(Caster)) - { - Caster.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move. - } - else if (!map.CanSpawnMobile(loc.X, loc.Y, loc.Z)) - { - Caster.SendLocalizedMessage(501942); // That location is blocked. - } - else if (checkMulti && SpellHelper.CheckMulti(loc, map)) - { - Caster.SendLocalizedMessage(501942); // That location is blocked. - } - else if (m_Book != null && m_Book.CurCharges <= 0) - { - Caster.SendLocalizedMessage(502412); // There are no charges left on that item. - } - else if (CheckSequence()) - { - BaseCreature.TeleportPets(Caster, loc, map, true); - - if (m_Book != null) - --m_Book.CurCharges; - - Caster.PlaySound(0x1FC); - Caster.MoveToWorld(loc, map); - Caster.PlaySound(0x1FC); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Gargoyle/SpellDefinitions/FlySpell.cs b/Projects/UOContent/Spells/Gargoyle/SpellDefinitions/FlySpell.cs index d043bc695..1184fdde0 100644 --- a/Projects/UOContent/Spells/Gargoyle/SpellDefinitions/FlySpell.cs +++ b/Projects/UOContent/Spells/Gargoyle/SpellDefinitions/FlySpell.cs @@ -2,64 +2,64 @@ using System; namespace Server.Spells { - public class FlySpell : Spell - { - private static readonly SpellInfo m_Info = new SpellInfo("Gargoyle Flight", null, -1, 9002); - private bool m_Stop; - - public FlySpell(Mobile caster) - : base(caster, null, m_Info) + public class FlySpell : Spell { + private static readonly SpellInfo m_Info = new SpellInfo("Gargoyle Flight", null, -1, 9002); + private bool m_Stop; + + public FlySpell(Mobile caster) + : base(caster, null, m_Info) + { + } + + public override bool ClearHandsOnCast => false; + + public override bool RevealOnCast => false; + + public override double CastDelayFastScalar => 0; + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(.25); + + public override TimeSpan GetCastRecovery() => TimeSpan.Zero; + + public override int GetMana() => 0; + + public override bool ConsumeReagents() => true; + + public override bool CheckFizzle() => true; + + public void Stop() + { + m_Stop = true; + Disturb(DisturbType.Hurt, false); + } + + public override bool CheckDisturb(DisturbType type, bool checkFirst, bool resistable) => + type != DisturbType.EquipRequest && type != DisturbType.UseRequest; + + public override void DoHurtFizzle() + { + } + + public override void DoFizzle() + { + } + + public override void OnDisturb(DisturbType type, bool message) + { + if (message && !m_Stop) + Caster.SendLocalizedMessage(1113192); // You have been disrupted while attempting to fly! + } + + public override void OnCast() + { + Caster.Flying = false; + BuffInfo.RemoveBuff(Caster, BuffIcon.Fly); + Caster.Animate(60, 10, 1, true, false, 0); + Caster.SendLocalizedMessage(1112567); // You are flying. + Caster.Flying = true; + BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.Fly, 1112567)); + FinishSequence(); + } } - - public override bool ClearHandsOnCast => false; - - public override bool RevealOnCast => false; - - public override double CastDelayFastScalar => 0; - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(.25); - - public override TimeSpan GetCastRecovery() => TimeSpan.Zero; - - public override int GetMana() => 0; - - public override bool ConsumeReagents() => true; - - public override bool CheckFizzle() => true; - - public void Stop() - { - m_Stop = true; - Disturb(DisturbType.Hurt, false); - } - - public override bool CheckDisturb(DisturbType type, bool checkFirst, bool resistable) => - type != DisturbType.EquipRequest && type != DisturbType.UseRequest; - - public override void DoHurtFizzle() - { - } - - public override void DoFizzle() - { - } - - public override void OnDisturb(DisturbType type, bool message) - { - if (message && !m_Stop) - Caster.SendLocalizedMessage(1113192); // You have been disrupted while attempting to fly! - } - - public override void OnCast() - { - Caster.Flying = false; - BuffInfo.RemoveBuff(Caster, BuffIcon.Fly); - Caster.Animate(60, 10, 1, true, false, 0); - Caster.SendLocalizedMessage(1112567); // You are flying. - Caster.Flying = true; - BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.Fly, 1112567)); - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Initializer.cs b/Projects/UOContent/Spells/Initializer.cs index 1f2940525..b7f6e90e4 100644 --- a/Projects/UOContent/Spells/Initializer.cs +++ b/Projects/UOContent/Spells/Initializer.cs @@ -16,192 +16,192 @@ using Server.Spells.Third; namespace Server.Spells { - public class Initializer - { - public static void Initialize() + public class Initializer { - // First circle - Register(00, typeof(ClumsySpell)); - Register(01, typeof(CreateFoodSpell)); - Register(02, typeof(FeeblemindSpell)); - Register(03, typeof(HealSpell)); - Register(04, typeof(MagicArrowSpell)); - Register(05, typeof(NightSightSpell)); - Register(06, typeof(ReactiveArmorSpell)); - Register(07, typeof(WeakenSpell)); - - // Second circle - Register(08, typeof(AgilitySpell)); - Register(09, typeof(CunningSpell)); - Register(10, typeof(CureSpell)); - Register(11, typeof(HarmSpell)); - Register(12, typeof(MagicTrapSpell)); - Register(13, typeof(RemoveTrapSpell)); - Register(14, typeof(ProtectionSpell)); - Register(15, typeof(StrengthSpell)); - - // Third circle - Register(16, typeof(BlessSpell)); - Register(17, typeof(FireballSpell)); - Register(18, typeof(MagicLockSpell)); - Register(19, typeof(PoisonSpell)); - Register(20, typeof(TelekinesisSpell)); - Register(21, typeof(TeleportSpell)); - Register(22, typeof(UnlockSpell)); - Register(23, typeof(WallOfStoneSpell)); - - // Fourth circle - Register(24, typeof(ArchCureSpell)); - Register(25, typeof(ArchProtectionSpell)); - Register(26, typeof(CurseSpell)); - Register(27, typeof(FireFieldSpell)); - Register(28, typeof(GreaterHealSpell)); - Register(29, typeof(LightningSpell)); - Register(30, typeof(ManaDrainSpell)); - Register(31, typeof(RecallSpell)); - - // Fifth circle - Register(32, typeof(BladeSpiritsSpell)); - Register(33, typeof(DispelFieldSpell)); - Register(34, typeof(IncognitoSpell)); - Register(35, typeof(MagicReflectSpell)); - Register(36, typeof(MindBlastSpell)); - Register(37, typeof(ParalyzeSpell)); - Register(38, typeof(PoisonFieldSpell)); - Register(39, typeof(SummonCreatureSpell)); - - // Sixth circle - Register(40, typeof(DispelSpell)); - Register(41, typeof(EnergyBoltSpell)); - Register(42, typeof(ExplosionSpell)); - Register(43, typeof(InvisibilitySpell)); - Register(44, typeof(MarkSpell)); - Register(45, typeof(MassCurseSpell)); - Register(46, typeof(ParalyzeFieldSpell)); - Register(47, typeof(RevealSpell)); - - // Seventh circle - Register(48, typeof(ChainLightningSpell)); - Register(49, typeof(EnergyFieldSpell)); - Register(50, typeof(FlameStrikeSpell)); - Register(51, typeof(GateTravelSpell)); - Register(52, typeof(ManaVampireSpell)); - Register(53, typeof(MassDispelSpell)); - Register(54, typeof(MeteorSwarmSpell)); - Register(55, typeof(PolymorphSpell)); - - // Eighth circle - Register(56, typeof(EarthquakeSpell)); - Register(57, typeof(EnergyVortexSpell)); - Register(58, typeof(ResurrectionSpell)); - Register(59, typeof(AirElementalSpell)); - Register(60, typeof(SummonDaemonSpell)); - Register(61, typeof(EarthElementalSpell)); - Register(62, typeof(FireElementalSpell)); - Register(63, typeof(WaterElementalSpell)); - - if (Core.AOS) - { - // Necromancy spells - Register(100, typeof(AnimateDeadSpell)); - Register(101, typeof(BloodOathSpell)); - Register(102, typeof(CorpseSkinSpell)); - Register(103, typeof(CurseWeaponSpell)); - Register(104, typeof(EvilOmenSpell)); - Register(105, typeof(HorrificBeastSpell)); - Register(106, typeof(LichFormSpell)); - Register(107, typeof(MindRotSpell)); - Register(108, typeof(PainSpikeSpell)); - Register(109, typeof(PoisonStrikeSpell)); - Register(110, typeof(StrangleSpell)); - Register(111, typeof(SummonFamiliarSpell)); - Register(112, typeof(VampiricEmbraceSpell)); - Register(113, typeof(VengefulSpiritSpell)); - Register(114, typeof(WitherSpell)); - Register(115, typeof(WraithFormSpell)); - - if (Core.SE) - Register(116, typeof(ExorcismSpell)); - - // Paladin abilities - Register(200, typeof(CleanseByFireSpell)); - Register(201, typeof(CloseWoundsSpell)); - Register(202, typeof(ConsecrateWeaponSpell)); - Register(203, typeof(DispelEvilSpell)); - Register(204, typeof(DivineFurySpell)); - Register(205, typeof(EnemyOfOneSpell)); - Register(206, typeof(HolyLightSpell)); - Register(207, typeof(NobleSacrificeSpell)); - Register(208, typeof(RemoveCurseSpell)); - Register(209, typeof(SacredJourneySpell)); - - if (Core.SE) + public static void Initialize() { - // Samurai abilities - Register(400, typeof(HonorableExecution)); - Register(401, typeof(Confidence)); - Register(402, typeof(Evasion)); - Register(403, typeof(CounterAttack)); - Register(404, typeof(LightningStrike)); - Register(405, typeof(MomentumStrike)); + // First circle + Register(00, typeof(ClumsySpell)); + Register(01, typeof(CreateFoodSpell)); + Register(02, typeof(FeeblemindSpell)); + Register(03, typeof(HealSpell)); + Register(04, typeof(MagicArrowSpell)); + Register(05, typeof(NightSightSpell)); + Register(06, typeof(ReactiveArmorSpell)); + Register(07, typeof(WeakenSpell)); - // Ninja abilities - Register(500, typeof(FocusAttack)); - Register(501, typeof(DeathStrike)); - Register(502, typeof(AnimalForm)); - Register(503, typeof(KiAttack)); - Register(504, typeof(SurpriseAttack)); - Register(505, typeof(Backstab)); - Register(506, typeof(Shadowjump)); - Register(507, typeof(MirrorImage)); + // Second circle + Register(08, typeof(AgilitySpell)); + Register(09, typeof(CunningSpell)); + Register(10, typeof(CureSpell)); + Register(11, typeof(HarmSpell)); + Register(12, typeof(MagicTrapSpell)); + Register(13, typeof(RemoveTrapSpell)); + Register(14, typeof(ProtectionSpell)); + Register(15, typeof(StrengthSpell)); + + // Third circle + Register(16, typeof(BlessSpell)); + Register(17, typeof(FireballSpell)); + Register(18, typeof(MagicLockSpell)); + Register(19, typeof(PoisonSpell)); + Register(20, typeof(TelekinesisSpell)); + Register(21, typeof(TeleportSpell)); + Register(22, typeof(UnlockSpell)); + Register(23, typeof(WallOfStoneSpell)); + + // Fourth circle + Register(24, typeof(ArchCureSpell)); + Register(25, typeof(ArchProtectionSpell)); + Register(26, typeof(CurseSpell)); + Register(27, typeof(FireFieldSpell)); + Register(28, typeof(GreaterHealSpell)); + Register(29, typeof(LightningSpell)); + Register(30, typeof(ManaDrainSpell)); + Register(31, typeof(RecallSpell)); + + // Fifth circle + Register(32, typeof(BladeSpiritsSpell)); + Register(33, typeof(DispelFieldSpell)); + Register(34, typeof(IncognitoSpell)); + Register(35, typeof(MagicReflectSpell)); + Register(36, typeof(MindBlastSpell)); + Register(37, typeof(ParalyzeSpell)); + Register(38, typeof(PoisonFieldSpell)); + Register(39, typeof(SummonCreatureSpell)); + + // Sixth circle + Register(40, typeof(DispelSpell)); + Register(41, typeof(EnergyBoltSpell)); + Register(42, typeof(ExplosionSpell)); + Register(43, typeof(InvisibilitySpell)); + Register(44, typeof(MarkSpell)); + Register(45, typeof(MassCurseSpell)); + Register(46, typeof(ParalyzeFieldSpell)); + Register(47, typeof(RevealSpell)); + + // Seventh circle + Register(48, typeof(ChainLightningSpell)); + Register(49, typeof(EnergyFieldSpell)); + Register(50, typeof(FlameStrikeSpell)); + Register(51, typeof(GateTravelSpell)); + Register(52, typeof(ManaVampireSpell)); + Register(53, typeof(MassDispelSpell)); + Register(54, typeof(MeteorSwarmSpell)); + Register(55, typeof(PolymorphSpell)); + + // Eighth circle + Register(56, typeof(EarthquakeSpell)); + Register(57, typeof(EnergyVortexSpell)); + Register(58, typeof(ResurrectionSpell)); + Register(59, typeof(AirElementalSpell)); + Register(60, typeof(SummonDaemonSpell)); + Register(61, typeof(EarthElementalSpell)); + Register(62, typeof(FireElementalSpell)); + Register(63, typeof(WaterElementalSpell)); + + if (Core.AOS) + { + // Necromancy spells + Register(100, typeof(AnimateDeadSpell)); + Register(101, typeof(BloodOathSpell)); + Register(102, typeof(CorpseSkinSpell)); + Register(103, typeof(CurseWeaponSpell)); + Register(104, typeof(EvilOmenSpell)); + Register(105, typeof(HorrificBeastSpell)); + Register(106, typeof(LichFormSpell)); + Register(107, typeof(MindRotSpell)); + Register(108, typeof(PainSpikeSpell)); + Register(109, typeof(PoisonStrikeSpell)); + Register(110, typeof(StrangleSpell)); + Register(111, typeof(SummonFamiliarSpell)); + Register(112, typeof(VampiricEmbraceSpell)); + Register(113, typeof(VengefulSpiritSpell)); + Register(114, typeof(WitherSpell)); + Register(115, typeof(WraithFormSpell)); + + if (Core.SE) + Register(116, typeof(ExorcismSpell)); + + // Paladin abilities + Register(200, typeof(CleanseByFireSpell)); + Register(201, typeof(CloseWoundsSpell)); + Register(202, typeof(ConsecrateWeaponSpell)); + Register(203, typeof(DispelEvilSpell)); + Register(204, typeof(DivineFurySpell)); + Register(205, typeof(EnemyOfOneSpell)); + Register(206, typeof(HolyLightSpell)); + Register(207, typeof(NobleSacrificeSpell)); + Register(208, typeof(RemoveCurseSpell)); + Register(209, typeof(SacredJourneySpell)); + + if (Core.SE) + { + // Samurai abilities + Register(400, typeof(HonorableExecution)); + Register(401, typeof(Confidence)); + Register(402, typeof(Evasion)); + Register(403, typeof(CounterAttack)); + Register(404, typeof(LightningStrike)); + Register(405, typeof(MomentumStrike)); + + // Ninja abilities + Register(500, typeof(FocusAttack)); + Register(501, typeof(DeathStrike)); + Register(502, typeof(AnimalForm)); + Register(503, typeof(KiAttack)); + Register(504, typeof(SurpriseAttack)); + Register(505, typeof(Backstab)); + Register(506, typeof(Shadowjump)); + Register(507, typeof(MirrorImage)); + } + + if (Core.ML) + { + Register(600, typeof(ArcaneCircleSpell)); + Register(601, typeof(GiftOfRenewalSpell)); + Register(602, typeof(ImmolatingWeaponSpell)); + Register(603, typeof(AttuneWeaponSpell)); + Register(604, typeof(ThunderstormSpell)); + Register(605, typeof(NatureFurySpell)); + Register(606, typeof(SummonFeySpell)); + Register(607, typeof(SummonFiendSpell)); + Register(608, typeof(ReaperFormSpell)); + // Register( 609, typeof( Spellweaving.WildfireSpell ) ); + Register(610, typeof(EssenceOfWindSpell)); + // Register( 611, typeof( Spellweaving.DryadAllureSpell ) ); + Register(612, typeof(EtherealVoyageSpell)); + Register(613, typeof(WordOfDeathSpell)); + Register(614, typeof(GiftOfLifeSpell)); + // Register( 615, typeof( Spellweaving.ArcaneEmpowermentSpell ) ); + } + + if (Core.SA) + { + // Mysticism spells + // Register( 677, typeof( Mysticism.NetherBoltSpell ) ); + // Register( 678, typeof( Mysticism.HealingStoneSpell ) ); + // Register( 679, typeof( Mysticism.PurgeMagicSpell ) ); + // Register( 680, typeof( Mysticism.EnchantSpell ) ); + // Register( 681, typeof( Mysticism.SleepSpell ) ); + Register(682, typeof(EagleStrikeSpell)); + Register(683, typeof(AnimatedWeaponSpell)); + Register(684, typeof(StoneFormSpell)); + // Register( 685, typeof( Mysticism.SpellTriggerSpell ) ); + // Register( 686, typeof( Mysticism.MassSleepSpell ) ); + // Register( 687, typeof( Mysticism.CleansingWindsSpell ) ); + // Register( 688, typeof( Mysticism.BombardSpell ) ); + Register(689, typeof(SpellPlagueSpell)); + Register(690, typeof(HailStormSpell)); + Register(691, typeof(NetherCycloneSpell)); + // Register( 692, typeof( Mysticism.RisingColossusSpell ) ); + } + } } - if (Core.ML) + public static void Register(int spellId, Type type) { - Register(600, typeof(ArcaneCircleSpell)); - Register(601, typeof(GiftOfRenewalSpell)); - Register(602, typeof(ImmolatingWeaponSpell)); - Register(603, typeof(AttuneWeaponSpell)); - Register(604, typeof(ThunderstormSpell)); - Register(605, typeof(NatureFurySpell)); - Register(606, typeof(SummonFeySpell)); - Register(607, typeof(SummonFiendSpell)); - Register(608, typeof(ReaperFormSpell)); - // Register( 609, typeof( Spellweaving.WildfireSpell ) ); - Register(610, typeof(EssenceOfWindSpell)); - // Register( 611, typeof( Spellweaving.DryadAllureSpell ) ); - Register(612, typeof(EtherealVoyageSpell)); - Register(613, typeof(WordOfDeathSpell)); - Register(614, typeof(GiftOfLifeSpell)); - // Register( 615, typeof( Spellweaving.ArcaneEmpowermentSpell ) ); + SpellRegistry.Register(spellId, type); } - - if (Core.SA) - { - // Mysticism spells - // Register( 677, typeof( Mysticism.NetherBoltSpell ) ); - // Register( 678, typeof( Mysticism.HealingStoneSpell ) ); - // Register( 679, typeof( Mysticism.PurgeMagicSpell ) ); - // Register( 680, typeof( Mysticism.EnchantSpell ) ); - // Register( 681, typeof( Mysticism.SleepSpell ) ); - Register(682, typeof(EagleStrikeSpell)); - Register(683, typeof(AnimatedWeaponSpell)); - Register(684, typeof(StoneFormSpell)); - // Register( 685, typeof( Mysticism.SpellTriggerSpell ) ); - // Register( 686, typeof( Mysticism.MassSleepSpell ) ); - // Register( 687, typeof( Mysticism.CleansingWindsSpell ) ); - // Register( 688, typeof( Mysticism.BombardSpell ) ); - Register(689, typeof(SpellPlagueSpell)); - Register(690, typeof(HailStormSpell)); - Register(691, typeof(NetherCycloneSpell)); - // Register( 692, typeof( Mysticism.RisingColossusSpell ) ); - } - } } - - public static void Register(int spellId, Type type) - { - SpellRegistry.Register(spellId, type); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Spells/Mysticism/AnimatedWeaponSpell.cs b/Projects/UOContent/Spells/Mysticism/AnimatedWeaponSpell.cs index a55b5e086..9fd9d20fb 100644 --- a/Projects/UOContent/Spells/Mysticism/AnimatedWeaponSpell.cs +++ b/Projects/UOContent/Spells/Mysticism/AnimatedWeaponSpell.cs @@ -3,63 +3,65 @@ using Server.Mobiles; namespace Server.Spells.Mysticism { - public class AnimatedWeaponSpell : MysticSpell, ISpellTargetingPoint3D - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Animated Weapon", "In Jux Por Ylem", - -1, - 9002, - Reagent.Bone, - Reagent.BlackPearl, - Reagent.MandrakeRoot, - Reagent.Nightshade); - - public AnimatedWeaponSpell(Mobile caster, Item scroll = null) - : base(caster, scroll, m_Info) + public class AnimatedWeaponSpell : MysticSpell, ISpellTargetingPoint3D { + private static readonly SpellInfo m_Info = new SpellInfo( + "Animated Weapon", + "In Jux Por Ylem", + -1, + 9002, + Reagent.Bone, + Reagent.BlackPearl, + Reagent.MandrakeRoot, + Reagent.Nightshade + ); + + public AnimatedWeaponSpell(Mobile caster, Item scroll = null) + : base(caster, scroll, m_Info) + { + } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); + + public override double RequiredSkill => 33.0; + public override int RequiredMana => 11; + + public void Target(IPoint3D p) + { + if (Caster.Followers + 4 > Caster.FollowersMax) + { + Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. + return; + } + + var map = Caster.Map; + + SpellHelper.GetSurfaceTop(ref p); + + if (map == null || Caster.Player && !map.CanSpawnMobile(p.X, p.Y, p.Z)) + { + Caster.SendLocalizedMessage(501942); // That location is blocked. + } + else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) + { + var level = (int)((GetBaseSkill(Caster) + GetBoostSkill(Caster)) / 2.0); + + var duration = TimeSpan.FromSeconds(10 + level); + + var summon = new AnimatedWeapon(Caster, level); + BaseCreature.Summon(summon, false, Caster, new Point3D(p), 0x212, duration); + + summon.PlaySound(0x64A); + + Effects.SendTargetParticles(summon, 0x3728, 10, 10, 0x13AA, (EffectLayer)255); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetPoint3D(this); + } } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); - - public override double RequiredSkill => 33.0; - public override int RequiredMana => 11; - - public override void OnCast() - { - Caster.Target = new SpellTargetPoint3D(this); - } - - public void Target(IPoint3D p) - { - if (Caster.Followers + 4 > Caster.FollowersMax) - { - Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. - return; - } - - Map map = Caster.Map; - - SpellHelper.GetSurfaceTop(ref p); - - if (map == null || (Caster.Player && !map.CanSpawnMobile(p.X, p.Y, p.Z))) - { - Caster.SendLocalizedMessage(501942); // That location is blocked. - } - else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) - { - int level = (int)((GetBaseSkill(Caster) + GetBoostSkill(Caster)) / 2.0); - - TimeSpan duration = TimeSpan.FromSeconds(10 + level); - - AnimatedWeapon summon = new AnimatedWeapon(Caster, level); - BaseCreature.Summon(summon, false, Caster, new Point3D(p), 0x212, duration); - - summon.PlaySound(0x64A); - - Effects.SendTargetParticles(summon, 0x3728, 10, 10, 0x13AA, (EffectLayer)255); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Mysticism/EagleStrikeSpell.cs b/Projects/UOContent/Spells/Mysticism/EagleStrikeSpell.cs index c9f09f6ea..6eabf3114 100644 --- a/Projects/UOContent/Spells/Mysticism/EagleStrikeSpell.cs +++ b/Projects/UOContent/Spells/Mysticism/EagleStrikeSpell.cs @@ -3,66 +3,68 @@ using Server.Targeting; namespace Server.Spells.Mysticism { - public class EagleStrikeSpell : MysticSpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Eagle Strike", "Kal Por Xen", - -1, - 9002, - Reagent.Bloodmoss, - Reagent.Bone, - Reagent.SpidersSilk, - Reagent.MandrakeRoot); - - public EagleStrikeSpell(Mobile caster, Item scroll = null) - : base(caster, scroll, m_Info) + public class EagleStrikeSpell : MysticSpell, ISpellTargetingMobile { + private static readonly SpellInfo m_Info = new SpellInfo( + "Eagle Strike", + "Kal Por Xen", + -1, + 9002, + Reagent.Bloodmoss, + Reagent.Bone, + Reagent.SpidersSilk, + Reagent.MandrakeRoot + ); + + public EagleStrikeSpell(Mobile caster, Item scroll = null) + : base(caster, scroll, m_Info) + { + } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.25); + + public override double RequiredSkill => 20.0; + public override int RequiredMana => 9; + + public void Target(Mobile m) + { + if (m == null) + return; + + if (CheckHSequence(m)) + { + /* Conjures a magical eagle that assaults the Target with + * its talons, dealing energy damage. + */ + + SpellHelper.Turn(Caster, m); + + SpellHelper.CheckReflect(2, Caster, ref m); + + Caster.MovingParticles(m, 0x407A, 7, 0, false, true, 0, 0, 0xBBE, 0xFA6, 0xFFFF, 0); + Caster.PlaySound(0x2EE); + + Timer.DelayCall(TimeSpan.FromSeconds(1.0), Damage, m); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful); + } + + private void Damage(Mobile to) + { + if (to == null) + return; + + double damage = GetNewAosDamage(19, 1, 5, to); + + SpellHelper.Damage(this, to, damage, 0, 0, 0, 0, 100); + + to.PlaySound(0x64D); + } } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.25); - - public override double RequiredSkill => 20.0; - public override int RequiredMana => 9; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (CheckHSequence(m)) - { - /* Conjures a magical eagle that assaults the Target with - * its talons, dealing energy damage. - */ - - SpellHelper.Turn(Caster, m); - - SpellHelper.CheckReflect(2, Caster, ref m); - - Caster.MovingParticles(m, 0x407A, 7, 0, false, true, 0, 0, 0xBBE, 0xFA6, 0xFFFF, 0); - Caster.PlaySound(0x2EE); - - Timer.DelayCall(TimeSpan.FromSeconds(1.0), Damage, m); - } - - FinishSequence(); - } - - private void Damage(Mobile to) - { - if (to == null) - return; - - double damage = GetNewAosDamage(19, 1, 5, to); - - SpellHelper.Damage(this, to, damage, 0, 0, 0, 0, 100); - - to.PlaySound(0x64D); - } - } } diff --git a/Projects/UOContent/Spells/Mysticism/HailStormSpell.cs b/Projects/UOContent/Spells/Mysticism/HailStormSpell.cs index 5fdabb989..6eac00a67 100644 --- a/Projects/UOContent/Spells/Mysticism/HailStormSpell.cs +++ b/Projects/UOContent/Spells/Mysticism/HailStormSpell.cs @@ -4,117 +4,134 @@ using Server.Network; namespace Server.Spells.Mysticism { - public class HailStormSpell : MysticSpell, ISpellTargetingPoint3D - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Hail Storm", "Kal Des Ylem", - -1, - 9002, - Reagent.DragonsBlood, - Reagent.Bloodmoss, - Reagent.BlackPearl, - Reagent.MandrakeRoot); - - public HailStormSpell(Mobile caster, Item scroll = null) - : base(caster, scroll, m_Info) + public class HailStormSpell : MysticSpell, ISpellTargetingPoint3D { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Hail Storm", + "Kal Des Ylem", + -1, + 9002, + Reagent.DragonsBlood, + Reagent.Bloodmoss, + Reagent.BlackPearl, + Reagent.MandrakeRoot + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.25); - - public override double RequiredSkill => 70.0; - public override int RequiredMana => 40; - - public override void OnCast() - { - Caster.Target = new SpellTargetPoint3D(this); - } - - public void Target(IPoint3D p) - { - if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) - { - /* Summons a storm of hailstones that strikes all Targets - * within a radius around the Target's Location, dealing - * cold damage. - */ - - SpellHelper.Turn(Caster, p); - - if (p is Item item) - p = item.GetWorldLocation(); - - List targets = new List(); - - Map map = Caster.Map; - - bool pvp = false; - - if (map != null) + public HailStormSpell(Mobile caster, Item scroll = null) + : base(caster, scroll, m_Info) { - PlayEffect(p, Caster.Map); + } - foreach (Mobile m in map.GetMobilesInRange(new Point3D(p), 2)) - { - if (m == Caster) - continue; + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.25); - if (SpellHelper.ValidIndirectTarget(Caster, m) && Caster.CanBeHarmful(m, false) && Caster.CanSee(m)) + public override double RequiredSkill => 70.0; + public override int RequiredMana => 40; + + public void Target(IPoint3D p) + { + if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) { - if (!Caster.InLOS(m)) - continue; + /* Summons a storm of hailstones that strikes all Targets + * within a radius around the Target's Location, dealing + * cold damage. + */ - targets.Add(m); + SpellHelper.Turn(Caster, p); - if (m.Player) - pvp = true; + if (p is Item item) + p = item.GetWorldLocation(); + + var targets = new List(); + + var map = Caster.Map; + + var pvp = false; + + if (map != null) + { + PlayEffect(p, Caster.Map); + + foreach (var m in map.GetMobilesInRange(new Point3D(p), 2)) + { + if (m == Caster) + continue; + + if (SpellHelper.ValidIndirectTarget(Caster, m) && Caster.CanBeHarmful(m, false) && Caster.CanSee(m)) + { + if (!Caster.InLOS(m)) + continue; + + targets.Add(m); + + if (m.Player) + pvp = true; + } + } + } + + double damage = GetNewAosDamage(51, 1, 5, pvp); + + foreach (var m in targets) + { + Caster.DoHarmful(m); + SpellHelper.Damage(this, m, damage, 0, 0, 100, 0, 0); + } } - } + + FinishSequence(); } - double damage = GetNewAosDamage(51, 1, 5, pvp); - - foreach (Mobile m in targets) + public override void OnCast() { - Caster.DoHarmful(m); - SpellHelper.Damage(this, m, damage, 0, 0, 100, 0, 0); + Caster.Target = new SpellTargetPoint3D(this); } - } - FinishSequence(); + private static void PlayEffect(IPoint3D p, Map map) + { + Effects.PlaySound(p, map, 0x64F); + + PlaySingleEffect(p, map, -1, 1, -1, 1); + PlaySingleEffect(p, map, -2, 0, -3, -1); + PlaySingleEffect(p, map, -3, -1, -1, 1); + PlaySingleEffect(p, map, 1, 3, -1, 1); + PlaySingleEffect(p, map, -1, 1, 1, 3); + } + + private static void PlaySingleEffect(IPoint3D p, Map map, int a, int b, int c, int d) + { + int x = p.X, y = p.Y, z = p.Z + 18; + + SendEffectPacket(p, map, new Point3D(x + a, y + c, z), new Point3D(x + a, y + c, z)); + SendEffectPacket(p, map, new Point3D(x + b, y + c, z), new Point3D(x + b, y + c, z)); + SendEffectPacket(p, map, new Point3D(x + b, y + d, z), new Point3D(x + b, y + d, z)); + SendEffectPacket(p, map, new Point3D(x + a, y + d, z), new Point3D(x + a, y + d, z)); + + SendEffectPacket(p, map, new Point3D(x + b, y + c, z), new Point3D(x + a, y + c, z)); + SendEffectPacket(p, map, new Point3D(x + b, y + d, z), new Point3D(x + b, y + c, z)); + SendEffectPacket(p, map, new Point3D(x + a, y + d, z), new Point3D(x + b, y + d, z)); + SendEffectPacket(p, map, new Point3D(x + a, y + c, z), new Point3D(x + a, y + d, z)); + } + + private static void SendEffectPacket(IPoint3D p, Map map, Point3D orig, Point3D dest) + { + Effects.SendPacket( + p, + map, + new HuedEffect( + EffectType.Moving, + Serial.Zero, + Serial.Zero, + 0x36D4, + orig, + dest, + 0, + 0, + false, + false, + 0x63, + 0x4 + ) + ); + } } - - private static void PlayEffect(IPoint3D p, Map map) - { - Effects.PlaySound(p, map, 0x64F); - - PlaySingleEffect(p, map, -1, 1, -1, 1); - PlaySingleEffect(p, map, -2, 0, -3, -1); - PlaySingleEffect(p, map, -3, -1, -1, 1); - PlaySingleEffect(p, map, 1, 3, -1, 1); - PlaySingleEffect(p, map, -1, 1, 1, 3); - } - - private static void PlaySingleEffect(IPoint3D p, Map map, int a, int b, int c, int d) - { - int x = p.X, y = p.Y, z = p.Z + 18; - - SendEffectPacket(p, map, new Point3D(x + a, y + c, z), new Point3D(x + a, y + c, z)); - SendEffectPacket(p, map, new Point3D(x + b, y + c, z), new Point3D(x + b, y + c, z)); - SendEffectPacket(p, map, new Point3D(x + b, y + d, z), new Point3D(x + b, y + d, z)); - SendEffectPacket(p, map, new Point3D(x + a, y + d, z), new Point3D(x + a, y + d, z)); - - SendEffectPacket(p, map, new Point3D(x + b, y + c, z), new Point3D(x + a, y + c, z)); - SendEffectPacket(p, map, new Point3D(x + b, y + d, z), new Point3D(x + b, y + c, z)); - SendEffectPacket(p, map, new Point3D(x + a, y + d, z), new Point3D(x + b, y + d, z)); - SendEffectPacket(p, map, new Point3D(x + a, y + c, z), new Point3D(x + a, y + d, z)); - } - - private static void SendEffectPacket(IPoint3D p, Map map, Point3D orig, Point3D dest) - { - Effects.SendPacket(p, map, - new HuedEffect(EffectType.Moving, Serial.Zero, Serial.Zero, 0x36D4, orig, dest, 0, 0, false, false, 0x63, - 0x4)); - } - } } diff --git a/Projects/UOContent/Spells/Mysticism/MysticSpell.cs b/Projects/UOContent/Spells/Mysticism/MysticSpell.cs index 68947b422..2ec16128e 100644 --- a/Projects/UOContent/Spells/Mysticism/MysticSpell.cs +++ b/Projects/UOContent/Spells/Mysticism/MysticSpell.cs @@ -2,77 +2,81 @@ namespace Server.Spells.Mysticism { - public abstract class MysticSpell : Spell - { - public MysticSpell(Mobile caster, Item scroll, SpellInfo info) - : base(caster, scroll, info) + public abstract class MysticSpell : Spell { + public MysticSpell(Mobile caster, Item scroll, SpellInfo info) + : base(caster, scroll, info) + { + } + + public abstract double RequiredSkill { get; } + public abstract int RequiredMana { get; } + + public override SkillName CastSkill => SkillName.Mysticism; + + /* + * As per OSI Publish 64: + * Imbuing is not the only skill associated with Mysticism now. + * Players can use EITHER their Focus skill or Imbuing skill. + * Evaluate Intelligence no longer has any effect on a Mystic’s spell power. + */ + public override double GetDamageSkill(Mobile m) => Math.Max(m.Skills.Imbuing.Value, m.Skills.Focus.Value); + + public override int GetDamageFixed(Mobile m) => Math.Max(m.Skills.Imbuing.Fixed, m.Skills.Focus.Fixed); + + public override void GetCastSkills(out double min, out double max) + { + // As per Mysticism page at the UO Herald Playguide + // This means that we have 25% success chance at min Required Skill + + min = RequiredSkill - 12.5; + max = RequiredSkill + 37.5; + } + + public override int GetMana() => RequiredMana; + + public override bool CheckCast() + { + if (!base.CheckCast()) + return false; + + var mana = ScaleMana(RequiredMana); + + if (Caster.Mana < mana) + { + Caster.SendLocalizedMessage( + 1060174, + mana.ToString() + ); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability. + return false; + } + + if (Caster.Skills[CastSkill].Value < RequiredSkill) + { + Caster.SendLocalizedMessage( + 1063013, + $"{RequiredSkill:F1}\t{CastSkill.ToString()}\t " + ); // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability. + return false; + } + + return true; + } + + public override void OnBeginCast() + { + base.OnBeginCast(); + + SendCastEffect(); + } + + public virtual void SendCastEffect() + { + Caster.FixedEffect(0x37C4, 10, (int)(GetCastDelay().TotalSeconds * 28), 0x66C, 3); + } + + public static double GetBaseSkill(Mobile m) => m.Skills.Mysticism.Value; + + public static double GetBoostSkill(Mobile m) => Math.Max(m.Skills.Imbuing.Value, m.Skills.Focus.Value); } - - public abstract double RequiredSkill { get; } - public abstract int RequiredMana { get; } - - public override SkillName CastSkill => SkillName.Mysticism; - - /* - * As per OSI Publish 64: - * Imbuing is not the only skill associated with Mysticism now. - * Players can use EITHER their Focus skill or Imbuing skill. - * Evaluate Intelligence no longer has any effect on a Mystic’s spell power. - */ - public override double GetDamageSkill(Mobile m) => Math.Max(m.Skills.Imbuing.Value, m.Skills.Focus.Value); - - public override int GetDamageFixed(Mobile m) => Math.Max(m.Skills.Imbuing.Fixed, m.Skills.Focus.Fixed); - - public override void GetCastSkills(out double min, out double max) - { - // As per Mysticism page at the UO Herald Playguide - // This means that we have 25% success chance at min Required Skill - - min = RequiredSkill - 12.5; - max = RequiredSkill + 37.5; - } - - public override int GetMana() => RequiredMana; - - public override bool CheckCast() - { - if (!base.CheckCast()) - return false; - - int mana = ScaleMana(RequiredMana); - - if (Caster.Mana < mana) - { - Caster.SendLocalizedMessage(1060174, - mana.ToString()); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability. - return false; - } - - if (Caster.Skills[CastSkill].Value < RequiredSkill) - { - Caster.SendLocalizedMessage(1063013, - $"{RequiredSkill:F1}\t{CastSkill.ToString()}\t "); // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability. - return false; - } - - return true; - } - - public override void OnBeginCast() - { - base.OnBeginCast(); - - SendCastEffect(); - } - - public virtual void SendCastEffect() - { - Caster.FixedEffect(0x37C4, 10, (int)(GetCastDelay().TotalSeconds * 28), 0x66C, 3); - } - - public static double GetBaseSkill(Mobile m) => m.Skills.Mysticism.Value; - - public static double GetBoostSkill(Mobile m) => Math.Max(m.Skills.Imbuing.Value, m.Skills.Focus.Value); - } } diff --git a/Projects/UOContent/Spells/Mysticism/NetherCycloneSpell.cs b/Projects/UOContent/Spells/Mysticism/NetherCycloneSpell.cs index 878f1c5bc..0865007d7 100644 --- a/Projects/UOContent/Spells/Mysticism/NetherCycloneSpell.cs +++ b/Projects/UOContent/Spells/Mysticism/NetherCycloneSpell.cs @@ -4,126 +4,143 @@ using Server.Network; namespace Server.Spells.Mysticism { - public class NetherCycloneSpell : MysticSpell, ISpellTargetingPoint3D - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Nether Cyclone", "Grav Hur", - -1, - 9002, - Reagent.MandrakeRoot, - Reagent.Nightshade, - Reagent.SulfurousAsh, - Reagent.Bloodmoss); - - public NetherCycloneSpell(Mobile caster, Item scroll = null) - : base(caster, scroll, m_Info) + public class NetherCycloneSpell : MysticSpell, ISpellTargetingPoint3D { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Nether Cyclone", + "Grav Hur", + -1, + 9002, + Reagent.MandrakeRoot, + Reagent.Nightshade, + Reagent.SulfurousAsh, + Reagent.Bloodmoss + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.5); - - public override double RequiredSkill => 83.0; - public override int RequiredMana => 50; - - public override void OnCast() - { - Caster.Target = new SpellTargetPoint3D(this); - } - - public void Target(IPoint3D p) - { - if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) - { - /* Summons a gale of lethal winds that strikes all Targets within a radius around - * the Target's Location, dealing chaos damage. In addition to inflicting damage, - * each Target of the Nether Cyclone temporarily loses a percentage of mana and - * stamina. The effectiveness of the Nether Cyclone is determined by a comparison - * between the Caster's Mysticism and either Focus or Imbuing (whichever is greater) - * skills and the Resisting Spells skill of the Target. - */ - - SpellHelper.Turn(Caster, p); - - if (p is Item item) - p = item.GetWorldLocation(); - - List targets = new List(); - - Map map = Caster.Map; - - bool pvp = false; - - if (map != null) + public NetherCycloneSpell(Mobile caster, Item scroll = null) + : base(caster, scroll, m_Info) { - PlayEffect(p, Caster.Map); + } - foreach (Mobile m in map.GetMobilesInRange(new Point3D(p), 2)) - { - if (m == Caster) - continue; + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.5); - if (SpellHelper.ValidIndirectTarget(Caster, m) && Caster.CanBeHarmful(m, false) && Caster.CanSee(m)) + public override double RequiredSkill => 83.0; + public override int RequiredMana => 50; + + public void Target(IPoint3D p) + { + if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) { - if (!Caster.InLOS(m)) - continue; + /* Summons a gale of lethal winds that strikes all Targets within a radius around + * the Target's Location, dealing chaos damage. In addition to inflicting damage, + * each Target of the Nether Cyclone temporarily loses a percentage of mana and + * stamina. The effectiveness of the Nether Cyclone is determined by a comparison + * between the Caster's Mysticism and either Focus or Imbuing (whichever is greater) + * skills and the Resisting Spells skill of the Target. + */ - targets.Add(m); + SpellHelper.Turn(Caster, p); - if (m.Player) - pvp = true; + if (p is Item item) + p = item.GetWorldLocation(); + + var targets = new List(); + + var map = Caster.Map; + + var pvp = false; + + if (map != null) + { + PlayEffect(p, Caster.Map); + + foreach (var m in map.GetMobilesInRange(new Point3D(p), 2)) + { + if (m == Caster) + continue; + + if (SpellHelper.ValidIndirectTarget(Caster, m) && Caster.CanBeHarmful(m, false) && Caster.CanSee(m)) + { + if (!Caster.InLOS(m)) + continue; + + targets.Add(m); + + if (m.Player) + pvp = true; + } + } + } + + var damage = GetNewAosDamage(51, 1, 5, pvp); + var reduction = (GetBaseSkill(Caster) + GetBoostSkill(Caster)) / 1200.0; + + foreach (var m in targets) + { + Caster.DoHarmful(m); + SpellHelper.Damage(this, m, damage, 0, 0, 0, 0, 0, 100); + + var resistedReduction = reduction - m.Skills.MagicResist.Value / 800.0; + + m.Stam -= (int)(m.StamMax * resistedReduction); + m.Mana -= (int)(m.ManaMax * resistedReduction); + } } - } + + FinishSequence(); } - int damage = GetNewAosDamage(51, 1, 5, pvp); - double reduction = (GetBaseSkill(Caster) + GetBoostSkill(Caster)) / 1200.0; - - foreach (Mobile m in targets) + public override void OnCast() { - Caster.DoHarmful(m); - SpellHelper.Damage(this, m, damage, 0, 0, 0, 0, 0, 100); - - double resistedReduction = reduction - m.Skills.MagicResist.Value / 800.0; - - m.Stam -= (int)(m.StamMax * resistedReduction); - m.Mana -= (int)(m.ManaMax * resistedReduction); + Caster.Target = new SpellTargetPoint3D(this); } - } - FinishSequence(); + private static void PlayEffect(IPoint3D p, Map map) + { + Effects.PlaySound(p, map, 0x64F); + + PlaySingleEffect(p, map, -1, 1, -1, 1); + PlaySingleEffect(p, map, -2, 0, -3, -1); + PlaySingleEffect(p, map, -3, -1, -1, 1); + PlaySingleEffect(p, map, 1, 3, -1, 1); + PlaySingleEffect(p, map, -1, 1, 1, 3); + } + + private static void PlaySingleEffect(IPoint3D p, Map map, int a, int b, int c, int d) + { + int x = p.X, y = p.Y, z = p.Z + 18; + + SendEffectPacket(p, map, new Point3D(x + a, y + c, z), new Point3D(x + a, y + c, z)); + SendEffectPacket(p, map, new Point3D(x + b, y + c, z), new Point3D(x + b, y + c, z)); + SendEffectPacket(p, map, new Point3D(x + b, y + d, z), new Point3D(x + b, y + d, z)); + SendEffectPacket(p, map, new Point3D(x + a, y + d, z), new Point3D(x + a, y + d, z)); + + SendEffectPacket(p, map, new Point3D(x + b, y + c, z), new Point3D(x + a, y + c, z)); + SendEffectPacket(p, map, new Point3D(x + b, y + d, z), new Point3D(x + b, y + c, z)); + SendEffectPacket(p, map, new Point3D(x + a, y + d, z), new Point3D(x + b, y + d, z)); + SendEffectPacket(p, map, new Point3D(x + a, y + c, z), new Point3D(x + a, y + d, z)); + } + + private static void SendEffectPacket(IPoint3D p, Map map, Point3D orig, Point3D dest) + { + Effects.SendPacket( + p, + map, + new HuedEffect( + EffectType.Moving, + Serial.Zero, + Serial.Zero, + 0x375A, + orig, + dest, + 0, + 0, + false, + false, + 0x49A, + 0x4 + ) + ); + } } - - private static void PlayEffect(IPoint3D p, Map map) - { - Effects.PlaySound(p, map, 0x64F); - - PlaySingleEffect(p, map, -1, 1, -1, 1); - PlaySingleEffect(p, map, -2, 0, -3, -1); - PlaySingleEffect(p, map, -3, -1, -1, 1); - PlaySingleEffect(p, map, 1, 3, -1, 1); - PlaySingleEffect(p, map, -1, 1, 1, 3); - } - - private static void PlaySingleEffect(IPoint3D p, Map map, int a, int b, int c, int d) - { - int x = p.X, y = p.Y, z = p.Z + 18; - - SendEffectPacket(p, map, new Point3D(x + a, y + c, z), new Point3D(x + a, y + c, z)); - SendEffectPacket(p, map, new Point3D(x + b, y + c, z), new Point3D(x + b, y + c, z)); - SendEffectPacket(p, map, new Point3D(x + b, y + d, z), new Point3D(x + b, y + d, z)); - SendEffectPacket(p, map, new Point3D(x + a, y + d, z), new Point3D(x + a, y + d, z)); - - SendEffectPacket(p, map, new Point3D(x + b, y + c, z), new Point3D(x + a, y + c, z)); - SendEffectPacket(p, map, new Point3D(x + b, y + d, z), new Point3D(x + b, y + c, z)); - SendEffectPacket(p, map, new Point3D(x + a, y + d, z), new Point3D(x + b, y + d, z)); - SendEffectPacket(p, map, new Point3D(x + a, y + c, z), new Point3D(x + a, y + d, z)); - } - - private static void SendEffectPacket(IPoint3D p, Map map, Point3D orig, Point3D dest) - { - Effects.SendPacket(p, map, - new HuedEffect(EffectType.Moving, Serial.Zero, Serial.Zero, 0x375A, orig, dest, 0, 0, false, false, 0x49A, - 0x4)); - } - } } diff --git a/Projects/UOContent/Spells/Mysticism/SpellPlagueSpell.cs b/Projects/UOContent/Spells/Mysticism/SpellPlagueSpell.cs index e475e8876..b8fa67baa 100644 --- a/Projects/UOContent/Spells/Mysticism/SpellPlagueSpell.cs +++ b/Projects/UOContent/Spells/Mysticism/SpellPlagueSpell.cs @@ -4,208 +4,215 @@ using Server.Targeting; namespace Server.Spells.Mysticism { - public class SpellPlagueSpell : MysticSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Spell Plague", "Vas Rel Jux Ort", - -1, - 9002, - Reagent.DaemonBone, - Reagent.DragonsBlood, - Reagent.Nightshade, - Reagent.SulfurousAsh); - - private static readonly Dictionary m_Table = new Dictionary(); - - public SpellPlagueSpell(Mobile caster, Item scroll = null) - : base(caster, scroll, m_Info) + public class SpellPlagueSpell : MysticSpell { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Spell Plague", + "Vas Rel Jux Ort", + -1, + 9002, + Reagent.DaemonBone, + Reagent.DragonsBlood, + Reagent.Nightshade, + Reagent.SulfurousAsh + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.25); + private static readonly Dictionary + m_Table = new Dictionary(); - public override double RequiredSkill => 70.0; - public override int RequiredMana => 40; - - public static void Initialize() - { - EventSink.PlayerDeath += OnPlayerDeath; - } - - public override void OnCast() - { - Caster.Target = new InternalTarget(this); - } - - public void Target(Mobile targeted) - { - if (!Caster.CanSee(targeted)) - { - Caster.SendLocalizedMessage(500237); // Target can not be seen. - } - else if (CheckHSequence(targeted)) - { - SpellHelper.Turn(Caster, targeted); - - SpellHelper.CheckReflect(6, Caster, ref targeted); - - /* The target is hit with an explosion of chaos damage and then inflicted - * with the spell plague curse. Each time the target is damaged while under - * the effect of the spell plague, they may suffer an explosion of chaos - * damage. The initial chance to trigger the explosion starts at 90% and - * reduces by 30% every time an explosion occurs. Once the target is - * afflicted by 3 explosions or 8 seconds have passed, that spell plague - * is removed from the target. Spell Plague will stack with other spell - * plagues so that they are applied one after the other. - */ - - VisualEffect(targeted); - - int damage = GetNewAosDamage(33, 1, 5, targeted); - SpellHelper.Damage(this, targeted, damage, 0, 0, 0, 0, 0); - - SpellPlagueContext context = new SpellPlagueContext(this, targeted); - - if (m_Table.TryGetValue(targeted, out SpellPlagueContext oldContext)) - oldContext.SetNext(context); - else + public SpellPlagueSpell(Mobile caster, Item scroll = null) + : base(caster, scroll, m_Info) { - m_Table[targeted] = context; - context.Start(); } - } - FinishSequence(); - } + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.25); - public static bool UnderEffect(Mobile m) => m_Table.ContainsKey(m); + public override double RequiredSkill => 70.0; + public override int RequiredMana => 40; - public static void RemoveEffect(Mobile m) - { - if (m_Table.TryGetValue(m, out SpellPlagueContext context)) - context.EndPlague(false); - } - - public static void CheckPlague(Mobile m) - { - if (m_Table.TryGetValue(m, out SpellPlagueContext context)) - context.OnDamage(); - } - - private static void OnPlayerDeath(Mobile m) - { - RemoveEffect(m); - } - - protected void VisualEffect(Mobile to) - { - to.PlaySound(0x658); - - to.FixedParticles(0x3728, 1, 13, 0x26B8, 0x47E, 7, EffectLayer.Head, 0); - to.FixedParticles(0x3779, 1, 15, 0x251E, 0x43, 7, EffectLayer.Head, 0); - } - - private class SpellPlagueContext - { - private int m_Explosions; - private DateTime m_LastExploded; - private SpellPlagueContext m_Next; - private readonly SpellPlagueSpell m_Owner; - private readonly Mobile m_Target; - private Timer m_Timer; - - public SpellPlagueContext(SpellPlagueSpell owner, Mobile target) - { - m_Owner = owner; - m_Target = target; - } - - public void SetNext(SpellPlagueContext context) - { - if (m_Next == null) - m_Next = context; - else - m_Next.SetNext(context); - } - - public void Start() - { - m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(8.0), EndPlague); - m_Timer.Start(); - - BuffInfo.AddBuff(m_Target, - new BuffInfo(BuffIcon.SpellPlague, 1031690, 1080167, TimeSpan.FromSeconds(8.5), m_Target)); - } - - public void OnDamage() - { - if (DateTime.Now > m_LastExploded + TimeSpan.FromSeconds(2.0)) + public static void Initialize() { - int exploChance = 90 - m_Explosions * 30; - - double resist = m_Target.Skills.MagicResist.Value; - - if (resist >= 70) - exploChance -= (int)((resist - 70.0) * 3.0 / 10.0); - - if (exploChance > Utility.Random(100)) - { - m_Owner.VisualEffect(m_Target); - - int damage = m_Owner.GetNewAosDamage(15 + m_Explosions * 3, 1, 5, m_Target); - - m_Explosions++; - m_LastExploded = DateTime.Now; - - SpellHelper.Damage(m_Owner, m_Target, damage, 0, 0, 0, 0, 0, 100); - - if (m_Explosions >= 3) - EndPlague(); - } + EventSink.PlayerDeath += OnPlayerDeath; } - } - private void EndPlague() - { - EndPlague(true); - } - - public void EndPlague(bool restart) - { - m_Timer?.Stop(); - - if (restart && m_Next != null) + public override void OnCast() { - m_Table[m_Target] = m_Next; - m_Next.Start(); + Caster.Target = new InternalTarget(this); } - else + + public void Target(Mobile targeted) { - m_Table.Remove(m_Target); + if (!Caster.CanSee(targeted)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckHSequence(targeted)) + { + SpellHelper.Turn(Caster, targeted); - BuffInfo.RemoveBuff(m_Target, BuffIcon.SpellPlague); + SpellHelper.CheckReflect(6, Caster, ref targeted); + + /* The target is hit with an explosion of chaos damage and then inflicted + * with the spell plague curse. Each time the target is damaged while under + * the effect of the spell plague, they may suffer an explosion of chaos + * damage. The initial chance to trigger the explosion starts at 90% and + * reduces by 30% every time an explosion occurs. Once the target is + * afflicted by 3 explosions or 8 seconds have passed, that spell plague + * is removed from the target. Spell Plague will stack with other spell + * plagues so that they are applied one after the other. + */ + + VisualEffect(targeted); + + var damage = GetNewAosDamage(33, 1, 5, targeted); + SpellHelper.Damage(this, targeted, damage, 0, 0, 0, 0, 0); + + var context = new SpellPlagueContext(this, targeted); + + if (m_Table.TryGetValue(targeted, out var oldContext)) + { + oldContext.SetNext(context); + } + else + { + m_Table[targeted] = context; + context.Start(); + } + } + + FinishSequence(); + } + + public static bool UnderEffect(Mobile m) => m_Table.ContainsKey(m); + + public static void RemoveEffect(Mobile m) + { + if (m_Table.TryGetValue(m, out var context)) + context.EndPlague(false); + } + + public static void CheckPlague(Mobile m) + { + if (m_Table.TryGetValue(m, out var context)) + context.OnDamage(); + } + + private static void OnPlayerDeath(Mobile m) + { + RemoveEffect(m); + } + + protected void VisualEffect(Mobile to) + { + to.PlaySound(0x658); + + to.FixedParticles(0x3728, 1, 13, 0x26B8, 0x47E, 7, EffectLayer.Head, 0); + to.FixedParticles(0x3779, 1, 15, 0x251E, 0x43, 7, EffectLayer.Head, 0); + } + + private class SpellPlagueContext + { + private readonly SpellPlagueSpell m_Owner; + private readonly Mobile m_Target; + private int m_Explosions; + private DateTime m_LastExploded; + private SpellPlagueContext m_Next; + private Timer m_Timer; + + public SpellPlagueContext(SpellPlagueSpell owner, Mobile target) + { + m_Owner = owner; + m_Target = target; + } + + public void SetNext(SpellPlagueContext context) + { + if (m_Next == null) + m_Next = context; + else + m_Next.SetNext(context); + } + + public void Start() + { + m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(8.0), EndPlague); + m_Timer.Start(); + + BuffInfo.AddBuff( + m_Target, + new BuffInfo(BuffIcon.SpellPlague, 1031690, 1080167, TimeSpan.FromSeconds(8.5), m_Target) + ); + } + + public void OnDamage() + { + if (DateTime.Now > m_LastExploded + TimeSpan.FromSeconds(2.0)) + { + var exploChance = 90 - m_Explosions * 30; + + var resist = m_Target.Skills.MagicResist.Value; + + if (resist >= 70) + exploChance -= (int)((resist - 70.0) * 3.0 / 10.0); + + if (exploChance > Utility.Random(100)) + { + m_Owner.VisualEffect(m_Target); + + var damage = m_Owner.GetNewAosDamage(15 + m_Explosions * 3, 1, 5, m_Target); + + m_Explosions++; + m_LastExploded = DateTime.Now; + + SpellHelper.Damage(m_Owner, m_Target, damage, 0, 0, 0, 0, 0, 100); + + if (m_Explosions >= 3) + EndPlague(); + } + } + } + + private void EndPlague() + { + EndPlague(true); + } + + public void EndPlague(bool restart) + { + m_Timer?.Stop(); + + if (restart && m_Next != null) + { + m_Table[m_Target] = m_Next; + m_Next.Start(); + } + else + { + m_Table.Remove(m_Target); + + BuffInfo.RemoveBuff(m_Target, BuffIcon.SpellPlague); + } + } + } + + private class InternalTarget : Target + { + private readonly SpellPlagueSpell m_Owner; + + public InternalTarget(SpellPlagueSpell owner) + : base(12, false, TargetFlags.Harmful) => + m_Owner = owner; + + protected override void OnTarget(Mobile from, object o) + { + if (o is Mobile mobile) + m_Owner.Target(mobile); + } + + protected override void OnTargetFinish(Mobile from) + { + m_Owner.FinishSequence(); + } } - } } - - private class InternalTarget : Target - { - private readonly SpellPlagueSpell m_Owner; - - public InternalTarget(SpellPlagueSpell owner) - : base(12, false, TargetFlags.Harmful) => - m_Owner = owner; - - protected override void OnTarget(Mobile from, object o) - { - if (o is Mobile mobile) - m_Owner.Target(mobile); - } - - protected override void OnTargetFinish(Mobile from) - { - m_Owner.FinishSequence(); - } - } - } } diff --git a/Projects/UOContent/Spells/Mysticism/StoneFormSpell.cs b/Projects/UOContent/Spells/Mysticism/StoneFormSpell.cs index c5d553399..2b45c1156 100644 --- a/Projects/UOContent/Spells/Mysticism/StoneFormSpell.cs +++ b/Projects/UOContent/Spells/Mysticism/StoneFormSpell.cs @@ -1,153 +1,163 @@ using System; using System.Collections.Generic; using Server.Factions; -using Server.Mobiles; using Server.Spells.Fifth; using Server.Spells.Ninjitsu; using Server.Spells.Seventh; namespace Server.Spells.Mysticism { - public class StoneFormSpell : MysticSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Stone Form", "In Rel Ylem", - -1, - 9002, - Reagent.Bloodmoss, - Reagent.FertileDirt, - Reagent.Garlic); - - private static readonly Dictionary m_Table = new Dictionary(); - - public StoneFormSpell(Mobile caster, Item scroll = null) - : base(caster, scroll, m_Info) + public class StoneFormSpell : MysticSpell { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Stone Form", + "In Rel Ylem", + -1, + 9002, + Reagent.Bloodmoss, + Reagent.FertileDirt, + Reagent.Garlic + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); + private static readonly Dictionary m_Table = new Dictionary(); - public override double RequiredSkill => 33.0; - public override int RequiredMana => 11; - - public static void Initialize() - { - EventSink.PlayerDeath += OnPlayerDeath; - } - - public static bool UnderEffect(Mobile m) => m_Table.ContainsKey(m); - - public override bool CheckCast() - { - if (Sigil.ExistsOn(Caster)) - { - Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. - return false; - } - - if (!Caster.CanBeginAction()) - { - Caster.SendLocalizedMessage(1061628); // You can't do that while polymorphed. - return false; - } - - if (AnimalForm.UnderTransformation(Caster)) - { - Caster.SendLocalizedMessage(1063218); // You cannot use that ability in this form. - return false; - } - - if (Caster.Flying) - { - Caster.SendLocalizedMessage(1113415); // You cannot use this ability while flying. - return false; - } - - return base.CheckCast(); - } - - public override void OnCast() - { - if (Sigil.ExistsOn(Caster)) - { - Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. - } - else if (!Caster.CanBeginAction()) - { - Caster.SendLocalizedMessage(1061628); // You can't do that while polymorphed. - } - else if (!Caster.CanBeginAction() || (Caster.IsBodyMod && !UnderEffect(Caster))) - { - Caster.SendLocalizedMessage(1063218); // You cannot use that ability in this form. - } - else if (CheckSequence()) - { - if (UnderEffect(Caster)) + public StoneFormSpell(Mobile caster, Item scroll = null) + : base(caster, scroll, m_Info) { - RemoveEffects(Caster); - - Caster.PlaySound(0xFA); - Caster.Delta(MobileDelta.Resistances); } - else + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); + + public override double RequiredSkill => 33.0; + public override int RequiredMana => 11; + + public static void Initialize() { - IMount mount = Caster.Mount; - - if (mount != null) - mount.Rider = null; - - Caster.BodyMod = 0x2C1; - Caster.HueMod = 0; - - int offset = (int)((GetBaseSkill(Caster) + GetBoostSkill(Caster)) / 24.0); - - ResistanceMod[] mods = { - new ResistanceMod(ResistanceType.Physical, offset), - new ResistanceMod(ResistanceType.Fire, offset), - new ResistanceMod(ResistanceType.Cold, offset), - new ResistanceMod(ResistanceType.Poison, offset), - new ResistanceMod(ResistanceType.Energy, offset) - }; - - for (int i = 0; i < mods.Length; ++i) - Caster.AddResistanceMod(mods[i]); - - m_Table[Caster] = mods; - - Caster.PlaySound(0x65A); - Caster.Delta(MobileDelta.Resistances); - - BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.StoneForm, 1080145, 1080146, - $"-10\t-2\t{offset}\t{GetResistCapBonus(Caster)}\t{GetDIBonus(Caster)}", false)); + EventSink.PlayerDeath += OnPlayerDeath; } - } - FinishSequence(); + public static bool UnderEffect(Mobile m) => m_Table.ContainsKey(m); + + public override bool CheckCast() + { + if (Sigil.ExistsOn(Caster)) + { + Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. + return false; + } + + if (!Caster.CanBeginAction()) + { + Caster.SendLocalizedMessage(1061628); // You can't do that while polymorphed. + return false; + } + + if (AnimalForm.UnderTransformation(Caster)) + { + Caster.SendLocalizedMessage(1063218); // You cannot use that ability in this form. + return false; + } + + if (Caster.Flying) + { + Caster.SendLocalizedMessage(1113415); // You cannot use this ability while flying. + return false; + } + + return base.CheckCast(); + } + + public override void OnCast() + { + if (Sigil.ExistsOn(Caster)) + { + Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. + } + else if (!Caster.CanBeginAction()) + { + Caster.SendLocalizedMessage(1061628); // You can't do that while polymorphed. + } + else if (!Caster.CanBeginAction() || Caster.IsBodyMod && !UnderEffect(Caster)) + { + Caster.SendLocalizedMessage(1063218); // You cannot use that ability in this form. + } + else if (CheckSequence()) + { + if (UnderEffect(Caster)) + { + RemoveEffects(Caster); + + Caster.PlaySound(0xFA); + Caster.Delta(MobileDelta.Resistances); + } + else + { + var mount = Caster.Mount; + + if (mount != null) + mount.Rider = null; + + Caster.BodyMod = 0x2C1; + Caster.HueMod = 0; + + var offset = (int)((GetBaseSkill(Caster) + GetBoostSkill(Caster)) / 24.0); + + ResistanceMod[] mods = + { + new ResistanceMod(ResistanceType.Physical, offset), + new ResistanceMod(ResistanceType.Fire, offset), + new ResistanceMod(ResistanceType.Cold, offset), + new ResistanceMod(ResistanceType.Poison, offset), + new ResistanceMod(ResistanceType.Energy, offset) + }; + + for (var i = 0; i < mods.Length; ++i) + Caster.AddResistanceMod(mods[i]); + + m_Table[Caster] = mods; + + Caster.PlaySound(0x65A); + Caster.Delta(MobileDelta.Resistances); + + BuffInfo.AddBuff( + Caster, + new BuffInfo( + BuffIcon.StoneForm, + 1080145, + 1080146, + $"-10\t-2\t{offset}\t{GetResistCapBonus(Caster)}\t{GetDIBonus(Caster)}", + false + ) + ); + } + } + + FinishSequence(); + } + + public static int GetDIBonus(Mobile m) => (int)((GetBaseSkill(m) + GetBoostSkill(m)) / 12.0); + + public static int GetResistCapBonus(Mobile m) => (int)((GetBaseSkill(m) + GetBoostSkill(m)) / 48.0); + + public static void RemoveEffects(Mobile m) + { + if (!m_Table.TryGetValue(m, out var mods)) + return; + + for (var i = 0; i < mods.Length; ++i) + m.RemoveResistanceMod(mods[i]); + + m.BodyMod = 0; + m.HueMod = -1; + + m_Table.Remove(m); + + BuffInfo.RemoveBuff(m, BuffIcon.StoneForm); + } + + private static void OnPlayerDeath(Mobile m) + { + RemoveEffects(m); + } } - - public static int GetDIBonus(Mobile m) => (int)((GetBaseSkill(m) + GetBoostSkill(m)) / 12.0); - - public static int GetResistCapBonus(Mobile m) => (int)((GetBaseSkill(m) + GetBoostSkill(m)) / 48.0); - - public static void RemoveEffects(Mobile m) - { - if (!m_Table.TryGetValue(m, out ResistanceMod[] mods)) - return; - - for (int i = 0; i < mods.Length; ++i) - m.RemoveResistanceMod(mods[i]); - - m.BodyMod = 0; - m.HueMod = -1; - - m_Table.Remove(m); - - BuffInfo.RemoveBuff(m, BuffIcon.StoneForm); - } - - private static void OnPlayerDeath(Mobile m) - { - RemoveEffects(m); - } - } } diff --git a/Projects/UOContent/Spells/Necromancy/AnimateDeadSpell.cs b/Projects/UOContent/Spells/Necromancy/AnimateDeadSpell.cs index a45e3ff15..6b0915d72 100644 --- a/Projects/UOContent/Spells/Necromancy/AnimateDeadSpell.cs +++ b/Projects/UOContent/Spells/Necromancy/AnimateDeadSpell.cs @@ -9,355 +9,381 @@ using Server.Utilities; namespace Server.Spells.Necromancy { - public class AnimateDeadSpell : NecromancerSpell, ISpellTargetingItem - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Animate Dead", "Uus Corp", - 203, - 9031, - Reagent.GraveDust, - Reagent.DaemonBlood); - - private static readonly CreatureGroup[] m_Groups = + public class AnimateDeadSpell : NecromancerSpell, ISpellTargetingItem { - // Undead group--empty - new CreatureGroup(SlayerGroup.GetEntryByName(SlayerName.Silver).Types, Array.Empty()), - // Insects - new CreatureGroup(new[] + private static readonly SpellInfo m_Info = new SpellInfo( + "Animate Dead", + "Uus Corp", + 203, + 9031, + Reagent.GraveDust, + Reagent.DaemonBlood + ); + + private static readonly CreatureGroup[] m_Groups = { - typeof(DreadSpider), typeof(FrostSpider), typeof(GiantSpider), typeof(GiantBlackWidow), - typeof(BlackSolenInfiltratorQueen), typeof(BlackSolenInfiltratorWarrior), - typeof(BlackSolenQueen), typeof(BlackSolenWarrior), typeof(BlackSolenWorker), - typeof(RedSolenInfiltratorQueen), typeof(RedSolenInfiltratorWarrior), - typeof(RedSolenQueen), typeof(RedSolenWarrior), typeof(RedSolenWorker), - typeof(TerathanAvenger), typeof(TerathanDrone), typeof(TerathanMatriarch), - typeof(TerathanWarrior) - // TODO: Giant beetle? Ant lion? Ophidians? - }, - new[] + // Undead group--empty + new CreatureGroup(SlayerGroup.GetEntryByName(SlayerName.Silver).Types, Array.Empty()), + // Insects + new CreatureGroup( + new[] + { + typeof(DreadSpider), typeof(FrostSpider), typeof(GiantSpider), typeof(GiantBlackWidow), + typeof(BlackSolenInfiltratorQueen), typeof(BlackSolenInfiltratorWarrior), + typeof(BlackSolenQueen), typeof(BlackSolenWarrior), typeof(BlackSolenWorker), + typeof(RedSolenInfiltratorQueen), typeof(RedSolenInfiltratorWarrior), + typeof(RedSolenQueen), typeof(RedSolenWarrior), typeof(RedSolenWorker), + typeof(TerathanAvenger), typeof(TerathanDrone), typeof(TerathanMatriarch), + typeof(TerathanWarrior) + // TODO: Giant beetle? Ant lion? Ophidians? + }, + new[] + { + new SummonEntry(0, typeof(MoundOfMaggots)) + } + ), + // Mounts + new CreatureGroup( + new[] + { + typeof(Horse), typeof(Nightmare), typeof(FireSteed), + typeof(Kirin), typeof(Unicorn) + }, + new[] + { + new SummonEntry(10000, typeof(HellSteed)), + new SummonEntry(0, typeof(SkeletalMount)) + } + ), + // Elementals + new CreatureGroup( + new[] + { + typeof(BloodElemental), typeof(EarthElemental), typeof(SummonedEarthElemental), + typeof(AgapiteElemental), typeof(BronzeElemental), typeof(CopperElemental), + typeof(DullCopperElemental), typeof(GoldenElemental), typeof(ShadowIronElemental), + typeof(ValoriteElemental), typeof(VeriteElemental), typeof(PoisonElemental), + typeof(FireElemental), typeof(SummonedFireElemental), typeof(SnowElemental), + typeof(AirElemental), typeof(SummonedAirElemental), typeof(WaterElemental), + typeof(SummonedAirElemental), typeof(AcidElemental) + }, + new[] + { + new SummonEntry(5000, typeof(WailingBanshee)), + new SummonEntry(0, typeof(Wraith)) + } + ), + // Dragons + new CreatureGroup( + new[] + { + typeof(AncientWyrm), typeof(Dragon), typeof(GreaterDragon), typeof(SerpentineDragon), + typeof(ShadowWyrm), typeof(SkeletalDragon), typeof(WhiteWyrm), + typeof(Drake), typeof(Wyvern), typeof(LesserHiryu), typeof(Hiryu) + }, + new[] + { + new SummonEntry(18000, typeof(SkeletalDragon)), + new SummonEntry(10000, typeof(FleshGolem)), + new SummonEntry(5000, typeof(Lich)), + new SummonEntry(3000, typeof(SkeletalKnight), typeof(BoneKnight)), + new SummonEntry(2000, typeof(Mummy)), + new SummonEntry(1000, typeof(SkeletalMage), typeof(BoneMagi)), + new SummonEntry(0, typeof(PatchworkSkeleton)) + } + ), + // Default group + new CreatureGroup( + Array.Empty(), + new[] + { + new SummonEntry(18000, typeof(LichLord)), + new SummonEntry(10000, typeof(FleshGolem)), + new SummonEntry(5000, typeof(Lich)), + new SummonEntry(3000, typeof(SkeletalKnight), typeof(BoneKnight)), + new SummonEntry(2000, typeof(Mummy)), + new SummonEntry(1000, typeof(SkeletalMage), typeof(BoneMagi)), + new SummonEntry(0, typeof(PatchworkSkeleton)) + } + ) + }; + + private static readonly Dictionary> m_Table = new Dictionary>(); + + public AnimateDeadSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - new SummonEntry(0, typeof(MoundOfMaggots)) - }), - // Mounts - new CreatureGroup(new[] - { - typeof(Horse), typeof(Nightmare), typeof(FireSteed), - typeof(Kirin), typeof(Unicorn) - }, new[] - { - new SummonEntry(10000, typeof(HellSteed)), - new SummonEntry(0, typeof(SkeletalMount)) - }), - // Elementals - new CreatureGroup(new[] - { - typeof(BloodElemental), typeof(EarthElemental), typeof(SummonedEarthElemental), - typeof(AgapiteElemental), typeof(BronzeElemental), typeof(CopperElemental), - typeof(DullCopperElemental), typeof(GoldenElemental), typeof(ShadowIronElemental), - typeof(ValoriteElemental), typeof(VeriteElemental), typeof(PoisonElemental), - typeof(FireElemental), typeof(SummonedFireElemental), typeof(SnowElemental), - typeof(AirElemental), typeof(SummonedAirElemental), typeof(WaterElemental), - typeof(SummonedAirElemental), typeof(AcidElemental) - }, new[] - { - new SummonEntry(5000, typeof(WailingBanshee)), - new SummonEntry(0, typeof(Wraith)) - }), - // Dragons - new CreatureGroup(new[] - { - typeof(AncientWyrm), typeof(Dragon), typeof(GreaterDragon), typeof(SerpentineDragon), - typeof(ShadowWyrm), typeof(SkeletalDragon), typeof(WhiteWyrm), - typeof(Drake), typeof(Wyvern), typeof(LesserHiryu), typeof(Hiryu) - }, new[] - { - new SummonEntry(18000, typeof(SkeletalDragon)), - new SummonEntry(10000, typeof(FleshGolem)), - new SummonEntry(5000, typeof(Lich)), - new SummonEntry(3000, typeof(SkeletalKnight), typeof(BoneKnight)), - new SummonEntry(2000, typeof(Mummy)), - new SummonEntry(1000, typeof(SkeletalMage), typeof(BoneMagi)), - new SummonEntry(0, typeof(PatchworkSkeleton)) - }), - // Default group - new CreatureGroup(Array.Empty(), new[] - { - new SummonEntry(18000, typeof(LichLord)), - new SummonEntry(10000, typeof(FleshGolem)), - new SummonEntry(5000, typeof(Lich)), - new SummonEntry(3000, typeof(SkeletalKnight), typeof(BoneKnight)), - new SummonEntry(2000, typeof(Mummy)), - new SummonEntry(1000, typeof(SkeletalMage), typeof(BoneMagi)), - new SummonEntry(0, typeof(PatchworkSkeleton)) - }) - }; - - private static readonly Dictionary> m_Table = new Dictionary>(); - - public AnimateDeadSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) - { - } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); - - public override double RequiredSkill => 40.0; - public override int RequiredMana => 23; - - public override void OnCast() - { - Caster.Target = new SpellTargetItem(this, TargetFlags.None, Core.ML ? 10 : 12); - Caster.SendLocalizedMessage(1061083); // Animate what corpse? - } - - private static CreatureGroup FindGroup(Type type) - { - for (int i = 0; i < m_Groups.Length; ++i) - { - CreatureGroup group = m_Groups[i]; - Type[] types = group.m_Types; - - bool contains = types.Length == 0; - - for (int j = 0; !contains && j < types.Length; ++j) - contains = types[j].IsAssignableFrom(type); - - if (contains) - return group; - } - - return null; - } - - public void Target(Item item) - { - MaabusCoffinComponent comp = item as MaabusCoffinComponent; - - if (comp?.Addon is MaabusCoffin addon) - { - PlayerMobile pm = Caster as PlayerMobile; - - QuestSystem qs = pm?.Quest; - - if (qs is DarkTidesQuest) - { - QuestObjective objective = qs.FindObjective(); - - if (objective?.Completed == false) - { - addon.Awake(Caster); - objective.Complete(); - } } - return; - } + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); - if (!(item is Corpse c)) - { - Caster.SendLocalizedMessage(1061084); // You cannot animate that. - } - else - { - Type type = null; + public override double RequiredSkill => 40.0; + public override int RequiredMana => 23; - if (c.Owner != null) type = c.Owner.GetType(); - - if (c.ItemID != 0x2006 || c.Animated || type == typeof(PlayerMobile) || type == null || - c.Owner != null && c.Owner.Fame < 100 || - c.Owner is BaseCreature creature && (creature.Summoned || creature.IsBonded)) + public void Target(Item item) { - Caster.SendLocalizedMessage(1061085); // There's not enough life force there to animate. - } - else - { - CreatureGroup group = FindGroup(type); + var comp = item as MaabusCoffinComponent; - if (group != null) - { - if (group.m_Entries.Length == 0 || type == typeof(DemonKnight)) + if (comp?.Addon is MaabusCoffin addon) { - Caster.SendLocalizedMessage(1061086); // You cannot animate undead remains. + var pm = Caster as PlayerMobile; + + var qs = pm?.Quest; + + if (qs is DarkTidesQuest) + { + QuestObjective objective = qs.FindObjective(); + + if (objective?.Completed == false) + { + addon.Awake(Caster); + objective.Complete(); + } + } + + return; } - else if (CheckSequence()) + + if (!(item is Corpse c)) { - Point3D p = c.GetWorldLocation(); - Map map = c.Map; - - if (map != null) - { - Effects.PlaySound(p, map, 0x1FB); - Effects.SendLocationParticles(EffectItem.Create(p, map, EffectItem.DefaultDuration), 0x3789, - 1, 40, 0x3F, 3, 9907, 0); - - Timer.DelayCall(TimeSpan.FromSeconds(2.0), - () => SummonDelay_Callback(Caster, c, p, map, group)); - } + Caster.SendLocalizedMessage(1061084); // You cannot animate that. } - } + else + { + Type type = null; + + if (c.Owner != null) type = c.Owner.GetType(); + + if (c.ItemID != 0x2006 || c.Animated || type == typeof(PlayerMobile) || type == null || + c.Owner != null && c.Owner.Fame < 100 || + c.Owner is BaseCreature creature && (creature.Summoned || creature.IsBonded)) + { + Caster.SendLocalizedMessage(1061085); // There's not enough life force there to animate. + } + else + { + var group = FindGroup(type); + + if (group != null) + { + if (group.m_Entries.Length == 0 || type == typeof(DemonKnight)) + { + Caster.SendLocalizedMessage(1061086); // You cannot animate undead remains. + } + else if (CheckSequence()) + { + var p = c.GetWorldLocation(); + var map = c.Map; + + if (map != null) + { + Effects.PlaySound(p, map, 0x1FB); + Effects.SendLocationParticles( + EffectItem.Create(p, map, EffectItem.DefaultDuration), + 0x3789, + 1, + 40, + 0x3F, + 3, + 9907, + 0 + ); + + Timer.DelayCall( + TimeSpan.FromSeconds(2.0), + () => SummonDelay_Callback(Caster, c, p, map, group) + ); + } + } + } + } + } + + FinishSequence(); } - } - FinishSequence(); + public override void OnCast() + { + Caster.Target = new SpellTargetItem(this, TargetFlags.None, Core.ML ? 10 : 12); + Caster.SendLocalizedMessage(1061083); // Animate what corpse? + } + + private static CreatureGroup FindGroup(Type type) + { + for (var i = 0; i < m_Groups.Length; ++i) + { + var group = m_Groups[i]; + var types = group.m_Types; + + var contains = types.Length == 0; + + for (var j = 0; !contains && j < types.Length; ++j) + contains = types[j].IsAssignableFrom(type); + + if (contains) + return group; + } + + return null; + } + + public static void Unregister(Mobile master, Mobile summoned) + { + if (master == null) + return; + + if (!m_Table.TryGetValue(master, out var list)) + return; + + list.Remove(summoned); + + if (list.Count == 0) + m_Table.Remove(master); + } + + public static void Register(Mobile master, Mobile summoned) + { + if (master == null) + return; + + if (!m_Table.TryGetValue(master, out var list)) + m_Table[master] = list = new List(); + + for (var i = list.Count - 1; i >= 0; --i) + { + if (i >= list.Count) + continue; + + var mob = list[i]; + + if (mob.Deleted) + list.RemoveAt(i--); + } + + list.Add(summoned); + + if (list.Count > 3) + Timer.DelayCall(list[0].Kill); + + Timer.DelayCall(TimeSpan.FromSeconds(2.0), TimeSpan.FromSeconds(2.0), Summoned_Damage, summoned); + } + + private static void Summoned_Damage(Mobile mob) + { + if (mob.Hits > 0) + --mob.Hits; + else + mob.Kill(); + } + + private static void SummonDelay_Callback(Mobile caster, Corpse corpse, Point3D loc, Map map, CreatureGroup group) + { + if (corpse.Animated) + return; + + var owner = corpse.Owner; + + if (owner == null) + return; + + var necromancy = caster.Skills.Necromancy.Value; + var spiritSpeak = caster.Skills.SpiritSpeak.Value; + + var casterAbility = (int)(necromancy * 30) + (int)(spiritSpeak * 70); + casterAbility = Math.Clamp(casterAbility / 10 * 18, 0, owner.Fame); + + Type toSummon = null; + var entries = group.m_Entries; + + for (var i = 0; toSummon == null && i < entries.Length; ++i) + { + var entry = entries[i]; + + if (casterAbility < entry.m_Requirement) + continue; + + var animates = entry.m_ToSummon; + + toSummon = animates.RandomElement(); + } + + if (toSummon == null) + return; + + Mobile summoned = null; + + try + { + summoned = ActivatorUtil.CreateInstance(toSummon) as Mobile; + } + catch + { + // ignored + } + + if (summoned == null) + return; + + if (summoned is BaseCreature bc) + { + // to be sure + bc.Tamable = false; + + bc.ControlSlots = bc is BaseMount ? 1 : 0; + + Effects.PlaySound(loc, map, bc.GetAngerSound()); + + BaseCreature.Summon(bc, false, caster, loc, 0x28, TimeSpan.FromDays(1.0)); + } + + if (summoned is SkeletalDragon dragon) + Scale(dragon, 50); // lose 50% hp and strength + + summoned.Fame = 0; + summoned.Karma = -1500; + + summoned.MoveToWorld(loc, map); + + corpse.Hue = 1109; + corpse.Animated = true; + + Register(caster, summoned); + } + + public static void Scale(BaseCreature bc, int scalar) + { + var toScale = bc.RawStr; + bc.RawStr = AOS.Scale(toScale, scalar); + + toScale = bc.HitsMaxSeed; + + if (toScale > 0) + bc.HitsMaxSeed = AOS.Scale(toScale, scalar); + + bc.Hits = bc.Hits; // refresh hits + } + + private class CreatureGroup + { + public readonly SummonEntry[] m_Entries; + public readonly Type[] m_Types; + + public CreatureGroup(Type[] types, SummonEntry[] entries) + { + m_Types = types; + m_Entries = entries; + } + } + + private class SummonEntry + { + public readonly int m_Requirement; + public readonly Type[] m_ToSummon; + + public SummonEntry(int requirement, params Type[] toSummon) + { + m_ToSummon = toSummon; + m_Requirement = requirement; + } + } } - - public static void Unregister(Mobile master, Mobile summoned) - { - if (master == null) - return; - - if (!m_Table.TryGetValue(master, out List list)) - return; - - list.Remove(summoned); - - if (list.Count == 0) - m_Table.Remove(master); - } - - public static void Register(Mobile master, Mobile summoned) - { - if (master == null) - return; - - if (!m_Table.TryGetValue(master, out List list)) - m_Table[master] = list = new List(); - - for (int i = list.Count - 1; i >= 0; --i) - { - if (i >= list.Count) - continue; - - Mobile mob = list[i]; - - if (mob.Deleted) - list.RemoveAt(i--); - } - - list.Add(summoned); - - if (list.Count > 3) - Timer.DelayCall(list[0].Kill); - - Timer.DelayCall(TimeSpan.FromSeconds(2.0), TimeSpan.FromSeconds(2.0), Summoned_Damage, summoned); - } - - private static void Summoned_Damage(Mobile mob) - { - if (mob.Hits > 0) - --mob.Hits; - else - mob.Kill(); - } - - private static void SummonDelay_Callback(Mobile caster, Corpse corpse, Point3D loc, Map map, CreatureGroup group) - { - if (corpse.Animated) - return; - - Mobile owner = corpse.Owner; - - if (owner == null) - return; - - double necromancy = caster.Skills.Necromancy.Value; - double spiritSpeak = caster.Skills.SpiritSpeak.Value; - - int casterAbility = (int)(necromancy * 30) + (int)(spiritSpeak * 70); - casterAbility = Math.Clamp(casterAbility / 10 * 18, 0, owner.Fame); - - Type toSummon = null; - SummonEntry[] entries = group.m_Entries; - - for (int i = 0; toSummon == null && i < entries.Length; ++i) - { - SummonEntry entry = entries[i]; - - if (casterAbility < entry.m_Requirement) - continue; - - Type[] animates = entry.m_ToSummon; - - toSummon = animates.RandomElement(); - } - - if (toSummon == null) - return; - - Mobile summoned = null; - - try - { - summoned = ActivatorUtil.CreateInstance(toSummon) as Mobile; - } - catch - { - // ignored - } - - if (summoned == null) - return; - - if (summoned is BaseCreature bc) - { - // to be sure - bc.Tamable = false; - - bc.ControlSlots = bc is BaseMount ? 1 : 0; - - Effects.PlaySound(loc, map, bc.GetAngerSound()); - - BaseCreature.Summon(bc, false, caster, loc, 0x28, TimeSpan.FromDays(1.0)); - } - - if (summoned is SkeletalDragon dragon) - Scale(dragon, 50); // lose 50% hp and strength - - summoned.Fame = 0; - summoned.Karma = -1500; - - summoned.MoveToWorld(loc, map); - - corpse.Hue = 1109; - corpse.Animated = true; - - Register(caster, summoned); - } - - public static void Scale(BaseCreature bc, int scalar) - { - int toScale = bc.RawStr; - bc.RawStr = AOS.Scale(toScale, scalar); - - toScale = bc.HitsMaxSeed; - - if (toScale > 0) - bc.HitsMaxSeed = AOS.Scale(toScale, scalar); - - bc.Hits = bc.Hits; // refresh hits - } - - private class CreatureGroup - { - public readonly SummonEntry[] m_Entries; - public readonly Type[] m_Types; - - public CreatureGroup(Type[] types, SummonEntry[] entries) - { - m_Types = types; - m_Entries = entries; - } - } - - private class SummonEntry - { - public readonly int m_Requirement; - public readonly Type[] m_ToSummon; - - public SummonEntry(int requirement, params Type[] toSummon) - { - m_ToSummon = toSummon; - m_Requirement = requirement; - } - } - } } diff --git a/Projects/UOContent/Spells/Necromancy/BloodOathSpell.cs b/Projects/UOContent/Spells/Necromancy/BloodOathSpell.cs index 9844c6ee4..fdc8c52f0 100644 --- a/Projects/UOContent/Spells/Necromancy/BloodOathSpell.cs +++ b/Projects/UOContent/Spells/Necromancy/BloodOathSpell.cs @@ -5,142 +5,153 @@ using Server.Targeting; namespace Server.Spells.Necromancy { - public class BloodOathSpell : NecromancerSpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Blood Oath", "In Jux Mani Xen", - 203, - 9031, - Reagent.DaemonBlood); - - private static readonly Dictionary m_OathTable = new Dictionary(); - private static readonly Dictionary m_Table = new Dictionary(); - - public BloodOathSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class BloodOathSpell : NecromancerSpell, ISpellTargetingMobile { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Blood Oath", + "In Jux Mani Xen", + 203, + 9031, + Reagent.DaemonBlood + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); + private static readonly Dictionary m_OathTable = new Dictionary(); + private static readonly Dictionary m_Table = new Dictionary(); - public override double RequiredSkill => 20.0; - public override int RequiredMana => 13; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - Caster.SendLocalizedMessage(1060508); // You can't curse that. - // only PlayerMobile and BaseCreature implement blood oath checking - else if (Caster == m || !(m is PlayerMobile || m is BaseCreature)) - Caster.SendLocalizedMessage(1060508); // You can't curse that. - else if (m_OathTable.ContainsKey(Caster)) - Caster.SendLocalizedMessage(1061607); // You are already bonded in a Blood Oath. - else if (m_OathTable.ContainsKey(m)) - { - if (m.Player) - Caster.SendLocalizedMessage(1061608); // That player is already bonded in a Blood Oath. - else - Caster.SendLocalizedMessage(1061609); // That creature is already bonded in a Blood Oath. - } - else if (CheckHSequence(m)) - { - SpellHelper.Turn(Caster, m); - - /* Temporarily creates a dark pact between the caster and the target. - * Any damage dealt by the target to the caster is increased, but the target receives the same amount of damage. - * The effect lasts for ((Spirit Speak skill level - target's Resist Magic skill level) / 80 ) + 8 seconds. - * - * NOTE: The above algorithm must be fixed point, it should be: - * ((ss-rm)/8)+8 - */ - - m_Table.TryGetValue(m, out ExpireTimer timer); - timer?.DoExpire(); - - m_OathTable[Caster] = Caster; - m_OathTable[m] = Caster; - - m.Spell?.OnCasterHurt(); - - Caster.PlaySound(0x175); - - Caster.FixedParticles(0x375A, 1, 17, 9919, 33, 7, EffectLayer.Waist); - Caster.FixedParticles(0x3728, 1, 13, 9502, 33, 7, (EffectLayer)255); - - m.FixedParticles(0x375A, 1, 17, 9919, 33, 7, EffectLayer.Waist); - m.FixedParticles(0x3728, 1, 13, 9502, 33, 7, (EffectLayer)255); - - TimeSpan duration = TimeSpan.FromSeconds((GetDamageSkill(Caster) - GetResistSkill(m)) / 8 + 8); - m.CheckSkill(SkillName.MagicResist, 0.0, 120.0); // Skill check for gain - - timer = new ExpireTimer(Caster, m, duration); - timer.Start(); - - BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.BloodOathCaster, 1075659, duration, Caster, m.Name)); - BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.BloodOathCurse, 1075661, duration, m, Caster.Name)); - - m_Table[m] = timer; - HarmfulSpell(m); - } - - FinishSequence(); - } - - public static void RemoveCurse(Mobile m) - { - m_Table.TryGetValue(m, out ExpireTimer t); - t?.DoExpire(); - } - - public static Mobile GetBloodOath(Mobile m) => m == null || (m_OathTable.TryGetValue(m, out Mobile oath) && oath == m) ? null : oath; - - private class ExpireTimer : Timer - { - private readonly Mobile m_Caster; - private readonly DateTime m_End; - private readonly Mobile m_Target; - - public ExpireTimer(Mobile caster, Mobile target, TimeSpan delay) : base(TimeSpan.FromSeconds(1.0), - TimeSpan.FromSeconds(1.0)) - { - m_Caster = caster; - m_Target = target; - m_End = DateTime.UtcNow + delay; - - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - if (m_Caster.Deleted || m_Target.Deleted || !m_Caster.Alive || !m_Target.Alive || - DateTime.UtcNow >= m_End) DoExpire(); - } - - public void DoExpire() - { - if (m_OathTable.ContainsKey(m_Caster)) + public BloodOathSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - m_Caster.SendLocalizedMessage(1061620); // Your Blood Oath has been broken. - m_OathTable.Remove(m_Caster); } - if (m_OathTable.ContainsKey(m_Target)) + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); + + public override double RequiredSkill => 20.0; + public override int RequiredMana => 13; + + public void Target(Mobile m) { - m_Target.SendLocalizedMessage(1061620); // Your Blood Oath has been broken. - m_OathTable.Remove(m_Target); + if (m == null) + { + Caster.SendLocalizedMessage(1060508); // You can't curse that. + } + // only PlayerMobile and BaseCreature implement blood oath checking + else if (Caster == m || !(m is PlayerMobile || m is BaseCreature)) + { + Caster.SendLocalizedMessage(1060508); // You can't curse that. + } + else if (m_OathTable.ContainsKey(Caster)) + { + Caster.SendLocalizedMessage(1061607); // You are already bonded in a Blood Oath. + } + else if (m_OathTable.ContainsKey(m)) + { + if (m.Player) + Caster.SendLocalizedMessage(1061608); // That player is already bonded in a Blood Oath. + else + Caster.SendLocalizedMessage(1061609); // That creature is already bonded in a Blood Oath. + } + else if (CheckHSequence(m)) + { + SpellHelper.Turn(Caster, m); + + /* Temporarily creates a dark pact between the caster and the target. + * Any damage dealt by the target to the caster is increased, but the target receives the same amount of damage. + * The effect lasts for ((Spirit Speak skill level - target's Resist Magic skill level) / 80 ) + 8 seconds. + * + * NOTE: The above algorithm must be fixed point, it should be: + * ((ss-rm)/8)+8 + */ + + m_Table.TryGetValue(m, out var timer); + timer?.DoExpire(); + + m_OathTable[Caster] = Caster; + m_OathTable[m] = Caster; + + m.Spell?.OnCasterHurt(); + + Caster.PlaySound(0x175); + + Caster.FixedParticles(0x375A, 1, 17, 9919, 33, 7, EffectLayer.Waist); + Caster.FixedParticles(0x3728, 1, 13, 9502, 33, 7, (EffectLayer)255); + + m.FixedParticles(0x375A, 1, 17, 9919, 33, 7, EffectLayer.Waist); + m.FixedParticles(0x3728, 1, 13, 9502, 33, 7, (EffectLayer)255); + + var duration = TimeSpan.FromSeconds((GetDamageSkill(Caster) - GetResistSkill(m)) / 8 + 8); + m.CheckSkill(SkillName.MagicResist, 0.0, 120.0); // Skill check for gain + + timer = new ExpireTimer(Caster, m, duration); + timer.Start(); + + BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.BloodOathCaster, 1075659, duration, Caster, m.Name)); + BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.BloodOathCurse, 1075661, duration, m, Caster.Name)); + + m_Table[m] = timer; + HarmfulSpell(m); + } + + FinishSequence(); } - Stop(); + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } - BuffInfo.RemoveBuff(m_Caster, BuffIcon.BloodOathCaster); - BuffInfo.RemoveBuff(m_Target, BuffIcon.BloodOathCurse); + public static void RemoveCurse(Mobile m) + { + m_Table.TryGetValue(m, out var t); + t?.DoExpire(); + } - m_Table.Remove(m_Caster); - } + public static Mobile GetBloodOath(Mobile m) => + m == null || m_OathTable.TryGetValue(m, out var oath) && oath == m ? null : oath; + + private class ExpireTimer : Timer + { + private readonly Mobile m_Caster; + private readonly DateTime m_End; + private readonly Mobile m_Target; + + public ExpireTimer(Mobile caster, Mobile target, TimeSpan delay) : base( + TimeSpan.FromSeconds(1.0), + TimeSpan.FromSeconds(1.0) + ) + { + m_Caster = caster; + m_Target = target; + m_End = DateTime.UtcNow + delay; + + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + if (m_Caster.Deleted || m_Target.Deleted || !m_Caster.Alive || !m_Target.Alive || + DateTime.UtcNow >= m_End) DoExpire(); + } + + public void DoExpire() + { + if (m_OathTable.ContainsKey(m_Caster)) + { + m_Caster.SendLocalizedMessage(1061620); // Your Blood Oath has been broken. + m_OathTable.Remove(m_Caster); + } + + if (m_OathTable.ContainsKey(m_Target)) + { + m_Target.SendLocalizedMessage(1061620); // Your Blood Oath has been broken. + m_OathTable.Remove(m_Target); + } + + Stop(); + + BuffInfo.RemoveBuff(m_Caster, BuffIcon.BloodOathCaster); + BuffInfo.RemoveBuff(m_Target, BuffIcon.BloodOathCurse); + + m_Table.Remove(m_Caster); + } + } } - } } diff --git a/Projects/UOContent/Spells/Necromancy/CorpseSkin.cs b/Projects/UOContent/Spells/Necromancy/CorpseSkin.cs index 774caedd7..9cc11283e 100644 --- a/Projects/UOContent/Spells/Necromancy/CorpseSkin.cs +++ b/Projects/UOContent/Spells/Necromancy/CorpseSkin.cs @@ -4,127 +4,130 @@ using Server.Targeting; namespace Server.Spells.Necromancy { - public class CorpseSkinSpell : NecromancerSpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Corpse Skin", "In Agle Corp Ylem", - 203, - 9051, - Reagent.BatWing, - Reagent.GraveDust); - - private static readonly Dictionary m_Table = new Dictionary(); - - public CorpseSkinSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class CorpseSkinSpell : NecromancerSpell, ISpellTargetingMobile { + private static readonly SpellInfo m_Info = new SpellInfo( + "Corpse Skin", + "In Agle Corp Ylem", + 203, + 9051, + Reagent.BatWing, + Reagent.GraveDust + ); + + private static readonly Dictionary m_Table = new Dictionary(); + + public CorpseSkinSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); + + public override double RequiredSkill => 20.0; + public override int RequiredMana => 11; + + public void Target(Mobile m) + { + if (m == null) + return; + + if (CheckHSequence(m)) + { + SpellHelper.Turn(Caster, m); + + /* Transmogrifies the flesh of the target creature or player to resemble rotted corpse flesh, + * making them more vulnerable to Fire and Poison damage, + * but increasing their resistance to Physical and Cold damage. + * + * The effect lasts for ((Spirit Speak skill level - target's Resist Magic skill level) / 25 ) + 40 seconds. + * + * NOTE: Algorithm above is fixed point, should be: + * ((ss-mr)/2.5) + 40 + * + * NOTE: Resistance is not checked if targeting yourself + */ + + if (m_Table.TryGetValue(m, out var timer)) + timer.DoExpire(); + else + m.SendLocalizedMessage(1061689); // Your skin turns dry and corpselike. + + m.Spell?.OnCasterHurt(); + + m.FixedParticles(0x373A, 1, 15, 9913, 67, 7, EffectLayer.Head); + m.PlaySound(0x1BB); + + var ss = GetDamageSkill(Caster); + var mr = Caster == m ? 0.0 : GetResistSkill(m); + m.CheckSkill(SkillName.MagicResist, 0.0, 120.0); // Skill check for gain + + var duration = TimeSpan.FromSeconds((ss - mr) / 2.5 + 40.0); + + ResistanceMod[] mods = + { + new ResistanceMod(ResistanceType.Fire, -15), + new ResistanceMod(ResistanceType.Poison, -15), + new ResistanceMod(ResistanceType.Cold, +10), + new ResistanceMod(ResistanceType.Physical, +10) + }; + + timer = new ExpireTimer(m, mods, duration); + timer.Start(); + + BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.CorpseSkin, 1075663, duration, m)); + + m_Table[m] = timer; + + for (var i = 0; i < mods.Length; ++i) + m.AddResistanceMod(mods[i]); + + HarmfulSpell(m); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } + + public static bool RemoveCurse(Mobile m) + { + if (!m_Table.TryGetValue(m, out var t)) + return false; + + m.SendLocalizedMessage(1061688); // Your skin returns to normal. + t?.DoExpire(); + return true; + } + + private class ExpireTimer : Timer + { + private readonly Mobile m_Mobile; + private readonly ResistanceMod[] m_Mods; + + public ExpireTimer(Mobile m, ResistanceMod[] mods, TimeSpan delay) : base(delay) + { + m_Mobile = m; + m_Mods = mods; + } + + public void DoExpire() + { + for (var i = 0; i < m_Mods.Length; ++i) + m_Mobile.RemoveResistanceMod(m_Mods[i]); + + Stop(); + BuffInfo.RemoveBuff(m_Mobile, BuffIcon.CorpseSkin); + m_Table.Remove(m_Mobile); + } + + protected override void OnTick() + { + m_Mobile.SendLocalizedMessage(1061688); // Your skin returns to normal. + DoExpire(); + } + } } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); - - public override double RequiredSkill => 20.0; - public override int RequiredMana => 11; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (CheckHSequence(m)) - { - SpellHelper.Turn(Caster, m); - - /* Transmogrifies the flesh of the target creature or player to resemble rotted corpse flesh, - * making them more vulnerable to Fire and Poison damage, - * but increasing their resistance to Physical and Cold damage. - * - * The effect lasts for ((Spirit Speak skill level - target's Resist Magic skill level) / 25 ) + 40 seconds. - * - * NOTE: Algorithm above is fixed point, should be: - * ((ss-mr)/2.5) + 40 - * - * NOTE: Resistance is not checked if targeting yourself - */ - - if (m_Table.TryGetValue(m, out ExpireTimer timer)) - timer.DoExpire(); - else - m.SendLocalizedMessage(1061689); // Your skin turns dry and corpselike. - - m.Spell?.OnCasterHurt(); - - m.FixedParticles(0x373A, 1, 15, 9913, 67, 7, EffectLayer.Head); - m.PlaySound(0x1BB); - - double ss = GetDamageSkill(Caster); - double mr = Caster == m ? 0.0 : GetResistSkill(m); - m.CheckSkill(SkillName.MagicResist, 0.0, 120.0); // Skill check for gain - - TimeSpan duration = TimeSpan.FromSeconds((ss - mr) / 2.5 + 40.0); - - ResistanceMod[] mods = { - new ResistanceMod(ResistanceType.Fire, -15), - new ResistanceMod(ResistanceType.Poison, -15), - new ResistanceMod(ResistanceType.Cold, +10), - new ResistanceMod(ResistanceType.Physical, +10) - }; - - timer = new ExpireTimer(m, mods, duration); - timer.Start(); - - BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.CorpseSkin, 1075663, duration, m)); - - m_Table[m] = timer; - - for (int i = 0; i < mods.Length; ++i) - m.AddResistanceMod(mods[i]); - - HarmfulSpell(m); - } - - FinishSequence(); - } - - public static bool RemoveCurse(Mobile m) - { - if (!m_Table.TryGetValue(m, out ExpireTimer t)) - return false; - - m.SendLocalizedMessage(1061688); // Your skin returns to normal. - t?.DoExpire(); - return true; - } - - private class ExpireTimer : Timer - { - private readonly Mobile m_Mobile; - private readonly ResistanceMod[] m_Mods; - - public ExpireTimer(Mobile m, ResistanceMod[] mods, TimeSpan delay) : base(delay) - { - m_Mobile = m; - m_Mods = mods; - } - - public void DoExpire() - { - for (int i = 0; i < m_Mods.Length; ++i) - m_Mobile.RemoveResistanceMod(m_Mods[i]); - - Stop(); - BuffInfo.RemoveBuff(m_Mobile, BuffIcon.CorpseSkin); - m_Table.Remove(m_Mobile); - } - - protected override void OnTick() - { - m_Mobile.SendLocalizedMessage(1061688); // Your skin returns to normal. - DoExpire(); - } - } - } } diff --git a/Projects/UOContent/Spells/Necromancy/CurseWeapon.cs b/Projects/UOContent/Spells/Necromancy/CurseWeapon.cs index e093f49ea..bcaf5d53a 100644 --- a/Projects/UOContent/Spells/Necromancy/CurseWeapon.cs +++ b/Projects/UOContent/Spells/Necromancy/CurseWeapon.cs @@ -4,94 +4,96 @@ using Server.Items; namespace Server.Spells.Necromancy { - public class CurseWeaponSpell : NecromancerSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Curse Weapon", "An Sanct Gra Char", - 203, - 9031, - Reagent.PigIron); - - private static readonly Dictionary m_Table = new Dictionary(); - - public CurseWeaponSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class CurseWeaponSpell : NecromancerSpell { + private static readonly SpellInfo m_Info = new SpellInfo( + "Curse Weapon", + "An Sanct Gra Char", + 203, + 9031, + Reagent.PigIron + ); + + private static readonly Dictionary m_Table = new Dictionary(); + + public CurseWeaponSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(0.75); + + public override double RequiredSkill => 0.0; + public override int RequiredMana => 7; + + public override void OnCast() + { + if (!(Caster.Weapon is BaseWeapon weapon) || weapon is Fists) + { + Caster.SendLocalizedMessage(501078); // You must be holding a weapon. + } + else if (CheckSequence()) + { + /* Temporarily imbues a weapon with a life draining effect. + * Half the damage that the weapon inflicts is added to the necromancer's health. + * The effects lasts for (Spirit Speak skill level / 34) + 1 seconds. + * + * NOTE: Above algorithm is fixed point, should be : + * (Spirit Speak skill level / 3.4) + 1 + * + * TODO: What happens if you curse a weapon then give it to someone else? Should they get the drain effect? + */ + + Caster.PlaySound(0x387); + Caster.FixedParticles(0x3779, 1, 15, 9905, 32, 2, EffectLayer.Head); + Caster.FixedParticles(0x37B9, 1, 14, 9502, 32, 5, (EffectLayer)255); + new SoundEffectTimer(Caster).Start(); + + var duration = TimeSpan.FromSeconds(Caster.Skills.SpiritSpeak.Value / 3.4 + 1.0); + + m_Table.TryGetValue(weapon, out var timer); + timer?.Stop(); + + weapon.Cursed = true; + m_Table[weapon] = timer = new ExpireTimer(weapon, duration); + + timer.Start(); + } + + FinishSequence(); + } + + private class ExpireTimer : Timer + { + private readonly BaseWeapon m_Weapon; + + public ExpireTimer(BaseWeapon weapon, TimeSpan delay) : base(delay) + { + m_Weapon = weapon; + Priority = TimerPriority.OneSecond; + } + + protected override void OnTick() + { + m_Weapon.Cursed = false; + Effects.PlaySound(m_Weapon.GetWorldLocation(), m_Weapon.Map, 0xFA); + m_Table.Remove(m_Weapon); + } + } + + private class SoundEffectTimer : Timer + { + private readonly Mobile m_Mobile; + + public SoundEffectTimer(Mobile m) : base(TimeSpan.FromSeconds(0.75)) + { + m_Mobile = m; + Priority = TimerPriority.FiftyMS; + } + + protected override void OnTick() + { + m_Mobile.PlaySound(0xFA); + } + } } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(0.75); - - public override double RequiredSkill => 0.0; - public override int RequiredMana => 7; - - public override void OnCast() - { - if (!(Caster.Weapon is BaseWeapon weapon) || weapon is Fists) - { - Caster.SendLocalizedMessage(501078); // You must be holding a weapon. - } - else if (CheckSequence()) - { - /* Temporarily imbues a weapon with a life draining effect. - * Half the damage that the weapon inflicts is added to the necromancer's health. - * The effects lasts for (Spirit Speak skill level / 34) + 1 seconds. - * - * NOTE: Above algorithm is fixed point, should be : - * (Spirit Speak skill level / 3.4) + 1 - * - * TODO: What happens if you curse a weapon then give it to someone else? Should they get the drain effect? - */ - - Caster.PlaySound(0x387); - Caster.FixedParticles(0x3779, 1, 15, 9905, 32, 2, EffectLayer.Head); - Caster.FixedParticles(0x37B9, 1, 14, 9502, 32, 5, (EffectLayer)255); - new SoundEffectTimer(Caster).Start(); - - TimeSpan duration = TimeSpan.FromSeconds(Caster.Skills.SpiritSpeak.Value / 3.4 + 1.0); - - m_Table.TryGetValue(weapon, out ExpireTimer timer); - timer?.Stop(); - - weapon.Cursed = true; - m_Table[weapon] = timer = new ExpireTimer(weapon, duration); - - timer.Start(); - } - - FinishSequence(); - } - - private class ExpireTimer : Timer - { - private readonly BaseWeapon m_Weapon; - - public ExpireTimer(BaseWeapon weapon, TimeSpan delay) : base(delay) - { - m_Weapon = weapon; - Priority = TimerPriority.OneSecond; - } - - protected override void OnTick() - { - m_Weapon.Cursed = false; - Effects.PlaySound(m_Weapon.GetWorldLocation(), m_Weapon.Map, 0xFA); - m_Table.Remove(m_Weapon); - } - } - - private class SoundEffectTimer : Timer - { - private readonly Mobile m_Mobile; - - public SoundEffectTimer(Mobile m) : base(TimeSpan.FromSeconds(0.75)) - { - m_Mobile = m; - Priority = TimerPriority.FiftyMS; - } - - protected override void OnTick() - { - m_Mobile.PlaySound(0xFA); - } - } - } } diff --git a/Projects/UOContent/Spells/Necromancy/EvilOmen.cs b/Projects/UOContent/Spells/Necromancy/EvilOmen.cs index fc0bf013c..8db928e1f 100644 --- a/Projects/UOContent/Spells/Necromancy/EvilOmen.cs +++ b/Projects/UOContent/Spells/Necromancy/EvilOmen.cs @@ -5,85 +5,89 @@ using Server.Targeting; namespace Server.Spells.Necromancy { - public class EvilOmenSpell : NecromancerSpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Evil Omen", "Pas Tym An Sanct", - 203, - 9031, - Reagent.BatWing, - Reagent.NoxCrystal); - - private static readonly Dictionary m_Table = new Dictionary(); - - public EvilOmenSpell(Mobile caster, Item scroll = null) - : base(caster, scroll, m_Info) + public class EvilOmenSpell : NecromancerSpell, ISpellTargetingMobile { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Evil Omen", + "Pas Tym An Sanct", + 203, + 9031, + Reagent.BatWing, + Reagent.NoxCrystal + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(0.75); + private static readonly Dictionary m_Table = new Dictionary(); - public override double RequiredSkill => 20.0; - public override int RequiredMana => 11; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (!(m is BaseCreature || m is PlayerMobile)) - Caster.SendLocalizedMessage(1060508); // You can't curse that. - else if (CheckHSequence(m)) - { - SpellHelper.Turn(Caster, m); - - /* Curses the target so that the next harmful event that affects them is magnified. - * Damage to the target's hit points is increased 25%, - * the poison level of the attack will be 1 higher - * and the Resist Magic skill of the target will be fixed on 50. - * - * The effect lasts for one harmful event only. - */ - - m.Spell?.OnCasterHurt(); - - m.PlaySound(0xFC); - m.FixedParticles(0x3728, 1, 13, 9912, 1150, 7, EffectLayer.Head); - m.FixedParticles(0x3779, 1, 15, 9502, 67, 7, EffectLayer.Head); - - if (!m_Table.ContainsKey(m)) + public EvilOmenSpell(Mobile caster, Item scroll = null) + : base(caster, scroll, m_Info) { - DefaultSkillMod mod = new DefaultSkillMod(SkillName.MagicResist, false, 50.0); - - if (m.Skills.MagicResist.Base > 50.0) - m.AddSkillMod(mod); - - m_Table[m] = mod; } - TimeSpan duration = TimeSpan.FromSeconds(Caster.Skills.SpiritSpeak.Value / 12 + 1.0); + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(0.75); - Timer.DelayCall(duration, mob => TryEndEffect(mob), m); + public override double RequiredSkill => 20.0; + public override int RequiredMana => 11; - HarmfulSpell(m); + public void Target(Mobile m) + { + if (!(m is BaseCreature || m is PlayerMobile)) + { + Caster.SendLocalizedMessage(1060508); // You can't curse that. + } + else if (CheckHSequence(m)) + { + SpellHelper.Turn(Caster, m); - BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.EvilOmen, 1075647, 1075648, duration, m)); - } + /* Curses the target so that the next harmful event that affects them is magnified. + * Damage to the target's hit points is increased 25%, + * the poison level of the attack will be 1 higher + * and the Resist Magic skill of the target will be fixed on 50. + * + * The effect lasts for one harmful event only. + */ - FinishSequence(); + m.Spell?.OnCasterHurt(); + + m.PlaySound(0xFC); + m.FixedParticles(0x3728, 1, 13, 9912, 1150, 7, EffectLayer.Head); + m.FixedParticles(0x3779, 1, 15, 9502, 67, 7, EffectLayer.Head); + + if (!m_Table.ContainsKey(m)) + { + var mod = new DefaultSkillMod(SkillName.MagicResist, false, 50.0); + + if (m.Skills.MagicResist.Base > 50.0) + m.AddSkillMod(mod); + + m_Table[m] = mod; + } + + var duration = TimeSpan.FromSeconds(Caster.Skills.SpiritSpeak.Value / 12 + 1.0); + + Timer.DelayCall(duration, mob => TryEndEffect(mob), m); + + HarmfulSpell(m); + + BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.EvilOmen, 1075647, 1075648, duration, m)); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } + + public static bool TryEndEffect(Mobile m) + { + if (!m_Table.TryGetValue(m, out var mod)) + return false; + + m_Table.Remove(m); + mod?.Remove(); + + return true; + } } - - public static bool TryEndEffect(Mobile m) - { - if (!m_Table.TryGetValue(m, out DefaultSkillMod mod)) - return false; - - m_Table.Remove(m); - mod?.Remove(); - - return true; - } - } } diff --git a/Projects/UOContent/Spells/Necromancy/Exorcism.cs b/Projects/UOContent/Spells/Necromancy/Exorcism.cs index 253b90a88..73f44df97 100644 --- a/Projects/UOContent/Spells/Necromancy/Exorcism.cs +++ b/Projects/UOContent/Spells/Necromancy/Exorcism.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using Server.Engines.CannedEvil; using Server.Engines.PartySystem; @@ -10,170 +9,172 @@ using Server.Regions; namespace Server.Spells.Necromancy { - public class ExorcismSpell : NecromancerSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Exorcism", "Ort Corp Grav", - 203, - 9031, - Reagent.NoxCrystal, - Reagent.GraveDust); - - private static readonly int Range = Core.ML ? 48 : 18; - - private static readonly Point3D[] m_BritanniaLocs = + public class ExorcismSpell : NecromancerSpell { - new Point3D(1470, 843, 0), - new Point3D(1857, 865, -1), - new Point3D(4220, 563, 36), - new Point3D(1732, 3528, 0), - new Point3D(1300, 644, 8), - new Point3D(3355, 302, 9), - new Point3D(1606, 2490, 5), - new Point3D(2500, 3931, 3), - new Point3D(4264, 3707, 0) - }; + private static readonly SpellInfo m_Info = new SpellInfo( + "Exorcism", + "Ort Corp Grav", + 203, + 9031, + Reagent.NoxCrystal, + Reagent.GraveDust + ); - private static readonly Point3D[] m_IllshLocs = - { - new Point3D(1222, 474, -17), - new Point3D(718, 1360, -60), - new Point3D(297, 1014, -19), - new Point3D(986, 1006, -36), - new Point3D(1180, 1288, -30), - new Point3D(1538, 1341, -3), - new Point3D(528, 223, -38) - }; + private static readonly int Range = Core.ML ? 48 : 18; - private static readonly Point3D[] m_MalasLocs = - { - new Point3D(976, 517, -30) - }; - - private static readonly Point3D[] m_TokunoLocs = - { - new Point3D(710, 1162, 25), - new Point3D(1034, 515, 18), - new Point3D(295, 712, 55) - }; - - public ExorcismSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) - { - } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.0); - - public override double RequiredSkill => 80.0; - public override int RequiredMana => 40; - - public override bool DelayedDamage => false; - - public override bool CheckCast() - { - if (Caster.Skills.SpiritSpeak.Value < 100.0) - { - Caster.SendLocalizedMessage(1072112); // You must have GM Spirit Speak to use this spell - return false; - } - - return base.CheckCast(); - } - - public override int ComputeKarmaAward() => 0; - - public override void OnCast() - { - ChampionSpawnRegion r = Caster.Region.GetRegion(); - if (r == null || !Caster.InRange(r.ChampionSpawn, Range)) - { - Caster.SendLocalizedMessage(1072111); // You are not in a valid exorcism region. - } - else if (CheckSequence()) - { - Map map = Caster.Map; - - if (map != null) + private static readonly Point3D[] m_BritanniaLocs = { - IEnumerable targets = r.ChampionSpawn.GetMobilesInRange(Range).Where(IsValidTarget); + new Point3D(1470, 843, 0), + new Point3D(1857, 865, -1), + new Point3D(4220, 563, 36), + new Point3D(1732, 3528, 0), + new Point3D(1300, 644, 8), + new Point3D(3355, 302, 9), + new Point3D(1606, 2490, 5), + new Point3D(2500, 3931, 3), + new Point3D(4264, 3707, 0) + }; - foreach (Mobile m in targets) - // Surprisingly, no sparkle type effects - m.Location = GetNearestShrine(m); - } - } - - FinishSequence(); - } - - private bool IsValidTarget(Mobile m) - { - if (!m.Player || m.Alive) - return false; - - Corpse c = m.Corpse as Corpse; - Map map = m.Map; - - if (c?.Deleted == false && map != null && c.Map == map) - { - if (SpellHelper.IsAnyT2A(map, c.Location) && SpellHelper.IsAnyT2A(map, m.Location)) - return false; // Same Map, both in T2A, ie, same 'sub server'. - - if (m.Region.IsPartOf() == Region.Find(c.Location, map).IsPartOf()) - return false; // Same Map, both in Dungeon region OR They're both NOT in a dungeon region. - - // Just an approximation cause RunUO doesn't divide up the world the same way OSI does ;p - } - - if (Party.Get(m)?.Contains(Caster) == true) - return false; - - if (m.Guild != null && Caster.Guild != null) - { - Guild mGuild = m.Guild as Guild; - Guild cGuild = Caster.Guild as Guild; - - if (mGuild?.IsAlly(cGuild) == true || mGuild == cGuild) - return false; - } - - Faction f = Faction.Find(m); - - return m.Map != Faction.Facet || f == null || f != Faction.Find(Caster); - } - - private static Point3D GetNearestShrine(Mobile m) - { - Map map = m.Map; - - Point3D[] locList; - - if (map == Map.Felucca || map == Map.Trammel) - locList = m_BritanniaLocs; - else if (map == Map.Ilshenar) - locList = m_IllshLocs; - else if (map == Map.Tokuno) - locList = m_TokunoLocs; - else if (map == Map.Malas) - locList = m_MalasLocs; - else - locList = Array.Empty(); - - Point3D closest = Point3D.Zero; - double minDist = double.MaxValue; - - for (int i = 0; i < locList.Length; i++) - { - Point3D p = locList[i]; - - double dist = m.GetDistanceToSqrt(p); - if (minDist > dist) + private static readonly Point3D[] m_IllshLocs = { - closest = p; - minDist = dist; - } - } + new Point3D(1222, 474, -17), + new Point3D(718, 1360, -60), + new Point3D(297, 1014, -19), + new Point3D(986, 1006, -36), + new Point3D(1180, 1288, -30), + new Point3D(1538, 1341, -3), + new Point3D(528, 223, -38) + }; - return closest; + private static readonly Point3D[] m_MalasLocs = + { + new Point3D(976, 517, -30) + }; + + private static readonly Point3D[] m_TokunoLocs = + { + new Point3D(710, 1162, 25), + new Point3D(1034, 515, 18), + new Point3D(295, 712, 55) + }; + + public ExorcismSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.0); + + public override double RequiredSkill => 80.0; + public override int RequiredMana => 40; + + public override bool DelayedDamage => false; + + public override bool CheckCast() + { + if (Caster.Skills.SpiritSpeak.Value < 100.0) + { + Caster.SendLocalizedMessage(1072112); // You must have GM Spirit Speak to use this spell + return false; + } + + return base.CheckCast(); + } + + public override int ComputeKarmaAward() => 0; + + public override void OnCast() + { + var r = Caster.Region.GetRegion(); + if (r == null || !Caster.InRange(r.ChampionSpawn, Range)) + { + Caster.SendLocalizedMessage(1072111); // You are not in a valid exorcism region. + } + else if (CheckSequence()) + { + var map = Caster.Map; + + if (map != null) + { + var targets = r.ChampionSpawn.GetMobilesInRange(Range).Where(IsValidTarget); + + foreach (var m in targets) + // Surprisingly, no sparkle type effects + m.Location = GetNearestShrine(m); + } + } + + FinishSequence(); + } + + private bool IsValidTarget(Mobile m) + { + if (!m.Player || m.Alive) + return false; + + var c = m.Corpse as Corpse; + var map = m.Map; + + if (c?.Deleted == false && map != null && c.Map == map) + { + if (SpellHelper.IsAnyT2A(map, c.Location) && SpellHelper.IsAnyT2A(map, m.Location)) + return false; // Same Map, both in T2A, ie, same 'sub server'. + + if (m.Region.IsPartOf() == Region.Find(c.Location, map).IsPartOf()) + return false; // Same Map, both in Dungeon region OR They're both NOT in a dungeon region. + + // Just an approximation cause RunUO doesn't divide up the world the same way OSI does ;p + } + + if (Party.Get(m)?.Contains(Caster) == true) + return false; + + if (m.Guild != null && Caster.Guild != null) + { + var mGuild = m.Guild as Guild; + var cGuild = Caster.Guild as Guild; + + if (mGuild?.IsAlly(cGuild) == true || mGuild == cGuild) + return false; + } + + var f = Faction.Find(m); + + return m.Map != Faction.Facet || f == null || f != Faction.Find(Caster); + } + + private static Point3D GetNearestShrine(Mobile m) + { + var map = m.Map; + + Point3D[] locList; + + if (map == Map.Felucca || map == Map.Trammel) + locList = m_BritanniaLocs; + else if (map == Map.Ilshenar) + locList = m_IllshLocs; + else if (map == Map.Tokuno) + locList = m_TokunoLocs; + else if (map == Map.Malas) + locList = m_MalasLocs; + else + locList = Array.Empty(); + + var closest = Point3D.Zero; + var minDist = double.MaxValue; + + for (var i = 0; i < locList.Length; i++) + { + var p = locList[i]; + + var dist = m.GetDistanceToSqrt(p); + if (minDist > dist) + { + closest = p; + minDist = dist; + } + } + + return closest; + } } - } } diff --git a/Projects/UOContent/Spells/Necromancy/HorrificBeast.cs b/Projects/UOContent/Spells/Necromancy/HorrificBeast.cs index eb6545720..f2a10cddf 100644 --- a/Projects/UOContent/Spells/Necromancy/HorrificBeast.cs +++ b/Projects/UOContent/Spells/Necromancy/HorrificBeast.cs @@ -2,38 +2,40 @@ using System; namespace Server.Spells.Necromancy { - public class HorrificBeastSpell : TransformationSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Horrific Beast", "Rel Xen Vas Bal", - 203, - 9031, - Reagent.BatWing, - Reagent.DaemonBlood); - - public HorrificBeastSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class HorrificBeastSpell : TransformationSpell { + private static readonly SpellInfo m_Info = new SpellInfo( + "Horrific Beast", + "Rel Xen Vas Bal", + 203, + 9031, + Reagent.BatWing, + Reagent.DaemonBlood + ); + + public HorrificBeastSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.0); + + public override double RequiredSkill => 40.0; + public override int RequiredMana => 11; + + public override int Body => 746; + + public override void DoEffect(Mobile m) + { + m.PlaySound(0x165); + m.FixedParticles(0x3728, 1, 13, 9918, 92, 3, EffectLayer.Head); + + m.Delta(MobileDelta.WeaponDamage); + m.CheckStatTimers(); + } + + public override void RemoveEffect(Mobile m) + { + m.Delta(MobileDelta.WeaponDamage); + } } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.0); - - public override double RequiredSkill => 40.0; - public override int RequiredMana => 11; - - public override int Body => 746; - - public override void DoEffect(Mobile m) - { - m.PlaySound(0x165); - m.FixedParticles(0x3728, 1, 13, 9918, 92, 3, EffectLayer.Head); - - m.Delta(MobileDelta.WeaponDamage); - m.CheckStatTimers(); - } - - public override void RemoveEffect(Mobile m) - { - m.Delta(MobileDelta.WeaponDamage); - } - } } diff --git a/Projects/UOContent/Spells/Necromancy/LichForm.cs b/Projects/UOContent/Spells/Necromancy/LichForm.cs index 47bc5be38..23422790c 100644 --- a/Projects/UOContent/Spells/Necromancy/LichForm.cs +++ b/Projects/UOContent/Spells/Necromancy/LichForm.cs @@ -2,42 +2,44 @@ using System; namespace Server.Spells.Necromancy { - public class LichFormSpell : TransformationSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Lich Form", "Rel Xen Corp Ort", - 203, - 9031, - Reagent.GraveDust, - Reagent.DaemonBlood, - Reagent.NoxCrystal); - - public LichFormSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class LichFormSpell : TransformationSpell { + private static readonly SpellInfo m_Info = new SpellInfo( + "Lich Form", + "Rel Xen Corp Ort", + 203, + 9031, + Reagent.GraveDust, + Reagent.DaemonBlood, + Reagent.NoxCrystal + ); + + public LichFormSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.0); + + public override double RequiredSkill => 70.0; + public override int RequiredMana => 23; + + public override int Body => 749; + + public override int FireResistOffset => -10; + public override int ColdResistOffset => +10; + public override int PoisResistOffset => +10; + + public override double TickRate => 2.5; + + public override void DoEffect(Mobile m) + { + m.PlaySound(0x19C); + m.FixedParticles(0x3709, 1, 30, 9904, 1108, 6, EffectLayer.RightFoot); + } + + public override void OnTick(Mobile m) + { + --m.Hits; + } } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.0); - - public override double RequiredSkill => 70.0; - public override int RequiredMana => 23; - - public override int Body => 749; - - public override int FireResistOffset => -10; - public override int ColdResistOffset => +10; - public override int PoisResistOffset => +10; - - public override double TickRate => 2.5; - - public override void DoEffect(Mobile m) - { - m.PlaySound(0x19C); - m.FixedParticles(0x3709, 1, 30, 9904, 1108, 6, EffectLayer.RightFoot); - } - - public override void OnTick(Mobile m) - { - --m.Hits; - } - } } diff --git a/Projects/UOContent/Spells/Necromancy/MindRot.cs b/Projects/UOContent/Spells/Necromancy/MindRot.cs index 3240e6e20..d4f4ea31c 100644 --- a/Projects/UOContent/Spells/Necromancy/MindRot.cs +++ b/Projects/UOContent/Spells/Necromancy/MindRot.cs @@ -4,136 +4,145 @@ using Server.Targeting; namespace Server.Spells.Necromancy { - public class MindRotSpell : NecromancerSpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Mind Rot", "Wis An Ben", - 203, - 9031, - Reagent.BatWing, - Reagent.PigIron, - Reagent.DaemonBlood); - - private static readonly Dictionary m_Table = new Dictionary(); - - public MindRotSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class MindRotSpell : NecromancerSpell, ISpellTargetingMobile { + private static readonly SpellInfo m_Info = new SpellInfo( + "Mind Rot", + "Wis An Ben", + 203, + 9031, + Reagent.BatWing, + Reagent.PigIron, + Reagent.DaemonBlood + ); + + private static readonly Dictionary m_Table = new Dictionary(); + + public MindRotSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); + + public override double RequiredSkill => 30.0; + public override int RequiredMana => 17; + + public void Target(Mobile m) + { + if (m == null) + { + Caster.SendLocalizedMessage(1060508); // You can't curse that. + } + else if (HasMindRotScalar(m)) + { + Caster.SendLocalizedMessage(1005559); // This spell is already in effect. + } + else if (CheckHSequence(m)) + { + SpellHelper.Turn(Caster, m); + + /* Attempts to place a curse on the Target that increases the mana cost of any spells they cast, + * for a duration based off a comparison between the Caster's Spirit Speak skill and the Target's Resisting Spells skill. + * The effect lasts for ((Spirit Speak skill level - target's Resist Magic skill level) / 50 ) + 20 seconds. + */ + + m.Spell?.OnCasterHurt(); + + m.PlaySound(0x1FB); + m.PlaySound(0x258); + m.FixedParticles(0x373A, 1, 17, 9903, 15, 4, EffectLayer.Head); + + var duration = + TimeSpan.FromSeconds( + ((GetDamageSkill(Caster) - GetResistSkill(m)) / 5.0 + 20.0) * (m.Player ? 1.0 : 2.0) + ); + m.CheckSkill(SkillName.MagicResist, 0.0, 120.0); // Skill check for gain + + SetMindRotScalar(Caster, m, m.Player ? 1.25 : 2.00, duration); + + HarmfulSpell(m); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } + + public static void ClearMindRotScalar(Mobile m) + { + if (!m_Table.TryGetValue(m, out var tmpB)) + return; + + BuffInfo.RemoveBuff(m, BuffIcon.Mindrot); + tmpB.m_MRExpireTimer.Stop(); + m_Table.Remove(m); + m.SendLocalizedMessage(1060872); // Your mind feels normal again. + } + + public static bool HasMindRotScalar(Mobile m) => m_Table.ContainsKey(m); + + public static bool GetMindRotScalar(Mobile m, ref double scalar) + { + if (m_Table.TryGetValue(m, out var tmpB)) + { + scalar = tmpB.m_Scalar; + return true; + } + + return false; + } + + public static void SetMindRotScalar(Mobile caster, Mobile target, double scalar, TimeSpan duration) + { + if (!m_Table.ContainsKey(target)) + { + var tmpB = new MRBucket(scalar, new MRExpireTimer(caster, target, duration)); + m_Table.Add(target, tmpB); + BuffInfo.AddBuff(target, new BuffInfo(BuffIcon.Mindrot, 1075665, duration, target)); + tmpB.m_MRExpireTimer.Start(); + target.SendLocalizedMessage(1074384); + } + } } - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); - - public override double RequiredSkill => 30.0; - public override int RequiredMana => 17; - - public override void OnCast() + public class MRExpireTimer : Timer { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + private readonly DateTime m_End; + private readonly Mobile m_Target; + + public MRExpireTimer(Mobile caster, Mobile target, TimeSpan delay) : base( + TimeSpan.FromSeconds(1.0), + TimeSpan.FromSeconds(1.0) + ) + { + m_Target = target; + m_End = DateTime.UtcNow + delay; + Priority = TimerPriority.TwoFiftyMS; + } + + protected override void OnTick() + { + if (m_Target.Deleted || !m_Target.Alive || DateTime.UtcNow >= m_End) + { + MindRotSpell.ClearMindRotScalar(m_Target); + Stop(); + } + } } - public void Target(Mobile m) + public class MRBucket { - if (m == null) - Caster.SendLocalizedMessage(1060508); // You can't curse that. - else if (HasMindRotScalar(m)) - Caster.SendLocalizedMessage(1005559); // This spell is already in effect. - else if (CheckHSequence(m)) - { - SpellHelper.Turn(Caster, m); + public MRExpireTimer m_MRExpireTimer; - /* Attempts to place a curse on the Target that increases the mana cost of any spells they cast, - * for a duration based off a comparison between the Caster's Spirit Speak skill and the Target's Resisting Spells skill. - * The effect lasts for ((Spirit Speak skill level - target's Resist Magic skill level) / 50 ) + 20 seconds. - */ + public double m_Scalar; - m.Spell?.OnCasterHurt(); - - m.PlaySound(0x1FB); - m.PlaySound(0x258); - m.FixedParticles(0x373A, 1, 17, 9903, 15, 4, EffectLayer.Head); - - TimeSpan duration = - TimeSpan.FromSeconds( - ((GetDamageSkill(Caster) - GetResistSkill(m)) / 5.0 + 20.0) * (m.Player ? 1.0 : 2.0)); - m.CheckSkill(SkillName.MagicResist, 0.0, 120.0); // Skill check for gain - - SetMindRotScalar(Caster, m, m.Player ? 1.25 : 2.00, duration); - - HarmfulSpell(m); - } - - FinishSequence(); + public MRBucket(double theScalar, MRExpireTimer theTimer) + { + m_Scalar = theScalar; + m_MRExpireTimer = theTimer; + } } - - public static void ClearMindRotScalar(Mobile m) - { - if (!m_Table.TryGetValue(m, out MRBucket tmpB)) - return; - - BuffInfo.RemoveBuff(m, BuffIcon.Mindrot); - tmpB.m_MRExpireTimer.Stop(); - m_Table.Remove(m); - m.SendLocalizedMessage(1060872); // Your mind feels normal again. - } - - public static bool HasMindRotScalar(Mobile m) => m_Table.ContainsKey(m); - - public static bool GetMindRotScalar(Mobile m, ref double scalar) - { - if (m_Table.TryGetValue(m, out MRBucket tmpB)) - { - scalar = tmpB.m_Scalar; - return true; - } - - return false; - } - - public static void SetMindRotScalar(Mobile caster, Mobile target, double scalar, TimeSpan duration) - { - if (!m_Table.ContainsKey(target)) - { - MRBucket tmpB = new MRBucket(scalar, new MRExpireTimer(caster, target, duration)); - m_Table.Add(target, tmpB); - BuffInfo.AddBuff(target, new BuffInfo(BuffIcon.Mindrot, 1075665, duration, target)); - tmpB.m_MRExpireTimer.Start(); - target.SendLocalizedMessage(1074384); - } - } - } - - public class MRExpireTimer : Timer - { - private readonly DateTime m_End; - private readonly Mobile m_Target; - - public MRExpireTimer(Mobile caster, Mobile target, TimeSpan delay) : base(TimeSpan.FromSeconds(1.0), - TimeSpan.FromSeconds(1.0)) - { - m_Target = target; - m_End = DateTime.UtcNow + delay; - Priority = TimerPriority.TwoFiftyMS; - } - - protected override void OnTick() - { - if (m_Target.Deleted || !m_Target.Alive || DateTime.UtcNow >= m_End) - { - MindRotSpell.ClearMindRotScalar(m_Target); - Stop(); - } - } - } - - public class MRBucket - { - public MRExpireTimer m_MRExpireTimer; - - public double m_Scalar; - - public MRBucket(double theScalar, MRExpireTimer theTimer) - { - m_Scalar = theScalar; - m_MRExpireTimer = theTimer; - } - } } diff --git a/Projects/UOContent/Spells/Necromancy/NecromancerSpell.cs b/Projects/UOContent/Spells/Necromancy/NecromancerSpell.cs index f6c5cdc95..bf400fd63 100644 --- a/Projects/UOContent/Spells/Necromancy/NecromancerSpell.cs +++ b/Projects/UOContent/Spells/Necromancy/NecromancerSpell.cs @@ -2,47 +2,48 @@ using Server.Items; namespace Server.Spells.Necromancy { - public abstract class NecromancerSpell : Spell - { - public NecromancerSpell(Mobile caster, Item scroll, SpellInfo info) : base(caster, scroll, info) + public abstract class NecromancerSpell : Spell { + public NecromancerSpell(Mobile caster, Item scroll, SpellInfo info) : base(caster, scroll, info) + { + } + + public abstract double RequiredSkill { get; } + public abstract int RequiredMana { get; } + + public override SkillName CastSkill => SkillName.Necromancy; + public override SkillName DamageSkill => SkillName.SpiritSpeak; + + // public override int CastDelayBase => base.CastDelayBase; // Reference, 3 + + public override bool ClearHandsOnCast => false; + + public override double CastDelayFastScalar => + Core.SE + ? base.CastDelayFastScalar + : 0; // Necromancer spells are not affected by fast cast items, though they are by fast cast recovery + + public override int ComputeKarmaAward() + { + // TODO: Verify this formula being that Necro spells don't HAVE a circle. + // int karma = -(70 + (10 * (int)Circle)); + var karma = -(40 + (int)(10 * (CastDelayBase.TotalSeconds / CastDelaySecondsPerTick))); + + if (Core.ML + ) // Pub 36: "Added a new property called Increased Karma Loss which grants higher karma loss for casting necromancy spells." + karma += AOS.Scale(karma, AosAttributes.GetValue(Caster, AosAttribute.IncreasedKarmaLoss)); + + return karma; + } + + public override void GetCastSkills(out double min, out double max) + { + min = RequiredSkill; + max = Scroll != null ? min : RequiredSkill + 40.0; + } + + public override bool ConsumeReagents() => base.ConsumeReagents() || ArcaneGem.ConsumeCharges(Caster, 1); + + public override int GetMana() => RequiredMana; } - - public abstract double RequiredSkill { get; } - public abstract int RequiredMana { get; } - - public override SkillName CastSkill => SkillName.Necromancy; - public override SkillName DamageSkill => SkillName.SpiritSpeak; - - // public override int CastDelayBase => base.CastDelayBase; // Reference, 3 - - public override bool ClearHandsOnCast => false; - - public override double CastDelayFastScalar => - Core.SE - ? base.CastDelayFastScalar - : 0; // Necromancer spells are not affected by fast cast items, though they are by fast cast recovery - - public override int ComputeKarmaAward() - { - // TODO: Verify this formula being that Necro spells don't HAVE a circle. - // int karma = -(70 + (10 * (int)Circle)); - int karma = -(40 + (int)(10 * (CastDelayBase.TotalSeconds / CastDelaySecondsPerTick))); - - if (Core.ML) // Pub 36: "Added a new property called Increased Karma Loss which grants higher karma loss for casting necromancy spells." - karma += AOS.Scale(karma, AosAttributes.GetValue(Caster, AosAttribute.IncreasedKarmaLoss)); - - return karma; - } - - public override void GetCastSkills(out double min, out double max) - { - min = RequiredSkill; - max = Scroll != null ? min : RequiredSkill + 40.0; - } - - public override bool ConsumeReagents() => base.ConsumeReagents() || ArcaneGem.ConsumeCharges(Caster, 1); - - public override int GetMana() => RequiredMana; - } } diff --git a/Projects/UOContent/Spells/Necromancy/PainSpike.cs b/Projects/UOContent/Spells/Necromancy/PainSpike.cs index e66627312..af667b8bc 100644 --- a/Projects/UOContent/Spells/Necromancy/PainSpike.cs +++ b/Projects/UOContent/Spells/Necromancy/PainSpike.cs @@ -5,107 +5,109 @@ using Server.Targeting; namespace Server.Spells.Necromancy { - public class PainSpikeSpell : NecromancerSpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Pain Spike", "In Sar", - 203, - 9031, - Reagent.GraveDust, - Reagent.PigIron); - - private static readonly Dictionary m_Table = new Dictionary(); - - public PainSpikeSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class PainSpikeSpell : NecromancerSpell, ISpellTargetingMobile { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Pain Spike", + "In Sar", + 203, + 9031, + Reagent.GraveDust, + Reagent.PigIron + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.0); + private static readonly Dictionary m_Table = new Dictionary(); - public override double RequiredSkill => 20.0; - public override int RequiredMana => 5; - - public override bool DelayedDamage => false; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (CheckHSequence(m)) - { - SpellHelper.Turn(Caster, m); - - // SpellHelper.CheckReflect( (int)this.Circle, Caster, ref m ); //Irrelevent after AoS - - /* Temporarily causes intense physical pain to the target, dealing direct damage. - * After 10 seconds the spell wears off, and if the target is still alive, - * some of the Hit Points lost through Pain Spike are restored. - */ - - m.FixedParticles(0x37C4, 1, 8, 9916, 39, 3, EffectLayer.Head); - m.FixedParticles(0x37C4, 1, 8, 9502, 39, 4, EffectLayer.Head); - m.PlaySound(0x210); - - double damage = Math.Max((GetDamageSkill(Caster) - GetResistSkill(m)) / 10 + (m.Player ? 18 : 30), 1); - m.CheckSkill(SkillName.MagicResist, 0.0, 120.0); // Skill check for gain - - TimeSpan buffTime = TimeSpan.FromSeconds(10.0); - - if (!m_Table.TryGetValue(m, out InternalTimer timer)) + public PainSpikeSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - m_Table[m] = timer = new InternalTimer(m, damage); - timer.Start(); - } - else - { - damage = Utility.RandomMinMax(3, 7); - timer.Delay += TimeSpan.FromSeconds(2.0); - buffTime = timer.Next - DateTime.UtcNow; } - BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.PainSpike, 1075667, buffTime, m, Convert.ToString((int)damage))); + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.0); - // TODO: Find a better way to do this - WeightOverloading.DFA = DFAlgorithm.PainSpike; - m.Damage((int)damage, Caster); - SpellHelper.DoLeech((int)damage, Caster, m); - WeightOverloading.DFA = DFAlgorithm.Standard; + public override double RequiredSkill => 20.0; + public override int RequiredMana => 5; - // SpellHelper.Damage( this, m, damage, 100, 0, 0, 0, 0, Misc.DFAlgorithm.PainSpike ); - HarmfulSpell(m); - } + public override bool DelayedDamage => false; - FinishSequence(); + public void Target(Mobile m) + { + if (m == null) + return; + + if (CheckHSequence(m)) + { + SpellHelper.Turn(Caster, m); + + // SpellHelper.CheckReflect( (int)this.Circle, Caster, ref m ); //Irrelevent after AoS + + /* Temporarily causes intense physical pain to the target, dealing direct damage. + * After 10 seconds the spell wears off, and if the target is still alive, + * some of the Hit Points lost through Pain Spike are restored. + */ + + m.FixedParticles(0x37C4, 1, 8, 9916, 39, 3, EffectLayer.Head); + m.FixedParticles(0x37C4, 1, 8, 9502, 39, 4, EffectLayer.Head); + m.PlaySound(0x210); + + var damage = Math.Max((GetDamageSkill(Caster) - GetResistSkill(m)) / 10 + (m.Player ? 18 : 30), 1); + m.CheckSkill(SkillName.MagicResist, 0.0, 120.0); // Skill check for gain + + var buffTime = TimeSpan.FromSeconds(10.0); + + if (!m_Table.TryGetValue(m, out var timer)) + { + m_Table[m] = timer = new InternalTimer(m, damage); + timer.Start(); + } + else + { + damage = Utility.RandomMinMax(3, 7); + timer.Delay += TimeSpan.FromSeconds(2.0); + buffTime = timer.Next - DateTime.UtcNow; + } + + BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.PainSpike, 1075667, buffTime, m, Convert.ToString((int)damage))); + + // TODO: Find a better way to do this + WeightOverloading.DFA = DFAlgorithm.PainSpike; + m.Damage((int)damage, Caster); + SpellHelper.DoLeech((int)damage, Caster, m); + WeightOverloading.DFA = DFAlgorithm.Standard; + + // SpellHelper.Damage( this, m, damage, 100, 0, 0, 0, 0, Misc.DFAlgorithm.PainSpike ); + HarmfulSpell(m); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } + + private class InternalTimer : Timer + { + private readonly Mobile m_Mobile; + private readonly int m_ToRestore; + + public InternalTimer(Mobile m, double toRestore) : base(TimeSpan.FromSeconds(10.0)) + { + Priority = TimerPriority.OneSecond; + + m_Mobile = m; + m_ToRestore = (int)toRestore; + } + + protected override void OnTick() + { + m_Table.Remove(m_Mobile); + + if (m_Mobile.Alive && !m_Mobile.IsDeadBondedPet) + m_Mobile.Hits += m_ToRestore; + + BuffInfo.RemoveBuff(m_Mobile, BuffIcon.PainSpike); + } + } } - - private class InternalTimer : Timer - { - private readonly Mobile m_Mobile; - private readonly int m_ToRestore; - - public InternalTimer(Mobile m, double toRestore) : base(TimeSpan.FromSeconds(10.0)) - { - Priority = TimerPriority.OneSecond; - - m_Mobile = m; - m_ToRestore = (int)toRestore; - } - - protected override void OnTick() - { - m_Table.Remove(m_Mobile); - - if (m_Mobile.Alive && !m_Mobile.IsDeadBondedPet) - m_Mobile.Hits += m_ToRestore; - - BuffInfo.RemoveBuff(m_Mobile, BuffIcon.PainSpike); - } - } - } } diff --git a/Projects/UOContent/Spells/Necromancy/PoisonStrike.cs b/Projects/UOContent/Spells/Necromancy/PoisonStrike.cs index e54715854..d99515f53 100644 --- a/Projects/UOContent/Spells/Necromancy/PoisonStrike.cs +++ b/Projects/UOContent/Spells/Necromancy/PoisonStrike.cs @@ -7,94 +7,117 @@ using Server.Targeting; namespace Server.Spells.Necromancy { - public class PoisonStrikeSpell : NecromancerSpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Poison Strike", "In Vas Nox", - 203, - 9031, - Reagent.NoxCrystal); - - public PoisonStrikeSpell(Mobile caster, Item scroll = null) - : base(caster, scroll, m_Info) + public class PoisonStrikeSpell : NecromancerSpell, ISpellTargetingMobile { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Poison Strike", + "In Vas Nox", + 203, + 9031, + Reagent.NoxCrystal + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(Core.ML ? 1.75 : 1.5); - - public override double RequiredSkill => 50.0; - public override int RequiredMana => 17; - - public override bool DelayedDamage => false; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (CheckHSequence(m)) - { - SpellHelper.Turn(Caster, m); - - /* Creates a blast of poisonous energy centered on the target. - * The main target is inflicted with a large amount of Poison damage, and all valid targets in a radius of 2 tiles around the main target are inflicted with a lesser effect. - * One tile from main target receives 50% damage, two tiles from target receives 33% damage. - */ - - // CheckResisted( m ); - // Check magic resist for skill, but do not use return value - // reports from OSI: Necro spells don't give Resist gain - - Effects.SendLocationParticles(EffectItem.Create(m.Location, m.Map, EffectItem.DefaultDuration), 0x36B0, 1, - 14, 63, 7, 9915, 0); - Effects.PlaySound(m.Location, m.Map, 0x229); - - double damage = Utility.RandomMinMax(Core.ML ? 32 : 36, 40) * ((300 + GetDamageSkill(Caster) * 9) / 1000); - - double sdiBonus = (double)AosAttributes.GetValue(Caster, AosAttribute.SpellDamage) / 100; - double pvmDamage = damage * (1 + sdiBonus); - - if (Core.ML && sdiBonus > 0.15) - sdiBonus = 0.15; - double pvpDamage = damage * (1 + sdiBonus); - - Map map = m.Map; - - if (map != null) + public PoisonStrikeSpell(Mobile caster, Item scroll = null) + : base(caster, scroll, m_Info) { - List targets = new List(); - - if (Caster.CanBeHarmful(m, false)) - targets.Add(m); - - targets.AddRange(m.GetMobilesInRange(2) - .Where(targ => !(Caster is BaseCreature && targ is BaseCreature && targ != Caster && m != targ && SpellHelper.ValidIndirectTarget(Caster, targ) && Caster.CanBeHarmful(targ, false)))); - - for (int i = 0; i < targets.Count; ++i) - { - Mobile targ = targets[i]; - int num; - - if (targ.InRange(m.Location, 0)) - num = 1; - else if (targ.InRange(m.Location, 1)) - num = 2; - else - num = 3; - - Caster.DoHarmful(targ); - SpellHelper.Damage(this, targ, (m.Player && Caster.Player ? pvpDamage : pvmDamage) / num, 0, 0, 0, - 100, 0); - } } - } - FinishSequence(); + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(Core.ML ? 1.75 : 1.5); + + public override double RequiredSkill => 50.0; + public override int RequiredMana => 17; + + public override bool DelayedDamage => false; + + public void Target(Mobile m) + { + if (m == null) + return; + + if (CheckHSequence(m)) + { + SpellHelper.Turn(Caster, m); + + /* Creates a blast of poisonous energy centered on the target. + * The main target is inflicted with a large amount of Poison damage, and all valid targets in a radius of 2 tiles around the main target are inflicted with a lesser effect. + * One tile from main target receives 50% damage, two tiles from target receives 33% damage. + */ + + // CheckResisted( m ); + // Check magic resist for skill, but do not use return value + // reports from OSI: Necro spells don't give Resist gain + + Effects.SendLocationParticles( + EffectItem.Create(m.Location, m.Map, EffectItem.DefaultDuration), + 0x36B0, + 1, + 14, + 63, + 7, + 9915, + 0 + ); + Effects.PlaySound(m.Location, m.Map, 0x229); + + var damage = Utility.RandomMinMax(Core.ML ? 32 : 36, 40) * ((300 + GetDamageSkill(Caster) * 9) / 1000); + + var sdiBonus = (double)AosAttributes.GetValue(Caster, AosAttribute.SpellDamage) / 100; + var pvmDamage = damage * (1 + sdiBonus); + + if (Core.ML && sdiBonus > 0.15) + sdiBonus = 0.15; + var pvpDamage = damage * (1 + sdiBonus); + + var map = m.Map; + + if (map != null) + { + var targets = new List(); + + if (Caster.CanBeHarmful(m, false)) + targets.Add(m); + + targets.AddRange( + m.GetMobilesInRange(2) + .Where( + targ => !(Caster is BaseCreature && targ is BaseCreature && targ != Caster && m != targ && + SpellHelper.ValidIndirectTarget(Caster, targ) && Caster.CanBeHarmful(targ, false)) + ) + ); + + for (var i = 0; i < targets.Count; ++i) + { + var targ = targets[i]; + int num; + + if (targ.InRange(m.Location, 0)) + num = 1; + else if (targ.InRange(m.Location, 1)) + num = 2; + else + num = 3; + + Caster.DoHarmful(targ); + SpellHelper.Damage( + this, + targ, + (m.Player && Caster.Player ? pvpDamage : pvmDamage) / num, + 0, + 0, + 0, + 100, + 0 + ); + } + } + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } } - } } diff --git a/Projects/UOContent/Spells/Necromancy/Strangle.cs b/Projects/UOContent/Spells/Necromancy/Strangle.cs index be4b8e995..2be755ff5 100644 --- a/Projects/UOContent/Spells/Necromancy/Strangle.cs +++ b/Projects/UOContent/Spells/Necromancy/Strangle.cs @@ -4,214 +4,217 @@ using Server.Targeting; namespace Server.Spells.Necromancy { - public class StrangleSpell : NecromancerSpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Strangle", "In Bal Nox", - 209, - 9031, - Reagent.DaemonBlood, - Reagent.NoxCrystal); - - private static readonly Dictionary m_Table = new Dictionary(); - - public StrangleSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class StrangleSpell : NecromancerSpell, ISpellTargetingMobile { + private static readonly SpellInfo m_Info = new SpellInfo( + "Strangle", + "In Bal Nox", + 209, + 9031, + Reagent.DaemonBlood, + Reagent.NoxCrystal + ); + + private static readonly Dictionary m_Table = new Dictionary(); + + public StrangleSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.0); + + public override double RequiredSkill => 65.0; + public override int RequiredMana => 29; + + public void Target(Mobile m) + { + if (m == null) + return; + + if (CheckHSequence(m)) + { + SpellHelper.Turn(Caster, m); + + // SpellHelper.CheckReflect( (int)this.Circle, Caster, ref m ); + // Irrelevent after AoS + + /* Temporarily chokes off the air suply of the target with poisonous fumes. + * The target is inflicted with poison damage over time. + * The amount of damage dealt each "hit" is based off of the caster's Spirit Speak skill and the Target's current Stamina. + * The less Stamina the target has, the more damage is done by Strangle. + * Duration of the effect is Spirit Speak skill level / 10 rounds, with a minimum number of 4 rounds. + * The first round of damage is dealt after 5 seconds, and every next round after that comes 1 second sooner than the one before, until there is only 1 second between rounds. + * The base damage of the effect lies between (Spirit Speak skill level / 10) - 2 and (Spirit Speak skill level / 10) + 1. + * Base damage is multiplied by the following formula: (3 - (target's current Stamina / target's maximum Stamina) * 2). + * Example: + * For a target at full Stamina the damage multiplier is 1, + * for a target at 50% Stamina the damage multiplier is 2 and + * for a target at 20% Stamina the damage multiplier is 2.6 + */ + + m.Spell?.OnCasterHurt(); + + m.PlaySound(0x22F); + m.FixedParticles(0x36CB, 1, 9, 9911, 67, 5, EffectLayer.Head); + m.FixedParticles(0x374A, 1, 17, 9502, 1108, 4, (EffectLayer)255); + + if (!m_Table.TryGetValue(m, out var timer)) + { + m_Table[m] = timer = new InternalTimer(m, Caster); + timer.Start(); + } + + HarmfulSpell(m); + } + + // Calculations for the buff bar + var spiritlevel = Caster.Skills.SpiritSpeak.Value / 10; + if (spiritlevel < 4) + spiritlevel = 4; + var d_MinDamage = 4; + var d_MaxDamage = ((int)spiritlevel + 1) * 3; + var args = $"{d_MinDamage}\t{d_MaxDamage}"; + + var i_Count = (int)spiritlevel; + var i_MaxCount = i_Count; + var i_HitDelay = 5; + var i_Length = i_HitDelay; + + while (i_Count > 1) + { + --i_Count; + if (i_HitDelay > 1) + { + if (i_MaxCount < 5) + { + --i_HitDelay; + } + else + { + var delay = (int)Math.Ceiling((1.0 + 5 * i_Count) / i_MaxCount); + + i_HitDelay = delay <= 5 ? delay : 5; + } + } + + i_Length += i_HitDelay; + } + + var t_Duration = TimeSpan.FromSeconds(i_Length); + BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Strangle, 1075794, 1075795, t_Duration, m, args)); + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } + + public static bool RemoveCurse(Mobile m) + { + if (!m_Table.TryGetValue(m, out var timer)) + return false; + + timer.Stop(); + m.SendLocalizedMessage(1061687); // You can breath normally again. + + m_Table.Remove(m); + return true; + } + + private class InternalTimer : Timer + { + private readonly Mobile m_From; + private readonly double m_MaxBaseDamage; + private readonly int m_MaxCount; + private readonly double m_MinBaseDamage; + private readonly Mobile m_Target; + private int m_Count; + private int m_HitDelay; + + private DateTime m_NextHit; + + public InternalTimer(Mobile target, Mobile from) : base(TimeSpan.FromSeconds(0.1), TimeSpan.FromSeconds(0.1)) + { + Priority = TimerPriority.FiftyMS; + + m_Target = target; + m_From = from; + + var spiritLevel = from.Skills.SpiritSpeak.Value / 10; + + m_MinBaseDamage = spiritLevel - 2; + m_MaxBaseDamage = spiritLevel + 1; + + m_HitDelay = 5; + m_NextHit = DateTime.UtcNow + TimeSpan.FromSeconds(m_HitDelay); + + m_Count = (int)spiritLevel; + + if (m_Count < 4) + m_Count = 4; + + m_MaxCount = m_Count; + } + + protected override void OnTick() + { + if (!m_Target.Alive) + { + m_Table.Remove(m_Target); + Stop(); + } + + if (!m_Target.Alive || DateTime.UtcNow < m_NextHit) + return; + + --m_Count; + + if (m_HitDelay > 1) + { + if (m_MaxCount < 5) + { + --m_HitDelay; + } + else + { + var delay = (int)Math.Ceiling((1.0 + 5 * m_Count) / m_MaxCount); + + if (delay <= 5) + m_HitDelay = delay; + else + m_HitDelay = 5; + } + } + + if (m_Count == 0) + { + m_Target.SendLocalizedMessage(1061687); // You can breath normally again. + m_Table.Remove(m_Target); + Stop(); + } + else + { + m_NextHit = DateTime.UtcNow + TimeSpan.FromSeconds(m_HitDelay); + + var damage = m_MinBaseDamage + Utility.RandomDouble() * (m_MaxBaseDamage - m_MinBaseDamage); + + damage *= 3 - (double)m_Target.Stam / m_Target.StamMax * 2; + + if (damage < 1) + damage = 1; + + if (!m_Target.Player) + damage *= 1.75; + + AOS.Damage(m_Target, m_From, (int)damage, 0, 0, 0, 100, 0); + + if (Utility.RandomDouble() >= 0.60 + ) // OSI: randomly revealed between first and third damage tick, guessing 60% chance + m_Target.RevealingAction(); + } + } + } } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.0); - - public override double RequiredSkill => 65.0; - public override int RequiredMana => 29; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (CheckHSequence(m)) - { - SpellHelper.Turn(Caster, m); - - // SpellHelper.CheckReflect( (int)this.Circle, Caster, ref m ); - // Irrelevent after AoS - - /* Temporarily chokes off the air suply of the target with poisonous fumes. - * The target is inflicted with poison damage over time. - * The amount of damage dealt each "hit" is based off of the caster's Spirit Speak skill and the Target's current Stamina. - * The less Stamina the target has, the more damage is done by Strangle. - * Duration of the effect is Spirit Speak skill level / 10 rounds, with a minimum number of 4 rounds. - * The first round of damage is dealt after 5 seconds, and every next round after that comes 1 second sooner than the one before, until there is only 1 second between rounds. - * The base damage of the effect lies between (Spirit Speak skill level / 10) - 2 and (Spirit Speak skill level / 10) + 1. - * Base damage is multiplied by the following formula: (3 - (target's current Stamina / target's maximum Stamina) * 2). - * Example: - * For a target at full Stamina the damage multiplier is 1, - * for a target at 50% Stamina the damage multiplier is 2 and - * for a target at 20% Stamina the damage multiplier is 2.6 - */ - - m.Spell?.OnCasterHurt(); - - m.PlaySound(0x22F); - m.FixedParticles(0x36CB, 1, 9, 9911, 67, 5, EffectLayer.Head); - m.FixedParticles(0x374A, 1, 17, 9502, 1108, 4, (EffectLayer)255); - - if (!m_Table.TryGetValue(m, out InternalTimer timer)) - { - m_Table[m] = timer = new InternalTimer(m, Caster); - timer.Start(); - } - - HarmfulSpell(m); - } - - // Calculations for the buff bar - double spiritlevel = Caster.Skills.SpiritSpeak.Value / 10; - if (spiritlevel < 4) - spiritlevel = 4; - int d_MinDamage = 4; - int d_MaxDamage = ((int)spiritlevel + 1) * 3; - string args = $"{d_MinDamage}\t{d_MaxDamage}"; - - int i_Count = (int)spiritlevel; - int i_MaxCount = i_Count; - int i_HitDelay = 5; - int i_Length = i_HitDelay; - - while (i_Count > 1) - { - --i_Count; - if (i_HitDelay > 1) - { - if (i_MaxCount < 5) - { - --i_HitDelay; - } - else - { - int delay = (int)Math.Ceiling((1.0 + 5 * i_Count) / i_MaxCount); - - i_HitDelay = delay <= 5 ? delay : 5; - } - } - - i_Length += i_HitDelay; - } - - TimeSpan t_Duration = TimeSpan.FromSeconds(i_Length); - BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Strangle, 1075794, 1075795, t_Duration, m, args)); - - FinishSequence(); - } - - public static bool RemoveCurse(Mobile m) - { - if (!m_Table.TryGetValue(m, out InternalTimer timer)) - return false; - - timer.Stop(); - m.SendLocalizedMessage(1061687); // You can breath normally again. - - m_Table.Remove(m); - return true; - } - - private class InternalTimer : Timer - { - private int m_Count; - private readonly int m_MaxCount; - private int m_HitDelay; - private readonly double m_MinBaseDamage; - private readonly double m_MaxBaseDamage; - - private DateTime m_NextHit; - private readonly Mobile m_Target; - private readonly Mobile m_From; - - public InternalTimer(Mobile target, Mobile from) : base(TimeSpan.FromSeconds(0.1), TimeSpan.FromSeconds(0.1)) - { - Priority = TimerPriority.FiftyMS; - - m_Target = target; - m_From = from; - - double spiritLevel = from.Skills.SpiritSpeak.Value / 10; - - m_MinBaseDamage = spiritLevel - 2; - m_MaxBaseDamage = spiritLevel + 1; - - m_HitDelay = 5; - m_NextHit = DateTime.UtcNow + TimeSpan.FromSeconds(m_HitDelay); - - m_Count = (int)spiritLevel; - - if (m_Count < 4) - m_Count = 4; - - m_MaxCount = m_Count; - } - - protected override void OnTick() - { - if (!m_Target.Alive) - { - m_Table.Remove(m_Target); - Stop(); - } - - if (!m_Target.Alive || DateTime.UtcNow < m_NextHit) - return; - - --m_Count; - - if (m_HitDelay > 1) - { - if (m_MaxCount < 5) - { - --m_HitDelay; - } - else - { - int delay = (int)Math.Ceiling((1.0 + 5 * m_Count) / m_MaxCount); - - if (delay <= 5) - m_HitDelay = delay; - else - m_HitDelay = 5; - } - } - - if (m_Count == 0) - { - m_Target.SendLocalizedMessage(1061687); // You can breath normally again. - m_Table.Remove(m_Target); - Stop(); - } - else - { - m_NextHit = DateTime.UtcNow + TimeSpan.FromSeconds(m_HitDelay); - - double damage = m_MinBaseDamage + Utility.RandomDouble() * (m_MaxBaseDamage - m_MinBaseDamage); - - damage *= 3 - (double)m_Target.Stam / m_Target.StamMax * 2; - - if (damage < 1) - damage = 1; - - if (!m_Target.Player) - damage *= 1.75; - - AOS.Damage(m_Target, m_From, (int)damage, 0, 0, 0, 100, 0); - - if (Utility.RandomDouble() >= 0.60) // OSI: randomly revealed between first and third damage tick, guessing 60% chance - m_Target.RevealingAction(); - } - } - } - } } diff --git a/Projects/UOContent/Spells/Necromancy/SummonFamiliar.cs b/Projects/UOContent/Spells/Necromancy/SummonFamiliar.cs index a281eefbe..89c6c4333 100644 --- a/Projects/UOContent/Spells/Necromancy/SummonFamiliar.cs +++ b/Projects/UOContent/Spells/Necromancy/SummonFamiliar.cs @@ -7,189 +7,196 @@ using Server.Utilities; namespace Server.Spells.Necromancy { - public class SummonFamiliarSpell : NecromancerSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Summon Familiar", "Kal Xen Bal", - 203, - 9031, - Reagent.BatWing, - Reagent.GraveDust, - Reagent.DaemonBlood); - - public SummonFamiliarSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class SummonFamiliarSpell : NecromancerSpell { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Summon Familiar", + "Kal Xen Bal", + 203, + 9031, + Reagent.BatWing, + Reagent.GraveDust, + Reagent.DaemonBlood + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.0); - - public override double RequiredSkill => 30.0; - public override int RequiredMana => 17; - - public static Dictionary Table { get; } = new Dictionary(); - - public static SummonFamiliarEntry[] Entries { get; } = - { - new SummonFamiliarEntry(typeof(HordeMinionFamiliar), 1060146, 30.0, 30.0), // Horde Minion - new SummonFamiliarEntry(typeof(ShadowWispFamiliar), 1060142, 50.0, 50.0), // Shadow Wisp - new SummonFamiliarEntry(typeof(DarkWolfFamiliar), 1060143, 60.0, 60.0), // Dark Wolf - new SummonFamiliarEntry(typeof(DeathAdder), 1060145, 80.0, 80.0), // Death Adder - new SummonFamiliarEntry(typeof(VampireBatFamiliar), 1060144, 100.0, 100.0) // Vampire Bat - }; - - public override bool CheckCast() - { - if (!(Table.TryGetValue(Caster, out BaseCreature check) && check?.Deleted == false)) - return base.CheckCast(); - - Caster.SendLocalizedMessage(1061605); // You already have a familiar. - return false; - } - - public override void OnCast() - { - if (CheckSequence()) - { - Caster.CloseGump(); - Caster.SendGump(new SummonFamiliarGump(Caster, Entries, this)); - } - - FinishSequence(); - } - } - - public class SummonFamiliarEntry - { - public SummonFamiliarEntry(Type type, object name, double reqNecromancy, double reqSpiritSpeak) - { - Type = type; - Name = name; - ReqNecromancy = reqNecromancy; - ReqSpiritSpeak = reqSpiritSpeak; - } - - public Type Type { get; } - - public object Name { get; } - - public double ReqNecromancy { get; } - - public double ReqSpiritSpeak { get; } - } - - public class SummonFamiliarGump : Gump - { - private const int EnabledColor16 = 0x0F20; - private const int DisabledColor16 = 0x262A; - - private const int EnabledColor32 = 0x18CD00; - private const int DisabledColor32 = 0x4A8B52; - - private readonly SummonFamiliarEntry[] m_Entries; - private readonly Mobile m_From; - - private readonly SummonFamiliarSpell m_Spell; - - public SummonFamiliarGump(Mobile from, SummonFamiliarEntry[] entries, SummonFamiliarSpell spell) : base(200, 100) - { - m_From = from; - m_Entries = entries; - m_Spell = spell; - - AddPage(0); - - AddBackground(10, 10, 250, 178, 9270); - AddAlphaRegion(20, 20, 230, 158); - - AddImage(220, 20, 10464); - AddImage(220, 72, 10464); - AddImage(220, 124, 10464); - - AddItem(188, 16, 6883); - AddItem(198, 168, 6881); - AddItem(8, 15, 6882); - AddItem(2, 168, 6880); - - AddHtmlLocalized(30, 26, 200, 20, 1060147, EnabledColor16); // Chose thy familiar... - - double necro = from.Skills.Necromancy.Value; - double spirit = from.Skills.SpiritSpeak.Value; - - for (int i = 0; i < entries.Length; ++i) - { - object name = entries[i].Name; - - bool enabled = necro >= entries[i].ReqNecromancy && spirit >= entries[i].ReqSpiritSpeak; - - AddButton(27, 53 + i * 21, 9702, 9703, i + 1); - - if (name is int intName) - AddHtmlLocalized(50, 51 + i * 21, 150, 20, intName, enabled ? EnabledColor16 : DisabledColor16); - else if (name is string strName) - AddHtml(50, 51 + i * 21, 150, 20, - $"{strName}"); - } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - int index = info.ButtonID - 1; - - if (index >= 0 && index < m_Entries.Length) - { - SummonFamiliarEntry entry = m_Entries[index]; - - double necro = m_From.Skills.Necromancy.Value; - double spirit = m_From.Skills.SpiritSpeak.Value; - - if ((m_From as PlayerMobile)?.DuelContext?.AllowSpellCast(m_From, m_Spell) == false) + public SummonFamiliarSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { } - else if (SummonFamiliarSpell.Table.TryGetValue(m_From, out BaseCreature check) && check?.Deleted == false) + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.0); + + public override double RequiredSkill => 30.0; + public override int RequiredMana => 17; + + public static Dictionary Table { get; } = new Dictionary(); + + public static SummonFamiliarEntry[] Entries { get; } = { - m_From.SendLocalizedMessage(1061605); // You already have a familiar. + new SummonFamiliarEntry(typeof(HordeMinionFamiliar), 1060146, 30.0, 30.0), // Horde Minion + new SummonFamiliarEntry(typeof(ShadowWispFamiliar), 1060142, 50.0, 50.0), // Shadow Wisp + new SummonFamiliarEntry(typeof(DarkWolfFamiliar), 1060143, 60.0, 60.0), // Dark Wolf + new SummonFamiliarEntry(typeof(DeathAdder), 1060145, 80.0, 80.0), // Death Adder + new SummonFamiliarEntry(typeof(VampireBatFamiliar), 1060144, 100.0, 100.0) // Vampire Bat + }; + + public override bool CheckCast() + { + if (!(Table.TryGetValue(Caster, out var check) && check?.Deleted == false)) + return base.CheckCast(); + + Caster.SendLocalizedMessage(1061605); // You already have a familiar. + return false; } - else if (necro < entry.ReqNecromancy || spirit < entry.ReqSpiritSpeak) + + public override void OnCast() { - // That familiar requires ~1_NECROMANCY~ Necromancy and ~2_SPIRIT~ Spirit Speak. - m_From.SendLocalizedMessage(1061606, $"{entry.ReqNecromancy:F1}\t{entry.ReqSpiritSpeak:F1}"); - - m_From.CloseGump(); - m_From.SendGump(new SummonFamiliarGump(m_From, SummonFamiliarSpell.Entries, m_Spell)); - } - else if (entry.Type == null) - { - m_From.SendMessage("That familiar has not yet been defined."); - - m_From.CloseGump(); - m_From.SendGump(new SummonFamiliarGump(m_From, SummonFamiliarSpell.Entries, m_Spell)); - } - else - { - try - { - BaseCreature bc = (BaseCreature)ActivatorUtil.CreateInstance(entry.Type); - - // TODO: Is this right? - bc.Skills.MagicResist.Base = m_From.Skills.MagicResist.Base; - - if (BaseCreature.Summon(bc, m_From, m_From.Location, -1, TimeSpan.FromDays(1.0))) + if (CheckSequence()) { - m_From.FixedParticles(0x3728, 1, 10, 9910, EffectLayer.Head); - bc.PlaySound(bc.GetIdleSound()); - SummonFamiliarSpell.Table[m_From] = bc; + Caster.CloseGump(); + Caster.SendGump(new SummonFamiliarGump(Caster, Entries, this)); + } + + FinishSequence(); + } + } + + public class SummonFamiliarEntry + { + public SummonFamiliarEntry(Type type, object name, double reqNecromancy, double reqSpiritSpeak) + { + Type = type; + Name = name; + ReqNecromancy = reqNecromancy; + ReqSpiritSpeak = reqSpiritSpeak; + } + + public Type Type { get; } + + public object Name { get; } + + public double ReqNecromancy { get; } + + public double ReqSpiritSpeak { get; } + } + + public class SummonFamiliarGump : Gump + { + private const int EnabledColor16 = 0x0F20; + private const int DisabledColor16 = 0x262A; + + private const int EnabledColor32 = 0x18CD00; + private const int DisabledColor32 = 0x4A8B52; + + private readonly SummonFamiliarEntry[] m_Entries; + private readonly Mobile m_From; + + private readonly SummonFamiliarSpell m_Spell; + + public SummonFamiliarGump(Mobile from, SummonFamiliarEntry[] entries, SummonFamiliarSpell spell) : base(200, 100) + { + m_From = from; + m_Entries = entries; + m_Spell = spell; + + AddPage(0); + + AddBackground(10, 10, 250, 178, 9270); + AddAlphaRegion(20, 20, 230, 158); + + AddImage(220, 20, 10464); + AddImage(220, 72, 10464); + AddImage(220, 124, 10464); + + AddItem(188, 16, 6883); + AddItem(198, 168, 6881); + AddItem(8, 15, 6882); + AddItem(2, 168, 6880); + + AddHtmlLocalized(30, 26, 200, 20, 1060147, EnabledColor16); // Chose thy familiar... + + var necro = from.Skills.Necromancy.Value; + var spirit = from.Skills.SpiritSpeak.Value; + + for (var i = 0; i < entries.Length; ++i) + { + var name = entries[i].Name; + + var enabled = necro >= entries[i].ReqNecromancy && spirit >= entries[i].ReqSpiritSpeak; + + AddButton(27, 53 + i * 21, 9702, 9703, i + 1); + + if (name is int intName) + AddHtmlLocalized(50, 51 + i * 21, 150, 20, intName, enabled ? EnabledColor16 : DisabledColor16); + else if (name is string strName) + AddHtml( + 50, + 51 + i * 21, + 150, + 20, + $"{strName}" + ); + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var index = info.ButtonID - 1; + + if (index >= 0 && index < m_Entries.Length) + { + var entry = m_Entries[index]; + + var necro = m_From.Skills.Necromancy.Value; + var spirit = m_From.Skills.SpiritSpeak.Value; + + if ((m_From as PlayerMobile)?.DuelContext?.AllowSpellCast(m_From, m_Spell) == false) + { + } + else if (SummonFamiliarSpell.Table.TryGetValue(m_From, out var check) && check?.Deleted == false) + { + m_From.SendLocalizedMessage(1061605); // You already have a familiar. + } + else if (necro < entry.ReqNecromancy || spirit < entry.ReqSpiritSpeak) + { + // That familiar requires ~1_NECROMANCY~ Necromancy and ~2_SPIRIT~ Spirit Speak. + m_From.SendLocalizedMessage(1061606, $"{entry.ReqNecromancy:F1}\t{entry.ReqSpiritSpeak:F1}"); + + m_From.CloseGump(); + m_From.SendGump(new SummonFamiliarGump(m_From, SummonFamiliarSpell.Entries, m_Spell)); + } + else if (entry.Type == null) + { + m_From.SendMessage("That familiar has not yet been defined."); + + m_From.CloseGump(); + m_From.SendGump(new SummonFamiliarGump(m_From, SummonFamiliarSpell.Entries, m_Spell)); + } + else + { + try + { + var bc = (BaseCreature)ActivatorUtil.CreateInstance(entry.Type); + + // TODO: Is this right? + bc.Skills.MagicResist.Base = m_From.Skills.MagicResist.Base; + + if (BaseCreature.Summon(bc, m_From, m_From.Location, -1, TimeSpan.FromDays(1.0))) + { + m_From.FixedParticles(0x3728, 1, 10, 9910, EffectLayer.Head); + bc.PlaySound(bc.GetIdleSound()); + SummonFamiliarSpell.Table[m_From] = bc; + } + } + catch + { + // ignored + } + } + } + else + { + m_From.SendLocalizedMessage(1061825); // You decide not to summon a familiar. } - } - catch - { - // ignored - } } - } - else - { - m_From.SendLocalizedMessage(1061825); // You decide not to summon a familiar. - } } - } } diff --git a/Projects/UOContent/Spells/Necromancy/TransformationSpell.cs b/Projects/UOContent/Spells/Necromancy/TransformationSpell.cs index e62c88c91..4647fbd6f 100644 --- a/Projects/UOContent/Spells/Necromancy/TransformationSpell.cs +++ b/Projects/UOContent/Spells/Necromancy/TransformationSpell.cs @@ -1,42 +1,42 @@ namespace Server.Spells.Necromancy { - public abstract class TransformationSpell : NecromancerSpell, ITransformationSpell - { - public TransformationSpell(Mobile caster, Item scroll, SpellInfo info) : base(caster, scroll, info) + public abstract class TransformationSpell : NecromancerSpell, ITransformationSpell { + public TransformationSpell(Mobile caster, Item scroll, SpellInfo info) : base(caster, scroll, info) + { + } + + public override bool BlockedByHorrificBeast => false; + public abstract int Body { get; } + public virtual int Hue => 0; + + public virtual int PhysResistOffset => 0; + public virtual int FireResistOffset => 0; + public virtual int ColdResistOffset => 0; + public virtual int PoisResistOffset => 0; + public virtual int NrgyResistOffset => 0; + + public virtual double TickRate => 1.0; + + public virtual void OnTick(Mobile m) + { + } + + public virtual void DoEffect(Mobile m) + { + } + + public virtual void RemoveEffect(Mobile m) + { + } + + public override bool CheckCast() => TransformationSpellHelper.CheckCast(Caster, this) && base.CheckCast(); + + public override void OnCast() + { + TransformationSpellHelper.OnCast(Caster, this); + + FinishSequence(); + } } - - public override bool BlockedByHorrificBeast => false; - public abstract int Body { get; } - public virtual int Hue => 0; - - public virtual int PhysResistOffset => 0; - public virtual int FireResistOffset => 0; - public virtual int ColdResistOffset => 0; - public virtual int PoisResistOffset => 0; - public virtual int NrgyResistOffset => 0; - - public virtual double TickRate => 1.0; - - public virtual void OnTick(Mobile m) - { - } - - public virtual void DoEffect(Mobile m) - { - } - - public virtual void RemoveEffect(Mobile m) - { - } - - public override bool CheckCast() => TransformationSpellHelper.CheckCast(Caster, this) && base.CheckCast(); - - public override void OnCast() - { - TransformationSpellHelper.OnCast(Caster, this); - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Necromancy/VampiricEmbrace.cs b/Projects/UOContent/Spells/Necromancy/VampiricEmbrace.cs index cc255613e..c7dd3ea27 100644 --- a/Projects/UOContent/Spells/Necromancy/VampiricEmbrace.cs +++ b/Projects/UOContent/Spells/Necromancy/VampiricEmbrace.cs @@ -3,50 +3,68 @@ using Server.Items; namespace Server.Spells.Necromancy { - public class VampiricEmbraceSpell : TransformationSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Vampiric Embrace", "Rel Xen An Sanct", - 203, - 9031, - Reagent.BatWing, - Reagent.NoxCrystal, - Reagent.PigIron); - - public VampiricEmbraceSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class VampiricEmbraceSpell : TransformationSpell { + private static readonly SpellInfo m_Info = new SpellInfo( + "Vampiric Embrace", + "Rel Xen An Sanct", + 203, + 9031, + Reagent.BatWing, + Reagent.NoxCrystal, + Reagent.PigIron + ); + + public VampiricEmbraceSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.0); + + public override double RequiredSkill => 99.0; + public override int RequiredMana => 23; + + public override int Body => Caster.Female ? 745 : 744; + public override int Hue => 0x847E; + + public override int FireResistOffset => -25; + + public override void GetCastSkills(out double min, out double max) + { + if (Caster.Skills[CastSkill].Value >= RequiredSkill) + { + min = 80.0; + max = 120.0; + } + else + { + base.GetCastSkills(out min, out max); + } + } + + public override void DoEffect(Mobile m) + { + Effects.SendLocationParticles( + EffectItem.Create(m.Location, m.Map, EffectItem.DefaultDuration), + 0x373A, + 1, + 17, + 1108, + 7, + 9914, + 0 + ); + Effects.SendLocationParticles( + EffectItem.Create(m.Location, m.Map, EffectItem.DefaultDuration), + 0x376A, + 1, + 22, + 67, + 7, + 9502, + 0 + ); + Effects.PlaySound(m.Location, m.Map, 0x4B1); + } } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.0); - - public override double RequiredSkill => 99.0; - public override int RequiredMana => 23; - - public override int Body => Caster.Female ? 745 : 744; - public override int Hue => 0x847E; - - public override int FireResistOffset => -25; - - public override void GetCastSkills(out double min, out double max) - { - if (Caster.Skills[CastSkill].Value >= RequiredSkill) - { - min = 80.0; - max = 120.0; - } - else - { - base.GetCastSkills(out min, out max); - } - } - - public override void DoEffect(Mobile m) - { - Effects.SendLocationParticles(EffectItem.Create(m.Location, m.Map, EffectItem.DefaultDuration), 0x373A, 1, 17, - 1108, 7, 9914, 0); - Effects.SendLocationParticles(EffectItem.Create(m.Location, m.Map, EffectItem.DefaultDuration), 0x376A, 1, 22, - 67, 7, 9502, 0); - Effects.PlaySound(m.Location, m.Map, 0x4B1); - } - } } diff --git a/Projects/UOContent/Spells/Necromancy/VengefulSpirit.cs b/Projects/UOContent/Spells/Necromancy/VengefulSpirit.cs index 415f956a3..f30318446 100644 --- a/Projects/UOContent/Spells/Necromancy/VengefulSpirit.cs +++ b/Projects/UOContent/Spells/Necromancy/VengefulSpirit.cs @@ -4,71 +4,81 @@ using Server.Targeting; namespace Server.Spells.Necromancy { - public class VengefulSpiritSpell : NecromancerSpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Vengeful Spirit", "Kal Xen Bal Beh", - 203, - 9031, - Reagent.BatWing, - Reagent.GraveDust, - Reagent.PigIron); - - public VengefulSpiritSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class VengefulSpiritSpell : NecromancerSpell, ISpellTargetingMobile { + private static readonly SpellInfo m_Info = new SpellInfo( + "Vengeful Spirit", + "Kal Xen Bal Beh", + 203, + 9031, + Reagent.BatWing, + Reagent.GraveDust, + Reagent.PigIron + ); + + public VengefulSpiritSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.0); + + public override double RequiredSkill => 80.0; + public override int RequiredMana => 41; + + public void Target(Mobile m) + { + if (m == null) + return; + + if (Caster == m) + { + Caster.SendLocalizedMessage(1061832); // You cannot exact vengeance on yourself. + } + else if (CheckHSequence(m)) + { + SpellHelper.Turn(Caster, m); + + /* Summons a Revenant which haunts the target until either the target or the Revenant is dead. + * Revenants have the ability to track down their targets wherever they may travel. + * A Revenant's strength is determined by the Necromancy and Spirit Speak skills of the Caster. + * The effect lasts for ((Spirit Speak skill level * 80) / 120) + 10 seconds. + */ + + var duration = TimeSpan.FromSeconds(GetDamageSkill(Caster) * 80 / 120 + 10); + + var rev = new Revenant(Caster, m, duration); + + if (BaseCreature.Summon( + rev, + false, + Caster, + m.Location, + 0x81, + TimeSpan.FromSeconds(duration.TotalSeconds + 2.0) + )) + rev.FixedParticles(0x373A, 1, 15, 9909, EffectLayer.Waist); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } + + public override bool CheckCast() + { + if (!base.CheckCast()) + return false; + + if (Caster.Followers + 3 > Caster.FollowersMax) + { + Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. + return false; + } + + return true; + } } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.0); - - public override double RequiredSkill => 80.0; - public override int RequiredMana => 41; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - public override bool CheckCast() - { - if (!base.CheckCast()) - return false; - - if (Caster.Followers + 3 > Caster.FollowersMax) - { - Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. - return false; - } - - return true; - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (Caster == m) - Caster.SendLocalizedMessage(1061832); // You cannot exact vengeance on yourself. - else if (CheckHSequence(m)) - { - SpellHelper.Turn(Caster, m); - - /* Summons a Revenant which haunts the target until either the target or the Revenant is dead. - * Revenants have the ability to track down their targets wherever they may travel. - * A Revenant's strength is determined by the Necromancy and Spirit Speak skills of the Caster. - * The effect lasts for ((Spirit Speak skill level * 80) / 120) + 10 seconds. - */ - - TimeSpan duration = TimeSpan.FromSeconds(GetDamageSkill(Caster) * 80 / 120 + 10); - - Revenant rev = new Revenant(Caster, m, duration); - - if (BaseCreature.Summon(rev, false, Caster, m.Location, 0x81, - TimeSpan.FromSeconds(duration.TotalSeconds + 2.0))) - rev.FixedParticles(0x373A, 1, 15, 9909, EffectLayer.Waist); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Necromancy/Wither.cs b/Projects/UOContent/Spells/Necromancy/Wither.cs index ca03c4fb7..82dafcf62 100644 --- a/Projects/UOContent/Spells/Necromancy/Wither.cs +++ b/Projects/UOContent/Spells/Necromancy/Wither.cs @@ -5,102 +5,112 @@ using Server.Mobiles; namespace Server.Spells.Necromancy { - public class WitherSpell : NecromancerSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Wither", "Kal Vas An Flam", - 203, - 9031, - Reagent.NoxCrystal, - Reagent.GraveDust, - Reagent.PigIron); - - public WitherSpell(Mobile caster, Item scroll = null) - : base(caster, scroll, m_Info) + public class WitherSpell : NecromancerSpell { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Wither", + "Kal Vas An Flam", + 203, + 9031, + Reagent.NoxCrystal, + Reagent.GraveDust, + Reagent.PigIron + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); - - public override double RequiredSkill => 60.0; - - public override int RequiredMana => 23; - - public override bool DelayedDamage => false; - - public override void OnCast() - { - if (CheckSequence()) - { - /* Creates a withering frost around the Caster, - * which deals Cold Damage to all valid targets in a radius of 5 tiles. - */ - - Map map = Caster.Map; - - if (map != null) + public WitherSpell(Mobile caster, Item scroll = null) + : base(caster, scroll, m_Info) { - List targets = new List(); + } - BaseCreature cbc = Caster as BaseCreature; - bool isMonster = cbc?.Controlled == false && !cbc.Summoned; + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); - foreach (Mobile m in Caster.GetMobilesInRange(Core.ML ? 4 : 5)) - if (Caster != m && Caster.InLOS(m) && (isMonster || SpellHelper.ValidIndirectTarget(Caster, m)) && - Caster.CanBeHarmful(m, false)) + public override double RequiredSkill => 60.0; + + public override int RequiredMana => 23; + + public override bool DelayedDamage => false; + + public override void OnCast() + { + if (CheckSequence()) { - if (isMonster) - { - if (m is BaseCreature bc) - { - if (!bc.Controlled && !bc.Summoned && bc.Team == cbc.Team) - continue; - } - else if (!m.Player) - { - continue; - } - } + /* Creates a withering frost around the Caster, + * which deals Cold Damage to all valid targets in a radius of 5 tiles. + */ - targets.Add(m); + var map = Caster.Map; + + if (map != null) + { + var targets = new List(); + + var cbc = Caster as BaseCreature; + var isMonster = cbc?.Controlled == false && !cbc.Summoned; + + foreach (var m in Caster.GetMobilesInRange(Core.ML ? 4 : 5)) + if (Caster != m && Caster.InLOS(m) && (isMonster || SpellHelper.ValidIndirectTarget(Caster, m)) && + Caster.CanBeHarmful(m, false)) + { + if (isMonster) + { + if (m is BaseCreature bc) + { + if (!bc.Controlled && !bc.Summoned && bc.Team == cbc.Team) + continue; + } + else if (!m.Player) + { + continue; + } + } + + targets.Add(m); + } + + Effects.PlaySound(Caster.Location, map, 0x1FB); + Effects.PlaySound(Caster.Location, map, 0x10B); + Effects.SendLocationParticles( + EffectItem.Create(Caster.Location, map, EffectItem.DefaultDuration), + 0x37CC, + 1, + 40, + 97, + 3, + 9917, + 0 + ); + + for (var i = 0; i < targets.Count; ++i) + { + var m = targets[i]; + + Caster.DoHarmful(m); + m.FixedParticles(0x374A, 1, 15, 9502, 97, 3, (EffectLayer)255); + + double damage = Utility.RandomMinMax(30, 35); + + damage *= 300 + m.Karma / 100 + GetDamageSkill(Caster) * 10; + damage /= 1000; + + var sdiBonus = AosAttributes.GetValue(Caster, AosAttribute.SpellDamage); + + // PvP spell damage increase cap of 15% from an item�s magic property in Publish 33(SE) + if (Core.SE && m.Player && Caster.Player && sdiBonus > 15) + sdiBonus = 15; + + damage *= 100 + sdiBonus; + damage /= 100; + + // TODO: cap? + // if (damage > 40) + // damage = 40; + + SpellHelper.Damage(this, m, damage, 0, 0, 100, 0, 0); + } + } } - Effects.PlaySound(Caster.Location, map, 0x1FB); - Effects.PlaySound(Caster.Location, map, 0x10B); - Effects.SendLocationParticles(EffectItem.Create(Caster.Location, map, EffectItem.DefaultDuration), - 0x37CC, 1, 40, 97, 3, 9917, 0); - - for (int i = 0; i < targets.Count; ++i) - { - Mobile m = targets[i]; - - Caster.DoHarmful(m); - m.FixedParticles(0x374A, 1, 15, 9502, 97, 3, (EffectLayer)255); - - double damage = Utility.RandomMinMax(30, 35); - - damage *= 300 + m.Karma / 100 + GetDamageSkill(Caster) * 10; - damage /= 1000; - - int sdiBonus = AosAttributes.GetValue(Caster, AosAttribute.SpellDamage); - - // PvP spell damage increase cap of 15% from an item�s magic property in Publish 33(SE) - if (Core.SE && m.Player && Caster.Player && sdiBonus > 15) - sdiBonus = 15; - - damage *= 100 + sdiBonus; - damage /= 100; - - // TODO: cap? - // if (damage > 40) - // damage = 40; - - SpellHelper.Damage(this, m, damage, 0, 0, 100, 0, 0); - } + FinishSequence(); } - } - - FinishSequence(); } - } } diff --git a/Projects/UOContent/Spells/Necromancy/WraithForm.cs b/Projects/UOContent/Spells/Necromancy/WraithForm.cs index 92236dd04..f88bf1739 100644 --- a/Projects/UOContent/Spells/Necromancy/WraithForm.cs +++ b/Projects/UOContent/Spells/Necromancy/WraithForm.cs @@ -3,46 +3,48 @@ using Server.Mobiles; namespace Server.Spells.Necromancy { - public class WraithFormSpell : TransformationSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Wraith Form", "Rel Xen Um", - 203, - 9031, - Reagent.NoxCrystal, - Reagent.PigIron); - - public WraithFormSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class WraithFormSpell : TransformationSpell { + private static readonly SpellInfo m_Info = new SpellInfo( + "Wraith Form", + "Rel Xen Um", + 203, + 9031, + Reagent.NoxCrystal, + Reagent.PigIron + ); + + public WraithFormSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.0); + + public override double RequiredSkill => 20.0; + public override int RequiredMana => 17; + + public override int Body => Caster.Female ? 747 : 748; + public override int Hue => Caster.Female ? 0 : 0x4001; + + public override int PhysResistOffset => +15; + public override int FireResistOffset => -5; + public override int ColdResistOffset => 0; + public override int PoisResistOffset => 0; + public override int NrgyResistOffset => -5; + + public override void DoEffect(Mobile m) + { + if (m is PlayerMobile mobile) + mobile.IgnoreMobiles = true; + + m.PlaySound(0x17F); + m.FixedParticles(0x374A, 1, 15, 9902, 1108, 4, EffectLayer.Waist); + } + + public override void RemoveEffect(Mobile m) + { + if (m is PlayerMobile mobile && mobile.AccessLevel == AccessLevel.Player) + mobile.IgnoreMobiles = false; + } } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.0); - - public override double RequiredSkill => 20.0; - public override int RequiredMana => 17; - - public override int Body => Caster.Female ? 747 : 748; - public override int Hue => Caster.Female ? 0 : 0x4001; - - public override int PhysResistOffset => +15; - public override int FireResistOffset => -5; - public override int ColdResistOffset => 0; - public override int PoisResistOffset => 0; - public override int NrgyResistOffset => -5; - - public override void DoEffect(Mobile m) - { - if (m is PlayerMobile mobile) - mobile.IgnoreMobiles = true; - - m.PlaySound(0x17F); - m.FixedParticles(0x374A, 1, 15, 9902, 1108, 4, EffectLayer.Waist); - } - - public override void RemoveEffect(Mobile m) - { - if (m is PlayerMobile mobile && mobile.AccessLevel == AccessLevel.Player) - mobile.IgnoreMobiles = false; - } - } } diff --git a/Projects/UOContent/Spells/Ninjitsu/AnimalForm.cs b/Projects/UOContent/Spells/Ninjitsu/AnimalForm.cs index f72850332..253b6fc0d 100644 --- a/Projects/UOContent/Spells/Ninjitsu/AnimalForm.cs +++ b/Projects/UOContent/Spells/Ninjitsu/AnimalForm.cs @@ -9,580 +9,604 @@ using Server.Spells.Seventh; namespace Server.Spells.Ninjitsu { - public class AnimalForm : NinjaSpell - { - public enum MorphResult + public class AnimalForm : NinjaSpell { - Success, - Fail, - NoSkill - } - - private static readonly SpellInfo m_Info = new SpellInfo( - "Animal Form", null, - -1, - 9002); - - private static readonly Dictionary m_LastAnimalForms = new Dictionary(); - private static readonly Dictionary m_Table = new Dictionary(); - - private bool m_WasMoving; - - public AnimalForm(Mobile caster, Item scroll) - : base(caster, scroll, m_Info) - { - } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.0); - - public override double RequiredSkill => 0.0; - public override int RequiredMana => Core.ML ? 10 : 0; - public override int CastRecoveryBase => Core.ML ? 10 : base.CastRecoveryBase; - - public override bool BlockedByAnimalForm => false; - - public static AnimalFormEntry[] Entries { get; } = - { - new AnimalFormEntry(typeof(Kirin), 1029632, 9632, 0, 1070811, 100.0, 0x84, 0, 0), - new AnimalFormEntry(typeof(Unicorn), 1018214, 9678, 0, 1070812, 100.0, 0x7A, 0, 0), - new AnimalFormEntry(typeof(BakeKitsune), 1030083, 10083, 0, 1070810, 82.5, 0xF6, 0, 0), - new AnimalFormEntry(typeof(GreyWolf), 1028482, 9681, 2309, 1070810, 82.5, 0x19, 0x8FD, 0x90E), - new AnimalFormEntry(typeof(Llama), 1028438, 8438, 0, 1070809, 70.0, 0xDC, 0, 0), - new AnimalFormEntry(typeof(ForestOstard), 1018273, 8503, 2212, 1070809, 70.0, 0xDB, 0x899, 0x8B0), - new AnimalFormEntry(typeof(BullFrog), 1028496, 8496, 2003, 1070807, 50.0, 0x51, 0x7D1, 0x7D6, false, false), - new AnimalFormEntry(typeof(GiantSerpent), 1018114, 9663, 2009, 1070808, 50.0, 0x15, 0x7D1, 0x7E2, false, false), - new AnimalFormEntry(typeof(Dog), 1018280, 8476, 2309, 1070806, 40.0, 0xD9, 0x8FD, 0x90E, false, false), - new AnimalFormEntry(typeof(Cat), 1018264, 8475, 2309, 1070806, 40.0, 0xC9, 0x8FD, 0x90E, false, false), - new AnimalFormEntry(typeof(Rat), 1018294, 8483, 2309, 1070805, 20.0, 0xEE, 0x8FD, 0x90E, true, false), - new AnimalFormEntry(typeof(Rabbit), 1028485, 8485, 2309, 1070805, 20.0, 0xCD, 0x8FD, 0x90E, true, false), - new AnimalFormEntry(typeof(Squirrel), 1031671, 11671, 0, 0, 20.0, 0x116, 0, 0, false, false), - new AnimalFormEntry(typeof(Ferret), 1031672, 11672, 0, 1075220, 40.0, 0x117, 0, 0, false, false, true), - new AnimalFormEntry(typeof(CuSidhe), 1031670, 11670, 0, 1075221, 60.0, 0x115, 0, 0, false, false), - new AnimalFormEntry(typeof(Reptalon), 1075202, 11669, 0, 1075222, 90.0, 0x114, 0, 0, false, false) - }; - - public static void Initialize() - { - EventSink.Login += OnLogin; - } - - public static void OnLogin(Mobile m) - { - if (GetContext(m)?.SpeedBoost == true) - m.Send(SpeedControl.MountSpeed); - } - - public override bool CheckCast() - { - if (!Caster.CanBeginAction()) - { - Caster.SendLocalizedMessage(1061628); // You can't do that while polymorphed. - return false; - } - - if (TransformationSpellHelper.UnderTransformation(Caster)) - { - Caster.SendLocalizedMessage(1063219); // You cannot mimic an animal while in that form. - return false; - } - - if (DisguiseTimers.IsDisguised(Caster)) - { - Caster.SendLocalizedMessage(1061631); // You can't do that while disguised. - return false; - } - - return base.CheckCast(); - } - - public override bool CheckDisturb(DisturbType type, bool firstCircle, bool resistable) => false; - - private bool CasterIsMoving() => Core.TickCount - Caster.LastMoveTime <= Caster.ComputeMovementSpeed(Caster.Direction); - - public override void OnBeginCast() - { - base.OnBeginCast(); - - Caster.FixedEffect(0x37C4, 10, 14, 4, 3); - m_WasMoving = CasterIsMoving(); - } - - public override bool CheckFizzle() => true; - - public override void OnCast() - { - if (!Caster.CanBeginAction()) - { - Caster.SendLocalizedMessage(1061628); // You can't do that while polymorphed. - } - else if (TransformationSpellHelper.UnderTransformation(Caster)) - { - Caster.SendLocalizedMessage(1063219); // You cannot mimic an animal while in that form. - } - else if (!Caster.CanBeginAction() || (Caster.IsBodyMod && GetContext(Caster) == null)) - { - DoFizzle(); - } - else if (CheckSequence()) - { - AnimalFormContext context = GetContext(Caster); - - int mana = ScaleMana(RequiredMana); - if (mana > Caster.Mana) + public enum MorphResult { - Caster.SendLocalizedMessage(1060174, - mana.ToString()); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability. + Success, + Fail, + NoSkill } - else if (context != null) - { - RemoveContext(Caster, context, true); - Caster.Mana -= mana; - } - else if (Caster is PlayerMobile) - { - bool skipGump = m_WasMoving || CasterIsMoving(); - if (GetLastAnimalForm(Caster) == -1 || !skipGump) - { - Caster.CloseGump(); - Caster.SendGump(new AnimalFormGump(Caster, Entries, this)); - } - else - { - if (Morph(Caster, GetLastAnimalForm(Caster)) == MorphResult.Fail) + private static readonly SpellInfo m_Info = new SpellInfo( + "Animal Form", + null, + -1, + 9002 + ); + + private static readonly Dictionary m_LastAnimalForms = new Dictionary(); + private static readonly Dictionary m_Table = new Dictionary(); + + private bool m_WasMoving; + + public AnimalForm(Mobile caster, Item scroll) + : base(caster, scroll, m_Info) + { + } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.0); + + public override double RequiredSkill => 0.0; + public override int RequiredMana => Core.ML ? 10 : 0; + public override int CastRecoveryBase => Core.ML ? 10 : base.CastRecoveryBase; + + public override bool BlockedByAnimalForm => false; + + public static AnimalFormEntry[] Entries { get; } = + { + new AnimalFormEntry(typeof(Kirin), 1029632, 9632, 0, 1070811, 100.0, 0x84, 0, 0), + new AnimalFormEntry(typeof(Unicorn), 1018214, 9678, 0, 1070812, 100.0, 0x7A, 0, 0), + new AnimalFormEntry(typeof(BakeKitsune), 1030083, 10083, 0, 1070810, 82.5, 0xF6, 0, 0), + new AnimalFormEntry(typeof(GreyWolf), 1028482, 9681, 2309, 1070810, 82.5, 0x19, 0x8FD, 0x90E), + new AnimalFormEntry(typeof(Llama), 1028438, 8438, 0, 1070809, 70.0, 0xDC, 0, 0), + new AnimalFormEntry(typeof(ForestOstard), 1018273, 8503, 2212, 1070809, 70.0, 0xDB, 0x899, 0x8B0), + new AnimalFormEntry(typeof(BullFrog), 1028496, 8496, 2003, 1070807, 50.0, 0x51, 0x7D1, 0x7D6, false, false), + new AnimalFormEntry(typeof(GiantSerpent), 1018114, 9663, 2009, 1070808, 50.0, 0x15, 0x7D1, 0x7E2, false, false), + new AnimalFormEntry(typeof(Dog), 1018280, 8476, 2309, 1070806, 40.0, 0xD9, 0x8FD, 0x90E, false, false), + new AnimalFormEntry(typeof(Cat), 1018264, 8475, 2309, 1070806, 40.0, 0xC9, 0x8FD, 0x90E, false, false), + new AnimalFormEntry(typeof(Rat), 1018294, 8483, 2309, 1070805, 20.0, 0xEE, 0x8FD, 0x90E, true, false), + new AnimalFormEntry(typeof(Rabbit), 1028485, 8485, 2309, 1070805, 20.0, 0xCD, 0x8FD, 0x90E, true, false), + new AnimalFormEntry(typeof(Squirrel), 1031671, 11671, 0, 0, 20.0, 0x116, 0, 0, false, false), + new AnimalFormEntry(typeof(Ferret), 1031672, 11672, 0, 1075220, 40.0, 0x117, 0, 0, false, false, true), + new AnimalFormEntry(typeof(CuSidhe), 1031670, 11670, 0, 1075221, 60.0, 0x115, 0, 0, false, false), + new AnimalFormEntry(typeof(Reptalon), 1075202, 11669, 0, 1075222, 90.0, 0x114, 0, 0, false, false) + }; + + public static void Initialize() + { + EventSink.Login += OnLogin; + } + + public static void OnLogin(Mobile m) + { + if (GetContext(m)?.SpeedBoost == true) + m.Send(SpeedControl.MountSpeed); + } + + public override bool CheckCast() + { + if (!Caster.CanBeginAction()) { - DoFizzle(); + Caster.SendLocalizedMessage(1061628); // You can't do that while polymorphed. + return false; + } + + if (TransformationSpellHelper.UnderTransformation(Caster)) + { + Caster.SendLocalizedMessage(1063219); // You cannot mimic an animal while in that form. + return false; + } + + if (DisguiseTimers.IsDisguised(Caster)) + { + Caster.SendLocalizedMessage(1061631); // You can't do that while disguised. + return false; + } + + return base.CheckCast(); + } + + public override bool CheckDisturb(DisturbType type, bool firstCircle, bool resistable) => false; + + private bool CasterIsMoving() => + Core.TickCount - Caster.LastMoveTime <= Caster.ComputeMovementSpeed(Caster.Direction); + + public override void OnBeginCast() + { + base.OnBeginCast(); + + Caster.FixedEffect(0x37C4, 10, 14, 4, 3); + m_WasMoving = CasterIsMoving(); + } + + public override bool CheckFizzle() => true; + + public override void OnCast() + { + if (!Caster.CanBeginAction()) + { + Caster.SendLocalizedMessage(1061628); // You can't do that while polymorphed. + } + else if (TransformationSpellHelper.UnderTransformation(Caster)) + { + Caster.SendLocalizedMessage(1063219); // You cannot mimic an animal while in that form. + } + else if (!Caster.CanBeginAction() || Caster.IsBodyMod && GetContext(Caster) == null) + { + DoFizzle(); + } + else if (CheckSequence()) + { + var context = GetContext(Caster); + + var mana = ScaleMana(RequiredMana); + if (mana > Caster.Mana) + { + Caster.SendLocalizedMessage( + 1060174, + mana.ToString() + ); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability. + } + else if (context != null) + { + RemoveContext(Caster, context, true); + Caster.Mana -= mana; + } + else if (Caster is PlayerMobile) + { + var skipGump = m_WasMoving || CasterIsMoving(); + + if (GetLastAnimalForm(Caster) == -1 || !skipGump) + { + Caster.CloseGump(); + Caster.SendGump(new AnimalFormGump(Caster, Entries, this)); + } + else + { + if (Morph(Caster, GetLastAnimalForm(Caster)) == MorphResult.Fail) + { + DoFizzle(); + } + else + { + Caster.FixedParticles(0x3728, 10, 13, 2023, EffectLayer.Waist); + Caster.Mana -= mana; + } + } + } + else + { + if (Morph(Caster, GetLastAnimalForm(Caster)) == MorphResult.Fail) + { + DoFizzle(); + } + else + { + Caster.FixedParticles(0x3728, 10, 13, 2023, EffectLayer.Waist); + Caster.Mana -= mana; + } + } + } + + FinishSequence(); + } + + public int GetLastAnimalForm(Mobile m) => m_LastAnimalForms.TryGetValue(m, out var value) ? value : -1; + + public static MorphResult Morph(Mobile m, int entryID) + { + if (entryID < 0 || entryID >= Entries.Length) + return MorphResult.Fail; + + var entry = Entries[entryID]; + + m_LastAnimalForms[m] = entryID; // On OSI, it's the last /attempted/ one not the last succeeded one + + if (m.Skills.Ninjitsu.Value < entry.ReqSkill) + { + var args = $"{entry.ReqSkill:F1}\t{SkillName.Ninjitsu}\t "; + m.SendLocalizedMessage( + 1063013, + args + ); // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability. + return MorphResult.NoSkill; + } + + /* + if (!m.CheckSkill( SkillName.Ninjitsu, entry.ReqSkill, entry.ReqSkill + 37.5 )) + return MorphResult.Fail; + * + * On OSI,it seems you can only gain starting at '0' using Animal form. + */ + + var ninjitsu = m.Skills.Ninjitsu.Value; + + if (ninjitsu < entry.ReqSkill + 37.5) + { + var chance = (ninjitsu - entry.ReqSkill) / 37.5; + + if (chance < Utility.RandomDouble()) + return MorphResult.Fail; + } + + m.CheckSkill(SkillName.Ninjitsu, 0.0, 37.5); + + if (!BaseFormTalisman.EntryEnabled(m, entry.Type)) + return MorphResult.Success; // Still consumes mana, just no effect + + BaseMount.Dismount(m); + + var bodyMod = entry.BodyMod; + var hueMod = entry.HueMod; + + m.BodyMod = bodyMod; + m.HueMod = hueMod; + + if (entry.SpeedBoost) + m.Send(SpeedControl.MountSpeed); + + SkillMod mod = null; + + if (entry.StealthBonus) + { + mod = new DefaultSkillMod(SkillName.Stealth, true, 20.0) { ObeyCap = true }; + m.AddSkillMod(mod); + } + + SkillMod stealingMod = null; + + if (entry.StealingBonus) + { + stealingMod = new DefaultSkillMod(SkillName.Stealing, true, 10.0) { ObeyCap = true }; + m.AddSkillMod(stealingMod); + } + + Timer timer = new AnimalFormTimer(m, bodyMod, hueMod); + timer.Start(); + + AddContext(m, new AnimalFormContext(timer, mod, entry.SpeedBoost, entry.Type, stealingMod)); + m.CheckStatTimers(); + return MorphResult.Success; + } + + public static void AddContext(Mobile m, AnimalFormContext context) + { + m_Table[m] = context; + + if (context.Type == typeof(BakeKitsune) || context.Type == typeof(GreyWolf)) + m.CheckStatTimers(); + } + + public static void RemoveContext(Mobile m, bool resetGraphics) + { + var context = GetContext(m); + + if (context != null) + RemoveContext(m, context, resetGraphics); + } + + public static void RemoveContext(Mobile m, AnimalFormContext context, bool resetGraphics) + { + m_Table.Remove(m); + + if (context.SpeedBoost) + m.Send(SpeedControl.Disable); + + var mod = context.Mod; + + if (mod != null) + m.RemoveSkillMod(mod); + + mod = context.StealingMod; + + if (mod != null) + m.RemoveSkillMod(mod); + + if (resetGraphics) + { + m.HueMod = -1; + m.BodyMod = 0; + } + + m.FixedParticles(0x3728, 10, 13, 2023, EffectLayer.Waist); + + context.Timer.Stop(); + } + + public static AnimalFormContext GetContext(Mobile m) => m_Table.TryGetValue(m, out var context) ? context : null; + + public static bool UnderTransformation(Mobile m) => m_Table.ContainsKey(m); + + public static bool UnderTransformation(Mobile m, Type type) => GetContext(m)?.Type == type; + + /* + private delegate void AnimalFormCallback( Mobile from ); + private delegate bool AnimalFormRequirementCallback( Mobile from ); + */ + + public class AnimalFormEntry + { + private readonly int m_HueModMax; + + private readonly int m_HueModMin; + /* + private AnimalFormCallback m_TransformCallback; + private AnimalFormCallback m_UntransformCallback; + private AnimalFormRequirementCallback m_RequirementCallback; + */ + + public AnimalFormEntry( + Type type, TextDefinition name, int itemID, int hue, int tooltip, double reqSkill, + int bodyMod, int hueModMin, int hueModMax, bool stealthBonus = false, bool speedBoost = true, + bool stealingBonus = false + ) + { + Type = type; + Name = name; + ItemID = itemID; + Hue = hue; + Tooltip = tooltip; + ReqSkill = reqSkill; + BodyMod = bodyMod; + m_HueModMin = hueModMin; + m_HueModMax = hueModMax; + StealthBonus = stealthBonus; + SpeedBoost = speedBoost; + StealingBonus = stealingBonus; + } + + public Type Type { get; } + + public TextDefinition Name { get; } + + public int ItemID { get; } + + public int Hue { get; } + + public int Tooltip { get; } + + public double ReqSkill { get; } + + public int BodyMod { get; } + + public int HueMod => Utility.RandomMinMax(m_HueModMin, m_HueModMax); + public bool StealthBonus { get; } + + public bool SpeedBoost { get; } + + public bool StealingBonus { get; } + } + + public class AnimalFormGump : Gump + { + // TODO: Convert this for ML to the BaseImageTileButtonsGump + private readonly Mobile m_Caster; + private readonly AnimalForm m_Spell; + + public AnimalFormGump(Mobile caster, AnimalFormEntry[] entries, AnimalForm spell) + : base(50, 50) + { + m_Caster = caster; + m_Spell = spell; + + AddPage(0); + + AddBackground(0, 0, 520, 404, 0x13BE); + AddImageTiled(10, 10, 500, 20, 0xA40); + AddImageTiled(10, 40, 500, 324, 0xA40); + AddImageTiled(10, 374, 500, 20, 0xA40); + AddAlphaRegion(10, 10, 500, 384); + + AddHtmlLocalized(14, 12, 500, 20, 1063394, 0x7FFF); //
Polymorph Selection Menu
+ + AddButton(10, 374, 0xFB1, 0xFB2, 0); + AddHtmlLocalized(45, 376, 450, 20, 1011012, 0x7FFF); // CANCEL + + var ninjitsu = caster.Skills.Ninjitsu.Value; + + var current = 0; + + for (var i = 0; i < entries.Length; ++i) + { + var enabled = ninjitsu >= entries[i].ReqSkill && BaseFormTalisman.EntryEnabled(caster, entries[i].Type); + + var page = current / 10 + 1; + var pos = current % 10; + + if (pos == 0) + { + if (page > 1) + { + AddButton(400, 374, 0xFA5, 0xFA7, 0, GumpButtonType.Page, page); + AddHtmlLocalized(440, 376, 60, 20, 1043353, 0x7FFF); // Next + } + + AddPage(page); + + if (page > 1) + { + AddButton(300, 374, 0xFAE, 0xFB0, 0, GumpButtonType.Page, 1); + AddHtmlLocalized(340, 376, 60, 20, 1011393, 0x7FFF); // Back + } + } + + if (!enabled) + continue; + + var x = pos % 2 == 0 ? 14 : 264; + var y = pos / 2 * 64 + 44; + + var b = ItemBounds.Table[entries[i].ItemID]; + + AddImageTiledButton( + x, + y, + 0x918, + 0x919, + i + 1, + GumpButtonType.Reply, + 0, + entries[i].ItemID, + entries[i].Hue, + 40 - b.Width / 2 - b.X, + 30 - b.Height / 2 - b.Y, + entries[i].Tooltip + ); + AddHtmlLocalized(x + 84, y, 250, 60, entries[i].Name, 0x7FFF); + + current++; + } + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + var entryID = info.ButtonID - 1; + + if (entryID < 0 || entryID >= AnimalForm.Entries.Length) + return; + + var mana = m_Spell.ScaleMana(m_Spell.RequiredMana); + var entry = AnimalForm.Entries[entryID]; + + if (mana > m_Caster.Mana) + { + m_Caster.SendLocalizedMessage( + 1060174, + mana.ToString() + ); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability. + } + else if (m_Caster is PlayerMobile mobile && mobile.MountBlockReason != BlockMountType.None) + { + mobile.SendLocalizedMessage(1063108); // You cannot use this ability right now. + } + else if (BaseFormTalisman.EntryEnabled(sender.Mobile, entry.Type)) + { + if ((m_Caster as PlayerMobile)?.DuelContext?.AllowSpellCast(m_Caster, m_Spell) == false) + { + } + else if (Morph(m_Caster, entryID) == MorphResult.Fail) + { + m_Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502632); // The spell fizzles. + m_Caster.FixedParticles(0x3735, 1, 30, 9503, EffectLayer.Waist); + m_Caster.PlaySound(0x5C); + } + else + { + m_Caster.FixedParticles(0x3728, 10, 13, 2023, EffectLayer.Waist); + m_Caster.Mana -= mana; + } + } + } + } + } + + public class AnimalFormContext + { + public AnimalFormContext(Timer timer, SkillMod mod, bool speedBoost, Type type, SkillMod stealingMod) + { + Timer = timer; + Mod = mod; + SpeedBoost = speedBoost; + Type = type; + StealingMod = stealingMod; + } + + public Timer Timer { get; } + + public SkillMod Mod { get; } + + public bool SpeedBoost { get; } + + public Type Type { get; } + + public SkillMod StealingMod { get; } + } + + public class AnimalFormTimer : Timer + { + private readonly int m_Body; + private readonly int m_Hue; + private readonly Mobile m_Mobile; + private int m_Counter; + private Mobile m_LastTarget; + + public AnimalFormTimer(Mobile from, int body, int hue) + : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)) + { + m_Mobile = from; + m_Body = body; + m_Hue = hue; + m_Counter = 0; + + Priority = TimerPriority.FiftyMS; + } + + protected override void OnTick() + { + if (m_Mobile.Deleted || !m_Mobile.Alive || m_Mobile.Body != m_Body || m_Mobile.Hue != m_Hue) + { + AnimalForm.RemoveContext(m_Mobile, true); + Stop(); } else { - Caster.FixedParticles(0x3728, 10, 13, 2023, EffectLayer.Waist); - Caster.Mana -= mana; + if (m_Body == 0x115) // Cu Sidhe + { + if (m_Counter++ >= 8) + { + if (m_Mobile.Hits < m_Mobile.HitsMax && m_Mobile.Backpack != null) + { + var b = m_Mobile.Backpack.FindItemByType(); + + if (b != null) + { + m_Mobile.Hits += Utility.RandomMinMax(20, 50); + b.Consume(); + } + } + + m_Counter = 0; + } + } + else if (m_Body == 0x114) // Reptalon + { + if (m_Mobile.Combatant != null && m_Mobile.Combatant != m_LastTarget) + { + m_Counter = 1; + m_LastTarget = m_Mobile.Combatant; + } + + if (m_Mobile.Warmode && m_LastTarget?.Alive == true && m_LastTarget?.Deleted != true && + m_Counter-- <= 0) + { + if (m_Mobile.CanBeHarmful(m_LastTarget) && m_LastTarget.Map == m_Mobile.Map && + m_LastTarget.InRange(m_Mobile.Location, BaseCreature.DefaultRangePerception) && + m_Mobile.InLOS(m_LastTarget)) + { + m_Mobile.Direction = m_Mobile.GetDirectionTo(m_LastTarget); + m_Mobile.Freeze(TimeSpan.FromSeconds(1)); + m_Mobile.PlaySound(0x16A); + + DelayCall(TimeSpan.FromSeconds(1.3), BreathEffect_Callback, m_LastTarget); + } + + m_Counter = Math.Min((int)m_Mobile.GetDistanceToSqrt(m_LastTarget), 10); + } + } } - } } - else + + public void BreathEffect_Callback(Mobile target) { - if (Morph(Caster, GetLastAnimalForm(Caster)) == MorphResult.Fail) - { - DoFizzle(); - } - else - { - Caster.FixedParticles(0x3728, 10, 13, 2023, EffectLayer.Waist); - Caster.Mana -= mana; - } - } - } - - FinishSequence(); - } - - public int GetLastAnimalForm(Mobile m) => m_LastAnimalForms.TryGetValue(m, out int value) ? value : -1; - - public static MorphResult Morph(Mobile m, int entryID) - { - if (entryID < 0 || entryID >= Entries.Length) - return MorphResult.Fail; - - AnimalFormEntry entry = Entries[entryID]; - - m_LastAnimalForms[m] = entryID; // On OSI, it's the last /attempted/ one not the last succeeded one - - if (m.Skills.Ninjitsu.Value < entry.ReqSkill) - { - string args = $"{entry.ReqSkill:F1}\t{SkillName.Ninjitsu}\t "; - m.SendLocalizedMessage(1063013, - args); // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability. - return MorphResult.NoSkill; - } - - /* - if (!m.CheckSkill( SkillName.Ninjitsu, entry.ReqSkill, entry.ReqSkill + 37.5 )) - return MorphResult.Fail; - * - * On OSI,it seems you can only gain starting at '0' using Animal form. - */ - - double ninjitsu = m.Skills.Ninjitsu.Value; - - if (ninjitsu < entry.ReqSkill + 37.5) - { - double chance = (ninjitsu - entry.ReqSkill) / 37.5; - - if (chance < Utility.RandomDouble()) - return MorphResult.Fail; - } - - m.CheckSkill(SkillName.Ninjitsu, 0.0, 37.5); - - if (!BaseFormTalisman.EntryEnabled(m, entry.Type)) - return MorphResult.Success; // Still consumes mana, just no effect - - BaseMount.Dismount(m); - - int bodyMod = entry.BodyMod; - int hueMod = entry.HueMod; - - m.BodyMod = bodyMod; - m.HueMod = hueMod; - - if (entry.SpeedBoost) - m.Send(SpeedControl.MountSpeed); - - SkillMod mod = null; - - if (entry.StealthBonus) - { - mod = new DefaultSkillMod(SkillName.Stealth, true, 20.0) { ObeyCap = true }; - m.AddSkillMod(mod); - } - - SkillMod stealingMod = null; - - if (entry.StealingBonus) - { - stealingMod = new DefaultSkillMod(SkillName.Stealing, true, 10.0) { ObeyCap = true }; - m.AddSkillMod(stealingMod); - } - - Timer timer = new AnimalFormTimer(m, bodyMod, hueMod); - timer.Start(); - - AddContext(m, new AnimalFormContext(timer, mod, entry.SpeedBoost, entry.Type, stealingMod)); - m.CheckStatTimers(); - return MorphResult.Success; - } - - public static void AddContext(Mobile m, AnimalFormContext context) - { - m_Table[m] = context; - - if (context.Type == typeof(BakeKitsune) || context.Type == typeof(GreyWolf)) - m.CheckStatTimers(); - } - - public static void RemoveContext(Mobile m, bool resetGraphics) - { - AnimalFormContext context = GetContext(m); - - if (context != null) - RemoveContext(m, context, resetGraphics); - } - - public static void RemoveContext(Mobile m, AnimalFormContext context, bool resetGraphics) - { - m_Table.Remove(m); - - if (context.SpeedBoost) - m.Send(SpeedControl.Disable); - - SkillMod mod = context.Mod; - - if (mod != null) - m.RemoveSkillMod(mod); - - mod = context.StealingMod; - - if (mod != null) - m.RemoveSkillMod(mod); - - if (resetGraphics) - { - m.HueMod = -1; - m.BodyMod = 0; - } - - m.FixedParticles(0x3728, 10, 13, 2023, EffectLayer.Waist); - - context.Timer.Stop(); - } - - public static AnimalFormContext GetContext(Mobile m) => m_Table.TryGetValue(m, out AnimalFormContext context) ? context : null; - - public static bool UnderTransformation(Mobile m) => m_Table.ContainsKey(m); - - public static bool UnderTransformation(Mobile m, Type type) => GetContext(m)?.Type == type; - - /* - private delegate void AnimalFormCallback( Mobile from ); - private delegate bool AnimalFormRequirementCallback( Mobile from ); - */ - - public class AnimalFormEntry - { - private readonly int m_HueModMax; - - private readonly int m_HueModMin; - /* - private AnimalFormCallback m_TransformCallback; - private AnimalFormCallback m_UntransformCallback; - private AnimalFormRequirementCallback m_RequirementCallback; - */ - - public AnimalFormEntry(Type type, TextDefinition name, int itemID, int hue, int tooltip, double reqSkill, - int bodyMod, int hueModMin, int hueModMax, bool stealthBonus = false, bool speedBoost = true, bool stealingBonus = false) - { - Type = type; - Name = name; - ItemID = itemID; - Hue = hue; - Tooltip = tooltip; - ReqSkill = reqSkill; - BodyMod = bodyMod; - m_HueModMin = hueModMin; - m_HueModMax = hueModMax; - StealthBonus = stealthBonus; - SpeedBoost = speedBoost; - StealingBonus = stealingBonus; - } - - public Type Type { get; } - - public TextDefinition Name { get; } - - public int ItemID { get; } - - public int Hue { get; } - - public int Tooltip { get; } - - public double ReqSkill { get; } - - public int BodyMod { get; } - - public int HueMod => Utility.RandomMinMax(m_HueModMin, m_HueModMax); - public bool StealthBonus { get; } - - public bool SpeedBoost { get; } - - public bool StealingBonus { get; } - } - - public class AnimalFormGump : Gump - { - // TODO: Convert this for ML to the BaseImageTileButtonsGump - private readonly Mobile m_Caster; - private readonly AnimalForm m_Spell; - - public AnimalFormGump(Mobile caster, AnimalFormEntry[] entries, AnimalForm spell) - : base(50, 50) - { - m_Caster = caster; - m_Spell = spell; - - AddPage(0); - - AddBackground(0, 0, 520, 404, 0x13BE); - AddImageTiled(10, 10, 500, 20, 0xA40); - AddImageTiled(10, 40, 500, 324, 0xA40); - AddImageTiled(10, 374, 500, 20, 0xA40); - AddAlphaRegion(10, 10, 500, 384); - - AddHtmlLocalized(14, 12, 500, 20, 1063394, 0x7FFF); //
Polymorph Selection Menu
- - AddButton(10, 374, 0xFB1, 0xFB2, 0); - AddHtmlLocalized(45, 376, 450, 20, 1011012, 0x7FFF); // CANCEL - - double ninjitsu = caster.Skills.Ninjitsu.Value; - - int current = 0; - - for (int i = 0; i < entries.Length; ++i) - { - bool enabled = ninjitsu >= entries[i].ReqSkill && BaseFormTalisman.EntryEnabled(caster, entries[i].Type); - - int page = current / 10 + 1; - int pos = current % 10; - - if (pos == 0) - { - if (page > 1) + if (m_Mobile.CanBeHarmful(target)) { - AddButton(400, 374, 0xFA5, 0xFA7, 0, GumpButtonType.Page, page); - AddHtmlLocalized(440, 376, 60, 20, 1043353, 0x7FFF); // Next + m_Mobile.RevealingAction(); + m_Mobile.PlaySound(0x227); + Effects.SendMovingEffect(m_Mobile, target, 0x36D4, 5, 0, false, false); + + DelayCall(TimeSpan.FromSeconds(1), BreathDamage_Callback, target); } + } - AddPage(page); - - if (page > 1) + public void BreathDamage_Callback(Mobile target) + { + if (m_Mobile.CanBeHarmful(target)) { - AddButton(300, 374, 0xFAE, 0xFB0, 0, GumpButtonType.Page, 1); - AddHtmlLocalized(340, 376, 60, 20, 1011393, 0x7FFF); // Back + m_Mobile.RevealingAction(); + m_Mobile.DoHarmful(target); + AOS.Damage(target, m_Mobile, 20, !target.Player, 0, 100, 0, 0, 0); } - } - - if (!enabled) - continue; - - int x = pos % 2 == 0 ? 14 : 264; - int y = pos / 2 * 64 + 44; - - Rectangle2D b = ItemBounds.Table[entries[i].ItemID]; - - AddImageTiledButton(x, y, 0x918, 0x919, i + 1, GumpButtonType.Reply, 0, entries[i].ItemID, - entries[i].Hue, 40 - b.Width / 2 - b.X, 30 - b.Height / 2 - b.Y, entries[i].Tooltip); - AddHtmlLocalized(x + 84, y, 250, 60, entries[i].Name, 0x7FFF); - - current++; } - } - - public override void OnResponse(NetState sender, RelayInfo info) - { - int entryID = info.ButtonID - 1; - - if (entryID < 0 || entryID >= AnimalForm.Entries.Length) - return; - - int mana = m_Spell.ScaleMana(m_Spell.RequiredMana); - AnimalFormEntry entry = AnimalForm.Entries[entryID]; - - if (mana > m_Caster.Mana) - { - m_Caster.SendLocalizedMessage(1060174, - mana.ToString()); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability. - } - else if (m_Caster is PlayerMobile mobile && mobile.MountBlockReason != BlockMountType.None) - { - mobile.SendLocalizedMessage(1063108); // You cannot use this ability right now. - } - else if (BaseFormTalisman.EntryEnabled(sender.Mobile, entry.Type)) - { - if ((m_Caster as PlayerMobile)?.DuelContext?.AllowSpellCast(m_Caster, m_Spell) == false) - { - } - else if (Morph(m_Caster, entryID) == MorphResult.Fail) - { - m_Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, 502632); // The spell fizzles. - m_Caster.FixedParticles(0x3735, 1, 30, 9503, EffectLayer.Waist); - m_Caster.PlaySound(0x5C); - } - else - { - m_Caster.FixedParticles(0x3728, 10, 13, 2023, EffectLayer.Waist); - m_Caster.Mana -= mana; - } - } - } } - } - - public class AnimalFormContext - { - public AnimalFormContext(Timer timer, SkillMod mod, bool speedBoost, Type type, SkillMod stealingMod) - { - Timer = timer; - Mod = mod; - SpeedBoost = speedBoost; - Type = type; - StealingMod = stealingMod; - } - - public Timer Timer { get; } - - public SkillMod Mod { get; } - - public bool SpeedBoost { get; } - - public Type Type { get; } - - public SkillMod StealingMod { get; } - } - - public class AnimalFormTimer : Timer - { - private readonly int m_Body; - private int m_Counter; - private readonly int m_Hue; - private Mobile m_LastTarget; - private readonly Mobile m_Mobile; - - public AnimalFormTimer(Mobile from, int body, int hue) - : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0)) - { - m_Mobile = from; - m_Body = body; - m_Hue = hue; - m_Counter = 0; - - Priority = TimerPriority.FiftyMS; - } - - protected override void OnTick() - { - if (m_Mobile.Deleted || !m_Mobile.Alive || m_Mobile.Body != m_Body || m_Mobile.Hue != m_Hue) - { - AnimalForm.RemoveContext(m_Mobile, true); - Stop(); - } - else - { - if (m_Body == 0x115) // Cu Sidhe - { - if (m_Counter++ >= 8) - { - if (m_Mobile.Hits < m_Mobile.HitsMax && m_Mobile.Backpack != null) - { - Bandage b = m_Mobile.Backpack.FindItemByType(); - - if (b != null) - { - m_Mobile.Hits += Utility.RandomMinMax(20, 50); - b.Consume(); - } - } - - m_Counter = 0; - } - } - else if (m_Body == 0x114) // Reptalon - { - if (m_Mobile.Combatant != null && m_Mobile.Combatant != m_LastTarget) - { - m_Counter = 1; - m_LastTarget = m_Mobile.Combatant; - } - - if (m_Mobile.Warmode && m_LastTarget?.Alive == true && m_LastTarget?.Deleted != true && - m_Counter-- <= 0) - { - if (m_Mobile.CanBeHarmful(m_LastTarget) && m_LastTarget.Map == m_Mobile.Map && - m_LastTarget.InRange(m_Mobile.Location, BaseCreature.DefaultRangePerception) && - m_Mobile.InLOS(m_LastTarget)) - { - m_Mobile.Direction = m_Mobile.GetDirectionTo(m_LastTarget); - m_Mobile.Freeze(TimeSpan.FromSeconds(1)); - m_Mobile.PlaySound(0x16A); - - DelayCall(TimeSpan.FromSeconds(1.3), BreathEffect_Callback, m_LastTarget); - } - - m_Counter = Math.Min((int)m_Mobile.GetDistanceToSqrt(m_LastTarget), 10); - } - } - } - } - - public void BreathEffect_Callback(Mobile target) - { - if (m_Mobile.CanBeHarmful(target)) - { - m_Mobile.RevealingAction(); - m_Mobile.PlaySound(0x227); - Effects.SendMovingEffect(m_Mobile, target, 0x36D4, 5, 0, false, false); - - DelayCall(TimeSpan.FromSeconds(1), BreathDamage_Callback, target); - } - } - - public void BreathDamage_Callback(Mobile target) - { - if (m_Mobile.CanBeHarmful(target)) - { - m_Mobile.RevealingAction(); - m_Mobile.DoHarmful(target); - AOS.Damage(target, m_Mobile, 20, !target.Player, 0, 100, 0, 0, 0); - } - } - } } diff --git a/Projects/UOContent/Spells/Ninjitsu/Backstab.cs b/Projects/UOContent/Spells/Ninjitsu/Backstab.cs index bfe5e141f..f4ac17cd4 100644 --- a/Projects/UOContent/Spells/Ninjitsu/Backstab.cs +++ b/Projects/UOContent/Spells/Ninjitsu/Backstab.cs @@ -3,69 +3,69 @@ using Server.SkillHandlers; namespace Server.Spells.Ninjitsu { - public class Backstab : NinjaMove - { - public override int BaseMana => 30; - public override double RequiredSkill => Core.ML ? 40.0 : 20.0; - - public override TextDefinition AbilityMessage => - new TextDefinition(1063089); // You prepare to Backstab your opponent. - - public override bool ValidatesDuringHit => false; - - public override double GetDamageScalar(Mobile attacker, Mobile defender) + public class Backstab : NinjaMove { - double ninjitsu = attacker.Skills.Ninjitsu.Value; + public override int BaseMana => 30; + public override double RequiredSkill => Core.ML ? 40.0 : 20.0; - return 1.0 + ninjitsu / 360 + Tracking.GetStalkingBonus(attacker, defender) / 100; + public override TextDefinition AbilityMessage => + new TextDefinition(1063089); // You prepare to Backstab your opponent. + + public override bool ValidatesDuringHit => false; + + public override double GetDamageScalar(Mobile attacker, Mobile defender) + { + var ninjitsu = attacker.Skills.Ninjitsu.Value; + + return 1.0 + ninjitsu / 360 + Tracking.GetStalkingBonus(attacker, defender) / 100; + } + + public override bool Validate(Mobile from) + { + if (!from.Hidden || from.AllowedStealthSteps <= 0) + { + from.SendLocalizedMessage(1063087); // You must be in stealth mode to use this ability. + return false; + } + + return base.Validate(from); + } + + public override bool OnBeforeSwing(Mobile attacker, Mobile defender) + { + var valid = Validate(attacker) && CheckMana(attacker, true); + + if (valid) + { + attacker.BeginAction(); + Timer.DelayCall(TimeSpan.FromSeconds(5.0), attacker.EndAction); + } + + return valid; + } + + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + // Validates before swing + + ClearCurrentMove(attacker); + + attacker.SendLocalizedMessage(1063090); // You quickly stab your opponent as you come out of hiding! + + defender.FixedParticles(0x37B9, 1, 5, 0x251D, 0x651, 0, EffectLayer.Waist); + + attacker.RevealingAction(); + + CheckGain(attacker); + } + + public override void OnMiss(Mobile attacker, Mobile defender) + { + ClearCurrentMove(attacker); + + attacker.SendLocalizedMessage(1063161); // You failed to properly use the element of surprise. + + attacker.RevealingAction(); + } } - - public override bool Validate(Mobile from) - { - if (!from.Hidden || from.AllowedStealthSteps <= 0) - { - from.SendLocalizedMessage(1063087); // You must be in stealth mode to use this ability. - return false; - } - - return base.Validate(from); - } - - public override bool OnBeforeSwing(Mobile attacker, Mobile defender) - { - bool valid = Validate(attacker) && CheckMana(attacker, true); - - if (valid) - { - attacker.BeginAction(); - Timer.DelayCall(TimeSpan.FromSeconds(5.0), attacker.EndAction); - } - - return valid; - } - - public override void OnHit(Mobile attacker, Mobile defender, int damage) - { - // Validates before swing - - ClearCurrentMove(attacker); - - attacker.SendLocalizedMessage(1063090); // You quickly stab your opponent as you come out of hiding! - - defender.FixedParticles(0x37B9, 1, 5, 0x251D, 0x651, 0, EffectLayer.Waist); - - attacker.RevealingAction(); - - CheckGain(attacker); - } - - public override void OnMiss(Mobile attacker, Mobile defender) - { - ClearCurrentMove(attacker); - - attacker.SendLocalizedMessage(1063161); // You failed to properly use the element of surprise. - - attacker.RevealingAction(); - } - } } diff --git a/Projects/UOContent/Spells/Ninjitsu/DeathStrike.cs b/Projects/UOContent/Spells/Ninjitsu/DeathStrike.cs index fc273562e..21f634bea 100644 --- a/Projects/UOContent/Spells/Ninjitsu/DeathStrike.cs +++ b/Projects/UOContent/Spells/Ninjitsu/DeathStrike.cs @@ -5,145 +5,159 @@ using Server.SkillHandlers; namespace Server.Spells.Ninjitsu { - public class DeathStrike : NinjaMove - { - private static readonly Dictionary m_Table = new Dictionary(); - - public override int BaseMana => 30; - public override double RequiredSkill => 85.0; - - public override TextDefinition AbilityMessage => - new TextDefinition(1063091); // You prepare to hit your opponent with a Death Strike. - - public override double GetDamageScalar(Mobile attacker, Mobile defender) => 0.5; - - public override void OnHit(Mobile attacker, Mobile defender, int damage) + public class DeathStrike : NinjaMove { - if (!Validate(attacker) || !CheckMana(attacker, true)) - return; + private static readonly Dictionary m_Table = new Dictionary(); - ClearCurrentMove(attacker); + public override int BaseMana => 30; + public override double RequiredSkill => 85.0; - double ninjitsu = attacker.Skills.Ninjitsu.Value; + public override TextDefinition AbilityMessage => + new TextDefinition(1063091); // You prepare to hit your opponent with a Death Strike. - double chance; + public override double GetDamageScalar(Mobile attacker, Mobile defender) => 0.5; - // TODO: should be defined onHit method, what if the player hit and remove the weapon before process? ;) - bool isRanged = attacker.Weapon is BaseRanged; + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + if (!Validate(attacker) || !CheckMana(attacker, true)) + return; - if (ninjitsu < 100) // This formula is an approximation from OSI data. TODO: find correct formula - chance = 30 + (ninjitsu - 85) * 2.2; - else - chance = 63 + (ninjitsu - 100) * 1.1; + ClearCurrentMove(attacker); - if (chance / 100 < Utility.RandomDouble()) - { - attacker.SendLocalizedMessage(1070779); // You missed your opponent with a Death Strike. - return; - } + var ninjitsu = attacker.Skills.Ninjitsu.Value; - int damageBonus = 0; + double chance; - if (m_Table.TryGetValue(defender, out DeathStrikeInfo info)) - { - defender.SendLocalizedMessage(1063092); // Your opponent lands another Death Strike! + // TODO: should be defined onHit method, what if the player hit and remove the weapon before process? ;) + var isRanged = attacker.Weapon is BaseRanged; - if (info.m_Steps > 0) - damageBonus = attacker.Skills.Ninjitsu.Fixed / 150; + if (ninjitsu < 100) // This formula is an approximation from OSI data. TODO: find correct formula + chance = 30 + (ninjitsu - 85) * 2.2; + else + chance = 63 + (ninjitsu - 100) * 1.1; - info.m_Timer?.Stop(); + if (chance / 100 < Utility.RandomDouble()) + { + attacker.SendLocalizedMessage(1070779); // You missed your opponent with a Death Strike. + return; + } - m_Table.Remove(defender); - } - else - { - defender.SendLocalizedMessage(1063093); // You have been hit by a Death Strike! Move with caution! - } + var damageBonus = 0; - attacker.SendLocalizedMessage(1063094); // You inflict a Death Strike upon your opponent! + if (m_Table.TryGetValue(defender, out var info)) + { + defender.SendLocalizedMessage(1063092); // Your opponent lands another Death Strike! - defender.FixedParticles(0x374A, 1, 17, 0x26BC, EffectLayer.Waist); - attacker.PlaySound(attacker.Female ? 0x50D : 0x50E); + if (info.m_Steps > 0) + damageBonus = attacker.Skills.Ninjitsu.Fixed / 150; - info = new DeathStrikeInfo(defender, attacker, damageBonus, isRanged) - { - m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(5.0), ProcessDeathStrike, defender) - }; + info.m_Timer?.Stop(); - m_Table[defender] = info; + m_Table.Remove(defender); + } + else + { + defender.SendLocalizedMessage(1063093); // You have been hit by a Death Strike! Move with caution! + } - CheckGain(attacker); + attacker.SendLocalizedMessage(1063094); // You inflict a Death Strike upon your opponent! + + defender.FixedParticles(0x374A, 1, 17, 0x26BC, EffectLayer.Waist); + attacker.PlaySound(attacker.Female ? 0x50D : 0x50E); + + info = new DeathStrikeInfo(defender, attacker, damageBonus, isRanged) + { + m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(5.0), ProcessDeathStrike, defender) + }; + + m_Table[defender] = info; + + CheckGain(attacker); + } + + public static void AddStep(Mobile m) + { + if (m_Table.TryGetValue(m, out var info) && ++info.m_Steps >= 5) + ProcessDeathStrike(m); + } + + private static void ProcessDeathStrike(Mobile defender) + { + if (!m_Table.TryGetValue(defender, out var info)) + return; + + int damage; + + var ninjitsu = info.m_Attacker.Skills.Ninjitsu.Value; + var stalkingBonus = Tracking.GetStalkingBonus(info.m_Attacker, info.m_Target); + + if (Core.ML) + { + var scalar = (info.m_Attacker.Skills.Hiding.Value + + info.m_Attacker.Skills.Stealth.Value) / 220; + + if (scalar > 1) + scalar = 1; + + // New formula doesn't apply DamageBonus anymore, caps must be, directly, 60/30. + if (info.m_Steps >= 5) + damage = (int)Math.Floor(Math.Min(60, ninjitsu / 3 * (0.3 + 0.7 * scalar) + stalkingBonus)); + else + damage = (int)Math.Floor(Math.Min(30, ninjitsu / 9 * (0.3 + 0.7 * scalar) + stalkingBonus)); + + if (info.m_isRanged) + damage /= 2; + } + else + { + var divisor = info.m_Steps >= 5 ? 30 : 80; + var baseDamage = ninjitsu / divisor * 10; + + var maxDamage = info.m_Steps >= 5 ? 62 : 22; + damage = Math.Clamp((int)(baseDamage + stalkingBonus), 0, maxDamage) + info.m_DamageBonus; + } + + if (Core.ML) + info.m_Target.Damage(damage, info.m_Attacker); // Damage is direct. + else + AOS.Damage( + info.m_Target, + info.m_Attacker, + damage, + true, + 100, + 0, + 0, + 0, + 0, + 0, + 0, + false, + false, + true + ); // Damage is physical. + + info.m_Timer?.Stop(); + + m_Table.Remove(info.m_Target); + } + + private class DeathStrikeInfo + { + public readonly Mobile m_Attacker; + public readonly int m_DamageBonus; + public readonly bool m_isRanged; + public readonly Mobile m_Target; + public int m_Steps; + public Timer m_Timer; + + public DeathStrikeInfo(Mobile target, Mobile attacker, int damageBonus, bool isRanged) + { + m_Target = target; + m_Attacker = attacker; + m_DamageBonus = damageBonus; + m_isRanged = isRanged; + } + } } - - public static void AddStep(Mobile m) - { - if (m_Table.TryGetValue(m, out DeathStrikeInfo info) && ++info.m_Steps >= 5) - ProcessDeathStrike(m); - } - - private static void ProcessDeathStrike(Mobile defender) - { - if (!m_Table.TryGetValue(defender, out DeathStrikeInfo info)) - return; - - int damage; - - double ninjitsu = info.m_Attacker.Skills.Ninjitsu.Value; - double stalkingBonus = Tracking.GetStalkingBonus(info.m_Attacker, info.m_Target); - - if (Core.ML) - { - double scalar = (info.m_Attacker.Skills.Hiding.Value + - info.m_Attacker.Skills.Stealth.Value) / 220; - - if (scalar > 1) - scalar = 1; - - // New formula doesn't apply DamageBonus anymore, caps must be, directly, 60/30. - if (info.m_Steps >= 5) - damage = (int)Math.Floor(Math.Min(60, ninjitsu / 3 * (0.3 + 0.7 * scalar) + stalkingBonus)); - else - damage = (int)Math.Floor(Math.Min(30, ninjitsu / 9 * (0.3 + 0.7 * scalar) + stalkingBonus)); - - if (info.m_isRanged) - damage /= 2; - } - else - { - int divisor = info.m_Steps >= 5 ? 30 : 80; - double baseDamage = ninjitsu / divisor * 10; - - int maxDamage = info.m_Steps >= 5 ? 62 : 22; - damage = Math.Clamp((int)(baseDamage + stalkingBonus), 0, maxDamage) + info.m_DamageBonus; - } - - if (Core.ML) - info.m_Target.Damage(damage, info.m_Attacker); // Damage is direct. - else - AOS.Damage(info.m_Target, info.m_Attacker, damage, true, 100, 0, 0, 0, 0, 0, 0, false, false, - true); // Damage is physical. - - info.m_Timer?.Stop(); - - m_Table.Remove(info.m_Target); - } - - private class DeathStrikeInfo - { - public readonly Mobile m_Attacker; - public readonly int m_DamageBonus; - public readonly bool m_isRanged; - public int m_Steps; - public readonly Mobile m_Target; - public Timer m_Timer; - - public DeathStrikeInfo(Mobile target, Mobile attacker, int damageBonus, bool isRanged) - { - m_Target = target; - m_Attacker = attacker; - m_DamageBonus = damageBonus; - m_isRanged = isRanged; - } - } - } } diff --git a/Projects/UOContent/Spells/Ninjitsu/FocusAttack.cs b/Projects/UOContent/Spells/Ninjitsu/FocusAttack.cs index 0509aae60..d9aae3f1b 100644 --- a/Projects/UOContent/Spells/Ninjitsu/FocusAttack.cs +++ b/Projects/UOContent/Spells/Ninjitsu/FocusAttack.cs @@ -2,62 +2,63 @@ using Server.Items; namespace Server.Spells.Ninjitsu { - public class FocusAttack : NinjaMove - { - public override int BaseMana => Core.ML ? 10 : 20; - public override double RequiredSkill => Core.ML ? 30.0 : 60; - - public override TextDefinition AbilityMessage => - new TextDefinition(1063095); // You prepare to focus all of your abilities into your next strike. - - public override bool Validate(Mobile from) + public class FocusAttack : NinjaMove { - if (from.FindItemOnLayer(Layer.TwoHanded) is BaseShield) - { - from.SendLocalizedMessage(1063096); // You cannot use this ability while holding a shield. - return false; - } + public override int BaseMana => Core.ML ? 10 : 20; + public override double RequiredSkill => Core.ML ? 30.0 : 60; - Item handOne = from.FindItemOnLayer(Layer.OneHanded) as BaseWeapon; + public override TextDefinition AbilityMessage => + new TextDefinition(1063095); // You prepare to focus all of your abilities into your next strike. - if (handOne != null && !(handOne is BaseRanged)) - return base.Validate(from); + public override bool Validate(Mobile from) + { + if (from.FindItemOnLayer(Layer.TwoHanded) is BaseShield) + { + from.SendLocalizedMessage(1063096); // You cannot use this ability while holding a shield. + return false; + } - Item handTwo = from.FindItemOnLayer(Layer.TwoHanded) as BaseWeapon; + Item handOne = from.FindItemOnLayer(Layer.OneHanded) as BaseWeapon; - if (handTwo != null && !(handTwo is BaseRanged)) - return base.Validate(from); + if (handOne != null && !(handOne is BaseRanged)) + return base.Validate(from); - from.SendLocalizedMessage(1063097); // You must be wielding a melee weapon without a shield to use this ability. - return false; + Item handTwo = from.FindItemOnLayer(Layer.TwoHanded) as BaseWeapon; + + if (handTwo != null && !(handTwo is BaseRanged)) + return base.Validate(from); + + from.SendLocalizedMessage(1063097); // You must be wielding a melee weapon without a shield to use this ability. + return false; + } + + public override double GetDamageScalar(Mobile attacker, Mobile defender) + { + var ninjitsu = attacker.Skills.Ninjitsu.Value; + + return 1.0 + ninjitsu * ninjitsu / 43636; + } + + public override double GetPropertyBonus(Mobile attacker) + { + var ninjitsu = attacker.Skills.Ninjitsu.Value; + + var bonus = ninjitsu * ninjitsu / 43636; + + return 1.0 + (bonus * 3 + 0.01); + } + + public override bool OnBeforeDamage(Mobile attacker, Mobile defender) => + Validate(attacker) && CheckMana(attacker, true); + + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + ClearCurrentMove(attacker); + + attacker.SendLocalizedMessage(1063098); // You focus all of your abilities and strike with deadly force! + attacker.PlaySound(0x510); + + CheckGain(attacker); + } } - - public override double GetDamageScalar(Mobile attacker, Mobile defender) - { - double ninjitsu = attacker.Skills.Ninjitsu.Value; - - return 1.0 + ninjitsu * ninjitsu / 43636; - } - - public override double GetPropertyBonus(Mobile attacker) - { - double ninjitsu = attacker.Skills.Ninjitsu.Value; - - double bonus = ninjitsu * ninjitsu / 43636; - - return 1.0 + (bonus * 3 + 0.01); - } - - public override bool OnBeforeDamage(Mobile attacker, Mobile defender) => Validate(attacker) && CheckMana(attacker, true); - - public override void OnHit(Mobile attacker, Mobile defender, int damage) - { - ClearCurrentMove(attacker); - - attacker.SendLocalizedMessage(1063098); // You focus all of your abilities and strike with deadly force! - attacker.PlaySound(0x510); - - CheckGain(attacker); - } - } } diff --git a/Projects/UOContent/Spells/Ninjitsu/KiAttack.cs b/Projects/UOContent/Spells/Ninjitsu/KiAttack.cs index cf732fe9e..a139c8c27 100644 --- a/Projects/UOContent/Spells/Ninjitsu/KiAttack.cs +++ b/Projects/UOContent/Spells/Ninjitsu/KiAttack.cs @@ -4,126 +4,127 @@ using Server.Items; namespace Server.Spells.Ninjitsu { - public class KiAttack : NinjaMove - { - private static readonly Dictionary m_Table = new Dictionary(); - - public override int BaseMana => 25; - public override double RequiredSkill => 80.0; - - public override TextDefinition AbilityMessage => - new TextDefinition(1063099); // Your Ki Attack must be complete within 2 seconds for the damage bonus! - - public override void OnUse(Mobile from) + public class KiAttack : NinjaMove { - if (!Validate(from)) - return; + private static readonly Dictionary m_Table = new Dictionary(); - KiAttackInfo info = new KiAttackInfo(from); - info.m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(2.0), EndKiAttack, info); + public override int BaseMana => 25; + public override double RequiredSkill => 80.0; - m_Table[from] = info; + public override TextDefinition AbilityMessage => + new TextDefinition(1063099); // Your Ki Attack must be complete within 2 seconds for the damage bonus! + + public override void OnUse(Mobile from) + { + if (!Validate(from)) + return; + + var info = new KiAttackInfo(from); + info.m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(2.0), EndKiAttack, info); + + m_Table[from] = info; + } + + public override bool Validate(Mobile from) + { + if (from.Hidden && from.AllowedStealthSteps > 0) + { + from.SendLocalizedMessage(1063127); // You cannot use this ability while in stealth mode. + return false; + } + + if (Core.ML && from.Weapon is BaseRanged) + { + from.SendLocalizedMessage(1075858); // You can only use this with melee attacks. + return false; + } + + return base.Validate(from); + } + + public override double GetDamageScalar(Mobile attacker, Mobile defender) + { + if (attacker.Hidden) + return 1.0; + + /* + * Pub40 changed pvp damage max to 55% + */ + + return 1.0 + GetBonus(attacker) / (Core.ML && attacker.Player && defender.Player ? 40 : 10); + } + + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + if (!Validate(attacker) || !CheckMana(attacker, true)) + return; + + if (GetBonus(attacker) == 0.0) + { + attacker.SendLocalizedMessage(1063101); // You were too close to your target to cause any additional damage. + } + else + { + attacker.FixedParticles(0x37BE, 1, 5, 0x26BD, 0x0, 0x1, EffectLayer.Waist); + attacker.PlaySound(0x510); + + attacker.SendLocalizedMessage( + 1063100 + ); // Your quick flight to your target causes extra damage as you strike! + defender.FixedParticles(0x37BE, 1, 5, 0x26BD, 0, 0x1, EffectLayer.Waist); + + CheckGain(attacker); + } + + ClearCurrentMove(attacker); + } + + public override void OnClearMove(Mobile from) + { + if (!m_Table.TryGetValue(from, out var info)) + return; + + info.m_Timer.Stop(); + m_Table.Remove(info.m_Mobile); + } + + public static double GetBonus(Mobile from) + { + if (!m_Table.TryGetValue(from, out var info)) + return 0; + + var xDelta = info.m_Location.X - from.X; + var yDelta = info.m_Location.Y - from.Y; + + var bonus = Math.Sqrt(xDelta * xDelta + yDelta * yDelta); + + if (bonus > 20.0) + bonus = 20.0; + + return bonus; + } + + private static void EndKiAttack(KiAttackInfo info) + { + info.m_Timer?.Stop(); + + ClearCurrentMove(info.m_Mobile); + info.m_Mobile.SendLocalizedMessage(1063102); // You failed to complete your Ki Attack in time. + + m_Table.Remove(info.m_Mobile); + } + + private class KiAttackInfo + { + public readonly Mobile m_Mobile; + public Point3D m_Location; + public Timer m_Timer; + + public KiAttackInfo(Mobile m) + { + m_Mobile = m; + m_Location = m.Location; + } + } } - - public override bool Validate(Mobile from) - { - if (from.Hidden && from.AllowedStealthSteps > 0) - { - from.SendLocalizedMessage(1063127); // You cannot use this ability while in stealth mode. - return false; - } - - if (Core.ML && from.Weapon is BaseRanged) - { - from.SendLocalizedMessage(1075858); // You can only use this with melee attacks. - return false; - } - - return base.Validate(from); - } - - public override double GetDamageScalar(Mobile attacker, Mobile defender) - { - if (attacker.Hidden) - return 1.0; - - /* - * Pub40 changed pvp damage max to 55% - */ - - return 1.0 + GetBonus(attacker) / (Core.ML && attacker.Player && defender.Player ? 40 : 10); - } - - public override void OnHit(Mobile attacker, Mobile defender, int damage) - { - if (!Validate(attacker) || !CheckMana(attacker, true)) - return; - - if (GetBonus(attacker) == 0.0) - { - attacker.SendLocalizedMessage(1063101); // You were too close to your target to cause any additional damage. - } - else - { - attacker.FixedParticles(0x37BE, 1, 5, 0x26BD, 0x0, 0x1, EffectLayer.Waist); - attacker.PlaySound(0x510); - - attacker.SendLocalizedMessage( - 1063100); // Your quick flight to your target causes extra damage as you strike! - defender.FixedParticles(0x37BE, 1, 5, 0x26BD, 0, 0x1, EffectLayer.Waist); - - CheckGain(attacker); - } - - ClearCurrentMove(attacker); - } - - public override void OnClearMove(Mobile from) - { - if (!m_Table.TryGetValue(from, out KiAttackInfo info)) - return; - - info.m_Timer.Stop(); - m_Table.Remove(info.m_Mobile); - } - - public static double GetBonus(Mobile from) - { - if (!m_Table.TryGetValue(from, out KiAttackInfo info)) - return 0; - - int xDelta = info.m_Location.X - from.X; - int yDelta = info.m_Location.Y - from.Y; - - double bonus = Math.Sqrt(xDelta * xDelta + yDelta * yDelta); - - if (bonus > 20.0) - bonus = 20.0; - - return bonus; - } - - private static void EndKiAttack(KiAttackInfo info) - { - info.m_Timer?.Stop(); - - ClearCurrentMove(info.m_Mobile); - info.m_Mobile.SendLocalizedMessage(1063102); // You failed to complete your Ki Attack in time. - - m_Table.Remove(info.m_Mobile); - } - - private class KiAttackInfo - { - public Point3D m_Location; - public readonly Mobile m_Mobile; - public Timer m_Timer; - - public KiAttackInfo(Mobile m) - { - m_Mobile = m; - m_Location = m.Location; - } - } - } } diff --git a/Projects/UOContent/Spells/Ninjitsu/MirrorImage.cs b/Projects/UOContent/Spells/Ninjitsu/MirrorImage.cs index fdcd5a819..5bdf51329 100644 --- a/Projects/UOContent/Spells/Ninjitsu/MirrorImage.cs +++ b/Projects/UOContent/Spells/Ninjitsu/MirrorImage.cs @@ -8,248 +8,257 @@ using Server.Spells.Ninjitsu; namespace Server.Spells.Ninjitsu { - public class MirrorImage : NinjaSpell - { - private static readonly Dictionary m_CloneCount = new Dictionary(); - - private static readonly SpellInfo m_Info = new SpellInfo( - "Mirror Image", null, - -1, - 9002); - - public MirrorImage(Mobile caster, Item scroll) : base(caster, scroll, m_Info) + public class MirrorImage : NinjaSpell { + private static readonly Dictionary m_CloneCount = new Dictionary(); + + private static readonly SpellInfo m_Info = new SpellInfo( + "Mirror Image", + null, + -1, + 9002 + ); + + public MirrorImage(Mobile caster, Item scroll) : base(caster, scroll, m_Info) + { + } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); + + public override double RequiredSkill => Core.ML ? 20.0 : 40.0; + public override int RequiredMana => 10; + + public override bool BlockedByAnimalForm => false; + + public static bool HasClone(Mobile m) => m_CloneCount.ContainsKey(m); + + public static void AddClone(Mobile m) + { + if (m == null) + return; + + m_CloneCount[m] = 1 + (m_CloneCount.TryGetValue(m, out var count) ? count : 0); + } + + public static void RemoveClone(Mobile m) + { + if (m == null || !m_CloneCount.TryGetValue(m, out var count)) + return; + + if (count <= 1) + m_CloneCount.Remove(m); + else + m_CloneCount[m]--; + } + + public override bool CheckCast() + { + if (Caster.Mounted) + { + Caster.SendLocalizedMessage(1063132); // You cannot use this ability while mounted. + return false; + } + + if (Caster.Followers + 1 > Caster.FollowersMax) + { + Caster.SendLocalizedMessage( + 1063133 + ); // You cannot summon a mirror image because you have too many followers. + return false; + } + + if (TransformationSpellHelper.UnderTransformation(Caster, typeof(HorrificBeastSpell))) + { + Caster.SendLocalizedMessage(1061091); // You cannot cast that spell in this form. + return false; + } + + return base.CheckCast(); + } + + public override bool CheckDisturb(DisturbType type, bool firstCircle, bool resistable) => false; + + public override void OnBeginCast() + { + base.OnBeginCast(); + + Caster.SendLocalizedMessage(1063134); // You begin to summon a mirror image of yourself. + } + + public override void OnCast() + { + if (Caster.Mounted) + { + Caster.SendLocalizedMessage(1063132); // You cannot use this ability while mounted. + } + else if (Caster.Followers + 1 > Caster.FollowersMax) + { + Caster.SendLocalizedMessage( + 1063133 + ); // You cannot summon a mirror image because you have too many followers. + } + else if (TransformationSpellHelper.UnderTransformation(Caster, typeof(HorrificBeastSpell))) + { + Caster.SendLocalizedMessage(1061091); // You cannot cast that spell in this form. + } + else if (CheckSequence()) + { + Caster.FixedParticles(0x376A, 1, 14, 0x13B5, EffectLayer.Waist); + Caster.PlaySound(0x511); + + new Clone(Caster).MoveToWorld(Caster.Location, Caster.Map); + } + + FinishSequence(); + } } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); - - public override double RequiredSkill => Core.ML ? 20.0 : 40.0; - public override int RequiredMana => 10; - - public override bool BlockedByAnimalForm => false; - - public static bool HasClone(Mobile m) => m_CloneCount.ContainsKey(m); - - public static void AddClone(Mobile m) - { - if (m == null) - return; - - m_CloneCount[m] = 1 + (m_CloneCount.TryGetValue(m, out int count) ? count : 0); - } - - public static void RemoveClone(Mobile m) - { - if (m == null || !m_CloneCount.TryGetValue(m, out int count)) - return; - - if (count <= 1) - m_CloneCount.Remove(m); - else - m_CloneCount[m]--; - } - - public override bool CheckCast() - { - if (Caster.Mounted) - { - Caster.SendLocalizedMessage(1063132); // You cannot use this ability while mounted. - return false; - } - - if (Caster.Followers + 1 > Caster.FollowersMax) - { - Caster.SendLocalizedMessage( - 1063133); // You cannot summon a mirror image because you have too many followers. - return false; - } - - if (TransformationSpellHelper.UnderTransformation(Caster, typeof(HorrificBeastSpell))) - { - Caster.SendLocalizedMessage(1061091); // You cannot cast that spell in this form. - return false; - } - - return base.CheckCast(); - } - - public override bool CheckDisturb(DisturbType type, bool firstCircle, bool resistable) => false; - - public override void OnBeginCast() - { - base.OnBeginCast(); - - Caster.SendLocalizedMessage(1063134); // You begin to summon a mirror image of yourself. - } - - public override void OnCast() - { - if (Caster.Mounted) - { - Caster.SendLocalizedMessage(1063132); // You cannot use this ability while mounted. - } - else if (Caster.Followers + 1 > Caster.FollowersMax) - { - Caster.SendLocalizedMessage( - 1063133); // You cannot summon a mirror image because you have too many followers. - } - else if (TransformationSpellHelper.UnderTransformation(Caster, typeof(HorrificBeastSpell))) - { - Caster.SendLocalizedMessage(1061091); // You cannot cast that spell in this form. - } - else if (CheckSequence()) - { - Caster.FixedParticles(0x376A, 1, 14, 0x13B5, EffectLayer.Waist); - Caster.PlaySound(0x511); - - new Clone(Caster).MoveToWorld(Caster.Location, Caster.Map); - } - - FinishSequence(); - } - } } namespace Server.Mobiles { - public class Clone : BaseCreature - { - private Mobile m_Caster; - - public Clone(Mobile caster) : base(AIType.AI_Melee, FightMode.None, 10, 1, 0.2, 0.4) + public class Clone : BaseCreature { - m_Caster = caster; + private Mobile m_Caster; - Body = caster.Body; + public Clone(Mobile caster) : base(AIType.AI_Melee, FightMode.None, 10, 1, 0.2, 0.4) + { + m_Caster = caster; - Hue = caster.Hue; - Female = caster.Female; + Body = caster.Body; - Name = caster.Name; - NameHue = caster.NameHue; + Hue = caster.Hue; + Female = caster.Female; - Title = caster.Title; - Kills = caster.Kills; + Name = caster.Name; + NameHue = caster.NameHue; - HairItemID = caster.HairItemID; - HairHue = caster.HairHue; + Title = caster.Title; + Kills = caster.Kills; - FacialHairItemID = caster.FacialHairItemID; - FacialHairHue = caster.FacialHairHue; + HairItemID = caster.HairItemID; + HairHue = caster.HairHue; - for (int i = 0; i < caster.Skills.Length; ++i) - { - Skills[i].Base = caster.Skills[i].Base; - Skills[i].Cap = caster.Skills[i].Cap; - } + FacialHairItemID = caster.FacialHairItemID; + FacialHairHue = caster.FacialHairHue; - for (int i = 0; i < caster.Items.Count; i++) AddItem(CloneItem(caster.Items[i])); + for (var i = 0; i < caster.Skills.Length; ++i) + { + Skills[i].Base = caster.Skills[i].Base; + Skills[i].Cap = caster.Skills[i].Cap; + } - Warmode = true; + for (var i = 0; i < caster.Items.Count; i++) AddItem(CloneItem(caster.Items[i])); - Summoned = true; - SummonMaster = caster; + Warmode = true; - ControlOrder = OrderType.Follow; - ControlTarget = caster; + Summoned = true; + SummonMaster = caster; - TimeSpan duration = TimeSpan.FromSeconds(30 + caster.Skills.Ninjitsu.Fixed / 40); + ControlOrder = OrderType.Follow; + ControlTarget = caster; - new UnsummonTimer(caster, this, duration).Start(); - SummonEnd = DateTime.UtcNow + duration; + var duration = TimeSpan.FromSeconds(30 + caster.Skills.Ninjitsu.Fixed / 40); - MirrorImage.AddClone(m_Caster); + new UnsummonTimer(caster, this, duration).Start(); + SummonEnd = DateTime.UtcNow + duration; + + MirrorImage.AddClone(m_Caster); + } + + public Clone(Serial serial) : base(serial) + { + } + + protected override BaseAI ForcedAI => new CloneAI(this); + + public override bool DeleteCorpseOnDeath => true; + + public override bool IsDispellable => false; + public override bool Commandable => false; + + public override bool IsHumanInTown() => false; + + private Item CloneItem(Item item) + { + var newItem = new Item(item.ItemID); + newItem.Hue = item.Hue; + newItem.Layer = item.Layer; + + return newItem; + } + + public override void OnDamage(int amount, Mobile from, bool willKill) + { + Delete(); + } + + public override void OnDelete() + { + Effects.SendLocationParticles( + EffectItem.Create(Location, Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 15, + 5042 + ); + + base.OnDelete(); + } + + public override void OnAfterDelete() + { + MirrorImage.RemoveClone(m_Caster); + base.OnAfterDelete(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.WriteEncodedInt(0); // version + + writer.Write(m_Caster); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadEncodedInt(); + + m_Caster = reader.ReadMobile(); + + MirrorImage.AddClone(m_Caster); + } } - - public Clone(Serial serial) : base(serial) - { - } - - protected override BaseAI ForcedAI => new CloneAI(this); - - public override bool DeleteCorpseOnDeath => true; - - public override bool IsDispellable => false; - public override bool Commandable => false; - - public override bool IsHumanInTown() => false; - - private Item CloneItem(Item item) - { - Item newItem = new Item(item.ItemID); - newItem.Hue = item.Hue; - newItem.Layer = item.Layer; - - return newItem; - } - - public override void OnDamage(int amount, Mobile from, bool willKill) - { - Delete(); - } - - public override void OnDelete() - { - Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x3728, 10, 15, - 5042); - - base.OnDelete(); - } - - public override void OnAfterDelete() - { - MirrorImage.RemoveClone(m_Caster); - base.OnAfterDelete(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.WriteEncodedInt(0); // version - - writer.Write(m_Caster); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadEncodedInt(); - - m_Caster = reader.ReadMobile(); - - MirrorImage.AddClone(m_Caster); - } - } } namespace Server.Mobiles { - public class CloneAI : BaseAI - { - public CloneAI(Clone m) : base(m) => m.CurrentSpeed = m.ActiveSpeed; - - public override bool CanDetectHidden => false; - - public override bool Think() + public class CloneAI : BaseAI { - // Clones only follow their owners - Mobile master = m_Mobile.SummonMaster; + public CloneAI(Clone m) : base(m) => m.CurrentSpeed = m.ActiveSpeed; - if (master?.Map == m_Mobile.Map && master?.InRange(m_Mobile, m_Mobile.RangePerception) == true) - { - int iCurrDist = (int)m_Mobile.GetDistanceToSqrt(master); - bool bRun = iCurrDist > 5; + public override bool CanDetectHidden => false; - WalkMobileRange(master, 2, bRun, 0, 1); - } - else - { - WalkRandom(2, 2, 1); - } + public override bool Think() + { + // Clones only follow their owners + var master = m_Mobile.SummonMaster; - return true; + if (master?.Map == m_Mobile.Map && master?.InRange(m_Mobile, m_Mobile.RangePerception) == true) + { + var iCurrDist = (int)m_Mobile.GetDistanceToSqrt(master); + var bRun = iCurrDist > 5; + + WalkMobileRange(master, 2, bRun, 0, 1); + } + else + { + WalkRandom(2, 2, 1); + } + + return true; + } } - } } diff --git a/Projects/UOContent/Spells/Ninjitsu/NinjaMove.cs b/Projects/UOContent/Spells/Ninjitsu/NinjaMove.cs index 1c474106e..ef85608ec 100644 --- a/Projects/UOContent/Spells/Ninjitsu/NinjaMove.cs +++ b/Projects/UOContent/Spells/Ninjitsu/NinjaMove.cs @@ -1,12 +1,12 @@ namespace Server.Spells { - public class NinjaMove : SpecialMove - { - public override SkillName MoveSkill => SkillName.Ninjitsu; - - public override void CheckGain(Mobile m) + public class NinjaMove : SpecialMove { - m.CheckSkill(MoveSkill, RequiredSkill - 12.5, RequiredSkill + 37.5); // Per five on friday 02/16/07 + public override SkillName MoveSkill => SkillName.Ninjitsu; + + public override void CheckGain(Mobile m) + { + m.CheckSkill(MoveSkill, RequiredSkill - 12.5, RequiredSkill + 37.5); // Per five on friday 02/16/07 + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Spells/Ninjitsu/NinjaSpell.cs b/Projects/UOContent/Spells/Ninjitsu/NinjaSpell.cs index e82f2db35..fc62b9d6c 100644 --- a/Projects/UOContent/Spells/Ninjitsu/NinjaSpell.cs +++ b/Projects/UOContent/Spells/Ninjitsu/NinjaSpell.cs @@ -2,93 +2,102 @@ using Server.Mobiles; namespace Server.Spells.Ninjitsu { - public abstract class NinjaSpell : Spell - { - public NinjaSpell(Mobile caster, Item scroll, SpellInfo info) : base(caster, scroll, info) + public abstract class NinjaSpell : Spell { + public NinjaSpell(Mobile caster, Item scroll, SpellInfo info) : base(caster, scroll, info) + { + } + + public abstract double RequiredSkill { get; } + public abstract int RequiredMana { get; } + + public override SkillName CastSkill => SkillName.Ninjitsu; + public override SkillName DamageSkill => SkillName.Ninjitsu; + + public override bool RevealOnCast => false; + public override bool ClearHandsOnCast => false; + public override bool ShowHandMovement => false; + + public override bool BlocksMovement => false; + + // public override int CastDelayBase => 1; + + public override int CastRecoveryBase => 7; + + public static bool CheckExpansion(Mobile from) => + (from as PlayerMobile)?.NetState?.SupportsExpansion(Expansion.SE) == true; + + public override bool CheckCast() + { + var mana = ScaleMana(RequiredMana); + + if (!base.CheckCast()) + return false; + + if (!CheckExpansion(Caster)) + { + Caster.SendLocalizedMessage(1063456); // You must upgrade to Samurai Empire in order to use that ability. + return false; + } + + if (Caster.Skills[CastSkill].Value < RequiredSkill) + { + var args = $"{RequiredSkill:F1}\t{CastSkill.ToString()}\t "; + Caster.SendLocalizedMessage( + 1063013, + args + ); // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability. + return false; + } + + if (Caster.Mana < mana) + { + Caster.SendLocalizedMessage( + 1060174, + mana.ToString() + ); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability. + return false; + } + + return true; + } + + public override bool CheckFizzle() + { + var mana = ScaleMana(RequiredMana); + + if (Caster.Skills[CastSkill].Value < RequiredSkill) + { + Caster.SendLocalizedMessage( + 1063352, + RequiredSkill.ToString("F1") + ); // You need ~1_SKILL_REQUIREMENT~ Ninjitsu skill to perform that attack! + return false; + } + + if (Caster.Mana < mana) + { + Caster.SendLocalizedMessage( + 1060174, + mana.ToString() + ); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability. + return false; + } + + if (!base.CheckFizzle()) + return false; + + Caster.Mana -= mana; + + return true; + } + + public override void GetCastSkills(out double min, out double max) + { + min = RequiredSkill - 12.5; // Per 5 on friday 2/16/07 + max = RequiredSkill + 37.5; + } + + public override int GetMana() => 0; } - - public abstract double RequiredSkill { get; } - public abstract int RequiredMana { get; } - - public override SkillName CastSkill => SkillName.Ninjitsu; - public override SkillName DamageSkill => SkillName.Ninjitsu; - - public override bool RevealOnCast => false; - public override bool ClearHandsOnCast => false; - public override bool ShowHandMovement => false; - - public override bool BlocksMovement => false; - - // public override int CastDelayBase => 1; - - public override int CastRecoveryBase => 7; - - public static bool CheckExpansion(Mobile from) => (from as PlayerMobile)?.NetState?.SupportsExpansion(Expansion.SE) == true; - - public override bool CheckCast() - { - int mana = ScaleMana(RequiredMana); - - if (!base.CheckCast()) - return false; - - if (!CheckExpansion(Caster)) - { - Caster.SendLocalizedMessage(1063456); // You must upgrade to Samurai Empire in order to use that ability. - return false; - } - - if (Caster.Skills[CastSkill].Value < RequiredSkill) - { - string args = $"{RequiredSkill:F1}\t{CastSkill.ToString()}\t "; - Caster.SendLocalizedMessage(1063013, - args); // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability. - return false; - } - - if (Caster.Mana < mana) - { - Caster.SendLocalizedMessage(1060174, - mana.ToString()); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability. - return false; - } - - return true; - } - - public override bool CheckFizzle() - { - int mana = ScaleMana(RequiredMana); - - if (Caster.Skills[CastSkill].Value < RequiredSkill) - { - Caster.SendLocalizedMessage(1063352, - RequiredSkill.ToString("F1")); // You need ~1_SKILL_REQUIREMENT~ Ninjitsu skill to perform that attack! - return false; - } - - if (Caster.Mana < mana) - { - Caster.SendLocalizedMessage(1060174, - mana.ToString()); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability. - return false; - } - - if (!base.CheckFizzle()) - return false; - - Caster.Mana -= mana; - - return true; - } - - public override void GetCastSkills(out double min, out double max) - { - min = RequiredSkill - 12.5; // Per 5 on friday 2/16/07 - max = RequiredSkill + 37.5; - } - - public override int GetMana() => 0; - } } diff --git a/Projects/UOContent/Spells/Ninjitsu/ShadowJump.cs b/Projects/UOContent/Spells/Ninjitsu/ShadowJump.cs index 5bba363d8..bacee7b35 100644 --- a/Projects/UOContent/Spells/Ninjitsu/ShadowJump.cs +++ b/Projects/UOContent/Spells/Ninjitsu/ShadowJump.cs @@ -9,102 +9,109 @@ using Server.Targeting; namespace Server.Spells.Ninjitsu { - public class Shadowjump : NinjaSpell, ISpellTargetingPoint3D - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Shadowjump", null, - -1, - 9002); - - public Shadowjump(Mobile caster, Item scroll) : base(caster, scroll, m_Info) + public class Shadowjump : NinjaSpell, ISpellTargetingPoint3D { + private static readonly SpellInfo m_Info = new SpellInfo( + "Shadowjump", + null, + -1, + 9002 + ); + + public Shadowjump(Mobile caster, Item scroll) : base(caster, scroll, m_Info) + { + } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.0); + + public override double RequiredSkill => 50.0; + public override int RequiredMana => 15; + + public override bool BlockedByAnimalForm => false; + + public void Target(IPoint3D p) + { + var orig = p; + var map = Caster.Map; + + SpellHelper.GetSurfaceTop(ref p); + + var from = Caster.Location; + var to = new Point3D(p); + + var pm = Caster as PlayerMobile; // IsStealthing should be moved to Server.Mobiles + + if (!pm.IsStealthing) + { + Caster.SendLocalizedMessage(1063087); // You must be in stealth mode to use this ability. + } + else if (Sigil.ExistsOn(Caster)) + { + Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. + } + else if (WeightOverloading.IsOverloaded(Caster)) + { + Caster.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move. + } + else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.TeleportFrom) || + !SpellHelper.CheckTravel(Caster, map, to, TravelCheckType.TeleportTo)) + { + } + else if (map?.CanSpawnMobile(p.X, p.Y, p.Z) != true) + { + Caster.SendLocalizedMessage(502831); // Cannot teleport to that spot. + } + else if (SpellHelper.CheckMulti(to, map, true, 5)) + { + Caster.SendLocalizedMessage(502831); // Cannot teleport to that spot. + } + else if (Region.Find(to, map).IsPartOf()) + { + Caster.SendLocalizedMessage(502829); // Cannot teleport to that spot. + } + else if (CheckSequence()) + { + SpellHelper.Turn(Caster, orig); + + var m = Caster; + + m.Location = to; + m.ProcessDelta(); + + Effects.SendLocationParticles( + EffectItem.Create(from, m.Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 2023 + ); + + m.PlaySound(0x512); + + Stealth.OnUse(m); // stealth check after the a jump + } + + FinishSequence(); + } + + public override bool CheckCast() + { + // IsStealthing should be moved to Server.Mobiles + if ((Caster as PlayerMobile)?.IsStealthing != true) + { + Caster.SendLocalizedMessage(1063087); // You must be in stealth mode to use this ability. + return false; + } + + return base.CheckCast(); + } + + public override bool CheckDisturb(DisturbType type, bool firstCircle, bool resistable) => false; + + public override void OnCast() + { + Caster.SendLocalizedMessage(1063088); // You prepare to perform a Shadowjump. + Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, 11); + } } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.0); - - public override double RequiredSkill => 50.0; - public override int RequiredMana => 15; - - public override bool BlockedByAnimalForm => false; - - public override bool CheckCast() - { - // IsStealthing should be moved to Server.Mobiles - if ((Caster as PlayerMobile)?.IsStealthing != true) - { - Caster.SendLocalizedMessage(1063087); // You must be in stealth mode to use this ability. - return false; - } - - return base.CheckCast(); - } - - public override bool CheckDisturb(DisturbType type, bool firstCircle, bool resistable) => false; - - public override void OnCast() - { - Caster.SendLocalizedMessage(1063088); // You prepare to perform a Shadowjump. - Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, 11); - } - - public void Target(IPoint3D p) - { - IPoint3D orig = p; - Map map = Caster.Map; - - SpellHelper.GetSurfaceTop(ref p); - - Point3D from = Caster.Location; - Point3D to = new Point3D(p); - - PlayerMobile pm = Caster as PlayerMobile; // IsStealthing should be moved to Server.Mobiles - - if (!pm.IsStealthing) - { - Caster.SendLocalizedMessage(1063087); // You must be in stealth mode to use this ability. - } - else if (Sigil.ExistsOn(Caster)) - { - Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. - } - else if (WeightOverloading.IsOverloaded(Caster)) - { - Caster.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move. - } - else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.TeleportFrom) || - !SpellHelper.CheckTravel(Caster, map, to, TravelCheckType.TeleportTo)) - { - } - else if (map?.CanSpawnMobile(p.X, p.Y, p.Z) != true) - { - Caster.SendLocalizedMessage(502831); // Cannot teleport to that spot. - } - else if (SpellHelper.CheckMulti(to, map, true, 5)) - { - Caster.SendLocalizedMessage(502831); // Cannot teleport to that spot. - } - else if (Region.Find(to, map).IsPartOf()) - { - Caster.SendLocalizedMessage(502829); // Cannot teleport to that spot. - } - else if (CheckSequence()) - { - SpellHelper.Turn(Caster, orig); - - Mobile m = Caster; - - m.Location = to; - m.ProcessDelta(); - - Effects.SendLocationParticles(EffectItem.Create(from, m.Map, EffectItem.DefaultDuration), 0x3728, 10, 10, - 2023); - - m.PlaySound(0x512); - - Stealth.OnUse(m); // stealth check after the a jump - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Ninjitsu/SurpriseAttack.cs b/Projects/UOContent/Spells/Ninjitsu/SurpriseAttack.cs index d5eae76e9..51bcbf692 100644 --- a/Projects/UOContent/Spells/Ninjitsu/SurpriseAttack.cs +++ b/Projects/UOContent/Spells/Ninjitsu/SurpriseAttack.cs @@ -4,110 +4,111 @@ using Server.SkillHandlers; namespace Server.Spells.Ninjitsu { - public class SurpriseAttack : NinjaMove - { - private static readonly Dictionary m_Table = new Dictionary(); - - public override int BaseMana => 20; - public override double RequiredSkill => Core.ML ? 60.0 : 30.0; - - public override TextDefinition AbilityMessage => new TextDefinition(1063128); // You prepare to surprise your prey. - - public override bool ValidatesDuringHit => false; - - public override bool Validate(Mobile from) + public class SurpriseAttack : NinjaMove { - if (!from.Hidden || from.AllowedStealthSteps <= 0) - { - from.SendLocalizedMessage(1063087); // You must be in stealth mode to use this ability. - return false; - } + private static readonly Dictionary + m_Table = new Dictionary(); - return base.Validate(from); + public override int BaseMana => 20; + public override double RequiredSkill => Core.ML ? 60.0 : 30.0; + + public override TextDefinition AbilityMessage => new TextDefinition(1063128); // You prepare to surprise your prey. + + public override bool ValidatesDuringHit => false; + + public override bool Validate(Mobile from) + { + if (!from.Hidden || from.AllowedStealthSteps <= 0) + { + from.SendLocalizedMessage(1063087); // You must be in stealth mode to use this ability. + return false; + } + + return base.Validate(from); + } + + public override bool OnBeforeSwing(Mobile attacker, Mobile defender) + { + var valid = Validate(attacker) && CheckMana(attacker, true); + + if (valid) + { + attacker.BeginAction(); + Timer.DelayCall(TimeSpan.FromSeconds(5.0), attacker.EndAction); + } + + return valid; + } + + public override void OnHit(Mobile attacker, Mobile defender, int damage) + { + // Validates before swing + + ClearCurrentMove(attacker); + + attacker.SendLocalizedMessage(1063129); // You catch your opponent off guard with your Surprise Attack! + defender.SendLocalizedMessage(1063130); // Your defenses are lowered as your opponent surprises you! + + defender.FixedParticles(0x37B9, 1, 5, 0x26DA, 0, 3, EffectLayer.Head); + + attacker.RevealingAction(); + + if (m_Table.TryGetValue(defender, out var info)) + { + info.m_Timer?.Stop(); + + m_Table.Remove(defender); + } + + var ninjitsu = attacker.Skills.Ninjitsu.Fixed; + + var malus = ninjitsu / 60 + (int)Tracking.GetStalkingBonus(attacker, defender); + + info = new SurpriseAttackInfo(defender, malus); + info.m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(8.0), EndSurprise, info); + + m_Table[defender] = info; + + CheckGain(attacker); + } + + public override void OnMiss(Mobile attacker, Mobile defender) + { + ClearCurrentMove(attacker); + + attacker.SendLocalizedMessage(1063161); // You failed to properly use the element of surprise. + + attacker.RevealingAction(); + } + + public static bool GetMalus(Mobile target, ref int malus) + { + if (!m_Table.TryGetValue(target, out var info)) + return false; + + malus = info.m_Malus; + return true; + } + + private static void EndSurprise(SurpriseAttackInfo info) + { + info.m_Timer?.Stop(); + info.m_Target.SendLocalizedMessage(1063131); // Your defenses have returned to normal. + + m_Table.Remove(info.m_Target); + } + + private class SurpriseAttackInfo + { + public readonly int m_Malus; + public readonly Mobile m_Target; + public Timer m_Timer; + + public SurpriseAttackInfo(Mobile target, int effect) + { + m_Target = target; + m_Malus = effect; + } + } } - - public override bool OnBeforeSwing(Mobile attacker, Mobile defender) - { - bool valid = Validate(attacker) && CheckMana(attacker, true); - - if (valid) - { - attacker.BeginAction(); - Timer.DelayCall(TimeSpan.FromSeconds(5.0), attacker.EndAction); - } - - return valid; - } - - public override void OnHit(Mobile attacker, Mobile defender, int damage) - { - // Validates before swing - - ClearCurrentMove(attacker); - - attacker.SendLocalizedMessage(1063129); // You catch your opponent off guard with your Surprise Attack! - defender.SendLocalizedMessage(1063130); // Your defenses are lowered as your opponent surprises you! - - defender.FixedParticles(0x37B9, 1, 5, 0x26DA, 0, 3, EffectLayer.Head); - - attacker.RevealingAction(); - - if (m_Table.TryGetValue(defender, out SurpriseAttackInfo info)) - { - info.m_Timer?.Stop(); - - m_Table.Remove(defender); - } - - int ninjitsu = attacker.Skills.Ninjitsu.Fixed; - - int malus = ninjitsu / 60 + (int)Tracking.GetStalkingBonus(attacker, defender); - - info = new SurpriseAttackInfo(defender, malus); - info.m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(8.0), EndSurprise, info); - - m_Table[defender] = info; - - CheckGain(attacker); - } - - public override void OnMiss(Mobile attacker, Mobile defender) - { - ClearCurrentMove(attacker); - - attacker.SendLocalizedMessage(1063161); // You failed to properly use the element of surprise. - - attacker.RevealingAction(); - } - - public static bool GetMalus(Mobile target, ref int malus) - { - if (!m_Table.TryGetValue(target, out SurpriseAttackInfo info)) - return false; - - malus = info.m_Malus; - return true; - } - - private static void EndSurprise(SurpriseAttackInfo info) - { - info.m_Timer?.Stop(); - info.m_Target.SendLocalizedMessage(1063131); // Your defenses have returned to normal. - - m_Table.Remove(info.m_Target); - } - - private class SurpriseAttackInfo - { - public readonly int m_Malus; - public readonly Mobile m_Target; - public Timer m_Timer; - - public SurpriseAttackInfo(Mobile target, int effect) - { - m_Target = target; - m_Malus = effect; - } - } - } } diff --git a/Projects/UOContent/Spells/Reagent.cs b/Projects/UOContent/Spells/Reagent.cs index fee372237..6c34cdb2e 100644 --- a/Projects/UOContent/Spells/Reagent.cs +++ b/Projects/UOContent/Spells/Reagent.cs @@ -3,131 +3,131 @@ using Server.Items; namespace Server.Spells { - public class Reagent - { - private static readonly Type[] m_Types = + public class Reagent { - typeof(BlackPearl), - typeof(Bloodmoss), - typeof(Garlic), - typeof(Ginseng), - typeof(MandrakeRoot), - typeof(Nightshade), - typeof(SulfurousAsh), - typeof(SpidersSilk), - typeof(BatWing), - typeof(GraveDust), - typeof(DaemonBlood), - typeof(NoxCrystal), - typeof(PigIron), - typeof(Bone), - typeof(FertileDirt), - typeof(DragonsBlood), - typeof(DaemonBone) - }; + private static readonly Type[] m_Types = + { + typeof(BlackPearl), + typeof(Bloodmoss), + typeof(Garlic), + typeof(Ginseng), + typeof(MandrakeRoot), + typeof(Nightshade), + typeof(SulfurousAsh), + typeof(SpidersSilk), + typeof(BatWing), + typeof(GraveDust), + typeof(DaemonBlood), + typeof(NoxCrystal), + typeof(PigIron), + typeof(Bone), + typeof(FertileDirt), + typeof(DragonsBlood), + typeof(DaemonBone) + }; - public Type[] Types => m_Types; + public Type[] Types => m_Types; - public static Type BlackPearl - { - get => m_Types[0]; - set => m_Types[0] = value; + public static Type BlackPearl + { + get => m_Types[0]; + set => m_Types[0] = value; + } + + public static Type Bloodmoss + { + get => m_Types[1]; + set => m_Types[1] = value; + } + + public static Type Garlic + { + get => m_Types[2]; + set => m_Types[2] = value; + } + + public static Type Ginseng + { + get => m_Types[3]; + set => m_Types[3] = value; + } + + public static Type MandrakeRoot + { + get => m_Types[4]; + set => m_Types[4] = value; + } + + public static Type Nightshade + { + get => m_Types[5]; + set => m_Types[5] = value; + } + + public static Type SulfurousAsh + { + get => m_Types[6]; + set => m_Types[6] = value; + } + + public static Type SpidersSilk + { + get => m_Types[7]; + set => m_Types[7] = value; + } + + public static Type BatWing + { + get => m_Types[8]; + set => m_Types[8] = value; + } + + public static Type GraveDust + { + get => m_Types[9]; + set => m_Types[9] = value; + } + + public static Type DaemonBlood + { + get => m_Types[10]; + set => m_Types[10] = value; + } + + public static Type NoxCrystal + { + get => m_Types[11]; + set => m_Types[11] = value; + } + + public static Type PigIron + { + get => m_Types[12]; + set => m_Types[12] = value; + } + + public static Type Bone + { + get => m_Types[13]; + set => m_Types[13] = value; + } + + public static Type FertileDirt + { + get => m_Types[14]; + set => m_Types[14] = value; + } + + public static Type DragonsBlood + { + get => m_Types[15]; + set => m_Types[15] = value; + } + + public static Type DaemonBone + { + get => m_Types[16]; + set => m_Types[16] = value; + } } - - public static Type Bloodmoss - { - get => m_Types[1]; - set => m_Types[1] = value; - } - - public static Type Garlic - { - get => m_Types[2]; - set => m_Types[2] = value; - } - - public static Type Ginseng - { - get => m_Types[3]; - set => m_Types[3] = value; - } - - public static Type MandrakeRoot - { - get => m_Types[4]; - set => m_Types[4] = value; - } - - public static Type Nightshade - { - get => m_Types[5]; - set => m_Types[5] = value; - } - - public static Type SulfurousAsh - { - get => m_Types[6]; - set => m_Types[6] = value; - } - - public static Type SpidersSilk - { - get => m_Types[7]; - set => m_Types[7] = value; - } - - public static Type BatWing - { - get => m_Types[8]; - set => m_Types[8] = value; - } - - public static Type GraveDust - { - get => m_Types[9]; - set => m_Types[9] = value; - } - - public static Type DaemonBlood - { - get => m_Types[10]; - set => m_Types[10] = value; - } - - public static Type NoxCrystal - { - get => m_Types[11]; - set => m_Types[11] = value; - } - - public static Type PigIron - { - get => m_Types[12]; - set => m_Types[12] = value; - } - - public static Type Bone - { - get => m_Types[13]; - set => m_Types[13] = value; - } - - public static Type FertileDirt - { - get => m_Types[14]; - set => m_Types[14] = value; - } - - public static Type DragonsBlood - { - get => m_Types[15]; - set => m_Types[15] = value; - } - - public static Type DaemonBone - { - get => m_Types[16]; - set => m_Types[16] = value; - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Spells/Second/Agility.cs b/Projects/UOContent/Spells/Second/Agility.cs index 4204440c1..406f17e30 100644 --- a/Projects/UOContent/Spells/Second/Agility.cs +++ b/Projects/UOContent/Spells/Second/Agility.cs @@ -1,63 +1,66 @@ -using System; using Server.Engines.ConPVP; using Server.Targeting; namespace Server.Spells.Second { - public class AgilitySpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Agility", "Ex Uus", - 212, - 9061, - Reagent.Bloodmoss, - Reagent.MandrakeRoot); - - public AgilitySpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class AgilitySpell : MagerySpell, ISpellTargetingMobile { + private static readonly SpellInfo m_Info = new SpellInfo( + "Agility", + "Ex Uus", + 212, + 9061, + Reagent.Bloodmoss, + Reagent.MandrakeRoot + ); + + public AgilitySpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.Second; + + public void Target(Mobile m) + { + if (m == null) + return; + + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckBSequence(m)) + { + SpellHelper.Turn(Caster, m); + + SpellHelper.AddStatBonus(Caster, m, StatType.Dex); + + m.FixedParticles(0x375A, 10, 15, 5010, EffectLayer.Waist); + m.PlaySound(0x1e7); + + var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, false) * 100); + var length = SpellHelper.GetDuration(Caster, m); + + BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Agility, 1075841, length, m, percentage.ToString())); + } + + FinishSequence(); + } + + public override bool CheckCast() + { + if (DuelContext.CheckSuddenDeath(Caster)) + { + Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); + return false; + } + + return base.CheckCast(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, Core.ML ? 10 : 12); + } } - - public override SpellCircle Circle => SpellCircle.Second; - - public override bool CheckCast() - { - if (DuelContext.CheckSuddenDeath(Caster)) - { - Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); - return false; - } - - return base.CheckCast(); - } - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (CheckBSequence(m)) - { - SpellHelper.Turn(Caster, m); - - SpellHelper.AddStatBonus(Caster, m, StatType.Dex); - - m.FixedParticles(0x375A, 10, 15, 5010, EffectLayer.Waist); - m.PlaySound(0x1e7); - - int percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, false) * 100); - TimeSpan length = SpellHelper.GetDuration(Caster, m); - - BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Agility, 1075841, length, m, percentage.ToString())); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Second/Cunning.cs b/Projects/UOContent/Spells/Second/Cunning.cs index 160256bc3..a33c2f6cc 100644 --- a/Projects/UOContent/Spells/Second/Cunning.cs +++ b/Projects/UOContent/Spells/Second/Cunning.cs @@ -1,63 +1,66 @@ -using System; using Server.Engines.ConPVP; using Server.Targeting; namespace Server.Spells.Second { - public class CunningSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Cunning", "Uus Wis", - 212, - 9061, - Reagent.MandrakeRoot, - Reagent.Nightshade); - - public CunningSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class CunningSpell : MagerySpell, ISpellTargetingMobile { + private static readonly SpellInfo m_Info = new SpellInfo( + "Cunning", + "Uus Wis", + 212, + 9061, + Reagent.MandrakeRoot, + Reagent.Nightshade + ); + + public CunningSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.Second; + + public void Target(Mobile m) + { + if (m == null) + return; + + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckBSequence(m)) + { + SpellHelper.Turn(Caster, m); + + SpellHelper.AddStatBonus(Caster, m, StatType.Int); + + m.FixedParticles(0x375A, 10, 15, 5011, EffectLayer.Head); + m.PlaySound(0x1EB); + + var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, false) * 100); + var length = SpellHelper.GetDuration(Caster, m); + + BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Cunning, 1075843, length, m, percentage.ToString())); + } + + FinishSequence(); + } + + public override bool CheckCast() + { + if (DuelContext.CheckSuddenDeath(Caster)) + { + Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); + return false; + } + + return base.CheckCast(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, Core.ML ? 10 : 12); + } } - - public override SpellCircle Circle => SpellCircle.Second; - - public override bool CheckCast() - { - if (DuelContext.CheckSuddenDeath(Caster)) - { - Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); - return false; - } - - return base.CheckCast(); - } - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (CheckBSequence(m)) - { - SpellHelper.Turn(Caster, m); - - SpellHelper.AddStatBonus(Caster, m, StatType.Int); - - m.FixedParticles(0x375A, 10, 15, 5011, EffectLayer.Head); - m.PlaySound(0x1EB); - - int percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, false) * 100); - TimeSpan length = SpellHelper.GetDuration(Caster, m); - - BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Cunning, 1075843, length, m, percentage.ToString())); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Second/Cure.cs b/Projects/UOContent/Spells/Second/Cure.cs index 5ba99637d..ab8d8bc2b 100644 --- a/Projects/UOContent/Spells/Second/Cure.cs +++ b/Projects/UOContent/Spells/Second/Cure.cs @@ -3,77 +3,81 @@ using Server.Targeting; namespace Server.Spells.Second { - public class CureSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Cure", "An Nox", - 212, - 9061, - Reagent.Garlic, - Reagent.Ginseng); - - public CureSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class CureSpell : MagerySpell, ISpellTargetingMobile { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Cure", + "An Nox", + 212, + 9061, + Reagent.Garlic, + Reagent.Ginseng + ); - public override SpellCircle Circle => SpellCircle.Second; - - public override bool CheckCast() - { - if (DuelContext.CheckSuddenDeath(Caster)) - { - Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); - return false; - } - - return base.CheckCast(); - } - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (CheckBSequence(m)) - { - SpellHelper.Turn(Caster, m); - - Poison p = m.Poison; - - if (p != null) + public CureSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - int chanceToCure = 10000 + (int)(Caster.Skills.Magery.Value * 75) - - (p.Level + 1) * (Core.AOS ? p.Level < 4 ? 3300 : 3100 : 1750); - chanceToCure /= 100; - - if (chanceToCure > Utility.Random(100)) - { - if (m.CurePoison(Caster)) - { - if (Caster != m) - Caster.SendLocalizedMessage(1010058); // You have cured the target of all poisons! - - m.SendLocalizedMessage(1010059); // You have been cured of all poisons. - } - } - else - { - m.SendLocalizedMessage(1010060); // You have failed to cure your target! - } } - m.FixedParticles(0x373A, 10, 15, 5012, EffectLayer.Waist); - m.PlaySound(0x1E0); - } + public override SpellCircle Circle => SpellCircle.Second; - FinishSequence(); + public void Target(Mobile m) + { + if (m == null) + return; + + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckBSequence(m)) + { + SpellHelper.Turn(Caster, m); + + var p = m.Poison; + + if (p != null) + { + var chanceToCure = 10000 + (int)(Caster.Skills.Magery.Value * 75) - + (p.Level + 1) * (Core.AOS ? p.Level < 4 ? 3300 : 3100 : 1750); + chanceToCure /= 100; + + if (chanceToCure > Utility.Random(100)) + { + if (m.CurePoison(Caster)) + { + if (Caster != m) + Caster.SendLocalizedMessage(1010058); // You have cured the target of all poisons! + + m.SendLocalizedMessage(1010059); // You have been cured of all poisons. + } + } + else + { + m.SendLocalizedMessage(1010060); // You have failed to cure your target! + } + } + + m.FixedParticles(0x373A, 10, 15, 5012, EffectLayer.Waist); + m.PlaySound(0x1E0); + } + + FinishSequence(); + } + + public override bool CheckCast() + { + if (DuelContext.CheckSuddenDeath(Caster)) + { + Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); + return false; + } + + return base.CheckCast(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, Core.ML ? 10 : 12); + } } - } } diff --git a/Projects/UOContent/Spells/Second/Harm.cs b/Projects/UOContent/Spells/Second/Harm.cs index 183569d34..18eb0d71b 100644 --- a/Projects/UOContent/Spells/Second/Harm.cs +++ b/Projects/UOContent/Spells/Second/Harm.cs @@ -2,83 +2,87 @@ using Server.Targeting; namespace Server.Spells.Second { - public class HarmSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Harm", "An Mani", - 212, - Core.AOS ? 9001 : 9041, - Reagent.Nightshade, - Reagent.SpidersSilk); - - public HarmSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class HarmSpell : MagerySpell, ISpellTargetingMobile { + private static readonly SpellInfo m_Info = new SpellInfo( + "Harm", + "An Mani", + 212, + Core.AOS ? 9001 : 9041, + Reagent.Nightshade, + Reagent.SpidersSilk + ); + + public HarmSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.Second; + + public override bool DelayedDamage => false; + + public void Target(Mobile m) + { + if (m == null) + return; + + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckHSequence(m)) + { + SpellHelper.Turn(Caster, m); + + SpellHelper.CheckReflect((int)Circle, Caster, ref m); + + double damage; + + if (Core.AOS) + { + damage = GetNewAosDamage(17, 1, 5, m); + } + else + { + damage = Utility.Random(1, 15); + + if (CheckResisted(m)) + { + damage *= 0.75; + + m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + } + + damage *= GetDamageScalar(m); + } + + if (!m.InRange(Caster, 2)) + damage *= 0.25; // 1/4 damage at > 2 tile range + else if (!m.InRange(Caster, 1)) + damage *= 0.50; // 1/2 damage at 2 tile range + + if (Core.AOS) + { + m.FixedParticles(0x374A, 10, 30, 5013, 1153, 2, EffectLayer.Waist); + m.PlaySound(0x0FC); + } + else + { + m.FixedParticles(0x374A, 10, 15, 5013, EffectLayer.Waist); + m.PlaySound(0x1F1); + } + + SpellHelper.Damage(this, m, damage, 0, 0, 100, 0, 0); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } + + public override double GetSlayerDamageScalar(Mobile target) => 1.0; } - - public override SpellCircle Circle => SpellCircle.Second; - - public override bool DelayedDamage => false; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - public override double GetSlayerDamageScalar(Mobile target) => 1.0; - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (CheckHSequence(m)) - { - SpellHelper.Turn(Caster, m); - - SpellHelper.CheckReflect((int)Circle, Caster, ref m); - - double damage; - - if (Core.AOS) - { - damage = GetNewAosDamage(17, 1, 5, m); - } - else - { - damage = Utility.Random(1, 15); - - if (CheckResisted(m)) - { - damage *= 0.75; - - m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. - } - - damage *= GetDamageScalar(m); - } - - if (!m.InRange(Caster, 2)) - damage *= 0.25; // 1/4 damage at > 2 tile range - else if (!m.InRange(Caster, 1)) - damage *= 0.50; // 1/2 damage at 2 tile range - - if (Core.AOS) - { - m.FixedParticles(0x374A, 10, 30, 5013, 1153, 2, EffectLayer.Waist); - m.PlaySound(0x0FC); - } - else - { - m.FixedParticles(0x374A, 10, 15, 5013, EffectLayer.Waist); - m.PlaySound(0x1F1); - } - - SpellHelper.Damage(this, m, damage, 0, 0, 100, 0, 0); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Second/MagicTrap.cs b/Projects/UOContent/Spells/Second/MagicTrap.cs index 13e5d240b..64baff50a 100644 --- a/Projects/UOContent/Spells/Second/MagicTrap.cs +++ b/Projects/UOContent/Spells/Second/MagicTrap.cs @@ -3,69 +3,93 @@ using Server.Targeting; namespace Server.Spells.Second { - public class MagicTrapSpell : MagerySpell, ISpellTargetingItem - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Magic Trap", "In Jux", - 212, - 9001, - Reagent.Garlic, - Reagent.SpidersSilk, - Reagent.SulfurousAsh); - - public MagicTrapSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class MagicTrapSpell : MagerySpell, ISpellTargetingItem { + private static readonly SpellInfo m_Info = new SpellInfo( + "Magic Trap", + "In Jux", + 212, + 9001, + Reagent.Garlic, + Reagent.SpidersSilk, + Reagent.SulfurousAsh + ); + + public MagicTrapSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.Second; + + public void Target(Item item) + { + if (!(item is TrappableContainer cont)) + { + Caster.SendMessage("You can't trap that"); // TODO: Localization for this? + } + else if (!Caster.CanSee(item)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (cont.TrapType != TrapType.None && cont.TrapType != TrapType.MagicTrap) + { + DoFizzle(); + } + else if (CheckSequence()) + { + SpellHelper.Turn(Caster, item); + + cont.TrapType = TrapType.MagicTrap; + cont.TrapPower = Core.AOS ? Utility.RandomMinMax(10, 50) : 1; + cont.TrapLevel = 0; + + var loc = item.GetWorldLocation(); + + Effects.SendLocationParticles( + EffectItem.Create(new Point3D(loc.X + 1, loc.Y, loc.Z), item.Map, EffectItem.DefaultDuration), + 0x376A, + 9, + 10, + 9502 + ); + Effects.SendLocationParticles( + EffectItem.Create(new Point3D(loc.X, loc.Y - 1, loc.Z), item.Map, EffectItem.DefaultDuration), + 0x376A, + 9, + 10, + 9502 + ); + Effects.SendLocationParticles( + EffectItem.Create(new Point3D(loc.X - 1, loc.Y, loc.Z), item.Map, EffectItem.DefaultDuration), + 0x376A, + 9, + 10, + 9502 + ); + Effects.SendLocationParticles( + EffectItem.Create(new Point3D(loc.X, loc.Y + 1, loc.Z), item.Map, EffectItem.DefaultDuration), + 0x376A, + 9, + 10, + 9502 + ); + Effects.SendLocationParticles( + EffectItem.Create(new Point3D(loc.X, loc.Y, loc.Z), item.Map, EffectItem.DefaultDuration), + 0, + 0, + 0, + 5014 + ); + + Effects.PlaySound(loc, item.Map, 0x1EF); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetItem(this, TargetFlags.None, Core.ML ? 10 : 12); + } } - - public override SpellCircle Circle => SpellCircle.Second; - - public override void OnCast() - { - Caster.Target = new SpellTargetItem(this, TargetFlags.None, Core.ML ? 10 : 12); - } - - public void Target(Item item) - { - if (!(item is TrappableContainer cont)) - Caster.SendMessage("You can't trap that"); // TODO: Localization for this? - else if (!Caster.CanSee(item)) - { - Caster.SendLocalizedMessage(500237); // Target can not be seen. - } - else if (cont.TrapType != TrapType.None && cont.TrapType != TrapType.MagicTrap) - { - DoFizzle(); - } - else if (CheckSequence()) - { - SpellHelper.Turn(Caster, item); - - cont.TrapType = TrapType.MagicTrap; - cont.TrapPower = Core.AOS ? Utility.RandomMinMax(10, 50) : 1; - cont.TrapLevel = 0; - - Point3D loc = item.GetWorldLocation(); - - Effects.SendLocationParticles( - EffectItem.Create(new Point3D(loc.X + 1, loc.Y, loc.Z), item.Map, EffectItem.DefaultDuration), 0x376A, 9, - 10, 9502); - Effects.SendLocationParticles( - EffectItem.Create(new Point3D(loc.X, loc.Y - 1, loc.Z), item.Map, EffectItem.DefaultDuration), 0x376A, 9, - 10, 9502); - Effects.SendLocationParticles( - EffectItem.Create(new Point3D(loc.X - 1, loc.Y, loc.Z), item.Map, EffectItem.DefaultDuration), 0x376A, 9, - 10, 9502); - Effects.SendLocationParticles( - EffectItem.Create(new Point3D(loc.X, loc.Y + 1, loc.Z), item.Map, EffectItem.DefaultDuration), 0x376A, 9, - 10, 9502); - Effects.SendLocationParticles( - EffectItem.Create(new Point3D(loc.X, loc.Y, loc.Z), item.Map, EffectItem.DefaultDuration), 0, 0, 0, - 5014); - - Effects.PlaySound(loc, item.Map, 0x1EF); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Second/Protection.cs b/Projects/UOContent/Spells/Second/Protection.cs index 376687c7a..722ceb6a5 100644 --- a/Projects/UOContent/Spells/Second/Protection.cs +++ b/Projects/UOContent/Spells/Second/Protection.cs @@ -3,168 +3,177 @@ using System.Collections.Generic; namespace Server.Spells.Second { - public class ProtectionSpell : MagerySpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Protection", "Uus Sanct", - 236, - 9011, - Reagent.Garlic, - Reagent.Ginseng, - Reagent.SulfurousAsh); - - private static readonly Dictionary> m_Table = new Dictionary>(); - - public ProtectionSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class ProtectionSpell : MagerySpell { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Protection", + "Uus Sanct", + 236, + 9011, + Reagent.Garlic, + Reagent.Ginseng, + Reagent.SulfurousAsh + ); - public static Dictionary Registry { get; } = new Dictionary(); + private static readonly Dictionary> m_Table = + new Dictionary>(); - public override SpellCircle Circle => SpellCircle.Second; - - public override bool CheckCast() - { - if (Core.AOS) - return true; - - if (Registry.ContainsKey(Caster)) - { - Caster.SendLocalizedMessage(1005559); // This spell is already in effect. - return false; - } - - if (Caster.CanBeginAction()) - return true; - - Caster.SendLocalizedMessage(1005385); // The spell will not adhere to you at this time. - return false; - } - - public static void Toggle(Mobile caster, Mobile target) - { - /* Players under the protection spell effect can no longer have their spells "disrupted" when hit. - * Players under the protection spell have decreased physical resistance stat value (-15 + (Inscription/20), - * a decreased "resisting spells" skill value by -35 + (Inscription/20), - * and a slower casting speed modifier (technically, a negative "faster cast speed") of 2 points. - * The protection spell has an indefinite duration, becoming active when cast, and deactivated when re-cast. - * Reactive Armor, Protection, and Magic Reflection will stay on�even after logging out, - * even after dying�until you �turn them off� by casting them again. - */ - - if (m_Table.TryGetValue(target, out Tuple mods)) - { - target.PlaySound(0x1ED); - target.FixedParticles(0x375A, 9, 20, 5016, EffectLayer.Waist); - - m_Table.Remove(target); - Registry.Remove(target); - - target.RemoveResistanceMod(mods.Item1); - target.RemoveSkillMod(mods.Item2); - - BuffInfo.RemoveBuff(target, BuffIcon.Protection); - } - else - { - target.PlaySound(0x1E9); - target.FixedParticles(0x375A, 9, 20, 5016, EffectLayer.Waist); - - mods = new Tuple( - new ResistanceMod(ResistanceType.Physical, - -15 + Math.Min((int)(caster.Skills.Inscribe.Value / 20), 15)), - new DefaultSkillMod(SkillName.MagicResist, true, - -35 + Math.Min((int)(caster.Skills.Inscribe.Value / 20), 35))); - - m_Table[target] = mods; - Registry[target] = 100.0; - - target.AddResistanceMod(mods.Item1); - target.AddSkillMod(mods.Item2); - - int physloss = -15 + (int)(caster.Skills.Inscribe.Value / 20); - int resistloss = -35 + (int)(caster.Skills.Inscribe.Value / 20); - string args = $"{physloss}\t{resistloss}"; - BuffInfo.AddBuff(target, new BuffInfo(BuffIcon.Protection, 1075814, 1075815, args)); - } - } - - public static void EndProtection(Mobile m) - { - if (!m_Table.TryGetValue(m, out Tuple mods)) - return; - - m_Table.Remove(m); - Registry.Remove(m); - - m.RemoveResistanceMod(mods.Item1); - m.RemoveSkillMod(mods.Item2); - - BuffInfo.RemoveBuff(m, BuffIcon.Protection); - } - - public override void OnCast() - { - if (Core.AOS) - { - if (CheckSequence()) - Toggle(Caster, Caster); - - FinishSequence(); - } - else - { - if (Registry.ContainsKey(Caster)) + public ProtectionSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - Caster.SendLocalizedMessage(1005559); // This spell is already in effect. } - else if (!Caster.CanBeginAction()) - { - Caster.SendLocalizedMessage(1005385); // The spell will not adhere to you at this time. - } - else if (CheckSequence()) - { - if (Caster.BeginAction()) - { - double value = (int)(Caster.Skills.EvalInt.Value + - Caster.Skills.Meditation.Value + - Caster.Skills.Inscribe.Value); - value /= 4; - Registry.Add(Caster, Math.Clamp(value, 0.0, 75.0)); - new InternalTimer(Caster).Start(); + public static Dictionary Registry { get; } = new Dictionary(); + + public override SpellCircle Circle => SpellCircle.Second; + + public override bool CheckCast() + { + if (Core.AOS) + return true; + + if (Registry.ContainsKey(Caster)) + { + Caster.SendLocalizedMessage(1005559); // This spell is already in effect. + return false; + } + + if (Caster.CanBeginAction()) + return true; - Caster.FixedParticles(0x375A, 9, 20, 5016, EffectLayer.Waist); - Caster.PlaySound(0x1ED); - } - else - { Caster.SendLocalizedMessage(1005385); // The spell will not adhere to you at this time. - } + return false; } - FinishSequence(); - } + public static void Toggle(Mobile caster, Mobile target) + { + /* Players under the protection spell effect can no longer have their spells "disrupted" when hit. + * Players under the protection spell have decreased physical resistance stat value (-15 + (Inscription/20), + * a decreased "resisting spells" skill value by -35 + (Inscription/20), + * and a slower casting speed modifier (technically, a negative "faster cast speed") of 2 points. + * The protection spell has an indefinite duration, becoming active when cast, and deactivated when re-cast. + * Reactive Armor, Protection, and Magic Reflection will stay on�even after logging out, + * even after dying�until you �turn them off� by casting them again. + */ + + if (m_Table.TryGetValue(target, out var mods)) + { + target.PlaySound(0x1ED); + target.FixedParticles(0x375A, 9, 20, 5016, EffectLayer.Waist); + + m_Table.Remove(target); + Registry.Remove(target); + + target.RemoveResistanceMod(mods.Item1); + target.RemoveSkillMod(mods.Item2); + + BuffInfo.RemoveBuff(target, BuffIcon.Protection); + } + else + { + target.PlaySound(0x1E9); + target.FixedParticles(0x375A, 9, 20, 5016, EffectLayer.Waist); + + mods = new Tuple( + new ResistanceMod( + ResistanceType.Physical, + -15 + Math.Min((int)(caster.Skills.Inscribe.Value / 20), 15) + ), + new DefaultSkillMod( + SkillName.MagicResist, + true, + -35 + Math.Min((int)(caster.Skills.Inscribe.Value / 20), 35) + ) + ); + + m_Table[target] = mods; + Registry[target] = 100.0; + + target.AddResistanceMod(mods.Item1); + target.AddSkillMod(mods.Item2); + + var physloss = -15 + (int)(caster.Skills.Inscribe.Value / 20); + var resistloss = -35 + (int)(caster.Skills.Inscribe.Value / 20); + var args = $"{physloss}\t{resistloss}"; + BuffInfo.AddBuff(target, new BuffInfo(BuffIcon.Protection, 1075814, 1075815, args)); + } + } + + public static void EndProtection(Mobile m) + { + if (!m_Table.TryGetValue(m, out var mods)) + return; + + m_Table.Remove(m); + Registry.Remove(m); + + m.RemoveResistanceMod(mods.Item1); + m.RemoveSkillMod(mods.Item2); + + BuffInfo.RemoveBuff(m, BuffIcon.Protection); + } + + public override void OnCast() + { + if (Core.AOS) + { + if (CheckSequence()) + Toggle(Caster, Caster); + + FinishSequence(); + } + else + { + if (Registry.ContainsKey(Caster)) + { + Caster.SendLocalizedMessage(1005559); // This spell is already in effect. + } + else if (!Caster.CanBeginAction()) + { + Caster.SendLocalizedMessage(1005385); // The spell will not adhere to you at this time. + } + else if (CheckSequence()) + { + if (Caster.BeginAction()) + { + double value = (int)(Caster.Skills.EvalInt.Value + + Caster.Skills.Meditation.Value + + Caster.Skills.Inscribe.Value); + value /= 4; + + Registry.Add(Caster, Math.Clamp(value, 0.0, 75.0)); + new InternalTimer(Caster).Start(); + + Caster.FixedParticles(0x375A, 9, 20, 5016, EffectLayer.Waist); + Caster.PlaySound(0x1ED); + } + else + { + Caster.SendLocalizedMessage(1005385); // The spell will not adhere to you at this time. + } + } + + FinishSequence(); + } + } + + private class InternalTimer : Timer + { + private readonly Mobile m_Caster; + + public InternalTimer(Mobile caster) : base(TimeSpan.FromSeconds(0)) + { + var val = Math.Clamp(caster.Skills.Magery.Value * 2.0, 15, 240); + + m_Caster = caster; + Delay = TimeSpan.FromSeconds(val); + Priority = TimerPriority.OneSecond; + } + + protected override void OnTick() + { + Registry.Remove(m_Caster); + DefensiveSpell.Nullify(m_Caster); + } + } } - - private class InternalTimer : Timer - { - private readonly Mobile m_Caster; - - public InternalTimer(Mobile caster) : base(TimeSpan.FromSeconds(0)) - { - double val = Math.Clamp(caster.Skills.Magery.Value * 2.0, 15, 240); - - m_Caster = caster; - Delay = TimeSpan.FromSeconds(val); - Priority = TimerPriority.OneSecond; - } - - protected override void OnTick() - { - Registry.Remove(m_Caster); - DefensiveSpell.Nullify(m_Caster); - } - } - } } diff --git a/Projects/UOContent/Spells/Second/RemoveTrap.cs b/Projects/UOContent/Spells/Second/RemoveTrap.cs index f99d2b47f..5423a405b 100644 --- a/Projects/UOContent/Spells/Second/RemoveTrap.cs +++ b/Projects/UOContent/Spells/Second/RemoveTrap.cs @@ -3,55 +3,64 @@ using Server.Targeting; namespace Server.Spells.Second { - public class RemoveTrapSpell : MagerySpell, ISpellTargetingItem - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Remove Trap", "An Jux", - 212, - 9001, - Reagent.Bloodmoss, - Reagent.SulfurousAsh); - - public RemoveTrapSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class RemoveTrapSpell : MagerySpell, ISpellTargetingItem { + private static readonly SpellInfo m_Info = new SpellInfo( + "Remove Trap", + "An Jux", + 212, + 9001, + Reagent.Bloodmoss, + Reagent.SulfurousAsh + ); + + public RemoveTrapSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.Second; + + public void Target(Item item) + { + if (!(item is TrappableContainer cont)) + { + Caster.SendMessage("You can't disarm that"); // TODO: Localization? + } + else if (!Caster.CanSee(item)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (cont.TrapType != TrapType.None && cont.TrapType != TrapType.MagicTrap) + { + DoFizzle(); + } + else if (CheckSequence()) + { + SpellHelper.Turn(Caster, item); + + var loc = item.GetWorldLocation(); + + Effects.SendLocationParticles( + EffectItem.Create(loc, item.Map, EffectItem.DefaultDuration), + 0x376A, + 9, + 32, + 5015 + ); + Effects.PlaySound(loc, item.Map, 0x1F0); + + cont.TrapType = TrapType.None; + cont.TrapPower = 0; + cont.TrapLevel = 0; + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetItem(this, TargetFlags.None, Core.ML ? 10 : 12); + Caster.SendMessage("What do you wish to untrap?"); // TODO: Localization? + } } - - public override SpellCircle Circle => SpellCircle.Second; - - public override void OnCast() - { - Caster.Target = new SpellTargetItem(this, TargetFlags.None, Core.ML ? 10 : 12); - Caster.SendMessage("What do you wish to untrap?"); // TODO: Localization? - } - - public void Target(Item item) - { - if (!(item is TrappableContainer cont)) - Caster.SendMessage("You can't disarm that"); // TODO: Localization? - else if (!Caster.CanSee(item)) - { - Caster.SendLocalizedMessage(500237); // Target can not be seen. - } - else if (cont.TrapType != TrapType.None && cont.TrapType != TrapType.MagicTrap) - { - DoFizzle(); - } - else if (CheckSequence()) - { - SpellHelper.Turn(Caster, item); - - Point3D loc = item.GetWorldLocation(); - - Effects.SendLocationParticles(EffectItem.Create(loc, item.Map, EffectItem.DefaultDuration), 0x376A, 9, 32, - 5015); - Effects.PlaySound(loc, item.Map, 0x1F0); - - cont.TrapType = TrapType.None; - cont.TrapPower = 0; - cont.TrapLevel = 0; - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Second/Strength.cs b/Projects/UOContent/Spells/Second/Strength.cs index ca2008ce0..7fc214868 100644 --- a/Projects/UOContent/Spells/Second/Strength.cs +++ b/Projects/UOContent/Spells/Second/Strength.cs @@ -1,63 +1,66 @@ -using System; using Server.Engines.ConPVP; using Server.Targeting; namespace Server.Spells.Second { - public class StrengthSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Strength", "Uus Mani", - 212, - 9061, - Reagent.MandrakeRoot, - Reagent.Nightshade); - - public StrengthSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class StrengthSpell : MagerySpell, ISpellTargetingMobile { + private static readonly SpellInfo m_Info = new SpellInfo( + "Strength", + "Uus Mani", + 212, + 9061, + Reagent.MandrakeRoot, + Reagent.Nightshade + ); + + public StrengthSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.Second; + + public void Target(Mobile m) + { + if (m == null) + return; + + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckBSequence(m)) + { + SpellHelper.Turn(Caster, m); + + SpellHelper.AddStatBonus(Caster, m, StatType.Str); + + m.FixedParticles(0x375A, 10, 15, 5017, EffectLayer.Waist); + m.PlaySound(0x1EE); + + var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, false) * 100); + var length = SpellHelper.GetDuration(Caster, m); + + BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Strength, 1075845, length, m, percentage.ToString())); + } + + FinishSequence(); + } + + public override bool CheckCast() + { + if (DuelContext.CheckSuddenDeath(Caster)) + { + Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); + return false; + } + + return base.CheckCast(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, Core.ML ? 10 : 12); + } } - - public override SpellCircle Circle => SpellCircle.Second; - - public override bool CheckCast() - { - if (DuelContext.CheckSuddenDeath(Caster)) - { - Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); - return false; - } - - return base.CheckCast(); - } - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (CheckBSequence(m)) - { - SpellHelper.Turn(Caster, m); - - SpellHelper.AddStatBonus(Caster, m, StatType.Str); - - m.FixedParticles(0x375A, 10, 15, 5017, EffectLayer.Waist); - m.PlaySound(0x1EE); - - int percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, false) * 100); - TimeSpan length = SpellHelper.GetDuration(Caster, m); - - BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Strength, 1075845, length, m, percentage.ToString())); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Seventh/ChainLightning.cs b/Projects/UOContent/Spells/Seventh/ChainLightning.cs index 0667496e1..c02489e32 100644 --- a/Projects/UOContent/Spells/Seventh/ChainLightning.cs +++ b/Projects/UOContent/Spells/Seventh/ChainLightning.cs @@ -4,107 +4,116 @@ using Server.Targeting; namespace Server.Spells.Seventh { - public class ChainLightningSpell : MagerySpell, ISpellTargetingPoint3D - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Chain Lightning", "Vas Ort Grav", - 209, - 9022, - false, - Reagent.BlackPearl, - Reagent.Bloodmoss, - Reagent.MandrakeRoot, - Reagent.SulfurousAsh); - - public ChainLightningSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class ChainLightningSpell : MagerySpell, ISpellTargetingPoint3D { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Chain Lightning", + "Vas Ort Grav", + 209, + 9022, + false, + Reagent.BlackPearl, + Reagent.Bloodmoss, + Reagent.MandrakeRoot, + Reagent.SulfurousAsh + ); - public override SpellCircle Circle => SpellCircle.Seventh; - - public override bool DelayedDamage => true; - - public override void OnCast() - { - Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); - } - - public void Target(IPoint3D p) - { - if (!Caster.CanSee(p)) - { - Caster.SendLocalizedMessage(500237); // Target can not be seen. - } - else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) - { - SpellHelper.Turn(Caster, p); - - if (p is Item item) - p = item.GetWorldLocation(); - - List targets = new List(); - - Map map = Caster.Map; - - bool playerVsPlayer = false; - - if (map != null) + public ChainLightningSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - IPooledEnumerable eable = map.GetMobilesInRange(new Point3D(p), 2); - - targets.AddRange(eable.Where(m => - { - if ((Core.AOS && (m == Caster || !Caster.InLOS(m))) || !SpellHelper.ValidIndirectTarget(Caster, m) || - !Caster.CanBeHarmful(m, false)) - return false; - - if (m.Player) - playerVsPlayer = true; - - return true; - }).ToList()); - - eable.Free(); } - double damage; + public override SpellCircle Circle => SpellCircle.Seventh; - damage = Core.AOS ? GetNewAosDamage(51, 1, 5, playerVsPlayer) - : Utility.Random(27, 22); + public override bool DelayedDamage => true; - if (targets.Count > 0) + public void Target(IPoint3D p) { - if (Core.AOS && targets.Count > 2) - damage = damage * 2 / targets.Count; - else if (!Core.AOS) - damage /= targets.Count; - - for (int i = 0; i < targets.Count; ++i) - { - double toDeal = damage; - Mobile m = targets[i]; - - if (!Core.AOS && CheckResisted(m)) + if (!Caster.CanSee(p)) { - toDeal *= 0.5; + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) + { + SpellHelper.Turn(Caster, p); - m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + if (p is Item item) + p = item.GetWorldLocation(); + + var targets = new List(); + + var map = Caster.Map; + + var playerVsPlayer = false; + + if (map != null) + { + var eable = map.GetMobilesInRange(new Point3D(p), 2); + + targets.AddRange( + eable.Where( + m => + { + if (Core.AOS && (m == Caster || !Caster.InLOS(m)) || + !SpellHelper.ValidIndirectTarget(Caster, m) || + !Caster.CanBeHarmful(m, false)) + return false; + + if (m.Player) + playerVsPlayer = true; + + return true; + } + ) + .ToList() + ); + + eable.Free(); + } + + double damage; + + damage = Core.AOS + ? GetNewAosDamage(51, 1, 5, playerVsPlayer) + : Utility.Random(27, 22); + + if (targets.Count > 0) + { + if (Core.AOS && targets.Count > 2) + damage = damage * 2 / targets.Count; + else if (!Core.AOS) + damage /= targets.Count; + + for (var i = 0; i < targets.Count; ++i) + { + var toDeal = damage; + var m = targets[i]; + + if (!Core.AOS && CheckResisted(m)) + { + toDeal *= 0.5; + + m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + } + + toDeal *= GetDamageScalar(m); + Caster.DoHarmful(m); + SpellHelper.Damage(this, m, toDeal, 0, 0, 0, 0, 100); + + m.BoltEffect(0); + } + } + else + { + Caster.PlaySound(0x29); + } } - toDeal *= GetDamageScalar(m); - Caster.DoHarmful(m); - SpellHelper.Damage(this, m, toDeal, 0, 0, 0, 0, 100); - - m.BoltEffect(0); - } + FinishSequence(); } - else + + public override void OnCast() { - Caster.PlaySound(0x29); + Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); } - } - - FinishSequence(); } - } } diff --git a/Projects/UOContent/Spells/Seventh/EnergyField.cs b/Projects/UOContent/Spells/Seventh/EnergyField.cs index 316461ee5..b8d125766 100644 --- a/Projects/UOContent/Spells/Seventh/EnergyField.cs +++ b/Projects/UOContent/Spells/Seventh/EnergyField.cs @@ -6,169 +6,178 @@ using Server.Targeting; namespace Server.Spells.Seventh { - public class EnergyFieldSpell : MagerySpell, ISpellTargetingPoint3D - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Energy Field", "In Sanct Grav", - 221, - 9022, - false, - Reagent.BlackPearl, - Reagent.MandrakeRoot, - Reagent.SpidersSilk, - Reagent.SulfurousAsh); - - public EnergyFieldSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class EnergyFieldSpell : MagerySpell, ISpellTargetingPoint3D { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Energy Field", + "In Sanct Grav", + 221, + 9022, + false, + Reagent.BlackPearl, + Reagent.MandrakeRoot, + Reagent.SpidersSilk, + Reagent.SulfurousAsh + ); - public override SpellCircle Circle => SpellCircle.Seventh; - - public override void OnCast() - { - Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); - } - - public void Target(IPoint3D p) - { - if (!Caster.CanSee(p)) - { - Caster.SendLocalizedMessage(500237); // Target can not be seen. - } - else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) - { - SpellHelper.Turn(Caster, p); - - SpellHelper.GetSurfaceTop(ref p); - - int dx = Caster.Location.X - p.X; - int dy = Caster.Location.Y - p.Y; - int rx = (dx - dy) * 44; - int ry = (dx + dy) * 44; - - bool eastToWest; - - if (rx >= 0 && ry >= 0) - eastToWest = false; - else if (rx >= 0) - eastToWest = true; - else if (ry >= 0) - eastToWest = true; - else - eastToWest = false; - - Effects.PlaySound(p, Caster.Map, 0x20B); - - TimeSpan duration; - - if (Core.AOS) - duration = TimeSpan.FromSeconds((15 + Caster.Skills.Magery.Fixed / 5) / 7.0); - else - duration = TimeSpan.FromSeconds(Caster.Skills.Magery.Value * 0.28 + - 2.0); // (28% of magery) + 2.0 seconds - - int itemID = eastToWest ? 0x3946 : 0x3956; - - for (int i = -2; i <= 2; ++i) + public EnergyFieldSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - Point3D loc = new Point3D(eastToWest ? p.X + i : p.X, eastToWest ? p.Y : p.Y + i, p.Z); - bool canFit = SpellHelper.AdjustField(ref loc, Caster.Map, 12, false); - - if (!canFit) - continue; - - Item item = new InternalItem(loc, Caster.Map, duration, itemID, Caster); - item.ProcessDelta(); - - Effects.SendLocationParticles(EffectItem.Create(loc, Caster.Map, EffectItem.DefaultDuration), 0x376A, 9, - 10, 5051); - } - } - - FinishSequence(); - } - - [DispellableField] - private class InternalItem : Item - { - private readonly Mobile m_Caster; - private readonly Timer m_Timer; - - public InternalItem(Point3D loc, Map map, TimeSpan duration, int itemID, Mobile caster) : base(itemID) - { - Visible = false; - Movable = false; - Light = LightType.Circle300; - - MoveToWorld(loc, map); - - m_Caster = caster; - - if (caster.InLOS(this)) - Visible = true; - else - Delete(); - - if (Deleted) - return; - - m_Timer = new InternalTimer(this, duration); - m_Timer.Start(); - } - - public InternalItem(Serial serial) : base(serial) - { - m_Timer = new InternalTimer(this, TimeSpan.FromSeconds(5.0)); - m_Timer.Start(); - } - - public override bool BlocksFit => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - } - - public override bool OnMoveOver(Mobile m) - { - if (!(m is PlayerMobile)) - return base.OnMoveOver(m); - - int noto = Notoriety.Compute(m_Caster, m); - return noto != Notoriety.Enemy && noto != Notoriety.Ally && base.OnMoveOver(m); - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Timer?.Stop(); - } - - private class InternalTimer : Timer - { - private readonly InternalItem m_Item; - - public InternalTimer(InternalItem item, TimeSpan duration) : base(duration) - { - Priority = TimerPriority.OneSecond; - m_Item = item; } - protected override void OnTick() + public override SpellCircle Circle => SpellCircle.Seventh; + + public void Target(IPoint3D p) { - m_Item.Delete(); + if (!Caster.CanSee(p)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) + { + SpellHelper.Turn(Caster, p); + + SpellHelper.GetSurfaceTop(ref p); + + var dx = Caster.Location.X - p.X; + var dy = Caster.Location.Y - p.Y; + var rx = (dx - dy) * 44; + var ry = (dx + dy) * 44; + + bool eastToWest; + + if (rx >= 0 && ry >= 0) + eastToWest = false; + else if (rx >= 0) + eastToWest = true; + else if (ry >= 0) + eastToWest = true; + else + eastToWest = false; + + Effects.PlaySound(p, Caster.Map, 0x20B); + + TimeSpan duration; + + if (Core.AOS) + duration = TimeSpan.FromSeconds((15 + Caster.Skills.Magery.Fixed / 5) / 7.0); + else + duration = TimeSpan.FromSeconds( + Caster.Skills.Magery.Value * 0.28 + + 2.0 + ); // (28% of magery) + 2.0 seconds + + var itemID = eastToWest ? 0x3946 : 0x3956; + + for (var i = -2; i <= 2; ++i) + { + var loc = new Point3D(eastToWest ? p.X + i : p.X, eastToWest ? p.Y : p.Y + i, p.Z); + var canFit = SpellHelper.AdjustField(ref loc, Caster.Map, 12, false); + + if (!canFit) + continue; + + Item item = new InternalItem(loc, Caster.Map, duration, itemID, Caster); + item.ProcessDelta(); + + Effects.SendLocationParticles( + EffectItem.Create(loc, Caster.Map, EffectItem.DefaultDuration), + 0x376A, + 9, + 10, + 5051 + ); + } + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); + } + + [DispellableField] + private class InternalItem : Item + { + private readonly Mobile m_Caster; + private readonly Timer m_Timer; + + public InternalItem(Point3D loc, Map map, TimeSpan duration, int itemID, Mobile caster) : base(itemID) + { + Visible = false; + Movable = false; + Light = LightType.Circle300; + + MoveToWorld(loc, map); + + m_Caster = caster; + + if (caster.InLOS(this)) + Visible = true; + else + Delete(); + + if (Deleted) + return; + + m_Timer = new InternalTimer(this, duration); + m_Timer.Start(); + } + + public InternalItem(Serial serial) : base(serial) + { + m_Timer = new InternalTimer(this, TimeSpan.FromSeconds(5.0)); + m_Timer.Start(); + } + + public override bool BlocksFit => true; + + 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 OnMoveOver(Mobile m) + { + if (!(m is PlayerMobile)) + return base.OnMoveOver(m); + + var noto = Notoriety.Compute(m_Caster, m); + return noto != Notoriety.Enemy && noto != Notoriety.Ally && base.OnMoveOver(m); + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Timer?.Stop(); + } + + private class InternalTimer : Timer + { + private readonly InternalItem m_Item; + + public InternalTimer(InternalItem item, TimeSpan duration) : base(duration) + { + Priority = TimerPriority.OneSecond; + m_Item = item; + } + + protected override void OnTick() + { + m_Item.Delete(); + } + } } - } } - } } diff --git a/Projects/UOContent/Spells/Seventh/FlameStrike.cs b/Projects/UOContent/Spells/Seventh/FlameStrike.cs index a3bae71e1..11fc91a4f 100644 --- a/Projects/UOContent/Spells/Seventh/FlameStrike.cs +++ b/Projects/UOContent/Spells/Seventh/FlameStrike.cs @@ -2,68 +2,72 @@ using Server.Targeting; namespace Server.Spells.Seventh { - public class FlameStrikeSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Flame Strike", "Kal Vas Flam", - 245, - 9042, - Reagent.SpidersSilk, - Reagent.SulfurousAsh); - - public FlameStrikeSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class FlameStrikeSpell : MagerySpell, ISpellTargetingMobile { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Flame Strike", + "Kal Vas Flam", + 245, + 9042, + Reagent.SpidersSilk, + Reagent.SulfurousAsh + ); - public override SpellCircle Circle => SpellCircle.Seventh; - - public override bool DelayedDamage => true; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (CheckHSequence(m)) - { - SpellHelper.Turn(Caster, m); - - SpellHelper.CheckReflect((int)Circle, Caster, ref m); - - double damage; - - if (Core.AOS) + public FlameStrikeSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - damage = GetNewAosDamage(48, 1, 5, m); - } - else - { - damage = Utility.Random(27, 22); - - if (CheckResisted(m)) - { - damage *= 0.6; - - m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. - } - - damage *= GetDamageScalar(m); } - m.FixedParticles(0x3709, 10, 30, 5052, EffectLayer.LeftFoot); - m.PlaySound(0x208); + public override SpellCircle Circle => SpellCircle.Seventh; - SpellHelper.Damage(this, m, damage, 0, 100, 0, 0, 0); - } + public override bool DelayedDamage => true; - FinishSequence(); + public void Target(Mobile m) + { + if (m == null) + return; + + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckHSequence(m)) + { + SpellHelper.Turn(Caster, m); + + SpellHelper.CheckReflect((int)Circle, Caster, ref m); + + double damage; + + if (Core.AOS) + { + damage = GetNewAosDamage(48, 1, 5, m); + } + else + { + damage = Utility.Random(27, 22); + + if (CheckResisted(m)) + { + damage *= 0.6; + + m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + } + + damage *= GetDamageScalar(m); + } + + m.FixedParticles(0x3709, 10, 30, 5052, EffectLayer.LeftFoot); + m.PlaySound(0x208); + + SpellHelper.Damage(this, m, damage, 0, 100, 0, 0, 0); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } } - } } diff --git a/Projects/UOContent/Spells/Seventh/GateTravel.cs b/Projects/UOContent/Spells/Seventh/GateTravel.cs index 3a0bb88ae..fae1de72f 100644 --- a/Projects/UOContent/Spells/Seventh/GateTravel.cs +++ b/Projects/UOContent/Spells/Seventh/GateTravel.cs @@ -7,173 +7,177 @@ using Server.Mobiles; namespace Server.Spells.Seventh { - public class GateTravelSpell : MagerySpell, IRecallSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Gate Travel", "Vas Rel Por", - 263, - 9032, - Reagent.BlackPearl, - Reagent.MandrakeRoot, - Reagent.SulfurousAsh); - - private readonly RunebookEntry m_Entry; - - public GateTravelSpell(Mobile caster, RunebookEntry entry = null, Item scroll = null) : base(caster, scroll, m_Info) => m_Entry = entry; - - public override SpellCircle Circle => SpellCircle.Seventh; - - public override void OnCast() + public class GateTravelSpell : MagerySpell, IRecallSpell { - if (m_Entry == null) - Caster.Target = new RecallSpellTarget(this, false); - else - Effect(m_Entry.Location, m_Entry.Map, true); - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Gate Travel", + "Vas Rel Por", + 263, + 9032, + Reagent.BlackPearl, + Reagent.MandrakeRoot, + Reagent.SulfurousAsh + ); - public override bool CheckCast() - { - if (Sigil.ExistsOn(Caster)) - { - Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. - return false; - } + private readonly RunebookEntry m_Entry; - if (Caster.Criminal) - { - Caster.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily. - return false; - } + public GateTravelSpell(Mobile caster, RunebookEntry entry = null, Item scroll = null) : + base(caster, scroll, m_Info) => m_Entry = entry; - if (SpellHelper.CheckCombat(Caster)) - { - Caster.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle?? - return false; - } + public override SpellCircle Circle => SpellCircle.Seventh; - return SpellHelper.CheckTravel(Caster, TravelCheckType.GateFrom); - } - - private bool GateExistsAt(Map map, Point3D loc) - { - IPooledEnumerable eable = map.GetItemsInRange(loc, 0); - bool gateFound = eable.Any(item => item is Moongate || item is PublicMoongate); - eable.Free(); - - return gateFound; - } - - public void Effect(Point3D loc, Map map, bool checkMulti) - { - if (Sigil.ExistsOn(Caster)) - { - Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. - } - else if (map == null || (!Core.AOS && Caster.Map != map)) - { - Caster.SendLocalizedMessage(1005570); // You can not gate to another facet. - } - else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.GateFrom)) - { - } - else if (!SpellHelper.CheckTravel(Caster, map, loc, TravelCheckType.GateTo)) - { - } - else if (map == Map.Felucca && Caster is PlayerMobile mobile && mobile.Young) - { - mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young. - } - else if (Caster.Kills >= 5 && map != Map.Felucca) - { - Caster.SendLocalizedMessage(1019004); // You are not allowed to travel there. - } - else if (Caster.Criminal) - { - Caster.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily. - } - else if (SpellHelper.CheckCombat(Caster)) - { - Caster.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle?? - } - else if (!map.CanSpawnMobile(loc.X, loc.Y, loc.Z)) - { - Caster.SendLocalizedMessage(501942); // That location is blocked. - } - else if (checkMulti && SpellHelper.CheckMulti(loc, map)) - { - Caster.SendLocalizedMessage(501942); // That location is blocked. - } - else if (Core.SE && (GateExistsAt(map, loc) || GateExistsAt(Caster.Map, Caster.Location))) // SE restricted stacking gates - { - Caster.SendLocalizedMessage(1071242); // There is already a gate there. - } - else if (CheckSequence()) - { - Caster.SendLocalizedMessage(501024); // You open a magical gate to another location - - Effects.PlaySound(Caster.Location, Caster.Map, 0x20E); - - InternalItem firstGate = new InternalItem(loc, map); - firstGate.MoveToWorld(Caster.Location, Caster.Map); - - Effects.PlaySound(loc, map, 0x20E); - - InternalItem secondGate = new InternalItem(Caster.Location, Caster.Map); - secondGate.MoveToWorld(loc, map); - } - - FinishSequence(); - } - - [DispellableField] - private class InternalItem : Moongate - { - public InternalItem(Point3D target, Map map) : base(target, map) - { - Map = map; - - if (ShowFeluccaWarning && map == Map.Felucca) - ItemID = 0xDDA; - - Dispellable = true; - - InternalTimer t = new InternalTimer(this); - t.Start(); - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public override bool ShowFeluccaWarning => Core.AOS; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - Delete(); - } - - private class InternalTimer : Timer - { - private readonly Item m_Item; - - public InternalTimer(Item item) : base(TimeSpan.FromSeconds(30.0)) + public void Effect(Point3D loc, Map map, bool checkMulti) { - Priority = TimerPriority.OneSecond; - m_Item = item; + if (Sigil.ExistsOn(Caster)) + { + Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. + } + else if (map == null || !Core.AOS && Caster.Map != map) + { + Caster.SendLocalizedMessage(1005570); // You can not gate to another facet. + } + else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.GateFrom)) + { + } + else if (!SpellHelper.CheckTravel(Caster, map, loc, TravelCheckType.GateTo)) + { + } + else if (map == Map.Felucca && Caster is PlayerMobile mobile && mobile.Young) + { + mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young. + } + else if (Caster.Kills >= 5 && map != Map.Felucca) + { + Caster.SendLocalizedMessage(1019004); // You are not allowed to travel there. + } + else if (Caster.Criminal) + { + Caster.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily. + } + else if (SpellHelper.CheckCombat(Caster)) + { + Caster.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle?? + } + else if (!map.CanSpawnMobile(loc.X, loc.Y, loc.Z)) + { + Caster.SendLocalizedMessage(501942); // That location is blocked. + } + else if (checkMulti && SpellHelper.CheckMulti(loc, map)) + { + Caster.SendLocalizedMessage(501942); // That location is blocked. + } + else if (Core.SE && (GateExistsAt(map, loc) || GateExistsAt(Caster.Map, Caster.Location)) + ) // SE restricted stacking gates + { + Caster.SendLocalizedMessage(1071242); // There is already a gate there. + } + else if (CheckSequence()) + { + Caster.SendLocalizedMessage(501024); // You open a magical gate to another location + + Effects.PlaySound(Caster.Location, Caster.Map, 0x20E); + + var firstGate = new InternalItem(loc, map); + firstGate.MoveToWorld(Caster.Location, Caster.Map); + + Effects.PlaySound(loc, map, 0x20E); + + var secondGate = new InternalItem(Caster.Location, Caster.Map); + secondGate.MoveToWorld(loc, map); + } + + FinishSequence(); } - protected override void OnTick() + public override void OnCast() { - m_Item.Delete(); + if (m_Entry == null) + Caster.Target = new RecallSpellTarget(this, false); + else + Effect(m_Entry.Location, m_Entry.Map, true); + } + + public override bool CheckCast() + { + if (Sigil.ExistsOn(Caster)) + { + Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. + return false; + } + + if (Caster.Criminal) + { + Caster.SendLocalizedMessage(1005561, "", 0x22); // Thou'rt a criminal and cannot escape so easily. + return false; + } + + if (SpellHelper.CheckCombat(Caster)) + { + Caster.SendLocalizedMessage(1005564, "", 0x22); // Wouldst thou flee during the heat of battle?? + return false; + } + + return SpellHelper.CheckTravel(Caster, TravelCheckType.GateFrom); + } + + private bool GateExistsAt(Map map, Point3D loc) + { + var eable = map.GetItemsInRange(loc, 0); + var gateFound = eable.Any(item => item is Moongate || item is PublicMoongate); + eable.Free(); + + return gateFound; + } + + [DispellableField] + private class InternalItem : Moongate + { + public InternalItem(Point3D target, Map map) : base(target, map) + { + Map = map; + + if (ShowFeluccaWarning && map == Map.Felucca) + ItemID = 0xDDA; + + Dispellable = true; + + var t = new InternalTimer(this); + t.Start(); + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override bool ShowFeluccaWarning => Core.AOS; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + Delete(); + } + + private class InternalTimer : Timer + { + private readonly Item m_Item; + + public InternalTimer(Item item) : base(TimeSpan.FromSeconds(30.0)) + { + Priority = TimerPriority.OneSecond; + m_Item = item; + } + + protected override void OnTick() + { + m_Item.Delete(); + } + } } - } } - } } diff --git a/Projects/UOContent/Spells/Seventh/ManaVampire.cs b/Projects/UOContent/Spells/Seventh/ManaVampire.cs index 1beae52f0..cc3354bf8 100644 --- a/Projects/UOContent/Spells/Seventh/ManaVampire.cs +++ b/Projects/UOContent/Spells/Seventh/ManaVampire.cs @@ -3,84 +3,88 @@ using Server.Targeting; namespace Server.Spells.Seventh { - public class ManaVampireSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Mana Vampire", "Ort Sanct", - 221, - 9032, - Reagent.BlackPearl, - Reagent.Bloodmoss, - Reagent.MandrakeRoot, - Reagent.SpidersSilk); - - public ManaVampireSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class ManaVampireSpell : MagerySpell, ISpellTargetingMobile { + private static readonly SpellInfo m_Info = new SpellInfo( + "Mana Vampire", + "Ort Sanct", + 221, + 9032, + Reagent.BlackPearl, + Reagent.Bloodmoss, + Reagent.MandrakeRoot, + Reagent.SpidersSilk + ); + + public ManaVampireSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.Seventh; + + public void Target(Mobile m) + { + if (m == null) + return; + + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckHSequence(m)) + { + SpellHelper.Turn(Caster, m); + + SpellHelper.CheckReflect((int)Circle, Caster, ref m); + + m.Spell?.OnCasterHurt(); + + m.Paralyzed = false; + + var toDrain = 0; + + if (Core.AOS) + { + toDrain = (int)(GetDamageSkill(Caster) - GetResistSkill(m)); + + if (!m.Player) + toDrain /= 2; + } + else + { + if (CheckResisted(m)) + m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + else + toDrain = m.Mana; + } + + m.Mana -= Math.Clamp(toDrain, 0, Math.Min(m.Mana, Caster.ManaMax - Caster.Mana)); + Caster.Mana += toDrain; + + if (Core.AOS) + { + m.FixedParticles(0x374A, 1, 15, 5054, 23, 7, EffectLayer.Head); + m.PlaySound(0x1F9); + + Caster.FixedParticles(0x0000, 10, 5, 2054, EffectLayer.Head); + } + else + { + m.FixedParticles(0x374A, 10, 15, 5054, EffectLayer.Head); + m.PlaySound(0x1F9); + } + + HarmfulSpell(m); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } + + public override double GetResistPercent(Mobile target) => 98.0; } - - public override SpellCircle Circle => SpellCircle.Seventh; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (CheckHSequence(m)) - { - SpellHelper.Turn(Caster, m); - - SpellHelper.CheckReflect((int)Circle, Caster, ref m); - - m.Spell?.OnCasterHurt(); - - m.Paralyzed = false; - - int toDrain = 0; - - if (Core.AOS) - { - toDrain = (int)(GetDamageSkill(Caster) - GetResistSkill(m)); - - if (!m.Player) - toDrain /= 2; - } - else - { - if (CheckResisted(m)) - m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. - else - toDrain = m.Mana; - } - - m.Mana -= Math.Clamp(toDrain, 0, Math.Min(m.Mana, Caster.ManaMax - Caster.Mana)); - Caster.Mana += toDrain; - - if (Core.AOS) - { - m.FixedParticles(0x374A, 1, 15, 5054, 23, 7, EffectLayer.Head); - m.PlaySound(0x1F9); - - Caster.FixedParticles(0x0000, 10, 5, 2054, EffectLayer.Head); - } - else - { - m.FixedParticles(0x374A, 10, 15, 5054, EffectLayer.Head); - m.PlaySound(0x1F9); - } - - HarmfulSpell(m); - } - - FinishSequence(); - } - - public override double GetResistPercent(Mobile target) => 98.0; - } } diff --git a/Projects/UOContent/Spells/Seventh/MassDispel.cs b/Projects/UOContent/Spells/Seventh/MassDispel.cs index dbf9b15bd..be02b6aea 100644 --- a/Projects/UOContent/Spells/Seventh/MassDispel.cs +++ b/Projects/UOContent/Spells/Seventh/MassDispel.cs @@ -4,75 +4,82 @@ using Server.Targeting; namespace Server.Spells.Seventh { - public class MassDispelSpell : MagerySpell, ISpellTargetingPoint3D - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Mass Dispel", "Vas An Ort", - 263, - 9002, - Reagent.Garlic, - Reagent.MandrakeRoot, - Reagent.BlackPearl, - Reagent.SulfurousAsh); - - public MassDispelSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class MassDispelSpell : MagerySpell, ISpellTargetingPoint3D { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Mass Dispel", + "Vas An Ort", + 263, + 9002, + Reagent.Garlic, + Reagent.MandrakeRoot, + Reagent.BlackPearl, + Reagent.SulfurousAsh + ); - public override SpellCircle Circle => SpellCircle.Seventh; - - public override void OnCast() - { - Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); - } - - public void Target(IPoint3D p) - { - if (!Caster.CanSee(p)) - { - Caster.SendLocalizedMessage(500237); // Target can not be seen. - } - else if (CheckSequence()) - { - SpellHelper.Turn(Caster, p); - - SpellHelper.GetSurfaceTop(ref p); - - Map map = Caster.Map; - - if (map != null) + public MassDispelSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - IPooledEnumerable eable = map.GetMobilesInRange(new Point3D(p), 8); - - foreach (BaseCreature bc in eable) - { - if (!(bc.IsDispellable && Caster.CanBeHarmful(bc, false))) - continue; - - double dispelChance = - (50.0 + 100 * (Caster.Skills.Magery.Value - bc.DispelDifficulty) / (bc.DispelFocus * 2)) / 100; - - if (dispelChance > Utility.RandomDouble()) - { - Effects.SendLocationParticles(EffectItem.Create(bc.Location, bc.Map, EffectItem.DefaultDuration), - 0x3728, 8, 20, 5042); - Effects.PlaySound(bc, bc.Map, 0x201); - - bc.Delete(); - } - else - { - Caster.DoHarmful(bc); - - bc.FixedEffect(0x3779, 10, 20); - } - } - - eable.Free(); } - } - FinishSequence(); + public override SpellCircle Circle => SpellCircle.Seventh; + + public void Target(IPoint3D p) + { + if (!Caster.CanSee(p)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckSequence()) + { + SpellHelper.Turn(Caster, p); + + SpellHelper.GetSurfaceTop(ref p); + + var map = Caster.Map; + + if (map != null) + { + var eable = map.GetMobilesInRange(new Point3D(p), 8); + + foreach (var bc in eable) + { + if (!(bc.IsDispellable && Caster.CanBeHarmful(bc, false))) + continue; + + var dispelChance = + (50.0 + 100 * (Caster.Skills.Magery.Value - bc.DispelDifficulty) / (bc.DispelFocus * 2)) / 100; + + if (dispelChance > Utility.RandomDouble()) + { + Effects.SendLocationParticles( + EffectItem.Create(bc.Location, bc.Map, EffectItem.DefaultDuration), + 0x3728, + 8, + 20, + 5042 + ); + Effects.PlaySound(bc, bc.Map, 0x201); + + bc.Delete(); + } + else + { + Caster.DoHarmful(bc); + + bc.FixedEffect(0x3779, 10, 20); + } + } + + eable.Free(); + } + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); + } } - } } diff --git a/Projects/UOContent/Spells/Seventh/MeteorSwarm.cs b/Projects/UOContent/Spells/Seventh/MeteorSwarm.cs index 9ba4d9637..d818e3e5a 100644 --- a/Projects/UOContent/Spells/Seventh/MeteorSwarm.cs +++ b/Projects/UOContent/Spells/Seventh/MeteorSwarm.cs @@ -4,110 +4,117 @@ using Server.Targeting; namespace Server.Spells.Seventh { - public class MeteorSwarmSpell : MagerySpell, ISpellTargetingPoint3D - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Meteor Swarm", "Flam Kal Des Ylem", - 233, - 9042, - false, - Reagent.Bloodmoss, - Reagent.MandrakeRoot, - Reagent.SulfurousAsh, - Reagent.SpidersSilk); - - public MeteorSwarmSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class MeteorSwarmSpell : MagerySpell, ISpellTargetingPoint3D { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Meteor Swarm", + "Flam Kal Des Ylem", + 233, + 9042, + false, + Reagent.Bloodmoss, + Reagent.MandrakeRoot, + Reagent.SulfurousAsh, + Reagent.SpidersSilk + ); - public override SpellCircle Circle => SpellCircle.Seventh; - - public override bool DelayedDamage => true; - - public override void OnCast() - { - Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); - } - - public void Target(IPoint3D p) - { - if (!Caster.CanSee(p)) - { - Caster.SendLocalizedMessage(500237); // Target can not be seen. - } - else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) - { - SpellHelper.Turn(Caster, p); - - if (p is Item item) - p = item.GetWorldLocation(); - - List targets; - - Map map = Caster.Map; - - bool playerVsPlayer = false; - - if (map != null) + public MeteorSwarmSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - IPooledEnumerable eable = map.GetMobilesInRange(new Point3D(p), 2); - - targets = eable.Where(m => - { - if (Caster == m || !SpellHelper.ValidIndirectTarget(Caster, m) || !Caster.CanBeHarmful(m, false) || - (Core.AOS && !Caster.InLOS(m))) - return false; - - if (m.Player) - playerVsPlayer = true; - - return true; - }).ToList(); - - eable.Free(); - } - else - { - targets = new List(); } - double damage; + public override SpellCircle Circle => SpellCircle.Seventh; - damage = Core.AOS ? GetNewAosDamage(51, 1, 5, playerVsPlayer) - : Utility.Random(27, 22); + public override bool DelayedDamage => true; - if (targets.Count > 0) + public void Target(IPoint3D p) { - Effects.PlaySound(p, Caster.Map, 0x160); - - if (Core.AOS && targets.Count > 2) - damage = damage * 2 / targets.Count; - else if (!Core.AOS) - damage /= targets.Count; - - for (int i = 0; i < targets.Count; ++i) - { - Mobile m = targets[i]; - - double toDeal = damage; - - if (!Core.AOS && CheckResisted(m)) + if (!Caster.CanSee(p)) { - damage *= 0.5; + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) + { + SpellHelper.Turn(Caster, p); - m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + if (p is Item item) + p = item.GetWorldLocation(); + + List targets; + + var map = Caster.Map; + + var playerVsPlayer = false; + + if (map != null) + { + var eable = map.GetMobilesInRange(new Point3D(p), 2); + + targets = eable.Where( + m => + { + if (Caster == m || !SpellHelper.ValidIndirectTarget(Caster, m) || + !Caster.CanBeHarmful(m, false) || + Core.AOS && !Caster.InLOS(m)) + return false; + + if (m.Player) + playerVsPlayer = true; + + return true; + } + ) + .ToList(); + + eable.Free(); + } + else + { + targets = new List(); + } + + double damage; + + damage = Core.AOS + ? GetNewAosDamage(51, 1, 5, playerVsPlayer) + : Utility.Random(27, 22); + + if (targets.Count > 0) + { + Effects.PlaySound(p, Caster.Map, 0x160); + + if (Core.AOS && targets.Count > 2) + damage = damage * 2 / targets.Count; + else if (!Core.AOS) + damage /= targets.Count; + + for (var i = 0; i < targets.Count; ++i) + { + var m = targets[i]; + + var toDeal = damage; + + if (!Core.AOS && CheckResisted(m)) + { + damage *= 0.5; + + m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + } + + toDeal *= GetDamageScalar(m); + Caster.DoHarmful(m); + SpellHelper.Damage(this, m, toDeal, 0, 100, 0, 0, 0); + + Caster.MovingParticles(m, 0x36D4, 7, 0, false, true, 9501, 1, 0, 0x100); + } + } } - toDeal *= GetDamageScalar(m); - Caster.DoHarmful(m); - SpellHelper.Damage(this, m, toDeal, 0, 100, 0, 0, 0); - - Caster.MovingParticles(m, 0x36D4, 7, 0, false, true, 9501, 1, 0, 0x100); - } + FinishSequence(); } - } - FinishSequence(); + public override void OnCast() + { + Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); + } } - } } diff --git a/Projects/UOContent/Spells/Seventh/Polymorph.cs b/Projects/UOContent/Spells/Seventh/Polymorph.cs index 05990123e..5a9f2b9f5 100644 --- a/Projects/UOContent/Spells/Seventh/Polymorph.cs +++ b/Projects/UOContent/Spells/Seventh/Polymorph.cs @@ -3,203 +3,204 @@ using System.Collections.Generic; using Server.Factions; using Server.Gumps; using Server.Items; -using Server.Mobiles; using Server.Spells.Fifth; namespace Server.Spells.Seventh { - public class PolymorphSpell : MagerySpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Polymorph", "Vas Ylem Rel", - 221, - 9002, - Reagent.Bloodmoss, - Reagent.SpidersSilk, - Reagent.MandrakeRoot); - - private static readonly Dictionary m_Timers = new Dictionary(); - - private readonly int m_NewBody; - - public PolymorphSpell(Mobile caster, Item scroll, int body = 0) : base(caster, scroll, m_Info) => m_NewBody = body; - - public override SpellCircle Circle => SpellCircle.Seventh; - - public override bool CheckCast() + public class PolymorphSpell : MagerySpell { - /*if (Caster.Mounted) - { - Caster.SendLocalizedMessage( 1042561 ); //Please dismount first. - return false; - } - else */ - if (Sigil.ExistsOn(Caster)) - { - Caster.SendLocalizedMessage(1010521); // You cannot polymorph while you have a Town Sigil - return false; - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Polymorph", + "Vas Ylem Rel", + 221, + 9002, + Reagent.Bloodmoss, + Reagent.SpidersSilk, + Reagent.MandrakeRoot + ); - if (TransformationSpellHelper.UnderTransformation(Caster)) - { - Caster.SendLocalizedMessage(1061633); // You cannot polymorph while in that form. - return false; - } + private static readonly Dictionary m_Timers = new Dictionary(); - if (DisguiseTimers.IsDisguised(Caster)) - { - Caster.SendLocalizedMessage(502167); // You cannot polymorph while disguised. - return false; - } + private readonly int m_NewBody; - if (Caster.BodyMod == 183 || Caster.BodyMod == 184) - { - Caster.SendLocalizedMessage(1042512); // You cannot polymorph while wearing body paint - return false; - } + public PolymorphSpell(Mobile caster, Item scroll, int body = 0) : base(caster, scroll, m_Info) => m_NewBody = body; - if (!Caster.CanBeginAction()) - { - if (Core.ML) - EndPolymorph(Caster); - else - Caster.SendLocalizedMessage(1005559); // This spell is already in effect. - return false; - } + public override SpellCircle Circle => SpellCircle.Seventh; - if (m_NewBody == 0) - { - Gump gump = Core.SE ? (Gump)new NewPolymorphGump(Caster, Scroll) : new PolymorphGump(Caster, Scroll); - - Caster.SendGump(gump); - return false; - } - - return true; - } - - public override void OnCast() - { - /*if (Caster.Mounted) - { - Caster.SendLocalizedMessage( 1042561 ); //Please dismount first. - } - else */ - if (Sigil.ExistsOn(Caster)) - { - Caster.SendLocalizedMessage(1010521); // You cannot polymorph while you have a Town Sigil - } - else if (!Caster.CanBeginAction()) - { - if (Core.ML) - EndPolymorph(Caster); - else - Caster.SendLocalizedMessage(1005559); // This spell is already in effect. - } - else if (TransformationSpellHelper.UnderTransformation(Caster)) - { - Caster.SendLocalizedMessage(1061633); // You cannot polymorph while in that form. - } - else if (DisguiseTimers.IsDisguised(Caster)) - { - Caster.SendLocalizedMessage(502167); // You cannot polymorph while disguised. - } - else if (Caster.BodyMod == 183 || Caster.BodyMod == 184) - { - Caster.SendLocalizedMessage(1042512); // You cannot polymorph while wearing body paint - } - else if (!Caster.CanBeginAction() || Caster.IsBodyMod) - { - DoFizzle(); - } - else if (CheckSequence()) - { - if (Caster.BeginAction()) + public override bool CheckCast() { - if (m_NewBody != 0) - { - if (!((Body)m_NewBody).IsHuman) + /*if (Caster.Mounted) { - IMount mt = Caster.Mount; - - if (mt != null) - mt.Rider = null; + Caster.SendLocalizedMessage( 1042561 ); //Please dismount first. + return false; + } + else */ + if (Sigil.ExistsOn(Caster)) + { + Caster.SendLocalizedMessage(1010521); // You cannot polymorph while you have a Town Sigil + return false; } - Caster.BodyMod = m_NewBody; - - if (m_NewBody == 400 || m_NewBody == 401) - Caster.HueMod = Caster.Race.RandomSkinHue(); - else - Caster.HueMod = 0; - - BaseArmor.ValidateMobile(Caster); - BaseClothing.ValidateMobile(Caster); - - if (!Core.ML) + if (TransformationSpellHelper.UnderTransformation(Caster)) { - StopTimer(Caster); - - InternalTimer timer = new InternalTimer(Caster); - - m_Timers[Caster] = timer; - - timer.Start(); + Caster.SendLocalizedMessage(1061633); // You cannot polymorph while in that form. + return false; } - } + + if (DisguiseTimers.IsDisguised(Caster)) + { + Caster.SendLocalizedMessage(502167); // You cannot polymorph while disguised. + return false; + } + + if (Caster.BodyMod == 183 || Caster.BodyMod == 184) + { + Caster.SendLocalizedMessage(1042512); // You cannot polymorph while wearing body paint + return false; + } + + if (!Caster.CanBeginAction()) + { + if (Core.ML) + EndPolymorph(Caster); + else + Caster.SendLocalizedMessage(1005559); // This spell is already in effect. + return false; + } + + if (m_NewBody == 0) + { + var gump = Core.SE ? (Gump)new NewPolymorphGump(Caster, Scroll) : new PolymorphGump(Caster, Scroll); + + Caster.SendGump(gump); + return false; + } + + return true; } - else + + public override void OnCast() { - Caster.SendLocalizedMessage(1005559); // This spell is already in effect. + /*if (Caster.Mounted) + { + Caster.SendLocalizedMessage( 1042561 ); //Please dismount first. + } + else */ + if (Sigil.ExistsOn(Caster)) + { + Caster.SendLocalizedMessage(1010521); // You cannot polymorph while you have a Town Sigil + } + else if (!Caster.CanBeginAction()) + { + if (Core.ML) + EndPolymorph(Caster); + else + Caster.SendLocalizedMessage(1005559); // This spell is already in effect. + } + else if (TransformationSpellHelper.UnderTransformation(Caster)) + { + Caster.SendLocalizedMessage(1061633); // You cannot polymorph while in that form. + } + else if (DisguiseTimers.IsDisguised(Caster)) + { + Caster.SendLocalizedMessage(502167); // You cannot polymorph while disguised. + } + else if (Caster.BodyMod == 183 || Caster.BodyMod == 184) + { + Caster.SendLocalizedMessage(1042512); // You cannot polymorph while wearing body paint + } + else if (!Caster.CanBeginAction() || Caster.IsBodyMod) + { + DoFizzle(); + } + else if (CheckSequence()) + { + if (Caster.BeginAction()) + { + if (m_NewBody != 0) + { + if (!((Body)m_NewBody).IsHuman) + { + var mt = Caster.Mount; + + if (mt != null) + mt.Rider = null; + } + + Caster.BodyMod = m_NewBody; + + if (m_NewBody == 400 || m_NewBody == 401) + Caster.HueMod = Caster.Race.RandomSkinHue(); + else + Caster.HueMod = 0; + + BaseArmor.ValidateMobile(Caster); + BaseClothing.ValidateMobile(Caster); + + if (!Core.ML) + { + StopTimer(Caster); + + var timer = new InternalTimer(Caster); + + m_Timers[Caster] = timer; + + timer.Start(); + } + } + } + else + { + Caster.SendLocalizedMessage(1005559); // This spell is already in effect. + } + } + + FinishSequence(); } - } - FinishSequence(); + public static void StopTimer(Mobile m) + { + if (!m_Timers.TryGetValue(m, out var timer)) + return; + + timer?.Stop(); + m_Timers.Remove(m); + } + + private static void EndPolymorph(Mobile m) + { + if (m.CanBeginAction()) + return; + + m.BodyMod = 0; + m.HueMod = -1; + m.EndAction(); + + BaseArmor.ValidateMobile(m); + BaseClothing.ValidateMobile(m); + } + + private class InternalTimer : Timer + { + private readonly Mobile m_Owner; + + public InternalTimer(Mobile owner) : base(TimeSpan.FromSeconds(0)) + { + m_Owner = owner; + + var val = (int)owner.Skills.Magery.Value; + + if (val > 120) + val = 120; + + Delay = TimeSpan.FromSeconds(val); + Priority = TimerPriority.OneSecond; + } + + protected override void OnTick() + { + EndPolymorph(m_Owner); + } + } } - - public static void StopTimer(Mobile m) - { - if (!m_Timers.TryGetValue(m, out InternalTimer timer)) - return; - - timer?.Stop(); - m_Timers.Remove(m); - } - - private static void EndPolymorph(Mobile m) - { - if (m.CanBeginAction()) - return; - - m.BodyMod = 0; - m.HueMod = -1; - m.EndAction(); - - BaseArmor.ValidateMobile(m); - BaseClothing.ValidateMobile(m); - } - - private class InternalTimer : Timer - { - private readonly Mobile m_Owner; - - public InternalTimer(Mobile owner) : base(TimeSpan.FromSeconds(0)) - { - m_Owner = owner; - - int val = (int)owner.Skills.Magery.Value; - - if (val > 120) - val = 120; - - Delay = TimeSpan.FromSeconds(val); - Priority = TimerPriority.OneSecond; - } - - protected override void OnTick() - { - EndPolymorph(m_Owner); - } - } - } } diff --git a/Projects/UOContent/Spells/Sixth/Dispel.cs b/Projects/UOContent/Spells/Sixth/Dispel.cs index 5ef612590..1ec56b4fb 100644 --- a/Projects/UOContent/Spells/Sixth/Dispel.cs +++ b/Projects/UOContent/Spells/Sixth/Dispel.cs @@ -4,59 +4,70 @@ using Server.Targeting; namespace Server.Spells.Sixth { - public class DispelSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Dispel", "An Ort", - 218, - 9002, - Reagent.Garlic, - Reagent.MandrakeRoot, - Reagent.SulfurousAsh); - - public DispelSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class DispelSpell : MagerySpell, ISpellTargetingMobile { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Dispel", + "An Ort", + 218, + 9002, + Reagent.Garlic, + Reagent.MandrakeRoot, + Reagent.SulfurousAsh + ); - public override SpellCircle Circle => SpellCircle.Sixth; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (!(m is BaseCreature bc && bc.IsDispellable)) - Caster.SendLocalizedMessage(1005049); // That cannot be dispelled. - else if (CheckHSequence(m)) - { - SpellHelper.Turn(Caster, m); - - double dispelChance = - (50.0 + 100 * (Caster.Skills.Magery.Value - bc.DispelDifficulty) / (bc.DispelFocus * 2)) / 100; - - if (dispelChance > Utility.RandomDouble()) + public DispelSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - Effects.SendLocationParticles(EffectItem.Create(m.Location, m.Map, EffectItem.DefaultDuration), - 0x3728, 8, 20, 5042); - Effects.PlaySound(m, m.Map, 0x201); - - m.Delete(); } - else + + public override SpellCircle Circle => SpellCircle.Sixth; + + public void Target(Mobile m) { - m.FixedEffect(0x3779, 10, 20); - Caster.SendLocalizedMessage(1010084); // The creature resisted the attempt to dispel it! - } - } + if (m == null) + return; - FinishSequence(); + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (!(m is BaseCreature bc && bc.IsDispellable)) + { + Caster.SendLocalizedMessage(1005049); // That cannot be dispelled. + } + else if (CheckHSequence(m)) + { + SpellHelper.Turn(Caster, m); + + var dispelChance = + (50.0 + 100 * (Caster.Skills.Magery.Value - bc.DispelDifficulty) / (bc.DispelFocus * 2)) / 100; + + if (dispelChance > Utility.RandomDouble()) + { + Effects.SendLocationParticles( + EffectItem.Create(m.Location, m.Map, EffectItem.DefaultDuration), + 0x3728, + 8, + 20, + 5042 + ); + Effects.PlaySound(m, m.Map, 0x201); + + m.Delete(); + } + else + { + m.FixedEffect(0x3779, 10, 20); + Caster.SendLocalizedMessage(1010084); // The creature resisted the attempt to dispel it! + } + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } } - } } diff --git a/Projects/UOContent/Spells/Sixth/EnergyBolt.cs b/Projects/UOContent/Spells/Sixth/EnergyBolt.cs index 9e0927555..23e46a664 100644 --- a/Projects/UOContent/Spells/Sixth/EnergyBolt.cs +++ b/Projects/UOContent/Spells/Sixth/EnergyBolt.cs @@ -2,73 +2,77 @@ using Server.Targeting; namespace Server.Spells.Sixth { - public class EnergyBoltSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Energy Bolt", "Corp Por", - 230, - 9022, - Reagent.BlackPearl, - Reagent.Nightshade); - - public EnergyBoltSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class EnergyBoltSpell : MagerySpell, ISpellTargetingMobile { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Energy Bolt", + "Corp Por", + 230, + 9022, + Reagent.BlackPearl, + Reagent.Nightshade + ); - public override SpellCircle Circle => SpellCircle.Sixth; - - public override bool DelayedDamage => true; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (CheckHSequence(m)) - { - Mobile source = Caster; - - SpellHelper.Turn(Caster, m); - - SpellHelper.CheckReflect((int)Circle, ref source, ref m); - - double damage; - - if (Core.AOS) + public EnergyBoltSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - damage = GetNewAosDamage(40, 1, 5, m); - } - else - { - damage = Utility.Random(24, 18); - - if (CheckResisted(m)) - { - damage *= 0.75; - - m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. - } - - // Scale damage based on evalint and resist - damage *= GetDamageScalar(m); } - // Do the effects - source.MovingParticles(m, 0x379F, 7, 0, false, true, 3043, 4043, 0x211); - source.PlaySound(0x20A); + public override SpellCircle Circle => SpellCircle.Sixth; - // Deal the damage - SpellHelper.Damage(this, m, damage, 0, 0, 0, 0, 100); - } + public override bool DelayedDamage => true; - FinishSequence(); + public void Target(Mobile m) + { + if (m == null) + return; + + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckHSequence(m)) + { + var source = Caster; + + SpellHelper.Turn(Caster, m); + + SpellHelper.CheckReflect((int)Circle, ref source, ref m); + + double damage; + + if (Core.AOS) + { + damage = GetNewAosDamage(40, 1, 5, m); + } + else + { + damage = Utility.Random(24, 18); + + if (CheckResisted(m)) + { + damage *= 0.75; + + m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + } + + // Scale damage based on evalint and resist + damage *= GetDamageScalar(m); + } + + // Do the effects + source.MovingParticles(m, 0x379F, 7, 0, false, true, 3043, 4043, 0x211); + source.PlaySound(0x20A); + + // Deal the damage + SpellHelper.Damage(this, m, damage, 0, 0, 0, 0, 100); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } } - } } diff --git a/Projects/UOContent/Spells/Sixth/Explosion.cs b/Projects/UOContent/Spells/Sixth/Explosion.cs index 1041f0512..d05eaf809 100644 --- a/Projects/UOContent/Spells/Sixth/Explosion.cs +++ b/Projects/UOContent/Spells/Sixth/Explosion.cs @@ -3,107 +3,109 @@ using Server.Targeting; namespace Server.Spells.Sixth { - public class ExplosionSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Explosion", "Vas Ort Flam", - 230, - 9041, - Reagent.Bloodmoss, - Reagent.MandrakeRoot); - - public ExplosionSpell(Mobile caster, Item scroll = null) - : base(caster, scroll, m_Info) + public class ExplosionSpell : MagerySpell, ISpellTargetingMobile { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Explosion", + "Vas Ort Flam", + 230, + 9041, + Reagent.Bloodmoss, + Reagent.MandrakeRoot + ); - public override SpellCircle Circle => SpellCircle.Sixth; - - public override bool DelayedDamageStacking => !Core.AOS; - - public override bool DelayedDamage => false; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - { - Caster.SendLocalizedMessage(500237); // Target can not be seen. - } - else if (Caster.CanBeHarmful(m) && CheckSequence()) - { - Mobile attacker = Caster, defender = m; - - SpellHelper.Turn(Caster, m); - - SpellHelper.CheckReflect((int)Circle, Caster, ref m); - - InternalTimer t = new InternalTimer(this, attacker, defender, m); - t.Start(); - } - - FinishSequence(); - } - - private class InternalTimer : Timer - { - private readonly Mobile m_Attacker; - private readonly Mobile m_Defender; - private readonly MagerySpell m_Spell; - private readonly Mobile m_Target; - - public InternalTimer(MagerySpell spell, Mobile attacker, Mobile defender, Mobile target) - : base(TimeSpan.FromSeconds(Core.AOS ? 3.0 : 2.5)) - { - m_Spell = spell; - m_Attacker = attacker; - m_Defender = defender; - m_Target = target; - - m_Spell?.StartDelayedDamageContext(attacker, this); - - Priority = TimerPriority.FiftyMS; - } - - protected override void OnTick() - { - if (m_Attacker.HarmfulCheck(m_Defender)) + public ExplosionSpell(Mobile caster, Item scroll = null) + : base(caster, scroll, m_Info) { - double damage; + } - if (Core.AOS) - { - damage = m_Spell.GetNewAosDamage(40, 1, 5, m_Defender); - } - else - { - damage = Utility.Random(23, 22); + public override SpellCircle Circle => SpellCircle.Sixth; - if (m_Spell.CheckResisted(m_Target)) + public override bool DelayedDamageStacking => !Core.AOS; + + public override bool DelayedDamage => false; + + public void Target(Mobile m) + { + if (m == null) + return; + + if (!Caster.CanSee(m)) { - damage *= 0.75; + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (Caster.CanBeHarmful(m) && CheckSequence()) + { + Mobile attacker = Caster, defender = m; - m_Target.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + SpellHelper.Turn(Caster, m); + + SpellHelper.CheckReflect((int)Circle, Caster, ref m); + + var t = new InternalTimer(this, attacker, defender, m); + t.Start(); } - damage *= m_Spell.GetDamageScalar(m_Target); - } - - m_Target.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); - m_Target.PlaySound(0x307); - - SpellHelper.Damage(m_Spell, m_Target, damage, 0, 100, 0, 0, 0); - - m_Spell?.RemoveDelayedDamageContext(m_Attacker); + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } + + private class InternalTimer : Timer + { + private readonly Mobile m_Attacker; + private readonly Mobile m_Defender; + private readonly MagerySpell m_Spell; + private readonly Mobile m_Target; + + public InternalTimer(MagerySpell spell, Mobile attacker, Mobile defender, Mobile target) + : base(TimeSpan.FromSeconds(Core.AOS ? 3.0 : 2.5)) + { + m_Spell = spell; + m_Attacker = attacker; + m_Defender = defender; + m_Target = target; + + m_Spell?.StartDelayedDamageContext(attacker, this); + + Priority = TimerPriority.FiftyMS; + } + + protected override void OnTick() + { + if (m_Attacker.HarmfulCheck(m_Defender)) + { + double damage; + + if (Core.AOS) + { + damage = m_Spell.GetNewAosDamage(40, 1, 5, m_Defender); + } + else + { + damage = Utility.Random(23, 22); + + if (m_Spell.CheckResisted(m_Target)) + { + damage *= 0.75; + + m_Target.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + } + + damage *= m_Spell.GetDamageScalar(m_Target); + } + + m_Target.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); + m_Target.PlaySound(0x307); + + SpellHelper.Damage(m_Spell, m_Target, damage, 0, 100, 0, 0, 0); + + m_Spell?.RemoveDelayedDamageContext(m_Attacker); + } + } } - } } - } } diff --git a/Projects/UOContent/Spells/Sixth/Invisibility.cs b/Projects/UOContent/Spells/Sixth/Invisibility.cs index b49c21dce..5e2c2e17b 100644 --- a/Projects/UOContent/Spells/Sixth/Invisibility.cs +++ b/Projects/UOContent/Spells/Sixth/Invisibility.cs @@ -7,108 +7,114 @@ using Server.Targeting; namespace Server.Spells.Sixth { - public class InvisibilitySpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Invisibility", "An Lor Xen", - 206, - 9002, - Reagent.Bloodmoss, - Reagent.Nightshade); - - private static readonly Dictionary m_Table = new Dictionary(); - - public InvisibilitySpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class InvisibilitySpell : MagerySpell, ISpellTargetingMobile { + private static readonly SpellInfo m_Info = new SpellInfo( + "Invisibility", + "An Lor Xen", + 206, + 9002, + Reagent.Bloodmoss, + Reagent.Nightshade + ); + + private static readonly Dictionary m_Table = new Dictionary(); + + public InvisibilitySpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.Sixth; + + public void Target(Mobile m) + { + if (m == null) + return; + + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (m is BaseVendor || m is PlayerVendor || m.AccessLevel > Caster.AccessLevel) + { + Caster.SendLocalizedMessage(501857); // This spell won't work on that! + } + else if (CheckBSequence(m)) + { + SpellHelper.Turn(Caster, m); + + Effects.SendLocationParticles( + EffectItem.Create(new Point3D(m.X, m.Y, m.Z + 16), Caster.Map, EffectItem.DefaultDuration), + 0x376A, + 10, + 15, + 5045 + ); + m.PlaySound(0x3C4); + + m.Hidden = true; + m.Combatant = null; + m.Warmode = false; + + RemoveTimer(m); + + var duration = TimeSpan.FromSeconds(1.2 * Caster.Skills.Magery.Fixed / 10); + + Timer t = new InternalTimer(m, duration); + + BuffInfo.RemoveBuff(m, BuffIcon.HidingAndOrStealth); + BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Invisibility, 1075825, duration, m)); // Invisibility/Invisible + + m_Table[m] = t; + + t.Start(); + } + + FinishSequence(); + } + + public override bool CheckCast() + { + if (DuelContext.CheckSuddenDeath(Caster)) + { + Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); + return false; + } + + return base.CheckCast(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, Core.ML ? 10 : 12); + } + + public static bool HasTimer(Mobile m) => m_Table.ContainsKey(m); + + public static void RemoveTimer(Mobile m) + { + if (!m_Table.TryGetValue(m, out var t)) + return; + + t.Stop(); + m_Table.Remove(m); + } + + private class InternalTimer : Timer + { + private readonly Mobile m_Mobile; + + public InternalTimer(Mobile m, TimeSpan duration) : base(duration) + { + Priority = TimerPriority.OneSecond; + m_Mobile = m; + } + + protected override void OnTick() + { + m_Mobile.RevealingAction(); + RemoveTimer(m_Mobile); + } + } } - - public override SpellCircle Circle => SpellCircle.Sixth; - - public override bool CheckCast() - { - if (DuelContext.CheckSuddenDeath(Caster)) - { - Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); - return false; - } - - return base.CheckCast(); - } - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - { - Caster.SendLocalizedMessage(500237); // Target can not be seen. - } - else if (m is BaseVendor || m is PlayerVendor || m.AccessLevel > Caster.AccessLevel) - { - Caster.SendLocalizedMessage(501857); // This spell won't work on that! - } - else if (CheckBSequence(m)) - { - SpellHelper.Turn(Caster, m); - - Effects.SendLocationParticles( - EffectItem.Create(new Point3D(m.X, m.Y, m.Z + 16), Caster.Map, EffectItem.DefaultDuration), 0x376A, 10, - 15, 5045); - m.PlaySound(0x3C4); - - m.Hidden = true; - m.Combatant = null; - m.Warmode = false; - - RemoveTimer(m); - - TimeSpan duration = TimeSpan.FromSeconds(1.2 * Caster.Skills.Magery.Fixed / 10); - - Timer t = new InternalTimer(m, duration); - - BuffInfo.RemoveBuff(m, BuffIcon.HidingAndOrStealth); - BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Invisibility, 1075825, duration, m)); // Invisibility/Invisible - - m_Table[m] = t; - - t.Start(); - } - - FinishSequence(); - } - - public static bool HasTimer(Mobile m) => m_Table.ContainsKey(m); - - public static void RemoveTimer(Mobile m) - { - if (!m_Table.TryGetValue(m, out Timer t)) - return; - - t.Stop(); - m_Table.Remove(m); - } - - private class InternalTimer : Timer - { - private readonly Mobile m_Mobile; - - public InternalTimer(Mobile m, TimeSpan duration) : base(duration) - { - Priority = TimerPriority.OneSecond; - m_Mobile = m; - } - - protected override void OnTick() - { - m_Mobile.RevealingAction(); - RemoveTimer(m_Mobile); - } - } - } } diff --git a/Projects/UOContent/Spells/Sixth/Mark.cs b/Projects/UOContent/Spells/Sixth/Mark.cs index 37467d210..a0f8ad40c 100644 --- a/Projects/UOContent/Spells/Sixth/Mark.cs +++ b/Projects/UOContent/Spells/Sixth/Mark.cs @@ -4,53 +4,76 @@ using Server.Targeting; namespace Server.Spells.Sixth { - public class MarkSpell : MagerySpell, ISpellTargetingItem - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Mark", "Kal Por Ylem", - 218, - 9002, - Reagent.BlackPearl, - Reagent.Bloodmoss, - Reagent.MandrakeRoot); - - public MarkSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class MarkSpell : MagerySpell, ISpellTargetingItem { + private static readonly SpellInfo m_Info = new SpellInfo( + "Mark", + "Kal Por Ylem", + 218, + 9002, + Reagent.BlackPearl, + Reagent.Bloodmoss, + Reagent.MandrakeRoot + ); + + public MarkSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.Sixth; + + public void Target(Item item) + { + if (!(item is RecallRune rune)) + { + Caster.Send( + new MessageLocalized( + Caster.Serial, + Caster.Body, + MessageType.Regular, + 0x3B2, + 3, + 501797, + Caster.Name, + "" + ) + ); // I cannot mark that object. + } + else if (!Caster.CanSee(rune)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.Mark)) + { + } + else if (SpellHelper.CheckMulti(Caster.Location, Caster.Map, !Core.AOS)) + { + Caster.SendLocalizedMessage(501942); // That location is blocked. + } + else if (!rune.IsChildOf(Caster.Backpack)) + { + Caster.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 1062422 + ); // You must have this rune in your backpack in order to mark it. + } + else if (CheckSequence()) + { + rune.Mark(Caster); + + Caster.PlaySound(0x1FA); + Effects.SendLocationEffect(Caster, Caster.Map, 14201, 16); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetItem(this, TargetFlags.None, Core.ML ? 10 : 12); + } + + public override bool CheckCast() => base.CheckCast() && SpellHelper.CheckTravel(Caster, TravelCheckType.Mark); } - - public override SpellCircle Circle => SpellCircle.Sixth; - - public override void OnCast() - { - Caster.Target = new SpellTargetItem(this, TargetFlags.None, Core.ML ? 10 : 12); - } - - public override bool CheckCast() => base.CheckCast() && SpellHelper.CheckTravel(Caster, TravelCheckType.Mark); - - public void Target(Item item) - { - if (!(item is RecallRune rune)) - Caster.Send(new MessageLocalized(Caster.Serial, Caster.Body, MessageType.Regular, 0x3B2, 3, 501797, Caster.Name, - "")); // I cannot mark that object. - else if (!Caster.CanSee(rune)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.Mark)) - { - } - else if (SpellHelper.CheckMulti(Caster.Location, Caster.Map, !Core.AOS)) - Caster.SendLocalizedMessage(501942); // That location is blocked. - else if (!rune.IsChildOf(Caster.Backpack)) - Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 1062422); // You must have this rune in your backpack in order to mark it. - else if (CheckSequence()) - { - rune.Mark(Caster); - - Caster.PlaySound(0x1FA); - Effects.SendLocationEffect(Caster, Caster.Map, 14201, 16); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Sixth/MassCurse.cs b/Projects/UOContent/Spells/Sixth/MassCurse.cs index 08bc08f04..d9c553f21 100644 --- a/Projects/UOContent/Spells/Sixth/MassCurse.cs +++ b/Projects/UOContent/Spells/Sixth/MassCurse.cs @@ -2,72 +2,74 @@ using Server.Targeting; namespace Server.Spells.Sixth { - public class MassCurseSpell : MagerySpell, ISpellTargetingPoint3D - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Mass Curse", "Vas Des Sanct", - 218, - 9031, - false, - Reagent.Garlic, - Reagent.Nightshade, - Reagent.MandrakeRoot, - Reagent.SulfurousAsh); - - public MassCurseSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class MassCurseSpell : MagerySpell, ISpellTargetingPoint3D { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Mass Curse", + "Vas Des Sanct", + 218, + 9031, + false, + Reagent.Garlic, + Reagent.Nightshade, + Reagent.MandrakeRoot, + Reagent.SulfurousAsh + ); - public override SpellCircle Circle => SpellCircle.Sixth; - - public override void OnCast() - { - Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); - } - - public void Target(IPoint3D p) - { - if (!Caster.CanSee(p)) - { - Caster.SendLocalizedMessage(500237); // Target can not be seen. - } - else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) - { - SpellHelper.Turn(Caster, p); - - SpellHelper.GetSurfaceTop(ref p); - - Map map = Caster.Map; - - if (map != null) + public MassCurseSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - IPooledEnumerable eable = map.GetMobilesInRange(new Point3D(p), 2); - - foreach (Mobile m in eable) - { - if (Core.AOS && (m == Caster || !SpellHelper.ValidIndirectTarget(Caster, m) || !Caster.CanSee(m) || - !Caster.CanBeHarmful(m, false))) - continue; - - Caster.DoHarmful(m); - - SpellHelper.AddStatCurse(Caster, m, StatType.Str); - SpellHelper.DisableSkillCheck = true; - SpellHelper.AddStatCurse(Caster, m, StatType.Dex); - SpellHelper.AddStatCurse(Caster, m, StatType.Int); - SpellHelper.DisableSkillCheck = false; - - m.FixedParticles(0x374A, 10, 15, 5028, EffectLayer.Waist); - m.PlaySound(0x1FB); - - HarmfulSpell(m); - } - - eable.Free(); } - } - FinishSequence(); + public override SpellCircle Circle => SpellCircle.Sixth; + + public void Target(IPoint3D p) + { + if (!Caster.CanSee(p)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) + { + SpellHelper.Turn(Caster, p); + + SpellHelper.GetSurfaceTop(ref p); + + var map = Caster.Map; + + if (map != null) + { + var eable = map.GetMobilesInRange(new Point3D(p), 2); + + foreach (var m in eable) + { + if (Core.AOS && (m == Caster || !SpellHelper.ValidIndirectTarget(Caster, m) || !Caster.CanSee(m) || + !Caster.CanBeHarmful(m, false))) + continue; + + Caster.DoHarmful(m); + + SpellHelper.AddStatCurse(Caster, m, StatType.Str); + SpellHelper.DisableSkillCheck = true; + SpellHelper.AddStatCurse(Caster, m, StatType.Dex); + SpellHelper.AddStatCurse(Caster, m, StatType.Int); + SpellHelper.DisableSkillCheck = false; + + m.FixedParticles(0x374A, 10, 15, 5028, EffectLayer.Waist); + m.PlaySound(0x1FB); + + HarmfulSpell(m); + } + + eable.Free(); + } + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); + } } - } } diff --git a/Projects/UOContent/Spells/Sixth/ParalyzeField.cs b/Projects/UOContent/Spells/Sixth/ParalyzeField.cs index bf5c007a2..11089f365 100644 --- a/Projects/UOContent/Spells/Sixth/ParalyzeField.cs +++ b/Projects/UOContent/Spells/Sixth/ParalyzeField.cs @@ -6,206 +6,215 @@ using Server.Targeting; namespace Server.Spells.Sixth { - public class ParalyzeFieldSpell : MagerySpell, ISpellTargetingPoint3D - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Paralyze Field", "In Ex Grav", - 230, - 9012, - false, - Reagent.BlackPearl, - Reagent.Ginseng, - Reagent.SpidersSilk); - - public ParalyzeFieldSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class ParalyzeFieldSpell : MagerySpell, ISpellTargetingPoint3D { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Paralyze Field", + "In Ex Grav", + 230, + 9012, + false, + Reagent.BlackPearl, + Reagent.Ginseng, + Reagent.SpidersSilk + ); - public override SpellCircle Circle => SpellCircle.Sixth; - - public override void OnCast() - { - Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); - } - - public void Target(IPoint3D p) - { - if (!Caster.CanSee(p)) - { - Caster.SendLocalizedMessage(500237); // Target can not be seen. - } - else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) - { - SpellHelper.Turn(Caster, p); - - SpellHelper.GetSurfaceTop(ref p); - - int dx = Caster.Location.X - p.X; - int dy = Caster.Location.Y - p.Y; - int rx = (dx - dy) * 44; - int ry = (dx + dy) * 44; - - bool eastToWest; - - if (rx >= 0 && ry >= 0) - eastToWest = false; - else if (rx >= 0) - eastToWest = true; - else if (ry >= 0) - eastToWest = true; - else - eastToWest = false; - - Effects.PlaySound(p, Caster.Map, 0x20B); - - int itemID = eastToWest ? 0x3967 : 0x3979; - - TimeSpan duration = TimeSpan.FromSeconds(3.0 + Caster.Skills.Magery.Value / 3.0); - - for (int i = -2; i <= 2; ++i) + public ParalyzeFieldSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - Point3D loc = new Point3D(eastToWest ? p.X + i : p.X, eastToWest ? p.Y : p.Y + i, p.Z); - - if (!SpellHelper.AdjustField(ref loc, Caster.Map, 12, false)) - continue; - - Item item = new InternalItem(Caster, itemID, loc, Caster.Map, duration); - item.ProcessDelta(); - - Effects.SendLocationParticles(EffectItem.Create(loc, Caster.Map, EffectItem.DefaultDuration), 0x376A, 9, - 10, 5048); } - } - FinishSequence(); - } + public override SpellCircle Circle => SpellCircle.Sixth; - [DispellableField] - public class InternalItem : Item - { - private Mobile m_Caster; - private DateTime m_End; - private Timer m_Timer; - - public InternalItem(Mobile caster, int itemID, Point3D loc, Map map, TimeSpan duration) : base(itemID) - { - Visible = false; - Movable = false; - Light = LightType.Circle300; - - MoveToWorld(loc, map); - - if (caster.InLOS(this)) - Visible = true; - else - Delete(); - - if (Deleted) - return; - - m_Caster = caster; - - m_Timer = new InternalTimer(this, duration); - m_Timer.Start(); - - m_End = DateTime.UtcNow + duration; - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public override bool BlocksFit => true; - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Timer?.Stop(); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(0); // version - - writer.Write(m_Caster); - writer.WriteDeltaTime(m_End); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) + public void Target(IPoint3D p) { - case 0: + if (!Caster.CanSee(p)) { - m_Caster = reader.ReadMobile(); - m_End = reader.ReadDeltaTime(); + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) + { + SpellHelper.Turn(Caster, p); - m_Timer = new InternalTimer(this, m_End - DateTime.UtcNow); - m_Timer.Start(); + SpellHelper.GetSurfaceTop(ref p); - break; + var dx = Caster.Location.X - p.X; + var dy = Caster.Location.Y - p.Y; + var rx = (dx - dy) * 44; + var ry = (dx + dy) * 44; + + bool eastToWest; + + if (rx >= 0 && ry >= 0) + eastToWest = false; + else if (rx >= 0) + eastToWest = true; + else if (ry >= 0) + eastToWest = true; + else + eastToWest = false; + + Effects.PlaySound(p, Caster.Map, 0x20B); + + var itemID = eastToWest ? 0x3967 : 0x3979; + + var duration = TimeSpan.FromSeconds(3.0 + Caster.Skills.Magery.Value / 3.0); + + for (var i = -2; i <= 2; ++i) + { + var loc = new Point3D(eastToWest ? p.X + i : p.X, eastToWest ? p.Y : p.Y + i, p.Z); + + if (!SpellHelper.AdjustField(ref loc, Caster.Map, 12, false)) + continue; + + Item item = new InternalItem(Caster, itemID, loc, Caster.Map, duration); + item.ProcessDelta(); + + Effects.SendLocationParticles( + EffectItem.Create(loc, Caster.Map, EffectItem.DefaultDuration), + 0x376A, + 9, + 10, + 5048 + ); + } + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); + } + + [DispellableField] + public class InternalItem : Item + { + private Mobile m_Caster; + private DateTime m_End; + private Timer m_Timer; + + public InternalItem(Mobile caster, int itemID, Point3D loc, Map map, TimeSpan duration) : base(itemID) + { + Visible = false; + Movable = false; + Light = LightType.Circle300; + + MoveToWorld(loc, map); + + if (caster.InLOS(this)) + Visible = true; + else + Delete(); + + if (Deleted) + return; + + m_Caster = caster; + + m_Timer = new InternalTimer(this, duration); + m_Timer.Start(); + + m_End = DateTime.UtcNow + duration; + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override bool BlocksFit => true; + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Timer?.Stop(); + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(0); // version + + writer.Write(m_Caster); + writer.WriteDeltaTime(m_End); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 0: + { + m_Caster = reader.ReadMobile(); + m_End = reader.ReadDeltaTime(); + + m_Timer = new InternalTimer(this, m_End - DateTime.UtcNow); + m_Timer.Start(); + + break; + } + } + } + + public override bool OnMoveOver(Mobile m) + { + if (Visible && m_Caster != null && (!Core.AOS || m != m_Caster) && + SpellHelper.ValidIndirectTarget(m_Caster, m) && m_Caster.CanBeHarmful(m, false)) + { + if (SpellHelper.CanRevealCaster(m)) + m_Caster.RevealingAction(); + + m_Caster.DoHarmful(m); + + double duration; + + if (Core.AOS) + { + duration = Math.Max( + 2.0 + ((int)(m_Caster.Skills.EvalInt.Value / 10) - (int)(m.Skills.MagicResist.Value / 10)), + 0.0 + ); + + if (!m.Player) + duration *= 3.0; + } + else + { + duration = 7.0 + m_Caster.Skills.Magery.Value * 0.2; + } + + m.Paralyze(TimeSpan.FromSeconds(duration)); + + m.PlaySound(0x204); + m.FixedEffect(0x376A, 10, 16); + + (m as BaseCreature)?.OnHarmfulSpell(m_Caster); + } + + return true; + } + + private class InternalTimer : Timer + { + private readonly Item m_Item; + + public InternalTimer(Item item, TimeSpan duration) : base(duration) + { + Priority = TimerPriority.OneSecond; + m_Item = item; + } + + protected override void OnTick() + { + m_Item.Delete(); + } } } - } - - public override bool OnMoveOver(Mobile m) - { - if (Visible && m_Caster != null && (!Core.AOS || m != m_Caster) && - SpellHelper.ValidIndirectTarget(m_Caster, m) && m_Caster.CanBeHarmful(m, false)) - { - if (SpellHelper.CanRevealCaster(m)) - m_Caster.RevealingAction(); - - m_Caster.DoHarmful(m); - - double duration; - - if (Core.AOS) - { - duration = Math.Max( - 2.0 + ((int)(m_Caster.Skills.EvalInt.Value / 10) - (int)(m.Skills.MagicResist.Value / 10)), 0.0); - - if (!m.Player) - duration *= 3.0; - } - else - { - duration = 7.0 + m_Caster.Skills.Magery.Value * 0.2; - } - - m.Paralyze(TimeSpan.FromSeconds(duration)); - - m.PlaySound(0x204); - m.FixedEffect(0x376A, 10, 16); - - (m as BaseCreature)?.OnHarmfulSpell(m_Caster); - } - - return true; - } - - private class InternalTimer : Timer - { - private readonly Item m_Item; - - public InternalTimer(Item item, TimeSpan duration) : base(duration) - { - Priority = TimerPriority.OneSecond; - m_Item = item; - } - - protected override void OnTick() - { - m_Item.Delete(); - } - } } - } } diff --git a/Projects/UOContent/Spells/Sixth/Reveal.cs b/Projects/UOContent/Spells/Sixth/Reveal.cs index f109bd48c..91c3ea3ca 100644 --- a/Projects/UOContent/Spells/Sixth/Reveal.cs +++ b/Projects/UOContent/Spells/Sixth/Reveal.cs @@ -3,85 +3,89 @@ using Server.Targeting; namespace Server.Spells.Sixth { - public class RevealSpell : MagerySpell, ISpellTargetingPoint3D - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Reveal", "Wis Quas", - 206, - 9002, - Reagent.Bloodmoss, - Reagent.SulfurousAsh); - - public RevealSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class RevealSpell : MagerySpell, ISpellTargetingPoint3D { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Reveal", + "Wis Quas", + 206, + 9002, + Reagent.Bloodmoss, + Reagent.SulfurousAsh + ); - public override SpellCircle Circle => SpellCircle.Sixth; - - public override void OnCast() - { - Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); - } - - public void Target(IPoint3D p) - { - if (!Caster.CanSee(p)) - { - Caster.SendLocalizedMessage(500237); // Target can not be seen. - } - else if (CheckSequence()) - { - SpellHelper.Turn(Caster, p); - SpellHelper.GetSurfaceTop(ref p); - Map map = Caster.Map; - - if (map != null) + public RevealSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - IPooledEnumerable eable = map.GetMobilesInRange(new Point3D(p), - 1 + (int)(Caster.Skills.Magery.Value / 20.0)); - - foreach (Mobile m in eable) - { - if (m is ShadowKnight && - (m.X != p.X || m.Y != p.Y || !m.Hidden || (m.AccessLevel != AccessLevel.Player && - Caster.AccessLevel <= m.AccessLevel) || - !CheckDifficulty(Caster, m))) - continue; - - m.RevealingAction(); - - m.FixedParticles(0x375A, 9, 20, 5049, EffectLayer.Head); - m.PlaySound(0x1FD); - } - - eable.Free(); } - } - FinishSequence(); + public override SpellCircle Circle => SpellCircle.Sixth; + + public void Target(IPoint3D p) + { + if (!Caster.CanSee(p)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckSequence()) + { + SpellHelper.Turn(Caster, p); + SpellHelper.GetSurfaceTop(ref p); + var map = Caster.Map; + + if (map != null) + { + var eable = map.GetMobilesInRange( + new Point3D(p), + 1 + (int)(Caster.Skills.Magery.Value / 20.0) + ); + + foreach (var m in eable) + { + if (m is ShadowKnight && + (m.X != p.X || m.Y != p.Y || !m.Hidden || m.AccessLevel != AccessLevel.Player && + Caster.AccessLevel <= m.AccessLevel || + !CheckDifficulty(Caster, m))) + continue; + + m.RevealingAction(); + + m.FixedParticles(0x375A, 9, 20, 5049, EffectLayer.Head); + m.PlaySound(0x1FD); + } + + eable.Free(); + } + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); + } + + // Reveal uses magery and detect hidden vs. hide and stealth + private static bool CheckDifficulty(Mobile from, Mobile m) + { + // Reveal always reveals vs. invisibility spell + if (!Core.AOS || InvisibilitySpell.HasTimer(m)) + return true; + + var magery = from.Skills.Magery.Fixed; + var detectHidden = from.Skills.DetectHidden.Fixed; + + var hiding = m.Skills.Hiding.Fixed; + var stealth = m.Skills.Stealth.Fixed; + var divisor = hiding + stealth; + + int chance; + if (divisor > 0) + chance = 50 * (magery + detectHidden) / divisor; + else + chance = 100; + + return chance > Utility.Random(100); + } } - - // Reveal uses magery and detect hidden vs. hide and stealth - private static bool CheckDifficulty(Mobile from, Mobile m) - { - // Reveal always reveals vs. invisibility spell - if (!Core.AOS || InvisibilitySpell.HasTimer(m)) - return true; - - int magery = from.Skills.Magery.Fixed; - int detectHidden = from.Skills.DetectHidden.Fixed; - - int hiding = m.Skills.Hiding.Fixed; - int stealth = m.Skills.Stealth.Fixed; - int divisor = hiding + stealth; - - int chance; - if (divisor > 0) - chance = 50 * (magery + detectHidden) / divisor; - else - chance = 100; - - return chance > Utility.Random(100); - } - } } diff --git a/Projects/UOContent/Spells/Spellweaving/ArcaneCircle.cs b/Projects/UOContent/Spells/Spellweaving/ArcaneCircle.cs index 83348e9f6..441b7074b 100644 --- a/Projects/UOContent/Spells/Spellweaving/ArcaneCircle.cs +++ b/Projects/UOContent/Spells/Spellweaving/ArcaneCircle.cs @@ -6,145 +6,157 @@ using Server.Mobiles; namespace Server.Spells.Spellweaving { - public class ArcaneCircleSpell : ArcanistSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Arcane Circle", "Myrshalee", - -1); - - public ArcaneCircleSpell(Mobile caster, Item scroll = null) - : base(caster, scroll, m_Info) + public class ArcaneCircleSpell : ArcanistSpell { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Arcane Circle", + "Myrshalee", + -1 + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(0.5); - - public override double RequiredSkill => 0.0; - public override int RequiredMana => 24; - - public override bool CheckCast() - { - if (!IsValidLocation(Caster.Location, Caster.Map)) - { - Caster.SendLocalizedMessage( - 1072705); // You must be standing on an arcane circle, pentagram or abbatoir to use this spell. - return false; - } - - if (GetArcanists().Count < 2) - { - Caster.SendLocalizedMessage(1080452); // There are not enough spellweavers present to create an Arcane Focus. - return false; - } - - return base.CheckCast(); - } - - public override void OnCast() - { - if (CheckSequence()) - { - Caster.FixedParticles(0x3779, 10, 20, 0x0, EffectLayer.Waist); - Caster.PlaySound(0x5C0); - - List Arcanists = GetArcanists(); - - TimeSpan duration = TimeSpan.FromHours(Math.Max(1, (int)(Caster.Skills.Spellweaving.Value / 24))); - - int strengthBonus = - Math.Min(Arcanists.Count, - IsSanctuary(Caster.Location, Caster.Map) - ? 6 - : 5); // The Sanctuary is a special, single location place - - for (int i = 0; i < Arcanists.Count; i++) - GiveArcaneFocus(Arcanists[i], duration, strengthBonus); - } - - FinishSequence(); - } - - private static bool IsSanctuary(Point3D p, Map m) => (m == Map.Trammel || m == Map.Felucca) && p.X == 6267 && p.Y == 131; - - private static bool IsValidLocation(Point3D location, Map map) - { - LandTile lt = map.Tiles.GetLandTile(location.X, location.Y); // Land Tiles - - if (IsValidTile(lt.ID) && lt.Z == location.Z) - return true; - - StaticTile[] tiles = map.Tiles.GetStaticTiles(location.X, location.Y); // Static Tiles - - for (int i = 0; i < tiles.Length; ++i) - { - StaticTile t = tiles[i]; - ItemData id = TileData.ItemTable[t.ID & TileData.MaxItemValue]; - - int tand = t.ID; - - if (t.Z + id.CalcHeight != location.Z) - continue; - if (IsValidTile(tand)) - return true; - } - - IPooledEnumerable eable = map.GetItemsInRange(location, 0); - - bool found = eable.Any(item => - item.Z + item.ItemData.CalcHeight == location.Z && IsValidTile(item.ItemID)); - - eable.Free(); - - return found; - } - - public static bool IsValidTile(int itemID) => - itemID == 0xFEA || itemID == 0x1216 || itemID == 0x307F || itemID == 0x1D10 || itemID == 0x1D0F || - itemID == 0x1D1F || - itemID == 0x1D12; - - private List GetArcanists() - { - List weavers = new List { Caster }; - - // OSI Verified: Even enemies/combatants count - // Everyone gets the Arcane Focus, power capped elsewhere - weavers.AddRange(Caster.GetMobilesInRange(1) - .Where(m => m != Caster && m is PlayerMobile && Caster.CanBeBeneficial(m, false) && - Math.Abs(Caster.Skills.Spellweaving.Value - m.Skills.Spellweaving.Value) <= 20)); - - return weavers; - } - - private void GiveArcaneFocus(Mobile to, TimeSpan duration, int strengthBonus) - { - if (to == null) // Sanity - return; - - ArcaneFocus focus = FindArcaneFocus(to); - - if (focus == null) - { - focus = new ArcaneFocus(duration, strengthBonus); - if (to.PlaceInBackpack(focus)) + public ArcaneCircleSpell(Mobile caster, Item scroll = null) + : base(caster, scroll, m_Info) { - focus.SendTimeRemainingMessage(to); - to.SendLocalizedMessage(1072740); // An arcane focus appears in your backpack. } - else + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(0.5); + + public override double RequiredSkill => 0.0; + public override int RequiredMana => 24; + + public override bool CheckCast() { - focus.Delete(); + if (!IsValidLocation(Caster.Location, Caster.Map)) + { + Caster.SendLocalizedMessage( + 1072705 + ); // You must be standing on an arcane circle, pentagram or abbatoir to use this spell. + return false; + } + + if (GetArcanists().Count < 2) + { + Caster.SendLocalizedMessage(1080452); // There are not enough spellweavers present to create an Arcane Focus. + return false; + } + + return base.CheckCast(); + } + + public override void OnCast() + { + if (CheckSequence()) + { + Caster.FixedParticles(0x3779, 10, 20, 0x0, EffectLayer.Waist); + Caster.PlaySound(0x5C0); + + var Arcanists = GetArcanists(); + + var duration = TimeSpan.FromHours(Math.Max(1, (int)(Caster.Skills.Spellweaving.Value / 24))); + + var strengthBonus = + Math.Min( + Arcanists.Count, + IsSanctuary(Caster.Location, Caster.Map) + ? 6 + : 5 + ); // The Sanctuary is a special, single location place + + for (var i = 0; i < Arcanists.Count; i++) + GiveArcaneFocus(Arcanists[i], duration, strengthBonus); + } + + FinishSequence(); + } + + private static bool IsSanctuary(Point3D p, Map m) => + (m == Map.Trammel || m == Map.Felucca) && p.X == 6267 && p.Y == 131; + + private static bool IsValidLocation(Point3D location, Map map) + { + var lt = map.Tiles.GetLandTile(location.X, location.Y); // Land Tiles + + if (IsValidTile(lt.ID) && lt.Z == location.Z) + return true; + + var tiles = map.Tiles.GetStaticTiles(location.X, location.Y); // Static Tiles + + for (var i = 0; i < tiles.Length; ++i) + { + var t = tiles[i]; + var id = TileData.ItemTable[t.ID & TileData.MaxItemValue]; + + var tand = t.ID; + + if (t.Z + id.CalcHeight != location.Z) + continue; + if (IsValidTile(tand)) + return true; + } + + var eable = map.GetItemsInRange(location, 0); + + var found = eable.Any( + item => + item.Z + item.ItemData.CalcHeight == location.Z && IsValidTile(item.ItemID) + ); + + eable.Free(); + + return found; + } + + public static bool IsValidTile(int itemID) => + itemID == 0xFEA || itemID == 0x1216 || itemID == 0x307F || itemID == 0x1D10 || itemID == 0x1D0F || + itemID == 0x1D1F || + itemID == 0x1D12; + + private List GetArcanists() + { + var weavers = new List { Caster }; + + // OSI Verified: Even enemies/combatants count + // Everyone gets the Arcane Focus, power capped elsewhere + weavers.AddRange( + Caster.GetMobilesInRange(1) + .Where( + m => m != Caster && m is PlayerMobile && Caster.CanBeBeneficial(m, false) && + Math.Abs(Caster.Skills.Spellweaving.Value - m.Skills.Spellweaving.Value) <= 20 + ) + ); + + return weavers; + } + + private void GiveArcaneFocus(Mobile to, TimeSpan duration, int strengthBonus) + { + if (to == null) // Sanity + return; + + var focus = FindArcaneFocus(to); + + if (focus == null) + { + focus = new ArcaneFocus(duration, strengthBonus); + if (to.PlaceInBackpack(focus)) + { + focus.SendTimeRemainingMessage(to); + to.SendLocalizedMessage(1072740); // An arcane focus appears in your backpack. + } + else + { + focus.Delete(); + } + } + else // OSI renewal rules: the new one will override the old one, always. + { + to.SendLocalizedMessage(1072828); // Your arcane focus is renewed. + focus.LifeSpan = duration; + focus.CreationTime = DateTime.UtcNow; + focus.StrengthBonus = strengthBonus; + focus.InvalidateProperties(); + focus.SendTimeRemainingMessage(to); + } } - } - else // OSI renewal rules: the new one will override the old one, always. - { - to.SendLocalizedMessage(1072828); // Your arcane focus is renewed. - focus.LifeSpan = duration; - focus.CreationTime = DateTime.UtcNow; - focus.StrengthBonus = strengthBonus; - focus.InvalidateProperties(); - focus.SendTimeRemainingMessage(to); - } } - } } diff --git a/Projects/UOContent/Spells/Spellweaving/ArcaneForm.cs b/Projects/UOContent/Spells/Spellweaving/ArcaneForm.cs index e6c7e1650..fbaadb7a6 100644 --- a/Projects/UOContent/Spells/Spellweaving/ArcaneForm.cs +++ b/Projects/UOContent/Spells/Spellweaving/ArcaneForm.cs @@ -1,47 +1,47 @@ namespace Server.Spells.Spellweaving { - public abstract class ArcaneForm : ArcanistSpell, ITransformationSpell - { - public ArcaneForm(Mobile caster, Item scroll, SpellInfo info) : base(caster, scroll, info) + public abstract class ArcaneForm : ArcanistSpell, ITransformationSpell { + public ArcaneForm(Mobile caster, Item scroll, SpellInfo info) : base(caster, scroll, info) + { + } + + public abstract int Body { get; } + public virtual int Hue => 0; + + public virtual int PhysResistOffset => 0; + public virtual int FireResistOffset => 0; + public virtual int ColdResistOffset => 0; + public virtual int PoisResistOffset => 0; + public virtual int NrgyResistOffset => 0; + + public virtual double TickRate => 1.0; + + public virtual void OnTick(Mobile m) + { + } + + public virtual void DoEffect(Mobile m) + { + } + + public virtual void RemoveEffect(Mobile m) + { + } + + public override bool CheckCast() + { + if (!TransformationSpellHelper.CheckCast(Caster, this)) + return false; + + return base.CheckCast(); + } + + public override void OnCast() + { + TransformationSpellHelper.OnCast(Caster, this); + + FinishSequence(); + } } - - public abstract int Body { get; } - public virtual int Hue => 0; - - public virtual int PhysResistOffset => 0; - public virtual int FireResistOffset => 0; - public virtual int ColdResistOffset => 0; - public virtual int PoisResistOffset => 0; - public virtual int NrgyResistOffset => 0; - - public virtual double TickRate => 1.0; - - public virtual void OnTick(Mobile m) - { - } - - public virtual void DoEffect(Mobile m) - { - } - - public virtual void RemoveEffect(Mobile m) - { - } - - public override bool CheckCast() - { - if (!TransformationSpellHelper.CheckCast(Caster, this)) - return false; - - return base.CheckCast(); - } - - public override void OnCast() - { - TransformationSpellHelper.OnCast(Caster, this); - - FinishSequence(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Spells/Spellweaving/ArcaneSummon.cs b/Projects/UOContent/Spells/Spellweaving/ArcaneSummon.cs index 424410f6c..a355f5751 100644 --- a/Projects/UOContent/Spells/Spellweaving/ArcaneSummon.cs +++ b/Projects/UOContent/Spells/Spellweaving/ArcaneSummon.cs @@ -4,54 +4,54 @@ using Server.Utilities; namespace Server.Spells.Spellweaving { - public abstract class ArcaneSummon : ArcanistSpell where T : BaseCreature - { - public ArcaneSummon(Mobile caster, Item scroll, SpellInfo info) - : base(caster, scroll, info) + public abstract class ArcaneSummon : ArcanistSpell where T : BaseCreature { - } - - public abstract int Sound { get; } - - public override bool CheckCast() - { - if (!base.CheckCast()) - return false; - - if (Caster.Followers + 1 > Caster.FollowersMax) - { - Caster.SendLocalizedMessage(1074270); // You have too many followers to summon another one. - return false; - } - - return true; - } - - public override void OnCast() - { - if (CheckSequence()) - { - TimeSpan duration = TimeSpan.FromMinutes(Caster.Skills.Spellweaving.Value / 24 + FocusLevel * 2); - int summons = Math.Min(1 + FocusLevel, Caster.FollowersMax - Caster.Followers); - - for (int i = 0; i < summons; i++) + public ArcaneSummon(Mobile caster, Item scroll, SpellInfo info) + : base(caster, scroll, info) { - BaseCreature bc; - - try - { - bc = ActivatorUtil.CreateInstance(); - } - catch - { - break; - } - - SpellHelper.Summon(bc, Caster, Sound, duration, false, false); } - FinishSequence(); - } + public abstract int Sound { get; } + + public override bool CheckCast() + { + if (!base.CheckCast()) + return false; + + if (Caster.Followers + 1 > Caster.FollowersMax) + { + Caster.SendLocalizedMessage(1074270); // You have too many followers to summon another one. + return false; + } + + return true; + } + + public override void OnCast() + { + if (CheckSequence()) + { + var duration = TimeSpan.FromMinutes(Caster.Skills.Spellweaving.Value / 24 + FocusLevel * 2); + var summons = Math.Min(1 + FocusLevel, Caster.FollowersMax - Caster.Followers); + + for (var i = 0; i < summons; i++) + { + BaseCreature bc; + + try + { + bc = ActivatorUtil.CreateInstance(); + } + catch + { + break; + } + + SpellHelper.Summon(bc, Caster, Sound, duration, false, false); + } + + FinishSequence(); + } + } } - } } diff --git a/Projects/UOContent/Spells/Spellweaving/ArcanistSpell.cs b/Projects/UOContent/Spells/Spellweaving/ArcanistSpell.cs index 9a0632314..55e3426a8 100644 --- a/Projects/UOContent/Spells/Spellweaving/ArcanistSpell.cs +++ b/Projects/UOContent/Spells/Spellweaving/ArcanistSpell.cs @@ -4,134 +4,142 @@ using Server.Mobiles; namespace Server.Spells.Spellweaving { - public abstract class ArcanistSpell : Spell - { - private int m_CastTimeFocusLevel; - - public ArcanistSpell(Mobile caster, Item scroll, SpellInfo info) - : base(caster, scroll, info) + public abstract class ArcanistSpell : Spell { - } + private int m_CastTimeFocusLevel; - public abstract double RequiredSkill { get; } - public abstract int RequiredMana { get; } - - public override SkillName CastSkill => SkillName.Spellweaving; - public override SkillName DamageSkill => SkillName.Spellweaving; - - public override bool ClearHandsOnCast => false; - - public virtual int FocusLevel => m_CastTimeFocusLevel; - - public static int GetFocusLevel(Mobile from) - { - ArcaneFocus focus = FindArcaneFocus(from); - - return focus?.Deleted != false ? 0 : focus.StrengthBonus; - } - - public static ArcaneFocus FindArcaneFocus(Mobile from) => from.Holding as ArcaneFocus ?? from.Backpack?.FindItemByType(); - - public static bool CheckExpansion(Mobile from) => !(from is PlayerMobile) || from.NetState?.SupportsExpansion(Expansion.ML) == true; - - public override bool CheckCast() - { - if (!base.CheckCast()) - return false; - - Mobile caster = Caster; - - if (!CheckExpansion(caster)) - { - caster.SendLocalizedMessage( - 1072176); // You must upgrade to the Mondain's Legacy Expansion Pack before using that ability - return false; - } - - if (caster is PlayerMobile mobile) - { - MLQuestContext context = MLQuestSystem.GetContext(mobile); - - if (context?.Spellweaving != true) + public ArcanistSpell(Mobile caster, Item scroll, SpellInfo info) + : base(caster, scroll, info) { - mobile.SendLocalizedMessage( - 1073220); // You must have completed the epic arcanist quest to use this ability. - return false; } - } - int mana = ScaleMana(RequiredMana); + public abstract double RequiredSkill { get; } + public abstract int RequiredMana { get; } - if (caster.Mana < mana) - { - caster.SendLocalizedMessage(1060174, - mana.ToString()); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability. - return false; - } + public override SkillName CastSkill => SkillName.Spellweaving; + public override SkillName DamageSkill => SkillName.Spellweaving; - if (caster.Skills[CastSkill].Value < RequiredSkill) - { - caster.SendLocalizedMessage(1063013, - $"{RequiredSkill:F1}\t{"#1044114"}"); // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability. - return false; - } + public override bool ClearHandsOnCast => false; - return true; + public virtual int FocusLevel => m_CastTimeFocusLevel; + + public static int GetFocusLevel(Mobile from) + { + var focus = FindArcaneFocus(from); + + return focus?.Deleted != false ? 0 : focus.StrengthBonus; + } + + public static ArcaneFocus FindArcaneFocus(Mobile from) => + from.Holding as ArcaneFocus ?? from.Backpack?.FindItemByType(); + + public static bool CheckExpansion(Mobile from) => + !(from is PlayerMobile) || from.NetState?.SupportsExpansion(Expansion.ML) == true; + + public override bool CheckCast() + { + if (!base.CheckCast()) + return false; + + var caster = Caster; + + if (!CheckExpansion(caster)) + { + caster.SendLocalizedMessage( + 1072176 + ); // You must upgrade to the Mondain's Legacy Expansion Pack before using that ability + return false; + } + + if (caster is PlayerMobile mobile) + { + var context = MLQuestSystem.GetContext(mobile); + + if (context?.Spellweaving != true) + { + mobile.SendLocalizedMessage( + 1073220 + ); // You must have completed the epic arcanist quest to use this ability. + return false; + } + } + + var mana = ScaleMana(RequiredMana); + + if (caster.Mana < mana) + { + caster.SendLocalizedMessage( + 1060174, + mana.ToString() + ); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability. + return false; + } + + if (caster.Skills[CastSkill].Value < RequiredSkill) + { + caster.SendLocalizedMessage( + 1063013, + $"{RequiredSkill:F1}\t{"#1044114"}" + ); // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability. + return false; + } + + return true; + } + + public override void GetCastSkills(out double min, out double max) + { + min = RequiredSkill - 12.5; // per 5 on Friday, 2/16/07 + max = RequiredSkill + 37.5; + } + + public override int GetMana() => RequiredMana; + + public override void DoFizzle() + { + Caster.PlaySound(0x1D6); + Caster.NextSpellTime = Core.TickCount; + } + + public override void DoHurtFizzle() + { + Caster.PlaySound(0x1D6); + } + + public override void OnDisturb(DisturbType type, bool message) + { + base.OnDisturb(type, message); + + if (message) + Caster.PlaySound(0x1D6); + } + + public override void OnBeginCast() + { + base.OnBeginCast(); + + SendCastEffect(); + m_CastTimeFocusLevel = GetFocusLevel(Caster); + } + + public virtual void SendCastEffect() + { + Caster.FixedEffect(0x37C4, 10, (int)(GetCastDelay().TotalSeconds * 28), 4, 3); + } + + public virtual bool CheckResisted(Mobile m) + { + var percent = + (50 + 2 * (GetResistSkill(m) - GetDamageSkill(Caster))) / + 100; // TODO: According to the guide this is it.. but.. is it correct per OSI? + + if (percent <= 0) + return false; + + if (percent >= 1.0) + return true; + + return percent >= Utility.RandomDouble(); + } } - - public override void GetCastSkills(out double min, out double max) - { - min = RequiredSkill - 12.5; // per 5 on Friday, 2/16/07 - max = RequiredSkill + 37.5; - } - - public override int GetMana() => RequiredMana; - - public override void DoFizzle() - { - Caster.PlaySound(0x1D6); - Caster.NextSpellTime = Core.TickCount; - } - - public override void DoHurtFizzle() - { - Caster.PlaySound(0x1D6); - } - - public override void OnDisturb(DisturbType type, bool message) - { - base.OnDisturb(type, message); - - if (message) - Caster.PlaySound(0x1D6); - } - - public override void OnBeginCast() - { - base.OnBeginCast(); - - SendCastEffect(); - m_CastTimeFocusLevel = GetFocusLevel(Caster); - } - - public virtual void SendCastEffect() - { - Caster.FixedEffect(0x37C4, 10, (int)(GetCastDelay().TotalSeconds * 28), 4, 3); - } - - public virtual bool CheckResisted(Mobile m) - { - double percent = - (50 + 2 * (GetResistSkill(m) - GetDamageSkill(Caster))) / - 100; // TODO: According to the guide this is it.. but.. is it correct per OSI? - - if (percent <= 0) - return false; - - if (percent >= 1.0) - return true; - - return percent >= Utility.RandomDouble(); - } - } } diff --git a/Projects/UOContent/Spells/Spellweaving/AttuneWeapon.cs b/Projects/UOContent/Spells/Spellweaving/AttuneWeapon.cs index d926a516a..35af05a5e 100644 --- a/Projects/UOContent/Spells/Spellweaving/AttuneWeapon.cs +++ b/Projects/UOContent/Spells/Spellweaving/AttuneWeapon.cs @@ -3,123 +3,129 @@ using System.Collections.Generic; namespace Server.Spells.Spellweaving { - public class AttuneWeaponSpell : ArcanistSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Attune Weapon", "Haeldril", - -1); - - private static readonly Dictionary m_Table = new Dictionary(); - - public AttuneWeaponSpell(Mobile caster, Item scroll = null) - : base(caster, scroll, m_Info) + public class AttuneWeaponSpell : ArcanistSpell { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Attune Weapon", + "Haeldril", + -1 + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.0); + private static readonly Dictionary m_Table = new Dictionary(); - public override double RequiredSkill => 0.0; - public override int RequiredMana => 24; - - public override bool CheckCast() - { - if (m_Table.ContainsKey(Caster)) - { - Caster.SendLocalizedMessage(501775); // This spell is already in effect. - return false; - } - - if (Caster.CanBeginAction()) - return base.CheckCast(); - - Caster.SendLocalizedMessage(1075124); // You must wait before casting that spell again. - return false; - } - - public override void OnCast() - { - if (CheckSequence()) - { - Caster.PlaySound(0x5C3); - Caster.FixedParticles(0x3728, 1, 13, 0x26B8, 0x455, 7, EffectLayer.Waist); - Caster.FixedParticles(0x3779, 1, 15, 0x251E, 0x3F, 7, EffectLayer.Waist); - - double skill = Caster.Skills.Spellweaving.Value; - - int damageAbsorb = (int)(18 + (skill - 10) / 10 * 3 + FocusLevel * 6); - Caster.MeleeDamageAbsorb = damageAbsorb; - - TimeSpan duration = TimeSpan.FromSeconds(60 + FocusLevel * 12); - - ExpireTimer t = new ExpireTimer(Caster, duration); - t.Start(); - - m_Table[Caster] = t; - - Caster.BeginAction(); - - BuffInfo.AddBuff(Caster, - new BuffInfo(BuffIcon.AttuneWeapon, 1075798, duration, Caster, damageAbsorb.ToString())); - } - - FinishSequence(); - } - - public static void TryAbsorb(Mobile defender, ref int damage) - { - if (damage == 0 || !IsAbsorbing(defender) || defender.MeleeDamageAbsorb <= 0) - return; - - int absorbed = Math.Min(damage, defender.MeleeDamageAbsorb); - - damage -= absorbed; - defender.MeleeDamageAbsorb -= absorbed; - - defender.SendLocalizedMessage(1075127, - $"{absorbed}\t{defender.MeleeDamageAbsorb}"); // ~1_damage~ point(s) of damage have been absorbed. A total of ~2_remaining~ point(s) of shielding remain. - - if (defender.MeleeDamageAbsorb <= 0) - StopAbsorbing(defender, true); - } - - public static bool IsAbsorbing(Mobile m) => m_Table.ContainsKey(m); - - public static void StopAbsorbing(Mobile m, bool message) - { - if (m_Table.TryGetValue(m, out ExpireTimer t)) - t.DoExpire(message); - } - - private class ExpireTimer : Timer - { - private readonly Mobile m_Mobile; - - public ExpireTimer(Mobile m, TimeSpan delay) - : base(delay) => - m_Mobile = m; - - protected override void OnTick() - { - DoExpire(true); - } - - public void DoExpire(bool message) - { - Stop(); - - m_Mobile.MeleeDamageAbsorb = 0; - - if (message) + public AttuneWeaponSpell(Mobile caster, Item scroll = null) + : base(caster, scroll, m_Info) { - m_Mobile.SendLocalizedMessage(1075126); // Your attunement fades. - m_Mobile.PlaySound(0x1F8); } - m_Table.Remove(m_Mobile); + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.0); - DelayCall(TimeSpan.FromSeconds(120), m_Mobile.EndAction); - BuffInfo.RemoveBuff(m_Mobile, BuffIcon.AttuneWeapon); - } + public override double RequiredSkill => 0.0; + public override int RequiredMana => 24; + + public override bool CheckCast() + { + if (m_Table.ContainsKey(Caster)) + { + Caster.SendLocalizedMessage(501775); // This spell is already in effect. + return false; + } + + if (Caster.CanBeginAction()) + return base.CheckCast(); + + Caster.SendLocalizedMessage(1075124); // You must wait before casting that spell again. + return false; + } + + public override void OnCast() + { + if (CheckSequence()) + { + Caster.PlaySound(0x5C3); + Caster.FixedParticles(0x3728, 1, 13, 0x26B8, 0x455, 7, EffectLayer.Waist); + Caster.FixedParticles(0x3779, 1, 15, 0x251E, 0x3F, 7, EffectLayer.Waist); + + var skill = Caster.Skills.Spellweaving.Value; + + var damageAbsorb = (int)(18 + (skill - 10) / 10 * 3 + FocusLevel * 6); + Caster.MeleeDamageAbsorb = damageAbsorb; + + var duration = TimeSpan.FromSeconds(60 + FocusLevel * 12); + + var t = new ExpireTimer(Caster, duration); + t.Start(); + + m_Table[Caster] = t; + + Caster.BeginAction(); + + BuffInfo.AddBuff( + Caster, + new BuffInfo(BuffIcon.AttuneWeapon, 1075798, duration, Caster, damageAbsorb.ToString()) + ); + } + + FinishSequence(); + } + + public static void TryAbsorb(Mobile defender, ref int damage) + { + if (damage == 0 || !IsAbsorbing(defender) || defender.MeleeDamageAbsorb <= 0) + return; + + var absorbed = Math.Min(damage, defender.MeleeDamageAbsorb); + + damage -= absorbed; + defender.MeleeDamageAbsorb -= absorbed; + + defender.SendLocalizedMessage( + 1075127, + $"{absorbed}\t{defender.MeleeDamageAbsorb}" + ); // ~1_damage~ point(s) of damage have been absorbed. A total of ~2_remaining~ point(s) of shielding remain. + + if (defender.MeleeDamageAbsorb <= 0) + StopAbsorbing(defender, true); + } + + public static bool IsAbsorbing(Mobile m) => m_Table.ContainsKey(m); + + public static void StopAbsorbing(Mobile m, bool message) + { + if (m_Table.TryGetValue(m, out var t)) + t.DoExpire(message); + } + + private class ExpireTimer : Timer + { + private readonly Mobile m_Mobile; + + public ExpireTimer(Mobile m, TimeSpan delay) + : base(delay) => + m_Mobile = m; + + protected override void OnTick() + { + DoExpire(true); + } + + public void DoExpire(bool message) + { + Stop(); + + m_Mobile.MeleeDamageAbsorb = 0; + + if (message) + { + m_Mobile.SendLocalizedMessage(1075126); // Your attunement fades. + m_Mobile.PlaySound(0x1F8); + } + + m_Table.Remove(m_Mobile); + + DelayCall(TimeSpan.FromSeconds(120), m_Mobile.EndAction); + BuffInfo.RemoveBuff(m_Mobile, BuffIcon.AttuneWeapon); + } + } } - } } diff --git a/Projects/UOContent/Spells/Spellweaving/EssenceOfWind.cs b/Projects/UOContent/Spells/Spellweaving/EssenceOfWind.cs index 9459a4e3e..858929ee4 100644 --- a/Projects/UOContent/Spells/Spellweaving/EssenceOfWind.cs +++ b/Projects/UOContent/Spells/Spellweaving/EssenceOfWind.cs @@ -3,115 +3,123 @@ using System.Collections.Generic; namespace Server.Spells.Spellweaving { - public class EssenceOfWindSpell : ArcanistSpell - { - private static readonly SpellInfo m_Info = new SpellInfo("Essence of Wind", "Anathrae", -1); - - private static readonly Dictionary m_Table = new Dictionary(); - - public EssenceOfWindSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class EssenceOfWindSpell : ArcanistSpell { - } + private static readonly SpellInfo m_Info = new SpellInfo("Essence of Wind", "Anathrae", -1); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(3.0); + private static readonly Dictionary m_Table = new Dictionary(); - public override double RequiredSkill => 52.0; - public override int RequiredMana => 40; - - public override void OnCast() - { - if (CheckSequence()) - { - Caster.PlaySound(0x5C6); - - int range = 5 + FocusLevel; - int damage = 25 + FocusLevel; - - double skill = Caster.Skills.Spellweaving.Value; - - TimeSpan duration = TimeSpan.FromSeconds((int)(skill / 24) + FocusLevel); - - int fcMalus = FocusLevel + 1; - int ssiMalus = 2 * (FocusLevel + 1); - - IPooledEnumerable eable = Caster.GetMobilesInRange(range); - - foreach (Mobile m in eable) + public EssenceOfWindSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - if (Caster == m || !Caster.InLOS(m) || !SpellHelper.ValidIndirectTarget(Caster, m) || - !Caster.CanBeHarmful(m, false)) - continue; - - Caster.DoHarmful(m); - - SpellHelper.Damage(this, m, damage, 0, 0, 100, 0, 0); - - if (CheckResisted(m)) - continue; - - m_Table[m] = new EssenceOfWindInfo(m, fcMalus, ssiMalus, duration); - - BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.EssenceOfWind, 1075802, duration, m, - $"{fcMalus.ToString()}\t{ssiMalus.ToString()}")); } - eable.Free(); - } + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(3.0); - FinishSequence(); + public override double RequiredSkill => 52.0; + public override int RequiredMana => 40; + + public override void OnCast() + { + if (CheckSequence()) + { + Caster.PlaySound(0x5C6); + + var range = 5 + FocusLevel; + var damage = 25 + FocusLevel; + + var skill = Caster.Skills.Spellweaving.Value; + + var duration = TimeSpan.FromSeconds((int)(skill / 24) + FocusLevel); + + var fcMalus = FocusLevel + 1; + var ssiMalus = 2 * (FocusLevel + 1); + + var eable = Caster.GetMobilesInRange(range); + + foreach (var m in eable) + { + if (Caster == m || !Caster.InLOS(m) || !SpellHelper.ValidIndirectTarget(Caster, m) || + !Caster.CanBeHarmful(m, false)) + continue; + + Caster.DoHarmful(m); + + SpellHelper.Damage(this, m, damage, 0, 0, 100, 0, 0); + + if (CheckResisted(m)) + continue; + + m_Table[m] = new EssenceOfWindInfo(m, fcMalus, ssiMalus, duration); + + BuffInfo.AddBuff( + m, + new BuffInfo( + BuffIcon.EssenceOfWind, + 1075802, + duration, + m, + $"{fcMalus.ToString()}\t{ssiMalus.ToString()}" + ) + ); + } + + eable.Free(); + } + + FinishSequence(); + } + + public static int GetFCMalus(Mobile m) => m_Table.TryGetValue(m, out var info) ? info.FCMalus : 0; + + public static int GetSSIMalus(Mobile m) => m_Table.TryGetValue(m, out var info) ? info.SSIMalus : 0; + + public static bool IsDebuffed(Mobile m) => m_Table.ContainsKey(m); + + public static void StopDebuffing(Mobile m, bool message) + { + if (m_Table.TryGetValue(m, out var info)) + info.Timer.DoExpire(message); + } + + private class EssenceOfWindInfo + { + public EssenceOfWindInfo(Mobile defender, int fcMalus, int ssiMalus, TimeSpan duration) + { + Defender = defender; + FCMalus = fcMalus; + SSIMalus = ssiMalus; + + Timer = new ExpireTimer(Defender, duration); + Timer.Start(); + } + + public Mobile Defender { get; } + + public int FCMalus { get; } + + public int SSIMalus { get; } + + public ExpireTimer Timer { get; } + } + + private class ExpireTimer : Timer + { + private readonly Mobile m_Mobile; + + public ExpireTimer(Mobile m, TimeSpan delay) : base(delay) => m_Mobile = m; + + protected override void OnTick() + { + DoExpire(true); + } + + public void DoExpire(bool message) + { + Stop(); + m_Table.Remove(m_Mobile); + + BuffInfo.RemoveBuff(m_Mobile, BuffIcon.EssenceOfWind); + } + } } - - public static int GetFCMalus(Mobile m) => m_Table.TryGetValue(m, out EssenceOfWindInfo info) ? info.FCMalus : 0; - - public static int GetSSIMalus(Mobile m) => m_Table.TryGetValue(m, out EssenceOfWindInfo info) ? info.SSIMalus : 0; - - public static bool IsDebuffed(Mobile m) => m_Table.ContainsKey(m); - - public static void StopDebuffing(Mobile m, bool message) - { - if (m_Table.TryGetValue(m, out EssenceOfWindInfo info)) - info.Timer.DoExpire(message); - } - - private class EssenceOfWindInfo - { - public EssenceOfWindInfo(Mobile defender, int fcMalus, int ssiMalus, TimeSpan duration) - { - Defender = defender; - FCMalus = fcMalus; - SSIMalus = ssiMalus; - - Timer = new ExpireTimer(Defender, duration); - Timer.Start(); - } - - public Mobile Defender { get; } - - public int FCMalus { get; } - - public int SSIMalus { get; } - - public ExpireTimer Timer { get; } - } - - private class ExpireTimer : Timer - { - private readonly Mobile m_Mobile; - - public ExpireTimer(Mobile m, TimeSpan delay) : base(delay) => m_Mobile = m; - - protected override void OnTick() - { - DoExpire(true); - } - - public void DoExpire(bool message) - { - Stop(); - m_Table.Remove(m_Mobile); - - BuffInfo.RemoveBuff(m_Mobile, BuffIcon.EssenceOfWind); - } - } - } } diff --git a/Projects/UOContent/Spells/Spellweaving/EtherealVoyage.cs b/Projects/UOContent/Spells/Spellweaving/EtherealVoyage.cs index 94085c6c3..bd339c034 100644 --- a/Projects/UOContent/Spells/Spellweaving/EtherealVoyage.cs +++ b/Projects/UOContent/Spells/Spellweaving/EtherealVoyage.cs @@ -2,76 +2,79 @@ using System; namespace Server.Spells.Spellweaving { - public class EtherealVoyageSpell : ArcaneForm - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Ethereal Voyage", "Orlavdra", - -1); - - public EtherealVoyageSpell(Mobile caster, Item scroll = null) - : base(caster, scroll, m_Info) + public class EtherealVoyageSpell : ArcaneForm { + private static readonly SpellInfo m_Info = new SpellInfo( + "Ethereal Voyage", + "Orlavdra", + -1 + ); + + public EtherealVoyageSpell(Mobile caster, Item scroll = null) + : base(caster, scroll, m_Info) + { + } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(3.5); + + public override double RequiredSkill => 24.0; + public override int RequiredMana => 32; + + public override int Body => 0x302; + public override int Hue => 0x48F; + + public static void Initialize() + { + EventSink.AggressiveAction += RemoveTransformationOnAggressiveAction; + } + + public static void RemoveTransformationOnAggressiveAction(AggressiveActionEventArgs e) + { + if (TransformationSpellHelper.UnderTransformation(e.Aggressor, typeof(EtherealVoyageSpell))) + TransformationSpellHelper.RemoveContext(e.Aggressor, true); + } + + public override bool CheckCast() + { + if (TransformationSpellHelper.UnderTransformation(Caster, typeof(EtherealVoyageSpell))) + Caster.SendLocalizedMessage(501775); // This spell is already in effect. + else if (!Caster.CanBeginAction()) + Caster.SendLocalizedMessage(1075124); // You must wait before casting that spell again. + else if (Caster.Combatant != null) + Caster.SendLocalizedMessage(1072586); // You cannot cast Ethereal Voyage while you are in combat. + else + return base.CheckCast(); + + return false; + } + + public override void DoEffect(Mobile m) + { + m.PlaySound(0x5C8); + m.SendLocalizedMessage(1074770); // You are now under the effects of Ethereal Voyage. + + var skill = Caster.Skills.Spellweaving.Value; + + var duration = TimeSpan.FromSeconds(12 + (int)(skill / 24) + FocusLevel * 2); + + Timer.DelayCall(duration, RemoveEffect, Caster); + + Caster.BeginAction( + typeof(EtherealVoyageSpell) + ); // Cannot cast this spell for another 5 minutes(300sec) after effect removed. + + BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.EtherealVoyage, 1031613, 1075805, duration, Caster)); + } + + public override void RemoveEffect(Mobile m) + { + m.SendLocalizedMessage(1074771); // You are no longer under the effects of Ethereal Voyage. + + TransformationSpellHelper.RemoveContext(m, true); + + Timer.DelayCall(TimeSpan.FromMinutes(5), m.EndAction); + + BuffInfo.RemoveBuff(m, BuffIcon.EtherealVoyage); + } } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(3.5); - - public override double RequiredSkill => 24.0; - public override int RequiredMana => 32; - - public override int Body => 0x302; - public override int Hue => 0x48F; - - public static void Initialize() - { - EventSink.AggressiveAction += RemoveTransformationOnAggressiveAction; - } - - public static void RemoveTransformationOnAggressiveAction(AggressiveActionEventArgs e) - { - if (TransformationSpellHelper.UnderTransformation(e.Aggressor, typeof(EtherealVoyageSpell))) - TransformationSpellHelper.RemoveContext(e.Aggressor, true); - } - - public override bool CheckCast() - { - if (TransformationSpellHelper.UnderTransformation(Caster, typeof(EtherealVoyageSpell))) - Caster.SendLocalizedMessage(501775); // This spell is already in effect. - else if (!Caster.CanBeginAction()) - Caster.SendLocalizedMessage(1075124); // You must wait before casting that spell again. - else if (Caster.Combatant != null) - Caster.SendLocalizedMessage(1072586); // You cannot cast Ethereal Voyage while you are in combat. - else - return base.CheckCast(); - - return false; - } - - public override void DoEffect(Mobile m) - { - m.PlaySound(0x5C8); - m.SendLocalizedMessage(1074770); // You are now under the effects of Ethereal Voyage. - - double skill = Caster.Skills.Spellweaving.Value; - - TimeSpan duration = TimeSpan.FromSeconds(12 + (int)(skill / 24) + FocusLevel * 2); - - Timer.DelayCall(duration, RemoveEffect, Caster); - - Caster.BeginAction( - typeof(EtherealVoyageSpell)); // Cannot cast this spell for another 5 minutes(300sec) after effect removed. - - BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.EtherealVoyage, 1031613, 1075805, duration, Caster)); - } - - public override void RemoveEffect(Mobile m) - { - m.SendLocalizedMessage(1074771); // You are no longer under the effects of Ethereal Voyage. - - TransformationSpellHelper.RemoveContext(m, true); - - Timer.DelayCall(TimeSpan.FromMinutes(5), m.EndAction); - - BuffInfo.RemoveBuff(m, BuffIcon.EtherealVoyage); - } - } } diff --git a/Projects/UOContent/Spells/Spellweaving/GiftOfLife.cs b/Projects/UOContent/Spells/Spellweaving/GiftOfLife.cs index a993af786..c91b26763 100644 --- a/Projects/UOContent/Spells/Spellweaving/GiftOfLife.cs +++ b/Projects/UOContent/Spells/Spellweaving/GiftOfLife.cs @@ -6,165 +6,175 @@ using Server.Targeting; namespace Server.Spells.Spellweaving { - public class GiftOfLifeSpell : ArcanistSpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Gift of Life", "Illorae", - -1); - - private static readonly Dictionary m_Table = new Dictionary(); - - public GiftOfLifeSpell(Mobile caster, Item scroll = null) - : base(caster, scroll, m_Info) + public class GiftOfLifeSpell : ArcanistSpell, ISpellTargetingMobile { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Gift of Life", + "Illorae", + -1 + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(4.0); + private static readonly Dictionary m_Table = new Dictionary(); - public override double RequiredSkill => 38.0; - public override int RequiredMana => 70; - - public double HitsScalar => (Caster.Skills.Spellweaving.Value / 2.4 + FocusLevel) / 100; - - public static void Initialize() - { - EventSink.PlayerDeath += HandleDeath; - } - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, 10); - } - - public void Target(Mobile m) - { - if (m == null) - Caster.SendLocalizedMessage(1072077); // You may only cast this spell on yourself or a bonded pet. - else if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (m.IsDeadBondedPet || !m.Alive) - { - // As per Osi: Nothing happens. - } - else if (m != Caster && !(m is BaseCreature bc && bc.IsBonded && bc.ControlMaster == Caster)) - Caster.SendLocalizedMessage(1072077); // You may only cast this spell on yourself or a bonded pet. - else if (m_Table.ContainsKey(m)) - Caster.SendLocalizedMessage(501775); // This spell is already in effect. - else if (CheckBSequence(m)) - { - if (Caster == m) + public GiftOfLifeSpell(Mobile caster, Item scroll = null) + : base(caster, scroll, m_Info) { - Caster.SendLocalizedMessage(1074774); // You weave powerful magic, protecting yourself from death. - } - else - { - Caster.SendLocalizedMessage(1074775); // You weave powerful magic, protecting your pet from death. - SpellHelper.Turn(Caster, m); } - m.PlaySound(0x244); - m.FixedParticles(0x3709, 1, 30, 0x26ED, 5, 2, EffectLayer.Waist); - m.FixedParticles(0x376A, 1, 30, 0x251E, 5, 3, EffectLayer.Waist); + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(4.0); - double skill = Caster.Skills.Spellweaving.Value; + public override double RequiredSkill => 38.0; + public override int RequiredMana => 70; - TimeSpan duration = TimeSpan.FromMinutes((int)(skill / 24) * 2 + FocusLevel); + public double HitsScalar => (Caster.Skills.Spellweaving.Value / 2.4 + FocusLevel) / 100; - ExpireTimer t = new ExpireTimer(m, duration, this); - t.Start(); - - m_Table[m] = t; - - BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.GiftOfLife, 1031615, 1075807, duration, m, null, true)); - } - - FinishSequence(); - } - - public static void HandleDeath(Mobile m) - { - if (m_Table.ContainsKey(m)) - Timer.DelayCall(TimeSpan.FromSeconds(Utility.RandomMinMax(2, 4)), HandleDeath_OnCallback, m); - } - - private static void HandleDeath_OnCallback(Mobile m) - { - if (!m_Table.TryGetValue(m, out ExpireTimer timer)) - return; - - double hitsScalar = timer.Spell.HitsScalar; - - if (m is BaseCreature pet && pet.IsDeadBondedPet) - { - Mobile master = pet.GetMaster(); - - if (master?.NetState != null && Utility.InUpdateRange(pet, master)) + public void Target(Mobile m) { - master.CloseGump(); - master.SendGump(new PetResurrectGump(master, pet, hitsScalar)); - } - else - { - List friends = pet.Friends; - - for (int i = 0; friends != null && i < friends.Count; i++) - { - Mobile friend = friends[i]; - - if (friend.NetState != null && Utility.InUpdateRange(pet, friend)) + if (m == null) { - friend.CloseGump(); - friend.SendGump(new PetResurrectGump(friend, pet)); - break; + Caster.SendLocalizedMessage(1072077); // You may only cast this spell on yourself or a bonded pet. } - } + else if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (m.IsDeadBondedPet || !m.Alive) + { + // As per Osi: Nothing happens. + } + else if (m != Caster && !(m is BaseCreature bc && bc.IsBonded && bc.ControlMaster == Caster)) + { + Caster.SendLocalizedMessage(1072077); // You may only cast this spell on yourself or a bonded pet. + } + else if (m_Table.ContainsKey(m)) + { + Caster.SendLocalizedMessage(501775); // This spell is already in effect. + } + else if (CheckBSequence(m)) + { + if (Caster == m) + { + Caster.SendLocalizedMessage(1074774); // You weave powerful magic, protecting yourself from death. + } + else + { + Caster.SendLocalizedMessage(1074775); // You weave powerful magic, protecting your pet from death. + SpellHelper.Turn(Caster, m); + } + + m.PlaySound(0x244); + m.FixedParticles(0x3709, 1, 30, 0x26ED, 5, 2, EffectLayer.Waist); + m.FixedParticles(0x376A, 1, 30, 0x251E, 5, 3, EffectLayer.Waist); + + var skill = Caster.Skills.Spellweaving.Value; + + var duration = TimeSpan.FromMinutes((int)(skill / 24) * 2 + FocusLevel); + + var t = new ExpireTimer(m, duration, this); + t.Start(); + + m_Table[m] = t; + + BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.GiftOfLife, 1031615, 1075807, duration, m, null, true)); + } + + FinishSequence(); } - } - else - { - m.CloseGump(); - m.SendGump(new ResurrectGump(m, hitsScalar)); - } - // Per OSI, buff is removed when gump sent, irregardless of online status or acceptance - timer.DoExpire(); + public static void Initialize() + { + EventSink.PlayerDeath += HandleDeath; + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, 10); + } + + public static void HandleDeath(Mobile m) + { + if (m_Table.ContainsKey(m)) + Timer.DelayCall(TimeSpan.FromSeconds(Utility.RandomMinMax(2, 4)), HandleDeath_OnCallback, m); + } + + private static void HandleDeath_OnCallback(Mobile m) + { + if (!m_Table.TryGetValue(m, out var timer)) + return; + + var hitsScalar = timer.Spell.HitsScalar; + + if (m is BaseCreature pet && pet.IsDeadBondedPet) + { + var master = pet.GetMaster(); + + if (master?.NetState != null && Utility.InUpdateRange(pet, master)) + { + master.CloseGump(); + master.SendGump(new PetResurrectGump(master, pet, hitsScalar)); + } + else + { + var friends = pet.Friends; + + for (var i = 0; friends != null && i < friends.Count; i++) + { + var friend = friends[i]; + + if (friend.NetState != null && Utility.InUpdateRange(pet, friend)) + { + friend.CloseGump(); + friend.SendGump(new PetResurrectGump(friend, pet)); + break; + } + } + } + } + else + { + m.CloseGump(); + m.SendGump(new ResurrectGump(m, hitsScalar)); + } + + // Per OSI, buff is removed when gump sent, irregardless of online status or acceptance + timer.DoExpire(); + } + + public static void OnLogin(Mobile m) + { + if (m?.Alive != false || m_Table[m] == null) + return; + + HandleDeath_OnCallback(m); + } + + private class ExpireTimer : Timer + { + private readonly Mobile m_Mobile; + + public ExpireTimer(Mobile m, TimeSpan delay, GiftOfLifeSpell spell) + : base(delay) + { + m_Mobile = m; + Spell = spell; + } + + public GiftOfLifeSpell Spell { get; } + + protected override void OnTick() + { + DoExpire(); + } + + public void DoExpire() + { + Stop(); + + m_Mobile.SendLocalizedMessage(1074776); // You are no longer protected with Gift of Life. + m_Table.Remove(m_Mobile); + + BuffInfo.RemoveBuff(m_Mobile, BuffIcon.GiftOfLife); + } + } } - - public static void OnLogin(Mobile m) - { - if (m?.Alive != false || m_Table[m] == null) - return; - - HandleDeath_OnCallback(m); - } - - private class ExpireTimer : Timer - { - private readonly Mobile m_Mobile; - - public ExpireTimer(Mobile m, TimeSpan delay, GiftOfLifeSpell spell) - : base(delay) - { - m_Mobile = m; - Spell = spell; - } - - public GiftOfLifeSpell Spell { get; } - - protected override void OnTick() - { - DoExpire(); - } - - public void DoExpire() - { - Stop(); - - m_Mobile.SendLocalizedMessage(1074776); // You are no longer protected with Gift of Life. - m_Table.Remove(m_Mobile); - - BuffInfo.RemoveBuff(m_Mobile, BuffIcon.GiftOfLife); - } - } - } } diff --git a/Projects/UOContent/Spells/Spellweaving/GiftOfRenewal.cs b/Projects/UOContent/Spells/Spellweaving/GiftOfRenewal.cs index 652c5b2e0..0c0dfe8ff 100644 --- a/Projects/UOContent/Spells/Spellweaving/GiftOfRenewal.cs +++ b/Projects/UOContent/Spells/Spellweaving/GiftOfRenewal.cs @@ -4,148 +4,160 @@ using Server.Targeting; namespace Server.Spells.Spellweaving { - public class GiftOfRenewalSpell : ArcanistSpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Gift of Renewal", "Olorisstra", - -1); - - private static readonly Dictionary m_Table = new Dictionary(); - - public GiftOfRenewalSpell(Mobile caster, Item scroll = null) - : base(caster, scroll, m_Info) + public class GiftOfRenewalSpell : ArcanistSpell, ISpellTargetingMobile { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Gift of Renewal", + "Olorisstra", + -1 + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(3.0); + private static readonly Dictionary m_Table = new Dictionary(); - public override double RequiredSkill => 0.0; - public override int RequiredMana => 24; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, 10); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (m_Table.ContainsKey(m)) - Caster.SendLocalizedMessage(501775); // This spell is already in effect. - else if (!Caster.CanBeginAction()) - Caster.SendLocalizedMessage(501789); // You must wait before trying again. - else if (CheckBSequence(m)) - { - SpellHelper.Turn(Caster, m); - - Caster.FixedEffect(0x374A, 10, 20); - Caster.PlaySound(0x5C9); - - if (m.Poisoned) + public GiftOfRenewalSpell(Mobile caster, Item scroll = null) + : base(caster, scroll, m_Info) { - m.CurePoison(m); } - else + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(3.0); + + public override double RequiredSkill => 0.0; + public override int RequiredMana => 24; + + public void Target(Mobile m) { - double skill = Caster.Skills.Spellweaving.Value; + if (m == null) + return; - int hitsPerRound = 5 + (int)(skill / 24) + FocusLevel; - TimeSpan duration = TimeSpan.FromSeconds(30 + FocusLevel * 10); - - GiftOfRenewalInfo info = new GiftOfRenewalInfo(Caster, m, hitsPerRound); - - Timer.DelayCall(duration, - () => + if (!Caster.CanSee(m)) { - if (StopEffect(m)) - { - m.PlaySound(0x455); - m.SendLocalizedMessage(1075071); // The Gift of Renewal has faded. - } - }); + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (m_Table.ContainsKey(m)) + { + Caster.SendLocalizedMessage(501775); // This spell is already in effect. + } + else if (!Caster.CanBeginAction()) + { + Caster.SendLocalizedMessage(501789); // You must wait before trying again. + } + else if (CheckBSequence(m)) + { + SpellHelper.Turn(Caster, m); - m_Table[m] = info; + Caster.FixedEffect(0x374A, 10, 20); + Caster.PlaySound(0x5C9); - Caster.BeginAction(); + if (m.Poisoned) + { + m.CurePoison(m); + } + else + { + var skill = Caster.Skills.Spellweaving.Value; - BuffInfo.AddBuff(m, - new BuffInfo(BuffIcon.GiftOfRenewal, 1031602, 1075797, duration, m, hitsPerRound.ToString())); + var hitsPerRound = 5 + (int)(skill / 24) + FocusLevel; + var duration = TimeSpan.FromSeconds(30 + FocusLevel * 10); + + var info = new GiftOfRenewalInfo(Caster, m, hitsPerRound); + + Timer.DelayCall( + duration, + () => + { + if (StopEffect(m)) + { + m.PlaySound(0x455); + m.SendLocalizedMessage(1075071); // The Gift of Renewal has faded. + } + } + ); + + m_Table[m] = info; + + Caster.BeginAction(); + + BuffInfo.AddBuff( + m, + new BuffInfo(BuffIcon.GiftOfRenewal, 1031602, 1075797, duration, m, hitsPerRound.ToString()) + ); + } + } + + FinishSequence(); } - } - FinishSequence(); - } - - public static bool StopEffect(Mobile m) - { - if (!m_Table.TryGetValue(m, out GiftOfRenewalInfo info)) - return false; - - m_Table.Remove(m); - - info.m_Timer.Stop(); - BuffInfo.RemoveBuff(m, BuffIcon.GiftOfRenewal); - - Timer.DelayCall(TimeSpan.FromSeconds(60), info.m_Caster.EndAction); - - return true; - } - - private class GiftOfRenewalInfo - { - public readonly Mobile m_Caster; - public readonly int m_HitsPerRound; - public readonly Mobile m_Mobile; - public readonly InternalTimer m_Timer; - - public GiftOfRenewalInfo(Mobile caster, Mobile mobile, int hitsPerRound) - { - m_Caster = caster; - m_Mobile = mobile; - m_HitsPerRound = hitsPerRound; - - m_Timer = new InternalTimer(this); - m_Timer.Start(); - } - } - - private class InternalTimer : Timer - { - private readonly GiftOfRenewalInfo m_GiftInfo; - - public InternalTimer(GiftOfRenewalInfo info) - : base(TimeSpan.FromSeconds(2.0), TimeSpan.FromSeconds(2.0)) => - m_GiftInfo = info; - - protected override void OnTick() - { - Mobile m = m_GiftInfo.m_Mobile; - - if (!m_Table.ContainsKey(m)) + public override void OnCast() { - Stop(); - return; + Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, 10); } - if (!m.Alive) + public static bool StopEffect(Mobile m) { - Stop(); - StopEffect(m); - return; + if (!m_Table.TryGetValue(m, out var info)) + return false; + + m_Table.Remove(m); + + info.m_Timer.Stop(); + BuffInfo.RemoveBuff(m, BuffIcon.GiftOfRenewal); + + Timer.DelayCall(TimeSpan.FromSeconds(60), info.m_Caster.EndAction); + + return true; } - if (m.Hits >= m.HitsMax) - return; + private class GiftOfRenewalInfo + { + public readonly Mobile m_Caster; + public readonly int m_HitsPerRound; + public readonly Mobile m_Mobile; + public readonly InternalTimer m_Timer; - int toHeal = m_GiftInfo.m_HitsPerRound; + public GiftOfRenewalInfo(Mobile caster, Mobile mobile, int hitsPerRound) + { + m_Caster = caster; + m_Mobile = mobile; + m_HitsPerRound = hitsPerRound; - SpellHelper.Heal(toHeal, m, m_GiftInfo.m_Caster); - m.FixedParticles(0x376A, 9, 32, 5005, EffectLayer.Waist); - } + m_Timer = new InternalTimer(this); + m_Timer.Start(); + } + } + + private class InternalTimer : Timer + { + private readonly GiftOfRenewalInfo m_GiftInfo; + + public InternalTimer(GiftOfRenewalInfo info) + : base(TimeSpan.FromSeconds(2.0), TimeSpan.FromSeconds(2.0)) => + m_GiftInfo = info; + + protected override void OnTick() + { + var m = m_GiftInfo.m_Mobile; + + if (!m_Table.ContainsKey(m)) + { + Stop(); + return; + } + + if (!m.Alive) + { + Stop(); + StopEffect(m); + return; + } + + if (m.Hits >= m.HitsMax) + return; + + var toHeal = m_GiftInfo.m_HitsPerRound; + + SpellHelper.Heal(toHeal, m, m_GiftInfo.m_Caster); + m.FixedParticles(0x376A, 9, 32, 5005, EffectLayer.Waist); + } + } } - } } diff --git a/Projects/UOContent/Spells/Spellweaving/ImmolatingWeapon.cs b/Projects/UOContent/Spells/Spellweaving/ImmolatingWeapon.cs index 359e227e1..34f6844c6 100644 --- a/Projects/UOContent/Spells/Spellweaving/ImmolatingWeapon.cs +++ b/Projects/UOContent/Spells/Spellweaving/ImmolatingWeapon.cs @@ -4,115 +4,118 @@ using Server.Items; namespace Server.Spells.Spellweaving { - public class ImmolatingWeaponSpell : ArcanistSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Immolating Weapon", "Thalshara", - -1); - - private static readonly Dictionary m_WeaponDamageTable = - new Dictionary(); - - public ImmolatingWeaponSpell(Mobile caster, Item scroll = null) - : base(caster, scroll, m_Info) + public class ImmolatingWeaponSpell : ArcanistSpell { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Immolating Weapon", + "Thalshara", + -1 + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.0); + private static readonly Dictionary m_WeaponDamageTable = + new Dictionary(); - public override double RequiredSkill => 10.0; - public override int RequiredMana => 32; - - public override bool CheckCast() - { - if (!(Caster.Weapon is BaseWeapon weapon) || weapon is Fists || weapon is BaseRanged) - { - Caster.SendLocalizedMessage(1060179); // You must be wielding a weapon to use this ability! - return false; - } - - return base.CheckCast(); - } - - public override void OnCast() - { - if (!(Caster.Weapon is BaseWeapon weapon) || weapon is Fists || weapon is BaseRanged) - { - Caster.SendLocalizedMessage(1060179); // You must be wielding a weapon to use this ability! - } - else if (CheckSequence()) - { - Caster.PlaySound(0x5CA); - Caster.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); - - if (!IsImmolating(weapon)) // On OSI, the effect is not re-applied + public ImmolatingWeaponSpell(Mobile caster, Item scroll = null) + : base(caster, scroll, m_Info) { - double skill = Caster.Skills.Spellweaving.Value; - - int duration = 10 + (int)(skill / 24) + FocusLevel; - int damage = 5 + (int)(skill / 24) + FocusLevel; - - Timer stopTimer = Timer.DelayCall(TimeSpan.FromSeconds(duration), StopImmolating, weapon); - - m_WeaponDamageTable[weapon] = new ImmolatingWeaponEntry(damage, stopTimer, Caster); - weapon.InvalidateProperties(); } - } - FinishSequence(); + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.0); + + public override double RequiredSkill => 10.0; + public override int RequiredMana => 32; + + public override bool CheckCast() + { + if (!(Caster.Weapon is BaseWeapon weapon) || weapon is Fists || weapon is BaseRanged) + { + Caster.SendLocalizedMessage(1060179); // You must be wielding a weapon to use this ability! + return false; + } + + return base.CheckCast(); + } + + public override void OnCast() + { + if (!(Caster.Weapon is BaseWeapon weapon) || weapon is Fists || weapon is BaseRanged) + { + Caster.SendLocalizedMessage(1060179); // You must be wielding a weapon to use this ability! + } + else if (CheckSequence()) + { + Caster.PlaySound(0x5CA); + Caster.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head); + + if (!IsImmolating(weapon)) // On OSI, the effect is not re-applied + { + var skill = Caster.Skills.Spellweaving.Value; + + var duration = 10 + (int)(skill / 24) + FocusLevel; + var damage = 5 + (int)(skill / 24) + FocusLevel; + + var stopTimer = Timer.DelayCall(TimeSpan.FromSeconds(duration), StopImmolating, weapon); + + m_WeaponDamageTable[weapon] = new ImmolatingWeaponEntry(damage, stopTimer, Caster); + weapon.InvalidateProperties(); + } + } + + FinishSequence(); + } + + public static bool IsImmolating(BaseWeapon weapon) => m_WeaponDamageTable.ContainsKey(weapon); + + public static int GetImmolatingDamage(BaseWeapon weapon) => + m_WeaponDamageTable.TryGetValue(weapon, out var entry) ? entry.m_Damage : 0; + + public static void DoEffect(BaseWeapon weapon, Mobile target) + { + Timer.DelayCall(TimeSpan.FromSeconds(0.25), FinishEffect, new DelayedEffectEntry(weapon, target)); + } + + private static void FinishEffect(DelayedEffectEntry effect) + { + if (m_WeaponDamageTable.TryGetValue(effect.m_Weapon, out var entry)) + AOS.Damage(effect.m_Target, entry.m_Caster, entry.m_Damage, 0, 100, 0, 0, 0); + } + + public static void StopImmolating(BaseWeapon weapon) + { + if (!m_WeaponDamageTable.TryGetValue(weapon, out var entry)) + return; + + entry.m_Caster?.PlaySound(0x27); + entry.m_Timer.Stop(); + m_WeaponDamageTable.Remove(weapon); + + weapon.InvalidateProperties(); + } + + private class ImmolatingWeaponEntry + { + public readonly Mobile m_Caster; + public readonly int m_Damage; + public readonly Timer m_Timer; + + public ImmolatingWeaponEntry(int damage, Timer stopTimer, Mobile caster) + { + m_Damage = damage; + m_Timer = stopTimer; + m_Caster = caster; + } + } + + private class DelayedEffectEntry + { + public readonly Mobile m_Target; + public readonly BaseWeapon m_Weapon; + + public DelayedEffectEntry(BaseWeapon weapon, Mobile target) + { + m_Weapon = weapon; + m_Target = target; + } + } } - - public static bool IsImmolating(BaseWeapon weapon) => m_WeaponDamageTable.ContainsKey(weapon); - - public static int GetImmolatingDamage(BaseWeapon weapon) => m_WeaponDamageTable.TryGetValue(weapon, out ImmolatingWeaponEntry entry) ? entry.m_Damage : 0; - - public static void DoEffect(BaseWeapon weapon, Mobile target) - { - Timer.DelayCall(TimeSpan.FromSeconds(0.25), FinishEffect, new DelayedEffectEntry(weapon, target)); - } - - private static void FinishEffect(DelayedEffectEntry effect) - { - if (m_WeaponDamageTable.TryGetValue(effect.m_Weapon, out ImmolatingWeaponEntry entry)) - AOS.Damage(effect.m_Target, entry.m_Caster, entry.m_Damage, 0, 100, 0, 0, 0); - } - - public static void StopImmolating(BaseWeapon weapon) - { - if (!m_WeaponDamageTable.TryGetValue(weapon, out ImmolatingWeaponEntry entry)) - return; - - entry.m_Caster?.PlaySound(0x27); - entry.m_Timer.Stop(); - m_WeaponDamageTable.Remove(weapon); - - weapon.InvalidateProperties(); - } - - private class ImmolatingWeaponEntry - { - public readonly Mobile m_Caster; - public readonly int m_Damage; - public readonly Timer m_Timer; - - public ImmolatingWeaponEntry(int damage, Timer stopTimer, Mobile caster) - { - m_Damage = damage; - m_Timer = stopTimer; - m_Caster = caster; - } - } - - private class DelayedEffectEntry - { - public readonly Mobile m_Target; - public readonly BaseWeapon m_Weapon; - - public DelayedEffectEntry(BaseWeapon weapon, Mobile target) - { - m_Weapon = weapon; - m_Target = target; - } - } - } } diff --git a/Projects/UOContent/Spells/Spellweaving/Items/ArcaneFocus.cs b/Projects/UOContent/Spells/Spellweaving/Items/ArcaneFocus.cs index ae68c3b93..f38d180d2 100644 --- a/Projects/UOContent/Spells/Spellweaving/Items/ArcaneFocus.cs +++ b/Projects/UOContent/Spells/Spellweaving/Items/ArcaneFocus.cs @@ -2,59 +2,59 @@ using System; namespace Server.Items { - public class ArcaneFocus : TransientItem - { - [Constructible] - public ArcaneFocus() - : this(TimeSpan.FromHours(1), 1) + public class ArcaneFocus : TransientItem { + [Constructible] + public ArcaneFocus() + : this(TimeSpan.FromHours(1), 1) + { + } + + [Constructible] + public ArcaneFocus(int lifeSpan, int strengthBonus) + : this(TimeSpan.FromSeconds(lifeSpan), strengthBonus) + { + } + + public ArcaneFocus(TimeSpan lifeSpan, int strengthBonus) : base(0x3155, lifeSpan) + { + LootType = LootType.Blessed; + StrengthBonus = strengthBonus; + } + + public ArcaneFocus(Serial serial) : base(serial) + { + } + + public override int LabelNumber => 1032629; // Arcane Focus + + [CommandProperty(AccessLevel.GameMaster)] + public int StrengthBonus { get; set; } + + public override TextDefinition InvalidTransferMessage => 1073480; // Your arcane focus disappears. + public override bool Nontransferable => true; + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + list.Add(1060485, StrengthBonus.ToString()); // strength bonus ~1_val~ + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(0); + + writer.Write(StrengthBonus); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + StrengthBonus = reader.ReadInt(); + } } - - [Constructible] - public ArcaneFocus(int lifeSpan, int strengthBonus) - : this(TimeSpan.FromSeconds(lifeSpan), strengthBonus) - { - } - - public ArcaneFocus(TimeSpan lifeSpan, int strengthBonus) : base(0x3155, lifeSpan) - { - LootType = LootType.Blessed; - StrengthBonus = strengthBonus; - } - - public ArcaneFocus(Serial serial) : base(serial) - { - } - - public override int LabelNumber => 1032629; // Arcane Focus - - [CommandProperty(AccessLevel.GameMaster)] - public int StrengthBonus { get; set; } - - public override TextDefinition InvalidTransferMessage => 1073480; // Your arcane focus disappears. - public override bool Nontransferable => true; - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - list.Add(1060485, StrengthBonus.ToString()); // strength bonus ~1_val~ - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - - writer.Write(StrengthBonus); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - StrengthBonus = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Spells/Spellweaving/Items/TransientItem.cs b/Projects/UOContent/Spells/Spellweaving/Items/TransientItem.cs index 8ae26b247..854604e7a 100644 --- a/Projects/UOContent/Spells/Spellweaving/Items/TransientItem.cs +++ b/Projects/UOContent/Spells/Spellweaving/Items/TransientItem.cs @@ -2,100 +2,102 @@ using System; namespace Server.Items { - public class TransientItem : Item - { - private Timer m_Timer; - - [Constructible] - public TransientItem(int itemID, TimeSpan lifeSpan) - : base(itemID) + public class TransientItem : Item { - CreationTime = DateTime.UtcNow; - LifeSpan = lifeSpan; + private Timer m_Timer; - m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5), CheckExpiry); + [Constructible] + public TransientItem(int itemID, TimeSpan lifeSpan) + : base(itemID) + { + CreationTime = DateTime.UtcNow; + LifeSpan = lifeSpan; + + m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5), CheckExpiry); + } + + public TransientItem(Serial serial) + : base(serial) + { + } + + [CommandProperty(AccessLevel.GameMaster)] + public TimeSpan LifeSpan { get; set; } + + [CommandProperty(AccessLevel.GameMaster)] + public DateTime CreationTime { get; set; } + + public override bool Nontransferable => true; + + public virtual TextDefinition InvalidTransferMessage => null; + + public override void HandleInvalidTransfer(Mobile from) + { + if (InvalidTransferMessage != null) + TextDefinition.SendMessageTo(from, InvalidTransferMessage); + + Delete(); + } + + public virtual void Expire(Mobile parent) + { + parent?.SendLocalizedMessage(1072515, Name ?? $"#{LabelNumber}"); // The ~1_name~ expired... + + Effects.PlaySound(GetWorldLocation(), Map, 0x201); + + Delete(); + } + + public virtual void SendTimeRemainingMessage(Mobile to) + { + to.SendLocalizedMessage( + 1072516, + $"{Name ?? $"#{LabelNumber}"}\t{(int)LifeSpan.TotalSeconds}" + ); // ~1_name~ will expire in ~2_val~ seconds! + } + + public override void OnDelete() + { + m_Timer?.Stop(); + + base.OnDelete(); + } + + public virtual void CheckExpiry() + { + if (CreationTime + LifeSpan < DateTime.UtcNow) + Expire(RootParent as Mobile); + else + InvalidateProperties(); + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + + var remaining = CreationTime + LifeSpan - DateTime.UtcNow; + + list.Add(1072517, ((int)remaining.TotalSeconds).ToString()); // Lifespan: ~1_val~ seconds + } + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + writer.Write(0); + + writer.Write(LifeSpan); + writer.Write(CreationTime); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + var version = reader.ReadInt(); + + LifeSpan = reader.ReadTimeSpan(); + CreationTime = reader.ReadDateTime(); + + m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5), CheckExpiry); + } } - - public TransientItem(Serial serial) - : base(serial) - { - } - - [CommandProperty(AccessLevel.GameMaster)] - public TimeSpan LifeSpan { get; set; } - - [CommandProperty(AccessLevel.GameMaster)] - public DateTime CreationTime { get; set; } - - public override bool Nontransferable => true; - - public virtual TextDefinition InvalidTransferMessage => null; - - public override void HandleInvalidTransfer(Mobile from) - { - if (InvalidTransferMessage != null) - TextDefinition.SendMessageTo(from, InvalidTransferMessage); - - Delete(); - } - - public virtual void Expire(Mobile parent) - { - parent?.SendLocalizedMessage(1072515, Name ?? $"#{LabelNumber}"); // The ~1_name~ expired... - - Effects.PlaySound(GetWorldLocation(), Map, 0x201); - - Delete(); - } - - public virtual void SendTimeRemainingMessage(Mobile to) - { - to.SendLocalizedMessage(1072516, - $"{Name ?? $"#{LabelNumber}"}\t{(int)LifeSpan.TotalSeconds}"); // ~1_name~ will expire in ~2_val~ seconds! - } - - public override void OnDelete() - { - m_Timer?.Stop(); - - base.OnDelete(); - } - - public virtual void CheckExpiry() - { - if (CreationTime + LifeSpan < DateTime.UtcNow) - Expire(RootParent as Mobile); - else - InvalidateProperties(); - } - - public override void GetProperties(ObjectPropertyList list) - { - base.GetProperties(list); - - TimeSpan remaining = CreationTime + LifeSpan - DateTime.UtcNow; - - list.Add(1072517, ((int)remaining.TotalSeconds).ToString()); // Lifespan: ~1_val~ seconds - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - - writer.Write(LifeSpan); - writer.Write(CreationTime); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - LifeSpan = reader.ReadTimeSpan(); - CreationTime = reader.ReadDateTime(); - - m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5), CheckExpiry); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Spells/Spellweaving/Mobiles/ArcaneFey.cs b/Projects/UOContent/Spells/Spellweaving/Mobiles/ArcaneFey.cs index 670bf2656..d93e03c44 100644 --- a/Projects/UOContent/Spells/Spellweaving/Mobiles/ArcaneFey.cs +++ b/Projects/UOContent/Spells/Spellweaving/Mobiles/ArcaneFey.cs @@ -1,62 +1,62 @@ namespace Server.Mobiles { - public class ArcaneFey : BaseCreature - { - [Constructible] - public ArcaneFey() : base(AIType.AI_Mage, FightMode.Evil, 10, 1, 0.2, 0.4) + public class ArcaneFey : BaseCreature { - Name = NameList.RandomName("pixie"); - Body = 128; - BaseSoundID = 0x467; + [Constructible] + public ArcaneFey() : base(AIType.AI_Mage, FightMode.Evil, 10, 1, 0.2, 0.4) + { + Name = NameList.RandomName("pixie"); + Body = 128; + BaseSoundID = 0x467; - SetStr(20); - SetDex(150); - SetInt(125); + SetStr(20); + SetDex(150); + SetInt(125); - SetDamage(9, 15); + SetDamage(9, 15); - SetDamageType(ResistanceType.Physical, 100); + SetDamageType(ResistanceType.Physical, 100); - SetResistance(ResistanceType.Physical, 80, 90); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 40, 50); - SetResistance(ResistanceType.Poison, 40, 50); - SetResistance(ResistanceType.Energy, 40, 50); + SetResistance(ResistanceType.Physical, 80, 90); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 40, 50); + SetResistance(ResistanceType.Energy, 40, 50); - SetSkill(SkillName.EvalInt, 70.1, 80.0); - SetSkill(SkillName.Magery, 70.1, 80.0); - SetSkill(SkillName.Meditation, 70.1, 80.0); - SetSkill(SkillName.MagicResist, 50.5, 100.0); - SetSkill(SkillName.Tactics, 10.1, 20.0); - SetSkill(SkillName.Wrestling, 10.1, 12.5); + SetSkill(SkillName.EvalInt, 70.1, 80.0); + SetSkill(SkillName.Magery, 70.1, 80.0); + SetSkill(SkillName.Meditation, 70.1, 80.0); + SetSkill(SkillName.MagicResist, 50.5, 100.0); + SetSkill(SkillName.Tactics, 10.1, 20.0); + SetSkill(SkillName.Wrestling, 10.1, 12.5); - Fame = 0; - Karma = 0; + Fame = 0; + Karma = 0; - ControlSlots = 1; + ControlSlots = 1; + } + + public ArcaneFey(Serial serial) : base(serial) + { + } + + public override string CorpseName => "a pixie corpse"; + public override double DispelDifficulty => 70.0; + public override double DispelFocus => 20.0; + + public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; + public override bool InitialInnocent => true; + + 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(); + } } - - public ArcaneFey(Serial serial) : base(serial) - { - } - - public override string CorpseName => "a pixie corpse"; - public override double DispelDifficulty => 70.0; - public override double DispelFocus => 20.0; - - public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead; - public override bool InitialInnocent => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Spells/Spellweaving/Mobiles/ArcaneFiend.cs b/Projects/UOContent/Spells/Spellweaving/Mobiles/ArcaneFiend.cs index 7eaa673b6..3b44cca14 100644 --- a/Projects/UOContent/Spells/Spellweaving/Mobiles/ArcaneFiend.cs +++ b/Projects/UOContent/Spells/Spellweaving/Mobiles/ArcaneFiend.cs @@ -1,63 +1,63 @@ namespace Server.Mobiles { - public class ArcaneFiend : BaseCreature - { - [Constructible] - public ArcaneFiend() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + public class ArcaneFiend : BaseCreature { - Body = 74; - BaseSoundID = 422; + [Constructible] + public ArcaneFiend() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 74; + BaseSoundID = 422; - SetStr(55); - SetDex(40); - SetInt(60); + SetStr(55); + SetDex(40); + SetInt(60); - SetDamage(10, 14); + SetDamage(10, 14); - SetDamageType(ResistanceType.Physical, 0); - SetDamageType(ResistanceType.Fire, 50); - SetDamageType(ResistanceType.Poison, 50); + SetDamageType(ResistanceType.Physical, 0); + SetDamageType(ResistanceType.Fire, 50); + SetDamageType(ResistanceType.Poison, 50); - SetResistance(ResistanceType.Physical, 25, 35); - SetResistance(ResistanceType.Fire, 40, 50); - SetResistance(ResistanceType.Cold, 20, 30); - SetResistance(ResistanceType.Poison, 30, 40); - SetResistance(ResistanceType.Energy, 30, 40); + SetResistance(ResistanceType.Physical, 25, 35); + SetResistance(ResistanceType.Fire, 40, 50); + SetResistance(ResistanceType.Cold, 20, 30); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 30, 40); - SetSkill(SkillName.EvalInt, 20.1, 30.0); - SetSkill(SkillName.Magery, 60.1, 70.0); - SetSkill(SkillName.MagicResist, 30.1, 50.0); - SetSkill(SkillName.Tactics, 42.1, 50.0); - SetSkill(SkillName.Wrestling, 40.1, 44.0); + SetSkill(SkillName.EvalInt, 20.1, 30.0); + SetSkill(SkillName.Magery, 60.1, 70.0); + SetSkill(SkillName.MagicResist, 30.1, 50.0); + SetSkill(SkillName.Tactics, 42.1, 50.0); + SetSkill(SkillName.Wrestling, 40.1, 44.0); - Fame = 0; - Karma = 0; + Fame = 0; + Karma = 0; - ControlSlots = 1; + ControlSlots = 1; + } + + public ArcaneFiend(Serial serial) : base(serial) + { + } + + public override string CorpseName => "an imp corpse"; + public override double DispelDifficulty => 70.0; + public override double DispelFocus => 20.0; + + public override PackInstinct PackInstinct => PackInstinct.Daemon; + public override bool BleedImmune => true; // TODO: Verify on OSI. Guide says this. + public override string DefaultName => "an imp"; + + 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(); + } } - - public ArcaneFiend(Serial serial) : base(serial) - { - } - - public override string CorpseName => "an imp corpse"; - public override double DispelDifficulty => 70.0; - public override double DispelFocus => 20.0; - - public override PackInstinct PackInstinct => PackInstinct.Daemon; - public override bool BleedImmune => true; // TODO: Verify on OSI. Guide says this. - public override string DefaultName => "an imp"; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Spells/Spellweaving/Mobiles/NatureFury.cs b/Projects/UOContent/Spells/Spellweaving/Mobiles/NatureFury.cs index 1e025704e..63dfc37d7 100644 --- a/Projects/UOContent/Spells/Spellweaving/Mobiles/NatureFury.cs +++ b/Projects/UOContent/Spells/Spellweaving/Mobiles/NatureFury.cs @@ -2,84 +2,84 @@ using System; namespace Server.Mobiles { - public class NatureFury : BaseCreature - { - [Constructible] - public NatureFury() - : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + public class NatureFury : BaseCreature { - Body = 0x33; - Hue = 0x4001; + [Constructible] + public NatureFury() + : base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4) + { + Body = 0x33; + Hue = 0x4001; - SetStr(150); - SetDex(150); - SetInt(100); + SetStr(150); + SetDex(150); + SetInt(100); - SetHits(80); - SetStam(250); - SetMana(0); + SetHits(80); + SetStam(250); + SetMana(0); - SetDamage(6, 8); + SetDamage(6, 8); - SetDamageType(ResistanceType.Poison, 100); - SetDamageType(ResistanceType.Physical, 0); - SetResistance(ResistanceType.Physical, 90); + SetDamageType(ResistanceType.Poison, 100); + SetDamageType(ResistanceType.Physical, 0); + SetResistance(ResistanceType.Physical, 90); - SetSkill(SkillName.Wrestling, 90.0); - SetSkill(SkillName.MagicResist, 70.0); - SetSkill(SkillName.Tactics, 100.0); + SetSkill(SkillName.Wrestling, 90.0); + SetSkill(SkillName.MagicResist, 70.0); + SetSkill(SkillName.Tactics, 100.0); - Fame = 0; - Karma = 0; + Fame = 0; + Karma = 0; - ControlSlots = 1; + ControlSlots = 1; + } + + public NatureFury(Serial serial) + : base(serial) + { + } + + public override bool DeleteCorpseOnDeath => Core.AOS; + public override bool IsHouseSummonable => true; + + public override double DispelDifficulty => 125.0; + public override double DispelFocus => 90.0; + + public override bool BleedImmune => true; + public override Poison PoisonImmune => Poison.Lethal; + + public override bool AlwaysMurderer => true; + public override string DefaultName => "a nature's fury"; + + public override void MoveToWorld(Point3D loc, Map map) + { + base.MoveToWorld(loc, map); + Timer.DelayCall(DoEffects); + } + + public void DoEffects() + { + FixedParticles(0x91C, 10, 180, 0x2543, 0, 0, EffectLayer.Waist); + PlaySound(0xE); + PlaySound(0x1BC); + + if (Alive && !Deleted) + Timer.DelayCall(TimeSpan.FromSeconds(7.0), DoEffects); + } + + 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(); + + Delete(); + } } - - public NatureFury(Serial serial) - : base(serial) - { - } - - public override bool DeleteCorpseOnDeath => Core.AOS; - public override bool IsHouseSummonable => true; - - public override double DispelDifficulty => 125.0; - public override double DispelFocus => 90.0; - - public override bool BleedImmune => true; - public override Poison PoisonImmune => Poison.Lethal; - - public override bool AlwaysMurderer => true; - public override string DefaultName => "a nature's fury"; - - public override void MoveToWorld(Point3D loc, Map map) - { - base.MoveToWorld(loc, map); - Timer.DelayCall(DoEffects); - } - - public void DoEffects() - { - FixedParticles(0x91C, 10, 180, 0x2543, 0, 0, EffectLayer.Waist); - PlaySound(0xE); - PlaySound(0x1BC); - - if (Alive && !Deleted) - Timer.DelayCall(TimeSpan.FromSeconds(7.0), DoEffects); - } - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - writer.Write(0); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - int version = reader.ReadInt(); - - Delete(); - } - } } diff --git a/Projects/UOContent/Spells/Spellweaving/NatureFury.cs b/Projects/UOContent/Spells/Spellweaving/NatureFury.cs index 24e4d4da5..93af2d754 100644 --- a/Projects/UOContent/Spells/Spellweaving/NatureFury.cs +++ b/Projects/UOContent/Spells/Spellweaving/NatureFury.cs @@ -5,90 +5,92 @@ using Server.Targeting; namespace Server.Spells.Spellweaving { - public class NatureFurySpell : ArcanistSpell, ISpellTargetingPoint3D - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Nature's Fury", "Rauvvrae", - -1, - false); - - public NatureFurySpell(Mobile caster, Item scroll = null) - : base(caster, scroll, m_Info) + public class NatureFurySpell : ArcanistSpell, ISpellTargetingPoint3D { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Nature's Fury", + "Rauvvrae", + -1, + false + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); - - public override double RequiredSkill => 0.0; - public override int RequiredMana => 24; - - public override bool CheckCast() - { - if (!base.CheckCast()) - return false; - - if (Caster.Followers + 1 > Caster.FollowersMax) - { - Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. - return false; - } - - return true; - } - - public override void OnCast() - { - Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, 10); - } - - public void Target(IPoint3D point) - { - Point3D p = new Point3D(point); - Map map = Caster.Map; - - if (map == null) - return; - - if (Region.Find(p, map).GetRegion()?.House?.IsFriend(Caster) == false) - return; - - if (!map.CanSpawnMobile(p.X, p.Y, p.Z)) - { - Caster.SendLocalizedMessage(501942); // That location is blocked. - } - else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) - { - TimeSpan duration = TimeSpan.FromSeconds(Caster.Skills.Spellweaving.Value / 24 + 25 + FocusLevel * 2); - - NatureFury nf = new NatureFury(); - BaseCreature.Summon(nf, false, Caster, p, 0x5CB, duration); - - new InternalTimer(nf).Start(); - } - - FinishSequence(); - } - - private class InternalTimer : Timer - { - private readonly NatureFury m_NatureFury; - - public InternalTimer(NatureFury nf) - : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0)) => - m_NatureFury = nf; - - protected override void OnTick() - { - if (m_NatureFury.Deleted || !m_NatureFury.Alive || m_NatureFury.DamageMin > 20) + public NatureFurySpell(Mobile caster, Item scroll = null) + : base(caster, scroll, m_Info) { - Stop(); } - else + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); + + public override double RequiredSkill => 0.0; + public override int RequiredMana => 24; + + public void Target(IPoint3D point) { - ++m_NatureFury.DamageMin; - ++m_NatureFury.DamageMax; + var p = new Point3D(point); + var map = Caster.Map; + + if (map == null) + return; + + if (Region.Find(p, map).GetRegion()?.House?.IsFriend(Caster) == false) + return; + + if (!map.CanSpawnMobile(p.X, p.Y, p.Z)) + { + Caster.SendLocalizedMessage(501942); // That location is blocked. + } + else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) + { + var duration = TimeSpan.FromSeconds(Caster.Skills.Spellweaving.Value / 24 + 25 + FocusLevel * 2); + + var nf = new NatureFury(); + BaseCreature.Summon(nf, false, Caster, p, 0x5CB, duration); + + new InternalTimer(nf).Start(); + } + + FinishSequence(); + } + + public override bool CheckCast() + { + if (!base.CheckCast()) + return false; + + if (Caster.Followers + 1 > Caster.FollowersMax) + { + Caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature. + return false; + } + + return true; + } + + public override void OnCast() + { + Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, 10); + } + + private class InternalTimer : Timer + { + private readonly NatureFury m_NatureFury; + + public InternalTimer(NatureFury nf) + : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0)) => + m_NatureFury = nf; + + protected override void OnTick() + { + if (m_NatureFury.Deleted || !m_NatureFury.Alive || m_NatureFury.DamageMin > 20) + { + Stop(); + } + else + { + ++m_NatureFury.DamageMin; + ++m_NatureFury.DamageMax; + } + } } - } } - } } diff --git a/Projects/UOContent/Spells/Spellweaving/ReaperForm.cs b/Projects/UOContent/Spells/Spellweaving/ReaperForm.cs index fdb91f157..0320216ea 100644 --- a/Projects/UOContent/Spells/Spellweaving/ReaperForm.cs +++ b/Projects/UOContent/Spells/Spellweaving/ReaperForm.cs @@ -3,53 +3,53 @@ using Server.Network; namespace Server.Spells.Spellweaving { - public class ReaperFormSpell : ArcaneForm - { - private static readonly SpellInfo m_Info = new SpellInfo("Reaper Form", "Tarisstree", -1); - - public ReaperFormSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class ReaperFormSpell : ArcaneForm { + private static readonly SpellInfo m_Info = new SpellInfo("Reaper Form", "Tarisstree", -1); + + public ReaperFormSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.5); + + public override double RequiredSkill => 24.0; + public override int RequiredMana => 34; + + public override int Body => 0x11D; + + public override int FireResistOffset => -25; + public override int PhysResistOffset => 5 + FocusLevel; + public override int ColdResistOffset => 5 + FocusLevel; + public override int PoisResistOffset => 5 + FocusLevel; + public override int NrgyResistOffset => 5 + FocusLevel; + + public virtual int SwingSpeedBonus => 10 + FocusLevel; + public virtual int SpellDamageBonus => 10 + FocusLevel; + + public static void Initialize() + { + EventSink.Login += OnLogin; + } + + public static void OnLogin(Mobile m) + { + var context = TransformationSpellHelper.GetContext(m); + + if (context?.Type == typeof(ReaperFormSpell)) + m.Send(SpeedControl.WalkSpeed); + } + + public override void DoEffect(Mobile m) + { + m.PlaySound(0x1BA); + + m.Send(SpeedControl.WalkSpeed); + } + + public override void RemoveEffect(Mobile m) + { + m.Send(SpeedControl.Disable); + } } - - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.5); - - public override double RequiredSkill => 24.0; - public override int RequiredMana => 34; - - public override int Body => 0x11D; - - public override int FireResistOffset => -25; - public override int PhysResistOffset => 5 + FocusLevel; - public override int ColdResistOffset => 5 + FocusLevel; - public override int PoisResistOffset => 5 + FocusLevel; - public override int NrgyResistOffset => 5 + FocusLevel; - - public virtual int SwingSpeedBonus => 10 + FocusLevel; - public virtual int SpellDamageBonus => 10 + FocusLevel; - - public static void Initialize() - { - EventSink.Login += OnLogin; - } - - public static void OnLogin(Mobile m) - { - TransformContext context = TransformationSpellHelper.GetContext(m); - - if (context?.Type == typeof(ReaperFormSpell)) - m.Send(SpeedControl.WalkSpeed); - } - - public override void DoEffect(Mobile m) - { - m.PlaySound(0x1BA); - - m.Send(SpeedControl.WalkSpeed); - } - - public override void RemoveEffect(Mobile m) - { - m.Send(SpeedControl.Disable); - } - } } diff --git a/Projects/UOContent/Spells/Spellweaving/SummonFey.cs b/Projects/UOContent/Spells/Spellweaving/SummonFey.cs index 4e2050953..d5cc55f3f 100644 --- a/Projects/UOContent/Spells/Spellweaving/SummonFey.cs +++ b/Projects/UOContent/Spells/Spellweaving/SummonFey.cs @@ -4,42 +4,45 @@ using Server.Mobiles; namespace Server.Spells.Spellweaving { - public class SummonFeySpell : ArcaneSummon - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Summon Fey", "Alalithra", - -1); - - public SummonFeySpell(Mobile caster, Item scroll = null) - : base(caster, scroll, m_Info) + public class SummonFeySpell : ArcaneSummon { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Summon Fey", + "Alalithra", + -1 + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); - - public override double RequiredSkill => 38.0; - public override int RequiredMana => 10; - - public override int Sound => 0x217; - - public override bool CheckSequence() - { - Mobile caster = Caster; - - // This is done after casting completes - if (caster is PlayerMobile mobile) - { - MLQuestContext context = MLQuestSystem.GetContext(mobile); - - if (context?.SummonFey != true) + public SummonFeySpell(Mobile caster, Item scroll = null) + : base(caster, scroll, m_Info) { - mobile.SendLocalizedMessage( - 1074563); // You haven't forged a friendship with the fey and are unable to summon their aid. - return false; } - } - return base.CheckSequence(); + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); + + public override double RequiredSkill => 38.0; + public override int RequiredMana => 10; + + public override int Sound => 0x217; + + public override bool CheckSequence() + { + var caster = Caster; + + // This is done after casting completes + if (caster is PlayerMobile mobile) + { + var context = MLQuestSystem.GetContext(mobile); + + if (context?.SummonFey != true) + { + mobile.SendLocalizedMessage( + 1074563 + ); // You haven't forged a friendship with the fey and are unable to summon their aid. + return false; + } + } + + return base.CheckSequence(); + } } - } } diff --git a/Projects/UOContent/Spells/Spellweaving/SummonFiend.cs b/Projects/UOContent/Spells/Spellweaving/SummonFiend.cs index 0c197b808..752c0716f 100644 --- a/Projects/UOContent/Spells/Spellweaving/SummonFiend.cs +++ b/Projects/UOContent/Spells/Spellweaving/SummonFiend.cs @@ -4,41 +4,43 @@ using Server.Mobiles; namespace Server.Spells.Spellweaving { - public class SummonFiendSpell : ArcaneSummon - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Summon Fiend", "Nylisstra", - -1); - - public SummonFiendSpell(Mobile caster, Item scroll = null) - : base(caster, scroll, m_Info) + public class SummonFiendSpell : ArcaneSummon { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Summon Fiend", + "Nylisstra", + -1 + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.0); - - public override double RequiredSkill => 38.0; - public override int RequiredMana => 10; - - public override int Sound => 0x216; - - public override bool CheckSequence() - { - Mobile caster = Caster; - - // This is done after casting completes - if (caster is PlayerMobile mobile) - { - MLQuestContext context = MLQuestSystem.GetContext(mobile); - - if (context?.SummonFiend != true) + public SummonFiendSpell(Mobile caster, Item scroll = null) + : base(caster, scroll, m_Info) { - mobile.SendLocalizedMessage(1074564); // You haven't demonstrated mastery to summon a fiend. - return false; } - } - return base.CheckSequence(); + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(2.0); + + public override double RequiredSkill => 38.0; + public override int RequiredMana => 10; + + public override int Sound => 0x216; + + public override bool CheckSequence() + { + var caster = Caster; + + // This is done after casting completes + if (caster is PlayerMobile mobile) + { + var context = MLQuestSystem.GetContext(mobile); + + if (context?.SummonFiend != true) + { + mobile.SendLocalizedMessage(1074564); // You haven't demonstrated mastery to summon a fiend. + return false; + } + } + + return base.CheckSequence(); + } } - } } diff --git a/Projects/UOContent/Spells/Spellweaving/Thunderstorm.cs b/Projects/UOContent/Spells/Spellweaving/Thunderstorm.cs index 2de6aea35..88e6f1b24 100644 --- a/Projects/UOContent/Spells/Spellweaving/Thunderstorm.cs +++ b/Projects/UOContent/Spells/Spellweaving/Thunderstorm.cs @@ -3,83 +3,87 @@ using System.Collections.Generic; namespace Server.Spells.Spellweaving { - public class ThunderstormSpell : ArcanistSpell - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Thunderstorm", "Erelonia", - -1); - - private static readonly Dictionary m_Table = new Dictionary(); - - public ThunderstormSpell(Mobile caster, Item scroll = null) - : base(caster, scroll, m_Info) + public class ThunderstormSpell : ArcanistSpell { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Thunderstorm", + "Erelonia", + -1 + ); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); + private static readonly Dictionary m_Table = new Dictionary(); - public override double RequiredSkill => 10.0; - public override int RequiredMana => 32; - - public override void OnCast() - { - if (CheckSequence()) - { - Caster.PlaySound(0x5CE); - - double skill = Caster.Skills.Spellweaving.Value; - - int damage = Math.Max(11, 10 + (int)(skill / 24)) + FocusLevel; - - int sdiBonus = AosAttributes.GetValue(Caster, AosAttribute.SpellDamage); - - int pvmDamage = damage * (100 + sdiBonus) / 100; - - int pvpDamage = damage * (100 + Math.Min(sdiBonus, 15)) / 100; - - int range = 2 + FocusLevel; - TimeSpan duration = TimeSpan.FromSeconds(5 + FocusLevel); - - IPooledEnumerable eable = Caster.GetMobilesInRange(range); - - foreach (Mobile m in eable) + public ThunderstormSpell(Mobile caster, Item scroll = null) + : base(caster, scroll, m_Info) { - if (Caster == m || !SpellHelper.ValidIndirectTarget(Caster, m) || !Caster.CanBeHarmful(m, false) || - !Caster.InLOS(m)) - continue; - - Caster.DoHarmful(m); - - Spell oldSpell = m.Spell as Spell; - - SpellHelper.Damage(this, m, m.Player && Caster.Player ? pvpDamage : pvmDamage, 0, 0, 0, 0, 100); - - if (oldSpell == null || oldSpell == m.Spell || CheckResisted(m)) - continue; - - m_Table[m] = Timer.DelayCall(duration, DoExpire, m); - - BuffInfo.AddBuff(m, - new BuffInfo(BuffIcon.Thunderstorm, 1075800, duration, m, GetCastRecoveryMalus(m))); } - eable.Free(); - } + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5); - FinishSequence(); + public override double RequiredSkill => 10.0; + public override int RequiredMana => 32; + + public override void OnCast() + { + if (CheckSequence()) + { + Caster.PlaySound(0x5CE); + + var skill = Caster.Skills.Spellweaving.Value; + + var damage = Math.Max(11, 10 + (int)(skill / 24)) + FocusLevel; + + var sdiBonus = AosAttributes.GetValue(Caster, AosAttribute.SpellDamage); + + var pvmDamage = damage * (100 + sdiBonus) / 100; + + var pvpDamage = damage * (100 + Math.Min(sdiBonus, 15)) / 100; + + var range = 2 + FocusLevel; + var duration = TimeSpan.FromSeconds(5 + FocusLevel); + + var eable = Caster.GetMobilesInRange(range); + + foreach (var m in eable) + { + if (Caster == m || !SpellHelper.ValidIndirectTarget(Caster, m) || !Caster.CanBeHarmful(m, false) || + !Caster.InLOS(m)) + continue; + + Caster.DoHarmful(m); + + var oldSpell = m.Spell as Spell; + + SpellHelper.Damage(this, m, m.Player && Caster.Player ? pvpDamage : pvmDamage, 0, 0, 0, 0, 100); + + if (oldSpell == null || oldSpell == m.Spell || CheckResisted(m)) + continue; + + m_Table[m] = Timer.DelayCall(duration, DoExpire, m); + + BuffInfo.AddBuff( + m, + new BuffInfo(BuffIcon.Thunderstorm, 1075800, duration, m, GetCastRecoveryMalus(m)) + ); + } + + eable.Free(); + } + + FinishSequence(); + } + + public static int GetCastRecoveryMalus(Mobile m) => m_Table.ContainsKey(m) ? 6 : 0; + + public static void DoExpire(Mobile m) + { + if (!m_Table.TryGetValue(m, out var t)) + return; + + t.Stop(); + m_Table.Remove(m); + + BuffInfo.RemoveBuff(m, BuffIcon.Thunderstorm); + } } - - public static int GetCastRecoveryMalus(Mobile m) => m_Table.ContainsKey(m) ? 6 : 0; - - public static void DoExpire(Mobile m) - { - if (!m_Table.TryGetValue(m, out Timer t)) - return; - - t.Stop(); - m_Table.Remove(m); - - BuffInfo.RemoveBuff(m, BuffIcon.Thunderstorm); - } - } } diff --git a/Projects/UOContent/Spells/Spellweaving/WordOfDeath.cs b/Projects/UOContent/Spells/Spellweaving/WordOfDeath.cs index 16ed8cf2f..0f32f5bf9 100644 --- a/Projects/UOContent/Spells/Spellweaving/WordOfDeath.cs +++ b/Projects/UOContent/Spells/Spellweaving/WordOfDeath.cs @@ -3,66 +3,82 @@ using Server.Targeting; namespace Server.Spells.Spellweaving { - public class WordOfDeathSpell : ArcanistSpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo("Word of Death", "Nyraxle", -1); - - public WordOfDeathSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class WordOfDeathSpell : ArcanistSpell, ISpellTargetingMobile { - } + private static readonly SpellInfo m_Info = new SpellInfo("Word of Death", "Nyraxle", -1); - public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(3.5); - - public override double RequiredSkill => 80.0; - public override int RequiredMana => 50; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, 10); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (CheckHSequence(m)) - { - Point3D loc = m.Location; - loc.Z += 50; - - m.PlaySound(0x211); - m.FixedParticles(0x3779, 1, 30, 0x26EC, 0x3, 0x3, EffectLayer.Waist); - - Effects.SendMovingParticles(new Entity(Serial.Zero, loc, m.Map), new Entity(Serial.Zero, m.Location, m.Map), - 0xF5F, 1, 0, true, false, 0x21, 0x3F, 0x251D, 0, 0, EffectLayer.Head, 0); - - double percentage = 0.05 * FocusLevel; - - int damage; - - if (!m.Player && m.Hits / (double)m.HitsMax < percentage) + public WordOfDeathSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - damage = 300; - } - else - { - int minDamage = (int)Caster.Skills.Spellweaving.Value / 5; - int maxDamage = (int)Caster.Skills.Spellweaving.Value / 3; - damage = Utility.RandomMinMax(minDamage, maxDamage); - int damageBonus = AosAttributes.GetValue(Caster, AosAttribute.SpellDamage); - if (m.Player && damageBonus > 15) - damageBonus = 15; - damage *= damageBonus + 100; - damage /= 100; } - SpellHelper.Damage(this, m, damage, 0, 0, 0, 0, 0, 100); - } + public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(3.5); - FinishSequence(); + public override double RequiredSkill => 80.0; + public override int RequiredMana => 50; + + public void Target(Mobile m) + { + if (m == null) + return; + + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckHSequence(m)) + { + var loc = m.Location; + loc.Z += 50; + + m.PlaySound(0x211); + m.FixedParticles(0x3779, 1, 30, 0x26EC, 0x3, 0x3, EffectLayer.Waist); + + Effects.SendMovingParticles( + new Entity(Serial.Zero, loc, m.Map), + new Entity(Serial.Zero, m.Location, m.Map), + 0xF5F, + 1, + 0, + true, + false, + 0x21, + 0x3F, + 0x251D, + 0, + 0, + EffectLayer.Head, + 0 + ); + + var percentage = 0.05 * FocusLevel; + + int damage; + + if (!m.Player && m.Hits / (double)m.HitsMax < percentage) + { + damage = 300; + } + else + { + var minDamage = (int)Caster.Skills.Spellweaving.Value / 5; + var maxDamage = (int)Caster.Skills.Spellweaving.Value / 3; + damage = Utility.RandomMinMax(minDamage, maxDamage); + var damageBonus = AosAttributes.GetValue(Caster, AosAttribute.SpellDamage); + if (m.Player && damageBonus > 15) + damageBonus = 15; + damage *= damageBonus + 100; + damage /= 100; + } + + SpellHelper.Damage(this, m, damage, 0, 0, 0, 0, 0, 100); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, 10); + } } - } } diff --git a/Projects/UOContent/Spells/Targeting/IRecallSpell.cs b/Projects/UOContent/Spells/Targeting/IRecallSpell.cs index 6123cf40f..76ca6bd77 100644 --- a/Projects/UOContent/Spells/Targeting/IRecallSpell.cs +++ b/Projects/UOContent/Spells/Targeting/IRecallSpell.cs @@ -1,9 +1,9 @@ namespace Server.Spells { - public interface IRecallSpell - { - Mobile Caster { get; } - void Effect(Point3D loc, Map map, bool checkMulti); - void FinishSequence(); - } + public interface IRecallSpell + { + Mobile Caster { get; } + void Effect(Point3D loc, Map map, bool checkMulti); + void FinishSequence(); + } } diff --git a/Projects/UOContent/Spells/Targeting/ISpellTarget.cs b/Projects/UOContent/Spells/Targeting/ISpellTarget.cs index 2779b1c85..9da3a893a 100644 --- a/Projects/UOContent/Spells/Targeting/ISpellTarget.cs +++ b/Projects/UOContent/Spells/Targeting/ISpellTarget.cs @@ -1,7 +1,7 @@ namespace Server.Spells { - public interface ISpellTarget - { - ISpell Spell { get; } - } + public interface ISpellTarget + { + ISpell Spell { get; } + } } diff --git a/Projects/UOContent/Spells/Targeting/RecallSpellTarget.cs b/Projects/UOContent/Spells/Targeting/RecallSpellTarget.cs index 8c3863601..11753e2d5 100644 --- a/Projects/UOContent/Spells/Targeting/RecallSpellTarget.cs +++ b/Projects/UOContent/Spells/Targeting/RecallSpellTarget.cs @@ -5,62 +5,82 @@ using Server.Targeting; namespace Server.Spells { - public class RecallSpellTarget : Target - { - private readonly IRecallSpell m_Spell; - private readonly bool m_ToBoat; - - public RecallSpellTarget(IRecallSpell spell, bool toBoat = true) : base(Core.ML ? 10 : 12, false, TargetFlags.None) + public class RecallSpellTarget : Target { - m_Spell = spell; - m_ToBoat = toBoat; - m_Spell.Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, 501029); // Select Marked item. - } + private readonly IRecallSpell m_Spell; + private readonly bool m_ToBoat; - protected override void OnTarget(Mobile from, object o) - { - if (o is RecallRune rune) - { - if (rune.Marked) - m_Spell.Effect(rune.Target, rune.TargetMap, true); - else - from.SendLocalizedMessage(501805); // That rune is not yet marked. - } - else if (o is Runebook runebook) - { - RunebookEntry e = runebook.Default; + public RecallSpellTarget(IRecallSpell spell, bool toBoat = true) : base(Core.ML ? 10 : 12, false, TargetFlags.None) + { + m_Spell = spell; + m_ToBoat = toBoat; + m_Spell.Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, 501029); // Select Marked item. + } - if (e != null) - m_Spell.Effect(e.Location, e.Map, true); - else - from.SendLocalizedMessage(502354); // Target is not marked. - } - else if (m_ToBoat && o is Key key && key.KeyValue != 0 && key.Link is BaseBoat boat) - { - if (!boat.Deleted && boat.CheckKey(key.KeyValue)) - m_Spell.Effect(boat.GetMarkedLocation(), boat.Map, false); - else - from.Send(new MessageLocalized(from.Serial, from.Body, MessageType.Regular, 0x3B2, 3, 502357, - from.Name, "")); // I can not recall from that object. - } - else if (o is HouseRaffleDeed deed && deed.ValidLocation()) - { - m_Spell.Effect(deed.PlotLocation, deed.PlotFacet, true); - } - else - { - from.Send(new MessageLocalized(from.Serial, from.Body, MessageType.Regular, 0x3B2, 3, 502357, from.Name, - "")); // I can not recall from that object. - } - } + protected override void OnTarget(Mobile from, object o) + { + if (o is RecallRune rune) + { + if (rune.Marked) + m_Spell.Effect(rune.Target, rune.TargetMap, true); + else + from.SendLocalizedMessage(501805); // That rune is not yet marked. + } + else if (o is Runebook runebook) + { + var e = runebook.Default; - protected override void OnNonlocalTarget(Mobile from, object o) - { - } + if (e != null) + m_Spell.Effect(e.Location, e.Map, true); + else + from.SendLocalizedMessage(502354); // Target is not marked. + } + else if (m_ToBoat && o is Key key && key.KeyValue != 0 && key.Link is BaseBoat boat) + { + if (!boat.Deleted && boat.CheckKey(key.KeyValue)) + m_Spell.Effect(boat.GetMarkedLocation(), boat.Map, false); + else + from.Send( + new MessageLocalized( + from.Serial, + from.Body, + MessageType.Regular, + 0x3B2, + 3, + 502357, + from.Name, + "" + ) + ); // I can not recall from that object. + } + else if (o is HouseRaffleDeed deed && deed.ValidLocation()) + { + m_Spell.Effect(deed.PlotLocation, deed.PlotFacet, true); + } + else + { + from.Send( + new MessageLocalized( + from.Serial, + from.Body, + MessageType.Regular, + 0x3B2, + 3, + 502357, + from.Name, + "" + ) + ); // I can not recall from that object. + } + } - protected override void OnTargetFinish(Mobile from) - { - m_Spell?.FinishSequence(); + protected override void OnNonlocalTarget(Mobile from, object o) + { + } + + protected override void OnTargetFinish(Mobile from) + { + m_Spell?.FinishSequence(); + } } - } } diff --git a/Projects/UOContent/Spells/Targeting/SpellTargetItem.cs b/Projects/UOContent/Spells/Targeting/SpellTargetItem.cs index 62cefcde3..498d10a57 100644 --- a/Projects/UOContent/Spells/Targeting/SpellTargetItem.cs +++ b/Projects/UOContent/Spells/Targeting/SpellTargetItem.cs @@ -2,27 +2,29 @@ using Server.Targeting; namespace Server.Spells { - public interface ISpellTargetingItem : ISpell - { - void Target(Item item); - } - - public class SpellTargetItem : Target, ISpellTarget - { - private readonly ISpellTargetingItem m_Spell; - public ISpell Spell => m_Spell; - - public SpellTargetItem(ISpellTargetingItem spell, TargetFlags flags, int range = 12) : base(range, false, flags) => m_Spell = spell; - - protected override void OnTarget(Mobile from, object o) + public interface ISpellTargetingItem : ISpell { - if (o is Item item) - m_Spell.Target(item); + void Target(Item item); } - protected override void OnTargetFinish(Mobile from) + public class SpellTargetItem : Target, ISpellTarget { - m_Spell?.FinishSequence(); + private readonly ISpellTargetingItem m_Spell; + + public SpellTargetItem(ISpellTargetingItem spell, TargetFlags flags, int range = 12) : base(range, false, flags) => + m_Spell = spell; + + public ISpell Spell => m_Spell; + + protected override void OnTarget(Mobile from, object o) + { + if (o is Item item) + m_Spell.Target(item); + } + + protected override void OnTargetFinish(Mobile from) + { + m_Spell?.FinishSequence(); + } } - } } diff --git a/Projects/UOContent/Spells/Targeting/SpellTargetMobile.cs b/Projects/UOContent/Spells/Targeting/SpellTargetMobile.cs index 46f7bd32d..e5758e734 100644 --- a/Projects/UOContent/Spells/Targeting/SpellTargetMobile.cs +++ b/Projects/UOContent/Spells/Targeting/SpellTargetMobile.cs @@ -2,26 +2,28 @@ using Server.Targeting; namespace Server.Spells { - public interface ISpellTargetingMobile : ISpell - { - void Target(Mobile from); - } - - public class SpellTargetMobile : Target, ISpellTarget - { - private readonly ISpellTargetingMobile m_Spell; - public ISpell Spell => m_Spell; - - public SpellTargetMobile(ISpellTargetingMobile spell, TargetFlags flags, int range = 12) : base(range, false, flags) => m_Spell = spell; - - protected override void OnTarget(Mobile from, object o) + public interface ISpellTargetingMobile : ISpell { - m_Spell.Target(o as Mobile); + void Target(Mobile from); } - protected override void OnTargetFinish(Mobile from) + public class SpellTargetMobile : Target, ISpellTarget { - m_Spell?.FinishSequence(); + private readonly ISpellTargetingMobile m_Spell; + + public SpellTargetMobile(ISpellTargetingMobile spell, TargetFlags flags, int range = 12) : + base(range, false, flags) => m_Spell = spell; + + public ISpell Spell => m_Spell; + + protected override void OnTarget(Mobile from, object o) + { + m_Spell.Target(o as Mobile); + } + + protected override void OnTargetFinish(Mobile from) + { + m_Spell?.FinishSequence(); + } } - } } diff --git a/Projects/UOContent/Spells/Targeting/SpellTargetPoint3D.cs b/Projects/UOContent/Spells/Targeting/SpellTargetPoint3D.cs index f0c824159..f28b43998 100644 --- a/Projects/UOContent/Spells/Targeting/SpellTargetPoint3D.cs +++ b/Projects/UOContent/Spells/Targeting/SpellTargetPoint3D.cs @@ -3,44 +3,46 @@ using Server.Targeting; namespace Server.Spells { - public interface ISpellTargetingPoint3D : ISpell - { - void Target(IPoint3D p); - } - - public class SpellTargetPoint3D : Target - { - private ISpellTargetingPoint3D m_Spell; - public ISpell Spell => m_Spell; - - private readonly bool m_CheckLOS; - - public SpellTargetPoint3D(ISpellTargetingPoint3D spell, TargetFlags flags = TargetFlags.None, int range = 12, bool checkLOS = true) : base(range, true, flags) + public interface ISpellTargetingPoint3D : ISpell { - m_Spell = spell; - m_CheckLOS = checkLOS; + void Target(IPoint3D p); } - protected override void OnTarget(Mobile from, object o) + public class SpellTargetPoint3D : Target { - if (o is IPoint3D p) - m_Spell.Target(p); - } + private readonly bool m_CheckLOS; + private ISpellTargetingPoint3D m_Spell; - protected override void OnTargetOutOfLOS(Mobile from, object o) - { - if (!m_CheckLOS) - return; + public SpellTargetPoint3D( + ISpellTargetingPoint3D spell, TargetFlags flags = TargetFlags.None, int range = 12, bool checkLOS = true + ) : base(range, true, flags) + { + m_Spell = spell; + m_CheckLOS = checkLOS; + } - from.SendLocalizedMessage(501943); // Target cannot be seen. Try again. - from.Target = new SpellTargetPoint3D(m_Spell); - from.Target.BeginTimeout(from, TimeoutTime - DateTime.UtcNow); - m_Spell = null; // Needed? - } + public ISpell Spell => m_Spell; - protected override void OnTargetFinish(Mobile from) - { - m_Spell?.FinishSequence(); + protected override void OnTarget(Mobile from, object o) + { + if (o is IPoint3D p) + m_Spell.Target(p); + } + + protected override void OnTargetOutOfLOS(Mobile from, object o) + { + if (!m_CheckLOS) + return; + + from.SendLocalizedMessage(501943); // Target cannot be seen. Try again. + from.Target = new SpellTargetPoint3D(m_Spell); + from.Target.BeginTimeout(from, TimeoutTime - DateTime.UtcNow); + m_Spell = null; // Needed? + } + + protected override void OnTargetFinish(Mobile from) + { + m_Spell?.FinishSequence(); + } } - } } diff --git a/Projects/UOContent/Spells/Third/Bless.cs b/Projects/UOContent/Spells/Third/Bless.cs index e38874d65..b30f1df80 100644 --- a/Projects/UOContent/Spells/Third/Bless.cs +++ b/Projects/UOContent/Spells/Third/Bless.cs @@ -1,69 +1,72 @@ -using System; using Server.Engines.ConPVP; using Server.Targeting; namespace Server.Spells.Third { - public class BlessSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Bless", "Rel Sanct", - 203, - 9061, - Reagent.Garlic, - Reagent.MandrakeRoot); - - public BlessSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class BlessSpell : MagerySpell, ISpellTargetingMobile { + private static readonly SpellInfo m_Info = new SpellInfo( + "Bless", + "Rel Sanct", + 203, + 9061, + Reagent.Garlic, + Reagent.MandrakeRoot + ); + + public BlessSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.Third; + + public void Target(Mobile m) + { + if (m == null) + return; + + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckBSequence(m)) + { + SpellHelper.Turn(Caster, m); + + SpellHelper.AddStatBonus(Caster, m, StatType.Str); + SpellHelper.DisableSkillCheck = true; + SpellHelper.AddStatBonus(Caster, m, StatType.Dex); + SpellHelper.AddStatBonus(Caster, m, StatType.Int); + SpellHelper.DisableSkillCheck = false; + + m.FixedParticles(0x373A, 10, 15, 5018, EffectLayer.Waist); + m.PlaySound(0x1EA); + + var percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, false) * 100); + var length = SpellHelper.GetDuration(Caster, m); + + var args = $"{percentage}\t{percentage}\t{percentage}"; + + BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Bless, 1075847, 1075848, length, m, args)); + } + + FinishSequence(); + } + + public override bool CheckCast() + { + if (DuelContext.CheckSuddenDeath(Caster)) + { + Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); + return false; + } + + return base.CheckCast(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, Core.ML ? 10 : 12); + } } - - public override SpellCircle Circle => SpellCircle.Third; - - public override bool CheckCast() - { - if (DuelContext.CheckSuddenDeath(Caster)) - { - Caster.SendMessage(0x22, "You cannot cast this spell when in sudden death."); - return false; - } - - return base.CheckCast(); - } - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (CheckBSequence(m)) - { - SpellHelper.Turn(Caster, m); - - SpellHelper.AddStatBonus(Caster, m, StatType.Str); - SpellHelper.DisableSkillCheck = true; - SpellHelper.AddStatBonus(Caster, m, StatType.Dex); - SpellHelper.AddStatBonus(Caster, m, StatType.Int); - SpellHelper.DisableSkillCheck = false; - - m.FixedParticles(0x373A, 10, 15, 5018, EffectLayer.Waist); - m.PlaySound(0x1EA); - - int percentage = (int)(SpellHelper.GetOffsetScalar(Caster, m, false) * 100); - TimeSpan length = SpellHelper.GetDuration(Caster, m); - - string args = $"{percentage}\t{percentage}\t{percentage}"; - - BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Bless, 1075847, 1075848, length, m, args)); - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Third/Fireball.cs b/Projects/UOContent/Spells/Third/Fireball.cs index 827e3f145..6870fd0a8 100644 --- a/Projects/UOContent/Spells/Third/Fireball.cs +++ b/Projects/UOContent/Spells/Third/Fireball.cs @@ -2,69 +2,73 @@ using Server.Targeting; namespace Server.Spells.Third { - public class FireballSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Fireball", "Vas Flam", - 203, - 9041, - Reagent.BlackPearl); - - public FireballSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class FireballSpell : MagerySpell, ISpellTargetingMobile { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Fireball", + "Vas Flam", + 203, + 9041, + Reagent.BlackPearl + ); - public override SpellCircle Circle => SpellCircle.Third; - - public override bool DelayedDamage => true; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (CheckHSequence(m)) - { - Mobile source = Caster; - - SpellHelper.Turn(source, m); - - SpellHelper.CheckReflect((int)Circle, ref source, ref m); - - double damage; - - if (Core.AOS) + public FireballSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - damage = GetNewAosDamage(19, 1, 5, m); - } - else - { - damage = Utility.Random(10, 7); - - if (CheckResisted(m)) - { - damage *= 0.75; - - m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. - } - - damage *= GetDamageScalar(m); } - source.MovingParticles(m, 0x36D4, 7, 0, false, true, 9502, 4019, 0x160); - source.PlaySound(Core.AOS ? 0x15E : 0x44B); + public override SpellCircle Circle => SpellCircle.Third; - SpellHelper.Damage(this, m, damage, 0, 100, 0, 0, 0); - } + public override bool DelayedDamage => true; - FinishSequence(); + public void Target(Mobile m) + { + if (m == null) + return; + + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckHSequence(m)) + { + var source = Caster; + + SpellHelper.Turn(source, m); + + SpellHelper.CheckReflect((int)Circle, ref source, ref m); + + double damage; + + if (Core.AOS) + { + damage = GetNewAosDamage(19, 1, 5, m); + } + else + { + damage = Utility.Random(10, 7); + + if (CheckResisted(m)) + { + damage *= 0.75; + + m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + } + + damage *= GetDamageScalar(m); + } + + source.MovingParticles(m, 0x36D4, 7, 0, false, true, 9502, 4019, 0x160); + source.PlaySound(Core.AOS ? 0x15E : 0x44B); + + SpellHelper.Damage(this, m, damage, 0, 100, 0, 0, 0); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } } - } } diff --git a/Projects/UOContent/Spells/Third/MagicLock.cs b/Projects/UOContent/Spells/Third/MagicLock.cs index 6e1bb1692..d72a8b2f1 100644 --- a/Projects/UOContent/Spells/Third/MagicLock.cs +++ b/Projects/UOContent/Spells/Third/MagicLock.cs @@ -5,55 +5,71 @@ using Server.Targeting; namespace Server.Spells.Third { - public class MagicLockSpell : MagerySpell, ISpellTargetingItem - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Magic Lock", "An Por", - 215, - 9001, - Reagent.Garlic, - Reagent.Bloodmoss, - Reagent.SulfurousAsh); - - public MagicLockSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class MagicLockSpell : MagerySpell, ISpellTargetingItem { + private static readonly SpellInfo m_Info = new SpellInfo( + "Magic Lock", + "An Por", + 215, + 9001, + Reagent.Garlic, + Reagent.Bloodmoss, + Reagent.SulfurousAsh + ); + + public MagicLockSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + { + } + + public override SpellCircle Circle => SpellCircle.Third; + + public void Target(Item item) + { + if (!(item is LockableContainer cont)) + { + Caster.SendLocalizedMessage(501762); // Target must be an unlocked chest. + } + else if (BaseHouse.CheckLockedDownOrSecured(cont)) + { + Caster.LocalOverheadMessage( + MessageType.Regular, + 0x22, + 501761 + ); // You cannot cast this on a locked down item. + } + else if (cont.Locked || cont.LockLevel == 0 || cont is ParagonChest) + { + Caster.SendLocalizedMessage(501762); // Target must be an unlocked chest. + } + else if (CheckSequence()) + { + SpellHelper.Turn(Caster, cont); + + var loc = cont.GetWorldLocation(); + + Effects.SendLocationParticles( + EffectItem.Create(loc, cont.Map, EffectItem.DefaultDuration), + 0x376A, + 9, + 32, + 5020 + ); + + Effects.PlaySound(loc, cont.Map, 0x1FA); + + // The chest is now locked! + Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, 501763); + + cont.LockLevel = -255; // signal magic lock + cont.Locked = true; + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetItem(this, TargetFlags.None, Core.ML ? 10 : 12); + } } - - public override SpellCircle Circle => SpellCircle.Third; - - public override void OnCast() - { - Caster.Target = new SpellTargetItem(this, TargetFlags.None, Core.ML ? 10 : 12); - } - - public void Target(Item item) - { - if (!(item is LockableContainer cont)) - Caster.SendLocalizedMessage(501762); // Target must be an unlocked chest. - else if (BaseHouse.CheckLockedDownOrSecured(cont)) - Caster.LocalOverheadMessage(MessageType.Regular, 0x22, 501761); // You cannot cast this on a locked down item. - else if (cont.Locked || cont.LockLevel == 0 || cont is ParagonChest) - Caster.SendLocalizedMessage(501762); // Target must be an unlocked chest. - else if (CheckSequence()) - { - SpellHelper.Turn(Caster, cont); - - Point3D loc = cont.GetWorldLocation(); - - Effects.SendLocationParticles( - EffectItem.Create(loc, cont.Map, EffectItem.DefaultDuration), - 0x376A, 9, 32, 5020); - - Effects.PlaySound(loc, cont.Map, 0x1FA); - - // The chest is now locked! - Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, 501763); - - cont.LockLevel = -255; // signal magic lock - cont.Locked = true; - } - - FinishSequence(); - } - } } diff --git a/Projects/UOContent/Spells/Third/Poison.cs b/Projects/UOContent/Spells/Third/Poison.cs index ef9255d77..f97ecda41 100644 --- a/Projects/UOContent/Spells/Third/Poison.cs +++ b/Projects/UOContent/Spells/Third/Poison.cs @@ -3,111 +3,116 @@ using Server.Targeting; namespace Server.Spells.Third { - public class PoisonSpell : MagerySpell, ISpellTargetingMobile - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Poison", "In Nox", - 203, - 9051, - Reagent.Nightshade); - - public PoisonSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class PoisonSpell : MagerySpell, ISpellTargetingMobile { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Poison", + "In Nox", + 203, + 9051, + Reagent.Nightshade + ); - public override SpellCircle Circle => SpellCircle.Third; - - public override void OnCast() - { - Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); - } - - public void Target(Mobile m) - { - if (m == null) - return; - - if (!Caster.CanSee(m)) - Caster.SendLocalizedMessage(500237); // Target can not be seen. - else if (CheckHSequence(m)) - { - SpellHelper.Turn(Caster, m); - - SpellHelper.CheckReflect((int)Circle, Caster, ref m); - - m.Spell?.OnCasterHurt(); - - m.Paralyzed = false; - - if (CheckResisted(m)) + public PoisonSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. - } - else - { - int level; - - if (Core.AOS) - { - if (Caster.InRange(m, 2)) - { - int total = (Caster.Skills.Magery.Fixed + Caster.Skills.Poisoning.Fixed) / 2; - - if (total >= 1000) - level = 3; - else if (total > 850) - level = 2; - else if (total > 650) - level = 1; - else - level = 0; - } - else - { - level = 0; - } - } - else - { - // double total = Caster.Skills.Magery.Value + Caster.Skills.Poisoning.Value; - - double total = Caster.Skills.Magery.Value; - - if (Caster is PlayerMobile pm) - { - if (pm.DuelContext?.Started != true || pm.DuelContext.Finished || pm.DuelContext.Ruleset.GetOption("Skills", "Poisoning")) - total += pm.Skills.Poisoning.Value; - } - else - { - total += Caster.Skills.Poisoning.Value; - } - - double dist = Caster.GetDistanceToSqrt(m); - - if (dist >= 3.0) - total -= (dist - 3.0) * 10.0; - - if (total >= 200.0 && Utility.Random(10) < 1) - level = 3; - else if (total > (Core.AOS ? 170.1 : 170.0)) - level = 2; - else if (total > (Core.AOS ? 130.1 : 130.0)) - level = 1; - else - level = 0; - } - - m.ApplyPoison(Caster, Poison.GetPoison(level)); } - m.FixedParticles(0x374A, 10, 15, 5021, EffectLayer.Waist); - m.PlaySound(0x205); + public override SpellCircle Circle => SpellCircle.Third; - HarmfulSpell(m); - } + public void Target(Mobile m) + { + if (m == null) + return; - FinishSequence(); + if (!Caster.CanSee(m)) + { + Caster.SendLocalizedMessage(500237); // Target can not be seen. + } + else if (CheckHSequence(m)) + { + SpellHelper.Turn(Caster, m); + + SpellHelper.CheckReflect((int)Circle, Caster, ref m); + + m.Spell?.OnCasterHurt(); + + m.Paralyzed = false; + + if (CheckResisted(m)) + { + m.SendLocalizedMessage(501783); // You feel yourself resisting magical energy. + } + else + { + int level; + + if (Core.AOS) + { + if (Caster.InRange(m, 2)) + { + var total = (Caster.Skills.Magery.Fixed + Caster.Skills.Poisoning.Fixed) / 2; + + if (total >= 1000) + level = 3; + else if (total > 850) + level = 2; + else if (total > 650) + level = 1; + else + level = 0; + } + else + { + level = 0; + } + } + else + { + // double total = Caster.Skills.Magery.Value + Caster.Skills.Poisoning.Value; + + var total = Caster.Skills.Magery.Value; + + if (Caster is PlayerMobile pm) + { + if (pm.DuelContext?.Started != true || pm.DuelContext.Finished || + pm.DuelContext.Ruleset.GetOption("Skills", "Poisoning")) + total += pm.Skills.Poisoning.Value; + } + else + { + total += Caster.Skills.Poisoning.Value; + } + + var dist = Caster.GetDistanceToSqrt(m); + + if (dist >= 3.0) + total -= (dist - 3.0) * 10.0; + + if (total >= 200.0 && Utility.Random(10) < 1) + level = 3; + else if (total > (Core.AOS ? 170.1 : 170.0)) + level = 2; + else if (total > (Core.AOS ? 130.1 : 130.0)) + level = 1; + else + level = 0; + } + + m.ApplyPoison(Caster, Poison.GetPoison(level)); + } + + m.FixedParticles(0x374A, 10, 15, 5021, EffectLayer.Waist); + m.PlaySound(0x205); + + HarmfulSpell(m); + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12); + } } - } } diff --git a/Projects/UOContent/Spells/Third/Telekinesis.cs b/Projects/UOContent/Spells/Third/Telekinesis.cs index 1416aa6ef..fb836c19f 100644 --- a/Projects/UOContent/Spells/Third/Telekinesis.cs +++ b/Projects/UOContent/Spells/Third/Telekinesis.cs @@ -3,80 +3,87 @@ using Server.Targeting; namespace Server.Spells.Third { - public class TelekinesisSpell : MagerySpell, ISpellTargetingItem - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Telekinesis", "Ort Por Ylem", - 203, - 9031, - Reagent.Bloodmoss, - Reagent.MandrakeRoot); - - public TelekinesisSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class TelekinesisSpell : MagerySpell, ISpellTargetingItem { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Telekinesis", + "Ort Por Ylem", + 203, + 9031, + Reagent.Bloodmoss, + Reagent.MandrakeRoot + ); - public override SpellCircle Circle => SpellCircle.Third; - - public override void OnCast() - { - Caster.Target = new SpellTargetItem(this, TargetFlags.None, Core.ML ? 10 : 12); - } - - public void Target(Item item) - { - ITelekinesisable t = item as ITelekinesisable; - if (!(t != null || item is Container)) - { - Caster.SendLocalizedMessage(501857); // This spell won't work on that! - return; - } - - if (CheckSequence()) - { - if (t != null) + public TelekinesisSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - SpellHelper.Turn(Caster, t); - t.OnTelekinesis(Caster); } - else + + public override SpellCircle Circle => SpellCircle.Third; + + public void Target(Item item) { - SpellHelper.Turn(Caster, item); + var t = item as ITelekinesisable; + if (!(t != null || item is Container)) + { + Caster.SendLocalizedMessage(501857); // This spell won't work on that! + return; + } - if (!item.IsAccessibleTo(Caster)) - { - item.OnDoubleClickNotAccessible(Caster); - } - else if (!item.CheckItemUse(Caster, item)) - { - } - else if (item.RootParent is Mobile && item.RootParent != Caster) - { - item.OnSnoop(Caster); - } - else if (item is Corpse corpse && !corpse.CheckLoot(Caster, null)) - { - } - else if (Caster.Region.OnDoubleClick(Caster, item)) - { - Effects.SendLocationParticles(EffectItem.Create(item.Location, item.Map, EffectItem.DefaultDuration), - 0x376A, 9, 32, 5022); - Effects.PlaySound(item.Location, item.Map, 0x1F5); + if (CheckSequence()) + { + if (t != null) + { + SpellHelper.Turn(Caster, t); + t.OnTelekinesis(Caster); + } + else + { + SpellHelper.Turn(Caster, item); - item.OnItemUsed(Caster, item); - } + if (!item.IsAccessibleTo(Caster)) + { + item.OnDoubleClickNotAccessible(Caster); + } + else if (!item.CheckItemUse(Caster, item)) + { + } + else if (item.RootParent is Mobile && item.RootParent != Caster) + { + item.OnSnoop(Caster); + } + else if (item is Corpse corpse && !corpse.CheckLoot(Caster, null)) + { + } + else if (Caster.Region.OnDoubleClick(Caster, item)) + { + Effects.SendLocationParticles( + EffectItem.Create(item.Location, item.Map, EffectItem.DefaultDuration), + 0x376A, + 9, + 32, + 5022 + ); + Effects.PlaySound(item.Location, item.Map, 0x1F5); + + item.OnItemUsed(Caster, item); + } + } + } + + FinishSequence(); } - } - FinishSequence(); + public override void OnCast() + { + Caster.Target = new SpellTargetItem(this, TargetFlags.None, Core.ML ? 10 : 12); + } } - } } namespace Server { - public interface ITelekinesisable : IPoint3D - { - void OnTelekinesis(Mobile from); - } + public interface ITelekinesisable : IPoint3D + { + void OnTelekinesis(Mobile from); + } } diff --git a/Projects/UOContent/Spells/Third/Teleport.cs b/Projects/UOContent/Spells/Third/Teleport.cs index 9b7d98032..fae747ae6 100644 --- a/Projects/UOContent/Spells/Third/Teleport.cs +++ b/Projects/UOContent/Spells/Third/Teleport.cs @@ -9,113 +9,125 @@ using Server.Targeting; namespace Server.Spells.Third { - public class TeleportSpell : MagerySpell, ISpellTargetingPoint3D - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Teleport", "Rel Por", - 215, - 9031, - Reagent.Bloodmoss, - Reagent.MandrakeRoot); - - public TeleportSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class TeleportSpell : MagerySpell, ISpellTargetingPoint3D { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Teleport", + "Rel Por", + 215, + 9031, + Reagent.Bloodmoss, + Reagent.MandrakeRoot + ); - public override SpellCircle Circle => SpellCircle.Third; - - public override bool CheckCast() - { - if (Sigil.ExistsOn(Caster)) - { - Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. - return false; - } - - if (WeightOverloading.IsOverloaded(Caster)) - { - Caster.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move. - return false; - } - - return SpellHelper.CheckTravel(Caster, TravelCheckType.TeleportFrom); - } - - public override void OnCast() - { - Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); - } - - public void Target(IPoint3D p) - { - IPoint3D orig = p; - Map map = Caster.Map; - - SpellHelper.GetSurfaceTop(ref p); - - Point3D from = Caster.Location; - Point3D to = new Point3D(p); - - if (Sigil.ExistsOn(Caster)) - { - Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. - } - else if (WeightOverloading.IsOverloaded(Caster)) - { - Caster.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move. - } - else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.TeleportFrom)) - { - } - else if (!SpellHelper.CheckTravel(Caster, map, to, TravelCheckType.TeleportTo)) - { - } - else if (map?.CanSpawnMobile(p.X, p.Y, p.Z) != true) - { - Caster.SendLocalizedMessage(501942); // That location is blocked. - } - else if (SpellHelper.CheckMulti(to, map)) - { - Caster.SendLocalizedMessage(502831); // Cannot teleport to that spot. - } - else if (Region.Find(to, map).IsPartOf()) - { - Caster.SendLocalizedMessage(502829); // Cannot teleport to that spot. - } - else if (CheckSequence()) - { - SpellHelper.Turn(Caster, orig); - - Mobile m = Caster; - - m.Location = to; - m.ProcessDelta(); - - if (m.Player) + public TeleportSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - Effects.SendLocationParticles(EffectItem.Create(from, m.Map, EffectItem.DefaultDuration), 0x3728, 10, 10, - 2023); - Effects.SendLocationParticles(EffectItem.Create(to, m.Map, EffectItem.DefaultDuration), 0x3728, 10, 10, - 5023); - } - else - { - m.FixedParticles(0x376A, 9, 32, 0x13AF, EffectLayer.Waist); } - m.PlaySound(0x1FE); + public override SpellCircle Circle => SpellCircle.Third; - IPooledEnumerable eable = m.GetItemsInRange(0); + public void Target(IPoint3D p) + { + var orig = p; + var map = Caster.Map; - foreach (Item item in eable) - if (item is ParalyzeFieldSpell.InternalItem || item is PoisonFieldSpell.InternalItem || - item is FireFieldSpell.FireFieldItem) - item.OnMoveOver(m); + SpellHelper.GetSurfaceTop(ref p); - eable.Free(); - } + var from = Caster.Location; + var to = new Point3D(p); - FinishSequence(); + if (Sigil.ExistsOn(Caster)) + { + Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. + } + else if (WeightOverloading.IsOverloaded(Caster)) + { + Caster.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move. + } + else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.TeleportFrom)) + { + } + else if (!SpellHelper.CheckTravel(Caster, map, to, TravelCheckType.TeleportTo)) + { + } + else if (map?.CanSpawnMobile(p.X, p.Y, p.Z) != true) + { + Caster.SendLocalizedMessage(501942); // That location is blocked. + } + else if (SpellHelper.CheckMulti(to, map)) + { + Caster.SendLocalizedMessage(502831); // Cannot teleport to that spot. + } + else if (Region.Find(to, map).IsPartOf()) + { + Caster.SendLocalizedMessage(502829); // Cannot teleport to that spot. + } + else if (CheckSequence()) + { + SpellHelper.Turn(Caster, orig); + + var m = Caster; + + m.Location = to; + m.ProcessDelta(); + + if (m.Player) + { + Effects.SendLocationParticles( + EffectItem.Create(from, m.Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 2023 + ); + Effects.SendLocationParticles( + EffectItem.Create(to, m.Map, EffectItem.DefaultDuration), + 0x3728, + 10, + 10, + 5023 + ); + } + else + { + m.FixedParticles(0x376A, 9, 32, 0x13AF, EffectLayer.Waist); + } + + m.PlaySound(0x1FE); + + var eable = m.GetItemsInRange(0); + + foreach (var item in eable) + if (item is ParalyzeFieldSpell.InternalItem || item is PoisonFieldSpell.InternalItem || + item is FireFieldSpell.FireFieldItem) + item.OnMoveOver(m); + + eable.Free(); + } + + FinishSequence(); + } + + public override bool CheckCast() + { + if (Sigil.ExistsOn(Caster)) + { + Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. + return false; + } + + if (WeightOverloading.IsOverloaded(Caster)) + { + Caster.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move. + return false; + } + + return SpellHelper.CheckTravel(Caster, TravelCheckType.TeleportFrom); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); + } } - } } diff --git a/Projects/UOContent/Spells/Third/Unlock.cs b/Projects/UOContent/Spells/Third/Unlock.cs index 6db454c97..2950b0868 100644 --- a/Projects/UOContent/Spells/Third/Unlock.cs +++ b/Projects/UOContent/Spells/Third/Unlock.cs @@ -5,70 +5,95 @@ using Server.Targeting; namespace Server.Spells.Third { - public class UnlockSpell : MagerySpell, ISpellTargetingPoint3D - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Unlock Spell", "Ex Por", - 215, - 9001, - Reagent.Bloodmoss, - Reagent.SulfurousAsh); - - public UnlockSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class UnlockSpell : MagerySpell, ISpellTargetingPoint3D { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Unlock Spell", + "Ex Por", + 215, + 9001, + Reagent.Bloodmoss, + Reagent.SulfurousAsh + ); - public override SpellCircle Circle => SpellCircle.Third; - - public override void OnCast() - { - Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); - } - - public void Target(IPoint3D p) - { - if (CheckSequence()) - { - SpellHelper.Turn(Caster, p); - - Effects.SendLocationParticles(EffectItem.Create(new Point3D(p), Caster.Map, EffectItem.DefaultDuration), - 0x376A, 9, 32, 5024); - - Effects.PlaySound(p, Caster.Map, 0x1FF); - - if (p is Mobile) - Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, 503101); // That did not need to be unlocked. - else if (!(p is LockableContainer cont)) - Caster.SendLocalizedMessage(501666); // You can't unlock that! - else + public UnlockSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - if (BaseHouse.CheckSecured(cont)) - Caster.SendLocalizedMessage(503098); // You cannot cast this on a secure item. - else if (!cont.Locked) - Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 503101); // That did not need to be unlocked. - else if (cont.LockLevel == 0) - Caster.SendLocalizedMessage(501666); // You can't unlock that! - else - { - int level = (int)(Caster.Skills.Magery.Value * 0.8) - 4; - - if (level >= cont.RequiredSkill && - !(cont is TreasureMapChest chest && chest.Level > 2)) - { - cont.Locked = false; - - if (cont.LockLevel == -255) - cont.LockLevel = cont.RequiredSkill - 10; - } - else - Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, - 503099); // My spell does not seem to have an effect on that lock. - } } - } - FinishSequence(); + public override SpellCircle Circle => SpellCircle.Third; + + public void Target(IPoint3D p) + { + if (CheckSequence()) + { + SpellHelper.Turn(Caster, p); + + Effects.SendLocationParticles( + EffectItem.Create(new Point3D(p), Caster.Map, EffectItem.DefaultDuration), + 0x376A, + 9, + 32, + 5024 + ); + + Effects.PlaySound(p, Caster.Map, 0x1FF); + + if (p is Mobile) + { + Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, 503101); // That did not need to be unlocked. + } + else if (!(p is LockableContainer cont)) + { + Caster.SendLocalizedMessage(501666); // You can't unlock that! + } + else + { + if (BaseHouse.CheckSecured(cont)) + { + Caster.SendLocalizedMessage(503098); // You cannot cast this on a secure item. + } + else if (!cont.Locked) + { + Caster.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 503101 + ); // That did not need to be unlocked. + } + else if (cont.LockLevel == 0) + { + Caster.SendLocalizedMessage(501666); // You can't unlock that! + } + else + { + var level = (int)(Caster.Skills.Magery.Value * 0.8) - 4; + + if (level >= cont.RequiredSkill && + !(cont is TreasureMapChest chest && chest.Level > 2)) + { + cont.Locked = false; + + if (cont.LockLevel == -255) + cont.LockLevel = cont.RequiredSkill - 10; + } + else + { + Caster.LocalOverheadMessage( + MessageType.Regular, + 0x3B2, + 503099 + ); // My spell does not seem to have an effect on that lock. + } + } + } + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); + } } - } } diff --git a/Projects/UOContent/Spells/Third/WallOfStone.cs b/Projects/UOContent/Spells/Third/WallOfStone.cs index 427adb8b9..9095c4b56 100644 --- a/Projects/UOContent/Spells/Third/WallOfStone.cs +++ b/Projects/UOContent/Spells/Third/WallOfStone.cs @@ -5,188 +5,190 @@ using Server.Targeting; namespace Server.Spells.Third { - public class WallOfStoneSpell : MagerySpell, ISpellTargetingPoint3D - { - private static readonly SpellInfo m_Info = new SpellInfo( - "Wall of Stone", "In Sanct Ylem", - 227, - 9011, - false, - Reagent.Bloodmoss, - Reagent.Garlic); - - public WallOfStoneSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) + public class WallOfStoneSpell : MagerySpell, ISpellTargetingPoint3D { - } + private static readonly SpellInfo m_Info = new SpellInfo( + "Wall of Stone", + "In Sanct Ylem", + 227, + 9011, + false, + Reagent.Bloodmoss, + Reagent.Garlic + ); - public override SpellCircle Circle => SpellCircle.Third; - - public override void OnCast() - { - Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); - } - - public void Target(IPoint3D p) - { - if (!Caster.CanSee(p)) - { - Caster.SendLocalizedMessage(500237); // Target can not be seen. - } - else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) - { - SpellHelper.Turn(Caster, p); - - SpellHelper.GetSurfaceTop(ref p); - - int dx = Caster.Location.X - p.X; - int dy = Caster.Location.Y - p.Y; - int rx = (dx - dy) * 44; - int ry = (dx + dy) * 44; - - bool eastToWest; - - if (rx >= 0 && ry >= 0) - eastToWest = false; - else if (rx >= 0) - eastToWest = true; - else if (ry >= 0) - eastToWest = true; - else - eastToWest = false; - - Effects.PlaySound(p, Caster.Map, 0x1F6); - - for (int i = -1; i <= 1; ++i) + public WallOfStoneSpell(Mobile caster, Item scroll = null) : base(caster, scroll, m_Info) { - Point3D loc = new Point3D(eastToWest ? p.X + i : p.X, eastToWest ? p.Y : p.Y + i, p.Z); - bool canFit = SpellHelper.AdjustField(ref loc, Caster.Map, 22, true); - - // Effects.SendLocationParticles( EffectItem.Create( loc, Caster.Map, EffectItem.DefaultDuration ), 0x376A, 9, 10, 5025 ); - - if (!canFit) - continue; - - Item item = new InternalItem(loc, Caster.Map, Caster); - - Effects.SendLocationParticles(item, 0x376A, 9, 10, 5025); - - // new InternalItem( loc, Caster.Map, Caster ); } - } - FinishSequence(); - } + public override SpellCircle Circle => SpellCircle.Third; - [DispellableField] - private class InternalItem : Item - { - private readonly Mobile m_Caster; - private DateTime m_End; - private Timer m_Timer; - - public InternalItem(Point3D loc, Map map, Mobile caster) : base(0x82) - { - Visible = false; - Movable = false; - - MoveToWorld(loc, map); - - m_Caster = caster; - - if (caster.InLOS(this)) - Visible = true; - else - Delete(); - - if (Deleted) - return; - - m_Timer = new InternalTimer(this, TimeSpan.FromSeconds(10.0)); - m_Timer.Start(); - - m_End = DateTime.UtcNow + TimeSpan.FromSeconds(10.0); - } - - public InternalItem(Serial serial) : base(serial) - { - } - - public override bool BlocksFit => true; - - public override void Serialize(IGenericWriter writer) - { - base.Serialize(writer); - - writer.Write(1); // version - - writer.WriteDeltaTime(m_End); - } - - public override void Deserialize(IGenericReader reader) - { - base.Deserialize(reader); - - int version = reader.ReadInt(); - - switch (version) + public void Target(IPoint3D p) { - case 1: + if (!Caster.CanSee(p)) { - m_End = reader.ReadDeltaTime(); - - m_Timer = new InternalTimer(this, m_End - DateTime.UtcNow); - m_Timer.Start(); - - break; + Caster.SendLocalizedMessage(500237); // Target can not be seen. } - case 0: + else if (SpellHelper.CheckTown(p, Caster) && CheckSequence()) { - TimeSpan duration = TimeSpan.FromSeconds(10.0); + SpellHelper.Turn(Caster, p); - m_Timer = new InternalTimer(this, duration); - m_Timer.Start(); + SpellHelper.GetSurfaceTop(ref p); - m_End = DateTime.UtcNow + duration; + var dx = Caster.Location.X - p.X; + var dy = Caster.Location.Y - p.Y; + var rx = (dx - dy) * 44; + var ry = (dx + dy) * 44; - break; + bool eastToWest; + + if (rx >= 0 && ry >= 0) + eastToWest = false; + else if (rx >= 0) + eastToWest = true; + else if (ry >= 0) + eastToWest = true; + else + eastToWest = false; + + Effects.PlaySound(p, Caster.Map, 0x1F6); + + for (var i = -1; i <= 1; ++i) + { + var loc = new Point3D(eastToWest ? p.X + i : p.X, eastToWest ? p.Y : p.Y + i, p.Z); + var canFit = SpellHelper.AdjustField(ref loc, Caster.Map, 22, true); + + // Effects.SendLocationParticles( EffectItem.Create( loc, Caster.Map, EffectItem.DefaultDuration ), 0x376A, 9, 10, 5025 ); + + if (!canFit) + continue; + + Item item = new InternalItem(loc, Caster.Map, Caster); + + Effects.SendLocationParticles(item, 0x376A, 9, 10, 5025); + + // new InternalItem( loc, Caster.Map, Caster ); + } + } + + FinishSequence(); + } + + public override void OnCast() + { + Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, Core.ML ? 10 : 12); + } + + [DispellableField] + private class InternalItem : Item + { + private readonly Mobile m_Caster; + private DateTime m_End; + private Timer m_Timer; + + public InternalItem(Point3D loc, Map map, Mobile caster) : base(0x82) + { + Visible = false; + Movable = false; + + MoveToWorld(loc, map); + + m_Caster = caster; + + if (caster.InLOS(this)) + Visible = true; + else + Delete(); + + if (Deleted) + return; + + m_Timer = new InternalTimer(this, TimeSpan.FromSeconds(10.0)); + m_Timer.Start(); + + m_End = DateTime.UtcNow + TimeSpan.FromSeconds(10.0); + } + + public InternalItem(Serial serial) : base(serial) + { + } + + public override bool BlocksFit => true; + + public override void Serialize(IGenericWriter writer) + { + base.Serialize(writer); + + writer.Write(1); // version + + writer.WriteDeltaTime(m_End); + } + + public override void Deserialize(IGenericReader reader) + { + base.Deserialize(reader); + + var version = reader.ReadInt(); + + switch (version) + { + case 1: + { + m_End = reader.ReadDeltaTime(); + + m_Timer = new InternalTimer(this, m_End - DateTime.UtcNow); + m_Timer.Start(); + + break; + } + case 0: + { + var duration = TimeSpan.FromSeconds(10.0); + + m_Timer = new InternalTimer(this, duration); + m_Timer.Start(); + + m_End = DateTime.UtcNow + duration; + + break; + } + } + } + + public override bool OnMoveOver(Mobile m) + { + if (m is PlayerMobile) + { + var noto = Notoriety.Compute(m_Caster, m); + if (noto == Notoriety.Enemy || noto == Notoriety.Ally) + return false; + } + + return base.OnMoveOver(m); + } + + public override void OnAfterDelete() + { + base.OnAfterDelete(); + + m_Timer?.Stop(); + } + + private class InternalTimer : Timer + { + private readonly InternalItem m_Item; + + public InternalTimer(InternalItem item, TimeSpan duration) : base(duration) + { + Priority = TimerPriority.OneSecond; + m_Item = item; + } + + protected override void OnTick() + { + m_Item.Delete(); + } } } - } - - public override bool OnMoveOver(Mobile m) - { - if (m is PlayerMobile) - { - int noto = Notoriety.Compute(m_Caster, m); - if (noto == Notoriety.Enemy || noto == Notoriety.Ally) - return false; - } - - return base.OnMoveOver(m); - } - - public override void OnAfterDelete() - { - base.OnAfterDelete(); - - m_Timer?.Stop(); - } - - private class InternalTimer : Timer - { - private readonly InternalItem m_Item; - - public InternalTimer(InternalItem item, TimeSpan duration) : base(duration) - { - Priority = TimerPriority.OneSecond; - m_Item = item; - } - - protected override void OnTick() - { - m_Item.Delete(); - } - } } - } } diff --git a/Projects/UOContent/Spells/UnsummonTimer.cs b/Projects/UOContent/Spells/UnsummonTimer.cs index 03ab22bce..f270eb08e 100644 --- a/Projects/UOContent/Spells/UnsummonTimer.cs +++ b/Projects/UOContent/Spells/UnsummonTimer.cs @@ -3,22 +3,22 @@ using Server.Mobiles; namespace Server.Spells { - internal class UnsummonTimer : Timer - { - private Mobile m_Caster; - private readonly BaseCreature m_Creature; - - public UnsummonTimer(Mobile caster, BaseCreature creature, TimeSpan delay) : base(delay) + internal class UnsummonTimer : Timer { - m_Caster = caster; - m_Creature = creature; - Priority = TimerPriority.OneSecond; - } + private readonly BaseCreature m_Creature; + private Mobile m_Caster; - protected override void OnTick() - { - if (!m_Creature.Deleted) - m_Creature.Delete(); + public UnsummonTimer(Mobile caster, BaseCreature creature, TimeSpan delay) : base(delay) + { + m_Caster = caster; + m_Creature = creature; + Priority = TimerPriority.OneSecond; + } + + protected override void OnTick() + { + if (!m_Creature.Deleted) + m_Creature.Delete(); + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Targets/BladedItemTarget.cs b/Projects/UOContent/Targets/BladedItemTarget.cs index c105cc35f..d72485019 100644 --- a/Projects/UOContent/Targets/BladedItemTarget.cs +++ b/Projects/UOContent/Targets/BladedItemTarget.cs @@ -1,5 +1,4 @@ using Server.Engines.Harvest; -using Server.Engines.Quests; using Server.Engines.Quests.Hag; using Server.Items; using Server.Mobiles; @@ -7,103 +6,103 @@ using Server.Targeting; namespace Server.Targets { - public class BladedItemTarget : Target - { - private readonly Item m_Item; - - public BladedItemTarget(Item item) : base(2, false, TargetFlags.None) => m_Item = item; - - protected override void OnTargetOutOfRange(Mobile from, object targeted) + public class BladedItemTarget : Target { - if (targeted is UnholyBone bone && from.InRange(bone, 12)) - bone.Carve(from, m_Item); - else - base.OnTargetOutOfRange(from, targeted); - } + private readonly Item m_Item; - protected override void OnTarget(Mobile from, object targeted) - { - if (m_Item.Deleted) - return; + public BladedItemTarget(Item item) : base(2, false, TargetFlags.None) => m_Item = item; - if (targeted is ICarvable carvable) - { - carvable.Carve(from, m_Item); - } - else if (targeted is SwampDragon pet && pet.HasBarding) - { - if (!pet.Controlled || pet.ControlMaster != from) - from.SendLocalizedMessage(1053022); // You cannot remove barding from a swamp dragon you do not own. - else - pet.HasBarding = false; - } - else - { - if (targeted is StaticTarget target) + protected override void OnTargetOutOfRange(Mobile from, object targeted) { - int itemID = target.ItemID; + if (targeted is UnholyBone bone && from.InRange(bone, 12)) + bone.Carve(from, m_Item); + else + base.OnTargetOutOfRange(from, targeted); + } - if (itemID == 0xD15 || itemID == 0xD16) // red mushroom - { - PlayerMobile player = from as PlayerMobile; - - QuestSystem qs = player?.Quest; - - if (qs is WitchApprenticeQuest) - { - FindIngredientObjective obj = qs.FindObjective(); - if (obj?.Completed == false && obj.Ingredient == Ingredient.RedMushrooms) - { - player.SendLocalizedMessage(1055036); // You slice a red cap mushroom from its stem. - obj.Complete(); + protected override void OnTarget(Mobile from, object targeted) + { + if (m_Item.Deleted) return; - } - } - } - } - HarvestSystem system = Lumberjacking.System; - HarvestDefinition def = Lumberjacking.System.GetDefinition(); - - if (!system.GetHarvestDetails(from, m_Item, targeted, out int tileID, out Map map, out Point3D loc)) - { - from.SendLocalizedMessage(500494); // You can't use a bladed item on that! - } - else if (!def.Validate(tileID)) - { - from.SendLocalizedMessage(500494); // You can't use a bladed item on that! - } - else - { - HarvestBank bank = def.GetBank(map, loc.X, loc.Y); - - if (bank == null) - return; - - if (bank.Current < 5) - { - from.SendLocalizedMessage(500493); // There's not enough wood here to harvest. - } - else - { - bank.Consume(5, from); - - Item item = new Kindling(); - - if (from.PlaceInBackpack(item)) + if (targeted is ICarvable carvable) { - from.SendLocalizedMessage(500491); // You put some kindling into your backpack. - from.SendLocalizedMessage(500492); // An axe would probably get you more wood. + carvable.Carve(from, m_Item); + } + else if (targeted is SwampDragon pet && pet.HasBarding) + { + if (!pet.Controlled || pet.ControlMaster != from) + from.SendLocalizedMessage(1053022); // You cannot remove barding from a swamp dragon you do not own. + else + pet.HasBarding = false; } else { - from.SendLocalizedMessage(500490); // You can't place any kindling into your backpack! + if (targeted is StaticTarget target) + { + var itemID = target.ItemID; - item.Delete(); + if (itemID == 0xD15 || itemID == 0xD16) // red mushroom + { + var player = from as PlayerMobile; + + var qs = player?.Quest; + + if (qs is WitchApprenticeQuest) + { + var obj = qs.FindObjective(); + if (obj?.Completed == false && obj.Ingredient == Ingredient.RedMushrooms) + { + player.SendLocalizedMessage(1055036); // You slice a red cap mushroom from its stem. + obj.Complete(); + return; + } + } + } + } + + HarvestSystem system = Lumberjacking.System; + var def = Lumberjacking.System.GetDefinition(); + + if (!system.GetHarvestDetails(from, m_Item, targeted, out var tileID, out var map, out var loc)) + { + from.SendLocalizedMessage(500494); // You can't use a bladed item on that! + } + else if (!def.Validate(tileID)) + { + from.SendLocalizedMessage(500494); // You can't use a bladed item on that! + } + else + { + var bank = def.GetBank(map, loc.X, loc.Y); + + if (bank == null) + return; + + if (bank.Current < 5) + { + from.SendLocalizedMessage(500493); // There's not enough wood here to harvest. + } + else + { + bank.Consume(5, from); + + Item item = new Kindling(); + + if (from.PlaceInBackpack(item)) + { + from.SendLocalizedMessage(500491); // You put some kindling into your backpack. + from.SendLocalizedMessage(500492); // An axe would probably get you more wood. + } + else + { + from.SendLocalizedMessage(500490); // You can't place any kindling into your backpack! + + item.Delete(); + } + } + } } - } } - } } - } } diff --git a/Projects/UOContent/Targets/MoveTarget.cs b/Projects/UOContent/Targets/MoveTarget.cs index d17c730f6..5d53bef34 100644 --- a/Projects/UOContent/Targets/MoveTarget.cs +++ b/Projects/UOContent/Targets/MoveTarget.cs @@ -4,39 +4,45 @@ using Server.Targeting; namespace Server.Targets { - public class MoveTarget : Target - { - private readonly object m_Object; - - public MoveTarget(object o) : base(-1, true, TargetFlags.None) => m_Object = o; - - protected override void OnTarget(Mobile from, object o) + public class MoveTarget : Target { - if (o is IPoint3D p) - { - if (!BaseCommand.IsAccessible(from, m_Object)) - { - from.SendLocalizedMessage(500447); // That is not accessible. - return; - } + private readonly object m_Object; - if (p is Item pItem) - p = pItem.GetWorldTop(); + public MoveTarget(object o) : base(-1, true, TargetFlags.None) => m_Object = o; - CommandLogging.WriteLine(from, "{0} {1} moving {2} to {3}", from.AccessLevel, CommandLogging.Format(from), - CommandLogging.Format(m_Object), new Point3D(p)); + protected override void OnTarget(Mobile from, object o) + { + if (o is IPoint3D p) + { + if (!BaseCommand.IsAccessible(from, m_Object)) + { + from.SendLocalizedMessage(500447); // That is not accessible. + return; + } - if (m_Object is Item item) - { - if (!item.Deleted) - item.MoveToWorld(new Point3D(p), from.Map); + if (p is Item pItem) + p = pItem.GetWorldTop(); + + CommandLogging.WriteLine( + from, + "{0} {1} moving {2} to {3}", + from.AccessLevel, + CommandLogging.Format(from), + CommandLogging.Format(m_Object), + new Point3D(p) + ); + + if (m_Object is Item item) + { + if (!item.Deleted) + item.MoveToWorld(new Point3D(p), from.Map); + } + else if (m_Object is Mobile m) + { + if (!m.Deleted) + m.MoveToWorld(new Point3D(p), from.Map); + } + } } - else if (m_Object is Mobile m) - { - if (!m.Deleted) - m.MoveToWorld(new Point3D(p), from.Map); - } - } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/Targets/PickMoveTarget.cs b/Projects/UOContent/Targets/PickMoveTarget.cs index 86c8aa760..424f2bacc 100644 --- a/Projects/UOContent/Targets/PickMoveTarget.cs +++ b/Projects/UOContent/Targets/PickMoveTarget.cs @@ -3,22 +3,22 @@ using Server.Targeting; namespace Server.Targets { - public class PickMoveTarget : Target - { - public PickMoveTarget() : base(-1, false, TargetFlags.None) + public class PickMoveTarget : Target { - } + public PickMoveTarget() : base(-1, false, TargetFlags.None) + { + } - protected override void OnTarget(Mobile from, object o) - { - if (!BaseCommand.IsAccessible(from, o)) - { - from.SendLocalizedMessage(500447); // That is not accessible. - return; - } + protected override void OnTarget(Mobile from, object o) + { + if (!BaseCommand.IsAccessible(from, o)) + { + from.SendLocalizedMessage(500447); // That is not accessible. + return; + } - if (o is Item || o is Mobile) - from.Target = new MoveTarget(o); + if (o is Item || o is Mobile) + from.Target = new MoveTarget(o); + } } - } -} \ No newline at end of file +} diff --git a/Projects/UOContent/packages.lock.json b/Projects/UOContent/packages.lock.json index c3397770a..6182f2980 100644 --- a/Projects/UOContent/packages.lock.json +++ b/Projects/UOContent/packages.lock.json @@ -7306,7312 +7306,6 @@ "runtime.any.System.Threading.Tasks": "4.3.0" } } - }, - ".NETCoreApp,Version=v5.0": { - "Argon2.Bindings": { - "type": "Direct", - "requested": "[1.6.0, )", - "resolved": "1.6.0", - "contentHash": "fj3n8L2UHJnQOfDy6phuJvu01u80TNEOx0Nkbtj7/G7pDmfRe0InLwHaQMmT59/8TOSDVLEDoi54D/yM8o7qZA==" - }, - "MailKit": { - "type": "Direct", - "requested": "[2.8.0, )", - "resolved": "2.8.0", - "contentHash": "oAbRyAfzymGSxOZRyDAeYwjZubWgj9b9e2CUp2bzMDMQ/2DRdvWkzSXIuVxLpR6QKA5MMixYkowyo1RSV16Atw==", - "dependencies": { - "MimeKit": "2.9.1", - "System.Net.NameResolution": "4.3.0", - "System.Net.Security": "4.3.2", - "System.Runtime.Serialization.Primitives": "4.3.0" - } - }, - "Microsoft.AspNetCore.Connections.Abstractions": { - "type": "Direct", - "requested": "[3.1.5, )", - "resolved": "3.1.5", - "contentHash": "d9QNKLjOIb+O8fW+Xolhw0ZpOP1nzJi822qthXUhZqzb1PpL/xD4tmZfeE6IRXlRmQOAKDKg38mDEDTaMPGy1w==", - "dependencies": { - "Microsoft.AspNetCore.Http.Features": "3.1.5", - "System.IO.Pipelines": "4.7.1" - } - }, - "Microsoft.Extensions.DependencyInjection.Abstractions": { - "type": "Direct", - "requested": "[3.1.5, )", - "resolved": "3.1.5", - "contentHash": "2VSCj2TZPMdeEi279Lawi6qJQu4+sEWizSOYrhY6hapyS1jxn1jVUZT1Ugv68bya+x8+3lD4+RqhUZql9PhISQ==" - }, - "Microsoft.Extensions.Hosting.Abstractions": { - "type": "Direct", - "requested": "[3.1.5, )", - "resolved": "3.1.5", - "contentHash": "e57iK9spITqHE7qNgC3IowzK+PK5NC2rmVY4Sz+ZoDNO24nIsgllIRbanSbt2wQz7Iy/N8Jm3C1sXqKc8zEOMQ==", - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "3.1.5", - "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.5", - "Microsoft.Extensions.FileProviders.Abstractions": "3.1.5", - "Microsoft.Extensions.Logging.Abstractions": "3.1.5" - } - }, - "Microsoft.Extensions.Logging.Abstractions": { - "type": "Direct", - "requested": "[3.1.5, )", - "resolved": "3.1.5", - "contentHash": "ZvwowjRSWXewdPI+whPFXgwF4Qme6Q9KV9SCPEITSGiqHLArct7q5hTBtTzj3GPsVLjTqehvTg6Bd/EQk9JS0A==" - }, - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.AspNetCore.Http.Features": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "I+G1L5363H2oCdMxHv2vtbluRgb4e33Gv6zJd8Uj93bBRFbE4MZlb3cB9PvRAYpSB0xbK216/qRtHmQJBzWIcg==", - "dependencies": { - "Microsoft.Extensions.Primitives": "3.1.5", - "System.IO.Pipelines": "4.7.1" - } - }, - "Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "RmWkwrdmpquJa3Tvui4AhNEy+LeqeDgd85RPNjamwKNjVSUW+Yaz8n1pKPz4IiqDJ+3XfdmaLjP9TSVnXSDNuA==", - "dependencies": { - "Libuv": "1.10.0", - "Microsoft.AspNetCore.Connections.Abstractions": "3.1.5", - "Microsoft.Extensions.Logging.Abstractions": "3.1.5", - "Microsoft.Extensions.Options": "3.1.5" - } - }, - "Microsoft.Extensions.Configuration.Abstractions": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "VBcAk6s9izZr04WCzNqOh1Sxz2RbVSh0G79MfpHSDv16cUJtSEYEHody9ZnF71LBEktzdu6cvDFBOFMh43q0iA==", - "dependencies": { - "Microsoft.Extensions.Primitives": "3.1.5" - } - }, - "Microsoft.Extensions.FileProviders.Abstractions": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "LrEQ97jhSWw84Y1m+CJfvh9qTUUswt27au54QYn2x5PCMPPgR+yAv/4VTJKMGSSI9T4scSLBXZ/fVhT4fPTCtA==", - "dependencies": { - "Microsoft.Extensions.Primitives": "3.1.5" - } - }, - "Microsoft.Extensions.Options": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "f+JT/7lkKBMp/Ak2tVjO+TD7o+UoCfjnExkZNn0PZIso8kIXrqNy6x42Lrxf4Q0pW3JMf9ExmL2EQlvk2XnFAg==", - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.5", - "Microsoft.Extensions.Primitives": "3.1.5" - } - }, - "Microsoft.Extensions.Primitives": { - "type": "Transitive", - "resolved": "3.1.5", - "contentHash": "6bLdjSAQix82oP2tsuX9MM2yjgUFFOkSZYyRSKoUULilw2cg0Y0H+dnugwYlfj8Jd7yjd/+QSdNBqEyYhTYv0w==" - }, - "Microsoft.NETCore.Platforms": { - "type": "Transitive", - "resolved": "2.0.0", - "contentHash": "VdLJOCXhZaEMY7Hm2GKiULmn7IEPFE4XC5LPSfBVCUIA8YLZVh846gtfBJalsPQF2PlzdD7ecX7DZEulJ402ZQ==" - }, - "Microsoft.NETCore.Targets": { - "type": "Transitive", - "resolved": "1.1.0", - "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "MimeKit": { - "type": "Transitive", - "resolved": "2.9.1", - "contentHash": "0XUFf9DEZiLROC7cWvCOqn2uXekNIWztZdpBsaJcvPrndqWpap32jLgQ2kribNj+rhRqK8vpDy9Uvg714v6KBg==", - "dependencies": { - "Portable.BouncyCastle": "1.8.5", - "System.Reflection.TypeExtensions": "4.4.0", - "System.Text.Encoding.CodePages": "4.4.0" - } - }, - "Portable.BouncyCastle": { - "type": "Transitive", - "resolved": "1.8.5", - "contentHash": "EaCgmntbH1sOzemRTqyXSqYjB6pLH7VCYHhhDYZ59guHSD5qPwhIYa7kfy0QUlmTRt9IXhaXdFhNuBUArp70Ng==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" - }, - "runtime.native.System": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "runtime.native.System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "runtime.native.System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M2nN92ePS8BgQ2oi6Jj3PlTUzadYSIWLdZrHY1n1ZcW9o4wAQQ6W+aQ2lfq1ysZQfVCgDwY58alUdowrzezztg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", - "dependencies": { - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" - } - }, - "runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "QR1OwtwehHxSeQvZKXe+iSd+d3XZNkEcuWMFYa2i0aG1l+lR739HPicKMlTbJst3spmeekDVBUS7SeS26s4U/g==", - "dependencies": { - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" - } - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Collections.Concurrent": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.IO.FileSystem.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "System.IO.Pipelines": { - "type": "Transitive", - "resolved": "4.7.2", - "contentHash": "rGIIhoY3lUdn9rWeuGdgeZZ0P+SpJ1wZI5g8TnXqgvuhFgUP7iP9Nt5FZebYInQZQxqnwjPxdYYBE5l/8PJmqQ==" - }, - "System.Linq": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Security": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Reflection.TypeExtensions": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "dkmh/ySlwnXJp/1qYP9uyKkCK1CXR/REFzl7abHcArxBcV91mY2CgrrzSRA5Z/X4MevJWwXsklGRdR3A7K9zbg==" - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.Numerics": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", - "dependencies": { - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Serialization.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Wz+0KOukJGAlXjtKr+5Xpuxf8+c8739RI1C+A2BoQZT+wMCCoMDDdO8/4IRHfaVINqL78GO8dW8G2lW/e45Mcw==", - "dependencies": { - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0" - } - }, - "System.Security.Claims": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", - "dependencies": { - "System.Collections": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Security.Principal": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I1tkfQlAoMM2URscUtpcRo/hX0jinXx6a/KUtEQoz3owaYwl3qwsO8cbzYVVnjxrzxjHo3nJC+62uolgeGIS9A==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "6JX7ZdaceBiLKLkYt8zJcp4xTJd1uYyXXEkPw6mnlUIjh1gZPIVKPtRXPmY5kLf6DwZmf5YLwR3QUrRonl7l0A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "2.0.0" - } - }, - "System.Threading": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0" - } - }, - "System.Threading.ThreadPool": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "ModernUO": { - "type": "Project", - "dependencies": { - "Microsoft.AspNetCore.Connections.Abstractions": "3.1.5", - "Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv": "3.1.5", - "Microsoft.Extensions.Hosting.Abstractions": "3.1.5", - "System.IO.Pipelines": "4.7.2", - "Zlib.Bindings": "1.2.0" - } - } - }, - ".NETCoreApp,Version=v5.0/centos.7-x64": { - "Argon2.Bindings": { - "type": "Direct", - "requested": "[1.6.0, )", - "resolved": "1.6.0", - "contentHash": "fj3n8L2UHJnQOfDy6phuJvu01u80TNEOx0Nkbtj7/G7pDmfRe0InLwHaQMmT59/8TOSDVLEDoi54D/yM8o7qZA==" - }, - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" - }, - "runtime.native.System": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.rhel.7-x64.runtime.native.System": "4.3.0" - } - }, - "runtime.native.System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.rhel.7-x64.runtime.native.System.Net.Http": "4.3.0" - } - }, - "runtime.native.System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M2nN92ePS8BgQ2oi6Jj3PlTUzadYSIWLdZrHY1n1ZcW9o4wAQQ6W+aQ2lfq1ysZQfVCgDwY58alUdowrzezztg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.rhel.7-x64.runtime.native.System.Net.Security": "4.3.0" - } - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" - }, - "runtime.rhel.7-x64.runtime.native.System": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FgYyVbr9KS9223IxpMTiFnjCN27sehWdnebTngl32eMX6qL6qaCrCjnBeoytG0oAGcNgBlz/CJw75dHVCGv3SQ==" - }, - "runtime.rhel.7-x64.runtime.native.System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lf3Zml87TF+bxQnUYnEtRQUc+YyWKFna4xWL2UPeHm/fOo5HtMHNCG96WQCPwte2OXv7WfQeOK5OGam8lqKJBA==" - }, - "runtime.rhel.7-x64.runtime.native.System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qyNeven0cnu+iqfuCSGPCPJeoM2dcQ6lPUtJVPHXoyRKindqTpzdLzAr5OkkmX1P5vOWtf4OOPikSwo6GoJkLg==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Security": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "6JX7ZdaceBiLKLkYt8zJcp4xTJd1uYyXXEkPw6mnlUIjh1gZPIVKPtRXPmY5kLf6DwZmf5YLwR3QUrRonl7l0A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "2.0.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - } - }, - ".NETCoreApp,Version=v5.0/centos.8-x64": { - "Argon2.Bindings": { - "type": "Direct", - "requested": "[1.6.0, )", - "resolved": "1.6.0", - "contentHash": "fj3n8L2UHJnQOfDy6phuJvu01u80TNEOx0Nkbtj7/G7pDmfRe0InLwHaQMmT59/8TOSDVLEDoi54D/yM8o7qZA==" - }, - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Security": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "6JX7ZdaceBiLKLkYt8zJcp4xTJd1uYyXXEkPw6mnlUIjh1gZPIVKPtRXPmY5kLf6DwZmf5YLwR3QUrRonl7l0A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "2.0.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - } - }, - ".NETCoreApp,Version=v5.0/debian.10-x64": { - "Argon2.Bindings": { - "type": "Direct", - "requested": "[1.6.0, )", - "resolved": "1.6.0", - "contentHash": "fj3n8L2UHJnQOfDy6phuJvu01u80TNEOx0Nkbtj7/G7pDmfRe0InLwHaQMmT59/8TOSDVLEDoi54D/yM8o7qZA==" - }, - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Security": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "6JX7ZdaceBiLKLkYt8zJcp4xTJd1uYyXXEkPw6mnlUIjh1gZPIVKPtRXPmY5kLf6DwZmf5YLwR3QUrRonl7l0A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "2.0.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - } - }, - ".NETCoreApp,Version=v5.0/debian.9-x64": { - "Argon2.Bindings": { - "type": "Direct", - "requested": "[1.6.0, )", - "resolved": "1.6.0", - "contentHash": "fj3n8L2UHJnQOfDy6phuJvu01u80TNEOx0Nkbtj7/G7pDmfRe0InLwHaQMmT59/8TOSDVLEDoi54D/yM8o7qZA==" - }, - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Security": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "6JX7ZdaceBiLKLkYt8zJcp4xTJd1uYyXXEkPw6mnlUIjh1gZPIVKPtRXPmY5kLf6DwZmf5YLwR3QUrRonl7l0A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "2.0.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - } - }, - ".NETCoreApp,Version=v5.0/osx-x64": { - "Argon2.Bindings": { - "type": "Direct", - "requested": "[1.6.0, )", - "resolved": "1.6.0", - "contentHash": "fj3n8L2UHJnQOfDy6phuJvu01u80TNEOx0Nkbtj7/G7pDmfRe0InLwHaQMmT59/8TOSDVLEDoi54D/yM8o7qZA==" - }, - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Security": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "6JX7ZdaceBiLKLkYt8zJcp4xTJd1uYyXXEkPw6mnlUIjh1gZPIVKPtRXPmY5kLf6DwZmf5YLwR3QUrRonl7l0A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "2.0.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - } - }, - ".NETCoreApp,Version=v5.0/ubuntu.16.04-x64": { - "Argon2.Bindings": { - "type": "Direct", - "requested": "[1.6.0, )", - "resolved": "1.6.0", - "contentHash": "fj3n8L2UHJnQOfDy6phuJvu01u80TNEOx0Nkbtj7/G7pDmfRe0InLwHaQMmT59/8TOSDVLEDoi54D/yM8o7qZA==" - }, - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" - }, - "runtime.native.System": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.ubuntu.16.04-x64.runtime.native.System": "4.3.0" - } - }, - "runtime.native.System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http": "4.3.0" - } - }, - "runtime.native.System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M2nN92ePS8BgQ2oi6Jj3PlTUzadYSIWLdZrHY1n1ZcW9o4wAQQ6W+aQ2lfq1ysZQfVCgDwY58alUdowrzezztg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security": "4.3.0" - } - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "vz5FoBq1abtDHjZdytIbxi5U34p1cqw6fX64R2x/ShSkRmfYUkN0cpD10Aw6Rafv5DZrH3/wpLLlBIxcIWXuRQ==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FXboIWG+yLuZVXqgZZmUyqKOuQx/MzPSrPW/OS3pRxLrFd7EQor9F4ZAunmZ3wcout51SMinZIWwOzkAVHnEBg==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "amUh4OUzit/SN6bWlc0ksEXhxAfWssejPDzYRHDS6Xzk4dQ2zFsHxR8n8KpGqOv0IZazaroXL0HgY7ime3gv8w==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Security": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "6JX7ZdaceBiLKLkYt8zJcp4xTJd1uYyXXEkPw6mnlUIjh1gZPIVKPtRXPmY5kLf6DwZmf5YLwR3QUrRonl7l0A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "2.0.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - } - }, - ".NETCoreApp,Version=v5.0/ubuntu.18.04-x64": { - "Argon2.Bindings": { - "type": "Direct", - "requested": "[1.6.0, )", - "resolved": "1.6.0", - "contentHash": "fj3n8L2UHJnQOfDy6phuJvu01u80TNEOx0Nkbtj7/G7pDmfRe0InLwHaQMmT59/8TOSDVLEDoi54D/yM8o7qZA==" - }, - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Security": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "6JX7ZdaceBiLKLkYt8zJcp4xTJd1uYyXXEkPw6mnlUIjh1gZPIVKPtRXPmY5kLf6DwZmf5YLwR3QUrRonl7l0A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "2.0.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - } - }, - ".NETCoreApp,Version=v5.0/ubuntu.20.04-x64": { - "Argon2.Bindings": { - "type": "Direct", - "requested": "[1.6.0, )", - "resolved": "1.6.0", - "contentHash": "fj3n8L2UHJnQOfDy6phuJvu01u80TNEOx0Nkbtj7/G7pDmfRe0InLwHaQMmT59/8TOSDVLEDoi54D/yM8o7qZA==" - }, - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" - }, - "runtime.unix.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "2mI2Mfq+CVatgr4RWGvAWBjoCfUafy6VNFU7G9OA52DjO8x/okfIbsEq2UPgeGfdpO7X5gmPXKT8slx0tn0Mhw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "WV8KLRHWVUVUDduFnvGMHt0FsEt2wK6xPl1EgDKlaMx2KnZ43A/O0GzP8wIuvAC7mq4T9V1mm90r+PXkL9FPdQ==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ajmTcjrqc3vgV1TH54DRioshbEniaFbOAJ0kReGuNsp9uIcqYle0RmUo6+Qlwqe3JIs4TDxgnqs3UzX3gRJ1rA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AZcRXhH7Gamr+bckUfX3iHefPIrujJTt9XWQWo0elNiP1SNasX0KBWINZkDKY0GsOrsyJ7cB4MgIRTZzLlsTKg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ooWzobr5RAq34r9uan1r/WPXJYG1XWy9KanrxNvEnBzbFdQbMG7Y3bVi4QxR7xZMNLOxLLTAyXvnSkfj5boZSg==", - "dependencies": { - "runtime.native.System": "4.3.0" - } - }, - "runtime.unix.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "zQiTBVpiLftTQZW8GFsV0gjYikB1WMkEPIxF5O6RkUrSV/OgvRRTYgeFQha/0keBpuS0HYweraGRwhfhJ7dj7w==", - "dependencies": { - "System.Private.Uri": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.unix.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.unix.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Security": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.unix.System.Private.Uri": "4.3.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.unix.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "6JX7ZdaceBiLKLkYt8zJcp4xTJd1uYyXXEkPw6mnlUIjh1gZPIVKPtRXPmY5kLf6DwZmf5YLwR3QUrRonl7l0A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "2.0.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - } - }, - ".NETCoreApp,Version=v5.0/win-x64": { - "Argon2.Bindings": { - "type": "Direct", - "requested": "[1.6.0, )", - "resolved": "1.6.0", - "contentHash": "fj3n8L2UHJnQOfDy6phuJvu01u80TNEOx0Nkbtj7/G7pDmfRe0InLwHaQMmT59/8TOSDVLEDoi54D/yM8o7qZA==" - }, - "Zlib.Bindings": { - "type": "Direct", - "requested": "[1.2.0, )", - "resolved": "1.2.0", - "contentHash": "z1/D7sNbpq3E6B+YLvV99vx9fa6cnOtxVLKMBVFJ8i/dGZG/y8bE+7lyOwLaDmQlTendwidPvjKfUKhLYgBryg==" - }, - "Libuv": { - "type": "Transitive", - "resolved": "1.10.0", - "contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.1" - } - }, - "Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.win.Microsoft.Win32.Primitives": "4.3.0" - } - }, - "runtime.any.System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "23g6rqftKmovn2cLeGsuHUYm0FD7pdutb0uQMJpZ3qTvq+zHkgmt6J65VtRry4WDGYlmkMa4xDACtaQ94alNag==", - "dependencies": { - "System.Runtime": "4.3.0" - } - }, - "runtime.any.System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1lpifymjGDzoYIaam6/Hyqf8GhBI3xXYLK2TgEvTtuZMorG3Kb9QnMTIKhLjJYXIiu1JvxjngHvtVFQQlpQ3HQ==" - }, - "runtime.any.System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "sMDBnad4rp4t7GY442Jux0MCUuKL4otn5BK6Ni0ARTXTSpRNBzZ7hpMfKSvnVSED5kYJm96YOWsqV0JH0d2uuw==" - }, - "runtime.any.System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "M1r+760j1CNA6M/ZaW6KX8gOS8nxPRqloqDcJYVidRG566Ykwcs29AweZs2JF+nMOCgWDiMfPSTMfvwOI9F77w==" - }, - "runtime.any.System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "SDZ5AD1DtyRoxYtEcqQ3HDlcrorMYXZeCt7ZhG9US9I5Vva+gpIWDGMkcwa5XiKL0ceQKRZIX2x0XEjLX7PDzQ==" - }, - "runtime.any.System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hLC3A3rI8jipR5d9k7+f0MgRCW6texsAp0MWkN/ci18FMtQ9KH7E2vDn/DH2LkxsszlpJpOn9qy6Z6/69rH6eQ==" - }, - "runtime.any.System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Nrm1p3armp6TTf2xuvaa+jGTTmncALWFq22CpmwRvhDf6dE9ZmH40EbOswD4GnFLrMRS0Ki6Kx5aUPmKK/hZBg==" - }, - "runtime.any.System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Lxb89SMvf8w9p9+keBLyL6H6x/TEmc6QVsIIA0T36IuyOY3kNvIdyGddA2qt35cRamzxF8K5p0Opq4G4HjNbhQ==" - }, - "runtime.any.System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "fRS7zJgaG9NkifaAxGGclDDoRn9HC7hXACl52Or06a/fxdzDajWb5wov3c6a+gVSlekRoexfjwQSK9sh5um5LQ==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "runtime.any.System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GG84X6vufoEzqx8PbeBKheE4srOhimv+yLtGb/JkR3Y2FmoqmueLNFU4Xx8Y67plFpltQSdK74x0qlEhIpv/CQ==" - }, - "runtime.any.System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lBoFeQfxe/4eqjPi46E0LU/YaCMdNkQ8B4MZu/mkzdIAZh8RQ1NYZSj0egrQKdgdvlPFtP4STtob40r4o2DBAw==" - }, - "runtime.any.System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "+ihI5VaXFCMVPJNstG4O4eo1CfbrByLxRrQQTqOTp1ttK0kUKDqOdBSTaCB2IBk/QtjDrs6+x4xuezyMXdm0HQ==" - }, - "runtime.any.System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NLrxmLsfRrOuVqPWG+2lrQZnE53MLVeo+w9c54EV+TUo4c8rILpsDXfY8pPiOy9kHpUHHP07ugKmtsU3vVW5Jg==" - }, - "runtime.any.System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OhBAVBQG5kFj1S+hCEQ3TUHBAEtZ3fbEMgZMRNdN8A0Pj4x+5nTELEqL59DU0TjKVE6II3dqKw4Dklb3szT65w==" - }, - "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" - }, - "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" - }, - "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" - }, - "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" - }, - "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" - }, - "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" - }, - "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" - }, - "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" - }, - "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" - }, - "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" - }, - "runtime.win.Microsoft.Win32.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "NU51SEt/ZaD2MF48sJ17BIqx7rjeNNLXUevfMOjqQIetdndXwYjZfZsT6jD+rSWp/FYxjesdK4xUSl4OTEI0jw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "runtime.win.System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "hHHP0WCStene2jjeYcuDkETozUYF/3sHVRHAEOgS3L15hlip24ssqCTnJC28Z03Wpo078oMcJd0H4egD2aJI8g==" - }, - "runtime.win.System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "Z37zcSCpXuGCYtFbqYO0TwOVXxS2d+BXgSoDFZmRg8BC4Cuy54edjyIvhhcfCrDQA9nl+EPFTgHN54dRAK7mNA==", - "dependencies": { - "System.Buffers": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Text.Encoding.Extensions": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Overlapped": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "runtime.win.System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "lkXXykakvXUU+Zq2j0pC6EO20lEhijjqMc01XXpp1CJN+DeCwl3nsj4t5Xbpz3kA7yQyTqw6d9SyIzsyLsV3zA==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "runtime.win.System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "RkgHVhUPvzZxuUubiZe8yr/6CypRVXj0VBzaR8hsqQ8f+rUo7e4PWrHTLOCjd8fBMGWCrY//fi7Ku3qXD7oHRw==", - "dependencies": { - "System.Private.Uri": "4.3.0" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", - "dependencies": { - "System.Diagnostics.Debug": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Collections": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Collections": "4.3.0" - } - }, - "System.Diagnostics.Debug": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.win.System.Diagnostics.Debug": "4.3.0" - } - }, - "System.Diagnostics.Tracing": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Diagnostics.Tracing": "4.3.0" - } - }, - "System.Globalization": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization": "4.3.0" - } - }, - "System.Globalization.Calendars": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Globalization.Calendars": "4.3.0" - } - }, - "System.Globalization.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Globalization": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.InteropServices": "4.3.0" - } - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.any.System.IO": "4.3.0" - } - }, - "System.IO.FileSystem": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.win.System.IO.FileSystem": "4.3.0" - } - }, - "System.Net.NameResolution": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Principal.Windows": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "runtime.native.System": "4.3.0" - } - }, - "System.Net.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.win.System.Net.Primitives": "4.3.0" - } - }, - "System.Net.Security": { - "type": "Transitive", - "resolved": "4.3.2", - "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Diagnostics.Tracing": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Extensions": "4.3.0", - "System.IO": "4.3.0", - "System.Net.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Security.Cryptography.X509Certificates": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "System.Threading.Tasks": "4.3.0", - "System.Threading.ThreadPool": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Security": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" - } - }, - "System.Private.Uri": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "I4SwANiUGho1esj4V4oSlPllXjzCZDE+5XXso2P03LW2vOda2Enzh8DWOxwN6hnrJyp314c7KuVu31QYhRzOGg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0" - } - }, - "System.Reflection": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection": "4.3.0" - } - }, - "System.Reflection.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Reflection.Primitives": "4.3.0" - } - }, - "System.Resources.ResourceManager": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Globalization": "4.3.0", - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Resources.ResourceManager": "4.3.0" - } - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "runtime.any.System.Runtime": "4.3.0" - } - }, - "System.Runtime.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.win.System.Runtime.Extensions": "4.3.0" - } - }, - "System.Runtime.Handles": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Runtime.Handles": "4.3.0" - } - }, - "System.Runtime.InteropServices": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Reflection": "4.3.0", - "System.Reflection.Primitives": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "runtime.any.System.Runtime.InteropServices": "4.3.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.Apple": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.Cng": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0" - } - }, - "System.Security.Cryptography.Csp": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.IO": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Collections.Concurrent": "4.3.0", - "System.Linq": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.OpenSsl": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", - "dependencies": { - "System.Collections": "4.3.0", - "System.IO": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Globalization": "4.3.0", - "System.Globalization.Calendars": "4.3.0", - "System.IO": "4.3.0", - "System.IO.FileSystem": "4.3.0", - "System.IO.FileSystem.Primitives": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Runtime.Numerics": "4.3.0", - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Cng": "4.3.0", - "System.Security.Cryptography.Csp": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.OpenSsl": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0", - "runtime.native.System": "4.3.0", - "runtime.native.System.Net.Http": "4.3.0", - "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "HVL1rvqYtnRCxFsYag/2le/ZfKLK4yMw79+s6FmKXbSCNN0JeAhrYxnRAHFoWRa0dEojsDcbBSpH3l22QxAVyw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.Win32.Primitives": "4.3.0", - "System.Collections": "4.3.0", - "System.Diagnostics.Debug": "4.3.0", - "System.Reflection": "4.3.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Extensions": "4.3.0", - "System.Runtime.Handles": "4.3.0", - "System.Runtime.InteropServices": "4.3.0", - "System.Security.Claims": "4.3.0", - "System.Security.Principal": "4.3.0", - "System.Text.Encoding": "4.3.0", - "System.Threading": "4.3.0" - } - }, - "System.Text.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Text.Encoding": "4.3.0" - } - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "4.4.0", - "contentHash": "6JX7ZdaceBiLKLkYt8zJcp4xTJd1uYyXXEkPw6mnlUIjh1gZPIVKPtRXPmY5kLf6DwZmf5YLwR3QUrRonl7l0A==", - "dependencies": { - "Microsoft.NETCore.Platforms": "2.0.0" - } - }, - "System.Text.Encoding.Extensions": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "System.Text.Encoding": "4.3.0", - "runtime.any.System.Text.Encoding.Extensions": "4.3.0" - } - }, - "System.Threading": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", - "dependencies": { - "System.Runtime": "4.3.0", - "System.Threading.Tasks": "4.3.0" - } - }, - "System.Threading.Overlapped": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "m3HQ2dPiX/DSTpf+yJt8B0c+SRvzfqAJKx+QDWi+VLhz8svLT23MVjEOHPF/KiSLeArKU/iHescrbLd3yVgyNg==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "System.Resources.ResourceManager": "4.3.0", - "System.Runtime": "4.3.0", - "System.Runtime.Handles": "4.3.0" - } - }, - "System.Threading.Tasks": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.1.0", - "Microsoft.NETCore.Targets": "1.1.0", - "System.Runtime": "4.3.0", - "runtime.any.System.Threading.Tasks": "4.3.0" - } - } } } } \ No newline at end of file diff --git a/rider-settings.zip b/rider-settings.zip new file mode 100644 index 000000000..85492fe12 Binary files /dev/null and b/rider-settings.zip differ